diff --git a/detail/1.html b/detail/1.html new file mode 100644 index 0000000..4913bef --- /dev/null +++ b/detail/1.html @@ -0,0 +1,167576 @@ +

Patches contributed by Massachusetts Institute of Technology


commit ee6a12d0d4d85f3833d177cd382cd417f0ef011b
+Author: Theodore Ts'o 
+Date:   Thu Oct 5 21:42:47 2023 -0400
+
+    ext4: add missing initialization of call_notify_error in update_super_work()
+    
+    Fixes: ff0722de896e ("ext4: add periodic superblock update check")
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index dbebd8b3127e..6f48dec19f4a 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -768,7 +768,8 @@ static void update_super_work(struct work_struct *work)
+ 	 */
+ 	if (!sb_rdonly(sbi->s_sb) && journal) {
+ 		struct buffer_head *sbh = sbi->s_sbh;
+-		bool call_notify_err;
++		bool call_notify_err = false;
++
+ 		handle = jbd2_journal_start(journal, 1);
+ 		if (IS_ERR(handle))
+ 			goto write_directly;

commit bb15cea20f211e110150e528fca806f38d5789e0
+Author: Theodore Ts'o 
+Date:   Tue Aug 22 23:43:38 2023 -0400
+
+    ext4: rename s_error_work to s_sb_upd_work
+    
+    The most common use that s_error_work will get scheduled is now the
+    periodic update of the superblock.  So rename it to s_sb_upd_work.
+    
+    Also rename the function flush_stashed_error_work() to
+    update_super_work().
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 2c2c3191bf41..84618c46f239 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1698,10 +1698,13 @@ struct ext4_sb_info {
+ 	const char *s_last_error_func;
+ 	time64_t s_last_error_time;
+ 	/*
+-	 * If we are in a context where we cannot update error information in
+-	 * the on-disk superblock, we queue this work to do it.
++	 * If we are in a context where we cannot update the on-disk
++	 * superblock, we queue the work here.  This is used to update
++	 * the error information in the superblock, and for periodic
++	 * updates of the superblock called from the commit callback
++	 * function.
+ 	 */
+-	struct work_struct s_error_work;
++	struct work_struct s_sb_upd_work;
+ 
+ 	/* Ext4 fast commit sub transaction ID */
+ 	atomic_t s_fc_subtid;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index bf0cfdffa9d0..91f20afa1d71 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -481,7 +481,7 @@ static void ext4_maybe_update_superblock(struct super_block *sb)
+ 	diff_size = lifetime_write_kbytes - le64_to_cpu(es->s_kbytes_written);
+ 
+ 	if (diff_size > EXT4_SB_REFRESH_INTERVAL_KB)
+-		schedule_work(&EXT4_SB(sb)->s_error_work);
++		schedule_work(&EXT4_SB(sb)->s_sb_upd_work);
+ }
+ 
+ /*
+@@ -723,7 +723,7 @@ static void ext4_handle_error(struct super_block *sb, bool force_ro, int error,
+ 		 * defer superblock flushing to a workqueue.
+ 		 */
+ 		if (continue_fs && journal)
+-			schedule_work(&EXT4_SB(sb)->s_error_work);
++			schedule_work(&EXT4_SB(sb)->s_sb_upd_work);
+ 		else
+ 			ext4_commit_super(sb);
+ 	}
+@@ -750,10 +750,10 @@ static void ext4_handle_error(struct super_block *sb, bool force_ro, int error,
+ 	sb->s_flags |= SB_RDONLY;
+ }
+ 
+-static void flush_stashed_error_work(struct work_struct *work)
++static void update_super_work(struct work_struct *work)
+ {
+ 	struct ext4_sb_info *sbi = container_of(work, struct ext4_sb_info,
+-						s_error_work);
++						s_sb_upd_work);
+ 	journal_t *journal = sbi->s_journal;
+ 	handle_t *handle;
+ 
+@@ -1078,7 +1078,7 @@ __acquires(bitlock)
+ 		if (!bdev_read_only(sb->s_bdev)) {
+ 			save_error_info(sb, EFSCORRUPTED, ino, block, function,
+ 					line);
+-			schedule_work(&EXT4_SB(sb)->s_error_work);
++			schedule_work(&EXT4_SB(sb)->s_sb_upd_work);
+ 		}
+ 		return;
+ 	}
+@@ -1318,10 +1318,10 @@ static void ext4_put_super(struct super_block *sb)
+ 	 * Unregister sysfs before destroying jbd2 journal.
+ 	 * Since we could still access attr_journal_task attribute via sysfs
+ 	 * path which could have sbi->s_journal->j_task as NULL
+-	 * Unregister sysfs before flush sbi->s_error_work.
++	 * Unregister sysfs before flush sbi->s_sb_upd_work.
+ 	 * Since user may read /proc/fs/ext4/xx/mb_groups during umount, If
+ 	 * read metadata verify failed then will queue error work.
+-	 * flush_stashed_error_work will call start_this_handle may trigger
++	 * update_super_work will call start_this_handle may trigger
+ 	 * BUG_ON.
+ 	 */
+ 	ext4_unregister_sysfs(sb);
+@@ -1333,7 +1333,7 @@ static void ext4_put_super(struct super_block *sb)
+ 	ext4_unregister_li_request(sb);
+ 	ext4_quotas_off(sb, EXT4_MAXQUOTAS);
+ 
+-	flush_work(&sbi->s_error_work);
++	flush_work(&sbi->s_sb_upd_work);
+ 	destroy_workqueue(sbi->rsv_conversion_wq);
+ 	ext4_release_orphan_info(sb);
+ 
+@@ -4998,8 +4998,8 @@ static int ext4_load_and_init_journal(struct super_block *sb,
+ 	return 0;
+ 
+ out:
+-	/* flush s_error_work before journal destroy. */
+-	flush_work(&sbi->s_error_work);
++	/* flush s_sb_upd_work before destroying the journal. */
++	flush_work(&sbi->s_sb_upd_work);
+ 	jbd2_journal_destroy(sbi->s_journal);
+ 	sbi->s_journal = NULL;
+ 	return -EINVAL;
+@@ -5322,7 +5322,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
+ 
+ 	timer_setup(&sbi->s_err_report, print_daily_error_info, 0);
+ 	spin_lock_init(&sbi->s_error_lock);
+-	INIT_WORK(&sbi->s_error_work, flush_stashed_error_work);
++	INIT_WORK(&sbi->s_sb_upd_work, update_super_work);
+ 
+ 	err = ext4_group_desc_init(sb, es, logical_sb_block, &first_not_zeroed);
+ 	if (err)
+@@ -5666,16 +5666,16 @@ failed_mount9: __maybe_unused
+ 	sbi->s_ea_block_cache = NULL;
+ 
+ 	if (sbi->s_journal) {
+-		/* flush s_error_work before journal destroy. */
+-		flush_work(&sbi->s_error_work);
++		/* flush s_sb_upd_work before journal destroy. */
++		flush_work(&sbi->s_sb_upd_work);
+ 		jbd2_journal_destroy(sbi->s_journal);
+ 		sbi->s_journal = NULL;
+ 	}
+ failed_mount3a:
+ 	ext4_es_unregister_shrinker(sbi);
+ failed_mount3:
+-	/* flush s_error_work before sbi destroy */
+-	flush_work(&sbi->s_error_work);
++	/* flush s_sb_upd_work before sbi destroy */
++	flush_work(&sbi->s_sb_upd_work);
+ 	del_timer_sync(&sbi->s_err_report);
+ 	ext4_stop_mmpd(sbi);
+ 	ext4_group_desc_free(sbi);
+@@ -6551,7 +6551,7 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb)
+ 	}
+ 
+ 	/* Flush outstanding errors before changing fs state */
+-	flush_work(&sbi->s_error_work);
++	flush_work(&sbi->s_sb_upd_work);
+ 
+ 	if ((bool)(fc->sb_flags & SB_RDONLY) != sb_rdonly(sb)) {
+ 		if (ext4_forced_shutdown(sb)) {

commit 2ef6c32a914b85217b44a0a2418e830e520b085e
+Author: Theodore Ts'o 
+Date:   Fri Jun 23 10:18:51 2023 -0400
+
+    ext4: avoid updating the superblock on a r/o mount if not needed
+    
+    This was noticed by a user who noticied that the mtime of a file
+    backing a loopback device was getting bumped when the loopback device
+    is mounted read/only.  Note: This doesn't show up when doing a
+    loopback mount of a file directly, via "mount -o ro /tmp/foo.img
+    /mnt", since the loop device is set read-only when mount automatically
+    creates loop device.  However, this is noticeable for a LUKS loop
+    device like this:
+    
+    % cryptsetup luksOpen /tmp/foo.img test
+    % mount -o ro /dev/loop0 /mnt ; umount /mnt
+    
+    or, if LUKS is not in use, if the user manually creates the loop
+    device like this:
+    
+    % losetup /dev/loop0 /tmp/foo.img
+    % mount -o ro /dev/loop0 /mnt ; umount /mnt
+    
+    The modified mtime causes rsync to do a rolling checksum scan of the
+    file on the local and remote side, incrementally increasing the time
+    to rsync the not-modified-but-touched image file.
+    
+    Fixes: eee00237fa5e ("ext4: commit super block if fs record error when journal record without error")
+    Cc: stable@kernel.org
+    Link: https://lore.kernel.org/r/ZIauBR7YiV3rVAHL@glitch
+    Reported-by: Sean Greenslade 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index b3819e70093e..c638b0db3b2b 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -5997,19 +5997,27 @@ static int ext4_load_journal(struct super_block *sb,
+ 		err = jbd2_journal_wipe(journal, !really_read_only);
+ 	if (!err) {
+ 		char *save = kmalloc(EXT4_S_ERR_LEN, GFP_KERNEL);
++		__le16 orig_state;
++		bool changed = false;
+ 
+ 		if (save)
+ 			memcpy(save, ((char *) es) +
+ 			       EXT4_S_ERR_START, EXT4_S_ERR_LEN);
+ 		err = jbd2_journal_load(journal);
+-		if (save)
++		if (save && memcmp(((char *) es) + EXT4_S_ERR_START,
++				   save, EXT4_S_ERR_LEN)) {
+ 			memcpy(((char *) es) + EXT4_S_ERR_START,
+ 			       save, EXT4_S_ERR_LEN);
++			changed = true;
++		}
+ 		kfree(save);
++		orig_state = es->s_state;
+ 		es->s_state |= cpu_to_le16(EXT4_SB(sb)->s_mount_state &
+ 					   EXT4_ERROR_FS);
++		if (orig_state != es->s_state)
++			changed = true;
+ 		/* Write out restored error information to the superblock */
+-		if (!bdev_read_only(sb->s_bdev)) {
++		if (changed && !really_read_only) {
+ 			int err2;
+ 			err2 = ext4_commit_super(sb);
+ 			err = err ? : err2;

commit 4c0cfebdf3c34c9cd2c55844f549fa46b1da3164
+Author: Theodore Ts'o 
+Date:   Thu Jun 8 10:39:35 2023 -0400
+
+    ext4: clean up mballoc criteria comments
+    
+    Line wrap and slightly clarify the comments describing mballoc's
+    cirtiera.
+    
+    Define EXT4_MB_NUM_CRS as part of the enum, so that it will
+    automatically get updated when criteria is added or removed.
+    
+    Also fix a potential unitialized use of 'cr' variable if
+    CONFIG_EXT4_DEBUG is enabled.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 6a1f013d23f7..45a531446ea2 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -128,47 +128,52 @@ enum SHIFT_DIRECTION {
+ };
+ 
+ /*
+- * Number of criterias defined. For each criteria, mballoc has slightly
+- * different way of finding the required blocks nad usually, higher the
+- * criteria the slower the allocation. We start at lower criterias and keep
+- * falling back to higher ones if we are not able to find any blocks.
+- */
+-#define EXT4_MB_NUM_CRS 5
+-/*
+- * All possible allocation criterias for mballoc. Lower are faster.
++ * For each criteria, mballoc has slightly different way of finding
++ * the required blocks nad usually, higher the criteria the slower the
++ * allocation.  We start at lower criterias and keep falling back to
++ * higher ones if we are not able to find any blocks.  Lower (earlier)
++ * criteria are faster.
+  */
+ enum criteria {
+ 	/*
+-	 * Used when number of blocks needed is a power of 2. This doesn't
+-	 * trigger any disk IO except prefetch and is the fastest criteria.
++	 * Used when number of blocks needed is a power of 2. This
++	 * doesn't trigger any disk IO except prefetch and is the
++	 * fastest criteria.
+ 	 */
+ 	CR_POWER2_ALIGNED,
+ 
+ 	/*
+-	 * Tries to lookup in-memory data structures to find the most suitable
+-	 * group that satisfies goal request. No disk IO except block prefetch.
++	 * Tries to lookup in-memory data structures to find the most
++	 * suitable group that satisfies goal request. No disk IO
++	 * except block prefetch.
+ 	 */
+ 	CR_GOAL_LEN_FAST,
+ 
+         /*
+-	 * Same as CR_GOAL_LEN_FAST but is allowed to reduce the goal length to
+-         * the best available length for faster allocation.
++	 * Same as CR_GOAL_LEN_FAST but is allowed to reduce the goal
++         * length to the best available length for faster allocation.
+ 	 */
+ 	CR_BEST_AVAIL_LEN,
+ 
+ 	/*
+-	 * Reads each block group sequentially, performing disk IO if necessary, to
+-	 * find find_suitable block group. Tries to allocate goal length but might trim
+-	 * the request if nothing is found after enough tries.
++	 * Reads each block group sequentially, performing disk IO if
++	 * necessary, to find find_suitable block group. Tries to
++	 * allocate goal length but might trim the request if nothing
++	 * is found after enough tries.
+ 	 */
+ 	CR_GOAL_LEN_SLOW,
+ 
+ 	/*
+-	 * Finds the first free set of blocks and allocates those. This is only
+-	 * used in rare cases when CR_GOAL_LEN_SLOW also fails to allocate
+-	 * anything.
++	 * Finds the first free set of blocks and allocates
++	 * those. This is only used in rare cases when
++	 * CR_GOAL_LEN_SLOW also fails to allocate anything.
+ 	 */
+ 	CR_ANY_FREE,
++
++	/*
++	 * Number of criterias defined.
++	 */
++	EXT4_MB_NUM_CRS
+ };
+ 
+ /* criteria below which we use fast block scanning and avoid unnecessary IO */
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 74ebe31f8d0f..a2475b8c9fb5 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -1035,11 +1035,9 @@ static void ext4_mb_choose_next_group_best_avail(struct ext4_allocation_context
+ 
+ 		if (num_stripe_clusters > 0) {
+ 			/*
+-			 * Try to round up the adjusted goal to stripe size
+-			 * (in cluster units) multiple for efficiency.
+-			 *
+-			 * XXX: Is s->stripe always a power of 2? In that case
+-			 * we can use the faster round_up() variant.
++			 * Try to round up the adjusted goal length to
++			 * stripe size (in cluster units) multiple for
++			 * efficiency.
+ 			 */
+ 			ac->ac_g_ex.fe_len = roundup(ac->ac_g_ex.fe_len,
+ 						     num_stripe_clusters);
+@@ -2758,7 +2756,7 @@ static noinline_for_stack int
+ ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
+ {
+ 	ext4_group_t prefetch_grp = 0, ngroups, group, i;
+-	enum criteria cr, new_cr;
++	enum criteria new_cr, cr = CR_GOAL_LEN_FAST;
+ 	int err = 0, first_err = 0;
+ 	unsigned int nr = 0, prefetch_ios = 0;
+ 	struct ext4_sb_info *sbi;
+@@ -2815,12 +2813,13 @@ ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
+ 		spin_unlock(&sbi->s_md_lock);
+ 	}
+ 
+-	/* Let's just scan groups to find more-less suitable blocks */
+-	cr = ac->ac_2order ? CR_POWER2_ALIGNED : CR_GOAL_LEN_FAST;
+ 	/*
+-	 * cr == CR_POWER2_ALIGNED try to get exact allocation,
+-	 * cr == CR_ANY_FREE try to get anything
++	 * Let's just scan groups to find more-less suitable blocks We
++	 * start with CR_GOAL_LEN_FAST, unless it is power of 2
++	 * aligned, in which case let's do that faster approach first.
+ 	 */
++	if (ac->ac_2order)
++		cr = CR_POWER2_ALIGNED;
+ repeat:
+ 	for (; cr < EXT4_MB_NUM_CRS && ac->ac_status == AC_STATUS_CONTINUE; cr++) {
+ 		ac->ac_criteria = cr;

commit dea9d8f7643fab07bf89a1155f1f94f37d096a5e
+Author: Theodore Ts'o 
+Date:   Thu Jun 8 10:06:40 2023 -0400
+
+    ext4: only check dquot_initialize_needed() when debugging
+    
+    ext4_xattr_block_set() relies on its caller to call dquot_initialize()
+    on the inode.  To assure that this has happened there are WARN_ON
+    checks.  Unfortunately, this is subject to false positives if there is
+    an antagonist thread which is flipping the file system at high rates
+    between r/o and rw.  So only do the check if EXT4_XATTR_DEBUG is
+    enabled.
+    
+    Link: https://lore.kernel.org/r/20230608044056.GA1418535@mit.edu
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 13d7f17a9c8c..321e3a888c20 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -2056,8 +2056,9 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
+ 			else {
+ 				u32 ref;
+ 
++#ifdef EXT4_XATTR_DEBUG
+ 				WARN_ON_ONCE(dquot_initialize_needed(inode));
+-
++#endif
+ 				/* The old block is released after updating
+ 				   the inode. */
+ 				error = dquot_alloc_block(inode,
+@@ -2120,8 +2121,9 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
+ 			/* We need to allocate a new block */
+ 			ext4_fsblk_t goal, block;
+ 
++#ifdef EXT4_XATTR_DEBUG
+ 			WARN_ON_ONCE(dquot_initialize_needed(inode));
+-
++#endif
+ 			goal = ext4_group_first_block_no(sb,
+ 						EXT4_I(inode)->i_block_group);
+ 			block = ext4_new_meta_blocks(handle, inode, goal, 0,

commit 1b29243933098cdbc31b579b5616e183b4275e2f
+Author: Theodore Ts'o 
+Date:   Thu Jun 8 09:57:04 2023 -0400
+
+    Revert "ext4: don't clear SB_RDONLY when remounting r/w until quota is re-enabled"
+    
+    This reverts commit a44be64bbecb15a452496f60db6eacfee2b59c79.
+    
+    Link: https://lore.kernel.org/r/653b3359-2005-21b1-039d-c55ca4cffdcc@gmail.com
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 56a5d1c469fc..05fcecc36244 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -6388,7 +6388,6 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb)
+ 	struct ext4_mount_options old_opts;
+ 	ext4_group_t g;
+ 	int err = 0;
+-	int enable_rw = 0;
+ #ifdef CONFIG_QUOTA
+ 	int enable_quota = 0;
+ 	int i, j;
+@@ -6575,7 +6574,7 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb)
+ 			if (err)
+ 				goto restore_opts;
+ 
+-			enable_rw = 1;
++			sb->s_flags &= ~SB_RDONLY;
+ 			if (ext4_has_feature_mmp(sb)) {
+ 				err = ext4_multi_mount_protect(sb,
+ 						le64_to_cpu(es->s_mmp_block));
+@@ -6622,9 +6621,6 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb)
+ 	if (!test_opt(sb, BLOCK_VALIDITY) && sbi->s_system_blks)
+ 		ext4_release_system_zone(sb);
+ 
+-	if (enable_rw)
+-		sb->s_flags &= ~SB_RDONLY;
+-
+ 	/*
+ 	 * Reinitialize lazy itable initialization thread based on
+ 	 * current settings

commit eb1f822c76beeaa76ab8b6737ab9dc9f9798408c
+Author: Theodore Ts'o 
+Date:   Fri May 26 23:57:29 2023 -0400
+
+    ext4: enable the lazy init thread when remounting read/write
+    
+    In commit a44be64bbecb ("ext4: don't clear SB_RDONLY when remounting
+    r/w until quota is re-enabled") we defer clearing tyhe SB_RDONLY flag
+    in struct super.  However, we didn't defer when we checked sb_rdonly()
+    to determine the lazy itable init thread should be enabled, with the
+    next result that the lazy inode table initialization would not be
+    properly started.  This can cause generic/231 to fail in ext4's
+    nojournal mode.
+    
+    Fix this by moving when we decide to start or stop the lazy itable
+    init thread to after we clear the SB_RDONLY flag when we are
+    remounting the file system read/write.
+    
+    Fixes a44be64bbecb ("ext4: don't clear SB_RDONLY when remounting r/w until...")
+    
+    Signed-off-by: Theodore Ts'o 
+    Link: https://lore.kernel.org/r/20230527035729.1001605-1-tytso@mit.edu
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 9680fe753e59..56a5d1c469fc 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -6588,18 +6588,6 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb)
+ 		}
+ 	}
+ 
+-	/*
+-	 * Reinitialize lazy itable initialization thread based on
+-	 * current settings
+-	 */
+-	if (sb_rdonly(sb) || !test_opt(sb, INIT_INODE_TABLE))
+-		ext4_unregister_li_request(sb);
+-	else {
+-		ext4_group_t first_not_zeroed;
+-		first_not_zeroed = ext4_has_uninit_itable(sb);
+-		ext4_register_li_request(sb, first_not_zeroed);
+-	}
+-
+ 	/*
+ 	 * Handle creation of system zone data early because it can fail.
+ 	 * Releasing of existing data is done when we are sure remount will
+@@ -6637,6 +6625,18 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb)
+ 	if (enable_rw)
+ 		sb->s_flags &= ~SB_RDONLY;
+ 
++	/*
++	 * Reinitialize lazy itable initialization thread based on
++	 * current settings
++	 */
++	if (sb_rdonly(sb) || !test_opt(sb, INIT_INODE_TABLE))
++		ext4_unregister_li_request(sb);
++	else {
++		ext4_group_t first_not_zeroed;
++		first_not_zeroed = ext4_has_uninit_itable(sb);
++		ext4_register_li_request(sb, first_not_zeroed);
++	}
++
+ 	if (!ext4_has_feature_mmp(sb) || sb_rdonly(sb))
+ 		ext4_stop_mmpd(sbi);
+ 

commit aff3bea95388299eec63440389b4545c8041b357
+Author: Theodore Ts'o 
+Date:   Tue May 23 23:49:51 2023 -0400
+
+    ext4: add lockdep annotations for i_data_sem for ea_inode's
+    
+    Treat i_data_sem for ea_inodes as being in their own lockdep class to
+    avoid lockdep complaints about ext4_setattr's use of inode_lock() on
+    normal inodes potentially causing lock ordering with i_data_sem on
+    ea_inodes in ext4_xattr_inode_write().  However, ea_inodes will be
+    operated on by ext4_setattr(), so this isn't a problem.
+    
+    Cc: stable@kernel.org
+    Link: https://syzkaller.appspot.com/bug?extid=298c5d8fb4a128bc27b0
+    Reported-by: syzbot+298c5d8fb4a128bc27b0@syzkaller.appspotmail.com
+    Signed-off-by: Theodore Ts'o 
+    Link: https://lore.kernel.org/r/20230524034951.779531-5-tytso@mit.edu
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 9525c52b78dc..8104a21b001a 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -918,11 +918,13 @@ do {									       \
+  *			  where the second inode has larger inode number
+  *			  than the first
+  *  I_DATA_SEM_QUOTA  - Used for quota inodes only
++ *  I_DATA_SEM_EA     - Used for ea_inodes only
+  */
+ enum {
+ 	I_DATA_SEM_NORMAL = 0,
+ 	I_DATA_SEM_OTHER,
+ 	I_DATA_SEM_QUOTA,
++	I_DATA_SEM_EA
+ };
+ 
+ 
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index ff7ab63c5b4f..13d7f17a9c8c 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -121,7 +121,11 @@ ext4_expand_inode_array(struct ext4_xattr_inode_array **ea_inode_array,
+ #ifdef CONFIG_LOCKDEP
+ void ext4_xattr_inode_set_class(struct inode *ea_inode)
+ {
++	struct ext4_inode_info *ei = EXT4_I(ea_inode);
++
+ 	lockdep_set_subclass(&ea_inode->i_rwsem, 1);
++	(void) ei;	/* shut up clang warning if !CONFIG_LOCKDEP */
++	lockdep_set_subclass(&ei->i_data_sem, I_DATA_SEM_EA);
+ }
+ #endif
+ 

commit 2bc7e7c1a3bc9bd0cbf0f71006f6fe7ef24a00c2
+Author: Theodore Ts'o 
+Date:   Tue May 23 23:49:50 2023 -0400
+
+    ext4: disallow ea_inodes with extended attributes
+    
+    An ea_inode stores the value of an extended attribute; it can not have
+    extended attributes itself, or this will cause recursive nightmares.
+    Add a check in ext4_iget() to make sure this is the case.
+    
+    Cc: stable@kernel.org
+    Reported-by: syzbot+e44749b6ba4d0434cd47@syzkaller.appspotmail.com
+    Signed-off-by: Theodore Ts'o 
+    Link: https://lore.kernel.org/r/20230524034951.779531-4-tytso@mit.edu
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 258f3cbed347..02de439bf1f0 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4647,6 +4647,9 @@ static const char *check_igot_inode(struct inode *inode, ext4_iget_flags flags)
+ 	if (flags & EXT4_IGET_EA_INODE) {
+ 		if (!(EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL))
+ 			return "missing EA_INODE flag";
++		if (ext4_test_inode_state(inode, EXT4_STATE_XATTR) ||
++		    EXT4_I(inode)->i_file_acl)
++			return "ea_inode with extended attributes";
+ 	} else {
+ 		if ((EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL))
+ 			return "unexpected EA_INODE flag";

commit b928dfdcb27d8fa59917b794cfba53052a2f050f
+Author: Theodore Ts'o 
+Date:   Tue May 23 23:49:49 2023 -0400
+
+    ext4: set lockdep subclass for the ea_inode in ext4_xattr_inode_cache_find()
+    
+    If the ea_inode has been pushed out of the inode cache while there is
+    still a reference in the mb_cache, the lockdep subclass will not be
+    set on the inode, which can lead to some lockdep false positives.
+    
+    Fixes: 33d201e0277b ("ext4: fix lockdep warning about recursive inode locking")
+    Cc: stable@kernel.org
+    Reported-by: syzbot+d4b971e744b1f5439336@syzkaller.appspotmail.com
+    Signed-off-by: Theodore Ts'o 
+    Link: https://lore.kernel.org/r/20230524034951.779531-3-tytso@mit.edu
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index a27208129a80..ff7ab63c5b4f 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -1539,6 +1539,7 @@ ext4_xattr_inode_cache_find(struct inode *inode, const void *value,
+ 				     EXT4_IGET_EA_INODE);
+ 		if (IS_ERR(ea_inode))
+ 			goto next_entry;
++		ext4_xattr_inode_set_class(ea_inode);
+ 		if (i_size_read(ea_inode) == value_len &&
+ 		    !ext4_xattr_inode_read(ea_inode, ea_data, value_len) &&
+ 		    !ext4_xattr_inode_verify_hashes(ea_inode, NULL, ea_data,

commit b3e6bcb94590dea45396b9481e47b809b1be4afa
+Author: Theodore Ts'o 
+Date:   Tue May 23 23:49:48 2023 -0400
+
+    ext4: add EA_INODE checking to ext4_iget()
+    
+    Add a new flag, EXT4_IGET_EA_INODE which indicates whether the inode
+    is expected to have the EA_INODE flag or not.  If the flag is not
+    set/clear as expected, then fail the iget() operation and mark the
+    file system as corrupted.
+    
+    This commit also makes the ext4_iget() always perform the
+    is_bad_inode() check even when the inode is already inode cache.  This
+    allows us to remove the is_bad_inode() check from the callers of
+    ext4_iget() in the ea_inode code.
+    
+    Reported-by: syzbot+cbb68193bdb95af4340a@syzkaller.appspotmail.com
+    Reported-by: syzbot+62120febbd1ee3c3c860@syzkaller.appspotmail.com
+    Reported-by: syzbot+edce54daffee36421b4c@syzkaller.appspotmail.com
+    Cc: stable@kernel.org
+    Signed-off-by: Theodore Ts'o 
+    Link: https://lore.kernel.org/r/20230524034951.779531-2-tytso@mit.edu
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 6948d673bba2..9525c52b78dc 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2901,7 +2901,8 @@ typedef enum {
+ 	EXT4_IGET_NORMAL =	0,
+ 	EXT4_IGET_SPECIAL =	0x0001, /* OK to iget a system inode */
+ 	EXT4_IGET_HANDLE = 	0x0002,	/* Inode # is from a handle */
+-	EXT4_IGET_BAD =		0x0004  /* Allow to iget a bad inode */
++	EXT4_IGET_BAD =		0x0004, /* Allow to iget a bad inode */
++	EXT4_IGET_EA_INODE =	0x0008	/* Inode should contain an EA value */
+ } ext4_iget_flags;
+ 
+ extern struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index ce5f21b6c2b3..258f3cbed347 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4641,6 +4641,21 @@ static inline void ext4_inode_set_iversion_queried(struct inode *inode, u64 val)
+ 		inode_set_iversion_queried(inode, val);
+ }
+ 
++static const char *check_igot_inode(struct inode *inode, ext4_iget_flags flags)
++
++{
++	if (flags & EXT4_IGET_EA_INODE) {
++		if (!(EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL))
++			return "missing EA_INODE flag";
++	} else {
++		if ((EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL))
++			return "unexpected EA_INODE flag";
++	}
++	if (is_bad_inode(inode) && !(flags & EXT4_IGET_BAD))
++		return "unexpected bad inode w/o EXT4_IGET_BAD";
++	return NULL;
++}
++
+ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
+ 			  ext4_iget_flags flags, const char *function,
+ 			  unsigned int line)
+@@ -4650,6 +4665,7 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
+ 	struct ext4_inode_info *ei;
+ 	struct ext4_super_block *es = EXT4_SB(sb)->s_es;
+ 	struct inode *inode;
++	const char *err_str;
+ 	journal_t *journal = EXT4_SB(sb)->s_journal;
+ 	long ret;
+ 	loff_t size;
+@@ -4677,8 +4693,14 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
+ 	inode = iget_locked(sb, ino);
+ 	if (!inode)
+ 		return ERR_PTR(-ENOMEM);
+-	if (!(inode->i_state & I_NEW))
++	if (!(inode->i_state & I_NEW)) {
++		if ((err_str = check_igot_inode(inode, flags)) != NULL) {
++			ext4_error_inode(inode, function, line, 0, err_str);
++			iput(inode);
++			return ERR_PTR(-EFSCORRUPTED);
++		}
+ 		return inode;
++	}
+ 
+ 	ei = EXT4_I(inode);
+ 	iloc.bh = NULL;
+@@ -4944,10 +4966,9 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
+ 	if (IS_CASEFOLDED(inode) && !ext4_has_feature_casefold(inode->i_sb))
+ 		ext4_error_inode(inode, function, line, 0,
+ 				 "casefold flag without casefold feature");
+-	if (is_bad_inode(inode) && !(flags & EXT4_IGET_BAD)) {
+-		ext4_error_inode(inode, function, line, 0,
+-				 "bad inode without EXT4_IGET_BAD flag");
+-		ret = -EUCLEAN;
++	if ((err_str = check_igot_inode(inode, flags)) != NULL) {
++		ext4_error_inode(inode, function, line, 0, err_str);
++		ret = -EFSCORRUPTED;
+ 		goto bad_inode;
+ 	}
+ 
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index dfc2e223bd10..a27208129a80 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -433,7 +433,7 @@ static int ext4_xattr_inode_iget(struct inode *parent, unsigned long ea_ino,
+ 		return -EFSCORRUPTED;
+ 	}
+ 
+-	inode = ext4_iget(parent->i_sb, ea_ino, EXT4_IGET_NORMAL);
++	inode = ext4_iget(parent->i_sb, ea_ino, EXT4_IGET_EA_INODE);
+ 	if (IS_ERR(inode)) {
+ 		err = PTR_ERR(inode);
+ 		ext4_error(parent->i_sb,
+@@ -441,23 +441,6 @@ static int ext4_xattr_inode_iget(struct inode *parent, unsigned long ea_ino,
+ 			   err);
+ 		return err;
+ 	}
+-
+-	if (is_bad_inode(inode)) {
+-		ext4_error(parent->i_sb,
+-			   "error while reading EA inode %lu is_bad_inode",
+-			   ea_ino);
+-		err = -EIO;
+-		goto error;
+-	}
+-
+-	if (!(EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) {
+-		ext4_error(parent->i_sb,
+-			   "EA inode %lu does not have EXT4_EA_INODE_FL flag",
+-			    ea_ino);
+-		err = -EINVAL;
+-		goto error;
+-	}
+-
+ 	ext4_xattr_inode_set_class(inode);
+ 
+ 	/*
+@@ -478,9 +461,6 @@ static int ext4_xattr_inode_iget(struct inode *parent, unsigned long ea_ino,
+ 
+ 	*ea_inode = inode;
+ 	return 0;
+-error:
+-	iput(inode);
+-	return err;
+ }
+ 
+ /* Remove entry from mbcache when EA inode is getting evicted */
+@@ -1556,11 +1536,10 @@ ext4_xattr_inode_cache_find(struct inode *inode, const void *value,
+ 
+ 	while (ce) {
+ 		ea_inode = ext4_iget(inode->i_sb, ce->e_value,
+-				     EXT4_IGET_NORMAL);
+-		if (!IS_ERR(ea_inode) &&
+-		    !is_bad_inode(ea_inode) &&
+-		    (EXT4_I(ea_inode)->i_flags & EXT4_EA_INODE_FL) &&
+-		    i_size_read(ea_inode) == value_len &&
++				     EXT4_IGET_EA_INODE);
++		if (IS_ERR(ea_inode))
++			goto next_entry;
++		if (i_size_read(ea_inode) == value_len &&
+ 		    !ext4_xattr_inode_read(ea_inode, ea_data, value_len) &&
+ 		    !ext4_xattr_inode_verify_hashes(ea_inode, NULL, ea_data,
+ 						    value_len) &&
+@@ -1570,9 +1549,8 @@ ext4_xattr_inode_cache_find(struct inode *inode, const void *value,
+ 			kvfree(ea_data);
+ 			return ea_inode;
+ 		}
+-
+-		if (!IS_ERR(ea_inode))
+-			iput(ea_inode);
++		iput(ea_inode);
++	next_entry:
+ 		ce = mb_cache_entry_find_next(ea_inode_cache, ce);
+ 	}
+ 	kvfree(ea_data);

commit 2a534e1d0d1591e951f9ece2fb460b2ff92edabd
+Author: Theodore Ts'o 
+Date:   Fri May 12 15:16:27 2023 -0400
+
+    ext4: bail out of ext4_xattr_ibody_get() fails for any reason
+    
+    In ext4_update_inline_data(), if ext4_xattr_ibody_get() fails for any
+    reason, it's best if we just fail as opposed to stumbling on,
+    especially if the failure is EFSCORRUPTED.
+    
+    Cc: stable@kernel.org
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index f47adb284e90..5854bd5a3352 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -360,7 +360,7 @@ static int ext4_update_inline_data(handle_t *handle, struct inode *inode,
+ 
+ 	error = ext4_xattr_ibody_get(inode, i.name_index, i.name,
+ 				     value, len);
+-	if (error == -ENODATA)
++	if (error < 0)
+ 		goto out;
+ 
+ 	BUFFER_TRACE(is.iloc.bh, "get_write_access");

commit 2220eaf90992c11d888fe771055d4de330385f01
+Author: Theodore Ts'o 
+Date:   Fri May 12 15:11:02 2023 -0400
+
+    ext4: add bounds checking in get_max_inline_xattr_value_size()
+    
+    Normally the extended attributes in the inode body would have been
+    checked when the inode is first opened, but if someone is writing to
+    the block device while the file system is mounted, it's possible for
+    the inode table to get corrupted.  Add bounds checking to avoid
+    reading beyond the end of allocated memory if this happens.
+    
+    Reported-by: syzbot+1966db24521e5f6e23f7@syzkaller.appspotmail.com
+    Link: https://syzkaller.appspot.com/bug?extid=1966db24521e5f6e23f7
+    Cc: stable@kernel.org
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index d3dfc51a43c5..f47adb284e90 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -34,6 +34,7 @@ static int get_max_inline_xattr_value_size(struct inode *inode,
+ 	struct ext4_xattr_ibody_header *header;
+ 	struct ext4_xattr_entry *entry;
+ 	struct ext4_inode *raw_inode;
++	void *end;
+ 	int free, min_offs;
+ 
+ 	if (!EXT4_INODE_HAS_XATTR_SPACE(inode))
+@@ -57,14 +58,23 @@ static int get_max_inline_xattr_value_size(struct inode *inode,
+ 	raw_inode = ext4_raw_inode(iloc);
+ 	header = IHDR(inode, raw_inode);
+ 	entry = IFIRST(header);
++	end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
+ 
+ 	/* Compute min_offs. */
+-	for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) {
++	while (!IS_LAST_ENTRY(entry)) {
++		void *next = EXT4_XATTR_NEXT(entry);
++
++		if (next >= end) {
++			EXT4_ERROR_INODE(inode,
++					 "corrupt xattr in inline inode");
++			return 0;
++		}
+ 		if (!entry->e_value_inum && entry->e_value_size) {
+ 			size_t offs = le16_to_cpu(entry->e_value_offs);
+ 			if (offs < min_offs)
+ 				min_offs = offs;
+ 		}
++		entry = next;
+ 	}
+ 	free = min_offs -
+ 		((void *)entry - (void *)IFIRST(header)) - sizeof(__u32);

commit 6dcc98fbc46511f7a6650946f198df6951a5a88c
+Author: Theodore Ts'o 
+Date:   Fri May 12 14:49:57 2023 -0400
+
+    ext4: add indication of ro vs r/w mounts in the mount message
+    
+    Whether the file system is mounted read-only or read/write is more
+    important than the quota mode, which we are already printing.  Add the
+    ro vs r/w indication since this can be helpful in debugging problems
+    from the console log.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index bc0b4a98b337..9680fe753e59 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -5684,8 +5684,9 @@ static int ext4_fill_super(struct super_block *sb, struct fs_context *fc)
+ 		descr = "out journal";
+ 
+ 	if (___ratelimit(&ext4_mount_msg_ratelimit, "EXT4-fs mount"))
+-		ext4_msg(sb, KERN_INFO, "mounted filesystem %pU with%s. "
+-			 "Quota mode: %s.", &sb->s_uuid, descr,
++		ext4_msg(sb, KERN_INFO, "mounted filesystem %pU %s with%s. "
++			 "Quota mode: %s.", &sb->s_uuid,
++			 sb_rdonly(sb) ? "ro" : "r/w", descr,
+ 			 ext4_quota_mode(sb));
+ 
+ 	/* Update the s_overhead_clusters if necessary */
+@@ -6689,8 +6690,9 @@ static int ext4_reconfigure(struct fs_context *fc)
+ 	if (ret < 0)
+ 		return ret;
+ 
+-	ext4_msg(sb, KERN_INFO, "re-mounted %pU. Quota mode: %s.",
+-		 &sb->s_uuid, ext4_quota_mode(sb));
++	ext4_msg(sb, KERN_INFO, "re-mounted %pU %s. Quota mode: %s.",
++		 &sb->s_uuid, sb_rdonly(sb) ? "ro" : "r/w",
++		 ext4_quota_mode(sb));
+ 
+ 	return 0;
+ }

commit f4ce24f54d9cca4f09a395f3eecce20d6bec4663
+Author: Theodore Ts'o 
+Date:   Sat May 6 21:04:01 2023 -0400
+
+    ext4: fix deadlock when converting an inline directory in nojournal mode
+    
+    In no journal mode, ext4_finish_convert_inline_dir() can self-deadlock
+    by calling ext4_handle_dirty_dirblock() when it already has taken the
+    directory lock.  There is a similar self-deadlock in
+    ext4_incvert_inline_data_nolock() for data files which we'll fix at
+    the same time.
+    
+    A simple reproducer demonstrating the problem:
+    
+        mke2fs -Fq -t ext2 -O inline_data -b 4k /dev/vdc 64
+        mount -t ext4 -o dirsync /dev/vdc /vdc
+        cd /vdc
+        mkdir file0
+        cd file0
+        touch file0
+        touch file1
+        attr -s BurnSpaceInEA -V abcde .
+        touch supercalifragilisticexpialidocious
+    
+    Cc: stable@kernel.org
+    Link: https://lore.kernel.org/r/20230507021608.1290720-1-tytso@mit.edu
+    Reported-by: syzbot+91dccab7c64e2850a4e5@syzkaller.appspotmail.com
+    Link: https://syzkaller.appspot.com/bug?id=ba84cc80a9491d65416bc7877e1650c87530fe8a
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index 859bc4e2c9b0..d3dfc51a43c5 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -1175,6 +1175,7 @@ static int ext4_finish_convert_inline_dir(handle_t *handle,
+ 		ext4_initialize_dirent_tail(dir_block,
+ 					    inode->i_sb->s_blocksize);
+ 	set_buffer_uptodate(dir_block);
++	unlock_buffer(dir_block);
+ 	err = ext4_handle_dirty_dirblock(handle, inode, dir_block);
+ 	if (err)
+ 		return err;
+@@ -1249,6 +1250,7 @@ static int ext4_convert_inline_data_nolock(handle_t *handle,
+ 	if (!S_ISDIR(inode->i_mode)) {
+ 		memcpy(data_bh->b_data, buf, inline_size);
+ 		set_buffer_uptodate(data_bh);
++		unlock_buffer(data_bh);
+ 		error = ext4_handle_dirty_metadata(handle,
+ 						   inode, data_bh);
+ 	} else {
+@@ -1256,7 +1258,6 @@ static int ext4_convert_inline_data_nolock(handle_t *handle,
+ 						       buf, inline_size);
+ 	}
+ 
+-	unlock_buffer(data_bh);
+ out_restore:
+ 	if (error)
+ 		ext4_restore_inline_data(handle, inode, iloc, buf, inline_size);

commit 4c0b4818b1f636bc96359f7817a2d8bab6370162
+Author: Theodore Ts'o 
+Date:   Fri May 5 22:20:29 2023 -0400
+
+    ext4: improve error recovery code paths in __ext4_remount()
+    
+    If there are failures while changing the mount options in
+    __ext4_remount(), we need to restore the old mount options.
+    
+    This commit fixes two problem.  The first is there is a chance that we
+    will free the old quota file names before a potential failure leading
+    to a use-after-free.  The second problem addressed in this commit is
+    if there is a failed read/write to read-only transition, if the quota
+    has already been suspended, we need to renable quota handling.
+    
+    Cc: stable@kernel.org
+    Link: https://lore.kernel.org/r/20230506142419.984260-2-tytso@mit.edu
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index c7bc4a2709cc..bc0b4a98b337 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -6617,9 +6617,6 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb)
+ 	}
+ 
+ #ifdef CONFIG_QUOTA
+-	/* Release old quota file names */
+-	for (i = 0; i < EXT4_MAXQUOTAS; i++)
+-		kfree(old_opts.s_qf_names[i]);
+ 	if (enable_quota) {
+ 		if (sb_any_quota_suspended(sb))
+ 			dquot_resume(sb, -1);
+@@ -6629,6 +6626,9 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb)
+ 				goto restore_opts;
+ 		}
+ 	}
++	/* Release old quota file names */
++	for (i = 0; i < EXT4_MAXQUOTAS; i++)
++		kfree(old_opts.s_qf_names[i]);
+ #endif
+ 	if (!test_opt(sb, BLOCK_VALIDITY) && sbi->s_system_blks)
+ 		ext4_release_system_zone(sb);
+@@ -6642,6 +6642,13 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb)
+ 	return 0;
+ 
+ restore_opts:
++	/*
++	 * If there was a failing r/w to ro transition, we may need to
++	 * re-enable quota
++	 */
++	if ((sb->s_flags & SB_RDONLY) && !(old_sb_flags & SB_RDONLY) &&
++	    sb_any_quota_suspended(sb))
++		dquot_resume(sb, -1);
+ 	sb->s_flags = old_sb_flags;
+ 	sbi->s_mount_opt = old_opts.s_mount_opt;
+ 	sbi->s_mount_opt2 = old_opts.s_mount_opt2;

commit 4b3cb1d108bfc2aebb0d7c8a52261a53cf7f5786
+Author: Theodore Ts'o 
+Date:   Sat May 6 11:59:13 2023 -0400
+
+    ext4: improve error handling from ext4_dirhash()
+    
+    The ext4_dirhash() will *almost* never fail, especially when the hash
+    tree feature was first introduced.  However, with the addition of
+    support of encrypted, casefolded file names, that function can most
+    certainly fail today.
+    
+    So make sure the callers of ext4_dirhash() properly check for
+    failures, and reflect the errors back up to their callers.
+    
+    Cc: stable@kernel.org
+    Link: https://lore.kernel.org/r/20230506142419.984260-1-tytso@mit.edu
+    Reported-by: syzbot+394aa8a792cb99dbc837@syzkaller.appspotmail.com
+    Reported-by: syzbot+344aaa8697ebd232bfc8@syzkaller.appspotmail.com
+    Link: https://syzkaller.appspot.com/bug?id=db56459ea4ac4a676ae4b4678f633e55da005a9b
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/hash.c b/fs/ext4/hash.c
+index 147b5241dd94..46c3423ddfa1 100644
+--- a/fs/ext4/hash.c
++++ b/fs/ext4/hash.c
+@@ -277,7 +277,11 @@ static int __ext4fs_dirhash(const struct inode *dir, const char *name, int len,
+ 	}
+ 	default:
+ 		hinfo->hash = 0;
+-		return -1;
++		hinfo->minor_hash = 0;
++		ext4_warning(dir->i_sb,
++			     "invalid/unsupported hash tree version %u",
++			     hinfo->hash_version);
++		return -EINVAL;
+ 	}
+ 	hash = hash & ~1;
+ 	if (hash == (EXT4_HTREE_EOF_32BIT << 1))
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index a5010b5b8a8c..45b579805c95 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -674,7 +674,7 @@ static struct stats dx_show_leaf(struct inode *dir,
+ 				len = de->name_len;
+ 				if (!IS_ENCRYPTED(dir)) {
+ 					/* Directory is not encrypted */
+-					ext4fs_dirhash(dir, de->name,
++					(void) ext4fs_dirhash(dir, de->name,
+ 						de->name_len, &h);
+ 					printk("%*.s:(U)%x.%u ", len,
+ 					       name, h.hash,
+@@ -709,8 +709,9 @@ static struct stats dx_show_leaf(struct inode *dir,
+ 					if (IS_CASEFOLDED(dir))
+ 						h.hash = EXT4_DIRENT_HASH(de);
+ 					else
+-						ext4fs_dirhash(dir, de->name,
+-						       de->name_len, &h);
++						(void) ext4fs_dirhash(dir,
++							de->name,
++							de->name_len, &h);
+ 					printk("%*.s:(E)%x.%u ", len, name,
+ 					       h.hash, (unsigned) ((char *) de
+ 								   - base));
+@@ -720,7 +721,8 @@ static struct stats dx_show_leaf(struct inode *dir,
+ #else
+ 				int len = de->name_len;
+ 				char *name = de->name;
+-				ext4fs_dirhash(dir, de->name, de->name_len, &h);
++				(void) ext4fs_dirhash(dir, de->name,
++						      de->name_len, &h);
+ 				printk("%*.s:%x.%u ", len, name, h.hash,
+ 				       (unsigned) ((char *) de - base));
+ #endif
+@@ -849,8 +851,14 @@ dx_probe(struct ext4_filename *fname, struct inode *dir,
+ 	hinfo->seed = EXT4_SB(dir->i_sb)->s_hash_seed;
+ 	/* hash is already computed for encrypted casefolded directory */
+ 	if (fname && fname_name(fname) &&
+-				!(IS_ENCRYPTED(dir) && IS_CASEFOLDED(dir)))
+-		ext4fs_dirhash(dir, fname_name(fname), fname_len(fname), hinfo);
++	    !(IS_ENCRYPTED(dir) && IS_CASEFOLDED(dir))) {
++		int ret = ext4fs_dirhash(dir, fname_name(fname),
++					 fname_len(fname), hinfo);
++		if (ret < 0) {
++			ret_err = ERR_PTR(ret);
++			goto fail;
++		}
++	}
+ 	hash = hinfo->hash;
+ 
+ 	if (root->info.unused_flags & 1) {
+@@ -1111,7 +1119,12 @@ static int htree_dirblock_to_tree(struct file *dir_file,
+ 				hinfo->minor_hash = 0;
+ 			}
+ 		} else {
+-			ext4fs_dirhash(dir, de->name, de->name_len, hinfo);
++			err = ext4fs_dirhash(dir, de->name,
++					     de->name_len, hinfo);
++			if (err < 0) {
++				count = err;
++				goto errout;
++			}
+ 		}
+ 		if ((hinfo->hash < start_hash) ||
+ 		    ((hinfo->hash == start_hash) &&
+@@ -1313,8 +1326,12 @@ static int dx_make_map(struct inode *dir, struct buffer_head *bh,
+ 		if (de->name_len && de->inode) {
+ 			if (ext4_hash_in_dirent(dir))
+ 				h.hash = EXT4_DIRENT_HASH(de);
+-			else
+-				ext4fs_dirhash(dir, de->name, de->name_len, &h);
++			else {
++				int err = ext4fs_dirhash(dir, de->name,
++						     de->name_len, &h);
++				if (err < 0)
++					return err;
++			}
+ 			map_tail--;
+ 			map_tail->hash = h.hash;
+ 			map_tail->offs = ((char *) de - base)>>2;
+@@ -1452,10 +1469,9 @@ int ext4_fname_setup_ci_filename(struct inode *dir, const struct qstr *iname,
+ 	hinfo->hash_version = DX_HASH_SIPHASH;
+ 	hinfo->seed = NULL;
+ 	if (cf_name->name)
+-		ext4fs_dirhash(dir, cf_name->name, cf_name->len, hinfo);
++		return ext4fs_dirhash(dir, cf_name->name, cf_name->len, hinfo);
+ 	else
+-		ext4fs_dirhash(dir, iname->name, iname->len, hinfo);
+-	return 0;
++		return ext4fs_dirhash(dir, iname->name, iname->len, hinfo);
+ }
+ #endif
+ 
+@@ -2298,10 +2314,15 @@ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname,
+ 	fname->hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed;
+ 
+ 	/* casefolded encrypted hashes are computed on fname setup */
+-	if (!ext4_hash_in_dirent(dir))
+-		ext4fs_dirhash(dir, fname_name(fname),
+-				fname_len(fname), &fname->hinfo);
+-
++	if (!ext4_hash_in_dirent(dir)) {
++		int err = ext4fs_dirhash(dir, fname_name(fname),
++					 fname_len(fname), &fname->hinfo);
++		if (err < 0) {
++			brelse(bh2);
++			brelse(bh);
++			return err;
++		}
++	}
+ 	memset(frames, 0, sizeof(frames));
+ 	frame = frames;
+ 	frame->entries = entries;

commit a44be64bbecb15a452496f60db6eacfee2b59c79
+Author: Theodore Ts'o 
+Date:   Fri May 5 21:02:30 2023 -0400
+
+    ext4: don't clear SB_RDONLY when remounting r/w until quota is re-enabled
+    
+    When a file system currently mounted read/only is remounted
+    read/write, if we clear the SB_RDONLY flag too early, before the quota
+    is initialized, and there is another process/thread constantly
+    attempting to create a directory, it's possible to trigger the
+    
+            WARN_ON_ONCE(dquot_initialize_needed(inode));
+    
+    in ext4_xattr_block_set(), with the following stack trace:
+    
+       WARNING: CPU: 0 PID: 5338 at fs/ext4/xattr.c:2141 ext4_xattr_block_set+0x2ef2/0x3680
+       RIP: 0010:ext4_xattr_block_set+0x2ef2/0x3680 fs/ext4/xattr.c:2141
+       Call Trace:
+        ext4_xattr_set_handle+0xcd4/0x15c0 fs/ext4/xattr.c:2458
+        ext4_initxattrs+0xa3/0x110 fs/ext4/xattr_security.c:44
+        security_inode_init_security+0x2df/0x3f0 security/security.c:1147
+        __ext4_new_inode+0x347e/0x43d0 fs/ext4/ialloc.c:1324
+        ext4_mkdir+0x425/0xce0 fs/ext4/namei.c:2992
+        vfs_mkdir+0x29d/0x450 fs/namei.c:4038
+        do_mkdirat+0x264/0x520 fs/namei.c:4061
+        __do_sys_mkdirat fs/namei.c:4076 [inline]
+        __se_sys_mkdirat fs/namei.c:4074 [inline]
+        __x64_sys_mkdirat+0x89/0xa0 fs/namei.c:4074
+    
+    Cc: stable@kernel.org
+    Link: https://lore.kernel.org/r/20230506142419.984260-1-tytso@mit.edu
+    Reported-by: syzbot+6385d7d3065524c5ca6d@syzkaller.appspotmail.com
+    Link: https://syzkaller.appspot.com/bug?id=6513f6cb5cd6b5fc9f37e3bb70d273b94be9c34c
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 425b95a7a0ab..c7bc4a2709cc 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -6387,6 +6387,7 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb)
+ 	struct ext4_mount_options old_opts;
+ 	ext4_group_t g;
+ 	int err = 0;
++	int enable_rw = 0;
+ #ifdef CONFIG_QUOTA
+ 	int enable_quota = 0;
+ 	int i, j;
+@@ -6573,7 +6574,7 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb)
+ 			if (err)
+ 				goto restore_opts;
+ 
+-			sb->s_flags &= ~SB_RDONLY;
++			enable_rw = 1;
+ 			if (ext4_has_feature_mmp(sb)) {
+ 				err = ext4_multi_mount_protect(sb,
+ 						le64_to_cpu(es->s_mmp_block));
+@@ -6632,6 +6633,9 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb)
+ 	if (!test_opt(sb, BLOCK_VALIDITY) && sbi->s_system_blks)
+ 		ext4_release_system_zone(sb);
+ 
++	if (enable_rw)
++		sb->s_flags &= ~SB_RDONLY;
++
+ 	if (!ext4_has_feature_mmp(sb) || sb_rdonly(sb))
+ 		ext4_stop_mmpd(sbi);
+ 

commit b87c7cdf2bed4928b899e1ce91ef0d147017ba45
+Author: Theodore Ts'o 
+Date:   Sun Apr 30 03:04:13 2023 -0400
+
+    ext4: fix invalid free tracking in ext4_xattr_move_to_block()
+    
+    In ext4_xattr_move_to_block(), the value of the extended attribute
+    which we need to move to an external block may be allocated by
+    kvmalloc() if the value is stored in an external inode.  So at the end
+    of the function the code tried to check if this was the case by
+    testing entry->e_value_inum.
+    
+    However, at this point, the pointer to the xattr entry is no longer
+    valid, because it was removed from the original location where it had
+    been stored.  So we could end up calling kvfree() on a pointer which
+    was not allocated by kvmalloc(); or we could also potentially leak
+    memory by not freeing the buffer when it should be freed.  Fix this by
+    storing whether it should be freed in a separate variable.
+    
+    Cc: stable@kernel.org
+    Link: https://lore.kernel.org/r/20230430160426.581366-1-tytso@mit.edu
+    Link: https://syzkaller.appspot.com/bug?id=5c2aee8256e30b55ccf57312c16d88417adbd5e1
+    Link: https://syzkaller.appspot.com/bug?id=41a6b5d4917c0412eb3b3c3c604965bed7d7420b
+    Reported-by: syzbot+64b645917ce07d89bde5@syzkaller.appspotmail.com
+    Reported-by: syzbot+0d042627c4f2ad332195@syzkaller.appspotmail.com
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index dadad29bd81b..dfc2e223bd10 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -2614,6 +2614,7 @@ static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode,
+ 		.in_inode = !!entry->e_value_inum,
+ 	};
+ 	struct ext4_xattr_ibody_header *header = IHDR(inode, raw_inode);
++	int needs_kvfree = 0;
+ 	int error;
+ 
+ 	is = kzalloc(sizeof(struct ext4_xattr_ibody_find), GFP_NOFS);
+@@ -2636,7 +2637,7 @@ static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode,
+ 			error = -ENOMEM;
+ 			goto out;
+ 		}
+-
++		needs_kvfree = 1;
+ 		error = ext4_xattr_inode_get(inode, entry, buffer, value_size);
+ 		if (error)
+ 			goto out;
+@@ -2675,7 +2676,7 @@ static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode,
+ 
+ out:
+ 	kfree(b_entry_name);
+-	if (entry->e_value_inum && buffer)
++	if (needs_kvfree && buffer)
+ 		kvfree(buffer);
+ 	if (is)
+ 		brelse(is->iloc.bh);

commit 463808f237cf73e98a1a45ff7460c2406a150a0b
+Author: Theodore Ts'o 
+Date:   Sat Apr 29 16:14:46 2023 -0400
+
+    ext4: remove a BUG_ON in ext4_mb_release_group_pa()
+    
+    If a malicious fuzzer overwrites the ext4 superblock while it is
+    mounted such that the s_first_data_block is set to a very large
+    number, the calculation of the block group can underflow, and trigger
+    a BUG_ON check.  Change this to be an ext4_warning so that we don't
+    crash the kernel.
+    
+    Cc: stable@kernel.org
+    Link: https://lore.kernel.org/r/20230430154311.579720-3-tytso@mit.edu
+    Reported-by: syzbot+e2efa3efc15a1c9e95c3@syzkaller.appspotmail.com
+    Link: https://syzkaller.appspot.com/bug?id=69b28112e098b070f639efb356393af3ffec4220
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index a857db48b383..7b2e36d103cb 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -5047,7 +5047,11 @@ ext4_mb_release_group_pa(struct ext4_buddy *e4b,
+ 	trace_ext4_mb_release_group_pa(sb, pa);
+ 	BUG_ON(pa->pa_deleted == 0);
+ 	ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit);
+-	BUG_ON(group != e4b->bd_group && pa->pa_len != 0);
++	if (unlikely(group != e4b->bd_group && pa->pa_len != 0)) {
++		ext4_warning(sb, "bad group: expected %u, group %u, pa_start %llu",
++			     e4b->bd_group, group, pa->pa_pstart);
++		return 0;
++	}
+ 	mb_free_blocks(pa->pa_inode, e4b, bit, pa->pa_len);
+ 	atomic_add(pa->pa_len, &EXT4_SB(sb)->s_mb_discarded);
+ 	trace_ext4_mballoc_discard(sb, NULL, group, bit, pa->pa_len);

commit 5354b2af34064a4579be8bc0e2f15a7b70f14b5f
+Author: Theodore Ts'o 
+Date:   Sat Apr 29 00:06:28 2023 -0400
+
+    ext4: allow ext4_get_group_info() to fail
+    
+    Previously, ext4_get_group_info() would treat an invalid group number
+    as BUG(), since in theory it should never happen.  However, if a
+    malicious attaker (or fuzzer) modifies the superblock via the block
+    device while it is the file system is mounted, it is possible for
+    s_first_data_block to get set to a very large number.  In that case,
+    when calculating the block group of some block number (such as the
+    starting block of a preallocation region), could result in an
+    underflow and very large block group number.  Then the BUG_ON check in
+    ext4_get_group_info() would fire, resutling in a denial of service
+    attack that can be triggered by root or someone with write access to
+    the block device.
+    
+    For a quality of implementation perspective, it's best that even if
+    the system administrator does something that they shouldn't, that it
+    will not trigger a BUG.  So instead of BUG'ing, ext4_get_group_info()
+    will call ext4_error and return NULL.  We also add fallback code in
+    all of the callers of ext4_get_group_info() that it might NULL.
+    
+    Also, since ext4_get_group_info() was already borderline to be an
+    inline function, un-inline it.  The results in a next reduction of the
+    compiled text size of ext4 by roughly 2k.
+    
+    Cc: stable@kernel.org
+    Link: https://lore.kernel.org/r/20230430154311.579720-2-tytso@mit.edu
+    Reported-by: syzbot+e2efa3efc15a1c9e95c3@syzkaller.appspotmail.com
+    Link: https://syzkaller.appspot.com/bug?id=69b28112e098b070f639efb356393af3ffec4220
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index c49e612e3975..c1edde817be8 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -321,6 +321,22 @@ static ext4_fsblk_t ext4_valid_block_bitmap_padding(struct super_block *sb,
+ 	return (next_zero_bit < bitmap_size ? next_zero_bit : 0);
+ }
+ 
++struct ext4_group_info *ext4_get_group_info(struct super_block *sb,
++					    ext4_group_t group)
++{
++	 struct ext4_group_info **grp_info;
++	 long indexv, indexh;
++
++	 if (unlikely(group >= EXT4_SB(sb)->s_groups_count)) {
++		 ext4_error(sb, "invalid group %u", group);
++		 return NULL;
++	 }
++	 indexv = group >> (EXT4_DESC_PER_BLOCK_BITS(sb));
++	 indexh = group & ((EXT4_DESC_PER_BLOCK(sb)) - 1);
++	 grp_info = sbi_array_rcu_deref(EXT4_SB(sb), s_group_info, indexv);
++	 return grp_info[indexh];
++}
++
+ /*
+  * Return the block number which was discovered to be invalid, or 0 if
+  * the block bitmap is valid.
+@@ -395,7 +411,7 @@ static int ext4_validate_block_bitmap(struct super_block *sb,
+ 
+ 	if (buffer_verified(bh))
+ 		return 0;
+-	if (EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
++	if (!grp || EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
+ 		return -EFSCORRUPTED;
+ 
+ 	ext4_lock_group(sb, block_group);
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 18cb2680dc39..7e8f66ba17f4 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2625,6 +2625,8 @@ extern void ext4_check_blocks_bitmap(struct super_block *);
+ extern struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
+ 						    ext4_group_t block_group,
+ 						    struct buffer_head ** bh);
++extern struct ext4_group_info *ext4_get_group_info(struct super_block *sb,
++						   ext4_group_t group);
+ extern int ext4_should_retry_alloc(struct super_block *sb, int *retries);
+ 
+ extern struct buffer_head *ext4_read_block_bitmap_nowait(struct super_block *sb,
+@@ -3232,19 +3234,6 @@ static inline void ext4_isize_set(struct ext4_inode *raw_inode, loff_t i_size)
+ 	raw_inode->i_size_high = cpu_to_le32(i_size >> 32);
+ }
+ 
+-static inline
+-struct ext4_group_info *ext4_get_group_info(struct super_block *sb,
+-					    ext4_group_t group)
+-{
+-	 struct ext4_group_info **grp_info;
+-	 long indexv, indexh;
+-	 BUG_ON(group >= EXT4_SB(sb)->s_groups_count);
+-	 indexv = group >> (EXT4_DESC_PER_BLOCK_BITS(sb));
+-	 indexh = group & ((EXT4_DESC_PER_BLOCK(sb)) - 1);
+-	 grp_info = sbi_array_rcu_deref(EXT4_SB(sb), s_group_info, indexv);
+-	 return grp_info[indexh];
+-}
+-
+ /*
+  * Reading s_groups_count requires using smp_rmb() afterwards.  See
+  * the locking protocol documented in the comments of ext4_group_add()
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 787ab89c2c26..754f961cd9fd 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -91,7 +91,7 @@ static int ext4_validate_inode_bitmap(struct super_block *sb,
+ 
+ 	if (buffer_verified(bh))
+ 		return 0;
+-	if (EXT4_MB_GRP_IBITMAP_CORRUPT(grp))
++	if (!grp || EXT4_MB_GRP_IBITMAP_CORRUPT(grp))
+ 		return -EFSCORRUPTED;
+ 
+ 	ext4_lock_group(sb, block_group);
+@@ -293,7 +293,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
+ 	}
+ 	if (!(sbi->s_mount_state & EXT4_FC_REPLAY)) {
+ 		grp = ext4_get_group_info(sb, block_group);
+-		if (unlikely(EXT4_MB_GRP_IBITMAP_CORRUPT(grp))) {
++		if (!grp || unlikely(EXT4_MB_GRP_IBITMAP_CORRUPT(grp))) {
+ 			fatal = -EFSCORRUPTED;
+ 			goto error_return;
+ 		}
+@@ -1046,7 +1046,7 @@ struct inode *__ext4_new_inode(struct mnt_idmap *idmap,
+ 			 * Skip groups with already-known suspicious inode
+ 			 * tables
+ 			 */
+-			if (EXT4_MB_GRP_IBITMAP_CORRUPT(grp))
++			if (!grp || EXT4_MB_GRP_IBITMAP_CORRUPT(grp))
+ 				goto next_group;
+ 		}
+ 
+@@ -1183,6 +1183,10 @@ struct inode *__ext4_new_inode(struct mnt_idmap *idmap,
+ 
+ 		if (!(sbi->s_mount_state & EXT4_FC_REPLAY)) {
+ 			grp = ext4_get_group_info(sb, group);
++			if (!grp) {
++				err = -EFSCORRUPTED;
++				goto out;
++			}
+ 			down_read(&grp->alloc_sem); /*
+ 						     * protect vs itable
+ 						     * lazyinit
+@@ -1526,7 +1530,7 @@ int ext4_init_inode_table(struct super_block *sb, ext4_group_t group,
+ 	}
+ 
+ 	gdp = ext4_get_group_desc(sb, group, &group_desc_bh);
+-	if (!gdp)
++	if (!gdp || !grp)
+ 		goto out;
+ 
+ 	/*
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 78259bddbc4d..a857db48b383 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -745,6 +745,8 @@ static int __mb_check_buddy(struct ext4_buddy *e4b, char *file,
+ 	MB_CHECK_ASSERT(e4b->bd_info->bb_fragments == fragments);
+ 
+ 	grp = ext4_get_group_info(sb, e4b->bd_group);
++	if (!grp)
++		return NULL;
+ 	list_for_each(cur, &grp->bb_prealloc_list) {
+ 		ext4_group_t groupnr;
+ 		struct ext4_prealloc_space *pa;
+@@ -1060,9 +1062,9 @@ mb_set_largest_free_order(struct super_block *sb, struct ext4_group_info *grp)
+ 
+ static noinline_for_stack
+ void ext4_mb_generate_buddy(struct super_block *sb,
+-				void *buddy, void *bitmap, ext4_group_t group)
++			    void *buddy, void *bitmap, ext4_group_t group,
++			    struct ext4_group_info *grp)
+ {
+-	struct ext4_group_info *grp = ext4_get_group_info(sb, group);
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	ext4_grpblk_t max = EXT4_CLUSTERS_PER_GROUP(sb);
+ 	ext4_grpblk_t i = 0;
+@@ -1181,6 +1183,8 @@ static int ext4_mb_init_cache(struct page *page, char *incore, gfp_t gfp)
+ 			break;
+ 
+ 		grinfo = ext4_get_group_info(sb, group);
++		if (!grinfo)
++			continue;
+ 		/*
+ 		 * If page is uptodate then we came here after online resize
+ 		 * which added some new uninitialized group info structs, so
+@@ -1246,6 +1250,10 @@ static int ext4_mb_init_cache(struct page *page, char *incore, gfp_t gfp)
+ 				group, page->index, i * blocksize);
+ 			trace_ext4_mb_buddy_bitmap_load(sb, group);
+ 			grinfo = ext4_get_group_info(sb, group);
++			if (!grinfo) {
++				err = -EFSCORRUPTED;
++				goto out;
++			}
+ 			grinfo->bb_fragments = 0;
+ 			memset(grinfo->bb_counters, 0,
+ 			       sizeof(*grinfo->bb_counters) *
+@@ -1256,7 +1264,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore, gfp_t gfp)
+ 			ext4_lock_group(sb, group);
+ 			/* init the buddy */
+ 			memset(data, 0xff, blocksize);
+-			ext4_mb_generate_buddy(sb, data, incore, group);
++			ext4_mb_generate_buddy(sb, data, incore, group, grinfo);
+ 			ext4_unlock_group(sb, group);
+ 			incore = NULL;
+ 		} else {
+@@ -1370,6 +1378,9 @@ int ext4_mb_init_group(struct super_block *sb, ext4_group_t group, gfp_t gfp)
+ 	might_sleep();
+ 	mb_debug(sb, "init group %u\n", group);
+ 	this_grp = ext4_get_group_info(sb, group);
++	if (!this_grp)
++		return -EFSCORRUPTED;
++
+ 	/*
+ 	 * This ensures that we don't reinit the buddy cache
+ 	 * page which map to the group from which we are already
+@@ -1444,6 +1455,8 @@ ext4_mb_load_buddy_gfp(struct super_block *sb, ext4_group_t group,
+ 
+ 	blocks_per_page = PAGE_SIZE / sb->s_blocksize;
+ 	grp = ext4_get_group_info(sb, group);
++	if (!grp)
++		return -EFSCORRUPTED;
+ 
+ 	e4b->bd_blkbits = sb->s_blocksize_bits;
+ 	e4b->bd_info = grp;
+@@ -2159,6 +2172,8 @@ int ext4_mb_find_by_goal(struct ext4_allocation_context *ac,
+ 	struct ext4_group_info *grp = ext4_get_group_info(ac->ac_sb, group);
+ 	struct ext4_free_extent ex;
+ 
++	if (!grp)
++		return -EFSCORRUPTED;
+ 	if (!(ac->ac_flags & (EXT4_MB_HINT_TRY_GOAL | EXT4_MB_HINT_GOAL_ONLY)))
+ 		return 0;
+ 	if (grp->bb_free == 0)
+@@ -2385,7 +2400,7 @@ static bool ext4_mb_good_group(struct ext4_allocation_context *ac,
+ 
+ 	BUG_ON(cr < 0 || cr >= 4);
+ 
+-	if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(grp)))
++	if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(grp) || !grp))
+ 		return false;
+ 
+ 	free = grp->bb_free;
+@@ -2454,6 +2469,8 @@ static int ext4_mb_good_group_nolock(struct ext4_allocation_context *ac,
+ 	ext4_grpblk_t free;
+ 	int ret = 0;
+ 
++	if (!grp)
++		return -EFSCORRUPTED;
+ 	if (sbi->s_mb_stats)
+ 		atomic64_inc(&sbi->s_bal_cX_groups_considered[ac->ac_criteria]);
+ 	if (should_lock) {
+@@ -2534,7 +2551,7 @@ ext4_group_t ext4_mb_prefetch(struct super_block *sb, ext4_group_t group,
+ 		 * prefetch once, so we avoid getblk() call, which can
+ 		 * be expensive.
+ 		 */
+-		if (!EXT4_MB_GRP_TEST_AND_SET_READ(grp) &&
++		if (gdp && grp && !EXT4_MB_GRP_TEST_AND_SET_READ(grp) &&
+ 		    EXT4_MB_GRP_NEED_INIT(grp) &&
+ 		    ext4_free_group_clusters(sb, gdp) > 0 &&
+ 		    !(ext4_has_group_desc_csum(sb) &&
+@@ -2578,7 +2595,7 @@ void ext4_mb_prefetch_fini(struct super_block *sb, ext4_group_t group,
+ 		gdp = ext4_get_group_desc(sb, group, NULL);
+ 		grp = ext4_get_group_info(sb, group);
+ 
+-		if (EXT4_MB_GRP_NEED_INIT(grp) &&
++		if (grp && gdp && EXT4_MB_GRP_NEED_INIT(grp) &&
+ 		    ext4_free_group_clusters(sb, gdp) > 0 &&
+ 		    !(ext4_has_group_desc_csum(sb) &&
+ 		      (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)))) {
+@@ -2837,6 +2854,8 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v)
+ 		sizeof(struct ext4_group_info);
+ 
+ 	grinfo = ext4_get_group_info(sb, group);
++	if (!grinfo)
++		return 0;
+ 	/* Load the group info in memory only if not already loaded. */
+ 	if (unlikely(EXT4_MB_GRP_NEED_INIT(grinfo))) {
+ 		err = ext4_mb_load_buddy(sb, group, &e4b);
+@@ -2847,7 +2866,7 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v)
+ 		buddy_loaded = 1;
+ 	}
+ 
+-	memcpy(&sg, ext4_get_group_info(sb, group), i);
++	memcpy(&sg, grinfo, i);
+ 
+ 	if (buddy_loaded)
+ 		ext4_mb_unload_buddy(&e4b);
+@@ -3208,8 +3227,12 @@ static int ext4_mb_init_backend(struct super_block *sb)
+ 
+ err_freebuddy:
+ 	cachep = get_groupinfo_cache(sb->s_blocksize_bits);
+-	while (i-- > 0)
+-		kmem_cache_free(cachep, ext4_get_group_info(sb, i));
++	while (i-- > 0) {
++		struct ext4_group_info *grp = ext4_get_group_info(sb, i);
++
++		if (grp)
++			kmem_cache_free(cachep, grp);
++	}
+ 	i = sbi->s_group_info_size;
+ 	rcu_read_lock();
+ 	group_info = rcu_dereference(sbi->s_group_info);
+@@ -3522,6 +3545,8 @@ int ext4_mb_release(struct super_block *sb)
+ 		for (i = 0; i < ngroups; i++) {
+ 			cond_resched();
+ 			grinfo = ext4_get_group_info(sb, i);
++			if (!grinfo)
++				continue;
+ 			mb_group_bb_bitmap_free(grinfo);
+ 			ext4_lock_group(sb, i);
+ 			count = ext4_mb_cleanup_pa(grinfo);
+@@ -4606,6 +4631,8 @@ static void ext4_mb_generate_from_freelist(struct super_block *sb, void *bitmap,
+ 	struct ext4_free_data *entry;
+ 
+ 	grp = ext4_get_group_info(sb, group);
++	if (!grp)
++		return;
+ 	n = rb_first(&(grp->bb_free_root));
+ 
+ 	while (n) {
+@@ -4633,6 +4660,9 @@ void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap,
+ 	int preallocated = 0;
+ 	int len;
+ 
++	if (!grp)
++		return;
++
+ 	/* all form of preallocation discards first load group,
+ 	 * so the only competing code is preallocation use.
+ 	 * we don't need any locking here
+@@ -4869,6 +4899,8 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
+ 
+ 	ei = EXT4_I(ac->ac_inode);
+ 	grp = ext4_get_group_info(sb, ac->ac_b_ex.fe_group);
++	if (!grp)
++		return;
+ 
+ 	pa->pa_node_lock.inode_lock = &ei->i_prealloc_lock;
+ 	pa->pa_inode = ac->ac_inode;
+@@ -4918,6 +4950,8 @@ ext4_mb_new_group_pa(struct ext4_allocation_context *ac)
+ 	atomic_add(pa->pa_free, &EXT4_SB(sb)->s_mb_preallocated);
+ 
+ 	grp = ext4_get_group_info(sb, ac->ac_b_ex.fe_group);
++	if (!grp)
++		return;
+ 	lg = ac->ac_lg;
+ 	BUG_ON(lg == NULL);
+ 
+@@ -5043,6 +5077,8 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
+ 	int err;
+ 	int free = 0;
+ 
++	if (!grp)
++		return 0;
+ 	mb_debug(sb, "discard preallocation for group %u\n", group);
+ 	if (list_empty(&grp->bb_prealloc_list))
+ 		goto out_dbg;
+@@ -5297,6 +5333,9 @@ static inline void ext4_mb_show_pa(struct super_block *sb)
+ 		struct ext4_prealloc_space *pa;
+ 		ext4_grpblk_t start;
+ 		struct list_head *cur;
++
++		if (!grp)
++			continue;
+ 		ext4_lock_group(sb, i);
+ 		list_for_each(cur, &grp->bb_prealloc_list) {
+ 			pa = list_entry(cur, struct ext4_prealloc_space,
+@@ -6064,6 +6103,7 @@ static void ext4_mb_clear_bb(handle_t *handle, struct inode *inode,
+ 	struct buffer_head *bitmap_bh = NULL;
+ 	struct super_block *sb = inode->i_sb;
+ 	struct ext4_group_desc *gdp;
++	struct ext4_group_info *grp;
+ 	unsigned int overflow;
+ 	ext4_grpblk_t bit;
+ 	struct buffer_head *gd_bh;
+@@ -6089,8 +6129,8 @@ static void ext4_mb_clear_bb(handle_t *handle, struct inode *inode,
+ 	overflow = 0;
+ 	ext4_get_group_no_and_offset(sb, block, &block_group, &bit);
+ 
+-	if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(
+-			ext4_get_group_info(sb, block_group))))
++	grp = ext4_get_group_info(sb, block_group);
++	if (unlikely(!grp || EXT4_MB_GRP_BBITMAP_CORRUPT(grp)))
+ 		return;
+ 
+ 	/*
+@@ -6692,6 +6732,8 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
+ 
+ 	for (group = first_group; group <= last_group; group++) {
+ 		grp = ext4_get_group_info(sb, group);
++		if (!grp)
++			continue;
+ 		/* We only do this if the grp has never been initialized */
+ 		if (unlikely(EXT4_MB_GRP_NEED_INIT(grp))) {
+ 			ret = ext4_mb_init_group(sb, group, GFP_NOFS);
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index d39f386e9baf..4037c8611c02 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1048,6 +1048,8 @@ void ext4_mark_group_bitmap_corrupted(struct super_block *sb,
+ 	struct ext4_group_desc *gdp = ext4_get_group_desc(sb, group, NULL);
+ 	int ret;
+ 
++	if (!grp || !gdp)
++		return;
+ 	if (flags & EXT4_GROUP_INFO_BBITMAP_CORRUPT) {
+ 		ret = ext4_test_and_set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT,
+ 					    &grp->bb_state);

commit d4fab7b28e2f5d74790d47a8d298da0abfb5132f
+Author: Theodore Ts'o 
+Date:   Thu Apr 27 23:01:41 2023 -0400
+
+    ext4: clean up error handling in __ext4_fill_super()
+    
+    There were two ways to return an error code; one was via setting the
+    'err' variable, and the second, if err was zero, was via the 'ret'
+    variable.  This was both confusing and fragile, and when code was
+    factored out of __ext4_fill_super(), some of the error codes returned
+    by the original code was replaced by -EINVAL, and in one case, the
+    error code was placed by 0, triggering a kernel null pointer
+    dereference.
+    
+    Clean this up by removing the 'ret' variable, leaving only one way to
+    set the error code to be returned, and restore the errno codes that
+    were returned via the the mount system call as they were before we
+    started refactoring __ext4_fill_super().
+    
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Jason Yan 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index c8ae6b7e8615..39f00f05f981 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -5196,9 +5196,8 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	ext4_fsblk_t logical_sb_block;
+ 	struct inode *root;
+-	int ret = -ENOMEM;
+ 	int needs_recovery;
+-	int err = 0;
++	int err;
+ 	ext4_group_t first_not_zeroed;
+ 	struct ext4_fs_context *ctx = fc->fs_private;
+ 	int silent = fc->sb_flags & SB_SILENT;
+@@ -5211,8 +5210,6 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
+ 	sbi->s_sectors_written_start =
+ 		part_stat_read(sb->s_bdev, sectors[STAT_WRITE]);
+ 
+-	/* -EINVAL is default */
+-	ret = -EINVAL;
+ 	err = ext4_load_super(sb, &logical_sb_block, silent);
+ 	if (err)
+ 		goto out_fail;
+@@ -5238,7 +5235,8 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
+ 	 */
+ 	sbi->s_li_wait_mult = EXT4_DEF_LI_WAIT_MULT;
+ 
+-	if (ext4_inode_info_init(sb, es))
++	err = ext4_inode_info_init(sb, es);
++	if (err)
+ 		goto failed_mount;
+ 
+ 	err = parse_apply_sb_mount_options(sb, ctx);
+@@ -5254,10 +5252,12 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
+ 
+ 	ext4_apply_options(fc, sb);
+ 
+-	if (ext4_encoding_init(sb, es))
++	err = ext4_encoding_init(sb, es);
++	if (err)
+ 		goto failed_mount;
+ 
+-	if (ext4_check_journal_data_mode(sb))
++	err = ext4_check_journal_data_mode(sb);
++	if (err)
+ 		goto failed_mount;
+ 
+ 	sb->s_flags = (sb->s_flags & ~SB_POSIXACL) |
+@@ -5266,18 +5266,22 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
+ 	/* i_version is always enabled now */
+ 	sb->s_flags |= SB_I_VERSION;
+ 
+-	if (ext4_check_feature_compatibility(sb, es, silent))
++	err = ext4_check_feature_compatibility(sb, es, silent);
++	if (err)
+ 		goto failed_mount;
+ 
+-	if (ext4_block_group_meta_init(sb, silent))
++	err = ext4_block_group_meta_init(sb, silent);
++	if (err)
+ 		goto failed_mount;
+ 
+ 	ext4_hash_info_init(sb);
+ 
+-	if (ext4_handle_clustersize(sb))
++	err = ext4_handle_clustersize(sb);
++	if (err)
+ 		goto failed_mount;
+ 
+-	if (ext4_check_geometry(sb, es))
++	err = ext4_check_geometry(sb, es);
++	if (err)
+ 		goto failed_mount;
+ 
+ 	timer_setup(&sbi->s_err_report, print_daily_error_info, 0);
+@@ -5288,8 +5292,8 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
+ 	if (err)
+ 		goto failed_mount3;
+ 
+-	/* Register extent status tree shrinker */
+-	if (ext4_es_register_shrinker(sbi))
++	err = ext4_es_register_shrinker(sbi);
++	if (err)
+ 		goto failed_mount3;
+ 
+ 	sbi->s_stripe = ext4_get_stripe_size(sbi);
+@@ -5334,6 +5338,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
+ 			goto failed_mount3a;
+ 	}
+ 
++	err = -EINVAL;
+ 	/*
+ 	 * The first inode we look at is the journal inode.  Don't try
+ 	 * root first: it may be modified in the journal!
+@@ -5385,6 +5390,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
+ 		if (!sbi->s_ea_block_cache) {
+ 			ext4_msg(sb, KERN_ERR,
+ 				 "Failed to create ea_block_cache");
++			err = -EINVAL;
+ 			goto failed_mount_wq;
+ 		}
+ 
+@@ -5393,6 +5399,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
+ 			if (!sbi->s_ea_inode_cache) {
+ 				ext4_msg(sb, KERN_ERR,
+ 					 "Failed to create ea_inode_cache");
++				err = -EINVAL;
+ 				goto failed_mount_wq;
+ 			}
+ 		}
+@@ -5427,7 +5434,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
+ 		alloc_workqueue("ext4-rsv-conversion", WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
+ 	if (!EXT4_SB(sb)->rsv_conversion_wq) {
+ 		printk(KERN_ERR "EXT4-fs: failed to create workqueue\n");
+-		ret = -ENOMEM;
++		err = -ENOMEM;
+ 		goto failed_mount4;
+ 	}
+ 
+@@ -5439,28 +5446,28 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
+ 	root = ext4_iget(sb, EXT4_ROOT_INO, EXT4_IGET_SPECIAL);
+ 	if (IS_ERR(root)) {
+ 		ext4_msg(sb, KERN_ERR, "get root inode failed");
+-		ret = PTR_ERR(root);
++		err = PTR_ERR(root);
+ 		root = NULL;
+ 		goto failed_mount4;
+ 	}
+ 	if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
+ 		ext4_msg(sb, KERN_ERR, "corrupt root inode, run e2fsck");
+ 		iput(root);
++		err = -EFSCORRUPTED;
+ 		goto failed_mount4;
+ 	}
+ 
+ 	sb->s_root = d_make_root(root);
+ 	if (!sb->s_root) {
+ 		ext4_msg(sb, KERN_ERR, "get root dentry failed");
+-		ret = -ENOMEM;
++		err = -ENOMEM;
+ 		goto failed_mount4;
+ 	}
+ 
+-	ret = ext4_setup_super(sb, es, sb_rdonly(sb));
+-	if (ret == -EROFS) {
++	err = ext4_setup_super(sb, es, sb_rdonly(sb));
++	if (err == -EROFS) {
+ 		sb->s_flags |= SB_RDONLY;
+-		ret = 0;
+-	} else if (ret)
++	} else if (err)
+ 		goto failed_mount4a;
+ 
+ 	ext4_set_resv_clusters(sb);
+@@ -5513,7 +5520,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
+ 			ext4_msg(sb, KERN_ERR,
+ 			       "unable to initialize "
+ 			       "flex_bg meta info!");
+-			ret = -ENOMEM;
++			err = -ENOMEM;
+ 			goto failed_mount6;
+ 		}
+ 
+@@ -5639,7 +5646,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
+ 	ext4_blkdev_remove(sbi);
+ out_fail:
+ 	sb->s_fs_info = NULL;
+-	return err ? err : ret;
++	return err;
+ }
+ 
+ static int ext4_fill_super(struct super_block *sb, struct fs_context *fc)

commit 3b50d5018ed06a647bb26c44bb5ae74e59c903c7
+Author: Theodore Ts'o 
+Date:   Thu Apr 27 22:49:34 2023 -0400
+
+    ext4: reflect error codes from ext4_multi_mount_protect() to its callers
+    
+    This will allow more fine-grained errno codes to be returned by the
+    mount system call.
+    
+    Cc: Andreas Dilger 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c
+index 4681fff6665f..4022bc713421 100644
+--- a/fs/ext4/mmp.c
++++ b/fs/ext4/mmp.c
+@@ -282,6 +282,7 @@ int ext4_multi_mount_protect(struct super_block *sb,
+ 	if (mmp_block < le32_to_cpu(es->s_first_data_block) ||
+ 	    mmp_block >= ext4_blocks_count(es)) {
+ 		ext4_warning(sb, "Invalid MMP block in superblock");
++		retval = -EINVAL;
+ 		goto failed;
+ 	}
+ 
+@@ -307,6 +308,7 @@ int ext4_multi_mount_protect(struct super_block *sb,
+ 
+ 	if (seq == EXT4_MMP_SEQ_FSCK) {
+ 		dump_mmp_msg(sb, mmp, "fsck is running on the filesystem");
++		retval = -EBUSY;
+ 		goto failed;
+ 	}
+ 
+@@ -320,6 +322,7 @@ int ext4_multi_mount_protect(struct super_block *sb,
+ 
+ 	if (schedule_timeout_interruptible(HZ * wait_time) != 0) {
+ 		ext4_warning(sb, "MMP startup interrupted, failing mount\n");
++		retval = -ETIMEDOUT;
+ 		goto failed;
+ 	}
+ 
+@@ -330,6 +333,7 @@ int ext4_multi_mount_protect(struct super_block *sb,
+ 	if (seq != le32_to_cpu(mmp->mmp_seq)) {
+ 		dump_mmp_msg(sb, mmp,
+ 			     "Device is already active on another node.");
++		retval = -EBUSY;
+ 		goto failed;
+ 	}
+ 
+@@ -349,6 +353,7 @@ int ext4_multi_mount_protect(struct super_block *sb,
+ 	 */
+ 	if (schedule_timeout_interruptible(HZ * wait_time) != 0) {
+ 		ext4_warning(sb, "MMP startup interrupted, failing mount");
++		retval = -ETIMEDOUT;
+ 		goto failed;
+ 	}
+ 
+@@ -359,6 +364,7 @@ int ext4_multi_mount_protect(struct super_block *sb,
+ 	if (seq != le32_to_cpu(mmp->mmp_seq)) {
+ 		dump_mmp_msg(sb, mmp,
+ 			     "Device is already active on another node.");
++		retval = -EBUSY;
+ 		goto failed;
+ 	}
+ 
+@@ -378,6 +384,7 @@ int ext4_multi_mount_protect(struct super_block *sb,
+ 		EXT4_SB(sb)->s_mmp_tsk = NULL;
+ 		ext4_warning(sb, "Unable to create kmmpd thread for %s.",
+ 			     sb->s_id);
++		retval = -ENOMEM;
+ 		goto failed;
+ 	}
+ 
+@@ -385,5 +392,5 @@ int ext4_multi_mount_protect(struct super_block *sb,
+ 
+ failed:
+ 	brelse(bh);
+-	return 1;
++	return retval;
+ }
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 8ed6450effaa..c8ae6b7e8615 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -5328,9 +5328,11 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
+ 			  ext4_has_feature_orphan_present(sb) ||
+ 			  ext4_has_feature_journal_needs_recovery(sb));
+ 
+-	if (ext4_has_feature_mmp(sb) && !sb_rdonly(sb))
+-		if (ext4_multi_mount_protect(sb, le64_to_cpu(es->s_mmp_block)))
++	if (ext4_has_feature_mmp(sb) && !sb_rdonly(sb)) {
++		err = ext4_multi_mount_protect(sb, le64_to_cpu(es->s_mmp_block));
++		if (err)
+ 			goto failed_mount3a;
++	}
+ 
+ 	/*
+ 	 * The first inode we look at is the journal inode.  Don't try
+@@ -6565,12 +6567,12 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb)
+ 				goto restore_opts;
+ 
+ 			sb->s_flags &= ~SB_RDONLY;
+-			if (ext4_has_feature_mmp(sb))
+-				if (ext4_multi_mount_protect(sb,
+-						le64_to_cpu(es->s_mmp_block))) {
+-					err = -EROFS;
++			if (ext4_has_feature_mmp(sb)) {
++				err = ext4_multi_mount_protect(sb,
++						le64_to_cpu(es->s_mmp_block));
++				if (err)
+ 					goto restore_opts;
+-				}
++			}
+ #ifdef CONFIG_QUOTA
+ 			enable_quota = 1;
+ #endif

commit d5e72c4e3256335d6fb75c2e321144f93141f4f5
+Author: Theodore Ts'o 
+Date:   Thu Apr 27 19:18:01 2023 -0400
+
+    ext4: fix lost error code reporting in __ext4_fill_super()
+    
+    When code was factored out of __ext4_fill_super() into
+    ext4_percpu_param_init() the error return was discarded.  This meant
+    that it was possible for __ext4_fill_super() to return zero,
+    indicating success, without the struct super getting completely filled
+    in, leading to a potential NULL pointer dereference.
+    
+    Reported-by: syzbot+bbf0f9a213c94f283a5c@syzkaller.appspotmail.com
+    Fixes: 1f79467c8a6b ("ext4: factor out ext4_percpu_param_init() ...")
+    Link: https://syzkaller.appspot.com/bug?id=6dac47d5e58af770c0055f680369586ec32e144c
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Jason Yan 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index f16492b8c98d..8ed6450effaa 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -5502,7 +5502,8 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
+ 		sbi->s_journal->j_commit_callback =
+ 			ext4_journal_commit_callback;
+ 
+-	if (ext4_percpu_param_init(sbi))
++	err = ext4_percpu_param_init(sbi);
++	if (err)
+ 		goto failed_mount6;
+ 
+ 	if (ext4_has_feature_flex_bg(sb))

commit 19b8b035a776939ceb3de0f45aded4751d7849ef
+Author: Theodore Ts'o 
+Date:   Thu Mar 16 17:07:32 2023 -0400
+
+    ext4: convert some BUG_ON's in mballoc to use WARN_RATELIMITED instead
+    
+    In cases where we have an obvious way of continuing, let's use
+    WARN_RATELIMITED() instead of BUG_ON().
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 05a1f19c925b..90b061edb57d 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -1487,7 +1487,13 @@ ext4_mb_load_buddy_gfp(struct super_block *sb, ext4_group_t group,
+ 			put_page(page);
+ 		page = find_or_create_page(inode->i_mapping, pnum, gfp);
+ 		if (page) {
+-			BUG_ON(page->mapping != inode->i_mapping);
++			if (WARN_RATELIMIT(page->mapping != inode->i_mapping,
++	"ext4: bitmap's paging->mapping != inode->i_mapping\n")) {
++				/* should never happen */
++				unlock_page(page);
++				ret = -EINVAL;
++				goto err;
++			}
+ 			if (!PageUptodate(page)) {
+ 				ret = ext4_mb_init_cache(page, NULL, gfp);
+ 				if (ret) {
+@@ -1523,7 +1529,13 @@ ext4_mb_load_buddy_gfp(struct super_block *sb, ext4_group_t group,
+ 			put_page(page);
+ 		page = find_or_create_page(inode->i_mapping, pnum, gfp);
+ 		if (page) {
+-			BUG_ON(page->mapping != inode->i_mapping);
++			if (WARN_RATELIMIT(page->mapping != inode->i_mapping,
++	"ext4: buddy bitmap's page->mapping != inode->i_mapping\n")) {
++				/* should never happen */
++				unlock_page(page);
++				ret = -EINVAL;
++				goto err;
++			}
+ 			if (!PageUptodate(page)) {
+ 				ret = ext4_mb_init_cache(page, e4b->bd_bitmap,
+ 							 gfp);
+@@ -2221,7 +2233,9 @@ void ext4_mb_simple_scan_group(struct ext4_allocation_context *ac,
+ 			continue;
+ 
+ 		buddy = mb_find_buddy(e4b, i, &max);
+-		BUG_ON(buddy == NULL);
++		if (WARN_RATELIMIT(buddy == NULL,
++			 "ext4: mb_simple_scan_group: mb_find_buddy failed, (%d)\n", i))
++			continue;
+ 
+ 		k = mb_find_next_zero_bit(buddy, max, 0);
+ 		if (k >= max) {
+@@ -4229,15 +4243,14 @@ static void ext4_discard_allocated_blocks(struct ext4_allocation_context *ac)
+ 		if (ac->ac_f_ex.fe_len == 0)
+ 			return;
+ 		err = ext4_mb_load_buddy(ac->ac_sb, ac->ac_f_ex.fe_group, &e4b);
+-		if (err) {
++		if (WARN_RATELIMIT(err,
++				   "ext4: mb_load_buddy failed (%d)", err))
+ 			/*
+ 			 * This should never happen since we pin the
+ 			 * pages in the ext4_allocation_context so
+ 			 * ext4_mb_load_buddy() should never fail.
+ 			 */
+-			WARN(1, "mb_load_buddy failed (%d)", err);
+ 			return;
+-		}
+ 		ext4_lock_group(ac->ac_sb, ac->ac_f_ex.fe_group);
+ 		mb_free_blocks(ac->ac_inode, &e4b, ac->ac_f_ex.fe_start,
+ 			       ac->ac_f_ex.fe_len);

commit 98ccceee3e0637a37e20c1c12a08173663db77e7
+Author: Theodore Ts'o 
+Date:   Wed Mar 15 14:34:18 2023 -0400
+
+    ext4: fix comment: "start start" -> "start" in mpage_prepare_extent_to_map()
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 6445b8017a8e..dbcc8b48c7ba 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2432,7 +2432,7 @@ static int mpage_prepare_extent_to_map(struct mpage_da_data *mpd)
+ 	mpd->next_page = index;
+ 	/*
+ 	 * Start a transaction for writeback of journalled data. We don't start
+-	 * start the transaction if the filesystem is frozen. In that case we
++	 * the transaction if the filesystem is frozen. In that case we
+ 	 * should not have any dirty data to write anymore but possibly there
+ 	 * are stray page dirty bits left by the checkpointing code so this
+ 	 * loop clears them.

commit 70e42feab2e20618ddd0cbfc4ab4b08628236ecd
+Author: Theodore Ts'o 
+Date:   Fri Mar 17 21:53:52 2023 -0400
+
+    ext4: fix possible double unlock when moving a directory
+    
+    Fixes: 0813299c586b ("ext4: Fix possible corruption when moving a directory")
+    Link: https://lore.kernel.org/r/5efbe1b9-ad8b-4a4f-b422-24824d2b775c@kili.mountain
+    Reported-by: Dan Carpenter 
+    Reported-by: syzbot+0c73d1d8b952c5f3d714@syzkaller.appspotmail.com
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 31e21de56432..a5010b5b8a8c 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -3884,10 +3884,8 @@ static int ext4_rename(struct mnt_idmap *idmap, struct inode *old_dir,
+ 				goto end_rename;
+ 		}
+ 		retval = ext4_rename_dir_prepare(handle, &old);
+-		if (retval) {
+-			inode_unlock(old.inode);
++		if (retval)
+ 			goto end_rename;
+-		}
+ 	}
+ 	/*
+ 	 * If we're renaming a file within an inline_data dir and adding or

commit 10a29eb658b3039eccfa6f249da079194f535a9a
+Author: Theodore Ts'o 
+Date:   Wed Mar 8 14:04:03 2023 -0500
+
+    Documentation/process: Add Linux Kernel Contribution Maturity Model
+    
+    As a follow-up to a discussion at the 2021 Maintainer's Summit on the
+    topic of maintainer recruitment and retention, the TAB took on the
+    task of creating a document which to help companies and other
+    organizations to grow in their ability to engage with the Linux Kernel
+    development community, using the Maturity Model[2] framework.
+    
+    The goal is to encourage, in a management-friendly way, companies to
+    allow their engineers to contribute with the upstream Linux Kernel
+    development community, so we can grow the "talent pipeline" for
+    contributors to become respected leaders, and eventually kernel
+    maintainers.
+    
+    [1] https://lwn.net/Articles/870581/
+    [2] https://en.wikipedia.org/wiki/Maturity_model
+    
+    Signed-off-by: Theodore Ts'o 
+    Co-developed-by: Kees Cook 
+    Signed-off-by: Kees Cook 
+    Co-developed-by: Dan Williams 
+    Signed-off-by: Dan Williams 
+    Acked-by: Jakub Kicinski 
+    Acked-by: Christian Brauner (Microsoft) 
+    Acked-by: Dave Hansen 
+    Acked-by: Jonathan Corbet 
+    Acked-by: Randy Dunlap 
+    Link: https://lore.kernel.org/r/20230308190403.2157046-1-tytso@mit.edu
+    Signed-off-by: Jonathan Corbet 
+
+diff --git a/Documentation/process/contribution-maturity-model.rst b/Documentation/process/contribution-maturity-model.rst
+new file mode 100644
+index 000000000000..b87ab34de22c
+--- /dev/null
++++ b/Documentation/process/contribution-maturity-model.rst
+@@ -0,0 +1,109 @@
++.. SPDX-License-Identifier: GPL-2.0
++
++========================================
++Linux Kernel Contribution Maturity Model
++========================================
++
++
++Background
++==========
++
++As a part of the 2021 Linux Kernel Maintainers’ Summit, there was a
++`discussion `_ about the challenges in
++recruiting kernel maintainers as well as maintainer succession.  Some of
++the conclusions from that discussion included that companies which are a
++part of the Linux Kernel community need to allow engineers to be
++maintainers as part of their job, so they can grow into becoming
++respected leaders and eventually, kernel maintainers.  To support a
++strong talent pipeline, developers should be allowed and encouraged to
++take on upstream contributions such as reviewing other people’s patches,
++refactoring kernel infrastructure, and writing documentation.
++
++To that end, the Linux Foundation Technical Advisory Board (TAB)
++proposes this Linux Kernel Contribution Maturity Model. These common
++expectations for upstream community engagement aim to increase the
++influence of individual developers, increase the collaboration of
++organizations, and improve the overall health of the Linux Kernel
++ecosystem.
++
++The TAB urges organizations to continuously evaluate their Open Source
++maturity model and commit to improvements to align with this model.  To
++be effective, this evaluation should incorporate feedback from across
++the organization, including management and developers at all seniority
++levels.  In the spirit of Open Source, we encourage organizations to
++publish their evaluations and plans to improve their engagement with the
++upstream community.
++
++Level 0
++=======
++
++* Software Engineers are not allowed to contribute patches to the Linux
++  kernel.
++
++
++Level 1
++=======
++
++* Software Engineers are allowed to contribute patches to the Linux
++  kernel, either as part of their job responsibilities or on their own
++  time.
++
++Level 2
++=======
++
++* Software Engineers are expected to contribute to the Linux Kernel as
++  part of their job responsibilities.
++* Software Engineers will be supported to attend Linux-related
++  conferences as a part of their job.
++* A Software Engineer’s upstream code contributions will be considered
++  in promotion and performance reviews.
++
++Level 3
++=======
++
++* Software Engineers are expected to review patches (including patches
++  authored by engineers from other companies) as part of their job
++  responsibilities
++* Contributing presentations or papers to Linux-related or academic
++  conferences (such those organized by the Linux Foundation, Usenix,
++  ACM, etc.), are considered part of an engineer’s work.
++* A Software Engineer’s community contributions will be considered in
++  promotion and performance reviews.
++* Organizations will regularly report metrics of their open source
++  contributions and track these metrics over time.  These metrics may be
++  published only internally within the organization, or at the
++  organization’s discretion, some or all may be published externally.
++  Metrics that are strongly suggested include:
++
++  * The number of upstream kernel contributions by team or organization
++    (e.g., all people reporting up to a manager, director, or VP).
++  * The percentage of kernel developers who have made upstream
++    contributions relative to the total kernel developers in the
++    organization.
++  * The time interval between kernels used in the organization’s servers
++    and/or products, and the publication date of the upstream kernel
++    upon which the internal kernel is based.
++  * The number of out-of-tree commits present in internal kernels.
++
++Level 4
++=======
++
++* Software Engineers are encouraged to spend a portion of their work
++  time focused on Upstream Work, which is defined as reviewing patches,
++  serving on program committees, improving core project infrastructure
++  such as writing or maintaining tests, upstream tech debt reduction,
++  writing documentation, etc.
++* Software Engineers are supported in helping to organize Linux-related
++  conferences.
++* Organizations will consider community member feedback in official
++  performance reviews.
++
++Level 5
++=======
++
++* Upstream kernel development is considered a formal job position, with
++  at least a third of the engineer’s time spent doing Upstream Work.
++* Organizations will actively seek out community member feedback as a
++  factor in official performance reviews.
++* Organizations will regularly report internally on the ratio of
++  Upstream Work to work focused on directly pursuing business goals.
+diff --git a/Documentation/process/index.rst b/Documentation/process/index.rst
+index d4b6217472b0..33715da7e684 100644
+--- a/Documentation/process/index.rst
++++ b/Documentation/process/index.rst
+@@ -50,6 +50,7 @@ Other guides to the community that are of interest to most developers are:
+    embargoed-hardware-issues
+    maintainers
+    researcher-guidelines
++   contribution-maturity-model
+ 
+ These are some overall technical guides that have been put here for now for
+ lack of a better place.
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 8d5bc223f305..3ce66e199c97 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -21244,6 +21244,14 @@ S:	Maintained
+ F:	Documentation/tools/rtla/
+ F:	tools/tracing/rtla/
+ 
++TECHNICAL ADVISORY BOARD PROCESS DOCS
++M:	"Theodore Ts'o" 
++M:	Greg Kroah-Hartman 
++L:	tech-board-discuss@lists.linux-foundation.org
++S:	Maintained
++F:	Documentation/process/researcher-guidelines.rst
++F:	Documentation/process/contribution-maturity-model.rst
++
+ TRADITIONAL CHINESE DOCUMENTATION
+ M:	Hu Haowen 
+ L:	linux-doc-tw-discuss@lists.sourceforge.net (moderated for non-subscribers)

commit 62913ae96de747091c4dacd06d158e7729c1a76d
+Author: Theodore Ts'o 
+Date:   Tue Mar 7 23:15:49 2023 -0500
+
+    ext4, jbd2: add an optimized bmap for the journal inode
+    
+    The generic bmap() function exported by the VFS takes locks and does
+    checks that are not necessary for the journal inode.  So allow the
+    file system to set a journal-optimized bmap function in
+    journal->j_bmap.
+    
+    Reported-by: syzbot+9543479984ae9e576000@syzkaller.appspotmail.com
+    Link: https://syzkaller.appspot.com/bug?id=e4aaa78795e490421c79f76ec3679006c8ff4cf0
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 2192b4111442..46b7345d2b6a 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -5742,6 +5742,28 @@ static struct inode *ext4_get_journal_inode(struct super_block *sb,
+ 	return journal_inode;
+ }
+ 
++static int ext4_journal_bmap(journal_t *journal, sector_t *block)
++{
++	struct ext4_map_blocks map;
++	int ret;
++
++	if (journal->j_inode == NULL)
++		return 0;
++
++	map.m_lblk = *block;
++	map.m_len = 1;
++	ret = ext4_map_blocks(NULL, journal->j_inode, &map, 0);
++	if (ret <= 0) {
++		ext4_msg(journal->j_inode->i_sb, KERN_CRIT,
++			 "journal bmap failed: block %llu ret %d\n",
++			 *block, ret);
++		jbd2_journal_abort(journal, ret ? ret : -EIO);
++		return ret;
++	}
++	*block = map.m_pblk;
++	return 0;
++}
++
+ static journal_t *ext4_get_journal(struct super_block *sb,
+ 				   unsigned int journal_inum)
+ {
+@@ -5762,6 +5784,7 @@ static journal_t *ext4_get_journal(struct super_block *sb,
+ 		return NULL;
+ 	}
+ 	journal->j_private = sb;
++	journal->j_bmap = ext4_journal_bmap;
+ 	ext4_init_journal_params(sb, journal);
+ 	return journal;
+ }
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 2696f43e7239..c84f588fdcd0 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -970,10 +970,13 @@ int jbd2_journal_bmap(journal_t *journal, unsigned long blocknr,
+ {
+ 	int err = 0;
+ 	unsigned long long ret;
+-	sector_t block = 0;
++	sector_t block = blocknr;
+ 
+-	if (journal->j_inode) {
+-		block = blocknr;
++	if (journal->j_bmap) {
++		err = journal->j_bmap(journal, &block);
++		if (err == 0)
++			*retp = block;
++	} else if (journal->j_inode) {
+ 		ret = bmap(journal->j_inode, &block);
+ 
+ 		if (ret || !block) {
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index 2170e0cc279d..6ffa34c51a11 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -1308,6 +1308,14 @@ struct journal_s
+ 				    struct buffer_head *bh,
+ 				    enum passtype pass, int off,
+ 				    tid_t expected_commit_id);
++
++	/**
++	 * @j_bmap:
++	 *
++	 * Bmap function that should be used instead of the generic
++	 * VFS bmap function.
++	 */
++	int (*j_bmap)(struct journal_s *journal, sector_t *block);
+ };
+ 
+ #define jbd2_might_wait_for_commit(j) \

commit 609d54441493c99f21c1823dfd66fa7f4c512ff4
+Author: Theodore Ts'o 
+Date:   Mon Mar 6 13:54:50 2023 -0500
+
+    fs: prevent out-of-bounds array speculation when closing a file descriptor
+    
+    Google-Bug-Id: 114199369
+    Signed-off-by: Theodore Ts'o 
+    Signed-off-by: Al Viro 
+
+diff --git a/fs/file.c b/fs/file.c
+index c942c89ca4cd..7893ea161d77 100644
+--- a/fs/file.c
++++ b/fs/file.c
+@@ -642,6 +642,7 @@ static struct file *pick_file(struct files_struct *files, unsigned fd)
+ 	if (fd >= fdt->max_fds)
+ 		return NULL;
+ 
++	fd = array_index_nospec(fd, fdt->max_fds);
+ 	file = fdt->fd[fd];
+ 	if (file) {
+ 		rcu_assign_pointer(fdt->fd[fd], NULL);

commit 3478c83cf26bbffd026ae6a56bcb1fe544f0834e
+Author: Theodore Ts'o 
+Date:   Wed Dec 14 15:08:18 2022 -0500
+
+    ext4: improve xattr consistency checking and error reporting
+    
+    Refactor the in-inode and xattr block consistency checking, and report
+    more fine-grained reports of the consistency problems.  Also add more
+    consistency checks for ea_inode number.
+    
+    Reviewed-by: Andreas Dilger 
+    Signed-off-by: Theodore Ts'o 
+    Link: https://lore.kernel.org/r/20221214200818.870087-1-tytso@mit.edu
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 69a1b8c6a2ec..e51052a247cc 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -184,27 +184,73 @@ ext4_xattr_handler(int name_index)
+ }
+ 
+ static int
+-ext4_xattr_check_entries(struct ext4_xattr_entry *entry, void *end,
+-			 void *value_start)
++check_xattrs(struct inode *inode, struct buffer_head *bh,
++	     struct ext4_xattr_entry *entry, void *end, void *value_start,
++	     const char *function, unsigned int line)
+ {
+ 	struct ext4_xattr_entry *e = entry;
++	int err = -EFSCORRUPTED;
++	char *err_str;
++
++	if (bh) {
++		if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) ||
++		    BHDR(bh)->h_blocks != cpu_to_le32(1)) {
++			err_str = "invalid header";
++			goto errout;
++		}
++		if (buffer_verified(bh))
++			return 0;
++		if (!ext4_xattr_block_csum_verify(inode, bh)) {
++			err = -EFSBADCRC;
++			err_str = "invalid checksum";
++			goto errout;
++		}
++	} else {
++		struct ext4_xattr_ibody_header *header = value_start;
++
++		header -= 1;
++		if (end - (void *)header < sizeof(*header) + sizeof(u32)) {
++			err_str = "in-inode xattr block too small";
++			goto errout;
++		}
++		if (header->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC)) {
++			err_str = "bad magic number in in-inode xattr";
++			goto errout;
++		}
++	}
+ 
+ 	/* Find the end of the names list */
+ 	while (!IS_LAST_ENTRY(e)) {
+ 		struct ext4_xattr_entry *next = EXT4_XATTR_NEXT(e);
+-		if ((void *)next >= end)
+-			return -EFSCORRUPTED;
+-		if (strnlen(e->e_name, e->e_name_len) != e->e_name_len)
+-			return -EFSCORRUPTED;
++		if ((void *)next >= end) {
++			err_str = "e_name out of bounds";
++			goto errout;
++		}
++		if (strnlen(e->e_name, e->e_name_len) != e->e_name_len) {
++			err_str = "bad e_name length";
++			goto errout;
++		}
+ 		e = next;
+ 	}
+ 
+ 	/* Check the values */
+ 	while (!IS_LAST_ENTRY(entry)) {
+ 		u32 size = le32_to_cpu(entry->e_value_size);
++		unsigned long ea_ino = le32_to_cpu(entry->e_value_inum);
+ 
+-		if (size > EXT4_XATTR_SIZE_MAX)
+-			return -EFSCORRUPTED;
++		if (!ext4_has_feature_ea_inode(inode->i_sb) && ea_ino) {
++			err_str = "ea_inode specified without ea_inode feature enabled";
++			goto errout;
++		}
++		if (ea_ino && ((ea_ino == EXT4_ROOT_INO) ||
++			       !ext4_valid_inum(inode->i_sb, ea_ino))) {
++			err_str = "invalid ea_ino";
++			goto errout;
++		}
++		if (size > EXT4_XATTR_SIZE_MAX) {
++			err_str = "e_value size too large";
++			goto errout;
++		}
+ 
+ 		if (size != 0 && entry->e_value_inum == 0) {
+ 			u16 offs = le16_to_cpu(entry->e_value_offs);
+@@ -216,66 +262,54 @@ ext4_xattr_check_entries(struct ext4_xattr_entry *entry, void *end,
+ 			 * the padded and unpadded sizes, since the size may
+ 			 * overflow to 0 when adding padding.
+ 			 */
+-			if (offs > end - value_start)
+-				return -EFSCORRUPTED;
++			if (offs > end - value_start) {
++				err_str = "e_value out of bounds";
++				goto errout;
++			}
+ 			value = value_start + offs;
+ 			if (value < (void *)e + sizeof(u32) ||
+ 			    size > end - value ||
+-			    EXT4_XATTR_SIZE(size) > end - value)
+-				return -EFSCORRUPTED;
++			    EXT4_XATTR_SIZE(size) > end - value) {
++				err_str = "overlapping e_value ";
++				goto errout;
++			}
+ 		}
+ 		entry = EXT4_XATTR_NEXT(entry);
+ 	}
+-
++	if (bh)
++		set_buffer_verified(bh);
+ 	return 0;
++
++errout:
++	if (bh)
++		__ext4_error_inode(inode, function, line, 0, -err,
++				   "corrupted xattr block %llu: %s",
++				   (unsigned long long) bh->b_blocknr,
++				   err_str);
++	else
++		__ext4_error_inode(inode, function, line, 0, -err,
++				   "corrupted in-inode xattr: %s", err_str);
++	return err;
+ }
+ 
+ static inline int
+ __ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh,
+ 			 const char *function, unsigned int line)
+ {
+-	int error = -EFSCORRUPTED;
+-
+-	if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) ||
+-	    BHDR(bh)->h_blocks != cpu_to_le32(1))
+-		goto errout;
+-	if (buffer_verified(bh))
+-		return 0;
+-
+-	error = -EFSBADCRC;
+-	if (!ext4_xattr_block_csum_verify(inode, bh))
+-		goto errout;
+-	error = ext4_xattr_check_entries(BFIRST(bh), bh->b_data + bh->b_size,
+-					 bh->b_data);
+-errout:
+-	if (error)
+-		__ext4_error_inode(inode, function, line, 0, -error,
+-				   "corrupted xattr block %llu",
+-				   (unsigned long long) bh->b_blocknr);
+-	else
+-		set_buffer_verified(bh);
+-	return error;
++	return check_xattrs(inode, bh, BFIRST(bh), bh->b_data + bh->b_size,
++			    bh->b_data, function, line);
+ }
+ 
+ #define ext4_xattr_check_block(inode, bh) \
+ 	__ext4_xattr_check_block((inode), (bh),  __func__, __LINE__)
+ 
+ 
+-static int
++static inline int
+ __xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header,
+ 			 void *end, const char *function, unsigned int line)
+ {
+-	int error = -EFSCORRUPTED;
+-
+-	if (end - (void *)header < sizeof(*header) + sizeof(u32) ||
+-	    (header->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC)))
+-		goto errout;
+-	error = ext4_xattr_check_entries(IFIRST(header), end, IFIRST(header));
+-errout:
+-	if (error)
+-		__ext4_error_inode(inode, function, line, 0, -error,
+-				   "corrupted in-inode xattr");
+-	return error;
++	return check_xattrs(inode, NULL, IFIRST(header), end, IFIRST(header),
++			    function, line);
+ }
+ 
+ #define xattr_check_inode(inode, header, end) \

commit 0d043351e5baf3857f915367deba2a518b6a0809
+Author: Theodore Ts'o 
+Date:   Sat Nov 5 23:42:36 2022 -0400
+
+    ext4: fix fortify warning in fs/ext4/fast_commit.c:1551
+    
+    With the new fortify string system, rework the memcpy to avoid this
+    warning:
+    
+    memcpy: detected field-spanning write (size 60) of single field "&raw_inode->i_generation" at fs/ext4/fast_commit.c:1551 (size 4)
+    
+    Cc: stable@kernel.org
+    Fixes: 54d9469bc515 ("fortify: Add run-time WARN for cross-field memcpy()")
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/fast_commit.c b/fs/ext4/fast_commit.c
+index ef05bfa87798..0f6d0a80467d 100644
+--- a/fs/ext4/fast_commit.c
++++ b/fs/ext4/fast_commit.c
+@@ -1521,6 +1521,7 @@ static int ext4_fc_replay_inode(struct super_block *sb, struct ext4_fc_tl *tl,
+ 	struct ext4_iloc iloc;
+ 	int inode_len, ino, ret, tag = tl->fc_tag;
+ 	struct ext4_extent_header *eh;
++	size_t off_gen = offsetof(struct ext4_inode, i_generation);
+ 
+ 	memcpy(&fc_inode, val, sizeof(fc_inode));
+ 
+@@ -1548,8 +1549,8 @@ static int ext4_fc_replay_inode(struct super_block *sb, struct ext4_fc_tl *tl,
+ 	raw_inode = ext4_raw_inode(&iloc);
+ 
+ 	memcpy(raw_inode, raw_fc_inode, offsetof(struct ext4_inode, i_block));
+-	memcpy(&raw_inode->i_generation, &raw_fc_inode->i_generation,
+-		inode_len - offsetof(struct ext4_inode, i_generation));
++	memcpy((u8 *)raw_inode + off_gen, (u8 *)raw_fc_inode + off_gen,
++	       inode_len - off_gen);
+ 	if (le32_to_cpu(raw_inode->i_flags) & EXT4_EXTENTS_FL) {
+ 		eh = (struct ext4_extent_header *)(&raw_inode->i_block[0]);
+ 		if (eh->eh_magic != EXT4_EXT_MAGIC) {

commit 9a8c5b0d061554fedd7dbe894e63aa34d0bac7c4
+Author: Theodore Ts'o 
+Date:   Thu Oct 27 16:04:36 2022 -0400
+
+    ext4: update the backup superblock's at the end of the online resize
+    
+    When expanding a file system using online resize, various fields in
+    the superblock (e.g., s_blocks_count, s_inodes_count, etc.) change.
+    To update the backup superblocks, the online resize uses the function
+    update_backups() in fs/ext4/resize.c.  This function was not updating
+    the checksum field in the backup superblocks.  This wasn't a big deal
+    previously, because e2fsck didn't care about the checksum field in the
+    backup superblock.  (And indeed, update_backups() goes all the way
+    back to the ext3 days, well before we had support for metadata
+    checksums.)
+    
+    However, there is an alternate, more general way of updating
+    superblock fields, ext4_update_primary_sb() in fs/ext4/ioctl.c.  This
+    function does check the checksum of the backup superblock, and if it
+    doesn't match will mark the file system as corrupted.  That was
+    clearly not the intent, so avoid to aborting the resize when a bad
+    superblock is found.
+    
+    In addition, teach update_backups() to properly update the checksum in
+    the backup superblocks.  We will eventually want to unify
+    updapte_backups() with the infrasture in ext4_update_primary_sb(), but
+    that's for another day.
+    
+    Note: The problem has been around for a while; it just didn't really
+    matter until ext4_update_primary_sb() was added by commit bbc605cdb1e1
+    ("ext4: implement support for get/set fs label").  And it became
+    trivially easy to reproduce after commit 827891a38acc ("ext4: update
+    the s_overhead_clusters in the backup sb's when resizing") in v6.0.
+    
+    Cc: stable@kernel.org # 5.17+
+    Fixes: bbc605cdb1e1 ("ext4: implement support for get/set fs label")
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index 4d49c5cfb690..790d5ffe8559 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -145,9 +145,8 @@ static int ext4_update_backup_sb(struct super_block *sb,
+ 	if (ext4_has_metadata_csum(sb) &&
+ 	    es->s_checksum != ext4_superblock_csum(sb, es)) {
+ 		ext4_msg(sb, KERN_ERR, "Invalid checksum for backup "
+-		"superblock %llu\n", sb_block);
++		"superblock %llu", sb_block);
+ 		unlock_buffer(bh);
+-		err = -EFSBADCRC;
+ 		goto out_bh;
+ 	}
+ 	func(es, arg);
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 6dfe9ccae0c5..46b87ffeb304 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -1158,6 +1158,7 @@ static void update_backups(struct super_block *sb, sector_t blk_off, char *data,
+ 	while (group < sbi->s_groups_count) {
+ 		struct buffer_head *bh;
+ 		ext4_fsblk_t backup_block;
++		struct ext4_super_block *es;
+ 
+ 		/* Out of journal space, and can't get more - abort - so sad */
+ 		err = ext4_resize_ensure_credits_batch(handle, 1);
+@@ -1186,6 +1187,10 @@ static void update_backups(struct super_block *sb, sector_t blk_off, char *data,
+ 		memcpy(bh->b_data, data, size);
+ 		if (rest)
+ 			memset(bh->b_data + size, 0, rest);
++		es = (struct ext4_super_block *) bh->b_data;
++		es->s_block_group_nr = cpu_to_le16(group);
++		if (ext4_has_metadata_csum(sb))
++			es->s_checksum = ext4_superblock_csum(sb, es);
+ 		set_buffer_uptodate(bh);
+ 		unlock_buffer(bh);
+ 		err = ext4_handle_dirty_metadata(handle, NULL, bh);

commit 80fa46d6b9e7b1527bfd2197d75431fd9c382161
+Author: Theodore Ts'o 
+Date:   Thu Sep 1 18:03:14 2022 -0400
+
+    ext4: limit the number of retries after discarding preallocations blocks
+    
+    This patch avoids threads live-locking for hours when a large number
+    threads are competing over the last few free extents as they blocks
+    getting added and removed from preallocation pools.  From our bug
+    reporter:
+    
+       A reliable way for triggering this has multiple writers
+       continuously write() to files when the filesystem is full, while
+       small amounts of space are freed (e.g. by truncating a large file
+       -1MiB at a time). In the local filesystem, this can be done by
+       simply not checking the return code of write (0) and/or the error
+       (ENOSPACE) that is set. Over NFS with an async mount, even clients
+       with proper error checking will behave this way since the linux NFS
+       client implementation will not propagate the server errors [the
+       write syscalls immediately return success] until the file handle is
+       closed. This leads to a situation where NFS clients send a
+       continuous stream of WRITE rpcs which result in ERRNOSPACE -- but
+       since the client isn't seeing this, the stream of writes continues
+       at maximum network speed.
+    
+       When some space does appear, multiple writers will all attempt to
+       claim it for their current write. For NFS, we may see dozens to
+       hundreds of threads that do this.
+    
+       The real-world scenario of this is database backup tooling (in
+       particular, github.com/mdkent/percona-xtrabackup) which may write
+       large files (>1TiB) to NFS for safe keeping. Some temporary files
+       are written, rewound, and read back -- all before closing the file
+       handle (the temp file is actually unlinked, to trigger automatic
+       deletion on close/crash.) An application like this operating on an
+       async NFS mount will not see an error code until TiB have been
+       written/read.
+    
+       The lockup was observed when running this database backup on large
+       filesystems (64 TiB in this case) with a high number of block
+       groups and no free space. Fragmentation is generally not a factor
+       in this filesystem (~thousands of large files, mostly contiguous
+       except for the parts written while the filesystem is at capacity.)
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 31873af0421b..71f5b67d7f28 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -5533,6 +5533,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
+ 	ext4_fsblk_t block = 0;
+ 	unsigned int inquota = 0;
+ 	unsigned int reserv_clstrs = 0;
++	int retries = 0;
+ 	u64 seq;
+ 
+ 	might_sleep();
+@@ -5635,7 +5636,8 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
+ 			ar->len = ac->ac_b_ex.fe_len;
+ 		}
+ 	} else {
+-		if (ext4_mb_discard_preallocations_should_retry(sb, ac, &seq))
++		if (++retries < 3 &&
++		    ext4_mb_discard_preallocations_should_retry(sb, ac, &seq))
+ 			goto repeat;
+ 		/*
+ 		 * If block allocation fails then the pa allocated above

commit 827891a38accfb4e04dbcdefe710f8746c6ad16d
+Author: Theodore Ts'o 
+Date:   Wed Jun 29 00:00:26 2022 -0400
+
+    ext4: update the s_overhead_clusters in the backup sb's when resizing
+    
+    When the EXT4_IOC_RESIZE_FS ioctl is complete, update the backup
+    superblocks.  We don't do this for the old-style resize ioctls since
+    they are quite ancient, and only used by very old versions of
+    resize2fs --- and we don't want to update the backup superblocks every
+    time EXT4_IOC_GROUP_ADD is called, since it might get called a lot.
+    
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Andreas Dilger 
+    Link: https://lore.kernel.org/r/20220629040026.112371-2-tytso@mit.edu
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index adfc30ee4b7b..310e976ef1fd 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -3016,7 +3016,7 @@ int ext4_fileattr_set(struct user_namespace *mnt_userns,
+ 		      struct dentry *dentry, struct fileattr *fa);
+ int ext4_fileattr_get(struct dentry *dentry, struct fileattr *fa);
+ extern void ext4_reset_inode_seed(struct inode *inode);
+-int ext4_update_overhead(struct super_block *sb);
++int ext4_update_overhead(struct super_block *sb, bool force);
+ 
+ /* migrate.c */
+ extern int ext4_ext_migrate(struct inode *);
+@@ -3800,7 +3800,7 @@ static inline void set_bitmap_uptodate(struct buffer_head *bh)
+ extern wait_queue_head_t ext4__ioend_wq[EXT4_WQ_HASH_SZ];
+ 
+ extern int ext4_resize_begin(struct super_block *sb);
+-extern void ext4_resize_end(struct super_block *sb);
++extern int ext4_resize_end(struct super_block *sb, bool update_backups);
+ 
+ static inline void ext4_set_io_unwritten_flag(struct inode *inode,
+ 					      struct ext4_io_end *io_end)
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index cb01c1da0f9d..1702c574407a 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -944,7 +944,9 @@ static long ext4_ioctl_group_add(struct file *file,
+ 	    test_opt(sb, INIT_INODE_TABLE))
+ 		err = ext4_register_li_request(sb, input->group);
+ group_add_out:
+-	ext4_resize_end(sb);
++	err2 = ext4_resize_end(sb, false);
++	if (err == 0)
++		err = err2;
+ 	return err;
+ }
+ 
+@@ -1223,7 +1225,9 @@ static long __ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 			err = err2;
+ 		mnt_drop_write_file(filp);
+ group_extend_out:
+-		ext4_resize_end(sb);
++		err2 = ext4_resize_end(sb, false);
++		if (err == 0)
++			err = err2;
+ 		return err;
+ 	}
+ 
+@@ -1371,7 +1375,9 @@ static long __ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 			err = ext4_register_li_request(sb, o_group);
+ 
+ resizefs_out:
+-		ext4_resize_end(sb);
++		err2 = ext4_resize_end(sb, true);
++		if (err == 0)
++			err = err2;
+ 		return err;
+ 	}
+ 
+@@ -1599,13 +1605,15 @@ static void set_overhead(struct ext4_super_block *es, const void *arg)
+ 	es->s_overhead_clusters = cpu_to_le32(*((unsigned long *) arg));
+ }
+ 
+-int ext4_update_overhead(struct super_block *sb)
++int ext4_update_overhead(struct super_block *sb, bool force)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 
+-	if (sb_rdonly(sb) || sbi->s_overhead == 0 ||
+-	    sbi->s_overhead == le32_to_cpu(sbi->s_es->s_overhead_clusters))
++	if (sb_rdonly(sb))
++		return 0;
++	if (!force &&
++	    (sbi->s_overhead == 0 ||
++	     sbi->s_overhead == le32_to_cpu(sbi->s_es->s_overhead_clusters)))
+ 		return 0;
+-
+ 	return ext4_update_superblocks_fn(sb, set_overhead, &sbi->s_overhead);
+ }
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index e5c2713aa11a..e4e89ca82f8c 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -97,10 +97,13 @@ int ext4_resize_begin(struct super_block *sb)
+ 	return ret;
+ }
+ 
+-void ext4_resize_end(struct super_block *sb)
++int ext4_resize_end(struct super_block *sb, bool update_backups)
+ {
+ 	clear_bit_unlock(EXT4_FLAGS_RESIZING, &EXT4_SB(sb)->s_ext4_flags);
+ 	smp_mb__after_atomic();
++	if (update_backups)
++		return ext4_update_overhead(sb, true);
++	return 0;
+ }
+ 
+ static ext4_group_t ext4_meta_bg_first_group(struct super_block *sb,
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 845f2f8aee5f..6a8a752d812b 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -5523,7 +5523,7 @@ static int ext4_fill_super(struct super_block *sb, struct fs_context *fc)
+ 			 "Quota mode: %s.", descr, ext4_quota_mode(sb));
+ 
+ 	/* Update the s_overhead_clusters if necessary */
+-	ext4_update_overhead(sb);
++	ext4_update_overhead(sb, false);
+ 	return 0;
+ 
+ free_sbi:

commit de394a86658ffe4e89e5328fd4993abfe41b7435
+Author: Theodore Ts'o 
+Date:   Wed Jun 29 00:00:25 2022 -0400
+
+    ext4: update s_overhead_clusters in the superblock during an on-line resize
+    
+    When doing an online resize, the on-disk superblock on-disk wasn't
+    updated.  This means that when the file system is unmounted and
+    remounted, and the on-disk overhead value is non-zero, this would
+    result in the results of statfs(2) to be incorrect.
+    
+    This was partially fixed by Commits 10b01ee92df5 ("ext4: fix overhead
+    calculation to account for the reserved gdt blocks"), 85d825dbf489
+    ("ext4: force overhead calculation if the s_overhead_cluster makes no
+    sense"), and eb7054212eac ("ext4: update the cached overhead value in
+    the superblock").
+    
+    However, since it was too expensive to forcibly recalculate the
+    overhead for bigalloc file systems at every mount, this didn't fix the
+    problem for bigalloc file systems.  This commit should address the
+    problem when resizing file systems with the bigalloc feature enabled.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+    Reviewed-by: Andreas Dilger 
+    Link: https://lore.kernel.org/r/20220629040026.112371-1-tytso@mit.edu
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 8b70a4701293..e5c2713aa11a 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -1484,6 +1484,7 @@ static void ext4_update_super(struct super_block *sb,
+ 	 * Update the fs overhead information
+ 	 */
+ 	ext4_calculate_overhead(sb);
++	es->s_overhead_clusters = cpu_to_le32(sbi->s_overhead);
+ 
+ 	if (test_opt(sb, DEBUG))
+ 		printk(KERN_DEBUG "EXT4-fs: added group %u:"

commit e408e695f5f1f60d784913afc45ff2c387a5aeb8
+Author: Theodore Ts'o 
+Date:   Thu Jul 14 21:59:12 2022 -0400
+
+    mm/shmem: support FS_IOC_[SG]ETFLAGS in tmpfs
+    
+    This allows userspace to set flags like FS_APPEND_FL, FS_IMMUTABLE_FL,
+    FS_NODUMP_FL, etc., like all other standard Linux file systems.
+    
+    [akpm@linux-foundation.org: fix CONFIG_TMPFS_XATTR=n warnings]
+    Link: https://lkml.kernel.org/r/20220715015912.2560575-1-tytso@mit.edu
+    Signed-off-by: Theodore Ts'o 
+    Cc: Hugh Dickins 
+    Signed-off-by: Andrew Morton 
+
+diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
+index a68f982f22d1..1b6c4013f691 100644
+--- a/include/linux/shmem_fs.h
++++ b/include/linux/shmem_fs.h
+@@ -25,9 +25,20 @@ struct shmem_inode_info {
+ 	struct simple_xattrs	xattrs;		/* list of xattrs */
+ 	atomic_t		stop_eviction;	/* hold when working on inode */
+ 	struct timespec64	i_crtime;	/* file creation time */
++	unsigned int		fsflags;	/* flags for FS_IOC_[SG]ETFLAGS */
+ 	struct inode		vfs_inode;
+ };
+ 
++#define SHMEM_FL_USER_VISIBLE FS_FL_USER_VISIBLE
++#define SHMEM_FL_USER_MODIFIABLE FS_FL_USER_MODIFIABLE
++#define SHMEM_FL_INHERITED FS_FL_USER_MODIFIABLE
++
++/* Flags that are appropriate for regular files (all but dir-specific ones). */
++#define SHMEM_REG_FLMASK (~(FS_DIRSYNC_FL | FS_TOPDIR_FL))
++
++/* Flags that are appropriate for non-directories/regular files. */
++#define SHMEM_OTHER_FLMASK (FS_NODUMP_FL | FS_NOATIME_FL)
++
+ struct shmem_sb_info {
+ 	unsigned long max_blocks;   /* How many blocks are allowed */
+ 	struct percpu_counter used_blocks;  /* How many are allocated */
+diff --git a/mm/shmem.c b/mm/shmem.c
+index 12ac67dc831f..06871a913b49 100644
+--- a/mm/shmem.c
++++ b/mm/shmem.c
+@@ -28,6 +28,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -1058,6 +1059,15 @@ static int shmem_getattr(struct user_namespace *mnt_userns,
+ 		shmem_recalc_inode(inode);
+ 		spin_unlock_irq(&info->lock);
+ 	}
++	if (info->fsflags & FS_APPEND_FL)
++		stat->attributes |= STATX_ATTR_APPEND;
++	if (info->fsflags & FS_IMMUTABLE_FL)
++		stat->attributes |= STATX_ATTR_IMMUTABLE;
++	if (info->fsflags & FS_NODUMP_FL)
++		stat->attributes |= STATX_ATTR_NODUMP;
++	stat->attributes_mask |= (STATX_ATTR_APPEND |
++			STATX_ATTR_IMMUTABLE |
++			STATX_ATTR_NODUMP);
+ 	generic_fillattr(&init_user_ns, inode, stat);
+ 
+ 	if (shmem_is_huge(NULL, inode, 0))
+@@ -2272,7 +2282,18 @@ static int shmem_mmap(struct file *file, struct vm_area_struct *vma)
+ 	return 0;
+ }
+ 
+-static struct inode *shmem_get_inode(struct super_block *sb, const struct inode *dir,
++/* Mask out flags that are inappropriate for the given type of inode. */
++static unsigned shmem_mask_flags(umode_t mode, __u32 flags)
++{
++	if (S_ISDIR(mode))
++		return flags;
++	else if (S_ISREG(mode))
++		return flags & SHMEM_REG_FLMASK;
++	else
++		return flags & SHMEM_OTHER_FLMASK;
++}
++
++static struct inode *shmem_get_inode(struct super_block *sb, struct inode *dir,
+ 				     umode_t mode, dev_t dev, unsigned long flags)
+ {
+ 	struct inode *inode;
+@@ -2297,6 +2318,9 @@ static struct inode *shmem_get_inode(struct super_block *sb, const struct inode
+ 		info->seals = F_SEAL_SEAL;
+ 		info->flags = flags & VM_NORESERVE;
+ 		info->i_crtime = inode->i_mtime;
++		info->fsflags = (dir == NULL) ? 0 :
++			SHMEM_I(dir)->fsflags & SHMEM_FL_INHERITED;
++		info->fsflags = shmem_mask_flags(mode, info->fsflags);
+ 		INIT_LIST_HEAD(&info->shrinklist);
+ 		INIT_LIST_HEAD(&info->swaplist);
+ 		simple_xattrs_init(&info->xattrs);
+@@ -3138,6 +3162,40 @@ static const char *shmem_get_link(struct dentry *dentry,
+ }
+ 
+ #ifdef CONFIG_TMPFS_XATTR
++
++static int shmem_fileattr_get(struct dentry *dentry, struct fileattr *fa)
++{
++	struct shmem_inode_info *info = SHMEM_I(d_inode(dentry));
++
++	fileattr_fill_flags(fa, info->fsflags & SHMEM_FL_USER_VISIBLE);
++
++	return 0;
++}
++
++static int shmem_fileattr_set(struct user_namespace *mnt_userns,
++			      struct dentry *dentry, struct fileattr *fa)
++{
++	struct inode *inode = d_inode(dentry);
++	struct shmem_inode_info *info = SHMEM_I(inode);
++
++	if (fileattr_has_fsx(fa))
++		return -EOPNOTSUPP;
++
++	info->fsflags = (info->fsflags & ~SHMEM_FL_USER_MODIFIABLE) |
++		(fa->flags & SHMEM_FL_USER_MODIFIABLE);
++
++	inode->i_flags &= ~(S_APPEND | S_IMMUTABLE | S_NOATIME);
++	if (info->fsflags & FS_APPEND_FL)
++		inode->i_flags |= S_APPEND;
++	if (info->fsflags & FS_IMMUTABLE_FL)
++		inode->i_flags |= S_IMMUTABLE;
++	if (info->fsflags & FS_NOATIME_FL)
++		inode->i_flags |= S_NOATIME;
++
++	inode->i_ctime = current_time(inode);
++	return 0;
++}
++
+ /*
+  * Superblocks without xattr inode operations may get some security.* xattr
+  * support from the LSM "for free". As soon as we have any other xattrs
+@@ -3828,6 +3886,8 @@ static const struct inode_operations shmem_inode_operations = {
+ #ifdef CONFIG_TMPFS_XATTR
+ 	.listxattr	= shmem_listxattr,
+ 	.set_acl	= simple_set_acl,
++	.fileattr_get	= shmem_fileattr_get,
++	.fileattr_set	= shmem_fileattr_set,
+ #endif
+ };
+ 
+@@ -3847,6 +3907,8 @@ static const struct inode_operations shmem_dir_inode_operations = {
+ #endif
+ #ifdef CONFIG_TMPFS_XATTR
+ 	.listxattr	= shmem_listxattr,
++	.fileattr_get	= shmem_fileattr_get,
++	.fileattr_set	= shmem_fileattr_set,
+ #endif
+ #ifdef CONFIG_TMPFS_POSIX_ACL
+ 	.setattr	= shmem_setattr,

commit c878bea3c9d724ddfa05a813f30de3d25a0ba83f
+Author: Theodore Ts'o 
+Date:   Tue May 17 13:27:55 2022 -0400
+
+    ext4: filter out EXT4_FC_REPLAY from on-disk superblock field s_state
+    
+    The EXT4_FC_REPLAY bit in sbi->s_mount_state is used to indicate that
+    we are in the middle of replay the fast commit journal.  This was
+    actually a mistake, since the sbi->s_mount_info is initialized from
+    es->s_state.  Arguably s_mount_state is misleadingly named, but the
+    name is historical --- s_mount_state and s_state dates back to ext2.
+    
+    What should have been used is the ext4_{set,clear,test}_mount_flag()
+    inline functions, which sets EXT4_MF_* bits in sbi->s_mount_flags.
+    
+    The problem with using EXT4_FC_REPLAY is that a maliciously corrupted
+    superblock could result in EXT4_FC_REPLAY getting set in
+    s_mount_state.  This bypasses some sanity checks, and this can trigger
+    a BUG() in ext4_es_cache_extent().  As a easy-to-backport-fix, filter
+    out the EXT4_FC_REPLAY bit for now.  We should eventually transition
+    away from EXT4_FC_REPLAY to something like EXT4_MF_REPLAY.
+    
+    Cc: stable@kernel.org
+    Signed-off-by: Theodore Ts'o 
+    Link: https://lore.kernel.org/r/20220420192312.1655305-1-phind.uet@gmail.com
+    Link: https://lore.kernel.org/r/20220517174028.942119-1-tytso@mit.edu
+    Reported-by: syzbot+c7358a3cd05ee786eb31@syzkaller.appspotmail.com
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 7f6cd2473163..9cbb22045379 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4770,7 +4770,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
+ 					sbi->s_inodes_per_block;
+ 	sbi->s_desc_per_block = blocksize / EXT4_DESC_SIZE(sb);
+ 	sbi->s_sbh = bh;
+-	sbi->s_mount_state = le16_to_cpu(es->s_state);
++	sbi->s_mount_state = le16_to_cpu(es->s_state) & ~EXT4_FC_REPLAY;
+ 	sbi->s_addr_per_block_bits = ilog2(EXT4_ADDR_PER_BLOCK(sb));
+ 	sbi->s_desc_per_block_bits = ilog2(EXT4_DESC_PER_BLOCK(sb));
+ 
+@@ -6333,7 +6333,8 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb)
+ 				if (err)
+ 					goto restore_opts;
+ 			}
+-			sbi->s_mount_state = le16_to_cpu(es->s_state);
++			sbi->s_mount_state = (le16_to_cpu(es->s_state) &
++					      ~EXT4_FC_REPLAY);
+ 
+ 			err = ext4_setup_super(sb, es, 0);
+ 			if (err)

commit 32452a3eb8b64e01e2be717f518c0be046975b9d
+Author: Joseph Ravichandran 
+Date:   Thu Apr 28 12:57:52 2022 -0400
+
+    io_uring: fix uninitialized field in rw io_kiocb
+    
+    io_rw_init_file does not initialize kiocb->private, so when iocb_bio_iopoll
+    reads kiocb->private it can contain uninitialized data.
+    
+    Fixes: 3e08773c3841 ("block: switch polling to be bio based")
+    Signed-off-by: Joseph Ravichandran 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/fs/io_uring.c b/fs/io_uring.c
+index 92ac50f139cd..e3ae26ff5d1a 100644
+--- a/fs/io_uring.c
++++ b/fs/io_uring.c
+@@ -3783,6 +3783,7 @@ static int io_rw_init_file(struct io_kiocb *req, fmode_t mode)
+ 		if (!(kiocb->ki_flags & IOCB_DIRECT) || !file->f_op->iopoll)
+ 			return -EOPNOTSUPP;
+ 
++		kiocb->private = NULL;
+ 		kiocb->ki_flags |= IOCB_HIPRI | IOCB_ALLOC_CACHE;
+ 		kiocb->ki_complete = io_complete_rw_iopoll;
+ 		req->iopoll_completed = 0;

commit eb7054212eac8b451d727bf079eae3db8c88f9d3
+Author: Theodore Ts'o 
+Date:   Thu Apr 14 22:39:00 2022 -0400
+
+    ext4: update the cached overhead value in the superblock
+    
+    If we (re-)calculate the file system overhead amount and it's
+    different from the on-disk s_overhead_clusters value, update the
+    on-disk version since this can take potentially quite a while on
+    bigalloc file systems.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 48dc2c3247ad..a743b1e3b89e 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -3068,6 +3068,7 @@ int ext4_fileattr_set(struct user_namespace *mnt_userns,
+ 		      struct dentry *dentry, struct fileattr *fa);
+ int ext4_fileattr_get(struct dentry *dentry, struct fileattr *fa);
+ extern void ext4_reset_inode_seed(struct inode *inode);
++int ext4_update_overhead(struct super_block *sb);
+ 
+ /* migrate.c */
+ extern int ext4_ext_migrate(struct inode *);
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index 992229ca2d83..ba44fa1be70a 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -1652,3 +1652,19 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ 	return ext4_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
+ }
+ #endif
++
++static void set_overhead(struct ext4_super_block *es, const void *arg)
++{
++	es->s_overhead_clusters = cpu_to_le32(*((unsigned long *) arg));
++}
++
++int ext4_update_overhead(struct super_block *sb)
++{
++	struct ext4_sb_info *sbi = EXT4_SB(sb);
++
++	if (sb_rdonly(sb) || sbi->s_overhead == 0 ||
++	    sbi->s_overhead == le32_to_cpu(sbi->s_es->s_overhead_clusters))
++		return 0;
++
++	return ext4_update_superblocks_fn(sb, set_overhead, &sbi->s_overhead);
++}
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index d08820fdfdee..1847b46af808 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -5618,6 +5618,8 @@ static int ext4_fill_super(struct super_block *sb, struct fs_context *fc)
+ 		ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. "
+ 			 "Quota mode: %s.", descr, ext4_quota_mode(sb));
+ 
++	/* Update the s_overhead_clusters if necessary */
++	ext4_update_overhead(sb);
+ 	return 0;
+ 
+ free_sbi:

commit 85d825dbf4899a69407338bae462a59aa9a37326
+Author: Theodore Ts'o 
+Date:   Thu Apr 14 21:57:49 2022 -0400
+
+    ext4: force overhead calculation if the s_overhead_cluster makes no sense
+    
+    If the file system does not use bigalloc, calculating the overhead is
+    cheap, so force the recalculation of the overhead so we don't have to
+    trust the precalculated overhead in the superblock.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 23a9b2c086ed..d08820fdfdee 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -5289,9 +5289,18 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
+ 	 * Get the # of file system overhead blocks from the
+ 	 * superblock if present.
+ 	 */
+-	if (es->s_overhead_clusters)
+-		sbi->s_overhead = le32_to_cpu(es->s_overhead_clusters);
+-	else {
++	sbi->s_overhead = le32_to_cpu(es->s_overhead_clusters);
++	/* ignore the precalculated value if it is ridiculous */
++	if (sbi->s_overhead > ext4_blocks_count(es))
++		sbi->s_overhead = 0;
++	/*
++	 * If the bigalloc feature is not enabled recalculating the
++	 * overhead doesn't take long, so we might as well just redo
++	 * it to make sure we are using the correct value.
++	 */
++	if (!ext4_has_feature_bigalloc(sb))
++		sbi->s_overhead = 0;
++	if (sbi->s_overhead == 0) {
+ 		err = ext4_calculate_overhead(sb);
+ 		if (err)
+ 			goto failed_mount_wq;

commit 10b01ee92df52c8d7200afead4d5e5f55a5c58b1
+Author: Theodore Ts'o 
+Date:   Thu Apr 14 21:31:27 2022 -0400
+
+    ext4: fix overhead calculation to account for the reserved gdt blocks
+    
+    The kernel calculation was underestimating the overhead by not taking
+    into account the reserved gdt blocks.  With this change, the overhead
+    calculated by the kernel matches the overhead calculation in mke2fs.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index f2a5e78f93a9..23a9b2c086ed 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4177,9 +4177,11 @@ static int count_overhead(struct super_block *sb, ext4_group_t grp,
+ 	ext4_fsblk_t		first_block, last_block, b;
+ 	ext4_group_t		i, ngroups = ext4_get_groups_count(sb);
+ 	int			s, j, count = 0;
++	int			has_super = ext4_bg_has_super(sb, grp);
+ 
+ 	if (!ext4_has_feature_bigalloc(sb))
+-		return (ext4_bg_has_super(sb, grp) + ext4_bg_num_gdb(sb, grp) +
++		return (has_super + ext4_bg_num_gdb(sb, grp) +
++			(has_super ? le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) : 0) +
+ 			sbi->s_itb_per_group + 2);
+ 
+ 	first_block = le32_to_cpu(sbi->s_es->s_first_data_block) +

commit 919adbfec29d5b89b3e45620653cbeeb0d42e6fd
+Author: Theodore Ts'o 
+Date:   Sat Mar 12 21:39:35 2022 -0500
+
+    ext4: fix kernel doc warnings
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index a0fb0c4bdc7c..78ee3ef795ae 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -411,6 +411,7 @@ static int ext4_validate_block_bitmap(struct super_block *sb,
+  * ext4_read_block_bitmap_nowait()
+  * @sb:			super block
+  * @block_group:	given block group
++ * @ignore_locked:	ignore locked buffers
+  *
+  * Read the bitmap for a given block_group,and validate the
+  * bits for block/inode/inode tables are set in the bitmaps
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index a8022c2c6a58..992229ca2d83 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -269,7 +269,7 @@ int ext4_update_superblocks_fn(struct super_block *sb,
+ 	return err ? err : 0;
+ }
+ 
+-/**
++/*
+  * Swap memory between @a and @b for @len bytes.
+  *
+  * @a:          pointer to first memory area
+@@ -290,7 +290,7 @@ static void memswap(void *a, void *b, size_t len)
+ 	}
+ }
+ 
+-/**
++/*
+  * Swap i_data and associated attributes between @inode1 and @inode2.
+  * This function is used for the primary swap between inode1 and inode2
+  * and also to revert this primary swap in case of errors.
+@@ -344,7 +344,7 @@ void ext4_reset_inode_seed(struct inode *inode)
+ 	ei->i_csum_seed = ext4_chksum(sbi, csum, (__u8 *)&gen, sizeof(gen));
+ }
+ 
+-/**
++/*
+  * Swap the information from the given @inode and the inode
+  * EXT4_BOOT_LOADER_INO. It will basically swap i_data and all other
+  * important fields of the inodes.

commit cc5095747edfb054ca2068d01af20be3fcc3634f
+Author: Theodore Ts'o 
+Date:   Thu Mar 3 09:38:47 2022 -0500
+
+    ext4: don't BUG if someone dirty pages without asking ext4 first
+    
+    [un]pin_user_pages_remote is dirtying pages without properly warning
+    the file system in advance.  A related race was noted by Jan Kara in
+    2018[1]; however, more recently instead of it being a very hard-to-hit
+    race, it could be reliably triggered by process_vm_writev(2) which was
+    discovered by Syzbot[2].
+    
+    This is technically a bug in mm/gup.c, but arguably ext4 is fragile in
+    that if some other kernel subsystem dirty pages without properly
+    notifying the file system using page_mkwrite(), ext4 will BUG, while
+    other file systems will not BUG (although data will still be lost).
+    
+    So instead of crashing with a BUG, issue a warning (since there may be
+    potential data loss) and just mark the page as clean to avoid
+    unprivileged denial of service attacks until the problem can be
+    properly fixed.  More discussion and background can be found in the
+    thread starting at [2].
+    
+    [1] https://lore.kernel.org/linux-mm/20180103100430.GE4911@quack2.suse.cz
+    [2] https://lore.kernel.org/r/Yg0m6IjcNmfaSokM@google.com
+    
+    Reported-by: syzbot+d59332e2db681cf18f0318a06e994ebbb529a8db@syzkaller.appspotmail.com
+    Reported-by: Lee Jones 
+    Signed-off-by: Theodore Ts'o 
+    Link: https://lore.kernel.org/r/YiDS9wVfq4mM2jGK@mit.edu
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 01c9e4f743ba..531a94f48637 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1993,6 +1993,15 @@ static int ext4_writepage(struct page *page,
+ 	else
+ 		len = PAGE_SIZE;
+ 
++	/* Should never happen but for bugs in other kernel subsystems */
++	if (!page_has_buffers(page)) {
++		ext4_warning_inode(inode,
++		   "page %lu does not have buffers attached", page->index);
++		ClearPageDirty(page);
++		unlock_page(page);
++		return 0;
++	}
++
+ 	page_bufs = page_buffers(page);
+ 	/*
+ 	 * We cannot do block allocation or other extent handling in this
+@@ -2594,6 +2603,22 @@ static int mpage_prepare_extent_to_map(struct mpage_da_data *mpd)
+ 			wait_on_page_writeback(page);
+ 			BUG_ON(PageWriteback(page));
+ 
++			/*
++			 * Should never happen but for buggy code in
++			 * other subsystems that call
++			 * set_page_dirty() without properly warning
++			 * the file system first.  See [1] for more
++			 * information.
++			 *
++			 * [1] https://lore.kernel.org/linux-mm/20180103100430.GE4911@quack2.suse.cz
++			 */
++			if (!page_has_buffers(page)) {
++				ext4_warning_inode(mpd->inode, "page %lu does not have buffers attached", page->index);
++				ClearPageDirty(page);
++				unlock_page(page);
++				continue;
++			}
++
+ 			if (mpd->map.m_len == 0)
+ 				mpd->first_page = page->index;
+ 			mpd->next_page = page->index + 1;

commit 6eeaf88fd586f05aaf1d48cb3a139d2a5c6eb055
+Author: Theodore Ts'o 
+Date:   Wed Jan 5 23:59:56 2022 -0500
+
+    ext4: don't use the orphan list when migrating an inode
+    
+    We probably want to remove the indirect block to extents migration
+    feature after a deprecation window, but until then, let's fix a
+    potential data loss problem caused by the fact that we put the
+    tmp_inode on the orphan list.  In the unlikely case where we crash and
+    do a journal recovery, the data blocks belonging to the inode being
+    migrated are also represented in the tmp_inode on the orphan list ---
+    and so its data blocks will get marked unallocated, and available for
+    reuse.
+    
+    Instead, stop putting the tmp_inode on the oprhan list.  So in the
+    case where we crash while migrating the inode, we'll leak an inode,
+    which is not a disaster.  It will be easily fixed the next time we run
+    fsck, and it's better than potentially having blocks getting claimed
+    by two different files, and losing data as a result.
+    
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Lukas Czerner 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
+index 36dfc88ce05b..ff8916e1d38e 100644
+--- a/fs/ext4/migrate.c
++++ b/fs/ext4/migrate.c
+@@ -437,12 +437,12 @@ int ext4_ext_migrate(struct inode *inode)
+ 	percpu_down_write(&sbi->s_writepages_rwsem);
+ 
+ 	/*
+-	 * Worst case we can touch the allocation bitmaps, a bgd
+-	 * block, and a block to link in the orphan list.  We do need
+-	 * need to worry about credits for modifying the quota inode.
++	 * Worst case we can touch the allocation bitmaps and a block
++	 * group descriptor block.  We do need need to worry about
++	 * credits for modifying the quota inode.
+ 	 */
+ 	handle = ext4_journal_start(inode, EXT4_HT_MIGRATE,
+-		4 + EXT4_MAXQUOTAS_TRANS_BLOCKS(inode->i_sb));
++		3 + EXT4_MAXQUOTAS_TRANS_BLOCKS(inode->i_sb));
+ 
+ 	if (IS_ERR(handle)) {
+ 		retval = PTR_ERR(handle);
+@@ -463,10 +463,6 @@ int ext4_ext_migrate(struct inode *inode)
+ 	 * Use the correct seed for checksum (i.e. the seed from 'inode').  This
+ 	 * is so that the metadata blocks will have the correct checksum after
+ 	 * the migration.
+-	 *
+-	 * Note however that, if a crash occurs during the migration process,
+-	 * the recovery process is broken because the tmp_inode checksums will
+-	 * be wrong and the orphans cleanup will fail.
+ 	 */
+ 	ei = EXT4_I(inode);
+ 	EXT4_I(tmp_inode)->i_csum_seed = ei->i_csum_seed;
+@@ -478,7 +474,6 @@ int ext4_ext_migrate(struct inode *inode)
+ 	clear_nlink(tmp_inode);
+ 
+ 	ext4_ext_tree_init(handle, tmp_inode);
+-	ext4_orphan_add(handle, tmp_inode);
+ 	ext4_journal_stop(handle);
+ 
+ 	/*
+@@ -503,12 +498,6 @@ int ext4_ext_migrate(struct inode *inode)
+ 
+ 	handle = ext4_journal_start(inode, EXT4_HT_MIGRATE, 1);
+ 	if (IS_ERR(handle)) {
+-		/*
+-		 * It is impossible to update on-disk structures without
+-		 * a handle, so just rollback in-core changes and live other
+-		 * work to orphan_list_cleanup()
+-		 */
+-		ext4_orphan_del(NULL, tmp_inode);
+ 		retval = PTR_ERR(handle);
+ 		goto out_tmp_inode;
+ 	}

commit 11ef08c9eb52a808b8903004cba0733df6902a43
+Merge: 1fd95c05d8f7 cc883236b792
+Author: Theodore Ts'o 
+Date:   Sat Sep 4 23:46:32 2021 -0400
+
+    Merge branch 'delalloc-buffer-write' into dev
+    
+    Fix a bug in how we update i_disksize, and the error path in
+    inline_data_end.  Finally, drop an unnecessary creation of a journal
+    handle which was only needed for inline data, which can give us a
+    large performance gain in delayed allocation writes.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --cc fs/ext4/inline.c
+index 82bf4ff6be28,d30709d42a27..50a3031bf466
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@@ -733,45 -729,76 +733,83 @@@ convert
+  int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,
+  			       unsigned copied, struct page *page)
+  {
+- 	int ret, no_expand;
++ 	handle_t *handle = ext4_journal_current_handle();
++ 	int no_expand;
+  	void *kaddr;
+  	struct ext4_iloc iloc;
++ 	int ret = 0, ret2;
++ 
++ 	if (unlikely(copied < len) && !PageUptodate(page))
++ 		copied = 0;
+  
+- 	if (unlikely(copied < len)) {
+- 		if (!PageUptodate(page)) {
+- 			copied = 0;
++ 	if (likely(copied)) {
++ 		ret = ext4_get_inode_loc(inode, &iloc);
++ 		if (ret) {
++ 			unlock_page(page);
++ 			put_page(page);
++ 			ext4_std_error(inode->i_sb, ret);
+  			goto out;
+  		}
+- 	}
++ 		ext4_write_lock_xattr(inode, &no_expand);
++ 		BUG_ON(!ext4_has_inline_data(inode));
+  
+- 	ret = ext4_get_inode_loc(inode, &iloc);
+- 	if (ret) {
+- 		ext4_std_error(inode->i_sb, ret);
+- 		copied = 0;
+- 		goto out;
+- 	}
+++		/*
+++		 * ei->i_inline_off may have changed since
+++		 * ext4_write_begin() called
+++		 * ext4_try_to_write_inline_data()
+++		 */
+++		(void) ext4_find_inline_data_nolock(inode);
+ +
+- 	ext4_write_lock_xattr(inode, &no_expand);
+- 	BUG_ON(!ext4_has_inline_data(inode));
++ 		kaddr = kmap_atomic(page);
++ 		ext4_write_inline_data(inode, &iloc, kaddr, pos, copied);
++ 		kunmap_atomic(kaddr);
++ 		SetPageUptodate(page);
++ 		/* clear page dirty so that writepages wouldn't work for us. */
++ 		ClearPageDirty(page);
+  
+- 	/*
+- 	 * ei->i_inline_off may have changed since ext4_write_begin()
+- 	 * called ext4_try_to_write_inline_data()
+- 	 */
+- 	(void) ext4_find_inline_data_nolock(inode);
++ 		ext4_write_unlock_xattr(inode, &no_expand);
++ 		brelse(iloc.bh);
+  
+- 	kaddr = kmap_atomic(page);
+- 	ext4_write_inline_data(inode, &iloc, kaddr, pos, len);
+- 	kunmap_atomic(kaddr);
+- 	SetPageUptodate(page);
+- 	/* clear page dirty so that writepages wouldn't work for us. */
+- 	ClearPageDirty(page);
++ 		/*
++ 		 * It's important to update i_size while still holding page
++ 		 * lock: page writeout could otherwise come in and zero
++ 		 * beyond i_size.
++ 		 */
++ 		ext4_update_inode_size(inode, pos + copied);
++ 	}
++ 	unlock_page(page);
++ 	put_page(page);
+  
+- 	ext4_write_unlock_xattr(inode, &no_expand);
+- 	brelse(iloc.bh);
+- 	mark_inode_dirty(inode);
++ 	/*
++ 	 * Don't mark the inode dirty under page lock. First, it unnecessarily
++ 	 * makes the holding time of page lock longer. Second, it forces lock
++ 	 * ordering of page lock and transaction start for journaling
++ 	 * filesystems.
++ 	 */
++ 	if (likely(copied))
++ 		mark_inode_dirty(inode);
+  out:
+- 	return copied;
++ 	/*
++ 	 * If we didn't copy as much data as expected, we need to trim back
++ 	 * size of xattr containing inline data.
++ 	 */
++ 	if (pos + len > inode->i_size && ext4_can_truncate(inode))
++ 		ext4_orphan_add(handle, inode);
++ 
++ 	ret2 = ext4_journal_stop(handle);
++ 	if (!ret)
++ 		ret = ret2;
++ 	if (pos + len > inode->i_size) {
++ 		ext4_truncate_failed_write(inode);
++ 		/*
++ 		 * If truncate failed early the inode might still be
++ 		 * on the orphan list; we need to make sure the inode
++ 		 * is removed from the orphan list in that case.
++ 		 */
++ 		if (inode->i_nlink)
++ 			ext4_orphan_del(NULL, inode);
++ 	}
++ 	return ret ? ret : copied;
+  }
+  
+  struct buffer_head *
+diff --cc fs/ext4/inode.c
+index 62e9165bc69c,502f60621bad..8204176256c8
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@@ -1404,24 -1392,18 +1395,18 @@@ static int ext4_journalled_write_end(st
+  
+  	BUG_ON(!ext4_handle_valid(handle));
+  
+- 	if (inline_data) {
+- 		ret = ext4_write_inline_data_end(inode, pos, len,
+- 						 copied, page);
+- 		if (ret < 0) {
+- 			unlock_page(page);
+- 			put_page(page);
+- 			goto errout;
+- 		}
+- 		copied = ret;
+- 	} else if (unlikely(copied < len) && !PageUptodate(page)) {
++ 	if (ext4_has_inline_data(inode))
++ 		return ext4_write_inline_data_end(inode, pos, len, copied, page);
++ 
++ 	if (unlikely(copied < len) && !PageUptodate(page)) {
+  		copied = 0;
+ -		ext4_journalled_zero_new_buffers(handle, page, from, to);
+ +		ext4_journalled_zero_new_buffers(handle, inode, page, from, to);
+  	} else {
+  		if (unlikely(copied < len))
+ -			ext4_journalled_zero_new_buffers(handle, page,
+ +			ext4_journalled_zero_new_buffers(handle, inode, page,
+  							 from + copied, to);
+ -		ret = ext4_walk_page_buffers(handle, page_buffers(page), from,
+ -					     from + copied, &partial,
+ +		ret = ext4_walk_page_buffers(handle, inode, page_buffers(page),
+ +					     from, from + copied, &partial,
+  					     write_end_fn);
+  		if (!partial)
+  			SetPageUptodate(page);

commit 1fd95c05d8f742abfe906620780aee4dbe1a2db0
+Author: Theodore Ts'o 
+Date:   Thu Sep 2 11:36:01 2021 -0400
+
+    ext4: add error checking to ext4_ext_replay_set_iblocks()
+    
+    If the call to ext4_map_blocks() fails due to an corrupted file
+    system, ext4_ext_replay_set_iblocks() can get stuck in an infinite
+    loop.  This could be reproduced by running generic/526 with a file
+    system that has inline_data and fast_commit enabled.  The system will
+    repeatedly log to the console:
+    
+    EXT4-fs warning (device dm-3): ext4_block_to_path:105: block 1074800922 > max in inode 131076
+    
+    and the stack that it gets stuck in is:
+    
+       ext4_block_to_path+0xe3/0x130
+       ext4_ind_map_blocks+0x93/0x690
+       ext4_map_blocks+0x100/0x660
+       skip_hole+0x47/0x70
+       ext4_ext_replay_set_iblocks+0x223/0x440
+       ext4_fc_replay_inode+0x29e/0x3b0
+       ext4_fc_replay+0x278/0x550
+       do_one_pass+0x646/0xc10
+       jbd2_journal_recover+0x14a/0x270
+       jbd2_journal_load+0xc4/0x150
+       ext4_load_journal+0x1f3/0x490
+       ext4_fill_super+0x22d4/0x2c00
+    
+    With this patch, generic/526 still fails, but system is no longer
+    locking up in a tight loop.  It's likely the root casue is that
+    fast_commit replay is corrupting file systems with inline_data, and we
+    probably need to add better error handling in the fast commit replay
+    code path beyond what is done here, which essentially just breaks the
+    infinite loop without reporting the to the higher levels of the code.
+    
+    Fixes: 8016E29F4362 ("ext4: fast commit recovery path")
+    Cc: stable@kernel.org
+    Cc: Harshad Shirwadkar 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index eb1dd4f024f2..e57019cc3601 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -5913,7 +5913,7 @@ void ext4_ext_replay_shrink_inode(struct inode *inode, ext4_lblk_t end)
+ }
+ 
+ /* Check if *cur is a hole and if it is, skip it */
+-static void skip_hole(struct inode *inode, ext4_lblk_t *cur)
++static int skip_hole(struct inode *inode, ext4_lblk_t *cur)
+ {
+ 	int ret;
+ 	struct ext4_map_blocks map;
+@@ -5922,9 +5922,12 @@ static void skip_hole(struct inode *inode, ext4_lblk_t *cur)
+ 	map.m_len = ((inode->i_size) >> inode->i_sb->s_blocksize_bits) - *cur;
+ 
+ 	ret = ext4_map_blocks(NULL, inode, &map, 0);
++	if (ret < 0)
++		return ret;
+ 	if (ret != 0)
+-		return;
++		return 0;
+ 	*cur = *cur + map.m_len;
++	return 0;
+ }
+ 
+ /* Count number of blocks used by this inode and update i_blocks */
+@@ -5973,7 +5976,9 @@ int ext4_ext_replay_set_iblocks(struct inode *inode)
+ 	 * iblocks by total number of differences found.
+ 	 */
+ 	cur = 0;
+-	skip_hole(inode, &cur);
++	ret = skip_hole(inode, &cur);
++	if (ret < 0)
++		goto out;
+ 	path = ext4_find_extent(inode, cur, NULL, 0);
+ 	if (IS_ERR(path))
+ 		goto out;
+@@ -5992,8 +5997,12 @@ int ext4_ext_replay_set_iblocks(struct inode *inode)
+ 		}
+ 		cur = max(cur + 1, le32_to_cpu(ex->ee_block) +
+ 					ext4_ext_get_actual_len(ex));
+-		skip_hole(inode, &cur);
+-
++		ret = skip_hole(inode, &cur);
++		if (ret < 0) {
++			ext4_ext_drop_refs(path);
++			kfree(path);
++			break;
++		}
+ 		path2 = ext4_find_extent(inode, cur, NULL, 0);
+ 		if (IS_ERR(path2)) {
+ 			ext4_ext_drop_refs(path);

commit b33d9f5909c8d30f1429fb9aefbb32760901a023
+Author: Theodore Ts'o 
+Date:   Sat Aug 14 10:54:09 2021 -0400
+
+    jbd2: add sparse annotations for add_transaction_credits()
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index 8804e126805f..5347411ae13e 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -223,9 +223,15 @@ static void sub_reserved_credits(journal_t *journal, int blocks)
+  * with j_state_lock held for reading. Returns 0 if handle joined the running
+  * transaction. Returns 1 if we had to wait, j_state_lock is dropped, and
+  * caller must retry.
++ *
++ * Note: because j_state_lock may be dropped depending on the return
++ * value, we need to fake out sparse so ti doesn't complain about a
++ * locking imbalance.  Callers of add_transaction_credits will need to
++ * make a similar accomodation.
+  */
+ static int add_transaction_credits(journal_t *journal, int blocks,
+ 				   int rsv_blocks)
++__must_hold(&journal->j_state_lock)
+ {
+ 	transaction_t *t = journal->j_running_transaction;
+ 	int needed;
+@@ -238,6 +244,7 @@ static int add_transaction_credits(journal_t *journal, int blocks,
+ 	if (t->t_state != T_RUNNING) {
+ 		WARN_ON_ONCE(t->t_state >= T_FLUSH);
+ 		wait_transaction_locked(journal);
++		__acquire(&journal->j_state_lock); /* fake out sparse */
+ 		return 1;
+ 	}
+ 
+@@ -266,10 +273,12 @@ static int add_transaction_credits(journal_t *journal, int blocks,
+ 			wait_event(journal->j_wait_reserved,
+ 				   atomic_read(&journal->j_reserved_credits) + total <=
+ 				   journal->j_max_transaction_buffers);
++			__acquire(&journal->j_state_lock); /* fake out sparse */
+ 			return 1;
+ 		}
+ 
+ 		wait_transaction_locked(journal);
++		__acquire(&journal->j_state_lock); /* fake out sparse */
+ 		return 1;
+ 	}
+ 
+@@ -293,6 +302,7 @@ static int add_transaction_credits(journal_t *journal, int blocks,
+ 					journal->j_max_transaction_buffers)
+ 			__jbd2_log_wait_for_space(journal);
+ 		write_unlock(&journal->j_state_lock);
++		__acquire(&journal->j_state_lock); /* fake out sparse */
+ 		return 1;
+ 	}
+ 
+@@ -310,6 +320,7 @@ static int add_transaction_credits(journal_t *journal, int blocks,
+ 		wait_event(journal->j_wait_reserved,
+ 			 atomic_read(&journal->j_reserved_credits) + rsv_blocks
+ 			 <= journal->j_max_transaction_buffers / 2);
++		__acquire(&journal->j_state_lock); /* fake out sparse */
+ 		return 1;
+ 	}
+ 	return 0;
+@@ -413,8 +424,14 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
+ 
+ 	if (!handle->h_reserved) {
+ 		/* We may have dropped j_state_lock - restart in that case */
+-		if (add_transaction_credits(journal, blocks, rsv_blocks))
++		if (add_transaction_credits(journal, blocks, rsv_blocks)) {
++			/*
++			 * add_transaction_credits releases
++			 * j_state_lock on a non-zero return
++			 */
++			__release(&journal->j_state_lock);
+ 			goto repeat;
++		}
+ 	} else {
+ 		/*
+ 		 * We have handle reserved so we are allowed to join T_LOCKED

commit a5fda11338180db13f3e9eec20c9deda1f7bad72
+Author: Theodore Ts'o 
+Date:   Sat Aug 14 10:41:30 2021 -0400
+
+    ext4: fix sparse warnings
+    
+    Add sparse annotations to suppress false positive context imbalance
+    warnings, and use NULL instead of 0 in EXT_MAX_{EXTENT,INDEX}.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h
+index 44e59881a1f0..26435f3a3094 100644
+--- a/fs/ext4/ext4_extents.h
++++ b/fs/ext4/ext4_extents.h
+@@ -173,10 +173,11 @@ struct partial_cluster {
+ #define EXT_MAX_EXTENT(__hdr__)	\
+ 	((le16_to_cpu((__hdr__)->eh_max)) ? \
+ 	((EXT_FIRST_EXTENT((__hdr__)) + le16_to_cpu((__hdr__)->eh_max) - 1)) \
+-					: 0)
++					: NULL)
+ #define EXT_MAX_INDEX(__hdr__) \
+ 	((le16_to_cpu((__hdr__)->eh_max)) ? \
+-	((EXT_FIRST_INDEX((__hdr__)) + le16_to_cpu((__hdr__)->eh_max) - 1)) : 0)
++	((EXT_FIRST_INDEX((__hdr__)) + le16_to_cpu((__hdr__)->eh_max) - 1)) \
++					: NULL)
+ 
+ static inline struct ext4_extent_header *ext_inode_hdr(struct inode *inode)
+ {
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 34670cb63588..665646a12e01 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2478,6 +2478,12 @@ static bool ext4_mb_good_group(struct ext4_allocation_context *ac,
+  * This could return negative error code if something goes wrong
+  * during ext4_mb_init_group(). This should not be called with
+  * ext4_lock_group() held.
++ *
++ * Note: because we are conditionally operating with the group lock in
++ * the EXT4_MB_STRICT_CHECK case, we need to fake out sparse in this
++ * function using __acquire and __release.  This means we need to be
++ * super careful before messing with the error path handling via "goto
++ * out"!
+  */
+ static int ext4_mb_good_group_nolock(struct ext4_allocation_context *ac,
+ 				     ext4_group_t group, int cr)
+@@ -2491,8 +2497,10 @@ static int ext4_mb_good_group_nolock(struct ext4_allocation_context *ac,
+ 
+ 	if (sbi->s_mb_stats)
+ 		atomic64_inc(&sbi->s_bal_cX_groups_considered[ac->ac_criteria]);
+-	if (should_lock)
++	if (should_lock) {
+ 		ext4_lock_group(sb, group);
++		__release(ext4_group_lock_ptr(sb, group));
++	}
+ 	free = grp->bb_free;
+ 	if (free == 0)
+ 		goto out;
+@@ -2500,8 +2508,10 @@ static int ext4_mb_good_group_nolock(struct ext4_allocation_context *ac,
+ 		goto out;
+ 	if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(grp)))
+ 		goto out;
+-	if (should_lock)
++	if (should_lock) {
++		__acquire(ext4_group_lock_ptr(sb, group));
+ 		ext4_unlock_group(sb, group);
++	}
+ 
+ 	/* We only do this if the grp has never been initialized */
+ 	if (unlikely(EXT4_MB_GRP_NEED_INIT(grp))) {
+@@ -2528,12 +2538,16 @@ static int ext4_mb_good_group_nolock(struct ext4_allocation_context *ac,
+ 			return ret;
+ 	}
+ 
+-	if (should_lock)
++	if (should_lock) {
+ 		ext4_lock_group(sb, group);
++		__release(ext4_group_lock_ptr(sb, group));
++	}
+ 	ret = ext4_mb_good_group(ac, group, cr);
+ out:
+-	if (should_lock)
++	if (should_lock) {
++		__acquire(ext4_group_lock_ptr(sb, group));
+ 		ext4_unlock_group(sb, group);
++	}
+ 	return ret;
+ }
+ 
+@@ -2969,6 +2983,7 @@ int ext4_seq_mb_stats_show(struct seq_file *seq, void *offset)
+ }
+ 
+ static void *ext4_mb_seq_structs_summary_start(struct seq_file *seq, loff_t *pos)
++__acquires(&EXT4_SB(sb)->s_mb_rb_lock)
+ {
+ 	struct super_block *sb = PDE_DATA(file_inode(seq->file));
+ 	unsigned long position;
+@@ -3041,6 +3056,7 @@ static int ext4_mb_seq_structs_summary_show(struct seq_file *seq, void *v)
+ }
+ 
+ static void ext4_mb_seq_structs_summary_stop(struct seq_file *seq, void *v)
++__releases(&EXT4_SB(sb)->s_mb_rb_lock)
+ {
+ 	struct super_block *sb = PDE_DATA(file_inode(seq->file));
+ 
+@@ -6275,6 +6291,8 @@ __acquires(bitlock)
+ static int ext4_try_to_trim_range(struct super_block *sb,
+ 		struct ext4_buddy *e4b, ext4_grpblk_t start,
+ 		ext4_grpblk_t max, ext4_grpblk_t minblocks)
++__acquires(ext4_group_lock_ptr(sb, e4b->bd_group))
++__releases(ext4_group_lock_ptr(sb, e4b->bd_group))
+ {
+ 	ext4_grpblk_t next, count, free_count;
+ 	void *bitmap;

commit a54c4613dac1500b40e4ab55199f7c51f028e848
+Author: Theodore Ts'o 
+Date:   Fri Aug 20 23:44:17 2021 -0400
+
+    ext4: fix race writing to an inline_data file while its xattrs are changing
+    
+    The location of the system.data extended attribute can change whenever
+    xattr_sem is not taken.  So we need to recalculate the i_inline_off
+    field since it mgiht have changed between ext4_write_begin() and
+    ext4_write_end().
+    
+    This means that caching i_inline_off is probably not helpful, so in
+    the long run we should probably get rid of it and shrink the in-memory
+    ext4 inode slightly, but let's fix the race the simple way for now.
+    
+    Cc: stable@kernel.org
+    Fixes: f19d5870cbf72 ("ext4: add normal write support for inline data")
+    Reported-by: syzbot+13146364637c7363a7de@syzkaller.appspotmail.com
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index 70cb64db33f7..24e994e75f5c 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -750,6 +750,12 @@ int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,
+ 	ext4_write_lock_xattr(inode, &no_expand);
+ 	BUG_ON(!ext4_has_inline_data(inode));
+ 
++	/*
++	 * ei->i_inline_off may have changed since ext4_write_begin()
++	 * called ext4_try_to_write_inline_data()
++	 */
++	(void) ext4_find_inline_data_nolock(inode);
++
+ 	kaddr = kmap_atomic(page);
+ 	ext4_write_inline_data(inode, &iloc, kaddr, pos, len);
+ 	kunmap_atomic(kaddr);

commit 308c57ccf4318236be75dfa251c84713e694457b
+Author: Theodore Ts'o 
+Date:   Fri Aug 13 11:20:48 2021 -0400
+
+    ext4: if zeroout fails fall back to splitting the extent node
+    
+    If the underlying storage device is using thin-provisioning, it's
+    possible for a zeroout operation to return ENOSPC.
+    
+    Commit df22291ff0fd ("ext4: Retry block allocation if we have free blocks
+    left") added logic to retry block allocation since we might get free block
+    after we commit a transaction. But the ENOSPC from thin-provisioning
+    will confuse ext4, and lead to an infinite loop.
+    
+    Since using zeroout instead of splitting the extent node is an
+    optimization, if it fails, we might as well fall back to splitting the
+    extent node.
+    
+    Reported-by: yangerkun 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 92ad64b89d9b..501516cadc1b 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -3569,7 +3569,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 				split_map.m_len - ee_block);
+ 			err = ext4_ext_zeroout(inode, &zero_ex1);
+ 			if (err)
+-				goto out;
++				goto fallback;
+ 			split_map.m_len = allocated;
+ 		}
+ 		if (split_map.m_lblk - ee_block + split_map.m_len <
+@@ -3583,7 +3583,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 						      ext4_ext_pblock(ex));
+ 				err = ext4_ext_zeroout(inode, &zero_ex2);
+ 				if (err)
+-					goto out;
++					goto fallback;
+ 			}
+ 
+ 			split_map.m_len += split_map.m_lblk - ee_block;
+@@ -3592,6 +3592,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 		}
+ 	}
+ 
++fallback:
+ 	err = ext4_split_extent(handle, inode, ppath, &split_map, split_flag,
+ 				flags);
+ 	if (err > 0)

commit 4009cc7ad6b5f8a260e46cdaabb3763f2e6ca2e0
+Author: Theodore Ts'o 
+Date:   Tue Aug 10 14:02:33 2021 -0400
+
+    jbd2: clean up two gcc -Wall warnings in recovery.c
+    
+    Fix a signed vs unsigned and a void * pointer arithmetic warning.
+    
+    This cleanup is also in e2fsprogs commit aec460db9a93 ("e2fsck: clean
+    up two gcc -Wall warnings in recovery.c").
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
+index ba979fcf1cd3..8ca3527189f8 100644
+--- a/fs/jbd2/recovery.c
++++ b/fs/jbd2/recovery.c
+@@ -179,8 +179,8 @@ static int jbd2_descriptor_block_csum_verify(journal_t *j, void *buf)
+ 	if (!jbd2_journal_has_csum_v2or3(j))
+ 		return 1;
+ 
+-	tail = (struct jbd2_journal_block_tail *)(buf + j->j_blocksize -
+-			sizeof(struct jbd2_journal_block_tail));
++	tail = (struct jbd2_journal_block_tail *)((char *)buf +
++		j->j_blocksize - sizeof(struct jbd2_journal_block_tail));
+ 	provided = tail->t_checksum;
+ 	tail->t_checksum = 0;
+ 	calculated = jbd2_chksum(j, j->j_csum_seed, buf, j->j_blocksize);
+@@ -896,7 +896,7 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
+ {
+ 	jbd2_journal_revoke_header_t *header;
+ 	int offset, max;
+-	int csum_size = 0;
++	unsigned csum_size = 0;
+ 	__u32 rcount;
+ 	int record_len = 4;
+ 

commit 390add0cc9f4d7fda89cf3db7651717e82cf0afc
+Author: Theodore Ts'o 
+Date:   Tue Aug 10 12:55:51 2021 -0400
+
+    jbd2: fix clang warning in recovery.c
+    
+    Remove unused variable store which was never used.
+    
+    This fix is also in e2fsprogs commit 99a2294f85f0 ("e2fsck: value
+    stored to err is never read").
+    
+    Signed-off-by: Lukas Czerner 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
+index 4c4209262437..ba979fcf1cd3 100644
+--- a/fs/jbd2/recovery.c
++++ b/fs/jbd2/recovery.c
+@@ -760,7 +760,6 @@ static int do_one_pass(journal_t *journal,
+ 				 */
+ 				jbd_debug(1, "JBD2: Invalid checksum ignored in transaction %u, likely stale data\n",
+ 					  next_commit_ID);
+-				err = 0;
+ 				brelse(bh);
+ 				goto done;
+ 			}

commit a20d1cebb98bba75f2e34fddc768dd8712c1bded
+Author: Theodore Ts'o 
+Date:   Mon May 3 15:37:33 2021 -0400
+
+    jbd2: fix portability problems caused by unaligned accesses
+    
+    This commit applies the e2fsck/recovery.c portions of commit
+    1e0c8ca7c08a ("e2fsck: fix portability problems caused by unaligned
+    accesses) from the e2fsprogs git tree.
+    
+    The on-disk format for the ext4 journal can have unaigned 32-bit
+    integers.  This can happen when replaying a journal using a obsolete
+    checksum format (which was never popularly used, since the v3 format
+    replaced v2 while the metadata checksum feature was being stablized).
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
+index d47a0d96bf30..4c4209262437 100644
+--- a/fs/jbd2/recovery.c
++++ b/fs/jbd2/recovery.c
+@@ -196,7 +196,7 @@ static int jbd2_descriptor_block_csum_verify(journal_t *j, void *buf)
+ static int count_tags(journal_t *journal, struct buffer_head *bh)
+ {
+ 	char *			tagp;
+-	journal_block_tag_t *	tag;
++	journal_block_tag_t	tag;
+ 	int			nr = 0, size = journal->j_blocksize;
+ 	int			tag_bytes = journal_tag_bytes(journal);
+ 
+@@ -206,14 +206,14 @@ static int count_tags(journal_t *journal, struct buffer_head *bh)
+ 	tagp = &bh->b_data[sizeof(journal_header_t)];
+ 
+ 	while ((tagp - bh->b_data + tag_bytes) <= size) {
+-		tag = (journal_block_tag_t *) tagp;
++		memcpy(&tag, tagp, sizeof(tag));
+ 
+ 		nr++;
+ 		tagp += tag_bytes;
+-		if (!(tag->t_flags & cpu_to_be16(JBD2_FLAG_SAME_UUID)))
++		if (!(tag.t_flags & cpu_to_be16(JBD2_FLAG_SAME_UUID)))
+ 			tagp += 16;
+ 
+-		if (tag->t_flags & cpu_to_be16(JBD2_FLAG_LAST_TAG))
++		if (tag.t_flags & cpu_to_be16(JBD2_FLAG_LAST_TAG))
+ 			break;
+ 	}
+ 
+@@ -433,9 +433,9 @@ static int jbd2_commit_block_csum_verify(journal_t *j, void *buf)
+ }
+ 
+ static int jbd2_block_tag_csum_verify(journal_t *j, journal_block_tag_t *tag,
++				      journal_block_tag3_t *tag3,
+ 				      void *buf, __u32 sequence)
+ {
+-	journal_block_tag3_t *tag3 = (journal_block_tag3_t *)tag;
+ 	__u32 csum32;
+ 	__be32 seq;
+ 
+@@ -496,7 +496,7 @@ static int do_one_pass(journal_t *journal,
+ 	while (1) {
+ 		int			flags;
+ 		char *			tagp;
+-		journal_block_tag_t *	tag;
++		journal_block_tag_t	tag;
+ 		struct buffer_head *	obh;
+ 		struct buffer_head *	nbh;
+ 
+@@ -613,8 +613,8 @@ static int do_one_pass(journal_t *journal,
+ 			       <= journal->j_blocksize - descr_csum_size) {
+ 				unsigned long io_block;
+ 
+-				tag = (journal_block_tag_t *) tagp;
+-				flags = be16_to_cpu(tag->t_flags);
++				memcpy(&tag, tagp, sizeof(tag));
++				flags = be16_to_cpu(tag.t_flags);
+ 
+ 				io_block = next_log_block++;
+ 				wrap(journal, next_log_block);
+@@ -632,7 +632,7 @@ static int do_one_pass(journal_t *journal,
+ 
+ 					J_ASSERT(obh != NULL);
+ 					blocknr = read_tag_block(journal,
+-								 tag);
++								 &tag);
+ 
+ 					/* If the block has been
+ 					 * revoked, then we're all done
+@@ -647,8 +647,8 @@ static int do_one_pass(journal_t *journal,
+ 
+ 					/* Look for block corruption */
+ 					if (!jbd2_block_tag_csum_verify(
+-						journal, tag, obh->b_data,
+-						be32_to_cpu(tmp->h_sequence))) {
++			journal, &tag, (journal_block_tag3_t *)tagp,
++			obh->b_data, be32_to_cpu(tmp->h_sequence))) {
+ 						brelse(obh);
+ 						success = -EFSBADCRC;
+ 						printk(KERN_ERR "JBD2: Invalid "

commit 877ba3f729fd3d8ef0e29bc2a55e57cfa54b2e43
+Author: Theodore Ts'o 
+Date:   Wed Aug 4 14:23:55 2021 -0400
+
+    ext4: fix potential htree corruption when growing large_dir directories
+    
+    Commit b5776e7524af ("ext4: fix potential htree index checksum
+    corruption) removed a required restart when multiple levels of index
+    nodes need to be split.  Fix this to avoid directory htree corruptions
+    when using the large_dir feature.
+    
+    Cc: stable@kernel.org # v5.11
+    Cc: Благодаренко Артём 
+    Fixes: b5776e7524af ("ext4: fix potential htree index checksum corruption)
+    Reported-by: Denis 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 5fd56f616cf0..f3bbcd4efb56 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -2517,7 +2517,7 @@ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
+ 				goto journal_error;
+ 			err = ext4_handle_dirty_dx_node(handle, dir,
+ 							frame->bh);
+-			if (err)
++			if (restart || err)
+ 				goto journal_error;
+ 		} else {
+ 			struct dx_root *dxroot;

commit 0705e8d1e2207ceeb83dc6e1751b6b82718b353a
+Author: Theodore Ts'o 
+Date:   Fri Jul 2 18:05:03 2021 -0400
+
+    ext4: inline jbd2_journal_[un]register_shrinker()
+    
+    The function jbd2_journal_unregister_shrinker() was getting called
+    twice when the file system was getting unmounted.  On Power and ARM
+    platforms this was causing kernel crash when unmounting the file
+    system, when a percpu_counter was destroyed twice.
+    
+    Fix this by removing jbd2_journal_[un]register_shrinker() functions,
+    and inlining the shrinker setup and teardown into
+    journal_init_common() and jbd2_journal_destroy().  This means that
+    ext4 and ocfs2 now no longer need to know about registering and
+    unregistering jbd2's shrinker.
+    
+    Also, while we're at it, rename the percpu counter from
+    j_jh_shrink_count to j_checkpoint_jh_count, since this makes it
+    clearer what this counter is intended to track.
+    
+    Link: https://lore.kernel.org/r/20210705145025.3363130-1-tytso@mit.edu
+    Fixes: 4ba3fcdde7e3 ("jbd2,ext4: add a shrinker to release checkpointed buffers")
+    Reported-by: Jon Hunter 
+    Reported-by: Sachin Sant 
+    Tested-by: Sachin Sant 
+    Tested-by: Jon Hunter 
+    Reviewed-by: Jan Kara 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index b8ff0399e171..dfa09a277b56 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1184,7 +1184,6 @@ static void ext4_put_super(struct super_block *sb)
+ 	ext4_unregister_sysfs(sb);
+ 
+ 	if (sbi->s_journal) {
+-		jbd2_journal_unregister_shrinker(sbi->s_journal);
+ 		aborted = is_journal_aborted(sbi->s_journal);
+ 		err = jbd2_journal_destroy(sbi->s_journal);
+ 		sbi->s_journal = NULL;
+@@ -5176,7 +5175,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	sbi->s_ea_block_cache = NULL;
+ 
+ 	if (sbi->s_journal) {
+-		jbd2_journal_unregister_shrinker(sbi->s_journal);
+ 		jbd2_journal_destroy(sbi->s_journal);
+ 		sbi->s_journal = NULL;
+ 	}
+@@ -5502,12 +5500,6 @@ static int ext4_load_journal(struct super_block *sb,
+ 		ext4_commit_super(sb);
+ 	}
+ 
+-	err = jbd2_journal_register_shrinker(journal);
+-	if (err) {
+-		EXT4_SB(sb)->s_journal = NULL;
+-		goto err_out;
+-	}
+-
+ 	return 0;
+ 
+ err_out:
+diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
+index 51d1eb2ffeb9..746132998c57 100644
+--- a/fs/jbd2/checkpoint.c
++++ b/fs/jbd2/checkpoint.c
+@@ -701,7 +701,7 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
+ 
+ 	__buffer_unlink(jh);
+ 	jh->b_cp_transaction = NULL;
+-	percpu_counter_dec(&journal->j_jh_shrink_count);
++	percpu_counter_dec(&journal->j_checkpoint_jh_count);
+ 	jbd2_journal_put_journal_head(jh);
+ 
+ 	/* Is this transaction empty? */
+@@ -764,7 +764,7 @@ void __jbd2_journal_insert_checkpoint(struct journal_head *jh,
+ 		jh->b_cpnext->b_cpprev = jh;
+ 	}
+ 	transaction->t_checkpoint_list = jh;
+-	percpu_counter_inc(&transaction->t_journal->j_jh_shrink_count);
++	percpu_counter_inc(&transaction->t_journal->j_checkpoint_jh_count);
+ }
+ 
+ /*
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 152880c298ca..35302bc192eb 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -1283,6 +1283,48 @@ static int jbd2_min_tag_size(void)
+ 	return sizeof(journal_block_tag_t) - 4;
+ }
+ 
++/**
++ * jbd2_journal_shrink_scan()
++ *
++ * Scan the checkpointed buffer on the checkpoint list and release the
++ * journal_head.
++ */
++static unsigned long jbd2_journal_shrink_scan(struct shrinker *shrink,
++					      struct shrink_control *sc)
++{
++	journal_t *journal = container_of(shrink, journal_t, j_shrinker);
++	unsigned long nr_to_scan = sc->nr_to_scan;
++	unsigned long nr_shrunk;
++	unsigned long count;
++
++	count = percpu_counter_read_positive(&journal->j_checkpoint_jh_count);
++	trace_jbd2_shrink_scan_enter(journal, sc->nr_to_scan, count);
++
++	nr_shrunk = jbd2_journal_shrink_checkpoint_list(journal, &nr_to_scan);
++
++	count = percpu_counter_read_positive(&journal->j_checkpoint_jh_count);
++	trace_jbd2_shrink_scan_exit(journal, nr_to_scan, nr_shrunk, count);
++
++	return nr_shrunk;
++}
++
++/**
++ * jbd2_journal_shrink_count()
++ *
++ * Count the number of checkpoint buffers on the checkpoint list.
++ */
++static unsigned long jbd2_journal_shrink_count(struct shrinker *shrink,
++					       struct shrink_control *sc)
++{
++	journal_t *journal = container_of(shrink, journal_t, j_shrinker);
++	unsigned long count;
++
++	count = percpu_counter_read_positive(&journal->j_checkpoint_jh_count);
++	trace_jbd2_shrink_count(journal, sc->nr_to_scan, count);
++
++	return count;
++}
++
+ /*
+  * Management for journal control blocks: functions to create and
+  * destroy journal_t structures, and to initialise and read existing
+@@ -1361,9 +1403,23 @@ static journal_t *journal_init_common(struct block_device *bdev,
+ 	journal->j_sb_buffer = bh;
+ 	journal->j_superblock = (journal_superblock_t *)bh->b_data;
+ 
++	journal->j_shrink_transaction = NULL;
++	journal->j_shrinker.scan_objects = jbd2_journal_shrink_scan;
++	journal->j_shrinker.count_objects = jbd2_journal_shrink_count;
++	journal->j_shrinker.seeks = DEFAULT_SEEKS;
++	journal->j_shrinker.batch = journal->j_max_transaction_buffers;
++
++	if (percpu_counter_init(&journal->j_checkpoint_jh_count, 0, GFP_KERNEL))
++		goto err_cleanup;
++
++	if (register_shrinker(&journal->j_shrinker)) {
++		percpu_counter_destroy(&journal->j_checkpoint_jh_count);
++		goto err_cleanup;
++	}
+ 	return journal;
+ 
+ err_cleanup:
++	brelse(journal->j_sb_buffer);
+ 	kfree(journal->j_wbuf);
+ 	jbd2_journal_destroy_revoke(journal);
+ 	kfree(journal);
+@@ -2050,93 +2106,6 @@ int jbd2_journal_load(journal_t *journal)
+ 	return -EIO;
+ }
+ 
+-/**
+- * jbd2_journal_shrink_scan()
+- *
+- * Scan the checkpointed buffer on the checkpoint list and release the
+- * journal_head.
+- */
+-static unsigned long jbd2_journal_shrink_scan(struct shrinker *shrink,
+-					      struct shrink_control *sc)
+-{
+-	journal_t *journal = container_of(shrink, journal_t, j_shrinker);
+-	unsigned long nr_to_scan = sc->nr_to_scan;
+-	unsigned long nr_shrunk;
+-	unsigned long count;
+-
+-	count = percpu_counter_read_positive(&journal->j_jh_shrink_count);
+-	trace_jbd2_shrink_scan_enter(journal, sc->nr_to_scan, count);
+-
+-	nr_shrunk = jbd2_journal_shrink_checkpoint_list(journal, &nr_to_scan);
+-
+-	count = percpu_counter_read_positive(&journal->j_jh_shrink_count);
+-	trace_jbd2_shrink_scan_exit(journal, nr_to_scan, nr_shrunk, count);
+-
+-	return nr_shrunk;
+-}
+-
+-/**
+- * jbd2_journal_shrink_count()
+- *
+- * Count the number of checkpoint buffers on the checkpoint list.
+- */
+-static unsigned long jbd2_journal_shrink_count(struct shrinker *shrink,
+-					       struct shrink_control *sc)
+-{
+-	journal_t *journal = container_of(shrink, journal_t, j_shrinker);
+-	unsigned long count;
+-
+-	count = percpu_counter_read_positive(&journal->j_jh_shrink_count);
+-	trace_jbd2_shrink_count(journal, sc->nr_to_scan, count);
+-
+-	return count;
+-}
+-
+-/**
+- * jbd2_journal_register_shrinker()
+- * @journal: Journal to act on.
+- *
+- * Init a percpu counter to record the checkpointed buffers on the checkpoint
+- * list and register a shrinker to release their journal_head.
+- */
+-int jbd2_journal_register_shrinker(journal_t *journal)
+-{
+-	int err;
+-
+-	journal->j_shrink_transaction = NULL;
+-
+-	err = percpu_counter_init(&journal->j_jh_shrink_count, 0, GFP_KERNEL);
+-	if (err)
+-		return err;
+-
+-	journal->j_shrinker.scan_objects = jbd2_journal_shrink_scan;
+-	journal->j_shrinker.count_objects = jbd2_journal_shrink_count;
+-	journal->j_shrinker.seeks = DEFAULT_SEEKS;
+-	journal->j_shrinker.batch = journal->j_max_transaction_buffers;
+-
+-	err = register_shrinker(&journal->j_shrinker);
+-	if (err) {
+-		percpu_counter_destroy(&journal->j_jh_shrink_count);
+-		return err;
+-	}
+-
+-	return 0;
+-}
+-EXPORT_SYMBOL(jbd2_journal_register_shrinker);
+-
+-/**
+- * jbd2_journal_unregister_shrinker()
+- * @journal: Journal to act on.
+- *
+- * Unregister the checkpointed buffer shrinker and destroy the percpu counter.
+- */
+-void jbd2_journal_unregister_shrinker(journal_t *journal)
+-{
+-	percpu_counter_destroy(&journal->j_jh_shrink_count);
+-	unregister_shrinker(&journal->j_shrinker);
+-}
+-EXPORT_SYMBOL(jbd2_journal_unregister_shrinker);
+-
+ /**
+  * jbd2_journal_destroy() - Release a journal_t structure.
+  * @journal: Journal to act on.
+@@ -2209,8 +2178,10 @@ int jbd2_journal_destroy(journal_t *journal)
+ 		brelse(journal->j_sb_buffer);
+ 	}
+ 
+-	jbd2_journal_unregister_shrinker(journal);
+-
++	if (journal->j_shrinker.flags & SHRINKER_REGISTERED) {
++		percpu_counter_destroy(&journal->j_checkpoint_jh_count);
++		unregister_shrinker(&journal->j_shrinker);
++	}
+ 	if (journal->j_proc_entry)
+ 		jbd2_stats_proc_exit(journal);
+ 	iput(journal->j_inode);
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index 6cc035321562..fd933c45281a 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -918,11 +918,11 @@ struct journal_s
+ 	struct shrinker		j_shrinker;
+ 
+ 	/**
+-	 * @j_jh_shrink_count:
++	 * @j_checkpoint_jh_count:
+ 	 *
+ 	 * Number of journal buffers on the checkpoint list. [j_list_lock]
+ 	 */
+-	struct percpu_counter	j_jh_shrink_count;
++	struct percpu_counter	j_checkpoint_jh_count;
+ 
+ 	/**
+ 	 * @j_shrink_transaction:
+@@ -1556,8 +1556,6 @@ extern int	   jbd2_journal_set_features
+ 		   (journal_t *, unsigned long, unsigned long, unsigned long);
+ extern void	   jbd2_journal_clear_features
+ 		   (journal_t *, unsigned long, unsigned long, unsigned long);
+-extern int	   jbd2_journal_register_shrinker(journal_t *journal);
+-extern void	   jbd2_journal_unregister_shrinker(journal_t *journal);
+ extern int	   jbd2_journal_load       (journal_t *journal);
+ extern int	   jbd2_journal_destroy    (journal_t *);
+ extern int	   jbd2_journal_recover    (journal_t *journal);

commit 0955901908e80384592ed85aa164d7e5be6cc067
+Author: Theodore Ts'o 
+Date:   Fri Jul 2 13:21:06 2021 -0400
+
+    ext4: fix flags validity checking for EXT4_IOC_CHECKPOINT
+    
+    Use the correct bitmask when checking for any not-yet-supported flags.
+    
+    Link: https://lore.kernel.org/r/20210702173425.1276158-1-tytso@mit.edu
+    Fixes: 351a0a3fbc35 ("ext4: add ioctl EXT4_IOC_CHECKPOINT")
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Leah Rumancik 
+
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index 5730aeca563c..6eed6170aded 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -823,7 +823,7 @@ static int ext4_ioctl_checkpoint(struct file *filp, unsigned long arg)
+ 	if (!EXT4_SB(sb)->s_journal)
+ 		return -ENODEV;
+ 
+-	if (flags & ~JBD2_JOURNAL_FLUSH_VALID)
++	if (flags & ~EXT4_IOC_CHECKPOINT_FLAG_VALID)
+ 		return -EINVAL;
+ 
+ 	q = bdev_get_queue(EXT4_SB(sb)->s_journal->j_dev);

commit 61bb4a1c417e5b95d9edb4f887f131de32e419cb
+Author: Theodore Ts'o 
+Date:   Fri Jul 2 12:45:02 2021 -0400
+
+    ext4: fix possible UAF when remounting r/o a mmp-protected file system
+    
+    After commit 618f003199c6 ("ext4: fix memory leak in
+    ext4_fill_super"), after the file system is remounted read-only, there
+    is a race where the kmmpd thread can exit, causing sbi->s_mmp_tsk to
+    point at freed memory, which the call to ext4_stop_mmpd() can trip
+    over.
+    
+    Fix this by only allowing kmmpd() to exit when it is stopped via
+    ext4_stop_mmpd().
+    
+    Link: https://lore.kernel.org/r/20210707002433.3719773-1-tytso@mit.edu
+    Reported-by: Ye Bin 
+    Bug-Report-Link: <20210629143603.2166962-1-yebin10@huawei.com>
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c
+index 6cb598b549ca..bc364c119af6 100644
+--- a/fs/ext4/mmp.c
++++ b/fs/ext4/mmp.c
+@@ -156,7 +156,12 @@ static int kmmpd(void *data)
+ 	memcpy(mmp->mmp_nodename, init_utsname()->nodename,
+ 	       sizeof(mmp->mmp_nodename));
+ 
+-	while (!kthread_should_stop()) {
++	while (!kthread_should_stop() && !sb_rdonly(sb)) {
++		if (!ext4_has_feature_mmp(sb)) {
++			ext4_warning(sb, "kmmpd being stopped since MMP feature"
++				     " has been disabled.");
++			goto wait_to_exit;
++		}
+ 		if (++seq > EXT4_MMP_SEQ_MAX)
+ 			seq = 1;
+ 
+@@ -177,16 +182,6 @@ static int kmmpd(void *data)
+ 			failed_writes++;
+ 		}
+ 
+-		if (!(le32_to_cpu(es->s_feature_incompat) &
+-		    EXT4_FEATURE_INCOMPAT_MMP)) {
+-			ext4_warning(sb, "kmmpd being stopped since MMP feature"
+-				     " has been disabled.");
+-			goto exit_thread;
+-		}
+-
+-		if (sb_rdonly(sb))
+-			break;
+-
+ 		diff = jiffies - last_update_time;
+ 		if (diff < mmp_update_interval * HZ)
+ 			schedule_timeout_interruptible(mmp_update_interval *
+@@ -207,7 +202,7 @@ static int kmmpd(void *data)
+ 				ext4_error_err(sb, -retval,
+ 					       "error reading MMP data: %d",
+ 					       retval);
+-				goto exit_thread;
++				goto wait_to_exit;
+ 			}
+ 
+ 			mmp_check = (struct mmp_struct *)(bh_check->b_data);
+@@ -221,7 +216,7 @@ static int kmmpd(void *data)
+ 				ext4_error_err(sb, EBUSY, "abort");
+ 				put_bh(bh_check);
+ 				retval = -EBUSY;
+-				goto exit_thread;
++				goto wait_to_exit;
+ 			}
+ 			put_bh(bh_check);
+ 		}
+@@ -244,7 +239,13 @@ static int kmmpd(void *data)
+ 
+ 	retval = write_mmp_block(sb, bh);
+ 
+-exit_thread:
++wait_to_exit:
++	while (!kthread_should_stop()) {
++		set_current_state(TASK_INTERRUPTIBLE);
++		if (!kthread_should_stop())
++			schedule();
++	}
++	set_current_state(TASK_RUNNING);
+ 	return retval;
+ }
+ 
+@@ -391,5 +392,3 @@ int ext4_multi_mount_protect(struct super_block *sb,
+ 	brelse(bh);
+ 	return 1;
+ }
+-
+-
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index cdbe71d935e8..b8ff0399e171 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -5993,7 +5993,6 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 				 */
+ 				ext4_mark_recovery_complete(sb, es);
+ 			}
+-			ext4_stop_mmpd(sbi);
+ 		} else {
+ 			/* Make sure we can mount this feature set readwrite */
+ 			if (ext4_has_feature_readonly(sb) ||
+@@ -6107,6 +6106,9 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 	if (!test_opt(sb, BLOCK_VALIDITY) && sbi->s_system_blks)
+ 		ext4_release_system_zone(sb);
+ 
++	if (!ext4_has_feature_mmp(sb) || sb_rdonly(sb))
++		ext4_stop_mmpd(sbi);
++
+ 	/*
+ 	 * Some options can be enabled by ext4 and/or by VFS mount flag
+ 	 * either way we need to make sure it matches in both *flags and
+@@ -6140,6 +6142,8 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 	for (i = 0; i < EXT4_MAXQUOTAS; i++)
+ 		kfree(to_free[i]);
+ #endif
++	if (!ext4_has_feature_mmp(sb) || sb_rdonly(sb))
++		ext4_stop_mmpd(sbi);
+ 	kfree(orig_data);
+ 	return err;
+ }

commit 8813587a996e7d2ae160be3b79f9f70d9fef4583
+Author: Theodore Ts'o 
+Date:   Wed Jun 30 20:54:22 2021 -0400
+
+    Revert "ext4: consolidate checks for resize of bigalloc into ext4_resize_begin"
+    
+    The function ext4_resize_begin() gets called from three different
+    places, and online resize for bigalloc file systems is disallowed from
+    the old-style online resize (EXT4_IOC_GROUP_ADD and
+    EXT4_IOC_GROUP_EXTEND), but it *is* supposed to be allowed via
+    EXT4_IOC_RESIZE_FS.
+    
+    This reverts commit e9f9f61d0cdcb7f0b0b5feb2d84aa1c5894751f3.
+
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index e27f34bceb8d..5730aeca563c 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -692,6 +692,13 @@ static long ext4_ioctl_group_add(struct file *file,
+ 	if (err)
+ 		return err;
+ 
++	if (ext4_has_feature_bigalloc(sb)) {
++		ext4_msg(sb, KERN_ERR,
++			 "Online resizing not supported with bigalloc");
++		err = -EOPNOTSUPP;
++		goto group_add_out;
++	}
++
+ 	err = mnt_want_write_file(file);
+ 	if (err)
+ 		goto group_add_out;
+@@ -914,6 +921,13 @@ static long __ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 			goto group_extend_out;
+ 		}
+ 
++		if (ext4_has_feature_bigalloc(sb)) {
++			ext4_msg(sb, KERN_ERR,
++				 "Online resizing not supported with bigalloc");
++			err = -EOPNOTSUPP;
++			goto group_extend_out;
++		}
++
+ 		err = mnt_want_write_file(filp);
+ 		if (err)
+ 			goto group_extend_out;
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index fc885914c88a..7a9f1adef679 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -74,10 +74,6 @@ int ext4_resize_begin(struct super_block *sb)
+ 		return -EPERM;
+ 	}
+ 
+-	if (ext4_has_feature_bigalloc(sb)) {
+-		ext4_msg(sb, KERN_ERR, "Online resizing not supported with bigalloc");
+-		return -EOPNOTSUPP;
+-	}
+ 	if (ext4_has_feature_sparse_super2(sb)) {
+ 		ext4_msg(sb, KERN_ERR, "Online resizing not supported with sparse_super2");
+ 		return -EOPNOTSUPP;

commit 5afa7e8b70d65819245fece61a65fd753b4aae33
+Author: Theodore Ts'o 
+Date:   Sat Apr 17 23:03:50 2021 -0400
+
+    fs: fix reporting supported extra file attributes for statx()
+    
+    statx(2) notes that any attribute that is not indicated as supported
+    by stx_attributes_mask has no usable value.  Commits 801e523796004
+    ("fs: move generic stat response attr handling to vfs_getattr_nosec")
+    and 712b2698e4c02 ("fs/stat: Define DAX statx attribute") sets
+    STATX_ATTR_AUTOMOUNT and STATX_ATTR_DAX, respectively, without setting
+    stx_attributes_mask, which can cause xfstests generic/532 to fail.
+    
+    Fix this in the same way as commit 1b9598c8fb99 ("xfs: fix reporting
+    supported extra file attributes for statx()")
+    
+    Fixes: 801e523796004 ("fs: move generic stat response attr handling to vfs_getattr_nosec")
+    Fixes: 712b2698e4c02 ("fs/stat: Define DAX statx attribute")
+    Cc: stable@kernel.org
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/stat.c b/fs/stat.c
+index fbc171d038aa..1fa38bdec1a6 100644
+--- a/fs/stat.c
++++ b/fs/stat.c
+@@ -86,12 +86,20 @@ int vfs_getattr_nosec(const struct path *path, struct kstat *stat,
+ 	/* SB_NOATIME means filesystem supplies dummy atime value */
+ 	if (inode->i_sb->s_flags & SB_NOATIME)
+ 		stat->result_mask &= ~STATX_ATIME;
++
++	/*
++	 * Note: If you add another clause to set an attribute flag, please
++	 * update attributes_mask below.
++	 */
+ 	if (IS_AUTOMOUNT(inode))
+ 		stat->attributes |= STATX_ATTR_AUTOMOUNT;
+ 
+ 	if (IS_DAX(inode))
+ 		stat->attributes |= STATX_ATTR_DAX;
+ 
++	stat->attributes_mask |= (STATX_ATTR_AUTOMOUNT |
++				  STATX_ATTR_DAX);
++
+ 	mnt_userns = mnt_user_ns(path->mnt);
+ 	if (inode->i_op->getattr)
+ 		return inode->i_op->getattr(mnt_userns, path, stat,

commit 4811d9929cdae4238baf5b2522247bd2f9fa7b50
+Author: Theodore Ts'o 
+Date:   Mon Apr 12 17:19:00 2021 -0400
+
+    ext4: allow the dax flag to be set and cleared on inline directories
+    
+    This is needed to allow generic/607 to pass for file systems with the
+    inline data_feature enabled, and it allows the use of file systems
+    where the directories use inline_data, while the files are accessed
+    via DAX.
+    
+    Cc: stable@kernel.org
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 5f0c7fe32672..71d321b3b984 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -1292,7 +1292,8 @@ struct inode *__ext4_new_inode(struct user_namespace *mnt_userns,
+ 
+ 	ei->i_extra_isize = sbi->s_want_extra_isize;
+ 	ei->i_inline_off = 0;
+-	if (ext4_has_feature_inline_data(sb))
++	if (ext4_has_feature_inline_data(sb) &&
++	    (!(ei->i_flags & EXT4_DAX_FL) || S_ISDIR(mode)))
+ 		ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
+ 	ret = inode;
+ 	err = dquot_alloc_inode(inode);
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index a2cf35066f46..0796bfa72829 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -315,6 +315,12 @@ static void ext4_dax_dontcache(struct inode *inode, unsigned int flags)
+ static bool dax_compatible(struct inode *inode, unsigned int oldflags,
+ 			   unsigned int flags)
+ {
++	/* Allow the DAX flag to be changed on inline directories */
++	if (S_ISDIR(inode->i_mode)) {
++		flags &= ~EXT4_INLINE_DATA_FL;
++		oldflags &= ~EXT4_INLINE_DATA_FL;
++	}
++
+ 	if (flags & EXT4_DAX_FL) {
+ 		if ((oldflags & EXT4_DAX_MUT_EXCL) ||
+ 		     ext4_test_inode_state(inode,

commit 64395d950bc476106b39341e42ebfd4d2eb71d2c
+Author: Theodore Ts'o 
+Date:   Sun Mar 21 00:45:37 2021 -0400
+
+    ext4: initialize ret to suppress smatch warning
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 77c7c8a54da7..77c84d6f1af6 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -4382,7 +4382,7 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
+ {
+ 	struct inode *inode = file_inode(file);
+ 	handle_t *handle;
+-	int ret, ret2 = 0, ret3 = 0;
++	int ret = 0, ret2 = 0, ret3 = 0;
+ 	int retries = 0;
+ 	int depth = 0;
+ 	struct ext4_map_blocks map;

commit b5776e7524afbd4569978ff790864755c438bba7
+Author: Theodore Ts'o 
+Date:   Thu Feb 4 00:05:20 2021 -0500
+
+    ext4: fix potential htree index checksum corruption
+    
+    In the case where we need to do an interior node split, and
+    immediately afterwards, we are unable to allocate a new directory leaf
+    block due to ENOSPC, the directory index checksum's will not be filled
+    in correctly (and indeed, will not be correctly journalled).
+    
+    This looks like a bug that was introduced when we added largedir
+    support.  The original code doesn't make any sense (and should have
+    been caught in code review), but it was hidden because most of the
+    time, the index node checksum will be set by do_split().  But if
+    do_split bails out due to ENOSPC, then ext4_handle_dirty_dx_node()
+    won't get called, and so the directory index checksum field will not
+    get set, leading to:
+    
+    EXT4-fs error (device sdb): dx_probe:858: inode #6635543: block 4022: comm nfsd: Directory index failed checksum
+    
+    Google-Bug-Id: 176345532
+    Fixes: e08ac99fa2a2 ("ext4: add largedir feature")
+    Cc: Artem Blagodarenko 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index a6e28b4b5a95..115762180801 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -2411,11 +2411,10 @@ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
+ 						   (frame - 1)->bh);
+ 			if (err)
+ 				goto journal_error;
+-			if (restart) {
+-				err = ext4_handle_dirty_dx_node(handle, dir,
+-							   frame->bh);
++			err = ext4_handle_dirty_dx_node(handle, dir,
++							frame->bh);
++			if (err)
+ 				goto journal_error;
+-			}
+ 		} else {
+ 			struct dx_root *dxroot;
+ 			memcpy((char *) entries2, (char *) entries,

commit 027f14f5357279655c3ebc6d14daff8368d4f53f
+Author: Theodore Ts'o 
+Date:   Thu Jan 21 12:33:20 2021 -0500
+
+    ext4: don't try to processed freed blocks until mballoc is initialized
+    
+    If we try to make any changes via the journal between when the journal
+    is initialized, but before the multi-block allocated is initialized,
+    we will end up deferencing a NULL pointer when the journal commit
+    callback function calls ext4_process_freed_data().
+    
+    The proximate cause of this failure was commit 2d01ddc86606 ("ext4:
+    save error info to sb through journal if available") since file system
+    corruption problems detected before the call to ext4_mb_init() would
+    result in a journal commit before we aborted the mount of the file
+    system.... and we would then trigger the NULL pointer deref.
+    
+    Link: https://lore.kernel.org/r/YAm8qH/0oo2ofSMR@mit.edu
+    Reported-by: Murphy Zhou 
+    Reviewed-by: Jan Kara 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index f361f9fb40d1..071d131fadd8 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4875,7 +4875,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 
+ 	set_task_ioprio(sbi->s_journal->j_task, journal_ioprio);
+ 
+-	sbi->s_journal->j_commit_callback = ext4_journal_commit_callback;
+ 	sbi->s_journal->j_submit_inode_data_buffers =
+ 		ext4_journal_submit_inode_data_buffers;
+ 	sbi->s_journal->j_finish_inode_data_buffers =
+@@ -4987,6 +4986,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		goto failed_mount5;
+ 	}
+ 
++	/*
++	 * We can only set up the journal commit callback once
++	 * mballoc is initialized
++	 */
++	if (sbi->s_journal)
++		sbi->s_journal->j_commit_callback =
++			ext4_journal_commit_callback;
++
+ 	block = ext4_count_free_clusters(sb);
+ 	ext4_free_blocks_count_set(sbi->s_es, 
+ 				   EXT4_C2B(sbi, block));

commit 5a3b590d4b2db187faa6f06adc9a53d6199fb1f9
+Author: Theodore Ts'o 
+Date:   Thu Dec 17 13:24:15 2020 -0500
+
+    ext4: don't leak old mountpoint samples
+    
+    When the first file is opened, ext4 samples the mountpoint of the
+    filesystem in 64 bytes of the super block.  It does so using
+    strlcpy(), this means that the remaining bytes in the super block
+    string buffer are untouched.  If the mount point before had a longer
+    path than the current one, it can be reconstructed.
+    
+    Consider the case where the fs was mounted to "/media/johnjdeveloper"
+    and later to "/".  The super block buffer then contains
+    "/\x00edia/johnjdeveloper".
+    
+    This case was seen in the wild and caused confusion how the name
+    of a developer ands up on the super block of a filesystem used
+    in production...
+    
+    Fix this by using strncpy() instead of strlcpy().  The superblock
+    field is defined to be a fixed-size char array, and it is already
+    marked using __nonstring in fs/ext4/ext4.h.  The consumer of the field
+    in e2fsprogs already assumes that in the case of a 64+ byte mount
+    path, that s_last_mounted will not be NUL terminated.
+    
+    Link: https://lore.kernel.org/r/X9ujIOJG/HqMr88R@mit.edu
+    Reported-by: Richard Weinberger 
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/file.c b/fs/ext4/file.c
+index 1cd3d26e3217..349b27f0dda0 100644
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -810,7 +810,7 @@ static int ext4_sample_last_mounted(struct super_block *sb,
+ 	if (err)
+ 		goto out_journal;
+ 	lock_buffer(sbi->s_sbh);
+-	strlcpy(sbi->s_es->s_last_mounted, cp,
++	strncpy(sbi->s_es->s_last_mounted, cp,
+ 		sizeof(sbi->s_es->s_last_mounted));
+ 	ext4_superblock_csum_set(sb);
+ 	unlock_buffer(sbi->s_sbh);

commit c9200760da8a728eb9767ca41a956764b28c1310
+Author: Theodore Ts'o 
+Date:   Wed Dec 9 15:59:11 2020 -0500
+
+    ext4: check for invalid block size early when mounting a file system
+    
+    Check for valid block size directly by validating s_log_block_size; we
+    were doing this in two places.  First, by calculating blocksize via
+    BLOCK_SIZE << s_log_block_size, and then checking that the blocksize
+    was valid.  And then secondly, by checking s_log_block_size directly.
+    
+    The first check is not reliable, and can trigger an UBSAN warning if
+    s_log_block_size on a maliciously corrupted superblock is greater than
+    22.  This is harmless, since the second test will correctly reject the
+    maliciously fuzzed file system, but to make syzbot shut up, and
+    because the two checks are duplicative in any case, delete the
+    blocksize check, and move the s_log_block_size earlier in
+    ext4_fill_super().
+    
+    Signed-off-by: Theodore Ts'o 
+    Reported-by: syzbot+345b75652b1d24227443@syzkaller.appspotmail.com
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index f86220a8df50..4a16bbf0432c 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4202,18 +4202,25 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	 */
+ 	sbi->s_li_wait_mult = EXT4_DEF_LI_WAIT_MULT;
+ 
+-	blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);
+-
+-	if (blocksize == PAGE_SIZE)
+-		set_opt(sb, DIOREAD_NOLOCK);
+-
+-	if (blocksize < EXT4_MIN_BLOCK_SIZE ||
+-	    blocksize > EXT4_MAX_BLOCK_SIZE) {
++	if (le32_to_cpu(es->s_log_block_size) >
++	    (EXT4_MAX_BLOCK_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) {
+ 		ext4_msg(sb, KERN_ERR,
+-		       "Unsupported filesystem blocksize %d (%d log_block_size)",
+-			 blocksize, le32_to_cpu(es->s_log_block_size));
++			 "Invalid log block size: %u",
++			 le32_to_cpu(es->s_log_block_size));
+ 		goto failed_mount;
+ 	}
++	if (le32_to_cpu(es->s_log_cluster_size) >
++	    (EXT4_MAX_CLUSTER_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) {
++		ext4_msg(sb, KERN_ERR,
++			 "Invalid log cluster size: %u",
++			 le32_to_cpu(es->s_log_cluster_size));
++		goto failed_mount;
++	}
++
++	blocksize = EXT4_MIN_BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);
++
++	if (blocksize == PAGE_SIZE)
++		set_opt(sb, DIOREAD_NOLOCK);
+ 
+ 	if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV) {
+ 		sbi->s_inode_size = EXT4_GOOD_OLD_INODE_SIZE;
+@@ -4432,21 +4439,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	if (!ext4_feature_set_ok(sb, (sb_rdonly(sb))))
+ 		goto failed_mount;
+ 
+-	if (le32_to_cpu(es->s_log_block_size) >
+-	    (EXT4_MAX_BLOCK_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) {
+-		ext4_msg(sb, KERN_ERR,
+-			 "Invalid log block size: %u",
+-			 le32_to_cpu(es->s_log_block_size));
+-		goto failed_mount;
+-	}
+-	if (le32_to_cpu(es->s_log_cluster_size) >
+-	    (EXT4_MAX_CLUSTER_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) {
+-		ext4_msg(sb, KERN_ERR,
+-			 "Invalid log cluster size: %u",
+-			 le32_to_cpu(es->s_log_cluster_size));
+-		goto failed_mount;
+-	}
+-
+ 	if (le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) > (blocksize / 4)) {
+ 		ext4_msg(sb, KERN_ERR,
+ 			 "Number of reserved GDT blocks insanely large: %d",

commit 704c2317cab5571da0e5763cd47ad07f8900aa76
+Author: Theodore Ts'o 
+Date:   Thu Nov 19 15:36:25 2020 -0500
+
+    ext4: drop fast_commit from /proc/mounts
+    
+    The options in /proc/mounts must be valid mount options --- and
+    fast_commit is not a mount option.  Otherwise, command sequences like
+    this will fail:
+    
+        # mount /dev/vdc /vdc
+        # mkdir -p /vdc/phoronix_test_suite /pts
+        # mount --bind /vdc/phoronix_test_suite /pts
+        # mount -o remount,nodioread_nolock /pts
+        mount: /pts: mount point not mounted or bad option.
+    
+    And in the system logs, you'll find:
+    
+        EXT4-fs (vdc): Unrecognized mount option "fast_commit" or missing value
+    
+    Fixes: 995a3ed67fc8 ("ext4: add fast_commit feature and handling for extended mount options")
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 6633b20224d5..94472044f4c1 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2638,10 +2638,6 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb,
+ 	} else if (test_opt2(sb, DAX_INODE)) {
+ 		SEQ_OPTS_PUTS("dax=inode");
+ 	}
+-
+-	if (test_opt2(sb, JOURNAL_FAST_COMMIT))
+-		SEQ_OPTS_PUTS("fast_commit");
+-
+ 	ext4_show_quota_options(seq, sb);
+ 	return 0;
+ }

commit d196e229a80c39254f4adbc312f55f5198e98941
+Author: Theodore Ts'o 
+Date:   Wed Nov 11 14:24:18 2020 -0500
+
+    Revert "ext4: fix superblock checksum calculation race"
+    
+    This reverts commit acaa532687cdc3a03757defafece9c27aa667546 which can
+    result in a ext4_superblock_csum_set() trying to sleep while a
+    spinlock is being held.
+    
+    For more discussion of this issue, please see:
+    
+    https://lore.kernel.org/r/000000000000f50cb705b313ed70@google.com
+    
+    Reported-by: syzbot+7a4ba6a239b91a126c28@syzkaller.appspotmail.com
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index c3b864588a0b..6633b20224d5 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -289,18 +289,7 @@ void ext4_superblock_csum_set(struct super_block *sb)
+ 	if (!ext4_has_metadata_csum(sb))
+ 		return;
+ 
+-	/*
+-	 * Locking the superblock prevents the scenario
+-	 * where:
+-	 *  1) a first thread pauses during checksum calculation.
+-	 *  2) a second thread updates the superblock, recalculates
+-	 *     the checksum, and updates s_checksum
+-	 *  3) the first thread resumes and finishes its checksum calculation
+-	 *     and updates s_checksum with a potentially stale or torn value.
+-	 */
+-	lock_buffer(EXT4_SB(sb)->s_sbh);
+ 	es->s_checksum = ext4_superblock_csum(sb, es);
+-	unlock_buffer(EXT4_SB(sb)->s_sbh);
+ }
+ 
+ ext4_fsblk_t ext4_block_bitmap(struct super_block *sb,

commit 05d5233df85e9621597c5838e95235107eb624a2
+Author: Theodore Ts'o 
+Date:   Sat Nov 7 00:00:49 2020 -0500
+
+    jbd2: fix up sparse warnings in checkpoint code
+    
+    Add missing __acquires() and __releases() annotations.  Also, in an
+    "this should never happen" WARN_ON check, if it *does* actually
+    happen, we need to release j_state_lock since this function is always
+    supposed to release that lock.  Otherwise, things will quickly grind
+    to a halt after the WARN_ON trips.
+    
+    Fixes: 96f1e0974575 ("jbd2: avoid long hold times of j_state_lock...")
+    Cc: stable@kernel.org
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
+index 263f02ad8ebf..472932b9e6bc 100644
+--- a/fs/jbd2/checkpoint.c
++++ b/fs/jbd2/checkpoint.c
+@@ -106,6 +106,8 @@ static int __try_to_free_cp_buf(struct journal_head *jh)
+  * for a checkpoint to free up some space in the log.
+  */
+ void __jbd2_log_wait_for_space(journal_t *journal)
++__acquires(&journal->j_state_lock)
++__releases(&journal->j_state_lock)
+ {
+ 	int nblocks, space_left;
+ 	/* assert_spin_locked(&journal->j_state_lock); */
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index 43985738aa86..d54f04674e8e 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -195,8 +195,10 @@ static void wait_transaction_switching(journal_t *journal)
+ 	DEFINE_WAIT(wait);
+ 
+ 	if (WARN_ON(!journal->j_running_transaction ||
+-		    journal->j_running_transaction->t_state != T_SWITCH))
++		    journal->j_running_transaction->t_state != T_SWITCH)) {
++		read_unlock(&journal->j_state_lock);
+ 		return;
++	}
+ 	prepare_to_wait(&journal->j_wait_transaction_locked, &wait,
+ 			TASK_UNINTERRUPTIBLE);
+ 	read_unlock(&journal->j_state_lock);

commit fa329e27317f7f0762001b9fb1e76c387a9db25d
+Author: Theodore Ts'o 
+Date:   Fri Nov 6 23:59:42 2020 -0500
+
+    ext4: fix sparse warnings in fast_commit code
+    
+    Add missing __acquire() and __releases() annotations, and make
+    fc_ineligible_reasons[] static, as it is not used outside of
+    fs/ext4/fast_commit.c.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/fast_commit.c b/fs/ext4/fast_commit.c
+index 5cd6630ab1b9..f2033e13a273 100644
+--- a/fs/ext4/fast_commit.c
++++ b/fs/ext4/fast_commit.c
+@@ -156,6 +156,7 @@ void ext4_fc_init_inode(struct inode *inode)
+ 
+ /* This function must be called with sbi->s_fc_lock held. */
+ static void ext4_fc_wait_committing_inode(struct inode *inode)
++__releases(&EXT4_SB(inode->i_sb)->s_fc_lock)
+ {
+ 	wait_queue_head_t *wq;
+ 	struct ext4_inode_info *ei = EXT4_I(inode);
+@@ -911,6 +912,8 @@ static int ext4_fc_wait_inode_data_all(journal_t *journal)
+ 
+ /* Commit all the directory entry updates */
+ static int ext4_fc_commit_dentry_updates(journal_t *journal, u32 *crc)
++__acquires(&sbi->s_fc_lock)
++__releases(&sbi->s_fc_lock)
+ {
+ 	struct super_block *sb = (struct super_block *)(journal->j_private);
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+@@ -2106,7 +2109,7 @@ void ext4_fc_init(struct super_block *sb, journal_t *journal)
+ 	journal->j_fc_cleanup_callback = ext4_fc_cleanup;
+ }
+ 
+-const char *fc_ineligible_reasons[] = {
++static const char *fc_ineligible_reasons[] = {
+ 	"Extended attributes changed",
+ 	"Cross rename",
+ 	"Journal flag changed",

commit 6694875ef8045cdb1e6712ee9b68fe08763507d8
+Author: Theodore Ts'o 
+Date:   Wed Oct 28 13:39:13 2020 -0400
+
+    ext4: indicate that fast_commit is available via /sys/fs/ext4/feature/...
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c
+index 5ff33d18996a..4e27fe6ed3ae 100644
+--- a/fs/ext4/sysfs.c
++++ b/fs/ext4/sysfs.c
+@@ -315,6 +315,7 @@ EXT4_ATTR_FEATURE(casefold);
+ EXT4_ATTR_FEATURE(verity);
+ #endif
+ EXT4_ATTR_FEATURE(metadata_csum_seed);
++EXT4_ATTR_FEATURE(fast_commit);
+ 
+ static struct attribute *ext4_feat_attrs[] = {
+ 	ATTR_LIST(lazy_itable_init),
+@@ -331,6 +332,7 @@ static struct attribute *ext4_feat_attrs[] = {
+ 	ATTR_LIST(verity),
+ #endif
+ 	ATTR_LIST(metadata_csum_seed),
++	ATTR_LIST(fast_commit),
+ 	NULL,
+ };
+ ATTRIBUTE_GROUPS(ext4_feat);

commit 3d392b2676bf3199863a1e5efb2c087ad9d442a4
+Author: Theodore Ts'o 
+Date:   Fri Jul 17 00:14:40 2020 -0400
+
+    ext4: add prefetch_block_bitmaps mount option
+    
+    For file systems where we can afford to keep the buddy bitmaps cached,
+    we can speed up initial writes to large file systems by starting to
+    load the block allocation bitmaps as soon as the file system is
+    mounted.  This won't work well for _super_ large file systems, or
+    memory constrained systems, so we only enable this when it is
+    requested via a mount option.
+    
+    Addresses-Google-Bug: 159488342
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Andreas Dilger 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 26ae31a994a2..e5f0c66a6156 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1188,6 +1188,7 @@ struct ext4_inode_info {
+ #define EXT4_MOUNT_JOURNAL_CHECKSUM	0x800000 /* Journal checksums */
+ #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT	0x1000000 /* Journal Async Commit */
+ #define EXT4_MOUNT_WARN_ON_ERROR	0x2000000 /* Trigger WARN_ON on error */
++#define EXT4_MOUNT_PREFETCH_BLOCK_BITMAPS 0x4000000
+ #define EXT4_MOUNT_DELALLOC		0x8000000 /* Delalloc support */
+ #define EXT4_MOUNT_DATA_ERR_ABORT	0x10000000 /* Abort on file data write */
+ #define EXT4_MOUNT_BLOCK_VALIDITY	0x20000000 /* Block validity checking */
+@@ -2334,9 +2335,15 @@ struct ext4_lazy_init {
+ 	struct mutex		li_list_mtx;
+ };
+ 
++enum ext4_li_mode {
++	EXT4_LI_MODE_PREFETCH_BBITMAP,
++	EXT4_LI_MODE_ITABLE,
++};
++
+ struct ext4_li_request {
+ 	struct super_block	*lr_super;
+-	struct ext4_sb_info	*lr_sbi;
++	enum ext4_li_mode	lr_mode;
++	ext4_group_t		lr_first_not_zeroed;
+ 	ext4_group_t		lr_next_group;
+ 	struct list_head	lr_request;
+ 	unsigned long		lr_next_sched;
+@@ -2676,6 +2683,12 @@ extern int ext4_mb_reserve_blocks(struct super_block *, int);
+ extern void ext4_discard_preallocations(struct inode *);
+ extern int __init ext4_init_mballoc(void);
+ extern void ext4_exit_mballoc(void);
++extern ext4_group_t ext4_mb_prefetch(struct super_block *sb,
++				     ext4_group_t group,
++				     unsigned int nr, int *cnt);
++extern void ext4_mb_prefetch_fini(struct super_block *sb, ext4_group_t group,
++				  unsigned int nr);
++
+ extern void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 			     struct buffer_head *bh, ext4_fsblk_t block,
+ 			     unsigned long count, int flags);
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 9a07da53ab7b..8ecd49dd3906 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2232,9 +2232,8 @@ static int ext4_mb_good_group_nolock(struct ext4_allocation_context *ac,
+  * Start prefetching @nr block bitmaps starting at @group.
+  * Return the next group which needs to be prefetched.
+  */
+-static ext4_group_t
+-ext4_mb_prefetch(struct super_block *sb, ext4_group_t group,
+-		 unsigned int nr, int *cnt)
++ext4_group_t ext4_mb_prefetch(struct super_block *sb, ext4_group_t group,
++			      unsigned int nr, int *cnt)
+ {
+ 	ext4_group_t ngroups = ext4_get_groups_count(sb);
+ 	struct buffer_head *bh;
+@@ -2284,9 +2283,8 @@ ext4_mb_prefetch(struct super_block *sb, ext4_group_t group,
+  * waiting for the block allocation bitmap read to finish when
+  * ext4_mb_prefetch_fini is called from ext4_mb_regular_allocator().
+  */
+-static void
+-ext4_mb_prefetch_fini(struct super_block *sb, ext4_group_t group,
+-		      unsigned int nr)
++void ext4_mb_prefetch_fini(struct super_block *sb, ext4_group_t group,
++			   unsigned int nr)
+ {
+ 	while (nr-- > 0) {
+ 		struct ext4_group_desc *gdp = ext4_get_group_desc(sb, group,
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 8c00f0a09f4d..1cbe3f248faf 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1521,6 +1521,7 @@ enum {
+ 	Opt_dioread_nolock, Opt_dioread_lock,
+ 	Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable,
+ 	Opt_max_dir_size_kb, Opt_nojournal_checksum, Opt_nombcache,
++	Opt_prefetch_block_bitmaps,
+ };
+ 
+ static const match_table_t tokens = {
+@@ -1612,6 +1613,7 @@ static const match_table_t tokens = {
+ 	{Opt_test_dummy_encryption, "test_dummy_encryption"},
+ 	{Opt_nombcache, "nombcache"},
+ 	{Opt_nombcache, "no_mbcache"},	/* for backward compatibility */
++	{Opt_prefetch_block_bitmaps, "prefetch_block_bitmaps"},
+ 	{Opt_removed, "check=none"},	/* mount option from ext2/3 */
+ 	{Opt_removed, "nocheck"},	/* mount option from ext2/3 */
+ 	{Opt_removed, "reservation"},	/* mount option from ext2/3 */
+@@ -1829,6 +1831,8 @@ static const struct mount_opts {
+ 	{Opt_max_dir_size_kb, 0, MOPT_GTE0},
+ 	{Opt_test_dummy_encryption, 0, MOPT_STRING},
+ 	{Opt_nombcache, EXT4_MOUNT_NO_MBCACHE, MOPT_SET},
++	{Opt_prefetch_block_bitmaps, EXT4_MOUNT_PREFETCH_BLOCK_BITMAPS,
++	 MOPT_SET},
+ 	{Opt_err, 0, 0}
+ };
+ 
+@@ -3201,15 +3205,34 @@ static void print_daily_error_info(struct timer_list *t)
+ static int ext4_run_li_request(struct ext4_li_request *elr)
+ {
+ 	struct ext4_group_desc *gdp = NULL;
+-	ext4_group_t group, ngroups;
+-	struct super_block *sb;
++	struct super_block *sb = elr->lr_super;
++	ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count;
++	ext4_group_t group = elr->lr_next_group;
+ 	unsigned long timeout = 0;
++	unsigned int prefetch_ios = 0;
+ 	int ret = 0;
+ 
+-	sb = elr->lr_super;
+-	ngroups = EXT4_SB(sb)->s_groups_count;
++	if (elr->lr_mode == EXT4_LI_MODE_PREFETCH_BBITMAP) {
++		elr->lr_next_group = ext4_mb_prefetch(sb, group,
++				EXT4_SB(sb)->s_mb_prefetch, &prefetch_ios);
++		if (prefetch_ios)
++			ext4_mb_prefetch_fini(sb, elr->lr_next_group,
++					      prefetch_ios);
++		trace_ext4_prefetch_bitmaps(sb, group, elr->lr_next_group,
++					    prefetch_ios);
++		if (group >= elr->lr_next_group) {
++			ret = 1;
++			if (elr->lr_first_not_zeroed != ngroups &&
++			    !sb_rdonly(sb) && test_opt(sb, INIT_INODE_TABLE)) {
++				elr->lr_next_group = elr->lr_first_not_zeroed;
++				elr->lr_mode = EXT4_LI_MODE_ITABLE;
++				ret = 0;
++			}
++		}
++		return ret;
++	}
+ 
+-	for (group = elr->lr_next_group; group < ngroups; group++) {
++	for (; group < ngroups; group++) {
+ 		gdp = ext4_get_group_desc(sb, group, NULL);
+ 		if (!gdp) {
+ 			ret = 1;
+@@ -3227,9 +3250,10 @@ static int ext4_run_li_request(struct ext4_li_request *elr)
+ 		timeout = jiffies;
+ 		ret = ext4_init_inode_table(sb, group,
+ 					    elr->lr_timeout ? 0 : 1);
++		trace_ext4_lazy_itable_init(sb, group);
+ 		if (elr->lr_timeout == 0) {
+ 			timeout = (jiffies - timeout) *
+-				  elr->lr_sbi->s_li_wait_mult;
++				EXT4_SB(elr->lr_super)->s_li_wait_mult;
+ 			elr->lr_timeout = timeout;
+ 		}
+ 		elr->lr_next_sched = jiffies + elr->lr_timeout;
+@@ -3244,15 +3268,11 @@ static int ext4_run_li_request(struct ext4_li_request *elr)
+  */
+ static void ext4_remove_li_request(struct ext4_li_request *elr)
+ {
+-	struct ext4_sb_info *sbi;
+-
+ 	if (!elr)
+ 		return;
+ 
+-	sbi = elr->lr_sbi;
+-
+ 	list_del(&elr->lr_request);
+-	sbi->s_li_request = NULL;
++	EXT4_SB(elr->lr_super)->s_li_request = NULL;
+ 	kfree(elr);
+ }
+ 
+@@ -3461,7 +3481,6 @@ static int ext4_li_info_new(void)
+ static struct ext4_li_request *ext4_li_request_new(struct super_block *sb,
+ 					    ext4_group_t start)
+ {
+-	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	struct ext4_li_request *elr;
+ 
+ 	elr = kzalloc(sizeof(*elr), GFP_KERNEL);
+@@ -3469,8 +3488,13 @@ static struct ext4_li_request *ext4_li_request_new(struct super_block *sb,
+ 		return NULL;
+ 
+ 	elr->lr_super = sb;
+-	elr->lr_sbi = sbi;
+-	elr->lr_next_group = start;
++	elr->lr_first_not_zeroed = start;
++	if (test_opt(sb, PREFETCH_BLOCK_BITMAPS))
++		elr->lr_mode = EXT4_LI_MODE_PREFETCH_BBITMAP;
++	else {
++		elr->lr_mode = EXT4_LI_MODE_ITABLE;
++		elr->lr_next_group = start;
++	}
+ 
+ 	/*
+ 	 * Randomize first schedule time of the request to
+@@ -3500,8 +3524,9 @@ int ext4_register_li_request(struct super_block *sb,
+ 		goto out;
+ 	}
+ 
+-	if (first_not_zeroed == ngroups || sb_rdonly(sb) ||
+-	    !test_opt(sb, INIT_INODE_TABLE))
++	if (!test_opt(sb, PREFETCH_BLOCK_BITMAPS) &&
++	    (first_not_zeroed == ngroups || sb_rdonly(sb) ||
++	     !test_opt(sb, INIT_INODE_TABLE)))
+ 		goto out;
+ 
+ 	elr = ext4_li_request_new(sb, first_not_zeroed);
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index cbcd2e1a608d..8008d2e116b9 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -2742,6 +2742,50 @@ TRACE_EVENT(ext4_error,
+ 		  __entry->function, __entry->line)
+ );
+ 
++TRACE_EVENT(ext4_prefetch_bitmaps,
++	    TP_PROTO(struct super_block *sb, ext4_group_t group,
++		     ext4_group_t next, unsigned int prefetch_ios),
++
++	TP_ARGS(sb, group, next, prefetch_ios),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	__u32,	group			)
++		__field(	__u32,	next			)
++		__field(	__u32,	ios			)
++	),
++
++	TP_fast_assign(
++		__entry->dev	= sb->s_dev;
++		__entry->group	= group;
++		__entry->next	= next;
++		__entry->ios	= prefetch_ios;
++	),
++
++	TP_printk("dev %d,%d group %u next %u ios %u",
++		  MAJOR(__entry->dev), MINOR(__entry->dev),
++		  __entry->group, __entry->next, __entry->ios)
++);
++
++TRACE_EVENT(ext4_lazy_itable_init,
++	    TP_PROTO(struct super_block *sb, ext4_group_t group),
++
++	TP_ARGS(sb, group),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	__u32,	group			)
++	),
++
++	TP_fast_assign(
++		__entry->dev	= sb->s_dev;
++		__entry->group	= group;
++	),
++
++	TP_printk("dev %d,%d group %u",
++		  MAJOR(__entry->dev), MINOR(__entry->dev), __entry->group)
++);
++
+ #endif /* _TRACE_EXT4_H */
+ 
+ /* This part must be outside protection */

commit ab74c7b23f3770935016e3eb3ecdf1e42b73efaa
+Author: Theodore Ts'o 
+Date:   Wed Jul 15 11:48:55 2020 -0400
+
+    ext4: indicate via a block bitmap read is prefetched via a tracepoint
+    
+    Modify the ext4_read_block_bitmap_load tracepoint so that it tells us
+    whether a block bitmap is being prefetched.
+    
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Artem Blagodarenko 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 1e2b1b4093aa..48c3df47748d 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -494,7 +494,7 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group,
+ 	 * submit the buffer_head for reading
+ 	 */
+ 	set_buffer_new(bh);
+-	trace_ext4_read_block_bitmap_load(sb, block_group);
++	trace_ext4_read_block_bitmap_load(sb, block_group, ignore_locked);
+ 	bh->b_end_io = ext4_end_bitmap_read;
+ 	get_bh(bh);
+ 	submit_bh(REQ_OP_READ, REQ_META | REQ_PRIO |
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index cc41d692ae8e..cbcd2e1a608d 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -1312,18 +1312,34 @@ DEFINE_EVENT(ext4__bitmap_load, ext4_mb_buddy_bitmap_load,
+ 	TP_ARGS(sb, group)
+ );
+ 
+-DEFINE_EVENT(ext4__bitmap_load, ext4_read_block_bitmap_load,
++DEFINE_EVENT(ext4__bitmap_load, ext4_load_inode_bitmap,
+ 
+ 	TP_PROTO(struct super_block *sb, unsigned long group),
+ 
+ 	TP_ARGS(sb, group)
+ );
+ 
+-DEFINE_EVENT(ext4__bitmap_load, ext4_load_inode_bitmap,
++TRACE_EVENT(ext4_read_block_bitmap_load,
++	TP_PROTO(struct super_block *sb, unsigned long group, bool prefetch),
+ 
+-	TP_PROTO(struct super_block *sb, unsigned long group),
++	TP_ARGS(sb, group, prefetch),
+ 
+-	TP_ARGS(sb, group)
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	__u32,	group			)
++		__field(	bool,	prefetch		)
++
++	),
++
++	TP_fast_assign(
++		__entry->dev	= sb->s_dev;
++		__entry->group	= group;
++		__entry->prefetch = prefetch;
++	),
++
++	TP_printk("dev %d,%d group %u prefetch %d",
++		  MAJOR(__entry->dev), MINOR(__entry->dev),
++		  __entry->group, __entry->prefetch)
+ );
+ 
+ TRACE_EVENT(ext4_direct_IO_enter,

commit 829b37b8cddb1db75c1b7905505b90e593b15db1
+Author: Theodore Ts'o 
+Date:   Wed Jun 10 11:16:37 2020 -0400
+
+    ext4: avoid race conditions when remounting with options that change dax
+    
+    Trying to change dax mount options when remounting could allow mount
+    options to be enabled for a small amount of time, and then the mount
+    option change would be reverted.
+    
+    In the case of "mount -o remount,dax", this can cause a race where
+    files would temporarily treated as DAX --- and then not.
+    
+    Cc: stable@kernel.org
+    Reported-by: syzbot+bca9799bf129256190da@syzkaller.appspotmail.com
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index a22d67c5bc00..edf06c1bee9d 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2104,16 +2104,40 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
+ 		switch (token) {
+ 		case Opt_dax:
+ 		case Opt_dax_always:
++			if (is_remount &&
++			    (!(sbi->s_mount_opt & EXT4_MOUNT_DAX_ALWAYS) ||
++			     (sbi->s_mount_opt2 & EXT4_MOUNT2_DAX_NEVER))) {
++			fail_dax_change_remount:
++				ext4_msg(sb, KERN_ERR, "can't change "
++					 "dax mount option while remounting");
++				return -1;
++			}
++			if (is_remount &&
++			    (test_opt(sb, DATA_FLAGS) ==
++			     EXT4_MOUNT_JOURNAL_DATA)) {
++				    ext4_msg(sb, KERN_ERR, "can't mount with "
++					     "both data=journal and dax");
++				    return -1;
++			}
+ 			ext4_msg(sb, KERN_WARNING,
+ 				"DAX enabled. Warning: EXPERIMENTAL, use at your own risk");
+ 			sbi->s_mount_opt |= EXT4_MOUNT_DAX_ALWAYS;
+ 			sbi->s_mount_opt2 &= ~EXT4_MOUNT2_DAX_NEVER;
+ 			break;
+ 		case Opt_dax_never:
++			if (is_remount &&
++			    (!(sbi->s_mount_opt2 & EXT4_MOUNT2_DAX_NEVER) ||
++			     (sbi->s_mount_opt & EXT4_MOUNT_DAX_ALWAYS)))
++				goto fail_dax_change_remount;
+ 			sbi->s_mount_opt2 |= EXT4_MOUNT2_DAX_NEVER;
+ 			sbi->s_mount_opt &= ~EXT4_MOUNT_DAX_ALWAYS;
+ 			break;
+ 		case Opt_dax_inode:
++			if (is_remount &&
++			    ((sbi->s_mount_opt & EXT4_MOUNT_DAX_ALWAYS) ||
++			     (sbi->s_mount_opt2 & EXT4_MOUNT2_DAX_NEVER) ||
++			     !(sbi->s_mount_opt2 & EXT4_MOUNT2_DAX_INODE)))
++				goto fail_dax_change_remount;
+ 			sbi->s_mount_opt &= ~EXT4_MOUNT_DAX_ALWAYS;
+ 			sbi->s_mount_opt2 &= ~EXT4_MOUNT2_DAX_NEVER;
+ 			/* Strictly for printing options */
+@@ -5454,12 +5478,6 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 			err = -EINVAL;
+ 			goto restore_opts;
+ 		}
+-		if (test_opt(sb, DAX_ALWAYS)) {
+-			ext4_msg(sb, KERN_ERR, "can't mount with "
+-				 "both data=journal and dax");
+-			err = -EINVAL;
+-			goto restore_opts;
+-		}
+ 	} else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA) {
+ 		if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) {
+ 			ext4_msg(sb, KERN_ERR, "can't mount with "
+@@ -5475,18 +5493,6 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 		goto restore_opts;
+ 	}
+ 
+-	if ((sbi->s_mount_opt ^ old_opts.s_mount_opt) & EXT4_MOUNT_DAX_ALWAYS ||
+-	    (sbi->s_mount_opt2 ^ old_opts.s_mount_opt2) & EXT4_MOUNT2_DAX_NEVER ||
+-	    (sbi->s_mount_opt2 ^ old_opts.s_mount_opt2) & EXT4_MOUNT2_DAX_INODE) {
+-		ext4_msg(sb, KERN_WARNING, "warning: refusing change of "
+-			"dax mount option with busy inodes while remounting");
+-		sbi->s_mount_opt &= ~EXT4_MOUNT_DAX_ALWAYS;
+-		sbi->s_mount_opt |= old_opts.s_mount_opt & EXT4_MOUNT_DAX_ALWAYS;
+-		sbi->s_mount_opt2 &= ~(EXT4_MOUNT2_DAX_NEVER | EXT4_MOUNT2_DAX_INODE);
+-		sbi->s_mount_opt2 |= old_opts.s_mount_opt2 &
+-				     (EXT4_MOUNT2_DAX_NEVER | EXT4_MOUNT2_DAX_INODE);
+-	}
+-
+ 	if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED)
+ 		ext4_abort(sb, EXT4_ERR_ESHUTDOWN, "Abort forced by user");
+ 

commit 68cd44920d2ccf32dea1502e71dc0175c9663af1
+Merge: 6b8ed62008a4 15ee65676f1e
+Author: Theodore Ts'o 
+Date:   Thu Jun 11 10:51:44 2020 -0400
+
+    Enable ext4 support for per-file/directory dax operations
+    
+    This adds the same per-file/per-directory DAX support for ext4 as was
+    done for xfs, now that we finally have consensus over what the
+    interface should be.
+
+diff --cc fs/ext4/ext4.h
+index 9e5c332a2b94,598e00a9453f..5148cbb0b4b3
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@@ -426,13 -415,16 +426,16 @@@ struct flex_groups 
+  #define EXT4_VERITY_FL			0x00100000 /* Verity protected inode */
+  #define EXT4_EA_INODE_FL	        0x00200000 /* Inode used for large EA */
+  /* 0x00400000 was formerly EXT4_EOFBLOCKS_FL */
++ 
++ #define EXT4_DAX_FL			0x02000000 /* Inode is DAX */
++ 
+  #define EXT4_INLINE_DATA_FL		0x10000000 /* Inode has inline data. */
+  #define EXT4_PROJINHERIT_FL		0x20000000 /* Create with parents projid */
+ -#define EXT4_CASEFOLD_FL		0x40000000 /* Casefolded file */
+ +#define EXT4_CASEFOLD_FL		0x40000000 /* Casefolded directory */
+  #define EXT4_RESERVED_FL		0x80000000 /* reserved for ext4 lib */
+  
+- #define EXT4_FL_USER_VISIBLE		0x705BDFFF /* User visible flags */
+- #define EXT4_FL_USER_MODIFIABLE		0x604BC0FF /* User modifiable flags */
++ #define EXT4_FL_USER_VISIBLE		0x725BDFFF /* User visible flags */
++ #define EXT4_FL_USER_MODIFIABLE		0x624BC0FF /* User modifiable flags */
+  
+  /* Flags we can manipulate with through EXT4_IOC_FSSETXATTR */
+  #define EXT4_FL_XFLAG_VISIBLE		(EXT4_SYNC_FL | \
+@@@ -499,9 -497,9 +508,10 @@@ enum 
+  	EXT4_INODE_VERITY	= 20,	/* Verity protected inode */
+  	EXT4_INODE_EA_INODE	= 21,	/* Inode used for large EA */
+  /* 22 was formerly EXT4_INODE_EOFBLOCKS */
++ 	EXT4_INODE_DAX		= 25,	/* Inode is DAX */
+  	EXT4_INODE_INLINE_DATA	= 28,	/* Data in inode. */
+  	EXT4_INODE_PROJINHERIT	= 29,	/* Create with parents projid */
+ +	EXT4_INODE_CASEFOLD	= 30,	/* Casefolded directory */
+  	EXT4_INODE_RESERVED	= 31,	/* reserved for ext4 lib */
+  };
+  
+diff --cc fs/ext4/super.c
+index c3983f87587d,3658e3016999..a22d67c5bc00
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@@ -3978,7 -4021,12 +4022,7 @@@ static int ext4_fill_super(struct super
+  				 "both data=journal and delalloc");
+  			goto failed_mount;
+  		}
+- 		if (test_opt(sb, DAX)) {
+ -		if (test_opt(sb, DIOREAD_NOLOCK)) {
+ -			ext4_msg(sb, KERN_ERR, "can't mount with "
+ -				 "both data=journal and dioread_nolock");
+ -			goto failed_mount;
+ -		}
++ 		if (test_opt(sb, DAX_ALWAYS)) {
+  			ext4_msg(sb, KERN_ERR, "can't mount with "
+  				 "both data=journal and dax");
+  			goto failed_mount;

commit 73c384c0cdaa8ea9ca9ef2d0cff6a25930f1648e
+Author: Theodore Ts'o 
+Date:   Thu May 7 10:50:28 2020 -0700
+
+    ext4: avoid ext4_error()'s caused by ENOMEM in the truncate path
+    
+    We can't fail in the truncate path without requiring an fsck.
+    Add work around for this by using a combination of retry loops
+    and the __GFP_NOFAIL flag.
+    
+    From: Theodore Ts'o 
+    Signed-off-by: Theodore Ts'o 
+    Signed-off-by: Anna Pendleton 
+    Reviewed-by: Harshad Shirwadkar 
+    Link: https://lore.kernel.org/r/20200507175028.15061-1-pendleton@google.com
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 884ce3086486..5d901bf92ce9 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -630,6 +630,7 @@ enum {
+  */
+ #define EXT4_EX_NOCACHE				0x40000000
+ #define EXT4_EX_FORCE_CACHE			0x20000000
++#define EXT4_EX_NOFAIL				0x10000000
+ 
+ /*
+  * Flags used by ext4_free_blocks
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 3ca797faa86b..ff7eeb5a77ef 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -297,11 +297,14 @@ ext4_force_split_extent_at(handle_t *handle, struct inode *inode,
+ {
+ 	struct ext4_ext_path *path = *ppath;
+ 	int unwritten = ext4_ext_is_unwritten(path[path->p_depth].p_ext);
++	int flags = EXT4_EX_NOCACHE | EXT4_GET_BLOCKS_PRE_IO;
++
++	if (nofail)
++		flags |= EXT4_GET_BLOCKS_METADATA_NOFAIL | EXT4_EX_NOFAIL;
+ 
+ 	return ext4_split_extent_at(handle, inode, ppath, lblk, unwritten ?
+ 			EXT4_EXT_MARK_UNWRIT1|EXT4_EXT_MARK_UNWRIT2 : 0,
+-			EXT4_EX_NOCACHE | EXT4_GET_BLOCKS_PRE_IO |
+-			(nofail ? EXT4_GET_BLOCKS_METADATA_NOFAIL:0));
++			flags);
+ }
+ 
+ static int
+@@ -487,8 +490,12 @@ __read_extent_tree_block(const char *function, unsigned int line,
+ {
+ 	struct buffer_head		*bh;
+ 	int				err;
++	gfp_t				gfp_flags = __GFP_MOVABLE | GFP_NOFS;
++
++	if (flags & EXT4_EX_NOFAIL)
++		gfp_flags |= __GFP_NOFAIL;
+ 
+-	bh = sb_getblk_gfp(inode->i_sb, pblk, __GFP_MOVABLE | GFP_NOFS);
++	bh = sb_getblk_gfp(inode->i_sb, pblk, gfp_flags);
+ 	if (unlikely(!bh))
+ 		return ERR_PTR(-ENOMEM);
+ 
+@@ -837,6 +844,10 @@ ext4_find_extent(struct inode *inode, ext4_lblk_t block,
+ 	struct ext4_ext_path *path = orig_path ? *orig_path : NULL;
+ 	short int depth, i, ppos = 0;
+ 	int ret;
++	gfp_t gfp_flags = GFP_NOFS;
++
++	if (flags & EXT4_EX_NOFAIL)
++		gfp_flags |= __GFP_NOFAIL;
+ 
+ 	eh = ext_inode_hdr(inode);
+ 	depth = ext_depth(inode);
+@@ -857,7 +868,7 @@ ext4_find_extent(struct inode *inode, ext4_lblk_t block,
+ 	if (!path) {
+ 		/* account possible depth increase */
+ 		path = kcalloc(depth + 2, sizeof(struct ext4_ext_path),
+-				GFP_NOFS);
++				gfp_flags);
+ 		if (unlikely(!path))
+ 			return ERR_PTR(-ENOMEM);
+ 		path[0].p_maxdepth = depth + 1;
+@@ -1007,9 +1018,13 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
+ 	ext4_fsblk_t newblock, oldblock;
+ 	__le32 border;
+ 	ext4_fsblk_t *ablocks = NULL; /* array of allocated blocks */
++	gfp_t gfp_flags = GFP_NOFS;
+ 	int err = 0;
+ 	size_t ext_size = 0;
+ 
++	if (flags & EXT4_EX_NOFAIL)
++		gfp_flags |= __GFP_NOFAIL;
++
+ 	/* make decision: where to split? */
+ 	/* FIXME: now decision is simplest: at current extent */
+ 
+@@ -1043,7 +1058,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
+ 	 * We need this to handle errors and free blocks
+ 	 * upon them.
+ 	 */
+-	ablocks = kcalloc(depth, sizeof(ext4_fsblk_t), GFP_NOFS);
++	ablocks = kcalloc(depth, sizeof(ext4_fsblk_t), gfp_flags);
+ 	if (!ablocks)
+ 		return -ENOMEM;
+ 
+@@ -2019,7 +2034,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+ 	if (next != EXT_MAX_BLOCKS) {
+ 		ext_debug("next leaf block - %u\n", next);
+ 		BUG_ON(npath != NULL);
+-		npath = ext4_find_extent(inode, next, NULL, 0);
++		npath = ext4_find_extent(inode, next, NULL, gb_flags);
+ 		if (IS_ERR(npath))
+ 			return PTR_ERR(npath);
+ 		BUG_ON(npath->p_depth != path->p_depth);
+@@ -2792,7 +2807,8 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
+ 		ext4_fsblk_t pblk;
+ 
+ 		/* find extent for or closest extent to this block */
+-		path = ext4_find_extent(inode, end, NULL, EXT4_EX_NOCACHE);
++		path = ext4_find_extent(inode, end, NULL,
++					EXT4_EX_NOCACHE | EXT4_EX_NOFAIL);
+ 		if (IS_ERR(path)) {
+ 			ext4_journal_stop(handle);
+ 			return PTR_ERR(path);
+@@ -2878,7 +2894,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
+ 				le16_to_cpu(path[k].p_hdr->eh_entries)+1;
+ 	} else {
+ 		path = kcalloc(depth + 1, sizeof(struct ext4_ext_path),
+-			       GFP_NOFS);
++			       GFP_NOFS | __GFP_NOFAIL);
+ 		if (path == NULL) {
+ 			ext4_journal_stop(handle);
+ 			return -ENOMEM;
+@@ -3303,7 +3319,7 @@ static int ext4_split_extent(handle_t *handle,
+ 	 * Update path is required because previous ext4_split_extent_at() may
+ 	 * result in split of original leaf or extent zeroout.
+ 	 */
+-	path = ext4_find_extent(inode, map->m_lblk, ppath, 0);
++	path = ext4_find_extent(inode, map->m_lblk, ppath, flags);
+ 	if (IS_ERR(path))
+ 		return PTR_ERR(path);
+ 	depth = ext_depth(inode);
+@@ -4365,7 +4381,14 @@ int ext4_ext_truncate(handle_t *handle, struct inode *inode)
+ 	}
+ 	if (err)
+ 		return err;
+-	return ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCKS - 1);
++retry_remove_space:
++	err = ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCKS - 1);
++	if (err == -ENOMEM) {
++		cond_resched();
++		congestion_wait(BLK_RW_ASYNC, HZ/50);
++		goto retry_remove_space;
++	}
++	return err;
+ }
+ 
+ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,

commit 4bfe6cce133cad82cea04490c308795275857782
+Author: Jay Lang 
+Date:   Sun May 24 12:27:39 2020 -0400
+
+    x86/ioperm: Prevent a memory leak when fork fails
+    
+    In the copy_process() routine called by _do_fork(), failure to allocate
+    a PID (or further along in the function) will trigger an invocation to
+    exit_thread(). This is done to clean up from an earlier call to
+    copy_thread_tls(). Naturally, the child task is passed into exit_thread(),
+    however during the process, io_bitmap_exit() nullifies the parent's
+    io_bitmap rather than the child's.
+    
+    As copy_thread_tls() has been called ahead of the failure, the reference
+    count on the calling thread's io_bitmap is incremented as we would expect.
+    However, io_bitmap_exit() doesn't accept any arguments, and thus assumes
+    it should trash the current thread's io_bitmap reference rather than the
+    child's. This is pretty sneaky in practice, because in all instances but
+    this one, exit_thread() is called with respect to the current task and
+    everything works out.
+    
+    A determined attacker can issue an appropriate ioctl (i.e. KDENABIO) to
+    get a bitmap allocated, and force a clone3() syscall to fail by passing
+    in a zeroed clone_args structure. The kernel handles the erroneous struct
+    and the buggy code path is followed, and even though the parent's reference
+    to the io_bitmap is trashed, the child still holds a reference and thus
+    the structure will never be freed.
+    
+    Fix this by tweaking io_bitmap_exit() and its subroutines to accept a
+    task_struct argument which to operate on.
+    
+    Fixes: ea5f1cd7ab49 ("x86/ioperm: Remove bitmap if all permissions dropped")
+    Signed-off-by: Jay Lang 
+    Signed-off-by: Thomas Gleixner 
+    Cc: stable#@vger.kernel.org
+    Link: https://lkml.kernel.org/r/20200524162742.253727-1-jaytlang@mit.edu
+
+diff --git a/arch/x86/include/asm/io_bitmap.h b/arch/x86/include/asm/io_bitmap.h
+index 07344d82e88e..ac1a99ffbd8d 100644
+--- a/arch/x86/include/asm/io_bitmap.h
++++ b/arch/x86/include/asm/io_bitmap.h
+@@ -17,7 +17,7 @@ struct task_struct;
+ 
+ #ifdef CONFIG_X86_IOPL_IOPERM
+ void io_bitmap_share(struct task_struct *tsk);
+-void io_bitmap_exit(void);
++void io_bitmap_exit(struct task_struct *tsk);
+ 
+ void native_tss_update_io_bitmap(void);
+ 
+@@ -29,7 +29,7 @@ void native_tss_update_io_bitmap(void);
+ 
+ #else
+ static inline void io_bitmap_share(struct task_struct *tsk) { }
+-static inline void io_bitmap_exit(void) { }
++static inline void io_bitmap_exit(struct task_struct *tsk) { }
+ static inline void tss_update_io_bitmap(void) { }
+ #endif
+ 
+diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c
+index a53e7b4a7419..e2fab3ceb09f 100644
+--- a/arch/x86/kernel/ioport.c
++++ b/arch/x86/kernel/ioport.c
+@@ -33,15 +33,15 @@ void io_bitmap_share(struct task_struct *tsk)
+ 	set_tsk_thread_flag(tsk, TIF_IO_BITMAP);
+ }
+ 
+-static void task_update_io_bitmap(void)
++static void task_update_io_bitmap(struct task_struct *tsk)
+ {
+-	struct thread_struct *t = ¤t->thread;
++	struct thread_struct *t = &tsk->thread;
+ 
+ 	if (t->iopl_emul == 3 || t->io_bitmap) {
+ 		/* TSS update is handled on exit to user space */
+-		set_thread_flag(TIF_IO_BITMAP);
++		set_tsk_thread_flag(tsk, TIF_IO_BITMAP);
+ 	} else {
+-		clear_thread_flag(TIF_IO_BITMAP);
++		clear_tsk_thread_flag(tsk, TIF_IO_BITMAP);
+ 		/* Invalidate TSS */
+ 		preempt_disable();
+ 		tss_update_io_bitmap();
+@@ -49,12 +49,12 @@ static void task_update_io_bitmap(void)
+ 	}
+ }
+ 
+-void io_bitmap_exit(void)
++void io_bitmap_exit(struct task_struct *tsk)
+ {
+-	struct io_bitmap *iobm = current->thread.io_bitmap;
++	struct io_bitmap *iobm = tsk->thread.io_bitmap;
+ 
+-	current->thread.io_bitmap = NULL;
+-	task_update_io_bitmap();
++	tsk->thread.io_bitmap = NULL;
++	task_update_io_bitmap(tsk);
+ 	if (iobm && refcount_dec_and_test(&iobm->refcnt))
+ 		kfree(iobm);
+ }
+@@ -102,7 +102,7 @@ long ksys_ioperm(unsigned long from, unsigned long num, int turn_on)
+ 		if (!iobm)
+ 			return -ENOMEM;
+ 		refcount_set(&iobm->refcnt, 1);
+-		io_bitmap_exit();
++		io_bitmap_exit(current);
+ 	}
+ 
+ 	/*
+@@ -134,7 +134,7 @@ long ksys_ioperm(unsigned long from, unsigned long num, int turn_on)
+ 	}
+ 	/* All permissions dropped? */
+ 	if (max_long == UINT_MAX) {
+-		io_bitmap_exit();
++		io_bitmap_exit(current);
+ 		return 0;
+ 	}
+ 
+@@ -192,7 +192,7 @@ SYSCALL_DEFINE1(iopl, unsigned int, level)
+ 	}
+ 
+ 	t->iopl_emul = level;
+-	task_update_io_bitmap();
++	task_update_io_bitmap(current);
+ 
+ 	return 0;
+ }
+diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
+index 9da70b279dad..35638f1c5791 100644
+--- a/arch/x86/kernel/process.c
++++ b/arch/x86/kernel/process.c
+@@ -96,7 +96,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
+ }
+ 
+ /*
+- * Free current thread data structures etc..
++ * Free thread data structures etc..
+  */
+ void exit_thread(struct task_struct *tsk)
+ {
+@@ -104,7 +104,7 @@ void exit_thread(struct task_struct *tsk)
+ 	struct fpu *fpu = &t->fpu;
+ 
+ 	if (test_thread_flag(TIF_IO_BITMAP))
+-		io_bitmap_exit();
++		io_bitmap_exit(tsk);
+ 
+ 	free_vm86(t);
+ 

commit 907ea529fc4c3296701d2bfc8b831dd2a8121a34
+Author: Theodore Ts'o 
+Date:   Mon Apr 13 23:33:05 2020 -0400
+
+    ext4: convert BUG_ON's to WARN_ON's in mballoc.c
+    
+    If the in-core buddy bitmap gets corrupted (or out of sync with the
+    block bitmap), issue a WARN_ON and try to recover.  In most cases this
+    involves skipping trying to allocate out of a particular block group.
+    We can end up declaring the file system corrupted, which is fair,
+    since the file system probably should be checked before we proceed any
+    further.
+    
+    Link: https://lore.kernel.org/r/20200414035649.293164-1-tytso@mit.edu
+    Google-Bug-Id: 34811296
+    Google-Bug-Id: 34639169
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 87c85be4c12e..30d5d97548c4 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -1943,7 +1943,8 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
+ 	int free;
+ 
+ 	free = e4b->bd_info->bb_free;
+-	BUG_ON(free <= 0);
++	if (WARN_ON(free <= 0))
++		return;
+ 
+ 	i = e4b->bd_info->bb_first_free;
+ 
+@@ -1966,7 +1967,8 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
+ 		}
+ 
+ 		mb_find_extent(e4b, i, ac->ac_g_ex.fe_len, &ex);
+-		BUG_ON(ex.fe_len <= 0);
++		if (WARN_ON(ex.fe_len <= 0))
++			break;
+ 		if (free < ex.fe_len) {
+ 			ext4_grp_locked_error(sb, e4b->bd_group, 0, 0,
+ 					"%d free clusters as per "

commit a17a9d935dc4a50acefaf319d58030f1da7f115a
+Author: Theodore Ts'o 
+Date:   Mon Apr 13 22:30:52 2020 -0400
+
+    ext4: increase wait time needed before reuse of deleted inode numbers
+    
+    Current wait times have proven to be too short to protect against inode
+    reuses that lead to metadata inconsistencies.
+    
+    Now that we will retry the inode allocation if we can't find any
+    recently deleted inodes, it's a lot safer to increase the recently
+    deleted time from 5 seconds to a minute.
+    
+    Link: https://lore.kernel.org/r/20200414023925.273867-1-tytso@mit.edu
+    Google-Bug-Id: 36602237
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 9faaf32be5cc..4b8c9a9bdf0c 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -662,7 +662,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent,
+  * block has been written back to disk.  (Yes, these values are
+  * somewhat arbitrary...)
+  */
+-#define RECENTCY_MIN	5
++#define RECENTCY_MIN	60
+ #define RECENTCY_DIRTY	300
+ 
+ static int recently_deleted(struct super_block *sb, ext4_group_t group, int ino)

commit 54d3adbc29f0c7c53890da1683e629cd220d7201
+Author: Theodore Ts'o 
+Date:   Sat Mar 28 19:33:43 2020 -0400
+
+    ext4: save all error info in save_error_info() and drop ext4_set_errno()
+    
+    Using a separate function, ext4_set_errno() to set the errno is
+    problematic because it doesn't do the right thing once
+    s_last_error_errorcode is non-zero.  It's also less racy to set all of
+    the error information all at once.  (Also, as a bonus, it shrinks code
+    size slightly.)
+    
+    Link: https://lore.kernel.org/r/20200329020404.686965-1-tytso@mit.edu
+    Fixes: 878520ac45f9 ("ext4: save the error code which triggered...")
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 8fd0b3cdab4c..0e0a4d6209c7 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -516,10 +516,9 @@ int ext4_wait_block_bitmap(struct super_block *sb, ext4_group_t block_group,
+ 	wait_on_buffer(bh);
+ 	ext4_simulate_fail_bh(sb, bh, EXT4_SIM_BBITMAP_EIO);
+ 	if (!buffer_uptodate(bh)) {
+-		ext4_set_errno(sb, EIO);
+-		ext4_error(sb, "Cannot read block bitmap - "
+-			   "block_group = %u, block_bitmap = %llu",
+-			   block_group, (unsigned long long) bh->b_blocknr);
++		ext4_error_err(sb, EIO, "Cannot read block bitmap - "
++			       "block_group = %u, block_bitmap = %llu",
++			       block_group, (unsigned long long) bh->b_blocknr);
+ 		ext4_mark_group_bitmap_corrupted(sb, block_group,
+ 					EXT4_GROUP_INFO_BBITMAP_CORRUPT);
+ 		return -EIO;
+diff --git a/fs/ext4/block_validity.c b/fs/ext4/block_validity.c
+index 0a734ffb4310..16e9b2fda03a 100644
+--- a/fs/ext4/block_validity.c
++++ b/fs/ext4/block_validity.c
+@@ -166,10 +166,8 @@ static int ext4_data_block_valid_rcu(struct ext4_sb_info *sbi,
+ 
+ 	if ((start_blk <= le32_to_cpu(sbi->s_es->s_first_data_block)) ||
+ 	    (start_blk + count < start_blk) ||
+-	    (start_blk + count > ext4_blocks_count(sbi->s_es))) {
+-		sbi->s_es->s_last_error_block = cpu_to_le64(start_blk);
++	    (start_blk + count > ext4_blocks_count(sbi->s_es)))
+ 		return 0;
+-	}
+ 
+ 	if (system_blks == NULL)
+ 		return 1;
+@@ -181,10 +179,8 @@ static int ext4_data_block_valid_rcu(struct ext4_sb_info *sbi,
+ 			n = n->rb_left;
+ 		else if (start_blk >= (entry->start_blk + entry->count))
+ 			n = n->rb_right;
+-		else {
+-			sbi->s_es->s_last_error_block = cpu_to_le64(start_blk);
++		else
+ 			return 0;
+-		}
+ 	}
+ 	return 1;
+ }
+@@ -220,10 +216,12 @@ static int ext4_protect_reserved_inode(struct super_block *sb,
+ 		} else {
+ 			if (!ext4_data_block_valid_rcu(sbi, system_blks,
+ 						map.m_pblk, n)) {
+-				ext4_error(sb, "blocks %llu-%llu from inode %u "
+-					   "overlap system zone", map.m_pblk,
+-					   map.m_pblk + map.m_len - 1, ino);
+ 				err = -EFSCORRUPTED;
++				__ext4_error(sb, __func__, __LINE__, -err,
++					     map.m_pblk, "blocks %llu-%llu "
++					     "from inode %u overlap system zone",
++					     map.m_pblk,
++					     map.m_pblk + map.m_len - 1, ino);
+ 				break;
+ 			}
+ 			err = add_system_zone(system_blks, map.m_pblk, n);
+@@ -365,7 +363,6 @@ int ext4_data_block_valid(struct ext4_sb_info *sbi, ext4_fsblk_t start_blk,
+ int ext4_check_blockref(const char *function, unsigned int line,
+ 			struct inode *inode, __le32 *p, unsigned int max)
+ {
+-	struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
+ 	__le32 *bref = p;
+ 	unsigned int blk;
+ 
+@@ -379,7 +376,6 @@ int ext4_check_blockref(const char *function, unsigned int line,
+ 		if (blk &&
+ 		    unlikely(!ext4_data_block_valid(EXT4_SB(inode->i_sb),
+ 						    blk, 1))) {
+-			es->s_last_error_block = cpu_to_le64(blk);
+ 			ext4_error_inode(inode, function, line, blk,
+ 					 "invalid block");
+ 			return -EFSCORRUPTED;
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 54f0a003053b..91eb4381cae5 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2770,21 +2770,20 @@ extern const char *ext4_decode_error(struct super_block *sb, int errno,
+ extern void ext4_mark_group_bitmap_corrupted(struct super_block *sb,
+ 					     ext4_group_t block_group,
+ 					     unsigned int flags);
+-extern void ext4_set_errno(struct super_block *sb, int err);
+ 
+-extern __printf(4, 5)
+-void __ext4_error(struct super_block *, const char *, unsigned int,
++extern __printf(6, 7)
++void __ext4_error(struct super_block *, const char *, unsigned int, int, __u64,
+ 		  const char *, ...);
+-extern __printf(5, 6)
+-void __ext4_error_inode(struct inode *, const char *, unsigned int, ext4_fsblk_t,
+-		      const char *, ...);
++extern __printf(6, 7)
++void __ext4_error_inode(struct inode *, const char *, unsigned int,
++			ext4_fsblk_t, int, const char *, ...);
+ extern __printf(5, 6)
+ void __ext4_error_file(struct file *, const char *, unsigned int, ext4_fsblk_t,
+ 		     const char *, ...);
+ extern void __ext4_std_error(struct super_block *, const char *,
+ 			     unsigned int, int);
+-extern __printf(4, 5)
+-void __ext4_abort(struct super_block *, const char *, unsigned int,
++extern __printf(5, 6)
++void __ext4_abort(struct super_block *, const char *, unsigned int, int,
+ 		  const char *, ...);
+ extern __printf(4, 5)
+ void __ext4_warning(struct super_block *, const char *, unsigned int,
+@@ -2805,8 +2804,12 @@ void __ext4_grp_locked_error(const char *, unsigned int,
+ #define EXT4_ERROR_INODE(inode, fmt, a...) \
+ 	ext4_error_inode((inode), __func__, __LINE__, 0, (fmt), ## a)
+ 
+-#define EXT4_ERROR_INODE_BLOCK(inode, block, fmt, a...)			\
+-	ext4_error_inode((inode), __func__, __LINE__, (block), (fmt), ## a)
++#define EXT4_ERROR_INODE_ERR(inode, err, fmt, a...)			\
++	__ext4_error_inode((inode), __func__, __LINE__, 0, (err), (fmt), ## a)
++
++#define ext4_error_inode_block(inode, block, err, fmt, a...)		\
++	__ext4_error_inode((inode), __func__, __LINE__, (block), (err),	\
++			   (fmt), ## a)
+ 
+ #define EXT4_ERROR_FILE(file, block, fmt, a...)				\
+ 	ext4_error_file((file), __func__, __LINE__, (block), (fmt), ## a)
+@@ -2814,13 +2817,18 @@ void __ext4_grp_locked_error(const char *, unsigned int,
+ #ifdef CONFIG_PRINTK
+ 
+ #define ext4_error_inode(inode, func, line, block, fmt, ...)		\
+-	__ext4_error_inode(inode, func, line, block, fmt, ##__VA_ARGS__)
++	__ext4_error_inode(inode, func, line, block, 0, fmt, ##__VA_ARGS__)
++#define ext4_error_inode_err(inode, func, line, block, err, fmt, ...)	\
++	__ext4_error_inode((inode), (func), (line), (block), 		\
++			   (err), (fmt), ##__VA_ARGS__)
+ #define ext4_error_file(file, func, line, block, fmt, ...)		\
+ 	__ext4_error_file(file, func, line, block, fmt, ##__VA_ARGS__)
+ #define ext4_error(sb, fmt, ...)					\
+-	__ext4_error(sb, __func__, __LINE__, fmt, ##__VA_ARGS__)
+-#define ext4_abort(sb, fmt, ...)					\
+-	__ext4_abort(sb, __func__, __LINE__, fmt, ##__VA_ARGS__)
++	__ext4_error((sb), __func__, __LINE__, 0, 0, (fmt), ##__VA_ARGS__)
++#define ext4_error_err(sb, err, fmt, ...)				\
++	__ext4_error((sb), __func__, __LINE__, (err), 0, (fmt), ##__VA_ARGS__)
++#define ext4_abort(sb, err, fmt, ...)					\
++	__ext4_abort((sb), __func__, __LINE__, (err), (fmt), ##__VA_ARGS__)
+ #define ext4_warning(sb, fmt, ...)					\
+ 	__ext4_warning(sb, __func__, __LINE__, fmt, ##__VA_ARGS__)
+ #define ext4_warning_inode(inode, fmt, ...)				\
+@@ -2838,7 +2846,12 @@ void __ext4_grp_locked_error(const char *, unsigned int,
+ #define ext4_error_inode(inode, func, line, block, fmt, ...)		\
+ do {									\
+ 	no_printk(fmt, ##__VA_ARGS__);					\
+-	__ext4_error_inode(inode, "", 0, block, " ");			\
++	__ext4_error_inode(inode, "", 0, block, 0, " ");		\
++} while (0)
++#define ext4_error_inode_err(inode, func, line, block, err, fmt, ...)	\
++do {									\
++	no_printk(fmt, ##__VA_ARGS__);					\
++	__ext4_error_inode(inode, "", 0, block, err, " ");		\
+ } while (0)
+ #define ext4_error_file(file, func, line, block, fmt, ...)		\
+ do {									\
+@@ -2848,12 +2861,17 @@ do {									\
+ #define ext4_error(sb, fmt, ...)					\
+ do {									\
+ 	no_printk(fmt, ##__VA_ARGS__);					\
+-	__ext4_error(sb, "", 0, " ");					\
++	__ext4_error(sb, "", 0, 0, 0, " ");				\
++} while (0)
++#define ext4_error_err(sb, err, fmt, ...)				\
++do {									\
++	no_printk(fmt, ##__VA_ARGS__);					\
++	__ext4_error(sb, "", 0, err, 0, " ");				\
+ } while (0)
+-#define ext4_abort(sb, fmt, ...)					\
++#define ext4_abort(sb, err, fmt, ...)					\
+ do {									\
+ 	no_printk(fmt, ##__VA_ARGS__);					\
+-	__ext4_abort(sb, "", 0, " ");					\
++	__ext4_abort(sb, "", 0, err, " ");				\
+ } while (0)
+ #define ext4_warning(sb, fmt, ...)					\
+ do {									\
+diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
+index ee3755c3110a..7f16e1af8d5c 100644
+--- a/fs/ext4/ext4_jbd2.c
++++ b/fs/ext4/ext4_jbd2.c
+@@ -80,8 +80,7 @@ static int ext4_journal_check_start(struct super_block *sb)
+ 	 * take the FS itself readonly cleanly.
+ 	 */
+ 	if (journal && is_journal_aborted(journal)) {
+-		ext4_set_errno(sb, -journal->j_errno);
+-		ext4_abort(sb, "Detected aborted journal");
++		ext4_abort(sb, -journal->j_errno, "Detected aborted journal");
+ 		return -EROFS;
+ 	}
+ 	return 0;
+@@ -272,8 +271,7 @@ int __ext4_forget(const char *where, unsigned int line, handle_t *handle,
+ 	if (err) {
+ 		ext4_journal_abort_handle(where, line, __func__,
+ 					  bh, handle, err);
+-		ext4_set_errno(inode->i_sb, -err);
+-		__ext4_abort(inode->i_sb, where, line,
++		__ext4_abort(inode->i_sb, where, line, -err,
+ 			   "error %d when attempting revoke", err);
+ 	}
+ 	BUFFER_TRACE(bh, "exit");
+@@ -343,11 +341,8 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
+ 				struct ext4_super_block *es;
+ 
+ 				es = EXT4_SB(inode->i_sb)->s_es;
+-				es->s_last_error_block =
+-					cpu_to_le64(bh->b_blocknr);
+-				ext4_set_errno(inode->i_sb, EIO);
+-				ext4_error_inode(inode, where, line,
+-						 bh->b_blocknr,
++				ext4_error_inode_err(inode, where, line,
++						     bh->b_blocknr, EIO,
+ 					"IO error syncing itable block");
+ 				err = -EIO;
+ 			}
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 0e86bc611f07..031752cfb6f7 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -349,8 +349,8 @@ static int ext4_valid_extent_idx(struct inode *inode,
+ }
+ 
+ static int ext4_valid_extent_entries(struct inode *inode,
+-				struct ext4_extent_header *eh,
+-				int depth)
++				     struct ext4_extent_header *eh,
++				     ext4_fsblk_t *pblk, int depth)
+ {
+ 	unsigned short entries;
+ 	if (eh->eh_entries == 0)
+@@ -361,8 +361,6 @@ static int ext4_valid_extent_entries(struct inode *inode,
+ 	if (depth == 0) {
+ 		/* leaf entries */
+ 		struct ext4_extent *ext = EXT_FIRST_EXTENT(eh);
+-		struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
+-		ext4_fsblk_t pblock = 0;
+ 		ext4_lblk_t lblock = 0;
+ 		ext4_lblk_t prev = 0;
+ 		int len = 0;
+@@ -374,8 +372,7 @@ static int ext4_valid_extent_entries(struct inode *inode,
+ 			lblock = le32_to_cpu(ext->ee_block);
+ 			len = ext4_ext_get_actual_len(ext);
+ 			if ((lblock <= prev) && prev) {
+-				pblock = ext4_ext_pblock(ext);
+-				es->s_last_error_block = cpu_to_le64(pblock);
++				*pblk = ext4_ext_pblock(ext);
+ 				return 0;
+ 			}
+ 			ext++;
+@@ -422,7 +419,7 @@ static int __ext4_ext_check(const char *function, unsigned int line,
+ 		error_msg = "invalid eh_entries";
+ 		goto corrupted;
+ 	}
+-	if (!ext4_valid_extent_entries(inode, eh, depth)) {
++	if (!ext4_valid_extent_entries(inode, eh, &pblk, depth)) {
+ 		error_msg = "invalid extent entries";
+ 		goto corrupted;
+ 	}
+@@ -440,14 +437,14 @@ static int __ext4_ext_check(const char *function, unsigned int line,
+ 	return 0;
+ 
+ corrupted:
+-	ext4_set_errno(inode->i_sb, -err);
+-	ext4_error_inode(inode, function, line, 0,
+-			 "pblk %llu bad header/extent: %s - magic %x, "
+-			 "entries %u, max %u(%u), depth %u(%u)",
+-			 (unsigned long long) pblk, error_msg,
+-			 le16_to_cpu(eh->eh_magic),
+-			 le16_to_cpu(eh->eh_entries), le16_to_cpu(eh->eh_max),
+-			 max, le16_to_cpu(eh->eh_depth), depth);
++	ext4_error_inode_err(inode, function, line, 0, -err,
++			     "pblk %llu bad header/extent: %s - magic %x, "
++			     "entries %u, max %u(%u), depth %u(%u)",
++			     (unsigned long long) pblk, error_msg,
++			     le16_to_cpu(eh->eh_magic),
++			     le16_to_cpu(eh->eh_entries),
++			     le16_to_cpu(eh->eh_max),
++			     max, le16_to_cpu(eh->eh_depth), depth);
+ 	return err;
+ }
+ 
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 9652a0eadd1c..b420c9dc444d 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -196,10 +196,9 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
+ 	ext4_simulate_fail_bh(sb, bh, EXT4_SIM_IBITMAP_EIO);
+ 	if (!buffer_uptodate(bh)) {
+ 		put_bh(bh);
+-		ext4_set_errno(sb, EIO);
+-		ext4_error(sb, "Cannot read inode bitmap - "
+-			   "block_group = %u, inode_bitmap = %llu",
+-			   block_group, bitmap_blk);
++		ext4_error_err(sb, EIO, "Cannot read inode bitmap - "
++			       "block_group = %u, inode_bitmap = %llu",
++			       block_group, bitmap_blk);
+ 		ext4_mark_group_bitmap_corrupted(sb, block_group,
+ 				EXT4_GROUP_INFO_IBITMAP_CORRUPT);
+ 		return ERR_PTR(-EIO);
+@@ -1244,9 +1243,9 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
+ 	inode = ext4_iget(sb, ino, EXT4_IGET_NORMAL);
+ 	if (IS_ERR(inode)) {
+ 		err = PTR_ERR(inode);
+-		ext4_set_errno(sb, -err);
+-		ext4_error(sb, "couldn't read orphan inode %lu (err %d)",
+-			   ino, err);
++		ext4_error_err(sb, -err,
++			       "couldn't read orphan inode %lu (err %d)",
++			       ino, err);
+ 		return inode;
+ 	}
+ 
+diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
+index 569fc68e8975..107f0043f67f 100644
+--- a/fs/ext4/indirect.c
++++ b/fs/ext4/indirect.c
+@@ -1019,7 +1019,7 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
+ 			 * (should be rare).
+ 			 */
+ 			if (!bh) {
+-				EXT4_ERROR_INODE_BLOCK(inode, nr,
++				ext4_error_inode_block(inode, nr, EIO,
+ 						       "Read failure");
+ 				continue;
+ 			}
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index e7db6ee23277..f35e289e17aa 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -98,10 +98,9 @@ int ext4_get_max_inline_size(struct inode *inode)
+ 
+ 	error = ext4_get_inode_loc(inode, &iloc);
+ 	if (error) {
+-		ext4_set_errno(inode->i_sb, -error);
+-		ext4_error_inode(inode, __func__, __LINE__, 0,
+-				 "can't get inode location %lu",
+-				 inode->i_ino);
++		ext4_error_inode_err(inode, __func__, __LINE__, 0, -error,
++				     "can't get inode location %lu",
++				     inode->i_ino);
+ 		return 0;
+ 	}
+ 
+@@ -1762,9 +1761,9 @@ bool empty_inline_dir(struct inode *dir, int *has_inline_data)
+ 
+ 	err = ext4_get_inode_loc(dir, &iloc);
+ 	if (err) {
+-		ext4_set_errno(dir->i_sb, -err);
+-		EXT4_ERROR_INODE(dir, "error %d getting inode %lu block",
+-				 err, dir->i_ino);
++		EXT4_ERROR_INODE_ERR(dir, -err,
++				     "error %d getting inode %lu block",
++				     err, dir->i_ino);
+ 		return true;
+ 	}
+ 
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index f6aebb792178..e416096fc081 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -269,10 +269,9 @@ void ext4_evict_inode(struct inode *inode)
+ 	if (inode->i_blocks) {
+ 		err = ext4_truncate(inode);
+ 		if (err) {
+-			ext4_set_errno(inode->i_sb, -err);
+-			ext4_error(inode->i_sb,
+-				   "couldn't truncate inode %lu (err %d)",
+-				   inode->i_ino, err);
++			ext4_error_err(inode->i_sb, -err,
++				       "couldn't truncate inode %lu (err %d)",
++				       inode->i_ino, err);
+ 			goto stop_handle;
+ 		}
+ 	}
+@@ -2478,10 +2477,9 @@ static int mpage_map_and_submit_extent(handle_t *handle,
+ 		up_write(&EXT4_I(inode)->i_data_sem);
+ 		err2 = ext4_mark_inode_dirty(handle, inode);
+ 		if (err2) {
+-			ext4_set_errno(inode->i_sb, -err2);
+-			ext4_error(inode->i_sb,
+-				   "Failed to mark inode %lu dirty",
+-				   inode->i_ino);
++			ext4_error_err(inode->i_sb, -err2,
++				       "Failed to mark inode %lu dirty",
++				       inode->i_ino);
+ 		}
+ 		if (!err)
+ 			err = err2;
+@@ -4382,8 +4380,7 @@ static int __ext4_get_inode_loc(struct inode *inode,
+ 		wait_on_buffer(bh);
+ 		if (!buffer_uptodate(bh)) {
+ 		simulate_eio:
+-			ext4_set_errno(inode->i_sb, EIO);
+-			EXT4_ERROR_INODE_BLOCK(inode, block,
++			ext4_error_inode_block(inode, block, EIO,
+ 					       "unable to read itable block");
+ 			brelse(bh);
+ 			return -EIO;
+@@ -4535,7 +4532,7 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
+ 	    (ino > le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count))) {
+ 		if (flags & EXT4_IGET_HANDLE)
+ 			return ERR_PTR(-ESTALE);
+-		__ext4_error(sb, function, line,
++		__ext4_error(sb, function, line, EFSCORRUPTED, 0,
+ 			     "inode #%lu: comm %s: iget: illegal inode #",
+ 			     ino, current->comm);
+ 		return ERR_PTR(-EFSCORRUPTED);
+@@ -4598,9 +4595,8 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
+ 
+ 	if (!ext4_inode_csum_verify(inode, raw_inode, ei) ||
+ 	    ext4_simulate_fail(sb, EXT4_SIM_INODE_CRC)) {
+-		ext4_set_errno(inode->i_sb, EFSBADCRC);
+-		ext4_error_inode(inode, function, line, 0,
+-				 "iget: checksum invalid");
++		ext4_error_inode_err(inode, function, line, 0, EFSBADCRC,
++				     "iget: checksum invalid");
+ 		ret = -EFSBADCRC;
+ 		goto bad_inode;
+ 	}
+@@ -5149,9 +5145,8 @@ int ext4_write_inode(struct inode *inode, struct writeback_control *wbc)
+ 		if (wbc->sync_mode == WB_SYNC_ALL && !wbc->for_sync)
+ 			sync_dirty_buffer(iloc.bh);
+ 		if (buffer_req(iloc.bh) && !buffer_uptodate(iloc.bh)) {
+-			ext4_set_errno(inode->i_sb, EIO);
+-			EXT4_ERROR_INODE_BLOCK(inode, iloc.bh->b_blocknr,
+-					 "IO error syncing inode");
++			ext4_error_inode_block(inode, iloc.bh->b_blocknr, EIO,
++					       "IO error syncing inode");
+ 			err = -EIO;
+ 		}
+ 		brelse(iloc.bh);
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 97cd1a2201a2..87c85be4c12e 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -3921,9 +3921,9 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
+ 	bitmap_bh = ext4_read_block_bitmap(sb, group);
+ 	if (IS_ERR(bitmap_bh)) {
+ 		err = PTR_ERR(bitmap_bh);
+-		ext4_set_errno(sb, -err);
+-		ext4_error(sb, "Error %d reading block bitmap for %u",
+-			   err, group);
++		ext4_error_err(sb, -err,
++			       "Error %d reading block bitmap for %u",
++			       err, group);
+ 		return 0;
+ 	}
+ 
+@@ -4090,18 +4090,16 @@ void ext4_discard_preallocations(struct inode *inode)
+ 		err = ext4_mb_load_buddy_gfp(sb, group, &e4b,
+ 					     GFP_NOFS|__GFP_NOFAIL);
+ 		if (err) {
+-			ext4_set_errno(sb, -err);
+-			ext4_error(sb, "Error %d loading buddy information for %u",
+-				   err, group);
++			ext4_error_err(sb, -err, "Error %d loading buddy information for %u",
++				       err, group);
+ 			continue;
+ 		}
+ 
+ 		bitmap_bh = ext4_read_block_bitmap(sb, group);
+ 		if (IS_ERR(bitmap_bh)) {
+ 			err = PTR_ERR(bitmap_bh);
+-			ext4_set_errno(sb, -err);
+-			ext4_error(sb, "Error %d reading block bitmap for %u",
+-					err, group);
++			ext4_error_err(sb, -err, "Error %d reading block bitmap for %u",
++				       err, group);
+ 			ext4_mb_unload_buddy(&e4b);
+ 			continue;
+ 		}
+@@ -4355,9 +4353,8 @@ ext4_mb_discard_lg_preallocations(struct super_block *sb,
+ 		err = ext4_mb_load_buddy_gfp(sb, group, &e4b,
+ 					     GFP_NOFS|__GFP_NOFAIL);
+ 		if (err) {
+-			ext4_set_errno(sb, -err);
+-			ext4_error(sb, "Error %d loading buddy information for %u",
+-				   err, group);
++			ext4_error_err(sb, -err, "Error %d loading buddy information for %u",
++				       err, group);
+ 			continue;
+ 		}
+ 		ext4_lock_group(sb, group);
+diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c
+index 87f7551c5132..d34cb8c46655 100644
+--- a/fs/ext4/mmp.c
++++ b/fs/ext4/mmp.c
+@@ -175,8 +175,8 @@ static int kmmpd(void *data)
+ 		 */
+ 		if (retval) {
+ 			if ((failed_writes % 60) == 0) {
+-				ext4_set_errno(sb, -retval);
+-				ext4_error(sb, "Error writing to MMP block");
++				ext4_error_err(sb, -retval,
++					       "Error writing to MMP block");
+ 			}
+ 			failed_writes++;
+ 		}
+@@ -208,9 +208,9 @@ static int kmmpd(void *data)
+ 
+ 			retval = read_mmp_block(sb, &bh_check, mmp_block);
+ 			if (retval) {
+-				ext4_set_errno(sb, -retval);
+-				ext4_error(sb, "error reading MMP data: %d",
+-					   retval);
++				ext4_error_err(sb, -retval,
++					       "error reading MMP data: %d",
++					       retval);
+ 				goto exit_thread;
+ 			}
+ 
+@@ -222,8 +222,7 @@ static int kmmpd(void *data)
+ 					     "Error while updating MMP info. "
+ 					     "The filesystem seems to have been"
+ 					     " multiply mounted.");
+-				ext4_set_errno(sb, EBUSY);
+-				ext4_error(sb, "abort");
++				ext4_error_err(sb, EBUSY, "abort");
+ 				put_bh(bh_check);
+ 				retval = -EBUSY;
+ 				goto exit_thread;
+diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
+index 30ce3dc69378..1ed86fb6c302 100644
+--- a/fs/ext4/move_extent.c
++++ b/fs/ext4/move_extent.c
+@@ -422,8 +422,8 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode,
+ 					   block_len_in_page, 0, &err2);
+ 	ext4_double_up_write_data_sem(orig_inode, donor_inode);
+ 	if (replaced_count != block_len_in_page) {
+-		EXT4_ERROR_INODE_BLOCK(orig_inode, (sector_t)(orig_blk_offset),
+-				       "Unable to copy data block,"
++		ext4_error_inode_block(orig_inode, (sector_t)(orig_blk_offset),
++				       EIO, "Unable to copy data block,"
+ 				       " data will be lost.");
+ 		*err = -EIO;
+ 	}
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 5f0a758956f6..a8aca4772aaa 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -160,9 +160,9 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
+ 		    !ext4_simulate_fail(inode->i_sb, EXT4_SIM_DIRBLOCK_CRC))
+ 			set_buffer_verified(bh);
+ 		else {
+-			ext4_set_errno(inode->i_sb, EFSBADCRC);
+-			ext4_error_inode(inode, func, line, block,
+-					 "Directory index failed checksum");
++			ext4_error_inode_err(inode, func, line, block,
++					     EFSBADCRC,
++					     "Directory index failed checksum");
+ 			brelse(bh);
+ 			return ERR_PTR(-EFSBADCRC);
+ 		}
+@@ -172,9 +172,9 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
+ 		    !ext4_simulate_fail(inode->i_sb, EXT4_SIM_DIRBLOCK_CRC))
+ 			set_buffer_verified(bh);
+ 		else {
+-			ext4_set_errno(inode->i_sb, EFSBADCRC);
+-			ext4_error_inode(inode, func, line, block,
+-					 "Directory block failed checksum");
++			ext4_error_inode_err(inode, func, line, block,
++					     EFSBADCRC,
++					     "Directory block failed checksum");
+ 			brelse(bh);
+ 			return ERR_PTR(-EFSBADCRC);
+ 		}
+@@ -1532,9 +1532,9 @@ static struct buffer_head *__ext4_find_entry(struct inode *dir,
+ 			goto next;
+ 		wait_on_buffer(bh);
+ 		if (!buffer_uptodate(bh)) {
+-			ext4_set_errno(sb, EIO);
+-			EXT4_ERROR_INODE(dir, "reading directory lblock %lu",
+-					 (unsigned long) block);
++			EXT4_ERROR_INODE_ERR(dir, EIO,
++					     "reading directory lblock %lu",
++					     (unsigned long) block);
+ 			brelse(bh);
+ 			ret = ERR_PTR(-EIO);
+ 			goto cleanup_and_exit;
+@@ -1543,9 +1543,9 @@ static struct buffer_head *__ext4_find_entry(struct inode *dir,
+ 		    !is_dx_internal_node(dir, block,
+ 					 (struct ext4_dir_entry *)bh->b_data) &&
+ 		    !ext4_dirblock_csum_verify(dir, bh)) {
+-			ext4_set_errno(sb, EFSBADCRC);
+-			EXT4_ERROR_INODE(dir, "checksumming directory "
+-					 "block %lu", (unsigned long)block);
++			EXT4_ERROR_INODE_ERR(dir, EFSBADCRC,
++					     "checksumming directory "
++					     "block %lu", (unsigned long)block);
+ 			brelse(bh);
+ 			ret = ERR_PTR(-EFSBADCRC);
+ 			goto cleanup_and_exit;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 0153ae330c86..1dc22825fdf7 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -335,10 +335,12 @@ static time64_t __ext4_get_tstamp(__le32 *lo, __u8 *hi)
+ #define ext4_get_tstamp(es, tstamp) \
+ 	__ext4_get_tstamp(&(es)->tstamp, &(es)->tstamp ## _hi)
+ 
+-static void __save_error_info(struct super_block *sb, const char *func,
+-			    unsigned int line)
++static void __save_error_info(struct super_block *sb, int error,
++			      __u32 ino, __u64 block,
++			      const char *func, unsigned int line)
+ {
+ 	struct ext4_super_block *es = EXT4_SB(sb)->s_es;
++	int err;
+ 
+ 	EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
+ 	if (bdev_read_only(sb->s_bdev))
+@@ -347,8 +349,62 @@ static void __save_error_info(struct super_block *sb, const char *func,
+ 	ext4_update_tstamp(es, s_last_error_time);
+ 	strncpy(es->s_last_error_func, func, sizeof(es->s_last_error_func));
+ 	es->s_last_error_line = cpu_to_le32(line);
+-	if (es->s_last_error_errcode == 0)
+-		es->s_last_error_errcode = EXT4_ERR_EFSCORRUPTED;
++	es->s_last_error_ino = cpu_to_le32(ino);
++	es->s_last_error_block = cpu_to_le64(block);
++	switch (error) {
++	case EIO:
++		err = EXT4_ERR_EIO;
++		break;
++	case ENOMEM:
++		err = EXT4_ERR_ENOMEM;
++		break;
++	case EFSBADCRC:
++		err = EXT4_ERR_EFSBADCRC;
++		break;
++	case 0:
++	case EFSCORRUPTED:
++		err = EXT4_ERR_EFSCORRUPTED;
++		break;
++	case ENOSPC:
++		err = EXT4_ERR_ENOSPC;
++		break;
++	case ENOKEY:
++		err = EXT4_ERR_ENOKEY;
++		break;
++	case EROFS:
++		err = EXT4_ERR_EROFS;
++		break;
++	case EFBIG:
++		err = EXT4_ERR_EFBIG;
++		break;
++	case EEXIST:
++		err = EXT4_ERR_EEXIST;
++		break;
++	case ERANGE:
++		err = EXT4_ERR_ERANGE;
++		break;
++	case EOVERFLOW:
++		err = EXT4_ERR_EOVERFLOW;
++		break;
++	case EBUSY:
++		err = EXT4_ERR_EBUSY;
++		break;
++	case ENOTDIR:
++		err = EXT4_ERR_ENOTDIR;
++		break;
++	case ENOTEMPTY:
++		err = EXT4_ERR_ENOTEMPTY;
++		break;
++	case ESHUTDOWN:
++		err = EXT4_ERR_ESHUTDOWN;
++		break;
++	case EFAULT:
++		err = EXT4_ERR_EFAULT;
++		break;
++	default:
++		err = EXT4_ERR_UNKNOWN;
++	}
++	es->s_last_error_errcode = err;
+ 	if (!es->s_first_error_time) {
+ 		es->s_first_error_time = es->s_last_error_time;
+ 		es->s_first_error_time_hi = es->s_last_error_time_hi;
+@@ -368,10 +424,11 @@ static void __save_error_info(struct super_block *sb, const char *func,
+ 	le32_add_cpu(&es->s_error_count, 1);
+ }
+ 
+-static void save_error_info(struct super_block *sb, const char *func,
+-			    unsigned int line)
++static void save_error_info(struct super_block *sb, int error,
++			    __u32 ino, __u64 block,
++			    const char *func, unsigned int line)
+ {
+-	__save_error_info(sb, func, line);
++	__save_error_info(sb, error, ino, block, func, line);
+ 	if (!bdev_read_only(sb->s_bdev))
+ 		ext4_commit_super(sb, 1);
+ }
+@@ -478,7 +535,8 @@ static void ext4_handle_error(struct super_block *sb)
+ 			     "EXT4-fs error")
+ 
+ void __ext4_error(struct super_block *sb, const char *function,
+-		  unsigned int line, const char *fmt, ...)
++		  unsigned int line, int error, __u64 block,
++		  const char *fmt, ...)
+ {
+ 	struct va_format vaf;
+ 	va_list args;
+@@ -496,24 +554,21 @@ void __ext4_error(struct super_block *sb, const char *function,
+ 		       sb->s_id, function, line, current->comm, &vaf);
+ 		va_end(args);
+ 	}
+-	save_error_info(sb, function, line);
++	save_error_info(sb, error, 0, block, function, line);
+ 	ext4_handle_error(sb);
+ }
+ 
+ void __ext4_error_inode(struct inode *inode, const char *function,
+-			unsigned int line, ext4_fsblk_t block,
++			unsigned int line, ext4_fsblk_t block, int error,
+ 			const char *fmt, ...)
+ {
+ 	va_list args;
+ 	struct va_format vaf;
+-	struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
+ 
+ 	if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
+ 		return;
+ 
+ 	trace_ext4_error(inode->i_sb, function, line);
+-	es->s_last_error_ino = cpu_to_le32(inode->i_ino);
+-	es->s_last_error_block = cpu_to_le64(block);
+ 	if (ext4_error_ratelimit(inode->i_sb)) {
+ 		va_start(args, fmt);
+ 		vaf.fmt = fmt;
+@@ -530,7 +585,8 @@ void __ext4_error_inode(struct inode *inode, const char *function,
+ 			       current->comm, &vaf);
+ 		va_end(args);
+ 	}
+-	save_error_info(inode->i_sb, function, line);
++	save_error_info(inode->i_sb, error, inode->i_ino, block,
++			function, line);
+ 	ext4_handle_error(inode->i_sb);
+ }
+ 
+@@ -549,7 +605,6 @@ void __ext4_error_file(struct file *file, const char *function,
+ 
+ 	trace_ext4_error(inode->i_sb, function, line);
+ 	es = EXT4_SB(inode->i_sb)->s_es;
+-	es->s_last_error_ino = cpu_to_le32(inode->i_ino);
+ 	if (ext4_error_ratelimit(inode->i_sb)) {
+ 		path = file_path(file, pathname, sizeof(pathname));
+ 		if (IS_ERR(path))
+@@ -571,7 +626,8 @@ void __ext4_error_file(struct file *file, const char *function,
+ 			       current->comm, path, &vaf);
+ 		va_end(args);
+ 	}
+-	save_error_info(inode->i_sb, function, line);
++	save_error_info(inode->i_sb, EFSCORRUPTED, inode->i_ino, block,
++			function, line);
+ 	ext4_handle_error(inode->i_sb);
+ }
+ 
+@@ -615,66 +671,6 @@ const char *ext4_decode_error(struct super_block *sb, int errno,
+ 	return errstr;
+ }
+ 
+-void ext4_set_errno(struct super_block *sb, int err)
+-{
+-	if (err < 0)
+-		err = -err;
+-
+-	switch (err) {
+-	case EIO:
+-		err = EXT4_ERR_EIO;
+-		break;
+-	case ENOMEM:
+-		err = EXT4_ERR_ENOMEM;
+-		break;
+-	case EFSBADCRC:
+-		err = EXT4_ERR_EFSBADCRC;
+-		break;
+-	case EFSCORRUPTED:
+-		err = EXT4_ERR_EFSCORRUPTED;
+-		break;
+-	case ENOSPC:
+-		err = EXT4_ERR_ENOSPC;
+-		break;
+-	case ENOKEY:
+-		err = EXT4_ERR_ENOKEY;
+-		break;
+-	case EROFS:
+-		err = EXT4_ERR_EROFS;
+-		break;
+-	case EFBIG:
+-		err = EXT4_ERR_EFBIG;
+-		break;
+-	case EEXIST:
+-		err = EXT4_ERR_EEXIST;
+-		break;
+-	case ERANGE:
+-		err = EXT4_ERR_ERANGE;
+-		break;
+-	case EOVERFLOW:
+-		err = EXT4_ERR_EOVERFLOW;
+-		break;
+-	case EBUSY:
+-		err = EXT4_ERR_EBUSY;
+-		break;
+-	case ENOTDIR:
+-		err = EXT4_ERR_ENOTDIR;
+-		break;
+-	case ENOTEMPTY:
+-		err = EXT4_ERR_ENOTEMPTY;
+-		break;
+-	case ESHUTDOWN:
+-		err = EXT4_ERR_ESHUTDOWN;
+-		break;
+-	case EFAULT:
+-		err = EXT4_ERR_EFAULT;
+-		break;
+-	default:
+-		err = EXT4_ERR_UNKNOWN;
+-	}
+-	EXT4_SB(sb)->s_es->s_last_error_errcode = err;
+-}
+-
+ /* __ext4_std_error decodes expected errors from journaling functions
+  * automatically and invokes the appropriate error response.  */
+ 
+@@ -699,8 +695,7 @@ void __ext4_std_error(struct super_block *sb, const char *function,
+ 		       sb->s_id, function, line, errstr);
+ 	}
+ 
+-	ext4_set_errno(sb, -errno);
+-	save_error_info(sb, function, line);
++	save_error_info(sb, -errno, 0, 0, function, line);
+ 	ext4_handle_error(sb);
+ }
+ 
+@@ -715,7 +710,7 @@ void __ext4_std_error(struct super_block *sb, const char *function,
+  */
+ 
+ void __ext4_abort(struct super_block *sb, const char *function,
+-		unsigned int line, const char *fmt, ...)
++		  unsigned int line, int error, const char *fmt, ...)
+ {
+ 	struct va_format vaf;
+ 	va_list args;
+@@ -723,7 +718,7 @@ void __ext4_abort(struct super_block *sb, const char *function,
+ 	if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
+ 		return;
+ 
+-	save_error_info(sb, function, line);
++	save_error_info(sb, error, 0, 0, function, line);
+ 	va_start(args, fmt);
+ 	vaf.fmt = fmt;
+ 	vaf.va = &args;
+@@ -742,7 +737,6 @@ void __ext4_abort(struct super_block *sb, const char *function,
+ 		sb->s_flags |= SB_RDONLY;
+ 		if (EXT4_SB(sb)->s_journal)
+ 			jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO);
+-		save_error_info(sb, function, line);
+ 	}
+ 	if (test_opt(sb, ERRORS_PANIC) && !system_going_down()) {
+ 		if (EXT4_SB(sb)->s_journal &&
+@@ -816,15 +810,12 @@ __acquires(bitlock)
+ {
+ 	struct va_format vaf;
+ 	va_list args;
+-	struct ext4_super_block *es = EXT4_SB(sb)->s_es;
+ 
+ 	if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
+ 		return;
+ 
+ 	trace_ext4_error(sb, function, line);
+-	es->s_last_error_ino = cpu_to_le32(ino);
+-	es->s_last_error_block = cpu_to_le64(block);
+-	__save_error_info(sb, function, line);
++	__save_error_info(sb, EFSCORRUPTED, ino, block, function, line);
+ 
+ 	if (ext4_error_ratelimit(sb)) {
+ 		va_start(args, fmt);
+@@ -1037,8 +1028,7 @@ static void ext4_put_super(struct super_block *sb)
+ 		err = jbd2_journal_destroy(sbi->s_journal);
+ 		sbi->s_journal = NULL;
+ 		if ((err < 0) && !aborted) {
+-			ext4_set_errno(sb, -err);
+-			ext4_abort(sb, "Couldn't clean up the journal");
++			ext4_abort(sb, -err, "Couldn't clean up the journal");
+ 		}
+ 	}
+ 
+@@ -5452,7 +5442,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 	}
+ 
+ 	if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED)
+-		ext4_abort(sb, "Abort forced by user");
++		ext4_abort(sb, EXT4_ERR_ESHUTDOWN, "Abort forced by user");
+ 
+ 	sb->s_flags = (sb->s_flags & ~SB_POSIXACL) |
+ 		(test_opt(sb, POSIX_ACL) ? SB_POSIXACL : 0);
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 8cac7d95c3ad..21df43a25328 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -245,7 +245,7 @@ __ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh,
+ 					 bh->b_data);
+ errout:
+ 	if (error)
+-		__ext4_error_inode(inode, function, line, 0,
++		__ext4_error_inode(inode, function, line, 0, -error,
+ 				   "corrupted xattr block %llu",
+ 				   (unsigned long long) bh->b_blocknr);
+ 	else
+@@ -269,7 +269,7 @@ __xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header,
+ 	error = ext4_xattr_check_entries(IFIRST(header), end, IFIRST(header));
+ errout:
+ 	if (error)
+-		__ext4_error_inode(inode, function, line, 0,
++		__ext4_error_inode(inode, function, line, 0, -error,
+ 				   "corrupted in-inode xattr");
+ 	return error;
+ }
+@@ -2880,9 +2880,9 @@ int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode,
+ 		if (IS_ERR(bh)) {
+ 			error = PTR_ERR(bh);
+ 			if (error == -EIO) {
+-				ext4_set_errno(inode->i_sb, EIO);
+-				EXT4_ERROR_INODE(inode, "block %llu read error",
+-						 EXT4_I(inode)->i_file_acl);
++				EXT4_ERROR_INODE_ERR(inode, EIO,
++						     "block %llu read error",
++						     EXT4_I(inode)->i_file_acl);
+ 			}
+ 			bh = NULL;
+ 			goto cleanup;

commit 3918e0667bbac99400b44fa5aef3f8be2eeada4a
+Author: Theodore Ts'o 
+Date:   Sun Feb 23 14:54:58 2020 -0500
+
+    dm thin metadata: fix lockdep complaint
+    
+    [ 3934.173244] ======================================================
+    [ 3934.179572] WARNING: possible circular locking dependency detected
+    [ 3934.185884] 5.4.21-xfstests #1 Not tainted
+    [ 3934.190151] ------------------------------------------------------
+    [ 3934.196673] dmsetup/8897 is trying to acquire lock:
+    [ 3934.201688] ffffffffbce82b18 (shrinker_rwsem){++++}, at: unregister_shrinker+0x22/0x80
+    [ 3934.210268]
+                   but task is already holding lock:
+    [ 3934.216489] ffff92a10cc5e1d0 (&pmd->root_lock){++++}, at: dm_pool_metadata_close+0xba/0x120
+    [ 3934.225083]
+                   which lock already depends on the new lock.
+    
+    [ 3934.564165] Chain exists of:
+                     shrinker_rwsem --> &journal->j_checkpoint_mutex --> &pmd->root_lock
+    
+    For a more detailed lockdep report, please see:
+    
+            https://lore.kernel.org/r/20200220234519.GA620489@mit.edu
+    
+    We shouldn't need to hold the lock while are just tearing down and
+    freeing the whole metadata pool structure.
+    
+    Fixes: 44d8ebf436399a4 ("dm thin metadata: use pool locking at end of dm_pool_metadata_close")
+    Signed-off-by: Theodore Ts'o 
+    Signed-off-by: Mike Snitzer 
+
+diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
+index fc9947d6210c..76b6b323bf4b 100644
+--- a/drivers/md/dm-thin-metadata.c
++++ b/drivers/md/dm-thin-metadata.c
+@@ -960,9 +960,9 @@ int dm_pool_metadata_close(struct dm_pool_metadata *pmd)
+ 			DMWARN("%s: __commit_transaction() failed, error = %d",
+ 			       __func__, r);
+ 	}
++	pmd_write_unlock(pmd);
+ 	if (!pmd->fail_io)
+ 		__destroy_persistent_data_objects(pmd);
+-	pmd_write_unlock(pmd);
+ 
+ 	kfree(pmd);
+ 	return 0;

commit 1d0c3924a92e69bfa91163bda83c12a994b4d106
+Author: Theodore Ts'o 
+Date:   Sat Feb 15 16:40:37 2020 -0500
+
+    ext4: fix potential race between online resizing and write operations
+    
+    During an online resize an array of pointers to buffer heads gets
+    replaced so it can get enlarged.  If there is a racing block
+    allocation or deallocation which uses the old array, and the old array
+    has gotten reused this can lead to a GPF or some other random kernel
+    memory getting modified.
+    
+    Link: https://bugzilla.kernel.org/show_bug.cgi?id=206443
+    Link: https://lore.kernel.org/r/20200221053458.730016-2-tytso@mit.edu
+    Reported-by: Suraj Jitindar Singh 
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 5f993a411251..8fd0b3cdab4c 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -270,6 +270,7 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
+ 	ext4_group_t ngroups = ext4_get_groups_count(sb);
+ 	struct ext4_group_desc *desc;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
++	struct buffer_head *bh_p;
+ 
+ 	if (block_group >= ngroups) {
+ 		ext4_error(sb, "block_group >= groups_count - block_group = %u,"
+@@ -280,7 +281,14 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
+ 
+ 	group_desc = block_group >> EXT4_DESC_PER_BLOCK_BITS(sb);
+ 	offset = block_group & (EXT4_DESC_PER_BLOCK(sb) - 1);
+-	if (!sbi->s_group_desc[group_desc]) {
++	bh_p = sbi_array_rcu_deref(sbi, s_group_desc, group_desc);
++	/*
++	 * sbi_array_rcu_deref returns with rcu unlocked, this is ok since
++	 * the pointer being dereferenced won't be dereferenced again. By
++	 * looking at the usage in add_new_gdb() the value isn't modified,
++	 * just the pointer, and so it remains valid.
++	 */
++	if (!bh_p) {
+ 		ext4_error(sb, "Group descriptor not loaded - "
+ 			   "block_group = %u, group_desc = %u, desc = %u",
+ 			   block_group, group_desc, offset);
+@@ -288,10 +296,10 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
+ 	}
+ 
+ 	desc = (struct ext4_group_desc *)(
+-		(__u8 *)sbi->s_group_desc[group_desc]->b_data +
++		(__u8 *)bh_p->b_data +
+ 		offset * EXT4_DESC_SIZE(sb));
+ 	if (bh)
+-		*bh = sbi->s_group_desc[group_desc];
++		*bh = bh_p;
+ 	return desc;
+ }
+ 
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 480badcf2783..b51003f75568 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1400,7 +1400,7 @@ struct ext4_sb_info {
+ 	loff_t s_bitmap_maxbytes;	/* max bytes for bitmap files */
+ 	struct buffer_head * s_sbh;	/* Buffer containing the super block */
+ 	struct ext4_super_block *s_es;	/* Pointer to the super block in the buffer */
+-	struct buffer_head **s_group_desc;
++	struct buffer_head * __rcu *s_group_desc;
+ 	unsigned int s_mount_opt;
+ 	unsigned int s_mount_opt2;
+ 	unsigned int s_mount_flags;
+@@ -1576,6 +1576,23 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
+ 		 ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count));
+ }
+ 
++/*
++ * Returns: sbi->field[index]
++ * Used to access an array element from the following sbi fields which require
++ * rcu protection to avoid dereferencing an invalid pointer due to reassignment
++ * - s_group_desc
++ * - s_group_info
++ * - s_flex_group
++ */
++#define sbi_array_rcu_deref(sbi, field, index)				   \
++({									   \
++	typeof(*((sbi)->field)) _v;					   \
++	rcu_read_lock();						   \
++	_v = ((typeof(_v)*)rcu_dereference((sbi)->field))[index];	   \
++	rcu_read_unlock();						   \
++	_v;								   \
++})
++
+ /*
+  * Simulate_fail codes
+  */
+@@ -2730,6 +2747,7 @@ extern int ext4_generic_delete_entry(handle_t *handle,
+ extern bool ext4_empty_dir(struct inode *inode);
+ 
+ /* resize.c */
++extern void ext4_kvfree_array_rcu(void *to_free);
+ extern int ext4_group_add(struct super_block *sb,
+ 				struct ext4_new_group_data *input);
+ extern int ext4_group_extend(struct super_block *sb,
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 86a2500ed292..536cc9f38091 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -17,6 +17,33 @@
+ 
+ #include "ext4_jbd2.h"
+ 
++struct ext4_rcu_ptr {
++	struct rcu_head rcu;
++	void *ptr;
++};
++
++static void ext4_rcu_ptr_callback(struct rcu_head *head)
++{
++	struct ext4_rcu_ptr *ptr;
++
++	ptr = container_of(head, struct ext4_rcu_ptr, rcu);
++	kvfree(ptr->ptr);
++	kfree(ptr);
++}
++
++void ext4_kvfree_array_rcu(void *to_free)
++{
++	struct ext4_rcu_ptr *ptr = kzalloc(sizeof(*ptr), GFP_KERNEL);
++
++	if (ptr) {
++		ptr->ptr = to_free;
++		call_rcu(&ptr->rcu, ext4_rcu_ptr_callback);
++		return;
++	}
++	synchronize_rcu();
++	kvfree(to_free);
++}
++
+ int ext4_resize_begin(struct super_block *sb)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+@@ -542,8 +569,8 @@ static int setup_new_flex_group_blocks(struct super_block *sb,
+ 				brelse(gdb);
+ 				goto out;
+ 			}
+-			memcpy(gdb->b_data, sbi->s_group_desc[j]->b_data,
+-			       gdb->b_size);
++			memcpy(gdb->b_data, sbi_array_rcu_deref(sbi,
++				s_group_desc, j)->b_data, gdb->b_size);
+ 			set_buffer_uptodate(gdb);
+ 
+ 			err = ext4_handle_dirty_metadata(handle, NULL, gdb);
+@@ -860,13 +887,15 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ 	}
+ 	brelse(dind);
+ 
+-	o_group_desc = EXT4_SB(sb)->s_group_desc;
++	rcu_read_lock();
++	o_group_desc = rcu_dereference(EXT4_SB(sb)->s_group_desc);
+ 	memcpy(n_group_desc, o_group_desc,
+ 	       EXT4_SB(sb)->s_gdb_count * sizeof(struct buffer_head *));
++	rcu_read_unlock();
+ 	n_group_desc[gdb_num] = gdb_bh;
+-	EXT4_SB(sb)->s_group_desc = n_group_desc;
++	rcu_assign_pointer(EXT4_SB(sb)->s_group_desc, n_group_desc);
+ 	EXT4_SB(sb)->s_gdb_count++;
+-	kvfree(o_group_desc);
++	ext4_kvfree_array_rcu(o_group_desc);
+ 
+ 	le16_add_cpu(&es->s_reserved_gdt_blocks, -1);
+ 	err = ext4_handle_dirty_super(handle, sb);
+@@ -909,9 +938,11 @@ static int add_new_gdb_meta_bg(struct super_block *sb,
+ 		return err;
+ 	}
+ 
+-	o_group_desc = EXT4_SB(sb)->s_group_desc;
++	rcu_read_lock();
++	o_group_desc = rcu_dereference(EXT4_SB(sb)->s_group_desc);
+ 	memcpy(n_group_desc, o_group_desc,
+ 	       EXT4_SB(sb)->s_gdb_count * sizeof(struct buffer_head *));
++	rcu_read_unlock();
+ 	n_group_desc[gdb_num] = gdb_bh;
+ 
+ 	BUFFER_TRACE(gdb_bh, "get_write_access");
+@@ -922,9 +953,9 @@ static int add_new_gdb_meta_bg(struct super_block *sb,
+ 		return err;
+ 	}
+ 
+-	EXT4_SB(sb)->s_group_desc = n_group_desc;
++	rcu_assign_pointer(EXT4_SB(sb)->s_group_desc, n_group_desc);
+ 	EXT4_SB(sb)->s_gdb_count++;
+-	kvfree(o_group_desc);
++	ext4_kvfree_array_rcu(o_group_desc);
+ 	return err;
+ }
+ 
+@@ -1188,7 +1219,8 @@ static int ext4_add_new_descs(handle_t *handle, struct super_block *sb,
+ 		 * use non-sparse filesystems anymore.  This is already checked above.
+ 		 */
+ 		if (gdb_off) {
+-			gdb_bh = sbi->s_group_desc[gdb_num];
++			gdb_bh = sbi_array_rcu_deref(sbi, s_group_desc,
++						     gdb_num);
+ 			BUFFER_TRACE(gdb_bh, "get_write_access");
+ 			err = ext4_journal_get_write_access(handle, gdb_bh);
+ 
+@@ -1270,7 +1302,7 @@ static int ext4_setup_new_descs(handle_t *handle, struct super_block *sb,
+ 		/*
+ 		 * get_write_access() has been called on gdb_bh by ext4_add_new_desc().
+ 		 */
+-		gdb_bh = sbi->s_group_desc[gdb_num];
++		gdb_bh = sbi_array_rcu_deref(sbi, s_group_desc, gdb_num);
+ 		/* Update group descriptor block for new group */
+ 		gdp = (struct ext4_group_desc *)(gdb_bh->b_data +
+ 						 gdb_off * EXT4_DESC_SIZE(sb));
+@@ -1497,7 +1529,8 @@ static int ext4_flex_group_add(struct super_block *sb,
+ 		for (; gdb_num <= gdb_num_end; gdb_num++) {
+ 			struct buffer_head *gdb_bh;
+ 
+-			gdb_bh = sbi->s_group_desc[gdb_num];
++			gdb_bh = sbi_array_rcu_deref(sbi, s_group_desc,
++						     gdb_num);
+ 			if (old_gdb == gdb_bh->b_blocknr)
+ 				continue;
+ 			update_backups(sb, gdb_bh->b_blocknr, gdb_bh->b_data,
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index f464dff09774..e00bcc19099f 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1014,6 +1014,7 @@ static void ext4_put_super(struct super_block *sb)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	struct ext4_super_block *es = sbi->s_es;
++	struct buffer_head **group_desc;
+ 	int aborted = 0;
+ 	int i, err;
+ 
+@@ -1046,9 +1047,12 @@ static void ext4_put_super(struct super_block *sb)
+ 	if (!sb_rdonly(sb))
+ 		ext4_commit_super(sb, 1);
+ 
++	rcu_read_lock();
++	group_desc = rcu_dereference(sbi->s_group_desc);
+ 	for (i = 0; i < sbi->s_gdb_count; i++)
+-		brelse(sbi->s_group_desc[i]);
+-	kvfree(sbi->s_group_desc);
++		brelse(group_desc[i]);
++	kvfree(group_desc);
++	rcu_read_unlock();
+ 	kvfree(sbi->s_flex_groups);
+ 	percpu_counter_destroy(&sbi->s_freeclusters_counter);
+ 	percpu_counter_destroy(&sbi->s_freeinodes_counter);
+@@ -3634,7 +3638,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ {
+ 	struct dax_device *dax_dev = fs_dax_get_by_bdev(sb->s_bdev);
+ 	char *orig_data = kstrdup(data, GFP_KERNEL);
+-	struct buffer_head *bh;
++	struct buffer_head *bh, **group_desc;
+ 	struct ext4_super_block *es = NULL;
+ 	struct ext4_sb_info *sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
+ 	ext4_fsblk_t block;
+@@ -4290,9 +4294,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 			goto failed_mount;
+ 		}
+ 	}
+-	sbi->s_group_desc = kvmalloc_array(db_count,
+-					   sizeof(struct buffer_head *),
+-					   GFP_KERNEL);
++	rcu_assign_pointer(sbi->s_group_desc,
++			   kvmalloc_array(db_count,
++					  sizeof(struct buffer_head *),
++					  GFP_KERNEL));
+ 	if (sbi->s_group_desc == NULL) {
+ 		ext4_msg(sb, KERN_ERR, "not enough memory");
+ 		ret = -ENOMEM;
+@@ -4308,14 +4313,19 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	}
+ 
+ 	for (i = 0; i < db_count; i++) {
++		struct buffer_head *bh;
++
+ 		block = descriptor_loc(sb, logical_sb_block, i);
+-		sbi->s_group_desc[i] = sb_bread_unmovable(sb, block);
+-		if (!sbi->s_group_desc[i]) {
++		bh = sb_bread_unmovable(sb, block);
++		if (!bh) {
+ 			ext4_msg(sb, KERN_ERR,
+ 			       "can't read group descriptor %d", i);
+ 			db_count = i;
+ 			goto failed_mount2;
+ 		}
++		rcu_read_lock();
++		rcu_dereference(sbi->s_group_desc)[i] = bh;
++		rcu_read_unlock();
+ 	}
+ 	sbi->s_gdb_count = db_count;
+ 	if (!ext4_check_descriptors(sb, logical_sb_block, &first_not_zeroed)) {
+@@ -4717,9 +4727,12 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	if (sbi->s_mmp_tsk)
+ 		kthread_stop(sbi->s_mmp_tsk);
+ failed_mount2:
++	rcu_read_lock();
++	group_desc = rcu_dereference(sbi->s_group_desc);
+ 	for (i = 0; i < db_count; i++)
+-		brelse(sbi->s_group_desc[i]);
+-	kvfree(sbi->s_group_desc);
++		brelse(group_desc[i]);
++	kvfree(group_desc);
++	rcu_read_unlock();
+ failed_mount:
+ 	if (sbi->s_chksum_driver)
+ 		crypto_free_shash(sbi->s_chksum_driver);

commit d65d87a07476aa17df2dcb3ad18c22c154315bec
+Author: Theodore Ts'o 
+Date:   Fri Feb 14 18:11:19 2020 -0500
+
+    ext4: improve explanation of a mount failure caused by a misconfigured kernel
+    
+    If CONFIG_QFMT_V2 is not enabled, but CONFIG_QUOTA is enabled, when a
+    user tries to mount a file system with the quota or project quota
+    enabled, the kernel will emit a very confusing messsage:
+    
+        EXT4-fs warning (device vdc): ext4_enable_quotas:5914: Failed to enable quota tracking (type=0, err=-3). Please run e2fsck to fix.
+        EXT4-fs (vdc): mount failed
+    
+    We will now report an explanatory message indicating which kernel
+    configuration options have to be enabled, to avoid customer/sysadmin
+    confusion.
+    
+    Link: https://lore.kernel.org/r/20200215012738.565735-1-tytso@mit.edu
+    Google-Bug-Id: 149093531
+    Fixes: 7c319d328505b778 ("ext4: make quota as first class supported feature")
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index b0b9150c9773..f131eaa52f22 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3009,17 +3009,11 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly)
+ 		return 0;
+ 	}
+ 
+-#ifndef CONFIG_QUOTA
+-	if (ext4_has_feature_quota(sb) && !readonly) {
++#if !defined(CONFIG_QUOTA) || !defined(CONFIG_QFMT_V2)
++	if (!readonly && (ext4_has_feature_quota(sb) ||
++			  ext4_has_feature_project(sb))) {
+ 		ext4_msg(sb, KERN_ERR,
+-			 "Filesystem with quota feature cannot be mounted RDWR "
+-			 "without CONFIG_QUOTA");
+-		return 0;
+-	}
+-	if (ext4_has_feature_project(sb) && !readonly) {
+-		ext4_msg(sb, KERN_ERR,
+-			 "Filesystem with project quota feature cannot be mounted RDWR "
+-			 "without CONFIG_QUOTA");
++			 "The kernel was not built with CONFIG_QUOTA and CONFIG_QFMT_V2");
+ 		return 0;
+ 	}
+ #endif  /* CONFIG_QUOTA */

commit 4f97a68192bd33b9963b400759cef0ca5963af00
+Author: Theodore Ts'o 
+Date:   Thu Feb 6 17:35:01 2020 -0500
+
+    ext4: fix support for inode sizes > 1024 bytes
+    
+    A recent commit, 9803387c55f7 ("ext4: validate the
+    debug_want_extra_isize mount option at parse time"), moved mount-time
+    checks around.  One of those changes moved the inode size check before
+    the blocksize variable was set to the blocksize of the file system.
+    After 9803387c55f7 was set to the minimum allowable blocksize, which
+    in practice on most systems would be 1024 bytes.  This cuased file
+    systems with inode sizes larger than 1024 bytes to be rejected with a
+    message:
+    
+    EXT4-fs (sdXX): unsupported inode size: 4096
+    
+    Fixes: 9803387c55f7 ("ext4: validate the debug_want_extra_isize mount option at parse time")
+    Link: https://lore.kernel.org/r/20200206225252.GA3673@mit.edu
+    Reported-by: Herbert Poetzl 
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index f23367a779e8..b0b9150c9773 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3814,6 +3814,15 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	 */
+ 	sbi->s_li_wait_mult = EXT4_DEF_LI_WAIT_MULT;
+ 
++	blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);
++	if (blocksize < EXT4_MIN_BLOCK_SIZE ||
++	    blocksize > EXT4_MAX_BLOCK_SIZE) {
++		ext4_msg(sb, KERN_ERR,
++		       "Unsupported filesystem blocksize %d (%d log_block_size)",
++			 blocksize, le32_to_cpu(es->s_log_block_size));
++		goto failed_mount;
++	}
++
+ 	if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV) {
+ 		sbi->s_inode_size = EXT4_GOOD_OLD_INODE_SIZE;
+ 		sbi->s_first_ino = EXT4_GOOD_OLD_FIRST_INO;
+@@ -3831,6 +3840,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 			ext4_msg(sb, KERN_ERR,
+ 			       "unsupported inode size: %d",
+ 			       sbi->s_inode_size);
++			ext4_msg(sb, KERN_ERR, "blocksize: %d", blocksize);
+ 			goto failed_mount;
+ 		}
+ 		/*
+@@ -4033,14 +4043,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	if (!ext4_feature_set_ok(sb, (sb_rdonly(sb))))
+ 		goto failed_mount;
+ 
+-	blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);
+-	if (blocksize < EXT4_MIN_BLOCK_SIZE ||
+-	    blocksize > EXT4_MAX_BLOCK_SIZE) {
+-		ext4_msg(sb, KERN_ERR,
+-		       "Unsupported filesystem blocksize %d (%d log_block_size)",
+-			 blocksize, le32_to_cpu(es->s_log_block_size));
+-		goto failed_mount;
+-	}
+ 	if (le32_to_cpu(es->s_log_block_size) >
+ 	    (EXT4_MAX_BLOCK_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) {
+ 		ext4_msg(sb, KERN_ERR,

commit 68f23b89067fdf187763e75a56087550624fdbee
+Author: Theodore Ts'o 
+Date:   Thu Jan 30 22:11:04 2020 -0800
+
+    memcg: fix a crash in wb_workfn when a device disappears
+    
+    Without memcg, there is a one-to-one mapping between the bdi and
+    bdi_writeback structures.  In this world, things are fairly
+    straightforward; the first thing bdi_unregister() does is to shutdown
+    the bdi_writeback structure (or wb), and part of that writeback ensures
+    that no other work queued against the wb, and that the wb is fully
+    drained.
+    
+    With memcg, however, there is a one-to-many relationship between the bdi
+    and bdi_writeback structures; that is, there are multiple wb objects
+    which can all point to a single bdi.  There is a refcount which prevents
+    the bdi object from being released (and hence, unregistered).  So in
+    theory, the bdi_unregister() *should* only get called once its refcount
+    goes to zero (bdi_put will drop the refcount, and when it is zero,
+    release_bdi gets called, which calls bdi_unregister).
+    
+    Unfortunately, del_gendisk() in block/gen_hd.c never got the memo about
+    the Brave New memcg World, and calls bdi_unregister directly.  It does
+    this without informing the file system, or the memcg code, or anything
+    else.  This causes the root wb associated with the bdi to be
+    unregistered, but none of the memcg-specific wb's are shutdown.  So when
+    one of these wb's are woken up to do delayed work, they try to
+    dereference their wb->bdi->dev to fetch the device name, but
+    unfortunately bdi->dev is now NULL, thanks to the bdi_unregister()
+    called by del_gendisk().  As a result, *boom*.
+    
+    Fortunately, it looks like the rest of the writeback path is perfectly
+    happy with bdi->dev and bdi->owner being NULL, so the simplest fix is to
+    create a bdi_dev_name() function which can handle bdi->dev being NULL.
+    This also allows us to bulletproof the writeback tracepoints to prevent
+    them from dereferencing a NULL pointer and crashing the kernel if one is
+    tracing with memcg's enabled, and an iSCSI device dies or a USB storage
+    stick is pulled.
+    
+    The most common way of triggering this will be hotremoval of a device
+    while writeback with memcg enabled is going on.  It was triggering
+    several times a day in a heavily loaded production environment.
+    
+    Google Bug Id: 145475544
+    
+    Link: https://lore.kernel.org/r/20191227194829.150110-1-tytso@mit.edu
+    Link: http://lkml.kernel.org/r/20191228005211.163952-1-tytso@mit.edu
+    Signed-off-by: Theodore Ts'o 
+    Cc: Chris Mason 
+    Cc: Tejun Heo 
+    Cc: Jens Axboe 
+    Cc: 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
+index 335607b8c5c0..76ac9c7d32ec 100644
+--- a/fs/fs-writeback.c
++++ b/fs/fs-writeback.c
+@@ -2063,7 +2063,7 @@ void wb_workfn(struct work_struct *work)
+ 						struct bdi_writeback, dwork);
+ 	long pages_written;
+ 
+-	set_worker_desc("flush-%s", dev_name(wb->bdi->dev));
++	set_worker_desc("flush-%s", bdi_dev_name(wb->bdi));
+ 	current->flags |= PF_SWAPWRITE;
+ 
+ 	if (likely(!current_is_workqueue_rescuer() ||
+diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
+index 97967ce06de3..f88197c1ffc2 100644
+--- a/include/linux/backing-dev.h
++++ b/include/linux/backing-dev.h
+@@ -13,6 +13,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -504,4 +505,13 @@ static inline int bdi_rw_congested(struct backing_dev_info *bdi)
+ 				  (1 << WB_async_congested));
+ }
+ 
++extern const char *bdi_unknown_name;
++
++static inline const char *bdi_dev_name(struct backing_dev_info *bdi)
++{
++	if (!bdi || !bdi->dev)
++		return bdi_unknown_name;
++	return dev_name(bdi->dev);
++}
++
+ #endif	/* _LINUX_BACKING_DEV_H */
+diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h
+index ef50be4e5e6c..d94def25e4dc 100644
+--- a/include/trace/events/writeback.h
++++ b/include/trace/events/writeback.h
+@@ -67,8 +67,8 @@ DECLARE_EVENT_CLASS(writeback_page_template,
+ 
+ 	TP_fast_assign(
+ 		strscpy_pad(__entry->name,
+-			    mapping ? dev_name(inode_to_bdi(mapping->host)->dev) : "(unknown)",
+-			    32);
++			    bdi_dev_name(mapping ? inode_to_bdi(mapping->host) :
++					 NULL), 32);
+ 		__entry->ino = mapping ? mapping->host->i_ino : 0;
+ 		__entry->index = page->index;
+ 	),
+@@ -111,8 +111,7 @@ DECLARE_EVENT_CLASS(writeback_dirty_inode_template,
+ 		struct backing_dev_info *bdi = inode_to_bdi(inode);
+ 
+ 		/* may be called for files on pseudo FSes w/ unregistered bdi */
+-		strscpy_pad(__entry->name,
+-			    bdi->dev ? dev_name(bdi->dev) : "(unknown)", 32);
++		strscpy_pad(__entry->name, bdi_dev_name(bdi), 32);
+ 		__entry->ino		= inode->i_ino;
+ 		__entry->state		= inode->i_state;
+ 		__entry->flags		= flags;
+@@ -193,7 +192,7 @@ TRACE_EVENT(inode_foreign_history,
+ 	),
+ 
+ 	TP_fast_assign(
+-		strncpy(__entry->name, dev_name(inode_to_bdi(inode)->dev), 32);
++		strncpy(__entry->name, bdi_dev_name(inode_to_bdi(inode)), 32);
+ 		__entry->ino		= inode->i_ino;
+ 		__entry->cgroup_ino	= __trace_wbc_assign_cgroup(wbc);
+ 		__entry->history	= history;
+@@ -222,7 +221,7 @@ TRACE_EVENT(inode_switch_wbs,
+ 	),
+ 
+ 	TP_fast_assign(
+-		strncpy(__entry->name,	dev_name(old_wb->bdi->dev), 32);
++		strncpy(__entry->name,	bdi_dev_name(old_wb->bdi), 32);
+ 		__entry->ino		= inode->i_ino;
+ 		__entry->old_cgroup_ino	= __trace_wb_assign_cgroup(old_wb);
+ 		__entry->new_cgroup_ino	= __trace_wb_assign_cgroup(new_wb);
+@@ -255,7 +254,7 @@ TRACE_EVENT(track_foreign_dirty,
+ 		struct address_space *mapping = page_mapping(page);
+ 		struct inode *inode = mapping ? mapping->host : NULL;
+ 
+-		strncpy(__entry->name,	dev_name(wb->bdi->dev), 32);
++		strncpy(__entry->name,	bdi_dev_name(wb->bdi), 32);
+ 		__entry->bdi_id		= wb->bdi->id;
+ 		__entry->ino		= inode ? inode->i_ino : 0;
+ 		__entry->memcg_id	= wb->memcg_css->id;
+@@ -288,7 +287,7 @@ TRACE_EVENT(flush_foreign,
+ 	),
+ 
+ 	TP_fast_assign(
+-		strncpy(__entry->name,	dev_name(wb->bdi->dev), 32);
++		strncpy(__entry->name,	bdi_dev_name(wb->bdi), 32);
+ 		__entry->cgroup_ino	= __trace_wb_assign_cgroup(wb);
+ 		__entry->frn_bdi_id	= frn_bdi_id;
+ 		__entry->frn_memcg_id	= frn_memcg_id;
+@@ -318,7 +317,7 @@ DECLARE_EVENT_CLASS(writeback_write_inode_template,
+ 
+ 	TP_fast_assign(
+ 		strscpy_pad(__entry->name,
+-			    dev_name(inode_to_bdi(inode)->dev), 32);
++			    bdi_dev_name(inode_to_bdi(inode)), 32);
+ 		__entry->ino		= inode->i_ino;
+ 		__entry->sync_mode	= wbc->sync_mode;
+ 		__entry->cgroup_ino	= __trace_wbc_assign_cgroup(wbc);
+@@ -361,9 +360,7 @@ DECLARE_EVENT_CLASS(writeback_work_class,
+ 		__field(ino_t, cgroup_ino)
+ 	),
+ 	TP_fast_assign(
+-		strscpy_pad(__entry->name,
+-			    wb->bdi->dev ? dev_name(wb->bdi->dev) :
+-			    "(unknown)", 32);
++		strscpy_pad(__entry->name, bdi_dev_name(wb->bdi), 32);
+ 		__entry->nr_pages = work->nr_pages;
+ 		__entry->sb_dev = work->sb ? work->sb->s_dev : 0;
+ 		__entry->sync_mode = work->sync_mode;
+@@ -416,7 +413,7 @@ DECLARE_EVENT_CLASS(writeback_class,
+ 		__field(ino_t, cgroup_ino)
+ 	),
+ 	TP_fast_assign(
+-		strscpy_pad(__entry->name, dev_name(wb->bdi->dev), 32);
++		strscpy_pad(__entry->name, bdi_dev_name(wb->bdi), 32);
+ 		__entry->cgroup_ino = __trace_wb_assign_cgroup(wb);
+ 	),
+ 	TP_printk("bdi %s: cgroup_ino=%lu",
+@@ -438,7 +435,7 @@ TRACE_EVENT(writeback_bdi_register,
+ 		__array(char, name, 32)
+ 	),
+ 	TP_fast_assign(
+-		strscpy_pad(__entry->name, dev_name(bdi->dev), 32);
++		strscpy_pad(__entry->name, bdi_dev_name(bdi), 32);
+ 	),
+ 	TP_printk("bdi %s",
+ 		__entry->name
+@@ -463,7 +460,7 @@ DECLARE_EVENT_CLASS(wbc_class,
+ 	),
+ 
+ 	TP_fast_assign(
+-		strscpy_pad(__entry->name, dev_name(bdi->dev), 32);
++		strscpy_pad(__entry->name, bdi_dev_name(bdi), 32);
+ 		__entry->nr_to_write	= wbc->nr_to_write;
+ 		__entry->pages_skipped	= wbc->pages_skipped;
+ 		__entry->sync_mode	= wbc->sync_mode;
+@@ -514,7 +511,7 @@ TRACE_EVENT(writeback_queue_io,
+ 	),
+ 	TP_fast_assign(
+ 		unsigned long *older_than_this = work->older_than_this;
+-		strscpy_pad(__entry->name, dev_name(wb->bdi->dev), 32);
++		strscpy_pad(__entry->name, bdi_dev_name(wb->bdi), 32);
+ 		__entry->older	= older_than_this ?  *older_than_this : 0;
+ 		__entry->age	= older_than_this ?
+ 				  (jiffies - *older_than_this) * 1000 / HZ : -1;
+@@ -600,7 +597,7 @@ TRACE_EVENT(bdi_dirty_ratelimit,
+ 	),
+ 
+ 	TP_fast_assign(
+-		strscpy_pad(__entry->bdi, dev_name(wb->bdi->dev), 32);
++		strscpy_pad(__entry->bdi, bdi_dev_name(wb->bdi), 32);
+ 		__entry->write_bw	= KBps(wb->write_bandwidth);
+ 		__entry->avg_write_bw	= KBps(wb->avg_write_bandwidth);
+ 		__entry->dirty_rate	= KBps(dirty_rate);
+@@ -665,7 +662,7 @@ TRACE_EVENT(balance_dirty_pages,
+ 
+ 	TP_fast_assign(
+ 		unsigned long freerun = (thresh + bg_thresh) / 2;
+-		strscpy_pad(__entry->bdi, dev_name(wb->bdi->dev), 32);
++		strscpy_pad(__entry->bdi, bdi_dev_name(wb->bdi), 32);
+ 
+ 		__entry->limit		= global_wb_domain.dirty_limit;
+ 		__entry->setpoint	= (global_wb_domain.dirty_limit +
+@@ -726,7 +723,7 @@ TRACE_EVENT(writeback_sb_inodes_requeue,
+ 
+ 	TP_fast_assign(
+ 		strscpy_pad(__entry->name,
+-			    dev_name(inode_to_bdi(inode)->dev), 32);
++			    bdi_dev_name(inode_to_bdi(inode)), 32);
+ 		__entry->ino		= inode->i_ino;
+ 		__entry->state		= inode->i_state;
+ 		__entry->dirtied_when	= inode->dirtied_when;
+@@ -800,7 +797,7 @@ DECLARE_EVENT_CLASS(writeback_single_inode_template,
+ 
+ 	TP_fast_assign(
+ 		strscpy_pad(__entry->name,
+-			    dev_name(inode_to_bdi(inode)->dev), 32);
++			    bdi_dev_name(inode_to_bdi(inode)), 32);
+ 		__entry->ino		= inode->i_ino;
+ 		__entry->state		= inode->i_state;
+ 		__entry->dirtied_when	= inode->dirtied_when;
+diff --git a/mm/backing-dev.c b/mm/backing-dev.c
+index c360f6a6c844..62f05f605fb5 100644
+--- a/mm/backing-dev.c
++++ b/mm/backing-dev.c
+@@ -21,6 +21,7 @@ struct backing_dev_info noop_backing_dev_info = {
+ EXPORT_SYMBOL_GPL(noop_backing_dev_info);
+ 
+ static struct class *bdi_class;
++const char *bdi_unknown_name = "(unknown)";
+ 
+ /*
+  * bdi_lock protects bdi_tree and updates to bdi_list. bdi_list has RCU

commit 244adf6426ee31a83f397b700d964cff12a247d3
+Author: Theodore Ts'o 
+Date:   Thu Jan 23 12:23:17 2020 -0500
+
+    ext4: make dioread_nolock the default
+    
+    This fixes the direct I/O versus writeback race which can reveal stale
+    data, and it improves the tail latency of commits on slow devices.
+    
+    Link: https://lore.kernel.org/r/20200125022254.1101588-1-tytso@mit.edu
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index ecf36a23e0c4..c6fe742db798 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1592,6 +1592,7 @@ static const match_table_t tokens = {
+ 	{Opt_auto_da_alloc, "auto_da_alloc"},
+ 	{Opt_noauto_da_alloc, "noauto_da_alloc"},
+ 	{Opt_dioread_nolock, "dioread_nolock"},
++	{Opt_dioread_lock, "nodioread_nolock"},
+ 	{Opt_dioread_lock, "dioread_lock"},
+ 	{Opt_discard, "discard"},
+ 	{Opt_nodiscard, "nodiscard"},
+@@ -3764,6 +3765,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		set_opt(sb, NO_UID32);
+ 	/* xattr user namespace & acls are now defaulted on */
+ 	set_opt(sb, XATTR_USER);
++	set_opt(sb, DIOREAD_NOLOCK);
+ #ifdef CONFIG_EXT4_FS_POSIX_ACL
+ 	set_opt(sb, POSIX_ACL);
+ #endif
+@@ -3931,9 +3933,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ #endif
+ 
+ 	if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
+-		printk_once(KERN_WARNING "EXT4-fs: Warning: mounting "
+-			    "with data=journal disables delayed "
+-			    "allocation and O_DIRECT support!\n");
++		printk_once(KERN_WARNING "EXT4-fs: Warning: mounting with data=journal disables delayed allocation, dioread_nolock, and O_DIRECT support!\n");
++		clear_opt(sb, DIOREAD_NOLOCK);
+ 		if (test_opt2(sb, EXPLICIT_DELALLOC)) {
+ 			ext4_msg(sb, KERN_ERR, "can't mount with "
+ 				 "both data=journal and delalloc");

commit 71b565ceff377a52e7d58cd871745cd339447323
+Author: Theodore Ts'o 
+Date:   Thu Jan 16 10:08:16 2020 -0500
+
+    ext4: drop ext4_kvmalloc()
+    
+    As Jan pointed out[1], as of commit 81378da64de ("jbd2: mark the
+    transaction context with the scope GFP_NOFS context") we use
+    memalloc_nofs_{save,restore}() while a jbd2 handle is active.  So
+    ext4_kvmalloc() so we can call allocate using GFP_NOFS is no longer
+    necessary.
+    
+    [1] https://lore.kernel.org/r/20200109100007.GC27035@quack2.suse.cz
+    
+    Signed-off-by: Theodore Ts'o 
+    Link: https://lore.kernel.org/r/20200116155031.266620-1-tytso@mit.edu
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 5e621b0da4da..9a2ee2428ecc 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2740,7 +2740,6 @@ extern struct buffer_head *ext4_sb_bread(struct super_block *sb,
+ extern int ext4_seq_options_show(struct seq_file *seq, void *offset);
+ extern int ext4_calculate_overhead(struct super_block *sb);
+ extern void ext4_superblock_csum_set(struct super_block *sb);
+-extern void *ext4_kvmalloc(size_t size, gfp_t flags);
+ extern int ext4_alloc_flex_bg_array(struct super_block *sb,
+ 				    ext4_group_t ngroup);
+ extern const char *ext4_decode_error(struct super_block *sb, int errno,
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index a8c0f2b5b6e1..86a2500ed292 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -824,9 +824,8 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ 	if (unlikely(err))
+ 		goto errout;
+ 
+-	n_group_desc = ext4_kvmalloc((gdb_num + 1) *
+-				     sizeof(struct buffer_head *),
+-				     GFP_NOFS);
++	n_group_desc = kvmalloc((gdb_num + 1) * sizeof(struct buffer_head *),
++				GFP_KERNEL);
+ 	if (!n_group_desc) {
+ 		err = -ENOMEM;
+ 		ext4_warning(sb, "not enough memory for %lu groups",
+@@ -900,9 +899,8 @@ static int add_new_gdb_meta_bg(struct super_block *sb,
+ 	gdb_bh = ext4_sb_bread(sb, gdblock, 0);
+ 	if (IS_ERR(gdb_bh))
+ 		return PTR_ERR(gdb_bh);
+-	n_group_desc = ext4_kvmalloc((gdb_num + 1) *
+-				     sizeof(struct buffer_head *),
+-				     GFP_NOFS);
++	n_group_desc = kvmalloc((gdb_num + 1) * sizeof(struct buffer_head *),
++				GFP_KERNEL);
+ 	if (!n_group_desc) {
+ 		brelse(gdb_bh);
+ 		err = -ENOMEM;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 84a86d9b790f..ecf36a23e0c4 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -204,16 +204,6 @@ void ext4_superblock_csum_set(struct super_block *sb)
+ 	es->s_checksum = ext4_superblock_csum(sb, es);
+ }
+ 
+-void *ext4_kvmalloc(size_t size, gfp_t flags)
+-{
+-	void *ret;
+-
+-	ret = kmalloc(size, flags | __GFP_NOWARN);
+-	if (!ret)
+-		ret = __vmalloc(size, flags, PAGE_KERNEL);
+-	return ret;
+-}
+-
+ ext4_fsblk_t ext4_block_bitmap(struct super_block *sb,
+ 			       struct ext4_group_desc *bg)
+ {
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 246fbeeb6366..8cac7d95c3ad 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -1456,7 +1456,7 @@ ext4_xattr_inode_cache_find(struct inode *inode, const void *value,
+ 	if (!ce)
+ 		return NULL;
+ 
+-	ea_data = ext4_kvmalloc(value_len, GFP_NOFS);
++	ea_data = kvmalloc(value_len, GFP_KERNEL);
+ 	if (!ea_data) {
+ 		mb_cache_entry_put(ea_inode_cache, ce);
+ 		return NULL;

commit d4c5e960bf202d99ec9a6922ad387eafb798b848
+Author: Theodore Ts'o 
+Date:   Thu Nov 28 22:26:51 2019 -0500
+
+    ext4: avoid fetching btime in ext4_getattr() unless requested
+    
+    Linus observed that an allmodconfig build which does a lot of stat(2)
+    calls that ext4_getattr() was a noticeable (1%) amount of CPU time,
+    due to the cache line for i_extra_isize getting pulled in.  Since the
+    normal stat system call doesn't return btime, it's a complete waste.
+    So only calculate btime when it is explicitly requested.
+    
+    [ Fixed to check against request_mask instead of query_flags. ]
+    
+    Link: https://lore.kernel.org/r/CAHk-=wivmk_j6KbTX+Er64mLrG8abXZo0M10PNdAnHc8fWXfsQ@mail.gmail.com
+    Reported-by: Linus Torvalds 
+    Reviewed-by: Andreas Dilger 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index d035acab5b2a..9100460d92e5 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -5399,7 +5399,8 @@ int ext4_getattr(const struct path *path, struct kstat *stat,
+ 	struct ext4_inode_info *ei = EXT4_I(inode);
+ 	unsigned int flags;
+ 
+-	if (EXT4_FITS_IN_INODE(raw_inode, ei, i_crtime)) {
++	if ((request_mask & STATX_BTIME) &&
++	    EXT4_FITS_IN_INODE(raw_inode, ei, i_crtime)) {
+ 		stat->result_mask |= STATX_BTIME;
+ 		stat->btime.tv_sec = ei->i_crtime.tv_sec;
+ 		stat->btime.tv_nsec = ei->i_crtime.tv_nsec;

commit 4549b49f82ab40c214778f316b6898aa4132723a
+Author: Theodore Ts'o 
+Date:   Mon Dec 23 18:44:49 2019 -0500
+
+    ext4: export information about first/last errors via /sys/fs/ext4/
+    
+    Make {first,last}_error_{ino,block,line,func,errcode} available via
+    sysfs.
+    
+    Also add a missing newline for {first,last}_error_time.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c
+index a990d28d191b..d218ebdafa4a 100644
+--- a/fs/ext4/sysfs.c
++++ b/fs/ext4/sysfs.c
+@@ -30,6 +30,9 @@ typedef enum {
+ 	attr_feature,
+ 	attr_pointer_ui,
+ 	attr_pointer_ul,
++	attr_pointer_u64,
++	attr_pointer_u8,
++	attr_pointer_string,
+ 	attr_pointer_atomic,
+ 	attr_journal_task,
+ } attr_id_t;
+@@ -47,6 +50,7 @@ struct ext4_attr {
+ 	struct attribute attr;
+ 	short attr_id;
+ 	short attr_ptr;
++	unsigned short attr_size;
+ 	union {
+ 		int offset;
+ 		void *explicit_ptr;
+@@ -155,9 +159,29 @@ static struct ext4_attr ext4_attr_##_name = {			\
+ 	},							\
+ }
+ 
++#define EXT4_ATTR_STRING(_name,_mode,_size,_struct,_elname)	\
++static struct ext4_attr ext4_attr_##_name = {			\
++	.attr = {.name = __stringify(_name), .mode = _mode },	\
++	.attr_id = attr_pointer_string,				\
++	.attr_size = _size,					\
++	.attr_ptr = ptr_##_struct##_offset,			\
++	.u = {							\
++		.offset = offsetof(struct _struct, _elname),\
++	},							\
++}
++
+ #define EXT4_RO_ATTR_ES_UI(_name,_elname)				\
+ 	EXT4_ATTR_OFFSET(_name, 0444, pointer_ui, ext4_super_block, _elname)
+ 
++#define EXT4_RO_ATTR_ES_U8(_name,_elname)				\
++	EXT4_ATTR_OFFSET(_name, 0444, pointer_u8, ext4_super_block, _elname)
++
++#define EXT4_RO_ATTR_ES_U64(_name,_elname)				\
++	EXT4_ATTR_OFFSET(_name, 0444, pointer_u64, ext4_super_block, _elname)
++
++#define EXT4_RO_ATTR_ES_STRING(_name,_elname,_size)			\
++	EXT4_ATTR_STRING(_name, 0444, _size, ext4_super_block, _elname)
++
+ #define EXT4_RW_ATTR_SBI_UI(_name,_elname)	\
+ 	EXT4_ATTR_OFFSET(_name, 0644, pointer_ui, ext4_sb_info, _elname)
+ 
+@@ -202,6 +226,16 @@ EXT4_RW_ATTR_SBI_UI(msg_ratelimit_burst, s_msg_ratelimit_state.burst);
+ EXT4_RW_ATTR_SBI_UL(simulate_fail, s_simulate_fail);
+ #endif
+ EXT4_RO_ATTR_ES_UI(errors_count, s_error_count);
++EXT4_RO_ATTR_ES_U8(first_error_errcode, s_first_error_errcode);
++EXT4_RO_ATTR_ES_U8(last_error_errcode, s_last_error_errcode);
++EXT4_RO_ATTR_ES_UI(first_error_ino, s_first_error_ino);
++EXT4_RO_ATTR_ES_UI(last_error_ino, s_last_error_ino);
++EXT4_RO_ATTR_ES_U64(first_error_block, s_first_error_block);
++EXT4_RO_ATTR_ES_U64(last_error_block, s_last_error_block);
++EXT4_RO_ATTR_ES_UI(first_error_line, s_first_error_line);
++EXT4_RO_ATTR_ES_UI(last_error_line, s_last_error_line);
++EXT4_RO_ATTR_ES_STRING(first_error_func, s_first_error_func, 32);
++EXT4_RO_ATTR_ES_STRING(last_error_func, s_last_error_func, 32);
+ EXT4_ATTR(first_error_time, 0444, first_error_time);
+ EXT4_ATTR(last_error_time, 0444, last_error_time);
+ EXT4_ATTR(journal_task, 0444, journal_task);
+@@ -232,6 +266,16 @@ static struct attribute *ext4_attrs[] = {
+ 	ATTR_LIST(msg_ratelimit_interval_ms),
+ 	ATTR_LIST(msg_ratelimit_burst),
+ 	ATTR_LIST(errors_count),
++	ATTR_LIST(first_error_ino),
++	ATTR_LIST(last_error_ino),
++	ATTR_LIST(first_error_block),
++	ATTR_LIST(last_error_block),
++	ATTR_LIST(first_error_line),
++	ATTR_LIST(last_error_line),
++	ATTR_LIST(first_error_func),
++	ATTR_LIST(last_error_func),
++	ATTR_LIST(first_error_errcode),
++	ATTR_LIST(last_error_errcode),
+ 	ATTR_LIST(first_error_time),
+ 	ATTR_LIST(last_error_time),
+ 	ATTR_LIST(journal_task),
+@@ -290,7 +334,7 @@ static void *calc_ptr(struct ext4_attr *a, struct ext4_sb_info *sbi)
+ 
+ static ssize_t __print_tstamp(char *buf, __le32 lo, __u8 hi)
+ {
+-	return snprintf(buf, PAGE_SIZE, "%lld",
++	return snprintf(buf, PAGE_SIZE, "%lld\n",
+ 			((time64_t)hi << 32) + le32_to_cpu(lo));
+ }
+ 
+@@ -333,6 +377,25 @@ static ssize_t ext4_attr_show(struct kobject *kobj,
+ 			return 0;
+ 		return snprintf(buf, PAGE_SIZE, "%lu\n",
+ 				*((unsigned long *) ptr));
++	case attr_pointer_u8:
++		if (!ptr)
++			return 0;
++		return snprintf(buf, PAGE_SIZE, "%u\n",
++				*((unsigned char *) ptr));
++	case attr_pointer_u64:
++		if (!ptr)
++			return 0;
++		if (a->attr_ptr == ptr_ext4_super_block_offset)
++			return snprintf(buf, PAGE_SIZE, "%llu\n",
++					le64_to_cpup(ptr));
++		else
++			return snprintf(buf, PAGE_SIZE, "%llu\n",
++					*((unsigned long long *) ptr));
++	case attr_pointer_string:
++		if (!ptr)
++			return 0;
++		return snprintf(buf, PAGE_SIZE, "%.*s\n", a->attr_size,
++				(char *) ptr);
+ 	case attr_pointer_atomic:
+ 		if (!ptr)
+ 			return 0;

commit 46f870d690fecc792a66730dcbbf0aa109f5f9ab
+Author: Theodore Ts'o 
+Date:   Thu Nov 21 13:09:43 2019 -0500
+
+    ext4: simulate various I/O and checksum errors when reading metadata
+    
+    This allows us to test various error handling code paths
+    
+    Link: https://lore.kernel.org/r/20191209012317.59398-1-tytso@mit.edu
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 102c38527a10..5f993a411251 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -371,7 +371,8 @@ static int ext4_validate_block_bitmap(struct super_block *sb,
+ 	if (buffer_verified(bh))
+ 		goto verified;
+ 	if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group,
+-			desc, bh))) {
++						    desc, bh) ||
++		     ext4_simulate_fail(sb, EXT4_SIM_BBITMAP_CRC))) {
+ 		ext4_unlock_group(sb, block_group);
+ 		ext4_error(sb, "bg %u: bad block bitmap checksum", block_group);
+ 		ext4_mark_group_bitmap_corrupted(sb, block_group,
+@@ -505,6 +506,7 @@ int ext4_wait_block_bitmap(struct super_block *sb, ext4_group_t block_group,
+ 	if (!desc)
+ 		return -EFSCORRUPTED;
+ 	wait_on_buffer(bh);
++	ext4_simulate_fail_bh(sb, bh, EXT4_SIM_BBITMAP_EIO);
+ 	if (!buffer_uptodate(bh)) {
+ 		ext4_set_errno(sb, EIO);
+ 		ext4_error(sb, "Cannot read block bitmap - "
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index b00d07bad45b..5edc16d36a96 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1557,6 +1557,9 @@ struct ext4_sb_info {
+ 	/* Barrier between changing inodes' journal flags and writepages ops. */
+ 	struct percpu_rw_semaphore s_journal_flag_rwsem;
+ 	struct dax_device *s_daxdev;
++#ifdef CONFIG_EXT4_DEBUG
++	unsigned long s_simulate_fail;
++#endif
+ };
+ 
+ static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb)
+@@ -1575,6 +1578,40 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
+ 		 ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count));
+ }
+ 
++/*
++ * Simulate_fail codes
++ */
++#define EXT4_SIM_BBITMAP_EIO	1
++#define EXT4_SIM_BBITMAP_CRC	2
++#define EXT4_SIM_IBITMAP_EIO	3
++#define EXT4_SIM_IBITMAP_CRC	4
++#define EXT4_SIM_INODE_EIO	5
++#define EXT4_SIM_INODE_CRC	6
++#define EXT4_SIM_DIRBLOCK_EIO	7
++#define EXT4_SIM_DIRBLOCK_CRC	8
++
++static inline bool ext4_simulate_fail(struct super_block *sb,
++				     unsigned long code)
++{
++#ifdef CONFIG_EXT4_DEBUG
++	struct ext4_sb_info *sbi = EXT4_SB(sb);
++
++	if (unlikely(sbi->s_simulate_fail == code)) {
++		sbi->s_simulate_fail = 0;
++		return true;
++	}
++#endif
++	return false;
++}
++
++static inline void ext4_simulate_fail_bh(struct super_block *sb,
++					 struct buffer_head *bh,
++					 unsigned long code)
++{
++	if (!IS_ERR(bh) && ext4_simulate_fail(sb, code))
++		clear_buffer_uptodate(bh);
++}
++
+ /*
+  * Error number codes for s_{first,last}_error_errno
+  *
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 0151ba8ea439..c66e8f9451a2 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -94,7 +94,8 @@ static int ext4_validate_inode_bitmap(struct super_block *sb,
+ 		goto verified;
+ 	blk = ext4_inode_bitmap(sb, desc);
+ 	if (!ext4_inode_bitmap_csum_verify(sb, block_group, desc, bh,
+-					   EXT4_INODES_PER_GROUP(sb) / 8)) {
++					   EXT4_INODES_PER_GROUP(sb) / 8) ||
++	    ext4_simulate_fail(sb, EXT4_SIM_IBITMAP_CRC)) {
+ 		ext4_unlock_group(sb, block_group);
+ 		ext4_error(sb, "Corrupt inode bitmap - block_group = %u, "
+ 			   "inode_bitmap = %llu", block_group, blk);
+@@ -192,6 +193,7 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
+ 	get_bh(bh);
+ 	submit_bh(REQ_OP_READ, REQ_META | REQ_PRIO, bh);
+ 	wait_on_buffer(bh);
++	ext4_simulate_fail_bh(sb, bh, EXT4_SIM_IBITMAP_EIO);
+ 	if (!buffer_uptodate(bh)) {
+ 		put_bh(bh);
+ 		ext4_set_errno(sb, EIO);
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 23fa585206f0..c3270aaa2b75 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4243,6 +4243,8 @@ static int __ext4_get_inode_loc(struct inode *inode,
+ 	bh = sb_getblk(sb, block);
+ 	if (unlikely(!bh))
+ 		return -ENOMEM;
++	if (ext4_simulate_fail(sb, EXT4_SIM_INODE_EIO))
++		goto simulate_eio;
+ 	if (!buffer_uptodate(bh)) {
+ 		lock_buffer(bh);
+ 
+@@ -4341,6 +4343,7 @@ static int __ext4_get_inode_loc(struct inode *inode,
+ 		blk_finish_plug(&plug);
+ 		wait_on_buffer(bh);
+ 		if (!buffer_uptodate(bh)) {
++		simulate_eio:
+ 			ext4_set_errno(inode->i_sb, EIO);
+ 			EXT4_ERROR_INODE_BLOCK(inode, block,
+ 					       "unable to read itable block");
+@@ -4555,7 +4558,8 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
+ 					      sizeof(gen));
+ 	}
+ 
+-	if (!ext4_inode_csum_verify(inode, raw_inode, ei)) {
++	if (!ext4_inode_csum_verify(inode, raw_inode, ei) ||
++	    ext4_simulate_fail(sb, EXT4_SIM_INODE_CRC)) {
+ 		ext4_set_errno(inode->i_sb, EFSBADCRC);
+ 		ext4_error_inode(inode, function, line, 0,
+ 				 "iget: checksum invalid");
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 1bb6099397af..d4c0d7a18d64 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -109,7 +109,10 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
+ 	struct ext4_dir_entry *dirent;
+ 	int is_dx_block = 0;
+ 
+-	bh = ext4_bread(NULL, inode, block, 0);
++	if (ext4_simulate_fail(inode->i_sb, EXT4_SIM_DIRBLOCK_EIO))
++		bh = ERR_PTR(-EIO);
++	else
++		bh = ext4_bread(NULL, inode, block, 0);
+ 	if (IS_ERR(bh)) {
+ 		__ext4_warning(inode->i_sb, func, line,
+ 			       "inode #%lu: lblock %lu: comm %s: "
+@@ -153,7 +156,8 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
+ 	 * caller is sure it should be an index block.
+ 	 */
+ 	if (is_dx_block && type == INDEX) {
+-		if (ext4_dx_csum_verify(inode, dirent))
++		if (ext4_dx_csum_verify(inode, dirent) &&
++		    !ext4_simulate_fail(inode->i_sb, EXT4_SIM_DIRBLOCK_CRC))
+ 			set_buffer_verified(bh);
+ 		else {
+ 			ext4_set_errno(inode->i_sb, EFSBADCRC);
+@@ -164,7 +168,8 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
+ 		}
+ 	}
+ 	if (!is_dx_block) {
+-		if (ext4_dirblock_csum_verify(inode, bh))
++		if (ext4_dirblock_csum_verify(inode, bh) &&
++		    !ext4_simulate_fail(inode->i_sb, EXT4_SIM_DIRBLOCK_CRC))
+ 			set_buffer_verified(bh);
+ 		else {
+ 			ext4_set_errno(inode->i_sb, EFSBADCRC);
+diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c
+index eb1efad0e20a..a990d28d191b 100644
+--- a/fs/ext4/sysfs.c
++++ b/fs/ext4/sysfs.c
+@@ -29,6 +29,7 @@ typedef enum {
+ 	attr_last_error_time,
+ 	attr_feature,
+ 	attr_pointer_ui,
++	attr_pointer_ul,
+ 	attr_pointer_atomic,
+ 	attr_journal_task,
+ } attr_id_t;
+@@ -160,6 +161,9 @@ static struct ext4_attr ext4_attr_##_name = {			\
+ #define EXT4_RW_ATTR_SBI_UI(_name,_elname)	\
+ 	EXT4_ATTR_OFFSET(_name, 0644, pointer_ui, ext4_sb_info, _elname)
+ 
++#define EXT4_RW_ATTR_SBI_UL(_name,_elname)	\
++	EXT4_ATTR_OFFSET(_name, 0644, pointer_ul, ext4_sb_info, _elname)
++
+ #define EXT4_ATTR_PTR(_name,_mode,_id,_ptr) \
+ static struct ext4_attr ext4_attr_##_name = {			\
+ 	.attr = {.name = __stringify(_name), .mode = _mode },	\
+@@ -194,6 +198,9 @@ EXT4_RW_ATTR_SBI_UI(warning_ratelimit_interval_ms, s_warning_ratelimit_state.int
+ EXT4_RW_ATTR_SBI_UI(warning_ratelimit_burst, s_warning_ratelimit_state.burst);
+ EXT4_RW_ATTR_SBI_UI(msg_ratelimit_interval_ms, s_msg_ratelimit_state.interval);
+ EXT4_RW_ATTR_SBI_UI(msg_ratelimit_burst, s_msg_ratelimit_state.burst);
++#ifdef CONFIG_EXT4_DEBUG
++EXT4_RW_ATTR_SBI_UL(simulate_fail, s_simulate_fail);
++#endif
+ EXT4_RO_ATTR_ES_UI(errors_count, s_error_count);
+ EXT4_ATTR(first_error_time, 0444, first_error_time);
+ EXT4_ATTR(last_error_time, 0444, last_error_time);
+@@ -228,6 +235,9 @@ static struct attribute *ext4_attrs[] = {
+ 	ATTR_LIST(first_error_time),
+ 	ATTR_LIST(last_error_time),
+ 	ATTR_LIST(journal_task),
++#ifdef CONFIG_EXT4_DEBUG
++	ATTR_LIST(simulate_fail),
++#endif
+ 	NULL,
+ };
+ ATTRIBUTE_GROUPS(ext4);
+@@ -318,6 +328,11 @@ static ssize_t ext4_attr_show(struct kobject *kobj,
+ 		else
+ 			return snprintf(buf, PAGE_SIZE, "%u\n",
+ 					*((unsigned int *) ptr));
++	case attr_pointer_ul:
++		if (!ptr)
++			return 0;
++		return snprintf(buf, PAGE_SIZE, "%lu\n",
++				*((unsigned long *) ptr));
+ 	case attr_pointer_atomic:
+ 		if (!ptr)
+ 			return 0;
+@@ -361,6 +376,14 @@ static ssize_t ext4_attr_store(struct kobject *kobj,
+ 		else
+ 			*((unsigned int *) ptr) = t;
+ 		return len;
++	case attr_pointer_ul:
++		if (!ptr)
++			return 0;
++		ret = kstrtoul(skip_spaces(buf), 0, &t);
++		if (ret)
++			return ret;
++		*((unsigned long *) ptr) = t;
++		return len;
+ 	case attr_inode_readahead:
+ 		return inode_readahead_blks_store(sbi, buf, len);
+ 	case attr_trigger_test_error:

commit 878520ac45f9f698432d4276db3d9144b83931b6
+Author: Theodore Ts'o 
+Date:   Tue Nov 19 21:54:15 2019 -0500
+
+    ext4: save the error code which triggered an ext4_error() in the superblock
+    
+    This allows the cause of an ext4_error() report to be categorized
+    based on whether it was triggered due to an I/O error, or an memory
+    allocation error, or other possible causes.  Most errors are caused by
+    a detected file system inconsistency, so the default code stored in
+    the superblock will be EXT4_ERR_EFSCORRUPTED.
+    
+    Link: https://lore.kernel.org/r/20191204032335.7683-1-tytso@mit.edu
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 0b202e00d93f..102c38527a10 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -506,6 +506,7 @@ int ext4_wait_block_bitmap(struct super_block *sb, ext4_group_t block_group,
+ 		return -EFSCORRUPTED;
+ 	wait_on_buffer(bh);
+ 	if (!buffer_uptodate(bh)) {
++		ext4_set_errno(sb, EIO);
+ 		ext4_error(sb, "Cannot read block bitmap - "
+ 			   "block_group = %u, block_bitmap = %llu",
+ 			   block_group, (unsigned long long) bh->b_blocknr);
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index f8578caba40d..b00d07bad45b 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1343,7 +1343,8 @@ struct ext4_super_block {
+ 	__u8	s_lastcheck_hi;
+ 	__u8	s_first_error_time_hi;
+ 	__u8	s_last_error_time_hi;
+-	__u8	s_pad[2];
++	__u8	s_first_error_errcode;
++	__u8    s_last_error_errcode;
+ 	__le16  s_encoding;		/* Filename charset encoding */
+ 	__le16  s_encoding_flags;	/* Filename charset encoding flags */
+ 	__le32	s_reserved[95];		/* Padding to the end of the block */
+@@ -1574,6 +1575,32 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
+ 		 ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count));
+ }
+ 
++/*
++ * Error number codes for s_{first,last}_error_errno
++ *
++ * Linux errno numbers are architecture specific, so we need to translate
++ * them into something which is architecture independent.   We don't define
++ * codes for all errno's; just the ones which are most likely to be the cause
++ * of an ext4_error() call.
++ */
++#define EXT4_ERR_UNKNOWN	 1
++#define EXT4_ERR_EIO		 2
++#define EXT4_ERR_ENOMEM		 3
++#define EXT4_ERR_EFSBADCRC	 4
++#define EXT4_ERR_EFSCORRUPTED	 5
++#define EXT4_ERR_ENOSPC		 6
++#define EXT4_ERR_ENOKEY		 7
++#define EXT4_ERR_EROFS		 8
++#define EXT4_ERR_EFBIG		 9
++#define EXT4_ERR_EEXIST		10
++#define EXT4_ERR_ERANGE		11
++#define EXT4_ERR_EOVERFLOW	12
++#define EXT4_ERR_EBUSY		13
++#define EXT4_ERR_ENOTDIR	14
++#define EXT4_ERR_ENOTEMPTY	15
++#define EXT4_ERR_ESHUTDOWN	16
++#define EXT4_ERR_EFAULT		17
++
+ /*
+  * Inode dynamic state flags
+  */
+@@ -2688,6 +2715,7 @@ extern const char *ext4_decode_error(struct super_block *sb, int errno,
+ extern void ext4_mark_group_bitmap_corrupted(struct super_block *sb,
+ 					     ext4_group_t block_group,
+ 					     unsigned int flags);
++extern void ext4_set_errno(struct super_block *sb, int err);
+ 
+ extern __printf(4, 5)
+ void __ext4_error(struct super_block *, const char *, unsigned int,
+diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
+index d3b8cdea5df7..19217a3f1ae4 100644
+--- a/fs/ext4/ext4_jbd2.c
++++ b/fs/ext4/ext4_jbd2.c
+@@ -58,6 +58,7 @@ static int ext4_journal_check_start(struct super_block *sb)
+ 	 * take the FS itself readonly cleanly.
+ 	 */
+ 	if (journal && is_journal_aborted(journal)) {
++		ext4_set_errno(sb, -journal->j_errno);
+ 		ext4_abort(sb, "Detected aborted journal");
+ 		return -EROFS;
+ 	}
+@@ -249,6 +250,7 @@ int __ext4_forget(const char *where, unsigned int line, handle_t *handle,
+ 	if (err) {
+ 		ext4_journal_abort_handle(where, line, __func__,
+ 					  bh, handle, err);
++		ext4_set_errno(inode->i_sb, -err);
+ 		__ext4_abort(inode->i_sb, where, line,
+ 			   "error %d when attempting revoke", err);
+ 	}
+@@ -320,6 +322,7 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
+ 				es = EXT4_SB(inode->i_sb)->s_es;
+ 				es->s_last_error_block =
+ 					cpu_to_le64(bh->b_blocknr);
++				ext4_set_errno(inode->i_sb, EIO);
+ 				ext4_error_inode(inode, where, line,
+ 						 bh->b_blocknr,
+ 					"IO error syncing itable block");
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 0e8708b77da6..ee83fe7c98aa 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -492,6 +492,7 @@ static int __ext4_ext_check(const char *function, unsigned int line,
+ 	return 0;
+ 
+ corrupted:
++	ext4_set_errno(inode->i_sb, -err);
+ 	ext4_error_inode(inode, function, line, 0,
+ 			 "pblk %llu bad header/extent: %s - magic %x, "
+ 			 "entries %u, max %u(%u), depth %u(%u)",
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 8ca4a23129aa..0151ba8ea439 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -194,6 +194,7 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
+ 	wait_on_buffer(bh);
+ 	if (!buffer_uptodate(bh)) {
+ 		put_bh(bh);
++		ext4_set_errno(sb, EIO);
+ 		ext4_error(sb, "Cannot read inode bitmap - "
+ 			   "block_group = %u, inode_bitmap = %llu",
+ 			   block_group, bitmap_blk);
+@@ -1223,6 +1224,7 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
+ 	inode = ext4_iget(sb, ino, EXT4_IGET_NORMAL);
+ 	if (IS_ERR(inode)) {
+ 		err = PTR_ERR(inode);
++		ext4_set_errno(sb, -err);
+ 		ext4_error(sb, "couldn't read orphan inode %lu (err %d)",
+ 			   ino, err);
+ 		return inode;
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index 2fec62d764fa..e61603f47035 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -98,6 +98,7 @@ int ext4_get_max_inline_size(struct inode *inode)
+ 
+ 	error = ext4_get_inode_loc(inode, &iloc);
+ 	if (error) {
++		ext4_set_errno(inode->i_sb, -error);
+ 		ext4_error_inode(inode, __func__, __LINE__, 0,
+ 				 "can't get inode location %lu",
+ 				 inode->i_ino);
+@@ -1761,6 +1762,7 @@ bool empty_inline_dir(struct inode *dir, int *has_inline_data)
+ 
+ 	err = ext4_get_inode_loc(dir, &iloc);
+ 	if (err) {
++		ext4_set_errno(dir->i_sb, -err);
+ 		EXT4_ERROR_INODE(dir, "error %d getting inode %lu block",
+ 				 err, dir->i_ino);
+ 		return true;
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 629a25d999f0..23fa585206f0 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -271,6 +271,7 @@ void ext4_evict_inode(struct inode *inode)
+ 	if (inode->i_blocks) {
+ 		err = ext4_truncate(inode);
+ 		if (err) {
++			ext4_set_errno(inode->i_sb, -err);
+ 			ext4_error(inode->i_sb,
+ 				   "couldn't truncate inode %lu (err %d)",
+ 				   inode->i_ino, err);
+@@ -2478,10 +2479,12 @@ static int mpage_map_and_submit_extent(handle_t *handle,
+ 			EXT4_I(inode)->i_disksize = disksize;
+ 		up_write(&EXT4_I(inode)->i_data_sem);
+ 		err2 = ext4_mark_inode_dirty(handle, inode);
+-		if (err2)
++		if (err2) {
++			ext4_set_errno(inode->i_sb, -err2);
+ 			ext4_error(inode->i_sb,
+ 				   "Failed to mark inode %lu dirty",
+ 				   inode->i_ino);
++		}
+ 		if (!err)
+ 			err = err2;
+ 	}
+@@ -4338,6 +4341,7 @@ static int __ext4_get_inode_loc(struct inode *inode,
+ 		blk_finish_plug(&plug);
+ 		wait_on_buffer(bh);
+ 		if (!buffer_uptodate(bh)) {
++			ext4_set_errno(inode->i_sb, EIO);
+ 			EXT4_ERROR_INODE_BLOCK(inode, block,
+ 					       "unable to read itable block");
+ 			brelse(bh);
+@@ -4552,6 +4556,7 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
+ 	}
+ 
+ 	if (!ext4_inode_csum_verify(inode, raw_inode, ei)) {
++		ext4_set_errno(inode->i_sb, EFSBADCRC);
+ 		ext4_error_inode(inode, function, line, 0,
+ 				 "iget: checksum invalid");
+ 		ret = -EFSBADCRC;
+@@ -5090,6 +5095,7 @@ int ext4_write_inode(struct inode *inode, struct writeback_control *wbc)
+ 		if (wbc->sync_mode == WB_SYNC_ALL && !wbc->for_sync)
+ 			sync_dirty_buffer(iloc.bh);
+ 		if (buffer_req(iloc.bh) && !buffer_uptodate(iloc.bh)) {
++			ext4_set_errno(inode->i_sb, EIO);
+ 			EXT4_ERROR_INODE_BLOCK(inode, iloc.bh->b_blocknr,
+ 					 "IO error syncing inode");
+ 			err = -EIO;
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index a3e2767bdf2f..f64838187559 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -3895,6 +3895,7 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
+ 	bitmap_bh = ext4_read_block_bitmap(sb, group);
+ 	if (IS_ERR(bitmap_bh)) {
+ 		err = PTR_ERR(bitmap_bh);
++		ext4_set_errno(sb, -err);
+ 		ext4_error(sb, "Error %d reading block bitmap for %u",
+ 			   err, group);
+ 		return 0;
+@@ -4063,6 +4064,7 @@ void ext4_discard_preallocations(struct inode *inode)
+ 		err = ext4_mb_load_buddy_gfp(sb, group, &e4b,
+ 					     GFP_NOFS|__GFP_NOFAIL);
+ 		if (err) {
++			ext4_set_errno(sb, -err);
+ 			ext4_error(sb, "Error %d loading buddy information for %u",
+ 				   err, group);
+ 			continue;
+@@ -4071,6 +4073,7 @@ void ext4_discard_preallocations(struct inode *inode)
+ 		bitmap_bh = ext4_read_block_bitmap(sb, group);
+ 		if (IS_ERR(bitmap_bh)) {
+ 			err = PTR_ERR(bitmap_bh);
++			ext4_set_errno(sb, -err);
+ 			ext4_error(sb, "Error %d reading block bitmap for %u",
+ 					err, group);
+ 			ext4_mb_unload_buddy(&e4b);
+@@ -4325,6 +4328,7 @@ ext4_mb_discard_lg_preallocations(struct super_block *sb,
+ 		err = ext4_mb_load_buddy_gfp(sb, group, &e4b,
+ 					     GFP_NOFS|__GFP_NOFAIL);
+ 		if (err) {
++			ext4_set_errno(sb, -err);
+ 			ext4_error(sb, "Error %d loading buddy information for %u",
+ 				   err, group);
+ 			continue;
+diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c
+index 2305b4374fd3..1c44b1a32001 100644
+--- a/fs/ext4/mmp.c
++++ b/fs/ext4/mmp.c
+@@ -173,8 +173,10 @@ static int kmmpd(void *data)
+ 		 * (s_mmp_update_interval * 60) seconds.
+ 		 */
+ 		if (retval) {
+-			if ((failed_writes % 60) == 0)
++			if ((failed_writes % 60) == 0) {
++				ext4_set_errno(sb, -retval);
+ 				ext4_error(sb, "Error writing to MMP block");
++			}
+ 			failed_writes++;
+ 		}
+ 
+@@ -205,6 +207,7 @@ static int kmmpd(void *data)
+ 
+ 			retval = read_mmp_block(sb, &bh_check, mmp_block);
+ 			if (retval) {
++				ext4_set_errno(sb, -retval);
+ 				ext4_error(sb, "error reading MMP data: %d",
+ 					   retval);
+ 				goto exit_thread;
+@@ -218,6 +221,7 @@ static int kmmpd(void *data)
+ 					     "Error while updating MMP info. "
+ 					     "The filesystem seems to have been"
+ 					     " multiply mounted.");
++				ext4_set_errno(sb, EBUSY);
+ 				ext4_error(sb, "abort");
+ 				put_bh(bh_check);
+ 				retval = -EBUSY;
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 1cb42d940784..1bb6099397af 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -156,6 +156,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
+ 		if (ext4_dx_csum_verify(inode, dirent))
+ 			set_buffer_verified(bh);
+ 		else {
++			ext4_set_errno(inode->i_sb, EFSBADCRC);
+ 			ext4_error_inode(inode, func, line, block,
+ 					 "Directory index failed checksum");
+ 			brelse(bh);
+@@ -166,6 +167,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
+ 		if (ext4_dirblock_csum_verify(inode, bh))
+ 			set_buffer_verified(bh);
+ 		else {
++			ext4_set_errno(inode->i_sb, EFSBADCRC);
+ 			ext4_error_inode(inode, func, line, block,
+ 					 "Directory block failed checksum");
+ 			brelse(bh);
+@@ -1527,6 +1529,7 @@ static struct buffer_head *__ext4_find_entry(struct inode *dir,
+ 			goto next;
+ 		wait_on_buffer(bh);
+ 		if (!buffer_uptodate(bh)) {
++			ext4_set_errno(sb, EIO);
+ 			EXT4_ERROR_INODE(dir, "reading directory lblock %lu",
+ 					 (unsigned long) block);
+ 			brelse(bh);
+@@ -1537,6 +1540,7 @@ static struct buffer_head *__ext4_find_entry(struct inode *dir,
+ 		    !is_dx_internal_node(dir, block,
+ 					 (struct ext4_dir_entry *)bh->b_data) &&
+ 		    !ext4_dirblock_csum_verify(dir, bh)) {
++			ext4_set_errno(sb, EFSBADCRC);
+ 			EXT4_ERROR_INODE(dir, "checksumming directory "
+ 					 "block %lu", (unsigned long)block);
+ 			brelse(bh);
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index c3d66bb7fd96..f1a5c14c2a93 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -367,6 +367,8 @@ static void __save_error_info(struct super_block *sb, const char *func,
+ 	ext4_update_tstamp(es, s_last_error_time);
+ 	strncpy(es->s_last_error_func, func, sizeof(es->s_last_error_func));
+ 	es->s_last_error_line = cpu_to_le32(line);
++	if (es->s_last_error_errcode == 0)
++		es->s_last_error_errcode = EXT4_ERR_EFSCORRUPTED;
+ 	if (!es->s_first_error_time) {
+ 		es->s_first_error_time = es->s_last_error_time;
+ 		es->s_first_error_time_hi = es->s_last_error_time_hi;
+@@ -375,6 +377,7 @@ static void __save_error_info(struct super_block *sb, const char *func,
+ 		es->s_first_error_line = cpu_to_le32(line);
+ 		es->s_first_error_ino = es->s_last_error_ino;
+ 		es->s_first_error_block = es->s_last_error_block;
++		es->s_first_error_errcode = es->s_last_error_errcode;
+ 	}
+ 	/*
+ 	 * Start the daily error reporting function if it hasn't been
+@@ -631,6 +634,66 @@ const char *ext4_decode_error(struct super_block *sb, int errno,
+ 	return errstr;
+ }
+ 
++void ext4_set_errno(struct super_block *sb, int err)
++{
++	if (err < 0)
++		err = -err;
++
++	switch (err) {
++	case EIO:
++		err = EXT4_ERR_EIO;
++		break;
++	case ENOMEM:
++		err = EXT4_ERR_ENOMEM;
++		break;
++	case EFSBADCRC:
++		err = EXT4_ERR_EFSBADCRC;
++		break;
++	case EFSCORRUPTED:
++		err = EXT4_ERR_EFSCORRUPTED;
++		break;
++	case ENOSPC:
++		err = EXT4_ERR_ENOSPC;
++		break;
++	case ENOKEY:
++		err = EXT4_ERR_ENOKEY;
++		break;
++	case EROFS:
++		err = EXT4_ERR_EROFS;
++		break;
++	case EFBIG:
++		err = EXT4_ERR_EFBIG;
++		break;
++	case EEXIST:
++		err = EXT4_ERR_EEXIST;
++		break;
++	case ERANGE:
++		err = EXT4_ERR_ERANGE;
++		break;
++	case EOVERFLOW:
++		err = EXT4_ERR_EOVERFLOW;
++		break;
++	case EBUSY:
++		err = EXT4_ERR_EBUSY;
++		break;
++	case ENOTDIR:
++		err = EXT4_ERR_ENOTDIR;
++		break;
++	case ENOTEMPTY:
++		err = EXT4_ERR_ENOTEMPTY;
++		break;
++	case ESHUTDOWN:
++		err = EXT4_ERR_ESHUTDOWN;
++		break;
++	case EFAULT:
++		err = EXT4_ERR_EFAULT;
++		break;
++	default:
++		err = EXT4_ERR_UNKNOWN;
++	}
++	EXT4_SB(sb)->s_es->s_last_error_errcode = err;
++}
++
+ /* __ext4_std_error decodes expected errors from journaling functions
+  * automatically and invokes the appropriate error response.  */
+ 
+@@ -655,6 +718,7 @@ void __ext4_std_error(struct super_block *sb, const char *function,
+ 		       sb->s_id, function, line, errstr);
+ 	}
+ 
++	ext4_set_errno(sb, -errno);
+ 	save_error_info(sb, function, line);
+ 	ext4_handle_error(sb);
+ }
+@@ -982,8 +1046,10 @@ static void ext4_put_super(struct super_block *sb)
+ 		aborted = is_journal_aborted(sbi->s_journal);
+ 		err = jbd2_journal_destroy(sbi->s_journal);
+ 		sbi->s_journal = NULL;
+-		if ((err < 0) && !aborted)
++		if ((err < 0) && !aborted) {
++			ext4_set_errno(sb, -err);
+ 			ext4_abort(sb, "Couldn't clean up the journal");
++		}
+ 	}
+ 
+ 	ext4_unregister_sysfs(sb);
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 8966a5439a22..246fbeeb6366 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -2879,9 +2879,11 @@ int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode,
+ 		bh = ext4_sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl, REQ_PRIO);
+ 		if (IS_ERR(bh)) {
+ 			error = PTR_ERR(bh);
+-			if (error == -EIO)
++			if (error == -EIO) {
++				ext4_set_errno(inode->i_sb, EIO);
+ 				EXT4_ERROR_INODE(inode, "block %llu read error",
+ 						 EXT4_I(inode)->i_file_acl);
++			}
+ 			bh = NULL;
+ 			goto cleanup;
+ 		}

commit a562c687d115fe5a90be1e27745cc771c1e6cbd9
+Merge: cf2834a5ed57 bc6385dab125
+Author: Theodore Ts'o 
+Date:   Thu Dec 26 09:57:24 2019 -0500
+
+    Merge branch 'rk/inode_lock' into dev
+    
+    These are ilock patches which helps improve the current inode lock scalabiliy
+    problem in ext4 DIO mixed read/write workload case. The problem was first
+    reported by Joseph [1]. This should help improve mixed read/write workload
+    cases for databases which use directIO.
+    
+    These patches are based upon upstream discussion with Jan Kara & Joseph [2].
+    
+    The problem really is that in case of DIO overwrites, we start with
+    a exclusive lock and then downgrade it later to shared lock. This causes a
+    scalability problem in case of mixed DIO read/write workload case.
+    i.e. if we have any ongoing DIO reads and then comes a DIO writes,
+    (since writes starts with excl. inode lock) then it has to wait until the
+    shared lock is released (which only happens when DIO read is completed).
+    Same is true for vice versa as well.
+    The same can be easily observed with perf-tools trace analysis [3].
+    
+    For more details, including performance numbers, please see [4].
+    
+    [1] https://lore.kernel.org/linux-ext4/1566871552-60946-4-git-send-email-joseph.qi@linux.alibaba.com/
+    [2] https://lore.kernel.org/linux-ext4/20190910215720.GA7561@quack2.suse.cz/
+    [3] https://raw.githubusercontent.com/riteshharjani/LinuxStudy/master/ext4/perf.report
+    [4] https://lore.kernel.org/r/20191212055557.11151-1-riteshh@linux.ibm.com
+

commit cf2834a5ed57562d6a1a8170724704149f0ae0a4
+Author: Theodore Ts'o 
+Date:   Sat Dec 14 16:42:52 2019 -0500
+
+    ext4: treat buffers contining write errors as valid in ext4_sb_bread()
+    
+    In commit 7963e5ac9012 ("ext4: treat buffers with write errors as
+    containing valid data") we missed changing ext4_sb_bread() to use
+    ext4_buffer_uptodate().  So fix this oversight.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 2937a8873fe1..c3d66bb7fd96 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -154,7 +154,7 @@ ext4_sb_bread(struct super_block *sb, sector_t block, int op_flags)
+ 
+ 	if (bh == NULL)
+ 		return ERR_PTR(-ENOMEM);
+-	if (buffer_uptodate(bh))
++	if (ext4_buffer_uptodate(bh))
+ 		return bh;
+ 	ll_rw_block(REQ_OP_READ, REQ_META | op_flags, 1, &bh);
+ 	wait_on_buffer(bh);

commit 9803387c55f7d2ce69aa64340c5fdc6b3027dbc8
+Author: Theodore Ts'o 
+Date:   Sun Dec 15 01:09:03 2019 -0500
+
+    ext4: validate the debug_want_extra_isize mount option at parse time
+    
+    Instead of setting s_want_extra_size and then making sure that it is a
+    valid value afterwards, validate the field before we set it.  This
+    avoids races and other problems when remounting the file system.
+    
+    Link: https://lore.kernel.org/r/20191215063020.GA11512@mit.edu
+    Cc: stable@kernel.org
+    Signed-off-by: Theodore Ts'o 
+    Reported-and-tested-by: syzbot+4a39a025912b265cacef@syzkaller.appspotmail.com
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index b205112ca051..46b6d5b150ac 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1886,6 +1886,13 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
+ 		}
+ 		sbi->s_commit_interval = HZ * arg;
+ 	} else if (token == Opt_debug_want_extra_isize) {
++		if ((arg & 1) ||
++		    (arg < 4) ||
++		    (arg > (sbi->s_inode_size - EXT4_GOOD_OLD_INODE_SIZE))) {
++			ext4_msg(sb, KERN_ERR,
++				 "Invalid want_extra_isize %d", arg);
++			return -1;
++		}
+ 		sbi->s_want_extra_isize = arg;
+ 	} else if (token == Opt_max_batch_time) {
+ 		sbi->s_max_batch_time = arg;
+@@ -3540,40 +3547,6 @@ int ext4_calculate_overhead(struct super_block *sb)
+ 	return 0;
+ }
+ 
+-static void ext4_clamp_want_extra_isize(struct super_block *sb)
+-{
+-	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-	struct ext4_super_block *es = sbi->s_es;
+-	unsigned def_extra_isize = sizeof(struct ext4_inode) -
+-						EXT4_GOOD_OLD_INODE_SIZE;
+-
+-	if (sbi->s_inode_size == EXT4_GOOD_OLD_INODE_SIZE) {
+-		sbi->s_want_extra_isize = 0;
+-		return;
+-	}
+-	if (sbi->s_want_extra_isize < 4) {
+-		sbi->s_want_extra_isize = def_extra_isize;
+-		if (ext4_has_feature_extra_isize(sb)) {
+-			if (sbi->s_want_extra_isize <
+-			    le16_to_cpu(es->s_want_extra_isize))
+-				sbi->s_want_extra_isize =
+-					le16_to_cpu(es->s_want_extra_isize);
+-			if (sbi->s_want_extra_isize <
+-			    le16_to_cpu(es->s_min_extra_isize))
+-				sbi->s_want_extra_isize =
+-					le16_to_cpu(es->s_min_extra_isize);
+-		}
+-	}
+-	/* Check if enough inode space is available */
+-	if ((sbi->s_want_extra_isize > sbi->s_inode_size) ||
+-	    (EXT4_GOOD_OLD_INODE_SIZE + sbi->s_want_extra_isize >
+-							sbi->s_inode_size)) {
+-		sbi->s_want_extra_isize = def_extra_isize;
+-		ext4_msg(sb, KERN_INFO,
+-			 "required extra inode space not available");
+-	}
+-}
+-
+ static void ext4_set_resv_clusters(struct super_block *sb)
+ {
+ 	ext4_fsblk_t resv_clusters;
+@@ -3781,6 +3754,68 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	 */
+ 	sbi->s_li_wait_mult = EXT4_DEF_LI_WAIT_MULT;
+ 
++	if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV) {
++		sbi->s_inode_size = EXT4_GOOD_OLD_INODE_SIZE;
++		sbi->s_first_ino = EXT4_GOOD_OLD_FIRST_INO;
++	} else {
++		sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
++		sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
++		if (sbi->s_first_ino < EXT4_GOOD_OLD_FIRST_INO) {
++			ext4_msg(sb, KERN_ERR, "invalid first ino: %u",
++				 sbi->s_first_ino);
++			goto failed_mount;
++		}
++		if ((sbi->s_inode_size < EXT4_GOOD_OLD_INODE_SIZE) ||
++		    (!is_power_of_2(sbi->s_inode_size)) ||
++		    (sbi->s_inode_size > blocksize)) {
++			ext4_msg(sb, KERN_ERR,
++			       "unsupported inode size: %d",
++			       sbi->s_inode_size);
++			goto failed_mount;
++		}
++		/*
++		 * i_atime_extra is the last extra field available for
++		 * [acm]times in struct ext4_inode. Checking for that
++		 * field should suffice to ensure we have extra space
++		 * for all three.
++		 */
++		if (sbi->s_inode_size >= offsetof(struct ext4_inode, i_atime_extra) +
++			sizeof(((struct ext4_inode *)0)->i_atime_extra)) {
++			sb->s_time_gran = 1;
++			sb->s_time_max = EXT4_EXTRA_TIMESTAMP_MAX;
++		} else {
++			sb->s_time_gran = NSEC_PER_SEC;
++			sb->s_time_max = EXT4_NON_EXTRA_TIMESTAMP_MAX;
++		}
++		sb->s_time_min = EXT4_TIMESTAMP_MIN;
++	}
++	if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE) {
++		sbi->s_want_extra_isize = sizeof(struct ext4_inode) -
++			EXT4_GOOD_OLD_INODE_SIZE;
++		if (ext4_has_feature_extra_isize(sb)) {
++			unsigned v, max = (sbi->s_inode_size -
++					   EXT4_GOOD_OLD_INODE_SIZE);
++
++			v = le16_to_cpu(es->s_want_extra_isize);
++			if (v > max) {
++				ext4_msg(sb, KERN_ERR,
++					 "bad s_want_extra_isize: %d", v);
++				goto failed_mount;
++			}
++			if (sbi->s_want_extra_isize < v)
++				sbi->s_want_extra_isize = v;
++
++			v = le16_to_cpu(es->s_min_extra_isize);
++			if (v > max) {
++				ext4_msg(sb, KERN_ERR,
++					 "bad s_min_extra_isize: %d", v);
++				goto failed_mount;
++			}
++			if (sbi->s_want_extra_isize < v)
++				sbi->s_want_extra_isize = v;
++		}
++	}
++
+ 	if (sbi->s_es->s_mount_opts[0]) {
+ 		char *s_mount_opts = kstrndup(sbi->s_es->s_mount_opts,
+ 					      sizeof(sbi->s_es->s_mount_opts),
+@@ -4019,42 +4054,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 						      has_huge_files);
+ 	sb->s_maxbytes = ext4_max_size(sb->s_blocksize_bits, has_huge_files);
+ 
+-	if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV) {
+-		sbi->s_inode_size = EXT4_GOOD_OLD_INODE_SIZE;
+-		sbi->s_first_ino = EXT4_GOOD_OLD_FIRST_INO;
+-	} else {
+-		sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
+-		sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
+-		if (sbi->s_first_ino < EXT4_GOOD_OLD_FIRST_INO) {
+-			ext4_msg(sb, KERN_ERR, "invalid first ino: %u",
+-				 sbi->s_first_ino);
+-			goto failed_mount;
+-		}
+-		if ((sbi->s_inode_size < EXT4_GOOD_OLD_INODE_SIZE) ||
+-		    (!is_power_of_2(sbi->s_inode_size)) ||
+-		    (sbi->s_inode_size > blocksize)) {
+-			ext4_msg(sb, KERN_ERR,
+-			       "unsupported inode size: %d",
+-			       sbi->s_inode_size);
+-			goto failed_mount;
+-		}
+-		/*
+-		 * i_atime_extra is the last extra field available for [acm]times in
+-		 * struct ext4_inode. Checking for that field should suffice to ensure
+-		 * we have extra space for all three.
+-		 */
+-		if (sbi->s_inode_size >= offsetof(struct ext4_inode, i_atime_extra) +
+-			sizeof(((struct ext4_inode *)0)->i_atime_extra)) {
+-			sb->s_time_gran = 1;
+-			sb->s_time_max = EXT4_EXTRA_TIMESTAMP_MAX;
+-		} else {
+-			sb->s_time_gran = NSEC_PER_SEC;
+-			sb->s_time_max = EXT4_NON_EXTRA_TIMESTAMP_MAX;
+-		}
+-
+-		sb->s_time_min = EXT4_TIMESTAMP_MIN;
+-	}
+-
+ 	sbi->s_desc_size = le16_to_cpu(es->s_desc_size);
+ 	if (ext4_has_feature_64bit(sb)) {
+ 		if (sbi->s_desc_size < EXT4_MIN_DESC_SIZE_64BIT ||
+@@ -4503,8 +4502,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	} else if (ret)
+ 		goto failed_mount4a;
+ 
+-	ext4_clamp_want_extra_isize(sb);
+-
+ 	ext4_set_resv_clusters(sb);
+ 
+ 	err = ext4_setup_system_zone(sb);
+@@ -5292,8 +5289,6 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 		goto restore_opts;
+ 	}
+ 
+-	ext4_clamp_want_extra_isize(sb);
+-
+ 	if ((old_opts.s_mount_opt & EXT4_MOUNT_JOURNAL_CHECKSUM) ^
+ 	    test_opt(sb, JOURNAL_CHECKSUM)) {
+ 		ext4_msg(sb, KERN_ERR, "changing journal_checksum "

commit 707d1a2f601bea6110a5633054253c0cb71b44c1
+Author: Theodore Ts'o 
+Date:   Sun Dec 8 19:43:46 2019 -0500
+
+    ext4: optimize __ext4_check_dir_entry()
+    
+    Make __ext4_check_dir_entry() a bit easier to understand, and reduce
+    the object size of the function by over 11%.
+    
+    Signed-off-by: Theodore Ts'o 
+    Link: https://lore.kernel.org/r/20191209004346.38526-1-tytso@mit.edu
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index 6305d5ec25af..9f00fc0bf21d 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -72,6 +72,7 @@ int __ext4_check_dir_entry(const char *function, unsigned int line,
+ 	const char *error_msg = NULL;
+ 	const int rlen = ext4_rec_len_from_disk(de->rec_len,
+ 						dir->i_sb->s_blocksize);
++	const int next_offset = ((char *) de - buf) + rlen;
+ 
+ 	if (unlikely(rlen < EXT4_DIR_REC_LEN(1)))
+ 		error_msg = "rec_len is smaller than minimal";
+@@ -79,13 +80,11 @@ int __ext4_check_dir_entry(const char *function, unsigned int line,
+ 		error_msg = "rec_len % 4 != 0";
+ 	else if (unlikely(rlen < EXT4_DIR_REC_LEN(de->name_len)))
+ 		error_msg = "rec_len is too small for name_len";
+-	else if (unlikely(((char *) de - buf) + rlen > size))
++	else if (unlikely(next_offset > size))
+ 		error_msg = "directory entry overrun";
+-	else if (unlikely(((char *) de - buf) + rlen >
+-			  size - EXT4_DIR_REC_LEN(1) &&
+-			  ((char *) de - buf) + rlen != size)) {
++	else if (unlikely(next_offset > size - EXT4_DIR_REC_LEN(1) &&
++			  next_offset != size))
+ 		error_msg = "directory entry too close to block end";
+-	}
+ 	else if (unlikely(le32_to_cpu(de->inode) >
+ 			le32_to_cpu(EXT4_SB(dir->i_sb)->s_es->s_inodes_count)))
+ 		error_msg = "inode out of bounds";

commit db5cce1afc8d2475d2c1c37c2a8267dd0e151526
+Author: Anders Kaseorg 
+Date:   Mon Dec 2 17:09:20 2019 -0500
+
+    Revert "iwlwifi: assign directly to iwl_trans->cfg in QuZ detection"
+    
+    This reverts commit 968dcfb4905245dc64d65312c0d17692fa087b99.
+    
+    Both that commit and commit 809805a820c6445f7a701ded24fdc6bbc841d1e4
+    attempted to fix the same bug (dead assignments to the local variable
+    cfg), but they did so in incompatible ways. When they were both merged,
+    independently of each other, the combination actually caused the bug to
+    reappear, leading to a firmware crash on boot for some cards.
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=205719
+    
+    Signed-off-by: Anders Kaseorg 
+    Acked-by: Luca Coelho 
+    Signed-off-by: Kalle Valo 
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+index 040cec17d3ad..b0b7eca1754e 100644
+--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
++++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+@@ -1111,18 +1111,18 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 
+ 	/* same thing for QuZ... */
+ 	if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QUZ) {
+-		if (iwl_trans->cfg == &iwl_ax101_cfg_qu_hr)
+-			iwl_trans->cfg = &iwl_ax101_cfg_quz_hr;
+-		else if (iwl_trans->cfg == &iwl_ax201_cfg_qu_hr)
+-			iwl_trans->cfg = &iwl_ax201_cfg_quz_hr;
+-		else if (iwl_trans->cfg == &iwl9461_2ac_cfg_qu_b0_jf_b0)
+-			iwl_trans->cfg = &iwl9461_2ac_cfg_quz_a0_jf_b0_soc;
+-		else if (iwl_trans->cfg == &iwl9462_2ac_cfg_qu_b0_jf_b0)
+-			iwl_trans->cfg = &iwl9462_2ac_cfg_quz_a0_jf_b0_soc;
+-		else if (iwl_trans->cfg == &iwl9560_2ac_cfg_qu_b0_jf_b0)
+-			iwl_trans->cfg = &iwl9560_2ac_cfg_quz_a0_jf_b0_soc;
+-		else if (iwl_trans->cfg == &iwl9560_2ac_160_cfg_qu_b0_jf_b0)
+-			iwl_trans->cfg = &iwl9560_2ac_160_cfg_quz_a0_jf_b0_soc;
++		if (cfg == &iwl_ax101_cfg_qu_hr)
++			cfg = &iwl_ax101_cfg_quz_hr;
++		else if (cfg == &iwl_ax201_cfg_qu_hr)
++			cfg = &iwl_ax201_cfg_quz_hr;
++		else if (cfg == &iwl9461_2ac_cfg_qu_b0_jf_b0)
++			cfg = &iwl9461_2ac_cfg_quz_a0_jf_b0_soc;
++		else if (cfg == &iwl9462_2ac_cfg_qu_b0_jf_b0)
++			cfg = &iwl9462_2ac_cfg_quz_a0_jf_b0_soc;
++		else if (cfg == &iwl9560_2ac_cfg_qu_b0_jf_b0)
++			cfg = &iwl9560_2ac_cfg_quz_a0_jf_b0_soc;
++		else if (cfg == &iwl9560_2ac_160_cfg_qu_b0_jf_b0)
++			cfg = &iwl9560_2ac_160_cfg_quz_a0_jf_b0_soc;
+ 	}
+ 
+ #endif

commit dfdeeb41fb08fbe11d3cfefba9c0fcd00c95a36d
+Merge: 3c845acd0237 c7df4a1ecb85
+Author: Theodore Ts'o 
+Date:   Tue Nov 19 12:25:42 2019 -0500
+
+    Merge branch 'tt/misc' into dev
+

commit c7df4a1ecb8579838ec8c56b2bb6a6716e974f37
+Author: Theodore Ts'o 
+Date:   Mon Nov 11 22:18:13 2019 -0500
+
+    ext4: work around deleting a file with i_nlink == 0 safely
+    
+    If the file system is corrupted such that a file's i_links_count is
+    too small, then it's possible that when unlinking that file, i_nlink
+    will already be zero.  Previously we were working around this kind of
+    corruption by forcing i_nlink to one; but we were doing this before
+    trying to delete the directory entry --- and if the file system is
+    corrupted enough that ext4_delete_entry() fails, then we exit with
+    i_nlink elevated, and this causes the orphan inode list handling to be
+    FUBAR'ed, such that when we unmount the file system, the orphan inode
+    list can get corrupted.
+    
+    A better way to fix this is to simply skip trying to call drop_nlink()
+    if i_nlink is already zero, thus moving the check to the place where
+    it makes the most sense.
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=205433
+    
+    Link: https://lore.kernel.org/r/20191112032903.8828-1-tytso@mit.edu
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+    Reviewed-by: Andreas Dilger 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index a67cae3c8ff5..a856997d87b5 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -3196,18 +3196,17 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
+ 	if (IS_DIRSYNC(dir))
+ 		ext4_handle_sync(handle);
+ 
+-	if (inode->i_nlink == 0) {
+-		ext4_warning_inode(inode, "Deleting file '%.*s' with no links",
+-				   dentry->d_name.len, dentry->d_name.name);
+-		set_nlink(inode, 1);
+-	}
+ 	retval = ext4_delete_entry(handle, dir, de, bh);
+ 	if (retval)
+ 		goto end_unlink;
+ 	dir->i_ctime = dir->i_mtime = current_time(dir);
+ 	ext4_update_dx_flag(dir);
+ 	ext4_mark_inode_dirty(handle, dir);
+-	drop_nlink(inode);
++	if (inode->i_nlink == 0)
++		ext4_warning_inode(inode, "Deleting file '%.*s' with no links",
++				   dentry->d_name.len, dentry->d_name.name);
++	else
++		drop_nlink(inode);
+ 	if (!inode->i_nlink)
+ 		ext4_orphan_add(handle, inode);
+ 	inode->i_ctime = current_time(inode);

commit 4ea99936a1630f51fc3a2d61a58ec4a1c4b7d55a
+Author: Theodore Ts'o 
+Date:   Thu Nov 7 21:43:41 2019 -0500
+
+    ext4: add more paranoia checking in ext4_expand_extra_isize handling
+    
+    It's possible to specify a non-zero s_want_extra_isize via debugging
+    option, and this can cause bad things(tm) to happen when using a file
+    system with an inode size of 128 bytes.
+    
+    Add better checking when the file system is mounted, as well as when
+    we are actually doing the trying to do the inode expansion.
+    
+    Link: https://lore.kernel.org/r/20191110121510.GH23325@mit.edu
+    Reported-by: syzbot+f8d6f8386ceacdbfff57@syzkaller.appspotmail.com
+    Reported-by: syzbot+33d7ea72e47de3bdf4e1@syzkaller.appspotmail.com
+    Reported-by: syzbot+44b6763edfc17144296f@syzkaller.appspotmail.com
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 381813205f99..c6e3fe287b50 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -5569,8 +5569,23 @@ static int __ext4_expand_extra_isize(struct inode *inode,
+ {
+ 	struct ext4_inode *raw_inode;
+ 	struct ext4_xattr_ibody_header *header;
++	unsigned int inode_size = EXT4_INODE_SIZE(inode->i_sb);
++	struct ext4_inode_info *ei = EXT4_I(inode);
+ 	int error;
+ 
++	/* this was checked at iget time, but double check for good measure */
++	if ((EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize > inode_size) ||
++	    (ei->i_extra_isize & 3)) {
++		EXT4_ERROR_INODE(inode, "bad extra_isize %u (inode size %u)",
++				 ei->i_extra_isize,
++				 EXT4_INODE_SIZE(inode->i_sb));
++		return -EFSCORRUPTED;
++	}
++	if ((new_extra_isize < ei->i_extra_isize) ||
++	    (new_extra_isize < 4) ||
++	    (new_extra_isize > inode_size - EXT4_GOOD_OLD_INODE_SIZE))
++		return -EINVAL;	/* Should never happen */
++
+ 	raw_inode = ext4_raw_inode(iloc);
+ 
+ 	header = IHDR(inode, raw_inode);
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 7796e2ffc294..71af8780d4ee 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3545,12 +3545,15 @@ static void ext4_clamp_want_extra_isize(struct super_block *sb)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	struct ext4_super_block *es = sbi->s_es;
++	unsigned def_extra_isize = sizeof(struct ext4_inode) -
++						EXT4_GOOD_OLD_INODE_SIZE;
+ 
+-	/* determine the minimum size of new large inodes, if present */
+-	if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE &&
+-	    sbi->s_want_extra_isize == 0) {
+-		sbi->s_want_extra_isize = sizeof(struct ext4_inode) -
+-						     EXT4_GOOD_OLD_INODE_SIZE;
++	if (sbi->s_inode_size == EXT4_GOOD_OLD_INODE_SIZE) {
++		sbi->s_want_extra_isize = 0;
++		return;
++	}
++	if (sbi->s_want_extra_isize < 4) {
++		sbi->s_want_extra_isize = def_extra_isize;
+ 		if (ext4_has_feature_extra_isize(sb)) {
+ 			if (sbi->s_want_extra_isize <
+ 			    le16_to_cpu(es->s_want_extra_isize))
+@@ -3563,10 +3566,10 @@ static void ext4_clamp_want_extra_isize(struct super_block *sb)
+ 		}
+ 	}
+ 	/* Check if enough inode space is available */
+-	if (EXT4_GOOD_OLD_INODE_SIZE + sbi->s_want_extra_isize >
+-							sbi->s_inode_size) {
+-		sbi->s_want_extra_isize = sizeof(struct ext4_inode) -
+-						       EXT4_GOOD_OLD_INODE_SIZE;
++	if ((sbi->s_want_extra_isize > sbi->s_inode_size) ||
++	    (EXT4_GOOD_OLD_INODE_SIZE + sbi->s_want_extra_isize >
++							sbi->s_inode_size)) {
++		sbi->s_want_extra_isize = def_extra_isize;
+ 		ext4_msg(sb, KERN_INFO,
+ 			 "required extra inode space not available");
+ 	}

commit 8d0d47ea1640b23678306c007ccc813b5b930af4
+Merge: a6d4040846bf 378f32bab371
+Author: Theodore Ts'o 
+Date:   Tue Nov 5 16:21:09 2019 -0500
+
+    Merge branch 'mb/dio' into master
+

commit a6d4040846bff49c7e870cee5693245f87f2cfce
+Merge: 0d0a60c92fed 19014d697147
+Author: Theodore Ts'o 
+Date:   Tue Nov 5 16:02:20 2019 -0500
+
+    Merge branch 'jk/jbd2-revoke-overflow'
+
+diff --cc fs/jbd2/transaction.c
+index 7c11afe60532,a9d3a2208506..c068912408dd
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@@ -1665,15 -1737,20 +1736,15 @@@ int jbd2_journal_forget (handle_t *hand
+  		__jbd2_journal_file_buffer(jh, transaction, BJ_Forget);
+  		spin_unlock(&journal->j_list_lock);
+  	}
+ -
+ -	jbd_unlock_bh_state(bh);
+ -	__brelse(bh);
+  drop:
+ +	__brelse(bh);
+ +	spin_unlock(&jh->b_state_lock);
+ +	jbd2_journal_put_journal_head(jh);
+  	if (drop_reserve) {
+  		/* no need to reserve log space for this block -bzzz */
+- 		handle->h_buffer_credits++;
++ 		handle->h_total_credits++;
+  	}
+  	return err;
+ -
+ -not_jbd:
+ -	jbd_unlock_bh_state(bh);
+ -	__bforget(bh);
+ -	goto drop;
+  }
+  
+  /**

commit f21bdbba0a5ac69e0a632ad974f5c0df9b7d411c
+Merge: 0d0a60c92fed a90100421499
+Author: Theodore Ts'o 
+Date:   Tue Nov 5 11:31:32 2019 -0500
+
+    Merge branch 'iomap-for-next' into mb/dio
+

commit 0d0a60c92fedbd4bf484c4c9b5cd49c16d05fb3f
+Merge: 7855a57d008b c33fbe8f673c
+Author: Theodore Ts'o 
+Date:   Fri Nov 1 14:49:52 2019 -0400
+
+    Merge branch 'rh/dioread-nolock-1k' into dev
+

commit 040823b5372b445d1d9483811e85a24d71314d33
+Merge: e85526404ca7 aa28b98d6dbc
+Author: Theodore Ts'o 
+Date:   Wed Sep 18 10:36:24 2019 -0400
+
+    Merge tag 'unicode-next-v5.4' of https://git.kernel.org/pub/scm/linux/kernel/git/krisman/unicode into dev
+    
+    fs/unicode patches for 5.4-rc1
+    
+    This includes two fixes for the unicode system for inclusion into Linux
+    v5.4.
+    
+      - A patch from Krzysztof Wilczynski solving a build time warning.
+    
+      - A patch from Colin King making a parsing format static, to reduce
+        stack size.
+    
+    Build validated and run time tested using xfstests casefold testcase.
+    
+    Signed-off-by: Gabriel Krisman Bertazi 
+

commit 6456ca6520ab6c9aec589b4640169cd6da378c68
+Author: Theodore Ts'o 
+Date:   Tue Sep 3 01:43:17 2019 -0400
+
+    ext4: fix kernel oops caused by spurious casefold flag
+    
+    If an directory has the a casefold flag set without the casefold
+    feature set, s_encoding will not be initialized, and this will cause
+    the kernel to dereference a NULL pointer.  In addition to adding
+    checks to avoid these kernel oops, attempts to load inodes with the
+    casefold flag when the casefold feature is not enable will cause the
+    file system to be declared corrupted.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index 86054f31fe4d..9fdd2b269d61 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -668,14 +668,15 @@ static int ext4_d_compare(const struct dentry *dentry, unsigned int len,
+ 			  const char *str, const struct qstr *name)
+ {
+ 	struct qstr qstr = {.name = str, .len = len };
++	struct inode *inode = dentry->d_parent->d_inode;
+ 
+-	if (!IS_CASEFOLDED(dentry->d_parent->d_inode)) {
++	if (!IS_CASEFOLDED(inode) || !EXT4_SB(inode->i_sb)->s_encoding) {
+ 		if (len != name->len)
+ 			return -1;
+ 		return memcmp(str, name->name, len);
+ 	}
+ 
+-	return ext4_ci_compare(dentry->d_parent->d_inode, name, &qstr, false);
++	return ext4_ci_compare(inode, name, &qstr, false);
+ }
+ 
+ static int ext4_d_hash(const struct dentry *dentry, struct qstr *str)
+@@ -685,7 +686,7 @@ static int ext4_d_hash(const struct dentry *dentry, struct qstr *str)
+ 	unsigned char *norm;
+ 	int len, ret = 0;
+ 
+-	if (!IS_CASEFOLDED(dentry->d_inode))
++	if (!IS_CASEFOLDED(dentry->d_inode) || !um)
+ 		return 0;
+ 
+ 	norm = kmalloc(PATH_MAX, GFP_ATOMIC);
+diff --git a/fs/ext4/hash.c b/fs/ext4/hash.c
+index d358bfcb6b3f..3e133793a5a3 100644
+--- a/fs/ext4/hash.c
++++ b/fs/ext4/hash.c
+@@ -280,7 +280,7 @@ int ext4fs_dirhash(const struct inode *dir, const char *name, int len,
+ 	unsigned char *buff;
+ 	struct qstr qstr = {.name = name, .len = len };
+ 
+-	if (len && IS_CASEFOLDED(dir)) {
++	if (len && IS_CASEFOLDED(dir) && um) {
+ 		buff = kzalloc(sizeof(char) * PATH_MAX, GFP_KERNEL);
+ 		if (!buff)
+ 			return -ENOMEM;
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index e567f0229d4e..4e271b509af1 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -5067,6 +5067,9 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
+ 				 "iget: bogus i_mode (%o)", inode->i_mode);
+ 		goto bad_inode;
+ 	}
++	if (IS_CASEFOLDED(inode) && !ext4_has_feature_casefold(inode->i_sb))
++		ext4_error_inode(inode, function, line, 0,
++				 "casefold flag without casefold feature");
+ 	brelse(iloc.bh);
+ 
+ 	unlock_new_inode(inode);
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 129029534075..a427d2031a8d 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1312,7 +1312,7 @@ void ext4_fname_setup_ci_filename(struct inode *dir, const struct qstr *iname,
+ {
+ 	int len;
+ 
+-	if (!IS_CASEFOLDED(dir)) {
++	if (!IS_CASEFOLDED(dir) || !EXT4_SB(dir->i_sb)->s_encoding) {
+ 		cf_name->name = NULL;
+ 		return;
+ 	}
+@@ -2183,7 +2183,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
+ 
+ #ifdef CONFIG_UNICODE
+ 	if (ext4_has_strict_mode(sbi) && IS_CASEFOLDED(dir) &&
+-	    utf8_validate(sbi->s_encoding, &dentry->d_name))
++	    sbi->s_encoding && utf8_validate(sbi->s_encoding, &dentry->d_name))
+ 		return -EINVAL;
+ #endif
+ 

commit c1e8220bd316d8ae8e524df39534b8a412a45d5e
+Author: Theodore Ts'o 
+Date:   Fri Aug 23 22:38:00 2019 -0400
+
+    ext4: fix punch hole for inline_data file systems
+    
+    If a program attempts to punch a hole on an inline data file, we need
+    to convert it to a normal file first.
+    
+    This was detected using ext4/032 using the adv configuration.  Simple
+    reproducer:
+    
+    mke2fs -Fq -t ext4 -O inline_data /dev/vdc
+    mount /vdc
+    echo "" > /vdc/testfile
+    xfs_io -c 'truncate 33554432' /vdc/testfile
+    xfs_io -c 'fpunch 0 1048576' /vdc/testfile
+    umount /vdc
+    e2fsck -fy /dev/vdc
+    
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 2b1c58da8d1e..e567f0229d4e 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4236,6 +4236,15 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
+ 
+ 	trace_ext4_punch_hole(inode, offset, length, 0);
+ 
++	ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
++	if (ext4_has_inline_data(inode)) {
++		down_write(&EXT4_I(inode)->i_mmap_sem);
++		ret = ext4_convert_inline_data(inode);
++		up_write(&EXT4_I(inode)->i_mmap_sem);
++		if (ret)
++			return ret;
++	}
++
+ 	/*
+ 	 * Write out all dirty pages to avoid race conditions
+ 	 * Then release them.

commit cd2d99229dc96219547e6349841e1aad851c6acc
+Author: Theodore Ts'o 
+Date:   Mon Aug 12 13:44:49 2019 -0400
+
+    ext4: drop legacy pre-1970 encoding workaround
+    
+    Originally, support for expanded timestamps had a bug in that pre-1970
+    times were erroneously encoded as being in the the 24th century.  This
+    was fixed in commit a4dad1ae24f8 ("ext4: Fix handling of extended
+    tv_sec") which landed in 4.4.  Starting with 4.4, pre-1970 timestamps
+    were correctly encoded, but for backwards compatibility those
+    incorrectly encoded timestamps were mapped back to the pre-1970 dates.
+    
+    Given that backwards compatibility workaround has been around for 4
+    years, and given that running e2fsck from e2fsprogs 1.43.2 and later
+    will offer to fix these timestamps (which has been released for 3
+    years), it's past time to drop the legacy workaround from the kernel.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index e2d8ad27f4d1..17cc2dc13174 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -828,21 +828,8 @@ static inline __le32 ext4_encode_extra_time(struct timespec64 *time)
+ static inline void ext4_decode_extra_time(struct timespec64 *time,
+ 					  __le32 extra)
+ {
+-	if (unlikely(extra & cpu_to_le32(EXT4_EPOCH_MASK))) {
+-
+-#if 1
+-		/* Handle legacy encoding of pre-1970 dates with epoch
+-		 * bits 1,1. (This backwards compatibility may be removed
+-		 * at the discretion of the ext4 developers.)
+-		 */
+-		u64 extra_bits = le32_to_cpu(extra) & EXT4_EPOCH_MASK;
+-		if (extra_bits == 3 && ((time->tv_sec) & 0x80000000) != 0)
+-			extra_bits = 0;
+-		time->tv_sec += extra_bits << 32;
+-#else
++	if (unlikely(extra & cpu_to_le32(EXT4_EPOCH_MASK)))
+ 		time->tv_sec += (u64)(le32_to_cpu(extra) & EXT4_EPOCH_MASK) << 32;
+-#endif
+-	}
+ 	time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS;
+ }
+ 

commit bb5835edcdf8bf78bbe51cff13e332c439bc0567
+Author: Theodore Ts'o 
+Date:   Sun Aug 11 16:32:41 2019 -0400
+
+    ext4: add new ioctl EXT4_IOC_GET_ES_CACHE
+    
+    For debugging reasons, it's useful to know the contents of the extent
+    cache.  Since the extent cache contains much of what is in the fiemap
+    ioctl, use an fiemap-style interface to return this information.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index ee296797bcd2..e2d8ad27f4d1 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -652,6 +652,7 @@ enum {
+ /* ioctl codes 19--39 are reserved for fscrypt */
+ #define EXT4_IOC_CLEAR_ES_CACHE		_IO('f', 40)
+ #define EXT4_IOC_GETSTATE		_IOW('f', 41, __u32)
++#define EXT4_IOC_GET_ES_CACHE		_IOWR('f', 42, struct fiemap)
+ 
+ #define EXT4_IOC_FSGETXATTR		FS_IOC_FSGETXATTR
+ #define EXT4_IOC_FSSETXATTR		FS_IOC_FSSETXATTR
+@@ -692,6 +693,12 @@ enum {
+ #define EXT4_IOC32_SETVERSION_OLD	FS_IOC32_SETVERSION
+ #endif
+ 
++/*
++ * Returned by EXT4_IOC_GET_ES_CACHE as an additional possible flag.
++ * It indicates that the entry in extent status cache is for a hole.
++ */
++#define EXT4_FIEMAP_EXTENT_HOLE		0x08000000
++
+ /* Max physical block we can address w/o extents */
+ #define EXT4_MAX_BLOCK_FILE_PHYS	0xFFFFFFFF
+ 
+@@ -3258,6 +3265,9 @@ extern int ext4_ext_check_inode(struct inode *inode);
+ extern ext4_lblk_t ext4_ext_next_allocated_block(struct ext4_ext_path *path);
+ extern int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ 			__u64 start, __u64 len);
++extern int ext4_get_es_cache(struct inode *inode,
++			     struct fiemap_extent_info *fieinfo,
++			     __u64 start, __u64 len);
+ extern int ext4_ext_precache(struct inode *inode);
+ extern int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len);
+ extern int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len);
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 92266a2da7d6..0620d495fd8a 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -2315,6 +2315,52 @@ static int ext4_fill_fiemap_extents(struct inode *inode,
+ 	return err;
+ }
+ 
++static int ext4_fill_es_cache_info(struct inode *inode,
++				   ext4_lblk_t block, ext4_lblk_t num,
++				   struct fiemap_extent_info *fieinfo)
++{
++	ext4_lblk_t next, end = block + num - 1;
++	struct extent_status es;
++	unsigned char blksize_bits = inode->i_sb->s_blocksize_bits;
++	unsigned int flags;
++	int err;
++
++	while (block <= end) {
++		next = 0;
++		flags = 0;
++		if (!ext4_es_lookup_extent(inode, block, &next, &es))
++			break;
++		if (ext4_es_is_unwritten(&es))
++			flags |= FIEMAP_EXTENT_UNWRITTEN;
++		if (ext4_es_is_delayed(&es))
++			flags |= (FIEMAP_EXTENT_DELALLOC |
++				  FIEMAP_EXTENT_UNKNOWN);
++		if (ext4_es_is_hole(&es))
++			flags |= EXT4_FIEMAP_EXTENT_HOLE;
++		if (next == 0)
++			flags |= FIEMAP_EXTENT_LAST;
++		if (flags & (FIEMAP_EXTENT_DELALLOC|
++			     EXT4_FIEMAP_EXTENT_HOLE))
++			es.es_pblk = 0;
++		else
++			es.es_pblk = ext4_es_pblock(&es);
++		err = fiemap_fill_next_extent(fieinfo,
++				(__u64)es.es_lblk << blksize_bits,
++				(__u64)es.es_pblk << blksize_bits,
++				(__u64)es.es_len << blksize_bits,
++				flags);
++		if (next == 0)
++			break;
++		block = next;
++		if (err < 0)
++			return err;
++		if (err == 1)
++			return 0;
++	}
++	return 0;
++}
++
++
+ /*
+  * ext4_ext_determine_hole - determine hole around given block
+  * @inode:	inode we lookup in
+@@ -5017,8 +5063,6 @@ static int ext4_find_delayed_extent(struct inode *inode,
+ 
+ 	return next_del;
+ }
+-/* fiemap flags we can handle specified here */
+-#define EXT4_FIEMAP_FLAGS	(FIEMAP_FLAG_SYNC|FIEMAP_FLAG_XATTR)
+ 
+ static int ext4_xattr_fiemap(struct inode *inode,
+ 				struct fiemap_extent_info *fieinfo)
+@@ -5055,10 +5099,16 @@ static int ext4_xattr_fiemap(struct inode *inode,
+ 	return (error < 0 ? error : 0);
+ }
+ 
+-int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+-		__u64 start, __u64 len)
++static int _ext4_fiemap(struct inode *inode,
++			struct fiemap_extent_info *fieinfo,
++			__u64 start, __u64 len,
++			int (*fill)(struct inode *, ext4_lblk_t,
++				    ext4_lblk_t,
++				    struct fiemap_extent_info *))
+ {
+ 	ext4_lblk_t start_blk;
++	u32 ext4_fiemap_flags = FIEMAP_FLAG_SYNC|FIEMAP_FLAG_XATTR;
++
+ 	int error = 0;
+ 
+ 	if (ext4_has_inline_data(inode)) {
+@@ -5075,14 +5125,18 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ 		error = ext4_ext_precache(inode);
+ 		if (error)
+ 			return error;
++		fieinfo->fi_flags &= ~FIEMAP_FLAG_CACHE;
+ 	}
+ 
+ 	/* fallback to generic here if not in extents fmt */
+-	if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
++	if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) &&
++	    fill == ext4_fill_fiemap_extents)
+ 		return generic_block_fiemap(inode, fieinfo, start, len,
+ 			ext4_get_block);
+ 
+-	if (fiemap_check_flags(fieinfo, EXT4_FIEMAP_FLAGS))
++	if (fill == ext4_fill_es_cache_info)
++		ext4_fiemap_flags &= FIEMAP_FLAG_XATTR;
++	if (fiemap_check_flags(fieinfo, ext4_fiemap_flags))
+ 		return -EBADR;
+ 
+ 	if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) {
+@@ -5101,12 +5155,36 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ 		 * Walk the extent tree gathering extent information
+ 		 * and pushing extents back to the user.
+ 		 */
+-		error = ext4_fill_fiemap_extents(inode, start_blk,
+-						 len_blks, fieinfo);
++		error = fill(inode, start_blk, len_blks, fieinfo);
+ 	}
+ 	return error;
+ }
+ 
++int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
++		__u64 start, __u64 len)
++{
++	return _ext4_fiemap(inode, fieinfo, start, len,
++			    ext4_fill_fiemap_extents);
++}
++
++int ext4_get_es_cache(struct inode *inode, struct fiemap_extent_info *fieinfo,
++		      __u64 start, __u64 len)
++{
++	if (ext4_has_inline_data(inode)) {
++		int has_inline;
++
++		down_read(&EXT4_I(inode)->xattr_sem);
++		has_inline = ext4_has_inline_data(inode);
++		up_read(&EXT4_I(inode)->xattr_sem);
++		if (has_inline)
++			return 0;
++	}
++
++	return _ext4_fiemap(inode, fieinfo, start, len,
++			    ext4_fill_es_cache_info);
++}
++
++
+ /*
+  * ext4_access_path:
+  * Function to access the path buffer for marking it dirty.
+diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
+index 02cc8eb3eb0e..a959adc59bcd 100644
+--- a/fs/ext4/extents_status.c
++++ b/fs/ext4/extents_status.c
+@@ -899,6 +899,7 @@ void ext4_es_cache_extent(struct inode *inode, ext4_lblk_t lblk,
+  * Return: 1 on found, 0 on not
+  */
+ int ext4_es_lookup_extent(struct inode *inode, ext4_lblk_t lblk,
++			  ext4_lblk_t *next_lblk,
+ 			  struct extent_status *es)
+ {
+ 	struct ext4_es_tree *tree;
+@@ -948,6 +949,15 @@ int ext4_es_lookup_extent(struct inode *inode, ext4_lblk_t lblk,
+ 		if (!ext4_es_is_referenced(es1))
+ 			ext4_es_set_referenced(es1);
+ 		stats->es_stats_cache_hits++;
++		if (next_lblk) {
++			node = rb_next(&es1->rb_node);
++			if (node) {
++				es1 = rb_entry(node, struct extent_status,
++					       rb_node);
++				*next_lblk = es1->es_lblk;
++			} else
++				*next_lblk = 0;
++		}
+ 	} else {
+ 		stats->es_stats_cache_misses++;
+ 	}
+diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h
+index e16785f431e7..eb56a1289031 100644
+--- a/fs/ext4/extents_status.h
++++ b/fs/ext4/extents_status.h
+@@ -140,6 +140,7 @@ extern void ext4_es_find_extent_range(struct inode *inode,
+ 				      ext4_lblk_t lblk, ext4_lblk_t end,
+ 				      struct extent_status *es);
+ extern int ext4_es_lookup_extent(struct inode *inode, ext4_lblk_t lblk,
++				 ext4_lblk_t *next_lblk,
+ 				 struct extent_status *es);
+ extern bool ext4_es_scan_range(struct inode *inode,
+ 			       int (*matching_fn)(struct extent_status *es),
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index a6523516d681..4b92c7603907 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -527,7 +527,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
+ 		return -EFSCORRUPTED;
+ 
+ 	/* Lookup extent status tree firstly */
+-	if (ext4_es_lookup_extent(inode, map->m_lblk, &es)) {
++	if (ext4_es_lookup_extent(inode, map->m_lblk, NULL, &es)) {
+ 		if (ext4_es_is_written(&es) || ext4_es_is_unwritten(&es)) {
+ 			map->m_pblk = ext4_es_pblock(&es) +
+ 					map->m_lblk - es.es_lblk;
+@@ -695,7 +695,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
+ 		 * extent status tree.
+ 		 */
+ 		if ((flags & EXT4_GET_BLOCKS_PRE_IO) &&
+-		    ext4_es_lookup_extent(inode, map->m_lblk, &es)) {
++		    ext4_es_lookup_extent(inode, map->m_lblk, NULL, &es)) {
+ 			if (ext4_es_is_written(&es))
+ 				goto out_sem;
+ 		}
+@@ -1868,7 +1868,7 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
+ 		  (unsigned long) map->m_lblk);
+ 
+ 	/* Lookup extent status tree firstly */
+-	if (ext4_es_lookup_extent(inode, iblock, &es)) {
++	if (ext4_es_lookup_extent(inode, iblock, NULL, &es)) {
+ 		if (ext4_es_is_hole(&es)) {
+ 			retval = 0;
+ 			down_read(&EXT4_I(inode)->i_data_sem);
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index ffb7bde4900d..d6242b7b8718 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -745,6 +745,74 @@ static void ext4_fill_fsxattr(struct inode *inode, struct fsxattr *fa)
+ 		fa->fsx_projid = from_kprojid(&init_user_ns, ei->i_projid);
+ }
+ 
++/* copied from fs/ioctl.c */
++static int fiemap_check_ranges(struct super_block *sb,
++			       u64 start, u64 len, u64 *new_len)
++{
++	u64 maxbytes = (u64) sb->s_maxbytes;
++
++	*new_len = len;
++
++	if (len == 0)
++		return -EINVAL;
++
++	if (start > maxbytes)
++		return -EFBIG;
++
++	/*
++	 * Shrink request scope to what the fs can actually handle.
++	 */
++	if (len > maxbytes || (maxbytes - len) < start)
++		*new_len = maxbytes - start;
++
++	return 0;
++}
++
++/* So that the fiemap access checks can't overflow on 32 bit machines. */
++#define FIEMAP_MAX_EXTENTS	(UINT_MAX / sizeof(struct fiemap_extent))
++
++static int ext4_ioctl_get_es_cache(struct file *filp, unsigned long arg)
++{
++	struct fiemap fiemap;
++	struct fiemap __user *ufiemap = (struct fiemap __user *) arg;
++	struct fiemap_extent_info fieinfo = { 0, };
++	struct inode *inode = file_inode(filp);
++	struct super_block *sb = inode->i_sb;
++	u64 len;
++	int error;
++
++	if (copy_from_user(&fiemap, ufiemap, sizeof(fiemap)))
++		return -EFAULT;
++
++	if (fiemap.fm_extent_count > FIEMAP_MAX_EXTENTS)
++		return -EINVAL;
++
++	error = fiemap_check_ranges(sb, fiemap.fm_start, fiemap.fm_length,
++				    &len);
++	if (error)
++		return error;
++
++	fieinfo.fi_flags = fiemap.fm_flags;
++	fieinfo.fi_extents_max = fiemap.fm_extent_count;
++	fieinfo.fi_extents_start = ufiemap->fm_extents;
++
++	if (fiemap.fm_extent_count != 0 &&
++	    !access_ok(fieinfo.fi_extents_start,
++		       fieinfo.fi_extents_max * sizeof(struct fiemap_extent)))
++		return -EFAULT;
++
++	if (fieinfo.fi_flags & FIEMAP_FLAG_SYNC)
++		filemap_write_and_wait(inode->i_mapping);
++
++	error = ext4_get_es_cache(inode, &fieinfo, fiemap.fm_start, len);
++	fiemap.fm_flags = fieinfo.fi_flags;
++	fiemap.fm_mapped_extents = fieinfo.fi_extents_mapped;
++	if (copy_to_user(ufiemap, &fiemap, sizeof(fiemap)))
++		error = -EFAULT;
++
++	return error;
++}
++
+ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ {
+ 	struct inode *inode = file_inode(filp);
+@@ -1139,6 +1207,9 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 		return put_user(state, (__u32 __user *) arg);
+ 	}
+ 
++	case EXT4_IOC_GET_ES_CACHE:
++		return ext4_ioctl_get_es_cache(filp, arg);
++
+ 	case EXT4_IOC_FSGETXATTR:
+ 	{
+ 		struct fsxattr fa;
+@@ -1259,6 +1330,7 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ 	case FS_IOC_GETFSMAP:
+ 	case EXT4_IOC_CLEAR_ES_CACHE:
+ 	case EXT4_IOC_GETSTATE:
++	case EXT4_IOC_GET_ES_CACHE:
+ 		break;
+ 	default:
+ 		return -ENOIOCTLCMD;

commit 1ad3ea6e0a694b0486eb2cbe60378ad0fbf23642
+Author: Theodore Ts'o 
+Date:   Sun Aug 11 16:31:41 2019 -0400
+
+    ext4: add a new ioctl EXT4_IOC_GETSTATE
+    
+    The new ioctl EXT4_IOC_GETSTATE returns some of the dynamic state of
+    an ext4 inode for debugging purposes.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index b22f24f1d365..ee296797bcd2 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -651,6 +651,7 @@ enum {
+ #define EXT4_IOC_GET_ENCRYPTION_POLICY	FS_IOC_GET_ENCRYPTION_POLICY
+ /* ioctl codes 19--39 are reserved for fscrypt */
+ #define EXT4_IOC_CLEAR_ES_CACHE		_IO('f', 40)
++#define EXT4_IOC_GETSTATE		_IOW('f', 41, __u32)
+ 
+ #define EXT4_IOC_FSGETXATTR		FS_IOC_FSGETXATTR
+ #define EXT4_IOC_FSSETXATTR		FS_IOC_FSSETXATTR
+@@ -664,6 +665,16 @@ enum {
+ #define EXT4_GOING_FLAGS_LOGFLUSH		0x1	/* flush log but not data */
+ #define EXT4_GOING_FLAGS_NOLOGFLUSH		0x2	/* don't flush log nor data */
+ 
++/*
++ * Flags returned by EXT4_IOC_GETSTATE
++ *
++ * We only expose to userspace a subset of the state flags in
++ * i_state_flags
++ */
++#define EXT4_STATE_FLAG_EXT_PRECACHED	0x00000001
++#define EXT4_STATE_FLAG_NEW		0x00000002
++#define EXT4_STATE_FLAG_NEWENTRY	0x00000004
++#define EXT4_STATE_FLAG_DA_ALLOC_CLOSE	0x00000008
+ 
+ #if defined(__KERNEL__) && defined(CONFIG_COMPAT)
+ /*
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index 15b1047878ab..ffb7bde4900d 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -1123,6 +1123,22 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 		return 0;
+ 	}
+ 
++	case EXT4_IOC_GETSTATE:
++	{
++		__u32	state = 0;
++
++		if (ext4_test_inode_state(inode, EXT4_STATE_EXT_PRECACHED))
++			state |= EXT4_STATE_FLAG_EXT_PRECACHED;
++		if (ext4_test_inode_state(inode, EXT4_STATE_NEW))
++			state |= EXT4_STATE_FLAG_NEW;
++		if (ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY))
++			state |= EXT4_STATE_FLAG_NEWENTRY;
++		if (ext4_test_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE))
++			state |= EXT4_STATE_FLAG_DA_ALLOC_CLOSE;
++
++		return put_user(state, (__u32 __user *) arg);
++	}
++
+ 	case EXT4_IOC_FSGETXATTR:
+ 	{
+ 		struct fsxattr fa;
+@@ -1242,6 +1258,7 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ 	case EXT4_IOC_SHUTDOWN:
+ 	case FS_IOC_GETFSMAP:
+ 	case EXT4_IOC_CLEAR_ES_CACHE:
++	case EXT4_IOC_GETSTATE:
+ 		break;
+ 	default:
+ 		return -ENOIOCTLCMD;

commit b0c013e2928d3696ceb6401311dbc1d7fcccd6dd
+Author: Theodore Ts'o 
+Date:   Sun Aug 11 16:30:41 2019 -0400
+
+    ext4: add a new ioctl EXT4_IOC_CLEAR_ES_CACHE
+    
+    The new ioctl EXT4_IOC_CLEAR_ES_CACHE will force an inode's extent
+    status cache to be cleared out.  This is intended for use for
+    debugging.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index bf660aa7a9e0..b22f24f1d365 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -649,6 +649,8 @@ enum {
+ #define EXT4_IOC_SET_ENCRYPTION_POLICY	FS_IOC_SET_ENCRYPTION_POLICY
+ #define EXT4_IOC_GET_ENCRYPTION_PWSALT	FS_IOC_GET_ENCRYPTION_PWSALT
+ #define EXT4_IOC_GET_ENCRYPTION_POLICY	FS_IOC_GET_ENCRYPTION_POLICY
++/* ioctl codes 19--39 are reserved for fscrypt */
++#define EXT4_IOC_CLEAR_ES_CACHE		_IO('f', 40)
+ 
+ #define EXT4_IOC_FSGETXATTR		FS_IOC_FSGETXATTR
+ #define EXT4_IOC_FSSETXATTR		FS_IOC_FSSETXATTR
+diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
+index 7521de2dcf3a..02cc8eb3eb0e 100644
+--- a/fs/ext4/extents_status.c
++++ b/fs/ext4/extents_status.c
+@@ -1374,6 +1374,34 @@ static int es_reclaim_extents(struct ext4_inode_info *ei, int *nr_to_scan)
+ 	return nr_shrunk;
+ }
+ 
++/*
++ * Called to support EXT4_IOC_CLEAR_ES_CACHE.  We can only remove
++ * discretionary entries from the extent status cache.  (Some entries
++ * must be present for proper operations.)
++ */
++void ext4_clear_inode_es(struct inode *inode)
++{
++	struct ext4_inode_info *ei = EXT4_I(inode);
++	struct extent_status *es;
++	struct ext4_es_tree *tree;
++	struct rb_node *node;
++
++	write_lock(&ei->i_es_lock);
++	tree = &EXT4_I(inode)->i_es_tree;
++	tree->cache_es = NULL;
++	node = rb_first(&tree->root);
++	while (node) {
++		es = rb_entry(node, struct extent_status, rb_node);
++		node = rb_next(node);
++		if (!ext4_es_is_delayed(es)) {
++			rb_erase(&es->rb_node, &tree->root);
++			ext4_es_free_extent(inode, es);
++		}
++	}
++	ext4_clear_inode_state(inode, EXT4_STATE_EXT_PRECACHED);
++	write_unlock(&ei->i_es_lock);
++}
++
+ #ifdef ES_DEBUG__
+ static void ext4_print_pending_tree(struct inode *inode)
+ {
+diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h
+index 131a8b7df265..e16785f431e7 100644
+--- a/fs/ext4/extents_status.h
++++ b/fs/ext4/extents_status.h
+@@ -248,5 +248,6 @@ extern unsigned int ext4_es_delayed_clu(struct inode *inode, ext4_lblk_t lblk,
+ 					ext4_lblk_t len);
+ extern void ext4_es_remove_blks(struct inode *inode, ext4_lblk_t lblk,
+ 				ext4_lblk_t len);
++extern void ext4_clear_inode_es(struct inode *inode);
+ 
+ #endif /* _EXT4_EXTENTS_STATUS_H */
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index 442f7ef873fc..15b1047878ab 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -1115,6 +1115,14 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 	case EXT4_IOC_GET_ENCRYPTION_POLICY:
+ 		return fscrypt_ioctl_get_policy(filp, (void __user *)arg);
+ 
++	case EXT4_IOC_CLEAR_ES_CACHE:
++	{
++		if (!inode_owner_or_capable(inode))
++			return -EACCES;
++		ext4_clear_inode_es(inode);
++		return 0;
++	}
++
+ 	case EXT4_IOC_FSGETXATTR:
+ 	{
+ 		struct fsxattr fa;
+@@ -1233,6 +1241,7 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ 	case EXT4_IOC_GET_ENCRYPTION_POLICY:
+ 	case EXT4_IOC_SHUTDOWN:
+ 	case FS_IOC_GETFSMAP:
++	case EXT4_IOC_CLEAR_ES_CACHE:
+ 		break;
+ 	default:
+ 		return -ENOIOCTLCMD;

commit 7633b08b2750513cef662fbcbe66065b9940fc6a
+Author: Theodore Ts'o 
+Date:   Fri Jun 21 21:57:00 2019 -0400
+
+    ext4: rename htree_inline_dir_to_tree() to ext4_inlinedir_to_tree()
+    
+    Clean up namespace pollution by the inline_data code.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 83128bdd7abb..bf660aa7a9e0 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -3104,11 +3104,11 @@ extern int ext4_try_create_inline_dir(handle_t *handle,
+ extern int ext4_read_inline_dir(struct file *filp,
+ 				struct dir_context *ctx,
+ 				int *has_inline_data);
+-extern int htree_inlinedir_to_tree(struct file *dir_file,
+-				   struct inode *dir, ext4_lblk_t block,
+-				   struct dx_hash_info *hinfo,
+-				   __u32 start_hash, __u32 start_minor_hash,
+-				   int *has_inline_data);
++extern int ext4_inlinedir_to_tree(struct file *dir_file,
++				  struct inode *dir, ext4_lblk_t block,
++				  struct dx_hash_info *hinfo,
++				  __u32 start_hash, __u32 start_minor_hash,
++				  int *has_inline_data);
+ extern struct buffer_head *ext4_find_inline_entry(struct inode *dir,
+ 					struct ext4_filename *fname,
+ 					struct ext4_dir_entry_2 **res_dir,
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index 796137bb7dfa..88cdf3c90bd1 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -1324,11 +1324,11 @@ int ext4_try_add_inline_entry(handle_t *handle, struct ext4_filename *fname,
+  * inlined dir.  It returns the number directory entries loaded
+  * into the tree.  If there is an error it is returned in err.
+  */
+-int htree_inlinedir_to_tree(struct file *dir_file,
+-			    struct inode *dir, ext4_lblk_t block,
+-			    struct dx_hash_info *hinfo,
+-			    __u32 start_hash, __u32 start_minor_hash,
+-			    int *has_inline_data)
++int ext4_inlinedir_to_tree(struct file *dir_file,
++			   struct inode *dir, ext4_lblk_t block,
++			   struct dx_hash_info *hinfo,
++			   __u32 start_hash, __u32 start_minor_hash,
++			   int *has_inline_data)
+ {
+ 	int err = 0, count = 0;
+ 	unsigned int parent_ino;
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 183ad614ae3d..c9568fee9e11 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1104,10 +1104,10 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
+ 		hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed;
+ 		if (ext4_has_inline_data(dir)) {
+ 			int has_inline_data = 1;
+-			count = htree_inlinedir_to_tree(dir_file, dir, 0,
+-							&hinfo, start_hash,
+-							start_minor_hash,
+-							&has_inline_data);
++			count = ext4_inlinedir_to_tree(dir_file, dir, 0,
++						       &hinfo, start_hash,
++						       start_minor_hash,
++						       &has_inline_data);
+ 			if (has_inline_data) {
+ 				*next_hash = ~0;
+ 				return count;

commit ddce3b94715ca5a19a107cd7c1d89fea177d2454
+Author: Theodore Ts'o 
+Date:   Fri Jun 21 16:31:47 2019 -0400
+
+    ext4: refactor initialize_dirent_tail()
+    
+    Move the calculation of the location of the dirent tail into
+    initialize_dirent_tail().  Also prefix the function with ext4_ to fix
+    kernel namepsace polution.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 5b86df7ec326..83128bdd7abb 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -3147,8 +3147,8 @@ extern struct ext4_dir_entry_2 *ext4_init_dot_dotdot(struct inode *inode,
+ 				 struct ext4_dir_entry_2 *de,
+ 				 int blocksize, int csum_size,
+ 				 unsigned int parent_ino, int dotdot_real_len);
+-extern void initialize_dirent_tail(struct ext4_dir_entry_tail *t,
+-				   unsigned int blocksize);
++extern void ext4_initialize_dirent_tail(struct buffer_head *bh,
++					unsigned int blocksize);
+ extern int ext4_handle_dirty_dirblock(handle_t *handle, struct inode *inode,
+ 				      struct buffer_head *bh);
+ extern int ext4_ci_compare(const struct inode *parent,
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index f19dd5a08d0d..796137bb7dfa 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -1132,7 +1132,6 @@ static int ext4_finish_convert_inline_dir(handle_t *handle,
+ {
+ 	int err, csum_size = 0, header_size = 0;
+ 	struct ext4_dir_entry_2 *de;
+-	struct ext4_dir_entry_tail *t;
+ 	void *target = dir_block->b_data;
+ 
+ 	/*
+@@ -1158,11 +1157,9 @@ static int ext4_finish_convert_inline_dir(handle_t *handle,
+ 			inline_size - EXT4_INLINE_DOTDOT_SIZE + header_size,
+ 			inode->i_sb->s_blocksize - csum_size);
+ 
+-	if (csum_size) {
+-		t = EXT4_DIRENT_TAIL(dir_block->b_data,
+-				     inode->i_sb->s_blocksize);
+-		initialize_dirent_tail(t, inode->i_sb->s_blocksize);
+-	}
++	if (csum_size)
++		ext4_initialize_dirent_tail(dir_block,
++					    inode->i_sb->s_blocksize);
+ 	set_buffer_uptodate(dir_block);
+ 	err = ext4_handle_dirty_dirblock(handle, inode, dir_block);
+ 	if (err)
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 4f0bcbbcfe96..183ad614ae3d 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -293,9 +293,11 @@ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
+ 			     struct inode *dir, struct inode *inode);
+ 
+ /* checksumming functions */
+-void initialize_dirent_tail(struct ext4_dir_entry_tail *t,
+-			    unsigned int blocksize)
++void ext4_initialize_dirent_tail(struct buffer_head *bh,
++				 unsigned int blocksize)
+ {
++	struct ext4_dir_entry_tail *t = EXT4_DIRENT_TAIL(bh->b_data, blocksize);
++
+ 	memset(t, 0, sizeof(struct ext4_dir_entry_tail));
+ 	t->det_rec_len = ext4_rec_len_to_disk(
+ 			sizeof(struct ext4_dir_entry_tail), blocksize);
+@@ -370,7 +372,7 @@ int ext4_dirblock_csum_verify(struct inode *inode, struct buffer_head *bh)
+ 	}
+ 
+ 	if (t->det_checksum != ext4_dirblock_csum(inode, bh->b_data,
+-						(char *)t - bh->b_data))
++						  (char *)t - bh->b_data))
+ 		return 0;
+ 
+ 	return 1;
+@@ -391,7 +393,7 @@ static void ext4_dirblock_csum_set(struct inode *inode,
+ 	}
+ 
+ 	t->det_checksum = ext4_dirblock_csum(inode, bh->b_data,
+-					   (char *)t - bh->b_data);
++					     (char *)t - bh->b_data);
+ }
+ 
+ int ext4_handle_dirty_dirblock(handle_t *handle,
+@@ -1813,7 +1815,6 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
+ 	char *data1 = (*bh)->b_data, *data2;
+ 	unsigned split, move, size;
+ 	struct ext4_dir_entry_2 *de = NULL, *de2;
+-	struct ext4_dir_entry_tail *t;
+ 	int	csum_size = 0;
+ 	int	err = 0, i;
+ 
+@@ -1874,11 +1875,8 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
+ 					    (char *) de2,
+ 					    blocksize);
+ 	if (csum_size) {
+-		t = EXT4_DIRENT_TAIL(data2, blocksize);
+-		initialize_dirent_tail(t, blocksize);
+-
+-		t = EXT4_DIRENT_TAIL(data1, blocksize);
+-		initialize_dirent_tail(t, blocksize);
++		ext4_initialize_dirent_tail(*bh, blocksize);
++		ext4_initialize_dirent_tail(bh2, blocksize);
+ 	}
+ 
+ 	dxtrace(dx_show_leaf(dir, hinfo, (struct ext4_dir_entry_2 *) data1,
+@@ -2039,8 +2037,7 @@ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname,
+ 	struct dx_frame	frames[EXT4_HTREE_LEVEL], *frame;
+ 	struct dx_entry *entries;
+ 	struct ext4_dir_entry_2	*de, *de2;
+-	struct ext4_dir_entry_tail *t;
+-	char		*data1, *top;
++	char		*data2, *top;
+ 	unsigned	len;
+ 	int		retval;
+ 	unsigned	blocksize;
+@@ -2080,21 +2077,18 @@ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname,
+ 		return PTR_ERR(bh2);
+ 	}
+ 	ext4_set_inode_flag(dir, EXT4_INODE_INDEX);
+-	data1 = bh2->b_data;
++	data2 = bh2->b_data;
+ 
+-	memcpy (data1, de, len);
+-	de = (struct ext4_dir_entry_2 *) data1;
+-	top = data1 + len;
++	memcpy(data2, de, len);
++	de = (struct ext4_dir_entry_2 *) data2;
++	top = data2 + len;
+ 	while ((char *)(de2 = ext4_next_entry(de, blocksize)) < top)
+ 		de = de2;
+-	de->rec_len = ext4_rec_len_to_disk(data1 + (blocksize - csum_size) -
+-					   (char *) de,
+-					   blocksize);
++	de->rec_len = ext4_rec_len_to_disk(data2 + (blocksize - csum_size) -
++					   (char *) de, blocksize);
+ 
+-	if (csum_size) {
+-		t = EXT4_DIRENT_TAIL(data1, blocksize);
+-		initialize_dirent_tail(t, blocksize);
+-	}
++	if (csum_size)
++		ext4_initialize_dirent_tail(bh2, blocksize);
+ 
+ 	/* Initialize the root; the dot dirents already exist */
+ 	de = (struct ext4_dir_entry_2 *) (&root->dotdot);
+@@ -2164,7 +2158,6 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
+ 	struct inode *dir = d_inode(dentry->d_parent);
+ 	struct buffer_head *bh = NULL;
+ 	struct ext4_dir_entry_2 *de;
+-	struct ext4_dir_entry_tail *t;
+ 	struct super_block *sb;
+ 	struct ext4_sb_info *sbi;
+ 	struct ext4_filename fname;
+@@ -2249,10 +2242,8 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
+ 	de->inode = 0;
+ 	de->rec_len = ext4_rec_len_to_disk(blocksize - csum_size, blocksize);
+ 
+-	if (csum_size) {
+-		t = EXT4_DIRENT_TAIL(bh->b_data, blocksize);
+-		initialize_dirent_tail(t, blocksize);
+-	}
++	if (csum_size)
++		ext4_initialize_dirent_tail(bh, blocksize);
+ 
+ 	retval = add_dirent_to_buf(handle, &fname, dir, inode, de, bh);
+ out:
+@@ -2712,7 +2703,6 @@ static int ext4_init_new_dir(handle_t *handle, struct inode *dir,
+ {
+ 	struct buffer_head *dir_block = NULL;
+ 	struct ext4_dir_entry_2 *de;
+-	struct ext4_dir_entry_tail *t;
+ 	ext4_lblk_t block = 0;
+ 	unsigned int blocksize = dir->i_sb->s_blocksize;
+ 	int csum_size = 0;
+@@ -2736,10 +2726,8 @@ static int ext4_init_new_dir(handle_t *handle, struct inode *dir,
+ 	de = (struct ext4_dir_entry_2 *)dir_block->b_data;
+ 	ext4_init_dot_dotdot(inode, de, blocksize, csum_size, dir->i_ino, 0);
+ 	set_nlink(inode, 2);
+-	if (csum_size) {
+-		t = EXT4_DIRENT_TAIL(dir_block->b_data, blocksize);
+-		initialize_dirent_tail(t, blocksize);
+-	}
++	if (csum_size)
++		ext4_initialize_dirent_tail(dir_block, blocksize);
+ 
+ 	BUFFER_TRACE(dir_block, "call ext4_handle_dirty_metadata");
+ 	err = ext4_handle_dirty_dirblock(handle, inode, dir_block);

commit f036adb39976467cf57f577490269594994f9eb4
+Author: Theodore Ts'o 
+Date:   Fri Jun 21 15:49:26 2019 -0400
+
+    ext4: rename "dirent_csum" functions to use "dirblock"
+    
+    Functions such as ext4_dirent_csum_verify() and ext4_dirent_csum_set()
+    don't actually operate on a directory entry, but a directory block.
+    And while they take a struct ext4_dir_entry *dirent as an argument, it
+    had better be the first directory at the beginning of the direct
+    block, or things will go very wrong.
+    
+    Rename the following functions so that things make more sense, and
+    remove a lot of confusing casts along the way:
+    
+       ext4_dirent_csum_verify       -> ext4_dirblock_csum_verify
+       ext4_dirent_csum_set          -> ext4_dirblock_csum_set
+       ext4_dirent_csum              -> ext4_dirblock_csum
+       ext4_handle_dirty_dirent_node -> ext4_handle_dirty_dirblock
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index 3a77b7affd09..86054f31fe4d 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -194,8 +194,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
+ 
+ 		/* Check the checksum */
+ 		if (!buffer_verified(bh) &&
+-		    !ext4_dirent_csum_verify(inode,
+-				(struct ext4_dir_entry *)bh->b_data)) {
++		    !ext4_dirblock_csum_verify(inode, bh)) {
+ 			EXT4_ERROR_FILE(file, 0, "directory fails checksum "
+ 					"at offset %llu",
+ 					(unsigned long long)ctx->pos);
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 7215a2a2a0de..5b86df7ec326 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2602,8 +2602,8 @@ extern int ext4_ext_migrate(struct inode *);
+ extern int ext4_ind_migrate(struct inode *inode);
+ 
+ /* namei.c */
+-extern int ext4_dirent_csum_verify(struct inode *inode,
+-				   struct ext4_dir_entry *dirent);
++extern int ext4_dirblock_csum_verify(struct inode *inode,
++				     struct buffer_head *bh);
+ extern int ext4_orphan_add(handle_t *, struct inode *);
+ extern int ext4_orphan_del(handle_t *, struct inode *);
+ extern int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
+@@ -3149,9 +3149,8 @@ extern struct ext4_dir_entry_2 *ext4_init_dot_dotdot(struct inode *inode,
+ 				 unsigned int parent_ino, int dotdot_real_len);
+ extern void initialize_dirent_tail(struct ext4_dir_entry_tail *t,
+ 				   unsigned int blocksize);
+-extern int ext4_handle_dirty_dirent_node(handle_t *handle,
+-					 struct inode *inode,
+-					 struct buffer_head *bh);
++extern int ext4_handle_dirty_dirblock(handle_t *handle, struct inode *inode,
++				      struct buffer_head *bh);
+ extern int ext4_ci_compare(const struct inode *parent,
+ 			   const struct qstr *fname,
+ 			   const struct qstr *entry, bool quick);
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index f73bc3925282..f19dd5a08d0d 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -1164,7 +1164,7 @@ static int ext4_finish_convert_inline_dir(handle_t *handle,
+ 		initialize_dirent_tail(t, inode->i_sb->s_blocksize);
+ 	}
+ 	set_buffer_uptodate(dir_block);
+-	err = ext4_handle_dirty_dirent_node(handle, inode, dir_block);
++	err = ext4_handle_dirty_dirblock(handle, inode, dir_block);
+ 	if (err)
+ 		return err;
+ 	set_buffer_verified(dir_block);
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 0cda080f3fd5..4f0bcbbcfe96 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -163,7 +163,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
+ 		}
+ 	}
+ 	if (!is_dx_block) {
+-		if (ext4_dirent_csum_verify(inode, dirent))
++		if (ext4_dirblock_csum_verify(inode, bh))
+ 			set_buffer_verified(bh);
+ 		else {
+ 			ext4_error_inode(inode, func, line, block,
+@@ -304,17 +304,17 @@ void initialize_dirent_tail(struct ext4_dir_entry_tail *t,
+ 
+ /* Walk through a dirent block to find a checksum "dirent" at the tail */
+ static struct ext4_dir_entry_tail *get_dirent_tail(struct inode *inode,
+-						   struct ext4_dir_entry *de)
++						   struct buffer_head *bh)
+ {
+ 	struct ext4_dir_entry_tail *t;
+ 
+ #ifdef PARANOID
+ 	struct ext4_dir_entry *d, *top;
+ 
+-	d = de;
+-	top = (struct ext4_dir_entry *)(((void *)de) +
++	d = (struct ext4_dir_entry *)bh->b_data;
++	top = (struct ext4_dir_entry *)(bh->b_data +
+ 		(EXT4_BLOCK_SIZE(inode->i_sb) -
+-		sizeof(struct ext4_dir_entry_tail)));
++		 sizeof(struct ext4_dir_entry_tail)));
+ 	while (d < top && d->rec_len)
+ 		d = (struct ext4_dir_entry *)(((void *)d) +
+ 		    le16_to_cpu(d->rec_len));
+@@ -324,7 +324,7 @@ static struct ext4_dir_entry_tail *get_dirent_tail(struct inode *inode,
+ 
+ 	t = (struct ext4_dir_entry_tail *)d;
+ #else
+-	t = EXT4_DIRENT_TAIL(de, EXT4_BLOCK_SIZE(inode->i_sb));
++	t = EXT4_DIRENT_TAIL(bh->b_data, EXT4_BLOCK_SIZE(inode->i_sb));
+ #endif
+ 
+ 	if (t->det_reserved_zero1 ||
+@@ -336,8 +336,7 @@ static struct ext4_dir_entry_tail *get_dirent_tail(struct inode *inode,
+ 	return t;
+ }
+ 
+-static __le32 ext4_dirent_csum(struct inode *inode,
+-			       struct ext4_dir_entry *dirent, int size)
++static __le32 ext4_dirblock_csum(struct inode *inode, void *dirent, int size)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+ 	struct ext4_inode_info *ei = EXT4_I(inode);
+@@ -357,49 +356,49 @@ static void __warn_no_space_for_csum(struct inode *inode, const char *func,
+ 		"No space for directory leaf checksum. Please run e2fsck -D.");
+ }
+ 
+-int ext4_dirent_csum_verify(struct inode *inode, struct ext4_dir_entry *dirent)
++int ext4_dirblock_csum_verify(struct inode *inode, struct buffer_head *bh)
+ {
+ 	struct ext4_dir_entry_tail *t;
+ 
+ 	if (!ext4_has_metadata_csum(inode->i_sb))
+ 		return 1;
+ 
+-	t = get_dirent_tail(inode, dirent);
++	t = get_dirent_tail(inode, bh);
+ 	if (!t) {
+ 		warn_no_space_for_csum(inode);
+ 		return 0;
+ 	}
+ 
+-	if (t->det_checksum != ext4_dirent_csum(inode, dirent,
+-						(void *)t - (void *)dirent))
++	if (t->det_checksum != ext4_dirblock_csum(inode, bh->b_data,
++						(char *)t - bh->b_data))
+ 		return 0;
+ 
+ 	return 1;
+ }
+ 
+-static void ext4_dirent_csum_set(struct inode *inode,
+-				 struct ext4_dir_entry *dirent)
++static void ext4_dirblock_csum_set(struct inode *inode,
++				 struct buffer_head *bh)
+ {
+ 	struct ext4_dir_entry_tail *t;
+ 
+ 	if (!ext4_has_metadata_csum(inode->i_sb))
+ 		return;
+ 
+-	t = get_dirent_tail(inode, dirent);
++	t = get_dirent_tail(inode, bh);
+ 	if (!t) {
+ 		warn_no_space_for_csum(inode);
+ 		return;
+ 	}
+ 
+-	t->det_checksum = ext4_dirent_csum(inode, dirent,
+-					   (void *)t - (void *)dirent);
++	t->det_checksum = ext4_dirblock_csum(inode, bh->b_data,
++					   (char *)t - bh->b_data);
+ }
+ 
+-int ext4_handle_dirty_dirent_node(handle_t *handle,
+-				  struct inode *inode,
+-				  struct buffer_head *bh)
++int ext4_handle_dirty_dirblock(handle_t *handle,
++			       struct inode *inode,
++			       struct buffer_head *bh)
+ {
+-	ext4_dirent_csum_set(inode, (struct ext4_dir_entry *)bh->b_data);
++	ext4_dirblock_csum_set(inode, bh);
+ 	return ext4_handle_dirty_metadata(handle, inode, bh);
+ }
+ 
+@@ -1530,8 +1529,7 @@ static struct buffer_head *__ext4_find_entry(struct inode *dir,
+ 		if (!buffer_verified(bh) &&
+ 		    !is_dx_internal_node(dir, block,
+ 					 (struct ext4_dir_entry *)bh->b_data) &&
+-		    !ext4_dirent_csum_verify(dir,
+-				(struct ext4_dir_entry *)bh->b_data)) {
++		    !ext4_dirblock_csum_verify(dir, bh)) {
+ 			EXT4_ERROR_INODE(dir, "checksumming directory "
+ 					 "block %lu", (unsigned long)block);
+ 			brelse(bh);
+@@ -1894,7 +1892,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
+ 		de = de2;
+ 	}
+ 	dx_insert_block(frame, hash2 + continued, newblock);
+-	err = ext4_handle_dirty_dirent_node(handle, dir, bh2);
++	err = ext4_handle_dirty_dirblock(handle, dir, bh2);
+ 	if (err)
+ 		goto journal_error;
+ 	err = ext4_handle_dirty_dx_node(handle, dir, frame->bh);
+@@ -2022,7 +2020,7 @@ static int add_dirent_to_buf(handle_t *handle, struct ext4_filename *fname,
+ 	inode_inc_iversion(dir);
+ 	ext4_mark_inode_dirty(handle, dir);
+ 	BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
+-	err = ext4_handle_dirty_dirent_node(handle, dir, bh);
++	err = ext4_handle_dirty_dirblock(handle, dir, bh);
+ 	if (err)
+ 		ext4_std_error(dir->i_sb, err);
+ 	return 0;
+@@ -2126,7 +2124,7 @@ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname,
+ 	retval = ext4_handle_dirty_dx_node(handle, dir, frame->bh);
+ 	if (retval)
+ 		goto out_frames;	
+-	retval = ext4_handle_dirty_dirent_node(handle, dir, bh2);
++	retval = ext4_handle_dirty_dirblock(handle, dir, bh2);
+ 	if (retval)
+ 		goto out_frames;	
+ 
+@@ -2512,7 +2510,7 @@ static int ext4_delete_entry(handle_t *handle,
+ 		goto out;
+ 
+ 	BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
+-	err = ext4_handle_dirty_dirent_node(handle, dir, bh);
++	err = ext4_handle_dirty_dirblock(handle, dir, bh);
+ 	if (unlikely(err))
+ 		goto out;
+ 
+@@ -2744,7 +2742,7 @@ static int ext4_init_new_dir(handle_t *handle, struct inode *dir,
+ 	}
+ 
+ 	BUFFER_TRACE(dir_block, "call ext4_handle_dirty_metadata");
+-	err = ext4_handle_dirty_dirent_node(handle, inode, dir_block);
++	err = ext4_handle_dirty_dirblock(handle, inode, dir_block);
+ 	if (err)
+ 		goto out;
+ 	set_buffer_verified(dir_block);
+@@ -3492,9 +3490,8 @@ static int ext4_rename_dir_finish(handle_t *handle, struct ext4_renament *ent,
+ 							   ent->inode,
+ 							   ent->dir_bh);
+ 		} else {
+-			retval = ext4_handle_dirty_dirent_node(handle,
+-							       ent->inode,
+-							       ent->dir_bh);
++			retval = ext4_handle_dirty_dirblock(handle, ent->inode,
++							    ent->dir_bh);
+ 		}
+ 	} else {
+ 		retval = ext4_mark_inode_dirty(handle, ent->inode);
+@@ -3524,8 +3521,7 @@ static int ext4_setent(handle_t *handle, struct ext4_renament *ent,
+ 	ext4_mark_inode_dirty(handle, ent->dir);
+ 	BUFFER_TRACE(ent->bh, "call ext4_handle_dirty_metadata");
+ 	if (!ent->inlined) {
+-		retval = ext4_handle_dirty_dirent_node(handle,
+-						       ent->dir, ent->bh);
++		retval = ext4_handle_dirty_dirblock(handle, ent->dir, ent->bh);
+ 		if (unlikely(retval)) {
+ 			ext4_std_error(ent->dir->i_sb, retval);
+ 			return retval;

commit 4e19d6b65fb4fc42e352ce9883649e049da14743
+Author: Theodore Ts'o 
+Date:   Thu Jun 20 21:19:02 2019 -0400
+
+    ext4: allow directory holes
+    
+    The largedir feature was intended to allow ext4 directories to have
+    unmapped directory blocks (e.g., directory holes).  And so the
+    released e2fsprogs no longer enforces this for largedir file systems;
+    however, the corresponding change to the kernel-side code was not made.
+    
+    This commit fixes this oversight.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index 770a1e6d4672..3a77b7affd09 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -112,7 +112,6 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
+ 	struct inode *inode = file_inode(file);
+ 	struct super_block *sb = inode->i_sb;
+ 	struct buffer_head *bh = NULL;
+-	int dir_has_error = 0;
+ 	struct fscrypt_str fstr = FSTR_INIT(NULL, 0);
+ 
+ 	if (IS_ENCRYPTED(inode)) {
+@@ -148,8 +147,6 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
+ 			return err;
+ 	}
+ 
+-	offset = ctx->pos & (sb->s_blocksize - 1);
+-
+ 	while (ctx->pos < inode->i_size) {
+ 		struct ext4_map_blocks map;
+ 
+@@ -158,9 +155,18 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
+ 			goto errout;
+ 		}
+ 		cond_resched();
++		offset = ctx->pos & (sb->s_blocksize - 1);
+ 		map.m_lblk = ctx->pos >> EXT4_BLOCK_SIZE_BITS(sb);
+ 		map.m_len = 1;
+ 		err = ext4_map_blocks(NULL, inode, &map, 0);
++		if (err == 0) {
++			/* m_len should never be zero but let's avoid
++			 * an infinite loop if it somehow is */
++			if (map.m_len == 0)
++				map.m_len = 1;
++			ctx->pos += map.m_len * sb->s_blocksize;
++			continue;
++		}
+ 		if (err > 0) {
+ 			pgoff_t index = map.m_pblk >>
+ 					(PAGE_SHIFT - inode->i_blkbits);
+@@ -179,13 +185,6 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
+ 		}
+ 
+ 		if (!bh) {
+-			if (!dir_has_error) {
+-				EXT4_ERROR_FILE(file, 0,
+-						"directory contains a "
+-						"hole at offset %llu",
+-					   (unsigned long long) ctx->pos);
+-				dir_has_error = 1;
+-			}
+ 			/* corrupt size?  Maybe no more blocks to read */
+ 			if (ctx->pos > inode->i_blocks << 9)
+ 				break;
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 4909ced4e672..0cda080f3fd5 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -82,8 +82,18 @@ static struct buffer_head *ext4_append(handle_t *handle,
+ static int ext4_dx_csum_verify(struct inode *inode,
+ 			       struct ext4_dir_entry *dirent);
+ 
++/*
++ * Hints to ext4_read_dirblock regarding whether we expect a directory
++ * block being read to be an index block, or a block containing
++ * directory entries (and if the latter, whether it was found via a
++ * logical block in an htree index block).  This is used to control
++ * what sort of sanity checkinig ext4_read_dirblock() will do on the
++ * directory block read from the storage device.  EITHER will means
++ * the caller doesn't know what kind of directory block will be read,
++ * so no specific verification will be done.
++ */
+ typedef enum {
+-	EITHER, INDEX, DIRENT
++	EITHER, INDEX, DIRENT, DIRENT_HTREE
+ } dirblock_type_t;
+ 
+ #define ext4_read_dirblock(inode, block, type) \
+@@ -109,11 +119,14 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
+ 
+ 		return bh;
+ 	}
+-	if (!bh) {
++	if (!bh && (type == INDEX || type == DIRENT_HTREE)) {
+ 		ext4_error_inode(inode, func, line, block,
+-				 "Directory hole found");
++				 "Directory hole found for htree %s block",
++				 (type == INDEX) ? "index" : "leaf");
+ 		return ERR_PTR(-EFSCORRUPTED);
+ 	}
++	if (!bh)
++		return NULL;
+ 	dirent = (struct ext4_dir_entry *) bh->b_data;
+ 	/* Determine whether or not we have an index block */
+ 	if (is_dx(inode)) {
+@@ -980,7 +993,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
+ 
+ 	dxtrace(printk(KERN_INFO "In htree dirblock_to_tree: block %lu\n",
+ 							(unsigned long)block));
+-	bh = ext4_read_dirblock(dir, block, DIRENT);
++	bh = ext4_read_dirblock(dir, block, DIRENT_HTREE);
+ 	if (IS_ERR(bh))
+ 		return PTR_ERR(bh);
+ 
+@@ -1619,7 +1632,7 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
+ 		return (struct buffer_head *) frame;
+ 	do {
+ 		block = dx_get_block(frame->at);
+-		bh = ext4_read_dirblock(dir, block, DIRENT);
++		bh = ext4_read_dirblock(dir, block, DIRENT_HTREE);
+ 		if (IS_ERR(bh))
+ 			goto errout;
+ 
+@@ -2203,6 +2216,11 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
+ 	blocks = dir->i_size >> sb->s_blocksize_bits;
+ 	for (block = 0; block < blocks; block++) {
+ 		bh = ext4_read_dirblock(dir, block, DIRENT);
++		if (bh == NULL) {
++			bh = ext4_bread(handle, dir, block,
++					EXT4_GET_BLOCKS_CREATE);
++			goto add_to_new_block;
++		}
+ 		if (IS_ERR(bh)) {
+ 			retval = PTR_ERR(bh);
+ 			bh = NULL;
+@@ -2223,6 +2241,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
+ 		brelse(bh);
+ 	}
+ 	bh = ext4_append(handle, dir, &block);
++add_to_new_block:
+ 	if (IS_ERR(bh)) {
+ 		retval = PTR_ERR(bh);
+ 		bh = NULL;
+@@ -2267,7 +2286,7 @@ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
+ 		return PTR_ERR(frame);
+ 	entries = frame->entries;
+ 	at = frame->at;
+-	bh = ext4_read_dirblock(dir, dx_get_block(frame->at), DIRENT);
++	bh = ext4_read_dirblock(dir, dx_get_block(frame->at), DIRENT_HTREE);
+ 	if (IS_ERR(bh)) {
+ 		err = PTR_ERR(bh);
+ 		bh = NULL;
+@@ -2815,7 +2834,10 @@ bool ext4_empty_dir(struct inode *inode)
+ 		EXT4_ERROR_INODE(inode, "invalid size");
+ 		return true;
+ 	}
+-	bh = ext4_read_dirblock(inode, 0, EITHER);
++	/* The first directory block must not be a hole,
++	 * so treat it as DIRENT_HTREE
++	 */
++	bh = ext4_read_dirblock(inode, 0, DIRENT_HTREE);
+ 	if (IS_ERR(bh))
+ 		return true;
+ 
+@@ -2837,6 +2859,10 @@ bool ext4_empty_dir(struct inode *inode)
+ 			brelse(bh);
+ 			lblock = offset >> EXT4_BLOCK_SIZE_BITS(sb);
+ 			bh = ext4_read_dirblock(inode, lblock, EITHER);
++			if (bh == NULL) {
++				offset += sb->s_blocksize;
++				continue;
++			}
+ 			if (IS_ERR(bh))
+ 				return true;
+ 			de = (struct ext4_dir_entry_2 *) bh->b_data;
+@@ -3402,7 +3428,10 @@ static struct buffer_head *ext4_get_first_dir_block(handle_t *handle,
+ 	struct buffer_head *bh;
+ 
+ 	if (!ext4_has_inline_data(inode)) {
+-		bh = ext4_read_dirblock(inode, 0, EITHER);
++		/* The first directory block must not be a hole, so
++		 * treat it as DIRENT_HTREE
++		 */
++		bh = ext4_read_dirblock(inode, 0, DIRENT_HTREE);
+ 		if (IS_ERR(bh)) {
+ 			*retval = PTR_ERR(bh);
+ 			return NULL;

commit 9382cde8cd8fb941fc333b644a5772d02e1ff924
+Author: Theodore Ts'o 
+Date:   Thu Jun 20 17:32:21 2019 -0400
+
+    jbd2: drop declaration of journal_sync_buffer()
+    
+    The journal_sync_buffer() function was never carried over from jbd to
+    jbd2.  So get rid of the vestigal declaration of this (non-existent)
+    function.
+    
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Darrick J. Wong 
+
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 17f679aeba7c..953990eb70a9 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -66,9 +66,6 @@ EXPORT_SYMBOL(jbd2_journal_get_undo_access);
+ EXPORT_SYMBOL(jbd2_journal_set_triggers);
+ EXPORT_SYMBOL(jbd2_journal_dirty_metadata);
+ EXPORT_SYMBOL(jbd2_journal_forget);
+-#if 0
+-EXPORT_SYMBOL(journal_sync_buffer);
+-#endif
+ EXPORT_SYMBOL(jbd2_journal_flush);
+ EXPORT_SYMBOL(jbd2_journal_revoke);
+ 
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index 0e0393e7f41a..df03825ad1a1 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -1373,7 +1373,6 @@ void		 jbd2_journal_set_triggers(struct buffer_head *,
+ 					   struct jbd2_buffer_trigger_type *type);
+ extern int	 jbd2_journal_dirty_metadata (handle_t *, struct buffer_head *);
+ extern int	 jbd2_journal_forget (handle_t *, struct buffer_head *);
+-extern void	 journal_sync_buffer (struct buffer_head *);
+ extern int	 jbd2_journal_invalidatepage(journal_t *,
+ 				struct page *, unsigned int, unsigned int);
+ extern int	 jbd2_journal_try_to_free_buffers(journal_t *, struct page *, gfp_t);

commit c60990b361cc0a08e7b442a8191d89e9304c2d62
+Author: Theodore Ts'o 
+Date:   Wed Jun 19 16:30:03 2019 -0400
+
+    ext4: clean up kerneldoc warnigns when building with W=1
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index e5d6ee61ff48..0b202e00d93f 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -603,9 +603,9 @@ int ext4_claim_free_clusters(struct ext4_sb_info *sbi,
+ }
+ 
+ /**
+- * ext4_should_retry_alloc()
++ * ext4_should_retry_alloc() - check if a block allocation should be retried
+  * @sb:			super block
+- * @retries		number of attemps has been made
++ * @retries:		number of attemps has been made
+  *
+  * ext4_should_retry_alloc() is called when ENOSPC is returned, and if
+  * it is profitable to retry the operation, this function will wait
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index c7843b149a1e..1f7784bee42a 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -33,6 +33,9 @@
+ static int ext4_dx_readdir(struct file *, struct dir_context *);
+ 
+ /**
++ * is_dx_dir() - check if a directory is using htree indexing
++ * @inode: directory inode
++ *
+  * Check if the given dir-inode refers to an htree-indexed directory
+  * (or a directory which could potentially get converted to use htree
+  * indexing).
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index d40ed940001e..92266a2da7d6 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -5676,8 +5676,8 @@ int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len)
+ }
+ 
+ /**
+- * ext4_swap_extents - Swap extents between two inodes
+- *
++ * ext4_swap_extents() - Swap extents between two inodes
++ * @handle: handle for this transaction
+  * @inode1:	First inode
+  * @inode2:	Second inode
+  * @lblk1:	Start block for first inode
+diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
+index 2024d3fa5504..36699a131168 100644
+--- a/fs/ext4/indirect.c
++++ b/fs/ext4/indirect.c
+@@ -294,14 +294,12 @@ static int ext4_blks_to_allocate(Indirect *branch, int k, unsigned int blks,
+ }
+ 
+ /**
+- *	ext4_alloc_branch - allocate and set up a chain of blocks.
+- *	@handle: handle for this transaction
+- *	@inode: owner
+- *	@indirect_blks: number of allocated indirect blocks
+- *	@blks: number of allocated direct blocks
+- *	@goal: preferred place for allocation
+- *	@offsets: offsets (in the blocks) to store the pointers to next.
+- *	@branch: place to store the chain in.
++ * ext4_alloc_branch() - allocate and set up a chain of blocks
++ * @handle: handle for this transaction
++ * @ar: structure describing the allocation request
++ * @indirect_blks: number of allocated indirect blocks
++ * @offsets: offsets (in the blocks) to store the pointers to next.
++ * @branch: place to store the chain in.
+  *
+  *	This function allocates blocks, zeroes out all but the last one,
+  *	links them into chain and (if we are synchronous) writes them to disk.
+@@ -396,15 +394,11 @@ static int ext4_alloc_branch(handle_t *handle,
+ }
+ 
+ /**
+- * ext4_splice_branch - splice the allocated branch onto inode.
++ * ext4_splice_branch() - splice the allocated branch onto inode.
+  * @handle: handle for this transaction
+- * @inode: owner
+- * @block: (logical) number of block we are adding
+- * @chain: chain of indirect blocks (with a missing link - see
+- *	ext4_alloc_branch)
++ * @ar: structure describing the allocation request
+  * @where: location of missing link
+  * @num:   number of indirect blocks we are adding
+- * @blks:  number of direct blocks we are adding
+  *
+  * This function fills the missing link and does all housekeeping needed in
+  * inode (->i_blocks, etc.). In case of success we end up with the full
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 99ba720dbb7a..a3e2767bdf2f 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -4696,8 +4696,9 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
+  * ext4_free_blocks() -- Free given blocks and update quota
+  * @handle:		handle for this transaction
+  * @inode:		inode
+- * @block:		start physical block to free
+- * @count:		number of blocks to count
++ * @bh:			optional buffer of the block to be freed
++ * @block:		starting physical block to be freed
++ * @count:		number of blocks to be freed
+  * @flags:		flags used by ext4_free_blocks
+  */
+ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
+index 1083a9f3f16a..3ec9627c9713 100644
+--- a/fs/ext4/move_extent.c
++++ b/fs/ext4/move_extent.c
+@@ -13,11 +13,10 @@
+ #include "ext4_extents.h"
+ 
+ /**
+- * get_ext_path - Find an extent path for designated logical block number.
+- *
+- * @inode:	an inode which is searched
++ * get_ext_path() - Find an extent path for designated logical block number.
++ * @inode:	inode to be searched
+  * @lblock:	logical block number to find an extent path
+- * @path:	pointer to an extent path pointer (for output)
++ * @ppath:	pointer to an extent path pointer (for output)
+  *
+  * ext4_find_extent wrapper. Return 0 on success, or a negative error value
+  * on failure.
+@@ -42,8 +41,9 @@ get_ext_path(struct inode *inode, ext4_lblk_t lblock,
+ }
+ 
+ /**
+- * ext4_double_down_write_data_sem - Acquire two inodes' write lock
+- *                                   of i_data_sem
++ * ext4_double_down_write_data_sem() - write lock two inodes's i_data_sem
++ * @first: inode to be locked
++ * @second: inode to be locked
+  *
+  * Acquire write lock of i_data_sem of the two inodes
+  */

commit 02b016ca7f99229ae6227e7b2fc950c4e140d74a
+Author: Theodore Ts'o 
+Date:   Sun Jun 9 22:04:33 2019 -0400
+
+    ext4: enforce the immutable flag on open files
+    
+    According to the chattr man page, "a file with the 'i' attribute
+    cannot be modified..."  Historically, this was only enforced when the
+    file was opened, per the rest of the description, "... and the file
+    can not be opened in write mode".
+    
+    There is general agreement that we should standardize all file systems
+    to prevent modifications even for files that were opened at the time
+    the immutable flag is set.  Eventually, a change to enforce this at
+    the VFS layer should be landing in mainline.  Until then, enforce this
+    at the ext4 level to prevent xfstests generic/553 from failing.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: "Darrick J. Wong" 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/file.c b/fs/ext4/file.c
+index 2c5baa5e8291..f4a24a46245e 100644
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -165,6 +165,10 @@ static ssize_t ext4_write_checks(struct kiocb *iocb, struct iov_iter *from)
+ 	ret = generic_write_checks(iocb, from);
+ 	if (ret <= 0)
+ 		return ret;
++
++	if (unlikely(IS_IMMUTABLE(inode)))
++		return -EPERM;
++
+ 	/*
+ 	 * If we have encountered a bitmap-format file, the size limit
+ 	 * is smaller than s_maxbytes, which is for extent-mapped files.
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index c16071547c9c..ed1d8f9ce5f9 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -5520,6 +5520,14 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
+ 	if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
+ 		return -EIO;
+ 
++	if (unlikely(IS_IMMUTABLE(inode)))
++		return -EPERM;
++
++	if (unlikely(IS_APPEND(inode) &&
++		     (ia_valid & (ATTR_MODE | ATTR_UID |
++				  ATTR_GID | ATTR_TIMES_SET))))
++		return -EPERM;
++
+ 	error = setattr_prepare(dentry, attr);
+ 	if (error)
+ 		return error;
+@@ -6194,6 +6202,9 @@ vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf)
+ 	get_block_t *get_block;
+ 	int retries = 0;
+ 
++	if (unlikely(IS_IMMUTABLE(inode)))
++		return VM_FAULT_SIGBUS;
++
+ 	sb_start_pagefault(inode->i_sb);
+ 	file_update_time(vma->vm_file);
+ 

commit 58be0106c5306b939b07b4b8bf00669a20593f4b
+Author: Theodore Ts'o 
+Date:   Wed May 22 12:02:16 2019 -0400
+
+    random: fix soft lockup when trying to read from an uninitialized blocking pool
+    
+    Fixes: eb9d1bf079bb: "random: only read from /dev/random after its pool has received 128 bits"
+    Reported-by: kernel test robot 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index a42b3d764da8..5d5ea4ce1442 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -772,8 +772,11 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
+ 	if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
+ 		goto retry;
+ 
+-	if (has_initialized)
++	if (has_initialized) {
+ 		r->initialized = 1;
++		wake_up_interruptible(&random_read_wait);
++		kill_fasync(&fasync, SIGIO, POLL_IN);
++	}
+ 
+ 	trace_credit_entropy_bits(r->name, nbits,
+ 				  entropy_count >> ENTROPY_SHIFT, _RET_IP_);
+@@ -789,6 +792,13 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
+ 			entropy_bits = r->entropy_count >> ENTROPY_SHIFT;
+ 		}
+ 
++		/* initialize the blocking pool if necessary */
++		if (entropy_bits >= random_read_wakeup_bits &&
++		    !other->initialized) {
++			schedule_work(&other->push_work);
++			return;
++		}
++
+ 		/* should we wake readers? */
+ 		if (entropy_bits >= random_read_wakeup_bits &&
+ 		    wq_has_sleeper(&random_read_wait)) {
+@@ -1936,8 +1946,8 @@ _random_read(int nonblock, char __user *buf, size_t nbytes)
+ 			return -EAGAIN;
+ 
+ 		wait_event_interruptible(random_read_wait,
+-			ENTROPY_BITS(&input_pool) >=
+-			random_read_wakeup_bits);
++		    blocking_pool.initialized &&
++		    (ENTROPY_BITS(&input_pool) >= random_read_wakeup_bits));
+ 		if (signal_pending(current))
+ 			return -ERESTARTSYS;
+ 	}

commit 0a944e8a6c66ca04c7afbaa17e22bf208a8b37f0
+Author: Theodore Ts'o 
+Date:   Wed May 22 10:27:01 2019 -0400
+
+    ext4: don't perform block validity checks on the journal inode
+    
+    Since the journal inode is already checked when we added it to the
+    block validity's system zone, if we check it again, we'll just trigger
+    a failure.
+    
+    This was causing failures like this:
+    
+    [   53.897001] EXT4-fs error (device sda): ext4_find_extent:909: inode
+    #8: comm jbd2/sda-8: pblk 121667583 bad header/extent: invalid extent entries - magic f30a, entries 8, max 340(340), depth 0(0)
+    [   53.931430] jbd2_journal_bmap: journal block not found at offset 49 on sda-8
+    [   53.938480] Aborting journal on device sda-8.
+    
+    ... but only if the system was under enough memory pressure that
+    logical->physical mapping for the journal inode gets pushed out of the
+    extent cache.  (This is why it wasn't noticed earlier.)
+    
+    Fixes: 345c0dbf3a30 ("ext4: protect journal inode's blocks using block_validity")
+    Reported-by: Dan Rue 
+    Signed-off-by: Theodore Ts'o 
+    Tested-by: Naresh Kamboju 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index f2c62e2a0c98..d40ed940001e 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -518,10 +518,14 @@ __read_extent_tree_block(const char *function, unsigned int line,
+ 	}
+ 	if (buffer_verified(bh) && !(flags & EXT4_EX_FORCE_CACHE))
+ 		return bh;
+-	err = __ext4_ext_check(function, line, inode,
+-			       ext_block_hdr(bh), depth, pblk);
+-	if (err)
+-		goto errout;
++	if (!ext4_has_feature_journal(inode->i_sb) ||
++	    (inode->i_ino !=
++	     le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum))) {
++		err = __ext4_ext_check(function, line, inode,
++				       ext_block_hdr(bh), depth, pblk);
++		if (err)
++			goto errout;
++	}
+ 	set_buffer_verified(bh);
+ 	/*
+ 	 * If this is a leaf block, cache all of its entries

commit 170417c8c7bb2cbbdd949bf5c443c0c8f24a203b
+Author: Theodore Ts'o 
+Date:   Wed May 15 00:51:19 2019 -0400
+
+    ext4: fix block validity checks for journal inodes using indirect blocks
+    
+    Commit 345c0dbf3a30 ("ext4: protect journal inode's blocks using
+    block_validity") failed to add an exception for the journal inode in
+    ext4_check_blockref(), which is the function used by ext4_get_branch()
+    for indirect blocks.  This caused attempts to read from the ext3-style
+    journals to fail with:
+    
+    [  848.968550] EXT4-fs error (device sdb7): ext4_get_branch:171: inode #8: block 30343695: comm jbd2/sdb7-8: invalid block
+    
+    Fix this by adding the missing exception check.
+    
+    Fixes: 345c0dbf3a30 ("ext4: protect journal inode's blocks using block_validity")
+    Reported-by: Arthur Marsh 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/block_validity.c b/fs/ext4/block_validity.c
+index 8d03550aaae3..8e83741b02e0 100644
+--- a/fs/ext4/block_validity.c
++++ b/fs/ext4/block_validity.c
+@@ -277,6 +277,11 @@ int ext4_check_blockref(const char *function, unsigned int line,
+ 	__le32 *bref = p;
+ 	unsigned int blk;
+ 
++	if (ext4_has_feature_journal(inode->i_sb) &&
++	    (inode->i_ino ==
++	     le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum)))
++		return 0;
++
+ 	while (bref < p+max) {
+ 		blk = le32_to_cpu(*bref++);
+ 		if (blk &&

commit 7fb64133360b10edcae3c6f5afffaa449668831e
+Author: Theodore Ts'o 
+Date:   Sun May 12 13:26:08 2019 -0400
+
+    unicode: update to Unicode 12.1.0 final
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: Gabriel Krisman Bertazi 
+
+diff --git a/fs/unicode/README.utf8data b/fs/unicode/README.utf8data
+index 9307cf0727de..c73786807d3b 100644
+--- a/fs/unicode/README.utf8data
++++ b/fs/unicode/README.utf8data
+@@ -5,29 +5,15 @@ The full set of files can be found here:
+ 
+   http://www.unicode.org/Public/12.1.0/ucd/
+ 
+-Note!
+-
+-The URL's listed below are not stable.  That's because Unicode 12.1.0
+-has not been officially released yet; it is scheduled to be released
+-on May 8, 2019.  We taking Unicode 12.1.0 a few weeks early because it
+-contains a new Japanese character which is required in order to
+-specify Japenese dates after May 1, 2019, when Crown Prince Naruhito
+-ascends to the Chrysanthemum Throne.  (Isn't internationalization fun?
+-The abdication of Emperor Akihito of Japan is requiring dozens of
+-software packages to be updated with only a month's notice.  :-)
+-
+-We will update the URL's (and any needed changes to the checksums)
+-after the final Unicode 12.1.0 is released.
+-
+ Individual source links:
+ 
+-  https://www.unicode.org/Public/12.1.0/ucd/CaseFolding-12.1.0d2.txt
+-  https://www.unicode.org/Public/12.1.0/ucd/DerivedAge-12.1.0d3.txt
+-  https://www.unicode.org/Public/12.1.0/ucd/extracted/DerivedCombiningClass-12.1.0d2.txt
+-  https://www.unicode.org/Public/12.1.0/ucd/DerivedCoreProperties-12.1.0d2.txt
+-  https://www.unicode.org/Public/12.1.0/ucd/NormalizationCorrections-12.1.0d1.txt
+-  https://www.unicode.org/Public/12.1.0/ucd/NormalizationTest-12.1.0d3.txt
+-  https://www.unicode.org/Public/12.1.0/ucd/UnicodeData-12.1.0d2.txt
++  https://www.unicode.org/Public/12.1.0/ucd/CaseFolding.txt
++  https://www.unicode.org/Public/12.1.0/ucd/DerivedAge.txt
++  https://www.unicode.org/Public/12.1.0/ucd/extracted/DerivedCombiningClass.txt
++  https://www.unicode.org/Public/12.1.0/ucd/DerivedCoreProperties.txt
++  https://www.unicode.org/Public/12.1.0/ucd/NormalizationCorrections.txt
++  https://www.unicode.org/Public/12.1.0/ucd/NormalizationTest.txt
++  https://www.unicode.org/Public/12.1.0/ucd/UnicodeData.txt
+ 
+ md5sums (verify by running "md5sum -c README.utf8data"):
+ 

commit 15f0d8d0bafb0d841dde53af549c4c44b059d7f5
+Author: Theodore Ts'o 
+Date:   Sun May 12 04:56:51 2019 -0400
+
+    unicode: add missing check for an error return from utf8lookup()
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: Gabriel Krisman Bertazi 
+
+diff --git a/fs/unicode/utf8-norm.c b/fs/unicode/utf8-norm.c
+index 20d440c3f2db..801ed6d2ea37 100644
+--- a/fs/unicode/utf8-norm.c
++++ b/fs/unicode/utf8-norm.c
+@@ -714,6 +714,8 @@ int utf8byte(struct utf8cursor *u8c)
+ 			}
+ 
+ 			leaf = utf8lookup(u8c->data, u8c->hangul, u8c->s);
++			if (!leaf)
++				return -1;
+ 			ccc = LEAF_CCC(leaf);
+ 		}
+ 

commit 0ba33facfc9bb556d1938caa67dfe452695a9be9
+Author: Theodore Ts'o 
+Date:   Sun May 12 04:49:47 2019 -0400
+
+    ext4: fix miscellaneous sparse warnings
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/fsmap.c b/fs/ext4/fsmap.c
+index 4b99e2db95b8..dbccf46f1770 100644
+--- a/fs/ext4/fsmap.c
++++ b/fs/ext4/fsmap.c
+@@ -626,7 +626,7 @@ int ext4_getfsmap(struct super_block *sb, struct ext4_fsmap_head *head,
+ {
+ 	struct ext4_fsmap dkeys[2];	/* per-dev keys */
+ 	struct ext4_getfsmap_dev handlers[EXT4_GETFSMAP_DEVS];
+-	struct ext4_getfsmap_info info = {0};
++	struct ext4_getfsmap_info info = { NULL };
+ 	int i;
+ 	int error = 0;
+ 
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index 7e85ecf0b849..e486e49b31ed 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -608,7 +608,7 @@ static int ext4_getfsmap_format(struct ext4_fsmap *xfm, void *priv)
+ static int ext4_ioc_getfsmap(struct super_block *sb,
+ 			     struct fsmap_head __user *arg)
+ {
+-	struct getfsmap_info info = {0};
++	struct getfsmap_info info = { NULL };
+ 	struct ext4_fsmap_head xhead = {0};
+ 	struct fsmap_head head;
+ 	bool aborted = false;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index fc6fa2c93e77..5013d04b41fd 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4679,7 +4679,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 
+ #ifdef CONFIG_QUOTA
+ 	for (i = 0; i < EXT4_MAXQUOTAS; i++)
+-		kfree(sbi->s_qf_names[i]);
++		kfree(get_qf_name(sb, sbi, i));
+ #endif
+ 	ext4_blkdev_remove(sbi);
+ 	brelse(bh);

commit db90f41916cf04c020062f8d8b0385942248283e
+Author: Theodore Ts'o 
+Date:   Mon May 6 14:03:52 2019 -0400
+
+    ext4: export /sys/fs/ext4/feature/casefold if Unicode support is present
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c
+index 616c075da062..04b4f53f0659 100644
+--- a/fs/ext4/sysfs.c
++++ b/fs/ext4/sysfs.c
+@@ -238,6 +238,9 @@ EXT4_ATTR_FEATURE(meta_bg_resize);
+ #ifdef CONFIG_FS_ENCRYPTION
+ EXT4_ATTR_FEATURE(encryption);
+ #endif
++#ifdef CONFIG_UNICODE
++EXT4_ATTR_FEATURE(casefold);
++#endif
+ EXT4_ATTR_FEATURE(metadata_csum_seed);
+ 
+ static struct attribute *ext4_feat_attrs[] = {
+@@ -246,6 +249,9 @@ static struct attribute *ext4_feat_attrs[] = {
+ 	ATTR_LIST(meta_bg_resize),
+ #ifdef CONFIG_FS_ENCRYPTION
+ 	ATTR_LIST(encryption),
++#endif
++#ifdef CONFIG_UNICODE
++	ATTR_LIST(casefold),
+ #endif
+ 	ATTR_LIST(metadata_csum_seed),
+ 	NULL,

commit eb9d1bf079bb438d1a066d72337092935fc770f6
+Author: Theodore Ts'o 
+Date:   Wed Feb 20 16:06:38 2019 -0500
+
+    random: only read from /dev/random after its pool has received 128 bits
+    
+    Immediately after boot, we allow reads from /dev/random before its
+    entropy pool has been fully initialized.  Fix this so that we don't
+    allow this until the blocking pool has received 128 bits.
+    
+    We do this by repurposing the initialized flag in the entropy pool
+    struct, and use the initialized flag in the blocking pool to indicate
+    whether it is safe to pull from the blocking pool.
+    
+    To do this, we needed to rework when we decide to push entropy from the
+    input pool to the blocking pool, since the initialized flag for the
+    input pool was used for this purpose.  To simplify things, we no
+    longer use the initialized flag for that purpose, nor do we use the
+    entropy_total field any more.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 47ac7cd20fb1..e247c45b2772 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -470,7 +470,6 @@ struct entropy_store {
+ 	unsigned short add_ptr;
+ 	unsigned short input_rotate;
+ 	int entropy_count;
+-	int entropy_total;
+ 	unsigned int initialized:1;
+ 	unsigned int last_data_init:1;
+ 	__u8 last_data[EXTRACT_SIZE];
+@@ -643,7 +642,7 @@ static void process_random_ready_list(void)
+  */
+ static void credit_entropy_bits(struct entropy_store *r, int nbits)
+ {
+-	int entropy_count, orig;
++	int entropy_count, orig, has_initialized = 0;
+ 	const int pool_size = r->poolinfo->poolfracbits;
+ 	int nfrac = nbits << ENTROPY_SHIFT;
+ 
+@@ -698,23 +697,25 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
+ 		entropy_count = 0;
+ 	} else if (entropy_count > pool_size)
+ 		entropy_count = pool_size;
++	if ((r == &blocking_pool) && !r->initialized &&
++	    (entropy_count >> ENTROPY_SHIFT) > 128)
++		has_initialized = 1;
+ 	if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
+ 		goto retry;
+ 
+-	r->entropy_total += nbits;
+-	if (!r->initialized && r->entropy_total > 128) {
++	if (has_initialized)
+ 		r->initialized = 1;
+-		r->entropy_total = 0;
+-	}
+ 
+ 	trace_credit_entropy_bits(r->name, nbits,
+-				  entropy_count >> ENTROPY_SHIFT,
+-				  r->entropy_total, _RET_IP_);
++				  entropy_count >> ENTROPY_SHIFT, _RET_IP_);
+ 
+ 	if (r == &input_pool) {
+ 		int entropy_bits = entropy_count >> ENTROPY_SHIFT;
++		struct entropy_store *other = &blocking_pool;
+ 
+-		if (crng_init < 2 && entropy_bits >= 128) {
++		if (crng_init < 2) {
++			if (entropy_bits < 128)
++				return;
+ 			crng_reseed(&primary_crng, r);
+ 			entropy_bits = r->entropy_count >> ENTROPY_SHIFT;
+ 		}
+@@ -725,20 +726,14 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
+ 			wake_up_interruptible(&random_read_wait);
+ 			kill_fasync(&fasync, SIGIO, POLL_IN);
+ 		}
+-		/* If the input pool is getting full, send some
+-		 * entropy to the blocking pool until it is 75% full.
++		/* If the input pool is getting full, and the blocking
++		 * pool has room, send some entropy to the blocking
++		 * pool.
+ 		 */
+-		if (entropy_bits > random_write_wakeup_bits &&
+-		    r->initialized &&
+-		    r->entropy_total >= 2*random_read_wakeup_bits) {
+-			struct entropy_store *other = &blocking_pool;
+-
+-			if (other->entropy_count <=
+-			    3 * other->poolinfo->poolfracbits / 4) {
+-				schedule_work(&other->push_work);
+-				r->entropy_total = 0;
+-			}
+-		}
++		if (!work_pending(&other->push_work) &&
++		    (ENTROPY_BITS(r) > 6 * r->poolinfo->poolbytes) &&
++		    (ENTROPY_BITS(other) <= 6 * other->poolinfo->poolbytes))
++			schedule_work(&other->push_work);
+ 	}
+ }
+ 
+@@ -1553,6 +1548,11 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
+ 	int large_request = (nbytes > 256);
+ 
+ 	trace_extract_entropy_user(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_);
++	if (!r->initialized && r->pull) {
++		xfer_secondary_pool(r, ENTROPY_BITS(r->pull)/8);
++		if (!r->initialized)
++			return 0;
++	}
+ 	xfer_secondary_pool(r, nbytes);
+ 	nbytes = account(r, nbytes, 0, 0);
+ 
+diff --git a/include/trace/events/random.h b/include/trace/events/random.h
+index 0560dfc33f1c..32c10a515e2d 100644
+--- a/include/trace/events/random.h
++++ b/include/trace/events/random.h
+@@ -62,15 +62,14 @@ DEFINE_EVENT(random__mix_pool_bytes, mix_pool_bytes_nolock,
+ 
+ TRACE_EVENT(credit_entropy_bits,
+ 	TP_PROTO(const char *pool_name, int bits, int entropy_count,
+-		 int entropy_total, unsigned long IP),
++		 unsigned long IP),
+ 
+-	TP_ARGS(pool_name, bits, entropy_count, entropy_total, IP),
++	TP_ARGS(pool_name, bits, entropy_count, IP),
+ 
+ 	TP_STRUCT__entry(
+ 		__field( const char *,	pool_name		)
+ 		__field(	  int,	bits			)
+ 		__field(	  int,	entropy_count		)
+-		__field(	  int,	entropy_total		)
+ 		__field(unsigned long,	IP			)
+ 	),
+ 
+@@ -78,14 +77,12 @@ TRACE_EVENT(credit_entropy_bits,
+ 		__entry->pool_name	= pool_name;
+ 		__entry->bits		= bits;
+ 		__entry->entropy_count	= entropy_count;
+-		__entry->entropy_total	= entropy_total;
+ 		__entry->IP		= IP;
+ 	),
+ 
+-	TP_printk("%s pool: bits %d entropy_count %d entropy_total %d "
+-		  "caller %pS", __entry->pool_name, __entry->bits,
+-		  __entry->entropy_count, __entry->entropy_total,
+-		  (void *)__entry->IP)
++	TP_printk("%s pool: bits %d entropy_count %d caller %pS",
++		  __entry->pool_name, __entry->bits,
++		  __entry->entropy_count, (void *)__entry->IP)
+ );
+ 
+ TRACE_EVENT(push_to_pool,

commit e5d01196c0428a206f307e9ee5f6842964098ff0
+Author: Theodore Ts'o 
+Date:   Wed Apr 10 00:37:36 2019 -0400
+
+    ext4: ignore e_value_offs for xattrs with value-in-ea-inode
+    
+    In other places in fs/ext4/xattr.c, if e_value_inum is non-zero, the
+    code ignores the value in e_value_offs.  The e_value_offs *should* be
+    zero, but we shouldn't depend upon it, since it might not be true in a
+    corrupted/fuzzed file system.
+    
+    Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=202897
+    Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=202877
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index dc82e7757f67..491f9ee4040e 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -1696,7 +1696,7 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i,
+ 
+ 	/* No failures allowed past this point. */
+ 
+-	if (!s->not_found && here->e_value_size && here->e_value_offs) {
++	if (!s->not_found && here->e_value_size && !here->e_value_inum) {
+ 		/* Remove the old value. */
+ 		void *first_val = s->base + min_offs;
+ 		size_t offs = le16_to_cpu(here->e_value_offs);

commit 345c0dbf3a30872d9b204db96b5857cd00808cae
+Author: Theodore Ts'o 
+Date:   Tue Apr 9 23:37:08 2019 -0400
+
+    ext4: protect journal inode's blocks using block_validity
+    
+    Add the blocks which belong to the journal inode to block_validity's
+    system zone so attempts to deallocate or overwrite the journal due a
+    corrupted file system where the journal blocks are also claimed by
+    another inode.
+    
+    Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=202879
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/block_validity.c b/fs/ext4/block_validity.c
+index 913061c0de1b..9409b1e11a22 100644
+--- a/fs/ext4/block_validity.c
++++ b/fs/ext4/block_validity.c
+@@ -137,6 +137,48 @@ static void debug_print_tree(struct ext4_sb_info *sbi)
+ 	printk(KERN_CONT "\n");
+ }
+ 
++static int ext4_protect_reserved_inode(struct super_block *sb, u32 ino)
++{
++	struct inode *inode;
++	struct ext4_sb_info *sbi = EXT4_SB(sb);
++	struct ext4_map_blocks map;
++	u32 i = 0, err = 0, num, n;
++
++	if ((ino < EXT4_ROOT_INO) ||
++	    (ino > le32_to_cpu(sbi->s_es->s_inodes_count)))
++		return -EINVAL;
++	inode = ext4_iget(sb, ino, EXT4_IGET_SPECIAL);
++	if (IS_ERR(inode))
++		return PTR_ERR(inode);
++	num = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
++	while (i < num) {
++		map.m_lblk = i;
++		map.m_len = num - i;
++		n = ext4_map_blocks(NULL, inode, &map, 0);
++		if (n < 0) {
++			err = n;
++			break;
++		}
++		if (n == 0) {
++			i++;
++		} else {
++			if (!ext4_data_block_valid(sbi, map.m_pblk, n)) {
++				ext4_error(sb, "blocks %llu-%llu from inode %u "
++					   "overlap system zone", map.m_pblk,
++					   map.m_pblk + map.m_len - 1, ino);
++				err = -EFSCORRUPTED;
++				break;
++			}
++			err = add_system_zone(sbi, map.m_pblk, n);
++			if (err < 0)
++				break;
++			i += n;
++		}
++	}
++	iput(inode);
++	return err;
++}
++
+ int ext4_setup_system_zone(struct super_block *sb)
+ {
+ 	ext4_group_t ngroups = ext4_get_groups_count(sb);
+@@ -171,6 +213,12 @@ int ext4_setup_system_zone(struct super_block *sb)
+ 		if (ret)
+ 			return ret;
+ 	}
++	if (ext4_has_feature_journal(sb) && sbi->s_es->s_journal_inum) {
++		ret = ext4_protect_reserved_inode(sb,
++				le32_to_cpu(sbi->s_es->s_journal_inum));
++		if (ret)
++			return ret;
++	}
+ 
+ 	if (test_opt(sb, DEBUG))
+ 		debug_print_tree(sbi);
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 190f0478582a..609c8366d029 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -399,6 +399,10 @@ static int __check_block_validity(struct inode *inode, const char *func,
+ 				unsigned int line,
+ 				struct ext4_map_blocks *map)
+ {
++	if (ext4_has_feature_journal(inode->i_sb) &&
++	    (inode->i_ino ==
++	     le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum)))
++		return 0;
+ 	if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), map->m_pblk,
+ 				   map->m_len)) {
+ 		ext4_error_inode(inode, func, line, map->m_pblk,

commit 129ca2d2a83f44551e73a408fa5e75a7b5169abb
+Author: Theodore Ts'o 
+Date:   Thu Jan 24 16:42:24 2019 -0500
+
+    MAINTAINERS: add Eric Biggers as an fscrypt maintainer
+    
+    Also update the location of the git tree as we will be using a shared
+    git tree.
+    
+    Signed-off-by: Theodore Ts'o 
+    Signed-off-by: Eric Biggers 
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 51029a425dbe..419b326e711a 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -6193,9 +6193,10 @@ F:	include/linux/fscache*.h
+ FSCRYPT: FILE SYSTEM LEVEL ENCRYPTION SUPPORT
+ M:	Theodore Y. Ts'o 
+ M:	Jaegeuk Kim 
++M:	Eric Biggers 
+ L:	linux-fscrypt@vger.kernel.org
+ Q:	https://patchwork.kernel.org/project/linux-fscrypt/list/
+-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/tytso/fscrypt.git
++T:	git git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt.git
+ S:	Supported
+ F:	fs/crypto/
+ F:	include/linux/fscrypt*.h

commit a58ca992661a4bc6a1dfa60e9d6f606e97784149
+Author: Theodore Ts'o 
+Date:   Thu Feb 14 16:28:14 2019 -0500
+
+    jbd2: fold jbd2_superblock_csum_{verify,set} into their callers
+    
+    The functions jbd2_superblock_csum_verify() and
+    jbd2_superblock_csum_set() only get called from one location, so to
+    simplify things, fold them into their callers.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 67ac91b53050..382c030cc78b 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -142,22 +142,6 @@ static __be32 jbd2_superblock_csum(journal_t *j, journal_superblock_t *sb)
+ 	return cpu_to_be32(csum);
+ }
+ 
+-static int jbd2_superblock_csum_verify(journal_t *j, journal_superblock_t *sb)
+-{
+-	if (!jbd2_journal_has_csum_v2or3(j))
+-		return 1;
+-
+-	return sb->s_checksum == jbd2_superblock_csum(j, sb);
+-}
+-
+-static void jbd2_superblock_csum_set(journal_t *j, journal_superblock_t *sb)
+-{
+-	if (!jbd2_journal_has_csum_v2or3(j))
+-		return;
+-
+-	sb->s_checksum = jbd2_superblock_csum(j, sb);
+-}
+-
+ /*
+  * Helper function used to manage commit timeouts
+  */
+@@ -1384,7 +1368,8 @@ static int jbd2_write_superblock(journal_t *journal, int write_flags)
+ 		clear_buffer_write_io_error(bh);
+ 		set_buffer_uptodate(bh);
+ 	}
+-	jbd2_superblock_csum_set(journal, sb);
++	if (jbd2_journal_has_csum_v2or3(journal))
++		sb->s_checksum = jbd2_superblock_csum(journal, sb);
+ 	get_bh(bh);
+ 	bh->b_end_io = end_buffer_write_sync;
+ 	ret = submit_bh(REQ_OP_WRITE, write_flags, bh);
+@@ -1597,17 +1582,18 @@ static int journal_get_superblock(journal_t *journal)
+ 		}
+ 	}
+ 
+-	/* Check superblock checksum */
+-	if (!jbd2_superblock_csum_verify(journal, sb)) {
+-		printk(KERN_ERR "JBD2: journal checksum error\n");
+-		err = -EFSBADCRC;
+-		goto out;
+-	}
++	if (jbd2_journal_has_csum_v2or3(journal)) {
++		/* Check superblock checksum */
++		if (sb->s_checksum != jbd2_superblock_csum(journal, sb)) {
++			printk(KERN_ERR "JBD2: journal checksum error\n");
++			err = -EFSBADCRC;
++			goto out;
++		}
+ 
+-	/* Precompute checksum seed for all metadata */
+-	if (jbd2_journal_has_csum_v2or3(journal))
++		/* Precompute checksum seed for all metadata */
+ 		journal->j_csum_seed = jbd2_chksum(journal, ~0, sb->s_uuid,
+ 						   sizeof(sb->s_uuid));
++	}
+ 
+ 	set_buffer_verified(bh);
+ 

commit 538bcaa6261b77e71d37f5596c33127c1a3ec3f7
+Author: Theodore Ts'o 
+Date:   Thu Feb 14 16:27:14 2019 -0500
+
+    jbd2: fix race when writing superblock
+    
+    The jbd2 superblock is lockless now, so there is probably a race
+    condition between writing it so disk and modifing contents of it, which
+    may lead to checksum error. The following race is the one case that we
+    have captured.
+    
+    jbd2                                fsstress
+    jbd2_journal_commit_transaction
+     jbd2_journal_update_sb_log_tail
+      jbd2_write_superblock
+       jbd2_superblock_csum_set         jbd2_journal_revoke
+                                         jbd2_journal_set_features(revork)
+                                         modify superblock
+       submit_bh(checksum incorrect)
+    
+    Fix this by locking the buffer head before modifing it.  We always
+    write the jbd2 superblock after we modify it, so this just means
+    calling the lock_buffer() a little earlier.
+    
+    This checksum corruption problem can be reproduced by xfstests
+    generic/475.
+    
+    Reported-by: zhangyi (F) 
+    Suggested-by: Jan Kara 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 88d8f22d2cba..67ac91b53050 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -1356,6 +1356,10 @@ static int journal_reset(journal_t *journal)
+ 	return jbd2_journal_start_thread(journal);
+ }
+ 
++/*
++ * This function expects that the caller will have locked the journal
++ * buffer head, and will return with it unlocked
++ */
+ static int jbd2_write_superblock(journal_t *journal, int write_flags)
+ {
+ 	struct buffer_head *bh = journal->j_sb_buffer;
+@@ -1365,7 +1369,6 @@ static int jbd2_write_superblock(journal_t *journal, int write_flags)
+ 	trace_jbd2_write_superblock(journal, write_flags);
+ 	if (!(journal->j_flags & JBD2_BARRIER))
+ 		write_flags &= ~(REQ_FUA | REQ_PREFLUSH);
+-	lock_buffer(bh);
+ 	if (buffer_write_io_error(bh)) {
+ 		/*
+ 		 * Oh, dear.  A previous attempt to write the journal
+@@ -1424,6 +1427,7 @@ int jbd2_journal_update_sb_log_tail(journal_t *journal, tid_t tail_tid,
+ 	jbd_debug(1, "JBD2: updating superblock (start %lu, seq %u)\n",
+ 		  tail_block, tail_tid);
+ 
++	lock_buffer(journal->j_sb_buffer);
+ 	sb->s_sequence = cpu_to_be32(tail_tid);
+ 	sb->s_start    = cpu_to_be32(tail_block);
+ 
+@@ -1454,18 +1458,17 @@ static void jbd2_mark_journal_empty(journal_t *journal, int write_op)
+ 	journal_superblock_t *sb = journal->j_superblock;
+ 
+ 	BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex));
+-	read_lock(&journal->j_state_lock);
+-	/* Is it already empty? */
+-	if (sb->s_start == 0) {
+-		read_unlock(&journal->j_state_lock);
++	lock_buffer(journal->j_sb_buffer);
++	if (sb->s_start == 0) {		/* Is it already empty? */
++		unlock_buffer(journal->j_sb_buffer);
+ 		return;
+ 	}
++
+ 	jbd_debug(1, "JBD2: Marking journal as empty (seq %d)\n",
+ 		  journal->j_tail_sequence);
+ 
+ 	sb->s_sequence = cpu_to_be32(journal->j_tail_sequence);
+ 	sb->s_start    = cpu_to_be32(0);
+-	read_unlock(&journal->j_state_lock);
+ 
+ 	jbd2_write_superblock(journal, write_op);
+ 
+@@ -1488,9 +1491,8 @@ void jbd2_journal_update_sb_errno(journal_t *journal)
+ 	journal_superblock_t *sb = journal->j_superblock;
+ 	int errcode;
+ 
+-	read_lock(&journal->j_state_lock);
++	lock_buffer(journal->j_sb_buffer);
+ 	errcode = journal->j_errno;
+-	read_unlock(&journal->j_state_lock);
+ 	if (errcode == -ESHUTDOWN)
+ 		errcode = 0;
+ 	jbd_debug(1, "JBD2: updating superblock error (errno %d)\n", errcode);
+@@ -1894,28 +1896,27 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat,
+ 
+ 	sb = journal->j_superblock;
+ 
++	/* Load the checksum driver if necessary */
++	if ((journal->j_chksum_driver == NULL) &&
++	    INCOMPAT_FEATURE_ON(JBD2_FEATURE_INCOMPAT_CSUM_V3)) {
++		journal->j_chksum_driver = crypto_alloc_shash("crc32c", 0, 0);
++		if (IS_ERR(journal->j_chksum_driver)) {
++			printk(KERN_ERR "JBD2: Cannot load crc32c driver.\n");
++			journal->j_chksum_driver = NULL;
++			return 0;
++		}
++		/* Precompute checksum seed for all metadata */
++		journal->j_csum_seed = jbd2_chksum(journal, ~0, sb->s_uuid,
++						   sizeof(sb->s_uuid));
++	}
++
++	lock_buffer(journal->j_sb_buffer);
++
+ 	/* If enabling v3 checksums, update superblock */
+ 	if (INCOMPAT_FEATURE_ON(JBD2_FEATURE_INCOMPAT_CSUM_V3)) {
+ 		sb->s_checksum_type = JBD2_CRC32C_CHKSUM;
+ 		sb->s_feature_compat &=
+ 			~cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM);
+-
+-		/* Load the checksum driver */
+-		if (journal->j_chksum_driver == NULL) {
+-			journal->j_chksum_driver = crypto_alloc_shash("crc32c",
+-								      0, 0);
+-			if (IS_ERR(journal->j_chksum_driver)) {
+-				printk(KERN_ERR "JBD2: Cannot load crc32c "
+-				       "driver.\n");
+-				journal->j_chksum_driver = NULL;
+-				return 0;
+-			}
+-
+-			/* Precompute checksum seed for all metadata */
+-			journal->j_csum_seed = jbd2_chksum(journal, ~0,
+-							   sb->s_uuid,
+-							   sizeof(sb->s_uuid));
+-		}
+ 	}
+ 
+ 	/* If enabling v1 checksums, downgrade superblock */
+@@ -1927,6 +1928,7 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat,
+ 	sb->s_feature_compat    |= cpu_to_be32(compat);
+ 	sb->s_feature_ro_compat |= cpu_to_be32(ro);
+ 	sb->s_feature_incompat  |= cpu_to_be32(incompat);
++	unlock_buffer(journal->j_sb_buffer);
+ 
+ 	return 1;
+ #undef COMPAT_FEATURE_ON

commit 6e589291f4b1b700ca12baec5930592a0d51e63c
+Author: Theodore Ts'o 
+Date:   Mon Feb 11 01:07:10 2019 -0500
+
+    ext4: disallow files with EXT4_JOURNAL_DATA_FL from EXT4_IOC_SWAP_BOOT
+    
+    A malicious/clueless root user can use EXT4_IOC_SWAP_BOOT to force a
+    corner casew which can lead to the file system getting corrupted.
+    There's no usefulness to allowing this, so just prohibit this case.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index 2e76fb55d94a..eb8ca8d80885 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -132,6 +132,7 @@ static long swap_inode_boot_loader(struct super_block *sb,
+ 
+ 	if (inode->i_nlink != 1 || !S_ISREG(inode->i_mode) ||
+ 	    IS_SWAPFILE(inode) || IS_ENCRYPTED(inode) ||
++	    (EXT4_I(inode)->i_flags & EXT4_JOURNAL_DATA_FL) ||
+ 	    ext4_has_inline_data(inode)) {
+ 		err = -EINVAL;
+ 		goto journal_err_out;

commit 8fdd60f2ae3682caf2a7258626abc21eb4711892
+Author: Theodore Ts'o 
+Date:   Thu Jan 31 23:41:11 2019 -0500
+
+    Revert "ext4: use ext4_write_inode() when fsyncing w/o a journal"
+    
+    This reverts commit ad211f3e94b314a910d4af03178a0b52a7d1ee0a.
+    
+    As Jan Kara pointed out, this change was unsafe since it means we lose
+    the call to sync_mapping_buffers() in the nojournal case.  The
+    original point of the commit was avoid taking the inode mutex (since
+    it causes a lockdep warning in generic/113); but we need the mutex in
+    order to call sync_mapping_buffers().
+    
+    The real fix to this problem was discussed here:
+    
+    https://lore.kernel.org/lkml/20181025150540.259281-4-bvanassche@acm.org
+    
+    The proposed patch was to fix a syzbot complaint, but the problem can
+    also demonstrated via "kvm-xfstests -c nojournal generic/113".
+    Multiple solutions were discused in the e-mail thread, but none have
+    landed in the kernel as of this writing.  Anyway, commit
+    ad211f3e94b314 is absolutely the wrong way to suppress the lockdep, so
+    revert it.
+    
+    Fixes: ad211f3e94b314a910d4af03178a0b52a7d1ee0a ("ext4: use ext4_write_inode() when fsyncing w/o a journal")
+    Signed-off-by: Theodore Ts'o 
+    Reported: Jan Kara 
+
+diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
+index 712f00995390..5508baa11bb6 100644
+--- a/fs/ext4/fsync.c
++++ b/fs/ext4/fsync.c
+@@ -116,16 +116,8 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
+ 		goto out;
+ 	}
+ 
+-	ret = file_write_and_wait_range(file, start, end);
+-	if (ret)
+-		return ret;
+-
+ 	if (!journal) {
+-		struct writeback_control wbc = {
+-			.sync_mode = WB_SYNC_ALL
+-		};
+-
+-		ret = ext4_write_inode(inode, &wbc);
++		ret = __generic_file_fsync(file, start, end, datasync);
+ 		if (!ret)
+ 			ret = ext4_sync_parent(inode);
+ 		if (test_opt(inode->i_sb, BARRIER))
+@@ -133,6 +125,9 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
+ 		goto out;
+ 	}
+ 
++	ret = file_write_and_wait_range(file, start, end);
++	if (ret)
++		return ret;
+ 	/*
+ 	 * data=writeback,ordered:
+ 	 *  The caller's filemap_fdatawrite()/wait will sync the data.

commit 191ce17876c9367819c4b0a25b503c0f6d9054d8
+Author: Theodore Ts'o 
+Date:   Mon Dec 31 22:34:31 2018 -0500
+
+    ext4: fix special inode number checks in __ext4_iget()
+    
+    The check for special (reserved) inode number checks in __ext4_iget()
+    was broken by commit 8a363970d1dc: ("ext4: avoid declaring fs
+    inconsistent due to invalid file handles").  This was caused by a
+    botched reversal of the sense of the flag now known as
+    EXT4_IGET_SPECIAL (when it was previously named EXT4_IGET_NORMAL).
+    Fix the logic appropriately.
+    
+    Fixes: 8a363970d1dc ("ext4: avoid declaring fs inconsistent...")
+    Signed-off-by: Theodore Ts'o 
+    Reported-by: Dan Carpenter 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 165ff331d998..34d7e0703cc6 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4834,7 +4834,7 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
+ 	gid_t i_gid;
+ 	projid_t i_projid;
+ 
+-	if (((flags & EXT4_IGET_NORMAL) &&
++	if ((!(flags & EXT4_IGET_SPECIAL) &&
+ 	     (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO)) ||
+ 	    (ino < EXT4_ROOT_INO) ||
+ 	    (ino > le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count))) {

commit 95cb67138746451cc84cf8e516e14989746e93b0
+Author: Theodore Ts'o 
+Date:   Mon Dec 31 00:11:07 2018 -0500
+
+    ext4: track writeback errors using the generic tracking infrastructure
+    
+    We already using mapping_set_error() in fs/ext4/page_io.c, so all we
+    need to do is to use file_check_and_advance_wb_err() when handling
+    fsync() requests in ext4_sync_file().
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
+index 87a7ff00ef62..712f00995390 100644
+--- a/fs/ext4/fsync.c
++++ b/fs/ext4/fsync.c
+@@ -164,6 +164,9 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
+ 			ret = err;
+ 	}
+ out:
++	err = file_check_and_advance_wb_err(file);
++	if (ret == 0)
++		ret = err;
+ 	trace_ext4_sync_file_exit(inode, ret);
+ 	return ret;
+ }

commit ad211f3e94b314a910d4af03178a0b52a7d1ee0a
+Author: Theodore Ts'o 
+Date:   Mon Dec 31 00:10:48 2018 -0500
+
+    ext4: use ext4_write_inode() when fsyncing w/o a journal
+    
+    In no-journal mode, we previously used __generic_file_fsync() in
+    no-journal mode.  This triggers a lockdep warning, and in addition,
+    it's not safe to depend on the inode writeback mechanism in the case
+    ext4.  We can solve both problems by calling ext4_write_inode()
+    directly.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
+index 26a7fe5c4fd3..87a7ff00ef62 100644
+--- a/fs/ext4/fsync.c
++++ b/fs/ext4/fsync.c
+@@ -116,8 +116,16 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
+ 		goto out;
+ 	}
+ 
++	ret = file_write_and_wait_range(file, start, end);
++	if (ret)
++		return ret;
++
+ 	if (!journal) {
+-		ret = __generic_file_fsync(file, start, end, datasync);
++		struct writeback_control wbc = {
++			.sync_mode = WB_SYNC_ALL
++		};
++
++		ret = ext4_write_inode(inode, &wbc);
+ 		if (!ret)
+ 			ret = ext4_sync_parent(inode);
+ 		if (test_opt(inode->i_sb, BARRIER))
+@@ -125,9 +133,6 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
+ 		goto out;
+ 	}
+ 
+-	ret = file_write_and_wait_range(file, start, end);
+-	if (ret)
+-		return ret;
+ 	/*
+ 	 * data=writeback,ordered:
+ 	 *  The caller's filemap_fdatawrite()/wait will sync the data.

commit e86807862e6880809f191c4cea7f88a489f0ed34
+Author: Theodore Ts'o 
+Date:   Sun Dec 30 23:20:39 2018 -0500
+
+    ext4: avoid kernel warning when writing the superblock to a dead device
+    
+    The xfstests generic/475 test switches the underlying device with
+    dm-error while running a stress test.  This results in a large number
+    of file system errors, and since we can't lock the buffer head when
+    marking the superblock dirty in the ext4_grp_locked_error() case, it's
+    possible the superblock to be !buffer_uptodate() without
+    buffer_write_io_error() being true.
+    
+    We need to set buffer_uptodate() before we call mark_buffer_dirty() or
+    this will trigger a WARN_ON.  It's safe to do this since the
+    superblock must have been properly read into memory or the mount would
+    have been successful.  So if buffer_uptodate() is not set, we can
+    safely assume that this happened due to a failed attempt to write the
+    superblock.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index d6c142d73d99..fb12d3c17c1b 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4902,7 +4902,7 @@ static int ext4_commit_super(struct super_block *sb, int sync)
+ 	ext4_superblock_csum_set(sb);
+ 	if (sync)
+ 		lock_buffer(sbh);
+-	if (buffer_write_io_error(sbh)) {
++	if (buffer_write_io_error(sbh) || !buffer_uptodate(sbh)) {
+ 		/*
+ 		 * Oh, dear.  A previous attempt to write the
+ 		 * superblock failed.  This could happen because the

commit 2b08b1f12cd664dc7d5c84ead9ff25ae97ad5491
+Author: Theodore Ts'o 
+Date:   Tue Dec 25 00:56:33 2018 -0500
+
+    ext4: fix a potential fiemap/page fault deadlock w/ inline_data
+    
+    The ext4_inline_data_fiemap() function calls fiemap_fill_next_extent()
+    while still holding the xattr semaphore.  This is not necessary and it
+    triggers a circular lockdep warning.  This is because
+    fiemap_fill_next_extent() could trigger a page fault when it writes
+    into page which triggers a page fault.  If that page is mmaped from
+    the inline file in question, this could very well result in a
+    deadlock.
+    
+    This problem can be reproduced using generic/519 with a file system
+    configuration which has the inline_data feature enabled.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index 27373d88b5f0..56f6e1782d5f 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -1890,12 +1890,12 @@ int ext4_inline_data_fiemap(struct inode *inode,
+ 	physical += (char *)ext4_raw_inode(&iloc) - iloc.bh->b_data;
+ 	physical += offsetof(struct ext4_inode, i_block);
+ 
+-	if (physical)
+-		error = fiemap_fill_next_extent(fieinfo, start, physical,
+-						inline_len, flags);
+ 	brelse(iloc.bh);
+ out:
+ 	up_read(&EXT4_I(inode)->xattr_sem);
++	if (physical)
++		error = fiemap_fill_next_extent(fieinfo, start, physical,
++						inline_len, flags);
+ 	return (error < 0 ? error : 0);
+ }
+ 

commit 812c0cab2c0dfad977605dbadf9148490ca5d93f
+Author: Theodore Ts'o 
+Date:   Mon Dec 24 20:27:08 2018 -0500
+
+    ext4: make sure enough credits are reserved for dioread_nolock writes
+    
+    There are enough credits reserved for most dioread_nolock writes;
+    however, if the extent tree is sufficiently deep, and/or quota is
+    enabled, the code was not allowing for all eventualities when
+    reserving journal credits for the unwritten extent conversion.
+    
+    This problem can be seen using xfstests ext4/034:
+    
+       WARNING: CPU: 1 PID: 257 at fs/ext4/ext4_jbd2.c:271 __ext4_handle_dirty_metadata+0x10c/0x180
+       Workqueue: ext4-rsv-conversion ext4_end_io_rsv_work
+       RIP: 0010:__ext4_handle_dirty_metadata+0x10c/0x180
+            ...
+       EXT4-fs: ext4_free_blocks:4938: aborting transaction: error 28 in __ext4_handle_dirty_metadata
+       EXT4: jbd2_journal_dirty_metadata failed: handle type 11 started at line 4921, credits 4/0, errcode -28
+       EXT4-fs error (device dm-1) in ext4_free_blocks:4950: error 28
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 9affabd07682..165ff331d998 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2778,7 +2778,8 @@ static int ext4_writepages(struct address_space *mapping,
+ 		 * We may need to convert up to one extent per block in
+ 		 * the page and we may dirty the inode.
+ 		 */
+-		rsv_blocks = 1 + (PAGE_SIZE >> inode->i_blkbits);
++		rsv_blocks = 1 + ext4_chunk_trans_blocks(inode,
++						PAGE_SIZE >> inode->i_blkbits);
+ 	}
+ 
+ 	/*

commit 18f2c4fcebf2582f96cbd5f2238f4f354a0e4847
+Author: Theodore Ts'o 
+Date:   Wed Dec 19 14:36:58 2018 -0500
+
+    ext4: check for shutdown and r/o file system in ext4_write_inode()
+    
+    If the file system has been shut down or is read-only, then
+    ext4_write_inode() needs to bail out early.
+    
+    Also use jbd2_complete_transaction() instead of ext4_force_commit() so
+    we only force a commit if it is needed.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 664b434ba836..9affabd07682 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -5400,9 +5400,13 @@ int ext4_write_inode(struct inode *inode, struct writeback_control *wbc)
+ {
+ 	int err;
+ 
+-	if (WARN_ON_ONCE(current->flags & PF_MEMALLOC))
++	if (WARN_ON_ONCE(current->flags & PF_MEMALLOC) ||
++	    sb_rdonly(inode->i_sb))
+ 		return 0;
+ 
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
++		return -EIO;
++
+ 	if (EXT4_SB(inode->i_sb)->s_journal) {
+ 		if (ext4_journal_current_handle()) {
+ 			jbd_debug(1, "called recursively, non-PF_MEMALLOC!\n");
+@@ -5418,7 +5422,8 @@ int ext4_write_inode(struct inode *inode, struct writeback_control *wbc)
+ 		if (wbc->sync_mode != WB_SYNC_ALL || wbc->for_sync)
+ 			return 0;
+ 
+-		err = ext4_force_commit(inode->i_sb);
++		err = jbd2_complete_transaction(EXT4_SB(inode->i_sb)->s_journal,
++						EXT4_I(inode)->i_sync_tid);
+ 	} else {
+ 		struct ext4_iloc iloc;
+ 

commit fde872682e175743e0c3ef939c89e3c6008a1529
+Author: Theodore Ts'o 
+Date:   Wed Dec 19 14:07:58 2018 -0500
+
+    ext4: force inode writes when nfsd calls commit_metadata()
+    
+    Some time back, nfsd switched from calling vfs_fsync() to using a new
+    commit_metadata() hook in export_operations().  If the file system did
+    not provide a commit_metadata() hook, it fell back to using
+    sync_inode_metadata().  Unfortunately doesn't work on all file
+    systems.  In particular, it doesn't work on ext4 due to how the inode
+    gets journalled --- the VFS writeback code will not always call
+    ext4_write_inode().
+    
+    So we need to provide our own ext4_nfs_commit_metdata() method which
+    calls ext4_write_inode() directly.
+    
+    Google-Bug-Id: 121195940
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index fc9071081600..d6c142d73d99 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1202,6 +1202,16 @@ static struct dentry *ext4_fh_to_parent(struct super_block *sb, struct fid *fid,
+ 				    ext4_nfs_get_inode);
+ }
+ 
++static int ext4_nfs_commit_metadata(struct inode *inode)
++{
++	struct writeback_control wbc = {
++		.sync_mode = WB_SYNC_ALL
++	};
++
++	trace_ext4_nfs_commit_metadata(inode);
++	return ext4_write_inode(inode, &wbc);
++}
++
+ /*
+  * Try to release metadata pages (indirect blocks, directories) which are
+  * mapped via the block device.  Since these pages could have journal heads
+@@ -1406,6 +1416,7 @@ static const struct export_operations ext4_export_ops = {
+ 	.fh_to_dentry = ext4_fh_to_dentry,
+ 	.fh_to_parent = ext4_fh_to_parent,
+ 	.get_parent = ext4_get_parent,
++	.commit_metadata = ext4_nfs_commit_metadata,
+ };
+ 
+ enum {
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index 698e0d8a5ca4..d68e9e536814 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -226,6 +226,26 @@ TRACE_EVENT(ext4_drop_inode,
+ 		  (unsigned long) __entry->ino, __entry->drop)
+ );
+ 
++TRACE_EVENT(ext4_nfs_commit_metadata,
++	TP_PROTO(struct inode *inode),
++
++	TP_ARGS(inode),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++	),
++
++	TP_fast_assign(
++		__entry->dev	= inode->i_sb->s_dev;
++		__entry->ino	= inode->i_ino;
++	),
++
++	TP_printk("dev %d,%d ino %lu",
++		  MAJOR(__entry->dev), MINOR(__entry->dev),
++		  (unsigned long) __entry->ino)
++);
++
+ TRACE_EVENT(ext4_mark_inode_dirty,
+ 	TP_PROTO(struct inode *inode, unsigned long IP),
+ 

commit 8a363970d1dc38c4ec4ad575c862f776f468d057
+Author: Theodore Ts'o 
+Date:   Wed Dec 19 12:29:13 2018 -0500
+
+    ext4: avoid declaring fs inconsistent due to invalid file handles
+    
+    If we receive a file handle, either from NFS or open_by_handle_at(2),
+    and it points at an inode which has not been initialized, and the file
+    system has metadata checksums enabled, we shouldn't try to get the
+    inode, discover the checksum is invalid, and then declare the file
+    system as being inconsistent.
+    
+    This can be reproduced by creating a test file system via "mke2fs -t
+    ext4 -O metadata_csum /tmp/foo.img 8M", mounting it, cd'ing into that
+    directory, and then running the following program.
+    
+    #define _GNU_SOURCE
+    #include 
+    
+    struct handle {
+            struct file_handle fh;
+            unsigned char fid[MAX_HANDLE_SZ];
+    };
+    
+    int main(int argc, char **argv)
+    {
+            struct handle h = {{8, 1 }, { 12, }};
+    
+            open_by_handle_at(AT_FDCWD, &h.fh, O_RDONLY);
+            return 0;
+    }
+    
+    Google-Bug-Id: 120690101
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index b4621277e259..185a05d3257e 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2454,8 +2454,19 @@ int do_journal_get_write_access(handle_t *handle,
+ #define FALL_BACK_TO_NONDELALLOC 1
+ #define CONVERT_INLINE_DATA	 2
+ 
+-extern struct inode *ext4_iget(struct super_block *, unsigned long);
+-extern struct inode *ext4_iget_normal(struct super_block *, unsigned long);
++typedef enum {
++	EXT4_IGET_NORMAL =	0,
++	EXT4_IGET_SPECIAL =	0x0001, /* OK to iget a system inode */
++	EXT4_IGET_HANDLE = 	0x0002	/* Inode # is from a handle */
++} ext4_iget_flags;
++
++extern struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
++				 ext4_iget_flags flags, const char *function,
++				 unsigned int line);
++
++#define ext4_iget(sb, ino, flags) \
++	__ext4_iget((sb), (ino), (flags), __func__, __LINE__)
++
+ extern int  ext4_write_inode(struct inode *, struct writeback_control *);
+ extern int  ext4_setattr(struct dentry *, struct iattr *);
+ extern int  ext4_getattr(const struct path *, struct kstat *, u32, unsigned int);
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 014f6a698cb7..7ff14a1adba3 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -1225,7 +1225,7 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
+ 	if (!ext4_test_bit(bit, bitmap_bh->b_data))
+ 		goto bad_orphan;
+ 
+-	inode = ext4_iget(sb, ino);
++	inode = ext4_iget(sb, ino, EXT4_IGET_NORMAL);
+ 	if (IS_ERR(inode)) {
+ 		err = PTR_ERR(inode);
+ 		ext4_error(sb, "couldn't read orphan inode %lu (err %d)",
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 22a9d8159720..664b434ba836 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4817,7 +4817,9 @@ static inline u64 ext4_inode_peek_iversion(const struct inode *inode)
+ 		return inode_peek_iversion(inode);
+ }
+ 
+-struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
++struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
++			  ext4_iget_flags flags, const char *function,
++			  unsigned int line)
+ {
+ 	struct ext4_iloc iloc;
+ 	struct ext4_inode *raw_inode;
+@@ -4831,6 +4833,18 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 	gid_t i_gid;
+ 	projid_t i_projid;
+ 
++	if (((flags & EXT4_IGET_NORMAL) &&
++	     (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO)) ||
++	    (ino < EXT4_ROOT_INO) ||
++	    (ino > le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count))) {
++		if (flags & EXT4_IGET_HANDLE)
++			return ERR_PTR(-ESTALE);
++		__ext4_error(sb, function, line,
++			     "inode #%lu: comm %s: iget: illegal inode #",
++			     ino, current->comm);
++		return ERR_PTR(-EFSCORRUPTED);
++	}
++
+ 	inode = iget_locked(sb, ino);
+ 	if (!inode)
+ 		return ERR_PTR(-ENOMEM);
+@@ -4846,18 +4860,26 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 	raw_inode = ext4_raw_inode(&iloc);
+ 
+ 	if ((ino == EXT4_ROOT_INO) && (raw_inode->i_links_count == 0)) {
+-		EXT4_ERROR_INODE(inode, "root inode unallocated");
++		ext4_error_inode(inode, function, line, 0,
++				 "iget: root inode unallocated");
+ 		ret = -EFSCORRUPTED;
+ 		goto bad_inode;
+ 	}
+ 
++	if ((flags & EXT4_IGET_HANDLE) &&
++	    (raw_inode->i_links_count == 0) && (raw_inode->i_mode == 0)) {
++		ret = -ESTALE;
++		goto bad_inode;
++	}
++
+ 	if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) {
+ 		ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize);
+ 		if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize >
+ 			EXT4_INODE_SIZE(inode->i_sb) ||
+ 		    (ei->i_extra_isize & 3)) {
+-			EXT4_ERROR_INODE(inode,
+-					 "bad extra_isize %u (inode size %u)",
++			ext4_error_inode(inode, function, line, 0,
++					 "iget: bad extra_isize %u "
++					 "(inode size %u)",
+ 					 ei->i_extra_isize,
+ 					 EXT4_INODE_SIZE(inode->i_sb));
+ 			ret = -EFSCORRUPTED;
+@@ -4879,7 +4901,8 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 	}
+ 
+ 	if (!ext4_inode_csum_verify(inode, raw_inode, ei)) {
+-		EXT4_ERROR_INODE(inode, "checksum invalid");
++		ext4_error_inode(inode, function, line, 0,
++				 "iget: checksum invalid");
+ 		ret = -EFSBADCRC;
+ 		goto bad_inode;
+ 	}
+@@ -4936,7 +4959,8 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 			((__u64)le16_to_cpu(raw_inode->i_file_acl_high)) << 32;
+ 	inode->i_size = ext4_isize(sb, raw_inode);
+ 	if ((size = i_size_read(inode)) < 0) {
+-		EXT4_ERROR_INODE(inode, "bad i_size value: %lld", size);
++		ext4_error_inode(inode, function, line, 0,
++				 "iget: bad i_size value: %lld", size);
+ 		ret = -EFSCORRUPTED;
+ 		goto bad_inode;
+ 	}
+@@ -5012,7 +5036,8 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 	ret = 0;
+ 	if (ei->i_file_acl &&
+ 	    !ext4_data_block_valid(EXT4_SB(sb), ei->i_file_acl, 1)) {
+-		EXT4_ERROR_INODE(inode, "bad extended attribute block %llu",
++		ext4_error_inode(inode, function, line, 0,
++				 "iget: bad extended attribute block %llu",
+ 				 ei->i_file_acl);
+ 		ret = -EFSCORRUPTED;
+ 		goto bad_inode;
+@@ -5040,8 +5065,9 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 	} else if (S_ISLNK(inode->i_mode)) {
+ 		/* VFS does not allow setting these so must be corruption */
+ 		if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) {
+-			EXT4_ERROR_INODE(inode,
+-			  "immutable or append flags not allowed on symlinks");
++			ext4_error_inode(inode, function, line, 0,
++					 "iget: immutable or append flags "
++					 "not allowed on symlinks");
+ 			ret = -EFSCORRUPTED;
+ 			goto bad_inode;
+ 		}
+@@ -5071,7 +5097,8 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 		make_bad_inode(inode);
+ 	} else {
+ 		ret = -EFSCORRUPTED;
+-		EXT4_ERROR_INODE(inode, "bogus i_mode (%o)", inode->i_mode);
++		ext4_error_inode(inode, function, line, 0,
++				 "iget: bogus i_mode (%o)", inode->i_mode);
+ 		goto bad_inode;
+ 	}
+ 	brelse(iloc.bh);
+@@ -5085,13 +5112,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 	return ERR_PTR(ret);
+ }
+ 
+-struct inode *ext4_iget_normal(struct super_block *sb, unsigned long ino)
+-{
+-	if (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO)
+-		return ERR_PTR(-EFSCORRUPTED);
+-	return ext4_iget(sb, ino);
+-}
+-
+ static int ext4_inode_blocks_set(handle_t *handle,
+ 				struct ext4_inode *raw_inode,
+ 				struct ext4_inode_info *ei)
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index 0edee31913d1..d37dafa1d133 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -125,7 +125,7 @@ static long swap_inode_boot_loader(struct super_block *sb,
+ 	    !inode_owner_or_capable(inode) || !capable(CAP_SYS_ADMIN))
+ 		return -EPERM;
+ 
+-	inode_bl = ext4_iget(sb, EXT4_BOOT_LOADER_INO);
++	inode_bl = ext4_iget(sb, EXT4_BOOT_LOADER_INO, EXT4_IGET_SPECIAL);
+ 	if (IS_ERR(inode_bl))
+ 		return PTR_ERR(inode_bl);
+ 	ei_bl = EXT4_I(inode_bl);
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 437f71fe83ae..2b928eb07fa2 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1571,7 +1571,7 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
+ 					 dentry);
+ 			return ERR_PTR(-EFSCORRUPTED);
+ 		}
+-		inode = ext4_iget_normal(dir->i_sb, ino);
++		inode = ext4_iget(dir->i_sb, ino, EXT4_IGET_NORMAL);
+ 		if (inode == ERR_PTR(-ESTALE)) {
+ 			EXT4_ERROR_INODE(dir,
+ 					 "deleted inode referenced: %u",
+@@ -1613,7 +1613,7 @@ struct dentry *ext4_get_parent(struct dentry *child)
+ 		return ERR_PTR(-EFSCORRUPTED);
+ 	}
+ 
+-	return d_obtain_alias(ext4_iget_normal(child->d_sb, ino));
++	return d_obtain_alias(ext4_iget(child->d_sb, ino, EXT4_IGET_NORMAL));
+ }
+ 
+ /*
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index bc8ee0c498cc..48421de803b7 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -1637,7 +1637,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
+ 				     "No reserved GDT blocks, can't resize");
+ 			return -EPERM;
+ 		}
+-		inode = ext4_iget(sb, EXT4_RESIZE_INO);
++		inode = ext4_iget(sb, EXT4_RESIZE_INO, EXT4_IGET_SPECIAL);
+ 		if (IS_ERR(inode)) {
+ 			ext4_warning(sb, "Error opening resize inode");
+ 			return PTR_ERR(inode);
+@@ -1965,7 +1965,8 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
+ 		}
+ 
+ 		if (!resize_inode)
+-			resize_inode = ext4_iget(sb, EXT4_RESIZE_INO);
++			resize_inode = ext4_iget(sb, EXT4_RESIZE_INO,
++						 EXT4_IGET_SPECIAL);
+ 		if (IS_ERR(resize_inode)) {
+ 			ext4_warning(sb, "Error opening resize inode");
+ 			return PTR_ERR(resize_inode);
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index e862b82066ab..fc9071081600 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1173,20 +1173,11 @@ static struct inode *ext4_nfs_get_inode(struct super_block *sb,
+ {
+ 	struct inode *inode;
+ 
+-	if (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO)
+-		return ERR_PTR(-ESTALE);
+-	if (ino > le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count))
+-		return ERR_PTR(-ESTALE);
+-
+-	/* iget isn't really right if the inode is currently unallocated!!
+-	 *
+-	 * ext4_read_inode will return a bad_inode if the inode had been
+-	 * deleted, so we should be safe.
+-	 *
++	/*
+ 	 * Currently we don't know the generation for parent directory, so
+ 	 * a generation of 0 means "accept any"
+ 	 */
+-	inode = ext4_iget_normal(sb, ino);
++	inode = ext4_iget(sb, ino, EXT4_IGET_HANDLE);
+ 	if (IS_ERR(inode))
+ 		return ERR_CAST(inode);
+ 	if (generation && inode->i_generation != generation) {
+@@ -4350,7 +4341,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	 * so we can safely mount the rest of the filesystem now.
+ 	 */
+ 
+-	root = ext4_iget(sb, EXT4_ROOT_INO);
++	root = ext4_iget(sb, EXT4_ROOT_INO, EXT4_IGET_SPECIAL);
+ 	if (IS_ERR(root)) {
+ 		ext4_msg(sb, KERN_ERR, "get root inode failed");
+ 		ret = PTR_ERR(root);
+@@ -4618,7 +4609,7 @@ static struct inode *ext4_get_journal_inode(struct super_block *sb,
+ 	 * happen if we iget() an unused inode, as the subsequent iput()
+ 	 * will try to delete it.
+ 	 */
+-	journal_inode = ext4_iget(sb, journal_inum);
++	journal_inode = ext4_iget(sb, journal_inum, EXT4_IGET_SPECIAL);
+ 	if (IS_ERR(journal_inode)) {
+ 		ext4_msg(sb, KERN_ERR, "no journal found");
+ 		return NULL;
+@@ -5700,7 +5691,7 @@ static int ext4_quota_enable(struct super_block *sb, int type, int format_id,
+ 	if (!qf_inums[type])
+ 		return -EPERM;
+ 
+-	qf_inode = ext4_iget(sb, qf_inums[type]);
++	qf_inode = ext4_iget(sb, qf_inums[type], EXT4_IGET_SPECIAL);
+ 	if (IS_ERR(qf_inode)) {
+ 		ext4_error(sb, "Bad quota inode # %lu", qf_inums[type]);
+ 		return PTR_ERR(qf_inode);
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 91037890a90b..86ed9c686249 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -384,7 +384,7 @@ static int ext4_xattr_inode_iget(struct inode *parent, unsigned long ea_ino,
+ 	struct inode *inode;
+ 	int err;
+ 
+-	inode = ext4_iget(parent->i_sb, ea_ino);
++	inode = ext4_iget(parent->i_sb, ea_ino, EXT4_IGET_NORMAL);
+ 	if (IS_ERR(inode)) {
+ 		err = PTR_ERR(inode);
+ 		ext4_error(parent->i_sb,
+@@ -1482,7 +1482,8 @@ ext4_xattr_inode_cache_find(struct inode *inode, const void *value,
+ 	}
+ 
+ 	while (ce) {
+-		ea_inode = ext4_iget(inode->i_sb, ce->e_value);
++		ea_inode = ext4_iget(inode->i_sb, ce->e_value,
++				     EXT4_IGET_NORMAL);
+ 		if (!IS_ERR(ea_inode) &&
+ 		    !is_bad_inode(ea_inode) &&
+ 		    (EXT4_I(ea_inode)->i_flags & EXT4_EA_INODE_FL) &&

commit a805622a757b6d7f65def4141d29317d8e37b8a1
+Author: Theodore Ts'o 
+Date:   Wed Dec 19 12:28:13 2018 -0500
+
+    ext4: include terminating u32 in size of xattr entries when expanding inodes
+    
+    In ext4_expand_extra_isize_ea(), we calculate the total size of the
+    xattr header, plus the xattr entries so we know how much of the
+    beginning part of the xattrs to move when expanding the inode extra
+    size.  We need to include the terminating u32 at the end of the xattr
+    entries, or else if there is uninitialized, non-zero bytes after the
+    xattr entries and before the xattr values, the list of xattr entries
+    won't be properly terminated.
+    
+    Reported-by: Steve Graham 
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 510c9bb7ce71..91037890a90b 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -2721,7 +2721,7 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
+ 	base = IFIRST(header);
+ 	end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
+ 	min_offs = end - base;
+-	total_ino = sizeof(struct ext4_xattr_ibody_header);
++	total_ino = sizeof(struct ext4_xattr_ibody_header) + sizeof(u32);
+ 
+ 	error = xattr_check_inode(inode, header, end);
+ 	if (error)

commit fb265c9cb49e2074ddcdd4de99728aefdd3b3592
+Author: Theodore Ts'o 
+Date:   Sun Nov 25 17:20:31 2018 -0500
+
+    ext4: add ext4_sb_bread() to disambiguate ENOMEM cases
+    
+    Today, when sb_bread() returns NULL, this can either be because of an
+    I/O error or because the system failed to allocate the buffer.  Since
+    it's an old interface, changing would require changing many call
+    sites.
+    
+    So instead we create our own ext4_sb_bread(), which also allows us to
+    set the REQ_META flag.
+    
+    Also fixed a problem in the xattr code where a NULL return in a
+    function could also mean that the xattr was not found, which could
+    lead to the wrong error getting returned to userspace.
+    
+    Fixes: ac27a0ec112a ("ext4: initial copy of files from ext3")
+    Cc: stable@kernel.org # 2.6.19
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 3f89d0ab08fc..b4621277e259 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2538,6 +2538,8 @@ extern int ext4_group_extend(struct super_block *sb,
+ extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count);
+ 
+ /* super.c */
++extern struct buffer_head *ext4_sb_bread(struct super_block *sb,
++					 sector_t block, int op_flags);
+ extern int ext4_seq_options_show(struct seq_file *seq, void *offset);
+ extern int ext4_calculate_overhead(struct super_block *sb);
+ extern void ext4_superblock_csum_set(struct super_block *sb);
+diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
+index 61a9d1927817..a98bfca9c463 100644
+--- a/fs/ext4/migrate.c
++++ b/fs/ext4/migrate.c
+@@ -116,9 +116,9 @@ static int update_ind_extent_range(handle_t *handle, struct inode *inode,
+ 	int i, retval = 0;
+ 	unsigned long max_entries = inode->i_sb->s_blocksize >> 2;
+ 
+-	bh = sb_bread(inode->i_sb, pblock);
+-	if (!bh)
+-		return -EIO;
++	bh = ext4_sb_bread(inode->i_sb, pblock, 0);
++	if (IS_ERR(bh))
++		return PTR_ERR(bh);
+ 
+ 	i_data = (__le32 *)bh->b_data;
+ 	for (i = 0; i < max_entries; i++) {
+@@ -145,9 +145,9 @@ static int update_dind_extent_range(handle_t *handle, struct inode *inode,
+ 	int i, retval = 0;
+ 	unsigned long max_entries = inode->i_sb->s_blocksize >> 2;
+ 
+-	bh = sb_bread(inode->i_sb, pblock);
+-	if (!bh)
+-		return -EIO;
++	bh = ext4_sb_bread(inode->i_sb, pblock, 0);
++	if (IS_ERR(bh))
++		return PTR_ERR(bh);
+ 
+ 	i_data = (__le32 *)bh->b_data;
+ 	for (i = 0; i < max_entries; i++) {
+@@ -175,9 +175,9 @@ static int update_tind_extent_range(handle_t *handle, struct inode *inode,
+ 	int i, retval = 0;
+ 	unsigned long max_entries = inode->i_sb->s_blocksize >> 2;
+ 
+-	bh = sb_bread(inode->i_sb, pblock);
+-	if (!bh)
+-		return -EIO;
++	bh = ext4_sb_bread(inode->i_sb, pblock, 0);
++	if (IS_ERR(bh))
++		return PTR_ERR(bh);
+ 
+ 	i_data = (__le32 *)bh->b_data;
+ 	for (i = 0; i < max_entries; i++) {
+@@ -224,9 +224,9 @@ static int free_dind_blocks(handle_t *handle,
+ 	struct buffer_head *bh;
+ 	unsigned long max_entries = inode->i_sb->s_blocksize >> 2;
+ 
+-	bh = sb_bread(inode->i_sb, le32_to_cpu(i_data));
+-	if (!bh)
+-		return -EIO;
++	bh = ext4_sb_bread(inode->i_sb, le32_to_cpu(i_data), 0);
++	if (IS_ERR(bh))
++		return PTR_ERR(bh);
+ 
+ 	tmp_idata = (__le32 *)bh->b_data;
+ 	for (i = 0; i < max_entries; i++) {
+@@ -254,9 +254,9 @@ static int free_tind_blocks(handle_t *handle,
+ 	struct buffer_head *bh;
+ 	unsigned long max_entries = inode->i_sb->s_blocksize >> 2;
+ 
+-	bh = sb_bread(inode->i_sb, le32_to_cpu(i_data));
+-	if (!bh)
+-		return -EIO;
++	bh = ext4_sb_bread(inode->i_sb, le32_to_cpu(i_data), 0);
++	if (IS_ERR(bh))
++		return PTR_ERR(bh);
+ 
+ 	tmp_idata = (__le32 *)bh->b_data;
+ 	for (i = 0; i < max_entries; i++) {
+@@ -382,9 +382,9 @@ static int free_ext_idx(handle_t *handle, struct inode *inode,
+ 	struct ext4_extent_header *eh;
+ 
+ 	block = ext4_idx_pblock(ix);
+-	bh = sb_bread(inode->i_sb, block);
+-	if (!bh)
+-		return -EIO;
++	bh = ext4_sb_bread(inode->i_sb, block, 0);
++	if (IS_ERR(bh))
++		return PTR_ERR(bh);
+ 
+ 	eh = (struct ext4_extent_header *)bh->b_data;
+ 	if (eh->eh_depth != 0) {
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index a5efee34415f..87350b642681 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -127,10 +127,12 @@ static int verify_group_input(struct super_block *sb,
+ 	else if (free_blocks_count < 0)
+ 		ext4_warning(sb, "Bad blocks count %u",
+ 			     input->blocks_count);
+-	else if (!(bh = sb_bread(sb, end - 1)))
++	else if (IS_ERR(bh = ext4_sb_bread(sb, end - 1, 0))) {
++		err = PTR_ERR(bh);
++		bh = NULL;
+ 		ext4_warning(sb, "Cannot read last block (%llu)",
+ 			     end - 1);
+-	else if (outside(input->block_bitmap, start, end))
++	} else if (outside(input->block_bitmap, start, end))
+ 		ext4_warning(sb, "Block bitmap not in group (block %llu)",
+ 			     (unsigned long long)input->block_bitmap);
+ 	else if (outside(input->inode_bitmap, start, end))
+@@ -781,11 +783,11 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ 	struct ext4_super_block *es = EXT4_SB(sb)->s_es;
+ 	unsigned long gdb_num = group / EXT4_DESC_PER_BLOCK(sb);
+ 	ext4_fsblk_t gdblock = EXT4_SB(sb)->s_sbh->b_blocknr + 1 + gdb_num;
+-	struct buffer_head **o_group_desc, **n_group_desc;
+-	struct buffer_head *dind;
+-	struct buffer_head *gdb_bh;
++	struct buffer_head **o_group_desc, **n_group_desc = NULL;
++	struct buffer_head *dind = NULL;
++	struct buffer_head *gdb_bh = NULL;
+ 	int gdbackups;
+-	struct ext4_iloc iloc;
++	struct ext4_iloc iloc = { .bh = NULL };
+ 	__le32 *data;
+ 	int err;
+ 
+@@ -794,21 +796,22 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ 		       "EXT4-fs: ext4_add_new_gdb: adding group block %lu\n",
+ 		       gdb_num);
+ 
+-	gdb_bh = sb_bread(sb, gdblock);
+-	if (!gdb_bh)
+-		return -EIO;
++	gdb_bh = ext4_sb_bread(sb, gdblock, 0);
++	if (IS_ERR(gdb_bh))
++		return PTR_ERR(gdb_bh);
+ 
+ 	gdbackups = verify_reserved_gdb(sb, group, gdb_bh);
+ 	if (gdbackups < 0) {
+ 		err = gdbackups;
+-		goto exit_bh;
++		goto errout;
+ 	}
+ 
+ 	data = EXT4_I(inode)->i_data + EXT4_DIND_BLOCK;
+-	dind = sb_bread(sb, le32_to_cpu(*data));
+-	if (!dind) {
+-		err = -EIO;
+-		goto exit_bh;
++	dind = ext4_sb_bread(sb, le32_to_cpu(*data), 0);
++	if (IS_ERR(dind)) {
++		err = PTR_ERR(dind);
++		dind = NULL;
++		goto errout;
+ 	}
+ 
+ 	data = (__le32 *)dind->b_data;
+@@ -816,18 +819,18 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ 		ext4_warning(sb, "new group %u GDT block %llu not reserved",
+ 			     group, gdblock);
+ 		err = -EINVAL;
+-		goto exit_dind;
++		goto errout;
+ 	}
+ 
+ 	BUFFER_TRACE(EXT4_SB(sb)->s_sbh, "get_write_access");
+ 	err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh);
+ 	if (unlikely(err))
+-		goto exit_dind;
++		goto errout;
+ 
+ 	BUFFER_TRACE(gdb_bh, "get_write_access");
+ 	err = ext4_journal_get_write_access(handle, gdb_bh);
+ 	if (unlikely(err))
+-		goto exit_dind;
++		goto errout;
+ 
+ 	BUFFER_TRACE(dind, "get_write_access");
+ 	err = ext4_journal_get_write_access(handle, dind);
+@@ -837,7 +840,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ 	/* ext4_reserve_inode_write() gets a reference on the iloc */
+ 	err = ext4_reserve_inode_write(handle, inode, &iloc);
+ 	if (unlikely(err))
+-		goto exit_dind;
++		goto errout;
+ 
+ 	n_group_desc = ext4_kvmalloc((gdb_num + 1) *
+ 				     sizeof(struct buffer_head *),
+@@ -846,7 +849,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ 		err = -ENOMEM;
+ 		ext4_warning(sb, "not enough memory for %lu groups",
+ 			     gdb_num + 1);
+-		goto exit_inode;
++		goto errout;
+ 	}
+ 
+ 	/*
+@@ -862,7 +865,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ 	err = ext4_handle_dirty_metadata(handle, NULL, dind);
+ 	if (unlikely(err)) {
+ 		ext4_std_error(sb, err);
+-		goto exit_inode;
++		goto errout;
+ 	}
+ 	inode->i_blocks -= (gdbackups + 1) * sb->s_blocksize >>
+ 			   (9 - EXT4_SB(sb)->s_cluster_bits);
+@@ -871,8 +874,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ 	err = ext4_handle_dirty_metadata(handle, NULL, gdb_bh);
+ 	if (unlikely(err)) {
+ 		ext4_std_error(sb, err);
+-		iloc.bh = NULL;
+-		goto exit_inode;
++		goto errout;
+ 	}
+ 	brelse(dind);
+ 
+@@ -888,15 +890,11 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ 	err = ext4_handle_dirty_super(handle, sb);
+ 	if (err)
+ 		ext4_std_error(sb, err);
+-
+ 	return err;
+-
+-exit_inode:
++errout:
+ 	kvfree(n_group_desc);
+ 	brelse(iloc.bh);
+-exit_dind:
+ 	brelse(dind);
+-exit_bh:
+ 	brelse(gdb_bh);
+ 
+ 	ext4_debug("leaving with error %d\n", err);
+@@ -916,9 +914,9 @@ static int add_new_gdb_meta_bg(struct super_block *sb,
+ 
+ 	gdblock = ext4_meta_bg_first_block_no(sb, group) +
+ 		   ext4_bg_has_super(sb, group);
+-	gdb_bh = sb_bread(sb, gdblock);
+-	if (!gdb_bh)
+-		return -EIO;
++	gdb_bh = ext4_sb_bread(sb, gdblock, 0);
++	if (IS_ERR(gdb_bh))
++		return PTR_ERR(gdb_bh);
+ 	n_group_desc = ext4_kvmalloc((gdb_num + 1) *
+ 				     sizeof(struct buffer_head *),
+ 				     GFP_NOFS);
+@@ -975,9 +973,10 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
+ 		return -ENOMEM;
+ 
+ 	data = EXT4_I(inode)->i_data + EXT4_DIND_BLOCK;
+-	dind = sb_bread(sb, le32_to_cpu(*data));
+-	if (!dind) {
+-		err = -EIO;
++	dind = ext4_sb_bread(sb, le32_to_cpu(*data), 0);
++	if (IS_ERR(dind)) {
++		err = PTR_ERR(dind);
++		dind = NULL;
+ 		goto exit_free;
+ 	}
+ 
+@@ -996,9 +995,10 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
+ 			err = -EINVAL;
+ 			goto exit_bh;
+ 		}
+-		primary[res] = sb_bread(sb, blk);
+-		if (!primary[res]) {
+-			err = -EIO;
++		primary[res] = ext4_sb_bread(sb, blk, 0);
++		if (IS_ERR(primary[res])) {
++			err = PTR_ERR(primary[res]);
++			primary[res] = NULL;
+ 			goto exit_bh;
+ 		}
+ 		gdbackups = verify_reserved_gdb(sb, group, primary[res]);
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 53ff6c2a26ed..361624460431 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -140,6 +140,29 @@ MODULE_ALIAS_FS("ext3");
+ MODULE_ALIAS("ext3");
+ #define IS_EXT3_SB(sb) ((sb)->s_bdev->bd_holder == &ext3_fs_type)
+ 
++/*
++ * This works like sb_bread() except it uses ERR_PTR for error
++ * returns.  Currently with sb_bread it's impossible to distinguish
++ * between ENOMEM and EIO situations (since both result in a NULL
++ * return.
++ */
++struct buffer_head *
++ext4_sb_bread(struct super_block *sb, sector_t block, int op_flags)
++{
++	struct buffer_head *bh = sb_getblk(sb, block);
++
++	if (bh == NULL)
++		return ERR_PTR(-ENOMEM);
++	if (buffer_uptodate(bh))
++		return bh;
++	ll_rw_block(REQ_OP_READ, REQ_META | op_flags, 1, &bh);
++	wait_on_buffer(bh);
++	if (buffer_uptodate(bh))
++		return bh;
++	put_bh(bh);
++	return ERR_PTR(-EIO);
++}
++
+ static int ext4_verify_csum_type(struct super_block *sb,
+ 				 struct ext4_super_block *es)
+ {
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 7643d52c776c..510c9bb7ce71 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -522,14 +522,13 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
+ 	ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
+ 		  name_index, name, buffer, (long)buffer_size);
+ 
+-	error = -ENODATA;
+ 	if (!EXT4_I(inode)->i_file_acl)
+-		goto cleanup;
++		return -ENODATA;
+ 	ea_idebug(inode, "reading block %llu",
+ 		  (unsigned long long)EXT4_I(inode)->i_file_acl);
+-	bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
+-	if (!bh)
+-		goto cleanup;
++	bh = ext4_sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl, REQ_PRIO);
++	if (IS_ERR(bh))
++		return PTR_ERR(bh);
+ 	ea_bdebug(bh, "b_count=%d, refcount=%d",
+ 		atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
+ 	error = ext4_xattr_check_block(inode, bh);
+@@ -696,26 +695,23 @@ ext4_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size)
+ 	ea_idebug(inode, "buffer=%p, buffer_size=%ld",
+ 		  buffer, (long)buffer_size);
+ 
+-	error = 0;
+ 	if (!EXT4_I(inode)->i_file_acl)
+-		goto cleanup;
++		return 0;
+ 	ea_idebug(inode, "reading block %llu",
+ 		  (unsigned long long)EXT4_I(inode)->i_file_acl);
+-	bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
+-	error = -EIO;
+-	if (!bh)
+-		goto cleanup;
++	bh = ext4_sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl, REQ_PRIO);
++	if (IS_ERR(bh))
++		return PTR_ERR(bh);
+ 	ea_bdebug(bh, "b_count=%d, refcount=%d",
+ 		atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
+ 	error = ext4_xattr_check_block(inode, bh);
+ 	if (error)
+ 		goto cleanup;
+ 	ext4_xattr_block_cache_insert(EA_BLOCK_CACHE(inode), bh);
+-	error = ext4_xattr_list_entries(dentry, BFIRST(bh), buffer, buffer_size);
+-
++	error = ext4_xattr_list_entries(dentry, BFIRST(bh), buffer,
++					buffer_size);
+ cleanup:
+ 	brelse(bh);
+-
+ 	return error;
+ }
+ 
+@@ -830,9 +826,9 @@ int ext4_get_inode_usage(struct inode *inode, qsize_t *usage)
+ 	}
+ 
+ 	if (EXT4_I(inode)->i_file_acl) {
+-		bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
+-		if (!bh) {
+-			ret = -EIO;
++		bh = ext4_sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl, REQ_PRIO);
++		if (IS_ERR(bh)) {
++			ret = PTR_ERR(bh);
+ 			goto out;
+ 		}
+ 
+@@ -1821,16 +1817,15 @@ ext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i,
+ 
+ 	if (EXT4_I(inode)->i_file_acl) {
+ 		/* The inode already has an extended attribute block. */
+-		bs->bh = sb_bread(sb, EXT4_I(inode)->i_file_acl);
+-		error = -EIO;
+-		if (!bs->bh)
+-			goto cleanup;
++		bs->bh = ext4_sb_bread(sb, EXT4_I(inode)->i_file_acl, REQ_PRIO);
++		if (IS_ERR(bs->bh))
++			return PTR_ERR(bs->bh);
+ 		ea_bdebug(bs->bh, "b_count=%d, refcount=%d",
+ 			atomic_read(&(bs->bh->b_count)),
+ 			le32_to_cpu(BHDR(bs->bh)->h_refcount));
+ 		error = ext4_xattr_check_block(inode, bs->bh);
+ 		if (error)
+-			goto cleanup;
++			return error;
+ 		/* Find the named attribute. */
+ 		bs->s.base = BHDR(bs->bh);
+ 		bs->s.first = BFIRST(bs->bh);
+@@ -1839,13 +1834,10 @@ ext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i,
+ 		error = xattr_find_entry(inode, &bs->s.here, bs->s.end,
+ 					 i->name_index, i->name, 1);
+ 		if (error && error != -ENODATA)
+-			goto cleanup;
++			return error;
+ 		bs->s.not_found = error;
+ 	}
+-	error = 0;
+-
+-cleanup:
+-	return error;
++	return 0;
+ }
+ 
+ static int
+@@ -2274,9 +2266,9 @@ static struct buffer_head *ext4_xattr_get_block(struct inode *inode)
+ 
+ 	if (!EXT4_I(inode)->i_file_acl)
+ 		return NULL;
+-	bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
+-	if (!bh)
+-		return ERR_PTR(-EIO);
++	bh = ext4_sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl, REQ_PRIO);
++	if (IS_ERR(bh))
++		return bh;
+ 	error = ext4_xattr_check_block(inode, bh);
+ 	if (error) {
+ 		brelse(bh);
+@@ -2746,10 +2738,11 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
+ 	if (EXT4_I(inode)->i_file_acl) {
+ 		struct buffer_head *bh;
+ 
+-		bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
+-		error = -EIO;
+-		if (!bh)
++		bh = ext4_sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl, REQ_PRIO);
++		if (IS_ERR(bh)) {
++			error = PTR_ERR(bh);
+ 			goto cleanup;
++		}
+ 		error = ext4_xattr_check_block(inode, bh);
+ 		if (error) {
+ 			brelse(bh);
+@@ -2903,11 +2896,12 @@ int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode,
+ 	}
+ 
+ 	if (EXT4_I(inode)->i_file_acl) {
+-		bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
+-		if (!bh) {
+-			EXT4_ERROR_INODE(inode, "block %llu read error",
+-					 EXT4_I(inode)->i_file_acl);
+-			error = -EIO;
++		bh = ext4_sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl, REQ_PRIO);
++		if (IS_ERR(bh)) {
++			error = PTR_ERR(bh);
++			if (error == -EIO)
++				EXT4_ERROR_INODE(inode, "block %llu read error",
++						 EXT4_I(inode)->i_file_acl);
+ 			goto cleanup;
+ 		}
+ 		error = ext4_xattr_check_block(inode, bh);
+@@ -3060,8 +3054,10 @@ ext4_xattr_block_cache_find(struct inode *inode,
+ 	while (ce) {
+ 		struct buffer_head *bh;
+ 
+-		bh = sb_bread(inode->i_sb, ce->e_value);
+-		if (!bh) {
++		bh = ext4_sb_bread(inode->i_sb, ce->e_value, REQ_PRIO);
++		if (IS_ERR(bh)) {
++			if (PTR_ERR(bh) == -ENOMEM)
++				return NULL;
+ 			EXT4_ERROR_INODE(inode, "block %lu read error",
+ 					 (unsigned long)ce->e_value);
+ 		} else if (ext4_xattr_cmp(header, BHDR(bh)) == 0) {

commit 9e463084cdb22e0b56b2dfbc50461020409a5fd3
+Author: Theodore Ts'o 
+Date:   Wed Nov 7 10:32:53 2018 -0500
+
+    ext4: fix possible leak of sbi->s_group_desc_leak in error path
+    
+    Fixes: bfe0a5f47ada ("ext4: add more mount time checks of the superblock")
+    Reported-by: Vasily Averin 
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org # 4.18
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index a221f1cdf704..92092b55db1e 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4075,6 +4075,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	sbi->s_groups_count = blocks_count;
+ 	sbi->s_blockfile_groups = min_t(ext4_group_t, sbi->s_groups_count,
+ 			(EXT4_MAX_BLOCK_FILE_PHYS / EXT4_BLOCKS_PER_GROUP(sb)));
++	if (((u64)sbi->s_groups_count * sbi->s_inodes_per_group) !=
++	    le32_to_cpu(es->s_inodes_count)) {
++		ext4_msg(sb, KERN_ERR, "inodes count not valid: %u vs %llu",
++			 le32_to_cpu(es->s_inodes_count),
++			 ((u64)sbi->s_groups_count * sbi->s_inodes_per_group));
++		ret = -EINVAL;
++		goto failed_mount;
++	}
+ 	db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) /
+ 		   EXT4_DESC_PER_BLOCK(sb);
+ 	if (ext4_has_feature_meta_bg(sb)) {
+@@ -4094,14 +4102,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		ret = -ENOMEM;
+ 		goto failed_mount;
+ 	}
+-	if (((u64)sbi->s_groups_count * sbi->s_inodes_per_group) !=
+-	    le32_to_cpu(es->s_inodes_count)) {
+-		ext4_msg(sb, KERN_ERR, "inodes count not valid: %u vs %llu",
+-			 le32_to_cpu(es->s_inodes_count),
+-			 ((u64)sbi->s_groups_count * sbi->s_inodes_per_group));
+-		ret = -EINVAL;
+-		goto failed_mount;
+-	}
+ 
+ 	bgl_lock_init(sbi->s_blockgroup_lock);
+ 

commit 4f32c38b4662312dd3c5f113d8bdd459887fb773
+Author: Theodore Ts'o 
+Date:   Tue Nov 6 17:18:17 2018 -0500
+
+    ext4: avoid possible double brelse() in add_new_gdb() on error path
+    
+    Fixes: b40971426a83 ("ext4: add error checking to calls to ...")
+    Reported-by: Vasily Averin 
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org # 2.6.38
+
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 85158e9de7c2..a5efee34415f 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -871,6 +871,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ 	err = ext4_handle_dirty_metadata(handle, NULL, gdb_bh);
+ 	if (unlikely(err)) {
+ 		ext4_std_error(sb, err);
++		iloc.bh = NULL;
+ 		goto exit_inode;
+ 	}
+ 	brelse(dind);

commit 33458eaba4dfe778a426df6a19b7aad2ff9f7eec
+Author: Theodore Ts'o 
+Date:   Fri Oct 12 09:28:09 2018 -0400
+
+    ext4: fix use-after-free race in ext4_remount()'s error path
+    
+    It's possible for ext4_show_quota_options() to try reading
+    s_qf_names[i] while it is being modified by ext4_remount() --- most
+    notably, in ext4_remount's error path when the original values of the
+    quota file name gets restored.
+    
+    Reported-by: syzbot+a2872d6feea6918008a9@syzkaller.appspotmail.com
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org # 3.2+
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 86e1bacac757..12f90d48ba61 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1405,7 +1405,8 @@ struct ext4_sb_info {
+ 	u32 s_min_batch_time;
+ 	struct block_device *journal_bdev;
+ #ifdef CONFIG_QUOTA
+-	char *s_qf_names[EXT4_MAXQUOTAS];	/* Names of quota files with journalled quota */
++	/* Names of quota files with journalled quota */
++	char __rcu *s_qf_names[EXT4_MAXQUOTAS];
+ 	int s_jquota_fmt;			/* Format of quota to use */
+ #endif
+ 	unsigned int s_want_extra_isize; /* New inodes should reserve # bytes */
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index faf293ed8060..a221f1cdf704 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -914,6 +914,18 @@ static inline void ext4_quota_off_umount(struct super_block *sb)
+ 	for (type = 0; type < EXT4_MAXQUOTAS; type++)
+ 		ext4_quota_off(sb, type);
+ }
++
++/*
++ * This is a helper function which is used in the mount/remount
++ * codepaths (which holds s_umount) to fetch the quota file name.
++ */
++static inline char *get_qf_name(struct super_block *sb,
++				struct ext4_sb_info *sbi,
++				int type)
++{
++	return rcu_dereference_protected(sbi->s_qf_names[type],
++					 lockdep_is_held(&sb->s_umount));
++}
+ #else
+ static inline void ext4_quota_off_umount(struct super_block *sb)
+ {
+@@ -965,7 +977,7 @@ static void ext4_put_super(struct super_block *sb)
+ 	percpu_free_rwsem(&sbi->s_journal_flag_rwsem);
+ #ifdef CONFIG_QUOTA
+ 	for (i = 0; i < EXT4_MAXQUOTAS; i++)
+-		kfree(sbi->s_qf_names[i]);
++		kfree(get_qf_name(sb, sbi, i));
+ #endif
+ 
+ 	/* Debugging code just in case the in-memory inode orphan list
+@@ -1531,11 +1543,10 @@ static const char deprecated_msg[] =
+ static int set_qf_name(struct super_block *sb, int qtype, substring_t *args)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-	char *qname;
++	char *qname, *old_qname = get_qf_name(sb, sbi, qtype);
+ 	int ret = -1;
+ 
+-	if (sb_any_quota_loaded(sb) &&
+-		!sbi->s_qf_names[qtype]) {
++	if (sb_any_quota_loaded(sb) && !old_qname) {
+ 		ext4_msg(sb, KERN_ERR,
+ 			"Cannot change journaled "
+ 			"quota options when quota turned on");
+@@ -1552,8 +1563,8 @@ static int set_qf_name(struct super_block *sb, int qtype, substring_t *args)
+ 			"Not enough memory for storing quotafile name");
+ 		return -1;
+ 	}
+-	if (sbi->s_qf_names[qtype]) {
+-		if (strcmp(sbi->s_qf_names[qtype], qname) == 0)
++	if (old_qname) {
++		if (strcmp(old_qname, qname) == 0)
+ 			ret = 1;
+ 		else
+ 			ext4_msg(sb, KERN_ERR,
+@@ -1566,7 +1577,7 @@ static int set_qf_name(struct super_block *sb, int qtype, substring_t *args)
+ 			"quotafile must be on filesystem root");
+ 		goto errout;
+ 	}
+-	sbi->s_qf_names[qtype] = qname;
++	rcu_assign_pointer(sbi->s_qf_names[qtype], qname);
+ 	set_opt(sb, QUOTA);
+ 	return 1;
+ errout:
+@@ -1578,15 +1589,16 @@ static int clear_qf_name(struct super_block *sb, int qtype)
+ {
+ 
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
++	char *old_qname = get_qf_name(sb, sbi, qtype);
+ 
+-	if (sb_any_quota_loaded(sb) &&
+-		sbi->s_qf_names[qtype]) {
++	if (sb_any_quota_loaded(sb) && old_qname) {
+ 		ext4_msg(sb, KERN_ERR, "Cannot change journaled quota options"
+ 			" when quota turned on");
+ 		return -1;
+ 	}
+-	kfree(sbi->s_qf_names[qtype]);
+-	sbi->s_qf_names[qtype] = NULL;
++	rcu_assign_pointer(sbi->s_qf_names[qtype], NULL);
++	synchronize_rcu();
++	kfree(old_qname);
+ 	return 1;
+ }
+ #endif
+@@ -1961,7 +1973,7 @@ static int parse_options(char *options, struct super_block *sb,
+ 			 int is_remount)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-	char *p;
++	char *p, __maybe_unused *usr_qf_name, __maybe_unused *grp_qf_name;
+ 	substring_t args[MAX_OPT_ARGS];
+ 	int token;
+ 
+@@ -1992,11 +2004,13 @@ static int parse_options(char *options, struct super_block *sb,
+ 			 "Cannot enable project quota enforcement.");
+ 		return 0;
+ 	}
+-	if (sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]) {
+-		if (test_opt(sb, USRQUOTA) && sbi->s_qf_names[USRQUOTA])
++	usr_qf_name = get_qf_name(sb, sbi, USRQUOTA);
++	grp_qf_name = get_qf_name(sb, sbi, GRPQUOTA);
++	if (usr_qf_name || grp_qf_name) {
++		if (test_opt(sb, USRQUOTA) && usr_qf_name)
+ 			clear_opt(sb, USRQUOTA);
+ 
+-		if (test_opt(sb, GRPQUOTA) && sbi->s_qf_names[GRPQUOTA])
++		if (test_opt(sb, GRPQUOTA) && grp_qf_name)
+ 			clear_opt(sb, GRPQUOTA);
+ 
+ 		if (test_opt(sb, GRPQUOTA) || test_opt(sb, USRQUOTA)) {
+@@ -2030,6 +2044,7 @@ static inline void ext4_show_quota_options(struct seq_file *seq,
+ {
+ #if defined(CONFIG_QUOTA)
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
++	char *usr_qf_name, *grp_qf_name;
+ 
+ 	if (sbi->s_jquota_fmt) {
+ 		char *fmtname = "";
+@@ -2048,11 +2063,14 @@ static inline void ext4_show_quota_options(struct seq_file *seq,
+ 		seq_printf(seq, ",jqfmt=%s", fmtname);
+ 	}
+ 
+-	if (sbi->s_qf_names[USRQUOTA])
+-		seq_show_option(seq, "usrjquota", sbi->s_qf_names[USRQUOTA]);
+-
+-	if (sbi->s_qf_names[GRPQUOTA])
+-		seq_show_option(seq, "grpjquota", sbi->s_qf_names[GRPQUOTA]);
++	rcu_read_lock();
++	usr_qf_name = rcu_dereference(sbi->s_qf_names[USRQUOTA]);
++	grp_qf_name = rcu_dereference(sbi->s_qf_names[GRPQUOTA]);
++	if (usr_qf_name)
++		seq_show_option(seq, "usrjquota", usr_qf_name);
++	if (grp_qf_name)
++		seq_show_option(seq, "grpjquota", grp_qf_name);
++	rcu_read_unlock();
+ #endif
+ }
+ 
+@@ -5104,6 +5122,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 	int err = 0;
+ #ifdef CONFIG_QUOTA
+ 	int i, j;
++	char *to_free[EXT4_MAXQUOTAS];
+ #endif
+ 	char *orig_data = kstrdup(data, GFP_KERNEL);
+ 
+@@ -5123,8 +5142,9 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 	old_opts.s_jquota_fmt = sbi->s_jquota_fmt;
+ 	for (i = 0; i < EXT4_MAXQUOTAS; i++)
+ 		if (sbi->s_qf_names[i]) {
+-			old_opts.s_qf_names[i] = kstrdup(sbi->s_qf_names[i],
+-							 GFP_KERNEL);
++			char *qf_name = get_qf_name(sb, sbi, i);
++
++			old_opts.s_qf_names[i] = kstrdup(qf_name, GFP_KERNEL);
+ 			if (!old_opts.s_qf_names[i]) {
+ 				for (j = 0; j < i; j++)
+ 					kfree(old_opts.s_qf_names[j]);
+@@ -5353,9 +5373,12 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ #ifdef CONFIG_QUOTA
+ 	sbi->s_jquota_fmt = old_opts.s_jquota_fmt;
+ 	for (i = 0; i < EXT4_MAXQUOTAS; i++) {
+-		kfree(sbi->s_qf_names[i]);
+-		sbi->s_qf_names[i] = old_opts.s_qf_names[i];
++		to_free[i] = get_qf_name(sb, sbi, i);
++		rcu_assign_pointer(sbi->s_qf_names[i], old_opts.s_qf_names[i]);
+ 	}
++	synchronize_rcu();
++	for (i = 0; i < EXT4_MAXQUOTAS; i++)
++		kfree(to_free[i]);
+ #endif
+ 	kfree(orig_data);
+ 	return err;
+@@ -5546,7 +5569,7 @@ static int ext4_write_info(struct super_block *sb, int type)
+  */
+ static int ext4_quota_on_mount(struct super_block *sb, int type)
+ {
+-	return dquot_quota_on_mount(sb, EXT4_SB(sb)->s_qf_names[type],
++	return dquot_quota_on_mount(sb, get_qf_name(sb, EXT4_SB(sb), type),
+ 					EXT4_SB(sb)->s_jquota_fmt, type);
+ }
+ 

commit 18aded17492088962ef43f00825179598b3e8c58
+Author: Theodore Ts'o 
+Date:   Tue Oct 2 18:21:19 2018 -0400
+
+    ext4: fix EXT4_IOC_SWAP_BOOT
+    
+    The code EXT4_IOC_SWAP_BOOT ioctl hasn't been updated in a while, and
+    it's a bit broken with respect to more modern ext4 kernels, especially
+    metadata checksums.
+    
+    Other problems fixed with this commit:
+    
+    * Don't allow installing a DAX, swap file, or an encrypted file as a
+      boot loader.
+    
+    * Respect the immutable and append-only flags.
+    
+    * Wait until any DIO operations are finished *before* calling
+      truncate_inode_pages().
+    
+    * Don't swap inode->i_flags, since these flags have nothing to do with
+      the inode blocks --- and it will give the IMA/audit code heartburn
+      when the inode is evicted.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+    Reported-by: syzbot+e81ccd4744c6c4f71354@syzkaller.appspotmail.com
+
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index a7074115d6f6..d7ed7487e630 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -67,7 +67,6 @@ static void swap_inode_data(struct inode *inode1, struct inode *inode2)
+ 	ei1 = EXT4_I(inode1);
+ 	ei2 = EXT4_I(inode2);
+ 
+-	swap(inode1->i_flags, inode2->i_flags);
+ 	swap(inode1->i_version, inode2->i_version);
+ 	swap(inode1->i_blocks, inode2->i_blocks);
+ 	swap(inode1->i_bytes, inode2->i_bytes);
+@@ -85,6 +84,21 @@ static void swap_inode_data(struct inode *inode1, struct inode *inode2)
+ 	i_size_write(inode2, isize);
+ }
+ 
++static void reset_inode_seed(struct inode *inode)
++{
++	struct ext4_inode_info *ei = EXT4_I(inode);
++	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
++	__le32 inum = cpu_to_le32(inode->i_ino);
++	__le32 gen = cpu_to_le32(inode->i_generation);
++	__u32 csum;
++
++	if (!ext4_has_metadata_csum(inode->i_sb))
++		return;
++
++	csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&inum, sizeof(inum));
++	ei->i_csum_seed = ext4_chksum(sbi, csum, (__u8 *)&gen, sizeof(gen));
++}
++
+ /**
+  * Swap the information from the given @inode and the inode
+  * EXT4_BOOT_LOADER_INO. It will basically swap i_data and all other
+@@ -102,10 +116,13 @@ static long swap_inode_boot_loader(struct super_block *sb,
+ 	struct inode *inode_bl;
+ 	struct ext4_inode_info *ei_bl;
+ 
+-	if (inode->i_nlink != 1 || !S_ISREG(inode->i_mode))
++	if (inode->i_nlink != 1 || !S_ISREG(inode->i_mode) ||
++	    IS_SWAPFILE(inode) || IS_ENCRYPTED(inode) ||
++	    ext4_has_inline_data(inode))
+ 		return -EINVAL;
+ 
+-	if (!inode_owner_or_capable(inode) || !capable(CAP_SYS_ADMIN))
++	if (IS_RDONLY(inode) || IS_APPEND(inode) || IS_IMMUTABLE(inode) ||
++	    !inode_owner_or_capable(inode) || !capable(CAP_SYS_ADMIN))
+ 		return -EPERM;
+ 
+ 	inode_bl = ext4_iget(sb, EXT4_BOOT_LOADER_INO);
+@@ -120,13 +137,13 @@ static long swap_inode_boot_loader(struct super_block *sb,
+ 	 * that only 1 swap_inode_boot_loader is running. */
+ 	lock_two_nondirectories(inode, inode_bl);
+ 
+-	truncate_inode_pages(&inode->i_data, 0);
+-	truncate_inode_pages(&inode_bl->i_data, 0);
+-
+ 	/* Wait for all existing dio workers */
+ 	inode_dio_wait(inode);
+ 	inode_dio_wait(inode_bl);
+ 
++	truncate_inode_pages(&inode->i_data, 0);
++	truncate_inode_pages(&inode_bl->i_data, 0);
++
+ 	handle = ext4_journal_start(inode_bl, EXT4_HT_MOVE_EXTENTS, 2);
+ 	if (IS_ERR(handle)) {
+ 		err = -EINVAL;
+@@ -159,6 +176,8 @@ static long swap_inode_boot_loader(struct super_block *sb,
+ 
+ 	inode->i_generation = prandom_u32();
+ 	inode_bl->i_generation = prandom_u32();
++	reset_inode_seed(inode);
++	reset_inode_seed(inode_bl);
+ 
+ 	ext4_discard_preallocations(inode);
+ 
+@@ -169,6 +188,7 @@ static long swap_inode_boot_loader(struct super_block *sb,
+ 			inode->i_ino, err);
+ 		/* Revert all changes: */
+ 		swap_inode_data(inode, inode_bl);
++		ext4_mark_inode_dirty(handle, inode);
+ 	} else {
+ 		err = ext4_mark_inode_dirty(handle, inode_bl);
+ 		if (err < 0) {
+@@ -178,6 +198,7 @@ static long swap_inode_boot_loader(struct super_block *sb,
+ 			/* Revert all changes: */
+ 			swap_inode_data(inode, inode_bl);
+ 			ext4_mark_inode_dirty(handle, inode);
++			ext4_mark_inode_dirty(handle, inode_bl);
+ 		}
+ 	}
+ 	ext4_journal_stop(handle);

commit f18b2b83a727a3db208308057d2c7945f368e625
+Author: Theodore Ts'o 
+Date:   Tue Oct 2 01:34:44 2018 -0400
+
+    ext4: fix argument checking in EXT4_IOC_MOVE_EXT
+    
+    If the starting block number of either the source or destination file
+    exceeds the EOF, EXT4_IOC_MOVE_EXT should return EINVAL.
+    
+    Also fixed the helper function mext_check_coverage() so that if the
+    logical block is beyond EOF, make it return immediately, instead of
+    looping until the block number wraps all the away around.  This takes
+    long enough that if there are multiple threads trying to do pound on
+    an the same inode doing non-sensical things, it can end up triggering
+    the kernel's soft lockup detector.
+    
+    Reported-by: syzbot+c61979f6f2cba5cb3c06@syzkaller.appspotmail.com
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
+index a409ff70d67b..2f5be02fc6f6 100644
+--- a/fs/ext4/move_extent.c
++++ b/fs/ext4/move_extent.c
+@@ -516,9 +516,13 @@ mext_check_arguments(struct inode *orig_inode,
+ 			orig_inode->i_ino, donor_inode->i_ino);
+ 		return -EINVAL;
+ 	}
+-	if (orig_eof < orig_start + *len - 1)
++	if (orig_eof <= orig_start)
++		*len = 0;
++	else if (orig_eof < orig_start + *len - 1)
+ 		*len = orig_eof - orig_start;
+-	if (donor_eof < donor_start + *len - 1)
++	if (donor_eof <= donor_start)
++		*len = 0;
++	else if (donor_eof < donor_start + *len - 1)
+ 		*len = donor_eof - donor_start;
+ 	if (!*len) {
+ 		ext4_debug("ext4 move extent: len should not be 0 "

commit 5f8c10936fab2b69a487400f2872902e597dd320
+Author: Theodore Ts'o 
+Date:   Mon Sep 3 22:25:01 2018 -0400
+
+    ext4: fix online resizing for bigalloc file systems with a 1k block size
+    
+    An online resize of a file system with the bigalloc feature enabled
+    and a 1k block size would be refused since ext4_resize_begin() did not
+    understand s_first_data_block is 0 for all bigalloc file systems, even
+    when the block size is 1k.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 33655a6eff4d..ebbc663d0798 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -19,6 +19,7 @@
+ 
+ int ext4_resize_begin(struct super_block *sb)
+ {
++	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	int ret = 0;
+ 
+ 	if (!capable(CAP_SYS_RESOURCE))
+@@ -29,7 +30,7 @@ int ext4_resize_begin(struct super_block *sb)
+          * because the user tools have no way of handling this.  Probably a
+          * bad time to do it anyways.
+          */
+-	if (EXT4_SB(sb)->s_sbh->b_blocknr !=
++	if (EXT4_B2C(sbi, sbi->s_sbh->b_blocknr) !=
+ 	    le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block)) {
+ 		ext4_warning(sb, "won't resize using backup superblock at %llu",
+ 			(unsigned long long)EXT4_SB(sb)->s_sbh->b_blocknr);

commit f0a459dec5495a3580f8d784555e6f8f3bf7f263
+Author: Theodore Ts'o 
+Date:   Mon Sep 3 22:19:43 2018 -0400
+
+    ext4: fix online resize's handling of a too-small final block group
+    
+    Avoid growing the file system to an extent so that the last block
+    group is too small to hold all of the metadata that must be stored in
+    the block group.
+    
+    This problem can be triggered with the following reproducer:
+    
+    umount /mnt
+    mke2fs -F -m0 -b 4096 -t ext4 -O resize_inode,^has_journal \
+            -E resize=1073741824 /tmp/foo.img 128M
+    mount /tmp/foo.img /mnt
+    truncate --size 1708M /tmp/foo.img
+    resize2fs /dev/loop0 295400
+    umount /mnt
+    e2fsck -fy /tmp/foo.img
+    
+    Reported-by: Torsten Hilbrich 
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index e5fb38451a73..33655a6eff4d 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -1986,6 +1986,26 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
+ 		}
+ 	}
+ 
++	/*
++	 * Make sure the last group has enough space so that it's
++	 * guaranteed to have enough space for all metadata blocks
++	 * that it might need to hold.  (We might not need to store
++	 * the inode table blocks in the last block group, but there
++	 * will be cases where this might be needed.)
++	 */
++	if ((ext4_group_first_block_no(sb, n_group) +
++	     ext4_group_overhead_blocks(sb, n_group) + 2 +
++	     sbi->s_itb_per_group + sbi->s_cluster_ratio) >= n_blocks_count) {
++		n_blocks_count = ext4_group_first_block_no(sb, n_group);
++		n_group--;
++		n_blocks_count_retry = 0;
++		if (resize_inode) {
++			iput(resize_inode);
++			resize_inode = NULL;
++		}
++		goto retry;
++	}
++
+ 	/* extend the last group */
+ 	if (n_group == o_group)
+ 		add = n_blocks_count - o_blocks_count;

commit 4274f516d4bc50648a4d97e4f67ecbd7b65cde4a
+Author: Theodore Ts'o 
+Date:   Sat Sep 1 14:42:14 2018 -0400
+
+    ext4: recalucate superblock checksum after updating free blocks/inodes
+    
+    When mounting the superblock, ext4_fill_super() calculates the free
+    blocks and free inodes and stores them in the superblock.  It's not
+    strictly necessary, since we don't use them any more, but it's nice to
+    keep them roughly aligned to reality.
+    
+    Since it's not critical for file system correctness, the code doesn't
+    call ext4_commit_super().  The problem is that it's in
+    ext4_commit_super() that we recalculate the superblock checksum.  So
+    if we're not going to call ext4_commit_super(), we need to call
+    ext4_superblock_csum_set() to make sure the superblock checksum is
+    consistent.
+    
+    Most of the time, this doesn't matter, since we end up calling
+    ext4_commit_super() very soon thereafter, and definitely by the time
+    the file system is unmounted.  However, it doesn't work in this
+    sequence:
+    
+    mke2fs -Fq -t ext4 /dev/vdc 128M
+    mount /dev/vdc /vdc
+    cp xfstests/git-versions /vdc
+    godown /vdc
+    umount /vdc
+    mount /dev/vdc
+    tune2fs -l /dev/vdc
+    
+    With this commit, the "tune2fs -l" no longer fails.
+    
+    Reported-by: Chengguang Xu 
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index f7750bc5b85a..e41da553b430 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4378,11 +4378,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	block = ext4_count_free_clusters(sb);
+ 	ext4_free_blocks_count_set(sbi->s_es, 
+ 				   EXT4_C2B(sbi, block));
++	ext4_superblock_csum_set(sb);
+ 	err = percpu_counter_init(&sbi->s_freeclusters_counter, block,
+ 				  GFP_KERNEL);
+ 	if (!err) {
+ 		unsigned long freei = ext4_count_free_inodes(sb);
+ 		sbi->s_es->s_free_inodes_count = cpu_to_le32(freei);
++		ext4_superblock_csum_set(sb);
+ 		err = percpu_counter_init(&sbi->s_freeinodes_counter, freei,
+ 					  GFP_KERNEL);
+ 	}

commit bcd8e91f98c156f4b1ebcfacae675f9cfd962441
+Author: Theodore Ts'o 
+Date:   Sat Sep 1 12:45:04 2018 -0400
+
+    ext4: avoid arithemetic overflow that can trigger a BUG
+    
+    A maliciously crafted file system can cause an overflow when the
+    results of a 64-bit calculation is stored into a 32-bit length
+    parameter.
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=200623
+    
+    Signed-off-by: Theodore Ts'o 
+    Reported-by: Wen Xu 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 249bcee4d7b2..ac05bd86643a 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -686,6 +686,9 @@ enum {
+ /* Max physical block we can address w/o extents */
+ #define EXT4_MAX_BLOCK_FILE_PHYS	0xFFFFFFFF
+ 
++/* Max logical block we can support */
++#define EXT4_MAX_LOGICAL_BLOCK		0xFFFFFFFF
++
+ /*
+  * Structure of an inode on the disk
+  */
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 8f6ad7667974..694f31364206 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -3412,12 +3412,16 @@ static int ext4_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+ 	unsigned int blkbits = inode->i_blkbits;
+-	unsigned long first_block = offset >> blkbits;
+-	unsigned long last_block = (offset + length - 1) >> blkbits;
++	unsigned long first_block, last_block;
+ 	struct ext4_map_blocks map;
+ 	bool delalloc = false;
+ 	int ret;
+ 
++	if ((offset >> blkbits) > EXT4_MAX_LOGICAL_BLOCK)
++		return -EINVAL;
++	first_block = offset >> blkbits;
++	last_block = min_t(loff_t, (offset + length - 1) >> blkbits,
++			   EXT4_MAX_LOGICAL_BLOCK);
+ 
+ 	if (flags & IOMAP_REPORT) {
+ 		if (ext4_has_inline_data(inode)) {

commit 4d982e25d0bdc83d8c64e66fdeca0b89240b3b85
+Author: Theodore Ts'o 
+Date:   Mon Aug 27 09:22:45 2018 -0400
+
+    ext4: avoid divide by zero fault when deleting corrupted inline directories
+    
+    A specially crafted file system can trick empty_inline_dir() into
+    reading past the last valid entry in a inline directory, and then run
+    into the end of xattr marker. This will trigger a divide by zero
+    fault.  Fix this by using the size of the inline directory instead of
+    dir->i_size.
+    
+    Also clean up error reporting in __ext4_check_dir_entry so that the
+    message is clearer and more understandable --- and avoids the division
+    by zero trap if the size passed in is zero.  (I'm not sure why we
+    coded it that way in the first place; printing offset % size is
+    actually more confusing and less useful.)
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=200933
+    
+    Signed-off-by: Theodore Ts'o 
+    Reported-by: Wen Xu 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index e2902d394f1b..f93f9881ec18 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -76,7 +76,7 @@ int __ext4_check_dir_entry(const char *function, unsigned int line,
+ 	else if (unlikely(rlen < EXT4_DIR_REC_LEN(de->name_len)))
+ 		error_msg = "rec_len is too small for name_len";
+ 	else if (unlikely(((char *) de - buf) + rlen > size))
+-		error_msg = "directory entry across range";
++		error_msg = "directory entry overrun";
+ 	else if (unlikely(le32_to_cpu(de->inode) >
+ 			le32_to_cpu(EXT4_SB(dir->i_sb)->s_es->s_inodes_count)))
+ 		error_msg = "inode out of bounds";
+@@ -85,18 +85,16 @@ int __ext4_check_dir_entry(const char *function, unsigned int line,
+ 
+ 	if (filp)
+ 		ext4_error_file(filp, function, line, bh->b_blocknr,
+-				"bad entry in directory: %s - offset=%u(%u), "
+-				"inode=%u, rec_len=%d, name_len=%d",
+-				error_msg, (unsigned) (offset % size),
+-				offset, le32_to_cpu(de->inode),
+-				rlen, de->name_len);
++				"bad entry in directory: %s - offset=%u, "
++				"inode=%u, rec_len=%d, name_len=%d, size=%d",
++				error_msg, offset, le32_to_cpu(de->inode),
++				rlen, de->name_len, size);
+ 	else
+ 		ext4_error_inode(dir, function, line, bh->b_blocknr,
+-				"bad entry in directory: %s - offset=%u(%u), "
+-				"inode=%u, rec_len=%d, name_len=%d",
+-				error_msg, (unsigned) (offset % size),
+-				offset, le32_to_cpu(de->inode),
+-				rlen, de->name_len);
++				"bad entry in directory: %s - offset=%u, "
++				"inode=%u, rec_len=%d, name_len=%d, size=%d",
++				 error_msg, offset, le32_to_cpu(de->inode),
++				 rlen, de->name_len, size);
+ 
+ 	return 1;
+ }
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index 3543fe80a3c4..7b4736022761 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -1753,6 +1753,7 @@ bool empty_inline_dir(struct inode *dir, int *has_inline_data)
+ {
+ 	int err, inline_size;
+ 	struct ext4_iloc iloc;
++	size_t inline_len;
+ 	void *inline_pos;
+ 	unsigned int offset;
+ 	struct ext4_dir_entry_2 *de;
+@@ -1780,8 +1781,9 @@ bool empty_inline_dir(struct inode *dir, int *has_inline_data)
+ 		goto out;
+ 	}
+ 
++	inline_len = ext4_get_inline_size(dir);
+ 	offset = EXT4_INLINE_DOTDOT_SIZE;
+-	while (offset < dir->i_size) {
++	while (offset < inline_len) {
+ 		de = ext4_get_inline_entry(dir, &iloc, offset,
+ 					   &inline_pos, &inline_size);
+ 		if (ext4_check_dir_entry(dir, NULL, de,

commit b50282f3241acee880514212d88b6049fb5039c8
+Author: Theodore Ts'o 
+Date:   Mon Aug 27 01:47:09 2018 -0400
+
+    ext4: check to make sure the rename(2)'s destination is not freed
+    
+    If the destination of the rename(2) system call exists, the inode's
+    link count (i_nlinks) must be non-zero.  If it is, the inode can end
+    up on the orphan list prematurely, leading to all sorts of hilarity,
+    including a use-after-free.
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=200931
+    
+    Signed-off-by: Theodore Ts'o 
+    Reported-by: Wen Xu 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 116ff68c5bd4..377d516c475f 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -3478,6 +3478,12 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 	int credits;
+ 	u8 old_file_type;
+ 
++	if (new.inode && new.inode->i_nlink == 0) {
++		EXT4_ERROR_INODE(new.inode,
++				 "target of rename is already freed");
++		return -EFSCORRUPTED;
++	}
++
+ 	if ((ext4_test_inode_flag(new_dir, EXT4_INODE_PROJINHERIT)) &&
+ 	    (!projid_eq(EXT4_I(new_dir)->i_projid,
+ 			EXT4_I(old_dentry->d_inode)->i_projid)))

commit 072ebb3bffe67d71d1f1e52add799f4491eab691
+Author: Theodore Ts'o 
+Date:   Mon Aug 27 01:15:11 2018 -0400
+
+    ext4: add nonstring annotations to ext4.h
+    
+    This suppresses some false positives in gcc 8's -Wstringop-truncation
+    
+    Suggested by Miguel Ojeda (hopefully the __nonstring definition will
+    eventually get accepted in the compiler-gcc.h header file).
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: Miguel Ojeda 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 1fc013f3d944..249bcee4d7b2 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -43,6 +43,17 @@
+ #define __FS_HAS_ENCRYPTION IS_ENABLED(CONFIG_EXT4_FS_ENCRYPTION)
+ #include 
+ 
++#include 
++
++/* Until this gets included into linux/compiler-gcc.h */
++#ifndef __nonstring
++#if defined(GCC_VERSION) && (GCC_VERSION >= 80000)
++#define __nonstring __attribute__((nonstring))
++#else
++#define __nonstring
++#endif
++#endif
++
+ /*
+  * The fourth extended filesystem constants/structures
+  */
+@@ -1226,7 +1237,7 @@ struct ext4_super_block {
+ 	__le32	s_feature_ro_compat;	/* readonly-compatible feature set */
+ /*68*/	__u8	s_uuid[16];		/* 128-bit uuid for volume */
+ /*78*/	char	s_volume_name[16];	/* volume name */
+-/*88*/	char	s_last_mounted[64];	/* directory where last mounted */
++/*88*/	char	s_last_mounted[64] __nonstring;	/* directory where last mounted */
+ /*C8*/	__le32	s_algorithm_usage_bitmap; /* For compression */
+ 	/*
+ 	 * Performance hints.  Directory preallocation should only
+@@ -1277,13 +1288,13 @@ struct ext4_super_block {
+ 	__le32	s_first_error_time;	/* first time an error happened */
+ 	__le32	s_first_error_ino;	/* inode involved in first error */
+ 	__le64	s_first_error_block;	/* block involved of first error */
+-	__u8	s_first_error_func[32];	/* function where the error happened */
++	__u8	s_first_error_func[32] __nonstring;	/* function where the error happened */
+ 	__le32	s_first_error_line;	/* line number where error happened */
+ 	__le32	s_last_error_time;	/* most recent time of an error */
+ 	__le32	s_last_error_ino;	/* inode involved in last error */
+ 	__le32	s_last_error_line;	/* line number where error happened */
+ 	__le64	s_last_error_block;	/* block involved of last error */
+-	__u8	s_last_error_func[32];	/* function where the error happened */
++	__u8	s_last_error_func[32] __nonstring;	/* function where the error happened */
+ #define EXT4_S_ERR_END offsetof(struct ext4_super_block, s_mount_opts)
+ 	__u8	s_mount_opts[64];
+ 	__le32	s_usr_quota_inum;	/* inode for tracking user quota */

commit 7d95178c77014dbd8dce36ee40bbbc5e6c121ff5
+Author: Theodore Ts'o 
+Date:   Wed Aug 1 12:36:52 2018 -0400
+
+    ext4: check for NUL characters in extended attribute's name
+    
+    Extended attribute names are defined to be NUL-terminated, so the name
+    must not contain a NUL character.  This is important because there are
+    places when remove extended attribute, the code uses strlen to
+    determine the length of the entry.  That should probably be fixed at
+    some point, but code is currently really messy, so the simplest fix
+    for now is to simply validate that the extended attributes are sane.
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=200401
+    
+    Reported-by: Wen Xu 
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 723df14f4084..f36fc5d5b257 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -190,6 +190,8 @@ ext4_xattr_check_entries(struct ext4_xattr_entry *entry, void *end,
+ 		struct ext4_xattr_entry *next = EXT4_XATTR_NEXT(e);
+ 		if ((void *)next >= end)
+ 			return -EFSCORRUPTED;
++		if (strnlen(e->e_name, e->e_name_len) != e->e_name_len)
++			return -EFSCORRUPTED;
+ 		e = next;
+ 	}
+ 

commit 0694f8c39f113bcdb759a7f84981a69bf5d7161d
+Author: Theodore Ts'o 
+Date:   Sun Jul 29 16:35:23 2018 -0400
+
+    docs: fix up the obviously obsolete bits in the new ext4 documentation
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/Documentation/filesystems/ext4/ext4.rst b/Documentation/filesystems/ext4/ext4.rst
+index 47f614c47f56..9d4368d591fa 100644
+--- a/Documentation/filesystems/ext4/ext4.rst
++++ b/Documentation/filesystems/ext4/ext4.rst
+@@ -20,43 +20,32 @@ Note: More extensive information for getting started with ext4 can be
+ found at the ext4 wiki site at the URL:
+ http://ext4.wiki.kernel.org/index.php/Ext4_Howto
+ 
+-  - Compile and install the latest version of e2fsprogs (as of this
+-    writing version 1.41.3) from:
++  - The latest version of e2fsprogs can be found at:
+ 
+-    http://sourceforge.net/project/showfiles.php?group_id=2406
++    https://www.kernel.org/pub/linux/kernel/people/tytso/e2fsprogs/
+ 
+ 	or
+ 
+-    https://www.kernel.org/pub/linux/kernel/people/tytso/e2fsprogs/
++    http://sourceforge.net/project/showfiles.php?group_id=2406
+ 
+ 	or grab the latest git repository from:
+ 
+-    git://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git
+-
+-  - Note that it is highly important to install the mke2fs.conf file
+-    that comes with the e2fsprogs 1.41.x sources in /etc/mke2fs.conf. If
+-    you have edited the /etc/mke2fs.conf file installed on your system,
+-    you will need to merge your changes with the version from e2fsprogs
+-    1.41.x.
++   https://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git
+ 
+-  - Create a new filesystem using the ext4 filesystem type:::
++  - Create a new filesystem using the ext4 filesystem type:
+ 
+         # mke2fs -t ext4 /dev/hda1
+ 
+-    Or to configure an existing ext3 filesystem to support extents:::
++    Or to configure an existing ext3 filesystem to support extents:
+ 
+ 	# tune2fs -O extents /dev/hda1
+ 
+     If the filesystem was created with 128 byte inodes, it can be
+-    converted to use 256 byte for greater efficiency via:::
++    converted to use 256 byte for greater efficiency via:
+ 
+         # tune2fs -I 256 /dev/hda1
+ 
+-    (Note: we currently do not have tools to convert an ext4
+-    filesystem back to ext3; so please do not do try this on production
+-    filesystems.)
+-
+-  - Mounting:::
++  - Mounting:
+ 
+ 	# mount -t ext4 /dev/hda1 /wherever
+ 
+@@ -106,26 +95,6 @@ Currently Available
+ [1] Filesystems with a block size of 1k may see a limit imposed by the
+ directory hash tree having a maximum depth of two.
+ 
+-Candidate Features for Future Inclusion
+----------------------------------------
+-
+-* online defrag (patches available but not well tested)
+-* reduced mke2fs time via lazy itable initialization in conjunction with
+-  the uninit_bg feature (capability to do this is available in e2fsprogs
+-  but a kernel thread to do lazy zeroing of unused inode table blocks
+-  after filesystem is first mounted is required for safety)
+-
+-There are several others under discussion, whether they all make it in is
+-partly a function of how much time everyone has to work on them. Features like
+-metadata checksumming have been discussed and planned for a bit but no patches
+-exist yet so I'm not sure they're in the near-term roadmap.
+-
+-The big performance win will come with mballoc, delalloc and flex_bg
+-grouping of bitmaps and inode tables.  Some test results available here:
+-
+- - http://www.bullopensource.org/ext4/20080818-ffsb/ffsb-write-2.6.27-rc1.html
+- - http://www.bullopensource.org/ext4/20080818-ffsb/ffsb-readwrite-2.6.27-rc1.html
+-
+ Options
+ =======
+ 
+diff --git a/Documentation/index.rst b/Documentation/index.rst
+index 65c22b1ff5f2..f95ba981f8cd 100644
+--- a/Documentation/index.rst
++++ b/Documentation/index.rst
+@@ -109,7 +109,7 @@ The documentation in this section are provided by specific filesystem
+ subprojects.
+ 
+ .. toctree::
+-   :maxdepth: 4
++   :maxdepth: 2
+ 
+    filesystems/ext4/index
+ 

commit 5012284700775a4e6e3fbe7eac4c543c4874b559
+Author: Theodore Ts'o 
+Date:   Sat Jul 28 08:12:04 2018 -0400
+
+    ext4: fix check to prevent initializing reserved inodes
+    
+    Commit 8844618d8aa7: "ext4: only look at the bg_flags field if it is
+    valid" will complain if block group zero does not have the
+    EXT4_BG_INODE_ZEROED flag set.  Unfortunately, this is not correct,
+    since a freshly created file system has this flag cleared.  It gets
+    almost immediately after the file system is mounted read-write --- but
+    the following somewhat unlikely sequence will end up triggering a
+    false positive report of a corrupted file system:
+    
+       mkfs.ext4 /dev/vdc
+       mount -o ro /dev/vdc /vdc
+       mount -o remount,rw /dev/vdc
+    
+    Instead, when initializing the inode table for block group zero, test
+    to make sure that itable_unused count is not too large, since that is
+    the case that will result in some or all of the reserved inodes
+    getting cleared.
+    
+    This fixes the failures reported by Eric Whiteney when running
+    generic/230 and generic/231 in the the nojournal test case.
+    
+    Fixes: 8844618d8aa7 ("ext4: only look at the bg_flags field if it is valid")
+    Reported-by: Eric Whitney 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index e9d8e2667ab5..f336cbc6e932 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -1388,7 +1388,10 @@ int ext4_init_inode_table(struct super_block *sb, ext4_group_t group,
+ 			    ext4_itable_unused_count(sb, gdp)),
+ 			    sbi->s_inodes_per_block);
+ 
+-	if ((used_blks < 0) || (used_blks > sbi->s_itb_per_group)) {
++	if ((used_blks < 0) || (used_blks > sbi->s_itb_per_group) ||
++	    ((group == 0) && ((EXT4_INODES_PER_GROUP(sb) -
++			       ext4_itable_unused_count(sb, gdp)) <
++			      EXT4_FIRST_INO(sb)))) {
+ 		ext4_error(sb, "Something is wrong with group %u: "
+ 			   "used itable blocks: %d; "
+ 			   "itable unused count: %u",
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 680526e9ee96..b7f7922061be 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3141,14 +3141,8 @@ static ext4_group_t ext4_has_uninit_itable(struct super_block *sb)
+ 		if (!gdp)
+ 			continue;
+ 
+-		if (gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED))
+-			continue;
+-		if (group != 0)
++		if (!(gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED)))
+ 			break;
+-		ext4_error(sb, "Inode table for bg 0 marked as "
+-			   "needing zeroing");
+-		if (sb_rdonly(sb))
+-			return ngroups;
+ 	}
+ 
+ 	return group;

commit 39a8883a2b989d1d21bd8dd99f5557f0c5e89694
+Author: Theodore Ts'o 
+Date:   Tue Jul 17 18:24:27 2018 -0400
+
+    random: add a config option to trust the CPU's hwrng
+    
+    This gives the user building their own kernel (or a Linux
+    distribution) the option of deciding whether or not to trust the CPU's
+    hardware random number generator (e.g., RDRAND for x86 CPU's) as being
+    correctly implemented and not having a back door introduced (perhaps
+    courtesy of a Nation State's law enforcement or intelligence
+    agencies).
+    
+    This will prevent getrandom(2) from blocking, if there is a
+    willingness to trust the CPU manufacturer.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
+index 212f447938ae..ce277ee0a28a 100644
+--- a/drivers/char/Kconfig
++++ b/drivers/char/Kconfig
+@@ -554,3 +554,17 @@ config ADI
+ 
+ endmenu
+ 
++config RANDOM_TRUST_CPU
++	bool "Trust the CPU manufacturer to initialize Linux's CRNG"
++	depends on X86 || S390 || PPC
++	default n
++	help
++	Assume that CPU manufacturer (e.g., Intel or AMD for RDSEED or
++	RDRAND, IBM for the S390 and Power PC architectures) is trustworthy
++	for the purposes of initializing Linux's CRNG.  Since this is not
++	something that can be independently audited, this amounts to trusting
++	that CPU manufacturer (perhaps with the insistence or mandate
++	of a Nation State's intelligence or law enforcement agencies)
++	has not installed a hidden back door to compromise the CPU's
++	random number generation facilities.
++
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 34ddfd57419b..f4013b8a711b 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -782,6 +782,7 @@ static void invalidate_batched_entropy(void);
+ static void crng_initialize(struct crng_state *crng)
+ {
+ 	int		i;
++	int		arch_init = 1;
+ 	unsigned long	rv;
+ 
+ 	memcpy(&crng->state[0], "expand 32-byte k", 16);
+@@ -792,10 +793,18 @@ static void crng_initialize(struct crng_state *crng)
+ 		_get_random_bytes(&crng->state[4], sizeof(__u32) * 12);
+ 	for (i = 4; i < 16; i++) {
+ 		if (!arch_get_random_seed_long(&rv) &&
+-		    !arch_get_random_long(&rv))
++		    !arch_get_random_long(&rv)) {
+ 			rv = random_get_entropy();
++			arch_init = 0;
++		}
+ 		crng->state[i] ^= rv;
+ 	}
++#ifdef CONFIG_RANDOM_TRUST_CPU
++	if (arch_init) {
++		crng_init = 2;
++		pr_notice("random: crng done (trusting CPU's manufacturer)\n");
++	}
++#endif
+ 	crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1;
+ }
+ 

commit 81e69df38e2911b642ec121dec319fad2a4782f3
+Author: Theodore Ts'o 
+Date:   Sat Jul 14 23:55:57 2018 -0400
+
+    random: mix rdrand with entropy sent in from userspace
+    
+    Fedora has integrated the jitter entropy daemon to work around slow
+    boot problems, especially on VM's that don't support virtio-rng:
+    
+        https://bugzilla.redhat.com/show_bug.cgi?id=1572944
+    
+    It's understandable why they did this, but the Jitter entropy daemon
+    works fundamentally on the principle: "the CPU microarchitecture is
+    **so** complicated and we can't figure it out, so it *must* be
+    random".  Yes, it uses statistical tests to "prove" it is secure, but
+    AES_ENCRYPT(NSA_KEY, COUNTER++) will also pass statistical tests with
+    flying colors.
+    
+    So if RDRAND is available, mix it into entropy submitted from
+    userspace.  It can't hurt, and if you believe the NSA has backdoored
+    RDRAND, then they probably have enough details about the Intel
+    microarchitecture that they can reverse engineer how the Jitter
+    entropy daemon affects the microarchitecture, and attack its output
+    stream.  And if RDRAND is in fact an honest DRNG, it will immeasurably
+    improve on what the Jitter entropy daemon might produce.
+    
+    This also provides some protection against someone who is able to read
+    or set the entropy seed file.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+    Cc: Arnd Bergmann 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index cd888d4ee605..bd449ad52442 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -1895,14 +1895,22 @@ static int
+ write_pool(struct entropy_store *r, const char __user *buffer, size_t count)
+ {
+ 	size_t bytes;
+-	__u32 buf[16];
++	__u32 t, buf[16];
+ 	const char __user *p = buffer;
+ 
+ 	while (count > 0) {
++		int b, i = 0;
++
+ 		bytes = min(count, sizeof(buf));
+ 		if (copy_from_user(&buf, p, bytes))
+ 			return -EFAULT;
+ 
++		for (b = bytes ; b > 0 ; b -= sizeof(__u32), i++) {
++			if (!arch_get_random_int(&t))
++				break;
++			buf[i] ^= t;
++		}
++
+ 		count -= bytes;
+ 		p += bytes;
+ 

commit 8d5a803c6a6ce4ec258e31f76059ea5153ba46ef
+Author: Theodore Ts'o 
+Date:   Thu Jul 12 19:08:05 2018 -0400
+
+    ext4: check for allocation block validity with block group locked
+    
+    With commit 044e6e3d74a3: "ext4: don't update checksum of new
+    initialized bitmaps" the buffer valid bit will get set without
+    actually setting up the checksum for the allocation bitmap, since the
+    checksum will get calculated once we actually allocate an inode or
+    block.
+    
+    If we are doing this, then we need to (re-)check the verified bit
+    after we take the block group lock.  Otherwise, we could race with
+    another process reading and verifying the bitmap, which would then
+    complain about the checksum being invalid.
+    
+    https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1780137
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index e68cefe08261..aa52d87985aa 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -368,6 +368,8 @@ static int ext4_validate_block_bitmap(struct super_block *sb,
+ 		return -EFSCORRUPTED;
+ 
+ 	ext4_lock_group(sb, block_group);
++	if (buffer_verified(bh))
++		goto verified;
+ 	if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group,
+ 			desc, bh))) {
+ 		ext4_unlock_group(sb, block_group);
+@@ -386,6 +388,7 @@ static int ext4_validate_block_bitmap(struct super_block *sb,
+ 		return -EFSCORRUPTED;
+ 	}
+ 	set_buffer_verified(bh);
++verified:
+ 	ext4_unlock_group(sb, block_group);
+ 	return 0;
+ }
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index fb83750c1a14..e9d8e2667ab5 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -90,6 +90,8 @@ static int ext4_validate_inode_bitmap(struct super_block *sb,
+ 		return -EFSCORRUPTED;
+ 
+ 	ext4_lock_group(sb, block_group);
++	if (buffer_verified(bh))
++		goto verified;
+ 	blk = ext4_inode_bitmap(sb, desc);
+ 	if (!ext4_inode_bitmap_csum_verify(sb, block_group, desc, bh,
+ 					   EXT4_INODES_PER_GROUP(sb) / 8)) {
+@@ -101,6 +103,7 @@ static int ext4_validate_inode_bitmap(struct super_block *sb,
+ 		return -EFSBADCRC;
+ 	}
+ 	set_buffer_verified(bh);
++verified:
+ 	ext4_unlock_group(sb, block_group);
+ 	return 0;
+ }

commit 4929c9428a171145f82f81aae0c3c25ef7d82837
+Author: Deepti Raghavan 
+Date:   Mon Jul 9 17:53:39 2018 +0000
+
+    tcp: expose both send and receive intervals for rate sample
+    
+    Congestion control algorithms, which access the rate sample
+    through the tcp_cong_control function, only have access to the maximum
+    of the send and receive interval, for cases where the acknowledgment
+    rate may be inaccurate due to ACK compression or decimation. Algorithms
+    may want to use send rates and receive rates as separate signals.
+    
+    Signed-off-by: Deepti Raghavan 
+    Acked-by: Neal Cardwell 
+    Signed-off-by: Eric Dumazet 
+    Signed-off-by: David S. Miller 
+
+diff --git a/include/net/tcp.h b/include/net/tcp.h
+index cce37694776e..f6cb20e6e524 100644
+--- a/include/net/tcp.h
++++ b/include/net/tcp.h
+@@ -954,6 +954,8 @@ struct rate_sample {
+ 	u32  prior_delivered;	/* tp->delivered at "prior_mstamp" */
+ 	s32  delivered;		/* number of packets delivered over interval */
+ 	long interval_us;	/* time for tp->delivered to incr "delivered" */
++	u32 snd_interval_us;	/* snd interval for delivered packets */
++	u32 rcv_interval_us;	/* rcv interval for delivered packets */
+ 	long rtt_us;		/* RTT of last (S)ACKed packet (or -1) */
+ 	int  losses;		/* number of packets marked lost upon ACK */
+ 	u32  acked_sacked;	/* number of packets newly (S)ACKed upon ACK */
+diff --git a/net/ipv4/tcp_rate.c b/net/ipv4/tcp_rate.c
+index c61240e43923..4dff40dad4dc 100644
+--- a/net/ipv4/tcp_rate.c
++++ b/net/ipv4/tcp_rate.c
+@@ -146,6 +146,10 @@ void tcp_rate_gen(struct sock *sk, u32 delivered, u32 lost,
+ 				    rs->prior_mstamp); /* ack phase */
+ 	rs->interval_us = max(snd_us, ack_us);
+ 
++	/* Record both segment send and ack receive intervals */
++	rs->snd_interval_us = snd_us;
++	rs->rcv_interval_us = ack_us;
++
+ 	/* Normally we expect interval_us >= min-rtt.
+ 	 * Note that rate may still be over-estimated when a spuriously
+ 	 * retransmistted skb was first (s)acked because "interval_us"

commit 362eca70b53389bddf3143fe20f53dcce2cfdf61
+Author: Theodore Ts'o 
+Date:   Tue Jul 10 01:07:43 2018 -0400
+
+    ext4: fix inline data updates with checksums enabled
+    
+    The inline data code was updating the raw inode directly; this is
+    problematic since if metadata checksums are enabled,
+    ext4_mark_inode_dirty() must be called to update the inode's checksum.
+    In addition, the jbd2 layer requires that get_write_access() be called
+    before the metadata buffer is modified.  Fix both of these problems.
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=200443
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index e55a8bc870bd..3543fe80a3c4 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -682,6 +682,10 @@ int ext4_try_to_write_inline_data(struct address_space *mapping,
+ 		goto convert;
+ 	}
+ 
++	ret = ext4_journal_get_write_access(handle, iloc.bh);
++	if (ret)
++		goto out;
++
+ 	flags |= AOP_FLAG_NOFS;
+ 
+ 	page = grab_cache_page_write_begin(mapping, 0, flags);
+@@ -710,7 +714,7 @@ int ext4_try_to_write_inline_data(struct address_space *mapping,
+ out_up_read:
+ 	up_read(&EXT4_I(inode)->xattr_sem);
+ out:
+-	if (handle)
++	if (handle && (ret != 1))
+ 		ext4_journal_stop(handle);
+ 	brelse(iloc.bh);
+ 	return ret;
+@@ -752,6 +756,7 @@ int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,
+ 
+ 	ext4_write_unlock_xattr(inode, &no_expand);
+ 	brelse(iloc.bh);
++	mark_inode_dirty(inode);
+ out:
+ 	return copied;
+ }
+@@ -898,7 +903,6 @@ int ext4_da_write_inline_data_begin(struct address_space *mapping,
+ 		goto out;
+ 	}
+ 
+-
+ 	page = grab_cache_page_write_begin(mapping, 0, flags);
+ 	if (!page) {
+ 		ret = -ENOMEM;
+@@ -916,6 +920,9 @@ int ext4_da_write_inline_data_begin(struct address_space *mapping,
+ 		if (ret < 0)
+ 			goto out_release_page;
+ 	}
++	ret = ext4_journal_get_write_access(handle, iloc.bh);
++	if (ret)
++		goto out_release_page;
+ 
+ 	up_read(&EXT4_I(inode)->xattr_sem);
+ 	*pagep = page;
+@@ -936,7 +943,6 @@ int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos,
+ 				  unsigned len, unsigned copied,
+ 				  struct page *page)
+ {
+-	int i_size_changed = 0;
+ 	int ret;
+ 
+ 	ret = ext4_write_inline_data_end(inode, pos, len, copied, page);
+@@ -954,10 +960,8 @@ int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos,
+ 	 * But it's important to update i_size while still holding page lock:
+ 	 * page writeout could otherwise come in and zero beyond i_size.
+ 	 */
+-	if (pos+copied > inode->i_size) {
++	if (pos+copied > inode->i_size)
+ 		i_size_write(inode, pos+copied);
+-		i_size_changed = 1;
+-	}
+ 	unlock_page(page);
+ 	put_page(page);
+ 
+@@ -967,8 +971,7 @@ int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos,
+ 	 * ordering of page lock and transaction start for journaling
+ 	 * filesystems.
+ 	 */
+-	if (i_size_changed)
+-		mark_inode_dirty(inode);
++	mark_inode_dirty(inode);
+ 
+ 	return copied;
+ }
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 7d6c10017bdf..4efe77286ecd 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1389,9 +1389,10 @@ static int ext4_write_end(struct file *file,
+ 	loff_t old_size = inode->i_size;
+ 	int ret = 0, ret2;
+ 	int i_size_changed = 0;
++	int inline_data = ext4_has_inline_data(inode);
+ 
+ 	trace_ext4_write_end(inode, pos, len, copied);
+-	if (ext4_has_inline_data(inode)) {
++	if (inline_data) {
+ 		ret = ext4_write_inline_data_end(inode, pos, len,
+ 						 copied, page);
+ 		if (ret < 0) {
+@@ -1419,7 +1420,7 @@ static int ext4_write_end(struct file *file,
+ 	 * ordering of page lock and transaction start for journaling
+ 	 * filesystems.
+ 	 */
+-	if (i_size_changed)
++	if (i_size_changed || inline_data)
+ 		ext4_mark_inode_dirty(handle, inode);
+ 
+ 	if (pos + len > inode->i_size && ext4_can_truncate(inode))
+@@ -1493,6 +1494,7 @@ static int ext4_journalled_write_end(struct file *file,
+ 	int partial = 0;
+ 	unsigned from, to;
+ 	int size_changed = 0;
++	int inline_data = ext4_has_inline_data(inode);
+ 
+ 	trace_ext4_journalled_write_end(inode, pos, len, copied);
+ 	from = pos & (PAGE_SIZE - 1);
+@@ -1500,7 +1502,7 @@ static int ext4_journalled_write_end(struct file *file,
+ 
+ 	BUG_ON(!ext4_handle_valid(handle));
+ 
+-	if (ext4_has_inline_data(inode)) {
++	if (inline_data) {
+ 		ret = ext4_write_inline_data_end(inode, pos, len,
+ 						 copied, page);
+ 		if (ret < 0) {
+@@ -1531,7 +1533,7 @@ static int ext4_journalled_write_end(struct file *file,
+ 	if (old_size < pos)
+ 		pagecache_isize_extended(inode, old_size, pos);
+ 
+-	if (size_changed) {
++	if (size_changed || inline_data) {
+ 		ret2 = ext4_mark_inode_dirty(handle, inode);
+ 		if (!ret)
+ 			ret = ret2;
+@@ -2028,11 +2030,7 @@ static int __ext4_journalled_writepage(struct page *page,
+ 	}
+ 
+ 	if (inline_data) {
+-		BUFFER_TRACE(inode_bh, "get write access");
+-		ret = ext4_journal_get_write_access(handle, inode_bh);
+-
+-		err = ext4_handle_dirty_metadata(handle, inode, inode_bh);
+-
++		ret = ext4_mark_inode_dirty(handle, inode);
+ 	} else {
+ 		ret = ext4_walk_page_buffers(handle, page_bufs, 0, len, NULL,
+ 					     do_journal_get_write_access);

commit 2dca60d98e241bea686004168f85208f215fc697
+Author: Theodore Ts'o 
+Date:   Sun Jul 8 19:36:02 2018 -0400
+
+    ext4: clear mmp sequence number when remounting read-only
+    
+    Previously, when an MMP-protected file system is remounted read-only,
+    the kmmpd thread would exit the next time it woke up (a few seconds
+    later), without resetting the MMP sequence number back to
+    EXT4_MMP_SEQ_CLEAN.
+    
+    Fix this by explicitly killing the MMP thread when the file system is
+    remounted read-only.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: Andreas Dilger 
+
+diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c
+index 27b9a76a0dfa..638ad4743477 100644
+--- a/fs/ext4/mmp.c
++++ b/fs/ext4/mmp.c
+@@ -186,11 +186,8 @@ static int kmmpd(void *data)
+ 			goto exit_thread;
+ 		}
+ 
+-		if (sb_rdonly(sb)) {
+-			ext4_warning(sb, "kmmpd being stopped since filesystem "
+-				     "has been remounted as readonly.");
+-			goto exit_thread;
+-		}
++		if (sb_rdonly(sb))
++			break;
+ 
+ 		diff = jiffies - last_update_time;
+ 		if (diff < mmp_update_interval * HZ)
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index eff5c983e067..680526e9ee96 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -5212,6 +5212,8 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 
+ 			if (sbi->s_journal)
+ 				ext4_mark_recovery_complete(sb, es);
++			if (sbi->s_mmp_tsk)
++				kthread_stop(sbi->s_mmp_tsk);
+ 		} else {
+ 			/* Make sure we can mount this feature set readwrite */
+ 			if (ext4_has_feature_readonly(sb) ||

commit 44de022c4382541cebdd6de4465d1f4f465ff1dd
+Author: Theodore Ts'o 
+Date:   Sun Jul 8 19:35:02 2018 -0400
+
+    ext4: fix false negatives *and* false positives in ext4_check_descriptors()
+    
+    Ext4_check_descriptors() was getting called before s_gdb_count was
+    initialized.  So for file systems w/o the meta_bg feature, allocation
+    bitmaps could overlap the block group descriptors and ext4 wouldn't
+    notice.
+    
+    For file systems with the meta_bg feature enabled, there was a
+    fencepost error which would cause the ext4_check_descriptors() to
+    incorrectly believe that the block allocation bitmap overlaps with the
+    block group descriptor blocks, and it would reject the mount.
+    
+    Fix both of these problems.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index ba2396a7bd04..eff5c983e067 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2342,7 +2342,7 @@ static int ext4_check_descriptors(struct super_block *sb,
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	ext4_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block);
+ 	ext4_fsblk_t last_block;
+-	ext4_fsblk_t last_bg_block = sb_block + ext4_bg_num_gdb(sb, 0) + 1;
++	ext4_fsblk_t last_bg_block = sb_block + ext4_bg_num_gdb(sb, 0);
+ 	ext4_fsblk_t block_bitmap;
+ 	ext4_fsblk_t inode_bitmap;
+ 	ext4_fsblk_t inode_table;
+@@ -4085,14 +4085,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 			goto failed_mount2;
+ 		}
+ 	}
++	sbi->s_gdb_count = db_count;
+ 	if (!ext4_check_descriptors(sb, logical_sb_block, &first_not_zeroed)) {
+ 		ext4_msg(sb, KERN_ERR, "group descriptors corrupted!");
+ 		ret = -EFSCORRUPTED;
+ 		goto failed_mount2;
+ 	}
+ 
+-	sbi->s_gdb_count = db_count;
+-
+ 	timer_setup(&sbi->s_err_report, print_daily_error_info, 0);
+ 
+ 	/* Register extent status tree shrinker */

commit bfe0a5f47ada40d7984de67e59a7d3390b9b9ecc
+Author: Theodore Ts'o 
+Date:   Sun Jun 17 18:11:20 2018 -0400
+
+    ext4: add more mount time checks of the superblock
+    
+    The kernel's ext4 mount-time checks were more permissive than
+    e2fsprogs's libext2fs checks when opening a file system.  The
+    superblock is considered too insane for debugfs or e2fsck to operate
+    on it, the kernel has no business trying to mount it.
+    
+    This will make file system fuzzing tools work harder, but the failure
+    cases that they find will be more useful and be easier to evaluate.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 1f955c128e0d..b37b00befd65 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3793,6 +3793,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 			 le32_to_cpu(es->s_log_block_size));
+ 		goto failed_mount;
+ 	}
++	if (le32_to_cpu(es->s_log_cluster_size) >
++	    (EXT4_MAX_CLUSTER_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) {
++		ext4_msg(sb, KERN_ERR,
++			 "Invalid log cluster size: %u",
++			 le32_to_cpu(es->s_log_cluster_size));
++		goto failed_mount;
++	}
+ 
+ 	if (le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) > (blocksize / 4)) {
+ 		ext4_msg(sb, KERN_ERR,
+@@ -3939,13 +3946,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 				 "block size (%d)", clustersize, blocksize);
+ 			goto failed_mount;
+ 		}
+-		if (le32_to_cpu(es->s_log_cluster_size) >
+-		    (EXT4_MAX_CLUSTER_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) {
+-			ext4_msg(sb, KERN_ERR,
+-				 "Invalid log cluster size: %u",
+-				 le32_to_cpu(es->s_log_cluster_size));
+-			goto failed_mount;
+-		}
+ 		sbi->s_cluster_bits = le32_to_cpu(es->s_log_cluster_size) -
+ 			le32_to_cpu(es->s_log_block_size);
+ 		sbi->s_clusters_per_group =
+@@ -3966,10 +3966,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		}
+ 	} else {
+ 		if (clustersize != blocksize) {
+-			ext4_warning(sb, "fragment/cluster size (%d) != "
+-				     "block size (%d)", clustersize,
+-				     blocksize);
+-			clustersize = blocksize;
++			ext4_msg(sb, KERN_ERR,
++				 "fragment/cluster size (%d) != "
++				 "block size (%d)", clustersize, blocksize);
++			goto failed_mount;
+ 		}
+ 		if (sbi->s_blocks_per_group > blocksize * 8) {
+ 			ext4_msg(sb, KERN_ERR,
+@@ -4023,6 +4023,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 			 ext4_blocks_count(es));
+ 		goto failed_mount;
+ 	}
++	if ((es->s_first_data_block == 0) && (es->s_log_block_size == 0) &&
++	    (sbi->s_cluster_ratio == 1)) {
++		ext4_msg(sb, KERN_WARNING, "bad geometry: first data "
++			 "block is 0 with a 1k block and cluster size");
++		goto failed_mount;
++	}
++
+ 	blocks_count = (ext4_blocks_count(es) -
+ 			le32_to_cpu(es->s_first_data_block) +
+ 			EXT4_BLOCKS_PER_GROUP(sb) - 1);
+@@ -4058,6 +4065,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		ret = -ENOMEM;
+ 		goto failed_mount;
+ 	}
++	if (((u64)sbi->s_groups_count * sbi->s_inodes_per_group) !=
++	    le32_to_cpu(es->s_inodes_count)) {
++		ext4_msg(sb, KERN_ERR, "inodes count not valid: %u vs %llu",
++			 le32_to_cpu(es->s_inodes_count),
++			 ((u64)sbi->s_groups_count * sbi->s_inodes_per_group));
++		ret = -EINVAL;
++		goto failed_mount;
++	}
+ 
+ 	bgl_lock_init(sbi->s_blockgroup_lock);
+ 

commit c37e9e013469521d9adb932d17a1795c139b36db
+Author: Theodore Ts'o 
+Date:   Sun Jun 17 00:41:14 2018 -0400
+
+    ext4: add more inode number paranoia checks
+    
+    If there is a directory entry pointing to a system inode (such as a
+    journal inode), complain and declare the file system to be corrupted.
+    
+    Also, if the superblock's first inode number field is too small,
+    refuse to mount the file system.
+    
+    This addresses CVE-2018-10882.
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=200069
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 859d6433dcc1..4bd69649a048 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1502,11 +1502,6 @@ static inline struct ext4_inode_info *EXT4_I(struct inode *inode)
+ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
+ {
+ 	return ino == EXT4_ROOT_INO ||
+-		ino == EXT4_USR_QUOTA_INO ||
+-		ino == EXT4_GRP_QUOTA_INO ||
+-		ino == EXT4_BOOT_LOADER_INO ||
+-		ino == EXT4_JOURNAL_INO ||
+-		ino == EXT4_RESIZE_INO ||
+ 		(ino >= EXT4_FIRST_INO(sb) &&
+ 		 ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count));
+ }
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index c2f4ccb880c4..7d6c10017bdf 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4506,7 +4506,8 @@ static int __ext4_get_inode_loc(struct inode *inode,
+ 	int			inodes_per_block, inode_offset;
+ 
+ 	iloc->bh = NULL;
+-	if (!ext4_valid_inum(sb, inode->i_ino))
++	if (inode->i_ino < EXT4_ROOT_INO ||
++	    inode->i_ino > le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count))
+ 		return -EFSCORRUPTED;
+ 
+ 	iloc->block_group = (inode->i_ino - 1) / EXT4_INODES_PER_GROUP(sb);
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 4d34430d75f6..1f955c128e0d 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3858,6 +3858,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	} else {
+ 		sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
+ 		sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
++		if (sbi->s_first_ino < EXT4_GOOD_OLD_FIRST_INO) {
++			ext4_msg(sb, KERN_ERR, "invalid first ino: %u",
++				 sbi->s_first_ino);
++			goto failed_mount;
++		}
+ 		if ((sbi->s_inode_size < EXT4_GOOD_OLD_INODE_SIZE) ||
+ 		    (!is_power_of_2(sbi->s_inode_size)) ||
+ 		    (sbi->s_inode_size > blocksize)) {

commit 8bc1379b82b8e809eef77a9fedbb75c6c297be19
+Author: Theodore Ts'o 
+Date:   Sat Jun 16 23:41:59 2018 -0400
+
+    ext4: avoid running out of journal credits when appending to an inline file
+    
+    Use a separate journal transaction if it turns out that we need to
+    convert an inline file to use an data block.  Otherwise we could end
+    up failing due to not having journal credits.
+    
+    This addresses CVE-2018-10883.
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=200071
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 856b6a54d82b..859d6433dcc1 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -3013,9 +3013,6 @@ extern int ext4_inline_data_fiemap(struct inode *inode,
+ struct iomap;
+ extern int ext4_inline_data_iomap(struct inode *inode, struct iomap *iomap);
+ 
+-extern int ext4_try_to_evict_inline_data(handle_t *handle,
+-					 struct inode *inode,
+-					 int needed);
+ extern int ext4_inline_data_truncate(struct inode *inode, int *has_inline);
+ 
+ extern int ext4_convert_inline_data(struct inode *inode);
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index d79115d8d716..851bc552d849 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -887,11 +887,11 @@ int ext4_da_write_inline_data_begin(struct address_space *mapping,
+ 	flags |= AOP_FLAG_NOFS;
+ 
+ 	if (ret == -ENOSPC) {
++		ext4_journal_stop(handle);
+ 		ret = ext4_da_convert_inline_data_to_extent(mapping,
+ 							    inode,
+ 							    flags,
+ 							    fsdata);
+-		ext4_journal_stop(handle);
+ 		if (ret == -ENOSPC &&
+ 		    ext4_should_retry_alloc(inode->i_sb, &retries))
+ 			goto retry_journal;
+@@ -1891,42 +1891,6 @@ int ext4_inline_data_fiemap(struct inode *inode,
+ 	return (error < 0 ? error : 0);
+ }
+ 
+-/*
+- * Called during xattr set, and if we can sparse space 'needed',
+- * just create the extent tree evict the data to the outer block.
+- *
+- * We use jbd2 instead of page cache to move data to the 1st block
+- * so that the whole transaction can be committed as a whole and
+- * the data isn't lost because of the delayed page cache write.
+- */
+-int ext4_try_to_evict_inline_data(handle_t *handle,
+-				  struct inode *inode,
+-				  int needed)
+-{
+-	int error;
+-	struct ext4_xattr_entry *entry;
+-	struct ext4_inode *raw_inode;
+-	struct ext4_iloc iloc;
+-
+-	error = ext4_get_inode_loc(inode, &iloc);
+-	if (error)
+-		return error;
+-
+-	raw_inode = ext4_raw_inode(&iloc);
+-	entry = (struct ext4_xattr_entry *)((void *)raw_inode +
+-					    EXT4_I(inode)->i_inline_off);
+-	if (EXT4_XATTR_LEN(entry->e_name_len) +
+-	    EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size)) < needed) {
+-		error = -ENOSPC;
+-		goto out;
+-	}
+-
+-	error = ext4_convert_inline_data_nolock(handle, inode, &iloc);
+-out:
+-	brelse(iloc.bh);
+-	return error;
+-}
+-
+ int ext4_inline_data_truncate(struct inode *inode, int *has_inline)
+ {
+ 	handle_t *handle;
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 72377b77fbd7..723df14f4084 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -2212,23 +2212,8 @@ int ext4_xattr_ibody_inline_set(handle_t *handle, struct inode *inode,
+ 	if (EXT4_I(inode)->i_extra_isize == 0)
+ 		return -ENOSPC;
+ 	error = ext4_xattr_set_entry(i, s, handle, inode, false /* is_block */);
+-	if (error) {
+-		if (error == -ENOSPC &&
+-		    ext4_has_inline_data(inode)) {
+-			error = ext4_try_to_evict_inline_data(handle, inode,
+-					EXT4_XATTR_LEN(strlen(i->name) +
+-					EXT4_XATTR_SIZE(i->value_len)));
+-			if (error)
+-				return error;
+-			error = ext4_xattr_ibody_find(inode, i, is);
+-			if (error)
+-				return error;
+-			error = ext4_xattr_set_entry(i, s, handle, inode,
+-						     false /* is_block */);
+-		}
+-		if (error)
+-			return error;
+-	}
++	if (error)
++		return error;
+ 	header = IHDR(inode, ext4_raw_inode(&is->iloc));
+ 	if (!IS_LAST_ENTRY(s->first)) {
+ 		header->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC);

commit e09463f220ca9a1a1ecfda84fcda658f99a1f12a
+Author: Theodore Ts'o 
+Date:   Sat Jun 16 20:21:45 2018 -0400
+
+    jbd2: don't mark block as modified if the handle is out of credits
+    
+    Do not set the b_modified flag in block's journal head should not
+    until after we're sure that jbd2_journal_dirty_metadat() will not
+    abort with an error due to there not being enough space reserved in
+    the jbd2 handle.
+    
+    Otherwise, future attempts to modify the buffer may lead a large
+    number of spurious errors and warnings.
+    
+    This addresses CVE-2018-10883.
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=200071
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index 51dd68e67b0f..c0b66a7a795b 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -1361,6 +1361,13 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
+ 		if (jh->b_transaction == transaction &&
+ 		    jh->b_jlist != BJ_Metadata) {
+ 			jbd_lock_bh_state(bh);
++			if (jh->b_transaction == transaction &&
++			    jh->b_jlist != BJ_Metadata)
++				pr_err("JBD2: assertion failure: h_type=%u "
++				       "h_line_no=%u block_no=%llu jlist=%u\n",
++				       handle->h_type, handle->h_line_no,
++				       (unsigned long long) bh->b_blocknr,
++				       jh->b_jlist);
+ 			J_ASSERT_JH(jh, jh->b_transaction != transaction ||
+ 					jh->b_jlist == BJ_Metadata);
+ 			jbd_unlock_bh_state(bh);
+@@ -1380,11 +1387,11 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
+ 		 * of the transaction. This needs to be done
+ 		 * once a transaction -bzzz
+ 		 */
+-		jh->b_modified = 1;
+ 		if (handle->h_buffer_credits <= 0) {
+ 			ret = -ENOSPC;
+ 			goto out_unlock_bh;
+ 		}
++		jh->b_modified = 1;
+ 		handle->h_buffer_credits--;
+ 	}
+ 

commit 8cdb5240ec5928b20490a2bb34cb87e9a5f40226
+Author: Theodore Ts'o 
+Date:   Sat Jun 16 15:40:48 2018 -0400
+
+    ext4: never move the system.data xattr out of the inode body
+    
+    When expanding the extra isize space, we must never move the
+    system.data xattr out of the inode body.  For performance reasons, it
+    doesn't make any sense, and the inline data implementation assumes
+    that system.data xattr is never in the external xattr block.
+    
+    This addresses CVE-2018-10880
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=200005
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 0263692979ec..72377b77fbd7 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -2657,6 +2657,11 @@ static int ext4_xattr_make_inode_space(handle_t *handle, struct inode *inode,
+ 		last = IFIRST(header);
+ 		/* Find the entry best suited to be pushed into EA block */
+ 		for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) {
++			/* never move system.data out of the inode */
++			if ((last->e_name_len == 4) &&
++			    (last->e_name_index == EXT4_XATTR_INDEX_SYSTEM) &&
++			    !memcmp(last->e_name, "data", 4))
++				continue;
+ 			total_size = EXT4_XATTR_LEN(last->e_name_len);
+ 			if (!last->e_value_inum)
+ 				total_size += EXT4_XATTR_SIZE(

commit 6e8ab72a812396996035a37e5ca4b3b99b5d214b
+Author: Theodore Ts'o 
+Date:   Fri Jun 15 12:28:16 2018 -0400
+
+    ext4: clear i_data in ext4_inode_info when removing inline data
+    
+    When converting from an inode from storing the data in-line to a data
+    block, ext4_destroy_inline_data_nolock() was only clearing the on-disk
+    copy of the i_blocks[] array.  It was not clearing copy of the
+    i_blocks[] in ext4_inode_info, in i_data[], which is the copy actually
+    used by ext4_map_blocks().
+    
+    This didn't matter much if we are using extents, since the extents
+    header would be invalid and thus the extents could would re-initialize
+    the extents tree.  But if we are using indirect blocks, the previous
+    contents of the i_blocks array will be treated as block numbers, with
+    potentially catastrophic results to the file system integrity and/or
+    user data.
+    
+    This gets worse if the file system is using a 1k block size and
+    s_first_data is zero, but even without this, the file system can get
+    quite badly corrupted.
+    
+    This addresses CVE-2018-10881.
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=200015
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index 44b4fcdc3755..d79115d8d716 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -437,6 +437,7 @@ static int ext4_destroy_inline_data_nolock(handle_t *handle,
+ 
+ 	memset((void *)ext4_raw_inode(&is.iloc)->i_block,
+ 		0, EXT4_MIN_INLINE_DATA_SIZE);
++	memset(ei->i_data, 0, EXT4_MIN_INLINE_DATA_SIZE);
+ 
+ 	if (ext4_has_feature_extents(inode->i_sb)) {
+ 		if (S_ISDIR(inode->i_mode) ||

commit bdbd6ce01a70f02e9373a584d0ae9538dcf0a121
+Author: Theodore Ts'o 
+Date:   Fri Jun 15 12:27:16 2018 -0400
+
+    ext4: include the illegal physical block in the bad map ext4_error msg
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 2ea07efbe016..c2f4ccb880c4 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -402,9 +402,9 @@ static int __check_block_validity(struct inode *inode, const char *func,
+ 	if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), map->m_pblk,
+ 				   map->m_len)) {
+ 		ext4_error_inode(inode, func, line, map->m_pblk,
+-				 "lblock %lu mapped to illegal pblock "
++				 "lblock %lu mapped to illegal pblock %llu "
+ 				 "(length %d)", (unsigned long) map->m_lblk,
+-				 map->m_len);
++				 map->m_pblk, map->m_len);
+ 		return -EFSCORRUPTED;
+ 	}
+ 	return 0;

commit bc890a60247171294acc0bd67d211fa4b88d40ba
+Author: Theodore Ts'o 
+Date:   Thu Jun 14 12:55:10 2018 -0400
+
+    ext4: verify the depth of extent tree in ext4_find_extent()
+    
+    If there is a corupted file system where the claimed depth of the
+    extent tree is -1, this can cause a massive buffer overrun leading to
+    sadness.
+    
+    This addresses CVE-2018-10877.
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=199417
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h
+index 98fb0c119c68..adf6668b596f 100644
+--- a/fs/ext4/ext4_extents.h
++++ b/fs/ext4/ext4_extents.h
+@@ -91,6 +91,7 @@ struct ext4_extent_header {
+ };
+ 
+ #define EXT4_EXT_MAGIC		cpu_to_le16(0xf30a)
++#define EXT4_MAX_EXTENT_DEPTH 5
+ 
+ #define EXT4_EXTENT_TAIL_OFFSET(hdr) \
+ 	(sizeof(struct ext4_extent_header) + \
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index c969275ce3ee..08226f72b7ee 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -869,6 +869,12 @@ ext4_find_extent(struct inode *inode, ext4_lblk_t block,
+ 
+ 	eh = ext_inode_hdr(inode);
+ 	depth = ext_depth(inode);
++	if (depth < 0 || depth > EXT4_MAX_EXTENT_DEPTH) {
++		EXT4_ERROR_INODE(inode, "inode has invalid extent depth: %d",
++				 depth);
++		ret = -EFSCORRUPTED;
++		goto err;
++	}
+ 
+ 	if (path) {
+ 		ext4_ext_drop_refs(path);

commit 8844618d8aa7a9973e7b527d038a2a589665002c
+Author: Theodore Ts'o 
+Date:   Thu Jun 14 00:58:00 2018 -0400
+
+    ext4: only look at the bg_flags field if it is valid
+    
+    The bg_flags field in the block group descripts is only valid if the
+    uninit_bg or metadata_csum feature is enabled.  We were not
+    consistently looking at this field; fix this.
+    
+    Also block group #0 must never have uninitialized allocation bitmaps,
+    or need to be zeroed, since that's where the root inode, and other
+    special inodes are set up.  Check for these conditions and mark the
+    file system as corrupted if they are detected.
+    
+    This addresses CVE-2018-10876.
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=199403
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 8a2e202ade8a..e68cefe08261 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -438,7 +438,16 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group)
+ 		goto verify;
+ 	}
+ 	ext4_lock_group(sb, block_group);
+-	if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
++	if (ext4_has_group_desc_csum(sb) &&
++	    (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) {
++		if (block_group == 0) {
++			ext4_unlock_group(sb, block_group);
++			unlock_buffer(bh);
++			ext4_error(sb, "Block bitmap for bg 0 marked "
++				   "uninitialized");
++			err = -EFSCORRUPTED;
++			goto out;
++		}
+ 		err = ext4_init_block_bitmap(sb, bh, block_group, desc);
+ 		set_bitmap_uptodate(bh);
+ 		set_buffer_uptodate(bh);
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 4d6e007f3569..da6c10c1e37a 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -150,7 +150,16 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
+ 	}
+ 
+ 	ext4_lock_group(sb, block_group);
+-	if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) {
++	if (ext4_has_group_desc_csum(sb) &&
++	    (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT))) {
++		if (block_group == 0) {
++			ext4_unlock_group(sb, block_group);
++			unlock_buffer(bh);
++			ext4_error(sb, "Inode bitmap for bg 0 marked "
++				   "uninitialized");
++			err = -EFSCORRUPTED;
++			goto out;
++		}
+ 		memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8);
+ 		ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb),
+ 				     sb->s_blocksize * 8, bh->b_data);
+@@ -994,7 +1003,8 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
+ 
+ 		/* recheck and clear flag under lock if we still need to */
+ 		ext4_lock_group(sb, group);
+-		if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
++		if (ext4_has_group_desc_csum(sb) &&
++		    (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) {
+ 			gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
+ 			ext4_free_group_clusters_set(sb, gdp,
+ 				ext4_free_clusters_after_init(sb, group, gdp));
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 243c42fdc155..402c769c51ea 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2444,7 +2444,8 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group,
+ 	 * initialize bb_free to be able to skip
+ 	 * empty groups without initialization
+ 	 */
+-	if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
++	if (ext4_has_group_desc_csum(sb) &&
++	    (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) {
+ 		meta_group_info[i]->bb_free =
+ 			ext4_free_clusters_after_init(sb, group, desc);
+ 	} else {
+@@ -3010,7 +3011,8 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
+ #endif
+ 	ext4_set_bits(bitmap_bh->b_data, ac->ac_b_ex.fe_start,
+ 		      ac->ac_b_ex.fe_len);
+-	if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
++	if (ext4_has_group_desc_csum(sb) &&
++	    (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) {
+ 		gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
+ 		ext4_free_group_clusters_set(sb, gdp,
+ 					     ext4_free_clusters_after_init(sb,
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index c61675d62195..4d34430d75f6 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3139,13 +3139,22 @@ static ext4_group_t ext4_has_uninit_itable(struct super_block *sb)
+ 	ext4_group_t group, ngroups = EXT4_SB(sb)->s_groups_count;
+ 	struct ext4_group_desc *gdp = NULL;
+ 
++	if (!ext4_has_group_desc_csum(sb))
++		return ngroups;
++
+ 	for (group = 0; group < ngroups; group++) {
+ 		gdp = ext4_get_group_desc(sb, group, NULL);
+ 		if (!gdp)
+ 			continue;
+ 
+-		if (!(gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED)))
++		if (gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED))
++			continue;
++		if (group != 0)
+ 			break;
++		ext4_error(sb, "Inode table for bg 0 marked as "
++			   "needing zeroing");
++		if (sb_rdonly(sb))
++			return ngroups;
+ 	}
+ 
+ 	return group;

commit 77260807d1170a8cf35dbb06e07461a655f67eee
+Author: Theodore Ts'o 
+Date:   Wed Jun 13 23:08:26 2018 -0400
+
+    ext4: make sure bitmaps and the inode table don't overlap with bg descriptors
+    
+    It's really bad when the allocation bitmaps and the inode table
+    overlap with the block group descriptors, since it causes random
+    corruption of the bg descriptors.  So we really want to head those off
+    at the pass.
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=199865
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index c8b7b8302e90..c61675d62195 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2348,6 +2348,7 @@ static int ext4_check_descriptors(struct super_block *sb,
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	ext4_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block);
+ 	ext4_fsblk_t last_block;
++	ext4_fsblk_t last_bg_block = sb_block + ext4_bg_num_gdb(sb, 0) + 1;
+ 	ext4_fsblk_t block_bitmap;
+ 	ext4_fsblk_t inode_bitmap;
+ 	ext4_fsblk_t inode_table;
+@@ -2380,6 +2381,14 @@ static int ext4_check_descriptors(struct super_block *sb,
+ 			if (!sb_rdonly(sb))
+ 				return 0;
+ 		}
++		if (block_bitmap >= sb_block + 1 &&
++		    block_bitmap <= last_bg_block) {
++			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
++				 "Block bitmap for group %u overlaps "
++				 "block group descriptors", i);
++			if (!sb_rdonly(sb))
++				return 0;
++		}
+ 		if (block_bitmap < first_block || block_bitmap > last_block) {
+ 			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
+ 			       "Block bitmap for group %u not in group "
+@@ -2394,6 +2403,14 @@ static int ext4_check_descriptors(struct super_block *sb,
+ 			if (!sb_rdonly(sb))
+ 				return 0;
+ 		}
++		if (inode_bitmap >= sb_block + 1 &&
++		    inode_bitmap <= last_bg_block) {
++			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
++				 "Inode bitmap for group %u overlaps "
++				 "block group descriptors", i);
++			if (!sb_rdonly(sb))
++				return 0;
++		}
+ 		if (inode_bitmap < first_block || inode_bitmap > last_block) {
+ 			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
+ 			       "Inode bitmap for group %u not in group "
+@@ -2408,6 +2425,14 @@ static int ext4_check_descriptors(struct super_block *sb,
+ 			if (!sb_rdonly(sb))
+ 				return 0;
+ 		}
++		if (inode_table >= sb_block + 1 &&
++		    inode_table <= last_bg_block) {
++			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
++				 "Inode table for group %u overlaps "
++				 "block group descriptors", i);
++			if (!sb_rdonly(sb))
++				return 0;
++		}
+ 		if (inode_table < first_block ||
+ 		    inode_table + sbi->s_itb_per_group - 1 > last_block) {
+ 			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "

commit 819b23f1c501b17b9694325471789e6b5cc2d0d2
+Author: Theodore Ts'o 
+Date:   Wed Jun 13 23:00:48 2018 -0400
+
+    ext4: always check block group bounds in ext4_init_block_bitmap()
+    
+    Regardless of whether the flex_bg feature is set, we should always
+    check to make sure the bits we are setting in the block bitmap are
+    within the block group bounds.
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=199865
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index b00481c475cb..8a2e202ade8a 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -184,7 +184,6 @@ static int ext4_init_block_bitmap(struct super_block *sb,
+ 	unsigned int bit, bit_max;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	ext4_fsblk_t start, tmp;
+-	int flex_bg = 0;
+ 
+ 	J_ASSERT_BH(bh, buffer_locked(bh));
+ 
+@@ -207,22 +206,19 @@ static int ext4_init_block_bitmap(struct super_block *sb,
+ 
+ 	start = ext4_group_first_block_no(sb, block_group);
+ 
+-	if (ext4_has_feature_flex_bg(sb))
+-		flex_bg = 1;
+-
+ 	/* Set bits for block and inode bitmaps, and inode table */
+ 	tmp = ext4_block_bitmap(sb, gdp);
+-	if (!flex_bg || ext4_block_in_group(sb, tmp, block_group))
++	if (ext4_block_in_group(sb, tmp, block_group))
+ 		ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data);
+ 
+ 	tmp = ext4_inode_bitmap(sb, gdp);
+-	if (!flex_bg || ext4_block_in_group(sb, tmp, block_group))
++	if (ext4_block_in_group(sb, tmp, block_group))
+ 		ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data);
+ 
+ 	tmp = ext4_inode_table(sb, gdp);
+ 	for (; tmp < ext4_inode_table(sb, gdp) +
+ 		     sbi->s_itb_per_group; tmp++) {
+-		if (!flex_bg || ext4_block_in_group(sb, tmp, block_group))
++		if (ext4_block_in_group(sb, tmp, block_group))
+ 			ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data);
+ 	}
+ 

commit 513f86d73855ce556ea9522b6bfd79f87356dc3a
+Author: Theodore Ts'o 
+Date:   Wed Jun 13 00:51:28 2018 -0400
+
+    ext4: always verify the magic number in xattr blocks
+    
+    If there an inode points to a block which is also some other type of
+    metadata block (such as a block allocation bitmap), the
+    buffer_verified flag can be set when it was validated as that other
+    metadata block type; however, it would make a really terrible external
+    attribute block.  The reason why we use the verified flag is to avoid
+    constantly reverifying the block.  However, it doesn't take much
+    overhead to make sure the magic number of the xattr block is correct,
+    and this will avoid potential crashes.
+    
+    This addresses CVE-2018-10879.
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=200001
+    
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Andreas Dilger 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 230ba79715f6..0263692979ec 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -230,12 +230,12 @@ __ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh,
+ {
+ 	int error = -EFSCORRUPTED;
+ 
+-	if (buffer_verified(bh))
+-		return 0;
+-
+ 	if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) ||
+ 	    BHDR(bh)->h_blocks != cpu_to_le32(1))
+ 		goto errout;
++	if (buffer_verified(bh))
++		return 0;
++
+ 	error = -EFSBADCRC;
+ 	if (!ext4_xattr_block_csum_verify(inode, bh))
+ 		goto errout;

commit 5369a762c882c0b6e9599e4ebbb3a9ba9eee7e2d
+Author: Theodore Ts'o 
+Date:   Wed Jun 13 00:23:11 2018 -0400
+
+    ext4: add corruption check in ext4_xattr_set_entry()
+    
+    In theory this should have been caught earlier when the xattr list was
+    verified, but in case it got missed, it's simple enough to add check
+    to make sure we don't overrun the xattr buffer.
+    
+    This addresses CVE-2018-10879.
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=200001
+    
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Andreas Dilger 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index fc4ced59c565..230ba79715f6 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -1560,7 +1560,7 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i,
+ 				handle_t *handle, struct inode *inode,
+ 				bool is_block)
+ {
+-	struct ext4_xattr_entry *last;
++	struct ext4_xattr_entry *last, *next;
+ 	struct ext4_xattr_entry *here = s->here;
+ 	size_t min_offs = s->end - s->base, name_len = strlen(i->name);
+ 	int in_inode = i->in_inode;
+@@ -1595,7 +1595,13 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i,
+ 
+ 	/* Compute min_offs and last. */
+ 	last = s->first;
+-	for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) {
++	for (; !IS_LAST_ENTRY(last); last = next) {
++		next = EXT4_XATTR_NEXT(last);
++		if ((void *)next >= s->end) {
++			EXT4_ERROR_INODE(inode, "corrupted xattr entries");
++			ret = -EFSCORRUPTED;
++			goto out;
++		}
+ 		if (!last->e_value_inum && last->e_value_size) {
+ 			size_t offs = le16_to_cpu(last->e_value_offs);
+ 			if (offs < min_offs)

commit 327eaf738ff97d19491362e30497954105d60414
+Author: Theodore Ts'o 
+Date:   Tue Jun 12 23:34:57 2018 -0400
+
+    ext4: add warn_on_error mount option
+    
+    This is very handy when debugging bugs handling maliciously corrupted
+    file systems.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index fa52b7dd4542..856b6a54d82b 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1108,6 +1108,7 @@ struct ext4_inode_info {
+ #define EXT4_MOUNT_DIOREAD_NOLOCK	0x400000 /* Enable support for dio read nolocking */
+ #define EXT4_MOUNT_JOURNAL_CHECKSUM	0x800000 /* Journal checksums */
+ #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT	0x1000000 /* Journal Async Commit */
++#define EXT4_MOUNT_WARN_ON_ERROR	0x2000000 /* Trigger WARN_ON on error */
+ #define EXT4_MOUNT_DELALLOC		0x8000000 /* Delalloc support */
+ #define EXT4_MOUNT_DATA_ERR_ABORT	0x10000000 /* Abort on file data write */
+ #define EXT4_MOUNT_BLOCK_VALIDITY	0x20000000 /* Block validity checking */
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index c1c5c8775ae7..c8b7b8302e90 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -405,6 +405,9 @@ static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn)
+ 
+ static void ext4_handle_error(struct super_block *sb)
+ {
++	if (test_opt(sb, WARN_ON_ERROR))
++		WARN_ON_ONCE(1);
++
+ 	if (sb_rdonly(sb))
+ 		return;
+ 
+@@ -740,6 +743,9 @@ __acquires(bitlock)
+ 		va_end(args);
+ 	}
+ 
++	if (test_opt(sb, WARN_ON_ERROR))
++		WARN_ON_ONCE(1);
++
+ 	if (test_opt(sb, ERRORS_CONT)) {
+ 		ext4_commit_super(sb, 0);
+ 		return;
+@@ -1377,7 +1383,8 @@ enum {
+ 	Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota,
+ 	Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err,
+ 	Opt_usrquota, Opt_grpquota, Opt_prjquota, Opt_i_version, Opt_dax,
+-	Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_mblk_io_submit,
++	Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_warn_on_error,
++	Opt_nowarn_on_error, Opt_mblk_io_submit,
+ 	Opt_lazytime, Opt_nolazytime, Opt_debug_want_extra_isize,
+ 	Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity,
+ 	Opt_inode_readahead_blks, Opt_journal_ioprio,
+@@ -1444,6 +1451,8 @@ static const match_table_t tokens = {
+ 	{Opt_dax, "dax"},
+ 	{Opt_stripe, "stripe=%u"},
+ 	{Opt_delalloc, "delalloc"},
++	{Opt_warn_on_error, "warn_on_error"},
++	{Opt_nowarn_on_error, "nowarn_on_error"},
+ 	{Opt_lazytime, "lazytime"},
+ 	{Opt_nolazytime, "nolazytime"},
+ 	{Opt_debug_want_extra_isize, "debug_want_extra_isize=%u"},
+@@ -1608,6 +1617,8 @@ static const struct mount_opts {
+ 	 MOPT_EXT4_ONLY | MOPT_SET | MOPT_EXPLICIT},
+ 	{Opt_nodelalloc, EXT4_MOUNT_DELALLOC,
+ 	 MOPT_EXT4_ONLY | MOPT_CLEAR},
++	{Opt_warn_on_error, EXT4_MOUNT_WARN_ON_ERROR, MOPT_SET},
++	{Opt_nowarn_on_error, EXT4_MOUNT_WARN_ON_ERROR, MOPT_CLEAR},
+ 	{Opt_nojournal_checksum, EXT4_MOUNT_JOURNAL_CHECKSUM,
+ 	 MOPT_EXT4_ONLY | MOPT_CLEAR},
+ 	{Opt_journal_checksum, EXT4_MOUNT_JOURNAL_CHECKSUM,

commit d2ac838e4cd7e5e9891ecc094d626734b0245c99
+Author: Theodore Ts'o 
+Date:   Mon May 7 11:37:58 2018 -0400
+
+    loop: add recursion validation to LOOP_CHANGE_FD
+    
+    Refactor the validation code used in LOOP_SET_FD so it is also used in
+    LOOP_CHANGE_FD.  Otherwise it is possible to construct a set of loop
+    devices that all refer to each other.  This can lead to a infinite
+    loop in starting with "while (is_loop_device(f)) .." in loop_set_fd().
+    
+    Fix this by refactoring out the validation code and using it for
+    LOOP_CHANGE_FD as well as LOOP_SET_FD.
+    
+    Reported-by: syzbot+4349872271ece473a7c91190b68b4bac7c5dbc87@syzkaller.appspotmail.com
+    Reported-by: syzbot+40bd32c4d9a3cc12a339@syzkaller.appspotmail.com
+    Reported-by: syzbot+769c54e66f994b041be7@syzkaller.appspotmail.com
+    Reported-by: syzbot+0a89a9ce473936c57065@syzkaller.appspotmail.com
+    Signed-off-by: Theodore Ts'o 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/drivers/block/loop.c b/drivers/block/loop.c
+index 4838b0dbaad3..f8f3ca6e77fd 100644
+--- a/drivers/block/loop.c
++++ b/drivers/block/loop.c
+@@ -644,6 +644,36 @@ static void loop_reread_partitions(struct loop_device *lo,
+ 			__func__, lo->lo_number, lo->lo_file_name, rc);
+ }
+ 
++static inline int is_loop_device(struct file *file)
++{
++	struct inode *i = file->f_mapping->host;
++
++	return i && S_ISBLK(i->i_mode) && MAJOR(i->i_rdev) == LOOP_MAJOR;
++}
++
++static int loop_validate_file(struct file *file, struct block_device *bdev)
++{
++	struct inode	*inode = file->f_mapping->host;
++	struct file	*f = file;
++
++	/* Avoid recursion */
++	while (is_loop_device(f)) {
++		struct loop_device *l;
++
++		if (f->f_mapping->host->i_bdev == bdev)
++			return -EBADF;
++
++		l = f->f_mapping->host->i_bdev->bd_disk->private_data;
++		if (l->lo_state == Lo_unbound) {
++			return -EINVAL;
++		}
++		f = l->lo_backing_file;
++	}
++	if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))
++		return -EINVAL;
++	return 0;
++}
++
+ /*
+  * loop_change_fd switched the backing store of a loopback device to
+  * a new file. This is useful for operating system installers to free up
+@@ -673,14 +703,15 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
+ 	if (!file)
+ 		goto out;
+ 
++	error = loop_validate_file(file, bdev);
++	if (error)
++		goto out_putf;
++
+ 	inode = file->f_mapping->host;
+ 	old_file = lo->lo_backing_file;
+ 
+ 	error = -EINVAL;
+ 
+-	if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))
+-		goto out_putf;
+-
+ 	/* size of the new backing store needs to be the same */
+ 	if (get_loop_size(lo, file) != get_loop_size(lo, old_file))
+ 		goto out_putf;
+@@ -706,13 +737,6 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
+ 	return error;
+ }
+ 
+-static inline int is_loop_device(struct file *file)
+-{
+-	struct inode *i = file->f_mapping->host;
+-
+-	return i && S_ISBLK(i->i_mode) && MAJOR(i->i_rdev) == LOOP_MAJOR;
+-}
+-
+ /* loop sysfs attributes */
+ 
+ static ssize_t loop_attr_show(struct device *dev, char *page,
+@@ -878,7 +902,7 @@ static int loop_prepare_queue(struct loop_device *lo)
+ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
+ 		       struct block_device *bdev, unsigned int arg)
+ {
+-	struct file	*file, *f;
++	struct file	*file;
+ 	struct inode	*inode;
+ 	struct address_space *mapping;
+ 	int		lo_flags = 0;
+@@ -897,29 +921,13 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
+ 	if (lo->lo_state != Lo_unbound)
+ 		goto out_putf;
+ 
+-	/* Avoid recursion */
+-	f = file;
+-	while (is_loop_device(f)) {
+-		struct loop_device *l;
+-
+-		if (f->f_mapping->host->i_bdev == bdev)
+-			goto out_putf;
+-
+-		l = f->f_mapping->host->i_bdev->bd_disk->private_data;
+-		if (l->lo_state == Lo_unbound) {
+-			error = -EINVAL;
+-			goto out_putf;
+-		}
+-		f = l->lo_backing_file;
+-	}
++	error = loop_validate_file(file, bdev);
++	if (error)
++		goto out_putf;
+ 
+ 	mapping = file->f_mapping;
+ 	inode = mapping->host;
+ 
+-	error = -EINVAL;
+-	if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))
+-		goto out_putf;
+-
+ 	if (!(file->f_mode & FMODE_WRITE) || !(mode & FMODE_WRITE) ||
+ 	    !file->f_op->write_iter)
+ 		lo_flags |= LO_FLAGS_READ_ONLY;

commit 8a2b307c21d4b290e3cbe33f768f194286d07c23
+Author: Theodore Ts'o 
+Date:   Wed May 23 11:31:03 2018 -0400
+
+    ext4: correctly handle a zero-length xattr with a non-zero e_value_offs
+    
+    Ext4 will always create ext4 extended attributes which do not have a
+    value (where e_value_size is zero) with e_value_offs set to zero.  In
+    most places e_value_offs will not be used in a substantive way if
+    e_value_size is zero.
+    
+    There was one exception to this, which is in ext4_xattr_set_entry(),
+    where if there is a maliciously crafted file system where there is an
+    extended attribute with e_value_offs is non-zero and e_value_size is
+    0, the attempt to remove this xattr will result in a negative value
+    getting passed to memmove, leading to the following sadness:
+    
+    [   41.225365] EXT4-fs (loop0): mounted filesystem with ordered data mode. Opts: (null)
+    [   44.538641] BUG: unable to handle kernel paging request at ffff9ec9a3000000
+    [   44.538733] IP: __memmove+0x81/0x1a0
+    [   44.538755] PGD 1249bd067 P4D 1249bd067 PUD 1249c1067 PMD 80000001230000e1
+    [   44.538793] Oops: 0003 [#1] SMP PTI
+    [   44.539074] CPU: 0 PID: 1470 Comm: poc Not tainted 4.16.0-rc1+ #1
+        ...
+    [   44.539475] Call Trace:
+    [   44.539832]  ext4_xattr_set_entry+0x9e7/0xf80
+        ...
+    [   44.539972]  ext4_xattr_block_set+0x212/0xea0
+        ...
+    [   44.540041]  ext4_xattr_set_handle+0x514/0x610
+    [   44.540065]  ext4_xattr_set+0x7f/0x120
+    [   44.540090]  __vfs_removexattr+0x4d/0x60
+    [   44.540112]  vfs_removexattr+0x75/0xe0
+    [   44.540132]  removexattr+0x4d/0x80
+        ...
+    [   44.540279]  path_removexattr+0x91/0xb0
+    [   44.540300]  SyS_removexattr+0xf/0x20
+    [   44.540322]  do_syscall_64+0x71/0x120
+    [   44.540344]  entry_SYSCALL_64_after_hwframe+0x21/0x86
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=199347
+    
+    This addresses CVE-2018-10840.
+    
+    Reported-by: "Xu, Wen" 
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Andreas Dilger 
+    Cc: stable@kernel.org
+    Fixes: dec214d00e0d7 ("ext4: xattr inode deduplication")
+
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 499cb4b1fbd2..fc4ced59c565 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -1688,7 +1688,7 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i,
+ 
+ 	/* No failures allowed past this point. */
+ 
+-	if (!s->not_found && here->e_value_offs) {
++	if (!s->not_found && here->e_value_size && here->e_value_offs) {
+ 		/* Remove the old value. */
+ 		void *first_val = s->base + min_offs;
+ 		size_t offs = le16_to_cpu(here->e_value_offs);

commit eb9b5f01c33adebc31cbc236c02695f605b0e417
+Author: Theodore Ts'o 
+Date:   Tue May 22 17:14:07 2018 -0400
+
+    ext4: bubble errors from ext4_find_inline_data_nolock() up to ext4_iget()
+    
+    If ext4_find_inline_data_nolock() returns an error it needs to get
+    reflected up to ext4_iget().  In order to fix this,
+    ext4_iget_extra_inode() needs to return an error (and not return
+    void).
+    
+    This is related to "ext4: do not allow external inodes for inline
+    data" (which fixes CVE-2018-11412) in that in the errors=continue
+    case, it would be useful to for userspace to receive an error
+    indicating that file system is corrupted.
+    
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Andreas Dilger 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 58301a697379..2ea07efbe016 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4701,19 +4701,21 @@ static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode,
+ 	}
+ }
+ 
+-static inline void ext4_iget_extra_inode(struct inode *inode,
++static inline int ext4_iget_extra_inode(struct inode *inode,
+ 					 struct ext4_inode *raw_inode,
+ 					 struct ext4_inode_info *ei)
+ {
+ 	__le32 *magic = (void *)raw_inode +
+ 			EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize;
++
+ 	if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize + sizeof(__le32) <=
+ 	    EXT4_INODE_SIZE(inode->i_sb) &&
+ 	    *magic == cpu_to_le32(EXT4_XATTR_MAGIC)) {
+ 		ext4_set_inode_state(inode, EXT4_STATE_XATTR);
+-		ext4_find_inline_data_nolock(inode);
++		return ext4_find_inline_data_nolock(inode);
+ 	} else
+ 		EXT4_I(inode)->i_inline_off = 0;
++	return 0;
+ }
+ 
+ int ext4_get_projid(struct inode *inode, kprojid_t *projid)
+@@ -4913,7 +4915,9 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 			ei->i_extra_isize = sizeof(struct ext4_inode) -
+ 					    EXT4_GOOD_OLD_INODE_SIZE;
+ 		} else {
+-			ext4_iget_extra_inode(inode, raw_inode, ei);
++			ret = ext4_iget_extra_inode(inode, raw_inode, ei);
++			if (ret)
++				goto bad_inode;
+ 		}
+ 	}
+ 

commit 117166efb1ee8f13c38f9e96b258f16d4923f888
+Author: Theodore Ts'o 
+Date:   Tue May 22 16:15:24 2018 -0400
+
+    ext4: do not allow external inodes for inline data
+    
+    The inline data feature was implemented before we added support for
+    external inodes for xattrs.  It makes no sense to support that
+    combination, but the problem is that there are a number of extended
+    attribute checks that are skipped if e_value_inum is non-zero.
+    
+    Unfortunately, the inline data code is completely e_value_inum
+    unaware, and attempts to interpret the xattr fields as if it were an
+    inline xattr --- at which point, Hilarty Ensues.
+    
+    This addresses CVE-2018-11412.
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=199803
+    
+    Reported-by: Jann Horn 
+    Reviewed-by: Andreas Dilger 
+    Signed-off-by: Theodore Ts'o 
+    Fixes: e50e5129f384 ("ext4: xattr-in-inode support")
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index 70cf4c7b268a..44b4fcdc3755 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -144,6 +144,12 @@ int ext4_find_inline_data_nolock(struct inode *inode)
+ 		goto out;
+ 
+ 	if (!is.s.not_found) {
++		if (is.s.here->e_value_inum) {
++			EXT4_ERROR_INODE(inode, "inline data xattr refers "
++					 "to an external xattr inode");
++			error = -EFSCORRUPTED;
++			goto out;
++		}
+ 		EXT4_I(inode)->i_inline_off = (u16)((void *)is.s.here -
+ 					(void *)ext4_raw_inode(&is.iloc));
+ 		EXT4_I(inode)->i_inline_size = EXT4_MIN_INLINE_DATA_SIZE +

commit 7ef79ad52136712172eb0525bf0b462516bf2f93
+Author: Theodore Ts'o 
+Date:   Thu Apr 26 00:44:46 2018 -0400
+
+    ext4: add MODULE_SOFTDEP to ensure crc32c is included in the initramfs
+    
+    Fixes: a45403b51582 ("ext4: always initialize the crc32c checksum driver")
+    Reported-by: François Valenduc 
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 185f7e61f4cf..eb104e8476f0 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -5886,5 +5886,6 @@ static void __exit ext4_exit_fs(void)
+ MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
+ MODULE_DESCRIPTION("Fourth Extended Filesystem");
+ MODULE_LICENSE("GPL");
++MODULE_SOFTDEP("pre: crc32c");
+ module_init(ext4_init_fs)
+ module_exit(ext4_exit_fs)

commit 4e00b339e264802851aff8e73cde7d24b57b18ce
+Author: Theodore Ts'o 
+Date:   Wed Apr 25 01:12:32 2018 -0400
+
+    random: rate limit unseeded randomness warnings
+    
+    On systems without sufficient boot randomness, no point spamming dmesg.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 721dca8db9cf..cd888d4ee605 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -261,6 +261,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -438,6 +439,16 @@ static void _crng_backtrack_protect(struct crng_state *crng,
+ static void process_random_ready_list(void);
+ static void _get_random_bytes(void *buf, int nbytes);
+ 
++static struct ratelimit_state unseeded_warning =
++	RATELIMIT_STATE_INIT("warn_unseeded_randomness", HZ, 3);
++static struct ratelimit_state urandom_warning =
++	RATELIMIT_STATE_INIT("warn_urandom_randomness", HZ, 3);
++
++static int ratelimit_disable __read_mostly;
++
++module_param_named(ratelimit_disable, ratelimit_disable, int, 0644);
++MODULE_PARM_DESC(ratelimit_disable, "Disable random ratelimit suppression");
++
+ /**********************************************************************
+  *
+  * OS independent entropy store.   Here are the functions which handle
+@@ -932,6 +943,18 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
+ 		process_random_ready_list();
+ 		wake_up_interruptible(&crng_init_wait);
+ 		pr_notice("random: crng init done\n");
++		if (unseeded_warning.missed) {
++			pr_notice("random: %d get_random_xx warning(s) missed "
++				  "due to ratelimiting\n",
++				  unseeded_warning.missed);
++			unseeded_warning.missed = 0;
++		}
++		if (urandom_warning.missed) {
++			pr_notice("random: %d urandom warning(s) missed "
++				  "due to ratelimiting\n",
++				  urandom_warning.missed);
++			urandom_warning.missed = 0;
++		}
+ 	}
+ }
+ 
+@@ -1572,8 +1595,9 @@ static void _warn_unseeded_randomness(const char *func_name, void *caller,
+ #ifndef CONFIG_WARN_ALL_UNSEEDED_RANDOM
+ 	print_once = true;
+ #endif
+-	pr_notice("random: %s called from %pS with crng_init=%d\n",
+-		  func_name, caller, crng_init);
++	if (__ratelimit(&unseeded_warning))
++		pr_notice("random: %s called from %pS with crng_init=%d\n",
++			  func_name, caller, crng_init);
+ }
+ 
+ /*
+@@ -1767,6 +1791,10 @@ static int rand_initialize(void)
+ 	init_std_data(&blocking_pool);
+ 	crng_initialize(&primary_crng);
+ 	crng_global_init_time = jiffies;
++	if (ratelimit_disable) {
++		urandom_warning.interval = 0;
++		unseeded_warning.interval = 0;
++	}
+ 	return 0;
+ }
+ early_initcall(rand_initialize);
+@@ -1834,9 +1862,10 @@ urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+ 
+ 	if (!crng_ready() && maxwarn > 0) {
+ 		maxwarn--;
+-		printk(KERN_NOTICE "random: %s: uninitialized urandom read "
+-		       "(%zd bytes read)\n",
+-		       current->comm, nbytes);
++		if (__ratelimit(&urandom_warning))
++			printk(KERN_NOTICE "random: %s: uninitialized "
++			       "urandom read (%zd bytes read)\n",
++			       current->comm, nbytes);
+ 		spin_lock_irqsave(&primary_crng.lock, flags);
+ 		crng_init_cnt = 0;
+ 		spin_unlock_irqrestore(&primary_crng.lock, flags);

commit 6c1e851c4edc13a43adb3ea4044e3fc8f43ccf7d
+Author: Theodore Ts'o 
+Date:   Mon Apr 23 18:51:28 2018 -0400
+
+    random: fix possible sleeping allocation from irq context
+    
+    We can do a sleeping allocation from an irq context when CONFIG_NUMA
+    is enabled.  Fix this by initializing the NUMA crng instances in a
+    workqueue.
+    
+    Reported-by: Tetsuo Handa 
+    Reported-by: syzbot+9de458f6a5e713ee8c1a@syzkaller.appspotmail.com
+    Fixes: 8ef35c866f8862df ("random: set up the NUMA crng instances...")
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 3cd3aae24d6d..721dca8db9cf 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -789,7 +789,7 @@ static void crng_initialize(struct crng_state *crng)
+ }
+ 
+ #ifdef CONFIG_NUMA
+-static void numa_crng_init(void)
++static void do_numa_crng_init(struct work_struct *work)
+ {
+ 	int i;
+ 	struct crng_state *crng;
+@@ -810,6 +810,13 @@ static void numa_crng_init(void)
+ 		kfree(pool);
+ 	}
+ }
++
++static DECLARE_WORK(numa_crng_init_work, do_numa_crng_init);
++
++static void numa_crng_init(void)
++{
++	schedule_work(&numa_crng_init_work);
++}
+ #else
+ static void numa_crng_init(void) {}
+ #endif

commit b2569260d55228b617bd82aba6d0db2faeeb4116
+Author: Theodore Ts'o 
+Date:   Wed Apr 18 11:49:31 2018 -0400
+
+    ext4: set h_journal if there is a failure starting a reserved handle
+    
+    If ext4 tries to start a reserved handle via
+    jbd2_journal_start_reserved(), and the journal has been aborted, this
+    can result in a NULL pointer dereference.  This is because the fields
+    h_journal and h_transaction in the handle structure share the same
+    memory, via a union, so jbd2_journal_start_reserved() will clear
+    h_journal before calling start_this_handle().  If this function fails
+    due to an aborted handle, h_journal will still be NULL, and the call
+    to jbd2_journal_free_reserved() will pass a NULL journal to
+    sub_reserve_credits().
+    
+    This can be reproduced by running "kvm-xfstests -c dioread_nolock
+    generic/475".
+    
+    Cc: stable@kernel.org # 3.11
+    Fixes: 8f7d89f36829b ("jbd2: transaction reservation support")
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Andreas Dilger 
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index ac311037d7a5..8aa453784402 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -532,6 +532,7 @@ int jbd2_journal_start_reserved(handle_t *handle, unsigned int type,
+ 	 */
+ 	ret = start_this_handle(journal, handle, GFP_NOFS);
+ 	if (ret < 0) {
++		handle->h_journal = journal;
+ 		jbd2_journal_free_reserved(handle);
+ 		return ret;
+ 	}

commit d848e5f8e1ebdb227d045db55fe4f825e82965fa
+Author: Theodore Ts'o 
+Date:   Wed Apr 11 16:32:17 2018 -0400
+
+    random: add new ioctl RNDRESEEDCRNG
+    
+    Add a new ioctl which forces the the crng to be reseeded.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 898233f594b4..3cd3aae24d6d 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -429,6 +429,7 @@ struct crng_state primary_crng = {
+ static int crng_init = 0;
+ #define crng_ready() (likely(crng_init > 1))
+ static int crng_init_cnt = 0;
++static unsigned long crng_global_init_time = 0;
+ #define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE)
+ static void _extract_crng(struct crng_state *crng,
+ 			  __u32 out[CHACHA20_BLOCK_WORDS]);
+@@ -933,7 +934,8 @@ static void _extract_crng(struct crng_state *crng,
+ 	unsigned long v, flags;
+ 
+ 	if (crng_ready() &&
+-	    time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL))
++	    (time_after(crng_global_init_time, crng->init_time) ||
++	     time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL)))
+ 		crng_reseed(crng, crng == &primary_crng ? &input_pool : NULL);
+ 	spin_lock_irqsave(&crng->lock, flags);
+ 	if (arch_get_random_long(&v))
+@@ -1757,6 +1759,7 @@ static int rand_initialize(void)
+ 	init_std_data(&input_pool);
+ 	init_std_data(&blocking_pool);
+ 	crng_initialize(&primary_crng);
++	crng_global_init_time = jiffies;
+ 	return 0;
+ }
+ early_initcall(rand_initialize);
+@@ -1930,6 +1933,14 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+ 		input_pool.entropy_count = 0;
+ 		blocking_pool.entropy_count = 0;
+ 		return 0;
++	case RNDRESEEDCRNG:
++		if (!capable(CAP_SYS_ADMIN))
++			return -EPERM;
++		if (crng_init < 2)
++			return -ENODATA;
++		crng_reseed(&primary_crng, NULL);
++		crng_global_init_time = jiffies - 1;
++		return 0;
+ 	default:
+ 		return -EINVAL;
+ 	}
+diff --git a/include/uapi/linux/random.h b/include/uapi/linux/random.h
+index c34f4490d025..26ee91300e3e 100644
+--- a/include/uapi/linux/random.h
++++ b/include/uapi/linux/random.h
+@@ -35,6 +35,9 @@
+ /* Clear the entropy pool and associated counters.  (Superuser only.) */
+ #define RNDCLEARPOOL	_IO( 'R', 0x06 )
+ 
++/* Reseed CRNG.  (Superuser only.) */
++#define RNDRESEEDCRNG	_IO( 'R', 0x07 )
++
+ struct rand_pool_info {
+ 	int	entropy_count;
+ 	int	buf_size;

commit 0bb29a849a6433b72e249eea7695477b02056e94
+Author: Theodore Ts'o 
+Date:   Thu Apr 12 00:50:45 2018 -0400
+
+    random: crng_reseed() should lock the crng instance that it is modifying
+    
+    Reported-by: Jann Horn 
+    Fixes: 1e7f583af67b ("random: make /dev/urandom scalable for silly...")
+    Cc: stable@kernel.org # 4.8+
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Jann Horn 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 02d792f7933f..898233f594b4 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -906,7 +906,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
+ 		_crng_backtrack_protect(&primary_crng, buf.block,
+ 					CHACHA20_KEY_SIZE);
+ 	}
+-	spin_lock_irqsave(&primary_crng.lock, flags);
++	spin_lock_irqsave(&crng->lock, flags);
+ 	for (i = 0; i < 8; i++) {
+ 		unsigned long	rv;
+ 		if (!arch_get_random_seed_long(&rv) &&
+@@ -916,7 +916,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
+ 	}
+ 	memzero_explicit(&buf, sizeof(buf));
+ 	crng->init_time = jiffies;
+-	spin_unlock_irqrestore(&primary_crng.lock, flags);
++	spin_unlock_irqrestore(&crng->lock, flags);
+ 	if (crng == &primary_crng && crng_init < 2) {
+ 		invalidate_batched_entropy();
+ 		numa_crng_init();

commit 8ef35c866f8862df074a49a93b0309725812dea8
+Author: Theodore Ts'o 
+Date:   Wed Apr 11 15:23:56 2018 -0400
+
+    random: set up the NUMA crng instances after the CRNG is fully initialized
+    
+    Until the primary_crng is fully initialized, don't initialize the NUMA
+    crng nodes.  Otherwise users of /dev/urandom on NUMA systems before
+    the CRNG is fully initialized can get very bad quality randomness.  Of
+    course everyone should move to getrandom(2) where this won't be an
+    issue, but there's a lot of legacy code out there.  This related to
+    CVE-2018-1108.
+    
+    Reported-by: Jann Horn 
+    Fixes: 1e7f583af67b ("random: make /dev/urandom scalable for silly...")
+    Cc: stable@kernel.org # 4.8+
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 6baa828c0493..02d792f7933f 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -787,6 +787,32 @@ static void crng_initialize(struct crng_state *crng)
+ 	crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1;
+ }
+ 
++#ifdef CONFIG_NUMA
++static void numa_crng_init(void)
++{
++	int i;
++	struct crng_state *crng;
++	struct crng_state **pool;
++
++	pool = kcalloc(nr_node_ids, sizeof(*pool), GFP_KERNEL|__GFP_NOFAIL);
++	for_each_online_node(i) {
++		crng = kmalloc_node(sizeof(struct crng_state),
++				    GFP_KERNEL | __GFP_NOFAIL, i);
++		spin_lock_init(&crng->lock);
++		crng_initialize(crng);
++		pool[i] = crng;
++	}
++	mb();
++	if (cmpxchg(&crng_node_pool, NULL, pool)) {
++		for_each_node(i)
++			kfree(pool[i]);
++		kfree(pool);
++	}
++}
++#else
++static void numa_crng_init(void) {}
++#endif
++
+ /*
+  * crng_fast_load() can be called by code in the interrupt service
+  * path.  So we can't afford to dilly-dally.
+@@ -893,6 +919,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
+ 	spin_unlock_irqrestore(&primary_crng.lock, flags);
+ 	if (crng == &primary_crng && crng_init < 2) {
+ 		invalidate_batched_entropy();
++		numa_crng_init();
+ 		crng_init = 2;
+ 		process_random_ready_list();
+ 		wake_up_interruptible(&crng_init_wait);
+@@ -1727,28 +1754,9 @@ static void init_std_data(struct entropy_store *r)
+  */
+ static int rand_initialize(void)
+ {
+-#ifdef CONFIG_NUMA
+-	int i;
+-	struct crng_state *crng;
+-	struct crng_state **pool;
+-#endif
+-
+ 	init_std_data(&input_pool);
+ 	init_std_data(&blocking_pool);
+ 	crng_initialize(&primary_crng);
+-
+-#ifdef CONFIG_NUMA
+-	pool = kcalloc(nr_node_ids, sizeof(*pool), GFP_KERNEL|__GFP_NOFAIL);
+-	for_each_online_node(i) {
+-		crng = kmalloc_node(sizeof(struct crng_state),
+-				    GFP_KERNEL | __GFP_NOFAIL, i);
+-		spin_lock_init(&crng->lock);
+-		crng_initialize(crng);
+-		pool[i] = crng;
+-	}
+-	mb();
+-	crng_node_pool = pool;
+-#endif
+ 	return 0;
+ }
+ early_initcall(rand_initialize);

commit dc12baacb95f205948f64dc936a47d89ee110117
+Author: Theodore Ts'o 
+Date:   Wed Apr 11 14:58:27 2018 -0400
+
+    random: use a different mixing algorithm for add_device_randomness()
+    
+    add_device_randomness() use of crng_fast_load() was highly
+    problematic.  Some callers of add_device_randomness() can pass in a
+    large amount of static information.  This would immediately promote
+    the crng_init state from 0 to 1, without really doing much to
+    initialize the primary_crng's internal state with something even
+    vaguely unpredictable.
+    
+    Since we don't have the speed constraints of add_interrupt_randomness(),
+    we can do a better job mixing in the what unpredictability a device
+    driver or architecture maintainer might see fit to give us, and do it
+    in a way which does not bump the crng_init_cnt variable.
+    
+    Also, since add_device_randomness() doesn't bump any entropy
+    accounting in crng_init state 0, mix the device randomness into the
+    input_pool entropy pool as well.  This is related to CVE-2018-1108.
+    
+    Reported-by: Jann Horn 
+    Fixes: ee7998c50c26 ("random: do not ignore early device randomness")
+    Cc: stable@kernel.org # 4.13+
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index c8ec1e70abde..6baa828c0493 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -787,6 +787,10 @@ static void crng_initialize(struct crng_state *crng)
+ 	crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1;
+ }
+ 
++/*
++ * crng_fast_load() can be called by code in the interrupt service
++ * path.  So we can't afford to dilly-dally.
++ */
+ static int crng_fast_load(const char *cp, size_t len)
+ {
+ 	unsigned long flags;
+@@ -813,6 +817,51 @@ static int crng_fast_load(const char *cp, size_t len)
+ 	return 1;
+ }
+ 
++/*
++ * crng_slow_load() is called by add_device_randomness, which has two
++ * attributes.  (1) We can't trust the buffer passed to it is
++ * guaranteed to be unpredictable (so it might not have any entropy at
++ * all), and (2) it doesn't have the performance constraints of
++ * crng_fast_load().
++ *
++ * So we do something more comprehensive which is guaranteed to touch
++ * all of the primary_crng's state, and which uses a LFSR with a
++ * period of 255 as part of the mixing algorithm.  Finally, we do
++ * *not* advance crng_init_cnt since buffer we may get may be something
++ * like a fixed DMI table (for example), which might very well be
++ * unique to the machine, but is otherwise unvarying.
++ */
++static int crng_slow_load(const char *cp, size_t len)
++{
++	unsigned long		flags;
++	static unsigned char	lfsr = 1;
++	unsigned char		tmp;
++	unsigned		i, max = CHACHA20_KEY_SIZE;
++	const char *		src_buf = cp;
++	char *			dest_buf = (char *) &primary_crng.state[4];
++
++	if (!spin_trylock_irqsave(&primary_crng.lock, flags))
++		return 0;
++	if (crng_init != 0) {
++		spin_unlock_irqrestore(&primary_crng.lock, flags);
++		return 0;
++	}
++	if (len > max)
++		max = len;
++
++	for (i = 0; i < max ; i++) {
++		tmp = lfsr;
++		lfsr >>= 1;
++		if (tmp & 1)
++			lfsr ^= 0xE1;
++		tmp = dest_buf[i % CHACHA20_KEY_SIZE];
++		dest_buf[i % CHACHA20_KEY_SIZE] ^= src_buf[i % len] ^ lfsr;
++		lfsr += (tmp << 3) | (tmp >> 5);
++	}
++	spin_unlock_irqrestore(&primary_crng.lock, flags);
++	return 1;
++}
++
+ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
+ {
+ 	unsigned long	flags;
+@@ -981,10 +1030,8 @@ void add_device_randomness(const void *buf, unsigned int size)
+ 	unsigned long time = random_get_entropy() ^ jiffies;
+ 	unsigned long flags;
+ 
+-	if (!crng_ready()) {
+-		crng_fast_load(buf, size);
+-		return;
+-	}
++	if (!crng_ready() && size)
++		crng_slow_load(buf, size);
+ 
+ 	trace_add_device_randomness(size, _RET_IP_);
+ 	spin_lock_irqsave(&input_pool.lock, flags);

commit 43838a23a05fbd13e47d750d3dfd77001536dd33
+Author: Theodore Ts'o 
+Date:   Wed Apr 11 13:27:52 2018 -0400
+
+    random: fix crng_ready() test
+    
+    The crng_init variable has three states:
+    
+    0: The CRNG is not initialized at all
+    1: The CRNG has a small amount of entropy, hopefully good enough for
+       early-boot, non-cryptographical use cases
+    2: The CRNG is fully initialized and we are sure it is safe for
+       cryptographic use cases.
+    
+    The crng_ready() function should only return true once we are in the
+    last state.  This addresses CVE-2018-1108.
+    
+    Reported-by: Jann Horn 
+    Fixes: e192be9d9a30 ("random: replace non-blocking pool...")
+    Cc: stable@kernel.org # 4.8+
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Jann Horn 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index e027e7fa1472..c8ec1e70abde 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -427,7 +427,7 @@ struct crng_state primary_crng = {
+  * its value (from 0->1->2).
+  */
+ static int crng_init = 0;
+-#define crng_ready() (likely(crng_init > 0))
++#define crng_ready() (likely(crng_init > 1))
+ static int crng_init_cnt = 0;
+ #define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE)
+ static void _extract_crng(struct crng_state *crng,
+@@ -794,7 +794,7 @@ static int crng_fast_load(const char *cp, size_t len)
+ 
+ 	if (!spin_trylock_irqsave(&primary_crng.lock, flags))
+ 		return 0;
+-	if (crng_ready()) {
++	if (crng_init != 0) {
+ 		spin_unlock_irqrestore(&primary_crng.lock, flags);
+ 		return 0;
+ 	}
+@@ -856,7 +856,7 @@ static void _extract_crng(struct crng_state *crng,
+ {
+ 	unsigned long v, flags;
+ 
+-	if (crng_init > 1 &&
++	if (crng_ready() &&
+ 	    time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL))
+ 		crng_reseed(crng, crng == &primary_crng ? &input_pool : NULL);
+ 	spin_lock_irqsave(&crng->lock, flags);
+@@ -1139,7 +1139,7 @@ void add_interrupt_randomness(int irq, int irq_flags)
+ 	fast_mix(fast_pool);
+ 	add_interrupt_bench(cycles);
+ 
+-	if (!crng_ready()) {
++	if (unlikely(crng_init == 0)) {
+ 		if ((fast_pool->count >= 64) &&
+ 		    crng_fast_load((char *) fast_pool->pool,
+ 				   sizeof(fast_pool->pool))) {
+@@ -2212,7 +2212,7 @@ void add_hwgenerator_randomness(const char *buffer, size_t count,
+ {
+ 	struct entropy_store *poolp = &input_pool;
+ 
+-	if (!crng_ready()) {
++	if (unlikely(crng_init == 0)) {
+ 		crng_fast_load(buffer, count);
+ 		return;
+ 	}

commit e40ff213898502d299351cc2fe1e350cd186f0d3
+Author: Theodore Ts'o 
+Date:   Sun Apr 1 23:21:03 2018 -0400
+
+    ext4: force revalidation of directory pointer after seekdir(2)
+    
+    A malicious user could force the directory pointer to be in an invalid
+    spot by using seekdir(2).  Use the mechanism we already have to notice
+    if the directory has changed since the last time we called
+    ext4_readdir() to force a revalidation of the pointer.
+    
+    Reported-by: syzbot+1236ce66f79263e8a862@syzkaller.appspotmail.com
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index da87cf757f7d..e2902d394f1b 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -365,13 +365,15 @@ static loff_t ext4_dir_llseek(struct file *file, loff_t offset, int whence)
+ {
+ 	struct inode *inode = file->f_mapping->host;
+ 	int dx_dir = is_dx_dir(inode);
+-	loff_t htree_max = ext4_get_htree_eof(file);
++	loff_t ret, htree_max = ext4_get_htree_eof(file);
+ 
+ 	if (likely(dx_dir))
+-		return generic_file_llseek_size(file, offset, whence,
++		ret = generic_file_llseek_size(file, offset, whence,
+ 						    htree_max, htree_max);
+ 	else
+-		return ext4_llseek(file, offset, whence);
++		ret = ext4_llseek(file, offset, whence);
++	file->f_version = inode_peek_iversion(inode) - 1;
++	return ret;
+ }
+ 
+ /*

commit 54dd0e0a1b255f115f8647fc6fb93273251b01b9
+Author: Theodore Ts'o 
+Date:   Fri Mar 30 20:04:11 2018 -0400
+
+    ext4: add extra checks to ext4_xattr_block_get()
+    
+    Add explicit checks in ext4_xattr_block_get() just in case the
+    e_value_offs and e_value_size fields in the the xattr block are
+    corrupted in memory after the buffer_verified bit is set on the xattr
+    block.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 6304e81bfe6a..499cb4b1fbd2 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -197,7 +197,7 @@ ext4_xattr_check_entries(struct ext4_xattr_entry *entry, void *end,
+ 	while (!IS_LAST_ENTRY(entry)) {
+ 		u32 size = le32_to_cpu(entry->e_value_size);
+ 
+-		if (size > INT_MAX)
++		if (size > EXT4_XATTR_SIZE_MAX)
+ 			return -EFSCORRUPTED;
+ 
+ 		if (size != 0 && entry->e_value_inum == 0) {
+@@ -540,8 +540,10 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
+ 	if (error)
+ 		goto cleanup;
+ 	size = le32_to_cpu(entry->e_value_size);
++	error = -ERANGE;
++	if (unlikely(size > EXT4_XATTR_SIZE_MAX))
++		goto cleanup;
+ 	if (buffer) {
+-		error = -ERANGE;
+ 		if (size > buffer_size)
+ 			goto cleanup;
+ 		if (entry->e_value_inum) {
+@@ -550,8 +552,12 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
+ 			if (error)
+ 				goto cleanup;
+ 		} else {
+-			memcpy(buffer, bh->b_data +
+-			       le16_to_cpu(entry->e_value_offs), size);
++			u16 offset = le16_to_cpu(entry->e_value_offs);
++			void *p = bh->b_data + offset;
++
++			if (unlikely(p + size > end))
++				goto cleanup;
++			memcpy(buffer, p, size);
+ 		}
+ 	}
+ 	error = size;
+@@ -589,8 +595,10 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
+ 	if (error)
+ 		goto cleanup;
+ 	size = le32_to_cpu(entry->e_value_size);
++	error = -ERANGE;
++	if (unlikely(size > EXT4_XATTR_SIZE_MAX))
++		goto cleanup;
+ 	if (buffer) {
+-		error = -ERANGE;
+ 		if (size > buffer_size)
+ 			goto cleanup;
+ 		if (entry->e_value_inum) {
+@@ -599,8 +607,12 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
+ 			if (error)
+ 				goto cleanup;
+ 		} else {
+-			memcpy(buffer, (void *)IFIRST(header) +
+-			       le16_to_cpu(entry->e_value_offs), size);
++			u16 offset = le16_to_cpu(entry->e_value_offs);
++			void *p = (void *)IFIRST(header) + offset;
++
++			if (unlikely(p + size > end))
++				goto cleanup;
++			memcpy(buffer, p, size);
+ 		}
+ 	}
+ 	error = size;
+diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
+index dd54c4f995c8..f39cad2abe2a 100644
+--- a/fs/ext4/xattr.h
++++ b/fs/ext4/xattr.h
+@@ -70,6 +70,17 @@ struct ext4_xattr_entry {
+ 		EXT4_I(inode)->i_extra_isize))
+ #define IFIRST(hdr) ((struct ext4_xattr_entry *)((hdr)+1))
+ 
++/*
++ * XATTR_SIZE_MAX is currently 64k, but for the purposes of checking
++ * for file system consistency errors, we use a somewhat bigger value.
++ * This allows XATTR_SIZE_MAX to grow in the future, but by using this
++ * instead of INT_MAX for certain consistency checks, we don't need to
++ * worry about arithmetic overflows.  (Actually XATTR_SIZE_MAX is
++ * defined in include/uapi/linux/limits.h, so changing it is going
++ * not going to be trivial....)
++ */
++#define EXT4_XATTR_SIZE_MAX (1 << 24)
++
+ /*
+  * The minimum size of EA value when you start storing it in an external inode
+  * size of block - size of header - size of 1 entry - 4 null bytes

commit 9496005d6ca4cf8f5ee8f828165a8956872dc59d
+Author: Theodore Ts'o 
+Date:   Fri Mar 30 20:00:56 2018 -0400
+
+    ext4: add bounds checking to ext4_xattr_find_entry()
+    
+    Add some paranoia checks to make sure we don't stray beyond the end of
+    the valid memory region containing ext4 xattr entries while we are
+    scanning for a match.
+    
+    Also rename the function to xattr_find_entry() since it is static and
+    thus only used in fs/ext4/xattr.c
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index c030e41818ab..6304e81bfe6a 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -276,18 +276,22 @@ __xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header,
+ 	__xattr_check_inode((inode), (header), (end), __func__, __LINE__)
+ 
+ static int
+-ext4_xattr_find_entry(struct ext4_xattr_entry **pentry, int name_index,
+-		      const char *name, int sorted)
++xattr_find_entry(struct inode *inode, struct ext4_xattr_entry **pentry,
++		 void *end, int name_index, const char *name, int sorted)
+ {
+-	struct ext4_xattr_entry *entry;
++	struct ext4_xattr_entry *entry, *next;
+ 	size_t name_len;
+ 	int cmp = 1;
+ 
+ 	if (name == NULL)
+ 		return -EINVAL;
+ 	name_len = strlen(name);
+-	entry = *pentry;
+-	for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) {
++	for (entry = *pentry; !IS_LAST_ENTRY(entry); entry = next) {
++		next = EXT4_XATTR_NEXT(entry);
++		if ((void *) next >= end) {
++			EXT4_ERROR_INODE(inode, "corrupted xattr entries");
++			return -EFSCORRUPTED;
++		}
+ 		cmp = name_index - entry->e_name_index;
+ 		if (!cmp)
+ 			cmp = name_len - entry->e_name_len;
+@@ -509,6 +513,7 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
+ 	struct buffer_head *bh = NULL;
+ 	struct ext4_xattr_entry *entry;
+ 	size_t size;
++	void *end;
+ 	int error;
+ 	struct mb_cache *ea_block_cache = EA_BLOCK_CACHE(inode);
+ 
+@@ -530,7 +535,8 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
+ 		goto cleanup;
+ 	ext4_xattr_block_cache_insert(ea_block_cache, bh);
+ 	entry = BFIRST(bh);
+-	error = ext4_xattr_find_entry(&entry, name_index, name, 1);
++	end = bh->b_data + bh->b_size;
++	error = xattr_find_entry(inode, &entry, end, name_index, name, 1);
+ 	if (error)
+ 		goto cleanup;
+ 	size = le32_to_cpu(entry->e_value_size);
+@@ -579,7 +585,7 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
+ 	if (error)
+ 		goto cleanup;
+ 	entry = IFIRST(header);
+-	error = ext4_xattr_find_entry(&entry, name_index, name, 0);
++	error = xattr_find_entry(inode, &entry, end, name_index, name, 0);
+ 	if (error)
+ 		goto cleanup;
+ 	size = le32_to_cpu(entry->e_value_size);
+@@ -1808,8 +1814,8 @@ ext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i,
+ 		bs->s.first = BFIRST(bs->bh);
+ 		bs->s.end = bs->bh->b_data + bs->bh->b_size;
+ 		bs->s.here = bs->s.first;
+-		error = ext4_xattr_find_entry(&bs->s.here, i->name_index,
+-					      i->name, 1);
++		error = xattr_find_entry(inode, &bs->s.here, bs->s.end,
++					 i->name_index, i->name, 1);
+ 		if (error && error != -ENODATA)
+ 			goto cleanup;
+ 		bs->s.not_found = error;
+@@ -2168,8 +2174,8 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i,
+ 		if (error)
+ 			return error;
+ 		/* Find the named attribute. */
+-		error = ext4_xattr_find_entry(&is->s.here, i->name_index,
+-					      i->name, 0);
++		error = xattr_find_entry(inode, &is->s.here, is->s.end,
++					 i->name_index, i->name, 0);
+ 		if (error && error != -ENODATA)
+ 			return error;
+ 		is->s.not_found = error;

commit de05ca8526796c7e9f7c7282b7f89a818af19818
+Author: Theodore Ts'o 
+Date:   Fri Mar 30 15:42:25 2018 -0400
+
+    ext4: move call to ext4_error() into ext4_xattr_check_block()
+    
+    Refactor the call to EXT4_ERROR_INODE() into ext4_xattr_check_block().
+    This simplifies the code, and fixes a problem where not all callers of
+    ext4_xattr_check_block() were not resulting in ext4_error() getting
+    called when the xattr block is corrupted.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 2077d87b09f2..c030e41818ab 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -225,25 +225,36 @@ ext4_xattr_check_entries(struct ext4_xattr_entry *entry, void *end,
+ }
+ 
+ static inline int
+-ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh)
++__ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh,
++			 const char *function, unsigned int line)
+ {
+-	int error;
++	int error = -EFSCORRUPTED;
+ 
+ 	if (buffer_verified(bh))
+ 		return 0;
+ 
+ 	if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) ||
+ 	    BHDR(bh)->h_blocks != cpu_to_le32(1))
+-		return -EFSCORRUPTED;
++		goto errout;
++	error = -EFSBADCRC;
+ 	if (!ext4_xattr_block_csum_verify(inode, bh))
+-		return -EFSBADCRC;
++		goto errout;
+ 	error = ext4_xattr_check_entries(BFIRST(bh), bh->b_data + bh->b_size,
+ 					 bh->b_data);
+-	if (!error)
++errout:
++	if (error)
++		__ext4_error_inode(inode, function, line, 0,
++				   "corrupted xattr block %llu",
++				   (unsigned long long) bh->b_blocknr);
++	else
+ 		set_buffer_verified(bh);
+ 	return error;
+ }
+ 
++#define ext4_xattr_check_block(inode, bh) \
++	__ext4_xattr_check_block((inode), (bh),  __func__, __LINE__)
++
++
+ static int
+ __xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header,
+ 			 void *end, const char *function, unsigned int line)
+@@ -514,12 +525,9 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
+ 		goto cleanup;
+ 	ea_bdebug(bh, "b_count=%d, refcount=%d",
+ 		atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
+-	if (ext4_xattr_check_block(inode, bh)) {
+-		EXT4_ERROR_INODE(inode, "bad block %llu",
+-				 EXT4_I(inode)->i_file_acl);
+-		error = -EFSCORRUPTED;
++	error = ext4_xattr_check_block(inode, bh);
++	if (error)
+ 		goto cleanup;
+-	}
+ 	ext4_xattr_block_cache_insert(ea_block_cache, bh);
+ 	entry = BFIRST(bh);
+ 	error = ext4_xattr_find_entry(&entry, name_index, name, 1);
+@@ -679,12 +687,9 @@ ext4_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size)
+ 		goto cleanup;
+ 	ea_bdebug(bh, "b_count=%d, refcount=%d",
+ 		atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
+-	if (ext4_xattr_check_block(inode, bh)) {
+-		EXT4_ERROR_INODE(inode, "bad block %llu",
+-				 EXT4_I(inode)->i_file_acl);
+-		error = -EFSCORRUPTED;
++	error = ext4_xattr_check_block(inode, bh);
++	if (error)
+ 		goto cleanup;
+-	}
+ 	ext4_xattr_block_cache_insert(EA_BLOCK_CACHE(inode), bh);
+ 	error = ext4_xattr_list_entries(dentry, BFIRST(bh), buffer, buffer_size);
+ 
+@@ -811,10 +816,9 @@ int ext4_get_inode_usage(struct inode *inode, qsize_t *usage)
+ 			goto out;
+ 		}
+ 
+-		if (ext4_xattr_check_block(inode, bh)) {
+-			ret = -EFSCORRUPTED;
++		ret = ext4_xattr_check_block(inode, bh);
++		if (ret)
+ 			goto out;
+-		}
+ 
+ 		for (entry = BFIRST(bh); !IS_LAST_ENTRY(entry);
+ 		     entry = EXT4_XATTR_NEXT(entry))
+@@ -1796,12 +1800,9 @@ ext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i,
+ 		ea_bdebug(bs->bh, "b_count=%d, refcount=%d",
+ 			atomic_read(&(bs->bh->b_count)),
+ 			le32_to_cpu(BHDR(bs->bh)->h_refcount));
+-		if (ext4_xattr_check_block(inode, bs->bh)) {
+-			EXT4_ERROR_INODE(inode, "bad block %llu",
+-					 EXT4_I(inode)->i_file_acl);
+-			error = -EFSCORRUPTED;
++		error = ext4_xattr_check_block(inode, bs->bh);
++		if (error)
+ 			goto cleanup;
+-		}
+ 		/* Find the named attribute. */
+ 		bs->s.base = BHDR(bs->bh);
+ 		bs->s.first = BFIRST(bs->bh);
+@@ -2724,13 +2725,9 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
+ 		error = -EIO;
+ 		if (!bh)
+ 			goto cleanup;
+-		if (ext4_xattr_check_block(inode, bh)) {
+-			EXT4_ERROR_INODE(inode, "bad block %llu",
+-					 EXT4_I(inode)->i_file_acl);
+-			error = -EFSCORRUPTED;
+-			brelse(bh);
++		error = ext4_xattr_check_block(inode, bh);
++		if (error)
+ 			goto cleanup;
+-		}
+ 		base = BHDR(bh);
+ 		end = bh->b_data + bh->b_size;
+ 		min_offs = end - base;
+@@ -2887,11 +2884,8 @@ int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode,
+ 			goto cleanup;
+ 		}
+ 		error = ext4_xattr_check_block(inode, bh);
+-		if (error) {
+-			EXT4_ERROR_INODE(inode, "bad block %llu (error %d)",
+-					 EXT4_I(inode)->i_file_acl, error);
++		if (error)
+ 			goto cleanup;
+-		}
+ 
+ 		if (ext4_has_feature_ea_inode(inode->i_sb)) {
+ 			for (entry = BFIRST(bh); !IS_LAST_ENTRY(entry);

commit 18db4b4e6fc31eda838dd1c1296d67dbcb3dc957
+Author: Theodore Ts'o 
+Date:   Thu Mar 29 22:10:35 2018 -0400
+
+    ext4: don't allow r/w mounts if metadata blocks overlap the superblock
+    
+    If some metadata block, such as an allocation bitmap, overlaps the
+    superblock, it's very likely that if the file system is mounted
+    read/write, the results will not be pretty.  So disallow r/w mounts
+    for file systems corrupted in this particular way.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 7cd022c344d1..edcfe6956eba 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2335,6 +2335,8 @@ static int ext4_check_descriptors(struct super_block *sb,
+ 			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
+ 				 "Block bitmap for group %u overlaps "
+ 				 "superblock", i);
++			if (!sb_rdonly(sb))
++				return 0;
+ 		}
+ 		if (block_bitmap < first_block || block_bitmap > last_block) {
+ 			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
+@@ -2347,6 +2349,8 @@ static int ext4_check_descriptors(struct super_block *sb,
+ 			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
+ 				 "Inode bitmap for group %u overlaps "
+ 				 "superblock", i);
++			if (!sb_rdonly(sb))
++				return 0;
+ 		}
+ 		if (inode_bitmap < first_block || inode_bitmap > last_block) {
+ 			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
+@@ -2359,6 +2363,8 @@ static int ext4_check_descriptors(struct super_block *sb,
+ 			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
+ 				 "Inode table for group %u overlaps "
+ 				 "superblock", i);
++			if (!sb_rdonly(sb))
++				return 0;
+ 		}
+ 		if (inode_table < first_block ||
+ 		    inode_table + sbi->s_itb_per_group - 1 > last_block) {

commit a45403b51582a87872927a3e0fc0a389c26867f1
+Author: Theodore Ts'o 
+Date:   Thu Mar 29 22:10:31 2018 -0400
+
+    ext4: always initialize the crc32c checksum driver
+    
+    The extended attribute code now uses the crc32c checksum for hashing
+    purposes, so we should just always always initialize it.  We also want
+    to prevent NULL pointer dereferences if one of the metadata checksum
+    features is enabled after the file sytsem is originally mounted.
+    
+    This issue has been assigned CVE-2018-1094.
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=199183
+    https://bugzilla.redhat.com/show_bug.cgi?id=1560788
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 9d1da40c1f62..7cd022c344d1 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3492,15 +3492,12 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	}
+ 
+ 	/* Load the checksum driver */
+-	if (ext4_has_feature_metadata_csum(sb) ||
+-	    ext4_has_feature_ea_inode(sb)) {
+-		sbi->s_chksum_driver = crypto_alloc_shash("crc32c", 0, 0);
+-		if (IS_ERR(sbi->s_chksum_driver)) {
+-			ext4_msg(sb, KERN_ERR, "Cannot load crc32c driver.");
+-			ret = PTR_ERR(sbi->s_chksum_driver);
+-			sbi->s_chksum_driver = NULL;
+-			goto failed_mount;
+-		}
++	sbi->s_chksum_driver = crypto_alloc_shash("crc32c", 0, 0);
++	if (IS_ERR(sbi->s_chksum_driver)) {
++		ext4_msg(sb, KERN_ERR, "Cannot load crc32c driver.");
++		ret = PTR_ERR(sbi->s_chksum_driver);
++		sbi->s_chksum_driver = NULL;
++		goto failed_mount;
+ 	}
+ 
+ 	/* Check superblock checksum */

commit 8e4b5eae5decd9dfe5a4ee369c22028f90ab4c44
+Author: Theodore Ts'o 
+Date:   Thu Mar 29 21:56:09 2018 -0400
+
+    ext4: fail ext4_iget for root directory if unallocated
+    
+    If the root directory has an i_links_count of zero, then when the file
+    system is mounted, then when ext4_fill_super() notices the problem and
+    tries to call iput() the root directory in the error return path,
+    ext4_evict_inode() will try to free the inode on disk, before all of
+    the file system structures are set up, and this will result in an OOPS
+    caused by a NULL pointer dereference.
+    
+    This issue has been assigned CVE-2018-1092.
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=199179
+    https://bugzilla.redhat.com/show_bug.cgi?id=1560777
+    
+    Reported-by: Wen Xu 
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 435965598cb8..18aa2ef963ad 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4732,6 +4732,12 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 		goto bad_inode;
+ 	raw_inode = ext4_raw_inode(&iloc);
+ 
++	if ((ino == EXT4_ROOT_INO) && (raw_inode->i_links_count == 0)) {
++		EXT4_ERROR_INODE(inode, "root inode unallocated");
++		ret = -EFSCORRUPTED;
++		goto bad_inode;
++	}
++
+ 	if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) {
+ 		ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize);
+ 		if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize >

commit 7dac4a1726a9c64a517d595c40e95e2d0d135f6f
+Author: Theodore Ts'o 
+Date:   Mon Mar 26 23:54:10 2018 -0400
+
+    ext4: add validity checks for bitmap block numbers
+    
+    An privileged attacker can cause a crash by mounting a crafted ext4
+    image which triggers a out-of-bounds read in the function
+    ext4_valid_block_bitmap() in fs/ext4/balloc.c.
+    
+    This issue has been assigned CVE-2018-1093.
+    
+    BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=199181
+    BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1560782
+    Reported-by: Wen Xu 
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index f82c4966f4ce..a33d8fb1bf2a 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -338,20 +338,25 @@ static ext4_fsblk_t ext4_valid_block_bitmap(struct super_block *sb,
+ 	/* check whether block bitmap block number is set */
+ 	blk = ext4_block_bitmap(sb, desc);
+ 	offset = blk - group_first_block;
+-	if (!ext4_test_bit(EXT4_B2C(sbi, offset), bh->b_data))
++	if (offset < 0 || EXT4_B2C(sbi, offset) >= sb->s_blocksize ||
++	    !ext4_test_bit(EXT4_B2C(sbi, offset), bh->b_data))
+ 		/* bad block bitmap */
+ 		return blk;
+ 
+ 	/* check whether the inode bitmap block number is set */
+ 	blk = ext4_inode_bitmap(sb, desc);
+ 	offset = blk - group_first_block;
+-	if (!ext4_test_bit(EXT4_B2C(sbi, offset), bh->b_data))
++	if (offset < 0 || EXT4_B2C(sbi, offset) >= sb->s_blocksize ||
++	    !ext4_test_bit(EXT4_B2C(sbi, offset), bh->b_data))
+ 		/* bad block bitmap */
+ 		return blk;
+ 
+ 	/* check whether the inode table block number is set */
+ 	blk = ext4_inode_table(sb, desc);
+ 	offset = blk - group_first_block;
++	if (offset < 0 || EXT4_B2C(sbi, offset) >= sb->s_blocksize ||
++	    EXT4_B2C(sbi, offset + sbi->s_itb_per_group) >= sb->s_blocksize)
++		return blk;
+ 	next_zero_bit = ext4_find_next_zero_bit(bh->b_data,
+ 			EXT4_B2C(sbi, offset + sbi->s_itb_per_group),
+ 			EXT4_B2C(sbi, offset));
+@@ -417,6 +422,7 @@ struct buffer_head *
+ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group)
+ {
+ 	struct ext4_group_desc *desc;
++	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	struct buffer_head *bh;
+ 	ext4_fsblk_t bitmap_blk;
+ 	int err;
+@@ -425,6 +431,12 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group)
+ 	if (!desc)
+ 		return ERR_PTR(-EFSCORRUPTED);
+ 	bitmap_blk = ext4_block_bitmap(sb, desc);
++	if ((bitmap_blk <= le32_to_cpu(sbi->s_es->s_first_data_block)) ||
++	    (bitmap_blk >= ext4_blocks_count(sbi->s_es))) {
++		ext4_error(sb, "Invalid block bitmap block %llu in "
++			   "block_group %u", bitmap_blk, block_group);
++		return ERR_PTR(-EFSCORRUPTED);
++	}
+ 	bh = sb_getblk(sb, bitmap_blk);
+ 	if (unlikely(!bh)) {
+ 		ext4_error(sb, "Cannot get buffer for block bitmap - "
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 3fa93665b4a3..df92e3ec9913 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -122,6 +122,7 @@ static struct buffer_head *
+ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
+ {
+ 	struct ext4_group_desc *desc;
++	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	struct buffer_head *bh = NULL;
+ 	ext4_fsblk_t bitmap_blk;
+ 	int err;
+@@ -131,6 +132,12 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
+ 		return ERR_PTR(-EFSCORRUPTED);
+ 
+ 	bitmap_blk = ext4_inode_bitmap(sb, desc);
++	if ((bitmap_blk <= le32_to_cpu(sbi->s_es->s_first_data_block)) ||
++	    (bitmap_blk >= ext4_blocks_count(sbi->s_es))) {
++		ext4_error(sb, "Invalid inode bitmap blk %llu in "
++			   "block_group %u", bitmap_blk, block_group);
++		return ERR_PTR(-EFSCORRUPTED);
++	}
+ 	bh = sb_getblk(sb, bitmap_blk);
+ 	if (unlikely(!bh)) {
+ 		ext4_error(sb, "Cannot read inode bitmap - "

commit 9f886f4d1d292442b2f22a0a33321eae821bde40
+Author: Theodore Ts'o 
+Date:   Sat Feb 25 18:21:33 2017 -0400
+
+    random: use a tighter cap in credit_entropy_bits_safe()
+    
+    This fixes a harmless UBSAN where root could potentially end up
+    causing an overflow while bumping the entropy_total field (which is
+    ignored once the entropy pool has been initialized, and this generally
+    is completed during the boot sequence).
+    
+    This is marginal for the stable kernel series, but it's a really
+    trivial patch, and it fixes UBSAN warning that might cause security
+    folks to get overly excited for no reason.
+    
+    Signed-off-by: Theodore Ts'o 
+    Reported-by: Chen Feng 
+    Cc: stable@vger.kernel.org
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index e5b3d3ba4660..11c23ca57430 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -732,7 +732,7 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
+ 
+ static int credit_entropy_bits_safe(struct entropy_store *r, int nbits)
+ {
+-	const int nbits_max = (int)(~0U >> (ENTROPY_SHIFT + 1));
++	const int nbits_max = r->poolinfo->poolwords * 32;
+ 
+ 	if (nbits < 0)
+ 		return -EINVAL;

commit 044e6e3d74a3d7103a0c8a9305dfd94d64000660
+Author: Theodore Ts'o 
+Date:   Mon Feb 19 14:16:47 2018 -0500
+
+    ext4: don't update checksum of new initialized bitmaps
+    
+    When reading the inode or block allocation bitmap, if the bitmap needs
+    to be initialized, do not update the checksum in the block group
+    descriptor.  That's because we're not set up to journal those changes.
+    Instead, just set the verified bit on the bitmap block, so that it's
+    not necessary to validate the checksum.
+    
+    When a block or inode allocation actually happens, at that point the
+    checksum will be calculated, and update of the bg descriptor block
+    will be properly journalled.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index f9b3e0a83526..f82c4966f4ce 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -243,8 +243,6 @@ static int ext4_init_block_bitmap(struct super_block *sb,
+ 	 */
+ 	ext4_mark_bitmap_end(num_clusters_in_group(sb, block_group),
+ 			     sb->s_blocksize * 8, bh->b_data);
+-	ext4_block_bitmap_csum_set(sb, block_group, gdp, bh);
+-	ext4_group_desc_csum_set(sb, block_group, gdp);
+ 	return 0;
+ }
+ 
+@@ -448,6 +446,7 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group)
+ 		err = ext4_init_block_bitmap(sb, bh, block_group, desc);
+ 		set_bitmap_uptodate(bh);
+ 		set_buffer_uptodate(bh);
++		set_buffer_verified(bh);
+ 		ext4_unlock_group(sb, block_group);
+ 		unlock_buffer(bh);
+ 		if (err) {
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 7830d28df331..3fa93665b4a3 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -66,44 +66,6 @@ void ext4_mark_bitmap_end(int start_bit, int end_bit, char *bitmap)
+ 		memset(bitmap + (i >> 3), 0xff, (end_bit - i) >> 3);
+ }
+ 
+-/* Initializes an uninitialized inode bitmap */
+-static int ext4_init_inode_bitmap(struct super_block *sb,
+-				       struct buffer_head *bh,
+-				       ext4_group_t block_group,
+-				       struct ext4_group_desc *gdp)
+-{
+-	struct ext4_group_info *grp;
+-	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-	J_ASSERT_BH(bh, buffer_locked(bh));
+-
+-	/* If checksum is bad mark all blocks and inodes use to prevent
+-	 * allocation, essentially implementing a per-group read-only flag. */
+-	if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) {
+-		grp = ext4_get_group_info(sb, block_group);
+-		if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
+-			percpu_counter_sub(&sbi->s_freeclusters_counter,
+-					   grp->bb_free);
+-		set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state);
+-		if (!EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) {
+-			int count;
+-			count = ext4_free_inodes_count(sb, gdp);
+-			percpu_counter_sub(&sbi->s_freeinodes_counter,
+-					   count);
+-		}
+-		set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state);
+-		return -EFSBADCRC;
+-	}
+-
+-	memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8);
+-	ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), sb->s_blocksize * 8,
+-			bh->b_data);
+-	ext4_inode_bitmap_csum_set(sb, block_group, gdp, bh,
+-				   EXT4_INODES_PER_GROUP(sb) / 8);
+-	ext4_group_desc_csum_set(sb, block_group, gdp);
+-
+-	return 0;
+-}
+-
+ void ext4_end_bitmap_read(struct buffer_head *bh, int uptodate)
+ {
+ 	if (uptodate) {
+@@ -187,17 +149,14 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
+ 
+ 	ext4_lock_group(sb, block_group);
+ 	if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) {
+-		err = ext4_init_inode_bitmap(sb, bh, block_group, desc);
++		memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8);
++		ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb),
++				     sb->s_blocksize * 8, bh->b_data);
+ 		set_bitmap_uptodate(bh);
+ 		set_buffer_uptodate(bh);
+ 		set_buffer_verified(bh);
+ 		ext4_unlock_group(sb, block_group);
+ 		unlock_buffer(bh);
+-		if (err) {
+-			ext4_error(sb, "Failed to init inode bitmap for group "
+-				   "%u: %d", block_group, err);
+-			goto out;
+-		}
+ 		return bh;
+ 	}
+ 	ext4_unlock_group(sb, block_group);

commit 85e0c4e89c1b864e763c4e3bb15d0b6d501ad5d9
+Author: Theodore Ts'o 
+Date:   Mon Feb 19 12:22:53 2018 -0500
+
+    jbd2: if the journal is aborted then don't allow update of the log tail
+    
+    This updates the jbd2 superblock unnecessarily, and on an abort we
+    shouldn't truncate the log.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index efa0c72a0b9f..dfb057900e79 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -974,7 +974,7 @@ int __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block)
+ }
+ 
+ /*
+- * This is a variaon of __jbd2_update_log_tail which checks for validity of
++ * This is a variation of __jbd2_update_log_tail which checks for validity of
+  * provided log tail and locks j_checkpoint_mutex. So it is safe against races
+  * with other threads updating log tail.
+  */
+@@ -1417,6 +1417,9 @@ int jbd2_journal_update_sb_log_tail(journal_t *journal, tid_t tail_tid,
+ 	journal_superblock_t *sb = journal->j_superblock;
+ 	int ret;
+ 
++	if (is_journal_aborted(journal))
++		return -EIO;
++
+ 	BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex));
+ 	jbd_debug(1, "JBD2: updating superblock (start %lu, seq %u)\n",
+ 		  tail_block, tail_tid);

commit fb7c02445c497943e7296cd3deee04422b63acb8
+Author: Theodore Ts'o 
+Date:   Sun Feb 18 23:45:18 2018 -0500
+
+    ext4: pass -ESHUTDOWN code to jbd2 layer
+    
+    Previously the jbd2 layer assumed that a file system check would be
+    required after a journal abort.  In the case of the deliberate file
+    system shutdown, this should not be necessary.  Allow the jbd2 layer
+    to distinguish between these two cases by using the ESHUTDOWN errno.
+    
+    Also add proper locking to __journal_abort_soft().
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index 16d3d1325f5b..9ac33a7cbd32 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -493,13 +493,13 @@ static int ext4_shutdown(struct super_block *sb, unsigned long arg)
+ 		set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags);
+ 		if (sbi->s_journal && !is_journal_aborted(sbi->s_journal)) {
+ 			(void) ext4_force_commit(sb);
+-			jbd2_journal_abort(sbi->s_journal, 0);
++			jbd2_journal_abort(sbi->s_journal, -ESHUTDOWN);
+ 		}
+ 		break;
+ 	case EXT4_GOING_FLAGS_NOLOGFLUSH:
+ 		set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags);
+ 		if (sbi->s_journal && !is_journal_aborted(sbi->s_journal))
+-			jbd2_journal_abort(sbi->s_journal, 0);
++			jbd2_journal_abort(sbi->s_journal, -ESHUTDOWN);
+ 		break;
+ 	default:
+ 		return -EINVAL;
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 3fbf48ec2188..efa0c72a0b9f 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -1483,12 +1483,15 @@ static void jbd2_mark_journal_empty(journal_t *journal, int write_op)
+ void jbd2_journal_update_sb_errno(journal_t *journal)
+ {
+ 	journal_superblock_t *sb = journal->j_superblock;
++	int errcode;
+ 
+ 	read_lock(&journal->j_state_lock);
+-	jbd_debug(1, "JBD2: updating superblock error (errno %d)\n",
+-		  journal->j_errno);
+-	sb->s_errno    = cpu_to_be32(journal->j_errno);
++	errcode = journal->j_errno;
+ 	read_unlock(&journal->j_state_lock);
++	if (errcode == -ESHUTDOWN)
++		errcode = 0;
++	jbd_debug(1, "JBD2: updating superblock error (errno %d)\n", errcode);
++	sb->s_errno    = cpu_to_be32(errcode);
+ 
+ 	jbd2_write_superblock(journal, REQ_SYNC | REQ_FUA);
+ }
+@@ -2105,12 +2108,22 @@ void __jbd2_journal_abort_hard(journal_t *journal)
+  * but don't do any other IO. */
+ static void __journal_abort_soft (journal_t *journal, int errno)
+ {
+-	if (journal->j_flags & JBD2_ABORT)
+-		return;
++	int old_errno;
+ 
+-	if (!journal->j_errno)
++	write_lock(&journal->j_state_lock);
++	old_errno = journal->j_errno;
++	if (!journal->j_errno || errno == -ESHUTDOWN)
+ 		journal->j_errno = errno;
+ 
++	if (journal->j_flags & JBD2_ABORT) {
++		write_unlock(&journal->j_state_lock);
++		if (!old_errno && old_errno != -ESHUTDOWN &&
++		    errno == -ESHUTDOWN)
++			jbd2_journal_update_sb_errno(journal);
++		return;
++	}
++	write_unlock(&journal->j_state_lock);
++
+ 	__jbd2_journal_abort_hard(journal);
+ 
+ 	if (errno) {

commit a6d9946bb925293fda9f5ed6d33d8580b001f006
+Author: Theodore Ts'o 
+Date:   Sun Feb 18 23:16:28 2018 -0500
+
+    ext4: eliminate sleep from shutdown ioctl
+    
+    The msleep() when processing EXT4_GOING_FLAGS_NOLOGFLUSH was a hack to
+    avoid some races (that are now fixed), but in fact it introduced its
+    own race.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index 4d1b1575f8ac..16d3d1325f5b 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -498,10 +498,8 @@ static int ext4_shutdown(struct super_block *sb, unsigned long arg)
+ 		break;
+ 	case EXT4_GOING_FLAGS_NOLOGFLUSH:
+ 		set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags);
+-		if (sbi->s_journal && !is_journal_aborted(sbi->s_journal)) {
+-			msleep(100);
++		if (sbi->s_journal && !is_journal_aborted(sbi->s_journal))
+ 			jbd2_journal_abort(sbi->s_journal, 0);
+-		}
+ 		break;
+ 	default:
+ 		return -EINVAL;

commit 576d18ed60f5465110087c5e0eb1010de13e374d
+Author: Theodore Ts'o 
+Date:   Sun Feb 18 22:07:36 2018 -0500
+
+    ext4: shutdown should not prevent get_write_access
+    
+    The ext4 forced shutdown flag needs to prevent new handles from being
+    started, but it needs to allow existing handles to complete.  So the
+    forced shutdown flag should not force ext4_journal_get_write_access to
+    fail.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
+index 2d593201cf7a..7c70b08d104c 100644
+--- a/fs/ext4/ext4_jbd2.c
++++ b/fs/ext4/ext4_jbd2.c
+@@ -166,13 +166,6 @@ int __ext4_journal_get_write_access(const char *where, unsigned int line,
+ 	might_sleep();
+ 
+ 	if (ext4_handle_valid(handle)) {
+-		struct super_block *sb;
+-
+-		sb = handle->h_transaction->t_journal->j_private;
+-		if (unlikely(ext4_forced_shutdown(EXT4_SB(sb)))) {
+-			jbd2_journal_abort_handle(handle);
+-			return -EIO;
+-		}
+ 		err = jbd2_journal_get_write_access(handle, bh);
+ 		if (err)
+ 			ext4_journal_abort_handle(where, line, __func__, bh,

commit ed65b00f8de1d0687565a1ad6511901a721adb66
+Author: Theodore Ts'o 
+Date:   Sun Feb 18 21:33:13 2018 -0500
+
+    jbd2: clarify bad journal block checksum message
+    
+    There were two error messages emitted by jbd2, one for a bad checksum
+    for a jbd2 descriptor block, and one for a bad checksum for a jbd2
+    data block.  Change the data block checksum error so that the two can
+    be disambiguated.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
+index f99910b69c78..a4967b27ffb6 100644
+--- a/fs/jbd2/recovery.c
++++ b/fs/jbd2/recovery.c
+@@ -600,8 +600,8 @@ static int do_one_pass(journal_t *journal,
+ 						success = -EFSBADCRC;
+ 						printk(KERN_ERR "JBD2: Invalid "
+ 						       "checksum recovering "
+-						       "block %llu in log\n",
+-						       blocknr);
++						       "data block %llu in "
++						       "log\n", blocknr);
+ 						block_error = 1;
+ 						goto skip_write;
+ 					}

commit ccf0f32acd436b9e554303fd571f1bbf5f49d8e2
+Author: Theodore Ts'o 
+Date:   Sun Feb 18 20:53:23 2018 -0500
+
+    ext4: add tracepoints for shutdown and file system errors
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index 7e99ad02f1ba..4d1b1575f8ac 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -481,6 +481,7 @@ static int ext4_shutdown(struct super_block *sb, unsigned long arg)
+ 		return 0;
+ 
+ 	ext4_msg(sb, KERN_ALERT, "shut down requested (%d)", flags);
++	trace_ext4_shutdown(sb, flags);
+ 
+ 	switch (flags) {
+ 	case EXT4_GOING_FLAGS_DEFAULT:
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 39bf464c35f1..756f515b762d 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -448,6 +448,7 @@ void __ext4_error(struct super_block *sb, const char *function,
+ 	if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
+ 		return;
+ 
++	trace_ext4_error(sb, function, line);
+ 	if (ext4_error_ratelimit(sb)) {
+ 		va_start(args, fmt);
+ 		vaf.fmt = fmt;
+@@ -472,6 +473,7 @@ void __ext4_error_inode(struct inode *inode, const char *function,
+ 	if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
+ 		return;
+ 
++	trace_ext4_error(inode->i_sb, function, line);
+ 	es->s_last_error_ino = cpu_to_le32(inode->i_ino);
+ 	es->s_last_error_block = cpu_to_le64(block);
+ 	if (ext4_error_ratelimit(inode->i_sb)) {
+@@ -507,6 +509,7 @@ void __ext4_error_file(struct file *file, const char *function,
+ 	if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
+ 		return;
+ 
++	trace_ext4_error(inode->i_sb, function, line);
+ 	es = EXT4_SB(inode->i_sb)->s_es;
+ 	es->s_last_error_ino = cpu_to_le32(inode->i_ino);
+ 	if (ext4_error_ratelimit(inode->i_sb)) {
+@@ -719,6 +722,7 @@ __acquires(bitlock)
+ 	if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
+ 		return;
+ 
++	trace_ext4_error(sb, function, line);
+ 	es->s_last_error_ino = cpu_to_le32(ino);
+ 	es->s_last_error_block = cpu_to_le64(block);
+ 	__save_error_info(sb, function, line);
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index 4d0e3af4e561..0e31eb136c57 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -2585,6 +2585,49 @@ DEFINE_GETFSMAP_EVENT(ext4_getfsmap_low_key);
+ DEFINE_GETFSMAP_EVENT(ext4_getfsmap_high_key);
+ DEFINE_GETFSMAP_EVENT(ext4_getfsmap_mapping);
+ 
++TRACE_EVENT(ext4_shutdown,
++	TP_PROTO(struct super_block *sb, unsigned long flags),
++
++	TP_ARGS(sb, flags),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(     unsigned,	flags			)
++	),
++
++	TP_fast_assign(
++		__entry->dev	= sb->s_dev;
++		__entry->flags	= flags;
++	),
++
++	TP_printk("dev %d,%d flags %u",
++		  MAJOR(__entry->dev), MINOR(__entry->dev),
++		  __entry->flags)
++);
++
++TRACE_EVENT(ext4_error,
++	TP_PROTO(struct super_block *sb, const char *function,
++		 unsigned int line),
++
++	TP_ARGS(sb, function, line),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field( const char *,	function		)
++		__field(     unsigned,	line			)
++	),
++
++	TP_fast_assign(
++		__entry->dev	= sb->s_dev;
++		__entry->function = function;
++		__entry->line	= line;
++	),
++
++	TP_printk("dev %d,%d function %s line %u",
++		  MAJOR(__entry->dev), MINOR(__entry->dev),
++		  __entry->function, __entry->line)
++);
++
+ #endif /* _TRACE_EXT4_H */
+ 
+ /* This part must be outside protection */

commit f51667685749edadb7cad45a51003e8ebf2e8426
+Author: Theodore Ts'o 
+Date:   Sun Dec 17 22:00:59 2017 -0500
+
+    ext4: fix up remaining files with SPDX cleanups
+    
+    A number of ext4 source files were skipped due because their copyright
+    permission statements didn't match the expected text used by the
+    automated conversion utilities.  I've added SPDX tags for the rest.
+    
+    While looking at some of these files, I've noticed that we have quite
+    a bit of variation on the licenses that were used --- in particular
+    some of the Red Hat licenses on the jbd2 files use a GPL2+ license,
+    and we have some files that have a LGPL-2.1 license (which was quite
+    surprising).
+    
+    I've not attempted to do any license changes.  Even if it is perfectly
+    legal to relicense to GPL 2.0-only for consistency's sake, that should
+    be done with ext4 developer community discussion.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/acl.h b/fs/ext4/acl.h
+index a48fc5ae2701..9b63f5416a2f 100644
+--- a/fs/ext4/acl.h
++++ b/fs/ext4/acl.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++// SPDX-License-Identifier: GPL-2.0
+ /*
+   File: fs/ext4/acl.h
+ 
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 4e091eae38b1..891d7636a9d0 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++// SPDX-License-Identifier: GPL-2.0
+ /*
+  *  ext4.h
+  *
+diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h
+index 8ecf84b8f5a1..98fb0c119c68 100644
+--- a/fs/ext4/ext4_extents.h
++++ b/fs/ext4/ext4_extents.h
+@@ -1,19 +1,7 @@
++// SPDX-License-Identifier: GPL-2.0
+ /*
+  * Copyright (c) 2003-2006, Cluster File Systems, Inc, info@clusterfs.com
+  * Written by Alex Tomas 
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
+  */
+ 
+ #ifndef _EXT4_EXTENTS
+diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
+index 48143e32411c..15b6dd733780 100644
+--- a/fs/ext4/ext4_jbd2.h
++++ b/fs/ext4/ext4_jbd2.h
+@@ -1,3 +1,4 @@
++// SPDX-License-Identifier: GPL-2.0+
+ /*
+  * ext4_jbd2.h
+  *
+@@ -5,10 +6,6 @@
+  *
+  * Copyright 1998--1999 Red Hat corp --- All Rights Reserved
+  *
+- * This file is part of the Linux kernel and is made available under
+- * the terms of the GNU General Public License, version 2, or at your
+- * option, any later version, incorporated herein by reference.
+- *
+  * Ext4-specific journaling extensions.
+  */
+ 
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index c941251ac0c0..054416e9d827 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -1,3 +1,4 @@
++// SPDX-License-Identifier: GPL-2.0
+ /*
+  * Copyright (c) 2003-2006, Cluster File Systems, Inc, info@clusterfs.com
+  * Written by Alex Tomas 
+@@ -5,19 +6,6 @@
+  * Architecture independence:
+  *   Copyright (c) 2005, Bull S.A.
+  *   Written by Pierre Peiffer 
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
+  */
+ 
+ /*
+diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h
+index ca90fc96f47e..8efdeb903d6b 100644
+--- a/fs/ext4/extents_status.h
++++ b/fs/ext4/extents_status.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++// SPDX-License-Identifier: GPL-2.0
+ /*
+  *  fs/ext4/extents_status.h
+  *
+diff --git a/fs/ext4/fsmap.c b/fs/ext4/fsmap.c
+index 7ec340898598..e871c4bf18e9 100644
+--- a/fs/ext4/fsmap.c
++++ b/fs/ext4/fsmap.c
+@@ -1,21 +1,8 @@
++// SPDX-License-Identifier: GPL-2.0+
+ /*
+  * Copyright (C) 2017 Oracle.  All Rights Reserved.
+  *
+  * Author: Darrick J. Wong 
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version 2
+- * of the License, or (at your option) any later version.
+- *
+- * This program is distributed in the hope that it would be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write the Free Software Foundation,
+- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+  */
+ #include "ext4.h"
+ #include 
+diff --git a/fs/ext4/fsmap.h b/fs/ext4/fsmap.h
+index 9a2cd367cc66..68c8001fee85 100644
+--- a/fs/ext4/fsmap.h
++++ b/fs/ext4/fsmap.h
+@@ -1,21 +1,8 @@
++// SPDX-License-Identifier: GPL-2.0+
+ /*
+  * Copyright (C) 2017 Oracle.  All Rights Reserved.
+  *
+  * Author: Darrick J. Wong 
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version 2
+- * of the License, or (at your option) any later version.
+- *
+- * This program is distributed in the hope that it would be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write the Free Software Foundation,
+- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+  */
+ #ifndef __EXT4_FSMAP_H__
+ #define	__EXT4_FSMAP_H__
+diff --git a/fs/ext4/hash.c b/fs/ext4/hash.c
+index 00c6dd29e621..e22dcfab308b 100644
+--- a/fs/ext4/hash.c
++++ b/fs/ext4/hash.c
+@@ -1,12 +1,8 @@
++// SPDX-License-Identifier: GPL-2.0
+ /*
+  *  linux/fs/ext4/hash.c
+  *
+  * Copyright (C) 2002 by Theodore Ts'o
+- *
+- * This file is released under the GPL v2.
+- *
+- * This file may be redistributed under the terms of the GNU Public
+- * License.
+  */
+ 
+ #include 
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index 1367553c43bb..8b1f2901a5df 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -1,15 +1,7 @@
++// SPDX-License-Identifier: LGPL-2.1
+ /*
+  * Copyright (c) 2012 Taobao.
+  * Written by Tao Ma 
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of version 2.1 of the GNU Lesser General Public License
+- * as published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+  */
+ 
+ #include 
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index d9f8b90a93ed..1a7ea5f9276f 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -1,19 +1,7 @@
++// SPDX-License-Identifier: GPL-2.0
+ /*
+  * Copyright (c) 2003-2006, Cluster File Systems, Inc, info@clusterfs.com
+  * Written by Alex Tomas 
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
+  */
+ 
+ 
+diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
+index dcf52540f379..88c98f17e3d9 100644
+--- a/fs/ext4/mballoc.h
++++ b/fs/ext4/mballoc.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++// SPDX-License-Identifier: GPL-2.0
+ /*
+  *  fs/ext4/mballoc.h
+  *
+diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
+index cf5181b62df1..61a9d1927817 100644
+--- a/fs/ext4/migrate.c
++++ b/fs/ext4/migrate.c
+@@ -1,15 +1,8 @@
++// SPDX-License-Identifier: LGPL-2.1
+ /*
+  * Copyright IBM Corporation, 2007
+  * Author Aneesh Kumar K.V 
+  *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of version 2.1 of the GNU Lesser General Public License
+- * as published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it would be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+- *
+  */
+ 
+ #include 
+diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
+index 9bb36909ec92..b96e4bd3b3ec 100644
+--- a/fs/ext4/move_extent.c
++++ b/fs/ext4/move_extent.c
+@@ -1,16 +1,8 @@
++// SPDX-License-Identifier: LGPL-2.1
+ /*
+  * Copyright (c) 2008,2009 NEC Software Tohoku, Ltd.
+  * Written by Takashi Sato 
+  *            Akira Fujita 
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of version 2.1 of the GNU Lesser General Public License
+- * as published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+  */
+ 
+ #include 
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 7c46693a14d7..e5b9a305ff72 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1,3 +1,4 @@
++// SPDX-License-Identifier: GPL-2.0
+ /*
+  *  linux/fs/ext4/super.c
+  *
+diff --git a/fs/ext4/truncate.h b/fs/ext4/truncate.h
+index b64a9fa0ff41..0cb13badf473 100644
+--- a/fs/ext4/truncate.h
++++ b/fs/ext4/truncate.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++// SPDX-License-Identifier: GPL-2.0
+ /*
+  * linux/fs/ext4/truncate.h
+  *
+diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
+index f8cc07588ac9..dd54c4f995c8 100644
+--- a/fs/ext4/xattr.h
++++ b/fs/ext4/xattr.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++// SPDX-License-Identifier: GPL-2.0
+ /*
+   File: fs/ext4/xattr.h
+ 
+diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
+index 4055f51617ef..c125d662777c 100644
+--- a/fs/jbd2/checkpoint.c
++++ b/fs/jbd2/checkpoint.c
+@@ -1,3 +1,4 @@
++// SPDX-License-Identifier: GPL-2.0+
+ /*
+  * linux/fs/jbd2/checkpoint.c
+  *
+@@ -5,10 +6,6 @@
+  *
+  * Copyright 1999 Red Hat Software --- All Rights Reserved
+  *
+- * This file is part of the Linux kernel and is made available under
+- * the terms of the GNU General Public License, version 2, or at your
+- * option, any later version, incorporated herein by reference.
+- *
+  * Checkpoint routines for the generic filesystem journaling code.
+  * Part of the ext2fs journaling system.
+  *
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index 3c1c31321d9b..8de0e7723316 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -1,3 +1,4 @@
++// SPDX-License-Identifier: GPL-2.0+
+ /*
+  * linux/fs/jbd2/commit.c
+  *
+@@ -5,10 +6,6 @@
+  *
+  * Copyright 1998 Red Hat corp --- All Rights Reserved
+  *
+- * This file is part of the Linux kernel and is made available under
+- * the terms of the GNU General Public License, version 2, or at your
+- * option, any later version, incorporated herein by reference.
+- *
+  * Journal commit routines for the generic filesystem journaling code;
+  * part of the ext2fs journaling system.
+  */
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 67546c7ad473..3fbf48ec2188 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -1,3 +1,4 @@
++// SPDX-License-Identifier: GPL-2.0+
+ /*
+  * linux/fs/jbd2/journal.c
+  *
+@@ -5,10 +6,6 @@
+  *
+  * Copyright 1998 Red Hat corp --- All Rights Reserved
+  *
+- * This file is part of the Linux kernel and is made available under
+- * the terms of the GNU General Public License, version 2, or at your
+- * option, any later version, incorporated herein by reference.
+- *
+  * Generic filesystem journal-writing code; part of the ext2fs
+  * journaling system.
+  *
+diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
+index 02dd3360cb20..f99910b69c78 100644
+--- a/fs/jbd2/recovery.c
++++ b/fs/jbd2/recovery.c
+@@ -1,3 +1,4 @@
++// SPDX-License-Identifier: GPL-2.0+
+ /*
+  * linux/fs/jbd2/recovery.c
+  *
+@@ -5,10 +6,6 @@
+  *
+  * Copyright 1999-2000 Red Hat Software --- All Rights Reserved
+  *
+- * This file is part of the Linux kernel and is made available under
+- * the terms of the GNU General Public License, version 2, or at your
+- * option, any later version, incorporated herein by reference.
+- *
+  * Journal recovery routines for the generic filesystem journaling code;
+  * part of the ext2fs journaling system.
+  */
+diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c
+index f9aefcda5854..696ef15ec942 100644
+--- a/fs/jbd2/revoke.c
++++ b/fs/jbd2/revoke.c
+@@ -1,3 +1,4 @@
++// SPDX-License-Identifier: GPL-2.0+
+ /*
+  * linux/fs/jbd2/revoke.c
+  *
+@@ -5,10 +6,6 @@
+  *
+  * Copyright 2000 Red Hat corp --- All Rights Reserved
+  *
+- * This file is part of the Linux kernel and is made available under
+- * the terms of the GNU General Public License, version 2, or at your
+- * option, any later version, incorporated herein by reference.
+- *
+  * Journal revoke routines for the generic filesystem journaling code;
+  * part of the ext2fs journaling system.
+  *
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index 8b08044b3120..881a9e09ca4e 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -1,3 +1,4 @@
++// SPDX-License-Identifier: GPL-2.0+
+ /*
+  * linux/fs/jbd2/transaction.c
+  *
+@@ -5,10 +6,6 @@
+  *
+  * Copyright 1998 Red Hat corp --- All Rights Reserved
+  *
+- * This file is part of the Linux kernel and is made available under
+- * the terms of the GNU General Public License, version 2, or at your
+- * option, any later version, incorporated herein by reference.
+- *
+  * Generic filesystem transaction handling code; part of the ext2fs
+  * journaling system.
+  *

commit 996fc4477a0ea28226b30d175f053fb6f9a4fa36
+Author: Theodore Ts'o 
+Date:   Sun Dec 10 23:44:11 2017 -0500
+
+    ext4: add missing error check in __ext4_new_inode()
+    
+    It's possible for ext4_get_acl() to return an ERR_PTR.  So we need to
+    add a check for this case in __ext4_new_inode().  Otherwise on an
+    error we can end up oops the kernel.
+    
+    This was getting triggered by xfstests generic/388, which is a test
+    which exercises the shutdown code path.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index b4267d72f249..b32cf263750d 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -816,6 +816,8 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
+ #ifdef CONFIG_EXT4_FS_POSIX_ACL
+ 		struct posix_acl *p = get_acl(dir, ACL_TYPE_DEFAULT);
+ 
++		if (IS_ERR(p))
++			return ERR_CAST(p);
+ 		if (p) {
+ 			int acl_size = p->a_count * sizeof(ext4_acl_entry);
+ 

commit 232530680290ba94ca37852ab10d9556ea28badf
+Author: Theodore Ts'o 
+Date:   Wed Nov 8 22:23:20 2017 -0500
+
+    ext4: improve smp scalability for inode generation
+    
+    ->s_next_generation is protected by s_next_gen_lock but its usage
+    pattern is very primitive.  We don't actually need sequentially
+    increasing new generation numbers, so let's use prandom_u32() instead.
+    
+    Reported-by: Dmitry Monakhov 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 53ce95b52fd8..5e6d7b6f50c7 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1355,8 +1355,6 @@ struct ext4_sb_info {
+ 	int s_first_ino;
+ 	unsigned int s_inode_readahead_blks;
+ 	unsigned int s_inode_goal;
+-	spinlock_t s_next_gen_lock;
+-	u32 s_next_generation;
+ 	u32 s_hash_seed[4];
+ 	int s_def_hash_version;
+ 	int s_hash_unsigned;	/* 3 if hash should be signed, 0 if not */
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index ee823022aa34..da79eb5dba40 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -1138,9 +1138,7 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
+ 			   inode->i_ino);
+ 		goto out;
+ 	}
+-	spin_lock(&sbi->s_next_gen_lock);
+-	inode->i_generation = sbi->s_next_generation++;
+-	spin_unlock(&sbi->s_next_gen_lock);
++	inode->i_generation = prandom_u32();
+ 
+ 	/* Precompute checksum seed for inode metadata */
+ 	if (ext4_has_metadata_csum(sb)) {
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index 144bbda2b808..23a4766f6678 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -14,6 +14,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -98,7 +99,6 @@ static long swap_inode_boot_loader(struct super_block *sb,
+ 	int err;
+ 	struct inode *inode_bl;
+ 	struct ext4_inode_info *ei_bl;
+-	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 
+ 	if (inode->i_nlink != 1 || !S_ISREG(inode->i_mode))
+ 		return -EINVAL;
+@@ -157,10 +157,8 @@ static long swap_inode_boot_loader(struct super_block *sb,
+ 
+ 	inode->i_ctime = inode_bl->i_ctime = current_time(inode);
+ 
+-	spin_lock(&sbi->s_next_gen_lock);
+-	inode->i_generation = sbi->s_next_generation++;
+-	inode_bl->i_generation = sbi->s_next_generation++;
+-	spin_unlock(&sbi->s_next_gen_lock);
++	inode->i_generation = prandom_u32();
++	inode_bl->i_generation = prandom_u32();
+ 
+ 	ext4_discard_preallocations(inode);
+ 
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 3a278faf5868..9f2e3eb5131f 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3982,8 +3982,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	}
+ 
+ 	sbi->s_gdb_count = db_count;
+-	get_random_bytes(&sbi->s_next_generation, sizeof(u32));
+-	spin_lock_init(&sbi->s_next_gen_lock);
+ 
+ 	timer_setup(&sbi->s_err_report, print_daily_error_info, 0);
+ 

commit 51e3ae81ec58e95f10a98ef3dd6d7bce5d8e35a2
+Author: Theodore Ts'o 
+Date:   Fri Oct 6 23:09:55 2017 -0400
+
+    ext4: fix interaction between i_size, fallocate, and delalloc after a crash
+    
+    If there are pending writes subject to delayed allocation, then i_size
+    will show size after the writes have completed, while i_disksize
+    contains the value of i_size on the disk (since the writes have not
+    been persisted to disk).
+    
+    If fallocate(2) is called with the FALLOC_FL_KEEP_SIZE flag, either
+    with or without the FALLOC_FL_ZERO_RANGE flag set, and the new size
+    after the fallocate(2) is between i_size and i_disksize, then after a
+    crash, if a journal commit has resulted in the changes made by the
+    fallocate() call to be persisted after a crash, but the delayed
+    allocation write has not resolved itself, i_size would not be updated,
+    and this would cause the following e2fsck complaint:
+    
+    Inode 12, end of extent exceeds allowed value
+            (logical block 33, physical block 33441, len 7)
+    
+    This can only take place on a sparse file, where the fallocate(2) call
+    is allocating blocks in a range which is before a pending delayed
+    allocation write which is extending i_size.  Since this situation is
+    quite rare, and the window in which the crash must take place is
+    typically < 30 seconds, in practice this condition will rarely happen.
+    
+    Nevertheless, it can be triggered in testing, and in particular by
+    xfstests generic/456.
+    
+    Signed-off-by: Theodore Ts'o 
+    Reported-by: Amir Goldstein 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 97f0fd06728d..07bca11749d4 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -4794,7 +4794,8 @@ static long ext4_zero_range(struct file *file, loff_t offset,
+ 	}
+ 
+ 	if (!(mode & FALLOC_FL_KEEP_SIZE) &&
+-	     offset + len > i_size_read(inode)) {
++	    (offset + len > i_size_read(inode) ||
++	     offset + len > EXT4_I(inode)->i_disksize)) {
+ 		new_size = offset + len;
+ 		ret = inode_newsize_ok(inode, new_size);
+ 		if (ret)
+@@ -4965,7 +4966,8 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
+ 	}
+ 
+ 	if (!(mode & FALLOC_FL_KEEP_SIZE) &&
+-	     offset + len > i_size_read(inode)) {
++	    (offset + len > i_size_read(inode) ||
++	     offset + len > EXT4_I(inode)->i_disksize)) {
+ 		new_size = offset + len;
+ 		ret = inode_newsize_ok(inode, new_size);
+ 		if (ret)

commit 68fd97504ad2f70850c47ce45caa110a0ca843d2
+Author: Theodore Ts'o 
+Date:   Sun Oct 1 17:59:54 2017 -0400
+
+    ext4: retry allocations conservatively
+    
+    Now that we no longer try to reserve metadata blocks for delayed
+    allocations (which tended to overestimate the required number of
+    blocks significantly), we really don't need retry allocations when the
+    disk is very full as aggressively any more.
+    
+    The only time when it makes sense to retry an allocation is if we have
+    freshly deleted blocks that will only become available after a
+    transaction commit.  And if we lose that race, it's not worth it to
+    try more than once.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index e04ec868e37e..a3798b25a8dc 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -600,22 +600,21 @@ int ext4_claim_free_clusters(struct ext4_sb_info *sbi,
+  * ext4_should_retry_alloc() is called when ENOSPC is returned, and if
+  * it is profitable to retry the operation, this function will wait
+  * for the current or committing transaction to complete, and then
+- * return TRUE.
+- *
+- * if the total number of retries exceed three times, return FALSE.
++ * return TRUE.  We will only retry once.
+  */
+ int ext4_should_retry_alloc(struct super_block *sb, int *retries)
+ {
+ 	if (!ext4_has_free_clusters(EXT4_SB(sb), 1, 0) ||
+-	    (*retries)++ > 3 ||
++	    (*retries)++ > 1 ||
+ 	    !EXT4_SB(sb)->s_journal)
+ 		return 0;
+ 
+-	jbd_debug(1, "%s: retrying operation after ENOSPC\n", sb->s_id);
+-
+ 	smp_mb();
+-	if (EXT4_SB(sb)->s_mb_free_pending)
+-		jbd2_journal_force_commit_nested(EXT4_SB(sb)->s_journal);
++	if (EXT4_SB(sb)->s_mb_free_pending == 0)
++		return 0;
++
++	jbd_debug(1, "%s: retrying operation after ENOSPC\n", sb->s_id);
++	jbd2_journal_force_commit_nested(EXT4_SB(sb)->s_journal);
+ 	return 1;
+ }
+ 

commit b80b32b6d5e79798b85cd4644206aaa069059390
+Author: Theodore Ts'o 
+Date:   Mon Aug 14 08:29:18 2017 -0400
+
+    ext4: fix clang build regression
+    
+    Arnd Bergmann 
+    
+    As Stefan pointed out, I misremembered what clang can do specifically,
+    and it turns out that the variable-length array at the end of the
+    structure did not work (a flexible array would have worked here
+    but not solved the problem):
+    
+    fs/ext4/mballoc.c:2303:17: error: fields must have a constant size:
+    'variable length array in structure' extension will never be supported
+                    ext4_grpblk_t counters[blocksize_bits + 2];
+    
+    This reverts part of my previous patch, using a fixed-size array
+    again, but keeping the check for the array overflow.
+    
+    Fixes: 2df2c3402fc8 ("ext4: fix warning about stack corruption")
+    Reported-by: Stefan Agner 
+    Tested-by: Chandan Rajendra 
+    Signed-off-by: Arnd Bergmann 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 5a1052627a81..701085620cd8 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2300,7 +2300,7 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v)
+ 					     EXT4_MAX_BLOCK_LOG_SIZE);
+ 	struct sg {
+ 		struct ext4_group_info info;
+-		ext4_grpblk_t counters[blocksize_bits + 2];
++		ext4_grpblk_t counters[EXT4_MAX_BLOCK_LOG_SIZE + 2];
+ 	} sg;
+ 
+ 	group--;
+@@ -2309,6 +2309,9 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v)
+ 			      " 2^0   2^1   2^2   2^3   2^4   2^5   2^6  "
+ 			      " 2^7   2^8   2^9   2^10  2^11  2^12  2^13  ]\n");
+ 
++	i = (blocksize_bits + 2) * sizeof(sg.info.bb_counters[0]) +
++		sizeof(struct ext4_group_info);
++
+ 	grinfo = ext4_get_group_info(sb, group);
+ 	/* Load the group info in memory only if not already loaded. */
+ 	if (unlikely(EXT4_MB_GRP_NEED_INIT(grinfo))) {
+@@ -2320,7 +2323,7 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v)
+ 		buddy_loaded = 1;
+ 	}
+ 
+-	memcpy(&sg, ext4_get_group_info(sb, group), sizeof(sg));
++	memcpy(&sg, ext4_get_group_info(sb, group), i);
+ 
+ 	if (buddy_loaded)
+ 		ext4_mb_unload_buddy(&e4b);

commit eecabf567422eda02bd179f2707d8fe24f52d888
+Author: Theodore Ts'o 
+Date:   Thu Jun 8 04:16:59 2017 -0400
+
+    random: suppress spammy warnings about unseeded randomness
+    
+    Unfortunately, on some models of some architectures getting a fully
+    seeded CRNG is extremely difficult, and so this can result in dmesg
+    getting spammed for a surprisingly long time.  This is really bad from
+    a security perspective, and so architecture maintainers really need to
+    do what they can to get the CRNG seeded sooner after the system is
+    booted.  However, users can't do anything actionble to address this,
+    and spamming the kernel messages log will only just annoy people.
+    
+    For developers who want to work on improving this situation,
+    CONFIG_WARN_UNSEEDED_RANDOM has been renamed to
+    CONFIG_WARN_ALL_UNSEEDED_RANDOM.  By default the kernel will always
+    print the first use of unseeded randomness.  This way, hopefully the
+    security obsessed will be happy that there is _some_ indication when
+    the kernel boots there may be a potential issue with that architecture
+    or subarchitecture.  To see all uses of unseeded randomness,
+    developers can enable CONFIG_WARN_ALL_UNSEEDED_RANDOM.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index fa5bbd5a7ca0..799d37981d99 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -436,6 +436,7 @@ static void _extract_crng(struct crng_state *crng,
+ static void _crng_backtrack_protect(struct crng_state *crng,
+ 				    __u8 tmp[CHACHA20_BLOCK_SIZE], int used);
+ static void process_random_ready_list(void);
++static void _get_random_bytes(void *buf, int nbytes);
+ 
+ /**********************************************************************
+  *
+@@ -776,7 +777,7 @@ static void crng_initialize(struct crng_state *crng)
+ 		_extract_entropy(&input_pool, &crng->state[4],
+ 				 sizeof(__u32) * 12, 0);
+ 	else
+-		get_random_bytes(&crng->state[4], sizeof(__u32) * 12);
++		_get_random_bytes(&crng->state[4], sizeof(__u32) * 12);
+ 	for (i = 4; i < 16; i++) {
+ 		if (!arch_get_random_seed_long(&rv) &&
+ 		    !arch_get_random_long(&rv))
+@@ -1466,6 +1467,30 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
+ 	return ret;
+ }
+ 
++#define warn_unseeded_randomness(previous) \
++	_warn_unseeded_randomness(__func__, (void *) _RET_IP_, (previous))
++
++static void _warn_unseeded_randomness(const char *func_name, void *caller,
++				      void **previous)
++{
++#ifdef CONFIG_WARN_ALL_UNSEEDED_RANDOM
++	const bool print_once = false;
++#else
++	static bool print_once __read_mostly;
++#endif
++
++	if (print_once ||
++	    crng_ready() ||
++	    (previous && (caller == READ_ONCE(*previous))))
++		return;
++	WRITE_ONCE(*previous, caller);
++#ifndef CONFIG_WARN_ALL_UNSEEDED_RANDOM
++	print_once = true;
++#endif
++	pr_notice("random: %s called from %pF with crng_init=%d\n",
++		  func_name, caller, crng_init);
++}
++
+ /*
+  * This function is the exported kernel interface.  It returns some
+  * number of good random numbers, suitable for key generation, seeding
+@@ -1476,15 +1501,10 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
+  * wait_for_random_bytes() should be called and return 0 at least once
+  * at any point prior.
+  */
+-void get_random_bytes(void *buf, int nbytes)
++static void _get_random_bytes(void *buf, int nbytes)
+ {
+ 	__u8 tmp[CHACHA20_BLOCK_SIZE];
+ 
+-#ifdef CONFIG_WARN_UNSEEDED_RANDOM
+-	if (!crng_ready())
+-		printk(KERN_NOTICE "random: %pF get_random_bytes called "
+-		       "with crng_init = %d\n", (void *) _RET_IP_, crng_init);
+-#endif
+ 	trace_get_random_bytes(nbytes, _RET_IP_);
+ 
+ 	while (nbytes >= CHACHA20_BLOCK_SIZE) {
+@@ -1501,6 +1521,14 @@ void get_random_bytes(void *buf, int nbytes)
+ 		crng_backtrack_protect(tmp, CHACHA20_BLOCK_SIZE);
+ 	memzero_explicit(tmp, sizeof(tmp));
+ }
++
++void get_random_bytes(void *buf, int nbytes)
++{
++	static void *previous;
++
++	warn_unseeded_randomness(&previous);
++	_get_random_bytes(buf, nbytes);
++}
+ EXPORT_SYMBOL(get_random_bytes);
+ 
+ /*
+@@ -2064,6 +2092,7 @@ u64 get_random_u64(void)
+ 	bool use_lock = READ_ONCE(crng_init) < 2;
+ 	unsigned long flags = 0;
+ 	struct batched_entropy *batch;
++	static void *previous;
+ 
+ #if BITS_PER_LONG == 64
+ 	if (arch_get_random_long((unsigned long *)&ret))
+@@ -2074,11 +2103,7 @@ u64 get_random_u64(void)
+ 	    return ret;
+ #endif
+ 
+-#ifdef CONFIG_WARN_UNSEEDED_RANDOM
+-	if (!crng_ready())
+-		printk(KERN_NOTICE "random: %pF get_random_u64 called "
+-		       "with crng_init = %d\n", (void *) _RET_IP_, crng_init);
+-#endif
++	warn_unseeded_randomness(&previous);
+ 
+ 	batch = &get_cpu_var(batched_entropy_u64);
+ 	if (use_lock)
+@@ -2102,15 +2127,12 @@ u32 get_random_u32(void)
+ 	bool use_lock = READ_ONCE(crng_init) < 2;
+ 	unsigned long flags = 0;
+ 	struct batched_entropy *batch;
++	static void *previous;
+ 
+ 	if (arch_get_random_int(&ret))
+ 		return ret;
+ 
+-#ifdef CONFIG_WARN_UNSEEDED_RANDOM
+-	if (!crng_ready())
+-		printk(KERN_NOTICE "random: %pF get_random_u32 called "
+-		       "with crng_init = %d\n", (void *) _RET_IP_, crng_init);
+-#endif
++	warn_unseeded_randomness(&previous);
+ 
+ 	batch = &get_cpu_var(batched_entropy_u32);
+ 	if (use_lock)
+diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
+index c4159605bfbf..9d0a244074b9 100644
+--- a/lib/Kconfig.debug
++++ b/lib/Kconfig.debug
+@@ -1209,10 +1209,9 @@ config STACKTRACE
+ 	  It is also used by various kernel debugging features that require
+ 	  stack trace generation.
+ 
+-config WARN_UNSEEDED_RANDOM
+-	bool "Warn when kernel uses unseeded randomness"
+-	default y
+-	depends on DEBUG_KERNEL
++config WARN_ALL_UNSEEDED_RANDOM
++	bool "Warn for all uses of unseeded randomness"
++	default n
+ 	help
+ 	  Some parts of the kernel contain bugs relating to their use of
+ 	  cryptographically secure random numbers before it's actually possible
+@@ -1222,8 +1221,21 @@ config WARN_UNSEEDED_RANDOM
+ 	  are going wrong, so that they might contact developers about fixing
+ 	  it.
+ 
+-	  Say Y here, unless you simply do not care about using unseeded
+-	  randomness and do not want a potential warning message in your logs.
++	  Unfortunately, on some models of some architectures getting
++	  a fully seeded CRNG is extremely difficult, and so this can
++	  result in dmesg getting spammed for a surprisingly long
++	  time.  This is really bad from a security perspective, and
++	  so architecture maintainers really need to do what they can
++	  to get the CRNG seeded sooner after the system is booted.
++	  However, since users can not do anything actionble to
++	  address this, by default the kernel will issue only a single
++	  warning for the first use of unseeded randomness.
++
++	  Say Y here if you want to receive warnings for all uses of
++	  unseeded randomness.  This will be of use primarily for
++	  those developers interersted in improving the security of
++	  Linux kernels running on their architecture (or
++	  subarchitecture).
+ 
+ config DEBUG_KOBJECT
+ 	bool "kobject debugging"

commit bdddf342796765a1a946e7c4aed2574f4488e4e5
+Author: Theodore Ts'o 
+Date:   Fri Jun 23 00:47:05 2017 -0400
+
+    ext4: return EFSBADCRC if a bad checksum error is found in ext4_find_entry()
+    
+    Previously a bad directory block with a bad checksum is skipped; we
+    should be returning EFSBADCRC (aka EBADMSG).
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 2a7f2dc7f4dd..13f0cadb1238 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1456,7 +1456,8 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
+ 			EXT4_ERROR_INODE(dir, "checksumming directory "
+ 					 "block %lu", (unsigned long)block);
+ 			brelse(bh);
+-			goto next;
++			ret = ERR_PTR(-EFSBADCRC);
++			goto cleanup_and_exit;
+ 		}
+ 		set_buffer_verified(bh);
+ 		i = search_dirblock(bh, dir, &fname,

commit 92e75428ffc90e2a0321062379f883f3671cfebe
+Author: Theodore Ts'o 
+Date:   Wed Jun 7 19:01:32 2017 -0400
+
+    random: use lockless method of accessing and updating f->reg_idx
+    
+    Linus pointed out that there is a much more efficient way of avoiding
+    the problem that we were trying to address in commit 9dfa7bba35ac0:
+    "fix race in drivers/char/random.c:get_reg()".
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index a561f0c2f428..473ad34378f2 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -1097,15 +1097,15 @@ static void add_interrupt_bench(cycles_t start)
+ static __u32 get_reg(struct fast_pool *f, struct pt_regs *regs)
+ {
+ 	__u32 *ptr = (__u32 *) regs;
+-	unsigned long flags;
++	unsigned int idx;
+ 
+ 	if (regs == NULL)
+ 		return 0;
+-	local_irq_save(flags);
+-	if (f->reg_idx >= sizeof(struct pt_regs) / sizeof(__u32))
+-		f->reg_idx = 0;
+-	ptr += f->reg_idx++;
+-	local_irq_restore(flags);
++	idx = READ_ONCE(f->reg_idx);
++	if (idx >= sizeof(struct pt_regs) / sizeof(__u32))
++		idx = 0;
++	ptr += idx++;
++	WRITE_ONCE(f->reg_idx, idx);
+ 	return *ptr;
+ }
+ 

commit 72d622b42258a0ed0b6e8c0f40d7628de935d058
+Author: Theodore Ts'o 
+Date:   Sun Apr 30 20:08:05 2017 -0400
+
+    ext4: replace BUG_ON with WARN_ONCE in ext4_end_bio()
+    
+    Add fallback code and a WARN_ONCE() call instead of a BUG_ON() in
+    the ext4_end_bio() function.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
+index 208241b06662..1a82138ba739 100644
+--- a/fs/ext4/page-io.c
++++ b/fs/ext4/page-io.c
+@@ -297,8 +297,17 @@ static void ext4_end_bio(struct bio *bio)
+ {
+ 	ext4_io_end_t *io_end = bio->bi_private;
+ 	sector_t bi_sector = bio->bi_iter.bi_sector;
++	char b[BDEVNAME_SIZE];
+ 
+-	BUG_ON(!io_end);
++	if (WARN_ONCE(!io_end, "io_end is NULL: %s: sector %Lu len %u err %d\n",
++		      bdevname(bio->bi_bdev, b),
++		      (long long) bio->bi_iter.bi_sector,
++		      (unsigned) bio_sectors(bio),
++		      bio->bi_error)) {
++		ext4_finish_bio(bio);
++		bio_put(bio);
++		return;
++	}
+ 	bio->bi_end_io = NULL;
+ 
+ 	if (bio->bi_error) {

commit 80a2ea9f85850f1cdae814be03b4a16c3d3abc00
+Author: Theodore Ts'o 
+Date:   Fri Apr 28 09:51:54 2017 -0400
+
+    mm: retry writepages() on ENOMEM when doing an data integrity writeback
+    
+    Currently, file system's writepages() function must not fail with an
+    ENOMEM, since if they do, it's possible for buffered data to be lost.
+    This is because on a data integrity writeback writepages() gets called
+    but once, and if it returns ENOMEM, if you're lucky the error will get
+    reflected back to the userspace process calling fsync().  If you
+    aren't lucky, the user is unmounting the file system, and the dirty
+    pages will simply be lost.
+    
+    For this reason, file system code generally will use GFP_NOFS, and in
+    some cases, will retry the allocation in a loop, on the theory that
+    "kernel livelocks are temporary; data loss is forever".
+    Unfortunately, this can indeed cause livelocks, since inside the
+    writepages() call, the file system is holding various mutexes, and
+    these mutexes may prevent the OOM killer from killing its targetted
+    victim if it is also holding on to those mutexes.
+    
+    A better solution would be to allow writepages() to call the memory
+    allocator with flags that give greater latitude to the allocator to
+    fail, and then release its locks and return ENOMEM, and in the case of
+    background writeback, the writes can be retried at a later time.  In
+    the case of data-integrity writeback retry after waiting a brief
+    amount of time.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/mm/page-writeback.c b/mm/page-writeback.c
+index d8ac2a7fb9e7..03a70d8a6030 100644
+--- a/mm/page-writeback.c
++++ b/mm/page-writeback.c
+@@ -2353,10 +2353,16 @@ int do_writepages(struct address_space *mapping, struct writeback_control *wbc)
+ 
+ 	if (wbc->nr_to_write <= 0)
+ 		return 0;
+-	if (mapping->a_ops->writepages)
+-		ret = mapping->a_ops->writepages(mapping, wbc);
+-	else
+-		ret = generic_writepages(mapping, wbc);
++	while (1) {
++		if (mapping->a_ops->writepages)
++			ret = mapping->a_ops->writepages(mapping, wbc);
++		else
++			ret = generic_writepages(mapping, wbc);
++		if ((ret != -ENOMEM) || (wbc->sync_mode != WB_SYNC_ALL))
++			break;
++		cond_resched();
++		congestion_wait(BLK_RW_ASYNC, HZ/50);
++	}
+ 	return ret;
+ }
+ 

commit d67d64f423147cf4fe8212658255e1160a4ef02c
+Author: Theodore Ts'o 
+Date:   Sat Mar 25 17:33:31 2017 -0400
+
+    ext4: fix two spelling nits
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index f622d4a577e3..f303d3a7f44a 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -5400,7 +5400,7 @@ int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ 	 * If there is inline data in the inode, the inode will normally not
+ 	 * have data blocks allocated (it may have an external xattr block).
+ 	 * Report at least one sector for such files, so tools like tar, rsync,
+-	 * others doen't incorrectly think the file is completely sparse.
++	 * others don't incorrectly think the file is completely sparse.
+ 	 */
+ 	if (unlikely(ext4_has_inline_data(inode)))
+ 		stat->blocks += (stat->size + 511) >> 9;
+diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
+index 6fc14def0c70..615bc03d0fbd 100644
+--- a/fs/ext4/move_extent.c
++++ b/fs/ext4/move_extent.c
+@@ -511,7 +511,7 @@ mext_check_arguments(struct inode *orig_inode,
+ 	if ((orig_start & ~(PAGE_MASK >> orig_inode->i_blkbits)) !=
+ 	    (donor_start & ~(PAGE_MASK >> orig_inode->i_blkbits))) {
+ 		ext4_debug("ext4 move extent: orig and donor's start "
+-			"offset are not alligned [ino:orig %lu, donor %lu]\n",
++			"offsets are not aligned [ino:orig %lu, donor %lu]\n",
+ 			orig_inode->i_ino, donor_inode->i_ino);
+ 		return -EINVAL;
+ 	}

commit dac7a4b4b1f664934e8b713f529b629f67db313c
+Author: Theodore Ts'o 
+Date:   Sat Mar 25 17:22:47 2017 -0400
+
+    ext4: lock the xattr block before checksuming it
+    
+    We must lock the xattr block before calculating or verifying the
+    checksum in order to avoid spurious checksum failures.
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=193661
+    
+    Reported-by: Colin Ian King 
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 67636acf7624..996e7900d4c8 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -131,31 +131,26 @@ static __le32 ext4_xattr_block_csum(struct inode *inode,
+ }
+ 
+ static int ext4_xattr_block_csum_verify(struct inode *inode,
+-					sector_t block_nr,
+-					struct ext4_xattr_header *hdr)
++					struct buffer_head *bh)
+ {
+-	if (ext4_has_metadata_csum(inode->i_sb) &&
+-	    (hdr->h_checksum != ext4_xattr_block_csum(inode, block_nr, hdr)))
+-		return 0;
+-	return 1;
+-}
+-
+-static void ext4_xattr_block_csum_set(struct inode *inode,
+-				      sector_t block_nr,
+-				      struct ext4_xattr_header *hdr)
+-{
+-	if (!ext4_has_metadata_csum(inode->i_sb))
+-		return;
++	struct ext4_xattr_header *hdr = BHDR(bh);
++	int ret = 1;
+ 
+-	hdr->h_checksum = ext4_xattr_block_csum(inode, block_nr, hdr);
++	if (ext4_has_metadata_csum(inode->i_sb)) {
++		lock_buffer(bh);
++		ret = (hdr->h_checksum == ext4_xattr_block_csum(inode,
++							bh->b_blocknr, hdr));
++		unlock_buffer(bh);
++	}
++	return ret;
+ }
+ 
+-static inline int ext4_handle_dirty_xattr_block(handle_t *handle,
+-						struct inode *inode,
+-						struct buffer_head *bh)
++static void ext4_xattr_block_csum_set(struct inode *inode,
++				      struct buffer_head *bh)
+ {
+-	ext4_xattr_block_csum_set(inode, bh->b_blocknr, BHDR(bh));
+-	return ext4_handle_dirty_metadata(handle, inode, bh);
++	if (ext4_has_metadata_csum(inode->i_sb))
++		BHDR(bh)->h_checksum = ext4_xattr_block_csum(inode,
++						bh->b_blocknr, BHDR(bh));
+ }
+ 
+ static inline const struct xattr_handler *
+@@ -233,7 +228,7 @@ ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh)
+ 	if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) ||
+ 	    BHDR(bh)->h_blocks != cpu_to_le32(1))
+ 		return -EFSCORRUPTED;
+-	if (!ext4_xattr_block_csum_verify(inode, bh->b_blocknr, BHDR(bh)))
++	if (!ext4_xattr_block_csum_verify(inode, bh))
+ 		return -EFSBADCRC;
+ 	error = ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size,
+ 				       bh->b_data);
+@@ -618,23 +613,22 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode,
+ 			}
+ 		}
+ 
++		ext4_xattr_block_csum_set(inode, bh);
+ 		/*
+ 		 * Beware of this ugliness: Releasing of xattr block references
+ 		 * from different inodes can race and so we have to protect
+ 		 * from a race where someone else frees the block (and releases
+ 		 * its journal_head) before we are done dirtying the buffer. In
+ 		 * nojournal mode this race is harmless and we actually cannot
+-		 * call ext4_handle_dirty_xattr_block() with locked buffer as
++		 * call ext4_handle_dirty_metadata() with locked buffer as
+ 		 * that function can call sync_dirty_buffer() so for that case
+ 		 * we handle the dirtying after unlocking the buffer.
+ 		 */
+ 		if (ext4_handle_valid(handle))
+-			error = ext4_handle_dirty_xattr_block(handle, inode,
+-							      bh);
++			error = ext4_handle_dirty_metadata(handle, inode, bh);
+ 		unlock_buffer(bh);
+ 		if (!ext4_handle_valid(handle))
+-			error = ext4_handle_dirty_xattr_block(handle, inode,
+-							      bh);
++			error = ext4_handle_dirty_metadata(handle, inode, bh);
+ 		if (IS_SYNC(inode))
+ 			ext4_handle_sync(handle);
+ 		dquot_free_block(inode, EXT4_C2B(EXT4_SB(inode->i_sb), 1));
+@@ -863,13 +857,14 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
+ 				ext4_xattr_cache_insert(ext4_mb_cache,
+ 					bs->bh);
+ 			}
++			ext4_xattr_block_csum_set(inode, bs->bh);
+ 			unlock_buffer(bs->bh);
+ 			if (error == -EFSCORRUPTED)
+ 				goto bad_block;
+ 			if (!error)
+-				error = ext4_handle_dirty_xattr_block(handle,
+-								      inode,
+-								      bs->bh);
++				error = ext4_handle_dirty_metadata(handle,
++								   inode,
++								   bs->bh);
+ 			if (error)
+ 				goto cleanup;
+ 			goto inserted;
+@@ -967,10 +962,11 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
+ 					ce->e_reusable = 0;
+ 				ea_bdebug(new_bh, "reusing; refcount now=%d",
+ 					  ref);
++				ext4_xattr_block_csum_set(inode, new_bh);
+ 				unlock_buffer(new_bh);
+-				error = ext4_handle_dirty_xattr_block(handle,
+-								      inode,
+-								      new_bh);
++				error = ext4_handle_dirty_metadata(handle,
++								   inode,
++								   new_bh);
+ 				if (error)
+ 					goto cleanup_dquot;
+ 			}
+@@ -1020,11 +1016,12 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
+ 				goto getblk_failed;
+ 			}
+ 			memcpy(new_bh->b_data, s->base, new_bh->b_size);
++			ext4_xattr_block_csum_set(inode, new_bh);
+ 			set_buffer_uptodate(new_bh);
+ 			unlock_buffer(new_bh);
+ 			ext4_xattr_cache_insert(ext4_mb_cache, new_bh);
+-			error = ext4_handle_dirty_xattr_block(handle,
+-							      inode, new_bh);
++			error = ext4_handle_dirty_metadata(handle, inode,
++							   new_bh);
+ 			if (error)
+ 				goto cleanup;
+ 		}

commit e9be2ac7c09cabcbbbb12b0869e49b7a715d6fb5
+Author: Theodore Ts'o 
+Date:   Mon Feb 20 15:34:59 2017 -0500
+
+    ext4: rename EXT4_IOC_GOINGDOWN to EXT4_IOC_SHUTDOWN
+    
+    It's very likely the file system independent ioctl name will be
+    FS_IOC_SHUTDOWN, so let's use the same name for the ext4 ioctl name.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 55b7a77a0444..3a87378b9563 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -679,7 +679,7 @@ struct fsxattr {
+ #define EXT4_IOC_FSGETXATTR		FS_IOC_FSGETXATTR
+ #define EXT4_IOC_FSSETXATTR		FS_IOC_FSSETXATTR
+ 
+-#define EXT4_IOC_GOINGDOWN _IOR ('X', 125, __u32)
++#define EXT4_IOC_SHUTDOWN _IOR ('X', 125, __u32)
+ 
+ /*
+  * Flags for going down operation
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index b383ebf4020c..a4273ddb9922 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -443,7 +443,7 @@ static inline unsigned long ext4_xflags_to_iflags(__u32 xflags)
+ 	return iflags;
+ }
+ 
+-int ext4_goingdown(struct super_block *sb, unsigned long arg)
++int ext4_shutdown(struct super_block *sb, unsigned long arg)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	__u32 flags;
+@@ -940,8 +940,8 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 
+ 		return 0;
+ 	}
+-	case EXT4_IOC_GOINGDOWN:
+-		return ext4_goingdown(sb, arg);
++	case EXT4_IOC_SHUTDOWN:
++		return ext4_shutdown(sb, arg);
+ 	default:
+ 		return -ENOTTY;
+ 	}
+@@ -1008,7 +1008,7 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ 	case EXT4_IOC_SET_ENCRYPTION_POLICY:
+ 	case EXT4_IOC_GET_ENCRYPTION_PWSALT:
+ 	case EXT4_IOC_GET_ENCRYPTION_POLICY:
+-	case EXT4_IOC_GOINGDOWN:
++	case EXT4_IOC_SHUTDOWN:
+ 		break;
+ 	default:
+ 		return -ENOIOCTLCMD;

commit 2ba3e6e8afc9b6188b471f27cf2b5e3cf34e7af2
+Author: Theodore Ts'o 
+Date:   Wed Feb 15 01:26:39 2017 -0500
+
+    ext4: fix fencepost in s_first_meta_bg validation
+    
+    It is OK for s_first_meta_bg to be equal to the number of block group
+    descriptor blocks.  (It rarely happens, but it shouldn't cause any
+    problems.)
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=194567
+    
+    Fixes: 3a4b77cd47bb837b8557595ec7425f281f2ca1fe
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index dde14a7ac6d7..a673558fe5f8 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3860,7 +3860,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) /
+ 		   EXT4_DESC_PER_BLOCK(sb);
+ 	if (ext4_has_feature_meta_bg(sb)) {
+-		if (le32_to_cpu(es->s_first_meta_bg) >= db_count) {
++		if (le32_to_cpu(es->s_first_meta_bg) > db_count) {
+ 			ext4_msg(sb, KERN_WARNING,
+ 				 "first meta block group too large: %u "
+ 				 "(group descriptor block count %u)",

commit 0d06863f903ac5f4f6efb0273079d27de3e53a28
+Author: Theodore Ts'o 
+Date:   Tue Feb 14 11:31:15 2017 -0500
+
+    ext4: don't BUG when truncating encrypted inodes on the orphan list
+    
+    Fix a BUG when the kernel tries to mount a file system constructed as
+    follows:
+    
+    echo foo > foo.txt
+    mke2fs -Fq -t ext4 -O encrypt foo.img 100
+    debugfs -w foo.img << EOF
+    write foo.txt a
+    set_inode_field a i_flags 0x80800
+    set_super_value s_last_orphan 12
+    quit
+    EOF
+    
+    root@kvm-xfstests:~# mount -o loop foo.img /mnt
+    [  160.238770] ------------[ cut here ]------------
+    [  160.240106] kernel BUG at /usr/projects/linux/ext4/fs/ext4/inode.c:3874!
+    [  160.240106] invalid opcode: 0000 [#1] SMP
+    [  160.240106] Modules linked in:
+    [  160.240106] CPU: 0 PID: 2547 Comm: mount Tainted: G        W       4.10.0-rc3-00034-gcdd33b941b67 #227
+    [  160.240106] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.1-1 04/01/2014
+    [  160.240106] task: f4518000 task.stack: f47b6000
+    [  160.240106] EIP: ext4_block_zero_page_range+0x1a7/0x2b4
+    [  160.240106] EFLAGS: 00010246 CPU: 0
+    [  160.240106] EAX: 00000001 EBX: f7be4b50 ECX: f47b7dc0 EDX: 00000007
+    [  160.240106] ESI: f43b05a8 EDI: f43babec EBP: f47b7dd0 ESP: f47b7dac
+    [  160.240106]  DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
+    [  160.240106] CR0: 80050033 CR2: bfd85b08 CR3: 34a00680 CR4: 000006f0
+    [  160.240106] Call Trace:
+    [  160.240106]  ext4_truncate+0x1e9/0x3e5
+    [  160.240106]  ext4_fill_super+0x286f/0x2b1e
+    [  160.240106]  ? set_blocksize+0x2e/0x7e
+    [  160.240106]  mount_bdev+0x114/0x15f
+    [  160.240106]  ext4_mount+0x15/0x17
+    [  160.240106]  ? ext4_calculate_overhead+0x39d/0x39d
+    [  160.240106]  mount_fs+0x58/0x115
+    [  160.240106]  vfs_kern_mount+0x4b/0xae
+    [  160.240106]  do_mount+0x671/0x8c3
+    [  160.240106]  ? _copy_from_user+0x70/0x83
+    [  160.240106]  ? strndup_user+0x31/0x46
+    [  160.240106]  SyS_mount+0x57/0x7b
+    [  160.240106]  do_int80_syscall_32+0x4f/0x61
+    [  160.240106]  entry_INT80_32+0x2f/0x2f
+    [  160.240106] EIP: 0xb76b919e
+    [  160.240106] EFLAGS: 00000246 CPU: 0
+    [  160.240106] EAX: ffffffda EBX: 08053838 ECX: 08052188 EDX: 080537e8
+    [  160.240106] ESI: c0ed0000 EDI: 00000000 EBP: 080537e8 ESP: bfa13660
+    [  160.240106]  DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 007b
+    [  160.240106] Code: 59 8b 00 a8 01 0f 84 09 01 00 00 8b 07 66 25 00 f0 66 3d 00 80 75 61 89 f8 e8 3e e2 ff ff 84 c0 74 56 83 bf 48 02 00 00 00 75 02 <0f> 0b 81 7d e8 00 10 00 00 74 02 0f 0b 8b 43 04 8b 53 08 31 c9
+    [  160.240106] EIP: ext4_block_zero_page_range+0x1a7/0x2b4 SS:ESP: 0068:f47b7dac
+    [  160.317241] ---[ end trace d6a773a375c810a5 ]---
+    
+    The problem is that when the kernel tries to truncate an inode in
+    ext4_truncate(), it tries to clear any on-disk data beyond i_size.
+    Without the encryption key, it can't do that, and so it triggers a
+    BUG.
+    
+    E2fsck does *not* provide this service, and in practice most file
+    systems have their orphan list processed by e2fsck, so to avoid
+    crashing, this patch skips this step if we don't have access to the
+    encryption key (which is the case when processing the orphan list; in
+    all other cases, we will have the encryption key, or the kernel
+    wouldn't have allowed the file to be opened).
+    
+    An open question is whether the fact that e2fsck isn't clearing the
+    bytes beyond i_size causing problems --- and if we've lived with it
+    not doing it for so long, can we drop this from the kernel replay of
+    the orphan list in all cases (not just when we don't have the key for
+    encrypted inodes).
+    
+    Addresses-Google-Bug: #35209576
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index bc282f9d0969..f622d4a577e3 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -3944,6 +3944,10 @@ static int ext4_block_truncate_page(handle_t *handle,
+ 	unsigned blocksize;
+ 	struct inode *inode = mapping->host;
+ 
++	/* If we are processing an encrypted inode during orphan list handling */
++	if (ext4_encrypted_inode(inode) && !fscrypt_has_encryption_key(inode))
++		return 0;
++
+ 	blocksize = inode->i_sb->s_blocksize;
+ 	length = blocksize - (offset & (blocksize - 1));
+ 

commit 783d948544993f55bdacc78b127532e8b6e2fc9f
+Author: Theodore Ts'o 
+Date:   Sun Feb 5 19:47:14 2017 -0500
+
+    ext4: add EXT4_IOC_GOINGDOWN ioctl
+    
+    This ioctl is modeled after the xfs's XFS_IOC_GOINGDOWN ioctl.  (In
+    fact, it uses the same code points.)
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 35d93ab7f3fb..55b7a77a0444 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -679,6 +679,16 @@ struct fsxattr {
+ #define EXT4_IOC_FSGETXATTR		FS_IOC_FSGETXATTR
+ #define EXT4_IOC_FSSETXATTR		FS_IOC_FSSETXATTR
+ 
++#define EXT4_IOC_GOINGDOWN _IOR ('X', 125, __u32)
++
++/*
++ * Flags for going down operation
++ */
++#define EXT4_GOING_FLAGS_DEFAULT		0x0	/* going down */
++#define EXT4_GOING_FLAGS_LOGFLUSH		0x1	/* flush log but not data */
++#define EXT4_GOING_FLAGS_NOLOGFLUSH		0x2	/* don't flush log nor data */
++
++
+ #if defined(__KERNEL__) && defined(CONFIG_COMPAT)
+ /*
+  * ioctl commands in 32 bit emulation
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index d534399cf607..b383ebf4020c 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -16,6 +16,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include "ext4_jbd2.h"
+ #include "ext4.h"
+ 
+@@ -442,6 +443,52 @@ static inline unsigned long ext4_xflags_to_iflags(__u32 xflags)
+ 	return iflags;
+ }
+ 
++int ext4_goingdown(struct super_block *sb, unsigned long arg)
++{
++	struct ext4_sb_info *sbi = EXT4_SB(sb);
++	__u32 flags;
++
++	if (!capable(CAP_SYS_ADMIN))
++		return -EPERM;
++
++	if (get_user(flags, (__u32 __user *)arg))
++		return -EFAULT;
++
++	if (flags > EXT4_GOING_FLAGS_NOLOGFLUSH)
++		return -EINVAL;
++
++	if (ext4_forced_shutdown(sbi))
++		return 0;
++
++	ext4_msg(sb, KERN_ALERT, "shut down requested (%d)", flags);
++
++	switch (flags) {
++	case EXT4_GOING_FLAGS_DEFAULT:
++		freeze_bdev(sb->s_bdev);
++		set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags);
++		thaw_bdev(sb->s_bdev, sb);
++		break;
++	case EXT4_GOING_FLAGS_LOGFLUSH:
++		set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags);
++		if (sbi->s_journal && !is_journal_aborted(sbi->s_journal)) {
++			(void) ext4_force_commit(sb);
++			jbd2_journal_abort(sbi->s_journal, 0);
++		}
++		break;
++	case EXT4_GOING_FLAGS_NOLOGFLUSH:
++		set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags);
++		if (sbi->s_journal && !is_journal_aborted(sbi->s_journal)) {
++			msleep(100);
++			jbd2_journal_abort(sbi->s_journal, 0);
++		}
++		break;
++	default:
++		return -EINVAL;
++	}
++	clear_opt(sb, DISCARD);
++	return 0;
++}
++
+ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ {
+ 	struct inode *inode = file_inode(filp);
+@@ -893,6 +940,8 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 
+ 		return 0;
+ 	}
++	case EXT4_IOC_GOINGDOWN:
++		return ext4_goingdown(sb, arg);
+ 	default:
+ 		return -ENOTTY;
+ 	}
+@@ -959,6 +1008,7 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ 	case EXT4_IOC_SET_ENCRYPTION_POLICY:
+ 	case EXT4_IOC_GET_ENCRYPTION_PWSALT:
+ 	case EXT4_IOC_GET_ENCRYPTION_POLICY:
++	case EXT4_IOC_GOINGDOWN:
+ 		break;
+ 	default:
+ 		return -ENOIOCTLCMD;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index cfa4ce5a1f80..3db5b6491513 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4821,7 +4821,7 @@ static int ext4_freeze(struct super_block *sb)
+  */
+ static int ext4_unfreeze(struct super_block *sb)
+ {
+-	if (sb->s_flags & MS_RDONLY)
++	if ((sb->s_flags & MS_RDONLY) || ext4_forced_shutdown(EXT4_SB(sb)))
+ 		return 0;
+ 
+ 	if (EXT4_SB(sb)->s_journal) {

commit 0db1ff222d40f1601c961f0edb86d10426992595
+Author: Theodore Ts'o 
+Date:   Sun Feb 5 01:28:48 2017 -0500
+
+    ext4: add shutdown bit and check for it
+    
+    Add a shutdown bit that will cause ext4 processing to fail immediately
+    with EIO.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 2e7e02f2f771..35d93ab7f3fb 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1836,6 +1836,12 @@ static inline bool ext4_has_incompat_features(struct super_block *sb)
+  * Superblock flags
+  */
+ #define EXT4_FLAGS_RESIZING	0
++#define EXT4_FLAGS_SHUTDOWN	1
++
++static inline int ext4_forced_shutdown(struct ext4_sb_info *sbi)
++{
++	return test_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags);
++}
+ 
+ 
+ /*
+diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
+index e770c1ee4613..dd106b1d5d89 100644
+--- a/fs/ext4/ext4_jbd2.c
++++ b/fs/ext4/ext4_jbd2.c
+@@ -43,6 +43,10 @@ static int ext4_journal_check_start(struct super_block *sb)
+ 	journal_t *journal;
+ 
+ 	might_sleep();
++
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
++		return -EIO;
++
+ 	if (sb->s_flags & MS_RDONLY)
+ 		return -EROFS;
+ 	WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE);
+@@ -161,6 +165,13 @@ int __ext4_journal_get_write_access(const char *where, unsigned int line,
+ 	might_sleep();
+ 
+ 	if (ext4_handle_valid(handle)) {
++		struct super_block *sb;
++
++		sb = handle->h_transaction->t_journal->j_private;
++		if (unlikely(ext4_forced_shutdown(EXT4_SB(sb)))) {
++			jbd2_journal_abort_handle(handle);
++			return -EIO;
++		}
+ 		err = jbd2_journal_get_write_access(handle, bh);
+ 		if (err)
+ 			ext4_journal_abort_handle(where, line, __func__, bh,
+diff --git a/fs/ext4/file.c b/fs/ext4/file.c
+index d663d3d7c81c..ff3f6107b0ba 100644
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -57,6 +57,9 @@ static ssize_t ext4_dax_read_iter(struct kiocb *iocb, struct iov_iter *to)
+ 
+ static ssize_t ext4_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
+ {
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(file_inode(iocb->ki_filp)->i_sb))))
++		return -EIO;
++
+ 	if (!iov_iter_count(to))
+ 		return 0; /* skip atime */
+ 
+@@ -213,6 +216,9 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
+ 	int overwrite = 0;
+ 	ssize_t ret;
+ 
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
++		return -EIO;
++
+ #ifdef CONFIG_FS_DAX
+ 	if (IS_DAX(inode))
+ 		return ext4_dax_write_iter(iocb, from);
+@@ -348,6 +354,9 @@ static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma)
+ {
+ 	struct inode *inode = file->f_mapping->host;
+ 
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
++		return -EIO;
++
+ 	if (ext4_encrypted_inode(inode)) {
+ 		int err = fscrypt_get_encryption_info(inode);
+ 		if (err)
+@@ -375,6 +384,9 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
+ 	char buf[64], *cp;
+ 	int ret;
+ 
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
++		return -EIO;
++
+ 	if (unlikely(!(sbi->s_mount_flags & EXT4_MF_MNTDIR_SAMPLED) &&
+ 		     !(sb->s_flags & MS_RDONLY))) {
+ 		sbi->s_mount_flags |= EXT4_MF_MNTDIR_SAMPLED;
+diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
+index 88effb1053c7..9d549608fd30 100644
+--- a/fs/ext4/fsync.c
++++ b/fs/ext4/fsync.c
+@@ -100,6 +100,9 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
+ 	tid_t commit_tid;
+ 	bool needs_barrier = false;
+ 
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
++		return -EIO;
++
+ 	J_ASSERT(ext4_journal_current_handle() == NULL);
+ 
+ 	trace_ext4_sync_file_enter(file, datasync);
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index f372fc431b8e..b14bae2598bc 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -764,6 +764,9 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
+ 	if (!dir || !dir->i_nlink)
+ 		return ERR_PTR(-EPERM);
+ 
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(dir->i_sb))))
++		return ERR_PTR(-EIO);
++
+ 	if ((ext4_encrypted_inode(dir) ||
+ 	     DUMMY_ENCRYPTION_ENABLED(EXT4_SB(dir->i_sb))) &&
+ 	    (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) {
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index b777b8aa14ae..30a9f210d1e3 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -215,6 +215,9 @@ static void ext4_write_inline_data(struct inode *inode, struct ext4_iloc *iloc,
+ 	struct ext4_inode *raw_inode;
+ 	int cp_len = 0;
+ 
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
++		return;
++
+ 	BUG_ON(!EXT4_I(inode)->i_inline_off);
+ 	BUG_ON(pos + len > EXT4_I(inode)->i_inline_size);
+ 
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index af97b9170358..bc282f9d0969 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1189,6 +1189,9 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
+ 	pgoff_t index;
+ 	unsigned from, to;
+ 
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
++		return -EIO;
++
+ 	trace_ext4_write_begin(inode, pos, len, flags);
+ 	/*
+ 	 * Reserve one block more for addition to orphan list in case
+@@ -2047,6 +2050,12 @@ static int ext4_writepage(struct page *page,
+ 	struct ext4_io_submit io_submit;
+ 	bool keep_towrite = false;
+ 
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) {
++		ext4_invalidatepage(page, 0, PAGE_SIZE);
++		unlock_page(page);
++		return -EIO;
++	}
++
+ 	trace_ext4_writepage(page);
+ 	size = i_size_read(inode);
+ 	if (page->index == size >> PAGE_SHIFT)
+@@ -2422,7 +2431,8 @@ static int mpage_map_and_submit_extent(handle_t *handle,
+ 		if (err < 0) {
+ 			struct super_block *sb = inode->i_sb;
+ 
+-			if (EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED)
++			if (ext4_forced_shutdown(EXT4_SB(sb)) ||
++			    EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED)
+ 				goto invalidate_dirty_pages;
+ 			/*
+ 			 * Let the uper layers retry transient errors.
+@@ -2644,6 +2654,9 @@ static int ext4_writepages(struct address_space *mapping,
+ 	struct blk_plug plug;
+ 	bool give_up_on_write = false;
+ 
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
++		return -EIO;
++
+ 	percpu_down_read(&sbi->s_journal_flag_rwsem);
+ 	trace_ext4_writepages(inode, wbc);
+ 
+@@ -2680,7 +2693,8 @@ static int ext4_writepages(struct address_space *mapping,
+ 	 * *never* be called, so if that ever happens, we would want
+ 	 * the stack trace.
+ 	 */
+-	if (unlikely(sbi->s_mount_flags & EXT4_MF_FS_ABORTED)) {
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(mapping->host->i_sb)) ||
++		     sbi->s_mount_flags & EXT4_MF_FS_ABORTED)) {
+ 		ret = -EROFS;
+ 		goto out_writepages;
+ 	}
+@@ -2905,6 +2919,9 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
+ 	struct inode *inode = mapping->host;
+ 	handle_t *handle;
+ 
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
++		return -EIO;
++
+ 	index = pos >> PAGE_SHIFT;
+ 
+ 	if (ext4_nonda_switch(inode->i_sb) ||
+@@ -5212,6 +5229,9 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
+ 	int orphan = 0;
+ 	const unsigned int ia_valid = attr->ia_valid;
+ 
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
++		return -EIO;
++
+ 	error = setattr_prepare(dentry, attr);
+ 	if (error)
+ 		return error;
+@@ -5498,6 +5518,9 @@ int ext4_mark_iloc_dirty(handle_t *handle,
+ {
+ 	int err = 0;
+ 
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
++		return -EIO;
++
+ 	if (IS_I_VERSION(inode))
+ 		inode_inc_iversion(inode);
+ 
+@@ -5521,6 +5544,9 @@ ext4_reserve_inode_write(handle_t *handle, struct inode *inode,
+ {
+ 	int err;
+ 
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
++		return -EIO;
++
+ 	err = ext4_get_inode_loc(inode, iloc);
+ 	if (!err) {
+ 		BUFFER_TRACE(iloc->bh, "get_write_access");
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 931da9d5d915..6ad612c576fc 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -2939,6 +2939,9 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
+ 	struct ext4_dir_entry_2 *de;
+ 	handle_t *handle = NULL;
+ 
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(dir->i_sb))))
++		return -EIO;
++
+ 	/* Initialize quotas before so that eventual writes go in
+ 	 * separate transaction */
+ 	retval = dquot_initialize(dir);
+@@ -3012,6 +3015,9 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
+ 	struct ext4_dir_entry_2 *de;
+ 	handle_t *handle = NULL;
+ 
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(dir->i_sb))))
++		return -EIO;
++
+ 	trace_ext4_unlink_enter(dir, dentry);
+ 	/* Initialize quotas before so that eventual writes go
+ 	 * in separate transaction */
+@@ -3082,6 +3088,9 @@ static int ext4_symlink(struct inode *dir,
+ 	struct fscrypt_str disk_link;
+ 	struct fscrypt_symlink_data *sd = NULL;
+ 
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(dir->i_sb))))
++		return -EIO;
++
+ 	disk_link.len = len + 1;
+ 	disk_link.name = (char *) symname;
+ 
+@@ -3874,6 +3883,9 @@ static int ext4_rename2(struct inode *old_dir, struct dentry *old_dentry,
+ 			struct inode *new_dir, struct dentry *new_dentry,
+ 			unsigned int flags)
+ {
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(old_dir->i_sb))))
++		return -EIO;
++
+ 	if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
+ 		return -EINVAL;
+ 
+diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
+index d83b0f3c5fe9..f8808835a28b 100644
+--- a/fs/ext4/page-io.c
++++ b/fs/ext4/page-io.c
+@@ -158,7 +158,7 @@ static int ext4_end_io(ext4_io_end_t *io)
+ 
+ 	io->handle = NULL;	/* Following call will use up the handle */
+ 	ret = ext4_convert_unwritten_extents(handle, inode, offset, size);
+-	if (ret < 0) {
++	if (ret < 0 && !ext4_forced_shutdown(EXT4_SB(inode->i_sb))) {
+ 		ext4_msg(inode->i_sb, KERN_EMERG,
+ 			 "failed to convert unwritten extents to written "
+ 			 "extents -- potential data loss!  "
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 514e5fc59893..cfa4ce5a1f80 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -438,6 +438,9 @@ void __ext4_error(struct super_block *sb, const char *function,
+ 	struct va_format vaf;
+ 	va_list args;
+ 
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
++		return;
++
+ 	if (ext4_error_ratelimit(sb)) {
+ 		va_start(args, fmt);
+ 		vaf.fmt = fmt;
+@@ -459,6 +462,9 @@ void __ext4_error_inode(struct inode *inode, const char *function,
+ 	struct va_format vaf;
+ 	struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
+ 
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
++		return;
++
+ 	es->s_last_error_ino = cpu_to_le32(inode->i_ino);
+ 	es->s_last_error_block = cpu_to_le64(block);
+ 	if (ext4_error_ratelimit(inode->i_sb)) {
+@@ -491,6 +497,9 @@ void __ext4_error_file(struct file *file, const char *function,
+ 	struct inode *inode = file_inode(file);
+ 	char pathname[80], *path;
+ 
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
++		return;
++
+ 	es = EXT4_SB(inode->i_sb)->s_es;
+ 	es->s_last_error_ino = cpu_to_le32(inode->i_ino);
+ 	if (ext4_error_ratelimit(inode->i_sb)) {
+@@ -567,6 +576,9 @@ void __ext4_std_error(struct super_block *sb, const char *function,
+ 	char nbuf[16];
+ 	const char *errstr;
+ 
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
++		return;
++
+ 	/* Special case: if the error is EROFS, and we're not already
+ 	 * inside a transaction, then there's really no point in logging
+ 	 * an error. */
+@@ -600,6 +612,9 @@ void __ext4_abort(struct super_block *sb, const char *function,
+ 	struct va_format vaf;
+ 	va_list args;
+ 
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
++		return;
++
+ 	save_error_info(sb, function, line);
+ 	va_start(args, fmt);
+ 	vaf.fmt = fmt;
+@@ -695,6 +710,9 @@ __acquires(bitlock)
+ 	va_list args;
+ 	struct ext4_super_block *es = EXT4_SB(sb)->s_es;
+ 
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
++		return;
++
+ 	es->s_last_error_ino = cpu_to_le32(ino);
+ 	es->s_last_error_block = cpu_to_le64(block);
+ 	__save_error_info(sb, function, line);
+@@ -4717,6 +4735,9 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
+ 	bool needs_barrier = false;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
++		return 0;
++
+ 	trace_ext4_sync_fs(sb, wait);
+ 	flush_workqueue(sbi->rsv_conversion_wq);
+ 	/*
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index c40bd55b6400..67636acf7624 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -411,6 +411,9 @@ ext4_xattr_get(struct inode *inode, int name_index, const char *name,
+ {
+ 	int error;
+ 
++	if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
++		return -EIO;
++
+ 	if (strlen(name) > 255)
+ 		return -ERANGE;
+ 

commit 9549a168bd500db1a76914e50775f7cd1690acef
+Author: Theodore Ts'o 
+Date:   Sun Feb 5 01:27:48 2017 -0500
+
+    ext4: rename s_resize_flags to s_ext4_flags
+    
+    We are currently using one bit in s_resize_flags; rename it in order
+    to allow more of the bits in that unsigned long for other purposes.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 1cd077e02517..2e7e02f2f771 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1399,8 +1399,7 @@ struct ext4_sb_info {
+ 	struct journal_s *s_journal;
+ 	struct list_head s_orphan;
+ 	struct mutex s_orphan_lock;
+-	unsigned long s_resize_flags;		/* Flags indicating if there
+-						   is a resizer */
++	unsigned long s_ext4_flags;		/* Ext4 superblock flags */
+ 	unsigned long s_commit_interval;
+ 	u32 s_max_batch_time;
+ 	u32 s_min_batch_time;
+@@ -1833,6 +1832,12 @@ static inline bool ext4_has_incompat_features(struct super_block *sb)
+ 	return (EXT4_SB(sb)->s_es->s_feature_incompat != 0);
+ }
+ 
++/*
++ * Superblock flags
++ */
++#define EXT4_FLAGS_RESIZING	0
++
++
+ /*
+  * Default values for user and/or group using reserved blocks
+  */
+@@ -3217,7 +3222,6 @@ static inline void ext4_inode_resume_unlocked_dio(struct inode *inode)
+ 					    EXT4_WQ_HASH_SZ])
+ extern wait_queue_head_t ext4__ioend_wq[EXT4_WQ_HASH_SZ];
+ 
+-#define EXT4_RESIZING	0
+ extern int ext4_resize_begin(struct super_block *sb);
+ extern void ext4_resize_end(struct super_block *sb);
+ 
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index cf681004b196..c3ed9021b781 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -45,7 +45,8 @@ int ext4_resize_begin(struct super_block *sb)
+ 		return -EPERM;
+ 	}
+ 
+-	if (test_and_set_bit_lock(EXT4_RESIZING, &EXT4_SB(sb)->s_resize_flags))
++	if (test_and_set_bit_lock(EXT4_FLAGS_RESIZING,
++				  &EXT4_SB(sb)->s_ext4_flags))
+ 		ret = -EBUSY;
+ 
+ 	return ret;
+@@ -53,7 +54,7 @@ int ext4_resize_begin(struct super_block *sb)
+ 
+ void ext4_resize_end(struct super_block *sb)
+ {
+-	clear_bit_unlock(EXT4_RESIZING, &EXT4_SB(sb)->s_resize_flags);
++	clear_bit_unlock(EXT4_FLAGS_RESIZING, &EXT4_SB(sb)->s_ext4_flags);
+ 	smp_mb__after_atomic();
+ }
+ 

commit 4753d8a24d4588657bc0a4cd66d4e282dff15c8c
+Author: Theodore Ts'o 
+Date:   Sun Feb 5 01:26:48 2017 -0500
+
+    ext4: return EROFS if device is r/o and journal replay is needed
+    
+    If the file system requires journal recovery, and the device is
+    read-ony, return EROFS to the mount system call.  This allows xfstests
+    generic/050 to pass.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 3fef82e79131..514e5fc59893 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3925,7 +3925,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	 * root first: it may be modified in the journal!
+ 	 */
+ 	if (!test_opt(sb, NOLOAD) && ext4_has_feature_journal(sb)) {
+-		if (ext4_load_journal(sb, es, journal_devnum))
++		err = ext4_load_journal(sb, es, journal_devnum);
++		if (err)
+ 			goto failed_mount3a;
+ 	} else if (test_opt(sb, NOLOAD) && !(sb->s_flags & MS_RDONLY) &&
+ 		   ext4_has_feature_journal_needs_recovery(sb)) {

commit 97abd7d4b5d9c48ec15c425485f054e1c15e591b
+Author: Theodore Ts'o 
+Date:   Sat Feb 4 23:38:06 2017 -0500
+
+    ext4: preserve the needs_recovery flag when the journal is aborted
+    
+    If the journal is aborted, the needs_recovery feature flag should not
+    be removed.  Otherwise, it's the journal might not get replayed and
+    this could lead to more data getting lost.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 829e4a7b59e4..3fef82e79131 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -825,6 +825,7 @@ static void ext4_put_super(struct super_block *sb)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	struct ext4_super_block *es = sbi->s_es;
++	int aborted = 0;
+ 	int i, err;
+ 
+ 	ext4_unregister_li_request(sb);
+@@ -834,9 +835,10 @@ static void ext4_put_super(struct super_block *sb)
+ 	destroy_workqueue(sbi->rsv_conversion_wq);
+ 
+ 	if (sbi->s_journal) {
++		aborted = is_journal_aborted(sbi->s_journal);
+ 		err = jbd2_journal_destroy(sbi->s_journal);
+ 		sbi->s_journal = NULL;
+-		if (err < 0)
++		if ((err < 0) && !aborted)
+ 			ext4_abort(sb, "Couldn't clean up the journal");
+ 	}
+ 
+@@ -847,7 +849,7 @@ static void ext4_put_super(struct super_block *sb)
+ 	ext4_mb_release(sb);
+ 	ext4_ext_release(sb);
+ 
+-	if (!(sb->s_flags & MS_RDONLY)) {
++	if (!(sb->s_flags & MS_RDONLY) && !aborted) {
+ 		ext4_clear_feature_journal_needs_recovery(sb);
+ 		es->s_state = cpu_to_le16(sbi->s_mount_state);
+ 	}

commit e112666b4959b25a8552d63bc564e1059be703e8
+Author: Theodore Ts'o 
+Date:   Sat Feb 4 23:14:19 2017 -0500
+
+    jbd2: don't leak modified metadata buffers on an aborted journal
+    
+    If the journal has been aborted, we shouldn't mark the underlying
+    buffer head as dirty, since that will cause the metadata block to get
+    modified.  And if the journal has been aborted, we shouldn't allow
+    this since it will almost certainly lead to a corrupted file system.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index e1652665bd93..5e659ee08d6a 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -1863,7 +1863,9 @@ static void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh)
+ 
+ 	__blist_del_buffer(list, jh);
+ 	jh->b_jlist = BJ_None;
+-	if (test_clear_buffer_jbddirty(bh))
++	if (transaction && is_journal_aborted(transaction->t_journal))
++		clear_buffer_jbddirty(bh);
++	else if (test_clear_buffer_jbddirty(bh))
+ 		mark_buffer_dirty(bh);	/* Expose it to the VM */
+ }
+ 

commit eb5efbcb762aee4b454b04f7115f73ccbcf8f0ef
+Author: Theodore Ts'o 
+Date:   Sat Feb 4 23:04:00 2017 -0500
+
+    ext4: fix inline data error paths
+    
+    The write_end() function must always unlock the page and drop its ref
+    count, even on an error.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index 338cfd862adb..b777b8aa14ae 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -943,8 +943,15 @@ int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos,
+ 				  struct page *page)
+ {
+ 	int i_size_changed = 0;
++	int ret;
+ 
+-	copied = ext4_write_inline_data_end(inode, pos, len, copied, page);
++	ret = ext4_write_inline_data_end(inode, pos, len, copied, page);
++	if (ret < 0) {
++		unlock_page(page);
++		put_page(page);
++		return ret;
++	}
++	copied = ret;
+ 
+ 	/*
+ 	 * No need to use i_size_read() here, the i_size
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 918d351d5b94..af97b9170358 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1330,8 +1330,11 @@ static int ext4_write_end(struct file *file,
+ 	if (ext4_has_inline_data(inode)) {
+ 		ret = ext4_write_inline_data_end(inode, pos, len,
+ 						 copied, page);
+-		if (ret < 0)
++		if (ret < 0) {
++			unlock_page(page);
++			put_page(page);
+ 			goto errout;
++		}
+ 		copied = ret;
+ 	} else
+ 		copied = block_write_end(file, mapping, pos,
+@@ -1433,10 +1436,16 @@ static int ext4_journalled_write_end(struct file *file,
+ 
+ 	BUG_ON(!ext4_handle_valid(handle));
+ 
+-	if (ext4_has_inline_data(inode))
+-		copied = ext4_write_inline_data_end(inode, pos, len,
+-						    copied, page);
+-	else if (unlikely(copied < len) && !PageUptodate(page)) {
++	if (ext4_has_inline_data(inode)) {
++		ret = ext4_write_inline_data_end(inode, pos, len,
++						 copied, page);
++		if (ret < 0) {
++			unlock_page(page);
++			put_page(page);
++			goto errout;
++		}
++		copied = ret;
++	} else if (unlikely(copied < len) && !PageUptodate(page)) {
+ 		copied = 0;
+ 		ext4_journalled_zero_new_buffers(handle, page, from, to);
+ 	} else {
+@@ -1471,6 +1480,7 @@ static int ext4_journalled_write_end(struct file *file,
+ 		 */
+ 		ext4_orphan_add(handle, inode);
+ 
++errout:
+ 	ret2 = ext4_journal_stop(handle);
+ 	if (!ret)
+ 		ret = ret2;

commit 43c73221b3b1cdc9156c78287c5f4b29dc085d22
+Author: Theodore Ts'o 
+Date:   Sun Jan 22 19:35:52 2017 -0500
+
+    ext4: replace BUG_ON with WARN_ON in mb_find_extent()
+    
+    The last BUG_ON in mb_find_extent() is apparently triggering in some
+    rare cases.  Most of the time it indicates a bug in the buddy bitmap
+    algorithms, but there are some weird cases where it can trigger when
+    buddy bitmap is still in memory, but the block bitmap has to be read
+    from disk, and there is disk or memory corruption such that the block
+    bitmap and the buddy bitmap are out of sync.
+    
+    Google-Bug-Id: #33702157
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 7ae43c59bc79..ec2f64b0e696 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -1556,7 +1556,17 @@ static int mb_find_extent(struct ext4_buddy *e4b, int block,
+ 		ex->fe_len += 1 << order;
+ 	}
+ 
+-	BUG_ON(ex->fe_start + ex->fe_len > (1 << (e4b->bd_blkbits + 3)));
++	if (ex->fe_start + ex->fe_len > (1 << (e4b->bd_blkbits + 3))) {
++		/* Should never happen! (but apparently sometimes does?!?) */
++		WARN_ON(1);
++		ext4_error(e4b->bd_sb, "corruption or bug in mb_find_extent "
++			   "block=%d, order=%d needed=%d ex=%u/%d/%d@%u",
++			   block, order, needed, ex->fe_group, ex->fe_start,
++			   ex->fe_len, ex->fe_logical);
++		ex->fe_len = 0;
++		ex->fe_start = 0;
++		ex->fe_group = 0;
++	}
+ 	return ex->fe_len;
+ }
+ 

commit 01daf9452569fe2e69e27fe3e617b43d2ebb1e93
+Author: Theodore Ts'o 
+Date:   Sun Jan 22 19:35:49 2017 -0500
+
+    ext4: propagate error values from ext4_inline_data_truncate()
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 6bcb9622fdf9..1cd077e02517 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -3023,7 +3023,7 @@ extern int ext4_inline_data_fiemap(struct inode *inode,
+ extern int ext4_try_to_evict_inline_data(handle_t *handle,
+ 					 struct inode *inode,
+ 					 int needed);
+-extern void ext4_inline_data_truncate(struct inode *inode, int *has_inline);
++extern int ext4_inline_data_truncate(struct inode *inode, int *has_inline);
+ 
+ extern int ext4_convert_inline_data(struct inode *inode);
+ 
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index 31f98dd04e51..338cfd862adb 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -1896,10 +1896,10 @@ int ext4_try_to_evict_inline_data(handle_t *handle,
+ 	return error;
+ }
+ 
+-void ext4_inline_data_truncate(struct inode *inode, int *has_inline)
++int ext4_inline_data_truncate(struct inode *inode, int *has_inline)
+ {
+ 	handle_t *handle;
+-	int inline_size, value_len, needed_blocks, no_expand;
++	int inline_size, value_len, needed_blocks, no_expand, err = 0;
+ 	size_t i_size;
+ 	void *value = NULL;
+ 	struct ext4_xattr_ibody_find is = {
+@@ -1914,19 +1914,19 @@ void ext4_inline_data_truncate(struct inode *inode, int *has_inline)
+ 	needed_blocks = ext4_writepage_trans_blocks(inode);
+ 	handle = ext4_journal_start(inode, EXT4_HT_INODE, needed_blocks);
+ 	if (IS_ERR(handle))
+-		return;
++		return PTR_ERR(handle);
+ 
+ 	ext4_write_lock_xattr(inode, &no_expand);
+ 	if (!ext4_has_inline_data(inode)) {
+ 		*has_inline = 0;
+ 		ext4_journal_stop(handle);
+-		return;
++		return 0;
+ 	}
+ 
+-	if (ext4_orphan_add(handle, inode))
++	if ((err = ext4_orphan_add(handle, inode)) != 0)
+ 		goto out;
+ 
+-	if (ext4_get_inode_loc(inode, &is.iloc))
++	if ((err = ext4_get_inode_loc(inode, &is.iloc)) != 0)
+ 		goto out;
+ 
+ 	down_write(&EXT4_I(inode)->i_data_sem);
+@@ -1937,24 +1937,29 @@ void ext4_inline_data_truncate(struct inode *inode, int *has_inline)
+ 	if (i_size < inline_size) {
+ 		/* Clear the content in the xattr space. */
+ 		if (inline_size > EXT4_MIN_INLINE_DATA_SIZE) {
+-			if (ext4_xattr_ibody_find(inode, &i, &is))
++			if ((err = ext4_xattr_ibody_find(inode, &i, &is)) != 0)
+ 				goto out_error;
+ 
+ 			BUG_ON(is.s.not_found);
+ 
+ 			value_len = le32_to_cpu(is.s.here->e_value_size);
+ 			value = kmalloc(value_len, GFP_NOFS);
+-			if (!value)
++			if (!value) {
++				err = -ENOMEM;
+ 				goto out_error;
++			}
+ 
+-			if (ext4_xattr_ibody_get(inode, i.name_index, i.name,
+-						value, value_len))
++			err = ext4_xattr_ibody_get(inode, i.name_index,
++						   i.name, value, value_len);
++			if (err <= 0)
+ 				goto out_error;
+ 
+ 			i.value = value;
+ 			i.value_len = i_size > EXT4_MIN_INLINE_DATA_SIZE ?
+ 					i_size - EXT4_MIN_INLINE_DATA_SIZE : 0;
+-			if (ext4_xattr_ibody_inline_set(handle, inode, &i, &is))
++			err = ext4_xattr_ibody_inline_set(handle, inode,
++							  &i, &is);
++			if (err)
+ 				goto out_error;
+ 		}
+ 
+@@ -1979,13 +1984,14 @@ void ext4_inline_data_truncate(struct inode *inode, int *has_inline)
+ 	if (inode->i_nlink)
+ 		ext4_orphan_del(handle, inode);
+ 
+-	inode->i_mtime = inode->i_ctime = current_time(inode);
+-	ext4_mark_inode_dirty(handle, inode);
+-	if (IS_SYNC(inode))
+-		ext4_handle_sync(handle);
+-
++	if (err == 0) {
++		inode->i_mtime = inode->i_ctime = current_time(inode);
++		err = ext4_mark_inode_dirty(handle, inode);
++		if (IS_SYNC(inode))
++			ext4_handle_sync(handle);
++	}
+ 	ext4_journal_stop(handle);
+-	return;
++	return err;
+ }
+ 
+ int ext4_convert_inline_data(struct inode *inode)
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 86dde0667ccc..1e2c881f102d 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4222,7 +4222,9 @@ int ext4_truncate(struct inode *inode)
+ 	if (ext4_has_inline_data(inode)) {
+ 		int has_inline = 1;
+ 
+-		ext4_inline_data_truncate(inode, &has_inline);
++		err = ext4_inline_data_truncate(inode, &has_inline);
++		if (err)
++			return err;
+ 		if (has_inline)
+ 			return 0;
+ 	}

commit b907f2d5194c2636623415d89cfb91d692af0629
+Author: Theodore Ts'o 
+Date:   Wed Jan 11 22:14:49 2017 -0500
+
+    ext4: avoid calling ext4_mark_inode_dirty() under unneeded semaphores
+    
+    There is no need to call ext4_mark_inode_dirty while holding xattr_sem
+    or i_data_sem, so where it's easy to avoid it, move it out from the
+    critical region.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index 99a5312ced52..31f98dd04e51 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -1042,7 +1042,6 @@ static int ext4_add_dirent_to_inline(handle_t *handle,
+ 	dir->i_mtime = dir->i_ctime = current_time(dir);
+ 	ext4_update_dx_flag(dir);
+ 	dir->i_version++;
+-	ext4_mark_inode_dirty(handle, dir);
+ 	return 1;
+ }
+ 
+@@ -1311,8 +1310,8 @@ int ext4_try_add_inline_entry(handle_t *handle, struct ext4_filename *fname,
+ 	ret = ext4_convert_inline_data_nolock(handle, dir, &iloc);
+ 
+ out:
+-	ext4_mark_inode_dirty(handle, dir);
+ 	ext4_write_unlock_xattr(dir, &no_expand);
++	ext4_mark_inode_dirty(handle, dir);
+ 	brelse(iloc.bh);
+ 	return ret;
+ }
+@@ -1708,13 +1707,11 @@ int ext4_delete_inline_entry(handle_t *handle,
+ 	if (err)
+ 		goto out;
+ 
+-	err = ext4_mark_inode_dirty(handle, dir);
+-	if (unlikely(err))
+-		goto out;
+-
+ 	ext4_show_inline_dir(dir, iloc.bh, inline_start, inline_size);
+ out:
+ 	ext4_write_unlock_xattr(dir, &no_expand);
++	if (likely(err == 0))
++		err = ext4_mark_inode_dirty(handle, dir);
+ 	brelse(iloc.bh);
+ 	if (err != -ENOENT)
+ 		ext4_std_error(dir->i_sb, err);
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 88d57af1b516..86dde0667ccc 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2464,8 +2464,8 @@ static int mpage_map_and_submit_extent(handle_t *handle,
+ 			disksize = i_size;
+ 		if (disksize > EXT4_I(inode)->i_disksize)
+ 			EXT4_I(inode)->i_disksize = disksize;
+-		err2 = ext4_mark_inode_dirty(handle, inode);
+ 		up_write(&EXT4_I(inode)->i_data_sem);
++		err2 = ext4_mark_inode_dirty(handle, inode);
+ 		if (err2)
+ 			ext4_error(inode->i_sb,
+ 				   "Failed to mark inode %lu dirty",

commit c755e251357a0cee0679081f08c3f4ba797a8009
+Author: Theodore Ts'o 
+Date:   Wed Jan 11 21:50:46 2017 -0500
+
+    ext4: fix deadlock between inline_data and ext4_expand_extra_isize_ea()
+    
+    The xattr_sem deadlock problems fixed in commit 2e81a4eeedca: "ext4:
+    avoid deadlock when expanding inode size" didn't include the use of
+    xattr_sem in fs/ext4/inline.c.  With the addition of project quota
+    which added a new extra inode field, this exposed deadlocks in the
+    inline_data code similar to the ones fixed by 2e81a4eeedca.
+    
+    The deadlock can be reproduced via:
+    
+       dmesg -n 7
+       mke2fs -t ext4 -O inline_data -Fq -I 256 /dev/vdc 32768
+       mount -t ext4 -o debug_want_extra_isize=24 /dev/vdc /vdc
+       mkdir /vdc/a
+       umount /vdc
+       mount -t ext4 /dev/vdc /vdc
+       echo foo > /vdc/a/foo
+    
+    and looks like this:
+    
+    [   11.158815]
+    [   11.160276] =============================================
+    [   11.161960] [ INFO: possible recursive locking detected ]
+    [   11.161960] 4.10.0-rc3-00015-g011b30a8a3cf #160 Tainted: G        W
+    [   11.161960] ---------------------------------------------
+    [   11.161960] bash/2519 is trying to acquire lock:
+    [   11.161960]  (&ei->xattr_sem){++++..}, at: [] ext4_expand_extra_isize_ea+0x3d/0x4cd
+    [   11.161960]
+    [   11.161960] but task is already holding lock:
+    [   11.161960]  (&ei->xattr_sem){++++..}, at: [] ext4_try_add_inline_entry+0x3a/0x152
+    [   11.161960]
+    [   11.161960] other info that might help us debug this:
+    [   11.161960]  Possible unsafe locking scenario:
+    [   11.161960]
+    [   11.161960]        CPU0
+    [   11.161960]        ----
+    [   11.161960]   lock(&ei->xattr_sem);
+    [   11.161960]   lock(&ei->xattr_sem);
+    [   11.161960]
+    [   11.161960]  *** DEADLOCK ***
+    [   11.161960]
+    [   11.161960]  May be due to missing lock nesting notation
+    [   11.161960]
+    [   11.161960] 4 locks held by bash/2519:
+    [   11.161960]  #0:  (sb_writers#3){.+.+.+}, at: [] mnt_want_write+0x1e/0x3e
+    [   11.161960]  #1:  (&type->i_mutex_dir_key){++++++}, at: [] path_openat+0x338/0x67a
+    [   11.161960]  #2:  (jbd2_handle){++++..}, at: [] start_this_handle+0x582/0x622
+    [   11.161960]  #3:  (&ei->xattr_sem){++++..}, at: [] ext4_try_add_inline_entry+0x3a/0x152
+    [   11.161960]
+    [   11.161960] stack backtrace:
+    [   11.161960] CPU: 0 PID: 2519 Comm: bash Tainted: G        W       4.10.0-rc3-00015-g011b30a8a3cf #160
+    [   11.161960] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.1-1 04/01/2014
+    [   11.161960] Call Trace:
+    [   11.161960]  dump_stack+0x72/0xa3
+    [   11.161960]  __lock_acquire+0xb7c/0xcb9
+    [   11.161960]  ? kvm_clock_read+0x1f/0x29
+    [   11.161960]  ? __lock_is_held+0x36/0x66
+    [   11.161960]  ? __lock_is_held+0x36/0x66
+    [   11.161960]  lock_acquire+0x106/0x18a
+    [   11.161960]  ? ext4_expand_extra_isize_ea+0x3d/0x4cd
+    [   11.161960]  down_write+0x39/0x72
+    [   11.161960]  ? ext4_expand_extra_isize_ea+0x3d/0x4cd
+    [   11.161960]  ext4_expand_extra_isize_ea+0x3d/0x4cd
+    [   11.161960]  ? _raw_read_unlock+0x22/0x2c
+    [   11.161960]  ? jbd2_journal_extend+0x1e2/0x262
+    [   11.161960]  ? __ext4_journal_get_write_access+0x3d/0x60
+    [   11.161960]  ext4_mark_inode_dirty+0x17d/0x26d
+    [   11.161960]  ? ext4_add_dirent_to_inline.isra.12+0xa5/0xb2
+    [   11.161960]  ext4_add_dirent_to_inline.isra.12+0xa5/0xb2
+    [   11.161960]  ext4_try_add_inline_entry+0x69/0x152
+    [   11.161960]  ext4_add_entry+0xa3/0x848
+    [   11.161960]  ? __brelse+0x14/0x2f
+    [   11.161960]  ? _raw_spin_unlock_irqrestore+0x44/0x4f
+    [   11.161960]  ext4_add_nondir+0x17/0x5b
+    [   11.161960]  ext4_create+0xcf/0x133
+    [   11.161960]  ? ext4_mknod+0x12f/0x12f
+    [   11.161960]  lookup_open+0x39e/0x3fb
+    [   11.161960]  ? __wake_up+0x1a/0x40
+    [   11.161960]  ? lock_acquire+0x11e/0x18a
+    [   11.161960]  path_openat+0x35c/0x67a
+    [   11.161960]  ? sched_clock_cpu+0xd7/0xf2
+    [   11.161960]  do_filp_open+0x36/0x7c
+    [   11.161960]  ? _raw_spin_unlock+0x22/0x2c
+    [   11.161960]  ? __alloc_fd+0x169/0x173
+    [   11.161960]  do_sys_open+0x59/0xcc
+    [   11.161960]  SyS_open+0x1d/0x1f
+    [   11.161960]  do_int80_syscall_32+0x4f/0x61
+    [   11.161960]  entry_INT80_32+0x2f/0x2f
+    [   11.161960] EIP: 0xb76ad469
+    [   11.161960] EFLAGS: 00000286 CPU: 0
+    [   11.161960] EAX: ffffffda EBX: 08168ac8 ECX: 00008241 EDX: 000001b6
+    [   11.161960] ESI: b75e46bc EDI: b7755000 EBP: bfbdb108 ESP: bfbdafc0
+    [   11.161960]  DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 007b
+    
+    Cc: stable@vger.kernel.org # 3.10 (requires 2e81a4eeedca as a prereq)
+    Reported-by: George Spelvin 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index 437df6a1a841..99a5312ced52 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -381,7 +381,7 @@ static int ext4_update_inline_data(handle_t *handle, struct inode *inode,
+ static int ext4_prepare_inline_data(handle_t *handle, struct inode *inode,
+ 				    unsigned int len)
+ {
+-	int ret, size;
++	int ret, size, no_expand;
+ 	struct ext4_inode_info *ei = EXT4_I(inode);
+ 
+ 	if (!ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA))
+@@ -391,15 +391,14 @@ static int ext4_prepare_inline_data(handle_t *handle, struct inode *inode,
+ 	if (size < len)
+ 		return -ENOSPC;
+ 
+-	down_write(&EXT4_I(inode)->xattr_sem);
++	ext4_write_lock_xattr(inode, &no_expand);
+ 
+ 	if (ei->i_inline_off)
+ 		ret = ext4_update_inline_data(handle, inode, len);
+ 	else
+ 		ret = ext4_create_inline_data(handle, inode, len);
+ 
+-	up_write(&EXT4_I(inode)->xattr_sem);
+-
++	ext4_write_unlock_xattr(inode, &no_expand);
+ 	return ret;
+ }
+ 
+@@ -533,7 +532,7 @@ static int ext4_convert_inline_data_to_extent(struct address_space *mapping,
+ 					      struct inode *inode,
+ 					      unsigned flags)
+ {
+-	int ret, needed_blocks;
++	int ret, needed_blocks, no_expand;
+ 	handle_t *handle = NULL;
+ 	int retries = 0, sem_held = 0;
+ 	struct page *page = NULL;
+@@ -573,7 +572,7 @@ static int ext4_convert_inline_data_to_extent(struct address_space *mapping,
+ 		goto out;
+ 	}
+ 
+-	down_write(&EXT4_I(inode)->xattr_sem);
++	ext4_write_lock_xattr(inode, &no_expand);
+ 	sem_held = 1;
+ 	/* If some one has already done this for us, just exit. */
+ 	if (!ext4_has_inline_data(inode)) {
+@@ -610,7 +609,7 @@ static int ext4_convert_inline_data_to_extent(struct address_space *mapping,
+ 		put_page(page);
+ 		page = NULL;
+ 		ext4_orphan_add(handle, inode);
+-		up_write(&EXT4_I(inode)->xattr_sem);
++		ext4_write_unlock_xattr(inode, &no_expand);
+ 		sem_held = 0;
+ 		ext4_journal_stop(handle);
+ 		handle = NULL;
+@@ -636,7 +635,7 @@ static int ext4_convert_inline_data_to_extent(struct address_space *mapping,
+ 		put_page(page);
+ 	}
+ 	if (sem_held)
+-		up_write(&EXT4_I(inode)->xattr_sem);
++		ext4_write_unlock_xattr(inode, &no_expand);
+ 	if (handle)
+ 		ext4_journal_stop(handle);
+ 	brelse(iloc.bh);
+@@ -729,7 +728,7 @@ int ext4_try_to_write_inline_data(struct address_space *mapping,
+ int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,
+ 			       unsigned copied, struct page *page)
+ {
+-	int ret;
++	int ret, no_expand;
+ 	void *kaddr;
+ 	struct ext4_iloc iloc;
+ 
+@@ -747,7 +746,7 @@ int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,
+ 		goto out;
+ 	}
+ 
+-	down_write(&EXT4_I(inode)->xattr_sem);
++	ext4_write_lock_xattr(inode, &no_expand);
+ 	BUG_ON(!ext4_has_inline_data(inode));
+ 
+ 	kaddr = kmap_atomic(page);
+@@ -757,7 +756,7 @@ int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,
+ 	/* clear page dirty so that writepages wouldn't work for us. */
+ 	ClearPageDirty(page);
+ 
+-	up_write(&EXT4_I(inode)->xattr_sem);
++	ext4_write_unlock_xattr(inode, &no_expand);
+ 	brelse(iloc.bh);
+ out:
+ 	return copied;
+@@ -768,7 +767,7 @@ ext4_journalled_write_inline_data(struct inode *inode,
+ 				  unsigned len,
+ 				  struct page *page)
+ {
+-	int ret;
++	int ret, no_expand;
+ 	void *kaddr;
+ 	struct ext4_iloc iloc;
+ 
+@@ -778,11 +777,11 @@ ext4_journalled_write_inline_data(struct inode *inode,
+ 		return NULL;
+ 	}
+ 
+-	down_write(&EXT4_I(inode)->xattr_sem);
++	ext4_write_lock_xattr(inode, &no_expand);
+ 	kaddr = kmap_atomic(page);
+ 	ext4_write_inline_data(inode, &iloc, kaddr, 0, len);
+ 	kunmap_atomic(kaddr);
+-	up_write(&EXT4_I(inode)->xattr_sem);
++	ext4_write_unlock_xattr(inode, &no_expand);
+ 
+ 	return iloc.bh;
+ }
+@@ -1259,7 +1258,7 @@ static int ext4_convert_inline_data_nolock(handle_t *handle,
+ int ext4_try_add_inline_entry(handle_t *handle, struct ext4_filename *fname,
+ 			      struct inode *dir, struct inode *inode)
+ {
+-	int ret, inline_size;
++	int ret, inline_size, no_expand;
+ 	void *inline_start;
+ 	struct ext4_iloc iloc;
+ 
+@@ -1267,7 +1266,7 @@ int ext4_try_add_inline_entry(handle_t *handle, struct ext4_filename *fname,
+ 	if (ret)
+ 		return ret;
+ 
+-	down_write(&EXT4_I(dir)->xattr_sem);
++	ext4_write_lock_xattr(dir, &no_expand);
+ 	if (!ext4_has_inline_data(dir))
+ 		goto out;
+ 
+@@ -1313,7 +1312,7 @@ int ext4_try_add_inline_entry(handle_t *handle, struct ext4_filename *fname,
+ 
+ out:
+ 	ext4_mark_inode_dirty(handle, dir);
+-	up_write(&EXT4_I(dir)->xattr_sem);
++	ext4_write_unlock_xattr(dir, &no_expand);
+ 	brelse(iloc.bh);
+ 	return ret;
+ }
+@@ -1673,7 +1672,7 @@ int ext4_delete_inline_entry(handle_t *handle,
+ 			     struct buffer_head *bh,
+ 			     int *has_inline_data)
+ {
+-	int err, inline_size;
++	int err, inline_size, no_expand;
+ 	struct ext4_iloc iloc;
+ 	void *inline_start;
+ 
+@@ -1681,7 +1680,7 @@ int ext4_delete_inline_entry(handle_t *handle,
+ 	if (err)
+ 		return err;
+ 
+-	down_write(&EXT4_I(dir)->xattr_sem);
++	ext4_write_lock_xattr(dir, &no_expand);
+ 	if (!ext4_has_inline_data(dir)) {
+ 		*has_inline_data = 0;
+ 		goto out;
+@@ -1715,7 +1714,7 @@ int ext4_delete_inline_entry(handle_t *handle,
+ 
+ 	ext4_show_inline_dir(dir, iloc.bh, inline_start, inline_size);
+ out:
+-	up_write(&EXT4_I(dir)->xattr_sem);
++	ext4_write_unlock_xattr(dir, &no_expand);
+ 	brelse(iloc.bh);
+ 	if (err != -ENOENT)
+ 		ext4_std_error(dir->i_sb, err);
+@@ -1814,11 +1813,11 @@ bool empty_inline_dir(struct inode *dir, int *has_inline_data)
+ 
+ int ext4_destroy_inline_data(handle_t *handle, struct inode *inode)
+ {
+-	int ret;
++	int ret, no_expand;
+ 
+-	down_write(&EXT4_I(inode)->xattr_sem);
++	ext4_write_lock_xattr(inode, &no_expand);
+ 	ret = ext4_destroy_inline_data_nolock(handle, inode);
+-	up_write(&EXT4_I(inode)->xattr_sem);
++	ext4_write_unlock_xattr(inode, &no_expand);
+ 
+ 	return ret;
+ }
+@@ -1903,7 +1902,7 @@ int ext4_try_to_evict_inline_data(handle_t *handle,
+ void ext4_inline_data_truncate(struct inode *inode, int *has_inline)
+ {
+ 	handle_t *handle;
+-	int inline_size, value_len, needed_blocks;
++	int inline_size, value_len, needed_blocks, no_expand;
+ 	size_t i_size;
+ 	void *value = NULL;
+ 	struct ext4_xattr_ibody_find is = {
+@@ -1920,7 +1919,7 @@ void ext4_inline_data_truncate(struct inode *inode, int *has_inline)
+ 	if (IS_ERR(handle))
+ 		return;
+ 
+-	down_write(&EXT4_I(inode)->xattr_sem);
++	ext4_write_lock_xattr(inode, &no_expand);
+ 	if (!ext4_has_inline_data(inode)) {
+ 		*has_inline = 0;
+ 		ext4_journal_stop(handle);
+@@ -1978,7 +1977,7 @@ void ext4_inline_data_truncate(struct inode *inode, int *has_inline)
+ 	up_write(&EXT4_I(inode)->i_data_sem);
+ out:
+ 	brelse(is.iloc.bh);
+-	up_write(&EXT4_I(inode)->xattr_sem);
++	ext4_write_unlock_xattr(inode, &no_expand);
+ 	kfree(value);
+ 	if (inode->i_nlink)
+ 		ext4_orphan_del(handle, inode);
+@@ -1994,7 +1993,7 @@ void ext4_inline_data_truncate(struct inode *inode, int *has_inline)
+ 
+ int ext4_convert_inline_data(struct inode *inode)
+ {
+-	int error, needed_blocks;
++	int error, needed_blocks, no_expand;
+ 	handle_t *handle;
+ 	struct ext4_iloc iloc;
+ 
+@@ -2016,15 +2015,10 @@ int ext4_convert_inline_data(struct inode *inode)
+ 		goto out_free;
+ 	}
+ 
+-	down_write(&EXT4_I(inode)->xattr_sem);
+-	if (!ext4_has_inline_data(inode)) {
+-		up_write(&EXT4_I(inode)->xattr_sem);
+-		goto out;
+-	}
+-
+-	error = ext4_convert_inline_data_nolock(handle, inode, &iloc);
+-	up_write(&EXT4_I(inode)->xattr_sem);
+-out:
++	ext4_write_lock_xattr(inode, &no_expand);
++	if (ext4_has_inline_data(inode))
++		error = ext4_convert_inline_data_nolock(handle, inode, &iloc);
++	ext4_write_unlock_xattr(inode, &no_expand);
+ 	ext4_journal_stop(handle);
+ out_free:
+ 	brelse(iloc.bh);
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 5a94fa52b74f..c40bd55b6400 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -1188,16 +1188,14 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
+ 	struct ext4_xattr_block_find bs = {
+ 		.s = { .not_found = -ENODATA, },
+ 	};
+-	unsigned long no_expand;
++	int no_expand;
+ 	int error;
+ 
+ 	if (!name)
+ 		return -EINVAL;
+ 	if (strlen(name) > 255)
+ 		return -ERANGE;
+-	down_write(&EXT4_I(inode)->xattr_sem);
+-	no_expand = ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND);
+-	ext4_set_inode_state(inode, EXT4_STATE_NO_EXPAND);
++	ext4_write_lock_xattr(inode, &no_expand);
+ 
+ 	error = ext4_reserve_inode_write(handle, inode, &is.iloc);
+ 	if (error)
+@@ -1264,7 +1262,7 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
+ 		ext4_xattr_update_super_block(handle, inode->i_sb);
+ 		inode->i_ctime = current_time(inode);
+ 		if (!value)
+-			ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND);
++			no_expand = 0;
+ 		error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);
+ 		/*
+ 		 * The bh is consumed by ext4_mark_iloc_dirty, even with
+@@ -1278,9 +1276,7 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
+ cleanup:
+ 	brelse(is.iloc.bh);
+ 	brelse(bs.bh);
+-	if (no_expand == 0)
+-		ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND);
+-	up_write(&EXT4_I(inode)->xattr_sem);
++	ext4_write_unlock_xattr(inode, &no_expand);
+ 	return error;
+ }
+ 
+@@ -1497,12 +1493,11 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
+ 	int error = 0, tried_min_extra_isize = 0;
+ 	int s_min_extra_isize = le16_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_min_extra_isize);
+ 	int isize_diff;	/* How much do we need to grow i_extra_isize */
++	int no_expand;
++
++	if (ext4_write_trylock_xattr(inode, &no_expand) == 0)
++		return 0;
+ 
+-	down_write(&EXT4_I(inode)->xattr_sem);
+-	/*
+-	 * Set EXT4_STATE_NO_EXPAND to avoid recursion when marking inode dirty
+-	 */
+-	ext4_set_inode_state(inode, EXT4_STATE_NO_EXPAND);
+ retry:
+ 	isize_diff = new_extra_isize - EXT4_I(inode)->i_extra_isize;
+ 	if (EXT4_I(inode)->i_extra_isize >= new_extra_isize)
+@@ -1584,17 +1579,16 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
+ 	EXT4_I(inode)->i_extra_isize = new_extra_isize;
+ 	brelse(bh);
+ out:
+-	ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND);
+-	up_write(&EXT4_I(inode)->xattr_sem);
++	ext4_write_unlock_xattr(inode, &no_expand);
+ 	return 0;
+ 
+ cleanup:
+ 	brelse(bh);
+ 	/*
+-	 * We deliberately leave EXT4_STATE_NO_EXPAND set here since inode
+-	 * size expansion failed.
++	 * Inode size expansion failed; don't try again
+ 	 */
+-	up_write(&EXT4_I(inode)->xattr_sem);
++	no_expand = 1;
++	ext4_write_unlock_xattr(inode, &no_expand);
+ 	return error;
+ }
+ 
+diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
+index a92e783fa057..099c8b670ef5 100644
+--- a/fs/ext4/xattr.h
++++ b/fs/ext4/xattr.h
+@@ -102,6 +102,38 @@ extern const struct xattr_handler ext4_xattr_security_handler;
+ 
+ #define EXT4_XATTR_NAME_ENCRYPTION_CONTEXT "c"
+ 
++/*
++ * The EXT4_STATE_NO_EXPAND is overloaded and used for two purposes.
++ * The first is to signal that there the inline xattrs and data are
++ * taking up so much space that we might as well not keep trying to
++ * expand it.  The second is that xattr_sem is taken for writing, so
++ * we shouldn't try to recurse into the inode expansion.  For this
++ * second case, we need to make sure that we take save and restore the
++ * NO_EXPAND state flag appropriately.
++ */
++static inline void ext4_write_lock_xattr(struct inode *inode, int *save)
++{
++	down_write(&EXT4_I(inode)->xattr_sem);
++	*save = ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND);
++	ext4_set_inode_state(inode, EXT4_STATE_NO_EXPAND);
++}
++
++static inline int ext4_write_trylock_xattr(struct inode *inode, int *save)
++{
++	if (down_write_trylock(&EXT4_I(inode)->xattr_sem) == 0)
++		return 0;
++	*save = ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND);
++	ext4_set_inode_state(inode, EXT4_STATE_NO_EXPAND);
++	return 1;
++}
++
++static inline void ext4_write_unlock_xattr(struct inode *inode, int *save)
++{
++	if (*save == 0)
++		ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND);
++	up_write(&EXT4_I(inode)->xattr_sem);
++}
++
+ extern ssize_t ext4_listxattr(struct dentry *, char *, size_t);
+ 
+ extern int ext4_xattr_get(struct inode *, int, const char *, void *, size_t);

commit 670e9875eb14b112fa6a206a65c776a4fb347eb1
+Author: Theodore Ts'o 
+Date:   Wed Jan 11 15:32:22 2017 -0500
+
+    ext4: add debug_want_extra_isize mount option
+    
+    In order to test the inode extra isize expansion code, it is useful to
+    be able to easily create file systems that have inodes with extra
+    isize values smaller than the current desired value.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 9d15a6293124..829e4a7b59e4 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1284,7 +1284,7 @@ enum {
+ 	Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err,
+ 	Opt_usrquota, Opt_grpquota, Opt_prjquota, Opt_i_version, Opt_dax,
+ 	Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_mblk_io_submit,
+-	Opt_lazytime, Opt_nolazytime,
++	Opt_lazytime, Opt_nolazytime, Opt_debug_want_extra_isize,
+ 	Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity,
+ 	Opt_inode_readahead_blks, Opt_journal_ioprio,
+ 	Opt_dioread_nolock, Opt_dioread_lock,
+@@ -1352,6 +1352,7 @@ static const match_table_t tokens = {
+ 	{Opt_delalloc, "delalloc"},
+ 	{Opt_lazytime, "lazytime"},
+ 	{Opt_nolazytime, "nolazytime"},
++	{Opt_debug_want_extra_isize, "debug_want_extra_isize=%u"},
+ 	{Opt_nodelalloc, "nodelalloc"},
+ 	{Opt_removed, "mblk_io_submit"},
+ 	{Opt_removed, "nomblk_io_submit"},
+@@ -1557,6 +1558,7 @@ static const struct mount_opts {
+ #endif
+ 	{Opt_nouid32, EXT4_MOUNT_NO_UID32, MOPT_SET},
+ 	{Opt_debug, EXT4_MOUNT_DEBUG, MOPT_SET},
++	{Opt_debug_want_extra_isize, 0, MOPT_GTE0},
+ 	{Opt_quota, EXT4_MOUNT_QUOTA | EXT4_MOUNT_USRQUOTA, MOPT_SET | MOPT_Q},
+ 	{Opt_usrquota, EXT4_MOUNT_QUOTA | EXT4_MOUNT_USRQUOTA,
+ 							MOPT_SET | MOPT_Q},
+@@ -1670,6 +1672,8 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
+ 		if (arg == 0)
+ 			arg = JBD2_DEFAULT_MAX_COMMIT_AGE;
+ 		sbi->s_commit_interval = HZ * arg;
++	} else if (token == Opt_debug_want_extra_isize) {
++		sbi->s_want_extra_isize = arg;
+ 	} else if (token == Opt_max_batch_time) {
+ 		sbi->s_max_batch_time = arg;
+ 	} else if (token == Opt_min_batch_time) {
+@@ -4081,7 +4085,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		sb->s_flags |= MS_RDONLY;
+ 
+ 	/* determine the minimum size of new large inodes, if present */
+-	if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE) {
++	if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE &&
++	    sbi->s_want_extra_isize == 0) {
+ 		sbi->s_want_extra_isize = sizeof(struct ext4_inode) -
+ 						     EXT4_GOOD_OLD_INODE_SIZE;
+ 		if (ext4_has_feature_extra_isize(sb)) {

commit 56735be05353b085a0862ca4c4943628df3420ca
+Merge: a121103c9228 a5d431eff2e0
+Author: Theodore Ts'o 
+Date:   Sun Jan 8 20:57:35 2017 -0500
+
+    Merge branch 'fscrypt' into d
+

commit 173b8439e1ba362007315868928bf9d26e5cc5a6
+Author: Theodore Ts'o 
+Date:   Wed Dec 28 00:22:52 2016 -0500
+
+    ext4: don't allow encrypted operations without keys
+    
+    While we allow deletes without the key, the following should not be
+    permitted:
+    
+    # cd /vdc/encrypted-dir-without-key
+    # ls -l
+    total 4
+    -rw-r--r-- 1 root root   0 Dec 27 22:35 6,LKNRJsp209FbXoSvJWzB
+    -rw-r--r-- 1 root root 286 Dec 27 22:35 uRJ5vJh9gE7vcomYMqTAyD
+    # mv uRJ5vJh9gE7vcomYMqTAyD  6,LKNRJsp209FbXoSvJWzB
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 80b8afa4a8f9..bb880c326191 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -3527,6 +3527,12 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 			EXT4_I(old_dentry->d_inode)->i_projid)))
+ 		return -EXDEV;
+ 
++	if ((ext4_encrypted_inode(old_dir) &&
++	     !fscrypt_has_encryption_key(old_dir)) ||
++	    (ext4_encrypted_inode(new_dir) &&
++	     !fscrypt_has_encryption_key(new_dir)))
++		return -ENOKEY;
++
+ 	retval = dquot_initialize(old.dir);
+ 	if (retval)
+ 		return retval;
+@@ -3727,6 +3733,12 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 	int retval;
+ 	struct timespec ctime;
+ 
++	if ((ext4_encrypted_inode(old_dir) &&
++	     !fscrypt_has_encryption_key(old_dir)) ||
++	    (ext4_encrypted_inode(new_dir) &&
++	     !fscrypt_has_encryption_key(new_dir)))
++		return -ENOKEY;
++
+ 	if ((ext4_encrypted_inode(old_dir) ||
+ 	     ext4_encrypted_inode(new_dir)) &&
+ 	    (old_dir != new_dir) &&

commit 5bbdcbbb396196f1c94110ad7a041e90de95c4c2
+Author: Theodore Ts'o 
+Date:   Mon Jan 2 15:12:17 2017 -0500
+
+    fscrypt: make test_dummy_encryption require a keyring key
+    
+    Currently, the test_dummy_encryption ext4 mount option, which exists
+    only to test encrypted I/O paths with xfstests, overrides all
+    per-inode encryption keys with a fixed key.
+    
+    This change minimizes test_dummy_encryption-specific code path changes
+    by supplying a fake context for directories which are not encrypted
+    for use when creating new directories, files, or symlinks.  This
+    allows us to properly exercise the keyring lookup, derivation, and
+    context inheritance code paths.
+    
+    Before mounting a file system using test_dummy_encryption, userspace
+    must execute the following shell commands:
+    
+        mode='\x00\x00\x00\x00'
+        raw="$(printf ""\\\\x%02x"" $(seq 0 63))"
+        if lscpu | grep "Byte Order" | grep -q Little ; then
+            size='\x40\x00\x00\x00'
+        else
+            size='\x00\x00\x00\x40'
+        fi
+        key="${mode}${raw}${size}"
+        keyctl new_session
+        echo -n -e "${key}" | keyctl padd logon fscrypt:4242424242424242 @s
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c
+index 95cd4c3b06c3..80f145c8d550 100644
+--- a/fs/crypto/keyinfo.c
++++ b/fs/crypto/keyinfo.c
+@@ -206,12 +206,16 @@ int fscrypt_get_crypt_info(struct inode *inode)
+ 
+ 	res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx));
+ 	if (res < 0) {
+-		if (!fscrypt_dummy_context_enabled(inode))
++		if (!fscrypt_dummy_context_enabled(inode) ||
++		    inode->i_sb->s_cop->is_encrypted(inode))
+ 			return res;
++		/* Fake up a context for an unencrypted directory */
++		memset(&ctx, 0, sizeof(ctx));
+ 		ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1;
+ 		ctx.contents_encryption_mode = FS_ENCRYPTION_MODE_AES_256_XTS;
+ 		ctx.filenames_encryption_mode = FS_ENCRYPTION_MODE_AES_256_CTS;
+-		ctx.flags = 0;
++		memset(ctx.master_key_descriptor, 0x42, FS_KEY_DESCRIPTOR_SIZE);
++		res = sizeof(ctx);
+ 	} else if (res != sizeof(ctx)) {
+ 		return -EINVAL;
+ 	}
+@@ -247,12 +251,6 @@ int fscrypt_get_crypt_info(struct inode *inode)
+ 	if (!raw_key)
+ 		goto out;
+ 
+-	if (fscrypt_dummy_context_enabled(inode)) {
+-		memset(raw_key, 0x42, keysize/2);
+-		memset(raw_key+keysize/2, 0x24, keysize - (keysize/2));
+-		goto got_key;
+-	}
+-
+ 	res = validate_user_key(crypt_info, &ctx, raw_key,
+ 			FS_KEY_DESC_PREFIX, FS_KEY_DESC_PREFIX_SIZE);
+ 	if (res && inode->i_sb->s_cop->key_prefix) {
+@@ -270,7 +268,6 @@ int fscrypt_get_crypt_info(struct inode *inode)
+ 	} else if (res) {
+ 		goto out;
+ 	}
+-got_key:
+ 	ctfm = crypto_alloc_skcipher(cipher_str, 0, 0);
+ 	if (!ctfm || IS_ERR(ctfm)) {
+ 		res = ctfm ? PTR_ERR(ctfm) : -ENOMEM;
+diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c
+index 4c99972899c7..14b76da71269 100644
+--- a/fs/crypto/policy.c
++++ b/fs/crypto/policy.c
+@@ -198,9 +198,9 @@ EXPORT_SYMBOL(fscrypt_has_permitted_context);
+  * @parent: Parent inode from which the context is inherited.
+  * @child:  Child inode that inherits the context from @parent.
+  * @fs_data:  private data given by FS.
+- * @preload:  preload child i_crypt_info
++ * @preload:  preload child i_crypt_info if true
+  *
+- * Return: Zero on success, non-zero otherwise
++ * Return: 0 on success, -errno on failure
+  */
+ int fscrypt_inherit_context(struct inode *parent, struct inode *child,
+ 						void *fs_data, bool preload)
+@@ -221,19 +221,11 @@ int fscrypt_inherit_context(struct inode *parent, struct inode *child,
+ 		return -ENOKEY;
+ 
+ 	ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1;
+-	if (fscrypt_dummy_context_enabled(parent)) {
+-		ctx.contents_encryption_mode = FS_ENCRYPTION_MODE_AES_256_XTS;
+-		ctx.filenames_encryption_mode = FS_ENCRYPTION_MODE_AES_256_CTS;
+-		ctx.flags = 0;
+-		memset(ctx.master_key_descriptor, 0x42, FS_KEY_DESCRIPTOR_SIZE);
+-		res = 0;
+-	} else {
+-		ctx.contents_encryption_mode = ci->ci_data_mode;
+-		ctx.filenames_encryption_mode = ci->ci_filename_mode;
+-		ctx.flags = ci->ci_flags;
+-		memcpy(ctx.master_key_descriptor, ci->ci_master_key,
+-				FS_KEY_DESCRIPTOR_SIZE);
+-	}
++	ctx.contents_encryption_mode = ci->ci_data_mode;
++	ctx.filenames_encryption_mode = ci->ci_filename_mode;
++	ctx.flags = ci->ci_flags;
++	memcpy(ctx.master_key_descriptor, ci->ci_master_key,
++	       FS_KEY_DESCRIPTOR_SIZE);
+ 	get_random_bytes(ctx.nonce, FS_KEY_DERIVATION_NONCE_SIZE);
+ 	res = parent->i_sb->s_cop->set_context(child, &ctx,
+ 						sizeof(ctx), fs_data);

commit fe4f6c801c03bc13113d0dc32f02d4ea8ed89ffd
+Author: Theodore Ts'o 
+Date:   Tue Dec 27 19:46:27 2016 -0500
+
+    fscrypt: fix the test_dummy_encryption mount option
+    
+    Commit f1c131b45410a: "crypto: xts - Convert to skcipher" now fails
+    the setkey operation if the AES key is the same as the tweak key.
+    Previously this check was only done if FIPS mode is enabled.  Now this
+    check is also done if weak key checking was requested.  This is
+    reasonable, but since we were using the dummy key which was a constant
+    series of 0x42 bytes, it now caused dummy encrpyption test mode to
+    fail.
+    
+    Fix this by using 0x42... and 0x24... for the two keys, so they are
+    different.
+    
+    Fixes: f1c131b45410a202eb45cc55980a7a9e4e4b4f40
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c
+index 6eeea1dcba41..95cd4c3b06c3 100644
+--- a/fs/crypto/keyinfo.c
++++ b/fs/crypto/keyinfo.c
+@@ -248,7 +248,8 @@ int fscrypt_get_crypt_info(struct inode *inode)
+ 		goto out;
+ 
+ 	if (fscrypt_dummy_context_enabled(inode)) {
+-		memset(raw_key, 0x42, FS_AES_256_XTS_KEY_SIZE);
++		memset(raw_key, 0x42, keysize/2);
++		memset(raw_key+keysize/2, 0x24, keysize - (keysize/2));
+ 		goto got_key;
+ 	}
+ 

commit a551d7c8deefb6d9fb45a1de03a617dd064e0419
+Merge: 0cb80b484755 6a34e4d2be07
+Author: Theodore Ts'o 
+Date:   Mon Dec 12 21:50:28 2016 -0500
+
+    Merge branch 'fscrypt' into dev
+
+diff --cc fs/ext4/ioctl.c
+index fcc9510a819c,70083863ce51..49fd1371bfa2
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@@ -787,24 -765,13 +787,14 @@@ resizefs_out
+  	}
+  	case EXT4_IOC_PRECACHE_EXTENTS:
+  		return ext4_ext_precache(inode);
+- 	case EXT4_IOC_SET_ENCRYPTION_POLICY: {
+- #ifdef CONFIG_EXT4_FS_ENCRYPTION
+- 		struct fscrypt_policy policy;
+  
++ 	case EXT4_IOC_SET_ENCRYPTION_POLICY:
+  		if (!ext4_has_feature_encrypt(sb))
+  			return -EOPNOTSUPP;
++ 		return fscrypt_ioctl_set_policy(filp, (const void __user *)arg);
+  
+- 		if (copy_from_user(&policy,
+- 				   (struct fscrypt_policy __user *)arg,
+- 				   sizeof(policy)))
+- 			return -EFAULT;
+- 		return fscrypt_process_policy(filp, &policy);
+- #else
+- 		return -EOPNOTSUPP;
+- #endif
+- 	}
+  	case EXT4_IOC_GET_ENCRYPTION_PWSALT: {
+ +#ifdef CONFIG_EXT4_FS_ENCRYPTION
+  		int err, err2;
+  		struct ext4_sb_info *sbi = EXT4_SB(sb);
+  		handle_t *handle;
+@@@ -839,27 -806,10 +829,13 @@@
+  				 sbi->s_es->s_encrypt_pw_salt, 16))
+  			return -EFAULT;
+  		return 0;
+ +#else
+ +		return -EOPNOTSUPP;
+ +#endif
+  	}
+- 	case EXT4_IOC_GET_ENCRYPTION_POLICY: {
+- #ifdef CONFIG_EXT4_FS_ENCRYPTION
+- 		struct fscrypt_policy policy;
+- 		int err = 0;
++ 	case EXT4_IOC_GET_ENCRYPTION_POLICY:
++ 		return fscrypt_ioctl_get_policy(filp, (void __user *)arg);
+  
+- 		if (!ext4_encrypted_inode(inode))
+- 			return -ENOENT;
+- 		err = fscrypt_get_policy(inode, &policy);
+- 		if (err)
+- 			return err;
+- 		if (copy_to_user((void __user *)arg, &policy, sizeof(policy)))
+- 			return -EFAULT;
+- 		return 0;
+- #else
+- 		return -EOPNOTSUPP;
+- #endif
+- 	}
+  	case EXT4_IOC_FSGETXATTR:
+  	{
+  		struct fsxattr fa;

commit 41d5319af3368127b55f6587f1c747dd6a7b9b04
+Author: Theodore Ts'o 
+Date:   Sat Nov 26 22:18:59 2016 -0500
+
+    fscrypt: move the policy flags and encryption mode definitions to uapi header
+    
+    These constants are part of the UAPI, so they belong in
+    include/uapi/linux/fs.h instead of include/linux/fscrypto.h
+    
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Eric Biggers 
+
+diff --git a/include/linux/fscrypto.h b/include/linux/fscrypto.h
+index 71e8a20711ec..42ef82d60790 100644
+--- a/include/linux/fscrypto.h
++++ b/include/linux/fscrypto.h
+@@ -18,20 +18,6 @@
+ #include 
+ #include 
+ 
+-#define FS_POLICY_FLAGS_PAD_4		0x00
+-#define FS_POLICY_FLAGS_PAD_8		0x01
+-#define FS_POLICY_FLAGS_PAD_16		0x02
+-#define FS_POLICY_FLAGS_PAD_32		0x03
+-#define FS_POLICY_FLAGS_PAD_MASK	0x03
+-#define FS_POLICY_FLAGS_VALID		0x03
+-
+-/* Encryption algorithms */
+-#define FS_ENCRYPTION_MODE_INVALID		0
+-#define FS_ENCRYPTION_MODE_AES_256_XTS		1
+-#define FS_ENCRYPTION_MODE_AES_256_GCM		2
+-#define FS_ENCRYPTION_MODE_AES_256_CBC		3
+-#define FS_ENCRYPTION_MODE_AES_256_CTS		4
+-
+ #define FS_CRYPTO_BLOCK_SIZE		16
+ 
+ struct fscrypt_info;
+diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
+index acb2b6152ba0..0496d37abe28 100644
+--- a/include/uapi/linux/fs.h
++++ b/include/uapi/linux/fs.h
+@@ -254,6 +254,20 @@ struct fsxattr {
+ /* Policy provided via an ioctl on the topmost directory */
+ #define FS_KEY_DESCRIPTOR_SIZE	8
+ 
++#define FS_POLICY_FLAGS_PAD_4		0x00
++#define FS_POLICY_FLAGS_PAD_8		0x01
++#define FS_POLICY_FLAGS_PAD_16		0x02
++#define FS_POLICY_FLAGS_PAD_32		0x03
++#define FS_POLICY_FLAGS_PAD_MASK	0x03
++#define FS_POLICY_FLAGS_VALID		0x03
++
++/* Encryption algorithms */
++#define FS_ENCRYPTION_MODE_INVALID		0
++#define FS_ENCRYPTION_MODE_AES_256_XTS		1
++#define FS_ENCRYPTION_MODE_AES_256_GCM		2
++#define FS_ENCRYPTION_MODE_AES_256_CBC		3
++#define FS_ENCRYPTION_MODE_AES_256_CTS		4
++
+ struct fscrypt_policy {
+ 	__u8 version;
+ 	__u8 contents_encryption_mode;

commit cc4e0df038ddb73510c01712abf302b3f0130147
+Author: Theodore Ts'o 
+Date:   Sat Nov 26 22:05:18 2016 -0500
+
+    fscrypt: move non-public structures and constants to fscrypt_private.h
+    
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Eric Biggers 
+
+diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
+index 56f98f45cece..4d9d221b1d60 100644
+--- a/fs/crypto/crypto.c
++++ b/fs/crypto/crypto.c
+@@ -27,7 +27,7 @@
+ #include 
+ #include 
+ #include 
+-#include 
++#include "fscrypt_private.h"
+ 
+ static unsigned int num_prealloc_crypto_pages = 32;
+ static unsigned int num_prealloc_crypto_ctxs = 128;
+diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
+index bb92f0c0961b..c98b2a7fb6d3 100644
+--- a/fs/crypto/fscrypt_private.h
++++ b/fs/crypto/fscrypt_private.h
+@@ -13,6 +13,77 @@
+ 
+ #include 
+ 
++#define FS_FNAME_CRYPTO_DIGEST_SIZE	32
++
++/* Encryption parameters */
++#define FS_XTS_TWEAK_SIZE		16
++#define FS_AES_128_ECB_KEY_SIZE		16
++#define FS_AES_256_GCM_KEY_SIZE		32
++#define FS_AES_256_CBC_KEY_SIZE		32
++#define FS_AES_256_CTS_KEY_SIZE		32
++#define FS_AES_256_XTS_KEY_SIZE		64
++#define FS_MAX_KEY_SIZE			64
++
++#define FS_KEY_DESC_PREFIX		"fscrypt:"
++#define FS_KEY_DESC_PREFIX_SIZE		8
++
++#define FS_KEY_DERIVATION_NONCE_SIZE		16
++
++/**
++ * Encryption context for inode
++ *
++ * Protector format:
++ *  1 byte: Protector format (1 = this version)
++ *  1 byte: File contents encryption mode
++ *  1 byte: File names encryption mode
++ *  1 byte: Flags
++ *  8 bytes: Master Key descriptor
++ *  16 bytes: Encryption Key derivation nonce
++ */
++struct fscrypt_context {
++	u8 format;
++	u8 contents_encryption_mode;
++	u8 filenames_encryption_mode;
++	u8 flags;
++	u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
++	u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
++} __packed;
++
++#define FS_ENCRYPTION_CONTEXT_FORMAT_V1		1
++
++/* This is passed in from userspace into the kernel keyring */
++struct fscrypt_key {
++	u32 mode;
++	u8 raw[FS_MAX_KEY_SIZE];
++	u32 size;
++} __packed;
++
++/*
++ * A pointer to this structure is stored in the file system's in-core
++ * representation of an inode.
++ */
++struct fscrypt_info {
++	u8 ci_data_mode;
++	u8 ci_filename_mode;
++	u8 ci_flags;
++	struct crypto_skcipher *ci_ctfm;
++	struct key *ci_keyring_key;
++	u8 ci_master_key[FS_KEY_DESCRIPTOR_SIZE];
++};
++
++#define FS_CTX_REQUIRES_FREE_ENCRYPT_FL		0x00000001
++#define FS_WRITE_PATH_FL			0x00000002
++
++struct fscrypt_completion_result {
++	struct completion completion;
++	int res;
++};
++
++#define DECLARE_FS_COMPLETION_RESULT(ecr) \
++	struct fscrypt_completion_result ecr = { \
++		COMPLETION_INITIALIZER((ecr).completion), 0 }
++
++
+ /* crypto.c */
+ int fscrypt_initialize(void);
+ 
+diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c
+index b96a10e3cf78..6ed7c2eebeec 100644
+--- a/fs/crypto/policy.c
++++ b/fs/crypto/policy.c
+@@ -10,8 +10,8 @@
+ 
+ #include 
+ #include 
+-#include 
+ #include 
++#include "fscrypt_private.h"
+ 
+ static int inode_has_encryption_context(struct inode *inode)
+ {
+diff --git a/include/linux/fscrypto.h b/include/linux/fscrypto.h
+index ce2ebdee6a89..71e8a20711ec 100644
+--- a/include/linux/fscrypto.h
++++ b/include/linux/fscrypto.h
+@@ -18,9 +18,6 @@
+ #include 
+ #include 
+ 
+-#define FS_KEY_DERIVATION_NONCE_SIZE		16
+-#define FS_ENCRYPTION_CONTEXT_FORMAT_V1		1
+-
+ #define FS_POLICY_FLAGS_PAD_4		0x00
+ #define FS_POLICY_FLAGS_PAD_8		0x01
+ #define FS_POLICY_FLAGS_PAD_16		0x02
+@@ -35,56 +32,10 @@
+ #define FS_ENCRYPTION_MODE_AES_256_CBC		3
+ #define FS_ENCRYPTION_MODE_AES_256_CTS		4
+ 
+-/**
+- * Encryption context for inode
+- *
+- * Protector format:
+- *  1 byte: Protector format (1 = this version)
+- *  1 byte: File contents encryption mode
+- *  1 byte: File names encryption mode
+- *  1 byte: Flags
+- *  8 bytes: Master Key descriptor
+- *  16 bytes: Encryption Key derivation nonce
+- */
+-struct fscrypt_context {
+-	u8 format;
+-	u8 contents_encryption_mode;
+-	u8 filenames_encryption_mode;
+-	u8 flags;
+-	u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
+-	u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
+-} __packed;
+-
+-/* Encryption parameters */
+-#define FS_XTS_TWEAK_SIZE		16
+-#define FS_AES_128_ECB_KEY_SIZE		16
+-#define FS_AES_256_GCM_KEY_SIZE		32
+-#define FS_AES_256_CBC_KEY_SIZE		32
+-#define FS_AES_256_CTS_KEY_SIZE		32
+-#define FS_AES_256_XTS_KEY_SIZE		64
+-#define FS_MAX_KEY_SIZE			64
+-
+-#define FS_KEY_DESC_PREFIX		"fscrypt:"
+-#define FS_KEY_DESC_PREFIX_SIZE		8
+-
+-/* This is passed in from userspace into the kernel keyring */
+-struct fscrypt_key {
+-	u32 mode;
+-	u8 raw[FS_MAX_KEY_SIZE];
+-	u32 size;
+-} __packed;
+-
+-struct fscrypt_info {
+-	u8 ci_data_mode;
+-	u8 ci_filename_mode;
+-	u8 ci_flags;
+-	struct crypto_skcipher *ci_ctfm;
+-	struct key *ci_keyring_key;
+-	u8 ci_master_key[FS_KEY_DESCRIPTOR_SIZE];
+-};
++#define FS_CRYPTO_BLOCK_SIZE		16
+ 
+-#define FS_CTX_REQUIRES_FREE_ENCRYPT_FL		0x00000001
+-#define FS_WRITE_PATH_FL			0x00000002
++struct fscrypt_info;
++struct fscrypt_ctx;
+ 
+ struct fscrypt_ctx {
+ 	union {
+@@ -102,19 +53,6 @@ struct fscrypt_ctx {
+ 	u8 mode;				/* Encryption mode for tfm */
+ };
+ 
+-struct fscrypt_completion_result {
+-	struct completion completion;
+-	int res;
+-};
+-
+-#define DECLARE_FS_COMPLETION_RESULT(ecr) \
+-	struct fscrypt_completion_result ecr = { \
+-		COMPLETION_INITIALIZER((ecr).completion), 0 }
+-
+-#define FS_FNAME_NUM_SCATTER_ENTRIES	4
+-#define FS_CRYPTO_BLOCK_SIZE		16
+-#define FS_FNAME_CRYPTO_DIGEST_SIZE	32
+-
+ /**
+  * For encrypted symlinks, the ciphertext length is stored at the beginning
+  * of the string in little-endian format.

commit b98701df349b7003efd52d9330acbb7be5a255c6
+Author: Theodore Ts'o 
+Date:   Sat Nov 26 20:43:09 2016 -0500
+
+    fscrypt: unexport fscrypt_initialize()
+    
+    The fscrypt_initalize() function isn't used outside fs/crypto, so
+    there's no point making it be an exported symbol.
+    
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Eric Biggers 
+
+diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
+index b6029785714c..56f98f45cece 100644
+--- a/fs/crypto/crypto.c
++++ b/fs/crypto/crypto.c
+@@ -540,7 +540,6 @@ int fscrypt_initialize(void)
+ 	mutex_unlock(&fscrypt_init_mutex);
+ 	return res;
+ }
+-EXPORT_SYMBOL(fscrypt_initialize);
+ 
+ /**
+  * fscrypt_init() - Set up for fs encryption.
+diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
+index 7c31108728e4..bb92f0c0961b 100644
+--- a/fs/crypto/fscrypt_private.h
++++ b/fs/crypto/fscrypt_private.h
+@@ -13,6 +13,9 @@
+ 
+ #include 
+ 
++/* crypto.c */
++int fscrypt_initialize(void);
++
+ /* keyinfo.c */
+ extern int fscrypt_get_crypt_info(struct inode *);
+ 
+diff --git a/include/linux/fscrypto.h b/include/linux/fscrypto.h
+index 2f8894f0696c..ce2ebdee6a89 100644
+--- a/include/linux/fscrypto.h
++++ b/include/linux/fscrypto.h
+@@ -244,7 +244,6 @@ static inline void fscrypt_set_d_op(struct dentry *dentry)
+ #if IS_ENABLED(CONFIG_FS_ENCRYPTION)
+ /* crypto.c */
+ extern struct kmem_cache *fscrypt_info_cachep;
+-int fscrypt_initialize(void);
+ 
+ extern struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *, gfp_t);
+ extern void fscrypt_release_ctx(struct fscrypt_ctx *);

commit 3325bea5b26ac67e2521383f10e5ea0156c9a4b6
+Author: Theodore Ts'o 
+Date:   Sat Nov 26 20:32:46 2016 -0500
+
+    fscrypt: rename get_crypt_info() to fscrypt_get_crypt_info()
+    
+    To avoid namespace collisions, rename get_crypt_info() to
+    fscrypt_get_crypt_info().  The function is only used inside the
+    fs/crypto directory, so declare it in the new header file,
+    fscrypt_private.h.
+    
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Eric Biggers 
+
+diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c
+index 6b45d9caeeb0..56ad9d195f18 100644
+--- a/fs/crypto/fname.c
++++ b/fs/crypto/fname.c
+@@ -12,7 +12,7 @@
+ 
+ #include 
+ #include 
+-#include 
++#include "fscrypt_private.h"
+ 
+ /**
+  * fname_crypt_complete() - completion callback for filename crypto
+@@ -350,7 +350,7 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname,
+ 		fname->disk_name.len = iname->len;
+ 		return 0;
+ 	}
+-	ret = get_crypt_info(dir);
++	ret = fscrypt_get_crypt_info(dir);
+ 	if (ret && ret != -EOPNOTSUPP)
+ 		return ret;
+ 
+diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
+new file mode 100644
+index 000000000000..7c31108728e4
+--- /dev/null
++++ b/fs/crypto/fscrypt_private.h
+@@ -0,0 +1,19 @@
++/*
++ * fscrypt_private.h
++ *
++ * Copyright (C) 2015, Google, Inc.
++ *
++ * This contains encryption key functions.
++ *
++ * Written by Michael Halcrow, Ildar Muslukhov, and Uday Savagaonkar, 2015.
++ */
++
++#ifndef _FSCRYPT_PRIVATE_H
++#define _FSCRYPT_PRIVATE_H
++
++#include 
++
++/* keyinfo.c */
++extern int fscrypt_get_crypt_info(struct inode *);
++
++#endif /* _FSCRYPT_PRIVATE_H */
+diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c
+index 67fb6d8876d0..35d3317a27b3 100644
+--- a/fs/crypto/keyinfo.c
++++ b/fs/crypto/keyinfo.c
+@@ -10,7 +10,7 @@
+ 
+ #include 
+ #include 
+-#include 
++#include "fscrypt_private.h"
+ 
+ static void derive_crypt_complete(struct crypto_async_request *req, int rc)
+ {
+@@ -178,7 +178,7 @@ static void put_crypt_info(struct fscrypt_info *ci)
+ 	kmem_cache_free(fscrypt_info_cachep, ci);
+ }
+ 
+-int get_crypt_info(struct inode *inode)
++int fscrypt_get_crypt_info(struct inode *inode)
+ {
+ 	struct fscrypt_info *crypt_info;
+ 	struct fscrypt_context ctx;
+@@ -327,7 +327,7 @@ int fscrypt_get_encryption_info(struct inode *inode)
+ 		 (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) |
+ 					       (1 << KEY_FLAG_REVOKED) |
+ 					       (1 << KEY_FLAG_DEAD)))))
+-		return get_crypt_info(inode);
++		return fscrypt_get_crypt_info(inode);
+ 	return 0;
+ }
+ EXPORT_SYMBOL(fscrypt_get_encryption_info);
+diff --git a/include/linux/fscrypto.h b/include/linux/fscrypto.h
+index be94684dc05f..2f8894f0696c 100644
+--- a/include/linux/fscrypto.h
++++ b/include/linux/fscrypto.h
+@@ -265,7 +265,6 @@ extern int fscrypt_has_permitted_context(struct inode *, struct inode *);
+ extern int fscrypt_inherit_context(struct inode *, struct inode *,
+ 					void *, bool);
+ /* keyinfo.c */
+-extern int get_crypt_info(struct inode *);
+ extern int fscrypt_get_encryption_info(struct inode *);
+ extern void fscrypt_put_encryption_info(struct inode *, struct fscrypt_info *);
+ 

commit 4db0d88e2ebc4f47092adc01f9885a43ad748995
+Author: Theodore Ts'o 
+Date:   Fri Dec 2 12:12:53 2016 -0500
+
+    ext4: fix reading new encrypted symlinks on no-journal file systems
+    
+    On a filesystem with no journal, a symlink longer than about 32
+    characters (exact length depending on padding for encryption) could not
+    be followed or read immediately after being created in an encrypted
+    directory.  This happened because when the symlink data went through the
+    delayed allocation path instead of the journaling path, the symlink was
+    incorrectly detected as a "fast" symlink rather than a "slow" symlink
+    until its data was written out.
+    
+    To fix this, disable delayed allocation for symlinks, since there is
+    no benefit for delayed allocation anyway.
+    
+    Reported-by: Eric Biggers 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 59a518ad6bb2..a1eac0054203 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2902,7 +2902,8 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
+ 
+ 	index = pos >> PAGE_SHIFT;
+ 
+-	if (ext4_nonda_switch(inode->i_sb)) {
++	if (ext4_nonda_switch(inode->i_sb) ||
++	    S_ISLNK(inode->i_mode)) {
+ 		*fsdata = (void *)FALL_BACK_TO_NONDELALLOC;
+ 		return ext4_write_begin(file, mapping, pos,
+ 					len, flags, pagep, fsdata);

commit 8cdf3372fe8368f56315e66bea9f35053c418093
+Author: Theodore Ts'o 
+Date:   Fri Nov 18 13:00:24 2016 -0500
+
+    ext4: sanity check the block and cluster size at mount time
+    
+    If the block size or cluster size is insane, reject the mount.  This
+    is important for security reasons (although we shouldn't be just
+    depending on this check).
+    
+    Ref: http://www.securityfocus.com/archive/1/539661
+    Ref: https://bugzilla.redhat.com/show_bug.cgi?id=1332506
+    Reported-by: Borislav Petkov 
+    Reported-by: Nikolay Borisov 
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 282a51b07c57..a8a750f59621 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -235,6 +235,7 @@ struct ext4_io_submit {
+ #define	EXT4_MAX_BLOCK_SIZE		65536
+ #define EXT4_MIN_BLOCK_LOG_SIZE		10
+ #define EXT4_MAX_BLOCK_LOG_SIZE		16
++#define EXT4_MAX_CLUSTER_LOG_SIZE	30
+ #ifdef __KERNEL__
+ # define EXT4_BLOCK_SIZE(s)		((s)->s_blocksize)
+ #else
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 20da99da0a34..52b0530c5d65 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3565,7 +3565,15 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	if (blocksize < EXT4_MIN_BLOCK_SIZE ||
+ 	    blocksize > EXT4_MAX_BLOCK_SIZE) {
+ 		ext4_msg(sb, KERN_ERR,
+-		       "Unsupported filesystem blocksize %d", blocksize);
++		       "Unsupported filesystem blocksize %d (%d log_block_size)",
++			 blocksize, le32_to_cpu(es->s_log_block_size));
++		goto failed_mount;
++	}
++	if (le32_to_cpu(es->s_log_block_size) >
++	    (EXT4_MAX_BLOCK_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) {
++		ext4_msg(sb, KERN_ERR,
++			 "Invalid log block size: %u",
++			 le32_to_cpu(es->s_log_block_size));
+ 		goto failed_mount;
+ 	}
+ 
+@@ -3697,6 +3705,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 				 "block size (%d)", clustersize, blocksize);
+ 			goto failed_mount;
+ 		}
++		if (le32_to_cpu(es->s_log_cluster_size) >
++		    (EXT4_MAX_CLUSTER_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) {
++			ext4_msg(sb, KERN_ERR,
++				 "Invalid log cluster size: %u",
++				 le32_to_cpu(es->s_log_cluster_size));
++			goto failed_mount;
++		}
+ 		sbi->s_cluster_bits = le32_to_cpu(es->s_log_cluster_size) -
+ 			le32_to_cpu(es->s_log_block_size);
+ 		sbi->s_clusters_per_group =

commit c48ae41bafe31e9a66d8be2ced4e42a6b57fa814
+Author: Theodore Ts'o 
+Date:   Fri Nov 18 13:37:47 2016 -0500
+
+    ext4: add sanity checking to count_overhead()
+    
+    The commit "ext4: sanity check the block and cluster size at mount
+    time" should prevent any problems, but in case the superblock is
+    modified while the file system is mounted, add an extra safety check
+    to make sure we won't overrun the allocated buffer.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 689c02df1af4..2d8a49d74f56 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3195,10 +3195,15 @@ static int count_overhead(struct super_block *sb, ext4_group_t grp,
+ 			ext4_set_bit(s++, buf);
+ 			count++;
+ 		}
+-		for (j = ext4_bg_num_gdb(sb, grp); j > 0; j--) {
+-			ext4_set_bit(EXT4_B2C(sbi, s++), buf);
+-			count++;
++		j = ext4_bg_num_gdb(sb, grp);
++		if (s + j > EXT4_BLOCKS_PER_GROUP(sb)) {
++			ext4_error(sb, "Invalid number of block group "
++				   "descriptor blocks: %d", j);
++			j = EXT4_BLOCKS_PER_GROUP(sb) - s;
+ 		}
++		count += j;
++		for (; j > 0; j--)
++			ext4_set_bit(EXT4_B2C(sbi, s++), buf);
+ 	}
+ 	if (!count)
+ 		return 0;

commit cd6bb35bf7f6d7d922509bf50265383a0ceabe96
+Author: Theodore Ts'o 
+Date:   Fri Nov 18 13:28:30 2016 -0500
+
+    ext4: use more strict checks for inodes_per_block on mount
+    
+    Centralize the checks for inodes_per_block and be more strict to make
+    sure the inodes_per_block_group can't end up being zero.
+    
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Andreas Dilger 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 404e6f3c1bed..689c02df1af4 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3668,12 +3668,16 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 
+ 	sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);
+ 	sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);
+-	if (EXT4_INODE_SIZE(sb) == 0 || EXT4_INODES_PER_GROUP(sb) == 0)
+-		goto cantfind_ext4;
+ 
+ 	sbi->s_inodes_per_block = blocksize / EXT4_INODE_SIZE(sb);
+ 	if (sbi->s_inodes_per_block == 0)
+ 		goto cantfind_ext4;
++	if (sbi->s_inodes_per_group < sbi->s_inodes_per_block ||
++	    sbi->s_inodes_per_group > blocksize * 8) {
++		ext4_msg(sb, KERN_ERR, "invalid inodes per group: %lu\n",
++			 sbi->s_blocks_per_group);
++		goto failed_mount;
++	}
+ 	sbi->s_itb_per_group = sbi->s_inodes_per_group /
+ 					sbi->s_inodes_per_block;
+ 	sbi->s_desc_per_block = blocksize / EXT4_DESC_SIZE(sb);
+@@ -3756,13 +3760,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	}
+ 	sbi->s_cluster_ratio = clustersize / blocksize;
+ 
+-	if (sbi->s_inodes_per_group > blocksize * 8) {
+-		ext4_msg(sb, KERN_ERR,
+-		       "#inodes per group too big: %lu",
+-		       sbi->s_inodes_per_group);
+-		goto failed_mount;
+-	}
+-
+ 	/* Do we have standard group size of clustersize * 8 blocks ? */
+ 	if (sbi->s_blocks_per_group == clustersize << 3)
+ 		set_opt2(sb, STD_GROUP_SIZE);

commit 5aee0f8a3f42c94c5012f1673420aee96315925a
+Author: Theodore Ts'o 
+Date:   Fri Nov 18 13:24:26 2016 -0500
+
+    ext4: fix in-superblock mount options processing
+    
+    Fix a large number of problems with how we handle mount options in the
+    superblock.  For one, if the string in the superblock is long enough
+    that it is not null terminated, we could run off the end of the string
+    and try to interpret superblocks fields as characters.  It's unlikely
+    this will cause a security problem, but it could result in an invalid
+    parse.  Also, parse_options is destructive to the string, so in some
+    cases if there is a comma-separated string, it would be modified in
+    the superblock.  (Fortunately it only happens on file systems with a
+    1k block size.)
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 0f9ae4ce33d6..404e6f3c1bed 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3303,7 +3303,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	char *orig_data = kstrdup(data, GFP_KERNEL);
+ 	struct buffer_head *bh;
+ 	struct ext4_super_block *es = NULL;
+-	struct ext4_sb_info *sbi;
++	struct ext4_sb_info *sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
+ 	ext4_fsblk_t block;
+ 	ext4_fsblk_t sb_block = get_sb_block(&data);
+ 	ext4_fsblk_t logical_sb_block;
+@@ -3322,16 +3322,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO;
+ 	ext4_group_t first_not_zeroed;
+ 
+-	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
+-	if (!sbi)
+-		goto out_free_orig;
++	if ((data && !orig_data) || !sbi)
++		goto out_free_base;
+ 
+ 	sbi->s_blockgroup_lock =
+ 		kzalloc(sizeof(struct blockgroup_lock), GFP_KERNEL);
+-	if (!sbi->s_blockgroup_lock) {
+-		kfree(sbi);
+-		goto out_free_orig;
+-	}
++	if (!sbi->s_blockgroup_lock)
++		goto out_free_base;
++
+ 	sb->s_fs_info = sbi;
+ 	sbi->s_sb = sb;
+ 	sbi->s_inode_readahead_blks = EXT4_DEF_INODE_READAHEAD_BLKS;
+@@ -3477,11 +3475,19 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	 */
+ 	sbi->s_li_wait_mult = EXT4_DEF_LI_WAIT_MULT;
+ 
+-	if (!parse_options((char *) sbi->s_es->s_mount_opts, sb,
+-			   &journal_devnum, &journal_ioprio, 0)) {
+-		ext4_msg(sb, KERN_WARNING,
+-			 "failed to parse options in superblock: %s",
+-			 sbi->s_es->s_mount_opts);
++	if (sbi->s_es->s_mount_opts[0]) {
++		char *s_mount_opts = kstrndup(sbi->s_es->s_mount_opts,
++					      sizeof(sbi->s_es->s_mount_opts),
++					      GFP_KERNEL);
++		if (!s_mount_opts)
++			goto failed_mount;
++		if (!parse_options(s_mount_opts, sb, &journal_devnum,
++				   &journal_ioprio, 0)) {
++			ext4_msg(sb, KERN_WARNING,
++				 "failed to parse options in superblock: %s",
++				 s_mount_opts);
++		}
++		kfree(s_mount_opts);
+ 	}
+ 	sbi->s_def_mount_opt = sbi->s_mount_opt;
+ 	if (!parse_options((char *) data, sb, &journal_devnum,
+@@ -4162,7 +4168,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 
+ 	if (___ratelimit(&ext4_mount_msg_ratelimit, "EXT4-fs mount"))
+ 		ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. "
+-			 "Opts: %s%s%s", descr, sbi->s_es->s_mount_opts,
++			 "Opts: %.*s%s%s", descr,
++			 (int) sizeof(sbi->s_es->s_mount_opts),
++			 sbi->s_es->s_mount_opts,
+ 			 *sbi->s_es->s_mount_opts ? "; " : "", orig_data);
+ 
+ 	if (es->s_error_count)
+@@ -4241,8 +4249,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ out_fail:
+ 	sb->s_fs_info = NULL;
+ 	kfree(sbi->s_blockgroup_lock);
++out_free_base:
+ 	kfree(sbi);
+-out_free_orig:
+ 	kfree(orig_data);
+ 	return err ? err : ret;
+ }

commit 9e47a4c9fc58032ee135bf76516809c7624b1551
+Author: Theodore Ts'o 
+Date:   Fri Nov 18 13:00:24 2016 -0500
+
+    ext4: sanity check the block and cluster size at mount time
+    
+    If the block size or cluster size is insane, reject the mount.  This
+    is important for security reasons (although we shouldn't be just
+    depending on this check).
+    
+    Ref: http://www.securityfocus.com/archive/1/539661
+    Ref: https://bugzilla.redhat.com/show_bug.cgi?id=1332506
+    Reported-by: Borislav Petkov 
+    Reported-by: Nikolay Borisov 
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 53d6d463ac4d..bdf1e5ee8642 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -235,6 +235,7 @@ struct ext4_io_submit {
+ #define	EXT4_MAX_BLOCK_SIZE		65536
+ #define EXT4_MIN_BLOCK_LOG_SIZE		10
+ #define EXT4_MAX_BLOCK_LOG_SIZE		16
++#define EXT4_MAX_CLUSTER_LOG_SIZE	30
+ #ifdef __KERNEL__
+ # define EXT4_BLOCK_SIZE(s)		((s)->s_blocksize)
+ #else
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 35ccbdc2d64e..0f9ae4ce33d6 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3567,7 +3567,15 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	if (blocksize < EXT4_MIN_BLOCK_SIZE ||
+ 	    blocksize > EXT4_MAX_BLOCK_SIZE) {
+ 		ext4_msg(sb, KERN_ERR,
+-		       "Unsupported filesystem blocksize %d", blocksize);
++		       "Unsupported filesystem blocksize %d (%d log_block_size)",
++			 blocksize, le32_to_cpu(es->s_log_block_size));
++		goto failed_mount;
++	}
++	if (le32_to_cpu(es->s_log_block_size) >
++	    (EXT4_MAX_BLOCK_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) {
++		ext4_msg(sb, KERN_ERR,
++			 "Invalid log block size: %u",
++			 le32_to_cpu(es->s_log_block_size));
+ 		goto failed_mount;
+ 	}
+ 
+@@ -3699,6 +3707,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 				 "block size (%d)", clustersize, blocksize);
+ 			goto failed_mount;
+ 		}
++		if (le32_to_cpu(es->s_log_cluster_size) >
++		    (EXT4_MAX_CLUSTER_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) {
++			ext4_msg(sb, KERN_ERR,
++				 "Invalid log cluster size: %u",
++				 le32_to_cpu(es->s_log_cluster_size));
++			goto failed_mount;
++		}
+ 		sbi->s_cluster_bits = le32_to_cpu(es->s_log_cluster_size) -
+ 			le32_to_cpu(es->s_log_block_size);
+ 		sbi->s_clusters_per_group =

commit 1566a48aaa10c6bb29b9a69dd8279f9a4fc41e35
+Author: Theodore Ts'o 
+Date:   Sun Nov 13 22:02:29 2016 -0500
+
+    ext4: don't lock buffer in ext4_commit_super if holding spinlock
+    
+    If there is an error reported in mballoc via ext4_grp_locked_error(),
+    the code is holding a spinlock, so ext4_commit_super() must not try to
+    lock the buffer head, or else it will trigger a BUG:
+    
+      BUG: sleeping function called from invalid context at ./include/linux/buffer_head.h:358
+      in_atomic(): 1, irqs_disabled(): 0, pid: 993, name: mount
+      CPU: 0 PID: 993 Comm: mount Not tainted 4.9.0-rc1-clouder1 #62
+      Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.1-0-g4adadbd-20150316_085822-nilsson.home.kraxel.org 04/01/2014
+       ffff880006423548 ffffffff81318c89 ffffffff819ecdd0 0000000000000166
+       ffff880006423558 ffffffff810810b0 ffff880006423580 ffffffff81081153
+       ffff880006e5a1a0 ffff88000690e400 0000000000000000 ffff8800064235c0
+      Call Trace:
+        [] dump_stack+0x67/0x9e
+        [] ___might_sleep+0xf0/0x140
+        [] __might_sleep+0x53/0xb0
+        [] ext4_commit_super+0x19c/0x290
+        [] __ext4_grp_locked_error+0x14a/0x230
+        [] ? __might_sleep+0x53/0xb0
+        [] ext4_mb_generate_buddy+0x1de/0x320
+    
+    Since ext4_grp_locked_error() calls ext4_commit_super with sync == 0
+    (and it is the only caller which does so), avoid locking and unlocking
+    the buffer in this case.
+    
+    This can result in races with ext4_commit_super() if there are other
+    problems (which is what commit 4743f83990614 was trying to address),
+    but a Warning is better than BUG.
+    
+    Fixes: 4743f83990614
+    Cc: stable@vger.kernel.org # 4.9
+    Reported-by: Nikolay Borisov 
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index e4f61c39328a..ff6f3ab09c7e 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4537,7 +4537,8 @@ static int ext4_commit_super(struct super_block *sb, int sync)
+ 				&EXT4_SB(sb)->s_freeinodes_counter));
+ 	BUFFER_TRACE(sbh, "marking dirty");
+ 	ext4_superblock_csum_set(sb);
+-	lock_buffer(sbh);
++	if (sync)
++		lock_buffer(sbh);
+ 	if (buffer_write_io_error(sbh)) {
+ 		/*
+ 		 * Oh, dear.  A previous attempt to write the
+@@ -4553,8 +4554,8 @@ static int ext4_commit_super(struct super_block *sb, int sync)
+ 		set_buffer_uptodate(sbh);
+ 	}
+ 	mark_buffer_dirty(sbh);
+-	unlock_buffer(sbh);
+ 	if (sync) {
++		unlock_buffer(sbh);
+ 		error = __sync_dirty_buffer(sbh,
+ 			test_opt(sb, BARRIER) ? WRITE_FUA : WRITE_SYNC);
+ 		if (error)

commit d0abb36db44faaf8f8aa148ca206fe2404042dec
+Author: Theodore Ts'o 
+Date:   Sun Nov 13 22:02:28 2016 -0500
+
+    ext4: allow ext4_ext_truncate() to return an error
+    
+    Return errors to the caller instead of declaring the file system
+    corrupted.
+    
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index be2282dcde7d..54211c7876f8 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -3128,7 +3128,7 @@ extern int ext4_ext_writepage_trans_blocks(struct inode *, int);
+ extern int ext4_ext_index_trans_blocks(struct inode *inode, int extents);
+ extern int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 			       struct ext4_map_blocks *map, int flags);
+-extern void ext4_ext_truncate(handle_t *, struct inode *);
++extern int ext4_ext_truncate(handle_t *, struct inode *);
+ extern int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
+ 				 ext4_lblk_t end);
+ extern void ext4_ext_init(struct super_block *);
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index c930a0110fb4..d3b119499c53 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -4631,7 +4631,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 	return err ? err : allocated;
+ }
+ 
+-void ext4_ext_truncate(handle_t *handle, struct inode *inode)
++int ext4_ext_truncate(handle_t *handle, struct inode *inode)
+ {
+ 	struct super_block *sb = inode->i_sb;
+ 	ext4_lblk_t last_block;
+@@ -4645,7 +4645,9 @@ void ext4_ext_truncate(handle_t *handle, struct inode *inode)
+ 
+ 	/* we have to know where to truncate from in crash case */
+ 	EXT4_I(inode)->i_disksize = inode->i_size;
+-	ext4_mark_inode_dirty(handle, inode);
++	err = ext4_mark_inode_dirty(handle, inode);
++	if (err)
++		return err;
+ 
+ 	last_block = (inode->i_size + sb->s_blocksize - 1)
+ 			>> EXT4_BLOCK_SIZE_BITS(sb);
+@@ -4657,12 +4659,9 @@ void ext4_ext_truncate(handle_t *handle, struct inode *inode)
+ 		congestion_wait(BLK_RW_ASYNC, HZ/50);
+ 		goto retry;
+ 	}
+-	if (err) {
+-		ext4_std_error(inode->i_sb, err);
+-		return;
+-	}
+-	err = ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCKS - 1);
+-	ext4_std_error(inode->i_sb, err);
++	if (err)
++		return err;
++	return ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCKS - 1);
+ }
+ 
+ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 585153057c2a..79f46f4b43b8 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4173,11 +4173,13 @@ int ext4_truncate(struct inode *inode)
+ 	ext4_discard_preallocations(inode);
+ 
+ 	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
+-		ext4_ext_truncate(handle, inode);
++		err = ext4_ext_truncate(handle, inode);
+ 	else
+ 		ext4_ind_truncate(handle, inode);
+ 
+ 	up_write(&ei->i_data_sem);
++	if (err)
++		goto out_stop;
+ 
+ 	if (IS_SYNC(inode))
+ 		ext4_handle_sync(handle);

commit 2c98eb5ea249767bbc11cf4e70e91d5b0458ed13
+Author: Theodore Ts'o 
+Date:   Sun Nov 13 22:02:26 2016 -0500
+
+    ext4: allow ext4_truncate() to return an error
+    
+    This allows us to properly propagate errors back up to
+    ext4_truncate()'s callers.  This also means we no longer have to
+    silently ignore some errors (e.g., when trying to add the inode to the
+    orphan inode list).
+    
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 282a51b07c57..be2282dcde7d 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2491,7 +2491,7 @@ extern int ext4_change_inode_journal_flag(struct inode *, int);
+ extern int ext4_get_inode_loc(struct inode *, struct ext4_iloc *);
+ extern int ext4_inode_attach_jinode(struct inode *inode);
+ extern int ext4_can_truncate(struct inode *inode);
+-extern void ext4_truncate(struct inode *);
++extern int ext4_truncate(struct inode *);
+ extern int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length);
+ extern int ext4_truncate_restart_trans(handle_t *, struct inode *, int nblocks);
+ extern void ext4_set_inode_flags(struct inode *);
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 48fbdfc43c10..585153057c2a 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -261,8 +261,15 @@ void ext4_evict_inode(struct inode *inode)
+ 			     "couldn't mark inode dirty (err %d)", err);
+ 		goto stop_handle;
+ 	}
+-	if (inode->i_blocks)
+-		ext4_truncate(inode);
++	if (inode->i_blocks) {
++		err = ext4_truncate(inode);
++		if (err) {
++			ext4_error(inode->i_sb,
++				   "couldn't truncate inode %lu (err %d)",
++				   inode->i_ino, err);
++			goto stop_handle;
++		}
++	}
+ 
+ 	/*
+ 	 * ext4_ext_truncate() doesn't reserve any slop when it
+@@ -4097,10 +4104,11 @@ int ext4_inode_attach_jinode(struct inode *inode)
+  * that's fine - as long as they are linked from the inode, the post-crash
+  * ext4_truncate() run will find them and release them.
+  */
+-void ext4_truncate(struct inode *inode)
++int ext4_truncate(struct inode *inode)
+ {
+ 	struct ext4_inode_info *ei = EXT4_I(inode);
+ 	unsigned int credits;
++	int err = 0;
+ 	handle_t *handle;
+ 	struct address_space *mapping = inode->i_mapping;
+ 
+@@ -4114,7 +4122,7 @@ void ext4_truncate(struct inode *inode)
+ 	trace_ext4_truncate_enter(inode);
+ 
+ 	if (!ext4_can_truncate(inode))
+-		return;
++		return 0;
+ 
+ 	ext4_clear_inode_flag(inode, EXT4_INODE_EOFBLOCKS);
+ 
+@@ -4126,13 +4134,13 @@ void ext4_truncate(struct inode *inode)
+ 
+ 		ext4_inline_data_truncate(inode, &has_inline);
+ 		if (has_inline)
+-			return;
++			return 0;
+ 	}
+ 
+ 	/* If we zero-out tail of the page, we have to create jinode for jbd2 */
+ 	if (inode->i_size & (inode->i_sb->s_blocksize - 1)) {
+ 		if (ext4_inode_attach_jinode(inode) < 0)
+-			return;
++			return 0;
+ 	}
+ 
+ 	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
+@@ -4141,10 +4149,8 @@ void ext4_truncate(struct inode *inode)
+ 		credits = ext4_blocks_for_truncate(inode);
+ 
+ 	handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits);
+-	if (IS_ERR(handle)) {
+-		ext4_std_error(inode->i_sb, PTR_ERR(handle));
+-		return;
+-	}
++	if (IS_ERR(handle))
++		return PTR_ERR(handle);
+ 
+ 	if (inode->i_size & (inode->i_sb->s_blocksize - 1))
+ 		ext4_block_truncate_page(handle, mapping, inode->i_size);
+@@ -4158,7 +4164,8 @@ void ext4_truncate(struct inode *inode)
+ 	 * Implication: the file must always be in a sane, consistent
+ 	 * truncatable state while each transaction commits.
+ 	 */
+-	if (ext4_orphan_add(handle, inode))
++	err = ext4_orphan_add(handle, inode);
++	if (err)
+ 		goto out_stop;
+ 
+ 	down_write(&EXT4_I(inode)->i_data_sem);
+@@ -4191,6 +4198,7 @@ void ext4_truncate(struct inode *inode)
+ 	ext4_journal_stop(handle);
+ 
+ 	trace_ext4_truncate_exit(inode);
++	return err;
+ }
+ 
+ /*
+@@ -5205,12 +5213,15 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
+ 		 * in data=journal mode to make pages freeable.
+ 		 */
+ 		truncate_pagecache(inode, inode->i_size);
+-		if (shrink)
+-			ext4_truncate(inode);
++		if (shrink) {
++			rc = ext4_truncate(inode);
++			if (rc)
++				error = rc;
++		}
+ 		up_write(&EXT4_I(inode)->i_mmap_sem);
+ 	}
+ 
+-	if (!rc) {
++	if (!error) {
+ 		setattr_copy(inode, attr);
+ 		mark_inode_dirty(inode);
+ 	}
+@@ -5222,7 +5233,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
+ 	if (orphan && inode->i_nlink)
+ 		ext4_orphan_del(NULL, inode);
+ 
+-	if (!rc && (ia_valid & ATTR_MODE))
++	if (!error && (ia_valid & ATTR_MODE))
+ 		rc = posix_acl_chmod(inode, inode->i_mode);
+ 
+ err_out:
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index bf5ae8ebbc97..99862a3726fc 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -248,8 +248,11 @@ static int ext4_ioctl_setflags(struct inode *inode,
+ 			err = -EOPNOTSUPP;
+ 			goto flags_out;
+ 		}
+-	} else if (oldflags & EXT4_EOFBLOCKS_FL)
+-		ext4_truncate(inode);
++	} else if (oldflags & EXT4_EOFBLOCKS_FL) {
++		err = ext4_truncate(inode);
++		if (err)
++			goto flags_out;
++	}
+ 
+ 	handle = ext4_journal_start(inode, EXT4_HT_INODE, 1);
+ 	if (IS_ERR(handle)) {
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 20da99da0a34..e4f61c39328a 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2330,7 +2330,7 @@ static void ext4_orphan_cleanup(struct super_block *sb,
+ 				struct ext4_super_block *es)
+ {
+ 	unsigned int s_flags = sb->s_flags;
+-	int nr_orphans = 0, nr_truncates = 0;
++	int ret, nr_orphans = 0, nr_truncates = 0;
+ #ifdef CONFIG_QUOTA
+ 	int i;
+ #endif
+@@ -2412,7 +2412,9 @@ static void ext4_orphan_cleanup(struct super_block *sb,
+ 				  inode->i_ino, inode->i_size);
+ 			inode_lock(inode);
+ 			truncate_inode_pages(inode->i_mapping, inode->i_size);
+-			ext4_truncate(inode);
++			ret = ext4_truncate(inode);
++			if (ret)
++				ext4_std_error(inode->i_sb, ret);
+ 			inode_unlock(inode);
+ 			nr_truncates++;
+ 		} else {

commit 6da22013bb7907b33c87968c25034b409a6161a2
+Merge: a2f6d9c4c081 a6e089128617
+Author: Theodore Ts'o 
+Date:   Sun Nov 13 22:02:22 2016 -0500
+
+    Merge branch 'fscrypt' into origin
+

commit a2f6d9c4c081ec2a02529b8af2c04f3e557a3a3e
+Merge: bc33b0ca11e3 9484ab1bf446
+Author: Theodore Ts'o 
+Date:   Sun Nov 13 22:02:15 2016 -0500
+
+    Merge branch 'dax-4.10-iomap-pmd' into origin
+
+diff --cc include/linux/iomap.h
+index 7892f55a1866,b9e7b8ec8c1d..f185156de74d
+--- a/include/linux/iomap.h
++++ b/include/linux/iomap.h
+@@@ -46,9 -42,9 +46,10 @@@ struct iomap 
+  /*
+   * Flags for iomap_begin / iomap_end.  No flag implies a read.
+   */
+ -#define IOMAP_WRITE		(1 << 0)
+ -#define IOMAP_ZERO		(1 << 1)
+ +#define IOMAP_WRITE		(1 << 0) /* writing, must allocate blocks */
+ +#define IOMAP_ZERO		(1 << 1) /* zeroing operation, may skip holes */
+ +#define IOMAP_REPORT		(1 << 2) /* report extent status, e.g. FIEMAP */
++ #define IOMAP_FAULT		(1 << 3) /* mapping for page fault */
+  
+  struct iomap_ops {
+  	/*

commit 829fa70dddadf9dd041d62b82cd7cea63943899d
+Author: Theodore Ts'o 
+Date:   Mon Aug 1 00:51:02 2016 -0400
+
+    ext4: validate that metadata blocks do not overlap superblock
+    
+    A number of fuzzing failures seem to be caused by allocation bitmaps
+    or other metadata blocks being pointed at the superblock.
+    
+    This can cause kernel BUG or WARNings once the superblock is
+    overwritten, so validate the group descriptor blocks to make sure this
+    doesn't happen.
+    
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index c13a4e464738..da3146e8d49a 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2211,6 +2211,7 @@ void ext4_group_desc_csum_set(struct super_block *sb, __u32 block_group,
+ 
+ /* Called at mount-time, super-block is locked */
+ static int ext4_check_descriptors(struct super_block *sb,
++				  ext4_fsblk_t sb_block,
+ 				  ext4_group_t *first_not_zeroed)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+@@ -2241,6 +2242,11 @@ static int ext4_check_descriptors(struct super_block *sb,
+ 			grp = i;
+ 
+ 		block_bitmap = ext4_block_bitmap(sb, gdp);
++		if (block_bitmap == sb_block) {
++			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
++				 "Block bitmap for group %u overlaps "
++				 "superblock", i);
++		}
+ 		if (block_bitmap < first_block || block_bitmap > last_block) {
+ 			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
+ 			       "Block bitmap for group %u not in group "
+@@ -2248,6 +2254,11 @@ static int ext4_check_descriptors(struct super_block *sb,
+ 			return 0;
+ 		}
+ 		inode_bitmap = ext4_inode_bitmap(sb, gdp);
++		if (inode_bitmap == sb_block) {
++			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
++				 "Inode bitmap for group %u overlaps "
++				 "superblock", i);
++		}
+ 		if (inode_bitmap < first_block || inode_bitmap > last_block) {
+ 			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
+ 			       "Inode bitmap for group %u not in group "
+@@ -2255,6 +2266,11 @@ static int ext4_check_descriptors(struct super_block *sb,
+ 			return 0;
+ 		}
+ 		inode_table = ext4_inode_table(sb, gdp);
++		if (inode_table == sb_block) {
++			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
++				 "Inode table for group %u overlaps "
++				 "superblock", i);
++		}
+ 		if (inode_table < first_block ||
+ 		    inode_table + sbi->s_itb_per_group - 1 > last_block) {
+ 			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
+@@ -3757,7 +3773,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 			goto failed_mount2;
+ 		}
+ 	}
+-	if (!ext4_check_descriptors(sb, &first_not_zeroed)) {
++	if (!ext4_check_descriptors(sb, logical_sb_block, &first_not_zeroed)) {
+ 		ext4_msg(sb, KERN_ERR, "group descriptors corrupted!");
+ 		ret = -EFSCORRUPTED;
+ 		goto failed_mount2;

commit 3980bd3b406addb327d858aebd19e229ea340b9a
+Author: Theodore Ts'o 
+Date:   Sun Jul 31 23:38:36 2016 -0400
+
+    ext4: reserve xattr index for the Hurd
+    
+    The Hurd is using inode fields which restricts it from using more
+    advanced ext4 file system features, due to design choices made over a
+    decade ago.  By giving the Hurd an extended attribute index field we
+    allow it to move the translator and author fields out of the core
+    inode fields, and hopefully we can get rid of ugly hacks such as
+    EXT4_OS_HURD and EXT4_MOUNT2_HURD_COMPAT somday.
+    
+    For more information please see:
+          https://summerofcode.withgoogle.com/projects/#5869799859027968
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
+index 69dd3e6566e0..a92e783fa057 100644
+--- a/fs/ext4/xattr.h
++++ b/fs/ext4/xattr.h
+@@ -24,6 +24,7 @@
+ #define EXT4_XATTR_INDEX_SYSTEM			7
+ #define EXT4_XATTR_INDEX_RICHACL		8
+ #define EXT4_XATTR_INDEX_ENCRYPTION		9
++#define EXT4_XATTR_INDEX_HURD			10 /* Reserved for Hurd */
+ 
+ struct ext4_xattr_header {
+ 	__le32	h_magic;	/* magic number for identification */

commit 59b8d4f1f5d26e4ca92172ff6dcd1492cdb39613
+Author: Theodore Ts'o 
+Date:   Wed Jul 27 23:30:25 2016 -0400
+
+    random: use for_each_online_node() to iterate over NUMA nodes
+    
+    This fixes a crash on s390 with fake NUMA enabled.
+    
+    Reported-by: Heiko Carstens 
+    Fixes: 1e7f583af67b ("random: make /dev/urandom scalable for silly userspace programs")
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 8d0af74f6569..7f0622426b97 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -1668,13 +1668,12 @@ static int rand_initialize(void)
+ #ifdef CONFIG_NUMA
+ 	pool = kmalloc(num_nodes * sizeof(void *),
+ 		       GFP_KERNEL|__GFP_NOFAIL|__GFP_ZERO);
+-	for (i=0; i < num_nodes; i++) {
++	for_each_online_node(i) {
+ 		crng = kmalloc_node(sizeof(struct crng_state),
+ 				    GFP_KERNEL | __GFP_NOFAIL, i);
+ 		spin_lock_init(&crng->lock);
+ 		crng_initialize(crng);
+ 		pool[i] = crng;
+-
+ 	}
+ 	mb();
+ 	crng_node_pool = pool;

commit 598c7d7abc832e35677b851f6afb93141c09993b
+Author: Theodore Ts'o 
+Date:   Thu Jul 14 22:44:13 2016 -0400
+
+    MAINTAINRES: fs-crypto maintainers update
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: Jaegeuk Kim 
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 7304d2e37a98..b2234f85eaca 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -4925,6 +4925,13 @@ F:	Documentation/filesystems/caching/
+ F:	fs/fscache/
+ F:	include/linux/fscache*.h
+ 
++FS-CRYPTO: FILE SYSTEM LEVEL ENCRYPTION SUPPORT
++M:	Theodore Y. Ts'o 
++M:	Jaegeuk Kim 
++S:	Supported
++F:	fs/crypto/
++F:	include/linux/fscrypto.h
++
+ F2FS FILE SYSTEM
+ M:	Jaegeuk Kim 
+ M:	Changman Lee 

commit 5b9554dc5bf008ae7f68a52e3d7e76c0920938a2
+Author: Theodore Ts'o 
+Date:   Tue Jul 5 20:01:52 2016 -0400
+
+    ext4: validate s_reserved_gdt_blocks on mount
+    
+    If s_reserved_gdt_blocks is extremely large, it's possible for
+    ext4_init_block_bitmap(), which is called when ext4 sets up an
+    uninitialized block bitmap, to corrupt random kernel memory.  Add the
+    same checks which e2fsck has --- it must never be larger than
+    blocksize / sizeof(__u32) --- and then add a backup check in
+    ext4_init_block_bitmap() in case the superblock gets modified after
+    the file system is mounted.
+    
+    Reported-by: Vegard Nossum 
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 0b8105b3293d..799a92bdf577 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -208,6 +208,9 @@ static int ext4_init_block_bitmap(struct super_block *sb,
+ 	memset(bh->b_data, 0, sb->s_blocksize);
+ 
+ 	bit_max = ext4_num_base_meta_clusters(sb, block_group);
++	if ((bit_max >> 3) >= bh->b_size)
++		return -EFSCORRUPTED;
++
+ 	for (bit = 0; bit < bit_max; bit++)
+ 		ext4_set_bit(bit, bh->b_data);
+ 
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 5664ee66b301..13c49af7a06a 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3416,6 +3416,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		goto failed_mount;
+ 	}
+ 
++	if (le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) > (blocksize / 4)) {
++		ext4_msg(sb, KERN_ERR,
++			 "Number of reserved GDT blocks insanely large: %d",
++			 le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks));
++		goto failed_mount;
++	}
++
+ 	if (sbi->s_mount_opt & EXT4_MOUNT_DAX) {
+ 		err = bdev_dax_supported(sb, blocksize);
+ 		if (err)

commit 86a574de4590ffe6fd3f3ca34cdcf655a78e36ec
+Author: Theodore Ts'o 
+Date:   Sun Jul 3 17:01:26 2016 -0400
+
+    random: strengthen input validation for RNDADDTOENTCNT
+    
+    Don't allow RNDADDTOENTCNT or RNDADDENTROPY to accept a negative
+    entropy value.  It doesn't make any sense to subtract from the entropy
+    counter, and it can trigger a warning:
+    
+    random: negative entropy/overflow: pool input count -40000
+    ------------[ cut here ]------------
+    WARNING: CPU: 3 PID: 6828 at drivers/char/random.c:670[<      none
+     >] credit_entropy_bits+0x21e/0xad0 drivers/char/random.c:670
+    Modules linked in:
+    CPU: 3 PID: 6828 Comm: a.out Not tainted 4.7.0-rc4+ #4
+    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
+     ffffffff880b58e0 ffff88005dd9fcb0 ffffffff82cc838f ffffffff87158b40
+     fffffbfff1016b1c 0000000000000000 0000000000000000 ffffffff87158b40
+     ffffffff83283dae 0000000000000009 ffff88005dd9fcf8 ffffffff8136d27f
+    Call Trace:
+     [<     inline     >] __dump_stack lib/dump_stack.c:15
+     [] dump_stack+0x12e/0x18f lib/dump_stack.c:51
+     [] __warn+0x19f/0x1e0 kernel/panic.c:516
+     [] warn_slowpath_null+0x2c/0x40 kernel/panic.c:551
+     [] credit_entropy_bits+0x21e/0xad0 drivers/char/random.c:670
+     [<     inline     >] credit_entropy_bits_safe drivers/char/random.c:734
+     [] random_ioctl+0x21d/0x250 drivers/char/random.c:1546
+     [<     inline     >] vfs_ioctl fs/ioctl.c:43
+     [] do_vfs_ioctl+0x18c/0xff0 fs/ioctl.c:674
+     [<     inline     >] SYSC_ioctl fs/ioctl.c:689
+     [] SyS_ioctl+0x8f/0xc0 fs/ioctl.c:680
+     [] entry_SYSCALL_64_fastpath+0x23/0xc1
+    arch/x86/entry/entry_64.S:207
+    ---[ end trace 5d4902b2ba842f1f ]---
+    
+    This was triggered using the test program:
+    
+    // autogenerated by syzkaller (http://github.com/google/syzkaller)
+    
+    int main() {
+            int fd = open("/dev/random", O_RDWR);
+            int val = -5000;
+            ioctl(fd, RNDADDTOENTCNT, &val);
+            return 0;
+    }
+    
+    It's harmless in that (a) only root can trigger it, and (b) after
+    complaining the code never does let the entropy count go negative, but
+    it's better to simply not allow this userspace from passing in a
+    negative entropy value altogether.
+    
+    Google-Bug-Id: #29575089
+    Reported-By: Dmitry Vyukov 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 783dee11cdc9..8d0af74f6569 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -738,15 +738,18 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
+ 	}
+ }
+ 
+-static void credit_entropy_bits_safe(struct entropy_store *r, int nbits)
++static int credit_entropy_bits_safe(struct entropy_store *r, int nbits)
+ {
+ 	const int nbits_max = (int)(~0U >> (ENTROPY_SHIFT + 1));
+ 
++	if (nbits < 0)
++		return -EINVAL;
++
+ 	/* Cap the value to avoid overflows */
+ 	nbits = min(nbits,  nbits_max);
+-	nbits = max(nbits, -nbits_max);
+ 
+ 	credit_entropy_bits(r, nbits);
++	return 0;
+ }
+ 
+ /*********************************************************************
+@@ -1823,8 +1826,7 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+ 			return -EPERM;
+ 		if (get_user(ent_count, p))
+ 			return -EFAULT;
+-		credit_entropy_bits_safe(&input_pool, ent_count);
+-		return 0;
++		return credit_entropy_bits_safe(&input_pool, ent_count);
+ 	case RNDADDENTROPY:
+ 		if (!capable(CAP_SYS_ADMIN))
+ 			return -EPERM;
+@@ -1838,8 +1840,7 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+ 				    size);
+ 		if (retval < 0)
+ 			return retval;
+-		credit_entropy_bits_safe(&input_pool, ent_count);
+-		return 0;
++		return credit_entropy_bits_safe(&input_pool, ent_count);
+ 	case RNDZAPENTCNT:
+ 	case RNDCLEARPOOL:
+ 		/*

commit c92e040d575a7389d72e7e6f25e2033bfb867f8b
+Author: Theodore Ts'o 
+Date:   Wed May 4 13:29:18 2016 -0400
+
+    random: add backtracking protection to the CRNG
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 2a30d9718a1b..783dee11cdc9 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -438,7 +438,8 @@ static int crng_init_cnt = 0;
+ #define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE)
+ static void _extract_crng(struct crng_state *crng,
+ 			  __u8 out[CHACHA20_BLOCK_SIZE]);
+-static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]);
++static void _crng_backtrack_protect(struct crng_state *crng,
++				    __u8 tmp[CHACHA20_BLOCK_SIZE], int used);
+ static void process_random_ready_list(void);
+ 
+ /**********************************************************************
+@@ -826,8 +827,11 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
+ 		num = extract_entropy(r, &buf, 32, 16, 0);
+ 		if (num == 0)
+ 			return;
+-	} else
++	} else {
+ 		_extract_crng(&primary_crng, buf.block);
++		_crng_backtrack_protect(&primary_crng, buf.block,
++					CHACHA20_KEY_SIZE);
++	}
+ 	spin_lock_irqsave(&primary_crng.lock, flags);
+ 	for (i = 0; i < 8; i++) {
+ 		unsigned long	rv;
+@@ -889,9 +893,46 @@ static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE])
+ 	_extract_crng(crng, out);
+ }
+ 
++/*
++ * Use the leftover bytes from the CRNG block output (if there is
++ * enough) to mutate the CRNG key to provide backtracking protection.
++ */
++static void _crng_backtrack_protect(struct crng_state *crng,
++				    __u8 tmp[CHACHA20_BLOCK_SIZE], int used)
++{
++	unsigned long	flags;
++	__u32		*s, *d;
++	int		i;
++
++	used = round_up(used, sizeof(__u32));
++	if (used + CHACHA20_KEY_SIZE > CHACHA20_BLOCK_SIZE) {
++		extract_crng(tmp);
++		used = 0;
++	}
++	spin_lock_irqsave(&crng->lock, flags);
++	s = (__u32 *) &tmp[used];
++	d = &crng->state[4];
++	for (i=0; i < 8; i++)
++		*d++ ^= *s++;
++	spin_unlock_irqrestore(&crng->lock, flags);
++}
++
++static void crng_backtrack_protect(__u8 tmp[CHACHA20_BLOCK_SIZE], int used)
++{
++	struct crng_state *crng = NULL;
++
++#ifdef CONFIG_NUMA
++	if (crng_node_pool)
++		crng = crng_node_pool[numa_node_id()];
++	if (crng == NULL)
++#endif
++		crng = &primary_crng;
++	_crng_backtrack_protect(crng, tmp, used);
++}
++
+ static ssize_t extract_crng_user(void __user *buf, size_t nbytes)
+ {
+-	ssize_t ret = 0, i;
++	ssize_t ret = 0, i = CHACHA20_BLOCK_SIZE;
+ 	__u8 tmp[CHACHA20_BLOCK_SIZE];
+ 	int large_request = (nbytes > 256);
+ 
+@@ -916,6 +957,7 @@ static ssize_t extract_crng_user(void __user *buf, size_t nbytes)
+ 		buf += i;
+ 		ret += i;
+ 	}
++	crng_backtrack_protect(tmp, i);
+ 
+ 	/* Wipe data just written to memory */
+ 	memzero_explicit(tmp, sizeof(tmp));
+@@ -1473,8 +1515,10 @@ void get_random_bytes(void *buf, int nbytes)
+ 	if (nbytes > 0) {
+ 		extract_crng(tmp);
+ 		memcpy(buf, tmp, nbytes);
+-		memzero_explicit(tmp, nbytes);
+-	}
++		crng_backtrack_protect(tmp, nbytes);
++	} else
++		crng_backtrack_protect(tmp, CHACHA20_BLOCK_SIZE);
++	memzero_explicit(tmp, sizeof(tmp));
+ }
+ EXPORT_SYMBOL(get_random_bytes);
+ 

commit 1e7f583af67be4ff091d0aeb863c649efd7a9112
+Author: Theodore Ts'o 
+Date:   Mon May 2 02:04:41 2016 -0400
+
+    random: make /dev/urandom scalable for silly userspace programs
+    
+    On a system with a 4 socket (NUMA) system where a large number of
+    application threads were all trying to read from /dev/urandom, this
+    can result in the system spending 80% of its time contending on the
+    global urandom spinlock.  The application should have used its own
+    PRNG, but let's try to help it from running, lemming-like, straight
+    over the locking cliff.
+    
+    Reported-by: Andi Kleen 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index dc2a9c2d8dcf..2a30d9718a1b 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -436,6 +436,8 @@ static int crng_init = 0;
+ #define crng_ready() (likely(crng_init > 0))
+ static int crng_init_cnt = 0;
+ #define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE)
++static void _extract_crng(struct crng_state *crng,
++			  __u8 out[CHACHA20_BLOCK_SIZE]);
+ static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]);
+ static void process_random_ready_list(void);
+ 
+@@ -756,6 +758,16 @@ static void credit_entropy_bits_safe(struct entropy_store *r, int nbits)
+ 
+ static DECLARE_WAIT_QUEUE_HEAD(crng_init_wait);
+ 
++#ifdef CONFIG_NUMA
++/*
++ * Hack to deal with crazy userspace progams when they are all trying
++ * to access /dev/urandom in parallel.  The programs are almost
++ * certainly doing something terribly wrong, but we'll work around
++ * their brain damage.
++ */
++static struct crng_state **crng_node_pool __read_mostly;
++#endif
++
+ static void crng_initialize(struct crng_state *crng)
+ {
+ 	int		i;
+@@ -815,7 +827,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
+ 		if (num == 0)
+ 			return;
+ 	} else
+-		extract_crng(buf.block);
++		_extract_crng(&primary_crng, buf.block);
+ 	spin_lock_irqsave(&primary_crng.lock, flags);
+ 	for (i = 0; i < 8; i++) {
+ 		unsigned long	rv;
+@@ -835,19 +847,26 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
+ 	spin_unlock_irqrestore(&primary_crng.lock, flags);
+ }
+ 
++static inline void maybe_reseed_primary_crng(void)
++{
++	if (crng_init > 2 &&
++	    time_after(jiffies, primary_crng.init_time + CRNG_RESEED_INTERVAL))
++		crng_reseed(&primary_crng, &input_pool);
++}
++
+ static inline void crng_wait_ready(void)
+ {
+ 	wait_event_interruptible(crng_init_wait, crng_ready());
+ }
+ 
+-static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE])
++static void _extract_crng(struct crng_state *crng,
++			  __u8 out[CHACHA20_BLOCK_SIZE])
+ {
+ 	unsigned long v, flags;
+-	struct crng_state *crng = &primary_crng;
+ 
+ 	if (crng_init > 1 &&
+ 	    time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL))
+-		crng_reseed(crng, &input_pool);
++		crng_reseed(crng, crng == &primary_crng ? &input_pool : NULL);
+ 	spin_lock_irqsave(&crng->lock, flags);
+ 	if (arch_get_random_long(&v))
+ 		crng->state[14] ^= v;
+@@ -857,6 +876,19 @@ static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE])
+ 	spin_unlock_irqrestore(&crng->lock, flags);
+ }
+ 
++static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE])
++{
++	struct crng_state *crng = NULL;
++
++#ifdef CONFIG_NUMA
++	if (crng_node_pool)
++		crng = crng_node_pool[numa_node_id()];
++	if (crng == NULL)
++#endif
++		crng = &primary_crng;
++	_extract_crng(crng, out);
++}
++
+ static ssize_t extract_crng_user(void __user *buf, size_t nbytes)
+ {
+ 	ssize_t ret = 0, i;
+@@ -1575,9 +1607,31 @@ static void init_std_data(struct entropy_store *r)
+  */
+ static int rand_initialize(void)
+ {
++#ifdef CONFIG_NUMA
++	int i;
++	int num_nodes = num_possible_nodes();
++	struct crng_state *crng;
++	struct crng_state **pool;
++#endif
++
+ 	init_std_data(&input_pool);
+ 	init_std_data(&blocking_pool);
+ 	crng_initialize(&primary_crng);
++
++#ifdef CONFIG_NUMA
++	pool = kmalloc(num_nodes * sizeof(void *),
++		       GFP_KERNEL|__GFP_NOFAIL|__GFP_ZERO);
++	for (i=0; i < num_nodes; i++) {
++		crng = kmalloc_node(sizeof(struct crng_state),
++				    GFP_KERNEL | __GFP_NOFAIL, i);
++		spin_lock_init(&crng->lock);
++		crng_initialize(crng);
++		pool[i] = crng;
++
++	}
++	mb();
++	crng_node_pool = pool;
++#endif
+ 	return 0;
+ }
+ early_initcall(rand_initialize);

commit e192be9d9a30555aae2ca1dc3aad37cba484cd4a
+Author: Theodore Ts'o 
+Date:   Sun Jun 12 18:13:36 2016 -0400
+
+    random: replace non-blocking pool with a Chacha20-based CRNG
+    
+    The CRNG is faster, and we don't pretend to track entropy usage in the
+    CRNG any more.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/crypto/chacha20_generic.c b/crypto/chacha20_generic.c
+index da9c89968223..1cab83146e33 100644
+--- a/crypto/chacha20_generic.c
++++ b/crypto/chacha20_generic.c
+@@ -15,72 +15,11 @@
+ #include 
+ #include 
+ 
+-static inline u32 rotl32(u32 v, u8 n)
+-{
+-	return (v << n) | (v >> (sizeof(v) * 8 - n));
+-}
+-
+ static inline u32 le32_to_cpuvp(const void *p)
+ {
+ 	return le32_to_cpup(p);
+ }
+ 
+-static void chacha20_block(u32 *state, void *stream)
+-{
+-	u32 x[16], *out = stream;
+-	int i;
+-
+-	for (i = 0; i < ARRAY_SIZE(x); i++)
+-		x[i] = state[i];
+-
+-	for (i = 0; i < 20; i += 2) {
+-		x[0]  += x[4];    x[12] = rotl32(x[12] ^ x[0],  16);
+-		x[1]  += x[5];    x[13] = rotl32(x[13] ^ x[1],  16);
+-		x[2]  += x[6];    x[14] = rotl32(x[14] ^ x[2],  16);
+-		x[3]  += x[7];    x[15] = rotl32(x[15] ^ x[3],  16);
+-
+-		x[8]  += x[12];   x[4]  = rotl32(x[4]  ^ x[8],  12);
+-		x[9]  += x[13];   x[5]  = rotl32(x[5]  ^ x[9],  12);
+-		x[10] += x[14];   x[6]  = rotl32(x[6]  ^ x[10], 12);
+-		x[11] += x[15];   x[7]  = rotl32(x[7]  ^ x[11], 12);
+-
+-		x[0]  += x[4];    x[12] = rotl32(x[12] ^ x[0],   8);
+-		x[1]  += x[5];    x[13] = rotl32(x[13] ^ x[1],   8);
+-		x[2]  += x[6];    x[14] = rotl32(x[14] ^ x[2],   8);
+-		x[3]  += x[7];    x[15] = rotl32(x[15] ^ x[3],   8);
+-
+-		x[8]  += x[12];   x[4]  = rotl32(x[4]  ^ x[8],   7);
+-		x[9]  += x[13];   x[5]  = rotl32(x[5]  ^ x[9],   7);
+-		x[10] += x[14];   x[6]  = rotl32(x[6]  ^ x[10],  7);
+-		x[11] += x[15];   x[7]  = rotl32(x[7]  ^ x[11],  7);
+-
+-		x[0]  += x[5];    x[15] = rotl32(x[15] ^ x[0],  16);
+-		x[1]  += x[6];    x[12] = rotl32(x[12] ^ x[1],  16);
+-		x[2]  += x[7];    x[13] = rotl32(x[13] ^ x[2],  16);
+-		x[3]  += x[4];    x[14] = rotl32(x[14] ^ x[3],  16);
+-
+-		x[10] += x[15];   x[5]  = rotl32(x[5]  ^ x[10], 12);
+-		x[11] += x[12];   x[6]  = rotl32(x[6]  ^ x[11], 12);
+-		x[8]  += x[13];   x[7]  = rotl32(x[7]  ^ x[8],  12);
+-		x[9]  += x[14];   x[4]  = rotl32(x[4]  ^ x[9],  12);
+-
+-		x[0]  += x[5];    x[15] = rotl32(x[15] ^ x[0],   8);
+-		x[1]  += x[6];    x[12] = rotl32(x[12] ^ x[1],   8);
+-		x[2]  += x[7];    x[13] = rotl32(x[13] ^ x[2],   8);
+-		x[3]  += x[4];    x[14] = rotl32(x[14] ^ x[3],   8);
+-
+-		x[10] += x[15];   x[5]  = rotl32(x[5]  ^ x[10],  7);
+-		x[11] += x[12];   x[6]  = rotl32(x[6]  ^ x[11],  7);
+-		x[8]  += x[13];   x[7]  = rotl32(x[7]  ^ x[8],   7);
+-		x[9]  += x[14];   x[4]  = rotl32(x[4]  ^ x[9],   7);
+-	}
+-
+-	for (i = 0; i < ARRAY_SIZE(x); i++)
+-		out[i] = cpu_to_le32(x[i] + state[i]);
+-
+-	state[12]++;
+-}
+-
+ static void chacha20_docrypt(u32 *state, u8 *dst, const u8 *src,
+ 			     unsigned int bytes)
+ {
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index a6253e89663c..dc2a9c2d8dcf 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -261,6 +261,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ #include 
+@@ -413,6 +414,31 @@ static struct fasync_struct *fasync;
+ static DEFINE_SPINLOCK(random_ready_list_lock);
+ static LIST_HEAD(random_ready_list);
+ 
++struct crng_state {
++	__u32		state[16];
++	unsigned long	init_time;
++	spinlock_t	lock;
++};
++
++struct crng_state primary_crng = {
++	.lock = __SPIN_LOCK_UNLOCKED(primary_crng.lock),
++};
++
++/*
++ * crng_init =  0 --> Uninitialized
++ *		1 --> Initialized
++ *		2 --> Initialized from input_pool
++ *
++ * crng_init is protected by primary_crng->lock, and only increases
++ * its value (from 0->1->2).
++ */
++static int crng_init = 0;
++#define crng_ready() (likely(crng_init > 0))
++static int crng_init_cnt = 0;
++#define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE)
++static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]);
++static void process_random_ready_list(void);
++
+ /**********************************************************************
+  *
+  * OS independent entropy store.   Here are the functions which handle
+@@ -442,10 +468,15 @@ struct entropy_store {
+ 	__u8 last_data[EXTRACT_SIZE];
+ };
+ 
++static ssize_t extract_entropy(struct entropy_store *r, void *buf,
++			       size_t nbytes, int min, int rsvd);
++static ssize_t _extract_entropy(struct entropy_store *r, void *buf,
++				size_t nbytes, int fips);
++
++static void crng_reseed(struct crng_state *crng, struct entropy_store *r);
+ static void push_to_pool(struct work_struct *work);
+ static __u32 input_pool_data[INPUT_POOL_WORDS];
+ static __u32 blocking_pool_data[OUTPUT_POOL_WORDS];
+-static __u32 nonblocking_pool_data[OUTPUT_POOL_WORDS];
+ 
+ static struct entropy_store input_pool = {
+ 	.poolinfo = &poolinfo_table[0],
+@@ -466,16 +497,6 @@ static struct entropy_store blocking_pool = {
+ 					push_to_pool),
+ };
+ 
+-static struct entropy_store nonblocking_pool = {
+-	.poolinfo = &poolinfo_table[1],
+-	.name = "nonblocking",
+-	.pull = &input_pool,
+-	.lock = __SPIN_LOCK_UNLOCKED(nonblocking_pool.lock),
+-	.pool = nonblocking_pool_data,
+-	.push_work = __WORK_INITIALIZER(nonblocking_pool.push_work,
+-					push_to_pool),
+-};
+-
+ static __u32 const twist_table[8] = {
+ 	0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
+ 	0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
+@@ -678,12 +699,6 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
+ 	if (!r->initialized && r->entropy_total > 128) {
+ 		r->initialized = 1;
+ 		r->entropy_total = 0;
+-		if (r == &nonblocking_pool) {
+-			prandom_reseed_late();
+-			process_random_ready_list();
+-			wake_up_all(&urandom_init_wait);
+-			pr_notice("random: %s pool is initialized\n", r->name);
+-		}
+ 	}
+ 
+ 	trace_credit_entropy_bits(r->name, nbits,
+@@ -693,30 +708,27 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
+ 	if (r == &input_pool) {
+ 		int entropy_bits = entropy_count >> ENTROPY_SHIFT;
+ 
++		if (crng_init < 2 && entropy_bits >= 128) {
++			crng_reseed(&primary_crng, r);
++			entropy_bits = r->entropy_count >> ENTROPY_SHIFT;
++		}
++
+ 		/* should we wake readers? */
+ 		if (entropy_bits >= random_read_wakeup_bits) {
+ 			wake_up_interruptible(&random_read_wait);
+ 			kill_fasync(&fasync, SIGIO, POLL_IN);
+ 		}
+ 		/* If the input pool is getting full, send some
+-		 * entropy to the two output pools, flipping back and
+-		 * forth between them, until the output pools are 75%
+-		 * full.
++		 * entropy to the blocking pool until it is 75% full.
+ 		 */
+ 		if (entropy_bits > random_write_wakeup_bits &&
+ 		    r->initialized &&
+ 		    r->entropy_total >= 2*random_read_wakeup_bits) {
+-			static struct entropy_store *last = &blocking_pool;
+ 			struct entropy_store *other = &blocking_pool;
+ 
+-			if (last == &blocking_pool)
+-				other = &nonblocking_pool;
+ 			if (other->entropy_count <=
+-			    3 * other->poolinfo->poolfracbits / 4)
+-				last = other;
+-			if (last->entropy_count <=
+-			    3 * last->poolinfo->poolfracbits / 4) {
+-				schedule_work(&last->push_work);
++			    3 * other->poolinfo->poolfracbits / 4) {
++				schedule_work(&other->push_work);
+ 				r->entropy_total = 0;
+ 			}
+ 		}
+@@ -734,6 +746,152 @@ static void credit_entropy_bits_safe(struct entropy_store *r, int nbits)
+ 	credit_entropy_bits(r, nbits);
+ }
+ 
++/*********************************************************************
++ *
++ * CRNG using CHACHA20
++ *
++ *********************************************************************/
++
++#define CRNG_RESEED_INTERVAL (300*HZ)
++
++static DECLARE_WAIT_QUEUE_HEAD(crng_init_wait);
++
++static void crng_initialize(struct crng_state *crng)
++{
++	int		i;
++	unsigned long	rv;
++
++	memcpy(&crng->state[0], "expand 32-byte k", 16);
++	if (crng == &primary_crng)
++		_extract_entropy(&input_pool, &crng->state[4],
++				 sizeof(__u32) * 12, 0);
++	else
++		get_random_bytes(&crng->state[4], sizeof(__u32) * 12);
++	for (i = 4; i < 16; i++) {
++		if (!arch_get_random_seed_long(&rv) &&
++		    !arch_get_random_long(&rv))
++			rv = random_get_entropy();
++		crng->state[i] ^= rv;
++	}
++	crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1;
++}
++
++static int crng_fast_load(const char *cp, size_t len)
++{
++	unsigned long flags;
++	char *p;
++
++	if (!spin_trylock_irqsave(&primary_crng.lock, flags))
++		return 0;
++	if (crng_ready()) {
++		spin_unlock_irqrestore(&primary_crng.lock, flags);
++		return 0;
++	}
++	p = (unsigned char *) &primary_crng.state[4];
++	while (len > 0 && crng_init_cnt < CRNG_INIT_CNT_THRESH) {
++		p[crng_init_cnt % CHACHA20_KEY_SIZE] ^= *cp;
++		cp++; crng_init_cnt++; len--;
++	}
++	if (crng_init_cnt >= CRNG_INIT_CNT_THRESH) {
++		crng_init = 1;
++		wake_up_interruptible(&crng_init_wait);
++		pr_notice("random: fast init done\n");
++	}
++	spin_unlock_irqrestore(&primary_crng.lock, flags);
++	return 1;
++}
++
++static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
++{
++	unsigned long	flags;
++	int		i, num;
++	union {
++		__u8	block[CHACHA20_BLOCK_SIZE];
++		__u32	key[8];
++	} buf;
++
++	if (r) {
++		num = extract_entropy(r, &buf, 32, 16, 0);
++		if (num == 0)
++			return;
++	} else
++		extract_crng(buf.block);
++	spin_lock_irqsave(&primary_crng.lock, flags);
++	for (i = 0; i < 8; i++) {
++		unsigned long	rv;
++		if (!arch_get_random_seed_long(&rv) &&
++		    !arch_get_random_long(&rv))
++			rv = random_get_entropy();
++		crng->state[i+4] ^= buf.key[i] ^ rv;
++	}
++	memzero_explicit(&buf, sizeof(buf));
++	crng->init_time = jiffies;
++	if (crng == &primary_crng && crng_init < 2) {
++		crng_init = 2;
++		process_random_ready_list();
++		wake_up_interruptible(&crng_init_wait);
++		pr_notice("random: crng init done\n");
++	}
++	spin_unlock_irqrestore(&primary_crng.lock, flags);
++}
++
++static inline void crng_wait_ready(void)
++{
++	wait_event_interruptible(crng_init_wait, crng_ready());
++}
++
++static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE])
++{
++	unsigned long v, flags;
++	struct crng_state *crng = &primary_crng;
++
++	if (crng_init > 1 &&
++	    time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL))
++		crng_reseed(crng, &input_pool);
++	spin_lock_irqsave(&crng->lock, flags);
++	if (arch_get_random_long(&v))
++		crng->state[14] ^= v;
++	chacha20_block(&crng->state[0], out);
++	if (crng->state[12] == 0)
++		crng->state[13]++;
++	spin_unlock_irqrestore(&crng->lock, flags);
++}
++
++static ssize_t extract_crng_user(void __user *buf, size_t nbytes)
++{
++	ssize_t ret = 0, i;
++	__u8 tmp[CHACHA20_BLOCK_SIZE];
++	int large_request = (nbytes > 256);
++
++	while (nbytes) {
++		if (large_request && need_resched()) {
++			if (signal_pending(current)) {
++				if (ret == 0)
++					ret = -ERESTARTSYS;
++				break;
++			}
++			schedule();
++		}
++
++		extract_crng(tmp);
++		i = min_t(int, nbytes, CHACHA20_BLOCK_SIZE);
++		if (copy_to_user(buf, tmp, i)) {
++			ret = -EFAULT;
++			break;
++		}
++
++		nbytes -= i;
++		buf += i;
++		ret += i;
++	}
++
++	/* Wipe data just written to memory */
++	memzero_explicit(tmp, sizeof(tmp));
++
++	return ret;
++}
++
++
+ /*********************************************************************
+  *
+  * Entropy input management
+@@ -750,12 +908,12 @@ struct timer_rand_state {
+ #define INIT_TIMER_RAND_STATE { INITIAL_JIFFIES, };
+ 
+ /*
+- * Add device- or boot-specific data to the input and nonblocking
+- * pools to help initialize them to unique values.
++ * Add device- or boot-specific data to the input pool to help
++ * initialize it.
+  *
+- * None of this adds any entropy, it is meant to avoid the
+- * problem of the nonblocking pool having similar initial state
+- * across largely identical devices.
++ * None of this adds any entropy; it is meant to avoid the problem of
++ * the entropy pool having similar initial state across largely
++ * identical devices.
+  */
+ void add_device_randomness(const void *buf, unsigned int size)
+ {
+@@ -767,11 +925,6 @@ void add_device_randomness(const void *buf, unsigned int size)
+ 	_mix_pool_bytes(&input_pool, buf, size);
+ 	_mix_pool_bytes(&input_pool, &time, sizeof(time));
+ 	spin_unlock_irqrestore(&input_pool.lock, flags);
+-
+-	spin_lock_irqsave(&nonblocking_pool.lock, flags);
+-	_mix_pool_bytes(&nonblocking_pool, buf, size);
+-	_mix_pool_bytes(&nonblocking_pool, &time, sizeof(time));
+-	spin_unlock_irqrestore(&nonblocking_pool.lock, flags);
+ }
+ EXPORT_SYMBOL(add_device_randomness);
+ 
+@@ -802,7 +955,7 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
+ 	sample.jiffies = jiffies;
+ 	sample.cycles = random_get_entropy();
+ 	sample.num = num;
+-	r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
++	r = &input_pool;
+ 	mix_pool_bytes(r, &sample, sizeof(sample));
+ 
+ 	/*
+@@ -918,11 +1071,21 @@ void add_interrupt_randomness(int irq, int irq_flags)
+ 	fast_mix(fast_pool);
+ 	add_interrupt_bench(cycles);
+ 
++	if (!crng_ready()) {
++		if ((fast_pool->count >= 64) &&
++		    crng_fast_load((char *) fast_pool->pool,
++				   sizeof(fast_pool->pool))) {
++			fast_pool->count = 0;
++			fast_pool->last = now;
++		}
++		return;
++	}
++
+ 	if ((fast_pool->count < 64) &&
+ 	    !time_after(now, fast_pool->last + HZ))
+ 		return;
+ 
+-	r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
++	r = &input_pool;
+ 	if (!spin_trylock(&r->lock))
+ 		return;
+ 
+@@ -966,9 +1129,6 @@ EXPORT_SYMBOL_GPL(add_disk_randomness);
+  *
+  *********************************************************************/
+ 
+-static ssize_t extract_entropy(struct entropy_store *r, void *buf,
+-			       size_t nbytes, int min, int rsvd);
+-
+ /*
+  * This utility inline function is responsible for transferring entropy
+  * from the primary pool to the secondary extraction pool. We make
+@@ -1143,6 +1303,36 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
+ 	memzero_explicit(&hash, sizeof(hash));
+ }
+ 
++static ssize_t _extract_entropy(struct entropy_store *r, void *buf,
++				size_t nbytes, int fips)
++{
++	ssize_t ret = 0, i;
++	__u8 tmp[EXTRACT_SIZE];
++	unsigned long flags;
++
++	while (nbytes) {
++		extract_buf(r, tmp);
++
++		if (fips) {
++			spin_lock_irqsave(&r->lock, flags);
++			if (!memcmp(tmp, r->last_data, EXTRACT_SIZE))
++				panic("Hardware RNG duplicated output!\n");
++			memcpy(r->last_data, tmp, EXTRACT_SIZE);
++			spin_unlock_irqrestore(&r->lock, flags);
++		}
++		i = min_t(int, nbytes, EXTRACT_SIZE);
++		memcpy(buf, tmp, i);
++		nbytes -= i;
++		buf += i;
++		ret += i;
++	}
++
++	/* Wipe data just returned from memory */
++	memzero_explicit(tmp, sizeof(tmp));
++
++	return ret;
++}
++
+ /*
+  * This function extracts randomness from the "entropy pool", and
+  * returns it in a buffer.
+@@ -1155,7 +1345,6 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
+ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
+ 				 size_t nbytes, int min, int reserved)
+ {
+-	ssize_t ret = 0, i;
+ 	__u8 tmp[EXTRACT_SIZE];
+ 	unsigned long flags;
+ 
+@@ -1179,27 +1368,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
+ 	xfer_secondary_pool(r, nbytes);
+ 	nbytes = account(r, nbytes, min, reserved);
+ 
+-	while (nbytes) {
+-		extract_buf(r, tmp);
+-
+-		if (fips_enabled) {
+-			spin_lock_irqsave(&r->lock, flags);
+-			if (!memcmp(tmp, r->last_data, EXTRACT_SIZE))
+-				panic("Hardware RNG duplicated output!\n");
+-			memcpy(r->last_data, tmp, EXTRACT_SIZE);
+-			spin_unlock_irqrestore(&r->lock, flags);
+-		}
+-		i = min_t(int, nbytes, EXTRACT_SIZE);
+-		memcpy(buf, tmp, i);
+-		nbytes -= i;
+-		buf += i;
+-		ret += i;
+-	}
+-
+-	/* Wipe data just returned from memory */
+-	memzero_explicit(tmp, sizeof(tmp));
+-
+-	return ret;
++	return _extract_entropy(r, buf, nbytes, fips_enabled);
+ }
+ 
+ /*
+@@ -1254,15 +1423,26 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
+  */
+ void get_random_bytes(void *buf, int nbytes)
+ {
++	__u8 tmp[CHACHA20_BLOCK_SIZE];
++
+ #if DEBUG_RANDOM_BOOT > 0
+-	if (unlikely(nonblocking_pool.initialized == 0))
++	if (!crng_ready())
+ 		printk(KERN_NOTICE "random: %pF get_random_bytes called "
+-		       "with %d bits of entropy available\n",
+-		       (void *) _RET_IP_,
+-		       nonblocking_pool.entropy_total);
++		       "with crng_init = %d\n", (void *) _RET_IP_, crng_init);
+ #endif
+ 	trace_get_random_bytes(nbytes, _RET_IP_);
+-	extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0);
++
++	while (nbytes >= CHACHA20_BLOCK_SIZE) {
++		extract_crng(buf);
++		buf += CHACHA20_BLOCK_SIZE;
++		nbytes -= CHACHA20_BLOCK_SIZE;
++	}
++
++	if (nbytes > 0) {
++		extract_crng(tmp);
++		memcpy(buf, tmp, nbytes);
++		memzero_explicit(tmp, nbytes);
++	}
+ }
+ EXPORT_SYMBOL(get_random_bytes);
+ 
+@@ -1280,7 +1460,7 @@ int add_random_ready_callback(struct random_ready_callback *rdy)
+ 	unsigned long flags;
+ 	int err = -EALREADY;
+ 
+-	if (likely(nonblocking_pool.initialized))
++	if (crng_ready())
+ 		return err;
+ 
+ 	owner = rdy->owner;
+@@ -1288,7 +1468,7 @@ int add_random_ready_callback(struct random_ready_callback *rdy)
+ 		return -ENOENT;
+ 
+ 	spin_lock_irqsave(&random_ready_list_lock, flags);
+-	if (nonblocking_pool.initialized)
++	if (crng_ready())
+ 		goto out;
+ 
+ 	owner = NULL;
+@@ -1352,7 +1532,7 @@ void get_random_bytes_arch(void *buf, int nbytes)
+ 	}
+ 
+ 	if (nbytes)
+-		extract_entropy(&nonblocking_pool, p, nbytes, 0, 0);
++		get_random_bytes(p, nbytes);
+ }
+ EXPORT_SYMBOL(get_random_bytes_arch);
+ 
+@@ -1397,7 +1577,7 @@ static int rand_initialize(void)
+ {
+ 	init_std_data(&input_pool);
+ 	init_std_data(&blocking_pool);
+-	init_std_data(&nonblocking_pool);
++	crng_initialize(&primary_crng);
+ 	return 0;
+ }
+ early_initcall(rand_initialize);
+@@ -1459,22 +1639,22 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+ static ssize_t
+ urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+ {
++	unsigned long flags;
+ 	static int maxwarn = 10;
+ 	int ret;
+ 
+-	if (unlikely(nonblocking_pool.initialized == 0) &&
+-	    maxwarn > 0) {
++	if (!crng_ready() && maxwarn > 0) {
+ 		maxwarn--;
+ 		printk(KERN_NOTICE "random: %s: uninitialized urandom read "
+-		       "(%zd bytes read, %d bits of entropy available)\n",
+-		       current->comm, nbytes, nonblocking_pool.entropy_total);
++		       "(%zd bytes read)\n",
++		       current->comm, nbytes);
++		spin_lock_irqsave(&primary_crng.lock, flags);
++		crng_init_cnt = 0;
++		spin_unlock_irqrestore(&primary_crng.lock, flags);
+ 	}
+-
+ 	nbytes = min_t(size_t, nbytes, INT_MAX >> (ENTROPY_SHIFT + 3));
+-	ret = extract_entropy_user(&nonblocking_pool, buf, nbytes);
+-
+-	trace_urandom_read(8 * nbytes, ENTROPY_BITS(&nonblocking_pool),
+-			   ENTROPY_BITS(&input_pool));
++	ret = extract_crng_user(buf, nbytes);
++	trace_urandom_read(8 * nbytes, 0, ENTROPY_BITS(&input_pool));
+ 	return ret;
+ }
+ 
+@@ -1520,10 +1700,7 @@ static ssize_t random_write(struct file *file, const char __user *buffer,
+ {
+ 	size_t ret;
+ 
+-	ret = write_pool(&blocking_pool, buffer, count);
+-	if (ret)
+-		return ret;
+-	ret = write_pool(&nonblocking_pool, buffer, count);
++	ret = write_pool(&input_pool, buffer, count);
+ 	if (ret)
+ 		return ret;
+ 
+@@ -1574,7 +1751,6 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+ 		if (!capable(CAP_SYS_ADMIN))
+ 			return -EPERM;
+ 		input_pool.entropy_count = 0;
+-		nonblocking_pool.entropy_count = 0;
+ 		blocking_pool.entropy_count = 0;
+ 		return 0;
+ 	default:
+@@ -1616,11 +1792,10 @@ SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
+ 	if (flags & GRND_RANDOM)
+ 		return _random_read(flags & GRND_NONBLOCK, buf, count);
+ 
+-	if (unlikely(nonblocking_pool.initialized == 0)) {
++	if (!crng_ready()) {
+ 		if (flags & GRND_NONBLOCK)
+ 			return -EAGAIN;
+-		wait_event_interruptible(urandom_init_wait,
+-					 nonblocking_pool.initialized);
++		crng_wait_ready();
+ 		if (signal_pending(current))
+ 			return -ERESTARTSYS;
+ 	}
+@@ -1856,18 +2031,17 @@ void add_hwgenerator_randomness(const char *buffer, size_t count,
+ {
+ 	struct entropy_store *poolp = &input_pool;
+ 
+-	if (unlikely(nonblocking_pool.initialized == 0))
+-		poolp = &nonblocking_pool;
+-	else {
+-		/* Suspend writing if we're above the trickle
+-		 * threshold.  We'll be woken up again once below
+-		 * random_write_wakeup_thresh, or when the calling
+-		 * thread is about to terminate.
+-		 */
+-		wait_event_interruptible(random_write_wait,
+-					 kthread_should_stop() ||
+-			ENTROPY_BITS(&input_pool) <= random_write_wakeup_bits);
++	if (!crng_ready()) {
++		crng_fast_load(buffer, count);
++		return;
+ 	}
++
++	/* Suspend writing if we're above the trickle threshold.
++	 * We'll be woken up again once below random_write_wakeup_thresh,
++	 * or when the calling thread is about to terminate.
++	 */
++	wait_event_interruptible(random_write_wait, kthread_should_stop() ||
++			ENTROPY_BITS(&input_pool) <= random_write_wakeup_bits);
+ 	mix_pool_bytes(poolp, buffer, count);
+ 	credit_entropy_bits(poolp, entropy);
+ }
+diff --git a/include/crypto/chacha20.h b/include/crypto/chacha20.h
+index 274bbaeeed0f..20d20f681a72 100644
+--- a/include/crypto/chacha20.h
++++ b/include/crypto/chacha20.h
+@@ -16,6 +16,7 @@ struct chacha20_ctx {
+ 	u32 key[8];
+ };
+ 
++void chacha20_block(u32 *state, void *stream);
+ void crypto_chacha20_init(u32 *state, struct chacha20_ctx *ctx, u8 *iv);
+ int crypto_chacha20_setkey(struct crypto_tfm *tfm, const u8 *key,
+ 			   unsigned int keysize);
+diff --git a/lib/Makefile b/lib/Makefile
+index 499fb354d627..34e205facfa3 100644
+--- a/lib/Makefile
++++ b/lib/Makefile
+@@ -22,7 +22,7 @@ KCOV_INSTRUMENT_hweight.o := n
+ lib-y := ctype.o string.o vsprintf.o cmdline.o \
+ 	 rbtree.o radix-tree.o dump_stack.o timerqueue.o\
+ 	 idr.o int_sqrt.o extable.o \
+-	 sha1.o md5.o irq_regs.o argv_split.o \
++	 sha1.o chacha20.o md5.o irq_regs.o argv_split.o \
+ 	 flex_proportions.o ratelimit.o show_mem.o \
+ 	 is_single_threaded.o plist.o decompress.o kobject_uevent.o \
+ 	 earlycpio.o seq_buf.o nmi_backtrace.o nodemask.o
+diff --git a/lib/chacha20.c b/lib/chacha20.c
+new file mode 100644
+index 000000000000..250ceed9ec9a
+--- /dev/null
++++ b/lib/chacha20.c
+@@ -0,0 +1,79 @@
++/*
++ * ChaCha20 256-bit cipher algorithm, RFC7539
++ *
++ * Copyright (C) 2015 Martin Willi
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++static inline u32 rotl32(u32 v, u8 n)
++{
++	return (v << n) | (v >> (sizeof(v) * 8 - n));
++}
++
++extern void chacha20_block(u32 *state, void *stream)
++{
++	u32 x[16], *out = stream;
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(x); i++)
++		x[i] = state[i];
++
++	for (i = 0; i < 20; i += 2) {
++		x[0]  += x[4];    x[12] = rotl32(x[12] ^ x[0],  16);
++		x[1]  += x[5];    x[13] = rotl32(x[13] ^ x[1],  16);
++		x[2]  += x[6];    x[14] = rotl32(x[14] ^ x[2],  16);
++		x[3]  += x[7];    x[15] = rotl32(x[15] ^ x[3],  16);
++
++		x[8]  += x[12];   x[4]  = rotl32(x[4]  ^ x[8],  12);
++		x[9]  += x[13];   x[5]  = rotl32(x[5]  ^ x[9],  12);
++		x[10] += x[14];   x[6]  = rotl32(x[6]  ^ x[10], 12);
++		x[11] += x[15];   x[7]  = rotl32(x[7]  ^ x[11], 12);
++
++		x[0]  += x[4];    x[12] = rotl32(x[12] ^ x[0],   8);
++		x[1]  += x[5];    x[13] = rotl32(x[13] ^ x[1],   8);
++		x[2]  += x[6];    x[14] = rotl32(x[14] ^ x[2],   8);
++		x[3]  += x[7];    x[15] = rotl32(x[15] ^ x[3],   8);
++
++		x[8]  += x[12];   x[4]  = rotl32(x[4]  ^ x[8],   7);
++		x[9]  += x[13];   x[5]  = rotl32(x[5]  ^ x[9],   7);
++		x[10] += x[14];   x[6]  = rotl32(x[6]  ^ x[10],  7);
++		x[11] += x[15];   x[7]  = rotl32(x[7]  ^ x[11],  7);
++
++		x[0]  += x[5];    x[15] = rotl32(x[15] ^ x[0],  16);
++		x[1]  += x[6];    x[12] = rotl32(x[12] ^ x[1],  16);
++		x[2]  += x[7];    x[13] = rotl32(x[13] ^ x[2],  16);
++		x[3]  += x[4];    x[14] = rotl32(x[14] ^ x[3],  16);
++
++		x[10] += x[15];   x[5]  = rotl32(x[5]  ^ x[10], 12);
++		x[11] += x[12];   x[6]  = rotl32(x[6]  ^ x[11], 12);
++		x[8]  += x[13];   x[7]  = rotl32(x[7]  ^ x[8],  12);
++		x[9]  += x[14];   x[4]  = rotl32(x[4]  ^ x[9],  12);
++
++		x[0]  += x[5];    x[15] = rotl32(x[15] ^ x[0],   8);
++		x[1]  += x[6];    x[12] = rotl32(x[12] ^ x[1],   8);
++		x[2]  += x[7];    x[13] = rotl32(x[13] ^ x[2],   8);
++		x[3]  += x[4];    x[14] = rotl32(x[14] ^ x[3],   8);
++
++		x[10] += x[15];   x[5]  = rotl32(x[5]  ^ x[10],  7);
++		x[11] += x[12];   x[6]  = rotl32(x[6]  ^ x[11],  7);
++		x[8]  += x[13];   x[7]  = rotl32(x[7]  ^ x[8],   7);
++		x[9]  += x[14];   x[4]  = rotl32(x[4]  ^ x[9],   7);
++	}
++
++	for (i = 0; i < ARRAY_SIZE(x); i++)
++		out[i] = cpu_to_le32(x[i] + state[i]);
++
++	state[12]++;
++}
++EXPORT_SYMBOL(chacha20_block);

commit 78d962510796fdf39ccc5efd23d2eea2eca1ed99
+Author: Theodore Ts'o 
+Date:   Sun Jun 26 18:25:01 2016 -0400
+
+    ext4: respect the nobarrier mount option in nojournal mode
+    
+    Also, if we are going to issue the barrier, we should do this after we
+    write out the parent directories if necessary.
+    
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
+index 8850254136ae..5c4372512ef7 100644
+--- a/fs/ext4/fsync.c
++++ b/fs/ext4/fsync.c
+@@ -106,9 +106,11 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
+ 	}
+ 
+ 	if (!journal) {
+-		ret = generic_file_fsync(file, start, end, datasync);
++		ret = __generic_file_fsync(file, start, end, datasync);
+ 		if (!ret && !hlist_empty(&inode->i_dentry))
+ 			ret = ext4_sync_parent(inode);
++		if (test_opt(inode->i_sb, BARRIER))
++			goto issue_flush;
+ 		goto out;
+ 	}
+ 
+@@ -140,6 +142,7 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
+ 		needs_barrier = true;
+ 	ret = jbd2_complete_transaction(journal, commit_tid);
+ 	if (needs_barrier) {
++	issue_flush:
+ 		err = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
+ 		if (!ret)
+ 			ret = err;

commit d08854f5bcf3ea0cabc6fd2fc49c2d97e00c7c88
+Author: Theodore Ts'o 
+Date:   Sun Jun 26 18:24:01 2016 -0400
+
+    ext4: optimize ext4_should_retry_alloc() to improve ENOSPC performance
+    
+    If there are no pending blocks to be released after a commit, forcing
+    a journal commit has no hope of helping.  It's possible that a commit
+    had just completed, so if there are now free blocks available for
+    allocation, it's worth retrying the commit.
+    
+    Reported-by: Chao Yu 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 3020fd70c392..0b8105b3293d 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -610,7 +610,9 @@ int ext4_should_retry_alloc(struct super_block *sb, int *retries)
+ 
+ 	jbd_debug(1, "%s: retrying operation after ENOSPC\n", sb->s_id);
+ 
+-	jbd2_journal_force_commit_nested(EXT4_SB(sb)->s_journal);
++	smp_mb();
++	if (EXT4_SB(sb)->s_mb_free_pending)
++		jbd2_journal_force_commit_nested(EXT4_SB(sb)->s_journal);
+ 	return 1;
+ }
+ 
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index b84aa1ca480a..96c73e6fec6e 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1430,6 +1430,7 @@ struct ext4_sb_info {
+ 	unsigned short *s_mb_offsets;
+ 	unsigned int *s_mb_maxs;
+ 	unsigned int s_group_info_size;
++	unsigned int s_mb_free_pending;
+ 
+ 	/* tunables */
+ 	unsigned long s_stripe;
+diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
+index 09c1ef38cbe6..b1d52c14098e 100644
+--- a/fs/ext4/ext4_jbd2.h
++++ b/fs/ext4/ext4_jbd2.h
+@@ -175,6 +175,13 @@ struct ext4_journal_cb_entry {
+  * There is no guaranteed calling order of multiple registered callbacks on
+  * the same transaction.
+  */
++static inline void _ext4_journal_callback_add(handle_t *handle,
++			struct ext4_journal_cb_entry *jce)
++{
++	/* Add the jce to transaction's private list */
++	list_add_tail(&jce->jce_list, &handle->h_transaction->t_private_list);
++}
++
+ static inline void ext4_journal_callback_add(handle_t *handle,
+ 			void (*func)(struct super_block *sb,
+ 				     struct ext4_journal_cb_entry *jce,
+@@ -187,10 +194,11 @@ static inline void ext4_journal_callback_add(handle_t *handle,
+ 	/* Add the jce to transaction's private list */
+ 	jce->jce_func = func;
+ 	spin_lock(&sbi->s_md_lock);
+-	list_add_tail(&jce->jce_list, &handle->h_transaction->t_private_list);
++	_ext4_journal_callback_add(handle, jce);
+ 	spin_unlock(&sbi->s_md_lock);
+ }
+ 
++
+ /**
+  * ext4_journal_callback_del: delete a registered callback
+  * @handle: active journal transaction handle on which callback was registered
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index c1ab3ec30423..77249e1f5c3a 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2627,6 +2627,7 @@ int ext4_mb_init(struct super_block *sb)
+ 
+ 	spin_lock_init(&sbi->s_md_lock);
+ 	spin_lock_init(&sbi->s_bal_lock);
++	sbi->s_mb_free_pending = 0;
+ 
+ 	sbi->s_mb_max_to_scan = MB_DEFAULT_MAX_TO_SCAN;
+ 	sbi->s_mb_min_to_scan = MB_DEFAULT_MIN_TO_SCAN;
+@@ -2814,6 +2815,9 @@ static void ext4_free_data_callback(struct super_block *sb,
+ 	/* we expect to find existing buddy because it's pinned */
+ 	BUG_ON(err != 0);
+ 
++	spin_lock(&EXT4_SB(sb)->s_md_lock);
++	EXT4_SB(sb)->s_mb_free_pending -= entry->efd_count;
++	spin_unlock(&EXT4_SB(sb)->s_md_lock);
+ 
+ 	db = e4b.bd_info;
+ 	/* there are blocks to put in buddy to make them really free */
+@@ -4583,6 +4587,7 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
+ {
+ 	ext4_group_t group = e4b->bd_group;
+ 	ext4_grpblk_t cluster;
++	ext4_grpblk_t clusters = new_entry->efd_count;
+ 	struct ext4_free_data *entry;
+ 	struct ext4_group_info *db = e4b->bd_info;
+ 	struct super_block *sb = e4b->bd_sb;
+@@ -4649,8 +4654,11 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
+ 		}
+ 	}
+ 	/* Add the extent to transaction's private list */
+-	ext4_journal_callback_add(handle, ext4_free_data_callback,
+-				  &new_entry->efd_jce);
++	new_entry->efd_jce.jce_func = ext4_free_data_callback;
++	spin_lock(&sbi->s_md_lock);
++	_ext4_journal_callback_add(handle, &new_entry->efd_jce);
++	sbi->s_mb_free_pending += clusters;
++	spin_unlock(&sbi->s_md_lock);
+ 	return 0;
+ }
+ 

commit 9b4d008787f864f17d008c9c15bbe8a0f7e2fc24
+Author: Theodore Ts'o 
+Date:   Mon Jun 13 10:10:51 2016 -0400
+
+    random: print a warning for the first ten uninitialized random users
+    
+    Since systemd is consistently using /dev/urandom before it is
+    initialized, we can't see the other potentially dangerous users of
+    /dev/urandom immediately after boot.  So print the first ten such
+    complaints instead.
+    
+    Cc: stable@kernel.org
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 4e2627a8d226..d057438266bb 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -1458,12 +1458,16 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+ static ssize_t
+ urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+ {
++	static int maxwarn = 10;
+ 	int ret;
+ 
+-	if (unlikely(nonblocking_pool.initialized == 0))
+-		printk_once(KERN_NOTICE "random: %s urandom read "
+-			    "with %d bits of entropy available\n",
+-			    current->comm, nonblocking_pool.entropy_total);
++	if (unlikely(nonblocking_pool.initialized == 0) &&
++	    maxwarn > 0) {
++		maxwarn--;
++		printk(KERN_NOTICE "random: %s: uninitialized urandom read "
++		       "(%zd bytes read, %d bits of entropy available)\n",
++		       current->comm, nbytes, nonblocking_pool.entropy_total);
++	}
+ 
+ 	nbytes = min_t(size_t, nbytes, INT_MAX >> (ENTROPY_SHIFT + 3));
+ 	ret = extract_entropy_user(&nonblocking_pool, buf, nbytes);

commit 3371f3da08cff4b75c1f2dce742d460539d6566d
+Author: Theodore Ts'o 
+Date:   Sun Jun 12 18:11:51 2016 -0400
+
+    random: initialize the non-blocking pool via add_hwgenerator_randomness()
+    
+    If we have a hardware RNG and are using the in-kernel rngd, we should
+    use this to initialize the non-blocking pool so that getrandom(2)
+    doesn't block unnecessarily.
+    
+    Cc: stable@kernel.org
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 0158d3bff7e5..4e2627a8d226 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -1849,12 +1849,18 @@ void add_hwgenerator_randomness(const char *buffer, size_t count,
+ {
+ 	struct entropy_store *poolp = &input_pool;
+ 
+-	/* Suspend writing if we're above the trickle threshold.
+-	 * We'll be woken up again once below random_write_wakeup_thresh,
+-	 * or when the calling thread is about to terminate.
+-	 */
+-	wait_event_interruptible(random_write_wait, kthread_should_stop() ||
++	if (unlikely(nonblocking_pool.initialized == 0))
++		poolp = &nonblocking_pool;
++	else {
++		/* Suspend writing if we're above the trickle
++		 * threshold.  We'll be woken up again once below
++		 * random_write_wakeup_thresh, or when the calling
++		 * thread is about to terminate.
++		 */
++		wait_event_interruptible(random_write_wait,
++					 kthread_should_stop() ||
+ 			ENTROPY_BITS(&input_pool) <= random_write_wakeup_bits);
++	}
+ 	mix_pool_bytes(poolp, buffer, count);
+ 	credit_entropy_bits(poolp, entropy);
+ }

commit 7827a7f6ebfcb7f388dc47fddd48567a314701ba
+Author: Theodore Ts'o 
+Date:   Sat Apr 30 00:49:54 2016 -0400
+
+    ext4: clean up error handling when orphan list is corrupted
+    
+    Instead of just printing warning messages, if the orphan list is
+    corrupted, declare the file system is corrupted.  If there are any
+    reserved inodes in the orphaned inode list, declare the file system
+    corrupted and stop right away to avoid doing more potential damage to
+    the file system.
+    
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index c2caf2df3695..3da4cf8d18b6 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -1150,25 +1150,20 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
+ 	unsigned long max_ino = le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count);
+ 	ext4_group_t block_group;
+ 	int bit;
+-	struct buffer_head *bitmap_bh;
++	struct buffer_head *bitmap_bh = NULL;
+ 	struct inode *inode = NULL;
+-	long err = -EIO;
++	int err = -EFSCORRUPTED;
+ 
+-	/* Error cases - e2fsck has already cleaned up for us */
+-	if (ino > max_ino) {
+-		ext4_warning(sb, "bad orphan ino %lu!  e2fsck was run?", ino);
+-		err = -EFSCORRUPTED;
+-		goto error;
+-	}
++	if (ino < EXT4_FIRST_INO(sb) || ino > max_ino)
++		goto bad_orphan;
+ 
+ 	block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb);
+ 	bit = (ino - 1) % EXT4_INODES_PER_GROUP(sb);
+ 	bitmap_bh = ext4_read_inode_bitmap(sb, block_group);
+ 	if (IS_ERR(bitmap_bh)) {
+-		err = PTR_ERR(bitmap_bh);
+-		ext4_warning(sb, "inode bitmap error %ld for orphan %lu",
+-			     ino, err);
+-		goto error;
++		ext4_error(sb, "inode bitmap error %ld for orphan %lu",
++			   ino, PTR_ERR(bitmap_bh));
++		return (struct inode *) bitmap_bh;
+ 	}
+ 
+ 	/* Having the inode bit set should be a 100% indicator that this
+@@ -1179,8 +1174,12 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
+ 		goto bad_orphan;
+ 
+ 	inode = ext4_iget(sb, ino);
+-	if (IS_ERR(inode))
+-		goto iget_failed;
++	if (IS_ERR(inode)) {
++		err = PTR_ERR(inode);
++		ext4_error(sb, "couldn't read orphan inode %lu (err %d)",
++			   ino, err);
++		return inode;
++	}
+ 
+ 	/*
+ 	 * If the orphans has i_nlinks > 0 then it should be able to
+@@ -1197,29 +1196,25 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
+ 	brelse(bitmap_bh);
+ 	return inode;
+ 
+-iget_failed:
+-	err = PTR_ERR(inode);
+-	inode = NULL;
+ bad_orphan:
+-	ext4_warning(sb, "bad orphan inode %lu!  e2fsck was run?", ino);
+-	printk(KERN_WARNING "ext4_test_bit(bit=%d, block=%llu) = %d\n",
+-	       bit, (unsigned long long)bitmap_bh->b_blocknr,
+-	       ext4_test_bit(bit, bitmap_bh->b_data));
+-	printk(KERN_WARNING "inode=%p\n", inode);
++	ext4_error(sb, "bad orphan inode %lu", ino);
++	if (bitmap_bh)
++		printk(KERN_ERR "ext4_test_bit(bit=%d, block=%llu) = %d\n",
++		       bit, (unsigned long long)bitmap_bh->b_blocknr,
++		       ext4_test_bit(bit, bitmap_bh->b_data));
+ 	if (inode) {
+-		printk(KERN_WARNING "is_bad_inode(inode)=%d\n",
++		printk(KERN_ERR "is_bad_inode(inode)=%d\n",
+ 		       is_bad_inode(inode));
+-		printk(KERN_WARNING "NEXT_ORPHAN(inode)=%u\n",
++		printk(KERN_ERR "NEXT_ORPHAN(inode)=%u\n",
+ 		       NEXT_ORPHAN(inode));
+-		printk(KERN_WARNING "max_ino=%lu\n", max_ino);
+-		printk(KERN_WARNING "i_nlink=%u\n", inode->i_nlink);
++		printk(KERN_ERR "max_ino=%lu\n", max_ino);
++		printk(KERN_ERR "i_nlink=%u\n", inode->i_nlink);
+ 		/* Avoid freeing blocks if we got a bad deleted inode */
+ 		if (inode->i_nlink == 0)
+ 			inode->i_blocks = 0;
+ 		iput(inode);
+ 	}
+ 	brelse(bitmap_bh);
+-error:
+ 	return ERR_PTR(err);
+ }
+ 

commit c9eb13a9105e2e418f72e46a2b6da3f49e696902
+Author: Theodore Ts'o 
+Date:   Sat Apr 30 00:48:54 2016 -0400
+
+    ext4: fix hang when processing corrupted orphaned inode list
+    
+    If the orphaned inode list contains inode #5, ext4_iget() returns a
+    bad inode (since the bootloader inode should never be referenced
+    directly).  Because of the bad inode, we end up processing the inode
+    repeatedly and this hangs the machine.
+    
+    This can be reproduced via:
+    
+       mke2fs -t ext4 /tmp/foo.img 100
+       debugfs -w -R "ssv last_orphan 5" /tmp/foo.img
+       mount -o loop /tmp/foo.img /mnt
+    
+    (But don't do this if you are using an unpatched kernel if you care
+    about the system staying functional.  :-)
+    
+    This bug was found by the port of American Fuzzy Lop into the kernel
+    to find file system problems[1].  (Since it *only* happens if inode #5
+    shows up on the orphan list --- 3, 7, 8, etc. won't do it, it's not
+    surprising that AFL needed two hours before it found it.)
+    
+    [1] http://events.linuxfoundation.org/sites/events/files/slides/AFL%20filesystem%20fuzzing%2C%20Vault%202016_0.pdf
+    
+    Cc: stable@vger.kernel.org
+    Reported by: Vegard Nossum 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 237b877d316d..c2caf2df3695 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -1183,11 +1183,13 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
+ 		goto iget_failed;
+ 
+ 	/*
+-	 * If the orphans has i_nlinks > 0 then it should be able to be
+-	 * truncated, otherwise it won't be removed from the orphan list
+-	 * during processing and an infinite loop will result.
++	 * If the orphans has i_nlinks > 0 then it should be able to
++	 * be truncated, otherwise it won't be removed from the orphan
++	 * list during processing and an infinite loop will result.
++	 * Similarly, it must not be a bad inode.
+ 	 */
+-	if (inode->i_nlink && !ext4_can_truncate(inode))
++	if ((inode->i_nlink && !ext4_can_truncate(inode)) ||
++	    is_bad_inode(inode))
+ 		goto bad_orphan;
+ 
+ 	if (NEXT_ORPHAN(inode) > max_ino)

commit 7b8081912d75df1d910d6969f0a374b66ef242bf
+Author: Theodore Ts'o 
+Date:   Mon Apr 25 23:13:17 2016 -0400
+
+    ext4: fix jbd2 handle extension in ext4_ext_truncate_extend_restart()
+    
+    The function jbd2_journal_extend() takes as its argument the number of
+    new credits to be added to the handle.  We weren't taking into account
+    the currently unused handle credits; worse, we would try to extend the
+    handle by N credits when it had N credits available.
+    
+    In the case where jbd2_journal_extend() fails because the transaction
+    is too large, when jbd2_journal_restart() gets called, the N credits
+    owned by the handle gets returned to the transaction, and the
+    transaction commit is asynchronously requested, and then
+    start_this_handle() will be able to successfully attach the handle to
+    the current transaction since the required credits are now available.
+    
+    This is mostly harmless, but since ext4_ext_truncate_extend_restart()
+    returns EAGAIN, the truncate machinery will once again try to call
+    ext4_ext_truncate_extend_restart(), which will do the above sequence
+    over and over again until the transaction has committed.
+    
+    This was found while I was debugging a lockup in caused by running
+    xfstests generic/074 in the data=journal case.  I'm still not sure why
+    we ended up looping forever, which suggests there may still be another
+    bug hiding in the transaction accounting machinery, but this commit
+    prevents us from looping in the first place.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 95bf4679ac54..ba2be53a61d2 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -120,9 +120,14 @@ static int ext4_ext_truncate_extend_restart(handle_t *handle,
+ 
+ 	if (!ext4_handle_valid(handle))
+ 		return 0;
+-	if (handle->h_buffer_credits > needed)
++	if (handle->h_buffer_credits >= needed)
+ 		return 0;
+-	err = ext4_journal_extend(handle, needed);
++	/*
++	 * If we need to extend the journal get a few extra blocks
++	 * while we're at it for efficiency's sake.
++	 */
++	needed += 3;
++	err = ext4_journal_extend(handle, needed - handle->h_buffer_credits);
+ 	if (err <= 0)
+ 		return err;
+ 	err = ext4_truncate_restart_trans(handle, inode, needed);

commit 1f60fbe7274918adb8db2f616e321890730ab7e3
+Author: Theodore Ts'o 
+Date:   Sat Apr 23 22:50:07 2016 -0400
+
+    ext4: allow readdir()'s of large empty directories to be interrupted
+    
+    If a directory has a large number of empty blocks, iterating over all
+    of them can take a long time, leading to scheduler warnings and users
+    getting irritated when they can't kill a process in the middle of one
+    of these long-running readdir operations.  Fix this by adding checks to
+    ext4_readdir() and ext4_htree_fill_tree().
+    
+    This was reverted earlier due to a typo in the original commit where I
+    experimented with using signal_pending() instead of
+    fatal_signal_pending().  The test was in the wrong place if we were
+    going to return signal_pending() since we would end up returning
+    duplicant entries.  See 9f2394c9be47 for a more detailed explanation.
+    
+    Added fix as suggested by Linus to check for signal_pending() in
+    in the filldir() functions.
+    
+    Reported-by: Benjamin LaHaise 
+    Google-Bug-Id: 27880676
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/compat.c b/fs/compat.c
+index a71936a3f4cb..f940cb20562f 100644
+--- a/fs/compat.c
++++ b/fs/compat.c
+@@ -936,6 +936,8 @@ static int compat_filldir(struct dir_context *ctx, const char *name, int namlen,
+ 	}
+ 	dirent = buf->previous;
+ 	if (dirent) {
++		if (signal_pending(current))
++			return -EINTR;
+ 		if (__put_user(offset, &dirent->d_off))
+ 			goto efault;
+ 	}
+@@ -1020,6 +1022,8 @@ static int compat_filldir64(struct dir_context *ctx, const char *name,
+ 	dirent = buf->previous;
+ 
+ 	if (dirent) {
++		if (signal_pending(current))
++			return -EINTR;
+ 		if (__put_user_unaligned(offset, &dirent->d_off))
+ 			goto efault;
+ 	}
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index 561d7308b393..4173bfe21114 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -150,6 +150,11 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
+ 	while (ctx->pos < inode->i_size) {
+ 		struct ext4_map_blocks map;
+ 
++		if (fatal_signal_pending(current)) {
++			err = -ERESTARTSYS;
++			goto errout;
++		}
++		cond_resched();
+ 		map.m_lblk = ctx->pos >> EXT4_BLOCK_SIZE_BITS(sb);
+ 		map.m_len = 1;
+ 		err = ext4_map_blocks(NULL, inode, &map, 0);
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 48e4b8907826..c07422d254b6 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1107,6 +1107,11 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
+ 	}
+ 
+ 	while (1) {
++		if (fatal_signal_pending(current)) {
++			err = -ERESTARTSYS;
++			goto errout;
++		}
++		cond_resched();
+ 		block = dx_get_block(frame->at);
+ 		ret = htree_dirblock_to_tree(dir_file, dir, block, &hinfo,
+ 					     start_hash, start_minor_hash);
+diff --git a/fs/readdir.c b/fs/readdir.c
+index e69ef3b79787..5f2d4bee5a73 100644
+--- a/fs/readdir.c
++++ b/fs/readdir.c
+@@ -169,6 +169,8 @@ static int filldir(struct dir_context *ctx, const char *name, int namlen,
+ 	}
+ 	dirent = buf->previous;
+ 	if (dirent) {
++		if (signal_pending(current))
++			return -EINTR;
+ 		if (__put_user(offset, &dirent->d_off))
+ 			goto efault;
+ 	}
+@@ -248,6 +250,8 @@ static int filldir64(struct dir_context *ctx, const char *name, int namlen,
+ 		return -EINVAL;
+ 	dirent = buf->previous;
+ 	if (dirent) {
++		if (signal_pending(current))
++			return -EINTR;
+ 		if (__put_user(offset, &dirent->d_off))
+ 			goto efault;
+ 	}

commit c325a67c72903e1cc30e990a15ce745bda0dbfde
+Author: Theodore Ts'o 
+Date:   Sun Apr 3 17:03:37 2016 -0400
+
+    ext4: ignore quota mount options if the quota feature is enabled
+    
+    Previously, ext4 would fail the mount if the file system had the quota
+    feature enabled and quota mount options (used for the older quota
+    setups) were present.  This broke xfstests, since xfs silently ignores
+    the usrquote and grpquota mount options if they are specified.  This
+    commit changes things so that we are consistent with xfs; having the
+    mount options specified is harmless, so no sense break users by
+    forbidding them.
+    
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 51a131162c11..df213616dc39 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1324,9 +1324,9 @@ static int set_qf_name(struct super_block *sb, int qtype, substring_t *args)
+ 		return -1;
+ 	}
+ 	if (ext4_has_feature_quota(sb)) {
+-		ext4_msg(sb, KERN_ERR, "Cannot set journaled quota options "
+-			 "when QUOTA feature is enabled");
+-		return -1;
++		ext4_msg(sb, KERN_INFO, "Journaled quota options "
++			 "ignored when QUOTA feature is enabled");
++		return 1;
+ 	}
+ 	qname = match_strdup(args);
+ 	if (!qname) {
+@@ -1689,10 +1689,10 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
+ 			return -1;
+ 		}
+ 		if (ext4_has_feature_quota(sb)) {
+-			ext4_msg(sb, KERN_ERR,
+-				 "Cannot set journaled quota options "
++			ext4_msg(sb, KERN_INFO,
++				 "Quota format mount options ignored "
+ 				 "when QUOTA feature is enabled");
+-			return -1;
++			return 1;
+ 		}
+ 		sbi->s_jquota_fmt = m->mount_opt;
+ #endif
+@@ -1757,11 +1757,11 @@ static int parse_options(char *options, struct super_block *sb,
+ #ifdef CONFIG_QUOTA
+ 	if (ext4_has_feature_quota(sb) &&
+ 	    (test_opt(sb, USRQUOTA) || test_opt(sb, GRPQUOTA))) {
+-		ext4_msg(sb, KERN_ERR, "Cannot set quota options when QUOTA "
+-			 "feature is enabled");
+-		return 0;
+-	}
+-	if (sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]) {
++		ext4_msg(sb, KERN_INFO, "Quota feature enabled, usrquota and grpquota "
++			 "mount options ignored.");
++		clear_opt(sb, USRQUOTA);
++		clear_opt(sb, GRPQUOTA);
++	} else if (sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]) {
+ 		if (test_opt(sb, USRQUOTA) && sbi->s_qf_names[USRQUOTA])
+ 			clear_opt(sb, USRQUOTA);
+ 

commit 8f0e8746b4d57303d84f7b161a201e94fe22638f
+Author: Theodore Ts'o 
+Date:   Fri Apr 1 12:00:03 2016 -0400
+
+    ext4: avoid calling dquot_get_next_id() if quota is not enabled
+    
+    This should be fixed in the quota layer so we can test with the quota
+    mutex held, but for now, we need this to avoid tests from crashing the
+    kernel aborting the regression test suite.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 7ebd9f040b16..51a131162c11 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1113,6 +1113,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
+ static int ext4_quota_enable(struct super_block *sb, int type, int format_id,
+ 			     unsigned int flags);
+ static int ext4_enable_quotas(struct super_block *sb);
++static int ext4_get_next_id(struct super_block *sb, struct kqid *qid);
+ 
+ static struct dquot **ext4_get_dquots(struct inode *inode)
+ {
+@@ -1129,7 +1130,7 @@ static const struct dquot_operations ext4_quota_operations = {
+ 	.alloc_dquot	= dquot_alloc,
+ 	.destroy_dquot	= dquot_destroy,
+ 	.get_projid	= ext4_get_projid,
+-	.get_next_id	= dquot_get_next_id,
++	.get_next_id	= ext4_get_next_id,
+ };
+ 
+ static const struct quotactl_ops ext4_qctl_operations = {
+@@ -5274,6 +5275,17 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
+ 	return len;
+ }
+ 
++static int ext4_get_next_id(struct super_block *sb, struct kqid *qid)
++{
++	const struct quota_format_ops	*ops;
++
++	if (!sb_has_quota_loaded(sb, qid->type))
++		return -ESRCH;
++	ops = sb_dqopt(sb)->ops[qid->type];
++	if (!ops || !ops->get_next_id)
++		return -ENOSYS;
++	return dquot_get_next_id(sb, qid);
++}
+ #endif
+ 
+ static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags,

commit daf647d2dd58cec59570d7698a45b98e580f2076
+Author: Theodore Ts'o 
+Date:   Fri Apr 1 01:31:28 2016 -0400
+
+    ext4: add lockdep annotations for i_data_sem
+    
+    With the internal Quota feature, mke2fs creates empty quota inodes and
+    quota usage tracking is enabled as soon as the file system is mounted.
+    Since quotacheck is no longer preallocating all of the blocks in the
+    quota inode that are likely needed to be written to, we are now seeing
+    a lockdep false positive caused by needing to allocate a quota block
+    from inside ext4_map_blocks(), while holding i_data_sem for a data
+    inode.  This results in this complaint:
+    
+      Possible unsafe locking scenario:
+    
+            CPU0                    CPU1
+            ----                    ----
+       lock(&ei->i_data_sem);
+                                    lock(&s->s_dquot.dqio_mutex);
+                                    lock(&ei->i_data_sem);
+       lock(&s->s_dquot.dqio_mutex);
+    
+    Google-Bug-Id: 27907753
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 7e4e3e9b4494..6a857af0e6b1 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -911,6 +911,29 @@ do {									       \
+ 
+ #include "extents_status.h"
+ 
++/*
++ * Lock subclasses for i_data_sem in the ext4_inode_info structure.
++ *
++ * These are needed to avoid lockdep false positives when we need to
++ * allocate blocks to the quota inode during ext4_map_blocks(), while
++ * holding i_data_sem for a normal (non-quota) inode.  Since we don't
++ * do quota tracking for the quota inode, this avoids deadlock (as
++ * well as infinite recursion, since it isn't turtles all the way
++ * down...)
++ *
++ *  I_DATA_SEM_NORMAL - Used for most inodes
++ *  I_DATA_SEM_OTHER  - Used by move_inode.c for the second normal inode
++ *			  where the second inode has larger inode number
++ *			  than the first
++ *  I_DATA_SEM_QUOTA  - Used for quota inodes only
++ */
++enum {
++	I_DATA_SEM_NORMAL = 0,
++	I_DATA_SEM_OTHER,
++	I_DATA_SEM_QUOTA,
++};
++
++
+ /*
+  * fourth extended file system inode data in memory
+  */
+diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
+index 4098acc701c3..796ff0eafd3c 100644
+--- a/fs/ext4/move_extent.c
++++ b/fs/ext4/move_extent.c
+@@ -60,10 +60,10 @@ ext4_double_down_write_data_sem(struct inode *first, struct inode *second)
+ {
+ 	if (first < second) {
+ 		down_write(&EXT4_I(first)->i_data_sem);
+-		down_write_nested(&EXT4_I(second)->i_data_sem, SINGLE_DEPTH_NESTING);
++		down_write_nested(&EXT4_I(second)->i_data_sem, I_DATA_SEM_OTHER);
+ 	} else {
+ 		down_write(&EXT4_I(second)->i_data_sem);
+-		down_write_nested(&EXT4_I(first)->i_data_sem, SINGLE_DEPTH_NESTING);
++		down_write_nested(&EXT4_I(first)->i_data_sem, I_DATA_SEM_OTHER);
+ 
+ 	}
+ }
+@@ -484,6 +484,13 @@ mext_check_arguments(struct inode *orig_inode,
+ 		return -EBUSY;
+ 	}
+ 
++	if (IS_NOQUOTA(orig_inode) || IS_NOQUOTA(donor_inode)) {
++		ext4_debug("ext4 move extent: The argument files should "
++			"not be quota files [ino:orig %lu, donor %lu]\n",
++			orig_inode->i_ino, donor_inode->i_ino);
++		return -EBUSY;
++	}
++
+ 	/* Ext4 move extent supports only extent based file */
+ 	if (!(ext4_test_inode_flag(orig_inode, EXT4_INODE_EXTENTS))) {
+ 		ext4_debug("ext4 move extent: orig file is not extents "
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 539297515896..7ebd9f040b16 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -5028,6 +5028,20 @@ static int ext4_quota_on_mount(struct super_block *sb, int type)
+ 					EXT4_SB(sb)->s_jquota_fmt, type);
+ }
+ 
++static void lockdep_set_quota_inode(struct inode *inode, int subclass)
++{
++	struct ext4_inode_info *ei = EXT4_I(inode);
++
++	/* The first argument of lockdep_set_subclass has to be
++	 * *exactly* the same as the argument to init_rwsem() --- in
++	 * this case, in init_once() --- or lockdep gets unhappy
++	 * because the name of the lock is set using the
++	 * stringification of the argument to init_rwsem().
++	 */
++	(void) ei;	/* shut up clang warning if !CONFIG_LOCKDEP */
++	lockdep_set_subclass(&ei->i_data_sem, subclass);
++}
++
+ /*
+  * Standard function to be called on quota_on
+  */
+@@ -5067,8 +5081,12 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
+ 		if (err)
+ 			return err;
+ 	}
+-
+-	return dquot_quota_on(sb, type, format_id, path);
++	lockdep_set_quota_inode(path->dentry->d_inode, I_DATA_SEM_QUOTA);
++	err = dquot_quota_on(sb, type, format_id, path);
++	if (err)
++		lockdep_set_quota_inode(path->dentry->d_inode,
++					     I_DATA_SEM_NORMAL);
++	return err;
+ }
+ 
+ static int ext4_quota_enable(struct super_block *sb, int type, int format_id,
+@@ -5095,8 +5113,11 @@ static int ext4_quota_enable(struct super_block *sb, int type, int format_id,
+ 
+ 	/* Don't account quota for quota files to avoid recursion */
+ 	qf_inode->i_flags |= S_NOQUOTA;
++	lockdep_set_quota_inode(qf_inode, I_DATA_SEM_QUOTA);
+ 	err = dquot_enable(qf_inode, type, format_id, flags);
+ 	iput(qf_inode);
++	if (err)
++		lockdep_set_quota_inode(qf_inode, I_DATA_SEM_NORMAL);
+ 
+ 	return err;
+ }

commit 1028b55bafb7611dda1d8fed2aeca16a436b7dff
+Author: Theodore Ts'o 
+Date:   Wed Mar 30 22:36:24 2016 -0400
+
+    ext4: allow readdir()'s of large empty directories to be interrupted
+    
+    If a directory has a large number of empty blocks, iterating over all
+    of them can take a long time, leading to scheduler warnings and users
+    getting irritated when they can't kill a process in the middle of one
+    of these long-running readdir operations.  Fix this by adding checks to
+    ext4_readdir() and ext4_htree_fill_tree().
+    
+    Reported-by: Benjamin LaHaise 
+    Google-Bug-Id: 27880676
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index 33f5e2a50cf8..ebfcb8999db2 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -150,6 +150,11 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
+ 	while (ctx->pos < inode->i_size) {
+ 		struct ext4_map_blocks map;
+ 
++		if (fatal_signal_pending(current)) {
++			err = -ERESTARTSYS;
++			goto errout;
++		}
++		cond_resched();
+ 		map.m_lblk = ctx->pos >> EXT4_BLOCK_SIZE_BITS(sb);
+ 		map.m_len = 1;
+ 		err = ext4_map_blocks(NULL, inode, &map, 0);
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 48e4b8907826..db98f89f737f 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1107,6 +1107,11 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
+ 	}
+ 
+ 	while (1) {
++		if (signal_pending(current)) {
++			err = -ERESTARTSYS;
++			goto errout;
++		}
++		cond_resched();
+ 		block = dx_get_block(frame->at);
+ 		ret = htree_dirblock_to_tree(dir_file, dir, block, &hinfo,
+ 					     start_hash, start_minor_hash);

commit 3d43bcfef5f0548845a425365011c499875491b0
+Author: Theodore Ts'o 
+Date:   Sat Mar 26 16:15:42 2016 -0400
+
+    ext4 crypto: use dget_parent() in ext4_d_revalidate()
+    
+    This avoids potential problems caused by a race where the inode gets
+    renamed out from its parent directory and the parent directory is
+    deleted while ext4_d_revalidate() is running.
+    
+    Fixes: 28b4c263961c
+    Reported-by: Al Viro 
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
+index 012fd3285147..ea69ce4f6d8f 100644
+--- a/fs/ext4/crypto.c
++++ b/fs/ext4/crypto.c
+@@ -478,13 +478,16 @@ uint32_t ext4_validate_encryption_key_size(uint32_t mode, uint32_t size)
+  */
+ static int ext4_d_revalidate(struct dentry *dentry, unsigned int flags)
+ {
+-	struct inode *dir = d_inode(dentry->d_parent);
+-	struct ext4_crypt_info *ci = EXT4_I(dir)->i_crypt_info;
++	struct dentry *dir;
++	struct ext4_crypt_info *ci;
+ 	int dir_has_key, cached_with_key;
+ 
+-	if (!ext4_encrypted_inode(dir))
++	dir = dget_parent(dentry);
++	if (!ext4_encrypted_inode(d_inode(dir))) {
++		dput(dir);
+ 		return 0;
+-
++	}
++	ci = EXT4_I(d_inode(dir))->i_crypt_info;
+ 	if (ci && ci->ci_keyring_key &&
+ 	    (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) |
+ 					  (1 << KEY_FLAG_REVOKED) |
+@@ -494,6 +497,7 @@ static int ext4_d_revalidate(struct dentry *dentry, unsigned int flags)
+ 	/* this should eventually be an flag in d_flags */
+ 	cached_with_key = dentry->d_fsdata != NULL;
+ 	dir_has_key = (ci != NULL);
++	dput(dir);
+ 
+ 	/*
+ 	 * If the dentry was cached without the key, and it is a

commit c9af28fdd44922a6c10c9f8315718408af98e315
+Author: Theodore Ts'o 
+Date:   Sat Mar 26 16:14:34 2016 -0400
+
+    ext4 crypto: don't let data integrity writebacks fail with ENOMEM
+    
+    We don't want the writeback triggered from the journal commit (in
+    data=writeback mode) to cause the journal to abort due to
+    generic_writepages() returning an ENOMEM error.  In addition, if
+    fsync() fails with ENOMEM, most applications will probably not do the
+    right thing.
+    
+    So if we are doing a data integrity sync, and ext4_encrypt() returns
+    ENOMEM, we will submit any queued I/O to date, and then retry the
+    allocation using GFP_NOFAIL.
+    
+    Google-Bug-Id: 27641567
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
+index edc053a81914..012fd3285147 100644
+--- a/fs/ext4/crypto.c
++++ b/fs/ext4/crypto.c
+@@ -91,7 +91,8 @@ void ext4_release_crypto_ctx(struct ext4_crypto_ctx *ctx)
+  * Return: An allocated and initialized encryption context on success; error
+  * value or NULL otherwise.
+  */
+-struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode)
++struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode,
++					    gfp_t gfp_flags)
+ {
+ 	struct ext4_crypto_ctx *ctx = NULL;
+ 	int res = 0;
+@@ -118,7 +119,7 @@ struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode)
+ 		list_del(&ctx->free_list);
+ 	spin_unlock_irqrestore(&ext4_crypto_ctx_lock, flags);
+ 	if (!ctx) {
+-		ctx = kmem_cache_zalloc(ext4_crypto_ctx_cachep, GFP_NOFS);
++		ctx = kmem_cache_zalloc(ext4_crypto_ctx_cachep, gfp_flags);
+ 		if (!ctx) {
+ 			res = -ENOMEM;
+ 			goto out;
+@@ -255,7 +256,8 @@ static int ext4_page_crypto(struct inode *inode,
+ 			    ext4_direction_t rw,
+ 			    pgoff_t index,
+ 			    struct page *src_page,
+-			    struct page *dest_page)
++			    struct page *dest_page,
++			    gfp_t gfp_flags)
+ 
+ {
+ 	u8 xts_tweak[EXT4_XTS_TWEAK_SIZE];
+@@ -266,7 +268,7 @@ static int ext4_page_crypto(struct inode *inode,
+ 	struct crypto_skcipher *tfm = ci->ci_ctfm;
+ 	int res = 0;
+ 
+-	req = skcipher_request_alloc(tfm, GFP_NOFS);
++	req = skcipher_request_alloc(tfm, gfp_flags);
+ 	if (!req) {
+ 		printk_ratelimited(KERN_ERR
+ 				   "%s: crypto_request_alloc() failed\n",
+@@ -307,9 +309,10 @@ static int ext4_page_crypto(struct inode *inode,
+ 	return 0;
+ }
+ 
+-static struct page *alloc_bounce_page(struct ext4_crypto_ctx *ctx)
++static struct page *alloc_bounce_page(struct ext4_crypto_ctx *ctx,
++				      gfp_t gfp_flags)
+ {
+-	ctx->w.bounce_page = mempool_alloc(ext4_bounce_page_pool, GFP_NOWAIT);
++	ctx->w.bounce_page = mempool_alloc(ext4_bounce_page_pool, gfp_flags);
+ 	if (ctx->w.bounce_page == NULL)
+ 		return ERR_PTR(-ENOMEM);
+ 	ctx->flags |= EXT4_WRITE_PATH_FL;
+@@ -332,7 +335,8 @@ static struct page *alloc_bounce_page(struct ext4_crypto_ctx *ctx)
+  * error value or NULL.
+  */
+ struct page *ext4_encrypt(struct inode *inode,
+-			  struct page *plaintext_page)
++			  struct page *plaintext_page,
++			  gfp_t gfp_flags)
+ {
+ 	struct ext4_crypto_ctx *ctx;
+ 	struct page *ciphertext_page = NULL;
+@@ -340,17 +344,17 @@ struct page *ext4_encrypt(struct inode *inode,
+ 
+ 	BUG_ON(!PageLocked(plaintext_page));
+ 
+-	ctx = ext4_get_crypto_ctx(inode);
++	ctx = ext4_get_crypto_ctx(inode, gfp_flags);
+ 	if (IS_ERR(ctx))
+ 		return (struct page *) ctx;
+ 
+ 	/* The encryption operation will require a bounce page. */
+-	ciphertext_page = alloc_bounce_page(ctx);
++	ciphertext_page = alloc_bounce_page(ctx, gfp_flags);
+ 	if (IS_ERR(ciphertext_page))
+ 		goto errout;
+ 	ctx->w.control_page = plaintext_page;
+ 	err = ext4_page_crypto(inode, EXT4_ENCRYPT, plaintext_page->index,
+-			       plaintext_page, ciphertext_page);
++			       plaintext_page, ciphertext_page, gfp_flags);
+ 	if (err) {
+ 		ciphertext_page = ERR_PTR(err);
+ 	errout:
+@@ -378,8 +382,8 @@ int ext4_decrypt(struct page *page)
+ {
+ 	BUG_ON(!PageLocked(page));
+ 
+-	return ext4_page_crypto(page->mapping->host,
+-				EXT4_DECRYPT, page->index, page, page);
++	return ext4_page_crypto(page->mapping->host, EXT4_DECRYPT,
++				page->index, page, page, GFP_NOFS);
+ }
+ 
+ int ext4_encrypted_zeroout(struct inode *inode, ext4_lblk_t lblk,
+@@ -398,11 +402,11 @@ int ext4_encrypted_zeroout(struct inode *inode, ext4_lblk_t lblk,
+ 
+ 	BUG_ON(inode->i_sb->s_blocksize != PAGE_CACHE_SIZE);
+ 
+-	ctx = ext4_get_crypto_ctx(inode);
++	ctx = ext4_get_crypto_ctx(inode, GFP_NOFS);
+ 	if (IS_ERR(ctx))
+ 		return PTR_ERR(ctx);
+ 
+-	ciphertext_page = alloc_bounce_page(ctx);
++	ciphertext_page = alloc_bounce_page(ctx, GFP_NOWAIT);
+ 	if (IS_ERR(ciphertext_page)) {
+ 		err = PTR_ERR(ciphertext_page);
+ 		goto errout;
+@@ -410,11 +414,12 @@ int ext4_encrypted_zeroout(struct inode *inode, ext4_lblk_t lblk,
+ 
+ 	while (len--) {
+ 		err = ext4_page_crypto(inode, EXT4_ENCRYPT, lblk,
+-				       ZERO_PAGE(0), ciphertext_page);
++				       ZERO_PAGE(0), ciphertext_page,
++				       GFP_NOFS);
+ 		if (err)
+ 			goto errout;
+ 
+-		bio = bio_alloc(GFP_KERNEL, 1);
++		bio = bio_alloc(GFP_NOWAIT, 1);
+ 		if (!bio) {
+ 			err = -ENOMEM;
+ 			goto errout;
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index c04743519865..7e4e3e9b4494 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2282,11 +2282,13 @@ extern struct kmem_cache *ext4_crypt_info_cachep;
+ bool ext4_valid_contents_enc_mode(uint32_t mode);
+ uint32_t ext4_validate_encryption_key_size(uint32_t mode, uint32_t size);
+ extern struct workqueue_struct *ext4_read_workqueue;
+-struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode);
++struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode,
++					    gfp_t gfp_flags);
+ void ext4_release_crypto_ctx(struct ext4_crypto_ctx *ctx);
+ void ext4_restore_control_page(struct page *data_page);
+ struct page *ext4_encrypt(struct inode *inode,
+-			  struct page *plaintext_page);
++			  struct page *plaintext_page,
++			  gfp_t gfp_flags);
+ int ext4_decrypt(struct page *page);
+ int ext4_encrypted_zeroout(struct inode *inode, ext4_lblk_t lblk,
+ 			   ext4_fsblk_t pblk, ext4_lblk_t len);
+diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
+index d77d15f4b674..51b349211da7 100644
+--- a/fs/ext4/page-io.c
++++ b/fs/ext4/page-io.c
+@@ -23,6 +23,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include "ext4_jbd2.h"
+ #include "xattr.h"
+@@ -470,9 +471,20 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
+ 
+ 	if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode) &&
+ 	    nr_to_submit) {
+-		data_page = ext4_encrypt(inode, page);
++		gfp_t gfp_flags = GFP_NOFS;
++
++	retry_encrypt:
++		data_page = ext4_encrypt(inode, page, gfp_flags);
+ 		if (IS_ERR(data_page)) {
+ 			ret = PTR_ERR(data_page);
++			if (ret == ENOMEM && wbc->sync_mode == WB_SYNC_ALL) {
++				if (io->io_bio) {
++					ext4_io_submit(io);
++					congestion_wait(BLK_RW_ASYNC, HZ/50);
++				}
++				gfp_flags |= __GFP_NOFAIL;
++				goto retry_encrypt;
++			}
+ 			data_page = NULL;
+ 			goto out;
+ 		}
+diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
+index 5dc5e95063de..bc7642f57dc8 100644
+--- a/fs/ext4/readpage.c
++++ b/fs/ext4/readpage.c
+@@ -279,7 +279,7 @@ int ext4_mpage_readpages(struct address_space *mapping,
+ 
+ 			if (ext4_encrypted_inode(inode) &&
+ 			    S_ISREG(inode->i_mode)) {
+-				ctx = ext4_get_crypto_ctx(inode);
++				ctx = ext4_get_crypto_ctx(inode, GFP_NOFS);
+ 				if (IS_ERR(ctx))
+ 					goto set_error_page;
+ 			}

commit 9e92f48c34eb2b9af9d12f892e2fe1fce5e8ce35
+Author: Theodore Ts'o 
+Date:   Tue Mar 22 16:13:15 2016 -0400
+
+    ext4: check if in-inode xattr is corrupted in ext4_expand_extra_isize_ea()
+    
+    We aren't checking to see if the in-inode extended attribute is
+    corrupted before we try to expand the inode's extra isize fields.
+    
+    This can lead to potential crashes caused by the BUG_ON() check in
+    ext4_xattr_shift_entries().
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 0441e055c8e8..e79bd32b9b79 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -230,6 +230,27 @@ ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh)
+ 	return error;
+ }
+ 
++static int
++__xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header,
++			 void *end, const char *function, unsigned int line)
++{
++	struct ext4_xattr_entry *entry = IFIRST(header);
++	int error = -EFSCORRUPTED;
++
++	if (((void *) header >= end) ||
++	    (header->h_magic != le32_to_cpu(EXT4_XATTR_MAGIC)))
++		goto errout;
++	error = ext4_xattr_check_names(entry, end, entry);
++errout:
++	if (error)
++		__ext4_error_inode(inode, function, line, 0,
++				   "corrupted in-inode xattr");
++	return error;
++}
++
++#define xattr_check_inode(inode, header, end) \
++	__xattr_check_inode((inode), (header), (end), __func__, __LINE__)
++
+ static inline int
+ ext4_xattr_check_entry(struct ext4_xattr_entry *entry, size_t size)
+ {
+@@ -341,7 +362,7 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
+ 	header = IHDR(inode, raw_inode);
+ 	entry = IFIRST(header);
+ 	end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
+-	error = ext4_xattr_check_names(entry, end, entry);
++	error = xattr_check_inode(inode, header, end);
+ 	if (error)
+ 		goto cleanup;
+ 	error = ext4_xattr_find_entry(&entry, name_index, name,
+@@ -477,7 +498,7 @@ ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size)
+ 	raw_inode = ext4_raw_inode(&iloc);
+ 	header = IHDR(inode, raw_inode);
+ 	end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
+-	error = ext4_xattr_check_names(IFIRST(header), end, IFIRST(header));
++	error = xattr_check_inode(inode, header, end);
+ 	if (error)
+ 		goto cleanup;
+ 	error = ext4_xattr_list_entries(dentry, IFIRST(header),
+@@ -1040,8 +1061,7 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i,
+ 	is->s.here = is->s.first;
+ 	is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
+ 	if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) {
+-		error = ext4_xattr_check_names(IFIRST(header), is->s.end,
+-					       IFIRST(header));
++		error = xattr_check_inode(inode, header, is->s.end);
+ 		if (error)
+ 			return error;
+ 		/* Find the named attribute. */
+@@ -1356,6 +1376,10 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
+ 	last = entry;
+ 	total_ino = sizeof(struct ext4_xattr_ibody_header);
+ 
++	error = xattr_check_inode(inode, header, end);
++	if (error)
++		goto cleanup;
++
+ 	free = ext4_xattr_free_space(last, &min_offs, base, &total_ino);
+ 	if (free >= new_extra_isize) {
+ 		entry = IFIRST(header);

commit ff978b09f973db0d0597704eba350a994d7729e6
+Author: Theodore Ts'o 
+Date:   Mon Feb 8 00:54:26 2016 -0500
+
+    ext4 crypto: move context consistency check to ext4_file_open()
+    
+    In the case where the per-file key for the directory is cached, but
+    root does not have access to the key needed to derive the per-file key
+    for the files in the directory, we allow the lookup to succeed, so
+    that lstat(2) and unlink(2) can suceed.  However, if a program tries
+    to open the file, it will get an ENOKEY error.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/file.c b/fs/ext4/file.c
+index 1126436dada1..474f1a4d2ca8 100644
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -350,6 +350,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
+ 	struct super_block *sb = inode->i_sb;
+ 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+ 	struct vfsmount *mnt = filp->f_path.mnt;
++	struct inode *dir = filp->f_path.dentry->d_parent->d_inode;
+ 	struct path path;
+ 	char buf[64], *cp;
+ 	int ret;
+@@ -393,6 +394,14 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
+ 		if (ext4_encryption_info(inode) == NULL)
+ 			return -ENOKEY;
+ 	}
++	if (ext4_encrypted_inode(dir) &&
++	    !ext4_is_child_context_consistent_with_parent(dir, inode)) {
++		ext4_warning(inode->i_sb,
++			     "Inconsistent encryption contexts: %lu/%lu\n",
++			     (unsigned long) dir->i_ino,
++			     (unsigned long) inode->i_ino);
++		return -EPERM;
++	}
+ 	/*
+ 	 * Set up the jbd2_inode if we are opening the inode for
+ 	 * writing and the journal is present
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 5de8483f0062..48e4b8907826 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1603,11 +1603,15 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
+ 			return ERR_PTR(-EFSCORRUPTED);
+ 		}
+ 		if (!IS_ERR(inode) && ext4_encrypted_inode(dir) &&
+-		    (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+-		     S_ISLNK(inode->i_mode)) &&
++		    (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) &&
+ 		    !ext4_is_child_context_consistent_with_parent(dir,
+ 								  inode)) {
++			int nokey = ext4_encrypted_inode(inode) &&
++				!ext4_encryption_info(inode);
++
+ 			iput(inode);
++			if (nokey)
++				return ERR_PTR(-ENOKEY);
+ 			ext4_warning(inode->i_sb,
+ 				     "Inconsistent encryption contexts: %lu/%lu\n",
+ 				     (unsigned long) dir->i_ino,

commit 28b4c263961c47da84ed8b5be0b5116bad1133eb
+Author: Theodore Ts'o 
+Date:   Sun Feb 7 19:35:05 2016 -0500
+
+    ext4 crypto: revalidate dentry after adding or removing the key
+    
+    Add a validation check for dentries for encrypted directory to make
+    sure we're not caching stale data after a key has been added or removed.
+    
+    Also check to make sure that status of the encryption key is updated
+    when readdir(2) is executed.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
+index c8021208a7eb..38f7562489bb 100644
+--- a/fs/ext4/crypto.c
++++ b/fs/ext4/crypto.c
+@@ -467,3 +467,59 @@ uint32_t ext4_validate_encryption_key_size(uint32_t mode, uint32_t size)
+ 		return size;
+ 	return 0;
+ }
++
++/*
++ * Validate dentries for encrypted directories to make sure we aren't
++ * potentially caching stale data after a key has been added or
++ * removed.
++ */
++static int ext4_d_revalidate(struct dentry *dentry, unsigned int flags)
++{
++	struct inode *dir = d_inode(dentry->d_parent);
++	struct ext4_crypt_info *ci = EXT4_I(dir)->i_crypt_info;
++	int dir_has_key, cached_with_key;
++
++	if (!ext4_encrypted_inode(dir))
++		return 0;
++
++	if (ci && ci->ci_keyring_key &&
++	    (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) |
++					  (1 << KEY_FLAG_REVOKED) |
++					  (1 << KEY_FLAG_DEAD))))
++		ci = NULL;
++
++	/* this should eventually be an flag in d_flags */
++	cached_with_key = dentry->d_fsdata != NULL;
++	dir_has_key = (ci != NULL);
++
++	/*
++	 * If the dentry was cached without the key, and it is a
++	 * negative dentry, it might be a valid name.  We can't check
++	 * if the key has since been made available due to locking
++	 * reasons, so we fail the validation so ext4_lookup() can do
++	 * this check.
++	 *
++	 * We also fail the validation if the dentry was created with
++	 * the key present, but we no longer have the key, or vice versa.
++	 */
++	if ((!cached_with_key && d_is_negative(dentry)) ||
++	    (!cached_with_key && dir_has_key) ||
++	    (cached_with_key && !dir_has_key)) {
++#if 0				/* Revalidation debug */
++		char buf[80];
++		char *cp = simple_dname(dentry, buf, sizeof(buf));
++
++		if (IS_ERR(cp))
++			cp = (char *) "???";
++		pr_err("revalidate: %s %p %d %d %d\n", cp, dentry->d_fsdata,
++		       cached_with_key, d_is_negative(dentry),
++		       dir_has_key);
++#endif
++		return 0;
++	}
++	return 1;
++}
++
++const struct dentry_operations ext4_encrypted_d_ops = {
++	.d_revalidate = ext4_d_revalidate,
++};
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index 1d1bca74f844..6d17f31a31d7 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -111,6 +111,12 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
+ 	int dir_has_error = 0;
+ 	struct ext4_str fname_crypto_str = {.name = NULL, .len = 0};
+ 
++	if (ext4_encrypted_inode(inode)) {
++		err = ext4_get_encryption_info(inode);
++		if (err && err != -ENOKEY)
++			return err;
++	}
++
+ 	if (is_dx_dir(inode)) {
+ 		err = ext4_dx_readdir(file, ctx);
+ 		if (err != ERR_BAD_DX_DIR) {
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 0662b285dc8a..157b458a69d4 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2302,6 +2302,7 @@ struct page *ext4_encrypt(struct inode *inode,
+ int ext4_decrypt(struct page *page);
+ int ext4_encrypted_zeroout(struct inode *inode, ext4_lblk_t lblk,
+ 			   ext4_fsblk_t pblk, ext4_lblk_t len);
++extern const struct dentry_operations ext4_encrypted_d_ops;
+ 
+ #ifdef CONFIG_EXT4_FS_ENCRYPTION
+ int ext4_init_crypto(void);
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 06574dd77614..5de8483f0062 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1558,6 +1558,24 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
+ 	struct ext4_dir_entry_2 *de;
+ 	struct buffer_head *bh;
+ 
++       if (ext4_encrypted_inode(dir)) {
++               int res = ext4_get_encryption_info(dir);
++
++		/*
++		 * This should be a properly defined flag for
++		 * dentry->d_flags when we uplift this to the VFS.
++		 * d_fsdata is set to (void *) 1 if if the dentry is
++		 * created while the directory was encrypted and we
++		 * don't have access to the key.
++		 */
++	       dentry->d_fsdata = NULL;
++	       if (ext4_encryption_info(dir))
++		       dentry->d_fsdata = (void *) 1;
++	       d_set_d_op(dentry, &ext4_encrypted_d_ops);
++	       if (res && res != -ENOKEY)
++		       return ERR_PTR(res);
++       }
++
+ 	if (dentry->d_name.len > EXT4_NAME_LEN)
+ 		return ERR_PTR(-ENAMETOOLONG);
+ 

commit 68ce7bfcd995a8a393b1b14fa67dbc16fa3dc784
+Author: Theodore Ts'o 
+Date:   Fri Jan 8 16:01:25 2016 -0500
+
+    fs: clean up the flags definition in uapi/linux/fs.h
+    
+    Add an explanation for the flags used by FS_IOC_[GS]ETFLAGS and remind
+    people that changes should be revised by linux-fsdevel and linux-api.
+    
+    Add flags that are used on-disk for ext4, and remove FS_DIRECTIO_FL
+    since it was used only by gfs2 and support was removed in 2008 in
+    commit c9f6a6bbc28 ("The ability to mark files for direct i/o access
+    when opened normally is both unused and pointless, so this patch
+    removes support for that feature.")  Now we have _two_ remaining flags
+    left.  But since we want to discourage people from assigning new
+    flags, that's OK.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
+index f15d980249b5..c5083d2e2c02 100644
+--- a/include/uapi/linux/fs.h
++++ b/include/uapi/linux/fs.h
+@@ -2,8 +2,11 @@
+ #define _UAPI_LINUX_FS_H
+ 
+ /*
+- * This file has definitions for some important file table
+- * structures etc.
++ * This file has definitions for some important file table structures
++ * and constants and structures used by various generic file system
++ * ioctl's.  Please do not make any changes in this file before
++ * sending patches for review to linux-fsdevel@vger.kernel.org and
++ * linux-api@vger.kernel.org.
+  */
+ 
+ #include 
+@@ -172,6 +175,23 @@ struct inodes_stat_t {
+ 
+ /*
+  * Inode flags (FS_IOC_GETFLAGS / FS_IOC_SETFLAGS)
++ *
++ * Note: for historical reasons, these flags were originally used and
++ * defined for use by ext2/ext3, and then other file systems started
++ * using these flags so they wouldn't need to write their own version
++ * of chattr/lsattr (which was shipped as part of e2fsprogs).  You
++ * should think twice before trying to use these flags in new
++ * contexts, or trying to assign these flags, since they are used both
++ * as the UAPI and the on-disk encoding for ext2/3/4.  Also, we are
++ * almost out of 32-bit flags.  :-)
++ *
++ * We have recently hoisted FS_IOC_FSGETXATTR / FS_IOC_FSSETXATTR from
++ * XFS to the generic FS level interface.  This uses a structure that
++ * has padding and hence has more room to grow, so it may be more
++ * appropriate for many new use cases.
++ *
++ * Please do not change these flags or interfaces before checking with
++ * linux-fsdevel@vger.kernel.org and linux-api@vger.kernel.org.
+  */
+ #define	FS_SECRM_FL			0x00000001 /* Secure deletion */
+ #define	FS_UNRM_FL			0x00000002 /* Undelete */
+@@ -185,8 +205,8 @@ struct inodes_stat_t {
+ #define FS_DIRTY_FL			0x00000100
+ #define FS_COMPRBLK_FL			0x00000200 /* One or more compressed clusters */
+ #define FS_NOCOMP_FL			0x00000400 /* Don't compress */
+-#define FS_ECOMPR_FL			0x00000800 /* Compression error */
+ /* End compression flags --- maybe not all used */
++#define FS_ENCRYPT_FL			0x00000800 /* Encrypted file */
+ #define FS_BTREE_FL			0x00001000 /* btree format dir */
+ #define FS_INDEX_FL			0x00001000 /* hash-indexed directory */
+ #define FS_IMAGIC_FL			0x00002000 /* AFS directory */
+@@ -194,9 +214,12 @@ struct inodes_stat_t {
+ #define FS_NOTAIL_FL			0x00008000 /* file tail should not be merged */
+ #define FS_DIRSYNC_FL			0x00010000 /* dirsync behaviour (directories only) */
+ #define FS_TOPDIR_FL			0x00020000 /* Top of directory hierarchies*/
++#define FS_HUGE_FILE_FL			0x00040000 /* Reserved for ext4 */
+ #define FS_EXTENT_FL			0x00080000 /* Extents */
+-#define FS_DIRECTIO_FL			0x00100000 /* Use direct i/o */
++#define FS_EA_INODE_FL			0x00200000 /* Inode used for large EA */
++#define FS_EOFBLOCKS_FL			0x00400000 /* Reserved for ext4 */
+ #define FS_NOCOW_FL			0x00800000 /* Do not cow file */
++#define FS_INLINE_DATA_FL		0x10000000 /* Reserved for ext4 */
+ #define FS_PROJINHERIT_FL		0x20000000 /* Create with parents projid */
+ #define FS_RESERVED_FL			0x80000000 /* reserved for ext2 lib */
+ 

commit 56a04915df4e85b34b1c1613c64b87dd2283c26a
+Author: Theodore Ts'o 
+Date:   Fri Jan 8 16:00:31 2016 -0500
+
+    ext4 crypto: simplify interfaces to directory entry insert functions
+    
+    A number of functions include ext4_add_dx_entry, make_indexed_dir,
+    etc. are being passed a dentry even though the only thing they use is
+    the containing parent.  We can shrink the code size slightly by making
+    this replacement.  This will also be useful in cases where we don't
+    have a dentry as the argument to the directory entry insert functions.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 1e20fa94fcf6..f82da361a823 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -3004,8 +3004,7 @@ extern int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos,
+ 					 struct page *page);
+ extern int ext4_try_add_inline_entry(handle_t *handle,
+ 				     struct ext4_filename *fname,
+-				     struct dentry *dentry,
+-				     struct inode *inode);
++				     struct inode *dir, struct inode *inode);
+ extern int ext4_try_create_inline_dir(handle_t *handle,
+ 				      struct inode *parent,
+ 				      struct inode *inode);
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index d884989cc83d..dfe3b9bafc0d 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -995,12 +995,11 @@ void ext4_show_inline_dir(struct inode *dir, struct buffer_head *bh,
+  */
+ static int ext4_add_dirent_to_inline(handle_t *handle,
+ 				     struct ext4_filename *fname,
+-				     struct dentry *dentry,
++				     struct inode *dir,
+ 				     struct inode *inode,
+ 				     struct ext4_iloc *iloc,
+ 				     void *inline_start, int inline_size)
+ {
+-	struct inode	*dir = d_inode(dentry->d_parent);
+ 	int		err;
+ 	struct ext4_dir_entry_2 *de;
+ 
+@@ -1245,12 +1244,11 @@ static int ext4_convert_inline_data_nolock(handle_t *handle,
+  * the new created block.
+  */
+ int ext4_try_add_inline_entry(handle_t *handle, struct ext4_filename *fname,
+-			      struct dentry *dentry, struct inode *inode)
++			      struct inode *dir, struct inode *inode)
+ {
+ 	int ret, inline_size;
+ 	void *inline_start;
+ 	struct ext4_iloc iloc;
+-	struct inode *dir = d_inode(dentry->d_parent);
+ 
+ 	ret = ext4_get_inode_loc(dir, &iloc);
+ 	if (ret)
+@@ -1264,7 +1262,7 @@ int ext4_try_add_inline_entry(handle_t *handle, struct ext4_filename *fname,
+ 						 EXT4_INLINE_DOTDOT_SIZE;
+ 	inline_size = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DOTDOT_SIZE;
+ 
+-	ret = ext4_add_dirent_to_inline(handle, fname, dentry, inode, &iloc,
++	ret = ext4_add_dirent_to_inline(handle, fname, dir, inode, &iloc,
+ 					inline_start, inline_size);
+ 	if (ret != -ENOSPC)
+ 		goto out;
+@@ -1285,7 +1283,7 @@ int ext4_try_add_inline_entry(handle_t *handle, struct ext4_filename *fname,
+ 	if (inline_size) {
+ 		inline_start = ext4_get_inline_xattr_pos(dir, &iloc);
+ 
+-		ret = ext4_add_dirent_to_inline(handle, fname, dentry,
++		ret = ext4_add_dirent_to_inline(handle, fname, dir,
+ 						inode, &iloc, inline_start,
+ 						inline_size);
+ 
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index a969ab39f302..06c3afcbfac8 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -273,7 +273,7 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
+ 		struct ext4_filename *fname,
+ 		struct ext4_dir_entry_2 **res_dir);
+ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
+-			     struct dentry *dentry, struct inode *inode);
++			     struct inode *dir, struct inode *inode);
+ 
+ /* checksumming functions */
+ void initialize_dirent_tail(struct ext4_dir_entry_tail *t,
+@@ -1928,10 +1928,9 @@ static int add_dirent_to_buf(handle_t *handle, struct ext4_filename *fname,
+  * directory, and adds the dentry to the indexed directory.
+  */
+ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname,
+-			    struct dentry *dentry,
++			    struct inode *dir,
+ 			    struct inode *inode, struct buffer_head *bh)
+ {
+-	struct inode	*dir = d_inode(dentry->d_parent);
+ 	struct buffer_head *bh2;
+ 	struct dx_root	*root;
+ 	struct dx_frame	frames[2], *frame;
+@@ -2086,8 +2085,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
+ 		return retval;
+ 
+ 	if (ext4_has_inline_data(dir)) {
+-		retval = ext4_try_add_inline_entry(handle, &fname,
+-						   dentry, inode);
++		retval = ext4_try_add_inline_entry(handle, &fname, dir, inode);
+ 		if (retval < 0)
+ 			goto out;
+ 		if (retval == 1) {
+@@ -2097,7 +2095,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
+ 	}
+ 
+ 	if (is_dx(dir)) {
+-		retval = ext4_dx_add_entry(handle, &fname, dentry, inode);
++		retval = ext4_dx_add_entry(handle, &fname, dir, inode);
+ 		if (!retval || (retval != ERR_BAD_DX_DIR))
+ 			goto out;
+ 		ext4_clear_inode_flag(dir, EXT4_INODE_INDEX);
+@@ -2119,7 +2117,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
+ 
+ 		if (blocks == 1 && !dx_fallback &&
+ 		    ext4_has_feature_dir_index(sb)) {
+-			retval = make_indexed_dir(handle, &fname, dentry,
++			retval = make_indexed_dir(handle, &fname, dir,
+ 						  inode, bh);
+ 			bh = NULL; /* make_indexed_dir releases bh */
+ 			goto out;
+@@ -2154,12 +2152,11 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
+  * Returns 0 for success, or a negative error value
+  */
+ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
+-			     struct dentry *dentry, struct inode *inode)
++			     struct inode *dir, struct inode *inode)
+ {
+ 	struct dx_frame frames[2], *frame;
+ 	struct dx_entry *entries, *at;
+ 	struct buffer_head *bh;
+-	struct inode *dir = d_inode(dentry->d_parent);
+ 	struct super_block *sb = dir->i_sb;
+ 	struct ext4_dir_entry_2 *de;
+ 	int err;

commit db7730e3091a52c2fcd8fcc952b964d88998e675
+Author: Theodore Ts'o 
+Date:   Thu Dec 10 00:57:58 2015 -0500
+
+    ext4 crypto: add missing locking for keyring_key access
+    
+    Cc: stable@kernel.org
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/crypto_key.c b/fs/ext4/crypto_key.c
+index c5882b36e558..9a16d1e75a49 100644
+--- a/fs/ext4/crypto_key.c
++++ b/fs/ext4/crypto_key.c
+@@ -213,9 +213,11 @@ int _ext4_get_encryption_info(struct inode *inode)
+ 		res = -ENOKEY;
+ 		goto out;
+ 	}
++	down_read(&keyring_key->sem);
+ 	ukp = user_key_payload(keyring_key);
+ 	if (ukp->datalen != sizeof(struct ext4_encryption_key)) {
+ 		res = -EINVAL;
++		up_read(&keyring_key->sem);
+ 		goto out;
+ 	}
+ 	master_key = (struct ext4_encryption_key *)ukp->data;
+@@ -226,10 +228,12 @@ int _ext4_get_encryption_info(struct inode *inode)
+ 			    "ext4: key size incorrect: %d\n",
+ 			    master_key->size);
+ 		res = -ENOKEY;
++		up_read(&keyring_key->sem);
+ 		goto out;
+ 	}
+ 	res = ext4_derive_key_aes(ctx.nonce, master_key->raw,
+ 				  raw_key);
++	up_read(&keyring_key->sem);
+ 	if (res)
+ 		goto out;
+ got_key:

commit 8b4953e13f4c5d9a3c869f5fca7d51e1700e7db0
+Author: Theodore Ts'o 
+Date:   Sat Oct 17 16:15:18 2015 -0400
+
+    ext4: reserve code points for the project quota feature
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 3f248c9f899f..320f10ef4a23 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -374,6 +374,7 @@ struct flex_groups {
+ #define EXT4_EA_INODE_FL	        0x00200000 /* Inode used for large EA */
+ #define EXT4_EOFBLOCKS_FL		0x00400000 /* Blocks allocated beyond EOF */
+ #define EXT4_INLINE_DATA_FL		0x10000000 /* Inode has inline data. */
++#define EXT4_PROJINHERIT_FL		0x20000000 /* Create with parents projid */
+ #define EXT4_RESERVED_FL		0x80000000 /* reserved for ext4 lib */
+ 
+ #define EXT4_FL_USER_VISIBLE		0x004BDFFF /* User visible flags */
+@@ -431,6 +432,7 @@ enum {
+ 	EXT4_INODE_EA_INODE	= 21,	/* Inode used for large EA */
+ 	EXT4_INODE_EOFBLOCKS	= 22,	/* Blocks allocated beyond EOF */
+ 	EXT4_INODE_INLINE_DATA	= 28,	/* Data in inode. */
++	EXT4_INODE_PROJINHERIT	= 29,	/* Create with parents projid */
+ 	EXT4_INODE_RESERVED	= 31,	/* reserved for ext4 lib */
+ };
+ 
+@@ -475,6 +477,7 @@ static inline void ext4_check_flag_values(void)
+ 	CHECK_FLAG_VALUE(EA_INODE);
+ 	CHECK_FLAG_VALUE(EOFBLOCKS);
+ 	CHECK_FLAG_VALUE(INLINE_DATA);
++	CHECK_FLAG_VALUE(PROJINHERIT);
+ 	CHECK_FLAG_VALUE(RESERVED);
+ }
+ 
+@@ -692,6 +695,7 @@ struct ext4_inode {
+ 	__le32  i_crtime;       /* File Creation time */
+ 	__le32  i_crtime_extra; /* extra FileCreationtime (nsec << 2 | epoch) */
+ 	__le32  i_version_hi;	/* high 32 bits for 64-bit version */
++	__le32	i_projid;	/* Project ID */
+ };
+ 
+ struct move_extent {
+@@ -1179,7 +1183,8 @@ struct ext4_super_block {
+ 	__u8	s_encrypt_algos[4];	/* Encryption algorithms in use  */
+ 	__u8	s_encrypt_pw_salt[16];	/* Salt used for string2key algorithm */
+ 	__le32	s_lpf_ino;		/* Location of the lost+found inode */
+-	__le32	s_reserved[100];	/* Padding to the end of the block */
++	__le32	s_prj_quota_inum;	/* inode for tracking project quota */
++	__le32	s_reserved[99];		/* Padding to the end of the block */
+ 	__le32	s_checksum;		/* crc32c(superblock) */
+ };
+ 
+@@ -1566,6 +1571,7 @@ static inline int ext4_encrypted_inode(struct inode *inode)
+  */
+ #define EXT4_FEATURE_RO_COMPAT_METADATA_CSUM	0x0400
+ #define EXT4_FEATURE_RO_COMPAT_READONLY		0x1000
++#define EXT4_FEATURE_RO_COMPAT_PROJECT		0x2000
+ 
+ #define EXT4_FEATURE_INCOMPAT_COMPRESSION	0x0001
+ #define EXT4_FEATURE_INCOMPAT_FILETYPE		0x0002
+diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
+index 9b964a5920af..f15d980249b5 100644
+--- a/include/uapi/linux/fs.h
++++ b/include/uapi/linux/fs.h
+@@ -197,6 +197,7 @@ struct inodes_stat_t {
+ #define FS_EXTENT_FL			0x00080000 /* Extents */
+ #define FS_DIRECTIO_FL			0x00100000 /* Use direct i/o */
+ #define FS_NOCOW_FL			0x00800000 /* Do not cow file */
++#define FS_PROJINHERIT_FL		0x20000000 /* Create with parents projid */
+ #define FS_RESERVED_FL			0x80000000 /* reserved for ext2 lib */
+ 
+ #define FS_FL_USER_VISIBLE		0x0003DFFF /* User visible flags */

commit b90197b655185a11640cce3a0a0bc5d8291b8ad2
+Author: Theodore Ts'o 
+Date:   Thu Oct 15 10:29:05 2015 -0400
+
+    ext4: use private version of page_zero_new_buffers() for data=journal mode
+    
+    If there is a error while copying data from userspace into the page
+    cache during a write(2) system call, in data=journal mode, in
+    ext4_journalled_write_end() were using page_zero_new_buffers() from
+    fs/buffer.c.  Unfortunately, this sets the buffer dirty flag, which is
+    no good if journalling is enabled.  This is a long-standing bug that
+    goes back for years and years in ext3, but a combination of (a)
+    data=journal not being very common, (b) in many case it only results
+    in a warning message. and (c) only very rarely causes the kernel hang,
+    means that we only really noticed this as a problem when commit
+    998ef75ddb caused this failure to happen frequently enough to cause
+    generic/208 to fail when run in data=journal mode.
+    
+    The fix is to have our own version of this function that doesn't call
+    mark_dirty_buffer(), since we will end up calling
+    ext4_handle_dirty_metadata() on the buffer head(s) in questions very
+    shortly afterwards in ext4_journalled_write_end().
+    
+    Thanks to Dave Hansen and Linus Torvalds for helping to identify the
+    root cause of the problem.
+    
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index ae52e329e986..f205ac3c4e41 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1181,6 +1181,38 @@ static int ext4_write_end(struct file *file,
+ 	return ret ? ret : copied;
+ }
+ 
++/*
++ * This is a private version of page_zero_new_buffers() which doesn't
++ * set the buffer to be dirty, since in data=journalled mode we need
++ * to call ext4_handle_dirty_metadata() instead.
++ */
++static void zero_new_buffers(struct page *page, unsigned from, unsigned to)
++{
++	unsigned int block_start = 0, block_end;
++	struct buffer_head *head, *bh;
++
++	bh = head = page_buffers(page);
++	do {
++		block_end = block_start + bh->b_size;
++		if (buffer_new(bh)) {
++			if (block_end > from && block_start < to) {
++				if (!PageUptodate(page)) {
++					unsigned start, size;
++
++					start = max(from, block_start);
++					size = min(to, block_end) - start;
++
++					zero_user(page, start, size);
++					set_buffer_uptodate(bh);
++				}
++				clear_buffer_new(bh);
++			}
++		}
++		block_start = block_end;
++		bh = bh->b_this_page;
++	} while (bh != head);
++}
++
+ static int ext4_journalled_write_end(struct file *file,
+ 				     struct address_space *mapping,
+ 				     loff_t pos, unsigned len, unsigned copied,
+@@ -1207,7 +1239,7 @@ static int ext4_journalled_write_end(struct file *file,
+ 		if (copied < len) {
+ 			if (!PageUptodate(page))
+ 				copied = 0;
+-			page_zero_new_buffers(page, from+copied, to);
++			zero_new_buffers(page, from+copied, to);
+ 		}
+ 
+ 		ret = ext4_walk_page_buffers(handle, page_buffers(page), from,

commit 36086d43f6575c081067de9855786a2fc91df77b
+Author: Theodore Ts'o 
+Date:   Sat Oct 3 10:49:29 2015 -0400
+
+    ext4 crypto: fix bugs in ext4_encrypted_zeroout()
+    
+    Fix multiple bugs in ext4_encrypted_zeroout(), including one that
+    could cause us to write an encrypted zero page to the wrong location
+    on disk, potentially causing data and file system corruption.
+    Fortunately, this tends to only show up in stress tests, but even with
+    these fixes, we are seeing some test failures with generic/127 --- but
+    these are now caused by data failures instead of metadata corruption.
+    
+    Since ext4_encrypted_zeroout() is only used for some optimizations to
+    keep the extent tree from being too fragmented, and
+    ext4_encrypted_zeroout() itself isn't all that optimized from a time
+    or IOPS perspective, disable the extent tree optimization for
+    encrypted inodes for now.  This prevents the data corruption issues
+    reported by generic/127 until we can figure out what's going wrong.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
+index 879cb15b7a21..af06830bfc00 100644
+--- a/fs/ext4/crypto.c
++++ b/fs/ext4/crypto.c
+@@ -392,7 +392,13 @@ int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex)
+ 	ext4_lblk_t		lblk = ex->ee_block;
+ 	ext4_fsblk_t		pblk = ext4_ext_pblock(ex);
+ 	unsigned int		len = ext4_ext_get_actual_len(ex);
+-	int			err = 0;
++	int			ret, err = 0;
++
++#if 0
++	ext4_msg(inode->i_sb, KERN_CRIT,
++		 "ext4_encrypted_zeroout ino %lu lblk %u len %u",
++		 (unsigned long) inode->i_ino, lblk, len);
++#endif
+ 
+ 	BUG_ON(inode->i_sb->s_blocksize != PAGE_CACHE_SIZE);
+ 
+@@ -418,17 +424,26 @@ int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex)
+ 			goto errout;
+ 		}
+ 		bio->bi_bdev = inode->i_sb->s_bdev;
+-		bio->bi_iter.bi_sector = pblk;
+-		err = bio_add_page(bio, ciphertext_page,
++		bio->bi_iter.bi_sector =
++			pblk << (inode->i_sb->s_blocksize_bits - 9);
++		ret = bio_add_page(bio, ciphertext_page,
+ 				   inode->i_sb->s_blocksize, 0);
+-		if (err) {
++		if (ret != inode->i_sb->s_blocksize) {
++			/* should never happen! */
++			ext4_msg(inode->i_sb, KERN_ERR,
++				 "bio_add_page failed: %d", ret);
++			WARN_ON(1);
+ 			bio_put(bio);
++			err = -EIO;
+ 			goto errout;
+ 		}
+ 		err = submit_bio_wait(WRITE, bio);
++		if ((err == 0) && bio->bi_error)
++			err = -EIO;
+ 		bio_put(bio);
+ 		if (err)
+ 			goto errout;
++		lblk++; pblk++;
+ 	}
+ 	err = 0;
+ errout:
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 2553aa8b608d..7f486e350d15 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -3558,6 +3558,9 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 		max_zeroout = sbi->s_extent_max_zeroout_kb >>
+ 			(inode->i_sb->s_blocksize_bits - 10);
+ 
++	if (ext4_encrypted_inode(inode))
++		max_zeroout = 0;
++
+ 	/* If extent is less than s_max_zeroout_kb, zeroout directly */
+ 	if (max_zeroout && (ee_len <= max_zeroout)) {
+ 		err = ext4_ext_zeroout(inode, ex);

commit 687c3c36e754a999a8263745b27965128db4fee5
+Author: Theodore Ts'o 
+Date:   Sat Oct 3 10:49:27 2015 -0400
+
+    ext4 crypto: replace some BUG_ON()'s with error checks
+    
+    Buggy (or hostile) userspace should not be able to cause the kernel to
+    crash.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
+index 3a5a7a2597de..879cb15b7a21 100644
+--- a/fs/ext4/crypto.c
++++ b/fs/ext4/crypto.c
+@@ -295,7 +295,6 @@ static int ext4_page_crypto(struct inode *inode,
+ 	else
+ 		res = crypto_ablkcipher_encrypt(req);
+ 	if (res == -EINPROGRESS || res == -EBUSY) {
+-		BUG_ON(req->base.data != &ecr);
+ 		wait_for_completion(&ecr.completion);
+ 		res = ecr.res;
+ 	}
+diff --git a/fs/ext4/crypto_fname.c b/fs/ext4/crypto_fname.c
+index 847f919c84d9..2fbef8a14760 100644
+--- a/fs/ext4/crypto_fname.c
++++ b/fs/ext4/crypto_fname.c
+@@ -120,7 +120,6 @@ static int ext4_fname_encrypt(struct inode *inode,
+ 	ablkcipher_request_set_crypt(req, &src_sg, &dst_sg, ciphertext_len, iv);
+ 	res = crypto_ablkcipher_encrypt(req);
+ 	if (res == -EINPROGRESS || res == -EBUSY) {
+-		BUG_ON(req->base.data != &ecr);
+ 		wait_for_completion(&ecr.completion);
+ 		res = ecr.res;
+ 	}
+@@ -182,7 +181,6 @@ static int ext4_fname_decrypt(struct inode *inode,
+ 	ablkcipher_request_set_crypt(req, &src_sg, &dst_sg, iname->len, iv);
+ 	res = crypto_ablkcipher_decrypt(req);
+ 	if (res == -EINPROGRESS || res == -EBUSY) {
+-		BUG_ON(req->base.data != &ecr);
+ 		wait_for_completion(&ecr.completion);
+ 		res = ecr.res;
+ 	}
+diff --git a/fs/ext4/crypto_key.c b/fs/ext4/crypto_key.c
+index 1d510c11b100..f9270ec2a132 100644
+--- a/fs/ext4/crypto_key.c
++++ b/fs/ext4/crypto_key.c
+@@ -71,7 +71,6 @@ static int ext4_derive_key_aes(char deriving_key[EXT4_AES_128_ECB_KEY_SIZE],
+ 				     EXT4_AES_256_XTS_KEY_SIZE, NULL);
+ 	res = crypto_ablkcipher_encrypt(req);
+ 	if (res == -EINPROGRESS || res == -EBUSY) {
+-		BUG_ON(req->base.data != &ecr);
+ 		wait_for_completion(&ecr.completion);
+ 		res = ecr.res;
+ 	}
+@@ -208,7 +207,12 @@ int _ext4_get_encryption_info(struct inode *inode)
+ 		goto out;
+ 	}
+ 	crypt_info->ci_keyring_key = keyring_key;
+-	BUG_ON(keyring_key->type != &key_type_logon);
++	if (keyring_key->type != &key_type_logon) {
++		printk_once(KERN_WARNING
++			    "ext4: key type must be logon\n");
++		res = -ENOKEY;
++		goto out;
++	}
+ 	ukp = ((struct user_key_payload *)keyring_key->payload.data);
+ 	if (ukp->datalen != sizeof(struct ext4_encryption_key)) {
+ 		res = -EINVAL;
+@@ -217,7 +221,13 @@ int _ext4_get_encryption_info(struct inode *inode)
+ 	master_key = (struct ext4_encryption_key *)ukp->data;
+ 	BUILD_BUG_ON(EXT4_AES_128_ECB_KEY_SIZE !=
+ 		     EXT4_KEY_DERIVATION_NONCE_SIZE);
+-	BUG_ON(master_key->size != EXT4_AES_256_XTS_KEY_SIZE);
++	if (master_key->size != EXT4_AES_256_XTS_KEY_SIZE) {
++		printk_once(KERN_WARNING
++			    "ext4: key size incorrect: %d\n",
++			    master_key->size);
++		res = -ENOKEY;
++		goto out;
++	}
+ 	res = ext4_derive_key_aes(ctx.nonce, master_key->raw,
+ 				  raw_key);
+ 	if (res)
+diff --git a/fs/ext4/crypto_policy.c b/fs/ext4/crypto_policy.c
+index a640ec2c4b13..ad050698143f 100644
+--- a/fs/ext4/crypto_policy.c
++++ b/fs/ext4/crypto_policy.c
+@@ -150,7 +150,8 @@ int ext4_is_child_context_consistent_with_parent(struct inode *parent,
+ 
+ 	if ((parent == NULL) || (child == NULL)) {
+ 		pr_err("parent %p child %p\n", parent, child);
+-		BUG_ON(1);
++		WARN_ON(1);	/* Should never happen */
++		return 0;
+ 	}
+ 	/* no restrictions if the parent directory is not encrypted */
+ 	if (!ext4_encrypted_inode(parent))

commit 3684de8ca2b82180f2cdcf5fbcfd3d29ef0afaf8
+Author: Theodore Ts'o 
+Date:   Sat Oct 3 10:49:26 2015 -0400
+
+    ext4 crypto: ext4_page_crypto() doesn't need a encryption context
+    
+    Since ext4_page_crypto() doesn't need an encryption context (at least
+    not any more), this allows us to simplify a number function signature
+    and also allows us to avoid needing to allocate a context in
+    ext4_block_write_begin().  It also means we no longer need a separate
+    ext4_decrypt_one() function.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
+index 45731558138c..3a5a7a2597de 100644
+--- a/fs/ext4/crypto.c
++++ b/fs/ext4/crypto.c
+@@ -253,8 +253,7 @@ typedef enum {
+ 	EXT4_ENCRYPT,
+ } ext4_direction_t;
+ 
+-static int ext4_page_crypto(struct ext4_crypto_ctx *ctx,
+-			    struct inode *inode,
++static int ext4_page_crypto(struct inode *inode,
+ 			    ext4_direction_t rw,
+ 			    pgoff_t index,
+ 			    struct page *src_page,
+@@ -353,7 +352,7 @@ struct page *ext4_encrypt(struct inode *inode,
+ 	if (IS_ERR(ciphertext_page))
+ 		goto errout;
+ 	ctx->w.control_page = plaintext_page;
+-	err = ext4_page_crypto(ctx, inode, EXT4_ENCRYPT, plaintext_page->index,
++	err = ext4_page_crypto(inode, EXT4_ENCRYPT, plaintext_page->index,
+ 			       plaintext_page, ciphertext_page);
+ 	if (err) {
+ 		ciphertext_page = ERR_PTR(err);
+@@ -378,31 +377,14 @@ struct page *ext4_encrypt(struct inode *inode,
+  *
+  * Return: Zero on success, non-zero otherwise.
+  */
+-int ext4_decrypt(struct ext4_crypto_ctx *ctx, struct page *page)
++int ext4_decrypt(struct page *page)
+ {
+ 	BUG_ON(!PageLocked(page));
+ 
+-	return ext4_page_crypto(ctx, page->mapping->host,
++	return ext4_page_crypto(page->mapping->host,
+ 				EXT4_DECRYPT, page->index, page, page);
+ }
+ 
+-/*
+- * Convenience function which takes care of allocating and
+- * deallocating the encryption context
+- */
+-int ext4_decrypt_one(struct inode *inode, struct page *page)
+-{
+-	int ret;
+-
+-	struct ext4_crypto_ctx *ctx = ext4_get_crypto_ctx(inode);
+-
+-	if (IS_ERR(ctx))
+-		return PTR_ERR(ctx);
+-	ret = ext4_decrypt(ctx, page);
+-	ext4_release_crypto_ctx(ctx);
+-	return ret;
+-}
+-
+ int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex)
+ {
+ 	struct ext4_crypto_ctx	*ctx;
+@@ -426,7 +408,7 @@ int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex)
+ 	}
+ 
+ 	while (len--) {
+-		err = ext4_page_crypto(ctx, inode, EXT4_ENCRYPT, lblk,
++		err = ext4_page_crypto(inode, EXT4_ENCRYPT, lblk,
+ 				       ZERO_PAGE(0), ciphertext_page);
+ 		if (err)
+ 			goto errout;
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 766b7f7b782b..3f248c9f899f 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2063,8 +2063,7 @@ void ext4_release_crypto_ctx(struct ext4_crypto_ctx *ctx);
+ void ext4_restore_control_page(struct page *data_page);
+ struct page *ext4_encrypt(struct inode *inode,
+ 			  struct page *plaintext_page);
+-int ext4_decrypt(struct ext4_crypto_ctx *ctx, struct page *page);
+-int ext4_decrypt_one(struct inode *inode, struct page *page);
++int ext4_decrypt(struct page *page);
+ int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex);
+ 
+ #ifdef CONFIG_EXT4_FS_ENCRYPTION
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index c95d40658979..ae52e329e986 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -965,7 +965,7 @@ static int ext4_block_write_begin(struct page *page, loff_t pos, unsigned len,
+ 	if (unlikely(err))
+ 		page_zero_new_buffers(page, from, to);
+ 	else if (decrypt)
+-		err = ext4_decrypt_one(inode, page);
++		err = ext4_decrypt(page);
+ 	return err;
+ }
+ #endif
+@@ -3404,7 +3404,7 @@ static int __ext4_block_zero_page_range(handle_t *handle,
+ 			/* We expect the key to be set. */
+ 			BUG_ON(!ext4_has_encryption_key(inode));
+ 			BUG_ON(blocksize != PAGE_CACHE_SIZE);
+-			WARN_ON_ONCE(ext4_decrypt_one(inode, page));
++			WARN_ON_ONCE(ext4_decrypt(page));
+ 		}
+ 	}
+ 	if (ext4_should_journal_data(inode)) {
+diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
+index e26803fb210d..a91e4bf6ebc4 100644
+--- a/fs/ext4/readpage.c
++++ b/fs/ext4/readpage.c
+@@ -62,7 +62,7 @@ static void completion_pages(struct work_struct *work)
+ 	bio_for_each_segment_all(bv, bio, i) {
+ 		struct page *page = bv->bv_page;
+ 
+-		int ret = ext4_decrypt(ctx, page);
++		int ret = ext4_decrypt(page);
+ 		if (ret) {
+ 			WARN_ON_ONCE(1);
+ 			SetPageError(page);

commit cccd147a57e47527ce9c27fcd5f0a1c5669d6870
+Author: Theodore Ts'o 
+Date:   Sat Oct 3 10:49:23 2015 -0400
+
+    ext4: optimize ext4_writepage() for attempted 4k delalloc writes
+    
+    In cases where the file system block size is the same as the page
+    size, and ext4_writepage() is asked to write out a page which is
+    either has the unwritten bit set in the extent tree, or which does not
+    yet have a block assigned due to delayed allocation, we can bail out
+    early and, unlocking the page earlier and avoiding a round trip
+    through ext4_bio_write_page() with the attendant calls to
+    set_page_writeback() and redirty_page_for_writeback().
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 612fbcf76b5c..c95d40658979 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1815,11 +1815,22 @@ static int ext4_writepage(struct page *page,
+ 	 * the page. But we may reach here when we do a journal commit via
+ 	 * journal_submit_inode_data_buffers() and in that case we must write
+ 	 * allocated buffers to achieve data=ordered mode guarantees.
++	 *
++	 * Also, if there is only one buffer per page (the fs block
++	 * size == the page size), if one buffer needs block
++	 * allocation or needs to modify the extent tree to clear the
++	 * unwritten flag, we know that the page can't be written at
++	 * all, so we might as well refuse the write immediately.
++	 * Unfortunately if the block size != page size, we can't as
++	 * easily detect this case using ext4_walk_page_buffers(), but
++	 * for the extremely common case, this is an optimization that
++	 * skips a useless round trip through ext4_bio_write_page().
+ 	 */
+ 	if (ext4_walk_page_buffers(NULL, page_bufs, 0, len, NULL,
+ 				   ext4_bh_delay_or_unwritten)) {
+ 		redirty_page_for_writepage(wbc, page);
+-		if (current->flags & PF_MEMALLOC) {
++		if ((current->flags & PF_MEMALLOC) ||
++		    (inode->i_sb->s_blocksize == PAGE_CACHE_SIZE)) {
+ 			/*
+ 			 * For memory cleaning there's no point in writing only
+ 			 * some buffers. So just bail out. Warn if we came here

commit 937d7b84dca58f2565715f2c8e52f14c3d65fb22
+Author: Theodore Ts'o 
+Date:   Fri Oct 2 23:54:58 2015 -0400
+
+    ext4 crypto: fix memory leak in ext4_bio_write_page()
+    
+    There are times when ext4_bio_write_page() is called even though we
+    don't actually need to do any I/O.  This happens when ext4_writepage()
+    gets called by the jbd2 commit path when an inode needs to force its
+    pages written out in order to provide data=ordered guarantees --- and
+    a page is backed by an unwritten (e.g., uninitialized) block on disk,
+    or if delayed allocation means the page's backing store hasn't been
+    allocated yet.  In that case, we need to skip the call to
+    ext4_encrypt_page(), since in addition to wasting CPU, it leads to a
+    bounce page and an ext4 crypto context getting leaked.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
+index 84ba4d2b3a35..17fbe3882b8e 100644
+--- a/fs/ext4/page-io.c
++++ b/fs/ext4/page-io.c
+@@ -425,6 +425,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
+ 	struct buffer_head *bh, *head;
+ 	int ret = 0;
+ 	int nr_submitted = 0;
++	int nr_to_submit = 0;
+ 
+ 	blocksize = 1 << inode->i_blkbits;
+ 
+@@ -477,11 +478,13 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
+ 			unmap_underlying_metadata(bh->b_bdev, bh->b_blocknr);
+ 		}
+ 		set_buffer_async_write(bh);
++		nr_to_submit++;
+ 	} while ((bh = bh->b_this_page) != head);
+ 
+ 	bh = head = page_buffers(page);
+ 
+-	if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode)) {
++	if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode) &&
++	    nr_to_submit) {
+ 		data_page = ext4_encrypt(inode, page);
+ 		if (IS_ERR(data_page)) {
+ 			ret = PTR_ERR(data_page);

commit ebd173beb8db5b8b315fa1c5bbac86c54059397a
+Author: Theodore Ts'o 
+Date:   Wed Sep 23 12:46:17 2015 -0400
+
+    ext4: move procfs registration code to fs/ext4/sysfs.c
+    
+    This allows us to refactor the procfs code, which saves a bit of
+    compiled space.  More importantly it isolates most of the procfs
+    support code into a single file, so it's easier to #ifdef it out if
+    the proc file system has been disabled.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 76daccf38aa3..766b7f7b782b 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2245,6 +2245,7 @@ extern int ext4_init_inode_table(struct super_block *sb,
+ extern void ext4_end_bitmap_read(struct buffer_head *bh, int uptodate);
+ 
+ /* mballoc.c */
++extern const struct file_operations ext4_seq_mb_groups_fops;
+ extern long ext4_mb_stats;
+ extern long ext4_mb_max_to_scan;
+ extern int ext4_mb_init(struct super_block *);
+@@ -2372,6 +2373,7 @@ extern int ext4_group_extend(struct super_block *sb,
+ extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count);
+ 
+ /* super.c */
++extern int ext4_seq_options_show(struct seq_file *seq, void *offset);
+ extern int ext4_calculate_overhead(struct super_block *sb);
+ extern void ext4_superblock_csum_set(struct super_block *sb);
+ extern void *ext4_kvmalloc(size_t size, gfp_t flags);
+@@ -2905,6 +2907,7 @@ extern const struct inode_operations ext4_fast_symlink_inode_operations;
+ 
+ /* sysfs.c */
+ extern int ext4_register_sysfs(struct super_block *sb);
++extern void ext4_unregister_sysfs(struct super_block *sb);
+ extern int __init ext4_init_sysfs(void);
+ extern void ext4_exit_sysfs(void);
+ 
+diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
+index 26724aeece73..ac748b3af1c1 100644
+--- a/fs/ext4/extents_status.c
++++ b/fs/ext4/extents_status.c
+@@ -1089,20 +1089,9 @@ static unsigned long ext4_es_scan(struct shrinker *shrink,
+ 	return nr_shrunk;
+ }
+ 
+-static void *ext4_es_seq_shrinker_info_start(struct seq_file *seq, loff_t *pos)
++int ext4_seq_es_shrinker_info_show(struct seq_file *seq, void *v)
+ {
+-	return *pos ? NULL : SEQ_START_TOKEN;
+-}
+-
+-static void *
+-ext4_es_seq_shrinker_info_next(struct seq_file *seq, void *v, loff_t *pos)
+-{
+-	return NULL;
+-}
+-
+-static int ext4_es_seq_shrinker_info_show(struct seq_file *seq, void *v)
+-{
+-	struct ext4_sb_info *sbi = seq->private;
++	struct ext4_sb_info *sbi = EXT4_SB((struct super_block *) seq->private);
+ 	struct ext4_es_stats *es_stats = &sbi->s_es_stats;
+ 	struct ext4_inode_info *ei, *max = NULL;
+ 	unsigned int inode_cnt = 0;
+@@ -1143,45 +1132,6 @@ static int ext4_es_seq_shrinker_info_show(struct seq_file *seq, void *v)
+ 	return 0;
+ }
+ 
+-static void ext4_es_seq_shrinker_info_stop(struct seq_file *seq, void *v)
+-{
+-}
+-
+-static const struct seq_operations ext4_es_seq_shrinker_info_ops = {
+-	.start = ext4_es_seq_shrinker_info_start,
+-	.next  = ext4_es_seq_shrinker_info_next,
+-	.stop  = ext4_es_seq_shrinker_info_stop,
+-	.show  = ext4_es_seq_shrinker_info_show,
+-};
+-
+-static int
+-ext4_es_seq_shrinker_info_open(struct inode *inode, struct file *file)
+-{
+-	int ret;
+-
+-	ret = seq_open(file, &ext4_es_seq_shrinker_info_ops);
+-	if (!ret) {
+-		struct seq_file *m = file->private_data;
+-		m->private = PDE_DATA(inode);
+-	}
+-
+-	return ret;
+-}
+-
+-static int
+-ext4_es_seq_shrinker_info_release(struct inode *inode, struct file *file)
+-{
+-	return seq_release(inode, file);
+-}
+-
+-static const struct file_operations ext4_es_seq_shrinker_info_fops = {
+-	.owner		= THIS_MODULE,
+-	.open		= ext4_es_seq_shrinker_info_open,
+-	.read		= seq_read,
+-	.llseek		= seq_lseek,
+-	.release	= ext4_es_seq_shrinker_info_release,
+-};
+-
+ int ext4_es_register_shrinker(struct ext4_sb_info *sbi)
+ {
+ 	int err;
+@@ -1210,10 +1160,6 @@ int ext4_es_register_shrinker(struct ext4_sb_info *sbi)
+ 	if (err)
+ 		goto err2;
+ 
+-	if (sbi->s_proc)
+-		proc_create_data("es_shrinker_info", S_IRUGO, sbi->s_proc,
+-				 &ext4_es_seq_shrinker_info_fops, sbi);
+-
+ 	return 0;
+ 
+ err2:
+@@ -1225,8 +1171,6 @@ int ext4_es_register_shrinker(struct ext4_sb_info *sbi)
+ 
+ void ext4_es_unregister_shrinker(struct ext4_sb_info *sbi)
+ {
+-	if (sbi->s_proc)
+-		remove_proc_entry("es_shrinker_info", sbi->s_proc);
+ 	percpu_counter_destroy(&sbi->s_es_stats.es_stats_all_cnt);
+ 	percpu_counter_destroy(&sbi->s_es_stats.es_stats_shk_cnt);
+ 	unregister_shrinker(&sbi->s_es_shrinker);
+diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h
+index 691b52613ce4..f7aa24f4642d 100644
+--- a/fs/ext4/extents_status.h
++++ b/fs/ext4/extents_status.h
+@@ -172,4 +172,6 @@ static inline void ext4_es_store_pblock_status(struct extent_status *es,
+ extern int ext4_es_register_shrinker(struct ext4_sb_info *sbi);
+ extern void ext4_es_unregister_shrinker(struct ext4_sb_info *sbi);
+ 
++extern int ext4_seq_es_shrinker_info_show(struct seq_file *seq, void *v);
++
+ #endif /* _EXT4_EXTENTS_STATUS_H */
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 34b610ea5030..b0f7ee57630b 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2333,7 +2333,7 @@ static int ext4_mb_seq_groups_open(struct inode *inode, struct file *file)
+ 
+ }
+ 
+-static const struct file_operations ext4_mb_seq_groups_fops = {
++const struct file_operations ext4_seq_mb_groups_fops = {
+ 	.owner		= THIS_MODULE,
+ 	.open		= ext4_mb_seq_groups_open,
+ 	.read		= seq_read,
+@@ -2661,10 +2661,6 @@ int ext4_mb_init(struct super_block *sb)
+ 	if (ret != 0)
+ 		goto out_free_locality_groups;
+ 
+-	if (sbi->s_proc)
+-		proc_create_data("mb_groups", S_IRUGO, sbi->s_proc,
+-				 &ext4_mb_seq_groups_fops, sb);
+-
+ 	return 0;
+ 
+ out_free_locality_groups:
+@@ -2705,9 +2701,6 @@ int ext4_mb_release(struct super_block *sb)
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	struct kmem_cache *cachep = get_groupinfo_cache(sb->s_blocksize_bits);
+ 
+-	if (sbi->s_proc)
+-		remove_proc_entry("mb_groups", sbi->s_proc);
+-
+ 	if (sbi->s_group_info) {
+ 		for (i = 0; i < ngroups; i++) {
+ 			grinfo = ext4_get_group_info(sb, i);
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 4a574fbeffec..7ef3fa58d3fe 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -34,7 +34,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ #include 
+ #include 
+ #include 
+@@ -54,7 +53,6 @@
+ #define CREATE_TRACE_POINTS
+ #include 
+ 
+-static struct proc_dir_entry *ext4_proc_root;
+ static struct ext4_lazy_init *ext4_li_info;
+ static struct mutex ext4_li_mtx;
+ static int ext4_mballoc_ready;
+@@ -797,6 +795,7 @@ static void ext4_put_super(struct super_block *sb)
+ 			ext4_abort(sb, "Couldn't clean up the journal");
+ 	}
+ 
++	ext4_unregister_sysfs(sb);
+ 	ext4_es_unregister_shrinker(sbi);
+ 	del_timer_sync(&sbi->s_err_report);
+ 	ext4_release_system_zone(sb);
+@@ -811,12 +810,6 @@ static void ext4_put_super(struct super_block *sb)
+ 	if (!(sb->s_flags & MS_RDONLY))
+ 		ext4_commit_super(sb, 1);
+ 
+-	if (sbi->s_proc) {
+-		remove_proc_entry("options", sbi->s_proc);
+-		remove_proc_entry(sb->s_id, ext4_proc_root);
+-	}
+-	kobject_del(&sbi->s_kobj);
+-
+ 	for (i = 0; i < sbi->s_gdb_count; i++)
+ 		brelse(sbi->s_group_desc[i]);
+ 	kvfree(sbi->s_group_desc);
+@@ -1877,7 +1870,7 @@ static int ext4_show_options(struct seq_file *seq, struct dentry *root)
+ 	return _ext4_show_options(seq, root->d_sb, 0);
+ }
+ 
+-static int options_seq_show(struct seq_file *seq, void *offset)
++int ext4_seq_options_show(struct seq_file *seq, void *offset)
+ {
+ 	struct super_block *sb = seq->private;
+ 	int rc;
+@@ -1888,19 +1881,6 @@ static int options_seq_show(struct seq_file *seq, void *offset)
+ 	return rc;
+ }
+ 
+-static int options_open_fs(struct inode *inode, struct file *file)
+-{
+-	return single_open(file, options_seq_show, PDE_DATA(inode));
+-}
+-
+-static const struct file_operations ext4_seq_options_fops = {
+-	.owner = THIS_MODULE,
+-	.open = options_open_fs,
+-	.read = seq_read,
+-	.llseek = seq_lseek,
+-	.release = single_release,
+-};
+-
+ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
+ 			    int read_only)
+ {
+@@ -3616,13 +3596,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		goto failed_mount;
+ 	}
+ 
+-	if (ext4_proc_root)
+-		sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root);
+-
+-	if (sbi->s_proc)
+-		proc_create_data("options", S_IRUGO, sbi->s_proc,
+-				 &ext4_seq_options_fops, sb);
+-
+ 	bgl_lock_init(sbi->s_blockgroup_lock);
+ 
+ 	for (i = 0; i < db_count; i++) {
+@@ -3960,7 +3933,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 
+ #ifdef CONFIG_QUOTA
+ failed_mount8:
+-	kobject_del(&sbi->s_kobj);
++	ext4_unregister_sysfs(sb);
+ #endif
+ failed_mount7:
+ 	ext4_unregister_li_request(sb);
+@@ -4000,10 +3973,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ failed_mount:
+ 	if (sbi->s_chksum_driver)
+ 		crypto_free_shash(sbi->s_chksum_driver);
+-	if (sbi->s_proc) {
+-		remove_proc_entry("options", sbi->s_proc);
+-		remove_proc_entry(sb->s_id, ext4_proc_root);
+-	}
+ #ifdef CONFIG_QUOTA
+ 	for (i = 0; i < EXT4_MAXQUOTAS; i++)
+ 		kfree(sbi->s_qf_names[i]);
+@@ -5264,7 +5233,6 @@ static int __init ext4_init_fs(void)
+ 	err = ext4_init_system_zone();
+ 	if (err)
+ 		goto out4;
+-	ext4_proc_root = proc_mkdir("fs/ext4", NULL);
+ 
+ 	err = ext4_init_sysfs();
+ 	if (err)
+@@ -5295,8 +5263,6 @@ static int __init ext4_init_fs(void)
+ out2:
+ 	ext4_exit_sysfs();
+ out3:
+-	if (ext4_proc_root)
+-		remove_proc_entry("fs/ext4", NULL);
+ 	ext4_exit_system_zone();
+ out4:
+ 	ext4_exit_pageio();
+@@ -5316,7 +5282,6 @@ static void __exit ext4_exit_fs(void)
+ 	destroy_inodecache();
+ 	ext4_exit_mballoc();
+ 	ext4_exit_sysfs();
+-	remove_proc_entry("fs/ext4", NULL);
+ 	ext4_exit_system_zone();
+ 	ext4_exit_pageio();
+ 	ext4_exit_es();
+diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c
+index 87ac08964683..62bef0f06421 100644
+--- a/fs/ext4/sysfs.c
++++ b/fs/ext4/sysfs.c
+@@ -34,6 +34,9 @@ typedef enum {
+ 	ptr_ext4_super_block_offset,
+ } attr_ptr_t;
+ 
++static const char *proc_dirname = "fs/ext4";
++static struct proc_dir_entry *ext4_proc_root;
++
+ struct ext4_attr {
+ 	struct attribute attr;
+ 	short attr_id;
+@@ -347,14 +350,71 @@ static struct kobject ext4_feat = {
+ 	.kset	= &ext4_kset,
+ };
+ 
++#define PROC_FILE_SHOW_DEFN(name) \
++static int name##_open(struct inode *inode, struct file *file) \
++{ \
++	return single_open(file, ext4_seq_##name##_show, PDE_DATA(inode)); \
++} \
++\
++const struct file_operations ext4_seq_##name##_fops = { \
++	.owner		= THIS_MODULE, \
++	.open		= name##_open, \
++	.read		= seq_read, \
++	.llseek		= seq_lseek, \
++	.release	= single_release, \
++}
++
++#define PROC_FILE_LIST(name) \
++	{ __stringify(name), &ext4_seq_##name##_fops }
++
++PROC_FILE_SHOW_DEFN(es_shrinker_info);
++PROC_FILE_SHOW_DEFN(options);
++
++static struct ext4_proc_files {
++	const char *name;
++	const struct file_operations *fops;
++} proc_files[] = {
++	PROC_FILE_LIST(options),
++	PROC_FILE_LIST(es_shrinker_info),
++	PROC_FILE_LIST(mb_groups),
++	{ NULL, NULL },
++};
++
+ int ext4_register_sysfs(struct super_block *sb)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
++	struct ext4_proc_files *p;
++	int err;
+ 
+ 	sbi->s_kobj.kset = &ext4_kset;
+ 	init_completion(&sbi->s_kobj_unregister);
+-	return kobject_init_and_add(&sbi->s_kobj, &ext4_sb_ktype, NULL,
+-				    "%s", sb->s_id);
++	err = kobject_init_and_add(&sbi->s_kobj, &ext4_sb_ktype, NULL,
++				   "%s", sb->s_id);
++	if (err)
++		return err;
++
++	if (ext4_proc_root)
++		sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root);
++
++	if (sbi->s_proc) {
++		for (p = proc_files; p->name; p++)
++			proc_create_data(p->name, S_IRUGO, sbi->s_proc,
++					 p->fops, sb);
++	}
++	return 0;
++}
++
++void ext4_unregister_sysfs(struct super_block *sb)
++{
++	struct ext4_sb_info *sbi = EXT4_SB(sb);
++	struct ext4_proc_files *p;
++
++	if (sbi->s_proc) {
++		for (p = proc_files; p->name; p++)
++			remove_proc_entry(p->name, sbi->s_proc);
++		remove_proc_entry(sb->s_id, ext4_proc_root);
++	}
++	kobject_del(&sbi->s_kobj);
+ }
+ 
+ int __init ext4_init_sysfs(void)
+@@ -371,6 +431,8 @@ int __init ext4_init_sysfs(void)
+ 				   NULL, "features");
+ 	if (ret)
+ 		kset_unregister(&ext4_kset);
++	else
++		ext4_proc_root = proc_mkdir(proc_dirname, NULL);
+ 	return ret;
+ }
+ 
+@@ -378,5 +440,7 @@ void ext4_exit_sysfs(void)
+ {
+ 	kobject_put(&ext4_feat);
+ 	kset_unregister(&ext4_kset);
++	remove_proc_entry(proc_dirname, NULL);
++	ext4_proc_root = NULL;
+ }
+ 

commit 76d33bca5581b1dd5c3157fa168db849a784ada4
+Author: Theodore Ts'o 
+Date:   Wed Sep 23 12:45:17 2015 -0400
+
+    ext4: refactor sysfs support code
+    
+    Make the code more easily extensible as well as taking up less
+    compiled space.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c
+index 9fdc21b9b265..87ac08964683 100644
+--- a/fs/ext4/sysfs.c
++++ b/fs/ext4/sysfs.c
+@@ -15,37 +15,35 @@
+ #include "ext4.h"
+ #include "ext4_jbd2.h"
+ 
++typedef enum {
++	attr_noop,
++	attr_delayed_allocation_blocks,
++	attr_session_write_kbytes,
++	attr_lifetime_write_kbytes,
++	attr_reserved_clusters,
++	attr_inode_readahead,
++	attr_trigger_test_error,
++	attr_feature,
++	attr_pointer_ui,
++	attr_pointer_atomic,
++} attr_id_t;
++
++typedef enum {
++	ptr_explicit,
++	ptr_ext4_sb_info_offset,
++	ptr_ext4_super_block_offset,
++} attr_ptr_t;
++
+ struct ext4_attr {
+ 	struct attribute attr;
+-	ssize_t (*show)(struct ext4_attr *, struct ext4_sb_info *, char *);
+-	ssize_t (*store)(struct ext4_attr *, struct ext4_sb_info *,
+-			 const char *, size_t);
++	short attr_id;
++	short attr_ptr;
+ 	union {
+ 		int offset;
+-		int deprecated_val;
++		void *explicit_ptr;
+ 	} u;
+ };
+ 
+-static int parse_strtoull(const char *buf,
+-		unsigned long long max, unsigned long long *value)
+-{
+-	int ret;
+-
+-	ret = kstrtoull(skip_spaces(buf), 0, value);
+-	if (!ret && *value > max)
+-		ret = -EINVAL;
+-	return ret;
+-}
+-
+-static ssize_t delayed_allocation_blocks_show(struct ext4_attr *a,
+-					      struct ext4_sb_info *sbi,
+-					      char *buf)
+-{
+-	return snprintf(buf, PAGE_SIZE, "%llu\n",
+-		(s64) EXT4_C2B(sbi,
+-			percpu_counter_sum(&sbi->s_dirtyclusters_counter)));
+-}
+-
+ static ssize_t session_write_kbytes_show(struct ext4_attr *a,
+ 					 struct ext4_sb_info *sbi, char *buf)
+ {
+@@ -89,46 +87,6 @@ static ssize_t inode_readahead_blks_store(struct ext4_attr *a,
+ 	return count;
+ }
+ 
+-static ssize_t sbi_ui_show(struct ext4_attr *a,
+-			   struct ext4_sb_info *sbi, char *buf)
+-{
+-	unsigned int *ui = (unsigned int *) (((char *) sbi) + a->u.offset);
+-
+-	return snprintf(buf, PAGE_SIZE, "%u\n", *ui);
+-}
+-
+-static ssize_t sbi_ui_store(struct ext4_attr *a,
+-			    struct ext4_sb_info *sbi,
+-			    const char *buf, size_t count)
+-{
+-	unsigned int *ui = (unsigned int *) (((char *) sbi) + a->u.offset);
+-	unsigned long t;
+-	int ret;
+-
+-	ret = kstrtoul(skip_spaces(buf), 0, &t);
+-	if (ret)
+-		return ret;
+-	*ui = t;
+-	return count;
+-}
+-
+-static ssize_t es_ui_show(struct ext4_attr *a,
+-			   struct ext4_sb_info *sbi, char *buf)
+-{
+-
+-	unsigned int *ui = (unsigned int *) (((char *) sbi->s_es) +
+-			   a->u.offset);
+-
+-	return snprintf(buf, PAGE_SIZE, "%u\n", *ui);
+-}
+-
+-static ssize_t reserved_clusters_show(struct ext4_attr *a,
+-				  struct ext4_sb_info *sbi, char *buf)
+-{
+-	return snprintf(buf, PAGE_SIZE, "%llu\n",
+-		(unsigned long long) atomic64_read(&sbi->s_resv_clusters));
+-}
+-
+ static ssize_t reserved_clusters_store(struct ext4_attr *a,
+ 				   struct ext4_sb_info *sbi,
+ 				   const char *buf, size_t count)
+@@ -136,11 +94,10 @@ static ssize_t reserved_clusters_store(struct ext4_attr *a,
+ 	unsigned long long val;
+ 	ext4_fsblk_t clusters = (ext4_blocks_count(sbi->s_es) >>
+ 				 sbi->s_cluster_bits);
++	int ret;
+ 
+-	if (parse_strtoull(buf, -1ULL, &val))
+-		return -EINVAL;
+-
+-	if (val >= clusters)
++	ret = kstrtoull(skip_spaces(buf), 0, &val);
++	if (!ret || val >= clusters)
+ 		return -EINVAL;
+ 
+ 	atomic64_set(&sbi->s_resv_clusters, val);
+@@ -164,60 +121,51 @@ static ssize_t trigger_test_error(struct ext4_attr *a,
+ 	return count;
+ }
+ 
+-static ssize_t sbi_deprecated_show(struct ext4_attr *a,
+-				   struct ext4_sb_info *sbi, char *buf)
+-{
+-	return snprintf(buf, PAGE_SIZE, "%d\n", a->u.deprecated_val);
++#define EXT4_ATTR(_name,_mode,_id)					\
++static struct ext4_attr ext4_attr_##_name = {				\
++	.attr = {.name = __stringify(_name), .mode = _mode },		\
++	.attr_id = attr_##_id,						\
+ }
+ 
+-#define EXT4_ATTR_OFFSET(_name,_mode,_show,_store,_elname) \
++#define EXT4_ATTR_FUNC(_name,_mode)  EXT4_ATTR(_name,_mode,_name)
++
++#define EXT4_ATTR_FEATURE(_name)   EXT4_ATTR(_name, 0444, feature)
++
++#define EXT4_ATTR_OFFSET(_name,_mode,_id,_struct,_elname)	\
+ static struct ext4_attr ext4_attr_##_name = {			\
+ 	.attr = {.name = __stringify(_name), .mode = _mode },	\
+-	.show	= _show,					\
+-	.store	= _store,					\
++	.attr_id = attr_##_id,					\
++	.attr_ptr = ptr_##_struct##_offset,			\
+ 	.u = {							\
+-		.offset = offsetof(struct ext4_sb_info, _elname),\
++		.offset = offsetof(struct _struct, _elname),\
+ 	},							\
+ }
+ 
+-#define EXT4_ATTR_OFFSET_ES(_name,_mode,_show,_store,_elname)		\
+-static struct ext4_attr ext4_attr_##_name = {				\
+-	.attr = {.name = __stringify(_name), .mode = _mode },		\
+-	.show	= _show,						\
+-	.store	= _store,						\
+-	.u = {								\
+-		.offset = offsetof(struct ext4_super_block, _elname),	\
+-	},								\
+-}
+-
+-#define EXT4_ATTR(name, mode, show, store) \
+-static struct ext4_attr ext4_attr_##name = __ATTR(name, mode, show, store)
+-
+-#define EXT4_INFO_ATTR(name) EXT4_ATTR(name, 0444, NULL, NULL)
+-#define EXT4_RO_ATTR(name) EXT4_ATTR(name, 0444, name##_show, NULL)
+-#define EXT4_RW_ATTR(name) EXT4_ATTR(name, 0644, name##_show, name##_store)
++#define EXT4_RO_ATTR_ES_UI(_name,_elname)				\
++	EXT4_ATTR_OFFSET(_name, 0444, pointer_ui, ext4_super_block, _elname)
+ 
+-#define EXT4_RO_ATTR_ES_UI(name, elname)	\
+-	EXT4_ATTR_OFFSET_ES(name, 0444, es_ui_show, NULL, elname)
+-#define EXT4_RW_ATTR_SBI_UI(name, elname)	\
+-	EXT4_ATTR_OFFSET(name, 0644, sbi_ui_show, sbi_ui_store, elname)
++#define EXT4_RW_ATTR_SBI_UI(_name,_elname)	\
++	EXT4_ATTR_OFFSET(_name, 0644, pointer_ui, ext4_sb_info, _elname)
+ 
+-#define ATTR_LIST(name) &ext4_attr_##name.attr
+-#define EXT4_DEPRECATED_ATTR(_name, _val)	\
++#define EXT4_ATTR_PTR(_name,_mode,_id,_ptr) \
+ static struct ext4_attr ext4_attr_##_name = {			\
+-	.attr = {.name = __stringify(_name), .mode = 0444 },	\
+-	.show	= sbi_deprecated_show,				\
++	.attr = {.name = __stringify(_name), .mode = _mode },	\
++	.attr_id = attr_##_id,					\
++	.attr_ptr = ptr_explicit,				\
+ 	.u = {							\
+-		.deprecated_val = _val,				\
++		.explicit_ptr = _ptr,				\
+ 	},							\
+ }
+ 
+-EXT4_RO_ATTR(delayed_allocation_blocks);
+-EXT4_RO_ATTR(session_write_kbytes);
+-EXT4_RO_ATTR(lifetime_write_kbytes);
+-EXT4_RW_ATTR(reserved_clusters);
+-EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show,
+-		 inode_readahead_blks_store, s_inode_readahead_blks);
++#define ATTR_LIST(name) &ext4_attr_##name.attr
++
++EXT4_ATTR_FUNC(delayed_allocation_blocks, 0444);
++EXT4_ATTR_FUNC(session_write_kbytes, 0444);
++EXT4_ATTR_FUNC(lifetime_write_kbytes, 0444);
++EXT4_ATTR_FUNC(reserved_clusters, 0644);
++
++EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, inode_readahead,
++		 ext4_sb_info, s_inode_readahead_blks);
+ EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal);
+ EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats);
+ EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan);
+@@ -225,9 +173,8 @@ EXT4_RW_ATTR_SBI_UI(mb_min_to_scan, s_mb_min_to_scan);
+ EXT4_RW_ATTR_SBI_UI(mb_order2_req, s_mb_order2_reqs);
+ EXT4_RW_ATTR_SBI_UI(mb_stream_req, s_mb_stream_request);
+ EXT4_RW_ATTR_SBI_UI(mb_group_prealloc, s_mb_group_prealloc);
+-EXT4_DEPRECATED_ATTR(max_writeback_mb_bump, 128);
+ EXT4_RW_ATTR_SBI_UI(extent_max_zeroout_kb, s_extent_max_zeroout_kb);
+-EXT4_ATTR(trigger_fs_error, 0200, NULL, trigger_test_error);
++EXT4_ATTR(trigger_fs_error, 0200, trigger_test_error);
+ EXT4_RW_ATTR_SBI_UI(err_ratelimit_interval_ms, s_err_ratelimit_state.interval);
+ EXT4_RW_ATTR_SBI_UI(err_ratelimit_burst, s_err_ratelimit_state.burst);
+ EXT4_RW_ATTR_SBI_UI(warning_ratelimit_interval_ms, s_warning_ratelimit_state.interval);
+@@ -238,6 +185,9 @@ EXT4_RO_ATTR_ES_UI(errors_count, s_error_count);
+ EXT4_RO_ATTR_ES_UI(first_error_time, s_first_error_time);
+ EXT4_RO_ATTR_ES_UI(last_error_time, s_last_error_time);
+ 
++static unsigned int old_bump_val = 128;
++EXT4_ATTR_PTR(max_writeback_mb_bump, 0444, pointer_ui, &old_bump_val);
++
+ static struct attribute *ext4_attrs[] = {
+ 	ATTR_LIST(delayed_allocation_blocks),
+ 	ATTR_LIST(session_write_kbytes),
+@@ -267,10 +217,10 @@ static struct attribute *ext4_attrs[] = {
+ };
+ 
+ /* Features this copy of ext4 supports */
+-EXT4_INFO_ATTR(lazy_itable_init);
+-EXT4_INFO_ATTR(batched_discard);
+-EXT4_INFO_ATTR(meta_bg_resize);
+-EXT4_INFO_ATTR(encryption);
++EXT4_ATTR_FEATURE(lazy_itable_init);
++EXT4_ATTR_FEATURE(batched_discard);
++EXT4_ATTR_FEATURE(meta_bg_resize);
++EXT4_ATTR_FEATURE(encryption);
+ 
+ static struct attribute *ext4_feat_attrs[] = {
+ 	ATTR_LIST(lazy_itable_init),
+@@ -280,14 +230,56 @@ static struct attribute *ext4_feat_attrs[] = {
+ 	NULL,
+ };
+ 
++static void *calc_ptr(struct ext4_attr *a, struct ext4_sb_info *sbi)
++{
++	switch (a->attr_ptr) {
++	case ptr_explicit:
++		return a->u.explicit_ptr;
++	case ptr_ext4_sb_info_offset:
++		return (void *) (((char *) sbi) + a->u.offset);
++	case ptr_ext4_super_block_offset:
++		return (void *) (((char *) sbi->s_es) + a->u.offset);
++	}
++	return NULL;
++}
++
+ static ssize_t ext4_attr_show(struct kobject *kobj,
+ 			      struct attribute *attr, char *buf)
+ {
+ 	struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info,
+ 						s_kobj);
+ 	struct ext4_attr *a = container_of(attr, struct ext4_attr, attr);
+-
+-	return a->show ? a->show(a, sbi, buf) : 0;
++	void *ptr = calc_ptr(a, sbi);
++
++	switch (a->attr_id) {
++	case attr_delayed_allocation_blocks:
++		return snprintf(buf, PAGE_SIZE, "%llu\n",
++				(s64) EXT4_C2B(sbi,
++		       percpu_counter_sum(&sbi->s_dirtyclusters_counter)));
++	case attr_session_write_kbytes:
++		return session_write_kbytes_show(a, sbi, buf);
++	case attr_lifetime_write_kbytes:
++		return lifetime_write_kbytes_show(a, sbi, buf);
++	case attr_reserved_clusters:
++		return snprintf(buf, PAGE_SIZE, "%llu\n",
++				(unsigned long long)
++				atomic64_read(&sbi->s_resv_clusters));
++	case attr_inode_readahead:
++	case attr_pointer_ui:
++		if (!ptr)
++			return 0;
++		return snprintf(buf, PAGE_SIZE, "%u\n",
++				*((unsigned int *) ptr));
++	case attr_pointer_atomic:
++		if (!ptr)
++			return 0;
++		return snprintf(buf, PAGE_SIZE, "%d\n",
++				atomic_read((atomic_t *) ptr));
++	case attr_feature:
++		return snprintf(buf, PAGE_SIZE, "supported\n");
++	}
++
++	return 0;
+ }
+ 
+ static ssize_t ext4_attr_store(struct kobject *kobj,
+@@ -297,8 +289,27 @@ static ssize_t ext4_attr_store(struct kobject *kobj,
+ 	struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info,
+ 						s_kobj);
+ 	struct ext4_attr *a = container_of(attr, struct ext4_attr, attr);
++	void *ptr = calc_ptr(a, sbi);
++	unsigned long t;
++	int ret;
+ 
+-	return a->store ? a->store(a, sbi, buf, len) : 0;
++	switch (a->attr_id) {
++	case attr_reserved_clusters:
++		return reserved_clusters_store(a, sbi, buf, len);
++	case attr_pointer_ui:
++		if (!ptr)
++			return 0;
++		ret = kstrtoul(skip_spaces(buf), 0, &t);
++		if (ret)
++			return ret;
++		*((unsigned int *) ptr) = t;
++		return len;
++	case attr_inode_readahead:
++		return inode_readahead_blks_store(a, sbi, buf, len);
++	case attr_trigger_test_error:
++		return trigger_test_error(a, sbi, buf, len);
++	}
++	return 0;
+ }
+ 
+ static void ext4_sb_release(struct kobject *kobj)
+@@ -327,25 +338,9 @@ static struct kset ext4_kset = {
+ 	.kobj   = {.ktype = &ext4_ktype},
+ };
+ 
+-static ssize_t ext4_feat_show(struct kobject *kobj,
+-			      struct attribute *attr, char *buf)
+-{
+-	return snprintf(buf, PAGE_SIZE, "supported\n");
+-}
+-
+-/*
+- * We can not use ext4_attr_show/store because it relies on the kobject
+- * being embedded in the ext4_sb_info structure which is definitely not
+- * true in this case.
+- */
+-static const struct sysfs_ops ext4_feat_ops = {
+-	.show	= ext4_feat_show,
+-	.store	= NULL,
+-};
+-
+ static struct kobj_type ext4_feat_ktype = {
+ 	.default_attrs	= ext4_feat_attrs,
+-	.sysfs_ops	= &ext4_feat_ops,
++	.sysfs_ops	= &ext4_attr_ops,
+ };
+ 
+ static struct kobject ext4_feat = {

commit b5799018827e67867fda77c3cde10fc080606fe2
+Author: Theodore Ts'o 
+Date:   Wed Sep 23 12:44:17 2015 -0400
+
+    ext4: move sysfs code from super.c to fs/ext4/sysfs.c
+    
+    Also statically allocate the ext4_kset and ext4_feat objects, since we
+    only need exactly one of each, and it's simpler and less code if we
+    drop the dynamic allocation and deallocation when it's not needed.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
+index 75285ea9aa05..f52cf54f0cbc 100644
+--- a/fs/ext4/Makefile
++++ b/fs/ext4/Makefile
+@@ -8,7 +8,7 @@ ext4-y	:= balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o page-io.o \
+ 		ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \
+ 		ext4_jbd2.o migrate.o mballoc.o block_validity.o move_extent.o \
+ 		mmp.o indirect.o extents_status.o xattr.o xattr_user.o \
+-		xattr_trusted.o inline.o readpage.o
++		xattr_trusted.o inline.o readpage.o sysfs.o
+ 
+ ext4-$(CONFIG_EXT4_FS_POSIX_ACL)	+= acl.o
+ ext4-$(CONFIG_EXT4_FS_SECURITY)		+= xattr_security.o
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index fd1f28be5296..76daccf38aa3 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2903,6 +2903,11 @@ extern const struct inode_operations ext4_encrypted_symlink_inode_operations;
+ extern const struct inode_operations ext4_symlink_inode_operations;
+ extern const struct inode_operations ext4_fast_symlink_inode_operations;
+ 
++/* sysfs.c */
++extern int ext4_register_sysfs(struct super_block *sb);
++extern int __init ext4_init_sysfs(void);
++extern void ext4_exit_sysfs(void);
++
+ /* block_validity */
+ extern void ext4_release_system_zone(struct super_block *sb);
+ extern int ext4_setup_system_zone(struct super_block *sb);
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index a63c7b0a10cf..4a574fbeffec 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -55,10 +55,8 @@
+ #include 
+ 
+ static struct proc_dir_entry *ext4_proc_root;
+-static struct kset *ext4_kset;
+ static struct ext4_lazy_init *ext4_li_info;
+ static struct mutex ext4_li_mtx;
+-static struct ext4_features *ext4_feat;
+ static int ext4_mballoc_ready;
+ static struct ratelimit_state ext4_mount_msg_ratelimit;
+ 
+@@ -83,7 +81,6 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly);
+ static void ext4_destroy_lazyinit_thread(void);
+ static void ext4_unregister_li_request(struct super_block *sb);
+ static void ext4_clear_request_list(void);
+-static int ext4_reserve_clusters(struct ext4_sb_info *, ext4_fsblk_t);
+ 
+ #if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT2)
+ static struct file_system_type ext2_fs_type = {
+@@ -2470,335 +2467,6 @@ static unsigned long ext4_get_stripe_size(struct ext4_sb_info *sbi)
+ 	return ret;
+ }
+ 
+-/* sysfs supprt */
+-
+-struct ext4_attr {
+-	struct attribute attr;
+-	ssize_t (*show)(struct ext4_attr *, struct ext4_sb_info *, char *);
+-	ssize_t (*store)(struct ext4_attr *, struct ext4_sb_info *,
+-			 const char *, size_t);
+-	union {
+-		int offset;
+-		int deprecated_val;
+-	} u;
+-};
+-
+-static int parse_strtoull(const char *buf,
+-		unsigned long long max, unsigned long long *value)
+-{
+-	int ret;
+-
+-	ret = kstrtoull(skip_spaces(buf), 0, value);
+-	if (!ret && *value > max)
+-		ret = -EINVAL;
+-	return ret;
+-}
+-
+-static ssize_t delayed_allocation_blocks_show(struct ext4_attr *a,
+-					      struct ext4_sb_info *sbi,
+-					      char *buf)
+-{
+-	return snprintf(buf, PAGE_SIZE, "%llu\n",
+-		(s64) EXT4_C2B(sbi,
+-			percpu_counter_sum(&sbi->s_dirtyclusters_counter)));
+-}
+-
+-static ssize_t session_write_kbytes_show(struct ext4_attr *a,
+-					 struct ext4_sb_info *sbi, char *buf)
+-{
+-	struct super_block *sb = sbi->s_buddy_cache->i_sb;
+-
+-	if (!sb->s_bdev->bd_part)
+-		return snprintf(buf, PAGE_SIZE, "0\n");
+-	return snprintf(buf, PAGE_SIZE, "%lu\n",
+-			(part_stat_read(sb->s_bdev->bd_part, sectors[1]) -
+-			 sbi->s_sectors_written_start) >> 1);
+-}
+-
+-static ssize_t lifetime_write_kbytes_show(struct ext4_attr *a,
+-					  struct ext4_sb_info *sbi, char *buf)
+-{
+-	struct super_block *sb = sbi->s_buddy_cache->i_sb;
+-
+-	if (!sb->s_bdev->bd_part)
+-		return snprintf(buf, PAGE_SIZE, "0\n");
+-	return snprintf(buf, PAGE_SIZE, "%llu\n",
+-			(unsigned long long)(sbi->s_kbytes_written +
+-			((part_stat_read(sb->s_bdev->bd_part, sectors[1]) -
+-			  EXT4_SB(sb)->s_sectors_written_start) >> 1)));
+-}
+-
+-static ssize_t inode_readahead_blks_store(struct ext4_attr *a,
+-					  struct ext4_sb_info *sbi,
+-					  const char *buf, size_t count)
+-{
+-	unsigned long t;
+-	int ret;
+-
+-	ret = kstrtoul(skip_spaces(buf), 0, &t);
+-	if (ret)
+-		return ret;
+-
+-	if (t && (!is_power_of_2(t) || t > 0x40000000))
+-		return -EINVAL;
+-
+-	sbi->s_inode_readahead_blks = t;
+-	return count;
+-}
+-
+-static ssize_t sbi_ui_show(struct ext4_attr *a,
+-			   struct ext4_sb_info *sbi, char *buf)
+-{
+-	unsigned int *ui = (unsigned int *) (((char *) sbi) + a->u.offset);
+-
+-	return snprintf(buf, PAGE_SIZE, "%u\n", *ui);
+-}
+-
+-static ssize_t sbi_ui_store(struct ext4_attr *a,
+-			    struct ext4_sb_info *sbi,
+-			    const char *buf, size_t count)
+-{
+-	unsigned int *ui = (unsigned int *) (((char *) sbi) + a->u.offset);
+-	unsigned long t;
+-	int ret;
+-
+-	ret = kstrtoul(skip_spaces(buf), 0, &t);
+-	if (ret)
+-		return ret;
+-	*ui = t;
+-	return count;
+-}
+-
+-static ssize_t es_ui_show(struct ext4_attr *a,
+-			   struct ext4_sb_info *sbi, char *buf)
+-{
+-
+-	unsigned int *ui = (unsigned int *) (((char *) sbi->s_es) +
+-			   a->u.offset);
+-
+-	return snprintf(buf, PAGE_SIZE, "%u\n", *ui);
+-}
+-
+-static ssize_t reserved_clusters_show(struct ext4_attr *a,
+-				  struct ext4_sb_info *sbi, char *buf)
+-{
+-	return snprintf(buf, PAGE_SIZE, "%llu\n",
+-		(unsigned long long) atomic64_read(&sbi->s_resv_clusters));
+-}
+-
+-static ssize_t reserved_clusters_store(struct ext4_attr *a,
+-				   struct ext4_sb_info *sbi,
+-				   const char *buf, size_t count)
+-{
+-	unsigned long long val;
+-	int ret;
+-
+-	if (parse_strtoull(buf, -1ULL, &val))
+-		return -EINVAL;
+-	ret = ext4_reserve_clusters(sbi, val);
+-
+-	return ret ? ret : count;
+-}
+-
+-static ssize_t trigger_test_error(struct ext4_attr *a,
+-				  struct ext4_sb_info *sbi,
+-				  const char *buf, size_t count)
+-{
+-	int len = count;
+-
+-	if (!capable(CAP_SYS_ADMIN))
+-		return -EPERM;
+-
+-	if (len && buf[len-1] == '\n')
+-		len--;
+-
+-	if (len)
+-		ext4_error(sbi->s_sb, "%.*s", len, buf);
+-	return count;
+-}
+-
+-static ssize_t sbi_deprecated_show(struct ext4_attr *a,
+-				   struct ext4_sb_info *sbi, char *buf)
+-{
+-	return snprintf(buf, PAGE_SIZE, "%d\n", a->u.deprecated_val);
+-}
+-
+-#define EXT4_ATTR_OFFSET(_name,_mode,_show,_store,_elname) \
+-static struct ext4_attr ext4_attr_##_name = {			\
+-	.attr = {.name = __stringify(_name), .mode = _mode },	\
+-	.show	= _show,					\
+-	.store	= _store,					\
+-	.u = {							\
+-		.offset = offsetof(struct ext4_sb_info, _elname),\
+-	},							\
+-}
+-
+-#define EXT4_ATTR_OFFSET_ES(_name,_mode,_show,_store,_elname)		\
+-static struct ext4_attr ext4_attr_##_name = {				\
+-	.attr = {.name = __stringify(_name), .mode = _mode },		\
+-	.show	= _show,						\
+-	.store	= _store,						\
+-	.u = {								\
+-		.offset = offsetof(struct ext4_super_block, _elname),	\
+-	},								\
+-}
+-
+-#define EXT4_ATTR(name, mode, show, store) \
+-static struct ext4_attr ext4_attr_##name = __ATTR(name, mode, show, store)
+-
+-#define EXT4_INFO_ATTR(name) EXT4_ATTR(name, 0444, NULL, NULL)
+-#define EXT4_RO_ATTR(name) EXT4_ATTR(name, 0444, name##_show, NULL)
+-#define EXT4_RW_ATTR(name) EXT4_ATTR(name, 0644, name##_show, name##_store)
+-
+-#define EXT4_RO_ATTR_ES_UI(name, elname)	\
+-	EXT4_ATTR_OFFSET_ES(name, 0444, es_ui_show, NULL, elname)
+-#define EXT4_RW_ATTR_SBI_UI(name, elname)	\
+-	EXT4_ATTR_OFFSET(name, 0644, sbi_ui_show, sbi_ui_store, elname)
+-
+-#define ATTR_LIST(name) &ext4_attr_##name.attr
+-#define EXT4_DEPRECATED_ATTR(_name, _val)	\
+-static struct ext4_attr ext4_attr_##_name = {			\
+-	.attr = {.name = __stringify(_name), .mode = 0444 },	\
+-	.show	= sbi_deprecated_show,				\
+-	.u = {							\
+-		.deprecated_val = _val,				\
+-	},							\
+-}
+-
+-EXT4_RO_ATTR(delayed_allocation_blocks);
+-EXT4_RO_ATTR(session_write_kbytes);
+-EXT4_RO_ATTR(lifetime_write_kbytes);
+-EXT4_RW_ATTR(reserved_clusters);
+-EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show,
+-		 inode_readahead_blks_store, s_inode_readahead_blks);
+-EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal);
+-EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats);
+-EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan);
+-EXT4_RW_ATTR_SBI_UI(mb_min_to_scan, s_mb_min_to_scan);
+-EXT4_RW_ATTR_SBI_UI(mb_order2_req, s_mb_order2_reqs);
+-EXT4_RW_ATTR_SBI_UI(mb_stream_req, s_mb_stream_request);
+-EXT4_RW_ATTR_SBI_UI(mb_group_prealloc, s_mb_group_prealloc);
+-EXT4_DEPRECATED_ATTR(max_writeback_mb_bump, 128);
+-EXT4_RW_ATTR_SBI_UI(extent_max_zeroout_kb, s_extent_max_zeroout_kb);
+-EXT4_ATTR(trigger_fs_error, 0200, NULL, trigger_test_error);
+-EXT4_RW_ATTR_SBI_UI(err_ratelimit_interval_ms, s_err_ratelimit_state.interval);
+-EXT4_RW_ATTR_SBI_UI(err_ratelimit_burst, s_err_ratelimit_state.burst);
+-EXT4_RW_ATTR_SBI_UI(warning_ratelimit_interval_ms, s_warning_ratelimit_state.interval);
+-EXT4_RW_ATTR_SBI_UI(warning_ratelimit_burst, s_warning_ratelimit_state.burst);
+-EXT4_RW_ATTR_SBI_UI(msg_ratelimit_interval_ms, s_msg_ratelimit_state.interval);
+-EXT4_RW_ATTR_SBI_UI(msg_ratelimit_burst, s_msg_ratelimit_state.burst);
+-EXT4_RO_ATTR_ES_UI(errors_count, s_error_count);
+-EXT4_RO_ATTR_ES_UI(first_error_time, s_first_error_time);
+-EXT4_RO_ATTR_ES_UI(last_error_time, s_last_error_time);
+-
+-static struct attribute *ext4_attrs[] = {
+-	ATTR_LIST(delayed_allocation_blocks),
+-	ATTR_LIST(session_write_kbytes),
+-	ATTR_LIST(lifetime_write_kbytes),
+-	ATTR_LIST(reserved_clusters),
+-	ATTR_LIST(inode_readahead_blks),
+-	ATTR_LIST(inode_goal),
+-	ATTR_LIST(mb_stats),
+-	ATTR_LIST(mb_max_to_scan),
+-	ATTR_LIST(mb_min_to_scan),
+-	ATTR_LIST(mb_order2_req),
+-	ATTR_LIST(mb_stream_req),
+-	ATTR_LIST(mb_group_prealloc),
+-	ATTR_LIST(max_writeback_mb_bump),
+-	ATTR_LIST(extent_max_zeroout_kb),
+-	ATTR_LIST(trigger_fs_error),
+-	ATTR_LIST(err_ratelimit_interval_ms),
+-	ATTR_LIST(err_ratelimit_burst),
+-	ATTR_LIST(warning_ratelimit_interval_ms),
+-	ATTR_LIST(warning_ratelimit_burst),
+-	ATTR_LIST(msg_ratelimit_interval_ms),
+-	ATTR_LIST(msg_ratelimit_burst),
+-	ATTR_LIST(errors_count),
+-	ATTR_LIST(first_error_time),
+-	ATTR_LIST(last_error_time),
+-	NULL,
+-};
+-
+-/* Features this copy of ext4 supports */
+-EXT4_INFO_ATTR(lazy_itable_init);
+-EXT4_INFO_ATTR(batched_discard);
+-EXT4_INFO_ATTR(meta_bg_resize);
+-EXT4_INFO_ATTR(encryption);
+-
+-static struct attribute *ext4_feat_attrs[] = {
+-	ATTR_LIST(lazy_itable_init),
+-	ATTR_LIST(batched_discard),
+-	ATTR_LIST(meta_bg_resize),
+-	ATTR_LIST(encryption),
+-	NULL,
+-};
+-
+-static ssize_t ext4_attr_show(struct kobject *kobj,
+-			      struct attribute *attr, char *buf)
+-{
+-	struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info,
+-						s_kobj);
+-	struct ext4_attr *a = container_of(attr, struct ext4_attr, attr);
+-
+-	return a->show ? a->show(a, sbi, buf) : 0;
+-}
+-
+-static ssize_t ext4_attr_store(struct kobject *kobj,
+-			       struct attribute *attr,
+-			       const char *buf, size_t len)
+-{
+-	struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info,
+-						s_kobj);
+-	struct ext4_attr *a = container_of(attr, struct ext4_attr, attr);
+-
+-	return a->store ? a->store(a, sbi, buf, len) : 0;
+-}
+-
+-static void ext4_sb_release(struct kobject *kobj)
+-{
+-	struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info,
+-						s_kobj);
+-	complete(&sbi->s_kobj_unregister);
+-}
+-
+-static const struct sysfs_ops ext4_attr_ops = {
+-	.show	= ext4_attr_show,
+-	.store	= ext4_attr_store,
+-};
+-
+-static struct kobj_type ext4_ktype = {
+-	.default_attrs	= ext4_attrs,
+-	.sysfs_ops	= &ext4_attr_ops,
+-	.release	= ext4_sb_release,
+-};
+-
+-static void ext4_feat_release(struct kobject *kobj)
+-{
+-	complete(&ext4_feat->f_kobj_unregister);
+-}
+-
+-static ssize_t ext4_feat_show(struct kobject *kobj,
+-			      struct attribute *attr, char *buf)
+-{
+-	return snprintf(buf, PAGE_SIZE, "supported\n");
+-}
+-
+-/*
+- * We can not use ext4_attr_show/store because it relies on the kobject
+- * being embedded in the ext4_sb_info structure which is definitely not
+- * true in this case.
+- */
+-static const struct sysfs_ops ext4_feat_ops = {
+-	.show	= ext4_feat_show,
+-	.store	= NULL,
+-};
+-
+-static struct kobj_type ext4_feat_ktype = {
+-	.default_attrs	= ext4_feat_attrs,
+-	.sysfs_ops	= &ext4_feat_ops,
+-	.release	= ext4_feat_release,
+-};
+-
+ /*
+  * Check whether this filesystem can be mounted based on
+  * the features present and the RDONLY/RDWR mount requested.
+@@ -3403,10 +3071,10 @@ int ext4_calculate_overhead(struct super_block *sb)
+ 	return 0;
+ }
+ 
+-
+-static ext4_fsblk_t ext4_calculate_resv_clusters(struct super_block *sb)
++static void ext4_set_resv_clusters(struct super_block *sb)
+ {
+ 	ext4_fsblk_t resv_clusters;
++	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 
+ 	/*
+ 	 * There's no need to reserve anything when we aren't using extents.
+@@ -3415,7 +3083,7 @@ static ext4_fsblk_t ext4_calculate_resv_clusters(struct super_block *sb)
+ 	 * to keep ext2/3 backward compatibility.
+ 	 */
+ 	if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS))
+-		return 0;
++		return;
+ 	/*
+ 	 * By default we reserve 2% or 4096 clusters, whichever is smaller.
+ 	 * This should cover the situations where we can not afford to run
+@@ -3424,26 +3092,13 @@ static ext4_fsblk_t ext4_calculate_resv_clusters(struct super_block *sb)
+ 	 * allocation would require 1, or 2 blocks, higher numbers are
+ 	 * very rare.
+ 	 */
+-	resv_clusters = ext4_blocks_count(EXT4_SB(sb)->s_es) >>
+-			EXT4_SB(sb)->s_cluster_bits;
++	resv_clusters = (ext4_blocks_count(sbi->s_es) >>
++			 sbi->s_cluster_bits);
+ 
+ 	do_div(resv_clusters, 50);
+ 	resv_clusters = min_t(ext4_fsblk_t, resv_clusters, 4096);
+ 
+-	return resv_clusters;
+-}
+-
+-
+-static int ext4_reserve_clusters(struct ext4_sb_info *sbi, ext4_fsblk_t count)
+-{
+-	ext4_fsblk_t clusters = ext4_blocks_count(sbi->s_es) >>
+-				sbi->s_cluster_bits;
+-
+-	if (count >= clusters)
+-		return -EINVAL;
+-
+-	atomic64_set(&sbi->s_resv_clusters, count);
+-	return 0;
++	atomic64_set(&sbi->s_resv_clusters, resv_clusters);
+ }
+ 
+ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+@@ -4192,12 +3847,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 			 "available");
+ 	}
+ 
+-	err = ext4_reserve_clusters(sbi, ext4_calculate_resv_clusters(sb));
+-	if (err) {
+-		ext4_msg(sb, KERN_ERR, "failed to reserve %llu clusters for "
+-			 "reserved pool", ext4_calculate_resv_clusters(sb));
+-		goto failed_mount4a;
+-	}
++	ext4_set_resv_clusters(sb);
+ 
+ 	err = ext4_setup_system_zone(sb);
+ 	if (err) {
+@@ -4248,10 +3898,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	if (err)
+ 		goto failed_mount6;
+ 
+-	sbi->s_kobj.kset = ext4_kset;
+-	init_completion(&sbi->s_kobj_unregister);
+-	err = kobject_init_and_add(&sbi->s_kobj, &ext4_ktype, NULL,
+-				   "%s", sb->s_id);
++	err = ext4_register_sysfs(sb);
+ 	if (err)
+ 		goto failed_mount7;
+ 
+@@ -5586,37 +5233,6 @@ static struct file_system_type ext4_fs_type = {
+ };
+ MODULE_ALIAS_FS("ext4");
+ 
+-static int __init ext4_init_feat_adverts(void)
+-{
+-	struct ext4_features *ef;
+-	int ret = -ENOMEM;
+-
+-	ef = kzalloc(sizeof(struct ext4_features), GFP_KERNEL);
+-	if (!ef)
+-		goto out;
+-
+-	ef->f_kobj.kset = ext4_kset;
+-	init_completion(&ef->f_kobj_unregister);
+-	ret = kobject_init_and_add(&ef->f_kobj, &ext4_feat_ktype, NULL,
+-				   "features");
+-	if (ret) {
+-		kfree(ef);
+-		goto out;
+-	}
+-
+-	ext4_feat = ef;
+-	ret = 0;
+-out:
+-	return ret;
+-}
+-
+-static void ext4_exit_feat_adverts(void)
+-{
+-	kobject_put(&ext4_feat->f_kobj);
+-	wait_for_completion(&ext4_feat->f_kobj_unregister);
+-	kfree(ext4_feat);
+-}
+-
+ /* Shared across all ext4 file systems */
+ wait_queue_head_t ext4__ioend_wq[EXT4_WQ_HASH_SZ];
+ struct mutex ext4__aio_mutex[EXT4_WQ_HASH_SZ];
+@@ -5643,21 +5259,16 @@ static int __init ext4_init_fs(void)
+ 
+ 	err = ext4_init_pageio();
+ 	if (err)
+-		goto out7;
++		goto out5;
+ 
+ 	err = ext4_init_system_zone();
+ 	if (err)
+-		goto out6;
+-	ext4_kset = kset_create_and_add("ext4", NULL, fs_kobj);
+-	if (!ext4_kset) {
+-		err = -ENOMEM;
+-		goto out5;
+-	}
++		goto out4;
+ 	ext4_proc_root = proc_mkdir("fs/ext4", NULL);
+ 
+-	err = ext4_init_feat_adverts();
++	err = ext4_init_sysfs();
+ 	if (err)
+-		goto out4;
++		goto out3;
+ 
+ 	err = ext4_init_mballoc();
+ 	if (err)
+@@ -5682,16 +5293,14 @@ static int __init ext4_init_fs(void)
+ 	ext4_mballoc_ready = 0;
+ 	ext4_exit_mballoc();
+ out2:
+-	ext4_exit_feat_adverts();
+-out4:
++	ext4_exit_sysfs();
++out3:
+ 	if (ext4_proc_root)
+ 		remove_proc_entry("fs/ext4", NULL);
+-	kset_unregister(ext4_kset);
+-out5:
+ 	ext4_exit_system_zone();
+-out6:
++out4:
+ 	ext4_exit_pageio();
+-out7:
++out5:
+ 	ext4_exit_es();
+ 
+ 	return err;
+@@ -5706,9 +5315,8 @@ static void __exit ext4_exit_fs(void)
+ 	unregister_filesystem(&ext4_fs_type);
+ 	destroy_inodecache();
+ 	ext4_exit_mballoc();
+-	ext4_exit_feat_adverts();
++	ext4_exit_sysfs();
+ 	remove_proc_entry("fs/ext4", NULL);
+-	kset_unregister(ext4_kset);
+ 	ext4_exit_system_zone();
+ 	ext4_exit_pageio();
+ 	ext4_exit_es();
+diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c
+new file mode 100644
+index 000000000000..9fdc21b9b265
+--- /dev/null
++++ b/fs/ext4/sysfs.c
+@@ -0,0 +1,387 @@
++/*
++ *  linux/fs/ext4/sysfs.c
++ *
++ * Copyright (C) 1992, 1993, 1994, 1995
++ * Remy Card (card@masi.ibp.fr)
++ * Theodore Ts'o (tytso@mit.edu)
++ *
++ */
++
++#include 
++#include 
++#include 
++#include 
++
++#include "ext4.h"
++#include "ext4_jbd2.h"
++
++struct ext4_attr {
++	struct attribute attr;
++	ssize_t (*show)(struct ext4_attr *, struct ext4_sb_info *, char *);
++	ssize_t (*store)(struct ext4_attr *, struct ext4_sb_info *,
++			 const char *, size_t);
++	union {
++		int offset;
++		int deprecated_val;
++	} u;
++};
++
++static int parse_strtoull(const char *buf,
++		unsigned long long max, unsigned long long *value)
++{
++	int ret;
++
++	ret = kstrtoull(skip_spaces(buf), 0, value);
++	if (!ret && *value > max)
++		ret = -EINVAL;
++	return ret;
++}
++
++static ssize_t delayed_allocation_blocks_show(struct ext4_attr *a,
++					      struct ext4_sb_info *sbi,
++					      char *buf)
++{
++	return snprintf(buf, PAGE_SIZE, "%llu\n",
++		(s64) EXT4_C2B(sbi,
++			percpu_counter_sum(&sbi->s_dirtyclusters_counter)));
++}
++
++static ssize_t session_write_kbytes_show(struct ext4_attr *a,
++					 struct ext4_sb_info *sbi, char *buf)
++{
++	struct super_block *sb = sbi->s_buddy_cache->i_sb;
++
++	if (!sb->s_bdev->bd_part)
++		return snprintf(buf, PAGE_SIZE, "0\n");
++	return snprintf(buf, PAGE_SIZE, "%lu\n",
++			(part_stat_read(sb->s_bdev->bd_part, sectors[1]) -
++			 sbi->s_sectors_written_start) >> 1);
++}
++
++static ssize_t lifetime_write_kbytes_show(struct ext4_attr *a,
++					  struct ext4_sb_info *sbi, char *buf)
++{
++	struct super_block *sb = sbi->s_buddy_cache->i_sb;
++
++	if (!sb->s_bdev->bd_part)
++		return snprintf(buf, PAGE_SIZE, "0\n");
++	return snprintf(buf, PAGE_SIZE, "%llu\n",
++			(unsigned long long)(sbi->s_kbytes_written +
++			((part_stat_read(sb->s_bdev->bd_part, sectors[1]) -
++			  EXT4_SB(sb)->s_sectors_written_start) >> 1)));
++}
++
++static ssize_t inode_readahead_blks_store(struct ext4_attr *a,
++					  struct ext4_sb_info *sbi,
++					  const char *buf, size_t count)
++{
++	unsigned long t;
++	int ret;
++
++	ret = kstrtoul(skip_spaces(buf), 0, &t);
++	if (ret)
++		return ret;
++
++	if (t && (!is_power_of_2(t) || t > 0x40000000))
++		return -EINVAL;
++
++	sbi->s_inode_readahead_blks = t;
++	return count;
++}
++
++static ssize_t sbi_ui_show(struct ext4_attr *a,
++			   struct ext4_sb_info *sbi, char *buf)
++{
++	unsigned int *ui = (unsigned int *) (((char *) sbi) + a->u.offset);
++
++	return snprintf(buf, PAGE_SIZE, "%u\n", *ui);
++}
++
++static ssize_t sbi_ui_store(struct ext4_attr *a,
++			    struct ext4_sb_info *sbi,
++			    const char *buf, size_t count)
++{
++	unsigned int *ui = (unsigned int *) (((char *) sbi) + a->u.offset);
++	unsigned long t;
++	int ret;
++
++	ret = kstrtoul(skip_spaces(buf), 0, &t);
++	if (ret)
++		return ret;
++	*ui = t;
++	return count;
++}
++
++static ssize_t es_ui_show(struct ext4_attr *a,
++			   struct ext4_sb_info *sbi, char *buf)
++{
++
++	unsigned int *ui = (unsigned int *) (((char *) sbi->s_es) +
++			   a->u.offset);
++
++	return snprintf(buf, PAGE_SIZE, "%u\n", *ui);
++}
++
++static ssize_t reserved_clusters_show(struct ext4_attr *a,
++				  struct ext4_sb_info *sbi, char *buf)
++{
++	return snprintf(buf, PAGE_SIZE, "%llu\n",
++		(unsigned long long) atomic64_read(&sbi->s_resv_clusters));
++}
++
++static ssize_t reserved_clusters_store(struct ext4_attr *a,
++				   struct ext4_sb_info *sbi,
++				   const char *buf, size_t count)
++{
++	unsigned long long val;
++	ext4_fsblk_t clusters = (ext4_blocks_count(sbi->s_es) >>
++				 sbi->s_cluster_bits);
++
++	if (parse_strtoull(buf, -1ULL, &val))
++		return -EINVAL;
++
++	if (val >= clusters)
++		return -EINVAL;
++
++	atomic64_set(&sbi->s_resv_clusters, val);
++	return count;
++}
++
++static ssize_t trigger_test_error(struct ext4_attr *a,
++				  struct ext4_sb_info *sbi,
++				  const char *buf, size_t count)
++{
++	int len = count;
++
++	if (!capable(CAP_SYS_ADMIN))
++		return -EPERM;
++
++	if (len && buf[len-1] == '\n')
++		len--;
++
++	if (len)
++		ext4_error(sbi->s_sb, "%.*s", len, buf);
++	return count;
++}
++
++static ssize_t sbi_deprecated_show(struct ext4_attr *a,
++				   struct ext4_sb_info *sbi, char *buf)
++{
++	return snprintf(buf, PAGE_SIZE, "%d\n", a->u.deprecated_val);
++}
++
++#define EXT4_ATTR_OFFSET(_name,_mode,_show,_store,_elname) \
++static struct ext4_attr ext4_attr_##_name = {			\
++	.attr = {.name = __stringify(_name), .mode = _mode },	\
++	.show	= _show,					\
++	.store	= _store,					\
++	.u = {							\
++		.offset = offsetof(struct ext4_sb_info, _elname),\
++	},							\
++}
++
++#define EXT4_ATTR_OFFSET_ES(_name,_mode,_show,_store,_elname)		\
++static struct ext4_attr ext4_attr_##_name = {				\
++	.attr = {.name = __stringify(_name), .mode = _mode },		\
++	.show	= _show,						\
++	.store	= _store,						\
++	.u = {								\
++		.offset = offsetof(struct ext4_super_block, _elname),	\
++	},								\
++}
++
++#define EXT4_ATTR(name, mode, show, store) \
++static struct ext4_attr ext4_attr_##name = __ATTR(name, mode, show, store)
++
++#define EXT4_INFO_ATTR(name) EXT4_ATTR(name, 0444, NULL, NULL)
++#define EXT4_RO_ATTR(name) EXT4_ATTR(name, 0444, name##_show, NULL)
++#define EXT4_RW_ATTR(name) EXT4_ATTR(name, 0644, name##_show, name##_store)
++
++#define EXT4_RO_ATTR_ES_UI(name, elname)	\
++	EXT4_ATTR_OFFSET_ES(name, 0444, es_ui_show, NULL, elname)
++#define EXT4_RW_ATTR_SBI_UI(name, elname)	\
++	EXT4_ATTR_OFFSET(name, 0644, sbi_ui_show, sbi_ui_store, elname)
++
++#define ATTR_LIST(name) &ext4_attr_##name.attr
++#define EXT4_DEPRECATED_ATTR(_name, _val)	\
++static struct ext4_attr ext4_attr_##_name = {			\
++	.attr = {.name = __stringify(_name), .mode = 0444 },	\
++	.show	= sbi_deprecated_show,				\
++	.u = {							\
++		.deprecated_val = _val,				\
++	},							\
++}
++
++EXT4_RO_ATTR(delayed_allocation_blocks);
++EXT4_RO_ATTR(session_write_kbytes);
++EXT4_RO_ATTR(lifetime_write_kbytes);
++EXT4_RW_ATTR(reserved_clusters);
++EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show,
++		 inode_readahead_blks_store, s_inode_readahead_blks);
++EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal);
++EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats);
++EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan);
++EXT4_RW_ATTR_SBI_UI(mb_min_to_scan, s_mb_min_to_scan);
++EXT4_RW_ATTR_SBI_UI(mb_order2_req, s_mb_order2_reqs);
++EXT4_RW_ATTR_SBI_UI(mb_stream_req, s_mb_stream_request);
++EXT4_RW_ATTR_SBI_UI(mb_group_prealloc, s_mb_group_prealloc);
++EXT4_DEPRECATED_ATTR(max_writeback_mb_bump, 128);
++EXT4_RW_ATTR_SBI_UI(extent_max_zeroout_kb, s_extent_max_zeroout_kb);
++EXT4_ATTR(trigger_fs_error, 0200, NULL, trigger_test_error);
++EXT4_RW_ATTR_SBI_UI(err_ratelimit_interval_ms, s_err_ratelimit_state.interval);
++EXT4_RW_ATTR_SBI_UI(err_ratelimit_burst, s_err_ratelimit_state.burst);
++EXT4_RW_ATTR_SBI_UI(warning_ratelimit_interval_ms, s_warning_ratelimit_state.interval);
++EXT4_RW_ATTR_SBI_UI(warning_ratelimit_burst, s_warning_ratelimit_state.burst);
++EXT4_RW_ATTR_SBI_UI(msg_ratelimit_interval_ms, s_msg_ratelimit_state.interval);
++EXT4_RW_ATTR_SBI_UI(msg_ratelimit_burst, s_msg_ratelimit_state.burst);
++EXT4_RO_ATTR_ES_UI(errors_count, s_error_count);
++EXT4_RO_ATTR_ES_UI(first_error_time, s_first_error_time);
++EXT4_RO_ATTR_ES_UI(last_error_time, s_last_error_time);
++
++static struct attribute *ext4_attrs[] = {
++	ATTR_LIST(delayed_allocation_blocks),
++	ATTR_LIST(session_write_kbytes),
++	ATTR_LIST(lifetime_write_kbytes),
++	ATTR_LIST(reserved_clusters),
++	ATTR_LIST(inode_readahead_blks),
++	ATTR_LIST(inode_goal),
++	ATTR_LIST(mb_stats),
++	ATTR_LIST(mb_max_to_scan),
++	ATTR_LIST(mb_min_to_scan),
++	ATTR_LIST(mb_order2_req),
++	ATTR_LIST(mb_stream_req),
++	ATTR_LIST(mb_group_prealloc),
++	ATTR_LIST(max_writeback_mb_bump),
++	ATTR_LIST(extent_max_zeroout_kb),
++	ATTR_LIST(trigger_fs_error),
++	ATTR_LIST(err_ratelimit_interval_ms),
++	ATTR_LIST(err_ratelimit_burst),
++	ATTR_LIST(warning_ratelimit_interval_ms),
++	ATTR_LIST(warning_ratelimit_burst),
++	ATTR_LIST(msg_ratelimit_interval_ms),
++	ATTR_LIST(msg_ratelimit_burst),
++	ATTR_LIST(errors_count),
++	ATTR_LIST(first_error_time),
++	ATTR_LIST(last_error_time),
++	NULL,
++};
++
++/* Features this copy of ext4 supports */
++EXT4_INFO_ATTR(lazy_itable_init);
++EXT4_INFO_ATTR(batched_discard);
++EXT4_INFO_ATTR(meta_bg_resize);
++EXT4_INFO_ATTR(encryption);
++
++static struct attribute *ext4_feat_attrs[] = {
++	ATTR_LIST(lazy_itable_init),
++	ATTR_LIST(batched_discard),
++	ATTR_LIST(meta_bg_resize),
++	ATTR_LIST(encryption),
++	NULL,
++};
++
++static ssize_t ext4_attr_show(struct kobject *kobj,
++			      struct attribute *attr, char *buf)
++{
++	struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info,
++						s_kobj);
++	struct ext4_attr *a = container_of(attr, struct ext4_attr, attr);
++
++	return a->show ? a->show(a, sbi, buf) : 0;
++}
++
++static ssize_t ext4_attr_store(struct kobject *kobj,
++			       struct attribute *attr,
++			       const char *buf, size_t len)
++{
++	struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info,
++						s_kobj);
++	struct ext4_attr *a = container_of(attr, struct ext4_attr, attr);
++
++	return a->store ? a->store(a, sbi, buf, len) : 0;
++}
++
++static void ext4_sb_release(struct kobject *kobj)
++{
++	struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info,
++						s_kobj);
++	complete(&sbi->s_kobj_unregister);
++}
++
++static const struct sysfs_ops ext4_attr_ops = {
++	.show	= ext4_attr_show,
++	.store	= ext4_attr_store,
++};
++
++static struct kobj_type ext4_sb_ktype = {
++	.default_attrs	= ext4_attrs,
++	.sysfs_ops	= &ext4_attr_ops,
++	.release	= ext4_sb_release,
++};
++
++static struct kobj_type ext4_ktype = {
++	.sysfs_ops	= &ext4_attr_ops,
++};
++
++static struct kset ext4_kset = {
++	.kobj   = {.ktype = &ext4_ktype},
++};
++
++static ssize_t ext4_feat_show(struct kobject *kobj,
++			      struct attribute *attr, char *buf)
++{
++	return snprintf(buf, PAGE_SIZE, "supported\n");
++}
++
++/*
++ * We can not use ext4_attr_show/store because it relies on the kobject
++ * being embedded in the ext4_sb_info structure which is definitely not
++ * true in this case.
++ */
++static const struct sysfs_ops ext4_feat_ops = {
++	.show	= ext4_feat_show,
++	.store	= NULL,
++};
++
++static struct kobj_type ext4_feat_ktype = {
++	.default_attrs	= ext4_feat_attrs,
++	.sysfs_ops	= &ext4_feat_ops,
++};
++
++static struct kobject ext4_feat = {
++	.kset	= &ext4_kset,
++};
++
++int ext4_register_sysfs(struct super_block *sb)
++{
++	struct ext4_sb_info *sbi = EXT4_SB(sb);
++
++	sbi->s_kobj.kset = &ext4_kset;
++	init_completion(&sbi->s_kobj_unregister);
++	return kobject_init_and_add(&sbi->s_kobj, &ext4_sb_ktype, NULL,
++				    "%s", sb->s_id);
++}
++
++int __init ext4_init_sysfs(void)
++{
++	int ret;
++
++	kobject_set_name(&ext4_kset.kobj, "ext4");
++	ext4_kset.kobj.parent = fs_kobj;
++	ret = kset_register(&ext4_kset);
++	if (ret)
++		return ret;
++
++	ret = kobject_init_and_add(&ext4_feat, &ext4_feat_ktype,
++				   NULL, "features");
++	if (ret)
++		kset_unregister(&ext4_kset);
++	return ret;
++}
++
++void ext4_exit_sysfs(void)
++{
++	kobject_put(&ext4_feat);
++	kset_unregister(&ext4_kset);
++}
++

commit bdfe0cbd746aa9b2509c2f6d6be17193cf7facd7
+Author: Theodore Ts'o 
+Date:   Sun Aug 16 10:03:57 2015 -0400
+
+    Revert "ext4: remove block_device_ejected"
+    
+    This reverts commit 08439fec266c3cc5702953b4f54bdf5649357de0.
+    
+    Unfortunately we still need to test for bdi->dev to avoid a crash when a
+    USB stick is yanked out while a file system is mounted:
+    
+       usb 2-2: USB disconnect, device number 2
+       Buffer I/O error on dev sdb1, logical block 15237120, lost sync page write
+       JBD2: Error -5 detected when updating journal superblock for sdb1-8.
+       BUG: unable to handle kernel paging request at 34beb000
+       IP: [] __percpu_counter_add+0x18/0xc0
+       *pdpt = 0000000023db9001 *pde = 0000000000000000
+       Oops: 0000 [#1] SMP
+       CPU: 0 PID: 4083 Comm: umount Tainted: G     U     OE   4.1.1-040101-generic #201507011435
+       Hardware name: LENOVO 7675CTO/7675CTO, BIOS 7NETC2WW (2.22 ) 03/22/2011
+       task: ebf06b50 ti: ebebc000 task.ti: ebebc000
+       EIP: 0060:[] EFLAGS: 00010082 CPU: 0
+       EIP is at __percpu_counter_add+0x18/0xc0
+       EAX: f21c8e88 EBX: f21c8e88 ECX: 00000000 EDX: 00000001
+       ESI: 00000001 EDI: 00000000 EBP: ebebde60 ESP: ebebde40
+        DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
+       CR0: 8005003b CR2: 34beb000 CR3: 33354200 CR4: 000007f0
+       Stack:
+        c1abe100 edcb0098 edcb00ec ffffffff f21c8e68 ffffffff f21c8e68 f286d160
+        ebebde84 c1160454 00000010 00000282 f72a77f8 00000984 f72a77f8 f286d160
+        f286d170 ebebdea0 c11e613f 00000000 00000282 f72a77f8 edd7f4d0 00000000
+       Call Trace:
+        [] account_page_dirtied+0x74/0x110
+        [] __set_page_dirty+0x3f/0xb0
+        [] mark_buffer_dirty+0x53/0xc0
+        [] ext4_commit_super+0x17b/0x250
+        [] ext4_put_super+0xc1/0x320
+        [] ? fsnotify_unmount_inodes+0x1aa/0x1c0
+        [] ? evict_inodes+0xca/0xe0
+        [] generic_shutdown_super+0x6a/0xe0
+        [] ? prepare_to_wait_event+0xd0/0xd0
+        [] ? unregister_shrinker+0x40/0x50
+        [] kill_block_super+0x26/0x70
+        [] deactivate_locked_super+0x45/0x80
+        [] deactivate_super+0x47/0x60
+        [] cleanup_mnt+0x39/0x80
+        [] __cleanup_mnt+0x10/0x20
+        [] task_work_run+0x91/0xd0
+        [] do_notify_resume+0x7c/0x90
+        [] work_notify
+       Code: 8b 55 e8 e9 f4 fe ff ff 90 90 90 90 90 90 90 90 90 90 90 55 89 e5 83 ec 20 89 5d f4 89 c3 89 75 f8 89 d6 89 7d fc 89 cf 8b 48 14 <64> 8b 01 89 45 ec 89 c2 8b 45 08 c1 fa 1f 01 75 ec 89 55 f0 89
+       EIP: [] __percpu_counter_add+0x18/0xc0 SS:ESP 0068:ebebde40
+       CR2: 0000000034beb000
+       ---[ end trace dd564a7bea834ecd ]---
+    
+    Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=101011
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 45658c1bc324..bd3ff923dd59 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -326,6 +326,22 @@ static void save_error_info(struct super_block *sb, const char *func,
+ 	ext4_commit_super(sb, 1);
+ }
+ 
++/*
++ * The del_gendisk() function uninitializes the disk-specific data
++ * structures, including the bdi structure, without telling anyone
++ * else.  Once this happens, any attempt to call mark_buffer_dirty()
++ * (for example, by ext4_commit_super), will cause a kernel OOPS.
++ * This is a kludge to prevent these oops until we can put in a proper
++ * hook in del_gendisk() to inform the VFS and file system layers.
++ */
++static int block_device_ejected(struct super_block *sb)
++{
++	struct inode *bd_inode = sb->s_bdev->bd_inode;
++	struct backing_dev_info *bdi = inode_to_bdi(bd_inode);
++
++	return bdi->dev == NULL;
++}
++
+ static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn)
+ {
+ 	struct super_block		*sb = journal->j_private;
+@@ -4621,7 +4637,7 @@ static int ext4_commit_super(struct super_block *sb, int sync)
+ 	struct buffer_head *sbh = EXT4_SB(sb)->s_sbh;
+ 	int error = 0;
+ 
+-	if (!sbh)
++	if (!sbh || block_device_ejected(sb))
+ 		return error;
+ 	if (buffer_write_io_error(sbh)) {
+ 		/*

commit e294a5371b2e0bd22d4a917d4c354a52a7057b6e
+Author: Theodore Ts'o 
+Date:   Sat Aug 15 14:59:44 2015 -0400
+
+    ext4: ratelimit the file system mounted message
+    
+    The xfstests ext4/305 will mount and unmount the same file system over
+    4,000 times, and each one of these will cause a system log message.
+    Ratelimit this message since if we are getting more than a few dozen
+    of these messages, they probably aren't going to be helpful.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 70c52ea0a27c..45658c1bc324 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -60,6 +60,7 @@ static struct ext4_lazy_init *ext4_li_info;
+ static struct mutex ext4_li_mtx;
+ static struct ext4_features *ext4_feat;
+ static int ext4_mballoc_ready;
++static struct ratelimit_state ext4_mount_msg_ratelimit;
+ 
+ static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
+ 			     unsigned long journal_devnum);
+@@ -4277,9 +4278,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 				 "the device does not support discard");
+ 	}
+ 
+-	ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. "
+-		 "Opts: %s%s%s", descr, sbi->s_es->s_mount_opts,
+-		 *sbi->s_es->s_mount_opts ? "; " : "", orig_data);
++	if (___ratelimit(&ext4_mount_msg_ratelimit, "EXT4-fs mount"))
++		ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. "
++			 "Opts: %s%s%s", descr, sbi->s_es->s_mount_opts,
++			 *sbi->s_es->s_mount_opts ? "; " : "", orig_data);
+ 
+ 	if (es->s_error_count)
+ 		mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */
+@@ -5617,6 +5619,7 @@ static int __init ext4_init_fs(void)
+ {
+ 	int i, err;
+ 
++	ratelimit_state_init(&ext4_mount_msg_ratelimit, 30 * HZ, 64);
+ 	ext4_li_info = NULL;
+ 	mutex_init(&ext4_li_mtx);
+ 

commit 27977b69e493c9b259eb0490534e0f74bc325ba8
+Author: Theodore Ts'o 
+Date:   Fri Jul 17 11:33:16 2015 -0400
+
+    ext4 crypto: check for too-short encrypted file names
+    
+    An encrypted file name should never be shorter than an 16 bytes, the
+    AES block size.  The 3.10 crypto layer will oops and crash the kernel
+    if ciphertext shorter than the block size is passed to it.
+    
+    Fortunately, in modern kernels the crypto layer will not crash the
+    kernel in this scenario, but nevertheless, it represents a corrupted
+    directory, and we should detect it and mark the file system as
+    corrupted so that e2fsck can fix this.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/crypto_fname.c b/fs/ext4/crypto_fname.c
+index 7dc4eb55913c..86ee996a2bd4 100644
+--- a/fs/ext4/crypto_fname.c
++++ b/fs/ext4/crypto_fname.c
+@@ -329,6 +329,10 @@ int _ext4_fname_disk_to_usr(struct inode *inode,
+ 			return oname->len;
+ 		}
+ 	}
++	if (iname->len < EXT4_CRYPTO_BLOCK_SIZE) {
++		EXT4_ERROR_INODE(inode, "encrypted inode too small");
++		return -EUCLEAN;
++	}
+ 	if (EXT4_I(inode)->i_crypt_info)
+ 		return ext4_fname_decrypt(inode, iname, oname);
+ 

commit 806c24adf74ec02543e4dcad989c0336f9fe82c4
+Author: Theodore Ts'o 
+Date:   Fri Jul 17 11:16:47 2015 -0400
+
+    ext4 crypto: use a jbd2 transaction when adding a crypto policy
+    
+    Start a jbd2 transaction, and mark the inode dirty on the inode under
+    that transaction after setting the encrypt flag.  Otherwise if the
+    directory isn't modified after setting the crypto policy, the
+    encrypted flag might not survive the inode getting pushed out from
+    memory, or the the file system getting unmounted and remounted.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/crypto_policy.c b/fs/ext4/crypto_policy.c
+index 02c4e5df7afb..a640ec2c4b13 100644
+--- a/fs/ext4/crypto_policy.c
++++ b/fs/ext4/crypto_policy.c
+@@ -12,6 +12,7 @@
+ #include 
+ #include 
+ 
++#include "ext4_jbd2.h"
+ #include "ext4.h"
+ #include "xattr.h"
+ 
+@@ -49,7 +50,8 @@ static int ext4_create_encryption_context_from_policy(
+ 	struct inode *inode, const struct ext4_encryption_policy *policy)
+ {
+ 	struct ext4_encryption_context ctx;
+-	int res = 0;
++	handle_t *handle;
++	int res, res2;
+ 
+ 	res = ext4_convert_inline_data(inode);
+ 	if (res)
+@@ -78,11 +80,22 @@ static int ext4_create_encryption_context_from_policy(
+ 	BUILD_BUG_ON(sizeof(ctx.nonce) != EXT4_KEY_DERIVATION_NONCE_SIZE);
+ 	get_random_bytes(ctx.nonce, EXT4_KEY_DERIVATION_NONCE_SIZE);
+ 
++	handle = ext4_journal_start(inode, EXT4_HT_MISC,
++				    ext4_jbd2_credits_xattr(inode));
++	if (IS_ERR(handle))
++		return PTR_ERR(handle);
+ 	res = ext4_xattr_set(inode, EXT4_XATTR_INDEX_ENCRYPTION,
+ 			     EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, &ctx,
+ 			     sizeof(ctx), 0);
+-	if (!res)
++	if (!res) {
+ 		ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
++		res = ext4_mark_inode_dirty(handle, inode);
++		if (res)
++			EXT4_ERROR_INODE(inode, "Failed to mark inode dirty");
++	}
++	res2 = ext4_journal_stop(handle);
++	if (!res)
++		res = res2;
+ 	return res;
+ }
+ 

commit 0f0ff9a9f3fa2ec6f427603fd521d5f3a0b076d1
+Author: Theodore Ts'o 
+Date:   Wed Jul 1 23:37:46 2015 -0400
+
+    ext4: fix fencepost error in lazytime optimization
+    
+    Commit 8f4d8558391: "ext4: fix lazytime optimization" was not a
+    complete fix.  In the case where the inode number is a multiple of 16,
+    and we could still end up updating an inode with dirty timestamps
+    written to the wrong inode on disk.  Oops.
+    
+    This can be easily reproduced by using generic/005 with a file system
+    with metadata_csum and lazytime enabled.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index e057c6fcc227..4ad73d3c1003 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4348,7 +4348,12 @@ static void ext4_update_other_inodes_time(struct super_block *sb,
+ 	int inode_size = EXT4_INODE_SIZE(sb);
+ 
+ 	oi.orig_ino = orig_ino;
+-	ino = (orig_ino & ~(inodes_per_block - 1)) + 1;
++	/*
++	 * Calculate the first inode in the inode table block.  Inode
++	 * numbers are one-based.  That is, the first inode in a block
++	 * (assuming 4k blocks and 256 byte inodes) is (n*16 + 1).
++	 */
++	ino = ((orig_ino - 1) & ~(inodes_per_block - 1)) + 1;
+ 	for (i = 0; i < inodes_per_block; i++, ino++, buf += inode_size) {
+ 		if (ino == orig_ino)
+ 			continue;

commit a2fd66d069d86d793e9d39d4079b96f46d13f237
+Author: Theodore Ts'o 
+Date:   Tue Jun 23 11:03:54 2015 -0400
+
+    ext4: set lazytime on remount if MS_LAZYTIME is set by mount
+    
+    Newer versions of mount parse the lazytime feature and pass it to the
+    mount system call via the flags field in the mount system call,
+    removing the lazytime string from the mount options list.  So we need
+    to check for the presence of MS_LAZYTIME and set it in sb->s_flags in
+    order for this flag to be set on a remount.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index bd4df9d379b2..90ec13fe8ac7 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4971,6 +4971,9 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 		set_task_ioprio(sbi->s_journal->j_task, journal_ioprio);
+ 	}
+ 
++	if (*flags & MS_LAZYTIME)
++		sb->s_flags |= MS_LAZYTIME;
++
+ 	if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY)) {
+ 		if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED) {
+ 			err = -EROFS;

commit c5e298ae53dc2eb69f2f7153be03454c8a33c658
+Author: Theodore Ts'o 
+Date:   Sun Jun 21 01:25:29 2015 -0400
+
+    ext4: prevent ext4_quota_write() from failing due to ENOSPC
+    
+    In order to prevent quota block tracking to be inaccurate when
+    ext4_quota_write() fails with ENOSPC, we make two changes.  The quota
+    file can now use the reserved block (since the quota file is arguably
+    file system metadata), and ext4_quota_write() now uses
+    ext4_should_retry_alloc() to retry the block allocation after a commit
+    has completed and released some blocks for allocation.
+    
+    This fixes failures of xfstests generic/270:
+    
+    Quota error (device vdc): write_blk: dquota write failed
+    Quota error (device vdc): qtree_write_dquot: Error -28 occurred while creating quota
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 1ba8b4ab03a8..d86d2622f826 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -4456,6 +4456,8 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 		ar.flags |= EXT4_MB_HINT_NOPREALLOC;
+ 	if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
+ 		ar.flags |= EXT4_MB_DELALLOC_RESERVED;
++	if (flags & EXT4_GET_BLOCKS_METADATA_NOFAIL)
++		ar.flags |= EXT4_MB_USE_RESERVED;
+ 	newblock = ext4_mb_new_blocks(handle, &ar, &err);
+ 	if (!newblock)
+ 		goto out2;
+diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
+index 958824019509..9962d577bad5 100644
+--- a/fs/ext4/indirect.c
++++ b/fs/ext4/indirect.c
+@@ -576,6 +576,8 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
+ 		ar.flags = EXT4_MB_HINT_DATA;
+ 	if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
+ 		ar.flags |= EXT4_MB_DELALLOC_RESERVED;
++	if (flags & EXT4_GET_BLOCKS_METADATA_NOFAIL)
++		ar.flags |= EXT4_MB_USE_RESERVED;
+ 
+ 	ar.goal = ext4_find_goal(inode, map->m_lblk, partial);
+ 
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 263a46c488c7..e8a67b8ba90c 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -731,18 +731,18 @@ int ext4_get_block(struct inode *inode, sector_t iblock,
+  * `handle' can be NULL if create is zero
+  */
+ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
+-				ext4_lblk_t block, int create)
++				ext4_lblk_t block, int map_flags)
+ {
+ 	struct ext4_map_blocks map;
+ 	struct buffer_head *bh;
++	int create = map_flags & EXT4_GET_BLOCKS_CREATE;
+ 	int err;
+ 
+ 	J_ASSERT(handle != NULL || create == 0);
+ 
+ 	map.m_lblk = block;
+ 	map.m_len = 1;
+-	err = ext4_map_blocks(handle, inode, &map,
+-			      create ? EXT4_GET_BLOCKS_CREATE : 0);
++	err = ext4_map_blocks(handle, inode, &map, map_flags);
+ 
+ 	if (err == 0)
+ 		return create ? ERR_PTR(-ENOSPC) : NULL;
+@@ -788,11 +788,11 @@ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
+ }
+ 
+ struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode,
+-			       ext4_lblk_t block, int create)
++			       ext4_lblk_t block, int map_flags)
+ {
+ 	struct buffer_head *bh;
+ 
+-	bh = ext4_getblk(handle, inode, block, create);
++	bh = ext4_getblk(handle, inode, block, map_flags);
+ 	if (IS_ERR(bh))
+ 		return bh;
+ 	if (!bh || buffer_uptodate(bh))
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 5e7676f1e82f..e230b31251f7 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -61,7 +61,7 @@ static struct buffer_head *ext4_append(handle_t *handle,
+ 
+ 	*block = inode->i_size >> inode->i_sb->s_blocksize_bits;
+ 
+-	bh = ext4_bread(handle, inode, *block, 1);
++	bh = ext4_bread(handle, inode, *block, EXT4_GET_BLOCKS_CREATE);
+ 	if (IS_ERR(bh))
+ 		return bh;
+ 	inode->i_size += inode->i_sb->s_blocksize;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 2858ac09f5a3..bd4df9d379b2 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -5438,6 +5438,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
+ 	struct inode *inode = sb_dqopt(sb)->files[type];
+ 	ext4_lblk_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb);
+ 	int err, offset = off & (sb->s_blocksize - 1);
++	int retries = 0;
+ 	struct buffer_head *bh;
+ 	handle_t *handle = journal_current_handle();
+ 
+@@ -5458,7 +5459,12 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
+ 		return -EIO;
+ 	}
+ 
+-	bh = ext4_bread(handle, inode, blk, 1);
++	do {
++		bh = ext4_bread(handle, inode, blk,
++				EXT4_GET_BLOCKS_CREATE |
++				EXT4_GET_BLOCKS_METADATA_NOFAIL);
++	} while (IS_ERR(bh) && (PTR_ERR(bh) == -ENOSPC) &&
++		 ext4_should_retry_alloc(inode->i_sb, &retries));
+ 	if (IS_ERR(bh))
+ 		return PTR_ERR(bh);
+ 	if (!bh)

commit 89d96a6f8e6491f24fc8f99fd6ae66820e85c6c1
+Author: Theodore Ts'o 
+Date:   Sat Jun 20 22:50:33 2015 -0400
+
+    ext4: call sync_blockdev() before invalidate_bdev() in put_super()
+    
+    Normally all of the buffers will have been forced out to disk before
+    we call invalidate_bdev(), but there will be some cases, where a file
+    system operation was aborted due to an ext4_error(), where there may
+    still be some dirty buffers in the buffer cache for the device.  So
+    try to force them out to memory before calling invalidate_bdev().
+    
+    This fixes a warning triggered by generic/081:
+    
+    WARNING: CPU: 1 PID: 3473 at /usr/projects/linux/ext4/fs/block_dev.c:56 __blkdev_put+0xb5/0x16f()
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index fdac076e0791..2858ac09f5a3 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -828,6 +828,7 @@ static void ext4_put_super(struct super_block *sb)
+ 		dump_orphan_list(sb, sbi);
+ 	J_ASSERT(list_empty(&sbi->s_orphan));
+ 
++	sync_blockdev(sb->s_bdev);
+ 	invalidate_bdev(sb->s_bdev);
+ 	if (sbi->journal_bdev && sbi->journal_bdev != sb->s_bdev) {
+ 		/*

commit bdf96838aea6a265f2ae6cbcfb12a778c84a0b8e
+Author: Theodore Ts'o 
+Date:   Fri Jun 12 23:45:33 2015 -0400
+
+    ext4: fix race between truncate and __ext4_journalled_writepage()
+    
+    The commit cf108bca465d: "ext4: Invert the locking order of page_lock
+    and transaction start" caused __ext4_journalled_writepage() to drop
+    the page lock before the page was written back, as part of changing
+    the locking order to jbd2_journal_start -> page_lock.  However, this
+    introduced a potential race if there was a truncate racing with the
+    data=journalled writeback mode.
+    
+    Fix this by grabbing the page lock after starting the journal handle,
+    and then checking to see if page had gotten truncated out from under
+    us.
+    
+    This fixes a number of different warnings or BUG_ON's when running
+    xfstests generic/086 in data=journalled mode, including:
+    
+    jbd2_journal_dirty_metadata: vdc-8: bad jh for block 115643: transaction (ee3fe7
+    c0, 164), jh->b_transaction (  (null), 0), jh->b_next_transaction (  (null), 0), jlist 0
+    
+                              - and -
+    
+    kernel BUG at /usr/projects/linux/ext4/fs/jbd2/transaction.c:2200!
+        ...
+    Call Trace:
+     [] ? __ext4_journalled_invalidatepage+0x117/0x117
+     [] __ext4_journalled_invalidatepage+0x10f/0x117
+     [] ? __ext4_journalled_invalidatepage+0x117/0x117
+     [] ? lock_buffer+0x36/0x36
+     [] ext4_journalled_invalidatepage+0xd/0x22
+     [] do_invalidatepage+0x22/0x26
+     [] truncate_inode_page+0x5b/0x85
+     [] truncate_inode_pages_range+0x156/0x38c
+     [] truncate_inode_pages+0x11/0x15
+     [] truncate_pagecache+0x55/0x71
+     [] ext4_setattr+0x4a9/0x560
+     [] ? current_kernel_time+0x10/0x44
+     [] notify_change+0x1c7/0x2be
+     [] do_truncate+0x65/0x85
+     [] ? file_ra_state_init+0x12/0x29
+    
+                              - and -
+    
+    WARNING: CPU: 1 PID: 1331 at /usr/projects/linux/ext4/fs/jbd2/transaction.c:1396
+    irty_metadata+0x14a/0x1ae()
+        ...
+    Call Trace:
+     [] ? console_unlock+0x3a1/0x3ce
+     [] dump_stack+0x48/0x60
+     [] warn_slowpath_common+0x89/0xa0
+     [] ? jbd2_journal_dirty_metadata+0x14a/0x1ae
+     [] warn_slowpath_null+0x14/0x18
+     [] jbd2_journal_dirty_metadata+0x14a/0x1ae
+     [] __ext4_handle_dirty_metadata+0xd4/0x19d
+     [] write_end_fn+0x40/0x53
+     [] ext4_walk_page_buffers+0x4e/0x6a
+     [] ext4_writepage+0x354/0x3b8
+     [] ? mpage_release_unused_pages+0xd4/0xd4
+     [] ? wait_on_buffer+0x2c/0x2c
+     [] ? ext4_writepage+0x3b8/0x3b8
+     [] __writepage+0x10/0x2e
+     [] write_cache_pages+0x22d/0x32c
+     [] ? ext4_writepage+0x3b8/0x3b8
+     [] ext4_writepages+0x102/0x607
+     [] ? sched_clock_local+0x10/0x10e
+     [] ? __lock_is_held+0x2e/0x44
+     [] ? lock_is_held+0x43/0x51
+     [] do_writepages+0x1c/0x29
+     [] __writeback_single_inode+0xc3/0x545
+     [] writeback_sb_inodes+0x21f/0x36d
+        ...
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 0554b0b5957b..263a46c488c7 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1701,19 +1701,32 @@ static int __ext4_journalled_writepage(struct page *page,
+ 		ext4_walk_page_buffers(handle, page_bufs, 0, len,
+ 				       NULL, bget_one);
+ 	}
+-	/* As soon as we unlock the page, it can go away, but we have
+-	 * references to buffers so we are safe */
++	/*
++	 * We need to release the page lock before we start the
++	 * journal, so grab a reference so the page won't disappear
++	 * out from under us.
++	 */
++	get_page(page);
+ 	unlock_page(page);
+ 
+ 	handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE,
+ 				    ext4_writepage_trans_blocks(inode));
+ 	if (IS_ERR(handle)) {
+ 		ret = PTR_ERR(handle);
+-		goto out;
++		put_page(page);
++		goto out_no_pagelock;
+ 	}
+-
+ 	BUG_ON(!ext4_handle_valid(handle));
+ 
++	lock_page(page);
++	put_page(page);
++	if (page->mapping != mapping) {
++		/* The page got truncated from under us */
++		ext4_journal_stop(handle);
++		ret = 0;
++		goto out;
++	}
++
+ 	if (inline_data) {
+ 		BUFFER_TRACE(inode_bh, "get write access");
+ 		ret = ext4_journal_get_write_access(handle, inode_bh);
+@@ -1739,6 +1752,8 @@ static int __ext4_journalled_writepage(struct page *page,
+ 				       NULL, bput_one);
+ 	ext4_set_inode_state(inode, EXT4_STATE_JDATA);
+ out:
++	unlock_page(page);
++out_no_pagelock:
+ 	brelse(inode_bh);
+ 	return ret;
+ }

commit 1cb767cd4a79703105f4f3774c76896d621fdc54
+Author: Theodore Ts'o 
+Date:   Fri Jun 12 23:44:33 2015 -0400
+
+    ext4 crypto: fail the mount if blocksize != pagesize
+    
+    We currently don't correctly handle the case where blocksize !=
+    pagesize, so disallow the mount in those cases.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 31e85bea9652..e13fe40d4a51 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4065,7 +4065,15 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		}
+ 	}
+ 
+-	if (unlikely(sbi->s_mount_flags & EXT4_MF_TEST_DUMMY_ENCRYPTION) &&
++	if ((DUMMY_ENCRYPTION_ENABLED(sbi) ||
++	     EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT)) &&
++	    (blocksize != PAGE_CACHE_SIZE)) {
++		ext4_msg(sb, KERN_ERR,
++			 "Unsupported blocksize for fs encryption");
++		goto failed_mount_wq;
++	}
++
++	if (DUMMY_ENCRYPTION_ENABLED(sbi) &&
+ 	    !(sb->s_flags & MS_RDONLY) &&
+ 	    !EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT)) {
+ 		EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT);

commit ad0a0ce894d554b112afab6a48fd500e636686a6
+Author: Theodore Ts'o 
+Date:   Mon Jun 8 11:54:56 2015 -0400
+
+    ext4 crypto: fix ext4_get_crypto_ctx()'s calling convention in ext4_decrypt_one
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
+index f5c82e8b7b5c..45731558138c 100644
+--- a/fs/ext4/crypto.c
++++ b/fs/ext4/crypto.c
+@@ -396,8 +396,8 @@ int ext4_decrypt_one(struct inode *inode, struct page *page)
+ 
+ 	struct ext4_crypto_ctx *ctx = ext4_get_crypto_ctx(inode);
+ 
+-	if (!ctx)
+-		return -ENOMEM;
++	if (IS_ERR(ctx))
++		return PTR_ERR(ctx);
+ 	ret = ext4_decrypt(ctx, page);
+ 	ext4_release_crypto_ctx(ctx);
+ 	return ret;

commit 3dbb5eb9a3aa04f40e551338eee5e8d06f352fe8
+Author: Theodore Ts'o 
+Date:   Wed Jun 3 09:32:39 2015 -0400
+
+    ext4 crypto: allocate bounce pages using GFP_NOWAIT
+    
+    Previously we allocated bounce pages using a combination of
+    alloc_page() and mempool_alloc() with the __GFP_WAIT bit set.
+    Instead, use mempool_alloc() with GFP_NOWAIT.  The mempool_alloc()
+    function will try using alloc_pages() initially, and then only use the
+    mempool reserve of pages if alloc_pages() is unable to fulfill the
+    request.
+    
+    This minimizes the the impact on the mm layer when we need to do a
+    large amount of writeback of encrypted files, as Jaeguk Kim had
+    reported that under a heavy fio workload on a system with restricted
+    amounts memory (which unfortunately, includes many mobile handsets),
+    he had observed the the OOM killer getting triggered several times.
+    Using GFP_NOWAIT
+    
+    If the mempool_alloc() function fails, we will retry the page
+    writeback at a later time; the function of the mempool is to ensure
+    that we can writeback at least 32 pages at a time, so we can more
+    efficiently dispatch I/O under high memory pressure situations.  In
+    the future we should make this be a tunable so we can determine the
+    best tradeoff between permanently sequestering memory and the ability
+    to quickly launder pages so we can free up memory quickly when
+    necessary.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
+index efcb7c04d172..f5c82e8b7b5c 100644
+--- a/fs/ext4/crypto.c
++++ b/fs/ext4/crypto.c
+@@ -71,12 +71,8 @@ void ext4_release_crypto_ctx(struct ext4_crypto_ctx *ctx)
+ {
+ 	unsigned long flags;
+ 
+-	if (ctx->flags & EXT4_WRITE_PATH_FL && ctx->w.bounce_page) {
+-		if (ctx->flags & EXT4_BOUNCE_PAGE_REQUIRES_FREE_ENCRYPT_FL)
+-			__free_page(ctx->w.bounce_page);
+-		else
+-			mempool_free(ctx->w.bounce_page, ext4_bounce_page_pool);
+-	}
++	if (ctx->flags & EXT4_WRITE_PATH_FL && ctx->w.bounce_page)
++		mempool_free(ctx->w.bounce_page, ext4_bounce_page_pool);
+ 	ctx->w.bounce_page = NULL;
+ 	ctx->w.control_page = NULL;
+ 	if (ctx->flags & EXT4_CTX_REQUIRES_FREE_ENCRYPT_FL) {
+@@ -317,22 +313,11 @@ static int ext4_page_crypto(struct ext4_crypto_ctx *ctx,
+ 
+ static struct page *alloc_bounce_page(struct ext4_crypto_ctx *ctx)
+ {
+-	struct page *ciphertext_page = alloc_page(GFP_NOFS);
+-
+-	if (!ciphertext_page) {
+-		/* This is a potential bottleneck, but at least we'll have
+-		 * forward progress. */
+-		ciphertext_page = mempool_alloc(ext4_bounce_page_pool,
+-						 GFP_NOFS);
+-		if (ciphertext_page == NULL)
+-			return ERR_PTR(-ENOMEM);
+-		ctx->flags &= ~EXT4_BOUNCE_PAGE_REQUIRES_FREE_ENCRYPT_FL;
+-	} else {
+-		ctx->flags |= EXT4_BOUNCE_PAGE_REQUIRES_FREE_ENCRYPT_FL;
+-	}
++	ctx->w.bounce_page = mempool_alloc(ext4_bounce_page_pool, GFP_NOWAIT);
++	if (ctx->w.bounce_page == NULL)
++		return ERR_PTR(-ENOMEM);
+ 	ctx->flags |= EXT4_WRITE_PATH_FL;
+-	ctx->w.bounce_page = ciphertext_page;
+-	return ciphertext_page;
++	return ctx->w.bounce_page;
+ }
+ 
+ /**
+diff --git a/fs/ext4/ext4_crypto.h b/fs/ext4/ext4_crypto.h
+index 34e0d2455881..ac7d4e813796 100644
+--- a/fs/ext4/ext4_crypto.h
++++ b/fs/ext4/ext4_crypto.h
+@@ -83,8 +83,7 @@ struct ext4_crypt_info {
+ };
+ 
+ #define EXT4_CTX_REQUIRES_FREE_ENCRYPT_FL             0x00000001
+-#define EXT4_BOUNCE_PAGE_REQUIRES_FREE_ENCRYPT_FL     0x00000002
+-#define EXT4_WRITE_PATH_FL			      0x00000004
++#define EXT4_WRITE_PATH_FL			      0x00000002
+ 
+ struct ext4_crypto_ctx {
+ 	union {

commit abdd438b26b409eaccf9c847fcf9c3ab52f1959e
+Author: Theodore Ts'o 
+Date:   Sun May 31 13:35:39 2015 -0400
+
+    ext4 crypto: handle unexpected lack of encryption keys
+    
+    Fix up attempts by users to try to write to a file when they don't
+    have access to the encryption key.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
+index 1c9a8c499369..efcb7c04d172 100644
+--- a/fs/ext4/crypto.c
++++ b/fs/ext4/crypto.c
+@@ -104,7 +104,8 @@ struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode)
+ 	unsigned long flags;
+ 	struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
+ 
+-	BUG_ON(ci == NULL);
++	if (ci == NULL)
++		return ERR_PTR(-ENOKEY);
+ 
+ 	/*
+ 	 * We first try getting the ctx from a free list because in
+diff --git a/fs/ext4/crypto_policy.c b/fs/ext4/crypto_policy.c
+index a1d434d0dea8..02c4e5df7afb 100644
+--- a/fs/ext4/crypto_policy.c
++++ b/fs/ext4/crypto_policy.c
+@@ -183,7 +183,8 @@ int ext4_inherit_context(struct inode *parent, struct inode *child)
+ 	if (res < 0)
+ 		return res;
+ 	ci = EXT4_I(parent)->i_crypt_info;
+-	BUG_ON(ci == NULL);
++	if (ci == NULL)
++		return -ENOKEY;
+ 
+ 	ctx.format = EXT4_ENCRYPTION_CONTEXT_FORMAT_V1;
+ 	if (DUMMY_ENCRYPTION_ENABLED(EXT4_SB(parent->i_sb))) {
+diff --git a/fs/ext4/file.c b/fs/ext4/file.c
+index 875ca6b95a4b..ac517f15741c 100644
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -226,6 +226,8 @@ static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma)
+ 		int err = ext4_get_encryption_info(inode);
+ 		if (err)
+ 			return 0;
++		if (ext4_encryption_info(inode) == NULL)
++			return -ENOKEY;
+ 	}
+ 	file_accessed(file);
+ 	if (IS_DAX(file_inode(file))) {
+@@ -278,6 +280,13 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
+ 			ext4_journal_stop(handle);
+ 		}
+ 	}
++	if (ext4_encrypted_inode(inode)) {
++		ret = ext4_get_encryption_info(inode);
++		if (ret)
++			return -EACCES;
++		if (ext4_encryption_info(inode) == NULL)
++			return -ENOKEY;
++	}
+ 	/*
+ 	 * Set up the jbd2_inode if we are opening the inode for
+ 	 * writing and the journal is present
+@@ -287,13 +296,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
+ 		if (ret < 0)
+ 			return ret;
+ 	}
+-	ret = dquot_file_open(inode, filp);
+-	if (!ret && ext4_encrypted_inode(inode)) {
+-		ret = ext4_get_encryption_info(inode);
+-		if (ret)
+-			ret = -EACCES;
+-	}
+-	return ret;
++	return dquot_file_open(inode, filp);
+ }
+ 
+ /*

commit 4d3c4e5b8cae3bb45ba933a22670504239958aa1
+Author: Theodore Ts'o 
+Date:   Sun May 31 13:35:32 2015 -0400
+
+    ext4 crypto: allocate the right amount of memory for the on-disk symlink
+    
+    Previously we were taking the required padding when allocating space
+    for the on-disk symlink.  This caused a buffer overrun which could
+    trigger a krenel crash when running fsstress.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/crypto_fname.c b/fs/ext4/crypto_fname.c
+index 23af41f73e90..7dc4eb55913c 100644
+--- a/fs/ext4/crypto_fname.c
++++ b/fs/ext4/crypto_fname.c
+@@ -262,8 +262,20 @@ u32 ext4_fname_crypto_round_up(u32 size, u32 blksize)
+ 	return ((size+blksize-1)/blksize)*blksize;
+ }
+ 
+-/**
+- * ext4_fname_crypto_alloc_obuff() -
++unsigned ext4_fname_encrypted_size(struct inode *inode, u32 ilen)
++{
++	struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
++	int padding = 32;
++
++	if (ci)
++		padding = 4 << (ci->ci_flags & EXT4_POLICY_FLAGS_PAD_MASK);
++	if (ilen < EXT4_CRYPTO_BLOCK_SIZE)
++		ilen = EXT4_CRYPTO_BLOCK_SIZE;
++	return ext4_fname_crypto_round_up(ilen, padding);
++}
++
++/*
++ * ext4_fname_crypto_alloc_buffer() -
+  *
+  * Allocates an output buffer that is sufficient for the crypto operation
+  * specified by the context and the direction.
+@@ -271,15 +283,8 @@ u32 ext4_fname_crypto_round_up(u32 size, u32 blksize)
+ int ext4_fname_crypto_alloc_buffer(struct inode *inode,
+ 				   u32 ilen, struct ext4_str *crypto_str)
+ {
+-	unsigned int olen;
+-	int padding = 16;
+-	struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
++	unsigned int olen = ext4_fname_encrypted_size(inode, ilen);
+ 
+-	if (ci)
+-		padding = 4 << (ci->ci_flags & EXT4_POLICY_FLAGS_PAD_MASK);
+-	if (padding < EXT4_CRYPTO_BLOCK_SIZE)
+-		padding = EXT4_CRYPTO_BLOCK_SIZE;
+-	olen = ext4_fname_crypto_round_up(ilen, padding);
+ 	crypto_str->len = olen;
+ 	if (olen < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2)
+ 		olen = EXT4_FNAME_CRYPTO_DIGEST_SIZE*2;
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index bd8d32d5214d..730c88d1b220 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2090,6 +2090,7 @@ static inline int ext4_sb_has_crypto(struct super_block *sb)
+ /* crypto_fname.c */
+ bool ext4_valid_filenames_enc_mode(uint32_t mode);
+ u32 ext4_fname_crypto_round_up(u32 size, u32 blksize);
++unsigned ext4_fname_encrypted_size(struct inode *inode, u32 ilen);
+ int ext4_fname_crypto_alloc_buffer(struct inode *inode,
+ 				   u32 ilen, struct ext4_str *crypto_str);
+ int _ext4_fname_disk_to_usr(struct inode *inode,
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 401b099e3af3..bda4a5d6f5a5 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -3039,10 +3039,23 @@ static int ext4_symlink(struct inode *dir,
+ 
+ 	encryption_required = (ext4_encrypted_inode(dir) ||
+ 			       DUMMY_ENCRYPTION_ENABLED(EXT4_SB(dir->i_sb)));
+-	if (encryption_required)
+-		disk_link.len = encrypted_symlink_data_len(len) + 1;
+-	if (disk_link.len > dir->i_sb->s_blocksize)
+-		return -ENAMETOOLONG;
++	if (encryption_required) {
++		err = ext4_get_encryption_info(dir);
++		if (err)
++			return err;
++		if (ext4_encryption_info(dir) == NULL)
++			return -EPERM;
++		disk_link.len = (ext4_fname_encrypted_size(dir, len) +
++				 sizeof(struct ext4_encrypted_symlink_data));
++		sd = kzalloc(disk_link.len, GFP_KERNEL);
++		if (!sd)
++			return -ENOMEM;
++	}
++
++	if (disk_link.len > dir->i_sb->s_blocksize) {
++		err = -ENAMETOOLONG;
++		goto err_free_sd;
++	}
+ 
+ 	dquot_initialize(dir);
+ 
+@@ -3073,18 +3086,14 @@ static int ext4_symlink(struct inode *dir,
+ 	if (IS_ERR(inode)) {
+ 		if (handle)
+ 			ext4_journal_stop(handle);
+-		return PTR_ERR(inode);
++		err = PTR_ERR(inode);
++		goto err_free_sd;
+ 	}
+ 
+ 	if (encryption_required) {
+ 		struct qstr istr;
+ 		struct ext4_str ostr;
+ 
+-		sd = kzalloc(disk_link.len, GFP_NOFS);
+-		if (!sd) {
+-			err = -ENOMEM;
+-			goto err_drop_inode;
+-		}
+ 		istr.name = (const unsigned char *) symname;
+ 		istr.len = len;
+ 		ostr.name = sd->encrypted_path;
+@@ -3156,10 +3165,11 @@ static int ext4_symlink(struct inode *dir,
+ err_drop_inode:
+ 	if (handle)
+ 		ext4_journal_stop(handle);
+-	kfree(sd);
+ 	clear_nlink(inode);
+ 	unlock_new_inode(inode);
+ 	iput(inode);
++err_free_sd:
++	kfree(sd);
+ 	return err;
+ }
+ 

commit 82d0d3e7e69ab509b5c91b61f12bd3593a7c6dcb
+Author: Theodore Ts'o 
+Date:   Sun May 31 13:35:22 2015 -0400
+
+    ext4 crypto: clean up error handling in ext4_fname_setup_filename
+    
+    Fix a potential memory leak where fname->crypto_buf.name wouldn't get
+    freed in some error paths, and also make the error handling easier to
+    understand/audit.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/crypto_fname.c b/fs/ext4/crypto_fname.c
+index 29a2dc9a6f82..23af41f73e90 100644
+--- a/fs/ext4/crypto_fname.c
++++ b/fs/ext4/crypto_fname.c
+@@ -401,7 +401,7 @@ int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname,
+ 	      ((iname->name[1] == '.') && (iname->len == 2))))) {
+ 		fname->disk_name.name = (unsigned char *) iname->name;
+ 		fname->disk_name.len = iname->len;
+-		goto out;
++		return 0;
+ 	}
+ 	ret = ext4_get_encryption_info(dir);
+ 	if (ret)
+@@ -411,19 +411,16 @@ int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname,
+ 		ret = ext4_fname_crypto_alloc_buffer(dir, iname->len,
+ 						     &fname->crypto_buf);
+ 		if (ret < 0)
+-			goto out;
++			return ret;
+ 		ret = ext4_fname_encrypt(dir, iname, &fname->crypto_buf);
+ 		if (ret < 0)
+-			goto out;
++			goto errout;
+ 		fname->disk_name.name = fname->crypto_buf.name;
+ 		fname->disk_name.len = fname->crypto_buf.len;
+-		ret = 0;
+-		goto out;
+-	}
+-	if (!lookup) {
+-		ret = -EACCES;
+-		goto out;
++		return 0;
+ 	}
++	if (!lookup)
++		return -EACCES;
+ 
+ 	/* We don't have the key and we are doing a lookup; decode the
+ 	 * user-supplied name
+@@ -431,19 +428,17 @@ int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname,
+ 	if (iname->name[0] == '_')
+ 		bigname = 1;
+ 	if ((bigname && (iname->len != 33)) ||
+-	    (!bigname && (iname->len > 43))) {
+-		ret = -ENOENT;
+-	}
++	    (!bigname && (iname->len > 43)))
++		return -ENOENT;
++
+ 	fname->crypto_buf.name = kmalloc(32, GFP_KERNEL);
+-	if (fname->crypto_buf.name == NULL) {
+-		ret = -ENOMEM;
+-		goto out;
+-	}
++	if (fname->crypto_buf.name == NULL)
++		return -ENOMEM;
+ 	ret = digest_decode(iname->name + bigname, iname->len - bigname,
+ 			    fname->crypto_buf.name);
+ 	if (ret < 0) {
+ 		ret = -ENOENT;
+-		goto out;
++		goto errout;
+ 	}
+ 	fname->crypto_buf.len = ret;
+ 	if (bigname) {
+@@ -453,8 +448,10 @@ int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname,
+ 		fname->disk_name.name = fname->crypto_buf.name;
+ 		fname->disk_name.len = fname->crypto_buf.len;
+ 	}
+-	ret = 0;
+-out:
++	return 0;
++errout:
++	kfree(fname->crypto_buf.name);
++	fname->crypto_buf.name = NULL;
+ 	return ret;
+ }
+ 

commit d87f6d78e996bbba27b649c0e0eed7a37d6b73ba
+Author: Theodore Ts'o 
+Date:   Sun May 31 13:35:14 2015 -0400
+
+    ext4 crypto: policies may only be set on directories
+    
+    Thanks to Chao Yu  for pointing out we were
+    missing this check.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/crypto_policy.c b/fs/ext4/crypto_policy.c
+index 81980a158dc7..a1d434d0dea8 100644
+--- a/fs/ext4/crypto_policy.c
++++ b/fs/ext4/crypto_policy.c
+@@ -93,6 +93,8 @@ int ext4_process_policy(const struct ext4_encryption_policy *policy,
+ 		return -EINVAL;
+ 
+ 	if (!ext4_inode_has_encryption_context(inode)) {
++		if (!S_ISDIR(inode->i_mode))
++			return -EINVAL;
+ 		if (!ext4_empty_dir(inode))
+ 			return -ENOTEMPTY;
+ 		return ext4_create_encryption_context_from_policy(inode,

commit c2faccaff6a16d331df832135ede6d4774c2d2a0
+Author: Theodore Ts'o 
+Date:   Sun May 31 13:35:09 2015 -0400
+
+    ext4 crypto: enforce crypto policy restrictions on cross-renames
+    
+    Thanks to Chao Yu  for pointing out the need for
+    this check.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 1e7d65d7e6d7..401b099e3af3 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -3647,6 +3647,15 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 	u8 new_file_type;
+ 	int retval;
+ 
++	if ((ext4_encrypted_inode(old_dir) ||
++	     ext4_encrypted_inode(new_dir)) &&
++	    (old_dir != new_dir) &&
++	    (!ext4_is_child_context_consistent_with_parent(new_dir,
++							   old.inode) ||
++	     !ext4_is_child_context_consistent_with_parent(old_dir,
++							   new.inode)))
++		return -EPERM;
++
+ 	dquot_initialize(old.dir);
+ 	dquot_initialize(new.dir);
+ 

commit e709e9df64928a99d41da75910b844976a535db7
+Author: Theodore Ts'o 
+Date:   Sun May 31 13:35:02 2015 -0400
+
+    ext4 crypto: encrypt tmpfile located in encryption protected directory
+    
+    Factor out calls to ext4_inherit_context() and move them to
+    __ext4_new_inode(); this fixes a problem where ext4_tmpfile() wasn't
+    calling calling ext4_inherit_context(), so the temporary file wasn't
+    getting protected.  Since the blocks for the tmpfile could end up on
+    disk, they really should be protected if the tmpfile is created within
+    the context of an encrypted directory.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 7435ff2c3efb..bd8d32d5214d 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2149,6 +2149,11 @@ static inline int ext4_get_encryption_info(struct inode *inode)
+ 	return 0;
+ }
+ 
++static inline struct ext4_crypt_info *ext4_encryption_info(struct inode *inode)
++{
++	return EXT4_I(inode)->i_crypt_info;
++}
++
+ #else
+ static inline int ext4_has_encryption_key(struct inode *inode)
+ {
+@@ -2158,6 +2163,10 @@ static inline int ext4_get_encryption_info(struct inode *inode)
+ {
+ 	return 0;
+ }
++static inline struct ext4_crypt_info *ext4_encryption_info(struct inode *inode)
++{
++	return NULL;
++}
+ #endif
+ 
+ 
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index ddca1697ad86..173c1ae21395 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -726,11 +726,25 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
+ 	ext4_group_t i;
+ 	ext4_group_t flex_group;
+ 	struct ext4_group_info *grp;
++	int encrypt = 0;
+ 
+ 	/* Cannot create files in a deleted directory */
+ 	if (!dir || !dir->i_nlink)
+ 		return ERR_PTR(-EPERM);
+ 
++	if ((ext4_encrypted_inode(dir) ||
++	     DUMMY_ENCRYPTION_ENABLED(EXT4_SB(dir->i_sb))) &&
++	    (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) {
++		err = ext4_get_encryption_info(dir);
++		if (err)
++			return ERR_PTR(err);
++		if (ext4_encryption_info(dir) == NULL)
++			return ERR_PTR(-EPERM);
++		if (!handle)
++			nblocks += EXT4_DATA_TRANS_BLOCKS(dir->i_sb);
++		encrypt = 1;
++	}
++
+ 	sb = dir->i_sb;
+ 	ngroups = ext4_get_groups_count(sb);
+ 	trace_ext4_request_inode(dir, mode);
+@@ -996,12 +1010,6 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
+ 	ei->i_block_group = group;
+ 	ei->i_last_alloc_group = ~0;
+ 
+-	/* If the directory encrypted, then we should encrypt the inode. */
+-	if ((S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode)) &&
+-	    (ext4_encrypted_inode(dir) ||
+-	     DUMMY_ENCRYPTION_ENABLED(sbi)))
+-		ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
+-
+ 	ext4_set_inode_flags(inode);
+ 	if (IS_DIRSYNC(inode))
+ 		ext4_handle_sync(handle);
+@@ -1063,6 +1071,12 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
+ 		ei->i_datasync_tid = handle->h_transaction->t_tid;
+ 	}
+ 
++	if (encrypt) {
++		err = ext4_inherit_context(dir, inode);
++		if (err)
++			goto fail_free_drop;
++	}
++
+ 	err = ext4_mark_inode_dirty(handle, inode);
+ 	if (err) {
+ 		ext4_std_error(sb, err);
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 6ab50f80964f..1e7d65d7e6d7 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -2437,20 +2437,7 @@ static int ext4_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+ 		inode->i_op = &ext4_file_inode_operations;
+ 		inode->i_fop = &ext4_file_operations;
+ 		ext4_set_aops(inode);
+-		err = 0;
+-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+-		if (!err && (ext4_encrypted_inode(dir) ||
+-			     DUMMY_ENCRYPTION_ENABLED(EXT4_SB(dir->i_sb)))) {
+-			err = ext4_inherit_context(dir, inode);
+-			if (err) {
+-				clear_nlink(inode);
+-				unlock_new_inode(inode);
+-				iput(inode);
+-			}
+-		}
+-#endif
+-		if (!err)
+-			err = ext4_add_nondir(handle, dentry, inode);
++		err = ext4_add_nondir(handle, dentry, inode);
+ 		if (!err && IS_DIRSYNC(dir))
+ 			ext4_handle_sync(handle);
+ 	}
+@@ -2631,14 +2618,6 @@ static int ext4_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+ 	err = ext4_init_new_dir(handle, dir, inode);
+ 	if (err)
+ 		goto out_clear_inode;
+-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+-	if (ext4_encrypted_inode(dir) ||
+-	    DUMMY_ENCRYPTION_ENABLED(EXT4_SB(dir->i_sb))) {
+-		err = ext4_inherit_context(dir, inode);
+-		if (err)
+-			goto out_clear_inode;
+-	}
+-#endif
+ 	err = ext4_mark_inode_dirty(handle, inode);
+ 	if (!err)
+ 		err = ext4_add_entry(handle, dentry, inode);
+@@ -3106,12 +3085,6 @@ static int ext4_symlink(struct inode *dir,
+ 			err = -ENOMEM;
+ 			goto err_drop_inode;
+ 		}
+-		err = ext4_inherit_context(dir, inode);
+-		if (err)
+-			goto err_drop_inode;
+-		err = ext4_get_encryption_info(inode);
+-		if (err)
+-			goto err_drop_inode;
+ 		istr.name = (const unsigned char *) symname;
+ 		istr.len = len;
+ 		ostr.name = sd->encrypted_path;

commit 6bc445e0ff44c7e83225124c214d350407e68ccf
+Author: Theodore Ts'o 
+Date:   Sun May 31 13:34:57 2015 -0400
+
+    ext4 crypto: make sure the encryption info is initialized on opendir(2)
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index e11e6ae26baa..f9e14911918c 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -593,6 +593,13 @@ static int ext4_dx_readdir(struct file *file, struct dir_context *ctx)
+ 	return 0;
+ }
+ 
++static int ext4_dir_open(struct inode * inode, struct file * filp)
++{
++	if (ext4_encrypted_inode(inode))
++		return ext4_get_encryption_info(inode) ? -EACCES : 0;
++	return 0;
++}
++
+ static int ext4_release_dir(struct inode *inode, struct file *filp)
+ {
+ 	if (filp->private_data)
+@@ -635,5 +642,6 @@ const struct file_operations ext4_dir_operations = {
+ 	.compat_ioctl	= ext4_compat_ioctl,
+ #endif
+ 	.fsync		= ext4_sync_file,
++	.open		= ext4_dir_open,
+ 	.release	= ext4_release_dir,
+ };

commit 5555702955326ac1b9971f81569d8a6851384d49
+Author: Theodore Ts'o 
+Date:   Sun May 31 13:34:29 2015 -0400
+
+    ext4 crypto: set up encryption info for new inodes in ext4_inherit_context()
+    
+    Set up the encryption information for newly created inodes immediately
+    after they inherit their encryption context from their parent
+    directories.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/crypto_policy.c b/fs/ext4/crypto_policy.c
+index 683391f790d6..81980a158dc7 100644
+--- a/fs/ext4/crypto_policy.c
++++ b/fs/ext4/crypto_policy.c
+@@ -206,6 +206,7 @@ int ext4_inherit_context(struct inode *parent, struct inode *child)
+ 	if (!res) {
+ 		ext4_set_inode_flag(child, EXT4_INODE_ENCRYPT);
+ 		ext4_clear_inode_state(child, EXT4_STATE_MAY_INLINE_DATA);
++		res = ext4_get_encryption_info(child);
+ 	}
+ 	return res;
+ }

commit 95ea68b4c7105179f507d31f7bf571623373aa0b
+Author: Theodore Ts'o 
+Date:   Sun May 31 13:34:24 2015 -0400
+
+    ext4 crypto: fix memory leaks in ext4_encrypted_zeroout
+    
+    ext4_encrypted_zeroout() could end up leaking a bio and bounce page.
+    Fortunately it's not used much.  While we're fixing things up,
+    refactor out common code into the static function alloc_bounce_page()
+    and fix up error handling if mempool_alloc() fails.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
+index c3a9b08309db..1c9a8c499369 100644
+--- a/fs/ext4/crypto.c
++++ b/fs/ext4/crypto.c
+@@ -314,6 +314,26 @@ static int ext4_page_crypto(struct ext4_crypto_ctx *ctx,
+ 	return 0;
+ }
+ 
++static struct page *alloc_bounce_page(struct ext4_crypto_ctx *ctx)
++{
++	struct page *ciphertext_page = alloc_page(GFP_NOFS);
++
++	if (!ciphertext_page) {
++		/* This is a potential bottleneck, but at least we'll have
++		 * forward progress. */
++		ciphertext_page = mempool_alloc(ext4_bounce_page_pool,
++						 GFP_NOFS);
++		if (ciphertext_page == NULL)
++			return ERR_PTR(-ENOMEM);
++		ctx->flags &= ~EXT4_BOUNCE_PAGE_REQUIRES_FREE_ENCRYPT_FL;
++	} else {
++		ctx->flags |= EXT4_BOUNCE_PAGE_REQUIRES_FREE_ENCRYPT_FL;
++	}
++	ctx->flags |= EXT4_WRITE_PATH_FL;
++	ctx->w.bounce_page = ciphertext_page;
++	return ciphertext_page;
++}
++
+ /**
+  * ext4_encrypt() - Encrypts a page
+  * @inode:          The inode for which the encryption should take place
+@@ -343,28 +363,17 @@ struct page *ext4_encrypt(struct inode *inode,
+ 		return (struct page *) ctx;
+ 
+ 	/* The encryption operation will require a bounce page. */
+-	ciphertext_page = alloc_page(GFP_NOFS);
+-	if (!ciphertext_page) {
+-		/* This is a potential bottleneck, but at least we'll have
+-		 * forward progress. */
+-		ciphertext_page = mempool_alloc(ext4_bounce_page_pool,
+-						 GFP_NOFS);
+-		if (WARN_ON_ONCE(!ciphertext_page)) {
+-			ciphertext_page = mempool_alloc(ext4_bounce_page_pool,
+-							 GFP_NOFS | __GFP_WAIT);
+-		}
+-		ctx->flags &= ~EXT4_BOUNCE_PAGE_REQUIRES_FREE_ENCRYPT_FL;
+-	} else {
+-		ctx->flags |= EXT4_BOUNCE_PAGE_REQUIRES_FREE_ENCRYPT_FL;
+-	}
+-	ctx->flags |= EXT4_WRITE_PATH_FL;
+-	ctx->w.bounce_page = ciphertext_page;
++	ciphertext_page = alloc_bounce_page(ctx);
++	if (IS_ERR(ciphertext_page))
++		goto errout;
+ 	ctx->w.control_page = plaintext_page;
+ 	err = ext4_page_crypto(ctx, inode, EXT4_ENCRYPT, plaintext_page->index,
+ 			       plaintext_page, ciphertext_page);
+ 	if (err) {
++		ciphertext_page = ERR_PTR(err);
++	errout:
+ 		ext4_release_crypto_ctx(ctx);
+-		return ERR_PTR(err);
++		return ciphertext_page;
+ 	}
+ 	SetPagePrivate(ciphertext_page);
+ 	set_page_private(ciphertext_page, (unsigned long)ctx);
+@@ -424,21 +433,11 @@ int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex)
+ 	if (IS_ERR(ctx))
+ 		return PTR_ERR(ctx);
+ 
+-	ciphertext_page = alloc_page(GFP_NOFS);
+-	if (!ciphertext_page) {
+-		/* This is a potential bottleneck, but at least we'll have
+-		 * forward progress. */
+-		ciphertext_page = mempool_alloc(ext4_bounce_page_pool,
+-						 GFP_NOFS);
+-		if (WARN_ON_ONCE(!ciphertext_page)) {
+-			ciphertext_page = mempool_alloc(ext4_bounce_page_pool,
+-							 GFP_NOFS | __GFP_WAIT);
+-		}
+-		ctx->flags &= ~EXT4_BOUNCE_PAGE_REQUIRES_FREE_ENCRYPT_FL;
+-	} else {
+-		ctx->flags |= EXT4_BOUNCE_PAGE_REQUIRES_FREE_ENCRYPT_FL;
++	ciphertext_page = alloc_bounce_page(ctx);
++	if (IS_ERR(ciphertext_page)) {
++		err = PTR_ERR(ciphertext_page);
++		goto errout;
+ 	}
+-	ctx->w.bounce_page = ciphertext_page;
+ 
+ 	while (len--) {
+ 		err = ext4_page_crypto(ctx, inode, EXT4_ENCRYPT, lblk,
+@@ -460,6 +459,7 @@ int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex)
+ 			goto errout;
+ 		}
+ 		err = submit_bio_wait(WRITE, bio);
++		bio_put(bio);
+ 		if (err)
+ 			goto errout;
+ 	}

commit c936e1ec2879e43599d801dfa6fe58e7ccfee433
+Author: Theodore Ts'o 
+Date:   Sun May 31 13:34:22 2015 -0400
+
+    ext4 crypto: use per-inode tfm structure
+    
+    As suggested by Herbert Xu, we shouldn't allocate a new tfm each time
+    we read or write a page.  Instead we can use a single tfm hanging off
+    the inode's crypt_info structure for all of our encryption needs for
+    that inode, since the tfm can be used by multiple crypto requests in
+    parallel.
+    
+    Also use cmpxchg() to avoid races that could result in crypt_info
+    structure getting doubly allocated or doubly freed.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
+index 28a0e4bd91b0..c3a9b08309db 100644
+--- a/fs/ext4/crypto.c
++++ b/fs/ext4/crypto.c
+@@ -80,8 +80,6 @@ void ext4_release_crypto_ctx(struct ext4_crypto_ctx *ctx)
+ 	ctx->w.bounce_page = NULL;
+ 	ctx->w.control_page = NULL;
+ 	if (ctx->flags & EXT4_CTX_REQUIRES_FREE_ENCRYPT_FL) {
+-		if (ctx->tfm)
+-			crypto_free_tfm(ctx->tfm);
+ 		kmem_cache_free(ext4_crypto_ctx_cachep, ctx);
+ 	} else {
+ 		spin_lock_irqsave(&ext4_crypto_ctx_lock, flags);
+@@ -136,36 +134,6 @@ struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode)
+ 	}
+ 	ctx->flags &= ~EXT4_WRITE_PATH_FL;
+ 
+-	/* Allocate a new Crypto API context if we don't already have
+-	 * one or if it isn't the right mode. */
+-	if (ctx->tfm && (ctx->mode != ci->ci_data_mode)) {
+-		crypto_free_tfm(ctx->tfm);
+-		ctx->tfm = NULL;
+-		ctx->mode = EXT4_ENCRYPTION_MODE_INVALID;
+-	}
+-	if (!ctx->tfm) {
+-		switch (ci->ci_data_mode) {
+-		case EXT4_ENCRYPTION_MODE_AES_256_XTS:
+-			ctx->tfm = crypto_ablkcipher_tfm(
+-				crypto_alloc_ablkcipher("xts(aes)", 0, 0));
+-			break;
+-		case EXT4_ENCRYPTION_MODE_AES_256_GCM:
+-			/* TODO(mhalcrow): AEAD w/ gcm(aes);
+-			 * crypto_aead_setauthsize() */
+-			ctx->tfm = ERR_PTR(-ENOTSUPP);
+-			break;
+-		default:
+-			BUG();
+-		}
+-		if (IS_ERR_OR_NULL(ctx->tfm)) {
+-			res = PTR_ERR(ctx->tfm);
+-			ctx->tfm = NULL;
+-			goto out;
+-		}
+-		ctx->mode = ci->ci_data_mode;
+-	}
+-	BUG_ON(ci->ci_size != ext4_encryption_key_size(ci->ci_data_mode));
+-
+ out:
+ 	if (res) {
+ 		if (!IS_ERR_OR_NULL(ctx))
+@@ -185,11 +153,8 @@ void ext4_exit_crypto(void)
+ {
+ 	struct ext4_crypto_ctx *pos, *n;
+ 
+-	list_for_each_entry_safe(pos, n, &ext4_free_crypto_ctxs, free_list) {
+-		if (pos->tfm)
+-			crypto_free_tfm(pos->tfm);
++	list_for_each_entry_safe(pos, n, &ext4_free_crypto_ctxs, free_list)
+ 		kmem_cache_free(ext4_crypto_ctx_cachep, pos);
+-	}
+ 	INIT_LIST_HEAD(&ext4_free_crypto_ctxs);
+ 	if (ext4_bounce_page_pool)
+ 		mempool_destroy(ext4_bounce_page_pool);
+@@ -303,32 +268,11 @@ static int ext4_page_crypto(struct ext4_crypto_ctx *ctx,
+ 	struct ablkcipher_request *req = NULL;
+ 	DECLARE_EXT4_COMPLETION_RESULT(ecr);
+ 	struct scatterlist dst, src;
+-	struct ext4_inode_info *ei = EXT4_I(inode);
+-	struct crypto_ablkcipher *atfm = __crypto_ablkcipher_cast(ctx->tfm);
++	struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
++	struct crypto_ablkcipher *tfm = ci->ci_ctfm;
+ 	int res = 0;
+ 
+-	BUG_ON(!ctx->tfm);
+-	BUG_ON(ctx->mode != ei->i_crypt_info->ci_data_mode);
+-
+-	if (ctx->mode != EXT4_ENCRYPTION_MODE_AES_256_XTS) {
+-		printk_ratelimited(KERN_ERR
+-				   "%s: unsupported crypto algorithm: %d\n",
+-				   __func__, ctx->mode);
+-		return -ENOTSUPP;
+-	}
+-
+-	crypto_ablkcipher_clear_flags(atfm, ~0);
+-	crypto_tfm_set_flags(ctx->tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+-
+-	res = crypto_ablkcipher_setkey(atfm, ei->i_crypt_info->ci_raw,
+-				       ei->i_crypt_info->ci_size);
+-	if (res) {
+-		printk_ratelimited(KERN_ERR
+-				   "%s: crypto_ablkcipher_setkey() failed\n",
+-				   __func__);
+-		return res;
+-	}
+-	req = ablkcipher_request_alloc(atfm, GFP_NOFS);
++	req = ablkcipher_request_alloc(tfm, GFP_NOFS);
+ 	if (!req) {
+ 		printk_ratelimited(KERN_ERR
+ 				   "%s: crypto_request_alloc() failed\n",
+diff --git a/fs/ext4/crypto_fname.c b/fs/ext4/crypto_fname.c
+index e63dd294d7aa..29a2dc9a6f82 100644
+--- a/fs/ext4/crypto_fname.c
++++ b/fs/ext4/crypto_fname.c
+@@ -252,52 +252,6 @@ static int digest_decode(const char *src, int len, char *dst)
+ 	return cp - dst;
+ }
+ 
+-int ext4_setup_fname_crypto(struct inode *inode)
+-{
+-	struct ext4_inode_info *ei = EXT4_I(inode);
+-	struct ext4_crypt_info *ci = ei->i_crypt_info;
+-	struct crypto_ablkcipher *ctfm;
+-	int res;
+-
+-	/* Check if the crypto policy is set on the inode */
+-	res = ext4_encrypted_inode(inode);
+-	if (res == 0)
+-		return 0;
+-
+-	res = ext4_get_encryption_info(inode);
+-	if (res < 0)
+-		return res;
+-	ci = ei->i_crypt_info;
+-
+-	if (!ci || ci->ci_ctfm)
+-		return 0;
+-
+-	if (ci->ci_filename_mode != EXT4_ENCRYPTION_MODE_AES_256_CTS) {
+-		printk_once(KERN_WARNING "ext4: unsupported key mode %d\n",
+-			    ci->ci_filename_mode);
+-		return -ENOKEY;
+-	}
+-
+-	ctfm = crypto_alloc_ablkcipher("cts(cbc(aes))", 0, 0);
+-	if (!ctfm || IS_ERR(ctfm)) {
+-		res = ctfm ? PTR_ERR(ctfm) : -ENOMEM;
+-		printk(KERN_DEBUG "%s: error (%d) allocating crypto tfm\n",
+-		       __func__, res);
+-		return res;
+-	}
+-	crypto_ablkcipher_clear_flags(ctfm, ~0);
+-	crypto_tfm_set_flags(crypto_ablkcipher_tfm(ctfm),
+-			     CRYPTO_TFM_REQ_WEAK_KEY);
+-
+-	res = crypto_ablkcipher_setkey(ctfm, ci->ci_raw, ci->ci_size);
+-	if (res) {
+-		crypto_free_ablkcipher(ctfm);
+-		return -EIO;
+-	}
+-	ci->ci_ctfm = ctfm;
+-	return 0;
+-}
+-
+ /**
+  * ext4_fname_crypto_round_up() -
+  *
+@@ -449,7 +403,7 @@ int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname,
+ 		fname->disk_name.len = iname->len;
+ 		goto out;
+ 	}
+-	ret = ext4_setup_fname_crypto(dir);
++	ret = ext4_get_encryption_info(dir);
+ 	if (ret)
+ 		return ret;
+ 	ci = EXT4_I(dir)->i_crypt_info;
+diff --git a/fs/ext4/crypto_key.c b/fs/ext4/crypto_key.c
+index 858d7d67a4e1..442d24e8efc0 100644
+--- a/fs/ext4/crypto_key.c
++++ b/fs/ext4/crypto_key.c
+@@ -84,20 +84,32 @@ static int ext4_derive_key_aes(char deriving_key[EXT4_AES_128_ECB_KEY_SIZE],
+ 	return res;
+ }
+ 
+-void ext4_free_encryption_info(struct inode *inode)
++void ext4_free_crypt_info(struct ext4_crypt_info *ci)
+ {
+-	struct ext4_inode_info *ei = EXT4_I(inode);
+-	struct ext4_crypt_info *ci = ei->i_crypt_info;
+-
+ 	if (!ci)
+ 		return;
+ 
+ 	if (ci->ci_keyring_key)
+ 		key_put(ci->ci_keyring_key);
+ 	crypto_free_ablkcipher(ci->ci_ctfm);
+-	memzero_explicit(&ci->ci_raw, sizeof(ci->ci_raw));
+ 	kmem_cache_free(ext4_crypt_info_cachep, ci);
+-	ei->i_crypt_info = NULL;
++}
++
++void ext4_free_encryption_info(struct inode *inode,
++			       struct ext4_crypt_info *ci)
++{
++	struct ext4_inode_info *ei = EXT4_I(inode);
++	struct ext4_crypt_info *prev;
++
++	if (ci == NULL)
++		ci = ACCESS_ONCE(ei->i_crypt_info);
++	if (ci == NULL)
++		return;
++	prev = cmpxchg(&ei->i_crypt_info, ci, NULL);
++	if (prev != ci)
++		return;
++
++	ext4_free_crypt_info(ci);
+ }
+ 
+ int _ext4_get_encryption_info(struct inode *inode)
+@@ -111,6 +123,10 @@ int _ext4_get_encryption_info(struct inode *inode)
+ 	struct ext4_encryption_context ctx;
+ 	struct user_key_payload *ukp;
+ 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
++	struct crypto_ablkcipher *ctfm;
++	const char *cipher_str;
++	char raw_key[EXT4_MAX_KEY_SIZE];
++	char mode;
+ 	int res;
+ 
+ 	if (!ext4_read_workqueue) {
+@@ -119,11 +135,14 @@ int _ext4_get_encryption_info(struct inode *inode)
+ 			return res;
+ 	}
+ 
+-	if (ei->i_crypt_info) {
+-		if (!ei->i_crypt_info->ci_keyring_key ||
+-		    key_validate(ei->i_crypt_info->ci_keyring_key) == 0)
++retry:
++	crypt_info = ACCESS_ONCE(ei->i_crypt_info);
++	if (crypt_info) {
++		if (!crypt_info->ci_keyring_key ||
++		    key_validate(crypt_info->ci_keyring_key) == 0)
+ 			return 0;
+-		ext4_free_encryption_info(inode);
++		ext4_free_encryption_info(inode, crypt_info);
++		goto retry;
+ 	}
+ 
+ 	res = ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION,
+@@ -144,26 +163,37 @@ int _ext4_get_encryption_info(struct inode *inode)
+ 	if (!crypt_info)
+ 		return -ENOMEM;
+ 
+-	ei->i_crypt_policy_flags = ctx.flags;
+ 	crypt_info->ci_flags = ctx.flags;
+ 	crypt_info->ci_data_mode = ctx.contents_encryption_mode;
+ 	crypt_info->ci_filename_mode = ctx.filenames_encryption_mode;
+ 	crypt_info->ci_ctfm = NULL;
++	crypt_info->ci_keyring_key = NULL;
+ 	memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor,
+ 	       sizeof(crypt_info->ci_master_key));
+ 	if (S_ISREG(inode->i_mode))
+-		crypt_info->ci_size =
+-			ext4_encryption_key_size(crypt_info->ci_data_mode);
++		mode = crypt_info->ci_data_mode;
+ 	else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+-		crypt_info->ci_size =
+-			ext4_encryption_key_size(crypt_info->ci_filename_mode);
++		mode = crypt_info->ci_filename_mode;
+ 	else
+ 		BUG();
+-	BUG_ON(!crypt_info->ci_size);
+-	if (DUMMY_ENCRYPTION_ENABLED(sbi)) {
+-		memset(crypt_info->ci_raw, 0x42, EXT4_AES_256_XTS_KEY_SIZE);
++	switch (mode) {
++	case EXT4_ENCRYPTION_MODE_AES_256_XTS:
++		cipher_str = "xts(aes)";
++		break;
++	case EXT4_ENCRYPTION_MODE_AES_256_CTS:
++		cipher_str = "cts(cbc(aes))";
++		break;
++	default:
++		printk_once(KERN_WARNING
++			    "ext4: unsupported key mode %d (ino %u)\n",
++			    mode, (unsigned) inode->i_ino);
++		res = -ENOKEY;
+ 		goto out;
+ 	}
++	if (DUMMY_ENCRYPTION_ENABLED(sbi)) {
++		memset(raw_key, 0x42, EXT4_AES_256_XTS_KEY_SIZE);
++		goto got_key;
++	}
+ 	memcpy(full_key_descriptor, EXT4_KEY_DESC_PREFIX,
+ 	       EXT4_KEY_DESC_PREFIX_SIZE);
+ 	sprintf(full_key_descriptor + EXT4_KEY_DESC_PREFIX_SIZE,
+@@ -177,6 +207,7 @@ int _ext4_get_encryption_info(struct inode *inode)
+ 		keyring_key = NULL;
+ 		goto out;
+ 	}
++	crypt_info->ci_keyring_key = keyring_key;
+ 	BUG_ON(keyring_key->type != &key_type_logon);
+ 	ukp = ((struct user_key_payload *)keyring_key->payload.data);
+ 	if (ukp->datalen != sizeof(struct ext4_encryption_key)) {
+@@ -188,19 +219,36 @@ int _ext4_get_encryption_info(struct inode *inode)
+ 		     EXT4_KEY_DERIVATION_NONCE_SIZE);
+ 	BUG_ON(master_key->size != EXT4_AES_256_XTS_KEY_SIZE);
+ 	res = ext4_derive_key_aes(ctx.nonce, master_key->raw,
+-				  crypt_info->ci_raw);
+-out:
+-	if (res < 0) {
+-		if (res == -ENOKEY)
+-			res = 0;
+-		kmem_cache_free(ext4_crypt_info_cachep, crypt_info);
+-	} else {
+-		ei->i_crypt_info = crypt_info;
+-		crypt_info->ci_keyring_key = keyring_key;
+-		keyring_key = NULL;
++				  raw_key);
++got_key:
++	ctfm = crypto_alloc_ablkcipher(cipher_str, 0, 0);
++	if (!ctfm || IS_ERR(ctfm)) {
++		res = ctfm ? PTR_ERR(ctfm) : -ENOMEM;
++		printk(KERN_DEBUG
++		       "%s: error %d (inode %u) allocating crypto tfm\n",
++		       __func__, res, (unsigned) inode->i_ino);
++		goto out;
++	}
++	crypt_info->ci_ctfm = ctfm;
++	crypto_ablkcipher_clear_flags(ctfm, ~0);
++	crypto_tfm_set_flags(crypto_ablkcipher_tfm(ctfm),
++			     CRYPTO_TFM_REQ_WEAK_KEY);
++	res = crypto_ablkcipher_setkey(ctfm, raw_key,
++				       ext4_encryption_key_size(mode));
++	if (res)
++		goto out;
++	memzero_explicit(raw_key, sizeof(raw_key));
++	if (cmpxchg(&ei->i_crypt_info, NULL, crypt_info) != NULL) {
++		ext4_free_crypt_info(crypt_info);
++		goto retry;
+ 	}
+-	if (keyring_key)
+-		key_put(keyring_key);
++	return 0;
++
++out:
++	if (res == -ENOKEY)
++		res = 0;
++	ext4_free_crypt_info(crypt_info);
++	memzero_explicit(raw_key, sizeof(raw_key));
+ 	return res;
+ }
+ 
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index 28cb94fbb1c9..e11e6ae26baa 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -133,9 +133,6 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
+ 			return err;
+ 	}
+ 
+-	err = ext4_setup_fname_crypto(inode);
+-	if (err)
+-		return err;
+ 	if (ext4_encrypted_inode(inode)) {
+ 		err = ext4_fname_crypto_alloc_buffer(inode, EXT4_NAME_LEN,
+ 						     &fname_crypto_str);
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 23e33fb3202e..7435ff2c3efb 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -911,7 +911,6 @@ struct ext4_inode_info {
+ 
+ 	/* on-disk additional length */
+ 	__u16 i_extra_isize;
+-	char i_crypt_policy_flags;
+ 
+ 	/* Indicate the inline data space. */
+ 	u16 i_inline_off;
+@@ -2105,7 +2104,6 @@ int ext4_fname_usr_to_disk(struct inode *inode,
+ 			   const struct qstr *iname,
+ 			   struct ext4_str *oname);
+ #ifdef CONFIG_EXT4_FS_ENCRYPTION
+-int ext4_setup_fname_crypto(struct inode *inode);
+ void ext4_fname_crypto_free_buffer(struct ext4_str *crypto_str);
+ int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname,
+ 			      int lookup, struct ext4_filename *fname);
+@@ -2131,7 +2129,8 @@ static inline void ext4_fname_free_filename(struct ext4_filename *fname) { }
+ 
+ 
+ /* crypto_key.c */
+-void ext4_free_encryption_info(struct inode *inode);
++void ext4_free_crypt_info(struct ext4_crypt_info *ci);
++void ext4_free_encryption_info(struct inode *inode, struct ext4_crypt_info *ci);
+ int _ext4_get_encryption_info(struct inode *inode);
+ 
+ #ifdef CONFIG_EXT4_FS_ENCRYPTION
+diff --git a/fs/ext4/ext4_crypto.h b/fs/ext4/ext4_crypto.h
+index c5258f242215..34e0d2455881 100644
+--- a/fs/ext4/ext4_crypto.h
++++ b/fs/ext4/ext4_crypto.h
+@@ -74,13 +74,11 @@ struct ext4_encryption_key {
+ } __attribute__((__packed__));
+ 
+ struct ext4_crypt_info {
+-	unsigned char	ci_size;
+ 	char		ci_data_mode;
+ 	char		ci_filename_mode;
+ 	char		ci_flags;
+ 	struct crypto_ablkcipher *ci_ctfm;
+ 	struct key	*ci_keyring_key;
+-	char		ci_raw[EXT4_MAX_KEY_SIZE];
+ 	char		ci_master_key[EXT4_KEY_DESCRIPTOR_SIZE];
+ };
+ 
+@@ -89,7 +87,6 @@ struct ext4_crypt_info {
+ #define EXT4_WRITE_PATH_FL			      0x00000004
+ 
+ struct ext4_crypto_ctx {
+-	struct crypto_tfm *tfm;         /* Crypto API context */
+ 	union {
+ 		struct {
+ 			struct page *bounce_page;       /* Ciphertext page */
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 9bed99fdd81a..6ab50f80964f 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -607,11 +607,12 @@ static struct stats dx_show_leaf(struct inode *dir,
+ 				char *name;
+ 				struct ext4_str fname_crypto_str
+ 					= {.name = NULL, .len = 0};
+-				int res;
++				int res = 0;
+ 
+ 				name  = de->name;
+ 				len = de->name_len;
+-				res = ext4_setup_fname_crypto(dir);
++				if (ext4_encrypted_inode(inode))
++					res = ext4_get_encryption_info(dir);
+ 				if (res) {
+ 					printk(KERN_WARNING "Error setting up"
+ 					       " fname crypto: %d\n", res);
+@@ -953,12 +954,12 @@ static int htree_dirblock_to_tree(struct file *dir_file,
+ 					   EXT4_DIR_REC_LEN(0));
+ #ifdef CONFIG_EXT4_FS_ENCRYPTION
+ 	/* Check if the directory is encrypted */
+-	err = ext4_setup_fname_crypto(dir);
+-	if (err) {
+-		brelse(bh);
+-		return err;
+-	}
+ 	if (ext4_encrypted_inode(dir)) {
++		err = ext4_get_encryption_info(dir);
++		if (err < 0) {
++			brelse(bh);
++			return err;
++		}
+ 		err = ext4_fname_crypto_alloc_buffer(dir, EXT4_NAME_LEN,
+ 						     &fname_crypto_str);
+ 		if (err < 0) {
+@@ -3108,7 +3109,7 @@ static int ext4_symlink(struct inode *dir,
+ 		err = ext4_inherit_context(dir, inode);
+ 		if (err)
+ 			goto err_drop_inode;
+-		err = ext4_setup_fname_crypto(inode);
++		err = ext4_get_encryption_info(inode);
+ 		if (err)
+ 			goto err_drop_inode;
+ 		istr.name = (const unsigned char *) symname;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index b0bd1c1061b3..56bfc2f25d90 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -959,7 +959,7 @@ void ext4_clear_inode(struct inode *inode)
+ 	}
+ #ifdef CONFIG_EXT4_FS_ENCRYPTION
+ 	if (EXT4_I(inode)->i_crypt_info)
+-		ext4_free_encryption_info(inode);
++		ext4_free_encryption_info(inode, EXT4_I(inode)->i_crypt_info);
+ #endif
+ }
+ 
+diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
+index 32870881188e..68e915aac0fe 100644
+--- a/fs/ext4/symlink.c
++++ b/fs/ext4/symlink.c
+@@ -37,7 +37,7 @@ static void *ext4_follow_link(struct dentry *dentry, struct nameidata *nd)
+ 	if (!ext4_encrypted_inode(inode))
+ 		return page_follow_link_light(dentry, nd);
+ 
+-	res = ext4_setup_fname_crypto(inode);
++	res = ext4_get_encryption_info(inode);
+ 	if (res)
+ 		return ERR_PTR(res);
+ 

commit 71dea01ea2edb73f3c5d9a0cd7ba028bb9313287
+Author: Theodore Ts'o 
+Date:   Sun May 31 13:31:37 2015 -0400
+
+    ext4 crypto: require CONFIG_CRYPTO_CTR if ext4 encryption is enabled
+    
+    On arm64 this is apparently needed for CTS mode to function correctly.
+    Otherwise attempts to use CTS return ENOENT.
+    
+    Change-Id: I732ea9a5157acc76de5b89edec195d0365f4ca63
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
+index 024f2284d3f6..bf8bc8aba471 100644
+--- a/fs/ext4/Kconfig
++++ b/fs/ext4/Kconfig
+@@ -72,6 +72,7 @@ config EXT4_ENCRYPTION
+ 	select CRYPTO_ECB
+ 	select CRYPTO_XTS
+ 	select CRYPTO_CTS
++	select CRYPTO_CTR
+ 	select CRYPTO_SHA256
+ 	select KEYS
+ 	select ENCRYPTED_KEYS

commit 614def7013574ffcd54019b6df40ac1c0df754af
+Author: Theodore Ts'o 
+Date:   Sun May 31 13:31:34 2015 -0400
+
+    ext4 crypto: shrink size of the ext4_crypto_ctx structure
+    
+    Some fields are only used when the crypto_ctx is being used on the
+    read path, some are only used on the write path, and some are only
+    used when the structure is on free list.  Optimize memory use by using
+    a union.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
+index 9969d054cd88..28a0e4bd91b0 100644
+--- a/fs/ext4/crypto.c
++++ b/fs/ext4/crypto.c
+@@ -71,14 +71,14 @@ void ext4_release_crypto_ctx(struct ext4_crypto_ctx *ctx)
+ {
+ 	unsigned long flags;
+ 
+-	if (ctx->bounce_page) {
++	if (ctx->flags & EXT4_WRITE_PATH_FL && ctx->w.bounce_page) {
+ 		if (ctx->flags & EXT4_BOUNCE_PAGE_REQUIRES_FREE_ENCRYPT_FL)
+-			__free_page(ctx->bounce_page);
++			__free_page(ctx->w.bounce_page);
+ 		else
+-			mempool_free(ctx->bounce_page, ext4_bounce_page_pool);
+-		ctx->bounce_page = NULL;
++			mempool_free(ctx->w.bounce_page, ext4_bounce_page_pool);
+ 	}
+-	ctx->control_page = NULL;
++	ctx->w.bounce_page = NULL;
++	ctx->w.control_page = NULL;
+ 	if (ctx->flags & EXT4_CTX_REQUIRES_FREE_ENCRYPT_FL) {
+ 		if (ctx->tfm)
+ 			crypto_free_tfm(ctx->tfm);
+@@ -134,6 +134,7 @@ struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode)
+ 	} else {
+ 		ctx->flags &= ~EXT4_CTX_REQUIRES_FREE_ENCRYPT_FL;
+ 	}
++	ctx->flags &= ~EXT4_WRITE_PATH_FL;
+ 
+ 	/* Allocate a new Crypto API context if we don't already have
+ 	 * one or if it isn't the right mode. */
+@@ -165,10 +166,6 @@ struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode)
+ 	}
+ 	BUG_ON(ci->ci_size != ext4_encryption_key_size(ci->ci_data_mode));
+ 
+-	/* There shouldn't be a bounce page attached to the crypto
+-	 * context at this point. */
+-	BUG_ON(ctx->bounce_page);
+-
+ out:
+ 	if (res) {
+ 		if (!IS_ERR_OR_NULL(ctx))
+@@ -189,15 +186,6 @@ void ext4_exit_crypto(void)
+ 	struct ext4_crypto_ctx *pos, *n;
+ 
+ 	list_for_each_entry_safe(pos, n, &ext4_free_crypto_ctxs, free_list) {
+-		if (pos->bounce_page) {
+-			if (pos->flags &
+-			    EXT4_BOUNCE_PAGE_REQUIRES_FREE_ENCRYPT_FL) {
+-				__free_page(pos->bounce_page);
+-			} else {
+-				mempool_free(pos->bounce_page,
+-					     ext4_bounce_page_pool);
+-			}
+-		}
+ 		if (pos->tfm)
+ 			crypto_free_tfm(pos->tfm);
+ 		kmem_cache_free(ext4_crypto_ctx_cachep, pos);
+@@ -425,8 +413,9 @@ struct page *ext4_encrypt(struct inode *inode,
+ 	} else {
+ 		ctx->flags |= EXT4_BOUNCE_PAGE_REQUIRES_FREE_ENCRYPT_FL;
+ 	}
+-	ctx->bounce_page = ciphertext_page;
+-	ctx->control_page = plaintext_page;
++	ctx->flags |= EXT4_WRITE_PATH_FL;
++	ctx->w.bounce_page = ciphertext_page;
++	ctx->w.control_page = plaintext_page;
+ 	err = ext4_page_crypto(ctx, inode, EXT4_ENCRYPT, plaintext_page->index,
+ 			       plaintext_page, ciphertext_page);
+ 	if (err) {
+@@ -505,7 +494,7 @@ int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex)
+ 	} else {
+ 		ctx->flags |= EXT4_BOUNCE_PAGE_REQUIRES_FREE_ENCRYPT_FL;
+ 	}
+-	ctx->bounce_page = ciphertext_page;
++	ctx->w.bounce_page = ciphertext_page;
+ 
+ 	while (len--) {
+ 		err = ext4_page_crypto(ctx, inode, EXT4_ENCRYPT, lblk,
+diff --git a/fs/ext4/ext4_crypto.h b/fs/ext4/ext4_crypto.h
+index 69faf0e9f874..c5258f242215 100644
+--- a/fs/ext4/ext4_crypto.h
++++ b/fs/ext4/ext4_crypto.h
+@@ -86,16 +86,23 @@ struct ext4_crypt_info {
+ 
+ #define EXT4_CTX_REQUIRES_FREE_ENCRYPT_FL             0x00000001
+ #define EXT4_BOUNCE_PAGE_REQUIRES_FREE_ENCRYPT_FL     0x00000002
++#define EXT4_WRITE_PATH_FL			      0x00000004
+ 
+ struct ext4_crypto_ctx {
+ 	struct crypto_tfm *tfm;         /* Crypto API context */
+-	struct page *bounce_page;       /* Ciphertext page on write path */
+-	struct page *control_page;      /* Original page on write path */
+-	struct bio *bio;                /* The bio for this context */
+-	struct work_struct work;        /* Work queue for read complete path */
+-	struct list_head free_list;     /* Free list */
+-	int flags;                      /* Flags */
+-	int mode;                       /* Encryption mode for tfm */
++	union {
++		struct {
++			struct page *bounce_page;       /* Ciphertext page */
++			struct page *control_page;      /* Original page  */
++		} w;
++		struct {
++			struct bio *bio;
++			struct work_struct work;
++		} r;
++		struct list_head free_list;     /* Free list */
++	};
++	char flags;                      /* Flags */
++	char mode;                       /* Encryption mode for tfm */
+ };
+ 
+ struct ext4_completion_result {
+diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
+index 5765f88b3904..79636e21d3a2 100644
+--- a/fs/ext4/page-io.c
++++ b/fs/ext4/page-io.c
+@@ -84,7 +84,7 @@ static void ext4_finish_bio(struct bio *bio)
+ 			/* The bounce data pages are unmapped. */
+ 			data_page = page;
+ 			ctx = (struct ext4_crypto_ctx *)page_private(data_page);
+-			page = ctx->control_page;
++			page = ctx->w.control_page;
+ 		}
+ #endif
+ 
+diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
+index 171b9ac4b45e..ec3ef93a52db 100644
+--- a/fs/ext4/readpage.c
++++ b/fs/ext4/readpage.c
+@@ -54,8 +54,8 @@ static void completion_pages(struct work_struct *work)
+ {
+ #ifdef CONFIG_EXT4_FS_ENCRYPTION
+ 	struct ext4_crypto_ctx *ctx =
+-		container_of(work, struct ext4_crypto_ctx, work);
+-	struct bio	*bio	= ctx->bio;
++		container_of(work, struct ext4_crypto_ctx, r.work);
++	struct bio	*bio	= ctx->r.bio;
+ 	struct bio_vec	*bv;
+ 	int		i;
+ 
+@@ -109,9 +109,9 @@ static void mpage_end_io(struct bio *bio, int err)
+ 		if (err) {
+ 			ext4_release_crypto_ctx(ctx);
+ 		} else {
+-			INIT_WORK(&ctx->work, completion_pages);
+-			ctx->bio = bio;
+-			queue_work(ext4_read_workqueue, &ctx->work);
++			INIT_WORK(&ctx->r.work, completion_pages);
++			ctx->r.bio = bio;
++			queue_work(ext4_read_workqueue, &ctx->r.work);
+ 			return;
+ 		}
+ 	}

commit 1aaa6e8b24114757a836ae0e62d2096deb76f274
+Author: Theodore Ts'o 
+Date:   Mon May 18 13:20:47 2015 -0400
+
+    ext4 crypto: get rid of ci_mode from struct ext4_crypt_info
+    
+    The ci_mode field was superfluous, and getting rid of it gets rid of
+    an unused hole in the structure.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
+index 1c34f0eb125b..9969d054cd88 100644
+--- a/fs/ext4/crypto.c
++++ b/fs/ext4/crypto.c
+@@ -137,14 +137,13 @@ struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode)
+ 
+ 	/* Allocate a new Crypto API context if we don't already have
+ 	 * one or if it isn't the right mode. */
+-	BUG_ON(ci->ci_mode == EXT4_ENCRYPTION_MODE_INVALID);
+-	if (ctx->tfm && (ctx->mode != ci->ci_mode)) {
++	if (ctx->tfm && (ctx->mode != ci->ci_data_mode)) {
+ 		crypto_free_tfm(ctx->tfm);
+ 		ctx->tfm = NULL;
+ 		ctx->mode = EXT4_ENCRYPTION_MODE_INVALID;
+ 	}
+ 	if (!ctx->tfm) {
+-		switch (ci->ci_mode) {
++		switch (ci->ci_data_mode) {
+ 		case EXT4_ENCRYPTION_MODE_AES_256_XTS:
+ 			ctx->tfm = crypto_ablkcipher_tfm(
+ 				crypto_alloc_ablkcipher("xts(aes)", 0, 0));
+@@ -162,9 +161,9 @@ struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode)
+ 			ctx->tfm = NULL;
+ 			goto out;
+ 		}
+-		ctx->mode = ci->ci_mode;
++		ctx->mode = ci->ci_data_mode;
+ 	}
+-	BUG_ON(ci->ci_size != ext4_encryption_key_size(ci->ci_mode));
++	BUG_ON(ci->ci_size != ext4_encryption_key_size(ci->ci_data_mode));
+ 
+ 	/* There shouldn't be a bounce page attached to the crypto
+ 	 * context at this point. */
+@@ -321,7 +320,7 @@ static int ext4_page_crypto(struct ext4_crypto_ctx *ctx,
+ 	int res = 0;
+ 
+ 	BUG_ON(!ctx->tfm);
+-	BUG_ON(ctx->mode != ei->i_crypt_info->ci_mode);
++	BUG_ON(ctx->mode != ei->i_crypt_info->ci_data_mode);
+ 
+ 	if (ctx->mode != EXT4_ENCRYPTION_MODE_AES_256_XTS) {
+ 		printk_ratelimited(KERN_ERR
+diff --git a/fs/ext4/crypto_fname.c b/fs/ext4/crypto_fname.c
+index 374d0e790315..e63dd294d7aa 100644
+--- a/fs/ext4/crypto_fname.c
++++ b/fs/ext4/crypto_fname.c
+@@ -272,9 +272,9 @@ int ext4_setup_fname_crypto(struct inode *inode)
+ 	if (!ci || ci->ci_ctfm)
+ 		return 0;
+ 
+-	if (ci->ci_mode != EXT4_ENCRYPTION_MODE_AES_256_CTS) {
++	if (ci->ci_filename_mode != EXT4_ENCRYPTION_MODE_AES_256_CTS) {
+ 		printk_once(KERN_WARNING "ext4: unsupported key mode %d\n",
+-			    ci->ci_mode);
++			    ci->ci_filename_mode);
+ 		return -ENOKEY;
+ 	}
+ 
+diff --git a/fs/ext4/crypto_key.c b/fs/ext4/crypto_key.c
+index d6abe4687cd5..858d7d67a4e1 100644
+--- a/fs/ext4/crypto_key.c
++++ b/fs/ext4/crypto_key.c
+@@ -152,14 +152,13 @@ int _ext4_get_encryption_info(struct inode *inode)
+ 	memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor,
+ 	       sizeof(crypt_info->ci_master_key));
+ 	if (S_ISREG(inode->i_mode))
+-		crypt_info->ci_mode = ctx.contents_encryption_mode;
++		crypt_info->ci_size =
++			ext4_encryption_key_size(crypt_info->ci_data_mode);
+ 	else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+-		crypt_info->ci_mode = ctx.filenames_encryption_mode;
+-	else {
+-		printk(KERN_ERR "ext4 crypto: Unsupported inode type.\n");
++		crypt_info->ci_size =
++			ext4_encryption_key_size(crypt_info->ci_filename_mode);
++	else
+ 		BUG();
+-	}
+-	crypt_info->ci_size = ext4_encryption_key_size(crypt_info->ci_mode);
+ 	BUG_ON(!crypt_info->ci_size);
+ 	if (DUMMY_ENCRYPTION_ENABLED(sbi)) {
+ 		memset(crypt_info->ci_raw, 0x42, EXT4_AES_256_XTS_KEY_SIZE);
+diff --git a/fs/ext4/ext4_crypto.h b/fs/ext4/ext4_crypto.h
+index d29687c232bd..69faf0e9f874 100644
+--- a/fs/ext4/ext4_crypto.h
++++ b/fs/ext4/ext4_crypto.h
+@@ -74,7 +74,6 @@ struct ext4_encryption_key {
+ } __attribute__((__packed__));
+ 
+ struct ext4_crypt_info {
+-	unsigned char	ci_mode;
+ 	unsigned char	ci_size;
+ 	char		ci_data_mode;
+ 	char		ci_filename_mode;

commit 8ee0371470038371729a39ee6669a2132ac47649
+Author: Theodore Ts'o 
+Date:   Mon May 18 13:19:47 2015 -0400
+
+    ext4 crypto: use slab caches
+    
+    Use slab caches the ext4_crypto_ctx and ext4_crypt_info structures for
+    slighly better memory efficiency and debuggability.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
+index 3a25aa4f3d94..1c34f0eb125b 100644
+--- a/fs/ext4/crypto.c
++++ b/fs/ext4/crypto.c
+@@ -55,6 +55,9 @@ static mempool_t *ext4_bounce_page_pool;
+ static LIST_HEAD(ext4_free_crypto_ctxs);
+ static DEFINE_SPINLOCK(ext4_crypto_ctx_lock);
+ 
++static struct kmem_cache *ext4_crypto_ctx_cachep;
++struct kmem_cache *ext4_crypt_info_cachep;
++
+ /**
+  * ext4_release_crypto_ctx() - Releases an encryption context
+  * @ctx: The encryption context to release.
+@@ -79,7 +82,7 @@ void ext4_release_crypto_ctx(struct ext4_crypto_ctx *ctx)
+ 	if (ctx->flags & EXT4_CTX_REQUIRES_FREE_ENCRYPT_FL) {
+ 		if (ctx->tfm)
+ 			crypto_free_tfm(ctx->tfm);
+-		kfree(ctx);
++		kmem_cache_free(ext4_crypto_ctx_cachep, ctx);
+ 	} else {
+ 		spin_lock_irqsave(&ext4_crypto_ctx_lock, flags);
+ 		list_add(&ctx->free_list, &ext4_free_crypto_ctxs);
+@@ -87,23 +90,6 @@ void ext4_release_crypto_ctx(struct ext4_crypto_ctx *ctx)
+ 	}
+ }
+ 
+-/**
+- * ext4_alloc_and_init_crypto_ctx() - Allocates and inits an encryption context
+- * @mask: The allocation mask.
+- *
+- * Return: An allocated and initialized encryption context on success. An error
+- * value or NULL otherwise.
+- */
+-static struct ext4_crypto_ctx *ext4_alloc_and_init_crypto_ctx(gfp_t mask)
+-{
+-	struct ext4_crypto_ctx *ctx = kzalloc(sizeof(struct ext4_crypto_ctx),
+-					      mask);
+-
+-	if (!ctx)
+-		return ERR_PTR(-ENOMEM);
+-	return ctx;
+-}
+-
+ /**
+  * ext4_get_crypto_ctx() - Gets an encryption context
+  * @inode:       The inode for which we are doing the crypto
+@@ -121,8 +107,6 @@ struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode)
+ 	struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
+ 
+ 	BUG_ON(ci == NULL);
+-	if (!ext4_read_workqueue)
+-		ext4_init_crypto();
+ 
+ 	/*
+ 	 * We first try getting the ctx from a free list because in
+@@ -141,9 +125,9 @@ struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode)
+ 		list_del(&ctx->free_list);
+ 	spin_unlock_irqrestore(&ext4_crypto_ctx_lock, flags);
+ 	if (!ctx) {
+-		ctx = ext4_alloc_and_init_crypto_ctx(GFP_NOFS);
+-		if (IS_ERR(ctx)) {
+-			res = PTR_ERR(ctx);
++		ctx = kmem_cache_zalloc(ext4_crypto_ctx_cachep, GFP_NOFS);
++		if (!ctx) {
++			res = -ENOMEM;
+ 			goto out;
+ 		}
+ 		ctx->flags |= EXT4_CTX_REQUIRES_FREE_ENCRYPT_FL;
+@@ -217,7 +201,7 @@ void ext4_exit_crypto(void)
+ 		}
+ 		if (pos->tfm)
+ 			crypto_free_tfm(pos->tfm);
+-		kfree(pos);
++		kmem_cache_free(ext4_crypto_ctx_cachep, pos);
+ 	}
+ 	INIT_LIST_HEAD(&ext4_free_crypto_ctxs);
+ 	if (ext4_bounce_page_pool)
+@@ -226,6 +210,12 @@ void ext4_exit_crypto(void)
+ 	if (ext4_read_workqueue)
+ 		destroy_workqueue(ext4_read_workqueue);
+ 	ext4_read_workqueue = NULL;
++	if (ext4_crypto_ctx_cachep)
++		kmem_cache_destroy(ext4_crypto_ctx_cachep);
++	ext4_crypto_ctx_cachep = NULL;
++	if (ext4_crypt_info_cachep)
++		kmem_cache_destroy(ext4_crypt_info_cachep);
++	ext4_crypt_info_cachep = NULL;
+ }
+ 
+ /**
+@@ -238,23 +228,31 @@ void ext4_exit_crypto(void)
+  */
+ int ext4_init_crypto(void)
+ {
+-	int i, res;
++	int i, res = -ENOMEM;
+ 
+ 	mutex_lock(&crypto_init);
+ 	if (ext4_read_workqueue)
+ 		goto already_initialized;
+ 	ext4_read_workqueue = alloc_workqueue("ext4_crypto", WQ_HIGHPRI, 0);
+-	if (!ext4_read_workqueue) {
+-		res = -ENOMEM;
++	if (!ext4_read_workqueue)
++		goto fail;
++
++	ext4_crypto_ctx_cachep = KMEM_CACHE(ext4_crypto_ctx,
++					    SLAB_RECLAIM_ACCOUNT);
++	if (!ext4_crypto_ctx_cachep)
++		goto fail;
++
++	ext4_crypt_info_cachep = KMEM_CACHE(ext4_crypt_info,
++					    SLAB_RECLAIM_ACCOUNT);
++	if (!ext4_crypt_info_cachep)
+ 		goto fail;
+-	}
+ 
+ 	for (i = 0; i < num_prealloc_crypto_ctxs; i++) {
+ 		struct ext4_crypto_ctx *ctx;
+ 
+-		ctx = ext4_alloc_and_init_crypto_ctx(GFP_KERNEL);
+-		if (IS_ERR(ctx)) {
+-			res = PTR_ERR(ctx);
++		ctx = kmem_cache_zalloc(ext4_crypto_ctx_cachep, GFP_NOFS);
++		if (!ctx) {
++			res = -ENOMEM;
+ 			goto fail;
+ 		}
+ 		list_add(&ctx->free_list, &ext4_free_crypto_ctxs);
+diff --git a/fs/ext4/crypto_key.c b/fs/ext4/crypto_key.c
+index 0075e43ffea6..d6abe4687cd5 100644
+--- a/fs/ext4/crypto_key.c
++++ b/fs/ext4/crypto_key.c
+@@ -96,7 +96,7 @@ void ext4_free_encryption_info(struct inode *inode)
+ 		key_put(ci->ci_keyring_key);
+ 	crypto_free_ablkcipher(ci->ci_ctfm);
+ 	memzero_explicit(&ci->ci_raw, sizeof(ci->ci_raw));
+-	kfree(ci);
++	kmem_cache_free(ext4_crypt_info_cachep, ci);
+ 	ei->i_crypt_info = NULL;
+ }
+ 
+@@ -113,6 +113,12 @@ int _ext4_get_encryption_info(struct inode *inode)
+ 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+ 	int res;
+ 
++	if (!ext4_read_workqueue) {
++		res = ext4_init_crypto();
++		if (res)
++			return res;
++	}
++
+ 	if (ei->i_crypt_info) {
+ 		if (!ei->i_crypt_info->ci_keyring_key ||
+ 		    key_validate(ei->i_crypt_info->ci_keyring_key) == 0)
+@@ -134,7 +140,7 @@ int _ext4_get_encryption_info(struct inode *inode)
+ 		return -EINVAL;
+ 	res = 0;
+ 
+-	crypt_info = kmalloc(sizeof(struct ext4_crypt_info), GFP_KERNEL);
++	crypt_info = kmem_cache_alloc(ext4_crypt_info_cachep, GFP_KERNEL);
+ 	if (!crypt_info)
+ 		return -ENOMEM;
+ 
+@@ -188,7 +194,7 @@ int _ext4_get_encryption_info(struct inode *inode)
+ 	if (res < 0) {
+ 		if (res == -ENOKEY)
+ 			res = 0;
+-		kfree(crypt_info);
++		kmem_cache_free(ext4_crypt_info_cachep, crypt_info);
+ 	} else {
+ 		ei->i_crypt_info = crypt_info;
+ 		crypt_info->ci_keyring_key = keyring_key;
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 213536fdab9f..23e33fb3202e 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2059,6 +2059,7 @@ int ext4_get_policy(struct inode *inode,
+ 		    struct ext4_encryption_policy *policy);
+ 
+ /* crypto.c */
++extern struct kmem_cache *ext4_crypt_info_cachep;
+ bool ext4_valid_contents_enc_mode(uint32_t mode);
+ uint32_t ext4_validate_encryption_key_size(uint32_t mode, uint32_t size);
+ extern struct workqueue_struct *ext4_read_workqueue;

commit f5aed2c2a825618553b20e8a67109570489b40d7
+Author: Theodore Ts'o 
+Date:   Mon May 18 13:18:47 2015 -0400
+
+    ext4: clean up superblock encryption mode fields
+    
+    The superblock fields s_file_encryption_mode and s_dir_encryption_mode
+    are vestigal, so remove them as a cleanup.  While we're at it, allow
+    file systems with both encryption and inline_data enabled at the same
+    time to work correctly.  We can't have encrypted inodes with inline
+    data, but there's no reason to prohibit unencrypted inodes from using
+    the inline data feature.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/crypto_policy.c b/fs/ext4/crypto_policy.c
+index 370d3aa0a9cf..683391f790d6 100644
+--- a/fs/ext4/crypto_policy.c
++++ b/fs/ext4/crypto_policy.c
+@@ -51,6 +51,10 @@ static int ext4_create_encryption_context_from_policy(
+ 	struct ext4_encryption_context ctx;
+ 	int res = 0;
+ 
++	res = ext4_convert_inline_data(inode);
++	if (res)
++		return res;
++
+ 	ctx.format = EXT4_ENCRYPTION_CONTEXT_FORMAT_V1;
+ 	memcpy(ctx.master_key_descriptor, policy->master_key_descriptor,
+ 	       EXT4_KEY_DESCRIPTOR_SIZE);
+@@ -199,8 +203,9 @@ int ext4_inherit_context(struct inode *parent, struct inode *child)
+ 	res = ext4_xattr_set(child, EXT4_XATTR_INDEX_ENCRYPTION,
+ 			     EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, &ctx,
+ 			     sizeof(ctx), 0);
+-	if (!res)
++	if (!res) {
+ 		ext4_set_inode_flag(child, EXT4_INODE_ENCRYPT);
++		ext4_clear_inode_state(child, EXT4_STATE_MAY_INLINE_DATA);
++	}
+ 	return res;
+-
+ }
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index cac1968e63cb..213536fdab9f 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1374,12 +1374,6 @@ struct ext4_sb_info {
+ 	struct ratelimit_state s_err_ratelimit_state;
+ 	struct ratelimit_state s_warning_ratelimit_state;
+ 	struct ratelimit_state s_msg_ratelimit_state;
+-
+-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+-	/* Encryption */
+-	uint32_t s_file_encryption_mode;
+-	uint32_t s_dir_encryption_mode;
+-#endif
+ };
+ 
+ static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb)
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 1eaa6cb96cd0..ddca1697ad86 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -1034,28 +1034,9 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
+ 	ext4_set_inode_state(inode, EXT4_STATE_NEW);
+ 
+ 	ei->i_extra_isize = EXT4_SB(sb)->s_want_extra_isize;
+-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+-	if ((sbi->s_file_encryption_mode == EXT4_ENCRYPTION_MODE_INVALID) &&
+-	    (sbi->s_dir_encryption_mode == EXT4_ENCRYPTION_MODE_INVALID)) {
+-		ei->i_inline_off = 0;
+-		if (EXT4_HAS_INCOMPAT_FEATURE(sb,
+-			EXT4_FEATURE_INCOMPAT_INLINE_DATA))
+-			ext4_set_inode_state(inode,
+-			EXT4_STATE_MAY_INLINE_DATA);
+-	} else {
+-		/* Inline data and encryption are incompatible
+-		 * We turn off inline data since encryption is enabled */
+-		ei->i_inline_off = 1;
+-		if (EXT4_HAS_INCOMPAT_FEATURE(sb,
+-			EXT4_FEATURE_INCOMPAT_INLINE_DATA))
+-			ext4_clear_inode_state(inode,
+-			EXT4_STATE_MAY_INLINE_DATA);
+-	}
+-#else
+ 	ei->i_inline_off = 0;
+ 	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_INLINE_DATA))
+ 		ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
+-#endif
+ 	ret = inode;
+ 	err = dquot_alloc_inode(inode);
+ 	if (err)
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index e0dac100fbe6..b0bd1c1061b3 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3452,11 +3452,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	if (sb->s_bdev->bd_part)
+ 		sbi->s_sectors_written_start =
+ 			part_stat_read(sb->s_bdev->bd_part, sectors[1]);
+-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+-	/* Modes of operations for file and directory encryption. */
+-	sbi->s_file_encryption_mode = EXT4_ENCRYPTION_MODE_AES_256_XTS;
+-	sbi->s_dir_encryption_mode = EXT4_ENCRYPTION_MODE_INVALID;
+-#endif
+ 
+ 	/* Cleanup superblock name */
+ 	for (cp = sb->s_id; (cp = strchr(cp, '/'));)

commit b7236e21d55ff9008737621c84dd8ee6c37c7c6d
+Author: Theodore Ts'o 
+Date:   Mon May 18 13:17:47 2015 -0400
+
+    ext4 crypto: reorganize how we store keys in the inode
+    
+    This is a pretty massive patch which does a number of different things:
+    
+    1) The per-inode encryption information is now stored in an allocated
+       data structure, ext4_crypt_info, instead of directly in the node.
+       This reduces the size usage of an in-memory inode when it is not
+       using encryption.
+    
+    2) We drop the ext4_fname_crypto_ctx entirely, and use the per-inode
+       encryption structure instead.  This remove an unnecessary memory
+       allocation and free for the fname_crypto_ctx as well as allowing us
+       to reuse the ctfm in a directory for multiple lookups and file
+       creations.
+    
+    3) We also cache the inode's policy information in the ext4_crypt_info
+       structure so we don't have to continually read it out of the
+       extended attributes.
+    
+    4) We now keep the keyring key in the inode's encryption structure
+       instead of releasing it after we are done using it to derive the
+       per-inode key.  This allows us to test to see if the key has been
+       revoked; if it has, we prevent the use of the derived key and free
+       it.
+    
+    5) When an inode is released (or when the derived key is freed), we
+       will use memset_explicit() to zero out the derived key, so it's not
+       left hanging around in memory.  This implies that when a user logs
+       out, it is important to first revoke the key, and then unlink it,
+       and then finally, to use "echo 3 > /proc/sys/vm/drop_caches" to
+       release any decrypted pages and dcache entries from the system
+       caches.
+    
+    6) All this, and we also shrink the number of lines of code by around
+       100.  :-)
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
+index 918200ed9bf8..3a25aa4f3d94 100644
+--- a/fs/ext4/crypto.c
++++ b/fs/ext4/crypto.c
+@@ -118,8 +118,9 @@ struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode)
+ 	struct ext4_crypto_ctx *ctx = NULL;
+ 	int res = 0;
+ 	unsigned long flags;
+-	struct ext4_crypt_info *ci = &EXT4_I(inode)->i_crypt_info;
++	struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
+ 
++	BUG_ON(ci == NULL);
+ 	if (!ext4_read_workqueue)
+ 		ext4_init_crypto();
+ 
+@@ -322,7 +323,7 @@ static int ext4_page_crypto(struct ext4_crypto_ctx *ctx,
+ 	int res = 0;
+ 
+ 	BUG_ON(!ctx->tfm);
+-	BUG_ON(ctx->mode != ei->i_crypt_info.ci_mode);
++	BUG_ON(ctx->mode != ei->i_crypt_info->ci_mode);
+ 
+ 	if (ctx->mode != EXT4_ENCRYPTION_MODE_AES_256_XTS) {
+ 		printk_ratelimited(KERN_ERR
+@@ -334,8 +335,8 @@ static int ext4_page_crypto(struct ext4_crypto_ctx *ctx,
+ 	crypto_ablkcipher_clear_flags(atfm, ~0);
+ 	crypto_tfm_set_flags(ctx->tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+ 
+-	res = crypto_ablkcipher_setkey(atfm, ei->i_crypt_info.ci_raw,
+-				       ei->i_crypt_info.ci_size);
++	res = crypto_ablkcipher_setkey(atfm, ei->i_crypt_info->ci_raw,
++				       ei->i_crypt_info->ci_size);
+ 	if (res) {
+ 		printk_ratelimited(KERN_ERR
+ 				   "%s: crypto_ablkcipher_setkey() failed\n",
+diff --git a/fs/ext4/crypto_fname.c b/fs/ext4/crypto_fname.c
+index d9f08ddbfda2..374d0e790315 100644
+--- a/fs/ext4/crypto_fname.c
++++ b/fs/ext4/crypto_fname.c
+@@ -48,6 +48,12 @@ bool ext4_valid_filenames_enc_mode(uint32_t mode)
+ 	return (mode == EXT4_ENCRYPTION_MODE_AES_256_CTS);
+ }
+ 
++static unsigned max_name_len(struct inode *inode)
++{
++	return S_ISLNK(inode->i_mode) ? inode->i_sb->s_blocksize :
++		EXT4_NAME_LEN;
++}
++
+ /**
+  * ext4_fname_encrypt() -
+  *
+@@ -55,28 +61,30 @@ bool ext4_valid_filenames_enc_mode(uint32_t mode)
+  * ciphertext. Errors are returned as negative numbers.  We trust the caller to
+  * allocate sufficient memory to oname string.
+  */
+-static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx,
++static int ext4_fname_encrypt(struct inode *inode,
+ 			      const struct qstr *iname,
+ 			      struct ext4_str *oname)
+ {
+ 	u32 ciphertext_len;
+ 	struct ablkcipher_request *req = NULL;
+ 	DECLARE_EXT4_COMPLETION_RESULT(ecr);
+-	struct crypto_ablkcipher *tfm = ctx->ctfm;
++	struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
++	struct crypto_ablkcipher *tfm = ci->ci_ctfm;
+ 	int res = 0;
+ 	char iv[EXT4_CRYPTO_BLOCK_SIZE];
+ 	struct scatterlist src_sg, dst_sg;
+-	int padding = 4 << (ctx->flags & EXT4_POLICY_FLAGS_PAD_MASK);
++	int padding = 4 << (ci->ci_flags & EXT4_POLICY_FLAGS_PAD_MASK);
+ 	char *workbuf, buf[32], *alloc_buf = NULL;
++	unsigned lim = max_name_len(inode);
+ 
+-	if (iname->len <= 0 || iname->len > ctx->lim)
++	if (iname->len <= 0 || iname->len > lim)
+ 		return -EIO;
+ 
+ 	ciphertext_len = (iname->len < EXT4_CRYPTO_BLOCK_SIZE) ?
+ 		EXT4_CRYPTO_BLOCK_SIZE : iname->len;
+ 	ciphertext_len = ext4_fname_crypto_round_up(ciphertext_len, padding);
+-	ciphertext_len = (ciphertext_len > ctx->lim)
+-			? ctx->lim : ciphertext_len;
++	ciphertext_len = (ciphertext_len > lim)
++			? lim : ciphertext_len;
+ 
+ 	if (ciphertext_len <= sizeof(buf)) {
+ 		workbuf = buf;
+@@ -134,7 +142,7 @@ static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx,
+  *	Errors are returned as negative numbers.
+  *	We trust the caller to allocate sufficient memory to oname string.
+  */
+-static int ext4_fname_decrypt(struct ext4_fname_crypto_ctx *ctx,
++static int ext4_fname_decrypt(struct inode *inode,
+ 			      const struct ext4_str *iname,
+ 			      struct ext4_str *oname)
+ {
+@@ -142,11 +150,13 @@ static int ext4_fname_decrypt(struct ext4_fname_crypto_ctx *ctx,
+ 	struct ablkcipher_request *req = NULL;
+ 	DECLARE_EXT4_COMPLETION_RESULT(ecr);
+ 	struct scatterlist src_sg, dst_sg;
+-	struct crypto_ablkcipher *tfm = ctx->ctfm;
++	struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
++	struct crypto_ablkcipher *tfm = ci->ci_ctfm;
+ 	int res = 0;
+ 	char iv[EXT4_CRYPTO_BLOCK_SIZE];
++	unsigned lim = max_name_len(inode);
+ 
+-	if (iname->len <= 0 || iname->len > ctx->lim)
++	if (iname->len <= 0 || iname->len > lim)
+ 		return -EIO;
+ 
+ 	tmp_in[0].name = iname->name;
+@@ -242,171 +252,50 @@ static int digest_decode(const char *src, int len, char *dst)
+ 	return cp - dst;
+ }
+ 
+-/**
+- * ext4_free_fname_crypto_ctx() -
+- *
+- * Frees up a crypto context.
+- */
+-void ext4_free_fname_crypto_ctx(struct ext4_fname_crypto_ctx *ctx)
+-{
+-	if (ctx == NULL || IS_ERR(ctx))
+-		return;
+-
+-	if (ctx->ctfm && !IS_ERR(ctx->ctfm))
+-		crypto_free_ablkcipher(ctx->ctfm);
+-	if (ctx->htfm && !IS_ERR(ctx->htfm))
+-		crypto_free_hash(ctx->htfm);
+-	kfree(ctx);
+-}
+-
+-/**
+- * ext4_put_fname_crypto_ctx() -
+- *
+- * Return: The crypto context onto free list. If the free list is above a
+- * threshold, completely frees up the context, and returns the memory.
+- *
+- * TODO: Currently we directly free the crypto context. Eventually we should
+- * add code it to return to free list. Such an approach will increase
+- * efficiency of directory lookup.
+- */
+-void ext4_put_fname_crypto_ctx(struct ext4_fname_crypto_ctx **ctx)
++int ext4_setup_fname_crypto(struct inode *inode)
+ {
+-	if (*ctx == NULL || IS_ERR(*ctx))
+-		return;
+-	ext4_free_fname_crypto_ctx(*ctx);
+-	*ctx = NULL;
+-}
+-
+-/**
+- * ext4_alloc_fname_crypto_ctx() -
+- */
+-struct ext4_fname_crypto_ctx *ext4_alloc_fname_crypto_ctx(
+-	const struct ext4_crypt_info *ci)
+-{
+-	struct ext4_fname_crypto_ctx *ctx;
+-
+-	ctx = kmalloc(sizeof(struct ext4_fname_crypto_ctx), GFP_NOFS);
+-	if (ctx == NULL)
+-		return ERR_PTR(-ENOMEM);
+-	if (ci->ci_mode == EXT4_ENCRYPTION_MODE_INVALID) {
+-		/* This will automatically set key mode to invalid
+-		 * As enum for ENCRYPTION_MODE_INVALID is zero */
+-		memset(&ctx->ci, 0, sizeof(ctx->ci));
+-	} else {
+-		memcpy(&ctx->ci, ci, sizeof(struct ext4_crypt_info));
+-	}
+-	ctx->has_valid_key = (EXT4_ENCRYPTION_MODE_INVALID == ci->ci_mode)
+-		? 0 : 1;
+-	ctx->ctfm_key_is_ready = 0;
+-	ctx->ctfm = NULL;
+-	ctx->htfm = NULL;
+-	return ctx;
+-}
+-
+-/**
+- * ext4_get_fname_crypto_ctx() -
+- *
+- * Allocates a free crypto context and initializes it to hold
+- * the crypto material for the inode.
+- *
+- * Return: NULL if not encrypted. Error value on error. Valid pointer otherwise.
+- */
+-struct ext4_fname_crypto_ctx *ext4_get_fname_crypto_ctx(
+-	struct inode *inode, u32 max_ciphertext_len)
+-{
+-	struct ext4_fname_crypto_ctx *ctx;
+ 	struct ext4_inode_info *ei = EXT4_I(inode);
++	struct ext4_crypt_info *ci = ei->i_crypt_info;
++	struct crypto_ablkcipher *ctfm;
+ 	int res;
+ 
+ 	/* Check if the crypto policy is set on the inode */
+ 	res = ext4_encrypted_inode(inode);
+ 	if (res == 0)
+-		return NULL;
+-
+-	if (!ext4_has_encryption_key(inode))
+-		ext4_generate_encryption_key(inode);
+-
+-	/* Get a crypto context based on the key. */
+-	ctx = ext4_alloc_fname_crypto_ctx(&(ei->i_crypt_info));
+-	if (IS_ERR(ctx))
+-		return ctx;
+-
+-	ctx->flags = ei->i_crypt_policy_flags;
+-	if (ctx->has_valid_key) {
+-		if (ctx->ci.ci_mode != EXT4_ENCRYPTION_MODE_AES_256_CTS) {
+-			printk_once(KERN_WARNING
+-				    "ext4: unsupported key mode %d\n",
+-				    ctx->ci.ci_mode);
+-			return ERR_PTR(-ENOKEY);
+-		}
++		return 0;
+ 
+-		/* As a first cut, we will allocate new tfm in every call.
+-		 * later, we will keep the tfm around, in case the key gets
+-		 * re-used */
+-		if (ctx->ctfm == NULL) {
+-			ctx->ctfm = crypto_alloc_ablkcipher("cts(cbc(aes))",
+-					0, 0);
+-		}
+-		if (IS_ERR(ctx->ctfm)) {
+-			res = PTR_ERR(ctx->ctfm);
+-			printk(
+-			    KERN_DEBUG "%s: error (%d) allocating crypto tfm\n",
+-			    __func__, res);
+-			ctx->ctfm = NULL;
+-			ext4_put_fname_crypto_ctx(&ctx);
+-			return ERR_PTR(res);
+-		}
+-		if (ctx->ctfm == NULL) {
+-			printk(
+-			    KERN_DEBUG "%s: could not allocate crypto tfm\n",
+-			    __func__);
+-			ext4_put_fname_crypto_ctx(&ctx);
+-			return ERR_PTR(-ENOMEM);
+-		}
+-		ctx->lim = max_ciphertext_len;
+-		crypto_ablkcipher_clear_flags(ctx->ctfm, ~0);
+-		crypto_tfm_set_flags(crypto_ablkcipher_tfm(ctx->ctfm),
+-			CRYPTO_TFM_REQ_WEAK_KEY);
+-
+-		/* If we are lucky, we will get a context that is already
+-		 * set up with the right key. Else, we will have to
+-		 * set the key */
+-		if (!ctx->ctfm_key_is_ready) {
+-			/* Since our crypto objectives for filename encryption
+-			 * are pretty weak,
+-			 * we directly use the inode master key */
+-			res = crypto_ablkcipher_setkey(ctx->ctfm,
+-					ctx->ci.ci_raw, ctx->ci.ci_size);
+-			if (res) {
+-				ext4_put_fname_crypto_ctx(&ctx);
+-				return ERR_PTR(-EIO);
+-			}
+-			ctx->ctfm_key_is_ready = 1;
+-		} else {
+-			/* In the current implementation, key should never be
+-			 * marked "ready" for a context that has just been
+-			 * allocated. So we should never reach here */
+-			 BUG();
+-		}
+-	}
+-	if (ctx->htfm == NULL)
+-		ctx->htfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);
+-	if (IS_ERR(ctx->htfm)) {
+-		res = PTR_ERR(ctx->htfm);
+-		printk(KERN_DEBUG "%s: error (%d) allocating hash tfm\n",
+-			__func__, res);
+-		ctx->htfm = NULL;
+-		ext4_put_fname_crypto_ctx(&ctx);
+-		return ERR_PTR(res);
++	res = ext4_get_encryption_info(inode);
++	if (res < 0)
++		return res;
++	ci = ei->i_crypt_info;
++
++	if (!ci || ci->ci_ctfm)
++		return 0;
++
++	if (ci->ci_mode != EXT4_ENCRYPTION_MODE_AES_256_CTS) {
++		printk_once(KERN_WARNING "ext4: unsupported key mode %d\n",
++			    ci->ci_mode);
++		return -ENOKEY;
+ 	}
+-	if (ctx->htfm == NULL) {
+-		printk(KERN_DEBUG "%s: could not allocate hash tfm\n",
+-				__func__);
+-		ext4_put_fname_crypto_ctx(&ctx);
+-		return ERR_PTR(-ENOMEM);
++
++	ctfm = crypto_alloc_ablkcipher("cts(cbc(aes))", 0, 0);
++	if (!ctfm || IS_ERR(ctfm)) {
++		res = ctfm ? PTR_ERR(ctfm) : -ENOMEM;
++		printk(KERN_DEBUG "%s: error (%d) allocating crypto tfm\n",
++		       __func__, res);
++		return res;
+ 	}
++	crypto_ablkcipher_clear_flags(ctfm, ~0);
++	crypto_tfm_set_flags(crypto_ablkcipher_tfm(ctfm),
++			     CRYPTO_TFM_REQ_WEAK_KEY);
+ 
+-	return ctx;
++	res = crypto_ablkcipher_setkey(ctfm, ci->ci_raw, ci->ci_size);
++	if (res) {
++		crypto_free_ablkcipher(ctfm);
++		return -EIO;
++	}
++	ci->ci_ctfm = ctfm;
++	return 0;
+ }
+ 
+ /**
+@@ -419,41 +308,21 @@ u32 ext4_fname_crypto_round_up(u32 size, u32 blksize)
+ 	return ((size+blksize-1)/blksize)*blksize;
+ }
+ 
+-/**
+- * ext4_fname_crypto_namelen_on_disk() -
+- */
+-int ext4_fname_crypto_namelen_on_disk(struct ext4_fname_crypto_ctx *ctx,
+-				      u32 namelen)
+-{
+-	u32 ciphertext_len;
+-	int padding = 4 << (ctx->flags & EXT4_POLICY_FLAGS_PAD_MASK);
+-
+-	if (ctx == NULL)
+-		return -EIO;
+-	if (!(ctx->has_valid_key))
+-		return -EACCES;
+-	ciphertext_len = (namelen < EXT4_CRYPTO_BLOCK_SIZE) ?
+-		EXT4_CRYPTO_BLOCK_SIZE : namelen;
+-	ciphertext_len = ext4_fname_crypto_round_up(ciphertext_len, padding);
+-	ciphertext_len = (ciphertext_len > ctx->lim)
+-			? ctx->lim : ciphertext_len;
+-	return (int) ciphertext_len;
+-}
+-
+ /**
+  * ext4_fname_crypto_alloc_obuff() -
+  *
+  * Allocates an output buffer that is sufficient for the crypto operation
+  * specified by the context and the direction.
+  */
+-int ext4_fname_crypto_alloc_buffer(struct ext4_fname_crypto_ctx *ctx,
++int ext4_fname_crypto_alloc_buffer(struct inode *inode,
+ 				   u32 ilen, struct ext4_str *crypto_str)
+ {
+ 	unsigned int olen;
+-	int padding = 4 << (ctx->flags & EXT4_POLICY_FLAGS_PAD_MASK);
++	int padding = 16;
++	struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
+ 
+-	if (!ctx)
+-		return -EIO;
++	if (ci)
++		padding = 4 << (ci->ci_flags & EXT4_POLICY_FLAGS_PAD_MASK);
+ 	if (padding < EXT4_CRYPTO_BLOCK_SIZE)
+ 		padding = EXT4_CRYPTO_BLOCK_SIZE;
+ 	olen = ext4_fname_crypto_round_up(ilen, padding);
+@@ -484,7 +353,7 @@ void ext4_fname_crypto_free_buffer(struct ext4_str *crypto_str)
+ /**
+  * ext4_fname_disk_to_usr() - converts a filename from disk space to user space
+  */
+-int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
++int _ext4_fname_disk_to_usr(struct inode *inode,
+ 			    struct dx_hash_info *hinfo,
+ 			    const struct ext4_str *iname,
+ 			    struct ext4_str *oname)
+@@ -492,8 +361,6 @@ int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
+ 	char buf[24];
+ 	int ret;
+ 
+-	if (ctx == NULL)
+-		return -EIO;
+ 	if (iname->len < 3) {
+ 		/*Check for . and .. */
+ 		if (iname->name[0] == '.' && iname->name[iname->len-1] == '.') {
+@@ -503,8 +370,8 @@ int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
+ 			return oname->len;
+ 		}
+ 	}
+-	if (ctx->has_valid_key)
+-		return ext4_fname_decrypt(ctx, iname, oname);
++	if (EXT4_I(inode)->i_crypt_info)
++		return ext4_fname_decrypt(inode, iname, oname);
+ 
+ 	if (iname->len <= EXT4_FNAME_CRYPTO_DIGEST_SIZE) {
+ 		ret = digest_encode(iname->name, iname->len, oname->name);
+@@ -523,7 +390,7 @@ int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
+ 	return ret + 1;
+ }
+ 
+-int ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
++int ext4_fname_disk_to_usr(struct inode *inode,
+ 			   struct dx_hash_info *hinfo,
+ 			   const struct ext4_dir_entry_2 *de,
+ 			   struct ext4_str *oname)
+@@ -531,21 +398,20 @@ int ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
+ 	struct ext4_str iname = {.name = (unsigned char *) de->name,
+ 				 .len = de->name_len };
+ 
+-	return _ext4_fname_disk_to_usr(ctx, hinfo, &iname, oname);
++	return _ext4_fname_disk_to_usr(inode, hinfo, &iname, oname);
+ }
+ 
+ 
+ /**
+  * ext4_fname_usr_to_disk() - converts a filename from user space to disk space
+  */
+-int ext4_fname_usr_to_disk(struct ext4_fname_crypto_ctx *ctx,
++int ext4_fname_usr_to_disk(struct inode *inode,
+ 			   const struct qstr *iname,
+ 			   struct ext4_str *oname)
+ {
+ 	int res;
++	struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
+ 
+-	if (ctx == NULL)
+-		return -EIO;
+ 	if (iname->len < 3) {
+ 		/*Check for . and .. */
+ 		if (iname->name[0] == '.' &&
+@@ -556,8 +422,8 @@ int ext4_fname_usr_to_disk(struct ext4_fname_crypto_ctx *ctx,
+ 			return oname->len;
+ 		}
+ 	}
+-	if (ctx->has_valid_key) {
+-		res = ext4_fname_encrypt(ctx, iname, oname);
++	if (ci) {
++		res = ext4_fname_encrypt(inode, iname, oname);
+ 		return res;
+ 	}
+ 	/* Without a proper key, a user is not allowed to modify the filenames
+@@ -569,16 +435,13 @@ int ext4_fname_usr_to_disk(struct ext4_fname_crypto_ctx *ctx,
+ int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname,
+ 			      int lookup, struct ext4_filename *fname)
+ {
+-	struct ext4_fname_crypto_ctx *ctx;
++	struct ext4_crypt_info *ci;
+ 	int ret = 0, bigname = 0;
+ 
+ 	memset(fname, 0, sizeof(struct ext4_filename));
+ 	fname->usr_fname = iname;
+ 
+-	ctx = ext4_get_fname_crypto_ctx(dir, EXT4_NAME_LEN);
+-	if (IS_ERR(ctx))
+-		return PTR_ERR(ctx);
+-	if ((ctx == NULL) ||
++	if (!ext4_encrypted_inode(dir) ||
+ 	    ((iname->name[0] == '.') &&
+ 	     ((iname->len == 1) ||
+ 	      ((iname->name[1] == '.') && (iname->len == 2))))) {
+@@ -586,12 +449,16 @@ int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname,
+ 		fname->disk_name.len = iname->len;
+ 		goto out;
+ 	}
+-	if (ctx->has_valid_key) {
+-		ret = ext4_fname_crypto_alloc_buffer(ctx, iname->len,
++	ret = ext4_setup_fname_crypto(dir);
++	if (ret)
++		return ret;
++	ci = EXT4_I(dir)->i_crypt_info;
++	if (ci) {
++		ret = ext4_fname_crypto_alloc_buffer(dir, iname->len,
+ 						     &fname->crypto_buf);
+ 		if (ret < 0)
+ 			goto out;
+-		ret = ext4_fname_encrypt(ctx, iname, &fname->crypto_buf);
++		ret = ext4_fname_encrypt(dir, iname, &fname->crypto_buf);
+ 		if (ret < 0)
+ 			goto out;
+ 		fname->disk_name.name = fname->crypto_buf.name;
+@@ -634,7 +501,6 @@ int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname,
+ 	}
+ 	ret = 0;
+ out:
+-	ext4_put_fname_crypto_ctx(&ctx);
+ 	return ret;
+ }
+ 
+diff --git a/fs/ext4/crypto_key.c b/fs/ext4/crypto_key.c
+index ec6635dc50f9..0075e43ffea6 100644
+--- a/fs/ext4/crypto_key.c
++++ b/fs/ext4/crypto_key.c
+@@ -84,14 +84,26 @@ static int ext4_derive_key_aes(char deriving_key[EXT4_AES_128_ECB_KEY_SIZE],
+ 	return res;
+ }
+ 
+-/**
+- * ext4_generate_encryption_key() - generates an encryption key
+- * @inode: The inode to generate the encryption key for.
+- */
+-int ext4_generate_encryption_key(struct inode *inode)
++void ext4_free_encryption_info(struct inode *inode)
++{
++	struct ext4_inode_info *ei = EXT4_I(inode);
++	struct ext4_crypt_info *ci = ei->i_crypt_info;
++
++	if (!ci)
++		return;
++
++	if (ci->ci_keyring_key)
++		key_put(ci->ci_keyring_key);
++	crypto_free_ablkcipher(ci->ci_ctfm);
++	memzero_explicit(&ci->ci_raw, sizeof(ci->ci_raw));
++	kfree(ci);
++	ei->i_crypt_info = NULL;
++}
++
++int _ext4_get_encryption_info(struct inode *inode)
+ {
+ 	struct ext4_inode_info *ei = EXT4_I(inode);
+-	struct ext4_crypt_info *crypt_info = &ei->i_crypt_info;
++	struct ext4_crypt_info *crypt_info;
+ 	char full_key_descriptor[EXT4_KEY_DESC_PREFIX_SIZE +
+ 				 (EXT4_KEY_DESCRIPTOR_SIZE * 2) + 1];
+ 	struct key *keyring_key = NULL;
+@@ -99,18 +111,40 @@ int ext4_generate_encryption_key(struct inode *inode)
+ 	struct ext4_encryption_context ctx;
+ 	struct user_key_payload *ukp;
+ 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+-	int res = ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION,
+-				 EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
+-				 &ctx, sizeof(ctx));
++	int res;
+ 
+-	if (res != sizeof(ctx)) {
+-		if (res > 0)
+-			res = -EINVAL;
+-		goto out;
++	if (ei->i_crypt_info) {
++		if (!ei->i_crypt_info->ci_keyring_key ||
++		    key_validate(ei->i_crypt_info->ci_keyring_key) == 0)
++			return 0;
++		ext4_free_encryption_info(inode);
+ 	}
++
++	res = ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION,
++				 EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
++				 &ctx, sizeof(ctx));
++	if (res < 0) {
++		if (!DUMMY_ENCRYPTION_ENABLED(sbi))
++			return res;
++		ctx.contents_encryption_mode = EXT4_ENCRYPTION_MODE_AES_256_XTS;
++		ctx.filenames_encryption_mode =
++			EXT4_ENCRYPTION_MODE_AES_256_CTS;
++		ctx.flags = 0;
++	} else if (res != sizeof(ctx))
++		return -EINVAL;
+ 	res = 0;
+ 
++	crypt_info = kmalloc(sizeof(struct ext4_crypt_info), GFP_KERNEL);
++	if (!crypt_info)
++		return -ENOMEM;
++
+ 	ei->i_crypt_policy_flags = ctx.flags;
++	crypt_info->ci_flags = ctx.flags;
++	crypt_info->ci_data_mode = ctx.contents_encryption_mode;
++	crypt_info->ci_filename_mode = ctx.filenames_encryption_mode;
++	crypt_info->ci_ctfm = NULL;
++	memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor,
++	       sizeof(crypt_info->ci_master_key));
+ 	if (S_ISREG(inode->i_mode))
+ 		crypt_info->ci_mode = ctx.contents_encryption_mode;
+ 	else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+@@ -151,17 +185,23 @@ int ext4_generate_encryption_key(struct inode *inode)
+ 	res = ext4_derive_key_aes(ctx.nonce, master_key->raw,
+ 				  crypt_info->ci_raw);
+ out:
++	if (res < 0) {
++		if (res == -ENOKEY)
++			res = 0;
++		kfree(crypt_info);
++	} else {
++		ei->i_crypt_info = crypt_info;
++		crypt_info->ci_keyring_key = keyring_key;
++		keyring_key = NULL;
++	}
+ 	if (keyring_key)
+ 		key_put(keyring_key);
+-	if (res < 0)
+-		crypt_info->ci_mode = EXT4_ENCRYPTION_MODE_INVALID;
+ 	return res;
+ }
+ 
+ int ext4_has_encryption_key(struct inode *inode)
+ {
+ 	struct ext4_inode_info *ei = EXT4_I(inode);
+-	struct ext4_crypt_info *crypt_info = &ei->i_crypt_info;
+ 
+-	return (crypt_info->ci_mode != EXT4_ENCRYPTION_MODE_INVALID);
++	return (ei->i_crypt_info != NULL);
+ }
+diff --git a/fs/ext4/crypto_policy.c b/fs/ext4/crypto_policy.c
+index a6d6291aea16..370d3aa0a9cf 100644
+--- a/fs/ext4/crypto_policy.c
++++ b/fs/ext4/crypto_policy.c
+@@ -126,7 +126,7 @@ int ext4_get_policy(struct inode *inode, struct ext4_encryption_policy *policy)
+ int ext4_is_child_context_consistent_with_parent(struct inode *parent,
+ 						 struct inode *child)
+ {
+-	struct ext4_encryption_context parent_ctx, child_ctx;
++	struct ext4_crypt_info *parent_ci, *child_ci;
+ 	int res;
+ 
+ 	if ((parent == NULL) || (child == NULL)) {
+@@ -136,26 +136,28 @@ int ext4_is_child_context_consistent_with_parent(struct inode *parent,
+ 	/* no restrictions if the parent directory is not encrypted */
+ 	if (!ext4_encrypted_inode(parent))
+ 		return 1;
+-	res = ext4_xattr_get(parent, EXT4_XATTR_INDEX_ENCRYPTION,
+-			     EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
+-			     &parent_ctx, sizeof(parent_ctx));
+-	if (res != sizeof(parent_ctx))
+-		return 0;
+ 	/* if the child directory is not encrypted, this is always a problem */
+ 	if (!ext4_encrypted_inode(child))
+ 		return 0;
+-	res = ext4_xattr_get(child, EXT4_XATTR_INDEX_ENCRYPTION,
+-			     EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
+-			     &child_ctx, sizeof(child_ctx));
+-	if (res != sizeof(child_ctx))
++	res = ext4_get_encryption_info(parent);
++	if (res)
++		return 0;
++	res = ext4_get_encryption_info(child);
++	if (res)
++		return 0;
++	parent_ci = EXT4_I(parent)->i_crypt_info;
++	child_ci = EXT4_I(child)->i_crypt_info;
++	if (!parent_ci && !child_ci)
++		return 1;
++	if (!parent_ci || !child_ci)
+ 		return 0;
+-	return (memcmp(parent_ctx.master_key_descriptor,
+-		       child_ctx.master_key_descriptor,
++
++	return (memcmp(parent_ci->ci_master_key,
++		       child_ci->ci_master_key,
+ 		       EXT4_KEY_DESCRIPTOR_SIZE) == 0 &&
+-		(parent_ctx.contents_encryption_mode ==
+-		 child_ctx.contents_encryption_mode) &&
+-		(parent_ctx.filenames_encryption_mode ==
+-		 child_ctx.filenames_encryption_mode));
++		(parent_ci->ci_data_mode == child_ci->ci_data_mode) &&
++		(parent_ci->ci_filename_mode == child_ci->ci_filename_mode) &&
++		(parent_ci->ci_flags == child_ci->ci_flags));
+ }
+ 
+ /**
+@@ -168,31 +170,37 @@ int ext4_is_child_context_consistent_with_parent(struct inode *parent,
+ int ext4_inherit_context(struct inode *parent, struct inode *child)
+ {
+ 	struct ext4_encryption_context ctx;
+-	int res = ext4_xattr_get(parent, EXT4_XATTR_INDEX_ENCRYPTION,
+-				 EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
+-				 &ctx, sizeof(ctx));
++	struct ext4_crypt_info *ci;
++	int res;
++
++	res = ext4_get_encryption_info(parent);
++	if (res < 0)
++		return res;
++	ci = EXT4_I(parent)->i_crypt_info;
++	BUG_ON(ci == NULL);
+ 
+-	if (res != sizeof(ctx)) {
+-		if (DUMMY_ENCRYPTION_ENABLED(EXT4_SB(parent->i_sb))) {
+-			ctx.format = EXT4_ENCRYPTION_CONTEXT_FORMAT_V1;
+-			ctx.contents_encryption_mode =
+-				EXT4_ENCRYPTION_MODE_AES_256_XTS;
+-			ctx.filenames_encryption_mode =
+-				EXT4_ENCRYPTION_MODE_AES_256_CTS;
+-			ctx.flags = 0;
+-			memset(ctx.master_key_descriptor, 0x42,
+-			       EXT4_KEY_DESCRIPTOR_SIZE);
+-			res = 0;
+-		} else {
+-			goto out;
+-		}
++	ctx.format = EXT4_ENCRYPTION_CONTEXT_FORMAT_V1;
++	if (DUMMY_ENCRYPTION_ENABLED(EXT4_SB(parent->i_sb))) {
++		ctx.contents_encryption_mode = EXT4_ENCRYPTION_MODE_AES_256_XTS;
++		ctx.filenames_encryption_mode =
++			EXT4_ENCRYPTION_MODE_AES_256_CTS;
++		ctx.flags = 0;
++		memset(ctx.master_key_descriptor, 0x42,
++		       EXT4_KEY_DESCRIPTOR_SIZE);
++		res = 0;
++	} else {
++		ctx.contents_encryption_mode = ci->ci_data_mode;
++		ctx.filenames_encryption_mode = ci->ci_filename_mode;
++		ctx.flags = ci->ci_flags;
++		memcpy(ctx.master_key_descriptor, ci->ci_master_key,
++		       EXT4_KEY_DESCRIPTOR_SIZE);
+ 	}
+ 	get_random_bytes(ctx.nonce, EXT4_KEY_DERIVATION_NONCE_SIZE);
+ 	res = ext4_xattr_set(child, EXT4_XATTR_INDEX_ENCRYPTION,
+ 			     EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, &ctx,
+ 			     sizeof(ctx), 0);
+-out:
+ 	if (!res)
+ 		ext4_set_inode_flag(child, EXT4_INODE_ENCRYPT);
+ 	return res;
++
+ }
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index d799d5d571e9..28cb94fbb1c9 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -110,7 +110,6 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
+ 	struct super_block *sb = inode->i_sb;
+ 	struct buffer_head *bh = NULL;
+ 	int dir_has_error = 0;
+-	struct ext4_fname_crypto_ctx *enc_ctx = NULL;
+ 	struct ext4_str fname_crypto_str = {.name = NULL, .len = 0};
+ 
+ 	if (is_dx_dir(inode)) {
+@@ -134,16 +133,14 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
+ 			return err;
+ 	}
+ 
+-	enc_ctx = ext4_get_fname_crypto_ctx(inode, EXT4_NAME_LEN);
+-	if (IS_ERR(enc_ctx))
+-		return PTR_ERR(enc_ctx);
+-	if (enc_ctx) {
+-		err = ext4_fname_crypto_alloc_buffer(enc_ctx, EXT4_NAME_LEN,
++	err = ext4_setup_fname_crypto(inode);
++	if (err)
++		return err;
++	if (ext4_encrypted_inode(inode)) {
++		err = ext4_fname_crypto_alloc_buffer(inode, EXT4_NAME_LEN,
+ 						     &fname_crypto_str);
+-		if (err < 0) {
+-			ext4_put_fname_crypto_ctx(&enc_ctx);
++		if (err < 0)
+ 			return err;
+-		}
+ 	}
+ 
+ 	offset = ctx->pos & (sb->s_blocksize - 1);
+@@ -239,8 +236,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
+ 			offset += ext4_rec_len_from_disk(de->rec_len,
+ 					sb->s_blocksize);
+ 			if (le32_to_cpu(de->inode)) {
+-				if (enc_ctx == NULL) {
+-					/* Directory is not encrypted */
++				if (!ext4_encrypted_inode(inode)) {
+ 					if (!dir_emit(ctx, de->name,
+ 					    de->name_len,
+ 					    le32_to_cpu(de->inode),
+@@ -250,7 +246,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
+ 					int save_len = fname_crypto_str.len;
+ 
+ 					/* Directory is encrypted */
+-					err = ext4_fname_disk_to_usr(enc_ctx,
++					err = ext4_fname_disk_to_usr(inode,
+ 						NULL, de, &fname_crypto_str);
+ 					fname_crypto_str.len = save_len;
+ 					if (err < 0)
+@@ -275,7 +271,6 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
+ 	err = 0;
+ errout:
+ #ifdef CONFIG_EXT4_FS_ENCRYPTION
+-	ext4_put_fname_crypto_ctx(&enc_ctx);
+ 	ext4_fname_crypto_free_buffer(&fname_crypto_str);
+ #endif
+ 	brelse(bh);
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 3cf3bcb6b239..cac1968e63cb 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -955,7 +955,7 @@ struct ext4_inode_info {
+ 
+ #ifdef CONFIG_EXT4_FS_ENCRYPTION
+ 	/* Encryption params */
+-	struct ext4_crypt_info i_crypt_info;
++	struct ext4_crypt_info *i_crypt_info;
+ #endif
+ };
+ 
+@@ -2096,37 +2096,30 @@ static inline int ext4_sb_has_crypto(struct super_block *sb)
+ /* crypto_fname.c */
+ bool ext4_valid_filenames_enc_mode(uint32_t mode);
+ u32 ext4_fname_crypto_round_up(u32 size, u32 blksize);
+-int ext4_fname_crypto_alloc_buffer(struct ext4_fname_crypto_ctx *ctx,
++int ext4_fname_crypto_alloc_buffer(struct inode *inode,
+ 				   u32 ilen, struct ext4_str *crypto_str);
+-int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
++int _ext4_fname_disk_to_usr(struct inode *inode,
+ 			    struct dx_hash_info *hinfo,
+ 			    const struct ext4_str *iname,
+ 			    struct ext4_str *oname);
+-int ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
++int ext4_fname_disk_to_usr(struct inode *inode,
+ 			   struct dx_hash_info *hinfo,
+ 			   const struct ext4_dir_entry_2 *de,
+ 			   struct ext4_str *oname);
+-int ext4_fname_usr_to_disk(struct ext4_fname_crypto_ctx *ctx,
++int ext4_fname_usr_to_disk(struct inode *inode,
+ 			   const struct qstr *iname,
+ 			   struct ext4_str *oname);
+-int ext4_fname_crypto_namelen_on_disk(struct ext4_fname_crypto_ctx *ctx,
+-				      u32 namelen);
+ #ifdef CONFIG_EXT4_FS_ENCRYPTION
+-void ext4_put_fname_crypto_ctx(struct ext4_fname_crypto_ctx **ctx);
+-struct ext4_fname_crypto_ctx *ext4_get_fname_crypto_ctx(struct inode *inode,
+-							u32 max_len);
++int ext4_setup_fname_crypto(struct inode *inode);
+ void ext4_fname_crypto_free_buffer(struct ext4_str *crypto_str);
+ int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname,
+ 			      int lookup, struct ext4_filename *fname);
+ void ext4_fname_free_filename(struct ext4_filename *fname);
+ #else
+ static inline
+-void ext4_put_fname_crypto_ctx(struct ext4_fname_crypto_ctx **ctx) { }
+-static inline
+-struct ext4_fname_crypto_ctx *ext4_get_fname_crypto_ctx(struct inode *inode,
+-							u32 max_len)
++int ext4_setup_fname_crypto(struct inode *inode)
+ {
+-	return NULL;
++	return 0;
+ }
+ static inline void ext4_fname_crypto_free_buffer(struct ext4_str *p) { }
+ static inline int ext4_fname_setup_filename(struct inode *dir,
+@@ -2143,15 +2136,34 @@ static inline void ext4_fname_free_filename(struct ext4_filename *fname) { }
+ 
+ 
+ /* crypto_key.c */
+-int ext4_generate_encryption_key(struct inode *inode);
++void ext4_free_encryption_info(struct inode *inode);
++int _ext4_get_encryption_info(struct inode *inode);
+ 
+ #ifdef CONFIG_EXT4_FS_ENCRYPTION
+ int ext4_has_encryption_key(struct inode *inode);
++
++static inline int ext4_get_encryption_info(struct inode *inode)
++{
++	struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
++
++	if (!ci ||
++	    (ci->ci_keyring_key &&
++	     (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) |
++					   (1 << KEY_FLAG_REVOKED) |
++					   (1 << KEY_FLAG_DEAD)))))
++		return _ext4_get_encryption_info(inode);
++	return 0;
++}
++
+ #else
+ static inline int ext4_has_encryption_key(struct inode *inode)
+ {
+ 	return 0;
+ }
++static inline int ext4_get_encryption_info(struct inode *inode)
++{
++	return 0;
++}
+ #endif
+ 
+ 
+diff --git a/fs/ext4/ext4_crypto.h b/fs/ext4/ext4_crypto.h
+index deecbe8968d1..d29687c232bd 100644
+--- a/fs/ext4/ext4_crypto.h
++++ b/fs/ext4/ext4_crypto.h
+@@ -76,7 +76,13 @@ struct ext4_encryption_key {
+ struct ext4_crypt_info {
+ 	unsigned char	ci_mode;
+ 	unsigned char	ci_size;
++	char		ci_data_mode;
++	char		ci_filename_mode;
++	char		ci_flags;
++	struct crypto_ablkcipher *ci_ctfm;
++	struct key	*ci_keyring_key;
+ 	char		ci_raw[EXT4_MAX_KEY_SIZE];
++	char		ci_master_key[EXT4_KEY_DESCRIPTOR_SIZE];
+ };
+ 
+ #define EXT4_CTX_REQUIRES_FREE_ENCRYPT_FL             0x00000001
+@@ -128,16 +134,6 @@ struct ext4_str {
+ 	u32 len;
+ };
+ 
+-struct ext4_fname_crypto_ctx {
+-	u32 lim;
+-	struct crypto_ablkcipher *ctfm;
+-	struct crypto_hash *htfm;
+-	struct ext4_crypt_info ci;
+-	unsigned flags : 8;
+-	unsigned has_valid_key : 1;
+-	unsigned ctfm_key_is_ready : 1;
+-};
+-
+ /**
+  * For encrypted symlinks, the ciphertext length is stored at the beginning
+  * of the string in little-endian format.
+diff --git a/fs/ext4/file.c b/fs/ext4/file.c
+index 0613c256c344..875ca6b95a4b 100644
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -223,7 +223,7 @@ static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma)
+ 	struct inode *inode = file->f_mapping->host;
+ 
+ 	if (ext4_encrypted_inode(inode)) {
+-		int err = ext4_generate_encryption_key(inode);
++		int err = ext4_get_encryption_info(inode);
+ 		if (err)
+ 			return 0;
+ 	}
+@@ -289,7 +289,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
+ 	}
+ 	ret = dquot_file_open(inode, filp);
+ 	if (!ret && ext4_encrypted_inode(inode)) {
+-		ret = ext4_generate_encryption_key(inode);
++		ret = ext4_get_encryption_info(inode);
+ 		if (ret)
+ 			ret = -EACCES;
+ 	}
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index b3406434c267..9bed99fdd81a 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -607,17 +607,14 @@ static struct stats dx_show_leaf(struct inode *dir,
+ 				char *name;
+ 				struct ext4_str fname_crypto_str
+ 					= {.name = NULL, .len = 0};
+-				struct ext4_fname_crypto_ctx *ctx = NULL;
+ 				int res;
+ 
+ 				name  = de->name;
+ 				len = de->name_len;
+-				ctx = ext4_get_fname_crypto_ctx(dir,
+-								EXT4_NAME_LEN);
+-				if (IS_ERR(ctx)) {
+-					printk(KERN_WARNING "Error acquiring"
+-					" crypto ctxt--skipping crypto\n");
+-					ctx = NULL;
++				res = ext4_setup_fname_crypto(dir);
++				if (res) {
++					printk(KERN_WARNING "Error setting up"
++					       " fname crypto: %d\n", res);
+ 				}
+ 				if (ctx == NULL) {
+ 					/* Directory is not encrypted */
+@@ -637,7 +634,6 @@ static struct stats dx_show_leaf(struct inode *dir,
+ 							"allocating crypto "
+ 							"buffer--skipping "
+ 							"crypto\n");
+-						ext4_put_fname_crypto_ctx(&ctx);
+ 						ctx = NULL;
+ 					}
+ 					res = ext4_fname_disk_to_usr(ctx, NULL, de,
+@@ -658,7 +654,6 @@ static struct stats dx_show_leaf(struct inode *dir,
+ 					printk("%*.s:(E)%x.%u ", len, name,
+ 					       h.hash, (unsigned) ((char *) de
+ 								   - base));
+-					ext4_put_fname_crypto_ctx(&ctx);
+ 					ext4_fname_crypto_free_buffer(
+ 						&fname_crypto_str);
+ 				}
+@@ -944,7 +939,6 @@ static int htree_dirblock_to_tree(struct file *dir_file,
+ 	struct buffer_head *bh;
+ 	struct ext4_dir_entry_2 *de, *top;
+ 	int err = 0, count = 0;
+-	struct ext4_fname_crypto_ctx *ctx = NULL;
+ 	struct ext4_str fname_crypto_str = {.name = NULL, .len = 0}, tmp_str;
+ 
+ 	dxtrace(printk(KERN_INFO "In htree dirblock_to_tree: block %lu\n",
+@@ -959,17 +953,15 @@ static int htree_dirblock_to_tree(struct file *dir_file,
+ 					   EXT4_DIR_REC_LEN(0));
+ #ifdef CONFIG_EXT4_FS_ENCRYPTION
+ 	/* Check if the directory is encrypted */
+-	ctx = ext4_get_fname_crypto_ctx(dir, EXT4_NAME_LEN);
+-	if (IS_ERR(ctx)) {
+-		err = PTR_ERR(ctx);
++	err = ext4_setup_fname_crypto(dir);
++	if (err) {
+ 		brelse(bh);
+ 		return err;
+ 	}
+-	if (ctx != NULL) {
+-		err = ext4_fname_crypto_alloc_buffer(ctx, EXT4_NAME_LEN,
++	if (ext4_encrypted_inode(dir)) {
++		err = ext4_fname_crypto_alloc_buffer(dir, EXT4_NAME_LEN,
+ 						     &fname_crypto_str);
+ 		if (err < 0) {
+-			ext4_put_fname_crypto_ctx(&ctx);
+ 			brelse(bh);
+ 			return err;
+ 		}
+@@ -990,8 +982,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
+ 			continue;
+ 		if (de->inode == 0)
+ 			continue;
+-		if (ctx == NULL) {
+-			/* Directory is not encrypted */
++		if (!ext4_encrypted_inode(dir)) {
+ 			tmp_str.name = de->name;
+ 			tmp_str.len = de->name_len;
+ 			err = ext4_htree_store_dirent(dir_file,
+@@ -1001,7 +992,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
+ 			int save_len = fname_crypto_str.len;
+ 
+ 			/* Directory is encrypted */
+-			err = ext4_fname_disk_to_usr(ctx, hinfo, de,
++			err = ext4_fname_disk_to_usr(dir, hinfo, de,
+ 						     &fname_crypto_str);
+ 			if (err < 0) {
+ 				count = err;
+@@ -1021,7 +1012,6 @@ static int htree_dirblock_to_tree(struct file *dir_file,
+ errout:
+ 	brelse(bh);
+ #ifdef CONFIG_EXT4_FS_ENCRYPTION
+-	ext4_put_fname_crypto_ctx(&ctx);
+ 	ext4_fname_crypto_free_buffer(&fname_crypto_str);
+ #endif
+ 	return count;
+@@ -3107,7 +3097,6 @@ static int ext4_symlink(struct inode *dir,
+ 	}
+ 
+ 	if (encryption_required) {
+-		struct ext4_fname_crypto_ctx *ctx = NULL;
+ 		struct qstr istr;
+ 		struct ext4_str ostr;
+ 
+@@ -3119,19 +3108,14 @@ static int ext4_symlink(struct inode *dir,
+ 		err = ext4_inherit_context(dir, inode);
+ 		if (err)
+ 			goto err_drop_inode;
+-		ctx = ext4_get_fname_crypto_ctx(inode,
+-						inode->i_sb->s_blocksize);
+-		if (IS_ERR_OR_NULL(ctx)) {
+-			/* We just set the policy, so ctx should not be NULL */
+-			err = (ctx == NULL) ? -EIO : PTR_ERR(ctx);
++		err = ext4_setup_fname_crypto(inode);
++		if (err)
+ 			goto err_drop_inode;
+-		}
+ 		istr.name = (const unsigned char *) symname;
+ 		istr.len = len;
+ 		ostr.name = sd->encrypted_path;
+ 		ostr.len = disk_link.len;
+-		err = ext4_fname_usr_to_disk(ctx, &istr, &ostr);
+-		ext4_put_fname_crypto_ctx(&ctx);
++		err = ext4_fname_usr_to_disk(inode, &istr, &ostr);
+ 		if (err < 0)
+ 			goto err_drop_inode;
+ 		sd->len = cpu_to_le16(ostr.len);
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index bcd7a4bc9036..e0dac100fbe6 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -879,9 +879,8 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
+ 	atomic_set(&ei->i_unwritten, 0);
+ 	INIT_WORK(&ei->i_rsv_conversion_work, ext4_end_io_rsv_work);
+ #ifdef CONFIG_EXT4_FS_ENCRYPTION
+-	ei->i_crypt_info.ci_mode = EXT4_ENCRYPTION_MODE_INVALID;
++	ei->i_crypt_info = NULL;
+ #endif
+-
+ 	return &ei->vfs_inode;
+ }
+ 
+@@ -958,6 +957,10 @@ void ext4_clear_inode(struct inode *inode)
+ 		jbd2_free_inode(EXT4_I(inode)->jinode);
+ 		EXT4_I(inode)->jinode = NULL;
+ 	}
++#ifdef CONFIG_EXT4_FS_ENCRYPTION
++	if (EXT4_I(inode)->i_crypt_info)
++		ext4_free_encryption_info(inode);
++#endif
+ }
+ 
+ static struct inode *ext4_nfs_get_inode(struct super_block *sb,
+diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
+index ca65d45c7f8d..32870881188e 100644
+--- a/fs/ext4/symlink.c
++++ b/fs/ext4/symlink.c
+@@ -29,7 +29,6 @@ static void *ext4_follow_link(struct dentry *dentry, struct nameidata *nd)
+ 	char *caddr, *paddr = NULL;
+ 	struct ext4_str cstr, pstr;
+ 	struct inode *inode = d_inode(dentry);
+-	struct ext4_fname_crypto_ctx *ctx = NULL;
+ 	struct ext4_encrypted_symlink_data *sd;
+ 	loff_t size = min_t(loff_t, i_size_read(inode), PAGE_SIZE - 1);
+ 	int res;
+@@ -38,19 +37,17 @@ static void *ext4_follow_link(struct dentry *dentry, struct nameidata *nd)
+ 	if (!ext4_encrypted_inode(inode))
+ 		return page_follow_link_light(dentry, nd);
+ 
+-	ctx = ext4_get_fname_crypto_ctx(inode, inode->i_sb->s_blocksize);
+-	if (IS_ERR(ctx))
+-		return ctx;
++	res = ext4_setup_fname_crypto(inode);
++	if (res)
++		return ERR_PTR(res);
+ 
+ 	if (ext4_inode_is_fast_symlink(inode)) {
+ 		caddr = (char *) EXT4_I(inode)->i_data;
+ 		max_size = sizeof(EXT4_I(inode)->i_data);
+ 	} else {
+ 		cpage = read_mapping_page(inode->i_mapping, 0, NULL);
+-		if (IS_ERR(cpage)) {
+-			ext4_put_fname_crypto_ctx(&ctx);
++		if (IS_ERR(cpage))
+ 			return cpage;
+-		}
+ 		caddr = kmap(cpage);
+ 		caddr[size] = 0;
+ 	}
+@@ -75,21 +72,19 @@ static void *ext4_follow_link(struct dentry *dentry, struct nameidata *nd)
+ 	}
+ 	pstr.name = paddr;
+ 	pstr.len = plen;
+-	res = _ext4_fname_disk_to_usr(ctx, NULL, &cstr, &pstr);
++	res = _ext4_fname_disk_to_usr(inode, NULL, &cstr, &pstr);
+ 	if (res < 0)
+ 		goto errout;
+ 	/* Null-terminate the name */
+ 	if (res <= plen)
+ 		paddr[res] = '\0';
+ 	nd_set_link(nd, paddr);
+-	ext4_put_fname_crypto_ctx(&ctx);
+ 	if (cpage) {
+ 		kunmap(cpage);
+ 		page_cache_release(cpage);
+ 	}
+ 	return NULL;
+ errout:
+-	ext4_put_fname_crypto_ctx(&ctx);
+ 	if (cpage) {
+ 		kunmap(cpage);
+ 		page_cache_release(cpage);

commit e2881b1b51d871a72911faf2fc7e090655940506
+Author: Theodore Ts'o 
+Date:   Mon May 18 13:16:47 2015 -0400
+
+    ext4 crypto: separate kernel and userspace structure for the key
+    
+    Use struct ext4_encryption_key only for the master key passed via the
+    kernel keyring.
+    
+    For internal kernel space users, we now use struct ext4_crypt_info.
+    This will allow us to put information from the policy structure so we
+    can cache it and avoid needing to constantly looking up the extended
+    attribute.  We will do this in a spearate patch.  This patch is mostly
+    mechnical to make it easier for patch review.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
+index 8ff15273ab0c..918200ed9bf8 100644
+--- a/fs/ext4/crypto.c
++++ b/fs/ext4/crypto.c
+@@ -118,7 +118,7 @@ struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode)
+ 	struct ext4_crypto_ctx *ctx = NULL;
+ 	int res = 0;
+ 	unsigned long flags;
+-	struct ext4_encryption_key *key = &EXT4_I(inode)->i_encryption_key;
++	struct ext4_crypt_info *ci = &EXT4_I(inode)->i_crypt_info;
+ 
+ 	if (!ext4_read_workqueue)
+ 		ext4_init_crypto();
+@@ -152,14 +152,14 @@ struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode)
+ 
+ 	/* Allocate a new Crypto API context if we don't already have
+ 	 * one or if it isn't the right mode. */
+-	BUG_ON(key->mode == EXT4_ENCRYPTION_MODE_INVALID);
+-	if (ctx->tfm && (ctx->mode != key->mode)) {
++	BUG_ON(ci->ci_mode == EXT4_ENCRYPTION_MODE_INVALID);
++	if (ctx->tfm && (ctx->mode != ci->ci_mode)) {
+ 		crypto_free_tfm(ctx->tfm);
+ 		ctx->tfm = NULL;
+ 		ctx->mode = EXT4_ENCRYPTION_MODE_INVALID;
+ 	}
+ 	if (!ctx->tfm) {
+-		switch (key->mode) {
++		switch (ci->ci_mode) {
+ 		case EXT4_ENCRYPTION_MODE_AES_256_XTS:
+ 			ctx->tfm = crypto_ablkcipher_tfm(
+ 				crypto_alloc_ablkcipher("xts(aes)", 0, 0));
+@@ -177,9 +177,9 @@ struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode)
+ 			ctx->tfm = NULL;
+ 			goto out;
+ 		}
+-		ctx->mode = key->mode;
++		ctx->mode = ci->ci_mode;
+ 	}
+-	BUG_ON(key->size != ext4_encryption_key_size(key->mode));
++	BUG_ON(ci->ci_size != ext4_encryption_key_size(ci->ci_mode));
+ 
+ 	/* There shouldn't be a bounce page attached to the crypto
+ 	 * context at this point. */
+@@ -322,7 +322,7 @@ static int ext4_page_crypto(struct ext4_crypto_ctx *ctx,
+ 	int res = 0;
+ 
+ 	BUG_ON(!ctx->tfm);
+-	BUG_ON(ctx->mode != ei->i_encryption_key.mode);
++	BUG_ON(ctx->mode != ei->i_crypt_info.ci_mode);
+ 
+ 	if (ctx->mode != EXT4_ENCRYPTION_MODE_AES_256_XTS) {
+ 		printk_ratelimited(KERN_ERR
+@@ -334,8 +334,8 @@ static int ext4_page_crypto(struct ext4_crypto_ctx *ctx,
+ 	crypto_ablkcipher_clear_flags(atfm, ~0);
+ 	crypto_tfm_set_flags(ctx->tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+ 
+-	res = crypto_ablkcipher_setkey(atfm, ei->i_encryption_key.raw,
+-				       ei->i_encryption_key.size);
++	res = crypto_ablkcipher_setkey(atfm, ei->i_crypt_info.ci_raw,
++				       ei->i_crypt_info.ci_size);
+ 	if (res) {
+ 		printk_ratelimited(KERN_ERR
+ 				   "%s: crypto_ablkcipher_setkey() failed\n",
+diff --git a/fs/ext4/crypto_fname.c b/fs/ext4/crypto_fname.c
+index 23d7f1d56b00..d9f08ddbfda2 100644
+--- a/fs/ext4/crypto_fname.c
++++ b/fs/ext4/crypto_fname.c
+@@ -277,34 +277,25 @@ void ext4_put_fname_crypto_ctx(struct ext4_fname_crypto_ctx **ctx)
+ 	*ctx = NULL;
+ }
+ 
+-/**
+- * ext4_search_fname_crypto_ctx() -
+- */
+-static struct ext4_fname_crypto_ctx *ext4_search_fname_crypto_ctx(
+-		const struct ext4_encryption_key *key)
+-{
+-	return NULL;
+-}
+-
+ /**
+  * ext4_alloc_fname_crypto_ctx() -
+  */
+ struct ext4_fname_crypto_ctx *ext4_alloc_fname_crypto_ctx(
+-	const struct ext4_encryption_key *key)
++	const struct ext4_crypt_info *ci)
+ {
+ 	struct ext4_fname_crypto_ctx *ctx;
+ 
+ 	ctx = kmalloc(sizeof(struct ext4_fname_crypto_ctx), GFP_NOFS);
+ 	if (ctx == NULL)
+ 		return ERR_PTR(-ENOMEM);
+-	if (key->mode == EXT4_ENCRYPTION_MODE_INVALID) {
++	if (ci->ci_mode == EXT4_ENCRYPTION_MODE_INVALID) {
+ 		/* This will automatically set key mode to invalid
+ 		 * As enum for ENCRYPTION_MODE_INVALID is zero */
+-		memset(&ctx->key, 0, sizeof(ctx->key));
++		memset(&ctx->ci, 0, sizeof(ctx->ci));
+ 	} else {
+-		memcpy(&ctx->key, key, sizeof(struct ext4_encryption_key));
++		memcpy(&ctx->ci, ci, sizeof(struct ext4_crypt_info));
+ 	}
+-	ctx->has_valid_key = (EXT4_ENCRYPTION_MODE_INVALID == key->mode)
++	ctx->has_valid_key = (EXT4_ENCRYPTION_MODE_INVALID == ci->ci_mode)
+ 		? 0 : 1;
+ 	ctx->ctfm_key_is_ready = 0;
+ 	ctx->ctfm = NULL;
+@@ -335,21 +326,17 @@ struct ext4_fname_crypto_ctx *ext4_get_fname_crypto_ctx(
+ 	if (!ext4_has_encryption_key(inode))
+ 		ext4_generate_encryption_key(inode);
+ 
+-	/* Get a crypto context based on the key.
+-	 * A new context is allocated if no context matches the requested key.
+-	 */
+-	ctx = ext4_search_fname_crypto_ctx(&(ei->i_encryption_key));
+-	if (ctx == NULL)
+-		ctx = ext4_alloc_fname_crypto_ctx(&(ei->i_encryption_key));
++	/* Get a crypto context based on the key. */
++	ctx = ext4_alloc_fname_crypto_ctx(&(ei->i_crypt_info));
+ 	if (IS_ERR(ctx))
+ 		return ctx;
+ 
+ 	ctx->flags = ei->i_crypt_policy_flags;
+ 	if (ctx->has_valid_key) {
+-		if (ctx->key.mode != EXT4_ENCRYPTION_MODE_AES_256_CTS) {
++		if (ctx->ci.ci_mode != EXT4_ENCRYPTION_MODE_AES_256_CTS) {
+ 			printk_once(KERN_WARNING
+ 				    "ext4: unsupported key mode %d\n",
+-				    ctx->key.mode);
++				    ctx->ci.ci_mode);
+ 			return ERR_PTR(-ENOKEY);
+ 		}
+ 
+@@ -389,7 +376,7 @@ struct ext4_fname_crypto_ctx *ext4_get_fname_crypto_ctx(
+ 			 * are pretty weak,
+ 			 * we directly use the inode master key */
+ 			res = crypto_ablkcipher_setkey(ctx->ctfm,
+-					ctx->key.raw, ctx->key.size);
++					ctx->ci.ci_raw, ctx->ci.ci_size);
+ 			if (res) {
+ 				ext4_put_fname_crypto_ctx(&ctx);
+ 				return ERR_PTR(-EIO);
+diff --git a/fs/ext4/crypto_key.c b/fs/ext4/crypto_key.c
+index 52170d0b7c40..ec6635dc50f9 100644
+--- a/fs/ext4/crypto_key.c
++++ b/fs/ext4/crypto_key.c
+@@ -91,7 +91,7 @@ static int ext4_derive_key_aes(char deriving_key[EXT4_AES_128_ECB_KEY_SIZE],
+ int ext4_generate_encryption_key(struct inode *inode)
+ {
+ 	struct ext4_inode_info *ei = EXT4_I(inode);
+-	struct ext4_encryption_key *crypt_key = &ei->i_encryption_key;
++	struct ext4_crypt_info *crypt_info = &ei->i_crypt_info;
+ 	char full_key_descriptor[EXT4_KEY_DESC_PREFIX_SIZE +
+ 				 (EXT4_KEY_DESCRIPTOR_SIZE * 2) + 1];
+ 	struct key *keyring_key = NULL;
+@@ -112,17 +112,17 @@ int ext4_generate_encryption_key(struct inode *inode)
+ 
+ 	ei->i_crypt_policy_flags = ctx.flags;
+ 	if (S_ISREG(inode->i_mode))
+-		crypt_key->mode = ctx.contents_encryption_mode;
++		crypt_info->ci_mode = ctx.contents_encryption_mode;
+ 	else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+-		crypt_key->mode = ctx.filenames_encryption_mode;
++		crypt_info->ci_mode = ctx.filenames_encryption_mode;
+ 	else {
+ 		printk(KERN_ERR "ext4 crypto: Unsupported inode type.\n");
+ 		BUG();
+ 	}
+-	crypt_key->size = ext4_encryption_key_size(crypt_key->mode);
+-	BUG_ON(!crypt_key->size);
++	crypt_info->ci_size = ext4_encryption_key_size(crypt_info->ci_mode);
++	BUG_ON(!crypt_info->ci_size);
+ 	if (DUMMY_ENCRYPTION_ENABLED(sbi)) {
+-		memset(crypt_key->raw, 0x42, EXT4_AES_256_XTS_KEY_SIZE);
++		memset(crypt_info->ci_raw, 0x42, EXT4_AES_256_XTS_KEY_SIZE);
+ 		goto out;
+ 	}
+ 	memcpy(full_key_descriptor, EXT4_KEY_DESC_PREFIX,
+@@ -148,19 +148,20 @@ int ext4_generate_encryption_key(struct inode *inode)
+ 	BUILD_BUG_ON(EXT4_AES_128_ECB_KEY_SIZE !=
+ 		     EXT4_KEY_DERIVATION_NONCE_SIZE);
+ 	BUG_ON(master_key->size != EXT4_AES_256_XTS_KEY_SIZE);
+-	res = ext4_derive_key_aes(ctx.nonce, master_key->raw, crypt_key->raw);
++	res = ext4_derive_key_aes(ctx.nonce, master_key->raw,
++				  crypt_info->ci_raw);
+ out:
+ 	if (keyring_key)
+ 		key_put(keyring_key);
+ 	if (res < 0)
+-		crypt_key->mode = EXT4_ENCRYPTION_MODE_INVALID;
++		crypt_info->ci_mode = EXT4_ENCRYPTION_MODE_INVALID;
+ 	return res;
+ }
+ 
+ int ext4_has_encryption_key(struct inode *inode)
+ {
+ 	struct ext4_inode_info *ei = EXT4_I(inode);
+-	struct ext4_encryption_key *crypt_key = &ei->i_encryption_key;
++	struct ext4_crypt_info *crypt_info = &ei->i_crypt_info;
+ 
+-	return (crypt_key->mode != EXT4_ENCRYPTION_MODE_INVALID);
++	return (crypt_info->ci_mode != EXT4_ENCRYPTION_MODE_INVALID);
+ }
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 866831e7c136..3cf3bcb6b239 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -955,7 +955,7 @@ struct ext4_inode_info {
+ 
+ #ifdef CONFIG_EXT4_FS_ENCRYPTION
+ 	/* Encryption params */
+-	struct ext4_encryption_key i_encryption_key;
++	struct ext4_crypt_info i_crypt_info;
+ #endif
+ };
+ 
+diff --git a/fs/ext4/ext4_crypto.h b/fs/ext4/ext4_crypto.h
+index 552424ae3ab3..deecbe8968d1 100644
+--- a/fs/ext4/ext4_crypto.h
++++ b/fs/ext4/ext4_crypto.h
+@@ -66,10 +66,17 @@ struct ext4_encryption_context {
+ #define EXT4_KEY_DESC_PREFIX "ext4:"
+ #define EXT4_KEY_DESC_PREFIX_SIZE 5
+ 
++/* This is passed in from userspace into the kernel keyring */
+ struct ext4_encryption_key {
+-	uint32_t mode;
+-	char raw[EXT4_MAX_KEY_SIZE];
+-	uint32_t size;
++        __u32 mode;
++        char raw[EXT4_MAX_KEY_SIZE];
++        __u32 size;
++} __attribute__((__packed__));
++
++struct ext4_crypt_info {
++	unsigned char	ci_mode;
++	unsigned char	ci_size;
++	char		ci_raw[EXT4_MAX_KEY_SIZE];
+ };
+ 
+ #define EXT4_CTX_REQUIRES_FREE_ENCRYPT_FL             0x00000001
+@@ -125,7 +132,7 @@ struct ext4_fname_crypto_ctx {
+ 	u32 lim;
+ 	struct crypto_ablkcipher *ctfm;
+ 	struct crypto_hash *htfm;
+-	struct ext4_encryption_key key;
++	struct ext4_crypt_info ci;
+ 	unsigned flags : 8;
+ 	unsigned has_valid_key : 1;
+ 	unsigned ctfm_key_is_ready : 1;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index ca9d4a2fed41..bcd7a4bc9036 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -879,7 +879,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
+ 	atomic_set(&ei->i_unwritten, 0);
+ 	INIT_WORK(&ei->i_rsv_conversion_work, ext4_end_io_rsv_work);
+ #ifdef CONFIG_EXT4_FS_ENCRYPTION
+-	ei->i_encryption_key.mode = EXT4_ENCRYPTION_MODE_INVALID;
++	ei->i_crypt_info.ci_mode = EXT4_ENCRYPTION_MODE_INVALID;
+ #endif
+ 
+ 	return &ei->vfs_inode;

commit d229959072eba40e1c2a4f53f8af17f1e770eb66
+Author: Theodore Ts'o 
+Date:   Mon May 18 13:15:47 2015 -0400
+
+    ext4 crypto: don't allocate a page when encrypting/decrypting file names
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/crypto_fname.c b/fs/ext4/crypto_fname.c
+index ad5e32867de0..23d7f1d56b00 100644
+--- a/fs/ext4/crypto_fname.c
++++ b/fs/ext4/crypto_fname.c
+@@ -65,9 +65,9 @@ static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx,
+ 	struct crypto_ablkcipher *tfm = ctx->ctfm;
+ 	int res = 0;
+ 	char iv[EXT4_CRYPTO_BLOCK_SIZE];
+-	struct scatterlist sg[1];
++	struct scatterlist src_sg, dst_sg;
+ 	int padding = 4 << (ctx->flags & EXT4_POLICY_FLAGS_PAD_MASK);
+-	char *workbuf;
++	char *workbuf, buf[32], *alloc_buf = NULL;
+ 
+ 	if (iname->len <= 0 || iname->len > ctx->lim)
+ 		return -EIO;
+@@ -78,20 +78,27 @@ static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx,
+ 	ciphertext_len = (ciphertext_len > ctx->lim)
+ 			? ctx->lim : ciphertext_len;
+ 
++	if (ciphertext_len <= sizeof(buf)) {
++		workbuf = buf;
++	} else {
++		alloc_buf = kmalloc(ciphertext_len, GFP_NOFS);
++		if (!alloc_buf)
++			return -ENOMEM;
++		workbuf = alloc_buf;
++	}
++
+ 	/* Allocate request */
+ 	req = ablkcipher_request_alloc(tfm, GFP_NOFS);
+ 	if (!req) {
+ 		printk_ratelimited(
+ 		    KERN_ERR "%s: crypto_request_alloc() failed\n", __func__);
++		kfree(alloc_buf);
+ 		return -ENOMEM;
+ 	}
+ 	ablkcipher_request_set_callback(req,
+ 		CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
+ 		ext4_dir_crypt_complete, &ecr);
+ 
+-	/* Map the workpage */
+-	workbuf = kmap(ctx->workpage);
+-
+ 	/* Copy the input */
+ 	memcpy(workbuf, iname->name, iname->len);
+ 	if (iname->len < ciphertext_len)
+@@ -101,21 +108,16 @@ static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx,
+ 	memset(iv, 0, EXT4_CRYPTO_BLOCK_SIZE);
+ 
+ 	/* Create encryption request */
+-	sg_init_table(sg, 1);
+-	sg_set_page(sg, ctx->workpage, PAGE_SIZE, 0);
+-	ablkcipher_request_set_crypt(req, sg, sg, ciphertext_len, iv);
++	sg_init_one(&src_sg, workbuf, ciphertext_len);
++	sg_init_one(&dst_sg, oname->name, ciphertext_len);
++	ablkcipher_request_set_crypt(req, &src_sg, &dst_sg, ciphertext_len, iv);
+ 	res = crypto_ablkcipher_encrypt(req);
+ 	if (res == -EINPROGRESS || res == -EBUSY) {
+ 		BUG_ON(req->base.data != &ecr);
+ 		wait_for_completion(&ecr.completion);
+ 		res = ecr.res;
+ 	}
+-	if (res >= 0) {
+-		/* Copy the result to output */
+-		memcpy(oname->name, workbuf, ciphertext_len);
+-		res = ciphertext_len;
+-	}
+-	kunmap(ctx->workpage);
++	kfree(alloc_buf);
+ 	ablkcipher_request_free(req);
+ 	if (res < 0) {
+ 		printk_ratelimited(
+@@ -139,11 +141,10 @@ static int ext4_fname_decrypt(struct ext4_fname_crypto_ctx *ctx,
+ 	struct ext4_str tmp_in[2], tmp_out[1];
+ 	struct ablkcipher_request *req = NULL;
+ 	DECLARE_EXT4_COMPLETION_RESULT(ecr);
+-	struct scatterlist sg[1];
++	struct scatterlist src_sg, dst_sg;
+ 	struct crypto_ablkcipher *tfm = ctx->ctfm;
+ 	int res = 0;
+ 	char iv[EXT4_CRYPTO_BLOCK_SIZE];
+-	char *workbuf;
+ 
+ 	if (iname->len <= 0 || iname->len > ctx->lim)
+ 		return -EIO;
+@@ -163,31 +164,19 @@ static int ext4_fname_decrypt(struct ext4_fname_crypto_ctx *ctx,
+ 		CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
+ 		ext4_dir_crypt_complete, &ecr);
+ 
+-	/* Map the workpage */
+-	workbuf = kmap(ctx->workpage);
+-
+-	/* Copy the input */
+-	memcpy(workbuf, iname->name, iname->len);
+-
+ 	/* Initialize IV */
+ 	memset(iv, 0, EXT4_CRYPTO_BLOCK_SIZE);
+ 
+ 	/* Create encryption request */
+-	sg_init_table(sg, 1);
+-	sg_set_page(sg, ctx->workpage, PAGE_SIZE, 0);
+-	ablkcipher_request_set_crypt(req, sg, sg, iname->len, iv);
++	sg_init_one(&src_sg, iname->name, iname->len);
++	sg_init_one(&dst_sg, oname->name, oname->len);
++	ablkcipher_request_set_crypt(req, &src_sg, &dst_sg, iname->len, iv);
+ 	res = crypto_ablkcipher_decrypt(req);
+ 	if (res == -EINPROGRESS || res == -EBUSY) {
+ 		BUG_ON(req->base.data != &ecr);
+ 		wait_for_completion(&ecr.completion);
+ 		res = ecr.res;
+ 	}
+-	if (res >= 0) {
+-		/* Copy the result to output */
+-		memcpy(oname->name, workbuf, iname->len);
+-		res = iname->len;
+-	}
+-	kunmap(ctx->workpage);
+ 	ablkcipher_request_free(req);
+ 	if (res < 0) {
+ 		printk_ratelimited(
+@@ -267,8 +256,6 @@ void ext4_free_fname_crypto_ctx(struct ext4_fname_crypto_ctx *ctx)
+ 		crypto_free_ablkcipher(ctx->ctfm);
+ 	if (ctx->htfm && !IS_ERR(ctx->htfm))
+ 		crypto_free_hash(ctx->htfm);
+-	if (ctx->workpage && !IS_ERR(ctx->workpage))
+-		__free_page(ctx->workpage);
+ 	kfree(ctx);
+ }
+ 
+@@ -322,7 +309,6 @@ struct ext4_fname_crypto_ctx *ext4_alloc_fname_crypto_ctx(
+ 	ctx->ctfm_key_is_ready = 0;
+ 	ctx->ctfm = NULL;
+ 	ctx->htfm = NULL;
+-	ctx->workpage = NULL;
+ 	return ctx;
+ }
+ 
+@@ -390,24 +376,6 @@ struct ext4_fname_crypto_ctx *ext4_get_fname_crypto_ctx(
+ 			ext4_put_fname_crypto_ctx(&ctx);
+ 			return ERR_PTR(-ENOMEM);
+ 		}
+-		if (ctx->workpage == NULL)
+-			ctx->workpage = alloc_page(GFP_NOFS);
+-		if (IS_ERR(ctx->workpage)) {
+-			res = PTR_ERR(ctx->workpage);
+-			printk(
+-			    KERN_DEBUG "%s: error (%d) allocating work page\n",
+-			    __func__, res);
+-			ctx->workpage = NULL;
+-			ext4_put_fname_crypto_ctx(&ctx);
+-			return ERR_PTR(res);
+-		}
+-		if (ctx->workpage == NULL) {
+-			printk(
+-			    KERN_DEBUG "%s: could not allocate work page\n",
+-			    __func__);
+-			ext4_put_fname_crypto_ctx(&ctx);
+-			return ERR_PTR(-ENOMEM);
+-		}
+ 		ctx->lim = max_ciphertext_len;
+ 		crypto_ablkcipher_clear_flags(ctx->ctfm, ~0);
+ 		crypto_tfm_set_flags(crypto_ablkcipher_tfm(ctx->ctfm),
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index 5665d82d2332..d799d5d571e9 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -247,9 +247,12 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
+ 					    get_dtype(sb, de->file_type)))
+ 						goto done;
+ 				} else {
++					int save_len = fname_crypto_str.len;
++
+ 					/* Directory is encrypted */
+ 					err = ext4_fname_disk_to_usr(enc_ctx,
+ 						NULL, de, &fname_crypto_str);
++					fname_crypto_str.len = save_len;
+ 					if (err < 0)
+ 						goto errout;
+ 					if (!dir_emit(ctx,
+diff --git a/fs/ext4/ext4_crypto.h b/fs/ext4/ext4_crypto.h
+index d75159c101ce..552424ae3ab3 100644
+--- a/fs/ext4/ext4_crypto.h
++++ b/fs/ext4/ext4_crypto.h
+@@ -123,10 +123,8 @@ struct ext4_str {
+ 
+ struct ext4_fname_crypto_ctx {
+ 	u32 lim;
+-	char tmp_buf[EXT4_CRYPTO_BLOCK_SIZE];
+ 	struct crypto_ablkcipher *ctfm;
+ 	struct crypto_hash *htfm;
+-	struct page *workpage;
+ 	struct ext4_encryption_key key;
+ 	unsigned flags : 8;
+ 	unsigned has_valid_key : 1;
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 56c60cb2d3fe..b3406434c267 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -998,6 +998,8 @@ static int htree_dirblock_to_tree(struct file *dir_file,
+ 				   hinfo->hash, hinfo->minor_hash, de,
+ 				   &tmp_str);
+ 		} else {
++			int save_len = fname_crypto_str.len;
++
+ 			/* Directory is encrypted */
+ 			err = ext4_fname_disk_to_usr(ctx, hinfo, de,
+ 						     &fname_crypto_str);
+@@ -1008,6 +1010,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
+ 			err = ext4_htree_store_dirent(dir_file,
+ 				   hinfo->hash, hinfo->minor_hash, de,
+ 					&fname_crypto_str);
++			fname_crypto_str.len = save_len;
+ 		}
+ 		if (err != 0) {
+ 			count = err;
+@@ -3126,6 +3129,7 @@ static int ext4_symlink(struct inode *dir,
+ 		istr.name = (const unsigned char *) symname;
+ 		istr.len = len;
+ 		ostr.name = sd->encrypted_path;
++		ostr.len = disk_link.len;
+ 		err = ext4_fname_usr_to_disk(ctx, &istr, &ostr);
+ 		ext4_put_fname_crypto_ctx(&ctx);
+ 		if (err < 0)
+diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
+index 187b78920314..ca65d45c7f8d 100644
+--- a/fs/ext4/symlink.c
++++ b/fs/ext4/symlink.c
+@@ -74,6 +74,7 @@ static void *ext4_follow_link(struct dentry *dentry, struct nameidata *nd)
+ 		goto errout;
+ 	}
+ 	pstr.name = paddr;
++	pstr.len = plen;
+ 	res = _ext4_fname_disk_to_usr(ctx, NULL, &cstr, &pstr);
+ 	if (res < 0)
+ 		goto errout;

commit 5b643f9ce34df945e58c7176275d406aa0db704f
+Author: Theodore Ts'o 
+Date:   Mon May 18 13:14:47 2015 -0400
+
+    ext4 crypto: optimize filename encryption
+    
+    Encrypt the filename as soon it is passed in by the user.  This avoids
+    our needing to encrypt the filename 2 or 3 times while in the process
+    of creating a filename.
+    
+    Similarly, when looking up a directory entry, encrypt the filename
+    early, or if the encryption key is not available, base-64 decode the
+    file syystem so that the hash value and the last 16 bytes of the
+    encrypted filename is available in the new struct ext4_filename data
+    structure.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/crypto_fname.c b/fs/ext4/crypto_fname.c
+index fded02f72299..ad5e32867de0 100644
+--- a/fs/ext4/crypto_fname.c
++++ b/fs/ext4/crypto_fname.c
+@@ -611,109 +611,82 @@ int ext4_fname_usr_to_disk(struct ext4_fname_crypto_ctx *ctx,
+ 	return -EACCES;
+ }
+ 
+-/*
+- * Calculate the htree hash from a filename from user space
+- */
+-int ext4_fname_usr_to_hash(struct ext4_fname_crypto_ctx *ctx,
+-			    const struct qstr *iname,
+-			    struct dx_hash_info *hinfo)
++int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname,
++			      int lookup, struct ext4_filename *fname)
+ {
+-	struct ext4_str tmp;
+-	int ret = 0;
+-	char buf[EXT4_FNAME_CRYPTO_DIGEST_SIZE+1];
++	struct ext4_fname_crypto_ctx *ctx;
++	int ret = 0, bigname = 0;
++
++	memset(fname, 0, sizeof(struct ext4_filename));
++	fname->usr_fname = iname;
+ 
+-	if (!ctx ||
++	ctx = ext4_get_fname_crypto_ctx(dir, EXT4_NAME_LEN);
++	if (IS_ERR(ctx))
++		return PTR_ERR(ctx);
++	if ((ctx == NULL) ||
+ 	    ((iname->name[0] == '.') &&
+ 	     ((iname->len == 1) ||
+ 	      ((iname->name[1] == '.') && (iname->len == 2))))) {
+-		ext4fs_dirhash(iname->name, iname->len, hinfo);
+-		return 0;
++		fname->disk_name.name = (unsigned char *) iname->name;
++		fname->disk_name.len = iname->len;
++		goto out;
+ 	}
+-
+-	if (!ctx->has_valid_key && iname->name[0] == '_') {
+-		if (iname->len != 33)
+-			return -ENOENT;
+-		ret = digest_decode(iname->name+1, iname->len, buf);
+-		if (ret != 24)
+-			return -ENOENT;
+-		memcpy(&hinfo->hash, buf, 4);
+-		memcpy(&hinfo->minor_hash, buf + 4, 4);
+-		return 0;
++	if (ctx->has_valid_key) {
++		ret = ext4_fname_crypto_alloc_buffer(ctx, iname->len,
++						     &fname->crypto_buf);
++		if (ret < 0)
++			goto out;
++		ret = ext4_fname_encrypt(ctx, iname, &fname->crypto_buf);
++		if (ret < 0)
++			goto out;
++		fname->disk_name.name = fname->crypto_buf.name;
++		fname->disk_name.len = fname->crypto_buf.len;
++		ret = 0;
++		goto out;
+ 	}
+-
+-	if (!ctx->has_valid_key && iname->name[0] != '_') {
+-		if (iname->len > 43)
+-			return -ENOENT;
+-		ret = digest_decode(iname->name, iname->len, buf);
+-		ext4fs_dirhash(buf, ret, hinfo);
+-		return 0;
++	if (!lookup) {
++		ret = -EACCES;
++		goto out;
+ 	}
+ 
+-	/* First encrypt the plaintext name */
+-	ret = ext4_fname_crypto_alloc_buffer(ctx, iname->len, &tmp);
+-	if (ret < 0)
+-		return ret;
+-
+-	ret = ext4_fname_encrypt(ctx, iname, &tmp);
+-	if (ret >= 0) {
+-		ext4fs_dirhash(tmp.name, tmp.len, hinfo);
+-		ret = 0;
++	/* We don't have the key and we are doing a lookup; decode the
++	 * user-supplied name
++	 */
++	if (iname->name[0] == '_')
++		bigname = 1;
++	if ((bigname && (iname->len != 33)) ||
++	    (!bigname && (iname->len > 43))) {
++		ret = -ENOENT;
+ 	}
+-
+-	ext4_fname_crypto_free_buffer(&tmp);
++	fname->crypto_buf.name = kmalloc(32, GFP_KERNEL);
++	if (fname->crypto_buf.name == NULL) {
++		ret = -ENOMEM;
++		goto out;
++	}
++	ret = digest_decode(iname->name + bigname, iname->len - bigname,
++			    fname->crypto_buf.name);
++	if (ret < 0) {
++		ret = -ENOENT;
++		goto out;
++	}
++	fname->crypto_buf.len = ret;
++	if (bigname) {
++		memcpy(&fname->hinfo.hash, fname->crypto_buf.name, 4);
++		memcpy(&fname->hinfo.minor_hash, fname->crypto_buf.name + 4, 4);
++	} else {
++		fname->disk_name.name = fname->crypto_buf.name;
++		fname->disk_name.len = fname->crypto_buf.len;
++	}
++	ret = 0;
++out:
++	ext4_put_fname_crypto_ctx(&ctx);
+ 	return ret;
+ }
+ 
+-int ext4_fname_match(struct ext4_fname_crypto_ctx *ctx, struct ext4_str *cstr,
+-		     int len, const char * const name,
+-		     struct ext4_dir_entry_2 *de)
++void ext4_fname_free_filename(struct ext4_filename *fname)
+ {
+-	int ret = -ENOENT;
+-	int bigname = (*name == '_');
+-
+-	if (ctx->has_valid_key) {
+-		if (cstr->name == NULL) {
+-			struct qstr istr;
+-
+-			ret = ext4_fname_crypto_alloc_buffer(ctx, len, cstr);
+-			if (ret < 0)
+-				goto errout;
+-			istr.name = name;
+-			istr.len = len;
+-			ret = ext4_fname_encrypt(ctx, &istr, cstr);
+-			if (ret < 0)
+-				goto errout;
+-		}
+-	} else {
+-		if (cstr->name == NULL) {
+-			cstr->name = kmalloc(32, GFP_KERNEL);
+-			if (cstr->name == NULL)
+-				return -ENOMEM;
+-			if ((bigname && (len != 33)) ||
+-			    (!bigname && (len > 43)))
+-				goto errout;
+-			ret = digest_decode(name+bigname, len-bigname,
+-					    cstr->name);
+-			if (ret < 0) {
+-				ret = -ENOENT;
+-				goto errout;
+-			}
+-			cstr->len = ret;
+-		}
+-		if (bigname) {
+-			if (de->name_len < 16)
+-				return 0;
+-			ret = memcmp(de->name + de->name_len - 16,
+-				     cstr->name + 8, 16);
+-			return (ret == 0) ? 1 : 0;
+-		}
+-	}
+-	if (de->name_len != cstr->len)
+-		return 0;
+-	ret = memcmp(de->name, cstr->name, cstr->len);
+-	return (ret == 0) ? 1 : 0;
+-errout:
+-	kfree(cstr->name);
+-	cstr->name = NULL;
+-	return ret;
++	kfree(fname->crypto_buf.name);
++	fname->crypto_buf.name = NULL;
++	fname->usr_fname = NULL;
++	fname->disk_name.name = NULL;
+ }
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 9a83f149ac85..866831e7c136 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1838,6 +1838,17 @@ struct dx_hash_info
+  */
+ #define HASH_NB_ALWAYS		1
+ 
++struct ext4_filename {
++	const struct qstr *usr_fname;
++	struct ext4_str disk_name;
++	struct dx_hash_info hinfo;
++#ifdef CONFIG_EXT4_FS_ENCRYPTION
++	struct ext4_str crypto_buf;
++#endif
++};
++
++#define fname_name(p) ((p)->disk_name.name)
++#define fname_len(p)  ((p)->disk_name.len)
+ 
+ /*
+  * Describe an inode's exact location on disk and in memory
+@@ -2098,21 +2109,16 @@ int ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
+ int ext4_fname_usr_to_disk(struct ext4_fname_crypto_ctx *ctx,
+ 			   const struct qstr *iname,
+ 			   struct ext4_str *oname);
+-int ext4_fname_usr_to_hash(struct ext4_fname_crypto_ctx *ctx,
+-			   const struct qstr *iname,
+-			   struct dx_hash_info *hinfo);
+ int ext4_fname_crypto_namelen_on_disk(struct ext4_fname_crypto_ctx *ctx,
+ 				      u32 namelen);
+-int ext4_fname_match(struct ext4_fname_crypto_ctx *ctx, struct ext4_str *cstr,
+-		     int len, const char * const name,
+-		     struct ext4_dir_entry_2 *de);
+-
+-
+ #ifdef CONFIG_EXT4_FS_ENCRYPTION
+ void ext4_put_fname_crypto_ctx(struct ext4_fname_crypto_ctx **ctx);
+ struct ext4_fname_crypto_ctx *ext4_get_fname_crypto_ctx(struct inode *inode,
+ 							u32 max_len);
+ void ext4_fname_crypto_free_buffer(struct ext4_str *crypto_str);
++int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname,
++			      int lookup, struct ext4_filename *fname);
++void ext4_fname_free_filename(struct ext4_filename *fname);
+ #else
+ static inline
+ void ext4_put_fname_crypto_ctx(struct ext4_fname_crypto_ctx **ctx) { }
+@@ -2123,6 +2129,16 @@ struct ext4_fname_crypto_ctx *ext4_get_fname_crypto_ctx(struct inode *inode,
+ 	return NULL;
+ }
+ static inline void ext4_fname_crypto_free_buffer(struct ext4_str *p) { }
++static inline int ext4_fname_setup_filename(struct inode *dir,
++				     const struct qstr *iname,
++				     int lookup, struct ext4_filename *fname)
++{
++	fname->usr_fname = iname;
++	fname->disk_name.name = (unsigned char *) iname->name;
++	fname->disk_name.len = iname->len;
++	return 0;
++}
++static inline void ext4_fname_free_filename(struct ext4_filename *fname) { }
+ #endif
+ 
+ 
+@@ -2156,14 +2172,13 @@ extern void ext4_htree_free_dir_info(struct dir_private_info *p);
+ extern int ext4_find_dest_de(struct inode *dir, struct inode *inode,
+ 			     struct buffer_head *bh,
+ 			     void *buf, int buf_size,
+-			     const char *name, int namelen,
++			     struct ext4_filename *fname,
+ 			     struct ext4_dir_entry_2 **dest_de);
+ int ext4_insert_dentry(struct inode *dir,
+-			struct inode *inode,
+-			struct ext4_dir_entry_2 *de,
+-			int buf_size,
+-		       const struct qstr *iname,
+-			const char *name, int namelen);
++		       struct inode *inode,
++		       struct ext4_dir_entry_2 *de,
++		       int buf_size,
++		       struct ext4_filename *fname);
+ static inline void ext4_update_dx_flag(struct inode *inode)
+ {
+ 	if (!EXT4_HAS_COMPAT_FEATURE(inode->i_sb,
+@@ -2317,13 +2332,14 @@ extern int ext4_orphan_add(handle_t *, struct inode *);
+ extern int ext4_orphan_del(handle_t *, struct inode *);
+ extern int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
+ 				__u32 start_minor_hash, __u32 *next_hash);
+-extern int search_dir(struct buffer_head *bh,
+-		      char *search_buf,
+-		      int buf_size,
+-		      struct inode *dir,
+-		      const struct qstr *d_name,
+-		      unsigned int offset,
+-		      struct ext4_dir_entry_2 **res_dir);
++extern int ext4_search_dir(struct buffer_head *bh,
++			   char *search_buf,
++			   int buf_size,
++			   struct inode *dir,
++			   struct ext4_filename *fname,
++			   const struct qstr *d_name,
++			   unsigned int offset,
++			   struct ext4_dir_entry_2 **res_dir);
+ extern int ext4_generic_delete_entry(handle_t *handle,
+ 				     struct inode *dir,
+ 				     struct ext4_dir_entry_2 *de_del,
+@@ -2768,7 +2784,9 @@ extern int ext4_da_write_inline_data_begin(struct address_space *mapping,
+ extern int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos,
+ 					 unsigned len, unsigned copied,
+ 					 struct page *page);
+-extern int ext4_try_add_inline_entry(handle_t *handle, struct dentry *dentry,
++extern int ext4_try_add_inline_entry(handle_t *handle,
++				     struct ext4_filename *fname,
++				     struct dentry *dentry,
+ 				     struct inode *inode);
+ extern int ext4_try_create_inline_dir(handle_t *handle,
+ 				      struct inode *parent,
+@@ -2782,6 +2800,7 @@ extern int htree_inlinedir_to_tree(struct file *dir_file,
+ 				   __u32 start_hash, __u32 start_minor_hash,
+ 				   int *has_inline_data);
+ extern struct buffer_head *ext4_find_inline_entry(struct inode *dir,
++					struct ext4_filename *fname,
+ 					const struct qstr *d_name,
+ 					struct ext4_dir_entry_2 **res_dir,
+ 					int *has_inline_data);
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index 095c7a258d97..cd944a7a99cd 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -995,20 +995,18 @@ void ext4_show_inline_dir(struct inode *dir, struct buffer_head *bh,
+  * and -EEXIST if directory entry already exists.
+  */
+ static int ext4_add_dirent_to_inline(handle_t *handle,
++				     struct ext4_filename *fname,
+ 				     struct dentry *dentry,
+ 				     struct inode *inode,
+ 				     struct ext4_iloc *iloc,
+ 				     void *inline_start, int inline_size)
+ {
+ 	struct inode	*dir = d_inode(dentry->d_parent);
+-	const char	*name = dentry->d_name.name;
+-	int		namelen = dentry->d_name.len;
+ 	int		err;
+ 	struct ext4_dir_entry_2 *de;
+ 
+-	err = ext4_find_dest_de(dir, inode, iloc->bh,
+-				inline_start, inline_size,
+-				name, namelen, &de);
++	err = ext4_find_dest_de(dir, inode, iloc->bh, inline_start,
++				inline_size, fname, &de);
+ 	if (err)
+ 		return err;
+ 
+@@ -1016,8 +1014,7 @@ static int ext4_add_dirent_to_inline(handle_t *handle,
+ 	err = ext4_journal_get_write_access(handle, iloc->bh);
+ 	if (err)
+ 		return err;
+-	ext4_insert_dentry(dir, inode, de, inline_size, &dentry->d_name,
+-			   name, namelen);
++	ext4_insert_dentry(dir, inode, de, inline_size, fname);
+ 
+ 	ext4_show_inline_dir(dir, iloc->bh, inline_start, inline_size);
+ 
+@@ -1248,8 +1245,8 @@ static int ext4_convert_inline_data_nolock(handle_t *handle,
+  * If succeeds, return 0. If not, extended the inline dir and copied data to
+  * the new created block.
+  */
+-int ext4_try_add_inline_entry(handle_t *handle, struct dentry *dentry,
+-			      struct inode *inode)
++int ext4_try_add_inline_entry(handle_t *handle, struct ext4_filename *fname,
++			      struct dentry *dentry, struct inode *inode)
+ {
+ 	int ret, inline_size;
+ 	void *inline_start;
+@@ -1268,7 +1265,7 @@ int ext4_try_add_inline_entry(handle_t *handle, struct dentry *dentry,
+ 						 EXT4_INLINE_DOTDOT_SIZE;
+ 	inline_size = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DOTDOT_SIZE;
+ 
+-	ret = ext4_add_dirent_to_inline(handle, dentry, inode, &iloc,
++	ret = ext4_add_dirent_to_inline(handle, fname, dentry, inode, &iloc,
+ 					inline_start, inline_size);
+ 	if (ret != -ENOSPC)
+ 		goto out;
+@@ -1289,8 +1286,9 @@ int ext4_try_add_inline_entry(handle_t *handle, struct dentry *dentry,
+ 	if (inline_size) {
+ 		inline_start = ext4_get_inline_xattr_pos(dir, &iloc);
+ 
+-		ret = ext4_add_dirent_to_inline(handle, dentry, inode, &iloc,
+-						inline_start, inline_size);
++		ret = ext4_add_dirent_to_inline(handle, fname, dentry,
++						inode, &iloc, inline_start,
++						inline_size);
+ 
+ 		if (ret != -ENOSPC)
+ 			goto out;
+@@ -1611,6 +1609,7 @@ int ext4_try_create_inline_dir(handle_t *handle, struct inode *parent,
+ }
+ 
+ struct buffer_head *ext4_find_inline_entry(struct inode *dir,
++					struct ext4_filename *fname,
+ 					const struct qstr *d_name,
+ 					struct ext4_dir_entry_2 **res_dir,
+ 					int *has_inline_data)
+@@ -1632,8 +1631,8 @@ struct buffer_head *ext4_find_inline_entry(struct inode *dir,
+ 	inline_start = (void *)ext4_raw_inode(&iloc)->i_block +
+ 						EXT4_INLINE_DOTDOT_SIZE;
+ 	inline_size = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DOTDOT_SIZE;
+-	ret = search_dir(iloc.bh, inline_start, inline_size,
+-			 dir, d_name, 0, res_dir);
++	ret = ext4_search_dir(iloc.bh, inline_start, inline_size,
++			      dir, fname, d_name, 0, res_dir);
+ 	if (ret == 1)
+ 		goto out_find;
+ 	if (ret < 0)
+@@ -1645,8 +1644,8 @@ struct buffer_head *ext4_find_inline_entry(struct inode *dir,
+ 	inline_start = ext4_get_inline_xattr_pos(dir, &iloc);
+ 	inline_size = ext4_get_inline_size(dir) - EXT4_MIN_INLINE_DATA_SIZE;
+ 
+-	ret = search_dir(iloc.bh, inline_start, inline_size,
+-			 dir, d_name, 0, res_dir);
++	ret = ext4_search_dir(iloc.bh, inline_start, inline_size,
++			      dir, fname, d_name, 0, res_dir);
+ 	if (ret == 1)
+ 		goto out_find;
+ 
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 814f3beb4369..56c60cb2d3fe 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -248,7 +248,7 @@ static void dx_set_count(struct dx_entry *entries, unsigned value);
+ static void dx_set_limit(struct dx_entry *entries, unsigned value);
+ static unsigned dx_root_limit(struct inode *dir, unsigned infosize);
+ static unsigned dx_node_limit(struct inode *dir);
+-static struct dx_frame *dx_probe(const struct qstr *d_name,
++static struct dx_frame *dx_probe(struct ext4_filename *fname,
+ 				 struct inode *dir,
+ 				 struct dx_hash_info *hinfo,
+ 				 struct dx_frame *frame);
+@@ -267,10 +267,10 @@ static int ext4_htree_next_block(struct inode *dir, __u32 hash,
+ 				 struct dx_frame *frames,
+ 				 __u32 *start_hash);
+ static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
+-		const struct qstr *d_name,
++		struct ext4_filename *fname,
+ 		struct ext4_dir_entry_2 **res_dir);
+-static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+-			     struct inode *inode);
++static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
++			     struct dentry *dentry, struct inode *inode);
+ 
+ /* checksumming functions */
+ void initialize_dirent_tail(struct ext4_dir_entry_tail *t,
+@@ -724,7 +724,7 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir,
+  * back to userspace.
+  */
+ static struct dx_frame *
+-dx_probe(const struct qstr *d_name, struct inode *dir,
++dx_probe(struct ext4_filename *fname, struct inode *dir,
+ 	 struct dx_hash_info *hinfo, struct dx_frame *frame_in)
+ {
+ 	unsigned count, indirect;
+@@ -746,32 +746,14 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
+ 			     root->info.hash_version);
+ 		goto fail;
+ 	}
++	if (fname)
++		hinfo = &fname->hinfo;
+ 	hinfo->hash_version = root->info.hash_version;
+ 	if (hinfo->hash_version <= DX_HASH_TEA)
+ 		hinfo->hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned;
+ 	hinfo->seed = EXT4_SB(dir->i_sb)->s_hash_seed;
+-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+-	if (d_name) {
+-		struct ext4_fname_crypto_ctx *ctx = NULL;
+-		int res;
+-
+-		/* Check if the directory is encrypted */
+-		ctx = ext4_get_fname_crypto_ctx(dir, EXT4_NAME_LEN);
+-		if (IS_ERR(ctx)) {
+-			ret_err = ERR_PTR(PTR_ERR(ctx));
+-			goto fail;
+-		}
+-		res = ext4_fname_usr_to_hash(ctx, d_name, hinfo);
+-		if (res < 0) {
+-			ret_err = ERR_PTR(res);
+-			goto fail;
+-		}
+-		ext4_put_fname_crypto_ctx(&ctx);
+-	}
+-#else
+-	if (d_name)
+-		ext4fs_dirhash(d_name->name, d_name->len, hinfo);
+-#endif
++	if (fname && fname_name(fname))
++		ext4fs_dirhash(fname_name(fname), fname_len(fname), hinfo);
+ 	hash = hinfo->hash;
+ 
+ 	if (root->info.unused_flags & 1) {
+@@ -1155,12 +1137,13 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
+ 
+ static inline int search_dirblock(struct buffer_head *bh,
+ 				  struct inode *dir,
++				  struct ext4_filename *fname,
+ 				  const struct qstr *d_name,
+ 				  unsigned int offset,
+ 				  struct ext4_dir_entry_2 **res_dir)
+ {
+-	return search_dir(bh, bh->b_data, dir->i_sb->s_blocksize, dir,
+-			  d_name, offset, res_dir);
++	return ext4_search_dir(bh, bh->b_data, dir->i_sb->s_blocksize, dir,
++			       fname, d_name, offset, res_dir);
+ }
+ 
+ /*
+@@ -1242,54 +1225,54 @@ static void dx_insert_block(struct dx_frame *frame, u32 hash, ext4_lblk_t block)
+  * `len <= EXT4_NAME_LEN' is guaranteed by caller.
+  * `de != NULL' is guaranteed by caller.
+  */
+-static inline int ext4_match(struct ext4_fname_crypto_ctx *ctx,
+-			     struct ext4_str *fname_crypto_str,
+-			     int len, const char * const name,
++static inline int ext4_match(struct ext4_filename *fname,
+ 			     struct ext4_dir_entry_2 *de)
+ {
+-	int res;
++	const void *name = fname_name(fname);
++	u32 len = fname_len(fname);
+ 
+ 	if (!de->inode)
+ 		return 0;
+ 
+ #ifdef CONFIG_EXT4_FS_ENCRYPTION
+-	if (ctx)
+-		return ext4_fname_match(ctx, fname_crypto_str, len, name, de);
++	if (unlikely(!name)) {
++		if (fname->usr_fname->name[0] == '_') {
++			int ret;
++			if (de->name_len < 16)
++				return 0;
++			ret = memcmp(de->name + de->name_len - 16,
++				     fname->crypto_buf.name + 8, 16);
++			return (ret == 0) ? 1 : 0;
++		}
++		name = fname->crypto_buf.name;
++		len = fname->crypto_buf.len;
++	}
+ #endif
+-	if (len != de->name_len)
++	if (de->name_len != len)
+ 		return 0;
+-	res = memcmp(name, de->name, len);
+-	return (res == 0) ? 1 : 0;
++	return (memcmp(de->name, name, len) == 0) ? 1 : 0;
+ }
+ 
+ /*
+  * Returns 0 if not found, -1 on failure, and 1 on success
+  */
+-int search_dir(struct buffer_head *bh, char *search_buf, int buf_size,
+-	       struct inode *dir, const struct qstr *d_name,
+-	       unsigned int offset, struct ext4_dir_entry_2 **res_dir)
++int ext4_search_dir(struct buffer_head *bh, char *search_buf, int buf_size,
++		    struct inode *dir, struct ext4_filename *fname,
++		    const struct qstr *d_name,
++		    unsigned int offset, struct ext4_dir_entry_2 **res_dir)
+ {
+ 	struct ext4_dir_entry_2 * de;
+ 	char * dlimit;
+ 	int de_len;
+-	const char *name = d_name->name;
+-	int namelen = d_name->len;
+-	struct ext4_fname_crypto_ctx *ctx = NULL;
+-	struct ext4_str fname_crypto_str = {.name = NULL, .len = 0};
+ 	int res;
+ 
+-	ctx = ext4_get_fname_crypto_ctx(dir, EXT4_NAME_LEN);
+-	if (IS_ERR(ctx))
+-		return -1;
+-
+ 	de = (struct ext4_dir_entry_2 *)search_buf;
+ 	dlimit = search_buf + buf_size;
+ 	while ((char *) de < dlimit) {
+ 		/* this code is executed quadratically often */
+ 		/* do minimal checking `by hand' */
+ 		if ((char *) de + de->name_len <= dlimit) {
+-			res = ext4_match(ctx, &fname_crypto_str, namelen,
+-					 name, de);
++			res = ext4_match(fname, de);
+ 			if (res < 0) {
+ 				res = -1;
+ 				goto return_result;
+@@ -1322,8 +1305,6 @@ int search_dir(struct buffer_head *bh, char *search_buf, int buf_size,
+ 
+ 	res = 0;
+ return_result:
+-	ext4_put_fname_crypto_ctx(&ctx);
+-	ext4_fname_crypto_free_buffer(&fname_crypto_str);
+ 	return res;
+ }
+ 
+@@ -1370,7 +1351,8 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
+ 				   buffer */
+ 	int num = 0;
+ 	ext4_lblk_t  nblocks;
+-	int i, namelen;
++	int i, namelen, retval;
++	struct ext4_filename fname;
+ 
+ 	*res_dir = NULL;
+ 	sb = dir->i_sb;
+@@ -1378,14 +1360,18 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
+ 	if (namelen > EXT4_NAME_LEN)
+ 		return NULL;
+ 
++	retval = ext4_fname_setup_filename(dir, d_name, 1, &fname);
++	if (retval)
++		return ERR_PTR(retval);
++
+ 	if (ext4_has_inline_data(dir)) {
+ 		int has_inline_data = 1;
+-		ret = ext4_find_inline_entry(dir, d_name, res_dir,
++		ret = ext4_find_inline_entry(dir, &fname, d_name, res_dir,
+ 					     &has_inline_data);
+ 		if (has_inline_data) {
+ 			if (inlined)
+ 				*inlined = 1;
+-			return ret;
++			goto cleanup_and_exit;
+ 		}
+ 	}
+ 
+@@ -1400,14 +1386,14 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
+ 		goto restart;
+ 	}
+ 	if (is_dx(dir)) {
+-		bh = ext4_dx_find_entry(dir, d_name, res_dir);
++		ret = ext4_dx_find_entry(dir, &fname, res_dir);
+ 		/*
+ 		 * On success, or if the error was file not found,
+ 		 * return.  Otherwise, fall back to doing a search the
+ 		 * old fashioned way.
+ 		 */
+-		if (!IS_ERR(bh) || PTR_ERR(bh) != ERR_BAD_DX_DIR)
+-			return bh;
++		if (!IS_ERR(ret) || PTR_ERR(ret) != ERR_BAD_DX_DIR)
++			goto cleanup_and_exit;
+ 		dxtrace(printk(KERN_DEBUG "ext4_find_entry: dx failed, "
+ 			       "falling back\n"));
+ 	}
+@@ -1438,8 +1424,10 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
+ 				num++;
+ 				bh = ext4_getblk(NULL, dir, b++, 0);
+ 				if (unlikely(IS_ERR(bh))) {
+-					if (ra_max == 0)
+-						return bh;
++					if (ra_max == 0) {
++						ret = bh;
++						goto cleanup_and_exit;
++					}
+ 					break;
+ 				}
+ 				bh_use[ra_max] = bh;
+@@ -1469,7 +1457,7 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
+ 			goto next;
+ 		}
+ 		set_buffer_verified(bh);
+-		i = search_dirblock(bh, dir, d_name,
++		i = search_dirblock(bh, dir, &fname, d_name,
+ 			    block << EXT4_BLOCK_SIZE_BITS(sb), res_dir);
+ 		if (i == 1) {
+ 			EXT4_I(dir)->i_dir_start_lookup = block;
+@@ -1500,15 +1488,17 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
+ 	/* Clean up the read-ahead blocks */
+ 	for (; ra_ptr < ra_max; ra_ptr++)
+ 		brelse(bh_use[ra_ptr]);
++	ext4_fname_free_filename(&fname);
+ 	return ret;
+ }
+ 
+-static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct qstr *d_name,
+-		       struct ext4_dir_entry_2 **res_dir)
++static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
++			struct ext4_filename *fname,
++			struct ext4_dir_entry_2 **res_dir)
+ {
+ 	struct super_block * sb = dir->i_sb;
+-	struct dx_hash_info	hinfo;
+ 	struct dx_frame frames[2], *frame;
++	const struct qstr *d_name = fname->usr_fname;
+ 	struct buffer_head *bh;
+ 	ext4_lblk_t block;
+ 	int retval;
+@@ -1516,7 +1506,7 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q
+ #ifdef CONFIG_EXT4_FS_ENCRYPTION
+ 	*res_dir = NULL;
+ #endif
+-	frame = dx_probe(d_name, dir, &hinfo, frames);
++	frame = dx_probe(fname, dir, NULL, frames);
+ 	if (IS_ERR(frame))
+ 		return (struct buffer_head *) frame;
+ 	do {
+@@ -1525,7 +1515,7 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q
+ 		if (IS_ERR(bh))
+ 			goto errout;
+ 
+-		retval = search_dirblock(bh, dir, d_name,
++		retval = search_dirblock(bh, dir, fname, d_name,
+ 					 block << EXT4_BLOCK_SIZE_BITS(sb),
+ 					 res_dir);
+ 		if (retval == 1)
+@@ -1537,7 +1527,7 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q
+ 		}
+ 
+ 		/* Check to see if we should continue to search */
+-		retval = ext4_htree_next_block(dir, hinfo.hash, frame,
++		retval = ext4_htree_next_block(dir, fname->hinfo.hash, frame,
+ 					       frames, NULL);
+ 		if (retval < 0) {
+ 			ext4_warning(sb,
+@@ -1796,32 +1786,16 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
+ int ext4_find_dest_de(struct inode *dir, struct inode *inode,
+ 		      struct buffer_head *bh,
+ 		      void *buf, int buf_size,
+-		      const char *name, int namelen,
++		      struct ext4_filename *fname,
+ 		      struct ext4_dir_entry_2 **dest_de)
+ {
+ 	struct ext4_dir_entry_2 *de;
+-	unsigned short reclen = EXT4_DIR_REC_LEN(namelen);
++	unsigned short reclen = EXT4_DIR_REC_LEN(fname_len(fname));
+ 	int nlen, rlen;
+ 	unsigned int offset = 0;
+ 	char *top;
+-	struct ext4_fname_crypto_ctx *ctx = NULL;
+-	struct ext4_str fname_crypto_str = {.name = NULL, .len = 0};
+ 	int res;
+ 
+-	ctx = ext4_get_fname_crypto_ctx(dir, EXT4_NAME_LEN);
+-	if (IS_ERR(ctx))
+-		return -1;
+-
+-	if (ctx != NULL) {
+-		/* Calculate record length needed to store the entry */
+-		res = ext4_fname_crypto_namelen_on_disk(ctx, namelen);
+-		if (res < 0) {
+-			ext4_put_fname_crypto_ctx(&ctx);
+-			return res;
+-		}
+-		reclen = EXT4_DIR_REC_LEN(res);
+-	}
+-
+ 	de = (struct ext4_dir_entry_2 *)buf;
+ 	top = buf + buf_size - reclen;
+ 	while ((char *) de <= top) {
+@@ -1831,7 +1805,7 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode,
+ 			goto return_result;
+ 		}
+ 		/* Provide crypto context and crypto buffer to ext4 match */
+-		res = ext4_match(ctx, &fname_crypto_str, namelen, name, de);
++		res = ext4_match(fname, de);
+ 		if (res < 0)
+ 			goto return_result;
+ 		if (res > 0) {
+@@ -1853,8 +1827,6 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode,
+ 		res = 0;
+ 	}
+ return_result:
+-	ext4_put_fname_crypto_ctx(&ctx);
+-	ext4_fname_crypto_free_buffer(&fname_crypto_str);
+ 	return res;
+ }
+ 
+@@ -1862,39 +1834,10 @@ int ext4_insert_dentry(struct inode *dir,
+ 		       struct inode *inode,
+ 		       struct ext4_dir_entry_2 *de,
+ 		       int buf_size,
+-		       const struct qstr *iname,
+-		       const char *name, int namelen)
++		       struct ext4_filename *fname)
+ {
+ 
+ 	int nlen, rlen;
+-	struct ext4_fname_crypto_ctx *ctx = NULL;
+-	struct ext4_str fname_crypto_str = {.name = NULL, .len = 0};
+-	struct ext4_str tmp_str;
+-	int res;
+-
+-	ctx = ext4_get_fname_crypto_ctx(dir, EXT4_NAME_LEN);
+-	if (IS_ERR(ctx))
+-		return -EIO;
+-	/* By default, the input name would be written to the disk */
+-	tmp_str.name = (unsigned char *)name;
+-	tmp_str.len = namelen;
+-	if (ctx != NULL) {
+-		/* Directory is encrypted */
+-		res = ext4_fname_crypto_alloc_buffer(ctx, EXT4_NAME_LEN,
+-						     &fname_crypto_str);
+-		if (res < 0) {
+-			ext4_put_fname_crypto_ctx(&ctx);
+-			return -ENOMEM;
+-		}
+-		res = ext4_fname_usr_to_disk(ctx, iname, &fname_crypto_str);
+-		if (res < 0) {
+-			ext4_put_fname_crypto_ctx(&ctx);
+-			ext4_fname_crypto_free_buffer(&fname_crypto_str);
+-			return res;
+-		}
+-		tmp_str.name = fname_crypto_str.name;
+-		tmp_str.len = fname_crypto_str.len;
+-	}
+ 
+ 	nlen = EXT4_DIR_REC_LEN(de->name_len);
+ 	rlen = ext4_rec_len_from_disk(de->rec_len, buf_size);
+@@ -1908,11 +1851,8 @@ int ext4_insert_dentry(struct inode *dir,
+ 	de->file_type = EXT4_FT_UNKNOWN;
+ 	de->inode = cpu_to_le32(inode->i_ino);
+ 	ext4_set_de_type(inode->i_sb, de, inode->i_mode);
+-	de->name_len = tmp_str.len;
+-
+-	memcpy(de->name, tmp_str.name, tmp_str.len);
+-	ext4_put_fname_crypto_ctx(&ctx);
+-	ext4_fname_crypto_free_buffer(&fname_crypto_str);
++	de->name_len = fname_len(fname);
++	memcpy(de->name, fname_name(fname), fname_len(fname));
+ 	return 0;
+ }
+ 
+@@ -1924,13 +1864,11 @@ int ext4_insert_dentry(struct inode *dir,
+  * space.  It will return -ENOSPC if no space is available, and -EIO
+  * and -EEXIST if directory entry already exists.
+  */
+-static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
++static int add_dirent_to_buf(handle_t *handle, struct ext4_filename *fname,
++			     struct inode *dir,
+ 			     struct inode *inode, struct ext4_dir_entry_2 *de,
+ 			     struct buffer_head *bh)
+ {
+-	struct inode	*dir = d_inode(dentry->d_parent);
+-	const char	*name = dentry->d_name.name;
+-	int		namelen = dentry->d_name.len;
+ 	unsigned int	blocksize = dir->i_sb->s_blocksize;
+ 	int		csum_size = 0;
+ 	int		err;
+@@ -1939,9 +1877,8 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
+ 		csum_size = sizeof(struct ext4_dir_entry_tail);
+ 
+ 	if (!de) {
+-		err = ext4_find_dest_de(dir, inode,
+-					bh, bh->b_data, blocksize - csum_size,
+-					name, namelen, &de);
++		err = ext4_find_dest_de(dir, inode, bh, bh->b_data,
++					blocksize - csum_size, fname, &de);
+ 		if (err)
+ 			return err;
+ 	}
+@@ -1954,8 +1891,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
+ 
+ 	/* By now the buffer is marked for journaling. Due to crypto operations,
+ 	 * the following function call may fail */
+-	err = ext4_insert_dentry(dir, inode, de, blocksize, &dentry->d_name,
+-				 name, namelen);
++	err = ext4_insert_dentry(dir, inode, de, blocksize, fname);
+ 	if (err < 0)
+ 		return err;
+ 
+@@ -1985,17 +1921,11 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
+  * This converts a one block unindexed directory to a 3 block indexed
+  * directory, and adds the dentry to the indexed directory.
+  */
+-static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
++static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname,
++			    struct dentry *dentry,
+ 			    struct inode *inode, struct buffer_head *bh)
+ {
+ 	struct inode	*dir = d_inode(dentry->d_parent);
+-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+-	struct ext4_fname_crypto_ctx *ctx = NULL;
+-	int res;
+-#else
+-	const char	*name = dentry->d_name.name;
+-	int		namelen = dentry->d_name.len;
+-#endif
+ 	struct buffer_head *bh2;
+ 	struct dx_root	*root;
+ 	struct dx_frame	frames[2], *frame;
+@@ -2006,17 +1936,10 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
+ 	unsigned	len;
+ 	int		retval;
+ 	unsigned	blocksize;
+-	struct dx_hash_info hinfo;
+ 	ext4_lblk_t  block;
+ 	struct fake_dirent *fde;
+ 	int csum_size = 0;
+ 
+-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+-	ctx = ext4_get_fname_crypto_ctx(dir, EXT4_NAME_LEN);
+-	if (IS_ERR(ctx))
+-		return PTR_ERR(ctx);
+-#endif
+-
+ 	if (ext4_has_metadata_csum(inode->i_sb))
+ 		csum_size = sizeof(struct ext4_dir_entry_tail);
+ 
+@@ -2078,22 +2001,12 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
+ 	dx_set_limit(entries, dx_root_limit(dir, sizeof(root->info)));
+ 
+ 	/* Initialize as for dx_probe */
+-	hinfo.hash_version = root->info.hash_version;
+-	if (hinfo.hash_version <= DX_HASH_TEA)
+-		hinfo.hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned;
+-	hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed;
+-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+-	res = ext4_fname_usr_to_hash(ctx, &dentry->d_name, &hinfo);
+-	if (res < 0) {
+-		ext4_put_fname_crypto_ctx(&ctx);
+-		ext4_mark_inode_dirty(handle, dir);
+-		brelse(bh);
+-		return res;
+-	}
+-	ext4_put_fname_crypto_ctx(&ctx);
+-#else
+-	ext4fs_dirhash(name, namelen, &hinfo);
+-#endif
++	fname->hinfo.hash_version = root->info.hash_version;
++	if (fname->hinfo.hash_version <= DX_HASH_TEA)
++		fname->hinfo.hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned;
++	fname->hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed;
++	ext4fs_dirhash(fname_name(fname), fname_len(fname), &fname->hinfo);
++
+ 	memset(frames, 0, sizeof(frames));
+ 	frame = frames;
+ 	frame->entries = entries;
+@@ -2108,14 +2021,14 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
+ 	if (retval)
+ 		goto out_frames;	
+ 
+-	de = do_split(handle,dir, &bh, frame, &hinfo);
++	de = do_split(handle,dir, &bh, frame, &fname->hinfo);
+ 	if (IS_ERR(de)) {
+ 		retval = PTR_ERR(de);
+ 		goto out_frames;
+ 	}
+ 	dx_release(frames);
+ 
+-	retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
++	retval = add_dirent_to_buf(handle, fname, dir, inode, de, bh);
+ 	brelse(bh);
+ 	return retval;
+ out_frames:
+@@ -2147,6 +2060,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
+ 	struct ext4_dir_entry_2 *de;
+ 	struct ext4_dir_entry_tail *t;
+ 	struct super_block *sb;
++	struct ext4_filename fname;
+ 	int	retval;
+ 	int	dx_fallback=0;
+ 	unsigned blocksize;
+@@ -2161,10 +2075,15 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
+ 	if (!dentry->d_name.len)
+ 		return -EINVAL;
+ 
++	retval = ext4_fname_setup_filename(dir, &dentry->d_name, 0, &fname);
++	if (retval)
++		return retval;
++
+ 	if (ext4_has_inline_data(dir)) {
+-		retval = ext4_try_add_inline_entry(handle, dentry, inode);
++		retval = ext4_try_add_inline_entry(handle, &fname,
++						   dentry, inode);
+ 		if (retval < 0)
+-			return retval;
++			goto out;
+ 		if (retval == 1) {
+ 			retval = 0;
+ 			goto out;
+@@ -2172,7 +2091,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
+ 	}
+ 
+ 	if (is_dx(dir)) {
+-		retval = ext4_dx_add_entry(handle, dentry, inode);
++		retval = ext4_dx_add_entry(handle, &fname, dentry, inode);
+ 		if (!retval || (retval != ERR_BAD_DX_DIR))
+ 			goto out;
+ 		ext4_clear_inode_flag(dir, EXT4_INODE_INDEX);
+@@ -2182,24 +2101,31 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
+ 	blocks = dir->i_size >> sb->s_blocksize_bits;
+ 	for (block = 0; block < blocks; block++) {
+ 		bh = ext4_read_dirblock(dir, block, DIRENT);
+-		if (IS_ERR(bh))
+-			return PTR_ERR(bh);
+-
+-		retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh);
++		if (IS_ERR(bh)) {
++			retval = PTR_ERR(bh);
++			bh = NULL;
++			goto out;
++		}
++		retval = add_dirent_to_buf(handle, &fname, dir, inode,
++					   NULL, bh);
+ 		if (retval != -ENOSPC)
+ 			goto out;
+ 
+ 		if (blocks == 1 && !dx_fallback &&
+ 		    EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) {
+-			retval = make_indexed_dir(handle, dentry, inode, bh);
++			retval = make_indexed_dir(handle, &fname, dentry,
++						  inode, bh);
+ 			bh = NULL; /* make_indexed_dir releases bh */
+ 			goto out;
+ 		}
+ 		brelse(bh);
+ 	}
+ 	bh = ext4_append(handle, dir, &block);
+-	if (IS_ERR(bh))
+-		return PTR_ERR(bh);
++	if (IS_ERR(bh)) {
++		retval = PTR_ERR(bh);
++		bh = NULL;
++		goto out;
++	}
+ 	de = (struct ext4_dir_entry_2 *) bh->b_data;
+ 	de->inode = 0;
+ 	de->rec_len = ext4_rec_len_to_disk(blocksize - csum_size, blocksize);
+@@ -2209,8 +2135,9 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
+ 		initialize_dirent_tail(t, blocksize);
+ 	}
+ 
+-	retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
++	retval = add_dirent_to_buf(handle, &fname, dir, inode, de, bh);
+ out:
++	ext4_fname_free_filename(&fname);
+ 	brelse(bh);
+ 	if (retval == 0)
+ 		ext4_set_inode_state(inode, EXT4_STATE_NEWENTRY);
+@@ -2220,19 +2147,18 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
+ /*
+  * Returns 0 for success, or a negative error value
+  */
+-static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+-			     struct inode *inode)
++static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
++			     struct dentry *dentry, struct inode *inode)
+ {
+ 	struct dx_frame frames[2], *frame;
+ 	struct dx_entry *entries, *at;
+-	struct dx_hash_info hinfo;
+ 	struct buffer_head *bh;
+ 	struct inode *dir = d_inode(dentry->d_parent);
+ 	struct super_block *sb = dir->i_sb;
+ 	struct ext4_dir_entry_2 *de;
+ 	int err;
+ 
+-	frame = dx_probe(&dentry->d_name, dir, &hinfo, frames);
++	frame = dx_probe(fname, dir, NULL, frames);
+ 	if (IS_ERR(frame))
+ 		return PTR_ERR(frame);
+ 	entries = frame->entries;
+@@ -2249,7 +2175,7 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+ 	if (err)
+ 		goto journal_error;
+ 
+-	err = add_dirent_to_buf(handle, dentry, inode, NULL, bh);
++	err = add_dirent_to_buf(handle, fname, dir, inode, NULL, bh);
+ 	if (err != -ENOSPC)
+ 		goto cleanup;
+ 
+@@ -2345,12 +2271,12 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+ 			goto cleanup;
+ 		}
+ 	}
+-	de = do_split(handle, dir, &bh, frame, &hinfo);
++	de = do_split(handle, dir, &bh, frame, &fname->hinfo);
+ 	if (IS_ERR(de)) {
+ 		err = PTR_ERR(de);
+ 		goto cleanup;
+ 	}
+-	err = add_dirent_to_buf(handle, dentry, inode, de, bh);
++	err = add_dirent_to_buf(handle, fname, dir, inode, de, bh);
+ 	goto cleanup;
+ 
+ journal_error:

commit b9576fc3624eb9fc88bec0d0ae883fd78be86239
+Author: Theodore Ts'o 
+Date:   Fri May 15 00:24:10 2015 -0400
+
+    ext4: fix an ext3 collapse range regression in xfstests
+    
+    The xfstests test suite assumes that an attempt to collapse range on
+    the range (0, 1) will return EOPNOTSUPP if the file system does not
+    support collapse range.  Commit 280227a75b56: "ext4: move check under
+    lock scope to close a race" broke this, and this caused xfstests to
+    fail when run when testing file systems that did not have the extents
+    feature enabled.
+    
+    Reported-by: Eric Whitney 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 451b92a9958a..e003a1e81dc3 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -5396,6 +5396,14 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
+ 	loff_t new_size, ioffset;
+ 	int ret;
+ 
++	/*
++	 * We need to test this early because xfstests assumes that a
++	 * collapse range of (0, 1) will return EOPNOTSUPP if the file
++	 * system does not support collapse range.
++	 */
++	if (!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
++		return -EOPNOTSUPP;
++
+ 	/* Collapse range works only on fs block size aligned offsets. */
+ 	if (offset & (EXT4_CLUSTER_SIZE(sb) - 1) ||
+ 	    len & (EXT4_CLUSTER_SIZE(sb) - 1))

commit 92c82639106214a9d34daa2bc791605eb1faab07
+Author: Theodore Ts'o 
+Date:   Thu May 14 18:43:36 2015 -0400
+
+    ext4: remove unused function prototype from ext4.h
+    
+    The ext4_extent_tree_init() function hasn't been in the ext4 code for
+    a long time ago, except in an unused function prototype in ext4.h
+    
+    Google-Bug-Id: 4530137
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 009a0590b20f..9a83f149ac85 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2889,7 +2889,6 @@ extern int ext4_map_blocks(handle_t *handle, struct inode *inode,
+ 			   struct ext4_map_blocks *map, int flags);
+ extern int ext4_ext_calc_metadata_amount(struct inode *inode,
+ 					 ext4_lblk_t lblocks);
+-extern int ext4_extent_tree_init(handle_t *, struct inode *);
+ extern int ext4_ext_calc_credits_for_single_extent(struct inode *inode,
+ 						   int num,
+ 						   struct ext4_ext_path *path);

commit 1b46617b8d0851c78b6440701d78fffbd9170741
+Author: Theodore Ts'o 
+Date:   Thu May 14 18:37:30 2015 -0400
+
+    ext4: don't save the error information if the block device is read-only
+    
+    Google-Bug-Id: 20939131
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index f06d0589ddba..ca9d4a2fed41 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -294,6 +294,8 @@ static void __save_error_info(struct super_block *sb, const char *func,
+ 	struct ext4_super_block *es = EXT4_SB(sb)->s_es;
+ 
+ 	EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
++	if (bdev_read_only(sb->s_bdev))
++		return;
+ 	es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
+ 	es->s_last_error_time = cpu_to_le32(get_seconds());
+ 	strncpy(es->s_last_error_func, func, sizeof(es->s_last_error_func));

commit 8f4d855839179f410fa910a26eb81d646d628f26
+Author: Theodore Ts'o 
+Date:   Thu May 14 18:19:01 2015 -0400
+
+    ext4: fix lazytime optimization
+    
+    We had a fencepost error in the lazytime optimization which means that
+    timestamp would get written to the wrong inode.
+    
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 55b187c3bac1..0554b0b5957b 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4345,7 +4345,7 @@ static void ext4_update_other_inodes_time(struct super_block *sb,
+ 	int inode_size = EXT4_INODE_SIZE(sb);
+ 
+ 	oi.orig_ino = orig_ino;
+-	ino = orig_ino & ~(inodes_per_block - 1);
++	ino = (orig_ino & ~(inodes_per_block - 1)) + 1;
+ 	for (i = 0; i < inodes_per_block; i++, ino++, buf += inode_size) {
+ 		if (ino == orig_ino)
+ 			continue;

commit a44cd7a05496d60fd2ba8cca080e3db8f481549b
+Author: Theodore Ts'o 
+Date:   Fri May 1 16:56:50 2015 -0400
+
+    ext4 crypto: add padding to filenames before encrypting
+    
+    This obscures the length of the filenames, to decrease the amount of
+    information leakage.  By default, we pad the filenames to the next 4
+    byte boundaries.  This costs nothing, since the directory entries are
+    aligned to 4 byte boundaries anyway.  Filenames can also be padded to
+    8, 16, or 32 bytes, which will consume more directory space.
+    
+    Change-Id: Ibb7a0fb76d2c48e2061240a709358ff40b14f322
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/crypto_fname.c b/fs/ext4/crypto_fname.c
+index 7a877e609e5f..fded02f72299 100644
+--- a/fs/ext4/crypto_fname.c
++++ b/fs/ext4/crypto_fname.c
+@@ -66,6 +66,7 @@ static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx,
+ 	int res = 0;
+ 	char iv[EXT4_CRYPTO_BLOCK_SIZE];
+ 	struct scatterlist sg[1];
++	int padding = 4 << (ctx->flags & EXT4_POLICY_FLAGS_PAD_MASK);
+ 	char *workbuf;
+ 
+ 	if (iname->len <= 0 || iname->len > ctx->lim)
+@@ -73,6 +74,7 @@ static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx,
+ 
+ 	ciphertext_len = (iname->len < EXT4_CRYPTO_BLOCK_SIZE) ?
+ 		EXT4_CRYPTO_BLOCK_SIZE : iname->len;
++	ciphertext_len = ext4_fname_crypto_round_up(ciphertext_len, padding);
+ 	ciphertext_len = (ciphertext_len > ctx->lim)
+ 			? ctx->lim : ciphertext_len;
+ 
+@@ -101,7 +103,7 @@ static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx,
+ 	/* Create encryption request */
+ 	sg_init_table(sg, 1);
+ 	sg_set_page(sg, ctx->workpage, PAGE_SIZE, 0);
+-	ablkcipher_request_set_crypt(req, sg, sg, iname->len, iv);
++	ablkcipher_request_set_crypt(req, sg, sg, ciphertext_len, iv);
+ 	res = crypto_ablkcipher_encrypt(req);
+ 	if (res == -EINPROGRESS || res == -EBUSY) {
+ 		BUG_ON(req->base.data != &ecr);
+@@ -356,6 +358,7 @@ struct ext4_fname_crypto_ctx *ext4_get_fname_crypto_ctx(
+ 	if (IS_ERR(ctx))
+ 		return ctx;
+ 
++	ctx->flags = ei->i_crypt_policy_flags;
+ 	if (ctx->has_valid_key) {
+ 		if (ctx->key.mode != EXT4_ENCRYPTION_MODE_AES_256_CTS) {
+ 			printk_once(KERN_WARNING
+@@ -468,6 +471,7 @@ int ext4_fname_crypto_namelen_on_disk(struct ext4_fname_crypto_ctx *ctx,
+ 				      u32 namelen)
+ {
+ 	u32 ciphertext_len;
++	int padding = 4 << (ctx->flags & EXT4_POLICY_FLAGS_PAD_MASK);
+ 
+ 	if (ctx == NULL)
+ 		return -EIO;
+@@ -475,6 +479,7 @@ int ext4_fname_crypto_namelen_on_disk(struct ext4_fname_crypto_ctx *ctx,
+ 		return -EACCES;
+ 	ciphertext_len = (namelen < EXT4_CRYPTO_BLOCK_SIZE) ?
+ 		EXT4_CRYPTO_BLOCK_SIZE : namelen;
++	ciphertext_len = ext4_fname_crypto_round_up(ciphertext_len, padding);
+ 	ciphertext_len = (ciphertext_len > ctx->lim)
+ 			? ctx->lim : ciphertext_len;
+ 	return (int) ciphertext_len;
+@@ -490,10 +495,13 @@ int ext4_fname_crypto_alloc_buffer(struct ext4_fname_crypto_ctx *ctx,
+ 				   u32 ilen, struct ext4_str *crypto_str)
+ {
+ 	unsigned int olen;
++	int padding = 4 << (ctx->flags & EXT4_POLICY_FLAGS_PAD_MASK);
+ 
+ 	if (!ctx)
+ 		return -EIO;
+-	olen = ext4_fname_crypto_round_up(ilen, EXT4_CRYPTO_BLOCK_SIZE);
++	if (padding < EXT4_CRYPTO_BLOCK_SIZE)
++		padding = EXT4_CRYPTO_BLOCK_SIZE;
++	olen = ext4_fname_crypto_round_up(ilen, padding);
+ 	crypto_str->len = olen;
+ 	if (olen < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2)
+ 		olen = EXT4_FNAME_CRYPTO_DIGEST_SIZE*2;
+diff --git a/fs/ext4/crypto_key.c b/fs/ext4/crypto_key.c
+index c8392af8abbb..52170d0b7c40 100644
+--- a/fs/ext4/crypto_key.c
++++ b/fs/ext4/crypto_key.c
+@@ -110,6 +110,7 @@ int ext4_generate_encryption_key(struct inode *inode)
+ 	}
+ 	res = 0;
+ 
++	ei->i_crypt_policy_flags = ctx.flags;
+ 	if (S_ISREG(inode->i_mode))
+ 		crypt_key->mode = ctx.contents_encryption_mode;
+ 	else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+diff --git a/fs/ext4/crypto_policy.c b/fs/ext4/crypto_policy.c
+index 30eaf9e9864a..a6d6291aea16 100644
+--- a/fs/ext4/crypto_policy.c
++++ b/fs/ext4/crypto_policy.c
+@@ -37,6 +37,8 @@ static int ext4_is_encryption_context_consistent_with_policy(
+ 		return 0;
+ 	return (memcmp(ctx.master_key_descriptor, policy->master_key_descriptor,
+ 			EXT4_KEY_DESCRIPTOR_SIZE) == 0 &&
++		(ctx.flags ==
++		 policy->flags) &&
+ 		(ctx.contents_encryption_mode ==
+ 		 policy->contents_encryption_mode) &&
+ 		(ctx.filenames_encryption_mode ==
+@@ -56,25 +58,25 @@ static int ext4_create_encryption_context_from_policy(
+ 		printk(KERN_WARNING
+ 		       "%s: Invalid contents encryption mode %d\n", __func__,
+ 			policy->contents_encryption_mode);
+-		res = -EINVAL;
+-		goto out;
++		return -EINVAL;
+ 	}
+ 	if (!ext4_valid_filenames_enc_mode(policy->filenames_encryption_mode)) {
+ 		printk(KERN_WARNING
+ 		       "%s: Invalid filenames encryption mode %d\n", __func__,
+ 			policy->filenames_encryption_mode);
+-		res = -EINVAL;
+-		goto out;
++		return -EINVAL;
+ 	}
++	if (policy->flags & ~EXT4_POLICY_FLAGS_VALID)
++		return -EINVAL;
+ 	ctx.contents_encryption_mode = policy->contents_encryption_mode;
+ 	ctx.filenames_encryption_mode = policy->filenames_encryption_mode;
++	ctx.flags = policy->flags;
+ 	BUILD_BUG_ON(sizeof(ctx.nonce) != EXT4_KEY_DERIVATION_NONCE_SIZE);
+ 	get_random_bytes(ctx.nonce, EXT4_KEY_DERIVATION_NONCE_SIZE);
+ 
+ 	res = ext4_xattr_set(inode, EXT4_XATTR_INDEX_ENCRYPTION,
+ 			     EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, &ctx,
+ 			     sizeof(ctx), 0);
+-out:
+ 	if (!res)
+ 		ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
+ 	return res;
+@@ -115,6 +117,7 @@ int ext4_get_policy(struct inode *inode, struct ext4_encryption_policy *policy)
+ 	policy->version = 0;
+ 	policy->contents_encryption_mode = ctx.contents_encryption_mode;
+ 	policy->filenames_encryption_mode = ctx.filenames_encryption_mode;
++	policy->flags = ctx.flags;
+ 	memcpy(&policy->master_key_descriptor, ctx.master_key_descriptor,
+ 	       EXT4_KEY_DESCRIPTOR_SIZE);
+ 	return 0;
+@@ -176,6 +179,7 @@ int ext4_inherit_context(struct inode *parent, struct inode *child)
+ 				EXT4_ENCRYPTION_MODE_AES_256_XTS;
+ 			ctx.filenames_encryption_mode =
+ 				EXT4_ENCRYPTION_MODE_AES_256_CTS;
++			ctx.flags = 0;
+ 			memset(ctx.master_key_descriptor, 0x42,
+ 			       EXT4_KEY_DESCRIPTOR_SIZE);
+ 			res = 0;
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index dfb113816672..bca1bdc67725 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -911,6 +911,7 @@ struct ext4_inode_info {
+ 
+ 	/* on-disk additional length */
+ 	__u16 i_extra_isize;
++	char i_crypt_policy_flags;
+ 
+ 	/* Indicate the inline data space. */
+ 	u16 i_inline_off;
+diff --git a/fs/ext4/ext4_crypto.h b/fs/ext4/ext4_crypto.h
+index c2ba35a914b6..d75159c101ce 100644
+--- a/fs/ext4/ext4_crypto.h
++++ b/fs/ext4/ext4_crypto.h
+@@ -20,12 +20,20 @@ struct ext4_encryption_policy {
+ 	char version;
+ 	char contents_encryption_mode;
+ 	char filenames_encryption_mode;
++	char flags;
+ 	char master_key_descriptor[EXT4_KEY_DESCRIPTOR_SIZE];
+ } __attribute__((__packed__));
+ 
+ #define EXT4_ENCRYPTION_CONTEXT_FORMAT_V1 1
+ #define EXT4_KEY_DERIVATION_NONCE_SIZE 16
+ 
++#define EXT4_POLICY_FLAGS_PAD_4		0x00
++#define EXT4_POLICY_FLAGS_PAD_8		0x01
++#define EXT4_POLICY_FLAGS_PAD_16	0x02
++#define EXT4_POLICY_FLAGS_PAD_32	0x03
++#define EXT4_POLICY_FLAGS_PAD_MASK	0x03
++#define EXT4_POLICY_FLAGS_VALID		0x03
++
+ /**
+  * Encryption context for inode
+  *
+@@ -41,7 +49,7 @@ struct ext4_encryption_context {
+ 	char format;
+ 	char contents_encryption_mode;
+ 	char filenames_encryption_mode;
+-	char reserved;
++	char flags;
+ 	char master_key_descriptor[EXT4_KEY_DESCRIPTOR_SIZE];
+ 	char nonce[EXT4_KEY_DERIVATION_NONCE_SIZE];
+ } __attribute__((__packed__));
+@@ -120,6 +128,7 @@ struct ext4_fname_crypto_ctx {
+ 	struct crypto_hash *htfm;
+ 	struct page *workpage;
+ 	struct ext4_encryption_key key;
++	unsigned flags : 8;
+ 	unsigned has_valid_key : 1;
+ 	unsigned ctfm_key_is_ready : 1;
+ };

commit 5de0b4d0cd153c471640b13aae6ae6d18d0a4603
+Author: Theodore Ts'o 
+Date:   Fri May 1 16:56:45 2015 -0400
+
+    ext4 crypto: simplify and speed up filename encryption
+    
+    Avoid using SHA-1 when calculating the user-visible filename when the
+    encryption key is available, and avoid decrypting lots of filenames
+    when searching for a directory entry in a directory block.
+    
+    Change-Id: If4655f144784978ba0305b597bfa1c8d7bb69e63
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/crypto_fname.c b/fs/ext4/crypto_fname.c
+index ca2f5948c1ac..7a877e609e5f 100644
+--- a/fs/ext4/crypto_fname.c
++++ b/fs/ext4/crypto_fname.c
+@@ -198,106 +198,57 @@ static int ext4_fname_decrypt(struct ext4_fname_crypto_ctx *ctx,
+ 	return oname->len;
+ }
+ 
++static const char *lookup_table =
++	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
++
+ /**
+  * ext4_fname_encode_digest() -
+  *
+  * Encodes the input digest using characters from the set [a-zA-Z0-9_+].
+  * The encoded string is roughly 4/3 times the size of the input string.
+  */
+-int ext4_fname_encode_digest(char *dst, char *src, u32 len)
++static int digest_encode(const char *src, int len, char *dst)
+ {
+-	static const char *lookup_table =
+-		"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+";
+-	u32 current_chunk, num_chunks, i;
+-	char tmp_buf[3];
+-	u32 c0, c1, c2, c3;
+-
+-	current_chunk = 0;
+-	num_chunks = len/3;
+-	for (i = 0; i < num_chunks; i++) {
+-		c0 = src[3*i] & 0x3f;
+-		c1 = (((src[3*i]>>6)&0x3) | ((src[3*i+1] & 0xf)<<2)) & 0x3f;
+-		c2 = (((src[3*i+1]>>4)&0xf) | ((src[3*i+2] & 0x3)<<4)) & 0x3f;
+-		c3 = (src[3*i+2]>>2) & 0x3f;
+-		dst[4*i] = lookup_table[c0];
+-		dst[4*i+1] = lookup_table[c1];
+-		dst[4*i+2] = lookup_table[c2];
+-		dst[4*i+3] = lookup_table[c3];
+-	}
+-	if (i*3 < len) {
+-		memset(tmp_buf, 0, 3);
+-		memcpy(tmp_buf, &src[3*i], len-3*i);
+-		c0 = tmp_buf[0] & 0x3f;
+-		c1 = (((tmp_buf[0]>>6)&0x3) | ((tmp_buf[1] & 0xf)<<2)) & 0x3f;
+-		c2 = (((tmp_buf[1]>>4)&0xf) | ((tmp_buf[2] & 0x3)<<4)) & 0x3f;
+-		c3 = (tmp_buf[2]>>2) & 0x3f;
+-		dst[4*i] = lookup_table[c0];
+-		dst[4*i+1] = lookup_table[c1];
+-		dst[4*i+2] = lookup_table[c2];
+-		dst[4*i+3] = lookup_table[c3];
++	int i = 0, bits = 0, ac = 0;
++	char *cp = dst;
++
++	while (i < len) {
++		ac += (((unsigned char) src[i]) << bits);
++		bits += 8;
++		do {
++			*cp++ = lookup_table[ac & 0x3f];
++			ac >>= 6;
++			bits -= 6;
++		} while (bits >= 6);
+ 		i++;
+ 	}
+-	return (i * 4);
++	if (bits)
++		*cp++ = lookup_table[ac & 0x3f];
++	return cp - dst;
+ }
+ 
+-/**
+- * ext4_fname_hash() -
+- *
+- * This function computes the hash of the input filename, and sets the output
+- * buffer to the *encoded* digest.  It returns the length of the digest as its
+- * return value.  Errors are returned as negative numbers.  We trust the caller
+- * to allocate sufficient memory to oname string.
+- */
+-static int ext4_fname_hash(struct ext4_fname_crypto_ctx *ctx,
+-			   const struct ext4_str *iname,
+-			   struct ext4_str *oname)
++static int digest_decode(const char *src, int len, char *dst)
+ {
+-	struct scatterlist sg;
+-	struct hash_desc desc = {
+-		.tfm = (struct crypto_hash *)ctx->htfm,
+-		.flags = CRYPTO_TFM_REQ_MAY_SLEEP
+-	};
+-	int res = 0;
+-
+-	if (iname->len <= EXT4_FNAME_CRYPTO_DIGEST_SIZE) {
+-		res = ext4_fname_encode_digest(oname->name, iname->name,
+-					       iname->len);
+-		oname->len = res;
+-		return res;
+-	}
+-
+-	sg_init_one(&sg, iname->name, iname->len);
+-	res = crypto_hash_init(&desc);
+-	if (res) {
+-		printk(KERN_ERR
+-		       "%s: Error initializing crypto hash; res = [%d]\n",
+-		       __func__, res);
+-		goto out;
+-	}
+-	res = crypto_hash_update(&desc, &sg, iname->len);
+-	if (res) {
+-		printk(KERN_ERR
+-		       "%s: Error updating crypto hash; res = [%d]\n",
+-		       __func__, res);
+-		goto out;
+-	}
+-	res = crypto_hash_final(&desc,
+-		&oname->name[EXT4_FNAME_CRYPTO_DIGEST_SIZE]);
+-	if (res) {
+-		printk(KERN_ERR
+-		       "%s: Error finalizing crypto hash; res = [%d]\n",
+-		       __func__, res);
+-		goto out;
++	int i = 0, bits = 0, ac = 0;
++	const char *p;
++	char *cp = dst;
++
++	while (i < len) {
++		p = strchr(lookup_table, src[i]);
++		if (p == NULL || src[i] == 0)
++			return -2;
++		ac += (p - lookup_table) << bits;
++		bits += 6;
++		if (bits >= 8) {
++			*cp++ = ac & 0xff;
++			ac >>= 8;
++			bits -= 8;
++		}
++		i++;
+ 	}
+-	/* Encode the digest as a printable string--this will increase the
+-	 * size of the digest */
+-	oname->name[0] = 'I';
+-	res = ext4_fname_encode_digest(oname->name+1,
+-		&oname->name[EXT4_FNAME_CRYPTO_DIGEST_SIZE],
+-		EXT4_FNAME_CRYPTO_DIGEST_SIZE) + 1;
+-	oname->len = res;
+-out:
+-	return res;
++	if (ac)
++		return -1;
++	return cp - dst;
+ }
+ 
+ /**
+@@ -571,9 +522,13 @@ void ext4_fname_crypto_free_buffer(struct ext4_str *crypto_str)
+  * ext4_fname_disk_to_usr() - converts a filename from disk space to user space
+  */
+ int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
+-			   const struct ext4_str *iname,
+-			   struct ext4_str *oname)
++			    struct dx_hash_info *hinfo,
++			    const struct ext4_str *iname,
++			    struct ext4_str *oname)
+ {
++	char buf[24];
++	int ret;
++
+ 	if (ctx == NULL)
+ 		return -EIO;
+ 	if (iname->len < 3) {
+@@ -587,18 +542,33 @@ int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
+ 	}
+ 	if (ctx->has_valid_key)
+ 		return ext4_fname_decrypt(ctx, iname, oname);
+-	else
+-		return ext4_fname_hash(ctx, iname, oname);
++
++	if (iname->len <= EXT4_FNAME_CRYPTO_DIGEST_SIZE) {
++		ret = digest_encode(iname->name, iname->len, oname->name);
++		oname->len = ret;
++		return ret;
++	}
++	if (hinfo) {
++		memcpy(buf, &hinfo->hash, 4);
++		memcpy(buf+4, &hinfo->minor_hash, 4);
++	} else
++		memset(buf, 0, 8);
++	memcpy(buf + 8, iname->name + iname->len - 16, 16);
++	oname->name[0] = '_';
++	ret = digest_encode(buf, 24, oname->name+1);
++	oname->len = ret + 1;
++	return ret + 1;
+ }
+ 
+ int ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
++			   struct dx_hash_info *hinfo,
+ 			   const struct ext4_dir_entry_2 *de,
+ 			   struct ext4_str *oname)
+ {
+ 	struct ext4_str iname = {.name = (unsigned char *) de->name,
+ 				 .len = de->name_len };
+ 
+-	return _ext4_fname_disk_to_usr(ctx, &iname, oname);
++	return _ext4_fname_disk_to_usr(ctx, hinfo, &iname, oname);
+ }
+ 
+ 
+@@ -640,10 +610,11 @@ int ext4_fname_usr_to_hash(struct ext4_fname_crypto_ctx *ctx,
+ 			    const struct qstr *iname,
+ 			    struct dx_hash_info *hinfo)
+ {
+-	struct ext4_str tmp, tmp2;
++	struct ext4_str tmp;
+ 	int ret = 0;
++	char buf[EXT4_FNAME_CRYPTO_DIGEST_SIZE+1];
+ 
+-	if (!ctx || !ctx->has_valid_key ||
++	if (!ctx ||
+ 	    ((iname->name[0] == '.') &&
+ 	     ((iname->len == 1) ||
+ 	      ((iname->name[1] == '.') && (iname->len == 2))))) {
+@@ -651,59 +622,90 @@ int ext4_fname_usr_to_hash(struct ext4_fname_crypto_ctx *ctx,
+ 		return 0;
+ 	}
+ 
++	if (!ctx->has_valid_key && iname->name[0] == '_') {
++		if (iname->len != 33)
++			return -ENOENT;
++		ret = digest_decode(iname->name+1, iname->len, buf);
++		if (ret != 24)
++			return -ENOENT;
++		memcpy(&hinfo->hash, buf, 4);
++		memcpy(&hinfo->minor_hash, buf + 4, 4);
++		return 0;
++	}
++
++	if (!ctx->has_valid_key && iname->name[0] != '_') {
++		if (iname->len > 43)
++			return -ENOENT;
++		ret = digest_decode(iname->name, iname->len, buf);
++		ext4fs_dirhash(buf, ret, hinfo);
++		return 0;
++	}
++
+ 	/* First encrypt the plaintext name */
+ 	ret = ext4_fname_crypto_alloc_buffer(ctx, iname->len, &tmp);
+ 	if (ret < 0)
+ 		return ret;
+ 
+ 	ret = ext4_fname_encrypt(ctx, iname, &tmp);
+-	if (ret < 0)
+-		goto out;
+-
+-	tmp2.len = (4 * ((EXT4_FNAME_CRYPTO_DIGEST_SIZE + 2) / 3)) + 1;
+-	tmp2.name = kmalloc(tmp2.len + 1, GFP_KERNEL);
+-	if (tmp2.name == NULL) {
+-		ret = -ENOMEM;
+-		goto out;
++	if (ret >= 0) {
++		ext4fs_dirhash(tmp.name, tmp.len, hinfo);
++		ret = 0;
+ 	}
+ 
+-	ret = ext4_fname_hash(ctx, &tmp, &tmp2);
+-	if (ret > 0)
+-		ext4fs_dirhash(tmp2.name, tmp2.len, hinfo);
+-	ext4_fname_crypto_free_buffer(&tmp2);
+-out:
+ 	ext4_fname_crypto_free_buffer(&tmp);
+ 	return ret;
+ }
+ 
+-/**
+- * ext4_fname_disk_to_htree() - converts a filename from disk space to htree-access string
+- */
+-int ext4_fname_disk_to_hash(struct ext4_fname_crypto_ctx *ctx,
+-			    const struct ext4_dir_entry_2 *de,
+-			    struct dx_hash_info *hinfo)
++int ext4_fname_match(struct ext4_fname_crypto_ctx *ctx, struct ext4_str *cstr,
++		     int len, const char * const name,
++		     struct ext4_dir_entry_2 *de)
+ {
+-	struct ext4_str iname = {.name = (unsigned char *) de->name,
+-				 .len = de->name_len};
+-	struct ext4_str tmp;
+-	int ret;
++	int ret = -ENOENT;
++	int bigname = (*name == '_');
+ 
+-	if (!ctx ||
+-	    ((iname.name[0] == '.') &&
+-	     ((iname.len == 1) ||
+-	      ((iname.name[1] == '.') && (iname.len == 2))))) {
+-		ext4fs_dirhash(iname.name, iname.len, hinfo);
+-		return 0;
++	if (ctx->has_valid_key) {
++		if (cstr->name == NULL) {
++			struct qstr istr;
++
++			ret = ext4_fname_crypto_alloc_buffer(ctx, len, cstr);
++			if (ret < 0)
++				goto errout;
++			istr.name = name;
++			istr.len = len;
++			ret = ext4_fname_encrypt(ctx, &istr, cstr);
++			if (ret < 0)
++				goto errout;
++		}
++	} else {
++		if (cstr->name == NULL) {
++			cstr->name = kmalloc(32, GFP_KERNEL);
++			if (cstr->name == NULL)
++				return -ENOMEM;
++			if ((bigname && (len != 33)) ||
++			    (!bigname && (len > 43)))
++				goto errout;
++			ret = digest_decode(name+bigname, len-bigname,
++					    cstr->name);
++			if (ret < 0) {
++				ret = -ENOENT;
++				goto errout;
++			}
++			cstr->len = ret;
++		}
++		if (bigname) {
++			if (de->name_len < 16)
++				return 0;
++			ret = memcmp(de->name + de->name_len - 16,
++				     cstr->name + 8, 16);
++			return (ret == 0) ? 1 : 0;
++		}
+ 	}
+-
+-	tmp.len = (4 * ((EXT4_FNAME_CRYPTO_DIGEST_SIZE + 2) / 3)) + 1;
+-	tmp.name = kmalloc(tmp.len + 1, GFP_KERNEL);
+-	if (tmp.name == NULL)
+-		return -ENOMEM;
+-
+-	ret = ext4_fname_hash(ctx, &iname, &tmp);
+-	if (ret > 0)
+-		ext4fs_dirhash(tmp.name, tmp.len, hinfo);
+-	ext4_fname_crypto_free_buffer(&tmp);
++	if (de->name_len != cstr->len)
++		return 0;
++	ret = memcmp(de->name, cstr->name, cstr->len);
++	return (ret == 0) ? 1 : 0;
++errout:
++	kfree(cstr->name);
++	cstr->name = NULL;
+ 	return ret;
+ }
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index 61db51a5ce4c..5665d82d2332 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -249,7 +249,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
+ 				} else {
+ 					/* Directory is encrypted */
+ 					err = ext4_fname_disk_to_usr(enc_ctx,
+-							de, &fname_crypto_str);
++						NULL, de, &fname_crypto_str);
+ 					if (err < 0)
+ 						goto errout;
+ 					if (!dir_emit(ctx,
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 0179654faf79..dfb113816672 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2093,9 +2093,11 @@ u32 ext4_fname_crypto_round_up(u32 size, u32 blksize);
+ int ext4_fname_crypto_alloc_buffer(struct ext4_fname_crypto_ctx *ctx,
+ 				   u32 ilen, struct ext4_str *crypto_str);
+ int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
++			    struct dx_hash_info *hinfo,
+ 			    const struct ext4_str *iname,
+ 			    struct ext4_str *oname);
+ int ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
++			   struct dx_hash_info *hinfo,
+ 			   const struct ext4_dir_entry_2 *de,
+ 			   struct ext4_str *oname);
+ int ext4_fname_usr_to_disk(struct ext4_fname_crypto_ctx *ctx,
+@@ -2104,11 +2106,12 @@ int ext4_fname_usr_to_disk(struct ext4_fname_crypto_ctx *ctx,
+ int ext4_fname_usr_to_hash(struct ext4_fname_crypto_ctx *ctx,
+ 			   const struct qstr *iname,
+ 			   struct dx_hash_info *hinfo);
+-int ext4_fname_disk_to_hash(struct ext4_fname_crypto_ctx *ctx,
+-			    const struct ext4_dir_entry_2 *de,
+-			    struct dx_hash_info *hinfo);
+ int ext4_fname_crypto_namelen_on_disk(struct ext4_fname_crypto_ctx *ctx,
+ 				      u32 namelen);
++int ext4_fname_match(struct ext4_fname_crypto_ctx *ctx, struct ext4_str *cstr,
++		     int len, const char * const name,
++		     struct ext4_dir_entry_2 *de);
++
+ 
+ #ifdef CONFIG_EXT4_FS_ENCRYPTION
+ void ext4_put_fname_crypto_ctx(struct ext4_fname_crypto_ctx **ctx);
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 4f87127f781f..5ea737114716 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -640,7 +640,7 @@ static struct stats dx_show_leaf(struct inode *dir,
+ 						ext4_put_fname_crypto_ctx(&ctx);
+ 						ctx = NULL;
+ 					}
+-					res = ext4_fname_disk_to_usr(ctx, de,
++					res = ext4_fname_disk_to_usr(ctx, NULL, de,
+ 							&fname_crypto_str);
+ 					if (res < 0) {
+ 						printk(KERN_WARNING "Error "
+@@ -653,15 +653,8 @@ static struct stats dx_show_leaf(struct inode *dir,
+ 						name = fname_crypto_str.name;
+ 						len = fname_crypto_str.len;
+ 					}
+-					res = ext4_fname_disk_to_hash(ctx, de,
+-								      &h);
+-					if (res < 0) {
+-						printk(KERN_WARNING "Error "
+-							"converting filename "
+-							"from disk to htree"
+-							"\n");
+-						h.hash = 0xDEADBEEF;
+-					}
++					ext4fs_dirhash(de->name, de->name_len,
++						       &h);
+ 					printk("%*.s:(E)%x.%u ", len, name,
+ 					       h.hash, (unsigned) ((char *) de
+ 								   - base));
+@@ -1008,15 +1001,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
+ 			/* silently ignore the rest of the block */
+ 			break;
+ 		}
+-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+-		err = ext4_fname_disk_to_hash(ctx, de, hinfo);
+-		if (err < 0) {
+-			count = err;
+-			goto errout;
+-		}
+-#else
+ 		ext4fs_dirhash(de->name, de->name_len, hinfo);
+-#endif
+ 		if ((hinfo->hash < start_hash) ||
+ 		    ((hinfo->hash == start_hash) &&
+ 		     (hinfo->minor_hash < start_minor_hash)))
+@@ -1032,7 +1017,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
+ 				   &tmp_str);
+ 		} else {
+ 			/* Directory is encrypted */
+-			err = ext4_fname_disk_to_usr(ctx, de,
++			err = ext4_fname_disk_to_usr(ctx, hinfo, de,
+ 						     &fname_crypto_str);
+ 			if (err < 0) {
+ 				count = err;
+@@ -1193,26 +1178,10 @@ static int dx_make_map(struct inode *dir, struct ext4_dir_entry_2 *de,
+ 	int count = 0;
+ 	char *base = (char *) de;
+ 	struct dx_hash_info h = *hinfo;
+-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+-	struct ext4_fname_crypto_ctx *ctx = NULL;
+-	int err;
+-
+-	ctx = ext4_get_fname_crypto_ctx(dir, EXT4_NAME_LEN);
+-	if (IS_ERR(ctx))
+-		return PTR_ERR(ctx);
+-#endif
+ 
+ 	while ((char *) de < base + blocksize) {
+ 		if (de->name_len && de->inode) {
+-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+-			err = ext4_fname_disk_to_hash(ctx, de, &h);
+-			if (err < 0) {
+-				ext4_put_fname_crypto_ctx(&ctx);
+-				return err;
+-			}
+-#else
+ 			ext4fs_dirhash(de->name, de->name_len, &h);
+-#endif
+ 			map_tail--;
+ 			map_tail->hash = h.hash;
+ 			map_tail->offs = ((char *) de - base)>>2;
+@@ -1223,9 +1192,6 @@ static int dx_make_map(struct inode *dir, struct ext4_dir_entry_2 *de,
+ 		/* XXX: do we need to check rec_len == 0 case? -Chris */
+ 		de = ext4_next_entry(de, blocksize);
+ 	}
+-#ifdef CONFIG_EXT4_FS_ENCRYPTION
+-	ext4_put_fname_crypto_ctx(&ctx);
+-#endif
+ 	return count;
+ }
+ 
+@@ -1287,16 +1253,8 @@ static inline int ext4_match(struct ext4_fname_crypto_ctx *ctx,
+ 		return 0;
+ 
+ #ifdef CONFIG_EXT4_FS_ENCRYPTION
+-	if (ctx) {
+-		/* Directory is encrypted */
+-		res = ext4_fname_disk_to_usr(ctx, de, fname_crypto_str);
+-		if (res < 0)
+-			return res;
+-		if (len != res)
+-			return 0;
+-		res = memcmp(name, fname_crypto_str->name, len);
+-		return (res == 0) ? 1 : 0;
+-	}
++	if (ctx)
++		return ext4_fname_match(ctx, fname_crypto_str, len, name, de);
+ #endif
+ 	if (len != de->name_len)
+ 		return 0;
+@@ -1324,16 +1282,6 @@ int search_dir(struct buffer_head *bh, char *search_buf, int buf_size,
+ 	if (IS_ERR(ctx))
+ 		return -1;
+ 
+-	if (ctx != NULL) {
+-		/* Allocate buffer to hold maximum name length */
+-		res = ext4_fname_crypto_alloc_buffer(ctx, EXT4_NAME_LEN,
+-						     &fname_crypto_str);
+-		if (res < 0) {
+-			ext4_put_fname_crypto_ctx(&ctx);
+-			return -1;
+-		}
+-	}
+-
+ 	de = (struct ext4_dir_entry_2 *)search_buf;
+ 	dlimit = search_buf + buf_size;
+ 	while ((char *) de < dlimit) {
+@@ -1872,14 +1820,6 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode,
+ 			return res;
+ 		}
+ 		reclen = EXT4_DIR_REC_LEN(res);
+-
+-		/* Allocate buffer to hold maximum name length */
+-		res = ext4_fname_crypto_alloc_buffer(ctx, EXT4_NAME_LEN,
+-						     &fname_crypto_str);
+-		if (res < 0) {
+-			ext4_put_fname_crypto_ctx(&ctx);
+-			return -1;
+-		}
+ 	}
+ 
+ 	de = (struct ext4_dir_entry_2 *)buf;
+diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
+index 136ca0e911fd..ce2ed286ba08 100644
+--- a/fs/ext4/symlink.c
++++ b/fs/ext4/symlink.c
+@@ -74,7 +74,7 @@ static void *ext4_follow_link(struct dentry *dentry, struct nameidata *nd)
+ 		goto errout;
+ 	}
+ 	pstr.name = paddr;
+-	res = _ext4_fname_disk_to_usr(ctx, &cstr, &pstr);
++	res = _ext4_fname_disk_to_usr(ctx, NULL, &cstr, &pstr);
+ 	if (res < 0)
+ 		goto errout;
+ 	/* Null-terminate the name */

commit 6ddb2447846a8ece111e316a2863c2355023682d
+Author: Theodore Ts'o 
+Date:   Thu Apr 16 01:56:00 2015 -0400
+
+    ext4 crypto: enable encryption feature flag
+    
+    Also add the test dummy encryption mode flag so we can more easily
+    test the encryption patches using xfstests.
+    
+    Signed-off-by: Michael Halcrow 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/crypto_key.c b/fs/ext4/crypto_key.c
+index 572bd97f58dd..c8392af8abbb 100644
+--- a/fs/ext4/crypto_key.c
++++ b/fs/ext4/crypto_key.c
+@@ -98,6 +98,7 @@ int ext4_generate_encryption_key(struct inode *inode)
+ 	struct ext4_encryption_key *master_key;
+ 	struct ext4_encryption_context ctx;
+ 	struct user_key_payload *ukp;
++	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+ 	int res = ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION,
+ 				 EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
+ 				 &ctx, sizeof(ctx));
+@@ -109,6 +110,20 @@ int ext4_generate_encryption_key(struct inode *inode)
+ 	}
+ 	res = 0;
+ 
++	if (S_ISREG(inode->i_mode))
++		crypt_key->mode = ctx.contents_encryption_mode;
++	else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
++		crypt_key->mode = ctx.filenames_encryption_mode;
++	else {
++		printk(KERN_ERR "ext4 crypto: Unsupported inode type.\n");
++		BUG();
++	}
++	crypt_key->size = ext4_encryption_key_size(crypt_key->mode);
++	BUG_ON(!crypt_key->size);
++	if (DUMMY_ENCRYPTION_ENABLED(sbi)) {
++		memset(crypt_key->raw, 0x42, EXT4_AES_256_XTS_KEY_SIZE);
++		goto out;
++	}
+ 	memcpy(full_key_descriptor, EXT4_KEY_DESC_PREFIX,
+ 	       EXT4_KEY_DESC_PREFIX_SIZE);
+ 	sprintf(full_key_descriptor + EXT4_KEY_DESC_PREFIX_SIZE,
+@@ -129,21 +144,9 @@ int ext4_generate_encryption_key(struct inode *inode)
+ 		goto out;
+ 	}
+ 	master_key = (struct ext4_encryption_key *)ukp->data;
+-
+-	if (S_ISREG(inode->i_mode))
+-		crypt_key->mode = ctx.contents_encryption_mode;
+-	else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+-		crypt_key->mode = ctx.filenames_encryption_mode;
+-	else {
+-		printk(KERN_ERR "ext4 crypto: Unsupported inode type.\n");
+-		BUG();
+-	}
+-	crypt_key->size = ext4_encryption_key_size(crypt_key->mode);
+-	BUG_ON(!crypt_key->size);
+ 	BUILD_BUG_ON(EXT4_AES_128_ECB_KEY_SIZE !=
+ 		     EXT4_KEY_DERIVATION_NONCE_SIZE);
+ 	BUG_ON(master_key->size != EXT4_AES_256_XTS_KEY_SIZE);
+-	BUG_ON(crypt_key->size < EXT4_AES_256_CBC_KEY_SIZE);
+ 	res = ext4_derive_key_aes(ctx.nonce, master_key->raw, crypt_key->raw);
+ out:
+ 	if (keyring_key)
+diff --git a/fs/ext4/crypto_policy.c b/fs/ext4/crypto_policy.c
+index 749ed6e91e50..30eaf9e9864a 100644
+--- a/fs/ext4/crypto_policy.c
++++ b/fs/ext4/crypto_policy.c
+@@ -169,13 +169,25 @@ int ext4_inherit_context(struct inode *parent, struct inode *child)
+ 				 EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
+ 				 &ctx, sizeof(ctx));
+ 
+-	if (res != sizeof(ctx))
+-		return -ENOENT;
+-
++	if (res != sizeof(ctx)) {
++		if (DUMMY_ENCRYPTION_ENABLED(EXT4_SB(parent->i_sb))) {
++			ctx.format = EXT4_ENCRYPTION_CONTEXT_FORMAT_V1;
++			ctx.contents_encryption_mode =
++				EXT4_ENCRYPTION_MODE_AES_256_XTS;
++			ctx.filenames_encryption_mode =
++				EXT4_ENCRYPTION_MODE_AES_256_CTS;
++			memset(ctx.master_key_descriptor, 0x42,
++			       EXT4_KEY_DESCRIPTOR_SIZE);
++			res = 0;
++		} else {
++			goto out;
++		}
++	}
+ 	get_random_bytes(ctx.nonce, EXT4_KEY_DERIVATION_NONCE_SIZE);
+ 	res = ext4_xattr_set(child, EXT4_XATTR_INDEX_ENCRYPTION,
+ 			     EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, &ctx,
+ 			     sizeof(ctx), 0);
++out:
+ 	if (!res)
+ 		ext4_set_inode_flag(child, EXT4_INODE_ENCRYPT);
+ 	return res;
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 86d15706d27a..0179654faf79 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1200,8 +1200,16 @@ struct ext4_super_block {
+ /*
+  * run-time mount flags
+  */
+-#define EXT4_MF_MNTDIR_SAMPLED	0x0001
+-#define EXT4_MF_FS_ABORTED	0x0002	/* Fatal error detected */
++#define EXT4_MF_MNTDIR_SAMPLED		0x0001
++#define EXT4_MF_FS_ABORTED		0x0002	/* Fatal error detected */
++#define EXT4_MF_TEST_DUMMY_ENCRYPTION	0x0004
++
++#ifdef CONFIG_EXT4_FS_ENCRYPTION
++#define DUMMY_ENCRYPTION_ENABLED(sbi) (unlikely((sbi)->s_mount_flags & \
++						EXT4_MF_TEST_DUMMY_ENCRYPTION))
++#else
++#define DUMMY_ENCRYPTION_ENABLED(sbi) (0)
++#endif
+ 
+ /* Number of quota types we support */
+ #define EXT4_MAXQUOTAS 2
+@@ -1613,8 +1621,9 @@ static inline int ext4_encrypted_inode(struct inode *inode)
+ 					 EXT4_FEATURE_INCOMPAT_EXTENTS| \
+ 					 EXT4_FEATURE_INCOMPAT_64BIT| \
+ 					 EXT4_FEATURE_INCOMPAT_FLEX_BG| \
+-					 EXT4_FEATURE_INCOMPAT_MMP |	\
+-					 EXT4_FEATURE_INCOMPAT_INLINE_DATA)
++					 EXT4_FEATURE_INCOMPAT_MMP | \
++					 EXT4_FEATURE_INCOMPAT_INLINE_DATA | \
++					 EXT4_FEATURE_INCOMPAT_ENCRYPT)
+ #define EXT4_FEATURE_RO_COMPAT_SUPP	(EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \
+ 					 EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \
+ 					 EXT4_FEATURE_RO_COMPAT_GDT_CSUM| \
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 850267c89407..2cf18a2d5c72 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -998,7 +998,8 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
+ 
+ 	/* If the directory encrypted, then we should encrypt the inode. */
+ 	if ((S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode)) &&
+-	    ext4_encrypted_inode(dir))
++	    (ext4_encrypted_inode(dir) ||
++	     DUMMY_ENCRYPTION_ENABLED(sbi)))
+ 		ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
+ 
+ 	ext4_set_inode_flags(inode);
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index d201426b8d39..4f87127f781f 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -2582,7 +2582,8 @@ static int ext4_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+ 		ext4_set_aops(inode);
+ 		err = 0;
+ #ifdef CONFIG_EXT4_FS_ENCRYPTION
+-		if (!err && ext4_encrypted_inode(dir)) {
++		if (!err && (ext4_encrypted_inode(dir) ||
++			     DUMMY_ENCRYPTION_ENABLED(EXT4_SB(dir->i_sb)))) {
+ 			err = ext4_inherit_context(dir, inode);
+ 			if (err) {
+ 				clear_nlink(inode);
+@@ -2777,7 +2778,8 @@ static int ext4_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+ 	if (err)
+ 		goto out_clear_inode;
+ #ifdef CONFIG_EXT4_FS_ENCRYPTION
+-	if (ext4_encrypted_inode(dir)) {
++	if (ext4_encrypted_inode(dir) ||
++	    DUMMY_ENCRYPTION_ENABLED(EXT4_SB(dir->i_sb))) {
+ 		err = ext4_inherit_context(dir, inode);
+ 		if (err)
+ 			goto out_clear_inode;
+@@ -3202,7 +3204,8 @@ static int ext4_symlink(struct inode *dir,
+ 	disk_link.len = len + 1;
+ 	disk_link.name = (char *) symname;
+ 
+-	encryption_required = ext4_encrypted_inode(dir);
++	encryption_required = (ext4_encrypted_inode(dir) ||
++			       DUMMY_ENCRYPTION_ENABLED(EXT4_SB(dir->i_sb)));
+ 	if (encryption_required)
+ 		disk_link.len = encrypted_symlink_data_len(len) + 1;
+ 	if (disk_link.len > dir->i_sb->s_blocksize)
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 1008ca258de4..f9ebd58f40dd 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1106,7 +1106,7 @@ enum {
+ 	Opt_commit, Opt_min_batch_time, Opt_max_batch_time, Opt_journal_dev,
+ 	Opt_journal_path, Opt_journal_checksum, Opt_journal_async_commit,
+ 	Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
+-	Opt_data_err_abort, Opt_data_err_ignore,
++	Opt_data_err_abort, Opt_data_err_ignore, Opt_test_dummy_encryption,
+ 	Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
+ 	Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota,
+ 	Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err,
+@@ -1197,6 +1197,7 @@ static const match_table_t tokens = {
+ 	{Opt_init_itable, "init_itable"},
+ 	{Opt_noinit_itable, "noinit_itable"},
+ 	{Opt_max_dir_size_kb, "max_dir_size_kb=%u"},
++	{Opt_test_dummy_encryption, "test_dummy_encryption"},
+ 	{Opt_removed, "check=none"},	/* mount option from ext2/3 */
+ 	{Opt_removed, "nocheck"},	/* mount option from ext2/3 */
+ 	{Opt_removed, "reservation"},	/* mount option from ext2/3 */
+@@ -1398,6 +1399,7 @@ static const struct mount_opts {
+ 	{Opt_jqfmt_vfsv0, QFMT_VFS_V0, MOPT_QFMT},
+ 	{Opt_jqfmt_vfsv1, QFMT_VFS_V1, MOPT_QFMT},
+ 	{Opt_max_dir_size_kb, 0, MOPT_GTE0},
++	{Opt_test_dummy_encryption, 0, MOPT_GTE0},
+ 	{Opt_err, 0, 0}
+ };
+ 
+@@ -1574,6 +1576,15 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
+ 		}
+ 		*journal_ioprio =
+ 			IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, arg);
++	} else if (token == Opt_test_dummy_encryption) {
++#ifdef CONFIG_EXT4_FS_ENCRYPTION
++		sbi->s_mount_flags |= EXT4_MF_TEST_DUMMY_ENCRYPTION;
++		ext4_msg(sb, KERN_WARNING,
++			 "Test dummy encryption mode enabled");
++#else
++		ext4_msg(sb, KERN_WARNING,
++			 "Test dummy encryption mount option ignored");
++#endif
+ 	} else if (m->flags & MOPT_DATAJ) {
+ 		if (is_remount) {
+ 			if (!sbi->s_journal)
+@@ -2671,11 +2682,13 @@ static struct attribute *ext4_attrs[] = {
+ EXT4_INFO_ATTR(lazy_itable_init);
+ EXT4_INFO_ATTR(batched_discard);
+ EXT4_INFO_ATTR(meta_bg_resize);
++EXT4_INFO_ATTR(encryption);
+ 
+ static struct attribute *ext4_feat_attrs[] = {
+ 	ATTR_LIST(lazy_itable_init),
+ 	ATTR_LIST(batched_discard),
+ 	ATTR_LIST(meta_bg_resize),
++	ATTR_LIST(encryption),
+ 	NULL,
+ };
+ 
+@@ -3683,6 +3696,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		}
+ 	}
+ 
++	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT) &&
++	    es->s_encryption_level) {
++		ext4_msg(sb, KERN_ERR, "Unsupported encryption level %d",
++			 es->s_encryption_level);
++		goto failed_mount;
++	}
++
+ 	if (sb->s_blocksize != blocksize) {
+ 		/* Validate the filesystem blocksize */
+ 		if (!sb_set_blocksize(sb, blocksize)) {
+@@ -4045,6 +4065,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		}
+ 	}
+ 
++	if (unlikely(sbi->s_mount_flags & EXT4_MF_TEST_DUMMY_ENCRYPTION) &&
++	    !(sb->s_flags & MS_RDONLY) &&
++	    !EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT)) {
++		EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT);
++		ext4_commit_super(sb, 1);
++	}
++
+ 	/*
+ 	 * Get the # of file system overhead blocks from the
+ 	 * superblock if present.

commit f348c252320b98e11176074fe04223f22bddaf0d
+Author: Theodore Ts'o 
+Date:   Thu Apr 16 01:55:00 2015 -0400
+
+    ext4 crypto: add symlink encryption
+    
+    Signed-off-by: Uday Savagaonkar 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 5146e67e8d51..86d15706d27a 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2233,6 +2233,7 @@ extern int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
+ extern int ext4_trim_fs(struct super_block *, struct fstrim_range *);
+ 
+ /* inode.c */
++int ext4_inode_is_fast_symlink(struct inode *inode);
+ struct buffer_head *ext4_getblk(handle_t *, struct inode *, ext4_lblk_t, int);
+ struct buffer_head *ext4_bread(handle_t *, struct inode *, ext4_lblk_t, int);
+ int ext4_get_block_write(struct inode *inode, sector_t iblock,
+diff --git a/fs/ext4/ext4_crypto.h b/fs/ext4/ext4_crypto.h
+index f7d46e8dc9d3..c2ba35a914b6 100644
+--- a/fs/ext4/ext4_crypto.h
++++ b/fs/ext4/ext4_crypto.h
+@@ -124,4 +124,24 @@ struct ext4_fname_crypto_ctx {
+ 	unsigned ctfm_key_is_ready : 1;
+ };
+ 
++/**
++ * For encrypted symlinks, the ciphertext length is stored at the beginning
++ * of the string in little-endian format.
++ */
++struct ext4_encrypted_symlink_data {
++	__le16 len;
++	char encrypted_path[1];
++} __attribute__((__packed__));
++
++/**
++ * This function is used to calculate the disk space required to
++ * store a filename of length l in encrypted symlink format.
++ */
++static inline u32 encrypted_symlink_data_len(u32 l)
++{
++	if (l < EXT4_CRYPTO_BLOCK_SIZE)
++		l = EXT4_CRYPTO_BLOCK_SIZE;
++	return (l + sizeof(struct ext4_encrypted_symlink_data) - 1);
++}
++
+ #endif	/* _EXT4_CRYPTO_H */
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 8b4fe626919a..f6b35d8a4a5b 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -139,7 +139,7 @@ static int ext4_meta_trans_blocks(struct inode *inode, int lblocks,
+ /*
+  * Test whether an inode is a fast symlink.
+  */
+-static int ext4_inode_is_fast_symlink(struct inode *inode)
++int ext4_inode_is_fast_symlink(struct inode *inode)
+ {
+         int ea_blocks = EXT4_I(inode)->i_file_acl ?
+ 		EXT4_CLUSTER_SIZE(inode->i_sb) >> 9 : 0;
+@@ -4215,7 +4215,8 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 		inode->i_op = &ext4_dir_inode_operations;
+ 		inode->i_fop = &ext4_dir_operations;
+ 	} else if (S_ISLNK(inode->i_mode)) {
+-		if (ext4_inode_is_fast_symlink(inode)) {
++		if (ext4_inode_is_fast_symlink(inode) &&
++		    !ext4_encrypted_inode(inode)) {
+ 			inode->i_op = &ext4_fast_symlink_inode_operations;
+ 			nd_terminate_link(ei->i_data, inode->i_size,
+ 				sizeof(ei->i_data) - 1);
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 4c84db862891..d201426b8d39 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -3193,16 +3193,24 @@ static int ext4_symlink(struct inode *dir,
+ {
+ 	handle_t *handle;
+ 	struct inode *inode;
+-	int l, err, retries = 0;
++	int err, len = strlen(symname);
+ 	int credits;
++	bool encryption_required;
++	struct ext4_str disk_link;
++	struct ext4_encrypted_symlink_data *sd = NULL;
+ 
+-	l = strlen(symname)+1;
+-	if (l > dir->i_sb->s_blocksize)
++	disk_link.len = len + 1;
++	disk_link.name = (char *) symname;
++
++	encryption_required = ext4_encrypted_inode(dir);
++	if (encryption_required)
++		disk_link.len = encrypted_symlink_data_len(len) + 1;
++	if (disk_link.len > dir->i_sb->s_blocksize)
+ 		return -ENAMETOOLONG;
+ 
+ 	dquot_initialize(dir);
+ 
+-	if (l > EXT4_N_BLOCKS * 4) {
++	if ((disk_link.len > EXT4_N_BLOCKS * 4)) {
+ 		/*
+ 		 * For non-fast symlinks, we just allocate inode and put it on
+ 		 * orphan list in the first transaction => we need bitmap,
+@@ -3221,16 +3229,49 @@ static int ext4_symlink(struct inode *dir,
+ 		credits = EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
+ 			  EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3;
+ 	}
+-retry:
++
+ 	inode = ext4_new_inode_start_handle(dir, S_IFLNK|S_IRWXUGO,
+ 					    &dentry->d_name, 0, NULL,
+ 					    EXT4_HT_DIR, credits);
+ 	handle = ext4_journal_current_handle();
+-	err = PTR_ERR(inode);
+-	if (IS_ERR(inode))
+-		goto out_stop;
++	if (IS_ERR(inode)) {
++		if (handle)
++			ext4_journal_stop(handle);
++		return PTR_ERR(inode);
++	}
++
++	if (encryption_required) {
++		struct ext4_fname_crypto_ctx *ctx = NULL;
++		struct qstr istr;
++		struct ext4_str ostr;
++
++		sd = kzalloc(disk_link.len, GFP_NOFS);
++		if (!sd) {
++			err = -ENOMEM;
++			goto err_drop_inode;
++		}
++		err = ext4_inherit_context(dir, inode);
++		if (err)
++			goto err_drop_inode;
++		ctx = ext4_get_fname_crypto_ctx(inode,
++						inode->i_sb->s_blocksize);
++		if (IS_ERR_OR_NULL(ctx)) {
++			/* We just set the policy, so ctx should not be NULL */
++			err = (ctx == NULL) ? -EIO : PTR_ERR(ctx);
++			goto err_drop_inode;
++		}
++		istr.name = (const unsigned char *) symname;
++		istr.len = len;
++		ostr.name = sd->encrypted_path;
++		err = ext4_fname_usr_to_disk(ctx, &istr, &ostr);
++		ext4_put_fname_crypto_ctx(&ctx);
++		if (err < 0)
++			goto err_drop_inode;
++		sd->len = cpu_to_le16(ostr.len);
++		disk_link.name = (char *) sd;
++	}
+ 
+-	if (l > EXT4_N_BLOCKS * 4) {
++	if ((disk_link.len > EXT4_N_BLOCKS * 4)) {
+ 		inode->i_op = &ext4_symlink_inode_operations;
+ 		ext4_set_aops(inode);
+ 		/*
+@@ -3246,9 +3287,10 @@ static int ext4_symlink(struct inode *dir,
+ 		drop_nlink(inode);
+ 		err = ext4_orphan_add(handle, inode);
+ 		ext4_journal_stop(handle);
++		handle = NULL;
+ 		if (err)
+ 			goto err_drop_inode;
+-		err = __page_symlink(inode, symname, l, 1);
++		err = __page_symlink(inode, disk_link.name, disk_link.len, 1);
+ 		if (err)
+ 			goto err_drop_inode;
+ 		/*
+@@ -3260,34 +3302,37 @@ static int ext4_symlink(struct inode *dir,
+ 				EXT4_INDEX_EXTRA_TRANS_BLOCKS + 1);
+ 		if (IS_ERR(handle)) {
+ 			err = PTR_ERR(handle);
++			handle = NULL;
+ 			goto err_drop_inode;
+ 		}
+ 		set_nlink(inode, 1);
+ 		err = ext4_orphan_del(handle, inode);
+-		if (err) {
+-			ext4_journal_stop(handle);
+-			clear_nlink(inode);
++		if (err)
+ 			goto err_drop_inode;
+-		}
+ 	} else {
+ 		/* clear the extent format for fast symlink */
+ 		ext4_clear_inode_flag(inode, EXT4_INODE_EXTENTS);
+-		inode->i_op = &ext4_fast_symlink_inode_operations;
+-		memcpy((char *)&EXT4_I(inode)->i_data, symname, l);
+-		inode->i_size = l-1;
++		inode->i_op = encryption_required ?
++			&ext4_symlink_inode_operations :
++			&ext4_fast_symlink_inode_operations;
++		memcpy((char *)&EXT4_I(inode)->i_data, disk_link.name,
++		       disk_link.len);
++		inode->i_size = disk_link.len - 1;
+ 	}
+ 	EXT4_I(inode)->i_disksize = inode->i_size;
+ 	err = ext4_add_nondir(handle, dentry, inode);
+ 	if (!err && IS_DIRSYNC(dir))
+ 		ext4_handle_sync(handle);
+ 
+-out_stop:
+ 	if (handle)
+ 		ext4_journal_stop(handle);
+-	if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
+-		goto retry;
++	kfree(sd);
+ 	return err;
+ err_drop_inode:
++	if (handle)
++		ext4_journal_stop(handle);
++	kfree(sd);
++	clear_nlink(inode);
+ 	unlock_new_inode(inode);
+ 	iput(inode);
+ 	return err;
+diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
+index 489b34333ea4..136ca0e911fd 100644
+--- a/fs/ext4/symlink.c
++++ b/fs/ext4/symlink.c
+@@ -22,7 +22,96 @@
+ #include "ext4.h"
+ #include "xattr.h"
+ 
++#ifdef CONFIG_EXT4_FS_ENCRYPTION
+ static void *ext4_follow_link(struct dentry *dentry, struct nameidata *nd)
++{
++	struct page *cpage = NULL;
++	char *caddr, *paddr = NULL;
++	struct ext4_str cstr, pstr;
++	struct inode *inode = dentry->d_inode;
++	struct ext4_fname_crypto_ctx *ctx = NULL;
++	struct ext4_encrypted_symlink_data *sd;
++	loff_t size = min_t(loff_t, i_size_read(inode), PAGE_SIZE - 1);
++	int res;
++	u32 plen, max_size = inode->i_sb->s_blocksize;
++
++	if (!ext4_encrypted_inode(inode))
++		return page_follow_link_light(dentry, nd);
++
++	ctx = ext4_get_fname_crypto_ctx(inode, inode->i_sb->s_blocksize);
++	if (IS_ERR(ctx))
++		return ctx;
++
++	if (ext4_inode_is_fast_symlink(inode)) {
++		caddr = (char *) EXT4_I(dentry->d_inode)->i_data;
++		max_size = sizeof(EXT4_I(dentry->d_inode)->i_data);
++	} else {
++		cpage = read_mapping_page(inode->i_mapping, 0, NULL);
++		if (IS_ERR(cpage)) {
++			ext4_put_fname_crypto_ctx(&ctx);
++			return cpage;
++		}
++		caddr = kmap(cpage);
++		caddr[size] = 0;
++	}
++
++	/* Symlink is encrypted */
++	sd = (struct ext4_encrypted_symlink_data *)caddr;
++	cstr.name = sd->encrypted_path;
++	cstr.len  = le32_to_cpu(sd->len);
++	if ((cstr.len +
++	     sizeof(struct ext4_encrypted_symlink_data) - 1) >
++	    max_size) {
++		/* Symlink data on the disk is corrupted */
++		res = -EIO;
++		goto errout;
++	}
++	plen = (cstr.len < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2) ?
++		EXT4_FNAME_CRYPTO_DIGEST_SIZE*2 : cstr.len;
++	paddr = kmalloc(plen + 1, GFP_NOFS);
++	if (!paddr) {
++		res = -ENOMEM;
++		goto errout;
++	}
++	pstr.name = paddr;
++	res = _ext4_fname_disk_to_usr(ctx, &cstr, &pstr);
++	if (res < 0)
++		goto errout;
++	/* Null-terminate the name */
++	if (res <= plen)
++		paddr[res] = '\0';
++	nd_set_link(nd, paddr);
++	ext4_put_fname_crypto_ctx(&ctx);
++	if (cpage) {
++		kunmap(cpage);
++		page_cache_release(cpage);
++	}
++	return NULL;
++errout:
++	ext4_put_fname_crypto_ctx(&ctx);
++	if (cpage) {
++		kunmap(cpage);
++		page_cache_release(cpage);
++	}
++	kfree(paddr);
++	return ERR_PTR(res);
++}
++
++static void ext4_put_link(struct dentry *dentry, struct nameidata *nd,
++			  void *cookie)
++{
++	struct page *page = cookie;
++
++	if (!page) {
++		kfree(nd_get_link(nd));
++	} else {
++		kunmap(page);
++		page_cache_release(page);
++	}
++}
++#endif
++
++static void *ext4_follow_fast_link(struct dentry *dentry, struct nameidata *nd)
+ {
+ 	struct ext4_inode_info *ei = EXT4_I(dentry->d_inode);
+ 	nd_set_link(nd, (char *) ei->i_data);
+@@ -31,8 +120,13 @@ static void *ext4_follow_link(struct dentry *dentry, struct nameidata *nd)
+ 
+ const struct inode_operations ext4_symlink_inode_operations = {
+ 	.readlink	= generic_readlink,
++#ifdef CONFIG_EXT4_FS_ENCRYPTION
++	.follow_link    = ext4_follow_link,
++	.put_link       = ext4_put_link,
++#else
+ 	.follow_link	= page_follow_link_light,
+ 	.put_link	= page_put_link,
++#endif
+ 	.setattr	= ext4_setattr,
+ 	.setxattr	= generic_setxattr,
+ 	.getxattr	= generic_getxattr,
+@@ -42,7 +136,7 @@ const struct inode_operations ext4_symlink_inode_operations = {
+ 
+ const struct inode_operations ext4_fast_symlink_inode_operations = {
+ 	.readlink	= generic_readlink,
+-	.follow_link	= ext4_follow_link,
++	.follow_link    = ext4_follow_fast_link,
+ 	.setattr	= ext4_setattr,
+ 	.setxattr	= generic_setxattr,
+ 	.getxattr	= generic_getxattr,

commit 2f61830ae33e2944ad66bb8bb40916f534b2e494
+Author: Theodore Ts'o 
+Date:   Sun Apr 12 00:56:26 2015 -0400
+
+    ext4 crypto: teach ext4_htree_store_dirent() to store decrypted filenames
+    
+    For encrypted directories, we need to pass in a separate parameter for
+    the decrypted filename, since the directory entry contains the
+    encrypted filename.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index 9e1e9e7869cb..315f13ad382e 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -382,10 +382,15 @@ void ext4_htree_free_dir_info(struct dir_private_info *p)
+ 
+ /*
+  * Given a directory entry, enter it into the fname rb tree.
++ *
++ * When filename encryption is enabled, the dirent will hold the
++ * encrypted filename, while the htree will hold decrypted filename.
++ * The decrypted filename is passed in via ent_name.  parameter.
+  */
+ int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
+ 			     __u32 minor_hash,
+-			     struct ext4_dir_entry_2 *dirent)
++			    struct ext4_dir_entry_2 *dirent,
++			    struct ext4_str *ent_name)
+ {
+ 	struct rb_node **p, *parent = NULL;
+ 	struct fname *fname, *new_fn;
+@@ -396,17 +401,17 @@ int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
+ 	p = &info->root.rb_node;
+ 
+ 	/* Create and allocate the fname structure */
+-	len = sizeof(struct fname) + dirent->name_len + 1;
++	len = sizeof(struct fname) + ent_name->len + 1;
+ 	new_fn = kzalloc(len, GFP_KERNEL);
+ 	if (!new_fn)
+ 		return -ENOMEM;
+ 	new_fn->hash = hash;
+ 	new_fn->minor_hash = minor_hash;
+ 	new_fn->inode = le32_to_cpu(dirent->inode);
+-	new_fn->name_len = dirent->name_len;
++	new_fn->name_len = ent_name->len;
+ 	new_fn->file_type = dirent->file_type;
+-	memcpy(new_fn->name, dirent->name, dirent->name_len);
+-	new_fn->name[dirent->name_len] = 0;
++	memcpy(new_fn->name, ent_name->name, ent_name->len);
++	new_fn->name[ent_name->len] = 0;
+ 
+ 	while (*p) {
+ 		parent = *p;
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 3462532b227f..ba75838f3588 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2142,8 +2142,9 @@ extern int __ext4_check_dir_entry(const char *, unsigned int, struct inode *,
+ 	unlikely(__ext4_check_dir_entry(__func__, __LINE__, (dir), (filp), \
+ 					(de), (bh), (buf), (size), (offset)))
+ extern int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
+-				    __u32 minor_hash,
+-				    struct ext4_dir_entry_2 *dirent);
++				__u32 minor_hash,
++				struct ext4_dir_entry_2 *dirent,
++				struct ext4_str *ent_name);
+ extern void ext4_htree_free_dir_info(struct dir_private_info *p);
+ extern int ext4_find_dest_de(struct inode *dir, struct inode *inode,
+ 			     struct buffer_head *bh,
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index 8b64d715e476..661f0b8dcfe0 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -1327,6 +1327,7 @@ int htree_inlinedir_to_tree(struct file *dir_file,
+ 	struct ext4_iloc iloc;
+ 	void *dir_buf = NULL;
+ 	struct ext4_dir_entry_2 fake;
++	struct ext4_str tmp_str;
+ 
+ 	ret = ext4_get_inode_loc(inode, &iloc);
+ 	if (ret)
+@@ -1398,8 +1399,10 @@ int htree_inlinedir_to_tree(struct file *dir_file,
+ 			continue;
+ 		if (de->inode == 0)
+ 			continue;
+-		err = ext4_htree_store_dirent(dir_file,
+-				   hinfo->hash, hinfo->minor_hash, de);
++		tmp_str.name = de->name;
++		tmp_str.len = de->name_len;
++		err = ext4_htree_store_dirent(dir_file, hinfo->hash,
++					      hinfo->minor_hash, de, &tmp_str);
+ 		if (err) {
+ 			count = err;
+ 			goto out;
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 77a63ff4aeb9..8cef115ee64a 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -877,6 +877,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
+ 	struct buffer_head *bh;
+ 	struct ext4_dir_entry_2 *de, *top;
+ 	int err = 0, count = 0;
++	struct ext4_str tmp_str;
+ 
+ 	dxtrace(printk(KERN_INFO "In htree dirblock_to_tree: block %lu\n",
+ 							(unsigned long)block));
+@@ -903,8 +904,11 @@ static int htree_dirblock_to_tree(struct file *dir_file,
+ 			continue;
+ 		if (de->inode == 0)
+ 			continue;
+-		if ((err = ext4_htree_store_dirent(dir_file,
+-				   hinfo->hash, hinfo->minor_hash, de)) != 0) {
++		tmp_str.name = de->name;
++		tmp_str.len = de->name_len;
++		err = ext4_htree_store_dirent(dir_file,
++			   hinfo->hash, hinfo->minor_hash, de, &tmp_str);
++		if (err != 0) {
+ 			brelse(bh);
+ 			return err;
+ 		}
+@@ -934,6 +938,7 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
+ 	int count = 0;
+ 	int ret, err;
+ 	__u32 hashval;
++	struct ext4_str tmp_str;
+ 
+ 	dxtrace(printk(KERN_DEBUG "In htree_fill_tree, start hash: %x:%x\n",
+ 		       start_hash, start_minor_hash));
+@@ -969,14 +974,22 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
+ 	/* Add '.' and '..' from the htree header */
+ 	if (!start_hash && !start_minor_hash) {
+ 		de = (struct ext4_dir_entry_2 *) frames[0].bh->b_data;
+-		if ((err = ext4_htree_store_dirent(dir_file, 0, 0, de)) != 0)
++		tmp_str.name = de->name;
++		tmp_str.len = de->name_len;
++		err = ext4_htree_store_dirent(dir_file, 0, 0,
++					      de, &tmp_str);
++		if (err != 0)
+ 			goto errout;
+ 		count++;
+ 	}
+ 	if (start_hash < 2 || (start_hash ==2 && start_minor_hash==0)) {
+ 		de = (struct ext4_dir_entry_2 *) frames[0].bh->b_data;
+ 		de = ext4_next_entry(de, dir->i_sb->s_blocksize);
+-		if ((err = ext4_htree_store_dirent(dir_file, 2, 0, de)) != 0)
++		tmp_str.name = de->name;
++		tmp_str.len = de->name_len;
++		err = ext4_htree_store_dirent(dir_file, 2, 0,
++					      de, &tmp_str);
++		if (err != 0)
+ 			goto errout;
+ 		count++;
+ 	}

commit d9cdc903318171571f1cd1e5737fd0cab94186be
+Author: Theodore Ts'o 
+Date:   Sun Apr 12 00:55:08 2015 -0400
+
+    ext4 crypto: enforce context consistency
+    
+    Enforce the following inheritance policy:
+    
+    1) An unencrypted directory may contain encrypted or unencrypted files
+    or directories.
+    
+    2) All files or directories in a directory must be protected using the
+    same key as their containing directory.
+    
+    As a result, assuming the following setup:
+    
+    mke2fs -t ext4 -Fq -O encrypt /dev/vdc
+    mount -t ext4 /dev/vdc /vdc
+    mkdir /vdc/a /vdc/b /vdc/c
+    echo foo | e4crypt add_key /vdc/a
+    echo bar | e4crypt add_key /vdc/b
+    for i in a b c ; do cp /etc/motd /vdc/$i/motd-$i ; done
+    
+    Then we will see the following results:
+    
+    cd /vdc
+    mv a b                  # will fail; /vdc/a and /vdc/b have different keys
+    mv b/motd-b a           # will fail, see above
+    ln a/motd-a b           # will fail, see above
+    mv c a                  # will fail; all inodes in an encrypted directory
+                            #       must be encrypted
+    ln c/motd-c b           # will fail, see above
+    mv a/motd-a c           # will succeed
+    mv c/motd-a a           # will succeed
+    
+    Signed-off-by: Michael Halcrow 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 0dbd2d2937f7..acd79198b800 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1416,6 +1416,18 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
+ 					 ino);
+ 			return ERR_PTR(-EIO);
+ 		}
++		if (!IS_ERR(inode) && ext4_encrypted_inode(dir) &&
++		    (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
++		     S_ISLNK(inode->i_mode)) &&
++		    !ext4_is_child_context_consistent_with_parent(dir,
++								  inode)) {
++			iput(inode);
++			ext4_warning(inode->i_sb,
++				     "Inconsistent encryption contexts: %lu/%lu\n",
++				     (unsigned long) dir->i_ino,
++				     (unsigned long) inode->i_ino);
++			return ERR_PTR(-EPERM);
++		}
+ 	}
+ 	return d_splice_alias(inode, dentry);
+ }
+@@ -2944,7 +2956,9 @@ static int ext4_link(struct dentry *old_dentry,
+ 
+ 	if (inode->i_nlink >= EXT4_LINK_MAX)
+ 		return -EMLINK;
+-
++	if (ext4_encrypted_inode(dir) &&
++	    !ext4_is_child_context_consistent_with_parent(dir, inode))
++		return -EPERM;
+ 	dquot_initialize(dir);
+ 
+ retry:
+@@ -3245,6 +3259,14 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 	if (!old.bh || le32_to_cpu(old.de->inode) != old.inode->i_ino)
+ 		goto end_rename;
+ 
++	if ((old.dir != new.dir) &&
++	    ext4_encrypted_inode(new.dir) &&
++	    !ext4_is_child_context_consistent_with_parent(new.dir,
++							  old.inode)) {
++		retval = -EPERM;
++		goto end_rename;
++	}
++
+ 	new.bh = ext4_find_entry(new.dir, &new.dentry->d_name,
+ 				 &new.de, &new.inlined);
+ 	if (IS_ERR(new.bh)) {

commit b17655fb7f4a1d27c1e50dcc28268612da944a54
+Author: Theodore Ts'o 
+Date:   Sat Apr 11 07:46:47 2015 -0400
+
+    ext4 crypto: add ext4 encryption Kconfig
+    
+    Signed-off-by: Michael Halcrow 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
+index efea5d5c44ce..18228c201f7f 100644
+--- a/fs/ext4/Kconfig
++++ b/fs/ext4/Kconfig
+@@ -64,6 +64,23 @@ config EXT4_FS_SECURITY
+ 	  If you are not using a security module that requires using
+ 	  extended attributes for file security labels, say N.
+ 
++config EXT4_FS_ENCRYPTION
++	bool "Ext4 Encryption"
++	depends on EXT4_FS
++	select CRYPTO_AES
++	select CRYPTO_CBC
++	select CRYPTO_ECB
++	select CRYPTO_XTS
++	select CRYPTO_CTS
++	select CRYPTO_SHA256
++	select KEYS
++	select ENCRYPTED_KEYS
++	help
++	  Enable encryption of ext4 files and directories.  This
++	  feature is similar to ecryptfs, but it is more memory
++	  efficient since it avoids caching the encrypted and
++	  decrypted pages in the page cache.
++
+ config EXT4_DEBUG
+ 	bool "EXT4 debugging support"
+ 	depends on EXT4_FS

commit f542fbe8d5e842ed4e9ad6ccc6c2913407451c51
+Author: Theodore Ts'o 
+Date:   Sat Apr 11 07:44:12 2015 -0400
+
+    ext4 crypto: reserve codepoints used by the ext4 encryption feature
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index f7f3f5871796..e1683829b2b5 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -422,7 +422,7 @@ enum {
+ 	EXT4_INODE_DIRTY	= 8,
+ 	EXT4_INODE_COMPRBLK	= 9,	/* One or more compressed clusters */
+ 	EXT4_INODE_NOCOMPR	= 10,	/* Don't compress */
+-	EXT4_INODE_ENCRYPT	= 11,	/* Compression error */
++	EXT4_INODE_ENCRYPT	= 11,	/* Encrypted file */
+ /* End compression flags --- maybe not all used */
+ 	EXT4_INODE_INDEX	= 12,	/* hash-indexed directory */
+ 	EXT4_INODE_IMAGIC	= 13,	/* AFS directory */
+@@ -582,6 +582,13 @@ enum {
+ #define EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER	0x0010
+ #define EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER	0x0020
+ 
++/* Encryption algorithms */
++#define EXT4_ENCRYPTION_MODE_INVALID		0
++#define EXT4_ENCRYPTION_MODE_AES_256_XTS	1
++#define EXT4_ENCRYPTION_MODE_AES_256_GCM	2
++#define EXT4_ENCRYPTION_MODE_AES_256_CBC	3
++#define EXT4_ENCRYPTION_MODE_AES_256_CTS	4
++
+ /*
+  * ioctl commands
+  */
+@@ -1142,7 +1149,8 @@ struct ext4_super_block {
+ 	__le32  s_raid_stripe_width;    /* blocks on all data disks (N*stride)*/
+ 	__u8	s_log_groups_per_flex;  /* FLEX_BG group size */
+ 	__u8	s_checksum_type;	/* metadata checksum algorithm used */
+-	__le16  s_reserved_pad;
++	__u8	s_encryption_level;	/* versioning level for encryption */
++	__u8	s_reserved_pad;		/* Padding to next 32bits */
+ 	__le64	s_kbytes_written;	/* nr of lifetime kilobytes written */
+ 	__le32	s_snapshot_inum;	/* Inode number of active snapshot */
+ 	__le32	s_snapshot_id;		/* sequential ID of active snapshot */
+@@ -1169,7 +1177,9 @@ struct ext4_super_block {
+ 	__le32	s_overhead_clusters;	/* overhead blocks/clusters in fs */
+ 	__le32	s_backup_bgs[2];	/* groups with sparse_super2 SBs */
+ 	__u8	s_encrypt_algos[4];	/* Encryption algorithms in use  */
+-	__le32	s_reserved[105];	/* Padding to the end of the block */
++	__u8	s_encrypt_pw_salt[16];	/* Salt used for string2key algorithm */
++	__le32	s_lpf_ino;		/* Location of the lost+found inode */
++	__le32	s_reserved[100];	/* Padding to the end of the block */
+ 	__le32	s_checksum;		/* crc32c(superblock) */
+ };
+ 

commit f64e02fe9bc6a359cab95632b33900094d225ae1
+Author: Theodore Ts'o 
+Date:   Wed Apr 8 00:00:32 2015 -0400
+
+    ext4 crypto: add ext4_mpage_readpages()
+    
+    This takes code from fs/mpage.c and optimizes it for ext4.  Its
+    primary reason is to allow us to more easily add encryption to ext4's
+    read path in an efficient manner.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
+index 0310fec2ee3d..cd6f50fce278 100644
+--- a/fs/ext4/Makefile
++++ b/fs/ext4/Makefile
+@@ -8,7 +8,7 @@ ext4-y	:= balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o page-io.o \
+ 		ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \
+ 		ext4_jbd2.o migrate.o mballoc.o block_validity.o move_extent.o \
+ 		mmp.o indirect.o extents_status.o xattr.o xattr_user.o \
+-		xattr_trusted.o inline.o
++		xattr_trusted.o inline.o readpage.o
+ 
+ ext4-$(CONFIG_EXT4_FS_POSIX_ACL)	+= acl.o
+ ext4-$(CONFIG_EXT4_FS_SECURITY)		+= xattr_security.o
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index f63c3d5805c4..f7f3f5871796 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2699,6 +2699,10 @@ static inline void ext4_set_de_type(struct super_block *sb,
+ 		de->file_type = ext4_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
+ }
+ 
++/* readpages.c */
++extern int ext4_mpage_readpages(struct address_space *mapping,
++				struct list_head *pages, struct page *page,
++				unsigned nr_pages);
+ 
+ /* symlink.c */
+ extern const struct inode_operations ext4_symlink_inode_operations;
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index ff0c111e52eb..cd3009152ae2 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2820,7 +2820,7 @@ static int ext4_readpage(struct file *file, struct page *page)
+ 		ret = ext4_readpage_inline(inode, page);
+ 
+ 	if (ret == -EAGAIN)
+-		return mpage_readpage(page, ext4_get_block);
++		return ext4_mpage_readpages(page->mapping, NULL, page, 1);
+ 
+ 	return ret;
+ }
+@@ -2835,7 +2835,7 @@ ext4_readpages(struct file *file, struct address_space *mapping,
+ 	if (ext4_has_inline_data(inode))
+ 		return 0;
+ 
+-	return mpage_readpages(mapping, pages, nr_pages, ext4_get_block);
++	return ext4_mpage_readpages(mapping, pages, NULL, nr_pages);
+ }
+ 
+ static void ext4_invalidatepage(struct page *page, unsigned int offset,
+diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
+new file mode 100644
+index 000000000000..fff9fe6aacf8
+--- /dev/null
++++ b/fs/ext4/readpage.c
+@@ -0,0 +1,264 @@
++/*
++ * linux/fs/ext4/readpage.c
++ *
++ * Copyright (C) 2002, Linus Torvalds.
++ * Copyright (C) 2015, Google, Inc.
++ *
++ * This was originally taken from fs/mpage.c
++ *
++ * The intent is the ext4_mpage_readpages() function here is intended
++ * to replace mpage_readpages() in the general case, not just for
++ * encrypted files.  It has some limitations (see below), where it
++ * will fall back to read_block_full_page(), but these limitations
++ * should only be hit when page_size != block_size.
++ *
++ * This will allow us to attach a callback function to support ext4
++ * encryption.
++ *
++ * If anything unusual happens, such as:
++ *
++ * - encountering a page which has buffers
++ * - encountering a page which has a non-hole after a hole
++ * - encountering a page with non-contiguous blocks
++ *
++ * then this code just gives up and calls the buffer_head-based read function.
++ * It does handle a page which has holes at the end - that is a common case:
++ * the end-of-file on blocksize < PAGE_CACHE_SIZE setups.
++ *
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include "ext4.h"
++
++/*
++ * I/O completion handler for multipage BIOs.
++ *
++ * The mpage code never puts partial pages into a BIO (except for end-of-file).
++ * If a page does not map to a contiguous run of blocks then it simply falls
++ * back to block_read_full_page().
++ *
++ * Why is this?  If a page's completion depends on a number of different BIOs
++ * which can complete in any order (or at the same time) then determining the
++ * status of that page is hard.  See end_buffer_async_read() for the details.
++ * There is no point in duplicating all that complexity.
++ */
++static void mpage_end_io(struct bio *bio, int err)
++{
++	struct bio_vec *bv;
++	int i;
++
++	bio_for_each_segment_all(bv, bio, i) {
++		struct page *page = bv->bv_page;
++
++		if (!err) {
++			SetPageUptodate(page);
++		} else {
++			ClearPageUptodate(page);
++			SetPageError(page);
++		}
++		unlock_page(page);
++	}
++
++	bio_put(bio);
++}
++
++int ext4_mpage_readpages(struct address_space *mapping,
++			 struct list_head *pages, struct page *page,
++			 unsigned nr_pages)
++{
++	struct bio *bio = NULL;
++	unsigned page_idx;
++	sector_t last_block_in_bio = 0;
++
++	struct inode *inode = mapping->host;
++	const unsigned blkbits = inode->i_blkbits;
++	const unsigned blocks_per_page = PAGE_CACHE_SIZE >> blkbits;
++	const unsigned blocksize = 1 << blkbits;
++	sector_t block_in_file;
++	sector_t last_block;
++	sector_t last_block_in_file;
++	sector_t blocks[MAX_BUF_PER_PAGE];
++	unsigned page_block;
++	struct block_device *bdev = inode->i_sb->s_bdev;
++	int length;
++	unsigned relative_block = 0;
++	struct ext4_map_blocks map;
++
++	map.m_pblk = 0;
++	map.m_lblk = 0;
++	map.m_len = 0;
++	map.m_flags = 0;
++
++	for (page_idx = 0; nr_pages; page_idx++, nr_pages--) {
++		int fully_mapped = 1;
++		unsigned first_hole = blocks_per_page;
++
++		prefetchw(&page->flags);
++		if (pages) {
++			page = list_entry(pages->prev, struct page, lru);
++			list_del(&page->lru);
++			if (add_to_page_cache_lru(page, mapping,
++						  page->index, GFP_KERNEL))
++				goto next_page;
++		}
++
++		if (page_has_buffers(page))
++			goto confused;
++
++		block_in_file = (sector_t)page->index << (PAGE_CACHE_SHIFT - blkbits);
++		last_block = block_in_file + nr_pages * blocks_per_page;
++		last_block_in_file = (i_size_read(inode) + blocksize - 1) >> blkbits;
++		if (last_block > last_block_in_file)
++			last_block = last_block_in_file;
++		page_block = 0;
++
++		/*
++		 * Map blocks using the previous result first.
++		 */
++		if ((map.m_flags & EXT4_MAP_MAPPED) &&
++		    block_in_file > map.m_lblk &&
++		    block_in_file < (map.m_lblk + map.m_len)) {
++			unsigned map_offset = block_in_file - map.m_lblk;
++			unsigned last = map.m_len - map_offset;
++
++			for (relative_block = 0; ; relative_block++) {
++				if (relative_block == last) {
++					/* needed? */
++					map.m_flags &= ~EXT4_MAP_MAPPED;
++					break;
++				}
++				if (page_block == blocks_per_page)
++					break;
++				blocks[page_block] = map.m_pblk + map_offset +
++					relative_block;
++				page_block++;
++				block_in_file++;
++			}
++		}
++
++		/*
++		 * Then do more ext4_map_blocks() calls until we are
++		 * done with this page.
++		 */
++		while (page_block < blocks_per_page) {
++			if (block_in_file < last_block) {
++				map.m_lblk = block_in_file;
++				map.m_len = last_block - block_in_file;
++
++				if (ext4_map_blocks(NULL, inode, &map, 0) < 0) {
++				set_error_page:
++					SetPageError(page);
++					zero_user_segment(page, 0,
++							  PAGE_CACHE_SIZE);
++					unlock_page(page);
++					goto next_page;
++				}
++			}
++			if ((map.m_flags & EXT4_MAP_MAPPED) == 0) {
++				fully_mapped = 0;
++				if (first_hole == blocks_per_page)
++					first_hole = page_block;
++				page_block++;
++				block_in_file++;
++				continue;
++			}
++			if (first_hole != blocks_per_page)
++				goto confused;		/* hole -> non-hole */
++
++			/* Contiguous blocks? */
++			if (page_block && blocks[page_block-1] != map.m_pblk-1)
++				goto confused;
++			for (relative_block = 0; ; relative_block++) {
++				if (relative_block == map.m_len) {
++					/* needed? */
++					map.m_flags &= ~EXT4_MAP_MAPPED;
++					break;
++				} else if (page_block == blocks_per_page)
++					break;
++				blocks[page_block] = map.m_pblk+relative_block;
++				page_block++;
++				block_in_file++;
++			}
++		}
++		if (first_hole != blocks_per_page) {
++			zero_user_segment(page, first_hole << blkbits,
++					  PAGE_CACHE_SIZE);
++			if (first_hole == 0) {
++				SetPageUptodate(page);
++				unlock_page(page);
++				goto next_page;
++			}
++		} else if (fully_mapped) {
++			SetPageMappedToDisk(page);
++		}
++		if (fully_mapped && blocks_per_page == 1 &&
++		    !PageUptodate(page) && cleancache_get_page(page) == 0) {
++			SetPageUptodate(page);
++			goto confused;
++		}
++
++		/*
++		 * This page will go to BIO.  Do we need to send this
++		 * BIO off first?
++		 */
++		if (bio && (last_block_in_bio != blocks[0] - 1)) {
++		submit_and_realloc:
++			submit_bio(READ, bio);
++			bio = NULL;
++		}
++		if (bio == NULL) {
++			bio = bio_alloc(GFP_KERNEL,
++				min_t(int, nr_pages, bio_get_nr_vecs(bdev)));
++			if (!bio)
++				goto set_error_page;
++			bio->bi_bdev = bdev;
++			bio->bi_iter.bi_sector = blocks[0] << (blkbits - 9);
++			bio->bi_end_io = mpage_end_io;
++		}
++
++		length = first_hole << blkbits;
++		if (bio_add_page(bio, page, length, 0) < length)
++			goto submit_and_realloc;
++
++		if (((map.m_flags & EXT4_MAP_BOUNDARY) &&
++		     (relative_block == map.m_len)) ||
++		    (first_hole != blocks_per_page)) {
++			submit_bio(READ, bio);
++			bio = NULL;
++		} else
++			last_block_in_bio = blocks[blocks_per_page - 1];
++		goto next_page;
++	confused:
++		if (bio) {
++			submit_bio(READ, bio);
++			bio = NULL;
++		}
++		if (!PageUptodate(page))
++			block_read_full_page(page, ext4_get_block);
++		else
++			unlock_page(page);
++	next_page:
++		if (pages)
++			page_cache_release(page);
++	}
++	BUG_ON(pages && !list_empty(pages));
++	if (bio)
++		submit_bio(READ, bio);
++	return 0;
++}

commit 1efff914afac8a965ad63817ecf8861a927c2ace
+Author: Theodore Ts'o 
+Date:   Tue Mar 17 12:23:32 2015 -0400
+
+    fs: add dirtytime_expire_seconds sysctl
+    
+    Add a tuning knob so we can adjust the dirtytime expiration timeout,
+    which is very useful for testing lazytime.
+    
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
+index 2cfcd74faf87..32a8bbd7a9ad 100644
+--- a/fs/fs-writeback.c
++++ b/fs/fs-writeback.c
+@@ -1188,6 +1188,17 @@ static int __init start_dirtytime_writeback(void)
+ }
+ __initcall(start_dirtytime_writeback);
+ 
++int dirtytime_interval_handler(struct ctl_table *table, int write,
++			       void __user *buffer, size_t *lenp, loff_t *ppos)
++{
++	int ret;
++
++	ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
++	if (ret == 0 && write)
++		mod_delayed_work(system_wq, &dirtytime_work, 0);
++	return ret;
++}
++
+ static noinline void block_dump___mark_inode_dirty(struct inode *inode)
+ {
+ 	if (inode->i_ino || strcmp(inode->i_sb->s_id, "bdev")) {
+diff --git a/include/linux/writeback.h b/include/linux/writeback.h
+index 00048339c23e..b2dd371ec0ca 100644
+--- a/include/linux/writeback.h
++++ b/include/linux/writeback.h
+@@ -130,6 +130,7 @@ extern int vm_dirty_ratio;
+ extern unsigned long vm_dirty_bytes;
+ extern unsigned int dirty_writeback_interval;
+ extern unsigned int dirty_expire_interval;
++extern unsigned int dirtytime_expire_interval;
+ extern int vm_highmem_is_dirtyable;
+ extern int block_dump;
+ extern int laptop_mode;
+@@ -146,6 +147,8 @@ extern int dirty_ratio_handler(struct ctl_table *table, int write,
+ extern int dirty_bytes_handler(struct ctl_table *table, int write,
+ 		void __user *buffer, size_t *lenp,
+ 		loff_t *ppos);
++int dirtytime_interval_handler(struct ctl_table *table, int write,
++			       void __user *buffer, size_t *lenp, loff_t *ppos);
+ 
+ struct ctl_table;
+ int dirty_writeback_centisecs_handler(struct ctl_table *, int,
+diff --git a/kernel/sysctl.c b/kernel/sysctl.c
+index 88ea2d6e0031..ce410bb9f2e1 100644
+--- a/kernel/sysctl.c
++++ b/kernel/sysctl.c
+@@ -1227,6 +1227,14 @@ static struct ctl_table vm_table[] = {
+ 		.proc_handler	= proc_dointvec_minmax,
+ 		.extra1		= &zero,
+ 	},
++	{
++		.procname	= "dirtytime_expire_seconds",
++		.data		= &dirtytime_expire_interval,
++		.maxlen		= sizeof(dirty_expire_interval),
++		.mode		= 0644,
++		.proc_handler	= dirtytime_interval_handler,
++		.extra1		= &zero,
++	},
+ 	{
+ 		.procname       = "nr_pdflush_threads",
+ 		.mode           = 0444 /* read-only */,

commit a2f4870697a5bcf4a87073ec6b32dd2928c1211d
+Author: Theodore Ts'o 
+Date:   Tue Mar 17 12:23:19 2015 -0400
+
+    fs: make sure the timestamps for lazytime inodes eventually get written
+    
+    Jan Kara pointed out that if there is an inode which is constantly
+    getting dirtied with I_DIRTY_PAGES, an inode with an updated timestamp
+    will never be written since inode->dirtied_when is constantly getting
+    updated.  We fix this by adding an extra field to the inode,
+    dirtied_time_when, so inodes with a stale dirtytime can get detected
+    and handled.
+    
+    In addition, if we have a dirtytime inode caused by an atime update,
+    and there is no write activity on the file system, we need to have a
+    secondary system to make sure these inodes get written out.  We do
+    this by setting up a second delayed work structure which wakes up the
+    CPU much more rarely compared to writeback_expire_centisecs.
+    
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
+index e907052eeadb..2cfcd74faf87 100644
+--- a/fs/fs-writeback.c
++++ b/fs/fs-writeback.c
+@@ -53,6 +53,18 @@ struct wb_writeback_work {
+ 	struct completion *done;	/* set if the caller waits */
+ };
+ 
++/*
++ * If an inode is constantly having its pages dirtied, but then the
++ * updates stop dirtytime_expire_interval seconds in the past, it's
++ * possible for the worst case time between when an inode has its
++ * timestamps updated and when they finally get written out to be two
++ * dirtytime_expire_intervals.  We set the default to 12 hours (in
++ * seconds), which means most of the time inodes will have their
++ * timestamps written to disk after 12 hours, but in the worst case a
++ * few inodes might not their timestamps updated for 24 hours.
++ */
++unsigned int dirtytime_expire_interval = 12 * 60 * 60;
++
+ /**
+  * writeback_in_progress - determine whether there is writeback in progress
+  * @bdi: the device's backing_dev_info structure.
+@@ -275,8 +287,8 @@ static int move_expired_inodes(struct list_head *delaying_queue,
+ 
+ 	if ((flags & EXPIRE_DIRTY_ATIME) == 0)
+ 		older_than_this = work->older_than_this;
+-	else if ((work->reason == WB_REASON_SYNC) == 0) {
+-		expire_time = jiffies - (HZ * 86400);
++	else if (!work->for_sync) {
++		expire_time = jiffies - (dirtytime_expire_interval * HZ);
+ 		older_than_this = &expire_time;
+ 	}
+ 	while (!list_empty(delaying_queue)) {
+@@ -458,6 +470,7 @@ static void requeue_inode(struct inode *inode, struct bdi_writeback *wb,
+ 		 */
+ 		redirty_tail(inode, wb);
+ 	} else if (inode->i_state & I_DIRTY_TIME) {
++		inode->dirtied_when = jiffies;
+ 		list_move(&inode->i_wb_list, &wb->b_dirty_time);
+ 	} else {
+ 		/* The inode is clean. Remove from writeback lists. */
+@@ -505,12 +518,17 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
+ 	spin_lock(&inode->i_lock);
+ 
+ 	dirty = inode->i_state & I_DIRTY;
+-	if (((dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) &&
+-	     (inode->i_state & I_DIRTY_TIME)) ||
+-	    (inode->i_state & I_DIRTY_TIME_EXPIRED)) {
+-		dirty |= I_DIRTY_TIME | I_DIRTY_TIME_EXPIRED;
+-		trace_writeback_lazytime(inode);
+-	}
++	if (inode->i_state & I_DIRTY_TIME) {
++		if ((dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) ||
++		    unlikely(inode->i_state & I_DIRTY_TIME_EXPIRED) ||
++		    unlikely(time_after(jiffies,
++					(inode->dirtied_time_when +
++					 dirtytime_expire_interval * HZ)))) {
++			dirty |= I_DIRTY_TIME | I_DIRTY_TIME_EXPIRED;
++			trace_writeback_lazytime(inode);
++		}
++	} else
++		inode->i_state &= ~I_DIRTY_TIME_EXPIRED;
+ 	inode->i_state &= ~dirty;
+ 
+ 	/*
+@@ -1131,6 +1149,45 @@ void wakeup_flusher_threads(long nr_pages, enum wb_reason reason)
+ 	rcu_read_unlock();
+ }
+ 
++/*
++ * Wake up bdi's periodically to make sure dirtytime inodes gets
++ * written back periodically.  We deliberately do *not* check the
++ * b_dirtytime list in wb_has_dirty_io(), since this would cause the
++ * kernel to be constantly waking up once there are any dirtytime
++ * inodes on the system.  So instead we define a separate delayed work
++ * function which gets called much more rarely.  (By default, only
++ * once every 12 hours.)
++ *
++ * If there is any other write activity going on in the file system,
++ * this function won't be necessary.  But if the only thing that has
++ * happened on the file system is a dirtytime inode caused by an atime
++ * update, we need this infrastructure below to make sure that inode
++ * eventually gets pushed out to disk.
++ */
++static void wakeup_dirtytime_writeback(struct work_struct *w);
++static DECLARE_DELAYED_WORK(dirtytime_work, wakeup_dirtytime_writeback);
++
++static void wakeup_dirtytime_writeback(struct work_struct *w)
++{
++	struct backing_dev_info *bdi;
++
++	rcu_read_lock();
++	list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) {
++		if (list_empty(&bdi->wb.b_dirty_time))
++			continue;
++		bdi_wakeup_thread(bdi);
++	}
++	rcu_read_unlock();
++	schedule_delayed_work(&dirtytime_work, dirtytime_expire_interval * HZ);
++}
++
++static int __init start_dirtytime_writeback(void)
++{
++	schedule_delayed_work(&dirtytime_work, dirtytime_expire_interval * HZ);
++	return 0;
++}
++__initcall(start_dirtytime_writeback);
++
+ static noinline void block_dump___mark_inode_dirty(struct inode *inode)
+ {
+ 	if (inode->i_ino || strcmp(inode->i_sb->s_id, "bdev")) {
+@@ -1269,8 +1326,13 @@ void __mark_inode_dirty(struct inode *inode, int flags)
+ 			}
+ 
+ 			inode->dirtied_when = jiffies;
+-			list_move(&inode->i_wb_list, dirtytime ?
+-				  &bdi->wb.b_dirty_time : &bdi->wb.b_dirty);
++			if (dirtytime)
++				inode->dirtied_time_when = jiffies;
++			if (inode->i_state & (I_DIRTY_INODE | I_DIRTY_PAGES))
++				list_move(&inode->i_wb_list, &bdi->wb.b_dirty);
++			else
++				list_move(&inode->i_wb_list,
++					  &bdi->wb.b_dirty_time);
+ 			spin_unlock(&bdi->wb.list_lock);
+ 			trace_writeback_dirty_inode_enqueue(inode);
+ 
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index b4d71b5e1ff2..f4131e8ead74 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -604,6 +604,7 @@ struct inode {
+ 	struct mutex		i_mutex;
+ 
+ 	unsigned long		dirtied_when;	/* jiffies of first dirtying */
++	unsigned long		dirtied_time_when;
+ 
+ 	struct hlist_node	i_hash;
+ 	struct list_head	i_wb_list;	/* backing dev IO list */

commit a26f49926da938f47561f386be56a83dd37a496d
+Author: Theodore Ts'o 
+Date:   Mon Feb 2 00:37:02 2015 -0500
+
+    ext4: add optimization for the lazytime mount option
+    
+    Add an optimization for the MS_LAZYTIME mount option so that we will
+    opportunistically write out any inodes with the I_DIRTY_TIME flag set
+    in a particular inode table block when we need to update some inode in
+    that inode table block anyway.
+    
+    Also add some temporary code so that we can set the lazytime mount
+    option without needing a modified /sbin/mount program which can set
+    MS_LAZYTIME.  We can eventually make this go away once util-linux has
+    added support.
+    
+    Google-Bug-Id: 18297052
+    
+    Signed-off-by: Theodore Ts'o 
+    Signed-off-by: Al Viro 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 628df5ba44a6..9193ea130dcb 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4139,6 +4139,65 @@ static int ext4_inode_blocks_set(handle_t *handle,
+ 	return 0;
+ }
+ 
++struct other_inode {
++	unsigned long		orig_ino;
++	struct ext4_inode	*raw_inode;
++};
++
++static int other_inode_match(struct inode * inode, unsigned long ino,
++			     void *data)
++{
++	struct other_inode *oi = (struct other_inode *) data;
++
++	if ((inode->i_ino != ino) ||
++	    (inode->i_state & (I_FREEING | I_WILL_FREE | I_NEW |
++			       I_DIRTY_SYNC | I_DIRTY_DATASYNC)) ||
++	    ((inode->i_state & I_DIRTY_TIME) == 0))
++		return 0;
++	spin_lock(&inode->i_lock);
++	if (((inode->i_state & (I_FREEING | I_WILL_FREE | I_NEW |
++				I_DIRTY_SYNC | I_DIRTY_DATASYNC)) == 0) &&
++	    (inode->i_state & I_DIRTY_TIME)) {
++		struct ext4_inode_info	*ei = EXT4_I(inode);
++
++		inode->i_state &= ~(I_DIRTY_TIME | I_DIRTY_TIME_EXPIRED);
++		spin_unlock(&inode->i_lock);
++
++		spin_lock(&ei->i_raw_lock);
++		EXT4_INODE_SET_XTIME(i_ctime, inode, oi->raw_inode);
++		EXT4_INODE_SET_XTIME(i_mtime, inode, oi->raw_inode);
++		EXT4_INODE_SET_XTIME(i_atime, inode, oi->raw_inode);
++		ext4_inode_csum_set(inode, oi->raw_inode, ei);
++		spin_unlock(&ei->i_raw_lock);
++		trace_ext4_other_inode_update_time(inode, oi->orig_ino);
++		return -1;
++	}
++	spin_unlock(&inode->i_lock);
++	return -1;
++}
++
++/*
++ * Opportunistically update the other time fields for other inodes in
++ * the same inode table block.
++ */
++static void ext4_update_other_inodes_time(struct super_block *sb,
++					  unsigned long orig_ino, char *buf)
++{
++	struct other_inode oi;
++	unsigned long ino;
++	int i, inodes_per_block = EXT4_SB(sb)->s_inodes_per_block;
++	int inode_size = EXT4_INODE_SIZE(sb);
++
++	oi.orig_ino = orig_ino;
++	ino = orig_ino & ~(inodes_per_block - 1);
++	for (i = 0; i < inodes_per_block; i++, ino++, buf += inode_size) {
++		if (ino == orig_ino)
++			continue;
++		oi.raw_inode = (struct ext4_inode *) buf;
++		(void) find_inode_nowait(sb, ino, other_inode_match, &oi);
++	}
++}
++
+ /*
+  * Post the struct inode info into an on-disk inode location in the
+  * buffer-cache.  This gobbles the caller's reference to the
+@@ -4248,10 +4307,11 @@ static int ext4_do_update_inode(handle_t *handle,
+ 				cpu_to_le16(ei->i_extra_isize);
+ 		}
+ 	}
+-
+ 	ext4_inode_csum_set(inode, raw_inode, ei);
+-
+ 	spin_unlock(&ei->i_raw_lock);
++	if (inode->i_sb->s_flags & MS_LAZYTIME)
++		ext4_update_other_inodes_time(inode->i_sb, inode->i_ino,
++					      bh->b_data);
+ 
+ 	BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
+ 	rc = ext4_handle_dirty_metadata(handle, NULL, bh);
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 74c5f53595fb..362b23c8497a 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1139,6 +1139,7 @@ enum {
+ 	Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err,
+ 	Opt_usrquota, Opt_grpquota, Opt_i_version,
+ 	Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_mblk_io_submit,
++	Opt_lazytime, Opt_nolazytime,
+ 	Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity,
+ 	Opt_inode_readahead_blks, Opt_journal_ioprio,
+ 	Opt_dioread_nolock, Opt_dioread_lock,
+@@ -1202,6 +1203,8 @@ static const match_table_t tokens = {
+ 	{Opt_i_version, "i_version"},
+ 	{Opt_stripe, "stripe=%u"},
+ 	{Opt_delalloc, "delalloc"},
++	{Opt_lazytime, "lazytime"},
++	{Opt_nolazytime, "nolazytime"},
+ 	{Opt_nodelalloc, "nodelalloc"},
+ 	{Opt_removed, "mblk_io_submit"},
+ 	{Opt_removed, "nomblk_io_submit"},
+@@ -1459,6 +1462,12 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
+ 	case Opt_i_version:
+ 		sb->s_flags |= MS_I_VERSION;
+ 		return 1;
++	case Opt_lazytime:
++		sb->s_flags |= MS_LAZYTIME;
++		return 1;
++	case Opt_nolazytime:
++		sb->s_flags &= ~MS_LAZYTIME;
++		return 1;
+ 	}
+ 
+ 	for (m = ext4_mount_opts; m->token != Opt_err; m++)
+@@ -5020,6 +5029,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 	}
+ #endif
+ 
++	*flags = (*flags & ~MS_LAZYTIME) | (sb->s_flags & MS_LAZYTIME);
+ 	ext4_msg(sb, KERN_INFO, "re-mounted. Opts: %s", orig_data);
+ 	kfree(orig_data);
+ 	return 0;
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index 6cfb841fea7c..6e5abd6d38a2 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -73,6 +73,36 @@ struct extent_status;
+ 	{ FALLOC_FL_ZERO_RANGE,		"ZERO_RANGE"})
+ 
+ 
++TRACE_EVENT(ext4_other_inode_update_time,
++	TP_PROTO(struct inode *inode, ino_t orig_ino),
++
++	TP_ARGS(inode, orig_ino),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	ino_t,	orig_ino		)
++		__field(	uid_t,	uid			)
++		__field(	gid_t,	gid			)
++		__field(	__u16, mode			)
++	),
++
++	TP_fast_assign(
++		__entry->orig_ino = orig_ino;
++		__entry->dev	= inode->i_sb->s_dev;
++		__entry->ino	= inode->i_ino;
++		__entry->uid	= i_uid_read(inode);
++		__entry->gid	= i_gid_read(inode);
++		__entry->mode	= inode->i_mode;
++	),
++
++	TP_printk("dev %d,%d orig_ino %lu ino %lu mode 0%o uid %u gid %u",
++		  MAJOR(__entry->dev), MINOR(__entry->dev),
++		  (unsigned long) __entry->orig_ino,
++		  (unsigned long) __entry->ino, __entry->mode,
++		  __entry->uid, __entry->gid)
++);
++
+ TRACE_EVENT(ext4_free_inode,
+ 	TP_PROTO(struct inode *inode),
+ 

commit fe032c422c5ba562ba9c2d316f55e258e03259c6
+Author: Theodore Ts'o 
+Date:   Mon Feb 2 00:37:01 2015 -0500
+
+    vfs: add find_inode_nowait() function
+    
+    Add a new function find_inode_nowait() which is an even more general
+    version of ilookup5_nowait().  It is designed for callers which need
+    very fine grained control over when the function is allowed to block
+    or increment the inode's reference count.
+    
+    Signed-off-by: Theodore Ts'o 
+    Signed-off-by: Al Viro 
+
+diff --git a/fs/inode.c b/fs/inode.c
+index 4feb85cc125f..740cba79c2b9 100644
+--- a/fs/inode.c
++++ b/fs/inode.c
+@@ -1284,6 +1284,56 @@ struct inode *ilookup(struct super_block *sb, unsigned long ino)
+ }
+ EXPORT_SYMBOL(ilookup);
+ 
++/**
++ * find_inode_nowait - find an inode in the inode cache
++ * @sb:		super block of file system to search
++ * @hashval:	hash value (usually inode number) to search for
++ * @match:	callback used for comparisons between inodes
++ * @data:	opaque data pointer to pass to @match
++ *
++ * Search for the inode specified by @hashval and @data in the inode
++ * cache, where the helper function @match will return 0 if the inode
++ * does not match, 1 if the inode does match, and -1 if the search
++ * should be stopped.  The @match function must be responsible for
++ * taking the i_lock spin_lock and checking i_state for an inode being
++ * freed or being initialized, and incrementing the reference count
++ * before returning 1.  It also must not sleep, since it is called with
++ * the inode_hash_lock spinlock held.
++ *
++ * This is a even more generalized version of ilookup5() when the
++ * function must never block --- find_inode() can block in
++ * __wait_on_freeing_inode() --- or when the caller can not increment
++ * the reference count because the resulting iput() might cause an
++ * inode eviction.  The tradeoff is that the @match funtion must be
++ * very carefully implemented.
++ */
++struct inode *find_inode_nowait(struct super_block *sb,
++				unsigned long hashval,
++				int (*match)(struct inode *, unsigned long,
++					     void *),
++				void *data)
++{
++	struct hlist_head *head = inode_hashtable + hash(sb, hashval);
++	struct inode *inode, *ret_inode = NULL;
++	int mval;
++
++	spin_lock(&inode_hash_lock);
++	hlist_for_each_entry(inode, head, i_hash) {
++		if (inode->i_sb != sb)
++			continue;
++		mval = match(inode, hashval, data);
++		if (mval == 0)
++			continue;
++		if (mval == 1)
++			ret_inode = inode;
++		goto out;
++	}
++out:
++	spin_unlock(&inode_hash_lock);
++	return ret_inode;
++}
++EXPORT_SYMBOL(find_inode_nowait);
++
+ int insert_inode_locked(struct inode *inode)
+ {
+ 	struct super_block *sb = inode->i_sb;
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index cd027ce2c705..5ea8b6e46a3d 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -2441,6 +2441,11 @@ extern struct inode *ilookup(struct super_block *sb, unsigned long ino);
+ 
+ extern struct inode * iget5_locked(struct super_block *, unsigned long, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *);
+ extern struct inode * iget_locked(struct super_block *, unsigned long);
++extern struct inode *find_inode_nowait(struct super_block *,
++				       unsigned long,
++				       int (*match)(struct inode *,
++						    unsigned long, void *),
++				       void *data);
+ extern int insert_inode_locked4(struct inode *, unsigned long, int (*test)(struct inode *, void *), void *);
+ extern int insert_inode_locked(struct inode *);
+ #ifdef CONFIG_DEBUG_LOCK_ALLOC

commit 0ae45f63d4ef8d8eeec49c7d8b44a1775fff13e8
+Author: Theodore Ts'o 
+Date:   Mon Feb 2 00:37:00 2015 -0500
+
+    vfs: add support for a lazytime mount option
+    
+    Add a new mount option which enables a new "lazytime" mode.  This mode
+    causes atime, mtime, and ctime updates to only be made to the
+    in-memory version of the inode.  The on-disk times will only get
+    updated when (a) if the inode needs to be updated for some non-time
+    related change, (b) if userspace calls fsync(), syncfs() or sync(), or
+    (c) just before an undeleted inode is evicted from memory.
+    
+    This is OK according to POSIX because there are no guarantees after a
+    crash unless userspace explicitly requests via a fsync(2) call.
+    
+    For workloads which feature a large number of random write to a
+    preallocated file, the lazytime mount option significantly reduces
+    writes to the inode table.  The repeated 4k writes to a single block
+    will result in undesirable stress on flash devices and SMR disk
+    drives.  Even on conventional HDD's, the repeated writes to the inode
+    table block will trigger Adjacent Track Interference (ATI) remediation
+    latencies, which very negatively impact long tail latencies --- which
+    is a very big deal for web serving tiers (for example).
+    
+    Google-Bug-Id: 18297052
+    
+    Signed-off-by: Theodore Ts'o 
+    Signed-off-by: Al Viro 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 5653fa42930b..628df5ba44a6 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4840,11 +4840,17 @@ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode)
+  * If the inode is marked synchronous, we don't honour that here - doing
+  * so would cause a commit on atime updates, which we don't bother doing.
+  * We handle synchronous inodes at the highest possible level.
++ *
++ * If only the I_DIRTY_TIME flag is set, we can skip everything.  If
++ * I_DIRTY_TIME and I_DIRTY_SYNC is set, the only inode fields we need
++ * to copy into the on-disk inode structure are the timestamp files.
+  */
+ void ext4_dirty_inode(struct inode *inode, int flags)
+ {
+ 	handle_t *handle;
+ 
++	if (flags == I_DIRTY_TIME)
++		return;
+ 	handle = ext4_journal_start(inode, EXT4_HT_INODE, 2);
+ 	if (IS_ERR(handle))
+ 		goto out;
+diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
+index 2d609a5fbfea..004686191354 100644
+--- a/fs/fs-writeback.c
++++ b/fs/fs-writeback.c
+@@ -247,14 +247,19 @@ static bool inode_dirtied_after(struct inode *inode, unsigned long t)
+ 	return ret;
+ }
+ 
++#define EXPIRE_DIRTY_ATIME 0x0001
++
+ /*
+  * Move expired (dirtied before work->older_than_this) dirty inodes from
+  * @delaying_queue to @dispatch_queue.
+  */
+ static int move_expired_inodes(struct list_head *delaying_queue,
+ 			       struct list_head *dispatch_queue,
++			       int flags,
+ 			       struct wb_writeback_work *work)
+ {
++	unsigned long *older_than_this = NULL;
++	unsigned long expire_time;
+ 	LIST_HEAD(tmp);
+ 	struct list_head *pos, *node;
+ 	struct super_block *sb = NULL;
+@@ -262,13 +267,21 @@ static int move_expired_inodes(struct list_head *delaying_queue,
+ 	int do_sb_sort = 0;
+ 	int moved = 0;
+ 
++	if ((flags & EXPIRE_DIRTY_ATIME) == 0)
++		older_than_this = work->older_than_this;
++	else if ((work->reason == WB_REASON_SYNC) == 0) {
++		expire_time = jiffies - (HZ * 86400);
++		older_than_this = &expire_time;
++	}
+ 	while (!list_empty(delaying_queue)) {
+ 		inode = wb_inode(delaying_queue->prev);
+-		if (work->older_than_this &&
+-		    inode_dirtied_after(inode, *work->older_than_this))
++		if (older_than_this &&
++		    inode_dirtied_after(inode, *older_than_this))
+ 			break;
+ 		list_move(&inode->i_wb_list, &tmp);
+ 		moved++;
++		if (flags & EXPIRE_DIRTY_ATIME)
++			set_bit(__I_DIRTY_TIME_EXPIRED, &inode->i_state);
+ 		if (sb_is_blkdev_sb(inode->i_sb))
+ 			continue;
+ 		if (sb && sb != inode->i_sb)
+@@ -309,9 +322,12 @@ static int move_expired_inodes(struct list_head *delaying_queue,
+ static void queue_io(struct bdi_writeback *wb, struct wb_writeback_work *work)
+ {
+ 	int moved;
++
+ 	assert_spin_locked(&wb->list_lock);
+ 	list_splice_init(&wb->b_more_io, &wb->b_io);
+-	moved = move_expired_inodes(&wb->b_dirty, &wb->b_io, work);
++	moved = move_expired_inodes(&wb->b_dirty, &wb->b_io, 0, work);
++	moved += move_expired_inodes(&wb->b_dirty_time, &wb->b_io,
++				     EXPIRE_DIRTY_ATIME, work);
+ 	trace_writeback_queue_io(wb, work, moved);
+ }
+ 
+@@ -435,6 +451,8 @@ static void requeue_inode(struct inode *inode, struct bdi_writeback *wb,
+ 		 * updates after data IO completion.
+ 		 */
+ 		redirty_tail(inode, wb);
++	} else if (inode->i_state & I_DIRTY_TIME) {
++		list_move(&inode->i_wb_list, &wb->b_dirty_time);
+ 	} else {
+ 		/* The inode is clean. Remove from writeback lists. */
+ 		list_del_init(&inode->i_wb_list);
+@@ -481,7 +499,13 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
+ 	spin_lock(&inode->i_lock);
+ 
+ 	dirty = inode->i_state & I_DIRTY;
+-	inode->i_state &= ~I_DIRTY;
++	if (((dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) &&
++	     (inode->i_state & I_DIRTY_TIME)) ||
++	    (inode->i_state & I_DIRTY_TIME_EXPIRED)) {
++		dirty |= I_DIRTY_TIME | I_DIRTY_TIME_EXPIRED;
++		trace_writeback_lazytime(inode);
++	}
++	inode->i_state &= ~dirty;
+ 
+ 	/*
+ 	 * Paired with smp_mb() in __mark_inode_dirty().  This allows
+@@ -501,8 +525,10 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
+ 
+ 	spin_unlock(&inode->i_lock);
+ 
++	if (dirty & I_DIRTY_TIME)
++		mark_inode_dirty_sync(inode);
+ 	/* Don't write the inode if only I_DIRTY_PAGES was set */
+-	if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) {
++	if (dirty & ~I_DIRTY_PAGES) {
+ 		int err = write_inode(inode, wbc);
+ 		if (ret == 0)
+ 			ret = err;
+@@ -550,7 +576,7 @@ writeback_single_inode(struct inode *inode, struct bdi_writeback *wb,
+ 	 * make sure inode is on some writeback list and leave it there unless
+ 	 * we have completely cleaned the inode.
+ 	 */
+-	if (!(inode->i_state & I_DIRTY) &&
++	if (!(inode->i_state & I_DIRTY_ALL) &&
+ 	    (wbc->sync_mode != WB_SYNC_ALL ||
+ 	     !mapping_tagged(inode->i_mapping, PAGECACHE_TAG_WRITEBACK)))
+ 		goto out;
+@@ -565,7 +591,7 @@ writeback_single_inode(struct inode *inode, struct bdi_writeback *wb,
+ 	 * If inode is clean, remove it from writeback lists. Otherwise don't
+ 	 * touch it. See comment above for explanation.
+ 	 */
+-	if (!(inode->i_state & I_DIRTY))
++	if (!(inode->i_state & I_DIRTY_ALL))
+ 		list_del_init(&inode->i_wb_list);
+ 	spin_unlock(&wb->list_lock);
+ 	inode_sync_complete(inode);
+@@ -707,7 +733,7 @@ static long writeback_sb_inodes(struct super_block *sb,
+ 		wrote += write_chunk - wbc.nr_to_write;
+ 		spin_lock(&wb->list_lock);
+ 		spin_lock(&inode->i_lock);
+-		if (!(inode->i_state & I_DIRTY))
++		if (!(inode->i_state & I_DIRTY_ALL))
+ 			wrote++;
+ 		requeue_inode(inode, wb, &wbc);
+ 		inode_sync_complete(inode);
+@@ -1145,16 +1171,20 @@ static noinline void block_dump___mark_inode_dirty(struct inode *inode)
+  * page->mapping->host, so the page-dirtying time is recorded in the internal
+  * blockdev inode.
+  */
++#define I_DIRTY_INODE (I_DIRTY_SYNC | I_DIRTY_DATASYNC)
+ void __mark_inode_dirty(struct inode *inode, int flags)
+ {
+ 	struct super_block *sb = inode->i_sb;
+ 	struct backing_dev_info *bdi = NULL;
++	int dirtytime;
++
++	trace_writeback_mark_inode_dirty(inode, flags);
+ 
+ 	/*
+ 	 * Don't do this for I_DIRTY_PAGES - that doesn't actually
+ 	 * dirty the inode itself
+ 	 */
+-	if (flags & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) {
++	if (flags & (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_TIME)) {
+ 		trace_writeback_dirty_inode_start(inode, flags);
+ 
+ 		if (sb->s_op->dirty_inode)
+@@ -1162,6 +1192,9 @@ void __mark_inode_dirty(struct inode *inode, int flags)
+ 
+ 		trace_writeback_dirty_inode(inode, flags);
+ 	}
++	if (flags & I_DIRTY_INODE)
++		flags &= ~I_DIRTY_TIME;
++	dirtytime = flags & I_DIRTY_TIME;
+ 
+ 	/*
+ 	 * Paired with smp_mb() in __writeback_single_inode() for the
+@@ -1169,16 +1202,21 @@ void __mark_inode_dirty(struct inode *inode, int flags)
+ 	 */
+ 	smp_mb();
+ 
+-	if ((inode->i_state & flags) == flags)
++	if (((inode->i_state & flags) == flags) ||
++	    (dirtytime && (inode->i_state & I_DIRTY_INODE)))
+ 		return;
+ 
+ 	if (unlikely(block_dump))
+ 		block_dump___mark_inode_dirty(inode);
+ 
+ 	spin_lock(&inode->i_lock);
++	if (dirtytime && (inode->i_state & I_DIRTY_INODE))
++		goto out_unlock_inode;
+ 	if ((inode->i_state & flags) != flags) {
+ 		const int was_dirty = inode->i_state & I_DIRTY;
+ 
++		if (flags & I_DIRTY_INODE)
++			inode->i_state &= ~I_DIRTY_TIME;
+ 		inode->i_state |= flags;
+ 
+ 		/*
+@@ -1225,8 +1263,10 @@ void __mark_inode_dirty(struct inode *inode, int flags)
+ 			}
+ 
+ 			inode->dirtied_when = jiffies;
+-			list_move(&inode->i_wb_list, &bdi->wb.b_dirty);
++			list_move(&inode->i_wb_list, dirtytime ?
++				  &bdi->wb.b_dirty_time : &bdi->wb.b_dirty);
+ 			spin_unlock(&bdi->wb.list_lock);
++			trace_writeback_dirty_inode_enqueue(inode);
+ 
+ 			if (wakeup_bdi)
+ 				bdi_wakeup_thread_delayed(bdi);
+diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
+index 6e600abf694a..15c44cf457cc 100644
+--- a/fs/gfs2/file.c
++++ b/fs/gfs2/file.c
+@@ -655,7 +655,7 @@ static int gfs2_fsync(struct file *file, loff_t start, loff_t end,
+ {
+ 	struct address_space *mapping = file->f_mapping;
+ 	struct inode *inode = mapping->host;
+-	int sync_state = inode->i_state & I_DIRTY;
++	int sync_state = inode->i_state & I_DIRTY_ALL;
+ 	struct gfs2_inode *ip = GFS2_I(inode);
+ 	int ret = 0, ret1 = 0;
+ 
+@@ -668,7 +668,7 @@ static int gfs2_fsync(struct file *file, loff_t start, loff_t end,
+ 	if (!gfs2_is_jdata(ip))
+ 		sync_state &= ~I_DIRTY_PAGES;
+ 	if (datasync)
+-		sync_state &= ~I_DIRTY_SYNC;
++		sync_state &= ~(I_DIRTY_SYNC | I_DIRTY_TIME);
+ 
+ 	if (sync_state) {
+ 		ret = sync_inode_metadata(inode, 1);
+diff --git a/fs/inode.c b/fs/inode.c
+index aa149e7262ac..4feb85cc125f 100644
+--- a/fs/inode.c
++++ b/fs/inode.c
+@@ -18,6 +18,7 @@
+ #include  /* for inode_has_buffers */
+ #include 
+ #include 
++#include 
+ #include "internal.h"
+ 
+ /*
+@@ -30,7 +31,7 @@
+  * inode_sb_list_lock protects:
+  *   sb->s_inodes, inode->i_sb_list
+  * bdi->wb.list_lock protects:
+- *   bdi->wb.b_{dirty,io,more_io}, inode->i_wb_list
++ *   bdi->wb.b_{dirty,io,more_io,dirty_time}, inode->i_wb_list
+  * inode_hash_lock protects:
+  *   inode_hashtable, inode->i_hash
+  *
+@@ -416,7 +417,8 @@ static void inode_lru_list_add(struct inode *inode)
+  */
+ void inode_add_lru(struct inode *inode)
+ {
+-	if (!(inode->i_state & (I_DIRTY | I_SYNC | I_FREEING | I_WILL_FREE)) &&
++	if (!(inode->i_state & (I_DIRTY_ALL | I_SYNC |
++				I_FREEING | I_WILL_FREE)) &&
+ 	    !atomic_read(&inode->i_count) && inode->i_sb->s_flags & MS_ACTIVE)
+ 		inode_lru_list_add(inode);
+ }
+@@ -647,7 +649,7 @@ int invalidate_inodes(struct super_block *sb, bool kill_dirty)
+ 			spin_unlock(&inode->i_lock);
+ 			continue;
+ 		}
+-		if (inode->i_state & I_DIRTY && !kill_dirty) {
++		if (inode->i_state & I_DIRTY_ALL && !kill_dirty) {
+ 			spin_unlock(&inode->i_lock);
+ 			busy = 1;
+ 			continue;
+@@ -1432,11 +1434,20 @@ static void iput_final(struct inode *inode)
+  */
+ void iput(struct inode *inode)
+ {
+-	if (inode) {
+-		BUG_ON(inode->i_state & I_CLEAR);
+-
+-		if (atomic_dec_and_lock(&inode->i_count, &inode->i_lock))
+-			iput_final(inode);
++	if (!inode)
++		return;
++	BUG_ON(inode->i_state & I_CLEAR);
++retry:
++	if (atomic_dec_and_lock(&inode->i_count, &inode->i_lock)) {
++		if (inode->i_nlink && (inode->i_state & I_DIRTY_TIME)) {
++			atomic_inc(&inode->i_count);
++			inode->i_state &= ~I_DIRTY_TIME;
++			spin_unlock(&inode->i_lock);
++			trace_writeback_lazytime_iput(inode);
++			mark_inode_dirty_sync(inode);
++			goto retry;
++		}
++		iput_final(inode);
+ 	}
+ }
+ EXPORT_SYMBOL(iput);
+@@ -1495,14 +1506,9 @@ static int relatime_need_update(struct vfsmount *mnt, struct inode *inode,
+ 	return 0;
+ }
+ 
+-/*
+- * This does the actual work of updating an inodes time or version.  Must have
+- * had called mnt_want_write() before calling this.
+- */
+-static int update_time(struct inode *inode, struct timespec *time, int flags)
++int generic_update_time(struct inode *inode, struct timespec *time, int flags)
+ {
+-	if (inode->i_op->update_time)
+-		return inode->i_op->update_time(inode, time, flags);
++	int iflags = I_DIRTY_TIME;
+ 
+ 	if (flags & S_ATIME)
+ 		inode->i_atime = *time;
+@@ -1512,9 +1518,27 @@ static int update_time(struct inode *inode, struct timespec *time, int flags)
+ 		inode->i_ctime = *time;
+ 	if (flags & S_MTIME)
+ 		inode->i_mtime = *time;
+-	mark_inode_dirty_sync(inode);
++
++	if (!(inode->i_sb->s_flags & MS_LAZYTIME) || (flags & S_VERSION))
++		iflags |= I_DIRTY_SYNC;
++	__mark_inode_dirty(inode, iflags);
+ 	return 0;
+ }
++EXPORT_SYMBOL(generic_update_time);
++
++/*
++ * This does the actual work of updating an inodes time or version.  Must have
++ * had called mnt_want_write() before calling this.
++ */
++static int update_time(struct inode *inode, struct timespec *time, int flags)
++{
++	int (*update_time)(struct inode *, struct timespec *, int);
++
++	update_time = inode->i_op->update_time ? inode->i_op->update_time :
++		generic_update_time;
++
++	return update_time(inode, time, flags);
++}
+ 
+ /**
+  *	touch_atime	-	update the access time
+diff --git a/fs/jfs/file.c b/fs/jfs/file.c
+index 33aa0cc1f8b8..10815f8dfd8b 100644
+--- a/fs/jfs/file.c
++++ b/fs/jfs/file.c
+@@ -39,7 +39,7 @@ int jfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
+ 		return rc;
+ 
+ 	mutex_lock(&inode->i_mutex);
+-	if (!(inode->i_state & I_DIRTY) ||
++	if (!(inode->i_state & I_DIRTY_ALL) ||
+ 	    (datasync && !(inode->i_state & I_DIRTY_DATASYNC))) {
+ 		/* Make sure committed changes hit the disk */
+ 		jfs_flush_journal(JFS_SBI(inode->i_sb)->log, 1);
+diff --git a/fs/libfs.c b/fs/libfs.c
+index 005843ce5dbd..b2ffdb045be4 100644
+--- a/fs/libfs.c
++++ b/fs/libfs.c
+@@ -948,7 +948,7 @@ int __generic_file_fsync(struct file *file, loff_t start, loff_t end,
+ 
+ 	mutex_lock(&inode->i_mutex);
+ 	ret = sync_mapping_buffers(inode->i_mapping);
+-	if (!(inode->i_state & I_DIRTY))
++	if (!(inode->i_state & I_DIRTY_ALL))
+ 		goto out;
+ 	if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
+ 		goto out;
+diff --git a/fs/proc_namespace.c b/fs/proc_namespace.c
+index 0f96f71ab32b..8db932da4009 100644
+--- a/fs/proc_namespace.c
++++ b/fs/proc_namespace.c
+@@ -44,6 +44,7 @@ static int show_sb_opts(struct seq_file *m, struct super_block *sb)
+ 		{ MS_SYNCHRONOUS, ",sync" },
+ 		{ MS_DIRSYNC, ",dirsync" },
+ 		{ MS_MANDLOCK, ",mand" },
++		{ MS_LAZYTIME, ",lazytime" },
+ 		{ 0, NULL }
+ 	};
+ 	const struct proc_fs_info *fs_infop;
+diff --git a/fs/sync.c b/fs/sync.c
+index 01d9f18a70b5..fbc98ee62044 100644
+--- a/fs/sync.c
++++ b/fs/sync.c
+@@ -177,8 +177,16 @@ SYSCALL_DEFINE1(syncfs, int, fd)
+  */
+ int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync)
+ {
++	struct inode *inode = file->f_mapping->host;
++
+ 	if (!file->f_op->fsync)
+ 		return -EINVAL;
++	if (!datasync && (inode->i_state & I_DIRTY_TIME)) {
++		spin_lock(&inode->i_lock);
++		inode->i_state &= ~I_DIRTY_TIME;
++		spin_unlock(&inode->i_lock);
++		mark_inode_dirty_sync(inode);
++	}
+ 	return file->f_op->fsync(file, start, end, datasync);
+ }
+ EXPORT_SYMBOL(vfs_fsync_range);
+diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
+index 5da6012b7a14..4cdf7336f64a 100644
+--- a/include/linux/backing-dev.h
++++ b/include/linux/backing-dev.h
+@@ -55,6 +55,7 @@ struct bdi_writeback {
+ 	struct list_head b_dirty;	/* dirty inodes */
+ 	struct list_head b_io;		/* parked for writeback */
+ 	struct list_head b_more_io;	/* parked for more writeback */
++	struct list_head b_dirty_time;	/* time stamps are dirty */
+ 	spinlock_t list_lock;		/* protects the b_* lists */
+ };
+ 
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 42efe13077b6..cd027ce2c705 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -1746,8 +1746,12 @@ struct super_operations {
+ #define __I_DIO_WAKEUP		9
+ #define I_DIO_WAKEUP		(1 << I_DIO_WAKEUP)
+ #define I_LINKABLE		(1 << 10)
++#define I_DIRTY_TIME		(1 << 11)
++#define __I_DIRTY_TIME_EXPIRED	12
++#define I_DIRTY_TIME_EXPIRED	(1 << __I_DIRTY_TIME_EXPIRED)
+ 
+ #define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES)
++#define I_DIRTY_ALL (I_DIRTY | I_DIRTY_TIME)
+ 
+ extern void __mark_inode_dirty(struct inode *, int);
+ static inline void mark_inode_dirty(struct inode *inode)
+@@ -1910,6 +1914,7 @@ extern int current_umask(void);
+ 
+ extern void ihold(struct inode * inode);
+ extern void iput(struct inode *);
++extern int generic_update_time(struct inode *, struct timespec *, int);
+ 
+ static inline struct inode *file_inode(const struct file *f)
+ {
+diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h
+index cee02d65ab3f..5ecb4c234625 100644
+--- a/include/trace/events/writeback.h
++++ b/include/trace/events/writeback.h
+@@ -18,6 +18,8 @@
+ 		{I_FREEING,		"I_FREEING"},		\
+ 		{I_CLEAR,		"I_CLEAR"},		\
+ 		{I_SYNC,		"I_SYNC"},		\
++		{I_DIRTY_TIME,		"I_DIRTY_TIME"},	\
++		{I_DIRTY_TIME_EXPIRED,	"I_DIRTY_TIME_EXPIRED"}, \
+ 		{I_REFERENCED,		"I_REFERENCED"}		\
+ 	)
+ 
+@@ -68,6 +70,7 @@ DECLARE_EVENT_CLASS(writeback_dirty_inode_template,
+ 	TP_STRUCT__entry (
+ 		__array(char, name, 32)
+ 		__field(unsigned long, ino)
++		__field(unsigned long, state)
+ 		__field(unsigned long, flags)
+ 	),
+ 
+@@ -78,16 +81,25 @@ DECLARE_EVENT_CLASS(writeback_dirty_inode_template,
+ 		strncpy(__entry->name,
+ 			bdi->dev ? dev_name(bdi->dev) : "(unknown)", 32);
+ 		__entry->ino		= inode->i_ino;
++		__entry->state		= inode->i_state;
+ 		__entry->flags		= flags;
+ 	),
+ 
+-	TP_printk("bdi %s: ino=%lu flags=%s",
++	TP_printk("bdi %s: ino=%lu state=%s flags=%s",
+ 		__entry->name,
+ 		__entry->ino,
++		show_inode_state(__entry->state),
+ 		show_inode_state(__entry->flags)
+ 	)
+ );
+ 
++DEFINE_EVENT(writeback_dirty_inode_template, writeback_mark_inode_dirty,
++
++	TP_PROTO(struct inode *inode, int flags),
++
++	TP_ARGS(inode, flags)
++);
++
+ DEFINE_EVENT(writeback_dirty_inode_template, writeback_dirty_inode_start,
+ 
+ 	TP_PROTO(struct inode *inode, int flags),
+@@ -598,6 +610,52 @@ DEFINE_EVENT(writeback_single_inode_template, writeback_single_inode,
+ 	TP_ARGS(inode, wbc, nr_to_write)
+ );
+ 
++DECLARE_EVENT_CLASS(writeback_lazytime_template,
++	TP_PROTO(struct inode *inode),
++
++	TP_ARGS(inode),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(unsigned long,	ino			)
++		__field(unsigned long,	state			)
++		__field(	__u16, mode			)
++		__field(unsigned long, dirtied_when		)
++	),
++
++	TP_fast_assign(
++		__entry->dev	= inode->i_sb->s_dev;
++		__entry->ino	= inode->i_ino;
++		__entry->state	= inode->i_state;
++		__entry->mode	= inode->i_mode;
++		__entry->dirtied_when = inode->dirtied_when;
++	),
++
++	TP_printk("dev %d,%d ino %lu dirtied %lu state %s mode 0%o",
++		  MAJOR(__entry->dev), MINOR(__entry->dev),
++		  __entry->ino, __entry->dirtied_when,
++		  show_inode_state(__entry->state), __entry->mode)
++);
++
++DEFINE_EVENT(writeback_lazytime_template, writeback_lazytime,
++	TP_PROTO(struct inode *inode),
++
++	TP_ARGS(inode)
++);
++
++DEFINE_EVENT(writeback_lazytime_template, writeback_lazytime_iput,
++	TP_PROTO(struct inode *inode),
++
++	TP_ARGS(inode)
++);
++
++DEFINE_EVENT(writeback_lazytime_template, writeback_dirty_inode_enqueue,
++
++	TP_PROTO(struct inode *inode),
++
++	TP_ARGS(inode)
++);
++
+ #endif /* _TRACE_WRITEBACK_H */
+ 
+ /* This part must be outside protection */
+diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
+index 3735fa0a6784..9b964a5920af 100644
+--- a/include/uapi/linux/fs.h
++++ b/include/uapi/linux/fs.h
+@@ -90,6 +90,7 @@ struct inodes_stat_t {
+ #define MS_KERNMOUNT	(1<<22) /* this is a kern_mount call */
+ #define MS_I_VERSION	(1<<23) /* Update inode I_version field */
+ #define MS_STRICTATIME	(1<<24) /* Always perform atime updates */
++#define MS_LAZYTIME	(1<<25) /* Update the on-disk [acm]times lazily */
+ 
+ /* These sb flags are internal to the kernel */
+ #define MS_NOSEC	(1<<28)
+@@ -100,7 +101,8 @@ struct inodes_stat_t {
+ /*
+  * Superblock flags that can be altered by MS_REMOUNT
+  */
+-#define MS_RMT_MASK	(MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_I_VERSION)
++#define MS_RMT_MASK	(MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_I_VERSION|\
++			 MS_LAZYTIME)
+ 
+ /*
+  * Old magic mount flag and mask
+diff --git a/mm/backing-dev.c b/mm/backing-dev.c
+index 0ae0df55000b..915feea94c66 100644
+--- a/mm/backing-dev.c
++++ b/mm/backing-dev.c
+@@ -69,10 +69,10 @@ static int bdi_debug_stats_show(struct seq_file *m, void *v)
+ 	unsigned long background_thresh;
+ 	unsigned long dirty_thresh;
+ 	unsigned long bdi_thresh;
+-	unsigned long nr_dirty, nr_io, nr_more_io;
++	unsigned long nr_dirty, nr_io, nr_more_io, nr_dirty_time;
+ 	struct inode *inode;
+ 
+-	nr_dirty = nr_io = nr_more_io = 0;
++	nr_dirty = nr_io = nr_more_io = nr_dirty_time = 0;
+ 	spin_lock(&wb->list_lock);
+ 	list_for_each_entry(inode, &wb->b_dirty, i_wb_list)
+ 		nr_dirty++;
+@@ -80,6 +80,9 @@ static int bdi_debug_stats_show(struct seq_file *m, void *v)
+ 		nr_io++;
+ 	list_for_each_entry(inode, &wb->b_more_io, i_wb_list)
+ 		nr_more_io++;
++	list_for_each_entry(inode, &wb->b_dirty_time, i_wb_list)
++		if (inode->i_state & I_DIRTY_TIME)
++			nr_dirty_time++;
+ 	spin_unlock(&wb->list_lock);
+ 
+ 	global_dirty_limits(&background_thresh, &dirty_thresh);
+@@ -98,6 +101,7 @@ static int bdi_debug_stats_show(struct seq_file *m, void *v)
+ 		   "b_dirty:            %10lu\n"
+ 		   "b_io:               %10lu\n"
+ 		   "b_more_io:          %10lu\n"
++		   "b_dirty_time:       %10lu\n"
+ 		   "bdi_list:           %10u\n"
+ 		   "state:              %10lx\n",
+ 		   (unsigned long) K(bdi_stat(bdi, BDI_WRITEBACK)),
+@@ -111,6 +115,7 @@ static int bdi_debug_stats_show(struct seq_file *m, void *v)
+ 		   nr_dirty,
+ 		   nr_io,
+ 		   nr_more_io,
++		   nr_dirty_time,
+ 		   !list_empty(&bdi->bdi_list), bdi->state);
+ #undef K
+ 
+@@ -418,6 +423,7 @@ static void bdi_wb_init(struct bdi_writeback *wb, struct backing_dev_info *bdi)
+ 	INIT_LIST_HEAD(&wb->b_dirty);
+ 	INIT_LIST_HEAD(&wb->b_io);
+ 	INIT_LIST_HEAD(&wb->b_more_io);
++	INIT_LIST_HEAD(&wb->b_dirty_time);
+ 	spin_lock_init(&wb->list_lock);
+ 	INIT_DELAYED_WORK(&wb->dwork, bdi_writeback_workfn);
+ }

commit 3edc18d84540b94c0eba9226d01a8cbe4c162b55
+Author: Theodore Ts'o 
+Date:   Mon Jan 19 16:00:58 2015 -0500
+
+    ext4: reserve codepoints used by the ext4 encryption feature
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index a75fba67bb1f..b7f393df2e4c 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -364,7 +364,8 @@ struct flex_groups {
+ #define EXT4_DIRTY_FL			0x00000100
+ #define EXT4_COMPRBLK_FL		0x00000200 /* One or more compressed clusters */
+ #define EXT4_NOCOMPR_FL			0x00000400 /* Don't compress */
+-#define EXT4_ECOMPR_FL			0x00000800 /* Compression error */
++	/* nb: was previously EXT2_ECOMPR_FL */
++#define EXT4_ENCRYPT_FL			0x00000800 /* encrypted file */
+ /* End compression flags --- maybe not all used */
+ #define EXT4_INDEX_FL			0x00001000 /* hash-indexed directory */
+ #define EXT4_IMAGIC_FL			0x00002000 /* AFS directory */
+@@ -421,7 +422,7 @@ enum {
+ 	EXT4_INODE_DIRTY	= 8,
+ 	EXT4_INODE_COMPRBLK	= 9,	/* One or more compressed clusters */
+ 	EXT4_INODE_NOCOMPR	= 10,	/* Don't compress */
+-	EXT4_INODE_ECOMPR	= 11,	/* Compression error */
++	EXT4_INODE_ENCRYPT	= 11,	/* Compression error */
+ /* End compression flags --- maybe not all used */
+ 	EXT4_INODE_INDEX	= 12,	/* hash-indexed directory */
+ 	EXT4_INODE_IMAGIC	= 13,	/* AFS directory */
+@@ -466,7 +467,7 @@ static inline void ext4_check_flag_values(void)
+ 	CHECK_FLAG_VALUE(DIRTY);
+ 	CHECK_FLAG_VALUE(COMPRBLK);
+ 	CHECK_FLAG_VALUE(NOCOMPR);
+-	CHECK_FLAG_VALUE(ECOMPR);
++	CHECK_FLAG_VALUE(ENCRYPT);
+ 	CHECK_FLAG_VALUE(INDEX);
+ 	CHECK_FLAG_VALUE(IMAGIC);
+ 	CHECK_FLAG_VALUE(JOURNAL_DATA);
+@@ -1043,6 +1044,12 @@ extern void ext4_set_bits(void *bm, int cur, int len);
+ /* Metadata checksum algorithm codes */
+ #define EXT4_CRC32C_CHKSUM		1
+ 
++/* Encryption algorithms */
++#define EXT4_ENCRYPTION_MODE_INVALID		0
++#define EXT4_ENCRYPTION_MODE_AES_256_XTS	1
++#define EXT4_ENCRYPTION_MODE_AES_256_GCM	2
++#define EXT4_ENCRYPTION_MODE_AES_256_CBC	3
++
+ /*
+  * Structure of the super block
+  */
+@@ -1156,7 +1163,8 @@ struct ext4_super_block {
+ 	__le32	s_grp_quota_inum;	/* inode for tracking group quota */
+ 	__le32	s_overhead_clusters;	/* overhead blocks/clusters in fs */
+ 	__le32	s_backup_bgs[2];	/* groups with sparse_super2 SBs */
+-	__le32	s_reserved[106];	/* Padding to the end of the block */
++	__u8	s_encrypt_algos[4];	/* Encryption algorithms in use  */
++	__le32	s_reserved[105];	/* Padding to the end of the block */
+ 	__le32	s_checksum;		/* crc32c(superblock) */
+ };
+ 
+@@ -1537,6 +1545,7 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei)
+ #define EXT4_FEATURE_INCOMPAT_BG_USE_META_CSUM	0x2000 /* use crc32c for bg */
+ #define EXT4_FEATURE_INCOMPAT_LARGEDIR		0x4000 /* >2GB or 3-lvl htree */
+ #define EXT4_FEATURE_INCOMPAT_INLINE_DATA	0x8000 /* data in inode */
++#define EXT4_FEATURE_INCOMPAT_ENCRYPT		0x10000
+ 
+ #define EXT2_FEATURE_COMPAT_SUPP	EXT4_FEATURE_COMPAT_EXT_ATTR
+ #define EXT2_FEATURE_INCOMPAT_SUPP	(EXT4_FEATURE_INCOMPAT_FILETYPE| \

commit ad7fefb109b0418bb4f16fc1176fd082f986698b
+Author: Theodore Ts'o 
+Date:   Fri Jan 2 15:16:00 2015 -0500
+
+    Revert "ext4: fix suboptimal seek_{data,hole} extents traversial"
+    
+    This reverts commit 14516bb7bb6ffbd49f35389f9ece3b2045ba5815.
+    
+    This was causing regression test failures with generic/285 with an ext3
+    filesystem using CONFIG_EXT4_USE_FOR_EXT23.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index e5d3eadf47b1..bed43081720f 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -5166,8 +5166,8 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ 
+ 	/* fallback to generic here if not in extents fmt */
+ 	if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
+-		return __generic_block_fiemap(inode, fieinfo, start, len,
+-					      ext4_get_block);
++		return generic_block_fiemap(inode, fieinfo, start, len,
++			ext4_get_block);
+ 
+ 	if (fiemap_check_flags(fieinfo, EXT4_FIEMAP_FLAGS))
+ 		return -EBADR;
+diff --git a/fs/ext4/file.c b/fs/ext4/file.c
+index 513c12cf444c..8131be8c0af3 100644
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -273,19 +273,24 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
+  * we determine this extent as a data or a hole according to whether the
+  * page cache has data or not.
+  */
+-static int ext4_find_unwritten_pgoff(struct inode *inode, int whence,
+-				     loff_t endoff, loff_t *offset)
++static int ext4_find_unwritten_pgoff(struct inode *inode,
++				     int whence,
++				     struct ext4_map_blocks *map,
++				     loff_t *offset)
+ {
+ 	struct pagevec pvec;
++	unsigned int blkbits;
+ 	pgoff_t index;
+ 	pgoff_t end;
++	loff_t endoff;
+ 	loff_t startoff;
+ 	loff_t lastoff;
+ 	int found = 0;
+ 
++	blkbits = inode->i_sb->s_blocksize_bits;
+ 	startoff = *offset;
+ 	lastoff = startoff;
+-
++	endoff = (loff_t)(map->m_lblk + map->m_len) << blkbits;
+ 
+ 	index = startoff >> PAGE_CACHE_SHIFT;
+ 	end = endoff >> PAGE_CACHE_SHIFT;
+@@ -403,144 +408,147 @@ static int ext4_find_unwritten_pgoff(struct inode *inode, int whence,
+ static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize)
+ {
+ 	struct inode *inode = file->f_mapping->host;
+-	struct fiemap_extent_info fie;
+-	struct fiemap_extent ext[2];
+-	loff_t next;
+-	int i, ret = 0;
++	struct ext4_map_blocks map;
++	struct extent_status es;
++	ext4_lblk_t start, last, end;
++	loff_t dataoff, isize;
++	int blkbits;
++	int ret = 0;
+ 
+ 	mutex_lock(&inode->i_mutex);
+-	if (offset >= inode->i_size) {
++
++	isize = i_size_read(inode);
++	if (offset >= isize) {
+ 		mutex_unlock(&inode->i_mutex);
+ 		return -ENXIO;
+ 	}
+-	fie.fi_flags = 0;
+-	fie.fi_extents_max = 2;
+-	fie.fi_extents_start = (struct fiemap_extent __user *) &ext;
+-	while (1) {
+-		mm_segment_t old_fs = get_fs();
+-
+-		fie.fi_extents_mapped = 0;
+-		memset(ext, 0, sizeof(*ext) * fie.fi_extents_max);
+-
+-		set_fs(get_ds());
+-		ret = ext4_fiemap(inode, &fie, offset, maxsize - offset);
+-		set_fs(old_fs);
+-		if (ret)
++
++	blkbits = inode->i_sb->s_blocksize_bits;
++	start = offset >> blkbits;
++	last = start;
++	end = isize >> blkbits;
++	dataoff = offset;
++
++	do {
++		map.m_lblk = last;
++		map.m_len = end - last + 1;
++		ret = ext4_map_blocks(NULL, inode, &map, 0);
++		if (ret > 0 && !(map.m_flags & EXT4_MAP_UNWRITTEN)) {
++			if (last != start)
++				dataoff = (loff_t)last << blkbits;
+ 			break;
++		}
+ 
+-		/* No extents found, EOF */
+-		if (!fie.fi_extents_mapped) {
+-			ret = -ENXIO;
++		/*
++		 * If there is a delay extent at this offset,
++		 * it will be as a data.
++		 */
++		ext4_es_find_delayed_extent_range(inode, last, last, &es);
++		if (es.es_len != 0 && in_range(last, es.es_lblk, es.es_len)) {
++			if (last != start)
++				dataoff = (loff_t)last << blkbits;
+ 			break;
+ 		}
+-		for (i = 0; i < fie.fi_extents_mapped; i++) {
+-			next = (loff_t)(ext[i].fe_length + ext[i].fe_logical);
+ 
+-			if (offset < (loff_t)ext[i].fe_logical)
+-				offset = (loff_t)ext[i].fe_logical;
+-			/*
+-			 * If extent is not unwritten, then it contains valid
+-			 * data, mapped or delayed.
+-			 */
+-			if (!(ext[i].fe_flags & FIEMAP_EXTENT_UNWRITTEN))
+-				goto out;
++		/*
++		 * If there is a unwritten extent at this offset,
++		 * it will be as a data or a hole according to page
++		 * cache that has data or not.
++		 */
++		if (map.m_flags & EXT4_MAP_UNWRITTEN) {
++			int unwritten;
++			unwritten = ext4_find_unwritten_pgoff(inode, SEEK_DATA,
++							      &map, &dataoff);
++			if (unwritten)
++				break;
++		}
+ 
+-			/*
+-			 * If there is a unwritten extent at this offset,
+-			 * it will be as a data or a hole according to page
+-			 * cache that has data or not.
+-			 */
+-			if (ext4_find_unwritten_pgoff(inode, SEEK_DATA,
+-						      next, &offset))
+-				goto out;
++		last++;
++		dataoff = (loff_t)last << blkbits;
++	} while (last <= end);
+ 
+-			if (ext[i].fe_flags & FIEMAP_EXTENT_LAST) {
+-				ret = -ENXIO;
+-				goto out;
+-			}
+-			offset = next;
+-		}
+-	}
+-	if (offset > inode->i_size)
+-		offset = inode->i_size;
+-out:
+ 	mutex_unlock(&inode->i_mutex);
+-	if (ret)
+-		return ret;
+ 
+-	return vfs_setpos(file, offset, maxsize);
++	if (dataoff > isize)
++		return -ENXIO;
++
++	return vfs_setpos(file, dataoff, maxsize);
+ }
+ 
+ /*
+- * ext4_seek_hole() retrieves the offset for SEEK_HOLE
++ * ext4_seek_hole() retrieves the offset for SEEK_HOLE.
+  */
+ static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize)
+ {
+ 	struct inode *inode = file->f_mapping->host;
+-	struct fiemap_extent_info fie;
+-	struct fiemap_extent ext[2];
+-	loff_t next;
+-	int i, ret = 0;
++	struct ext4_map_blocks map;
++	struct extent_status es;
++	ext4_lblk_t start, last, end;
++	loff_t holeoff, isize;
++	int blkbits;
++	int ret = 0;
+ 
+ 	mutex_lock(&inode->i_mutex);
+-	if (offset >= inode->i_size) {
++
++	isize = i_size_read(inode);
++	if (offset >= isize) {
+ 		mutex_unlock(&inode->i_mutex);
+ 		return -ENXIO;
+ 	}
+ 
+-	fie.fi_flags = 0;
+-	fie.fi_extents_max = 2;
+-	fie.fi_extents_start = (struct fiemap_extent __user *)&ext;
+-	while (1) {
+-		mm_segment_t old_fs = get_fs();
+-
+-		fie.fi_extents_mapped = 0;
+-		memset(ext, 0, sizeof(*ext));
++	blkbits = inode->i_sb->s_blocksize_bits;
++	start = offset >> blkbits;
++	last = start;
++	end = isize >> blkbits;
++	holeoff = offset;
+ 
+-		set_fs(get_ds());
+-		ret = ext4_fiemap(inode, &fie, offset, maxsize - offset);
+-		set_fs(old_fs);
+-		if (ret)
+-			break;
++	do {
++		map.m_lblk = last;
++		map.m_len = end - last + 1;
++		ret = ext4_map_blocks(NULL, inode, &map, 0);
++		if (ret > 0 && !(map.m_flags & EXT4_MAP_UNWRITTEN)) {
++			last += ret;
++			holeoff = (loff_t)last << blkbits;
++			continue;
++		}
+ 
+-		/* No extents found */
+-		if (!fie.fi_extents_mapped)
+-			break;
++		/*
++		 * If there is a delay extent at this offset,
++		 * we will skip this extent.
++		 */
++		ext4_es_find_delayed_extent_range(inode, last, last, &es);
++		if (es.es_len != 0 && in_range(last, es.es_lblk, es.es_len)) {
++			last = es.es_lblk + es.es_len;
++			holeoff = (loff_t)last << blkbits;
++			continue;
++		}
+ 
+-		for (i = 0; i < fie.fi_extents_mapped; i++) {
+-			next = (loff_t)(ext[i].fe_logical + ext[i].fe_length);
+-			/*
+-			 * If extent is not unwritten, then it contains valid
+-			 * data, mapped or delayed.
+-			 */
+-			if (!(ext[i].fe_flags & FIEMAP_EXTENT_UNWRITTEN)) {
+-				if (offset < (loff_t)ext[i].fe_logical)
+-					goto out;
+-				offset = next;
++		/*
++		 * If there is a unwritten extent at this offset,
++		 * it will be as a data or a hole according to page
++		 * cache that has data or not.
++		 */
++		if (map.m_flags & EXT4_MAP_UNWRITTEN) {
++			int unwritten;
++			unwritten = ext4_find_unwritten_pgoff(inode, SEEK_HOLE,
++							      &map, &holeoff);
++			if (!unwritten) {
++				last += ret;
++				holeoff = (loff_t)last << blkbits;
+ 				continue;
+ 			}
+-			/*
+-			 * If there is a unwritten extent at this offset,
+-			 * it will be as a data or a hole according to page
+-			 * cache that has data or not.
+-			 */
+-			if (ext4_find_unwritten_pgoff(inode, SEEK_HOLE,
+-						      next, &offset))
+-				goto out;
+-
+-			offset = next;
+-			if (ext[i].fe_flags & FIEMAP_EXTENT_LAST)
+-				goto out;
+ 		}
+-	}
+-	if (offset > inode->i_size)
+-		offset = inode->i_size;
+-out:
++
++		/* find a hole */
++		break;
++	} while (last <= end);
++
+ 	mutex_unlock(&inode->i_mutex);
+-	if (ret)
+-		return ret;
+ 
+-	return vfs_setpos(file, offset, maxsize);
++	if (holeoff > isize)
++		holeoff = isize;
++
++	return vfs_setpos(file, holeoff, maxsize);
+ }
+ 
+ /*

commit 011fa99404bea3f5d897c4983f6bd51170e3b18f
+Author: Theodore Ts'o 
+Date:   Fri Dec 26 23:58:21 2014 -0500
+
+    ext4: prevent online resize with backup superblock
+    
+    Prevent BUG or corrupted file systems after the following:
+    
+    mkfs.ext4 /dev/vdc 100M
+    mount -t ext4 -o sb=40961 /dev/vdc /vdc
+    resize2fs /dev/vdc
+    
+    We previously prevented online resizing using the old resize ioctl.
+    Move the code to ext4_resize_begin(), so the check applies for all of
+    the resize ioctl's.
+    
+    Reported-by: Maxim Malkov 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index bf76f405a5f9..8a8ec6293b19 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -23,6 +23,18 @@ int ext4_resize_begin(struct super_block *sb)
+ 	if (!capable(CAP_SYS_RESOURCE))
+ 		return -EPERM;
+ 
++	/*
++	 * If we are not using the primary superblock/GDT copy don't resize,
++         * because the user tools have no way of handling this.  Probably a
++         * bad time to do it anyways.
++         */
++	if (EXT4_SB(sb)->s_sbh->b_blocknr !=
++	    le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block)) {
++		ext4_warning(sb, "won't resize using backup superblock at %llu",
++			(unsigned long long)EXT4_SB(sb)->s_sbh->b_blocknr);
++		return -EPERM;
++	}
++
+ 	/*
+ 	 * We are not allowed to do online-resizing on a filesystem mounted
+ 	 * with error, because it can destroy the filesystem easily.
+@@ -758,18 +770,6 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ 		       "EXT4-fs: ext4_add_new_gdb: adding group block %lu\n",
+ 		       gdb_num);
+ 
+-	/*
+-	 * If we are not using the primary superblock/GDT copy don't resize,
+-         * because the user tools have no way of handling this.  Probably a
+-         * bad time to do it anyways.
+-         */
+-	if (EXT4_SB(sb)->s_sbh->b_blocknr !=
+-	    le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block)) {
+-		ext4_warning(sb, "won't resize using backup superblock at %llu",
+-			(unsigned long long)EXT4_SB(sb)->s_sbh->b_blocknr);
+-		return -EPERM;
+-	}
+-
+ 	gdb_bh = sb_bread(sb, gdblock);
+ 	if (!gdb_bh)
+ 		return -EIO;

commit d9f39d1e44c43fba26becc4145fabf9d767ff1cd
+Author: Theodore Ts'o 
+Date:   Tue Nov 25 20:02:37 2014 -0500
+
+    jbd2: remove unnecessary NULL check before iput()
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index e4dc74713a43..56dde1e85c24 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -1714,8 +1714,7 @@ int jbd2_journal_destroy(journal_t *journal)
+ 
+ 	if (journal->j_proc_entry)
+ 		jbd2_stats_proc_exit(journal);
+-	if (journal->j_inode)
+-		iput(journal->j_inode);
++	iput(journal->j_inode);
+ 	if (journal->j_revoke)
+ 		jbd2_journal_destroy_revoke(journal);
+ 	if (journal->j_chksum_driver)

commit d48458d4a768cece43f80a081a26cf912877da9c
+Author: Theodore Ts'o 
+Date:   Thu Oct 30 10:53:17 2014 -0400
+
+    jbd2: use a better hash function for the revoke table
+    
+    The old hash function didn't work well for 64-bit block numbers, and
+    used undefined (negative) shift right behavior.  Use the generic
+    64-bit hash function instead.
+    
+    Signed-off-by: Theodore Ts'o 
+    Reported-by: Andrey Ryabinin 
+
+diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c
+index d5e95a175c92..c6cbaef2bda1 100644
+--- a/fs/jbd2/revoke.c
++++ b/fs/jbd2/revoke.c
+@@ -92,6 +92,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #endif
+ 
+ static struct kmem_cache *jbd2_revoke_record_cache;
+@@ -130,16 +131,9 @@ static void flush_descriptor(journal_t *, struct buffer_head *, int, int);
+ 
+ /* Utility functions to maintain the revoke table */
+ 
+-/* Borrowed from buffer.c: this is a tried and tested block hash function */
+ static inline int hash(journal_t *journal, unsigned long long block)
+ {
+-	struct jbd2_revoke_table_s *table = journal->j_revoke;
+-	int hash_shift = table->hash_shift;
+-	int hash = (int)block ^ (int)((block >> 31) >> 1);
+-
+-	return ((hash << (hash_shift - 6)) ^
+-		(hash >> 13) ^
+-		(hash << (hash_shift - 12))) & (table->hash_size - 1);
++	return hash_64(block, journal->j_revoke->hash_shift);
+ }
+ 
+ static int insert_revoke_hash(journal_t *journal, unsigned long long blocknr,

commit f4bb2981024fc91b23b4d09a8817c415396dbabb
+Author: Theodore Ts'o 
+Date:   Sun Oct 5 22:56:00 2014 -0400
+
+    ext4: add ext4_iget_normal() which is to be used for dir tree lookups
+    
+    If there is a corrupted file system which has directory entries that
+    point at reserved, metadata inodes, prohibit them from being used by
+    treating them the same way we treat Boot Loader inodes --- that is,
+    mark them to be bad inodes.  This prohibits them from being opened,
+    deleted, or modified via chmod, chown, utimes, etc.
+    
+    In particular, this prevents a corrupted file system which has a
+    directory entry which points at the journal inode from being deleted
+    and its blocks released, after which point Much Hilarity Ensues.
+    
+    Reported-by: Sami Liedes 
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 1eb5b7b912a8..012e89bd9644 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2109,6 +2109,7 @@ int do_journal_get_write_access(handle_t *handle,
+ #define CONVERT_INLINE_DATA	 2
+ 
+ extern struct inode *ext4_iget(struct super_block *, unsigned long);
++extern struct inode *ext4_iget_normal(struct super_block *, unsigned long);
+ extern int  ext4_write_inode(struct inode *, struct writeback_control *);
+ extern int  ext4_setattr(struct dentry *, struct iattr *);
+ extern int  ext4_getattr(struct vfsmount *mnt, struct dentry *dentry,
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 59983b28a93c..e204d8aabe7d 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4104,6 +4104,13 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 	return ERR_PTR(ret);
+ }
+ 
++struct inode *ext4_iget_normal(struct super_block *sb, unsigned long ino)
++{
++	if (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO)
++		return ERR_PTR(-EIO);
++	return ext4_iget(sb, ino);
++}
++
+ static int ext4_inode_blocks_set(handle_t *handle,
+ 				struct ext4_inode *raw_inode,
+ 				struct ext4_inode_info *ei)
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index a2a9d40522d2..7037ecf0fc23 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1417,7 +1417,7 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
+ 					 dentry);
+ 			return ERR_PTR(-EIO);
+ 		}
+-		inode = ext4_iget(dir->i_sb, ino);
++		inode = ext4_iget_normal(dir->i_sb, ino);
+ 		if (inode == ERR_PTR(-ESTALE)) {
+ 			EXT4_ERROR_INODE(dir,
+ 					 "deleted inode referenced: %u",
+@@ -1450,7 +1450,7 @@ struct dentry *ext4_get_parent(struct dentry *child)
+ 		return ERR_PTR(-EIO);
+ 	}
+ 
+-	return d_obtain_alias(ext4_iget(child->d_inode->i_sb, ino));
++	return d_obtain_alias(ext4_iget_normal(child->d_inode->i_sb, ino));
+ }
+ 
+ /*
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 1070d6e521c6..a0811cc00c91 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1001,7 +1001,7 @@ static struct inode *ext4_nfs_get_inode(struct super_block *sb,
+ 	 * Currently we don't know the generation for parent directory, so
+ 	 * a generation of 0 means "accept any"
+ 	 */
+-	inode = ext4_iget(sb, ino);
++	inode = ext4_iget_normal(sb, ino);
+ 	if (IS_ERR(inode))
+ 		return ERR_CAST(inode);
+ 	if (generation && inode->i_generation != generation) {

commit e2bfb088fac03c0f621886a04cffc7faa2b49b1d
+Author: Theodore Ts'o 
+Date:   Sun Oct 5 22:47:07 2014 -0400
+
+    ext4: don't orphan or truncate the boot loader inode
+    
+    The boot loader inode (inode #5) should never be visible in the
+    directory hierarchy, but it's possible if the file system is corrupted
+    that there will be a directory entry that points at inode #5.  In
+    order to avoid accidentally trashing it, when such a directory inode
+    is opened, the inode will be marked as a bad inode, so that it's not
+    possible to modify (or read) the inode from userspace.
+    
+    Unfortunately, when we unlink this (invalid/illegal) directory entry,
+    we will put the bad inode on the ophan list, and then when try to
+    unlink the directory, we don't actually remove the bad inode from the
+    orphan list before freeing in-memory inode structure.  This means the
+    in-memory orphan list is corrupted, leading to a kernel oops.
+    
+    In addition, avoid truncating a bad inode in ext4_destroy_inode(),
+    since truncating the boot loader inode is not a smart thing to do.
+    
+    Reported-by: Sami Liedes 
+    Reviewed-by: Jan Kara 
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 41c4f97c39d3..59983b28a93c 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -224,16 +224,15 @@ void ext4_evict_inode(struct inode *inode)
+ 		goto no_delete;
+ 	}
+ 
+-	if (!is_bad_inode(inode))
+-		dquot_initialize(inode);
++	if (is_bad_inode(inode))
++		goto no_delete;
++	dquot_initialize(inode);
+ 
+ 	if (ext4_should_order_data(inode))
+ 		ext4_begin_ordered_truncate(inode, 0);
+ 	truncate_inode_pages_final(&inode->i_data);
+ 
+ 	WARN_ON(atomic_read(&EXT4_I(inode)->i_ioend_count));
+-	if (is_bad_inode(inode))
+-		goto no_delete;
+ 
+ 	/*
+ 	 * Protect us against freezing - iput() caller didn't have to have any
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 51705f8c4116..a2a9d40522d2 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -2544,7 +2544,7 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode)
+ 	int err = 0, rc;
+ 	bool dirty = false;
+ 
+-	if (!sbi->s_journal)
++	if (!sbi->s_journal || is_bad_inode(inode))
+ 		return 0;
+ 
+ 	WARN_ON_ONCE(!(inode->i_state & (I_NEW | I_FREEING)) &&

commit f6e63f90809946d410c42045577cb159fedabf8c
+Author: Theodore Ts'o 
+Date:   Thu Sep 18 17:12:30 2014 -0400
+
+    ext4: fold ext4_nojournal_sops into ext4_sops
+    
+    There's no longer any need to have a separate set of super_operations
+    for nojournal mode.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 4db537b3a162..1070d6e521c6 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1123,27 +1123,6 @@ static const struct super_operations ext4_sops = {
+ 	.bdev_try_to_free_page = bdev_try_to_free_page,
+ };
+ 
+-static const struct super_operations ext4_nojournal_sops = {
+-	.alloc_inode	= ext4_alloc_inode,
+-	.destroy_inode	= ext4_destroy_inode,
+-	.write_inode	= ext4_write_inode,
+-	.dirty_inode	= ext4_dirty_inode,
+-	.drop_inode	= ext4_drop_inode,
+-	.evict_inode	= ext4_evict_inode,
+-	.sync_fs	= ext4_sync_fs,
+-	.freeze_fs	= ext4_freeze,
+-	.unfreeze_fs	= ext4_unfreeze,
+-	.put_super	= ext4_put_super,
+-	.statfs		= ext4_statfs,
+-	.remount_fs	= ext4_remount,
+-	.show_options	= ext4_show_options,
+-#ifdef CONFIG_QUOTA
+-	.quota_read	= ext4_quota_read,
+-	.quota_write	= ext4_quota_write,
+-#endif
+-	.bdev_try_to_free_page = bdev_try_to_free_page,
+-};
+-
+ static const struct export_operations ext4_export_ops = {
+ 	.fh_to_dentry = ext4_fh_to_dentry,
+ 	.fh_to_parent = ext4_fh_to_parent,
+@@ -3941,11 +3920,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	/*
+ 	 * set up enough so that it can read an inode
+ 	 */
+-	if (!test_opt(sb, NOLOAD) &&
+-	    EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL))
+-		sb->s_op = &ext4_sops;
+-	else
+-		sb->s_op = &ext4_nojournal_sops;
++	sb->s_op = &ext4_sops;
+ 	sb->s_export_op = &ext4_export_ops;
+ 	sb->s_xattr = ext4_xattr_handlers;
+ #ifdef CONFIG_QUOTA

commit bb0445765866e5b1607af81e2f48ca5a8efbeed8
+Author: Theodore Ts'o 
+Date:   Thu Sep 18 17:12:02 2014 -0400
+
+    ext4: support freezing ext2 (nojournal) file systems
+    
+    Through an oversight, when we added nojournal support to ext4, we
+    didn't add support to allow file system freezing.  This is relatively
+    easy to add, so let's do it.
+    
+    Signed-off-by: Theodore Ts'o 
+    Reported-by: Dexuan Cui 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 4770c98bdb61..4db537b3a162 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1131,6 +1131,8 @@ static const struct super_operations ext4_nojournal_sops = {
+ 	.drop_inode	= ext4_drop_inode,
+ 	.evict_inode	= ext4_evict_inode,
+ 	.sync_fs	= ext4_sync_fs,
++	.freeze_fs	= ext4_freeze,
++	.unfreeze_fs	= ext4_unfreeze,
+ 	.put_super	= ext4_put_super,
+ 	.statfs		= ext4_statfs,
+ 	.remount_fs	= ext4_remount,
+@@ -4758,23 +4760,26 @@ static int ext4_freeze(struct super_block *sb)
+ 
+ 	journal = EXT4_SB(sb)->s_journal;
+ 
+-	/* Now we set up the journal barrier. */
+-	jbd2_journal_lock_updates(journal);
++	if (journal) {
++		/* Now we set up the journal barrier. */
++		jbd2_journal_lock_updates(journal);
+ 
+-	/*
+-	 * Don't clear the needs_recovery flag if we failed to flush
+-	 * the journal.
+-	 */
+-	error = jbd2_journal_flush(journal);
+-	if (error < 0)
+-		goto out;
++		/*
++		 * Don't clear the needs_recovery flag if we failed to
++		 * flush the journal.
++		 */
++		error = jbd2_journal_flush(journal);
++		if (error < 0)
++			goto out;
++	}
+ 
+ 	/* Journal blocked and flushed, clear needs_recovery flag. */
+ 	EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+ 	error = ext4_commit_super(sb, 1);
+ out:
+-	/* we rely on upper layer to stop further updates */
+-	jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
++	if (journal)
++		/* we rely on upper layer to stop further updates */
++		jbd2_journal_unlock_updates(journal);
+ 	return error;
+ }
+ 

commit bda3253043c54a705c8352096194ab6216e2e5c1
+Author: Theodore Ts'o 
+Date:   Thu Sep 18 16:12:37 2014 -0400
+
+    ext4: fold ext4_sync_fs_nojournal() into ext4_sync_fs()
+    
+    This allows us to eliminate duplicate code, and eventually allow us to
+    also fold ext4_sops and ext4_nojournal_sops together.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 115e27d855ef..4770c98bdb61 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -70,7 +70,6 @@ static void ext4_mark_recovery_complete(struct super_block *sb,
+ static void ext4_clear_journal_err(struct super_block *sb,
+ 				   struct ext4_super_block *es);
+ static int ext4_sync_fs(struct super_block *sb, int wait);
+-static int ext4_sync_fs_nojournal(struct super_block *sb, int wait);
+ static int ext4_remount(struct super_block *sb, int *flags, char *data);
+ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf);
+ static int ext4_unfreeze(struct super_block *sb);
+@@ -1131,7 +1130,7 @@ static const struct super_operations ext4_nojournal_sops = {
+ 	.dirty_inode	= ext4_dirty_inode,
+ 	.drop_inode	= ext4_drop_inode,
+ 	.evict_inode	= ext4_evict_inode,
+-	.sync_fs	= ext4_sync_fs_nojournal,
++	.sync_fs	= ext4_sync_fs,
+ 	.put_super	= ext4_put_super,
+ 	.statfs		= ext4_statfs,
+ 	.remount_fs	= ext4_remount,
+@@ -4718,15 +4717,19 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
+ 	 * being sent at the end of the function. But we can skip it if
+ 	 * transaction_commit will do it for us.
+ 	 */
+-	target = jbd2_get_latest_transaction(sbi->s_journal);
+-	if (wait && sbi->s_journal->j_flags & JBD2_BARRIER &&
+-	    !jbd2_trans_will_send_data_barrier(sbi->s_journal, target))
++	if (sbi->s_journal) {
++		target = jbd2_get_latest_transaction(sbi->s_journal);
++		if (wait && sbi->s_journal->j_flags & JBD2_BARRIER &&
++		    !jbd2_trans_will_send_data_barrier(sbi->s_journal, target))
++			needs_barrier = true;
++
++		if (jbd2_journal_start_commit(sbi->s_journal, &target)) {
++			if (wait)
++				ret = jbd2_log_wait_commit(sbi->s_journal,
++							   target);
++		}
++	} else if (wait && test_opt(sb, BARRIER))
+ 		needs_barrier = true;
+-
+-	if (jbd2_journal_start_commit(sbi->s_journal, &target)) {
+-		if (wait)
+-			ret = jbd2_log_wait_commit(sbi->s_journal, target);
+-	}
+ 	if (needs_barrier) {
+ 		int err;
+ 		err = blkdev_issue_flush(sb->s_bdev, GFP_KERNEL, NULL);
+@@ -4737,19 +4740,6 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
+ 	return ret;
+ }
+ 
+-static int ext4_sync_fs_nojournal(struct super_block *sb, int wait)
+-{
+-	int ret = 0;
+-
+-	trace_ext4_sync_fs(sb, wait);
+-	flush_workqueue(EXT4_SB(sb)->rsv_conversion_wq);
+-	dquot_writeback_dquots(sb, -1);
+-	if (wait && test_opt(sb, BARRIER))
+-		ret = blkdev_issue_flush(sb->s_bdev, GFP_KERNEL, NULL);
+-
+-	return ret;
+-}
+-
+ /*
+  * LVM calls this function before a (read-only) snapshot is created.  This
+  * gives us a chance to flush the journal completely and mark the fs clean.

commit d26e2c4d72c2f2a38246f618480864fe3224929c
+Author: Theodore Ts'o 
+Date:   Thu Sep 4 18:09:29 2014 -0400
+
+    ext4: renumber EXT4_EX_* flags to avoid flag aliasing problems
+    
+    Suggested-by: Andreas Dilger 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 4855800fcc5d..f70c3fc94296 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -569,7 +569,6 @@ enum {
+ #define EXT4_GET_BLOCKS_NO_PUT_HOLE		0x0200
+ 	/* Convert written extents to unwritten */
+ #define EXT4_GET_BLOCKS_CONVERT_UNWRITTEN	0x0400
+-/* DO NOT ASSIGN ADDITIONAL FLAG VALUES WITHOUT ADJUSTING THE FLAGS BELOW */
+ 
+ /*
+  * The bit position of these flags must not overlap with any of the
+@@ -580,8 +579,8 @@ enum {
+  * caching the extents when reading from the extent tree while a
+  * truncate or punch hole operation is in progress.
+  */
+-#define EXT4_EX_NOCACHE				0x0800
+-#define EXT4_EX_FORCE_CACHE			0x1000
++#define EXT4_EX_NOCACHE				0x40000000
++#define EXT4_EX_FORCE_CACHE			0x20000000
+ 
+ /*
+  * Flags used by ext4_free_blocks

commit dc6e8d669cf5cb3ff84707c372c0a2a8a5e80845
+Author: Theodore Ts'o 
+Date:   Thu Sep 4 18:09:22 2014 -0400
+
+    jbd2: don't call get_bh() before calling __jbd2_journal_remove_checkpoint()
+    
+    The __jbd2_journal_remove_checkpoint() doesn't require an elevated
+    b_count; indeed, until the jh structure gets released by the call to
+    jbd2_journal_put_journal_head(), the bh's b_count is elevated by
+    virtue of the existence of the jh structure.
+    
+    Suggested-by: Jan Kara 
+    Reviewed-by: Jan Kara 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
+index 18c7a8d3da13..90d6091d7e18 100644
+--- a/fs/jbd2/checkpoint.c
++++ b/fs/jbd2/checkpoint.c
+@@ -96,15 +96,8 @@ static int __try_to_free_cp_buf(struct journal_head *jh)
+ 
+ 	if (jh->b_transaction == NULL && !buffer_locked(bh) &&
+ 	    !buffer_dirty(bh) && !buffer_write_io_error(bh)) {
+-		/*
+-		 * Get our reference so that bh cannot be freed before
+-		 * we unlock it
+-		 */
+-		get_bh(bh);
+ 		JBUFFER_TRACE(jh, "remove from checkpoint list");
+ 		ret = __jbd2_journal_remove_checkpoint(jh) + 1;
+-		BUFFER_TRACE(bh, "release");
+-		__brelse(bh);
+ 	}
+ 	return ret;
+ }
+@@ -216,7 +209,7 @@ int jbd2_log_do_checkpoint(journal_t *journal)
+ 	struct buffer_head	*bh;
+ 	transaction_t		*transaction;
+ 	tid_t			this_tid;
+-	int			result, batch_count = 0, done = 0;
++	int			result, batch_count = 0;
+ 
+ 	jbd_debug(1, "Start checkpoint\n");
+ 
+@@ -291,11 +284,9 @@ int jbd2_log_do_checkpoint(journal_t *journal)
+ 		if (!buffer_dirty(bh)) {
+ 			if (unlikely(buffer_write_io_error(bh)) && !result)
+ 				result = -EIO;
+-			get_bh(bh);
+ 			BUFFER_TRACE(bh, "remove from checkpoint");
+ 			__jbd2_journal_remove_checkpoint(jh);
+ 			spin_unlock(&journal->j_list_lock);
+-			__brelse(bh);
+ 			goto retry;
+ 		}
+ 		/*
+@@ -338,12 +329,12 @@ int jbd2_log_do_checkpoint(journal_t *journal)
+ 	    transaction->t_tid != this_tid)
+ 		goto out;
+ 
+-	while (!done && transaction->t_checkpoint_io_list) {
++	while (transaction->t_checkpoint_io_list) {
+ 		jh = transaction->t_checkpoint_io_list;
+ 		bh = jh2bh(jh);
+-		get_bh(bh);
+ 		if (buffer_locked(bh)) {
+ 			spin_unlock(&journal->j_list_lock);
++			get_bh(bh);
+ 			wait_on_buffer(bh);
+ 			/* the journal_head may have gone by now */
+ 			BUFFER_TRACE(bh, "brelse");
+@@ -359,8 +350,8 @@ int jbd2_log_do_checkpoint(journal_t *journal)
+ 		 * know that it has been written out and so we can
+ 		 * drop it from the list
+ 		 */
+-		done = __jbd2_journal_remove_checkpoint(jh);
+-		__brelse(bh);
++		if (__jbd2_journal_remove_checkpoint(jh))
++			break;
+ 	}
+ out:
+ 	spin_unlock(&journal->j_list_lock);

commit 754cfed6bbcfdea6afb14f2686f7f8d71e94d4e2
+Author: Theodore Ts'o 
+Date:   Thu Sep 4 18:08:22 2014 -0400
+
+    ext4: drop the EXT4_STATE_DELALLOC_RESERVED flag
+    
+    Having done a full regression test, we can now drop the
+    DELALLOC_RESERVED state flag.
+    
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 00fd822ac6e4..4855800fcc5d 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1400,7 +1400,6 @@ enum {
+ 	EXT4_STATE_EXT_MIGRATE,		/* Inode is migrating */
+ 	EXT4_STATE_DIO_UNWRITTEN,	/* need convert on dio done*/
+ 	EXT4_STATE_NEWENTRY,		/* File just added to dir */
+-	EXT4_STATE_DELALLOC_RESERVED,	/* blks already reserved for delalloc */
+ 	EXT4_STATE_DIOREAD_LOCK,	/* Disable support for dio read
+ 					   nolocking */
+ 	EXT4_STATE_MAY_INLINE_DATA,	/* may have in-inode data */
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 4a16b0cc02de..d5dd7d46844e 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -595,14 +595,6 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
+ 	 */
+ 	down_write(&EXT4_I(inode)->i_data_sem);
+ 
+-	/*
+-	 * if the caller is from delayed allocation writeout path
+-	 * we have already reserved fs blocks for allocation
+-	 * let the underlying get_block() function know to
+-	 * avoid double accounting
+-	 */
+-	if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
+-		ext4_set_inode_state(inode, EXT4_STATE_DELALLOC_RESERVED);
+ 	/*
+ 	 * We need to check for EXT4 here because migrate
+ 	 * could have changed the inode type in between
+@@ -631,8 +623,6 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
+ 			(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE))
+ 			ext4_da_update_reserve_space(inode, retval, 1);
+ 	}
+-	if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
+-		ext4_clear_inode_state(inode, EXT4_STATE_DELALLOC_RESERVED);
+ 
+ 	if (retval > 0) {
+ 		unsigned int status;
+@@ -2004,12 +1994,10 @@ static int mpage_map_one_extent(handle_t *handle, struct mpage_da_data *mpd)
+ 	 * in data loss.  So use reserved blocks to allocate metadata if
+ 	 * possible.
+ 	 *
+-	 * We pass in the magic EXT4_GET_BLOCKS_DELALLOC_RESERVE if the blocks
+-	 * in question are delalloc blocks.  This affects functions in many
+-	 * different parts of the allocation call path.  This flag exists
+-	 * primarily because we don't want to change *many* call functions, so
+-	 * ext4_map_blocks() will set the EXT4_STATE_DELALLOC_RESERVED flag
+-	 * once the inode's allocation semaphore is taken.
++	 * We pass in the magic EXT4_GET_BLOCKS_DELALLOC_RESERVE if
++	 * the blocks in question are delalloc blocks.  This indicates
++	 * that the blocks and quotas has already been checked when
++	 * the data was copied into the page cache.
+ 	 */
+ 	get_blocks_flags = EXT4_GET_BLOCKS_CREATE |
+ 			   EXT4_GET_BLOCKS_METADATA_NOFAIL;
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 15dffdac5907..65cca2881d71 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -4410,16 +4410,6 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
+ 	if (IS_NOQUOTA(ar->inode))
+ 		ar->flags |= EXT4_MB_USE_ROOT_BLOCKS;
+ 
+-	/*
+-	 * For delayed allocation, we could skip the ENOSPC and
+-	 * EDQUOT check, as blocks and quotas have been already
+-	 * reserved when data being copied into pagecache.
+-	 */
+-	if (ext4_test_inode_state(ar->inode, EXT4_STATE_DELALLOC_RESERVED)) {
+-		WARN_ON((ar->flags & EXT4_MB_DELALLOC_RESERVED) == 0);
+-		ar->flags |= EXT4_MB_DELALLOC_RESERVED;
+-	}
+-
+ 	if ((ar->flags & EXT4_MB_DELALLOC_RESERVED) == 0) {
+ 		/* Without delayed allocation we need to verify
+ 		 * there is enough free blocks to do block allocation

commit e3cf5d5d9a86df1c5e413bdd3725c25a16ff854c
+Author: Theodore Ts'o 
+Date:   Thu Sep 4 18:07:25 2014 -0400
+
+    ext4: prepare to drop EXT4_STATE_DELALLOC_RESERVED
+    
+    The EXT4_STATE_DELALLOC_RESERVED flag was originally implemented
+    because it was too hard to make sure the mballoc and get_block flags
+    could be reliably passed down through all of the codepaths that end up
+    calling ext4_mb_new_blocks().
+    
+    Since then, we have mb_flags passed down through most of the code
+    paths, so getting rid of EXT4_STATE_DELALLOC_RESERVED isn't as tricky
+    as it used to.
+    
+    This commit plumbs in the last of what is required, and then adds a
+    WARN_ON check to make sure we haven't missed anything.  If this passes
+    a full regression test run, we can then drop
+    EXT4_STATE_DELALLOC_RESERVED.
+    
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 581ef40fbe90..d70f154f6da3 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -636,8 +636,7 @@ ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
+ 	 * Account for the allocated meta blocks.  We will never
+ 	 * fail EDQUOT for metdata, but we do account for it.
+ 	 */
+-	if (!(*errp) &&
+-	    ext4_test_inode_state(inode, EXT4_STATE_DELALLOC_RESERVED)) {
++	if (!(*errp) && (flags & EXT4_MB_DELALLOC_RESERVED)) {
+ 		spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
+ 		spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+ 		dquot_alloc_block_nofail(inode,
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 3ac1686efff8..8170b3254767 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -1933,6 +1933,8 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+ 	ext4_lblk_t next;
+ 	int mb_flags = 0, unwritten;
+ 
++	if (gb_flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
++		mb_flags |= EXT4_MB_DELALLOC_RESERVED;
+ 	if (unlikely(ext4_ext_get_actual_len(newext) == 0)) {
+ 		EXT4_ERROR_INODE(inode, "ext4_ext_get_actual_len(newext) == 0");
+ 		return -EIO;
+@@ -2054,7 +2056,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+ 	 * We're gonna add a new leaf in the tree.
+ 	 */
+ 	if (gb_flags & EXT4_GET_BLOCKS_METADATA_NOFAIL)
+-		mb_flags = EXT4_MB_USE_RESERVED;
++		mb_flags |= EXT4_MB_USE_RESERVED;
+ 	err = ext4_ext_create_new_leaf(handle, inode, mb_flags, gb_flags,
+ 				       ppath, newext);
+ 	if (err)
+@@ -4438,6 +4440,8 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 		ar.flags = 0;
+ 	if (flags & EXT4_GET_BLOCKS_NO_NORMALIZE)
+ 		ar.flags |= EXT4_MB_HINT_NOPREALLOC;
++	if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
++		ar.flags |= EXT4_MB_DELALLOC_RESERVED;
+ 	newblock = ext4_mb_new_blocks(handle, &ar, &err);
+ 	if (!newblock)
+ 		goto out2;
+diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
+index 69af0cd64724..36b369697a13 100644
+--- a/fs/ext4/indirect.c
++++ b/fs/ext4/indirect.c
+@@ -333,7 +333,9 @@ static int ext4_alloc_branch(handle_t *handle,
+ 			new_blocks[i] = ext4_mb_new_blocks(handle, ar, &err);
+ 		} else
+ 			ar->goal = new_blocks[i] = ext4_new_meta_blocks(handle,
+-				    ar->inode, ar->goal, 0, NULL, &err);
++					ar->inode, ar->goal,
++					ar->flags & EXT4_MB_DELALLOC_RESERVED,
++					NULL, &err);
+ 		if (err) {
+ 			i--;
+ 			goto failed;
+@@ -572,6 +574,8 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
+ 	ar.logical = map->m_lblk;
+ 	if (S_ISREG(inode->i_mode))
+ 		ar.flags = EXT4_MB_HINT_DATA;
++	if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
++		ar.flags |= EXT4_MB_DELALLOC_RESERVED;
+ 
+ 	ar.goal = ext4_find_goal(inode, map->m_lblk, partial);
+ 
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 8b0f9ef517d6..15dffdac5907 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -4415,9 +4415,12 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
+ 	 * EDQUOT check, as blocks and quotas have been already
+ 	 * reserved when data being copied into pagecache.
+ 	 */
+-	if (ext4_test_inode_state(ar->inode, EXT4_STATE_DELALLOC_RESERVED))
++	if (ext4_test_inode_state(ar->inode, EXT4_STATE_DELALLOC_RESERVED)) {
++		WARN_ON((ar->flags & EXT4_MB_DELALLOC_RESERVED) == 0);
+ 		ar->flags |= EXT4_MB_DELALLOC_RESERVED;
+-	else {
++	}
++
++	if ((ar->flags & EXT4_MB_DELALLOC_RESERVED) == 0) {
+ 		/* Without delayed allocation we need to verify
+ 		 * there is enough free blocks to do block allocation
+ 		 * and verify allocation doesn't exceed the quota limits.
+@@ -4528,8 +4531,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
+ 	if (inquota && ar->len < inquota)
+ 		dquot_free_block(ar->inode, EXT4_C2B(sbi, inquota - ar->len));
+ 	if (!ar->len) {
+-		if (!ext4_test_inode_state(ar->inode,
+-					   EXT4_STATE_DELALLOC_RESERVED))
++		if ((ar->flags & EXT4_MB_DELALLOC_RESERVED) == 0)
+ 			/* release all the reserved blocks if non delalloc */
+ 			percpu_counter_sub(&sbi->s_dirtyclusters_counter,
+ 						reserv_clstrs);
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index e7387337060c..da4df703c211 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -899,14 +899,8 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
+ 			if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
+ 				goal = goal & EXT4_MAX_BLOCK_FILE_PHYS;
+ 
+-			/*
+-			 * take i_data_sem because we will test
+-			 * i_delalloc_reserved_flag in ext4_mb_new_blocks
+-			 */
+-			down_read(&EXT4_I(inode)->i_data_sem);
+ 			block = ext4_new_meta_blocks(handle, inode, goal, 0,
+ 						     NULL, &error);
+-			up_read((&EXT4_I(inode)->i_data_sem));
+ 			if (error)
+ 				goto cleanup;
+ 

commit a521100231f816f8cdd9c8e77da14ff1e42c2b17
+Author: Theodore Ts'o 
+Date:   Thu Sep 4 18:06:25 2014 -0400
+
+    ext4: pass allocation_request struct to ext4_(alloc,splice)_branch
+    
+    Instead of initializing the allocation_request structure in
+    ext4_alloc_branch(), set it up in ext4_ind_map_blocks(), and then pass
+    it to ext4_alloc_branch() and ext4_splice_branch().
+    
+    This allows ext4_ind_map_blocks to pass flags in the allocation
+    request structure without having to add Yet Another argument to
+    ext4_alloc_branch().
+    
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
+index e75f840000a0..69af0cd64724 100644
+--- a/fs/ext4/indirect.c
++++ b/fs/ext4/indirect.c
+@@ -318,34 +318,22 @@ static int ext4_blks_to_allocate(Indirect *branch, int k, unsigned int blks,
+  *	ext4_alloc_block() (normally -ENOSPC). Otherwise we set the chain
+  *	as described above and return 0.
+  */
+-static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
+-			     ext4_lblk_t iblock, int indirect_blks,
+-			     int *blks, ext4_fsblk_t goal,
+-			     ext4_lblk_t *offsets, Indirect *branch)
++static int ext4_alloc_branch(handle_t *handle,
++			     struct ext4_allocation_request *ar,
++			     int indirect_blks, ext4_lblk_t *offsets,
++			     Indirect *branch)
+ {
+-	struct ext4_allocation_request	ar;
+ 	struct buffer_head *		bh;
+ 	ext4_fsblk_t			b, new_blocks[4];
+ 	__le32				*p;
+ 	int				i, j, err, len = 1;
+ 
+-	/*
+-	 * Set up for the direct block allocation
+-	 */
+-	memset(&ar, 0, sizeof(ar));
+-	ar.inode = inode;
+-	ar.len = *blks;
+-	ar.logical = iblock;
+-	if (S_ISREG(inode->i_mode))
+-		ar.flags = EXT4_MB_HINT_DATA;
+-
+ 	for (i = 0; i <= indirect_blks; i++) {
+ 		if (i == indirect_blks) {
+-			ar.goal = goal;
+-			new_blocks[i] = ext4_mb_new_blocks(handle, &ar, &err);
++			new_blocks[i] = ext4_mb_new_blocks(handle, ar, &err);
+ 		} else
+-			goal = new_blocks[i] = ext4_new_meta_blocks(handle, inode,
+-							goal, 0, NULL, &err);
++			ar->goal = new_blocks[i] = ext4_new_meta_blocks(handle,
++				    ar->inode, ar->goal, 0, NULL, &err);
+ 		if (err) {
+ 			i--;
+ 			goto failed;
+@@ -354,7 +342,7 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
+ 		if (i == 0)
+ 			continue;
+ 
+-		bh = branch[i].bh = sb_getblk(inode->i_sb, new_blocks[i-1]);
++		bh = branch[i].bh = sb_getblk(ar->inode->i_sb, new_blocks[i-1]);
+ 		if (unlikely(!bh)) {
+ 			err = -ENOMEM;
+ 			goto failed;
+@@ -372,7 +360,7 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
+ 		b = new_blocks[i];
+ 
+ 		if (i == indirect_blks)
+-			len = ar.len;
++			len = ar->len;
+ 		for (j = 0; j < len; j++)
+ 			*p++ = cpu_to_le32(b++);
+ 
+@@ -381,11 +369,10 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
+ 		unlock_buffer(bh);
+ 
+ 		BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
+-		err = ext4_handle_dirty_metadata(handle, inode, bh);
++		err = ext4_handle_dirty_metadata(handle, ar->inode, bh);
+ 		if (err)
+ 			goto failed;
+ 	}
+-	*blks = ar.len;
+ 	return 0;
+ failed:
+ 	for (; i >= 0; i--) {
+@@ -396,10 +383,10 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
+ 		 * existing before ext4_alloc_branch() was called.
+ 		 */
+ 		if (i > 0 && i != indirect_blks && branch[i].bh)
+-			ext4_forget(handle, 1, inode, branch[i].bh,
++			ext4_forget(handle, 1, ar->inode, branch[i].bh,
+ 				    branch[i].bh->b_blocknr);
+-		ext4_free_blocks(handle, inode, NULL, new_blocks[i],
+-				 (i == indirect_blks) ? ar.len : 1, 0);
++		ext4_free_blocks(handle, ar->inode, NULL, new_blocks[i],
++				 (i == indirect_blks) ? ar->len : 1, 0);
+ 	}
+ 	return err;
+ }
+@@ -419,9 +406,9 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
+  * inode (->i_blocks, etc.). In case of success we end up with the full
+  * chain to new block and return 0.
+  */
+-static int ext4_splice_branch(handle_t *handle, struct inode *inode,
+-			      ext4_lblk_t block, Indirect *where, int num,
+-			      int blks)
++static int ext4_splice_branch(handle_t *handle,
++			      struct ext4_allocation_request *ar,
++			      Indirect *where, int num)
+ {
+ 	int i;
+ 	int err = 0;
+@@ -446,9 +433,9 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
+ 	 * Update the host buffer_head or inode to point to more just allocated
+ 	 * direct blocks blocks
+ 	 */
+-	if (num == 0 && blks > 1) {
++	if (num == 0 && ar->len > 1) {
+ 		current_block = le32_to_cpu(where->key) + 1;
+-		for (i = 1; i < blks; i++)
++		for (i = 1; i < ar->len; i++)
+ 			*(where->p + i) = cpu_to_le32(current_block++);
+ 	}
+ 
+@@ -465,14 +452,14 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
+ 		 */
+ 		jbd_debug(5, "splicing indirect only\n");
+ 		BUFFER_TRACE(where->bh, "call ext4_handle_dirty_metadata");
+-		err = ext4_handle_dirty_metadata(handle, inode, where->bh);
++		err = ext4_handle_dirty_metadata(handle, ar->inode, where->bh);
+ 		if (err)
+ 			goto err_out;
+ 	} else {
+ 		/*
+ 		 * OK, we spliced it into the inode itself on a direct block.
+ 		 */
+-		ext4_mark_inode_dirty(handle, inode);
++		ext4_mark_inode_dirty(handle, ar->inode);
+ 		jbd_debug(5, "splicing direct\n");
+ 	}
+ 	return err;
+@@ -484,11 +471,11 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
+ 		 * need to revoke the block, which is why we don't
+ 		 * need to set EXT4_FREE_BLOCKS_METADATA.
+ 		 */
+-		ext4_free_blocks(handle, inode, where[i].bh, 0, 1,
++		ext4_free_blocks(handle, ar->inode, where[i].bh, 0, 1,
+ 				 EXT4_FREE_BLOCKS_FORGET);
+ 	}
+-	ext4_free_blocks(handle, inode, NULL, le32_to_cpu(where[num].key),
+-			 blks, 0);
++	ext4_free_blocks(handle, ar->inode, NULL, le32_to_cpu(where[num].key),
++			 ar->len, 0);
+ 
+ 	return err;
+ }
+@@ -525,11 +512,11 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
+ 			struct ext4_map_blocks *map,
+ 			int flags)
+ {
++	struct ext4_allocation_request ar;
+ 	int err = -EIO;
+ 	ext4_lblk_t offsets[4];
+ 	Indirect chain[4];
+ 	Indirect *partial;
+-	ext4_fsblk_t goal;
+ 	int indirect_blks;
+ 	int blocks_to_boundary = 0;
+ 	int depth;
+@@ -579,7 +566,14 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
+ 		return -ENOSPC;
+ 	}
+ 
+-	goal = ext4_find_goal(inode, map->m_lblk, partial);
++	/* Set up for the direct block allocation */
++	memset(&ar, 0, sizeof(ar));
++	ar.inode = inode;
++	ar.logical = map->m_lblk;
++	if (S_ISREG(inode->i_mode))
++		ar.flags = EXT4_MB_HINT_DATA;
++
++	ar.goal = ext4_find_goal(inode, map->m_lblk, partial);
+ 
+ 	/* the number of blocks need to allocate for [d,t]indirect blocks */
+ 	indirect_blks = (chain + depth) - partial - 1;
+@@ -588,13 +582,13 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
+ 	 * Next look up the indirect map to count the totoal number of
+ 	 * direct blocks to allocate for this branch.
+ 	 */
+-	count = ext4_blks_to_allocate(partial, indirect_blks,
+-				      map->m_len, blocks_to_boundary);
++	ar.len = ext4_blks_to_allocate(partial, indirect_blks,
++				       map->m_len, blocks_to_boundary);
++
+ 	/*
+ 	 * Block out ext4_truncate while we alter the tree
+ 	 */
+-	err = ext4_alloc_branch(handle, inode, map->m_lblk, indirect_blks,
+-				&count, goal,
++	err = ext4_alloc_branch(handle, &ar, indirect_blks,
+ 				offsets + (partial - chain), partial);
+ 
+ 	/*
+@@ -605,14 +599,14 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
+ 	 * may need to return -EAGAIN upwards in the worst case.  --sct
+ 	 */
+ 	if (!err)
+-		err = ext4_splice_branch(handle, inode, map->m_lblk,
+-					 partial, indirect_blks, count);
++		err = ext4_splice_branch(handle, &ar, partial, indirect_blks);
+ 	if (err)
+ 		goto cleanup;
+ 
+ 	map->m_flags |= EXT4_MAP_NEW;
+ 
+ 	ext4_update_inode_fsync_trans(handle, inode, 1);
++	count = ar.len;
+ got_it:
+ 	map->m_flags |= EXT4_MAP_MAPPED;
+ 	map->m_pblk = le32_to_cpu(chain[depth-1].key);

commit a9cfcd63e8d206ce4235c355d857c4fbdf0f4587
+Author: Theodore Ts'o 
+Date:   Wed Sep 3 09:33:00 2014 -0400
+
+    ext4: avoid trying to kfree an ERR_PTR pointer
+    
+    Thanks to Dan Carpenter for extending smatch to find bugs like this.
+    (This was found using a development version of smatch.)
+    
+    Fixes: 36de928641ee48b2078d3fe9514242aaa2f92013
+    Reported-by: Dan Carpenter 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 90a3cdca3f88..603e4ebbd0ac 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -3240,6 +3240,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 				 &new.de, &new.inlined);
+ 	if (IS_ERR(new.bh)) {
+ 		retval = PTR_ERR(new.bh);
++		new.bh = NULL;
+ 		goto end_rename;
+ 	}
+ 	if (new.bh) {
+@@ -3386,6 +3387,7 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 				 &new.de, &new.inlined);
+ 	if (IS_ERR(new.bh)) {
+ 		retval = PTR_ERR(new.bh);
++		new.bh = NULL;
+ 		goto end_rename;
+ 	}
+ 
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index bb0e80f03e2e..1e43b905ff98 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -575,6 +575,7 @@ static int setup_new_flex_group_blocks(struct super_block *sb,
+ 		bh = bclean(handle, sb, block);
+ 		if (IS_ERR(bh)) {
+ 			err = PTR_ERR(bh);
++			bh = NULL;
+ 			goto out;
+ 		}
+ 		overhead = ext4_group_overhead_blocks(sb, group);
+@@ -603,6 +604,7 @@ static int setup_new_flex_group_blocks(struct super_block *sb,
+ 		bh = bclean(handle, sb, block);
+ 		if (IS_ERR(bh)) {
+ 			err = PTR_ERR(bh);
++			bh = NULL;
+ 			goto out;
+ 		}
+ 

commit 88fe1acb5bedfcba5f42fcdf165493ee587ba643
+Author: Theodore Ts'o 
+Date:   Mon Sep 1 21:26:09 2014 -0400
+
+    jbd2: fold __wait_cp_io into jbd2_log_do_checkpoint()
+    
+    __wait_cp_io() is only called by jbd2_log_do_checkpoint().  Fold it in
+    to make it a bit easier to understand.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
+index f1507e5b7c9a..18c7a8d3da13 100644
+--- a/fs/jbd2/checkpoint.c
++++ b/fs/jbd2/checkpoint.c
+@@ -183,58 +183,6 @@ void __jbd2_log_wait_for_space(journal_t *journal)
+ 	}
+ }
+ 
+-/*
+- * Clean up transaction's list of buffers submitted for io.
+- * We wait for any pending IO to complete and remove any clean
+- * buffers. Note that we take the buffers in the opposite ordering
+- * from the one in which they were submitted for IO.
+- *
+- * Return 0 on success, and return <0 if some buffers have failed
+- * to be written out.
+- *
+- * Called with j_list_lock held.
+- */
+-static int __wait_cp_io(journal_t *journal, transaction_t *transaction)
+-{
+-	struct journal_head *jh;
+-	struct buffer_head *bh;
+-	tid_t this_tid;
+-	int released = 0;
+-	int ret = 0;
+-
+-	this_tid = transaction->t_tid;
+-restart:
+-	/* Did somebody clean up the transaction in the meanwhile? */
+-	if (journal->j_checkpoint_transactions != transaction ||
+-			transaction->t_tid != this_tid)
+-		return ret;
+-	while (!released && transaction->t_checkpoint_io_list) {
+-		jh = transaction->t_checkpoint_io_list;
+-		bh = jh2bh(jh);
+-		get_bh(bh);
+-		if (buffer_locked(bh)) {
+-			spin_unlock(&journal->j_list_lock);
+-			wait_on_buffer(bh);
+-			/* the journal_head may have gone by now */
+-			BUFFER_TRACE(bh, "brelse");
+-			__brelse(bh);
+-			spin_lock(&journal->j_list_lock);
+-			goto restart;
+-		}
+-		if (unlikely(buffer_write_io_error(bh)))
+-			ret = -EIO;
+-
+-		/*
+-		 * Now in whatever state the buffer currently is, we know that
+-		 * it has been written out and so we can drop it from the list
+-		 */
+-		released = __jbd2_journal_remove_checkpoint(jh);
+-		__brelse(bh);
+-	}
+-
+-	return ret;
+-}
+-
+ static void
+ __flush_batch(journal_t *journal, int *batch_count)
+ {
+@@ -268,7 +216,7 @@ int jbd2_log_do_checkpoint(journal_t *journal)
+ 	struct buffer_head	*bh;
+ 	transaction_t		*transaction;
+ 	tid_t			this_tid;
+-	int			err, result, batch_count = 0;
++	int			result, batch_count = 0, done = 0;
+ 
+ 	jbd_debug(1, "Start checkpoint\n");
+ 
+@@ -384,9 +332,36 @@ int jbd2_log_do_checkpoint(journal_t *journal)
+ 	 * Now we issued all of the transaction's buffers, let's deal
+ 	 * with the buffers that are out for I/O.
+ 	 */
+-	err = __wait_cp_io(journal, transaction);
+-	if (!result)
+-		result = err;
++restart2:
++	/* Did somebody clean up the transaction in the meanwhile? */
++	if (journal->j_checkpoint_transactions != transaction ||
++	    transaction->t_tid != this_tid)
++		goto out;
++
++	while (!done && transaction->t_checkpoint_io_list) {
++		jh = transaction->t_checkpoint_io_list;
++		bh = jh2bh(jh);
++		get_bh(bh);
++		if (buffer_locked(bh)) {
++			spin_unlock(&journal->j_list_lock);
++			wait_on_buffer(bh);
++			/* the journal_head may have gone by now */
++			BUFFER_TRACE(bh, "brelse");
++			__brelse(bh);
++			spin_lock(&journal->j_list_lock);
++			goto restart2;
++		}
++		if (unlikely(buffer_write_io_error(bh)) && !result)
++			result = -EIO;
++
++		/*
++		 * Now in whatever state the buffer currently is, we
++		 * know that it has been written out and so we can
++		 * drop it from the list
++		 */
++		done = __jbd2_journal_remove_checkpoint(jh);
++		__brelse(bh);
++	}
+ out:
+ 	spin_unlock(&journal->j_list_lock);
+ 	if (result < 0)

commit be1158cc615fd723552f0d9912087423c7cadda5
+Author: Theodore Ts'o 
+Date:   Mon Sep 1 21:19:01 2014 -0400
+
+    jbd2: fold __process_buffer() into jbd2_log_do_checkpoint()
+    
+    __process_buffer() is only called by jbd2_log_do_checkpoint(), and it
+    had a very complex locking protocol where it would be called with the
+    j_list_lock, and sometimes exit with the lock held (if the return code
+    was 0), or release the lock.
+    
+    This was confusing both to humans and to smatch (which erronously
+    complained that the lock was taken twice).
+    
+    Folding __process_buffer() to the caller allows us to simplify the
+    control flow, making the resulting function easier to read and reason
+    about, and dropping the compiled size of fs/jbd2/checkpoint.c by 150
+    bytes (over 4% of the text size).
+    
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
+index 7f34f4716165..f1507e5b7c9a 100644
+--- a/fs/jbd2/checkpoint.c
++++ b/fs/jbd2/checkpoint.c
+@@ -254,81 +254,6 @@ __flush_batch(journal_t *journal, int *batch_count)
+ 	*batch_count = 0;
+ }
+ 
+-/*
+- * Try to flush one buffer from the checkpoint list to disk.
+- *
+- * Return 1 if something happened which requires us to abort the current
+- * scan of the checkpoint list.  Return <0 if the buffer has failed to
+- * be written out.
+- *
+- * Called with j_list_lock held and drops it if 1 is returned
+- */
+-static int __process_buffer(journal_t *journal, struct journal_head *jh,
+-			    int *batch_count, transaction_t *transaction)
+-{
+-	struct buffer_head *bh = jh2bh(jh);
+-	int ret = 0;
+-
+-	if (buffer_locked(bh)) {
+-		get_bh(bh);
+-		spin_unlock(&journal->j_list_lock);
+-		wait_on_buffer(bh);
+-		/* the journal_head may have gone by now */
+-		BUFFER_TRACE(bh, "brelse");
+-		__brelse(bh);
+-		ret = 1;
+-	} else if (jh->b_transaction != NULL) {
+-		transaction_t *t = jh->b_transaction;
+-		tid_t tid = t->t_tid;
+-
+-		transaction->t_chp_stats.cs_forced_to_close++;
+-		spin_unlock(&journal->j_list_lock);
+-		if (unlikely(journal->j_flags & JBD2_UNMOUNT))
+-			/*
+-			 * The journal thread is dead; so starting and
+-			 * waiting for a commit to finish will cause
+-			 * us to wait for a _very_ long time.
+-			 */
+-			printk(KERN_ERR "JBD2: %s: "
+-			       "Waiting for Godot: block %llu\n",
+-			       journal->j_devname,
+-			       (unsigned long long) bh->b_blocknr);
+-		jbd2_log_start_commit(journal, tid);
+-		jbd2_log_wait_commit(journal, tid);
+-		ret = 1;
+-	} else if (!buffer_dirty(bh)) {
+-		ret = 1;
+-		if (unlikely(buffer_write_io_error(bh)))
+-			ret = -EIO;
+-		get_bh(bh);
+-		BUFFER_TRACE(bh, "remove from checkpoint");
+-		__jbd2_journal_remove_checkpoint(jh);
+-		spin_unlock(&journal->j_list_lock);
+-		__brelse(bh);
+-	} else {
+-		/*
+-		 * Important: we are about to write the buffer, and
+-		 * possibly block, while still holding the journal lock.
+-		 * We cannot afford to let the transaction logic start
+-		 * messing around with this buffer before we write it to
+-		 * disk, as that would break recoverability.
+-		 */
+-		BUFFER_TRACE(bh, "queue");
+-		get_bh(bh);
+-		J_ASSERT_BH(bh, !buffer_jwrite(bh));
+-		journal->j_chkpt_bhs[*batch_count] = bh;
+-		__buffer_relink_io(jh);
+-		transaction->t_chp_stats.cs_written++;
+-		(*batch_count)++;
+-		if (*batch_count == JBD2_NR_BATCH) {
+-			spin_unlock(&journal->j_list_lock);
+-			__flush_batch(journal, batch_count);
+-			ret = 1;
+-		}
+-	}
+-	return ret;
+-}
+-
+ /*
+  * Perform an actual checkpoint. We take the first transaction on the
+  * list of transactions to be checkpointed and send all its buffers
+@@ -339,9 +264,11 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
+  */
+ int jbd2_log_do_checkpoint(journal_t *journal)
+ {
+-	transaction_t *transaction;
+-	tid_t this_tid;
+-	int result;
++	struct journal_head	*jh;
++	struct buffer_head	*bh;
++	transaction_t		*transaction;
++	tid_t			this_tid;
++	int			err, result, batch_count = 0;
+ 
+ 	jbd_debug(1, "Start checkpoint\n");
+ 
+@@ -374,46 +301,92 @@ int jbd2_log_do_checkpoint(journal_t *journal)
+ 	 * done (maybe it's a new transaction, but it fell at the same
+ 	 * address).
+ 	 */
+-	if (journal->j_checkpoint_transactions == transaction &&
+-			transaction->t_tid == this_tid) {
+-		int batch_count = 0;
+-		struct journal_head *jh;
+-		int retry = 0, err;
+-
+-		while (!retry && transaction->t_checkpoint_list) {
+-			jh = transaction->t_checkpoint_list;
+-			retry = __process_buffer(journal, jh, &batch_count,
+-						 transaction);
+-			if (retry < 0 && !result)
+-				result = retry;
+-			if (!retry && (need_resched() ||
+-				spin_needbreak(&journal->j_list_lock))) {
+-				spin_unlock(&journal->j_list_lock);
+-				retry = 1;
+-				break;
+-			}
+-		}
++	if (journal->j_checkpoint_transactions != transaction ||
++	    transaction->t_tid != this_tid)
++		goto out;
+ 
+-		if (batch_count) {
+-			if (!retry) {
+-				spin_unlock(&journal->j_list_lock);
+-				retry = 1;
+-			}
+-			__flush_batch(journal, &batch_count);
++	/* checkpoint all of the transaction's buffers */
++	while (transaction->t_checkpoint_list) {
++		jh = transaction->t_checkpoint_list;
++		bh = jh2bh(jh);
++
++		if (buffer_locked(bh)) {
++			spin_unlock(&journal->j_list_lock);
++			get_bh(bh);
++			wait_on_buffer(bh);
++			/* the journal_head may have gone by now */
++			BUFFER_TRACE(bh, "brelse");
++			__brelse(bh);
++			goto retry;
+ 		}
++		if (jh->b_transaction != NULL) {
++			transaction_t *t = jh->b_transaction;
++			tid_t tid = t->t_tid;
+ 
+-		if (retry) {
+-			spin_lock(&journal->j_list_lock);
+-			goto restart;
++			transaction->t_chp_stats.cs_forced_to_close++;
++			spin_unlock(&journal->j_list_lock);
++			if (unlikely(journal->j_flags & JBD2_UNMOUNT))
++				/*
++				 * The journal thread is dead; so
++				 * starting and waiting for a commit
++				 * to finish will cause us to wait for
++				 * a _very_ long time.
++				 */
++				printk(KERN_ERR
++		"JBD2: %s: Waiting for Godot: block %llu\n",
++		journal->j_devname, (unsigned long long) bh->b_blocknr);
++
++			jbd2_log_start_commit(journal, tid);
++			jbd2_log_wait_commit(journal, tid);
++			goto retry;
++		}
++		if (!buffer_dirty(bh)) {
++			if (unlikely(buffer_write_io_error(bh)) && !result)
++				result = -EIO;
++			get_bh(bh);
++			BUFFER_TRACE(bh, "remove from checkpoint");
++			__jbd2_journal_remove_checkpoint(jh);
++			spin_unlock(&journal->j_list_lock);
++			__brelse(bh);
++			goto retry;
+ 		}
+ 		/*
+-		 * Now we have cleaned up the first transaction's checkpoint
+-		 * list. Let's clean up the second one
++		 * Important: we are about to write the buffer, and
++		 * possibly block, while still holding the journal
++		 * lock.  We cannot afford to let the transaction
++		 * logic start messing around with this buffer before
++		 * we write it to disk, as that would break
++		 * recoverability.
+ 		 */
+-		err = __wait_cp_io(journal, transaction);
+-		if (!result)
+-			result = err;
++		BUFFER_TRACE(bh, "queue");
++		get_bh(bh);
++		J_ASSERT_BH(bh, !buffer_jwrite(bh));
++		journal->j_chkpt_bhs[batch_count++] = bh;
++		__buffer_relink_io(jh);
++		transaction->t_chp_stats.cs_written++;
++		if ((batch_count == JBD2_NR_BATCH) ||
++		    need_resched() ||
++		    spin_needbreak(&journal->j_list_lock))
++			goto unlock_and_flush;
+ 	}
++
++	if (batch_count) {
++		unlock_and_flush:
++			spin_unlock(&journal->j_list_lock);
++		retry:
++			if (batch_count)
++				__flush_batch(journal, &batch_count);
++			spin_lock(&journal->j_list_lock);
++			goto restart;
++	}
++
++	/*
++	 * Now we issued all of the transaction's buffers, let's deal
++	 * with the buffers that are out for I/O.
++	 */
++	err = __wait_cp_io(journal, transaction);
++	if (!result)
++		result = err;
+ out:
+ 	spin_unlock(&journal->j_list_lock);
+ 	if (result < 0)

commit ed8a1a766af7371bfbe41857a3a11496b4165143
+Author: Theodore Ts'o 
+Date:   Mon Sep 1 14:43:09 2014 -0400
+
+    ext4: rename ext4_ext_find_extent() to ext4_find_extent()
+    
+    Make the function name less redundant.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 4a5a6b95b2fa..c07f43f8eb93 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -573,7 +573,7 @@ enum {
+ 
+ /*
+  * The bit position of these flags must not overlap with any of the
+- * EXT4_GET_BLOCKS_*.  They are used by ext4_ext_find_extent(),
++ * EXT4_GET_BLOCKS_*.  They are used by ext4_find_extent(),
+  * read_extent_tree_block(), ext4_split_extent_at(),
+  * ext4_ext_insert_extent(), and ext4_ext_create_new_leaf().
+  * EXT4_EX_NOCACHE is used to indicate that the we shouldn't be
+@@ -2732,9 +2732,9 @@ extern int ext4_can_extents_be_merged(struct inode *inode,
+ extern int ext4_ext_insert_extent(handle_t *, struct inode *,
+ 				  struct ext4_ext_path **,
+ 				  struct ext4_extent *, int);
+-extern struct ext4_ext_path *ext4_ext_find_extent(struct inode *, ext4_lblk_t,
+-						  struct ext4_ext_path **,
+-						  int flags);
++extern struct ext4_ext_path *ext4_find_extent(struct inode *, ext4_lblk_t,
++					      struct ext4_ext_path **,
++					      int flags);
+ extern void ext4_ext_drop_refs(struct ext4_ext_path *);
+ extern int ext4_ext_check_inode(struct inode *inode);
+ extern int ext4_find_delalloc_range(struct inode *inode,
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 22828e44a70d..3ac1686efff8 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -857,8 +857,8 @@ int ext4_ext_tree_init(handle_t *handle, struct inode *inode)
+ }
+ 
+ struct ext4_ext_path *
+-ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
+-		     struct ext4_ext_path **orig_path, int flags)
++ext4_find_extent(struct inode *inode, ext4_lblk_t block,
++		 struct ext4_ext_path **orig_path, int flags)
+ {
+ 	struct ext4_extent_header *eh;
+ 	struct buffer_head *bh;
+@@ -1366,7 +1366,7 @@ static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
+ 			goto out;
+ 
+ 		/* refill path */
+-		path = ext4_ext_find_extent(inode,
++		path = ext4_find_extent(inode,
+ 				    (ext4_lblk_t)le32_to_cpu(newext->ee_block),
+ 				    ppath, gb_flags);
+ 		if (IS_ERR(path))
+@@ -1378,7 +1378,7 @@ static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
+ 			goto out;
+ 
+ 		/* refill path */
+-		path = ext4_ext_find_extent(inode,
++		path = ext4_find_extent(inode,
+ 				   (ext4_lblk_t)le32_to_cpu(newext->ee_block),
+ 				    ppath, gb_flags);
+ 		if (IS_ERR(path)) {
+@@ -1951,7 +1951,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+ 		/*
+ 		 * Try to see whether we should rather test the extent on
+ 		 * right from ex, or from the left of ex. This is because
+-		 * ext4_ext_find_extent() can return either extent on the
++		 * ext4_find_extent() can return either extent on the
+ 		 * left, or on the right from the searched position. This
+ 		 * will make merging more effective.
+ 		 */
+@@ -2034,7 +2034,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+ 	if (next != EXT_MAX_BLOCKS) {
+ 		ext_debug("next leaf block - %u\n", next);
+ 		BUG_ON(npath != NULL);
+-		npath = ext4_ext_find_extent(inode, next, NULL, 0);
++		npath = ext4_find_extent(inode, next, NULL, 0);
+ 		if (IS_ERR(npath))
+ 			return PTR_ERR(npath);
+ 		BUG_ON(npath->p_depth != path->p_depth);
+@@ -2157,7 +2157,7 @@ static int ext4_fill_fiemap_extents(struct inode *inode,
+ 		/* find extent for this block */
+ 		down_read(&EXT4_I(inode)->i_data_sem);
+ 
+-		path = ext4_ext_find_extent(inode, block, &path, 0);
++		path = ext4_find_extent(inode, block, &path, 0);
+ 		if (IS_ERR(path)) {
+ 			up_read(&EXT4_I(inode)->i_data_sem);
+ 			err = PTR_ERR(path);
+@@ -2840,7 +2840,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
+ 		ext4_lblk_t ee_block;
+ 
+ 		/* find extent for this block */
+-		path = ext4_ext_find_extent(inode, end, NULL, EXT4_EX_NOCACHE);
++		path = ext4_find_extent(inode, end, NULL, EXT4_EX_NOCACHE);
+ 		if (IS_ERR(path)) {
+ 			ext4_journal_stop(handle);
+ 			return PTR_ERR(path);
+@@ -3314,7 +3314,7 @@ static int ext4_split_extent(handle_t *handle,
+ 	 * Update path is required because previous ext4_split_extent_at() may
+ 	 * result in split of original leaf or extent zeroout.
+ 	 */
+-	path = ext4_ext_find_extent(inode, map->m_lblk, ppath, 0);
++	path = ext4_find_extent(inode, map->m_lblk, ppath, 0);
+ 	if (IS_ERR(path))
+ 		return PTR_ERR(path);
+ 	depth = ext_depth(inode);
+@@ -3712,7 +3712,7 @@ static int ext4_convert_unwritten_extents_endio(handle_t *handle,
+ 						 EXT4_GET_BLOCKS_CONVERT);
+ 		if (err < 0)
+ 			return err;
+-		path = ext4_ext_find_extent(inode, map->m_lblk, ppath, 0);
++		path = ext4_find_extent(inode, map->m_lblk, ppath, 0);
+ 		if (IS_ERR(path))
+ 			return PTR_ERR(path);
+ 		depth = ext_depth(inode);
+@@ -3940,7 +3940,7 @@ convert_initialized_extent(handle_t *handle, struct inode *inode,
+ 				EXT4_GET_BLOCKS_CONVERT_UNWRITTEN);
+ 		if (err < 0)
+ 			return err;
+-		path = ext4_ext_find_extent(inode, map->m_lblk, ppath, 0);
++		path = ext4_find_extent(inode, map->m_lblk, ppath, 0);
+ 		if (IS_ERR(path))
+ 			return PTR_ERR(path);
+ 		depth = ext_depth(inode);
+@@ -4266,7 +4266,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 	trace_ext4_ext_map_blocks_enter(inode, map->m_lblk, map->m_len, flags);
+ 
+ 	/* find extent for this block */
+-	path = ext4_ext_find_extent(inode, map->m_lblk, NULL, 0);
++	path = ext4_find_extent(inode, map->m_lblk, NULL, 0);
+ 	if (IS_ERR(path)) {
+ 		err = PTR_ERR(path);
+ 		path = NULL;
+@@ -4278,7 +4278,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 	/*
+ 	 * consistent leaf must not be empty;
+ 	 * this situation is possible, though, _during_ tree modification;
+-	 * this is why assert can't be put in ext4_ext_find_extent()
++	 * this is why assert can't be put in ext4_find_extent()
+ 	 */
+ 	if (unlikely(path[depth].p_ext == NULL && depth != 0)) {
+ 		EXT4_ERROR_INODE(inode, "bad extent address "
+@@ -4363,7 +4363,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 
+ 	/*
+ 	 * If we are doing bigalloc, check to see if the extent returned
+-	 * by ext4_ext_find_extent() implies a cluster we can use.
++	 * by ext4_find_extent() implies a cluster we can use.
+ 	 */
+ 	if (cluster_offset && ex &&
+ 	    get_implied_cluster_alloc(inode->i_sb, map, ex, path)) {
+@@ -5300,7 +5300,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
+ 	ext4_lblk_t ex_start, ex_end;
+ 
+ 	/* Let path point to the last extent */
+-	path = ext4_ext_find_extent(inode, EXT_MAX_BLOCKS - 1, NULL, 0);
++	path = ext4_find_extent(inode, EXT_MAX_BLOCKS - 1, NULL, 0);
+ 	if (IS_ERR(path))
+ 		return PTR_ERR(path);
+ 
+@@ -5320,7 +5320,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
+ 	 * Don't start shifting extents until we make sure the hole is big
+ 	 * enough to accomodate the shift.
+ 	 */
+-	path = ext4_ext_find_extent(inode, start - 1, &path, 0);
++	path = ext4_find_extent(inode, start - 1, &path, 0);
+ 	if (IS_ERR(path))
+ 		return PTR_ERR(path);
+ 	depth = path->p_depth;
+@@ -5340,7 +5340,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
+ 
+ 	/* Its safe to start updating extents */
+ 	while (start < stop_block) {
+-		path = ext4_ext_find_extent(inode, start, &path, 0);
++		path = ext4_find_extent(inode, start, &path, 0);
+ 		if (IS_ERR(path))
+ 			return PTR_ERR(path);
+ 		depth = path->p_depth;
+@@ -5537,7 +5537,7 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
+ 		int e1_len, e2_len, len;
+ 		int split = 0;
+ 
+-		path1 = ext4_ext_find_extent(inode1, lblk1, NULL, EXT4_EX_NOCACHE);
++		path1 = ext4_find_extent(inode1, lblk1, NULL, EXT4_EX_NOCACHE);
+ 		if (unlikely(IS_ERR(path1))) {
+ 			*erp = PTR_ERR(path1);
+ 			path1 = NULL;
+@@ -5545,7 +5545,7 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
+ 			count = 0;
+ 			goto repeat;
+ 		}
+-		path2 = ext4_ext_find_extent(inode2, lblk2, NULL, EXT4_EX_NOCACHE);
++		path2 = ext4_find_extent(inode2, lblk2, NULL, EXT4_EX_NOCACHE);
+ 		if (unlikely(IS_ERR(path2))) {
+ 			*erp = PTR_ERR(path2);
+ 			path2 = NULL;
+diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
+index 8ffff966d594..bdd400c81533 100644
+--- a/fs/ext4/extents_status.c
++++ b/fs/ext4/extents_status.c
+@@ -426,7 +426,7 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode,
+ 	unsigned short ee_len;
+ 	int depth, ee_status, es_status;
+ 
+-	path = ext4_ext_find_extent(inode, es->es_lblk, NULL, EXT4_EX_NOCACHE);
++	path = ext4_find_extent(inode, es->es_lblk, NULL, EXT4_EX_NOCACHE);
+ 	if (IS_ERR(path))
+ 		return;
+ 
+diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
+index 061c300703c7..a432634f2e6a 100644
+--- a/fs/ext4/migrate.c
++++ b/fs/ext4/migrate.c
+@@ -41,8 +41,7 @@ static int finish_range(handle_t *handle, struct inode *inode,
+ 	ext4_ext_store_pblock(&newext, lb->first_pblock);
+ 	/* Locking only for convinience since we are operating on temp inode */
+ 	down_write(&EXT4_I(inode)->i_data_sem);
+-	path = ext4_ext_find_extent(inode, lb->first_block, NULL, 0);
+-
++	path = ext4_find_extent(inode, lb->first_block, NULL, 0);
+ 	if (IS_ERR(path)) {
+ 		retval = PTR_ERR(path);
+ 		path = NULL;
+diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
+index 7bf970dd61f5..5d7806390102 100644
+--- a/fs/ext4/move_extent.c
++++ b/fs/ext4/move_extent.c
+@@ -27,7 +27,7 @@
+  * @lblock:	logical block number to find an extent path
+  * @path:	pointer to an extent path pointer (for output)
+  *
+- * ext4_ext_find_extent wrapper. Return 0 on success, or a negative error value
++ * ext4_find_extent wrapper. Return 0 on success, or a negative error value
+  * on failure.
+  */
+ static inline int
+@@ -36,7 +36,7 @@ get_ext_path(struct inode *inode, ext4_lblk_t lblock,
+ {
+ 	struct ext4_ext_path *path;
+ 
+-	path = ext4_ext_find_extent(inode, lblock, ppath, EXT4_EX_NOCACHE);
++	path = ext4_find_extent(inode, lblock, ppath, EXT4_EX_NOCACHE);
+ 	if (IS_ERR(path))
+ 		return PTR_ERR(path);
+ 	if (path[ext_depth(inode)].p_ext == NULL) {

commit 3bdf14b4d7a3a7416577e9f9f421dbf29b5b6747
+Author: Theodore Ts'o 
+Date:   Mon Sep 1 14:42:09 2014 -0400
+
+    ext4: reuse path object in ext4_move_extents()
+    
+    Reuse the path object in ext4_move_extents() so we don't unnecessarily
+    free and reallocate it.
+    
+    Also clean up the get_ext_path() wrapper so that it has the same
+    semantics of freeing the path object on error as ext4_ext_find_extent().
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
+index a34c0760276c..7bf970dd61f5 100644
+--- a/fs/ext4/move_extent.c
++++ b/fs/ext4/move_extent.c
+@@ -32,20 +32,21 @@
+  */
+ static inline int
+ get_ext_path(struct inode *inode, ext4_lblk_t lblock,
+-		struct ext4_ext_path **orig_path)
++		struct ext4_ext_path **ppath)
+ {
+-	int ret = 0;
+ 	struct ext4_ext_path *path;
+ 
+-	path = ext4_ext_find_extent(inode, lblock, orig_path, EXT4_EX_NOCACHE);
++	path = ext4_ext_find_extent(inode, lblock, ppath, EXT4_EX_NOCACHE);
+ 	if (IS_ERR(path))
+-		ret = PTR_ERR(path);
+-	else if (path[ext_depth(inode)].p_ext == NULL)
+-		ret = -ENODATA;
+-	else
+-		*orig_path = path;
+-
+-	return ret;
++		return PTR_ERR(path);
++	if (path[ext_depth(inode)].p_ext == NULL) {
++		ext4_ext_drop_refs(path);
++		kfree(path);
++		*ppath = NULL;
++		return -ENODATA;
++	}
++	*ppath = path;
++	return 0;
+ }
+ 
+ /**
+@@ -667,7 +668,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, __u64 orig_blk,
+ 			}
+ 			d_start += next_blk - o_start;
+ 			o_start = next_blk;
+-			goto repeat;
++			continue;
+ 		/* Check hole after the start pos */
+ 		} else if (cur_blk > o_start) {
+ 			/* Skip hole */
+@@ -708,10 +709,6 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, __u64 orig_blk,
+ 			break;
+ 		o_start += cur_len;
+ 		d_start += cur_len;
+-	repeat:
+-		ext4_ext_drop_refs(path);
+-		kfree(path);
+-		path = NULL;
+ 	}
+ 	*moved_len = o_start - orig_blk;
+ 	if (*moved_len > len)

commit ee4bd0d963b75cbad9bfb59b547146671c7a655a
+Author: Theodore Ts'o 
+Date:   Mon Sep 1 14:41:09 2014 -0400
+
+    ext4: reuse path object in ext4_ext_shift_extents()
+    
+    Now that the semantics of ext4_ext_find_extent() are much cleaner,
+    it's safe and more efficient to reuse the path object across the
+    multiple calls to ext4_ext_find_extent() in ext4_ext_shift_extents().
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index c94c7480053e..22828e44a70d 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -5306,26 +5306,21 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
+ 
+ 	depth = path->p_depth;
+ 	extent = path[depth].p_ext;
+-	if (!extent) {
+-		ext4_ext_drop_refs(path);
+-		kfree(path);
+-		return ret;
+-	}
++	if (!extent)
++		goto out;
+ 
+ 	stop_block = le32_to_cpu(extent->ee_block) +
+ 			ext4_ext_get_actual_len(extent);
+-	ext4_ext_drop_refs(path);
+-	kfree(path);
+ 
+ 	/* Nothing to shift, if hole is at the end of file */
+ 	if (start >= stop_block)
+-		return ret;
++		goto out;
+ 
+ 	/*
+ 	 * Don't start shifting extents until we make sure the hole is big
+ 	 * enough to accomodate the shift.
+ 	 */
+-	path = ext4_ext_find_extent(inode, start - 1, NULL, 0);
++	path = ext4_ext_find_extent(inode, start - 1, &path, 0);
+ 	if (IS_ERR(path))
+ 		return PTR_ERR(path);
+ 	depth = path->p_depth;
+@@ -5338,8 +5333,6 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
+ 		ex_start = 0;
+ 		ex_end = 0;
+ 	}
+-	ext4_ext_drop_refs(path);
+-	kfree(path);
+ 
+ 	if ((start == ex_start && shift > ex_start) ||
+ 	    (shift > start - ex_end))
+@@ -5347,7 +5340,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
+ 
+ 	/* Its safe to start updating extents */
+ 	while (start < stop_block) {
+-		path = ext4_ext_find_extent(inode, start, NULL, 0);
++		path = ext4_ext_find_extent(inode, start, &path, 0);
+ 		if (IS_ERR(path))
+ 			return PTR_ERR(path);
+ 		depth = path->p_depth;
+@@ -5363,19 +5356,17 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
+ 				path[depth].p_ext++;
+ 			} else {
+ 				start = ext4_ext_next_allocated_block(path);
+-				ext4_ext_drop_refs(path);
+-				kfree(path);
+ 				continue;
+ 			}
+ 		}
+ 		ret = ext4_ext_shift_path_extents(path, shift, inode,
+ 				handle, &start);
+-		ext4_ext_drop_refs(path);
+-		kfree(path);
+ 		if (ret)
+ 			break;
+ 	}
+-
++out:
++	ext4_ext_drop_refs(path);
++	kfree(path);
+ 	return ret;
+ }
+ 

commit 10809df84a4d868db61af621bae3658494165279
+Author: Theodore Ts'o 
+Date:   Mon Sep 1 14:40:09 2014 -0400
+
+    ext4: teach ext4_ext_find_extent() to realloc path if necessary
+    
+    This adds additional safety in case for some reason we end reusing a
+    path structure which isn't big enough for current depth of the inode.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h
+index a867f5ca9991..3c9381547094 100644
+--- a/fs/ext4/ext4_extents.h
++++ b/fs/ext4/ext4_extents.h
+@@ -123,6 +123,7 @@ find_ext4_extent_tail(struct ext4_extent_header *eh)
+ struct ext4_ext_path {
+ 	ext4_fsblk_t			p_block;
+ 	__u16				p_depth;
++	__u16				p_maxdepth;
+ 	struct ext4_extent		*p_ext;
+ 	struct ext4_extent_idx		*p_idx;
+ 	struct ext4_extent_header	*p_hdr;
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 538f9a4d96ff..c94c7480053e 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -869,14 +869,20 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
+ 	eh = ext_inode_hdr(inode);
+ 	depth = ext_depth(inode);
+ 
+-	if (path)
++	if (path) {
+ 		ext4_ext_drop_refs(path);
+-	else {
++		if (depth > path[0].p_maxdepth) {
++			kfree(path);
++			*orig_path = path = NULL;
++		}
++	}
++	if (!path) {
+ 		/* account possible depth increase */
+ 		path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 2),
+ 				GFP_NOFS);
+ 		if (unlikely(!path))
+ 			return ERR_PTR(-ENOMEM);
++		path[0].p_maxdepth = depth + 1;
+ 	}
+ 	path[0].p_hdr = eh;
+ 	path[0].p_bh = NULL;
+@@ -1820,6 +1826,7 @@ static void ext4_ext_try_to_merge_up(handle_t *handle,
+ 		sizeof(struct ext4_extent_idx);
+ 	s += sizeof(struct ext4_extent_header);
+ 
++	path[1].p_maxdepth = path[0].p_maxdepth;
+ 	memcpy(path[0].p_hdr, path[1].p_hdr, s);
+ 	path[0].p_depth = 0;
+ 	path[0].p_ext = EXT_FIRST_EXTENT(path[0].p_hdr) +
+@@ -2150,12 +2157,6 @@ static int ext4_fill_fiemap_extents(struct inode *inode,
+ 		/* find extent for this block */
+ 		down_read(&EXT4_I(inode)->i_data_sem);
+ 
+-		if (path && ext_depth(inode) != depth) {
+-			/* depth was changed. we have to realloc path */
+-			kfree(path);
+-			path = NULL;
+-		}
+-
+ 		path = ext4_ext_find_extent(inode, block, &path, 0);
+ 		if (IS_ERR(path)) {
+ 			up_read(&EXT4_I(inode)->i_data_sem);
+@@ -2173,7 +2174,6 @@ static int ext4_fill_fiemap_extents(struct inode *inode,
+ 		}
+ 		ex = path[depth].p_ext;
+ 		next = ext4_ext_next_allocated_block(path);
+-		ext4_ext_drop_refs(path);
+ 
+ 		flags = 0;
+ 		exists = 0;
+@@ -2897,7 +2897,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
+ 			ext4_journal_stop(handle);
+ 			return -ENOMEM;
+ 		}
+-		path[0].p_depth = depth;
++		path[0].p_maxdepth = path[0].p_depth = depth;
+ 		path[0].p_hdr = ext_inode_hdr(inode);
+ 		i = 0;
+ 

commit b7ea89ad0a6b855172158a999d3f5008403f4011
+Author: Theodore Ts'o 
+Date:   Mon Sep 1 14:39:09 2014 -0400
+
+    ext4: allow a NULL argument to ext4_ext_drop_refs()
+    
+    Teach ext4_ext_drop_refs() to accept a NULL argument, much like
+    kfree().  This allows us to drop a lot of checks to make sure path is
+    non-NULL before calling ext4_ext_drop_refs().
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 4f4d52398712..538f9a4d96ff 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -709,9 +709,11 @@ static void ext4_ext_show_move(struct inode *inode, struct ext4_ext_path *path,
+ 
+ void ext4_ext_drop_refs(struct ext4_ext_path *path)
+ {
+-	int depth = path->p_depth;
+-	int i;
++	int depth, i;
+ 
++	if (!path)
++		return;
++	depth = path->p_depth;
+ 	for (i = 0; i <= depth; i++, path++)
+ 		if (path->p_bh) {
+ 			brelse(path->p_bh);
+@@ -2125,10 +2127,8 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+ 	err = ext4_ext_dirty(handle, inode, path + path->p_depth);
+ 
+ cleanup:
+-	if (npath) {
+-		ext4_ext_drop_refs(npath);
+-		kfree(npath);
+-	}
++	ext4_ext_drop_refs(npath);
++	kfree(npath);
+ 	return err;
+ }
+ 
+@@ -2283,11 +2283,8 @@ static int ext4_fill_fiemap_extents(struct inode *inode,
+ 		block = es.es_lblk + es.es_len;
+ 	}
+ 
+-	if (path) {
+-		ext4_ext_drop_refs(path);
+-		kfree(path);
+-	}
+-
++	ext4_ext_drop_refs(path);
++	kfree(path);
+ 	return err;
+ }
+ 
+@@ -3018,11 +3015,9 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
+ 		}
+ 	}
+ out:
+-	if (path) {
+-		ext4_ext_drop_refs(path);
+-		kfree(path);
+-		path = NULL;
+-	}
++	ext4_ext_drop_refs(path);
++	kfree(path);
++	path = NULL;
+ 	if (err == -EAGAIN)
+ 		goto again;
+ 	ext4_journal_stop(handle);
+@@ -4611,10 +4606,8 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 	map->m_pblk = newblock;
+ 	map->m_len = allocated;
+ out2:
+-	if (path) {
+-		ext4_ext_drop_refs(path);
+-		kfree(path);
+-	}
++	ext4_ext_drop_refs(path);
++	kfree(path);
+ 
+ 	trace_ext4_ext_map_blocks_exit(inode, flags, map,
+ 				       err ? err : allocated);
+@@ -5693,16 +5686,11 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
+ 		count -= len;
+ 
+ 	repeat:
+-		if (path1) {
+-			ext4_ext_drop_refs(path1);
+-			kfree(path1);
+-			path1 = NULL;
+-		}
+-		if (path2) {
+-			ext4_ext_drop_refs(path2);
+-			kfree(path2);
+-			path2 = NULL;
+-		}
++		ext4_ext_drop_refs(path1);
++		kfree(path1);
++		ext4_ext_drop_refs(path2);
++		kfree(path2);
++		path1 = path2 = NULL;
+ 	}
+ 	return replaced_count;
+ }
+diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
+index 0b7e28e7eaa4..8ffff966d594 100644
+--- a/fs/ext4/extents_status.c
++++ b/fs/ext4/extents_status.c
+@@ -499,10 +499,8 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode,
+ 		}
+ 	}
+ out:
+-	if (path) {
+-		ext4_ext_drop_refs(path);
+-		kfree(path);
+-	}
++	ext4_ext_drop_refs(path);
++	kfree(path);
+ }
+ 
+ static void ext4_es_insert_extent_ind_check(struct inode *inode,
+diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
+index aff7bdfdc461..061c300703c7 100644
+--- a/fs/ext4/migrate.c
++++ b/fs/ext4/migrate.c
+@@ -84,10 +84,8 @@ static int finish_range(handle_t *handle, struct inode *inode,
+ 	retval = ext4_ext_insert_extent(handle, inode, &path, &newext, 0);
+ err_out:
+ 	up_write((&EXT4_I(inode)->i_data_sem));
+-	if (path) {
+-		ext4_ext_drop_refs(path);
+-		kfree(path);
+-	}
++	ext4_ext_drop_refs(path);
++	kfree(path);
+ 	lb->first_pblock = 0;
+ 	return retval;
+ }
+diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
+index 5e2465a8e4ce..a34c0760276c 100644
+--- a/fs/ext4/move_extent.c
++++ b/fs/ext4/move_extent.c
+@@ -113,10 +113,8 @@ mext_check_coverage(struct inode *inode, ext4_lblk_t from, ext4_lblk_t count,
+ 	}
+ 	ret = 1;
+ out:
+-	if (path) {
+-		ext4_ext_drop_refs(path);
+-		kfree(path);
+-	}
++	ext4_ext_drop_refs(path);
++	kfree(path);
+ 	return ret;
+ }
+ 
+@@ -711,11 +709,9 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, __u64 orig_blk,
+ 		o_start += cur_len;
+ 		d_start += cur_len;
+ 	repeat:
+-		if (path) {
+-			ext4_ext_drop_refs(path);
+-			kfree(path);
+-			path = NULL;
+-		}
++		ext4_ext_drop_refs(path);
++		kfree(path);
++		path = NULL;
+ 	}
+ 	*moved_len = o_start - orig_blk;
+ 	if (*moved_len > len)
+@@ -727,10 +723,8 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, __u64 orig_blk,
+ 		ext4_discard_preallocations(donor_inode);
+ 	}
+ 
+-	if (path) {
+-		ext4_ext_drop_refs(path);
+-		kfree(path);
+-	}
++	ext4_ext_drop_refs(path);
++	kfree(path);
+ 	ext4_double_up_write_data_sem(orig_inode, donor_inode);
+ 	ext4_inode_resume_unlocked_dio(orig_inode);
+ 	ext4_inode_resume_unlocked_dio(donor_inode);

commit 523f431ccfffd3022e80e13befb9594f54b5607e
+Author: Theodore Ts'o 
+Date:   Mon Sep 1 14:38:09 2014 -0400
+
+    ext4: call ext4_ext_drop_refs() from ext4_ext_find_extent()
+    
+    In nearly all of the calls to ext4_ext_find_extent() where the caller
+    is trying to recycle the path object, ext4_ext_drop_refs() gets called
+    to release the buffer heads before the path object gets overwritten.
+    To simplify things for the callers, and to avoid the possibility of a
+    memory leak, make ext4_ext_find_extent() responsible for dropping the
+    buffers.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index ccdd2afc546e..4f4d52398712 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -867,8 +867,10 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
+ 	eh = ext_inode_hdr(inode);
+ 	depth = ext_depth(inode);
+ 
+-	/* account possible depth increase */
+-	if (!path) {
++	if (path)
++		ext4_ext_drop_refs(path);
++	else {
++		/* account possible depth increase */
+ 		path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 2),
+ 				GFP_NOFS);
+ 		if (unlikely(!path))
+@@ -1356,7 +1358,6 @@ static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
+ 			goto out;
+ 
+ 		/* refill path */
+-		ext4_ext_drop_refs(path);
+ 		path = ext4_ext_find_extent(inode,
+ 				    (ext4_lblk_t)le32_to_cpu(newext->ee_block),
+ 				    ppath, gb_flags);
+@@ -1369,7 +1370,6 @@ static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
+ 			goto out;
+ 
+ 		/* refill path */
+-		ext4_ext_drop_refs(path);
+ 		path = ext4_ext_find_extent(inode,
+ 				   (ext4_lblk_t)le32_to_cpu(newext->ee_block),
+ 				    ppath, gb_flags);
+@@ -3319,7 +3319,6 @@ static int ext4_split_extent(handle_t *handle,
+ 	 * Update path is required because previous ext4_split_extent_at() may
+ 	 * result in split of original leaf or extent zeroout.
+ 	 */
+-	ext4_ext_drop_refs(path);
+ 	path = ext4_ext_find_extent(inode, map->m_lblk, ppath, 0);
+ 	if (IS_ERR(path))
+ 		return PTR_ERR(path);
+@@ -3718,7 +3717,6 @@ static int ext4_convert_unwritten_extents_endio(handle_t *handle,
+ 						 EXT4_GET_BLOCKS_CONVERT);
+ 		if (err < 0)
+ 			return err;
+-		ext4_ext_drop_refs(path);
+ 		path = ext4_ext_find_extent(inode, map->m_lblk, ppath, 0);
+ 		if (IS_ERR(path))
+ 			return PTR_ERR(path);
+@@ -3947,7 +3945,6 @@ convert_initialized_extent(handle_t *handle, struct inode *inode,
+ 				EXT4_GET_BLOCKS_CONVERT_UNWRITTEN);
+ 		if (err < 0)
+ 			return err;
+-		ext4_ext_drop_refs(path);
+ 		path = ext4_ext_find_extent(inode, map->m_lblk, ppath, 0);
+ 		if (IS_ERR(path))
+ 			return PTR_ERR(path);

commit dfe5080939ea4686b3414b5d970a9b26733c57a4
+Author: Theodore Ts'o 
+Date:   Mon Sep 1 14:37:09 2014 -0400
+
+    ext4: drop EXT4_EX_NOFREE_ON_ERR from rest of extents handling code
+    
+    Drop EXT4_EX_NOFREE_ON_ERR from ext4_ext_create_new_leaf(),
+    ext4_split_extent(), ext4_convert_unwritten_extents_endio().
+    
+    This requires fixing all of their callers to potentially
+    ext4_ext_find_extent() to free the struct ext4_ext_path object in case
+    of an error, and there are interlocking dependencies all the way up to
+    ext4_ext_map_blocks(), ext4_swap_extents(), and
+    ext4_ext_remove_space().
+    
+    Once this is done, we can drop the EXT4_EX_NOFREE_ON_ERR flag since it
+    is no longer necessary.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 696e51ae02fa..4a5a6b95b2fa 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -582,7 +582,6 @@ enum {
+  */
+ #define EXT4_EX_NOCACHE				0x0800
+ #define EXT4_EX_FORCE_CACHE			0x1000
+-#define EXT4_EX_NOFREE_ON_ERR			0x2000
+ 
+ /*
+  * Flags used by ext4_free_blocks
+@@ -2731,7 +2730,7 @@ extern int ext4_can_extents_be_merged(struct inode *inode,
+ 				      struct ext4_extent *ex1,
+ 				      struct ext4_extent *ex2);
+ extern int ext4_ext_insert_extent(handle_t *, struct inode *,
+-				  struct ext4_ext_path *,
++				  struct ext4_ext_path **,
+ 				  struct ext4_extent *, int);
+ extern struct ext4_ext_path *ext4_ext_find_extent(struct inode *, ext4_lblk_t,
+ 						  struct ext4_ext_path **,
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index acb92ac47220..ccdd2afc546e 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -98,14 +98,14 @@ static void ext4_extent_block_csum_set(struct inode *inode,
+ 
+ static int ext4_split_extent(handle_t *handle,
+ 				struct inode *inode,
+-				struct ext4_ext_path *path,
++				struct ext4_ext_path **ppath,
+ 				struct ext4_map_blocks *map,
+ 				int split_flag,
+ 				int flags);
+ 
+ static int ext4_split_extent_at(handle_t *handle,
+ 			     struct inode *inode,
+-			     struct ext4_ext_path *path,
++			     struct ext4_ext_path **ppath,
+ 			     ext4_lblk_t split,
+ 			     int split_flag,
+ 			     int flags);
+@@ -293,12 +293,13 @@ static inline int ext4_ext_space_root_idx(struct inode *inode, int check)
+ 
+ static inline int
+ ext4_force_split_extent_at(handle_t *handle, struct inode *inode,
+-			   struct ext4_ext_path *path, ext4_lblk_t lblk,
++			   struct ext4_ext_path **ppath, ext4_lblk_t lblk,
+ 			   int nofail)
+ {
++	struct ext4_ext_path *path = *ppath;
+ 	int unwritten = ext4_ext_is_unwritten(path[path->p_depth].p_ext);
+ 
+-	return ext4_split_extent_at(handle, inode, path, lblk, unwritten ?
++	return ext4_split_extent_at(handle, inode, ppath, lblk, unwritten ?
+ 			EXT4_EXT_MARK_UNWRIT1|EXT4_EXT_MARK_UNWRIT2 : 0,
+ 			EXT4_EX_NOCACHE | EXT4_GET_BLOCKS_PRE_IO |
+ 			(nofail ? EXT4_GET_BLOCKS_METADATA_NOFAIL:0));
+@@ -861,7 +862,6 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
+ 	struct buffer_head *bh;
+ 	struct ext4_ext_path *path = orig_path ? *orig_path : NULL;
+ 	short int depth, i, ppos = 0;
+-	short free_on_err = (flags & EXT4_EX_NOFREE_ON_ERR) == 0;
+ 	int ret;
+ 
+ 	eh = ext_inode_hdr(inode);
+@@ -873,7 +873,6 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
+ 				GFP_NOFS);
+ 		if (unlikely(!path))
+ 			return ERR_PTR(-ENOMEM);
+-		free_on_err = 1;
+ 	}
+ 	path[0].p_hdr = eh;
+ 	path[0].p_bh = NULL;
+@@ -925,11 +924,9 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
+ 
+ err:
+ 	ext4_ext_drop_refs(path);
+-	if (free_on_err) {
+-		kfree(path);
+-		if (orig_path)
+-			*orig_path = NULL;
+-	}
++	kfree(path);
++	if (orig_path)
++		*orig_path = NULL;
+ 	return ERR_PTR(ret);
+ }
+ 
+@@ -1332,9 +1329,10 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
+ static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
+ 				    unsigned int mb_flags,
+ 				    unsigned int gb_flags,
+-				    struct ext4_ext_path *path,
++				    struct ext4_ext_path **ppath,
+ 				    struct ext4_extent *newext)
+ {
++	struct ext4_ext_path *path = *ppath;
+ 	struct ext4_ext_path *curp;
+ 	int depth, i, err = 0;
+ 
+@@ -1361,7 +1359,7 @@ static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
+ 		ext4_ext_drop_refs(path);
+ 		path = ext4_ext_find_extent(inode,
+ 				    (ext4_lblk_t)le32_to_cpu(newext->ee_block),
+-				    &path, gb_flags | EXT4_EX_NOFREE_ON_ERR);
++				    ppath, gb_flags);
+ 		if (IS_ERR(path))
+ 			err = PTR_ERR(path);
+ 	} else {
+@@ -1374,7 +1372,7 @@ static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
+ 		ext4_ext_drop_refs(path);
+ 		path = ext4_ext_find_extent(inode,
+ 				   (ext4_lblk_t)le32_to_cpu(newext->ee_block),
+-				    &path, gb_flags | EXT4_EX_NOFREE_ON_ERR);
++				    ppath, gb_flags);
+ 		if (IS_ERR(path)) {
+ 			err = PTR_ERR(path);
+ 			goto out;
+@@ -1914,9 +1912,10 @@ static unsigned int ext4_ext_check_overlap(struct ext4_sb_info *sbi,
+  * creating new leaf in the no-space case.
+  */
+ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+-				struct ext4_ext_path *path,
++				struct ext4_ext_path **ppath,
+ 				struct ext4_extent *newext, int gb_flags)
+ {
++	struct ext4_ext_path *path = *ppath;
+ 	struct ext4_extent_header *eh;
+ 	struct ext4_extent *ex, *fex;
+ 	struct ext4_extent *nearex; /* nearest extent */
+@@ -2048,7 +2047,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+ 	if (gb_flags & EXT4_GET_BLOCKS_METADATA_NOFAIL)
+ 		mb_flags = EXT4_MB_USE_RESERVED;
+ 	err = ext4_ext_create_new_leaf(handle, inode, mb_flags, gb_flags,
+-				       path, newext);
++				       ppath, newext);
+ 	if (err)
+ 		goto cleanup;
+ 	depth = ext_depth(inode);
+@@ -2878,7 +2877,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
+ 			 * fail removing space due to ENOSPC so try to use
+ 			 * reserved block if that happens.
+ 			 */
+-			err = ext4_force_split_extent_at(handle, inode, path,
++			err = ext4_force_split_extent_at(handle, inode, &path,
+ 							 end + 1, 1);
+ 			if (err < 0)
+ 				goto out;
+@@ -3019,12 +3018,13 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
+ 		}
+ 	}
+ out:
+-	ext4_ext_drop_refs(path);
+-	kfree(path);
+-	if (err == -EAGAIN) {
++	if (path) {
++		ext4_ext_drop_refs(path);
++		kfree(path);
+ 		path = NULL;
+-		goto again;
+ 	}
++	if (err == -EAGAIN)
++		goto again;
+ 	ext4_journal_stop(handle);
+ 
+ 	return err;
+@@ -3138,11 +3138,12 @@ static int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex)
+  */
+ static int ext4_split_extent_at(handle_t *handle,
+ 			     struct inode *inode,
+-			     struct ext4_ext_path *path,
++			     struct ext4_ext_path **ppath,
+ 			     ext4_lblk_t split,
+ 			     int split_flag,
+ 			     int flags)
+ {
++	struct ext4_ext_path *path = *ppath;
+ 	ext4_fsblk_t newblock;
+ 	ext4_lblk_t ee_block;
+ 	struct ext4_extent *ex, newex, orig_ex, zero_ex;
+@@ -3213,7 +3214,7 @@ static int ext4_split_extent_at(handle_t *handle,
+ 	if (split_flag & EXT4_EXT_MARK_UNWRIT2)
+ 		ext4_ext_mark_unwritten(ex2);
+ 
+-	err = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
++	err = ext4_ext_insert_extent(handle, inode, ppath, &newex, flags);
+ 	if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) {
+ 		if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) {
+ 			if (split_flag & EXT4_EXT_DATA_VALID1) {
+@@ -3279,11 +3280,12 @@ static int ext4_split_extent_at(handle_t *handle,
+  */
+ static int ext4_split_extent(handle_t *handle,
+ 			      struct inode *inode,
+-			      struct ext4_ext_path *path,
++			      struct ext4_ext_path **ppath,
+ 			      struct ext4_map_blocks *map,
+ 			      int split_flag,
+ 			      int flags)
+ {
++	struct ext4_ext_path *path = *ppath;
+ 	ext4_lblk_t ee_block;
+ 	struct ext4_extent *ex;
+ 	unsigned int ee_len, depth;
+@@ -3306,7 +3308,7 @@ static int ext4_split_extent(handle_t *handle,
+ 				       EXT4_EXT_MARK_UNWRIT2;
+ 		if (split_flag & EXT4_EXT_DATA_VALID2)
+ 			split_flag1 |= EXT4_EXT_DATA_VALID1;
+-		err = ext4_split_extent_at(handle, inode, path,
++		err = ext4_split_extent_at(handle, inode, ppath,
+ 				map->m_lblk + map->m_len, split_flag1, flags1);
+ 		if (err)
+ 			goto out;
+@@ -3318,8 +3320,7 @@ static int ext4_split_extent(handle_t *handle,
+ 	 * result in split of original leaf or extent zeroout.
+ 	 */
+ 	ext4_ext_drop_refs(path);
+-	path = ext4_ext_find_extent(inode, map->m_lblk, &path,
+-				    EXT4_EX_NOFREE_ON_ERR);
++	path = ext4_ext_find_extent(inode, map->m_lblk, ppath, 0);
+ 	if (IS_ERR(path))
+ 		return PTR_ERR(path);
+ 	depth = ext_depth(inode);
+@@ -3339,7 +3340,7 @@ static int ext4_split_extent(handle_t *handle,
+ 			split_flag1 |= split_flag & (EXT4_EXT_MAY_ZEROOUT |
+ 						     EXT4_EXT_MARK_UNWRIT2);
+ 		}
+-		err = ext4_split_extent_at(handle, inode, path,
++		err = ext4_split_extent_at(handle, inode, ppath,
+ 				map->m_lblk, split_flag1, flags);
+ 		if (err)
+ 			goto out;
+@@ -3373,9 +3374,10 @@ static int ext4_split_extent(handle_t *handle,
+ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 					   struct inode *inode,
+ 					   struct ext4_map_blocks *map,
+-					   struct ext4_ext_path *path,
++					   struct ext4_ext_path **ppath,
+ 					   int flags)
+ {
++	struct ext4_ext_path *path = *ppath;
+ 	struct ext4_sb_info *sbi;
+ 	struct ext4_extent_header *eh;
+ 	struct ext4_map_blocks split_map;
+@@ -3599,7 +3601,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 		}
+ 	}
+ 
+-	allocated = ext4_split_extent(handle, inode, path,
++	allocated = ext4_split_extent(handle, inode, ppath,
+ 				      &split_map, split_flag, flags);
+ 	if (allocated < 0)
+ 		err = allocated;
+@@ -3638,9 +3640,10 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ static int ext4_split_convert_extents(handle_t *handle,
+ 					struct inode *inode,
+ 					struct ext4_map_blocks *map,
+-					struct ext4_ext_path *path,
++					struct ext4_ext_path **ppath,
+ 					int flags)
+ {
++	struct ext4_ext_path *path = *ppath;
+ 	ext4_lblk_t eof_block;
+ 	ext4_lblk_t ee_block;
+ 	struct ext4_extent *ex;
+@@ -3674,14 +3677,15 @@ static int ext4_split_convert_extents(handle_t *handle,
+ 		split_flag |= (EXT4_EXT_MARK_UNWRIT2 | EXT4_EXT_DATA_VALID2);
+ 	}
+ 	flags |= EXT4_GET_BLOCKS_PRE_IO;
+-	return ext4_split_extent(handle, inode, path, map, split_flag, flags);
++	return ext4_split_extent(handle, inode, ppath, map, split_flag, flags);
+ }
+ 
+ static int ext4_convert_unwritten_extents_endio(handle_t *handle,
+ 						struct inode *inode,
+ 						struct ext4_map_blocks *map,
+-						struct ext4_ext_path *path)
++						struct ext4_ext_path **ppath)
+ {
++	struct ext4_ext_path *path = *ppath;
+ 	struct ext4_extent *ex;
+ 	ext4_lblk_t ee_block;
+ 	unsigned int ee_len;
+@@ -3710,17 +3714,14 @@ static int ext4_convert_unwritten_extents_endio(handle_t *handle,
+ 			     inode->i_ino, (unsigned long long)ee_block, ee_len,
+ 			     (unsigned long long)map->m_lblk, map->m_len);
+ #endif
+-		err = ext4_split_convert_extents(handle, inode, map, path,
++		err = ext4_split_convert_extents(handle, inode, map, ppath,
+ 						 EXT4_GET_BLOCKS_CONVERT);
+ 		if (err < 0)
+-			goto out;
++			return err;
+ 		ext4_ext_drop_refs(path);
+-		path = ext4_ext_find_extent(inode, map->m_lblk, &path,
+-					    EXT4_EX_NOFREE_ON_ERR);
+-		if (IS_ERR(path)) {
+-			err = PTR_ERR(path);
+-			goto out;
+-		}
++		path = ext4_ext_find_extent(inode, map->m_lblk, ppath, 0);
++		if (IS_ERR(path))
++			return PTR_ERR(path);
+ 		depth = ext_depth(inode);
+ 		ex = path[depth].p_ext;
+ 	}
+@@ -3942,7 +3943,7 @@ convert_initialized_extent(handle_t *handle, struct inode *inode,
+ 		  (unsigned long long)ee_block, ee_len);
+ 
+ 	if (ee_block != map->m_lblk || ee_len > map->m_len) {
+-		err = ext4_split_convert_extents(handle, inode, map, path,
++		err = ext4_split_convert_extents(handle, inode, map, ppath,
+ 				EXT4_GET_BLOCKS_CONVERT_UNWRITTEN);
+ 		if (err < 0)
+ 			return err;
+@@ -3990,9 +3991,10 @@ convert_initialized_extent(handle_t *handle, struct inode *inode,
+ static int
+ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode,
+ 			struct ext4_map_blocks *map,
+-			struct ext4_ext_path *path, int flags,
++			struct ext4_ext_path **ppath, int flags,
+ 			unsigned int allocated, ext4_fsblk_t newblock)
+ {
++	struct ext4_ext_path *path = *ppath;
+ 	int ret = 0;
+ 	int err = 0;
+ 	ext4_io_end_t *io = ext4_inode_aio(inode);
+@@ -4014,8 +4016,8 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode,
+ 
+ 	/* get_block() before submit the IO, split the extent */
+ 	if (flags & EXT4_GET_BLOCKS_PRE_IO) {
+-		ret = ext4_split_convert_extents(handle, inode, map,
+-					 path, flags | EXT4_GET_BLOCKS_CONVERT);
++		ret = ext4_split_convert_extents(handle, inode, map, ppath,
++					 flags | EXT4_GET_BLOCKS_CONVERT);
+ 		if (ret <= 0)
+ 			goto out;
+ 		/*
+@@ -4033,7 +4035,7 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode,
+ 	/* IO end_io complete, convert the filled extent to written */
+ 	if (flags & EXT4_GET_BLOCKS_CONVERT) {
+ 		ret = ext4_convert_unwritten_extents_endio(handle, inode, map,
+-							path);
++							   ppath);
+ 		if (ret >= 0) {
+ 			ext4_update_inode_fsync_trans(handle, inode, 1);
+ 			err = check_eofblocks_fl(handle, inode, map->m_lblk,
+@@ -4071,7 +4073,7 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode,
+ 	}
+ 
+ 	/* buffered write, writepage time, convert*/
+-	ret = ext4_ext_convert_to_initialized(handle, inode, map, path, flags);
++	ret = ext4_ext_convert_to_initialized(handle, inode, map, ppath, flags);
+ 	if (ret >= 0)
+ 		ext4_update_inode_fsync_trans(handle, inode, 1);
+ out:
+@@ -4332,7 +4334,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 				goto out;
+ 
+ 			ret = ext4_ext_handle_unwritten_extents(
+-				handle, inode, map, path, flags,
++				handle, inode, map, &path, flags,
+ 				allocated, newblock);
+ 			if (ret < 0)
+ 				err = ret;
+@@ -4479,7 +4481,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 		err = check_eofblocks_fl(handle, inode, map->m_lblk,
+ 					 path, ar.len);
+ 	if (!err)
+-		err = ext4_ext_insert_extent(handle, inode, path,
++		err = ext4_ext_insert_extent(handle, inode, &path,
+ 					     &newex, flags);
+ 
+ 	if (!err && set_unwritten) {
+@@ -5611,18 +5613,18 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
+ 		if (e1_blk < lblk1) {
+ 			split = 1;
+ 			*erp = ext4_force_split_extent_at(handle, inode1,
+-						path1, lblk1, 0);
++						&path1, lblk1, 0);
+ 			if (unlikely(*erp))
+ 				goto finish;
+ 		}
+ 		if (e2_blk < lblk2) {
+ 			split = 1;
+ 			*erp = ext4_force_split_extent_at(handle, inode2,
+-						path2,  lblk2, 0);
++						&path2,  lblk2, 0);
+ 			if (unlikely(*erp))
+ 				goto finish;
+ 		}
+-		/* ext4_split_extent_at() may retult in leaf extent split,
++		/* ext4_split_extent_at() may result in leaf extent split,
+ 		 * path must to be revalidated. */
+ 		if (split)
+ 			goto repeat;
+@@ -5637,18 +5639,18 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
+ 		if (len != e1_len) {
+ 			split = 1;
+ 			*erp = ext4_force_split_extent_at(handle, inode1,
+-						path1, lblk1 + len, 0);
++						&path1, lblk1 + len, 0);
+ 			if (unlikely(*erp))
+ 				goto finish;
+ 		}
+ 		if (len != e2_len) {
+ 			split = 1;
+ 			*erp = ext4_force_split_extent_at(handle, inode2,
+-						path2, lblk2 + len, 0);
++						&path2, lblk2 + len, 0);
+ 			if (*erp)
+ 				goto finish;
+ 		}
+-		/* ext4_split_extent_at() may retult in leaf extent split,
++		/* ext4_split_extent_at() may result in leaf extent split,
+ 		 * path must to be revalidated. */
+ 		if (split)
+ 			goto repeat;
+diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
+index d3567f27bae7..aff7bdfdc461 100644
+--- a/fs/ext4/migrate.c
++++ b/fs/ext4/migrate.c
+@@ -81,7 +81,7 @@ static int finish_range(handle_t *handle, struct inode *inode,
+ 				goto err_out;
+ 		}
+ 	}
+-	retval = ext4_ext_insert_extent(handle, inode, path, &newext, 0);
++	retval = ext4_ext_insert_extent(handle, inode, &path, &newext, 0);
+ err_out:
+ 	up_write((&EXT4_I(inode)->i_data_sem));
+ 	if (path) {

commit 4f224b8b7be6856a3ceaf7f9d9c1860d467174ae
+Author: Theodore Ts'o 
+Date:   Mon Sep 1 14:36:09 2014 -0400
+
+    ext4: drop EXT4_EX_NOFREE_ON_ERR in convert_initialized_extent()
+    
+    Transfer responsibility of freeing struct ext4_ext_path on error to
+    ext4_ext_find_extent().
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 5fc5e2b6e3a7..acb92ac47220 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -3915,9 +3915,10 @@ get_reserved_cluster_alloc(struct inode *inode, ext4_lblk_t lblk_start,
+ static int
+ convert_initialized_extent(handle_t *handle, struct inode *inode,
+ 			   struct ext4_map_blocks *map,
+-			   struct ext4_ext_path *path, int flags,
++			   struct ext4_ext_path **ppath, int flags,
+ 			   unsigned int allocated, ext4_fsblk_t newblock)
+ {
++	struct ext4_ext_path *path = *ppath;
+ 	struct ext4_extent *ex;
+ 	ext4_lblk_t ee_block;
+ 	unsigned int ee_len;
+@@ -3946,8 +3947,7 @@ convert_initialized_extent(handle_t *handle, struct inode *inode,
+ 		if (err < 0)
+ 			return err;
+ 		ext4_ext_drop_refs(path);
+-		path = ext4_ext_find_extent(inode, map->m_lblk, &path,
+-					    EXT4_EX_NOFREE_ON_ERR);
++		path = ext4_ext_find_extent(inode, map->m_lblk, ppath, 0);
+ 		if (IS_ERR(path))
+ 			return PTR_ERR(path);
+ 		depth = ext_depth(inode);
+@@ -4325,8 +4325,8 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 			if ((!ext4_ext_is_unwritten(ex)) &&
+ 			    (flags & EXT4_GET_BLOCKS_CONVERT_UNWRITTEN)) {
+ 				allocated = convert_initialized_extent(
+-						handle, inode, map, path, flags,
+-						allocated, newblock);
++						handle, inode, map, &path,
++						flags, allocated, newblock);
+ 				goto out2;
+ 			} else if (!ext4_ext_is_unwritten(ex))
+ 				goto out;

commit e8b83d9303317fb068ad83d87991b610fe990ed5
+Author: Theodore Ts'o 
+Date:   Mon Sep 1 14:35:09 2014 -0400
+
+    ext4: collapse ext4_convert_initialized_extents()
+    
+    The function ext4_convert_initialized_extents() is only called by a
+    single function --- ext4_ext_convert_initalized_extents().  Inline the
+    code and get rid of the unnecessary bits in order to simplify the code.
+    
+    Rename ext4_ext_convert_initalized_extents() to
+    convert_initalized_extents() since it's a static function that is
+    actually only used in a single caller, ext4_ext_map_blocks().
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 0ced78c974e2..5fc5e2b6e3a7 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -3677,67 +3677,6 @@ static int ext4_split_convert_extents(handle_t *handle,
+ 	return ext4_split_extent(handle, inode, path, map, split_flag, flags);
+ }
+ 
+-static int ext4_convert_initialized_extents(handle_t *handle,
+-					    struct inode *inode,
+-					    struct ext4_map_blocks *map,
+-					    struct ext4_ext_path *path)
+-{
+-	struct ext4_extent *ex;
+-	ext4_lblk_t ee_block;
+-	unsigned int ee_len;
+-	int depth;
+-	int err = 0;
+-
+-	depth = ext_depth(inode);
+-	ex = path[depth].p_ext;
+-	ee_block = le32_to_cpu(ex->ee_block);
+-	ee_len = ext4_ext_get_actual_len(ex);
+-
+-	ext_debug("%s: inode %lu, logical"
+-		"block %llu, max_blocks %u\n", __func__, inode->i_ino,
+-		  (unsigned long long)ee_block, ee_len);
+-
+-	if (ee_block != map->m_lblk || ee_len > map->m_len) {
+-		err = ext4_split_convert_extents(handle, inode, map, path,
+-				EXT4_GET_BLOCKS_CONVERT_UNWRITTEN);
+-		if (err < 0)
+-			goto out;
+-		ext4_ext_drop_refs(path);
+-		path = ext4_ext_find_extent(inode, map->m_lblk, &path,
+-					    EXT4_EX_NOFREE_ON_ERR);
+-		if (IS_ERR(path)) {
+-			err = PTR_ERR(path);
+-			goto out;
+-		}
+-		depth = ext_depth(inode);
+-		ex = path[depth].p_ext;
+-		if (!ex) {
+-			EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
+-					 (unsigned long) map->m_lblk);
+-			err = -EIO;
+-			goto out;
+-		}
+-	}
+-
+-	err = ext4_ext_get_access(handle, inode, path + depth);
+-	if (err)
+-		goto out;
+-	/* first mark the extent as unwritten */
+-	ext4_ext_mark_unwritten(ex);
+-
+-	/* note: ext4_ext_correct_indexes() isn't needed here because
+-	 * borders are not changed
+-	 */
+-	ext4_ext_try_to_merge(handle, inode, path, ex);
+-
+-	/* Mark modified extent as dirty */
+-	err = ext4_ext_dirty(handle, inode, path + path->p_depth);
+-out:
+-	ext4_ext_show_leaf(inode, path);
+-	return err;
+-}
+-
+-
+ static int ext4_convert_unwritten_extents_endio(handle_t *handle,
+ 						struct inode *inode,
+ 						struct ext4_map_blocks *map,
+@@ -3974,12 +3913,15 @@ get_reserved_cluster_alloc(struct inode *inode, ext4_lblk_t lblk_start,
+ }
+ 
+ static int
+-ext4_ext_convert_initialized_extent(handle_t *handle, struct inode *inode,
+-			struct ext4_map_blocks *map,
+-			struct ext4_ext_path *path, int flags,
+-			unsigned int allocated, ext4_fsblk_t newblock)
++convert_initialized_extent(handle_t *handle, struct inode *inode,
++			   struct ext4_map_blocks *map,
++			   struct ext4_ext_path *path, int flags,
++			   unsigned int allocated, ext4_fsblk_t newblock)
+ {
+-	int ret = 0;
++	struct ext4_extent *ex;
++	ext4_lblk_t ee_block;
++	unsigned int ee_len;
++	int depth;
+ 	int err = 0;
+ 
+ 	/*
+@@ -3989,20 +3931,60 @@ ext4_ext_convert_initialized_extent(handle_t *handle, struct inode *inode,
+ 	if (map->m_len > EXT_UNWRITTEN_MAX_LEN)
+ 		map->m_len = EXT_UNWRITTEN_MAX_LEN / 2;
+ 
+-	ret = ext4_convert_initialized_extents(handle, inode, map,
+-						path);
+-	if (ret >= 0) {
+-		ext4_update_inode_fsync_trans(handle, inode, 1);
+-		err = check_eofblocks_fl(handle, inode, map->m_lblk,
+-					 path, map->m_len);
+-	} else
+-		err = ret;
++	depth = ext_depth(inode);
++	ex = path[depth].p_ext;
++	ee_block = le32_to_cpu(ex->ee_block);
++	ee_len = ext4_ext_get_actual_len(ex);
++
++	ext_debug("%s: inode %lu, logical"
++		"block %llu, max_blocks %u\n", __func__, inode->i_ino,
++		  (unsigned long long)ee_block, ee_len);
++
++	if (ee_block != map->m_lblk || ee_len > map->m_len) {
++		err = ext4_split_convert_extents(handle, inode, map, path,
++				EXT4_GET_BLOCKS_CONVERT_UNWRITTEN);
++		if (err < 0)
++			return err;
++		ext4_ext_drop_refs(path);
++		path = ext4_ext_find_extent(inode, map->m_lblk, &path,
++					    EXT4_EX_NOFREE_ON_ERR);
++		if (IS_ERR(path))
++			return PTR_ERR(path);
++		depth = ext_depth(inode);
++		ex = path[depth].p_ext;
++		if (!ex) {
++			EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
++					 (unsigned long) map->m_lblk);
++			return -EIO;
++		}
++	}
++
++	err = ext4_ext_get_access(handle, inode, path + depth);
++	if (err)
++		return err;
++	/* first mark the extent as unwritten */
++	ext4_ext_mark_unwritten(ex);
++
++	/* note: ext4_ext_correct_indexes() isn't needed here because
++	 * borders are not changed
++	 */
++	ext4_ext_try_to_merge(handle, inode, path, ex);
++
++	/* Mark modified extent as dirty */
++	err = ext4_ext_dirty(handle, inode, path + path->p_depth);
++	if (err)
++		return err;
++	ext4_ext_show_leaf(inode, path);
++
++	ext4_update_inode_fsync_trans(handle, inode, 1);
++	err = check_eofblocks_fl(handle, inode, map->m_lblk, path, map->m_len);
++	if (err)
++		return err;
+ 	map->m_flags |= EXT4_MAP_UNWRITTEN;
+ 	if (allocated > map->m_len)
+ 		allocated = map->m_len;
+ 	map->m_len = allocated;
+-
+-	return err ? err : allocated;
++	return allocated;
+ }
+ 
+ static int
+@@ -4342,7 +4324,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 			 */
+ 			if ((!ext4_ext_is_unwritten(ex)) &&
+ 			    (flags & EXT4_GET_BLOCKS_CONVERT_UNWRITTEN)) {
+-				allocated = ext4_ext_convert_initialized_extent(
++				allocated = convert_initialized_extent(
+ 						handle, inode, map, path, flags,
+ 						allocated, newblock);
+ 				goto out2;

commit 705912ca95f4bbdbb3be753e46bf30d6be15a5e8
+Author: Theodore Ts'o 
+Date:   Mon Sep 1 14:34:09 2014 -0400
+
+    ext4: teach ext4_ext_find_extent() to free path on error
+    
+    Right now, there are a places where it is all to easy to leak memory
+    on an error path, via a usage like this:
+    
+            struct ext4_ext_path *path = NULL
+    
+            while (...) {
+                    ...
+                    path = ext4_ext_find_extent(inode, block, path, 0);
+                    if (IS_ERR(path)) {
+                            /* oops, if path was non-NULL before the call to
+                               ext4_ext_find_extent, we've leaked it!  :-(  */
+                            ...
+                            return PTR_ERR(path);
+                    }
+                    ...
+            }
+    
+    Unfortunately, there some code paths where we are doing the following
+    instead:
+    
+            path = ext4_ext_find_extent(inode, block, orig_path, 0);
+    
+    and where it's important that we _not_ free orig_path in the case
+    where ext4_ext_find_extent() returns an error.
+    
+    So change the function signature of ext4_ext_find_extent() so that it
+    takes a struct ext4_ext_path ** for its third argument, and by
+    default, on an error, it will free the struct ext4_ext_path, and then
+    zero out the struct ext4_ext_path * pointer.  In order to avoid
+    causing problems, we add a flag EXT4_EX_NOFREE_ON_ERR which causes
+    ext4_ext_find_extent() to use the original behavior of forcing the
+    caller to deal with freeing the original path pointer on the error
+    case.
+    
+    The goal is to get rid of EXT4_EX_NOFREE_ON_ERR entirely, but this
+    allows for a gentle transition and makes the patches easier to verify.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 550b4f99a843..696e51ae02fa 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -582,6 +582,7 @@ enum {
+  */
+ #define EXT4_EX_NOCACHE				0x0800
+ #define EXT4_EX_FORCE_CACHE			0x1000
++#define EXT4_EX_NOFREE_ON_ERR			0x2000
+ 
+ /*
+  * Flags used by ext4_free_blocks
+@@ -2733,7 +2734,7 @@ extern int ext4_ext_insert_extent(handle_t *, struct inode *,
+ 				  struct ext4_ext_path *,
+ 				  struct ext4_extent *, int);
+ extern struct ext4_ext_path *ext4_ext_find_extent(struct inode *, ext4_lblk_t,
+-						  struct ext4_ext_path *,
++						  struct ext4_ext_path **,
+ 						  int flags);
+ extern void ext4_ext_drop_refs(struct ext4_ext_path *);
+ extern int ext4_ext_check_inode(struct inode *inode);
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index bf205f72be35..0ced78c974e2 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -855,11 +855,13 @@ int ext4_ext_tree_init(handle_t *handle, struct inode *inode)
+ 
+ struct ext4_ext_path *
+ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
+-		     struct ext4_ext_path *path, int flags)
++		     struct ext4_ext_path **orig_path, int flags)
+ {
+ 	struct ext4_extent_header *eh;
+ 	struct buffer_head *bh;
+-	short int depth, i, ppos = 0, alloc = 0;
++	struct ext4_ext_path *path = orig_path ? *orig_path : NULL;
++	short int depth, i, ppos = 0;
++	short free_on_err = (flags & EXT4_EX_NOFREE_ON_ERR) == 0;
+ 	int ret;
+ 
+ 	eh = ext_inode_hdr(inode);
+@@ -871,7 +873,7 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
+ 				GFP_NOFS);
+ 		if (unlikely(!path))
+ 			return ERR_PTR(-ENOMEM);
+-		alloc = 1;
++		free_on_err = 1;
+ 	}
+ 	path[0].p_hdr = eh;
+ 	path[0].p_bh = NULL;
+@@ -923,8 +925,11 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
+ 
+ err:
+ 	ext4_ext_drop_refs(path);
+-	if (alloc)
++	if (free_on_err) {
+ 		kfree(path);
++		if (orig_path)
++			*orig_path = NULL;
++	}
+ 	return ERR_PTR(ret);
+ }
+ 
+@@ -1356,7 +1361,7 @@ static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
+ 		ext4_ext_drop_refs(path);
+ 		path = ext4_ext_find_extent(inode,
+ 				    (ext4_lblk_t)le32_to_cpu(newext->ee_block),
+-				    path, gb_flags);
++				    &path, gb_flags | EXT4_EX_NOFREE_ON_ERR);
+ 		if (IS_ERR(path))
+ 			err = PTR_ERR(path);
+ 	} else {
+@@ -1369,7 +1374,7 @@ static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
+ 		ext4_ext_drop_refs(path);
+ 		path = ext4_ext_find_extent(inode,
+ 				   (ext4_lblk_t)le32_to_cpu(newext->ee_block),
+-				    path, gb_flags);
++				    &path, gb_flags | EXT4_EX_NOFREE_ON_ERR);
+ 		if (IS_ERR(path)) {
+ 			err = PTR_ERR(path);
+ 			goto out;
+@@ -2152,7 +2157,7 @@ static int ext4_fill_fiemap_extents(struct inode *inode,
+ 			path = NULL;
+ 		}
+ 
+-		path = ext4_ext_find_extent(inode, block, path, 0);
++		path = ext4_ext_find_extent(inode, block, &path, 0);
+ 		if (IS_ERR(path)) {
+ 			up_read(&EXT4_I(inode)->i_data_sem);
+ 			err = PTR_ERR(path);
+@@ -3313,7 +3318,8 @@ static int ext4_split_extent(handle_t *handle,
+ 	 * result in split of original leaf or extent zeroout.
+ 	 */
+ 	ext4_ext_drop_refs(path);
+-	path = ext4_ext_find_extent(inode, map->m_lblk, path, 0);
++	path = ext4_ext_find_extent(inode, map->m_lblk, &path,
++				    EXT4_EX_NOFREE_ON_ERR);
+ 	if (IS_ERR(path))
+ 		return PTR_ERR(path);
+ 	depth = ext_depth(inode);
+@@ -3697,7 +3703,8 @@ static int ext4_convert_initialized_extents(handle_t *handle,
+ 		if (err < 0)
+ 			goto out;
+ 		ext4_ext_drop_refs(path);
+-		path = ext4_ext_find_extent(inode, map->m_lblk, path, 0);
++		path = ext4_ext_find_extent(inode, map->m_lblk, &path,
++					    EXT4_EX_NOFREE_ON_ERR);
+ 		if (IS_ERR(path)) {
+ 			err = PTR_ERR(path);
+ 			goto out;
+@@ -3769,7 +3776,8 @@ static int ext4_convert_unwritten_extents_endio(handle_t *handle,
+ 		if (err < 0)
+ 			goto out;
+ 		ext4_ext_drop_refs(path);
+-		path = ext4_ext_find_extent(inode, map->m_lblk, path, 0);
++		path = ext4_ext_find_extent(inode, map->m_lblk, &path,
++					    EXT4_EX_NOFREE_ON_ERR);
+ 		if (IS_ERR(path)) {
+ 			err = PTR_ERR(path);
+ 			goto out;
+diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
+index c8f895b410f6..5e2465a8e4ce 100644
+--- a/fs/ext4/move_extent.c
++++ b/fs/ext4/move_extent.c
+@@ -37,7 +37,7 @@ get_ext_path(struct inode *inode, ext4_lblk_t lblock,
+ 	int ret = 0;
+ 	struct ext4_ext_path *path;
+ 
+-	path = ext4_ext_find_extent(inode, lblock, *orig_path, EXT4_EX_NOCACHE);
++	path = ext4_ext_find_extent(inode, lblock, orig_path, EXT4_EX_NOCACHE);
+ 	if (IS_ERR(path))
+ 		ret = PTR_ERR(path);
+ 	else if (path[ext_depth(inode)].p_ext == NULL)

commit bd30d702fc320085f178d22866b32fdc4736c991
+Author: Theodore Ts'o 
+Date:   Mon Sep 1 14:33:09 2014 -0400
+
+    ext4: fix accidental flag aliasing in ext4_map_blocks flags
+    
+    Commit b8a8684502a0f introduced an accidental flag aliasing between
+    EXT4_EX_NOCACHE and EXT4_GET_BLOCKS_CONVERT_UNWRITTEN.
+    
+    Fortunately, this didn't introduce any untorward side effects --- we
+    got lucky.  Nevertheless, fix this and leave a warning to hopefully
+    avoid this from happening in the future.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index cf3ad75d3015..550b4f99a843 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -569,6 +569,7 @@ enum {
+ #define EXT4_GET_BLOCKS_NO_PUT_HOLE		0x0200
+ 	/* Convert written extents to unwritten */
+ #define EXT4_GET_BLOCKS_CONVERT_UNWRITTEN	0x0400
++/* DO NOT ASSIGN ADDITIONAL FLAG VALUES WITHOUT ADJUSTING THE FLAGS BELOW */
+ 
+ /*
+  * The bit position of these flags must not overlap with any of the
+@@ -579,8 +580,8 @@ enum {
+  * caching the extents when reading from the extent tree while a
+  * truncate or punch hole operation is in progress.
+  */
+-#define EXT4_EX_NOCACHE				0x0400
+-#define EXT4_EX_FORCE_CACHE			0x0800
++#define EXT4_EX_NOCACHE				0x0800
++#define EXT4_EX_FORCE_CACHE			0x1000
+ 
+ /*
+  * Flags used by ext4_free_blocks

commit 713e8dde3e71e92db2d8cc8459d236ce1fb576ce
+Author: Theodore Ts'o 
+Date:   Mon Sep 1 14:32:09 2014 -0400
+
+    ext4: fix ZERO_RANGE bug hidden by flag aliasing
+    
+    We accidently aliased EXT4_EX_NOCACHE and EXT4_GET_CONVERT_UNWRITTEN
+    falgs, which apparently was hiding a bug that was unmasked when this
+    flag aliasing issue was addressed (see the subsequent commit).  The
+    reproduction case was:
+    
+       fsx -N 10000 -l 500000 -r 4096 -t 4096 -w 4096 -Z -R -W /vdb/junk
+    
+    ... which would cause fsx to report corruption in the data file.
+    
+    The fix we have is a bit of an overkill, but I'd much rather be
+    conservative for now, and we can optimize ZERO_RANGE_FL handling
+    later.  The fact that we need to zap the extent_status cache for the
+    inode is unfortunate, but correctness is far more important than
+    performance.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: Namjae Jeon 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index d00937336f19..bf205f72be35 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -4802,7 +4802,8 @@ static long ext4_zero_range(struct file *file, loff_t offset,
+ 		max_blocks -= lblk;
+ 
+ 	flags = EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT |
+-		EXT4_GET_BLOCKS_CONVERT_UNWRITTEN;
++		EXT4_GET_BLOCKS_CONVERT_UNWRITTEN |
++		EXT4_EX_NOCACHE;
+ 	if (mode & FALLOC_FL_KEEP_SIZE)
+ 		flags |= EXT4_GET_BLOCKS_KEEP_SIZE;
+ 
+@@ -4840,15 +4841,21 @@ static long ext4_zero_range(struct file *file, loff_t offset,
+ 		ext4_inode_block_unlocked_dio(inode);
+ 		inode_dio_wait(inode);
+ 
++		ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size,
++					     flags, mode);
++		if (ret)
++			goto out_dio;
+ 		/*
+ 		 * Remove entire range from the extent status tree.
++		 *
++		 * ext4_es_remove_extent(inode, lblk, max_blocks) is
++		 * NOT sufficient.  I'm not sure why this is the case,
++		 * but let's be conservative and remove the extent
++		 * status tree for the entire inode.  There should be
++		 * no outstanding delalloc extents thanks to the
++		 * filemap_write_and_wait_range() call above.
+ 		 */
+-		ret = ext4_es_remove_extent(inode, lblk, max_blocks);
+-		if (ret)
+-			goto out_dio;
+-
+-		ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size,
+-					     flags, mode);
++		ret = ext4_es_remove_extent(inode, 0, EXT_MAX_BLOCKS);
+ 		if (ret)
+ 			goto out_dio;
+ 	}

commit 19008f6dfa16d23afcd09dceaa598bb6da8de4b1
+Author: Theodore Ts'o 
+Date:   Sun Aug 31 15:03:14 2014 -0400
+
+    ext4: fix ext4_swap_extents() error handling
+    
+    If ext4_ext_find_extent() returns an error, we have to clear path1 or
+    path2 or else we would end up trying to free an ERR_PTR, which would
+    be bad.
+    
+    Also eliminate some redundant code and mark the error paths as unlikely()
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 73d9ae9a16db..d00937336f19 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -869,7 +869,7 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
+ 	if (!path) {
+ 		path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 2),
+ 				GFP_NOFS);
+-		if (!path)
++		if (unlikely(!path))
+ 			return ERR_PTR(-ENOMEM);
+ 		alloc = 1;
+ 	}
+@@ -889,7 +889,7 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
+ 
+ 		bh = read_extent_tree_block(inode, path[ppos].p_block, --i,
+ 					    flags);
+-		if (IS_ERR(bh)) {
++		if (unlikely(IS_ERR(bh))) {
+ 			ret = PTR_ERR(bh);
+ 			goto err;
+ 		}
+@@ -5545,10 +5545,10 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
+ 	BUG_ON(!mutex_is_locked(&inode1->i_mutex));
+ 
+ 	*erp = ext4_es_remove_extent(inode1, lblk1, count);
+-	if (*erp)
++	if (unlikely(*erp))
+ 		return 0;
+ 	*erp = ext4_es_remove_extent(inode2, lblk2, count);
+-	if (*erp)
++	if (unlikely(*erp))
+ 		return 0;
+ 
+ 	while (count) {
+@@ -5558,20 +5558,24 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
+ 		int split = 0;
+ 
+ 		path1 = ext4_ext_find_extent(inode1, lblk1, NULL, EXT4_EX_NOCACHE);
+-		if (IS_ERR(path1)) {
++		if (unlikely(IS_ERR(path1))) {
+ 			*erp = PTR_ERR(path1);
+-			break;
++			path1 = NULL;
++		finish:
++			count = 0;
++			goto repeat;
+ 		}
+ 		path2 = ext4_ext_find_extent(inode2, lblk2, NULL, EXT4_EX_NOCACHE);
+-		if (IS_ERR(path2)) {
++		if (unlikely(IS_ERR(path2))) {
+ 			*erp = PTR_ERR(path2);
+-			break;
++			path2 = NULL;
++			goto finish;
+ 		}
+ 		ex1 = path1[path1->p_depth].p_ext;
+ 		ex2 = path2[path2->p_depth].p_ext;
+ 		/* Do we have somthing to swap ? */
+ 		if (unlikely(!ex2 || !ex1))
+-			break;
++			goto finish;
+ 
+ 		e1_blk = le32_to_cpu(ex1->ee_block);
+ 		e2_blk = le32_to_cpu(ex2->ee_block);
+@@ -5593,7 +5597,7 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
+ 				next2 = e1_blk;
+ 			/* Do we have something to swap */
+ 			if (next1 == EXT_MAX_BLOCKS || next2 == EXT_MAX_BLOCKS)
+-				break;
++				goto finish;
+ 			/* Move to the rightest boundary */
+ 			len = next1 - lblk1;
+ 			if (len < next2 - lblk2)
+@@ -5611,15 +5615,15 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
+ 			split = 1;
+ 			*erp = ext4_force_split_extent_at(handle, inode1,
+ 						path1, lblk1, 0);
+-			if (*erp)
+-				break;
++			if (unlikely(*erp))
++				goto finish;
+ 		}
+ 		if (e2_blk < lblk2) {
+ 			split = 1;
+ 			*erp = ext4_force_split_extent_at(handle, inode2,
+ 						path2,  lblk2, 0);
+-			if (*erp)
+-				break;
++			if (unlikely(*erp))
++				goto finish;
+ 		}
+ 		/* ext4_split_extent_at() may retult in leaf extent split,
+ 		 * path must to be revalidated. */
+@@ -5637,15 +5641,15 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
+ 			split = 1;
+ 			*erp = ext4_force_split_extent_at(handle, inode1,
+ 						path1, lblk1 + len, 0);
+-			if (*erp)
+-				break;
++			if (unlikely(*erp))
++				goto finish;
+ 		}
+ 		if (len != e2_len) {
+ 			split = 1;
+ 			*erp = ext4_force_split_extent_at(handle, inode2,
+ 						path2, lblk2 + len, 0);
+ 			if (*erp)
+-				break;
++				goto finish;
+ 		}
+ 		/* ext4_split_extent_at() may retult in leaf extent split,
+ 		 * path must to be revalidated. */
+@@ -5654,11 +5658,11 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
+ 
+ 		BUG_ON(e2_len != e1_len);
+ 		*erp = ext4_ext_get_access(handle, inode1, path1 + path1->p_depth);
+-		if (*erp)
+-			break;
++		if (unlikely(*erp))
++			goto finish;
+ 		*erp = ext4_ext_get_access(handle, inode2, path2 + path2->p_depth);
+-		if (*erp)
+-			break;
++		if (unlikely(*erp))
++			goto finish;
+ 
+ 		/* Both extents are fully inside boundaries. Swap it now */
+ 		tmp_ex = *ex1;
+@@ -5675,8 +5679,8 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
+ 		ext4_ext_try_to_merge(handle, inode1, path1, ex1);
+ 		*erp = ext4_ext_dirty(handle, inode2, path2 +
+ 				      path2->p_depth);
+-		if (*erp)
+-			break;
++		if (unlikely(*erp))
++			goto finish;
+ 		*erp = ext4_ext_dirty(handle, inode1, path1 +
+ 				      path1->p_depth);
+ 		/*
+@@ -5685,8 +5689,8 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
+ 		 * only due to journal error, so full transaction will be
+ 		 * aborted anyway.
+ 		 */
+-		if (*erp)
+-			break;
++		if (unlikely(*erp))
++			goto finish;
+ 		lblk1 += len;
+ 		lblk2 += len;
+ 		replaced_count += len;
+@@ -5704,13 +5708,5 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
+ 			path2 = NULL;
+ 		}
+ 	}
+-	if (path1) {
+-		ext4_ext_drop_refs(path1);
+-		kfree(path1);
+-	}
+-	if (path2) {
+-		ext4_ext_drop_refs(path2);
+-		kfree(path2);
+-	}
+ 	return replaced_count;
+ }

commit f8b3b59d4d561368cf8c92d50218fc0d5be7cb46
+Author: Theodore Ts'o 
+Date:   Fri Aug 29 20:52:18 2014 -0400
+
+    ext4: convert do_split() to use the ERR_PTR convention
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index e6d51655ffcd..dec92b675b35 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1509,7 +1509,7 @@ static struct ext4_dir_entry_2* dx_pack_dirents(char *base, unsigned blocksize)
+  */
+ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
+ 			struct buffer_head **bh,struct dx_frame *frame,
+-			struct dx_hash_info *hinfo, int *error)
++			struct dx_hash_info *hinfo)
+ {
+ 	unsigned blocksize = dir->i_sb->s_blocksize;
+ 	unsigned count, continued;
+@@ -1532,8 +1532,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
+ 	if (IS_ERR(bh2)) {
+ 		brelse(*bh);
+ 		*bh = NULL;
+-		*error = PTR_ERR(bh2);
+-		return NULL;
++		return (struct ext4_dir_entry_2 *) bh2;
+ 	}
+ 
+ 	BUFFER_TRACE(*bh, "get_write_access");
+@@ -1593,8 +1592,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
+ 	dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data2, blocksize, 1));
+ 
+ 	/* Which block gets the new entry? */
+-	if (hinfo->hash >= hash2)
+-	{
++	if (hinfo->hash >= hash2) {
+ 		swap(*bh, bh2);
+ 		de = de2;
+ 	}
+@@ -1614,8 +1612,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
+ 	brelse(bh2);
+ 	*bh = NULL;
+ 	ext4_std_error(dir->i_sb, err);
+-	*error = err;
+-	return NULL;
++	return ERR_PTR(err);
+ }
+ 
+ int ext4_find_dest_de(struct inode *dir, struct inode *inode,
+@@ -1838,8 +1835,8 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
+ 	ext4_handle_dirty_dx_node(handle, dir, frame->bh);
+ 	ext4_handle_dirty_dirent_node(handle, dir, bh);
+ 
+-	de = do_split(handle,dir, &bh, frame, &hinfo, &retval);
+-	if (!de) {
++	de = do_split(handle,dir, &bh, frame, &hinfo);
++	if (IS_ERR(de)) {
+ 		/*
+ 		 * Even if the block split failed, we have to properly write
+ 		 * out all the changes we did so far. Otherwise we can end up
+@@ -1847,7 +1844,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
+ 		 */
+ 		ext4_mark_inode_dirty(handle, dir);
+ 		dx_release(frames);
+-		return retval;
++		return PTR_ERR(de);
+ 	}
+ 	dx_release(frames);
+ 
+@@ -2071,9 +2068,11 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+ 			goto cleanup;
+ 		}
+ 	}
+-	de = do_split(handle, dir, &bh, frame, &hinfo, &err);
+-	if (!de)
++	de = do_split(handle, dir, &bh, frame, &hinfo);
++	if (IS_ERR(de)) {
++		err = PTR_ERR(de);
+ 		goto cleanup;
++	}
+ 	err = add_dirent_to_buf(handle, dentry, inode, de, bh);
+ 	goto cleanup;
+ 

commit dd73b5d5cb675e2aa3b1d4952e208af1546f91c1
+Author: Theodore Ts'o 
+Date:   Fri Aug 29 20:52:17 2014 -0400
+
+    ext4: convert dx_probe() to use the ERR_PTR convention
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index af13c908f617..e6d51655ffcd 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -253,8 +253,7 @@ static unsigned dx_node_limit(struct inode *dir);
+ static struct dx_frame *dx_probe(const struct qstr *d_name,
+ 				 struct inode *dir,
+ 				 struct dx_hash_info *hinfo,
+-				 struct dx_frame *frame,
+-				 int *err);
++				 struct dx_frame *frame);
+ static void dx_release(struct dx_frame *frames);
+ static int dx_make_map(struct ext4_dir_entry_2 *de, unsigned blocksize,
+ 		       struct dx_hash_info *hinfo, struct dx_map_entry map[]);
+@@ -670,29 +669,25 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir,
+  */
+ static struct dx_frame *
+ dx_probe(const struct qstr *d_name, struct inode *dir,
+-	 struct dx_hash_info *hinfo, struct dx_frame *frame_in, int *err)
++	 struct dx_hash_info *hinfo, struct dx_frame *frame_in)
+ {
+ 	unsigned count, indirect;
+ 	struct dx_entry *at, *entries, *p, *q, *m;
+ 	struct dx_root *root;
+-	struct buffer_head *bh;
+ 	struct dx_frame *frame = frame_in;
++	struct dx_frame *ret_err = ERR_PTR(ERR_BAD_DX_DIR);
+ 	u32 hash;
+ 
+-	frame->bh = NULL;
+-	bh = ext4_read_dirblock(dir, 0, INDEX);
+-	if (IS_ERR(bh)) {
+-		*err = PTR_ERR(bh);
+-		goto fail;
+-	}
+-	root = (struct dx_root *) bh->b_data;
++	frame->bh = ext4_read_dirblock(dir, 0, INDEX);
++	if (IS_ERR(frame->bh))
++		return (struct dx_frame *) frame->bh;
++
++	root = (struct dx_root *) frame->bh->b_data;
+ 	if (root->info.hash_version != DX_HASH_TEA &&
+ 	    root->info.hash_version != DX_HASH_HALF_MD4 &&
+ 	    root->info.hash_version != DX_HASH_LEGACY) {
+ 		ext4_warning(dir->i_sb, "Unrecognised inode hash code %d",
+ 			     root->info.hash_version);
+-		brelse(bh);
+-		*err = ERR_BAD_DX_DIR;
+ 		goto fail;
+ 	}
+ 	hinfo->hash_version = root->info.hash_version;
+@@ -706,16 +701,12 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
+ 	if (root->info.unused_flags & 1) {
+ 		ext4_warning(dir->i_sb, "Unimplemented inode hash flags: %#06x",
+ 			     root->info.unused_flags);
+-		brelse(bh);
+-		*err = ERR_BAD_DX_DIR;
+ 		goto fail;
+ 	}
+ 
+ 	if ((indirect = root->info.indirect_levels) > 1) {
+ 		ext4_warning(dir->i_sb, "Unimplemented inode hash depth: %#06x",
+ 			     root->info.indirect_levels);
+-		brelse(bh);
+-		*err = ERR_BAD_DX_DIR;
+ 		goto fail;
+ 	}
+ 
+@@ -725,27 +716,21 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
+ 	if (dx_get_limit(entries) != dx_root_limit(dir,
+ 						   root->info.info_length)) {
+ 		ext4_warning(dir->i_sb, "dx entry: limit != root limit");
+-		brelse(bh);
+-		*err = ERR_BAD_DX_DIR;
+ 		goto fail;
+ 	}
+ 
+ 	dxtrace(printk("Look up %x", hash));
+-	while (1)
+-	{
++	while (1) {
+ 		count = dx_get_count(entries);
+ 		if (!count || count > dx_get_limit(entries)) {
+ 			ext4_warning(dir->i_sb,
+ 				     "dx entry: no count or count > limit");
+-			brelse(bh);
+-			*err = ERR_BAD_DX_DIR;
+-			goto fail2;
++			goto fail;
+ 		}
+ 
+ 		p = entries + 1;
+ 		q = entries + count - 1;
+-		while (p <= q)
+-		{
++		while (p <= q) {
+ 			m = p + (q - p)/2;
+ 			dxtrace(printk("."));
+ 			if (dx_get_hash(m) > hash)
+@@ -754,8 +739,7 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
+ 				p = m + 1;
+ 		}
+ 
+-		if (0) // linear search cross check
+-		{
++		if (0) { // linear search cross check
+ 			unsigned n = count - 1;
+ 			at = entries;
+ 			while (n--)
+@@ -772,38 +756,35 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
+ 
+ 		at = p - 1;
+ 		dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at)));
+-		frame->bh = bh;
+ 		frame->entries = entries;
+ 		frame->at = at;
+-		if (!indirect--) return frame;
+-		bh = ext4_read_dirblock(dir, dx_get_block(at), INDEX);
+-		if (IS_ERR(bh)) {
+-			*err = PTR_ERR(bh);
+-			goto fail2;
++		if (!indirect--)
++			return frame;
++		frame++;
++		frame->bh = ext4_read_dirblock(dir, dx_get_block(at), INDEX);
++		if (IS_ERR(frame->bh)) {
++			ret_err = (struct dx_frame *) frame->bh;
++			frame->bh = NULL;
++			goto fail;
+ 		}
+-		entries = ((struct dx_node *) bh->b_data)->entries;
++		entries = ((struct dx_node *) frame->bh->b_data)->entries;
+ 
+ 		if (dx_get_limit(entries) != dx_node_limit (dir)) {
+ 			ext4_warning(dir->i_sb,
+ 				     "dx entry: limit != node limit");
+-			brelse(bh);
+-			*err = ERR_BAD_DX_DIR;
+-			goto fail2;
++			goto fail;
+ 		}
+-		frame++;
+-		frame->bh = NULL;
+ 	}
+-fail2:
++fail:
+ 	while (frame >= frame_in) {
+ 		brelse(frame->bh);
+ 		frame--;
+ 	}
+-fail:
+-	if (*err == ERR_BAD_DX_DIR)
++	if (ret_err == ERR_PTR(ERR_BAD_DX_DIR))
+ 		ext4_warning(dir->i_sb,
+ 			     "Corrupt dir inode %lu, running e2fsck is "
+ 			     "recommended.", dir->i_ino);
+-	return NULL;
++	return ret_err;
+ }
+ 
+ static void dx_release (struct dx_frame *frames)
+@@ -989,9 +970,9 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
+ 	}
+ 	hinfo.hash = start_hash;
+ 	hinfo.minor_hash = 0;
+-	frame = dx_probe(NULL, dir, &hinfo, frames, &err);
+-	if (!frame)
+-		return err;
++	frame = dx_probe(NULL, dir, &hinfo, frames);
++	if (IS_ERR(frame))
++		return PTR_ERR(frame);
+ 
+ 	/* Add '.' and '..' from the htree header */
+ 	if (!start_hash && !start_minor_hash) {
+@@ -1369,11 +1350,11 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q
+ 	struct dx_frame frames[2], *frame;
+ 	struct buffer_head *bh;
+ 	ext4_lblk_t block;
+-	int err = 0, retval;
++	int retval;
+ 
+-	frame = dx_probe(d_name, dir, &hinfo, frames, &err);
+-	if (err)
+-		return ERR_PTR(err);
++	frame = dx_probe(d_name, dir, &hinfo, frames);
++	if (IS_ERR(frame))
++		return (struct buffer_head *) frame;
+ 	do {
+ 		block = dx_get_block(frame->at);
+ 		bh = ext4_read_dirblock(dir, block, DIRENT);
+@@ -1977,9 +1958,9 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+ 	struct ext4_dir_entry_2 *de;
+ 	int err;
+ 
+-	frame = dx_probe(&dentry->d_name, dir, &hinfo, frames, &err);
+-	if (!frame)
+-		return err;
++	frame = dx_probe(&dentry->d_name, dir, &hinfo, frames);
++	if (IS_ERR(frame))
++		return PTR_ERR(frame);
+ 	entries = frame->entries;
+ 	at = frame->at;
+ 	bh = ext4_read_dirblock(dir, dx_get_block(frame->at), DIRENT);

commit 1c2150283cae895526d0db3953d13d139f4e7a03
+Author: Theodore Ts'o 
+Date:   Fri Aug 29 20:52:15 2014 -0400
+
+    ext4: convert ext4_bread() to use the ERR_PTR convention
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index 0bb3f9ea0832..c24143ea9c08 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -151,13 +151,11 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
+ 					&file->f_ra, file,
+ 					index, 1);
+ 			file->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT;
+-			bh = ext4_bread(NULL, inode, map.m_lblk, 0, &err);
++			bh = ext4_bread(NULL, inode, map.m_lblk, 0);
++			if (IS_ERR(bh))
++				return PTR_ERR(bh);
+ 		}
+ 
+-		/*
+-		 * We ignore I/O errors on directories so users have a chance
+-		 * of recovering data when there's a bad sector
+-		 */
+ 		if (!bh) {
+ 			if (!dir_has_error) {
+ 				EXT4_ERROR_FILE(file, 0,
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 8009077079e4..ca53bcece838 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2087,8 +2087,7 @@ extern int ext4_trim_fs(struct super_block *, struct fstrim_range *);
+ 
+ /* inode.c */
+ struct buffer_head *ext4_getblk(handle_t *, struct inode *, ext4_lblk_t, int);
+-struct buffer_head *ext4_bread(handle_t *, struct inode *,
+-						ext4_lblk_t, int, int *);
++struct buffer_head *ext4_bread(handle_t *, struct inode *, ext4_lblk_t, int);
+ int ext4_get_block_write(struct inode *inode, sector_t iblock,
+ 			 struct buffer_head *bh_result, int create);
+ int ext4_get_block(struct inode *inode, sector_t iblock,
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 0dfc1cd1eb52..8aa241a000c5 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -791,27 +791,21 @@ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
+ }
+ 
+ struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode,
+-			       ext4_lblk_t block, int create, int *err)
++			       ext4_lblk_t block, int create)
+ {
+ 	struct buffer_head *bh;
+ 
+-	*err = 0;
+ 	bh = ext4_getblk(handle, inode, block, create);
+-	if (IS_ERR(bh)) {
+-		*err = PTR_ERR(bh);
+-		return NULL;
+-	}
+-	if (!bh)
++	if (IS_ERR(bh))
+ 		return bh;
+-	if (buffer_uptodate(bh))
++	if (!bh || buffer_uptodate(bh))
+ 		return bh;
+ 	ll_rw_block(READ | REQ_META | REQ_PRIO, 1, &bh);
+ 	wait_on_buffer(bh);
+ 	if (buffer_uptodate(bh))
+ 		return bh;
+ 	put_bh(bh);
+-	*err = -EIO;
+-	return NULL;
++	return ERR_PTR(-EIO);
+ }
+ 
+ int ext4_walk_page_buffers(handle_t *handle,
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 26f114b1e4d6..af13c908f617 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -53,7 +53,7 @@ static struct buffer_head *ext4_append(handle_t *handle,
+ 					ext4_lblk_t *block)
+ {
+ 	struct buffer_head *bh;
+-	int err = 0;
++	int err;
+ 
+ 	if (unlikely(EXT4_SB(inode->i_sb)->s_max_dir_size_kb &&
+ 		     ((inode->i_size >> 10) >=
+@@ -62,9 +62,9 @@ static struct buffer_head *ext4_append(handle_t *handle,
+ 
+ 	*block = inode->i_size >> inode->i_sb->s_blocksize_bits;
+ 
+-	bh = ext4_bread(handle, inode, *block, 1, &err);
+-	if (!bh)
+-		return ERR_PTR(err);
++	bh = ext4_bread(handle, inode, *block, 1);
++	if (IS_ERR(bh))
++		return bh;
+ 	inode->i_size += inode->i_sb->s_blocksize;
+ 	EXT4_I(inode)->i_disksize = inode->i_size;
+ 	BUFFER_TRACE(bh, "get_write_access");
+@@ -94,20 +94,20 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
+ {
+ 	struct buffer_head *bh;
+ 	struct ext4_dir_entry *dirent;
+-	int err = 0, is_dx_block = 0;
++	int is_dx_block = 0;
+ 
+-	bh = ext4_bread(NULL, inode, block, 0, &err);
+-	if (!bh) {
+-		if (err == 0) {
+-			ext4_error_inode(inode, __func__, line, block,
+-					       "Directory hole found");
+-			return ERR_PTR(-EIO);
+-		}
++	bh = ext4_bread(NULL, inode, block, 0);
++	if (IS_ERR(bh)) {
+ 		__ext4_warning(inode->i_sb, __func__, line,
+-			       "error reading directory block "
+-			       "(ino %lu, block %lu)", inode->i_ino,
++			       "error %ld reading directory block "
++			       "(ino %lu, block %lu)", PTR_ERR(bh), inode->i_ino,
+ 			       (unsigned long) block);
+-		return ERR_PTR(err);
++
++		return bh;
++	}
++	if (!bh) {
++		ext4_error_inode(inode, __func__, line, block, "Directory hole found");
++		return ERR_PTR(-EIO);
+ 	}
+ 	dirent = (struct ext4_dir_entry *) bh->b_data;
+ 	/* Determine whether or not we have an index block */
+@@ -640,7 +640,9 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir,
+ 		u32 range = i < count - 1? (dx_get_hash(entries + 1) - hash): ~hash;
+ 		struct stats stats;
+ 		printk("%s%3u:%03u hash %8x/%8x ",levels?"":"   ", i, block, hash, range);
+-		if (!(bh = ext4_bread (NULL,dir, block, 0,&err))) continue;
++		bh = ext4_bread(NULL,dir, block, 0);
++		if (!bh || IS_ERR(bh))
++			continue;
+ 		stats = levels?
+ 		   dx_show_entries(hinfo, dir, ((struct dx_node *) bh->b_data)->entries, levels - 1):
+ 		   dx_show_leaf(hinfo, (struct ext4_dir_entry_2 *) bh->b_data, blocksize, 0);
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 0b28b36e7915..896e452b739d 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -5305,7 +5305,6 @@ static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data,
+ {
+ 	struct inode *inode = sb_dqopt(sb)->files[type];
+ 	ext4_lblk_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb);
+-	int err = 0;
+ 	int offset = off & (sb->s_blocksize - 1);
+ 	int tocopy;
+ 	size_t toread;
+@@ -5320,9 +5319,9 @@ static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data,
+ 	while (toread > 0) {
+ 		tocopy = sb->s_blocksize - offset < toread ?
+ 				sb->s_blocksize - offset : toread;
+-		bh = ext4_bread(NULL, inode, blk, 0, &err);
+-		if (err)
+-			return err;
++		bh = ext4_bread(NULL, inode, blk, 0);
++		if (IS_ERR(bh))
++			return PTR_ERR(bh);
+ 		if (!bh)	/* A hole? */
+ 			memset(data, 0, tocopy);
+ 		else
+@@ -5343,8 +5342,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
+ {
+ 	struct inode *inode = sb_dqopt(sb)->files[type];
+ 	ext4_lblk_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb);
+-	int err = 0;
+-	int offset = off & (sb->s_blocksize - 1);
++	int err, offset = off & (sb->s_blocksize - 1);
+ 	struct buffer_head *bh;
+ 	handle_t *handle = journal_current_handle();
+ 
+@@ -5365,14 +5363,16 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
+ 		return -EIO;
+ 	}
+ 
+-	bh = ext4_bread(handle, inode, blk, 1, &err);
++	bh = ext4_bread(handle, inode, blk, 1);
++	if (IS_ERR(bh))
++		return PTR_ERR(bh);
+ 	if (!bh)
+ 		goto out;
+ 	BUFFER_TRACE(bh, "get write access");
+ 	err = ext4_journal_get_write_access(handle, bh);
+ 	if (err) {
+ 		brelse(bh);
+-		goto out;
++		return err;
+ 	}
+ 	lock_buffer(bh);
+ 	memcpy(bh->b_data+offset, data, len);
+@@ -5381,8 +5381,6 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
+ 	err = ext4_handle_dirty_metadata(handle, NULL, bh);
+ 	brelse(bh);
+ out:
+-	if (err)
+-		return err;
+ 	if (inode->i_size < off + len) {
+ 		i_size_write(inode, off + len);
+ 		EXT4_I(inode)->i_disksize = inode->i_size;

commit 1056008226769fe982236c26038a095aeb47714b
+Author: Theodore Ts'o 
+Date:   Fri Aug 29 20:51:32 2014 -0400
+
+    ext4: convert ext4_getblk() to use the ERR_PTR convention
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index b0c225cdb52c..8009077079e4 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2086,8 +2086,7 @@ extern int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
+ extern int ext4_trim_fs(struct super_block *, struct fstrim_range *);
+ 
+ /* inode.c */
+-struct buffer_head *ext4_getblk(handle_t *, struct inode *,
+-						ext4_lblk_t, int, int *);
++struct buffer_head *ext4_getblk(handle_t *, struct inode *, ext4_lblk_t, int);
+ struct buffer_head *ext4_bread(handle_t *, struct inode *,
+ 						ext4_lblk_t, int, int *);
+ int ext4_get_block_write(struct inode *inode, sector_t iblock,
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 3aa26e9117c4..0dfc1cd1eb52 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -734,11 +734,11 @@ int ext4_get_block(struct inode *inode, sector_t iblock,
+  * `handle' can be NULL if create is zero
+  */
+ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
+-				ext4_lblk_t block, int create, int *errp)
++				ext4_lblk_t block, int create)
+ {
+ 	struct ext4_map_blocks map;
+ 	struct buffer_head *bh;
+-	int fatal = 0, err;
++	int err;
+ 
+ 	J_ASSERT(handle != NULL || create == 0);
+ 
+@@ -747,21 +747,14 @@ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
+ 	err = ext4_map_blocks(handle, inode, &map,
+ 			      create ? EXT4_GET_BLOCKS_CREATE : 0);
+ 
+-	/* ensure we send some value back into *errp */
+-	*errp = 0;
+-
+-	if (create && err == 0)
+-		err = -ENOSPC;	/* should never happen */
++	if (err == 0)
++		return create ? ERR_PTR(-ENOSPC) : NULL;
+ 	if (err < 0)
+-		*errp = err;
+-	if (err <= 0)
+-		return NULL;
++		return ERR_PTR(err);
+ 
+ 	bh = sb_getblk(inode->i_sb, map.m_pblk);
+-	if (unlikely(!bh)) {
+-		*errp = -ENOMEM;
+-		return NULL;
+-	}
++	if (unlikely(!bh))
++		return ERR_PTR(-ENOMEM);
+ 	if (map.m_flags & EXT4_MAP_NEW) {
+ 		J_ASSERT(create != 0);
+ 		J_ASSERT(handle != NULL);
+@@ -775,25 +768,26 @@ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
+ 		 */
+ 		lock_buffer(bh);
+ 		BUFFER_TRACE(bh, "call get_create_access");
+-		fatal = ext4_journal_get_create_access(handle, bh);
+-		if (!fatal && !buffer_uptodate(bh)) {
++		err = ext4_journal_get_create_access(handle, bh);
++		if (unlikely(err)) {
++			unlock_buffer(bh);
++			goto errout;
++		}
++		if (!buffer_uptodate(bh)) {
+ 			memset(bh->b_data, 0, inode->i_sb->s_blocksize);
+ 			set_buffer_uptodate(bh);
+ 		}
+ 		unlock_buffer(bh);
+ 		BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
+ 		err = ext4_handle_dirty_metadata(handle, inode, bh);
+-		if (!fatal)
+-			fatal = err;
+-	} else {
++		if (unlikely(err))
++			goto errout;
++	} else
+ 		BUFFER_TRACE(bh, "not a new buffer");
+-	}
+-	if (fatal) {
+-		*errp = fatal;
+-		brelse(bh);
+-		bh = NULL;
+-	}
+ 	return bh;
++errout:
++	brelse(bh);
++	return ERR_PTR(err);
+ }
+ 
+ struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode,
+@@ -801,7 +795,12 @@ struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode,
+ {
+ 	struct buffer_head *bh;
+ 
+-	bh = ext4_getblk(handle, inode, block, create, err);
++	*err = 0;
++	bh = ext4_getblk(handle, inode, block, create);
++	if (IS_ERR(bh)) {
++		*err = PTR_ERR(bh);
++		return NULL;
++	}
+ 	if (!bh)
+ 		return bh;
+ 	if (buffer_uptodate(bh))
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 1421ec1cd7e4..26f114b1e4d6 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1226,8 +1226,7 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
+ 				   buffer */
+ 	int num = 0;
+ 	ext4_lblk_t  nblocks;
+-	int i, err = 0;
+-	int namelen;
++	int i, namelen;
+ 
+ 	*res_dir = NULL;
+ 	sb = dir->i_sb;
+@@ -1293,10 +1292,10 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
+ 					break;
+ 				}
+ 				num++;
+-				bh = ext4_getblk(NULL, dir, b++, 0, &err);
+-				if (unlikely(err)) {
++				bh = ext4_getblk(NULL, dir, b++, 0);
++				if (unlikely(IS_ERR(bh))) {
+ 					if (ra_max == 0)
+-						return ERR_PTR(err);
++						return bh;
+ 					break;
+ 				}
+ 				bh_use[ra_max] = bh;

commit 537d8f93805ace30ce097736d3aac041931274b1
+Author: Theodore Ts'o 
+Date:   Fri Aug 29 20:49:51 2014 -0400
+
+    ext4: convert ext4_dx_find_entry() to use the ERR_PTR convention
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 90a3cdca3f88..1421ec1cd7e4 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -270,8 +270,7 @@ static int ext4_htree_next_block(struct inode *dir, __u32 hash,
+ 				 __u32 *start_hash);
+ static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
+ 		const struct qstr *d_name,
+-		struct ext4_dir_entry_2 **res_dir,
+-		int *err);
++		struct ext4_dir_entry_2 **res_dir);
+ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+ 			     struct inode *inode);
+ 
+@@ -1258,17 +1257,13 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
+ 		goto restart;
+ 	}
+ 	if (is_dx(dir)) {
+-		bh = ext4_dx_find_entry(dir, d_name, res_dir, &err);
++		bh = ext4_dx_find_entry(dir, d_name, res_dir);
+ 		/*
+ 		 * On success, or if the error was file not found,
+ 		 * return.  Otherwise, fall back to doing a search the
+ 		 * old fashioned way.
+ 		 */
+-		if (err == -ENOENT)
+-			return NULL;
+-		if (err && err != ERR_BAD_DX_DIR)
+-			return ERR_PTR(err);
+-		if (bh)
++		if (!IS_ERR(bh) || PTR_ERR(bh) != ERR_BAD_DX_DIR)
+ 			return bh;
+ 		dxtrace(printk(KERN_DEBUG "ext4_find_entry: dx failed, "
+ 			       "falling back\n"));
+@@ -1366,34 +1361,32 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
+ }
+ 
+ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct qstr *d_name,
+-		       struct ext4_dir_entry_2 **res_dir, int *err)
++		       struct ext4_dir_entry_2 **res_dir)
+ {
+ 	struct super_block * sb = dir->i_sb;
+ 	struct dx_hash_info	hinfo;
+ 	struct dx_frame frames[2], *frame;
+ 	struct buffer_head *bh;
+ 	ext4_lblk_t block;
+-	int retval;
++	int err = 0, retval;
+ 
+-	if (!(frame = dx_probe(d_name, dir, &hinfo, frames, err)))
+-		return NULL;
++	frame = dx_probe(d_name, dir, &hinfo, frames, &err);
++	if (err)
++		return ERR_PTR(err);
+ 	do {
+ 		block = dx_get_block(frame->at);
+ 		bh = ext4_read_dirblock(dir, block, DIRENT);
+-		if (IS_ERR(bh)) {
+-			*err = PTR_ERR(bh);
++		if (IS_ERR(bh))
+ 			goto errout;
+-		}
++
+ 		retval = search_dirblock(bh, dir, d_name,
+ 					 block << EXT4_BLOCK_SIZE_BITS(sb),
+ 					 res_dir);
+-		if (retval == 1) { 	/* Success! */
+-			dx_release(frames);
+-			return bh;
+-		}
++		if (retval == 1)
++			goto success;
+ 		brelse(bh);
+ 		if (retval == -1) {
+-			*err = ERR_BAD_DX_DIR;
++			bh = ERR_PTR(ERR_BAD_DX_DIR);
+ 			goto errout;
+ 		}
+ 
+@@ -1402,18 +1395,19 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q
+ 					       frames, NULL);
+ 		if (retval < 0) {
+ 			ext4_warning(sb,
+-			     "error reading index page in directory #%lu",
+-			     dir->i_ino);
+-			*err = retval;
++			     "error %d reading index page in directory #%lu",
++			     retval, dir->i_ino);
++			bh = ERR_PTR(retval);
+ 			goto errout;
+ 		}
+ 	} while (retval == 1);
+ 
+-	*err = -ENOENT;
++	bh = NULL;
+ errout:
+ 	dxtrace(printk(KERN_DEBUG "%s not found\n", d_name->name));
+-	dx_release (frames);
+-	return NULL;
++success:
++	dx_release(frames);
++	return bh;
+ }
+ 
+ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)

commit c99d1e6e83b06744c75d9f5e491ed495a7086b7b
+Author: Theodore Ts'o 
+Date:   Sat Aug 23 17:47:28 2014 -0400
+
+    ext4: fix BUG_ON in mb_free_blocks()
+    
+    If we suffer a block allocation failure (for example due to a memory
+    allocation failure), it's possible that we will call
+    ext4_discard_allocated_blocks() before we've actually allocated any
+    blocks.  In that case, fe_len and fe_start in ac->ac_f_ex will still
+    be zero, and this will result in mb_free_blocks(inode, e4b, 0, 0)
+    triggering the BUG_ON on mb_free_blocks():
+    
+            BUG_ON(last >= (sb->s_blocksize << 3));
+    
+    Fix this by bailing out of ext4_discard_allocated_blocks() if fs_len
+    is zero.
+    
+    Also fix a missing ext4_mb_unload_buddy() call in
+    ext4_discard_allocated_blocks().
+    
+    Google-Bug-Id: 16844242
+    
+    Fixes: 86f0afd463215fc3e58020493482faa4ac3a4d69
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 956027711faf..8b0f9ef517d6 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -1412,6 +1412,8 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
+ 	int last = first + count - 1;
+ 	struct super_block *sb = e4b->bd_sb;
+ 
++	if (WARN_ON(count == 0))
++		return;
+ 	BUG_ON(last >= (sb->s_blocksize << 3));
+ 	assert_spin_locked(ext4_group_lock_ptr(sb, e4b->bd_group));
+ 	/* Don't bother if the block group is corrupt. */
+@@ -3221,6 +3223,8 @@ static void ext4_discard_allocated_blocks(struct ext4_allocation_context *ac)
+ 	int err;
+ 
+ 	if (pa == NULL) {
++		if (ac->ac_f_ex.fe_len == 0)
++			return;
+ 		err = ext4_mb_load_buddy(ac->ac_sb, ac->ac_f_ex.fe_group, &e4b);
+ 		if (err) {
+ 			/*
+@@ -3235,6 +3239,7 @@ static void ext4_discard_allocated_blocks(struct ext4_allocation_context *ac)
+ 		mb_free_blocks(ac->ac_inode, &e4b, ac->ac_f_ex.fe_start,
+ 			       ac->ac_f_ex.fe_len);
+ 		ext4_unlock_group(ac->ac_sb, ac->ac_f_ex.fe_group);
++		ext4_mb_unload_buddy(&e4b);
+ 		return;
+ 	}
+ 	if (pa->pa_type == MB_INODE_PA)

commit 36de928641ee48b2078d3fe9514242aaa2f92013
+Author: Theodore Ts'o 
+Date:   Sat Aug 23 17:47:19 2014 -0400
+
+    ext4: propagate errors up to ext4_find_entry()'s callers
+    
+    If we run into some kind of error, such as ENOMEM, while calling
+    ext4_getblk() or ext4_dx_find_entry(), we need to make sure this error
+    gets propagated up to ext4_find_entry() and then to its callers.  This
+    way, transient errors such as ENOMEM can get propagated to the VFS.
+    This is important so that the system calls return the appropriate
+    error, and also so that in the case of ext4_lookup(), we return an
+    error instead of a NULL inode, since that will result in a negative
+    dentry cache entry that will stick around long past the OOM condition
+    which caused a transient ENOMEM error.
+    
+    Google-Bug-Id: #17142205
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 5b19760b1de5..4d95c3301775 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1825,7 +1825,7 @@ ext4_group_first_block_no(struct super_block *sb, ext4_group_t group_no)
+ /*
+  * Special error return code only used by dx_probe() and its callers.
+  */
+-#define ERR_BAD_DX_DIR	-75000
++#define ERR_BAD_DX_DIR	(-(MAX_ERRNO - 1))
+ 
+ /*
+  * Timeout and state flag for lazy initialization inode thread.
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index b147a67baa0d..ae7088b446d1 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1227,7 +1227,7 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
+ 				   buffer */
+ 	int num = 0;
+ 	ext4_lblk_t  nblocks;
+-	int i, err;
++	int i, err = 0;
+ 	int namelen;
+ 
+ 	*res_dir = NULL;
+@@ -1264,7 +1264,11 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
+ 		 * return.  Otherwise, fall back to doing a search the
+ 		 * old fashioned way.
+ 		 */
+-		if (bh || (err != ERR_BAD_DX_DIR))
++		if (err == -ENOENT)
++			return NULL;
++		if (err && err != ERR_BAD_DX_DIR)
++			return ERR_PTR(err);
++		if (bh)
+ 			return bh;
+ 		dxtrace(printk(KERN_DEBUG "ext4_find_entry: dx failed, "
+ 			       "falling back\n"));
+@@ -1295,6 +1299,11 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
+ 				}
+ 				num++;
+ 				bh = ext4_getblk(NULL, dir, b++, 0, &err);
++				if (unlikely(err)) {
++					if (ra_max == 0)
++						return ERR_PTR(err);
++					break;
++				}
+ 				bh_use[ra_max] = bh;
+ 				if (bh)
+ 					ll_rw_block(READ | REQ_META | REQ_PRIO,
+@@ -1417,6 +1426,8 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
+ 		return ERR_PTR(-ENAMETOOLONG);
+ 
+ 	bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL);
++	if (IS_ERR(bh))
++		return (struct dentry *) bh;
+ 	inode = NULL;
+ 	if (bh) {
+ 		__u32 ino = le32_to_cpu(de->inode);
+@@ -1450,6 +1461,8 @@ struct dentry *ext4_get_parent(struct dentry *child)
+ 	struct buffer_head *bh;
+ 
+ 	bh = ext4_find_entry(child->d_inode, &dotdot, &de, NULL);
++	if (IS_ERR(bh))
++		return (struct dentry *) bh;
+ 	if (!bh)
+ 		return ERR_PTR(-ENOENT);
+ 	ino = le32_to_cpu(de->inode);
+@@ -2727,6 +2740,8 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
+ 
+ 	retval = -ENOENT;
+ 	bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL);
++	if (IS_ERR(bh))
++		return PTR_ERR(bh);
+ 	if (!bh)
+ 		goto end_rmdir;
+ 
+@@ -2794,6 +2809,8 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
+ 
+ 	retval = -ENOENT;
+ 	bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL);
++	if (IS_ERR(bh))
++		return PTR_ERR(bh);
+ 	if (!bh)
+ 		goto end_unlink;
+ 
+@@ -3121,6 +3138,8 @@ static int ext4_find_delete_entry(handle_t *handle, struct inode *dir,
+ 	struct ext4_dir_entry_2 *de;
+ 
+ 	bh = ext4_find_entry(dir, d_name, &de, NULL);
++	if (IS_ERR(bh))
++		return PTR_ERR(bh);
+ 	if (bh) {
+ 		retval = ext4_delete_entry(handle, dir, de, bh);
+ 		brelse(bh);
+@@ -3202,6 +3221,8 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 		dquot_initialize(new.inode);
+ 
+ 	old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL);
++	if (IS_ERR(old.bh))
++		return PTR_ERR(old.bh);
+ 	/*
+ 	 *  Check for inode number is _not_ due to possible IO errors.
+ 	 *  We might rmdir the source, keep it as pwd of some process
+@@ -3214,6 +3235,10 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 
+ 	new.bh = ext4_find_entry(new.dir, &new.dentry->d_name,
+ 				 &new.de, &new.inlined);
++	if (IS_ERR(new.bh)) {
++		retval = PTR_ERR(new.bh);
++		goto end_rename;
++	}
+ 	if (new.bh) {
+ 		if (!new.inode) {
+ 			brelse(new.bh);
+@@ -3330,6 +3355,8 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 
+ 	old.bh = ext4_find_entry(old.dir, &old.dentry->d_name,
+ 				 &old.de, &old.inlined);
++	if (IS_ERR(old.bh))
++		return PTR_ERR(old.bh);
+ 	/*
+ 	 *  Check for inode number is _not_ due to possible IO errors.
+ 	 *  We might rmdir the source, keep it as pwd of some process
+@@ -3342,6 +3369,10 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 
+ 	new.bh = ext4_find_entry(new.dir, &new.dentry->d_name,
+ 				 &new.de, &new.inlined);
++	if (IS_ERR(new.bh)) {
++		retval = PTR_ERR(new.bh);
++		goto end_rename;
++	}
+ 
+ 	/* RENAME_EXCHANGE case: old *and* new must both exist */
+ 	if (!new.bh || le32_to_cpu(new.de->inode) != new.inode->i_ino)

commit 48d6be955a7167b0d0e025ae6c39e795e3544499
+Author: Theodore Ts'o 
+Date:   Thu Jul 17 05:27:30 2014 -0400
+
+    random: limit the contribution of the hw rng to at most half
+    
+    For people who don't trust a hardware RNG which can not be audited,
+    the changes to add support for RDSEED can be troubling since 97% or
+    more of the entropy will be contributed from the in-CPU hardware RNG.
+    
+    We now have a in-kernel khwrngd, so for those people who do want to
+    implicitly trust the CPU-based system, we could create an arch-rng
+    hw_random driver, and allow khwrng refill the entropy pool.  This
+    allows system administrator whether or not they trust the CPU (I
+    assume the NSA will trust RDRAND/RDSEED implicitly :-), and if so,
+    what level of entropy derating they want to use.
+    
+    The reason why this is a really good idea is that if different people
+    use different levels of entropy derating, it will make it much more
+    difficult to design a backdoor'ed hwrng that can be generally
+    exploited in terms of the output of /dev/random when different attack
+    targets are using differing levels of entropy derating.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 7d1682ea1e86..6e455bc4a39e 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -910,12 +910,13 @@ void add_interrupt_randomness(int irq, int irq_flags)
+ 
+ 	/*
+ 	 * If we have architectural seed generator, produce a seed and
+-	 * add it to the pool.  For the sake of paranoia count it as
+-	 * 50% entropic.
++	 * add it to the pool.  For the sake of paranoia don't let the
++	 * architectural seed generator dominate the input from the
++	 * interrupt noise.
+ 	 */
+ 	if (arch_get_random_seed_long(&seed)) {
+ 		__mix_pool_bytes(r, &seed, sizeof(seed));
+-		credit += sizeof(seed) * 4;
++		credit = 1;
+ 	}
+ 	spin_unlock(&r->lock);
+ 
+@@ -1328,37 +1329,6 @@ void rand_initialize_disk(struct gendisk *disk)
+ }
+ #endif
+ 
+-/*
+- * Attempt an emergency refill using arch_get_random_seed_long().
+- *
+- * As with add_interrupt_randomness() be paranoid and only
+- * credit the output as 50% entropic.
+- */
+-static int arch_random_refill(void)
+-{
+-	const unsigned int nlongs = 64;	/* Arbitrary number */
+-	unsigned int n = 0;
+-	unsigned int i;
+-	unsigned long buf[nlongs];
+-
+-	if (!arch_has_random_seed())
+-		return 0;
+-
+-	for (i = 0; i < nlongs; i++) {
+-		if (arch_get_random_seed_long(&buf[n]))
+-			n++;
+-	}
+-
+-	if (n) {
+-		unsigned int rand_bytes = n * sizeof(unsigned long);
+-
+-		mix_pool_bytes(&input_pool, buf, rand_bytes);
+-		credit_entropy_bits(&input_pool, rand_bytes*4);
+-	}
+-
+-	return n;
+-}
+-
+ static ssize_t
+ _random_read(int nonblock, char __user *buf, size_t nbytes)
+ {
+@@ -1379,11 +1349,6 @@ _random_read(int nonblock, char __user *buf, size_t nbytes)
+ 			return n;
+ 
+ 		/* Pool is (near) empty.  Maybe wait and retry. */
+-
+-		/* First try an emergency refill */
+-		if (arch_random_refill())
+-			continue;
+-
+ 		if (nonblock)
+ 			return -EAGAIN;
+ 

commit c6e9d6f38894798696f23c8084ca7edbf16ee895
+Author: Theodore Ts'o 
+Date:   Thu Jul 17 04:13:05 2014 -0400
+
+    random: introduce getrandom(2) system call
+    
+    The getrandom(2) system call was requested by the LibreSSL Portable
+    developers.  It is analoguous to the getentropy(2) system call in
+    OpenBSD.
+    
+    The rationale of this system call is to provide resiliance against
+    file descriptor exhaustion attacks, where the attacker consumes all
+    available file descriptors, forcing the use of the fallback code where
+    /dev/[u]random is not available.  Since the fallback code is often not
+    well-tested, it is better to eliminate this potential failure mode
+    entirely.
+    
+    The other feature provided by this new system call is the ability to
+    request randomness from the /dev/urandom entropy pool, but to block
+    until at least 128 bits of entropy has been accumulated in the
+    /dev/urandom entropy pool.  Historically, the emphasis in the
+    /dev/urandom development has been to ensure that urandom pool is
+    initialized as quickly as possible after system boot, and preferably
+    before the init scripts start execution.
+    
+    This is because changing /dev/urandom reads to block represents an
+    interface change that could potentially break userspace which is not
+    acceptable.  In practice, on most x86 desktop and server systems, in
+    general the entropy pool can be initialized before it is needed (and
+    in modern kernels, we will printk a warning message if not).  However,
+    on an embedded system, this may not be the case.  And so with this new
+    interface, we can provide the functionality of blocking until the
+    urandom pool has been initialized.  Any userspace program which uses
+    this new functionality must take care to assure that if it is used
+    during the boot process, that it will not cause the init scripts or
+    other portions of the system startup to hang indefinitely.
+    
+    SYNOPSIS
+            #include 
+    
+            int getrandom(void *buf, size_t buflen, unsigned int flags);
+    
+    DESCRIPTION
+            The system call getrandom() fills the buffer pointed to by buf
+            with up to buflen random bytes which can be used to seed user
+            space random number generators (i.e., DRBG's) or for other
+            cryptographic uses.  It should not be used for Monte Carlo
+            simulations or other programs/algorithms which are doing
+            probabilistic sampling.
+    
+            If the GRND_RANDOM flags bit is set, then draw from the
+            /dev/random pool instead of the /dev/urandom pool.  The
+            /dev/random pool is limited based on the entropy that can be
+            obtained from environmental noise, so if there is insufficient
+            entropy, the requested number of bytes may not be returned.
+            If there is no entropy available at all, getrandom(2) will
+            either block, or return an error with errno set to EAGAIN if
+            the GRND_NONBLOCK bit is set in flags.
+    
+            If the GRND_RANDOM bit is not set, then the /dev/urandom pool
+            will be used.  Unlike using read(2) to fetch data from
+            /dev/urandom, if the urandom pool has not been sufficiently
+            initialized, getrandom(2) will block (or return -1 with the
+            errno set to EAGAIN if the GRND_NONBLOCK bit is set in flags).
+    
+            The getentropy(2) system call in OpenBSD can be emulated using
+            the following function:
+    
+                int getentropy(void *buf, size_t buflen)
+                {
+                        int     ret;
+    
+                        if (buflen > 256)
+                                goto failure;
+                        ret = getrandom(buf, buflen, 0);
+                        if (ret < 0)
+                                return ret;
+                        if (ret == buflen)
+                                return 0;
+                failure:
+                        errno = EIO;
+                        return -1;
+                }
+    
+    RETURN VALUE
+           On success, the number of bytes that was filled in the buf is
+           returned.  This may not be all the bytes requested by the
+           caller via buflen if insufficient entropy was present in the
+           /dev/random pool, or if the system call was interrupted by a
+           signal.
+    
+           On error, -1 is returned, and errno is set appropriately.
+    
+    ERRORS
+            EINVAL          An invalid flag was passed to getrandom(2)
+    
+            EFAULT          buf is outside the accessible address space.
+    
+            EAGAIN          The requested entropy was not available, and
+                            getentropy(2) would have blocked if the
+                            GRND_NONBLOCK flag was not set.
+    
+            EINTR           While blocked waiting for entropy, the call was
+                            interrupted by a signal handler; see the description
+                            of how interrupted read(2) calls on "slow" devices
+                            are handled with and without the SA_RESTART flag
+                            in the signal(7) man page.
+    
+    NOTES
+            For small requests (buflen <= 256) getrandom(2) will not
+            return EINTR when reading from the urandom pool once the
+            entropy pool has been initialized, and it will return all of
+            the bytes that have been requested.  This is the recommended
+            way to use getrandom(2), and is designed for compatibility
+            with OpenBSD's getentropy() system call.
+    
+            However, if you are using GRND_RANDOM, then getrandom(2) may
+            block until the entropy accounting determines that sufficient
+            environmental noise has been gathered such that getrandom(2)
+            will be operating as a NRBG instead of a DRBG for those people
+            who are working in the NIST SP 800-90 regime.  Since it may
+            block for a long time, these guarantees do *not* apply.  The
+            user may want to interrupt a hanging process using a signal,
+            so blocking until all of the requested bytes are returned
+            would be unfriendly.
+    
+            For this reason, the user of getrandom(2) MUST always check
+            the return value, in case it returns some error, or if fewer
+            bytes than requested was returned.  In the case of
+            !GRND_RANDOM and small request, the latter should never
+            happen, but the careful userspace code (and all crypto code
+            should be careful) should check for this anyway!
+    
+            Finally, unless you are doing long-term key generation (and
+            perhaps not even then), you probably shouldn't be using
+            GRND_RANDOM.  The cryptographic algorithms used for
+            /dev/urandom are quite conservative, and so should be
+            sufficient for all purposes.  The disadvantage of GRND_RANDOM
+            is that it can block, and the increased complexity required to
+            deal with partially fulfilled getrandom(2) requests.
+    
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Zach Brown 
+
+diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl
+index d6b867921612..5b46a618aeb1 100644
+--- a/arch/x86/syscalls/syscall_32.tbl
++++ b/arch/x86/syscalls/syscall_32.tbl
+@@ -360,3 +360,4 @@
+ 351	i386	sched_setattr		sys_sched_setattr
+ 352	i386	sched_getattr		sys_sched_getattr
+ 353	i386	renameat2		sys_renameat2
++355	i386	getrandom		sys_getrandom
+diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl
+index ec255a1646d2..0dc4bf891460 100644
+--- a/arch/x86/syscalls/syscall_64.tbl
++++ b/arch/x86/syscalls/syscall_64.tbl
+@@ -323,6 +323,7 @@
+ 314	common	sched_setattr		sys_sched_setattr
+ 315	common	sched_getattr		sys_sched_getattr
+ 316	common	renameat2		sys_renameat2
++318	common	getrandom		sys_getrandom
+ 
+ #
+ # x32-specific system call numbers start at 512 to avoid cache impact
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index aa22fe551c2a..7d1682ea1e86 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -258,6 +258,8 @@
+ #include 
+ #include 
+ #include 
++#include 
++#include 
+ 
+ #include 
+ #include 
+@@ -404,6 +406,7 @@ static struct poolinfo {
+  */
+ static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
+ static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
++static DECLARE_WAIT_QUEUE_HEAD(urandom_init_wait);
+ static struct fasync_struct *fasync;
+ 
+ /**********************************************************************
+@@ -657,6 +660,7 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
+ 		r->entropy_total = 0;
+ 		if (r == &nonblocking_pool) {
+ 			prandom_reseed_late();
++			wake_up_interruptible(&urandom_init_wait);
+ 			pr_notice("random: %s pool is initialized\n", r->name);
+ 		}
+ 	}
+@@ -1174,13 +1178,14 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
+ {
+ 	ssize_t ret = 0, i;
+ 	__u8 tmp[EXTRACT_SIZE];
++	int large_request = (nbytes > 256);
+ 
+ 	trace_extract_entropy_user(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_);
+ 	xfer_secondary_pool(r, nbytes);
+ 	nbytes = account(r, nbytes, 0, 0);
+ 
+ 	while (nbytes) {
+-		if (need_resched()) {
++		if (large_request && need_resched()) {
+ 			if (signal_pending(current)) {
+ 				if (ret == 0)
+ 					ret = -ERESTARTSYS;
+@@ -1355,7 +1360,7 @@ static int arch_random_refill(void)
+ }
+ 
+ static ssize_t
+-random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
++_random_read(int nonblock, char __user *buf, size_t nbytes)
+ {
+ 	ssize_t n;
+ 
+@@ -1379,7 +1384,7 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+ 		if (arch_random_refill())
+ 			continue;
+ 
+-		if (file->f_flags & O_NONBLOCK)
++		if (nonblock)
+ 			return -EAGAIN;
+ 
+ 		wait_event_interruptible(random_read_wait,
+@@ -1390,6 +1395,12 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+ 	}
+ }
+ 
++static ssize_t
++random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
++{
++	return _random_read(file->f_flags & O_NONBLOCK, buf, nbytes);
++}
++
+ static ssize_t
+ urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+ {
+@@ -1533,6 +1544,29 @@ const struct file_operations urandom_fops = {
+ 	.llseek = noop_llseek,
+ };
+ 
++SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
++		unsigned int, flags)
++{
++	if (flags & ~(GRND_NONBLOCK|GRND_RANDOM))
++		return -EINVAL;
++
++	if (count > INT_MAX)
++		count = INT_MAX;
++
++	if (flags & GRND_RANDOM)
++		return _random_read(flags & GRND_NONBLOCK, buf, count);
++
++	if (unlikely(nonblocking_pool.initialized == 0)) {
++		if (flags & GRND_NONBLOCK)
++			return -EAGAIN;
++		wait_event_interruptible(urandom_init_wait,
++					 nonblocking_pool.initialized);
++		if (signal_pending(current))
++			return -ERESTARTSYS;
++	}
++	return urandom_read(NULL, buf, count, NULL);
++}
++
+ /***************************************************************
+  * Random UUID interface
+  *
+diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
+index b0881a0ed322..43324a897cf2 100644
+--- a/include/linux/syscalls.h
++++ b/include/linux/syscalls.h
+@@ -866,4 +866,7 @@ asmlinkage long sys_process_vm_writev(pid_t pid,
+ asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type,
+ 			 unsigned long idx1, unsigned long idx2);
+ asmlinkage long sys_finit_module(int fd, const char __user *uargs, int flags);
++asmlinkage long sys_getrandom(char __user *buf, size_t count,
++			      unsigned int flags);
++
+ #endif
+diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
+index 333640608087..1d104a2ca643 100644
+--- a/include/uapi/asm-generic/unistd.h
++++ b/include/uapi/asm-generic/unistd.h
+@@ -699,9 +699,11 @@ __SYSCALL(__NR_sched_setattr, sys_sched_setattr)
+ __SYSCALL(__NR_sched_getattr, sys_sched_getattr)
+ #define __NR_renameat2 276
+ __SYSCALL(__NR_renameat2, sys_renameat2)
++#define __NR_getrandom 278
++__SYSCALL(__NR_getrandom, sys_getrandom)
+ 
+ #undef __NR_syscalls
+-#define __NR_syscalls 277
++#define __NR_syscalls 279
+ 
+ /*
+  * All syscalls below here should go away really,
+diff --git a/include/uapi/linux/random.h b/include/uapi/linux/random.h
+index fff3528a078f..3f93d1695e7f 100644
+--- a/include/uapi/linux/random.h
++++ b/include/uapi/linux/random.h
+@@ -40,4 +40,13 @@ struct rand_pool_info {
+ 	__u32	buf[0];
+ };
+ 
++/*
++ * Flags for getrandom(2)
++ *
++ * GRND_NONBLOCK	Don't block and return EAGAIN instead
++ * GRND_RANDOM		Use the /dev/random pool instead of /dev/urandom
++ */
++#define GRND_NONBLOCK	0x0001
++#define GRND_RANDOM	0x0002
++
+ #endif /* _UAPI_LINUX_RANDOM_H */

commit 86f0afd463215fc3e58020493482faa4ac3a4d69
+Author: Theodore Ts'o 
+Date:   Wed Jul 30 22:17:17 2014 -0400
+
+    ext4: fix ext4_discard_allocated_blocks() if we can't allocate the pa struct
+    
+    If there is a failure while allocating the preallocation structure, a
+    number of blocks can end up getting marked in the in-memory buddy
+    bitmap, and then not getting released.  This can result in the
+    following corruption getting reported by the kernel:
+    
+    EXT4-fs error (device sda3): ext4_mb_generate_buddy:758: group 1126,
+    12793 clusters in bitmap, 12729 in gd
+    
+    In that case, we need to release the blocks using mb_free_blocks().
+    
+    Tested: fs smoke test; also demonstrated that with injected errors,
+            the file system is no longer getting corrupted
+    
+    Google-Bug-Id: 16657874
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 0e9466f9e767..956027711faf 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -3217,8 +3217,27 @@ static void ext4_mb_collect_stats(struct ext4_allocation_context *ac)
+ static void ext4_discard_allocated_blocks(struct ext4_allocation_context *ac)
+ {
+ 	struct ext4_prealloc_space *pa = ac->ac_pa;
++	struct ext4_buddy e4b;
++	int err;
+ 
+-	if (pa && pa->pa_type == MB_INODE_PA)
++	if (pa == NULL) {
++		err = ext4_mb_load_buddy(ac->ac_sb, ac->ac_f_ex.fe_group, &e4b);
++		if (err) {
++			/*
++			 * This should never happen since we pin the
++			 * pages in the ext4_allocation_context so
++			 * ext4_mb_load_buddy() should never fail.
++			 */
++			WARN(1, "mb_load_buddy failed (%d)", err);
++			return;
++		}
++		ext4_lock_group(ac->ac_sb, ac->ac_f_ex.fe_group);
++		mb_free_blocks(ac->ac_inode, &e4b, ac->ac_f_ex.fe_start,
++			       ac->ac_f_ex.fe_len);
++		ext4_unlock_group(ac->ac_sb, ac->ac_f_ex.fe_group);
++		return;
++	}
++	if (pa->pa_type == MB_INODE_PA)
+ 		pa->pa_free += ac->ac_b_ex.fe_len;
+ }
+ 

commit 71d4f7d032149b935a26eb3ff85c6c837f3714e1
+Author: Theodore Ts'o 
+Date:   Tue Jul 15 06:02:38 2014 -0400
+
+    ext4: remove metadata reservation checks
+    
+    Commit 27dd43854227b ("ext4: introduce reserved space") reserves 2% of
+    the file system space to make sure metadata allocations will always
+    succeed.  Given that, tracking the reservation of metadata blocks is
+    no longer necessary.
+    
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index fca382037ddd..581ef40fbe90 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -639,7 +639,6 @@ ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
+ 	if (!(*errp) &&
+ 	    ext4_test_inode_state(inode, EXT4_STATE_DELALLOC_RESERVED)) {
+ 		spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
+-		EXT4_I(inode)->i_allocated_meta_blocks += ar.len;
+ 		spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+ 		dquot_alloc_block_nofail(inode,
+ 				EXT4_C2B(EXT4_SB(inode->i_sb), ar.len));
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 7cc5a0e23688..d35c78c96184 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -591,7 +591,6 @@ enum {
+ #define EXT4_FREE_BLOCKS_NO_QUOT_UPDATE	0x0008
+ #define EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER	0x0010
+ #define EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER	0x0020
+-#define EXT4_FREE_BLOCKS_RESERVE		0x0040
+ 
+ /*
+  * ioctl commands
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 4da228a0e6d0..b30172dd55eb 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -1808,8 +1808,7 @@ static void ext4_ext_try_to_merge_up(handle_t *handle,
+ 
+ 	brelse(path[1].p_bh);
+ 	ext4_free_blocks(handle, inode, NULL, blk, 1,
+-			 EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET |
+-			 EXT4_FREE_BLOCKS_RESERVE);
++			 EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET);
+ }
+ 
+ /*
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 8a064734e6eb..027ee8c40470 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -324,18 +324,6 @@ qsize_t *ext4_get_reserved_space(struct inode *inode)
+ }
+ #endif
+ 
+-/*
+- * Calculate the number of metadata blocks need to reserve
+- * to allocate a block located at @lblock
+- */
+-static int ext4_calc_metadata_amount(struct inode *inode, ext4_lblk_t lblock)
+-{
+-	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
+-		return ext4_ext_calc_metadata_amount(inode, lblock);
+-
+-	return ext4_ind_calc_metadata_amount(inode, lblock);
+-}
+-
+ /*
+  * Called with i_data_sem down, which is important since we can call
+  * ext4_discard_preallocations() from here.
+@@ -357,35 +345,10 @@ void ext4_da_update_reserve_space(struct inode *inode,
+ 		used = ei->i_reserved_data_blocks;
+ 	}
+ 
+-	if (unlikely(ei->i_allocated_meta_blocks > ei->i_reserved_meta_blocks)) {
+-		ext4_warning(inode->i_sb, "ino %lu, allocated %d "
+-			"with only %d reserved metadata blocks "
+-			"(releasing %d blocks with reserved %d data blocks)",
+-			inode->i_ino, ei->i_allocated_meta_blocks,
+-			     ei->i_reserved_meta_blocks, used,
+-			     ei->i_reserved_data_blocks);
+-		WARN_ON(1);
+-		ei->i_allocated_meta_blocks = ei->i_reserved_meta_blocks;
+-	}
+-
+ 	/* Update per-inode reservations */
+ 	ei->i_reserved_data_blocks -= used;
+-	ei->i_reserved_meta_blocks -= ei->i_allocated_meta_blocks;
+-	percpu_counter_sub(&sbi->s_dirtyclusters_counter,
+-			   used + ei->i_allocated_meta_blocks);
+-	ei->i_allocated_meta_blocks = 0;
++	percpu_counter_sub(&sbi->s_dirtyclusters_counter, used);
+ 
+-	if (ei->i_reserved_data_blocks == 0) {
+-		/*
+-		 * We can release all of the reserved metadata blocks
+-		 * only when we have written all of the delayed
+-		 * allocation blocks.
+-		 */
+-		percpu_counter_sub(&sbi->s_dirtyclusters_counter,
+-				   ei->i_reserved_meta_blocks);
+-		ei->i_reserved_meta_blocks = 0;
+-		ei->i_da_metadata_calc_len = 0;
+-	}
+ 	spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+ 
+ 	/* Update quota subsystem for data blocks */
+@@ -1221,49 +1184,6 @@ static int ext4_journalled_write_end(struct file *file,
+ 	return ret ? ret : copied;
+ }
+ 
+-/*
+- * Reserve a metadata for a single block located at lblock
+- */
+-static int ext4_da_reserve_metadata(struct inode *inode, ext4_lblk_t lblock)
+-{
+-	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+-	struct ext4_inode_info *ei = EXT4_I(inode);
+-	unsigned int md_needed;
+-	ext4_lblk_t save_last_lblock;
+-	int save_len;
+-
+-	/*
+-	 * recalculate the amount of metadata blocks to reserve
+-	 * in order to allocate nrblocks
+-	 * worse case is one extent per block
+-	 */
+-	spin_lock(&ei->i_block_reservation_lock);
+-	/*
+-	 * ext4_calc_metadata_amount() has side effects, which we have
+-	 * to be prepared undo if we fail to claim space.
+-	 */
+-	save_len = ei->i_da_metadata_calc_len;
+-	save_last_lblock = ei->i_da_metadata_calc_last_lblock;
+-	md_needed = EXT4_NUM_B2C(sbi,
+-				 ext4_calc_metadata_amount(inode, lblock));
+-	trace_ext4_da_reserve_space(inode, md_needed);
+-
+-	/*
+-	 * We do still charge estimated metadata to the sb though;
+-	 * we cannot afford to run out of free blocks.
+-	 */
+-	if (ext4_claim_free_clusters(sbi, md_needed, 0)) {
+-		ei->i_da_metadata_calc_len = save_len;
+-		ei->i_da_metadata_calc_last_lblock = save_last_lblock;
+-		spin_unlock(&ei->i_block_reservation_lock);
+-		return -ENOSPC;
+-	}
+-	ei->i_reserved_meta_blocks += md_needed;
+-	spin_unlock(&ei->i_block_reservation_lock);
+-
+-	return 0;       /* success */
+-}
+-
+ /*
+  * Reserve a single cluster located at lblock
+  */
+@@ -1273,8 +1193,6 @@ static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock)
+ 	struct ext4_inode_info *ei = EXT4_I(inode);
+ 	unsigned int md_needed;
+ 	int ret;
+-	ext4_lblk_t save_last_lblock;
+-	int save_len;
+ 
+ 	/*
+ 	 * We will charge metadata quota at writeout time; this saves
+@@ -1295,25 +1213,15 @@ static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock)
+ 	 * ext4_calc_metadata_amount() has side effects, which we have
+ 	 * to be prepared undo if we fail to claim space.
+ 	 */
+-	save_len = ei->i_da_metadata_calc_len;
+-	save_last_lblock = ei->i_da_metadata_calc_last_lblock;
+-	md_needed = EXT4_NUM_B2C(sbi,
+-				 ext4_calc_metadata_amount(inode, lblock));
+-	trace_ext4_da_reserve_space(inode, md_needed);
++	md_needed = 0;
++	trace_ext4_da_reserve_space(inode, 0);
+ 
+-	/*
+-	 * We do still charge estimated metadata to the sb though;
+-	 * we cannot afford to run out of free blocks.
+-	 */
+-	if (ext4_claim_free_clusters(sbi, md_needed + 1, 0)) {
+-		ei->i_da_metadata_calc_len = save_len;
+-		ei->i_da_metadata_calc_last_lblock = save_last_lblock;
++	if (ext4_claim_free_clusters(sbi, 1, 0)) {
+ 		spin_unlock(&ei->i_block_reservation_lock);
+ 		dquot_release_reservation_block(inode, EXT4_C2B(sbi, 1));
+ 		return -ENOSPC;
+ 	}
+ 	ei->i_reserved_data_blocks++;
+-	ei->i_reserved_meta_blocks += md_needed;
+ 	spin_unlock(&ei->i_block_reservation_lock);
+ 
+ 	return 0;       /* success */
+@@ -1346,20 +1254,6 @@ static void ext4_da_release_space(struct inode *inode, int to_free)
+ 	}
+ 	ei->i_reserved_data_blocks -= to_free;
+ 
+-	if (ei->i_reserved_data_blocks == 0) {
+-		/*
+-		 * We can release all of the reserved metadata blocks
+-		 * only when we have written all of the delayed
+-		 * allocation blocks.
+-		 * Note that in case of bigalloc, i_reserved_meta_blocks,
+-		 * i_reserved_data_blocks, etc. refer to number of clusters.
+-		 */
+-		percpu_counter_sub(&sbi->s_dirtyclusters_counter,
+-				   ei->i_reserved_meta_blocks);
+-		ei->i_reserved_meta_blocks = 0;
+-		ei->i_da_metadata_calc_len = 0;
+-	}
+-
+ 	/* update fs dirty data blocks counter */
+ 	percpu_counter_sub(&sbi->s_dirtyclusters_counter, to_free);
+ 
+@@ -1500,10 +1394,6 @@ static void ext4_print_free_blocks(struct inode *inode)
+ 	ext4_msg(sb, KERN_CRIT, "Block reservation details");
+ 	ext4_msg(sb, KERN_CRIT, "i_reserved_data_blocks=%u",
+ 		 ei->i_reserved_data_blocks);
+-	ext4_msg(sb, KERN_CRIT, "i_reserved_meta_blocks=%u",
+-	       ei->i_reserved_meta_blocks);
+-	ext4_msg(sb, KERN_CRIT, "i_allocated_meta_blocks=%u",
+-	       ei->i_allocated_meta_blocks);
+ 	return;
+ }
+ 
+@@ -1620,13 +1510,6 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
+ 				retval = ret;
+ 				goto out_unlock;
+ 			}
+-		} else {
+-			ret = ext4_da_reserve_metadata(inode, iblock);
+-			if (ret) {
+-				/* not enough space to reserve */
+-				retval = ret;
+-				goto out_unlock;
+-			}
+ 		}
+ 
+ 		ret = ext4_es_insert_extent(inode, map->m_lblk, map->m_len,
+@@ -2843,8 +2726,7 @@ int ext4_alloc_da_blocks(struct inode *inode)
+ {
+ 	trace_ext4_alloc_da_blocks(inode);
+ 
+-	if (!EXT4_I(inode)->i_reserved_data_blocks &&
+-	    !EXT4_I(inode)->i_reserved_meta_blocks)
++	if (!EXT4_I(inode)->i_reserved_data_blocks)
+ 		return 0;
+ 
+ 	/*
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 2dcb936be90e..18a16191249a 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -4627,7 +4627,6 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 	struct buffer_head *gd_bh;
+ 	ext4_group_t block_group;
+ 	struct ext4_sb_info *sbi;
+-	struct ext4_inode_info *ei = EXT4_I(inode);
+ 	struct ext4_buddy e4b;
+ 	unsigned int count_clusters;
+ 	int err = 0;
+@@ -4838,19 +4837,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 			     &sbi->s_flex_groups[flex_group].free_clusters);
+ 	}
+ 
+-	if (flags & EXT4_FREE_BLOCKS_RESERVE && ei->i_reserved_data_blocks) {
+-		percpu_counter_add(&sbi->s_dirtyclusters_counter,
+-				   count_clusters);
+-		spin_lock(&ei->i_block_reservation_lock);
+-		if (flags & EXT4_FREE_BLOCKS_METADATA)
+-			ei->i_reserved_meta_blocks += count_clusters;
+-		else
+-			ei->i_reserved_data_blocks += count_clusters;
+-		spin_unlock(&ei->i_block_reservation_lock);
+-		if (!(flags & EXT4_FREE_BLOCKS_NO_QUOT_UPDATE))
+-			dquot_reclaim_block(inode,
+-					EXT4_C2B(sbi, count_clusters));
+-	} else if (!(flags & EXT4_FREE_BLOCKS_NO_QUOT_UPDATE))
++	if (!(flags & EXT4_FREE_BLOCKS_NO_QUOT_UPDATE))
+ 		dquot_free_block(inode, EXT4_C2B(sbi, count_clusters));
+ 	percpu_counter_add(&sbi->s_freeclusters_counter, count_clusters);
+ 

commit d5e03cbb0c88cd1be39f2adc37d602230045964b
+Author: Theodore Ts'o 
+Date:   Tue Jul 15 06:01:38 2014 -0400
+
+    ext4: rearrange initialization to fix EXT4FS_DEBUG
+    
+    The EXT4FS_DEBUG is a *very* developer specific #ifdef designed for
+    ext4 developers only.  (You have to modify fs/ext4/ext4.h to enable
+    it.)
+    
+    Rearrange how we initialize data structures to avoid calling
+    ext4_count_free_clusters() until the multiblock allocator has been
+    initialized.
+    
+    This also allows us to only call ext4_count_free_clusters() once, and
+    simplifies the code somewhat.
+    
+    (Thanks to Chen Gang  for pointing out a
+    !CONFIG_SMP compile breakage in the original patch.)
+    
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Lukas Czerner 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 6df7bc611dbd..32b43ad154b9 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2142,10 +2142,6 @@ static int ext4_check_descriptors(struct super_block *sb,
+ 	}
+ 	if (NULL != first_not_zeroed)
+ 		*first_not_zeroed = grp;
+-
+-	ext4_free_blocks_count_set(sbi->s_es,
+-				   EXT4_C2B(sbi, ext4_count_free_clusters(sb)));
+-	sbi->s_es->s_free_inodes_count =cpu_to_le32(ext4_count_free_inodes(sb));
+ 	return 1;
+ }
+ 
+@@ -3883,13 +3879,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		ext4_msg(sb, KERN_ERR, "group descriptors corrupted!");
+ 		goto failed_mount2;
+ 	}
+-	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG))
+-		if (!ext4_fill_flex_info(sb)) {
+-			ext4_msg(sb, KERN_ERR,
+-			       "unable to initialize "
+-			       "flex_bg meta info!");
+-			goto failed_mount2;
+-		}
+ 
+ 	sbi->s_gdb_count = db_count;
+ 	get_random_bytes(&sbi->s_next_generation, sizeof(u32));
+@@ -3902,23 +3891,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	/* Register extent status tree shrinker */
+ 	ext4_es_register_shrinker(sbi);
+ 
+-	err = percpu_counter_init(&sbi->s_freeclusters_counter,
+-			ext4_count_free_clusters(sb));
+-	if (!err) {
+-		err = percpu_counter_init(&sbi->s_freeinodes_counter,
+-				ext4_count_free_inodes(sb));
+-	}
+-	if (!err) {
+-		err = percpu_counter_init(&sbi->s_dirs_counter,
+-				ext4_count_dirs(sb));
+-	}
+-	if (!err) {
+-		err = percpu_counter_init(&sbi->s_dirtyclusters_counter, 0);
+-	}
+-	if (!err) {
+-		err = percpu_counter_init(&sbi->s_extent_cache_cnt, 0);
+-	}
+-	if (err) {
++	if ((err = percpu_counter_init(&sbi->s_extent_cache_cnt, 0)) != 0) {
+ 		ext4_msg(sb, KERN_ERR, "insufficient memory");
+ 		goto failed_mount3;
+ 	}
+@@ -4022,18 +3995,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 
+ 	sbi->s_journal->j_commit_callback = ext4_journal_commit_callback;
+ 
+-	/*
+-	 * The journal may have updated the bg summary counts, so we
+-	 * need to update the global counters.
+-	 */
+-	percpu_counter_set(&sbi->s_freeclusters_counter,
+-			   ext4_count_free_clusters(sb));
+-	percpu_counter_set(&sbi->s_freeinodes_counter,
+-			   ext4_count_free_inodes(sb));
+-	percpu_counter_set(&sbi->s_dirs_counter,
+-			   ext4_count_dirs(sb));
+-	percpu_counter_set(&sbi->s_dirtyclusters_counter, 0);
+-
+ no_journal:
+ 	if (ext4_mballoc_ready) {
+ 		sbi->s_mb_cache = ext4_xattr_create_cache(sb->s_id);
+@@ -4141,6 +4102,33 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		goto failed_mount5;
+ 	}
+ 
++	block = ext4_count_free_clusters(sb);
++	ext4_free_blocks_count_set(sbi->s_es, 
++				   EXT4_C2B(sbi, block));
++	err = percpu_counter_init(&sbi->s_freeclusters_counter, block);
++	if (!err) {
++		unsigned long freei = ext4_count_free_inodes(sb);
++		sbi->s_es->s_free_inodes_count = cpu_to_le32(freei);
++		err = percpu_counter_init(&sbi->s_freeinodes_counter, freei);
++	}
++	if (!err)
++		err = percpu_counter_init(&sbi->s_dirs_counter,
++					  ext4_count_dirs(sb));
++	if (!err)
++		err = percpu_counter_init(&sbi->s_dirtyclusters_counter, 0);
++	if (err) {
++		ext4_msg(sb, KERN_ERR, "insufficient memory");
++		goto failed_mount6;
++	}
++
++	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG))
++		if (!ext4_fill_flex_info(sb)) {
++			ext4_msg(sb, KERN_ERR,
++			       "unable to initialize "
++			       "flex_bg meta info!");
++			goto failed_mount6;
++		}
++
+ 	err = ext4_register_li_request(sb, first_not_zeroed);
+ 	if (err)
+ 		goto failed_mount6;
+@@ -4215,6 +4203,12 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	ext4_unregister_li_request(sb);
+ failed_mount6:
+ 	ext4_mb_release(sb);
++	if (sbi->s_flex_groups)
++		ext4_kvfree(sbi->s_flex_groups);
++	percpu_counter_destroy(&sbi->s_freeclusters_counter);
++	percpu_counter_destroy(&sbi->s_freeinodes_counter);
++	percpu_counter_destroy(&sbi->s_dirs_counter);
++	percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
+ failed_mount5:
+ 	ext4_ext_release(sb);
+ 	ext4_release_system_zone(sb);
+@@ -4233,12 +4227,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ failed_mount3:
+ 	ext4_es_unregister_shrinker(sbi);
+ 	del_timer_sync(&sbi->s_err_report);
+-	if (sbi->s_flex_groups)
+-		ext4_kvfree(sbi->s_flex_groups);
+-	percpu_counter_destroy(&sbi->s_freeclusters_counter);
+-	percpu_counter_destroy(&sbi->s_freeinodes_counter);
+-	percpu_counter_destroy(&sbi->s_dirs_counter);
+-	percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
+ 	percpu_counter_destroy(&sbi->s_extent_cache_cnt);
+ 	if (sbi->s_mmp_tsk)
+ 		kthread_stop(sbi->s_mmp_tsk);
+@@ -4556,11 +4544,13 @@ static int ext4_commit_super(struct super_block *sb, int sync)
+ 	else
+ 		es->s_kbytes_written =
+ 			cpu_to_le64(EXT4_SB(sb)->s_kbytes_written);
+-	ext4_free_blocks_count_set(es,
++	if (percpu_counter_initialized(&EXT4_SB(sb)->s_freeclusters_counter))
++		ext4_free_blocks_count_set(es,
+ 			EXT4_C2B(EXT4_SB(sb), percpu_counter_sum_positive(
+ 				&EXT4_SB(sb)->s_freeclusters_counter)));
+-	es->s_free_inodes_count =
+-		cpu_to_le32(percpu_counter_sum_positive(
++	if (percpu_counter_initialized(&EXT4_SB(sb)->s_freeinodes_counter))
++		es->s_free_inodes_count =
++			cpu_to_le32(percpu_counter_sum_positive(
+ 				&EXT4_SB(sb)->s_freeinodes_counter));
+ 	BUFFER_TRACE(sbh, "marking dirty");
+ 	ext4_superblock_csum_set(sb);

commit ee3e00e9e7101c80a2ff2d5672d4b486bf001b88
+Author: Theodore Ts'o 
+Date:   Sun Jun 15 16:59:24 2014 -0400
+
+    random: use registers from interrupted code for CPU's w/o a cycle counter
+    
+    For CPU's that don't have a cycle counter, or something equivalent
+    which can be used for random_get_entropy(), random_get_entropy() will
+    always return 0.  In that case, substitute with the saved interrupt
+    registers to add a bit more unpredictability.
+    
+    Some folks have suggested hashing all of the registers
+    unconditionally, but this would increase the overhead of
+    add_interrupt_randomness() by at least an order of magnitude, and this
+    would very likely be unacceptable.
+    
+    The changes in this commit have been benchmarked as mostly unaffecting
+    the overhead of add_interrupt_randomness() if the entropy counter is
+    present, and doubling the overhead if it is not present.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: Jörn Engel 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 914b1575df8f..aa22fe551c2a 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -551,9 +551,8 @@ static void mix_pool_bytes(struct entropy_store *r, const void *in,
+ struct fast_pool {
+ 	__u32		pool[4];
+ 	unsigned long	last;
++	unsigned short	reg_idx;
+ 	unsigned char	count;
+-	unsigned char	notimer_count;
+-	unsigned char	rotate;
+ };
+ 
+ /*
+@@ -857,6 +856,17 @@ static void add_interrupt_bench(cycles_t start)
+ #define add_interrupt_bench(x)
+ #endif
+ 
++static __u32 get_reg(struct fast_pool *f, struct pt_regs *regs)
++{
++	__u32 *ptr = (__u32 *) regs;
++
++	if (regs == NULL)
++		return 0;
++	if (f->reg_idx >= sizeof(struct pt_regs) / sizeof(__u32))
++		f->reg_idx = 0;
++	return *(ptr + f->reg_idx++);
++}
++
+ void add_interrupt_randomness(int irq, int irq_flags)
+ {
+ 	struct entropy_store	*r;
+@@ -869,28 +879,23 @@ void add_interrupt_randomness(int irq, int irq_flags)
+ 	unsigned long		seed;
+ 	int			credit = 0;
+ 
++	if (cycles == 0)
++		cycles = get_reg(fast_pool, regs);
+ 	c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0;
+ 	j_high = (sizeof(now) > 4) ? now >> 32 : 0;
+ 	fast_pool->pool[0] ^= cycles ^ j_high ^ irq;
+ 	fast_pool->pool[1] ^= now ^ c_high;
+ 	ip = regs ? instruction_pointer(regs) : _RET_IP_;
+ 	fast_pool->pool[2] ^= ip;
+-	fast_pool->pool[3] ^= ip >> 32;
++	fast_pool->pool[3] ^= (sizeof(ip) > 4) ? ip >> 32 :
++		get_reg(fast_pool, regs);
+ 
+ 	fast_mix(fast_pool);
+-	if ((irq_flags & __IRQF_TIMER) == 0)
+-		fast_pool->notimer_count++;
+ 	add_interrupt_bench(cycles);
+ 
+-	if (cycles) {
+-		if ((fast_pool->count < 64) &&
+-		    !time_after(now, fast_pool->last + HZ))
+-			return;
+-	} else {
+-		/* CPU does not have a cycle counting register :-( */
+-		if (fast_pool->count < 64)
+-			return;
+-	}
++	if ((fast_pool->count < 64) &&
++	    !time_after(now, fast_pool->last + HZ))
++		return;
+ 
+ 	r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
+ 	if (!spin_trylock(&r->lock))
+@@ -910,18 +915,10 @@ void add_interrupt_randomness(int irq, int irq_flags)
+ 	}
+ 	spin_unlock(&r->lock);
+ 
+-	/*
+-	 * If we have a valid cycle counter or if the majority of
+-	 * interrupts collected were non-timer interrupts, then give
+-	 * an entropy credit of 1 bit.  Yes, this is being very
+-	 * conservative.
+-	 */
+-	if (cycles || (fast_pool->notimer_count >= 32))
+-		credit++;
+-
+-	fast_pool->count = fast_pool->notimer_count = 0;
++	fast_pool->count = 0;
+ 
+-	credit_entropy_bits(r, credit);
++	/* award one bit for the contents of the fast pool */
++	credit_entropy_bits(r, credit + 1);
+ }
+ 
+ #ifdef CONFIG_BLOCK

commit 43759d4f429c8d55fd56f863542e20f4e6e8f589
+Author: Theodore Ts'o 
+Date:   Sat Jun 14 21:43:13 2014 -0400
+
+    random: use an improved fast_mix() function
+    
+    Use more efficient fast_mix() function.  Thanks to George Spelvin for
+    doing the leg work to find a more efficient mixing function.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: George Spelvin 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index dfe918a21e32..d3bb7927fb49 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -267,6 +267,8 @@
+ #define CREATE_TRACE_POINTS
+ #include 
+ 
++/* #define ADD_INTERRUPT_BENCH */
++
+ /*
+  * Configuration information
+  */
+@@ -558,25 +560,29 @@ struct fast_pool {
+  * collector.  It's hardcoded for an 128 bit pool and assumes that any
+  * locks that might be needed are taken by the caller.
+  */
+-static void fast_mix(struct fast_pool *f, __u32 input[4])
++static void fast_mix(struct fast_pool *f)
+ {
+-	__u32		w;
+-	unsigned	input_rotate = f->rotate;
+-
+-	w = rol32(input[0], input_rotate) ^ f->pool[0] ^ f->pool[3];
+-	f->pool[0] = (w >> 3) ^ twist_table[w & 7];
+-	input_rotate = (input_rotate + 14) & 31;
+-	w = rol32(input[1], input_rotate) ^ f->pool[1] ^ f->pool[0];
+-	f->pool[1] = (w >> 3) ^ twist_table[w & 7];
+-	input_rotate = (input_rotate + 7) & 31;
+-	w = rol32(input[2], input_rotate) ^ f->pool[2] ^ f->pool[1];
+-	f->pool[2] = (w >> 3) ^ twist_table[w & 7];
+-	input_rotate = (input_rotate + 7) & 31;
+-	w = rol32(input[3], input_rotate) ^ f->pool[3] ^ f->pool[2];
+-	f->pool[3] = (w >> 3) ^ twist_table[w & 7];
+-	input_rotate = (input_rotate + 7) & 31;
+-
+-	f->rotate = input_rotate;
++	__u32 a = f->pool[0],	b = f->pool[1];
++	__u32 c = f->pool[2],	d = f->pool[3];
++
++	a += b;			c += d;
++	b = rol32(a, 6);	d = rol32(c, 27);
++	d ^= a;			b ^= c;
++
++	a += b;			c += d;
++	b = rol32(a, 16);	d = rol32(c, 14);
++	d ^= a;			b ^= c;
++
++	a += b;			c += d;
++	b = rol32(a, 6);	d = rol32(c, 27);
++	d ^= a;			b ^= c;
++
++	a += b;			c += d;
++	b = rol32(a, 16);	d = rol32(c, 14);
++	d ^= a;			b ^= c;
++
++	f->pool[0] = a;  f->pool[1] = b;
++	f->pool[2] = c;  f->pool[3] = d;
+ 	f->count++;
+ }
+ 
+@@ -829,6 +835,27 @@ EXPORT_SYMBOL_GPL(add_input_randomness);
+ 
+ static DEFINE_PER_CPU(struct fast_pool, irq_randomness);
+ 
++#ifdef ADD_INTERRUPT_BENCH
++static unsigned long avg_cycles, avg_deviation;
++
++#define AVG_SHIFT 8     /* Exponential average factor k=1/256 */
++#define FIXED_1_2 (1 << (AVG_SHIFT-1))
++
++static void add_interrupt_bench(cycles_t start)
++{
++        long delta = random_get_entropy() - start;
++
++        /* Use a weighted moving average */
++        delta = delta - ((avg_cycles + FIXED_1_2) >> AVG_SHIFT);
++        avg_cycles += delta;
++        /* And average deviation */
++        delta = abs(delta) - ((avg_deviation + FIXED_1_2) >> AVG_SHIFT);
++        avg_deviation += delta;
++}
++#else
++#define add_interrupt_bench(x)
++#endif
++
+ void add_interrupt_randomness(int irq, int irq_flags)
+ {
+ 	struct entropy_store	*r;
+@@ -836,22 +863,23 @@ void add_interrupt_randomness(int irq, int irq_flags)
+ 	struct pt_regs		*regs = get_irq_regs();
+ 	unsigned long		now = jiffies;
+ 	cycles_t		cycles = random_get_entropy();
+-	__u32			input[4], c_high, j_high;
++	__u32			c_high, j_high;
+ 	__u64			ip;
+ 	unsigned long		seed;
+ 	int			credit = 0;
+ 
+ 	c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0;
+ 	j_high = (sizeof(now) > 4) ? now >> 32 : 0;
+-	input[0] = cycles ^ j_high ^ irq;
+-	input[1] = now ^ c_high;
++	fast_pool->pool[0] ^= cycles ^ j_high ^ irq;
++	fast_pool->pool[1] ^= now ^ c_high;
+ 	ip = regs ? instruction_pointer(regs) : _RET_IP_;
+-	input[2] = ip;
+-	input[3] = ip >> 32;
++	fast_pool->pool[2] ^= ip;
++	fast_pool->pool[3] ^= ip >> 32;
+ 
+-	fast_mix(fast_pool, input);
++	fast_mix(fast_pool);
+ 	if ((irq_flags & __IRQF_TIMER) == 0)
+ 		fast_pool->notimer_count++;
++	add_interrupt_bench(cycles);
+ 
+ 	if (cycles) {
+ 		if ((fast_pool->count < 64) &&
+@@ -1650,6 +1678,22 @@ struct ctl_table random_table[] = {
+ 		.mode		= 0444,
+ 		.proc_handler	= proc_do_uuid,
+ 	},
++#ifdef ADD_INTERRUPT_BENCH
++	{
++		.procname	= "add_interrupt_avg_cycles",
++		.data		= &avg_cycles,
++		.maxlen		= sizeof(avg_cycles),
++		.mode		= 0444,
++		.proc_handler	= proc_doulongvec_minmax,
++	},
++	{
++		.procname	= "add_interrupt_avg_deviation",
++		.data		= &avg_deviation,
++		.maxlen		= sizeof(avg_deviation),
++		.mode		= 0444,
++		.proc_handler	= proc_doulongvec_minmax,
++	},
++#endif
+ 	{ }
+ };
+ #endif 	/* CONFIG_SYSCTL */

commit 840f95077ffd640df9c74ad9796fa094a5c8075a
+Author: Theodore Ts'o 
+Date:   Sat Jun 14 03:06:57 2014 -0400
+
+    random: clean up interrupt entropy accounting for archs w/o cycle counters
+    
+    For architectures that don't have cycle counters, the algorithm for
+    deciding when to avoid giving entropy credit due to back-to-back timer
+    interrupts didn't make any sense, since we were checking every 64
+    interrupts.  Change it so that we only give an entropy credit if the
+    majority of the interrupts are not based on the timer.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: George Spelvin 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 364a8001a2bd..dfe918a21e32 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -548,9 +548,9 @@ static void mix_pool_bytes(struct entropy_store *r, const void *in,
+ struct fast_pool {
+ 	__u32		pool[4];
+ 	unsigned long	last;
+-	unsigned short	count;
++	unsigned char	count;
++	unsigned char	notimer_count;
+ 	unsigned char	rotate;
+-	unsigned char	last_timer_intr;
+ };
+ 
+ /*
+@@ -850,15 +850,23 @@ void add_interrupt_randomness(int irq, int irq_flags)
+ 	input[3] = ip >> 32;
+ 
+ 	fast_mix(fast_pool, input);
++	if ((irq_flags & __IRQF_TIMER) == 0)
++		fast_pool->notimer_count++;
+ 
+-	if ((fast_pool->count & 63) && !time_after(now, fast_pool->last + HZ))
+-		return;
++	if (cycles) {
++		if ((fast_pool->count < 64) &&
++		    !time_after(now, fast_pool->last + HZ))
++			return;
++	} else {
++		/* CPU does not have a cycle counting register :-( */
++		if (fast_pool->count < 64)
++			return;
++	}
+ 
+ 	r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
+-	if (!spin_trylock(&r->lock)) {
+-		fast_pool->count--;
++	if (!spin_trylock(&r->lock))
+ 		return;
+-	}
++
+ 	fast_pool->last = now;
+ 	__mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool));
+ 
+@@ -874,19 +882,15 @@ void add_interrupt_randomness(int irq, int irq_flags)
+ 	spin_unlock(&r->lock);
+ 
+ 	/*
+-	 * If we don't have a valid cycle counter, and we see
+-	 * back-to-back timer interrupts, then skip giving credit for
+-	 * any entropy, otherwise credit 1 bit.
++	 * If we have a valid cycle counter or if the majority of
++	 * interrupts collected were non-timer interrupts, then give
++	 * an entropy credit of 1 bit.  Yes, this is being very
++	 * conservative.
+ 	 */
+-	credit++;
+-	if (cycles == 0) {
+-		if (irq_flags & __IRQF_TIMER) {
+-			if (fast_pool->last_timer_intr)
+-				credit--;
+-			fast_pool->last_timer_intr = 1;
+-		} else
+-			fast_pool->last_timer_intr = 0;
+-	}
++	if (cycles || (fast_pool->notimer_count >= 32))
++		credit++;
++
++	fast_pool->count = fast_pool->notimer_count = 0;
+ 
+ 	credit_entropy_bits(r, credit);
+ }

commit cff850312cc7c0e0b9fe8b573687812dea232031
+Author: Theodore Ts'o 
+Date:   Tue Jun 10 23:18:16 2014 -0400
+
+    random: only update the last_pulled time if we actually transferred entropy
+    
+    In xfer_secondary_pull(), check to make sure we need to pull from the
+    secondary pool before checking and potentially updating the
+    last_pulled time.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: George Spelvin 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index bc0de22f31f4..364a8001a2bd 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -920,6 +920,11 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
+ static void _xfer_secondary_pool(struct entropy_store *r, size_t nbytes);
+ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
+ {
++	if (!r->pull ||
++	    r->entropy_count >= (nbytes << (ENTROPY_SHIFT + 3)) ||
++	    r->entropy_count > r->poolinfo->poolfracbits)
++		return;
++
+ 	if (r->limit == 0 && random_min_urandom_seed) {
+ 		unsigned long now = jiffies;
+ 
+@@ -928,10 +933,8 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
+ 			return;
+ 		r->last_pulled = now;
+ 	}
+-	if (r->pull &&
+-	    r->entropy_count < (nbytes << (ENTROPY_SHIFT + 3)) &&
+-	    r->entropy_count < r->poolinfo->poolfracbits)
+-		_xfer_secondary_pool(r, nbytes);
++
++	_xfer_secondary_pool(r, nbytes);
+ }
+ 
+ static void _xfer_secondary_pool(struct entropy_store *r, size_t nbytes)

commit 85608f8e16c28f818f6bb9918958d231afa8bec2
+Author: Theodore Ts'o 
+Date:   Tue Jun 10 23:09:20 2014 -0400
+
+    random: remove unneeded hash of a portion of the entropy pool
+    
+    We previously extracted a portion of the entropy pool in
+    mix_pool_bytes() and hashed it in to avoid racing CPU's from returning
+    duplicate random values.  Now that we are using a spinlock to prevent
+    this from happening, this is no longer necessary.  So remove it, to
+    simplify the code a bit.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: George Spelvin 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 922a2e4089f9..bc0de22f31f4 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -481,9 +481,9 @@ static __u32 const twist_table[8] = {
+  * the entropy is concentrated in the low-order bits.
+  */
+ static void _mix_pool_bytes(struct entropy_store *r, const void *in,
+-			    int nbytes, __u8 out[64])
++			    int nbytes)
+ {
+-	unsigned long i, j, tap1, tap2, tap3, tap4, tap5;
++	unsigned long i, tap1, tap2, tap3, tap4, tap5;
+ 	int input_rotate;
+ 	int wordmask = r->poolinfo->poolwords - 1;
+ 	const char *bytes = in;
+@@ -525,27 +525,23 @@ static void _mix_pool_bytes(struct entropy_store *r, const void *in,
+ 
+ 	r->input_rotate = input_rotate;
+ 	r->add_ptr = i;
+-
+-	if (out)
+-		for (j = 0; j < 16; j++)
+-			((__u32 *)out)[j] = r->pool[(i - j) & wordmask];
+ }
+ 
+ static void __mix_pool_bytes(struct entropy_store *r, const void *in,
+-			     int nbytes, __u8 out[64])
++			     int nbytes)
+ {
+ 	trace_mix_pool_bytes_nolock(r->name, nbytes, _RET_IP_);
+-	_mix_pool_bytes(r, in, nbytes, out);
++	_mix_pool_bytes(r, in, nbytes);
+ }
+ 
+ static void mix_pool_bytes(struct entropy_store *r, const void *in,
+-			   int nbytes, __u8 out[64])
++			   int nbytes)
+ {
+ 	unsigned long flags;
+ 
+ 	trace_mix_pool_bytes(r->name, nbytes, _RET_IP_);
+ 	spin_lock_irqsave(&r->lock, flags);
+-	_mix_pool_bytes(r, in, nbytes, out);
++	_mix_pool_bytes(r, in, nbytes);
+ 	spin_unlock_irqrestore(&r->lock, flags);
+ }
+ 
+@@ -737,13 +733,13 @@ void add_device_randomness(const void *buf, unsigned int size)
+ 
+ 	trace_add_device_randomness(size, _RET_IP_);
+ 	spin_lock_irqsave(&input_pool.lock, flags);
+-	_mix_pool_bytes(&input_pool, buf, size, NULL);
+-	_mix_pool_bytes(&input_pool, &time, sizeof(time), NULL);
++	_mix_pool_bytes(&input_pool, buf, size);
++	_mix_pool_bytes(&input_pool, &time, sizeof(time));
+ 	spin_unlock_irqrestore(&input_pool.lock, flags);
+ 
+ 	spin_lock_irqsave(&nonblocking_pool.lock, flags);
+-	_mix_pool_bytes(&nonblocking_pool, buf, size, NULL);
+-	_mix_pool_bytes(&nonblocking_pool, &time, sizeof(time), NULL);
++	_mix_pool_bytes(&nonblocking_pool, buf, size);
++	_mix_pool_bytes(&nonblocking_pool, &time, sizeof(time));
+ 	spin_unlock_irqrestore(&nonblocking_pool.lock, flags);
+ }
+ EXPORT_SYMBOL(add_device_randomness);
+@@ -776,7 +772,7 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
+ 	sample.cycles = random_get_entropy();
+ 	sample.num = num;
+ 	r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
+-	mix_pool_bytes(r, &sample, sizeof(sample), NULL);
++	mix_pool_bytes(r, &sample, sizeof(sample));
+ 
+ 	/*
+ 	 * Calculate number of bits of randomness we probably added.
+@@ -864,7 +860,7 @@ void add_interrupt_randomness(int irq, int irq_flags)
+ 		return;
+ 	}
+ 	fast_pool->last = now;
+-	__mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool), NULL);
++	__mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool));
+ 
+ 	/*
+ 	 * If we have architectural seed generator, produce a seed and
+@@ -872,7 +868,7 @@ void add_interrupt_randomness(int irq, int irq_flags)
+ 	 * 50% entropic.
+ 	 */
+ 	if (arch_get_random_seed_long(&seed)) {
+-		__mix_pool_bytes(r, &seed, sizeof(seed), NULL);
++		__mix_pool_bytes(r, &seed, sizeof(seed));
+ 		credit += sizeof(seed) * 4;
+ 	}
+ 	spin_unlock(&r->lock);
+@@ -955,7 +951,7 @@ static void _xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
+ 				  ENTROPY_BITS(r), ENTROPY_BITS(r->pull));
+ 	bytes = extract_entropy(r->pull, tmp, bytes,
+ 				random_read_wakeup_bits / 8, rsvd_bytes);
+-	mix_pool_bytes(r, tmp, bytes, NULL);
++	mix_pool_bytes(r, tmp, bytes);
+ 	credit_entropy_bits(r, bytes*8);
+ }
+ 
+@@ -1031,7 +1027,6 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
+ 		unsigned long l[LONGS(20)];
+ 	} hash;
+ 	__u32 workspace[SHA_WORKSPACE_WORDS];
+-	__u8 extract[64];
+ 	unsigned long flags;
+ 
+ 	/*
+@@ -1060,15 +1055,9 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
+ 	 * brute-forcing the feedback as hard as brute-forcing the
+ 	 * hash.
+ 	 */
+-	__mix_pool_bytes(r, hash.w, sizeof(hash.w), extract);
++	__mix_pool_bytes(r, hash.w, sizeof(hash.w));
+ 	spin_unlock_irqrestore(&r->lock, flags);
+ 
+-	/*
+-	 * To avoid duplicates, we atomically extract a portion of the
+-	 * pool while mixing, and hash one final time.
+-	 */
+-	sha_transform(hash.w, extract, workspace);
+-	memset(extract, 0, sizeof(extract));
+ 	memset(workspace, 0, sizeof(workspace));
+ 
+ 	/*
+@@ -1255,14 +1244,14 @@ static void init_std_data(struct entropy_store *r)
+ 	unsigned long rv;
+ 
+ 	r->last_pulled = jiffies;
+-	mix_pool_bytes(r, &now, sizeof(now), NULL);
++	mix_pool_bytes(r, &now, sizeof(now));
+ 	for (i = r->poolinfo->poolbytes; i > 0; i -= sizeof(rv)) {
+ 		if (!arch_get_random_seed_long(&rv) &&
+ 		    !arch_get_random_long(&rv))
+ 			rv = random_get_entropy();
+-		mix_pool_bytes(r, &rv, sizeof(rv), NULL);
++		mix_pool_bytes(r, &rv, sizeof(rv));
+ 	}
+-	mix_pool_bytes(r, utsname(), sizeof(*(utsname())), NULL);
++	mix_pool_bytes(r, utsname(), sizeof(*(utsname())));
+ }
+ 
+ /*
+@@ -1325,7 +1314,7 @@ static int arch_random_refill(void)
+ 	if (n) {
+ 		unsigned int rand_bytes = n * sizeof(unsigned long);
+ 
+-		mix_pool_bytes(&input_pool, buf, rand_bytes, NULL);
++		mix_pool_bytes(&input_pool, buf, rand_bytes);
+ 		credit_entropy_bits(&input_pool, rand_bytes*4);
+ 	}
+ 
+@@ -1415,7 +1404,7 @@ write_pool(struct entropy_store *r, const char __user *buffer, size_t count)
+ 		count -= bytes;
+ 		p += bytes;
+ 
+-		mix_pool_bytes(r, buf, bytes, NULL);
++		mix_pool_bytes(r, buf, bytes);
+ 		cond_resched();
+ 	}
+ 

commit 91fcb532efe366d79b93a3c8c368b9dca6176a55
+Author: Theodore Ts'o 
+Date:   Tue Jun 10 22:46:37 2014 -0400
+
+    random: always update the entropy pool under the spinlock
+    
+    Instead of using lockless techniques introduced in commit
+    902c098a3663, use spin_trylock to try to grab entropy pool's lock.  If
+    we can't get the lock, then just try again on the next interrupt.
+    
+    Based on discussions with George Spelvin.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: George Spelvin 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 0a7ac0a7b252..922a2e4089f9 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -495,9 +495,8 @@ static void _mix_pool_bytes(struct entropy_store *r, const void *in,
+ 	tap4 = r->poolinfo->tap4;
+ 	tap5 = r->poolinfo->tap5;
+ 
+-	smp_rmb();
+-	input_rotate = ACCESS_ONCE(r->input_rotate);
+-	i = ACCESS_ONCE(r->add_ptr);
++	input_rotate = r->input_rotate;
++	i = r->add_ptr;
+ 
+ 	/* mix one byte at a time to simplify size handling and churn faster */
+ 	while (nbytes--) {
+@@ -524,9 +523,8 @@ static void _mix_pool_bytes(struct entropy_store *r, const void *in,
+ 		input_rotate = (input_rotate + (i ? 7 : 14)) & 31;
+ 	}
+ 
+-	ACCESS_ONCE(r->input_rotate) = input_rotate;
+-	ACCESS_ONCE(r->add_ptr) = i;
+-	smp_wmb();
++	r->input_rotate = input_rotate;
++	r->add_ptr = i;
+ 
+ 	if (out)
+ 		for (j = 0; j < 16; j++)
+@@ -845,7 +843,7 @@ void add_interrupt_randomness(int irq, int irq_flags)
+ 	__u32			input[4], c_high, j_high;
+ 	__u64			ip;
+ 	unsigned long		seed;
+-	int			credit;
++	int			credit = 0;
+ 
+ 	c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0;
+ 	j_high = (sizeof(now) > 4) ? now >> 32 : 0;
+@@ -860,36 +858,40 @@ void add_interrupt_randomness(int irq, int irq_flags)
+ 	if ((fast_pool->count & 63) && !time_after(now, fast_pool->last + HZ))
+ 		return;
+ 
+-	fast_pool->last = now;
+-
+ 	r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
++	if (!spin_trylock(&r->lock)) {
++		fast_pool->count--;
++		return;
++	}
++	fast_pool->last = now;
+ 	__mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool), NULL);
+ 
++	/*
++	 * If we have architectural seed generator, produce a seed and
++	 * add it to the pool.  For the sake of paranoia count it as
++	 * 50% entropic.
++	 */
++	if (arch_get_random_seed_long(&seed)) {
++		__mix_pool_bytes(r, &seed, sizeof(seed), NULL);
++		credit += sizeof(seed) * 4;
++	}
++	spin_unlock(&r->lock);
++
+ 	/*
+ 	 * If we don't have a valid cycle counter, and we see
+ 	 * back-to-back timer interrupts, then skip giving credit for
+ 	 * any entropy, otherwise credit 1 bit.
+ 	 */
+-	credit = 1;
++	credit++;
+ 	if (cycles == 0) {
+ 		if (irq_flags & __IRQF_TIMER) {
+ 			if (fast_pool->last_timer_intr)
+-				credit = 0;
++				credit--;
+ 			fast_pool->last_timer_intr = 1;
+ 		} else
+ 			fast_pool->last_timer_intr = 0;
+ 	}
+ 
+-	/*
+-	 * If we have architectural seed generator, produce a seed and
+-	 * add it to the pool.  For the sake of paranoia count it as
+-	 * 50% entropic.
+-	 */
+-	if (arch_get_random_seed_long(&seed)) {
+-		__mix_pool_bytes(r, &seed, sizeof(seed), NULL);
+-		credit += sizeof(seed) * 4;
+-	}
+-
+ 	credit_entropy_bits(r, credit);
+ }
+ 

commit 3f1f9b851311a76226140b55b1ea22111234a7c2
+Author: Theodore Ts'o 
+Date:   Sat Jul 12 15:32:24 2014 -0400
+
+    ext4: fix a potential deadlock in __ext4_es_shrink()
+    
+    This fixes the following lockdep complaint:
+    
+    [ INFO: possible circular locking dependency detected ]
+    3.16.0-rc2-mm1+ #7 Tainted: G           O
+    -------------------------------------------------------
+    kworker/u24:0/4356 is trying to acquire lock:
+     (&(&sbi->s_es_lru_lock)->rlock){+.+.-.}, at: [] __ext4_es_shrink+0x4f/0x2e0
+    
+    but task is already holding lock:
+     (&ei->i_es_lock){++++-.}, at: [] ext4_es_insert_extent+0x71/0x180
+    
+    which lock already depends on the new lock.
+    
+     Possible unsafe locking scenario:
+    
+           CPU0                    CPU1
+           ----                    ----
+      lock(&ei->i_es_lock);
+                                   lock(&(&sbi->s_es_lru_lock)->rlock);
+                                   lock(&ei->i_es_lock);
+      lock(&(&sbi->s_es_lru_lock)->rlock);
+    
+     *** DEADLOCK ***
+    
+    6 locks held by kworker/u24:0/4356:
+     #0:  ("writeback"){.+.+.+}, at: [] process_one_work+0x180/0x560
+     #1:  ((&(&wb->dwork)->work)){+.+.+.}, at: [] process_one_work+0x180/0x560
+     #2:  (&type->s_umount_key#22){++++++}, at: [] grab_super_passive+0x44/0x90
+     #3:  (jbd2_handle){+.+...}, at: [] start_this_handle+0x189/0x5f0
+     #4:  (&ei->i_data_sem){++++..}, at: [] ext4_map_blocks+0x132/0x550
+     #5:  (&ei->i_es_lock){++++-.}, at: [] ext4_es_insert_extent+0x71/0x180
+    
+    stack backtrace:
+    CPU: 0 PID: 4356 Comm: kworker/u24:0 Tainted: G           O   3.16.0-rc2-mm1+ #7
+    Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
+    Workqueue: writeback bdi_writeback_workfn (flush-253:0)
+     ffffffff8213dce0 ffff880014b07538 ffffffff815df0bb 0000000000000007
+     ffffffff8213e040 ffff880014b07588 ffffffff815db3dd ffff880014b07568
+     ffff880014b07610 ffff88003b868930 ffff88003b868908 ffff88003b868930
+    Call Trace:
+     [] dump_stack+0x4e/0x68
+     [] print_circular_bug+0x1fb/0x20c
+     [] __lock_acquire+0x163e/0x1d00
+     [] ? retint_restore_args+0xe/0xe
+     [] ? __slab_alloc+0x4a8/0x4ce
+     [] ? __ext4_es_shrink+0x4f/0x2e0
+     [] lock_acquire+0x87/0x120
+     [] ? __ext4_es_shrink+0x4f/0x2e0
+     [] ? ext4_es_free_extent+0x5d/0x70
+     [] _raw_spin_lock+0x39/0x50
+     [] ? __ext4_es_shrink+0x4f/0x2e0
+     [] ? kmem_cache_alloc+0x18b/0x1a0
+     [] __ext4_es_shrink+0x4f/0x2e0
+     [] ext4_es_insert_extent+0xc8/0x180
+     [] ext4_map_blocks+0x1c4/0x550
+     [] ext4_writepages+0x6d4/0xd00
+            ...
+    
+    Reported-by: Minchan Kim 
+    Signed-off-by: Theodore Ts'o 
+    Reported-by: Minchan Kim 
+    Cc: stable@vger.kernel.org
+    Cc: Zheng Liu 
+
+diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
+index 3f5c188953a4..0b7e28e7eaa4 100644
+--- a/fs/ext4/extents_status.c
++++ b/fs/ext4/extents_status.c
+@@ -966,10 +966,10 @@ static int __ext4_es_shrink(struct ext4_sb_info *sbi, int nr_to_scan,
+ 			continue;
+ 		}
+ 
+-		if (ei->i_es_lru_nr == 0 || ei == locked_ei)
++		if (ei->i_es_lru_nr == 0 || ei == locked_ei ||
++		    !write_trylock(&ei->i_es_lock))
+ 			continue;
+ 
+-		write_lock(&ei->i_es_lock);
+ 		shrunk = __es_try_to_reclaim_extents(ei, nr_to_scan);
+ 		if (ei->i_es_lru_nr == 0)
+ 			list_del_init(&ei->i_es_lru);

commit f9ae9cf5d72b3926ca48ea60e15bdbb840f42372
+Author: Theodore Ts'o 
+Date:   Fri Jul 11 13:55:40 2014 -0400
+
+    ext4: revert commit which was causing fs corruption after journal replays
+    
+    Commit 007649375f6af2 ("ext4: initialize multi-block allocator before
+    checking block descriptors") causes the block group descriptor's count
+    of the number of free blocks to become inconsistent with the number of
+    free blocks in the allocation bitmap.  This is a harmless form of fs
+    corruption, but it causes the kernel to potentially remount the file
+    system read-only, or to panic, depending on the file systems's error
+    behavior.
+    
+    Thanks to Eric Whitney for his tireless work to reproduce and to find
+    the guilty commit.
+    
+    Fixes: 007649375f6af2 ("ext4: initialize multi-block allocator before checking block descriptors"
+    
+    Cc: stable@vger.kernel.org  # 3.15
+    Reported-by: David Jander 
+    Reported-by: Matteo Croce 
+    Tested-by: Eric Whitney 
+    Suggested-by: Eric Whitney 
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 6297c07c937f..6df7bc611dbd 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3879,38 +3879,19 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 			goto failed_mount2;
+ 		}
+ 	}
+-
+-	/*
+-	 * set up enough so that it can read an inode,
+-	 * and create new inode for buddy allocator
+-	 */
+-	sbi->s_gdb_count = db_count;
+-	if (!test_opt(sb, NOLOAD) &&
+-	    EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL))
+-		sb->s_op = &ext4_sops;
+-	else
+-		sb->s_op = &ext4_nojournal_sops;
+-
+-	ext4_ext_init(sb);
+-	err = ext4_mb_init(sb);
+-	if (err) {
+-		ext4_msg(sb, KERN_ERR, "failed to initialize mballoc (%d)",
+-			 err);
+-		goto failed_mount2;
+-	}
+-
+ 	if (!ext4_check_descriptors(sb, &first_not_zeroed)) {
+ 		ext4_msg(sb, KERN_ERR, "group descriptors corrupted!");
+-		goto failed_mount2a;
++		goto failed_mount2;
+ 	}
+ 	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG))
+ 		if (!ext4_fill_flex_info(sb)) {
+ 			ext4_msg(sb, KERN_ERR,
+ 			       "unable to initialize "
+ 			       "flex_bg meta info!");
+-			goto failed_mount2a;
++			goto failed_mount2;
+ 		}
+ 
++	sbi->s_gdb_count = db_count;
+ 	get_random_bytes(&sbi->s_next_generation, sizeof(u32));
+ 	spin_lock_init(&sbi->s_next_gen_lock);
+ 
+@@ -3945,6 +3926,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	sbi->s_stripe = ext4_get_stripe_size(sbi);
+ 	sbi->s_extent_max_zeroout_kb = 32;
+ 
++	/*
++	 * set up enough so that it can read an inode
++	 */
++	if (!test_opt(sb, NOLOAD) &&
++	    EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL))
++		sb->s_op = &ext4_sops;
++	else
++		sb->s_op = &ext4_nojournal_sops;
+ 	sb->s_export_op = &ext4_export_ops;
+ 	sb->s_xattr = ext4_xattr_handlers;
+ #ifdef CONFIG_QUOTA
+@@ -4134,13 +4123,21 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	if (err) {
+ 		ext4_msg(sb, KERN_ERR, "failed to reserve %llu clusters for "
+ 			 "reserved pool", ext4_calculate_resv_clusters(sb));
+-		goto failed_mount5;
++		goto failed_mount4a;
+ 	}
+ 
+ 	err = ext4_setup_system_zone(sb);
+ 	if (err) {
+ 		ext4_msg(sb, KERN_ERR, "failed to initialize system "
+ 			 "zone (%d)", err);
++		goto failed_mount4a;
++	}
++
++	ext4_ext_init(sb);
++	err = ext4_mb_init(sb);
++	if (err) {
++		ext4_msg(sb, KERN_ERR, "failed to initialize mballoc (%d)",
++			 err);
+ 		goto failed_mount5;
+ 	}
+ 
+@@ -4217,8 +4214,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ failed_mount7:
+ 	ext4_unregister_li_request(sb);
+ failed_mount6:
+-	ext4_release_system_zone(sb);
++	ext4_mb_release(sb);
+ failed_mount5:
++	ext4_ext_release(sb);
++	ext4_release_system_zone(sb);
++failed_mount4a:
+ 	dput(sb->s_root);
+ 	sb->s_root = NULL;
+ failed_mount4:
+@@ -4242,14 +4242,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	percpu_counter_destroy(&sbi->s_extent_cache_cnt);
+ 	if (sbi->s_mmp_tsk)
+ 		kthread_stop(sbi->s_mmp_tsk);
+-failed_mount2a:
+-	ext4_mb_release(sb);
+ failed_mount2:
+ 	for (i = 0; i < db_count; i++)
+ 		brelse(sbi->s_group_desc[i]);
+ 	ext4_kvfree(sbi->s_group_desc);
+ failed_mount:
+-	ext4_ext_release(sb);
+ 	if (sbi->s_chksum_driver)
+ 		crypto_free_shash(sbi->s_chksum_driver);
+ 	if (sbi->s_proc) {

commit 94d4c066a4ff170a2671b1a9b153febbf36796f6
+Author: Theodore Ts'o 
+Date:   Sat Jul 5 19:15:50 2014 -0400
+
+    ext4: clarify ext4_error message in ext4_mb_generate_buddy_error()
+    
+    We are spending a lot of time explaining to users what this error
+    means.  Let's try to improve the message to avoid this problem.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 7f72f50a8fa7..2dcb936be90e 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -752,8 +752,8 @@ void ext4_mb_generate_buddy(struct super_block *sb,
+ 
+ 	if (free != grp->bb_free) {
+ 		ext4_grp_locked_error(sb, group, 0, 0,
+-				      "%u clusters in bitmap, %u in gd; "
+-				      "block bitmap corrupt.",
++				      "block bitmap and bg descriptor "
++				      "inconsistent: %u vs %u free clusters",
+ 				      free, grp->bb_free);
+ 		/*
+ 		 * If we intend to continue, we consider group descriptor

commit ae0f78de2c43b6fadd007c231a352b13b5be8ed2
+Author: Theodore Ts'o 
+Date:   Sat Jul 5 18:40:52 2014 -0400
+
+    ext4: clarify error count warning messages
+    
+    Make it clear that values printed are times, and that it is error
+    since last fsck. Also add note about fsck version required.
+    
+    Signed-off-by: Pavel Machek 
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Andreas Dilger 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index b9b9aabfb4d2..342394772b6c 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2809,10 +2809,11 @@ static void print_daily_error_info(unsigned long arg)
+ 	es = sbi->s_es;
+ 
+ 	if (es->s_error_count)
+-		ext4_msg(sb, KERN_NOTICE, "error count: %u",
++		/* fsck newer than v1.41.13 is needed to clean this condition. */
++		ext4_msg(sb, KERN_NOTICE, "error count since last fsck: %u",
+ 			 le32_to_cpu(es->s_error_count));
+ 	if (es->s_first_error_time) {
+-		printk(KERN_NOTICE "EXT4-fs (%s): initial error at %u: %.*s:%d",
++		printk(KERN_NOTICE "EXT4-fs (%s): initial error at time %u: %.*s:%d",
+ 		       sb->s_id, le32_to_cpu(es->s_first_error_time),
+ 		       (int) sizeof(es->s_first_error_func),
+ 		       es->s_first_error_func,
+@@ -2826,7 +2827,7 @@ static void print_daily_error_info(unsigned long arg)
+ 		printk("\n");
+ 	}
+ 	if (es->s_last_error_time) {
+-		printk(KERN_NOTICE "EXT4-fs (%s): last error at %u: %.*s:%d",
++		printk(KERN_NOTICE "EXT4-fs (%s): last error at time %u: %.*s:%d",
+ 		       sb->s_id, le32_to_cpu(es->s_last_error_time),
+ 		       (int) sizeof(es->s_last_error_func),
+ 		       es->s_last_error_func,

commit 61c219f5814277ecb71d64cb30297028d6665979
+Author: Theodore Ts'o 
+Date:   Sat Jul 5 16:28:35 2014 -0400
+
+    ext4: fix unjournalled bg descriptor while initializing inode bitmap
+    
+    The first time that we allocate from an uninitialized inode allocation
+    bitmap, if the block allocation bitmap is also uninitalized, we need
+    to get write access to the block group descriptor before we start
+    modifying the block group descriptor flags and updating the free block
+    count, etc.  Otherwise, there is the potential of a bad journal
+    checksum (if journal checksums are enabled), and of the file system
+    becoming inconsistent if we crash at exactly the wrong time.
+    
+    Signed-off-by: Theodore Ts'o 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index a87455df38bc..0840bf321cdb 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -874,6 +874,13 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
+ 		goto out;
+ 	}
+ 
++	BUFFER_TRACE(group_desc_bh, "get_write_access");
++	err = ext4_journal_get_write_access(handle, group_desc_bh);
++	if (err) {
++		ext4_std_error(sb, err);
++		goto out;
++	}
++
+ 	/* We may have to initialize the block bitmap if it isn't already */
+ 	if (ext4_has_group_desc_csum(sb) &&
+ 	    gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
+@@ -910,13 +917,6 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
+ 		}
+ 	}
+ 
+-	BUFFER_TRACE(group_desc_bh, "get_write_access");
+-	err = ext4_journal_get_write_access(handle, group_desc_bh);
+-	if (err) {
+-		ext4_std_error(sb, err);
+-		goto out;
+-	}
+-
+ 	/* Update the relevant bg descriptor fields */
+ 	if (ext4_has_group_desc_csum(sb)) {
+ 		int free;

commit e33ba5fa7afce1a9f159704121d4e4d110df8185
+Author: Theodore Ts'o 
+Date:   Sun Jun 15 21:04:32 2014 -0400
+
+    random: fix nasty entropy accounting bug
+    
+    Commit 0fb7a01af5b0 "random: simplify accounting code", introduced in
+    v3.15, has a very nasty accounting problem when the entropy pool has
+    has fewer bytes of entropy than the number of requested reserved
+    bytes.  In that case, "have_bytes - reserved" goes negative, and since
+    size_t is unsigned, the expression:
+    
+           ibytes = min_t(size_t, ibytes, have_bytes - reserved);
+    
+    ... does not do the right thing.  This is rather bad, because it
+    defeats the catastrophic reseeding feature in the
+    xfer_secondary_pool() path.
+    
+    It also can cause the "BUG: spinlock trylock failure on UP" for some
+    kernel configurations when prandom_reseed() calls get_random_bytes()
+    in the early init, since when the entropy count gets corrupted,
+    credit_entropy_bits() erroneously believes that the nonblocking pool
+    has been fully initialized (when in fact it is not), and so it calls
+    prandom_reseed(true) recursively leading to the spinlock BUG.
+    
+    The logic is *not* the same it was originally, but in the cases where
+    it matters, the behavior is the same, and the resulting code is
+    hopefully easier to read and understand.
+    
+    Fixes: 0fb7a01af5b0 "random: simplify accounting code"
+    Signed-off-by: Theodore Ts'o 
+    Cc: Greg Price 
+    Cc: stable@vger.kernel.org  #v3.15
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 102c50d38902..2b6e4cd8de8e 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -979,7 +979,6 @@ static void push_to_pool(struct work_struct *work)
+ static size_t account(struct entropy_store *r, size_t nbytes, int min,
+ 		      int reserved)
+ {
+-	int have_bytes;
+ 	int entropy_count, orig;
+ 	size_t ibytes;
+ 
+@@ -988,17 +987,19 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
+ 	/* Can we pull enough? */
+ retry:
+ 	entropy_count = orig = ACCESS_ONCE(r->entropy_count);
+-	have_bytes = entropy_count >> (ENTROPY_SHIFT + 3);
+ 	ibytes = nbytes;
+ 	/* If limited, never pull more than available */
+-	if (r->limit)
+-		ibytes = min_t(size_t, ibytes, have_bytes - reserved);
++	if (r->limit) {
++		int have_bytes = entropy_count >> (ENTROPY_SHIFT + 3);
++
++		if ((have_bytes -= reserved) < 0)
++			have_bytes = 0;
++		ibytes = min_t(size_t, ibytes, have_bytes);
++	}
+ 	if (ibytes < min)
+ 		ibytes = 0;
+-	if (have_bytes >= ibytes + reserved)
+-		entropy_count -= ibytes << (ENTROPY_SHIFT + 3);
+-	else
+-		entropy_count = reserved << (ENTROPY_SHIFT + 3);
++	if ((entropy_count -= ibytes << (ENTROPY_SHIFT + 3)) < 0)
++		entropy_count = 0;
+ 
+ 	if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
+ 		goto retry;

commit f9c6d4987b23e0a514464bae6771933a48e4cd01
+Author: Theodore Ts'o 
+Date:   Fri May 16 21:40:41 2014 -0400
+
+    random: fix BUG_ON caused by accounting simplification
+    
+    Commit ee1de406ba6eb1 ("random: simplify accounting logic") simplified
+    things too much, in that it allows the following to trigger an
+    overflow that results in a BUG_ON crash:
+    
+    dd if=/dev/urandom of=/dev/zero bs=67108707 count=1
+    
+    Thanks to Peter Zihlstra for discovering the crash, and Hannes
+    Frederic for analyizing the root cause.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reported-by: Peter Zijlstra 
+    Reported-by: Hannes Frederic Sowa 
+    Cc: Greg Price 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 6b75713d953a..102c50d38902 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -995,8 +995,11 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
+ 		ibytes = min_t(size_t, ibytes, have_bytes - reserved);
+ 	if (ibytes < min)
+ 		ibytes = 0;
+-	entropy_count = max_t(int, 0,
+-			      entropy_count - (ibytes << (ENTROPY_SHIFT + 3)));
++	if (have_bytes >= ibytes + reserved)
++		entropy_count -= ibytes << (ENTROPY_SHIFT + 3);
++	else
++		entropy_count = reserved << (ENTROPY_SHIFT + 3);
++
+ 	if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
+ 		goto retry;
+ 

commit 202ee5df38b33f7ea28286807a0b548b49613194
+Author: Theodore Ts'o 
+Date:   Mon Apr 21 14:37:55 2014 -0400
+
+    ext4: add a new spinlock i_raw_lock to protect the ext4's raw inode
+    
+    To avoid potential data races, use a spinlock which protects the raw
+    (on-disk) inode.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 86c2cda208ea..1d08a1b51bdd 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -875,6 +875,8 @@ struct ext4_inode_info {
+ 	struct inode vfs_inode;
+ 	struct jbd2_inode *jinode;
+ 
++	spinlock_t i_raw_lock;	/* protects updates to the raw inode */
++
+ 	/*
+ 	 * File creation time. Its function is same as that of
+ 	 * struct timespec i_{a,c,m}time in the generic inode.
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 7dfbcbba67d5..9b3c52fbe86d 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4305,12 +4305,15 @@ static int ext4_do_update_inode(handle_t *handle,
+ 	struct ext4_inode *raw_inode = ext4_raw_inode(iloc);
+ 	struct ext4_inode_info *ei = EXT4_I(inode);
+ 	struct buffer_head *bh = iloc->bh;
++	struct super_block *sb = inode->i_sb;
+ 	int err = 0, rc, block;
+-	int need_datasync = 0;
++	int need_datasync = 0, set_large_file = 0;
+ 	uid_t i_uid;
+ 	gid_t i_gid;
+ 
+-	/* For fields not not tracking in the in-memory inode,
++	spin_lock(&ei->i_raw_lock);
++
++	/* For fields not tracked in the in-memory inode,
+ 	 * initialise them to zero for new inodes. */
+ 	if (ext4_test_inode_state(inode, EXT4_STATE_NEW))
+ 		memset(raw_inode, 0, EXT4_SB(inode->i_sb)->s_inode_size);
+@@ -4348,8 +4351,10 @@ static int ext4_do_update_inode(handle_t *handle,
+ 	EXT4_INODE_SET_XTIME(i_atime, inode, raw_inode);
+ 	EXT4_EINODE_SET_XTIME(i_crtime, ei, raw_inode);
+ 
+-	if (ext4_inode_blocks_set(handle, raw_inode, ei))
++	if (ext4_inode_blocks_set(handle, raw_inode, ei)) {
++		spin_unlock(&ei->i_raw_lock);
+ 		goto out_brelse;
++	}
+ 	raw_inode->i_dtime = cpu_to_le32(ei->i_dtime);
+ 	raw_inode->i_flags = cpu_to_le32(ei->i_flags & 0xFFFFFFFF);
+ 	if (likely(!test_opt2(inode->i_sb, HURD_COMPAT)))
+@@ -4361,24 +4366,11 @@ static int ext4_do_update_inode(handle_t *handle,
+ 		need_datasync = 1;
+ 	}
+ 	if (ei->i_disksize > 0x7fffffffULL) {
+-		struct super_block *sb = inode->i_sb;
+ 		if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
+ 				EXT4_FEATURE_RO_COMPAT_LARGE_FILE) ||
+ 				EXT4_SB(sb)->s_es->s_rev_level ==
+-				cpu_to_le32(EXT4_GOOD_OLD_REV)) {
+-			/* If this is the first large file
+-			 * created, add a flag to the superblock.
+-			 */
+-			err = ext4_journal_get_write_access(handle,
+-					EXT4_SB(sb)->s_sbh);
+-			if (err)
+-				goto out_brelse;
+-			ext4_update_dynamic_rev(sb);
+-			EXT4_SET_RO_COMPAT_FEATURE(sb,
+-					EXT4_FEATURE_RO_COMPAT_LARGE_FILE);
+-			ext4_handle_sync(handle);
+-			err = ext4_handle_dirty_super(handle, sb);
+-		}
++		    cpu_to_le32(EXT4_GOOD_OLD_REV))
++			set_large_file = 1;
+ 	}
+ 	raw_inode->i_generation = cpu_to_le32(inode->i_generation);
+ 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
+@@ -4410,12 +4402,23 @@ static int ext4_do_update_inode(handle_t *handle,
+ 
+ 	ext4_inode_csum_set(inode, raw_inode, ei);
+ 
++	spin_unlock(&ei->i_raw_lock);
++
+ 	BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
+ 	rc = ext4_handle_dirty_metadata(handle, NULL, bh);
+ 	if (!err)
+ 		err = rc;
+ 	ext4_clear_inode_state(inode, EXT4_STATE_NEW);
+-
++	if (set_large_file) {
++		err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh);
++		if (err)
++			goto out_brelse;
++		ext4_update_dynamic_rev(sb);
++		EXT4_SET_RO_COMPAT_FEATURE(sb,
++					   EXT4_FEATURE_RO_COMPAT_LARGE_FILE);
++		ext4_handle_sync(handle);
++		err = ext4_handle_dirty_super(handle, sb);
++	}
+ 	ext4_update_inode_fsync_trans(handle, inode, need_datasync);
+ out_brelse:
+ 	brelse(bh);
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index c4895c195e00..1f8cb1812723 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -879,6 +879,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
+ 		return NULL;
+ 
+ 	ei->vfs_inode.i_version = 1;
++	spin_lock_init(&ei->i_raw_lock);
+ 	INIT_LIST_HEAD(&ei->i_prealloc_list);
+ 	spin_lock_init(&ei->i_prealloc_lock);
+ 	ext4_es_init_tree(&ei->i_es_tree);

commit f5ccfe1ddbaf9d923a3ebdadcb1e5e32d83e9c28
+Author: Theodore Ts'o 
+Date:   Mon Apr 21 14:37:52 2014 -0400
+
+    ext4: fix locking for O_APPEND writes
+    
+    Al Viro pointed out that locking for O_APPEND writes was problematic,
+    since the location of the write isn't known until after we take the
+    i_mutex, which impacts the ext4_unaligned_aio() and s_bitmap_maxbytes
+    check.
+    
+    For O_APPEND always assume that the write is unaligned so call
+    ext4_unwritten_wait().  And to solve the second problem, take the
+    i_mutex earlier before we start the s_bitmap_maxbytes check.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/file.c b/fs/ext4/file.c
+index 3736d9dfe325..7d55a591deba 100644
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -106,17 +106,37 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
+ 
+ 	BUG_ON(iocb->ki_pos != pos);
+ 
++	/*
++	 * Unaligned direct AIO must be serialized; see comment above
++	 * In the case of O_APPEND, assume that we must always serialize
++	 */
++	if (o_direct &&
++	    ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) &&
++	    !is_sync_kiocb(iocb) &&
++	    (file->f_flags & O_APPEND ||
++	     ext4_unaligned_aio(inode, iov, nr_segs, pos))) {
++		aio_mutex = ext4_aio_mutex(inode);
++		mutex_lock(aio_mutex);
++		ext4_unwritten_wait(inode);
++	}
++
++	mutex_lock(&inode->i_mutex);
++	if (file->f_flags & O_APPEND)
++		iocb->ki_pos = pos = i_size_read(inode);
++
+ 	/*
+ 	 * If we have encountered a bitmap-format file, the size limit
+ 	 * is smaller than s_maxbytes, which is for extent-mapped files.
+ 	 */
+-
+ 	if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) {
+ 		struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+ 
+-		if ((pos > sbi->s_bitmap_maxbytes ||
+-		    (pos == sbi->s_bitmap_maxbytes && length > 0)))
+-			return -EFBIG;
++		if ((pos > sbi->s_bitmap_maxbytes) ||
++		    (pos == sbi->s_bitmap_maxbytes && length > 0)) {
++			mutex_unlock(&inode->i_mutex);
++			ret = -EFBIG;
++			goto errout;
++		}
+ 
+ 		if (pos + length > sbi->s_bitmap_maxbytes) {
+ 			nr_segs = iov_shorten((struct iovec *)iov, nr_segs,
+@@ -125,16 +145,6 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
+ 	}
+ 
+ 	if (o_direct) {
+-		/* Unaligned direct AIO must be serialized; see comment above */
+-		if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) &&
+-		    !is_sync_kiocb(iocb) &&
+-		    ext4_unaligned_aio(inode, iov, nr_segs, pos)) {
+-			aio_mutex = ext4_aio_mutex(inode);
+-			mutex_lock(aio_mutex);
+-			ext4_unwritten_wait(inode);
+-		}
+-
+-		mutex_lock(&inode->i_mutex);
+ 		blk_start_plug(&plug);
+ 
+ 		iocb->private = &overwrite;
+@@ -167,8 +177,7 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
+ 			if (err == len && (map.m_flags & EXT4_MAP_MAPPED))
+ 				overwrite = 1;
+ 		}
+-	} else
+-		mutex_lock(&inode->i_mutex);
++	}
+ 
+ 	ret = __generic_file_aio_write(iocb, iov, nr_segs);
+ 	mutex_unlock(&inode->i_mutex);
+@@ -183,6 +192,7 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
+ 	if (o_direct)
+ 		blk_finish_plug(&plug);
+ 
++errout:
+ 	if (aio_mutex)
+ 		mutex_unlock(aio_mutex);
+ 	return ret;

commit 7ed07ba8c3e6160e0af3adc0f59561de154c4c2e
+Author: Theodore Ts'o 
+Date:   Mon Apr 21 14:36:30 2014 -0400
+
+    ext4: factor out common code in ext4_file_write()
+    
+    This shouldn't change any logic flow; just delete duplicated code.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/ext4/file.c b/fs/ext4/file.c
+index 20f1c03b6077..3736d9dfe325 100644
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -97,8 +97,9 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
+ {
+ 	struct file *file = iocb->ki_filp;
+ 	struct inode *inode = file_inode(iocb->ki_filp);
++	struct mutex *aio_mutex = NULL;
+ 	struct blk_plug plug;
+-	int unaligned_aio = 0;
++	int o_direct = file->f_flags & O_DIRECT;
+ 	int overwrite = 0;
+ 	size_t length = iov_length(iov, nr_segs);
+ 	ssize_t ret;
+@@ -123,15 +124,13 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
+ 		}
+ 	}
+ 
+-	if (unlikely(iocb->ki_filp->f_flags & O_DIRECT)) {
+-		if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) &&
+-		    !is_sync_kiocb(iocb))
+-			unaligned_aio = ext4_unaligned_aio(inode, iov,
+-							   nr_segs, pos);
+-
++	if (o_direct) {
+ 		/* Unaligned direct AIO must be serialized; see comment above */
+-		if (unaligned_aio) {
+-			mutex_lock(ext4_aio_mutex(inode));
++		if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) &&
++		    !is_sync_kiocb(iocb) &&
++		    ext4_unaligned_aio(inode, iov, nr_segs, pos)) {
++			aio_mutex = ext4_aio_mutex(inode);
++			mutex_lock(aio_mutex);
+ 			ext4_unwritten_wait(inode);
+ 		}
+ 
+@@ -141,7 +140,7 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
+ 		iocb->private = &overwrite;
+ 
+ 		/* check whether we do a DIO overwrite or not */
+-		if (ext4_should_dioread_nolock(inode) && !unaligned_aio &&
++		if (ext4_should_dioread_nolock(inode) && !aio_mutex &&
+ 		    !file->f_mapping->nrpages && pos + length <= i_size_read(inode)) {
+ 			struct ext4_map_blocks map;
+ 			unsigned int blkbits = inode->i_blkbits;
+@@ -168,35 +167,24 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
+ 			if (err == len && (map.m_flags & EXT4_MAP_MAPPED))
+ 				overwrite = 1;
+ 		}
+-
+-		ret = __generic_file_aio_write(iocb, iov, nr_segs);
+-		mutex_unlock(&inode->i_mutex);
+-
+-		if (ret > 0) {
+-			ssize_t err;
+-
+-			err = generic_write_sync(file, iocb->ki_pos - ret, ret);
+-			if (err < 0)
+-				ret = err;
+-		}
+-		blk_finish_plug(&plug);
+-
+-		if (unaligned_aio)
+-			mutex_unlock(ext4_aio_mutex(inode));
+-	} else {
++	} else
+ 		mutex_lock(&inode->i_mutex);
+-		ret = __generic_file_aio_write(iocb, iov, nr_segs);
+-		mutex_unlock(&inode->i_mutex);
+ 
+-		if (ret > 0) {
+-			ssize_t err;
++	ret = __generic_file_aio_write(iocb, iov, nr_segs);
++	mutex_unlock(&inode->i_mutex);
+ 
+-			err = generic_write_sync(file, iocb->ki_pos - ret, ret);
+-			if (err < 0)
+-				ret = err;
+-		}
++	if (ret > 0) {
++		ssize_t err;
++
++		err = generic_write_sync(file, iocb->ki_pos - ret, ret);
++		if (err < 0)
++			ret = err;
+ 	}
++	if (o_direct)
++		blk_finish_plug(&plug);
+ 
++	if (aio_mutex)
++		mutex_unlock(aio_mutex);
+ 	return ret;
+ }
+ 

commit 8ad2850f44831919f63f0e58d7203e65d5b3914c
+Author: Theodore Ts'o 
+Date:   Mon Apr 21 14:26:57 2014 -0400
+
+    ext4: move ext4_file_dio_write() into ext4_file_write()
+    
+    This commit doesn't actually change anything; it just moves code
+    around in preparation for some code simplification work.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/ext4/file.c b/fs/ext4/file.c
+index 79b77a51a322..20f1c03b6077 100644
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -92,82 +92,15 @@ ext4_unaligned_aio(struct inode *inode, const struct iovec *iov,
+ }
+ 
+ static ssize_t
+-ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov,
+-		    unsigned long nr_segs, loff_t pos)
++ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
++		unsigned long nr_segs, loff_t pos)
+ {
+ 	struct file *file = iocb->ki_filp;
+-	struct inode *inode = file->f_mapping->host;
++	struct inode *inode = file_inode(iocb->ki_filp);
+ 	struct blk_plug plug;
+ 	int unaligned_aio = 0;
+-	ssize_t ret;
+ 	int overwrite = 0;
+ 	size_t length = iov_length(iov, nr_segs);
+-
+-	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) &&
+-	    !is_sync_kiocb(iocb))
+-		unaligned_aio = ext4_unaligned_aio(inode, iov, nr_segs, pos);
+-
+-	/* Unaligned direct AIO must be serialized; see comment above */
+-	if (unaligned_aio) {
+-		mutex_lock(ext4_aio_mutex(inode));
+-		ext4_unwritten_wait(inode);
+-	}
+-
+-	mutex_lock(&inode->i_mutex);
+-	blk_start_plug(&plug);
+-
+-	iocb->private = &overwrite;
+-
+-	/* check whether we do a DIO overwrite or not */
+-	if (ext4_should_dioread_nolock(inode) && !unaligned_aio &&
+-	    !file->f_mapping->nrpages && pos + length <= i_size_read(inode)) {
+-		struct ext4_map_blocks map;
+-		unsigned int blkbits = inode->i_blkbits;
+-		int err, len;
+-
+-		map.m_lblk = pos >> blkbits;
+-		map.m_len = (EXT4_BLOCK_ALIGN(pos + length, blkbits) >> blkbits)
+-			- map.m_lblk;
+-		len = map.m_len;
+-
+-		err = ext4_map_blocks(NULL, inode, &map, 0);
+-		/*
+-		 * 'err==len' means that all of blocks has been preallocated no
+-		 * matter they are initialized or not.  For excluding
+-		 * unwritten extents, we need to check m_flags.  There are
+-		 * two conditions that indicate for initialized extents.
+-		 * 1) If we hit extent cache, EXT4_MAP_MAPPED flag is returned;
+-		 * 2) If we do a real lookup, non-flags are returned.
+-		 * So we should check these two conditions.
+-		 */
+-		if (err == len && (map.m_flags & EXT4_MAP_MAPPED))
+-			overwrite = 1;
+-	}
+-
+-	ret = __generic_file_aio_write(iocb, iov, nr_segs);
+-	mutex_unlock(&inode->i_mutex);
+-
+-	if (ret > 0) {
+-		ssize_t err;
+-
+-		err = generic_write_sync(file, iocb->ki_pos - ret, ret);
+-		if (err < 0)
+-			ret = err;
+-	}
+-	blk_finish_plug(&plug);
+-
+-	if (unaligned_aio)
+-		mutex_unlock(ext4_aio_mutex(inode));
+-
+-	return ret;
+-}
+-
+-static ssize_t
+-ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
+-		unsigned long nr_segs, loff_t pos)
+-{
+-	struct file *file = iocb->ki_filp;
+-	struct inode *inode = file_inode(iocb->ki_filp);
+ 	ssize_t ret;
+ 
+ 	BUG_ON(iocb->ki_pos != pos);
+@@ -179,7 +112,6 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
+ 
+ 	if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) {
+ 		struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+-		size_t length = iov_length(iov, nr_segs);
+ 
+ 		if ((pos > sbi->s_bitmap_maxbytes ||
+ 		    (pos == sbi->s_bitmap_maxbytes && length > 0)))
+@@ -191,9 +123,67 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
+ 		}
+ 	}
+ 
+-	if (unlikely(iocb->ki_filp->f_flags & O_DIRECT))
+-		ret = ext4_file_dio_write(iocb, iov, nr_segs, pos);
+-	else {
++	if (unlikely(iocb->ki_filp->f_flags & O_DIRECT)) {
++		if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) &&
++		    !is_sync_kiocb(iocb))
++			unaligned_aio = ext4_unaligned_aio(inode, iov,
++							   nr_segs, pos);
++
++		/* Unaligned direct AIO must be serialized; see comment above */
++		if (unaligned_aio) {
++			mutex_lock(ext4_aio_mutex(inode));
++			ext4_unwritten_wait(inode);
++		}
++
++		mutex_lock(&inode->i_mutex);
++		blk_start_plug(&plug);
++
++		iocb->private = &overwrite;
++
++		/* check whether we do a DIO overwrite or not */
++		if (ext4_should_dioread_nolock(inode) && !unaligned_aio &&
++		    !file->f_mapping->nrpages && pos + length <= i_size_read(inode)) {
++			struct ext4_map_blocks map;
++			unsigned int blkbits = inode->i_blkbits;
++			int err, len;
++
++			map.m_lblk = pos >> blkbits;
++			map.m_len = (EXT4_BLOCK_ALIGN(pos + length, blkbits) >> blkbits)
++				- map.m_lblk;
++			len = map.m_len;
++
++			err = ext4_map_blocks(NULL, inode, &map, 0);
++			/*
++			 * 'err==len' means that all of blocks has
++			 * been preallocated no matter they are
++			 * initialized or not.  For excluding
++			 * unwritten extents, we need to check
++			 * m_flags.  There are two conditions that
++			 * indicate for initialized extents.  1) If we
++			 * hit extent cache, EXT4_MAP_MAPPED flag is
++			 * returned; 2) If we do a real lookup,
++			 * non-flags are returned.  So we should check
++			 * these two conditions.
++			 */
++			if (err == len && (map.m_flags & EXT4_MAP_MAPPED))
++				overwrite = 1;
++		}
++
++		ret = __generic_file_aio_write(iocb, iov, nr_segs);
++		mutex_unlock(&inode->i_mutex);
++
++		if (ret > 0) {
++			ssize_t err;
++
++			err = generic_write_sync(file, iocb->ki_pos - ret, ret);
++			if (err < 0)
++				ret = err;
++		}
++		blk_finish_plug(&plug);
++
++		if (unaligned_aio)
++			mutex_unlock(ext4_aio_mutex(inode));
++	} else {
+ 		mutex_lock(&inode->i_mutex);
+ 		ret = __generic_file_aio_write(iocb, iov, nr_segs);
+ 		mutex_unlock(&inode->i_mutex);

commit 7608e61044e7636a2ca04ff33fa1ff9697d1df88
+Author: Theodore Ts'o 
+Date:   Mon Apr 21 14:26:28 2014 -0400
+
+    ext4: inline generic_file_aio_write() into ext4_file_write()
+    
+    Copy generic_file_aio_write() into ext4_file_write().  This is part of
+    a patch series which allows us to simplify ext4_file_write() and
+    ext4_file_dio_write(), by calling __generic_file_aio_write() directly.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/ext4/file.c b/fs/ext4/file.c
+index bf0e772b6a03..79b77a51a322 100644
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -113,8 +113,6 @@ ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov,
+ 		ext4_unwritten_wait(inode);
+ 	}
+ 
+-	BUG_ON(iocb->ki_pos != pos);
+-
+ 	mutex_lock(&inode->i_mutex);
+ 	blk_start_plug(&plug);
+ 
+@@ -168,9 +166,12 @@ static ssize_t
+ ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
+ 		unsigned long nr_segs, loff_t pos)
+ {
++	struct file *file = iocb->ki_filp;
+ 	struct inode *inode = file_inode(iocb->ki_filp);
+ 	ssize_t ret;
+ 
++	BUG_ON(iocb->ki_pos != pos);
++
+ 	/*
+ 	 * If we have encountered a bitmap-format file, the size limit
+ 	 * is smaller than s_maxbytes, which is for extent-mapped files.
+@@ -192,8 +193,19 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
+ 
+ 	if (unlikely(iocb->ki_filp->f_flags & O_DIRECT))
+ 		ret = ext4_file_dio_write(iocb, iov, nr_segs, pos);
+-	else
+-		ret = generic_file_aio_write(iocb, iov, nr_segs, pos);
++	else {
++		mutex_lock(&inode->i_mutex);
++		ret = __generic_file_aio_write(iocb, iov, nr_segs);
++		mutex_unlock(&inode->i_mutex);
++
++		if (ret > 0) {
++			ssize_t err;
++
++			err = generic_write_sync(file, iocb->ki_pos - ret, ret);
++			if (err < 0)
++				ret = err;
++		}
++	}
+ 
+ 	return ret;
+ }

commit 86f1ca3889142d5959362c5694db3f3dc26f377a
+Author: Theodore Ts'o 
+Date:   Fri Apr 18 11:52:11 2014 -0400
+
+    ext4: use EINVAL if not a regular file in ext4_collapse_range()
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 2f49b12a4c40..9b9251adb400 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -5404,7 +5404,7 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
+ 		return -EINVAL;
+ 
+ 	if (!S_ISREG(inode->i_mode))
+-		return -EOPNOTSUPP;
++		return -EINVAL;
+ 
+ 	trace_ext4_collapse_range(inode, offset, len);
+ 

commit 50e02fd84543d82e663000e780e0ec0cfde52283
+Author: Theodore Ts'o 
+Date:   Mon Apr 14 23:37:35 2014 -0400
+
+    ext4: remove temporary shim used to merge COLLAPSE_RANGE and ZERO_RANGE
+    
+    In retrospect, this was a bad way to handle things, since it limited
+    testing of these patches.  We should just get the VFS level changes
+    merged in first.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index 010ea89eeb0e..6a1a0245474f 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -16,15 +16,6 @@ struct mpage_da_data;
+ struct ext4_map_blocks;
+ struct extent_status;
+ 
+-/* shim until we merge in the xfs_collapse_range branch */
+-#ifndef FALLOC_FL_COLLAPSE_RANGE
+-#define FALLOC_FL_COLLAPSE_RANGE	0x08
+-#endif
+-
+-#ifndef FALLOC_FL_ZERO_RANGE
+-#define FALLOC_FL_ZERO_RANGE           0x10
+-#endif
+-
+ #define EXT4_I(inode) (container_of(inode, struct ext4_inode_info, vfs_inode))
+ 
+ #define show_mballoc_flags(flags) __print_flags(flags, "|",	\

commit 40c406c74eb9eed58ae7d4d12a0197f7279c9499
+Author: Theodore Ts'o 
+Date:   Sat Apr 12 22:53:53 2014 -0400
+
+    ext4: COLLAPSE_RANGE only works on extent-based files
+    
+    Unfortunately, we weren't checking to make sure of this the inode was
+    extent-based before attempt operate on it.  Hilarity ensues.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Namjae Jeon 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index f24ef8697609..96e0a4bc8faa 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -4878,9 +4878,6 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
+ 	if (mode & FALLOC_FL_PUNCH_HOLE)
+ 		return ext4_punch_hole(inode, offset, len);
+ 
+-	if (mode & FALLOC_FL_COLLAPSE_RANGE)
+-		return ext4_collapse_range(inode, offset, len);
+-
+ 	ret = ext4_convert_inline_data(inode);
+ 	if (ret)
+ 		return ret;
+@@ -4892,6 +4889,9 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
+ 	if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
+ 		return -EOPNOTSUPP;
+ 
++	if (mode & FALLOC_FL_COLLAPSE_RANGE)
++		return ext4_collapse_range(inode, offset, len);
++
+ 	if (mode & FALLOC_FL_ZERO_RANGE)
+ 		return ext4_zero_range(file, offset, len, mode);
+ 

commit 6e6358fc3c3c862bfe9a5bc029d3f8ce43dc9765
+Author: Theodore Ts'o 
+Date:   Sat Apr 12 12:45:25 2014 -0400
+
+    ext4: use i_size_read in ext4_unaligned_aio()
+    
+    We haven't taken i_mutex yet, so we need to use i_size_read().
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/file.c b/fs/ext4/file.c
+index 6db7f7db7777..bc765591101a 100644
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -82,7 +82,7 @@ ext4_unaligned_aio(struct inode *inode, const struct iovec *iov,
+ 	size_t count = iov_length(iov, nr_segs);
+ 	loff_t final_size = pos + count;
+ 
+-	if (pos >= inode->i_size)
++	if (pos >= i_size_read(inode))
+ 		return 0;
+ 
+ 	if ((pos & blockmask) || (final_size & blockmask))

commit 622cad1325e404598fe3b148c3fa640dbaabc235
+Author: Theodore Ts'o 
+Date:   Fri Apr 11 10:35:17 2014 -0400
+
+    ext4: move ext4_update_i_disksize() into mpage_map_and_submit_extent()
+    
+    The function ext4_update_i_disksize() is used in only one place, in
+    the function mpage_map_and_submit_extent().  Move its code to simplify
+    the code paths, and also move the call to ext4_mark_inode_dirty() into
+    the i_data_sem's critical region, to be consistent with all of the
+    other places where we update i_disksize.  That way, we also keep the
+    raw_inode's i_disksize protected, to avoid the following race:
+    
+          CPU #1                                 CPU #2
+    
+       down_write(&i_data_sem)
+       Modify i_disk_size
+       up_write(&i_data_sem)
+                                            down_write(&i_data_sem)
+                                            Modify i_disk_size
+                                            Copy i_disk_size to on-disk inode
+                                            up_write(&i_data_sem)
+       Copy i_disk_size to on-disk inode
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Jan Kara 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index f1c65dc7cc0a..66946aa62127 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2466,23 +2466,6 @@ static inline void ext4_update_i_disksize(struct inode *inode, loff_t newsize)
+ 	up_write(&EXT4_I(inode)->i_data_sem);
+ }
+ 
+-/*
+- * Update i_disksize after writeback has been started. Races with truncate
+- * are avoided by checking i_size under i_data_sem.
+- */
+-static inline void ext4_wb_update_i_disksize(struct inode *inode, loff_t newsize)
+-{
+-	loff_t i_size;
+-
+-	down_write(&EXT4_I(inode)->i_data_sem);
+-	i_size = i_size_read(inode);
+-	if (newsize > i_size)
+-		newsize = i_size;
+-	if (newsize > EXT4_I(inode)->i_disksize)
+-		EXT4_I(inode)->i_disksize = newsize;
+-	up_write(&EXT4_I(inode)->i_data_sem);
+-}
+-
+ struct ext4_group_info {
+ 	unsigned long   bb_state;
+ 	struct rb_root  bb_free_root;
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 7b93df9aa182..f023f0cb46fc 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2247,13 +2247,23 @@ static int mpage_map_and_submit_extent(handle_t *handle,
+ 			return err;
+ 	} while (map->m_len);
+ 
+-	/* Update on-disk size after IO is submitted */
++	/*
++	 * Update on-disk size after IO is submitted.  Races with
++	 * truncate are avoided by checking i_size under i_data_sem.
++	 */
+ 	disksize = ((loff_t)mpd->first_page) << PAGE_CACHE_SHIFT;
+ 	if (disksize > EXT4_I(inode)->i_disksize) {
+ 		int err2;
+-
+-		ext4_wb_update_i_disksize(inode, disksize);
++		loff_t i_size;
++
++		down_write(&EXT4_I(inode)->i_data_sem);
++		i_size = i_size_read(inode);
++		if (disksize > i_size)
++			disksize = i_size;
++		if (disksize > EXT4_I(inode)->i_disksize)
++			EXT4_I(inode)->i_disksize = disksize;
+ 		err2 = ext4_mark_inode_dirty(handle, inode);
++		up_write(&EXT4_I(inode)->i_data_sem);
+ 		if (err2)
+ 			ext4_error(inode->i_sb,
+ 				   "Failed to mark inode %lu dirty",

commit 87f7e41636ff201148443551d06bc74497160aac
+Author: Theodore Ts'o 
+Date:   Tue Apr 8 11:38:28 2014 -0400
+
+    ext4: update PF_MEMALLOC handling in ext4_write_inode()
+    
+    The special handling of PF_MEMALLOC callers in ext4_write_inode()
+    shouldn't be necessary as there shouldn't be any. Warn about it. Also
+    update comment before the function as it seems somewhat outdated.
+    
+    (Changes modeled on an ext3 patch posted by Jan Kara to the linux-ext4
+    mailing list on Februaryt 28, 2014, which apparently never went into
+    the ext3 tree.)
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Jan Kara 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 93f16c5e8a8e..7b93df9aa182 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4427,21 +4427,20 @@ static int ext4_do_update_inode(handle_t *handle,
+  *
+  * We are called from a few places:
+  *
+- * - Within generic_file_write() for O_SYNC files.
++ * - Within generic_file_aio_write() -> generic_write_sync() for O_SYNC files.
+  *   Here, there will be no transaction running. We wait for any running
+  *   transaction to commit.
+  *
+- * - Within sys_sync(), kupdate and such.
+- *   We wait on commit, if tol to.
++ * - Within flush work (sys_sync(), kupdate and such).
++ *   We wait on commit, if told to.
+  *
+- * - Within prune_icache() (PF_MEMALLOC == true)
+- *   Here we simply return.  We can't afford to block kswapd on the
+- *   journal commit.
++ * - Within iput_final() -> write_inode_now()
++ *   We wait on commit, if told to.
+  *
+  * In all cases it is actually safe for us to return without doing anything,
+  * because the inode has been copied into a raw inode buffer in
+- * ext4_mark_inode_dirty().  This is a correctness thing for O_SYNC and for
+- * knfsd.
++ * ext4_mark_inode_dirty().  This is a correctness thing for WB_SYNC_ALL
++ * writeback.
+  *
+  * Note that we are absolutely dependent upon all inode dirtiers doing the
+  * right thing: they *must* call mark_inode_dirty() after dirtying info in
+@@ -4453,15 +4452,15 @@ static int ext4_do_update_inode(handle_t *handle,
+  *	stuff();
+  *	inode->i_size = expr;
+  *
+- * is in error because a kswapd-driven write_inode() could occur while
+- * `stuff()' is running, and the new i_size will be lost.  Plus the inode
+- * will no longer be on the superblock's dirty inode list.
++ * is in error because write_inode() could occur while `stuff()' is running,
++ * and the new i_size will be lost.  Plus the inode will no longer be on the
++ * superblock's dirty inode list.
+  */
+ int ext4_write_inode(struct inode *inode, struct writeback_control *wbc)
+ {
+ 	int err;
+ 
+-	if (current->flags & PF_MEMALLOC)
++	if (WARN_ON_ONCE(current->flags & PF_MEMALLOC))
+ 		return 0;
+ 
+ 	if (EXT4_SB(inode->i_sb)->s_journal) {

commit 00a1a053ebe5febcfc2ec498bd894f035ad2aa06
+Author: Theodore Ts'o 
+Date:   Sun Mar 30 10:20:01 2014 -0400
+
+    ext4: atomically set inode->i_flags in ext4_set_inode_flags()
+    
+    Use cmpxchg() to atomically set i_flags instead of clearing out the
+    S_IMMUTABLE, S_APPEND, etc. flags and then setting them from the
+    EXT4_IMMUTABLE_FL, EXT4_APPEND_FL flags, since this opens up a race
+    where an immutable file has the immutable flag cleared for a brief
+    window of time.
+    
+    Reported-by: John Sullivan 
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@kernel.org
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 6e39895a91b8..24bfd7ff3049 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -38,6 +38,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include "ext4_jbd2.h"
+ #include "xattr.h"
+@@ -3921,18 +3922,20 @@ int ext4_get_inode_loc(struct inode *inode, struct ext4_iloc *iloc)
+ void ext4_set_inode_flags(struct inode *inode)
+ {
+ 	unsigned int flags = EXT4_I(inode)->i_flags;
++	unsigned int new_fl = 0;
+ 
+-	inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC);
+ 	if (flags & EXT4_SYNC_FL)
+-		inode->i_flags |= S_SYNC;
++		new_fl |= S_SYNC;
+ 	if (flags & EXT4_APPEND_FL)
+-		inode->i_flags |= S_APPEND;
++		new_fl |= S_APPEND;
+ 	if (flags & EXT4_IMMUTABLE_FL)
+-		inode->i_flags |= S_IMMUTABLE;
++		new_fl |= S_IMMUTABLE;
+ 	if (flags & EXT4_NOATIME_FL)
+-		inode->i_flags |= S_NOATIME;
++		new_fl |= S_NOATIME;
+ 	if (flags & EXT4_DIRSYNC_FL)
+-		inode->i_flags |= S_DIRSYNC;
++		new_fl |= S_DIRSYNC;
++	set_mask_bits(&inode->i_flags,
++		      S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC, new_fl);
+ }
+ 
+ /* Propagate flags from i_flags to EXT4_I(inode)->i_flags */
+diff --git a/include/linux/bitops.h b/include/linux/bitops.h
+index abc9ca778456..be5fd38bd5a0 100644
+--- a/include/linux/bitops.h
++++ b/include/linux/bitops.h
+@@ -196,6 +196,21 @@ static inline unsigned long __ffs64(u64 word)
+ 
+ #ifdef __KERNEL__
+ 
++#ifndef set_mask_bits
++#define set_mask_bits(ptr, _mask, _bits)	\
++({								\
++	const typeof(*ptr) mask = (_mask), bits = (_bits);	\
++	typeof(*ptr) old, new;					\
++								\
++	do {							\
++		old = ACCESS_ONCE(*ptr);			\
++		new = (old & ~mask) | bits;			\
++	} while (cmpxchg(ptr, old, new) != old);		\
++								\
++	new;							\
++})
++#endif
++
+ #ifndef find_last_bit
+ /**
+  * find_last_bit - find the last set bit in a memory region

commit 5f16f3225b06242a9ee876f07c1c9b6ed36a22b6
+Author: Theodore Ts'o 
+Date:   Mon Mar 24 14:43:12 2014 -0400
+
+    ext4: atomically set inode->i_flags in ext4_set_inode_flags()
+    
+    Use cmpxchg() to atomically set i_flags instead of clearing out the
+    S_IMMUTABLE, S_APPEND, etc. flags and then setting them from the
+    EXT4_IMMUTABLE_FL, EXT4_APPEND_FL flags, since this opens up a race
+    where an immutable file has the immutable flag cleared for a brief
+    window of time.
+    
+    Reported-by: John Sullivan 
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index b5e182acf9b9..df067c3c6c93 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -3938,18 +3938,20 @@ int ext4_get_inode_loc(struct inode *inode, struct ext4_iloc *iloc)
+ void ext4_set_inode_flags(struct inode *inode)
+ {
+ 	unsigned int flags = EXT4_I(inode)->i_flags;
++	unsigned int new_fl = 0;
+ 
+-	inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC);
+ 	if (flags & EXT4_SYNC_FL)
+-		inode->i_flags |= S_SYNC;
++		new_fl |= S_SYNC;
+ 	if (flags & EXT4_APPEND_FL)
+-		inode->i_flags |= S_APPEND;
++		new_fl |= S_APPEND;
+ 	if (flags & EXT4_IMMUTABLE_FL)
+-		inode->i_flags |= S_IMMUTABLE;
++		new_fl |= S_IMMUTABLE;
+ 	if (flags & EXT4_NOATIME_FL)
+-		inode->i_flags |= S_NOATIME;
++		new_fl |= S_NOATIME;
+ 	if (flags & EXT4_DIRSYNC_FL)
+-		inode->i_flags |= S_DIRSYNC;
++		new_fl |= S_DIRSYNC;
++	inode_set_flags(inode, new_fl,
++			S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC);
+ }
+ 
+ /* Propagate flags from i_flags to EXT4_I(inode)->i_flags */
+diff --git a/fs/inode.c b/fs/inode.c
+index 4bcdad3c9361..26f95ceb6250 100644
+--- a/fs/inode.c
++++ b/fs/inode.c
+@@ -1899,3 +1899,34 @@ void inode_dio_done(struct inode *inode)
+ 		wake_up_bit(&inode->i_state, __I_DIO_WAKEUP);
+ }
+ EXPORT_SYMBOL(inode_dio_done);
++
++/*
++ * inode_set_flags - atomically set some inode flags
++ *
++ * Note: the caller should be holding i_mutex, or else be sure that
++ * they have exclusive access to the inode structure (i.e., while the
++ * inode is being instantiated).  The reason for the cmpxchg() loop
++ * --- which wouldn't be necessary if all code paths which modify
++ * i_flags actually followed this rule, is that there is at least one
++ * code path which doesn't today --- for example,
++ * __generic_file_aio_write() calls file_remove_suid() without holding
++ * i_mutex --- so we use cmpxchg() out of an abundance of caution.
++ *
++ * In the long run, i_mutex is overkill, and we should probably look
++ * at using the i_lock spinlock to protect i_flags, and then make sure
++ * it is so documented in include/linux/fs.h and that all code follows
++ * the locking convention!!
++ */
++void inode_set_flags(struct inode *inode, unsigned int flags,
++		     unsigned int mask)
++{
++	unsigned int old_flags, new_flags;
++
++	WARN_ON_ONCE(flags & ~mask);
++	do {
++		old_flags = ACCESS_ONCE(inode->i_flags);
++		new_flags = (old_flags & ~mask) | flags;
++	} while (unlikely(cmpxchg(&inode->i_flags, old_flags,
++				  new_flags) != old_flags));
++}
++EXPORT_SYMBOL(inode_set_flags);
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 60829565e552..5d1f6fa8daed 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -2556,6 +2556,9 @@ static inline ssize_t blockdev_direct_IO(int rw, struct kiocb *iocb,
+ void inode_dio_wait(struct inode *inode);
+ void inode_dio_done(struct inode *inode);
+ 
++extern void inode_set_flags(struct inode *inode, unsigned int flags,
++			    unsigned int mask);
++
+ extern const struct file_operations generic_ro_fops;
+ 
+ #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))

commit ed3654eb981fd44694b4d2a636e13f998bc10e7f
+Author: Theodore Ts'o 
+Date:   Mon Mar 24 14:09:06 2014 -0400
+
+    ext4: optimize Hurd tests when reading/writing inodes
+    
+    Set a in-memory superblock flag to indicate whether the file system is
+    designed to support the Hurd.
+    
+    Also, add a sanity check to make sure the 64-bit feature is not set
+    for Hurd file systems, since i_file_acl_high conflicts with a
+    Hurd-specific field.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index f4f889e6df83..e01135d791ca 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1001,6 +1001,8 @@ struct ext4_inode_info {
+ #define EXT4_MOUNT2_STD_GROUP_SIZE	0x00000002 /* We have standard group
+ 						      size of blocksize * 8
+ 						      blocks */
++#define EXT4_MOUNT2_HURD_COMPAT		0x00000004 /* Support HURD-castrated
++						      file systems */
+ 
+ #define clear_opt(sb, opt)		EXT4_SB(sb)->s_mount_opt &= \
+ 						~EXT4_MOUNT_##opt
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index ed2c13a7f293..b5e182acf9b9 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4168,8 +4168,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 	EXT4_INODE_GET_XTIME(i_atime, inode, raw_inode);
+ 	EXT4_EINODE_GET_XTIME(i_crtime, ei, raw_inode);
+ 
+-	if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=
+-	    cpu_to_le32(EXT4_OS_HURD)) {
++	if (likely(!test_opt2(inode->i_sb, HURD_COMPAT))) {
+ 		inode->i_version = le32_to_cpu(raw_inode->i_disk_version);
+ 		if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) {
+ 			if (EXT4_FITS_IN_INODE(raw_inode, ei, i_version_hi))
+@@ -4345,8 +4344,7 @@ static int ext4_do_update_inode(handle_t *handle,
+ 		goto out_brelse;
+ 	raw_inode->i_dtime = cpu_to_le32(ei->i_dtime);
+ 	raw_inode->i_flags = cpu_to_le32(ei->i_flags & 0xFFFFFFFF);
+-	if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=
+-	    cpu_to_le32(EXT4_OS_HURD))
++	if (likely(!test_opt2(inode->i_sb, HURD_COMPAT)))
+ 		raw_inode->i_file_acl_high =
+ 			cpu_to_le16(ei->i_file_acl >> 32);
+ 	raw_inode->i_file_acl_lo = cpu_to_le32(ei->i_file_acl);
+@@ -4391,8 +4389,7 @@ static int ext4_do_update_inode(handle_t *handle,
+ 			raw_inode->i_block[block] = ei->i_data[block];
+ 	}
+ 
+-	if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=
+-	    cpu_to_le32(EXT4_OS_HURD)) {
++	if (likely(!test_opt2(inode->i_sb, HURD_COMPAT))) {
+ 		raw_inode->i_disk_version = cpu_to_le32(inode->i_version);
+ 		if (ei->i_extra_isize) {
+ 			if (EXT4_FITS_IN_INODE(raw_inode, ei, i_version_hi))
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 5a51af7d0335..f3c667091618 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3580,6 +3580,16 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		       "feature flags set on rev 0 fs, "
+ 		       "running e2fsck is recommended");
+ 
++	if (es->s_creator_os == cpu_to_le32(EXT4_OS_HURD)) {
++		set_opt2(sb, HURD_COMPAT);
++		if (EXT4_HAS_INCOMPAT_FEATURE(sb,
++					      EXT4_FEATURE_INCOMPAT_64BIT)) {
++			ext4_msg(sb, KERN_ERR,
++				 "The Hurd can't support 64-bit file systems");
++			goto failed_mount;
++		}
++	}
++
+ 	if (IS_EXT2_SB(sb)) {
+ 		if (ext2_feature_set_ok(sb))
+ 			ext4_msg(sb, KERN_INFO, "mounting ext2 file system "

commit c4f65706056e9f0c2cf126b29c6920a179d91150
+Author: Theodore Ts'o 
+Date:   Thu Mar 20 00:32:57 2014 -0400
+
+    ext4: kill i_version support for Hurd-castrated file systems
+    
+    The Hurd file system uses uses the inode field which is now used for
+    i_version for its translator block.  This means that ext2 file systems
+    that are formatted for GNU Hurd can't be used to support NFSv4.  Given
+    that Hurd file systems don't support extents, and a huge number of
+    modern file system features, this is no great loss.
+    
+    If we don't do this, the attempt to update the i_version field will
+    stomp over the translator block field, which will cause file system
+    corruption for Hurd file systems.  This can be replicated via:
+    
+    mke2fs -t ext2 -o hurd /dev/vdc
+    mount -t ext4 /dev/vdc /vdc
+    touch /vdc/bug0000
+    umount /dev/vdc
+    e2fsck -f /dev/vdc
+    
+    Addresses-Debian-Bug: #738758
+    
+    Reported-By: Gabriele Giacone <1o5g4r8o@gmail.com>
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 7cc24555eca8..ed2c13a7f293 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4168,11 +4168,14 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 	EXT4_INODE_GET_XTIME(i_atime, inode, raw_inode);
+ 	EXT4_EINODE_GET_XTIME(i_crtime, ei, raw_inode);
+ 
+-	inode->i_version = le32_to_cpu(raw_inode->i_disk_version);
+-	if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) {
+-		if (EXT4_FITS_IN_INODE(raw_inode, ei, i_version_hi))
+-			inode->i_version |=
+-			(__u64)(le32_to_cpu(raw_inode->i_version_hi)) << 32;
++	if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=
++	    cpu_to_le32(EXT4_OS_HURD)) {
++		inode->i_version = le32_to_cpu(raw_inode->i_disk_version);
++		if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) {
++			if (EXT4_FITS_IN_INODE(raw_inode, ei, i_version_hi))
++				inode->i_version |=
++		    (__u64)(le32_to_cpu(raw_inode->i_version_hi)) << 32;
++		}
+ 	}
+ 
+ 	ret = 0;
+@@ -4388,12 +4391,16 @@ static int ext4_do_update_inode(handle_t *handle,
+ 			raw_inode->i_block[block] = ei->i_data[block];
+ 	}
+ 
+-	raw_inode->i_disk_version = cpu_to_le32(inode->i_version);
+-	if (ei->i_extra_isize) {
+-		if (EXT4_FITS_IN_INODE(raw_inode, ei, i_version_hi))
+-			raw_inode->i_version_hi =
+-			cpu_to_le32(inode->i_version >> 32);
+-		raw_inode->i_extra_isize = cpu_to_le16(ei->i_extra_isize);
++	if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=
++	    cpu_to_le32(EXT4_OS_HURD)) {
++		raw_inode->i_disk_version = cpu_to_le32(inode->i_version);
++		if (ei->i_extra_isize) {
++			if (EXT4_FITS_IN_INODE(raw_inode, ei, i_version_hi))
++				raw_inode->i_version_hi =
++					cpu_to_le32(inode->i_version >> 32);
++			raw_inode->i_extra_isize =
++				cpu_to_le16(ei->i_extra_isize);
++		}
+ 	}
+ 
+ 	ext4_inode_csum_set(inode, raw_inode, ei);

commit 46884442fc5bb81a896f7245bd850fde9b435509
+Author: Theodore Ts'o 
+Date:   Tue Dec 17 21:16:39 2013 -0500
+
+    random: use the architectural HWRNG for the SHA's IV in extract_buf()
+    
+    To help assuage the fears of those who think the NSA can introduce a
+    massive hack into the instruction decode and out of order execution
+    engine in the CPU without hundreds of Intel engineers knowing about
+    it (only one of which woud need to have the conscience and courage of
+    Edward Snowden to spill the beans to the public), use the HWRNG to
+    initialize the SHA starting value, instead of xor'ing it in
+    afterwards.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 8cc7d6515676..d07575c99a5f 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -1012,23 +1012,23 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
+ 	__u8 extract[64];
+ 	unsigned long flags;
+ 
+-	/* Generate a hash across the pool, 16 words (512 bits) at a time */
+-	sha_init(hash.w);
+-	spin_lock_irqsave(&r->lock, flags);
+-	for (i = 0; i < r->poolinfo->poolwords; i += 16)
+-		sha_transform(hash.w, (__u8 *)(r->pool + i), workspace);
+-
+ 	/*
+ 	 * If we have an architectural hardware random number
+-	 * generator, mix that in, too.
++	 * generator, use it for SHA's initial vector
+ 	 */
++	sha_init(hash.w);
+ 	for (i = 0; i < LONGS(20); i++) {
+ 		unsigned long v;
+ 		if (!arch_get_random_long(&v))
+ 			break;
+-		hash.l[i] ^= v;
++		hash.l[i] = v;
+ 	}
+ 
++	/* Generate a hash across the pool, 16 words (512 bits) at a time */
++	spin_lock_irqsave(&r->lock, flags);
++	for (i = 0; i < r->poolinfo->poolwords; i += 16)
++		sha_transform(hash.w, (__u8 *)(r->pool + i), workspace);
++
+ 	/*
+ 	 * We mix the hash back into the pool to prevent backtracking
+ 	 * attacks (where the attacker knows the state of the pool

commit 38c03b34391dd25a39576073e58485e5949d29fe
+Author: Theodore Ts'o 
+Date:   Thu Mar 13 22:49:42 2014 -0400
+
+    ext4: only call sync_filesystm() when remounting read-only
+    
+    This is the only time it is required for ext4.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index a5f1170048bd..89baee42f353 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4765,8 +4765,6 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ #endif
+ 	char *orig_data = kstrdup(data, GFP_KERNEL);
+ 
+-	sync_filesystem(sb);
+-
+ 	/* Store the original options */
+ 	old_sb_flags = sb->s_flags;
+ 	old_opts.s_mount_opt = sbi->s_mount_opt;
+@@ -4837,6 +4835,9 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 		}
+ 
+ 		if (*flags & MS_RDONLY) {
++			err = sync_filesystem(sb);
++			if (err < 0)
++				goto restore_opts;
+ 			err = dquot_suspend(sb, -1);
+ 			if (err < 0)
+ 				goto restore_opts;

commit 02b9984d640873b7b3809e63f81a0d7e13496886
+Author: Theodore Ts'o 
+Date:   Thu Mar 13 10:14:33 2014 -0400
+
+    fs: push sync_filesystem() down to the file system's remount_fs()
+    
+    Previously, the no-op "mount -o mount /dev/xxx" operation when the
+    file system is already mounted read-write causes an implied,
+    unconditional syncfs().  This seems pretty stupid, and it's certainly
+    documented or guaraunteed to do this, nor is it particularly useful,
+    except in the case where the file system was mounted rw and is getting
+    remounted read-only.
+    
+    However, it's possible that there might be some file systems that are
+    actually depending on this behavior.  In most file systems, it's
+    probably fine to only call sync_filesystem() when transitioning from
+    read-write to read-only, and there are some file systems where this is
+    not needed at all (for example, for a pseudo-filesystem or something
+    like romfs).
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: linux-fsdevel@vger.kernel.org
+    Cc: Christoph Hellwig 
+    Cc: Artem Bityutskiy 
+    Cc: Adrian Hunter 
+    Cc: Evgeniy Dushistov 
+    Cc: Jan Kara 
+    Cc: OGAWA Hirofumi 
+    Cc: Anders Larsen 
+    Cc: Phillip Lougher 
+    Cc: Kees Cook 
+    Cc: Mikulas Patocka 
+    Cc: Petr Vandrovec 
+    Cc: xfs@oss.sgi.com
+    Cc: linux-btrfs@vger.kernel.org
+    Cc: linux-cifs@vger.kernel.org
+    Cc: samba-technical@lists.samba.org
+    Cc: codalist@coda.cs.cmu.edu
+    Cc: linux-ext4@vger.kernel.org
+    Cc: linux-f2fs-devel@lists.sourceforge.net
+    Cc: fuse-devel@lists.sourceforge.net
+    Cc: cluster-devel@redhat.com
+    Cc: linux-mtd@lists.infradead.org
+    Cc: jfs-discussion@lists.sourceforge.net
+    Cc: linux-nfs@vger.kernel.org
+    Cc: linux-nilfs@vger.kernel.org
+    Cc: linux-ntfs-dev@lists.sourceforge.net
+    Cc: ocfs2-devel@oss.oracle.com
+    Cc: reiserfs-devel@vger.kernel.org
+
+diff --git a/fs/adfs/super.c b/fs/adfs/super.c
+index 7b3003cb6f1b..952aeb048349 100644
+--- a/fs/adfs/super.c
++++ b/fs/adfs/super.c
+@@ -212,6 +212,7 @@ static int parse_options(struct super_block *sb, char *options)
+ 
+ static int adfs_remount(struct super_block *sb, int *flags, char *data)
+ {
++	sync_filesystem(sb);
+ 	*flags |= MS_NODIRATIME;
+ 	return parse_options(sb, data);
+ }
+diff --git a/fs/affs/super.c b/fs/affs/super.c
+index d098731b82ff..307453086c3f 100644
+--- a/fs/affs/super.c
++++ b/fs/affs/super.c
+@@ -530,6 +530,7 @@ affs_remount(struct super_block *sb, int *flags, char *data)
+ 
+ 	pr_debug("AFFS: remount(flags=0x%x,opts=\"%s\")\n",*flags,data);
+ 
++	sync_filesystem(sb);
+ 	*flags |= MS_NODIRATIME;
+ 
+ 	memcpy(volume, sbi->s_volume, 32);
+diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
+index 845d2d690ce2..56d70c8a89b0 100644
+--- a/fs/befs/linuxvfs.c
++++ b/fs/befs/linuxvfs.c
+@@ -913,6 +913,7 @@ befs_fill_super(struct super_block *sb, void *data, int silent)
+ static int
+ befs_remount(struct super_block *sb, int *flags, char *data)
+ {
++	sync_filesystem(sb);
+ 	if (!(*flags & MS_RDONLY))
+ 		return -EINVAL;
+ 	return 0;
+diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
+index 97cc24198554..00cd0c57b0b3 100644
+--- a/fs/btrfs/super.c
++++ b/fs/btrfs/super.c
+@@ -1381,6 +1381,7 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
+ 	unsigned int old_metadata_ratio = fs_info->metadata_ratio;
+ 	int ret;
+ 
++	sync_filesystem(sb);
+ 	btrfs_remount_prepare(fs_info);
+ 
+ 	ret = btrfs_parse_options(root, data);
+diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
+index 849f6132b327..4942c94bf7ee 100644
+--- a/fs/cifs/cifsfs.c
++++ b/fs/cifs/cifsfs.c
+@@ -541,6 +541,7 @@ static int cifs_show_stats(struct seq_file *s, struct dentry *root)
+ 
+ static int cifs_remount(struct super_block *sb, int *flags, char *data)
+ {
++	sync_filesystem(sb);
+ 	*flags |= MS_NODIRATIME;
+ 	return 0;
+ }
+diff --git a/fs/coda/inode.c b/fs/coda/inode.c
+index 506de34a4ef3..3f48000ef1a5 100644
+--- a/fs/coda/inode.c
++++ b/fs/coda/inode.c
+@@ -96,6 +96,7 @@ void coda_destroy_inodecache(void)
+ 
+ static int coda_remount(struct super_block *sb, int *flags, char *data)
+ {
++	sync_filesystem(sb);
+ 	*flags |= MS_NOATIME;
+ 	return 0;
+ }
+diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
+index 06610cf94d57..a2759112563c 100644
+--- a/fs/cramfs/inode.c
++++ b/fs/cramfs/inode.c
+@@ -244,6 +244,7 @@ static void cramfs_kill_sb(struct super_block *sb)
+ 
+ static int cramfs_remount(struct super_block *sb, int *flags, char *data)
+ {
++	sync_filesystem(sb);
+ 	*flags |= MS_RDONLY;
+ 	return 0;
+ }
+diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
+index 9c0444cccbe1..02928a9d00a8 100644
+--- a/fs/debugfs/inode.c
++++ b/fs/debugfs/inode.c
+@@ -218,6 +218,7 @@ static int debugfs_remount(struct super_block *sb, int *flags, char *data)
+ 	int err;
+ 	struct debugfs_fs_info *fsi = sb->s_fs_info;
+ 
++	sync_filesystem(sb);
+ 	err = debugfs_parse_options(data, &fsi->mount_opts);
+ 	if (err)
+ 		goto fail;
+diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
+index a726b9f29cb7..c71038079b47 100644
+--- a/fs/devpts/inode.c
++++ b/fs/devpts/inode.c
+@@ -313,6 +313,7 @@ static int devpts_remount(struct super_block *sb, int *flags, char *data)
+ 	struct pts_fs_info *fsi = DEVPTS_SB(sb);
+ 	struct pts_mount_opts *opts = &fsi->mount_opts;
+ 
++	sync_filesystem(sb);
+ 	err = parse_mount_options(data, PARSE_REMOUNT, opts);
+ 
+ 	/*
+diff --git a/fs/efs/super.c b/fs/efs/super.c
+index 50215bbd6463..103bbd820b87 100644
+--- a/fs/efs/super.c
++++ b/fs/efs/super.c
+@@ -114,6 +114,7 @@ static void destroy_inodecache(void)
+ 
+ static int efs_remount(struct super_block *sb, int *flags, char *data)
+ {
++	sync_filesystem(sb);
+ 	*flags |= MS_RDONLY;
+ 	return 0;
+ }
+diff --git a/fs/ext2/super.c b/fs/ext2/super.c
+index 20d6697bd638..d260115c0350 100644
+--- a/fs/ext2/super.c
++++ b/fs/ext2/super.c
+@@ -1254,6 +1254,7 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data)
+ 	unsigned long old_sb_flags;
+ 	int err;
+ 
++	sync_filesystem(sb);
+ 	spin_lock(&sbi->s_lock);
+ 
+ 	/* Store the old options */
+diff --git a/fs/ext3/super.c b/fs/ext3/super.c
+index 37fd31ed16e7..95c6c5a6d0c5 100644
+--- a/fs/ext3/super.c
++++ b/fs/ext3/super.c
+@@ -2649,6 +2649,8 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
+ 	int i;
+ #endif
+ 
++	sync_filesystem(sb);
++
+ 	/* Store the original options */
+ 	old_sb_flags = sb->s_flags;
+ 	old_opts.s_mount_opt = sbi->s_mount_opt;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 7a829f750235..a5f1170048bd 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4765,6 +4765,8 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ #endif
+ 	char *orig_data = kstrdup(data, GFP_KERNEL);
+ 
++	sync_filesystem(sb);
++
+ 	/* Store the original options */
+ 	old_sb_flags = sb->s_flags;
+ 	old_opts.s_mount_opt = sbi->s_mount_opt;
+diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
+index 1a85f83abd53..856bdf994c0a 100644
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -568,6 +568,8 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
+ 	struct f2fs_mount_info org_mount_opt;
+ 	int err, active_logs;
+ 
++	sync_filesystem(sb);
++
+ 	/*
+ 	 * Save the old mount options in case we
+ 	 * need to restore them.
+diff --git a/fs/fat/inode.c b/fs/fat/inode.c
+index 854b578f6695..343e477c6dcb 100644
+--- a/fs/fat/inode.c
++++ b/fs/fat/inode.c
+@@ -635,6 +635,8 @@ static int fat_remount(struct super_block *sb, int *flags, char *data)
+ 	struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ 	*flags |= MS_NODIRATIME | (sbi->options.isvfat ? 0 : MS_NOATIME);
+ 
++	sync_filesystem(sb);
++
+ 	/* make sure we update state on remount. */
+ 	new_rdonly = *flags & MS_RDONLY;
+ 	if (new_rdonly != (sb->s_flags & MS_RDONLY)) {
+diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
+index e37eb274e492..7ca8c75d50d3 100644
+--- a/fs/freevxfs/vxfs_super.c
++++ b/fs/freevxfs/vxfs_super.c
+@@ -124,6 +124,7 @@ vxfs_statfs(struct dentry *dentry, struct kstatfs *bufp)
+ 
+ static int vxfs_remount(struct super_block *sb, int *flags, char *data)
+ {
++	sync_filesystem(sb);
+ 	*flags |= MS_RDONLY;
+ 	return 0;
+ }
+diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
+index d468643a68b2..ecdb255d086d 100644
+--- a/fs/fuse/inode.c
++++ b/fs/fuse/inode.c
+@@ -135,6 +135,7 @@ static void fuse_evict_inode(struct inode *inode)
+ 
+ static int fuse_remount_fs(struct super_block *sb, int *flags, char *data)
+ {
++	sync_filesystem(sb);
+ 	if (*flags & MS_MANDLOCK)
+ 		return -EINVAL;
+ 
+diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
+index 60f60f6181f3..4c6dd50831ba 100644
+--- a/fs/gfs2/super.c
++++ b/fs/gfs2/super.c
+@@ -1175,6 +1175,8 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data)
+ 	struct gfs2_tune *gt = &sdp->sd_tune;
+ 	int error;
+ 
++	sync_filesystem(sb);
++
+ 	spin_lock(>->gt_spin);
+ 	args.ar_commit = gt->gt_logd_secs;
+ 	args.ar_quota_quantum = gt->gt_quota_quantum;
+diff --git a/fs/hfs/super.c b/fs/hfs/super.c
+index 2d2039e754cd..eee7206c38d1 100644
+--- a/fs/hfs/super.c
++++ b/fs/hfs/super.c
+@@ -112,6 +112,7 @@ static int hfs_statfs(struct dentry *dentry, struct kstatfs *buf)
+ 
+ static int hfs_remount(struct super_block *sb, int *flags, char *data)
+ {
++	sync_filesystem(sb);
+ 	*flags |= MS_NODIRATIME;
+ 	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
+ 		return 0;
+diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
+index 80875aa640ef..8eb787b52c05 100644
+--- a/fs/hfsplus/super.c
++++ b/fs/hfsplus/super.c
+@@ -323,6 +323,7 @@ static int hfsplus_statfs(struct dentry *dentry, struct kstatfs *buf)
+ 
+ static int hfsplus_remount(struct super_block *sb, int *flags, char *data)
+ {
++	sync_filesystem(sb);
+ 	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
+ 		return 0;
+ 	if (!(*flags & MS_RDONLY)) {
+diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
+index 4534ff688b76..fe3463a43236 100644
+--- a/fs/hpfs/super.c
++++ b/fs/hpfs/super.c
+@@ -421,6 +421,8 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
+ 	struct hpfs_sb_info *sbi = hpfs_sb(s);
+ 	char *new_opts = kstrdup(data, GFP_KERNEL);
+ 	
++	sync_filesystem(s);
++
+ 	*flags |= MS_NOATIME;
+ 	
+ 	hpfs_lock(s);
+diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
+index 4a9e10ea13f2..6af66ee56390 100644
+--- a/fs/isofs/inode.c
++++ b/fs/isofs/inode.c
+@@ -117,6 +117,7 @@ static void destroy_inodecache(void)
+ 
+ static int isofs_remount(struct super_block *sb, int *flags, char *data)
+ {
++	sync_filesystem(sb);
+ 	if (!(*flags & MS_RDONLY))
+ 		return -EROFS;
+ 	return 0;
+diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
+index 0defb1cc2a35..0918f0e2e266 100644
+--- a/fs/jffs2/super.c
++++ b/fs/jffs2/super.c
+@@ -243,6 +243,7 @@ static int jffs2_remount_fs(struct super_block *sb, int *flags, char *data)
+ 	struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
+ 	int err;
+ 
++	sync_filesystem(sb);
+ 	err = jffs2_parse_options(c, data);
+ 	if (err)
+ 		return -EINVAL;
+diff --git a/fs/jfs/super.c b/fs/jfs/super.c
+index e2b7483444fd..97f7fda51890 100644
+--- a/fs/jfs/super.c
++++ b/fs/jfs/super.c
+@@ -418,6 +418,7 @@ static int jfs_remount(struct super_block *sb, int *flags, char *data)
+ 	int flag = JFS_SBI(sb)->flag;
+ 	int ret;
+ 
++	sync_filesystem(sb);
+ 	if (!parse_options(data, sb, &newLVSize, &flag)) {
+ 		return -EINVAL;
+ 	}
+diff --git a/fs/minix/inode.c b/fs/minix/inode.c
+index 0332109162a5..dcdc2989370d 100644
+--- a/fs/minix/inode.c
++++ b/fs/minix/inode.c
+@@ -123,6 +123,7 @@ static int minix_remount (struct super_block * sb, int * flags, char * data)
+ 	struct minix_sb_info * sbi = minix_sb(sb);
+ 	struct minix_super_block * ms;
+ 
++	sync_filesystem(sb);
+ 	ms = sbi->s_ms;
+ 	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
+ 		return 0;
+diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
+index 2cf2ebecb55f..5f86e8080178 100644
+--- a/fs/ncpfs/inode.c
++++ b/fs/ncpfs/inode.c
+@@ -99,6 +99,7 @@ static void destroy_inodecache(void)
+ 
+ static int ncp_remount(struct super_block *sb, int *flags, char* data)
+ {
++	sync_filesystem(sb);
+ 	*flags |= MS_NODIRATIME;
+ 	return 0;
+ }
+diff --git a/fs/nfs/super.c b/fs/nfs/super.c
+index 910ed906eb82..2cb56943e232 100644
+--- a/fs/nfs/super.c
++++ b/fs/nfs/super.c
+@@ -2215,6 +2215,8 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data)
+ 	struct nfs4_mount_data *options4 = (struct nfs4_mount_data *)raw_data;
+ 	u32 nfsvers = nfss->nfs_client->rpc_ops->version;
+ 
++	sync_filesystem(sb);
++
+ 	/*
+ 	 * Userspace mount programs that send binary options generally send
+ 	 * them populated with default values. We have no way to know which
+diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
+index 7ac2a122ca1d..8c532b2ca3ab 100644
+--- a/fs/nilfs2/super.c
++++ b/fs/nilfs2/super.c
+@@ -1129,6 +1129,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
+ 	unsigned long old_mount_opt;
+ 	int err;
+ 
++	sync_filesystem(sb);
+ 	old_sb_flags = sb->s_flags;
+ 	old_mount_opt = nilfs->ns_mount_opt;
+ 
+diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
+index 82650d52d916..bd5610d48242 100644
+--- a/fs/ntfs/super.c
++++ b/fs/ntfs/super.c
+@@ -468,6 +468,8 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
+ 
+ 	ntfs_debug("Entering with remount options string: %s", opt);
+ 
++	sync_filesystem(sb);
++
+ #ifndef NTFS_RW
+ 	/* For read-only compiled driver, enforce read-only flag. */
+ 	*flags |= MS_RDONLY;
+diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
+index 49d84f80f36c..5f9bf8f9dfa7 100644
+--- a/fs/ocfs2/super.c
++++ b/fs/ocfs2/super.c
+@@ -631,6 +631,8 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data)
+ 	struct ocfs2_super *osb = OCFS2_SB(sb);
+ 	u32 tmp;
+ 
++	sync_filesystem(sb);
++
+ 	if (!ocfs2_parse_options(sb, data, &parsed_options, 1) ||
+ 	    !ocfs2_check_set_options(sb, &parsed_options)) {
+ 		ret = -EINVAL;
+diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
+index 8c0ceb8dd1f7..15e4500cda3e 100644
+--- a/fs/openpromfs/inode.c
++++ b/fs/openpromfs/inode.c
+@@ -368,6 +368,7 @@ static struct inode *openprom_iget(struct super_block *sb, ino_t ino)
+ 
+ static int openprom_remount(struct super_block *sb, int *flags, char *data)
+ {
++	sync_filesystem(sb);
+ 	*flags |= MS_NOATIME;
+ 	return 0;
+ }
+diff --git a/fs/proc/root.c b/fs/proc/root.c
+index 87dbcbef7fe4..ac823a85cf6e 100644
+--- a/fs/proc/root.c
++++ b/fs/proc/root.c
+@@ -92,6 +92,8 @@ static int proc_parse_options(char *options, struct pid_namespace *pid)
+ int proc_remount(struct super_block *sb, int *flags, char *data)
+ {
+ 	struct pid_namespace *pid = sb->s_fs_info;
++
++	sync_filesystem(sb);
+ 	return !proc_parse_options(data, pid);
+ }
+ 
+diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
+index 12823845d324..192297b0090d 100644
+--- a/fs/pstore/inode.c
++++ b/fs/pstore/inode.c
+@@ -249,6 +249,7 @@ static void parse_options(char *options)
+ 
+ static int pstore_remount(struct super_block *sb, int *flags, char *data)
+ {
++	sync_filesystem(sb);
+ 	parse_options(data);
+ 
+ 	return 0;
+diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
+index 89558810381c..c4bcb778886e 100644
+--- a/fs/qnx4/inode.c
++++ b/fs/qnx4/inode.c
+@@ -44,6 +44,7 @@ static int qnx4_remount(struct super_block *sb, int *flags, char *data)
+ {
+ 	struct qnx4_sb_info *qs;
+ 
++	sync_filesystem(sb);
+ 	qs = qnx4_sb(sb);
+ 	qs->Version = QNX4_VERSION;
+ 	*flags |= MS_RDONLY;
+diff --git a/fs/qnx6/inode.c b/fs/qnx6/inode.c
+index 8d941edfefa1..65cdaab3ed49 100644
+--- a/fs/qnx6/inode.c
++++ b/fs/qnx6/inode.c
+@@ -55,6 +55,7 @@ static int qnx6_show_options(struct seq_file *seq, struct dentry *root)
+ 
+ static int qnx6_remount(struct super_block *sb, int *flags, char *data)
+ {
++	sync_filesystem(sb);
+ 	*flags |= MS_RDONLY;
+ 	return 0;
+ }
+diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
+index 2c803353f8ac..abf2b76c0d19 100644
+--- a/fs/reiserfs/super.c
++++ b/fs/reiserfs/super.c
+@@ -1319,6 +1319,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
+ 	int i;
+ #endif
+ 
++	sync_filesystem(s);
+ 	reiserfs_write_lock(s);
+ 
+ #ifdef CONFIG_QUOTA
+diff --git a/fs/romfs/super.c b/fs/romfs/super.c
+index d8418782862b..ef90e8bca95a 100644
+--- a/fs/romfs/super.c
++++ b/fs/romfs/super.c
+@@ -432,6 +432,7 @@ static int romfs_statfs(struct dentry *dentry, struct kstatfs *buf)
+  */
+ static int romfs_remount(struct super_block *sb, int *flags, char *data)
+ {
++	sync_filesystem(sb);
+ 	*flags |= MS_RDONLY;
+ 	return 0;
+ }
+diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
+index 202df6312d4e..031c8d67fd51 100644
+--- a/fs/squashfs/super.c
++++ b/fs/squashfs/super.c
+@@ -371,6 +371,7 @@ static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf)
+ 
+ static int squashfs_remount(struct super_block *sb, int *flags, char *data)
+ {
++	sync_filesystem(sb);
+ 	*flags |= MS_RDONLY;
+ 	return 0;
+ }
+diff --git a/fs/super.c b/fs/super.c
+index 80d5cf2ca765..e9dc3c3fe159 100644
+--- a/fs/super.c
++++ b/fs/super.c
+@@ -719,8 +719,6 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
+ 		}
+ 	}
+ 
+-	sync_filesystem(sb);
+-
+ 	if (sb->s_op->remount_fs) {
+ 		retval = sb->s_op->remount_fs(sb, &flags, data);
+ 		if (retval) {
+diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
+index c327d4ee1235..4742e58f3fc5 100644
+--- a/fs/sysv/inode.c
++++ b/fs/sysv/inode.c
+@@ -60,6 +60,7 @@ static int sysv_remount(struct super_block *sb, int *flags, char *data)
+ {
+ 	struct sysv_sb_info *sbi = SYSV_SB(sb);
+ 
++	sync_filesystem(sb);
+ 	if (sbi->s_forced_ro)
+ 		*flags |= MS_RDONLY;
+ 	return 0;
+diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
+index 5ded8490c0c6..e1598abd7475 100644
+--- a/fs/ubifs/super.c
++++ b/fs/ubifs/super.c
+@@ -1827,6 +1827,7 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data)
+ 	int err;
+ 	struct ubifs_info *c = sb->s_fs_info;
+ 
++	sync_filesystem(sb);
+ 	dbg_gen("old flags %#lx, new flags %#x", sb->s_flags, *flags);
+ 
+ 	err = ubifs_parse_options(c, data, 1);
+diff --git a/fs/udf/super.c b/fs/udf/super.c
+index 3306b9f69bed..64f2b7334d08 100644
+--- a/fs/udf/super.c
++++ b/fs/udf/super.c
+@@ -646,6 +646,7 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options)
+ 	int error = 0;
+ 	struct logicalVolIntegrityDescImpUse *lvidiu = udf_sb_lvidiu(sb);
+ 
++	sync_filesystem(sb);
+ 	if (lvidiu) {
+ 		int write_rev = le16_to_cpu(lvidiu->minUDFWriteRev);
+ 		if (write_rev > UDF_MAX_WRITE_VERSION && !(*flags & MS_RDONLY))
+diff --git a/fs/ufs/super.c b/fs/ufs/super.c
+index 329f2f53b7ed..b8c6791f046f 100644
+--- a/fs/ufs/super.c
++++ b/fs/ufs/super.c
+@@ -1280,6 +1280,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
+ 	unsigned new_mount_opt, ufstype;
+ 	unsigned flags;
+ 
++	sync_filesystem(sb);
+ 	lock_ufs(sb);
+ 	mutex_lock(&UFS_SB(sb)->s_lock);
+ 	uspi = UFS_SB(sb)->s_uspi;
+diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
+index f317488263dd..aaa3eca3f234 100644
+--- a/fs/xfs/xfs_super.c
++++ b/fs/xfs/xfs_super.c
+@@ -1197,6 +1197,7 @@ xfs_fs_remount(
+ 	char			*p;
+ 	int			error;
+ 
++	sync_filesystem(sb);
+ 	while ((p = strsep(&options, ",")) != NULL) {
+ 		int token;
+ 

commit 66a4cb187b92ca8663203fe8fda621e6585a2a00
+Author: Theodore Ts'o 
+Date:   Wed Mar 12 16:38:03 2014 -0400
+
+    jbd2: improve error messages for inconsistent journal heads
+    
+    Fix up error messages printed when the transaction pointers in a
+    journal head are inconsistent.  This improves the error messages which
+    are printed when running xfstests generic/068 in data=journal mode.
+    See the bug report at: https://bugzilla.kernel.org/show_bug.cgi?id=60786
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
+index 3fe29de832c8..c3fb607413ed 100644
+--- a/fs/ext4/ext4_jbd2.c
++++ b/fs/ext4/ext4_jbd2.c
+@@ -259,6 +259,16 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
+ 		if (WARN_ON_ONCE(err)) {
+ 			ext4_journal_abort_handle(where, line, __func__, bh,
+ 						  handle, err);
++			if (inode == NULL) {
++				pr_err("EXT4: jbd2_journal_dirty_metadata "
++				       "failed: handle type %u started at "
++				       "line %u, credits %u/%u, errcode %d",
++				       handle->h_type,
++				       handle->h_line_no,
++				       handle->h_requested_credits,
++				       handle->h_buffer_credits, err);
++				return err;
++			}
+ 			ext4_error_inode(inode, where, line,
+ 					 bh->b_blocknr,
+ 					 "journal_dirty_metadata failed: "
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index d999b1f6847c..38cfcf5f6fce 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -1313,7 +1313,7 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
+ 			     journal->j_running_transaction)) {
+ 			printk(KERN_ERR "JBD2: %s: "
+ 			       "jh->b_transaction (%llu, %p, %u) != "
+-			       "journal->j_running_transaction (%p, %u)",
++			       "journal->j_running_transaction (%p, %u)\n",
+ 			       journal->j_devname,
+ 			       (unsigned long long) bh->b_blocknr,
+ 			       jh->b_transaction,
+@@ -1336,30 +1336,25 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
+ 	 */
+ 	if (jh->b_transaction != transaction) {
+ 		JBUFFER_TRACE(jh, "already on other transaction");
+-		if (unlikely(jh->b_transaction !=
+-			     journal->j_committing_transaction)) {
+-			printk(KERN_ERR "JBD2: %s: "
+-			       "jh->b_transaction (%llu, %p, %u) != "
+-			       "journal->j_committing_transaction (%p, %u)",
++		if (unlikely(((jh->b_transaction !=
++			       journal->j_committing_transaction)) ||
++			     (jh->b_next_transaction != transaction))) {
++			printk(KERN_ERR "jbd2_journal_dirty_metadata: %s: "
++			       "bad jh for block %llu: "
++			       "transaction (%p, %u), "
++			       "jh->b_transaction (%p, %u), "
++			       "jh->b_next_transaction (%p, %u), jlist %u\n",
+ 			       journal->j_devname,
+ 			       (unsigned long long) bh->b_blocknr,
++			       transaction, transaction->t_tid,
+ 			       jh->b_transaction,
+-			       jh->b_transaction ? jh->b_transaction->t_tid : 0,
+-			       journal->j_committing_transaction,
+-			       journal->j_committing_transaction ?
+-			       journal->j_committing_transaction->t_tid : 0);
+-			ret = -EINVAL;
+-		}
+-		if (unlikely(jh->b_next_transaction != transaction)) {
+-			printk(KERN_ERR "JBD2: %s: "
+-			       "jh->b_next_transaction (%llu, %p, %u) != "
+-			       "transaction (%p, %u)",
+-			       journal->j_devname,
+-			       (unsigned long long) bh->b_blocknr,
++			       jh->b_transaction ?
++			       jh->b_transaction->t_tid : 0,
+ 			       jh->b_next_transaction,
+ 			       jh->b_next_transaction ?
+ 			       jh->b_next_transaction->t_tid : 0,
+-			       transaction, transaction->t_tid);
++			       jh->b_jlist);
++			WARN_ON(1);
+ 			ret = -EINVAL;
+ 		}
+ 		/* And this case is illegal: we can't reuse another

commit 0bfea8118d8e4f6aeb476511350d649e8dcb0ce8
+Author: Theodore Ts'o 
+Date:   Sun Mar 9 00:56:58 2014 -0500
+
+    jbd2: minimize region locked by j_list_lock in jbd2_journal_forget()
+    
+    It's not needed until we start trying to modifying fields in the
+    journal_head which are protected by j_list_lock.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index 357f3dc5201f..d999b1f6847c 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -1416,7 +1416,6 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
+ 	BUFFER_TRACE(bh, "entry");
+ 
+ 	jbd_lock_bh_state(bh);
+-	spin_lock(&journal->j_list_lock);
+ 
+ 	if (!buffer_jbd(bh))
+ 		goto not_jbd;
+@@ -1469,6 +1468,7 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
+ 		 * we know to remove the checkpoint after we commit.
+ 		 */
+ 
++		spin_lock(&journal->j_list_lock);
+ 		if (jh->b_cp_transaction) {
+ 			__jbd2_journal_temp_unlink_buffer(jh);
+ 			__jbd2_journal_file_buffer(jh, transaction, BJ_Forget);
+@@ -1481,6 +1481,7 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
+ 				goto drop;
+ 			}
+ 		}
++		spin_unlock(&journal->j_list_lock);
+ 	} else if (jh->b_transaction) {
+ 		J_ASSERT_JH(jh, (jh->b_transaction ==
+ 				 journal->j_committing_transaction));
+@@ -1492,7 +1493,9 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
+ 
+ 		if (jh->b_next_transaction) {
+ 			J_ASSERT(jh->b_next_transaction == transaction);
++			spin_lock(&journal->j_list_lock);
+ 			jh->b_next_transaction = NULL;
++			spin_unlock(&journal->j_list_lock);
+ 
+ 			/*
+ 			 * only drop a reference if this transaction modified
+@@ -1504,7 +1507,6 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
+ 	}
+ 
+ not_jbd:
+-	spin_unlock(&journal->j_list_lock);
+ 	jbd_unlock_bh_state(bh);
+ 	__brelse(bh);
+ drop:

commit 6e4862a5bb9d12be87e4ea5d9a60836ebed71d28
+Author: Theodore Ts'o 
+Date:   Sun Mar 9 00:46:23 2014 -0500
+
+    jbd2: minimize region locked by j_list_lock in journal_get_create_access()
+    
+    It's not needed until we start trying to modifying fields in the
+    journal_head which are protected by j_list_lock.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index 78900a1252b2..357f3dc5201f 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -1073,7 +1073,6 @@ int jbd2_journal_get_create_access(handle_t *handle, struct buffer_head *bh)
+ 	 * reused here.
+ 	 */
+ 	jbd_lock_bh_state(bh);
+-	spin_lock(&journal->j_list_lock);
+ 	J_ASSERT_JH(jh, (jh->b_transaction == transaction ||
+ 		jh->b_transaction == NULL ||
+ 		(jh->b_transaction == journal->j_committing_transaction &&
+@@ -1096,12 +1095,14 @@ int jbd2_journal_get_create_access(handle_t *handle, struct buffer_head *bh)
+ 		jh->b_modified = 0;
+ 
+ 		JBUFFER_TRACE(jh, "file as BJ_Reserved");
++		spin_lock(&journal->j_list_lock);
+ 		__jbd2_journal_file_buffer(jh, transaction, BJ_Reserved);
+ 	} else if (jh->b_transaction == journal->j_committing_transaction) {
+ 		/* first access by this transaction */
+ 		jh->b_modified = 0;
+ 
+ 		JBUFFER_TRACE(jh, "set next transaction");
++		spin_lock(&journal->j_list_lock);
+ 		jh->b_next_transaction = transaction;
+ 	}
+ 	spin_unlock(&journal->j_list_lock);

commit d2eb0b998990abf51d6e1d3bf16a2637b920a660
+Author: Theodore Ts'o 
+Date:   Sun Mar 9 00:07:19 2014 -0500
+
+    jbd2: check jh->b_transaction without taking j_list_lock
+    
+    jh->b_transaction is adequately protected for reading by the
+    jbd_lock_bh_state(bh), so we don't need to take j_list_lock in
+    __journal_try_to_free_buffer().
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index 60bb365f54a5..78900a1252b2 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -1821,11 +1821,11 @@ __journal_try_to_free_buffer(journal_t *journal, struct buffer_head *bh)
+ 	if (buffer_locked(bh) || buffer_dirty(bh))
+ 		goto out;
+ 
+-	if (jh->b_next_transaction != NULL)
++	if (jh->b_next_transaction != NULL || jh->b_transaction != NULL)
+ 		goto out;
+ 
+ 	spin_lock(&journal->j_list_lock);
+-	if (jh->b_cp_transaction != NULL && jh->b_transaction == NULL) {
++	if (jh->b_cp_transaction != NULL) {
+ 		/* written-back checkpointed metadata buffer */
+ 		JBUFFER_TRACE(jh, "remove from checkpoint list");
+ 		__jbd2_journal_remove_checkpoint(jh);

commit d4e839d4a9dc31d0c229e616146b01e1ace56604
+Author: Theodore Ts'o 
+Date:   Sat Mar 8 22:34:10 2014 -0500
+
+    jbd2: add transaction to checkpoint list earlier
+    
+    We don't otherwise need j_list_lock during the rest of commit phase
+    #7, so add the transaction to the checkpoint list at the very end of
+    commit phase #6.  This allows us to drop j_list_lock earlier, which is
+    a good thing since it is a super hot lock.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index af36252b5b2d..5f26139a165a 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -1065,6 +1065,25 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 		goto restart_loop;
+ 	}
+ 
++	/* Add the transaction to the checkpoint list
++	 * __journal_remove_checkpoint() can not destroy transaction
++	 * under us because it is not marked as T_FINISHED yet */
++	if (journal->j_checkpoint_transactions == NULL) {
++		journal->j_checkpoint_transactions = commit_transaction;
++		commit_transaction->t_cpnext = commit_transaction;
++		commit_transaction->t_cpprev = commit_transaction;
++	} else {
++		commit_transaction->t_cpnext =
++			journal->j_checkpoint_transactions;
++		commit_transaction->t_cpprev =
++			commit_transaction->t_cpnext->t_cpprev;
++		commit_transaction->t_cpnext->t_cpprev =
++			commit_transaction;
++		commit_transaction->t_cpprev->t_cpnext =
++				commit_transaction;
++	}
++	spin_unlock(&journal->j_list_lock);
++
+ 	/* Done with this transaction! */
+ 
+ 	jbd_debug(3, "JBD2: commit phase 7\n");
+@@ -1103,24 +1122,6 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 
+ 	write_unlock(&journal->j_state_lock);
+ 
+-	if (journal->j_checkpoint_transactions == NULL) {
+-		journal->j_checkpoint_transactions = commit_transaction;
+-		commit_transaction->t_cpnext = commit_transaction;
+-		commit_transaction->t_cpprev = commit_transaction;
+-	} else {
+-		commit_transaction->t_cpnext =
+-			journal->j_checkpoint_transactions;
+-		commit_transaction->t_cpprev =
+-			commit_transaction->t_cpnext->t_cpprev;
+-		commit_transaction->t_cpnext->t_cpprev =
+-			commit_transaction;
+-		commit_transaction->t_cpprev->t_cpnext =
+-				commit_transaction;
+-	}
+-	spin_unlock(&journal->j_list_lock);
+-	/* Drop all spin_locks because commit_callback may be block.
+-	 * __journal_remove_checkpoint() can not destroy transaction
+-	 * under us because it is not marked as T_FINISHED yet */
+ 	if (journal->j_commit_callback)
+ 		journal->j_commit_callback(journal, commit_transaction);
+ 
+@@ -1131,7 +1132,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	write_lock(&journal->j_state_lock);
+ 	spin_lock(&journal->j_list_lock);
+ 	commit_transaction->t_state = T_FINISHED;
+-	/* Recheck checkpoint lists after j_list_lock was dropped */
++	/* Check if the transaction can be dropped now that we are finished */
+ 	if (commit_transaction->t_checkpoint_list == NULL &&
+ 	    commit_transaction->t_checkpoint_io_list == NULL) {
+ 		__jbd2_journal_drop_transaction(journal, commit_transaction);

commit 42cf3452d5f5b0817d27c93e4e7d7eab6e89077d
+Author: Theodore Ts'o 
+Date:   Sat Mar 8 19:51:16 2014 -0500
+
+    jbd2: calculate statistics without holding j_state_lock and j_list_lock
+    
+    The two hottest locks, and thus the biggest scalability bottlenecks,
+    in the jbd2 layer, are the j_list_lock and j_state_lock.  This has
+    inspired some people to do some truly unnatural things[1].
+    
+    [1] https://www.usenix.org/system/files/conference/fast14/fast14-paper_kang.pdf
+    
+    We don't need to be holding both j_state_lock and j_list_lock while
+    calculating the journal statistics, so move those calculations to the
+    very end of jbd2_journal_commit_transaction.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index 765b31da4029..af36252b5b2d 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -1083,24 +1083,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 		atomic_read(&commit_transaction->t_handle_count);
+ 	trace_jbd2_run_stats(journal->j_fs_dev->bd_dev,
+ 			     commit_transaction->t_tid, &stats.run);
+-
+-	/*
+-	 * Calculate overall stats
+-	 */
+-	spin_lock(&journal->j_history_lock);
+-	journal->j_stats.ts_tid++;
+-	if (commit_transaction->t_requested)
+-		journal->j_stats.ts_requested++;
+-	journal->j_stats.run.rs_wait += stats.run.rs_wait;
+-	journal->j_stats.run.rs_request_delay += stats.run.rs_request_delay;
+-	journal->j_stats.run.rs_running += stats.run.rs_running;
+-	journal->j_stats.run.rs_locked += stats.run.rs_locked;
+-	journal->j_stats.run.rs_flushing += stats.run.rs_flushing;
+-	journal->j_stats.run.rs_logging += stats.run.rs_logging;
+-	journal->j_stats.run.rs_handle_count += stats.run.rs_handle_count;
+-	journal->j_stats.run.rs_blocks += stats.run.rs_blocks;
+-	journal->j_stats.run.rs_blocks_logged += stats.run.rs_blocks_logged;
+-	spin_unlock(&journal->j_history_lock);
++	stats.ts_requested = (commit_transaction->t_requested) ? 1 : 0;
+ 
+ 	commit_transaction->t_state = T_COMMIT_CALLBACK;
+ 	J_ASSERT(commit_transaction == journal->j_committing_transaction);
+@@ -1157,4 +1140,21 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	spin_unlock(&journal->j_list_lock);
+ 	write_unlock(&journal->j_state_lock);
+ 	wake_up(&journal->j_wait_done_commit);
++
++	/*
++	 * Calculate overall stats
++	 */
++	spin_lock(&journal->j_history_lock);
++	journal->j_stats.ts_tid++;
++	journal->j_stats.ts_requested += stats.ts_requested;
++	journal->j_stats.run.rs_wait += stats.run.rs_wait;
++	journal->j_stats.run.rs_request_delay += stats.run.rs_request_delay;
++	journal->j_stats.run.rs_running += stats.run.rs_running;
++	journal->j_stats.run.rs_locked += stats.run.rs_locked;
++	journal->j_stats.run.rs_flushing += stats.run.rs_flushing;
++	journal->j_stats.run.rs_logging += stats.run.rs_logging;
++	journal->j_stats.run.rs_handle_count += stats.run.rs_handle_count;
++	journal->j_stats.run.rs_blocks += stats.run.rs_blocks;
++	journal->j_stats.run.rs_blocks_logged += stats.run.rs_blocks_logged;
++	spin_unlock(&journal->j_history_lock);
+ }

commit 3469a32a1e948c54204b5dd6f7476a7d11349e9e
+Author: Theodore Ts'o 
+Date:   Sat Mar 8 19:11:36 2014 -0500
+
+    jbd2: don't hold j_state_lock while calling wake_up()
+    
+    The j_state_lock is one of the hottest locks in the jbd2 layer and
+    thus one of its scalability bottlenecks.
+    
+    We don't need to be holding the j_state_lock while we are calling
+    wake_up(&journal->j_wait_commit), so release the lock a little bit
+    earlier.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 244b6f6b7908..67b8e303946c 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -302,8 +302,8 @@ static void journal_kill_thread(journal_t *journal)
+ 	journal->j_flags |= JBD2_UNMOUNT;
+ 
+ 	while (journal->j_task) {
+-		wake_up(&journal->j_wait_commit);
+ 		write_unlock(&journal->j_state_lock);
++		wake_up(&journal->j_wait_commit);
+ 		wait_event(journal->j_wait_done_commit, journal->j_task == NULL);
+ 		write_lock(&journal->j_state_lock);
+ 	}
+@@ -710,8 +710,8 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid)
+ 	while (tid_gt(tid, journal->j_commit_sequence)) {
+ 		jbd_debug(1, "JBD2: want %d, j_commit_sequence=%d\n",
+ 				  tid, journal->j_commit_sequence);
+-		wake_up(&journal->j_wait_commit);
+ 		read_unlock(&journal->j_state_lock);
++		wake_up(&journal->j_wait_commit);
+ 		wait_event(journal->j_wait_done_commit,
+ 				!tid_gt(tid, journal->j_commit_sequence));
+ 		read_lock(&journal->j_state_lock);

commit df3c1e9a05ff25aca9f54a6c08b77003e2e32bf1
+Author: Theodore Ts'o 
+Date:   Sat Mar 8 18:13:52 2014 -0500
+
+    jbd2: don't unplug after writing revoke records
+    
+    During commit process, keep the block device plugged after we are done
+    writing the revoke records, until we are finished writing the rest of
+    the commit records in the journal.  This will allow most of the
+    journal blocks to be written in a single I/O operation, instead of
+    separating the the revoke blocks from the rest of the journal blocks.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index cf2fc0594063..765b31da4029 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -555,7 +555,6 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	blk_start_plug(&plug);
+ 	jbd2_journal_write_revoke_records(journal, commit_transaction,
+ 					  &log_bufs, WRITE_SYNC);
+-	blk_finish_plug(&plug);
+ 
+ 	jbd_debug(3, "JBD2: commit phase 2b\n");
+ 
+@@ -582,7 +581,6 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	err = 0;
+ 	bufs = 0;
+ 	descriptor = NULL;
+-	blk_start_plug(&plug);
+ 	while (commit_transaction->t_buffers) {
+ 
+ 		/* Find the next buffer to be journaled... */

commit e861b5e9a47bd8c6a7491a2b9f6e9a230b1b8e86
+Author: Theodore Ts'o 
+Date:   Thu Feb 20 12:54:05 2014 -0500
+
+    ext4: avoid possible overflow in ext4_map_blocks()
+    
+    The ext4_map_blocks() function returns the number of blocks which
+    satisfying the caller's request.  This number of blocks requested by
+    the caller is specified by an unsigned integer, but the return value
+    of ext4_map_blocks() is a signed integer (to accomodate error codes
+    per the kernel's standard error signalling convention).
+    
+    Historically, overflows could never happen since mballoc() will refuse
+    to allocate more than 2048 blocks at a time (which is something we
+    should fix), and if the blocks were already allocated, the fact that
+    there would be some number of intervening metadata blocks pretty much
+    guaranteed that there could never be a contiguous region of data
+    blocks that was greater than 2**31 blocks.
+    
+    However, this is now possible if there is a file system which is a bit
+    bigger than 8TB, and is created using the new mke2fs hugeblock
+    feature, which can create a perfectly contiguous file.  In that case,
+    if a userspace program attempted to call fallocate() on this already
+    fully allocated file, it's possible that ext4_map_blocks() could
+    return a number large enough that it would overflow a signed integer,
+    resulting in a ext4 thinking that the ext4_map_blocks() call had
+    failed with some strange error code.
+    
+    Since ext4_map_blocks() is always free to return a smaller number of
+    blocks than what was requested by the caller, fix this by capping the
+    number of blocks that ext4_map_blocks() will ever try to map to 2**31
+    - 1.  In practice this should never get hit, except by someone
+    deliberately trying to provke the above-described bug.
+    
+    Thanks to the PaX team for asking whethre this could possibly happen
+    in some off-line discussions about using some static code checking
+    technology they are developing to find bugs in kernel code.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 6e39895a91b8..113458c9d08b 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -514,6 +514,12 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
+ 		  "logical block %lu\n", inode->i_ino, flags, map->m_len,
+ 		  (unsigned long) map->m_lblk);
+ 
++	/*
++	 * ext4_map_blocks returns an int, and m_len is an unsigned int
++	 */
++	if (unlikely(map->m_len > INT_MAX))
++		map->m_len = INT_MAX;
++
+ 	/* Lookup extent status tree firstly */
+ 	if (ext4_es_lookup_extent(inode, map->m_lblk, &es)) {
+ 		ext4_es_lru_add(inode);

commit ab0c00fccf81dcf1dc5db0e389294ffea53be666
+Author: Theodore Ts'o 
+Date:   Thu Feb 20 00:36:41 2014 -0500
+
+    ext4: make sure ex.fe_logical is initialized
+    
+    The lowest levels of mballoc set all of the fields of struct
+    ext4_free_extent except for fe_logical, since they are just trying to
+    find the requested free set of blocks, and the logical block hasn't
+    been set yet.  This makes some static code checkers sad.  Set it to
+    various different debug values, which would be useful when
+    debugging mballoc if these values were to ever show up due to the
+    parts of mballoc triyng to use ac->ac_b_ex.fe_logical before it is
+    properly upper layers of mballoc failing to properly set, usually by
+    ext4_mb_use_best_found().
+    
+    Addresses-Coverity-Id: #139697
+    Addresses-Coverity-Id: #139698
+    Addresses-Coverity-Id: #139699
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 04a5c7504be9..0d42f635dda9 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -1808,6 +1808,7 @@ int ext4_mb_find_by_goal(struct ext4_allocation_context *ac,
+ 	ext4_lock_group(ac->ac_sb, group);
+ 	max = mb_find_extent(e4b, ac->ac_g_ex.fe_start,
+ 			     ac->ac_g_ex.fe_len, &ex);
++	ex.fe_logical = 0xDEADFA11; /* debug value */
+ 
+ 	if (max >= ac->ac_g_ex.fe_len && ac->ac_g_ex.fe_len == sbi->s_stripe) {
+ 		ext4_fsblk_t start;
+@@ -1936,7 +1937,7 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
+ 			 */
+ 			break;
+ 		}
+-
++		ex.fe_logical = 0xDEADC0DE; /* debug value */
+ 		ext4_mb_measure_extent(ac, &ex, e4b);
+ 
+ 		i += ex.fe_len;
+@@ -1977,6 +1978,7 @@ void ext4_mb_scan_aligned(struct ext4_allocation_context *ac,
+ 			max = mb_find_extent(e4b, i, sbi->s_stripe, &ex);
+ 			if (max >= sbi->s_stripe) {
+ 				ac->ac_found++;
++				ex.fe_logical = 0xDEADF00D; /* debug value */
+ 				ac->ac_b_ex = ex;
+ 				ext4_mb_use_best_found(ac, e4b);
+ 				break;

commit 7b1b2c1b9c397dcb86293ae79aa7fb7c5446120f
+Author: Theodore Ts'o 
+Date:   Wed Feb 19 20:15:21 2014 -0500
+
+    ext4: don't calculate total xattr header size unless needed
+    
+    The function ext4_expand_extra_isize_ea() doesn't need the size of all
+    of the extended attribute headers.  So if we don't calculate it when
+    it is unneeded, it we can skip some undeeded memory references, and as
+    a bonus, we eliminate some kvetching by static code analysis tools.
+    
+    Addresses-Coverity-Id: #741291
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index e175e94116ac..185066f475f1 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -567,12 +567,13 @@ static size_t ext4_xattr_free_space(struct ext4_xattr_entry *last,
+ 				    size_t *min_offs, void *base, int *total)
+ {
+ 	for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) {
+-		*total += EXT4_XATTR_LEN(last->e_name_len);
+ 		if (!last->e_value_block && last->e_value_size) {
+ 			size_t offs = le16_to_cpu(last->e_value_offs);
+ 			if (offs < *min_offs)
+ 				*min_offs = offs;
+ 		}
++		if (total)
++			*total += EXT4_XATTR_LEN(last->e_name_len);
+ 	}
+ 	return (*min_offs - ((void *)last - base) - sizeof(__u32));
+ }
+@@ -1228,7 +1229,7 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
+ 	struct ext4_xattr_block_find *bs = NULL;
+ 	char *buffer = NULL, *b_entry_name = NULL;
+ 	size_t min_offs, free;
+-	int total_ino, total_blk;
++	int total_ino;
+ 	void *base, *start, *end;
+ 	int extra_isize = 0, error = 0, tried_min_extra_isize = 0;
+ 	int s_min_extra_isize = le16_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_min_extra_isize);
+@@ -1286,8 +1287,7 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
+ 		first = BFIRST(bh);
+ 		end = bh->b_data + bh->b_size;
+ 		min_offs = end - base;
+-		free = ext4_xattr_free_space(first, &min_offs, base,
+-					     &total_blk);
++		free = ext4_xattr_free_space(first, &min_offs, base, NULL);
+ 		if (free < new_extra_isize) {
+ 			if (!tried_min_extra_isize && s_min_extra_isize) {
+ 				tried_min_extra_isize++;

commit 9a6633b1a3603ccdffec669033616f9ebb35a988
+Author: Theodore Ts'o 
+Date:   Wed Feb 19 20:15:15 2014 -0500
+
+    ext4: add ext4_es_store_pblock_status()
+    
+    Avoid false positives by static code analysis tools such as sparse and
+    coverity caused by the fact that we set the physical block, and then
+    the status in the extent_status structure.  It is also more efficient
+    to set both of these values at once.
+    
+    Addresses-Coverity-Id: #989077
+    Addresses-Coverity-Id: #989078
+    Addresses-Coverity-Id: #1080722
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Zheng Liu 
+
+diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
+index 3981ff783950..a900004a63e1 100644
+--- a/fs/ext4/extents_status.c
++++ b/fs/ext4/extents_status.c
+@@ -658,8 +658,7 @@ int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
+ 
+ 	newes.es_lblk = lblk;
+ 	newes.es_len = len;
+-	ext4_es_store_pblock(&newes, pblk);
+-	ext4_es_store_status(&newes, status);
++	ext4_es_store_pblock_status(&newes, pblk, status);
+ 	trace_ext4_es_insert_extent(inode, &newes);
+ 
+ 	ext4_es_insert_extent_check(inode, &newes);
+@@ -699,8 +698,7 @@ void ext4_es_cache_extent(struct inode *inode, ext4_lblk_t lblk,
+ 
+ 	newes.es_lblk = lblk;
+ 	newes.es_len = len;
+-	ext4_es_store_pblock(&newes, pblk);
+-	ext4_es_store_status(&newes, status);
++	ext4_es_store_pblock_status(&newes, pblk, status);
+ 	trace_ext4_es_cache_extent(inode, &newes);
+ 
+ 	if (!len)
+@@ -812,13 +810,13 @@ static int __es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
+ 
+ 			newes.es_lblk = end + 1;
+ 			newes.es_len = len2;
++			block = 0x7FDEADBEEF;
+ 			if (ext4_es_is_written(&orig_es) ||
+-			    ext4_es_is_unwritten(&orig_es)) {
++			    ext4_es_is_unwritten(&orig_es))
+ 				block = ext4_es_pblock(&orig_es) +
+ 					orig_es.es_len - len2;
+-				ext4_es_store_pblock(&newes, block);
+-			}
+-			ext4_es_store_status(&newes, ext4_es_status(&orig_es));
++			ext4_es_store_pblock_status(&newes, block,
++						    ext4_es_status(&orig_es));
+ 			err = __es_insert_extent(inode, &newes);
+ 			if (err) {
+ 				es->es_lblk = orig_es.es_lblk;
+diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h
+index 167f4ab8ecc3..f1b62a419920 100644
+--- a/fs/ext4/extents_status.h
++++ b/fs/ext4/extents_status.h
+@@ -129,6 +129,15 @@ static inline void ext4_es_store_status(struct extent_status *es,
+ 		       (es->es_pblk & ~ES_MASK));
+ }
+ 
++static inline void ext4_es_store_pblock_status(struct extent_status *es,
++					       ext4_fsblk_t pb,
++					       unsigned int status)
++{
++	es->es_pblk = (((ext4_fsblk_t)
++			(status & EXTENT_STATUS_FLAGS) << ES_SHIFT) |
++		       (pb & ~ES_MASK));
++}
++
+ extern void ext4_es_register_shrinker(struct ext4_sb_info *sbi);
+ extern void ext4_es_unregister_shrinker(struct ext4_sb_info *sbi);
+ extern void ext4_es_lru_add(struct inode *inode);

commit d8558a297878f1a7af995f6801983783e1487208
+Author: Theodore Ts'o 
+Date:   Mon Feb 17 20:44:36 2014 -0500
+
+    ext4: clean up error handling in swap_inode_boot_loader()
+    
+    Tighten up the code to make the code easier to read and maintain.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index a2a837f00407..0f2252ec274d 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -104,21 +104,15 @@ static long swap_inode_boot_loader(struct super_block *sb,
+ 	struct ext4_inode_info *ei_bl;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 
+-	if (inode->i_nlink != 1 || !S_ISREG(inode->i_mode)) {
+-		err = -EINVAL;
+-		goto swap_boot_out;
+-	}
++	if (inode->i_nlink != 1 || !S_ISREG(inode->i_mode))
++		return -EINVAL;
+ 
+-	if (!inode_owner_or_capable(inode) || !capable(CAP_SYS_ADMIN)) {
+-		err = -EPERM;
+-		goto swap_boot_out;
+-	}
++	if (!inode_owner_or_capable(inode) || !capable(CAP_SYS_ADMIN))
++		return -EPERM;
+ 
+ 	inode_bl = ext4_iget(sb, EXT4_BOOT_LOADER_INO);
+-	if (IS_ERR(inode_bl)) {
+-		err = PTR_ERR(inode_bl);
+-		goto swap_boot_out;
+-	}
++	if (IS_ERR(inode_bl))
++		return PTR_ERR(inode_bl);
+ 	ei_bl = EXT4_I(inode_bl);
+ 
+ 	filemap_flush(inode->i_mapping);
+@@ -193,20 +187,14 @@ static long swap_inode_boot_loader(struct super_block *sb,
+ 			ext4_mark_inode_dirty(handle, inode);
+ 		}
+ 	}
+-
+ 	ext4_journal_stop(handle);
+-
+ 	ext4_double_up_write_data_sem(inode, inode_bl);
+ 
+ journal_err_out:
+ 	ext4_inode_resume_unlocked_dio(inode);
+ 	ext4_inode_resume_unlocked_dio(inode_bl);
+-
+ 	unlock_two_nondirectories(inode, inode_bl);
+-
+ 	iput(inode_bl);
+-
+-swap_boot_out:
+ 	return err;
+ }
+ 

commit 19ea80603715d473600cd993b9987bc97d042e02
+Author: Theodore Ts'o 
+Date:   Sun Feb 16 19:29:32 2014 -0500
+
+    ext4: don't leave i_crtime.tv_sec uninitialized
+    
+    If the i_crtime field is not present in the inode, don't leave the
+    field uninitialized.
+    
+    Fixes: ef7f38359 ("ext4: Add nanosecond timestamps")
+    Reported-by: Vegard Nossum 
+    Tested-by: Vegard Nossum 
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index ece55565b9cd..d3a534fdc5ff 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -771,6 +771,8 @@ do {									       \
+ 	if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime))		       \
+ 		(einode)->xtime.tv_sec = 				       \
+ 			(signed)le32_to_cpu((raw_inode)->xtime);	       \
++	else								       \
++		(einode)->xtime.tv_sec = 0;				       \
+ 	if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime ## _extra))	       \
+ 		ext4_decode_extra_time(&(einode)->xtime,		       \
+ 				       raw_inode->xtime ## _extra);	       \

commit 3d2660d0c9c2f296837078c189b68a47f6b2e3b5
+Author: Theodore Ts'o 
+Date:   Sat Feb 15 22:42:25 2014 -0500
+
+    ext4: fix online resize with a non-standard blocks per group setting
+    
+    The set_flexbg_block_bitmap() function assumed that the number of
+    blocks in a blockgroup was sb->blocksize * 8, which is normally true,
+    but not always!  Use EXT4_BLOCKS_PER_GROUP(sb) instead, to fix block
+    bitmap corruption after:
+    
+    mke2fs -t ext4 -g 3072 -i 4096 /dev/vdd 1G
+    mount -t ext4 /dev/vdd /vdd
+    resize2fs /dev/vdd 8G
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reported-by: Jon Bernard 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 69a62610a6ca..f3b84cd9de56 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -409,7 +409,7 @@ static int set_flexbg_block_bitmap(struct super_block *sb, handle_t *handle,
+ 		start = ext4_group_first_block_no(sb, group);
+ 		group -= flex_gd->groups[0].group;
+ 
+-		count2 = sb->s_blocksize * 8 - (block - start);
++		count2 = EXT4_BLOCKS_PER_GROUP(sb) - (block - start);
+ 		if (count2 > count)
+ 			count2 = count;
+ 

commit b93c95353413041a8cebad915a8109619f66bcc6
+Author: Theodore Ts'o 
+Date:   Sat Feb 15 21:33:13 2014 -0500
+
+    ext4: fix online resize with very large inode tables
+    
+    If a file system has a large number of inodes per block group, all of
+    the metadata blocks in a flex_bg may be larger than what can fit in a
+    single block group.  Unfortunately, ext4_alloc_group_tables() in
+    resize.c was never tested to see if it would handle this case
+    correctly, and there were a large number of bugs which caused the
+    following sequence to result in a BUG_ON:
+    
+    kernel bug at fs/ext4/resize.c:409!
+       ...
+    call trace:
+     [] ext4_flex_group_add+0x1448/0x1830
+     [] ext4_resize_fs+0x7b2/0xe80
+     [] ext4_ioctl+0xbf0/0xf00
+     [] do_vfs_ioctl+0x2dd/0x4b0
+     [] ? final_putname+0x22/0x50
+     [] sys_ioctl+0x81/0xa0
+     [] system_call_fastpath+0x16/0x1b
+    code: c8 4c 89 df e8 41 96 f8 ff 44 89 e8 49 01 c4 44 29 6d d4 0
+    rip  [] set_flexbg_block_bitmap+0x171/0x180
+    
+    
+    This can be reproduced with the following command sequence:
+    
+       mke2fs -t ext4 -i 4096 /dev/vdd 1G
+       mount -t ext4 /dev/vdd /vdd
+       resize2fs /dev/vdd 8G
+    
+    To fix this, we need to make sure the right thing happens when a block
+    group's inode table straddles two block groups, which means the
+    following bugs had to be fixed:
+    
+    1) Not clearing the BLOCK_UNINIT flag in the second block group in
+       ext4_alloc_group_tables --- the was proximate cause of the BUG_ON.
+    
+    2) Incorrectly determining how many block groups contained contiguous
+       free blocks in ext4_alloc_group_tables().
+    
+    3) Incorrectly setting the start of the next block range to be marked
+       in use after a discontinuity in setup_new_flex_group_blocks().
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index c5adbb318a90..69a62610a6ca 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -243,6 +243,7 @@ static int ext4_alloc_group_tables(struct super_block *sb,
+ 	ext4_group_t group;
+ 	ext4_group_t last_group;
+ 	unsigned overhead;
++	__u16 uninit_mask = (flexbg_size > 1) ? ~EXT4_BG_BLOCK_UNINIT : ~0;
+ 
+ 	BUG_ON(flex_gd->count == 0 || group_data == NULL);
+ 
+@@ -266,7 +267,7 @@ static int ext4_alloc_group_tables(struct super_block *sb,
+ 	src_group++;
+ 	for (; src_group <= last_group; src_group++) {
+ 		overhead = ext4_group_overhead_blocks(sb, src_group);
+-		if (overhead != 0)
++		if (overhead == 0)
+ 			last_blk += group_data[src_group - group].blocks_count;
+ 		else
+ 			break;
+@@ -280,8 +281,7 @@ static int ext4_alloc_group_tables(struct super_block *sb,
+ 		group = ext4_get_group_number(sb, start_blk - 1);
+ 		group -= group_data[0].group;
+ 		group_data[group].free_blocks_count--;
+-		if (flexbg_size > 1)
+-			flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT;
++		flex_gd->bg_flags[group] &= uninit_mask;
+ 	}
+ 
+ 	/* Allocate inode bitmaps */
+@@ -292,22 +292,30 @@ static int ext4_alloc_group_tables(struct super_block *sb,
+ 		group = ext4_get_group_number(sb, start_blk - 1);
+ 		group -= group_data[0].group;
+ 		group_data[group].free_blocks_count--;
+-		if (flexbg_size > 1)
+-			flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT;
++		flex_gd->bg_flags[group] &= uninit_mask;
+ 	}
+ 
+ 	/* Allocate inode tables */
+ 	for (; it_index < flex_gd->count; it_index++) {
+-		if (start_blk + EXT4_SB(sb)->s_itb_per_group > last_blk)
++		unsigned int itb = EXT4_SB(sb)->s_itb_per_group;
++		ext4_fsblk_t next_group_start;
++
++		if (start_blk + itb > last_blk)
+ 			goto next_group;
+ 		group_data[it_index].inode_table = start_blk;
+-		group = ext4_get_group_number(sb, start_blk - 1);
++		group = ext4_get_group_number(sb, start_blk);
++		next_group_start = ext4_group_first_block_no(sb, group + 1);
+ 		group -= group_data[0].group;
+-		group_data[group].free_blocks_count -=
+-					EXT4_SB(sb)->s_itb_per_group;
+-		if (flexbg_size > 1)
+-			flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT;
+ 
++		if (start_blk + itb > next_group_start) {
++			flex_gd->bg_flags[group + 1] &= uninit_mask;
++			overhead = start_blk + itb - next_group_start;
++			group_data[group + 1].free_blocks_count -= overhead;
++			itb -= overhead;
++		}
++
++		group_data[group].free_blocks_count -= itb;
++		flex_gd->bg_flags[group] &= uninit_mask;
+ 		start_blk += EXT4_SB(sb)->s_itb_per_group;
+ 	}
+ 
+@@ -620,7 +628,7 @@ static int setup_new_flex_group_blocks(struct super_block *sb,
+ 			if (err)
+ 				goto out;
+ 			count = group_table_count[j];
+-			start = group_data[i].block_bitmap;
++			start = (&group_data[i].block_bitmap)[j];
+ 			block = start;
+ 		}
+ 

commit 23301410972330c0ae9a8afc379ba2005e249cc6
+Author: Theodore Ts'o 
+Date:   Wed Feb 12 12:16:04 2014 -0500
+
+    ext4: don't try to modify s_flags if the the file system is read-only
+    
+    If an ext4 file system is created by some tool other than mke2fs
+    (perhaps by someone who has a pathalogical fear of the GPL) that
+    doesn't set one or the other of the EXT2_FLAGS_{UN}SIGNED_HASH flags,
+    and that file system is then mounted read-only, don't try to modify
+    the s_flags field.  Otherwise, if dm_verity is in use, the superblock
+    will change, causing an dm_verity failure.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 1f7784de05b6..710fed2377d4 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3695,16 +3695,22 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	for (i = 0; i < 4; i++)
+ 		sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
+ 	sbi->s_def_hash_version = es->s_def_hash_version;
+-	i = le32_to_cpu(es->s_flags);
+-	if (i & EXT2_FLAGS_UNSIGNED_HASH)
+-		sbi->s_hash_unsigned = 3;
+-	else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) {
++	if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) {
++		i = le32_to_cpu(es->s_flags);
++		if (i & EXT2_FLAGS_UNSIGNED_HASH)
++			sbi->s_hash_unsigned = 3;
++		else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) {
+ #ifdef __CHAR_UNSIGNED__
+-		es->s_flags |= cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH);
+-		sbi->s_hash_unsigned = 3;
++			if (!(sb->s_flags & MS_RDONLY))
++				es->s_flags |=
++					cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH);
++			sbi->s_hash_unsigned = 3;
+ #else
+-		es->s_flags |= cpu_to_le32(EXT2_FLAGS_SIGNED_HASH);
++			if (!(sb->s_flags & MS_RDONLY))
++				es->s_flags |=
++					cpu_to_le32(EXT2_FLAGS_SIGNED_HASH);
+ #endif
++		}
+ 	}
+ 
+ 	/* Handle clustersize */

commit 8c9367fd9bf252b57c6d4f8e1a7f9de809d8b862
+Author: Theodore Ts'o 
+Date:   Tue Jan 7 13:08:03 2014 -0500
+
+    ext4: don't pass freed handle to ext4_walk_page_buffers
+    
+    This is harmless, since ext4_walk_page_buffers only passes the handle
+    onto the callback function, and in this call site the function in
+    question, bput_one(), doesn't actually use the handle.  But there's no
+    point passing in an invalid handle, and it creates a Coverity warning,
+    so let's just clean it up.
+    
+    Addresses-Coverity-Id: #1091168
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 8454ebe238a0..f33b4eb82d80 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1772,7 +1772,7 @@ static int __ext4_journalled_writepage(struct page *page,
+ 		ret = err;
+ 
+ 	if (!ext4_has_inline_data(inode))
+-		ext4_walk_page_buffers(handle, page_bufs, 0, len,
++		ext4_walk_page_buffers(NULL, page_bufs, 0, len,
+ 				       NULL, bput_one);
+ 	ext4_set_inode_state(inode, EXT4_STATE_JDATA);
+ out:

commit 09c455aaa8f47a94d5bafaa23d58365768210507
+Author: Theodore Ts'o 
+Date:   Tue Jan 7 12:58:19 2014 -0500
+
+    ext4: avoid clearing beyond i_blocks when truncating an inline data file
+    
+    A missing cast means that when we are truncating a file which is less
+    than 60 bytes, we don't clear the correct area of memory, and in fact
+    we can end up truncating the next inode in the inode table, or worse
+    yet, some other kernel data structure.
+    
+    Addresses-Coverity-Id: #751987
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index c417e52d194e..ed29e720e880 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -1928,9 +1928,11 @@ void ext4_inline_data_truncate(struct inode *inode, int *has_inline)
+ 		}
+ 
+ 		/* Clear the content within i_blocks. */
+-		if (i_size < EXT4_MIN_INLINE_DATA_SIZE)
+-			memset(ext4_raw_inode(&is.iloc)->i_block + i_size, 0,
+-					EXT4_MIN_INLINE_DATA_SIZE - i_size);
++		if (i_size < EXT4_MIN_INLINE_DATA_SIZE) {
++			void *p = (void *) ext4_raw_inode(&is.iloc)->i_block;
++			memset(p + i_size, 0,
++			       EXT4_MIN_INLINE_DATA_SIZE - i_size);
++		}
+ 
+ 		EXT4_I(inode)->i_inline_size = i_size <
+ 					EXT4_MIN_INLINE_DATA_SIZE ?

commit f5a44db5d2d677dfbf12deee461f85e9ec633961
+Author: Theodore Ts'o 
+Date:   Fri Dec 20 09:29:35 2013 -0500
+
+    ext4: add explicit casts when masking cluster sizes
+    
+    The missing casts can cause the high 64-bits of the physical blocks to
+    be lost.  Set up new macros which allows us to make sure the right
+    thing happen, even if at some point we end up supporting larger
+    logical block numbers.
+    
+    Thanks to the Emese Revfy and the PaX security team for reporting this
+    issue.
+    
+    Reported-by: PaX Team 
+    Reported-by: Emese Revfy 
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index e6185031c1cc..ece55565b9cd 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -268,6 +268,16 @@ struct ext4_io_submit {
+ /* Translate # of blks to # of clusters */
+ #define EXT4_NUM_B2C(sbi, blks)	(((blks) + (sbi)->s_cluster_ratio - 1) >> \
+ 				 (sbi)->s_cluster_bits)
++/* Mask out the low bits to get the starting block of the cluster */
++#define EXT4_PBLK_CMASK(s, pblk) ((pblk) &				\
++				  ~((ext4_fsblk_t) (s)->s_cluster_ratio - 1))
++#define EXT4_LBLK_CMASK(s, lblk) ((lblk) &				\
++				  ~((ext4_lblk_t) (s)->s_cluster_ratio - 1))
++/* Get the cluster offset */
++#define EXT4_PBLK_COFF(s, pblk) ((pblk) &				\
++				 ((ext4_fsblk_t) (s)->s_cluster_ratio - 1))
++#define EXT4_LBLK_COFF(s, lblk) ((lblk) &				\
++				 ((ext4_lblk_t) (s)->s_cluster_ratio - 1))
+ 
+ /*
+  * Structure of a blocks group descriptor
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 267c9fb53bf9..4410cc3d6ee2 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -1851,8 +1851,7 @@ static unsigned int ext4_ext_check_overlap(struct ext4_sb_info *sbi,
+ 	depth = ext_depth(inode);
+ 	if (!path[depth].p_ext)
+ 		goto out;
+-	b2 = le32_to_cpu(path[depth].p_ext->ee_block);
+-	b2 &= ~(sbi->s_cluster_ratio - 1);
++	b2 = EXT4_LBLK_CMASK(sbi, le32_to_cpu(path[depth].p_ext->ee_block));
+ 
+ 	/*
+ 	 * get the next allocated block if the extent in the path
+@@ -1862,7 +1861,7 @@ static unsigned int ext4_ext_check_overlap(struct ext4_sb_info *sbi,
+ 		b2 = ext4_ext_next_allocated_block(path);
+ 		if (b2 == EXT_MAX_BLOCKS)
+ 			goto out;
+-		b2 &= ~(sbi->s_cluster_ratio - 1);
++		b2 = EXT4_LBLK_CMASK(sbi, b2);
+ 	}
+ 
+ 	/* check for wrap through zero on extent logical start block*/
+@@ -2521,7 +2520,7 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
+ 		 * extent, we have to mark the cluster as used (store negative
+ 		 * cluster number in partial_cluster).
+ 		 */
+-		unaligned = pblk & (sbi->s_cluster_ratio - 1);
++		unaligned = EXT4_PBLK_COFF(sbi, pblk);
+ 		if (unaligned && (ee_len == num) &&
+ 		    (*partial_cluster != -((long long)EXT4_B2C(sbi, pblk))))
+ 			*partial_cluster = EXT4_B2C(sbi, pblk);
+@@ -2615,7 +2614,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
+ 			 * accidentally freeing it later on
+ 			 */
+ 			pblk = ext4_ext_pblock(ex);
+-			if (pblk & (sbi->s_cluster_ratio - 1))
++			if (EXT4_PBLK_COFF(sbi, pblk))
+ 				*partial_cluster =
+ 					-((long long)EXT4_B2C(sbi, pblk));
+ 			ex--;
+@@ -3770,7 +3769,7 @@ int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+ 	ext4_lblk_t lblk_start, lblk_end;
+-	lblk_start = lblk & (~(sbi->s_cluster_ratio - 1));
++	lblk_start = EXT4_LBLK_CMASK(sbi, lblk);
+ 	lblk_end = lblk_start + sbi->s_cluster_ratio - 1;
+ 
+ 	return ext4_find_delalloc_range(inode, lblk_start, lblk_end);
+@@ -3829,9 +3828,9 @@ get_reserved_cluster_alloc(struct inode *inode, ext4_lblk_t lblk_start,
+ 	trace_ext4_get_reserved_cluster_alloc(inode, lblk_start, num_blks);
+ 
+ 	/* Check towards left side */
+-	c_offset = lblk_start & (sbi->s_cluster_ratio - 1);
++	c_offset = EXT4_LBLK_COFF(sbi, lblk_start);
+ 	if (c_offset) {
+-		lblk_from = lblk_start & (~(sbi->s_cluster_ratio - 1));
++		lblk_from = EXT4_LBLK_CMASK(sbi, lblk_start);
+ 		lblk_to = lblk_from + c_offset - 1;
+ 
+ 		if (ext4_find_delalloc_range(inode, lblk_from, lblk_to))
+@@ -3839,7 +3838,7 @@ get_reserved_cluster_alloc(struct inode *inode, ext4_lblk_t lblk_start,
+ 	}
+ 
+ 	/* Now check towards right. */
+-	c_offset = (lblk_start + num_blks) & (sbi->s_cluster_ratio - 1);
++	c_offset = EXT4_LBLK_COFF(sbi, lblk_start + num_blks);
+ 	if (allocated_clusters && c_offset) {
+ 		lblk_from = lblk_start + num_blks;
+ 		lblk_to = lblk_from + (sbi->s_cluster_ratio - c_offset) - 1;
+@@ -4047,7 +4046,7 @@ static int get_implied_cluster_alloc(struct super_block *sb,
+ 				     struct ext4_ext_path *path)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-	ext4_lblk_t c_offset = map->m_lblk & (sbi->s_cluster_ratio-1);
++	ext4_lblk_t c_offset = EXT4_LBLK_COFF(sbi, map->m_lblk);
+ 	ext4_lblk_t ex_cluster_start, ex_cluster_end;
+ 	ext4_lblk_t rr_cluster_start;
+ 	ext4_lblk_t ee_block = le32_to_cpu(ex->ee_block);
+@@ -4065,8 +4064,7 @@ static int get_implied_cluster_alloc(struct super_block *sb,
+ 	    (rr_cluster_start == ex_cluster_start)) {
+ 		if (rr_cluster_start == ex_cluster_end)
+ 			ee_start += ee_len - 1;
+-		map->m_pblk = (ee_start & ~(sbi->s_cluster_ratio - 1)) +
+-			c_offset;
++		map->m_pblk = EXT4_PBLK_CMASK(sbi, ee_start) + c_offset;
+ 		map->m_len = min(map->m_len,
+ 				 (unsigned) sbi->s_cluster_ratio - c_offset);
+ 		/*
+@@ -4220,7 +4218,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 	 */
+ 	map->m_flags &= ~EXT4_MAP_FROM_CLUSTER;
+ 	newex.ee_block = cpu_to_le32(map->m_lblk);
+-	cluster_offset = map->m_lblk & (sbi->s_cluster_ratio-1);
++	cluster_offset = EXT4_LBLK_CMASK(sbi, map->m_lblk);
+ 
+ 	/*
+ 	 * If we are doing bigalloc, check to see if the extent returned
+@@ -4288,7 +4286,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 	 * needed so that future calls to get_implied_cluster_alloc()
+ 	 * work correctly.
+ 	 */
+-	offset = map->m_lblk & (sbi->s_cluster_ratio - 1);
++	offset = EXT4_LBLK_COFF(sbi, map->m_lblk);
+ 	ar.len = EXT4_NUM_B2C(sbi, offset+allocated);
+ 	ar.goal -= offset;
+ 	ar.logical -= offset;
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 04766d9a29cd..04a5c7504be9 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -4126,7 +4126,7 @@ ext4_mb_initialize_context(struct ext4_allocation_context *ac,
+ 	ext4_get_group_no_and_offset(sb, goal, &group, &block);
+ 
+ 	/* set up allocation goals */
+-	ac->ac_b_ex.fe_logical = ar->logical & ~(sbi->s_cluster_ratio - 1);
++	ac->ac_b_ex.fe_logical = EXT4_LBLK_CMASK(sbi, ar->logical);
+ 	ac->ac_status = AC_STATUS_CONTINUE;
+ 	ac->ac_sb = sb;
+ 	ac->ac_inode = ar->inode;
+@@ -4668,7 +4668,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 	 * blocks at the beginning or the end unless we are explicitly
+ 	 * requested to avoid doing so.
+ 	 */
+-	overflow = block & (sbi->s_cluster_ratio - 1);
++	overflow = EXT4_PBLK_COFF(sbi, block);
+ 	if (overflow) {
+ 		if (flags & EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER) {
+ 			overflow = sbi->s_cluster_ratio - overflow;
+@@ -4682,7 +4682,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 			count += overflow;
+ 		}
+ 	}
+-	overflow = count & (sbi->s_cluster_ratio - 1);
++	overflow = EXT4_LBLK_COFF(sbi, count);
+ 	if (overflow) {
+ 		if (flags & EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER) {
+ 			if (count > overflow)

commit f6c07cad081ba222d63623d913aafba5586c1d2c
+Author: Theodore Ts'o 
+Date:   Sun Dec 8 21:12:59 2013 -0500
+
+    jbd2: don't BUG but return ENOSPC if a handle runs out of space
+    
+    If a handle runs out of space, we currently stop the kernel with a BUG
+    in jbd2_journal_dirty_metadata().  This makes it hard to figure out
+    what might be going on.  So return an error of ENOSPC, so we can let
+    the file system layer figure out what is going on, to make it more
+    likely we can get useful debugging information).  This should make it
+    easier to debug problems such as the one which was reported by:
+    
+        https://bugzilla.kernel.org/show_bug.cgi?id=44731
+    
+    The only two callers of this function are ext4_handle_dirty_metadata()
+    and ocfs2_journal_dirty().  The ocfs2 function will trigger a
+    BUG_ON(), which means there will be no change in behavior.  The ext4
+    function will call ext4_error_inode() which will print the useful
+    debugging information and then handle the situation using ext4's error
+    handling mechanisms (i.e., which might mean halting the kernel or
+    remounting the file system read-only).
+    
+    Also, since both file systems already call WARN_ON(), drop the WARN_ON
+    from jbd2_journal_dirty_metadata() to avoid two stack traces from
+    being displayed.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: ocfs2-devel@oss.oracle.com
+    Acked-by: Joel Becker 
+
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index 7aa9a32573bb..b0b74e58697b 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -1290,7 +1290,10 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
+ 		 * once a transaction -bzzz
+ 		 */
+ 		jh->b_modified = 1;
+-		J_ASSERT_JH(jh, handle->h_buffer_credits > 0);
++		if (handle->h_buffer_credits <= 0) {
++			ret = -ENOSPC;
++			goto out_unlock_bh;
++		}
+ 		handle->h_buffer_credits--;
+ 	}
+ 
+@@ -1373,7 +1376,6 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
+ 	jbd2_journal_put_journal_head(jh);
+ out:
+ 	JBUFFER_TRACE(jh, "exit");
+-	WARN_ON(ret);	/* All errors are bugs, so dump the stack */
+ 	return ret;
+ }
+ 

commit ae1495b12df1897d4f42842a7aa7276d920f6290
+Author: Theodore Ts'o 
+Date:   Mon Dec 2 09:31:36 2013 -0500
+
+    ext4: call ext4_error_inode() if jbd2_journal_dirty_metadata() fails
+    
+    While it's true that errors can only happen if there is a bug in
+    jbd2_journal_dirty_metadata(), if a bug does happen, we need to halt
+    the kernel or remount the file system read-only in order to avoid
+    further data loss.  The ext4_journal_abort_handle() function doesn't
+    do any of this, and while it's likely that this call (since it doesn't
+    adjust refcounts) will likely result in the file system eventually
+    deadlocking since the current transaction will never be able to close,
+    it's much cleaner to call let ext4's error handling system deal with
+    this situation.
+    
+    There's a separate bug here which is that if certain jbd2 errors
+    errors occur and file system is mounted errors=continue, the file
+    system will probably eventually end grind to a halt as described
+    above.  But things have been this way in a long time, and usually when
+    we have these sorts of errors it's pretty much a disaster --- and
+    that's why the jbd2 layer aggressively retries memory allocations,
+    which is the most likely cause of these jbd2 errors.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Jan Kara 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
+index 17ac112ab101..3fe29de832c8 100644
+--- a/fs/ext4/ext4_jbd2.c
++++ b/fs/ext4/ext4_jbd2.c
+@@ -259,6 +259,15 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
+ 		if (WARN_ON_ONCE(err)) {
+ 			ext4_journal_abort_handle(where, line, __func__, bh,
+ 						  handle, err);
++			ext4_error_inode(inode, where, line,
++					 bh->b_blocknr,
++					 "journal_dirty_metadata failed: "
++					 "handle type %u started at line %u, "
++					 "credits %u/%u, errcode %d",
++					 handle->h_type,
++					 handle->h_line_no,
++					 handle->h_requested_credits,
++					 handle->h_buffer_credits, err);
+ 		}
+ 	} else {
+ 		if (inode)

commit dd1f723bf56bd96efc9d90e9e60dc511c79de48f
+Author: Theodore Ts'o 
+Date:   Fri Nov 8 00:14:53 2013 -0500
+
+    ext4: use prandom_u32() instead of get_random_bytes()
+    
+    Many of the uses of get_random_bytes() do not actually need
+    cryptographically secure random numbers.  Replace those uses with a
+    call to prandom_u32(), which is faster and which doesn't consume
+    entropy from the /dev/random driver.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 137193ff389b..0ee59a6644e2 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -432,7 +432,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
+ 			ext4fs_dirhash(qstr->name, qstr->len, &hinfo);
+ 			grp = hinfo.hash;
+ 		} else
+-			get_random_bytes(&grp, sizeof(grp));
++			grp = prandom_u32();
+ 		parent_group = (unsigned)grp % ngroups;
+ 		for (i = 0; i < ngroups; i++) {
+ 			g = (parent_group + i) % ngroups;
+diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c
+index 214461e42a05..04434ad3e8e0 100644
+--- a/fs/ext4/mmp.c
++++ b/fs/ext4/mmp.c
+@@ -259,7 +259,7 @@ static unsigned int mmp_new_seq(void)
+ 	u32 new_seq;
+ 
+ 	do {
+-		get_random_bytes(&new_seq, sizeof(u32));
++		new_seq = prandom_u32();
+ 	} while (new_seq > EXT4_MMP_SEQ_MAX);
+ 
+ 	return new_seq;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index d3a857bfae47..c977f4e4e63b 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3068,7 +3068,6 @@ static struct ext4_li_request *ext4_li_request_new(struct super_block *sb,
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	struct ext4_li_request *elr;
+-	unsigned long rnd;
+ 
+ 	elr = kzalloc(sizeof(*elr), GFP_KERNEL);
+ 	if (!elr)
+@@ -3083,10 +3082,8 @@ static struct ext4_li_request *ext4_li_request_new(struct super_block *sb,
+ 	 * spread the inode table initialization requests
+ 	 * better.
+ 	 */
+-	get_random_bytes(&rnd, sizeof(rnd));
+-	elr->lr_next_sched = jiffies + (unsigned long)rnd %
+-			     (EXT4_DEF_LI_MAX_START_DELAY * HZ);
+-
++	elr->lr_next_sched = jiffies + (prandom_u32() %
++				(EXT4_DEF_LI_MAX_START_DELAY * HZ));
+ 	return elr;
+ }
+ 

commit 392a546dc8368d1745f9891ef3f8f7c380de8650
+Author: Theodore Ts'o 
+Date:   Sun Nov 3 18:24:08 2013 -0500
+
+    random: add debugging code to detect early use of get_random_bytes()
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 0894d86253fd..cdf4cfb2da4d 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -280,6 +280,8 @@
+ #define SEC_XFER_SIZE		512
+ #define EXTRACT_SIZE		10
+ 
++#define DEBUG_RANDOM_BOOT 0
++
+ #define LONGS(x) (((x) + sizeof(unsigned long) - 1)/sizeof(unsigned long))
+ 
+ /*
+@@ -1177,6 +1179,13 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
+  */
+ void get_random_bytes(void *buf, int nbytes)
+ {
++#if DEBUG_RANDOM_BOOT > 0
++	if (unlikely(nonblocking_pool.initialized == 0))
++		printk(KERN_NOTICE "random: %pF get_random_bytes called "
++		       "with %d bits of entropy available\n",
++		       (void *) _RET_IP_,
++		       nonblocking_pool.entropy_total);
++#endif
+ 	trace_get_random_bytes(nbytes, _RET_IP_);
+ 	extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0);
+ }

commit 644008df899ec252e78db28c1b6d6b86779aada8
+Author: Theodore Ts'o 
+Date:   Sun Nov 3 16:40:53 2013 -0500
+
+    random: initialize the last_time field in struct timer_rand_state
+    
+    Since we initialize jiffies to wrap five minutes before boot (see
+    INITIAL_JIFFIES defined in include/linux/jiffies.h) it's important to
+    make sure the last_time field is initialized to INITIAL_JIFFIES.
+    Otherwise, the entropy estimator will overestimate the amount of
+    entropy resulting from the first call to add_timer_randomness(),
+    generally by about 8 bits.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index a38d97a21455..0894d86253fd 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -724,6 +724,8 @@ struct timer_rand_state {
+ 	unsigned dont_count_entropy:1;
+ };
+ 
++#define INIT_TIMER_RAND_STATE { INITIAL_JIFFIES, };
++
+ /*
+  * Add device- or boot-specific data to the input and nonblocking
+  * pools to help initialize them to unique values.
+@@ -750,7 +752,7 @@ void add_device_randomness(const void *buf, unsigned int size)
+ }
+ EXPORT_SYMBOL(add_device_randomness);
+ 
+-static struct timer_rand_state input_timer_state;
++static struct timer_rand_state input_timer_state = INIT_TIMER_RAND_STATE;
+ 
+ /*
+  * This function adds entropy to the entropy "pool" by using timing
+@@ -1267,8 +1269,10 @@ void rand_initialize_disk(struct gendisk *disk)
+ 	 * source.
+ 	 */
+ 	state = kzalloc(sizeof(struct timer_rand_state), GFP_KERNEL);
+-	if (state)
++	if (state) {
++		state->last_time = INITIAL_JIFFIES;
+ 		disk->random = state;
++	}
+ }
+ #endif
+ 

commit ae9ecd92ddabc250817baa7eb401df3cfbd4c2da
+Author: Theodore Ts'o 
+Date:   Sun Nov 3 07:56:17 2013 -0500
+
+    random: don't zap entropy count in rand_initialize()
+    
+    The rand_initialize() function was being run fairly late in the kernel
+    boot sequence.  This was unfortunate, since it zero'ed the entropy
+    counters, thus throwing away credit that was accumulated earlier in
+    the boot sequence, and it also meant that initcall functions run
+    before rand_initialize were using a minimally initialized pool.
+    
+    To fix this, fix init_std_data() to no longer zap the entropy counter;
+    it wasn't necessary, and move rand_initialize() to be an early
+    initcall.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index a19a7a63ec35..a38d97a21455 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -1228,14 +1228,11 @@ static void init_std_data(struct entropy_store *r)
+ 	ktime_t now = ktime_get_real();
+ 	unsigned long rv;
+ 
+-	r->entropy_count = 0;
+-	r->entropy_total = 0;
+-	r->last_data_init = 0;
+ 	r->last_pulled = jiffies;
+ 	mix_pool_bytes(r, &now, sizeof(now), NULL);
+ 	for (i = r->poolinfo->poolbytes; i > 0; i -= sizeof(rv)) {
+ 		if (!arch_get_random_long(&rv))
+-			break;
++			rv = random_get_entropy();
+ 		mix_pool_bytes(r, &rv, sizeof(rv), NULL);
+ 	}
+ 	mix_pool_bytes(r, utsname(), sizeof(*(utsname())), NULL);
+@@ -1258,7 +1255,7 @@ static int rand_initialize(void)
+ 	init_std_data(&nonblocking_pool);
+ 	return 0;
+ }
+-module_init(rand_initialize);
++early_initcall(rand_initialize);
+ 
+ #ifdef CONFIG_BLOCK
+ void rand_initialize_disk(struct gendisk *disk)
+@@ -1433,10 +1430,15 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+ 		return 0;
+ 	case RNDZAPENTCNT:
+ 	case RNDCLEARPOOL:
+-		/* Clear the entropy pool counters. */
++		/*
++		 * Clear the entropy pool counters. We no longer clear
++		 * the entropy pool, as that's silly.
++		 */
+ 		if (!capable(CAP_SYS_ADMIN))
+ 			return -EPERM;
+-		rand_initialize();
++		input_pool.entropy_count = 0;
++		nonblocking_pool.entropy_count = 0;
++		blocking_pool.entropy_count = 0;
+ 		return 0;
+ 	default:
+ 		return -EINVAL;

commit 301f0595c0e788edacc3521c4caa90b4e56ffee1
+Author: Theodore Ts'o 
+Date:   Sun Nov 3 06:54:51 2013 -0500
+
+    random: printk notifications for urandom pool initialization
+    
+    Print a notification to the console when the nonblocking pool is
+    initialized.  Also printk a warning when a process tries reading from
+    /dev/urandom before it is fully initialized.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 62923138e77a..a19a7a63ec35 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -655,6 +655,9 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
+ 	r->entropy_total += nbits;
+ 	if (!r->initialized && nbits > 0) {
+ 		if (r->entropy_total > 128) {
++			if (r == &nonblocking_pool)
++				pr_notice("random: %s pool is initialized\n",
++					  r->name);
+ 			r->initialized = 1;
+ 			r->entropy_total = 0;
+ 		}
+@@ -1327,7 +1330,14 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+ static ssize_t
+ urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+ {
+-	int ret = extract_entropy_user(&nonblocking_pool, buf, nbytes);
++	int ret;
++
++	if (unlikely(nonblocking_pool.initialized == 0))
++		printk_once(KERN_NOTICE "random: %s urandom read "
++			    "with %d bits of entropy available\n",
++			    current->comm, nonblocking_pool.entropy_total);
++
++	ret = extract_entropy_user(&nonblocking_pool, buf, nbytes);
+ 
+ 	trace_urandom_read(8 * nbytes, ENTROPY_BITS(&nonblocking_pool),
+ 			   ENTROPY_BITS(&input_pool));

commit 40db23e5337d99fda05ee6cd18034b516f8f123d
+Author: Theodore Ts'o 
+Date:   Sun Nov 3 00:15:05 2013 -0400
+
+    random: make add_timer_randomness() fill the nonblocking pool first
+    
+    Change add_timer_randomness() so that it directs incoming entropy to
+    the nonblocking pool first if it hasn't been fully initialized yet.
+    This matches the strategy we use in add_interrupt_randomness(), which
+    allows us to push the randomness where we need it the most during when
+    the system is first booting up, so that get_random_bytes() and
+    /dev/urandom become safe to use as soon as possible.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index f126bd2f69fe..62923138e77a 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -761,6 +761,7 @@ static struct timer_rand_state input_timer_state;
+  */
+ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
+ {
++	struct entropy_store	*r;
+ 	struct {
+ 		long jiffies;
+ 		unsigned cycles;
+@@ -773,7 +774,8 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
+ 	sample.jiffies = jiffies;
+ 	sample.cycles = random_get_entropy();
+ 	sample.num = num;
+-	mix_pool_bytes(&input_pool, &sample, sizeof(sample), NULL);
++	r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
++	mix_pool_bytes(r, &sample, sizeof(sample), NULL);
+ 
+ 	/*
+ 	 * Calculate number of bits of randomness we probably added.
+@@ -807,8 +809,7 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
+ 		 * Round down by 1 bit on general principles,
+ 		 * and limit entropy entimate to 12 bits.
+ 		 */
+-		credit_entropy_bits(&input_pool,
+-				    min_t(int, fls(delta>>1), 11));
++		credit_entropy_bits(r, min_t(int, fls(delta>>1), 11));
+ 	}
+ 	preempt_enable();
+ }

commit dcb9917ba041866686fe152850364826c4622a36
+Author: Theodore Ts'o 
+Date:   Thu Oct 31 23:00:24 2013 -0400
+
+    ext4: avoid bh leak in retry path of ext4_expand_extra_isize_ea()
+    
+    Reported-by: Dave Jones 
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 03e9bebba198..1423c4816a47 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -1352,6 +1352,7 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
+ 					new_extra_isize = s_min_extra_isize;
+ 					kfree(is); is = NULL;
+ 					kfree(bs); bs = NULL;
++					brelse(bh);
+ 					goto retry;
+ 				}
+ 				error = -1;

commit efbed4dc5857f845d787e406ce85097d1ccc5c4f
+Author: Theodore Ts'o 
+Date:   Thu Oct 17 21:11:01 2013 -0400
+
+    ext4: add ratelimiting to ext4 messages
+    
+    In the case of a storage device that suddenly disappears, or in the
+    case of significant file system corruption, this can result in a huge
+    flood of messages being sent to the console.  This can overflow the
+    file system containing /var/log/messages, or if a serial console is
+    configured, this can slow down the system so much that a hardware
+    watchdog can end up triggering forcing a system reboot.
+    
+    Google-Bug-Id: 7258357
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index af815ea9d7cc..65485ab7a889 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -29,6 +29,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #ifdef __KERNEL__
+ #include 
+@@ -1314,6 +1315,11 @@ struct ext4_sb_info {
+ 	unsigned long s_es_last_sorted;
+ 	struct percpu_counter s_extent_cache_cnt;
+ 	spinlock_t s_es_lru_lock ____cacheline_aligned_in_smp;
++
++	/* Ratelimit ext4 messages. */
++	struct ratelimit_state s_err_ratelimit_state;
++	struct ratelimit_state s_warning_ratelimit_state;
++	struct ratelimit_state s_msg_ratelimit_state;
+ };
+ 
+ static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb)
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 2c2e6cbc6bed..d3a857bfae47 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -411,20 +411,26 @@ static void ext4_handle_error(struct super_block *sb)
+ 			sb->s_id);
+ }
+ 
++#define ext4_error_ratelimit(sb)					\
++		___ratelimit(&(EXT4_SB(sb)->s_err_ratelimit_state),	\
++			     "EXT4-fs error")
++
+ void __ext4_error(struct super_block *sb, const char *function,
+ 		  unsigned int line, const char *fmt, ...)
+ {
+ 	struct va_format vaf;
+ 	va_list args;
+ 
+-	va_start(args, fmt);
+-	vaf.fmt = fmt;
+-	vaf.va = &args;
+-	printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: comm %s: %pV\n",
+-	       sb->s_id, function, line, current->comm, &vaf);
+-	va_end(args);
++	if (ext4_error_ratelimit(sb)) {
++		va_start(args, fmt);
++		vaf.fmt = fmt;
++		vaf.va = &args;
++		printk(KERN_CRIT
++		       "EXT4-fs error (device %s): %s:%d: comm %s: %pV\n",
++		       sb->s_id, function, line, current->comm, &vaf);
++		va_end(args);
++	}
+ 	save_error_info(sb, function, line);
+-
+ 	ext4_handle_error(sb);
+ }
+ 
+@@ -438,22 +444,23 @@ void __ext4_error_inode(struct inode *inode, const char *function,
+ 
+ 	es->s_last_error_ino = cpu_to_le32(inode->i_ino);
+ 	es->s_last_error_block = cpu_to_le64(block);
++	if (ext4_error_ratelimit(inode->i_sb)) {
++		va_start(args, fmt);
++		vaf.fmt = fmt;
++		vaf.va = &args;
++		if (block)
++			printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: "
++			       "inode #%lu: block %llu: comm %s: %pV\n",
++			       inode->i_sb->s_id, function, line, inode->i_ino,
++			       block, current->comm, &vaf);
++		else
++			printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: "
++			       "inode #%lu: comm %s: %pV\n",
++			       inode->i_sb->s_id, function, line, inode->i_ino,
++			       current->comm, &vaf);
++		va_end(args);
++	}
+ 	save_error_info(inode->i_sb, function, line);
+-	va_start(args, fmt);
+-	vaf.fmt = fmt;
+-	vaf.va = &args;
+-	if (block)
+-		printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: "
+-		       "inode #%lu: block %llu: comm %s: %pV\n",
+-		       inode->i_sb->s_id, function, line, inode->i_ino,
+-		       block, current->comm, &vaf);
+-	else
+-		printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: "
+-		       "inode #%lu: comm %s: %pV\n",
+-		       inode->i_sb->s_id, function, line, inode->i_ino,
+-		       current->comm, &vaf);
+-	va_end(args);
+-
+ 	ext4_handle_error(inode->i_sb);
+ }
+ 
+@@ -469,27 +476,28 @@ void __ext4_error_file(struct file *file, const char *function,
+ 
+ 	es = EXT4_SB(inode->i_sb)->s_es;
+ 	es->s_last_error_ino = cpu_to_le32(inode->i_ino);
++	if (ext4_error_ratelimit(inode->i_sb)) {
++		path = d_path(&(file->f_path), pathname, sizeof(pathname));
++		if (IS_ERR(path))
++			path = "(unknown)";
++		va_start(args, fmt);
++		vaf.fmt = fmt;
++		vaf.va = &args;
++		if (block)
++			printk(KERN_CRIT
++			       "EXT4-fs error (device %s): %s:%d: inode #%lu: "
++			       "block %llu: comm %s: path %s: %pV\n",
++			       inode->i_sb->s_id, function, line, inode->i_ino,
++			       block, current->comm, path, &vaf);
++		else
++			printk(KERN_CRIT
++			       "EXT4-fs error (device %s): %s:%d: inode #%lu: "
++			       "comm %s: path %s: %pV\n",
++			       inode->i_sb->s_id, function, line, inode->i_ino,
++			       current->comm, path, &vaf);
++		va_end(args);
++	}
+ 	save_error_info(inode->i_sb, function, line);
+-	path = d_path(&(file->f_path), pathname, sizeof(pathname));
+-	if (IS_ERR(path))
+-		path = "(unknown)";
+-	va_start(args, fmt);
+-	vaf.fmt = fmt;
+-	vaf.va = &args;
+-	if (block)
+-		printk(KERN_CRIT
+-		       "EXT4-fs error (device %s): %s:%d: inode #%lu: "
+-		       "block %llu: comm %s: path %s: %pV\n",
+-		       inode->i_sb->s_id, function, line, inode->i_ino,
+-		       block, current->comm, path, &vaf);
+-	else
+-		printk(KERN_CRIT
+-		       "EXT4-fs error (device %s): %s:%d: inode #%lu: "
+-		       "comm %s: path %s: %pV\n",
+-		       inode->i_sb->s_id, function, line, inode->i_ino,
+-		       current->comm, path, &vaf);
+-	va_end(args);
+-
+ 	ext4_handle_error(inode->i_sb);
+ }
+ 
+@@ -543,11 +551,13 @@ void __ext4_std_error(struct super_block *sb, const char *function,
+ 	    (sb->s_flags & MS_RDONLY))
+ 		return;
+ 
+-	errstr = ext4_decode_error(sb, errno, nbuf);
+-	printk(KERN_CRIT "EXT4-fs error (device %s) in %s:%d: %s\n",
+-	       sb->s_id, function, line, errstr);
+-	save_error_info(sb, function, line);
++	if (ext4_error_ratelimit(sb)) {
++		errstr = ext4_decode_error(sb, errno, nbuf);
++		printk(KERN_CRIT "EXT4-fs error (device %s) in %s:%d: %s\n",
++		       sb->s_id, function, line, errstr);
++	}
+ 
++	save_error_info(sb, function, line);
+ 	ext4_handle_error(sb);
+ }
+ 
+@@ -597,6 +607,9 @@ void __ext4_msg(struct super_block *sb,
+ 	struct va_format vaf;
+ 	va_list args;
+ 
++	if (!___ratelimit(&(EXT4_SB(sb)->s_msg_ratelimit_state), "EXT4-fs"))
++		return;
++
+ 	va_start(args, fmt);
+ 	vaf.fmt = fmt;
+ 	vaf.va = &args;
+@@ -610,6 +623,10 @@ void __ext4_warning(struct super_block *sb, const char *function,
+ 	struct va_format vaf;
+ 	va_list args;
+ 
++	if (!___ratelimit(&(EXT4_SB(sb)->s_warning_ratelimit_state),
++			  "EXT4-fs warning"))
++		return;
++
+ 	va_start(args, fmt);
+ 	vaf.fmt = fmt;
+ 	vaf.va = &args;
+@@ -633,18 +650,20 @@ __acquires(bitlock)
+ 	es->s_last_error_block = cpu_to_le64(block);
+ 	__save_error_info(sb, function, line);
+ 
+-	va_start(args, fmt);
+-
+-	vaf.fmt = fmt;
+-	vaf.va = &args;
+-	printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: group %u, ",
+-	       sb->s_id, function, line, grp);
+-	if (ino)
+-		printk(KERN_CONT "inode %lu: ", ino);
+-	if (block)
+-		printk(KERN_CONT "block %llu:", (unsigned long long) block);
+-	printk(KERN_CONT "%pV\n", &vaf);
+-	va_end(args);
++	if (ext4_error_ratelimit(sb)) {
++		va_start(args, fmt);
++		vaf.fmt = fmt;
++		vaf.va = &args;
++		printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: group %u, ",
++		       sb->s_id, function, line, grp);
++		if (ino)
++			printk(KERN_CONT "inode %lu: ", ino);
++		if (block)
++			printk(KERN_CONT "block %llu:",
++			       (unsigned long long) block);
++		printk(KERN_CONT "%pV\n", &vaf);
++		va_end(args);
++	}
+ 
+ 	if (test_opt(sb, ERRORS_CONT)) {
+ 		ext4_commit_super(sb, 0);
+@@ -2606,6 +2625,12 @@ EXT4_RW_ATTR_SBI_UI(mb_group_prealloc, s_mb_group_prealloc);
+ EXT4_DEPRECATED_ATTR(max_writeback_mb_bump, 128);
+ EXT4_RW_ATTR_SBI_UI(extent_max_zeroout_kb, s_extent_max_zeroout_kb);
+ EXT4_ATTR(trigger_fs_error, 0200, NULL, trigger_test_error);
++EXT4_RW_ATTR_SBI_UI(err_ratelimit_interval_ms, s_err_ratelimit_state.interval);
++EXT4_RW_ATTR_SBI_UI(err_ratelimit_burst, s_err_ratelimit_state.burst);
++EXT4_RW_ATTR_SBI_UI(warning_ratelimit_interval_ms, s_warning_ratelimit_state.interval);
++EXT4_RW_ATTR_SBI_UI(warning_ratelimit_burst, s_warning_ratelimit_state.burst);
++EXT4_RW_ATTR_SBI_UI(msg_ratelimit_interval_ms, s_msg_ratelimit_state.interval);
++EXT4_RW_ATTR_SBI_UI(msg_ratelimit_burst, s_msg_ratelimit_state.burst);
+ 
+ static struct attribute *ext4_attrs[] = {
+ 	ATTR_LIST(delayed_allocation_blocks),
+@@ -2623,6 +2648,12 @@ static struct attribute *ext4_attrs[] = {
+ 	ATTR_LIST(max_writeback_mb_bump),
+ 	ATTR_LIST(extent_max_zeroout_kb),
+ 	ATTR_LIST(trigger_fs_error),
++	ATTR_LIST(err_ratelimit_interval_ms),
++	ATTR_LIST(err_ratelimit_burst),
++	ATTR_LIST(warning_ratelimit_interval_ms),
++	ATTR_LIST(warning_ratelimit_burst),
++	ATTR_LIST(msg_ratelimit_interval_ms),
++	ATTR_LIST(msg_ratelimit_burst),
+ 	NULL,
+ };
+ 
+@@ -4118,6 +4149,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	if (es->s_error_count)
+ 		mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */
+ 
++	/* Enable message ratelimiting. Default is 10 messages per 5 secs. */
++	ratelimit_state_init(&sbi->s_err_ratelimit_state, 5 * HZ, 10);
++	ratelimit_state_init(&sbi->s_warning_ratelimit_state, 5 * HZ, 10);
++	ratelimit_state_init(&sbi->s_msg_ratelimit_state, 5 * HZ, 10);
++
+ 	kfree(orig_data);
+ 	return 0;
+ 

commit f80bbd8b92987f55f26691cd53785c4a54622eb0
+Author: Theodore Ts'o 
+Date:   Thu Oct 3 12:02:37 2013 -0400
+
+    random: convert DEBUG_ENT to tracepoints
+    
+    Instead of using the random driver's ad-hoc DEBUG_ENT() mechanism, use
+    tracepoints instead.  This allows for a much more fine-grained control
+    of which debugging mechanism which a developer might need, and unifies
+    the debugging messages with all of the existing tracepoints.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 84c576ec20e9..f126bd2f69fe 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -404,17 +404,6 @@ static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
+ static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
+ static struct fasync_struct *fasync;
+ 
+-static bool debug;
+-module_param(debug, bool, 0644);
+-#define DEBUG_ENT(fmt, arg...) do { \
+-	if (debug) \
+-		printk(KERN_DEBUG "random %04d %04d %04d: " \
+-		fmt,\
+-		input_pool.entropy_count,\
+-		blocking_pool.entropy_count,\
+-		nonblocking_pool.entropy_count,\
+-		## arg); } while (0)
+-
+ /**********************************************************************
+  *
+  * OS independent entropy store.   Here are the functions which handle
+@@ -612,7 +601,6 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
+ 	if (!nbits)
+ 		return;
+ 
+-	DEBUG_ENT("added %d entropy credits to %s\n", nbits, r->name);
+ retry:
+ 	entropy_count = orig = ACCESS_ONCE(r->entropy_count);
+ 	if (nfrac < 0) {
+@@ -655,7 +643,9 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
+ 	}
+ 
+ 	if (entropy_count < 0) {
+-		DEBUG_ENT("negative entropy/overflow\n");
++		pr_warn("random: negative entropy/overflow: pool %s count %d\n",
++			r->name, entropy_count);
++		WARN_ON(1);
+ 		entropy_count = 0;
+ 	} else if (entropy_count > pool_size)
+ 		entropy_count = pool_size;
+@@ -832,10 +822,10 @@ void add_input_randomness(unsigned int type, unsigned int code,
+ 	if (value == last_value)
+ 		return;
+ 
+-	DEBUG_ENT("input event\n");
+ 	last_value = value;
+ 	add_timer_randomness(&input_timer_state,
+ 			     (type << 4) ^ code ^ (code >> 4) ^ value);
++	trace_add_input_randomness(ENTROPY_BITS(&input_pool));
+ }
+ EXPORT_SYMBOL_GPL(add_input_randomness);
+ 
+@@ -890,10 +880,8 @@ void add_disk_randomness(struct gendisk *disk)
+ 	if (!disk || !disk->random)
+ 		return;
+ 	/* first major is 1, so we get >= 0x200 here */
+-	DEBUG_ENT("disk event %d:%d\n",
+-		  MAJOR(disk_devt(disk)), MINOR(disk_devt(disk)));
+-
+ 	add_timer_randomness(disk->random, 0x100 + disk_devt(disk));
++	trace_add_disk_randomness(disk_devt(disk), ENTROPY_BITS(&input_pool));
+ }
+ #endif
+ 
+@@ -941,10 +929,8 @@ static void _xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
+ 	/* but never more than the buffer size */
+ 	bytes = min_t(int, bytes, sizeof(tmp));
+ 
+-	DEBUG_ENT("going to reseed %s with %d bits (%zu of %d requested)\n",
+-		  r->name, bytes * 8, nbytes * 8,
+-		  r->entropy_count >> ENTROPY_SHIFT);
+-
++	trace_xfer_secondary_pool(r->name, bytes * 8, nbytes * 8,
++				  ENTROPY_BITS(r), ENTROPY_BITS(r->pull));
+ 	bytes = extract_entropy(r->pull, tmp, bytes,
+ 				random_read_wakeup_thresh / 8, rsvd);
+ 	mix_pool_bytes(r, tmp, bytes, NULL);
+@@ -992,8 +978,6 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
+ 	spin_lock_irqsave(&r->lock, flags);
+ 
+ 	BUG_ON(r->entropy_count > r->poolinfo->poolfracbits);
+-	DEBUG_ENT("trying to extract %zu bits from %s\n",
+-		  nbytes * 8, r->name);
+ 
+ 	/* Can we pull enough? */
+ retry:
+@@ -1019,12 +1003,9 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
+ 		    < random_write_wakeup_thresh)
+ 			wakeup_write = 1;
+ 	}
+-
+-	DEBUG_ENT("debiting %zu entropy credits from %s%s\n",
+-		  ibytes * 8, r->name, r->limit ? "" : " (unlimited)");
+-
+ 	spin_unlock_irqrestore(&r->lock, flags);
+ 
++	trace_debit_entropy(r->name, 8 * ibytes);
+ 	if (wakeup_write) {
+ 		wake_up_interruptible(&random_write_wait);
+ 		kill_fasync(&fasync, SIGIO, POLL_OUT);
+@@ -1303,8 +1284,6 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+ 		if (n > SEC_XFER_SIZE)
+ 			n = SEC_XFER_SIZE;
+ 
+-		DEBUG_ENT("reading %zu bits\n", n*8);
+-
+ 		n = extract_entropy_user(&blocking_pool, buf, n);
+ 
+ 		if (n < 0) {
+@@ -1312,8 +1291,9 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+ 			break;
+ 		}
+ 
+-		DEBUG_ENT("read got %zd bits (%zd still needed)\n",
+-			  n*8, (nbytes-n)*8);
++		trace_random_read(n*8, (nbytes-n)*8,
++				  ENTROPY_BITS(&blocking_pool),
++				  ENTROPY_BITS(&input_pool));
+ 
+ 		if (n == 0) {
+ 			if (file->f_flags & O_NONBLOCK) {
+@@ -1321,14 +1301,10 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+ 				break;
+ 			}
+ 
+-			DEBUG_ENT("sleeping?\n");
+-
+ 			wait_event_interruptible(random_read_wait,
+ 				ENTROPY_BITS(&input_pool) >=
+ 				random_read_wakeup_thresh);
+ 
+-			DEBUG_ENT("awake\n");
+-
+ 			if (signal_pending(current)) {
+ 				retval = -ERESTARTSYS;
+ 				break;
+@@ -1350,7 +1326,11 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+ static ssize_t
+ urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+ {
+-	return extract_entropy_user(&nonblocking_pool, buf, nbytes);
++	int ret = extract_entropy_user(&nonblocking_pool, buf, nbytes);
++
++	trace_urandom_read(8 * nbytes, ENTROPY_BITS(&nonblocking_pool),
++			   ENTROPY_BITS(&input_pool));
++	return ret;
+ }
+ 
+ static unsigned int
+diff --git a/include/trace/events/random.h b/include/trace/events/random.h
+index 527b5dc1b416..805af6db41cc 100644
+--- a/include/trace/events/random.h
++++ b/include/trace/events/random.h
+@@ -109,6 +109,89 @@ TRACE_EVENT(push_to_pool,
+ 		  __entry->input_bits)
+ );
+ 
++TRACE_EVENT(debit_entropy,
++	TP_PROTO(const char *pool_name, int debit_bits),
++
++	TP_ARGS(pool_name, debit_bits),
++
++	TP_STRUCT__entry(
++		__field( const char *,	pool_name		)
++		__field(	  int,	debit_bits		)
++	),
++
++	TP_fast_assign(
++		__entry->pool_name	= pool_name;
++		__entry->debit_bits	= debit_bits;
++	),
++
++	TP_printk("%s: debit_bits %d", __entry->pool_name,
++		  __entry->debit_bits)
++);
++
++TRACE_EVENT(add_input_randomness,
++	TP_PROTO(int input_bits),
++
++	TP_ARGS(input_bits),
++
++	TP_STRUCT__entry(
++		__field(	  int,	input_bits		)
++	),
++
++	TP_fast_assign(
++		__entry->input_bits	= input_bits;
++	),
++
++	TP_printk("input_pool_bits %d", __entry->input_bits)
++);
++
++TRACE_EVENT(add_disk_randomness,
++	TP_PROTO(dev_t dev, int input_bits),
++
++	TP_ARGS(dev, input_bits),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	  int,	input_bits		)
++	),
++
++	TP_fast_assign(
++		__entry->dev		= dev;
++		__entry->input_bits	= input_bits;
++	),
++
++	TP_printk("dev %d,%d input_pool_bits %d", MAJOR(__entry->dev),
++		  MINOR(__entry->dev), __entry->input_bits)
++);
++
++TRACE_EVENT(xfer_secondary_pool,
++	TP_PROTO(const char *pool_name, int xfer_bits, int request_bits,
++		 int pool_entropy, int input_entropy),
++
++	TP_ARGS(pool_name, xfer_bits, request_bits, pool_entropy,
++		input_entropy),
++
++	TP_STRUCT__entry(
++		__field( const char *,	pool_name		)
++		__field(	  int,	xfer_bits		)
++		__field(	  int,	request_bits		)
++		__field(	  int,	pool_entropy		)
++		__field(	  int,	input_entropy		)
++	),
++
++	TP_fast_assign(
++		__entry->pool_name	= pool_name;
++		__entry->xfer_bits	= xfer_bits;
++		__entry->request_bits	= request_bits;
++		__entry->pool_entropy	= pool_entropy;
++		__entry->input_entropy	= input_entropy;
++	),
++
++	TP_printk("pool %s xfer_bits %d request_bits %d pool_entropy %d "
++		  "input_entropy %d", __entry->pool_name, __entry->xfer_bits,
++		  __entry->request_bits, __entry->pool_entropy,
++		  __entry->input_entropy)
++);
++
+ DECLARE_EVENT_CLASS(random__get_random_bytes,
+ 	TP_PROTO(int nbytes, unsigned long IP),
+ 
+@@ -179,7 +262,52 @@ DEFINE_EVENT(random__extract_entropy, extract_entropy_user,
+ 	TP_ARGS(pool_name, nbytes, entropy_count, IP)
+ );
+ 
++TRACE_EVENT(random_read,
++	TP_PROTO(int got_bits, int need_bits, int pool_left, int input_left),
+ 
++	TP_ARGS(got_bits, need_bits, pool_left, input_left),
++
++	TP_STRUCT__entry(
++		__field(	  int,	got_bits		)
++		__field(	  int,	need_bits		)
++		__field(	  int,	pool_left		)
++		__field(	  int,	input_left		)
++	),
++
++	TP_fast_assign(
++		__entry->got_bits	= got_bits;
++		__entry->need_bits	= need_bits;
++		__entry->pool_left	= pool_left;
++		__entry->input_left	= input_left;
++	),
++
++	TP_printk("got_bits %d still_needed_bits %d "
++		  "blocking_pool_entropy_left %d input_entropy_left %d",
++		  __entry->got_bits, __entry->got_bits, __entry->pool_left,
++		  __entry->input_left)
++);
++
++TRACE_EVENT(urandom_read,
++	TP_PROTO(int got_bits, int pool_left, int input_left),
++
++	TP_ARGS(got_bits, pool_left, input_left),
++
++	TP_STRUCT__entry(
++		__field(	  int,	got_bits		)
++		__field(	  int,	pool_left		)
++		__field(	  int,	input_left		)
++	),
++
++	TP_fast_assign(
++		__entry->got_bits	= got_bits;
++		__entry->pool_left	= pool_left;
++		__entry->input_left	= input_left;
++	),
++
++	TP_printk("got_bits %d nonblocking_pool_entropy_left %d "
++		  "input_entropy_left %d", __entry->got_bits,
++		  __entry->pool_left, __entry->input_left)
++);
+ 
+ #endif /* _TRACE_RANDOM_H */
+ 

commit 6265e169cd313d6f3aad3c33d0a5b0d9624f69f5
+Author: Theodore Ts'o 
+Date:   Thu Oct 3 01:08:15 2013 -0400
+
+    random: push extra entropy to the output pools
+    
+    As the input pool gets filled, start transfering entropy to the output
+    pools until they get filled.  This allows us to use the output pools
+    to store more system entropy.  Waste not, want not....
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 6da3f250804c..84c576ec20e9 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -255,6 +255,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #ifdef CONFIG_GENERIC_HARDIRQS
+ # include 
+@@ -302,7 +303,7 @@ static int random_read_wakeup_thresh = 64;
+  * should wake up processes which are selecting or polling on write
+  * access to /dev/random.
+  */
+-static int random_write_wakeup_thresh = 128;
++static int random_write_wakeup_thresh = 28 * OUTPUT_POOL_WORDS;
+ 
+ /*
+  * The minimum number of seconds between urandom pool resending.  We
+@@ -428,6 +429,7 @@ struct entropy_store {
+ 	__u32 *pool;
+ 	const char *name;
+ 	struct entropy_store *pull;
++	struct work_struct push_work;
+ 
+ 	/* read-write data: */
+ 	unsigned long last_pulled;
+@@ -442,6 +444,7 @@ struct entropy_store {
+ 	__u8 last_data[EXTRACT_SIZE];
+ };
+ 
++static void push_to_pool(struct work_struct *work);
+ static __u32 input_pool_data[INPUT_POOL_WORDS];
+ static __u32 blocking_pool_data[OUTPUT_POOL_WORDS];
+ static __u32 nonblocking_pool_data[OUTPUT_POOL_WORDS];
+@@ -460,7 +463,9 @@ static struct entropy_store blocking_pool = {
+ 	.limit = 1,
+ 	.pull = &input_pool,
+ 	.lock = __SPIN_LOCK_UNLOCKED(blocking_pool.lock),
+-	.pool = blocking_pool_data
++	.pool = blocking_pool_data,
++	.push_work = __WORK_INITIALIZER(blocking_pool.push_work,
++					push_to_pool),
+ };
+ 
+ static struct entropy_store nonblocking_pool = {
+@@ -468,7 +473,9 @@ static struct entropy_store nonblocking_pool = {
+ 	.name = "nonblocking",
+ 	.pull = &input_pool,
+ 	.lock = __SPIN_LOCK_UNLOCKED(nonblocking_pool.lock),
+-	.pool = nonblocking_pool_data
++	.pool = nonblocking_pool_data,
++	.push_work = __WORK_INITIALIZER(nonblocking_pool.push_work,
++					push_to_pool),
+ };
+ 
+ static __u32 const twist_table[8] = {
+@@ -655,21 +662,48 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
+ 	if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
+ 		goto retry;
+ 
++	r->entropy_total += nbits;
+ 	if (!r->initialized && nbits > 0) {
+-		r->entropy_total += nbits;
+-		if (r->entropy_total > 128)
++		if (r->entropy_total > 128) {
+ 			r->initialized = 1;
++			r->entropy_total = 0;
++		}
+ 	}
+ 
+ 	trace_credit_entropy_bits(r->name, nbits,
+ 				  entropy_count >> ENTROPY_SHIFT,
+ 				  r->entropy_total, _RET_IP_);
+ 
+-	/* should we wake readers? */
+-	if (r == &input_pool &&
+-	    (entropy_count >> ENTROPY_SHIFT) >= random_read_wakeup_thresh) {
+-		wake_up_interruptible(&random_read_wait);
+-		kill_fasync(&fasync, SIGIO, POLL_IN);
++	if (r == &input_pool) {
++		int entropy_bytes = entropy_count >> ENTROPY_SHIFT;
++
++		/* should we wake readers? */
++		if (entropy_bytes >= random_read_wakeup_thresh) {
++			wake_up_interruptible(&random_read_wait);
++			kill_fasync(&fasync, SIGIO, POLL_IN);
++		}
++		/* If the input pool is getting full, send some
++		 * entropy to the two output pools, flipping back and
++		 * forth between them, until the output pools are 75%
++		 * full.
++		 */
++		if (entropy_bytes > random_write_wakeup_thresh &&
++		    r->initialized &&
++		    r->entropy_total >= 2*random_read_wakeup_thresh) {
++			static struct entropy_store *last = &blocking_pool;
++			struct entropy_store *other = &blocking_pool;
++
++			if (last == &blocking_pool)
++				other = &nonblocking_pool;
++			if (other->entropy_count <=
++			    3 * other->poolinfo->poolfracbits / 4)
++				last = other;
++			if (last->entropy_count <=
++			    3 * last->poolinfo->poolfracbits / 4) {
++				schedule_work(&last->push_work);
++				r->entropy_total = 0;
++			}
++		}
+ 	}
+ }
+ 
+@@ -877,10 +911,9 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
+  * from the primary pool to the secondary extraction pool. We make
+  * sure we pull enough for a 'catastrophic reseed'.
+  */
++static void _xfer_secondary_pool(struct entropy_store *r, size_t nbytes);
+ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
+ {
+-	__u32	tmp[OUTPUT_POOL_WORDS];
+-
+ 	if (r->limit == 0 && random_min_urandom_seed) {
+ 		unsigned long now = jiffies;
+ 
+@@ -891,26 +924,47 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
+ 	}
+ 	if (r->pull &&
+ 	    r->entropy_count < (nbytes << (ENTROPY_SHIFT + 3)) &&
+-	    r->entropy_count < r->poolinfo->poolfracbits) {
+-		/* If we're limited, always leave two wakeup worth's BITS */
+-		int rsvd = r->limit ? 0 : random_read_wakeup_thresh/4;
+-		int bytes = nbytes;
+-
+-		/* pull at least as many as BYTES as wakeup BITS */
+-		bytes = max_t(int, bytes, random_read_wakeup_thresh / 8);
+-		/* but never more than the buffer size */
+-		bytes = min_t(int, bytes, sizeof(tmp));
+-
+-		DEBUG_ENT("going to reseed %s with %d bits "
+-			  "(%zu of %d requested)\n",
+-			  r->name, bytes * 8, nbytes * 8,
+-			  r->entropy_count >> ENTROPY_SHIFT);
+-
+-		bytes = extract_entropy(r->pull, tmp, bytes,
+-					random_read_wakeup_thresh / 8, rsvd);
+-		mix_pool_bytes(r, tmp, bytes, NULL);
+-		credit_entropy_bits(r, bytes*8);
+-	}
++	    r->entropy_count < r->poolinfo->poolfracbits)
++		_xfer_secondary_pool(r, nbytes);
++}
++
++static void _xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
++{
++	__u32	tmp[OUTPUT_POOL_WORDS];
++
++	/* For /dev/random's pool, always leave two wakeup worth's BITS */
++	int rsvd = r->limit ? 0 : random_read_wakeup_thresh/4;
++	int bytes = nbytes;
++
++	/* pull at least as many as BYTES as wakeup BITS */
++	bytes = max_t(int, bytes, random_read_wakeup_thresh / 8);
++	/* but never more than the buffer size */
++	bytes = min_t(int, bytes, sizeof(tmp));
++
++	DEBUG_ENT("going to reseed %s with %d bits (%zu of %d requested)\n",
++		  r->name, bytes * 8, nbytes * 8,
++		  r->entropy_count >> ENTROPY_SHIFT);
++
++	bytes = extract_entropy(r->pull, tmp, bytes,
++				random_read_wakeup_thresh / 8, rsvd);
++	mix_pool_bytes(r, tmp, bytes, NULL);
++	credit_entropy_bits(r, bytes*8);
++}
++
++/*
++ * Used as a workqueue function so that when the input pool is getting
++ * full, we can "spill over" some entropy to the output pools.  That
++ * way the output pools can store some of the excess entropy instead
++ * of letting it go to waste.
++ */
++static void push_to_pool(struct work_struct *work)
++{
++	struct entropy_store *r = container_of(work, struct entropy_store,
++					      push_work);
++	BUG_ON(!r);
++	_xfer_secondary_pool(r, random_read_wakeup_thresh/8);
++	trace_push_to_pool(r->name, r->entropy_count >> ENTROPY_SHIFT,
++			   r->pull->entropy_count >> ENTROPY_SHIFT);
+ }
+ 
+ /*
+diff --git a/include/trace/events/random.h b/include/trace/events/random.h
+index 2ffcaec5860a..527b5dc1b416 100644
+--- a/include/trace/events/random.h
++++ b/include/trace/events/random.h
+@@ -87,6 +87,28 @@ TRACE_EVENT(credit_entropy_bits,
+ 		  (void *)__entry->IP)
+ );
+ 
++TRACE_EVENT(push_to_pool,
++	TP_PROTO(const char *pool_name, int pool_bits, int input_bits),
++
++	TP_ARGS(pool_name, pool_bits, input_bits),
++
++	TP_STRUCT__entry(
++		__field( const char *,	pool_name		)
++		__field(	  int,	pool_bits		)
++		__field(	  int,	input_bits		)
++	),
++
++	TP_fast_assign(
++		__entry->pool_name	= pool_name;
++		__entry->pool_bits	= pool_bits;
++		__entry->input_bits	= input_bits;
++	),
++
++	TP_printk("%s: pool_bits %d input_pool_bits %d",
++		  __entry->pool_name, __entry->pool_bits,
++		  __entry->input_bits)
++);
++
+ DECLARE_EVENT_CLASS(random__get_random_bytes,
+ 	TP_PROTO(int nbytes, unsigned long IP),
+ 

commit 95b709b6be49e4ff3933ef6a5b5e623de2713a71
+Author: Theodore Ts'o 
+Date:   Wed Oct 2 21:10:35 2013 -0400
+
+    random: drop trickle mode
+    
+    The add_timer_randomness() used to drop into trickle mode when entropy
+    pool was estimated to be 87.5% full.  This was important when
+    add_timer_randomness() was used to sample interrupts.  It's not used
+    for this any more --- add_interrupt_randomness() now uses fast_mix()
+    instead.  By elimitating trickle mode, it allows us to fully utilize
+    entropy provided by add_input_randomness() and add_disk_randomness()
+    even when the input pool is above the old trickle threshold of 87.5%.
+    
+    This helps to answer the criticism in [1] in their hypothetical
+    scenario where our entropy estimator was inaccurate, even though the
+    measurements in [2] seem to indicate that our entropy estimator given
+    real-life entropy collection is actually pretty good, albeit on the
+    conservative side (which was as it was designed).
+    
+    [1] http://eprint.iacr.org/2013/338.pdf
+    [2] http://eprint.iacr.org/2012/251.pdf
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 7ae7ea65da68..6da3f250804c 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -282,10 +282,8 @@
+ #define LONGS(x) (((x) + sizeof(unsigned long) - 1)/sizeof(unsigned long))
+ 
+ /*
+- * To allow fractional bits to be tracked, the following fields contain
+- * this many fractional bits:
+- *
+- * entropy_count, trickle_thresh
++ * To allow fractional bits to be tracked, the entropy_count field is
++ * denominated in units of 1/8th bits.
+  *
+  * 2*(ENTROPY_SHIFT + log2(poolbits)) must <= 31, or the multiply in
+  * credit_entropy_bits() needs to be 64 bits wide.
+@@ -313,14 +311,6 @@ static int random_write_wakeup_thresh = 128;
+  */
+ static int random_min_urandom_seed = 60;
+ 
+-/*
+- * When the input pool goes over trickle_thresh, start dropping most
+- * samples to avoid wasting CPU time and reduce lock contention.
+- */
+-static const int trickle_thresh = (INPUT_POOL_WORDS * 28) << ENTROPY_SHIFT;
+-
+-static DEFINE_PER_CPU(int, trickle_count);
+-
+ /*
+  * Originally, we used a primitive polynomial of degree .poolwords
+  * over GF(2).  The taps for various sizes are defined below.  They
+@@ -755,10 +745,6 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
+ 	long delta, delta2, delta3;
+ 
+ 	preempt_disable();
+-	/* if over the trickle threshold, use only 1 in 4096 samples */
+-	if (ENTROPY_BITS(&input_pool) > trickle_thresh &&
+-	    ((__this_cpu_inc_return(trickle_count) - 1) & 0xfff))
+-		goto out;
+ 
+ 	sample.jiffies = jiffies;
+ 	sample.cycles = random_get_entropy();
+@@ -800,7 +786,6 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
+ 		credit_entropy_bits(&input_pool,
+ 				    min_t(int, fls(delta>>1), 11));
+ 	}
+-out:
+ 	preempt_enable();
+ }
+ 

commit 6e9fa2c8a630e6d0882828012431038abce285b9
+Author: Theodore Ts'o 
+Date:   Sun Sep 22 16:04:19 2013 -0400
+
+    random: adjust the generator polynomials in the mixing function slightly
+    
+    Our mixing functions were analyzed by Lacharme, Roeck, Strubel, and
+    Videau in their paper, "The Linux Pseudorandom Number Generator
+    Revisited" (see: http://eprint.iacr.org/2012/251.pdf).
+    
+    They suggested a slight change to improve our mixing functions
+    slightly.  I also adjusted the comments to better explain what is
+    going on, and to document why the polynomials were changed.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 74eeec58e779..7ae7ea65da68 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -322,23 +322,61 @@ static const int trickle_thresh = (INPUT_POOL_WORDS * 28) << ENTROPY_SHIFT;
+ static DEFINE_PER_CPU(int, trickle_count);
+ 
+ /*
+- * A pool of size .poolwords is stirred with a primitive polynomial
+- * of degree .poolwords over GF(2).  The taps for various sizes are
+- * defined below.  They are chosen to be evenly spaced (minimum RMS
+- * distance from evenly spaced; the numbers in the comments are a
+- * scaled squared error sum) except for the last tap, which is 1 to
+- * get the twisting happening as fast as possible.
++ * Originally, we used a primitive polynomial of degree .poolwords
++ * over GF(2).  The taps for various sizes are defined below.  They
++ * were chosen to be evenly spaced except for the last tap, which is 1
++ * to get the twisting happening as fast as possible.
++ *
++ * For the purposes of better mixing, we use the CRC-32 polynomial as
++ * well to make a (modified) twisted Generalized Feedback Shift
++ * Register.  (See M. Matsumoto & Y. Kurita, 1992.  Twisted GFSR
++ * generators.  ACM Transactions on Modeling and Computer Simulation
++ * 2(3):179-194.  Also see M. Matsumoto & Y. Kurita, 1994.  Twisted
++ * GFSR generators II.  ACM Transactions on Mdeling and Computer
++ * Simulation 4:254-266)
++ *
++ * Thanks to Colin Plumb for suggesting this.
++ *
++ * The mixing operation is much less sensitive than the output hash,
++ * where we use SHA-1.  All that we want of mixing operation is that
++ * it be a good non-cryptographic hash; i.e. it not produce collisions
++ * when fed "random" data of the sort we expect to see.  As long as
++ * the pool state differs for different inputs, we have preserved the
++ * input entropy and done a good job.  The fact that an intelligent
++ * attacker can construct inputs that will produce controlled
++ * alterations to the pool's state is not important because we don't
++ * consider such inputs to contribute any randomness.  The only
++ * property we need with respect to them is that the attacker can't
++ * increase his/her knowledge of the pool's state.  Since all
++ * additions are reversible (knowing the final state and the input,
++ * you can reconstruct the initial state), if an attacker has any
++ * uncertainty about the initial state, he/she can only shuffle that
++ * uncertainty about, but never cause any collisions (which would
++ * decrease the uncertainty).
++ *
++ * Our mixing functions were analyzed by Lacharme, Roeck, Strubel, and
++ * Videau in their paper, "The Linux Pseudorandom Number Generator
++ * Revisited" (see: http://eprint.iacr.org/2012/251.pdf).  In their
++ * paper, they point out that we are not using a true Twisted GFSR,
++ * since Matsumoto & Kurita used a trinomial feedback polynomial (that
++ * is, with only three taps, instead of the six that we are using).
++ * As a result, the resulting polynomial is neither primitive nor
++ * irreducible, and hence does not have a maximal period over
++ * GF(2**32).  They suggest a slight change to the generator
++ * polynomial which improves the resulting TGFSR polynomial to be
++ * irreducible, which we have made here.
+  */
+-
+ static struct poolinfo {
+ 	int poolbitshift, poolwords, poolbytes, poolbits, poolfracbits;
+ #define S(x) ilog2(x)+5, (x), (x)*4, (x)*32, (x) << (ENTROPY_SHIFT+5)
+ 	int tap1, tap2, tap3, tap4, tap5;
+ } poolinfo_table[] = {
+-	/* x^128 + x^103 + x^76 + x^51 +x^25 + x + 1 -- 105 */
+-	{ S(128),	103,	76,	51,	25,	1 },
+-	/* x^32 + x^26 + x^20 + x^14 + x^7 + x + 1 -- 15 */
+-	{ S(32),	26,	20,	14,	7,	1 },
++	/* was: x^128 + x^103 + x^76 + x^51 +x^25 + x + 1 */
++	/* x^128 + x^104 + x^76 + x^51 +x^25 + x + 1 */
++	{ S(128),	104,	76,	51,	25,	1 },
++	/* was: x^32 + x^26 + x^20 + x^14 + x^7 + x + 1 */
++	/* x^32 + x^26 + x^19 + x^14 + x^7 + x + 1 */
++	{ S(32),	26,	19,	14,	7,	1 },
+ #if 0
+ 	/* x^2048 + x^1638 + x^1231 + x^819 + x^411 + x + 1  -- 115 */
+ 	{ S(2048),	1638,	1231,	819,	411,	1 },
+@@ -368,49 +406,6 @@ static struct poolinfo {
+ #endif
+ };
+ 
+-/*
+- * For the purposes of better mixing, we use the CRC-32 polynomial as
+- * well to make a twisted Generalized Feedback Shift Reigster
+- *
+- * (See M. Matsumoto & Y. Kurita, 1992.  Twisted GFSR generators.  ACM
+- * Transactions on Modeling and Computer Simulation 2(3):179-194.
+- * Also see M. Matsumoto & Y. Kurita, 1994.  Twisted GFSR generators
+- * II.  ACM Transactions on Mdeling and Computer Simulation 4:254-266)
+- *
+- * Thanks to Colin Plumb for suggesting this.
+- *
+- * We have not analyzed the resultant polynomial to prove it primitive;
+- * in fact it almost certainly isn't.  Nonetheless, the irreducible factors
+- * of a random large-degree polynomial over GF(2) are more than large enough
+- * that periodicity is not a concern.
+- *
+- * The input hash is much less sensitive than the output hash.  All
+- * that we want of it is that it be a good non-cryptographic hash;
+- * i.e. it not produce collisions when fed "random" data of the sort
+- * we expect to see.  As long as the pool state differs for different
+- * inputs, we have preserved the input entropy and done a good job.
+- * The fact that an intelligent attacker can construct inputs that
+- * will produce controlled alterations to the pool's state is not
+- * important because we don't consider such inputs to contribute any
+- * randomness.  The only property we need with respect to them is that
+- * the attacker can't increase his/her knowledge of the pool's state.
+- * Since all additions are reversible (knowing the final state and the
+- * input, you can reconstruct the initial state), if an attacker has
+- * any uncertainty about the initial state, he/she can only shuffle
+- * that uncertainty about, but never cause any collisions (which would
+- * decrease the uncertainty).
+- *
+- * The chosen system lets the state of the pool be (essentially) the input
+- * modulo the generator polymnomial.  Now, for random primitive polynomials,
+- * this is a universal class of hash functions, meaning that the chance
+- * of a collision is limited by the attacker's knowledge of the generator
+- * polynomail, so if it is chosen at random, an attacker can never force
+- * a collision.  Here, we use a fixed polynomial, but we *can* assume that
+- * ###--> it is unknown to the processes generating the input entropy. <-###
+- * Because of this important property, this is a good, collision-resistant
+- * hash; hash collisions will occur no more often than chance.
+- */
+-
+ /*
+  * Static global variables
+  */

commit 655b226470b229552ad95b21323864df9bd9fc74
+Author: Theodore Ts'o 
+Date:   Sun Sep 22 15:24:02 2013 -0400
+
+    random: speed up the fast_mix function by a factor of four
+    
+    By mixing the entropy in chunks of 32-bit words instead of byte by
+    byte, we can speed up the fast_mix function significantly.  Since it
+    is called on every single interrupt, on systems with a very heavy
+    interrupt load, this can make a noticeable difference.
+    
+    Also fix a compilation warning in add_interrupt_randomness() and avoid
+    xor'ing cycles and jiffies together just in case we have an
+    architecture which tries to define random_get_entropy() by returning
+    jiffies.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reported-by: Jörn Engel 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index a68b4a093272..74eeec58e779 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -584,21 +584,26 @@ struct fast_pool {
+  * collector.  It's hardcoded for an 128 bit pool and assumes that any
+  * locks that might be needed are taken by the caller.
+  */
+-static void fast_mix(struct fast_pool *f, const void *in, int nbytes)
++static void fast_mix(struct fast_pool *f, __u32 input[4])
+ {
+-	const char	*bytes = in;
+ 	__u32		w;
+-	unsigned	i = f->count;
+ 	unsigned	input_rotate = f->rotate;
+ 
+-	while (nbytes--) {
+-		w = rol32(*bytes++, input_rotate & 31) ^ f->pool[i & 3] ^
+-			f->pool[(i + 1) & 3];
+-		f->pool[i & 3] = (w >> 3) ^ twist_table[w & 7];
+-		input_rotate += (i++ & 3) ? 7 : 14;
+-	}
+-	f->count = i;
++	w = rol32(input[0], input_rotate) ^ f->pool[0] ^ f->pool[3];
++	f->pool[0] = (w >> 3) ^ twist_table[w & 7];
++	input_rotate = (input_rotate + 14) & 31;
++	w = rol32(input[1], input_rotate) ^ f->pool[1] ^ f->pool[0];
++	f->pool[1] = (w >> 3) ^ twist_table[w & 7];
++	input_rotate = (input_rotate + 7) & 31;
++	w = rol32(input[2], input_rotate) ^ f->pool[2] ^ f->pool[1];
++	f->pool[2] = (w >> 3) ^ twist_table[w & 7];
++	input_rotate = (input_rotate + 7) & 31;
++	w = rol32(input[3], input_rotate) ^ f->pool[3] ^ f->pool[2];
++	f->pool[3] = (w >> 3) ^ twist_table[w & 7];
++	input_rotate = (input_rotate + 7) & 31;
++
+ 	f->rotate = input_rotate;
++	f->count++;
+ }
+ 
+ /*
+@@ -828,20 +833,21 @@ void add_interrupt_randomness(int irq, int irq_flags)
+ 	struct fast_pool	*fast_pool = &__get_cpu_var(irq_randomness);
+ 	struct pt_regs		*regs = get_irq_regs();
+ 	unsigned long		now = jiffies;
+-	__u32			input[4], cycles = random_get_entropy();
+-
+-	input[0] = cycles ^ jiffies;
+-	input[1] = irq;
+-	if (regs) {
+-		__u64 ip = instruction_pointer(regs);
+-		input[2] = ip;
+-		input[3] = ip >> 32;
+-	}
++	cycles_t		cycles = random_get_entropy();
++	__u32			input[4], c_high, j_high;
++	__u64			ip;
++
++	c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0;
++	j_high = (sizeof(now) > 4) ? now >> 32 : 0;
++	input[0] = cycles ^ j_high ^ irq;
++	input[1] = now ^ c_high;
++	ip = regs ? instruction_pointer(regs) : _RET_IP_;
++	input[2] = ip;
++	input[3] = ip >> 32;
+ 
+-	fast_mix(fast_pool, input, sizeof(input));
++	fast_mix(fast_pool, input);
+ 
+-	if ((fast_pool->count & 1023) &&
+-	    !time_after(now, fast_pool->last + HZ))
++	if ((fast_pool->count & 63) && !time_after(now, fast_pool->last + HZ))
+ 		return;
+ 
+ 	fast_pool->last = now;

commit f5c2742c23886e707f062881c5f206c1fc704782
+Author: Theodore Ts'o 
+Date:   Sun Sep 22 15:14:32 2013 -0400
+
+    random: cap the rate which the /dev/urandom pool gets reseeded
+    
+    In order to avoid draining the input pool of its entropy at too high
+    of a rate, enforce a minimum time interval between reseedings of the
+    urandom pool.  This is set to 60 seconds by default.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index b8809d4ae186..a68b4a093272 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -306,6 +306,13 @@ static int random_read_wakeup_thresh = 64;
+  */
+ static int random_write_wakeup_thresh = 128;
+ 
++/*
++ * The minimum number of seconds between urandom pool resending.  We
++ * do this to limit the amount of entropy that can be drained from the
++ * input pool even if there are heavy demands on /dev/urandom.
++ */
++static int random_min_urandom_seed = 60;
++
+ /*
+  * When the input pool goes over trickle_thresh, start dropping most
+  * samples to avoid wasting CPU time and reduce lock contention.
+@@ -438,6 +445,7 @@ struct entropy_store {
+ 	struct entropy_store *pull;
+ 
+ 	/* read-write data: */
++	unsigned long last_pulled;
+ 	spinlock_t lock;
+ 	unsigned short add_ptr;
+ 	unsigned short input_rotate;
+@@ -887,6 +895,14 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
+ {
+ 	__u32	tmp[OUTPUT_POOL_WORDS];
+ 
++	if (r->limit == 0 && random_min_urandom_seed) {
++		unsigned long now = jiffies;
++
++		if (time_before(now,
++				r->last_pulled + random_min_urandom_seed * HZ))
++			return;
++		r->last_pulled = now;
++	}
+ 	if (r->pull &&
+ 	    r->entropy_count < (nbytes << (ENTROPY_SHIFT + 3)) &&
+ 	    r->entropy_count < r->poolinfo->poolfracbits) {
+@@ -1190,6 +1206,7 @@ static void init_std_data(struct entropy_store *r)
+ 	r->entropy_count = 0;
+ 	r->entropy_total = 0;
+ 	r->last_data_init = 0;
++	r->last_pulled = jiffies;
+ 	mix_pool_bytes(r, &now, sizeof(now), NULL);
+ 	for (i = r->poolinfo->poolbytes; i > 0; i -= sizeof(rv)) {
+ 		if (!arch_get_random_long(&rv))
+@@ -1540,6 +1557,13 @@ struct ctl_table random_table[] = {
+ 		.extra1		= &min_write_thresh,
+ 		.extra2		= &max_write_thresh,
+ 	},
++	{
++		.procname	= "urandom_min_reseed_secs",
++		.data		= &random_min_urandom_seed,
++		.maxlen		= sizeof(int),
++		.mode		= 0644,
++		.proc_handler	= proc_dointvec,
++	},
+ 	{
+ 		.procname	= "boot_id",
+ 		.data		= &sysctl_bootid,

commit c59974aea43fd292a0784dbf7b3d7347e2caf4e9
+Author: Theodore Ts'o 
+Date:   Sat Sep 21 19:42:41 2013 -0400
+
+    random: optimize the entropy_store structure
+    
+    Use smaller types to slightly shrink the size of the entropy store
+    structure.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 89eb5a8dec82..b8809d4ae186 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -436,16 +436,16 @@ struct entropy_store {
+ 	__u32 *pool;
+ 	const char *name;
+ 	struct entropy_store *pull;
+-	int limit;
+ 
+ 	/* read-write data: */
+ 	spinlock_t lock;
+-	unsigned add_ptr;
+-	unsigned input_rotate;
++	unsigned short add_ptr;
++	unsigned short input_rotate;
+ 	int entropy_count;
+ 	int entropy_total;
+ 	unsigned int initialized:1;
+-	bool last_data_init;
++	unsigned int limit:1;
++	unsigned int last_data_init:1;
+ 	__u8 last_data[EXTRACT_SIZE];
+ };
+ 
+@@ -513,7 +513,7 @@ static void _mix_pool_bytes(struct entropy_store *r, const void *in,
+ 
+ 	/* mix one byte at a time to simplify size handling and churn faster */
+ 	while (nbytes--) {
+-		w = rol32(*bytes++, input_rotate & 31);
++		w = rol32(*bytes++, input_rotate);
+ 		i = (i - 1) & wordmask;
+ 
+ 		/* XOR in the various taps */
+@@ -533,7 +533,7 @@ static void _mix_pool_bytes(struct entropy_store *r, const void *in,
+ 		 * rotation, so that successive passes spread the
+ 		 * input bits across the pool evenly.
+ 		 */
+-		input_rotate += i ? 7 : 14;
++		input_rotate = (input_rotate + (i ? 7 : 14)) & 31;
+ 	}
+ 
+ 	ACCESS_ONCE(r->input_rotate) = input_rotate;
+@@ -1049,7 +1049,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
+ 	if (fips_enabled) {
+ 		spin_lock_irqsave(&r->lock, flags);
+ 		if (!r->last_data_init) {
+-			r->last_data_init = true;
++			r->last_data_init = 1;
+ 			spin_unlock_irqrestore(&r->lock, flags);
+ 			trace_extract_entropy(r->name, EXTRACT_SIZE,
+ 					      ENTROPY_BITS(r), _RET_IP_);
+@@ -1189,7 +1189,7 @@ static void init_std_data(struct entropy_store *r)
+ 
+ 	r->entropy_count = 0;
+ 	r->entropy_total = 0;
+-	r->last_data_init = false;
++	r->last_data_init = 0;
+ 	mix_pool_bytes(r, &now, sizeof(now), NULL);
+ 	for (i = r->poolinfo->poolbytes; i > 0; i -= sizeof(rv)) {
+ 		if (!arch_get_random_long(&rv))

commit 3ef4cb2d65ee13d84140cbede8e1980c6ae49ffd
+Author: Theodore Ts'o 
+Date:   Thu Sep 12 14:27:22 2013 -0400
+
+    random: optimize spinlock use in add_device_randomness()
+    
+    The add_device_randomness() function calls mix_pool_bytes() twice for
+    the input pool and the non-blocking pool, for a total of four times.
+    By using _mix_pool_byte() and taking the spinlock in
+    add_device_randomness(), we can halve the number of times we need
+    take each pool's spinlock.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 80b58774e891..89eb5a8dec82 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -710,12 +710,18 @@ struct timer_rand_state {
+ void add_device_randomness(const void *buf, unsigned int size)
+ {
+ 	unsigned long time = random_get_entropy() ^ jiffies;
++	unsigned long flags;
+ 
+ 	trace_add_device_randomness(size, _RET_IP_);
+-	mix_pool_bytes(&input_pool, buf, size, NULL);
+-	mix_pool_bytes(&input_pool, &time, sizeof(time), NULL);
+-	mix_pool_bytes(&nonblocking_pool, buf, size, NULL);
+-	mix_pool_bytes(&nonblocking_pool, &time, sizeof(time), NULL);
++	spin_lock_irqsave(&input_pool.lock, flags);
++	_mix_pool_bytes(&input_pool, buf, size, NULL);
++	_mix_pool_bytes(&input_pool, &time, sizeof(time), NULL);
++	spin_unlock_irqrestore(&input_pool.lock, flags);
++
++	spin_lock_irqsave(&nonblocking_pool.lock, flags);
++	_mix_pool_bytes(&nonblocking_pool, buf, size, NULL);
++	_mix_pool_bytes(&nonblocking_pool, &time, sizeof(time), NULL);
++	spin_unlock_irqrestore(&nonblocking_pool.lock, flags);
+ }
+ EXPORT_SYMBOL(add_device_randomness);
+ 

commit 5910895f0e868d4f70303922ed00ccdc328b3c30
+Author: Theodore Ts'o 
+Date:   Thu Sep 12 14:10:25 2013 -0400
+
+    random: fix the tracepoint for get_random_bytes(_arch)
+    
+    Fix a problem where get_random_bytes_arch() was calling the tracepoint
+    get_random_bytes().  So add a new tracepoint for
+    get_random_bytes_arch(), and make get_random_bytes() and
+    get_random_bytes_arch() call their correct tracepoint.
+    
+    Also, add a new tracepoint for add_device_randomness()
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 867b823e7fea..80b58774e891 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -711,6 +711,7 @@ void add_device_randomness(const void *buf, unsigned int size)
+ {
+ 	unsigned long time = random_get_entropy() ^ jiffies;
+ 
++	trace_add_device_randomness(size, _RET_IP_);
+ 	mix_pool_bytes(&input_pool, buf, size, NULL);
+ 	mix_pool_bytes(&input_pool, &time, sizeof(time), NULL);
+ 	mix_pool_bytes(&nonblocking_pool, buf, size, NULL);
+@@ -1127,6 +1128,7 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
+  */
+ void get_random_bytes(void *buf, int nbytes)
+ {
++	trace_get_random_bytes(nbytes, _RET_IP_);
+ 	extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0);
+ }
+ EXPORT_SYMBOL(get_random_bytes);
+@@ -1145,7 +1147,7 @@ void get_random_bytes_arch(void *buf, int nbytes)
+ {
+ 	char *p = buf;
+ 
+-	trace_get_random_bytes(nbytes, _RET_IP_);
++	trace_get_random_bytes_arch(nbytes, _RET_IP_);
+ 	while (nbytes) {
+ 		unsigned long v;
+ 		int chunk = min(nbytes, (int)sizeof(unsigned long));
+diff --git a/include/trace/events/random.h b/include/trace/events/random.h
+index 422df19de732..2ffcaec5860a 100644
+--- a/include/trace/events/random.h
++++ b/include/trace/events/random.h
+@@ -7,6 +7,25 @@
+ #include 
+ #include 
+ 
++TRACE_EVENT(add_device_randomness,
++	TP_PROTO(int bytes, unsigned long IP),
++
++	TP_ARGS(bytes, IP),
++
++	TP_STRUCT__entry(
++		__field(	  int,	bytes			)
++		__field(unsigned long,	IP			)
++	),
++
++	TP_fast_assign(
++		__entry->bytes		= bytes;
++		__entry->IP		= IP;
++	),
++
++	TP_printk("bytes %d caller %pF",
++		__entry->bytes, (void *)__entry->IP)
++);
++
+ DECLARE_EVENT_CLASS(random__mix_pool_bytes,
+ 	TP_PROTO(const char *pool_name, int bytes, unsigned long IP),
+ 
+@@ -68,7 +87,7 @@ TRACE_EVENT(credit_entropy_bits,
+ 		  (void *)__entry->IP)
+ );
+ 
+-TRACE_EVENT(get_random_bytes,
++DECLARE_EVENT_CLASS(random__get_random_bytes,
+ 	TP_PROTO(int nbytes, unsigned long IP),
+ 
+ 	TP_ARGS(nbytes, IP),
+@@ -86,6 +105,18 @@ TRACE_EVENT(get_random_bytes,
+ 	TP_printk("nbytes %d caller %pF", __entry->nbytes, (void *)__entry->IP)
+ );
+ 
++DEFINE_EVENT(random__get_random_bytes, get_random_bytes,
++	TP_PROTO(int nbytes, unsigned long IP),
++
++	TP_ARGS(nbytes, IP)
++);
++
++DEFINE_EVENT(random__get_random_bytes, get_random_bytes_arch,
++	TP_PROTO(int nbytes, unsigned long IP),
++
++	TP_ARGS(nbytes, IP)
++);
++
+ DECLARE_EVENT_CLASS(random__extract_entropy,
+ 	TP_PROTO(const char *pool_name, int nbytes, int entropy_count,
+ 		 unsigned long IP),

commit 85a1f77716cf546d9b9c42e2848b5712f51ba1ee
+Author: Theodore Ts'o 
+Date:   Sat Sep 21 18:06:02 2013 -0400
+
+    random: mix in architectural randomness earlier in extract_buf()
+    
+    Previously if CPU chip had a built-in random number generator (i.e.,
+    RDRAND on newer x86 chips), we mixed it in at the very end of
+    extract_buf() using an XOR operation.
+    
+    We now mix it in right after the calculate a hash across the entire
+    pool.  This has the advantage that any contribution of entropy from
+    the CPU's HWRNG will get mixed back into the pool.  In addition, it
+    means that if the HWRNG has any defects (either accidentally or
+    maliciously introduced), this will be mitigated via the non-linear
+    transform of the SHA-1 hash function before we hand out generated
+    output.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 2d5daf9b58e9..54d020815b4e 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -904,7 +904,7 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
+ 	int i;
+ 	union {
+ 		__u32 w[5];
+-		unsigned long l[LONGS(EXTRACT_SIZE)];
++		unsigned long l[LONGS(20)];
+ 	} hash;
+ 	__u32 workspace[SHA_WORKSPACE_WORDS];
+ 	__u8 extract[64];
+@@ -916,6 +916,17 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
+ 	for (i = 0; i < r->poolinfo->poolwords; i += 16)
+ 		sha_transform(hash.w, (__u8 *)(r->pool + i), workspace);
+ 
++	/*
++	 * If we have a architectural hardware random number
++	 * generator, mix that in, too.
++	 */
++	for (i = 0; i < LONGS(20); i++) {
++		unsigned long v;
++		if (!arch_get_random_long(&v))
++			break;
++		hash.l[i] ^= v;
++	}
++
+ 	/*
+ 	 * We mix the hash back into the pool to prevent backtracking
+ 	 * attacks (where the attacker knows the state of the pool
+@@ -945,17 +956,6 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
+ 	hash.w[1] ^= hash.w[4];
+ 	hash.w[2] ^= rol32(hash.w[2], 16);
+ 
+-	/*
+-	 * If we have a architectural hardware random number
+-	 * generator, mix that in, too.
+-	 */
+-	for (i = 0; i < LONGS(EXTRACT_SIZE); i++) {
+-		unsigned long v;
+-		if (!arch_get_random_long(&v))
+-			break;
+-		hash.l[i] ^= v;
+-	}
+-
+ 	memcpy(out, &hash, EXTRACT_SIZE);
+ 	memset(&hash, 0, sizeof(hash));
+ }

commit 61875f30daf60305712e25b209ef41ced2635bad
+Author: Theodore Ts'o 
+Date:   Sat Sep 21 13:58:22 2013 -0400
+
+    random: allow architectures to optionally define random_get_entropy()
+    
+    Allow architectures which have a disabled get_cycles() function to
+    provide a random_get_entropy() function which provides a fine-grained,
+    rapidly changing counter that can be used by the /dev/random driver.
+    
+    For example, an architecture might have a rapidly changing register
+    used to control random TLB cache eviction, or DRAM refresh that
+    doesn't meet the requirements of get_cycles(), but which is good
+    enough for the needs of the random driver.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 92e6c67e1ae6..2d5daf9b58e9 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -643,7 +643,7 @@ struct timer_rand_state {
+  */
+ void add_device_randomness(const void *buf, unsigned int size)
+ {
+-	unsigned long time = get_cycles() ^ jiffies;
++	unsigned long time = random_get_entropy() ^ jiffies;
+ 
+ 	mix_pool_bytes(&input_pool, buf, size, NULL);
+ 	mix_pool_bytes(&input_pool, &time, sizeof(time), NULL);
+@@ -680,7 +680,7 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
+ 		goto out;
+ 
+ 	sample.jiffies = jiffies;
+-	sample.cycles = get_cycles();
++	sample.cycles = random_get_entropy();
+ 	sample.num = num;
+ 	mix_pool_bytes(&input_pool, &sample, sizeof(sample), NULL);
+ 
+@@ -747,7 +747,7 @@ void add_interrupt_randomness(int irq, int irq_flags)
+ 	struct fast_pool	*fast_pool = &__get_cpu_var(irq_randomness);
+ 	struct pt_regs		*regs = get_irq_regs();
+ 	unsigned long		now = jiffies;
+-	__u32			input[4], cycles = get_cycles();
++	__u32			input[4], cycles = random_get_entropy();
+ 
+ 	input[0] = cycles ^ jiffies;
+ 	input[1] = irq;
+@@ -1485,7 +1485,7 @@ unsigned int get_random_int(void)
+ 
+ 	hash = get_cpu_var(get_random_int_hash);
+ 
+-	hash[0] += current->pid + jiffies + get_cycles();
++	hash[0] += current->pid + jiffies + random_get_entropy();
+ 	md5_transform(hash, random_int_secret);
+ 	ret = hash[0];
+ 	put_cpu_var(get_random_int_hash);
+diff --git a/include/linux/timex.h b/include/linux/timex.h
+index b3726e61368e..da4c32dbb2aa 100644
+--- a/include/linux/timex.h
++++ b/include/linux/timex.h
+@@ -64,6 +64,20 @@
+ 
+ #include 
+ 
++#ifndef random_get_entropy
++/*
++ * The random_get_entropy() function is used by the /dev/random driver
++ * in order to extract entropy via the relative unpredictability of
++ * when an interrupt takes places versus a high speed, fine-grained
++ * timing source or cycle counter.  Since it will be occurred on every
++ * single interrupt, it must have a very low cost/overhead.
++ *
++ * By default we use get_cycles() for this purpose, but individual
++ * architectures may override this in their asm/timex.h header file.
++ */
++#define random_get_entropy()	get_cycles()
++#endif
++
+ /*
+  * SHIFT_PLL is used as a dampening factor to define how much we
+  * adjust the frequency correction for a given offset in PLL mode.

commit 47d06e532e95b71c0db3839ebdef3fe8812fca2c
+Author: Theodore Ts'o 
+Date:   Tue Sep 10 10:52:35 2013 -0400
+
+    random: run random_int_secret_init() run after all late_initcalls
+    
+    The some platforms (e.g., ARM) initializes their clocks as
+    late_initcalls for some unknown reason.  So make sure
+    random_int_secret_init() is run after all of the late_initcalls are
+    run.
+    
+    Cc: stable@vger.kernel.org
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 0d91fe52f3f5..92e6c67e1ae6 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -1462,12 +1462,11 @@ struct ctl_table random_table[] = {
+ 
+ static u32 random_int_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned;
+ 
+-static int __init random_int_secret_init(void)
++int random_int_secret_init(void)
+ {
+ 	get_random_bytes(random_int_secret, sizeof(random_int_secret));
+ 	return 0;
+ }
+-late_initcall(random_int_secret_init);
+ 
+ /*
+  * Get a random word for internal kernel use only. Similar to urandom but
+diff --git a/include/linux/random.h b/include/linux/random.h
+index 3b9377d6b7a5..6312dd9ba449 100644
+--- a/include/linux/random.h
++++ b/include/linux/random.h
+@@ -17,6 +17,7 @@ extern void add_interrupt_randomness(int irq, int irq_flags);
+ extern void get_random_bytes(void *buf, int nbytes);
+ extern void get_random_bytes_arch(void *buf, int nbytes);
+ void generate_random_uuid(unsigned char uuid_out[16]);
++extern int random_int_secret_init(void);
+ 
+ #ifndef MODULE
+ extern const struct file_operations random_fops, urandom_fops;
+diff --git a/init/main.c b/init/main.c
+index d03d2ec2eacf..586cd3359c02 100644
+--- a/init/main.c
++++ b/init/main.c
+@@ -75,6 +75,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ #include 
+@@ -778,6 +779,7 @@ static void __init do_basic_setup(void)
+ 	do_ctors();
+ 	usermodehelper_enable();
+ 	do_initcalls();
++	random_int_secret_init();
+ }
+ 
+ static void __init do_pre_smp_initcalls(void)

commit 19883bd9658d0dc269fc228b1b39db3615f7c7b0
+Author: Theodore Ts'o 
+Date:   Fri Aug 16 22:06:55 2013 -0400
+
+    ext4: avoid reusing recently deleted inodes in no journal mode
+    
+    In no journal mode, if an inode has recently been deleted, we
+    shouldn't reuse it right away.  Otherwise it's possible, after an
+    unclean shutdown, to hit a situation where a recently deleted inode
+    gets reused for some other purpose before the inode table block has
+    been written to disk.  However, if the directory entry has been
+    updated, then the directory entry will be pointing at the old inode
+    contents.
+    
+    E2fsck will make sure the file system is consistent after the
+    unclean shutdown.  However, if the recently deleted inode is a
+    character mode device, or an inode with the immutable bit set, even
+    after the file system has been fixed up by e2fsck, it can be
+    possible for a *.pyc file to be pointing at a character mode
+    device, and when python tries to open the *.pyc file, Hilarity
+    Ensues.  We could change all of userspace to be very suspicious
+    about stat'ing files before opening them, and clearing the
+    immutable flag if necessary --- or we can just avoid reusing an
+    inode number if it has been recently deleted.
+    
+    Google-Bug-Id: 10017573
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 8bf5999875ee..666a5ed48bcc 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -624,6 +624,51 @@ static int find_group_other(struct super_block *sb, struct inode *parent,
+ 	return -1;
+ }
+ 
++/*
++ * In no journal mode, if an inode has recently been deleted, we want
++ * to avoid reusing it until we're reasonably sure the inode table
++ * block has been written back to disk.  (Yes, these values are
++ * somewhat arbitrary...)
++ */
++#define RECENTCY_MIN	5
++#define RECENTCY_DIRTY	30
++
++static int recently_deleted(struct super_block *sb, ext4_group_t group, int ino)
++{
++	struct ext4_group_desc	*gdp;
++	struct ext4_inode	*raw_inode;
++	struct buffer_head	*bh;
++	unsigned long		dtime, now;
++	int	inodes_per_block = EXT4_SB(sb)->s_inodes_per_block;
++	int	offset, ret = 0, recentcy = RECENTCY_MIN;
++
++	gdp = ext4_get_group_desc(sb, group, NULL);
++	if (unlikely(!gdp))
++		return 0;
++
++	bh = sb_getblk(sb, ext4_inode_table(sb, gdp) +
++		       (ino / inodes_per_block));
++	if (unlikely(!bh) || !buffer_uptodate(bh))
++		/*
++		 * If the block is not in the buffer cache, then it
++		 * must have been written out.
++		 */
++		goto out;
++
++	offset = (ino % inodes_per_block) * EXT4_INODE_SIZE(sb);
++	raw_inode = (struct ext4_inode *) (bh->b_data + offset);
++	dtime = le32_to_cpu(raw_inode->i_dtime);
++	now = get_seconds();
++	if (buffer_dirty(bh))
++		recentcy += RECENTCY_DIRTY;
++
++	if (dtime && (dtime < now) && (now < dtime + recentcy))
++		ret = 1;
++out:
++	brelse(bh);
++	return ret;
++}
++
+ /*
+  * There are two policies for allocating an inode.  If the new inode is
+  * a directory, then a forward search is made for a block group with both
+@@ -741,6 +786,11 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
+ 				   "inode=%lu", ino + 1);
+ 			continue;
+ 		}
++		if ((EXT4_SB(sb)->s_journal == NULL) &&
++		    recently_deleted(sb, group, ino)) {
++			ino++;
++			goto next_inode;
++		}
+ 		if (!handle) {
+ 			BUG_ON(nblocks <= 0);
+ 			handle = __ext4_journal_start_sb(dir->i_sb, line_no,
+@@ -764,6 +814,7 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
+ 		ino++;		/* the inode bitmap is zero-based */
+ 		if (!ret2)
+ 			goto got; /* we grabbed the inode! */
++next_inode:
+ 		if (ino < EXT4_INODES_PER_GROUP(sb))
+ 			goto repeat_in_this_group;
+ next_group:

commit 0e20270454e45ff54c9f8546159924038e31bfa0
+Author: Theodore Ts'o 
+Date:   Fri Aug 16 22:06:53 2013 -0400
+
+    ext4: allocate delayed allocation blocks before rename
+    
+    When ext4_rename() overwrites an already existing file, call
+    ext4_alloc_da_blocks() before starting the journal handle which
+    actually does the rename, instead of doing this afterwards.  This
+    improves the likelihood that the contents will survive a crash if an
+    application replaces a file using the sequence:
+    
+    1)  write replacement contents to foo.new
+    2)  
+    3)  rename foo.new to foo
+    
+    It is still not a guarantee, since ext4_alloc_da_blocks() is *not*
+    doing a file integrity sync; this means if foo.new is a very large
+    file, it may not be completely flushed out to disk.
+    
+    However, for files smaller than a megabyte or so, any dirty pages
+    should be flushed out before we do the rename operation, and so at the
+    next journal commit, the CACHE FLUSH command will make sure al of
+    these pages are safely on the disk platter.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index d9b721c172a6..1bec5a5c1e45 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -3005,6 +3005,10 @@ static struct buffer_head *ext4_get_first_dir_block(handle_t *handle,
+ /*
+  * Anybody can rename anything with this: the permission checks are left to the
+  * higher-level routines.
++ *
++ * n.b.  old_{dentry,inode) refers to the source dentry/inode
++ * while new_{dentry,inode) refers to the destination dentry/inode
++ * This comes from rename(const char *oldpath, const char *newpath)
+  */
+ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 		       struct inode *new_dir, struct dentry *new_dentry)
+@@ -3013,7 +3017,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 	struct inode *old_inode, *new_inode;
+ 	struct buffer_head *old_bh, *new_bh, *dir_bh;
+ 	struct ext4_dir_entry_2 *old_de, *new_de;
+-	int retval, force_da_alloc = 0;
++	int retval;
+ 	int inlined = 0, new_inlined = 0;
+ 	struct ext4_dir_entry_2 *parent_de;
+ 
+@@ -3048,6 +3052,8 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 			new_bh = NULL;
+ 		}
+ 	}
++	if (new_inode && !test_opt(new_dir->i_sb, NO_AUTO_DA_ALLOC))
++		ext4_alloc_da_blocks(old_inode);
+ 
+ 	handle = ext4_journal_start(old_dir, EXT4_HT_DIR,
+ 		(2 * EXT4_DATA_TRANS_BLOCKS(old_dir->i_sb) +
+@@ -3188,8 +3194,6 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 		ext4_mark_inode_dirty(handle, new_inode);
+ 		if (!new_inode->i_nlink)
+ 			ext4_orphan_add(handle, new_inode);
+-		if (!test_opt(new_dir->i_sb, NO_AUTO_DA_ALLOC))
+-			force_da_alloc = 1;
+ 	}
+ 	retval = 0;
+ 
+@@ -3199,8 +3203,6 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 	brelse(new_bh);
+ 	if (handle)
+ 		ext4_journal_stop(handle);
+-	if (retval == 0 && force_da_alloc)
+-		ext4_alloc_da_blocks(old_inode);
+ 	return retval;
+ }
+ 

commit 5b61de757535095c99212c1ed857c3a0e0bbe386
+Author: Theodore Ts'o 
+Date:   Fri Aug 16 22:06:14 2013 -0400
+
+    ext4: start handle at least possible moment when renaming files
+    
+    In ext4_rename(), don't start the journal handle until the the
+    directory entries have been successfully looked up.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 35f55a0dbc4b..d9b721c172a6 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -3009,7 +3009,7 @@ static struct buffer_head *ext4_get_first_dir_block(handle_t *handle,
+ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 		       struct inode *new_dir, struct dentry *new_dentry)
+ {
+-	handle_t *handle;
++	handle_t *handle = NULL;
+ 	struct inode *old_inode, *new_inode;
+ 	struct buffer_head *old_bh, *new_bh, *dir_bh;
+ 	struct ext4_dir_entry_2 *old_de, *new_de;
+@@ -3026,14 +3026,6 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 	 * in separate transaction */
+ 	if (new_dentry->d_inode)
+ 		dquot_initialize(new_dentry->d_inode);
+-	handle = ext4_journal_start(old_dir, EXT4_HT_DIR,
+-		(2 * EXT4_DATA_TRANS_BLOCKS(old_dir->i_sb) +
+-		 EXT4_INDEX_EXTRA_TRANS_BLOCKS + 2));
+-	if (IS_ERR(handle))
+-		return PTR_ERR(handle);
+-
+-	if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir))
+-		ext4_handle_sync(handle);
+ 
+ 	old_bh = ext4_find_entry(old_dir, &old_dentry->d_name, &old_de, NULL);
+ 	/*
+@@ -3056,6 +3048,16 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 			new_bh = NULL;
+ 		}
+ 	}
++
++	handle = ext4_journal_start(old_dir, EXT4_HT_DIR,
++		(2 * EXT4_DATA_TRANS_BLOCKS(old_dir->i_sb) +
++		 EXT4_INDEX_EXTRA_TRANS_BLOCKS + 2));
++	if (IS_ERR(handle))
++		return PTR_ERR(handle);
++
++	if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir))
++		ext4_handle_sync(handle);
++
+ 	if (S_ISDIR(old_inode->i_mode)) {
+ 		if (new_inode) {
+ 			retval = -ENOTEMPTY;
+@@ -3195,7 +3197,8 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 	brelse(dir_bh);
+ 	brelse(old_bh);
+ 	brelse(new_bh);
+-	ext4_journal_stop(handle);
++	if (handle)
++		ext4_journal_stop(handle);
+ 	if (retval == 0 && force_da_alloc)
+ 		ext4_alloc_da_blocks(old_inode);
+ 	return retval;

commit 7869a4a6c5caa7b2e5c41ccaf46eb3371f88eea7
+Author: Theodore Ts'o 
+Date:   Fri Aug 16 22:05:14 2013 -0400
+
+    ext4: add support for extent pre-caching
+    
+    Add a new fiemap flag which forces the all of the extents in an inode
+    to be cached in the extent_status tree.  This is critically important
+    when using AIO to a preallocated file, since if we need to read in
+    blocks from the extent tree, the io_submit(2) system call becomes
+    synchronous, and the AIO is no longer "A", which is bad.
+    
+    In addition, for most files which have an external leaf tree block,
+    the cost of caching the information in the extent status tree will be
+    less than caching the entire 4k block in the buffer cache.  So it is
+    generally a win to keep the extent information cached.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index c74b1948feb0..635135e6148e 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -561,15 +561,16 @@ enum {
+ #define EXT4_GET_BLOCKS_NO_PUT_HOLE		0x0200
+ 
+ /*
+- * The bit position of this flag must not overlap with any of the
+- * EXT4_GET_BLOCKS_*.  It is used by ext4_ext_find_extent(),
++ * The bit position of these flags must not overlap with any of the
++ * EXT4_GET_BLOCKS_*.  They are used by ext4_ext_find_extent(),
+  * read_extent_tree_block(), ext4_split_extent_at(),
+- * ext4_ext_insert_extent(), and ext4_ext_create_new_leaf() to
+- * indicate that the we shouldn't be caching the extents when reading
+- * from the extent tree while a truncate or punch hole operation
+- * is in progress.
++ * ext4_ext_insert_extent(), and ext4_ext_create_new_leaf().
++ * EXT4_EX_NOCACHE is used to indicate that the we shouldn't be
++ * caching the extents when reading from the extent tree while a
++ * truncate or punch hole operation is in progress.
+  */
+ #define EXT4_EX_NOCACHE				0x0400
++#define EXT4_EX_FORCE_CACHE			0x0800
+ 
+ /*
+  * Flags used by ext4_free_blocks
+@@ -601,6 +602,7 @@ enum {
+ #define EXT4_IOC_MOVE_EXT		_IOWR('f', 15, struct move_extent)
+ #define EXT4_IOC_RESIZE_FS		_IOW('f', 16, __u64)
+ #define EXT4_IOC_SWAP_BOOT		_IO('f', 17)
++#define EXT4_IOC_PRECACHE_EXTENTS	_IO('f', 18)
+ 
+ #if defined(__KERNEL__) && defined(CONFIG_COMPAT)
+ /*
+@@ -1386,6 +1388,7 @@ enum {
+ 					   nolocking */
+ 	EXT4_STATE_MAY_INLINE_DATA,	/* may have in-inode data */
+ 	EXT4_STATE_ORDERED_MODE,	/* data=ordered mode */
++	EXT4_STATE_EXT_PRECACHED,	/* extents have been precached */
+ };
+ 
+ #define EXT4_INODE_BIT_FNS(name, field, offset)				\
+@@ -2705,7 +2708,7 @@ extern int ext4_find_delalloc_range(struct inode *inode,
+ extern int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk);
+ extern int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ 			__u64 start, __u64 len);
+-
++extern int ext4_ext_precache(struct inode *inode);
+ 
+ /* move_extent.c */
+ extern void ext4_double_down_write_data_sem(struct inode *first,
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 08c1ac976479..01838875fcaf 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -482,7 +482,7 @@ __read_extent_tree_block(const char *function, unsigned int line,
+ 		if (err < 0)
+ 			goto errout;
+ 	}
+-	if (buffer_verified(bh))
++	if (buffer_verified(bh) && !(flags & EXT4_EX_FORCE_CACHE))
+ 		return bh;
+ 	err = __ext4_ext_check(function, line, inode,
+ 			       ext_block_hdr(bh), depth, pblk);
+@@ -526,6 +526,71 @@ __read_extent_tree_block(const char *function, unsigned int line,
+ 	__read_extent_tree_block(__func__, __LINE__, (inode), (pblk),   \
+ 				 (depth), (flags))
+ 
++/*
++ * This function is called to cache a file's extent information in the
++ * extent status tree
++ */
++int ext4_ext_precache(struct inode *inode)
++{
++	struct ext4_inode_info *ei = EXT4_I(inode);
++	struct ext4_ext_path *path = NULL;
++	struct buffer_head *bh;
++	int i = 0, depth, ret = 0;
++
++	if (!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
++		return 0;	/* not an extent-mapped inode */
++
++	down_read(&ei->i_data_sem);
++	depth = ext_depth(inode);
++
++	path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 1),
++		       GFP_NOFS);
++	if (path == NULL) {
++		up_read(&ei->i_data_sem);
++		return -ENOMEM;
++	}
++
++	/* Don't cache anything if there are no external extent blocks */
++	if (depth == 0)
++		goto out;
++	path[0].p_hdr = ext_inode_hdr(inode);
++	ret = ext4_ext_check(inode, path[0].p_hdr, depth, 0);
++	if (ret)
++		goto out;
++	path[0].p_idx = EXT_FIRST_INDEX(path[0].p_hdr);
++	while (i >= 0) {
++		/*
++		 * If this is a leaf block or we've reached the end of
++		 * the index block, go up
++		 */
++		if ((i == depth) ||
++		    path[i].p_idx > EXT_LAST_INDEX(path[i].p_hdr)) {
++			brelse(path[i].p_bh);
++			path[i].p_bh = NULL;
++			i--;
++			continue;
++		}
++		bh = read_extent_tree_block(inode,
++					    ext4_idx_pblock(path[i].p_idx++),
++					    depth - i - 1,
++					    EXT4_EX_FORCE_CACHE);
++		if (IS_ERR(bh)) {
++			ret = PTR_ERR(bh);
++			break;
++		}
++		i++;
++		path[i].p_bh = bh;
++		path[i].p_hdr = ext_block_hdr(bh);
++		path[i].p_idx = EXT_FIRST_INDEX(path[i].p_hdr);
++	}
++	ext4_set_inode_state(inode, EXT4_STATE_EXT_PRECACHED);
++out:
++	up_read(&ei->i_data_sem);
++	ext4_ext_drop_refs(path);
++	kfree(path);
++	return ret;
++}
++
+ #ifdef EXT_DEBUG
+ static void ext4_ext_show_path(struct inode *inode, struct ext4_ext_path *path)
+ {
+@@ -4766,6 +4831,12 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ 			return error;
+ 	}
+ 
++	if (fieinfo->fi_flags & FIEMAP_FLAG_CACHE) {
++		error = ext4_ext_precache(inode);
++		if (error)
++			return error;
++	}
++
+ 	/* fallback to generic here if not in extents fmt */
+ 	if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
+ 		return generic_block_fiemap(inode, fieinfo, start, len,
+diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
+index 1dc5df016e25..0e88a367b535 100644
+--- a/fs/ext4/extents_status.c
++++ b/fs/ext4/extents_status.c
+@@ -710,11 +710,8 @@ void ext4_es_cache_extent(struct inode *inode, ext4_lblk_t lblk,
+ 	write_lock(&EXT4_I(inode)->i_es_lock);
+ 
+ 	es = __es_tree_search(&EXT4_I(inode)->i_es_tree.root, lblk);
+-	if (es && ((es->es_lblk <= lblk) || (es->es_lblk <= end)))
+-		goto out;
+-
+-	__es_insert_extent(inode, &newes);
+-out:
++	if (!es || es->es_lblk > end)
++		__es_insert_extent(inode, &newes);
+ 	write_unlock(&EXT4_I(inode)->i_es_lock);
+ }
+ 
+@@ -930,6 +927,12 @@ static int ext4_inode_touch_time_cmp(void *priv, struct list_head *a,
+ 	eia = list_entry(a, struct ext4_inode_info, i_es_lru);
+ 	eib = list_entry(b, struct ext4_inode_info, i_es_lru);
+ 
++	if (ext4_test_inode_state(&eia->vfs_inode, EXT4_STATE_EXT_PRECACHED) &&
++	    !ext4_test_inode_state(&eib->vfs_inode, EXT4_STATE_EXT_PRECACHED))
++		return 1;
++	if (!ext4_test_inode_state(&eia->vfs_inode, EXT4_STATE_EXT_PRECACHED) &&
++	    ext4_test_inode_state(&eib->vfs_inode, EXT4_STATE_EXT_PRECACHED))
++		return -1;
+ 	if (eia->i_touch_when == eib->i_touch_when)
+ 		return 0;
+ 	if (time_after(eia->i_touch_when, eib->i_touch_when))
+@@ -943,21 +946,13 @@ static int __ext4_es_shrink(struct ext4_sb_info *sbi, int nr_to_scan,
+ {
+ 	struct ext4_inode_info *ei;
+ 	struct list_head *cur, *tmp;
+-	LIST_HEAD(skiped);
++	LIST_HEAD(skipped);
+ 	int ret, nr_shrunk = 0;
++	int retried = 0, skip_precached = 1, nr_skipped = 0;
+ 
+ 	spin_lock(&sbi->s_es_lru_lock);
+ 
+-	/*
+-	 * If the inode that is at the head of LRU list is newer than
+-	 * last_sorted time, that means that we need to sort this list.
+-	 */
+-	ei = list_first_entry(&sbi->s_es_lru, struct ext4_inode_info, i_es_lru);
+-	if (sbi->s_es_last_sorted < ei->i_touch_when) {
+-		list_sort(NULL, &sbi->s_es_lru, ext4_inode_touch_time_cmp);
+-		sbi->s_es_last_sorted = jiffies;
+-	}
+-
++retry:
+ 	list_for_each_safe(cur, tmp, &sbi->s_es_lru) {
+ 		/*
+ 		 * If we have already reclaimed all extents from extent
+@@ -968,9 +963,16 @@ static int __ext4_es_shrink(struct ext4_sb_info *sbi, int nr_to_scan,
+ 
+ 		ei = list_entry(cur, struct ext4_inode_info, i_es_lru);
+ 
+-		/* Skip the inode that is newer than the last_sorted time */
+-		if (sbi->s_es_last_sorted < ei->i_touch_when) {
+-			list_move_tail(cur, &skiped);
++		/*
++		 * Skip the inode that is newer than the last_sorted
++		 * time.  Normally we try hard to avoid shrinking
++		 * precached inodes, but we will as a last resort.
++		 */
++		if ((sbi->s_es_last_sorted < ei->i_touch_when) ||
++		    (skip_precached && ext4_test_inode_state(&ei->vfs_inode,
++						EXT4_STATE_EXT_PRECACHED))) {
++			nr_skipped++;
++			list_move_tail(cur, &skipped);
+ 			continue;
+ 		}
+ 
+@@ -990,11 +992,33 @@ static int __ext4_es_shrink(struct ext4_sb_info *sbi, int nr_to_scan,
+ 	}
+ 
+ 	/* Move the newer inodes into the tail of the LRU list. */
+-	list_splice_tail(&skiped, &sbi->s_es_lru);
++	list_splice_tail(&skipped, &sbi->s_es_lru);
++	INIT_LIST_HEAD(&skipped);
++
++	/*
++	 * If we skipped any inodes, and we weren't able to make any
++	 * forward progress, sort the list and try again.
++	 */
++	if ((nr_shrunk == 0) && nr_skipped && !retried) {
++		retried++;
++		list_sort(NULL, &sbi->s_es_lru, ext4_inode_touch_time_cmp);
++		sbi->s_es_last_sorted = jiffies;
++		ei = list_first_entry(&sbi->s_es_lru, struct ext4_inode_info,
++				      i_es_lru);
++		/*
++		 * If there are no non-precached inodes left on the
++		 * list, start releasing precached extents.
++		 */
++		if (ext4_test_inode_state(&ei->vfs_inode,
++					  EXT4_STATE_EXT_PRECACHED))
++			skip_precached = 0;
++		goto retry;
++	}
++
+ 	spin_unlock(&sbi->s_es_lru_lock);
+ 
+ 	if (locked_ei && nr_shrunk == 0)
+-		nr_shrunk = __es_try_to_reclaim_extents(ei, nr_to_scan);
++		nr_shrunk = __es_try_to_reclaim_extents(locked_ei, nr_to_scan);
+ 
+ 	return nr_shrunk;
+ }
+@@ -1069,10 +1093,16 @@ static int __es_try_to_reclaim_extents(struct ext4_inode_info *ei,
+ 	struct rb_node *node;
+ 	struct extent_status *es;
+ 	int nr_shrunk = 0;
++	static DEFINE_RATELIMIT_STATE(_rs, DEFAULT_RATELIMIT_INTERVAL,
++				      DEFAULT_RATELIMIT_BURST);
+ 
+ 	if (ei->i_es_lru_nr == 0)
+ 		return 0;
+ 
++	if (ext4_test_inode_state(inode, EXT4_STATE_EXT_PRECACHED) &&
++	    __ratelimit(&_rs))
++		ext4_warning(inode->i_sb, "forced shrink of precached extents");
++
+ 	node = rb_first(&tree->root);
+ 	while (node != NULL) {
+ 		es = rb_entry(node, struct extent_status, rb_node);
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index c0427e2f6648..5498f75a1648 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -624,6 +624,8 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 
+ 		return 0;
+ 	}
++	case EXT4_IOC_PRECACHE_EXTENTS:
++		return ext4_ext_precache(inode);
+ 
+ 	default:
+ 		return -ENOTTY;
+@@ -688,6 +690,7 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ 	case EXT4_IOC_MOVE_EXT:
+ 	case FITRIM:
+ 	case EXT4_IOC_RESIZE_FS:
++	case EXT4_IOC_PRECACHE_EXTENTS:
+ 		break;
+ 	default:
+ 		return -ENOIOCTLCMD;
+diff --git a/include/uapi/linux/fiemap.h b/include/uapi/linux/fiemap.h
+index d830747f5c0b..0c51d617dae9 100644
+--- a/include/uapi/linux/fiemap.h
++++ b/include/uapi/linux/fiemap.h
+@@ -40,6 +40,7 @@ struct fiemap {
+ 
+ #define FIEMAP_FLAG_SYNC	0x00000001 /* sync file data before map */
+ #define FIEMAP_FLAG_XATTR	0x00000002 /* map extended attribute tree */
++#define FIEMAP_FLAG_CACHE	0x00000004 /* request caching of the extents */
+ 
+ #define FIEMAP_FLAGS_COMPAT	(FIEMAP_FLAG_SYNC | FIEMAP_FLAG_XATTR)
+ 

commit 107a7bd31ac003e42c0f966aa8e5b26947de6024
+Author: Theodore Ts'o 
+Date:   Fri Aug 16 21:23:41 2013 -0400
+
+    ext4: cache all of an extent tree's leaf block upon reading
+    
+    When we read in an extent tree leaf block from disk, arrange to have
+    all of its entries cached.  In nearly all cases the in-memory
+    representation will be more compact than the on-disk representation in
+    the buffer cache, and it allows us to get the information without
+    having to traverse the extent tree for successive extents.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Zheng Liu 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 0ab26fbf3380..c74b1948feb0 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -560,6 +560,17 @@ enum {
+ 	/* Do not put hole in extent cache */
+ #define EXT4_GET_BLOCKS_NO_PUT_HOLE		0x0200
+ 
++/*
++ * The bit position of this flag must not overlap with any of the
++ * EXT4_GET_BLOCKS_*.  It is used by ext4_ext_find_extent(),
++ * read_extent_tree_block(), ext4_split_extent_at(),
++ * ext4_ext_insert_extent(), and ext4_ext_create_new_leaf() to
++ * indicate that the we shouldn't be caching the extents when reading
++ * from the extent tree while a truncate or punch hole operation
++ * is in progress.
++ */
++#define EXT4_EX_NOCACHE				0x0400
++
+ /*
+  * Flags used by ext4_free_blocks
+  */
+@@ -2684,7 +2695,8 @@ extern int ext4_ext_insert_extent(handle_t *, struct inode *,
+ 				  struct ext4_ext_path *,
+ 				  struct ext4_extent *, int);
+ extern struct ext4_ext_path *ext4_ext_find_extent(struct inode *, ext4_lblk_t,
+-						  struct ext4_ext_path *);
++						  struct ext4_ext_path *,
++						  int flags);
+ extern void ext4_ext_drop_refs(struct ext4_ext_path *);
+ extern int ext4_ext_check_inode(struct inode *inode);
+ extern int ext4_find_delalloc_range(struct inode *inode,
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 6e7b7d928f4a..08c1ac976479 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -466,7 +466,8 @@ int ext4_ext_check_inode(struct inode *inode)
+ 
+ static struct buffer_head *
+ __read_extent_tree_block(const char *function, unsigned int line,
+-			 struct inode *inode, ext4_fsblk_t pblk, int depth)
++			 struct inode *inode, ext4_fsblk_t pblk, int depth,
++			 int flags)
+ {
+ 	struct buffer_head		*bh;
+ 	int				err;
+@@ -488,6 +489,32 @@ __read_extent_tree_block(const char *function, unsigned int line,
+ 	if (err)
+ 		goto errout;
+ 	set_buffer_verified(bh);
++	/*
++	 * If this is a leaf block, cache all of its entries
++	 */
++	if (!(flags & EXT4_EX_NOCACHE) && depth == 0) {
++		struct ext4_extent_header *eh = ext_block_hdr(bh);
++		struct ext4_extent *ex = EXT_FIRST_EXTENT(eh);
++		ext4_lblk_t prev = 0;
++		int i;
++
++		for (i = le16_to_cpu(eh->eh_entries); i > 0; i--, ex++) {
++			unsigned int status = EXTENT_STATUS_WRITTEN;
++			ext4_lblk_t lblk = le32_to_cpu(ex->ee_block);
++			int len = ext4_ext_get_actual_len(ex);
++
++			if (prev && (prev != lblk))
++				ext4_es_cache_extent(inode, prev,
++						     lblk - prev, ~0,
++						     EXTENT_STATUS_HOLE);
++
++			if (ext4_ext_is_uninitialized(ex))
++				status = EXTENT_STATUS_UNWRITTEN;
++			ext4_es_cache_extent(inode, lblk, len,
++					     ext4_ext_pblock(ex), status);
++			prev = lblk + len;
++		}
++	}
+ 	return bh;
+ errout:
+ 	put_bh(bh);
+@@ -495,8 +522,9 @@ __read_extent_tree_block(const char *function, unsigned int line,
+ 
+ }
+ 
+-#define read_extent_tree_block(inode, pblk, depth)		\
+-	__read_extent_tree_block(__func__, __LINE__, (inode), (pblk), (depth))
++#define read_extent_tree_block(inode, pblk, depth, flags)		\
++	__read_extent_tree_block(__func__, __LINE__, (inode), (pblk),   \
++				 (depth), (flags))
+ 
+ #ifdef EXT_DEBUG
+ static void ext4_ext_show_path(struct inode *inode, struct ext4_ext_path *path)
+@@ -730,7 +758,7 @@ int ext4_ext_tree_init(handle_t *handle, struct inode *inode)
+ 
+ struct ext4_ext_path *
+ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
+-					struct ext4_ext_path *path)
++		     struct ext4_ext_path *path, int flags)
+ {
+ 	struct ext4_extent_header *eh;
+ 	struct buffer_head *bh;
+@@ -762,7 +790,8 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
+ 		path[ppos].p_depth = i;
+ 		path[ppos].p_ext = NULL;
+ 
+-		bh = read_extent_tree_block(inode, path[ppos].p_block, --i);
++		bh = read_extent_tree_block(inode, path[ppos].p_block, --i,
++					    flags);
+ 		if (IS_ERR(bh)) {
+ 			ret = PTR_ERR(bh);
+ 			goto err;
+@@ -1199,7 +1228,8 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
+  * if no free index is found, then it requests in-depth growing.
+  */
+ static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
+-				    unsigned int flags,
++				    unsigned int mb_flags,
++				    unsigned int gb_flags,
+ 				    struct ext4_ext_path *path,
+ 				    struct ext4_extent *newext)
+ {
+@@ -1221,7 +1251,7 @@ static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
+ 	if (EXT_HAS_FREE_INDEX(curp)) {
+ 		/* if we found index with free entry, then use that
+ 		 * entry: create all needed subtree and add new leaf */
+-		err = ext4_ext_split(handle, inode, flags, path, newext, i);
++		err = ext4_ext_split(handle, inode, mb_flags, path, newext, i);
+ 		if (err)
+ 			goto out;
+ 
+@@ -1229,12 +1259,12 @@ static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
+ 		ext4_ext_drop_refs(path);
+ 		path = ext4_ext_find_extent(inode,
+ 				    (ext4_lblk_t)le32_to_cpu(newext->ee_block),
+-				    path);
++				    path, gb_flags);
+ 		if (IS_ERR(path))
+ 			err = PTR_ERR(path);
+ 	} else {
+ 		/* tree is full, time to grow in depth */
+-		err = ext4_ext_grow_indepth(handle, inode, flags, newext);
++		err = ext4_ext_grow_indepth(handle, inode, mb_flags, newext);
+ 		if (err)
+ 			goto out;
+ 
+@@ -1242,7 +1272,7 @@ static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
+ 		ext4_ext_drop_refs(path);
+ 		path = ext4_ext_find_extent(inode,
+ 				   (ext4_lblk_t)le32_to_cpu(newext->ee_block),
+-				    path);
++				    path, gb_flags);
+ 		if (IS_ERR(path)) {
+ 			err = PTR_ERR(path);
+ 			goto out;
+@@ -1415,7 +1445,7 @@ static int ext4_ext_search_right(struct inode *inode,
+ 	while (++depth < path->p_depth) {
+ 		/* subtract from p_depth to get proper eh_depth */
+ 		bh = read_extent_tree_block(inode, block,
+-					    path->p_depth - depth);
++					    path->p_depth - depth, 0);
+ 		if (IS_ERR(bh))
+ 			return PTR_ERR(bh);
+ 		eh = ext_block_hdr(bh);
+@@ -1424,7 +1454,7 @@ static int ext4_ext_search_right(struct inode *inode,
+ 		put_bh(bh);
+ 	}
+ 
+-	bh = read_extent_tree_block(inode, block, path->p_depth - depth);
++	bh = read_extent_tree_block(inode, block, path->p_depth - depth, 0);
+ 	if (IS_ERR(bh))
+ 		return PTR_ERR(bh);
+ 	eh = ext_block_hdr(bh);
+@@ -1786,7 +1816,7 @@ static unsigned int ext4_ext_check_overlap(struct ext4_sb_info *sbi,
+  */
+ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+ 				struct ext4_ext_path *path,
+-				struct ext4_extent *newext, int flag)
++				struct ext4_extent *newext, int gb_flags)
+ {
+ 	struct ext4_extent_header *eh;
+ 	struct ext4_extent *ex, *fex;
+@@ -1795,7 +1825,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+ 	int depth, len, err;
+ 	ext4_lblk_t next;
+ 	unsigned uninitialized = 0;
+-	int flags = 0;
++	int mb_flags = 0;
+ 
+ 	if (unlikely(ext4_ext_get_actual_len(newext) == 0)) {
+ 		EXT4_ERROR_INODE(inode, "ext4_ext_get_actual_len(newext) == 0");
+@@ -1810,7 +1840,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+ 	}
+ 
+ 	/* try to insert block into found extent and return */
+-	if (ex && !(flag & EXT4_GET_BLOCKS_PRE_IO)) {
++	if (ex && !(gb_flags & EXT4_GET_BLOCKS_PRE_IO)) {
+ 
+ 		/*
+ 		 * Try to see whether we should rather test the extent on
+@@ -1913,7 +1943,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+ 	if (next != EXT_MAX_BLOCKS) {
+ 		ext_debug("next leaf block - %u\n", next);
+ 		BUG_ON(npath != NULL);
+-		npath = ext4_ext_find_extent(inode, next, NULL);
++		npath = ext4_ext_find_extent(inode, next, NULL, 0);
+ 		if (IS_ERR(npath))
+ 			return PTR_ERR(npath);
+ 		BUG_ON(npath->p_depth != path->p_depth);
+@@ -1932,9 +1962,10 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+ 	 * There is no free space in the found leaf.
+ 	 * We're gonna add a new leaf in the tree.
+ 	 */
+-	if (flag & EXT4_GET_BLOCKS_METADATA_NOFAIL)
+-		flags = EXT4_MB_USE_RESERVED;
+-	err = ext4_ext_create_new_leaf(handle, inode, flags, path, newext);
++	if (gb_flags & EXT4_GET_BLOCKS_METADATA_NOFAIL)
++		mb_flags = EXT4_MB_USE_RESERVED;
++	err = ext4_ext_create_new_leaf(handle, inode, mb_flags, gb_flags,
++				       path, newext);
+ 	if (err)
+ 		goto cleanup;
+ 	depth = ext_depth(inode);
+@@ -2000,7 +2031,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+ 
+ merge:
+ 	/* try to merge extents */
+-	if (!(flag & EXT4_GET_BLOCKS_PRE_IO))
++	if (!(gb_flags & EXT4_GET_BLOCKS_PRE_IO))
+ 		ext4_ext_try_to_merge(handle, inode, path, nearex);
+ 
+ 
+@@ -2043,7 +2074,7 @@ static int ext4_fill_fiemap_extents(struct inode *inode,
+ 			path = NULL;
+ 		}
+ 
+-		path = ext4_ext_find_extent(inode, block, path);
++		path = ext4_ext_find_extent(inode, block, path, 0);
+ 		if (IS_ERR(path)) {
+ 			up_read(&EXT4_I(inode)->i_data_sem);
+ 			err = PTR_ERR(path);
+@@ -2705,7 +2736,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
+ 		ext4_lblk_t ee_block;
+ 
+ 		/* find extent for this block */
+-		path = ext4_ext_find_extent(inode, end, NULL);
++		path = ext4_ext_find_extent(inode, end, NULL, EXT4_EX_NOCACHE);
+ 		if (IS_ERR(path)) {
+ 			ext4_journal_stop(handle);
+ 			return PTR_ERR(path);
+@@ -2747,6 +2778,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
+ 			 */
+ 			err = ext4_split_extent_at(handle, inode, path,
+ 					end + 1, split_flag,
++					EXT4_EX_NOCACHE |
+ 					EXT4_GET_BLOCKS_PRE_IO |
+ 					EXT4_GET_BLOCKS_METADATA_NOFAIL);
+ 
+@@ -2823,7 +2855,8 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
+ 				  i + 1, ext4_idx_pblock(path[i].p_idx));
+ 			memset(path + i + 1, 0, sizeof(*path));
+ 			bh = read_extent_tree_block(inode,
+-				ext4_idx_pblock(path[i].p_idx), depth - i - 1);
++				ext4_idx_pblock(path[i].p_idx), depth - i - 1,
++				EXT4_EX_NOCACHE);
+ 			if (IS_ERR(bh)) {
+ 				/* should we reset i_size? */
+ 				err = PTR_ERR(bh);
+@@ -3170,7 +3203,7 @@ static int ext4_split_extent(handle_t *handle,
+ 	 * result in split of original leaf or extent zeroout.
+ 	 */
+ 	ext4_ext_drop_refs(path);
+-	path = ext4_ext_find_extent(inode, map->m_lblk, path);
++	path = ext4_ext_find_extent(inode, map->m_lblk, path, 0);
+ 	if (IS_ERR(path))
+ 		return PTR_ERR(path);
+ 	depth = ext_depth(inode);
+@@ -3554,7 +3587,7 @@ static int ext4_convert_unwritten_extents_endio(handle_t *handle,
+ 		if (err < 0)
+ 			goto out;
+ 		ext4_ext_drop_refs(path);
+-		path = ext4_ext_find_extent(inode, map->m_lblk, path);
++		path = ext4_ext_find_extent(inode, map->m_lblk, path, 0);
+ 		if (IS_ERR(path)) {
+ 			err = PTR_ERR(path);
+ 			goto out;
+@@ -4041,7 +4074,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 	trace_ext4_ext_map_blocks_enter(inode, map->m_lblk, map->m_len, flags);
+ 
+ 	/* find extent for this block */
+-	path = ext4_ext_find_extent(inode, map->m_lblk, NULL);
++	path = ext4_ext_find_extent(inode, map->m_lblk, NULL, 0);
+ 	if (IS_ERR(path)) {
+ 		err = PTR_ERR(path);
+ 		path = NULL;
+@@ -4760,6 +4793,6 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ 		error = ext4_fill_fiemap_extents(inode, start_blk,
+ 						 len_blks, fieinfo);
+ 	}
+-
++	ext4_es_lru_add(inode);
+ 	return error;
+ }
+diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
+index ded2615b63e0..1dc5df016e25 100644
+--- a/fs/ext4/extents_status.c
++++ b/fs/ext4/extents_status.c
+@@ -419,7 +419,7 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode,
+ 	unsigned short ee_len;
+ 	int depth, ee_status, es_status;
+ 
+-	path = ext4_ext_find_extent(inode, es->es_lblk, NULL);
++	path = ext4_ext_find_extent(inode, es->es_lblk, NULL, EXT4_EX_NOCACHE);
+ 	if (IS_ERR(path))
+ 		return;
+ 
+@@ -683,6 +683,41 @@ int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
+ 	return err;
+ }
+ 
++/*
++ * ext4_es_cache_extent() inserts information into the extent status
++ * tree if and only if there isn't information about the range in
++ * question already.
++ */
++void ext4_es_cache_extent(struct inode *inode, ext4_lblk_t lblk,
++			  ext4_lblk_t len, ext4_fsblk_t pblk,
++			  unsigned int status)
++{
++	struct extent_status *es;
++	struct extent_status newes;
++	ext4_lblk_t end = lblk + len - 1;
++
++	newes.es_lblk = lblk;
++	newes.es_len = len;
++	ext4_es_store_pblock(&newes, pblk);
++	ext4_es_store_status(&newes, status);
++	trace_ext4_es_cache_extent(inode, &newes);
++
++	if (!len)
++		return;
++
++	BUG_ON(end < lblk);
++
++	write_lock(&EXT4_I(inode)->i_es_lock);
++
++	es = __es_tree_search(&EXT4_I(inode)->i_es_tree.root, lblk);
++	if (es && ((es->es_lblk <= lblk) || (es->es_lblk <= end)))
++		goto out;
++
++	__es_insert_extent(inode, &newes);
++out:
++	write_unlock(&EXT4_I(inode)->i_es_lock);
++}
++
+ /*
+  * ext4_es_lookup_extent() looks up an extent in extent status tree.
+  *
+diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h
+index d72af848f989..3e83aef3653a 100644
+--- a/fs/ext4/extents_status.h
++++ b/fs/ext4/extents_status.h
+@@ -71,6 +71,9 @@ extern void ext4_es_init_tree(struct ext4_es_tree *tree);
+ extern int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
+ 				 ext4_lblk_t len, ext4_fsblk_t pblk,
+ 				 unsigned int status);
++extern void ext4_es_cache_extent(struct inode *inode, ext4_lblk_t lblk,
++				 ext4_lblk_t len, ext4_fsblk_t pblk,
++				 unsigned int status);
+ extern int ext4_es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
+ 				 ext4_lblk_t len);
+ extern void ext4_es_find_delayed_extent_range(struct inode *inode,
+diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
+index 49e8bdff9163..f99bdb8548b2 100644
+--- a/fs/ext4/migrate.c
++++ b/fs/ext4/migrate.c
+@@ -39,7 +39,7 @@ static int finish_range(handle_t *handle, struct inode *inode,
+ 	newext.ee_block = cpu_to_le32(lb->first_block);
+ 	newext.ee_len   = cpu_to_le16(lb->last_block - lb->first_block + 1);
+ 	ext4_ext_store_pblock(&newext, lb->first_pblock);
+-	path = ext4_ext_find_extent(inode, lb->first_block, NULL);
++	path = ext4_ext_find_extent(inode, lb->first_block, NULL, 0);
+ 
+ 	if (IS_ERR(path)) {
+ 		retval = PTR_ERR(path);
+diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
+index e86dddbd8296..7fa4d855dbd5 100644
+--- a/fs/ext4/move_extent.c
++++ b/fs/ext4/move_extent.c
+@@ -37,7 +37,7 @@ get_ext_path(struct inode *inode, ext4_lblk_t lblock,
+ 	int ret = 0;
+ 	struct ext4_ext_path *path;
+ 
+-	path = ext4_ext_find_extent(inode, lblock, *orig_path);
++	path = ext4_ext_find_extent(inode, lblock, *orig_path, EXT4_EX_NOCACHE);
+ 	if (IS_ERR(path))
+ 		ret = PTR_ERR(path);
+ 	else if (path[ext_depth(inode)].p_ext == NULL)
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index 47a355b251e4..d892b55d91ab 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -2192,7 +2192,7 @@ TRACE_EVENT(ext4_ext_remove_space_done,
+ 		  (unsigned short) __entry->eh_entries)
+ );
+ 
+-TRACE_EVENT(ext4_es_insert_extent,
++DECLARE_EVENT_CLASS(ext4__es_extent,
+ 	TP_PROTO(struct inode *inode, struct extent_status *es),
+ 
+ 	TP_ARGS(inode, es),
+@@ -2222,6 +2222,18 @@ TRACE_EVENT(ext4_es_insert_extent,
+ 		  __entry->pblk, show_extent_status(__entry->status))
+ );
+ 
++DEFINE_EVENT(ext4__es_extent, ext4_es_insert_extent,
++	TP_PROTO(struct inode *inode, struct extent_status *es),
++
++	TP_ARGS(inode, es)
++);
++
++DEFINE_EVENT(ext4__es_extent, ext4_es_cache_extent,
++	TP_PROTO(struct inode *inode, struct extent_status *es),
++
++	TP_ARGS(inode, es)
++);
++
+ TRACE_EVENT(ext4_es_remove_extent,
+ 	TP_PROTO(struct inode *inode, ext4_lblk_t lblk, ext4_lblk_t len),
+ 

commit 3be78c73179c9347bdc0a92b2898063bd2300ff7
+Author: Theodore Ts'o 
+Date:   Fri Aug 16 21:22:41 2013 -0400
+
+    ext4: use unsigned int for es_status values
+    
+    Don't use an unsigned long long for the es_status flags; this requires
+    that we pass 64-bit values around which is painful on 32-bit systems.
+    Instead pass the extent status flags around using the low 4 bits of an
+    unsigned int, and shift them into place when we are reading or writing
+    es_pblk.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Zheng Liu 
+
+diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
+index 91cb110da1b4..ded2615b63e0 100644
+--- a/fs/ext4/extents_status.c
++++ b/fs/ext4/extents_status.c
+@@ -263,7 +263,7 @@ void ext4_es_find_delayed_extent_range(struct inode *inode,
+ 	if (tree->cache_es) {
+ 		es1 = tree->cache_es;
+ 		if (in_range(lblk, es1->es_lblk, es1->es_len)) {
+-			es_debug("%u cached by [%u/%u) %llu %llx\n",
++			es_debug("%u cached by [%u/%u) %llu %x\n",
+ 				 lblk, es1->es_lblk, es1->es_len,
+ 				 ext4_es_pblock(es1), ext4_es_status(es1));
+ 			goto out;
+@@ -641,13 +641,13 @@ static int __es_insert_extent(struct inode *inode, struct extent_status *newes)
+  */
+ int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
+ 			  ext4_lblk_t len, ext4_fsblk_t pblk,
+-			  unsigned long long status)
++			  unsigned int status)
+ {
+ 	struct extent_status newes;
+ 	ext4_lblk_t end = lblk + len - 1;
+ 	int err = 0;
+ 
+-	es_debug("add [%u/%u) %llu %llx to extent status tree of inode %lu\n",
++	es_debug("add [%u/%u) %llu %x to extent status tree of inode %lu\n",
+ 		 lblk, len, pblk, status, inode->i_ino);
+ 
+ 	if (!len)
+diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h
+index e936730cc5b0..d72af848f989 100644
+--- a/fs/ext4/extents_status.h
++++ b/fs/ext4/extents_status.h
+@@ -29,16 +29,26 @@
+ /*
+  * These flags live in the high bits of extent_status.es_pblk
+  */
+-#define EXTENT_STATUS_WRITTEN	(1ULL << 63)
+-#define EXTENT_STATUS_UNWRITTEN (1ULL << 62)
+-#define EXTENT_STATUS_DELAYED	(1ULL << 61)
+-#define EXTENT_STATUS_HOLE	(1ULL << 60)
++#define ES_SHIFT	60
++
++#define EXTENT_STATUS_WRITTEN	(1 << 3)
++#define EXTENT_STATUS_UNWRITTEN (1 << 2)
++#define EXTENT_STATUS_DELAYED	(1 << 1)
++#define EXTENT_STATUS_HOLE	(1 << 0)
+ 
+ #define EXTENT_STATUS_FLAGS	(EXTENT_STATUS_WRITTEN | \
+ 				 EXTENT_STATUS_UNWRITTEN | \
+ 				 EXTENT_STATUS_DELAYED | \
+ 				 EXTENT_STATUS_HOLE)
+ 
++#define ES_WRITTEN		(1ULL << 63)
++#define ES_UNWRITTEN		(1ULL << 62)
++#define ES_DELAYED		(1ULL << 61)
++#define ES_HOLE			(1ULL << 60)
++
++#define ES_MASK			(ES_WRITTEN | ES_UNWRITTEN | \
++				 ES_DELAYED | ES_HOLE)
++
+ struct ext4_sb_info;
+ struct ext4_extent;
+ 
+@@ -60,7 +70,7 @@ extern void ext4_es_init_tree(struct ext4_es_tree *tree);
+ 
+ extern int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
+ 				 ext4_lblk_t len, ext4_fsblk_t pblk,
+-				 unsigned long long status);
++				 unsigned int status);
+ extern int ext4_es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
+ 				 ext4_lblk_t len);
+ extern void ext4_es_find_delayed_extent_range(struct inode *inode,
+@@ -72,32 +82,32 @@ extern int ext4_es_zeroout(struct inode *inode, struct ext4_extent *ex);
+ 
+ static inline int ext4_es_is_written(struct extent_status *es)
+ {
+-	return (es->es_pblk & EXTENT_STATUS_WRITTEN) != 0;
++	return (es->es_pblk & ES_WRITTEN) != 0;
+ }
+ 
+ static inline int ext4_es_is_unwritten(struct extent_status *es)
+ {
+-	return (es->es_pblk & EXTENT_STATUS_UNWRITTEN) != 0;
++	return (es->es_pblk & ES_UNWRITTEN) != 0;
+ }
+ 
+ static inline int ext4_es_is_delayed(struct extent_status *es)
+ {
+-	return (es->es_pblk & EXTENT_STATUS_DELAYED) != 0;
++	return (es->es_pblk & ES_DELAYED) != 0;
+ }
+ 
+ static inline int ext4_es_is_hole(struct extent_status *es)
+ {
+-	return (es->es_pblk & EXTENT_STATUS_HOLE) != 0;
++	return (es->es_pblk & ES_HOLE) != 0;
+ }
+ 
+-static inline ext4_fsblk_t ext4_es_status(struct extent_status *es)
++static inline unsigned int ext4_es_status(struct extent_status *es)
+ {
+-	return (es->es_pblk & EXTENT_STATUS_FLAGS);
++	return es->es_pblk >> ES_SHIFT;
+ }
+ 
+ static inline ext4_fsblk_t ext4_es_pblock(struct extent_status *es)
+ {
+-	return (es->es_pblk & ~EXTENT_STATUS_FLAGS);
++	return es->es_pblk & ~ES_MASK;
+ }
+ 
+ static inline void ext4_es_store_pblock(struct extent_status *es,
+@@ -105,19 +115,16 @@ static inline void ext4_es_store_pblock(struct extent_status *es,
+ {
+ 	ext4_fsblk_t block;
+ 
+-	block = (pb & ~EXTENT_STATUS_FLAGS) |
+-		(es->es_pblk & EXTENT_STATUS_FLAGS);
++	block = (pb & ~ES_MASK) | (es->es_pblk & ES_MASK);
+ 	es->es_pblk = block;
+ }
+ 
+ static inline void ext4_es_store_status(struct extent_status *es,
+-					unsigned long long status)
++					unsigned int status)
+ {
+-	ext4_fsblk_t block;
+-
+-	block = (status & EXTENT_STATUS_FLAGS) |
+-		(es->es_pblk & ~EXTENT_STATUS_FLAGS);
+-	es->es_pblk = block;
++	es->es_pblk = (((ext4_fsblk_t)
++			(status & EXTENT_STATUS_FLAGS) << ES_SHIFT) |
++		       (es->es_pblk & ~ES_MASK));
+ }
+ 
+ extern void ext4_es_register_shrinker(struct ext4_sb_info *sbi);
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index c2ca04e67a4f..0569c745475c 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -553,7 +553,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
+ 	}
+ 	if (retval > 0) {
+ 		int ret;
+-		unsigned long long status;
++		unsigned int status;
+ 
+ 		if (unlikely(retval != map->m_len)) {
+ 			ext4_warning(inode->i_sb,
+@@ -653,7 +653,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
+ 
+ 	if (retval > 0) {
+ 		int ret;
+-		unsigned long long status;
++		unsigned int status;
+ 
+ 		if (unlikely(retval != map->m_len)) {
+ 			ext4_warning(inode->i_sb,
+@@ -1633,7 +1633,7 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
+ 		set_buffer_delay(bh);
+ 	} else if (retval > 0) {
+ 		int ret;
+-		unsigned long long status;
++		unsigned int status;
+ 
+ 		if (unlikely(retval != map->m_len)) {
+ 			ext4_warning(inode->i_sb,
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index 2068db241f22..47a355b251e4 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -64,10 +64,10 @@ struct extent_status;
+ 	{ EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER,	"LAST_CLUSTER" })
+ 
+ #define show_extent_status(status) __print_flags(status, "",	\
+-	{ (1 << 3),	"W" }, 					\
+-	{ (1 << 2),	"U" },					\
+-	{ (1 << 1),	"D" },					\
+-	{ (1 << 0),	"H" })
++	{ EXTENT_STATUS_WRITTEN,	"W" },			\
++	{ EXTENT_STATUS_UNWRITTEN,	"U" },			\
++	{ EXTENT_STATUS_DELAYED,	"D" },			\
++	{ EXTENT_STATUS_HOLE,		"H" })
+ 
+ 
+ TRACE_EVENT(ext4_free_inode,
+@@ -2212,7 +2212,7 @@ TRACE_EVENT(ext4_es_insert_extent,
+ 		__entry->lblk	= es->es_lblk;
+ 		__entry->len	= es->es_len;
+ 		__entry->pblk	= ext4_es_pblock(es);
+-		__entry->status	= ext4_es_status(es) >> 60;
++		__entry->status	= ext4_es_status(es);
+ 	),
+ 
+ 	TP_printk("dev %d,%d ino %lu es [%u/%u) mapped %llu status %s",
+@@ -2289,7 +2289,7 @@ TRACE_EVENT(ext4_es_find_delayed_extent_range_exit,
+ 		__entry->lblk	= es->es_lblk;
+ 		__entry->len	= es->es_len;
+ 		__entry->pblk	= ext4_es_pblock(es);
+-		__entry->status	= ext4_es_status(es) >> 60;
++		__entry->status	= ext4_es_status(es);
+ 	),
+ 
+ 	TP_printk("dev %d,%d ino %lu es [%u/%u) mapped %llu status %s",
+@@ -2343,7 +2343,7 @@ TRACE_EVENT(ext4_es_lookup_extent_exit,
+ 		__entry->lblk	= es->es_lblk;
+ 		__entry->len	= es->es_len;
+ 		__entry->pblk	= ext4_es_pblock(es);
+-		__entry->status	= ext4_es_status(es) >> 60;
++		__entry->status	= ext4_es_status(es);
+ 		__entry->found	= found;
+ 	),
+ 

commit c349179b4808f7c8e1ff1b4dd967c047eefd24bc
+Author: Theodore Ts'o 
+Date:   Fri Aug 16 21:21:41 2013 -0400
+
+    ext4: print the block number of invalid extent tree blocks
+    
+    When we find an invalid extent tree block, report the block number of
+    the bad block for debugging purposes.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Zheng Liu 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index a40be59ddce6..6e7b7d928f4a 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -407,7 +407,7 @@ static int ext4_valid_extent_entries(struct inode *inode,
+ 
+ static int __ext4_ext_check(const char *function, unsigned int line,
+ 			    struct inode *inode, struct ext4_extent_header *eh,
+-			    int depth)
++			    int depth, ext4_fsblk_t pblk)
+ {
+ 	const char *error_msg;
+ 	int max = 0;
+@@ -447,21 +447,21 @@ static int __ext4_ext_check(const char *function, unsigned int line,
+ 
+ corrupted:
+ 	ext4_error_inode(inode, function, line, 0,
+-			"bad header/extent: %s - magic %x, "
+-			"entries %u, max %u(%u), depth %u(%u)",
+-			error_msg, le16_to_cpu(eh->eh_magic),
+-			le16_to_cpu(eh->eh_entries), le16_to_cpu(eh->eh_max),
+-			max, le16_to_cpu(eh->eh_depth), depth);
+-
++			 "pblk %llu bad header/extent: %s - magic %x, "
++			 "entries %u, max %u(%u), depth %u(%u)",
++			 (unsigned long long) pblk, error_msg,
++			 le16_to_cpu(eh->eh_magic),
++			 le16_to_cpu(eh->eh_entries), le16_to_cpu(eh->eh_max),
++			 max, le16_to_cpu(eh->eh_depth), depth);
+ 	return -EIO;
+ }
+ 
+-#define ext4_ext_check(inode, eh, depth)	\
+-	__ext4_ext_check(__func__, __LINE__, inode, eh, depth)
++#define ext4_ext_check(inode, eh, depth, pblk)			\
++	__ext4_ext_check(__func__, __LINE__, (inode), (eh), (depth), (pblk))
+ 
+ int ext4_ext_check_inode(struct inode *inode)
+ {
+-	return ext4_ext_check(inode, ext_inode_hdr(inode), ext_depth(inode));
++	return ext4_ext_check(inode, ext_inode_hdr(inode), ext_depth(inode), 0);
+ }
+ 
+ static struct buffer_head *
+@@ -484,7 +484,7 @@ __read_extent_tree_block(const char *function, unsigned int line,
+ 	if (buffer_verified(bh))
+ 		return bh;
+ 	err = __ext4_ext_check(function, line, inode,
+-			       ext_block_hdr(bh), depth);
++			       ext_block_hdr(bh), depth, pblk);
+ 	if (err)
+ 		goto errout;
+ 	set_buffer_verified(bh);
+@@ -2775,7 +2775,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
+ 		path[0].p_hdr = ext_inode_hdr(inode);
+ 		i = 0;
+ 
+-		if (ext4_ext_check(inode, path[0].p_hdr, depth)) {
++		if (ext4_ext_check(inode, path[0].p_hdr, depth, 0)) {
+ 			err = -EIO;
+ 			goto out;
+ 		}

commit 7d7ea89e756ea18a3b08cd396e2a4c0c12d473a8
+Author: Theodore Ts'o 
+Date:   Fri Aug 16 21:20:41 2013 -0400
+
+    ext4: refactor code to read the extent tree block
+    
+    Refactor out the code needed to read the extent tree block into a
+    single read_extent_tree_block() function.  In addition to simplifying
+    the code, it also makes sure that we call the ext4_ext_load_extent
+    tracepoint whenever we need to read an extent tree block from disk.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Zheng Liu 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 72ba4705d4fa..a40be59ddce6 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -464,25 +464,39 @@ int ext4_ext_check_inode(struct inode *inode)
+ 	return ext4_ext_check(inode, ext_inode_hdr(inode), ext_depth(inode));
+ }
+ 
+-static int __ext4_ext_check_block(const char *function, unsigned int line,
+-				  struct inode *inode,
+-				  struct ext4_extent_header *eh,
+-				  int depth,
+-				  struct buffer_head *bh)
++static struct buffer_head *
++__read_extent_tree_block(const char *function, unsigned int line,
++			 struct inode *inode, ext4_fsblk_t pblk, int depth)
+ {
+-	int ret;
++	struct buffer_head		*bh;
++	int				err;
+ 
++	bh = sb_getblk(inode->i_sb, pblk);
++	if (unlikely(!bh))
++		return ERR_PTR(-ENOMEM);
++
++	if (!bh_uptodate_or_lock(bh)) {
++		trace_ext4_ext_load_extent(inode, pblk, _RET_IP_);
++		err = bh_submit_read(bh);
++		if (err < 0)
++			goto errout;
++	}
+ 	if (buffer_verified(bh))
+-		return 0;
+-	ret = ext4_ext_check(inode, eh, depth);
+-	if (ret)
+-		return ret;
++		return bh;
++	err = __ext4_ext_check(function, line, inode,
++			       ext_block_hdr(bh), depth);
++	if (err)
++		goto errout;
+ 	set_buffer_verified(bh);
+-	return ret;
++	return bh;
++errout:
++	put_bh(bh);
++	return ERR_PTR(err);
++
+ }
+ 
+-#define ext4_ext_check_block(inode, eh, depth, bh)	\
+-	__ext4_ext_check_block(__func__, __LINE__, inode, eh, depth, bh)
++#define read_extent_tree_block(inode, pblk, depth)		\
++	__read_extent_tree_block(__func__, __LINE__, (inode), (pblk), (depth))
+ 
+ #ifdef EXT_DEBUG
+ static void ext4_ext_show_path(struct inode *inode, struct ext4_ext_path *path)
+@@ -748,20 +762,12 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
+ 		path[ppos].p_depth = i;
+ 		path[ppos].p_ext = NULL;
+ 
+-		bh = sb_getblk(inode->i_sb, path[ppos].p_block);
+-		if (unlikely(!bh)) {
+-			ret = -ENOMEM;
++		bh = read_extent_tree_block(inode, path[ppos].p_block, --i);
++		if (IS_ERR(bh)) {
++			ret = PTR_ERR(bh);
+ 			goto err;
+ 		}
+-		if (!bh_uptodate_or_lock(bh)) {
+-			trace_ext4_ext_load_extent(inode, block,
+-						path[ppos].p_block);
+-			ret = bh_submit_read(bh);
+-			if (ret < 0) {
+-				put_bh(bh);
+-				goto err;
+-			}
+-		}
++
+ 		eh = ext_block_hdr(bh);
+ 		ppos++;
+ 		if (unlikely(ppos > depth)) {
+@@ -773,11 +779,6 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
+ 		}
+ 		path[ppos].p_bh = bh;
+ 		path[ppos].p_hdr = eh;
+-		i--;
+-
+-		ret = ext4_ext_check_block(inode, eh, i, bh);
+-		if (ret < 0)
+-			goto err;
+ 	}
+ 
+ 	path[ppos].p_depth = i;
+@@ -1412,29 +1413,21 @@ static int ext4_ext_search_right(struct inode *inode,
+ 	ix++;
+ 	block = ext4_idx_pblock(ix);
+ 	while (++depth < path->p_depth) {
+-		bh = sb_bread(inode->i_sb, block);
+-		if (bh == NULL)
+-			return -EIO;
+-		eh = ext_block_hdr(bh);
+ 		/* subtract from p_depth to get proper eh_depth */
+-		if (ext4_ext_check_block(inode, eh,
+-					 path->p_depth - depth, bh)) {
+-			put_bh(bh);
+-			return -EIO;
+-		}
++		bh = read_extent_tree_block(inode, block,
++					    path->p_depth - depth);
++		if (IS_ERR(bh))
++			return PTR_ERR(bh);
++		eh = ext_block_hdr(bh);
+ 		ix = EXT_FIRST_INDEX(eh);
+ 		block = ext4_idx_pblock(ix);
+ 		put_bh(bh);
+ 	}
+ 
+-	bh = sb_bread(inode->i_sb, block);
+-	if (bh == NULL)
+-		return -EIO;
++	bh = read_extent_tree_block(inode, block, path->p_depth - depth);
++	if (IS_ERR(bh))
++		return PTR_ERR(bh);
+ 	eh = ext_block_hdr(bh);
+-	if (ext4_ext_check_block(inode, eh, path->p_depth - depth, bh)) {
+-		put_bh(bh);
+-		return -EIO;
+-	}
+ 	ex = EXT_FIRST_EXTENT(eh);
+ found_extent:
+ 	*logical = le32_to_cpu(ex->ee_block);
+@@ -2829,10 +2822,11 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
+ 			ext_debug("move to level %d (block %llu)\n",
+ 				  i + 1, ext4_idx_pblock(path[i].p_idx));
+ 			memset(path + i + 1, 0, sizeof(*path));
+-			bh = sb_bread(sb, ext4_idx_pblock(path[i].p_idx));
+-			if (!bh) {
++			bh = read_extent_tree_block(inode,
++				ext4_idx_pblock(path[i].p_idx), depth - i - 1);
++			if (IS_ERR(bh)) {
+ 				/* should we reset i_size? */
+-				err = -EIO;
++				err = PTR_ERR(bh);
+ 				break;
+ 			}
+ 			/* Yield here to deal with large extent trees.
+@@ -2842,11 +2836,6 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
+ 				err = -EIO;
+ 				break;
+ 			}
+-			if (ext4_ext_check_block(inode, ext_block_hdr(bh),
+-							depth - i - 1, bh)) {
+-				err = -EIO;
+-				break;
+-			}
+ 			path[i + 1].p_bh = bh;
+ 
+ 			/* save actual number of indexes since this

commit cde2d7a796f7e895e25b43471ed658079345636d
+Author: Theodore Ts'o 
+Date:   Mon Aug 12 09:29:30 2013 -0400
+
+    ext4: flush the extent status cache during EXT4_IOC_SWAP_BOOT
+    
+    Previously we weren't swapping only some of the extent_status LRU
+    fields during the processing of the EXT4_IOC_SWAP_BOOT ioctl.  The
+    much safer thing to do is to just completely flush the extent status
+    tree when doing the swap.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Zheng Liu 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index 9491ac0590f7..c0427e2f6648 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -77,8 +77,10 @@ static void swap_inode_data(struct inode *inode1, struct inode *inode2)
+ 	memswap(ei1->i_data, ei2->i_data, sizeof(ei1->i_data));
+ 	memswap(&ei1->i_flags, &ei2->i_flags, sizeof(ei1->i_flags));
+ 	memswap(&ei1->i_disksize, &ei2->i_disksize, sizeof(ei1->i_disksize));
+-	memswap(&ei1->i_es_tree, &ei2->i_es_tree, sizeof(ei1->i_es_tree));
+-	memswap(&ei1->i_es_lru_nr, &ei2->i_es_lru_nr, sizeof(ei1->i_es_lru_nr));
++	ext4_es_remove_extent(inode1, 0, EXT_MAX_BLOCKS);
++	ext4_es_remove_extent(inode2, 0, EXT_MAX_BLOCKS);
++	ext4_es_lru_del(inode1);
++	ext4_es_lru_del(inode2);
+ 
+ 	isize = i_size_read(inode1);
+ 	i_size_write(inode1, i_size_read(inode2));

commit 59d9fa5c2e9086db11aa287bb4030151d0095a17
+Author: Theodore Ts'o 
+Date:   Thu Aug 8 23:01:24 2013 -0400
+
+    ext4: allow the mount options nodelalloc and data=journal
+    
+    Commit 26092bf ("ext4: use a table-driven handler for mount options")
+    wrongly disallows the specifying the mount options nodelalloc and
+    data=journal simultaneously.  This is incorrect; it should have only
+    disallowed the combination of delalloc and data=journal
+    simultaneously.
+    
+    Reported-by: Piotr Sarna 
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 36b141e420b7..75b3708b778e 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1359,7 +1359,7 @@ static const struct mount_opts {
+ 	{Opt_delalloc, EXT4_MOUNT_DELALLOC,
+ 	 MOPT_EXT4_ONLY | MOPT_SET | MOPT_EXPLICIT},
+ 	{Opt_nodelalloc, EXT4_MOUNT_DELALLOC,
+-	 MOPT_EXT4_ONLY | MOPT_CLEAR | MOPT_EXPLICIT},
++	 MOPT_EXT4_ONLY | MOPT_CLEAR},
+ 	{Opt_journal_checksum, EXT4_MOUNT_JOURNAL_CHECKSUM,
+ 	 MOPT_EXT4_ONLY | MOPT_SET},
+ 	{Opt_journal_async_commit, (EXT4_MOUNT_JOURNAL_ASYNC_COMMIT |

commit 94eec0fc3520c759831763d866421b4d60b599b4
+Author: Theodore Ts'o 
+Date:   Mon Jul 29 12:12:56 2013 -0400
+
+    ext4: fix retry handling in ext4_ext_truncate()
+    
+    We tested for ENOMEM instead of -ENOMEM.   Oops.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index a61873808f76..72ba4705d4fa 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -4412,7 +4412,7 @@ void ext4_ext_truncate(handle_t *handle, struct inode *inode)
+ retry:
+ 	err = ext4_es_remove_extent(inode, last_block,
+ 				    EXT_MAX_BLOCKS - last_block);
+-	if (err == ENOMEM) {
++	if (err == -ENOMEM) {
+ 		cond_resched();
+ 		congestion_wait(BLK_RW_ASYNC, HZ/50);
+ 		goto retry;

commit a34eb503742fd25155fd6cff6163daacead9fbc3
+Author: Theodore Ts'o 
+Date:   Fri Jul 26 15:15:46 2013 -0400
+
+    ext4: make sure group number is bumped after a inode allocation race
+    
+    When we try to allocate an inode, and there is a race between two
+    CPU's trying to grab the same inode, _and_ this inode is the last free
+    inode in the block group, make sure the group number is bumped before
+    we continue searching the rest of the block groups.  Otherwise, we end
+    up searching the current block group twice, and we end up skipping
+    searching the last block group.  So in the unlikely situation where
+    almost all of the inodes are allocated, it's possible that we will
+    return ENOSPC even though there might be free inodes in that last
+    block group.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index f03598c6ffd3..8bf5999875ee 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -734,11 +734,8 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
+ 		ino = ext4_find_next_zero_bit((unsigned long *)
+ 					      inode_bitmap_bh->b_data,
+ 					      EXT4_INODES_PER_GROUP(sb), ino);
+-		if (ino >= EXT4_INODES_PER_GROUP(sb)) {
+-			if (++group == ngroups)
+-				group = 0;
+-			continue;
+-		}
++		if (ino >= EXT4_INODES_PER_GROUP(sb))
++			goto next_group;
+ 		if (group == 0 && (ino+1) < EXT4_FIRST_INO(sb)) {
+ 			ext4_error(sb, "reserved inode found cleared - "
+ 				   "inode=%lu", ino + 1);
+@@ -769,6 +766,9 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
+ 			goto got; /* we grabbed the inode! */
+ 		if (ino < EXT4_INODES_PER_GROUP(sb))
+ 			goto repeat_in_this_group;
++next_group:
++		if (++group == ngroups)
++			group = 0;
+ 	}
+ 	err = -ENOSPC;
+ 	goto out;

commit 63b999685cb372e24eb73f255cd73547026370fd
+Author: Theodore Ts'o 
+Date:   Tue Jul 16 10:28:47 2013 -0400
+
+    ext4: call ext4_es_lru_add() after handling cache miss
+    
+    If there are no items in the extent status tree, ext4_es_lru_add() is
+    a no-op.  So it is not sufficient to call ext4_es_lru_add() before we
+    try to lookup an entry in the extent status tree.  We also need to
+    call it at the end of ext4_ext_map_blocks(), after items have been
+    added to the extent status tree.
+    
+    This could lead to inodes with that have extent status trees but which
+    are not in the LRU list, which means they won't get considered for
+    eviction by the es_shrinker.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Zheng Liu 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index cfdc51e30257..a61873808f76 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -4385,8 +4385,9 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 	}
+ 
+ out3:
+-	trace_ext4_ext_map_blocks_exit(inode, flags, map, err ? err : allocated);
+-
++	trace_ext4_ext_map_blocks_exit(inode, flags, map,
++				       err ? err : allocated);
++	ext4_es_lru_add(inode);
+ 	return err ? err : allocated;
+ }
+ 
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 98b9bff92a8a..ba33c67d6e48 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -514,10 +514,9 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
+ 		  "logical block %lu\n", inode->i_ino, flags, map->m_len,
+ 		  (unsigned long) map->m_lblk);
+ 
+-	ext4_es_lru_add(inode);
+-
+ 	/* Lookup extent status tree firstly */
+ 	if (ext4_es_lookup_extent(inode, map->m_lblk, &es)) {
++		ext4_es_lru_add(inode);
+ 		if (ext4_es_is_written(&es) || ext4_es_is_unwritten(&es)) {
+ 			map->m_pblk = ext4_es_pblock(&es) +
+ 					map->m_lblk - es.es_lblk;
+@@ -1529,11 +1528,9 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
+ 		  "logical block %lu\n", inode->i_ino, map->m_len,
+ 		  (unsigned long) map->m_lblk);
+ 
+-	ext4_es_lru_add(inode);
+-
+ 	/* Lookup extent status tree firstly */
+ 	if (ext4_es_lookup_extent(inode, iblock, &es)) {
+-
++		ext4_es_lru_add(inode);
+ 		if (ext4_es_is_hole(&es)) {
+ 			retval = 0;
+ 			down_read((&EXT4_I(inode)->i_data_sem));

commit 76828c882630ced08b5ddce22cc0095b05de9bc5
+Author: Theodore Ts'o 
+Date:   Mon Jul 15 12:27:47 2013 -0400
+
+    ext4: yield during large unlinks
+    
+    During large unlink operations on files with extents, we can use a lot
+    of CPU time.  This adds a cond_resched() call when starting to examine
+    the next level of a multi-level extent tree.  Multi-level extent trees
+    are rare in the first place, and this should rarely be executed.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 593091537e76..cfdc51e30257 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -2835,6 +2835,9 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
+ 				err = -EIO;
+ 				break;
+ 			}
++			/* Yield here to deal with large extent trees.
++			 * Should be a no-op if we did IO above. */
++			cond_resched();
+ 			if (WARN_ON(i + 1 > depth)) {
+ 				err = -EIO;
+ 				break;

commit e15f742ce816076497549b955fbec3254820db85
+Author: Theodore Ts'o 
+Date:   Mon Jul 15 00:12:14 2013 -0400
+
+    ext4: make the extent_status code more robust against ENOMEM failures
+    
+    Some callers of ext4_es_remove_extent() and ext4_es_insert_extent()
+    may not be completely robust against ENOMEM failures (or the
+    consequences of reflecting ENOMEM back up to userspace may lead to
+    xfstest or user application failure).
+    
+    To mitigate against this, when trying to insert an entry in the extent
+    status tree, try to shrink the inode's extent status tree before
+    returning ENOMEM.  If there are entries which don't record information
+    about extents under delayed allocations, freeing one of them is
+    preferable to returning ENOMEM.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Zheng Liu 
+
+diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
+index 4b8df7fbb10a..91cb110da1b4 100644
+--- a/fs/ext4/extents_status.c
++++ b/fs/ext4/extents_status.c
+@@ -148,6 +148,8 @@ static int __es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
+ 			      ext4_lblk_t end);
+ static int __es_try_to_reclaim_extents(struct ext4_inode_info *ei,
+ 				       int nr_to_scan);
++static int __ext4_es_shrink(struct ext4_sb_info *sbi, int nr_to_scan,
++			    struct ext4_inode_info *locked_ei);
+ 
+ int __init ext4_init_es(void)
+ {
+@@ -665,7 +667,13 @@ int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
+ 	err = __es_remove_extent(inode, lblk, end);
+ 	if (err != 0)
+ 		goto error;
++retry:
+ 	err = __es_insert_extent(inode, &newes);
++	if (err == -ENOMEM && __ext4_es_shrink(EXT4_SB(inode->i_sb), 1,
++					       EXT4_I(inode)))
++		goto retry;
++	if (err == -ENOMEM && !ext4_es_is_delayed(&newes))
++		err = 0;
+ 
+ error:
+ 	write_unlock(&EXT4_I(inode)->i_es_lock);
+@@ -744,8 +752,10 @@ static int __es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
+ 	struct extent_status orig_es;
+ 	ext4_lblk_t len1, len2;
+ 	ext4_fsblk_t block;
+-	int err = 0;
++	int err;
+ 
++retry:
++	err = 0;
+ 	es = __es_tree_search(&tree->root, lblk);
+ 	if (!es)
+ 		goto out;
+@@ -780,6 +790,10 @@ static int __es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
+ 			if (err) {
+ 				es->es_lblk = orig_es.es_lblk;
+ 				es->es_len = orig_es.es_len;
++				if ((err == -ENOMEM) &&
++				    __ext4_es_shrink(EXT4_SB(inode->i_sb), 1,
++						     EXT4_I(inode)))
++					goto retry;
+ 				goto out;
+ 			}
+ 		} else {
+@@ -889,22 +903,14 @@ static int ext4_inode_touch_time_cmp(void *priv, struct list_head *a,
+ 		return -1;
+ }
+ 
+-static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc)
++static int __ext4_es_shrink(struct ext4_sb_info *sbi, int nr_to_scan,
++			    struct ext4_inode_info *locked_ei)
+ {
+-	struct ext4_sb_info *sbi = container_of(shrink,
+-					struct ext4_sb_info, s_es_shrinker);
+ 	struct ext4_inode_info *ei;
+ 	struct list_head *cur, *tmp;
+ 	LIST_HEAD(skiped);
+-	int nr_to_scan = sc->nr_to_scan;
+ 	int ret, nr_shrunk = 0;
+ 
+-	ret = percpu_counter_read_positive(&sbi->s_extent_cache_cnt);
+-	trace_ext4_es_shrink_enter(sbi->s_sb, nr_to_scan, ret);
+-
+-	if (!nr_to_scan)
+-		return ret;
+-
+ 	spin_lock(&sbi->s_es_lru_lock);
+ 
+ 	/*
+@@ -933,7 +939,7 @@ static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc)
+ 			continue;
+ 		}
+ 
+-		if (ei->i_es_lru_nr == 0)
++		if (ei->i_es_lru_nr == 0 || ei == locked_ei)
+ 			continue;
+ 
+ 		write_lock(&ei->i_es_lock);
+@@ -952,6 +958,27 @@ static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc)
+ 	list_splice_tail(&skiped, &sbi->s_es_lru);
+ 	spin_unlock(&sbi->s_es_lru_lock);
+ 
++	if (locked_ei && nr_shrunk == 0)
++		nr_shrunk = __es_try_to_reclaim_extents(ei, nr_to_scan);
++
++	return nr_shrunk;
++}
++
++static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc)
++{
++	struct ext4_sb_info *sbi = container_of(shrink,
++					struct ext4_sb_info, s_es_shrinker);
++	int nr_to_scan = sc->nr_to_scan;
++	int ret, nr_shrunk;
++
++	ret = percpu_counter_read_positive(&sbi->s_extent_cache_cnt);
++	trace_ext4_es_shrink_enter(sbi->s_sb, nr_to_scan, ret);
++
++	if (!nr_to_scan)
++		return ret;
++
++	nr_shrunk = __ext4_es_shrink(sbi, nr_to_scan, NULL);
++
+ 	ret = percpu_counter_read_positive(&sbi->s_extent_cache_cnt);
+ 	trace_ext4_es_shrink_exit(sbi->s_sb, nr_shrunk, ret);
+ 	return ret;

commit c8e15130e1636f68d5165aa2605b8e9cba0f644c
+Author: Theodore Ts'o 
+Date:   Mon Jul 15 00:09:37 2013 -0400
+
+    ext4: simplify calculation of blocks to free on error
+    
+    In ext4_ext_map_blocks(), if we have successfully allocated the data
+    blocks, but then run into trouble inserting the extent into the extent
+    tree, most likely due to an ENOSPC condition, determine the arguments
+    to ext4_free_blocks() in a simpler way which is easier to prove to be
+    correct.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index f57cc0e7f1bc..593091537e76 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -4261,8 +4261,8 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 		/* not a good idea to call discard here directly,
+ 		 * but otherwise we'd need to call it every free() */
+ 		ext4_discard_preallocations(inode);
+-		ext4_free_blocks(handle, inode, NULL, ext4_ext_pblock(&newex),
+-				 ext4_ext_get_actual_len(&newex), fb_flags);
++		ext4_free_blocks(handle, inode, NULL, newblock,
++				 EXT4_C2B(sbi, allocated_clusters), fb_flags);
+ 		goto out2;
+ 	}
+ 

commit 8acd5e9b1217e58a57124d9e225afa12efeae20d
+Author: Theodore Ts'o 
+Date:   Mon Jul 15 00:09:19 2013 -0400
+
+    ext4: fix error handling in ext4_ext_truncate()
+    
+    Previously ext4_ext_truncate() was ignoring potential error returns
+    from ext4_es_remove_extent() and ext4_ext_remove_space().  This can
+    lead to the on-diks extent tree and the extent status tree cache
+    getting out of sync, which is particuarlly bad, and can lead to file
+    system corruption and potential data loss.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 7097b0f680e6..f57cc0e7f1bc 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -4405,9 +4405,20 @@ void ext4_ext_truncate(handle_t *handle, struct inode *inode)
+ 
+ 	last_block = (inode->i_size + sb->s_blocksize - 1)
+ 			>> EXT4_BLOCK_SIZE_BITS(sb);
++retry:
+ 	err = ext4_es_remove_extent(inode, last_block,
+ 				    EXT_MAX_BLOCKS - last_block);
++	if (err == ENOMEM) {
++		cond_resched();
++		congestion_wait(BLK_RW_ASYNC, HZ/50);
++		goto retry;
++	}
++	if (err) {
++		ext4_std_error(inode->i_sb, err);
++		return;
++	}
+ 	err = ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCKS - 1);
++	ext4_std_error(inode->i_sb, err);
+ }
+ 
+ static void ext4_falloc_update_inode(struct inode *inode,

commit e7676a704ee0a1ef71a6b23760b5a8f6896cb1a1
+Author: Theodore Ts'o 
+Date:   Sat Jul 13 00:40:35 2013 -0400
+
+    ext4: don't allow ext4_free_blocks() to fail due to ENOMEM
+    
+    The filesystem should not be marked inconsistent if ext4_free_blocks()
+    is not able to allocate memory.  Unfortunately some callers (most
+    notably ext4_truncate) don't have a way to reflect an error back up to
+    the VFS.  And even if we did, most userspace applications won't deal
+    with most system calls returning ENOMEM anyway.
+    
+    Reported-by: Nagachandra P 
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index a9ff5e5137ca..4bbbf13bd743 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -4740,11 +4740,16 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 		 * blocks being freed are metadata. these blocks shouldn't
+ 		 * be used until this transaction is committed
+ 		 */
++	retry:
+ 		new_entry = kmem_cache_alloc(ext4_free_data_cachep, GFP_NOFS);
+ 		if (!new_entry) {
+-			ext4_mb_unload_buddy(&e4b);
+-			err = -ENOMEM;
+-			goto error_return;
++			/*
++			 * We use a retry loop because
++			 * ext4_free_blocks() is not allowed to fail.
++			 */
++			cond_resched();
++			congestion_wait(BLK_RW_ASYNC, HZ/50);
++			goto retry;
+ 		}
+ 		new_entry->efd_start_cluster = bit;
+ 		new_entry->efd_group = block_group;

commit bdafe42aaf72859166f784f0fad3e6b4a815fa6d
+Author: Theodore Ts'o 
+Date:   Sat Jul 13 00:40:31 2013 -0400
+
+    ext4: fix spelling errors and a comment in extent_status tree
+    
+    Replace "assertation" with "assertion" in lots and lots of debugging
+    messages.
+    
+    Correct the comment stating when ext4_es_insert_extent() is used.  It
+    was no doubt tree at one point, but it is no longer true...
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Zheng Liu 
+
+diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
+index ee018d5f397e..4b8df7fbb10a 100644
+--- a/fs/ext4/extents_status.c
++++ b/fs/ext4/extents_status.c
+@@ -439,7 +439,7 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode,
+ 		 */
+ 		if (!ext4_es_is_written(es) && !ext4_es_is_unwritten(es)) {
+ 			if (in_range(es->es_lblk, ee_block, ee_len)) {
+-				pr_warn("ES insert assertation failed for "
++				pr_warn("ES insert assertion failed for "
+ 					"inode: %lu we can find an extent "
+ 					"at block [%d/%d/%llu/%c], but we "
+ 					"want to add an delayed/hole extent "
+@@ -458,7 +458,7 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode,
+ 		 */
+ 		if (es->es_lblk < ee_block ||
+ 		    ext4_es_pblock(es) != ee_start + es->es_lblk - ee_block) {
+-			pr_warn("ES insert assertation failed for inode: %lu "
++			pr_warn("ES insert assertion failed for inode: %lu "
+ 				"ex_status [%d/%d/%llu/%c] != "
+ 				"es_status [%d/%d/%llu/%c]\n", inode->i_ino,
+ 				ee_block, ee_len, ee_start,
+@@ -468,7 +468,7 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode,
+ 		}
+ 
+ 		if (ee_status ^ es_status) {
+-			pr_warn("ES insert assertation failed for inode: %lu "
++			pr_warn("ES insert assertion failed for inode: %lu "
+ 				"ex_status [%d/%d/%llu/%c] != "
+ 				"es_status [%d/%d/%llu/%c]\n", inode->i_ino,
+ 				ee_block, ee_len, ee_start,
+@@ -481,7 +481,7 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode,
+ 		 * that we don't want to add an written/unwritten extent.
+ 		 */
+ 		if (!ext4_es_is_delayed(es) && !ext4_es_is_hole(es)) {
+-			pr_warn("ES insert assertation failed for inode: %lu "
++			pr_warn("ES insert assertion failed for inode: %lu "
+ 				"can't find an extent at block %d but we want "
+ 				"to add an written/unwritten extent "
+ 				"[%d/%d/%llu/%llx]\n", inode->i_ino,
+@@ -519,7 +519,7 @@ static void ext4_es_insert_extent_ind_check(struct inode *inode,
+ 			 * We want to add a delayed/hole extent but this
+ 			 * block has been allocated.
+ 			 */
+-			pr_warn("ES insert assertation failed for inode: %lu "
++			pr_warn("ES insert assertion failed for inode: %lu "
+ 				"We can find blocks but we want to add a "
+ 				"delayed/hole extent [%d/%d/%llu/%llx]\n",
+ 				inode->i_ino, es->es_lblk, es->es_len,
+@@ -527,13 +527,13 @@ static void ext4_es_insert_extent_ind_check(struct inode *inode,
+ 			return;
+ 		} else if (ext4_es_is_written(es)) {
+ 			if (retval != es->es_len) {
+-				pr_warn("ES insert assertation failed for "
++				pr_warn("ES insert assertion failed for "
+ 					"inode: %lu retval %d != es_len %d\n",
+ 					inode->i_ino, retval, es->es_len);
+ 				return;
+ 			}
+ 			if (map.m_pblk != ext4_es_pblock(es)) {
+-				pr_warn("ES insert assertation failed for "
++				pr_warn("ES insert assertion failed for "
+ 					"inode: %lu m_pblk %llu != "
+ 					"es_pblk %llu\n",
+ 					inode->i_ino, map.m_pblk,
+@@ -549,7 +549,7 @@ static void ext4_es_insert_extent_ind_check(struct inode *inode,
+ 		}
+ 	} else if (retval == 0) {
+ 		if (ext4_es_is_written(es)) {
+-			pr_warn("ES insert assertation failed for inode: %lu "
++			pr_warn("ES insert assertion failed for inode: %lu "
+ 				"We can't find the block but we want to add "
+ 				"an written extent [%d/%d/%llu/%llx]\n",
+ 				inode->i_ino, es->es_lblk, es->es_len,
+@@ -632,10 +632,8 @@ static int __es_insert_extent(struct inode *inode, struct extent_status *newes)
+ }
+ 
+ /*
+- * ext4_es_insert_extent() adds a space to a extent status tree.
+- *
+- * ext4_es_insert_extent is called by ext4_da_write_begin and
+- * ext4_es_remove_extent.
++ * ext4_es_insert_extent() adds information to an inode's extent
++ * status tree.
+  *
+  * Return 0 on success, error code on failure.
+  */
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 19a1643cbdfa..98b9bff92a8a 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -465,7 +465,7 @@ static void ext4_map_blocks_es_recheck(handle_t *handle,
+ 	if (es_map->m_lblk != map->m_lblk ||
+ 	    es_map->m_flags != map->m_flags ||
+ 	    es_map->m_pblk != map->m_pblk) {
+-		printk("ES cache assertation failed for inode: %lu "
++		printk("ES cache assertion failed for inode: %lu "
+ 		       "es_cached ex [%d/%d/%llu/%x] != "
+ 		       "found ex [%d/%d/%llu/%x] retval %d flags %x\n",
+ 		       inode->i_ino, es_map->m_lblk, es_map->m_len,
+@@ -558,7 +558,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
+ 
+ #ifdef ES_AGGRESSIVE_TEST
+ 		if (retval != map->m_len) {
+-			printk("ES len assertation failed for inode: %lu "
++			printk("ES len assertion failed for inode: %lu "
+ 			       "retval %d != map->m_len %d "
+ 			       "in %s (lookup)\n", inode->i_ino, retval,
+ 			       map->m_len, __func__);
+@@ -659,7 +659,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
+ 
+ #ifdef ES_AGGRESSIVE_TEST
+ 		if (retval != map->m_len) {
+-			printk("ES len assertation failed for inode: %lu "
++			printk("ES len assertion failed for inode: %lu "
+ 			       "retval %d != map->m_len %d "
+ 			       "in %s (allocation)\n", inode->i_ino, retval,
+ 			       map->m_len, __func__);
+@@ -1642,7 +1642,7 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
+ 
+ #ifdef ES_AGGRESSIVE_TEST
+ 		if (retval != map->m_len) {
+-			printk("ES len assertation failed for inode: %lu "
++			printk("ES len assertion failed for inode: %lu "
+ 			       "retval %d != map->m_len %d "
+ 			       "in %s (lookup)\n", inode->i_ino, retval,
+ 			       map->m_len, __func__);

commit ad065dd01662ae22138899e6b1c8eeb3a529964f
+Author: Theodore Ts'o 
+Date:   Thu Jul 11 18:54:37 2013 -0400
+
+    ext4: don't show usrquota/grpquota twice in /proc/mounts
+    
+    We now print mount options in a generic fashion in
+    ext4_show_options(), so we shouldn't be explicitly printing the
+    {usr,grp}quota options in ext4_show_quota_options().
+    
+    Without this patch, /proc/mounts can look like this:
+    
+     /dev/vdb /vdb ext4 rw,relatime,quota,usrquota,data=ordered,usrquota 0 0
+                                          ^^^^^^^^              ^^^^^^^^
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 8862d4ddf71f..bca26f34edf4 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1702,12 +1702,6 @@ static inline void ext4_show_quota_options(struct seq_file *seq,
+ 
+ 	if (sbi->s_qf_names[GRPQUOTA])
+ 		seq_printf(seq, ",grpjquota=%s", sbi->s_qf_names[GRPQUOTA]);
+-
+-	if (test_opt(sb, USRQUOTA))
+-		seq_puts(seq, ",usrquota");
+-
+-	if (test_opt(sb, GRPQUOTA))
+-		seq_puts(seq, ",grpquota");
+ #endif
+ }
+ 

commit 960fd856fdc3b08b3638f3f9b6b4bfceb77660c7
+Author: Theodore Ts'o 
+Date:   Fri Jul 5 23:11:16 2013 -0400
+
+    ext4: fix ext4_get_group_number()
+    
+    The function ext4_get_group_number() was introduced as an optimization
+    in commit bd86298e60b8.  Unfortunately, this commit incorrectly
+    calculate the group number for file systems with a 1k block size (when
+    s_first_data_block is 1 instead of zero).  This could cause the
+    following kernel BUG:
+    
+    [  568.877799] ------------[ cut here ]------------
+    [  568.877833] kernel BUG at fs/ext4/mballoc.c:3728!
+    [  568.877840] Oops: Exception in kernel mode, sig: 5 [#1]
+    [  568.877845] SMP NR_CPUS=32 NUMA pSeries
+    [  568.877852] Modules linked in: binfmt_misc
+    [  568.877861] CPU: 1 PID: 3516 Comm: fs_mark Not tainted 3.10.0-03216-g7c6809f-dirty #1
+    [  568.877867] task: c0000001fb0b8000 ti: c0000001fa954000 task.ti: c0000001fa954000
+    [  568.877873] NIP: c0000000002f42a4 LR: c0000000002f4274 CTR: c000000000317ef8
+    [  568.877879] REGS: c0000001fa956ed0 TRAP: 0700   Not tainted  (3.10.0-03216-g7c6809f-dirty)
+    [  568.877884] MSR: 8000000000029032   CR: 24000428  XER: 00000000
+    [  568.877902] SOFTE: 1
+    [  568.877905] CFAR: c0000000002b5464
+    [  568.877908]
+    GPR00: 0000000000000001 c0000001fa957150 c000000000c6a408 c0000001fb588000
+    GPR04: 0000000000003fff c0000001fa9571c0 c0000001fa9571c4 000138098c50625f
+    GPR08: 1301200000000000 0000000000000002 0000000000000001 0000000000000000
+    GPR12: 0000000024000422 c00000000f33a300 0000000000008000 c0000001fa9577f0
+    GPR16: c0000001fb7d0100 c000000000c29190 c0000000007f46e8 c000000000a14672
+    GPR20: 0000000000000001 0000000000000008 ffffffffffffffff 0000000000000000
+    GPR24: 0000000000000100 c0000001fa957278 c0000001fdb2bc78 c0000001fa957288
+    GPR28: 0000000000100100 c0000001fa957288 c0000001fb588000 c0000001fdb2bd10
+    [  568.877993] NIP [c0000000002f42a4] .ext4_mb_release_group_pa+0xec/0x1c0
+    [  568.877999] LR [c0000000002f4274] .ext4_mb_release_group_pa+0xbc/0x1c0
+    [  568.878004] Call Trace:
+    [  568.878008] [c0000001fa957150] [c0000000002f4274] .ext4_mb_release_group_pa+0xbc/0x1c0 (unreliable)
+    [  568.878017] [c0000001fa957200] [c0000000002fb070] .ext4_mb_discard_lg_preallocations+0x394/0x444
+    [  568.878025] [c0000001fa957340] [c0000000002fb45c] .ext4_mb_release_context+0x33c/0x734
+    [  568.878032] [c0000001fa957440] [c0000000002fbcf8] .ext4_mb_new_blocks+0x4a4/0x5f4
+    [  568.878039] [c0000001fa957510] [c0000000002ef56c] .ext4_ext_map_blocks+0xc28/0x1178
+    [  568.878047] [c0000001fa957640] [c0000000002c1a94] .ext4_map_blocks+0x2c8/0x490
+    [  568.878054] [c0000001fa957730] [c0000000002c536c] .ext4_writepages+0x738/0xc60
+    [  568.878062] [c0000001fa957950] [c000000000168a78] .do_writepages+0x5c/0x80
+    [  568.878069] [c0000001fa9579d0] [c00000000015d1c4] .__filemap_fdatawrite_range+0x88/0xb0
+    [  568.878078] [c0000001fa957aa0] [c00000000015d23c] .filemap_write_and_wait_range+0x50/0xfc
+    [  568.878085] [c0000001fa957b30] [c0000000002b8edc] .ext4_sync_file+0x220/0x3c4
+    [  568.878092] [c0000001fa957be0] [c0000000001f849c] .vfs_fsync_range+0x64/0x80
+    [  568.878098] [c0000001fa957c70] [c0000000001f84f0] .vfs_fsync+0x38/0x4c
+    [  568.878105] [c0000001fa957d00] [c0000000001f87f4] .do_fsync+0x54/0x90
+    [  568.878111] [c0000001fa957db0] [c0000000001f8894] .SyS_fsync+0x28/0x3c
+    [  568.878120] [c0000001fa957e30] [c000000000009c88] syscall_exit+0x0/0x7c
+    [  568.878125] Instruction dump:
+    [  568.878130] 60000000 813d0034 81610070 38000000 7f8b4800 419e001c 813f007c 7d2bfe70
+    [  568.878144] 7d604a78 7c005850 54000ffe 7c0007b4 <0b000000> e8a10076 e87f0090 7fa4eb78
+    [  568.878160] ---[ end trace 594d911d9654770b ]---
+    
+    In addition fix the STD_GROUP optimization so that it works for
+    bigalloc file systems as well.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reported-by: Li Zhong 
+    Reviewed-by: Lukas Czerner 
+    Cc: stable@vger.kernel.org  # 3.10
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 58339393fa6e..ddd715e42a5c 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -38,8 +38,8 @@ ext4_group_t ext4_get_group_number(struct super_block *sb,
+ 	ext4_group_t group;
+ 
+ 	if (test_opt2(sb, STD_GROUP_SIZE))
+-		group = (le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block) +
+-			 block) >>
++		group = (block -
++			 le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block)) >>
+ 			(EXT4_BLOCK_SIZE_BITS(sb) + EXT4_CLUSTER_BITS(sb) + 3);
+ 	else
+ 		ext4_get_group_no_and_offset(sb, block, &group, NULL);
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 85b3dd60169b..8862d4ddf71f 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3624,10 +3624,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	sbi->s_addr_per_block_bits = ilog2(EXT4_ADDR_PER_BLOCK(sb));
+ 	sbi->s_desc_per_block_bits = ilog2(EXT4_DESC_PER_BLOCK(sb));
+ 
+-	/* Do we have standard group size of blocksize * 8 blocks ? */
+-	if (sbi->s_blocks_per_group == blocksize << 3)
+-		set_opt2(sb, STD_GROUP_SIZE);
+-
+ 	for (i = 0; i < 4; i++)
+ 		sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
+ 	sbi->s_def_hash_version = es->s_def_hash_version;
+@@ -3697,6 +3693,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		goto failed_mount;
+ 	}
+ 
++	/* Do we have standard group size of clustersize * 8 blocks ? */
++	if (sbi->s_blocks_per_group == clustersize << 3)
++		set_opt2(sb, STD_GROUP_SIZE);
++
+ 	/*
+ 	 * Test whether we have more sectors than will fit in sector_t,
+ 	 * and whether the max offset is addressable by the page cache.

commit 41a5b913197c3a25fddef1735dc9b3d1fdc57428
+Author: Theodore Ts'o 
+Date:   Mon Jul 1 08:12:41 2013 -0400
+
+    jbd2: invalidate handle if jbd2_journal_restart() fails
+    
+    If jbd2_journal_restart() fails the handle will have been disconnected
+    from the current transaction.  In this situation, the handle must not
+    be used for for any jbd2 function other than jbd2_journal_stop().
+    Enforce this with by treating a handle which has a NULL transaction
+    pointer as an aborted handle, and issue a kernel warning if
+    jbd2_journal_extent(), jbd2_journal_get_write_access(),
+    jbd2_journal_dirty_metadata(), etc. is called with an invalid handle.
+    
+    This commit also fixes a bug where jbd2_journal_stop() would trip over
+    a kernel jbd2 assertion check when trying to free an invalid handle.
+    
+    Also move the responsibility of setting current->journal_info to
+    start_this_handle(), simplifying the three users of this function.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reported-by: Younger Liu 
+    Cc: Jan Kara 
+
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index 383b0fbc6e19..7aa9a32573bb 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -368,6 +368,7 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
+ 		  atomic_read(&transaction->t_outstanding_credits),
+ 		  jbd2_log_space_left(journal));
+ 	read_unlock(&journal->j_state_lock);
++	current->journal_info = handle;
+ 
+ 	lock_map_acquire(&handle->h_lockdep_map);
+ 	jbd2_journal_free_transaction(new_transaction);
+@@ -442,14 +443,11 @@ handle_t *jbd2__journal_start(journal_t *journal, int nblocks, int rsv_blocks,
+ 		handle->h_rsv_handle = rsv_handle;
+ 	}
+ 
+-	current->journal_info = handle;
+-
+ 	err = start_this_handle(journal, handle, gfp_mask);
+ 	if (err < 0) {
+ 		if (handle->h_rsv_handle)
+ 			jbd2_free_handle(handle->h_rsv_handle);
+ 		jbd2_free_handle(handle);
+-		current->journal_info = NULL;
+ 		return ERR_PTR(err);
+ 	}
+ 	handle->h_type = type;
+@@ -511,16 +509,13 @@ int jbd2_journal_start_reserved(handle_t *handle, unsigned int type,
+ 	}
+ 
+ 	handle->h_journal = NULL;
+-	current->journal_info = handle;
+ 	/*
+ 	 * GFP_NOFS is here because callers are likely from writeback or
+ 	 * similarly constrained call sites
+ 	 */
+ 	ret = start_this_handle(journal, handle, GFP_NOFS);
+-	if (ret < 0) {
+-		current->journal_info = NULL;
++	if (ret < 0)
+ 		jbd2_journal_free_reserved(handle);
+-	}
+ 	handle->h_type = type;
+ 	handle->h_line_no = line_no;
+ 	return ret;
+@@ -550,20 +545,21 @@ EXPORT_SYMBOL(jbd2_journal_start_reserved);
+ int jbd2_journal_extend(handle_t *handle, int nblocks)
+ {
+ 	transaction_t *transaction = handle->h_transaction;
+-	journal_t *journal = transaction->t_journal;
++	journal_t *journal;
+ 	int result;
+ 	int wanted;
+ 
+-	result = -EIO;
++	WARN_ON(!transaction);
+ 	if (is_handle_aborted(handle))
+-		goto out;
++		return -EROFS;
++	journal = transaction->t_journal;
+ 
+ 	result = 1;
+ 
+ 	read_lock(&journal->j_state_lock);
+ 
+ 	/* Don't extend a locked-down transaction! */
+-	if (handle->h_transaction->t_state != T_RUNNING) {
++	if (transaction->t_state != T_RUNNING) {
+ 		jbd_debug(3, "denied handle %p %d blocks: "
+ 			  "transaction not running\n", handle, nblocks);
+ 		goto error_out;
+@@ -589,7 +585,7 @@ int jbd2_journal_extend(handle_t *handle, int nblocks)
+ 	}
+ 
+ 	trace_jbd2_handle_extend(journal->j_fs_dev->bd_dev,
+-				 handle->h_transaction->t_tid,
++				 transaction->t_tid,
+ 				 handle->h_type, handle->h_line_no,
+ 				 handle->h_buffer_credits,
+ 				 nblocks);
+@@ -603,7 +599,6 @@ int jbd2_journal_extend(handle_t *handle, int nblocks)
+ 	spin_unlock(&transaction->t_handle_lock);
+ error_out:
+ 	read_unlock(&journal->j_state_lock);
+-out:
+ 	return result;
+ }
+ 
+@@ -626,14 +621,16 @@ int jbd2_journal_extend(handle_t *handle, int nblocks)
+ int jbd2__journal_restart(handle_t *handle, int nblocks, gfp_t gfp_mask)
+ {
+ 	transaction_t *transaction = handle->h_transaction;
+-	journal_t *journal = transaction->t_journal;
++	journal_t *journal;
+ 	tid_t		tid;
+ 	int		need_to_start, ret;
+ 
++	WARN_ON(!transaction);
+ 	/* If we've had an abort of any type, don't even think about
+ 	 * actually doing the restart! */
+ 	if (is_handle_aborted(handle))
+ 		return 0;
++	journal = transaction->t_journal;
+ 
+ 	/*
+ 	 * First unlink the handle from its current transaction, and start the
+@@ -654,6 +651,8 @@ int jbd2__journal_restart(handle_t *handle, int nblocks, gfp_t gfp_mask)
+ 		wake_up(&journal->j_wait_updates);
+ 	tid = transaction->t_tid;
+ 	spin_unlock(&transaction->t_handle_lock);
++	handle->h_transaction = NULL;
++	current->journal_info = NULL;
+ 
+ 	jbd_debug(2, "restarting handle %p\n", handle);
+ 	need_to_start = !tid_geq(journal->j_commit_request, tid);
+@@ -783,17 +782,16 @@ do_get_write_access(handle_t *handle, struct journal_head *jh,
+ 			int force_copy)
+ {
+ 	struct buffer_head *bh;
+-	transaction_t *transaction;
++	transaction_t *transaction = handle->h_transaction;
+ 	journal_t *journal;
+ 	int error;
+ 	char *frozen_buffer = NULL;
+ 	int need_copy = 0;
+ 	unsigned long start_lock, time_lock;
+ 
++	WARN_ON(!transaction);
+ 	if (is_handle_aborted(handle))
+ 		return -EROFS;
+-
+-	transaction = handle->h_transaction;
+ 	journal = transaction->t_journal;
+ 
+ 	jbd_debug(5, "journal_head %p, force_copy %d\n", jh, force_copy);
+@@ -1052,14 +1050,16 @@ int jbd2_journal_get_write_access(handle_t *handle, struct buffer_head *bh)
+ int jbd2_journal_get_create_access(handle_t *handle, struct buffer_head *bh)
+ {
+ 	transaction_t *transaction = handle->h_transaction;
+-	journal_t *journal = transaction->t_journal;
++	journal_t *journal;
+ 	struct journal_head *jh = jbd2_journal_add_journal_head(bh);
+ 	int err;
+ 
+ 	jbd_debug(5, "journal_head %p\n", jh);
++	WARN_ON(!transaction);
+ 	err = -EROFS;
+ 	if (is_handle_aborted(handle))
+ 		goto out;
++	journal = transaction->t_journal;
+ 	err = 0;
+ 
+ 	JBUFFER_TRACE(jh, "entry");
+@@ -1265,12 +1265,14 @@ void jbd2_buffer_abort_trigger(struct journal_head *jh,
+ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
+ {
+ 	transaction_t *transaction = handle->h_transaction;
+-	journal_t *journal = transaction->t_journal;
++	journal_t *journal;
+ 	struct journal_head *jh;
+ 	int ret = 0;
+ 
++	WARN_ON(!transaction);
+ 	if (is_handle_aborted(handle))
+-		goto out;
++		return -EROFS;
++	journal = transaction->t_journal;
+ 	jh = jbd2_journal_grab_journal_head(bh);
+ 	if (!jh) {
+ 		ret = -EUCLEAN;
+@@ -1364,7 +1366,7 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
+ 
+ 	JBUFFER_TRACE(jh, "file as BJ_Metadata");
+ 	spin_lock(&journal->j_list_lock);
+-	__jbd2_journal_file_buffer(jh, handle->h_transaction, BJ_Metadata);
++	__jbd2_journal_file_buffer(jh, transaction, BJ_Metadata);
+ 	spin_unlock(&journal->j_list_lock);
+ out_unlock_bh:
+ 	jbd_unlock_bh_state(bh);
+@@ -1395,12 +1397,17 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
+ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
+ {
+ 	transaction_t *transaction = handle->h_transaction;
+-	journal_t *journal = transaction->t_journal;
++	journal_t *journal;
+ 	struct journal_head *jh;
+ 	int drop_reserve = 0;
+ 	int err = 0;
+ 	int was_modified = 0;
+ 
++	WARN_ON(!transaction);
++	if (is_handle_aborted(handle))
++		return -EROFS;
++	journal = transaction->t_journal;
++
+ 	BUFFER_TRACE(bh, "entry");
+ 
+ 	jbd_lock_bh_state(bh);
+@@ -1427,7 +1434,7 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
+ 	 */
+ 	jh->b_modified = 0;
+ 
+-	if (jh->b_transaction == handle->h_transaction) {
++	if (jh->b_transaction == transaction) {
+ 		J_ASSERT_JH(jh, !jh->b_frozen_data);
+ 
+ 		/* If we are forgetting a buffer which is already part
+@@ -1522,19 +1529,21 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
+ int jbd2_journal_stop(handle_t *handle)
+ {
+ 	transaction_t *transaction = handle->h_transaction;
+-	journal_t *journal = transaction->t_journal;
+-	int err, wait_for_commit = 0;
++	journal_t *journal;
++	int err = 0, wait_for_commit = 0;
+ 	tid_t tid;
+ 	pid_t pid;
+ 
++	if (!transaction)
++		goto free_and_exit;
++	journal = transaction->t_journal;
++
+ 	J_ASSERT(journal_current_handle() == handle);
+ 
+ 	if (is_handle_aborted(handle))
+ 		err = -EIO;
+-	else {
++	else
+ 		J_ASSERT(atomic_read(&transaction->t_updates) > 0);
+-		err = 0;
+-	}
+ 
+ 	if (--handle->h_ref > 0) {
+ 		jbd_debug(4, "h_ref %d -> %d\n", handle->h_ref + 1,
+@@ -1544,7 +1553,7 @@ int jbd2_journal_stop(handle_t *handle)
+ 
+ 	jbd_debug(4, "Handle %p going down\n", handle);
+ 	trace_jbd2_handle_stats(journal->j_fs_dev->bd_dev,
+-				handle->h_transaction->t_tid,
++				transaction->t_tid,
+ 				handle->h_type, handle->h_line_no,
+ 				jiffies - handle->h_start_jiffies,
+ 				handle->h_sync, handle->h_requested_credits,
+@@ -1657,6 +1666,7 @@ int jbd2_journal_stop(handle_t *handle)
+ 
+ 	if (handle->h_rsv_handle)
+ 		jbd2_journal_free_reserved(handle->h_rsv_handle);
++free_and_exit:
+ 	jbd2_free_handle(handle);
+ 	return err;
+ }
+@@ -2362,10 +2372,12 @@ void jbd2_journal_refile_buffer(journal_t *journal, struct journal_head *jh)
+ int jbd2_journal_file_inode(handle_t *handle, struct jbd2_inode *jinode)
+ {
+ 	transaction_t *transaction = handle->h_transaction;
+-	journal_t *journal = transaction->t_journal;
++	journal_t *journal;
+ 
++	WARN_ON(!transaction);
+ 	if (is_handle_aborted(handle))
+-		return -EIO;
++		return -EROFS;
++	journal = transaction->t_journal;
+ 
+ 	jbd_debug(4, "Adding inode %lu, tid:%d\n", jinode->i_vfs_inode->i_ino,
+ 			transaction->t_tid);
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index 0302f3f14063..d5b50a19463c 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -1266,7 +1266,7 @@ static inline int is_journal_aborted(journal_t *journal)
+ 
+ static inline int is_handle_aborted(handle_t *handle)
+ {
+-	if (handle->h_aborted)
++	if (handle->h_aborted || !handle->h_transaction)
+ 		return 1;
+ 	return is_journal_aborted(handle->h_transaction->t_journal);
+ }

commit 21ddd568c133024196d394c43923f55cad1e7bd0
+Author: Theodore Ts'o 
+Date:   Mon Jul 1 08:12:40 2013 -0400
+
+    ext4: translate flag bits to strings in tracepoints
+    
+    Translate the bitfields used in various flags argument to strings to
+    make the tracepoint output more human-readable.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 937593e2f006..575faa090253 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -4380,7 +4380,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 	}
+ 
+ out3:
+-	trace_ext4_ext_map_blocks_exit(inode, map, err ? err : allocated);
++	trace_ext4_ext_map_blocks_exit(inode, flags, map, err ? err : allocated);
+ 
+ 	return err ? err : allocated;
+ }
+diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
+index 963d23dc1028..87b30cd357e7 100644
+--- a/fs/ext4/indirect.c
++++ b/fs/ext4/indirect.c
+@@ -624,7 +624,7 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
+ 		partial--;
+ 	}
+ out:
+-	trace_ext4_ind_map_blocks_exit(inode, map, err);
++	trace_ext4_ind_map_blocks_exit(inode, flags, map, err);
+ 	return err;
+ }
+ 
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index 72f523eb82e0..2068db241f22 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -19,6 +19,57 @@ struct extent_status;
+ 
+ #define EXT4_I(inode) (container_of(inode, struct ext4_inode_info, vfs_inode))
+ 
++#define show_mballoc_flags(flags) __print_flags(flags, "|",	\
++	{ EXT4_MB_HINT_MERGE,		"HINT_MERGE" },		\
++	{ EXT4_MB_HINT_RESERVED,	"HINT_RESV" },		\
++	{ EXT4_MB_HINT_METADATA,	"HINT_MDATA" },		\
++	{ EXT4_MB_HINT_FIRST,		"HINT_FIRST" },		\
++	{ EXT4_MB_HINT_BEST,		"HINT_BEST" },		\
++	{ EXT4_MB_HINT_DATA,		"HINT_DATA" },		\
++	{ EXT4_MB_HINT_NOPREALLOC,	"HINT_NOPREALLOC" },	\
++	{ EXT4_MB_HINT_GROUP_ALLOC,	"HINT_GRP_ALLOC" },	\
++	{ EXT4_MB_HINT_GOAL_ONLY,	"HINT_GOAL_ONLY" },	\
++	{ EXT4_MB_HINT_TRY_GOAL,	"HINT_TRY_GOAL" },	\
++	{ EXT4_MB_DELALLOC_RESERVED,	"DELALLOC_RESV" },	\
++	{ EXT4_MB_STREAM_ALLOC,		"STREAM_ALLOC" },	\
++	{ EXT4_MB_USE_ROOT_BLOCKS,	"USE_ROOT_BLKS" },	\
++	{ EXT4_MB_USE_RESERVED,		"USE_RESV" })
++
++#define show_map_flags(flags) __print_flags(flags, "|",			\
++	{ EXT4_GET_BLOCKS_CREATE,		"CREATE" },		\
++	{ EXT4_GET_BLOCKS_UNINIT_EXT,		"UNINIT" },		\
++	{ EXT4_GET_BLOCKS_DELALLOC_RESERVE,	"DELALLOC" },		\
++	{ EXT4_GET_BLOCKS_PRE_IO,		"PRE_IO" },		\
++	{ EXT4_GET_BLOCKS_CONVERT,		"CONVERT" },		\
++	{ EXT4_GET_BLOCKS_METADATA_NOFAIL,	"METADATA_NOFAIL" },	\
++	{ EXT4_GET_BLOCKS_NO_NORMALIZE,		"NO_NORMALIZE" },	\
++	{ EXT4_GET_BLOCKS_KEEP_SIZE,		"KEEP_SIZE" },		\
++	{ EXT4_GET_BLOCKS_NO_LOCK,		"NO_LOCK" },		\
++	{ EXT4_GET_BLOCKS_NO_PUT_HOLE,		"NO_PUT_HOLE" })
++
++#define show_mflags(flags) __print_flags(flags, "",	\
++	{ EXT4_MAP_NEW,		"N" },			\
++	{ EXT4_MAP_MAPPED,	"M" },			\
++	{ EXT4_MAP_UNWRITTEN,	"U" },			\
++	{ EXT4_MAP_BOUNDARY,	"B" },			\
++	{ EXT4_MAP_UNINIT,	"u" },			\
++	{ EXT4_MAP_FROM_CLUSTER, "C" })
++
++#define show_free_flags(flags) __print_flags(flags, "|",	\
++	{ EXT4_FREE_BLOCKS_METADATA,		"METADATA" },	\
++	{ EXT4_FREE_BLOCKS_FORGET,		"FORGET" },	\
++	{ EXT4_FREE_BLOCKS_VALIDATED,		"VALIDATED" },	\
++	{ EXT4_FREE_BLOCKS_NO_QUOT_UPDATE,	"NO_QUOTA" },	\
++	{ EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER,"1ST_CLUSTER" },\
++	{ EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER,	"LAST_CLUSTER" })
++
++#define show_extent_status(status) __print_flags(status, "",	\
++	{ (1 << 3),	"W" }, 					\
++	{ (1 << 2),	"U" },					\
++	{ (1 << 1),	"D" },					\
++	{ (1 << 0),	"H" })
++
++
+ TRACE_EVENT(ext4_free_inode,
+ 	TP_PROTO(struct inode *inode),
+ 
+@@ -373,10 +424,10 @@ TRACE_EVENT(ext4_da_write_pages_extent,
+ 		__entry->flags		= map->m_flags;
+ 	),
+ 
+-	TP_printk("dev %d,%d ino %lu lblk %llu len %u flags 0x%04x",
++	TP_printk("dev %d,%d ino %lu lblk %llu len %u flags %s",
+ 		  MAJOR(__entry->dev), MINOR(__entry->dev),
+ 		  (unsigned long) __entry->ino, __entry->lblk, __entry->len,
+-		  __entry->flags)
++		  show_mflags(__entry->flags))
+ );
+ 
+ TRACE_EVENT(ext4_writepages_result,
+@@ -691,10 +742,10 @@ TRACE_EVENT(ext4_request_blocks,
+ 		__entry->flags	= ar->flags;
+ 	),
+ 
+-	TP_printk("dev %d,%d ino %lu flags %u len %u lblk %u goal %llu "
++	TP_printk("dev %d,%d ino %lu flags %s len %u lblk %u goal %llu "
+ 		  "lleft %u lright %u pleft %llu pright %llu ",
+ 		  MAJOR(__entry->dev), MINOR(__entry->dev),
+-		  (unsigned long) __entry->ino, __entry->flags,
++		  (unsigned long) __entry->ino, show_mballoc_flags(__entry->flags),
+ 		  __entry->len, __entry->logical, __entry->goal,
+ 		  __entry->lleft, __entry->lright, __entry->pleft,
+ 		  __entry->pright)
+@@ -733,10 +784,10 @@ TRACE_EVENT(ext4_allocate_blocks,
+ 		__entry->flags	= ar->flags;
+ 	),
+ 
+-	TP_printk("dev %d,%d ino %lu flags %u len %u block %llu lblk %u "
++	TP_printk("dev %d,%d ino %lu flags %s len %u block %llu lblk %u "
+ 		  "goal %llu lleft %u lright %u pleft %llu pright %llu",
+ 		  MAJOR(__entry->dev), MINOR(__entry->dev),
+-		  (unsigned long) __entry->ino, __entry->flags,
++		  (unsigned long) __entry->ino, show_mballoc_flags(__entry->flags),
+ 		  __entry->len, __entry->block, __entry->logical,
+ 		  __entry->goal,  __entry->lleft, __entry->lright,
+ 		  __entry->pleft, __entry->pright)
+@@ -766,11 +817,11 @@ TRACE_EVENT(ext4_free_blocks,
+ 		__entry->mode		= inode->i_mode;
+ 	),
+ 
+-	TP_printk("dev %d,%d ino %lu mode 0%o block %llu count %lu flags %d",
++	TP_printk("dev %d,%d ino %lu mode 0%o block %llu count %lu flags %s",
+ 		  MAJOR(__entry->dev), MINOR(__entry->dev),
+ 		  (unsigned long) __entry->ino,
+ 		  __entry->mode, __entry->block, __entry->count,
+-		  __entry->flags)
++		  show_free_flags(__entry->flags))
+ );
+ 
+ TRACE_EVENT(ext4_sync_file_enter,
+@@ -921,7 +972,7 @@ TRACE_EVENT(ext4_mballoc_alloc,
+ 	),
+ 
+ 	TP_printk("dev %d,%d inode %lu orig %u/%d/%u@%u goal %u/%d/%u@%u "
+-		  "result %u/%d/%u@%u blks %u grps %u cr %u flags 0x%04x "
++		  "result %u/%d/%u@%u blks %u grps %u cr %u flags %s "
+ 		  "tail %u broken %u",
+ 		  MAJOR(__entry->dev), MINOR(__entry->dev),
+ 		  (unsigned long) __entry->ino,
+@@ -932,7 +983,7 @@ TRACE_EVENT(ext4_mballoc_alloc,
+ 		  __entry->result_group, __entry->result_start,
+ 		  __entry->result_len, __entry->result_logical,
+ 		  __entry->found, __entry->groups, __entry->cr,
+-		  __entry->flags, __entry->tail,
++		  show_mballoc_flags(__entry->flags), __entry->tail,
+ 		  __entry->buddy ? 1 << __entry->buddy : 0)
+ );
+ 
+@@ -1546,10 +1597,10 @@ DECLARE_EVENT_CLASS(ext4__map_blocks_enter,
+ 		__entry->flags	= flags;
+ 	),
+ 
+-	TP_printk("dev %d,%d ino %lu lblk %u len %u flags %u",
++	TP_printk("dev %d,%d ino %lu lblk %u len %u flags %s",
+ 		  MAJOR(__entry->dev), MINOR(__entry->dev),
+ 		  (unsigned long) __entry->ino,
+-		  __entry->lblk, __entry->len, __entry->flags)
++		  __entry->lblk, __entry->len, show_map_flags(__entry->flags))
+ );
+ 
+ DEFINE_EVENT(ext4__map_blocks_enter, ext4_ext_map_blocks_enter,
+@@ -1567,47 +1618,53 @@ DEFINE_EVENT(ext4__map_blocks_enter, ext4_ind_map_blocks_enter,
+ );
+ 
+ DECLARE_EVENT_CLASS(ext4__map_blocks_exit,
+-	TP_PROTO(struct inode *inode, struct ext4_map_blocks *map, int ret),
++	TP_PROTO(struct inode *inode, unsigned flags, struct ext4_map_blocks *map,
++		 int ret),
+ 
+-	TP_ARGS(inode, map, ret),
++	TP_ARGS(inode, flags, map, ret),
+ 
+ 	TP_STRUCT__entry(
+ 		__field(	dev_t,		dev		)
+ 		__field(	ino_t,		ino		)
++		__field(	unsigned int,	flags		)
+ 		__field(	ext4_fsblk_t,	pblk		)
+ 		__field(	ext4_lblk_t,	lblk		)
+ 		__field(	unsigned int,	len		)
+-		__field(	unsigned int,	flags		)
++		__field(	unsigned int,	mflags		)
+ 		__field(	int,		ret		)
+ 	),
+ 
+ 	TP_fast_assign(
+ 		__entry->dev    = inode->i_sb->s_dev;
+ 		__entry->ino    = inode->i_ino;
++		__entry->flags	= flags;
+ 		__entry->pblk	= map->m_pblk;
+ 		__entry->lblk	= map->m_lblk;
+ 		__entry->len	= map->m_len;
+-		__entry->flags	= map->m_flags;
++		__entry->mflags	= map->m_flags;
+ 		__entry->ret	= ret;
+ 	),
+ 
+-	TP_printk("dev %d,%d ino %lu lblk %u pblk %llu len %u flags %x ret %d",
++	TP_printk("dev %d,%d ino %lu flags %s lblk %u pblk %llu len %u "
++		  "mflags %s ret %d",
+ 		  MAJOR(__entry->dev), MINOR(__entry->dev),
+ 		  (unsigned long) __entry->ino,
+-		  __entry->lblk, __entry->pblk,
+-		  __entry->len, __entry->flags, __entry->ret)
++		  show_map_flags(__entry->flags), __entry->lblk, __entry->pblk,
++		  __entry->len, show_mflags(__entry->mflags), __entry->ret)
+ );
+ 
+ DEFINE_EVENT(ext4__map_blocks_exit, ext4_ext_map_blocks_exit,
+-	TP_PROTO(struct inode *inode, struct ext4_map_blocks *map, int ret),
++	TP_PROTO(struct inode *inode, unsigned flags,
++		 struct ext4_map_blocks *map, int ret),
+ 
+-	TP_ARGS(inode, map, ret)
++	TP_ARGS(inode, flags, map, ret)
+ );
+ 
+ DEFINE_EVENT(ext4__map_blocks_exit, ext4_ind_map_blocks_exit,
+-	TP_PROTO(struct inode *inode, struct ext4_map_blocks *map, int ret),
++	TP_PROTO(struct inode *inode, unsigned flags,
++		 struct ext4_map_blocks *map, int ret),
+ 
+-	TP_ARGS(inode, map, ret)
++	TP_ARGS(inode, flags, map, ret)
+ );
+ 
+ TRACE_EVENT(ext4_ext_load_extent,
+@@ -1779,12 +1836,12 @@ TRACE_EVENT(ext4_ext_handle_uninitialized_extents,
+ 		__entry->newblk		= newblock;
+ 	),
+ 
+-	TP_printk("dev %d,%d ino %lu m_lblk %u m_pblk %llu m_len %u flags %x "
++	TP_printk("dev %d,%d ino %lu m_lblk %u m_pblk %llu m_len %u flags %s "
+ 		  "allocated %d newblock %llu",
+ 		  MAJOR(__entry->dev), MINOR(__entry->dev),
+ 		  (unsigned long) __entry->ino,
+ 		  (unsigned) __entry->lblk, (unsigned long long) __entry->pblk,
+-		  __entry->len, __entry->flags,
++		  __entry->len, show_map_flags(__entry->flags),
+ 		  (unsigned int) __entry->allocated,
+ 		  (unsigned long long) __entry->newblk)
+ );
+@@ -1812,10 +1869,10 @@ TRACE_EVENT(ext4_get_implied_cluster_alloc_exit,
+ 		__entry->ret	= ret;
+ 	),
+ 
+-	TP_printk("dev %d,%d m_lblk %u m_pblk %llu m_len %u m_flags %u ret %d",
++	TP_printk("dev %d,%d m_lblk %u m_pblk %llu m_len %u m_flags %s ret %d",
+ 		  MAJOR(__entry->dev), MINOR(__entry->dev),
+ 		  __entry->lblk, (unsigned long long) __entry->pblk,
+-		  __entry->len, __entry->flags, __entry->ret)
++		  __entry->len, show_mflags(__entry->flags), __entry->ret)
+ );
+ 
+ TRACE_EVENT(ext4_ext_put_in_cache,
+@@ -2146,7 +2203,7 @@ TRACE_EVENT(ext4_es_insert_extent,
+ 		__field(	ext4_lblk_t,	lblk		)
+ 		__field(	ext4_lblk_t,	len		)
+ 		__field(	ext4_fsblk_t,	pblk		)
+-		__field(	unsigned long long, status	)
++		__field(	char, status	)
+ 	),
+ 
+ 	TP_fast_assign(
+@@ -2155,14 +2212,14 @@ TRACE_EVENT(ext4_es_insert_extent,
+ 		__entry->lblk	= es->es_lblk;
+ 		__entry->len	= es->es_len;
+ 		__entry->pblk	= ext4_es_pblock(es);
+-		__entry->status	= ext4_es_status(es);
++		__entry->status	= ext4_es_status(es) >> 60;
+ 	),
+ 
+-	TP_printk("dev %d,%d ino %lu es [%u/%u) mapped %llu status %llx",
++	TP_printk("dev %d,%d ino %lu es [%u/%u) mapped %llu status %s",
+ 		  MAJOR(__entry->dev), MINOR(__entry->dev),
+ 		  (unsigned long) __entry->ino,
+ 		  __entry->lblk, __entry->len,
+-		  __entry->pblk, __entry->status)
++		  __entry->pblk, show_extent_status(__entry->status))
+ );
+ 
+ TRACE_EVENT(ext4_es_remove_extent,
+@@ -2223,7 +2280,7 @@ TRACE_EVENT(ext4_es_find_delayed_extent_range_exit,
+ 		__field(	ext4_lblk_t,	lblk		)
+ 		__field(	ext4_lblk_t,	len		)
+ 		__field(	ext4_fsblk_t,	pblk		)
+-		__field(	unsigned long long, status	)
++		__field(	char, status	)
+ 	),
+ 
+ 	TP_fast_assign(
+@@ -2232,14 +2289,14 @@ TRACE_EVENT(ext4_es_find_delayed_extent_range_exit,
+ 		__entry->lblk	= es->es_lblk;
+ 		__entry->len	= es->es_len;
+ 		__entry->pblk	= ext4_es_pblock(es);
+-		__entry->status	= ext4_es_status(es);
++		__entry->status	= ext4_es_status(es) >> 60;
+ 	),
+ 
+-	TP_printk("dev %d,%d ino %lu es [%u/%u) mapped %llu status %llx",
++	TP_printk("dev %d,%d ino %lu es [%u/%u) mapped %llu status %s",
+ 		  MAJOR(__entry->dev), MINOR(__entry->dev),
+ 		  (unsigned long) __entry->ino,
+ 		  __entry->lblk, __entry->len,
+-		  __entry->pblk, __entry->status)
++		  __entry->pblk, show_extent_status(__entry->status))
+ );
+ 
+ TRACE_EVENT(ext4_es_lookup_extent_enter,
+@@ -2276,7 +2333,7 @@ TRACE_EVENT(ext4_es_lookup_extent_exit,
+ 		__field(	ext4_lblk_t,	lblk		)
+ 		__field(	ext4_lblk_t,	len		)
+ 		__field(	ext4_fsblk_t,	pblk		)
+-		__field(	unsigned long long,	status	)
++		__field(	char,		status		)
+ 		__field(	int,		found		)
+ 	),
+ 
+@@ -2286,16 +2343,16 @@ TRACE_EVENT(ext4_es_lookup_extent_exit,
+ 		__entry->lblk	= es->es_lblk;
+ 		__entry->len	= es->es_len;
+ 		__entry->pblk	= ext4_es_pblock(es);
+-		__entry->status	= ext4_es_status(es);
++		__entry->status	= ext4_es_status(es) >> 60;
+ 		__entry->found	= found;
+ 	),
+ 
+-	TP_printk("dev %d,%d ino %lu found %d [%u/%u) %llu %llx",
++	TP_printk("dev %d,%d ino %lu found %d [%u/%u) %llu %s",
+ 		  MAJOR(__entry->dev), MINOR(__entry->dev),
+ 		  (unsigned long) __entry->ino, __entry->found,
+ 		  __entry->lblk, __entry->len,
+ 		  __entry->found ? __entry->pblk : 0,
+-		  __entry->found ? __entry->status : 0)
++		  show_extent_status(__entry->found ? __entry->status : 0))
+ );
+ 
+ TRACE_EVENT(ext4_es_shrink_enter,

commit cb530541182bee14112675046331f20a1c831507
+Author: Theodore Ts'o 
+Date:   Mon Jul 1 08:12:40 2013 -0400
+
+    ext4: fix up error handling for mpage_map_and_submit_extent()
+    
+    The function mpage_released_unused_page() must only be called once;
+    otherwise the kernel will BUG() when the second call to
+    mpage_released_unused_page() tries to unlock the pages which had been
+    unlocked by the first call.
+    
+    Also restructure the error handling so that we only give up on writing
+    the dirty pages in the case of ENOSPC where retrying the allocation
+    won't help.  Otherwise, a transient failure, such as a kmalloc()
+    failure in calling ext4_map_blocks() might cause us to give up on
+    those pages, leading to a scary message in /var/log/messages plus data
+    loss.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 502a9e1f5aa3..0188e65e1f58 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2153,7 +2153,8 @@ static int mpage_map_one_extent(handle_t *handle, struct mpage_da_data *mpd)
+  * guaranteed). After mapping we submit all mapped pages for IO.
+  */
+ static int mpage_map_and_submit_extent(handle_t *handle,
+-				       struct mpage_da_data *mpd)
++				       struct mpage_da_data *mpd,
++				       bool *give_up_on_write)
+ {
+ 	struct inode *inode = mpd->inode;
+ 	struct ext4_map_blocks *map = &mpd->map;
+@@ -2167,29 +2168,30 @@ static int mpage_map_and_submit_extent(handle_t *handle,
+ 		if (err < 0) {
+ 			struct super_block *sb = inode->i_sb;
+ 
++			if (EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED)
++				goto invalidate_dirty_pages;
+ 			/*
+-			 * Need to commit transaction to free blocks. Let upper
+-			 * layers sort it out.
++			 * Let the uper layers retry transient errors.
++			 * In the case of ENOSPC, if ext4_count_free_blocks()
++			 * is non-zero, a commit should free up blocks.
+ 			 */
+-			if (err == -ENOSPC && ext4_count_free_clusters(sb))
+-				return -ENOSPC;
+-
+-			if (!(EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED)) {
+-				ext4_msg(sb, KERN_CRIT,
+-					 "Delayed block allocation failed for "
+-					 "inode %lu at logical offset %llu with"
+-					 " max blocks %u with error %d",
+-					 inode->i_ino,
+-					 (unsigned long long)map->m_lblk,
+-					 (unsigned)map->m_len, err);
+-				ext4_msg(sb, KERN_CRIT,
+-					 "This should not happen!! Data will "
+-					 "be lost\n");
+-				if (err == -ENOSPC)
+-					ext4_print_free_blocks(inode);
+-			}
+-			/* invalidate all the pages */
+-			mpage_release_unused_pages(mpd, true);
++			if ((err == -ENOMEM) ||
++			    (err == -ENOSPC && ext4_count_free_clusters(sb)))
++				return err;
++			ext4_msg(sb, KERN_CRIT,
++				 "Delayed block allocation failed for "
++				 "inode %lu at logical offset %llu with"
++				 " max blocks %u with error %d",
++				 inode->i_ino,
++				 (unsigned long long)map->m_lblk,
++				 (unsigned)map->m_len, -err);
++			ext4_msg(sb, KERN_CRIT,
++				 "This should not happen!! Data will "
++				 "be lost\n");
++			if (err == -ENOSPC)
++				ext4_print_free_blocks(inode);
++		invalidate_dirty_pages:
++			*give_up_on_write = true;
+ 			return err;
+ 		}
+ 		/*
+@@ -2377,6 +2379,7 @@ static int ext4_writepages(struct address_space *mapping,
+ 	struct ext4_sb_info *sbi = EXT4_SB(mapping->host->i_sb);
+ 	bool done;
+ 	struct blk_plug plug;
++	bool give_up_on_write = false;
+ 
+ 	trace_ext4_writepages(inode, wbc);
+ 
+@@ -2494,7 +2497,8 @@ static int ext4_writepages(struct address_space *mapping,
+ 		ret = mpage_prepare_extent_to_map(&mpd);
+ 		if (!ret) {
+ 			if (mpd.map.m_len)
+-				ret = mpage_map_and_submit_extent(handle, &mpd);
++				ret = mpage_map_and_submit_extent(handle, &mpd,
++					&give_up_on_write);
+ 			else {
+ 				/*
+ 				 * We scanned the whole range (or exhausted
+@@ -2509,7 +2513,7 @@ static int ext4_writepages(struct address_space *mapping,
+ 		/* Submit prepared bio */
+ 		ext4_io_submit(&mpd.io_submit);
+ 		/* Unlock pages we didn't use */
+-		mpage_release_unused_pages(&mpd, false);
++		mpage_release_unused_pages(&mpd, give_up_on_write);
+ 		/* Drop our io_end reference we got from init */
+ 		ext4_put_io_end(mpd.io_submit.io_end);
+ 

commit 39c04153fda8c32e85b51c96eb5511a326ad7609
+Author: Theodore Ts'o 
+Date:   Mon Jul 1 08:12:40 2013 -0400
+
+    jbd2: fix theoretical race in jbd2__journal_restart
+    
+    Once we decrement transaction->t_updates, if this is the last handle
+    holding the transaction from closing, and once we release the
+    t_handle_lock spinlock, it's possible for the transaction to commit
+    and be released.  In practice with normal kernels, this probably won't
+    happen, since the commit happens in a separate kernel thread and it's
+    unlikely this could all happen within the space of a few CPU cycles.
+    
+    On the other hand, with a real-time kernel, this could potentially
+    happen, so save the tid found in transaction->t_tid before we release
+    t_handle_lock.  It would require an insane configuration, such as one
+    where the jbd2 thread was set to a very high real-time priority,
+    perhaps because a high priority real-time thread is trying to read or
+    write to a file system.  But some people who use real-time kernels
+    have been known to do insane things, including controlling
+    laser-wielding industrial robots.  :-)
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index dd422e680418..383b0fbc6e19 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -652,10 +652,10 @@ int jbd2__journal_restart(handle_t *handle, int nblocks, gfp_t gfp_mask)
+ 	}
+ 	if (atomic_dec_and_test(&transaction->t_updates))
+ 		wake_up(&journal->j_wait_updates);
++	tid = transaction->t_tid;
+ 	spin_unlock(&transaction->t_handle_lock);
+ 
+ 	jbd_debug(2, "restarting handle %p\n", handle);
+-	tid = transaction->t_tid;
+ 	need_to_start = !tid_geq(journal->j_commit_request, tid);
+ 	read_unlock(&journal->j_state_lock);
+ 	if (need_to_start)

commit 42c832debbbf819f6c4ad8601baa559c44105ba4
+Author: Theodore Ts'o 
+Date:   Mon Jul 1 08:12:39 2013 -0400
+
+    ext4: check error return from ext4_write_inline_data_end()
+    
+    The function ext4_write_inline_data_end() can return an error.  So we
+    need to assign it to a signed integer variable to check for an error
+    return (since copied is an unsigned int).
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Zheng Liu 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 6d051deafc39..09942341dfae 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1061,10 +1061,13 @@ static int ext4_write_end(struct file *file,
+ 		}
+ 	}
+ 
+-	if (ext4_has_inline_data(inode))
+-		copied = ext4_write_inline_data_end(inode, pos, len,
+-						    copied, page);
+-	else
++	if (ext4_has_inline_data(inode)) {
++		ret = ext4_write_inline_data_end(inode, pos, len,
++						 copied, page);
++		if (ret < 0)
++			goto errout;
++		copied = ret;
++	} else
+ 		copied = block_write_end(file, mapping, pos,
+ 					 len, copied, page, fsdata);
+ 

commit fe52d17cdd343ac43c85cf72940a58865b9d3bfb
+Author: Theodore Ts'o 
+Date:   Mon Jul 1 08:12:38 2013 -0400
+
+    jbd2: move superblock checksum calculation to jbd2_write_superblock()
+    
+    Some of the functions which modify the jbd2 superblock were not
+    updating the checksum before calling jbd2_write_superblock().  Move
+    the call to jbd2_superblock_csum_set() to jbd2_write_superblock(), so
+    that the checksum is calculated consistently.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Darrick J. Wong 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 915dd575cd46..02c7ad9d7a41 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -1335,6 +1335,7 @@ static int journal_reset(journal_t *journal)
+ static void jbd2_write_superblock(journal_t *journal, int write_op)
+ {
+ 	struct buffer_head *bh = journal->j_sb_buffer;
++	journal_superblock_t *sb = journal->j_superblock;
+ 	int ret;
+ 
+ 	trace_jbd2_write_superblock(journal, write_op);
+@@ -1356,6 +1357,7 @@ static void jbd2_write_superblock(journal_t *journal, int write_op)
+ 		clear_buffer_write_io_error(bh);
+ 		set_buffer_uptodate(bh);
+ 	}
++	jbd2_superblock_csum_set(journal, sb);
+ 	get_bh(bh);
+ 	bh->b_end_io = end_buffer_write_sync;
+ 	ret = submit_bh(write_op, bh);
+@@ -1452,7 +1454,6 @@ void jbd2_journal_update_sb_errno(journal_t *journal)
+ 	jbd_debug(1, "JBD2: updating superblock error (errno %d)\n",
+ 		  journal->j_errno);
+ 	sb->s_errno    = cpu_to_be32(journal->j_errno);
+-	jbd2_superblock_csum_set(journal, sb);
+ 	read_unlock(&journal->j_state_lock);
+ 
+ 	jbd2_write_superblock(journal, WRITE_SYNC);

commit 981250ca89261f98bdfd2d6be1fcccb96cbbc00d
+Author: Theodore Ts'o 
+Date:   Wed Jun 12 11:48:29 2013 -0400
+
+    ext4: don't use EXT4_FREE_BLOCKS_FORGET unnecessarily
+    
+    Commit 18888cf0883c: "ext4: speed up truncate/unlink by not using
+    bforget() unless needed" removed the use of EXT4_FREE_BLOCKS_FORGET in
+    the most important codepath for file systems using extents, but a
+    similar optimization also can be done for file systems using indirect
+    blocks, and for the two special cases in the ext4 extents code.
+    
+    Cc: Andrey Sidorov 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 208f664f9ee0..d04f40936397 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -2355,6 +2355,15 @@ int ext4_ext_index_trans_blocks(struct inode *inode, int extents)
+ 	return index;
+ }
+ 
++static inline int get_default_free_blocks_flags(struct inode *inode)
++{
++	if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
++		return EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET;
++	else if (ext4_should_journal_data(inode))
++		return EXT4_FREE_BLOCKS_FORGET;
++	return 0;
++}
++
+ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
+ 			      struct ext4_extent *ex,
+ 			      long long *partial_cluster,
+@@ -2363,12 +2372,7 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
+ 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+ 	unsigned short ee_len =  ext4_ext_get_actual_len(ex);
+ 	ext4_fsblk_t pblk;
+-	int flags = 0;
+-
+-	if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+-		flags |= EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET;
+-	else if (ext4_should_journal_data(inode))
+-		flags |= EXT4_FREE_BLOCKS_FORGET;
++	int flags = get_default_free_blocks_flags(inode);
+ 
+ 	/*
+ 	 * For bigalloc file systems, we never free a partial cluster
+@@ -2635,10 +2639,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
+ 	if (*partial_cluster > 0 &&
+ 	    (EXT4_B2C(sbi, ext4_ext_pblock(ex) + ex_ee_len - 1) !=
+ 	     *partial_cluster)) {
+-		int flags = EXT4_FREE_BLOCKS_FORGET;
+-
+-		if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+-			flags |= EXT4_FREE_BLOCKS_METADATA;
++		int flags = get_default_free_blocks_flags(inode);
+ 
+ 		ext4_free_blocks(handle, inode, NULL,
+ 				 EXT4_C2B(sbi, *partial_cluster),
+@@ -2869,10 +2870,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
+ 	 * even the first extent, then we should free the blocks in the partial
+ 	 * cluster as well. */
+ 	if (partial_cluster > 0 && path->p_hdr->eh_entries == 0) {
+-		int flags = EXT4_FREE_BLOCKS_FORGET;
+-
+-		if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+-			flags |= EXT4_FREE_BLOCKS_METADATA;
++		int flags = get_default_free_blocks_flags(inode);
+ 
+ 		ext4_free_blocks(handle, inode, NULL,
+ 				 EXT4_C2B(EXT4_SB(sb), partial_cluster),
+diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
+index 2a1f8a577e08..963d23dc1028 100644
+--- a/fs/ext4/indirect.c
++++ b/fs/ext4/indirect.c
+@@ -926,11 +926,13 @@ static int ext4_clear_blocks(handle_t *handle, struct inode *inode,
+ 			     __le32 *last)
+ {
+ 	__le32 *p;
+-	int	flags = EXT4_FREE_BLOCKS_FORGET | EXT4_FREE_BLOCKS_VALIDATED;
++	int	flags = EXT4_FREE_BLOCKS_VALIDATED;
+ 	int	err;
+ 
+ 	if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+-		flags |= EXT4_FREE_BLOCKS_METADATA;
++		flags |= EXT4_FREE_BLOCKS_FORGET | EXT4_FREE_BLOCKS_METADATA;
++	else if (ext4_should_journal_data(inode))
++		flags |= EXT4_FREE_BLOCKS_FORGET;
+ 
+ 	if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), block_to_free,
+ 				   count)) {

commit 2ed5724d5a78a22864ef0bd6af4fcb8a15379f00
+Author: Theodore Ts'o 
+Date:   Wed Jun 12 11:43:02 2013 -0400
+
+    ext4: add cond_resched() to ext4_free_blocks() & ext4_mb_regular_allocator()
+    
+    For a file systems with a very large number of block groups, if all of
+    the block group bitmaps are in memory and the file system is
+    relatively badly fragmented, it's possible ext4_mb_regular_allocator()
+    to take a long time trying to find a good match.  This is especially
+    true if the tuning parameter mb_max_to_scan has been sent to a very
+    large number.  So add a cond_resched() to avoid soft lockup warnings
+    and to provide better system responsiveness.
+    
+    For ext4_free_blocks(), if we are deleting a large range of blocks,
+    and data=journal is enabled so that EXT4_FREE_BLOCKS_FORGET is passed,
+    the loop to call sb_find_get_block() and to call ext4_forget() can
+    take over 10-15 milliseocnds or more.  So it's better to add a
+    cond_resched() here a well.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index def84082a9a9..1a9c22b45a01 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2105,6 +2105,7 @@ ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
+ 		group = ac->ac_g_ex.fe_group;
+ 
+ 		for (i = 0; i < ngroups; group++, i++) {
++			cond_resched();
+ 			/*
+ 			 * Artificially restricted ngroups for non-extent
+ 			 * files makes group > ngroups possible on first loop.
+@@ -4612,10 +4613,11 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 		BUG_ON(bh && (count > 1));
+ 
+ 		for (i = 0; i < count; i++) {
++			cond_resched();
+ 			if (!bh)
+ 				tbh = sb_find_get_block(inode->i_sb,
+ 							block + i);
+-			if (unlikely(!tbh))
++			if (!tbh)
+ 				continue;
+ 			ext4_forget(handle, flags & EXT4_FREE_BLOCKS_METADATA,
+ 				    inode, tbh, block + i);

commit 20970ba65d5a22f2e4efbfa100377722fde56935
+Author: Theodore Ts'o 
+Date:   Thu Jun 6 14:00:46 2013 -0400
+
+    ext4: use ext4_da_writepages() for all modes
+    
+    Rename ext4_da_writepages() to ext4_writepages() and use it for all
+    modes.  We still need to iterate over all the pages in the case of
+    data=journalling, but in the case of nodelalloc/data=ordered (which is
+    what file systems mounted using ext3 backwards compatibility will use)
+    this will allow us to use a much more efficient I/O submission path.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 442c5d2e0978..0db830d541ec 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1799,7 +1799,7 @@ static int __ext4_journalled_writepage(struct page *page,
+  * lock so we have to do some magic.
+  *
+  * This function can get called via...
+- *   - ext4_da_writepages after taking page lock (have journal handle)
++ *   - ext4_writepages after taking page lock (have journal handle)
+  *   - journal_submit_inode_data_buffers (no journal handle)
+  *   - shrink_page_list via the kswapd/direct reclaim (no journal handle)
+  *   - grab_page_cache when doing write_begin (have journal handle)
+@@ -2217,7 +2217,7 @@ static int mpage_map_and_submit_extent(handle_t *handle,
+ 
+ /*
+  * Calculate the total number of credits to reserve for one writepages
+- * iteration. This is called from ext4_da_writepages(). We map an extent of
++ * iteration. This is called from ext4_writepages(). We map an extent of
+  * upto MAX_WRITEPAGES_EXTENT_LEN blocks and then we go on and finish mapping
+  * the last partial page. So in total we can map MAX_WRITEPAGES_EXTENT_LEN +
+  * bpp - 1 blocks in bpp different extents.
+@@ -2349,8 +2349,17 @@ static int mpage_prepare_extent_to_map(struct mpage_da_data *mpd)
+ 	return err;
+ }
+ 
+-static int ext4_da_writepages(struct address_space *mapping,
+-			      struct writeback_control *wbc)
++static int __writepage(struct page *page, struct writeback_control *wbc,
++		       void *data)
++{
++	struct address_space *mapping = data;
++	int ret = ext4_writepage(page, wbc);
++	mapping_set_error(mapping, ret);
++	return ret;
++}
++
++static int ext4_writepages(struct address_space *mapping,
++			   struct writeback_control *wbc)
+ {
+ 	pgoff_t	writeback_index = 0;
+ 	long nr_to_write = wbc->nr_to_write;
+@@ -2364,7 +2373,7 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 	bool done;
+ 	struct blk_plug plug;
+ 
+-	trace_ext4_da_writepages(inode, wbc);
++	trace_ext4_writepages(inode, wbc);
+ 
+ 	/*
+ 	 * No pages to write? This is mainly a kludge to avoid starting
+@@ -2374,13 +2383,23 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 	if (!mapping->nrpages || !mapping_tagged(mapping, PAGECACHE_TAG_DIRTY))
+ 		return 0;
+ 
++	if (ext4_should_journal_data(inode)) {
++		struct blk_plug plug;
++		int ret;
++
++		blk_start_plug(&plug);
++		ret = write_cache_pages(mapping, wbc, __writepage, mapping);
++		blk_finish_plug(&plug);
++		return ret;
++	}
++
+ 	/*
+ 	 * If the filesystem has aborted, it is read-only, so return
+ 	 * right away instead of dumping stack traces later on that
+ 	 * will obscure the real source of the problem.  We test
+ 	 * EXT4_MF_FS_ABORTED instead of sb->s_flag's MS_RDONLY because
+ 	 * the latter could be true if the filesystem is mounted
+-	 * read-only, and in that case, ext4_da_writepages should
++	 * read-only, and in that case, ext4_writepages should
+ 	 * *never* be called, so if that ever happens, we would want
+ 	 * the stack trace.
+ 	 */
+@@ -2520,8 +2539,8 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 		mapping->writeback_index = mpd.first_page;
+ 
+ out_writepages:
+-	trace_ext4_da_writepages_result(inode, wbc, ret,
+-					nr_to_write - wbc->nr_to_write);
++	trace_ext4_writepages_result(inode, wbc, ret,
++				     nr_to_write - wbc->nr_to_write);
+ 	return ret;
+ }
+ 
+@@ -2769,7 +2788,7 @@ int ext4_alloc_da_blocks(struct inode *inode)
+ 	 * laptop_mode, not even desirable).  However, to do otherwise
+ 	 * would require replicating code paths in:
+ 	 *
+-	 * ext4_da_writepages() ->
++	 * ext4_writepages() ->
+ 	 *    write_cache_pages() ---> (via passed in callback function)
+ 	 *        __mpage_da_writepage() -->
+ 	 *           mpage_add_bh_to_extent()
+@@ -3213,6 +3232,7 @@ static const struct address_space_operations ext4_aops = {
+ 	.readpage		= ext4_readpage,
+ 	.readpages		= ext4_readpages,
+ 	.writepage		= ext4_writepage,
++	.writepages		= ext4_writepages,
+ 	.write_begin		= ext4_write_begin,
+ 	.write_end		= ext4_write_end,
+ 	.bmap			= ext4_bmap,
+@@ -3228,6 +3248,7 @@ static const struct address_space_operations ext4_journalled_aops = {
+ 	.readpage		= ext4_readpage,
+ 	.readpages		= ext4_readpages,
+ 	.writepage		= ext4_writepage,
++	.writepages		= ext4_writepages,
+ 	.write_begin		= ext4_write_begin,
+ 	.write_end		= ext4_journalled_write_end,
+ 	.set_page_dirty		= ext4_journalled_set_page_dirty,
+@@ -3243,7 +3264,7 @@ static const struct address_space_operations ext4_da_aops = {
+ 	.readpage		= ext4_readpage,
+ 	.readpages		= ext4_readpages,
+ 	.writepage		= ext4_writepage,
+-	.writepages		= ext4_da_writepages,
++	.writepages		= ext4_writepages,
+ 	.write_begin		= ext4_da_write_begin,
+ 	.write_end		= ext4_da_write_end,
+ 	.bmap			= ext4_bmap,
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index 832a412e6515..72f523eb82e0 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -281,7 +281,7 @@ DEFINE_EVENT(ext4__write_end, ext4_da_write_end,
+ 	TP_ARGS(inode, pos, len, copied)
+ );
+ 
+-TRACE_EVENT(ext4_da_writepages,
++TRACE_EVENT(ext4_writepages,
+ 	TP_PROTO(struct inode *inode, struct writeback_control *wbc),
+ 
+ 	TP_ARGS(inode, wbc),
+@@ -379,7 +379,7 @@ TRACE_EVENT(ext4_da_write_pages_extent,
+ 		  __entry->flags)
+ );
+ 
+-TRACE_EVENT(ext4_da_writepages_result,
++TRACE_EVENT(ext4_writepages_result,
+ 	TP_PROTO(struct inode *inode, struct writeback_control *wbc,
+ 			int ret, int pages_written),
+ 

commit f4afb4f4e3e9af626ad695c87e4f9aaa780b29ec
+Author: Theodore Ts'o 
+Date:   Thu Jun 6 11:40:37 2013 -0400
+
+    ext4: optimize test_root()
+    
+    The test_root() function could potentially loop forever due to
+    overflow issues.  So rewrite test_root() to avoid this issue; as a
+    bonus, it is 38% faster when benchmarked via a test loop:
+    
+    int main(int argc, char **argv)
+    {
+            int  i;
+    
+            for (i = 0; i < 1 << 24; i++) {
+                    if (test_root(i, 7))
+                            printf("%d\n", i);
+            }
+    }
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index d0f13eada0ed..58339393fa6e 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -682,11 +682,15 @@ ext4_fsblk_t ext4_count_free_clusters(struct super_block *sb)
+ 
+ static inline int test_root(ext4_group_t a, int b)
+ {
+-	int num = b;
+-
+-	while (a > num)
+-		num *= b;
+-	return num == a;
++	while (1) {
++		if (a < b)
++			return 0;
++		if (a == b)
++			return 1;
++		if ((a % b) != 0)
++			return 0;
++		a = a / b;
++	}
+ }
+ 
+ static int ext4_group_sparse(ext4_group_t group)

commit 2f2e09eb15849562aede80ed007658e4504ded26
+Author: Theodore Ts'o 
+Date:   Thu Jun 6 11:16:43 2013 -0400
+
+    ext4: add sanity check to ext4_get_group_info()
+    
+    The group number passed to ext4_get_group_info() should be valid, but
+    let's add an assert to check this before we start creating a pointer
+    based on that group number and dereferencing it.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index bd9890f6d9ce..f85f1fb49df8 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2313,6 +2313,7 @@ struct ext4_group_info *ext4_get_group_info(struct super_block *sb,
+ {
+ 	 struct ext4_group_info ***grp_info;
+ 	 long indexv, indexh;
++	 BUG_ON(group >= EXT4_SB(sb)->s_groups_count);
+ 	 grp_info = EXT4_SB(sb)->s_group_info;
+ 	 indexv = group >> (EXT4_DESC_PER_BLOCK_BITS(sb));
+ 	 indexh = group & ((EXT4_DESC_PER_BLOCK(sb)) - 1);

commit b302ef2d3c73d8a07ed2f0679ce35f00b6dcacef
+Author: Theodore Ts'o 
+Date:   Thu Jun 6 11:14:31 2013 -0400
+
+    ext4: verify group number in verify_group_input() before using it
+    
+    Check the group number for sanity earilier, before calling routines
+    such as ext4_bg_has_super() or ext4_group_overhead_blocks().
+    
+    Reported-by: Jonathan Salwan 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index b27c96d01965..6ed4df27da8d 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -79,12 +79,20 @@ static int verify_group_input(struct super_block *sb,
+ 	ext4_fsblk_t end = start + input->blocks_count;
+ 	ext4_group_t group = input->group;
+ 	ext4_fsblk_t itend = input->inode_table + sbi->s_itb_per_group;
+-	unsigned overhead = ext4_group_overhead_blocks(sb, group);
+-	ext4_fsblk_t metaend = start + overhead;
++	unsigned overhead;
++	ext4_fsblk_t metaend;
+ 	struct buffer_head *bh = NULL;
+ 	ext4_grpblk_t free_blocks_count, offset;
+ 	int err = -EINVAL;
+ 
++	if (group != sbi->s_groups_count) {
++		ext4_warning(sb, "Cannot add at group %u (only %u groups)",
++			     input->group, sbi->s_groups_count);
++		return -EINVAL;
++	}
++
++	overhead = ext4_group_overhead_blocks(sb, group);
++	metaend = start + overhead;
+ 	input->free_blocks_count = free_blocks_count =
+ 		input->blocks_count - 2 - overhead - sbi->s_itb_per_group;
+ 
+@@ -96,10 +104,7 @@ static int verify_group_input(struct super_block *sb,
+ 		       free_blocks_count, input->reserved_blocks);
+ 
+ 	ext4_get_group_no_and_offset(sb, start, NULL, &offset);
+-	if (group != sbi->s_groups_count)
+-		ext4_warning(sb, "Cannot add at group %u (only %u groups)",
+-			     input->group, sbi->s_groups_count);
+-	else if (offset != 0)
++	if (offset != 0)
+ 			ext4_warning(sb, "Last group not full");
+ 	else if (input->reserved_blocks > input->blocks_count / 5)
+ 		ext4_warning(sb, "Reserved blocks too high (%u)",

commit a1d8d9a757cd46e044a3f6061c315eda14bf697e
+Author: Theodore Ts'o 
+Date:   Thu Jun 6 10:18:22 2013 -0400
+
+    ext4: add check to io_submit_init_bio
+    
+    The bio_alloc() function can return NULL if the memory allocation
+    fails.  So we need to check for this.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
+index ce8c15a7eabc..48786cdb5e6c 100644
+--- a/fs/ext4/page-io.c
++++ b/fs/ext4/page-io.c
+@@ -372,6 +372,8 @@ static int io_submit_init_bio(struct ext4_io_submit *io,
+ 	struct bio *bio;
+ 
+ 	bio = bio_alloc(GFP_NOIO, min(nvecs, BIO_MAX_PAGES));
++	if (!bio)
++		return -ENOMEM;
+ 	bio->bi_sector = bh->b_blocknr * (bh->b_size >> 9);
+ 	bio->bi_bdev = bh->b_bdev;
+ 	bio->bi_end_io = ext4_end_bio;

commit a549984b8c95acbecefd1fdd4bfdbea4d29b0588
+Author: Theodore Ts'o 
+Date:   Sat May 11 19:07:42 2013 -0400
+
+    ext4: revert "ext4: use io_end for multiple bios"
+    
+    This reverts commit 4eec708d263f0ee10861d69251708a225b64cac7.
+    
+    Multiple users have reported crashes which is apparently caused by
+    this commit.  Thanks to Dmitry Monakhov for bisecting it.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Dmitry Monakhov 
+    Cc: Jan Kara 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 0aabb344b02e..5aae3d12d400 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -209,7 +209,6 @@ typedef struct ext4_io_end {
+ 	ssize_t			size;		/* size of the extent */
+ 	struct kiocb		*iocb;		/* iocb struct for AIO */
+ 	int			result;		/* error value for AIO */
+-	atomic_t		count;		/* reference counter */
+ } ext4_io_end_t;
+ 
+ struct ext4_io_submit {
+@@ -2651,14 +2650,11 @@ extern int ext4_move_extents(struct file *o_filp, struct file *d_filp,
+ 
+ /* page-io.c */
+ extern int __init ext4_init_pageio(void);
++extern void ext4_add_complete_io(ext4_io_end_t *io_end);
+ extern void ext4_exit_pageio(void);
+ extern void ext4_ioend_shutdown(struct inode *);
++extern void ext4_free_io_end(ext4_io_end_t *io);
+ extern ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags);
+-extern ext4_io_end_t *ext4_get_io_end(ext4_io_end_t *io_end);
+-extern int ext4_put_io_end(ext4_io_end_t *io_end);
+-extern void ext4_put_io_end_defer(ext4_io_end_t *io_end);
+-extern void ext4_io_submit_init(struct ext4_io_submit *io,
+-				struct writeback_control *wbc);
+ extern void ext4_end_io_work(struct work_struct *work);
+ extern void ext4_io_submit(struct ext4_io_submit *io);
+ extern int ext4_bio_write_page(struct ext4_io_submit *io,
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 793d44b84d7f..d66656992358 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1487,10 +1487,7 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd,
+ 	struct ext4_io_submit io_submit;
+ 
+ 	BUG_ON(mpd->next_page <= mpd->first_page);
+-	ext4_io_submit_init(&io_submit, mpd->wbc);
+-	io_submit.io_end = ext4_init_io_end(inode, GFP_NOFS);
+-	if (!io_submit.io_end)
+-		return -ENOMEM;
++	memset(&io_submit, 0, sizeof(io_submit));
+ 	/*
+ 	 * We need to start from the first_page to the next_page - 1
+ 	 * to make sure we also write the mapped dirty buffer_heads.
+@@ -1578,8 +1575,6 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd,
+ 		pagevec_release(&pvec);
+ 	}
+ 	ext4_io_submit(&io_submit);
+-	/* Drop io_end reference we got from init */
+-	ext4_put_io_end_defer(io_submit.io_end);
+ 	return ret;
+ }
+ 
+@@ -2238,16 +2233,9 @@ static int ext4_writepage(struct page *page,
+ 		 */
+ 		return __ext4_journalled_writepage(page, len);
+ 
+-	ext4_io_submit_init(&io_submit, wbc);
+-	io_submit.io_end = ext4_init_io_end(inode, GFP_NOFS);
+-	if (!io_submit.io_end) {
+-		redirty_page_for_writepage(wbc, page);
+-		return -ENOMEM;
+-	}
++	memset(&io_submit, 0, sizeof(io_submit));
+ 	ret = ext4_bio_write_page(&io_submit, page, len, wbc);
+ 	ext4_io_submit(&io_submit);
+-	/* Drop io_end reference we got from init */
+-	ext4_put_io_end_defer(io_submit.io_end);
+ 	return ret;
+ }
+ 
+@@ -3078,13 +3066,9 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
+ 	struct inode *inode = file_inode(iocb->ki_filp);
+         ext4_io_end_t *io_end = iocb->private;
+ 
+-	/* if not async direct IO just return */
+-	if (!io_end) {
+-		inode_dio_done(inode);
+-		if (is_async)
+-			aio_complete(iocb, ret, 0);
+-		return;
+-	}
++	/* if not async direct IO or dio with 0 bytes write, just return */
++	if (!io_end || !size)
++		goto out;
+ 
+ 	ext_debug("ext4_end_io_dio(): io_end 0x%p "
+ 		  "for inode %lu, iocb 0x%p, offset %llu, size %zd\n",
+@@ -3092,13 +3076,25 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
+ 		  size);
+ 
+ 	iocb->private = NULL;
++
++	/* if not aio dio with unwritten extents, just free io and return */
++	if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) {
++		ext4_free_io_end(io_end);
++out:
++		inode_dio_done(inode);
++		if (is_async)
++			aio_complete(iocb, ret, 0);
++		return;
++	}
++
+ 	io_end->offset = offset;
+ 	io_end->size = size;
+ 	if (is_async) {
+ 		io_end->iocb = iocb;
+ 		io_end->result = ret;
+ 	}
+-	ext4_put_io_end_defer(io_end);
++
++	ext4_add_complete_io(io_end);
+ }
+ 
+ /*
+@@ -3132,7 +3128,6 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
+ 	get_block_t *get_block_func = NULL;
+ 	int dio_flags = 0;
+ 	loff_t final_size = offset + count;
+-	ext4_io_end_t *io_end = NULL;
+ 
+ 	/* Use the old path for reads and writes beyond i_size. */
+ 	if (rw != WRITE || final_size > inode->i_size)
+@@ -3171,16 +3166,13 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
+ 	iocb->private = NULL;
+ 	ext4_inode_aio_set(inode, NULL);
+ 	if (!is_sync_kiocb(iocb)) {
+-		io_end = ext4_init_io_end(inode, GFP_NOFS);
++		ext4_io_end_t *io_end = ext4_init_io_end(inode, GFP_NOFS);
+ 		if (!io_end) {
+ 			ret = -ENOMEM;
+ 			goto retake_lock;
+ 		}
+ 		io_end->flag |= EXT4_IO_END_DIRECT;
+-		/*
+-		 * Grab reference for DIO. Will be dropped in ext4_end_io_dio()
+-		 */
+-		iocb->private = ext4_get_io_end(io_end);
++		iocb->private = io_end;
+ 		/*
+ 		 * we save the io structure for current async direct
+ 		 * IO, so that later ext4_map_blocks() could flag the
+@@ -3204,27 +3196,26 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
+ 				   NULL,
+ 				   dio_flags);
+ 
++	if (iocb->private)
++		ext4_inode_aio_set(inode, NULL);
+ 	/*
+-	 * Put our reference to io_end. This can free the io_end structure e.g.
+-	 * in sync IO case or in case of error. It can even perform extent
+-	 * conversion if all bios we submitted finished before we got here.
+-	 * Note that in that case iocb->private can be already set to NULL
+-	 * here.
++	 * The io_end structure takes a reference to the inode, that
++	 * structure needs to be destroyed and the reference to the
++	 * inode need to be dropped, when IO is complete, even with 0
++	 * byte write, or failed.
++	 *
++	 * In the successful AIO DIO case, the io_end structure will
++	 * be destroyed and the reference to the inode will be dropped
++	 * after the end_io call back function is called.
++	 *
++	 * In the case there is 0 byte write, or error case, since VFS
++	 * direct IO won't invoke the end_io call back function, we
++	 * need to free the end_io structure here.
+ 	 */
+-	if (io_end) {
+-		ext4_inode_aio_set(inode, NULL);
+-		ext4_put_io_end(io_end);
+-		/*
+-		 * In case of error or no write ext4_end_io_dio() was not
+-		 * called so we have to put iocb's reference.
+-		 */
+-		if (ret <= 0 && ret != -EIOCBQUEUED) {
+-			WARN_ON(iocb->private != io_end);
+-			ext4_put_io_end(io_end);
+-			iocb->private = NULL;
+-		}
+-	}
+-	if (ret > 0 && !overwrite && ext4_test_inode_state(inode,
++	if (ret != -EIOCBQUEUED && ret <= 0 && iocb->private) {
++		ext4_free_io_end(iocb->private);
++		iocb->private = NULL;
++	} else if (ret > 0 && !overwrite && ext4_test_inode_state(inode,
+ 						EXT4_STATE_DIO_UNWRITTEN)) {
+ 		int err;
+ 		/*
+diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
+index 5929cd0baa20..6626aba57ebb 100644
+--- a/fs/ext4/page-io.c
++++ b/fs/ext4/page-io.c
+@@ -61,28 +61,15 @@ void ext4_ioend_shutdown(struct inode *inode)
+ 		cancel_work_sync(&EXT4_I(inode)->i_unwritten_work);
+ }
+ 
+-static void ext4_release_io_end(ext4_io_end_t *io_end)
++void ext4_free_io_end(ext4_io_end_t *io)
+ {
+-	BUG_ON(!list_empty(&io_end->list));
+-	BUG_ON(io_end->flag & EXT4_IO_END_UNWRITTEN);
+-
+-	if (atomic_dec_and_test(&EXT4_I(io_end->inode)->i_ioend_count))
+-		wake_up_all(ext4_ioend_wq(io_end->inode));
+-	if (io_end->flag & EXT4_IO_END_DIRECT)
+-		inode_dio_done(io_end->inode);
+-	if (io_end->iocb)
+-		aio_complete(io_end->iocb, io_end->result, 0);
+-	kmem_cache_free(io_end_cachep, io_end);
+-}
+-
+-static void ext4_clear_io_unwritten_flag(ext4_io_end_t *io_end)
+-{
+-	struct inode *inode = io_end->inode;
++	BUG_ON(!io);
++	BUG_ON(!list_empty(&io->list));
++	BUG_ON(io->flag & EXT4_IO_END_UNWRITTEN);
+ 
+-	io_end->flag &= ~EXT4_IO_END_UNWRITTEN;
+-	/* Wake up anyone waiting on unwritten extent conversion */
+-	if (atomic_dec_and_test(&EXT4_I(inode)->i_unwritten))
+-		wake_up_all(ext4_ioend_wq(inode));
++	if (atomic_dec_and_test(&EXT4_I(io->inode)->i_ioend_count))
++		wake_up_all(ext4_ioend_wq(io->inode));
++	kmem_cache_free(io_end_cachep, io);
+ }
+ 
+ /* check a range of space and convert unwritten extents to written. */
+@@ -105,8 +92,13 @@ static int ext4_end_io(ext4_io_end_t *io)
+ 			 "(inode %lu, offset %llu, size %zd, error %d)",
+ 			 inode->i_ino, offset, size, ret);
+ 	}
+-	ext4_clear_io_unwritten_flag(io);
+-	ext4_release_io_end(io);
++	/* Wake up anyone waiting on unwritten extent conversion */
++	if (atomic_dec_and_test(&EXT4_I(inode)->i_unwritten))
++		wake_up_all(ext4_ioend_wq(inode));
++	if (io->flag & EXT4_IO_END_DIRECT)
++		inode_dio_done(inode);
++	if (io->iocb)
++		aio_complete(io->iocb, io->result, 0);
+ 	return ret;
+ }
+ 
+@@ -137,7 +129,7 @@ static void dump_completed_IO(struct inode *inode)
+ }
+ 
+ /* Add the io_end to per-inode completed end_io list. */
+-static void ext4_add_complete_io(ext4_io_end_t *io_end)
++void ext4_add_complete_io(ext4_io_end_t *io_end)
+ {
+ 	struct ext4_inode_info *ei = EXT4_I(io_end->inode);
+ 	struct workqueue_struct *wq;
+@@ -174,6 +166,8 @@ static int ext4_do_flush_completed_IO(struct inode *inode)
+ 		err = ext4_end_io(io);
+ 		if (unlikely(!ret && err))
+ 			ret = err;
++		io->flag &= ~EXT4_IO_END_UNWRITTEN;
++		ext4_free_io_end(io);
+ 	}
+ 	return ret;
+ }
+@@ -205,43 +199,10 @@ ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags)
+ 		atomic_inc(&EXT4_I(inode)->i_ioend_count);
+ 		io->inode = inode;
+ 		INIT_LIST_HEAD(&io->list);
+-		atomic_set(&io->count, 1);
+ 	}
+ 	return io;
+ }
+ 
+-void ext4_put_io_end_defer(ext4_io_end_t *io_end)
+-{
+-	if (atomic_dec_and_test(&io_end->count)) {
+-		if (!(io_end->flag & EXT4_IO_END_UNWRITTEN) || !io_end->size) {
+-			ext4_release_io_end(io_end);
+-			return;
+-		}
+-		ext4_add_complete_io(io_end);
+-	}
+-}
+-
+-int ext4_put_io_end(ext4_io_end_t *io_end)
+-{
+-	int err = 0;
+-
+-	if (atomic_dec_and_test(&io_end->count)) {
+-		if (io_end->flag & EXT4_IO_END_UNWRITTEN) {
+-			err = ext4_convert_unwritten_extents(io_end->inode,
+-						io_end->offset, io_end->size);
+-			ext4_clear_io_unwritten_flag(io_end);
+-		}
+-		ext4_release_io_end(io_end);
+-	}
+-	return err;
+-}
+-
+-ext4_io_end_t *ext4_get_io_end(ext4_io_end_t *io_end)
+-{
+-	atomic_inc(&io_end->count);
+-	return io_end;
+-}
+-
+ /*
+  * Print an buffer I/O error compatible with the fs/buffer.c.  This
+  * provides compatibility with dmesg scrapers that look for a specific
+@@ -324,7 +285,12 @@ static void ext4_end_bio(struct bio *bio, int error)
+ 			     bi_sector >> (inode->i_blkbits - 9));
+ 	}
+ 
+-	ext4_put_io_end_defer(io_end);
++	if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) {
++		ext4_free_io_end(io_end);
++		return;
++	}
++
++	ext4_add_complete_io(io_end);
+ }
+ 
+ void ext4_io_submit(struct ext4_io_submit *io)
+@@ -338,37 +304,40 @@ void ext4_io_submit(struct ext4_io_submit *io)
+ 		bio_put(io->io_bio);
+ 	}
+ 	io->io_bio = NULL;
+-}
+-
+-void ext4_io_submit_init(struct ext4_io_submit *io,
+-			 struct writeback_control *wbc)
+-{
+-	io->io_op = (wbc->sync_mode == WB_SYNC_ALL ?  WRITE_SYNC : WRITE);
+-	io->io_bio = NULL;
++	io->io_op = 0;
+ 	io->io_end = NULL;
+ }
+ 
+-static int io_submit_init_bio(struct ext4_io_submit *io,
+-			      struct buffer_head *bh)
++static int io_submit_init(struct ext4_io_submit *io,
++			  struct inode *inode,
++			  struct writeback_control *wbc,
++			  struct buffer_head *bh)
+ {
++	ext4_io_end_t *io_end;
++	struct page *page = bh->b_page;
+ 	int nvecs = bio_get_nr_vecs(bh->b_bdev);
+ 	struct bio *bio;
+ 
++	io_end = ext4_init_io_end(inode, GFP_NOFS);
++	if (!io_end)
++		return -ENOMEM;
+ 	bio = bio_alloc(GFP_NOIO, min(nvecs, BIO_MAX_PAGES));
+ 	bio->bi_sector = bh->b_blocknr * (bh->b_size >> 9);
+ 	bio->bi_bdev = bh->b_bdev;
++	bio->bi_private = io->io_end = io_end;
+ 	bio->bi_end_io = ext4_end_bio;
+-	bio->bi_private = ext4_get_io_end(io->io_end);
+-	if (!io->io_end->size)
+-		io->io_end->offset = (bh->b_page->index << PAGE_CACHE_SHIFT)
+-				     + bh_offset(bh);
++
++	io_end->offset = (page->index << PAGE_CACHE_SHIFT) + bh_offset(bh);
++
+ 	io->io_bio = bio;
++	io->io_op = (wbc->sync_mode == WB_SYNC_ALL ?  WRITE_SYNC : WRITE);
+ 	io->io_next_block = bh->b_blocknr;
+ 	return 0;
+ }
+ 
+ static int io_submit_add_bh(struct ext4_io_submit *io,
+ 			    struct inode *inode,
++			    struct writeback_control *wbc,
+ 			    struct buffer_head *bh)
+ {
+ 	ext4_io_end_t *io_end;
+@@ -379,18 +348,18 @@ static int io_submit_add_bh(struct ext4_io_submit *io,
+ 		ext4_io_submit(io);
+ 	}
+ 	if (io->io_bio == NULL) {
+-		ret = io_submit_init_bio(io, bh);
++		ret = io_submit_init(io, inode, wbc, bh);
+ 		if (ret)
+ 			return ret;
+ 	}
+-	ret = bio_add_page(io->io_bio, bh->b_page, bh->b_size, bh_offset(bh));
+-	if (ret != bh->b_size)
+-		goto submit_and_retry;
+ 	io_end = io->io_end;
+ 	if (test_clear_buffer_uninit(bh))
+ 		ext4_set_io_unwritten_flag(inode, io_end);
+-	io_end->size += bh->b_size;
++	io->io_end->size += bh->b_size;
+ 	io->io_next_block++;
++	ret = bio_add_page(io->io_bio, bh->b_page, bh->b_size, bh_offset(bh));
++	if (ret != bh->b_size)
++		goto submit_and_retry;
+ 	return 0;
+ }
+ 
+@@ -462,7 +431,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
+ 	do {
+ 		if (!buffer_async_write(bh))
+ 			continue;
+-		ret = io_submit_add_bh(io, inode, bh);
++		ret = io_submit_add_bh(io, inode, wbc, bh);
+ 		if (ret) {
+ 			/*
+ 			 * We only get here on ENOMEM.  Not much else

commit 0d606e2c9fccdd4e67febf1e2da500e1bfe9e045
+Author: Theodore Ts'o 
+Date:   Tue Apr 23 08:59:35 2013 -0400
+
+    ext4: fix type-widening bug in inode table readahead code
+    
+    Due to a missing cast, the high 32-bits of a 64-bit block number used
+    when calculating the readahead block for inode tables can get lost.
+    This means we can end up fetching the wrong blocks for readahead for
+    file systems > 16TB.
+    
+    Linus found this when experimenting with an enhacement to the sparse
+    static code checker which checks for missing widening casts before
+    binary "not" operators.
+    
+    Reported-by: Linus Torvalds 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index d7518e2728f1..793d44b84d7f 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4011,13 +4011,14 @@ static int __ext4_get_inode_loc(struct inode *inode,
+ 		if (EXT4_SB(sb)->s_inode_readahead_blks) {
+ 			ext4_fsblk_t b, end, table;
+ 			unsigned num;
++			__u32 ra_blks = EXT4_SB(sb)->s_inode_readahead_blks;
+ 
+ 			table = ext4_inode_table(sb, gdp);
+ 			/* s_inode_readahead_blks is always a power of 2 */
+-			b = block & ~(EXT4_SB(sb)->s_inode_readahead_blks-1);
++			b = block & ~((ext4_fsblk_t) ra_blks - 1);
+ 			if (table > b)
+ 				b = table;
+-			end = b + EXT4_SB(sb)->s_inode_readahead_blks;
++			end = b + ra_blks;
+ 			num = EXT4_INODES_PER_GROUP(sb);
+ 			if (ext4_has_group_desc_csum(sb))
+ 				num -= ext4_itable_unused_count(sb, gdp);

commit 3f8a6411fbada1fa482276591e037f3b1adcf55b
+Author: Theodore Ts'o 
+Date:   Sun Apr 21 22:56:32 2013 -0400
+
+    ext4: add check for inodes_count overflow in new resize ioctl
+    
+    Addresses-Red-Hat-Bugzilla: #913245
+    
+    Reported-by: Eric Sandeen 
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Carlos Maiolino 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 08d2312c0fd4..b27c96d01965 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -1882,6 +1882,10 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
+ 		return 0;
+ 
+ 	n_group = ext4_get_group_number(sb, n_blocks_count - 1);
++	if (n_group > (0xFFFFFFFFUL / EXT4_INODES_PER_GROUP(sb))) {
++		ext4_warning(sb, "resize would cause inodes_count overflow");
++		return -EINVAL;
++	}
+ 	ext4_get_group_no_and_offset(sb, o_blocks_count - 1, &o_group, &offset);
+ 
+ 	n_desc_blocks = num_desc_blocks(sb, n_group + 1);

commit 7f3e3c7cfcec148ccca9c0dd2dbfd7b00b7ac10f
+Author: Theodore Ts'o 
+Date:   Sun Apr 21 20:32:03 2013 -0400
+
+    ext4: fix Kconfig documentation for CONFIG_EXT4_DEBUG
+    
+    Fox the Kconfig documentation for CONFIG_EXT4_DEBUG to match the
+    change made by commit a0b30c1229: ext4: use module parameters instead
+    of debugfs for mballoc_debug
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
+index 987358740cb9..efea5d5c44ce 100644
+--- a/fs/ext4/Kconfig
++++ b/fs/ext4/Kconfig
+@@ -71,4 +71,5 @@ config EXT4_DEBUG
+ 	  Enables run-time debugging support for the ext4 filesystem.
+ 
+ 	  If you select Y here, then you will be able to turn on debugging
+-	  with a command such as "echo 1 > /sys/kernel/debug/ext4/mballoc-debug"
++	  with a command such as:
++		echo 1 > /sys/module/ext4/parameters/mballoc_debug

commit c5c72d814cf0f650010337c73638b25e6d14d2d4
+Author: Theodore Ts'o 
+Date:   Sun Apr 21 20:19:43 2013 -0400
+
+    ext4: fix online resizing for ext3-compat file systems
+    
+    Commit fb0a387dcdc restricts block allocations for indirect-mapped
+    files to block groups less than s_blockfile_groups.  However, the
+    online resizing code wasn't setting s_blockfile_groups, so the newly
+    added block groups were not available for non-extent mapped files.
+    
+    Reported-by: Eric Sandeen 
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index e3498534a2c1..08d2312c0fd4 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -1341,6 +1341,8 @@ static void ext4_update_super(struct super_block *sb,
+ 
+ 	/* Update the global fs size fields */
+ 	sbi->s_groups_count += flex_gd->count;
++	sbi->s_blockfile_groups = min_t(ext4_group_t, sbi->s_groups_count,
++			(EXT4_MAX_BLOCK_FILE_PHYS / EXT4_BLOCKS_PER_GROUP(sb)));
+ 
+ 	/* Update the reserved block counts only once the new group is
+ 	 * active. */

commit f783f091e49ce4896e6b026af82d76e0537c6089
+Author: Theodore Ts'o 
+Date:   Sun Apr 21 16:47:54 2013 -0400
+
+    jbd2: trace when lock_buffer in do_get_write_access takes a long time
+    
+    While investigating interactivity problems it was clear that processes
+    sometimes stall for long periods of times if an attempt is made to
+    lock a buffer which is undergoing writeback.  It would stall in
+    a trace looking something like
+    
+    [] __lock_buffer+0x2e/0x30
+    [] do_get_write_access+0x43f/0x4b0
+    [] jbd2_journal_get_write_access+0x2b/0x50
+    [] __ext4_journal_get_write_access+0x39/0x80
+    [] ext4_reserve_inode_write+0x78/0xa0
+    [] ext4_mark_inode_dirty+0x49/0x220
+    [] ext4_dirty_inode+0x41/0x60
+    [] __mark_inode_dirty+0x4e/0x2d0
+    [] update_time+0x79/0xc0
+    [] file_update_time+0x98/0x100
+    [] __generic_file_aio_write+0x17c/0x3b0
+    [] generic_file_aio_write+0x7a/0xf0
+    [] ext4_file_write+0x83/0xd0
+    [] do_sync_write+0xa3/0xe0
+    [] vfs_write+0xae/0x180
+    [] sys_write+0x4d/0x90
+    [] system_call_fastpath+0x1a/0x1f
+    [] 0xffffffffffffffff
+    
+    Signed-off-by: Mel Gorman 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index a1920da22802..10f524c59ea8 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -639,6 +639,7 @@ do_get_write_access(handle_t *handle, struct journal_head *jh,
+ 	int error;
+ 	char *frozen_buffer = NULL;
+ 	int need_copy = 0;
++	unsigned long start_lock, time_lock;
+ 
+ 	if (is_handle_aborted(handle))
+ 		return -EROFS;
+@@ -654,9 +655,16 @@ do_get_write_access(handle_t *handle, struct journal_head *jh,
+ 
+ 	/* @@@ Need to check for errors here at some point. */
+ 
++ 	start_lock = jiffies;
+ 	lock_buffer(bh);
+ 	jbd_lock_bh_state(bh);
+ 
++	/* If it takes too long to lock the buffer, trace it */
++	time_lock = jbd2_time_diff(start_lock, jiffies);
++	if (time_lock > HZ/10)
++		trace_jbd2_lock_buffer_stall(bh->b_bdev->bd_dev,
++			jiffies_to_msecs(time_lock));
++
+ 	/* We now hold the buffer lock so it is safe to query the buffer
+ 	 * state.  Is the buffer dirty?
+ 	 *
+diff --git a/include/trace/events/jbd2.h b/include/trace/events/jbd2.h
+index 070df49e4a1d..c1d1f3eb242d 100644
+--- a/include/trace/events/jbd2.h
++++ b/include/trace/events/jbd2.h
+@@ -358,6 +358,27 @@ TRACE_EVENT(jbd2_write_superblock,
+ 		  MINOR(__entry->dev), __entry->write_op)
+ );
+ 
++TRACE_EVENT(jbd2_lock_buffer_stall,
++
++	TP_PROTO(dev_t dev, unsigned long stall_ms),
++
++	TP_ARGS(dev, stall_ms),
++
++	TP_STRUCT__entry(
++		__field(        dev_t, dev	)
++		__field(unsigned long, stall_ms	)
++	),
++
++	TP_fast_assign(
++		__entry->dev		= dev;
++		__entry->stall_ms	= stall_ms;
++	),
++
++	TP_printk("dev %d,%d stall_ms %lu",
++		MAJOR(__entry->dev), MINOR(__entry->dev),
++		__entry->stall_ms)
++);
++
+ #endif /* _TRACE_JBD2_H */
+ 
+ /* This part must be outside protection */

commit 13fca323e9a8b63c08de7a4e05d3c702516b535d
+Author: Theodore Ts'o 
+Date:   Sun Apr 21 16:45:54 2013 -0400
+
+    ext4: mark metadata blocks using bh flags
+    
+    This allows metadata writebacks which are issued via block device
+    writeback to be sent with the current write request flags.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
+index 0e1dc9e70ce5..451eb4045330 100644
+--- a/fs/ext4/ext4_jbd2.c
++++ b/fs/ext4/ext4_jbd2.c
+@@ -215,6 +215,8 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
+ 
+ 	might_sleep();
+ 
++	set_buffer_meta(bh);
++	set_buffer_prio(bh);
+ 	if (ext4_handle_valid(handle)) {
+ 		err = jbd2_journal_dirty_metadata(handle, bh);
+ 		if (err) {
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 62492e954483..d7518e2728f1 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1080,10 +1080,14 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
+ /* For write_end() in data=journal mode */
+ static int write_end_fn(handle_t *handle, struct buffer_head *bh)
+ {
++	int ret;
+ 	if (!buffer_mapped(bh) || buffer_freed(bh))
+ 		return 0;
+ 	set_buffer_uptodate(bh);
+-	return ext4_handle_dirty_metadata(handle, NULL, bh);
++	ret = ext4_handle_dirty_metadata(handle, NULL, bh);
++	clear_buffer_meta(bh);
++	clear_buffer_prio(bh);
++	return ret;
+ }
+ 
+ /*

commit 877f962c5edacfef60ab21cfed6d8d54ce25b8a6
+Author: Theodore Ts'o 
+Date:   Sat Apr 20 19:58:37 2013 -0400
+
+    buffer: add BH_Prio and BH_Meta flags
+    
+    Add buffer_head flags so that buffer cache writebacks can be marked
+    with the the appropriate request flags, so that metadata blocks can be
+    marked appropriately in blktrace.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/buffer.c b/fs/buffer.c
+index b4dcb34c9635..a15575c0b9ee 100644
+--- a/fs/buffer.c
++++ b/fs/buffer.c
+@@ -2988,6 +2988,11 @@ int submit_bh(int rw, struct buffer_head * bh)
+ 	/* Take care of bh's that straddle the end of the device */
+ 	guard_bh_eod(rw, bio, bh);
+ 
++	if (buffer_meta(bh))
++		rw |= REQ_META;
++	if (buffer_prio(bh))
++		rw |= REQ_PRIO;
++
+ 	bio_get(bio);
+ 	submit_bio(rw, bio);
+ 
+diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
+index 5afc4f94d110..33c0f8103fe4 100644
+--- a/include/linux/buffer_head.h
++++ b/include/linux/buffer_head.h
+@@ -34,6 +34,8 @@ enum bh_state_bits {
+ 	BH_Write_EIO,	/* I/O error on write */
+ 	BH_Unwritten,	/* Buffer is allocated on disk but not written */
+ 	BH_Quiet,	/* Buffer Error Prinks to be quiet */
++	BH_Meta,	/* Buffer contains metadata */
++	BH_Prio,	/* Buffer should be submitted with REQ_PRIO */
+ 
+ 	BH_PrivateStart,/* not a state bit, but the first bit available
+ 			 * for private allocation by other entities
+@@ -124,6 +126,8 @@ BUFFER_FNS(Delay, delay)
+ BUFFER_FNS(Boundary, boundary)
+ BUFFER_FNS(Write_EIO, write_io_error)
+ BUFFER_FNS(Unwritten, unwritten)
++BUFFER_FNS(Meta, meta)
++BUFFER_FNS(Prio, prio)
+ 
+ #define bh_offset(bh)		((unsigned long)(bh)->b_data & ~PAGE_MASK)
+ 

commit 9f203507ed277ee86e3f76a15e09db1c92e40b94
+Author: Theodore Ts'o 
+Date:   Sat Apr 20 15:46:17 2013 -0400
+
+    ext4: mark all metadata I/O with REQ_META
+    
+    As Dave Chinner pointed out at the 2013 LSF/MM workshop, it's
+    important that metadata I/O requests are marked as such to avoid
+    priority inversions caused by I/O bandwidth throttling.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 8dcaea69e37f..d0f13eada0ed 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -441,7 +441,7 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group)
+ 	trace_ext4_read_block_bitmap_load(sb, block_group);
+ 	bh->b_end_io = ext4_end_bitmap_read;
+ 	get_bh(bh);
+-	submit_bh(READ, bh);
++	submit_bh(READ | REQ_META | REQ_PRIO, bh);
+ 	return bh;
+ verify:
+ 	ext4_validate_block_bitmap(sb, desc, block_group, bh);
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 18d36d85f5c9..00a818d67b54 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -166,7 +166,7 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
+ 	trace_ext4_load_inode_bitmap(sb, block_group);
+ 	bh->b_end_io = ext4_end_bitmap_read;
+ 	get_bh(bh);
+-	submit_bh(READ, bh);
++	submit_bh(READ | REQ_META | REQ_PRIO, bh);
+ 	wait_on_buffer(bh);
+ 	if (!buffer_uptodate(bh)) {
+ 		put_bh(bh);
+diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c
+index b3b1f7d99448..214461e42a05 100644
+--- a/fs/ext4/mmp.c
++++ b/fs/ext4/mmp.c
+@@ -54,7 +54,7 @@ static int write_mmp_block(struct super_block *sb, struct buffer_head *bh)
+ 	lock_buffer(bh);
+ 	bh->b_end_io = end_buffer_write_sync;
+ 	get_bh(bh);
+-	submit_bh(WRITE_SYNC, bh);
++	submit_bh(WRITE_SYNC | REQ_META | REQ_PRIO, bh);
+ 	wait_on_buffer(bh);
+ 	sb_end_write(sb);
+ 	if (unlikely(!buffer_uptodate(bh)))
+@@ -86,7 +86,7 @@ static int read_mmp_block(struct super_block *sb, struct buffer_head **bh,
+ 		get_bh(*bh);
+ 		lock_buffer(*bh);
+ 		(*bh)->b_end_io = end_buffer_read_sync;
+-		submit_bh(READ_SYNC, *bh);
++		submit_bh(READ_SYNC | REQ_META | REQ_PRIO, *bh);
+ 		wait_on_buffer(*bh);
+ 		if (!buffer_uptodate(*bh)) {
+ 			brelse(*bh);
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index bfa29ecfb47a..dbc7c090c13a 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4252,7 +4252,7 @@ static journal_t *ext4_get_dev_journal(struct super_block *sb,
+ 		goto out_bdev;
+ 	}
+ 	journal->j_private = sb;
+-	ll_rw_block(READ, 1, &journal->j_sb_buffer);
++	ll_rw_block(READ | REQ_META | REQ_PRIO, 1, &journal->j_sb_buffer);
+ 	wait_on_buffer(journal->j_sb_buffer);
+ 	if (!buffer_uptodate(journal->j_sb_buffer)) {
+ 		ext4_msg(sb, KERN_ERR, "I/O error on journal device");

commit fd03d8daf417fffbcb27fdb30d60f6c81ed813c8
+Author: Theodore Ts'o 
+Date:   Thu Apr 18 14:53:15 2013 -0400
+
+    ext4: reserve xattr index for Rich ACL support
+    
+    Jan Kara 
+    
+    SUSE is carrying out of tree patches for Rich ACL support for ext4 as
+    they didn't get upstream due to opposition of some VFS maintainers.
+    Reserve xattr index for Rich ACLs so that it cannot be taken by
+    anything else which would force users to backup and reset their Rich
+    ACLs on files.
+    
+    Signed-off-by: Jan Kara 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
+index aa25deb5c6cd..c767dbdd7fc4 100644
+--- a/fs/ext4/xattr.h
++++ b/fs/ext4/xattr.h
+@@ -22,6 +22,7 @@
+ #define	EXT4_XATTR_INDEX_LUSTRE			5
+ #define EXT4_XATTR_INDEX_SECURITY	        6
+ #define EXT4_XATTR_INDEX_SYSTEM			7
++#define EXT4_XATTR_INDEX_RICHACL		8
+ 
+ struct ext4_xattr_header {
+ 	__le32	h_magic;	/* magic number for identification */

commit d6a771056b32146da1280f7872f6936b0c7770ea
+Author: Theodore Ts'o 
+Date:   Tue Apr 9 23:59:55 2013 -0400
+
+    ext4: fix miscellaneous big endian warnings
+    
+    None of these result in any bug, but they makes sparse complain.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 3825d6aa8336..45a5ca89797f 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -416,15 +416,16 @@ static __le32 ext4_dx_csum(struct inode *inode, struct ext4_dir_entry *dirent,
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+ 	struct ext4_inode_info *ei = EXT4_I(inode);
+-	__u32 csum, old_csum;
++	__u32 csum;
++	__le32 save_csum;
+ 	int size;
+ 
+ 	size = count_offset + (count * sizeof(struct dx_entry));
+-	old_csum = t->dt_checksum;
++	save_csum = t->dt_checksum;
+ 	t->dt_checksum = 0;
+ 	csum = ext4_chksum(sbi, ei->i_csum_seed, (__u8 *)dirent, size);
+ 	csum = ext4_chksum(sbi, csum, (__u8 *)t, sizeof(struct dx_tail));
+-	t->dt_checksum = old_csum;
++	t->dt_checksum = save_csum;
+ 
+ 	return cpu_to_le32(csum);
+ }
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 6fea87db7daa..f355c28fa080 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1952,16 +1952,16 @@ static __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 block_group,
+ 	if ((sbi->s_es->s_feature_ro_compat &
+ 	     cpu_to_le32(EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))) {
+ 		/* Use new metadata_csum algorithm */
+-		__u16 old_csum;
++		__le16 save_csum;
+ 		__u32 csum32;
+ 
+-		old_csum = gdp->bg_checksum;
++		save_csum = gdp->bg_checksum;
+ 		gdp->bg_checksum = 0;
+ 		csum32 = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&le_group,
+ 				     sizeof(le_group));
+ 		csum32 = ext4_chksum(sbi, csum32, (__u8 *)gdp,
+ 				     sbi->s_desc_size);
+-		gdp->bg_checksum = old_csum;
++		gdp->bg_checksum = save_csum;
+ 
+ 		crc = csum32 & 0xFFFF;
+ 		goto out;
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 3a120b277240..c081e34f717f 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -122,17 +122,18 @@ static __le32 ext4_xattr_block_csum(struct inode *inode,
+ 				    struct ext4_xattr_header *hdr)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+-	__u32 csum, old;
++	__u32 csum;
++	__le32 save_csum;
++	__le64 dsk_block_nr = cpu_to_le64(block_nr);
+ 
+-	old = hdr->h_checksum;
++	save_csum = hdr->h_checksum;
+ 	hdr->h_checksum = 0;
+-	block_nr = cpu_to_le64(block_nr);
+-	csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&block_nr,
+-			   sizeof(block_nr));
++	csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&dsk_block_nr,
++			   sizeof(dsk_block_nr));
+ 	csum = ext4_chksum(sbi, csum, (__u8 *)hdr,
+ 			   EXT4_BLOCK_SIZE(inode->i_sb));
+ 
+-	hdr->h_checksum = old;
++	hdr->h_checksum = save_csum;
+ 	return cpu_to_le32(csum);
+ }
+ 
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index 58459b785565..d0e686402df8 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -1948,7 +1948,7 @@ TRACE_EVENT(ext4_remove_blocks,
+ 		__entry->to		= to;
+ 		__entry->partial	= partial_cluster;
+ 		__entry->ee_pblk	= ext4_ext_pblock(ex);
+-		__entry->ee_lblk	= cpu_to_le32(ex->ee_block);
++		__entry->ee_lblk	= le32_to_cpu(ex->ee_block);
+ 		__entry->ee_len		= ext4_ext_get_actual_len(ex);
+ 	),
+ 
+@@ -2052,7 +2052,7 @@ TRACE_EVENT(ext4_ext_remove_space,
+ 
+ TRACE_EVENT(ext4_ext_remove_space_done,
+ 	TP_PROTO(struct inode *inode, ext4_lblk_t start, int depth,
+-		ext4_lblk_t partial, unsigned short eh_entries),
++		ext4_lblk_t partial, __le16 eh_entries),
+ 
+ 	TP_ARGS(inode, start, depth, partial, eh_entries),
+ 
+@@ -2071,7 +2071,7 @@ TRACE_EVENT(ext4_ext_remove_space_done,
+ 		__entry->start		= start;
+ 		__entry->depth		= depth;
+ 		__entry->partial	= partial;
+-		__entry->eh_entries	= eh_entries;
++		__entry->eh_entries	= le16_to_cpu(eh_entries);
+ 	),
+ 
+ 	TP_printk("dev %d,%d ino %lu since %u depth %d partial %u "

commit 996bb9fddd5b68d1dfb5e27d30ca2c7a72448596
+Author: Theodore Ts'o 
+Date:   Wed Apr 3 22:04:52 2013 -0400
+
+    ext4: support simple conversion of extent-mapped inodes to use i_blocks
+    
+    In order to make it simpler to test the code which support
+    i_blocks/indirect-mapped inodes, support the conversion of inodes
+    which are less than 12 blocks and which are contained in no more than
+    a single extent.
+    
+    The primary intended use of this code is to converting freshly created
+    zero-length files and empty directories.
+    
+    Note that the version of chattr in e2fsprogs 1.42.7 and earlier has a
+    check that prevents the clearing of the extent flag.  A simple patch
+    which allows "chattr -e " to work will be checked into the
+    e2fsprogs git repository.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index d05ba3886f33..73f3e60f7078 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -403,7 +403,7 @@ struct flex_groups {
+ #define EXT4_RESERVED_FL		0x80000000 /* reserved for ext4 lib */
+ 
+ #define EXT4_FL_USER_VISIBLE		0x004BDFFF /* User visible flags */
+-#define EXT4_FL_USER_MODIFIABLE		0x004B80FF /* User modifiable flags */
++#define EXT4_FL_USER_MODIFIABLE		0x004380FF /* User modifiable flags */
+ 
+ /* Flags that should be inherited by new inodes from their parent. */
+ #define EXT4_FL_INHERITED (EXT4_SECRM_FL | EXT4_UNRM_FL | EXT4_COMPR_FL |\
+@@ -2608,6 +2608,7 @@ extern int ext4_find_delalloc_range(struct inode *inode,
+ extern int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk);
+ extern int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ 			__u64 start, __u64 len);
++extern int ext4_ind_migrate(struct inode *inode);
+ 
+ 
+ /* move_extent.c */
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index cbbe8a4deac6..235246719074 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -4610,3 +4610,62 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ 
+ 	return error;
+ }
++
++/*
++ * Migrate a simple extent-based inode to use the i_blocks[] array
++ */
++int ext4_ind_migrate(struct inode *inode)
++{
++	struct ext4_extent_header	*eh;
++	struct ext4_super_block		*es = EXT4_SB(inode->i_sb)->s_es;
++	struct ext4_inode_info		*ei = EXT4_I(inode);
++	struct ext4_extent		*ex;
++	unsigned int			i, len;
++	ext4_fsblk_t			blk;
++	handle_t			*handle;
++	int				ret;
++
++	if (!EXT4_HAS_INCOMPAT_FEATURE(inode->i_sb,
++				       EXT4_FEATURE_INCOMPAT_EXTENTS) ||
++	    (!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
++		return -EINVAL;
++
++	down_write(&EXT4_I(inode)->i_data_sem);
++	ret = ext4_ext_check_inode(inode);
++	if (ret)
++		goto errout;
++
++	eh = ext_inode_hdr(inode);
++	ex  = EXT_FIRST_EXTENT(eh);
++	if (ext4_blocks_count(es) > EXT4_MAX_BLOCK_FILE_PHYS ||
++	    eh->eh_depth != 0 || eh->eh_entries > 1) {
++		ret = -EOPNOTSUPP;
++		goto errout;
++	}
++	if (eh->eh_entries == 0)
++		blk = len = 0;
++	else {
++		len = le16_to_cpu(ex->ee_len);
++		blk = ext4_ext_pblock(ex);
++		if (len > EXT4_NDIR_BLOCKS) {
++			ret = -EOPNOTSUPP;
++			goto errout;
++		}
++	}
++
++	handle = ext4_journal_start(inode, EXT4_HT_MIGRATE, 1);
++	if (IS_ERR(handle)) {
++		ret = PTR_ERR(handle);
++		goto errout;
++	}
++
++	ext4_clear_inode_flag(inode, EXT4_INODE_EXTENTS);
++	memset(ei->i_data, 0, sizeof(ei->i_data));
++	for (i=0; i < len; i++)
++		ei->i_data[i] = cpu_to_le32(blk++);
++	ext4_mark_inode_dirty(handle, inode);
++	ext4_journal_stop(handle);
++errout:
++	up_write(&EXT4_I(inode)->i_data_sem);
++	return ret;
++}
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index 721f4d33e148..a07b7bc0856a 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -83,17 +83,8 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 			if (!capable(CAP_SYS_RESOURCE))
+ 				goto flags_out;
+ 		}
+-		if (oldflags & EXT4_EXTENTS_FL) {
+-			/* We don't support clearning extent flags */
+-			if (!(flags & EXT4_EXTENTS_FL)) {
+-				err = -EOPNOTSUPP;
+-				goto flags_out;
+-			}
+-		} else if (flags & EXT4_EXTENTS_FL) {
+-			/* migrate the file */
++		if ((flags ^ oldflags) & EXT4_EXTENTS_FL)
+ 			migrate = 1;
+-			flags &= ~EXT4_EXTENTS_FL;
+-		}
+ 
+ 		if (flags & EXT4_EOFBLOCKS_FL) {
+ 			/* we don't support adding EOFBLOCKS flag */
+@@ -137,8 +128,13 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 			err = ext4_change_inode_journal_flag(inode, jflag);
+ 		if (err)
+ 			goto flags_out;
+-		if (migrate)
+-			err = ext4_ext_migrate(inode);
++		if (migrate) {
++			if (flags & EXT4_EXTENTS_FL)
++				err = ext4_ext_migrate(inode);
++			else
++				err = ext4_ind_migrate(inode);
++		}
++
+ flags_out:
+ 		mutex_unlock(&inode->i_mutex);
+ 		mnt_drop_write_file(filp);

commit d76a3a77113db020d9bb1e894822869410450bd9
+Author: Theodore Ts'o 
+Date:   Wed Apr 3 22:02:52 2013 -0400
+
+    ext4/jbd2: don't wait (forever) for stale tid caused by wraparound
+    
+    In the case where an inode has a very stale transaction id (tid) in
+    i_datasync_tid or i_sync_tid, it's possible that after a very large
+    (2**31) number of transactions, that the tid number space might wrap,
+    causing tid_geq()'s calculations to fail.
+    
+    Commit deeeaf13 "jbd2: fix fsync() tid wraparound bug", later modified
+    by commit e7b04ac0 "jbd2: don't wake kjournald unnecessarily",
+    attempted to fix this problem, but it only avoided kjournald spinning
+    forever by fixing the logic in jbd2_log_start_commit().
+    
+    Unfortunately, in the codepaths in fs/ext4/fsync.c and fs/ext4/inode.c
+    that might call jbd2_log_start_commit() with a stale tid, those
+    functions will subsequently call jbd2_log_wait_commit() with the same
+    stale tid, and then wait for a very long time.  To fix this, we
+    replace the calls to jbd2_log_start_commit() and
+    jbd2_log_wait_commit() with a call to a new function,
+    jbd2_complete_transaction(), which will correctly handle stale tid's.
+    
+    As a bonus, jbd2_complete_transaction() will avoid locking
+    j_state_lock for writing unless a commit needs to be started.  This
+    should have a small (but probably not measurable) improvement for
+    ext4's scalability.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reported-by: Ben Hutchings 
+    Reported-by: George Barnett 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
+index 3278e64e57b6..e0ba8a408def 100644
+--- a/fs/ext4/fsync.c
++++ b/fs/ext4/fsync.c
+@@ -166,8 +166,7 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
+ 	if (journal->j_flags & JBD2_BARRIER &&
+ 	    !jbd2_trans_will_send_data_barrier(journal, commit_tid))
+ 		needs_barrier = true;
+-	jbd2_log_start_commit(journal, commit_tid);
+-	ret = jbd2_log_wait_commit(journal, commit_tid);
++	ret = jbd2_complete_transaction(journal, commit_tid);
+ 	if (needs_barrier) {
+ 		err = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
+ 		if (!ret)
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 56ebd662033b..addba9e0a1a4 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -210,8 +210,7 @@ void ext4_evict_inode(struct inode *inode)
+ 			journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
+ 			tid_t commit_tid = EXT4_I(inode)->i_datasync_tid;
+ 
+-			jbd2_log_start_commit(journal, commit_tid);
+-			jbd2_log_wait_commit(journal, commit_tid);
++			jbd2_complete_transaction(journal, commit_tid);
+ 			filemap_write_and_wait(&inode->i_data);
+ 		}
+ 		truncate_inode_pages(&inode->i_data, 0);
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index ed10991ab006..886ec2faa9b4 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -709,6 +709,37 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid)
+ 	return err;
+ }
+ 
++/*
++ * When this function returns the transaction corresponding to tid
++ * will be completed.  If the transaction has currently running, start
++ * committing that transaction before waiting for it to complete.  If
++ * the transaction id is stale, it is by definition already completed,
++ * so just return SUCCESS.
++ */
++int jbd2_complete_transaction(journal_t *journal, tid_t tid)
++{
++	int	need_to_wait = 1;
++
++	read_lock(&journal->j_state_lock);
++	if (journal->j_running_transaction &&
++	    journal->j_running_transaction->t_tid == tid) {
++		if (journal->j_commit_request != tid) {
++			/* transaction not yet started, so request it */
++			read_unlock(&journal->j_state_lock);
++			jbd2_log_start_commit(journal, tid);
++			goto wait_commit;
++		}
++	} else if (!(journal->j_committing_transaction &&
++		     journal->j_committing_transaction->t_tid == tid))
++		need_to_wait = 0;
++	read_unlock(&journal->j_state_lock);
++	if (!need_to_wait)
++		return 0;
++wait_commit:
++	return jbd2_log_wait_commit(journal, tid);
++}
++EXPORT_SYMBOL(jbd2_complete_transaction);
++
+ /*
+  * Log buffer allocation routines:
+  */
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index 50e5a5e6a712..f0289754b464 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -1200,6 +1200,7 @@ int __jbd2_log_start_commit(journal_t *journal, tid_t tid);
+ int jbd2_journal_start_commit(journal_t *journal, tid_t *tid);
+ int jbd2_journal_force_commit_nested(journal_t *journal);
+ int jbd2_log_wait_commit(journal_t *journal, tid_t tid);
++int jbd2_complete_transaction(journal_t *journal, tid_t tid);
+ int jbd2_log_do_checkpoint(journal_t *journal);
+ int jbd2_trans_will_send_data_barrier(journal_t *journal, tid_t tid);
+ 

commit b10a44c369d7b8a28825f1fd24f13dc31c2e3a25
+Author: Theodore Ts'o 
+Date:   Wed Apr 3 22:00:52 2013 -0400
+
+    ext4: add might_sleep() annotations
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Lukas Czerner 
+
+diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
+index 7058975e3a55..0e1dc9e70ce5 100644
+--- a/fs/ext4/ext4_jbd2.c
++++ b/fs/ext4/ext4_jbd2.c
+@@ -43,6 +43,8 @@ handle_t *__ext4_journal_start_sb(struct super_block *sb, unsigned int line,
+ {
+ 	journal_t *journal;
+ 
++	might_sleep();
++
+ 	trace_ext4_journal_start(sb, nblocks, _RET_IP_);
+ 	if (sb->s_flags & MS_RDONLY)
+ 		return ERR_PTR(-EROFS);
+@@ -113,6 +115,8 @@ int __ext4_journal_get_write_access(const char *where, unsigned int line,
+ {
+ 	int err = 0;
+ 
++	might_sleep();
++
+ 	if (ext4_handle_valid(handle)) {
+ 		err = jbd2_journal_get_write_access(handle, bh);
+ 		if (err)
+@@ -209,6 +213,8 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
+ {
+ 	int err = 0;
+ 
++	might_sleep();
++
+ 	if (ext4_handle_valid(handle)) {
+ 		err = jbd2_journal_dirty_metadata(handle, bh);
+ 		if (err) {
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index ee6614bdb639..36c82a39d03f 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -1011,6 +1011,7 @@ int ext4_mb_init_group(struct super_block *sb, ext4_group_t group)
+ 	struct page *page;
+ 	int ret = 0;
+ 
++	might_sleep();
+ 	mb_debug(1, "init group %u\n", group);
+ 	this_grp = ext4_get_group_info(sb, group);
+ 	/*
+@@ -1082,6 +1083,7 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group,
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	struct inode *inode = sbi->s_buddy_cache;
+ 
++	might_sleep();
+ 	mb_debug(1, "load group %u\n", group);
+ 
+ 	blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize;
+@@ -4217,6 +4219,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
+ 	unsigned int inquota = 0;
+ 	unsigned int reserv_clstrs = 0;
+ 
++	might_sleep();
+ 	sb = ar->inode->i_sb;
+ 	sbi = EXT4_SB(sb);
+ 
+@@ -4470,6 +4473,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 	int err = 0;
+ 	int ret;
+ 
++	might_sleep();
+ 	if (bh) {
+ 		if (block)
+ 			BUG_ON(block != bh->b_blocknr);

commit 19b5ef615787062a87c4ea15fcdb0e256b62ed19
+Author: Theodore Ts'o 
+Date:   Wed Apr 3 21:58:52 2013 -0400
+
+    ext4: add mutex_is_locked() assertion to ext4_truncate()
+    
+    [ Added fixup from Lukáš Czerner which only checks the assertion when
+      the inode is not new and is not being freed. ]
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 49c80e4ac5ac..56ebd662033b 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -3788,6 +3788,13 @@ void ext4_truncate(struct inode *inode)
+ 	struct address_space *mapping = inode->i_mapping;
+ 	loff_t page_len;
+ 
++	/*
++	 * There is a possibility that we're either freeing the inode
++	 * or it completely new indode. In those cases we might not
++	 * have i_mutex locked because it's not necessary.
++	 */
++	if (!(inode->i_state & (I_NEW|I_FREEING)))
++		WARN_ON(!mutex_is_locked(&inode->i_mutex));
+ 	trace_ext4_truncate_enter(inode);
+ 
+ 	if (!ext4_can_truncate(inode))

commit 819c4920b7e60ecfd6f0f61d890af4cdf3873d18
+Author: Theodore Ts'o 
+Date:   Wed Apr 3 12:47:17 2013 -0400
+
+    ext4: refactor truncate code
+    
+    Move common code in ext4_ind_truncate() and ext4_ext_truncate() into
+    ext4_truncate().  This saves over 60 lines of code.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 0649253804c4..d05ba3886f33 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2109,7 +2109,7 @@ extern ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb,
+ 				unsigned long nr_segs);
+ extern int ext4_ind_calc_metadata_amount(struct inode *inode, sector_t lblock);
+ extern int ext4_ind_trans_blocks(struct inode *inode, int nrblocks, int chunk);
+-extern void ext4_ind_truncate(struct inode *inode);
++extern void ext4_ind_truncate(handle_t *, struct inode *inode);
+ extern int ext4_free_hole_blocks(handle_t *handle, struct inode *inode,
+ 				 ext4_lblk_t first, ext4_lblk_t stop);
+ 
+@@ -2575,7 +2575,7 @@ extern int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks,
+ 				       int chunk);
+ extern int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 			       struct ext4_map_blocks *map, int flags);
+-extern void ext4_ext_truncate(struct inode *);
++extern void ext4_ext_truncate(handle_t *, struct inode *);
+ extern int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
+ 				 ext4_lblk_t end);
+ extern void ext4_ext_init(struct super_block *);
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index d58365e40df7..cbbe8a4deac6 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -4257,47 +4257,12 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 	return err ? err : allocated;
+ }
+ 
+-void ext4_ext_truncate(struct inode *inode)
++void ext4_ext_truncate(handle_t *handle, struct inode *inode)
+ {
+-	struct address_space *mapping = inode->i_mapping;
+ 	struct super_block *sb = inode->i_sb;
+ 	ext4_lblk_t last_block;
+-	handle_t *handle;
+-	loff_t page_len;
+ 	int err = 0;
+ 
+-	/*
+-	 * finish any pending end_io work so we won't run the risk of
+-	 * converting any truncated blocks to initialized later
+-	 */
+-	ext4_flush_unwritten_io(inode);
+-
+-	/*
+-	 * probably first extent we're gonna free will be last in block
+-	 */
+-	err = ext4_writepage_trans_blocks(inode);
+-	handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, err);
+-	if (IS_ERR(handle))
+-		return;
+-
+-	if (inode->i_size % PAGE_CACHE_SIZE != 0) {
+-		page_len = PAGE_CACHE_SIZE -
+-			(inode->i_size & (PAGE_CACHE_SIZE - 1));
+-
+-		err = ext4_discard_partial_page_buffers(handle,
+-			mapping, inode->i_size, page_len, 0);
+-
+-		if (err)
+-			goto out_stop;
+-	}
+-
+-	if (ext4_orphan_add(handle, inode))
+-		goto out_stop;
+-
+-	down_write(&EXT4_I(inode)->i_data_sem);
+-
+-	ext4_discard_preallocations(inode);
+-
+ 	/*
+ 	 * TODO: optimization is possible here.
+ 	 * Probably we need not scan at all,
+@@ -4313,29 +4278,6 @@ void ext4_ext_truncate(struct inode *inode)
+ 	err = ext4_es_remove_extent(inode, last_block,
+ 				    EXT_MAX_BLOCKS - last_block);
+ 	err = ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCKS - 1);
+-
+-	/* In a multi-transaction truncate, we only make the final
+-	 * transaction synchronous.
+-	 */
+-	if (IS_SYNC(inode))
+-		ext4_handle_sync(handle);
+-
+-	up_write(&EXT4_I(inode)->i_data_sem);
+-
+-out_stop:
+-	/*
+-	 * If this was a simple ftruncate() and the file will remain alive,
+-	 * then we need to clear up the orphan record which we created above.
+-	 * However, if this was a real unlink then we were called by
+-	 * ext4_delete_inode(), and we allow that function to clean up the
+-	 * orphan info for us.
+-	 */
+-	if (inode->i_nlink)
+-		ext4_orphan_del(handle, inode);
+-
+-	inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
+-	ext4_mark_inode_dirty(handle, inode);
+-	ext4_journal_stop(handle);
+ }
+ 
+ static void ext4_falloc_update_inode(struct inode *inode,
+diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
+index d8846779f4ea..98be6f697463 100644
+--- a/fs/ext4/indirect.c
++++ b/fs/ext4/indirect.c
+@@ -806,26 +806,9 @@ int ext4_ind_trans_blocks(struct inode *inode, int nrblocks, int chunk)
+  * be able to restart the transaction at a conventient checkpoint to make
+  * sure we don't overflow the journal.
+  *
+- * start_transaction gets us a new handle for a truncate transaction,
+- * and extend_transaction tries to extend the existing one a bit.  If
++ * Try to extend this transaction for the purposes of truncation.  If
+  * extend fails, we need to propagate the failure up and restart the
+  * transaction in the top-level truncate loop. --sct
+- */
+-static handle_t *start_transaction(struct inode *inode)
+-{
+-	handle_t *result;
+-
+-	result = ext4_journal_start(inode, EXT4_HT_TRUNCATE,
+-				    ext4_blocks_for_truncate(inode));
+-	if (!IS_ERR(result))
+-		return result;
+-
+-	ext4_std_error(inode->i_sb, PTR_ERR(result));
+-	return result;
+-}
+-
+-/*
+- * Try to extend this transaction for the purposes of truncation.
+  *
+  * Returns 0 if we managed to create more room.  If we can't create more
+  * room, and the transaction must be restarted we return 1.
+@@ -1218,68 +1201,30 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
+ 	}
+ }
+ 
+-void ext4_ind_truncate(struct inode *inode)
++void ext4_ind_truncate(handle_t *handle, struct inode *inode)
+ {
+-	handle_t *handle;
+ 	struct ext4_inode_info *ei = EXT4_I(inode);
+ 	__le32 *i_data = ei->i_data;
+ 	int addr_per_block = EXT4_ADDR_PER_BLOCK(inode->i_sb);
+-	struct address_space *mapping = inode->i_mapping;
+ 	ext4_lblk_t offsets[4];
+ 	Indirect chain[4];
+ 	Indirect *partial;
+ 	__le32 nr = 0;
+ 	int n = 0;
+ 	ext4_lblk_t last_block, max_block;
+-	loff_t page_len;
+ 	unsigned blocksize = inode->i_sb->s_blocksize;
+-	int err;
+-
+-	handle = start_transaction(inode);
+-	if (IS_ERR(handle))
+-		return;		/* AKPM: return what? */
+ 
+ 	last_block = (inode->i_size + blocksize-1)
+ 					>> EXT4_BLOCK_SIZE_BITS(inode->i_sb);
+ 	max_block = (EXT4_SB(inode->i_sb)->s_bitmap_maxbytes + blocksize-1)
+ 					>> EXT4_BLOCK_SIZE_BITS(inode->i_sb);
+ 
+-	if (inode->i_size % PAGE_CACHE_SIZE != 0) {
+-		page_len = PAGE_CACHE_SIZE -
+-			(inode->i_size & (PAGE_CACHE_SIZE - 1));
+-
+-		err = ext4_discard_partial_page_buffers(handle,
+-			mapping, inode->i_size, page_len, 0);
+-
+-		if (err)
+-			goto out_stop;
+-	}
+-
+ 	if (last_block != max_block) {
+ 		n = ext4_block_to_path(inode, last_block, offsets, NULL);
+ 		if (n == 0)
+-			goto out_stop;	/* error */
++			return;
+ 	}
+ 
+-	/*
+-	 * OK.  This truncate is going to happen.  We add the inode to the
+-	 * orphan list, so that if this truncate spans multiple transactions,
+-	 * and we crash, we will resume the truncate when the filesystem
+-	 * recovers.  It also marks the inode dirty, to catch the new size.
+-	 *
+-	 * Implication: the file must always be in a sane, consistent
+-	 * truncatable state while each transaction commits.
+-	 */
+-	if (ext4_orphan_add(handle, inode))
+-		goto out_stop;
+-
+-	/*
+-	 * From here we block out all ext4_get_block() callers who want to
+-	 * modify the block allocation tree.
+-	 */
+-	down_write(&ei->i_data_sem);
+-
+-	ext4_discard_preallocations(inode);
+ 	ext4_es_remove_extent(inode, last_block, EXT_MAX_BLOCKS - last_block);
+ 
+ 	/*
+@@ -1296,7 +1241,7 @@ void ext4_ind_truncate(struct inode *inode)
+ 		 * It is unnecessary to free any data blocks if last_block is
+ 		 * equal to the indirect block limit.
+ 		 */
+-		goto out_unlock;
++		return;
+ 	} else if (n == 1) {		/* direct blocks */
+ 		ext4_free_data(handle, inode, NULL, i_data+offsets[0],
+ 			       i_data + EXT4_NDIR_BLOCKS);
+@@ -1356,31 +1301,6 @@ void ext4_ind_truncate(struct inode *inode)
+ 	case EXT4_TIND_BLOCK:
+ 		;
+ 	}
+-
+-out_unlock:
+-	up_write(&ei->i_data_sem);
+-	inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
+-	ext4_mark_inode_dirty(handle, inode);
+-
+-	/*
+-	 * In a multi-transaction truncate, we only make the final transaction
+-	 * synchronous
+-	 */
+-	if (IS_SYNC(inode))
+-		ext4_handle_sync(handle);
+-out_stop:
+-	/*
+-	 * If this was a simple ftruncate(), and the file will remain alive
+-	 * then we need to clear up the orphan record which we created above.
+-	 * However, if this was a real unlink then we were called by
+-	 * ext4_delete_inode(), and we allow that function to clean up the
+-	 * orphan info for us.
+-	 */
+-	if (inode->i_nlink)
+-		ext4_orphan_del(handle, inode);
+-
+-	ext4_journal_stop(handle);
+-	trace_ext4_truncate_exit(inode);
+ }
+ 
+ static int free_hole_blocks(handle_t *handle, struct inode *inode,
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 9bda50aa34e2..49c80e4ac5ac 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -3738,9 +3738,9 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length)
+ 					    stop_block);
+ 
+ 	ext4_discard_preallocations(inode);
++	up_write(&EXT4_I(inode)->i_data_sem);
+ 	if (IS_SYNC(inode))
+ 		ext4_handle_sync(handle);
+-	up_write(&EXT4_I(inode)->i_data_sem);
+ 	inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
+ 	ext4_mark_inode_dirty(handle, inode);
+ out_stop:
+@@ -3782,6 +3782,12 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length)
+  */
+ void ext4_truncate(struct inode *inode)
+ {
++	struct ext4_inode_info *ei = EXT4_I(inode);
++	unsigned int credits;
++	handle_t *handle;
++	struct address_space *mapping = inode->i_mapping;
++	loff_t page_len;
++
+ 	trace_ext4_truncate_enter(inode);
+ 
+ 	if (!ext4_can_truncate(inode))
+@@ -3800,10 +3806,72 @@ void ext4_truncate(struct inode *inode)
+ 			return;
+ 	}
+ 
++	/*
++	 * finish any pending end_io work so we won't run the risk of
++	 * converting any truncated blocks to initialized later
++	 */
++	ext4_flush_unwritten_io(inode);
++
++	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
++		credits = ext4_writepage_trans_blocks(inode);
++	else
++		credits = ext4_blocks_for_truncate(inode);
++
++	handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits);
++	if (IS_ERR(handle)) {
++		ext4_std_error(inode->i_sb, PTR_ERR(handle));
++		return;
++	}
++
++	if (inode->i_size % PAGE_CACHE_SIZE != 0) {
++		page_len = PAGE_CACHE_SIZE -
++			(inode->i_size & (PAGE_CACHE_SIZE - 1));
++
++		if (ext4_discard_partial_page_buffers(handle,
++				mapping, inode->i_size, page_len, 0))
++			goto out_stop;
++	}
++
++	/*
++	 * We add the inode to the orphan list, so that if this
++	 * truncate spans multiple transactions, and we crash, we will
++	 * resume the truncate when the filesystem recovers.  It also
++	 * marks the inode dirty, to catch the new size.
++	 *
++	 * Implication: the file must always be in a sane, consistent
++	 * truncatable state while each transaction commits.
++	 */
++	if (ext4_orphan_add(handle, inode))
++		goto out_stop;
++
++	down_write(&EXT4_I(inode)->i_data_sem);
++
++	ext4_discard_preallocations(inode);
++
+ 	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
+-		ext4_ext_truncate(inode);
++		ext4_ext_truncate(handle, inode);
+ 	else
+-		ext4_ind_truncate(inode);
++		ext4_ind_truncate(handle, inode);
++
++	up_write(&ei->i_data_sem);
++
++	if (IS_SYNC(inode))
++		ext4_handle_sync(handle);
++
++out_stop:
++	/*
++	 * If this was a simple ftruncate() and the file will remain alive,
++	 * then we need to clear up the orphan record which we created above.
++	 * However, if this was a real unlink then we were called by
++	 * ext4_delete_inode(), and we allow that function to clean up the
++	 * orphan info for us.
++	 */
++	if (inode->i_nlink)
++		ext4_orphan_del(handle, inode);
++
++	inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
++	ext4_mark_inode_dirty(handle, inode);
++	ext4_journal_stop(handle);
+ 
+ 	trace_ext4_truncate_exit(inode);
+ }

commit 26a4c0c6ccecf6814cf44f951c97222bd795bc1a
+Author: Theodore Ts'o 
+Date:   Wed Apr 3 12:45:17 2013 -0400
+
+    ext4: refactor punch hole code
+    
+    Move common code in ext4_ind_punch_hole() and ext4_ext_punch_hole()
+    into ext4_punch_hole().  This saves over 150 lines of code.
+    
+    This also fixes a potential bug when the punch_hole() code is racing
+    against indirect-to-extents or extents-to-indirect migation.  We are
+    currently using i_mutex to protect against changes to the inode flag;
+    specifically, the append-only, immutable, and extents inode flags.  So
+    we need to take i_mutex before deciding whether to use the
+    extents-specific or indirect-specific punch_hole code.
+    
+    Also, there was a missing call to ext4_inode_block_unlocked_dio() in
+    the indirect punch codepath.  This was added in commit 02d262dffcf4c
+    to block DIO readers racing against the punch operation in the
+    codepath for extent-mapped inodes, but it was missing for
+    indirect-block mapped inodes.  One of the advantages of refactoring
+    the code is that it makes such oversights much less likely.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index f91e11bd9753..0649253804c4 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2110,7 +2110,8 @@ extern ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb,
+ extern int ext4_ind_calc_metadata_amount(struct inode *inode, sector_t lblock);
+ extern int ext4_ind_trans_blocks(struct inode *inode, int nrblocks, int chunk);
+ extern void ext4_ind_truncate(struct inode *inode);
+-extern int ext4_ind_punch_hole(struct file *file, loff_t offset, loff_t length);
++extern int ext4_free_hole_blocks(handle_t *handle, struct inode *inode,
++				 ext4_lblk_t first, ext4_lblk_t stop);
+ 
+ /* ioctl.c */
+ extern long ext4_ioctl(struct file *, unsigned int, unsigned long);
+@@ -2575,8 +2576,8 @@ extern int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks,
+ extern int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 			       struct ext4_map_blocks *map, int flags);
+ extern void ext4_ext_truncate(struct inode *);
+-extern int ext4_ext_punch_hole(struct file *file, loff_t offset,
+-				loff_t length);
++extern int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
++				 ext4_lblk_t end);
+ extern void ext4_ext_init(struct super_block *);
+ extern void ext4_ext_release(struct super_block *);
+ extern long ext4_fallocate(struct file *file, int mode, loff_t offset,
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 9c6d06dcef8b..d58365e40df7 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -2599,8 +2599,8 @@ ext4_ext_more_to_rm(struct ext4_ext_path *path)
+ 	return 1;
+ }
+ 
+-static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
+-				 ext4_lblk_t end)
++int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
++			  ext4_lblk_t end)
+ {
+ 	struct super_block *sb = inode->i_sb;
+ 	int depth = ext_depth(inode);
+@@ -4623,187 +4623,6 @@ static int ext4_xattr_fiemap(struct inode *inode,
+ 	return (error < 0 ? error : 0);
+ }
+ 
+-/*
+- * ext4_ext_punch_hole
+- *
+- * Punches a hole of "length" bytes in a file starting
+- * at byte "offset"
+- *
+- * @inode:  The inode of the file to punch a hole in
+- * @offset: The starting byte offset of the hole
+- * @length: The length of the hole
+- *
+- * Returns the number of blocks removed or negative on err
+- */
+-int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length)
+-{
+-	struct inode *inode = file_inode(file);
+-	struct super_block *sb = inode->i_sb;
+-	ext4_lblk_t first_block, stop_block;
+-	struct address_space *mapping = inode->i_mapping;
+-	handle_t *handle;
+-	loff_t first_page, last_page, page_len;
+-	loff_t first_page_offset, last_page_offset;
+-	int credits, err = 0;
+-
+-	/*
+-	 * Write out all dirty pages to avoid race conditions
+-	 * Then release them.
+-	 */
+-	if (mapping->nrpages && mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
+-		err = filemap_write_and_wait_range(mapping,
+-			offset, offset + length - 1);
+-
+-		if (err)
+-			return err;
+-	}
+-
+-	mutex_lock(&inode->i_mutex);
+-	/* It's not possible punch hole on append only file */
+-	if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) {
+-		err = -EPERM;
+-		goto out_mutex;
+-	}
+-	if (IS_SWAPFILE(inode)) {
+-		err = -ETXTBSY;
+-		goto out_mutex;
+-	}
+-
+-	/* No need to punch hole beyond i_size */
+-	if (offset >= inode->i_size)
+-		goto out_mutex;
+-
+-	/*
+-	 * If the hole extends beyond i_size, set the hole
+-	 * to end after the page that contains i_size
+-	 */
+-	if (offset + length > inode->i_size) {
+-		length = inode->i_size +
+-		   PAGE_CACHE_SIZE - (inode->i_size & (PAGE_CACHE_SIZE - 1)) -
+-		   offset;
+-	}
+-
+-	first_page = (offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+-	last_page = (offset + length) >> PAGE_CACHE_SHIFT;
+-
+-	first_page_offset = first_page << PAGE_CACHE_SHIFT;
+-	last_page_offset = last_page << PAGE_CACHE_SHIFT;
+-
+-	/* Now release the pages */
+-	if (last_page_offset > first_page_offset) {
+-		truncate_pagecache_range(inode, first_page_offset,
+-					 last_page_offset - 1);
+-	}
+-
+-	/* Wait all existing dio workers, newcomers will block on i_mutex */
+-	ext4_inode_block_unlocked_dio(inode);
+-	err = ext4_flush_unwritten_io(inode);
+-	if (err)
+-		goto out_dio;
+-	inode_dio_wait(inode);
+-
+-	credits = ext4_writepage_trans_blocks(inode);
+-	handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits);
+-	if (IS_ERR(handle)) {
+-		err = PTR_ERR(handle);
+-		goto out_dio;
+-	}
+-
+-
+-	/*
+-	 * Now we need to zero out the non-page-aligned data in the
+-	 * pages at the start and tail of the hole, and unmap the buffer
+-	 * heads for the block aligned regions of the page that were
+-	 * completely zeroed.
+-	 */
+-	if (first_page > last_page) {
+-		/*
+-		 * If the file space being truncated is contained within a page
+-		 * just zero out and unmap the middle of that page
+-		 */
+-		err = ext4_discard_partial_page_buffers(handle,
+-			mapping, offset, length, 0);
+-
+-		if (err)
+-			goto out;
+-	} else {
+-		/*
+-		 * zero out and unmap the partial page that contains
+-		 * the start of the hole
+-		 */
+-		page_len  = first_page_offset - offset;
+-		if (page_len > 0) {
+-			err = ext4_discard_partial_page_buffers(handle, mapping,
+-						   offset, page_len, 0);
+-			if (err)
+-				goto out;
+-		}
+-
+-		/*
+-		 * zero out and unmap the partial page that contains
+-		 * the end of the hole
+-		 */
+-		page_len = offset + length - last_page_offset;
+-		if (page_len > 0) {
+-			err = ext4_discard_partial_page_buffers(handle, mapping,
+-					last_page_offset, page_len, 0);
+-			if (err)
+-				goto out;
+-		}
+-	}
+-
+-	/*
+-	 * If i_size is contained in the last page, we need to
+-	 * unmap and zero the partial page after i_size
+-	 */
+-	if (inode->i_size >> PAGE_CACHE_SHIFT == last_page &&
+-	   inode->i_size % PAGE_CACHE_SIZE != 0) {
+-
+-		page_len = PAGE_CACHE_SIZE -
+-			(inode->i_size & (PAGE_CACHE_SIZE - 1));
+-
+-		if (page_len > 0) {
+-			err = ext4_discard_partial_page_buffers(handle,
+-			  mapping, inode->i_size, page_len, 0);
+-
+-			if (err)
+-				goto out;
+-		}
+-	}
+-
+-	first_block = (offset + sb->s_blocksize - 1) >>
+-		EXT4_BLOCK_SIZE_BITS(sb);
+-	stop_block = (offset + length) >> EXT4_BLOCK_SIZE_BITS(sb);
+-
+-	/* If there are no blocks to remove, return now */
+-	if (first_block >= stop_block)
+-		goto out;
+-
+-	down_write(&EXT4_I(inode)->i_data_sem);
+-	ext4_discard_preallocations(inode);
+-
+-	err = ext4_es_remove_extent(inode, first_block,
+-				    stop_block - first_block);
+-	err = ext4_ext_remove_space(inode, first_block, stop_block - 1);
+-
+-	ext4_discard_preallocations(inode);
+-
+-	if (IS_SYNC(inode))
+-		ext4_handle_sync(handle);
+-
+-	up_write(&EXT4_I(inode)->i_data_sem);
+-
+-out:
+-	inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
+-	ext4_mark_inode_dirty(handle, inode);
+-	ext4_journal_stop(handle);
+-out_dio:
+-	ext4_inode_resume_unlocked_dio(inode);
+-out_mutex:
+-	mutex_unlock(&inode->i_mutex);
+-	return err;
+-}
+-
+ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ 		__u64 start, __u64 len)
+ {
+diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
+index c0f9e4699f0b..d8846779f4ea 100644
+--- a/fs/ext4/indirect.c
++++ b/fs/ext4/indirect.c
+@@ -1434,8 +1434,8 @@ static int free_hole_blocks(handle_t *handle, struct inode *inode,
+ 	return ret;
+ }
+ 
+-static int ext4_free_hole_blocks(handle_t *handle, struct inode *inode,
+-				 ext4_lblk_t first, ext4_lblk_t stop)
++int ext4_free_hole_blocks(handle_t *handle, struct inode *inode,
++			  ext4_lblk_t first, ext4_lblk_t stop)
+ {
+ 	int addr_per_block = EXT4_ADDR_PER_BLOCK(inode->i_sb);
+ 	int level, ret = 0;
+@@ -1469,157 +1469,3 @@ static int ext4_free_hole_blocks(handle_t *handle, struct inode *inode,
+ 	return ret;
+ }
+ 
+-int ext4_ind_punch_hole(struct file *file, loff_t offset, loff_t length)
+-{
+-	struct inode *inode = file_inode(file);
+-	struct super_block *sb = inode->i_sb;
+-	ext4_lblk_t first_block, stop_block;
+-	struct address_space *mapping = inode->i_mapping;
+-	handle_t *handle = NULL;
+-	loff_t first_page, last_page, page_len;
+-	loff_t first_page_offset, last_page_offset;
+-	int err = 0;
+-
+-	/*
+-	 * Write out all dirty pages to avoid race conditions
+-	 * Then release them.
+-	 */
+-	if (mapping->nrpages && mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
+-		err = filemap_write_and_wait_range(mapping,
+-			offset, offset + length - 1);
+-		if (err)
+-			return err;
+-	}
+-
+-	mutex_lock(&inode->i_mutex);
+-	/* It's not possible punch hole on append only file */
+-	if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) {
+-		err = -EPERM;
+-		goto out_mutex;
+-	}
+-	if (IS_SWAPFILE(inode)) {
+-		err = -ETXTBSY;
+-		goto out_mutex;
+-	}
+-
+-	/* No need to punch hole beyond i_size */
+-	if (offset >= inode->i_size)
+-		goto out_mutex;
+-
+-	/*
+-	 * If the hole extents beyond i_size, set the hole
+-	 * to end after the page that contains i_size
+-	 */
+-	if (offset + length > inode->i_size) {
+-		length = inode->i_size +
+-		    PAGE_CACHE_SIZE - (inode->i_size & (PAGE_CACHE_SIZE - 1)) -
+-		    offset;
+-	}
+-
+-	first_page = (offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+-	last_page = (offset + length) >> PAGE_CACHE_SHIFT;
+-
+-	first_page_offset = first_page << PAGE_CACHE_SHIFT;
+-	last_page_offset = last_page << PAGE_CACHE_SHIFT;
+-
+-	/* Now release the pages */
+-	if (last_page_offset > first_page_offset) {
+-		truncate_pagecache_range(inode, first_page_offset,
+-					 last_page_offset - 1);
+-	}
+-
+-	/* Wait all existing dio works, newcomers will block on i_mutex */
+-	inode_dio_wait(inode);
+-
+-	handle = start_transaction(inode);
+-	if (IS_ERR(handle))
+-		goto out_mutex;
+-
+-	/*
+-	 * Now we need to zero out the non-page-aligned data in the
+-	 * pages at the start and tail of the hole, and unmap the buffer
+-	 * heads for the block aligned regions of the page that were
+-	 * completely zerod.
+-	 */
+-	if (first_page > last_page) {
+-		/*
+-		 * If the file space being truncated is contained within a page
+-		 * just zero out and unmap the middle of that page
+-		 */
+-		err = ext4_discard_partial_page_buffers(handle,
+-			mapping, offset, length, 0);
+-		if (err)
+-			goto out;
+-	} else {
+-		/*
+-		 * Zero out and unmap the paritial page that contains
+-		 * the start of the hole
+-		 */
+-		page_len = first_page_offset - offset;
+-		if (page_len > 0) {
+-			err = ext4_discard_partial_page_buffers(handle, mapping,
+-							offset, page_len, 0);
+-			if (err)
+-				goto out;
+-		}
+-
+-		/*
+-		 * Zero out and unmap the partial page that contains
+-		 * the end of the hole
+-		 */
+-		page_len = offset + length - last_page_offset;
+-		if (page_len > 0) {
+-			err = ext4_discard_partial_page_buffers(handle, mapping,
+-						last_page_offset, page_len, 0);
+-			if (err)
+-				goto out;
+-		}
+-	}
+-
+-	/*
+-	 * If i_size contained in the last page, we need to
+-	 * unmap and zero the paritial page after i_size
+-	 */
+-	if (inode->i_size >> PAGE_CACHE_SHIFT == last_page &&
+-	    inode->i_size % PAGE_CACHE_SIZE != 0) {
+-		page_len = PAGE_CACHE_SIZE -
+-			(inode->i_size & (PAGE_CACHE_SIZE - 1));
+-		if (page_len > 0) {
+-			err = ext4_discard_partial_page_buffers(handle,
+-				mapping, inode->i_size, page_len, 0);
+-			if (err)
+-				goto out;
+-		}
+-	}
+-
+-	first_block = (offset + sb->s_blocksize - 1) >>
+-		EXT4_BLOCK_SIZE_BITS(sb);
+-	stop_block = (offset + length) >> EXT4_BLOCK_SIZE_BITS(sb);
+-
+-	if (first_block >= stop_block)
+-		goto out;
+-
+-	down_write(&EXT4_I(inode)->i_data_sem);
+-	ext4_discard_preallocations(inode);
+-
+-	err = ext4_es_remove_extent(inode, first_block,
+-				    stop_block - first_block);
+-	err = ext4_free_hole_blocks(handle, inode, first_block, stop_block);
+-
+-	ext4_discard_preallocations(inode);
+-
+-	if (IS_SYNC(inode))
+-		ext4_handle_sync(handle);
+-
+-	up_write(&EXT4_I(inode)->i_data_sem);
+-
+-out:
+-	inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
+-	ext4_mark_inode_dirty(handle, inode);
+-	ext4_journal_stop(handle);
+-
+-out_mutex:
+-	mutex_unlock(&inode->i_mutex);
+-
+-	return err;
+-}
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index a4ffb470fbf3..9bda50aa34e2 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -3566,20 +3566,190 @@ int ext4_can_truncate(struct inode *inode)
+ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length)
+ {
+ 	struct inode *inode = file_inode(file);
++	struct super_block *sb = inode->i_sb;
++	ext4_lblk_t first_block, stop_block;
++	struct address_space *mapping = inode->i_mapping;
++	loff_t first_page, last_page, page_len;
++	loff_t first_page_offset, last_page_offset;
++	handle_t *handle;
++	unsigned int credits;
++	int ret = 0;
++
+ 	if (!S_ISREG(inode->i_mode))
+ 		return -EOPNOTSUPP;
+ 
+-	if (!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
+-		return ext4_ind_punch_hole(file, offset, length);
+-
+-	if (EXT4_SB(inode->i_sb)->s_cluster_ratio > 1) {
++	if (EXT4_SB(sb)->s_cluster_ratio > 1) {
+ 		/* TODO: Add support for bigalloc file systems */
+ 		return -EOPNOTSUPP;
+ 	}
+ 
+ 	trace_ext4_punch_hole(inode, offset, length);
+ 
+-	return ext4_ext_punch_hole(file, offset, length);
++	/*
++	 * Write out all dirty pages to avoid race conditions
++	 * Then release them.
++	 */
++	if (mapping->nrpages && mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
++		ret = filemap_write_and_wait_range(mapping, offset,
++						   offset + length - 1);
++		if (ret)
++			return ret;
++	}
++
++	mutex_lock(&inode->i_mutex);
++	/* It's not possible punch hole on append only file */
++	if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) {
++		ret = -EPERM;
++		goto out_mutex;
++	}
++	if (IS_SWAPFILE(inode)) {
++		ret = -ETXTBSY;
++		goto out_mutex;
++	}
++
++	/* No need to punch hole beyond i_size */
++	if (offset >= inode->i_size)
++		goto out_mutex;
++
++	/*
++	 * If the hole extends beyond i_size, set the hole
++	 * to end after the page that contains i_size
++	 */
++	if (offset + length > inode->i_size) {
++		length = inode->i_size +
++		   PAGE_CACHE_SIZE - (inode->i_size & (PAGE_CACHE_SIZE - 1)) -
++		   offset;
++	}
++
++	first_page = (offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
++	last_page = (offset + length) >> PAGE_CACHE_SHIFT;
++
++	first_page_offset = first_page << PAGE_CACHE_SHIFT;
++	last_page_offset = last_page << PAGE_CACHE_SHIFT;
++
++	/* Now release the pages */
++	if (last_page_offset > first_page_offset) {
++		truncate_pagecache_range(inode, first_page_offset,
++					 last_page_offset - 1);
++	}
++
++	/* Wait all existing dio workers, newcomers will block on i_mutex */
++	ext4_inode_block_unlocked_dio(inode);
++	ret = ext4_flush_unwritten_io(inode);
++	if (ret)
++		goto out_dio;
++	inode_dio_wait(inode);
++
++	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
++		credits = ext4_writepage_trans_blocks(inode);
++	else
++		credits = ext4_blocks_for_truncate(inode);
++	handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits);
++	if (IS_ERR(handle)) {
++		ret = PTR_ERR(handle);
++		ext4_std_error(sb, ret);
++		goto out_dio;
++	}
++
++	/*
++	 * Now we need to zero out the non-page-aligned data in the
++	 * pages at the start and tail of the hole, and unmap the
++	 * buffer heads for the block aligned regions of the page that
++	 * were completely zeroed.
++	 */
++	if (first_page > last_page) {
++		/*
++		 * If the file space being truncated is contained
++		 * within a page just zero out and unmap the middle of
++		 * that page
++		 */
++		ret = ext4_discard_partial_page_buffers(handle,
++			mapping, offset, length, 0);
++
++		if (ret)
++			goto out_stop;
++	} else {
++		/*
++		 * zero out and unmap the partial page that contains
++		 * the start of the hole
++		 */
++		page_len = first_page_offset - offset;
++		if (page_len > 0) {
++			ret = ext4_discard_partial_page_buffers(handle, mapping,
++						offset, page_len, 0);
++			if (ret)
++				goto out_stop;
++		}
++
++		/*
++		 * zero out and unmap the partial page that contains
++		 * the end of the hole
++		 */
++		page_len = offset + length - last_page_offset;
++		if (page_len > 0) {
++			ret = ext4_discard_partial_page_buffers(handle, mapping,
++					last_page_offset, page_len, 0);
++			if (ret)
++				goto out_stop;
++		}
++	}
++
++	/*
++	 * If i_size is contained in the last page, we need to
++	 * unmap and zero the partial page after i_size
++	 */
++	if (inode->i_size >> PAGE_CACHE_SHIFT == last_page &&
++	   inode->i_size % PAGE_CACHE_SIZE != 0) {
++		page_len = PAGE_CACHE_SIZE -
++			(inode->i_size & (PAGE_CACHE_SIZE - 1));
++
++		if (page_len > 0) {
++			ret = ext4_discard_partial_page_buffers(handle,
++					mapping, inode->i_size, page_len, 0);
++
++			if (ret)
++				goto out_stop;
++		}
++	}
++
++	first_block = (offset + sb->s_blocksize - 1) >>
++		EXT4_BLOCK_SIZE_BITS(sb);
++	stop_block = (offset + length) >> EXT4_BLOCK_SIZE_BITS(sb);
++
++	/* If there are no blocks to remove, return now */
++	if (first_block >= stop_block)
++		goto out_stop;
++
++	down_write(&EXT4_I(inode)->i_data_sem);
++	ext4_discard_preallocations(inode);
++
++	ret = ext4_es_remove_extent(inode, first_block,
++				    stop_block - first_block);
++	if (ret) {
++		up_write(&EXT4_I(inode)->i_data_sem);
++		goto out_stop;
++	}
++
++	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
++		ret = ext4_ext_remove_space(inode, first_block,
++					    stop_block - 1);
++	else
++		ret = ext4_free_hole_blocks(handle, inode, first_block,
++					    stop_block);
++
++	ext4_discard_preallocations(inode);
++	if (IS_SYNC(inode))
++		ext4_handle_sync(handle);
++	up_write(&EXT4_I(inode)->i_data_sem);
++	inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
++	ext4_mark_inode_dirty(handle, inode);
++out_stop:
++	ext4_journal_stop(handle);
++out_dio:
++	ext4_inode_resume_unlocked_dio(inode);
++out_mutex:
++	mutex_unlock(&inode->i_mutex);
++	return ret;
+ }
+ 
+ /*

commit 781f143ea0fd7981ebe2e8cd96114997c8cf6c07
+Author: Theodore Ts'o 
+Date:   Wed Apr 3 12:43:17 2013 -0400
+
+    ext4: fold ext4_alloc_blocks() in ext4_alloc_branch()
+    
+    The older code was far more complicated than it needed to be because
+    of how we spliced in the ext4's new multiblock allocator into ext3's
+    indirect block code.  By folding ext4_alloc_blocks() into
+    ext4_alloc_branch(), we make the code far more understable, shave off
+    over 130 lines of code and half a kilobyte of compiled object code.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
+index a04183127ef0..c0f9e4699f0b 100644
+--- a/fs/ext4/indirect.c
++++ b/fs/ext4/indirect.c
+@@ -291,131 +291,6 @@ static int ext4_blks_to_allocate(Indirect *branch, int k, unsigned int blks,
+ 	return count;
+ }
+ 
+-/**
+- *	ext4_alloc_blocks: multiple allocate blocks needed for a branch
+- *	@handle: handle for this transaction
+- *	@inode: inode which needs allocated blocks
+- *	@iblock: the logical block to start allocated at
+- *	@goal: preferred physical block of allocation
+- *	@indirect_blks: the number of blocks need to allocate for indirect
+- *			blocks
+- *	@blks: number of desired blocks
+- *	@new_blocks: on return it will store the new block numbers for
+- *	the indirect blocks(if needed) and the first direct block,
+- *	@err: on return it will store the error code
+- *
+- *	This function will return the number of blocks allocated as
+- *	requested by the passed-in parameters.
+- */
+-static int ext4_alloc_blocks(handle_t *handle, struct inode *inode,
+-			     ext4_lblk_t iblock, ext4_fsblk_t goal,
+-			     int indirect_blks, int blks,
+-			     ext4_fsblk_t new_blocks[4], int *err)
+-{
+-	struct ext4_allocation_request ar;
+-	int target, i;
+-	unsigned long count = 0, blk_allocated = 0;
+-	int index = 0;
+-	ext4_fsblk_t current_block = 0;
+-	int ret = 0;
+-
+-	/*
+-	 * Here we try to allocate the requested multiple blocks at once,
+-	 * on a best-effort basis.
+-	 * To build a branch, we should allocate blocks for
+-	 * the indirect blocks(if not allocated yet), and at least
+-	 * the first direct block of this branch.  That's the
+-	 * minimum number of blocks need to allocate(required)
+-	 */
+-	/* first we try to allocate the indirect blocks */
+-	target = indirect_blks;
+-	while (target > 0) {
+-		count = target;
+-		/* allocating blocks for indirect blocks and direct blocks */
+-		current_block = ext4_new_meta_blocks(handle, inode, goal,
+-						     0, &count, err);
+-		if (*err)
+-			goto failed_out;
+-
+-		if (unlikely(current_block + count > EXT4_MAX_BLOCK_FILE_PHYS)) {
+-			EXT4_ERROR_INODE(inode,
+-					 "current_block %llu + count %lu > %d!",
+-					 current_block, count,
+-					 EXT4_MAX_BLOCK_FILE_PHYS);
+-			*err = -EIO;
+-			goto failed_out;
+-		}
+-
+-		target -= count;
+-		/* allocate blocks for indirect blocks */
+-		while (index < indirect_blks && count) {
+-			new_blocks[index++] = current_block++;
+-			count--;
+-		}
+-		if (count > 0) {
+-			/*
+-			 * save the new block number
+-			 * for the first direct block
+-			 */
+-			new_blocks[index] = current_block;
+-			WARN(1, KERN_INFO "%s returned more blocks than "
+-						"requested\n", __func__);
+-			break;
+-		}
+-	}
+-
+-	target = blks - count ;
+-	blk_allocated = count;
+-	if (!target)
+-		goto allocated;
+-	/* Now allocate data blocks */
+-	memset(&ar, 0, sizeof(ar));
+-	ar.inode = inode;
+-	ar.goal = goal;
+-	ar.len = target;
+-	ar.logical = iblock;
+-	if (S_ISREG(inode->i_mode))
+-		/* enable in-core preallocation only for regular files */
+-		ar.flags = EXT4_MB_HINT_DATA;
+-
+-	current_block = ext4_mb_new_blocks(handle, &ar, err);
+-	if (unlikely(current_block + ar.len > EXT4_MAX_BLOCK_FILE_PHYS)) {
+-		EXT4_ERROR_INODE(inode,
+-				 "current_block %llu + ar.len %d > %d!",
+-				 current_block, ar.len,
+-				 EXT4_MAX_BLOCK_FILE_PHYS);
+-		*err = -EIO;
+-		goto failed_out;
+-	}
+-
+-	if (*err && (target == blks)) {
+-		/*
+-		 * if the allocation failed and we didn't allocate
+-		 * any blocks before
+-		 */
+-		goto failed_out;
+-	}
+-	if (!*err) {
+-		if (target == blks) {
+-			/*
+-			 * save the new block number
+-			 * for the first direct block
+-			 */
+-			new_blocks[index] = current_block;
+-		}
+-		blk_allocated += ar.len;
+-	}
+-allocated:
+-	/* total number of blocks allocated for direct blocks */
+-	ret = blk_allocated;
+-	*err = 0;
+-	return ret;
+-failed_out:
+-	for (i = 0; i < index; i++)
+-		ext4_free_blocks(handle, inode, NULL, new_blocks[i], 1, 0);
+-	return ret;
+-}
+-
+ /**
+  *	ext4_alloc_branch - allocate and set up a chain of blocks.
+  *	@handle: handle for this transaction
+@@ -448,60 +323,59 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
+ 			     int *blks, ext4_fsblk_t goal,
+ 			     ext4_lblk_t *offsets, Indirect *branch)
+ {
+-	int blocksize = inode->i_sb->s_blocksize;
+-	int i, n = 0;
+-	int err = 0;
+-	struct buffer_head *bh;
+-	int num;
+-	ext4_fsblk_t new_blocks[4];
+-	ext4_fsblk_t current_block;
++	struct ext4_allocation_request	ar;
++	struct buffer_head *		bh;
++	ext4_fsblk_t			b, new_blocks[4];
++	__le32				*p;
++	int				i, j, err, len = 1;
+ 
+-	num = ext4_alloc_blocks(handle, inode, iblock, goal, indirect_blks,
+-				*blks, new_blocks, &err);
+-	if (err)
+-		return err;
+-
+-	branch[0].key = cpu_to_le32(new_blocks[0]);
+ 	/*
+-	 * metadata blocks and data blocks are allocated.
++	 * Set up for the direct block allocation
+ 	 */
+-	for (n = 1; n <= indirect_blks;  n++) {
+-		/*
+-		 * Get buffer_head for parent block, zero it out
+-		 * and set the pointer to new one, then send
+-		 * parent to disk.
+-		 */
+-		bh = sb_getblk(inode->i_sb, new_blocks[n-1]);
++	memset(&ar, 0, sizeof(ar));
++	ar.inode = inode;
++	ar.len = *blks;
++	ar.logical = iblock;
++	if (S_ISREG(inode->i_mode))
++		ar.flags = EXT4_MB_HINT_DATA;
++
++	for (i = 0; i <= indirect_blks; i++) {
++		if (i == indirect_blks) {
++			ar.goal = goal;
++			new_blocks[i] = ext4_mb_new_blocks(handle, &ar, &err);
++		} else
++			goal = new_blocks[i] = ext4_new_meta_blocks(handle, inode,
++							goal, 0, NULL, &err);
++		if (err) {
++			i--;
++			goto failed;
++		}
++		branch[i].key = cpu_to_le32(new_blocks[i]);
++		if (i == 0)
++			continue;
++
++		bh = branch[i].bh = sb_getblk(inode->i_sb, new_blocks[i-1]);
+ 		if (unlikely(!bh)) {
+ 			err = -ENOMEM;
+ 			goto failed;
+ 		}
+-
+-		branch[n].bh = bh;
+ 		lock_buffer(bh);
+ 		BUFFER_TRACE(bh, "call get_create_access");
+ 		err = ext4_journal_get_create_access(handle, bh);
+ 		if (err) {
+-			/* Don't brelse(bh) here; it's done in
+-			 * ext4_journal_forget() below */
+ 			unlock_buffer(bh);
+ 			goto failed;
+ 		}
+ 
+-		memset(bh->b_data, 0, blocksize);
+-		branch[n].p = (__le32 *) bh->b_data + offsets[n];
+-		branch[n].key = cpu_to_le32(new_blocks[n]);
+-		*branch[n].p = branch[n].key;
+-		if (n == indirect_blks) {
+-			current_block = new_blocks[n];
+-			/*
+-			 * End of chain, update the last new metablock of
+-			 * the chain to point to the new allocated
+-			 * data blocks numbers
+-			 */
+-			for (i = 1; i < num; i++)
+-				*(branch[n].p + i) = cpu_to_le32(++current_block);
+-		}
++		memset(bh->b_data, 0, bh->b_size);
++		p = branch[i].p = (__le32 *) bh->b_data + offsets[i];
++		b = new_blocks[i];
++
++		if (i == indirect_blks)
++			len = ar.len;
++		for (j = 0; j < len; j++)
++			*p++ = cpu_to_le32(b++);
++
+ 		BUFFER_TRACE(bh, "marking uptodate");
+ 		set_buffer_uptodate(bh);
+ 		unlock_buffer(bh);
+@@ -511,25 +385,16 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
+ 		if (err)
+ 			goto failed;
+ 	}
+-	*blks = num;
+-	return err;
++	*blks = ar.len;
++	return 0;
+ failed:
+-	/* Allocation failed, free what we already allocated */
+-	ext4_free_blocks(handle, inode, NULL, new_blocks[0], 1, 0);
+-	for (i = 1; i <= n ; i++) {
+-		/*
+-		 * branch[i].bh is newly allocated, so there is no
+-		 * need to revoke the block, which is why we don't
+-		 * need to set EXT4_FREE_BLOCKS_METADATA.
+-		 */
+-		ext4_free_blocks(handle, inode, NULL, new_blocks[i], 1,
+-				 EXT4_FREE_BLOCKS_FORGET);
++	for (; i >= 0; i--) {
++		if (i != indirect_blks && branch[i].bh)
++			ext4_forget(handle, 1, inode, branch[i].bh,
++				    branch[i].bh->b_blocknr);
++		ext4_free_blocks(handle, inode, NULL, new_blocks[i],
++				 (i == indirect_blks) ? ar.len : 1, 0);
+ 	}
+-	for (i = n+1; i < indirect_blks; i++)
+-		ext4_free_blocks(handle, inode, NULL, new_blocks[i], 1, 0);
+-
+-	ext4_free_blocks(handle, inode, NULL, new_blocks[i], num, 0);
+-
+ 	return err;
+ }
+ 

commit 74d553aad7926ed05e05d9d5cff516a7b31375fc
+Author: Theodore Ts'o 
+Date:   Wed Apr 3 12:39:17 2013 -0400
+
+    ext4: collapse handling of data=ordered and data=writeback codepaths
+    
+    The only difference between how we handle data=ordered and
+    data=writeback is a single call to ext4_jbd2_file_inode().  Eliminate
+    code duplication by factoring out redundant the code paths.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Lukas Czerner 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 3b83cd604796..f91e11bd9753 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1374,6 +1374,7 @@ enum {
+ 	EXT4_STATE_DIOREAD_LOCK,	/* Disable support for dio read
+ 					   nolocking */
+ 	EXT4_STATE_MAY_INLINE_DATA,	/* may have in-inode data */
++	EXT4_STATE_ORDERED_MODE,	/* data=ordered mode */
+ };
+ 
+ #define EXT4_INODE_BIT_FNS(name, field, offset)				\
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index b3a5213bc73e..4ee69270a48a 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1145,77 +1145,36 @@ static int ext4_generic_write_end(struct file *file,
+  * ext4 never places buffers on inode->i_mapping->private_list.  metadata
+  * buffers are managed internally.
+  */
+-static int ext4_ordered_write_end(struct file *file,
+-				  struct address_space *mapping,
+-				  loff_t pos, unsigned len, unsigned copied,
+-				  struct page *page, void *fsdata)
++static int ext4_write_end(struct file *file,
++			  struct address_space *mapping,
++			  loff_t pos, unsigned len, unsigned copied,
++			  struct page *page, void *fsdata)
+ {
+ 	handle_t *handle = ext4_journal_current_handle();
+ 	struct inode *inode = mapping->host;
+ 	int ret = 0, ret2;
+ 
+-	trace_ext4_ordered_write_end(inode, pos, len, copied);
+-	ret = ext4_jbd2_file_inode(handle, inode);
+-
+-	if (ret == 0) {
+-		ret2 = ext4_generic_write_end(file, mapping, pos, len, copied,
+-							page, fsdata);
+-		copied = ret2;
+-		if (pos + len > inode->i_size && ext4_can_truncate(inode))
+-			/* if we have allocated more blocks and copied
+-			 * less. We will have blocks allocated outside
+-			 * inode->i_size. So truncate them
+-			 */
+-			ext4_orphan_add(handle, inode);
+-		if (ret2 < 0)
+-			ret = ret2;
+-	} else {
+-		unlock_page(page);
+-		page_cache_release(page);
+-	}
+-
+-	ret2 = ext4_journal_stop(handle);
+-	if (!ret)
+-		ret = ret2;
+-
+-	if (pos + len > inode->i_size) {
+-		ext4_truncate_failed_write(inode);
+-		/*
+-		 * If truncate failed early the inode might still be
+-		 * on the orphan list; we need to make sure the inode
+-		 * is removed from the orphan list in that case.
+-		 */
+-		if (inode->i_nlink)
+-			ext4_orphan_del(NULL, inode);
++	trace_ext4_write_end(inode, pos, len, copied);
++	if (ext4_test_inode_state(inode, EXT4_STATE_ORDERED_MODE)) {
++		ret = ext4_jbd2_file_inode(handle, inode);
++		if (ret) {
++			unlock_page(page);
++			page_cache_release(page);
++			goto errout;
++		}
+ 	}
+ 
+-
+-	return ret ? ret : copied;
+-}
+-
+-static int ext4_writeback_write_end(struct file *file,
+-				    struct address_space *mapping,
+-				    loff_t pos, unsigned len, unsigned copied,
+-				    struct page *page, void *fsdata)
+-{
+-	handle_t *handle = ext4_journal_current_handle();
+-	struct inode *inode = mapping->host;
+-	int ret = 0, ret2;
+-
+-	trace_ext4_writeback_write_end(inode, pos, len, copied);
+-	ret2 = ext4_generic_write_end(file, mapping, pos, len, copied,
+-							page, fsdata);
+-	copied = ret2;
++	copied = ext4_generic_write_end(file, mapping, pos, len, copied,
++					page, fsdata);
++	if (copied < 0)
++		ret = copied;
+ 	if (pos + len > inode->i_size && ext4_can_truncate(inode))
+ 		/* if we have allocated more blocks and copied
+ 		 * less. We will have blocks allocated outside
+ 		 * inode->i_size. So truncate them
+ 		 */
+ 		ext4_orphan_add(handle, inode);
+-
+-	if (ret2 < 0)
+-		ret = ret2;
+-
++errout:
+ 	ret2 = ext4_journal_stop(handle);
+ 	if (!ret)
+ 		ret = ret2;
+@@ -2818,18 +2777,9 @@ static int ext4_da_write_end(struct file *file,
+ 	unsigned long start, end;
+ 	int write_mode = (int)(unsigned long)fsdata;
+ 
+-	if (write_mode == FALL_BACK_TO_NONDELALLOC) {
+-		switch (ext4_inode_journal_mode(inode)) {
+-		case EXT4_INODE_ORDERED_DATA_MODE:
+-			return ext4_ordered_write_end(file, mapping, pos,
+-					len, copied, page, fsdata);
+-		case EXT4_INODE_WRITEBACK_DATA_MODE:
+-			return ext4_writeback_write_end(file, mapping, pos,
+-					len, copied, page, fsdata);
+-		default:
+-			BUG();
+-		}
+-	}
++	if (write_mode == FALL_BACK_TO_NONDELALLOC)
++		return ext4_write_end(file, mapping, pos,
++				      len, copied, page, fsdata);
+ 
+ 	trace_ext4_da_write_end(inode, pos, len, copied);
+ 	start = pos & (PAGE_CACHE_SIZE - 1);
+@@ -3334,27 +3284,12 @@ static int ext4_journalled_set_page_dirty(struct page *page)
+ 	return __set_page_dirty_nobuffers(page);
+ }
+ 
+-static const struct address_space_operations ext4_ordered_aops = {
++static const struct address_space_operations ext4_aops = {
+ 	.readpage		= ext4_readpage,
+ 	.readpages		= ext4_readpages,
+ 	.writepage		= ext4_writepage,
+ 	.write_begin		= ext4_write_begin,
+-	.write_end		= ext4_ordered_write_end,
+-	.bmap			= ext4_bmap,
+-	.invalidatepage		= ext4_invalidatepage,
+-	.releasepage		= ext4_releasepage,
+-	.direct_IO		= ext4_direct_IO,
+-	.migratepage		= buffer_migrate_page,
+-	.is_partially_uptodate  = block_is_partially_uptodate,
+-	.error_remove_page	= generic_error_remove_page,
+-};
+-
+-static const struct address_space_operations ext4_writeback_aops = {
+-	.readpage		= ext4_readpage,
+-	.readpages		= ext4_readpages,
+-	.writepage		= ext4_writepage,
+-	.write_begin		= ext4_write_begin,
+-	.write_end		= ext4_writeback_write_end,
++	.write_end		= ext4_write_end,
+ 	.bmap			= ext4_bmap,
+ 	.invalidatepage		= ext4_invalidatepage,
+ 	.releasepage		= ext4_releasepage,
+@@ -3399,23 +3334,21 @@ void ext4_set_aops(struct inode *inode)
+ {
+ 	switch (ext4_inode_journal_mode(inode)) {
+ 	case EXT4_INODE_ORDERED_DATA_MODE:
+-		if (test_opt(inode->i_sb, DELALLOC))
+-			inode->i_mapping->a_ops = &ext4_da_aops;
+-		else
+-			inode->i_mapping->a_ops = &ext4_ordered_aops;
++		ext4_set_inode_state(inode, EXT4_STATE_ORDERED_MODE);
+ 		break;
+ 	case EXT4_INODE_WRITEBACK_DATA_MODE:
+-		if (test_opt(inode->i_sb, DELALLOC))
+-			inode->i_mapping->a_ops = &ext4_da_aops;
+-		else
+-			inode->i_mapping->a_ops = &ext4_writeback_aops;
++		ext4_clear_inode_state(inode, EXT4_STATE_ORDERED_MODE);
+ 		break;
+ 	case EXT4_INODE_JOURNAL_DATA_MODE:
+ 		inode->i_mapping->a_ops = &ext4_journalled_aops;
+-		break;
++		return;
+ 	default:
+ 		BUG();
+ 	}
++	if (test_opt(inode->i_sb, DELALLOC))
++		inode->i_mapping->a_ops = &ext4_da_aops;
++	else
++		inode->i_mapping->a_ops = &ext4_aops;
+ }
+ 
+ 
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index 4ee471003859..58459b785565 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -257,15 +257,7 @@ DECLARE_EVENT_CLASS(ext4__write_end,
+ 		  __entry->pos, __entry->len, __entry->copied)
+ );
+ 
+-DEFINE_EVENT(ext4__write_end, ext4_ordered_write_end,
+-
+-	TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
+-		 unsigned int copied),
+-
+-	TP_ARGS(inode, pos, len, copied)
+-);
+-
+-DEFINE_EVENT(ext4__write_end, ext4_writeback_write_end,
++DEFINE_EVENT(ext4__write_end, ext4_write_end,
+ 
+ 	TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
+ 		 unsigned int copied),

commit 2b405bfa84063bfa35621d2d6879f52693c614b0
+Author: Theodore Ts'o 
+Date:   Wed Mar 20 09:42:11 2013 -0400
+
+    ext4: fix data=journal fast mount/umount hang
+    
+    In data=journal mode, if we unmount the file system before a
+    transaction has a chance to complete, when the journal inode is being
+    evicted, we can end up calling into jbd2_log_wait_commit() for the
+    last transaction, after the journalling machinery has been shut down.
+    
+    Arguably we should adjust ext4_should_journal_data() to return FALSE
+    for the journal inode, but the only place it matters is
+    ext4_evict_inode(), and so to save a bit of CPU time, and to make the
+    patch much more obviously correct by inspection(tm), we'll fix it by
+    explicitly not trying to waiting for a journal commit when we are
+    evicting the journal inode, since it's guaranteed to never succeed in
+    this case.
+    
+    This can be easily replicated via:
+    
+         mount -t ext4 -o data=journal /dev/vdb /vdb ; umount /vdb
+    
+    ------------[ cut here ]------------
+    WARNING: at /usr/projects/linux/ext4/fs/jbd2/journal.c:542 __jbd2_log_start_commit+0xba/0xcd()
+    Hardware name: Bochs
+    JBD2: bad log_start_commit: 3005630206 3005630206 0 0
+    Modules linked in:
+    Pid: 2909, comm: umount Not tainted 3.8.0-rc3 #1020
+    Call Trace:
+     [] warn_slowpath_common+0x68/0x7d
+     [] ? __jbd2_log_start_commit+0xba/0xcd
+     [] warn_slowpath_fmt+0x2b/0x2f
+     [] __jbd2_log_start_commit+0xba/0xcd
+     [] jbd2_log_start_commit+0x24/0x34
+     [] ext4_evict_inode+0x71/0x2e3
+     [] evict+0x94/0x135
+     [] iput+0x10a/0x110
+     [] jbd2_journal_destroy+0x190/0x1ce
+     [] ? bit_waitqueue+0x50/0x50
+     [] ext4_put_super+0x52/0x294
+     [] generic_shutdown_super+0x48/0xb4
+     [] kill_block_super+0x22/0x60
+     [] deactivate_locked_super+0x22/0x49
+     [] deactivate_super+0x30/0x33
+     [] mntput_no_expire+0x107/0x10c
+     [] sys_umount+0x2cf/0x2e0
+     [] sys_oldumount+0x12/0x14
+     [] syscall_call+0x7/0xb
+    ---[ end trace 6a954cc790501c1f ]---
+    jbd2_log_wait_commit: error: j_commit_request=-1289337090, tid=0
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Jan Kara 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index ea5f24ffa60c..85e41a2a39ad 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -205,7 +205,8 @@ void ext4_evict_inode(struct inode *inode)
+ 		 * don't use page cache.
+ 		 */
+ 		if (ext4_should_journal_data(inode) &&
+-		    (S_ISLNK(inode->i_mode) || S_ISREG(inode->i_mode))) {
++		    (S_ISLNK(inode->i_mode) || S_ISREG(inode->i_mode)) &&
++		    inode->i_ino != EXT4_JOURNAL_INO) {
+ 			journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
+ 			tid_t commit_tid = EXT4_I(inode)->i_datasync_tid;
+ 

commit 1ada47d9468fe3907f7f9e00179168f5e2f90803
+Author: Theodore Ts'o 
+Date:   Wed Mar 20 09:39:42 2013 -0400
+
+    ext4: fix ext4_evict_inode() racing against workqueue processing code
+    
+    Commit 84c17543ab56 (ext4: move work from io_end to inode) triggered a
+    regression when running xfstest #270 when the file system is mounted
+    with dioread_nolock.
+    
+    The problem is that after ext4_evict_inode() calls ext4_ioend_wait(),
+    this guarantees that last io_end structure has been freed, but it does
+    not guarantee that the workqueue structure, which was moved into the
+    inode by commit 84c17543ab56, is actually finished.  Once
+    ext4_flush_completed_IO() calls ext4_free_io_end() on CPU #1, this
+    will allow ext4_ioend_wait() to return on CPU #2, at which point the
+    evict_inode() codepath can race against the workqueue code on CPU #1
+    accessing EXT4_I(inode)->i_unwritten_work to find the next item of
+    work to do.
+    
+    Fix this by calling cancel_work_sync() in ext4_ioend_wait(), which
+    will be renamed ext4_ioend_shutdown(), since it is only used by
+    ext4_evict_inode().  Also, move the call to ext4_ioend_shutdown()
+    until after truncate_inode_pages() and filemap_write_and_wait() are
+    called, to make sure all dirty pages have been written back and
+    flushed from the page cache first.
+    
+    BUG: unable to handle kernel NULL pointer dereference at   (null)
+    IP: [] cwq_activate_delayed_work+0x3b/0x7e
+    *pdpt = 0000000030bc3001 *pde = 0000000000000000
+    Oops: 0000 [#1] SMP DEBUG_PAGEALLOC
+    Modules linked in:
+    Pid: 6, comm: kworker/u:0 Not tainted 3.8.0-rc3-00013-g84c1754-dirty #91 Bochs Bochs
+    EIP: 0060:[] EFLAGS: 00010046 CPU: 0
+    EIP is at cwq_activate_delayed_work+0x3b/0x7e
+    EAX: 00000000 EBX: 00000000 ECX: f505fe54 EDX: 00000000
+    ESI: ed5b697c EDI: 00000006 EBP: f64b7e8c ESP: f64b7e84
+     DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068
+    CR0: 8005003b CR2: 00000000 CR3: 30bc2000 CR4: 000006f0
+    DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
+    DR6: ffff0ff0 DR7: 00000400
+    Process kworker/u:0 (pid: 6, ti=f64b6000 task=f64b4160 task.ti=f64b6000)
+    Stack:
+     f505fe00 00000006 f64b7e9c c01de3d7 f6435540 00000003 f64b7efc c01def1d
+     f6435540 00000002 00000000 0000008a c16d0808 c040a10b c16d07d8 c16d08b0
+     f505fe00 c16d0780 00000000 00000000 ee153df4 c1ce4a30 c17d0e30 00000000
+    Call Trace:
+     [] cwq_dec_nr_in_flight+0x71/0xfb
+     [] process_one_work+0x5d8/0x637
+     [] ? ext4_end_bio+0x300/0x300
+     [] worker_thread+0x249/0x3ef
+     [] kthread+0xd8/0xeb
+     [] ? manage_workers+0x4bb/0x4bb
+     [] ? trace_hardirqs_on+0x27/0x37
+     [] ret_from_kernel_thread+0x1b/0x28
+     [] ? __init_kthread_worker+0x71/0x71
+    Code: 01 83 15 ac ff 6c c1 00 31 db 89 c6 8b 00 a8 04 74 12 89 c3 30 db 83 05 b0 ff 6c c1 01 83 15 b4 ff 6c c1 00 89 f0 e8 42 ff ff ff <8b> 13 89 f0 83 05 b8 ff 6c c1
+     6c c1 00 31 c9 83
+    EIP: [] cwq_activate_delayed_work+0x3b/0x7e SS:ESP 0068:f64b7e84
+    CR2: 0000000000000000
+    ---[ end trace a1923229da53d8a4 ]---
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Jan Kara 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 167ff564bbfa..3b83cd604796 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2617,7 +2617,7 @@ extern int ext4_move_extents(struct file *o_filp, struct file *d_filp,
+ extern int __init ext4_init_pageio(void);
+ extern void ext4_add_complete_io(ext4_io_end_t *io_end);
+ extern void ext4_exit_pageio(void);
+-extern void ext4_ioend_wait(struct inode *);
++extern void ext4_ioend_shutdown(struct inode *);
+ extern void ext4_free_io_end(ext4_io_end_t *io);
+ extern ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags);
+ extern void ext4_end_io_work(struct work_struct *work);
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 65bbc9339aca..ea5f24ffa60c 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -185,8 +185,6 @@ void ext4_evict_inode(struct inode *inode)
+ 
+ 	trace_ext4_evict_inode(inode);
+ 
+-	ext4_ioend_wait(inode);
+-
+ 	if (inode->i_nlink) {
+ 		/*
+ 		 * When journalling data dirty buffers are tracked only in the
+@@ -216,6 +214,7 @@ void ext4_evict_inode(struct inode *inode)
+ 			filemap_write_and_wait(&inode->i_data);
+ 		}
+ 		truncate_inode_pages(&inode->i_data, 0);
++		ext4_ioend_shutdown(inode);
+ 		goto no_delete;
+ 	}
+ 
+@@ -225,6 +224,7 @@ void ext4_evict_inode(struct inode *inode)
+ 	if (ext4_should_order_data(inode))
+ 		ext4_begin_ordered_truncate(inode, 0);
+ 	truncate_inode_pages(&inode->i_data, 0);
++	ext4_ioend_shutdown(inode);
+ 
+ 	if (is_bad_inode(inode))
+ 		goto no_delete;
+diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
+index 809b31003ecc..047a6de04a0a 100644
+--- a/fs/ext4/page-io.c
++++ b/fs/ext4/page-io.c
+@@ -50,11 +50,21 @@ void ext4_exit_pageio(void)
+ 	kmem_cache_destroy(io_page_cachep);
+ }
+ 
+-void ext4_ioend_wait(struct inode *inode)
++/*
++ * This function is called by ext4_evict_inode() to make sure there is
++ * no more pending I/O completion work left to do.
++ */
++void ext4_ioend_shutdown(struct inode *inode)
+ {
+ 	wait_queue_head_t *wq = ext4_ioend_wq(inode);
+ 
+ 	wait_event(*wq, (atomic_read(&EXT4_I(inode)->i_ioend_count) == 0));
++	/*
++	 * We need to make sure the work structure is finished being
++	 * used before we let the inode get destroyed.
++	 */
++	if (work_pending(&EXT4_I(inode)->i_unwritten_work))
++		cancel_work_sync(&EXT4_I(inode)->i_unwritten_work);
+ }
+ 
+ static void put_io_page(struct ext4_io_page *io_page)

commit 90ba983f6889e65a3b506b30dc606aa9d1d46cd2
+Author: Theodore Ts'o 
+Date:   Mon Mar 11 23:39:59 2013 -0400
+
+    ext4: use atomic64_t for the per-flexbg free_clusters count
+    
+    A user who was using a 8TB+ file system and with a very large flexbg
+    size (> 65536) could cause the atomic_t used in the struct flex_groups
+    to overflow.  This was detected by PaX security patchset:
+    
+    http://forums.grsecurity.net/viewtopic.php?f=3&t=3289&p=12551#p12551
+    
+    This bug was introduced in commit 9f24e4208f7e, so it's been around
+    since 2.6.30.  :-(
+    
+    Fix this by using an atomic64_t for struct orlav_stats's
+    free_clusters.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Lukas Czerner 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 4a01ba315262..167ff564bbfa 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -335,9 +335,9 @@ struct ext4_group_desc
+  */
+ 
+ struct flex_groups {
+-	atomic_t free_inodes;
+-	atomic_t free_clusters;
+-	atomic_t used_dirs;
++	atomic64_t	free_clusters;
++	atomic_t	free_inodes;
++	atomic_t	used_dirs;
+ };
+ 
+ #define EXT4_BG_INODE_UNINIT	0x0001 /* Inode table/bitmap not in use */
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 32fd2b9075dd..6c5bb8d993fe 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -324,8 +324,8 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
+ }
+ 
+ struct orlov_stats {
++	__u64 free_clusters;
+ 	__u32 free_inodes;
+-	__u32 free_clusters;
+ 	__u32 used_dirs;
+ };
+ 
+@@ -342,7 +342,7 @@ static void get_orlov_stats(struct super_block *sb, ext4_group_t g,
+ 
+ 	if (flex_size > 1) {
+ 		stats->free_inodes = atomic_read(&flex_group[g].free_inodes);
+-		stats->free_clusters = atomic_read(&flex_group[g].free_clusters);
++		stats->free_clusters = atomic64_read(&flex_group[g].free_clusters);
+ 		stats->used_dirs = atomic_read(&flex_group[g].used_dirs);
+ 		return;
+ 	}
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 8b2ea9f75004..ee6614bdb639 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2804,8 +2804,8 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
+ 	if (sbi->s_log_groups_per_flex) {
+ 		ext4_group_t flex_group = ext4_flex_group(sbi,
+ 							  ac->ac_b_ex.fe_group);
+-		atomic_sub(ac->ac_b_ex.fe_len,
+-			   &sbi->s_flex_groups[flex_group].free_clusters);
++		atomic64_sub(ac->ac_b_ex.fe_len,
++			     &sbi->s_flex_groups[flex_group].free_clusters);
+ 	}
+ 
+ 	err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
+@@ -4661,8 +4661,8 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 
+ 	if (sbi->s_log_groups_per_flex) {
+ 		ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
+-		atomic_add(count_clusters,
+-			   &sbi->s_flex_groups[flex_group].free_clusters);
++		atomic64_add(count_clusters,
++			     &sbi->s_flex_groups[flex_group].free_clusters);
+ 	}
+ 
+ 	ext4_mb_unload_buddy(&e4b);
+@@ -4804,8 +4804,8 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
+ 
+ 	if (sbi->s_log_groups_per_flex) {
+ 		ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
+-		atomic_add(EXT4_NUM_B2C(sbi, blocks_freed),
+-			   &sbi->s_flex_groups[flex_group].free_clusters);
++		atomic64_add(EXT4_NUM_B2C(sbi, blocks_freed),
++			     &sbi->s_flex_groups[flex_group].free_clusters);
+ 	}
+ 
+ 	ext4_mb_unload_buddy(&e4b);
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index b2c8ee56eb98..c169477a62c9 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -1360,8 +1360,8 @@ static void ext4_update_super(struct super_block *sb,
+ 	    sbi->s_log_groups_per_flex) {
+ 		ext4_group_t flex_group;
+ 		flex_group = ext4_flex_group(sbi, group_data[0].group);
+-		atomic_add(EXT4_NUM_B2C(sbi, free_blocks),
+-			   &sbi->s_flex_groups[flex_group].free_clusters);
++		atomic64_add(EXT4_NUM_B2C(sbi, free_blocks),
++			     &sbi->s_flex_groups[flex_group].free_clusters);
+ 		atomic_add(EXT4_INODES_PER_GROUP(sb) * flex_gd->count,
+ 			   &sbi->s_flex_groups[flex_group].free_inodes);
+ 	}
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 9379b7fbfd92..d1ee6a84338a 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1923,8 +1923,8 @@ static int ext4_fill_flex_info(struct super_block *sb)
+ 		flex_group = ext4_flex_group(sbi, i);
+ 		atomic_add(ext4_free_inodes_count(sb, gdp),
+ 			   &sbi->s_flex_groups[flex_group].free_inodes);
+-		atomic_add(ext4_free_group_clusters(sb, gdp),
+-			   &sbi->s_flex_groups[flex_group].free_clusters);
++		atomic64_add(ext4_free_group_clusters(sb, gdp),
++			     &sbi->s_flex_groups[flex_group].free_clusters);
+ 		atomic_add(ext4_used_dirs_count(sb, gdp),
+ 			   &sbi->s_flex_groups[flex_group].used_dirs);
+ 	}

commit b980955236922ae6106774511c5c05003d3ad225
+Author: Theodore Ts'o 
+Date:   Mon Mar 4 11:59:12 2013 -0500
+
+    random: fix locking dependency with the tasklist_lock
+    
+    Commit 6133705494bb introduced a circular lock dependency because
+    posix_cpu_timers_exit() is called by release_task(), which is holding
+    a writer lock on tasklist_lock, and this can cause a deadlock since
+    kill_fasync() gets called with nonblocking_pool.lock taken.
+    
+    There's no reason why kill_fasync() needs to be taken while the random
+    pool is locked, so move it out to fix this locking dependency.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reported-by: Russ Dill 
+    Cc: stable@kernel.org
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 85e81ec1451e..57d4b152267c 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -852,6 +852,7 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
+ 		      int reserved)
+ {
+ 	unsigned long flags;
++	int wakeup_write = 0;
+ 
+ 	/* Hold lock while accounting */
+ 	spin_lock_irqsave(&r->lock, flags);
+@@ -873,10 +874,8 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
+ 		else
+ 			r->entropy_count = reserved;
+ 
+-		if (r->entropy_count < random_write_wakeup_thresh) {
+-			wake_up_interruptible(&random_write_wait);
+-			kill_fasync(&fasync, SIGIO, POLL_OUT);
+-		}
++		if (r->entropy_count < random_write_wakeup_thresh)
++			wakeup_write = 1;
+ 	}
+ 
+ 	DEBUG_ENT("debiting %zu entropy credits from %s%s\n",
+@@ -884,6 +883,11 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
+ 
+ 	spin_unlock_irqrestore(&r->lock, flags);
+ 
++	if (wakeup_write) {
++		wake_up_interruptible(&random_write_wait);
++		kill_fasync(&fasync, SIGIO, POLL_OUT);
++	}
++
+ 	return nbytes;
+ }
+ 

commit 1ac6466f253ef7bd063b7877fb056afe1820841c
+Author: Theodore Ts'o 
+Date:   Sat Mar 2 10:27:46 2013 -0500
+
+    ext4: use percpu counter for extent cache count
+    
+    Use a percpu counter rather than atomic types for shrinker accounting.
+    There's no need for ultimate accuracy in the shrinker, so this
+    should come a little more cheaply.  The percpu struct is somewhat
+    large, but there was a big gap before the cache-aligned
+    s_es_lru_lock anyway, and it fits nicely in there.
+    
+    Signed-off-by: Eric Sandeen 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 96c10934bb96..4a01ba315262 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1268,7 +1268,6 @@ struct ext4_sb_info {
+ 	atomic_t s_mb_preallocated;
+ 	atomic_t s_mb_discarded;
+ 	atomic_t s_lock_busy;
+-	atomic_t s_extent_cache_cnt;
+ 
+ 	/* locality groups */
+ 	struct ext4_locality_group __percpu *s_locality_groups;
+@@ -1310,6 +1309,7 @@ struct ext4_sb_info {
+ 	/* Reclaim extents from extent status tree */
+ 	struct shrinker s_es_shrinker;
+ 	struct list_head s_es_lru;
++	struct percpu_counter s_extent_cache_cnt;
+ 	spinlock_t s_es_lru_lock ____cacheline_aligned_in_smp;
+ };
+ 
+diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
+index 27fcdd2b2607..95796a1b7522 100644
+--- a/fs/ext4/extents_status.c
++++ b/fs/ext4/extents_status.c
+@@ -305,7 +305,7 @@ ext4_es_alloc_extent(struct inode *inode, ext4_lblk_t lblk, ext4_lblk_t len,
+ 	 */
+ 	if (!ext4_es_is_delayed(es)) {
+ 		EXT4_I(inode)->i_es_lru_nr++;
+-		atomic_inc(&EXT4_SB(inode->i_sb)->s_extent_cache_cnt);
++		percpu_counter_inc(&EXT4_SB(inode->i_sb)->s_extent_cache_cnt);
+ 	}
+ 
+ 	return es;
+@@ -317,7 +317,7 @@ static void ext4_es_free_extent(struct inode *inode, struct extent_status *es)
+ 	if (!ext4_es_is_delayed(es)) {
+ 		BUG_ON(EXT4_I(inode)->i_es_lru_nr == 0);
+ 		EXT4_I(inode)->i_es_lru_nr--;
+-		atomic_dec(&EXT4_SB(inode->i_sb)->s_extent_cache_cnt);
++		percpu_counter_dec(&EXT4_SB(inode->i_sb)->s_extent_cache_cnt);
+ 	}
+ 
+ 	kmem_cache_free(ext4_es_cachep, es);
+@@ -678,7 +678,7 @@ static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc)
+ 	int nr_to_scan = sc->nr_to_scan;
+ 	int ret, nr_shrunk = 0;
+ 
+-	ret = atomic_read(&sbi->s_extent_cache_cnt);
++	ret = percpu_counter_read_positive(&sbi->s_extent_cache_cnt);
+ 	trace_ext4_es_shrink_enter(sbi->s_sb, nr_to_scan, ret);
+ 
+ 	if (!nr_to_scan)
+@@ -711,7 +711,7 @@ static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc)
+ 	list_splice_tail(&scanned, &sbi->s_es_lru);
+ 	spin_unlock(&sbi->s_es_lru_lock);
+ 
+-	ret = atomic_read(&sbi->s_extent_cache_cnt);
++	ret = percpu_counter_read_positive(&sbi->s_extent_cache_cnt);
+ 	trace_ext4_es_shrink_exit(sbi->s_sb, nr_shrunk, ret);
+ 	return ret;
+ }
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 373d46cd5d3f..1ae5860b30a3 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -783,6 +783,7 @@ static void ext4_put_super(struct super_block *sb)
+ 	percpu_counter_destroy(&sbi->s_freeinodes_counter);
+ 	percpu_counter_destroy(&sbi->s_dirs_counter);
+ 	percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
++	percpu_counter_destroy(&sbi->s_extent_cache_cnt);
+ 	brelse(sbi->s_sbh);
+ #ifdef CONFIG_QUOTA
+ 	for (i = 0; i < MAXQUOTAS; i++)
+@@ -3688,6 +3689,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	if (!err) {
+ 		err = percpu_counter_init(&sbi->s_dirtyclusters_counter, 0);
+ 	}
++	if (!err) {
++		err = percpu_counter_init(&sbi->s_extent_cache_cnt, 0);
++	}
+ 	if (err) {
+ 		ext4_msg(sb, KERN_ERR, "insufficient memory");
+ 		goto failed_mount3;
+@@ -3993,6 +3997,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	percpu_counter_destroy(&sbi->s_freeinodes_counter);
+ 	percpu_counter_destroy(&sbi->s_dirs_counter);
+ 	percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
++	percpu_counter_destroy(&sbi->s_extent_cache_cnt);
+ 	if (sbi->s_mmp_tsk)
+ 		kthread_stop(sbi->s_mmp_tsk);
+ failed_mount2:

commit 246307745c406379996e6ed6411f0e20f1ce1449
+Author: Theodore Ts'o 
+Date:   Thu Feb 28 23:58:56 2013 -0500
+
+    ext4: optimize ext4_es_shrink()
+    
+    When the system is under memory pressure, ext4_es_srhink() will get
+    called very often.  So optimize returning the number of items in the
+    file system's extent status cache by keeping a per-filesystem count,
+    instead of calculating it each time by scanning all of the inodes in
+    the extent status cache.
+    
+    Also rename the slab used for the extent status cache to be
+    "ext4_extent_status" so it's obviousl the slab in question is created
+    by ext4.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Zheng Liu 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 6e16c1867959..96c10934bb96 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1268,6 +1268,7 @@ struct ext4_sb_info {
+ 	atomic_t s_mb_preallocated;
+ 	atomic_t s_mb_discarded;
+ 	atomic_t s_lock_busy;
++	atomic_t s_extent_cache_cnt;
+ 
+ 	/* locality groups */
+ 	struct ext4_locality_group __percpu *s_locality_groups;
+diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
+index f768f4a98a2b..27fcdd2b2607 100644
+--- a/fs/ext4/extents_status.c
++++ b/fs/ext4/extents_status.c
+@@ -147,11 +147,12 @@ static int __es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
+ 			      ext4_lblk_t end);
+ static int __es_try_to_reclaim_extents(struct ext4_inode_info *ei,
+ 				       int nr_to_scan);
+-static int ext4_es_reclaim_extents_count(struct super_block *sb);
+ 
+ int __init ext4_init_es(void)
+ {
+-	ext4_es_cachep = KMEM_CACHE(extent_status, SLAB_RECLAIM_ACCOUNT);
++	ext4_es_cachep = kmem_cache_create("ext4_extent_status",
++					   sizeof(struct extent_status),
++					   0, (SLAB_RECLAIM_ACCOUNT), NULL);
+ 	if (ext4_es_cachep == NULL)
+ 		return -ENOMEM;
+ 	return 0;
+@@ -302,8 +303,10 @@ ext4_es_alloc_extent(struct inode *inode, ext4_lblk_t lblk, ext4_lblk_t len,
+ 	/*
+ 	 * We don't count delayed extent because we never try to reclaim them
+ 	 */
+-	if (!ext4_es_is_delayed(es))
++	if (!ext4_es_is_delayed(es)) {
+ 		EXT4_I(inode)->i_es_lru_nr++;
++		atomic_inc(&EXT4_SB(inode->i_sb)->s_extent_cache_cnt);
++	}
+ 
+ 	return es;
+ }
+@@ -314,6 +317,7 @@ static void ext4_es_free_extent(struct inode *inode, struct extent_status *es)
+ 	if (!ext4_es_is_delayed(es)) {
+ 		BUG_ON(EXT4_I(inode)->i_es_lru_nr == 0);
+ 		EXT4_I(inode)->i_es_lru_nr--;
++		atomic_dec(&EXT4_SB(inode->i_sb)->s_extent_cache_cnt);
+ 	}
+ 
+ 	kmem_cache_free(ext4_es_cachep, es);
+@@ -674,10 +678,11 @@ static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc)
+ 	int nr_to_scan = sc->nr_to_scan;
+ 	int ret, nr_shrunk = 0;
+ 
+-	trace_ext4_es_shrink_enter(sbi->s_sb, nr_to_scan);
++	ret = atomic_read(&sbi->s_extent_cache_cnt);
++	trace_ext4_es_shrink_enter(sbi->s_sb, nr_to_scan, ret);
+ 
+ 	if (!nr_to_scan)
+-		return ext4_es_reclaim_extents_count(sbi->s_sb);
++		return ret;
+ 
+ 	INIT_LIST_HEAD(&scanned);
+ 
+@@ -705,9 +710,10 @@ static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc)
+ 	}
+ 	list_splice_tail(&scanned, &sbi->s_es_lru);
+ 	spin_unlock(&sbi->s_es_lru_lock);
+-	trace_ext4_es_shrink_exit(sbi->s_sb, nr_shrunk);
+ 
+-	return ext4_es_reclaim_extents_count(sbi->s_sb);
++	ret = atomic_read(&sbi->s_extent_cache_cnt);
++	trace_ext4_es_shrink_exit(sbi->s_sb, nr_shrunk, ret);
++	return ret;
+ }
+ 
+ void ext4_es_register_shrinker(struct super_block *sb)
+@@ -751,25 +757,6 @@ void ext4_es_lru_del(struct inode *inode)
+ 	spin_unlock(&sbi->s_es_lru_lock);
+ }
+ 
+-static int ext4_es_reclaim_extents_count(struct super_block *sb)
+-{
+-	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-	struct ext4_inode_info *ei;
+-	struct list_head *cur;
+-	int nr_cached = 0;
+-
+-	spin_lock(&sbi->s_es_lru_lock);
+-	list_for_each(cur, &sbi->s_es_lru) {
+-		ei = list_entry(cur, struct ext4_inode_info, i_es_lru);
+-		read_lock(&ei->i_es_lock);
+-		nr_cached += ei->i_es_lru_nr;
+-		read_unlock(&ei->i_es_lock);
+-	}
+-	spin_unlock(&sbi->s_es_lru_lock);
+-	trace_ext4_es_reclaim_extents_count(sb, nr_cached);
+-	return nr_cached;
+-}
+-
+ static int __es_try_to_reclaim_extents(struct ext4_inode_info *ei,
+ 				       int nr_to_scan)
+ {
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index c0457c0d1a68..4ee471003859 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -2255,64 +2255,48 @@ TRACE_EVENT(ext4_es_lookup_extent_exit,
+ 		  __entry->found ? __entry->status : 0)
+ );
+ 
+-TRACE_EVENT(ext4_es_reclaim_extents_count,
+-	TP_PROTO(struct super_block *sb, int nr_cached),
+-
+-	TP_ARGS(sb, nr_cached),
+-
+-	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
+-		__field(	int,	nr_cached		)
+-	),
+-
+-	TP_fast_assign(
+-		__entry->dev		= sb->s_dev;
+-		__entry->nr_cached	= nr_cached;
+-	),
+-
+-	TP_printk("dev %d,%d cached objects nr %d",
+-		  MAJOR(__entry->dev), MINOR(__entry->dev),
+-		  __entry->nr_cached)
+-);
+-
+ TRACE_EVENT(ext4_es_shrink_enter,
+-	TP_PROTO(struct super_block *sb, int nr_to_scan),
++	TP_PROTO(struct super_block *sb, int nr_to_scan, int cache_cnt),
+ 
+-	TP_ARGS(sb, nr_to_scan),
++	TP_ARGS(sb, nr_to_scan, cache_cnt),
+ 
+ 	TP_STRUCT__entry(
+ 		__field(	dev_t,	dev			)
+ 		__field(	int,	nr_to_scan		)
++		__field(	int,	cache_cnt		)
+ 	),
+ 
+ 	TP_fast_assign(
+ 		__entry->dev		= sb->s_dev;
+ 		__entry->nr_to_scan	= nr_to_scan;
++		__entry->cache_cnt	= cache_cnt;
+ 	),
+ 
+-	TP_printk("dev %d,%d nr to scan %d",
++	TP_printk("dev %d,%d nr_to_scan %d cache_cnt %d",
+ 		  MAJOR(__entry->dev), MINOR(__entry->dev),
+-		  __entry->nr_to_scan)
++		  __entry->nr_to_scan, __entry->cache_cnt)
+ );
+ 
+ TRACE_EVENT(ext4_es_shrink_exit,
+-	TP_PROTO(struct super_block *sb, int shrunk_nr),
++	TP_PROTO(struct super_block *sb, int shrunk_nr, int cache_cnt),
+ 
+-	TP_ARGS(sb, shrunk_nr),
++	TP_ARGS(sb, shrunk_nr, cache_cnt),
+ 
+ 	TP_STRUCT__entry(
+ 		__field(	dev_t,	dev			)
+ 		__field(	int,	shrunk_nr		)
++		__field(	int,	cache_cnt		)
+ 	),
+ 
+ 	TP_fast_assign(
+ 		__entry->dev		= sb->s_dev;
+ 		__entry->shrunk_nr	= shrunk_nr;
++		__entry->cache_cnt	= cache_cnt;
+ 	),
+ 
+-	TP_printk("dev %d,%d nr to scan %d",
++	TP_printk("dev %d,%d shrunk_nr %d cache_cnt %d",
+ 		  MAJOR(__entry->dev), MINOR(__entry->dev),
+-		  __entry->shrunk_nr)
++		  __entry->shrunk_nr, __entry->cache_cnt)
+ );
+ 
+ #endif /* _TRACE_EXT4_H */

commit 8e919d13048cd5acaadb2b15b48acbfb8832d3c2
+Author: Theodore Ts'o 
+Date:   Wed Feb 27 14:54:37 2013 -0500
+
+    ext4: fix extent status tree regression for file systems > 512GB
+    
+    This fixes a regression introduced by commit f7fec032aa782.  The
+    problem was that the extents status flags caused us to mask out block
+    numbers smaller than 2**28 blocks.  Since we didn't test with file
+    systems smaller than 512GB, we didn't notice this during the
+    development cycle.
+    
+    A typical failure looks like this:
+    
+    EXT4-fs error (device sdb1): htree_dirblock_to_tree:919: inode #172235804: block
+    152052301: comm ls: bad entry in directory: rec_len is smaller than minimal -
+    offset=0(0), inode=0, rec_len=0, name_len=0
+    
+    ... where 'debugfs -R "stat <172235804>" /dev/sdb1' reports that the
+    inode has block number 688923213.  When viewed in hex, block number
+    152052301 (from the syslog) is 0x910224D, while block number 688923213
+    is 0x2910224D.  Note the missing "0x20000000" in the block number.
+    
+    Reported-by: Markus Trippelsdorf 
+    Verified-by: Markus Trippelsdorf 
+    Reported-by: Dave Jones 
+    Verified-by: Dave Jones 
+    Cc: Zheng Liu 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h
+index cf83e77b16cb..f190dfe969da 100644
+--- a/fs/ext4/extents_status.h
++++ b/fs/ext4/extents_status.h
+@@ -20,10 +20,13 @@
+ #define es_debug(fmt, ...)	no_printk(fmt, ##__VA_ARGS__)
+ #endif
+ 
+-#define EXTENT_STATUS_WRITTEN	0x80000000	/* written extent */
+-#define EXTENT_STATUS_UNWRITTEN	0x40000000	/* unwritten extent */
+-#define EXTENT_STATUS_DELAYED	0x20000000	/* delayed extent */
+-#define EXTENT_STATUS_HOLE	0x10000000	/* hole */
++/*
++ * These flags live in the high bits of extent_status.es_pblk
++ */
++#define EXTENT_STATUS_WRITTEN	(1ULL << 63)
++#define EXTENT_STATUS_UNWRITTEN (1ULL << 62)
++#define EXTENT_STATUS_DELAYED	(1ULL << 61)
++#define EXTENT_STATUS_HOLE	(1ULL << 60)
+ 
+ #define EXTENT_STATUS_FLAGS	(EXTENT_STATUS_WRITTEN | \
+ 				 EXTENT_STATUS_UNWRITTEN | \
+@@ -58,22 +61,22 @@ extern int ext4_es_lookup_extent(struct inode *inode, ext4_lblk_t lblk,
+ 
+ static inline int ext4_es_is_written(struct extent_status *es)
+ {
+-	return (es->es_pblk & EXTENT_STATUS_WRITTEN);
++	return (es->es_pblk & EXTENT_STATUS_WRITTEN) != 0;
+ }
+ 
+ static inline int ext4_es_is_unwritten(struct extent_status *es)
+ {
+-	return (es->es_pblk & EXTENT_STATUS_UNWRITTEN);
++	return (es->es_pblk & EXTENT_STATUS_UNWRITTEN) != 0;
+ }
+ 
+ static inline int ext4_es_is_delayed(struct extent_status *es)
+ {
+-	return (es->es_pblk & EXTENT_STATUS_DELAYED);
++	return (es->es_pblk & EXTENT_STATUS_DELAYED) != 0;
+ }
+ 
+ static inline int ext4_es_is_hole(struct extent_status *es)
+ {
+-	return (es->es_pblk & EXTENT_STATUS_HOLE);
++	return (es->es_pblk & EXTENT_STATUS_HOLE) != 0;
+ }
+ 
+ static inline ext4_fsblk_t ext4_es_status(struct extent_status *es)

commit 0f70b40613ee14b0cadafeb461034cff81b4419a
+Author: Theodore Ts'o 
+Date:   Fri Feb 15 03:35:57 2013 -0500
+
+    ext4: use ERR_PTR() abstraction for ext4_append()
+    
+    Use ERR_PTR()/IS_ERR() abstraction instead of passing in a separate
+    pointer to an integer for the error code, as a code cleanup.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index c4e9177f60c6..f4466c3650dc 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -707,6 +707,8 @@ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
+ 	/* ensure we send some value back into *errp */
+ 	*errp = 0;
+ 
++	if (create && err == 0)
++		err = -ENOSPC;	/* should never happen */
+ 	if (err < 0)
+ 		*errp = err;
+ 	if (err <= 0)
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 0e28c749e273..f58c053d13e0 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -51,34 +51,28 @@
+ 
+ static struct buffer_head *ext4_append(handle_t *handle,
+ 					struct inode *inode,
+-					ext4_lblk_t *block, int *err)
++					ext4_lblk_t *block)
+ {
+ 	struct buffer_head *bh;
++	int err = 0;
+ 
+ 	if (unlikely(EXT4_SB(inode->i_sb)->s_max_dir_size_kb &&
+ 		     ((inode->i_size >> 10) >=
+-		      EXT4_SB(inode->i_sb)->s_max_dir_size_kb))) {
+-		*err = -ENOSPC;
+-		return NULL;
+-	}
++		      EXT4_SB(inode->i_sb)->s_max_dir_size_kb)))
++		return ERR_PTR(-ENOSPC);
+ 
+ 	*block = inode->i_size >> inode->i_sb->s_blocksize_bits;
+ 
+-	bh = ext4_bread(handle, inode, *block, 1, err);
+-	if (bh) {
+-		inode->i_size += inode->i_sb->s_blocksize;
+-		EXT4_I(inode)->i_disksize = inode->i_size;
+-		*err = ext4_journal_get_write_access(handle, bh);
+-		if (*err) {
+-			brelse(bh);
+-			bh = NULL;
+-		}
+-	}
+-	if (!bh && !(*err)) {
+-		*err = -EIO;
+-		ext4_error(inode->i_sb,
+-			   "Directory hole detected on inode %lu\n",
+-			   inode->i_ino);
++	bh = ext4_bread(handle, inode, *block, 1, &err);
++	if (!bh)
++		return ERR_PTR(err);
++	inode->i_size += inode->i_sb->s_blocksize;
++	EXT4_I(inode)->i_disksize = inode->i_size;
++	err = ext4_journal_get_write_access(handle, bh);
++	if (err) {
++		brelse(bh);
++		ext4_std_error(inode->i_sb, err);
++		return ERR_PTR(err);
+ 	}
+ 	return bh;
+ }
+@@ -1555,11 +1549,12 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
+ 				       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+ 		csum_size = sizeof(struct ext4_dir_entry_tail);
+ 
+-	bh2 = ext4_append (handle, dir, &newblock, &err);
+-	if (!(bh2)) {
++	bh2 = ext4_append(handle, dir, &newblock);
++	if (IS_ERR(bh2)) {
+ 		brelse(*bh);
+ 		*bh = NULL;
+-		goto errout;
++		*error = PTR_ERR(bh2);
++		return NULL;
+ 	}
+ 
+ 	BUFFER_TRACE(*bh, "get_write_access");
+@@ -1640,7 +1635,6 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
+ 	brelse(bh2);
+ 	*bh = NULL;
+ 	ext4_std_error(dir->i_sb, err);
+-errout:
+ 	*error = err;
+ 	return NULL;
+ }
+@@ -1815,10 +1809,10 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
+ 	len = ((char *) root) + (blocksize - csum_size) - (char *) de;
+ 
+ 	/* Allocate new block for the 0th block's dirents */
+-	bh2 = ext4_append(handle, dir, &block, &retval);
+-	if (!(bh2)) {
++	bh2 = ext4_append(handle, dir, &block);
++	if (IS_ERR(bh2)) {
+ 		brelse(bh);
+-		return retval;
++		return PTR_ERR(bh2);
+ 	}
+ 	ext4_set_inode_flag(dir, EXT4_INODE_INDEX);
+ 	data1 = bh2->b_data;
+@@ -1950,9 +1944,9 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
+ 			return make_indexed_dir(handle, dentry, inode, bh);
+ 		brelse(bh);
+ 	}
+-	bh = ext4_append(handle, dir, &block, &retval);
+-	if (!bh)
+-		return retval;
++	bh = ext4_append(handle, dir, &block);
++	if (IS_ERR(bh))
++		return PTR_ERR(bh);
+ 	de = (struct ext4_dir_entry_2 *) bh->b_data;
+ 	de->inode = 0;
+ 	de->rec_len = ext4_rec_len_to_disk(blocksize - csum_size, blocksize);
+@@ -2023,9 +2017,11 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+ 			err = -ENOSPC;
+ 			goto cleanup;
+ 		}
+-		bh2 = ext4_append (handle, dir, &newblock, &err);
+-		if (!(bh2))
++		bh2 = ext4_append(handle, dir, &newblock);
++		if (IS_ERR(bh2)) {
++			err = PTR_ERR(bh2);
+ 			goto cleanup;
++		}
+ 		node2 = (struct dx_node *)(bh2->b_data);
+ 		entries2 = node2->entries;
+ 		memset(&node2->fake, 0, sizeof(struct fake_dirent));
+@@ -2364,8 +2360,9 @@ static int ext4_init_new_dir(handle_t *handle, struct inode *dir,
+ 	}
+ 
+ 	inode->i_size = 0;
+-	if (!(dir_block = ext4_append(handle, inode, &block, &err)))
+-		goto out;
++	dir_block = ext4_append(handle, inode, &block);
++	if (IS_ERR(dir_block))
++		return PTR_ERR(dir_block);
+ 	BUFFER_TRACE(dir_block, "get_write_access");
+ 	err = ext4_journal_get_write_access(handle, dir_block);
+ 	if (err)

commit dc6982ff4db1f47da73b1967ef5302d6721e5b95
+Author: Theodore Ts'o 
+Date:   Thu Feb 14 23:59:26 2013 -0500
+
+    ext4: refactor code to read directory blocks into ext4_read_dirblock()
+    
+    The code to read in directory blocks and verify their metadata
+    checksums was replicated in ten different places across
+    fs/ext4/namei.c, and the code was buggy in subtle ways in a number of
+    those replicated sites.  In some cases, ext4_error() was called with a
+    training newline.  In others, in particularly in empty_dir(), it was
+    possible to call ext4_dirent_csum_verify() on an index block, which
+    would trigger false warnings requesting the system adminsitrator to
+    run e2fsck.
+    
+    By refactoring the code, we make the code more readable, as well as
+    shrinking the compiled object file by over 700 bytes and 50 lines of
+    code.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 3e1529c39808..0e28c749e273 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -83,6 +83,86 @@ static struct buffer_head *ext4_append(handle_t *handle,
+ 	return bh;
+ }
+ 
++static int ext4_dx_csum_verify(struct inode *inode,
++			       struct ext4_dir_entry *dirent);
++
++typedef enum {
++	EITHER, INDEX, DIRENT
++} dirblock_type_t;
++
++#define ext4_read_dirblock(inode, block, type) \
++	__ext4_read_dirblock((inode), (block), (type), __LINE__)
++
++static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
++					      ext4_lblk_t block,
++					      dirblock_type_t type,
++					      unsigned int line)
++{
++	struct buffer_head *bh;
++	struct ext4_dir_entry *dirent;
++	int err = 0, is_dx_block = 0;
++
++	bh = ext4_bread(NULL, inode, block, 0, &err);
++	if (!bh) {
++		if (err == 0) {
++			ext4_error_inode(inode, __func__, line, block,
++					       "Directory hole found");
++			return ERR_PTR(-EIO);
++		}
++		__ext4_warning(inode->i_sb, __func__, line,
++			       "error reading directory block "
++			       "(ino %lu, block %lu)", inode->i_ino,
++			       (unsigned long) block);
++		return ERR_PTR(err);
++	}
++	dirent = (struct ext4_dir_entry *) bh->b_data;
++	/* Determine whether or not we have an index block */
++	if (is_dx(inode)) {
++		if (block == 0)
++			is_dx_block = 1;
++		else if (ext4_rec_len_from_disk(dirent->rec_len,
++						inode->i_sb->s_blocksize) ==
++			 inode->i_sb->s_blocksize)
++			is_dx_block = 1;
++	}
++	if (!is_dx_block && type == INDEX) {
++		ext4_error_inode(inode, __func__, line, block,
++		       "directory leaf block found instead of index block");
++		return ERR_PTR(-EIO);
++	}
++	if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
++					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) ||
++	    buffer_verified(bh))
++		return bh;
++
++	/*
++	 * An empty leaf block can get mistaken for a index block; for
++	 * this reason, we can only check the index checksum when the
++	 * caller is sure it should be an index block.
++	 */
++	if (is_dx_block && type == INDEX) {
++		if (ext4_dx_csum_verify(inode, dirent))
++			set_buffer_verified(bh);
++		else {
++			ext4_error_inode(inode, __func__, line, block,
++				"Directory index failed checksum");
++			brelse(bh);
++			return ERR_PTR(-EIO);
++		}
++	}
++	if (!is_dx_block) {
++		if (ext4_dirent_csum_verify(inode, dirent))
++			set_buffer_verified(bh);
++		else {
++			ext4_error_inode(inode, __func__, line, block,
++				"Directory block failed checksum");
++			brelse(bh);
++			return ERR_PTR(-EIO);
++		}
++	}
++	return bh;
++}
++
+ #ifndef assert
+ #define assert(test) J_ASSERT(test)
+ #endif
+@@ -604,9 +684,9 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
+ 	u32 hash;
+ 
+ 	frame->bh = NULL;
+-	if (!(bh = ext4_bread(NULL, dir, 0, 0, err))) {
+-		if (*err == 0)
+-			*err = ERR_BAD_DX_DIR;
++	bh = ext4_read_dirblock(dir, 0, INDEX);
++	if (IS_ERR(bh)) {
++		*err = PTR_ERR(bh);
+ 		goto fail;
+ 	}
+ 	root = (struct dx_root *) bh->b_data;
+@@ -643,15 +723,6 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
+ 		goto fail;
+ 	}
+ 
+-	if (!buffer_verified(bh) &&
+-	    !ext4_dx_csum_verify(dir, (struct ext4_dir_entry *)bh->b_data)) {
+-		ext4_warning(dir->i_sb, "Root failed checksum");
+-		brelse(bh);
+-		*err = ERR_BAD_DX_DIR;
+-		goto fail;
+-	}
+-	set_buffer_verified(bh);
+-
+ 	entries = (struct dx_entry *) (((char *)&root->info) +
+ 				       root->info.info_length);
+ 
+@@ -709,23 +780,13 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
+ 		frame->entries = entries;
+ 		frame->at = at;
+ 		if (!indirect--) return frame;
+-		if (!(bh = ext4_bread(NULL, dir, dx_get_block(at), 0, err))) {
+-			if (!(*err))
+-				*err = ERR_BAD_DX_DIR;
++		bh = ext4_read_dirblock(dir, dx_get_block(at), INDEX);
++		if (IS_ERR(bh)) {
++			*err = PTR_ERR(bh);
+ 			goto fail2;
+ 		}
+ 		entries = ((struct dx_node *) bh->b_data)->entries;
+ 
+-		if (!buffer_verified(bh) &&
+-		    !ext4_dx_csum_verify(dir,
+-					 (struct ext4_dir_entry *)bh->b_data)) {
+-			ext4_warning(dir->i_sb, "Node failed checksum");
+-			brelse(bh);
+-			*err = ERR_BAD_DX_DIR;
+-			goto fail2;
+-		}
+-		set_buffer_verified(bh);
+-
+ 		if (dx_get_limit(entries) != dx_node_limit (dir)) {
+ 			ext4_warning(dir->i_sb,
+ 				     "dx entry: limit != node limit");
+@@ -783,7 +844,7 @@ static int ext4_htree_next_block(struct inode *dir, __u32 hash,
+ {
+ 	struct dx_frame *p;
+ 	struct buffer_head *bh;
+-	int err, num_frames = 0;
++	int num_frames = 0;
+ 	__u32 bhash;
+ 
+ 	p = frame;
+@@ -822,26 +883,9 @@ static int ext4_htree_next_block(struct inode *dir, __u32 hash,
+ 	 * block so no check is necessary
+ 	 */
+ 	while (num_frames--) {
+-		if (!(bh = ext4_bread(NULL, dir, dx_get_block(p->at),
+-				      0, &err))) {
+-			if (!err) {
+-				ext4_error(dir->i_sb,
+-					   "Directory hole detected on inode %lu\n",
+-					   dir->i_ino);
+-				return -EIO;
+-			}
+-			return err; /* Failure */
+-		}
+-
+-		if (!buffer_verified(bh) &&
+-		    !ext4_dx_csum_verify(dir,
+-					 (struct ext4_dir_entry *)bh->b_data)) {
+-			ext4_warning(dir->i_sb, "Node failed checksum");
+-			brelse(bh);
+-			return -EIO;
+-		}
+-		set_buffer_verified(bh);
+-
++		bh = ext4_read_dirblock(dir, dx_get_block(p->at), INDEX);
++		if (IS_ERR(bh))
++			return PTR_ERR(bh);
+ 		p++;
+ 		brelse(p->bh);
+ 		p->bh = bh;
+@@ -867,23 +911,9 @@ static int htree_dirblock_to_tree(struct file *dir_file,
+ 
+ 	dxtrace(printk(KERN_INFO "In htree dirblock_to_tree: block %lu\n",
+ 							(unsigned long)block));
+-	if (!(bh = ext4_bread(NULL, dir, block, 0, &err))) {
+-		if (!err) {
+-			err = -EIO;
+-			ext4_error(dir->i_sb,
+-				   "Directory hole detected on inode %lu\n",
+-				   dir->i_ino);
+-		}
+-		return err;
+-	}
+-
+-	if (!buffer_verified(bh) &&
+-			!ext4_dirent_csum_verify(dir,
+-				(struct ext4_dir_entry *)bh->b_data)) {
+-		brelse(bh);
+-		return -EIO;
+-	}
+-	set_buffer_verified(bh);
++	bh = ext4_read_dirblock(dir, block, DIRENT);
++	if (IS_ERR(bh))
++		return PTR_ERR(bh);
+ 
+ 	de = (struct ext4_dir_entry_2 *) bh->b_data;
+ 	top = (struct ext4_dir_entry_2 *) ((char *) de +
+@@ -1337,26 +1367,11 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q
+ 		return NULL;
+ 	do {
+ 		block = dx_get_block(frame->at);
+-		if (!(bh = ext4_bread(NULL, dir, block, 0, err))) {
+-			if (!(*err)) {
+-				*err = -EIO;
+-				ext4_error(dir->i_sb,
+-					   "Directory hole detected on inode %lu\n",
+-					   dir->i_ino);
+-			}
++		bh = ext4_read_dirblock(dir, block, DIRENT);
++		if (IS_ERR(bh)) {
++			*err = PTR_ERR(bh);
+ 			goto errout;
+ 		}
+-
+-		if (!buffer_verified(bh) &&
+-		    !ext4_dirent_csum_verify(dir,
+-				(struct ext4_dir_entry *)bh->b_data)) {
+-			EXT4_ERROR_INODE(dir, "checksumming directory "
+-					 "block %lu", (unsigned long)block);
+-			brelse(bh);
+-			*err = -EIO;
+-			goto errout;
+-		}
+-		set_buffer_verified(bh);
+ 		retval = search_dirblock(bh, dir, d_name,
+ 					 block << EXT4_BLOCK_SIZE_BITS(sb),
+ 					 res_dir);
+@@ -1920,22 +1935,10 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
+ 	}
+ 	blocks = dir->i_size >> sb->s_blocksize_bits;
+ 	for (block = 0; block < blocks; block++) {
+-		if (!(bh = ext4_bread(handle, dir, block, 0, &retval))) {
+-			if (!retval) {
+-				retval = -EIO;
+-				ext4_error(inode->i_sb,
+-					   "Directory hole detected on inode %lu\n",
+-					   inode->i_ino);
+-			}
+-			return retval;
+-		}
+-		if (!buffer_verified(bh) &&
+-		    !ext4_dirent_csum_verify(dir,
+-				(struct ext4_dir_entry *)bh->b_data)) {
+-			brelse(bh);
+-			return -EIO;
+-		}
+-		set_buffer_verified(bh);
++		bh = ext4_read_dirblock(dir, block, DIRENT);
++		if (IS_ERR(bh))
++			return PTR_ERR(bh);
++
+ 		retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh);
+ 		if (retval != -ENOSPC) {
+ 			brelse(bh);
+@@ -1986,22 +1989,13 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+ 		return err;
+ 	entries = frame->entries;
+ 	at = frame->at;
+-
+-	if (!(bh = ext4_bread(handle, dir, dx_get_block(frame->at), 0, &err))) {
+-		if (!err) {
+-			err = -EIO;
+-			ext4_error(dir->i_sb,
+-				   "Directory hole detected on inode %lu\n",
+-				   dir->i_ino);
+-		}
++	bh = ext4_read_dirblock(dir, dx_get_block(frame->at), DIRENT);
++	if (IS_ERR(bh)) {
++		err = PTR_ERR(bh);
++		bh = NULL;
+ 		goto cleanup;
+ 	}
+ 
+-	if (!buffer_verified(bh) &&
+-	    !ext4_dirent_csum_verify(dir, (struct ext4_dir_entry *)bh->b_data))
+-		goto journal_error;
+-	set_buffer_verified(bh);
+-
+ 	BUFFER_TRACE(bh, "get_write_access");
+ 	err = ext4_journal_get_write_access(handle, bh);
+ 	if (err)
+@@ -2352,6 +2346,7 @@ static int ext4_init_new_dir(handle_t *handle, struct inode *dir,
+ 	struct buffer_head *dir_block = NULL;
+ 	struct ext4_dir_entry_2 *de;
+ 	struct ext4_dir_entry_tail *t;
++	ext4_lblk_t block = 0;
+ 	unsigned int blocksize = dir->i_sb->s_blocksize;
+ 	int csum_size = 0;
+ 	int err;
+@@ -2368,16 +2363,9 @@ static int ext4_init_new_dir(handle_t *handle, struct inode *dir,
+ 			goto out;
+ 	}
+ 
+-	inode->i_size = EXT4_I(inode)->i_disksize = blocksize;
+-	if (!(dir_block = ext4_bread(handle, inode, 0, 1, &err))) {
+-		if (!err) {
+-			err = -EIO;
+-			ext4_error(inode->i_sb,
+-				   "Directory hole detected on inode %lu\n",
+-				   inode->i_ino);
+-		}
++	inode->i_size = 0;
++	if (!(dir_block = ext4_append(handle, inode, &block, &err)))
+ 		goto out;
+-	}
+ 	BUFFER_TRACE(dir_block, "get_write_access");
+ 	err = ext4_journal_get_write_access(handle, dir_block);
+ 	if (err)
+@@ -2477,26 +2465,14 @@ static int empty_dir(struct inode *inode)
+ 	}
+ 
+ 	sb = inode->i_sb;
+-	if (inode->i_size < EXT4_DIR_REC_LEN(1) + EXT4_DIR_REC_LEN(2) ||
+-	    !(bh = ext4_bread(NULL, inode, 0, 0, &err))) {
+-		if (err)
+-			EXT4_ERROR_INODE(inode,
+-				"error %d reading directory lblock 0", err);
+-		else
+-			ext4_warning(inode->i_sb,
+-				     "bad directory (dir #%lu) - no data block",
+-				     inode->i_ino);
++	if (inode->i_size < EXT4_DIR_REC_LEN(1) + EXT4_DIR_REC_LEN(2)) {
++		EXT4_ERROR_INODE(inode, "invalid size");
+ 		return 1;
+ 	}
+-	if (!buffer_verified(bh) &&
+-	    !ext4_dirent_csum_verify(inode,
+-			(struct ext4_dir_entry *)bh->b_data)) {
+-		EXT4_ERROR_INODE(inode, "checksum error reading directory "
+-				 "lblock 0");
+-		brelse(bh);
+-		return -EIO;
+-	}
+-	set_buffer_verified(bh);
++	bh = ext4_read_dirblock(inode, 0, EITHER);
++	if (IS_ERR(bh))
++		return 1;
++
+ 	de = (struct ext4_dir_entry_2 *) bh->b_data;
+ 	de1 = ext4_next_entry(de, sb->s_blocksize);
+ 	if (le32_to_cpu(de->inode) != inode->i_ino ||
+@@ -2519,29 +2495,9 @@ static int empty_dir(struct inode *inode)
+ 			err = 0;
+ 			brelse(bh);
+ 			lblock = offset >> EXT4_BLOCK_SIZE_BITS(sb);
+-			bh = ext4_bread(NULL, inode, lblock, 0, &err);
+-			if (!bh) {
+-				if (err)
+-					EXT4_ERROR_INODE(inode,
+-						"error %d reading directory "
+-						"lblock %u", err, lblock);
+-				else
+-					ext4_warning(inode->i_sb,
+-						"bad directory (dir #%lu) - no data block",
+-						inode->i_ino);
+-
+-				offset += sb->s_blocksize;
+-				continue;
+-			}
+-			if (!buffer_verified(bh) &&
+-			    !ext4_dirent_csum_verify(inode,
+-					(struct ext4_dir_entry *)bh->b_data)) {
+-				EXT4_ERROR_INODE(inode, "checksum error "
+-						 "reading directory lblock 0");
+-				brelse(bh);
+-				return -EIO;
+-			}
+-			set_buffer_verified(bh);
++			bh = ext4_read_dirblock(inode, lblock, EITHER);
++			if (IS_ERR(bh))
++				return 1;
+ 			de = (struct ext4_dir_entry_2 *) bh->b_data;
+ 		}
+ 		if (ext4_check_dir_entry(inode, NULL, de, bh,
+@@ -3004,13 +2960,9 @@ static struct buffer_head *ext4_get_first_dir_block(handle_t *handle,
+ 	struct buffer_head *bh;
+ 
+ 	if (!ext4_has_inline_data(inode)) {
+-		if (!(bh = ext4_bread(handle, inode, 0, 0, retval))) {
+-			if (!*retval) {
+-				*retval = -EIO;
+-				ext4_error(inode->i_sb,
+-					   "Directory hole detected on inode %lu\n",
+-					   inode->i_ino);
+-			}
++		bh = ext4_read_dirblock(inode, 0, EITHER);
++		if (IS_ERR(bh)) {
++			*retval = PTR_ERR(bh);
+ 			return NULL;
+ 		}
+ 		*parent_de = ext4_next_entry(
+@@ -3089,11 +3041,6 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 						  &inlined);
+ 		if (!dir_bh)
+ 			goto end_rename;
+-		if (!inlined && !buffer_verified(dir_bh) &&
+-		    !ext4_dirent_csum_verify(old_inode,
+-				(struct ext4_dir_entry *)dir_bh->b_data))
+-			goto end_rename;
+-		set_buffer_verified(dir_bh);
+ 		if (le32_to_cpu(parent_de->inode) != old_dir->i_ino)
+ 			goto end_rename;
+ 		retval = -EMLINK;

commit 01a523eb51cb505a4bc1eaffeeccd2527d6ab619
+Author: Theodore Ts'o 
+Date:   Thu Feb 14 15:51:58 2013 -0500
+
+    ext4: add debugging context for warning in ext4_da_update_reserve_space()
+    
+    Print some additional debugging context to hopefully help to debug a
+    warning which is getting triggered by xfstests #74.
+    
+    Also remove extraneous newlines from when printk's were converted to
+    ext4_warning() and ext4_msg().
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index b85d5dae726b..c4e9177f60c6 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -352,10 +352,12 @@ void ext4_da_update_reserve_space(struct inode *inode,
+ 	}
+ 
+ 	if (unlikely(ei->i_allocated_meta_blocks > ei->i_reserved_meta_blocks)) {
+-		ext4_warning(inode->i_sb, "%s: ino %lu, allocated %d "
+-			 "with only %d reserved metadata blocks\n", __func__,
+-			 inode->i_ino, ei->i_allocated_meta_blocks,
+-			 ei->i_reserved_meta_blocks);
++		ext4_warning(inode->i_sb, "ino %lu, allocated %d "
++			"with only %d reserved metadata blocks "
++			"(releasing %d blocks with reserved %d data blocks)",
++			inode->i_ino, ei->i_allocated_meta_blocks,
++			     ei->i_reserved_meta_blocks, used,
++			     ei->i_reserved_data_blocks);
+ 		WARN_ON(1);
+ 		ei->i_allocated_meta_blocks = ei->i_reserved_meta_blocks;
+ 	}
+@@ -1609,7 +1611,7 @@ static void mpage_da_map_and_submit(struct mpage_da_data *mpd)
+ 				 (unsigned long long) next,
+ 				 mpd->b_size >> mpd->inode->i_blkbits, err);
+ 			ext4_msg(sb, KERN_CRIT,
+-				"This should not happen!! Data will be lost\n");
++				"This should not happen!! Data will be lost");
+ 			if (err == -ENOSPC)
+ 				ext4_print_free_blocks(mpd->inode);
+ 		}

commit 8de5c325b4ee7d5b23b95edd28b81c9a2a9f427f
+Author: Theodore Ts'o 
+Date:   Thu Feb 14 15:11:41 2013 -0500
+
+    ext4: use KERN_WARNING for warning messages
+    
+    Some messages printed related to a WARN_ON(1) were printed using
+    KERN_NOTICE.  Use KERN_WARNING or ext4_warning() instead so that
+    context related to the WARN_ON() is printed at the same printk warning
+    level (and log files, etc.)
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 91d8fe3aced3..32fd2b9075dd 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -1028,17 +1028,17 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
+ 	inode = NULL;
+ bad_orphan:
+ 	ext4_warning(sb, "bad orphan inode %lu!  e2fsck was run?", ino);
+-	printk(KERN_NOTICE "ext4_test_bit(bit=%d, block=%llu) = %d\n",
++	printk(KERN_WARNING "ext4_test_bit(bit=%d, block=%llu) = %d\n",
+ 	       bit, (unsigned long long)bitmap_bh->b_blocknr,
+ 	       ext4_test_bit(bit, bitmap_bh->b_data));
+-	printk(KERN_NOTICE "inode=%p\n", inode);
++	printk(KERN_WARNING "inode=%p\n", inode);
+ 	if (inode) {
+-		printk(KERN_NOTICE "is_bad_inode(inode)=%d\n",
++		printk(KERN_WARNING "is_bad_inode(inode)=%d\n",
+ 		       is_bad_inode(inode));
+-		printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%u\n",
++		printk(KERN_WARNING "NEXT_ORPHAN(inode)=%u\n",
+ 		       NEXT_ORPHAN(inode));
+-		printk(KERN_NOTICE "max_ino=%lu\n", max_ino);
+-		printk(KERN_NOTICE "i_nlink=%u\n", inode->i_nlink);
++		printk(KERN_WARNING "max_ino=%lu\n", max_ino);
++		printk(KERN_WARNING "i_nlink=%u\n", inode->i_nlink);
+ 		/* Avoid freeing blocks if we got a bad deleted inode */
+ 		if (inode->i_nlink == 0)
+ 			inode->i_blocks = 0;
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 2fa18bb0bf3c..b85d5dae726b 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -343,7 +343,7 @@ void ext4_da_update_reserve_space(struct inode *inode,
+ 	spin_lock(&ei->i_block_reservation_lock);
+ 	trace_ext4_da_update_reserve_space(inode, used, quota_claim);
+ 	if (unlikely(used > ei->i_reserved_data_blocks)) {
+-		ext4_msg(inode->i_sb, KERN_NOTICE, "%s: ino %lu, used %d "
++		ext4_warning(inode->i_sb, "%s: ino %lu, used %d "
+ 			 "with only %d reserved data blocks",
+ 			 __func__, inode->i_ino, used,
+ 			 ei->i_reserved_data_blocks);
+@@ -352,7 +352,7 @@ void ext4_da_update_reserve_space(struct inode *inode,
+ 	}
+ 
+ 	if (unlikely(ei->i_allocated_meta_blocks > ei->i_reserved_meta_blocks)) {
+-		ext4_msg(inode->i_sb, KERN_NOTICE, "%s: ino %lu, allocated %d "
++		ext4_warning(inode->i_sb, "%s: ino %lu, allocated %d "
+ 			 "with only %d reserved metadata blocks\n", __func__,
+ 			 inode->i_ino, ei->i_allocated_meta_blocks,
+ 			 ei->i_reserved_meta_blocks);
+@@ -1263,7 +1263,7 @@ static void ext4_da_release_space(struct inode *inode, int to_free)
+ 		 * function is called from invalidate page, it's
+ 		 * harmless to return without any action.
+ 		 */
+-		ext4_msg(inode->i_sb, KERN_NOTICE, "ext4_da_release_space: "
++		ext4_warning(inode->i_sb, "ext4_da_release_space: "
+ 			 "ino %lu, to_free %d with only %d reserved "
+ 			 "data blocks", inode->i_ino, to_free,
+ 			 ei->i_reserved_data_blocks);

commit b6e96d0067d81f6a300bedee661b5ece8164e210
+Author: Theodore Ts'o 
+Date:   Sat Feb 9 16:29:20 2013 -0500
+
+    jbd2: use module parameters instead of debugfs for jbd_debug
+    
+    There are multiple reasons to move away from debugfs.  First of all,
+    we are only using it for a single parameter, and it is much more
+    complicated to set up (some 30 lines of code compared to 3), and one
+    more thing that might fail while loading the jbd2 module.
+    
+    Secondly, as a module paramter it can be specified as a boot option if
+    jbd2 is built into the kernel, or as a parameter when the module is
+    loaded, and it can also be manipulated dynamically under
+    /sys/module/jbd2/parameters/jbd2_debug.  So it is more flexible.
+    
+    Ultimately we want to move away from using jbd_debug() towards
+    tracepoints, but for now this is still a useful simplification of the
+    code base.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 4ba2e81e35ac..ed10991ab006 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -35,7 +35,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ #include 
+ #include 
+ #include 
+@@ -51,6 +50,14 @@
+ #include 
+ #include 
+ 
++#ifdef CONFIG_JBD2_DEBUG
++ushort jbd2_journal_enable_debug __read_mostly;
++EXPORT_SYMBOL(jbd2_journal_enable_debug);
++
++module_param_named(jbd2_debug, jbd2_journal_enable_debug, ushort, 0644);
++MODULE_PARM_DESC(jbd2_debug, "Debugging level for jbd2");
++#endif
++
+ EXPORT_SYMBOL(jbd2_journal_extend);
+ EXPORT_SYMBOL(jbd2_journal_stop);
+ EXPORT_SYMBOL(jbd2_journal_lock_updates);
+@@ -2495,45 +2502,6 @@ void jbd2_journal_release_jbd_inode(journal_t *journal,
+ 	spin_unlock(&journal->j_list_lock);
+ }
+ 
+-/*
+- * debugfs tunables
+- */
+-#ifdef CONFIG_JBD2_DEBUG
+-u8 jbd2_journal_enable_debug __read_mostly;
+-EXPORT_SYMBOL(jbd2_journal_enable_debug);
+-
+-#define JBD2_DEBUG_NAME "jbd2-debug"
+-
+-static struct dentry *jbd2_debugfs_dir;
+-static struct dentry *jbd2_debug;
+-
+-static void __init jbd2_create_debugfs_entry(void)
+-{
+-	jbd2_debugfs_dir = debugfs_create_dir("jbd2", NULL);
+-	if (jbd2_debugfs_dir)
+-		jbd2_debug = debugfs_create_u8(JBD2_DEBUG_NAME,
+-					       S_IRUGO | S_IWUSR,
+-					       jbd2_debugfs_dir,
+-					       &jbd2_journal_enable_debug);
+-}
+-
+-static void __exit jbd2_remove_debugfs_entry(void)
+-{
+-	debugfs_remove(jbd2_debug);
+-	debugfs_remove(jbd2_debugfs_dir);
+-}
+-
+-#else
+-
+-static void __init jbd2_create_debugfs_entry(void)
+-{
+-}
+-
+-static void __exit jbd2_remove_debugfs_entry(void)
+-{
+-}
+-
+-#endif
+ 
+ #ifdef CONFIG_PROC_FS
+ 
+@@ -2619,7 +2587,6 @@ static int __init journal_init(void)
+ 
+ 	ret = journal_init_caches();
+ 	if (ret == 0) {
+-		jbd2_create_debugfs_entry();
+ 		jbd2_create_jbd_stats_proc_entry();
+ 	} else {
+ 		jbd2_journal_destroy_caches();
+@@ -2634,7 +2601,6 @@ static void __exit journal_exit(void)
+ 	if (n)
+ 		printk(KERN_EMERG "JBD2: leaked %d journal_heads!\n", n);
+ #endif
+-	jbd2_remove_debugfs_entry();
+ 	jbd2_remove_jbd_stats_proc_entry();
+ 	jbd2_journal_destroy_caches();
+ }
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index fa5fea17b619..50e5a5e6a712 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -20,7 +20,6 @@
+ #ifndef __KERNEL__
+ #include "jfs_compat.h"
+ #define JBD2_DEBUG
+-#define jfs_debug jbd_debug
+ #else
+ 
+ #include 
+@@ -57,7 +56,7 @@
+  * CONFIG_JBD2_DEBUG is on.
+  */
+ #define JBD2_EXPENSIVE_CHECKING
+-extern u8 jbd2_journal_enable_debug;
++extern ushort jbd2_journal_enable_debug;
+ 
+ #define jbd_debug(n, f, a...)						\
+ 	do {								\

commit a0b30c12297eb63e9b994164f9c0937d29b9352d
+Author: Theodore Ts'o 
+Date:   Sat Feb 9 16:28:20 2013 -0500
+
+    ext4: use module parameters instead of debugfs for mballoc_debug
+    
+    There are multiple reasons to move away from debugfs.  First of all,
+    we are only using it for a single parameter, and it is much more
+    complicated to set up (some 30 lines of code compared to 3), and one
+    more thing that might fail while loading the ext4 module.
+    
+    Secondly, as a module paramter it can be specified as a boot option if
+    ext4 is built into the kernel, or as a parameter when the module is
+    loaded, and it can also be manipulated dynamically under
+    /sys/module/ext4/parameters/mballoc_debug.  So it is more flexible.
+    
+    Ultimately we want to move away from using mb_debug() towards
+    tracepoints, but for now this is still a useful simplification of the
+    code base.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index e350885aec30..6540ebe058e3 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -23,11 +23,18 @@
+ 
+ #include "ext4_jbd2.h"
+ #include "mballoc.h"
+-#include 
+ #include 
++#include 
+ #include 
+ #include 
+ 
++#ifdef CONFIG_EXT4_DEBUG
++ushort ext4_mballoc_debug __read_mostly;
++
++module_param_named(mballoc_debug, ext4_mballoc_debug, ushort, 0644);
++MODULE_PARM_DESC(mballoc_debug, "Debugging level for ext4's mballoc");
++#endif
++
+ /*
+  * MUSTDO:
+  *   - test ext4_ext_search_left() and ext4_ext_search_right()
+@@ -2660,40 +2667,6 @@ static void ext4_free_data_callback(struct super_block *sb,
+ 	mb_debug(1, "freed %u blocks in %u structures\n", count, count2);
+ }
+ 
+-#ifdef CONFIG_EXT4_DEBUG
+-u8 mb_enable_debug __read_mostly;
+-
+-static struct dentry *debugfs_dir;
+-static struct dentry *debugfs_debug;
+-
+-static void __init ext4_create_debugfs_entry(void)
+-{
+-	debugfs_dir = debugfs_create_dir("ext4", NULL);
+-	if (debugfs_dir)
+-		debugfs_debug = debugfs_create_u8("mballoc-debug",
+-						  S_IRUGO | S_IWUSR,
+-						  debugfs_dir,
+-						  &mb_enable_debug);
+-}
+-
+-static void ext4_remove_debugfs_entry(void)
+-{
+-	debugfs_remove(debugfs_debug);
+-	debugfs_remove(debugfs_dir);
+-}
+-
+-#else
+-
+-static void __init ext4_create_debugfs_entry(void)
+-{
+-}
+-
+-static void ext4_remove_debugfs_entry(void)
+-{
+-}
+-
+-#endif
+-
+ int __init ext4_init_mballoc(void)
+ {
+ 	ext4_pspace_cachep = KMEM_CACHE(ext4_prealloc_space,
+@@ -2715,7 +2688,6 @@ int __init ext4_init_mballoc(void)
+ 		kmem_cache_destroy(ext4_ac_cachep);
+ 		return -ENOMEM;
+ 	}
+-	ext4_create_debugfs_entry();
+ 	return 0;
+ }
+ 
+@@ -2730,7 +2702,6 @@ void ext4_exit_mballoc(void)
+ 	kmem_cache_destroy(ext4_ac_cachep);
+ 	kmem_cache_destroy(ext4_free_data_cachep);
+ 	ext4_groupinfo_destroy_slabs();
+-	ext4_remove_debugfs_entry();
+ }
+ 
+ 
+@@ -3876,7 +3847,7 @@ static void ext4_mb_show_ac(struct ext4_allocation_context *ac)
+ 	struct super_block *sb = ac->ac_sb;
+ 	ext4_group_t ngroups, i;
+ 
+-	if (!mb_enable_debug ||
++	if (!ext4_mballoc_debug ||
+ 	    (EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED))
+ 		return;
+ 
+diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
+index 3ccd889ba953..08481ee84cd5 100644
+--- a/fs/ext4/mballoc.h
++++ b/fs/ext4/mballoc.h
+@@ -37,11 +37,11 @@
+ /*
+  */
+ #ifdef CONFIG_EXT4_DEBUG
+-extern u8 mb_enable_debug;
++extern ushort ext4_mballoc_debug;
+ 
+ #define mb_debug(n, fmt, a...)	                                        \
+ 	do {								\
+-		if ((n) <= mb_enable_debug) {		        	\
++		if ((n) <= ext4_mballoc_debug) {		        \
+ 			printk(KERN_DEBUG "(%s, %d): %s: ",		\
+ 			       __FILE__, __LINE__, __func__);		\
+ 			printk(fmt, ## a);				\

commit 1139575a927010390c6b38e4215a6d741b056074
+Author: Theodore Ts'o 
+Date:   Sat Feb 9 16:27:09 2013 -0500
+
+    ext4: start handle at the last possible moment when creating inodes
+    
+    In ext4_{create,mknod,mkdir,symlink}(), don't start the journal handle
+    until the inode has been succesfully allocated.  In order to do this,
+    we need to start the handle in the ext4_new_inode().  So create a new
+    variant of this function, ext4_new_inode_start_handle(), so the handle
+    can be created at the last possible minute, before we need to modify
+    the inode allocation bitmap block.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 61ecf059f70c..fc1c0375c9f2 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2004,9 +2004,20 @@ extern int ext4fs_dirhash(const char *name, int len, struct
+ 			  dx_hash_info *hinfo);
+ 
+ /* ialloc.c */
+-extern struct inode *ext4_new_inode(handle_t *, struct inode *, umode_t,
+-				    const struct qstr *qstr, __u32 goal,
+-				    uid_t *owner);
++extern struct inode *__ext4_new_inode(handle_t *, struct inode *, umode_t,
++				      const struct qstr *qstr, __u32 goal,
++				      uid_t *owner, int handle_type,
++				      unsigned int line_no, int nblocks);
++
++#define ext4_new_inode(handle, dir, mode, qstr, goal, owner) \
++	__ext4_new_inode((handle), (dir), (mode), (qstr), (goal), (owner), \
++			 0, 0, 0)
++#define ext4_new_inode_start_handle(dir, mode, qstr, goal, owner, \
++				    type, nblocks)		    \
++	__ext4_new_inode(NULL, (dir), (mode), (qstr), (goal), (owner), \
++			 (type), __LINE__, (nblocks))
++
++
+ extern void ext4_free_inode(handle_t *, struct inode *);
+ extern struct inode * ext4_orphan_get(struct super_block *, unsigned long);
+ extern unsigned long ext4_count_free_inodes(struct super_block *);
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 10bd6fecc9ff..91d8fe3aced3 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -634,8 +634,10 @@ static int find_group_other(struct super_block *sb, struct inode *parent,
+  * For other inodes, search forward from the parent directory's block
+  * group to find a free inode.
+  */
+-struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode,
+-			     const struct qstr *qstr, __u32 goal, uid_t *owner)
++struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
++			       umode_t mode, const struct qstr *qstr,
++			       __u32 goal, uid_t *owner, int handle_type,
++			       unsigned int line_no, int nblocks)
+ {
+ 	struct super_block *sb;
+ 	struct buffer_head *inode_bitmap_bh = NULL;
+@@ -725,6 +727,15 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode,
+ 				   "inode=%lu", ino + 1);
+ 			continue;
+ 		}
++		if (!handle) {
++			BUG_ON(nblocks <= 0);
++			handle = __ext4_journal_start_sb(dir->i_sb, line_no,
++							 handle_type, nblocks);
++			if (IS_ERR(handle)) {
++				err = PTR_ERR(handle);
++				goto fail;
++			}
++		}
+ 		BUFFER_TRACE(inode_bitmap_bh, "get_write_access");
+ 		err = ext4_journal_get_write_access(handle, inode_bitmap_bh);
+ 		if (err)
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 5f3d2b569c63..3e1529c39808 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -2257,30 +2257,28 @@ static int ext4_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+ {
+ 	handle_t *handle;
+ 	struct inode *inode;
+-	int err, retries = 0;
++	int err, credits, retries = 0;
+ 
+ 	dquot_initialize(dir);
+ 
++	credits = (EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
++		   EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
++		   EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb));
+ retry:
+-	handle = ext4_journal_start(dir, EXT4_HT_DIR,
+-		(EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
+-		 EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
+-		 EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb)));
+-	if (IS_ERR(handle))
+-		return PTR_ERR(handle);
+-
+-	if (IS_DIRSYNC(dir))
+-		ext4_handle_sync(handle);
+-
+-	inode = ext4_new_inode(handle, dir, mode, &dentry->d_name, 0, NULL);
++	inode = ext4_new_inode_start_handle(dir, mode, &dentry->d_name, 0,
++					    NULL, EXT4_HT_DIR, credits);
++	handle = ext4_journal_current_handle();
+ 	err = PTR_ERR(inode);
+ 	if (!IS_ERR(inode)) {
+ 		inode->i_op = &ext4_file_inode_operations;
+ 		inode->i_fop = &ext4_file_operations;
+ 		ext4_set_aops(inode);
+ 		err = ext4_add_nondir(handle, dentry, inode);
++		if (!err && IS_DIRSYNC(dir))
++			ext4_handle_sync(handle);
+ 	}
+-	ext4_journal_stop(handle);
++	if (handle)
++		ext4_journal_stop(handle);
+ 	if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
+ 		goto retry;
+ 	return err;
+@@ -2291,32 +2289,30 @@ static int ext4_mknod(struct inode *dir, struct dentry *dentry,
+ {
+ 	handle_t *handle;
+ 	struct inode *inode;
+-	int err, retries = 0;
++	int err, credits, retries = 0;
+ 
+ 	if (!new_valid_dev(rdev))
+ 		return -EINVAL;
+ 
+ 	dquot_initialize(dir);
+ 
++	credits = (EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
++		   EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
++		   EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb));
+ retry:
+-	handle = ext4_journal_start(dir, EXT4_HT_DIR,
+-		(EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
+-		 EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
+-		 EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb)));
+-	if (IS_ERR(handle))
+-		return PTR_ERR(handle);
+-
+-	if (IS_DIRSYNC(dir))
+-		ext4_handle_sync(handle);
+-
+-	inode = ext4_new_inode(handle, dir, mode, &dentry->d_name, 0, NULL);
++	inode = ext4_new_inode_start_handle(dir, mode, &dentry->d_name, 0,
++					    NULL, EXT4_HT_DIR, credits);
++	handle = ext4_journal_current_handle();
+ 	err = PTR_ERR(inode);
+ 	if (!IS_ERR(inode)) {
+ 		init_special_inode(inode, inode->i_mode, rdev);
+ 		inode->i_op = &ext4_special_inode_operations;
+ 		err = ext4_add_nondir(handle, dentry, inode);
++		if (!err && IS_DIRSYNC(dir))
++			ext4_handle_sync(handle);
+ 	}
+-	ext4_journal_stop(handle);
++	if (handle)
++		ext4_journal_stop(handle);
+ 	if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
+ 		goto retry;
+ 	return err;
+@@ -2408,26 +2404,21 @@ static int ext4_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+ {
+ 	handle_t *handle;
+ 	struct inode *inode;
+-	int err, retries = 0;
++	int err, credits, retries = 0;
+ 
+ 	if (EXT4_DIR_LINK_MAX(dir))
+ 		return -EMLINK;
+ 
+ 	dquot_initialize(dir);
+ 
++	credits = (EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
++		   EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
++		   EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb));
+ retry:
+-	handle = ext4_journal_start(dir, EXT4_HT_DIR,
+-		(EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
+-		 EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
+-		 EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb)));
+-	if (IS_ERR(handle))
+-		return PTR_ERR(handle);
+-
+-	if (IS_DIRSYNC(dir))
+-		ext4_handle_sync(handle);
+-
+-	inode = ext4_new_inode(handle, dir, S_IFDIR | mode,
+-			       &dentry->d_name, 0, NULL);
++	inode = ext4_new_inode_start_handle(dir, S_IFDIR | mode,
++					    &dentry->d_name,
++					    0, NULL, EXT4_HT_DIR, credits);
++	handle = ext4_journal_current_handle();
+ 	err = PTR_ERR(inode);
+ 	if (IS_ERR(inode))
+ 		goto out_stop;
+@@ -2455,8 +2446,12 @@ static int ext4_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+ 		goto out_clear_inode;
+ 	unlock_new_inode(inode);
+ 	d_instantiate(dentry, inode);
++	if (IS_DIRSYNC(dir))
++		ext4_handle_sync(handle);
++
+ out_stop:
+-	ext4_journal_stop(handle);
++	if (handle)
++		ext4_journal_stop(handle);
+ 	if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
+ 		goto retry;
+ 	return err;
+@@ -2883,15 +2878,10 @@ static int ext4_symlink(struct inode *dir,
+ 			  EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb);
+ 	}
+ retry:
+-	handle = ext4_journal_start(dir, EXT4_HT_DIR, credits);
+-	if (IS_ERR(handle))
+-		return PTR_ERR(handle);
+-
+-	if (IS_DIRSYNC(dir))
+-		ext4_handle_sync(handle);
+-
+-	inode = ext4_new_inode(handle, dir, S_IFLNK|S_IRWXUGO,
+-			       &dentry->d_name, 0, NULL);
++	inode = ext4_new_inode_start_handle(dir, S_IFLNK|S_IRWXUGO,
++					    &dentry->d_name, 0, NULL,
++					    EXT4_HT_DIR, credits);
++	handle = ext4_journal_current_handle();
+ 	err = PTR_ERR(inode);
+ 	if (IS_ERR(inode))
+ 		goto out_stop;
+@@ -2944,8 +2934,12 @@ static int ext4_symlink(struct inode *dir,
+ 	}
+ 	EXT4_I(inode)->i_disksize = inode->i_size;
+ 	err = ext4_add_nondir(handle, dentry, inode);
++	if (!err && IS_DIRSYNC(dir))
++		ext4_handle_sync(handle);
++
+ out_stop:
+-	ext4_journal_stop(handle);
++	if (handle)
++		ext4_journal_stop(handle);
+ 	if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
+ 		goto retry;
+ 	return err;

commit 95eaefbdececae5e781d76d03fe7472a857c8c7a
+Author: Theodore Ts'o 
+Date:   Sat Feb 9 15:23:03 2013 -0500
+
+    ext4: fix the number of credits needed for acl ops with inline data
+    
+    Operations which modify extended attributes may need extra journal
+    credits if inline data is used, since there is a chance that some
+    extended attributes may need to get pushed to an external attribute
+    block.
+    
+    Changes to reflect this was made in xattr.c, but they were missed in
+    fs/ext4/acl.c.  To fix this, abstract the calculation of the number of
+    credits needed for xattr operations to an inline function defined in
+    ext4_jbd2.h, and use it in acl.c and xattr.c.
+    
+    Also move the function declarations used in inline.c from xattr.h
+    (where they are non-obviously hidden, and caused problems since
+    ext4_jbd2.h needs to use the function ext4_has_inline_data), and move
+    them to ext4.h.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Tao Ma 
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
+index 406cf8bb12d5..39a54a0e9fe4 100644
+--- a/fs/ext4/acl.c
++++ b/fs/ext4/acl.c
+@@ -325,7 +325,7 @@ ext4_acl_chmod(struct inode *inode)
+ 		return error;
+ retry:
+ 	handle = ext4_journal_start(inode, EXT4_HT_XATTR,
+-			EXT4_DATA_TRANS_BLOCKS(inode->i_sb));
++				    ext4_jbd2_credits_xattr(inode));
+ 	if (IS_ERR(handle)) {
+ 		error = PTR_ERR(handle);
+ 		ext4_std_error(inode->i_sb, error);
+@@ -423,7 +423,7 @@ ext4_xattr_set_acl(struct dentry *dentry, const char *name, const void *value,
+ 
+ retry:
+ 	handle = ext4_journal_start(inode, EXT4_HT_XATTR,
+-				    EXT4_DATA_TRANS_BLOCKS(inode->i_sb));
++				    ext4_jbd2_credits_xattr(inode));
+ 	if (IS_ERR(handle)) {
+ 		error = PTR_ERR(handle);
+ 		goto release_and_out;
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index a5ae87c51401..61ecf059f70c 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2456,6 +2456,75 @@ extern const struct file_operations ext4_file_operations;
+ extern loff_t ext4_llseek(struct file *file, loff_t offset, int origin);
+ extern void ext4_unwritten_wait(struct inode *inode);
+ 
++/* inline.c */
++extern int ext4_has_inline_data(struct inode *inode);
++extern int ext4_get_inline_size(struct inode *inode);
++extern int ext4_get_max_inline_size(struct inode *inode);
++extern int ext4_find_inline_data_nolock(struct inode *inode);
++extern void ext4_write_inline_data(struct inode *inode,
++				   struct ext4_iloc *iloc,
++				   void *buffer, loff_t pos,
++				   unsigned int len);
++extern int ext4_prepare_inline_data(handle_t *handle, struct inode *inode,
++				    unsigned int len);
++extern int ext4_init_inline_data(handle_t *handle, struct inode *inode,
++				 unsigned int len);
++extern int ext4_destroy_inline_data(handle_t *handle, struct inode *inode);
++
++extern int ext4_readpage_inline(struct inode *inode, struct page *page);
++extern int ext4_try_to_write_inline_data(struct address_space *mapping,
++					 struct inode *inode,
++					 loff_t pos, unsigned len,
++					 unsigned flags,
++					 struct page **pagep);
++extern int ext4_write_inline_data_end(struct inode *inode,
++				      loff_t pos, unsigned len,
++				      unsigned copied,
++				      struct page *page);
++extern struct buffer_head *
++ext4_journalled_write_inline_data(struct inode *inode,
++				  unsigned len,
++				  struct page *page);
++extern int ext4_da_write_inline_data_begin(struct address_space *mapping,
++					   struct inode *inode,
++					   loff_t pos, unsigned len,
++					   unsigned flags,
++					   struct page **pagep,
++					   void **fsdata);
++extern int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos,
++					 unsigned len, unsigned copied,
++					 struct page *page);
++extern int ext4_try_add_inline_entry(handle_t *handle, struct dentry *dentry,
++				     struct inode *inode);
++extern int ext4_try_create_inline_dir(handle_t *handle,
++				      struct inode *parent,
++				      struct inode *inode);
++extern int ext4_read_inline_dir(struct file *filp,
++				void *dirent, filldir_t filldir,
++				int *has_inline_data);
++extern struct buffer_head *ext4_find_inline_entry(struct inode *dir,
++					const struct qstr *d_name,
++					struct ext4_dir_entry_2 **res_dir,
++					int *has_inline_data);
++extern int ext4_delete_inline_entry(handle_t *handle,
++				    struct inode *dir,
++				    struct ext4_dir_entry_2 *de_del,
++				    struct buffer_head *bh,
++				    int *has_inline_data);
++extern int empty_inline_dir(struct inode *dir, int *has_inline_data);
++extern struct buffer_head *ext4_get_first_inline_block(struct inode *inode,
++					struct ext4_dir_entry_2 **parent_de,
++					int *retval);
++extern int ext4_inline_data_fiemap(struct inode *inode,
++				   struct fiemap_extent_info *fieinfo,
++				   int *has_inline);
++extern int ext4_try_to_evict_inline_data(handle_t *handle,
++					 struct inode *inode,
++					 int needed);
++extern void ext4_inline_data_truncate(struct inode *inode, int *has_inline);
++
++extern int ext4_convert_inline_data(struct inode *inode);
++
+ /* namei.c */
+ extern const struct inode_operations ext4_dir_inode_operations;
+ extern const struct inode_operations ext4_special_inode_operations;
+diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
+index c1fc2dca14ae..4c216b1bf20c 100644
+--- a/fs/ext4/ext4_jbd2.h
++++ b/fs/ext4/ext4_jbd2.h
+@@ -104,6 +104,20 @@
+ #define EXT4_MAXQUOTAS_INIT_BLOCKS(sb) (MAXQUOTAS*EXT4_QUOTA_INIT_BLOCKS(sb))
+ #define EXT4_MAXQUOTAS_DEL_BLOCKS(sb) (MAXQUOTAS*EXT4_QUOTA_DEL_BLOCKS(sb))
+ 
++static inline int ext4_jbd2_credits_xattr(struct inode *inode)
++{
++	int credits = EXT4_DATA_TRANS_BLOCKS(inode->i_sb);
++
++	/*
++	 * In case of inline data, we may push out the data to a block,
++	 * so we need to reserve credits for this eventuality
++	 */
++	if (ext4_has_inline_data(inode))
++		credits += ext4_writepage_trans_blocks(inode) + 1;
++	return credits;
++}
++
++
+ /*
+  * Ext4 handle operation types -- for logging purposes
+  */
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 2efc5600b03b..cc31da027596 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -1165,16 +1165,9 @@ ext4_xattr_set(struct inode *inode, int name_index, const char *name,
+ {
+ 	handle_t *handle;
+ 	int error, retries = 0;
+-	int credits = EXT4_DATA_TRANS_BLOCKS(inode->i_sb);
++	int credits = ext4_jbd2_credits_xattr(inode);
+ 
+ retry:
+-	/*
+-	 * In case of inline data, we may push out the data to a block,
+-	 * So reserve the journal space first.
+-	 */
+-	if (ext4_has_inline_data(inode))
+-		credits += ext4_writepage_trans_blocks(inode) + 1;
+-
+ 	handle = ext4_journal_start(inode, EXT4_HT_XATTR, credits);
+ 	if (IS_ERR(handle)) {
+ 		error = PTR_ERR(handle);
+diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
+index 69eda787a96a..aa25deb5c6cd 100644
+--- a/fs/ext4/xattr.h
++++ b/fs/ext4/xattr.h
+@@ -125,74 +125,6 @@ extern int ext4_xattr_ibody_inline_set(handle_t *handle, struct inode *inode,
+ 				       struct ext4_xattr_info *i,
+ 				       struct ext4_xattr_ibody_find *is);
+ 
+-extern int ext4_has_inline_data(struct inode *inode);
+-extern int ext4_get_inline_size(struct inode *inode);
+-extern int ext4_get_max_inline_size(struct inode *inode);
+-extern int ext4_find_inline_data_nolock(struct inode *inode);
+-extern void ext4_write_inline_data(struct inode *inode,
+-				   struct ext4_iloc *iloc,
+-				   void *buffer, loff_t pos,
+-				   unsigned int len);
+-extern int ext4_prepare_inline_data(handle_t *handle, struct inode *inode,
+-				    unsigned int len);
+-extern int ext4_init_inline_data(handle_t *handle, struct inode *inode,
+-				 unsigned int len);
+-extern int ext4_destroy_inline_data(handle_t *handle, struct inode *inode);
+-
+-extern int ext4_readpage_inline(struct inode *inode, struct page *page);
+-extern int ext4_try_to_write_inline_data(struct address_space *mapping,
+-					 struct inode *inode,
+-					 loff_t pos, unsigned len,
+-					 unsigned flags,
+-					 struct page **pagep);
+-extern int ext4_write_inline_data_end(struct inode *inode,
+-				      loff_t pos, unsigned len,
+-				      unsigned copied,
+-				      struct page *page);
+-extern struct buffer_head *
+-ext4_journalled_write_inline_data(struct inode *inode,
+-				  unsigned len,
+-				  struct page *page);
+-extern int ext4_da_write_inline_data_begin(struct address_space *mapping,
+-					   struct inode *inode,
+-					   loff_t pos, unsigned len,
+-					   unsigned flags,
+-					   struct page **pagep,
+-					   void **fsdata);
+-extern int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos,
+-					 unsigned len, unsigned copied,
+-					 struct page *page);
+-extern int ext4_try_add_inline_entry(handle_t *handle, struct dentry *dentry,
+-				     struct inode *inode);
+-extern int ext4_try_create_inline_dir(handle_t *handle,
+-				      struct inode *parent,
+-				      struct inode *inode);
+-extern int ext4_read_inline_dir(struct file *filp,
+-				void *dirent, filldir_t filldir,
+-				int *has_inline_data);
+-extern struct buffer_head *ext4_find_inline_entry(struct inode *dir,
+-					const struct qstr *d_name,
+-					struct ext4_dir_entry_2 **res_dir,
+-					int *has_inline_data);
+-extern int ext4_delete_inline_entry(handle_t *handle,
+-				    struct inode *dir,
+-				    struct ext4_dir_entry_2 *de_del,
+-				    struct buffer_head *bh,
+-				    int *has_inline_data);
+-extern int empty_inline_dir(struct inode *dir, int *has_inline_data);
+-extern struct buffer_head *ext4_get_first_inline_block(struct inode *inode,
+-					struct ext4_dir_entry_2 **parent_de,
+-					int *retval);
+-extern int ext4_inline_data_fiemap(struct inode *inode,
+-				   struct fiemap_extent_info *fieinfo,
+-				   int *has_inline);
+-extern int ext4_try_to_evict_inline_data(handle_t *handle,
+-					 struct inode *inode,
+-					 int needed);
+-extern void ext4_inline_data_truncate(struct inode *inode, int *has_inline);
+-
+-extern int ext4_convert_inline_data(struct inode *inode);
+-
+ #ifdef CONFIG_EXT4_FS_SECURITY
+ extern int ext4_init_security(handle_t *handle, struct inode *inode,
+ 			      struct inode *dir, const struct qstr *qstr);

commit 64044abf05d0842a7fed30e102fa411a744c7d9f
+Author: Theodore Ts'o 
+Date:   Sat Feb 9 15:06:24 2013 -0500
+
+    ext4: fix the number of credits needed for ext4_unlink() and ext4_rmdir()
+    
+    The ext4_unlink() and ext4_rmdir() don't actually release the blocks
+    associated with the file/directory.  This gets done in a separate jbd2
+    handle called via ext4_evict_inode().  Thus, we don't need to reserve
+    lots of journal credits for the truncate.
+    
+    Note that using too many journal credits is non-optimal because it can
+    leading to the journal transmit getting closed too early, before it is
+    strictly necessary.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
+index 302814b85945..c1fc2dca14ae 100644
+--- a/fs/ext4/ext4_jbd2.h
++++ b/fs/ext4/ext4_jbd2.h
+@@ -59,12 +59,6 @@
+ #define EXT4_META_TRANS_BLOCKS(sb)	(EXT4_XATTR_TRANS_BLOCKS + \
+ 					EXT4_MAXQUOTAS_TRANS_BLOCKS(sb))
+ 
+-/* Delete operations potentially hit one directory's namespace plus an
+- * entire inode, plus arbitrary amounts of bitmap/indirection data.  Be
+- * generous.  We can grow the delete transaction later if necessary. */
+-
+-#define EXT4_DELETE_TRANS_BLOCKS(sb)	(2 * EXT4_DATA_TRANS_BLOCKS(sb) + 64)
+-
+ /* Define an arbitrary limit for the amount of data we will anticipate
+  * writing to any given transaction.  For unbounded transactions such as
+  * write(2) and truncate(2) we can write more than this, but we always
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 36a4afd12f39..5f3d2b569c63 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -2748,7 +2748,7 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
+ 		goto end_rmdir;
+ 
+ 	handle = ext4_journal_start(dir, EXT4_HT_DIR,
+-				    EXT4_DELETE_TRANS_BLOCKS(dir->i_sb));
++				    EXT4_DATA_TRANS_BLOCKS(dir->i_sb));
+ 	if (IS_ERR(handle)) {
+ 		retval = PTR_ERR(handle);
+ 		handle = NULL;
+@@ -2811,7 +2811,7 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
+ 		goto end_unlink;
+ 
+ 	handle = ext4_journal_start(dir, EXT4_HT_DIR,
+-				    EXT4_DELETE_TRANS_BLOCKS(dir->i_sb));
++				    EXT4_DATA_TRANS_BLOCKS(dir->i_sb));
+ 	if (IS_ERR(handle)) {
+ 		retval = PTR_ERR(handle);
+ 		handle = NULL;

commit 4b217630d0ec277c961e57f6d2985433b352c2ce
+Author: Theodore Ts'o 
+Date:   Sat Feb 9 12:50:27 2013 -0500
+
+    ext4: fix the number of credits needed for ext4_ext_migrate()
+    
+    The migration ioctl creates a temporary inode.  Since this inode is
+    never linked to a directory, we don't need to reserve journal credits
+    required for modifying the directory.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
+index 4e4fcfd342f8..480acf4a085f 100644
+--- a/fs/ext4/migrate.c
++++ b/fs/ext4/migrate.c
+@@ -456,11 +456,14 @@ int ext4_ext_migrate(struct inode *inode)
+ 		 */
+ 		return retval;
+ 
++	/*
++	 * Worst case we can touch the allocation bitmaps, a bgd
++	 * block, and a block to link in the orphan list.  We do need
++	 * need to worry about credits for modifying the quota inode.
++	 */
+ 	handle = ext4_journal_start(inode, EXT4_HT_MIGRATE,
+-					EXT4_DATA_TRANS_BLOCKS(inode->i_sb) +
+-					EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
+-					EXT4_MAXQUOTAS_INIT_BLOCKS(inode->i_sb)
+-					+ 1);
++		4 + EXT4_MAXQUOTAS_TRANS_BLOCKS(inode->i_sb));
++
+ 	if (IS_ERR(handle)) {
+ 		retval = PTR_ERR(handle);
+ 		return retval;

commit 8dcfaad244cdfa245cc2b4ddf42cea5fd8b80ece
+Author: Theodore Ts'o 
+Date:   Sat Feb 9 09:45:11 2013 -0500
+
+    ext4: start handle at the last possible moment in ext4_rmdir()
+    
+    Don't start the jbd2 transaction handle until after the directory
+    entry has been found, to minimize the amount of time that a handle is
+    held active.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 4a27069d54ad..36a4afd12f39 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -2725,26 +2725,18 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
+ 	struct inode *inode;
+ 	struct buffer_head *bh;
+ 	struct ext4_dir_entry_2 *de;
+-	handle_t *handle;
++	handle_t *handle = NULL;
+ 
+ 	/* Initialize quotas before so that eventual writes go in
+ 	 * separate transaction */
+ 	dquot_initialize(dir);
+ 	dquot_initialize(dentry->d_inode);
+ 
+-	handle = ext4_journal_start(dir, EXT4_HT_DIR,
+-				    EXT4_DELETE_TRANS_BLOCKS(dir->i_sb));
+-	if (IS_ERR(handle))
+-		return PTR_ERR(handle);
+-
+ 	retval = -ENOENT;
+ 	bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL);
+ 	if (!bh)
+ 		goto end_rmdir;
+ 
+-	if (IS_DIRSYNC(dir))
+-		ext4_handle_sync(handle);
+-
+ 	inode = dentry->d_inode;
+ 
+ 	retval = -EIO;
+@@ -2755,6 +2747,17 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
+ 	if (!empty_dir(inode))
+ 		goto end_rmdir;
+ 
++	handle = ext4_journal_start(dir, EXT4_HT_DIR,
++				    EXT4_DELETE_TRANS_BLOCKS(dir->i_sb));
++	if (IS_ERR(handle)) {
++		retval = PTR_ERR(handle);
++		handle = NULL;
++		goto end_rmdir;
++	}
++
++	if (IS_DIRSYNC(dir))
++		ext4_handle_sync(handle);
++
+ 	retval = ext4_delete_entry(handle, dir, de, bh);
+ 	if (retval)
+ 		goto end_rmdir;
+@@ -2776,8 +2779,9 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
+ 	ext4_mark_inode_dirty(handle, dir);
+ 
+ end_rmdir:
+-	ext4_journal_stop(handle);
+ 	brelse(bh);
++	if (handle)
++		ext4_journal_stop(handle);
+ 	return retval;
+ }
+ 

commit 931b68649d31b6b52608110f34856f8eb77adb36
+Author: Theodore Ts'o 
+Date:   Sat Feb 9 09:43:39 2013 -0500
+
+    ext4: start handle at the last possible moment in ext4_unlink()
+    
+    Don't start the jbd2 transaction handle until after the directory
+    entry has been found, to minimize the amount of time that a handle is
+    held active.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 51841032ca03..4a27069d54ad 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -2787,7 +2787,7 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
+ 	struct inode *inode;
+ 	struct buffer_head *bh;
+ 	struct ext4_dir_entry_2 *de;
+-	handle_t *handle;
++	handle_t *handle = NULL;
+ 
+ 	trace_ext4_unlink_enter(dir, dentry);
+ 	/* Initialize quotas before so that eventual writes go
+@@ -2795,14 +2795,6 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
+ 	dquot_initialize(dir);
+ 	dquot_initialize(dentry->d_inode);
+ 
+-	handle = ext4_journal_start(dir, EXT4_HT_DIR,
+-				    EXT4_DELETE_TRANS_BLOCKS(dir->i_sb));
+-	if (IS_ERR(handle))
+-		return PTR_ERR(handle);
+-
+-	if (IS_DIRSYNC(dir))
+-		ext4_handle_sync(handle);
+-
+ 	retval = -ENOENT;
+ 	bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL);
+ 	if (!bh)
+@@ -2814,6 +2806,17 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
+ 	if (le32_to_cpu(de->inode) != inode->i_ino)
+ 		goto end_unlink;
+ 
++	handle = ext4_journal_start(dir, EXT4_HT_DIR,
++				    EXT4_DELETE_TRANS_BLOCKS(dir->i_sb));
++	if (IS_ERR(handle)) {
++		retval = PTR_ERR(handle);
++		handle = NULL;
++		goto end_unlink;
++	}
++
++	if (IS_DIRSYNC(dir))
++		ext4_handle_sync(handle);
++
+ 	if (!inode->i_nlink) {
+ 		ext4_warning(inode->i_sb,
+ 			     "Deleting nonexistent file (%lu), %d",
+@@ -2834,8 +2837,9 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
+ 	retval = 0;
+ 
+ end_unlink:
+-	ext4_journal_stop(handle);
+ 	brelse(bh);
++	if (handle)
++		ext4_journal_stop(handle);
+ 	trace_ext4_unlink_exit(dentry, retval);
+ 	return retval;
+ }

commit 47564bfb95bf370d73906fc4ae57c271e8ba96cd
+Author: Theodore Ts'o 
+Date:   Sat Feb 9 09:24:14 2013 -0500
+
+    ext4: grab page before starting transaction handle in write_begin()
+    
+    The grab_cache_page_write_begin() function can potentially sleep for a
+    long time, since it may need to do memory allocation which can block
+    if the system is under significant memory pressure, and because it may
+    be blocked on page writeback.  If it does take a long time to grab the
+    page, it's better that we not hold an active jbd2 handle.
+    
+    So grab a handle on the page first, and _then_ start the transaction
+    handle.
+    
+    This commit fixes the following long transaction handle hold time:
+    
+    postmark-2917  [000] ....   196.435786: jbd2_handle_stats: dev 254,32
+       tid 570 type 2 line_no 2541 interval 311 sync 0 requested_blocks 1
+       dirtied_blocks 0
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 5042c8773ad7..2fa18bb0bf3c 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -875,32 +875,40 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
+ 		ret = ext4_try_to_write_inline_data(mapping, inode, pos, len,
+ 						    flags, pagep);
+ 		if (ret < 0)
+-			goto out;
+-		if (ret == 1) {
+-			ret = 0;
+-			goto out;
+-		}
++			return ret;
++		if (ret == 1)
++			return 0;
+ 	}
+ 
+-retry:
++	/*
++	 * grab_cache_page_write_begin() can take a long time if the
++	 * system is thrashing due to memory pressure, or if the page
++	 * is being written back.  So grab it first before we start
++	 * the transaction handle.  This also allows us to allocate
++	 * the page (if needed) without using GFP_NOFS.
++	 */
++retry_grab:
++	page = grab_cache_page_write_begin(mapping, index, flags);
++	if (!page)
++		return -ENOMEM;
++	unlock_page(page);
++
++retry_journal:
+ 	handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, needed_blocks);
+ 	if (IS_ERR(handle)) {
+-		ret = PTR_ERR(handle);
+-		goto out;
++		page_cache_release(page);
++		return PTR_ERR(handle);
+ 	}
+ 
+-	/* We cannot recurse into the filesystem as the transaction is already
+-	 * started */
+-	flags |= AOP_FLAG_NOFS;
+-
+-	page = grab_cache_page_write_begin(mapping, index, flags);
+-	if (!page) {
++	lock_page(page);
++	if (page->mapping != mapping) {
++		/* The page got truncated from under us */
++		unlock_page(page);
++		page_cache_release(page);
+ 		ext4_journal_stop(handle);
+-		ret = -ENOMEM;
+-		goto out;
++		goto retry_grab;
+ 	}
+-
+-	*pagep = page;
++	wait_on_page_writeback(page);
+ 
+ 	if (ext4_should_dioread_nolock(inode))
+ 		ret = __block_write_begin(page, pos, len, ext4_get_block_write);
+@@ -915,7 +923,6 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
+ 
+ 	if (ret) {
+ 		unlock_page(page);
+-		page_cache_release(page);
+ 		/*
+ 		 * __block_write_begin may have instantiated a few blocks
+ 		 * outside i_size.  Trim these off again. Don't need
+@@ -939,11 +946,14 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
+ 			if (inode->i_nlink)
+ 				ext4_orphan_del(NULL, inode);
+ 		}
+-	}
+ 
+-	if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
+-		goto retry;
+-out:
++		if (ret == -ENOSPC &&
++		    ext4_should_retry_alloc(inode->i_sb, &retries))
++			goto retry_journal;
++		page_cache_release(page);
++		return ret;
++	}
++	*pagep = page;
+ 	return ret;
+ }
+ 
+@@ -2458,42 +2468,52 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
+ 						      pos, len, flags,
+ 						      pagep, fsdata);
+ 		if (ret < 0)
+-			goto out;
+-		if (ret == 1) {
+-			ret = 0;
+-			goto out;
+-		}
++			return ret;
++		if (ret == 1)
++			return 0;
+ 	}
+ 
+-retry:
++	/*
++	 * grab_cache_page_write_begin() can take a long time if the
++	 * system is thrashing due to memory pressure, or if the page
++	 * is being written back.  So grab it first before we start
++	 * the transaction handle.  This also allows us to allocate
++	 * the page (if needed) without using GFP_NOFS.
++	 */
++retry_grab:
++	page = grab_cache_page_write_begin(mapping, index, flags);
++	if (!page)
++		return -ENOMEM;
++	unlock_page(page);
++
+ 	/*
+ 	 * With delayed allocation, we don't log the i_disksize update
+ 	 * if there is delayed block allocation. But we still need
+ 	 * to journalling the i_disksize update if writes to the end
+ 	 * of file which has an already mapped buffer.
+ 	 */
++retry_journal:
+ 	handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, 1);
+ 	if (IS_ERR(handle)) {
+-		ret = PTR_ERR(handle);
+-		goto out;
++		page_cache_release(page);
++		return PTR_ERR(handle);
+ 	}
+-	/* We cannot recurse into the filesystem as the transaction is already
+-	 * started */
+-	flags |= AOP_FLAG_NOFS;
+ 
+-	page = grab_cache_page_write_begin(mapping, index, flags);
+-	if (!page) {
++	lock_page(page);
++	if (page->mapping != mapping) {
++		/* The page got truncated from under us */
++		unlock_page(page);
++		page_cache_release(page);
+ 		ext4_journal_stop(handle);
+-		ret = -ENOMEM;
+-		goto out;
++		goto retry_grab;
+ 	}
+-	*pagep = page;
++	/* In case writeback began while the page was unlocked */
++	wait_on_page_writeback(page);
+ 
+ 	ret = __block_write_begin(page, pos, len, ext4_da_get_block_prep);
+ 	if (ret < 0) {
+ 		unlock_page(page);
+ 		ext4_journal_stop(handle);
+-		page_cache_release(page);
+ 		/*
+ 		 * block_write_begin may have instantiated a few blocks
+ 		 * outside i_size.  Trim these off again. Don't need
+@@ -2501,11 +2521,16 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
+ 		 */
+ 		if (pos + len > inode->i_size)
+ 			ext4_truncate_failed_write(inode);
++
++		if (ret == -ENOSPC &&
++		    ext4_should_retry_alloc(inode->i_sb, &retries))
++			goto retry_journal;
++
++		page_cache_release(page);
++		return ret;
+ 	}
+ 
+-	if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
+-		goto retry;
+-out:
++	*pagep = page;
+ 	return ret;
+ }
+ 

commit 9924a92a8c217576bd2a2b1bbbb854462f1a00ae
+Author: Theodore Ts'o 
+Date:   Fri Feb 8 21:59:22 2013 -0500
+
+    ext4: pass context information to jbd2__journal_start()
+    
+    So we can better understand what bits of ext4 are responsible for
+    long-running jbd2 handles, use jbd2__journal_start() so we can pass
+    context information for logging purposes.
+    
+    The recommended way for finding the longer-running handles is:
+    
+       T=/sys/kernel/debug/tracing
+       EVENT=$T/events/jbd2/jbd2_handle_stats
+       echo "interval > 5" > $EVENT/filter
+       echo 1 > $EVENT/enable
+    
+       ./run-my-fs-benchmark
+    
+       cat $T/trace > /tmp/problem-handles
+    
+    This will list handles that were active for longer than 20ms.  Having
+    longer-running handles is bad, because a commit started at the wrong
+    time could stall for those 20+ milliseconds, which could delay an
+    fsync() or an O_SYNC operation.  Here is an example line from the
+    trace file describing a handle which lived on for 311 jiffies, or over
+    1.2 seconds:
+    
+    postmark-2917  [000] ....   196.435786: jbd2_handle_stats: dev 254,32
+       tid 570 type 2 line_no 2541 interval 311 sync 0 requested_blocks 1
+       dirtied_blocks 0
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
+index e6e0d988439b..406cf8bb12d5 100644
+--- a/fs/ext4/acl.c
++++ b/fs/ext4/acl.c
+@@ -324,7 +324,7 @@ ext4_acl_chmod(struct inode *inode)
+ 	if (error)
+ 		return error;
+ retry:
+-	handle = ext4_journal_start(inode,
++	handle = ext4_journal_start(inode, EXT4_HT_XATTR,
+ 			EXT4_DATA_TRANS_BLOCKS(inode->i_sb));
+ 	if (IS_ERR(handle)) {
+ 		error = PTR_ERR(handle);
+@@ -422,7 +422,8 @@ ext4_xattr_set_acl(struct dentry *dentry, const char *name, const void *value,
+ 		acl = NULL;
+ 
+ retry:
+-	handle = ext4_journal_start(inode, EXT4_DATA_TRANS_BLOCKS(inode->i_sb));
++	handle = ext4_journal_start(inode, EXT4_HT_XATTR,
++				    EXT4_DATA_TRANS_BLOCKS(inode->i_sb));
+ 	if (IS_ERR(handle)) {
+ 		error = PTR_ERR(handle);
+ 		goto release_and_out;
+diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
+index 6f6114525535..7058975e3a55 100644
+--- a/fs/ext4/ext4_jbd2.c
++++ b/fs/ext4/ext4_jbd2.c
+@@ -38,7 +38,8 @@ static void ext4_put_nojournal(handle_t *handle)
+ /*
+  * Wrappers for jbd2_journal_start/end.
+  */
+-handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks)
++handle_t *__ext4_journal_start_sb(struct super_block *sb, unsigned int line,
++				  int type, int nblocks)
+ {
+ 	journal_t *journal;
+ 
+@@ -59,7 +60,7 @@ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks)
+ 		ext4_abort(sb, "Detected aborted journal");
+ 		return ERR_PTR(-EROFS);
+ 	}
+-	return jbd2_journal_start(journal, nblocks);
++	return jbd2__journal_start(journal, nblocks, GFP_NOFS, type, line);
+ }
+ 
+ int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle)
+diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
+index 7177f9b21cb2..302814b85945 100644
+--- a/fs/ext4/ext4_jbd2.h
++++ b/fs/ext4/ext4_jbd2.h
+@@ -110,6 +110,22 @@
+ #define EXT4_MAXQUOTAS_INIT_BLOCKS(sb) (MAXQUOTAS*EXT4_QUOTA_INIT_BLOCKS(sb))
+ #define EXT4_MAXQUOTAS_DEL_BLOCKS(sb) (MAXQUOTAS*EXT4_QUOTA_DEL_BLOCKS(sb))
+ 
++/*
++ * Ext4 handle operation types -- for logging purposes
++ */
++#define EXT4_HT_MISC             0
++#define EXT4_HT_INODE            1
++#define EXT4_HT_WRITE_PAGE       2
++#define EXT4_HT_MAP_BLOCKS       3
++#define EXT4_HT_DIR              4
++#define EXT4_HT_TRUNCATE         5
++#define EXT4_HT_QUOTA            6
++#define EXT4_HT_RESIZE           7
++#define EXT4_HT_MIGRATE          8
++#define EXT4_HT_MOVE_EXTENTS     9
++#define EXT4_HT_XATTR           10
++#define EXT4_HT_MAX             11
++
+ /**
+  *   struct ext4_journal_cb_entry - Base structure for callback information.
+  *
+@@ -234,7 +250,8 @@ int __ext4_handle_dirty_super(const char *where, unsigned int line,
+ #define ext4_handle_dirty_super(handle, sb) \
+ 	__ext4_handle_dirty_super(__func__, __LINE__, (handle), (sb))
+ 
+-handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks);
++handle_t *__ext4_journal_start_sb(struct super_block *sb, unsigned int line,
++				  int type, int nblocks);
+ int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle);
+ 
+ #define EXT4_NOJOURNAL_MAX_REF_COUNT ((unsigned long) 4096)
+@@ -268,9 +285,17 @@ static inline int ext4_handle_has_enough_credits(handle_t *handle, int needed)
+ 	return 1;
+ }
+ 
+-static inline handle_t *ext4_journal_start(struct inode *inode, int nblocks)
++#define ext4_journal_start_sb(sb, type, nblocks)			\
++	__ext4_journal_start_sb((sb), __LINE__, (type), (nblocks))
++
++#define ext4_journal_start(inode, type, nblocks)			\
++	__ext4_journal_start((inode), __LINE__, (type), (nblocks))
++
++static inline handle_t *__ext4_journal_start(struct inode *inode,
++					     unsigned int line, int type,
++					     int nblocks)
+ {
+-	return ext4_journal_start_sb(inode->i_sb, nblocks);
++	return __ext4_journal_start_sb(inode->i_sb, line, type, nblocks);
+ }
+ 
+ #define ext4_journal_stop(handle) \
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index db55c62e1f01..b6b54d658dc2 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -2656,7 +2656,7 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
+ 	ext_debug("truncate since %u to %u\n", start, end);
+ 
+ 	/* probably first extent we're gonna free will be last in block */
+-	handle = ext4_journal_start(inode, depth + 1);
++	handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, depth + 1);
+ 	if (IS_ERR(handle))
+ 		return PTR_ERR(handle);
+ 
+@@ -4287,7 +4287,7 @@ void ext4_ext_truncate(struct inode *inode)
+ 	 * probably first extent we're gonna free will be last in block
+ 	 */
+ 	err = ext4_writepage_trans_blocks(inode);
+-	handle = ext4_journal_start(inode, err);
++	handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, err);
+ 	if (IS_ERR(handle))
+ 		return;
+ 
+@@ -4454,7 +4454,8 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
+ 	while (ret >= 0 && ret < max_blocks) {
+ 		map.m_lblk = map.m_lblk + ret;
+ 		map.m_len = max_blocks = max_blocks - ret;
+-		handle = ext4_journal_start(inode, credits);
++		handle = ext4_journal_start(inode, EXT4_HT_MAP_BLOCKS,
++					    credits);
+ 		if (IS_ERR(handle)) {
+ 			ret = PTR_ERR(handle);
+ 			break;
+@@ -4532,7 +4533,7 @@ int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset,
+ 	while (ret >= 0 && ret < max_blocks) {
+ 		map.m_lblk += ret;
+ 		map.m_len = (max_blocks -= ret);
+-		handle = ext4_journal_start(inode, credits);
++		handle = ext4_journal_start(inode, EXT4_HT_MAP_BLOCKS, credits);
+ 		if (IS_ERR(handle)) {
+ 			ret = PTR_ERR(handle);
+ 			break;
+@@ -4710,7 +4711,7 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length)
+ 	inode_dio_wait(inode);
+ 
+ 	credits = ext4_writepage_trans_blocks(inode);
+-	handle = ext4_journal_start(inode, credits);
++	handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits);
+ 	if (IS_ERR(handle)) {
+ 		err = PTR_ERR(handle);
+ 		goto out_dio;
+diff --git a/fs/ext4/file.c b/fs/ext4/file.c
+index 405565a62277..2cf8ab810687 100644
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -240,7 +240,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
+ 			handle_t *handle;
+ 			int err;
+ 
+-			handle = ext4_journal_start_sb(sb, 1);
++			handle = ext4_journal_start_sb(sb, EXT4_HT_MISC, 1);
+ 			if (IS_ERR(handle))
+ 				return PTR_ERR(handle);
+ 			err = ext4_journal_get_write_access(handle, sbi->s_sbh);
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 3f32c8012447..10bd6fecc9ff 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -1137,7 +1137,7 @@ int ext4_init_inode_table(struct super_block *sb, ext4_group_t group,
+ 	if (gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED))
+ 		goto out;
+ 
+-	handle = ext4_journal_start_sb(sb, 1);
++	handle = ext4_journal_start_sb(sb, EXT4_HT_MISC, 1);
+ 	if (IS_ERR(handle)) {
+ 		ret = PTR_ERR(handle);
+ 		goto out;
+diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
+index 193281098fb6..c541ab8b64dd 100644
+--- a/fs/ext4/indirect.c
++++ b/fs/ext4/indirect.c
+@@ -791,7 +791,7 @@ ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb,
+ 
+ 		if (final_size > inode->i_size) {
+ 			/* Credits for sb + inode write */
+-			handle = ext4_journal_start(inode, 2);
++			handle = ext4_journal_start(inode, EXT4_HT_INODE, 2);
+ 			if (IS_ERR(handle)) {
+ 				ret = PTR_ERR(handle);
+ 				goto out;
+@@ -851,7 +851,7 @@ ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb,
+ 		int err;
+ 
+ 		/* Credits for sb + inode write */
+-		handle = ext4_journal_start(inode, 2);
++		handle = ext4_journal_start(inode, EXT4_HT_INODE, 2);
+ 		if (IS_ERR(handle)) {
+ 			/* This is really bad luck. We've written the data
+ 			 * but cannot extend i_size. Bail out and pretend
+@@ -950,7 +950,8 @@ static handle_t *start_transaction(struct inode *inode)
+ {
+ 	handle_t *result;
+ 
+-	result = ext4_journal_start(inode, ext4_blocks_for_truncate(inode));
++	result = ext4_journal_start(inode, EXT4_HT_TRUNCATE,
++				    ext4_blocks_for_truncate(inode));
+ 	if (!IS_ERR(result))
+ 		return result;
+ 
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index 93a3408fc89b..bc5f871f0893 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -545,7 +545,7 @@ static int ext4_convert_inline_data_to_extent(struct address_space *mapping,
+ 		return ret;
+ 
+ retry:
+-	handle = ext4_journal_start(inode, needed_blocks);
++	handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, needed_blocks);
+ 	if (IS_ERR(handle)) {
+ 		ret = PTR_ERR(handle);
+ 		handle = NULL;
+@@ -657,7 +657,7 @@ int ext4_try_to_write_inline_data(struct address_space *mapping,
+ 	 * The possible write could happen in the inode,
+ 	 * so try to reserve the space in inode first.
+ 	 */
+-	handle = ext4_journal_start(inode, 1);
++	handle = ext4_journal_start(inode, EXT4_HT_INODE, 1);
+ 	if (IS_ERR(handle)) {
+ 		ret = PTR_ERR(handle);
+ 		handle = NULL;
+@@ -853,7 +853,7 @@ int ext4_da_write_inline_data_begin(struct address_space *mapping,
+ 	if (ret)
+ 		return ret;
+ 
+-	handle = ext4_journal_start(inode, 1);
++	handle = ext4_journal_start(inode, EXT4_HT_INODE, 1);
+ 	if (IS_ERR(handle)) {
+ 		ret = PTR_ERR(handle);
+ 		handle = NULL;
+@@ -1770,7 +1770,7 @@ void ext4_inline_data_truncate(struct inode *inode, int *has_inline)
+ 
+ 
+ 	needed_blocks = ext4_writepage_trans_blocks(inode);
+-	handle = ext4_journal_start(inode, needed_blocks);
++	handle = ext4_journal_start(inode, EXT4_HT_INODE, needed_blocks);
+ 	if (IS_ERR(handle))
+ 		return;
+ 
+@@ -1862,7 +1862,7 @@ int ext4_convert_inline_data(struct inode *inode)
+ 	if (error)
+ 		return error;
+ 
+-	handle = ext4_journal_start(inode, needed_blocks);
++	handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, needed_blocks);
+ 	if (IS_ERR(handle)) {
+ 		error = PTR_ERR(handle);
+ 		goto out_free;
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 07d9defeaf8c..5042c8773ad7 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -234,7 +234,8 @@ void ext4_evict_inode(struct inode *inode)
+ 	 * protection against it
+ 	 */
+ 	sb_start_intwrite(inode->i_sb);
+-	handle = ext4_journal_start(inode, ext4_blocks_for_truncate(inode)+3);
++	handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE,
++				    ext4_blocks_for_truncate(inode)+3);
+ 	if (IS_ERR(handle)) {
+ 		ext4_std_error(inode->i_sb, PTR_ERR(handle));
+ 		/*
+@@ -656,7 +657,8 @@ static int _ext4_get_block(struct inode *inode, sector_t iblock,
+ 		if (map.m_len > DIO_MAX_BLOCKS)
+ 			map.m_len = DIO_MAX_BLOCKS;
+ 		dio_credits = ext4_chunk_trans_blocks(inode, map.m_len);
+-		handle = ext4_journal_start(inode, dio_credits);
++		handle = ext4_journal_start(inode, EXT4_HT_MAP_BLOCKS,
++					    dio_credits);
+ 		if (IS_ERR(handle)) {
+ 			ret = PTR_ERR(handle);
+ 			return ret;
+@@ -881,7 +883,7 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
+ 	}
+ 
+ retry:
+-	handle = ext4_journal_start(inode, needed_blocks);
++	handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, needed_blocks);
+ 	if (IS_ERR(handle)) {
+ 		ret = PTR_ERR(handle);
+ 		goto out;
+@@ -1881,7 +1883,8 @@ static int __ext4_journalled_writepage(struct page *page,
+ 	 * references to buffers so we are safe */
+ 	unlock_page(page);
+ 
+-	handle = ext4_journal_start(inode, ext4_writepage_trans_blocks(inode));
++	handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE,
++				    ext4_writepage_trans_blocks(inode));
+ 	if (IS_ERR(handle)) {
+ 		ret = PTR_ERR(handle);
+ 		goto out;
+@@ -2312,7 +2315,8 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 		needed_blocks = ext4_da_writepages_trans_blocks(inode);
+ 
+ 		/* start a new transaction*/
+-		handle = ext4_journal_start(inode, needed_blocks);
++		handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE,
++					    needed_blocks);
+ 		if (IS_ERR(handle)) {
+ 			ret = PTR_ERR(handle);
+ 			ext4_msg(inode->i_sb, KERN_CRIT, "%s: jbd2_start: "
+@@ -2468,7 +2472,7 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
+ 	 * to journalling the i_disksize update if writes to the end
+ 	 * of file which has an already mapped buffer.
+ 	 */
+-	handle = ext4_journal_start(inode, 1);
++	handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, 1);
+ 	if (IS_ERR(handle)) {
+ 		ret = PTR_ERR(handle);
+ 		goto out;
+@@ -4215,8 +4219,9 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
+ 
+ 		/* (user+group)*(old+new) structure, inode write (sb,
+ 		 * inode block, ? - but truncate inode update has it) */
+-		handle = ext4_journal_start(inode, (EXT4_MAXQUOTAS_INIT_BLOCKS(inode->i_sb)+
+-					EXT4_MAXQUOTAS_DEL_BLOCKS(inode->i_sb))+3);
++		handle = ext4_journal_start(inode, EXT4_HT_QUOTA,
++			(EXT4_MAXQUOTAS_INIT_BLOCKS(inode->i_sb) +
++			 EXT4_MAXQUOTAS_DEL_BLOCKS(inode->i_sb)) + 3);
+ 		if (IS_ERR(handle)) {
+ 			error = PTR_ERR(handle);
+ 			goto err_out;
+@@ -4251,7 +4256,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
+ 	    (attr->ia_size < inode->i_size)) {
+ 		handle_t *handle;
+ 
+-		handle = ext4_journal_start(inode, 3);
++		handle = ext4_journal_start(inode, EXT4_HT_INODE, 3);
+ 		if (IS_ERR(handle)) {
+ 			error = PTR_ERR(handle);
+ 			goto err_out;
+@@ -4271,7 +4276,8 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
+ 							    attr->ia_size);
+ 			if (error) {
+ 				/* Do as much error cleanup as possible */
+-				handle = ext4_journal_start(inode, 3);
++				handle = ext4_journal_start(inode,
++							    EXT4_HT_INODE, 3);
+ 				if (IS_ERR(handle)) {
+ 					ext4_orphan_del(NULL, inode);
+ 					goto err_out;
+@@ -4612,7 +4618,7 @@ void ext4_dirty_inode(struct inode *inode, int flags)
+ {
+ 	handle_t *handle;
+ 
+-	handle = ext4_journal_start(inode, 2);
++	handle = ext4_journal_start(inode, EXT4_HT_INODE, 2);
+ 	if (IS_ERR(handle))
+ 		goto out;
+ 
+@@ -4713,7 +4719,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val)
+ 
+ 	/* Finally we can mark the inode as dirty. */
+ 
+-	handle = ext4_journal_start(inode, 1);
++	handle = ext4_journal_start(inode, EXT4_HT_INODE, 1);
+ 	if (IS_ERR(handle))
+ 		return PTR_ERR(handle);
+ 
+@@ -4791,7 +4797,8 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
+ 	else
+ 		get_block = ext4_get_block;
+ retry_alloc:
+-	handle = ext4_journal_start(inode, ext4_writepage_trans_blocks(inode));
++	handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE,
++				    ext4_writepage_trans_blocks(inode));
+ 	if (IS_ERR(handle)) {
+ 		ret = VM_FAULT_SIGBUS;
+ 		goto out;
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index 4784ac244fc6..31f4f56a32d6 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -104,7 +104,7 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 		} else if (oldflags & EXT4_EOFBLOCKS_FL)
+ 			ext4_truncate(inode);
+ 
+-		handle = ext4_journal_start(inode, 1);
++		handle = ext4_journal_start(inode, EXT4_HT_INODE, 1);
+ 		if (IS_ERR(handle)) {
+ 			err = PTR_ERR(handle);
+ 			goto flags_out;
+@@ -173,7 +173,7 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 		}
+ 
+ 		mutex_lock(&inode->i_mutex);
+-		handle = ext4_journal_start(inode, 1);
++		handle = ext4_journal_start(inode, EXT4_HT_INODE, 1);
+ 		if (IS_ERR(handle)) {
+ 			err = PTR_ERR(handle);
+ 			goto unlock_out;
+diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
+index db8226d595fa..4e4fcfd342f8 100644
+--- a/fs/ext4/migrate.c
++++ b/fs/ext4/migrate.c
+@@ -456,7 +456,7 @@ int ext4_ext_migrate(struct inode *inode)
+ 		 */
+ 		return retval;
+ 
+-	handle = ext4_journal_start(inode,
++	handle = ext4_journal_start(inode, EXT4_HT_MIGRATE,
+ 					EXT4_DATA_TRANS_BLOCKS(inode->i_sb) +
+ 					EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
+ 					EXT4_MAXQUOTAS_INIT_BLOCKS(inode->i_sb)
+@@ -507,7 +507,7 @@ int ext4_ext_migrate(struct inode *inode)
+ 	ext4_set_inode_state(inode, EXT4_STATE_EXT_MIGRATE);
+ 	up_read((&EXT4_I(inode)->i_data_sem));
+ 
+-	handle = ext4_journal_start(inode, 1);
++	handle = ext4_journal_start(inode, EXT4_HT_MIGRATE, 1);
+ 	if (IS_ERR(handle)) {
+ 		/*
+ 		 * It is impossible to update on-disk structures without
+diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
+index e4cdb5188f34..0d6734394eac 100644
+--- a/fs/ext4/move_extent.c
++++ b/fs/ext4/move_extent.c
+@@ -923,7 +923,7 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode,
+ again:
+ 	*err = 0;
+ 	jblocks = ext4_writepage_trans_blocks(orig_inode) * 2;
+-	handle = ext4_journal_start(orig_inode, jblocks);
++	handle = ext4_journal_start(orig_inode, EXT4_HT_MOVE_EXTENTS, jblocks);
+ 	if (IS_ERR(handle)) {
+ 		*err = PTR_ERR(handle);
+ 		return 0;
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 34ed624d2c56..51841032ca03 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -2262,9 +2262,10 @@ static int ext4_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+ 	dquot_initialize(dir);
+ 
+ retry:
+-	handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
+-					EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
+-					EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb));
++	handle = ext4_journal_start(dir, EXT4_HT_DIR,
++		(EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
++		 EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
++		 EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb)));
+ 	if (IS_ERR(handle))
+ 		return PTR_ERR(handle);
+ 
+@@ -2298,9 +2299,10 @@ static int ext4_mknod(struct inode *dir, struct dentry *dentry,
+ 	dquot_initialize(dir);
+ 
+ retry:
+-	handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
+-					EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
+-					EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb));
++	handle = ext4_journal_start(dir, EXT4_HT_DIR,
++		(EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
++		 EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
++		 EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb)));
+ 	if (IS_ERR(handle))
+ 		return PTR_ERR(handle);
+ 
+@@ -2414,9 +2416,10 @@ static int ext4_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+ 	dquot_initialize(dir);
+ 
+ retry:
+-	handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
+-					EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
+-					EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb));
++	handle = ext4_journal_start(dir, EXT4_HT_DIR,
++		(EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
++		 EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
++		 EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb)));
+ 	if (IS_ERR(handle))
+ 		return PTR_ERR(handle);
+ 
+@@ -2729,7 +2732,8 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
+ 	dquot_initialize(dir);
+ 	dquot_initialize(dentry->d_inode);
+ 
+-	handle = ext4_journal_start(dir, EXT4_DELETE_TRANS_BLOCKS(dir->i_sb));
++	handle = ext4_journal_start(dir, EXT4_HT_DIR,
++				    EXT4_DELETE_TRANS_BLOCKS(dir->i_sb));
+ 	if (IS_ERR(handle))
+ 		return PTR_ERR(handle);
+ 
+@@ -2791,7 +2795,8 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
+ 	dquot_initialize(dir);
+ 	dquot_initialize(dentry->d_inode);
+ 
+-	handle = ext4_journal_start(dir, EXT4_DELETE_TRANS_BLOCKS(dir->i_sb));
++	handle = ext4_journal_start(dir, EXT4_HT_DIR,
++				    EXT4_DELETE_TRANS_BLOCKS(dir->i_sb));
+ 	if (IS_ERR(handle))
+ 		return PTR_ERR(handle);
+ 
+@@ -2870,7 +2875,7 @@ static int ext4_symlink(struct inode *dir,
+ 			  EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb);
+ 	}
+ retry:
+-	handle = ext4_journal_start(dir, credits);
++	handle = ext4_journal_start(dir, EXT4_HT_DIR, credits);
+ 	if (IS_ERR(handle))
+ 		return PTR_ERR(handle);
+ 
+@@ -2908,7 +2913,7 @@ static int ext4_symlink(struct inode *dir,
+ 		 * Now inode is being linked into dir (EXT4_DATA_TRANS_BLOCKS
+ 		 * + EXT4_INDEX_EXTRA_TRANS_BLOCKS), inode is also modified
+ 		 */
+-		handle = ext4_journal_start(dir,
++		handle = ext4_journal_start(dir, EXT4_HT_DIR,
+ 				EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
+ 				EXT4_INDEX_EXTRA_TRANS_BLOCKS + 1);
+ 		if (IS_ERR(handle)) {
+@@ -2955,8 +2960,9 @@ static int ext4_link(struct dentry *old_dentry,
+ 	dquot_initialize(dir);
+ 
+ retry:
+-	handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
+-					EXT4_INDEX_EXTRA_TRANS_BLOCKS);
++	handle = ext4_journal_start(dir, EXT4_HT_DIR,
++		(EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
++		 EXT4_INDEX_EXTRA_TRANS_BLOCKS));
+ 	if (IS_ERR(handle))
+ 		return PTR_ERR(handle);
+ 
+@@ -3039,9 +3045,9 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 	 * in separate transaction */
+ 	if (new_dentry->d_inode)
+ 		dquot_initialize(new_dentry->d_inode);
+-	handle = ext4_journal_start(old_dir, 2 *
+-					EXT4_DATA_TRANS_BLOCKS(old_dir->i_sb) +
+-					EXT4_INDEX_EXTRA_TRANS_BLOCKS + 2);
++	handle = ext4_journal_start(old_dir, EXT4_HT_DIR,
++		(2 * EXT4_DATA_TRANS_BLOCKS(old_dir->i_sb) +
++		 EXT4_INDEX_EXTRA_TRANS_BLOCKS + 2));
+ 	if (IS_ERR(handle))
+ 		return PTR_ERR(handle);
+ 
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 8eefb636beb8..c7f4d7584669 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -466,7 +466,7 @@ static int setup_new_flex_group_blocks(struct super_block *sb,
+ 	meta_bg = EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG);
+ 
+ 	/* This transaction may be extended/restarted along the way */
+-	handle = ext4_journal_start_sb(sb, EXT4_MAX_TRANS_DATA);
++	handle = ext4_journal_start_sb(sb, EXT4_HT_RESIZE, EXT4_MAX_TRANS_DATA);
+ 	if (IS_ERR(handle))
+ 		return PTR_ERR(handle);
+ 
+@@ -1031,7 +1031,7 @@ static void update_backups(struct super_block *sb, int blk_off, char *data,
+ 	handle_t *handle;
+ 	int err = 0, err2;
+ 
+-	handle = ext4_journal_start_sb(sb, EXT4_MAX_TRANS_DATA);
++	handle = ext4_journal_start_sb(sb, EXT4_HT_RESIZE, EXT4_MAX_TRANS_DATA);
+ 	if (IS_ERR(handle)) {
+ 		group = 1;
+ 		err = PTR_ERR(handle);
+@@ -1412,7 +1412,7 @@ static int ext4_flex_group_add(struct super_block *sb,
+ 	 * modify each of the reserved GDT dindirect blocks.
+ 	 */
+ 	credit = flex_gd->count * 4 + reserved_gdb;
+-	handle = ext4_journal_start_sb(sb, credit);
++	handle = ext4_journal_start_sb(sb, EXT4_HT_RESIZE, credit);
+ 	if (IS_ERR(handle)) {
+ 		err = PTR_ERR(handle);
+ 		goto exit;
+@@ -1624,7 +1624,7 @@ static int ext4_group_extend_no_check(struct super_block *sb,
+ 	/* We will update the superblock, one block bitmap, and
+ 	 * one group descriptor via ext4_group_add_blocks().
+ 	 */
+-	handle = ext4_journal_start_sb(sb, 3);
++	handle = ext4_journal_start_sb(sb, EXT4_HT_RESIZE, 3);
+ 	if (IS_ERR(handle)) {
+ 		err = PTR_ERR(handle);
+ 		ext4_warning(sb, "error %d on journal start", err);
+@@ -1788,7 +1788,7 @@ static int ext4_convert_meta_bg(struct super_block *sb, struct inode *inode)
+ 		credits += 3;	/* block bitmap, bg descriptor, resize inode */
+ 	}
+ 
+-	handle = ext4_journal_start_sb(sb, credits);
++	handle = ext4_journal_start_sb(sb, EXT4_HT_RESIZE, credits);
+ 	if (IS_ERR(handle))
+ 		return PTR_ERR(handle);
+ 
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index cb9d67fbc8f0..ef6ac59e4961 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4762,7 +4762,7 @@ static int ext4_write_dquot(struct dquot *dquot)
+ 	struct inode *inode;
+ 
+ 	inode = dquot_to_inode(dquot);
+-	handle = ext4_journal_start(inode,
++	handle = ext4_journal_start(inode, EXT4_HT_QUOTA,
+ 				    EXT4_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
+ 	if (IS_ERR(handle))
+ 		return PTR_ERR(handle);
+@@ -4778,7 +4778,7 @@ static int ext4_acquire_dquot(struct dquot *dquot)
+ 	int ret, err;
+ 	handle_t *handle;
+ 
+-	handle = ext4_journal_start(dquot_to_inode(dquot),
++	handle = ext4_journal_start(dquot_to_inode(dquot), EXT4_HT_QUOTA,
+ 				    EXT4_QUOTA_INIT_BLOCKS(dquot->dq_sb));
+ 	if (IS_ERR(handle))
+ 		return PTR_ERR(handle);
+@@ -4794,7 +4794,7 @@ static int ext4_release_dquot(struct dquot *dquot)
+ 	int ret, err;
+ 	handle_t *handle;
+ 
+-	handle = ext4_journal_start(dquot_to_inode(dquot),
++	handle = ext4_journal_start(dquot_to_inode(dquot), EXT4_HT_QUOTA,
+ 				    EXT4_QUOTA_DEL_BLOCKS(dquot->dq_sb));
+ 	if (IS_ERR(handle)) {
+ 		/* Release dquot anyway to avoid endless cycle in dqput() */
+@@ -4826,7 +4826,7 @@ static int ext4_write_info(struct super_block *sb, int type)
+ 	handle_t *handle;
+ 
+ 	/* Data block + inode block */
+-	handle = ext4_journal_start(sb->s_root->d_inode, 2);
++	handle = ext4_journal_start(sb->s_root->d_inode, EXT4_HT_QUOTA, 2);
+ 	if (IS_ERR(handle))
+ 		return PTR_ERR(handle);
+ 	ret = dquot_commit_info(sb, type);
+@@ -4972,7 +4972,7 @@ static int ext4_quota_off(struct super_block *sb, int type)
+ 
+ 	/* Update modification times of quota files when userspace can
+ 	 * start looking at them */
+-	handle = ext4_journal_start(inode, 1);
++	handle = ext4_journal_start(inode, EXT4_HT_QUOTA, 1);
+ 	if (IS_ERR(handle))
+ 		goto out;
+ 	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index c68990c392c7..2efc5600b03b 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -1175,7 +1175,7 @@ ext4_xattr_set(struct inode *inode, int name_index, const char *name,
+ 	if (ext4_has_inline_data(inode))
+ 		credits += ext4_writepage_trans_blocks(inode) + 1;
+ 
+-	handle = ext4_journal_start(inode, credits);
++	handle = ext4_journal_start(inode, EXT4_HT_XATTR, credits);
+ 	if (IS_ERR(handle)) {
+ 		error = PTR_ERR(handle);
+ 	} else {

commit 722887ddc8982ff40e40b650fbca9ae1e56259bc
+Author: Theodore Ts'o 
+Date:   Fri Feb 8 13:00:31 2013 -0500
+
+    ext4: move the jbd2 wrapper functions out of super.c
+    
+    Move the jbd2 wrapper functions which start and stop handles out of
+    super.c, where they don't really logically belong, and into
+    ext4_jbd2.c.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index d93393eb5f2d..a5ae87c51401 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2149,6 +2149,8 @@ extern void *ext4_kvzalloc(size_t size, gfp_t flags);
+ extern void ext4_kvfree(void *ptr);
+ extern int ext4_alloc_flex_bg_array(struct super_block *sb,
+ 				    ext4_group_t ngroup);
++extern const char *ext4_decode_error(struct super_block *sb, int errno,
++				     char nbuf[16]);
+ extern __printf(4, 5)
+ void __ext4_error(struct super_block *, const char *, unsigned int,
+ 		  const char *, ...);
+diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
+index b4323ba846b5..6f6114525535 100644
+--- a/fs/ext4/ext4_jbd2.c
++++ b/fs/ext4/ext4_jbd2.c
+@@ -6,6 +6,107 @@
+ 
+ #include 
+ 
++/* Just increment the non-pointer handle value */
++static handle_t *ext4_get_nojournal(void)
++{
++	handle_t *handle = current->journal_info;
++	unsigned long ref_cnt = (unsigned long)handle;
++
++	BUG_ON(ref_cnt >= EXT4_NOJOURNAL_MAX_REF_COUNT);
++
++	ref_cnt++;
++	handle = (handle_t *)ref_cnt;
++
++	current->journal_info = handle;
++	return handle;
++}
++
++
++/* Decrement the non-pointer handle value */
++static void ext4_put_nojournal(handle_t *handle)
++{
++	unsigned long ref_cnt = (unsigned long)handle;
++
++	BUG_ON(ref_cnt == 0);
++
++	ref_cnt--;
++	handle = (handle_t *)ref_cnt;
++
++	current->journal_info = handle;
++}
++
++/*
++ * Wrappers for jbd2_journal_start/end.
++ */
++handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks)
++{
++	journal_t *journal;
++
++	trace_ext4_journal_start(sb, nblocks, _RET_IP_);
++	if (sb->s_flags & MS_RDONLY)
++		return ERR_PTR(-EROFS);
++
++	WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE);
++	journal = EXT4_SB(sb)->s_journal;
++	if (!journal)
++		return ext4_get_nojournal();
++	/*
++	 * Special case here: if the journal has aborted behind our
++	 * backs (eg. EIO in the commit thread), then we still need to
++	 * take the FS itself readonly cleanly.
++	 */
++	if (is_journal_aborted(journal)) {
++		ext4_abort(sb, "Detected aborted journal");
++		return ERR_PTR(-EROFS);
++	}
++	return jbd2_journal_start(journal, nblocks);
++}
++
++int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle)
++{
++	struct super_block *sb;
++	int err;
++	int rc;
++
++	if (!ext4_handle_valid(handle)) {
++		ext4_put_nojournal(handle);
++		return 0;
++	}
++	sb = handle->h_transaction->t_journal->j_private;
++	err = handle->h_err;
++	rc = jbd2_journal_stop(handle);
++
++	if (!err)
++		err = rc;
++	if (err)
++		__ext4_std_error(sb, where, line, err);
++	return err;
++}
++
++void ext4_journal_abort_handle(const char *caller, unsigned int line,
++			       const char *err_fn, struct buffer_head *bh,
++			       handle_t *handle, int err)
++{
++	char nbuf[16];
++	const char *errstr = ext4_decode_error(NULL, err, nbuf);
++
++	BUG_ON(!ext4_handle_valid(handle));
++
++	if (bh)
++		BUFFER_TRACE(bh, "abort");
++
++	if (!handle->h_err)
++		handle->h_err = err;
++
++	if (is_handle_aborted(handle))
++		return;
++
++	printk(KERN_ERR "EXT4-fs: %s:%d: aborting transaction: %s in %s\n",
++	       caller, line, errstr, err_fn);
++
++	jbd2_journal_abort_handle(handle);
++}
++
+ int __ext4_journal_get_write_access(const char *where, unsigned int line,
+ 				    handle_t *handle, struct buffer_head *bh)
+ {
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 2e1f94704b1f..cb9d67fbc8f0 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -69,8 +69,6 @@ static void ext4_mark_recovery_complete(struct super_block *sb,
+ static void ext4_clear_journal_err(struct super_block *sb,
+ 				   struct ext4_super_block *es);
+ static int ext4_sync_fs(struct super_block *sb, int wait);
+-static const char *ext4_decode_error(struct super_block *sb, int errno,
+-				     char nbuf[16]);
+ static int ext4_remount(struct super_block *sb, int *flags, char *data);
+ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf);
+ static int ext4_unfreeze(struct super_block *sb);
+@@ -296,107 +294,6 @@ void ext4_itable_unused_set(struct super_block *sb,
+ }
+ 
+ 
+-/* Just increment the non-pointer handle value */
+-static handle_t *ext4_get_nojournal(void)
+-{
+-	handle_t *handle = current->journal_info;
+-	unsigned long ref_cnt = (unsigned long)handle;
+-
+-	BUG_ON(ref_cnt >= EXT4_NOJOURNAL_MAX_REF_COUNT);
+-
+-	ref_cnt++;
+-	handle = (handle_t *)ref_cnt;
+-
+-	current->journal_info = handle;
+-	return handle;
+-}
+-
+-
+-/* Decrement the non-pointer handle value */
+-static void ext4_put_nojournal(handle_t *handle)
+-{
+-	unsigned long ref_cnt = (unsigned long)handle;
+-
+-	BUG_ON(ref_cnt == 0);
+-
+-	ref_cnt--;
+-	handle = (handle_t *)ref_cnt;
+-
+-	current->journal_info = handle;
+-}
+-
+-/*
+- * Wrappers for jbd2_journal_start/end.
+- */
+-handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks)
+-{
+-	journal_t *journal;
+-
+-	trace_ext4_journal_start(sb, nblocks, _RET_IP_);
+-	if (sb->s_flags & MS_RDONLY)
+-		return ERR_PTR(-EROFS);
+-
+-	WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE);
+-	journal = EXT4_SB(sb)->s_journal;
+-	if (!journal)
+-		return ext4_get_nojournal();
+-	/*
+-	 * Special case here: if the journal has aborted behind our
+-	 * backs (eg. EIO in the commit thread), then we still need to
+-	 * take the FS itself readonly cleanly.
+-	 */
+-	if (is_journal_aborted(journal)) {
+-		ext4_abort(sb, "Detected aborted journal");
+-		return ERR_PTR(-EROFS);
+-	}
+-	return jbd2_journal_start(journal, nblocks);
+-}
+-
+-int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle)
+-{
+-	struct super_block *sb;
+-	int err;
+-	int rc;
+-
+-	if (!ext4_handle_valid(handle)) {
+-		ext4_put_nojournal(handle);
+-		return 0;
+-	}
+-	sb = handle->h_transaction->t_journal->j_private;
+-	err = handle->h_err;
+-	rc = jbd2_journal_stop(handle);
+-
+-	if (!err)
+-		err = rc;
+-	if (err)
+-		__ext4_std_error(sb, where, line, err);
+-	return err;
+-}
+-
+-void ext4_journal_abort_handle(const char *caller, unsigned int line,
+-			       const char *err_fn, struct buffer_head *bh,
+-			       handle_t *handle, int err)
+-{
+-	char nbuf[16];
+-	const char *errstr = ext4_decode_error(NULL, err, nbuf);
+-
+-	BUG_ON(!ext4_handle_valid(handle));
+-
+-	if (bh)
+-		BUFFER_TRACE(bh, "abort");
+-
+-	if (!handle->h_err)
+-		handle->h_err = err;
+-
+-	if (is_handle_aborted(handle))
+-		return;
+-
+-	printk(KERN_ERR "EXT4-fs: %s:%d: aborting transaction: %s in %s\n",
+-	       caller, line, errstr, err_fn);
+-
+-	jbd2_journal_abort_handle(handle);
+-}
+-
+ static void __save_error_info(struct super_block *sb, const char *func,
+ 			    unsigned int line)
+ {
+@@ -582,8 +479,8 @@ void ext4_error_file(struct file *file, const char *function,
+ 	ext4_handle_error(inode->i_sb);
+ }
+ 
+-static const char *ext4_decode_error(struct super_block *sb, int errno,
+-				     char nbuf[16])
++const char *ext4_decode_error(struct super_block *sb, int errno,
++			      char nbuf[16])
+ {
+ 	char *errstr = NULL;
+ 

commit 343d9c283c9847da043fda3e76e3197f27b667dd
+Author: Theodore Ts'o 
+Date:   Fri Feb 8 13:00:22 2013 -0500
+
+    jbd2: add tracepoints which provide per-handle statistics
+    
+    Handles which stay open a long time are problematic when it comes time
+    to close down a transaction so it can be committed.  These tracepoints
+    will help us determine which ones are the problematic ones, and to
+    validate whether changes makes things better or worse.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index 735609e2d636..b7e2385c6e92 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -30,6 +30,8 @@
+ #include 
+ #include 
+ 
++#include 
++
+ static void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh);
+ static void __jbd2_journal_unfile_buffer(struct journal_head *jh);
+ 
+@@ -307,6 +309,8 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
+ 	 */
+ 	update_t_max_wait(transaction, ts);
+ 	handle->h_transaction = transaction;
++	handle->h_requested_credits = nblocks;
++	handle->h_start_jiffies = jiffies;
+ 	atomic_inc(&transaction->t_updates);
+ 	atomic_inc(&transaction->t_handle_count);
+ 	jbd_debug(4, "Handle %p given %d credits (total %d, free %d)\n",
+@@ -353,7 +357,8 @@ static handle_t *new_handle(int nblocks)
+  * Return a pointer to a newly allocated handle, or an ERR_PTR() value
+  * on failure.
+  */
+-handle_t *jbd2__journal_start(journal_t *journal, int nblocks, gfp_t gfp_mask)
++handle_t *jbd2__journal_start(journal_t *journal, int nblocks, gfp_t gfp_mask,
++			      unsigned int type, unsigned int line_no)
+ {
+ 	handle_t *handle = journal_current_handle();
+ 	int err;
+@@ -379,6 +384,11 @@ handle_t *jbd2__journal_start(journal_t *journal, int nblocks, gfp_t gfp_mask)
+ 		current->journal_info = NULL;
+ 		handle = ERR_PTR(err);
+ 	}
++	handle->h_type = type;
++	handle->h_line_no = line_no;
++	trace_jbd2_handle_start(journal->j_fs_dev->bd_dev,
++				handle->h_transaction->t_tid, type,
++				line_no, nblocks);
+ 	return handle;
+ }
+ EXPORT_SYMBOL(jbd2__journal_start);
+@@ -386,7 +396,7 @@ EXPORT_SYMBOL(jbd2__journal_start);
+ 
+ handle_t *jbd2_journal_start(journal_t *journal, int nblocks)
+ {
+-	return jbd2__journal_start(journal, nblocks, GFP_NOFS);
++	return jbd2__journal_start(journal, nblocks, GFP_NOFS, 0, 0);
+ }
+ EXPORT_SYMBOL(jbd2_journal_start);
+ 
+@@ -448,7 +458,14 @@ int jbd2_journal_extend(handle_t *handle, int nblocks)
+ 		goto unlock;
+ 	}
+ 
++	trace_jbd2_handle_extend(journal->j_fs_dev->bd_dev,
++				 handle->h_transaction->t_tid,
++				 handle->h_type, handle->h_line_no,
++				 handle->h_buffer_credits,
++				 nblocks);
++
+ 	handle->h_buffer_credits += nblocks;
++	handle->h_requested_credits += nblocks;
+ 	atomic_add(nblocks, &transaction->t_outstanding_credits);
+ 	result = 0;
+ 
+@@ -1377,6 +1394,13 @@ int jbd2_journal_stop(handle_t *handle)
+ 	}
+ 
+ 	jbd_debug(4, "Handle %p going down\n", handle);
++	trace_jbd2_handle_stats(journal->j_fs_dev->bd_dev,
++				handle->h_transaction->t_tid,
++				handle->h_type, handle->h_line_no,
++				jiffies - handle->h_start_jiffies,
++				handle->h_sync, handle->h_requested_credits,
++				(handle->h_requested_credits -
++				 handle->h_buffer_credits));
+ 
+ 	/*
+ 	 * Implement synchronous transaction batching.  If the handle
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index 24db7256a5ff..fa5fea17b619 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -400,6 +400,11 @@ struct jbd2_journal_handle
+ 	unsigned int	h_sync:		1;	/* sync-on-close */
+ 	unsigned int	h_jdata:	1;	/* force data journaling */
+ 	unsigned int	h_aborted:	1;	/* fatal error on handle */
++	unsigned int	h_type:		8;	/* for handle statistics */
++	unsigned int	h_line_no:	16;	/* for handle statistics */
++
++	unsigned long		h_start_jiffies;
++	unsigned int		h_requested_credits;
+ 
+ #ifdef CONFIG_DEBUG_LOCK_ALLOC
+ 	struct lockdep_map	h_lockdep_map;
+@@ -1071,7 +1076,8 @@ static inline handle_t *journal_current_handle(void)
+  */
+ 
+ extern handle_t *jbd2_journal_start(journal_t *, int nblocks);
+-extern handle_t *jbd2__journal_start(journal_t *, int nblocks, gfp_t gfp_mask);
++extern handle_t *jbd2__journal_start(journal_t *, int nblocks, gfp_t gfp_mask,
++				     unsigned int type, unsigned int line_no);
+ extern int	 jbd2_journal_restart(handle_t *, int nblocks);
+ extern int	 jbd2__journal_restart(handle_t *, int nblocks, gfp_t gfp_mask);
+ extern int	 jbd2_journal_extend (handle_t *, int nblocks);
+diff --git a/include/trace/events/jbd2.h b/include/trace/events/jbd2.h
+index 5419f57beb1f..070df49e4a1d 100644
+--- a/include/trace/events/jbd2.h
++++ b/include/trace/events/jbd2.h
+@@ -132,6 +132,104 @@ TRACE_EVENT(jbd2_submit_inode_data,
+ 		  (unsigned long) __entry->ino)
+ );
+ 
++TRACE_EVENT(jbd2_handle_start,
++	TP_PROTO(dev_t dev, unsigned long tid, unsigned int type,
++		 unsigned int line_no, int requested_blocks),
++
++	TP_ARGS(dev, tid, type, line_no, requested_blocks),
++
++	TP_STRUCT__entry(
++		__field(		dev_t,	dev		)
++		__field(	unsigned long,	tid		)
++		__field(	 unsigned int,	type		)
++		__field(	 unsigned int,	line_no		)
++		__field(		  int,	requested_blocks)
++	),
++
++	TP_fast_assign(
++		__entry->dev		  = dev;
++		__entry->tid		  = tid;
++		__entry->type		  = type;
++		__entry->line_no	  = line_no;
++		__entry->requested_blocks = requested_blocks;
++	),
++
++	TP_printk("dev %d,%d tid %lu type %u line_no %u "
++		  "requested_blocks %d",
++		  MAJOR(__entry->dev), MINOR(__entry->dev), __entry->tid,
++		  __entry->type, __entry->line_no, __entry->requested_blocks)
++);
++
++TRACE_EVENT(jbd2_handle_extend,
++	TP_PROTO(dev_t dev, unsigned long tid, unsigned int type,
++		 unsigned int line_no, int buffer_credits,
++		 int requested_blocks),
++
++	TP_ARGS(dev, tid, type, line_no, buffer_credits, requested_blocks),
++
++	TP_STRUCT__entry(
++		__field(		dev_t,	dev		)
++		__field(	unsigned long,	tid		)
++		__field(	 unsigned int,	type		)
++		__field(	 unsigned int,	line_no		)
++		__field(		  int,	buffer_credits  )
++		__field(		  int,	requested_blocks)
++	),
++
++	TP_fast_assign(
++		__entry->dev		  = dev;
++		__entry->tid		  = tid;
++		__entry->type		  = type;
++		__entry->line_no	  = line_no;
++		__entry->buffer_credits   = buffer_credits;
++		__entry->requested_blocks = requested_blocks;
++	),
++
++	TP_printk("dev %d,%d tid %lu type %u line_no %u "
++		  "buffer_credits %d requested_blocks %d",
++		  MAJOR(__entry->dev), MINOR(__entry->dev), __entry->tid,
++		  __entry->type, __entry->line_no, __entry->buffer_credits,
++		  __entry->requested_blocks)
++);
++
++TRACE_EVENT(jbd2_handle_stats,
++	TP_PROTO(dev_t dev, unsigned long tid, unsigned int type,
++		 unsigned int line_no, int interval, int sync,
++		 int requested_blocks, int dirtied_blocks),
++
++	TP_ARGS(dev, tid, type, line_no, interval, sync,
++		requested_blocks, dirtied_blocks),
++
++	TP_STRUCT__entry(
++		__field(		dev_t,	dev		)
++		__field(	unsigned long,	tid		)
++		__field(	 unsigned int,	type		)
++		__field(	 unsigned int,	line_no		)
++		__field(		  int,	interval	)
++		__field(		  int,	sync		)
++		__field(		  int,	requested_blocks)
++		__field(		  int,	dirtied_blocks	)
++	),
++
++	TP_fast_assign(
++		__entry->dev		  = dev;
++		__entry->tid		  = tid;
++		__entry->type		  = type;
++		__entry->line_no	  = line_no;
++		__entry->interval	  = interval;
++		__entry->sync		  = sync;
++		__entry->requested_blocks = requested_blocks;
++		__entry->dirtied_blocks	  = dirtied_blocks;
++	),
++
++	TP_printk("dev %d,%d tid %lu type %u line_no %u interval %d "
++		  "sync %d requested_blocks %d dirtied_blocks %d",
++		  MAJOR(__entry->dev), MINOR(__entry->dev), __entry->tid,
++		  __entry->type, __entry->line_no, __entry->interval,
++		  __entry->sync, __entry->requested_blocks,
++		  __entry->dirtied_blocks)
++);
++
+ TRACE_EVENT(jbd2_run_stats,
+ 	TP_PROTO(dev_t dev, unsigned long tid,
+ 		 struct transaction_run_stats_s *stats),

commit 078d5039a13dedbd2ed14153a6d764fd75baae07
+Author: Theodore Ts'o 
+Date:   Thu Feb 7 00:02:15 2013 -0500
+
+    jbd2: revert "jbd2: add COW fields to struct jbd2_journal_handle"
+    
+    This reverts commit 93737456d68ddcb86232f669b83da673dd12e351.
+    
+    The cow-snapshots effort is no longer active, so remove these extra
+    fields to shrink down the handle structure.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Jan Kara 
+
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index e0aafc46064f..24db7256a5ff 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -397,35 +397,13 @@ struct jbd2_journal_handle
+ 	int			h_err;
+ 
+ 	/* Flags [no locking] */
+-	unsigned int	h_sync:1;	/* sync-on-close */
+-	unsigned int	h_jdata:1;	/* force data journaling */
+-	unsigned int	h_aborted:1;	/* fatal error on handle */
+-	unsigned int	h_cowing:1;	/* COWing block to snapshot */
+-
+-	/* Number of buffers requested by user:
+-	 * (before adding the COW credits factor) */
+-	unsigned int	h_base_credits:14;
+-
+-	/* Number of buffers the user is allowed to dirty:
+-	 * (counts only buffers dirtied when !h_cowing) */
+-	unsigned int	h_user_credits:14;
+-
++	unsigned int	h_sync:		1;	/* sync-on-close */
++	unsigned int	h_jdata:	1;	/* force data journaling */
++	unsigned int	h_aborted:	1;	/* fatal error on handle */
+ 
+ #ifdef CONFIG_DEBUG_LOCK_ALLOC
+ 	struct lockdep_map	h_lockdep_map;
+ #endif
+-
+-#ifdef CONFIG_JBD2_DEBUG
+-	/* COW debugging counters: */
+-	unsigned int h_cow_moved; /* blocks moved to snapshot */
+-	unsigned int h_cow_copied; /* blocks copied to snapshot */
+-	unsigned int h_cow_ok_jh; /* blocks already COWed during current
+-				     transaction */
+-	unsigned int h_cow_ok_bitmap; /* blocks not set in COW bitmap */
+-	unsigned int h_cow_ok_mapped;/* blocks already mapped in snapshot */
+-	unsigned int h_cow_bitmaps; /* COW bitmaps created */
+-	unsigned int h_cow_excluded; /* blocks set in exclude bitmap */
+-#endif
+ };
+ 
+ 

commit 9fff24aa2c5c504aadead1ff9599e813604c2e53
+Author: Theodore Ts'o 
+Date:   Wed Feb 6 22:30:23 2013 -0500
+
+    jbd2: track request delay statistics
+    
+    Track the delay between when we first request that the commit begin
+    and when it actually begins, so we can see how much of a gap exists.
+    In theory, this should just be the remaining scheduling quantuum of
+    the thread which requested the commit (assuming it was not a
+    synchronous operation which triggered the commit request) plus
+    scheduling overhead; however, it's possible that real time processes
+    might get in the way of letting the kjournald thread from executing.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index 3091d42992f0..750c70148eff 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -435,7 +435,12 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 
+ 	trace_jbd2_commit_locking(journal, commit_transaction);
+ 	stats.run.rs_wait = commit_transaction->t_max_wait;
++	stats.run.rs_request_delay = 0;
+ 	stats.run.rs_locked = jiffies;
++	if (commit_transaction->t_requested)
++		stats.run.rs_request_delay =
++			jbd2_time_diff(commit_transaction->t_requested,
++				       stats.run.rs_locked);
+ 	stats.run.rs_running = jbd2_time_diff(commit_transaction->t_start,
+ 					      stats.run.rs_locked);
+ 
+@@ -1116,7 +1121,10 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	 */
+ 	spin_lock(&journal->j_history_lock);
+ 	journal->j_stats.ts_tid++;
++	if (commit_transaction->t_requested)
++		journal->j_stats.ts_requested++;
+ 	journal->j_stats.run.rs_wait += stats.run.rs_wait;
++	journal->j_stats.run.rs_request_delay += stats.run.rs_request_delay;
+ 	journal->j_stats.run.rs_running += stats.run.rs_running;
+ 	journal->j_stats.run.rs_locked += stats.run.rs_locked;
+ 	journal->j_stats.run.rs_flushing += stats.run.rs_flushing;
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 1a80e3146a59..4ba2e81e35ac 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -533,6 +533,7 @@ int __jbd2_log_start_commit(journal_t *journal, tid_t target)
+ 		jbd_debug(1, "JBD2: requesting commit %d/%d\n",
+ 			  journal->j_commit_request,
+ 			  journal->j_commit_sequence);
++		journal->j_running_transaction->t_requested = jiffies;
+ 		wake_up(&journal->j_wait_commit);
+ 		return 1;
+ 	} else if (!tid_geq(journal->j_commit_request, target))
+@@ -898,13 +899,18 @@ static int jbd2_seq_info_show(struct seq_file *seq, void *v)
+ 
+ 	if (v != SEQ_START_TOKEN)
+ 		return 0;
+-	seq_printf(seq, "%lu transaction, each up to %u blocks\n",
+-			s->stats->ts_tid,
+-			s->journal->j_max_transaction_buffers);
++	seq_printf(seq, "%lu transactions (%lu requested), "
++		   "each up to %u blocks\n",
++		   s->stats->ts_tid, s->stats->ts_requested,
++		   s->journal->j_max_transaction_buffers);
+ 	if (s->stats->ts_tid == 0)
+ 		return 0;
+ 	seq_printf(seq, "average: \n  %ums waiting for transaction\n",
+ 	    jiffies_to_msecs(s->stats->run.rs_wait / s->stats->ts_tid));
++	seq_printf(seq, "  %ums request delay\n",
++	    (s->stats->ts_requested == 0) ? 0 :
++	    jiffies_to_msecs(s->stats->run.rs_request_delay /
++			     s->stats->ts_requested));
+ 	seq_printf(seq, "  %ums running transaction\n",
+ 	    jiffies_to_msecs(s->stats->run.rs_running / s->stats->ts_tid));
+ 	seq_printf(seq, "  %ums transaction was being locked\n",
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index df9f29760efa..735609e2d636 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -100,6 +100,7 @@ jbd2_get_transaction(journal_t *journal, transaction_t *transaction)
+ 	journal->j_running_transaction = transaction;
+ 	transaction->t_max_wait = 0;
+ 	transaction->t_start = jiffies;
++	transaction->t_requested = 0;
+ 
+ 	return transaction;
+ }
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index e30b66346942..e0aafc46064f 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -580,6 +580,11 @@ struct transaction_s
+ 	 */
+ 	unsigned long		t_start;
+ 
++	/*
++	 * When commit was requested
++	 */
++	unsigned long		t_requested;
++
+ 	/*
+ 	 * Checkpointing stats [j_checkpoint_sem]
+ 	 */
+@@ -637,6 +642,7 @@ struct transaction_s
+ 
+ struct transaction_run_stats_s {
+ 	unsigned long		rs_wait;
++	unsigned long		rs_request_delay;
+ 	unsigned long		rs_running;
+ 	unsigned long		rs_locked;
+ 	unsigned long		rs_flushing;
+@@ -649,6 +655,7 @@ struct transaction_run_stats_s {
+ 
+ struct transaction_stats_s {
+ 	unsigned long		ts_tid;
++	unsigned long		ts_requested;
+ 	struct transaction_run_stats_s run;
+ };
+ 
+diff --git a/include/trace/events/jbd2.h b/include/trace/events/jbd2.h
+index 127993dbf322..5419f57beb1f 100644
+--- a/include/trace/events/jbd2.h
++++ b/include/trace/events/jbd2.h
+@@ -142,6 +142,7 @@ TRACE_EVENT(jbd2_run_stats,
+ 		__field(		dev_t,	dev		)
+ 		__field(	unsigned long,	tid		)
+ 		__field(	unsigned long,	wait		)
++		__field(	unsigned long,	request_delay	)
+ 		__field(	unsigned long,	running		)
+ 		__field(	unsigned long,	locked		)
+ 		__field(	unsigned long,	flushing	)
+@@ -155,6 +156,7 @@ TRACE_EVENT(jbd2_run_stats,
+ 		__entry->dev		= dev;
+ 		__entry->tid		= tid;
+ 		__entry->wait		= stats->rs_wait;
++		__entry->request_delay	= stats->rs_request_delay;
+ 		__entry->running	= stats->rs_running;
+ 		__entry->locked		= stats->rs_locked;
+ 		__entry->flushing	= stats->rs_flushing;
+@@ -164,10 +166,12 @@ TRACE_EVENT(jbd2_run_stats,
+ 		__entry->blocks_logged	= stats->rs_blocks_logged;
+ 	),
+ 
+-	TP_printk("dev %d,%d tid %lu wait %u running %u locked %u flushing %u "
+-		  "logging %u handle_count %u blocks %u blocks_logged %u",
++	TP_printk("dev %d,%d tid %lu wait %u request_delay %u running %u "
++		  "locked %u flushing %u logging %u handle_count %u "
++		  "blocks %u blocks_logged %u",
+ 		  MAJOR(__entry->dev), MINOR(__entry->dev), __entry->tid,
+ 		  jiffies_to_msecs(__entry->wait),
++		  jiffies_to_msecs(__entry->request_delay),
+ 		  jiffies_to_msecs(__entry->running),
+ 		  jiffies_to_msecs(__entry->locked),
+ 		  jiffies_to_msecs(__entry->flushing),

commit 40ae3487628235e5f1eb27542cca0cdb6e5dbe16
+Author: Theodore Ts'o 
+Date:   Mon Feb 4 15:08:40 2013 -0500
+
+    ext4: optimize mballoc for large allocations
+    
+    The ext4 block allocator only maintains buddy bitmaps for chunks which
+    are less than or equal to one quarter of a block group.  That is, for
+    a file aystem with a 1k blocksize, and where the number of blocks in a
+    block group is 8192 blocks, the largest chunk size tracked by buddy
+    bitmaps is 2048 blocks.
+    
+    For a file system with a 4k blocksize, and where the number of blocks
+    in a block group is 32768 blocks, the largest chunk size tracked by
+    buddy bitmaps is 8192 blocks.
+    
+    To work around this code, mballoc.c before this commit would truncate
+    allocation requests to the number of blocks in a block group minus 10.
+    Why 10?  Aside from being a completely arbitrary number, it avoids
+    block allocation to be a power of two larger than 25% of the block
+    group.  If you try to explicitly fallocate 50% of the block group
+    size, this will demonstrate the problem; the block allocation code
+    will scan the all of the blocks in the file system with cr==0 (since
+    the request is for a natural power of two), but then completely fail
+    for all blocks groups, since the buddy bitmaps don't track chunk sizes
+    of 50% of the block group.
+    
+    To fix this, in these we use ext4_mb_complex_scan_group() instead of
+    ext4_mb_simple_scan_group().
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Andreas Dilger 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 061727acd990..e350885aec30 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -1884,15 +1884,19 @@ static int ext4_mb_good_group(struct ext4_allocation_context *ac,
+ 	case 0:
+ 		BUG_ON(ac->ac_2order == 0);
+ 
+-		if (grp->bb_largest_free_order < ac->ac_2order)
+-			return 0;
+-
+ 		/* Avoid using the first bg of a flexgroup for data files */
+ 		if ((ac->ac_flags & EXT4_MB_HINT_DATA) &&
+ 		    (flex_size >= EXT4_FLEX_SIZE_DIR_ALLOC_SCHEME) &&
+ 		    ((group % flex_size) == 0))
+ 			return 0;
+ 
++		if ((ac->ac_2order > ac->ac_sb->s_blocksize_bits+1) ||
++		    (free / fragments) >= ac->ac_g_ex.fe_len)
++			return 1;
++
++		if (grp->bb_largest_free_order < ac->ac_2order)
++			return 0;
++
+ 		return 1;
+ 	case 1:
+ 		if ((free / fragments) >= ac->ac_g_ex.fe_len)
+@@ -2007,7 +2011,7 @@ ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
+ 			}
+ 
+ 			ac->ac_groups_scanned++;
+-			if (cr == 0)
++			if (cr == 0 && ac->ac_2order < sb->s_blocksize_bits+2)
+ 				ext4_mb_simple_scan_group(ac, &e4b);
+ 			else if (cr == 1 && sbi->s_stripe &&
+ 					!(ac->ac_g_ex.fe_len % sbi->s_stripe))
+@@ -4005,8 +4009,8 @@ ext4_mb_initialize_context(struct ext4_allocation_context *ac,
+ 	len = ar->len;
+ 
+ 	/* just a dirty hack to filter too big requests  */
+-	if (len >= EXT4_CLUSTERS_PER_GROUP(sb) - 10)
+-		len = EXT4_CLUSTERS_PER_GROUP(sb) - 10;
++	if (len >= EXT4_CLUSTERS_PER_GROUP(sb))
++		len = EXT4_CLUSTERS_PER_GROUP(sb);
+ 
+ 	/* start searching from the goal */
+ 	goal = ar->goal;

commit 8dc0aa8cf0f7b51e6c7c342e6f1e61520fb94222
+Author: Theodore Ts'o 
+Date:   Sat Feb 2 23:38:39 2013 -0500
+
+    ext4: check incompatible mount options while mounting ext2/3
+    
+    Check for incompatible mount options when using the ext4 file system
+    driver to mount ext2 or ext3 file systems.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index b68f4b671bc7..2e1f94704b1f 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1406,6 +1406,9 @@ static int clear_qf_name(struct super_block *sb, int qtype)
+ #define MOPT_QFMT	MOPT_NOSUPPORT
+ #endif
+ #define MOPT_DATAJ	0x0080
++#define MOPT_NO_EXT2	0x0100
++#define MOPT_NO_EXT3	0x0200
++#define MOPT_EXT4_ONLY	(MOPT_NO_EXT2 | MOPT_NO_EXT3)
+ 
+ static const struct mount_opts {
+ 	int	token;
+@@ -1418,21 +1421,29 @@ static const struct mount_opts {
+ 	{Opt_nogrpid, EXT4_MOUNT_GRPID, MOPT_CLEAR},
+ 	{Opt_block_validity, EXT4_MOUNT_BLOCK_VALIDITY, MOPT_SET},
+ 	{Opt_noblock_validity, EXT4_MOUNT_BLOCK_VALIDITY, MOPT_CLEAR},
+-	{Opt_dioread_nolock, EXT4_MOUNT_DIOREAD_NOLOCK, MOPT_SET},
+-	{Opt_dioread_lock, EXT4_MOUNT_DIOREAD_NOLOCK, MOPT_CLEAR},
++	{Opt_dioread_nolock, EXT4_MOUNT_DIOREAD_NOLOCK,
++	 MOPT_EXT4_ONLY | MOPT_SET},
++	{Opt_dioread_lock, EXT4_MOUNT_DIOREAD_NOLOCK,
++	 MOPT_EXT4_ONLY | MOPT_CLEAR},
+ 	{Opt_discard, EXT4_MOUNT_DISCARD, MOPT_SET},
+ 	{Opt_nodiscard, EXT4_MOUNT_DISCARD, MOPT_CLEAR},
+-	{Opt_delalloc, EXT4_MOUNT_DELALLOC, MOPT_SET | MOPT_EXPLICIT},
+-	{Opt_nodelalloc, EXT4_MOUNT_DELALLOC, MOPT_CLEAR | MOPT_EXPLICIT},
+-	{Opt_journal_checksum, EXT4_MOUNT_JOURNAL_CHECKSUM, MOPT_SET},
++	{Opt_delalloc, EXT4_MOUNT_DELALLOC,
++	 MOPT_EXT4_ONLY | MOPT_SET | MOPT_EXPLICIT},
++	{Opt_nodelalloc, EXT4_MOUNT_DELALLOC,
++	 MOPT_EXT4_ONLY | MOPT_CLEAR | MOPT_EXPLICIT},
++	{Opt_journal_checksum, EXT4_MOUNT_JOURNAL_CHECKSUM,
++	 MOPT_EXT4_ONLY | MOPT_SET},
+ 	{Opt_journal_async_commit, (EXT4_MOUNT_JOURNAL_ASYNC_COMMIT |
+-				    EXT4_MOUNT_JOURNAL_CHECKSUM), MOPT_SET},
+-	{Opt_noload, EXT4_MOUNT_NOLOAD, MOPT_SET},
++				    EXT4_MOUNT_JOURNAL_CHECKSUM),
++	 MOPT_EXT4_ONLY | MOPT_SET},
++	{Opt_noload, EXT4_MOUNT_NOLOAD, MOPT_NO_EXT2 | MOPT_SET},
+ 	{Opt_err_panic, EXT4_MOUNT_ERRORS_PANIC, MOPT_SET | MOPT_CLEAR_ERR},
+ 	{Opt_err_ro, EXT4_MOUNT_ERRORS_RO, MOPT_SET | MOPT_CLEAR_ERR},
+ 	{Opt_err_cont, EXT4_MOUNT_ERRORS_CONT, MOPT_SET | MOPT_CLEAR_ERR},
+-	{Opt_data_err_abort, EXT4_MOUNT_DATA_ERR_ABORT, MOPT_SET},
+-	{Opt_data_err_ignore, EXT4_MOUNT_DATA_ERR_ABORT, MOPT_CLEAR},
++	{Opt_data_err_abort, EXT4_MOUNT_DATA_ERR_ABORT,
++	 MOPT_NO_EXT2 | MOPT_SET},
++	{Opt_data_err_ignore, EXT4_MOUNT_DATA_ERR_ABORT,
++	 MOPT_NO_EXT2 | MOPT_CLEAR},
+ 	{Opt_barrier, EXT4_MOUNT_BARRIER, MOPT_SET},
+ 	{Opt_nobarrier, EXT4_MOUNT_BARRIER, MOPT_CLEAR},
+ 	{Opt_noauto_da_alloc, EXT4_MOUNT_NO_AUTO_DA_ALLOC, MOPT_SET},
+@@ -1448,9 +1459,10 @@ static const struct mount_opts {
+ 	{Opt_resgid, 0, MOPT_GTE0},
+ 	{Opt_journal_dev, 0, MOPT_GTE0},
+ 	{Opt_journal_ioprio, 0, MOPT_GTE0},
+-	{Opt_data_journal, EXT4_MOUNT_JOURNAL_DATA, MOPT_DATAJ},
+-	{Opt_data_ordered, EXT4_MOUNT_ORDERED_DATA, MOPT_DATAJ},
+-	{Opt_data_writeback, EXT4_MOUNT_WRITEBACK_DATA, MOPT_DATAJ},
++	{Opt_data_journal, EXT4_MOUNT_JOURNAL_DATA, MOPT_NO_EXT2 | MOPT_DATAJ},
++	{Opt_data_ordered, EXT4_MOUNT_ORDERED_DATA, MOPT_NO_EXT2 | MOPT_DATAJ},
++	{Opt_data_writeback, EXT4_MOUNT_WRITEBACK_DATA,
++	 MOPT_NO_EXT2 | MOPT_DATAJ},
+ 	{Opt_user_xattr, EXT4_MOUNT_XATTR_USER, MOPT_SET},
+ 	{Opt_nouser_xattr, EXT4_MOUNT_XATTR_USER, MOPT_CLEAR},
+ #ifdef CONFIG_EXT4_FS_POSIX_ACL
+@@ -1528,6 +1540,17 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
+ 		return -1;
+ 	}
+ 
++	if ((m->flags & MOPT_NO_EXT2) && IS_EXT2_SB(sb)) {
++		ext4_msg(sb, KERN_ERR,
++			 "Mount option \"%s\" incompatible with ext2", opt);
++		return -1;
++	}
++	if ((m->flags & MOPT_NO_EXT3) && IS_EXT3_SB(sb)) {
++		ext4_msg(sb, KERN_ERR,
++			 "Mount option \"%s\" incompatible with ext3", opt);
++		return -1;
++	}
++
+ 	if (args->from && match_int(args, &arg))
+ 		return -1;
+ 	if (args->from && (m->flags & MOPT_GTE0) && (arg < 0))

commit c3ad83d9efdfe6a86efd44945a781f00c879b7b4
+Author: Theodore Ts'o 
+Date:   Thu Jan 24 23:24:56 2013 -0500
+
+    quota: autoload the quota_v2 module for QFMT_VFS_V1 quota format
+    
+    Otherwise, ext4 file systems with the quota featured enable will get a
+    very confusing "No such process" error message if the quota code is
+    built as a module and the quota_v2 module has not been loaded.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Carlos Maiolino 
+    Acked-by: Jan Kara 
+    Cc: stable@vger.kernel.org
+
+diff --git a/include/linux/quota.h b/include/linux/quota.h
+index 58fdef125252..d13371134c59 100644
+--- a/include/linux/quota.h
++++ b/include/linux/quota.h
+@@ -405,6 +405,7 @@ struct quota_module_name {
+ #define INIT_QUOTA_MODULE_NAMES {\
+ 	{QFMT_VFS_OLD, "quota_v1"},\
+ 	{QFMT_VFS_V0, "quota_v2"},\
++	{QFMT_VFS_V1, "quota_v2"},\
+ 	{0, NULL}}
+ 
+ #endif /* _QUOTA_ */

commit 72ba74508b2857e71d65fc93f0d6b684492fc740
+Author: Theodore Ts'o 
+Date:   Thu Jan 24 23:24:54 2013 -0500
+
+    ext4: release sysfs kobject when failing to enable quotas on mount
+    
+    In addition, print the error returned from ext4_enable_quotas()
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Carlos Maiolino 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index c014edd12648..3ac306064b28 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4009,7 +4009,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	    !(sb->s_flags & MS_RDONLY)) {
+ 		err = ext4_enable_quotas(sb);
+ 		if (err)
+-			goto failed_mount7;
++			goto failed_mount8;
+ 	}
+ #endif  /* CONFIG_QUOTA */
+ 
+@@ -4036,6 +4036,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		ext4_msg(sb, KERN_ERR, "VFS: Can't find ext4 filesystem");
+ 	goto failed_mount;
+ 
++#ifdef CONFIG_QUOTA
++failed_mount8:
++	kobject_del(&sbi->s_kobj);
++#endif
+ failed_mount7:
+ 	ext4_unregister_li_request(sb);
+ failed_mount6:
+@@ -5006,9 +5010,9 @@ static int ext4_enable_quotas(struct super_block *sb)
+ 						DQUOT_USAGE_ENABLED);
+ 			if (err) {
+ 				ext4_warning(sb,
+-					"Failed to enable quota (type=%d) "
+-					"tracking. Please run e2fsck to fix.",
+-					type);
++					"Failed to enable quota tracking "
++					"(type=%d, err=%d). Please run "
++					"e2fsck to fix.", type, err);
+ 				return err;
+ 			}
+ 		}

commit 7f5118629f74b82bd4ba5e47415d1b4dcb940241
+Author: Theodore Ts'o 
+Date:   Sun Jan 13 08:41:45 2013 -0500
+
+    ext4: trigger the lazy inode table initialization after resize
+    
+    After we have finished extending the file system, we need to trigger a
+    the lazy inode table thread to zero out the inode tables.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 8462eb3c33aa..80246237f6d5 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2227,6 +2227,8 @@ extern int ext4_group_desc_csum_verify(struct super_block *sb, __u32 group,
+ 				       struct ext4_group_desc *gdp);
+ extern void ext4_group_desc_csum_set(struct super_block *sb, __u32 group,
+ 				     struct ext4_group_desc *gdp);
++extern int ext4_register_li_request(struct super_block *sb,
++				    ext4_group_t first_not_zeroed);
+ 
+ static inline int ext4_has_group_desc_csum(struct super_block *sb)
+ {
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index 5747f52f7c72..4784ac244fc6 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -313,6 +313,9 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 		if (err == 0)
+ 			err = err2;
+ 		mnt_drop_write_file(filp);
++		if (!err && ext4_has_group_desc_csum(sb) &&
++		    test_opt(sb, INIT_INODE_TABLE))
++			err = ext4_register_li_request(sb, input.group);
+ group_add_out:
+ 		ext4_resize_end(sb);
+ 		return err;
+@@ -358,6 +361,7 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 		ext4_fsblk_t n_blocks_count;
+ 		struct super_block *sb = inode->i_sb;
+ 		int err = 0, err2 = 0;
++		ext4_group_t o_group = EXT4_SB(sb)->s_groups_count;
+ 
+ 		if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
+ 			       EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {
+@@ -388,6 +392,11 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 		if (err == 0)
+ 			err = err2;
+ 		mnt_drop_write_file(filp);
++		if (!err && (o_group > EXT4_SB(sb)->s_groups_count) &&
++		    ext4_has_group_desc_csum(sb) &&
++		    test_opt(sb, INIT_INODE_TABLE))
++			err = ext4_register_li_request(sb, o_group);
++
+ resizefs_out:
+ 		ext4_resize_end(sb);
+ 		return err;
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 05f8d4502d42..8eefb636beb8 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -1506,10 +1506,12 @@ static int ext4_setup_next_flex_gd(struct super_block *sb,
+ 		group_data[i].blocks_count = blocks_per_group;
+ 		overhead = ext4_group_overhead_blocks(sb, group + i);
+ 		group_data[i].free_blocks_count = blocks_per_group - overhead;
+-		if (ext4_has_group_desc_csum(sb))
++		if (ext4_has_group_desc_csum(sb)) {
+ 			flex_gd->bg_flags[i] = EXT4_BG_BLOCK_UNINIT |
+ 					       EXT4_BG_INODE_UNINIT;
+-		else
++			if (!test_opt(sb, INIT_INODE_TABLE))
++				flex_gd->bg_flags[i] |= EXT4_BG_INODE_ZEROED;
++		} else
+ 			flex_gd->bg_flags[i] = EXT4_BG_INODE_ZEROED;
+ 	}
+ 
+@@ -1594,7 +1596,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
+ 
+ 	err = ext4_alloc_flex_bg_array(sb, input->group + 1);
+ 	if (err)
+-		return err;
++		goto out;
+ 
+ 	err = ext4_mb_alloc_groupinfo(sb, input->group + 1);
+ 	if (err)
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 3d4fb81bacd5..c014edd12648 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2776,7 +2776,7 @@ static int ext4_run_li_request(struct ext4_li_request *elr)
+ 			break;
+ 	}
+ 
+-	if (group == ngroups)
++	if (group >= ngroups)
+ 		ret = 1;
+ 
+ 	if (!ret) {
+@@ -3016,33 +3016,34 @@ static struct ext4_li_request *ext4_li_request_new(struct super_block *sb,
+ 	return elr;
+ }
+ 
+-static int ext4_register_li_request(struct super_block *sb,
+-				    ext4_group_t first_not_zeroed)
++int ext4_register_li_request(struct super_block *sb,
++			     ext4_group_t first_not_zeroed)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-	struct ext4_li_request *elr;
++	struct ext4_li_request *elr = NULL;
+ 	ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count;
+ 	int ret = 0;
+ 
++	mutex_lock(&ext4_li_mtx);
+ 	if (sbi->s_li_request != NULL) {
+ 		/*
+ 		 * Reset timeout so it can be computed again, because
+ 		 * s_li_wait_mult might have changed.
+ 		 */
+ 		sbi->s_li_request->lr_timeout = 0;
+-		return 0;
++		goto out;
+ 	}
+ 
+ 	if (first_not_zeroed == ngroups ||
+ 	    (sb->s_flags & MS_RDONLY) ||
+ 	    !test_opt(sb, INIT_INODE_TABLE))
+-		return 0;
++		goto out;
+ 
+ 	elr = ext4_li_request_new(sb, first_not_zeroed);
+-	if (!elr)
+-		return -ENOMEM;
+-
+-	mutex_lock(&ext4_li_mtx);
++	if (!elr) {
++		ret = -ENOMEM;
++		goto out;
++	}
+ 
+ 	if (NULL == ext4_li_info) {
+ 		ret = ext4_li_info_new();

commit 860d21e2c585f7ee8a4ecc06f474fdc33c9474f4
+Author: Theodore Ts'o 
+Date:   Sat Jan 12 16:19:36 2013 -0500
+
+    ext4: return ENOMEM if sb_getblk() fails
+    
+    The only reason for sb_getblk() failing is if it can't allocate the
+    buffer_head.  So ENOMEM is more appropriate than EIO.  In addition,
+    make sure that the file system is marked as being inconsistent if
+    sb_getblk() fails.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 5ae1674ec12f..d42a8c49ad69 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -725,6 +725,7 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
+ 	struct ext4_extent_header *eh;
+ 	struct buffer_head *bh;
+ 	short int depth, i, ppos = 0, alloc = 0;
++	int ret;
+ 
+ 	eh = ext_inode_hdr(inode);
+ 	depth = ext_depth(inode);
+@@ -752,12 +753,15 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
+ 		path[ppos].p_ext = NULL;
+ 
+ 		bh = sb_getblk(inode->i_sb, path[ppos].p_block);
+-		if (unlikely(!bh))
++		if (unlikely(!bh)) {
++			ret = -ENOMEM;
+ 			goto err;
++		}
+ 		if (!bh_uptodate_or_lock(bh)) {
+ 			trace_ext4_ext_load_extent(inode, block,
+ 						path[ppos].p_block);
+-			if (bh_submit_read(bh) < 0) {
++			ret = bh_submit_read(bh);
++			if (ret < 0) {
+ 				put_bh(bh);
+ 				goto err;
+ 			}
+@@ -768,13 +772,15 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
+ 			put_bh(bh);
+ 			EXT4_ERROR_INODE(inode,
+ 					 "ppos %d > depth %d", ppos, depth);
++			ret = -EIO;
+ 			goto err;
+ 		}
+ 		path[ppos].p_bh = bh;
+ 		path[ppos].p_hdr = eh;
+ 		i--;
+ 
+-		if (ext4_ext_check_block(inode, eh, i, bh))
++		ret = ext4_ext_check_block(inode, eh, i, bh);
++		if (ret < 0)
+ 			goto err;
+ 	}
+ 
+@@ -796,7 +802,7 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
+ 	ext4_ext_drop_refs(path);
+ 	if (alloc)
+ 		kfree(path);
+-	return ERR_PTR(-EIO);
++	return ERR_PTR(ret);
+ }
+ 
+ /*
+@@ -951,7 +957,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
+ 	}
+ 	bh = sb_getblk(inode->i_sb, newblock);
+ 	if (!bh) {
+-		err = -EIO;
++		err = -ENOMEM;
+ 		goto cleanup;
+ 	}
+ 	lock_buffer(bh);
+@@ -1024,7 +1030,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
+ 		newblock = ablocks[--a];
+ 		bh = sb_getblk(inode->i_sb, newblock);
+ 		if (!bh) {
+-			err = -EIO;
++			err = -ENOMEM;
+ 			goto cleanup;
+ 		}
+ 		lock_buffer(bh);
+@@ -1136,11 +1142,8 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
+ 		return err;
+ 
+ 	bh = sb_getblk(inode->i_sb, newblock);
+-	if (!bh) {
+-		err = -EIO;
+-		ext4_std_error(inode->i_sb, err);
+-		return err;
+-	}
++	if (!bh)
++		return -ENOMEM;
+ 	lock_buffer(bh);
+ 
+ 	err = ext4_journal_get_create_access(handle, bh);
+diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
+index 20862f96e8ae..8d83d1e508e4 100644
+--- a/fs/ext4/indirect.c
++++ b/fs/ext4/indirect.c
+@@ -146,6 +146,7 @@ static Indirect *ext4_get_branch(struct inode *inode, int depth,
+ 	struct super_block *sb = inode->i_sb;
+ 	Indirect *p = chain;
+ 	struct buffer_head *bh;
++	int ret = -EIO;
+ 
+ 	*err = 0;
+ 	/* i_data is not going away, no lock needed */
+@@ -154,8 +155,10 @@ static Indirect *ext4_get_branch(struct inode *inode, int depth,
+ 		goto no_block;
+ 	while (--depth) {
+ 		bh = sb_getblk(sb, le32_to_cpu(p->key));
+-		if (unlikely(!bh))
++		if (unlikely(!bh)) {
++			ret = -ENOMEM;
+ 			goto failure;
++		}
+ 
+ 		if (!bh_uptodate_or_lock(bh)) {
+ 			if (bh_submit_read(bh) < 0) {
+@@ -177,7 +180,7 @@ static Indirect *ext4_get_branch(struct inode *inode, int depth,
+ 	return NULL;
+ 
+ failure:
+-	*err = -EIO;
++	*err = ret;
+ no_block:
+ 	return p;
+ }
+@@ -471,7 +474,7 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
+ 		 */
+ 		bh = sb_getblk(inode->i_sb, new_blocks[n-1]);
+ 		if (unlikely(!bh)) {
+-			err = -EIO;
++			err = -ENOMEM;
+ 			goto failed;
+ 		}
+ 
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index 387c47c6cda9..93a3408fc89b 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -1188,7 +1188,7 @@ static int ext4_convert_inline_data_nolock(handle_t *handle,
+ 
+ 	data_bh = sb_getblk(inode->i_sb, map.m_pblk);
+ 	if (!data_bh) {
+-		error = -EIO;
++		error = -ENOMEM;
+ 		goto out_restore;
+ 	}
+ 
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index cbfe13bf5b2a..9ccc140b82d2 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -714,7 +714,7 @@ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
+ 
+ 	bh = sb_getblk(inode->i_sb, map.m_pblk);
+ 	if (!bh) {
+-		*errp = -EIO;
++		*errp = -ENOMEM;
+ 		return NULL;
+ 	}
+ 	if (map.m_flags & EXT4_MAP_NEW) {
+@@ -3660,11 +3660,8 @@ static int __ext4_get_inode_loc(struct inode *inode,
+ 	iloc->offset = (inode_offset % inodes_per_block) * EXT4_INODE_SIZE(sb);
+ 
+ 	bh = sb_getblk(sb, block);
+-	if (!bh) {
+-		EXT4_ERROR_INODE_BLOCK(inode, block,
+-				       "unable to read itable block");
+-		return -EIO;
+-	}
++	if (!bh)
++		return -ENOMEM;
+ 	if (!buffer_uptodate(bh)) {
+ 		lock_buffer(bh);
+ 
+diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c
+index fe7c63f4717e..44734f1ca554 100644
+--- a/fs/ext4/mmp.c
++++ b/fs/ext4/mmp.c
+@@ -80,6 +80,8 @@ static int read_mmp_block(struct super_block *sb, struct buffer_head **bh,
+ 	 * is not blocked in the elevator. */
+ 	if (!*bh)
+ 		*bh = sb_getblk(sb, mmp_block);
++	if (!*bh)
++		return -ENOMEM;
+ 	if (*bh) {
+ 		get_bh(*bh);
+ 		lock_buffer(*bh);
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index d99387b89edd..02824dc2ff3b 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -334,7 +334,7 @@ static struct buffer_head *bclean(handle_t *handle, struct super_block *sb,
+ 
+ 	bh = sb_getblk(sb, blk);
+ 	if (!bh)
+-		return ERR_PTR(-EIO);
++		return ERR_PTR(-ENOMEM);
+ 	if ((err = ext4_journal_get_write_access(handle, bh))) {
+ 		brelse(bh);
+ 		bh = ERR_PTR(err);
+@@ -411,7 +411,7 @@ static int set_flexbg_block_bitmap(struct super_block *sb, handle_t *handle,
+ 
+ 		bh = sb_getblk(sb, flex_gd->groups[group].block_bitmap);
+ 		if (!bh)
+-			return -EIO;
++			return -ENOMEM;
+ 
+ 		err = ext4_journal_get_write_access(handle, bh);
+ 		if (err)
+@@ -501,7 +501,7 @@ static int setup_new_flex_group_blocks(struct super_block *sb,
+ 
+ 			gdb = sb_getblk(sb, block);
+ 			if (!gdb) {
+-				err = -EIO;
++				err = -ENOMEM;
+ 				goto out;
+ 			}
+ 
+@@ -1065,7 +1065,7 @@ static void update_backups(struct super_block *sb, int blk_off, char *data,
+ 
+ 		bh = sb_getblk(sb, backup_block);
+ 		if (!bh) {
+-			err = -EIO;
++			err = -ENOMEM;
+ 			break;
+ 		}
+ 		ext4_debug("update metadata backup %llu(+%llu)\n",
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 3a91ebc2b66f..07d684a4e523 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -887,16 +887,17 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
+ 
+ 			new_bh = sb_getblk(sb, block);
+ 			if (!new_bh) {
++				error = -ENOMEM;
+ getblk_failed:
+ 				ext4_free_blocks(handle, inode, NULL, block, 1,
+ 						 EXT4_FREE_BLOCKS_METADATA);
+-				error = -EIO;
+ 				goto cleanup;
+ 			}
+ 			lock_buffer(new_bh);
+ 			error = ext4_journal_get_create_access(handle, new_bh);
+ 			if (error) {
+ 				unlock_buffer(new_bh);
++				error = -EIO;
+ 				goto getblk_failed;
+ 			}
+ 			memcpy(new_bh->b_data, s->base, new_bh->b_size);

commit 0e9a9a1ad619e7e987815d20262d36a2f95717ca
+Author: Theodore Ts'o 
+Date:   Thu Dec 27 01:42:50 2012 -0500
+
+    ext4: avoid hang when mounting non-journal filesystems with orphan list
+    
+    When trying to mount a file system which does not contain a journal,
+    but which does have a orphan list containing an inode which needs to
+    be truncated, the mount call with hang forever in
+    ext4_orphan_cleanup() because ext4_orphan_del() will return
+    immediately without removing the inode from the orphan list, leading
+    to an uninterruptible loop in kernel code which will busy out one of
+    the CPU's on the system.
+    
+    This can be trivially reproduced by trying to mount the file system
+    found in tests/f_orphan_extents_inode/image.gz from the e2fsprogs
+    source tree.  If a malicious user were to put this on a USB stick, and
+    mount it on a Linux desktop which has automatic mounts enabled, this
+    could be considered a potential denial of service attack.  (Not a big
+    deal in practice, but professional paranoids worry about such things,
+    and have even been known to allocate CVE numbers for such problems.)
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Zheng Liu 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index cac448282331..8990165346ee 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -2648,7 +2648,8 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode)
+ 	struct ext4_iloc iloc;
+ 	int err = 0;
+ 
+-	if (!EXT4_SB(inode->i_sb)->s_journal)
++	if ((!EXT4_SB(inode->i_sb)->s_journal) &&
++	    !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS))
+ 		return 0;
+ 
+ 	mutex_lock(&EXT4_SB(inode->i_sb)->s_orphan_lock);

commit 721e3eba21e43532e438652dd8f1fcdfce3187e7
+Author: Theodore Ts'o 
+Date:   Thu Dec 27 01:42:48 2012 -0500
+
+    ext4: lock i_mutex when truncating orphan inodes
+    
+    Commit c278531d39 added a warning when ext4_flush_unwritten_io() is
+    called without i_mutex being taken.  It had previously not been taken
+    during orphan cleanup since races weren't possible at that point in
+    the mount process, but as a result of this c278531d39, we will now see
+    a kernel WARN_ON in this case.  Take the i_mutex in
+    ext4_orphan_cleanup() to suppress this warning.
+    
+    Reported-by: Alexander Beregalov 
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Zheng Liu 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 183ae3447f64..3d4fb81bacd5 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2220,7 +2220,9 @@ static void ext4_orphan_cleanup(struct super_block *sb,
+ 				__func__, inode->i_ino, inode->i_size);
+ 			jbd_debug(2, "truncating inode %lu to %lld bytes\n",
+ 				  inode->i_ino, inode->i_size);
++			mutex_lock(&inode->i_mutex);
+ 			ext4_truncate(inode);
++			mutex_unlock(&inode->i_mutex);
+ 			nr_truncates++;
+ 		} else {
+ 			ext4_msg(sb, KERN_DEBUG,

commit bd9926e80330d43f15b710c2935fa41b792d56fd
+Author: Theodore Ts'o 
+Date:   Tue Dec 11 03:31:49 2012 -0500
+
+    ext4: zero out inline data using memset() instead of empty_zero_page
+    
+    Not all architectures (in particular, sparc64) have empty_zero_page.
+    So instead of copying from empty_zero_page, use memset to clear the
+    inline data by signalling to ext4_xattr_set_entry() via a magic
+    pointer value, EXT4_ZERO_ATTR_VALUE, which is defined by casting -1 to
+    a pointer.
+    
+    This fixes a build failure on sparc64, and the memset() should be more
+    efficient than using memcpy() anyway.
+    
+    Signed-off-by: Tao Ma 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index 53b2f65091dd..387c47c6cda9 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -268,7 +268,7 @@ static int ext4_create_inline_data(handle_t *handle,
+ 		goto out;
+ 
+ 	if (len > EXT4_MIN_INLINE_DATA_SIZE) {
+-		value = (void *)empty_zero_page;
++		value = EXT4_ZERO_XATTR_VALUE;
+ 		len -= EXT4_MIN_INLINE_DATA_SIZE;
+ 	} else {
+ 		value = "";
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 2251769a3c53..3a91ebc2b66f 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -628,9 +628,14 @@ ext4_xattr_set_entry(struct ext4_xattr_info *i, struct ext4_xattr_search *s)
+ 				   size. Just replace. */
+ 				s->here->e_value_size =
+ 					cpu_to_le32(i->value_len);
+-				memset(val + size - EXT4_XATTR_PAD, 0,
+-				       EXT4_XATTR_PAD); /* Clear pad bytes. */
+-				memcpy(val, i->value, i->value_len);
++				if (i->value == EXT4_ZERO_XATTR_VALUE) {
++					memset(val, 0, size);
++				} else {
++					/* Clear pad bytes first. */
++					memset(val + size - EXT4_XATTR_PAD, 0,
++					       EXT4_XATTR_PAD);
++					memcpy(val, i->value, i->value_len);
++				}
+ 				return 0;
+ 			}
+ 
+@@ -669,9 +674,14 @@ ext4_xattr_set_entry(struct ext4_xattr_info *i, struct ext4_xattr_search *s)
+ 			size_t size = EXT4_XATTR_SIZE(i->value_len);
+ 			void *val = s->base + min_offs - size;
+ 			s->here->e_value_offs = cpu_to_le16(min_offs - size);
+-			memset(val + size - EXT4_XATTR_PAD, 0,
+-			       EXT4_XATTR_PAD); /* Clear the pad bytes. */
+-			memcpy(val, i->value, i->value_len);
++			if (i->value == EXT4_ZERO_XATTR_VALUE) {
++				memset(val, 0, size);
++			} else {
++				/* Clear the pad bytes first. */
++				memset(val + size - EXT4_XATTR_PAD, 0,
++				       EXT4_XATTR_PAD);
++				memcpy(val, i->value, i->value_len);
++			}
+ 		}
+ 	}
+ 	return 0;
+diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
+index 7b5513ed3b38..69eda787a96a 100644
+--- a/fs/ext4/xattr.h
++++ b/fs/ext4/xattr.h
+@@ -71,6 +71,7 @@ struct ext4_xattr_entry {
+ #define BFIRST(bh) ENTRY(BHDR(bh)+1)
+ #define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
+ 
++#define EXT4_ZERO_XATTR_VALUE ((void *)-1)
+ 
+ struct ext4_xattr_info {
+ 	int name_index;

commit aeb1e5d69a5be592e86a926be73efb38c55af404
+Author: Theodore Ts'o 
+Date:   Thu Nov 29 21:21:22 2012 -0500
+
+    ext4: fix possible use after free with metadata csum
+    
+    Commit fa77dcfafeaa introduces block bitmap checksum calculation into
+    ext4_new_inode() in the case that block group was uninitialized.
+    However we brelse() the bitmap buffer before we attempt to checksum it
+    so we have no guarantee that the buffer is still there.
+    
+    Fix this by releasing the buffer after the possible checksum
+    computation.
+    
+    Signed-off-by: Lukas Czerner 
+    Signed-off-by: "Theodore Ts'o" 
+    Acked-by: Darrick J. Wong 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 3a100e7a62a8..c7efa88d7149 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -762,7 +762,6 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode,
+ 
+ 		BUFFER_TRACE(block_bitmap_bh, "dirty block bitmap");
+ 		err = ext4_handle_dirty_metadata(handle, NULL, block_bitmap_bh);
+-		brelse(block_bitmap_bh);
+ 
+ 		/* recheck and clear flag under lock if we still need to */
+ 		ext4_lock_group(sb, group);
+@@ -775,6 +774,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode,
+ 			ext4_group_desc_csum_set(sb, group, gdp);
+ 		}
+ 		ext4_unlock_group(sb, group);
++		brelse(block_bitmap_bh);
+ 
+ 		if (err)
+ 			goto fail;

commit 69c499d152a7fe2c4443e5ddd91568ad5a79145a
+Author: Theodore Ts'o 
+Date:   Thu Nov 29 21:13:48 2012 -0500
+
+    ext4: restructure ext4_ext_direct_IO()
+    
+    Remove a level of indentation by moving the DIO read and extending
+    write case to the beginning of the file.  This results in no actual
+    programmatic changes to the file, but makes it easier to
+    read/understand.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index cf5d30a7cce3..91a24967b8ae 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2927,10 +2927,10 @@ static int ext4_set_bh_endio(struct buffer_head *bh, struct inode *inode)
+  * fall back to buffered IO.
+  *
+  * For holes, we fallocate those blocks, mark them as uninitialized
+- * If those blocks were preallocated, we mark sure they are splited, but
++ * If those blocks were preallocated, we mark sure they are split, but
+  * still keep the range to write as uninitialized.
+  *
+- * The unwrritten extents will be converted to written when DIO is completed.
++ * The unwritten extents will be converted to written when DIO is completed.
+  * For async direct IO, since the IO may still pending when return, we
+  * set up an end_io call back function, which will do the conversion
+  * when async direct IO completed.
+@@ -2948,125 +2948,120 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
+ 	struct inode *inode = file->f_mapping->host;
+ 	ssize_t ret;
+ 	size_t count = iov_length(iov, nr_segs);
+-
++	int overwrite = 0;
++	get_block_t *get_block_func = NULL;
++	int dio_flags = 0;
+ 	loff_t final_size = offset + count;
+-	if (rw == WRITE && final_size <= inode->i_size) {
+-		int overwrite = 0;
+-		get_block_t *get_block_func = NULL;
+-		int dio_flags = 0;
+ 
+-		BUG_ON(iocb->private == NULL);
++	/* Use the old path for reads and writes beyond i_size. */
++	if (rw != WRITE || final_size > inode->i_size)
++		return ext4_ind_direct_IO(rw, iocb, iov, offset, nr_segs);
+ 
+-		/* If we do a overwrite dio, i_mutex locking can be released */
+-		overwrite = *((int *)iocb->private);
++	BUG_ON(iocb->private == NULL);
+ 
+-		if (overwrite) {
+-			atomic_inc(&inode->i_dio_count);
+-			down_read(&EXT4_I(inode)->i_data_sem);
+-			mutex_unlock(&inode->i_mutex);
+-		}
++	/* If we do a overwrite dio, i_mutex locking can be released */
++	overwrite = *((int *)iocb->private);
+ 
+-		/*
+- 		 * We could direct write to holes and fallocate.
+-		 *
+- 		 * Allocated blocks to fill the hole are marked as uninitialized
+- 		 * to prevent parallel buffered read to expose the stale data
+- 		 * before DIO complete the data IO.
+-		 *
+- 		 * As to previously fallocated extents, ext4 get_block
+- 		 * will just simply mark the buffer mapped but still
+- 		 * keep the extents uninitialized.
+- 		 *
+-		 * for non AIO case, we will convert those unwritten extents
+-		 * to written after return back from blockdev_direct_IO.
+-		 *
+-		 * for async DIO, the conversion needs to be defered when
+-		 * the IO is completed. The ext4 end_io callback function
+-		 * will be called to take care of the conversion work.
+-		 * Here for async case, we allocate an io_end structure to
+-		 * hook to the iocb.
+- 		 */
+-		iocb->private = NULL;
+-		ext4_inode_aio_set(inode, NULL);
+-		if (!is_sync_kiocb(iocb)) {
+-			ext4_io_end_t *io_end =
+-				ext4_init_io_end(inode, GFP_NOFS);
+-			if (!io_end) {
+-				ret = -ENOMEM;
+-				goto retake_lock;
+-			}
+-			io_end->flag |= EXT4_IO_END_DIRECT;
+-			iocb->private = io_end;
+-			/*
+-			 * we save the io structure for current async
+-			 * direct IO, so that later ext4_map_blocks()
+-			 * could flag the io structure whether there
+-			 * is a unwritten extents needs to be converted
+-			 * when IO is completed.
+-			 */
+-			ext4_inode_aio_set(inode, io_end);
+-		}
++	if (overwrite) {
++		atomic_inc(&inode->i_dio_count);
++		down_read(&EXT4_I(inode)->i_data_sem);
++		mutex_unlock(&inode->i_mutex);
++	}
+ 
+-		if (overwrite) {
+-			get_block_func = ext4_get_block_write_nolock;
+-		} else {
+-			get_block_func = ext4_get_block_write;
+-			dio_flags = DIO_LOCKING;
++	/*
++	 * We could direct write to holes and fallocate.
++	 *
++	 * Allocated blocks to fill the hole are marked as
++	 * uninitialized to prevent parallel buffered read to expose
++	 * the stale data before DIO complete the data IO.
++	 *
++	 * As to previously fallocated extents, ext4 get_block will
++	 * just simply mark the buffer mapped but still keep the
++	 * extents uninitialized.
++	 *
++	 * For non AIO case, we will convert those unwritten extents
++	 * to written after return back from blockdev_direct_IO.
++	 *
++	 * For async DIO, the conversion needs to be deferred when the
++	 * IO is completed. The ext4 end_io callback function will be
++	 * called to take care of the conversion work.  Here for async
++	 * case, we allocate an io_end structure to hook to the iocb.
++	 */
++	iocb->private = NULL;
++	ext4_inode_aio_set(inode, NULL);
++	if (!is_sync_kiocb(iocb)) {
++		ext4_io_end_t *io_end = ext4_init_io_end(inode, GFP_NOFS);
++		if (!io_end) {
++			ret = -ENOMEM;
++			goto retake_lock;
+ 		}
+-		ret = __blockdev_direct_IO(rw, iocb, inode,
+-					 inode->i_sb->s_bdev, iov,
+-					 offset, nr_segs,
+-					 get_block_func,
+-					 ext4_end_io_dio,
+-					 NULL,
+-					 dio_flags);
+-
+-		if (iocb->private)
+-			ext4_inode_aio_set(inode, NULL);
++		io_end->flag |= EXT4_IO_END_DIRECT;
++		iocb->private = io_end;
+ 		/*
+-		 * The io_end structure takes a reference to the inode,
+-		 * that structure needs to be destroyed and the
+-		 * reference to the inode need to be dropped, when IO is
+-		 * complete, even with 0 byte write, or failed.
+-		 *
+-		 * In the successful AIO DIO case, the io_end structure will be
+-		 * desctroyed and the reference to the inode will be dropped
+-		 * after the end_io call back function is called.
+-		 *
+-		 * In the case there is 0 byte write, or error case, since
+-		 * VFS direct IO won't invoke the end_io call back function,
+-		 * we need to free the end_io structure here.
++		 * we save the io structure for current async direct
++		 * IO, so that later ext4_map_blocks() could flag the
++		 * io structure whether there is a unwritten extents
++		 * needs to be converted when IO is completed.
+ 		 */
+-		if (ret != -EIOCBQUEUED && ret <= 0 && iocb->private) {
+-			ext4_free_io_end(iocb->private);
+-			iocb->private = NULL;
+-		} else if (ret > 0 && !overwrite && ext4_test_inode_state(inode,
+-						EXT4_STATE_DIO_UNWRITTEN)) {
+-			int err;
+-			/*
+-			 * for non AIO case, since the IO is already
+-			 * completed, we could do the conversion right here
+-			 */
+-			err = ext4_convert_unwritten_extents(inode,
+-							     offset, ret);
+-			if (err < 0)
+-				ret = err;
+-			ext4_clear_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN);
+-		}
++		ext4_inode_aio_set(inode, io_end);
++	}
+ 
+-	retake_lock:
+-		/* take i_mutex locking again if we do a ovewrite dio */
+-		if (overwrite) {
+-			inode_dio_done(inode);
+-			up_read(&EXT4_I(inode)->i_data_sem);
+-			mutex_lock(&inode->i_mutex);
+-		}
++	if (overwrite) {
++		get_block_func = ext4_get_block_write_nolock;
++	} else {
++		get_block_func = ext4_get_block_write;
++		dio_flags = DIO_LOCKING;
++	}
++	ret = __blockdev_direct_IO(rw, iocb, inode,
++				   inode->i_sb->s_bdev, iov,
++				   offset, nr_segs,
++				   get_block_func,
++				   ext4_end_io_dio,
++				   NULL,
++				   dio_flags);
++
++	if (iocb->private)
++		ext4_inode_aio_set(inode, NULL);
++	/*
++	 * The io_end structure takes a reference to the inode, that
++	 * structure needs to be destroyed and the reference to the
++	 * inode need to be dropped, when IO is complete, even with 0
++	 * byte write, or failed.
++	 *
++	 * In the successful AIO DIO case, the io_end structure will
++	 * be destroyed and the reference to the inode will be dropped
++	 * after the end_io call back function is called.
++	 *
++	 * In the case there is 0 byte write, or error case, since VFS
++	 * direct IO won't invoke the end_io call back function, we
++	 * need to free the end_io structure here.
++	 */
++	if (ret != -EIOCBQUEUED && ret <= 0 && iocb->private) {
++		ext4_free_io_end(iocb->private);
++		iocb->private = NULL;
++	} else if (ret > 0 && !overwrite && ext4_test_inode_state(inode,
++						EXT4_STATE_DIO_UNWRITTEN)) {
++		int err;
++		/*
++		 * for non AIO case, since the IO is already
++		 * completed, we could do the conversion right here
++		 */
++		err = ext4_convert_unwritten_extents(inode,
++						     offset, ret);
++		if (err < 0)
++			ret = err;
++		ext4_clear_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN);
++	}
+ 
+-		return ret;
++retake_lock:
++	/* take i_mutex locking again if we do a ovewrite dio */
++	if (overwrite) {
++		inode_dio_done(inode);
++		up_read(&EXT4_I(inode)->i_data_sem);
++		mutex_lock(&inode->i_mutex);
+ 	}
+ 
+-	/* for write the the end of file case, we fall back to old way */
+-	return ext4_ind_direct_IO(rw, iocb, iov, offset, nr_segs);
++	return ret;
+ }
+ 
+ static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb,

commit 4a092d737955301da22b9d5e07f5036da821a932
+Author: Theodore Ts'o 
+Date:   Wed Nov 28 13:03:30 2012 -0500
+
+    ext4: rationalize ext4_extents.h inclusion
+    
+    Previously, ext4_extents.h was being included at the end of ext4.h,
+    which was bad for a number of reasons: (a) it was not being included
+    in the expected place, and (b) it caused the header to be included
+    multiple times.  There were #ifdef's to prevent this from causing any
+    problems, but it still was unnecessary.
+    
+    By moving the function declarations that were in ext4_extents.h to
+    ext4.h, which is standard practice for where the function declarations
+    for the rest of ext4.h can be found, we can remove ext4_extents.h from
+    being included in ext4.h at all, and then we can only include
+    ext4_extents.h where it is needed in ext4's source files.
+    
+    It should be possible to move a few more things into ext4.h, and
+    further reduce the number of source files that need to #include
+    ext4_extents.h, but that's a cleanup for another day.
+    
+    Reported-by: Sachin Kamat 
+    Reported-by: Wei Yongjun 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 246e38f3915a..2e9ffa9100bb 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -57,6 +57,16 @@
+ #define ext4_debug(fmt, ...)	no_printk(fmt, ##__VA_ARGS__)
+ #endif
+ 
++/*
++ * Turn on EXT_DEBUG to get lots of info about extents operations.
++ */
++#define EXT_DEBUG__
++#ifdef EXT_DEBUG
++#define ext_debug(fmt, ...)	printk(fmt, ##__VA_ARGS__)
++#else
++#define ext_debug(fmt, ...)	no_printk(fmt, ##__VA_ARGS__)
++#endif
++
+ #define EXT4_ERROR_INODE(inode, fmt, a...) \
+ 	ext4_error_inode((inode), __func__, __LINE__, 0, (fmt), ## a)
+ 
+@@ -2399,6 +2409,9 @@ extern int ext4_check_blockref(const char *, unsigned int,
+ 			       struct inode *, __le32 *, unsigned int);
+ 
+ /* extents.c */
++struct ext4_ext_path;
++struct ext4_extent;
++
+ extern int ext4_ext_tree_init(handle_t *handle, struct inode *);
+ extern int ext4_ext_writepage_trans_blocks(struct inode *, int);
+ extern int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks,
+@@ -2416,8 +2429,27 @@ extern int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset,
+ 			  ssize_t len);
+ extern int ext4_map_blocks(handle_t *handle, struct inode *inode,
+ 			   struct ext4_map_blocks *map, int flags);
++extern int ext4_ext_calc_metadata_amount(struct inode *inode,
++					 ext4_lblk_t lblocks);
++extern int ext4_extent_tree_init(handle_t *, struct inode *);
++extern int ext4_ext_calc_credits_for_single_extent(struct inode *inode,
++						   int num,
++						   struct ext4_ext_path *path);
++extern int ext4_can_extents_be_merged(struct inode *inode,
++				      struct ext4_extent *ex1,
++				      struct ext4_extent *ex2);
++extern int ext4_ext_insert_extent(handle_t *, struct inode *,
++				  struct ext4_ext_path *,
++				  struct ext4_extent *, int);
++extern struct ext4_ext_path *ext4_ext_find_extent(struct inode *, ext4_lblk_t,
++						  struct ext4_ext_path *);
++extern void ext4_ext_drop_refs(struct ext4_ext_path *);
++extern int ext4_ext_check_inode(struct inode *inode);
++extern int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk);
+ extern int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ 			__u64 start, __u64 len);
++
++
+ /* move_extent.c */
+ extern int ext4_move_extents(struct file *o_filp, struct file *d_filp,
+ 			     __u64 start_orig, __u64 start_donor,
+@@ -2505,6 +2537,4 @@ extern void ext4_resize_end(struct super_block *sb);
+ 
+ #endif	/* __KERNEL__ */
+ 
+-#include "ext4_extents.h"
+-
+ #endif	/* _EXT4_H */
+diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h
+index 173b6c545323..487fda12bc00 100644
+--- a/fs/ext4/ext4_extents.h
++++ b/fs/ext4/ext4_extents.h
+@@ -42,16 +42,6 @@
+  */
+ #define CHECK_BINSEARCH__
+ 
+-/*
+- * Turn on EXT_DEBUG to get lots of info about extents operations.
+- */
+-#define EXT_DEBUG__
+-#ifdef EXT_DEBUG
+-#define ext_debug(fmt, ...)	printk(fmt, ##__VA_ARGS__)
+-#else
+-#define ext_debug(fmt, ...)	no_printk(fmt, ##__VA_ARGS__)
+-#endif
+-
+ /*
+  * If EXT_STATS is defined then stats numbers are collected.
+  * These number will be displayed at umount time.
+@@ -286,20 +276,5 @@ static inline void ext4_idx_store_pblock(struct ext4_extent_idx *ix,
+ 				     0xffff);
+ }
+ 
+-extern int ext4_ext_calc_metadata_amount(struct inode *inode,
+-					 ext4_lblk_t lblocks);
+-extern int ext4_extent_tree_init(handle_t *, struct inode *);
+-extern int ext4_ext_calc_credits_for_single_extent(struct inode *inode,
+-						   int num,
+-						   struct ext4_ext_path *path);
+-extern int ext4_can_extents_be_merged(struct inode *inode,
+-				      struct ext4_extent *ex1,
+-				      struct ext4_extent *ex2);
+-extern int ext4_ext_insert_extent(handle_t *, struct inode *, struct ext4_ext_path *, struct ext4_extent *, int);
+-extern struct ext4_ext_path *ext4_ext_find_extent(struct inode *, ext4_lblk_t,
+-							struct ext4_ext_path *);
+-extern void ext4_ext_drop_refs(struct ext4_ext_path *);
+-extern int ext4_ext_check_inode(struct inode *inode);
+-extern int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk);
+ #endif /* _EXT4_EXTENTS */
+ 
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 56251466750c..1dc19a7b449f 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -41,6 +41,7 @@
+ #include 
+ #include 
+ #include "ext4_jbd2.h"
++#include "ext4_extents.h"
+ 
+ #include 
+ 
+diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
+index f6663c3a946d..20862f96e8ae 100644
+--- a/fs/ext4/indirect.c
++++ b/fs/ext4/indirect.c
+@@ -22,6 +22,7 @@
+ 
+ #include "ext4_jbd2.h"
+ #include "truncate.h"
++#include "ext4_extents.h"	/* Needed for EXT_MAX_BLOCKS */
+ 
+ #include 
+ 
+diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
+index f1bb32ec0169..db8226d595fa 100644
+--- a/fs/ext4/migrate.c
++++ b/fs/ext4/migrate.c
+@@ -14,6 +14,7 @@
+ 
+ #include 
+ #include "ext4_jbd2.h"
++#include "ext4_extents.h"
+ 
+ /*
+  * The contiguous blocks details which can be
+diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
+index 292daeeed455..d9cc5ee42f53 100644
+--- a/fs/ext4/move_extent.c
++++ b/fs/ext4/move_extent.c
+@@ -18,6 +18,7 @@
+ #include 
+ #include "ext4_jbd2.h"
+ #include "ext4.h"
++#include "ext4_extents.h"
+ 
+ /**
+  * get_ext_path - Find an extent path for designated logical block number.
+diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
+index 0fd16e653ebd..0016fbca2a40 100644
+--- a/fs/ext4/page-io.c
++++ b/fs/ext4/page-io.c
+@@ -27,7 +27,6 @@
+ #include "ext4_jbd2.h"
+ #include "xattr.h"
+ #include "acl.h"
+-#include "ext4_extents.h"
+ 
+ static struct kmem_cache *io_page_cachep, *io_end_cachep;
+ 
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 66a4e20424cf..856206f255aa 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -45,12 +45,11 @@
+ #include 
+ 
+ #include "ext4.h"
+-#include "ext4_extents.h"
++#include "ext4_extents.h"	/* Needed for trace points definition */
+ #include "ext4_jbd2.h"
+ #include "xattr.h"
+ #include "acl.h"
+ #include "mballoc.h"
+-#include "ext4_extents.h"
+ 
+ #define CREATE_TRACE_POINTS
+ #include 

commit f3b59291a69d0b734be1fc8be489fef2dd846d3d
+Author: Theodore Ts'o 
+Date:   Thu Nov 15 23:08:57 2012 -0500
+
+    ext4: remove calls to ext4_jbd2_file_inode() from delalloc write path
+    
+    The calls to ext4_jbd2_file_inode() are needed to guarantee that we do
+    not expose stale data in the data=ordered mode.  However, they are not
+    necessary because in all of the cases where we have newly allocated
+    blocks in the delayed allocation write path, we immediately submit the
+    dirty pages for I/O.  Hence, we can avoid the overhead of adding the
+    inode to the list of inodes whose data pages will be to be flushed out
+    to disk completely during the next commit operation.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 52f7ff2f2e7e..cf5d30a7cce3 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1636,15 +1636,6 @@ static void mpage_da_map_and_submit(struct mpage_da_data *mpd)
+ 
+ 		for (i = 0; i < map.m_len; i++)
+ 			unmap_underlying_metadata(bdev, map.m_pblk + i);
+-
+-		if (ext4_should_order_data(mpd->inode)) {
+-			err = ext4_jbd2_file_inode(handle, mpd->inode);
+-			if (err) {
+-				/* Only if the journal is aborted */
+-				mpd->retval = err;
+-				goto submit_io;
+-			}
+-		}
+ 	}
+ 
+ 	/*
+@@ -2592,17 +2583,8 @@ static int ext4_da_write_end(struct file *file,
+ 	if (copied && new_i_size > EXT4_I(inode)->i_disksize) {
+ 		if (ext4_da_should_update_i_disksize(page, end)) {
+ 			down_write(&EXT4_I(inode)->i_data_sem);
+-			if (new_i_size > EXT4_I(inode)->i_disksize) {
+-				/*
+-				 * Updating i_disksize when extending file
+-				 * without needing block allocation
+-				 */
+-				if (ext4_should_order_data(inode))
+-					ret = ext4_jbd2_file_inode(handle,
+-								   inode);
+-
++			if (new_i_size > EXT4_I(inode)->i_disksize)
+ 				EXT4_I(inode)->i_disksize = new_i_size;
+-			}
+ 			up_write(&EXT4_I(inode)->i_data_sem);
+ 			/* We need to mark inode dirty even if
+ 			 * new_i_size is less that inode->i_size

commit dffe9d8da715bed4d395883add90a2d150d85729
+Author: Theodore Ts'o 
+Date:   Sat Nov 10 22:20:05 2012 -0500
+
+    ext4: do not use ext4_error() when there is no space in dir leaf for csum
+    
+    If there is no space for a checksum in a directory leaf node,
+    previously we would use EXT4_ERROR_INODE() which would mark the file
+    system as inconsistent.  While it would be nice to use e2fsck -D, it
+    certainly isn't required, so just print a warning using
+    ext4_warning().
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: "Darrick J. Wong" 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 6d600a69fc9d..580af3dfc0eb 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -261,6 +261,12 @@ static __le32 ext4_dirent_csum(struct inode *inode,
+ 	return cpu_to_le32(csum);
+ }
+ 
++static void warn_no_space_for_csum(struct inode *inode)
++{
++	ext4_warning(inode->i_sb, "no space in directory inode %lu leaf for "
++		     "checksum.  Please run e2fsck -D.", inode->i_ino);
++}
++
+ int ext4_dirent_csum_verify(struct inode *inode, struct ext4_dir_entry *dirent)
+ {
+ 	struct ext4_dir_entry_tail *t;
+@@ -271,8 +277,7 @@ int ext4_dirent_csum_verify(struct inode *inode, struct ext4_dir_entry *dirent)
+ 
+ 	t = get_dirent_tail(inode, dirent);
+ 	if (!t) {
+-		EXT4_ERROR_INODE(inode, "metadata_csum set but no space in dir "
+-				 "leaf for checksum.  Please run e2fsck -D.");
++		warn_no_space_for_csum(inode);
+ 		return 0;
+ 	}
+ 
+@@ -294,8 +299,7 @@ static void ext4_dirent_csum_set(struct inode *inode,
+ 
+ 	t = get_dirent_tail(inode, dirent);
+ 	if (!t) {
+-		EXT4_ERROR_INODE(inode, "metadata_csum set but no space in dir "
+-				 "leaf for checksum.  Please run e2fsck -D.");
++		warn_no_space_for_csum(inode);
+ 		return;
+ 	}
+ 
+@@ -377,8 +381,7 @@ static int ext4_dx_csum_verify(struct inode *inode,
+ 	count = le16_to_cpu(c->count);
+ 	if (count_offset + (limit * sizeof(struct dx_entry)) >
+ 	    EXT4_BLOCK_SIZE(inode->i_sb) - sizeof(struct dx_tail)) {
+-		EXT4_ERROR_INODE(inode, "metadata_csum set but no space for "
+-				 "tree checksum found.  Run e2fsck -D.");
++		warn_no_space_for_csum(inode);
+ 		return 1;
+ 	}
+ 	t = (struct dx_tail *)(((struct dx_entry *)c) + limit);
+@@ -408,8 +411,7 @@ static void ext4_dx_csum_set(struct inode *inode, struct ext4_dir_entry *dirent)
+ 	count = le16_to_cpu(c->count);
+ 	if (count_offset + (limit * sizeof(struct dx_entry)) >
+ 	    EXT4_BLOCK_SIZE(inode->i_sb) - sizeof(struct dx_tail)) {
+-		EXT4_ERROR_INODE(inode, "metadata_csum set but no space for "
+-				 "tree checksum.  Run e2fsck -D.");
++		warn_no_space_for_csum(inode);
+ 		return;
+ 	}
+ 	t = (struct dx_tail *)(((struct dx_entry *)c) + limit);

commit 06db49e68ae70cf16819b85a14057acb2820776a
+Author: Theodore Ts'o 
+Date:   Wed Oct 10 01:06:58 2012 -0400
+
+    ext4: fix metadata checksum calculation for the superblock
+    
+    The function ext4_handle_dirty_super() was calculating the superblock
+    on the wrong block data.  As a result, when the superblock is modified
+    while it is mounted (most commonly, when inodes are added or removed
+    from the orphan list), the superblock checksum would be wrong.  We
+    didn't notice because the superblock *was* being correctly calculated
+    in ext4_commit_super(), and this would get called when the file system
+    was unmounted.  So the problem only became obvious if the system
+    crashed while the file system was mounted.
+    
+    Fix this by removing the poorly designed function signature for
+    ext4_superblock_csum_set(); if it only took a single argument, the
+    pointer to a struct superblock, the ambiguity which caused this
+    mistake would have been impossible.
+    
+    Reported-by: George Spelvin 
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 3ab2539b7b2e..78971cfd9c7f 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2063,8 +2063,7 @@ extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count);
+ extern int ext4_calculate_overhead(struct super_block *sb);
+ extern int ext4_superblock_csum_verify(struct super_block *sb,
+ 				       struct ext4_super_block *es);
+-extern void ext4_superblock_csum_set(struct super_block *sb,
+-				     struct ext4_super_block *es);
++extern void ext4_superblock_csum_set(struct super_block *sb);
+ extern void *ext4_kvmalloc(size_t size, gfp_t flags);
+ extern void *ext4_kvzalloc(size_t size, gfp_t flags);
+ extern void ext4_kvfree(void *ptr);
+diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
+index bfa65b49d424..b4323ba846b5 100644
+--- a/fs/ext4/ext4_jbd2.c
++++ b/fs/ext4/ext4_jbd2.c
+@@ -143,17 +143,13 @@ int __ext4_handle_dirty_super(const char *where, unsigned int line,
+ 	struct buffer_head *bh = EXT4_SB(sb)->s_sbh;
+ 	int err = 0;
+ 
++	ext4_superblock_csum_set(sb);
+ 	if (ext4_handle_valid(handle)) {
+-		ext4_superblock_csum_set(sb,
+-				(struct ext4_super_block *)bh->b_data);
+ 		err = jbd2_journal_dirty_metadata(handle, bh);
+ 		if (err)
+ 			ext4_journal_abort_handle(where, line, __func__,
+ 						  bh, handle, err);
+-	} else {
+-		ext4_superblock_csum_set(sb,
+-				(struct ext4_super_block *)bh->b_data);
++	} else
+ 		mark_buffer_dirty(bh);
+-	}
+ 	return err;
+ }
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 982f6fc22c88..5ededf135335 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -143,9 +143,10 @@ int ext4_superblock_csum_verify(struct super_block *sb,
+ 	return es->s_checksum == ext4_superblock_csum(sb, es);
+ }
+ 
+-void ext4_superblock_csum_set(struct super_block *sb,
+-			      struct ext4_super_block *es)
++void ext4_superblock_csum_set(struct super_block *sb)
+ {
++	struct ext4_super_block *es = EXT4_SB(sb)->s_es;
++
+ 	if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
+ 		EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+ 		return;
+@@ -4387,7 +4388,7 @@ static int ext4_commit_super(struct super_block *sb, int sync)
+ 		cpu_to_le32(percpu_counter_sum_positive(
+ 				&EXT4_SB(sb)->s_freeinodes_counter));
+ 	BUFFER_TRACE(sbh, "marking dirty");
+-	ext4_superblock_csum_set(sb, es);
++	ext4_superblock_csum_set(sb);
+ 	mark_buffer_dirty(sbh);
+ 	if (sync) {
+ 		error = sync_dirty_buffer(sbh);

commit 041bbb6d369811e948ae01f3d00414264076be35
+Author: Theodore Ts'o 
+Date:   Sun Sep 30 23:04:56 2012 -0400
+
+    ext4: fix mtime update in nodelalloc mode
+    
+    Commits 5e8830dc85d0 and 41c4d25f78c0 introduced a regression into
+    v3.6-rc1 for ext4 in nodealloc mode, such that mtime updates would not
+    take place for files modified via mmap if the page was already in the
+    page cache.  This would also affect ext3 file systems mounted using
+    the ext4 file system driver.
+    
+    The problem was that ext4_page_mkwrite() had a shortcut which would
+    avoid calling __block_page_mkwrite() under some circumstances, and the
+    above two commit transferred the responsibility of calling
+    file_update_time() to __block_page_mkwrite --- which woudln't get
+    called in some circumstances.
+    
+    Since __block_page_mkwrite() only has three callers,
+    block_page_mkwrite(), ext4_page_mkwrite, and nilfs_page_mkwrite(), the
+    best way to solve this is to move the responsibility for calling
+    file_update_time() to its caller.
+    
+    This problem was found via xfstests #215 with a file system mounted
+    with -o nodelalloc.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Jan Kara 
+    Cc: KONISHI Ryusuke 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/buffer.c b/fs/buffer.c
+index 9f6d2e41281d..1fe3968357a9 100644
+--- a/fs/buffer.c
++++ b/fs/buffer.c
+@@ -2318,12 +2318,6 @@ int __block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
+ 	loff_t size;
+ 	int ret;
+ 
+-	/*
+-	 * Update file times before taking page lock. We may end up failing the
+-	 * fault so this update may be superfluous but who really cares...
+-	 */
+-	file_update_time(vma->vm_file);
+-
+ 	lock_page(page);
+ 	size = i_size_read(inode);
+ 	if ((page->mapping != inode->i_mapping) ||
+@@ -2361,6 +2355,13 @@ int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
+ 	struct super_block *sb = vma->vm_file->f_path.dentry->d_inode->i_sb;
+ 
+ 	sb_start_pagefault(sb);
++
++	/*
++	 * Update file times before taking page lock. We may end up failing the
++	 * fault so this update may be superfluous but who really cares...
++	 */
++	file_update_time(vma->vm_file);
++
+ 	ret = __block_page_mkwrite(vma, vmf, get_block);
+ 	sb_end_pagefault(sb);
+ 	return block_page_mkwrite_return(ret);
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 09308ad0f314..f18e786e87b0 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4788,6 +4788,7 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
+ 	int retries = 0;
+ 
+ 	sb_start_pagefault(inode->i_sb);
++	file_update_time(vma->vm_file);
+ 	/* Delalloc case is easy... */
+ 	if (test_opt(inode->i_sb, DELALLOC) &&
+ 	    !ext4_should_journal_data(inode) &&
+diff --git a/fs/nilfs2/file.c b/fs/nilfs2/file.c
+index a4d56ac02e6c..5b387a4c293e 100644
+--- a/fs/nilfs2/file.c
++++ b/fs/nilfs2/file.c
+@@ -116,6 +116,7 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
+ 	if (unlikely(ret))
+ 		goto out;
+ 
++	file_update_time(vma->vm_file);
+ 	ret = __block_page_mkwrite(vma, vmf, nilfs_get_block);
+ 	if (ret) {
+ 		nilfs_transaction_abort(inode->i_sb);

commit bbdd68086ca4a8976226e23efd08e2058d34dd81
+Author: Theodore Ts'o 
+Date:   Thu Sep 27 09:29:33 2012 -0400
+
+    fs: reserve fallocate flag codepoint
+    
+    As discussed at the Plumber's Conference, reserve the bit 0x04 in
+    fallocate() to prevent collisions with a commonly used out-of-tree
+    patch which implements the no-hide-stale feature.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/include/linux/falloc.h b/include/linux/falloc.h
+index 73e0b628e058..d39b824a780c 100644
+--- a/include/linux/falloc.h
++++ b/include/linux/falloc.h
+@@ -3,6 +3,7 @@
+ 
+ #define FALLOC_FL_KEEP_SIZE	0x01 /* default is extend size */
+ #define FALLOC_FL_PUNCH_HOLE	0x02 /* de-allocates range */
++#define FALLOC_FL_NO_HIDE_STALE	0x04 /* reserved codepoint */
+ 
+ #ifdef __KERNEL__
+ 

commit 641f14560035bbb86500ea4b3a27ad27f034725b
+Author: Silas Boyd-Wickizer 
+Date:   Sun Sep 23 20:27:32 2012 +0200
+
+    hwmon: (coretemp) Use get_online_cpus to avoid races involving CPU hotplug
+    
+    coretemp_init loops with for_each_online_cpu, adding platform_devices
+    and sysfs interfaces, then calls register_hotcpu_notifier.  There is a
+    race if a CPU is offlined or onlined after the loop, but before
+    register_hotcpu_notifier.  The race might result in the absence of a
+    platform_device+sysfs interface for an online CPU, or the presence of
+    a platform_device+sysfs interface for an offline CPU.  A similar race
+    occurs during coretemp_exit, after the module calls
+    unregister_hotcpu_notifier, but before it unregisters all devices, a
+    CPU might offline and a device for an offline CPU will exist for a
+    short while.
+    
+    This fix surrounds for_each_online_cpu and register_hotcpu_notifier
+    with get_online_cpus+put_online_cpus; and surrounds
+    unregister_hotcpu_notifier and device unregistering with
+    get_online_cpus+put_online_cpus.
+    
+    Build tested.
+    
+    Signed-off-by: Silas Boyd-Wickizer 
+    Signed-off-by: Jean Delvare 
+
+diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
+index 0fa356fe82cc..984a3f13923b 100644
+--- a/drivers/hwmon/coretemp.c
++++ b/drivers/hwmon/coretemp.c
+@@ -815,17 +815,20 @@ static int __init coretemp_init(void)
+ 	if (err)
+ 		goto exit;
+ 
++	get_online_cpus();
+ 	for_each_online_cpu(i)
+ 		get_core_online(i);
+ 
+ #ifndef CONFIG_HOTPLUG_CPU
+ 	if (list_empty(&pdev_list)) {
++		put_online_cpus();
+ 		err = -ENODEV;
+ 		goto exit_driver_unreg;
+ 	}
+ #endif
+ 
+ 	register_hotcpu_notifier(&coretemp_cpu_notifier);
++	put_online_cpus();
+ 	return 0;
+ 
+ #ifndef CONFIG_HOTPLUG_CPU
+@@ -840,6 +843,7 @@ static void __exit coretemp_exit(void)
+ {
+ 	struct pdev_entry *p, *n;
+ 
++	get_online_cpus();
+ 	unregister_hotcpu_notifier(&coretemp_cpu_notifier);
+ 	mutex_lock(&pdev_list_mutex);
+ 	list_for_each_entry_safe(p, n, &pdev_list, list) {
+@@ -848,6 +852,7 @@ static void __exit coretemp_exit(void)
+ 		kfree(p);
+ 	}
+ 	mutex_unlock(&pdev_list_mutex);
++	put_online_cpus();
+ 	platform_driver_unregister(&coretemp_driver);
+ }
+ 

commit 1ec3ddfd27a77db55b8c0e80bcd27c656473fb96
+Author: Silas Boyd-Wickizer 
+Date:   Sun Sep 23 20:27:32 2012 +0200
+
+    hwmon: (via-cputemp) Use get_online_cpus to avoid races involving CPU hotplug
+    
+    via_cputemp_init loops with for_each_online_cpu, adding
+    platform_devices, then calls register_hotcpu_notifier.  If a CPU is
+    offlined between the loop and register_hotcpu_notifier, then later
+    onlined, via_cputemp_device_add will attempt to add platform devices
+    with the same ID.  A similar race occurs during via_cputemp_exit,
+    after the module calls unregister_hotcpu_notifier, a CPU might offline
+    and a device will exist for a CPU that is offline.
+    
+    This fix surrounds for_each_online_cpu and register_hotcpu_notifier
+    with get_online_cpus+put_online_cpus; and surrounds
+    unregister_hotcpu_notifier and device unregistering with
+    get_online_cpus+put_online_cpus.
+    
+    Build tested.
+    
+    Signed-off-by: Silas Boyd-Wickizer 
+    Acked-by: Harald Welte 
+    Signed-off-by: Jean Delvare 
+
+diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c
+index ee4ebc198a94..2e56c6ce9fb6 100644
+--- a/drivers/hwmon/via-cputemp.c
++++ b/drivers/hwmon/via-cputemp.c
+@@ -328,6 +328,7 @@ static int __init via_cputemp_init(void)
+ 	if (err)
+ 		goto exit;
+ 
++	get_online_cpus();
+ 	for_each_online_cpu(i) {
+ 		struct cpuinfo_x86 *c = &cpu_data(i);
+ 
+@@ -347,12 +348,14 @@ static int __init via_cputemp_init(void)
+ 
+ #ifndef CONFIG_HOTPLUG_CPU
+ 	if (list_empty(&pdev_list)) {
++		put_online_cpus();
+ 		err = -ENODEV;
+ 		goto exit_driver_unreg;
+ 	}
+ #endif
+ 
+ 	register_hotcpu_notifier(&via_cputemp_cpu_notifier);
++	put_online_cpus();
+ 	return 0;
+ 
+ #ifndef CONFIG_HOTPLUG_CPU
+@@ -367,6 +370,7 @@ static void __exit via_cputemp_exit(void)
+ {
+ 	struct pdev_entry *p, *n;
+ 
++	get_online_cpus();
+ 	unregister_hotcpu_notifier(&via_cputemp_cpu_notifier);
+ 	mutex_lock(&pdev_list_mutex);
+ 	list_for_each_entry_safe(p, n, &pdev_list, list) {
+@@ -375,6 +379,7 @@ static void __exit via_cputemp_exit(void)
+ 		kfree(p);
+ 	}
+ 	mutex_unlock(&pdev_list_mutex);
++	put_online_cpus();
+ 	platform_driver_unregister(&via_cputemp_driver);
+ }
+ 

commit 429227bbe55647aa42f8f63cac61e4544e248629
+Author: Silas Boyd-Wickizer 
+Date:   Fri Aug 3 12:34:50 2012 -0700
+
+    Use get_online_cpus to avoid races involving CPU hotplug
+    
+    If arch/x86/kernel/cpuid.c is a module, a CPU might offline or online
+    between the for_each_online_cpu() loop and the call to
+    register_hotcpu_notifier in cpuid_init or the call to
+    unregister_hotcpu_notifier in cpuid_exit.  The potential races can
+    lead to leaks/duplicates, attempts to destroy non-existant devices, or
+    random pointer dereferences.
+    
+    For example, in cpuid_exit if:
+    
+            for_each_online_cpu(cpu)
+                    cpuid_device_destroy(cpu);
+            class_destroy(cpuid_class);
+            __unregister_chrdev(CPUID_MAJOR, 0, NR_CPUS, "cpu/cpuid");
+            <----- CPU onlines
+            unregister_hotcpu_notifier(&cpuid_class_cpu_notifier);
+    
+    the hotcpu notifier will attempt to create a device for the
+    cpuid_class, which the module already destroyed.
+    
+    This fix surrounds for_each_online_cpu and register_hotcpu_notifier or
+    unregister_hotcpu_notifier with get_online_cpus+put_online_cpus.
+    
+    Tested on a VM.
+    
+    Signed-off-by: Silas Boyd-Wickizer 
+    Signed-off-by: Paul E. McKenney 
+
+diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c
+index 39472dd2323f..60c78917190c 100644
+--- a/arch/x86/kernel/cpuid.c
++++ b/arch/x86/kernel/cpuid.c
+@@ -199,12 +199,14 @@ static int __init cpuid_init(void)
+ 		goto out_chrdev;
+ 	}
+ 	cpuid_class->devnode = cpuid_devnode;
++	get_online_cpus();
+ 	for_each_online_cpu(i) {
+ 		err = cpuid_device_create(i);
+ 		if (err != 0)
+ 			goto out_class;
+ 	}
+ 	register_hotcpu_notifier(&cpuid_class_cpu_notifier);
++	put_online_cpus();
+ 
+ 	err = 0;
+ 	goto out;
+@@ -214,6 +216,7 @@ static int __init cpuid_init(void)
+ 	for_each_online_cpu(i) {
+ 		cpuid_device_destroy(i);
+ 	}
++	put_online_cpus();
+ 	class_destroy(cpuid_class);
+ out_chrdev:
+ 	__unregister_chrdev(CPUID_MAJOR, 0, NR_CPUS, "cpu/cpuid");
+@@ -225,11 +228,13 @@ static void __exit cpuid_exit(void)
+ {
+ 	int cpu = 0;
+ 
++	get_online_cpus();
+ 	for_each_online_cpu(cpu)
+ 		cpuid_device_destroy(cpu);
+ 	class_destroy(cpuid_class);
+ 	__unregister_chrdev(CPUID_MAJOR, 0, NR_CPUS, "cpu/cpuid");
+ 	unregister_hotcpu_notifier(&cpuid_class_cpu_notifier);
++	put_online_cpus();
+ }
+ 
+ module_init(cpuid_init);

commit a2db672aa305a045404615e5222ba681bab6cf58
+Author: Silas Boyd-Wickizer 
+Date:   Fri Aug 3 12:33:27 2012 -0700
+
+    Use get_online_cpus to avoid races involving CPU hotplug
+    
+    If arch/x86/kernel/msr.c is a module, a CPU might offline or online
+    between the for_each_online_cpu(i) loop and the call to
+    register_hotcpu_notifier in msr_init or the call to
+    unregister_hotcpu_notifier in msr_exit. The potential races can lead
+    to leaks/duplicates, attempts to destroy non-existant devices, or
+    random pointer dereferences.
+    
+    For example, in msr_init if:
+    
+            for_each_online_cpu(i) {
+                    err = msr_device_create(i);
+                    if (err != 0)
+                            goto out_class;
+            }
+            <----- CPU offlines
+            register_hotcpu_notifier(&msr_class_cpu_notifier);
+    
+    and the CPU never onlines before msr_exit, then the module will never
+    call msr_device_destroy for the associated CPU.
+    
+    This fix surrounds for_each_online_cpu and register_hotcpu_notifier or
+    unregister_hotcpu_notifier with get_online_cpus+put_online_cpus.
+    
+    Tested on a VM.
+    
+    Signed-off-by: Silas Boyd-Wickizer 
+    Signed-off-by: Paul E. McKenney 
+
+diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c
+index eb113693f043..a7c5661f8496 100644
+--- a/arch/x86/kernel/msr.c
++++ b/arch/x86/kernel/msr.c
+@@ -257,12 +257,14 @@ static int __init msr_init(void)
+ 		goto out_chrdev;
+ 	}
+ 	msr_class->devnode = msr_devnode;
++	get_online_cpus();
+ 	for_each_online_cpu(i) {
+ 		err = msr_device_create(i);
+ 		if (err != 0)
+ 			goto out_class;
+ 	}
+ 	register_hotcpu_notifier(&msr_class_cpu_notifier);
++	put_online_cpus();
+ 
+ 	err = 0;
+ 	goto out;
+@@ -271,6 +273,7 @@ static int __init msr_init(void)
+ 	i = 0;
+ 	for_each_online_cpu(i)
+ 		msr_device_destroy(i);
++	put_online_cpus();
+ 	class_destroy(msr_class);
+ out_chrdev:
+ 	__unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr");
+@@ -281,11 +284,13 @@ static int __init msr_init(void)
+ static void __exit msr_exit(void)
+ {
+ 	int cpu = 0;
++	get_online_cpus();
+ 	for_each_online_cpu(cpu)
+ 		msr_device_destroy(cpu);
+ 	class_destroy(msr_class);
+ 	__unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr");
+ 	unregister_hotcpu_notifier(&msr_class_cpu_notifier);
++	put_online_cpus();
+ }
+ 
+ module_init(msr_init);

commit 00d4e7362ed01987183e9528295de3213031309c
+Author: Theodore Ts'o 
+Date:   Wed Sep 19 22:42:36 2012 -0400
+
+    ext4: fix potential deadlock in ext4_nonda_switch()
+    
+    In ext4_nonda_switch(), if the file system is getting full we used to
+    call writeback_inodes_sb_if_idle().  The problem is that we can be
+    holding i_mutex already, and this causes a potential deadlock when
+    writeback_inodes_sb_if_idle() when it tries to take s_umount.  (See
+    lockdep output below).
+    
+    As it turns out we don't need need to hold s_umount; the fact that we
+    are in the middle of the write(2) system call will keep the superblock
+    pinned.  Unfortunately writeback_inodes_sb() checks to make sure
+    s_umount is taken, and the VFS uses a different mechanism for making
+    sure the file system doesn't get unmounted out from under us.  The
+    simplest way of dealing with this is to just simply grab s_umount
+    using a trylock, and skip kicking the writeback flusher thread in the
+    very unlikely case that we can't take a read lock on s_umount without
+    blocking.
+    
+    Also, we now check the cirteria for kicking the writeback thread
+    before we decide to whether to fall back to non-delayed writeback, so
+    if there are any outstanding delayed allocation writes, we try to get
+    them resolved as soon as possible.
+    
+       [ INFO: possible circular locking dependency detected ]
+       3.6.0-rc1-00042-gce894ca #367 Not tainted
+       -------------------------------------------------------
+       dd/8298 is trying to acquire lock:
+        (&type->s_umount_key#18){++++..}, at: [] writeback_inodes_sb_if_idle+0x28/0x46
+    
+       but task is already holding lock:
+        (&sb->s_type->i_mutex_key#8){+.+...}, at: [] generic_file_aio_write+0x5f/0xd3
+    
+       which lock already depends on the new lock.
+    
+       2 locks held by dd/8298:
+        #0:  (sb_writers#2){.+.+.+}, at: [] generic_file_aio_write+0x56/0xd3
+        #1:  (&sb->s_type->i_mutex_key#8){+.+...}, at: [] generic_file_aio_write+0x5f/0xd3
+    
+       stack backtrace:
+       Pid: 8298, comm: dd Not tainted 3.6.0-rc1-00042-gce894ca #367
+       Call Trace:
+        [] ? console_unlock+0x345/0x372
+        [] print_circular_bug+0x190/0x19d
+        [] __lock_acquire+0x86d/0xb6c
+        [] ? mark_held_locks+0x5c/0x7b
+        [] lock_acquire+0x66/0xb9
+        [] ? writeback_inodes_sb_if_idle+0x28/0x46
+        [] down_read+0x28/0x58
+        [] ? writeback_inodes_sb_if_idle+0x28/0x46
+        [] writeback_inodes_sb_if_idle+0x28/0x46
+        [] ext4_nonda_switch+0xe1/0xf4
+        [] ext4_da_write_begin+0x27/0x193
+        [] generic_file_buffered_write+0xc8/0x1bb
+        [] __generic_file_aio_write+0x1dd/0x205
+        [] generic_file_aio_write+0x78/0xd3
+        [] ext4_file_write+0x480/0x4a6
+        [] ? __lock_acquire+0x41e/0xb6c
+        [] ? sched_clock_cpu+0x11a/0x13e
+        [] ? trace_hardirqs_off+0xb/0xd
+        [] ? local_clock+0x37/0x4e
+        [] do_sync_write+0x67/0x9d
+        [] ? wait_on_retry_sync_kiocb+0x44/0x44
+        [] vfs_write+0x7b/0xe6
+        [] sys_write+0x3b/0x64
+        [] syscall_call+0x7/0xb
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index ca76b5ed6c9e..0a31197590d7 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2462,6 +2462,16 @@ static int ext4_nonda_switch(struct super_block *sb)
+ 	free_blocks  = EXT4_C2B(sbi,
+ 		percpu_counter_read_positive(&sbi->s_freeclusters_counter));
+ 	dirty_blocks = percpu_counter_read_positive(&sbi->s_dirtyclusters_counter);
++	/*
++	 * Start pushing delalloc when 1/2 of free blocks are dirty.
++	 */
++	if (dirty_blocks && (free_blocks < 2 * dirty_blocks) &&
++	    !writeback_in_progress(sb->s_bdi) &&
++	    down_read_trylock(&sb->s_umount)) {
++		writeback_inodes_sb(sb, WB_REASON_FS_FREE_SPACE);
++		up_read(&sb->s_umount);
++	}
++
+ 	if (2 * free_blocks < 3 * dirty_blocks ||
+ 		free_blocks < (dirty_blocks + EXT4_FREECLUSTERS_WATERMARK)) {
+ 		/*
+@@ -2470,13 +2480,6 @@ static int ext4_nonda_switch(struct super_block *sb)
+ 		 */
+ 		return 1;
+ 	}
+-	/*
+-	 * Even if we don't switch but are nearing capacity,
+-	 * start pushing delalloc when 1/2 of free blocks are dirty.
+-	 */
+-	if (free_blocks < 2 * dirty_blocks)
+-		writeback_inodes_sb_if_idle(sb, WB_REASON_FS_FREE_SPACE);
+-
+ 	return 0;
+ }
+ 
+diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
+index be3efc4f64f4..5602d73d4ec7 100644
+--- a/fs/fs-writeback.c
++++ b/fs/fs-writeback.c
+@@ -63,6 +63,7 @@ int writeback_in_progress(struct backing_dev_info *bdi)
+ {
+ 	return test_bit(BDI_writeback_running, &bdi->state);
+ }
++EXPORT_SYMBOL(writeback_in_progress);
+ 
+ static inline struct backing_dev_info *inode_to_bdi(struct inode *inode)
+ {

commit 59e31c156a24d483bbd2ea07d4dc96043a55b6bc
+Author: Theodore Ts'o 
+Date:   Wed Sep 19 00:55:56 2012 -0400
+
+    ext4: fix online resizing when the # of block groups is constant
+    
+    Commit 1c6bd7173d66b3 introduced a regression where an online resize
+    operation which did not change the number of block groups would fail,
+    i.e:
+    
+            mke2fs -t /dev/vdc 60000
+            mount /dev/vdc
+            resize2fs /dev/vdc 60001
+    
+    This was due to a bug in the logic regarding when to try converting
+    the filesystem to use meta_bg.
+    
+    Also fix up a number of other minor issues with the online resizing
+    code: (a) Fix a sparse warning; (b) only check to make sure the device
+    is large enough once, instead of multiple times through the resize
+    loop.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 3c9367b9bebd..ee985ca05100 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -1772,23 +1772,18 @@ static int ext4_convert_meta_bg(struct super_block *sb, struct inode *inode)
+ 	handle_t *handle;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	struct ext4_super_block *es = sbi->s_es;
+-	struct ext4_inode_info *ei = 0;
++	struct ext4_inode_info *ei = EXT4_I(inode);
+ 	ext4_fsblk_t nr;
+ 	int i, ret, err = 0;
+ 	int credits = 1;
+ 
+ 	ext4_msg(sb, KERN_INFO, "Converting file system to meta_bg");
+-	if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_RESIZE_INODE)) {
++	if (inode) {
+ 		if (es->s_reserved_gdt_blocks) {
+ 			ext4_error(sb, "Unexpected non-zero "
+ 				   "s_reserved_gdt_blocks");
+ 			return -EPERM;
+ 		}
+-		if (!inode) {
+-			ext4_error(sb, "Unexpected NULL resize_inode");
+-			return -EPERM;
+-		}
+-		ei = EXT4_I(inode);
+ 
+ 		/* Do a quick sanity check of the resize inode */
+ 		if (inode->i_blocks != 1 << (inode->i_blkbits - 9))
+@@ -1873,12 +1868,19 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
+ 	int err = 0, flexbg_size = 1 << sbi->s_log_groups_per_flex;
+ 	int meta_bg;
+ 
++	/* See if the device is actually as big as what was requested */
++	bh = sb_bread(sb, n_blocks_count - 1);
++	if (!bh) {
++		ext4_warning(sb, "can't read last block, resize aborted");
++		return -ENOSPC;
++	}
++	brelse(bh);
++
+ retry:
+ 	o_blocks_count = ext4_blocks_count(es);
+ 
+-	if (test_opt(sb, DEBUG))
+-		ext4_msg(sb, KERN_DEBUG, "resizing filesystem from %llu "
+-		       "to %llu blocks", o_blocks_count, n_blocks_count);
++	ext4_msg(sb, KERN_INFO, "resizing filesystem from %llu "
++		 "to %llu blocks", o_blocks_count, n_blocks_count);
+ 
+ 	if (n_blocks_count < o_blocks_count) {
+ 		/* On-line shrinking not supported */
+@@ -1922,7 +1924,7 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
+ 		}
+ 	}
+ 
+-	if ((!resize_inode && !meta_bg) || n_group == o_group) {
++	if ((!resize_inode && !meta_bg) || n_blocks_count == o_blocks_count) {
+ 		err = ext4_convert_meta_bg(sb, resize_inode);
+ 		if (err)
+ 			goto out;
+@@ -1937,14 +1939,6 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
+ 		}
+ 	}
+ 
+-	/* See if the device is actually as big as what was requested */
+-	bh = sb_bread(sb, n_blocks_count - 1);
+-	if (!bh) {
+-		ext4_warning(sb, "can't read last block, resize aborted");
+-		return -ENOSPC;
+-	}
+-	brelse(bh);
+-
+ 	/* extend the last group */
+ 	if (n_group == o_group)
+ 		add = n_blocks_count - o_blocks_count;
+@@ -2005,8 +1999,6 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
+ 		free_flex_gd(flex_gd);
+ 	if (resize_inode != NULL)
+ 		iput(resize_inode);
+-	if (test_opt(sb, DEBUG))
+-		ext4_msg(sb, KERN_DEBUG, "resized filesystem to %llu",
+-			 n_blocks_count);
++	ext4_msg(sb, KERN_INFO, "resized filesystem to %llu", n_blocks_count);
+ 	return err;
+ }

commit b5e2368baeddf401bf3da9e364fc1c96676279cd
+Author: Theodore Ts'o 
+Date:   Tue Sep 18 13:33:44 2012 -0400
+
+    ext4: re-enable -o discard functionality in no-journal mode
+    
+    This is a revert of commit b56ff9d397ce, which removed the call to
+    ext4_issue_discard() to fix a BUG reported because
+    ext4_issue_discard() was being called from inside a block group
+    spinlock.  As it turns out this bug had already been fixed by Lukas
+    Czerner in commit 53fdcf992d61 by the simple expedient of moving when
+    we call ext4_issue_discard() outside the spinlock.
+    
+    So it should be safe to re-enable this functionality, which I tested
+    by putting an BUG_ON(in_atomic) just after the restored callsite to
+    ext4_issue_discard().
+    
+    Addresses-Google-Bug: #6750518
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Anatol Pomozov 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 2102c20f7e98..2c7c082b8169 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -4656,6 +4656,8 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 		 * with group lock held. generate_buddy look at
+ 		 * them with group lock_held
+ 		 */
++		if (test_opt(sb, DISCARD))
++			ext4_issue_discard(sb, block_group, bit, count);
+ 		ext4_lock_group(sb, block_group);
+ 		mb_clear_bits(bitmap_bh->b_data, bit, count_clusters);
+ 		mb_free_blocks(inode, &e4b, bit, count_clusters);

commit bc0b75f77a944b482293972eb8fd5c88c576eb46
+Author: Theodore Ts'o 
+Date:   Mon Sep 17 22:54:36 2012 -0400
+
+    ext4: do not enable delalloc by default for ext2
+    
+    Signed-off-by: Brian Foster 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index eb7722ab771c..e6784b3276be 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3411,7 +3411,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	 * enable delayed allocation by default
+ 	 * Use -o nodelalloc to turn it off
+ 	 */
+-	if (!IS_EXT3_SB(sb) &&
++	if (!IS_EXT3_SB(sb) && !IS_EXT2_SB(sb) &&
+ 	    ((def_mount_opts & EXT4_DEFM_NODELALLOC) == 0))
+ 		set_opt(sb, DELALLOC);
+ 

commit 5e7bbef19c8385895cb21c41a88bd937902e6316
+Author: Theodore Ts'o 
+Date:   Thu Sep 13 12:11:40 2012 -0400
+
+    ext4: advertise the fact that the kernel supports meta_bg resizing
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index b8de488889d6..eb7722ab771c 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2585,10 +2585,12 @@ static struct attribute *ext4_attrs[] = {
+ /* Features this copy of ext4 supports */
+ EXT4_INFO_ATTR(lazy_itable_init);
+ EXT4_INFO_ATTR(batched_discard);
++EXT4_INFO_ATTR(meta_bg_resize);
+ 
+ static struct attribute *ext4_feat_attrs[] = {
+ 	ATTR_LIST(lazy_itable_init),
+ 	ATTR_LIST(batched_discard),
++	ATTR_LIST(meta_bg_resize),
+ 	NULL,
+ };
+ 

commit 4da4a56e4f83f52d71e2c5fa86fb1ad77be09753
+Author: Theodore Ts'o 
+Date:   Thu Sep 13 10:24:21 2012 -0400
+
+    ext4: log a resize update to the console every 10 seconds
+    
+    For very long online resizes, a periodic update to the console log is
+    helpful for debugging and for progress reporting.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 5932ab5ca53f..3c9367b9bebd 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -1869,6 +1869,7 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
+ 	ext4_group_t n_group;
+ 	ext4_fsblk_t o_blocks_count;
+ 	ext4_fsblk_t n_blocks_count_retry = 0;
++	unsigned long last_update_time = 0;
+ 	int err = 0, flexbg_size = 1 << sbi->s_log_groups_per_flex;
+ 	int meta_bg;
+ 
+@@ -1977,6 +1978,13 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
+ 	 */
+ 	while (ext4_setup_next_flex_gd(sb, flex_gd, n_blocks_count,
+ 					      flexbg_size)) {
++		if (jiffies - last_update_time > HZ * 10) {
++			if (last_update_time)
++				ext4_msg(sb, KERN_INFO,
++					 "resized to %llu blocks",
++					 ext4_blocks_count(es));
++			last_update_time = jiffies;
++		}
+ 		if (ext4_alloc_group_tables(sb, flex_gd, flexbg_size) != 0)
+ 			break;
+ 		err = ext4_flex_group_add(sb, resize_inode, flex_gd);

commit 1c6bd7173d66b3dfdefcedb38cabc1fb03997509
+Author: Theodore Ts'o 
+Date:   Thu Sep 13 10:19:24 2012 -0400
+
+    ext4: convert file system to meta_bg if needed during resizing
+    
+    If we have run out of reserved gdt blocks, then clear the resize_inode
+    feature and enable the meta_bg feature, so that we can continue
+    resizing the file system seamlessly.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index a5be589c85bc..5932ab5ca53f 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -1756,6 +1756,99 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
+ 	return err;
+ } /* ext4_group_extend */
+ 
++
++static int num_desc_blocks(struct super_block *sb, ext4_group_t groups)
++{
++	return (groups + EXT4_DESC_PER_BLOCK(sb) - 1) / EXT4_DESC_PER_BLOCK(sb);
++}
++
++/*
++ * Release the resize inode and drop the resize_inode feature if there
++ * are no more reserved gdt blocks, and then convert the file system
++ * to enable meta_bg
++ */
++static int ext4_convert_meta_bg(struct super_block *sb, struct inode *inode)
++{
++	handle_t *handle;
++	struct ext4_sb_info *sbi = EXT4_SB(sb);
++	struct ext4_super_block *es = sbi->s_es;
++	struct ext4_inode_info *ei = 0;
++	ext4_fsblk_t nr;
++	int i, ret, err = 0;
++	int credits = 1;
++
++	ext4_msg(sb, KERN_INFO, "Converting file system to meta_bg");
++	if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_RESIZE_INODE)) {
++		if (es->s_reserved_gdt_blocks) {
++			ext4_error(sb, "Unexpected non-zero "
++				   "s_reserved_gdt_blocks");
++			return -EPERM;
++		}
++		if (!inode) {
++			ext4_error(sb, "Unexpected NULL resize_inode");
++			return -EPERM;
++		}
++		ei = EXT4_I(inode);
++
++		/* Do a quick sanity check of the resize inode */
++		if (inode->i_blocks != 1 << (inode->i_blkbits - 9))
++			goto invalid_resize_inode;
++		for (i = 0; i < EXT4_N_BLOCKS; i++) {
++			if (i == EXT4_DIND_BLOCK) {
++				if (ei->i_data[i])
++					continue;
++				else
++					goto invalid_resize_inode;
++			}
++			if (ei->i_data[i])
++				goto invalid_resize_inode;
++		}
++		credits += 3;	/* block bitmap, bg descriptor, resize inode */
++	}
++
++	handle = ext4_journal_start_sb(sb, credits);
++	if (IS_ERR(handle))
++		return PTR_ERR(handle);
++
++	err = ext4_journal_get_write_access(handle, sbi->s_sbh);
++	if (err)
++		goto errout;
++
++	EXT4_CLEAR_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_RESIZE_INODE);
++	EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG);
++	sbi->s_es->s_first_meta_bg =
++		cpu_to_le32(num_desc_blocks(sb, sbi->s_groups_count));
++
++	err = ext4_handle_dirty_super(handle, sb);
++	if (err) {
++		ext4_std_error(sb, err);
++		goto errout;
++	}
++
++	if (inode) {
++		nr = le32_to_cpu(ei->i_data[EXT4_DIND_BLOCK]);
++		ext4_free_blocks(handle, inode, NULL, nr, 1,
++				 EXT4_FREE_BLOCKS_METADATA |
++				 EXT4_FREE_BLOCKS_FORGET);
++		ei->i_data[EXT4_DIND_BLOCK] = 0;
++		inode->i_blocks = 0;
++
++		err = ext4_mark_inode_dirty(handle, inode);
++		if (err)
++			ext4_std_error(sb, err);
++	}
++
++errout:
++	ret = ext4_journal_stop(handle);
++	if (!err)
++		err = ret;
++	return ret;
++
++invalid_resize_inode:
++	ext4_error(sb, "corrupted/inconsistent resize inode");
++	return -EINVAL;
++}
++
+ /*
+  * ext4_resize_fs() resizes a fs to new size specified by @n_blocks_count
+  *
+@@ -1772,13 +1865,14 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
+ 	ext4_grpblk_t add, offset;
+ 	unsigned long n_desc_blocks;
+ 	unsigned long o_desc_blocks;
+-	unsigned long desc_blocks;
+ 	ext4_group_t o_group;
+ 	ext4_group_t n_group;
+ 	ext4_fsblk_t o_blocks_count;
++	ext4_fsblk_t n_blocks_count_retry = 0;
+ 	int err = 0, flexbg_size = 1 << sbi->s_log_groups_per_flex;
+ 	int meta_bg;
+ 
++retry:
+ 	o_blocks_count = ext4_blocks_count(es);
+ 
+ 	if (test_opt(sb, DEBUG))
+@@ -1798,11 +1892,8 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
+ 	ext4_get_group_no_and_offset(sb, n_blocks_count - 1, &n_group, &offset);
+ 	ext4_get_group_no_and_offset(sb, o_blocks_count - 1, &o_group, &offset);
+ 
+-	n_desc_blocks = (n_group + EXT4_DESC_PER_BLOCK(sb)) /
+-			 EXT4_DESC_PER_BLOCK(sb);
+-	o_desc_blocks = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) /
+-			 EXT4_DESC_PER_BLOCK(sb);
+-	desc_blocks = n_desc_blocks - o_desc_blocks;
++	n_desc_blocks = num_desc_blocks(sb, n_group + 1);
++	o_desc_blocks = num_desc_blocks(sb, sbi->s_groups_count);
+ 
+ 	meta_bg = EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG);
+ 
+@@ -1812,20 +1903,37 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
+ 				   "simultaneously");
+ 			return -EINVAL;
+ 		}
+-		if (le16_to_cpu(es->s_reserved_gdt_blocks) < desc_blocks) {
+-			ext4_warning(sb,
+-				     "No reserved GDT blocks, can't resize");
+-			return -EPERM;
++		if (n_desc_blocks > o_desc_blocks +
++		    le16_to_cpu(es->s_reserved_gdt_blocks)) {
++			n_blocks_count_retry = n_blocks_count;
++			n_desc_blocks = o_desc_blocks +
++				le16_to_cpu(es->s_reserved_gdt_blocks);
++			n_group = n_desc_blocks * EXT4_DESC_PER_BLOCK(sb);
++			n_blocks_count = n_group * EXT4_BLOCKS_PER_GROUP(sb);
++			n_group--; /* set to last group number */
+ 		}
+-		resize_inode = ext4_iget(sb, EXT4_RESIZE_INO);
++
++		if (!resize_inode)
++			resize_inode = ext4_iget(sb, EXT4_RESIZE_INO);
+ 		if (IS_ERR(resize_inode)) {
+ 			ext4_warning(sb, "Error opening resize inode");
+ 			return PTR_ERR(resize_inode);
+ 		}
+-	} else if (!meta_bg) {
+-		ext4_warning(sb, "File system features do not permit "
+-			     "online resize");
+-		return -EPERM;
++	}
++
++	if ((!resize_inode && !meta_bg) || n_group == o_group) {
++		err = ext4_convert_meta_bg(sb, resize_inode);
++		if (err)
++			goto out;
++		if (resize_inode) {
++			iput(resize_inode);
++			resize_inode = NULL;
++		}
++		if (n_blocks_count_retry) {
++			n_blocks_count = n_blocks_count_retry;
++			n_blocks_count_retry = 0;
++			goto retry;
++		}
+ 	}
+ 
+ 	/* See if the device is actually as big as what was requested */
+@@ -1876,13 +1984,21 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
+ 			break;
+ 	}
+ 
++	if (!err && n_blocks_count_retry) {
++		n_blocks_count = n_blocks_count_retry;
++		n_blocks_count_retry = 0;
++		free_flex_gd(flex_gd);
++		flex_gd = NULL;
++		goto retry;
++	}
++
+ out:
+ 	if (flex_gd)
+ 		free_flex_gd(flex_gd);
+ 	if (resize_inode != NULL)
+ 		iput(resize_inode);
+ 	if (test_opt(sb, DEBUG))
+-		ext4_msg(sb, KERN_DEBUG, "resized filesystem from %llu "
+-		       "upto %llu blocks", o_blocks_count, n_blocks_count);
++		ext4_msg(sb, KERN_DEBUG, "resized filesystem to %llu",
++			 n_blocks_count);
+ 	return err;
+ }

commit 93f9052643409c13b3b5f76833865087351f55b8
+Author: Theodore Ts'o 
+Date:   Wed Sep 12 14:32:42 2012 -0400
+
+    ext4: set bg_itable_unused when resizing
+    
+    Set bg_itable_unused for file systems that have uninit_bg enabled.
+    This will speed up the first e2fsck run after the file system is
+    resized.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 7adc08854588..a5be589c85bc 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -1268,6 +1268,9 @@ static int ext4_setup_new_descs(handle_t *handle, struct super_block *sb,
+ 		ext4_free_group_clusters_set(sb, gdp,
+ 					     EXT4_B2C(sbi, group_data->free_blocks_count));
+ 		ext4_free_inodes_set(sb, gdp, EXT4_INODES_PER_GROUP(sb));
++		if (ext4_has_group_desc_csum(sb))
++			ext4_itable_unused_set(sb, gdp,
++					       EXT4_INODES_PER_GROUP(sb));
+ 		gdp->bg_flags = cpu_to_le16(*bg_flags);
+ 		ext4_group_desc_csum_set(sb, group, gdp);
+ 

commit 28623c2f5b0dca3c3ea34fd6108940661352e276
+Author: Theodore Ts'o 
+Date:   Wed Sep 5 01:31:50 2012 -0400
+
+    ext4: grow the s_group_info array as needed
+    
+    Previously we allocated the s_group_info array with enough space for
+    any future possible growth of the file system via online resize.  This
+    is unfortunate because it wastes memory, and it doesn't work for the
+    meta_bg scheme, since there is no limit based on the number of
+    reserved gdt blocks.  So add the code to grow the s_group_info array
+    as needed.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 464cff711ed6..8b6902c4d7be 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1233,6 +1233,7 @@ struct ext4_sb_info {
+ 	spinlock_t s_md_lock;
+ 	unsigned short *s_mb_offsets;
+ 	unsigned int *s_mb_maxs;
++	unsigned int s_group_info_size;
+ 
+ 	/* tunables */
+ 	unsigned long s_stripe;
+@@ -1971,6 +1972,8 @@ extern void ext4_exit_mballoc(void);
+ extern void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 			     struct buffer_head *bh, ext4_fsblk_t block,
+ 			     unsigned long count, int flags);
++extern int ext4_mb_alloc_groupinfo(struct super_block *sb,
++				   ext4_group_t ngroups);
+ extern int ext4_mb_add_groupinfo(struct super_block *sb,
+ 		ext4_group_t i, struct ext4_group_desc *desc);
+ extern int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 6873571c9f44..2102c20f7e98 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -24,6 +24,7 @@
+ #include "ext4_jbd2.h"
+ #include "mballoc.h"
+ #include 
++#include 
+ #include 
+ #include 
+ 
+@@ -2163,6 +2164,39 @@ static struct kmem_cache *get_groupinfo_cache(int blocksize_bits)
+ 	return cachep;
+ }
+ 
++/*
++ * Allocate the top-level s_group_info array for the specified number
++ * of groups
++ */
++int ext4_mb_alloc_groupinfo(struct super_block *sb, ext4_group_t ngroups)
++{
++	struct ext4_sb_info *sbi = EXT4_SB(sb);
++	unsigned size;
++	struct ext4_group_info ***new_groupinfo;
++
++	size = (ngroups + EXT4_DESC_PER_BLOCK(sb) - 1) >>
++		EXT4_DESC_PER_BLOCK_BITS(sb);
++	if (size <= sbi->s_group_info_size)
++		return 0;
++
++	size = roundup_pow_of_two(sizeof(*sbi->s_group_info) * size);
++	new_groupinfo = ext4_kvzalloc(size, GFP_KERNEL);
++	if (!new_groupinfo) {
++		ext4_msg(sb, KERN_ERR, "can't allocate buddy meta group");
++		return -ENOMEM;
++	}
++	if (sbi->s_group_info) {
++		memcpy(new_groupinfo, sbi->s_group_info,
++		       sbi->s_group_info_size * sizeof(*sbi->s_group_info));
++		ext4_kvfree(sbi->s_group_info);
++	}
++	sbi->s_group_info = new_groupinfo;
++	sbi->s_group_info_size = size / sizeof(*sbi->s_group_info);
++	ext4_debug("allocated s_groupinfo array for %d meta_bg's\n", 
++		   sbi->s_group_info_size);
++	return 0;
++}
++
+ /* Create and initialize ext4_group_info data for the given group. */
+ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group,
+ 			  struct ext4_group_desc *desc)
+@@ -2252,49 +2286,14 @@ static int ext4_mb_init_backend(struct super_block *sb)
+ 	ext4_group_t ngroups = ext4_get_groups_count(sb);
+ 	ext4_group_t i;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-	struct ext4_super_block *es = sbi->s_es;
+-	int num_meta_group_infos;
+-	int num_meta_group_infos_max;
+-	int array_size;
++	int err;
+ 	struct ext4_group_desc *desc;
+ 	struct kmem_cache *cachep;
+ 
+-	/* This is the number of blocks used by GDT */
+-	num_meta_group_infos = (ngroups + EXT4_DESC_PER_BLOCK(sb) -
+-				1) >> EXT4_DESC_PER_BLOCK_BITS(sb);
+-
+-	/*
+-	 * This is the total number of blocks used by GDT including
+-	 * the number of reserved blocks for GDT.
+-	 * The s_group_info array is allocated with this value
+-	 * to allow a clean online resize without a complex
+-	 * manipulation of pointer.
+-	 * The drawback is the unused memory when no resize
+-	 * occurs but it's very low in terms of pages
+-	 * (see comments below)
+-	 * Need to handle this properly when META_BG resizing is allowed
+-	 */
+-	num_meta_group_infos_max = num_meta_group_infos +
+-				le16_to_cpu(es->s_reserved_gdt_blocks);
++	err = ext4_mb_alloc_groupinfo(sb, ngroups);
++	if (err)
++		return err;
+ 
+-	/*
+-	 * array_size is the size of s_group_info array. We round it
+-	 * to the next power of two because this approximation is done
+-	 * internally by kmalloc so we can have some more memory
+-	 * for free here (e.g. may be used for META_BG resize).
+-	 */
+-	array_size = 1;
+-	while (array_size < sizeof(*sbi->s_group_info) *
+-	       num_meta_group_infos_max)
+-		array_size = array_size << 1;
+-	/* An 8TB filesystem with 64-bit pointers requires a 4096 byte
+-	 * kmalloc. A 128kb malloc should suffice for a 256TB filesystem.
+-	 * So a two level scheme suffices for now. */
+-	sbi->s_group_info = ext4_kvzalloc(array_size, GFP_KERNEL);
+-	if (sbi->s_group_info == NULL) {
+-		ext4_msg(sb, KERN_ERR, "can't allocate buddy meta group");
+-		return -ENOMEM;
+-	}
+ 	sbi->s_buddy_cache = new_inode(sb);
+ 	if (sbi->s_buddy_cache == NULL) {
+ 		ext4_msg(sb, KERN_ERR, "can't get new inode");
+@@ -2322,7 +2321,7 @@ static int ext4_mb_init_backend(struct super_block *sb)
+ 	cachep = get_groupinfo_cache(sb->s_blocksize_bits);
+ 	while (i-- > 0)
+ 		kmem_cache_free(cachep, ext4_get_group_info(sb, i));
+-	i = num_meta_group_infos;
++	i = sbi->s_group_info_size;
+ 	while (i-- > 0)
+ 		kfree(sbi->s_group_info[i]);
+ 	iput(sbi->s_buddy_cache);
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 3f5c67bf13a2..f288933bf4c0 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -1507,6 +1507,10 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
+ 	if (err)
+ 		return err;
+ 
++	err = ext4_mb_alloc_groupinfo(sb, input->group + 1);
++	if (err)
++		goto out;
++
+ 	flex_gd.count = 1;
+ 	flex_gd.groups = input;
+ 	flex_gd.bg_flags = &bg_flags;
+@@ -1732,6 +1736,10 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
+ 	if (err)
+ 		return err;
+ 
++	err = ext4_mb_alloc_groupinfo(sb, n_group + 1);
++	if (err)
++		goto out;
++
+ 	flex_gd = alloc_flex_gd(flexbg_size);
+ 	if (flex_gd == NULL) {
+ 		err = -ENOMEM;

commit 117fff10d7f140e12dd43df20d3f9fda80577460
+Author: Theodore Ts'o 
+Date:   Wed Sep 5 01:29:50 2012 -0400
+
+    ext4: grow the s_flex_groups array as needed when resizing
+    
+    Previously, we allocated the s_flex_groups array to the maximum size
+    that the file system could be resized.  There was two problems with
+    this approach.  First, it wasted memory in the common case where the
+    file system was not resized.  Secondly, once we start allowing online
+    resizing using the meta_bg scheme, there is no maximum size that the
+    file system can be resized.  So instead, we need to grow the
+    s_flex_groups at inline resize time.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 0df5ee102b61..464cff711ed6 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1276,6 +1276,7 @@ struct ext4_sb_info {
+ 
+ 	unsigned int s_log_groups_per_flex;
+ 	struct flex_groups *s_flex_groups;
++	ext4_group_t s_flex_groups_allocated;
+ 
+ 	/* workqueue for dio unwritten */
+ 	struct workqueue_struct *dio_unwritten_wq;
+@@ -2055,6 +2056,8 @@ extern void ext4_superblock_csum_set(struct super_block *sb,
+ extern void *ext4_kvmalloc(size_t size, gfp_t flags);
+ extern void *ext4_kvzalloc(size_t size, gfp_t flags);
+ extern void ext4_kvfree(void *ptr);
++extern int ext4_alloc_flex_bg_array(struct super_block *sb,
++				    ext4_group_t ngroup);
+ extern __printf(4, 5)
+ void __ext4_error(struct super_block *, const char *, unsigned int,
+ 		  const char *, ...);
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 365d800ff8c1..3f5c67bf13a2 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -1503,6 +1503,10 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
+ 	if (err)
+ 		goto out;
+ 
++	err = ext4_alloc_flex_bg_array(sb, input->group + 1);
++	if (err)
++		return err;
++
+ 	flex_gd.count = 1;
+ 	flex_gd.groups = input;
+ 	flex_gd.bg_flags = &bg_flags;
+@@ -1662,7 +1666,7 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
+ 	unsigned long n_desc_blocks;
+ 	unsigned long o_desc_blocks;
+ 	unsigned long desc_blocks;
+-	int err = 0, flexbg_size = 1;
++	int err = 0, flexbg_size = 1 << sbi->s_log_groups_per_flex;
+ 
+ 	o_blocks_count = ext4_blocks_count(es);
+ 
+@@ -1721,13 +1725,13 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
+ 			goto out;
+ 	}
+ 
+-	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG) &&
+-	    es->s_log_groups_per_flex)
+-		flexbg_size = 1 << es->s_log_groups_per_flex;
+-
+ 	if (ext4_blocks_count(es) == n_blocks_count)
+ 		goto out;
+ 
++	err = ext4_alloc_flex_bg_array(sb, n_group + 1);
++	if (err)
++		return err;
++
+ 	flex_gd = alloc_flex_gd(flexbg_size);
+ 	if (flex_gd == NULL) {
+ 		err = -ENOMEM;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index b875ff555865..b8de488889d6 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1925,15 +1925,45 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
+ 	return res;
+ }
+ 
++int ext4_alloc_flex_bg_array(struct super_block *sb, ext4_group_t ngroup)
++{
++	struct ext4_sb_info *sbi = EXT4_SB(sb);
++	struct flex_groups *new_groups;
++	int size;
++
++	if (!sbi->s_log_groups_per_flex)
++		return 0;
++
++	size = ext4_flex_group(sbi, ngroup - 1) + 1;
++	if (size <= sbi->s_flex_groups_allocated)
++		return 0;
++
++	size = roundup_pow_of_two(size * sizeof(struct flex_groups));
++	new_groups = ext4_kvzalloc(size, GFP_KERNEL);
++	if (!new_groups) {
++		ext4_msg(sb, KERN_ERR, "not enough memory for %d flex groups",
++			 size / (int) sizeof(struct flex_groups));
++		return -ENOMEM;
++	}
++
++	if (sbi->s_flex_groups) {
++		memcpy(new_groups, sbi->s_flex_groups,
++		       (sbi->s_flex_groups_allocated *
++			sizeof(struct flex_groups)));
++		ext4_kvfree(sbi->s_flex_groups);
++	}
++	sbi->s_flex_groups = new_groups;
++	sbi->s_flex_groups_allocated = size / sizeof(struct flex_groups);
++	return 0;
++}
++
+ static int ext4_fill_flex_info(struct super_block *sb)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	struct ext4_group_desc *gdp = NULL;
+-	ext4_group_t flex_group_count;
+ 	ext4_group_t flex_group;
+ 	unsigned int groups_per_flex = 0;
+-	size_t size;
+-	int i;
++	int i, err;
+ 
+ 	sbi->s_log_groups_per_flex = sbi->s_es->s_log_groups_per_flex;
+ 	if (sbi->s_log_groups_per_flex < 1 || sbi->s_log_groups_per_flex > 31) {
+@@ -1942,17 +1972,9 @@ static int ext4_fill_flex_info(struct super_block *sb)
+ 	}
+ 	groups_per_flex = 1 << sbi->s_log_groups_per_flex;
+ 
+-	/* We allocate both existing and potentially added groups */
+-	flex_group_count = ((sbi->s_groups_count + groups_per_flex - 1) +
+-			((le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) + 1) <<
+-			      EXT4_DESC_PER_BLOCK_BITS(sb))) / groups_per_flex;
+-	size = flex_group_count * sizeof(struct flex_groups);
+-	sbi->s_flex_groups = ext4_kvzalloc(size, GFP_KERNEL);
+-	if (sbi->s_flex_groups == NULL) {
+-		ext4_msg(sb, KERN_ERR, "not enough memory for %u flex groups",
+-			 flex_group_count);
++	err = ext4_alloc_flex_bg_array(sb, sbi->s_groups_count);
++	if (err)
+ 		goto failed;
+-	}
+ 
+ 	for (i = 0; i < sbi->s_groups_count; i++) {
+ 		gdp = ext4_get_group_desc(sb, i, NULL);

commit 07724f98978ad39386a3996a4e1b6780489a4dda
+Author: Theodore Ts'o 
+Date:   Fri Aug 17 19:08:42 2012 -0400
+
+    ext4: drop lock_super()/unlock_super()
+    
+    We don't need lock_super()/unlock_super() any more, since the places
+    where it is used, we are protected by the s_umount r/w semaphore.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Marco Stornelli 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 3ab798d00f02..bae4124e1473 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -861,7 +861,6 @@ static void ext4_put_super(struct super_block *sb)
+ 	flush_workqueue(sbi->dio_unwritten_wq);
+ 	destroy_workqueue(sbi->dio_unwritten_wq);
+ 
+-	lock_super(sb);
+ 	if (sbi->s_journal) {
+ 		err = jbd2_journal_destroy(sbi->s_journal);
+ 		sbi->s_journal = NULL;
+@@ -928,7 +927,6 @@ static void ext4_put_super(struct super_block *sb)
+ 	 * Now that we are completely done shutting down the
+ 	 * superblock, we need to actually destroy the kobject.
+ 	 */
+-	unlock_super(sb);
+ 	kobject_put(&sbi->s_kobj);
+ 	wait_for_completion(&sbi->s_kobj_unregister);
+ 	if (sbi->s_chksum_driver)
+@@ -4535,11 +4533,9 @@ static int ext4_unfreeze(struct super_block *sb)
+ 	if (sb->s_flags & MS_RDONLY)
+ 		return 0;
+ 
+-	lock_super(sb);
+ 	/* Reset the needs_recovery flag before the fs is unlocked. */
+ 	EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+ 	ext4_commit_super(sb, 1);
+-	unlock_super(sb);
+ 	return 0;
+ }
+ 
+@@ -4575,7 +4571,6 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 	char *orig_data = kstrdup(data, GFP_KERNEL);
+ 
+ 	/* Store the original options */
+-	lock_super(sb);
+ 	old_sb_flags = sb->s_flags;
+ 	old_opts.s_mount_opt = sbi->s_mount_opt;
+ 	old_opts.s_mount_opt2 = sbi->s_mount_opt2;
+@@ -4717,7 +4712,6 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 	if (sbi->s_journal == NULL)
+ 		ext4_commit_super(sb, 1);
+ 
+-	unlock_super(sb);
+ #ifdef CONFIG_QUOTA
+ 	/* Release old quota file names */
+ 	for (i = 0; i < MAXQUOTAS; i++)
+@@ -4730,10 +4724,8 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 		else if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
+ 					EXT4_FEATURE_RO_COMPAT_QUOTA)) {
+ 			err = ext4_enable_quotas(sb);
+-			if (err) {
+-				lock_super(sb);
++			if (err)
+ 				goto restore_opts;
+-			}
+ 		}
+ 	}
+ #endif
+@@ -4760,7 +4752,6 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 		sbi->s_qf_names[i] = old_opts.s_qf_names[i];
+ 	}
+ #endif
+-	unlock_super(sb);
+ 	kfree(orig_data);
+ 	return err;
+ }

commit 0e376b1e3ccedee49cb8cc6b652fbc1e7c15eeef
+Author: Theodore Ts'o 
+Date:   Fri Aug 17 10:04:17 2012 -0400
+
+    ext4: return an error if kset_create_and_add fails in ext4_init_fs()
+    
+    In the very unlikely case that kset_create_and_add() fails when the
+    ext4.ko module is being loaded (or during kernel startup) set err so
+    that it's clear that the module load failed.
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=27912
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 0423e2e7f615..3ab798d00f02 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -5285,8 +5285,10 @@ static int __init ext4_init_fs(void)
+ 	if (err)
+ 		goto out6;
+ 	ext4_kset = kset_create_and_add("ext4", NULL, fs_kobj);
+-	if (!ext4_kset)
++	if (!ext4_kset) {
++		err = -ENOMEM;
+ 		goto out5;
++	}
+ 	ext4_proc_root = proc_mkdir("fs/ext4", NULL);
+ 
+ 	err = ext4_init_feat_adverts();

commit a4a39040e9dacb5fa28b7ee7f842237ee534e7bf
+Author: Theodore Ts'o 
+Date:   Fri Aug 17 09:58:17 2012 -0400
+
+    ext4: check return value of blkdev_issue_flush()
+    
+    blkdev_issue_flush() can fail; make sure the error gets properly
+    propagated.
+    
+    This is a port of the equivalent ext3 patch from commit 44f4f729e7a1.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
+index 2a1dcea4f12e..323eb15c2d94 100644
+--- a/fs/ext4/fsync.c
++++ b/fs/ext4/fsync.c
+@@ -203,7 +203,7 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
+ 	struct inode *inode = file->f_mapping->host;
+ 	struct ext4_inode_info *ei = EXT4_I(inode);
+ 	journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
+-	int ret;
++	int ret, err;
+ 	tid_t commit_tid;
+ 	bool needs_barrier = false;
+ 
+@@ -255,8 +255,11 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
+ 		needs_barrier = true;
+ 	jbd2_log_start_commit(journal, commit_tid);
+ 	ret = jbd2_log_wait_commit(journal, commit_tid);
+-	if (needs_barrier)
+-		blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
++	if (needs_barrier) {
++		err = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
++		if (!ret)
++			ret = err;
++	}
+  out:
+ 	mutex_unlock(&inode->i_mutex);
+ 	trace_ext4_sync_file_exit(inode, ret);

commit 316e4cfd0b0b4ce846fd0fbda2deebcffbd3e440
+Author: Theodore Ts'o 
+Date:   Fri Aug 17 09:56:17 2012 -0400
+
+    jbd2: check return value of blkdev_issue_flush()
+    
+    blkdev_issue_flush() can fail; make sure the error gets properly
+    propagated.
+    
+    This is a port of the equivalent jbd patch from commit 349ecd6a3c0e.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
+index 0131e4362534..626846bac32f 100644
+--- a/fs/jbd2/recovery.c
++++ b/fs/jbd2/recovery.c
+@@ -289,8 +289,11 @@ int jbd2_journal_recover(journal_t *journal)
+ 	if (!err)
+ 		err = err2;
+ 	/* Make sure all replayed data is on permanent storage */
+-	if (journal->j_flags & JBD2_BARRIER)
+-		blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL);
++	if (journal->j_flags & JBD2_BARRIER) {
++		err2 = blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL);
++		if (!err)
++			err = err2;
++	}
+ 	return err;
+ }
+ 

commit df981d03eeff7971ac7e6ff37000bfa702327ef1
+Author: Theodore Ts'o 
+Date:   Fri Aug 17 09:48:17 2012 -0400
+
+    ext4: add max_dir_size_kb mount option
+    
+    Very large directories can cause significant performance problems, or
+    perhaps even invoke the OOM killer, if the process is running in a
+    highly constrained memory environment (whether it is VM's with a small
+    amount of memory or in a small memory cgroup).
+    
+    So it is useful, in cloud server/data center environments, to be able
+    to set a filesystem-wide cap on the maximum size of a directory, to
+    ensure that directories never get larger than a sane size.  We do this
+    via a new mount option, max_dir_size_kb.  If there is an attempt to
+    grow the directory larger than max_dir_size_kb, the system call will
+    return ENOSPC instead.
+    
+    Google-Bug-Id: 6863013
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
+index 1b7f9acbcbbe..104322bf378c 100644
+--- a/Documentation/filesystems/ext4.txt
++++ b/Documentation/filesystems/ext4.txt
+@@ -375,6 +375,16 @@ dioread_nolock		locking. If the dioread_nolock option is specified
+ 			Because of the restrictions this options comprises
+ 			it is off by default (e.g. dioread_lock).
+ 
++max_dir_size_kb=n	This limits the size of directories so that any
++			attempt to expand them beyond the specified
++			limit in kilobytes will cause an ENOSPC error.
++			This is useful in memory constrained
++			environments, where a very large directory can
++			cause severe performance problems or even
++			provoke the Out Of Memory killer.  (For example,
++			if there is only 512mb memory available, a 176mb
++			directory may seriously cramp the system's style.)
++
+ i_version		Enable 64-bit inode version support. This option is
+ 			off by default.
+ 
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index c3411d4ce2da..7c0841ecde6c 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1243,6 +1243,7 @@ struct ext4_sb_info {
+ 	unsigned int s_mb_order2_reqs;
+ 	unsigned int s_mb_group_prealloc;
+ 	unsigned int s_max_writeback_mb_bump;
++	unsigned int s_max_dir_size_kb;
+ 	/* where last allocation was done - for stream allocation */
+ 	unsigned long s_mb_last_group;
+ 	unsigned long s_mb_last_start;
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 2a42cc04466f..7450ff01c3c4 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -55,6 +55,13 @@ static struct buffer_head *ext4_append(handle_t *handle,
+ {
+ 	struct buffer_head *bh;
+ 
++	if (unlikely(EXT4_SB(inode->i_sb)->s_max_dir_size_kb &&
++		     ((inode->i_size >> 10) >=
++		      EXT4_SB(inode->i_sb)->s_max_dir_size_kb))) {
++		*err = -ENOSPC;
++		return NULL;
++	}
++
+ 	*block = inode->i_size >> inode->i_sb->s_blocksize_bits;
+ 
+ 	bh = ext4_bread(handle, inode, *block, 1, err);
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 598498904035..5a97e590692d 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1230,6 +1230,7 @@ enum {
+ 	Opt_inode_readahead_blks, Opt_journal_ioprio,
+ 	Opt_dioread_nolock, Opt_dioread_lock,
+ 	Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable,
++	Opt_max_dir_size_kb,
+ };
+ 
+ static const match_table_t tokens = {
+@@ -1303,6 +1304,7 @@ static const match_table_t tokens = {
+ 	{Opt_init_itable, "init_itable=%u"},
+ 	{Opt_init_itable, "init_itable"},
+ 	{Opt_noinit_itable, "noinit_itable"},
++	{Opt_max_dir_size_kb, "max_dir_size_kb=%u"},
+ 	{Opt_removed, "check=none"},	/* mount option from ext2/3 */
+ 	{Opt_removed, "nocheck"},	/* mount option from ext2/3 */
+ 	{Opt_removed, "reservation"},	/* mount option from ext2/3 */
+@@ -1483,6 +1485,7 @@ static const struct mount_opts {
+ 	{Opt_jqfmt_vfsold, QFMT_VFS_OLD, MOPT_QFMT},
+ 	{Opt_jqfmt_vfsv0, QFMT_VFS_V0, MOPT_QFMT},
+ 	{Opt_jqfmt_vfsv1, QFMT_VFS_V1, MOPT_QFMT},
++	{Opt_max_dir_size_kb, 0, MOPT_GTE0},
+ 	{Opt_err, 0, 0}
+ };
+ 
+@@ -1598,6 +1601,8 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
+ 			if (!args->from)
+ 				arg = EXT4_DEF_LI_WAIT_MULT;
+ 			sbi->s_li_wait_mult = arg;
++		} else if (token == Opt_max_dir_size_kb) {
++			sbi->s_max_dir_size_kb = arg;
+ 		} else if (token == Opt_stripe) {
+ 			sbi->s_stripe = arg;
+ 		} else if (m->flags & MOPT_DATAJ) {
+@@ -1829,6 +1834,8 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb,
+ 	if (nodefs || (test_opt(sb, INIT_INODE_TABLE) &&
+ 		       (sbi->s_li_wait_mult != EXT4_DEF_LI_WAIT_MULT)))
+ 		SEQ_OPTS_PRINT("init_itable=%u", sbi->s_li_wait_mult);
++	if (nodefs || sbi->s_max_dir_size_kb)
++		SEQ_OPTS_PRINT("max_dir_size_kb=%u", sbi->s_max_dir_size_kb);
+ 
+ 	ext4_show_quota_options(seq, sb);
+ 	return 0;

commit 01fc48e8929e45e67527200017cff4e74e4ba054
+Author: Theodore Ts'o 
+Date:   Fri Aug 17 09:46:17 2012 -0400
+
+    ext4: don't load the block bitmap for block groups which have no space
+    
+    Add a short circuit check to ext4_mb_group_group() so that we don't
+    bother to load the block bitmap for a block group which does not have
+    any space available.  (Or which does not have enough space until we
+    are in desperation mode, i.e., when cr == 3.)
+    
+    Resolves-bug: https://bugzilla.kernel.org/show_bug.cgi?id=45741
+    Reported-by: mirek@me.com
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 8eae94771c45..3a57975b73cc 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -1862,6 +1862,12 @@ static int ext4_mb_good_group(struct ext4_allocation_context *ac,
+ 
+ 	BUG_ON(cr < 0 || cr >= 4);
+ 
++	free = grp->bb_free;
++	if (free == 0)
++		return 0;
++	if (cr <= 2 && free < ac->ac_g_ex.fe_len)
++		return 0;
++
+ 	/* We only do this if the grp has never been initialized */
+ 	if (unlikely(EXT4_MB_GRP_NEED_INIT(grp))) {
+ 		int ret = ext4_mb_init_group(ac->ac_sb, group);
+@@ -1869,10 +1875,7 @@ static int ext4_mb_good_group(struct ext4_allocation_context *ac,
+ 			return 0;
+ 	}
+ 
+-	free = grp->bb_free;
+ 	fragments = grp->bb_fragments;
+-	if (free == 0)
+-		return 0;
+ 	if (fragments == 0)
+ 		return 0;
+ 

commit ecb94f5fdf4b72547fca022421a9dca1672bddd4
+Author: Theodore Ts'o 
+Date:   Fri Aug 17 09:44:17 2012 -0400
+
+    ext4: collapse a single extent tree block into the inode if possible
+    
+    If an inode has more than 4 extents, but then later some of the
+    extents are merged together, we can optimize the file system by moving
+    the extents up into the inode, and discarding the extent tree block.
+    This is important, because if there are a large number of inodes with
+    an external extent tree blocks where the contents could fit in the
+    inode, this can significantly increase the fsck time of the file
+    system.
+    
+    Google-Bug-Id: 6801242
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index aabbb3f53683..e8755c21f4b9 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -1655,17 +1655,61 @@ static int ext4_ext_try_to_merge_right(struct inode *inode,
+ 	return merge_done;
+ }
+ 
++/*
++ * This function does a very simple check to see if we can collapse
++ * an extent tree with a single extent tree leaf block into the inode.
++ */
++static void ext4_ext_try_to_merge_up(handle_t *handle,
++				     struct inode *inode,
++				     struct ext4_ext_path *path)
++{
++	size_t s;
++	unsigned max_root = ext4_ext_space_root(inode, 0);
++	ext4_fsblk_t blk;
++
++	if ((path[0].p_depth != 1) ||
++	    (le16_to_cpu(path[0].p_hdr->eh_entries) != 1) ||
++	    (le16_to_cpu(path[1].p_hdr->eh_entries) > max_root))
++		return;
++
++	/*
++	 * We need to modify the block allocation bitmap and the block
++	 * group descriptor to release the extent tree block.  If we
++	 * can't get the journal credits, give up.
++	 */
++	if (ext4_journal_extend(handle, 2))
++		return;
++
++	/*
++	 * Copy the extent data up to the inode
++	 */
++	blk = ext4_idx_pblock(path[0].p_idx);
++	s = le16_to_cpu(path[1].p_hdr->eh_entries) *
++		sizeof(struct ext4_extent_idx);
++	s += sizeof(struct ext4_extent_header);
++
++	memcpy(path[0].p_hdr, path[1].p_hdr, s);
++	path[0].p_depth = 0;
++	path[0].p_ext = EXT_FIRST_EXTENT(path[0].p_hdr) +
++		(path[1].p_ext - EXT_FIRST_EXTENT(path[1].p_hdr));
++	path[0].p_hdr->eh_max = cpu_to_le16(max_root);
++
++	brelse(path[1].p_bh);
++	ext4_free_blocks(handle, inode, NULL, blk, 1,
++			 EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET);
++}
++
+ /*
+  * This function tries to merge the @ex extent to neighbours in the tree.
+  * return 1 if merge left else 0.
+  */
+-static int ext4_ext_try_to_merge(struct inode *inode,
++static void ext4_ext_try_to_merge(handle_t *handle,
++				  struct inode *inode,
+ 				  struct ext4_ext_path *path,
+ 				  struct ext4_extent *ex) {
+ 	struct ext4_extent_header *eh;
+ 	unsigned int depth;
+ 	int merge_done = 0;
+-	int ret = 0;
+ 
+ 	depth = ext_depth(inode);
+ 	BUG_ON(path[depth].p_hdr == NULL);
+@@ -1675,9 +1719,9 @@ static int ext4_ext_try_to_merge(struct inode *inode,
+ 		merge_done = ext4_ext_try_to_merge_right(inode, path, ex - 1);
+ 
+ 	if (!merge_done)
+-		ret = ext4_ext_try_to_merge_right(inode, path, ex);
++		(void) ext4_ext_try_to_merge_right(inode, path, ex);
+ 
+-	return ret;
++	ext4_ext_try_to_merge_up(handle, inode, path);
+ }
+ 
+ /*
+@@ -1893,7 +1937,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+ merge:
+ 	/* try to merge extents */
+ 	if (!(flag & EXT4_GET_BLOCKS_PRE_IO))
+-		ext4_ext_try_to_merge(inode, path, nearex);
++		ext4_ext_try_to_merge(handle, inode, path, nearex);
+ 
+ 
+ 	/* time to correct all indexes above */
+@@ -1901,7 +1945,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+ 	if (err)
+ 		goto cleanup;
+ 
+-	err = ext4_ext_dirty(handle, inode, path + depth);
++	err = ext4_ext_dirty(handle, inode, path + path->p_depth);
+ 
+ cleanup:
+ 	if (npath) {
+@@ -2924,9 +2968,9 @@ static int ext4_split_extent_at(handle_t *handle,
+ 			ext4_ext_mark_initialized(ex);
+ 
+ 		if (!(flags & EXT4_GET_BLOCKS_PRE_IO))
+-			ext4_ext_try_to_merge(inode, path, ex);
++			ext4_ext_try_to_merge(handle, inode, path, ex);
+ 
+-		err = ext4_ext_dirty(handle, inode, path + depth);
++		err = ext4_ext_dirty(handle, inode, path + path->p_depth);
+ 		goto out;
+ 	}
+ 
+@@ -2958,8 +3002,8 @@ static int ext4_split_extent_at(handle_t *handle,
+ 			goto fix_extent_len;
+ 		/* update the extent length and mark as initialized */
+ 		ex->ee_len = cpu_to_le16(ee_len);
+-		ext4_ext_try_to_merge(inode, path, ex);
+-		err = ext4_ext_dirty(handle, inode, path + depth);
++		ext4_ext_try_to_merge(handle, inode, path, ex);
++		err = ext4_ext_dirty(handle, inode, path + path->p_depth);
+ 		goto out;
+ 	} else if (err)
+ 		goto fix_extent_len;
+@@ -3191,8 +3235,8 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 		if (err)
+ 			goto out;
+ 		ext4_ext_mark_initialized(ex);
+-		ext4_ext_try_to_merge(inode, path, ex);
+-		err = ext4_ext_dirty(handle, inode, path + depth);
++		ext4_ext_try_to_merge(handle, inode, path, ex);
++		err = ext4_ext_dirty(handle, inode, path + path->p_depth);
+ 		goto out;
+ 	}
+ 
+@@ -3333,10 +3377,10 @@ static int ext4_convert_unwritten_extents_endio(handle_t *handle,
+ 	/* note: ext4_ext_correct_indexes() isn't needed here because
+ 	 * borders are not changed
+ 	 */
+-	ext4_ext_try_to_merge(inode, path, ex);
++	ext4_ext_try_to_merge(handle, inode, path, ex);
+ 
+ 	/* Mark modified extent as dirty */
+-	err = ext4_ext_dirty(handle, inode, path + depth);
++	err = ext4_ext_dirty(handle, inode, path + path->p_depth);
+ out:
+ 	ext4_ext_show_leaf(inode, path);
+ 	return err;

commit 89a4e48f8479f8145eca9698f39fe188c982212f
+Author: Theodore Ts'o 
+Date:   Fri Aug 17 08:54:52 2012 -0400
+
+    ext4: fix kernel BUG on large-scale rm -rf commands
+    
+    Commit 968dee7722: "ext4: fix hole punch failure when depth is greater
+    than 0" introduced a regression in v3.5.1/v3.6-rc1 which caused kernel
+    crashes when users ran run "rm -rf" on large directory hierarchy on
+    ext4 filesystems on RAID devices:
+    
+        BUG: unable to handle kernel NULL pointer dereference at 0000000000000028
+    
+        Process rm (pid: 18229, threadinfo ffff8801276bc000, task ffff880123631710)
+        Call Trace:
+         [] ? __ext4_handle_dirty_metadata+0x83/0x110
+         [] ext4_ext_truncate+0x193/0x1d0
+         [] ? ext4_mark_inode_dirty+0x7f/0x1f0
+         [] ext4_truncate+0xf5/0x100
+         [] ext4_evict_inode+0x461/0x490
+         [] evict+0xa2/0x1a0
+         [] iput+0x103/0x1f0
+         [] do_unlinkat+0x154/0x1c0
+         [] ? sys_newfstatat+0x2a/0x40
+         [] sys_unlinkat+0x1b/0x50
+         [] system_call_fastpath+0x16/0x1b
+        Code: 8b 4d 20 0f b7 41 02 48 8d 04 40 48 8d 04 81 49 89 45 18 0f b7 49 02 48 83 c1 01 49 89 4d 00 e9 ae f8 ff ff 0f 1f 00 49 8b 45 28 <48> 8b 40 28 49 89 45 20 e9 85 f8 ff ff 0f 1f 80 00 00 00
+    
+        RIP  [] ext4_ext_remove_space+0xa34/0xdf0
+    
+    This could be reproduced as follows:
+    
+    The problem in commit 968dee7722 was that caused the variable 'i' to
+    be left uninitialized if the truncate required more space than was
+    available in the journal.  This resulted in the function
+    ext4_ext_truncate_extend_restart() returning -EAGAIN, which caused
+    ext4_ext_remove_space() to restart the truncate operation after
+    starting a new jbd2 handle.
+    
+    Reported-by: Maciej Żenczykowski 
+    Reported-by: Marti Raudsepp 
+    Tested-by: Fengguang Wu 
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index cd0c7ed06772..aabbb3f53683 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -2662,6 +2662,7 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
+ 		}
+ 		path[0].p_depth = depth;
+ 		path[0].p_hdr = ext_inode_hdr(inode);
++		i = 0;
+ 
+ 		if (ext4_ext_check(inode, path[0].p_hdr, depth)) {
+ 			err = -EIO;

commit 0548bbb85337e532ca2ed697c3e9b227ff2ed4b4
+Author: Theodore Ts'o 
+Date:   Thu Aug 16 11:59:04 2012 -0400
+
+    ext4: fix long mount times on very big file systems
+    
+    Commit 8aeb00ff85a: "ext4: fix overhead calculation used by
+    ext4_statfs()" introduced a O(n**2) calculation which makes very large
+    file systems take forever to mount.  Fix this with an optimization for
+    non-bigalloc file systems.  (For bigalloc file systems the overhead
+    needs to be set in the the superblock.)
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 56bcaec9149c..598498904035 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3120,6 +3120,10 @@ static int count_overhead(struct super_block *sb, ext4_group_t grp,
+ 	ext4_group_t		i, ngroups = ext4_get_groups_count(sb);
+ 	int			s, j, count = 0;
+ 
++	if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_BIGALLOC))
++		return (ext4_bg_has_super(sb, grp) + ext4_bg_num_gdb(sb, grp) +
++			sbi->s_itb_per_group + 2);
++
+ 	first_block = le32_to_cpu(sbi->s_es->s_first_data_block) +
+ 		(grp * EXT4_BLOCKS_PER_GROUP(sb));
+ 	last_block = first_block + EXT4_BLOCKS_PER_GROUP(sb) - 1;

commit 7a4c5de27efa4c2ecca87af0a3deea63446367e2
+Author: Theodore Ts'o 
+Date:   Fri Aug 10 13:57:52 2012 -0400
+
+    ext4: don't call ext4_error while block group is locked
+    
+    While in ext4_validate_block_bitmap(), if an block allocation bitmap
+    is found to be invalid, we call ext4_error() while the block group is
+    still locked.  This causes ext4_commit_super() to call a function
+    which might sleep while in an atomic context.
+    
+    There's no need to keep the block group locked at this point, so hoist
+    the ext4_error() call up to ext4_validate_block_bitmap() and release
+    the block group spinlock before calling ext4_error().
+    
+    The reported stack trace can be found at:
+    
+            http://article.gmane.org/gmane.comp.file-systems.ext4/33731
+    
+    Reported-by: Dave Jones 
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index d23b31ca9d7a..1b5089067d01 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -280,14 +280,18 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
+ 	return desc;
+ }
+ 
+-static int ext4_valid_block_bitmap(struct super_block *sb,
+-				   struct ext4_group_desc *desc,
+-				   unsigned int block_group,
+-				   struct buffer_head *bh)
++/*
++ * Return the block number which was discovered to be invalid, or 0 if
++ * the block bitmap is valid.
++ */
++static ext4_fsblk_t ext4_valid_block_bitmap(struct super_block *sb,
++					    struct ext4_group_desc *desc,
++					    unsigned int block_group,
++					    struct buffer_head *bh)
+ {
+ 	ext4_grpblk_t offset;
+ 	ext4_grpblk_t next_zero_bit;
+-	ext4_fsblk_t bitmap_blk;
++	ext4_fsblk_t blk;
+ 	ext4_fsblk_t group_first_block;
+ 
+ 	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
+@@ -297,37 +301,33 @@ static int ext4_valid_block_bitmap(struct super_block *sb,
+ 		 * or it has to also read the block group where the bitmaps
+ 		 * are located to verify they are set.
+ 		 */
+-		return 1;
++		return 0;
+ 	}
+ 	group_first_block = ext4_group_first_block_no(sb, block_group);
+ 
+ 	/* check whether block bitmap block number is set */
+-	bitmap_blk = ext4_block_bitmap(sb, desc);
+-	offset = bitmap_blk - group_first_block;
++	blk = ext4_block_bitmap(sb, desc);
++	offset = blk - group_first_block;
+ 	if (!ext4_test_bit(offset, bh->b_data))
+ 		/* bad block bitmap */
+-		goto err_out;
++		return blk;
+ 
+ 	/* check whether the inode bitmap block number is set */
+-	bitmap_blk = ext4_inode_bitmap(sb, desc);
+-	offset = bitmap_blk - group_first_block;
++	blk = ext4_inode_bitmap(sb, desc);
++	offset = blk - group_first_block;
+ 	if (!ext4_test_bit(offset, bh->b_data))
+ 		/* bad block bitmap */
+-		goto err_out;
++		return blk;
+ 
+ 	/* check whether the inode table block number is set */
+-	bitmap_blk = ext4_inode_table(sb, desc);
+-	offset = bitmap_blk - group_first_block;
++	blk = ext4_inode_table(sb, desc);
++	offset = blk - group_first_block;
+ 	next_zero_bit = ext4_find_next_zero_bit(bh->b_data,
+ 				offset + EXT4_SB(sb)->s_itb_per_group,
+ 				offset);
+-	if (next_zero_bit >= offset + EXT4_SB(sb)->s_itb_per_group)
+-		/* good bitmap for inode tables */
+-		return 1;
+-
+-err_out:
+-	ext4_error(sb, "Invalid block bitmap - block_group = %d, block = %llu",
+-			block_group, bitmap_blk);
++	if (next_zero_bit < offset + EXT4_SB(sb)->s_itb_per_group)
++		/* bad bitmap for inode tables */
++		return blk;
+ 	return 0;
+ }
+ 
+@@ -336,14 +336,26 @@ void ext4_validate_block_bitmap(struct super_block *sb,
+ 			       unsigned int block_group,
+ 			       struct buffer_head *bh)
+ {
++	ext4_fsblk_t	blk;
++
+ 	if (buffer_verified(bh))
+ 		return;
+ 
+ 	ext4_lock_group(sb, block_group);
+-	if (ext4_valid_block_bitmap(sb, desc, block_group, bh) &&
+-	    ext4_block_bitmap_csum_verify(sb, block_group, desc, bh,
+-					  EXT4_BLOCKS_PER_GROUP(sb) / 8))
+-		set_buffer_verified(bh);
++	blk = ext4_valid_block_bitmap(sb, desc, block_group, bh);
++	if (unlikely(blk != 0)) {
++		ext4_unlock_group(sb, block_group);
++		ext4_error(sb, "bg %u: block %llu: invalid block bitmap",
++			   block_group, blk);
++		return;
++	}
++	if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group,
++			desc, bh, EXT4_BLOCKS_PER_GROUP(sb) / 8))) {
++		ext4_unlock_group(sb, block_group);
++		ext4_error(sb, "bg %u: bad block bitmap checksum", block_group);
++		return;
++	}
++	set_buffer_verified(bh);
+ 	ext4_unlock_group(sb, block_group);
+ }
+ 
+diff --git a/fs/ext4/bitmap.c b/fs/ext4/bitmap.c
+index f8716eab9995..5c2d1813ebe9 100644
+--- a/fs/ext4/bitmap.c
++++ b/fs/ext4/bitmap.c
+@@ -79,7 +79,6 @@ int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
+ 	if (provided == calculated)
+ 		return 1;
+ 
+-	ext4_error(sb, "Bad block bitmap checksum: block_group = %u", group);
+ 	return 0;
+ }
+ 

commit 7e731bc9a12339f344cddf82166b82633d99dd86
+Author: Theodore Ts'o 
+Date:   Sun Aug 5 23:28:16 2012 -0400
+
+    ext4: avoid kmemcheck complaint from reading uninitialized memory
+    
+    Commit 03179fe923 introduced a kmemcheck complaint in
+    ext4_da_get_block_prep() because we save and restore
+    ei->i_da_metadata_calc_last_lblock even though it is left
+    uninitialized in the case where i_da_metadata_calc_len is zero.
+    
+    This doesn't hurt anything, but silencing the kmemcheck complaint
+    makes it easier for people to find real bugs.
+    
+    Addresses https://bugzilla.kernel.org/show_bug.cgi?id=45631
+    (which is marked as a regression).
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index ccc4bcad5616..56bcaec9149c 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -959,6 +959,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
+ 	ei->i_reserved_meta_blocks = 0;
+ 	ei->i_allocated_meta_blocks = 0;
+ 	ei->i_da_metadata_calc_len = 0;
++	ei->i_da_metadata_calc_last_lblock = 0;
+ 	spin_lock_init(&(ei->i_block_reservation_lock));
+ #ifdef CONFIG_QUOTA
+ 	ei->i_reserved_quota = 0;

commit d796c52ef0b71a988364f6109aeb63d79c5b116b
+Author: Theodore Ts'o 
+Date:   Sun Aug 5 19:04:57 2012 -0400
+
+    ext4: make sure the journal sb is written in ext4_clear_journal_err()
+    
+    After we transfer set the EXT4_ERROR_FS bit in the file system
+    superblock, it's not enough to call jbd2_journal_clear_err() to clear
+    the error indication from journal superblock --- we need to call
+    jbd2_journal_update_sb_errno() as well.  Otherwise, when the root file
+    system is mounted read-only, the journal is replayed, and the error
+    indicator is transferred to the superblock --- but the s_errno field
+    in the jbd2 superblock is left set (since although we cleared it in
+    memory, we never flushed it out to disk).
+    
+    This can end up confusing e2fsck.  We should make e2fsck more robust
+    in this case, but the kernel shouldn't be leaving things in this
+    confused state, either.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index d76ec8277d3f..ccc4bcad5616 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4430,6 +4430,7 @@ static void ext4_clear_journal_err(struct super_block *sb,
+ 		ext4_commit_super(sb, 1);
+ 
+ 		jbd2_journal_clear_err(journal);
++		jbd2_journal_update_sb_errno(journal);
+ 	}
+ }
+ 
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index e9a3c4c85594..bd23f2ebaa67 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -1377,7 +1377,7 @@ static void jbd2_mark_journal_empty(journal_t *journal)
+  * Update a journal's errno.  Write updated superblock to disk waiting for IO
+  * to complete.
+  */
+-static void jbd2_journal_update_sb_errno(journal_t *journal)
++void jbd2_journal_update_sb_errno(journal_t *journal)
+ {
+ 	journal_superblock_t *sb = journal->j_superblock;
+ 
+@@ -1390,6 +1390,7 @@ static void jbd2_journal_update_sb_errno(journal_t *journal)
+ 
+ 	jbd2_write_superblock(journal, WRITE_SYNC);
+ }
++EXPORT_SYMBOL(jbd2_journal_update_sb_errno);
+ 
+ /*
+  * Read the superblock for a given journal, performing initial
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index f334c7fab967..3efc43f3f162 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -1125,6 +1125,7 @@ extern int	   jbd2_journal_destroy    (journal_t *);
+ extern int	   jbd2_journal_recover    (journal_t *journal);
+ extern int	   jbd2_journal_wipe       (journal_t *, int);
+ extern int	   jbd2_journal_skip_recovery	(journal_t *);
++extern void	   jbd2_journal_update_sb_errno(journal_t *);
+ extern void	   jbd2_journal_update_sb_log_tail	(journal_t *, tid_t,
+ 				unsigned long, int);
+ extern void	   __jbd2_journal_abort_hard	(journal_t *);

commit 03179fe92318e7934c180d96f12eff2cb36ef7b6
+Author: Theodore Ts'o 
+Date:   Mon Jul 23 00:00:20 2012 -0400
+
+    ext4: undo ext4_calc_metadata_amount if we fail to claim space
+    
+    The function ext4_calc_metadata_amount() has side effects, although
+    it's not obvious from its function name.  So if we fail to claim
+    space, regardless of whether we retry to claim the space again, or
+    return an error, we need to undo these side effects.
+    
+    Otherwise we can end up incorrectly calculating the number of metadata
+    blocks needed for the operation, which was responsible for an xfstests
+    failure for test #271 when using an ext2 file system with delalloc
+    enabled.
+    
+    Reported-by: Brian Foster 
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 25f809dc45a3..89b59cb7f9b8 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1182,6 +1182,17 @@ static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock)
+ 	struct ext4_inode_info *ei = EXT4_I(inode);
+ 	unsigned int md_needed;
+ 	int ret;
++	ext4_lblk_t save_last_lblock;
++	int save_len;
++
++	/*
++	 * We will charge metadata quota at writeout time; this saves
++	 * us from metadata over-estimation, though we may go over by
++	 * a small amount in the end.  Here we just reserve for data.
++	 */
++	ret = dquot_reserve_block(inode, EXT4_C2B(sbi, 1));
++	if (ret)
++		return ret;
+ 
+ 	/*
+ 	 * recalculate the amount of metadata blocks to reserve
+@@ -1190,32 +1201,31 @@ static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock)
+ 	 */
+ repeat:
+ 	spin_lock(&ei->i_block_reservation_lock);
++	/*
++	 * ext4_calc_metadata_amount() has side effects, which we have
++	 * to be prepared undo if we fail to claim space.
++	 */
++	save_len = ei->i_da_metadata_calc_len;
++	save_last_lblock = ei->i_da_metadata_calc_last_lblock;
+ 	md_needed = EXT4_NUM_B2C(sbi,
+ 				 ext4_calc_metadata_amount(inode, lblock));
+ 	trace_ext4_da_reserve_space(inode, md_needed);
+-	spin_unlock(&ei->i_block_reservation_lock);
+ 
+-	/*
+-	 * We will charge metadata quota at writeout time; this saves
+-	 * us from metadata over-estimation, though we may go over by
+-	 * a small amount in the end.  Here we just reserve for data.
+-	 */
+-	ret = dquot_reserve_block(inode, EXT4_C2B(sbi, 1));
+-	if (ret)
+-		return ret;
+ 	/*
+ 	 * We do still charge estimated metadata to the sb though;
+ 	 * we cannot afford to run out of free blocks.
+ 	 */
+ 	if (ext4_claim_free_clusters(sbi, md_needed + 1, 0)) {
+-		dquot_release_reservation_block(inode, EXT4_C2B(sbi, 1));
++		ei->i_da_metadata_calc_len = save_len;
++		ei->i_da_metadata_calc_last_lblock = save_last_lblock;
++		spin_unlock(&ei->i_block_reservation_lock);
+ 		if (ext4_should_retry_alloc(inode->i_sb, &retries)) {
+ 			yield();
+ 			goto repeat;
+ 		}
++		dquot_release_reservation_block(inode, EXT4_C2B(sbi, 1));
+ 		return -ENOSPC;
+ 	}
+-	spin_lock(&ei->i_block_reservation_lock);
+ 	ei->i_reserved_data_blocks++;
+ 	ei->i_reserved_meta_blocks += md_needed;
+ 	spin_unlock(&ei->i_block_reservation_lock);

commit 3108b54bcedde5d952c90460df5bc21efc1e134f
+Author: Theodore Ts'o 
+Date:   Sun Jul 22 20:25:31 2012 -0400
+
+    ext4: remove dynamic array size in ext4_chksum()
+    
+    The ext4_checksum() inline function was using a dynamic array size,
+    which is not legal C.  (It is a gcc extension).
+    
+    Remove it.
+    
+    Cc: "Darrick J. Wong" 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 1610e808ebe3..e8e8afa402f1 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1667,10 +1667,12 @@ static inline u32 ext4_chksum(struct ext4_sb_info *sbi, u32 crc,
+ {
+ 	struct {
+ 		struct shash_desc shash;
+-		char ctx[crypto_shash_descsize(sbi->s_chksum_driver)];
++		char ctx[4];
+ 	} desc;
+ 	int err;
+ 
++	BUG_ON(crypto_shash_descsize(sbi->s_chksum_driver)!=sizeof(desc.ctx));
++
+ 	desc.shash.tfm = sbi->s_chksum_driver;
+ 	desc.shash.flags = 0;
+ 	*(u32 *)desc.ctx = crc;

commit 8a9918497bcf5aaa8d45eb61c373605bc4e8c81f
+Author: Theodore Ts'o 
+Date:   Sun Jul 22 20:23:31 2012 -0400
+
+    ext4: remove unused variable in ext4_update_super()
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 17d38de4068c..50530bdbc02a 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -1197,7 +1197,7 @@ static void ext4_update_super(struct super_block *sb,
+ 	struct ext4_new_group_data *group_data = flex_gd->groups;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	struct ext4_super_block *es = sbi->s_es;
+-	int i, ret;
++	int i;
+ 
+ 	BUG_ON(flex_gd->count == 0 || group_data == NULL);
+ 	/*

commit b4237003cff66084ebeb502412d9cee392e6f52f
+Author: Theodore Ts'o 
+Date:   Tue Jul 17 14:20:51 2012 -0400
+
+    random: final removal of IRQF_SAMPLE_RANDOM
+    
+    The IRQF_SAMPLE_RANDOM flag is finally gone from the kernel tree, only
+    three years late.  :-)
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
+index 56000b33340b..27f39cf73578 100644
+--- a/Documentation/feature-removal-schedule.txt
++++ b/Documentation/feature-removal-schedule.txt
+@@ -70,20 +70,6 @@ Who:	Luis R. Rodriguez 
+ 
+ ---------------------------
+ 
+-What:	IRQF_SAMPLE_RANDOM
+-Check:	IRQF_SAMPLE_RANDOM
+-When:	July 2009
+-
+-Why:	Many of IRQF_SAMPLE_RANDOM users are technically bogus as entropy
+-	sources in the kernel's current entropy model. To resolve this, every
+-	input point to the kernel's entropy pool needs to better document the
+-	type of entropy source it actually is. This will be replaced with
+-	additional add_*_randomness functions in drivers/char/random.c
+-
+-Who:	Robin Getz  & Matt Mackall 
+-
+----------------------------
+-
+ What:	The ieee80211_regdom module parameter
+ When:	March 2010 / desktop catchup
+ 
+diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
+index e68a8e53bb59..c5f856a040b9 100644
+--- a/include/linux/interrupt.h
++++ b/include/linux/interrupt.h
+@@ -42,7 +42,6 @@
+  *
+  * IRQF_DISABLED - keep irqs disabled when calling the action handler.
+  *                 DEPRECATED. This flag is a NOOP and scheduled to be removed
+- * IRQF_SAMPLE_RANDOM - irq is used to feed the random generator
+  * IRQF_SHARED - allow sharing the irq among several devices
+  * IRQF_PROBE_SHARED - set by callers when they expect sharing mismatches to occur
+  * IRQF_TIMER - Flag to mark this interrupt as timer interrupt
+@@ -61,7 +60,6 @@
+  *                resume time.
+  */
+ #define IRQF_DISABLED		0x00000020
+-#define IRQF_SAMPLE_RANDOM	0x00000040
+ #define IRQF_SHARED		0x00000080
+ #define IRQF_PROBE_SHARED	0x00000100
+ #define __IRQF_TIMER		0x00000200

commit aab944606f9490f158d3b28f6c44a33c4701a5b3
+Author: Theodore Ts'o 
+Date:   Tue Jul 17 14:18:23 2012 -0400
+
+    um: remove IRQF_SAMPLE_RANDOM which is now a no-op
+    
+    With the changes in the random tree, IRQF_SAMPLE_RANDOM is now a
+    no-op; interrupt randomness is now collected unconditionally in a very
+    low-overhead fashion; see commit 775f4b297b.  The IRQF_SAMPLE_RANDOM
+    flag was scheduled to be removed in 2009 on the
+    feature-removal-schedule, so this patch is preparation for the final
+    removal of this flag.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Jeff Dike 
+    Cc: Richard Weinberger 
+
+diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
+index acfd0e0fd0c9..ac9d25c8dc01 100644
+--- a/arch/um/drivers/line.c
++++ b/arch/um/drivers/line.c
+@@ -362,18 +362,18 @@ static irqreturn_t line_write_interrupt(int irq, void *data)
+ int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
+ {
+ 	const struct line_driver *driver = line->driver;
+-	int err = 0, flags = IRQF_SHARED | IRQF_SAMPLE_RANDOM;
++	int err = 0;
+ 
+ 	if (input)
+ 		err = um_request_irq(driver->read_irq, fd, IRQ_READ,
+-				       line_interrupt, flags,
+-				       driver->read_irq_name, data);
++				     line_interrupt, IRQF_SHARED,
++				     driver->read_irq_name, data);
+ 	if (err)
+ 		return err;
+ 	if (output)
+ 		err = um_request_irq(driver->write_irq, fd, IRQ_WRITE,
+-					line_write_interrupt, flags,
+-					driver->write_irq_name, data);
++				     line_write_interrupt, IRQF_SHARED,
++				     driver->write_irq_name, data);
+ 	return err;
+ }
+ 
+@@ -779,8 +779,7 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty,
+ 				   .stack	= stack });
+ 
+ 	if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
+-			   IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+-			   "winch", winch) < 0) {
++			   IRQF_SHARED, "winch", winch) < 0) {
+ 		printk(KERN_ERR "register_winch_irq - failed to register "
+ 		       "IRQ\n");
+ 		goto out_free;
+diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
+index 88e466b159dc..e1c519790b5c 100644
+--- a/arch/um/drivers/mconsole_kern.c
++++ b/arch/um/drivers/mconsole_kern.c
+@@ -775,8 +775,7 @@ static int __init mconsole_init(void)
+ 	register_reboot_notifier(&reboot_notifier);
+ 
+ 	err = um_request_irq(MCONSOLE_IRQ, sock, IRQ_READ, mconsole_interrupt,
+-			     IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+-			     "mconsole", (void *)sock);
++			     IRQF_SHARED, "mconsole", (void *)sock);
+ 	if (err) {
+ 		printk(KERN_ERR "Failed to get IRQ for management console\n");
+ 		goto out;
+diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
+index 11866ffd45a9..1d83d50236e1 100644
+--- a/arch/um/drivers/port_kern.c
++++ b/arch/um/drivers/port_kern.c
+@@ -100,8 +100,7 @@ static int port_accept(struct port_list *port)
+ 		  .port 	= port });
+ 
+ 	if (um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt,
+-			  IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+-			  "telnetd", conn)) {
++			  IRQF_SHARED, "telnetd", conn)) {
+ 		printk(KERN_ERR "port_accept : failed to get IRQ for "
+ 		       "telnetd\n");
+ 		goto out_free;
+@@ -184,8 +183,7 @@ void *port_data(int port_num)
+ 	}
+ 
+ 	if (um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt,
+-			  IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+-			  "port", port)) {
++			  IRQF_SHARED, "port", port)) {
+ 		printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num);
+ 		goto out_close;
+ 	}
+diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
+index b25296e6218a..e32c6aa6396f 100644
+--- a/arch/um/drivers/random.c
++++ b/arch/um/drivers/random.c
+@@ -131,8 +131,7 @@ static int __init rng_init (void)
+ 	random_fd = err;
+ 
+ 	err = um_request_irq(RANDOM_IRQ, random_fd, IRQ_READ, random_interrupt,
+-			     IRQF_SAMPLE_RANDOM, "random",
+-			     NULL);
++			     0, "random", NULL);
+ 	if (err)
+ 		goto err_out_cleanup_hw;
+ 
+diff --git a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c
+index b68bbe269e01..e3031e69445d 100644
+--- a/arch/um/drivers/xterm_kern.c
++++ b/arch/um/drivers/xterm_kern.c
+@@ -50,8 +50,7 @@ int xterm_fd(int socket, int *pid_out)
+ 	init_completion(&data->ready);
+ 
+ 	err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt,
+-			     IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+-			     "xterm", data);
++			     IRQF_SHARED, "xterm", data);
+ 	if (err) {
+ 		printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, "
+ 		       "err = %d\n",  err);
+diff --git a/arch/um/kernel/sigio.c b/arch/um/kernel/sigio.c
+index 2a1639255763..c88211139a51 100644
+--- a/arch/um/kernel/sigio.c
++++ b/arch/um/kernel/sigio.c
+@@ -25,8 +25,7 @@ int write_sigio_irq(int fd)
+ 	int err;
+ 
+ 	err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt,
+-			     IRQF_SAMPLE_RANDOM, "write sigio",
+-			     NULL);
++			     0, "write sigio", NULL);
+ 	if (err) {
+ 		printk(KERN_ERR "write_sigio_irq : um_request_irq failed, "
+ 		       "err = %d\n", err);

commit 71ba8d44da550089bda22b2a921757613b5e0b4e
+Author: Theodore Ts'o 
+Date:   Tue Jul 17 14:10:26 2012 -0400
+
+    sparc/ldc: remove IRQF_SAMPLE_RANDOM which is now a no-op
+    
+    With the changes in the random tree, IRQF_SAMPLE_RANDOM is now a
+    no-op; interrupt randomness is now collected unconditionally in a very
+    low-overhead fashion; see commit 775f4b297b.  The IRQF_SAMPLE_RANDOM
+    flag was scheduled to be removed in 2009 on the
+    feature-removal-schedule, so this patch is preparation for the final
+    removal of this flag.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Acked-by: "David S. Miller" 
+
+diff --git a/arch/sparc/kernel/ldc.c b/arch/sparc/kernel/ldc.c
+index 435e406fdec3..81d92fc9983b 100644
+--- a/arch/sparc/kernel/ldc.c
++++ b/arch/sparc/kernel/ldc.c
+@@ -1250,14 +1250,12 @@ int ldc_bind(struct ldc_channel *lp, const char *name)
+ 	snprintf(lp->rx_irq_name, LDC_IRQ_NAME_MAX, "%s RX", name);
+ 	snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name);
+ 
+-	err = request_irq(lp->cfg.rx_irq, ldc_rx,
+-			  IRQF_SAMPLE_RANDOM | IRQF_DISABLED,
++	err = request_irq(lp->cfg.rx_irq, ldc_rx, IRQF_DISABLED,
+ 			  lp->rx_irq_name, lp);
+ 	if (err)
+ 		return err;
+ 
+-	err = request_irq(lp->cfg.tx_irq, ldc_tx,
+-			  IRQF_SAMPLE_RANDOM | IRQF_DISABLED,
++	err = request_irq(lp->cfg.tx_irq, ldc_tx, IRQF_DISABLED,
+ 			  lp->tx_irq_name, lp);
+ 	if (err) {
+ 		free_irq(lp->cfg.rx_irq, lp);

commit 14673764249eb2cae4c7e9d73cb261129739563d
+Author: Theodore Ts'o 
+Date:   Tue Jul 17 14:05:52 2012 -0400
+
+    [ARM] pxa: remove IRQF_SAMPLE_RANDOM which is now a no-op
+    
+    With the changes in the random tree, IRQF_SAMPLE_RANDOM is now a
+    no-op; interrupt randomness is now collected unconditionally in a very
+    low-overhead fashion; see commit 775f4b297b.  The IRQF_SAMPLE_RANDOM
+    flag was scheduled to be removed in 2009 on the
+    feature-removal-schedule, so this patch is preparation for the final
+    removal of this flag.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Acked-by: Haojian Zhuang 
+    Cc: Eric Miao 
+    Cc: Russell King 
+
+diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
+index 6bb3f47b1f14..0ca0db787903 100644
+--- a/arch/arm/mach-pxa/lubbock.c
++++ b/arch/arm/mach-pxa/lubbock.c
+@@ -456,7 +456,7 @@ static int lubbock_mci_init(struct device *dev,
+ 	init_timer(&mmc_timer);
+ 	mmc_timer.data = (unsigned long) data;
+ 	return request_irq(LUBBOCK_SD_IRQ, lubbock_detect_int,
+-			IRQF_SAMPLE_RANDOM, "lubbock-sd-detect", data);
++			   0, "lubbock-sd-detect", data);
+ }
+ 
+ static int lubbock_mci_get_ro(struct device *dev)
+diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
+index 2db697cd2b4e..39561dcf65f2 100644
+--- a/arch/arm/mach-pxa/magician.c
++++ b/arch/arm/mach-pxa/magician.c
+@@ -633,9 +633,8 @@ static struct platform_device bq24022 = {
+ static int magician_mci_init(struct device *dev,
+ 				irq_handler_t detect_irq, void *data)
+ {
+-	return request_irq(IRQ_MAGICIAN_SD, detect_irq,
+-				IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
+-				"mmc card detect", data);
++	return request_irq(IRQ_MAGICIAN_SD, detect_irq, IRQF_DISABLED,
++			   "mmc card detect", data);
+ }
+ 
+ static void magician_mci_exit(struct device *dev, void *data)
+diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
+index 2b6ac00b2cd9..166dd32cc1d3 100644
+--- a/arch/arm/mach-pxa/trizeps4.c
++++ b/arch/arm/mach-pxa/trizeps4.c
+@@ -332,8 +332,8 @@ static int trizeps4_mci_init(struct device *dev, irq_handler_t mci_detect_int,
+ 	int err;
+ 
+ 	err = request_irq(TRIZEPS4_MMC_IRQ, mci_detect_int,
+-		IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_SAMPLE_RANDOM,
+-		"MMC card detect", data);
++			  IRQF_DISABLED | IRQF_TRIGGER_RISING,
++			  "MMC card detect", data);
+ 	if (err) {
+ 		printk(KERN_ERR "trizeps4_mci_init: MMC/SD: can't request"
+ 						"MMC card detect IRQ\n");

commit 9863fa6c8b05ca9e6efd3471cb8bc35583b4664a
+Author: Theodore Ts'o 
+Date:   Tue Jul 17 14:04:00 2012 -0400
+
+    board-palmz71: remove IRQF_SAMPLE_RANDOM which is now a no-op
+    
+    With the changes in the random tree, IRQF_SAMPLE_RANDOM is now a
+    no-op; interrupt randomness is now collected unconditionally in a very
+    low-overhead fashion; see commit 775f4b297b.  The IRQF_SAMPLE_RANDOM
+    flag was scheduled to be removed in 2009 on the
+    feature-removal-schedule, so this patch is preparation for the final
+    removal of this flag.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Tony Lindgren 
+
+diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c
+index 3c71c6bace2c..efcd365c64ed 100644
+--- a/arch/arm/mach-omap1/board-palmz71.c
++++ b/arch/arm/mach-omap1/board-palmz71.c
+@@ -288,8 +288,7 @@ palmz71_gpio_setup(int early)
+ 		}
+ 		gpio_direction_input(PALMZ71_USBDETECT_GPIO);
+ 		if (request_irq(gpio_to_irq(PALMZ71_USBDETECT_GPIO),
+-				palmz71_powercable, IRQF_SAMPLE_RANDOM,
+-				"palmz71-cable", NULL))
++				palmz71_powercable, 0, "palmz71-cable", NULL))
+ 			printk(KERN_ERR
+ 					"IRQ request for power cable failed!\n");
+ 		palmz71_powercable(gpio_to_irq(PALMZ71_USBDETECT_GPIO), NULL);

commit 34e4cc40a0b077ee28a66d989491b6777a49a778
+Author: Theodore Ts'o 
+Date:   Tue Jul 17 14:02:16 2012 -0400
+
+    isp1301_omap: remove IRQF_SAMPLE_RANDOM which is now a no-op
+    
+    With the changes in the random tree, IRQF_SAMPLE_RANDOM is now a
+    no-op; interrupt randomness is now collected unconditionally in a very
+    low-overhead fashion; see commit 775f4b297b.  The IRQF_SAMPLE_RANDOM
+    flag was scheduled to be removed in 2009 on the
+    feature-removal-schedule, so this patch is preparation for the final
+    removal of this flag.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Felipe Balbi 
+
+diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c
+index 70cf5d7bca48..512397a98803 100644
+--- a/drivers/usb/otg/isp1301_omap.c
++++ b/drivers/usb/otg/isp1301_omap.c
+@@ -1575,7 +1575,6 @@ isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
+ 		isp->irq_type = IRQF_TRIGGER_FALLING;
+ 	}
+ 
+-	isp->irq_type |= IRQF_SAMPLE_RANDOM;
+ 	status = request_irq(i2c->irq, isp1301_irq,
+ 			isp->irq_type, DRIVER_NAME, isp);
+ 	if (status < 0) {

commit 8de1ee8f93fb756000176f916fd0681b47ceb292
+Author: Theodore Ts'o 
+Date:   Tue Jul 17 14:00:26 2012 -0400
+
+    pxa25x_udc: remove IRQF_SAMPLE_RANDOM which is now a no-op
+    
+    With the changes in the random tree, IRQF_SAMPLE_RANDOM is now a
+    no-op; interrupt randomness is now collected unconditionally in a very
+    low-overhead fashion; see commit 775f4b297b.  The IRQF_SAMPLE_RANDOM
+    flag was scheduled to be removed in 2009 on the
+    feature-removal-schedule, so this patch is preparation for the final
+    removal of this flag.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Acked-by: Haojian Zhuang 
+    Cc: Eric Miao 
+    Cc: Russell King 
+
+diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
+index f7ff9e8e746a..c319814ad120 100644
+--- a/drivers/usb/gadget/pxa25x_udc.c
++++ b/drivers/usb/gadget/pxa25x_udc.c
+@@ -2200,19 +2200,15 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
+ 
+ #ifdef CONFIG_ARCH_LUBBOCK
+ 	if (machine_is_lubbock()) {
+-		retval = request_irq(LUBBOCK_USB_DISC_IRQ,
+-				lubbock_vbus_irq,
+-				IRQF_SAMPLE_RANDOM,
+-				driver_name, dev);
++		retval = request_irq(LUBBOCK_USB_DISC_IRQ, lubbock_vbus_irq,
++				     0, driver_name, dev);
+ 		if (retval != 0) {
+ 			pr_err("%s: can't get irq %i, err %d\n",
+ 				driver_name, LUBBOCK_USB_DISC_IRQ, retval);
+ 			goto err_irq_lub;
+ 		}
+-		retval = request_irq(LUBBOCK_USB_IRQ,
+-				lubbock_vbus_irq,
+-				IRQF_SAMPLE_RANDOM,
+-				driver_name, dev);
++		retval = request_irq(LUBBOCK_USB_IRQ, lubbock_vbus_irq,
++				     0, driver_name, dev);
+ 		if (retval != 0) {
+ 			pr_err("%s: can't get irq %i, err %d\n",
+ 				driver_name, LUBBOCK_USB_IRQ, retval);

commit 9728276835f319e32e2571fb0fb18777237de87c
+Author: Theodore Ts'o 
+Date:   Tue Jul 17 13:56:28 2012 -0400
+
+    omap_udc: remove IRQF_SAMPLE_RANDOM which is now a no-op
+    
+    With the changes in the random tree, IRQF_SAMPLE_RANDOM is now a
+    no-op; interrupt randomness is now collected unconditionally in a very
+    low-overhead fashion; see commit 775f4b297b.  The IRQF_SAMPLE_RANDOM
+    flag was scheduled to be removed in 2009 on the
+    feature-removal-schedule, so this patch is preparation for the final
+    removal of this flag.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
+index a460e8c204f4..2980100bcde7 100644
+--- a/drivers/usb/gadget/omap_udc.c
++++ b/drivers/usb/gadget/omap_udc.c
+@@ -2944,7 +2944,7 @@ static int __init omap_udc_probe(struct platform_device *pdev)
+ 
+ 	/* USB general purpose IRQ:  ep0, state changes, dma, etc */
+ 	status = request_irq(pdev->resource[1].start, omap_udc_irq,
+-			IRQF_SAMPLE_RANDOM, driver_name, udc);
++			     0, driver_name, udc);
+ 	if (status != 0) {
+ 		ERR("can't get irq %d, err %d\n",
+ 			(int) pdev->resource[1].start, status);
+@@ -2953,7 +2953,7 @@ static int __init omap_udc_probe(struct platform_device *pdev)
+ 
+ 	/* USB "non-iso" IRQ (PIO for all but ep0) */
+ 	status = request_irq(pdev->resource[2].start, omap_udc_pio_irq,
+-			IRQF_SAMPLE_RANDOM, "omap_udc pio", udc);
++			     0, "omap_udc pio", udc);
+ 	if (status != 0) {
+ 		ERR("can't get irq %d, err %d\n",
+ 			(int) pdev->resource[2].start, status);

commit 11bc26836acc6aa19f30ea377cd44cd74d4c185b
+Author: Theodore Ts'o 
+Date:   Tue Jul 17 13:53:36 2012 -0400
+
+    goku_udc: remove IRQF_SAMPLE_RANDOM which was commented out
+    
+    With the changes in the random tree, IRQF_SAMPLE_RANDOM is now a
+    no-op; interrupt randomness is now collected unconditionally in a very
+    low-overhead fashion; see commit 775f4b297b.  The IRQF_SAMPLE_RANDOM
+    flag was scheduled to be removed in 2009 on the
+    feature-removal-schedule.
+    
+    The flag was only commented-out in the driver, but we should just
+    remove it altogether.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
+index 3d28fb976c78..9fd7886cfa9a 100644
+--- a/drivers/usb/gadget/goku_udc.c
++++ b/drivers/usb/gadget/goku_udc.c
+@@ -1836,7 +1836,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	/* init to known state, then setup irqs */
+ 	udc_reset(dev);
+ 	udc_reinit (dev);
+-	if (request_irq(pdev->irq, goku_irq, IRQF_SHARED/*|IRQF_SAMPLE_RANDOM*/,
++	if (request_irq(pdev->irq, goku_irq, IRQF_SHARED,
+ 			driver_name, dev) != 0) {
+ 		DBG(dev, "request interrupt %d failed\n", pdev->irq);
+ 		retval = -EBUSY;

commit fc4b1863a59171ac29e795dc5a9a7227d94313c8
+Author: Theodore Ts'o 
+Date:   Tue Jul 17 13:51:51 2012 -0400
+
+    uartlite: remove IRQF_SAMPLE_RANDOM which is now a no-op
+    
+    With the changes in the random tree, IRQF_SAMPLE_RANDOM is now a
+    no-op; interrupt randomness is now collected unconditionally in a very
+    low-overhead fashion; see commit 775f4b297b.  The IRQF_SAMPLE_RANDOM
+    flag was scheduled to be removed in 2009 on the
+    feature-removal-schedule, so this patch is preparation for the final
+    removal of this flag.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Acked-by: Peter Korsgaard 
+
+diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
+index 6cd414341d5e..6579ffdd8e9b 100644
+--- a/drivers/tty/serial/uartlite.c
++++ b/drivers/tty/serial/uartlite.c
+@@ -216,8 +216,7 @@ static int ulite_startup(struct uart_port *port)
+ {
+ 	int ret;
+ 
+-	ret = request_irq(port->irq, ulite_isr,
+-			  IRQF_SHARED | IRQF_SAMPLE_RANDOM, "uartlite", port);
++	ret = request_irq(port->irq, ulite_isr, IRQF_SHARED, "uartlite", port);
+ 	if (ret)
+ 		return ret;
+ 

commit 20ed3ef7f3e39cb18fb64acc61aa40a74a9c7e19
+Author: Theodore Ts'o 
+Date:   Tue Jul 17 13:50:30 2012 -0400
+
+    drivers: hv: remove IRQF_SAMPLE_RANDOM which is now a no-op
+    
+    With the changes in the random tree, IRQF_SAMPLE_RANDOM is now a
+    no-op; interrupt randomness is now collected unconditionally in a very
+    low-overhead fashion; see commit 775f4b297b.  The IRQF_SAMPLE_RANDOM
+    flag was scheduled to be removed in 2009 on the
+    feature-removal-schedule, so this patch is preparation for the final
+    removal of this flag.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Acked-by: "K. Y. Srinivasan" 
+    Cc: Haiyang Zhang 
+
+diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
+index a220e5746d67..4748086eaaf2 100644
+--- a/drivers/hv/vmbus_drv.c
++++ b/drivers/hv/vmbus_drv.c
+@@ -545,8 +545,7 @@ static int vmbus_bus_init(int irq)
+ 	if (ret)
+ 		goto err_cleanup;
+ 
+-	ret = request_irq(irq, vmbus_isr, IRQF_SAMPLE_RANDOM,
+-			driver_name, hv_acpi_dev);
++	ret = request_irq(irq, vmbus_isr, 0, driver_name, hv_acpi_dev);
+ 
+ 	if (ret != 0) {
+ 		pr_err("Unable to request IRQ %d\n",

commit 89c30f161cd03d9baa4c88105b0449ce7025d713
+Author: Theodore Ts'o 
+Date:   Tue Jul 17 13:46:19 2012 -0400
+
+    xen-blkfront: remove IRQF_SAMPLE_RANDOM which is now a no-op
+    
+    With the changes in the random tree, IRQF_SAMPLE_RANDOM is now a
+    no-op; interrupt randomness is now collected unconditionally in a very
+    low-overhead fashion; see commit 775f4b297b.  The IRQF_SAMPLE_RANDOM
+    flag was scheduled to be removed in 2009 on the
+    feature-removal-schedule, so this patch is preparation for the final
+    removal of this flag.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Konrad Rzeszutek Wilk 
+    Cc: Jeremy Fitzhardinge 
+
+diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
+index 60eed4bdd2e4..8f7a071c6dbe 100644
+--- a/drivers/block/xen-blkfront.c
++++ b/drivers/block/xen-blkfront.c
+@@ -854,9 +854,8 @@ static int setup_blkring(struct xenbus_device *dev,
+ 	if (err)
+ 		goto fail;
+ 
+-	err = bind_evtchn_to_irqhandler(info->evtchn,
+-					blkif_interrupt,
+-					IRQF_SAMPLE_RANDOM, "blkif", info);
++	err = bind_evtchn_to_irqhandler(info->evtchn, blkif_interrupt, 0,
++					"blkif", info);
+ 	if (err <= 0) {
+ 		xenbus_dev_fatal(dev, err,
+ 				 "bind_evtchn_to_irqhandler failed");

commit 9751bfd1c9177a8ab0a910fe279a8815e498561e
+Author: Theodore Ts'o 
+Date:   Tue Jul 17 13:42:34 2012 -0400
+
+    n2_crypto: remove IRQF_SAMPLE_RANDOM which is now a no-op
+    
+    With the changes in the random tree, IRQF_SAMPLE_RANDOM is now a
+    no-op; interrupt randomness is now collected unconditionally in a very
+    low-overhead fashion; see commit 775f4b297b.  The IRQF_SAMPLE_RANDOM
+    flag was scheduled to be removed in 2009 on the
+    feature-removal-schedule, so this patch is preparation for the final
+    removal of this flag.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Acked-by: Herbert Xu 
+
+diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c
+index 67b97c5fd859..a8bd0310f8fe 100644
+--- a/drivers/crypto/n2_core.c
++++ b/drivers/crypto/n2_core.c
+@@ -1610,8 +1610,7 @@ static int spu_map_ino(struct platform_device *dev, struct spu_mdesc_info *ip,
+ 
+ 	sprintf(p->irq_name, "%s-%d", irq_name, index);
+ 
+-	return request_irq(p->irq, handler, IRQF_SAMPLE_RANDOM,
+-			   p->irq_name, p);
++	return request_irq(p->irq, handler, 0, p->irq_name, p);
+ }
+ 
+ static struct kmem_cache *queue_cache[2];

commit d554a3f9d3f3b0bb2faefad712e6d0dbd7c82ba6
+Author: Theodore Ts'o 
+Date:   Tue Jul 17 13:40:18 2012 -0400
+
+    pda_power: remove IRQF_SAMPLE_RANDOM which is now a no-op
+    
+    With the changes in the random tree, IRQF_SAMPLE_RANDOM is now a
+    no-op; interrupt randomness is now collected unconditionally in a very
+    low-overhead fashion; see commit 775f4b297b.  The IRQF_SAMPLE_RANDOM
+    flag was scheduled to be removed in 2009 on the
+    feature-removal-schedule, so this patch is preparation for the final
+    removal of this flag.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Acked-by: Anton Vorontsov 
+    Cc: David Woodhouse 
+
+diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c
+index 214468f4444a..db5c526154d0 100644
+--- a/drivers/power/pda_power.c
++++ b/drivers/power/pda_power.c
+@@ -24,11 +24,7 @@
+ 
+ static inline unsigned int get_irq_flags(struct resource *res)
+ {
+-	unsigned int flags = IRQF_SAMPLE_RANDOM | IRQF_SHARED;
+-
+-	flags |= res->flags & IRQF_TRIGGER_MASK;
+-
+-	return flags;
++	return IRQF_SHARED | (res->flags & IRQF_TRIGGER_MASK);
+ }
+ 
+ static struct device *dev;

commit d38a0149e8a11ca333c1a6c489a2ccac2b73f2cb
+Author: Theodore Ts'o 
+Date:   Tue Jul 17 13:34:18 2012 -0400
+
+    i2c-pmcmsp: remove IRQF_SAMPLE_RANDOM which is now a no-op
+    
+    With the changes in the random tree, IRQF_SAMPLE_RANDOM is now a
+    no-op; interrupt randomness is now collected unconditionally in a very
+    low-overhead fashion; see commit 775f4b297b.  The IRQF_SAMPLE_RANDOM
+    flag was scheduled to be removed in 2009 on the
+    feature-removal-schedule, so this patch is preparation for the final
+    removal of this flag.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: "Ben Dooks" 
+    Cc: "Wolfram Sang" 
+
+diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c
+index 07b7447ecbc9..3d71395ae1f7 100644
+--- a/drivers/i2c/busses/i2c-pmcmsp.c
++++ b/drivers/i2c/busses/i2c-pmcmsp.c
+@@ -306,8 +306,7 @@ static int __devinit pmcmsptwi_probe(struct platform_device *pldev)
+ 	pmcmsptwi_data.irq = platform_get_irq(pldev, 0);
+ 	if (pmcmsptwi_data.irq) {
+ 		rc = request_irq(pmcmsptwi_data.irq, &pmcmsptwi_interrupt,
+-			IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+-			pldev->name, &pmcmsptwi_data);
++				 IRQF_SHARED, pldev->name, &pmcmsptwi_data);
+ 		if (rc == 0) {
+ 			/*
+ 			 * Enable 'DONE' interrupt only.

commit a5d600f874e7d73c5ccfa37072f883701ade668d
+Author: Theodore Ts'o 
+Date:   Tue Jul 17 13:30:34 2012 -0400
+
+    input/serio/hp_sdc.c: remove IRQF_SAMPLE_RANDOM which is now a no-op
+    
+    With the changes in the random tree, IRQF_SAMPLE_RANDOM is now a
+    no-op; interrupt randomness is now collected unconditionally in a very
+    low-overhead fashion; see commit 775f4b297b.  The IRQF_SAMPLE_RANDOM
+    flag was scheduled to be removed in 2009 on the
+    feature-removal-schedule, so this patch is preparation for the final
+    removal of this flag.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Acked-by: Dmitry Torokhov 
+
+diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
+index 09a089996ded..d7a7e54f6465 100644
+--- a/drivers/input/serio/hp_sdc.c
++++ b/drivers/input/serio/hp_sdc.c
+@@ -878,7 +878,7 @@ static int __init hp_sdc_init(void)
+ #endif
+ 
+ 	errstr = "IRQ not available for";
+-	if (request_irq(hp_sdc.irq, &hp_sdc_isr, IRQF_SHARED|IRQF_SAMPLE_RANDOM,
++	if (request_irq(hp_sdc.irq, &hp_sdc_isr, IRQF_SHARED,
+ 			"HP SDC", &hp_sdc))
+ 		goto err1;
+ 

commit 212436c2ac11bce48d40fae04147dc025f2775ca
+Author: Theodore Ts'o 
+Date:   Tue Jul 17 13:23:36 2012 -0400
+
+    mfd: remove IRQF_SAMPLE_RANDOM which is now a no-op
+    
+    With the changes in the random tree, IRQF_SAMPLE_RANDOM is now a
+    no-op; interrupt randomness is now collected unconditionally in a very
+    low-overhead fashion; see commit 775f4b297b.  The IRQF_SAMPLE_RANDOM
+    flag was scheduled to be removed in 2009 on the
+    feature-removal-schedule, so this patch is preparation for the final
+    removal of this flag.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Samuel Ortiz 
+
+diff --git a/drivers/mfd/tps65010.c b/drivers/mfd/tps65010.c
+index 93d5fdf020c7..da2691f22e11 100644
+--- a/drivers/mfd/tps65010.c
++++ b/drivers/mfd/tps65010.c
+@@ -563,8 +563,7 @@ static int tps65010_probe(struct i2c_client *client,
+ 	 */
+ 	if (client->irq > 0) {
+ 		status = request_irq(client->irq, tps65010_irq,
+-			IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_FALLING,
+-			DRIVER_NAME, tps);
++				     IRQF_TRIGGER_FALLING, DRIVER_NAME, tps);
+ 		if (status < 0) {
+ 			dev_dbg(&client->dev, "can't get IRQ %d, err %d\n",
+ 					client->irq, status);

commit c5857ccf293968348e5eb4ebedc68074de3dcda6
+Author: Theodore Ts'o 
+Date:   Sat Jul 14 20:27:52 2012 -0400
+
+    random: remove rand_initialize_irq()
+    
+    With the new interrupt sampling system, we are no longer using the
+    timer_rand_state structure in the irq descriptor, so we can stop
+    initializing it now.
+    
+    [ Merged in fixes from Sedat to find some last missing references to
+      rand_initialize_irq() ]
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Sedat Dilek 
+
+diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
+index 5c3e0888265a..1034884b77da 100644
+--- a/arch/ia64/kernel/irq_ia64.c
++++ b/arch/ia64/kernel/irq_ia64.c
+@@ -23,7 +23,6 @@
+ #include 
+ #include 
+ #include 
+-#include 	/* for rand_initialize_irq() */
+ #include 
+ #include 
+ #include 
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index e3180852ec85..9793b40f5754 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -634,43 +634,6 @@ struct timer_rand_state {
+ 	unsigned dont_count_entropy:1;
+ };
+ 
+-#ifndef CONFIG_GENERIC_HARDIRQS
+-
+-static struct timer_rand_state *irq_timer_state[NR_IRQS];
+-
+-static struct timer_rand_state *get_timer_rand_state(unsigned int irq)
+-{
+-	return irq_timer_state[irq];
+-}
+-
+-static void set_timer_rand_state(unsigned int irq,
+-				 struct timer_rand_state *state)
+-{
+-	irq_timer_state[irq] = state;
+-}
+-
+-#else
+-
+-static struct timer_rand_state *get_timer_rand_state(unsigned int irq)
+-{
+-	struct irq_desc *desc;
+-
+-	desc = irq_to_desc(irq);
+-
+-	return desc->timer_rand_state;
+-}
+-
+-static void set_timer_rand_state(unsigned int irq,
+-				 struct timer_rand_state *state)
+-{
+-	struct irq_desc *desc;
+-
+-	desc = irq_to_desc(irq);
+-
+-	desc->timer_rand_state = state;
+-}
+-#endif
+-
+ /*
+  * Add device- or boot-specific data to the input and nonblocking
+  * pools to help initialize them to unique values.
+@@ -1133,24 +1096,6 @@ static int rand_initialize(void)
+ }
+ module_init(rand_initialize);
+ 
+-void rand_initialize_irq(int irq)
+-{
+-	struct timer_rand_state *state;
+-
+-	state = get_timer_rand_state(irq);
+-
+-	if (state)
+-		return;
+-
+-	/*
+-	 * If kzalloc returns null, we just won't use that entropy
+-	 * source.
+-	 */
+-	state = kzalloc(sizeof(struct timer_rand_state), GFP_KERNEL);
+-	if (state)
+-		set_timer_rand_state(irq, state);
+-}
+-
+ #ifdef CONFIG_BLOCK
+ void rand_initialize_disk(struct gendisk *disk)
+ {
+diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
+index 9522d6bda4f7..1287645b984d 100644
+--- a/drivers/mfd/ab3100-core.c
++++ b/drivers/mfd/ab3100-core.c
+@@ -931,9 +931,6 @@ static int __devinit ab3100_probe(struct i2c_client *client,
+ 
+ 	err = request_threaded_irq(client->irq, NULL, ab3100_irq_handler,
+ 				IRQF_ONESHOT, "ab3100-core", ab3100);
+-	/* This real unpredictable IRQ is of course sampled for entropy */
+-	rand_initialize_irq(client->irq);
+-
+ 	if (err)
+ 		goto exit_no_irq;
+ 
+diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h
+index f1e2527006bd..9a323d12de1c 100644
+--- a/include/linux/irqdesc.h
++++ b/include/linux/irqdesc.h
+@@ -39,7 +39,6 @@ struct module;
+  */
+ struct irq_desc {
+ 	struct irq_data		irq_data;
+-	struct timer_rand_state *timer_rand_state;
+ 	unsigned int __percpu	*kstat_irqs;
+ 	irq_flow_handler_t	handle_irq;
+ #ifdef CONFIG_IRQ_PREFLOW_FASTEOI
+diff --git a/include/linux/random.h b/include/linux/random.h
+index 29e217a7e6d0..ac621ce886ca 100644
+--- a/include/linux/random.h
++++ b/include/linux/random.h
+@@ -48,8 +48,6 @@ struct rnd_state {
+ 
+ #ifdef __KERNEL__
+ 
+-extern void rand_initialize_irq(int irq);
+-
+ extern void add_device_randomness(const void *, unsigned int);
+ extern void add_input_randomness(unsigned int type, unsigned int code,
+ 				 unsigned int value);
+diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
+index 8c548232ba39..5e42eb119677 100644
+--- a/kernel/irq/manage.c
++++ b/kernel/irq/manage.c
+@@ -893,22 +893,6 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
+ 		return -ENOSYS;
+ 	if (!try_module_get(desc->owner))
+ 		return -ENODEV;
+-	/*
+-	 * Some drivers like serial.c use request_irq() heavily,
+-	 * so we have to be careful not to interfere with a
+-	 * running system.
+-	 */
+-	if (new->flags & IRQF_SAMPLE_RANDOM) {
+-		/*
+-		 * This function might sleep, we want to call it first,
+-		 * outside of the atomic block.
+-		 * Yes, this might clear the entropy pool if the wrong
+-		 * driver is attempted to be loaded, without actually
+-		 * installing a new handler, but is this really a problem,
+-		 * only the sysadmin is able to do this.
+-		 */
+-		rand_initialize_irq(irq);
+-	}
+ 
+ 	/*
+ 	 * Check whether the interrupt nests into another interrupt
+@@ -1354,7 +1338,6 @@ EXPORT_SYMBOL(free_irq);
+  *	Flags:
+  *
+  *	IRQF_SHARED		Interrupt is shared
+- *	IRQF_SAMPLE_RANDOM	The interrupt can be used for entropy
+  *	IRQF_TRIGGER_*		Specify active edge(s) or level
+  *
+  */

commit 330e0a01d54c2b8606c56816f99af6ebc58ec92c
+Author: Theodore Ts'o 
+Date:   Wed Jul 4 11:32:48 2012 -0400
+
+    MAINTAINERS: Theodore Ts'o is taking over the random driver
+    
+    Matt Mackall stepped down as the /dev/random driver maintainer last
+    year, so Theodore Ts'o is taking back the /dev/random driver.
+    
+    Cc: Matt Mackall 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index eb22272b2116..335c525879e5 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -5634,7 +5634,7 @@ F:	Documentation/blockdev/ramdisk.txt
+ F:	drivers/block/brd.c
+ 
+ RANDOM NUMBER DRIVER
+-M:	Matt Mackall 
++M:	Theodore Ts'o" 
+ S:	Maintained
+ F:	drivers/char/random.c
+ 

commit 00ce1db1a634746040ace24c09a4e3a7949a3145
+Author: Theodore Ts'o 
+Date:   Wed Jul 4 16:19:30 2012 -0400
+
+    random: add tracepoints for easier debugging and verification
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index eacd61479112..e3180852ec85 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -266,6 +266,9 @@
+ #include 
+ #include 
+ 
++#define CREATE_TRACE_POINTS
++#include 
++
+ /*
+  * Configuration information
+  */
+@@ -478,8 +481,8 @@ static __u32 const twist_table[8] = {
+  * it's cheap to do so and helps slightly in the expected case where
+  * the entropy is concentrated in the low-order bits.
+  */
+-static void __mix_pool_bytes(struct entropy_store *r, const void *in,
+-			     int nbytes, __u8 out[64])
++static void _mix_pool_bytes(struct entropy_store *r, const void *in,
++			    int nbytes, __u8 out[64])
+ {
+ 	unsigned long i, j, tap1, tap2, tap3, tap4, tap5;
+ 	int input_rotate;
+@@ -531,13 +534,21 @@ static void __mix_pool_bytes(struct entropy_store *r, const void *in,
+ 			((__u32 *)out)[j] = r->pool[(i - j) & wordmask];
+ }
+ 
+-static void mix_pool_bytes(struct entropy_store *r, const void *in,
++static void __mix_pool_bytes(struct entropy_store *r, const void *in,
+ 			     int nbytes, __u8 out[64])
++{
++	trace_mix_pool_bytes_nolock(r->name, nbytes, _RET_IP_);
++	_mix_pool_bytes(r, in, nbytes, out);
++}
++
++static void mix_pool_bytes(struct entropy_store *r, const void *in,
++			   int nbytes, __u8 out[64])
+ {
+ 	unsigned long flags;
+ 
++	trace_mix_pool_bytes(r->name, nbytes, _RET_IP_);
+ 	spin_lock_irqsave(&r->lock, flags);
+-	__mix_pool_bytes(r, in, nbytes, out);
++	_mix_pool_bytes(r, in, nbytes, out);
+ 	spin_unlock_irqrestore(&r->lock, flags);
+ }
+ 
+@@ -585,6 +596,7 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
+ retry:
+ 	entropy_count = orig = ACCESS_ONCE(r->entropy_count);
+ 	entropy_count += nbits;
++
+ 	if (entropy_count < 0) {
+ 		DEBUG_ENT("negative entropy/overflow\n");
+ 		entropy_count = 0;
+@@ -599,6 +611,9 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
+ 			r->initialized = 1;
+ 	}
+ 
++	trace_credit_entropy_bits(r->name, nbits, entropy_count,
++				  r->entropy_total, _RET_IP_);
++
+ 	/* should we wake readers? */
+ 	if (r == &input_pool && entropy_count >= random_read_wakeup_thresh) {
+ 		wake_up_interruptible(&random_read_wait);
+@@ -971,6 +986,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
+ 	ssize_t ret = 0, i;
+ 	__u8 tmp[EXTRACT_SIZE];
+ 
++	trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_);
+ 	xfer_secondary_pool(r, nbytes);
+ 	nbytes = account(r, nbytes, min, reserved);
+ 
+@@ -1005,6 +1021,7 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
+ 	ssize_t ret = 0, i;
+ 	__u8 tmp[EXTRACT_SIZE];
+ 
++	trace_extract_entropy_user(r->name, nbytes, r->entropy_count, _RET_IP_);
+ 	xfer_secondary_pool(r, nbytes);
+ 	nbytes = account(r, nbytes, 0, 0);
+ 
+@@ -1062,6 +1079,7 @@ void get_random_bytes_arch(void *buf, int nbytes)
+ {
+ 	char *p = buf;
+ 
++	trace_get_random_bytes(nbytes, _RET_IP_);
+ 	while (nbytes) {
+ 		unsigned long v;
+ 		int chunk = min(nbytes, (int)sizeof(unsigned long));
+diff --git a/include/trace/events/random.h b/include/trace/events/random.h
+new file mode 100644
+index 000000000000..422df19de732
+--- /dev/null
++++ b/include/trace/events/random.h
+@@ -0,0 +1,134 @@
++#undef TRACE_SYSTEM
++#define TRACE_SYSTEM random
++
++#if !defined(_TRACE_RANDOM_H) || defined(TRACE_HEADER_MULTI_READ)
++#define _TRACE_RANDOM_H
++
++#include 
++#include 
++
++DECLARE_EVENT_CLASS(random__mix_pool_bytes,
++	TP_PROTO(const char *pool_name, int bytes, unsigned long IP),
++
++	TP_ARGS(pool_name, bytes, IP),
++
++	TP_STRUCT__entry(
++		__field( const char *,	pool_name		)
++		__field(	  int,	bytes			)
++		__field(unsigned long,	IP			)
++	),
++
++	TP_fast_assign(
++		__entry->pool_name	= pool_name;
++		__entry->bytes		= bytes;
++		__entry->IP		= IP;
++	),
++
++	TP_printk("%s pool: bytes %d caller %pF",
++		  __entry->pool_name, __entry->bytes, (void *)__entry->IP)
++);
++
++DEFINE_EVENT(random__mix_pool_bytes, mix_pool_bytes,
++	TP_PROTO(const char *pool_name, int bytes, unsigned long IP),
++
++	TP_ARGS(pool_name, bytes, IP)
++);
++
++DEFINE_EVENT(random__mix_pool_bytes, mix_pool_bytes_nolock,
++	TP_PROTO(const char *pool_name, int bytes, unsigned long IP),
++
++	TP_ARGS(pool_name, bytes, IP)
++);
++
++TRACE_EVENT(credit_entropy_bits,
++	TP_PROTO(const char *pool_name, int bits, int entropy_count,
++		 int entropy_total, unsigned long IP),
++
++	TP_ARGS(pool_name, bits, entropy_count, entropy_total, IP),
++
++	TP_STRUCT__entry(
++		__field( const char *,	pool_name		)
++		__field(	  int,	bits			)
++		__field(	  int,	entropy_count		)
++		__field(	  int,	entropy_total		)
++		__field(unsigned long,	IP			)
++	),
++
++	TP_fast_assign(
++		__entry->pool_name	= pool_name;
++		__entry->bits		= bits;
++		__entry->entropy_count	= entropy_count;
++		__entry->entropy_total	= entropy_total;
++		__entry->IP		= IP;
++	),
++
++	TP_printk("%s pool: bits %d entropy_count %d entropy_total %d "
++		  "caller %pF", __entry->pool_name, __entry->bits,
++		  __entry->entropy_count, __entry->entropy_total,
++		  (void *)__entry->IP)
++);
++
++TRACE_EVENT(get_random_bytes,
++	TP_PROTO(int nbytes, unsigned long IP),
++
++	TP_ARGS(nbytes, IP),
++
++	TP_STRUCT__entry(
++		__field(	  int,	nbytes			)
++		__field(unsigned long,	IP			)
++	),
++
++	TP_fast_assign(
++		__entry->nbytes		= nbytes;
++		__entry->IP		= IP;
++	),
++
++	TP_printk("nbytes %d caller %pF", __entry->nbytes, (void *)__entry->IP)
++);
++
++DECLARE_EVENT_CLASS(random__extract_entropy,
++	TP_PROTO(const char *pool_name, int nbytes, int entropy_count,
++		 unsigned long IP),
++
++	TP_ARGS(pool_name, nbytes, entropy_count, IP),
++
++	TP_STRUCT__entry(
++		__field( const char *,	pool_name		)
++		__field(	  int,	nbytes			)
++		__field(	  int,	entropy_count		)
++		__field(unsigned long,	IP			)
++	),
++
++	TP_fast_assign(
++		__entry->pool_name	= pool_name;
++		__entry->nbytes		= nbytes;
++		__entry->entropy_count	= entropy_count;
++		__entry->IP		= IP;
++	),
++
++	TP_printk("%s pool: nbytes %d entropy_count %d caller %pF",
++		  __entry->pool_name, __entry->nbytes, __entry->entropy_count,
++		  (void *)__entry->IP)
++);
++
++
++DEFINE_EVENT(random__extract_entropy, extract_entropy,
++	TP_PROTO(const char *pool_name, int nbytes, int entropy_count,
++		 unsigned long IP),
++
++	TP_ARGS(pool_name, nbytes, entropy_count, IP)
++);
++
++DEFINE_EVENT(random__extract_entropy, extract_entropy_user,
++	TP_PROTO(const char *pool_name, int nbytes, int entropy_count,
++		 unsigned long IP),
++
++	TP_ARGS(pool_name, nbytes, entropy_count, IP)
++);
++
++
++
++#endif /* _TRACE_RANDOM_H */
++
++/* This part must be outside protection */
++#include 

commit c2557a303ab6712bb6e09447df828c557c710ac9
+Author: Theodore Ts'o 
+Date:   Thu Jul 5 10:35:23 2012 -0400
+
+    random: add new get_random_bytes_arch() function
+    
+    Create a new function, get_random_bytes_arch() which will use the
+    architecture-specific hardware random number generator if it is
+    present.  Change get_random_bytes() to not use the HW RNG, even if it
+    is avaiable.
+    
+    The reason for this is that the hw random number generator is fast (if
+    it is present), but it requires that we trust the hardware
+    manufacturer to have not put in a back door.  (For example, an
+    increasing counter encrypted by an AES key known to the NSA.)
+    
+    It's unlikely that Intel (for example) was paid off by the US
+    Government to do this, but it's impossible for them to prove otherwise
+    --- especially since Bull Mountain is documented to use AES as a
+    whitener.  Hence, the output of an evil, trojan-horse version of
+    RDRAND is statistically indistinguishable from an RDRAND implemented
+    to the specifications claimed by Intel.  Short of using a tunnelling
+    electronic microscope to reverse engineer an Ivy Bridge chip and
+    disassembling and analyzing the CPU microcode, there's no way for us
+    to tell for sure.
+    
+    Since users of get_random_bytes() in the Linux kernel need to be able
+    to support hardware systems where the HW RNG is not present, most
+    time-sensitive users of this interface have already created their own
+    cryptographic RNG interface which uses get_random_bytes() as a seed.
+    So it's much better to use the HW RNG to improve the existing random
+    number generator, by mixing in any entropy returned by the HW RNG into
+    /dev/random's entropy pool, but to always _use_ /dev/random's entropy
+    pool.
+    
+    This way we get almost of the benefits of the HW RNG without any
+    potential liabilities.  The only benefits we forgo is the
+    speed/performance enhancements --- and generic kernel code can't
+    depend on depend on get_random_bytes() having the speed of a HW RNG
+    anyway.
+    
+    For those places that really want access to the arch-specific HW RNG,
+    if it is available, we provide get_random_bytes_arch().
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index f67ae3e473ba..eacd61479112 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -1038,17 +1038,34 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
+ 
+ /*
+  * This function is the exported kernel interface.  It returns some
+- * number of good random numbers, suitable for seeding TCP sequence
+- * numbers, etc.
++ * number of good random numbers, suitable for key generation, seeding
++ * TCP sequence numbers, etc.  It does not use the hw random number
++ * generator, if available; use get_random_bytes_arch() for that.
+  */
+ void get_random_bytes(void *buf, int nbytes)
++{
++	extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0);
++}
++EXPORT_SYMBOL(get_random_bytes);
++
++/*
++ * This function will use the architecture-specific hardware random
++ * number generator if it is available.  The arch-specific hw RNG will
++ * almost certainly be faster than what we can do in software, but it
++ * is impossible to verify that it is implemented securely (as
++ * opposed, to, say, the AES encryption of a sequence number using a
++ * key known by the NSA).  So it's useful if we need the speed, but
++ * only if we're willing to trust the hardware manufacturer not to
++ * have put in a back door.
++ */
++void get_random_bytes_arch(void *buf, int nbytes)
+ {
+ 	char *p = buf;
+ 
+ 	while (nbytes) {
+ 		unsigned long v;
+ 		int chunk = min(nbytes, (int)sizeof(unsigned long));
+-		
++
+ 		if (!arch_get_random_long(&v))
+ 			break;
+ 		
+@@ -1057,9 +1074,11 @@ void get_random_bytes(void *buf, int nbytes)
+ 		nbytes -= chunk;
+ 	}
+ 
+-	extract_entropy(&nonblocking_pool, p, nbytes, 0, 0);
++	if (nbytes)
++		extract_entropy(&nonblocking_pool, p, nbytes, 0, 0);
+ }
+-EXPORT_SYMBOL(get_random_bytes);
++EXPORT_SYMBOL(get_random_bytes_arch);
++
+ 
+ /*
+  * init_std_data - initialize pool with system data
+diff --git a/include/linux/random.h b/include/linux/random.h
+index e14b4387354a..29e217a7e6d0 100644
+--- a/include/linux/random.h
++++ b/include/linux/random.h
+@@ -56,6 +56,7 @@ extern void add_input_randomness(unsigned int type, unsigned int code,
+ extern void add_interrupt_randomness(int irq, int irq_flags);
+ 
+ extern void get_random_bytes(void *buf, int nbytes);
++extern void get_random_bytes_arch(void *buf, int nbytes);
+ void generate_random_uuid(unsigned char uuid_out[16]);
+ 
+ #ifndef MODULE

commit e6d4947b12e8ad947add1032dd754803c6004824
+Author: Theodore Ts'o 
+Date:   Thu Jul 5 10:21:01 2012 -0400
+
+    random: use the arch-specific rng in xfer_secondary_pool
+    
+    If the CPU supports a hardware random number generator, use it in
+    xfer_secondary_pool(), where it will significantly improve things and
+    where we can afford it.
+    
+    Also, remove the use of the arch-specific rng in
+    add_timer_randomness(), since the call is significantly slower than
+    get_cycles(), and we're much better off using it in
+    xfer_secondary_pool() anyway.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index df3358ab5b99..f67ae3e473ba 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -254,6 +254,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #ifdef CONFIG_GENERIC_HARDIRQS
+ # include 
+@@ -702,11 +703,7 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
+ 		goto out;
+ 
+ 	sample.jiffies = jiffies;
+-
+-	/* Use arch random value, fall back to cycles */
+-	if (!arch_get_random_int(&sample.cycles))
+-		sample.cycles = get_cycles();
+-
++	sample.cycles = get_cycles();
+ 	sample.num = num;
+ 	mix_pool_bytes(&input_pool, &sample, sizeof(sample), NULL);
+ 
+@@ -838,7 +835,11 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
+  */
+ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
+ {
+-	__u32 tmp[OUTPUT_POOL_WORDS];
++	union {
++		__u32	tmp[OUTPUT_POOL_WORDS];
++		long	hwrand[4];
++	} u;
++	int	i;
+ 
+ 	if (r->pull && r->entropy_count < nbytes * 8 &&
+ 	    r->entropy_count < r->poolinfo->POOLBITS) {
+@@ -849,17 +850,23 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
+ 		/* pull at least as many as BYTES as wakeup BITS */
+ 		bytes = max_t(int, bytes, random_read_wakeup_thresh / 8);
+ 		/* but never more than the buffer size */
+-		bytes = min_t(int, bytes, sizeof(tmp));
++		bytes = min_t(int, bytes, sizeof(u.tmp));
+ 
+ 		DEBUG_ENT("going to reseed %s with %d bits "
+ 			  "(%d of %d requested)\n",
+ 			  r->name, bytes * 8, nbytes * 8, r->entropy_count);
+ 
+-		bytes = extract_entropy(r->pull, tmp, bytes,
++		bytes = extract_entropy(r->pull, u.tmp, bytes,
+ 					random_read_wakeup_thresh / 8, rsvd);
+-		mix_pool_bytes(r, tmp, bytes, NULL);
++		mix_pool_bytes(r, u.tmp, bytes, NULL);
+ 		credit_entropy_bits(r, bytes*8);
+ 	}
++	kmemcheck_mark_initialized(&u.hwrand, sizeof(u.hwrand));
++	for (i = 0; i < 4; i++)
++		if (arch_get_random_long(&u.hwrand[i]))
++			break;
++	if (i)
++		mix_pool_bytes(r, &u.hwrand, sizeof(u.hwrand), 0);
+ }
+ 
+ /*

commit 7bf2357524408b97fec58344caf7397f8140c3fd
+Author: Theodore Ts'o 
+Date:   Wed Jul 4 21:23:25 2012 -0400
+
+    net: feed /dev/random with the MAC address when registering a device
+    
+    Cc: David Miller 
+    Cc: Linus Torvalds 
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/net/core/dev.c b/net/core/dev.c
+index 6df214041a5e..bdd1e88f60d3 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -1172,6 +1172,7 @@ static int __dev_open(struct net_device *dev)
+ 		net_dmaengine_get();
+ 		dev_set_rx_mode(dev);
+ 		dev_activate(dev);
++		add_device_randomness(dev->dev_addr, dev->addr_len);
+ 	}
+ 
+ 	return ret;
+@@ -4763,6 +4764,7 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa)
+ 	err = ops->ndo_set_mac_address(dev, sa);
+ 	if (!err)
+ 		call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
++	add_device_randomness(dev->dev_addr, dev->addr_len);
+ 	return err;
+ }
+ EXPORT_SYMBOL(dev_set_mac_address);
+@@ -5541,6 +5543,7 @@ int register_netdevice(struct net_device *dev)
+ 	dev_init_scheduler(dev);
+ 	dev_hold(dev);
+ 	list_netdevice(dev);
++	add_device_randomness(dev->dev_addr, dev->addr_len);
+ 
+ 	/* Notify protocols, that a new device appeared. */
+ 	ret = call_netdevice_notifiers(NETDEV_REGISTER, dev);
+diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
+index 21318d15bbc3..f058e599d858 100644
+--- a/net/core/rtnetlink.c
++++ b/net/core/rtnetlink.c
+@@ -1378,6 +1378,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
+ 			goto errout;
+ 		send_addr_notify = 1;
+ 		modified = 1;
++		add_device_randomness(dev->dev_addr, dev->addr_len);
+ 	}
+ 
+ 	if (tb[IFLA_MTU]) {

commit b04b3156a20d395a7faa8eed98698d1e17a36000
+Author: Theodore Ts'o 
+Date:   Wed Jul 4 11:22:20 2012 -0400
+
+    usb: feed USB device information to the /dev/random driver
+    
+    Send the USB device's serial, product, and manufacturer strings to the
+    /dev/random driver to help seed its pools.
+    
+    Cc: Linus Torvalds 
+    Acked-by: Greg KH 
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 25a7422ee657..7f380ff1f786 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -24,6 +24,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ #include 
+@@ -2173,6 +2174,14 @@ int usb_new_device(struct usb_device *udev)
+ 	/* Tell the world! */
+ 	announce_device(udev);
+ 
++	if (udev->serial)
++		add_device_randomness(udev->serial, strlen(udev->serial));
++	if (udev->product)
++		add_device_randomness(udev->product, strlen(udev->product));
++	if (udev->manufacturer)
++		add_device_randomness(udev->manufacturer,
++				      strlen(udev->manufacturer));
++
+ 	device_enable_async_suspend(&udev->dev);
+ 
+ 	/*

commit 902c098a3663de3fa18639efbb71b6080f0bcd3c
+Author: Theodore Ts'o 
+Date:   Wed Jul 4 10:38:30 2012 -0400
+
+    random: use lockless techniques in the interrupt path
+    
+    The real-time Linux folks don't like add_interrupt_randomness() taking
+    a spinlock since it is called in the low-level interrupt routine.
+    This also allows us to reduce the overhead in the fast path, for the
+    random driver, which is the interrupt collection path.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 9fcceace239c..315feb1f59f3 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -418,9 +418,9 @@ struct entropy_store {
+ 	/* read-write data: */
+ 	spinlock_t lock;
+ 	unsigned add_ptr;
++	unsigned input_rotate;
+ 	int entropy_count;
+ 	int entropy_total;
+-	int input_rotate;
+ 	unsigned int initialized:1;
+ 	__u8 last_data[EXTRACT_SIZE];
+ };
+@@ -468,26 +468,24 @@ static __u32 const twist_table[8] = {
+  * it's cheap to do so and helps slightly in the expected case where
+  * the entropy is concentrated in the low-order bits.
+  */
+-static void mix_pool_bytes_extract(struct entropy_store *r, const void *in,
+-				   int nbytes, __u8 out[64])
++static void __mix_pool_bytes(struct entropy_store *r, const void *in,
++			     int nbytes, __u8 out[64])
+ {
+ 	unsigned long i, j, tap1, tap2, tap3, tap4, tap5;
+ 	int input_rotate;
+ 	int wordmask = r->poolinfo->poolwords - 1;
+ 	const char *bytes = in;
+ 	__u32 w;
+-	unsigned long flags;
+ 
+-	/* Taps are constant, so we can load them without holding r->lock.  */
+ 	tap1 = r->poolinfo->tap1;
+ 	tap2 = r->poolinfo->tap2;
+ 	tap3 = r->poolinfo->tap3;
+ 	tap4 = r->poolinfo->tap4;
+ 	tap5 = r->poolinfo->tap5;
+ 
+-	spin_lock_irqsave(&r->lock, flags);
+-	input_rotate = r->input_rotate;
+-	i = r->add_ptr;
++	smp_rmb();
++	input_rotate = ACCESS_ONCE(r->input_rotate);
++	i = ACCESS_ONCE(r->add_ptr);
+ 
+ 	/* mix one byte at a time to simplify size handling and churn faster */
+ 	while (nbytes--) {
+@@ -514,19 +512,23 @@ static void mix_pool_bytes_extract(struct entropy_store *r, const void *in,
+ 		input_rotate += i ? 7 : 14;
+ 	}
+ 
+-	r->input_rotate = input_rotate;
+-	r->add_ptr = i;
++	ACCESS_ONCE(r->input_rotate) = input_rotate;
++	ACCESS_ONCE(r->add_ptr) = i;
++	smp_wmb();
+ 
+ 	if (out)
+ 		for (j = 0; j < 16; j++)
+ 			((__u32 *)out)[j] = r->pool[(i - j) & wordmask];
+-
+-	spin_unlock_irqrestore(&r->lock, flags);
+ }
+ 
+-static void mix_pool_bytes(struct entropy_store *r, const void *in, int bytes)
++static void mix_pool_bytes(struct entropy_store *r, const void *in,
++			     int nbytes, __u8 out[64])
+ {
+-       mix_pool_bytes_extract(r, in, bytes, NULL);
++	unsigned long flags;
++
++	spin_lock_irqsave(&r->lock, flags);
++	__mix_pool_bytes(r, in, nbytes, out);
++	spin_unlock_irqrestore(&r->lock, flags);
+ }
+ 
+ struct fast_pool {
+@@ -564,23 +566,22 @@ static void fast_mix(struct fast_pool *f, const void *in, int nbytes)
+  */
+ static void credit_entropy_bits(struct entropy_store *r, int nbits)
+ {
+-	unsigned long flags;
+-	int entropy_count;
++	int entropy_count, orig;
+ 
+ 	if (!nbits)
+ 		return;
+ 
+-	spin_lock_irqsave(&r->lock, flags);
+-
+ 	DEBUG_ENT("added %d entropy credits to %s\n", nbits, r->name);
+-	entropy_count = r->entropy_count;
++retry:
++	entropy_count = orig = ACCESS_ONCE(r->entropy_count);
+ 	entropy_count += nbits;
+ 	if (entropy_count < 0) {
+ 		DEBUG_ENT("negative entropy/overflow\n");
+ 		entropy_count = 0;
+ 	} else if (entropy_count > r->poolinfo->POOLBITS)
+ 		entropy_count = r->poolinfo->POOLBITS;
+-	r->entropy_count = entropy_count;
++	if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
++		goto retry;
+ 
+ 	if (!r->initialized && nbits > 0) {
+ 		r->entropy_total += nbits;
+@@ -593,7 +594,6 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
+ 		wake_up_interruptible(&random_read_wait);
+ 		kill_fasync(&fasync, SIGIO, POLL_IN);
+ 	}
+-	spin_unlock_irqrestore(&r->lock, flags);
+ }
+ 
+ /*********************************************************************
+@@ -680,7 +680,7 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
+ 		sample.cycles = get_cycles();
+ 
+ 	sample.num = num;
+-	mix_pool_bytes(&input_pool, &sample, sizeof(sample));
++	mix_pool_bytes(&input_pool, &sample, sizeof(sample), NULL);
+ 
+ 	/*
+ 	 * Calculate number of bits of randomness we probably added.
+@@ -764,7 +764,7 @@ void add_interrupt_randomness(int irq, int irq_flags)
+ 	fast_pool->last = now;
+ 
+ 	r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
+-	mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool));
++	__mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool), NULL);
+ 	/*
+ 	 * If we don't have a valid cycle counter, and we see
+ 	 * back-to-back timer interrupts, then skip giving credit for
+@@ -829,7 +829,7 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
+ 
+ 		bytes = extract_entropy(r->pull, tmp, bytes,
+ 					random_read_wakeup_thresh / 8, rsvd);
+-		mix_pool_bytes(r, tmp, bytes);
++		mix_pool_bytes(r, tmp, bytes, NULL);
+ 		credit_entropy_bits(r, bytes*8);
+ 	}
+ }
+@@ -890,9 +890,11 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
+ 	int i;
+ 	__u32 hash[5], workspace[SHA_WORKSPACE_WORDS];
+ 	__u8 extract[64];
++	unsigned long flags;
+ 
+ 	/* Generate a hash across the pool, 16 words (512 bits) at a time */
+ 	sha_init(hash);
++	spin_lock_irqsave(&r->lock, flags);
+ 	for (i = 0; i < r->poolinfo->poolwords; i += 16)
+ 		sha_transform(hash, (__u8 *)(r->pool + i), workspace);
+ 
+@@ -905,7 +907,8 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
+ 	 * brute-forcing the feedback as hard as brute-forcing the
+ 	 * hash.
+ 	 */
+-	mix_pool_bytes_extract(r, hash, sizeof(hash), extract);
++	__mix_pool_bytes(r, hash, sizeof(hash), extract);
++	spin_unlock_irqrestore(&r->lock, flags);
+ 
+ 	/*
+ 	 * To avoid duplicates, we atomically extract a portion of the
+@@ -928,11 +931,10 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
+ }
+ 
+ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
+-			       size_t nbytes, int min, int reserved)
++				 size_t nbytes, int min, int reserved)
+ {
+ 	ssize_t ret = 0, i;
+ 	__u8 tmp[EXTRACT_SIZE];
+-	unsigned long flags;
+ 
+ 	xfer_secondary_pool(r, nbytes);
+ 	nbytes = account(r, nbytes, min, reserved);
+@@ -941,6 +943,8 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
+ 		extract_buf(r, tmp);
+ 
+ 		if (fips_enabled) {
++			unsigned long flags;
++
+ 			spin_lock_irqsave(&r->lock, flags);
+ 			if (!memcmp(tmp, r->last_data, EXTRACT_SIZE))
+ 				panic("Hardware RNG duplicated output!\n");
+@@ -1034,22 +1038,18 @@ EXPORT_SYMBOL(get_random_bytes);
+ static void init_std_data(struct entropy_store *r)
+ {
+ 	int i;
+-	ktime_t now;
+-	unsigned long flags;
++	ktime_t now = ktime_get_real();
++	unsigned long rv;
+ 
+-	spin_lock_irqsave(&r->lock, flags);
+ 	r->entropy_count = 0;
+ 	r->entropy_total = 0;
+-	spin_unlock_irqrestore(&r->lock, flags);
+-
+-	now = ktime_get_real();
+-	mix_pool_bytes(r, &now, sizeof(now));
+-	for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof flags) {
+-		if (!arch_get_random_long(&flags))
++	mix_pool_bytes(r, &now, sizeof(now), NULL);
++	for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof(rv)) {
++		if (!arch_get_random_long(&rv))
+ 			break;
+-		mix_pool_bytes(r, &flags, sizeof(flags));
++		mix_pool_bytes(r, &rv, sizeof(rv), NULL);
+ 	}
+-	mix_pool_bytes(r, utsname(), sizeof(*(utsname())));
++	mix_pool_bytes(r, utsname(), sizeof(*(utsname())), NULL);
+ }
+ 
+ static int rand_initialize(void)
+@@ -1186,7 +1186,7 @@ write_pool(struct entropy_store *r, const char __user *buffer, size_t count)
+ 		count -= bytes;
+ 		p += bytes;
+ 
+-		mix_pool_bytes(r, buf, bytes);
++		mix_pool_bytes(r, buf, bytes, NULL);
+ 		cond_resched();
+ 	}
+ 

commit 775f4b297b780601e61787b766f306ed3e1d23eb
+Author: Theodore Ts'o 
+Date:   Mon Jul 2 07:52:16 2012 -0400
+
+    random: make 'add_interrupt_randomness()' do something sane
+    
+    We've been moving away from add_interrupt_randomness() for various
+    reasons: it's too expensive to do on every interrupt, and flooding the
+    CPU with interrupts could theoretically cause bogus floods of entropy
+    from a somewhat externally controllable source.
+    
+    This solves both problems by limiting the actual randomness addition
+    to just once a second or after 64 interrupts, whicever comes first.
+    During that time, the interrupt cycle data is buffered up in a per-cpu
+    pool.  Also, we make sure the the nonblocking pool used by urandom is
+    initialized before we start feeding the normal input pool.  This
+    assures that /dev/urandom is returning unpredictable data as soon as
+    possible.
+    
+    (Based on an original patch by Linus, but significantly modified by
+    tytso.)
+    
+    Tested-by: Eric Wustrow 
+    Reported-by: Eric Wustrow 
+    Reported-by: Nadia Heninger 
+    Reported-by: Zakir Durumeric 
+    Reported-by: J. Alex Halderman .
+    Signed-off-by: Linus Torvalds 
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index cb541b9a5231..9fcceace239c 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -127,19 +127,15 @@
+  *
+  * 	void add_input_randomness(unsigned int type, unsigned int code,
+  *                                unsigned int value);
+- * 	void add_interrupt_randomness(int irq);
++ *	void add_interrupt_randomness(int irq, int irq_flags);
+  * 	void add_disk_randomness(struct gendisk *disk);
+  *
+  * add_input_randomness() uses the input layer interrupt timing, as well as
+  * the event type information from the hardware.
+  *
+- * add_interrupt_randomness() uses the inter-interrupt timing as random
+- * inputs to the entropy pool.  Note that not all interrupts are good
+- * sources of randomness!  For example, the timer interrupts is not a
+- * good choice, because the periodicity of the interrupts is too
+- * regular, and hence predictable to an attacker.  Network Interface
+- * Controller interrupts are a better measure, since the timing of the
+- * NIC interrupts are more unpredictable.
++ * add_interrupt_randomness() uses the interrupt timing as random
++ * inputs to the entropy pool. Using the cycle counters and the irq source
++ * as inputs, it feeds the randomness roughly once a second.
+  *
+  * add_disk_randomness() uses what amounts to the seek time of block
+  * layer request events, on a per-disk_devt basis, as input to the
+@@ -248,6 +244,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #ifdef CONFIG_GENERIC_HARDIRQS
+ # include 
+@@ -256,6 +253,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ 
+ /*
+@@ -421,7 +419,9 @@ struct entropy_store {
+ 	spinlock_t lock;
+ 	unsigned add_ptr;
+ 	int entropy_count;
++	int entropy_total;
+ 	int input_rotate;
++	unsigned int initialized:1;
+ 	__u8 last_data[EXTRACT_SIZE];
+ };
+ 
+@@ -454,6 +454,10 @@ static struct entropy_store nonblocking_pool = {
+ 	.pool = nonblocking_pool_data
+ };
+ 
++static __u32 const twist_table[8] = {
++	0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
++	0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
++
+ /*
+  * This function adds bytes into the entropy "pool".  It does not
+  * update the entropy estimate.  The caller should call
+@@ -467,9 +471,6 @@ static struct entropy_store nonblocking_pool = {
+ static void mix_pool_bytes_extract(struct entropy_store *r, const void *in,
+ 				   int nbytes, __u8 out[64])
+ {
+-	static __u32 const twist_table[8] = {
+-		0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
+-		0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
+ 	unsigned long i, j, tap1, tap2, tap3, tap4, tap5;
+ 	int input_rotate;
+ 	int wordmask = r->poolinfo->poolwords - 1;
+@@ -528,6 +529,36 @@ static void mix_pool_bytes(struct entropy_store *r, const void *in, int bytes)
+        mix_pool_bytes_extract(r, in, bytes, NULL);
+ }
+ 
++struct fast_pool {
++	__u32		pool[4];
++	unsigned long	last;
++	unsigned short	count;
++	unsigned char	rotate;
++	unsigned char	last_timer_intr;
++};
++
++/*
++ * This is a fast mixing routine used by the interrupt randomness
++ * collector.  It's hardcoded for an 128 bit pool and assumes that any
++ * locks that might be needed are taken by the caller.
++ */
++static void fast_mix(struct fast_pool *f, const void *in, int nbytes)
++{
++	const char	*bytes = in;
++	__u32		w;
++	unsigned	i = f->count;
++	unsigned	input_rotate = f->rotate;
++
++	while (nbytes--) {
++		w = rol32(*bytes++, input_rotate & 31) ^ f->pool[i & 3] ^
++			f->pool[(i + 1) & 3];
++		f->pool[i & 3] = (w >> 3) ^ twist_table[w & 7];
++		input_rotate += (i++ & 3) ? 7 : 14;
++	}
++	f->count = i;
++	f->rotate = input_rotate;
++}
++
+ /*
+  * Credit (or debit) the entropy store with n bits of entropy
+  */
+@@ -551,6 +582,12 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
+ 		entropy_count = r->poolinfo->POOLBITS;
+ 	r->entropy_count = entropy_count;
+ 
++	if (!r->initialized && nbits > 0) {
++		r->entropy_total += nbits;
++		if (r->entropy_total > 128)
++			r->initialized = 1;
++	}
++
+ 	/* should we wake readers? */
+ 	if (r == &input_pool && entropy_count >= random_read_wakeup_thresh) {
+ 		wake_up_interruptible(&random_read_wait);
+@@ -700,17 +737,48 @@ void add_input_randomness(unsigned int type, unsigned int code,
+ }
+ EXPORT_SYMBOL_GPL(add_input_randomness);
+ 
+-void add_interrupt_randomness(int irq)
++static DEFINE_PER_CPU(struct fast_pool, irq_randomness);
++
++void add_interrupt_randomness(int irq, int irq_flags)
+ {
+-	struct timer_rand_state *state;
++	struct entropy_store	*r;
++	struct fast_pool	*fast_pool = &__get_cpu_var(irq_randomness);
++	struct pt_regs		*regs = get_irq_regs();
++	unsigned long		now = jiffies;
++	__u32			input[4], cycles = get_cycles();
++
++	input[0] = cycles ^ jiffies;
++	input[1] = irq;
++	if (regs) {
++		__u64 ip = instruction_pointer(regs);
++		input[2] = ip;
++		input[3] = ip >> 32;
++	}
+ 
+-	state = get_timer_rand_state(irq);
++	fast_mix(fast_pool, input, sizeof(input));
+ 
+-	if (state == NULL)
++	if ((fast_pool->count & 1023) &&
++	    !time_after(now, fast_pool->last + HZ))
+ 		return;
+ 
+-	DEBUG_ENT("irq event %d\n", irq);
+-	add_timer_randomness(state, 0x100 + irq);
++	fast_pool->last = now;
++
++	r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
++	mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool));
++	/*
++	 * If we don't have a valid cycle counter, and we see
++	 * back-to-back timer interrupts, then skip giving credit for
++	 * any entropy.
++	 */
++	if (cycles == 0) {
++		if (irq_flags & __IRQF_TIMER) {
++			if (fast_pool->last_timer_intr)
++				return;
++			fast_pool->last_timer_intr = 1;
++		} else
++			fast_pool->last_timer_intr = 0;
++	}
++	credit_entropy_bits(r, 1);
+ }
+ 
+ #ifdef CONFIG_BLOCK
+@@ -971,6 +1039,7 @@ static void init_std_data(struct entropy_store *r)
+ 
+ 	spin_lock_irqsave(&r->lock, flags);
+ 	r->entropy_count = 0;
++	r->entropy_total = 0;
+ 	spin_unlock_irqrestore(&r->lock, flags);
+ 
+ 	now = ktime_get_real();
+diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
+index 1efad20fb175..9522d6bda4f7 100644
+--- a/drivers/mfd/ab3100-core.c
++++ b/drivers/mfd/ab3100-core.c
+@@ -409,8 +409,6 @@ static irqreturn_t ab3100_irq_handler(int irq, void *data)
+ 	u32 fatevent;
+ 	int err;
+ 
+-	add_interrupt_randomness(irq);
+-
+ 	err = ab3100_get_register_page_interruptible(ab3100, AB3100_EVENTA1,
+ 				       event_regs, 3);
+ 	if (err)
+diff --git a/include/linux/random.h b/include/linux/random.h
+index 8f74538c96db..6ef39d7f2db1 100644
+--- a/include/linux/random.h
++++ b/include/linux/random.h
+@@ -52,7 +52,7 @@ extern void rand_initialize_irq(int irq);
+ 
+ extern void add_input_randomness(unsigned int type, unsigned int code,
+ 				 unsigned int value);
+-extern void add_interrupt_randomness(int irq);
++extern void add_interrupt_randomness(int irq, int irq_flags);
+ 
+ extern void get_random_bytes(void *buf, int nbytes);
+ void generate_random_uuid(unsigned char uuid_out[16]);
+diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
+index bdb180325551..131ca176b497 100644
+--- a/kernel/irq/handle.c
++++ b/kernel/irq/handle.c
+@@ -133,7 +133,7 @@ irqreturn_t
+ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
+ {
+ 	irqreturn_t retval = IRQ_NONE;
+-	unsigned int random = 0, irq = desc->irq_data.irq;
++	unsigned int flags = 0, irq = desc->irq_data.irq;
+ 
+ 	do {
+ 		irqreturn_t res;
+@@ -161,7 +161,7 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
+ 
+ 			/* Fall through to add to randomness */
+ 		case IRQ_HANDLED:
+-			random |= action->flags;
++			flags |= action->flags;
+ 			break;
+ 
+ 		default:
+@@ -172,8 +172,7 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
+ 		action = action->next;
+ 	} while (action);
+ 
+-	if (random & IRQF_SAMPLE_RANDOM)
+-		add_interrupt_randomness(irq);
++	add_interrupt_randomness(irq, flags);
+ 
+ 	if (!noirqdebug)
+ 		note_interrupt(irq, desc, retval);

commit 952fc18ef9ec707ebdc16c0786ec360295e5ff15
+Author: Theodore Ts'o 
+Date:   Mon Jul 9 16:27:05 2012 -0400
+
+    ext4: fix overhead calculation used by ext4_statfs()
+    
+    Commit f975d6bcc7a introduced bug which caused ext4_statfs() to
+    miscalculate the number of file system overhead blocks.  This causes
+    the f_blocks field in the statfs structure to be larger than it should
+    be.  This would in turn cause the "df" output to show the number of
+    data blocks in the file system and the number of data blocks used to
+    be larger than they should be.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/bitmap.c b/fs/ext4/bitmap.c
+index 7e86a6d28c64..a94b9c63ee5c 100644
+--- a/fs/ext4/bitmap.c
++++ b/fs/ext4/bitmap.c
+@@ -11,8 +11,6 @@
+ #include 
+ #include "ext4.h"
+ 
+-#ifdef EXT4FS_DEBUG
+-
+ static const int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
+ 
+ unsigned int ext4_count_free(char *bitmap, unsigned int numchars)
+@@ -25,8 +23,6 @@ unsigned int ext4_count_free(char *bitmap, unsigned int numchars)
+ 	return sum;
+ }
+ 
+-#endif  /*  EXT4FS_DEBUG  */
+-
+ int ext4_inode_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
+ 				  struct ext4_group_desc *gdp,
+ 				  struct buffer_head *bh, int sz)
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 293fa1ced21b..01434f25917d 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1161,8 +1161,7 @@ struct ext4_sb_info {
+ 	unsigned long s_desc_per_block;	/* Number of group descriptors per block */
+ 	ext4_group_t s_groups_count;	/* Number of groups in the fs */
+ 	ext4_group_t s_blockfile_groups;/* Groups acceptable for non-extent files */
+-	unsigned long s_overhead_last;  /* Last calculated overhead */
+-	unsigned long s_blocks_last;    /* Last seen block count */
++	unsigned long s_overhead;  /* # of fs overhead clusters */
+ 	unsigned int s_cluster_ratio;	/* Number of blocks per cluster */
+ 	unsigned int s_cluster_bits;	/* log2 of s_cluster_ratio */
+ 	loff_t s_bitmap_maxbytes;	/* max bytes for bitmap files */
+@@ -2037,6 +2036,7 @@ extern int ext4_group_extend(struct super_block *sb,
+ extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count);
+ 
+ /* super.c */
++extern int ext4_calculate_overhead(struct super_block *sb);
+ extern int ext4_superblock_csum_verify(struct super_block *sb,
+ 				       struct ext4_super_block *es);
+ extern void ext4_superblock_csum_set(struct super_block *sb,
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 7ea6cbb44121..17d38de4068c 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -1197,7 +1197,7 @@ static void ext4_update_super(struct super_block *sb,
+ 	struct ext4_new_group_data *group_data = flex_gd->groups;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	struct ext4_super_block *es = sbi->s_es;
+-	int i;
++	int i, ret;
+ 
+ 	BUG_ON(flex_gd->count == 0 || group_data == NULL);
+ 	/*
+@@ -1272,6 +1272,11 @@ static void ext4_update_super(struct super_block *sb,
+ 			   &sbi->s_flex_groups[flex_group].free_inodes);
+ 	}
+ 
++	/*
++	 * Update the fs overhead information
++	 */
++	ext4_calculate_overhead(sb);
++
+ 	if (test_opt(sb, DEBUG))
+ 		printk(KERN_DEBUG "EXT4-fs: added group %u:"
+ 		       "%llu blocks(%llu free %llu reserved)\n", flex_gd->count,
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index eb7aa3e4ef05..78b7ede2efa0 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3085,6 +3085,114 @@ static int set_journal_csum_feature_set(struct super_block *sb)
+ 	return ret;
+ }
+ 
++/*
++ * Note: calculating the overhead so we can be compatible with
++ * historical BSD practice is quite difficult in the face of
++ * clusters/bigalloc.  This is because multiple metadata blocks from
++ * different block group can end up in the same allocation cluster.
++ * Calculating the exact overhead in the face of clustered allocation
++ * requires either O(all block bitmaps) in memory or O(number of block
++ * groups**2) in time.  We will still calculate the superblock for
++ * older file systems --- and if we come across with a bigalloc file
++ * system with zero in s_overhead_clusters the estimate will be close to
++ * correct especially for very large cluster sizes --- but for newer
++ * file systems, it's better to calculate this figure once at mkfs
++ * time, and store it in the superblock.  If the superblock value is
++ * present (even for non-bigalloc file systems), we will use it.
++ */
++static int count_overhead(struct super_block *sb, ext4_group_t grp,
++			  char *buf)
++{
++	struct ext4_sb_info	*sbi = EXT4_SB(sb);
++	struct ext4_group_desc	*gdp;
++	ext4_fsblk_t		first_block, last_block, b;
++	ext4_group_t		i, ngroups = ext4_get_groups_count(sb);
++	int			s, j, count = 0;
++
++	first_block = le32_to_cpu(sbi->s_es->s_first_data_block) +
++		(grp * EXT4_BLOCKS_PER_GROUP(sb));
++	last_block = first_block + EXT4_BLOCKS_PER_GROUP(sb) - 1;
++	for (i = 0; i < ngroups; i++) {
++		gdp = ext4_get_group_desc(sb, i, NULL);
++		b = ext4_block_bitmap(sb, gdp);
++		if (b >= first_block && b <= last_block) {
++			ext4_set_bit(EXT4_B2C(sbi, b - first_block), buf);
++			count++;
++		}
++		b = ext4_inode_bitmap(sb, gdp);
++		if (b >= first_block && b <= last_block) {
++			ext4_set_bit(EXT4_B2C(sbi, b - first_block), buf);
++			count++;
++		}
++		b = ext4_inode_table(sb, gdp);
++		if (b >= first_block && b + sbi->s_itb_per_group <= last_block)
++			for (j = 0; j < sbi->s_itb_per_group; j++, b++) {
++				int c = EXT4_B2C(sbi, b - first_block);
++				ext4_set_bit(c, buf);
++				count++;
++			}
++		if (i != grp)
++			continue;
++		s = 0;
++		if (ext4_bg_has_super(sb, grp)) {
++			ext4_set_bit(s++, buf);
++			count++;
++		}
++		for (j = ext4_bg_num_gdb(sb, grp); j > 0; j--) {
++			ext4_set_bit(EXT4_B2C(sbi, s++), buf);
++			count++;
++		}
++	}
++	if (!count)
++		return 0;
++	return EXT4_CLUSTERS_PER_GROUP(sb) -
++		ext4_count_free(buf, EXT4_CLUSTERS_PER_GROUP(sb) / 8);
++}
++
++/*
++ * Compute the overhead and stash it in sbi->s_overhead
++ */
++int ext4_calculate_overhead(struct super_block *sb)
++{
++	struct ext4_sb_info *sbi = EXT4_SB(sb);
++	struct ext4_super_block *es = sbi->s_es;
++	ext4_group_t i, ngroups = ext4_get_groups_count(sb);
++	ext4_fsblk_t overhead = 0;
++	char *buf = (char *) get_zeroed_page(GFP_KERNEL);
++
++	memset(buf, 0, PAGE_SIZE);
++	if (!buf)
++		return -ENOMEM;
++
++	/*
++	 * Compute the overhead (FS structures).  This is constant
++	 * for a given filesystem unless the number of block groups
++	 * changes so we cache the previous value until it does.
++	 */
++
++	/*
++	 * All of the blocks before first_data_block are overhead
++	 */
++	overhead = EXT4_B2C(sbi, le32_to_cpu(es->s_first_data_block));
++
++	/*
++	 * Add the overhead found in each block group
++	 */
++	for (i = 0; i < ngroups; i++) {
++		int blks;
++
++		blks = count_overhead(sb, i, buf);
++		overhead += blks;
++		if (blks)
++			memset(buf, 0, PAGE_SIZE);
++		cond_resched();
++	}
++	sbi->s_overhead = overhead;
++	smp_wmb();
++	free_page((unsigned long) buf);
++	return 0;
++}
++
+ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ {
+ 	char *orig_data = kstrdup(data, GFP_KERNEL);
+@@ -3734,6 +3842,18 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	percpu_counter_set(&sbi->s_dirtyclusters_counter, 0);
+ 
+ no_journal:
++	/*
++	 * Get the # of file system overhead blocks from the
++	 * superblock if present.
++	 */
++	if (es->s_overhead_clusters)
++		sbi->s_overhead = le32_to_cpu(es->s_overhead_clusters);
++	else {
++		ret = ext4_calculate_overhead(sb);
++		if (ret)
++			goto failed_mount_wq;
++	}
++
+ 	/*
+ 	 * The maximum number of concurrent works can be high and
+ 	 * concurrency isn't really necessary.  Limit it to 1.
+@@ -4600,67 +4720,21 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 	return err;
+ }
+ 
+-/*
+- * Note: calculating the overhead so we can be compatible with
+- * historical BSD practice is quite difficult in the face of
+- * clusters/bigalloc.  This is because multiple metadata blocks from
+- * different block group can end up in the same allocation cluster.
+- * Calculating the exact overhead in the face of clustered allocation
+- * requires either O(all block bitmaps) in memory or O(number of block
+- * groups**2) in time.  We will still calculate the superblock for
+- * older file systems --- and if we come across with a bigalloc file
+- * system with zero in s_overhead_clusters the estimate will be close to
+- * correct especially for very large cluster sizes --- but for newer
+- * file systems, it's better to calculate this figure once at mkfs
+- * time, and store it in the superblock.  If the superblock value is
+- * present (even for non-bigalloc file systems), we will use it.
+- */
+ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
+ {
+ 	struct super_block *sb = dentry->d_sb;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	struct ext4_super_block *es = sbi->s_es;
+-	struct ext4_group_desc *gdp;
++	ext4_fsblk_t overhead = 0;
+ 	u64 fsid;
+ 	s64 bfree;
+ 
+-	if (test_opt(sb, MINIX_DF)) {
+-		sbi->s_overhead_last = 0;
+-	} else if (es->s_overhead_clusters) {
+-		sbi->s_overhead_last = le32_to_cpu(es->s_overhead_clusters);
+-	} else if (sbi->s_blocks_last != ext4_blocks_count(es)) {
+-		ext4_group_t i, ngroups = ext4_get_groups_count(sb);
+-		ext4_fsblk_t overhead = 0;
+-
+-		/*
+-		 * Compute the overhead (FS structures).  This is constant
+-		 * for a given filesystem unless the number of block groups
+-		 * changes so we cache the previous value until it does.
+-		 */
+-
+-		/*
+-		 * All of the blocks before first_data_block are
+-		 * overhead
+-		 */
+-		overhead = EXT4_B2C(sbi, le32_to_cpu(es->s_first_data_block));
+-
+-		/*
+-		 * Add the overhead found in each block group
+-		 */
+-		for (i = 0; i < ngroups; i++) {
+-			gdp = ext4_get_group_desc(sb, i, NULL);
+-			overhead += ext4_num_overhead_clusters(sb, i, gdp);
+-			cond_resched();
+-		}
+-		sbi->s_overhead_last = overhead;
+-		smp_wmb();
+-		sbi->s_blocks_last = ext4_blocks_count(es);
+-	}
++	if (!test_opt(sb, MINIX_DF))
++		overhead = sbi->s_overhead;
+ 
+ 	buf->f_type = EXT4_SUPER_MAGIC;
+ 	buf->f_bsize = sb->s_blocksize;
+-	buf->f_blocks = (ext4_blocks_count(es) -
+-			 EXT4_C2B(sbi, sbi->s_overhead_last));
++	buf->f_blocks = ext4_blocks_count(es) - EXT4_C2B(sbi, sbi->s_overhead);
+ 	bfree = percpu_counter_sum_positive(&sbi->s_freeclusters_counter) -
+ 		percpu_counter_sum_positive(&sbi->s_dirtyclusters_counter);
+ 	/* prevent underflow in case that few free space is available */

commit 74feec5dd83d879368c1081aec5b6a1cb6dd7ce2
+Author: Theodore Ts'o 
+Date:   Fri Jul 6 14:03:18 2012 -0400
+
+    random: fix up sparse warnings
+    
+    Add extern and static declarations to suppress sparse warnings
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 4ec04a754733..cb541b9a5231 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -1279,6 +1279,7 @@ static int proc_do_uuid(ctl_table *table, int write,
+ }
+ 
+ static int sysctl_poolsize = INPUT_POOL_WORDS * 32;
++extern ctl_table random_table[];
+ ctl_table random_table[] = {
+ 	{
+ 		.procname	= "poolsize",
+@@ -1344,7 +1345,7 @@ late_initcall(random_int_secret_init);
+  * value is not cryptographically secure but for several uses the cost of
+  * depleting entropy is too high
+  */
+-DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash);
++static DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash);
+ unsigned int get_random_int(void)
+ {
+ 	__u32 *hash;

commit f6fb99cadcd44660c68e13f6eab28333653621e6
+Author: Theodore Ts'o 
+Date:   Sat Jun 30 19:14:57 2012 -0400
+
+    ext4: pass a char * to ext4_count_free() instead of a buffer_head ptr
+    
+    Make it possible for ext4_count_free to operate on buffers and not
+    just data in buffer_heads.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index cee7812cc3cf..d23b31ca9d7a 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -609,7 +609,8 @@ ext4_fsblk_t ext4_count_free_clusters(struct super_block *sb)
+ 		if (bitmap_bh == NULL)
+ 			continue;
+ 
+-		x = ext4_count_free(bitmap_bh, sb->s_blocksize);
++		x = ext4_count_free(bitmap_bh->b_data,
++				    EXT4_BLOCKS_PER_GROUP(sb) / 8);
+ 		printk(KERN_DEBUG "group %u: stored = %d, counted = %u\n",
+ 			i, ext4_free_group_clusters(sb, gdp), x);
+ 		bitmap_count += x;
+diff --git a/fs/ext4/bitmap.c b/fs/ext4/bitmap.c
+index b319721da26a..7e86a6d28c64 100644
+--- a/fs/ext4/bitmap.c
++++ b/fs/ext4/bitmap.c
+@@ -15,15 +15,13 @@
+ 
+ static const int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
+ 
+-unsigned int ext4_count_free(struct buffer_head *map, unsigned int numchars)
++unsigned int ext4_count_free(char *bitmap, unsigned int numchars)
+ {
+ 	unsigned int i, sum = 0;
+ 
+-	if (!map)
+-		return 0;
+ 	for (i = 0; i < numchars; i++)
+-		sum += nibblemap[map->b_data[i] & 0xf] +
+-			nibblemap[(map->b_data[i] >> 4) & 0xf];
++		sum += nibblemap[bitmap[i] & 0xf] +
++			nibblemap[(bitmap[i] >> 4) & 0xf];
+ 	return sum;
+ }
+ 
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index cfc4e01b3c83..293fa1ced21b 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1852,7 +1852,7 @@ struct mmpd_data {
+ # define NORET_AND	noreturn,
+ 
+ /* bitmap.c */
+-extern unsigned int ext4_count_free(struct buffer_head *, unsigned);
++extern unsigned int ext4_count_free(char *bitmap, unsigned numchars);
+ void ext4_inode_bitmap_csum_set(struct super_block *sb, ext4_group_t group,
+ 				struct ext4_group_desc *gdp,
+ 				struct buffer_head *bh, int sz);
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index d48e8b14928c..6866bc233e94 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -1054,7 +1054,8 @@ unsigned long ext4_count_free_inodes(struct super_block *sb)
+ 		if (!bitmap_bh)
+ 			continue;
+ 
+-		x = ext4_count_free(bitmap_bh, EXT4_INODES_PER_GROUP(sb) / 8);
++		x = ext4_count_free(bitmap_bh->b_data,
++				    EXT4_INODES_PER_GROUP(sb) / 8);
+ 		printk(KERN_DEBUG "group %lu: stored = %d, counted = %lu\n",
+ 			(unsigned long) i, ext4_free_inodes_count(sb, gdp), x);
+ 		bitmap_count += x;

commit b0dd6b70f0fda17ae9762fbb72d98e40a4f66556
+Author: Theodore Ts'o 
+Date:   Thu Jun 7 18:56:06 2012 -0400
+
+    ext4: fix the free blocks calculation for ext3 file systems w/ uninit_bg
+    
+    Ext3 filesystems that are converted to use as many ext4 file system
+    features as possible will enable uninit_bg to speed up e2fsck times.
+    These file systems will have a native ext3 layout of inode tables and
+    block allocation bitmaps (as opposed to ext4's flex_bg layout).
+    Unfortunately, in these cases, when first allocating a block in an
+    uninitialized block group, ext4 would incorrectly calculate the number
+    of free blocks in that block group, and then errorneously report that
+    the file system was corrupt:
+    
+    EXT4-fs error (device vdd): ext4_mb_generate_buddy:741: group 30, 32254 clusters in bitmap, 32258 in gd
+    
+    This problem can be reproduced via:
+    
+        mke2fs -q -t ext4 -O ^flex_bg /dev/vdd 5g
+        mount -t ext4 /dev/vdd /mnt
+        fallocate -l 4600m /mnt/test
+    
+    The problem was caused by a bone headed mistake in the check to see if a
+    particular metadata block was part of the block group.
+    
+    Many thanks to Kees Cook for finding and bisecting the buggy commit
+    which introduced this bug (commit fd034a84e1, present since v3.2).
+    
+    Reported-by: Sander Eikelenboom 
+    Reported-by: Kees Cook 
+    Signed-off-by: "Theodore Ts'o" 
+    Tested-by: Kees Cook 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 99b6324290db..cee7812cc3cf 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -90,8 +90,8 @@ unsigned ext4_num_overhead_clusters(struct super_block *sb,
+ 	 * unusual file system layouts.
+ 	 */
+ 	if (ext4_block_in_group(sb, ext4_block_bitmap(sb, gdp), block_group)) {
+-		block_cluster = EXT4_B2C(sbi, (start -
+-					       ext4_block_bitmap(sb, gdp)));
++		block_cluster = EXT4_B2C(sbi,
++					 ext4_block_bitmap(sb, gdp) - start);
+ 		if (block_cluster < num_clusters)
+ 			block_cluster = -1;
+ 		else if (block_cluster == num_clusters) {
+@@ -102,7 +102,7 @@ unsigned ext4_num_overhead_clusters(struct super_block *sb,
+ 
+ 	if (ext4_block_in_group(sb, ext4_inode_bitmap(sb, gdp), block_group)) {
+ 		inode_cluster = EXT4_B2C(sbi,
+-					 start - ext4_inode_bitmap(sb, gdp));
++					 ext4_inode_bitmap(sb, gdp) - start);
+ 		if (inode_cluster < num_clusters)
+ 			inode_cluster = -1;
+ 		else if (inode_cluster == num_clusters) {
+@@ -114,7 +114,7 @@ unsigned ext4_num_overhead_clusters(struct super_block *sb,
+ 	itbl_blk = ext4_inode_table(sb, gdp);
+ 	for (i = 0; i < sbi->s_itb_per_group; i++) {
+ 		if (ext4_block_in_group(sb, itbl_blk + i, block_group)) {
+-			c = EXT4_B2C(sbi, start - itbl_blk + i);
++			c = EXT4_B2C(sbi, itbl_blk + i - start);
+ 			if ((c < num_clusters) || (c == inode_cluster) ||
+ 			    (c == block_cluster) || (c == itbl_cluster))
+ 				continue;

commit 79906964a187c405db72a3abc60eb9b50d804fbc
+Author: Theodore Ts'o 
+Date:   Thu May 31 23:46:01 2012 -0400
+
+    ext4: don't trash state flags in EXT4_IOC_SETFLAGS
+    
+    In commit 353eb83c we removed i_state_flags with 64-bit longs, But
+    when handling the EXT4_IOC_SETFLAGS ioctl, we replace i_flags
+    directly, which trashes the state flags which are stored in the high
+    32-bits of i_flags on 64-bit platforms.  So use the the
+    ext4_{set,clear}_inode_flags() functions which use atomic bit
+    manipulation functions instead.
+    
+    Reported-by: Tao Ma 
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index feba55a225a6..8ad112ae0ade 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -38,7 +38,7 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 		handle_t *handle = NULL;
+ 		int err, migrate = 0;
+ 		struct ext4_iloc iloc;
+-		unsigned int oldflags;
++		unsigned int oldflags, mask, i;
+ 		unsigned int jflag;
+ 
+ 		if (!inode_owner_or_capable(inode))
+@@ -115,8 +115,14 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 		if (err)
+ 			goto flags_err;
+ 
+-		flags = flags & EXT4_FL_USER_MODIFIABLE;
+-		flags |= oldflags & ~EXT4_FL_USER_MODIFIABLE;
++		for (i = 0, mask = 1; i < 32; i++, mask <<= 1) {
++			if (!(mask & EXT4_FL_USER_MODIFIABLE))
++				continue;
++			if (mask & flags)
++				ext4_set_inode_flag(inode, i);
++			else
++				ext4_clear_inode_flag(inode, i);
++		}
+ 		ei->i_flags = flags;
+ 
+ 		ext4_set_inode_flags(inode);

commit f3fc0210c0fc91900766c995f089c39170e68305
+Author: Theodore Ts'o 
+Date:   Wed May 30 23:00:16 2012 -0400
+
+    ext4: add missing save_error_info() to ext4_error()
+    
+    The ext4_error() function is missing a call to save_error_info().
+    Since this is the function which marks the file system as containing
+    an error, this oversight (which was introduced in 2.6.36) is quite
+    significant, and should be backported to older stable kernels with
+    high urgency.
+    
+    Reported-by: Ken Sumrall 
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: ksumrall@google.com
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 9f1ae6b36502..b8d5fc10d8c0 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -539,6 +539,7 @@ void __ext4_error(struct super_block *sb, const char *function,
+ 	printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: comm %s: %pV\n",
+ 	       sb->s_id, function, line, current->comm, &vaf);
+ 	va_end(args);
++	save_error_info(sb, function, line);
+ 
+ 	ext4_handle_error(sb);
+ }

commit 2c0544b23568674efba22532e1f25fb62ce10163
+Author: Theodore Ts'o 
+Date:   Wed May 30 22:56:46 2012 -0400
+
+    ext4: add debugging trigger for ext4_error()
+    
+    Make it easy to test whether or not the error handling subsystem in
+    ext4 is working correctly.  This allows us to simulate an ext4_error()
+    by echoing a string to /sys/fs/ext4//trigger_fs_error.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: ksumrall@google.com
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 511011a1e85d..decc15d1b4b6 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1197,6 +1197,7 @@ struct ext4_sb_info {
+ 	struct proc_dir_entry *s_proc;
+ 	struct kobject s_kobj;
+ 	struct completion s_kobj_unregister;
++	struct super_block *s_sb;
+ 
+ 	/* Journaling */
+ 	struct journal_s *s_journal;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 628cfcdc0823..9f1ae6b36502 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2473,6 +2473,23 @@ static ssize_t sbi_ui_store(struct ext4_attr *a,
+ 	return count;
+ }
+ 
++static ssize_t trigger_test_error(struct ext4_attr *a,
++				  struct ext4_sb_info *sbi,
++				  const char *buf, size_t count)
++{
++	int len = count;
++
++	if (!capable(CAP_SYS_ADMIN))
++		return -EPERM;
++
++	if (len && buf[len-1] == '\n')
++		len--;
++
++	if (len)
++		ext4_error(sbi->s_sb, "%.*s", len, buf);
++	return count;
++}
++
+ #define EXT4_ATTR_OFFSET(_name,_mode,_show,_store,_elname) \
+ static struct ext4_attr ext4_attr_##_name = {			\
+ 	.attr = {.name = __stringify(_name), .mode = _mode },	\
+@@ -2503,6 +2520,7 @@ EXT4_RW_ATTR_SBI_UI(mb_order2_req, s_mb_order2_reqs);
+ EXT4_RW_ATTR_SBI_UI(mb_stream_req, s_mb_stream_request);
+ EXT4_RW_ATTR_SBI_UI(mb_group_prealloc, s_mb_group_prealloc);
+ EXT4_RW_ATTR_SBI_UI(max_writeback_mb_bump, s_max_writeback_mb_bump);
++EXT4_ATTR(trigger_fs_error, 0200, NULL, trigger_test_error);
+ 
+ static struct attribute *ext4_attrs[] = {
+ 	ATTR_LIST(delayed_allocation_blocks),
+@@ -2517,6 +2535,7 @@ static struct attribute *ext4_attrs[] = {
+ 	ATTR_LIST(mb_stream_req),
+ 	ATTR_LIST(mb_group_prealloc),
+ 	ATTR_LIST(max_writeback_mb_bump),
++	ATTR_LIST(trigger_fs_error),
+ 	NULL,
+ };
+ 
+@@ -3087,6 +3106,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		goto out_free_orig;
+ 	}
+ 	sb->s_fs_info = sbi;
++	sbi->s_sb = sb;
+ 	sbi->s_mount_opt = 0;
+ 	sbi->s_resuid = EXT4_DEF_RESUID;
+ 	sbi->s_resgid = EXT4_DEF_RESGID;

commit 2cde417de013b2e5ae3007374d937e8c4c426bd4
+Author: Theodore Ts'o 
+Date:   Mon May 28 17:49:54 2012 -0400
+
+    ext4: return ENOMEM when mounts fail due to lack of memory
+    
+    This is a port of the ext3 commit: 4569cd1b0d9
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 545932c0a290..628cfcdc0823 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3527,6 +3527,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 					  GFP_KERNEL);
+ 	if (sbi->s_group_desc == NULL) {
+ 		ext4_msg(sb, KERN_ERR, "not enough memory");
++		ret = -ENOMEM;
+ 		goto failed_mount;
+ 	}
+ 
+@@ -3584,6 +3585,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	}
+ 	if (err) {
+ 		ext4_msg(sb, KERN_ERR, "insufficient memory");
++		ret = err;
+ 		goto failed_mount3;
+ 	}
+ 

commit 2716b80284c5ca415b8ce93ca178b0ca28482568
+Author: Theodore Ts'o 
+Date:   Mon May 28 17:47:52 2012 -0400
+
+    ext4: remove redundundant "(char *) bh->b_data" casts
+    
+    The b_data field of the buffer_head is already a char *, so there's no
+    point casting it to a char *.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 05c7979226e5..7ea6cbb44121 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -1145,7 +1145,7 @@ static int ext4_setup_new_descs(handle_t *handle, struct super_block *sb,
+ 		 */
+ 		gdb_bh = sbi->s_group_desc[gdb_num];
+ 		/* Update group descriptor block for new group */
+-		gdp = (struct ext4_group_desc *)((char *)gdb_bh->b_data +
++		gdp = (struct ext4_group_desc *)(gdb_bh->b_data +
+ 						 gdb_off * EXT4_DESC_SIZE(sb));
+ 
+ 		memset(gdp, 0, EXT4_DESC_SIZE(sb));
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index dbc9544c7087..545932c0a290 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3126,7 +3126,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	 * Note: s_es must be initialized as soon as possible because
+ 	 *       some ext4 macro-instructions depend on its value
+ 	 */
+-	es = (struct ext4_super_block *) (((char *)bh->b_data) + offset);
++	es = (struct ext4_super_block *) (bh->b_data + offset);
+ 	sbi->s_es = es;
+ 	sb->s_magic = le16_to_cpu(es->s_magic);
+ 	if (sb->s_magic != EXT4_SUPER_MAGIC)
+@@ -3335,7 +3335,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 			       "Can't read superblock on 2nd try");
+ 			goto failed_mount;
+ 		}
+-		es = (struct ext4_super_block *)(((char *)bh->b_data) + offset);
++		es = (struct ext4_super_block *)(bh->b_data + offset);
+ 		sbi->s_es = es;
+ 		if (es->s_magic != cpu_to_le16(EXT4_SUPER_MAGIC)) {
+ 			ext4_msg(sb, KERN_ERR,
+@@ -3976,7 +3976,7 @@ static journal_t *ext4_get_dev_journal(struct super_block *sb,
+ 		goto out_bdev;
+ 	}
+ 
+-	es = (struct ext4_super_block *) (((char *)bh->b_data) + offset);
++	es = (struct ext4_super_block *) (bh->b_data + offset);
+ 	if ((le16_to_cpu(es->s_magic) != EXT4_SUPER_MAGIC) ||
+ 	    !(le32_to_cpu(es->s_feature_incompat) &
+ 	      EXT4_FEATURE_INCOMPAT_JOURNAL_DEV)) {

commit f32aaf2d2b996b14e993da1c23f7ee22ea7333a3
+Author: Theodore Ts'o 
+Date:   Mon May 21 11:42:02 2012 -0400
+
+    ext4: enable the 64-bit jbd2 feature based on the 64-bit ext4 feature
+    
+    Previously we were only enabling the 64-bit jbd2 feature if the number
+    of blocks in the file system was greater 2**32-1.  The problem with
+    this is that it makes it harder to test the 64-bit journal code paths
+    with small file systems, since a small test file system would with the
+    64-bit ext4 feature enable would use a 64-bit file system on-disk data
+    structures, but use a 32-bit journal.
+    
+    This would also cause problems when trying to do an online resize to
+    grow the filesystem above the 2**32-1 boundary.  Fortunately the patch
+    to support online resize for 64-bit file systems hasn't been merged
+    yet, so this problem hasn't arisen in practice.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index c18c5968cd96..88c2054fb938 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3603,7 +3603,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		goto no_journal;
+ 	}
+ 
+-	if (ext4_blocks_count(es) > 0xffffffffULL &&
++	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_64BIT) &&
+ 	    !jbd2_journal_set_features(EXT4_SB(sb)->s_journal, 0, 0,
+ 				       JBD2_FEATURE_INCOMPAT_64BIT)) {
+ 		ext4_msg(sb, KERN_ERR, "Failed to set 64-bit journal feature");

commit b09de7fa5217bbcb4caf3d19bd5e94816947ff7a
+Author: Theodore Ts'o 
+Date:   Mon Apr 30 07:40:00 2012 -0400
+
+    ext4: remove unnecessary check in add_dirent_to_buf()
+    
+    None of this function callers ever pass in a NULL inode pointer, so
+    this check is unnecessary, and the else clause is dead code.  (This
+    change should make the code coverage people a little happier.  :-)
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 5861d64929f6..a9fd5f48f3bf 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1612,11 +1612,8 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
+ 		de = de1;
+ 	}
+ 	de->file_type = EXT4_FT_UNKNOWN;
+-	if (inode) {
+-		de->inode = cpu_to_le32(inode->i_ino);
+-		ext4_set_de_type(dir->i_sb, de, inode->i_mode);
+-	} else
+-		de->inode = 0;
++	de->inode = cpu_to_le32(inode->i_ino);
++	ext4_set_de_type(dir->i_sb, de, inode->i_mode);
+ 	de->name_len = namelen;
+ 	memcpy(de->name, name, namelen);
+ 	/*

commit 57f73c2c89a5d3b2ed87201c8100d1fa989a1a65
+Author: Theodore Ts'o 
+Date:   Mon Apr 16 18:55:26 2012 -0400
+
+    ext4: fix handling of journalled quota options
+    
+    Commit 26092bf5 broke handling of journalled quota mount options by
+    trying to parse argument of every mount option as a number.  Fix this
+    by dealing with the quota options before we call match_int().
+    
+    Thanks to Jan Kara for discovering this regression.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Jan Kara 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index ef7db5044262..6da193564e43 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1305,20 +1305,20 @@ static int set_qf_name(struct super_block *sb, int qtype, substring_t *args)
+ 		ext4_msg(sb, KERN_ERR,
+ 			"Cannot change journaled "
+ 			"quota options when quota turned on");
+-		return 0;
++		return -1;
+ 	}
+ 	qname = match_strdup(args);
+ 	if (!qname) {
+ 		ext4_msg(sb, KERN_ERR,
+ 			"Not enough memory for storing quotafile name");
+-		return 0;
++		return -1;
+ 	}
+ 	if (sbi->s_qf_names[qtype] &&
+ 		strcmp(sbi->s_qf_names[qtype], qname)) {
+ 		ext4_msg(sb, KERN_ERR,
+ 			"%s quota file already specified", QTYPE2NAME(qtype));
+ 		kfree(qname);
+-		return 0;
++		return -1;
+ 	}
+ 	sbi->s_qf_names[qtype] = qname;
+ 	if (strchr(sbi->s_qf_names[qtype], '/')) {
+@@ -1326,7 +1326,7 @@ static int set_qf_name(struct super_block *sb, int qtype, substring_t *args)
+ 			"quotafile must be on filesystem root");
+ 		kfree(sbi->s_qf_names[qtype]);
+ 		sbi->s_qf_names[qtype] = NULL;
+-		return 0;
++		return -1;
+ 	}
+ 	set_opt(sb, QUOTA);
+ 	return 1;
+@@ -1341,7 +1341,7 @@ static int clear_qf_name(struct super_block *sb, int qtype)
+ 		sbi->s_qf_names[qtype]) {
+ 		ext4_msg(sb, KERN_ERR, "Cannot change journaled quota options"
+ 			" when quota turned on");
+-		return 0;
++		return -1;
+ 	}
+ 	/*
+ 	 * The space will be released later when all options are confirmed
+@@ -1450,6 +1450,16 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
+ 	const struct mount_opts *m;
+ 	int arg = 0;
+ 
++#ifdef CONFIG_QUOTA
++	if (token == Opt_usrjquota)
++		return set_qf_name(sb, USRQUOTA, &args[0]);
++	else if (token == Opt_grpjquota)
++		return set_qf_name(sb, GRPQUOTA, &args[0]);
++	else if (token == Opt_offusrjquota)
++		return clear_qf_name(sb, USRQUOTA);
++	else if (token == Opt_offgrpjquota)
++		return clear_qf_name(sb, GRPQUOTA);
++#endif
+ 	if (args->from && match_int(args, &arg))
+ 		return -1;
+ 	switch (token) {
+@@ -1549,18 +1559,6 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
+ 				sbi->s_mount_opt |= m->mount_opt;
+ 			}
+ #ifdef CONFIG_QUOTA
+-		} else if (token == Opt_usrjquota) {
+-			if (!set_qf_name(sb, USRQUOTA, &args[0]))
+-				return -1;
+-		} else if (token == Opt_grpjquota) {
+-			if (!set_qf_name(sb, GRPQUOTA, &args[0]))
+-				return -1;
+-		} else if (token == Opt_offusrjquota) {
+-			if (!clear_qf_name(sb, USRQUOTA))
+-				return -1;
+-		} else if (token == Opt_offgrpjquota) {
+-			if (!clear_qf_name(sb, GRPQUOTA))
+-				return -1;
+ 		} else if (m->flags & MOPT_QFMT) {
+ 			if (sb_any_quota_loaded(sb) &&
+ 			    sbi->s_jquota_fmt != m->mount_opt) {

commit 9cd70b347e9761ea2d2ac3d758c529a48a8193e6
+Author: Theodore Ts'o 
+Date:   Mon Apr 16 12:16:20 2012 -0400
+
+    ext4: address scalability issue by removing extent cache statistics
+    
+    Andi Kleen and Tim Chen have reported that under certain circumstances
+    the extent cache statistics are causing scalability problems due to
+    cache line bounces.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@vger.kernel.org
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index ab2594a30f86..0e01e90add8b 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1203,9 +1203,6 @@ struct ext4_sb_info {
+ 	unsigned long s_ext_blocks;
+ 	unsigned long s_ext_extents;
+ #endif
+-	/* ext4 extent cache stats */
+-	unsigned long extent_cache_hits;
+-	unsigned long extent_cache_misses;
+ 
+ 	/* for buddy allocator */
+ 	struct ext4_group_info ***s_group_info;
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 1421938e6792..8a12cd207679 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -2066,10 +2066,6 @@ static int ext4_ext_check_cache(struct inode *inode, ext4_lblk_t block,
+ 		ret = 1;
+ 	}
+ errout:
+-	if (!ret)
+-		sbi->extent_cache_misses++;
+-	else
+-		sbi->extent_cache_hits++;
+ 	trace_ext4_ext_in_cache(inode, block, ret);
+ 	spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+ 	return ret;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index ceebaf853beb..ef7db5044262 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2366,18 +2366,6 @@ static ssize_t lifetime_write_kbytes_show(struct ext4_attr *a,
+ 			  EXT4_SB(sb)->s_sectors_written_start) >> 1)));
+ }
+ 
+-static ssize_t extent_cache_hits_show(struct ext4_attr *a,
+-				      struct ext4_sb_info *sbi, char *buf)
+-{
+-	return snprintf(buf, PAGE_SIZE, "%lu\n", sbi->extent_cache_hits);
+-}
+-
+-static ssize_t extent_cache_misses_show(struct ext4_attr *a,
+-					struct ext4_sb_info *sbi, char *buf)
+-{
+-	return snprintf(buf, PAGE_SIZE, "%lu\n", sbi->extent_cache_misses);
+-}
+-
+ static ssize_t inode_readahead_blks_store(struct ext4_attr *a,
+ 					  struct ext4_sb_info *sbi,
+ 					  const char *buf, size_t count)
+@@ -2435,8 +2423,6 @@ static struct ext4_attr ext4_attr_##name = __ATTR(name, mode, show, store)
+ EXT4_RO_ATTR(delayed_allocation_blocks);
+ EXT4_RO_ATTR(session_write_kbytes);
+ EXT4_RO_ATTR(lifetime_write_kbytes);
+-EXT4_RO_ATTR(extent_cache_hits);
+-EXT4_RO_ATTR(extent_cache_misses);
+ EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show,
+ 		 inode_readahead_blks_store, s_inode_readahead_blks);
+ EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal);
+@@ -2452,8 +2438,6 @@ static struct attribute *ext4_attrs[] = {
+ 	ATTR_LIST(delayed_allocation_blocks),
+ 	ATTR_LIST(session_write_kbytes),
+ 	ATTR_LIST(lifetime_write_kbytes),
+-	ATTR_LIST(extent_cache_hits),
+-	ATTR_LIST(extent_cache_misses),
+ 	ATTR_LIST(inode_readahead_blks),
+ 	ATTR_LIST(inode_goal),
+ 	ATTR_LIST(mb_stats),

commit 5f293474c4c6c4dc2baaf2dfd486748b5986de76
+Author: Andy Lutomirski 
+Date:   Thu Mar 22 21:15:52 2012 -0700
+
+    x86-64: Inline vdso clock_gettime helpers
+    
+    This is about a 3% speedup on Sandy Bridge.
+    
+    Signed-off-by: Andy Lutomirski 
+    Signed-off-by: John Stultz 
+
+diff --git a/arch/x86/vdso/vclock_gettime.c b/arch/x86/vdso/vclock_gettime.c
+index 6eea70b8f384..885eff49d6ab 100644
+--- a/arch/x86/vdso/vclock_gettime.c
++++ b/arch/x86/vdso/vclock_gettime.c
+@@ -94,7 +94,8 @@ notrace static inline long vgetns(void)
+ 	return (v * gtod->clock.mult) >> gtod->clock.shift;
+ }
+ 
+-notrace static noinline int do_realtime(struct timespec *ts)
++/* Code size doesn't matter (vdso is 4k anyway) and this is faster. */
++notrace static int __always_inline do_realtime(struct timespec *ts)
+ {
+ 	unsigned long seq, ns;
+ 	int mode;
+@@ -111,7 +112,7 @@ notrace static noinline int do_realtime(struct timespec *ts)
+ 	return mode;
+ }
+ 
+-notrace static noinline int do_monotonic(struct timespec *ts)
++notrace static int do_monotonic(struct timespec *ts)
+ {
+ 	unsigned long seq, ns;
+ 	int mode;
+@@ -128,7 +129,7 @@ notrace static noinline int do_monotonic(struct timespec *ts)
+ 	return mode;
+ }
+ 
+-notrace static noinline int do_realtime_coarse(struct timespec *ts)
++notrace static int do_realtime_coarse(struct timespec *ts)
+ {
+ 	unsigned long seq;
+ 	do {
+@@ -139,7 +140,7 @@ notrace static noinline int do_realtime_coarse(struct timespec *ts)
+ 	return 0;
+ }
+ 
+-notrace static noinline int do_monotonic_coarse(struct timespec *ts)
++notrace static int do_monotonic_coarse(struct timespec *ts)
+ {
+ 	unsigned long seq;
+ 	do {

commit 91ec87d57fc38c529034e853687dfb7756de5406
+Author: Andy Lutomirski 
+Date:   Thu Mar 22 21:15:51 2012 -0700
+
+    x86-64: Simplify and optimize vdso clock_gettime monotonic variants
+    
+    We used to store the wall-to-monotonic offset and the realtime base.
+    It's faster to precompute the monotonic base.
+    
+    This is about a 3% speedup on Sandy Bridge for CLOCK_MONOTONIC.
+    It's much more impressive for CLOCK_MONOTONIC_COARSE.
+    
+    Signed-off-by: Andy Lutomirski 
+    Signed-off-by: John Stultz 
+
+diff --git a/arch/x86/include/asm/vgtod.h b/arch/x86/include/asm/vgtod.h
+index 1f007178c813..8b38be2de9e1 100644
+--- a/arch/x86/include/asm/vgtod.h
++++ b/arch/x86/include/asm/vgtod.h
+@@ -7,11 +7,6 @@
+ struct vsyscall_gtod_data {
+ 	seqcount_t	seq;
+ 
+-	/* open coded 'struct timespec' */
+-	time_t		wall_time_sec;
+-	u32		wall_time_nsec;
+-
+-	struct timezone sys_tz;
+ 	struct { /* extract of a clocksource struct */
+ 		int vclock_mode;
+ 		cycle_t	cycle_last;
+@@ -19,8 +14,16 @@ struct vsyscall_gtod_data {
+ 		u32	mult;
+ 		u32	shift;
+ 	} clock;
+-	struct timespec wall_to_monotonic;
++
++	/* open coded 'struct timespec' */
++	time_t		wall_time_sec;
++	u32		wall_time_nsec;
++	u32		monotonic_time_nsec;
++	time_t		monotonic_time_sec;
++
++	struct timezone sys_tz;
+ 	struct timespec wall_time_coarse;
++	struct timespec monotonic_time_coarse;
+ };
+ extern struct vsyscall_gtod_data vsyscall_gtod_data;
+ 
+diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
+index cdc95a707cd1..4285f1f404c2 100644
+--- a/arch/x86/kernel/vsyscall_64.c
++++ b/arch/x86/kernel/vsyscall_64.c
+@@ -84,6 +84,7 @@ void update_vsyscall(struct timespec *wall_time, struct timespec *wtm,
+ 			struct clocksource *clock, u32 mult)
+ {
+ 	write_seqcount_begin(&vsyscall_gtod_data.seq);
++	struct timespec monotonic;
+ 
+ 	/* copy vsyscall data */
+ 	vsyscall_gtod_data.clock.vclock_mode	= clock->archdata.vclock_mode;
+@@ -91,10 +92,17 @@ void update_vsyscall(struct timespec *wall_time, struct timespec *wtm,
+ 	vsyscall_gtod_data.clock.mask		= clock->mask;
+ 	vsyscall_gtod_data.clock.mult		= mult;
+ 	vsyscall_gtod_data.clock.shift		= clock->shift;
++
+ 	vsyscall_gtod_data.wall_time_sec	= wall_time->tv_sec;
+ 	vsyscall_gtod_data.wall_time_nsec	= wall_time->tv_nsec;
+-	vsyscall_gtod_data.wall_to_monotonic	= *wtm;
++
++	monotonic = timespec_add(*wall_time, *wtm);
++	vsyscall_gtod_data.monotonic_time_sec	= monotonic.tv_sec;
++	vsyscall_gtod_data.monotonic_time_nsec	= monotonic.tv_nsec;
++
+ 	vsyscall_gtod_data.wall_time_coarse	= __current_kernel_time();
++	vsyscall_gtod_data.monotonic_time_coarse =
++		timespec_add(vsyscall_gtod_data.wall_time_coarse, *wtm);
+ 
+ 	write_seqcount_end(&vsyscall_gtod_data.seq);
+ }
+diff --git a/arch/x86/vdso/vclock_gettime.c b/arch/x86/vdso/vclock_gettime.c
+index 944c5e5d6b6a..6eea70b8f384 100644
+--- a/arch/x86/vdso/vclock_gettime.c
++++ b/arch/x86/vdso/vclock_gettime.c
+@@ -113,27 +113,17 @@ notrace static noinline int do_realtime(struct timespec *ts)
+ 
+ notrace static noinline int do_monotonic(struct timespec *ts)
+ {
+-	unsigned long seq, ns, secs;
++	unsigned long seq, ns;
+ 	int mode;
+ 
+ 	do {
+ 		seq = read_seqcount_begin(>od->seq);
+ 		mode = gtod->clock.vclock_mode;
+-		secs = gtod->wall_time_sec;
+-		ns = gtod->wall_time_nsec + vgetns();
+-		secs += gtod->wall_to_monotonic.tv_sec;
+-		ns += gtod->wall_to_monotonic.tv_nsec;
++		ts->tv_sec = gtod->monotonic_time_sec;
++		ts->tv_nsec = gtod->monotonic_time_nsec;
++		ns = vgetns();
+ 	} while (unlikely(read_seqcount_retry(>od->seq, seq)));
+-
+-	/* wall_time_nsec, vgetns(), and wall_to_monotonic.tv_nsec
+-	 * are all guaranteed to be nonnegative.
+-	 */
+-	while (ns >= NSEC_PER_SEC) {
+-		ns -= NSEC_PER_SEC;
+-		++secs;
+-	}
+-	ts->tv_sec = secs;
+-	ts->tv_nsec = ns;
++	timespec_add_ns(ts, ns);
+ 
+ 	return mode;
+ }
+@@ -151,25 +141,13 @@ notrace static noinline int do_realtime_coarse(struct timespec *ts)
+ 
+ notrace static noinline int do_monotonic_coarse(struct timespec *ts)
+ {
+-	unsigned long seq, ns, secs;
++	unsigned long seq;
+ 	do {
+ 		seq = read_seqcount_begin(>od->seq);
+-		secs = gtod->wall_time_coarse.tv_sec;
+-		ns = gtod->wall_time_coarse.tv_nsec;
+-		secs += gtod->wall_to_monotonic.tv_sec;
+-		ns += gtod->wall_to_monotonic.tv_nsec;
++		ts->tv_sec = gtod->monotonic_time_coarse.tv_sec;
++		ts->tv_nsec = gtod->monotonic_time_coarse.tv_nsec;
+ 	} while (unlikely(read_seqcount_retry(>od->seq, seq)));
+ 
+-	/* wall_time_nsec and wall_to_monotonic.tv_nsec are
+-	 * guaranteed to be between 0 and NSEC_PER_SEC.
+-	 */
+-	if (ns >= NSEC_PER_SEC) {
+-		ns -= NSEC_PER_SEC;
+-		++secs;
+-	}
+-	ts->tv_sec = secs;
+-	ts->tv_nsec = ns;
+-
+ 	return 0;
+ }
+ 

commit 92b9781658dba287a1354ad74ed351f68c3ee740
+Author: Theodore Ts'o 
+Date:   Mon Mar 19 23:41:49 2012 -0400
+
+    ext4: change some printk() calls to use ext4_msg() instead
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index a4a0234cb5cb..ad56866d729a 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -425,8 +425,9 @@ static int call_filldir(struct file *filp, void *dirent,
+ 	sb = inode->i_sb;
+ 
+ 	if (!fname) {
+-		printk(KERN_ERR "EXT4-fs: call_filldir: called with "
+-		       "null fname?!?\n");
++		ext4_msg(sb, KERN_ERR, "%s:%d: inode #%lu: comm %s: "
++			 "called with null fname?!?", __func__, __LINE__,
++			 inode->i_ino, current->comm);
+ 		return 0;
+ 	}
+ 	curr_pos = hash2pos(fname->hash, fname->minor_hash);
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 5c9c067abca0..d075f34f9bae 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -2728,17 +2728,17 @@ void ext4_ext_init(struct super_block *sb)
+ 
+ 	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
+ #if defined(AGGRESSIVE_TEST) || defined(CHECK_BINSEARCH) || defined(EXTENTS_STATS)
+-		printk(KERN_INFO "EXT4-fs: file extents enabled");
++		printk(KERN_INFO "EXT4-fs: file extents enabled"
+ #ifdef AGGRESSIVE_TEST
+-		printk(", aggressive tests");
++		       ", aggressive tests"
+ #endif
+ #ifdef CHECK_BINSEARCH
+-		printk(", check binsearch");
++		       ", check binsearch"
+ #endif
+ #ifdef EXTENTS_STATS
+-		printk(", stats");
++		       ", stats"
+ #endif
+-		printk("\n");
++		       "\n");
+ #endif
+ #ifdef EXTENTS_STATS
+ 		spin_lock_init(&EXT4_SB(sb)->s_ext_stats_lock);
+@@ -4412,10 +4412,11 @@ int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset,
+ 				      EXT4_GET_BLOCKS_IO_CONVERT_EXT);
+ 		if (ret <= 0) {
+ 			WARN_ON(ret <= 0);
+-			printk(KERN_ERR "%s: ext4_ext_map_blocks "
+-				    "returned error inode#%lu, block=%u, "
+-				    "max_blocks=%u", __func__,
+-				    inode->i_ino, map.m_lblk, map.m_len);
++			ext4_msg(inode->i_sb, KERN_ERR,
++				 "%s:%d: inode #%lu: block %u: len %u: "
++				 "ext4_ext_map_blocks returned %d",
++				 __func__, __LINE__, inode->i_ino, map.m_lblk,
++				 map.m_len, ret);
+ 		}
+ 		ext4_mark_inode_dirty(handle, inode);
+ 		ret2 = ext4_journal_stop(handle);
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 75e2eae74cd1..409c2ee7750a 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -204,19 +204,20 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
+ 	struct ext4_sb_info *sbi;
+ 	int fatal = 0, err, count, cleared;
+ 
+-	if (atomic_read(&inode->i_count) > 1) {
+-		printk(KERN_ERR "ext4_free_inode: inode has count=%d\n",
+-		       atomic_read(&inode->i_count));
++	if (!sb) {
++		printk(KERN_ERR "EXT4-fs: %s:%d: inode on "
++		       "nonexistent device\n", __func__, __LINE__);
+ 		return;
+ 	}
+-	if (inode->i_nlink) {
+-		printk(KERN_ERR "ext4_free_inode: inode has nlink=%d\n",
+-		       inode->i_nlink);
++	if (atomic_read(&inode->i_count) > 1) {
++		ext4_msg(sb, KERN_ERR, "%s:%d: inode #%lu: count=%d",
++			 __func__, __LINE__, inode->i_ino,
++			 atomic_read(&inode->i_count));
+ 		return;
+ 	}
+-	if (!sb) {
+-		printk(KERN_ERR "ext4_free_inode: inode on "
+-		       "nonexistent device\n");
++	if (inode->i_nlink) {
++		ext4_msg(sb, KERN_ERR, "%s:%d: inode #%lu: nlink=%d\n",
++			 __func__, __LINE__, inode->i_ino, inode->i_nlink);
+ 		return;
+ 	}
+ 	sbi = EXT4_SB(sb);
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index a11264ebd1f3..83a2daeb813c 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1428,20 +1428,22 @@ static void ext4_da_block_invalidatepages(struct mpage_da_data *mpd)
+ static void ext4_print_free_blocks(struct inode *inode)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+-	printk(KERN_CRIT "Total free blocks count %lld\n",
++	struct super_block *sb = inode->i_sb;
++
++	ext4_msg(sb, KERN_CRIT, "Total free blocks count %lld",
+ 	       EXT4_C2B(EXT4_SB(inode->i_sb),
+ 			ext4_count_free_clusters(inode->i_sb)));
+-	printk(KERN_CRIT "Free/Dirty block details\n");
+-	printk(KERN_CRIT "free_blocks=%lld\n",
++	ext4_msg(sb, KERN_CRIT, "Free/Dirty block details");
++	ext4_msg(sb, KERN_CRIT, "free_blocks=%lld",
+ 	       (long long) EXT4_C2B(EXT4_SB(inode->i_sb),
+ 		percpu_counter_sum(&sbi->s_freeclusters_counter)));
+-	printk(KERN_CRIT "dirty_blocks=%lld\n",
++	ext4_msg(sb, KERN_CRIT, "dirty_blocks=%lld",
+ 	       (long long) EXT4_C2B(EXT4_SB(inode->i_sb),
+ 		percpu_counter_sum(&sbi->s_dirtyclusters_counter)));
+-	printk(KERN_CRIT "Block reservation details\n");
+-	printk(KERN_CRIT "i_reserved_data_blocks=%u\n",
+-	       EXT4_I(inode)->i_reserved_data_blocks);
+-	printk(KERN_CRIT "i_reserved_meta_blocks=%u\n",
++	ext4_msg(sb, KERN_CRIT, "Block reservation details");
++	ext4_msg(sb, KERN_CRIT, "i_reserved_data_blocks=%u",
++		 EXT4_I(inode)->i_reserved_data_blocks);
++	ext4_msg(sb, KERN_CRIT, "i_reserved_meta_blocks=%u",
+ 	       EXT4_I(inode)->i_reserved_meta_blocks);
+ 	return;
+ }
+@@ -2809,8 +2811,9 @@ static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate)
+ 		goto out;
+ 
+ 	if (!(io_end->inode->i_sb->s_flags & MS_ACTIVE)) {
+-		printk("sb umounted, discard end_io request for inode %lu\n",
+-			io_end->inode->i_ino);
++		ext4_msg(io_end->inode->i_sb, KERN_INFO,
++			 "sb umounted, discard end_io request for inode %lu",
++			 io_end->inode->i_ino);
+ 		ext4_free_io_end(io_end);
+ 		goto out;
+ 	}
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 3fed79da0d2c..b6ad461930ca 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -1512,16 +1512,17 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
+ 	o_blocks_count = ext4_blocks_count(es);
+ 
+ 	if (test_opt(sb, DEBUG))
+-		printk(KERN_DEBUG "EXT4-fs: extending last group from %llu to %llu blocks\n",
+-		       o_blocks_count, n_blocks_count);
++		ext4_msg(sb, KERN_DEBUG,
++			 "extending last group from %llu to %llu blocks",
++			 o_blocks_count, n_blocks_count);
+ 
+ 	if (n_blocks_count == 0 || n_blocks_count == o_blocks_count)
+ 		return 0;
+ 
+ 	if (n_blocks_count > (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
+-		printk(KERN_ERR "EXT4-fs: filesystem on %s:"
+-			" too large to resize to %llu blocks safely\n",
+-			sb->s_id, n_blocks_count);
++		ext4_msg(sb, KERN_ERR,
++			 "filesystem too large to resize to %llu blocks safely",
++			 n_blocks_count);
+ 		if (sizeof(sector_t) < 8)
+ 			ext4_warning(sb, "CONFIG_LBDAF not enabled");
+ 		return -EINVAL;
+@@ -1591,8 +1592,8 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
+ 	o_blocks_count = ext4_blocks_count(es);
+ 
+ 	if (test_opt(sb, DEBUG))
+-		printk(KERN_DEBUG "EXT4-fs: resizing filesystem from %llu "
+-		       "upto %llu blocks\n", o_blocks_count, n_blocks_count);
++		ext4_msg(sb, KERN_DEBUG, "resizing filesystem from %llu "
++		       "to %llu blocks", o_blocks_count, n_blocks_count);
+ 
+ 	if (n_blocks_count < o_blocks_count) {
+ 		/* On-line shrinking not supported */
+@@ -1676,7 +1677,7 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
+ 
+ 	iput(resize_inode);
+ 	if (test_opt(sb, DEBUG))
+-		printk(KERN_DEBUG "EXT4-fs: resized filesystem from %llu "
+-		       "upto %llu blocks\n", o_blocks_count, n_blocks_count);
++		ext4_msg(sb, KERN_DEBUG, "resized filesystem from %llu "
++		       "upto %llu blocks", o_blocks_count, n_blocks_count);
+ 	return err;
+ }
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 11dfaad232cf..1e26f4a0b555 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -376,7 +376,7 @@ void ext4_journal_abort_handle(const char *caller, unsigned int line,
+ 	if (is_handle_aborted(handle))
+ 		return;
+ 
+-	printk(KERN_ERR "%s:%d: aborting transaction: %s in %s\n",
++	printk(KERN_ERR "EXT4-fs: %s:%d: aborting transaction: %s in %s\n",
+ 	       caller, line, errstr, err_fn);
+ 
+ 	jbd2_journal_abort_handle(handle);
+@@ -2809,7 +2809,7 @@ static int ext4_run_lazyinit_thread(void)
+ 		ext4_clear_request_list();
+ 		kfree(ext4_li_info);
+ 		ext4_li_info = NULL;
+-		printk(KERN_CRIT "EXT4: error %d creating inode table "
++		printk(KERN_CRIT "EXT4-fs: error %d creating inode table "
+ 				 "initialization thread\n",
+ 				 err);
+ 		return err;

commit 1084f252e3490392575b80cbdfa1baf0842173d8
+Author: Theodore Ts'o 
+Date:   Mon Mar 19 23:13:43 2012 -0400
+
+    ext4: remove trailing newlines from ext4_msg() and ext4_error() messages
+    
+    The functions ext4_msg() and ext4_error() already tack on a trailing
+    newline, so remove the unnecessary extra newline.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index b2685992fb2d..75e2eae74cd1 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -1102,9 +1102,9 @@ int ext4_init_inode_table(struct super_block *sb, ext4_group_t group,
+ 			    sbi->s_inodes_per_block);
+ 
+ 	if ((used_blks < 0) || (used_blks > sbi->s_itb_per_group)) {
+-		ext4_error(sb, "Something is wrong with group %u\n"
+-			   "Used itable blocks: %d"
+-			   "itable unused count: %u\n",
++		ext4_error(sb, "Something is wrong with group %u: "
++			   "used itable blocks: %d; "
++			   "itable unused count: %u",
+ 			   group, used_blks,
+ 			   ext4_itable_unused_count(sb, gdp));
+ 		ret = 1;
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 028140213aee..a11264ebd1f3 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -272,7 +272,7 @@ void ext4_da_update_reserve_space(struct inode *inode,
+ 	trace_ext4_da_update_reserve_space(inode, used, quota_claim);
+ 	if (unlikely(used > ei->i_reserved_data_blocks)) {
+ 		ext4_msg(inode->i_sb, KERN_NOTICE, "%s: ino %lu, used %d "
+-			 "with only %d reserved data blocks\n",
++			 "with only %d reserved data blocks",
+ 			 __func__, inode->i_ino, used,
+ 			 ei->i_reserved_data_blocks);
+ 		WARN_ON(1);
+@@ -1165,7 +1165,7 @@ static void ext4_da_release_space(struct inode *inode, int to_free)
+ 		 */
+ 		ext4_msg(inode->i_sb, KERN_NOTICE, "ext4_da_release_space: "
+ 			 "ino %lu, to_free %d with only %d reserved "
+-			 "data blocks\n", inode->i_ino, to_free,
++			 "data blocks", inode->i_ino, to_free,
+ 			 ei->i_reserved_data_blocks);
+ 		WARN_ON(1);
+ 		to_free = ei->i_reserved_data_blocks;
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 8631e73f8f77..23ec6a879b35 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2762,7 +2762,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
+ 	len = EXT4_C2B(sbi, ac->ac_b_ex.fe_len);
+ 	if (!ext4_data_block_valid(sbi, block, len)) {
+ 		ext4_error(sb, "Allocating blocks %llu-%llu which overlap "
+-			   "fs metadata\n", block, block+len);
++			   "fs metadata", block, block+len);
+ 		/* File system mounted not to panic on error
+ 		 * Fix the bitmap and repeat the block allocation
+ 		 * We leak some of the blocks here.

commit 31d4f3a2f3c73f279ff96a7135d7202ef6833f12
+Author: Theodore Ts'o 
+Date:   Sun Mar 11 23:30:16 2012 -0400
+
+    ext4: check for zero length extent
+    
+    Explicitly test for an extent whose length is zero, and flag that as a
+    corrupted extent.
+    
+    This avoids a kernel BUG_ON assertion failure.
+    
+    Tested: Without this patch, the file system image found in
+    tests/f_ext_zero_len/image.gz in the latest e2fsprogs sources causes a
+    kernel panic.  With this patch, an ext4 file system error is noted
+    instead, and the file system is marked as being corrupted.
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=42859
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 74f23c292e1b..4394a757aa4c 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -300,6 +300,8 @@ static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext)
+ 	ext4_fsblk_t block = ext4_ext_pblock(ext);
+ 	int len = ext4_ext_get_actual_len(ext);
+ 
++	if (len == 0)
++		return 0;
+ 	return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, len);
+ }
+ 

commit f70486055ee351158bd6999f3965ad378b52c694
+Author: Theodore Ts'o 
+Date:   Sun Mar 4 22:06:20 2012 -0500
+
+    ext4: try to deprecate noacl and noxattr_user mount options
+    
+    No other file system allows ACL's and extended attributes to be
+    enabled or disabled via a mount option.  So let's try to deprecate
+    these options from ext4.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 960681fae64e..25b1f0374f01 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1443,6 +1443,10 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
+ 	if (args->from && match_int(args, &arg))
+ 		return -1;
+ 	switch (token) {
++	case Opt_noacl:
++	case Opt_nouser_xattr:
++		ext4_msg(sb, KERN_WARNING, deprecated_msg, opt, "3.5");
++		break;
+ 	case Opt_sb:
+ 		return 1;	/* handled by get_sb_block() */
+ 	case Opt_removed:

commit c7198b9c1e4520d3b16f0f65e37d3db78745f1e1
+Author: Theodore Ts'o 
+Date:   Sun Mar 4 22:00:53 2012 -0500
+
+    ext4: ignore mount options supported by ext2/3 (but have since been removed)
+    
+    Users who tried to use the ext4 file system driver is being used for
+    the ext2 or ext3 file systems (via the CONFIG_EXT4_USE_FOR_EXT23
+    option) could have failed mounts if their /etc/fstab contains options
+    recognized by ext2 or ext3 but which have since been removed in ext4.
+    
+    So teach ext4 to recognize them and give a warning that the mount
+    option was removed.
+    
+    Report: https://bbs.archlinux.org/profile.php?id=33804
+    
+    Signed-off-by: Tom Gundersen 
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Thomas Baechler 
+    Cc: Tobias Powalowski 
+    Cc: Dave Reisner 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 27d490d6eb02..960681fae64e 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1249,6 +1249,11 @@ static const match_table_t tokens = {
+ 	{Opt_init_itable, "init_itable=%u"},
+ 	{Opt_init_itable, "init_itable"},
+ 	{Opt_noinit_itable, "noinit_itable"},
++	{Opt_removed, "check=none"},	/* mount option from ext2/3 */
++	{Opt_removed, "nocheck"},	/* mount option from ext2/3 */
++	{Opt_removed, "reservation"},	/* mount option from ext2/3 */
++	{Opt_removed, "noreservation"}, /* mount option from ext2/3 */
++	{Opt_removed, "journal=%u"},	/* mount option from ext2/3 */
+ 	{Opt_err, NULL},
+ };
+ 

commit 66acdcf4ea37f67e59a955509289e82e5f59a5d0
+Author: Theodore Ts'o 
+Date:   Sun Mar 4 20:21:38 2012 -0500
+
+    ext4: add debugging /proc file showing file system options
+    
+    Now that /proc/mounts is consistently showing only those mount options
+    which need to be specified in /etc/fstab or on the mount command line,
+    it is useful to have file which shows exactly which file system
+    options are enabled.  This can be useful when debugging a user
+    problem.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 70828699fa89..27d490d6eb02 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -847,6 +847,7 @@ static void ext4_put_super(struct super_block *sb)
+ 		ext4_commit_super(sb, 1);
+ 	}
+ 	if (sbi->s_proc) {
++		remove_proc_entry("options", sbi->s_proc);
+ 		remove_proc_entry(sb->s_id, ext4_proc_root);
+ 	}
+ 	kobject_del(&sbi->s_kobj);
+@@ -1683,16 +1684,17 @@ static const char *token2str(int token)
+  *  - it's set to a non-default value OR
+  *  - if the per-sb default is different from the global default
+  */
+-static int ext4_show_options(struct seq_file *seq, struct dentry *root)
++static int _ext4_show_options(struct seq_file *seq, struct super_block *sb,
++			      int nodefs)
+ {
+-	int def_errors;
+-	struct super_block *sb = root->d_sb;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	struct ext4_super_block *es = sbi->s_es;
++	int def_errors, def_mount_opt = nodefs ? 0 : sbi->s_def_mount_opt;
+ 	const struct mount_opts *m;
++	char sep = nodefs ? '\n' : ',';
+ 
+-#define SEQ_OPTS_PUTS(str) seq_printf(seq, "," str)
+-#define SEQ_OPTS_PRINT(str, arg) seq_printf(seq, "," str, arg)
++#define SEQ_OPTS_PUTS(str) seq_printf(seq, "%c" str, sep)
++#define SEQ_OPTS_PRINT(str, arg) seq_printf(seq, "%c" str, sep, arg)
+ 
+ 	if (sbi->s_sb_block != 1)
+ 		SEQ_OPTS_PRINT("sb=%llu", sbi->s_sb_block);
+@@ -1702,7 +1704,7 @@ static int ext4_show_options(struct seq_file *seq, struct dentry *root)
+ 		if (((m->flags & (MOPT_SET|MOPT_CLEAR)) == 0) ||
+ 		    (m->flags & MOPT_CLEAR_ERR))
+ 			continue;
+-		if (!(m->mount_opt & (sbi->s_mount_opt ^ sbi->s_def_mount_opt)))
++		if (!(m->mount_opt & (sbi->s_mount_opt ^ def_mount_opt)))
+ 			continue; /* skip if same as the default */
+ 		if ((want_set &&
+ 		     (sbi->s_mount_opt & m->mount_opt) != m->mount_opt) ||
+@@ -1711,30 +1713,30 @@ static int ext4_show_options(struct seq_file *seq, struct dentry *root)
+ 		SEQ_OPTS_PRINT("%s", token2str(m->token));
+ 	}
+ 
+-	if (sbi->s_resuid != EXT4_DEF_RESUID ||
++	if (nodefs || sbi->s_resuid != EXT4_DEF_RESUID ||
+ 	    le16_to_cpu(es->s_def_resuid) != EXT4_DEF_RESUID)
+ 		SEQ_OPTS_PRINT("resuid=%u", sbi->s_resuid);
+-	if (sbi->s_resgid != EXT4_DEF_RESGID ||
++	if (nodefs || sbi->s_resgid != EXT4_DEF_RESGID ||
+ 	    le16_to_cpu(es->s_def_resgid) != EXT4_DEF_RESGID)
+ 		SEQ_OPTS_PRINT("resgid=%u", sbi->s_resgid);
+-	def_errors = le16_to_cpu(es->s_errors);
++	def_errors = nodefs ? -1 : le16_to_cpu(es->s_errors);
+ 	if (test_opt(sb, ERRORS_RO) && def_errors != EXT4_ERRORS_RO)
+ 		SEQ_OPTS_PUTS("errors=remount-ro");
+ 	if (test_opt(sb, ERRORS_CONT) && def_errors != EXT4_ERRORS_CONTINUE)
+ 		SEQ_OPTS_PUTS("errors=continue");
+ 	if (test_opt(sb, ERRORS_PANIC) && def_errors != EXT4_ERRORS_PANIC)
+ 		SEQ_OPTS_PUTS("errors=panic");
+-	if (sbi->s_commit_interval != JBD2_DEFAULT_MAX_COMMIT_AGE*HZ)
++	if (nodefs || sbi->s_commit_interval != JBD2_DEFAULT_MAX_COMMIT_AGE*HZ)
+ 		SEQ_OPTS_PRINT("commit=%lu", sbi->s_commit_interval / HZ);
+-	if (sbi->s_min_batch_time != EXT4_DEF_MIN_BATCH_TIME)
++	if (nodefs || sbi->s_min_batch_time != EXT4_DEF_MIN_BATCH_TIME)
+ 		SEQ_OPTS_PRINT("min_batch_time=%u", sbi->s_min_batch_time);
+-	if (sbi->s_max_batch_time != EXT4_DEF_MAX_BATCH_TIME)
++	if (nodefs || sbi->s_max_batch_time != EXT4_DEF_MAX_BATCH_TIME)
+ 		SEQ_OPTS_PRINT("max_batch_time=%u", sbi->s_max_batch_time);
+ 	if (sb->s_flags & MS_I_VERSION)
+ 		SEQ_OPTS_PUTS("i_version");
+-	if (sbi->s_stripe)
++	if (nodefs || sbi->s_stripe)
+ 		SEQ_OPTS_PRINT("stripe=%lu", sbi->s_stripe);
+-	if (EXT4_MOUNT_DATA_FLAGS & (sbi->s_mount_opt ^ sbi->s_def_mount_opt)) {
++	if (EXT4_MOUNT_DATA_FLAGS & (sbi->s_mount_opt ^ def_mount_opt)) {
+ 		if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
+ 			SEQ_OPTS_PUTS("data=journal");
+ 		else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
+@@ -1742,18 +1744,48 @@ static int ext4_show_options(struct seq_file *seq, struct dentry *root)
+ 		else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
+ 			SEQ_OPTS_PUTS("data=writeback");
+ 	}
+-	if (sbi->s_inode_readahead_blks != EXT4_DEF_INODE_READAHEAD_BLKS)
++	if (nodefs ||
++	    sbi->s_inode_readahead_blks != EXT4_DEF_INODE_READAHEAD_BLKS)
+ 		SEQ_OPTS_PRINT("inode_readahead_blks=%u",
+ 			       sbi->s_inode_readahead_blks);
+ 
+-	if (test_opt(sb, INIT_INODE_TABLE) &&
+-	    (sbi->s_li_wait_mult != EXT4_DEF_LI_WAIT_MULT))
++	if (nodefs || (test_opt(sb, INIT_INODE_TABLE) &&
++		       (sbi->s_li_wait_mult != EXT4_DEF_LI_WAIT_MULT)))
+ 		SEQ_OPTS_PRINT("init_itable=%u", sbi->s_li_wait_mult);
+ 
+ 	ext4_show_quota_options(seq, sb);
+ 	return 0;
+ }
+ 
++static int ext4_show_options(struct seq_file *seq, struct dentry *root)
++{
++	return _ext4_show_options(seq, root->d_sb, 0);
++}
++
++static int options_seq_show(struct seq_file *seq, void *offset)
++{
++	struct super_block *sb = seq->private;
++	int rc;
++
++	seq_puts(seq, (sb->s_flags & MS_RDONLY) ? "ro" : "rw");
++	rc = _ext4_show_options(seq, sb, 1);
++	seq_puts(seq, "\n");
++	return rc;
++}
++
++static int options_open_fs(struct inode *inode, struct file *file)
++{
++	return single_open(file, options_seq_show, PDE(inode)->data);
++}
++
++static const struct file_operations ext4_seq_options_fops = {
++	.owner = THIS_MODULE,
++	.open = options_open_fs,
++	.read = seq_read,
++	.llseek = seq_lseek,
++	.release = single_release,
++};
++
+ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
+ 			    int read_only)
+ {
+@@ -3350,6 +3382,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	if (ext4_proc_root)
+ 		sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root);
+ 
++	if (sbi->s_proc)
++		proc_create_data("options", S_IRUGO, sbi->s_proc,
++				 &ext4_seq_options_fops, sb);
++
+ 	bgl_lock_init(sbi->s_blockgroup_lock);
+ 
+ 	for (i = 0; i < db_count; i++) {
+@@ -3674,6 +3710,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	ext4_kvfree(sbi->s_group_desc);
+ failed_mount:
+ 	if (sbi->s_proc) {
++		remove_proc_entry("options", sbi->s_proc);
+ 		remove_proc_entry(sb->s_id, ext4_proc_root);
+ 	}
+ #ifdef CONFIG_QUOTA

commit 5a916be1b31de9e833aa764de6faf27bb79f9b83
+Author: Theodore Ts'o 
+Date:   Sun Mar 4 19:27:31 2012 -0500
+
+    ext4: make ext4_show_options() be table-driven
+    
+    Consistently show mount options which are the non-default, so that
+    /proc/mounts accurately shows the mount options that would be
+    necessary to mount the file system in its current mode of operation.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index d70b981b85fb..6481e3ca3528 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1143,6 +1143,7 @@ struct ext4_sb_info {
+ 	unsigned int s_mount_opt;
+ 	unsigned int s_mount_opt2;
+ 	unsigned int s_mount_flags;
++	unsigned int s_def_mount_opt;
+ 	ext4_fsblk_t s_sb_block;
+ 	uid_t s_resuid;
+ 	gid_t s_resgid;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 7e3a319ec402..70828699fa89 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1198,8 +1198,8 @@ static const match_table_t tokens = {
+ 	{Opt_nouser_xattr, "nouser_xattr"},
+ 	{Opt_acl, "acl"},
+ 	{Opt_noacl, "noacl"},
+-	{Opt_noload, "noload"},
+ 	{Opt_noload, "norecovery"},
++	{Opt_noload, "noload"},
+ 	{Opt_removed, "nobh"},
+ 	{Opt_removed, "bh"},
+ 	{Opt_commit, "commit=%u"},
+@@ -1668,6 +1668,16 @@ static inline void ext4_show_quota_options(struct seq_file *seq,
+ #endif
+ }
+ 
++static const char *token2str(int token)
++{
++	static const struct match_token *t;
++
++	for (t = tokens; t->token != Opt_err; t++)
++		if (t->token == token && !strchr(t->pattern, '='))
++			break;
++	return t->pattern;
++}
++
+ /*
+  * Show an option if
+  *  - it's set to a non-default value OR
+@@ -1676,132 +1686,71 @@ static inline void ext4_show_quota_options(struct seq_file *seq,
+ static int ext4_show_options(struct seq_file *seq, struct dentry *root)
+ {
+ 	int def_errors;
+-	unsigned long def_mount_opts;
+ 	struct super_block *sb = root->d_sb;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	struct ext4_super_block *es = sbi->s_es;
++	const struct mount_opts *m;
+ 
+-	def_mount_opts = le32_to_cpu(es->s_default_mount_opts);
+-	def_errors     = le16_to_cpu(es->s_errors);
++#define SEQ_OPTS_PUTS(str) seq_printf(seq, "," str)
++#define SEQ_OPTS_PRINT(str, arg) seq_printf(seq, "," str, arg)
+ 
+ 	if (sbi->s_sb_block != 1)
+-		seq_printf(seq, ",sb=%llu", sbi->s_sb_block);
+-	if (test_opt(sb, MINIX_DF))
+-		seq_puts(seq, ",minixdf");
+-	if (test_opt(sb, GRPID) && !(def_mount_opts & EXT4_DEFM_BSDGROUPS))
+-		seq_puts(seq, ",grpid");
+-	if (!test_opt(sb, GRPID) && (def_mount_opts & EXT4_DEFM_BSDGROUPS))
+-		seq_puts(seq, ",nogrpid");
+-	if (sbi->s_resuid != EXT4_DEF_RESUID ||
+-	    le16_to_cpu(es->s_def_resuid) != EXT4_DEF_RESUID) {
+-		seq_printf(seq, ",resuid=%u", sbi->s_resuid);
++		SEQ_OPTS_PRINT("sb=%llu", sbi->s_sb_block);
++
++	for (m = ext4_mount_opts; m->token != Opt_err; m++) {
++		int want_set = m->flags & MOPT_SET;
++		if (((m->flags & (MOPT_SET|MOPT_CLEAR)) == 0) ||
++		    (m->flags & MOPT_CLEAR_ERR))
++			continue;
++		if (!(m->mount_opt & (sbi->s_mount_opt ^ sbi->s_def_mount_opt)))
++			continue; /* skip if same as the default */
++		if ((want_set &&
++		     (sbi->s_mount_opt & m->mount_opt) != m->mount_opt) ||
++		    (!want_set && (sbi->s_mount_opt & m->mount_opt)))
++			continue; /* select Opt_noFoo vs Opt_Foo */
++		SEQ_OPTS_PRINT("%s", token2str(m->token));
+ 	}
++
++	if (sbi->s_resuid != EXT4_DEF_RESUID ||
++	    le16_to_cpu(es->s_def_resuid) != EXT4_DEF_RESUID)
++		SEQ_OPTS_PRINT("resuid=%u", sbi->s_resuid);
+ 	if (sbi->s_resgid != EXT4_DEF_RESGID ||
+-	    le16_to_cpu(es->s_def_resgid) != EXT4_DEF_RESGID) {
+-		seq_printf(seq, ",resgid=%u", sbi->s_resgid);
+-	}
+-	if (test_opt(sb, ERRORS_RO)) {
+-		if (def_errors == EXT4_ERRORS_PANIC ||
+-		    def_errors == EXT4_ERRORS_CONTINUE) {
+-			seq_puts(seq, ",errors=remount-ro");
+-		}
+-	}
++	    le16_to_cpu(es->s_def_resgid) != EXT4_DEF_RESGID)
++		SEQ_OPTS_PRINT("resgid=%u", sbi->s_resgid);
++	def_errors = le16_to_cpu(es->s_errors);
++	if (test_opt(sb, ERRORS_RO) && def_errors != EXT4_ERRORS_RO)
++		SEQ_OPTS_PUTS("errors=remount-ro");
+ 	if (test_opt(sb, ERRORS_CONT) && def_errors != EXT4_ERRORS_CONTINUE)
+-		seq_puts(seq, ",errors=continue");
++		SEQ_OPTS_PUTS("errors=continue");
+ 	if (test_opt(sb, ERRORS_PANIC) && def_errors != EXT4_ERRORS_PANIC)
+-		seq_puts(seq, ",errors=panic");
+-	if (test_opt(sb, NO_UID32) && !(def_mount_opts & EXT4_DEFM_UID16))
+-		seq_puts(seq, ",nouid32");
+-	if (test_opt(sb, DEBUG) && !(def_mount_opts & EXT4_DEFM_DEBUG))
+-		seq_puts(seq, ",debug");
+-#ifdef CONFIG_EXT4_FS_XATTR
+-	if (test_opt(sb, XATTR_USER))
+-		seq_puts(seq, ",user_xattr");
+-	if (!test_opt(sb, XATTR_USER))
+-		seq_puts(seq, ",nouser_xattr");
+-#endif
+-#ifdef CONFIG_EXT4_FS_POSIX_ACL
+-	if (test_opt(sb, POSIX_ACL) && !(def_mount_opts & EXT4_DEFM_ACL))
+-		seq_puts(seq, ",acl");
+-	if (!test_opt(sb, POSIX_ACL) && (def_mount_opts & EXT4_DEFM_ACL))
+-		seq_puts(seq, ",noacl");
+-#endif
+-	if (sbi->s_commit_interval != JBD2_DEFAULT_MAX_COMMIT_AGE*HZ) {
+-		seq_printf(seq, ",commit=%u",
+-			   (unsigned) (sbi->s_commit_interval / HZ));
+-	}
+-	if (sbi->s_min_batch_time != EXT4_DEF_MIN_BATCH_TIME) {
+-		seq_printf(seq, ",min_batch_time=%u",
+-			   (unsigned) sbi->s_min_batch_time);
+-	}
+-	if (sbi->s_max_batch_time != EXT4_DEF_MAX_BATCH_TIME) {
+-		seq_printf(seq, ",max_batch_time=%u",
+-			   (unsigned) sbi->s_max_batch_time);
+-	}
+-
+-	/*
+-	 * We're changing the default of barrier mount option, so
+-	 * let's always display its mount state so it's clear what its
+-	 * status is.
+-	 */
+-	seq_puts(seq, ",barrier=");
+-	seq_puts(seq, test_opt(sb, BARRIER) ? "1" : "0");
+-	if (test_opt(sb, JOURNAL_ASYNC_COMMIT))
+-		seq_puts(seq, ",journal_async_commit");
+-	else if (test_opt(sb, JOURNAL_CHECKSUM))
+-		seq_puts(seq, ",journal_checksum");
++		SEQ_OPTS_PUTS("errors=panic");
++	if (sbi->s_commit_interval != JBD2_DEFAULT_MAX_COMMIT_AGE*HZ)
++		SEQ_OPTS_PRINT("commit=%lu", sbi->s_commit_interval / HZ);
++	if (sbi->s_min_batch_time != EXT4_DEF_MIN_BATCH_TIME)
++		SEQ_OPTS_PRINT("min_batch_time=%u", sbi->s_min_batch_time);
++	if (sbi->s_max_batch_time != EXT4_DEF_MAX_BATCH_TIME)
++		SEQ_OPTS_PRINT("max_batch_time=%u", sbi->s_max_batch_time);
+ 	if (sb->s_flags & MS_I_VERSION)
+-		seq_puts(seq, ",i_version");
+-	if (!test_opt(sb, DELALLOC) &&
+-	    !(def_mount_opts & EXT4_DEFM_NODELALLOC))
+-		seq_puts(seq, ",nodelalloc");
+-
+-	if (!test_opt(sb, MBLK_IO_SUBMIT))
+-		seq_puts(seq, ",nomblk_io_submit");
++		SEQ_OPTS_PUTS("i_version");
+ 	if (sbi->s_stripe)
+-		seq_printf(seq, ",stripe=%lu", sbi->s_stripe);
+-	/*
+-	 * journal mode get enabled in different ways
+-	 * So just print the value even if we didn't specify it
+-	 */
+-	if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
+-		seq_puts(seq, ",data=journal");
+-	else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
+-		seq_puts(seq, ",data=ordered");
+-	else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
+-		seq_puts(seq, ",data=writeback");
+-
++		SEQ_OPTS_PRINT("stripe=%lu", sbi->s_stripe);
++	if (EXT4_MOUNT_DATA_FLAGS & (sbi->s_mount_opt ^ sbi->s_def_mount_opt)) {
++		if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
++			SEQ_OPTS_PUTS("data=journal");
++		else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
++			SEQ_OPTS_PUTS("data=ordered");
++		else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
++			SEQ_OPTS_PUTS("data=writeback");
++	}
+ 	if (sbi->s_inode_readahead_blks != EXT4_DEF_INODE_READAHEAD_BLKS)
+-		seq_printf(seq, ",inode_readahead_blks=%u",
+-			   sbi->s_inode_readahead_blks);
+-
+-	if (test_opt(sb, DATA_ERR_ABORT))
+-		seq_puts(seq, ",data_err=abort");
+-
+-	if (test_opt(sb, NO_AUTO_DA_ALLOC))
+-		seq_puts(seq, ",noauto_da_alloc");
++		SEQ_OPTS_PRINT("inode_readahead_blks=%u",
++			       sbi->s_inode_readahead_blks);
+ 
+-	if (test_opt(sb, DISCARD) && !(def_mount_opts & EXT4_DEFM_DISCARD))
+-		seq_puts(seq, ",discard");
+-
+-	if (test_opt(sb, NOLOAD))
+-		seq_puts(seq, ",norecovery");
+-
+-	if (test_opt(sb, DIOREAD_NOLOCK))
+-		seq_puts(seq, ",dioread_nolock");
+-
+-	if (test_opt(sb, BLOCK_VALIDITY) &&
+-	    !(def_mount_opts & EXT4_DEFM_BLOCK_VALIDITY))
+-		seq_puts(seq, ",block_validity");
+-
+-	if (!test_opt(sb, INIT_INODE_TABLE))
+-		seq_puts(seq, ",noinit_itable");
+-	else if (sbi->s_li_wait_mult != EXT4_DEF_LI_WAIT_MULT)
+-		seq_printf(seq, ",init_itable=%u",
+-			   (unsigned) sbi->s_li_wait_mult);
++	if (test_opt(sb, INIT_INODE_TABLE) &&
++	    (sbi->s_li_wait_mult != EXT4_DEF_LI_WAIT_MULT))
++		SEQ_OPTS_PRINT("init_itable=%u", sbi->s_li_wait_mult);
+ 
+ 	ext4_show_quota_options(seq, sb);
+-
+ 	return 0;
+ }
+ 
+@@ -3105,6 +3054,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 			 "failed to parse options in superblock: %s",
+ 			 sbi->s_es->s_mount_opts);
+ 	}
++	sbi->s_def_mount_opt = sbi->s_mount_opt;
+ 	if (!parse_options((char *) data, sb, &journal_devnum,
+ 			   &journal_ioprio, 0))
+ 		goto failed_mount;

commit 2adf6da8379b68838aa1002e11efd66916689a9b
+Author: Theodore Ts'o 
+Date:   Sat Mar 3 23:20:50 2012 -0500
+
+    ext4: move ext4_show_options() after parse_options()
+    
+    This commit is strictly a code movement so in preparation of changing
+    ext4_show_options to be table driven.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 61a65ee2c905..7e3a319ec402 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -62,6 +62,7 @@ static struct ext4_features *ext4_feat;
+ 
+ static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
+ 			     unsigned long journal_devnum);
++static int ext4_show_options(struct seq_file *seq, struct dentry *root);
+ static int ext4_commit_super(struct super_block *sb, int sync);
+ static void ext4_mark_recovery_complete(struct super_block *sb,
+ 					struct ext4_super_block *es);
+@@ -1006,180 +1007,6 @@ void ext4_clear_inode(struct inode *inode)
+ 	}
+ }
+ 
+-static inline void ext4_show_quota_options(struct seq_file *seq,
+-					   struct super_block *sb)
+-{
+-#if defined(CONFIG_QUOTA)
+-	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-
+-	if (sbi->s_jquota_fmt) {
+-		char *fmtname = "";
+-
+-		switch (sbi->s_jquota_fmt) {
+-		case QFMT_VFS_OLD:
+-			fmtname = "vfsold";
+-			break;
+-		case QFMT_VFS_V0:
+-			fmtname = "vfsv0";
+-			break;
+-		case QFMT_VFS_V1:
+-			fmtname = "vfsv1";
+-			break;
+-		}
+-		seq_printf(seq, ",jqfmt=%s", fmtname);
+-	}
+-
+-	if (sbi->s_qf_names[USRQUOTA])
+-		seq_printf(seq, ",usrjquota=%s", sbi->s_qf_names[USRQUOTA]);
+-
+-	if (sbi->s_qf_names[GRPQUOTA])
+-		seq_printf(seq, ",grpjquota=%s", sbi->s_qf_names[GRPQUOTA]);
+-
+-	if (test_opt(sb, USRQUOTA))
+-		seq_puts(seq, ",usrquota");
+-
+-	if (test_opt(sb, GRPQUOTA))
+-		seq_puts(seq, ",grpquota");
+-#endif
+-}
+-
+-/*
+- * Show an option if
+- *  - it's set to a non-default value OR
+- *  - if the per-sb default is different from the global default
+- */
+-static int ext4_show_options(struct seq_file *seq, struct dentry *root)
+-{
+-	int def_errors;
+-	unsigned long def_mount_opts;
+-	struct super_block *sb = root->d_sb;
+-	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-	struct ext4_super_block *es = sbi->s_es;
+-
+-	def_mount_opts = le32_to_cpu(es->s_default_mount_opts);
+-	def_errors     = le16_to_cpu(es->s_errors);
+-
+-	if (sbi->s_sb_block != 1)
+-		seq_printf(seq, ",sb=%llu", sbi->s_sb_block);
+-	if (test_opt(sb, MINIX_DF))
+-		seq_puts(seq, ",minixdf");
+-	if (test_opt(sb, GRPID) && !(def_mount_opts & EXT4_DEFM_BSDGROUPS))
+-		seq_puts(seq, ",grpid");
+-	if (!test_opt(sb, GRPID) && (def_mount_opts & EXT4_DEFM_BSDGROUPS))
+-		seq_puts(seq, ",nogrpid");
+-	if (sbi->s_resuid != EXT4_DEF_RESUID ||
+-	    le16_to_cpu(es->s_def_resuid) != EXT4_DEF_RESUID) {
+-		seq_printf(seq, ",resuid=%u", sbi->s_resuid);
+-	}
+-	if (sbi->s_resgid != EXT4_DEF_RESGID ||
+-	    le16_to_cpu(es->s_def_resgid) != EXT4_DEF_RESGID) {
+-		seq_printf(seq, ",resgid=%u", sbi->s_resgid);
+-	}
+-	if (test_opt(sb, ERRORS_RO)) {
+-		if (def_errors == EXT4_ERRORS_PANIC ||
+-		    def_errors == EXT4_ERRORS_CONTINUE) {
+-			seq_puts(seq, ",errors=remount-ro");
+-		}
+-	}
+-	if (test_opt(sb, ERRORS_CONT) && def_errors != EXT4_ERRORS_CONTINUE)
+-		seq_puts(seq, ",errors=continue");
+-	if (test_opt(sb, ERRORS_PANIC) && def_errors != EXT4_ERRORS_PANIC)
+-		seq_puts(seq, ",errors=panic");
+-	if (test_opt(sb, NO_UID32) && !(def_mount_opts & EXT4_DEFM_UID16))
+-		seq_puts(seq, ",nouid32");
+-	if (test_opt(sb, DEBUG) && !(def_mount_opts & EXT4_DEFM_DEBUG))
+-		seq_puts(seq, ",debug");
+-#ifdef CONFIG_EXT4_FS_XATTR
+-	if (test_opt(sb, XATTR_USER))
+-		seq_puts(seq, ",user_xattr");
+-	if (!test_opt(sb, XATTR_USER))
+-		seq_puts(seq, ",nouser_xattr");
+-#endif
+-#ifdef CONFIG_EXT4_FS_POSIX_ACL
+-	if (test_opt(sb, POSIX_ACL) && !(def_mount_opts & EXT4_DEFM_ACL))
+-		seq_puts(seq, ",acl");
+-	if (!test_opt(sb, POSIX_ACL) && (def_mount_opts & EXT4_DEFM_ACL))
+-		seq_puts(seq, ",noacl");
+-#endif
+-	if (sbi->s_commit_interval != JBD2_DEFAULT_MAX_COMMIT_AGE*HZ) {
+-		seq_printf(seq, ",commit=%u",
+-			   (unsigned) (sbi->s_commit_interval / HZ));
+-	}
+-	if (sbi->s_min_batch_time != EXT4_DEF_MIN_BATCH_TIME) {
+-		seq_printf(seq, ",min_batch_time=%u",
+-			   (unsigned) sbi->s_min_batch_time);
+-	}
+-	if (sbi->s_max_batch_time != EXT4_DEF_MAX_BATCH_TIME) {
+-		seq_printf(seq, ",max_batch_time=%u",
+-			   (unsigned) sbi->s_max_batch_time);
+-	}
+-
+-	/*
+-	 * We're changing the default of barrier mount option, so
+-	 * let's always display its mount state so it's clear what its
+-	 * status is.
+-	 */
+-	seq_puts(seq, ",barrier=");
+-	seq_puts(seq, test_opt(sb, BARRIER) ? "1" : "0");
+-	if (test_opt(sb, JOURNAL_ASYNC_COMMIT))
+-		seq_puts(seq, ",journal_async_commit");
+-	else if (test_opt(sb, JOURNAL_CHECKSUM))
+-		seq_puts(seq, ",journal_checksum");
+-	if (sb->s_flags & MS_I_VERSION)
+-		seq_puts(seq, ",i_version");
+-	if (!test_opt(sb, DELALLOC) &&
+-	    !(def_mount_opts & EXT4_DEFM_NODELALLOC))
+-		seq_puts(seq, ",nodelalloc");
+-
+-	if (!test_opt(sb, MBLK_IO_SUBMIT))
+-		seq_puts(seq, ",nomblk_io_submit");
+-	if (sbi->s_stripe)
+-		seq_printf(seq, ",stripe=%lu", sbi->s_stripe);
+-	/*
+-	 * journal mode get enabled in different ways
+-	 * So just print the value even if we didn't specify it
+-	 */
+-	if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
+-		seq_puts(seq, ",data=journal");
+-	else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
+-		seq_puts(seq, ",data=ordered");
+-	else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
+-		seq_puts(seq, ",data=writeback");
+-
+-	if (sbi->s_inode_readahead_blks != EXT4_DEF_INODE_READAHEAD_BLKS)
+-		seq_printf(seq, ",inode_readahead_blks=%u",
+-			   sbi->s_inode_readahead_blks);
+-
+-	if (test_opt(sb, DATA_ERR_ABORT))
+-		seq_puts(seq, ",data_err=abort");
+-
+-	if (test_opt(sb, NO_AUTO_DA_ALLOC))
+-		seq_puts(seq, ",noauto_da_alloc");
+-
+-	if (test_opt(sb, DISCARD) && !(def_mount_opts & EXT4_DEFM_DISCARD))
+-		seq_puts(seq, ",discard");
+-
+-	if (test_opt(sb, NOLOAD))
+-		seq_puts(seq, ",norecovery");
+-
+-	if (test_opt(sb, DIOREAD_NOLOCK))
+-		seq_puts(seq, ",dioread_nolock");
+-
+-	if (test_opt(sb, BLOCK_VALIDITY) &&
+-	    !(def_mount_opts & EXT4_DEFM_BLOCK_VALIDITY))
+-		seq_puts(seq, ",block_validity");
+-
+-	if (!test_opt(sb, INIT_INODE_TABLE))
+-		seq_puts(seq, ",noinit_itable");
+-	else if (sbi->s_li_wait_mult != EXT4_DEF_LI_WAIT_MULT)
+-		seq_printf(seq, ",init_itable=%u",
+-			   (unsigned) sbi->s_li_wait_mult);
+-
+-	ext4_show_quota_options(seq, sb);
+-
+-	return 0;
+-}
+-
+ static struct inode *ext4_nfs_get_inode(struct super_block *sb,
+ 					u64 ino, u32 generation)
+ {
+@@ -1804,6 +1631,180 @@ static int parse_options(char *options, struct super_block *sb,
+ 	return 1;
+ }
+ 
++static inline void ext4_show_quota_options(struct seq_file *seq,
++					   struct super_block *sb)
++{
++#if defined(CONFIG_QUOTA)
++	struct ext4_sb_info *sbi = EXT4_SB(sb);
++
++	if (sbi->s_jquota_fmt) {
++		char *fmtname = "";
++
++		switch (sbi->s_jquota_fmt) {
++		case QFMT_VFS_OLD:
++			fmtname = "vfsold";
++			break;
++		case QFMT_VFS_V0:
++			fmtname = "vfsv0";
++			break;
++		case QFMT_VFS_V1:
++			fmtname = "vfsv1";
++			break;
++		}
++		seq_printf(seq, ",jqfmt=%s", fmtname);
++	}
++
++	if (sbi->s_qf_names[USRQUOTA])
++		seq_printf(seq, ",usrjquota=%s", sbi->s_qf_names[USRQUOTA]);
++
++	if (sbi->s_qf_names[GRPQUOTA])
++		seq_printf(seq, ",grpjquota=%s", sbi->s_qf_names[GRPQUOTA]);
++
++	if (test_opt(sb, USRQUOTA))
++		seq_puts(seq, ",usrquota");
++
++	if (test_opt(sb, GRPQUOTA))
++		seq_puts(seq, ",grpquota");
++#endif
++}
++
++/*
++ * Show an option if
++ *  - it's set to a non-default value OR
++ *  - if the per-sb default is different from the global default
++ */
++static int ext4_show_options(struct seq_file *seq, struct dentry *root)
++{
++	int def_errors;
++	unsigned long def_mount_opts;
++	struct super_block *sb = root->d_sb;
++	struct ext4_sb_info *sbi = EXT4_SB(sb);
++	struct ext4_super_block *es = sbi->s_es;
++
++	def_mount_opts = le32_to_cpu(es->s_default_mount_opts);
++	def_errors     = le16_to_cpu(es->s_errors);
++
++	if (sbi->s_sb_block != 1)
++		seq_printf(seq, ",sb=%llu", sbi->s_sb_block);
++	if (test_opt(sb, MINIX_DF))
++		seq_puts(seq, ",minixdf");
++	if (test_opt(sb, GRPID) && !(def_mount_opts & EXT4_DEFM_BSDGROUPS))
++		seq_puts(seq, ",grpid");
++	if (!test_opt(sb, GRPID) && (def_mount_opts & EXT4_DEFM_BSDGROUPS))
++		seq_puts(seq, ",nogrpid");
++	if (sbi->s_resuid != EXT4_DEF_RESUID ||
++	    le16_to_cpu(es->s_def_resuid) != EXT4_DEF_RESUID) {
++		seq_printf(seq, ",resuid=%u", sbi->s_resuid);
++	}
++	if (sbi->s_resgid != EXT4_DEF_RESGID ||
++	    le16_to_cpu(es->s_def_resgid) != EXT4_DEF_RESGID) {
++		seq_printf(seq, ",resgid=%u", sbi->s_resgid);
++	}
++	if (test_opt(sb, ERRORS_RO)) {
++		if (def_errors == EXT4_ERRORS_PANIC ||
++		    def_errors == EXT4_ERRORS_CONTINUE) {
++			seq_puts(seq, ",errors=remount-ro");
++		}
++	}
++	if (test_opt(sb, ERRORS_CONT) && def_errors != EXT4_ERRORS_CONTINUE)
++		seq_puts(seq, ",errors=continue");
++	if (test_opt(sb, ERRORS_PANIC) && def_errors != EXT4_ERRORS_PANIC)
++		seq_puts(seq, ",errors=panic");
++	if (test_opt(sb, NO_UID32) && !(def_mount_opts & EXT4_DEFM_UID16))
++		seq_puts(seq, ",nouid32");
++	if (test_opt(sb, DEBUG) && !(def_mount_opts & EXT4_DEFM_DEBUG))
++		seq_puts(seq, ",debug");
++#ifdef CONFIG_EXT4_FS_XATTR
++	if (test_opt(sb, XATTR_USER))
++		seq_puts(seq, ",user_xattr");
++	if (!test_opt(sb, XATTR_USER))
++		seq_puts(seq, ",nouser_xattr");
++#endif
++#ifdef CONFIG_EXT4_FS_POSIX_ACL
++	if (test_opt(sb, POSIX_ACL) && !(def_mount_opts & EXT4_DEFM_ACL))
++		seq_puts(seq, ",acl");
++	if (!test_opt(sb, POSIX_ACL) && (def_mount_opts & EXT4_DEFM_ACL))
++		seq_puts(seq, ",noacl");
++#endif
++	if (sbi->s_commit_interval != JBD2_DEFAULT_MAX_COMMIT_AGE*HZ) {
++		seq_printf(seq, ",commit=%u",
++			   (unsigned) (sbi->s_commit_interval / HZ));
++	}
++	if (sbi->s_min_batch_time != EXT4_DEF_MIN_BATCH_TIME) {
++		seq_printf(seq, ",min_batch_time=%u",
++			   (unsigned) sbi->s_min_batch_time);
++	}
++	if (sbi->s_max_batch_time != EXT4_DEF_MAX_BATCH_TIME) {
++		seq_printf(seq, ",max_batch_time=%u",
++			   (unsigned) sbi->s_max_batch_time);
++	}
++
++	/*
++	 * We're changing the default of barrier mount option, so
++	 * let's always display its mount state so it's clear what its
++	 * status is.
++	 */
++	seq_puts(seq, ",barrier=");
++	seq_puts(seq, test_opt(sb, BARRIER) ? "1" : "0");
++	if (test_opt(sb, JOURNAL_ASYNC_COMMIT))
++		seq_puts(seq, ",journal_async_commit");
++	else if (test_opt(sb, JOURNAL_CHECKSUM))
++		seq_puts(seq, ",journal_checksum");
++	if (sb->s_flags & MS_I_VERSION)
++		seq_puts(seq, ",i_version");
++	if (!test_opt(sb, DELALLOC) &&
++	    !(def_mount_opts & EXT4_DEFM_NODELALLOC))
++		seq_puts(seq, ",nodelalloc");
++
++	if (!test_opt(sb, MBLK_IO_SUBMIT))
++		seq_puts(seq, ",nomblk_io_submit");
++	if (sbi->s_stripe)
++		seq_printf(seq, ",stripe=%lu", sbi->s_stripe);
++	/*
++	 * journal mode get enabled in different ways
++	 * So just print the value even if we didn't specify it
++	 */
++	if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
++		seq_puts(seq, ",data=journal");
++	else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
++		seq_puts(seq, ",data=ordered");
++	else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
++		seq_puts(seq, ",data=writeback");
++
++	if (sbi->s_inode_readahead_blks != EXT4_DEF_INODE_READAHEAD_BLKS)
++		seq_printf(seq, ",inode_readahead_blks=%u",
++			   sbi->s_inode_readahead_blks);
++
++	if (test_opt(sb, DATA_ERR_ABORT))
++		seq_puts(seq, ",data_err=abort");
++
++	if (test_opt(sb, NO_AUTO_DA_ALLOC))
++		seq_puts(seq, ",noauto_da_alloc");
++
++	if (test_opt(sb, DISCARD) && !(def_mount_opts & EXT4_DEFM_DISCARD))
++		seq_puts(seq, ",discard");
++
++	if (test_opt(sb, NOLOAD))
++		seq_puts(seq, ",norecovery");
++
++	if (test_opt(sb, DIOREAD_NOLOCK))
++		seq_puts(seq, ",dioread_nolock");
++
++	if (test_opt(sb, BLOCK_VALIDITY) &&
++	    !(def_mount_opts & EXT4_DEFM_BLOCK_VALIDITY))
++		seq_puts(seq, ",block_validity");
++
++	if (!test_opt(sb, INIT_INODE_TABLE))
++		seq_puts(seq, ",noinit_itable");
++	else if (sbi->s_li_wait_mult != EXT4_DEF_LI_WAIT_MULT)
++		seq_printf(seq, ",init_itable=%u",
++			   (unsigned) sbi->s_li_wait_mult);
++
++	ext4_show_quota_options(seq, sb);
++
++	return 0;
++}
++
+ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
+ 			    int read_only)
+ {

commit 26092bf52478d23f872c6531e9e3ea9bde2c66c1
+Author: Theodore Ts'o 
+Date:   Sat Mar 3 23:20:47 2012 -0500
+
+    ext4: use a table-driven handler for mount options
+    
+    By using a table-drive approach, we shave about 100 lines of code from
+    ext4, and make the code a bit more regular and factored out.  This
+    will also make it possible in a future patch to use this table for
+    displaying the mount options that were specified in /proc/mounts.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index b5f2e6816ec3..61a65ee2c905 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1509,371 +1509,269 @@ static int clear_qf_name(struct super_block *sb, int qtype)
+ }
+ #endif
+ 
+-static int parse_options(char *options, struct super_block *sb,
+-			 unsigned long *journal_devnum,
+-			 unsigned int *journal_ioprio,
+-			 int is_remount)
+-{
+-	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-	char *p;
+-	substring_t args[MAX_OPT_ARGS];
+-	int data_opt = 0;
+-	int option;
++#define MOPT_SET	0x0001
++#define MOPT_CLEAR	0x0002
++#define MOPT_NOSUPPORT	0x0004
++#define MOPT_EXPLICIT	0x0008
++#define MOPT_CLEAR_ERR	0x0010
++#define MOPT_GTE0	0x0020
+ #ifdef CONFIG_QUOTA
+-	int qfmt;
++#define MOPT_Q		0
++#define MOPT_QFMT	0x0040
++#else
++#define MOPT_Q		MOPT_NOSUPPORT
++#define MOPT_QFMT	MOPT_NOSUPPORT
+ #endif
+-
+-	if (!options)
+-		return 1;
+-
+-	while ((p = strsep(&options, ",")) != NULL) {
+-		int token;
+-		if (!*p)
+-			continue;
+-
+-		/*
+-		 * Initialize args struct so we know whether arg was
+-		 * found; some options take optional arguments.
+-		 */
+-		args[0].to = args[0].from = NULL;
+-		token = match_token(p, tokens, args);
+-		switch (token) {
+-		case Opt_bsd_df:
+-			clear_opt(sb, MINIX_DF);
+-			break;
+-		case Opt_minix_df:
+-			set_opt(sb, MINIX_DF);
+-			break;
+-		case Opt_grpid:
+-			set_opt(sb, GRPID);
+-			break;
+-		case Opt_nogrpid:
+-			clear_opt(sb, GRPID);
+-			break;
+-		case Opt_resuid:
+-			if (match_int(&args[0], &option))
+-				return 0;
+-			sbi->s_resuid = option;
+-			break;
+-		case Opt_resgid:
+-			if (match_int(&args[0], &option))
+-				return 0;
+-			sbi->s_resgid = option;
+-			break;
+-		case Opt_sb:
+-			/* handled by get_sb_block() instead of here */
+-			/* *sb_block = match_int(&args[0]); */
+-			break;
+-		case Opt_err_panic:
+-			clear_opt(sb, ERRORS_MASK);
+-			set_opt(sb, ERRORS_PANIC);
+-			break;
+-		case Opt_err_ro:
+-			clear_opt(sb, ERRORS_MASK);
+-			set_opt(sb, ERRORS_RO);
+-			break;
+-		case Opt_err_cont:
+-			clear_opt(sb, ERRORS_MASK);
+-			set_opt(sb, ERRORS_CONT);
+-			break;
+-		case Opt_nouid32:
+-			set_opt(sb, NO_UID32);
+-			break;
+-		case Opt_debug:
+-			set_opt(sb, DEBUG);
+-			break;
+-		case Opt_removed:
+-			ext4_msg(sb, KERN_WARNING,
+-				 "Ignoring deprecated %s option", p);
+-			break;
++#define MOPT_DATAJ	0x0080
++
++static const struct mount_opts {
++	int	token;
++	int	mount_opt;
++	int	flags;
++} ext4_mount_opts[] = {
++	{Opt_minix_df, EXT4_MOUNT_MINIX_DF, MOPT_SET},
++	{Opt_bsd_df, EXT4_MOUNT_MINIX_DF, MOPT_CLEAR},
++	{Opt_grpid, EXT4_MOUNT_GRPID, MOPT_SET},
++	{Opt_nogrpid, EXT4_MOUNT_GRPID, MOPT_CLEAR},
++	{Opt_mblk_io_submit, EXT4_MOUNT_MBLK_IO_SUBMIT, MOPT_SET},
++	{Opt_nomblk_io_submit, EXT4_MOUNT_MBLK_IO_SUBMIT, MOPT_CLEAR},
++	{Opt_block_validity, EXT4_MOUNT_BLOCK_VALIDITY, MOPT_SET},
++	{Opt_noblock_validity, EXT4_MOUNT_BLOCK_VALIDITY, MOPT_CLEAR},
++	{Opt_dioread_nolock, EXT4_MOUNT_DIOREAD_NOLOCK, MOPT_SET},
++	{Opt_dioread_lock, EXT4_MOUNT_DIOREAD_NOLOCK, MOPT_CLEAR},
++	{Opt_discard, EXT4_MOUNT_DISCARD, MOPT_SET},
++	{Opt_nodiscard, EXT4_MOUNT_DISCARD, MOPT_CLEAR},
++	{Opt_delalloc, EXT4_MOUNT_DELALLOC, MOPT_SET | MOPT_EXPLICIT},
++	{Opt_nodelalloc, EXT4_MOUNT_DELALLOC, MOPT_CLEAR | MOPT_EXPLICIT},
++	{Opt_journal_checksum, EXT4_MOUNT_JOURNAL_CHECKSUM, MOPT_SET},
++	{Opt_journal_async_commit, (EXT4_MOUNT_JOURNAL_ASYNC_COMMIT |
++				    EXT4_MOUNT_JOURNAL_CHECKSUM), MOPT_SET},
++	{Opt_noload, EXT4_MOUNT_NOLOAD, MOPT_SET},
++	{Opt_err_panic, EXT4_MOUNT_ERRORS_PANIC, MOPT_SET | MOPT_CLEAR_ERR},
++	{Opt_err_ro, EXT4_MOUNT_ERRORS_RO, MOPT_SET | MOPT_CLEAR_ERR},
++	{Opt_err_cont, EXT4_MOUNT_ERRORS_CONT, MOPT_SET | MOPT_CLEAR_ERR},
++	{Opt_data_err_abort, EXT4_MOUNT_DATA_ERR_ABORT, MOPT_SET},
++	{Opt_data_err_ignore, EXT4_MOUNT_DATA_ERR_ABORT, MOPT_CLEAR},
++	{Opt_barrier, EXT4_MOUNT_BARRIER, MOPT_SET},
++	{Opt_nobarrier, EXT4_MOUNT_BARRIER, MOPT_CLEAR},
++	{Opt_noauto_da_alloc, EXT4_MOUNT_NO_AUTO_DA_ALLOC, MOPT_SET},
++	{Opt_auto_da_alloc, EXT4_MOUNT_NO_AUTO_DA_ALLOC, MOPT_CLEAR},
++	{Opt_noinit_itable, EXT4_MOUNT_INIT_INODE_TABLE, MOPT_CLEAR},
++	{Opt_commit, 0, MOPT_GTE0},
++	{Opt_max_batch_time, 0, MOPT_GTE0},
++	{Opt_min_batch_time, 0, MOPT_GTE0},
++	{Opt_inode_readahead_blks, 0, MOPT_GTE0},
++	{Opt_init_itable, 0, MOPT_GTE0},
++	{Opt_stripe, 0, MOPT_GTE0},
++	{Opt_data_journal, EXT4_MOUNT_JOURNAL_DATA, MOPT_DATAJ},
++	{Opt_data_ordered, EXT4_MOUNT_ORDERED_DATA, MOPT_DATAJ},
++	{Opt_data_writeback, EXT4_MOUNT_WRITEBACK_DATA, MOPT_DATAJ},
+ #ifdef CONFIG_EXT4_FS_XATTR
+-		case Opt_user_xattr:
+-			set_opt(sb, XATTR_USER);
+-			break;
+-		case Opt_nouser_xattr:
+-			clear_opt(sb, XATTR_USER);
+-			break;
++	{Opt_user_xattr, EXT4_MOUNT_XATTR_USER, MOPT_SET},
++	{Opt_nouser_xattr, EXT4_MOUNT_XATTR_USER, MOPT_CLEAR},
+ #else
+-		case Opt_user_xattr:
+-		case Opt_nouser_xattr:
+-			ext4_msg(sb, KERN_ERR, "(no)user_xattr options not supported");
+-			break;
++	{Opt_user_xattr, 0, MOPT_NOSUPPORT},
++	{Opt_nouser_xattr, 0, MOPT_NOSUPPORT},
+ #endif
+ #ifdef CONFIG_EXT4_FS_POSIX_ACL
+-		case Opt_acl:
+-			set_opt(sb, POSIX_ACL);
+-			break;
+-		case Opt_noacl:
+-			clear_opt(sb, POSIX_ACL);
+-			break;
++	{Opt_acl, EXT4_MOUNT_POSIX_ACL, MOPT_SET},
++	{Opt_noacl, EXT4_MOUNT_POSIX_ACL, MOPT_CLEAR},
+ #else
+-		case Opt_acl:
+-		case Opt_noacl:
+-			ext4_msg(sb, KERN_ERR, "(no)acl options not supported");
+-			break;
++	{Opt_acl, 0, MOPT_NOSUPPORT},
++	{Opt_noacl, 0, MOPT_NOSUPPORT},
+ #endif
+-		case Opt_journal_dev:
+-			if (is_remount) {
++	{Opt_nouid32, EXT4_MOUNT_NO_UID32, MOPT_SET},
++	{Opt_debug, EXT4_MOUNT_DEBUG, MOPT_SET},
++	{Opt_quota, EXT4_MOUNT_QUOTA | EXT4_MOUNT_USRQUOTA, MOPT_SET | MOPT_Q},
++	{Opt_usrquota, EXT4_MOUNT_QUOTA | EXT4_MOUNT_USRQUOTA,
++							MOPT_SET | MOPT_Q},
++	{Opt_grpquota, EXT4_MOUNT_QUOTA | EXT4_MOUNT_GRPQUOTA,
++							MOPT_SET | MOPT_Q},
++	{Opt_noquota, (EXT4_MOUNT_QUOTA | EXT4_MOUNT_USRQUOTA |
++		       EXT4_MOUNT_GRPQUOTA), MOPT_CLEAR | MOPT_Q},
++	{Opt_usrjquota, 0, MOPT_Q},
++	{Opt_grpjquota, 0, MOPT_Q},
++	{Opt_offusrjquota, 0, MOPT_Q},
++	{Opt_offgrpjquota, 0, MOPT_Q},
++	{Opt_jqfmt_vfsold, QFMT_VFS_OLD, MOPT_QFMT},
++	{Opt_jqfmt_vfsv0, QFMT_VFS_V0, MOPT_QFMT},
++	{Opt_jqfmt_vfsv1, QFMT_VFS_V1, MOPT_QFMT},
++	{Opt_err, 0, 0}
++};
++
++static int handle_mount_opt(struct super_block *sb, char *opt, int token,
++			    substring_t *args, unsigned long *journal_devnum,
++			    unsigned int *journal_ioprio, int is_remount)
++{
++	struct ext4_sb_info *sbi = EXT4_SB(sb);
++	const struct mount_opts *m;
++	int arg = 0;
++
++	if (args->from && match_int(args, &arg))
++		return -1;
++	switch (token) {
++	case Opt_sb:
++		return 1;	/* handled by get_sb_block() */
++	case Opt_removed:
++		ext4_msg(sb, KERN_WARNING,
++			 "Ignoring removed %s option", opt);
++		return 1;
++	case Opt_resuid:
++		sbi->s_resuid = arg;
++		return 1;
++	case Opt_resgid:
++		sbi->s_resgid = arg;
++		return 1;
++	case Opt_abort:
++		sbi->s_mount_flags |= EXT4_MF_FS_ABORTED;
++		return 1;
++	case Opt_i_version:
++		sb->s_flags |= MS_I_VERSION;
++		return 1;
++	case Opt_journal_dev:
++		if (is_remount) {
++			ext4_msg(sb, KERN_ERR,
++				 "Cannot specify journal on remount");
++			return -1;
++		}
++		*journal_devnum = arg;
++		return 1;
++	case Opt_journal_ioprio:
++		if (arg < 0 || arg > 7)
++			return -1;
++		*journal_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, arg);
++		return 1;
++	}
++
++	for (m = ext4_mount_opts; m->token != Opt_err; m++) {
++		if (token != m->token)
++			continue;
++		if (args->from && (m->flags & MOPT_GTE0) && (arg < 0))
++			return -1;
++		if (m->flags & MOPT_EXPLICIT)
++			set_opt2(sb, EXPLICIT_DELALLOC);
++		if (m->flags & MOPT_CLEAR_ERR)
++			clear_opt(sb, ERRORS_MASK);
++		if (token == Opt_noquota && sb_any_quota_loaded(sb)) {
++			ext4_msg(sb, KERN_ERR, "Cannot change quota "
++				 "options when quota turned on");
++			return -1;
++		}
++
++		if (m->flags & MOPT_NOSUPPORT) {
++			ext4_msg(sb, KERN_ERR, "%s option not supported", opt);
++		} else if (token == Opt_commit) {
++			if (arg == 0)
++				arg = JBD2_DEFAULT_MAX_COMMIT_AGE;
++			sbi->s_commit_interval = HZ * arg;
++		} else if (token == Opt_max_batch_time) {
++			if (arg == 0)
++				arg = EXT4_DEF_MAX_BATCH_TIME;
++			sbi->s_max_batch_time = arg;
++		} else if (token == Opt_min_batch_time) {
++			sbi->s_min_batch_time = arg;
++		} else if (token == Opt_inode_readahead_blks) {
++			if (arg > (1 << 30))
++				return -1;
++			if (arg && !is_power_of_2(arg)) {
+ 				ext4_msg(sb, KERN_ERR,
+-					"Cannot specify journal on remount");
+-				return 0;
++					 "EXT4-fs: inode_readahead_blks"
++					 " must be a power of 2");
++				return -1;
+ 			}
+-			if (match_int(&args[0], &option))
+-				return 0;
+-			*journal_devnum = option;
+-			break;
+-		case Opt_journal_checksum:
+-			set_opt(sb, JOURNAL_CHECKSUM);
+-			break;
+-		case Opt_journal_async_commit:
+-			set_opt(sb, JOURNAL_ASYNC_COMMIT);
+-			set_opt(sb, JOURNAL_CHECKSUM);
+-			break;
+-		case Opt_noload:
+-			set_opt(sb, NOLOAD);
+-			break;
+-		case Opt_commit:
+-			if (match_int(&args[0], &option))
+-				return 0;
+-			if (option < 0)
+-				return 0;
+-			if (option == 0)
+-				option = JBD2_DEFAULT_MAX_COMMIT_AGE;
+-			sbi->s_commit_interval = HZ * option;
+-			break;
+-		case Opt_max_batch_time:
+-			if (match_int(&args[0], &option))
+-				return 0;
+-			if (option < 0)
+-				return 0;
+-			if (option == 0)
+-				option = EXT4_DEF_MAX_BATCH_TIME;
+-			sbi->s_max_batch_time = option;
+-			break;
+-		case Opt_min_batch_time:
+-			if (match_int(&args[0], &option))
+-				return 0;
+-			if (option < 0)
+-				return 0;
+-			sbi->s_min_batch_time = option;
+-			break;
+-		case Opt_data_journal:
+-			data_opt = EXT4_MOUNT_JOURNAL_DATA;
+-			goto datacheck;
+-		case Opt_data_ordered:
+-			data_opt = EXT4_MOUNT_ORDERED_DATA;
+-			goto datacheck;
+-		case Opt_data_writeback:
+-			data_opt = EXT4_MOUNT_WRITEBACK_DATA;
+-		datacheck:
++			sbi->s_inode_readahead_blks = arg;
++		} else if (token == Opt_init_itable) {
++			set_opt(sb, INIT_INODE_TABLE);
++			if (!args->from)
++				arg = EXT4_DEF_LI_WAIT_MULT;
++			sbi->s_li_wait_mult = arg;
++		} else if (token == Opt_stripe) {
++			sbi->s_stripe = arg;
++		} else if (m->flags & MOPT_DATAJ) {
+ 			if (is_remount) {
+ 				if (!sbi->s_journal)
+ 					ext4_msg(sb, KERN_WARNING, "Remounting file system with no journal so ignoring journalled data option");
+-				else if (test_opt(sb, DATA_FLAGS) != data_opt) {
++				else if (test_opt(sb, DATA_FLAGS) !=
++					 m->mount_opt) {
+ 					ext4_msg(sb, KERN_ERR,
+-						"Cannot change data mode on remount");
+-					return 0;
++					 "Cannot change data mode on remount");
++					return -1;
+ 				}
+ 			} else {
+ 				clear_opt(sb, DATA_FLAGS);
+-				sbi->s_mount_opt |= data_opt;
++				sbi->s_mount_opt |= m->mount_opt;
+ 			}
+-			break;
+-		case Opt_data_err_abort:
+-			set_opt(sb, DATA_ERR_ABORT);
+-			break;
+-		case Opt_data_err_ignore:
+-			clear_opt(sb, DATA_ERR_ABORT);
+-			break;
+ #ifdef CONFIG_QUOTA
+-		case Opt_usrjquota:
++		} else if (token == Opt_usrjquota) {
+ 			if (!set_qf_name(sb, USRQUOTA, &args[0]))
+-				return 0;
+-			break;
+-		case Opt_grpjquota:
++				return -1;
++		} else if (token == Opt_grpjquota) {
+ 			if (!set_qf_name(sb, GRPQUOTA, &args[0]))
+-				return 0;
+-			break;
+-		case Opt_offusrjquota:
++				return -1;
++		} else if (token == Opt_offusrjquota) {
+ 			if (!clear_qf_name(sb, USRQUOTA))
+-				return 0;
+-			break;
+-		case Opt_offgrpjquota:
++				return -1;
++		} else if (token == Opt_offgrpjquota) {
+ 			if (!clear_qf_name(sb, GRPQUOTA))
+-				return 0;
+-			break;
+-
+-		case Opt_jqfmt_vfsold:
+-			qfmt = QFMT_VFS_OLD;
+-			goto set_qf_format;
+-		case Opt_jqfmt_vfsv0:
+-			qfmt = QFMT_VFS_V0;
+-			goto set_qf_format;
+-		case Opt_jqfmt_vfsv1:
+-			qfmt = QFMT_VFS_V1;
+-set_qf_format:
++				return -1;
++		} else if (m->flags & MOPT_QFMT) {
+ 			if (sb_any_quota_loaded(sb) &&
+-			    sbi->s_jquota_fmt != qfmt) {
+-				ext4_msg(sb, KERN_ERR, "Cannot change "
+-					"journaled quota options when "
+-					"quota turned on");
+-				return 0;
++			    sbi->s_jquota_fmt != m->mount_opt) {
++				ext4_msg(sb, KERN_ERR, "Cannot "
++					 "change journaled quota options "
++					 "when quota turned on");
++				return -1;
+ 			}
+-			sbi->s_jquota_fmt = qfmt;
+-			break;
+-		case Opt_quota:
+-		case Opt_usrquota:
+-			set_opt(sb, QUOTA);
+-			set_opt(sb, USRQUOTA);
+-			break;
+-		case Opt_grpquota:
+-			set_opt(sb, QUOTA);
+-			set_opt(sb, GRPQUOTA);
+-			break;
+-		case Opt_noquota:
+-			if (sb_any_quota_loaded(sb)) {
+-				ext4_msg(sb, KERN_ERR, "Cannot change quota "
+-					"options when quota turned on");
+-				return 0;
+-			}
+-			clear_opt(sb, QUOTA);
+-			clear_opt(sb, USRQUOTA);
+-			clear_opt(sb, GRPQUOTA);
+-			break;
+-#else
+-		case Opt_quota:
+-		case Opt_usrquota:
+-		case Opt_grpquota:
+-			ext4_msg(sb, KERN_ERR,
+-				"quota options not supported");
+-			break;
+-		case Opt_usrjquota:
+-		case Opt_grpjquota:
+-		case Opt_offusrjquota:
+-		case Opt_offgrpjquota:
+-		case Opt_jqfmt_vfsold:
+-		case Opt_jqfmt_vfsv0:
+-		case Opt_jqfmt_vfsv1:
+-			ext4_msg(sb, KERN_ERR,
+-				"journaled quota options not supported");
+-			break;
+-		case Opt_noquota:
+-			break;
++			sbi->s_jquota_fmt = m->mount_opt;
+ #endif
+-		case Opt_abort:
+-			sbi->s_mount_flags |= EXT4_MF_FS_ABORTED;
+-			break;
+-		case Opt_nobarrier:
+-			clear_opt(sb, BARRIER);
+-			break;
+-		case Opt_barrier:
+-			if (args[0].from) {
+-				if (match_int(&args[0], &option))
+-					return 0;
+-			} else
+-				option = 1;	/* No argument, default to 1 */
+-			if (option)
+-				set_opt(sb, BARRIER);
+-			else
+-				clear_opt(sb, BARRIER);
+-			break;
+-		case Opt_i_version:
+-			sb->s_flags |= MS_I_VERSION;
+-			break;
+-		case Opt_nodelalloc:
+-			clear_opt(sb, DELALLOC);
+-			clear_opt2(sb, EXPLICIT_DELALLOC);
+-			break;
+-		case Opt_mblk_io_submit:
+-			set_opt(sb, MBLK_IO_SUBMIT);
+-			break;
+-		case Opt_nomblk_io_submit:
+-			clear_opt(sb, MBLK_IO_SUBMIT);
+-			break;
+-		case Opt_stripe:
+-			if (match_int(&args[0], &option))
+-				return 0;
+-			if (option < 0)
+-				return 0;
+-			sbi->s_stripe = option;
+-			break;
+-		case Opt_delalloc:
+-			set_opt(sb, DELALLOC);
+-			set_opt2(sb, EXPLICIT_DELALLOC);
+-			break;
+-		case Opt_block_validity:
+-			set_opt(sb, BLOCK_VALIDITY);
+-			break;
+-		case Opt_noblock_validity:
+-			clear_opt(sb, BLOCK_VALIDITY);
+-			break;
+-		case Opt_inode_readahead_blks:
+-			if (match_int(&args[0], &option))
+-				return 0;
+-			if (option < 0 || option > (1 << 30))
+-				return 0;
+-			if (option && !is_power_of_2(option)) {
+-				ext4_msg(sb, KERN_ERR,
+-					 "EXT4-fs: inode_readahead_blks"
+-					 " must be a power of 2");
+-				return 0;
++		} else {
++			if (!args->from)
++				arg = 1;
++			if (m->flags & MOPT_CLEAR)
++				arg = !arg;
++			else if (unlikely(!(m->flags & MOPT_SET))) {
++				ext4_msg(sb, KERN_WARNING,
++					 "buggy handling of option %s", opt);
++				WARN_ON(1);
++				return -1;
+ 			}
+-			sbi->s_inode_readahead_blks = option;
+-			break;
+-		case Opt_journal_ioprio:
+-			if (match_int(&args[0], &option))
+-				return 0;
+-			if (option < 0 || option > 7)
+-				break;
+-			*journal_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE,
+-							    option);
+-			break;
+-		case Opt_noauto_da_alloc:
+-			set_opt(sb, NO_AUTO_DA_ALLOC);
+-			break;
+-		case Opt_auto_da_alloc:
+-			if (args[0].from) {
+-				if (match_int(&args[0], &option))
+-					return 0;
+-			} else
+-				option = 1;	/* No argument, default to 1 */
+-			if (option)
+-				clear_opt(sb, NO_AUTO_DA_ALLOC);
++			if (arg != 0)
++				sbi->s_mount_opt |= m->mount_opt;
+ 			else
+-				set_opt(sb,NO_AUTO_DA_ALLOC);
+-			break;
+-		case Opt_discard:
+-			set_opt(sb, DISCARD);
+-			break;
+-		case Opt_nodiscard:
+-			clear_opt(sb, DISCARD);
+-			break;
+-		case Opt_dioread_nolock:
+-			set_opt(sb, DIOREAD_NOLOCK);
+-			break;
+-		case Opt_dioread_lock:
+-			clear_opt(sb, DIOREAD_NOLOCK);
+-			break;
+-		case Opt_init_itable:
+-			set_opt(sb, INIT_INODE_TABLE);
+-			if (args[0].from) {
+-				if (match_int(&args[0], &option))
+-					return 0;
+-			} else
+-				option = EXT4_DEF_LI_WAIT_MULT;
+-			if (option < 0)
+-				return 0;
+-			sbi->s_li_wait_mult = option;
+-			break;
+-		case Opt_noinit_itable:
+-			clear_opt(sb, INIT_INODE_TABLE);
+-			break;
+-		default:
+-			ext4_msg(sb, KERN_ERR,
+-			       "Unrecognized mount option \"%s\" "
+-			       "or missing value", p);
+-			return 0;
++				sbi->s_mount_opt &= ~m->mount_opt;
+ 		}
++		return 1;
++	}
++	ext4_msg(sb, KERN_ERR, "Unrecognized mount option \"%s\" "
++		 "or missing value", opt);
++	return -1;
++}
++
++static int parse_options(char *options, struct super_block *sb,
++			 unsigned long *journal_devnum,
++			 unsigned int *journal_ioprio,
++			 int is_remount)
++{
++	struct ext4_sb_info *sbi = EXT4_SB(sb);
++	char *p;
++	substring_t args[MAX_OPT_ARGS];
++	int token;
++
++	if (!options)
++		return 1;
++
++	while ((p = strsep(&options, ",")) != NULL) {
++		if (!*p)
++			continue;
++		/*
++		 * Initialize args struct so we know whether arg was
++		 * found; some options take optional arguments.
++		 */
++		args[0].to = args[0].from = 0;
++		token = match_token(p, tokens, args);
++		if (handle_mount_opt(sb, p, token, args, journal_devnum,
++				     journal_ioprio, is_remount) < 0)
++			return 0;
+ 	}
+ #ifdef CONFIG_QUOTA
+ 	if (sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]) {

commit 72578c33c4977941a5094f1d7011c8e1f5c43552
+Author: Theodore Ts'o 
+Date:   Sat Mar 3 18:04:40 2012 -0500
+
+    ext4: unify handling of mount options which have been removed
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 93cca1fa3903..b5f2e6816ec3 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1332,9 +1332,9 @@ static const struct export_operations ext4_export_ops = {
+ enum {
+ 	Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid,
+ 	Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro,
+-	Opt_nouid32, Opt_debug, Opt_oldalloc, Opt_orlov,
++	Opt_nouid32, Opt_debug, Opt_removed,
+ 	Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
+-	Opt_auto_da_alloc, Opt_noauto_da_alloc, Opt_noload, Opt_nobh, Opt_bh,
++	Opt_auto_da_alloc, Opt_noauto_da_alloc, Opt_noload,
+ 	Opt_commit, Opt_min_batch_time, Opt_max_batch_time,
+ 	Opt_journal_dev, Opt_journal_checksum, Opt_journal_async_commit,
+ 	Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
+@@ -1365,16 +1365,16 @@ static const match_table_t tokens = {
+ 	{Opt_err_ro, "errors=remount-ro"},
+ 	{Opt_nouid32, "nouid32"},
+ 	{Opt_debug, "debug"},
+-	{Opt_oldalloc, "oldalloc"},
+-	{Opt_orlov, "orlov"},
++	{Opt_removed, "oldalloc"},
++	{Opt_removed, "orlov"},
+ 	{Opt_user_xattr, "user_xattr"},
+ 	{Opt_nouser_xattr, "nouser_xattr"},
+ 	{Opt_acl, "acl"},
+ 	{Opt_noacl, "noacl"},
+ 	{Opt_noload, "noload"},
+ 	{Opt_noload, "norecovery"},
+-	{Opt_nobh, "nobh"},
+-	{Opt_bh, "bh"},
++	{Opt_removed, "nobh"},
++	{Opt_removed, "bh"},
+ 	{Opt_commit, "commit=%u"},
+ 	{Opt_min_batch_time, "min_batch_time=%u"},
+ 	{Opt_max_batch_time, "max_batch_time=%u"},
+@@ -1582,13 +1582,9 @@ static int parse_options(char *options, struct super_block *sb,
+ 		case Opt_debug:
+ 			set_opt(sb, DEBUG);
+ 			break;
+-		case Opt_oldalloc:
++		case Opt_removed:
+ 			ext4_msg(sb, KERN_WARNING,
+-				 "Ignoring deprecated oldalloc option");
+-			break;
+-		case Opt_orlov:
+-			ext4_msg(sb, KERN_WARNING,
+-				 "Ignoring deprecated orlov option");
++				 "Ignoring deprecated %s option", p);
+ 			break;
+ #ifdef CONFIG_EXT4_FS_XATTR
+ 		case Opt_user_xattr:
+@@ -1781,14 +1777,6 @@ static int parse_options(char *options, struct super_block *sb,
+ 			else
+ 				clear_opt(sb, BARRIER);
+ 			break;
+-		case Opt_nobh:
+-			ext4_msg(sb, KERN_WARNING,
+-				 "Ignoring deprecated nobh option");
+-			break;
+-		case Opt_bh:
+-			ext4_msg(sb, KERN_WARNING,
+-				 "Ignoring deprecated bh option");
+-			break;
+ 		case Opt_i_version:
+ 			sb->s_flags |= MS_I_VERSION;
+ 			break;

commit 39ef17f1b0613b46c6973596525c2bc816d90b5b
+Author: Theodore Ts'o 
+Date:   Sat Mar 3 17:56:23 2012 -0500
+
+    ext4: simplify handling of the errors=* mount options
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index df93dc196514..d70b981b85fb 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -924,6 +924,7 @@ struct ext4_inode_info {
+ #define EXT4_MOUNT_ERRORS_CONT		0x00010	/* Continue on errors */
+ #define EXT4_MOUNT_ERRORS_RO		0x00020	/* Remount fs ro on errors */
+ #define EXT4_MOUNT_ERRORS_PANIC		0x00040	/* Panic on errors */
++#define EXT4_MOUNT_ERRORS_MASK		0x00070
+ #define EXT4_MOUNT_MINIX_DF		0x00080	/* Mimics the Minix statfs */
+ #define EXT4_MOUNT_NOLOAD		0x00100	/* Don't use existing journal*/
+ #define EXT4_MOUNT_DATA_FLAGS		0x00C00	/* Mode for data writes: */
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 6b27bc6eba40..93cca1fa3903 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1565,18 +1565,15 @@ static int parse_options(char *options, struct super_block *sb,
+ 			/* *sb_block = match_int(&args[0]); */
+ 			break;
+ 		case Opt_err_panic:
+-			clear_opt(sb, ERRORS_CONT);
+-			clear_opt(sb, ERRORS_RO);
++			clear_opt(sb, ERRORS_MASK);
+ 			set_opt(sb, ERRORS_PANIC);
+ 			break;
+ 		case Opt_err_ro:
+-			clear_opt(sb, ERRORS_CONT);
+-			clear_opt(sb, ERRORS_PANIC);
++			clear_opt(sb, ERRORS_MASK);
+ 			set_opt(sb, ERRORS_RO);
+ 			break;
+ 		case Opt_err_cont:
+-			clear_opt(sb, ERRORS_RO);
+-			clear_opt(sb, ERRORS_PANIC);
++			clear_opt(sb, ERRORS_MASK);
+ 			set_opt(sb, ERRORS_CONT);
+ 			break;
+ 		case Opt_nouid32:

commit c64db50e76c4bf68c0a84379d7bd70daada531b4
+Author: Theodore Ts'o 
+Date:   Fri Mar 2 12:23:11 2012 -0500
+
+    ext4: remove the I_VERSION mount flag and use the super_block flag instead
+    
+    There's no point to have two bits that are set in parallel; so use the
+    MS_I_VERSION flag that is needed by the VFS anyway, and that way we
+    free up a bit in sbi->s_mount_opts.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 4076746d721d..df93dc196514 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -942,7 +942,6 @@ struct ext4_inode_info {
+ #define EXT4_MOUNT_DIOREAD_NOLOCK	0x400000 /* Enable support for dio read nolocking */
+ #define EXT4_MOUNT_JOURNAL_CHECKSUM	0x800000 /* Journal checksums */
+ #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT	0x1000000 /* Journal Async Commit */
+-#define EXT4_MOUNT_I_VERSION            0x2000000 /* i_version support */
+ #define EXT4_MOUNT_MBLK_IO_SUBMIT	0x4000000 /* multi-block io submits */
+ #define EXT4_MOUNT_DELALLOC		0x8000000 /* Delalloc support */
+ #define EXT4_MOUNT_DATA_ERR_ABORT	0x10000000 /* Abort on file data write */
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index aafc626d64ac..38dc5f3e9dd3 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4322,7 +4322,7 @@ int ext4_mark_iloc_dirty(handle_t *handle,
+ {
+ 	int err = 0;
+ 
+-	if (test_opt(inode->i_sb, I_VERSION))
++	if (IS_I_VERSION(inode))
+ 		inode_inc_iversion(inode);
+ 
+ 	/* the do_update_inode consumes one bh->b_count */
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 7dbad76f92e8..6b27bc6eba40 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1125,7 +1125,7 @@ static int ext4_show_options(struct seq_file *seq, struct dentry *root)
+ 		seq_puts(seq, ",journal_async_commit");
+ 	else if (test_opt(sb, JOURNAL_CHECKSUM))
+ 		seq_puts(seq, ",journal_checksum");
+-	if (test_opt(sb, I_VERSION))
++	if (sb->s_flags & MS_I_VERSION)
+ 		seq_puts(seq, ",i_version");
+ 	if (!test_opt(sb, DELALLOC) &&
+ 	    !(def_mount_opts & EXT4_DEFM_NODELALLOC))
+@@ -1793,7 +1793,6 @@ static int parse_options(char *options, struct super_block *sb,
+ 				 "Ignoring deprecated bh option");
+ 			break;
+ 		case Opt_i_version:
+-			set_opt(sb, I_VERSION);
+ 			sb->s_flags |= MS_I_VERSION;
+ 			break;
+ 		case Opt_nodelalloc:

commit ee4a3fcd1da660147624f13a9dc31d8bf43f5b06
+Author: Theodore Ts'o 
+Date:   Fri Mar 2 12:14:24 2012 -0500
+
+    ext4: remove Opt_ignore
+    
+    This is completely unused so let's just get rid of it.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index ed9a4b595c04..7dbad76f92e8 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1341,7 +1341,7 @@ enum {
+ 	Opt_data_err_abort, Opt_data_err_ignore,
+ 	Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
+ 	Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota,
+-	Opt_noquota, Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err,
++	Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err,
+ 	Opt_usrquota, Opt_grpquota, Opt_i_version,
+ 	Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_mblk_io_submit,
+ 	Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity,
+@@ -1784,8 +1784,6 @@ static int parse_options(char *options, struct super_block *sb,
+ 			else
+ 				clear_opt(sb, BARRIER);
+ 			break;
+-		case Opt_ignore:
+-			break;
+ 		case Opt_nobh:
+ 			ext4_msg(sb, KERN_WARNING,
+ 				 "Ignoring deprecated nobh option");

commit 87f26807e91102f2526d59c0232bf020479c8d0c
+Author: Theodore Ts'o 
+Date:   Fri Mar 2 00:03:21 2012 -0500
+
+    ext4: remove deprecation warnings for minix_df and grpid
+    
+    People complained about removing both of these features, so per
+    Linus's dictate, we won't be able to remove them.  Sigh...
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index deb6eb35ff3d..ed9a4b595c04 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1539,23 +1539,16 @@ static int parse_options(char *options, struct super_block *sb,
+ 		token = match_token(p, tokens, args);
+ 		switch (token) {
+ 		case Opt_bsd_df:
+-			ext4_msg(sb, KERN_WARNING, deprecated_msg, p, "2.6.38");
+ 			clear_opt(sb, MINIX_DF);
+ 			break;
+ 		case Opt_minix_df:
+-			ext4_msg(sb, KERN_WARNING, deprecated_msg, p, "2.6.38");
+ 			set_opt(sb, MINIX_DF);
+-
+ 			break;
+ 		case Opt_grpid:
+-			ext4_msg(sb, KERN_WARNING, deprecated_msg, p, "2.6.38");
+ 			set_opt(sb, GRPID);
+-
+ 			break;
+ 		case Opt_nogrpid:
+-			ext4_msg(sb, KERN_WARNING, deprecated_msg, p, "2.6.38");
+ 			clear_opt(sb, GRPID);
+-
+ 			break;
+ 		case Opt_resuid:
+ 			if (match_int(&args[0], &option))
+@@ -3172,11 +3165,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	set_opt(sb, INIT_INODE_TABLE);
+ 	if (def_mount_opts & EXT4_DEFM_DEBUG)
+ 		set_opt(sb, DEBUG);
+-	if (def_mount_opts & EXT4_DEFM_BSDGROUPS) {
+-		ext4_msg(sb, KERN_WARNING, deprecated_msg, "bsdgroups",
+-			"2.6.38");
++	if (def_mount_opts & EXT4_DEFM_BSDGROUPS)
+ 		set_opt(sb, GRPID);
+-	}
+ 	if (def_mount_opts & EXT4_DEFM_UID16)
+ 		set_opt(sb, NO_UID32);
+ 	/* xattr user namespace & acls are now defaulted on */

commit c5e8f3f3bc4b5e4a73b075ea7128f48c3f215168
+Author: Theodore Ts'o 
+Date:   Mon Feb 20 17:54:06 2012 -0500
+
+    ext4: remove EXT4_MB_{BITMAP,BUDDY} macros
+    
+    The EXT4_MB_BITMAP and EXT4_MB_BUDDY macros obfuscate more than they
+    provide any abstraction.   So remove them.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 8e01214a4421..7e6fab9e889e 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -427,7 +427,7 @@ static void *mb_find_buddy(struct ext4_buddy *e4b, int order, int *max)
+ {
+ 	char *bb;
+ 
+-	BUG_ON(EXT4_MB_BITMAP(e4b) == EXT4_MB_BUDDY(e4b));
++	BUG_ON(e4b->bd_bitmap == e4b->bd_buddy);
+ 	BUG_ON(max == NULL);
+ 
+ 	if (order > e4b->bd_blkbits + 1) {
+@@ -438,10 +438,10 @@ static void *mb_find_buddy(struct ext4_buddy *e4b, int order, int *max)
+ 	/* at order 0 we see each particular block */
+ 	if (order == 0) {
+ 		*max = 1 << (e4b->bd_blkbits + 3);
+-		return EXT4_MB_BITMAP(e4b);
++		return e4b->bd_bitmap;
+ 	}
+ 
+-	bb = EXT4_MB_BUDDY(e4b) + EXT4_SB(e4b->bd_sb)->s_mb_offsets[order];
++	bb = e4b->bd_buddy + EXT4_SB(e4b->bd_sb)->s_mb_offsets[order];
+ 	*max = EXT4_SB(e4b->bd_sb)->s_mb_maxs[order];
+ 
+ 	return bb;
+@@ -590,7 +590,7 @@ static int __mb_check_buddy(struct ext4_buddy *e4b, char *file,
+ 			for (j = 0; j < (1 << order); j++) {
+ 				k = (i * (1 << order)) + j;
+ 				MB_CHECK_ASSERT(
+-					!mb_test_bit(k, EXT4_MB_BITMAP(e4b)));
++					!mb_test_bit(k, e4b->bd_bitmap));
+ 			}
+ 			count++;
+ 		}
+@@ -1203,10 +1203,10 @@ static int mb_find_order_for_block(struct ext4_buddy *e4b, int block)
+ 	int order = 1;
+ 	void *bb;
+ 
+-	BUG_ON(EXT4_MB_BITMAP(e4b) == EXT4_MB_BUDDY(e4b));
++	BUG_ON(e4b->bd_bitmap == e4b->bd_buddy);
+ 	BUG_ON(block >= (1 << (e4b->bd_blkbits + 3)));
+ 
+-	bb = EXT4_MB_BUDDY(e4b);
++	bb = e4b->bd_buddy;
+ 	while (order <= e4b->bd_blkbits + 1) {
+ 		block = block >> 1;
+ 		if (!mb_test_bit(block, bb)) {
+@@ -1276,9 +1276,9 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
+ 
+ 	/* let's maintain fragments counter */
+ 	if (first != 0)
+-		block = !mb_test_bit(first - 1, EXT4_MB_BITMAP(e4b));
++		block = !mb_test_bit(first - 1, e4b->bd_bitmap);
+ 	if (first + count < EXT4_SB(sb)->s_mb_maxs[0])
+-		max = !mb_test_bit(first + count, EXT4_MB_BITMAP(e4b));
++		max = !mb_test_bit(first + count, e4b->bd_bitmap);
+ 	if (block && max)
+ 		e4b->bd_info->bb_fragments--;
+ 	else if (!block && !max)
+@@ -1289,7 +1289,7 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
+ 		block = first++;
+ 		order = 0;
+ 
+-		if (!mb_test_bit(block, EXT4_MB_BITMAP(e4b))) {
++		if (!mb_test_bit(block, e4b->bd_bitmap)) {
+ 			ext4_fsblk_t blocknr;
+ 
+ 			blocknr = ext4_group_first_block_no(sb, e4b->bd_group);
+@@ -1300,7 +1300,7 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
+ 					      "freeing already freed block "
+ 					      "(bit %u)", block);
+ 		}
+-		mb_clear_bit(block, EXT4_MB_BITMAP(e4b));
++		mb_clear_bit(block, e4b->bd_bitmap);
+ 		e4b->bd_info->bb_counters[order]++;
+ 
+ 		/* start of the buddy */
+@@ -1382,7 +1382,7 @@ static int mb_find_extent(struct ext4_buddy *e4b, int order, int block,
+ 			break;
+ 
+ 		next = (block + 1) * (1 << order);
+-		if (mb_test_bit(next, EXT4_MB_BITMAP(e4b)))
++		if (mb_test_bit(next, e4b->bd_bitmap))
+ 			break;
+ 
+ 		order = mb_find_order_for_block(e4b, next);
+@@ -1419,9 +1419,9 @@ static int mb_mark_used(struct ext4_buddy *e4b, struct ext4_free_extent *ex)
+ 
+ 	/* let's maintain fragments counter */
+ 	if (start != 0)
+-		mlen = !mb_test_bit(start - 1, EXT4_MB_BITMAP(e4b));
++		mlen = !mb_test_bit(start - 1, e4b->bd_bitmap);
+ 	if (start + len < EXT4_SB(e4b->bd_sb)->s_mb_maxs[0])
+-		max = !mb_test_bit(start + len, EXT4_MB_BITMAP(e4b));
++		max = !mb_test_bit(start + len, e4b->bd_bitmap);
+ 	if (mlen && max)
+ 		e4b->bd_info->bb_fragments++;
+ 	else if (!mlen && !max)
+@@ -1464,7 +1464,7 @@ static int mb_mark_used(struct ext4_buddy *e4b, struct ext4_free_extent *ex)
+ 	}
+ 	mb_set_largest_free_order(e4b->bd_sb, e4b->bd_info);
+ 
+-	ext4_set_bits(EXT4_MB_BITMAP(e4b), ex->fe_start, len0);
++	ext4_set_bits(e4b->bd_bitmap, ex->fe_start, len0);
+ 	mb_check_buddy(e4b);
+ 
+ 	return ret;
+@@ -1763,7 +1763,7 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
+ 					struct ext4_buddy *e4b)
+ {
+ 	struct super_block *sb = ac->ac_sb;
+-	void *bitmap = EXT4_MB_BITMAP(e4b);
++	void *bitmap = e4b->bd_bitmap;
+ 	struct ext4_free_extent ex;
+ 	int i;
+ 	int free;
+@@ -1823,7 +1823,7 @@ void ext4_mb_scan_aligned(struct ext4_allocation_context *ac,
+ {
+ 	struct super_block *sb = ac->ac_sb;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-	void *bitmap = EXT4_MB_BITMAP(e4b);
++	void *bitmap = e4b->bd_bitmap;
+ 	struct ext4_free_extent ex;
+ 	ext4_fsblk_t first_group_block;
+ 	ext4_fsblk_t a;
+diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
+index 7128f46d8501..c070618c21ce 100644
+--- a/fs/ext4/mballoc.h
++++ b/fs/ext4/mballoc.h
+@@ -212,8 +212,6 @@ struct ext4_buddy {
+ 	__u16 bd_blkbits;
+ 	ext4_group_t bd_group;
+ };
+-#define EXT4_MB_BITMAP(e4b)	((e4b)->bd_bitmap)
+-#define EXT4_MB_BUDDY(e4b)	((e4b)->bd_buddy)
+ 
+ static inline ext4_fsblk_t ext4_grp_offs_to_block(struct super_block *sb,
+ 					struct ext4_free_extent *fex)

commit 856cbcf9a971b43a83e78ac708ed6459ab1d0c89
+Author: Theodore Ts'o 
+Date:   Mon Feb 20 17:53:01 2012 -0500
+
+    ext4: fix INCOMPAT feature codepoint reservation for INLINEDATA
+    
+    In commit 9b90e5e028 I incorrectly reserved the wrong bit for
+    EXT4_FEATURE_INCOMPAT_INLINEDATA per the discussion on the linux-ext4
+    list on December 7, 2011.  The codepoint 0x2000 should be used for
+    EXT4_FEATURE_INCOMPAT_USE_META_CSUM, so INLINEDATA will be assigned
+    the value 0x8000.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 315f01be73e6..c2314dcbe4fb 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1420,8 +1420,9 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei)
+ #define EXT4_FEATURE_INCOMPAT_FLEX_BG		0x0200
+ #define EXT4_FEATURE_INCOMPAT_EA_INODE		0x0400 /* EA in inode */
+ #define EXT4_FEATURE_INCOMPAT_DIRDATA		0x1000 /* data in dirent */
+-#define EXT4_FEATURE_INCOMPAT_INLINEDATA	0x2000 /* data in inode */
++#define EXT4_FEATURE_INCOMPAT_BG_USE_META_CSUM	0x2000 /* use crc32c for bg */
+ #define EXT4_FEATURE_INCOMPAT_LARGEDIR		0x4000 /* >2GB or 3-lvl htree */
++#define EXT4_FEATURE_INCOMPAT_INLINEDATA	0x8000 /* data in inode */
+ 
+ #define EXT2_FEATURE_COMPAT_SUPP	EXT4_FEATURE_COMPAT_EXT_ATTR
+ #define EXT2_FEATURE_INCOMPAT_SUPP	(EXT4_FEATURE_INCOMPAT_FILETYPE| \

commit 813e57276fd909f7d5a816ef7ca706fca491ee61
+Author: Theodore Ts'o 
+Date:   Mon Feb 20 17:52:46 2012 -0500
+
+    ext4: fix race when setting bitmap_uptodate flag
+    
+    In ext4_read_{inode,block}_bitmap() we were setting bitmap_uptodate()
+    before submitting the buffer for read.  The is bad, since we check
+    bitmap_uptodate() without locking the buffer, and so if another
+    process is racing with us, it's possible that they will think the
+    bitmap is uptodate even though the read has not completed yet,
+    resulting in inodes and blocks potentially getting allocated more than
+    once if we get really unlucky.
+    
+    Addresses-Google-Bug: 2828254
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index f9e2cd8cf711..a2cff2b9d5b5 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -336,10 +336,10 @@ static int ext4_valid_block_bitmap(struct super_block *sb,
+  * Return buffer_head on success or NULL in case of failure.
+  */
+ struct buffer_head *
+-ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
++ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group)
+ {
+ 	struct ext4_group_desc *desc;
+-	struct buffer_head *bh = NULL;
++	struct buffer_head *bh;
+ 	ext4_fsblk_t bitmap_blk;
+ 
+ 	desc = ext4_get_group_desc(sb, block_group, NULL);
+@@ -348,9 +348,9 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
+ 	bitmap_blk = ext4_block_bitmap(sb, desc);
+ 	bh = sb_getblk(sb, bitmap_blk);
+ 	if (unlikely(!bh)) {
+-		ext4_error(sb, "Cannot read block bitmap - "
+-			    "block_group = %u, block_bitmap = %llu",
+-			    block_group, bitmap_blk);
++		ext4_error(sb, "Cannot get buffer for block bitmap - "
++			   "block_group = %u, block_bitmap = %llu",
++			   block_group, bitmap_blk);
+ 		return NULL;
+ 	}
+ 
+@@ -382,25 +382,50 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
+ 		return bh;
+ 	}
+ 	/*
+-	 * submit the buffer_head for read. We can
+-	 * safely mark the bitmap as uptodate now.
+-	 * We do it here so the bitmap uptodate bit
+-	 * get set with buffer lock held.
++	 * submit the buffer_head for reading
+ 	 */
++	set_buffer_new(bh);
+ 	trace_ext4_read_block_bitmap_load(sb, block_group);
+-	set_bitmap_uptodate(bh);
+-	if (bh_submit_read(bh) < 0) {
+-		put_bh(bh);
++	bh->b_end_io = ext4_end_bitmap_read;
++	get_bh(bh);
++	submit_bh(READ, bh);
++	return bh;
++}
++
++/* Returns 0 on success, 1 on error */
++int ext4_wait_block_bitmap(struct super_block *sb, ext4_group_t block_group,
++			   struct buffer_head *bh)
++{
++	struct ext4_group_desc *desc;
++
++	if (!buffer_new(bh))
++		return 0;
++	desc = ext4_get_group_desc(sb, block_group, NULL);
++	if (!desc)
++		return 1;
++	wait_on_buffer(bh);
++	if (!buffer_uptodate(bh)) {
+ 		ext4_error(sb, "Cannot read block bitmap - "
+-			    "block_group = %u, block_bitmap = %llu",
+-			    block_group, bitmap_blk);
+-		return NULL;
++			   "block_group = %u, block_bitmap = %llu",
++			   block_group, bh->b_blocknr);
++		return 1;
+ 	}
++	clear_buffer_new(bh);
++	/* Panic or remount fs read-only if block bitmap is invalid */
+ 	ext4_valid_block_bitmap(sb, desc, block_group, bh);
+-	/*
+-	 * file system mounted not to panic on error,
+-	 * continue with corrupt bitmap
+-	 */
++	return 0;
++}
++
++struct buffer_head *
++ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
++{
++	struct buffer_head *bh;
++
++	bh = ext4_read_block_bitmap_nowait(sb, block_group);
++	if (ext4_wait_block_bitmap(sb, block_group, bh)) {
++		put_bh(bh);
++		return NULL;
++	}
+ 	return bh;
+ }
+ 
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 513004fc3d84..315f01be73e6 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1794,8 +1794,14 @@ extern struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
+ 						    ext4_group_t block_group,
+ 						    struct buffer_head ** bh);
+ extern int ext4_should_retry_alloc(struct super_block *sb, int *retries);
+-struct buffer_head *ext4_read_block_bitmap(struct super_block *sb,
+-				      ext4_group_t block_group);
++
++extern struct buffer_head *ext4_read_block_bitmap_nowait(struct super_block *sb,
++						ext4_group_t block_group);
++extern int ext4_wait_block_bitmap(struct super_block *sb,
++				  ext4_group_t block_group,
++				  struct buffer_head *bh);
++extern struct buffer_head *ext4_read_block_bitmap(struct super_block *sb,
++						  ext4_group_t block_group);
+ extern void ext4_init_block_bitmap(struct super_block *sb,
+ 				   struct buffer_head *bh,
+ 				   ext4_group_t group,
+@@ -1841,6 +1847,7 @@ extern void ext4_check_inodes_bitmap(struct super_block *);
+ extern void ext4_mark_bitmap_end(int start_bit, int end_bit, char *bitmap);
+ extern int ext4_init_inode_table(struct super_block *sb,
+ 				 ext4_group_t group, int barrier);
++extern void ext4_end_bitmap_read(struct buffer_head *bh, int uptodate);
+ 
+ /* mballoc.c */
+ extern long ext4_mb_stats;
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 84e6e9a3986b..b2685992fb2d 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -92,6 +92,16 @@ static unsigned ext4_init_inode_bitmap(struct super_block *sb,
+ 	return EXT4_INODES_PER_GROUP(sb);
+ }
+ 
++void ext4_end_bitmap_read(struct buffer_head *bh, int uptodate)
++{
++	if (uptodate) {
++		set_buffer_uptodate(bh);
++		set_bitmap_uptodate(bh);
++	}
++	unlock_buffer(bh);
++	put_bh(bh);
++}
++
+ /*
+  * Read the inode allocation bitmap for a given block_group, reading
+  * into the specified slot in the superblock's bitmap cache.
+@@ -147,18 +157,18 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
+ 		return bh;
+ 	}
+ 	/*
+-	 * submit the buffer_head for read. We can
+-	 * safely mark the bitmap as uptodate now.
+-	 * We do it here so the bitmap uptodate bit
+-	 * get set with buffer lock held.
++	 * submit the buffer_head for reading
+ 	 */
+ 	trace_ext4_load_inode_bitmap(sb, block_group);
+-	set_bitmap_uptodate(bh);
+-	if (bh_submit_read(bh) < 0) {
++	bh->b_end_io = ext4_end_bitmap_read;
++	get_bh(bh);
++	submit_bh(READ, bh);
++	wait_on_buffer(bh);
++	if (!buffer_uptodate(bh)) {
+ 		put_bh(bh);
+ 		ext4_error(sb, "Cannot read inode bitmap - "
+-			    "block_group = %u, inode_bitmap = %llu",
+-			    block_group, bitmap_blk);
++			   "block_group = %u, inode_bitmap = %llu",
++			   block_group, bitmap_blk);
+ 		return NULL;
+ 	}
+ 	return bh;
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index cb990b21c698..545fa0256606 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -782,7 +782,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
+ 	int groups_per_page;
+ 	int err = 0;
+ 	int i;
+-	ext4_group_t first_group;
++	ext4_group_t first_group, group;
+ 	int first_block;
+ 	struct super_block *sb;
+ 	struct buffer_head *bhs;
+@@ -806,24 +806,23 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
+ 
+ 	/* allocate buffer_heads to read bitmaps */
+ 	if (groups_per_page > 1) {
+-		err = -ENOMEM;
+ 		i = sizeof(struct buffer_head *) * groups_per_page;
+ 		bh = kzalloc(i, GFP_NOFS);
+-		if (bh == NULL)
++		if (bh == NULL) {
++			err = -ENOMEM;
+ 			goto out;
++		}
+ 	} else
+ 		bh = &bhs;
+ 
+ 	first_group = page->index * blocks_per_page / 2;
+ 
+ 	/* read all groups the page covers into the cache */
+-	for (i = 0; i < groups_per_page; i++) {
+-		struct ext4_group_desc *desc;
+-
+-		if (first_group + i >= ngroups)
++	for (i = 0, group = first_group; i < groups_per_page; i++, group++) {
++		if (group >= ngroups)
+ 			break;
+ 
+-		grinfo = ext4_get_group_info(sb, first_group + i);
++		grinfo = ext4_get_group_info(sb, group);
+ 		/*
+ 		 * If page is uptodate then we came here after online resize
+ 		 * which added some new uninitialized group info structs, so
+@@ -834,69 +833,21 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
+ 			bh[i] = NULL;
+ 			continue;
+ 		}
+-
+-		err = -EIO;
+-		desc = ext4_get_group_desc(sb, first_group + i, NULL);
+-		if (desc == NULL)
+-			goto out;
+-
+-		err = -ENOMEM;
+-		bh[i] = sb_getblk(sb, ext4_block_bitmap(sb, desc));
+-		if (bh[i] == NULL)
++		if (!(bh[i] = ext4_read_block_bitmap_nowait(sb, group))) {
++			err = -ENOMEM;
+ 			goto out;
+-
+-		if (bitmap_uptodate(bh[i]))
+-			continue;
+-
+-		lock_buffer(bh[i]);
+-		if (bitmap_uptodate(bh[i])) {
+-			unlock_buffer(bh[i]);
+-			continue;
+ 		}
+-		ext4_lock_group(sb, first_group + i);
+-		if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
+-			ext4_init_block_bitmap(sb, bh[i],
+-						first_group + i, desc);
+-			set_bitmap_uptodate(bh[i]);
+-			set_buffer_uptodate(bh[i]);
+-			ext4_unlock_group(sb, first_group + i);
+-			unlock_buffer(bh[i]);
+-			continue;
+-		}
+-		ext4_unlock_group(sb, first_group + i);
+-		if (buffer_uptodate(bh[i])) {
+-			/*
+-			 * if not uninit if bh is uptodate,
+-			 * bitmap is also uptodate
+-			 */
+-			set_bitmap_uptodate(bh[i]);
+-			unlock_buffer(bh[i]);
+-			continue;
+-		}
+-		get_bh(bh[i]);
+-		/*
+-		 * submit the buffer_head for read. We can
+-		 * safely mark the bitmap as uptodate now.
+-		 * We do it here so the bitmap uptodate bit
+-		 * get set with buffer lock held.
+-		 */
+-		set_bitmap_uptodate(bh[i]);
+-		bh[i]->b_end_io = end_buffer_read_sync;
+-		submit_bh(READ, bh[i]);
+-		mb_debug(1, "read bitmap for group %u\n", first_group + i);
++		mb_debug(1, "read bitmap for group %u\n", group);
+ 	}
+ 
+ 	/* wait for I/O completion */
+-	for (i = 0; i < groups_per_page; i++)
+-		if (bh[i])
+-			wait_on_buffer(bh[i]);
+-
+-	err = -EIO;
+-	for (i = 0; i < groups_per_page; i++)
+-		if (bh[i] && !buffer_uptodate(bh[i]))
++	for (i = 0, group = first_group; i < groups_per_page; i++, group++) {
++		if (bh[i] && ext4_wait_block_bitmap(sb, group, bh[i])) {
++			err = -EIO;
+ 			goto out;
++		}
++	}
+ 
+-	err = 0;
+ 	first_block = page->index * blocks_per_page;
+ 	for (i = 0; i < blocks_per_page; i++) {
+ 		int group;

commit 119c0d4460b001e44b41dcf73dc6ee794b98bd31
+Author: Theodore Ts'o 
+Date:   Mon Feb 6 20:12:03 2012 -0500
+
+    ext4: fold ext4_claim_inode into ext4_new_inode
+    
+    The function ext4_claim_inode() is only called by one function,
+    ext4_new_inode(), and by folding the functionality into
+    ext4_new_inode(), we can remove almost 50 lines of code, and put all
+    of the logic of allocating a new inode into a single place.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 25d8c9781ad9..84e6e9a3986b 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -592,94 +592,6 @@ static int find_group_other(struct super_block *sb, struct inode *parent,
+ 	return -1;
+ }
+ 
+-/*
+- * claim the inode from the inode bitmap. If the group
+- * is uninit we need to take the groups's ext4_group_lock
+- * and clear the uninit flag. The inode bitmap update
+- * and group desc uninit flag clear should be done
+- * after holding ext4_group_lock so that ext4_read_inode_bitmap
+- * doesn't race with the ext4_claim_inode
+- */
+-static int ext4_claim_inode(struct super_block *sb,
+-			struct buffer_head *inode_bitmap_bh,
+-			unsigned long ino, ext4_group_t group, umode_t mode)
+-{
+-	int free = 0, retval = 0, count;
+-	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-	struct ext4_group_info *grp = ext4_get_group_info(sb, group);
+-	struct ext4_group_desc *gdp = ext4_get_group_desc(sb, group, NULL);
+-
+-	/*
+-	 * We have to be sure that new inode allocation does not race with
+-	 * inode table initialization, because otherwise we may end up
+-	 * allocating and writing new inode right before sb_issue_zeroout
+-	 * takes place and overwriting our new inode with zeroes. So we
+-	 * take alloc_sem to prevent it.
+-	 */
+-	down_read(&grp->alloc_sem);
+-	ext4_lock_group(sb, group);
+-	if (ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data)) {
+-		/* not a free inode */
+-		retval = 1;
+-		goto err_ret;
+-	}
+-	ino++;
+-	if ((group == 0 && ino < EXT4_FIRST_INO(sb)) ||
+-			ino > EXT4_INODES_PER_GROUP(sb)) {
+-		ext4_unlock_group(sb, group);
+-		up_read(&grp->alloc_sem);
+-		ext4_error(sb, "reserved inode or inode > inodes count - "
+-			   "block_group = %u, inode=%lu", group,
+-			   ino + group * EXT4_INODES_PER_GROUP(sb));
+-		return 1;
+-	}
+-	/* If we didn't allocate from within the initialized part of the inode
+-	 * table then we need to initialize up to this inode. */
+-	if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
+-
+-		if (gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) {
+-			gdp->bg_flags &= cpu_to_le16(~EXT4_BG_INODE_UNINIT);
+-			/* When marking the block group with
+-			 * ~EXT4_BG_INODE_UNINIT we don't want to depend
+-			 * on the value of bg_itable_unused even though
+-			 * mke2fs could have initialized the same for us.
+-			 * Instead we calculated the value below
+-			 */
+-
+-			free = 0;
+-		} else {
+-			free = EXT4_INODES_PER_GROUP(sb) -
+-				ext4_itable_unused_count(sb, gdp);
+-		}
+-
+-		/*
+-		 * Check the relative inode number against the last used
+-		 * relative inode number in this group. if it is greater
+-		 * we need to  update the bg_itable_unused count
+-		 *
+-		 */
+-		if (ino > free)
+-			ext4_itable_unused_set(sb, gdp,
+-					(EXT4_INODES_PER_GROUP(sb) - ino));
+-	}
+-	count = ext4_free_inodes_count(sb, gdp) - 1;
+-	ext4_free_inodes_set(sb, gdp, count);
+-	if (S_ISDIR(mode)) {
+-		count = ext4_used_dirs_count(sb, gdp) + 1;
+-		ext4_used_dirs_set(sb, gdp, count);
+-		if (sbi->s_log_groups_per_flex) {
+-			ext4_group_t f = ext4_flex_group(sbi, group);
+-
+-			atomic_inc(&sbi->s_flex_groups[f].used_dirs);
+-		}
+-	}
+-	gdp->bg_checksum = ext4_group_desc_csum(sbi, group, gdp);
+-err_ret:
+-	ext4_unlock_group(sb, group);
+-	up_read(&grp->alloc_sem);
+-	return retval;
+-}
+-
+ /*
+  * There are two policies for allocating an inode.  If the new inode is
+  * a directory, then a forward search is made for a block group with both
+@@ -741,6 +653,11 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode,
+ 	if (ret2 == -1)
+ 		goto out;
+ 
++	/*
++	 * Normally we will only go through one pass of this loop,
++	 * unless we get unlucky and it turns out the group we selected
++	 * had its last inode grabbed by someone else.
++	 */
+ 	for (i = 0; i < ngroups; i++, ino = 0) {
+ 		err = -EIO;
+ 
+@@ -757,51 +674,24 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode,
+ 		ino = ext4_find_next_zero_bit((unsigned long *)
+ 					      inode_bitmap_bh->b_data,
+ 					      EXT4_INODES_PER_GROUP(sb), ino);
+-
+-		if (ino < EXT4_INODES_PER_GROUP(sb)) {
+-
+-			BUFFER_TRACE(inode_bitmap_bh, "get_write_access");
+-			err = ext4_journal_get_write_access(handle,
+-							    inode_bitmap_bh);
+-			if (err)
+-				goto fail;
+-
+-			BUFFER_TRACE(group_desc_bh, "get_write_access");
+-			err = ext4_journal_get_write_access(handle,
+-								group_desc_bh);
+-			if (err)
+-				goto fail;
+-			if (!ext4_claim_inode(sb, inode_bitmap_bh,
+-						ino, group, mode)) {
+-				/* we won it */
+-				BUFFER_TRACE(inode_bitmap_bh,
+-					"call ext4_handle_dirty_metadata");
+-				err = ext4_handle_dirty_metadata(handle,
+-								 NULL,
+-							inode_bitmap_bh);
+-				if (err)
+-					goto fail;
+-				/* zero bit is inode number 1*/
+-				ino++;
+-				goto got;
+-			}
+-			/* we lost it */
+-			ext4_handle_release_buffer(handle, inode_bitmap_bh);
+-			ext4_handle_release_buffer(handle, group_desc_bh);
+-
+-			if (++ino < EXT4_INODES_PER_GROUP(sb))
+-				goto repeat_in_this_group;
++		if (ino >= EXT4_INODES_PER_GROUP(sb)) {
++			if (++group == ngroups)
++				group = 0;
++			continue;
+ 		}
+-
+-		/*
+-		 * This case is possible in concurrent environment.  It is very
+-		 * rare.  We cannot repeat the find_group_xxx() call because
+-		 * that will simply return the same blockgroup, because the
+-		 * group descriptor metadata has not yet been updated.
+-		 * So we just go onto the next blockgroup.
+-		 */
+-		if (++group == ngroups)
+-			group = 0;
++		if (group == 0 && (ino+1) < EXT4_FIRST_INO(sb)) {
++			ext4_error(sb, "reserved inode found cleared - "
++				   "inode=%lu", ino + 1);
++			continue;
++		}
++		ext4_lock_group(sb, group);
++		ret2 = ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data);
++		ext4_unlock_group(sb, group);
++		ino++;		/* the inode bitmap is zero-based */
++		if (!ret2)
++			goto got; /* we grabbed the inode! */
++		if (ino < EXT4_INODES_PER_GROUP(sb))
++			goto repeat_in_this_group;
+ 	}
+ 	err = -ENOSPC;
+ 	goto out;
+@@ -838,6 +728,59 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode,
+ 		if (err)
+ 			goto fail;
+ 	}
++
++	BUFFER_TRACE(inode_bitmap_bh, "get_write_access");
++	err = ext4_journal_get_write_access(handle, inode_bitmap_bh);
++	if (err)
++		goto fail;
++
++	BUFFER_TRACE(group_desc_bh, "get_write_access");
++	err = ext4_journal_get_write_access(handle, group_desc_bh);
++	if (err)
++		goto fail;
++
++	/* Update the relevant bg descriptor fields */
++	if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
++		int free;
++		struct ext4_group_info *grp = ext4_get_group_info(sb, group);
++
++		down_read(&grp->alloc_sem); /* protect vs itable lazyinit */
++		ext4_lock_group(sb, group); /* while we modify the bg desc */
++		free = EXT4_INODES_PER_GROUP(sb) -
++			ext4_itable_unused_count(sb, gdp);
++		if (gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) {
++			gdp->bg_flags &= cpu_to_le16(~EXT4_BG_INODE_UNINIT);
++			free = 0;
++		}
++		/*
++		 * Check the relative inode number against the last used
++		 * relative inode number in this group. if it is greater
++		 * we need to update the bg_itable_unused count
++		 */
++		if (ino > free)
++			ext4_itable_unused_set(sb, gdp,
++					(EXT4_INODES_PER_GROUP(sb) - ino));
++		up_read(&grp->alloc_sem);
++	}
++	ext4_free_inodes_set(sb, gdp, ext4_free_inodes_count(sb, gdp) - 1);
++	if (S_ISDIR(mode)) {
++		ext4_used_dirs_set(sb, gdp, ext4_used_dirs_count(sb, gdp) + 1);
++		if (sbi->s_log_groups_per_flex) {
++			ext4_group_t f = ext4_flex_group(sbi, group);
++
++			atomic_inc(&sbi->s_flex_groups[f].used_dirs);
++		}
++	}
++	if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
++		gdp->bg_checksum = ext4_group_desc_csum(sbi, group, gdp);
++		ext4_unlock_group(sb, group);
++	}
++
++	BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata");
++	err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh);
++	if (err)
++		goto fail;
++
+ 	BUFFER_TRACE(group_desc_bh, "call ext4_handle_dirty_metadata");
+ 	err = ext4_handle_dirty_metadata(handle, NULL, group_desc_bh);
+ 	if (err)
+@@ -1101,7 +1044,7 @@ unsigned long ext4_count_dirs(struct super_block * sb)
+  * where it is called from on active part of filesystem is ext4lazyinit
+  * thread, so we do not need any special locks, however we have to prevent
+  * inode allocation from the current group, so we take alloc_sem lock, to
+- * block ext4_claim_inode until we are finished.
++ * block ext4_new_inode() until we are finished.
+  */
+ int ext4_init_inode_table(struct super_block *sb, ext4_group_t group,
+ 				 int barrier)

commit 3e88bdff1c65145f7ba297ccec69c774afe4c785
+Author: Theodore Ts'o 
+Date:   Thu Dec 22 16:28:01 2011 -0500
+
+    random: Use arch-specific RNG to initialize the entropy store
+    
+    If there is an architecture-specific random number generator (such as
+    RDRAND for Intel architectures), use it to initialize /dev/random's
+    entropy stores.  Even in the worst case, if RDRAND is something like
+    AES(NSA_KEY, counter++), it won't hurt, and it will definitely help
+    against any other adversaries.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Link: http://lkml.kernel.org/r/1324589281-31931-1-git-send-email-tytso@mit.edu
+    Signed-off-by: H. Peter Anvin 
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 85da8740586b..30794779c523 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -965,6 +965,7 @@ EXPORT_SYMBOL(get_random_bytes);
+  */
+ static void init_std_data(struct entropy_store *r)
+ {
++	int i;
+ 	ktime_t now;
+ 	unsigned long flags;
+ 
+@@ -974,6 +975,11 @@ static void init_std_data(struct entropy_store *r)
+ 
+ 	now = ktime_get_real();
+ 	mix_pool_bytes(r, &now, sizeof(now));
++	for (i = r->poolinfo->poolwords; i; i--) {
++		if (!arch_get_random_long(&flags))
++			break;
++		mix_pool_bytes(r, &flags, sizeof(flags));
++	}
+ 	mix_pool_bytes(r, utsname(), sizeof(*(utsname())));
+ }
+ 

commit ff9cb1c4eead5e4c292e75cd3170a82d66944101
+Merge: e4e11180dfa5 d50f2ab6f050
+Author: Theodore Ts'o 
+Date:   Tue Jan 10 11:54:07 2012 -0500
+
+    Merge branch 'for_linus' into for_linus_merged
+    
+    Conflicts:
+            fs/ext4/ioctl.c
+
+diff --cc fs/ext4/ioctl.c
+index e87a932b073b,b81a5f1b6976..6eee25591b81
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@@ -193,12 -193,13 +197,13 @@@ setversion_out
+  			       EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {
+  			ext4_msg(sb, KERN_ERR,
+  				 "Online resizing not supported with bigalloc");
+- 			return -EOPNOTSUPP;
++ 			err = -EOPNOTSUPP;
++ 			goto group_extend_out;
+  		}
+  
+ -		err = mnt_want_write(filp->f_path.mnt);
+ +		err = mnt_want_write_file(filp);
+  		if (err)
+- 			return err;
++ 			goto group_extend_out;
+  
+  		err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count);
+  		if (EXT4_SB(sb)->s_journal) {
+@@@ -208,9 -209,10 +213,9 @@@
+  		}
+  		if (err == 0)
+  			err = err2;
+ -
+ -		mnt_drop_write(filp->f_path.mnt);
+ +		mnt_drop_write_file(filp);
++ group_extend_out:
+  		ext4_resize_end(sb);
+- 
+  		return err;
+  	}
+  
+@@@ -250,9 -252,7 +255,8 @@@
+  
+  		err = ext4_move_extents(filp, donor_filp, me.orig_start,
+  					me.donor_start, me.len, &me.moved_len);
+ +		mnt_drop_write_file(filp);
+- 		if (me.moved_len > 0)
+- 			file_remove_suid(donor_filp);
++ 		mnt_drop_write(filp->f_path.mnt);
+  
+  		if (copy_to_user((struct move_extent __user *)arg,
+  				 &me, sizeof(me)))
+@@@ -278,12 -280,13 +284,13 @@@ mext_out
+  			       EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {
+  			ext4_msg(sb, KERN_ERR,
+  				 "Online resizing not supported with bigalloc");
+- 			return -EOPNOTSUPP;
++ 			err = -EOPNOTSUPP;
++ 			goto group_add_out;
+  		}
+  
+ -		err = mnt_want_write(filp->f_path.mnt);
+ +		err = mnt_want_write_file(filp);
+  		if (err)
+- 			return err;
++ 			goto group_add_out;
+  
+  		err = ext4_group_add(sb, &input);
+  		if (EXT4_SB(sb)->s_journal) {
+@@@ -293,9 -296,10 +300,9 @@@
+  		}
+  		if (err == 0)
+  			err = err2;
+ -
+ -		mnt_drop_write(filp->f_path.mnt);
+ +		mnt_drop_write_file(filp);
++ group_add_out:
+  		ext4_resize_end(sb);
+- 
+  		return err;
+  	}
+  

commit 9b90e5e02896406a6da28a376568003d14c06770
+Author: Theodore Ts'o 
+Date:   Wed Jan 4 22:01:53 2012 -0500
+
+    ext4: reserve new feature flag codepoints
+    
+    Reserve the ext4 features flags EXT4_FEATURE_RO_COMPAT_METADATA_CSUM,
+    EXT4_FEATURE_INCOMPAT_INLINEDATA, and EXT4_FEATURE_INCOMPAT_LARGEDIR.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 4bc0e82a9054..13d15149c85c 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1407,6 +1407,7 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei)
+ #define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE	0x0040
+ #define EXT4_FEATURE_RO_COMPAT_QUOTA		0x0100
+ #define EXT4_FEATURE_RO_COMPAT_BIGALLOC		0x0200
++#define EXT4_FEATURE_RO_COMPAT_METADATA_CSUM	0x0400
+ 
+ #define EXT4_FEATURE_INCOMPAT_COMPRESSION	0x0001
+ #define EXT4_FEATURE_INCOMPAT_FILETYPE		0x0002
+@@ -1419,6 +1420,8 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei)
+ #define EXT4_FEATURE_INCOMPAT_FLEX_BG		0x0200
+ #define EXT4_FEATURE_INCOMPAT_EA_INODE		0x0400 /* EA in inode */
+ #define EXT4_FEATURE_INCOMPAT_DIRDATA		0x1000 /* data in dirent */
++#define EXT4_FEATURE_INCOMPAT_INLINEDATA	0x2000 /* data in inode */
++#define EXT4_FEATURE_INCOMPAT_LARGEDIR		0x4000 /* >2GB or 3-lvl htree */
+ 
+ #define EXT2_FEATURE_COMPAT_SUPP	EXT4_FEATURE_COMPAT_EXT_ATTR
+ #define EXT2_FEATURE_INCOMPAT_SUPP	(EXT4_FEATURE_INCOMPAT_FILETYPE| \

commit 14c83c9fddf2e75bdd0c20f1072f35260e356484
+Author: Theodore Ts'o 
+Date:   Wed Dec 28 20:25:13 2011 -0500
+
+    ext4: avoid counting the number of free inodes twice in find_group_orlov()
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 8fb6844f9734..cdafc05d79c9 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -358,7 +358,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	ext4_group_t real_ngroups = ext4_get_groups_count(sb);
+ 	int inodes_per_group = EXT4_INODES_PER_GROUP(sb);
+-	unsigned int freei, avefreei;
++	unsigned int freei, avefreei, grp_free;
+ 	ext4_fsblk_t freeb, avefreec;
+ 	unsigned int ndirs;
+ 	int max_dirs, min_inodes;
+@@ -477,8 +477,8 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
+ 	for (i = 0; i < ngroups; i++) {
+ 		grp = (parent_group + i) % ngroups;
+ 		desc = ext4_get_group_desc(sb, grp, NULL);
+-		if (desc && ext4_free_inodes_count(sb, desc) &&
+-		    ext4_free_inodes_count(sb, desc) >= avefreei) {
++		grp_free = ext4_free_inodes_count(sb, desc);
++		if (desc && grp_free && grp_free >= avefreei) {
+ 			*group = grp;
+ 			return 0;
+ 		}

commit 22cdfca5641817060dd724a9c30442f5c0675fcd
+Author: Theodore Ts'o 
+Date:   Wed Dec 21 14:14:31 2011 -0500
+
+    ext4: remove unneeded file_remove_suid() from ext4_ioctl()
+    
+    In the code to support EXT4_IOC_MOVE_EXT, ext4_ioctl calls
+    file_remove_suid() after the call to ext4_move_extents() if any
+    extents has been moved.  There are at least three things wrong with
+    this.  First, file_remove_suid() should be called with i_mutex down,
+    which is not here.  Second, it should be called before the donor file
+    has been modified, to avoid a potential race condition.  Third, and
+    most importantly, it's pointless, because ext4_file_extents() already
+    checks if the donor file has the setuid or setgid bit set, and will
+    return an error in that case.  So the first two objections don't
+    really matter, since file_remove_suid() will never need to modify the
+    inode in any case.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index a56796814d6a..ff1aab7cd6e8 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -247,8 +247,6 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 		err = ext4_move_extents(filp, donor_filp, me.orig_start,
+ 					me.donor_start, me.len, &me.moved_len);
+ 		mnt_drop_write(filp->f_path.mnt);
+-		if (me.moved_len > 0)
+-			file_remove_suid(donor_filp);
+ 
+ 		if (copy_to_user((struct move_extent __user *)arg,
+ 				 &me, sizeof(me)))

commit fc6cb1cda5db7b2d24bf32890826214b857c728e
+Author: Theodore Ts'o 
+Date:   Mon Dec 12 22:06:18 2011 -0500
+
+    ext4: display the correct mount option in /proc/mounts for [no]init_itable
+    
+    /proc/mounts was showing the mount option [no]init_inode_table when
+    the correct mount option that will be accepted by parse_options() is
+    [no]init_itable.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 3858767ec672..3e1329e2f826 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1155,9 +1155,9 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
+ 		seq_puts(seq, ",block_validity");
+ 
+ 	if (!test_opt(sb, INIT_INODE_TABLE))
+-		seq_puts(seq, ",noinit_inode_table");
++		seq_puts(seq, ",noinit_itable");
+ 	else if (sbi->s_li_wait_mult != EXT4_DEF_LI_WAIT_MULT)
+-		seq_printf(seq, ",init_inode_table=%u",
++		seq_printf(seq, ",init_itable=%u",
+ 			   (unsigned) sbi->s_li_wait_mult);
+ 
+ 	ext4_show_quota_options(seq, sb);
+@@ -1333,8 +1333,7 @@ enum {
+ 	Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity,
+ 	Opt_inode_readahead_blks, Opt_journal_ioprio,
+ 	Opt_dioread_nolock, Opt_dioread_lock,
+-	Opt_discard, Opt_nodiscard,
+-	Opt_init_inode_table, Opt_noinit_inode_table,
++	Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable,
+ };
+ 
+ static const match_table_t tokens = {
+@@ -1407,9 +1406,9 @@ static const match_table_t tokens = {
+ 	{Opt_dioread_lock, "dioread_lock"},
+ 	{Opt_discard, "discard"},
+ 	{Opt_nodiscard, "nodiscard"},
+-	{Opt_init_inode_table, "init_itable=%u"},
+-	{Opt_init_inode_table, "init_itable"},
+-	{Opt_noinit_inode_table, "noinit_itable"},
++	{Opt_init_itable, "init_itable=%u"},
++	{Opt_init_itable, "init_itable"},
++	{Opt_noinit_itable, "noinit_itable"},
+ 	{Opt_err, NULL},
+ };
+ 
+@@ -1892,7 +1891,7 @@ static int parse_options(char *options, struct super_block *sb,
+ 		case Opt_dioread_lock:
+ 			clear_opt(sb, DIOREAD_NOLOCK);
+ 			break;
+-		case Opt_init_inode_table:
++		case Opt_init_itable:
+ 			set_opt(sb, INIT_INODE_TABLE);
+ 			if (args[0].from) {
+ 				if (match_int(&args[0], &option))
+@@ -1903,7 +1902,7 @@ static int parse_options(char *options, struct super_block *sb,
+ 				return 0;
+ 			sbi->s_li_wait_mult = option;
+ 			break;
+-		case Opt_noinit_inode_table:
++		case Opt_noinit_itable:
+ 			clear_opt(sb, INIT_INODE_TABLE);
+ 			break;
+ 		default:

commit b5a7e97039a80fae673ccc115ce595d5b88fb4ee
+Author: Theodore Ts'o 
+Date:   Mon Dec 12 10:53:02 2011 -0500
+
+    ext4: fix ext4_end_io_dio() racing against fsync()
+    
+    We need to make sure iocb->private is cleared *before* we put the
+    io_end structure on i_completed_io_list.  Otherwise fsync() could
+    potentially run on another CPU and free the iocb structure out from
+    under us.
+    
+    Reported-by: Kent Overstreet 
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 848f436df29f..d2c86633811f 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2781,10 +2781,11 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
+  		  iocb->private, io_end->inode->i_ino, iocb, offset,
+ 		  size);
+ 
++	iocb->private = NULL;
++
+ 	/* if not aio dio with unwritten extents, just free io and return */
+ 	if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) {
+ 		ext4_free_io_end(io_end);
+-		iocb->private = NULL;
+ out:
+ 		if (is_async)
+ 			aio_complete(iocb, ret, 0);
+@@ -2807,7 +2808,6 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
+ 	spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
+ 
+ 	/* queue the work to convert unwritten extents to written */
+-	iocb->private = NULL;
+ 	queue_work(wq, &io_end->work);
+ 
+ 	/* XXX: probably should move into the real I/O completion handler */

commit eb513689c97e3e73bb9b4459d490a8e894b4a546
+Author: Theodore Ts'o 
+Date:   Mon Nov 7 10:47:42 2011 -0500
+
+    ext4: ignore journalled data options on remount if fs has no journal
+    
+    This avoids a confusing failure in the init scripts when the
+    /etc/fstab has data=writeback or data=journal but the file system does
+    not have a journal.  So check for this case explicitly, and warn the
+    user that we are ignoring the (pointless, since they have no journal)
+    data=* mount option.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 9953d80145ad..0435013dbd46 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1683,7 +1683,9 @@ static int parse_options(char *options, struct super_block *sb,
+ 			data_opt = EXT4_MOUNT_WRITEBACK_DATA;
+ 		datacheck:
+ 			if (is_remount) {
+-				if (test_opt(sb, DATA_FLAGS) != data_opt) {
++				if (!sbi->s_journal)
++					ext4_msg(sb, KERN_WARNING, "Remounting file system with no journal so ignoring journalled data option");
++				else if (test_opt(sb, DATA_FLAGS) != data_opt) {
+ 					ext4_msg(sb, KERN_ERR,
+ 						"Cannot change data mode on remount");
+ 					return 0;

commit b82e384c7bb9a19036b4daf58fa216df7cd48aa0
+Author: Theodore Ts'o 
+Date:   Mon Oct 31 10:56:32 2011 -0400
+
+    ext4: optimize locking for end_io extent conversion
+    
+    Now that we are doing the locking correctly, we need to grab the
+    i_completed_io_lock() twice per end_io.  We can clean this up by
+    removing the structure from the i_complted_io_list, and use this as
+    the locking mechanism to prevent ext4_flush_completed_IO() racing
+    against ext4_end_io_work(), instead of clearing the
+    EXT4_IO_END_UNWRITTEN in io->flag.
+    
+    In addition, if the ext4_convert_unwritten_extents() returns an error,
+    we no longer keep the end_io structure on the linked list.  This
+    doesn't help, because it tends to lock up the file system and wedges
+    the system.  That's one way to call attention to the problem, but it
+    doesn't help the overall robustness of the system.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
+index 851ac5b3cec9..00a2cb753efd 100644
+--- a/fs/ext4/fsync.c
++++ b/fs/ext4/fsync.c
+@@ -88,6 +88,7 @@ int ext4_flush_completed_IO(struct inode *inode)
+ 	while (!list_empty(&ei->i_completed_io_list)){
+ 		io = list_entry(ei->i_completed_io_list.next,
+ 				ext4_io_end_t, list);
++		list_del_init(&io->list);
+ 		/*
+ 		 * Calling ext4_end_io_nolock() to convert completed
+ 		 * IO to written.
+@@ -104,11 +105,9 @@ int ext4_flush_completed_IO(struct inode *inode)
+ 		 */
+ 		spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
+ 		ret = ext4_end_io_nolock(io);
+-		spin_lock_irqsave(&ei->i_completed_io_lock, flags);
+ 		if (ret < 0)
+ 			ret2 = ret;
+-		else
+-			list_del_init(&io->list);
++		spin_lock_irqsave(&ei->i_completed_io_lock, flags);
+ 	}
+ 	spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
+ 	return (ret2 < 0) ? ret2 : 0;
+diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
+index 4fa1d709b604..9eebf44646f6 100644
+--- a/fs/ext4/page-io.c
++++ b/fs/ext4/page-io.c
+@@ -99,28 +99,21 @@ int ext4_end_io_nolock(ext4_io_end_t *io)
+ 		   "list->prev 0x%p\n",
+ 		   io, inode->i_ino, io->list.next, io->list.prev);
+ 
+-	if (!(io->flag & EXT4_IO_END_UNWRITTEN))
+-		return ret;
+-
+ 	ret = ext4_convert_unwritten_extents(inode, offset, size);
+ 	if (ret < 0) {
+-		printk(KERN_EMERG "%s: failed to convert unwritten "
+-			"extents to written extents, error is %d "
+-			"io is still on inode %lu aio dio list\n",
+-		       __func__, ret, inode->i_ino);
+-		return ret;
++		ext4_msg(inode->i_sb, KERN_EMERG,
++			 "failed to convert unwritten extents to written "
++			 "extents -- potential data loss!  "
++			 "(inode %lu, offset %llu, size %zd, error %d)",
++			 inode->i_ino, offset, size, ret);
+ 	}
+ 
+ 	if (io->iocb)
+ 		aio_complete(io->iocb, io->result, 0);
+-	/* clear the DIO AIO unwritten flag */
+-	if (io->flag & EXT4_IO_END_UNWRITTEN) {
+-		io->flag &= ~EXT4_IO_END_UNWRITTEN;
+-		/* Wake up anyone waiting on unwritten extent conversion */
+-		if (atomic_dec_and_test(&EXT4_I(inode)->i_aiodio_unwritten))
+-			wake_up_all(ext4_ioend_wq(io->inode));
+-	}
+ 
++	/* Wake up anyone waiting on unwritten extent conversion */
++	if (atomic_dec_and_test(&EXT4_I(inode)->i_aiodio_unwritten))
++		wake_up_all(ext4_ioend_wq(io->inode));
+ 	return ret;
+ }
+ 
+@@ -133,16 +126,15 @@ static void ext4_end_io_work(struct work_struct *work)
+ 	struct inode		*inode = io->inode;
+ 	struct ext4_inode_info	*ei = EXT4_I(inode);
+ 	unsigned long		flags;
+-	int			ret;
+ 
+ 	spin_lock_irqsave(&ei->i_completed_io_lock, flags);
+ 	if (list_empty(&io->list)) {
+ 		spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
+ 		goto free;
+ 	}
+-	spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
+ 
+ 	if (!mutex_trylock(&inode->i_mutex)) {
++		spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
+ 		/*
+ 		 * Requeue the work instead of waiting so that the work
+ 		 * items queued after this can be processed.
+@@ -159,16 +151,9 @@ static void ext4_end_io_work(struct work_struct *work)
+ 		io->flag |= EXT4_IO_END_QUEUED;
+ 		return;
+ 	}
+-	ret = ext4_end_io_nolock(io);
+-	if (ret < 0) {
+-		mutex_unlock(&inode->i_mutex);
+-		return;
+-	}
+-
+-	spin_lock_irqsave(&ei->i_completed_io_lock, flags);
+-	if (!list_empty(&io->list))
+-		list_del_init(&io->list);
++	list_del_init(&io->list);
+ 	spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
++	(void) ext4_end_io_nolock(io);
+ 	mutex_unlock(&inode->i_mutex);
+ free:
+ 	ext4_free_io_end(io);

commit 4e298021216727cc27017c5032ade86167c66256
+Author: Theodore Ts'o 
+Date:   Sun Oct 30 18:41:19 2011 -0400
+
+    ext4: remove unnecessary call to waitqueue_active()
+    
+    The usage of waitqueue_active() is not necessary, and introduces (I
+    believe) a hard-to-hit race.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
+index aed40966f342..4fa1d709b604 100644
+--- a/fs/ext4/page-io.c
++++ b/fs/ext4/page-io.c
+@@ -70,7 +70,6 @@ static void put_io_page(struct ext4_io_page *io_page)
+ void ext4_free_io_end(ext4_io_end_t *io)
+ {
+ 	int i;
+-	wait_queue_head_t *wq;
+ 
+ 	BUG_ON(!io);
+ 	if (io->page)
+@@ -78,10 +77,8 @@ void ext4_free_io_end(ext4_io_end_t *io)
+ 	for (i = 0; i < io->num_io_pages; i++)
+ 		put_io_page(io->pages[i]);
+ 	io->num_io_pages = 0;
+-	wq = ext4_ioend_wq(io->inode);
+-	if (atomic_dec_and_test(&EXT4_I(io->inode)->i_ioend_count) &&
+-	    waitqueue_active(wq))
+-		wake_up_all(wq);
++	if (atomic_dec_and_test(&EXT4_I(io->inode)->i_ioend_count))
++		wake_up_all(ext4_ioend_wq(io->inode));
+ 	kmem_cache_free(io_end_cachep, io);
+ }
+ 
+@@ -96,7 +93,6 @@ int ext4_end_io_nolock(ext4_io_end_t *io)
+ 	struct inode *inode = io->inode;
+ 	loff_t offset = io->offset;
+ 	ssize_t size = io->size;
+-	wait_queue_head_t *wq;
+ 	int ret = 0;
+ 
+ 	ext4_debug("ext4_end_io_nolock: io 0x%p from inode %lu,list->next 0x%p,"
+@@ -121,11 +117,8 @@ int ext4_end_io_nolock(ext4_io_end_t *io)
+ 	if (io->flag & EXT4_IO_END_UNWRITTEN) {
+ 		io->flag &= ~EXT4_IO_END_UNWRITTEN;
+ 		/* Wake up anyone waiting on unwritten extent conversion */
+-		wq = ext4_ioend_wq(io->inode);
+-		if (atomic_dec_and_test(&EXT4_I(inode)->i_aiodio_unwritten) &&
+-		    waitqueue_active(wq)) {
+-			wake_up_all(wq);
+-		}
++		if (atomic_dec_and_test(&EXT4_I(inode)->i_aiodio_unwritten))
++			wake_up_all(ext4_ioend_wq(io->inode));
+ 	}
+ 
+ 	return ret;

commit 6cdbb0effc2f511ced23e46f2117e4b31d3d4a50
+Author: Theodore Ts'o 
+Date:   Sat Oct 29 08:24:18 2011 -0400
+
+    fs: optimize out 16 bytes worth of padding in struct inode
+    
+    Rearrange the fields in struct inode so that on an x86_64 system,
+    fields that require 8-byte alignment don't end up causing 4-byte holes
+    in the structure.  It reduces the size of struct inode from 568 bytes
+    to 552 bytes.
+    
+    Also move the fields protected by i_lock (i_blocks, i_bytes, and
+    i_size) into the same cache line as i_lock.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 178cdb4f1d4a..fbda9a662f57 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -771,12 +771,13 @@ struct inode {
+ 	unsigned long		i_ino;
+ 	unsigned int		i_nlink;
+ 	dev_t			i_rdev;
+-	loff_t			i_size;
+ 	struct timespec		i_atime;
+ 	struct timespec		i_mtime;
+ 	struct timespec		i_ctime;
+-	unsigned int		i_blkbits;
++	spinlock_t		i_lock;	/* i_blocks, i_bytes, maybe i_size */
++	unsigned short          i_bytes;
+ 	blkcnt_t		i_blocks;
++	loff_t			i_size;
+ 
+ #ifdef __NEED_I_SIZE_ORDERED
+ 	seqcount_t		i_size_seqcount;
+@@ -784,7 +785,6 @@ struct inode {
+ 
+ 	/* Misc */
+ 	unsigned long		i_state;
+-	spinlock_t		i_lock;	/* i_blocks, i_bytes, maybe i_size */
+ 	struct mutex		i_mutex;
+ 
+ 	unsigned long		dirtied_when;	/* jiffies of first dirtying */
+@@ -798,9 +798,10 @@ struct inode {
+ 		struct rcu_head		i_rcu;
+ 	};
+ 	atomic_t		i_count;
++	unsigned int		i_blkbits;
+ 	u64			i_version;
+-	unsigned short          i_bytes;
+ 	atomic_t		i_dio_count;
++	atomic_t		i_writecount;
+ 	const struct file_operations	*i_fop;	/* former ->i_op->default_file_ops */
+ 	struct file_lock	*i_flock;
+ 	struct address_space	i_data;
+@@ -824,7 +825,6 @@ struct inode {
+ #ifdef CONFIG_IMA
+ 	atomic_t		i_readcount; /* struct files open RO */
+ #endif
+-	atomic_t		i_writecount;
+ 	void			*i_private; /* fs or device private pointer */
+ };
+ 

commit af909a57fde821627282204ba43f27331342bf26
+Author: Theodore Ts'o 
+Date:   Sat Oct 8 14:01:08 2011 -0400
+
+    ext4: documentation: remove acl and user_xattr mount options
+    
+    Acl and user_xattr mount options are no longer needed since those
+    features are enabled by default if configured in (seee commit
+    ea6633369458992241599c9d9ebadffaeddec164). We can not easily deprecate
+    mount options itself (since it is probably too early), but we can
+    remove it from documentation first.
+    
+    Signed-off-by: Lukas Czerner 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
+index 168242b5c045..a53040193967 100644
+--- a/Documentation/filesystems/ext4.txt
++++ b/Documentation/filesystems/ext4.txt
+@@ -211,22 +211,19 @@ oldalloc		This disables the Orlov block allocator and enables
+ 			performance - we'd like to get some feedback if it's
+ 			the contrary for you.
+ 
+-user_xattr		Enables Extended User Attributes.  Additionally, you
+-			need to have extended attribute support enabled in the
+-			kernel configuration (CONFIG_EXT4_FS_XATTR).  See the
+-			attr(5) manual page and http://acl.bestbits.at/ to
+-			learn more about extended attributes.
+-
+-nouser_xattr		Disables Extended User Attributes.
+-
+-acl			Enables POSIX Access Control Lists support.
+-			Additionally, you need to have ACL support enabled in
+-			the kernel configuration (CONFIG_EXT4_FS_POSIX_ACL).
+-			See the acl(5) manual page and http://acl.bestbits.at/
+-			for more information.
++nouser_xattr		Disables Extended User Attributes. If you have extended
++			attribute support enabled in the kernel configuration
++			(CONFIG_EXT4_FS_XATTR), extended attribute support
++			is enabled by default on mount. See the attr(5) manual
++			page and http://acl.bestbits.at/ for more information
++			about extended attributes.
+ 
+ noacl			This option disables POSIX Access Control List
+-			support.
++			support. If ACL support is enabled in the kernel
++			configuration (CONFIG_EXT4_FS_POSIX_ACL), ACL is
++			enabled by default on mount. See the acl(5) manual
++			page and http://acl.bestbits.at/ for more information
++			about acl.
+ 
+ bsddf		(*)	Make 'df' act like BSD.
+ minixdf			Make 'df' act like Minix.

commit df55c99dc8ee4c3c886a5edc8a4aa6b131c95afc
+Author: Theodore Ts'o 
+Date:   Fri Sep 9 19:16:51 2011 -0400
+
+    ext4: rename ext4_has_free_blocks() to ext4_has_free_clusters()
+    
+    Rename the function so it is more clear what is going on.  Also rename
+    the various variables so it's clearer what's happening.
+    
+    Also fix a missing blocks to cluster conversion when reading the
+    number of reserved blocks for root.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index af0c5357e35a..f6dba4505f1c 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -403,42 +403,43 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
+ }
+ 
+ /**
+- * ext4_has_free_blocks()
++ * ext4_has_free_clusters()
+  * @sbi:	in-core super block structure.
+- * @nblocks:	number of needed blocks
++ * @nclusters:	number of needed blocks
++ * @flags:	flags from ext4_mb_new_blocks()
+  *
+- * Check if filesystem has nblocks free & available for allocation.
++ * Check if filesystem has nclusters free & available for allocation.
+  * On success return 1, return 0 on failure.
+  */
+-static int ext4_has_free_blocks(struct ext4_sb_info *sbi,
+-				s64 nblocks, unsigned int flags)
++static int ext4_has_free_clusters(struct ext4_sb_info *sbi,
++				  s64 nclusters, unsigned int flags)
+ {
+-	s64 free_blocks, dirty_blocks, root_blocks;
++	s64 free_clusters, dirty_clusters, root_clusters;
+ 	struct percpu_counter *fcc = &sbi->s_freeclusters_counter;
+-	struct percpu_counter *dbc = &sbi->s_dirtyclusters_counter;
++	struct percpu_counter *dcc = &sbi->s_dirtyclusters_counter;
+ 
+-	free_blocks  = percpu_counter_read_positive(fcc);
+-	dirty_blocks = percpu_counter_read_positive(dbc);
+-	root_blocks = ext4_r_blocks_count(sbi->s_es);
++	free_clusters  = percpu_counter_read_positive(fcc);
++	dirty_clusters = percpu_counter_read_positive(dcc);
++	root_clusters = EXT4_B2C(sbi, ext4_r_blocks_count(sbi->s_es));
+ 
+-	if (free_blocks - (nblocks + root_blocks + dirty_blocks) <
+-						EXT4_FREEBLOCKS_WATERMARK) {
+-		free_blocks  = EXT4_C2B(sbi, percpu_counter_sum_positive(fcc));
+-		dirty_blocks = percpu_counter_sum_positive(dbc);
++	if (free_clusters - (nclusters + root_clusters + dirty_clusters) <
++					EXT4_FREECLUSTERS_WATERMARK) {
++		free_clusters  = EXT4_C2B(sbi, percpu_counter_sum_positive(fcc));
++		dirty_clusters = percpu_counter_sum_positive(dcc);
+ 	}
+-	/* Check whether we have space after
+-	 * accounting for current dirty blocks & root reserved blocks.
++	/* Check whether we have space after accounting for current
++	 * dirty clusters & root reserved clusters.
+ 	 */
+-	if (free_blocks >= ((root_blocks + nblocks) + dirty_blocks))
++	if (free_clusters >= ((root_clusters + nclusters) + dirty_clusters))
+ 		return 1;
+ 
+-	/* Hm, nope.  Are (enough) root reserved blocks available? */
++	/* Hm, nope.  Are (enough) root reserved clusters available? */
+ 	if (sbi->s_resuid == current_fsuid() ||
+ 	    ((sbi->s_resgid != 0) && in_group_p(sbi->s_resgid)) ||
+ 	    capable(CAP_SYS_RESOURCE) ||
+ 		(flags & EXT4_MB_USE_ROOT_BLOCKS)) {
+ 
+-		if (free_blocks >= (nblocks + dirty_blocks))
++		if (free_clusters >= (nclusters + dirty_clusters))
+ 			return 1;
+ 	}
+ 
+@@ -448,7 +449,7 @@ static int ext4_has_free_blocks(struct ext4_sb_info *sbi,
+ int ext4_claim_free_clusters(struct ext4_sb_info *sbi,
+ 			     s64 nclusters, unsigned int flags)
+ {
+-	if (ext4_has_free_blocks(sbi, nclusters, flags)) {
++	if (ext4_has_free_clusters(sbi, nclusters, flags)) {
+ 		percpu_counter_add(&sbi->s_dirtyclusters_counter, nclusters);
+ 		return 0;
+ 	} else
+@@ -469,7 +470,7 @@ int ext4_claim_free_clusters(struct ext4_sb_info *sbi,
+  */
+ int ext4_should_retry_alloc(struct super_block *sb, int *retries)
+ {
+-	if (!ext4_has_free_blocks(EXT4_SB(sb), 1, 0) ||
++	if (!ext4_has_free_clusters(EXT4_SB(sb), 1, 0) ||
+ 	    (*retries)++ > 3 ||
+ 	    !EXT4_SB(sb)->s_journal)
+ 		return 0;
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index f97638634e34..21ea65d8bd46 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2103,13 +2103,13 @@ do {								\
+ } while (0)
+ 
+ #ifdef CONFIG_SMP
+-/* Each CPU can accumulate percpu_counter_batch blocks in their local
+- * counters. So we need to make sure we have free blocks more
++/* Each CPU can accumulate percpu_counter_batch clusters in their local
++ * counters. So we need to make sure we have free clusters more
+  * than percpu_counter_batch  * nr_cpu_ids. Also add a window of 4 times.
+  */
+-#define EXT4_FREEBLOCKS_WATERMARK (4 * (percpu_counter_batch * nr_cpu_ids))
++#define EXT4_FREECLUSTERS_WATERMARK (4 * (percpu_counter_batch * nr_cpu_ids))
+ #else
+-#define EXT4_FREEBLOCKS_WATERMARK 0
++#define EXT4_FREECLUSTERS_WATERMARK 0
+ #endif
+ 
+ static inline void ext4_update_i_disksize(struct inode *inode, loff_t newsize)
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 557c34ffa05b..88dc63a01756 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2255,7 +2255,7 @@ static int ext4_nonda_switch(struct super_block *sb)
+ 		percpu_counter_read_positive(&sbi->s_freeclusters_counter));
+ 	dirty_blocks = percpu_counter_read_positive(&sbi->s_dirtyclusters_counter);
+ 	if (2 * free_blocks < 3 * dirty_blocks ||
+-		free_blocks < (dirty_blocks + EXT4_FREEBLOCKS_WATERMARK)) {
++		free_blocks < (dirty_blocks + EXT4_FREECLUSTERS_WATERMARK)) {
+ 		/*
+ 		 * free block count is less than 150% of dirty blocks
+ 		 * or free blocks is less than watermark

commit e7d5f3156e6827970f75ab27ad7eb0155826eb0b
+Author: Theodore Ts'o 
+Date:   Fri Sep 9 19:14:51 2011 -0400
+
+    ext4: rename ext4_claim_free_blocks() to ext4_claim_free_clusters()
+    
+    This function really claims a number of free clusters, not blocks, so
+    rename it so it's clearer what's going on.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 3d07c35c7089..af0c5357e35a 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -445,11 +445,11 @@ static int ext4_has_free_blocks(struct ext4_sb_info *sbi,
+ 	return 0;
+ }
+ 
+-int ext4_claim_free_blocks(struct ext4_sb_info *sbi,
+-			   s64 nblocks, unsigned int flags)
++int ext4_claim_free_clusters(struct ext4_sb_info *sbi,
++			     s64 nclusters, unsigned int flags)
+ {
+-	if (ext4_has_free_blocks(sbi, nblocks, flags)) {
+-		percpu_counter_add(&sbi->s_dirtyclusters_counter, nblocks);
++	if (ext4_has_free_blocks(sbi, nclusters, flags)) {
++		percpu_counter_add(&sbi->s_dirtyclusters_counter, nclusters);
+ 		return 0;
+ 	} else
+ 		return -ENOSPC;
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 1473c06e4c94..f97638634e34 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1773,8 +1773,8 @@ extern ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
+ 					 unsigned int flags,
+ 					 unsigned long *count,
+ 					 int *errp);
+-extern int ext4_claim_free_blocks(struct ext4_sb_info *sbi,
+-				  s64 nblocks, unsigned int flags);
++extern int ext4_claim_free_clusters(struct ext4_sb_info *sbi,
++				    s64 nclusters, unsigned int flags);
+ extern ext4_fsblk_t ext4_count_free_clusters(struct super_block *);
+ extern void ext4_check_blocks_bitmap(struct super_block *);
+ extern struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index f9198d7875cc..557c34ffa05b 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1071,7 +1071,7 @@ int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock)
+ 	 * We do still charge estimated metadata to the sb though;
+ 	 * we cannot afford to run out of free blocks.
+ 	 */
+-	if (ext4_claim_free_blocks(sbi, md_needed + 1, 0)) {
++	if (ext4_claim_free_clusters(sbi, md_needed + 1, 0)) {
+ 		dquot_release_reservation_block(inode, EXT4_C2B(sbi, 1));
+ 		if (ext4_should_retry_alloc(inode->i_sb, &retries)) {
+ 			yield();
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 90a3ed7c565c..1c83161090f8 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -4297,7 +4297,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
+ 		 * and verify allocation doesn't exceed the quota limits.
+ 		 */
+ 		while (ar->len &&
+-			ext4_claim_free_blocks(sbi, ar->len, ar->flags)) {
++			ext4_claim_free_clusters(sbi, ar->len, ar->flags)) {
+ 
+ 			/* let others to free the space */
+ 			yield();

commit cff1dfd767d1ee3c773fd8b57fe310957e5f8abb
+Author: Theodore Ts'o 
+Date:   Fri Sep 9 19:12:51 2011 -0400
+
+    ext4: rename ext4_free_blocks_after_init() to ext4_free_clusters_after_init()
+    
+    This function really returns the number of clusters after initializing
+    an uninitalized block bitmap has been initialized.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 4f303809e076..3d07c35c7089 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -213,9 +213,9 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
+ /* Return the number of free blocks in a block group.  It is used when
+  * the block bitmap is uninitialized, so we can't just count the bits
+  * in the bitmap. */
+-unsigned ext4_free_blocks_after_init(struct super_block *sb,
+-				     ext4_group_t block_group,
+-				     struct ext4_group_desc *gdp)
++unsigned ext4_free_clusters_after_init(struct super_block *sb,
++				       ext4_group_t block_group,
++				       struct ext4_group_desc *gdp)
+ {
+ 	return num_clusters_in_group(sb, block_group) - 
+ 		ext4_num_overhead_clusters(sb, block_group, gdp);
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index f6963cd7f709..1473c06e4c94 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1787,9 +1787,9 @@ extern void ext4_init_block_bitmap(struct super_block *sb,
+ 				   struct buffer_head *bh,
+ 				   ext4_group_t group,
+ 				   struct ext4_group_desc *desc);
+-extern unsigned ext4_free_blocks_after_init(struct super_block *sb,
+-					    ext4_group_t block_group,
+-					    struct ext4_group_desc *gdp);
++extern unsigned ext4_free_clusters_after_init(struct super_block *sb,
++					      ext4_group_t block_group,
++					      struct ext4_group_desc *gdp);
+ extern unsigned ext4_num_base_meta_clusters(struct super_block *sb,
+ 					    ext4_group_t block_group);
+ extern unsigned ext4_num_overhead_clusters(struct super_block *sb,
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 71a9c8f3dece..d50a7d5e4726 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -961,7 +961,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
+ 		if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
+ 			gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
+ 			ext4_free_group_clusters_set(sb, gdp,
+-				ext4_free_blocks_after_init(sb, group, gdp));
++				ext4_free_clusters_after_init(sb, group, gdp));
+ 			gdp->bg_checksum = ext4_group_desc_csum(sbi, group,
+ 								gdp);
+ 		}
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 76db2f12107f..90a3ed7c565c 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2253,7 +2253,7 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group,
+ 	 */
+ 	if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
+ 		meta_group_info[i]->bb_free =
+-			ext4_free_blocks_after_init(sb, group, desc);
++			ext4_free_clusters_after_init(sb, group, desc);
+ 	} else {
+ 		meta_group_info[i]->bb_free =
+ 			ext4_free_group_clusters(sb, desc);
+@@ -2840,7 +2840,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
+ 	if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
+ 		gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
+ 		ext4_free_group_clusters_set(sb, gdp,
+-					     ext4_free_blocks_after_init(sb,
++					     ext4_free_clusters_after_init(sb,
+ 						ac->ac_b_ex.fe_group, gdp));
+ 	}
+ 	len = ext4_free_group_clusters(sb, gdp) - ac->ac_b_ex.fe_len;

commit 5dee54372c1ea15ab482b959634cda8c01b042bd
+Author: Theodore Ts'o 
+Date:   Fri Sep 9 19:10:51 2011 -0400
+
+    ext4: rename ext4_count_free_blocks() to ext4_count_free_clusters()
+    
+    This function really counts the free clusters reported in the block
+    group descriptors, so rename it to reduce confusion.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 84dc3d62b40c..4f303809e076 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -524,12 +524,12 @@ ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
+ }
+ 
+ /**
+- * ext4_count_free_blocks() -- count filesystem free blocks
++ * ext4_count_free_clusters() -- count filesystem free clusters
+  * @sb:		superblock
+  *
+- * Adds up the number of free blocks from each block group.
++ * Adds up the number of free clusters from each block group.
+  */
+-ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
++ext4_fsblk_t ext4_count_free_clusters(struct super_block *sb)
+ {
+ 	ext4_fsblk_t desc_count;
+ 	struct ext4_group_desc *gdp;
+@@ -562,8 +562,9 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
+ 		bitmap_count += x;
+ 	}
+ 	brelse(bitmap_bh);
+-	printk(KERN_DEBUG "ext4_count_free_blocks: stored = %llu"
+-		", computed = %llu, %llu\n", ext4_free_blocks_count(es),
++	printk(KERN_DEBUG "ext4_count_free_clusters: stored = %llu"
++	       ", computed = %llu, %llu\n",
++	       EXT4_B2C(sbi, ext4_free_blocks_count(es)),
+ 	       desc_count, bitmap_count);
+ 	return bitmap_count;
+ #else
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index db279c362017..f6963cd7f709 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1775,7 +1775,7 @@ extern ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
+ 					 int *errp);
+ extern int ext4_claim_free_blocks(struct ext4_sb_info *sbi,
+ 				  s64 nblocks, unsigned int flags);
+-extern ext4_fsblk_t ext4_count_free_blocks(struct super_block *);
++extern ext4_fsblk_t ext4_count_free_clusters(struct super_block *);
+ extern void ext4_check_blocks_bitmap(struct super_block *);
+ extern struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
+ 						    ext4_group_t block_group,
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index d1c17e47c1c6..f9198d7875cc 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1365,7 +1365,8 @@ static void ext4_print_free_blocks(struct inode *inode)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+ 	printk(KERN_CRIT "Total free blocks count %lld\n",
+-	       ext4_count_free_blocks(inode->i_sb));
++	       EXT4_C2B(EXT4_SB(inode->i_sb),
++			ext4_count_free_clusters(inode->i_sb)));
+ 	printk(KERN_CRIT "Free/Dirty block details\n");
+ 	printk(KERN_CRIT "free_blocks=%lld\n",
+ 	       (long long) EXT4_C2B(EXT4_SB(inode->i_sb),
+@@ -1451,8 +1452,7 @@ static void mpage_da_map_and_submit(struct mpage_da_data *mpd)
+ 		if (err == -EAGAIN)
+ 			goto submit_io;
+ 
+-		if (err == -ENOSPC &&
+-		    ext4_count_free_blocks(sb)) {
++		if (err == -ENOSPC && ext4_count_free_clusters(sb)) {
+ 			mpd->retval = err;
+ 			goto submit_io;
+ 		}
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 30cf0e1bd89c..07f3de341452 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2153,7 +2153,8 @@ static int ext4_check_descriptors(struct super_block *sb,
+ 	if (NULL != first_not_zeroed)
+ 		*first_not_zeroed = grp;
+ 
+-	ext4_free_blocks_count_set(sbi->s_es, ext4_count_free_blocks(sb));
++	ext4_free_blocks_count_set(sbi->s_es,
++				   EXT4_C2B(sbi, ext4_count_free_clusters(sb)));
+ 	sbi->s_es->s_free_inodes_count =cpu_to_le32(ext4_count_free_inodes(sb));
+ 	return 1;
+ }
+@@ -3577,7 +3578,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	sbi->s_err_report.data = (unsigned long) sb;
+ 
+ 	err = percpu_counter_init(&sbi->s_freeclusters_counter,
+-			ext4_count_free_blocks(sb));
++			ext4_count_free_clusters(sb));
+ 	if (!err) {
+ 		err = percpu_counter_init(&sbi->s_freeinodes_counter,
+ 				ext4_count_free_inodes(sb));
+@@ -3703,7 +3704,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	 * need to update the global counters.
+ 	 */
+ 	percpu_counter_set(&sbi->s_freeclusters_counter,
+-			   ext4_count_free_blocks(sb));
++			   ext4_count_free_clusters(sb));
+ 	percpu_counter_set(&sbi->s_freeinodes_counter,
+ 			   ext4_count_free_inodes(sb));
+ 	percpu_counter_set(&sbi->s_dirs_counter,

commit 021b65bb1e4e4b625c80bbb82651e5e155721ef3
+Author: Theodore Ts'o 
+Date:   Fri Sep 9 19:08:51 2011 -0400
+
+    ext4: Rename ext4_free_blks_{count,set}() to refer to clusters
+    
+    The field bg_free_blocks_count_{lo,high} in the block group
+    descriptor has been repurposed to hold the number of free clusters for
+    bigalloc functions.  So rename the functions so it makes it easier to
+    read and audit the block allocation and block freeing code.
+    
+    Note: at this point in bigalloc development we doesn't support
+    online resize, so this also makes it really obvious all of the places
+    we need to fix up to add support for online resize.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index bf42b3219e3c..84dc3d62b40c 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -168,7 +168,7 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
+ 	 * essentially implementing a per-group read-only flag. */
+ 	if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
+ 		ext4_error(sb, "Checksum bad for group %u", block_group);
+-		ext4_free_blks_set(sb, gdp, 0);
++		ext4_free_group_clusters_set(sb, gdp, 0);
+ 		ext4_free_inodes_set(sb, gdp, 0);
+ 		ext4_itable_unused_set(sb, gdp, 0);
+ 		memset(bh->b_data, 0xff, sb->s_blocksize);
+@@ -550,7 +550,7 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
+ 		gdp = ext4_get_group_desc(sb, i, NULL);
+ 		if (!gdp)
+ 			continue;
+-		desc_count += ext4_free_blks_count(sb, gdp);
++		desc_count += ext4_free_group_clusters(sb, gdp);
+ 		brelse(bitmap_bh);
+ 		bitmap_bh = ext4_read_block_bitmap(sb, i);
+ 		if (bitmap_bh == NULL)
+@@ -558,7 +558,7 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
+ 
+ 		x = ext4_count_free(bitmap_bh, sb->s_blocksize);
+ 		printk(KERN_DEBUG "group %u: stored = %d, counted = %u\n",
+-			i, ext4_free_blks_count(sb, gdp), x);
++			i, ext4_free_group_clusters(sb, gdp), x);
+ 		bitmap_count += x;
+ 	}
+ 	brelse(bitmap_bh);
+@@ -572,7 +572,7 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
+ 		gdp = ext4_get_group_desc(sb, i, NULL);
+ 		if (!gdp)
+ 			continue;
+-		desc_count += ext4_free_blks_count(sb, gdp);
++		desc_count += ext4_free_group_clusters(sb, gdp);
+ 	}
+ 
+ 	return desc_count;
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index a5a7e369f719..db279c362017 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1978,8 +1978,8 @@ extern ext4_fsblk_t ext4_inode_bitmap(struct super_block *sb,
+ 				      struct ext4_group_desc *bg);
+ extern ext4_fsblk_t ext4_inode_table(struct super_block *sb,
+ 				     struct ext4_group_desc *bg);
+-extern __u32 ext4_free_blks_count(struct super_block *sb,
+-				struct ext4_group_desc *bg);
++extern __u32 ext4_free_group_clusters(struct super_block *sb,
++				      struct ext4_group_desc *bg);
+ extern __u32 ext4_free_inodes_count(struct super_block *sb,
+ 				 struct ext4_group_desc *bg);
+ extern __u32 ext4_used_dirs_count(struct super_block *sb,
+@@ -1992,8 +1992,9 @@ extern void ext4_inode_bitmap_set(struct super_block *sb,
+ 				  struct ext4_group_desc *bg, ext4_fsblk_t blk);
+ extern void ext4_inode_table_set(struct super_block *sb,
+ 				 struct ext4_group_desc *bg, ext4_fsblk_t blk);
+-extern void ext4_free_blks_set(struct super_block *sb,
+-			       struct ext4_group_desc *bg, __u32 count);
++extern void ext4_free_group_clusters_set(struct super_block *sb,
++					 struct ext4_group_desc *bg,
++					 __u32 count);
+ extern void ext4_free_inodes_set(struct super_block *sb,
+ 				struct ext4_group_desc *bg, __u32 count);
+ extern void ext4_used_dirs_set(struct super_block *sb,
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 0be5862313f0..71a9c8f3dece 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -78,7 +78,7 @@ static unsigned ext4_init_inode_bitmap(struct super_block *sb,
+ 	 * allocation, essentially implementing a per-group read-only flag. */
+ 	if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
+ 		ext4_error(sb, "Checksum bad for group %u", block_group);
+-		ext4_free_blks_set(sb, gdp, 0);
++		ext4_free_group_clusters_set(sb, gdp, 0);
+ 		ext4_free_inodes_set(sb, gdp, 0);
+ 		ext4_itable_unused_set(sb, gdp, 0);
+ 		memset(bh->b_data, 0xff, sb->s_blocksize);
+@@ -322,8 +322,8 @@ static int find_group_dir(struct super_block *sb, struct inode *parent,
+ 		if (ext4_free_inodes_count(sb, desc) < avefreei)
+ 			continue;
+ 		if (!best_desc ||
+-		    (ext4_free_blks_count(sb, desc) >
+-		     ext4_free_blks_count(sb, best_desc))) {
++		    (ext4_free_group_clusters(sb, desc) >
++		     ext4_free_group_clusters(sb, best_desc))) {
+ 			*best_group = group;
+ 			best_desc = desc;
+ 			ret = 0;
+@@ -434,7 +434,7 @@ static void get_orlov_stats(struct super_block *sb, ext4_group_t g,
+ 	desc = ext4_get_group_desc(sb, g, NULL);
+ 	if (desc) {
+ 		stats->free_inodes = ext4_free_inodes_count(sb, desc);
+-		stats->free_clusters = ext4_free_blks_count(sb, desc);
++		stats->free_clusters = ext4_free_group_clusters(sb, desc);
+ 		stats->used_dirs = ext4_used_dirs_count(sb, desc);
+ 	} else {
+ 		stats->free_inodes = 0;
+@@ -662,7 +662,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent,
+ 	*group = parent_group;
+ 	desc = ext4_get_group_desc(sb, *group, NULL);
+ 	if (desc && ext4_free_inodes_count(sb, desc) &&
+-			ext4_free_blks_count(sb, desc))
++	    ext4_free_group_clusters(sb, desc))
+ 		return 0;
+ 
+ 	/*
+@@ -686,7 +686,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent,
+ 			*group -= ngroups;
+ 		desc = ext4_get_group_desc(sb, *group, NULL);
+ 		if (desc && ext4_free_inodes_count(sb, desc) &&
+-				ext4_free_blks_count(sb, desc))
++		    ext4_free_group_clusters(sb, desc))
+ 			return 0;
+ 	}
+ 
+@@ -960,7 +960,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
+ 		ext4_lock_group(sb, group);
+ 		if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
+ 			gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
+-			ext4_free_blks_set(sb, gdp,
++			ext4_free_group_clusters_set(sb, gdp,
+ 				ext4_free_blocks_after_init(sb, group, gdp));
+ 			gdp->bg_checksum = ext4_group_desc_csum(sbi, group,
+ 								gdp);
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 5e1215d38331..76db2f12107f 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2256,7 +2256,7 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group,
+ 			ext4_free_blocks_after_init(sb, group, desc);
+ 	} else {
+ 		meta_group_info[i]->bb_free =
+-			ext4_free_blks_count(sb, desc);
++			ext4_free_group_clusters(sb, desc);
+ 	}
+ 
+ 	INIT_LIST_HEAD(&meta_group_info[i]->bb_prealloc_list);
+@@ -2799,7 +2799,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
+ 		goto out_err;
+ 
+ 	ext4_debug("using block group %u(%d)\n", ac->ac_b_ex.fe_group,
+-			ext4_free_blks_count(sb, gdp));
++			ext4_free_group_clusters(sb, gdp));
+ 
+ 	err = ext4_journal_get_write_access(handle, gdp_bh);
+ 	if (err)
+@@ -2839,12 +2839,12 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
+ 		      ac->ac_b_ex.fe_len);
+ 	if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
+ 		gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
+-		ext4_free_blks_set(sb, gdp,
+-					ext4_free_blocks_after_init(sb,
+-					ac->ac_b_ex.fe_group, gdp));
++		ext4_free_group_clusters_set(sb, gdp,
++					     ext4_free_blocks_after_init(sb,
++						ac->ac_b_ex.fe_group, gdp));
+ 	}
+-	len = ext4_free_blks_count(sb, gdp) - ac->ac_b_ex.fe_len;
+-	ext4_free_blks_set(sb, gdp, len);
++	len = ext4_free_group_clusters(sb, gdp) - ac->ac_b_ex.fe_len;
++	ext4_free_group_clusters_set(sb, gdp, len);
+ 	gdp->bg_checksum = ext4_group_desc_csum(sbi, ac->ac_b_ex.fe_group, gdp);
+ 
+ 	ext4_unlock_group(sb, ac->ac_b_ex.fe_group);
+@@ -4702,8 +4702,8 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 		mb_free_blocks(inode, &e4b, bit, count_clusters);
+ 	}
+ 
+-	ret = ext4_free_blks_count(sb, gdp) + count_clusters;
+-	ext4_free_blks_set(sb, gdp, ret);
++	ret = ext4_free_group_clusters(sb, gdp) + count_clusters;
++	ext4_free_group_clusters_set(sb, gdp, ret);
+ 	gdp->bg_checksum = ext4_group_desc_csum(sbi, block_group, gdp);
+ 	ext4_unlock_group(sb, block_group);
+ 	percpu_counter_add(&sbi->s_freeclusters_counter, count_clusters);
+@@ -4846,8 +4846,8 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
+ 	ext4_lock_group(sb, block_group);
+ 	mb_clear_bits(bitmap_bh->b_data, bit, count);
+ 	mb_free_blocks(NULL, &e4b, bit, count);
+-	blk_free_count = blocks_freed + ext4_free_blks_count(sb, desc);
+-	ext4_free_blks_set(sb, desc, blk_free_count);
++	blk_free_count = blocks_freed + ext4_free_group_clusters(sb, desc);
++	ext4_free_group_clusters_set(sb, desc, blk_free_count);
+ 	desc->bg_checksum = ext4_group_desc_csum(sbi, block_group, desc);
+ 	ext4_unlock_group(sb, block_group);
+ 	percpu_counter_add(&sbi->s_freeclusters_counter,
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 95a09ddca3b9..996780ab4f4e 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -875,7 +875,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
+ 	ext4_block_bitmap_set(sb, gdp, input->block_bitmap); /* LV FIXME */
+ 	ext4_inode_bitmap_set(sb, gdp, input->inode_bitmap); /* LV FIXME */
+ 	ext4_inode_table_set(sb, gdp, input->inode_table); /* LV FIXME */
+-	ext4_free_blks_set(sb, gdp, input->free_blocks_count);
++	ext4_free_group_clusters_set(sb, gdp, input->free_blocks_count);
+ 	ext4_free_inodes_set(sb, gdp, EXT4_INODES_PER_GROUP(sb));
+ 	gdp->bg_flags = cpu_to_le16(EXT4_BG_INODE_ZEROED);
+ 	gdp->bg_checksum = ext4_group_desc_csum(sbi, input->group, gdp);
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 66b8cfa15636..30cf0e1bd89c 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -163,8 +163,8 @@ ext4_fsblk_t ext4_inode_table(struct super_block *sb,
+ 		 (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_table_hi) << 32 : 0);
+ }
+ 
+-__u32 ext4_free_blks_count(struct super_block *sb,
+-			      struct ext4_group_desc *bg)
++__u32 ext4_free_group_clusters(struct super_block *sb,
++			       struct ext4_group_desc *bg)
+ {
+ 	return le16_to_cpu(bg->bg_free_blocks_count_lo) |
+ 		(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
+@@ -219,8 +219,8 @@ void ext4_inode_table_set(struct super_block *sb,
+ 		bg->bg_inode_table_hi = cpu_to_le32(blk >> 32);
+ }
+ 
+-void ext4_free_blks_set(struct super_block *sb,
+-			  struct ext4_group_desc *bg, __u32 count)
++void ext4_free_group_clusters_set(struct super_block *sb,
++				  struct ext4_group_desc *bg, __u32 count)
+ {
+ 	bg->bg_free_blocks_count_lo = cpu_to_le16((__u16)count);
+ 	if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
+@@ -2034,7 +2034,7 @@ static int ext4_fill_flex_info(struct super_block *sb)
+ 		flex_group = ext4_flex_group(sbi, i);
+ 		atomic_add(ext4_free_inodes_count(sb, gdp),
+ 			   &sbi->s_flex_groups[flex_group].free_inodes);
+-		atomic_add(ext4_free_blks_count(sb, gdp),
++		atomic_add(ext4_free_group_clusters(sb, gdp),
+ 			   &sbi->s_flex_groups[flex_group].free_clusters);
+ 		atomic_add(ext4_used_dirs_count(sb, gdp),
+ 			   &sbi->s_flex_groups[flex_group].used_dirs);

commit 6f16b60690ba04cf476480a6f19b204e4b95b4a6
+Author: Theodore Ts'o 
+Date:   Fri Sep 9 19:06:51 2011 -0400
+
+    ext4: enable mounting bigalloc as read/write
+    
+    Now that we have implemented all of the changes needed for bigalloc,
+    we can finally enable it!
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index a6307f7c9807..a5a7e369f719 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1439,7 +1439,8 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei)
+ 					 EXT4_FEATURE_RO_COMPAT_DIR_NLINK | \
+ 					 EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE | \
+ 					 EXT4_FEATURE_RO_COMPAT_BTREE_DIR |\
+-					 EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
++					 EXT4_FEATURE_RO_COMPAT_HUGE_FILE |\
++					 EXT4_FEATURE_RO_COMPAT_BIGALLOC)
+ 
+ /*
+  * Default values for user and/or group using reserved blocks

commit 27baebb849d46d901e756e6502b0a65a62e43771
+Author: Theodore Ts'o 
+Date:   Fri Sep 9 19:02:51 2011 -0400
+
+    ext4: tune mballoc's default group prealloc size for bigalloc file systems
+    
+    The default group preallocation size had been previously set to 512
+    blocks/clusters, regardless of the block/cluster size.  This is
+    probably too big for large cluster sizes.  So adjust the default so
+    that it is 2 megabytes or 32 clusters, whichever is larger.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index f8e37cf2c2dd..63dd56703342 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -126,7 +126,8 @@
+  * list. In case of inode preallocation we follow a list of heuristics
+  * based on file size. This can be found in ext4_mb_normalize_request. If
+  * we are doing a group prealloc we try to normalize the request to
+- * sbi->s_mb_group_prealloc. Default value of s_mb_group_prealloc is
++ * sbi->s_mb_group_prealloc.  The default value of s_mb_group_prealloc is
++ * dependent on the cluster size; for non-bigalloc file systems, it is
+  * 512 blocks. This can be tuned via
+  * /sys/fs/ext4//mb_group_prealloc. The value is represented in
+  * terms of number of blocks. If we have mounted the file system with -O
+@@ -2473,7 +2474,20 @@ int ext4_mb_init(struct super_block *sb, int needs_recovery)
+ 	sbi->s_mb_stats = MB_DEFAULT_STATS;
+ 	sbi->s_mb_stream_request = MB_DEFAULT_STREAM_THRESHOLD;
+ 	sbi->s_mb_order2_reqs = MB_DEFAULT_ORDER2_REQS;
+-	sbi->s_mb_group_prealloc = MB_DEFAULT_GROUP_PREALLOC;
++	/*
++	 * The default group preallocation is 512, which for 4k block
++	 * sizes translates to 2 megabytes.  However for bigalloc file
++	 * systems, this is probably too big (i.e, if the cluster size
++	 * is 1 megabyte, then group preallocation size becomes half a
++	 * gigabyte!).  As a default, we will keep a two megabyte
++	 * group pralloc size for cluster sizes up to 64k, and after
++	 * that, we will force a minimum group preallocation size of
++	 * 32 clusters.  This translates to 8 megs when the cluster
++	 * size is 256k, and 32 megs when the cluster size is 1 meg,
++	 * which seems reasonable as a default.
++	 */
++	sbi->s_mb_group_prealloc = max(MB_DEFAULT_GROUP_PREALLOC >>
++				       sbi->s_cluster_bits, 32);
+ 	/*
+ 	 * If there is a s_stripe > 1, then we set the s_mb_group_prealloc
+ 	 * to the lowest multiple of s_stripe which is bigger than

commit f975d6bcc7a698a10cc755115e27d3612dcfe322
+Author: Theodore Ts'o 
+Date:   Fri Sep 9 19:00:51 2011 -0400
+
+    ext4: teach ext4_statfs() to deal with clusters if bigalloc is enabled
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index d7e0e045b11b..6810957e0ac7 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4580,16 +4580,34 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 	return err;
+ }
+ 
++/*
++ * Note: calculating the overhead so we can be compatible with
++ * historical BSD practice is quite difficult in the face of
++ * clusters/bigalloc.  This is because multiple metadata blocks from
++ * different block group can end up in the same allocation cluster.
++ * Calculating the exact overhead in the face of clustered allocation
++ * requires either O(all block bitmaps) in memory or O(number of block
++ * groups**2) in time.  We will still calculate the superblock for
++ * older file systems --- and if we come across with a bigalloc file
++ * system with zero in s_overhead_clusters the estimate will be close to
++ * correct especially for very large cluster sizes --- but for newer
++ * file systems, it's better to calculate this figure once at mkfs
++ * time, and store it in the superblock.  If the superblock value is
++ * present (even for non-bigalloc file systems), we will use it.
++ */
+ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
+ {
+ 	struct super_block *sb = dentry->d_sb;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	struct ext4_super_block *es = sbi->s_es;
++	struct ext4_group_desc *gdp;
+ 	u64 fsid;
+ 	s64 bfree;
+ 
+ 	if (test_opt(sb, MINIX_DF)) {
+ 		sbi->s_overhead_last = 0;
++	} else if (es->s_overhead_clusters) {
++		sbi->s_overhead_last = le32_to_cpu(es->s_overhead_clusters);
+ 	} else if (sbi->s_blocks_last != ext4_blocks_count(es)) {
+ 		ext4_group_t i, ngroups = ext4_get_groups_count(sb);
+ 		ext4_fsblk_t overhead = 0;
+@@ -4604,24 +4622,16 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
+ 		 * All of the blocks before first_data_block are
+ 		 * overhead
+ 		 */
+-		overhead = le32_to_cpu(es->s_first_data_block);
++		overhead = EXT4_B2C(sbi, le32_to_cpu(es->s_first_data_block));
+ 
+ 		/*
+-		 * Add the overhead attributed to the superblock and
+-		 * block group descriptors.  If the sparse superblocks
+-		 * feature is turned on, then not all groups have this.
++		 * Add the overhead found in each block group
+ 		 */
+ 		for (i = 0; i < ngroups; i++) {
+-			overhead += ext4_bg_has_super(sb, i) +
+-				ext4_bg_num_gdb(sb, i);
++			gdp = ext4_get_group_desc(sb, i, NULL);
++			overhead += ext4_num_overhead_clusters(sb, i, gdp);
+ 			cond_resched();
+ 		}
+-
+-		/*
+-		 * Every block group has an inode bitmap, a block
+-		 * bitmap, and an inode table.
+-		 */
+-		overhead += ngroups * (2 + sbi->s_itb_per_group);
+ 		sbi->s_overhead_last = overhead;
+ 		smp_wmb();
+ 		sbi->s_blocks_last = ext4_blocks_count(es);
+@@ -4629,7 +4639,8 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
+ 
+ 	buf->f_type = EXT4_SUPER_MAGIC;
+ 	buf->f_bsize = sb->s_blocksize;
+-	buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last;
++	buf->f_blocks = (ext4_blocks_count(es) -
++			 EXT4_C2B(sbi, sbi->s_overhead_last));
+ 	bfree = percpu_counter_sum_positive(&sbi->s_freeclusters_counter) -
+ 		percpu_counter_sum_positive(&sbi->s_dirtyclusters_counter);
+ 	/* prevent underflow in case that few free space is available */

commit 24aaa8ef4e2b5764ada1fc69787e2fbd4f6276e5
+Author: Theodore Ts'o 
+Date:   Fri Sep 9 18:58:51 2011 -0400
+
+    ext4: convert the free_blocks field in s_flex_groups to be free_clusters
+    
+    Convert the free_blocks to be free_clusters to make the final revised
+    bigalloc changes easier to read/understand.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index c7588366471c..d2584224c89a 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -300,7 +300,7 @@ struct ext4_group_desc
+ 
+ struct flex_groups {
+ 	atomic_t free_inodes;
+-	atomic_t free_blocks;
++	atomic_t free_clusters;
+ 	atomic_t used_dirs;
+ };
+ 
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 58115bad163f..0be5862313f0 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -346,7 +346,7 @@ static int find_group_flex(struct super_block *sb, struct inode *parent,
+ 	int flex_size = ext4_flex_bg_size(sbi);
+ 	ext4_group_t best_flex = parent_fbg_group;
+ 	int blocks_per_flex = sbi->s_blocks_per_group * flex_size;
+-	int flexbg_free_blocks;
++	int flexbg_free_clusters;
+ 	int flex_freeb_ratio;
+ 	ext4_group_t n_fbg_groups;
+ 	ext4_group_t i;
+@@ -355,8 +355,9 @@ static int find_group_flex(struct super_block *sb, struct inode *parent,
+ 		sbi->s_log_groups_per_flex;
+ 
+ find_close_to_parent:
+-	flexbg_free_blocks = atomic_read(&flex_group[best_flex].free_blocks);
+-	flex_freeb_ratio = flexbg_free_blocks * 100 / blocks_per_flex;
++	flexbg_free_clusters = atomic_read(&flex_group[best_flex].free_clusters);
++	flex_freeb_ratio = EXT4_C2B(sbi, flexbg_free_clusters) * 100 /
++		blocks_per_flex;
+ 	if (atomic_read(&flex_group[best_flex].free_inodes) &&
+ 	    flex_freeb_ratio > free_block_ratio)
+ 		goto found_flexbg;
+@@ -370,8 +371,9 @@ static int find_group_flex(struct super_block *sb, struct inode *parent,
+ 		if (i == parent_fbg_group || i == parent_fbg_group - 1)
+ 			continue;
+ 
+-		flexbg_free_blocks = atomic_read(&flex_group[i].free_blocks);
+-		flex_freeb_ratio = flexbg_free_blocks * 100 / blocks_per_flex;
++		flexbg_free_clusters = atomic_read(&flex_group[i].free_clusters);
++		flex_freeb_ratio = EXT4_C2B(sbi, flexbg_free_clusters) * 100 /
++			blocks_per_flex;
+ 
+ 		if (flex_freeb_ratio > free_block_ratio &&
+ 		    (atomic_read(&flex_group[i].free_inodes))) {
+@@ -380,14 +382,14 @@ static int find_group_flex(struct super_block *sb, struct inode *parent,
+ 		}
+ 
+ 		if ((atomic_read(&flex_group[best_flex].free_inodes) == 0) ||
+-		    ((atomic_read(&flex_group[i].free_blocks) >
+-		      atomic_read(&flex_group[best_flex].free_blocks)) &&
++		    ((atomic_read(&flex_group[i].free_clusters) >
++		      atomic_read(&flex_group[best_flex].free_clusters)) &&
+ 		     atomic_read(&flex_group[i].free_inodes)))
+ 			best_flex = i;
+ 	}
+ 
+ 	if (!atomic_read(&flex_group[best_flex].free_inodes) ||
+-	    !atomic_read(&flex_group[best_flex].free_blocks))
++	    !atomic_read(&flex_group[best_flex].free_clusters))
+ 		return -1;
+ 
+ found_flexbg:
+@@ -407,7 +409,7 @@ static int find_group_flex(struct super_block *sb, struct inode *parent,
+ 
+ struct orlov_stats {
+ 	__u32 free_inodes;
+-	__u32 free_blocks;
++	__u32 free_clusters;
+ 	__u32 used_dirs;
+ };
+ 
+@@ -424,7 +426,7 @@ static void get_orlov_stats(struct super_block *sb, ext4_group_t g,
+ 
+ 	if (flex_size > 1) {
+ 		stats->free_inodes = atomic_read(&flex_group[g].free_inodes);
+-		stats->free_blocks = atomic_read(&flex_group[g].free_blocks);
++		stats->free_clusters = atomic_read(&flex_group[g].free_clusters);
+ 		stats->used_dirs = atomic_read(&flex_group[g].used_dirs);
+ 		return;
+ 	}
+@@ -432,11 +434,11 @@ static void get_orlov_stats(struct super_block *sb, ext4_group_t g,
+ 	desc = ext4_get_group_desc(sb, g, NULL);
+ 	if (desc) {
+ 		stats->free_inodes = ext4_free_inodes_count(sb, desc);
+-		stats->free_blocks = ext4_free_blks_count(sb, desc);
++		stats->free_clusters = ext4_free_blks_count(sb, desc);
+ 		stats->used_dirs = ext4_used_dirs_count(sb, desc);
+ 	} else {
+ 		stats->free_inodes = 0;
+-		stats->free_blocks = 0;
++		stats->free_clusters = 0;
+ 		stats->used_dirs = 0;
+ 	}
+ }
+@@ -471,10 +473,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
+ 	ext4_group_t real_ngroups = ext4_get_groups_count(sb);
+ 	int inodes_per_group = EXT4_INODES_PER_GROUP(sb);
+ 	unsigned int freei, avefreei;
+-	ext4_fsblk_t freeb, avefreeb;
++	ext4_fsblk_t freeb, avefreec;
+ 	unsigned int ndirs;
+ 	int max_dirs, min_inodes;
+-	ext4_grpblk_t min_blocks;
++	ext4_grpblk_t min_clusters;
+ 	ext4_group_t i, grp, g, ngroups;
+ 	struct ext4_group_desc *desc;
+ 	struct orlov_stats stats;
+@@ -492,8 +494,8 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
+ 	avefreei = freei / ngroups;
+ 	freeb = EXT4_C2B(sbi,
+ 		percpu_counter_read_positive(&sbi->s_freeclusters_counter));
+-	avefreeb = freeb;
+-	do_div(avefreeb, ngroups);
++	avefreec = freeb;
++	do_div(avefreec, ngroups);
+ 	ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter);
+ 
+ 	if (S_ISDIR(mode) &&
+@@ -519,7 +521,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
+ 				continue;
+ 			if (stats.free_inodes < avefreei)
+ 				continue;
+-			if (stats.free_blocks < avefreeb)
++			if (stats.free_clusters < avefreec)
+ 				continue;
+ 			grp = g;
+ 			ret = 0;
+@@ -557,7 +559,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
+ 	min_inodes = avefreei - inodes_per_group*flex_size / 4;
+ 	if (min_inodes < 1)
+ 		min_inodes = 1;
+-	min_blocks = avefreeb - EXT4_BLOCKS_PER_GROUP(sb)*flex_size / 4;
++	min_clusters = avefreec - EXT4_CLUSTERS_PER_GROUP(sb)*flex_size / 4;
+ 
+ 	/*
+ 	 * Start looking in the flex group where we last allocated an
+@@ -576,7 +578,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
+ 			continue;
+ 		if (stats.free_inodes < min_inodes)
+ 			continue;
+-		if (stats.free_blocks < min_blocks)
++		if (stats.free_clusters < min_clusters)
+ 			continue;
+ 		goto found_flex_bg;
+ 	}
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 4a38b65bd564..f8e37cf2c2dd 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2847,7 +2847,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
+ 		ext4_group_t flex_group = ext4_flex_group(sbi,
+ 							  ac->ac_b_ex.fe_group);
+ 		atomic_sub(ac->ac_b_ex.fe_len,
+-			   &sbi->s_flex_groups[flex_group].free_blocks);
++			   &sbi->s_flex_groups[flex_group].free_clusters);
+ 	}
+ 
+ 	err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
+@@ -4696,7 +4696,8 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 
+ 	if (sbi->s_log_groups_per_flex) {
+ 		ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
+-		atomic_add(count, &sbi->s_flex_groups[flex_group].free_blocks);
++		atomic_add(count_clusters,
++			   &sbi->s_flex_groups[flex_group].free_clusters);
+ 	}
+ 
+ 	ext4_mb_unload_buddy(&e4b);
+@@ -4839,8 +4840,8 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
+ 
+ 	if (sbi->s_log_groups_per_flex) {
+ 		ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
+-		atomic_add(blocks_freed,
+-			   &sbi->s_flex_groups[flex_group].free_blocks);
++		atomic_add(EXT4_B2C(sbi, blocks_freed),
++			   &sbi->s_flex_groups[flex_group].free_clusters);
+ 	}
+ 
+ 	ext4_mb_unload_buddy(&e4b);
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index a324a537f2dc..95a09ddca3b9 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -946,8 +946,8 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
+ 	    sbi->s_log_groups_per_flex) {
+ 		ext4_group_t flex_group;
+ 		flex_group = ext4_flex_group(sbi, input->group);
+-		atomic_add(input->free_blocks_count,
+-			   &sbi->s_flex_groups[flex_group].free_blocks);
++		atomic_add(EXT4_B2C(sbi, input->free_blocks_count),
++			   &sbi->s_flex_groups[flex_group].free_clusters);
+ 		atomic_add(EXT4_INODES_PER_GROUP(sb),
+ 			   &sbi->s_flex_groups[flex_group].free_inodes);
+ 	}
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index f81e7e791655..d7e0e045b11b 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2035,7 +2035,7 @@ static int ext4_fill_flex_info(struct super_block *sb)
+ 		atomic_add(ext4_free_inodes_count(sb, gdp),
+ 			   &sbi->s_flex_groups[flex_group].free_inodes);
+ 		atomic_add(ext4_free_blks_count(sb, gdp),
+-			   &sbi->s_flex_groups[flex_group].free_blocks);
++			   &sbi->s_flex_groups[flex_group].free_clusters);
+ 		atomic_add(ext4_used_dirs_count(sb, gdp),
+ 			   &sbi->s_flex_groups[flex_group].used_dirs);
+ 	}

commit 5704265188ffe4290ed73b3cb685206c3ed8209d
+Author: Theodore Ts'o 
+Date:   Fri Sep 9 18:56:51 2011 -0400
+
+    ext4: convert s_{dirty,free}blocks_counter to s_{dirty,free}clusters_counter
+    
+    Convert the percpu counters s_dirtyblocks_counter and
+    s_freeblocks_counter in struct ext4_super_info to be
+    s_dirtyclusters_counter and s_freeclusters_counter.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 89abf1f7b253..9080a857cda9 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -414,16 +414,16 @@ static int ext4_has_free_blocks(struct ext4_sb_info *sbi,
+ 				s64 nblocks, unsigned int flags)
+ {
+ 	s64 free_blocks, dirty_blocks, root_blocks;
+-	struct percpu_counter *fbc = &sbi->s_freeblocks_counter;
+-	struct percpu_counter *dbc = &sbi->s_dirtyblocks_counter;
++	struct percpu_counter *fcc = &sbi->s_freeclusters_counter;
++	struct percpu_counter *dbc = &sbi->s_dirtyclusters_counter;
+ 
+-	free_blocks  = percpu_counter_read_positive(fbc);
++	free_blocks  = percpu_counter_read_positive(fcc);
+ 	dirty_blocks = percpu_counter_read_positive(dbc);
+ 	root_blocks = ext4_r_blocks_count(sbi->s_es);
+ 
+ 	if (free_blocks - (nblocks + root_blocks + dirty_blocks) <
+ 						EXT4_FREEBLOCKS_WATERMARK) {
+-		free_blocks  = percpu_counter_sum_positive(fbc);
++		free_blocks  = EXT4_C2B(sbi, percpu_counter_sum_positive(fcc));
+ 		dirty_blocks = percpu_counter_sum_positive(dbc);
+ 	}
+ 	/* Check whether we have space after
+@@ -449,7 +449,7 @@ int ext4_claim_free_blocks(struct ext4_sb_info *sbi,
+ 			   s64 nblocks, unsigned int flags)
+ {
+ 	if (ext4_has_free_blocks(sbi, nblocks, flags)) {
+-		percpu_counter_add(&sbi->s_dirtyblocks_counter, nblocks);
++		percpu_counter_add(&sbi->s_dirtyclusters_counter, nblocks);
+ 		return 0;
+ 	} else
+ 		return -ENOSPC;
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 030bfc1cb59d..c7588366471c 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -855,6 +855,7 @@ struct ext4_inode_info {
+ 	ext4_group_t	i_last_alloc_group;
+ 
+ 	/* allocation reservation info for delalloc */
++	/* In case of bigalloc, these refer to clusters rather than blocks */
+ 	unsigned int i_reserved_data_blocks;
+ 	unsigned int i_reserved_meta_blocks;
+ 	unsigned int i_allocated_meta_blocks;
+@@ -1144,10 +1145,10 @@ struct ext4_sb_info {
+ 	u32 s_hash_seed[4];
+ 	int s_def_hash_version;
+ 	int s_hash_unsigned;	/* 3 if hash should be signed, 0 if not */
+-	struct percpu_counter s_freeblocks_counter;
++	struct percpu_counter s_freeclusters_counter;
+ 	struct percpu_counter s_freeinodes_counter;
+ 	struct percpu_counter s_dirs_counter;
+-	struct percpu_counter s_dirtyblocks_counter;
++	struct percpu_counter s_dirtyclusters_counter;
+ 	struct blockgroup_lock *s_blockgroup_lock;
+ 	struct proc_dir_entry *s_proc;
+ 	struct kobject s_kobj;
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index b7a8130d0af4..58115bad163f 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -490,7 +490,8 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
+ 
+ 	freei = percpu_counter_read_positive(&sbi->s_freeinodes_counter);
+ 	avefreei = freei / ngroups;
+-	freeb = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
++	freeb = EXT4_C2B(sbi,
++		percpu_counter_read_positive(&sbi->s_freeclusters_counter));
+ 	avefreeb = freeb;
+ 	do_div(avefreeb, ngroups);
+ 	ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter);
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 904a9a623dab..40f51aae42fe 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -281,7 +281,7 @@ void ext4_da_update_reserve_space(struct inode *inode,
+ 	/* Update per-inode reservations */
+ 	ei->i_reserved_data_blocks -= used;
+ 	ei->i_reserved_meta_blocks -= ei->i_allocated_meta_blocks;
+-	percpu_counter_sub(&sbi->s_dirtyblocks_counter,
++	percpu_counter_sub(&sbi->s_dirtyclusters_counter,
+ 			   used + ei->i_allocated_meta_blocks);
+ 	ei->i_allocated_meta_blocks = 0;
+ 
+@@ -291,7 +291,7 @@ void ext4_da_update_reserve_space(struct inode *inode,
+ 		 * only when we have written all of the delayed
+ 		 * allocation blocks.
+ 		 */
+-		percpu_counter_sub(&sbi->s_dirtyblocks_counter,
++		percpu_counter_sub(&sbi->s_dirtyclusters_counter,
+ 				   ei->i_reserved_meta_blocks);
+ 		ei->i_reserved_meta_blocks = 0;
+ 		ei->i_da_metadata_calc_len = 0;
+@@ -1119,14 +1119,14 @@ static void ext4_da_release_space(struct inode *inode, int to_free)
+ 		 * only when we have written all of the delayed
+ 		 * allocation blocks.
+ 		 */
+-		percpu_counter_sub(&sbi->s_dirtyblocks_counter,
++		percpu_counter_sub(&sbi->s_dirtyclusters_counter,
+ 				   ei->i_reserved_meta_blocks);
+ 		ei->i_reserved_meta_blocks = 0;
+ 		ei->i_da_metadata_calc_len = 0;
+ 	}
+ 
+ 	/* update fs dirty data blocks counter */
+-	percpu_counter_sub(&sbi->s_dirtyblocks_counter, to_free);
++	percpu_counter_sub(&sbi->s_dirtyclusters_counter, to_free);
+ 
+ 	spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+ 
+@@ -1349,9 +1349,10 @@ static void ext4_print_free_blocks(struct inode *inode)
+ 	       ext4_count_free_blocks(inode->i_sb));
+ 	printk(KERN_CRIT "Free/Dirty block details\n");
+ 	printk(KERN_CRIT "free_blocks=%lld\n",
+-	       (long long) percpu_counter_sum(&sbi->s_freeblocks_counter));
++	       (long long) EXT4_C2B(EXT4_SB(inode->i_sb),
++		percpu_counter_sum(&sbi->s_freeclusters_counter)));
+ 	printk(KERN_CRIT "dirty_blocks=%lld\n",
+-	       (long long) percpu_counter_sum(&sbi->s_dirtyblocks_counter));
++	       (long long) percpu_counter_sum(&sbi->s_dirtyclusters_counter));
+ 	printk(KERN_CRIT "Block reservation details\n");
+ 	printk(KERN_CRIT "i_reserved_data_blocks=%u\n",
+ 	       EXT4_I(inode)->i_reserved_data_blocks);
+@@ -2226,8 +2227,9 @@ static int ext4_nonda_switch(struct super_block *sb)
+ 	 * Delalloc need an accurate free block accounting. So switch
+ 	 * to non delalloc when we are near to error range.
+ 	 */
+-	free_blocks  = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
+-	dirty_blocks = percpu_counter_read_positive(&sbi->s_dirtyblocks_counter);
++	free_blocks  = EXT4_C2B(sbi,
++		percpu_counter_read_positive(&sbi->s_freeclusters_counter));
++	dirty_blocks = percpu_counter_read_positive(&sbi->s_dirtyclusters_counter);
+ 	if (2 * free_blocks < 3 * dirty_blocks ||
+ 		free_blocks < (dirty_blocks + EXT4_FREEBLOCKS_WATERMARK)) {
+ 		/*
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 57ce6960e940..4a38b65bd564 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2834,13 +2834,14 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
+ 	gdp->bg_checksum = ext4_group_desc_csum(sbi, ac->ac_b_ex.fe_group, gdp);
+ 
+ 	ext4_unlock_group(sb, ac->ac_b_ex.fe_group);
+-	percpu_counter_sub(&sbi->s_freeblocks_counter, ac->ac_b_ex.fe_len);
++	percpu_counter_sub(&sbi->s_freeclusters_counter, ac->ac_b_ex.fe_len);
+ 	/*
+ 	 * Now reduce the dirty block count also. Should not go negative
+ 	 */
+ 	if (!(ac->ac_flags & EXT4_MB_DELALLOC_RESERVED))
+ 		/* release all the reserved blocks if non delalloc */
+-		percpu_counter_sub(&sbi->s_dirtyblocks_counter, reserv_clstrs);
++		percpu_counter_sub(&sbi->s_dirtyclusters_counter,
++				   reserv_clstrs);
+ 
+ 	if (sbi->s_log_groups_per_flex) {
+ 		ext4_group_t flex_group = ext4_flex_group(sbi,
+@@ -4384,7 +4385,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
+ 		if (!ext4_test_inode_state(ar->inode,
+ 					   EXT4_STATE_DELALLOC_RESERVED))
+ 			/* release all the reserved blocks if non delalloc */
+-			percpu_counter_sub(&sbi->s_dirtyblocks_counter,
++			percpu_counter_sub(&sbi->s_dirtyclusters_counter,
+ 						reserv_clstrs);
+ 	}
+ 
+@@ -4691,7 +4692,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 	ext4_free_blks_set(sb, gdp, ret);
+ 	gdp->bg_checksum = ext4_group_desc_csum(sbi, block_group, gdp);
+ 	ext4_unlock_group(sb, block_group);
+-	percpu_counter_add(&sbi->s_freeblocks_counter, count);
++	percpu_counter_add(&sbi->s_freeclusters_counter, count_clusters);
+ 
+ 	if (sbi->s_log_groups_per_flex) {
+ 		ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
+@@ -4833,7 +4834,8 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
+ 	ext4_free_blks_set(sb, desc, blk_free_count);
+ 	desc->bg_checksum = ext4_group_desc_csum(sbi, block_group, desc);
+ 	ext4_unlock_group(sb, block_group);
+-	percpu_counter_add(&sbi->s_freeblocks_counter, blocks_freed);
++	percpu_counter_add(&sbi->s_freeclusters_counter,
++			   EXT4_B2C(sbi, blocks_freed));
+ 
+ 	if (sbi->s_log_groups_per_flex) {
+ 		ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 707d3f16f7ce..a324a537f2dc 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -937,8 +937,8 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
+ 		input->reserved_blocks);
+ 
+ 	/* Update the free space counts */
+-	percpu_counter_add(&sbi->s_freeblocks_counter,
+-			   input->free_blocks_count);
++	percpu_counter_add(&sbi->s_freeclusters_counter,
++			   EXT4_B2C(sbi, input->free_blocks_count));
+ 	percpu_counter_add(&sbi->s_freeinodes_counter,
+ 			   EXT4_INODES_PER_GROUP(sb));
+ 
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 25a4bfe3f39f..f81e7e791655 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -837,10 +837,10 @@ static void ext4_put_super(struct super_block *sb)
+ 		brelse(sbi->s_group_desc[i]);
+ 	ext4_kvfree(sbi->s_group_desc);
+ 	ext4_kvfree(sbi->s_flex_groups);
+-	percpu_counter_destroy(&sbi->s_freeblocks_counter);
++	percpu_counter_destroy(&sbi->s_freeclusters_counter);
+ 	percpu_counter_destroy(&sbi->s_freeinodes_counter);
+ 	percpu_counter_destroy(&sbi->s_dirs_counter);
+-	percpu_counter_destroy(&sbi->s_dirtyblocks_counter);
++	percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
+ 	brelse(sbi->s_sbh);
+ #ifdef CONFIG_QUOTA
+ 	for (i = 0; i < MAXQUOTAS; i++)
+@@ -2473,7 +2473,7 @@ static ssize_t delayed_allocation_blocks_show(struct ext4_attr *a,
+ 					      char *buf)
+ {
+ 	return snprintf(buf, PAGE_SIZE, "%llu\n",
+-			(s64) percpu_counter_sum(&sbi->s_dirtyblocks_counter));
++		(s64) percpu_counter_sum(&sbi->s_dirtyclusters_counter));
+ }
+ 
+ static ssize_t session_write_kbytes_show(struct ext4_attr *a,
+@@ -3575,7 +3575,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	sbi->s_err_report.function = print_daily_error_info;
+ 	sbi->s_err_report.data = (unsigned long) sb;
+ 
+-	err = percpu_counter_init(&sbi->s_freeblocks_counter,
++	err = percpu_counter_init(&sbi->s_freeclusters_counter,
+ 			ext4_count_free_blocks(sb));
+ 	if (!err) {
+ 		err = percpu_counter_init(&sbi->s_freeinodes_counter,
+@@ -3586,7 +3586,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 				ext4_count_dirs(sb));
+ 	}
+ 	if (!err) {
+-		err = percpu_counter_init(&sbi->s_dirtyblocks_counter, 0);
++		err = percpu_counter_init(&sbi->s_dirtyclusters_counter, 0);
+ 	}
+ 	if (err) {
+ 		ext4_msg(sb, KERN_ERR, "insufficient memory");
+@@ -3701,13 +3701,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	 * The journal may have updated the bg summary counts, so we
+ 	 * need to update the global counters.
+ 	 */
+-	percpu_counter_set(&sbi->s_freeblocks_counter,
++	percpu_counter_set(&sbi->s_freeclusters_counter,
+ 			   ext4_count_free_blocks(sb));
+ 	percpu_counter_set(&sbi->s_freeinodes_counter,
+ 			   ext4_count_free_inodes(sb));
+ 	percpu_counter_set(&sbi->s_dirs_counter,
+ 			   ext4_count_dirs(sb));
+-	percpu_counter_set(&sbi->s_dirtyblocks_counter, 0);
++	percpu_counter_set(&sbi->s_dirtyclusters_counter, 0);
+ 
+ no_journal:
+ 	/*
+@@ -3847,10 +3847,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	del_timer(&sbi->s_err_report);
+ 	if (sbi->s_flex_groups)
+ 		ext4_kvfree(sbi->s_flex_groups);
+-	percpu_counter_destroy(&sbi->s_freeblocks_counter);
++	percpu_counter_destroy(&sbi->s_freeclusters_counter);
+ 	percpu_counter_destroy(&sbi->s_freeinodes_counter);
+ 	percpu_counter_destroy(&sbi->s_dirs_counter);
+-	percpu_counter_destroy(&sbi->s_dirtyblocks_counter);
++	percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
+ 	if (sbi->s_mmp_tsk)
+ 		kthread_stop(sbi->s_mmp_tsk);
+ failed_mount2:
+@@ -4173,8 +4173,9 @@ static int ext4_commit_super(struct super_block *sb, int sync)
+ 	else
+ 		es->s_kbytes_written =
+ 			cpu_to_le64(EXT4_SB(sb)->s_kbytes_written);
+-	ext4_free_blocks_count_set(es, percpu_counter_sum_positive(
+-					   &EXT4_SB(sb)->s_freeblocks_counter));
++	ext4_free_blocks_count_set(es,
++			EXT4_C2B(EXT4_SB(sb), percpu_counter_sum_positive(
++				&EXT4_SB(sb)->s_freeclusters_counter)));
+ 	es->s_free_inodes_count =
+ 		cpu_to_le32(percpu_counter_sum_positive(
+ 				&EXT4_SB(sb)->s_freeinodes_counter));
+@@ -4629,10 +4630,10 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
+ 	buf->f_type = EXT4_SUPER_MAGIC;
+ 	buf->f_bsize = sb->s_blocksize;
+ 	buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last;
+-	bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter) -
+-		       percpu_counter_sum_positive(&sbi->s_dirtyblocks_counter);
++	bfree = percpu_counter_sum_positive(&sbi->s_freeclusters_counter) -
++		percpu_counter_sum_positive(&sbi->s_dirtyclusters_counter);
+ 	/* prevent underflow in case that few free space is available */
+-	buf->f_bfree = max_t(s64, bfree, 0);
++	buf->f_bfree = EXT4_C2B(sbi, max_t(s64, bfree, 0));
+ 	buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es);
+ 	if (buf->f_bfree < ext4_r_blocks_count(es))
+ 		buf->f_bavail = 0;

commit 0aa060000e83ca3d09ddc446a7174fb0820d99bc
+Author: Theodore Ts'o 
+Date:   Fri Sep 9 18:54:51 2011 -0400
+
+    ext4: teach ext4_ext_truncate() about the bigalloc feature
+    
+    When we are truncating (as opposed unlinking) a file, we need to worry
+    about partial truncates of a file, especially in the light of sparse
+    files.  The changes here make sure that arbitrary truncates of sparse
+    files works correctly.  Yeah, it's messy.
+    
+    Note that these functions will need to be revisted when the punch
+    ioctl is integrated --- in fact this commit will probably have merge
+    conflicts with the punch changes which Allison Henders and the IBM LTC
+    have been working on.  I will need to fix this up when either patch
+    hits mainline.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index bd42ab29efec..cd4479c08031 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -2202,14 +2202,39 @@ int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks, int chunk)
+ }
+ 
+ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
+-				struct ext4_extent *ex,
+-				ext4_lblk_t from, ext4_lblk_t to)
++			      struct ext4_extent *ex,
++			      ext4_fsblk_t *partial_cluster,
++			      ext4_lblk_t from, ext4_lblk_t to)
+ {
++	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+ 	unsigned short ee_len =  ext4_ext_get_actual_len(ex);
++	ext4_fsblk_t pblk;
+ 	int flags = EXT4_FREE_BLOCKS_FORGET;
+ 
+ 	if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+ 		flags |= EXT4_FREE_BLOCKS_METADATA;
++	/*
++	 * For bigalloc file systems, we never free a partial cluster
++	 * at the beginning of the extent.  Instead, we make a note
++	 * that we tried freeing the cluster, and check to see if we
++	 * need to free it on a subsequent call to ext4_remove_blocks,
++	 * or at the end of the ext4_truncate() operation.
++	 */
++	flags |= EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER;
++
++	/*
++	 * If we have a partial cluster, and it's different from the
++	 * cluster of the last block, we need to explicitly free the
++	 * partial cluster here.
++	 */
++	pblk = ext4_ext_pblock(ex) + ee_len - 1;
++	if (*partial_cluster && (EXT4_B2C(sbi, pblk) != *partial_cluster)) {
++		ext4_free_blocks(handle, inode, NULL,
++				 EXT4_C2B(sbi, *partial_cluster),
++				 sbi->s_cluster_ratio, flags);
++		*partial_cluster = 0;
++	}
++
+ #ifdef EXTENTS_STATS
+ 	{
+ 		struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+@@ -2229,12 +2254,24 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
+ 	    && to == le32_to_cpu(ex->ee_block) + ee_len - 1) {
+ 		/* tail removal */
+ 		ext4_lblk_t num;
+-		ext4_fsblk_t start;
+ 
+ 		num = le32_to_cpu(ex->ee_block) + ee_len - from;
+-		start = ext4_ext_pblock(ex) + ee_len - num;
+-		ext_debug("free last %u blocks starting %llu\n", num, start);
+-		ext4_free_blocks(handle, inode, NULL, start, num, flags);
++		pblk = ext4_ext_pblock(ex) + ee_len - num;
++		ext_debug("free last %u blocks starting %llu\n", num, pblk);
++		ext4_free_blocks(handle, inode, NULL, pblk, num, flags);
++		/*
++		 * If the block range to be freed didn't start at the
++		 * beginning of a cluster, and we removed the entire
++		 * extent, save the partial cluster here, since we
++		 * might need to delete if we determine that the
++		 * truncate operation has removed all of the blocks in
++		 * the cluster.
++		 */
++		if (pblk & (sbi->s_cluster_ratio - 1) &&
++		    (ee_len == num))
++			*partial_cluster = EXT4_B2C(sbi, pblk);
++		else
++			*partial_cluster = 0;
+ 	} else if (from == le32_to_cpu(ex->ee_block)
+ 		   && to <= le32_to_cpu(ex->ee_block) + ee_len - 1) {
+ 		/* head removal */
+@@ -2269,9 +2306,10 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
+  */
+ static int
+ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
+-		struct ext4_ext_path *path, ext4_lblk_t start,
+-		ext4_lblk_t end)
++		 struct ext4_ext_path *path, ext4_fsblk_t *partial_cluster,
++		 ext4_lblk_t start, ext4_lblk_t end)
+ {
++	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+ 	int err = 0, correct_index = 0;
+ 	int depth = ext_depth(inode), credits;
+ 	struct ext4_extent_header *eh;
+@@ -2423,7 +2461,8 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
+ 		if (err)
+ 			goto out;
+ 
+-		err = ext4_remove_blocks(handle, inode, ex, a, b);
++		err = ext4_remove_blocks(handle, inode, ex, partial_cluster,
++					 a, b);
+ 		if (err)
+ 			goto out;
+ 
+@@ -2471,7 +2510,8 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
+ 					sizeof(struct ext4_extent));
+ 			}
+ 			le16_add_cpu(&eh->eh_entries, -1);
+-		}
++		} else
++			*partial_cluster = 0;
+ 
+ 		ext_debug("new extent: %u:%u:%llu\n", block, num,
+ 				ext4_ext_pblock(ex));
+@@ -2483,6 +2523,25 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
+ 	if (correct_index && eh->eh_entries)
+ 		err = ext4_ext_correct_indexes(handle, inode, path);
+ 
++	/*
++	 * If there is still a entry in the leaf node, check to see if
++	 * it references the partial cluster.  This is the only place
++	 * where it could; if it doesn't, we can free the cluster.
++	 */
++	if (*partial_cluster && ex >= EXT_FIRST_EXTENT(eh) &&
++	    (EXT4_B2C(sbi, ext4_ext_pblock(ex) + ex_ee_len - 1) !=
++	     *partial_cluster)) {
++		int flags = EXT4_FREE_BLOCKS_FORGET;
++
++		if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
++			flags |= EXT4_FREE_BLOCKS_METADATA;
++
++		ext4_free_blocks(handle, inode, NULL,
++				 EXT4_C2B(sbi, *partial_cluster),
++				 sbi->s_cluster_ratio, flags);
++		*partial_cluster = 0;
++	}
++
+ 	/* if this leaf is free, then we should
+ 	 * remove it from index block above */
+ 	if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL)
+@@ -2518,6 +2577,7 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start)
+ 	struct super_block *sb = inode->i_sb;
+ 	int depth = ext_depth(inode);
+ 	struct ext4_ext_path *path;
++	ext4_fsblk_t partial_cluster = 0;
+ 	handle_t *handle;
+ 	int i, err;
+ 
+@@ -2553,7 +2613,8 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start)
+ 		if (i == depth) {
+ 			/* this is leaf block */
+ 			err = ext4_ext_rm_leaf(handle, inode, path,
+-					start, EXT_MAX_BLOCKS - 1);
++					       &partial_cluster, start,
++					       EXT_MAX_BLOCKS - 1);
+ 			/* root level has p_bh == NULL, brelse() eats this */
+ 			brelse(path[i].p_bh);
+ 			path[i].p_bh = NULL;
+@@ -3495,6 +3556,8 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 		ee_len = ext4_ext_get_actual_len(ex);
+ 		/* if found extent covers block, simply return it */
+ 		if (in_range(map->m_lblk, ee_block, ee_len)) {
++			ext4_fsblk_t partial_cluster = 0;
++
+ 			newblock = map->m_lblk - ee_block + ee_start;
+ 			/* number of remaining blocks in the extent */
+ 			allocated = ee_len - (map->m_lblk - ee_block);
+@@ -3578,7 +3641,8 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 			ext4_ext_invalidate_cache(inode);
+ 
+ 			err = ext4_ext_rm_leaf(handle, inode, path,
+-				map->m_lblk, map->m_lblk + punched_out);
++					       &partial_cluster, map->m_lblk,
++					       map->m_lblk + punched_out);
+ 
+ 			if (!err && path->p_hdr->eh_entries == 0) {
+ 				/*

commit 4d33b1ef10995d7ba6191d67456202c697a92a32
+Author: Theodore Ts'o 
+Date:   Fri Sep 9 18:52:51 2011 -0400
+
+    ext4: teach ext4_ext_map_blocks() about the bigalloc feature
+    
+    If we need to allocate a new block in ext4_ext_map_blocks(), the
+    function needs to see if the cluster has already been allocated.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index ba7bd5a176ce..bd42ab29efec 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -1270,7 +1270,8 @@ static int ext4_ext_search_left(struct inode *inode,
+  */
+ static int ext4_ext_search_right(struct inode *inode,
+ 				 struct ext4_ext_path *path,
+-				 ext4_lblk_t *logical, ext4_fsblk_t *phys)
++				 ext4_lblk_t *logical, ext4_fsblk_t *phys,
++				 struct ext4_extent **ret_ex)
+ {
+ 	struct buffer_head *bh = NULL;
+ 	struct ext4_extent_header *eh;
+@@ -1312,9 +1313,7 @@ static int ext4_ext_search_right(struct inode *inode,
+ 				return -EIO;
+ 			}
+ 		}
+-		*logical = le32_to_cpu(ex->ee_block);
+-		*phys = ext4_ext_pblock(ex);
+-		return 0;
++		goto found_extent;
+ 	}
+ 
+ 	if (unlikely(*logical < (le32_to_cpu(ex->ee_block) + ee_len))) {
+@@ -1327,9 +1326,7 @@ static int ext4_ext_search_right(struct inode *inode,
+ 	if (ex != EXT_LAST_EXTENT(path[depth].p_hdr)) {
+ 		/* next allocated block in this leaf */
+ 		ex++;
+-		*logical = le32_to_cpu(ex->ee_block);
+-		*phys = ext4_ext_pblock(ex);
+-		return 0;
++		goto found_extent;
+ 	}
+ 
+ 	/* go up and search for index to the right */
+@@ -1372,9 +1369,12 @@ static int ext4_ext_search_right(struct inode *inode,
+ 		return -EIO;
+ 	}
+ 	ex = EXT_FIRST_EXTENT(eh);
++found_extent:
+ 	*logical = le32_to_cpu(ex->ee_block);
+ 	*phys = ext4_ext_pblock(ex);
+-	put_bh(bh);
++	*ret_ex = ex;
++	if (bh)
++		put_bh(bh);
+ 	return 0;
+ }
+ 
+@@ -1627,7 +1627,8 @@ static int ext4_ext_try_to_merge(struct inode *inode,
+  * such that there will be no overlap, and then returns 1.
+  * If there is no overlap found, it returns 0.
+  */
+-static unsigned int ext4_ext_check_overlap(struct inode *inode,
++static unsigned int ext4_ext_check_overlap(struct ext4_sb_info *sbi,
++					   struct inode *inode,
+ 					   struct ext4_extent *newext,
+ 					   struct ext4_ext_path *path)
+ {
+@@ -1641,6 +1642,7 @@ static unsigned int ext4_ext_check_overlap(struct inode *inode,
+ 	if (!path[depth].p_ext)
+ 		goto out;
+ 	b2 = le32_to_cpu(path[depth].p_ext->ee_block);
++	b2 &= ~(sbi->s_cluster_ratio - 1);
+ 
+ 	/*
+ 	 * get the next allocated block if the extent in the path
+@@ -1650,6 +1652,7 @@ static unsigned int ext4_ext_check_overlap(struct inode *inode,
+ 		b2 = ext4_ext_next_allocated_block(path);
+ 		if (b2 == EXT_MAX_BLOCKS)
+ 			goto out;
++		b2 &= ~(sbi->s_cluster_ratio - 1);
+ 	}
+ 
+ 	/* check for wrap through zero on extent logical start block*/
+@@ -3293,6 +3296,106 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
+ 	return err ? err : allocated;
+ }
+ 
++/*
++ * get_implied_cluster_alloc - check to see if the requested
++ * allocation (in the map structure) overlaps with a cluster already
++ * allocated in an extent.
++ *	@sbi	The ext4-specific superblock structure
++ *	@map	The requested lblk->pblk mapping
++ *	@ex	The extent structure which might contain an implied
++ *			cluster allocation
++ *
++ * This function is called by ext4_ext_map_blocks() after we failed to
++ * find blocks that were already in the inode's extent tree.  Hence,
++ * we know that the beginning of the requested region cannot overlap
++ * the extent from the inode's extent tree.  There are three cases we
++ * want to catch.  The first is this case:
++ *
++ *		 |--- cluster # N--|
++ *    |--- extent ---|	|---- requested region ---|
++ *			|==========|
++ *
++ * The second case that we need to test for is this one:
++ *
++ *   |--------- cluster # N ----------------|
++ *	   |--- requested region --|   |------- extent ----|
++ *	   |=======================|
++ *
++ * The third case is when the requested region lies between two extents
++ * within the same cluster:
++ *          |------------- cluster # N-------------|
++ * |----- ex -----|                  |---- ex_right ----|
++ *                  |------ requested region ------|
++ *                  |================|
++ *
++ * In each of the above cases, we need to set the map->m_pblk and
++ * map->m_len so it corresponds to the return the extent labelled as
++ * "|====|" from cluster #N, since it is already in use for data in
++ * cluster EXT4_B2C(sbi, map->m_lblk).	We will then return 1 to
++ * signal to ext4_ext_map_blocks() that map->m_pblk should be treated
++ * as a new "allocated" block region.  Otherwise, we will return 0 and
++ * ext4_ext_map_blocks() will then allocate one or more new clusters
++ * by calling ext4_mb_new_blocks().
++ */
++static int get_implied_cluster_alloc(struct ext4_sb_info *sbi,
++				     struct ext4_map_blocks *map,
++				     struct ext4_extent *ex,
++				     struct ext4_ext_path *path)
++{
++	ext4_lblk_t c_offset = map->m_lblk & (sbi->s_cluster_ratio-1);
++	ext4_lblk_t ex_cluster_start, ex_cluster_end;
++	ext4_lblk_t rr_cluster_start, rr_cluster_end;
++	ext4_lblk_t ee_block = le32_to_cpu(ex->ee_block);
++	ext4_fsblk_t ee_start = ext4_ext_pblock(ex);
++	unsigned short ee_len = ext4_ext_get_actual_len(ex);
++
++	/* The extent passed in that we are trying to match */
++	ex_cluster_start = EXT4_B2C(sbi, ee_block);
++	ex_cluster_end = EXT4_B2C(sbi, ee_block + ee_len - 1);
++
++	/* The requested region passed into ext4_map_blocks() */
++	rr_cluster_start = EXT4_B2C(sbi, map->m_lblk);
++	rr_cluster_end = EXT4_B2C(sbi, map->m_lblk + map->m_len - 1);
++
++	if ((rr_cluster_start == ex_cluster_end) ||
++	    (rr_cluster_start == ex_cluster_start)) {
++		if (rr_cluster_start == ex_cluster_end)
++			ee_start += ee_len - 1;
++		map->m_pblk = (ee_start & ~(sbi->s_cluster_ratio - 1)) +
++			c_offset;
++		map->m_len = min(map->m_len,
++				 (unsigned) sbi->s_cluster_ratio - c_offset);
++		/*
++		 * Check for and handle this case:
++		 *
++		 *   |--------- cluster # N-------------|
++		 *		       |------- extent ----|
++		 *	   |--- requested region ---|
++		 *	   |===========|
++		 */
++
++		if (map->m_lblk < ee_block)
++			map->m_len = min(map->m_len, ee_block - map->m_lblk);
++
++		/*
++		 * Check for the case where there is already another allocated
++		 * block to the right of 'ex' but before the end of the cluster.
++		 *
++		 *          |------------- cluster # N-------------|
++		 * |----- ex -----|                  |---- ex_right ----|
++		 *                  |------ requested region ------|
++		 *                  |================|
++		 */
++		if (map->m_lblk > ee_block) {
++			ext4_lblk_t next = ext4_ext_next_allocated_block(path);
++			map->m_len = min(map->m_len, next - map->m_lblk);
++		}
++		return 1;
++	}
++	return 0;
++}
++
++
+ /*
+  * Block allocation/map/preallocation routine for extents based files
+  *
+@@ -3315,14 +3418,16 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 			struct ext4_map_blocks *map, int flags)
+ {
+ 	struct ext4_ext_path *path = NULL;
+-	struct ext4_extent newex, *ex;
++	struct ext4_extent newex, *ex, *ex2;
++	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+ 	ext4_fsblk_t newblock = 0;
+-	int err = 0, depth, ret;
+-	unsigned int allocated = 0;
++	int free_on_err = 0, err = 0, depth, ret;
++	unsigned int allocated = 0, offset = 0;
+ 	unsigned int punched_out = 0;
+ 	unsigned int result = 0;
+ 	struct ext4_allocation_request ar;
+ 	ext4_io_end_t *io = EXT4_I(inode)->cur_aio_dio;
++	ext4_lblk_t cluster_offset;
+ 	struct ext4_map_blocks punch_map;
+ 
+ 	ext_debug("blocks %u/%u requested for inode %lu\n",
+@@ -3508,9 +3613,23 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 		ext4_ext_put_gap_in_cache(inode, path, map->m_lblk);
+ 		goto out2;
+ 	}
++
+ 	/*
+ 	 * Okay, we need to do block allocation.
+ 	 */
++	newex.ee_block = cpu_to_le32(map->m_lblk);
++	cluster_offset = map->m_lblk & (sbi->s_cluster_ratio-1);
++
++	/*
++	 * If we are doing bigalloc, check to see if the extent returned
++	 * by ext4_ext_find_extent() implies a cluster we can use.
++	 */
++	if (cluster_offset && ex &&
++	    get_implied_cluster_alloc(sbi, map, ex, path)) {
++		ar.len = allocated = map->m_len;
++		newblock = map->m_pblk;
++		goto got_allocated_blocks;
++	}
+ 
+ 	/* find neighbour allocated blocks */
+ 	ar.lleft = map->m_lblk;
+@@ -3518,10 +3637,20 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 	if (err)
+ 		goto out2;
+ 	ar.lright = map->m_lblk;
+-	err = ext4_ext_search_right(inode, path, &ar.lright, &ar.pright);
++	ex2 = NULL;
++	err = ext4_ext_search_right(inode, path, &ar.lright, &ar.pright, &ex2);
+ 	if (err)
+ 		goto out2;
+ 
++	/* Check if the extent after searching to the right implies a
++	 * cluster we can use. */
++	if ((sbi->s_cluster_ratio > 1) && ex2 &&
++	    get_implied_cluster_alloc(sbi, map, ex2, path)) {
++		ar.len = allocated = map->m_len;
++		newblock = map->m_pblk;
++		goto got_allocated_blocks;
++	}
++
+ 	/*
+ 	 * See if request is beyond maximum number of blocks we can have in
+ 	 * a single extent. For an initialized extent this limit is
+@@ -3536,9 +3665,8 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 		map->m_len = EXT_UNINIT_MAX_LEN;
+ 
+ 	/* Check if we can really insert (m_lblk)::(m_lblk + m_len) extent */
+-	newex.ee_block = cpu_to_le32(map->m_lblk);
+ 	newex.ee_len = cpu_to_le16(map->m_len);
+-	err = ext4_ext_check_overlap(inode, &newex, path);
++	err = ext4_ext_check_overlap(sbi, inode, &newex, path);
+ 	if (err)
+ 		allocated = ext4_ext_get_actual_len(&newex);
+ 	else
+@@ -3548,7 +3676,18 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 	ar.inode = inode;
+ 	ar.goal = ext4_ext_find_goal(inode, path, map->m_lblk);
+ 	ar.logical = map->m_lblk;
+-	ar.len = allocated;
++	/*
++	 * We calculate the offset from the beginning of the cluster
++	 * for the logical block number, since when we allocate a
++	 * physical cluster, the physical block should start at the
++	 * same offset from the beginning of the cluster.  This is
++	 * needed so that future calls to get_implied_cluster_alloc()
++	 * work correctly.
++	 */
++	offset = map->m_lblk & (sbi->s_cluster_ratio - 1);
++	ar.len = EXT4_NUM_B2C(sbi, offset+allocated);
++	ar.goal -= offset;
++	ar.logical -= offset;
+ 	if (S_ISREG(inode->i_mode))
+ 		ar.flags = EXT4_MB_HINT_DATA;
+ 	else
+@@ -3561,9 +3700,14 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 		goto out2;
+ 	ext_debug("allocate new block: goal %llu, found %llu/%u\n",
+ 		  ar.goal, newblock, allocated);
++	free_on_err = 1;
++	ar.len = EXT4_C2B(sbi, ar.len) - offset;
++	if (ar.len > allocated)
++		ar.len = allocated;
+ 
++got_allocated_blocks:
+ 	/* try to insert new extent into found leaf and return */
+-	ext4_ext_store_pblock(&newex, newblock);
++	ext4_ext_store_pblock(&newex, newblock + offset);
+ 	newex.ee_len = cpu_to_le16(ar.len);
+ 	/* Mark uninitialized */
+ 	if (flags & EXT4_GET_BLOCKS_UNINIT_EXT){
+@@ -3591,7 +3735,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 	if (!err)
+ 		err = ext4_ext_insert_extent(handle, inode, path,
+ 					     &newex, flags);
+-	if (err) {
++	if (err && free_on_err) {
+ 		int fb_flags = flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE ?
+ 			EXT4_FREE_BLOCKS_NO_QUOT_UPDATE : 0;
+ 		/* free data blocks we just allocated */
+@@ -4115,7 +4259,6 @@ static int ext4_ext_fiemap_cb(struct inode *inode, ext4_lblk_t next,
+ 		return EXT_BREAK;
+ 	return EXT_CONTINUE;
+ }
+-
+ /* fiemap flags we can handle specified here */
+ #define EXT4_FIEMAP_FLAGS	(FIEMAP_FLAG_SYNC|FIEMAP_FLAG_XATTR)
+ 

commit 84130193e0e6568dfdfb823f0e1e19aec80aff6e
+Author: Theodore Ts'o 
+Date:   Fri Sep 9 18:50:51 2011 -0400
+
+    ext4: teach ext4_free_blocks() about bigalloc and clusters
+    
+    The ext4_free_blocks() function now has two new flags that indicate
+    whether a partial cluster at the beginning or the end of the block
+    extents should be freed or not.  That will be up the caller (i.e.,
+    truncate), who can figure out whether partial clusters at the
+    beginning or the end of a block range can be freed.
+    
+    We also have to update the ext4_mb_free_metadata() and
+    release_blocks_on_commit() machinery to be cluster-based, since it is
+    used by ext4_free_blocks().
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 803cfa42e1e8..030bfc1cb59d 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -539,6 +539,8 @@ struct ext4_new_group_data {
+ #define EXT4_FREE_BLOCKS_FORGET		0x0002
+ #define EXT4_FREE_BLOCKS_VALIDATED	0x0004
+ #define EXT4_FREE_BLOCKS_NO_QUOT_UPDATE	0x0008
++#define EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER	0x0010
++#define EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER	0x0020
+ 
+ /*
+  * Flags used by ext4_discard_partial_page_buffers
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 8765f2512f13..57ce6960e940 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2602,11 +2602,13 @@ int ext4_mb_release(struct super_block *sb)
+ }
+ 
+ static inline int ext4_issue_discard(struct super_block *sb,
+-		ext4_group_t block_group, ext4_grpblk_t block, int count)
++		ext4_group_t block_group, ext4_grpblk_t cluster, int count)
+ {
+ 	ext4_fsblk_t discard_block;
+ 
+-	discard_block = block + ext4_group_first_block_no(sb, block_group);
++	discard_block = (EXT4_C2B(EXT4_SB(sb), cluster) +
++			 ext4_group_first_block_no(sb, block_group));
++	count = EXT4_C2B(EXT4_SB(sb), count);
+ 	trace_ext4_discard_blocks(sb,
+ 			(unsigned long long) discard_block, count);
+ 	return sb_issue_discard(sb, discard_block, count, GFP_NOFS, 0);
+@@ -2633,7 +2635,7 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn)
+ 
+ 		if (test_opt(sb, DISCARD))
+ 			ext4_issue_discard(sb, entry->group,
+-					   entry->start_blk, entry->count);
++					   entry->start_cluster, entry->count);
+ 
+ 		err = ext4_mb_load_buddy(sb, entry->group, &e4b);
+ 		/* we expect to find existing buddy because it's pinned */
+@@ -2646,7 +2648,7 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn)
+ 		ext4_lock_group(sb, entry->group);
+ 		/* Take it out of per group rb tree */
+ 		rb_erase(&entry->node, &(db->bb_free_root));
+-		mb_free_blocks(NULL, &e4b, entry->start_blk, entry->count);
++		mb_free_blocks(NULL, &e4b, entry->start_cluster, entry->count);
+ 
+ 		/*
+ 		 * Clear the trimmed flag for the group so that the next
+@@ -3300,7 +3302,7 @@ static void ext4_mb_generate_from_freelist(struct super_block *sb, void *bitmap,
+ 
+ 	while (n) {
+ 		entry = rb_entry(n, struct ext4_free_data, node);
+-		ext4_set_bits(bitmap, entry->start_blk, entry->count);
++		ext4_set_bits(bitmap, entry->start_cluster, entry->count);
+ 		n = rb_next(n);
+ 	}
+ 	return;
+@@ -4401,7 +4403,7 @@ static int can_merge(struct ext4_free_data *entry1,
+ {
+ 	if ((entry1->t_tid == entry2->t_tid) &&
+ 	    (entry1->group == entry2->group) &&
+-	    ((entry1->start_blk + entry1->count) == entry2->start_blk))
++	    ((entry1->start_cluster + entry1->count) == entry2->start_cluster))
+ 		return 1;
+ 	return 0;
+ }
+@@ -4411,7 +4413,7 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
+ 		      struct ext4_free_data *new_entry)
+ {
+ 	ext4_group_t group = e4b->bd_group;
+-	ext4_grpblk_t block;
++	ext4_grpblk_t cluster;
+ 	struct ext4_free_data *entry;
+ 	struct ext4_group_info *db = e4b->bd_info;
+ 	struct super_block *sb = e4b->bd_sb;
+@@ -4424,7 +4426,7 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
+ 	BUG_ON(e4b->bd_buddy_page == NULL);
+ 
+ 	new_node = &new_entry->node;
+-	block = new_entry->start_blk;
++	cluster = new_entry->start_cluster;
+ 
+ 	if (!*n) {
+ 		/* first free block exent. We need to
+@@ -4438,13 +4440,14 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
+ 	while (*n) {
+ 		parent = *n;
+ 		entry = rb_entry(parent, struct ext4_free_data, node);
+-		if (block < entry->start_blk)
++		if (cluster < entry->start_cluster)
+ 			n = &(*n)->rb_left;
+-		else if (block >= (entry->start_blk + entry->count))
++		else if (cluster >= (entry->start_cluster + entry->count))
+ 			n = &(*n)->rb_right;
+ 		else {
+ 			ext4_grp_locked_error(sb, group, 0,
+-				ext4_group_first_block_no(sb, group) + block,
++				ext4_group_first_block_no(sb, group) +
++				EXT4_C2B(sbi, cluster),
+ 				"Block already on to-be-freed list");
+ 			return 0;
+ 		}
+@@ -4458,7 +4461,7 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
+ 	if (node) {
+ 		entry = rb_entry(node, struct ext4_free_data, node);
+ 		if (can_merge(entry, new_entry)) {
+-			new_entry->start_blk = entry->start_blk;
++			new_entry->start_cluster = entry->start_cluster;
+ 			new_entry->count += entry->count;
+ 			rb_erase(node, &(db->bb_free_root));
+ 			spin_lock(&sbi->s_md_lock);
+@@ -4509,6 +4512,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 	ext4_group_t block_group;
+ 	struct ext4_sb_info *sbi;
+ 	struct ext4_buddy e4b;
++	unsigned int count_clusters;
+ 	int err = 0;
+ 	int ret;
+ 
+@@ -4557,6 +4561,38 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 	if (!ext4_should_writeback_data(inode))
+ 		flags |= EXT4_FREE_BLOCKS_METADATA;
+ 
++	/*
++	 * If the extent to be freed does not begin on a cluster
++	 * boundary, we need to deal with partial clusters at the
++	 * beginning and end of the extent.  Normally we will free
++	 * blocks at the beginning or the end unless we are explicitly
++	 * requested to avoid doing so.
++	 */
++	overflow = block & (sbi->s_cluster_ratio - 1);
++	if (overflow) {
++		if (flags & EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER) {
++			overflow = sbi->s_cluster_ratio - overflow;
++			block += overflow;
++			if (count > overflow)
++				count -= overflow;
++			else
++				return;
++		} else {
++			block -= overflow;
++			count += overflow;
++		}
++	}
++	overflow = count & (sbi->s_cluster_ratio - 1);
++	if (overflow) {
++		if (flags & EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER) {
++			if (count > overflow)
++				count -= overflow;
++			else
++				return;
++		} else
++			count += sbi->s_cluster_ratio - overflow;
++	}
++
+ do_more:
+ 	overflow = 0;
+ 	ext4_get_group_no_and_offset(sb, block, &block_group, &bit);
+@@ -4565,10 +4601,12 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 	 * Check to see if we are freeing blocks across a group
+ 	 * boundary.
+ 	 */
+-	if (bit + count > EXT4_CLUSTERS_PER_GROUP(sb)) {
+-		overflow = bit + count - EXT4_CLUSTERS_PER_GROUP(sb);
++	if (EXT4_C2B(sbi, bit) + count > EXT4_BLOCKS_PER_GROUP(sb)) {
++		overflow = EXT4_C2B(sbi, bit) + count -
++			EXT4_BLOCKS_PER_GROUP(sb);
+ 		count -= overflow;
+ 	}
++	count_clusters = EXT4_B2C(sbi, count);
+ 	bitmap_bh = ext4_read_block_bitmap(sb, block_group);
+ 	if (!bitmap_bh) {
+ 		err = -EIO;
+@@ -4583,9 +4621,9 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 	if (in_range(ext4_block_bitmap(sb, gdp), block, count) ||
+ 	    in_range(ext4_inode_bitmap(sb, gdp), block, count) ||
+ 	    in_range(block, ext4_inode_table(sb, gdp),
+-		      EXT4_SB(sb)->s_itb_per_group) ||
++		     EXT4_SB(sb)->s_itb_per_group) ||
+ 	    in_range(block + count - 1, ext4_inode_table(sb, gdp),
+-		      EXT4_SB(sb)->s_itb_per_group)) {
++		     EXT4_SB(sb)->s_itb_per_group)) {
+ 
+ 		ext4_error(sb, "Freeing blocks in system zone - "
+ 			   "Block = %llu, count = %lu", block, count);
+@@ -4610,11 +4648,11 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ #ifdef AGGRESSIVE_CHECK
+ 	{
+ 		int i;
+-		for (i = 0; i < count; i++)
++		for (i = 0; i < count_clusters; i++)
+ 			BUG_ON(!mb_test_bit(bit + i, bitmap_bh->b_data));
+ 	}
+ #endif
+-	trace_ext4_mballoc_free(sb, inode, block_group, bit, count);
++	trace_ext4_mballoc_free(sb, inode, block_group, bit, count_clusters);
+ 
+ 	err = ext4_mb_load_buddy(sb, block_group, &e4b);
+ 	if (err)
+@@ -4631,13 +4669,13 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 			err = -ENOMEM;
+ 			goto error_return;
+ 		}
+-		new_entry->start_blk = bit;
++		new_entry->start_cluster = bit;
+ 		new_entry->group  = block_group;
+-		new_entry->count = count;
++		new_entry->count = count_clusters;
+ 		new_entry->t_tid = handle->h_transaction->t_tid;
+ 
+ 		ext4_lock_group(sb, block_group);
+-		mb_clear_bits(bitmap_bh->b_data, bit, count);
++		mb_clear_bits(bitmap_bh->b_data, bit, count_clusters);
+ 		ext4_mb_free_metadata(handle, &e4b, new_entry);
+ 	} else {
+ 		/* need to update group_info->bb_free and bitmap
+@@ -4645,11 +4683,11 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 		 * them with group lock_held
+ 		 */
+ 		ext4_lock_group(sb, block_group);
+-		mb_clear_bits(bitmap_bh->b_data, bit, count);
+-		mb_free_blocks(inode, &e4b, bit, count);
++		mb_clear_bits(bitmap_bh->b_data, bit, count_clusters);
++		mb_free_blocks(inode, &e4b, bit, count_clusters);
+ 	}
+ 
+-	ret = ext4_free_blks_count(sb, gdp) + count;
++	ret = ext4_free_blks_count(sb, gdp) + count_clusters;
+ 	ext4_free_blks_set(sb, gdp, ret);
+ 	gdp->bg_checksum = ext4_group_desc_csum(sbi, block_group, gdp);
+ 	ext4_unlock_group(sb, block_group);
+diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
+index 1641f4b57439..dc99930d4cb5 100644
+--- a/fs/ext4/mballoc.h
++++ b/fs/ext4/mballoc.h
+@@ -106,7 +106,7 @@ struct ext4_free_data {
+ 	ext4_group_t group;
+ 
+ 	/* free block extent */
+-	ext4_grpblk_t start_blk;
++	ext4_grpblk_t start_cluster;
+ 	ext4_grpblk_t count;
+ 
+ 	/* transaction which freed this extent */

commit 53accfa9f819c80056db6f03f9c5cfa4bcba1ed8
+Author: Theodore Ts'o 
+Date:   Fri Sep 9 18:48:51 2011 -0400
+
+    ext4: teach mballoc preallocation code about bigalloc clusters
+    
+    In most of mballoc.c, we do everything in units of clusters, since the
+    block allocation bitmaps and buddy bitmaps are all denominated in
+    clusters.  The one place where we do deal with absolute block numbers
+    is in the code that handles the preallocation regions, since in the
+    case of inode-based preallocation regions, the start of the
+    preallocation region can't be relative to the beginning of the group.
+    
+    So this adds a bit of complexity, where pa_pstart and pa_lstart are
+    block numbers, while pa_free, pa_len, and fe_len are denominated in
+    units of clusters.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 81e28657a3c2..8765f2512f13 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -70,8 +70,8 @@
+  *
+  * pa_lstart -> the logical start block for this prealloc space
+  * pa_pstart -> the physical start block for this prealloc space
+- * pa_len    -> length for this prealloc space
+- * pa_free   ->  free space available in this prealloc space
++ * pa_len    -> length for this prealloc space (in clusters)
++ * pa_free   ->  free space available in this prealloc space (in clusters)
+  *
+  * The inode preallocation space is used looking at the _logical_ start
+  * block. If only the logical file block falls within the range of prealloc
+@@ -459,7 +459,7 @@ static void mb_free_blocks_double(struct inode *inode, struct ext4_buddy *e4b,
+ 			ext4_fsblk_t blocknr;
+ 
+ 			blocknr = ext4_group_first_block_no(sb, e4b->bd_group);
+-			blocknr += first + i;
++			blocknr += EXT4_C2B(EXT4_SB(sb), first + i);
+ 			ext4_grp_locked_error(sb, e4b->bd_group,
+ 					      inode ? inode->i_ino : 0,
+ 					      blocknr,
+@@ -734,7 +734,7 @@ void ext4_mb_generate_buddy(struct super_block *sb,
+ 
+ 	if (free != grp->bb_free) {
+ 		ext4_grp_locked_error(sb, group, 0, 0,
+-				      "%u blocks in bitmap, %u in gd",
++				      "%u clusters in bitmap, %u in gd",
+ 				      free, grp->bb_free);
+ 		/*
+ 		 * If we intent to continue, we consider group descritor
+@@ -1339,7 +1339,7 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
+ 			ext4_fsblk_t blocknr;
+ 
+ 			blocknr = ext4_group_first_block_no(sb, e4b->bd_group);
+-			blocknr += block;
++			blocknr += EXT4_C2B(EXT4_SB(sb), block);
+ 			ext4_grp_locked_error(sb, e4b->bd_group,
+ 					      inode ? inode->i_ino : 0,
+ 					      blocknr,
+@@ -1831,7 +1831,7 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
+ 			 * we have free blocks
+ 			 */
+ 			ext4_grp_locked_error(sb, e4b->bd_group, 0, 0,
+-					"%d free blocks as per "
++					"%d free clusters as per "
+ 					"group info. But bitmap says 0",
+ 					free);
+ 			break;
+@@ -1841,7 +1841,7 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
+ 		BUG_ON(ex.fe_len <= 0);
+ 		if (free < ex.fe_len) {
+ 			ext4_grp_locked_error(sb, e4b->bd_group, 0, 0,
+-					"%d free blocks as per "
++					"%d free clusters as per "
+ 					"group info. But got %d blocks",
+ 					free, ex.fe_len);
+ 			/*
+@@ -2752,7 +2752,7 @@ void ext4_exit_mballoc(void)
+  */
+ static noinline_for_stack int
+ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
+-				handle_t *handle, unsigned int reserv_blks)
++				handle_t *handle, unsigned int reserv_clstrs)
+ {
+ 	struct buffer_head *bitmap_bh = NULL;
+ 	struct ext4_group_desc *gdp;
+@@ -2791,7 +2791,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
+ 
+ 	block = ext4_grp_offs_to_block(sb, &ac->ac_b_ex);
+ 
+-	len = ac->ac_b_ex.fe_len;
++	len = EXT4_C2B(sbi, ac->ac_b_ex.fe_len);
+ 	if (!ext4_data_block_valid(sbi, block, len)) {
+ 		ext4_error(sb, "Allocating blocks %llu-%llu which overlap "
+ 			   "fs metadata\n", block, block+len);
+@@ -2838,7 +2838,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
+ 	 */
+ 	if (!(ac->ac_flags & EXT4_MB_DELALLOC_RESERVED))
+ 		/* release all the reserved blocks if non delalloc */
+-		percpu_counter_sub(&sbi->s_dirtyblocks_counter, reserv_blks);
++		percpu_counter_sub(&sbi->s_dirtyblocks_counter, reserv_clstrs);
+ 
+ 	if (sbi->s_log_groups_per_flex) {
+ 		ext4_group_t flex_group = ext4_flex_group(sbi,
+@@ -2886,6 +2886,7 @@ static noinline_for_stack void
+ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
+ 				struct ext4_allocation_request *ar)
+ {
++	struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);
+ 	int bsbits, max;
+ 	ext4_lblk_t end;
+ 	loff_t size, orig_size, start_off;
+@@ -2916,7 +2917,7 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
+ 
+ 	/* first, let's learn actual file size
+ 	 * given current request is allocated */
+-	size = ac->ac_o_ex.fe_logical + ac->ac_o_ex.fe_len;
++	size = ac->ac_o_ex.fe_logical + EXT4_C2B(sbi, ac->ac_o_ex.fe_len);
+ 	size = size << bsbits;
+ 	if (size < i_size_read(ac->ac_inode))
+ 		size = i_size_read(ac->ac_inode);
+@@ -2988,7 +2989,8 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
+ 			continue;
+ 		}
+ 
+-		pa_end = pa->pa_lstart + pa->pa_len;
++		pa_end = pa->pa_lstart + EXT4_C2B(EXT4_SB(ac->ac_sb),
++						  pa->pa_len);
+ 
+ 		/* PA must not overlap original request */
+ 		BUG_ON(!(ac->ac_o_ex.fe_logical >= pa_end ||
+@@ -3018,9 +3020,11 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
+ 	rcu_read_lock();
+ 	list_for_each_entry_rcu(pa, &ei->i_prealloc_list, pa_inode_list) {
+ 		ext4_lblk_t pa_end;
++
+ 		spin_lock(&pa->pa_lock);
+ 		if (pa->pa_deleted == 0) {
+-			pa_end = pa->pa_lstart + pa->pa_len;
++			pa_end = pa->pa_lstart + EXT4_C2B(EXT4_SB(ac->ac_sb),
++							  pa->pa_len);
+ 			BUG_ON(!(start >= pa_end || end <= pa->pa_lstart));
+ 		}
+ 		spin_unlock(&pa->pa_lock);
+@@ -3043,7 +3047,7 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
+ 	/* XXX: is it better to align blocks WRT to logical
+ 	 * placement or satisfy big request as is */
+ 	ac->ac_g_ex.fe_logical = start;
+-	ac->ac_g_ex.fe_len = size;
++	ac->ac_g_ex.fe_len = EXT4_NUM_B2C(sbi, size);
+ 
+ 	/* define goal start in order to merge */
+ 	if (ar->pright && (ar->lright == (start + size))) {
+@@ -3112,14 +3116,16 @@ static void ext4_discard_allocated_blocks(struct ext4_allocation_context *ac)
+ static void ext4_mb_use_inode_pa(struct ext4_allocation_context *ac,
+ 				struct ext4_prealloc_space *pa)
+ {
++	struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);
+ 	ext4_fsblk_t start;
+ 	ext4_fsblk_t end;
+ 	int len;
+ 
+ 	/* found preallocated blocks, use them */
+ 	start = pa->pa_pstart + (ac->ac_o_ex.fe_logical - pa->pa_lstart);
+-	end = min(pa->pa_pstart + pa->pa_len, start + ac->ac_o_ex.fe_len);
+-	len = end - start;
++	end = min(pa->pa_pstart + EXT4_C2B(sbi, pa->pa_len),
++		  start + EXT4_C2B(sbi, ac->ac_o_ex.fe_len));
++	len = EXT4_NUM_B2C(sbi, end - start);
+ 	ext4_get_group_no_and_offset(ac->ac_sb, start, &ac->ac_b_ex.fe_group,
+ 					&ac->ac_b_ex.fe_start);
+ 	ac->ac_b_ex.fe_len = len;
+@@ -3127,7 +3133,7 @@ static void ext4_mb_use_inode_pa(struct ext4_allocation_context *ac,
+ 	ac->ac_pa = pa;
+ 
+ 	BUG_ON(start < pa->pa_pstart);
+-	BUG_ON(start + len > pa->pa_pstart + pa->pa_len);
++	BUG_ON(end > pa->pa_pstart + EXT4_C2B(sbi, pa->pa_len));
+ 	BUG_ON(pa->pa_free < len);
+ 	pa->pa_free -= len;
+ 
+@@ -3193,6 +3199,7 @@ ext4_mb_check_group_pa(ext4_fsblk_t goal_block,
+ static noinline_for_stack int
+ ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
+ {
++	struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);
+ 	int order, i;
+ 	struct ext4_inode_info *ei = EXT4_I(ac->ac_inode);
+ 	struct ext4_locality_group *lg;
+@@ -3210,12 +3217,14 @@ ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
+ 		/* all fields in this condition don't change,
+ 		 * so we can skip locking for them */
+ 		if (ac->ac_o_ex.fe_logical < pa->pa_lstart ||
+-			ac->ac_o_ex.fe_logical >= pa->pa_lstart + pa->pa_len)
++		    ac->ac_o_ex.fe_logical >= (pa->pa_lstart +
++					       EXT4_C2B(sbi, pa->pa_len)))
+ 			continue;
+ 
+ 		/* non-extent files can't have physical blocks past 2^32 */
+ 		if (!(ext4_test_inode_flag(ac->ac_inode, EXT4_INODE_EXTENTS)) &&
+-			pa->pa_pstart + pa->pa_len > EXT4_MAX_BLOCK_FILE_PHYS)
++		    (pa->pa_pstart + EXT4_C2B(sbi, pa->pa_len) >
++		     EXT4_MAX_BLOCK_FILE_PHYS))
+ 			continue;
+ 
+ 		/* found preallocated blocks, use them */
+@@ -3412,6 +3421,7 @@ static noinline_for_stack int
+ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
+ {
+ 	struct super_block *sb = ac->ac_sb;
++	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	struct ext4_prealloc_space *pa;
+ 	struct ext4_group_info *grp;
+ 	struct ext4_inode_info *ei;
+@@ -3443,16 +3453,18 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
+ 		winl = ac->ac_o_ex.fe_logical - ac->ac_g_ex.fe_logical;
+ 
+ 		/* also, we should cover whole original request */
+-		wins = ac->ac_b_ex.fe_len - ac->ac_o_ex.fe_len;
++		wins = EXT4_C2B(sbi, ac->ac_b_ex.fe_len - ac->ac_o_ex.fe_len);
+ 
+ 		/* the smallest one defines real window */
+ 		win = min(winl, wins);
+ 
+-		offs = ac->ac_o_ex.fe_logical % ac->ac_b_ex.fe_len;
++		offs = ac->ac_o_ex.fe_logical %
++			EXT4_C2B(sbi, ac->ac_b_ex.fe_len);
+ 		if (offs && offs < win)
+ 			win = offs;
+ 
+-		ac->ac_b_ex.fe_logical = ac->ac_o_ex.fe_logical - win;
++		ac->ac_b_ex.fe_logical = ac->ac_o_ex.fe_logical -
++			EXT4_B2C(sbi, win);
+ 		BUG_ON(ac->ac_o_ex.fe_logical < ac->ac_b_ex.fe_logical);
+ 		BUG_ON(ac->ac_o_ex.fe_len > ac->ac_b_ex.fe_len);
+ 	}
+@@ -3477,7 +3489,7 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
+ 	trace_ext4_mb_new_inode_pa(ac, pa);
+ 
+ 	ext4_mb_use_inode_pa(ac, pa);
+-	atomic_add(pa->pa_free, &EXT4_SB(sb)->s_mb_preallocated);
++	atomic_add(pa->pa_free, &sbi->s_mb_preallocated);
+ 
+ 	ei = EXT4_I(ac->ac_inode);
+ 	grp = ext4_get_group_info(sb, ac->ac_b_ex.fe_group);
+@@ -3592,7 +3604,7 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh,
+ 
+ 	BUG_ON(pa->pa_deleted == 0);
+ 	ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit);
+-	grp_blk_start = pa->pa_pstart - bit;
++	grp_blk_start = pa->pa_pstart - EXT4_C2B(sbi, bit);
+ 	BUG_ON(group != e4b->bd_group && pa->pa_len != 0);
+ 	end = bit + pa->pa_len;
+ 
+@@ -3607,7 +3619,8 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh,
+ 		free += next - bit;
+ 
+ 		trace_ext4_mballoc_discard(sb, NULL, group, bit, next - bit);
+-		trace_ext4_mb_release_inode_pa(pa, grp_blk_start + bit,
++		trace_ext4_mb_release_inode_pa(pa, (grp_blk_start +
++						    EXT4_C2B(sbi, bit)),
+ 					       next - bit);
+ 		mb_free_blocks(pa->pa_inode, e4b, bit, next - bit);
+ 		bit = next + 1;
+@@ -3958,7 +3971,7 @@ static void ext4_mb_group_or_file(struct ext4_allocation_context *ac)
+ 	if (unlikely(ac->ac_flags & EXT4_MB_HINT_GOAL_ONLY))
+ 		return;
+ 
+-	size = ac->ac_o_ex.fe_logical + ac->ac_o_ex.fe_len;
++	size = ac->ac_o_ex.fe_logical + EXT4_C2B(sbi, ac->ac_o_ex.fe_len);
+ 	isize = (i_size_read(ac->ac_inode) + ac->ac_sb->s_blocksize - 1)
+ 		>> bsbits;
+ 
+@@ -4019,18 +4032,15 @@ ext4_mb_initialize_context(struct ext4_allocation_context *ac,
+ 
+ 	/* set up allocation goals */
+ 	memset(ac, 0, sizeof(struct ext4_allocation_context));
+-	ac->ac_b_ex.fe_logical = ar->logical;
++	ac->ac_b_ex.fe_logical = ar->logical & ~(sbi->s_cluster_ratio - 1);
+ 	ac->ac_status = AC_STATUS_CONTINUE;
+ 	ac->ac_sb = sb;
+ 	ac->ac_inode = ar->inode;
+-	ac->ac_o_ex.fe_logical = ar->logical;
++	ac->ac_o_ex.fe_logical = ac->ac_b_ex.fe_logical;
+ 	ac->ac_o_ex.fe_group = group;
+ 	ac->ac_o_ex.fe_start = block;
+ 	ac->ac_o_ex.fe_len = len;
+-	ac->ac_g_ex.fe_logical = ar->logical;
+-	ac->ac_g_ex.fe_group = group;
+-	ac->ac_g_ex.fe_start = block;
+-	ac->ac_g_ex.fe_len = len;
++	ac->ac_g_ex = ac->ac_o_ex;
+ 	ac->ac_flags = ar->flags;
+ 
+ 	/* we have to define context: we'll we work with a file or
+@@ -4182,13 +4192,14 @@ static void ext4_mb_add_n_trim(struct ext4_allocation_context *ac)
+  */
+ static int ext4_mb_release_context(struct ext4_allocation_context *ac)
+ {
++	struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);
+ 	struct ext4_prealloc_space *pa = ac->ac_pa;
+ 	if (pa) {
+ 		if (pa->pa_type == MB_GROUP_PA) {
+ 			/* see comment in ext4_mb_use_group_pa() */
+ 			spin_lock(&pa->pa_lock);
+-			pa->pa_pstart += ac->ac_b_ex.fe_len;
+-			pa->pa_lstart += ac->ac_b_ex.fe_len;
++			pa->pa_pstart += EXT4_C2B(sbi, ac->ac_b_ex.fe_len);
++			pa->pa_lstart += EXT4_C2B(sbi, ac->ac_b_ex.fe_len);
+ 			pa->pa_free -= ac->ac_b_ex.fe_len;
+ 			pa->pa_len -= ac->ac_b_ex.fe_len;
+ 			spin_unlock(&pa->pa_lock);
+@@ -4249,7 +4260,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
+ 	struct super_block *sb;
+ 	ext4_fsblk_t block = 0;
+ 	unsigned int inquota = 0;
+-	unsigned int reserv_blks = 0;
++	unsigned int reserv_clstrs = 0;
+ 
+ 	sb = ar->inode->i_sb;
+ 	sbi = EXT4_SB(sb);
+@@ -4279,12 +4290,14 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
+ 			*errp = -ENOSPC;
+ 			return 0;
+ 		}
+-		reserv_blks = ar->len;
++		reserv_clstrs = ar->len;
+ 		if (ar->flags & EXT4_MB_USE_ROOT_BLOCKS) {
+-			dquot_alloc_block_nofail(ar->inode, ar->len);
++			dquot_alloc_block_nofail(ar->inode,
++						 EXT4_C2B(sbi, ar->len));
+ 		} else {
+ 			while (ar->len &&
+-				dquot_alloc_block(ar->inode, ar->len)) {
++				dquot_alloc_block(ar->inode,
++						  EXT4_C2B(sbi, ar->len))) {
+ 
+ 				ar->flags |= EXT4_MB_HINT_NOPREALLOC;
+ 				ar->len--;
+@@ -4328,7 +4341,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
+ 			ext4_mb_new_preallocation(ac);
+ 	}
+ 	if (likely(ac->ac_status == AC_STATUS_FOUND)) {
+-		*errp = ext4_mb_mark_diskspace_used(ac, handle, reserv_blks);
++		*errp = ext4_mb_mark_diskspace_used(ac, handle, reserv_clstrs);
+ 		if (*errp == -EAGAIN) {
+ 			/*
+ 			 * drop the reference that we took
+@@ -4364,13 +4377,13 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
+ 	if (ac)
+ 		kmem_cache_free(ext4_ac_cachep, ac);
+ 	if (inquota && ar->len < inquota)
+-		dquot_free_block(ar->inode, inquota - ar->len);
++		dquot_free_block(ar->inode, EXT4_C2B(sbi, inquota - ar->len));
+ 	if (!ar->len) {
+ 		if (!ext4_test_inode_state(ar->inode,
+ 					   EXT4_STATE_DELALLOC_RESERVED))
+ 			/* release all the reserved blocks if non delalloc */
+ 			percpu_counter_sub(&sbi->s_dirtyblocks_counter,
+-						reserv_blks);
++						reserv_clstrs);
+ 	}
+ 
+ 	trace_ext4_allocate_blocks(ar, (unsigned long long)block);
+diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
+index 3cdb8aa9f6b7..1641f4b57439 100644
+--- a/fs/ext4/mballoc.h
++++ b/fs/ext4/mballoc.h
+@@ -139,9 +139,9 @@ enum {
+ 
+ struct ext4_free_extent {
+ 	ext4_lblk_t fe_logical;
+-	ext4_grpblk_t fe_start;
++	ext4_grpblk_t fe_start;	/* In cluster units */
+ 	ext4_group_t fe_group;
+-	ext4_grpblk_t fe_len;
++	ext4_grpblk_t fe_len;	/* In cluster units */
+ };
+ 
+ /*

commit 3212a80a58062056bb922811071062be58d8fee1
+Author: Theodore Ts'o 
+Date:   Fri Sep 9 18:46:51 2011 -0400
+
+    ext4: convert block group-relative offsets to use clusters
+    
+    Certain parts of the ext4 code base, primarily in mballoc.c, use a
+    block group number and offset from the beginning of the block group.
+    This offset is invariably used to index into the allocation bitmap, so
+    change the offset to be denominated in units of clusters.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 1c6d777b35a2..89abf1f7b253 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -28,7 +28,8 @@
+  */
+ 
+ /*
+- * Calculate the block group number and offset, given a block number
++ * Calculate the block group number and offset into the block/cluster
++ * allocation bitmap, given a block number
+  */
+ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
+ 		ext4_group_t *blockgrpp, ext4_grpblk_t *offsetp)
+@@ -37,7 +38,8 @@ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
+ 	ext4_grpblk_t offset;
+ 
+ 	blocknr = blocknr - le32_to_cpu(es->s_first_data_block);
+-	offset = do_div(blocknr, EXT4_BLOCKS_PER_GROUP(sb));
++	offset = do_div(blocknr, EXT4_BLOCKS_PER_GROUP(sb)) >>
++		EXT4_SB(sb)->s_cluster_bits;
+ 	if (offsetp)
+ 		*offsetp = offset;
+ 	if (blockgrpp)
+diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
+index 9d4a636b546c..3cdb8aa9f6b7 100644
+--- a/fs/ext4/mballoc.h
++++ b/fs/ext4/mballoc.h
+@@ -216,6 +216,7 @@ struct ext4_buddy {
+ static inline ext4_fsblk_t ext4_grp_offs_to_block(struct super_block *sb,
+ 					struct ext4_free_extent *fex)
+ {
+-	return ext4_group_first_block_no(sb, fex->fe_group) + fex->fe_start;
++	return ext4_group_first_block_no(sb, fex->fe_group) +
++		(fex->fe_start << EXT4_SB(sb)->s_cluster_bits);
+ }
+ #endif

commit d5b8f31007a93777cfb0603b665858fb7aebebfc
+Author: Theodore Ts'o 
+Date:   Fri Sep 9 18:44:51 2011 -0400
+
+    ext4: bigalloc changes to block bitmap initialization functions
+    
+    Add bigalloc support to ext4_init_block_bitmap() and
+    ext4_free_blocks_after_init().
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 735d9fcc72e6..1c6d777b35a2 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -23,9 +23,6 @@
+ 
+ #include 
+ 
+-static unsigned int num_base_meta_blocks(struct super_block *sb,
+-					 ext4_group_t block_group);
+-
+ /*
+  * balloc.c contains the blocks allocation and deallocation routines
+  */
+@@ -58,37 +55,87 @@ static int ext4_block_in_group(struct super_block *sb, ext4_fsblk_t block,
+ 	return 0;
+ }
+ 
+-static int ext4_group_used_meta_blocks(struct super_block *sb,
+-				       ext4_group_t block_group,
+-				       struct ext4_group_desc *gdp)
++/* Return the number of clusters used for file system metadata; this
++ * represents the overhead needed by the file system.
++ */
++unsigned ext4_num_overhead_clusters(struct super_block *sb,
++				    ext4_group_t block_group,
++				    struct ext4_group_desc *gdp)
+ {
+-	ext4_fsblk_t tmp;
++	unsigned num_clusters;
++	int block_cluster = -1, inode_cluster = -1, itbl_cluster = -1, i, c;
++	ext4_fsblk_t start = ext4_group_first_block_no(sb, block_group);
++	ext4_fsblk_t itbl_blk;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-	/* block bitmap, inode bitmap, and inode table blocks */
+-	int used_blocks = sbi->s_itb_per_group + 2;
+ 
+-	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
+-		if (!ext4_block_in_group(sb, ext4_block_bitmap(sb, gdp),
+-					block_group))
+-			used_blocks--;
+-
+-		if (!ext4_block_in_group(sb, ext4_inode_bitmap(sb, gdp),
+-					block_group))
+-			used_blocks--;
+-
+-		tmp = ext4_inode_table(sb, gdp);
+-		for (; tmp < ext4_inode_table(sb, gdp) +
+-				sbi->s_itb_per_group; tmp++) {
+-			if (!ext4_block_in_group(sb, tmp, block_group))
+-				used_blocks -= 1;
++	/* This is the number of clusters used by the superblock,
++	 * block group descriptors, and reserved block group
++	 * descriptor blocks */
++	num_clusters = ext4_num_base_meta_clusters(sb, block_group);
++
++	/*
++	 * For the allocation bitmaps and inode table, we first need
++	 * to check to see if the block is in the block group.  If it
++	 * is, then check to see if the cluster is already accounted
++	 * for in the clusters used for the base metadata cluster, or
++	 * if we can increment the base metadata cluster to include
++	 * that block.  Otherwise, we will have to track the cluster
++	 * used for the allocation bitmap or inode table explicitly.
++	 * Normally all of these blocks are contiguous, so the special
++	 * case handling shouldn't be necessary except for *very*
++	 * unusual file system layouts.
++	 */
++	if (ext4_block_in_group(sb, ext4_block_bitmap(sb, gdp), block_group)) {
++		block_cluster = EXT4_B2C(sbi, (start -
++					       ext4_block_bitmap(sb, gdp)));
++		if (block_cluster < num_clusters)
++			block_cluster = -1;
++		else if (block_cluster == num_clusters) {
++			num_clusters++;
++			block_cluster = -1;
++		}
++	}
++
++	if (ext4_block_in_group(sb, ext4_inode_bitmap(sb, gdp), block_group)) {
++		inode_cluster = EXT4_B2C(sbi,
++					 start - ext4_inode_bitmap(sb, gdp));
++		if (inode_cluster < num_clusters)
++			inode_cluster = -1;
++		else if (inode_cluster == num_clusters) {
++			num_clusters++;
++			inode_cluster = -1;
++		}
++	}
++
++	itbl_blk = ext4_inode_table(sb, gdp);
++	for (i = 0; i < sbi->s_itb_per_group; i++) {
++		if (ext4_block_in_group(sb, itbl_blk + i, block_group)) {
++			c = EXT4_B2C(sbi, start - itbl_blk + i);
++			if ((c < num_clusters) || (c == inode_cluster) ||
++			    (c == block_cluster) || (c == itbl_cluster))
++				continue;
++			if (c == num_clusters) {
++				num_clusters++;
++				continue;
++			}
++			num_clusters++;
++			itbl_cluster = c;
+ 		}
+ 	}
+-	return used_blocks;
++
++	if (block_cluster != -1)
++		num_clusters++;
++	if (inode_cluster != -1)
++		num_clusters++;
++
++	return num_clusters;
+ }
+ 
+-static unsigned int num_blocks_in_group(struct super_block *sb,
+-					ext4_group_t block_group)
++static unsigned int num_clusters_in_group(struct super_block *sb,
++					  ext4_group_t block_group)
+ {
++	unsigned int blocks;
++
+ 	if (block_group == ext4_get_groups_count(sb) - 1) {
+ 		/*
+ 		 * Even though mke2fs always initializes the first and
+@@ -96,10 +143,11 @@ static unsigned int num_blocks_in_group(struct super_block *sb,
+ 		 * we need to make sure we calculate the right free
+ 		 * blocks.
+ 		 */
+-		return ext4_blocks_count(EXT4_SB(sb)->s_es) -
++		blocks = ext4_blocks_count(EXT4_SB(sb)->s_es) -
+ 			ext4_group_first_block_no(sb, block_group);
+ 	} else
+-		return EXT4_BLOCKS_PER_GROUP(sb);
++		blocks = EXT4_BLOCKS_PER_GROUP(sb);
++	return EXT4_NUM_B2C(EXT4_SB(sb), blocks);
+ }
+ 
+ /* Initializes an uninitialized block bitmap */
+@@ -107,7 +155,7 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
+ 			    ext4_group_t block_group,
+ 			    struct ext4_group_desc *gdp)
+ {
+-	unsigned int bit, bit_max = num_base_meta_blocks(sb, block_group);
++	unsigned int bit, bit_max;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	ext4_fsblk_t start, tmp;
+ 	int flex_bg = 0;
+@@ -126,6 +174,7 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
+ 	}
+ 	memset(bh->b_data, 0, sb->s_blocksize);
+ 
++	bit_max = ext4_num_base_meta_clusters(sb, block_group);
+ 	for (bit = 0; bit < bit_max; bit++)
+ 		ext4_set_bit(bit, bh->b_data);
+ 
+@@ -137,24 +186,25 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
+ 	/* Set bits for block and inode bitmaps, and inode table */
+ 	tmp = ext4_block_bitmap(sb, gdp);
+ 	if (!flex_bg || ext4_block_in_group(sb, tmp, block_group))
+-		ext4_set_bit(tmp - start, bh->b_data);
++		ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data);
+ 
+ 	tmp = ext4_inode_bitmap(sb, gdp);
+ 	if (!flex_bg || ext4_block_in_group(sb, tmp, block_group))
+-		ext4_set_bit(tmp - start, bh->b_data);
++		ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data);
+ 
+ 	tmp = ext4_inode_table(sb, gdp);
+ 	for (; tmp < ext4_inode_table(sb, gdp) +
+ 		     sbi->s_itb_per_group; tmp++) {
+ 		if (!flex_bg || ext4_block_in_group(sb, tmp, block_group))
+-			ext4_set_bit(tmp - start, bh->b_data);
++			ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data);
+ 	}
++
+ 	/*
+ 	 * Also if the number of blocks within the group is less than
+ 	 * the blocksize * 8 ( which is the size of bitmap ), set rest
+ 	 * of the block bitmap to 1
+ 	 */
+-	ext4_mark_bitmap_end(num_blocks_in_group(sb, block_group),
++	ext4_mark_bitmap_end(num_clusters_in_group(sb, block_group),
+ 			     sb->s_blocksize * 8, bh->b_data);
+ }
+ 
+@@ -165,9 +215,8 @@ unsigned ext4_free_blocks_after_init(struct super_block *sb,
+ 				     ext4_group_t block_group,
+ 				     struct ext4_group_desc *gdp)
+ {
+-	return num_blocks_in_group(sb, block_group) -
+-		num_base_meta_blocks(sb, block_group) -
+-		ext4_group_used_meta_blocks(sb, block_group, gdp);
++	return num_clusters_in_group(sb, block_group) - 
++		ext4_num_overhead_clusters(sb, block_group, gdp);
+ }
+ 
+ /*
+@@ -611,14 +660,14 @@ unsigned long ext4_bg_num_gdb(struct super_block *sb, ext4_group_t group)
+ }
+ 
+ /*
+- * This function returns the number of file system metadata blocks at
++ * This function returns the number of file system metadata clusters at
+  * the beginning of a block group, including the reserved gdt blocks.
+  */
+-static unsigned int num_base_meta_blocks(struct super_block *sb,
+-					 ext4_group_t block_group)
++unsigned ext4_num_base_meta_clusters(struct super_block *sb,
++				     ext4_group_t block_group)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-	int num;
++	unsigned num;
+ 
+ 	/* Check for superblock and gdt backups in this group */
+ 	num = ext4_bg_has_super(sb, block_group);
+@@ -633,7 +682,7 @@ static unsigned int num_base_meta_blocks(struct super_block *sb,
+ 	} else { /* For META_BG_BLOCK_GROUPS */
+ 		num += ext4_bg_num_gdb(sb, block_group);
+ 	}
+-	return num;
++	return EXT4_NUM_B2C(sbi, num);
+ }
+ /**
+  *	ext4_inode_to_goal_block - return a hint for block allocation
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index b0b7b67e439d..803cfa42e1e8 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -261,6 +261,14 @@ struct ext4_io_submit {
+ #endif
+ #define EXT4_BLOCK_ALIGN(size, blkbits)		ALIGN((size), (1 << (blkbits)))
+ 
++/* Translate a block number to a cluster number */
++#define EXT4_B2C(sbi, blk)	((blk) >> (sbi)->s_cluster_bits)
++/* Translate a cluster number to a block number */
++#define EXT4_C2B(sbi, cluster)	((cluster) << (sbi)->s_cluster_bits)
++/* Translate # of blks to # of clusters */
++#define EXT4_NUM_B2C(sbi, blks)	(((blks) + (sbi)->s_cluster_ratio - 1) >> \
++				 (sbi)->s_cluster_bits)
++
+ /*
+  * Structure of a blocks group descriptor
+  */
+@@ -1770,6 +1778,11 @@ extern void ext4_init_block_bitmap(struct super_block *sb,
+ extern unsigned ext4_free_blocks_after_init(struct super_block *sb,
+ 					    ext4_group_t block_group,
+ 					    struct ext4_group_desc *gdp);
++extern unsigned ext4_num_base_meta_clusters(struct super_block *sb,
++					    ext4_group_t block_group);
++extern unsigned ext4_num_overhead_clusters(struct super_block *sb,
++					   ext4_group_t block_group,
++					   struct ext4_group_desc *gdp);
+ ext4_fsblk_t ext4_inode_to_goal_block(struct inode *);
+ 
+ /* dir.c */

commit fd034a84e1ea5c8c8d159cd2089c32e792c269b0
+Author: Theodore Ts'o 
+Date:   Fri Sep 9 18:42:51 2011 -0400
+
+    ext4: split out ext4_free_blocks_after_init()
+    
+    The function ext4_free_blocks_after_init() used to be a #define of
+    ext4_init_block_bitmap().  This actually made it difficult to
+    understand how the function worked, and made it hard make changes to
+    support clusters.  So as an initial cleanup, I've separated out the
+    functionality of initializing block bitmap from calculating the number
+    of free blocks in the new block group.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 8573e2bfb78a..735d9fcc72e6 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -102,74 +102,73 @@ static unsigned int num_blocks_in_group(struct super_block *sb,
+ 		return EXT4_BLOCKS_PER_GROUP(sb);
+ }
+ 
+-/* Initializes an uninitialized block bitmap if given, and returns the
+- * number of blocks free in the group. */
+-unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
+-		 ext4_group_t block_group, struct ext4_group_desc *gdp)
++/* Initializes an uninitialized block bitmap */
++void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
++			    ext4_group_t block_group,
++			    struct ext4_group_desc *gdp)
+ {
+ 	unsigned int bit, bit_max = num_base_meta_blocks(sb, block_group);
+-	ext4_group_t ngroups = ext4_get_groups_count(sb);
+-	unsigned group_blocks = num_blocks_in_group(sb, block_group);
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-
+-	if (bh) {
+-		J_ASSERT_BH(bh, buffer_locked(bh));
+-
+-		/* If checksum is bad mark all blocks used to prevent allocation
+-		 * essentially implementing a per-group read-only flag. */
+-		if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
+-			ext4_error(sb, "Checksum bad for group %u",
+-					block_group);
+-			ext4_free_blks_set(sb, gdp, 0);
+-			ext4_free_inodes_set(sb, gdp, 0);
+-			ext4_itable_unused_set(sb, gdp, 0);
+-			memset(bh->b_data, 0xff, sb->s_blocksize);
+-			return 0;
+-		}
+-		memset(bh->b_data, 0, sb->s_blocksize);
++	ext4_fsblk_t start, tmp;
++	int flex_bg = 0;
++
++	J_ASSERT_BH(bh, buffer_locked(bh));
++
++	/* If checksum is bad mark all blocks used to prevent allocation
++	 * essentially implementing a per-group read-only flag. */
++	if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
++		ext4_error(sb, "Checksum bad for group %u", block_group);
++		ext4_free_blks_set(sb, gdp, 0);
++		ext4_free_inodes_set(sb, gdp, 0);
++		ext4_itable_unused_set(sb, gdp, 0);
++		memset(bh->b_data, 0xff, sb->s_blocksize);
++		return;
+ 	}
++	memset(bh->b_data, 0, sb->s_blocksize);
+ 
+-	if (bh) {
+-		ext4_fsblk_t start, tmp;
+-		int flex_bg = 0;
++	for (bit = 0; bit < bit_max; bit++)
++		ext4_set_bit(bit, bh->b_data);
+ 
+-		for (bit = 0; bit < bit_max; bit++)
+-			ext4_set_bit(bit, bh->b_data);
++	start = ext4_group_first_block_no(sb, block_group);
+ 
+-		start = ext4_group_first_block_no(sb, block_group);
++	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG))
++		flex_bg = 1;
+ 
+-		if (EXT4_HAS_INCOMPAT_FEATURE(sb,
+-					      EXT4_FEATURE_INCOMPAT_FLEX_BG))
+-			flex_bg = 1;
++	/* Set bits for block and inode bitmaps, and inode table */
++	tmp = ext4_block_bitmap(sb, gdp);
++	if (!flex_bg || ext4_block_in_group(sb, tmp, block_group))
++		ext4_set_bit(tmp - start, bh->b_data);
+ 
+-		/* Set bits for block and inode bitmaps, and inode table */
+-		tmp = ext4_block_bitmap(sb, gdp);
+-		if (!flex_bg || ext4_block_in_group(sb, tmp, block_group))
+-			ext4_set_bit(tmp - start, bh->b_data);
++	tmp = ext4_inode_bitmap(sb, gdp);
++	if (!flex_bg || ext4_block_in_group(sb, tmp, block_group))
++		ext4_set_bit(tmp - start, bh->b_data);
+ 
+-		tmp = ext4_inode_bitmap(sb, gdp);
++	tmp = ext4_inode_table(sb, gdp);
++	for (; tmp < ext4_inode_table(sb, gdp) +
++		     sbi->s_itb_per_group; tmp++) {
+ 		if (!flex_bg || ext4_block_in_group(sb, tmp, block_group))
+ 			ext4_set_bit(tmp - start, bh->b_data);
+-
+-		tmp = ext4_inode_table(sb, gdp);
+-		for (; tmp < ext4_inode_table(sb, gdp) +
+-				sbi->s_itb_per_group; tmp++) {
+-			if (!flex_bg ||
+-				ext4_block_in_group(sb, tmp, block_group))
+-				ext4_set_bit(tmp - start, bh->b_data);
+-		}
+-		/*
+-		 * Also if the number of blocks within the group is
+-		 * less than the blocksize * 8 ( which is the size
+-		 * of bitmap ), set rest of the block bitmap to 1
+-		 */
+-		ext4_mark_bitmap_end(group_blocks, sb->s_blocksize * 8,
+-				     bh->b_data);
+ 	}
+-	return group_blocks - bit_max -
+-		ext4_group_used_meta_blocks(sb, block_group, gdp);
++	/*
++	 * Also if the number of blocks within the group is less than
++	 * the blocksize * 8 ( which is the size of bitmap ), set rest
++	 * of the block bitmap to 1
++	 */
++	ext4_mark_bitmap_end(num_blocks_in_group(sb, block_group),
++			     sb->s_blocksize * 8, bh->b_data);
+ }
+ 
++/* Return the number of free blocks in a block group.  It is used when
++ * the block bitmap is uninitialized, so we can't just count the bits
++ * in the bitmap. */
++unsigned ext4_free_blocks_after_init(struct super_block *sb,
++				     ext4_group_t block_group,
++				     struct ext4_group_desc *gdp)
++{
++	return num_blocks_in_group(sb, block_group) -
++		num_base_meta_blocks(sb, block_group) -
++		ext4_group_used_meta_blocks(sb, block_group, gdp);
++}
+ 
+ /*
+  * The free blocks are managed by bitmaps.  A file system contains several
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index f7257aa6bf81..b0b7b67e439d 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1763,12 +1763,13 @@ extern struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
+ extern int ext4_should_retry_alloc(struct super_block *sb, int *retries);
+ struct buffer_head *ext4_read_block_bitmap(struct super_block *sb,
+ 				      ext4_group_t block_group);
+-extern unsigned ext4_init_block_bitmap(struct super_block *sb,
+-				       struct buffer_head *bh,
+-				       ext4_group_t group,
+-				       struct ext4_group_desc *desc);
+-#define ext4_free_blocks_after_init(sb, group, desc)			\
+-		ext4_init_block_bitmap(sb, NULL, group, desc)
++extern void ext4_init_block_bitmap(struct super_block *sb,
++				   struct buffer_head *bh,
++				   ext4_group_t group,
++				   struct ext4_group_desc *desc);
++extern unsigned ext4_free_blocks_after_init(struct super_block *sb,
++					    ext4_group_t block_group,
++					    struct ext4_group_desc *gdp);
+ ext4_fsblk_t ext4_inode_to_goal_block(struct inode *);
+ 
+ /* dir.c */
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 9c63f273b550..b7a8130d0af4 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -816,7 +816,6 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
+ 	int ret2, err = 0;
+ 	struct inode *ret;
+ 	ext4_group_t i;
+-	int free = 0;
+ 	static int once = 1;
+ 	ext4_group_t flex_group;
+ 
+@@ -950,26 +949,21 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
+ 			goto fail;
+ 		}
+ 
+-		free = 0;
+-		ext4_lock_group(sb, group);
++		BUFFER_TRACE(block_bitmap_bh, "dirty block bitmap");
++		err = ext4_handle_dirty_metadata(handle, NULL, block_bitmap_bh);
++		brelse(block_bitmap_bh);
++
+ 		/* recheck and clear flag under lock if we still need to */
++		ext4_lock_group(sb, group);
+ 		if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
+-			free = ext4_free_blocks_after_init(sb, group, gdp);
+ 			gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
+-			ext4_free_blks_set(sb, gdp, free);
++			ext4_free_blks_set(sb, gdp,
++				ext4_free_blocks_after_init(sb, group, gdp));
+ 			gdp->bg_checksum = ext4_group_desc_csum(sbi, group,
+ 								gdp);
+ 		}
+ 		ext4_unlock_group(sb, group);
+ 
+-		/* Don't need to dirty bitmap block if we didn't change it */
+-		if (free) {
+-			BUFFER_TRACE(block_bitmap_bh, "dirty block bitmap");
+-			err = ext4_handle_dirty_metadata(handle,
+-							NULL, block_bitmap_bh);
+-		}
+-
+-		brelse(block_bitmap_bh);
+ 		if (err)
+ 			goto fail;
+ 	}

commit 49f7f9af4bb4d7972f3a35a74877937fec9f622d
+Author: Theodore Ts'o 
+Date:   Fri Sep 9 18:40:51 2011 -0400
+
+    ext4: factor out block group accounting into functions
+    
+    This makes it easier to understand how ext4_init_block_bitmap() works,
+    and it will assist when we split out ext4_free_blocks_after_init() in
+    the next commit.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index f8224adf496e..8573e2bfb78a 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -23,6 +23,9 @@
+ 
+ #include 
+ 
++static unsigned int num_base_meta_blocks(struct super_block *sb,
++					 ext4_group_t block_group);
++
+ /*
+  * balloc.c contains the blocks allocation and deallocation routines
+  */
+@@ -83,14 +86,30 @@ static int ext4_group_used_meta_blocks(struct super_block *sb,
+ 	return used_blocks;
+ }
+ 
++static unsigned int num_blocks_in_group(struct super_block *sb,
++					ext4_group_t block_group)
++{
++	if (block_group == ext4_get_groups_count(sb) - 1) {
++		/*
++		 * Even though mke2fs always initializes the first and
++		 * last group, just in case some other tool was used,
++		 * we need to make sure we calculate the right free
++		 * blocks.
++		 */
++		return ext4_blocks_count(EXT4_SB(sb)->s_es) -
++			ext4_group_first_block_no(sb, block_group);
++	} else
++		return EXT4_BLOCKS_PER_GROUP(sb);
++}
++
+ /* Initializes an uninitialized block bitmap if given, and returns the
+  * number of blocks free in the group. */
+ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
+ 		 ext4_group_t block_group, struct ext4_group_desc *gdp)
+ {
+-	int bit, bit_max;
++	unsigned int bit, bit_max = num_base_meta_blocks(sb, block_group);
+ 	ext4_group_t ngroups = ext4_get_groups_count(sb);
+-	unsigned free_blocks, group_blocks;
++	unsigned group_blocks = num_blocks_in_group(sb, block_group);
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 
+ 	if (bh) {
+@@ -110,35 +129,6 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
+ 		memset(bh->b_data, 0, sb->s_blocksize);
+ 	}
+ 
+-	/* Check for superblock and gdt backups in this group */
+-	bit_max = ext4_bg_has_super(sb, block_group);
+-
+-	if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG) ||
+-	    block_group < le32_to_cpu(sbi->s_es->s_first_meta_bg) *
+-			  sbi->s_desc_per_block) {
+-		if (bit_max) {
+-			bit_max += ext4_bg_num_gdb(sb, block_group);
+-			bit_max +=
+-				le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks);
+-		}
+-	} else { /* For META_BG_BLOCK_GROUPS */
+-		bit_max += ext4_bg_num_gdb(sb, block_group);
+-	}
+-
+-	if (block_group == ngroups - 1) {
+-		/*
+-		 * Even though mke2fs always initialize first and last group
+-		 * if some other tool enabled the EXT4_BG_BLOCK_UNINIT we need
+-		 * to make sure we calculate the right free blocks
+-		 */
+-		group_blocks = ext4_blocks_count(sbi->s_es) -
+-			ext4_group_first_block_no(sb, ngroups - 1);
+-	} else {
+-		group_blocks = EXT4_BLOCKS_PER_GROUP(sb);
+-	}
+-
+-	free_blocks = group_blocks - bit_max;
+-
+ 	if (bh) {
+ 		ext4_fsblk_t start, tmp;
+ 		int flex_bg = 0;
+@@ -176,7 +166,8 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
+ 		ext4_mark_bitmap_end(group_blocks, sb->s_blocksize * 8,
+ 				     bh->b_data);
+ 	}
+-	return free_blocks - ext4_group_used_meta_blocks(sb, block_group, gdp);
++	return group_blocks - bit_max -
++		ext4_group_used_meta_blocks(sb, block_group, gdp);
+ }
+ 
+ 
+@@ -620,6 +611,31 @@ unsigned long ext4_bg_num_gdb(struct super_block *sb, ext4_group_t group)
+ 
+ }
+ 
++/*
++ * This function returns the number of file system metadata blocks at
++ * the beginning of a block group, including the reserved gdt blocks.
++ */
++static unsigned int num_base_meta_blocks(struct super_block *sb,
++					 ext4_group_t block_group)
++{
++	struct ext4_sb_info *sbi = EXT4_SB(sb);
++	int num;
++
++	/* Check for superblock and gdt backups in this group */
++	num = ext4_bg_has_super(sb, block_group);
++
++	if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG) ||
++	    block_group < le32_to_cpu(sbi->s_es->s_first_meta_bg) *
++			  sbi->s_desc_per_block) {
++		if (num) {
++			num += ext4_bg_num_gdb(sb, block_group);
++			num += le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks);
++		}
++	} else { /* For META_BG_BLOCK_GROUPS */
++		num += ext4_bg_num_gdb(sb, block_group);
++	}
++	return num;
++}
+ /**
+  *	ext4_inode_to_goal_block - return a hint for block allocation
+  *	@inode: inode for block allocation

commit 7137d7a48e2213eb1f6d6529da14c2ed3706b795
+Author: Theodore Ts'o 
+Date:   Fri Sep 9 18:38:51 2011 -0400
+
+    ext4: convert instances of EXT4_BLOCKS_PER_GROUP to EXT4_CLUSTERS_PER_GROUP
+    
+    Change the places in fs/ext4/mballoc.c where EXT4_BLOCKS_PER_GROUP are
+    used to indicate the number of bits in a block bitmap (which is really
+    a cluster allocation bitmap in bigalloc file systems).  There are
+    still some places in the ext4 codebase where usage of
+    EXT4_BLOCKS_PER_GROUP needs to be audited/fixed, in code paths that
+    aren't used given the initial restricted assumptions for bigalloc.
+    These will need to be fixed before we can relax those restrictions.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 17a5a57c415a..81e28657a3c2 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -653,7 +653,7 @@ static void ext4_mb_mark_free_simple(struct super_block *sb,
+ 	ext4_grpblk_t chunk;
+ 	unsigned short border;
+ 
+-	BUG_ON(len > EXT4_BLOCKS_PER_GROUP(sb));
++	BUG_ON(len > EXT4_CLUSTERS_PER_GROUP(sb));
+ 
+ 	border = 2 << sb->s_blocksize_bits;
+ 
+@@ -705,7 +705,7 @@ void ext4_mb_generate_buddy(struct super_block *sb,
+ 				void *buddy, void *bitmap, ext4_group_t group)
+ {
+ 	struct ext4_group_info *grp = ext4_get_group_info(sb, group);
+-	ext4_grpblk_t max = EXT4_BLOCKS_PER_GROUP(sb);
++	ext4_grpblk_t max = EXT4_CLUSTERS_PER_GROUP(sb);
+ 	ext4_grpblk_t i = 0;
+ 	ext4_grpblk_t first;
+ 	ext4_grpblk_t len;
+@@ -1624,8 +1624,8 @@ static void ext4_mb_measure_extent(struct ext4_allocation_context *ac,
+ 	struct ext4_free_extent *gex = &ac->ac_g_ex;
+ 
+ 	BUG_ON(ex->fe_len <= 0);
+-	BUG_ON(ex->fe_len > EXT4_BLOCKS_PER_GROUP(ac->ac_sb));
+-	BUG_ON(ex->fe_start >= EXT4_BLOCKS_PER_GROUP(ac->ac_sb));
++	BUG_ON(ex->fe_len > EXT4_CLUSTERS_PER_GROUP(ac->ac_sb));
++	BUG_ON(ex->fe_start >= EXT4_CLUSTERS_PER_GROUP(ac->ac_sb));
+ 	BUG_ON(ac->ac_status != AC_STATUS_CONTINUE);
+ 
+ 	ac->ac_found++;
+@@ -1823,8 +1823,8 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
+ 
+ 	while (free && ac->ac_status == AC_STATUS_CONTINUE) {
+ 		i = mb_find_next_zero_bit(bitmap,
+-						EXT4_BLOCKS_PER_GROUP(sb), i);
+-		if (i >= EXT4_BLOCKS_PER_GROUP(sb)) {
++						EXT4_CLUSTERS_PER_GROUP(sb), i);
++		if (i >= EXT4_CLUSTERS_PER_GROUP(sb)) {
+ 			/*
+ 			 * IF we have corrupt bitmap, we won't find any
+ 			 * free blocks even though group info says we
+@@ -1887,7 +1887,7 @@ void ext4_mb_scan_aligned(struct ext4_allocation_context *ac,
+ 	do_div(a, sbi->s_stripe);
+ 	i = (a * sbi->s_stripe) - first_group_block;
+ 
+-	while (i < EXT4_BLOCKS_PER_GROUP(sb)) {
++	while (i < EXT4_CLUSTERS_PER_GROUP(sb)) {
+ 		if (!mb_test_bit(i, bitmap)) {
+ 			max = mb_find_extent(e4b, 0, i, sbi->s_stripe, &ex);
+ 			if (max >= sbi->s_stripe) {
+@@ -3036,7 +3036,7 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
+ 	}
+ 	BUG_ON(start + size <= ac->ac_o_ex.fe_logical &&
+ 			start > ac->ac_o_ex.fe_logical);
+-	BUG_ON(size <= 0 || size > EXT4_BLOCKS_PER_GROUP(ac->ac_sb));
++	BUG_ON(size <= 0 || size > EXT4_CLUSTERS_PER_GROUP(ac->ac_sb));
+ 
+ 	/* now prepare goal request */
+ 
+@@ -3690,7 +3690,7 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
+ 	}
+ 
+ 	if (needed == 0)
+-		needed = EXT4_BLOCKS_PER_GROUP(sb) + 1;
++		needed = EXT4_CLUSTERS_PER_GROUP(sb) + 1;
+ 
+ 	INIT_LIST_HEAD(&list);
+ repeat:
+@@ -4007,8 +4007,8 @@ ext4_mb_initialize_context(struct ext4_allocation_context *ac,
+ 	len = ar->len;
+ 
+ 	/* just a dirty hack to filter too big requests  */
+-	if (len >= EXT4_BLOCKS_PER_GROUP(sb) - 10)
+-		len = EXT4_BLOCKS_PER_GROUP(sb) - 10;
++	if (len >= EXT4_CLUSTERS_PER_GROUP(sb) - 10)
++		len = EXT4_CLUSTERS_PER_GROUP(sb) - 10;
+ 
+ 	/* start searching from the goal */
+ 	goal = ar->goal;
+@@ -4552,8 +4552,8 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 	 * Check to see if we are freeing blocks across a group
+ 	 * boundary.
+ 	 */
+-	if (bit + count > EXT4_BLOCKS_PER_GROUP(sb)) {
+-		overflow = bit + count - EXT4_BLOCKS_PER_GROUP(sb);
++	if (bit + count > EXT4_CLUSTERS_PER_GROUP(sb)) {
++		overflow = bit + count - EXT4_CLUSTERS_PER_GROUP(sb);
+ 		count -= overflow;
+ 	}
+ 	bitmap_bh = ext4_read_block_bitmap(sb, block_group);
+@@ -4948,7 +4948,7 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
+ 	struct ext4_group_info *grp;
+ 	ext4_group_t first_group, last_group;
+ 	ext4_group_t group, ngroups = ext4_get_groups_count(sb);
+-	ext4_grpblk_t cnt = 0, first_block, last_block;
++	ext4_grpblk_t cnt = 0, first_cluster, last_cluster;
+ 	uint64_t start, len, minlen, trimmed = 0;
+ 	ext4_fsblk_t first_data_blk =
+ 			le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
+@@ -4958,7 +4958,7 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
+ 	len = range->len >> sb->s_blocksize_bits;
+ 	minlen = range->minlen >> sb->s_blocksize_bits;
+ 
+-	if (unlikely(minlen > EXT4_BLOCKS_PER_GROUP(sb)))
++	if (unlikely(minlen > EXT4_CLUSTERS_PER_GROUP(sb)))
+ 		return -EINVAL;
+ 	if (start + len <= first_data_blk)
+ 		goto out;
+@@ -4969,11 +4969,11 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
+ 
+ 	/* Determine first and last group to examine based on start and len */
+ 	ext4_get_group_no_and_offset(sb, (ext4_fsblk_t) start,
+-				     &first_group, &first_block);
++				     &first_group, &first_cluster);
+ 	ext4_get_group_no_and_offset(sb, (ext4_fsblk_t) (start + len),
+-				     &last_group, &last_block);
++				     &last_group, &last_cluster);
+ 	last_group = (last_group > ngroups - 1) ? ngroups - 1 : last_group;
+-	last_block = EXT4_BLOCKS_PER_GROUP(sb);
++	last_cluster = EXT4_CLUSTERS_PER_GROUP(sb);
+ 
+ 	if (first_group > last_group)
+ 		return -EINVAL;
+@@ -4993,20 +4993,20 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
+ 		 * change it for the last group in which case start +
+ 		 * len < EXT4_BLOCKS_PER_GROUP(sb).
+ 		 */
+-		if (first_block + len < EXT4_BLOCKS_PER_GROUP(sb))
+-			last_block = first_block + len;
+-		len -= last_block - first_block;
++		if (first_cluster + len < EXT4_CLUSTERS_PER_GROUP(sb))
++			last_cluster = first_cluster + len;
++		len -= last_cluster - first_cluster;
+ 
+ 		if (grp->bb_free >= minlen) {
+-			cnt = ext4_trim_all_free(sb, group, first_block,
+-						last_block, minlen);
++			cnt = ext4_trim_all_free(sb, group, first_cluster,
++						last_cluster, minlen);
+ 			if (cnt < 0) {
+ 				ret = cnt;
+ 				break;
+ 			}
+ 		}
+ 		trimmed += cnt;
+-		first_block = 0;
++		first_cluster = 0;
+ 	}
+ 	range->len = trimmed * sb->s_blocksize;
+ 

commit bab08ab9646288f1b0b72a7aaeecdff94bd62c18
+Author: Theodore Ts'o 
+Date:   Fri Sep 9 18:36:51 2011 -0400
+
+    ext4: enforce bigalloc restrictions (e.g., no online resizing, etc.)
+    
+    At least initially if the bigalloc feature is enabled, we will not
+    support non-extent mapped inodes, online resizing, online defrag, or
+    the FITRIM ioctl.  This simplifies the initial implementation.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
+index ea704dff8669..3cfc73fbca8e 100644
+--- a/fs/ext4/indirect.c
++++ b/fs/ext4/indirect.c
+@@ -699,6 +699,13 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
+ 	/*
+ 	 * Okay, we need to do block allocation.
+ 	*/
++	if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
++				       EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {
++		EXT4_ERROR_INODE(inode, "Can't allocate blocks for "
++				 "non-extent mapped inodes with bigalloc");
++		return -ENOSPC;
++	}
++
+ 	goal = ext4_find_goal(inode, map->m_lblk, partial);
+ 
+ 	/* the number of blocks need to allocate for [d,t]indirect blocks */
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 6ecc93979e48..904a9a623dab 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -3358,6 +3358,11 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length)
+ 		return -ENOTSUPP;
+ 	}
+ 
++	if (EXT4_SB(inode->i_sb)->s_cluster_ratio > 1) {
++		/* TODO: Add support for bigalloc file systems */
++		return -ENOTSUPP;
++	}
++
+ 	return ext4_ext_punch_hole(file, offset, length);
+ }
+ 
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index f18bfe37aff8..2046d699b4a7 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -21,6 +21,7 @@
+ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ {
+ 	struct inode *inode = filp->f_dentry->d_inode;
++	struct super_block *sb = inode->i_sb;
+ 	struct ext4_inode_info *ei = EXT4_I(inode);
+ 	unsigned int flags;
+ 
+@@ -183,7 +184,6 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 		 * Returns 1 if it slept, else zero.
+ 		 */
+ 		{
+-			struct super_block *sb = inode->i_sb;
+ 			DECLARE_WAITQUEUE(wait, current);
+ 			int ret = 0;
+ 
+@@ -199,7 +199,6 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ #endif
+ 	case EXT4_IOC_GROUP_EXTEND: {
+ 		ext4_fsblk_t n_blocks_count;
+-		struct super_block *sb = inode->i_sb;
+ 		int err, err2=0;
+ 
+ 		err = ext4_resize_begin(sb);
+@@ -209,6 +208,13 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 		if (get_user(n_blocks_count, (__u32 __user *)arg))
+ 			return -EFAULT;
+ 
++		if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
++			       EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {
++			ext4_msg(sb, KERN_ERR,
++				 "Online resizing not supported with bigalloc");
++			return -EOPNOTSUPP;
++		}
++
+ 		err = mnt_want_write(filp->f_path.mnt);
+ 		if (err)
+ 			return err;
+@@ -250,6 +256,13 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 			goto mext_out;
+ 		}
+ 
++		if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
++			       EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {
++			ext4_msg(sb, KERN_ERR,
++				 "Online defrag not supported with bigalloc");
++			return -EOPNOTSUPP;
++		}
++
+ 		err = mnt_want_write(filp->f_path.mnt);
+ 		if (err)
+ 			goto mext_out;
+@@ -270,7 +283,6 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 
+ 	case EXT4_IOC_GROUP_ADD: {
+ 		struct ext4_new_group_data input;
+-		struct super_block *sb = inode->i_sb;
+ 		int err, err2=0;
+ 
+ 		err = ext4_resize_begin(sb);
+@@ -281,6 +293,13 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 				sizeof(input)))
+ 			return -EFAULT;
+ 
++		if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
++			       EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {
++			ext4_msg(sb, KERN_ERR,
++				 "Online resizing not supported with bigalloc");
++			return -EOPNOTSUPP;
++		}
++
+ 		err = mnt_want_write(filp->f_path.mnt);
+ 		if (err)
+ 			return err;
+@@ -337,7 +356,6 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 
+ 	case FITRIM:
+ 	{
+-		struct super_block *sb = inode->i_sb;
+ 		struct request_queue *q = bdev_get_queue(sb->s_bdev);
+ 		struct fstrim_range range;
+ 		int ret = 0;
+@@ -348,6 +366,13 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 		if (!blk_queue_discard(q))
+ 			return -EOPNOTSUPP;
+ 
++		if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
++			       EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {
++			ext4_msg(sb, KERN_ERR,
++				 "FITRIM not supported with bigalloc");
++			return -EOPNOTSUPP;
++		}
++
+ 		if (copy_from_user(&range, (struct fstrim_range *)arg,
+ 		    sizeof(range)))
+ 			return -EFAULT;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 823e7d9deee2..25a4bfe3f39f 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2701,6 +2701,13 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly)
+ 			return 0;
+ 		}
+ 	}
++	if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_BIGALLOC) &&
++	    !EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
++		ext4_msg(sb, KERN_ERR,
++			 "Can't support bigalloc feature without "
++			 "extents feature\n");
++		return 0;
++	}
+ 	return 1;
+ }
+ 

commit 281b59959707dfae03ce038cdf231bf4904e170c
+Author: Theodore Ts'o 
+Date:   Fri Sep 9 18:34:51 2011 -0400
+
+    ext4: read-only support for bigalloc file systems
+    
+    This adds supports for bigalloc file systems.  It teaches the mount
+    code just enough about bigalloc superblock fields that it will mount
+    the file system without freaking out that the number of blocks per
+    group is too big.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 48ae98819d35..f7257aa6bf81 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -239,8 +239,11 @@ struct ext4_io_submit {
+ # define EXT4_BLOCK_SIZE(s)		(EXT4_MIN_BLOCK_SIZE << (s)->s_log_block_size)
+ #endif
+ #define	EXT4_ADDR_PER_BLOCK(s)		(EXT4_BLOCK_SIZE(s) / sizeof(__u32))
++#define EXT4_CLUSTER_SIZE(s)		(EXT4_BLOCK_SIZE(s) << \
++					 EXT4_SB(s)->s_cluster_bits)
+ #ifdef __KERNEL__
+ # define EXT4_BLOCK_SIZE_BITS(s)	((s)->s_blocksize_bits)
++# define EXT4_CLUSTER_BITS(s)		(EXT4_SB(s)->s_cluster_bits)
+ #else
+ # define EXT4_BLOCK_SIZE_BITS(s)	((s)->s_log_block_size + 10)
+ #endif
+@@ -306,6 +309,7 @@ struct flex_groups {
+ #define EXT4_DESC_SIZE(s)		(EXT4_SB(s)->s_desc_size)
+ #ifdef __KERNEL__
+ # define EXT4_BLOCKS_PER_GROUP(s)	(EXT4_SB(s)->s_blocks_per_group)
++# define EXT4_CLUSTERS_PER_GROUP(s)	(EXT4_SB(s)->s_clusters_per_group)
+ # define EXT4_DESC_PER_BLOCK(s)		(EXT4_SB(s)->s_desc_per_block)
+ # define EXT4_INODES_PER_GROUP(s)	(EXT4_SB(s)->s_inodes_per_group)
+ # define EXT4_DESC_PER_BLOCK_BITS(s)	(EXT4_SB(s)->s_desc_per_block_bits)
+@@ -975,9 +979,9 @@ struct ext4_super_block {
+ /*10*/	__le32	s_free_inodes_count;	/* Free inodes count */
+ 	__le32	s_first_data_block;	/* First Data Block */
+ 	__le32	s_log_block_size;	/* Block size */
+-	__le32	s_obso_log_frag_size;	/* Obsoleted fragment size */
++	__le32	s_log_cluster_size;	/* Allocation cluster size */
+ /*20*/	__le32	s_blocks_per_group;	/* # Blocks per group */
+-	__le32	s_obso_frags_per_group;	/* Obsoleted fragments per group */
++	__le32	s_clusters_per_group;	/* # Clusters per group */
+ 	__le32	s_inodes_per_group;	/* # Inodes per group */
+ 	__le32	s_mtime;		/* Mount time */
+ /*30*/	__le32	s_wtime;		/* Write time */
+@@ -1073,7 +1077,10 @@ struct ext4_super_block {
+ 	__u8	s_last_error_func[32];	/* function where the error happened */
+ #define EXT4_S_ERR_END offsetof(struct ext4_super_block, s_mount_opts)
+ 	__u8	s_mount_opts[64];
+-	__le32	s_reserved[112];        /* Padding to the end of the block */
++	__le32	s_usr_quota_inum;	/* inode for tracking user quota */
++	__le32	s_grp_quota_inum;	/* inode for tracking group quota */
++	__le32	s_overhead_clusters;	/* overhead blocks/clusters in fs */
++	__le32  s_reserved[109];        /* Padding to the end of the block */
+ };
+ 
+ #define EXT4_S_ERR_LEN (EXT4_S_ERR_END - EXT4_S_ERR_START)
+@@ -1093,6 +1100,7 @@ struct ext4_sb_info {
+ 	unsigned long s_desc_size;	/* Size of a group descriptor in bytes */
+ 	unsigned long s_inodes_per_block;/* Number of inodes per block */
+ 	unsigned long s_blocks_per_group;/* Number of blocks in a group */
++	unsigned long s_clusters_per_group; /* Number of clusters in a group */
+ 	unsigned long s_inodes_per_group;/* Number of inodes in a group */
+ 	unsigned long s_itb_per_group;	/* Number of inode table blocks per group */
+ 	unsigned long s_gdb_count;	/* Number of group descriptor blocks */
+@@ -1101,6 +1109,8 @@ struct ext4_sb_info {
+ 	ext4_group_t s_blockfile_groups;/* Groups acceptable for non-extent files */
+ 	unsigned long s_overhead_last;  /* Last calculated overhead */
+ 	unsigned long s_blocks_last;    /* Last seen block count */
++	unsigned int s_cluster_ratio;	/* Number of blocks per cluster */
++	unsigned int s_cluster_bits;	/* log2 of s_cluster_ratio */
+ 	loff_t s_bitmap_maxbytes;	/* max bytes for bitmap files */
+ 	struct buffer_head * s_sbh;	/* Buffer containing the super block */
+ 	struct ext4_super_block *s_es;	/* Pointer to the super block in the buffer */
+@@ -1367,6 +1377,7 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei)
+ #define EXT4_FEATURE_RO_COMPAT_DIR_NLINK	0x0020
+ #define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE	0x0040
+ #define EXT4_FEATURE_RO_COMPAT_QUOTA		0x0100
++#define EXT4_FEATURE_RO_COMPAT_BIGALLOC		0x0200
+ 
+ #define EXT4_FEATURE_INCOMPAT_COMPRESSION	0x0001
+ #define EXT4_FEATURE_INCOMPAT_FILETYPE		0x0002
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 5dcd0dacc591..823e7d9deee2 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1953,7 +1953,7 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
+ 		res = MS_RDONLY;
+ 	}
+ 	if (read_only)
+-		return res;
++		goto done;
+ 	if (!(sbi->s_mount_state & EXT4_VALID_FS))
+ 		ext4_msg(sb, KERN_WARNING, "warning: mounting unchecked fs, "
+ 			 "running e2fsck is recommended");
+@@ -1984,6 +1984,7 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
+ 		EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+ 
+ 	ext4_commit_super(sb, 1);
++done:
+ 	if (test_opt(sb, DEBUG))
+ 		printk(KERN_INFO "[EXT4 FS bs=%lu, gc=%u, "
+ 				"bpg=%lu, ipg=%lu, mo=%04x, mo2=%04x]\n",
+@@ -3105,10 +3106,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	char *cp;
+ 	const char *descr;
+ 	int ret = -ENOMEM;
+-	int blocksize;
++	int blocksize, clustersize;
+ 	unsigned int db_count;
+ 	unsigned int i;
+-	int needs_recovery, has_huge_files;
++	int needs_recovery, has_huge_files, has_bigalloc;
+ 	__u64 blocks_count;
+ 	int err;
+ 	unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO;
+@@ -3412,12 +3413,53 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		sb->s_dirt = 1;
+ 	}
+ 
+-	if (sbi->s_blocks_per_group > blocksize * 8) {
+-		ext4_msg(sb, KERN_ERR,
+-		       "#blocks per group too big: %lu",
+-		       sbi->s_blocks_per_group);
+-		goto failed_mount;
++	/* Handle clustersize */
++	clustersize = BLOCK_SIZE << le32_to_cpu(es->s_log_cluster_size);
++	has_bigalloc = EXT4_HAS_RO_COMPAT_FEATURE(sb,
++				EXT4_FEATURE_RO_COMPAT_BIGALLOC);
++	if (has_bigalloc) {
++		if (clustersize < blocksize) {
++			ext4_msg(sb, KERN_ERR,
++				 "cluster size (%d) smaller than "
++				 "block size (%d)", clustersize, blocksize);
++			goto failed_mount;
++		}
++		sbi->s_cluster_bits = le32_to_cpu(es->s_log_cluster_size) -
++			le32_to_cpu(es->s_log_block_size);
++		sbi->s_clusters_per_group =
++			le32_to_cpu(es->s_clusters_per_group);
++		if (sbi->s_clusters_per_group > blocksize * 8) {
++			ext4_msg(sb, KERN_ERR,
++				 "#clusters per group too big: %lu",
++				 sbi->s_clusters_per_group);
++			goto failed_mount;
++		}
++		if (sbi->s_blocks_per_group !=
++		    (sbi->s_clusters_per_group * (clustersize / blocksize))) {
++			ext4_msg(sb, KERN_ERR, "blocks per group (%lu) and "
++				 "clusters per group (%lu) inconsistent",
++				 sbi->s_blocks_per_group,
++				 sbi->s_clusters_per_group);
++			goto failed_mount;
++		}
++	} else {
++		if (clustersize != blocksize) {
++			ext4_warning(sb, "fragment/cluster size (%d) != "
++				     "block size (%d)", clustersize,
++				     blocksize);
++			clustersize = blocksize;
++		}
++		if (sbi->s_blocks_per_group > blocksize * 8) {
++			ext4_msg(sb, KERN_ERR,
++				 "#blocks per group too big: %lu",
++				 sbi->s_blocks_per_group);
++			goto failed_mount;
++		}
++		sbi->s_clusters_per_group = sbi->s_blocks_per_group;
++		sbi->s_cluster_bits = 0;
+ 	}
++	sbi->s_cluster_ratio = clustersize / blocksize;
++
+ 	if (sbi->s_inodes_per_group > blocksize * 8) {
+ 		ext4_msg(sb, KERN_ERR,
+ 		       "#inodes per group too big: %lu",

commit 7c2e70879fc0949b4220ee61b7c4553f6976a94d
+Author: Theodore Ts'o 
+Date:   Fri Sep 9 18:28:51 2011 -0400
+
+    ext4: add ext4-specific kludge to avoid an oops after the disk disappears
+    
+    The del_gendisk() function uninitializes the disk-specific data
+    structures, including the bdi structure, without telling anyone
+    else.  Once this happens, any attempt to call mark_buffer_dirty()
+    (for example, by ext4_commit_super), will cause a kernel OOPS.
+    
+    Fix this for now until we can fix things in an architecturally correct
+    way.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index ee2f74a7084d..5dcd0dacc591 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -414,6 +414,22 @@ static void save_error_info(struct super_block *sb, const char *func,
+ 	ext4_commit_super(sb, 1);
+ }
+ 
++/*
++ * The del_gendisk() function uninitializes the disk-specific data
++ * structures, including the bdi structure, without telling anyone
++ * else.  Once this happens, any attempt to call mark_buffer_dirty()
++ * (for example, by ext4_commit_super), will cause a kernel OOPS.
++ * This is a kludge to prevent these oops until we can put in a proper
++ * hook in del_gendisk() to inform the VFS and file system layers.
++ */
++static int block_device_ejected(struct super_block *sb)
++{
++	struct inode *bd_inode = sb->s_bdev->bd_inode;
++	struct backing_dev_info *bdi = bd_inode->i_mapping->backing_dev_info;
++
++	return bdi->dev == NULL;
++}
++
+ 
+ /* Deal with the reporting of failure conditions on a filesystem such as
+  * inconsistencies detected or read IO failures.
+@@ -4072,7 +4088,7 @@ static int ext4_commit_super(struct super_block *sb, int sync)
+ 	struct buffer_head *sbh = EXT4_SB(sb)->s_sbh;
+ 	int error = 0;
+ 
+-	if (!sbh)
++	if (!sbh || block_device_ejected(sb))
+ 		return error;
+ 	if (buffer_write_io_error(sbh)) {
+ 		/*

commit decbd919f4bb9cb698486880c026c4104b13d3c3
+Author: Theodore Ts'o 
+Date:   Tue Sep 6 02:37:06 2011 -0400
+
+    ext4: only call ext4_jbd2_file_inode when an inode has been extended
+    
+    In delayed allocation mode, it's important to only call
+    ext4_jbd2_file_inode when the file has been extended.  This is
+    necessary to avoid a race which first got introduced in commit
+    678aaf481, but which was made much more common with the introduction
+    of the "punch hole" functionality.  (Especially when dioread_nolock
+    was enabled; when I could reliably reproduce this problem with
+    xfstests #74.)
+    
+    The race is this: If while trying to writeback a delayed allocation
+    inode, there is a need to map delalloc blocks, and we run out of space
+    in the journal, *and* at the same time the inode is already on the
+    committing transaction's t_inode_list (because for example while doing
+    the punch hole operation, ext4_jbd2_file_inode() is called), then the
+    commit operation will wait for the inode to finish all of its pending
+    writebacks by calling filemap_fdatawait(), but since that inode has
+    one or more pages with the PageWriteback flag set, the commit
+    operation will wait forever, and the so the writeback of the inode can
+    never take place, and the kjournald thread and the writeback thread
+    end up waiting for each other --- forever.
+    
+    It's important at this point to recall why an inode is placed on the
+    t_inode_list; it is to provide the data=ordered guarantees that we
+    don't end up exposing stale data.  In the case where we are truncating
+    or punching a hole in the inode, there is no possibility that stale
+    data could be exposed in the first place, so we don't need to put the
+    inode on the t_inode_list!
+    
+    The right long-term fix is to get rid of data=ordered mode altogether,
+    and only update the extent tree or indirect blocks after the data has
+    been written.  Until then, this change will also avoid some
+    unnecessary waiting in the commit operation.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Allison Henderson 
+    Cc: Jan Kara 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index d1b1ef71e5b7..f86b149fb8b1 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1471,13 +1471,13 @@ static void mpage_da_map_and_submit(struct mpage_da_data *mpd)
+ 
+ 		for (i = 0; i < map.m_len; i++)
+ 			unmap_underlying_metadata(bdev, map.m_pblk + i);
+-	}
+ 
+-	if (ext4_should_order_data(mpd->inode)) {
+-		err = ext4_jbd2_file_inode(handle, mpd->inode);
+-		if (err)
+-			/* This only happens if the journal is aborted */
+-			return;
++		if (ext4_should_order_data(mpd->inode)) {
++			err = ext4_jbd2_file_inode(handle, mpd->inode);
++			if (err)
++				/* Only if the journal is aborted */
++				return;
++		}
+ 	}
+ 
+ 	/*
+@@ -3173,12 +3173,8 @@ int ext4_discard_partial_page_buffers_no_lock(handle_t *handle,
+ 		err = 0;
+ 		if (ext4_should_journal_data(inode)) {
+ 			err = ext4_handle_dirty_metadata(handle, inode, bh);
+-		} else {
+-			if (ext4_should_order_data(inode) &&
+-			   EXT4_I(inode)->jinode)
+-				err = ext4_jbd2_file_inode(handle, inode);
++		} else
+ 			mark_buffer_dirty(bh);
+-		}
+ 
+ 		BUFFER_TRACE(bh, "Partial buffer zeroed");
+ next:
+@@ -3301,11 +3297,8 @@ int ext4_block_zero_page_range(handle_t *handle,
+ 	err = 0;
+ 	if (ext4_should_journal_data(inode)) {
+ 		err = ext4_handle_dirty_metadata(handle, inode, bh);
+-	} else {
+-		if (ext4_should_order_data(inode) && EXT4_I(inode)->jinode)
+-			err = ext4_jbd2_file_inode(handle, inode);
++	} else
+ 		mark_buffer_dirty(bh);
+-	}
+ 
+ unlock:
+ 	unlock_page(page);

commit 9ea7a0df63630ad8197716cd313ea66e28906fc0
+Author: Theodore Ts'o 
+Date:   Sun Sep 4 10:18:14 2011 -0400
+
+    jbd2: add debugging information to jbd2_journal_dirty_metadata()
+    
+    Add debugging information in case jbd2_journal_dirty_metadata() is
+    called with a buffer_head which didn't have
+    jbd2_journal_get_write_access() called on it, or if the journal_head
+    has the wrong transaction in it.  In addition, return an error code.
+    This won't change anything for ocfs2, which will BUG_ON() the non-zero
+    exit code.
+    
+    For ext4, the caller of this function is ext4_handle_dirty_metadata(),
+    and on seeing a non-zero return code, will call __ext4_journal_stop(),
+    which will print the function and line number of the (buggy) calling
+    function and abort the journal.  This will allow us to recover instead
+    of bug halting, which is better from a robustness and reliability
+    point of view.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
+index f5240aa15601..aca179017582 100644
+--- a/fs/ext4/ext4_jbd2.c
++++ b/fs/ext4/ext4_jbd2.c
+@@ -109,9 +109,11 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
+ 
+ 	if (ext4_handle_valid(handle)) {
+ 		err = jbd2_journal_dirty_metadata(handle, bh);
+-		if (err)
+-			ext4_journal_abort_handle(where, line, __func__,
+-						  bh, handle, err);
++		if (err) {
++			/* Errors can only happen if there is a bug */
++			handle->h_err = err;
++			__ext4_journal_stop(where, line, handle);
++		}
+ 	} else {
+ 		if (inode)
+ 			mark_buffer_dirty_inode(bh, inode);
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 9124cd24e093..2c5216a8d03b 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -96,13 +96,17 @@ static int ext4_ext_get_access(handle_t *handle, struct inode *inode,
+  *  - ENOMEM
+  *  - EIO
+  */
+-static int ext4_ext_dirty(handle_t *handle, struct inode *inode,
+-				struct ext4_ext_path *path)
++#define ext4_ext_dirty(handle, inode, path) \
++		__ext4_ext_dirty(__func__, __LINE__, (handle), (inode), (path))
++static int __ext4_ext_dirty(const char *where, unsigned int line,
++			    handle_t *handle, struct inode *inode,
++			    struct ext4_ext_path *path)
+ {
+ 	int err;
+ 	if (path->p_bh) {
+ 		/* path points to block */
+-		err = ext4_handle_dirty_metadata(handle, inode, path->p_bh);
++		err = __ext4_handle_dirty_metadata(where, line, handle,
++						   inode, path->p_bh);
+ 	} else {
+ 		/* path points to leaf/index in inode body */
+ 		err = ext4_mark_inode_dirty(handle, inode);
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index 2d7109414cdd..cb56fe9aaabb 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -1049,6 +1049,10 @@ void jbd2_buffer_abort_trigger(struct journal_head *jh,
+  * mark dirty metadata which needs to be journaled as part of the current
+  * transaction.
+  *
++ * The buffer must have previously had jbd2_journal_get_write_access()
++ * called so that it has a valid journal_head attached to the buffer
++ * head.
++ *
+  * The buffer is placed on the transaction's metadata list and is marked
+  * as belonging to the transaction.
+  *
+@@ -1065,11 +1069,16 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
+ 	transaction_t *transaction = handle->h_transaction;
+ 	journal_t *journal = transaction->t_journal;
+ 	struct journal_head *jh = bh2jh(bh);
++	int ret = 0;
+ 
+ 	jbd_debug(5, "journal_head %p\n", jh);
+ 	JBUFFER_TRACE(jh, "entry");
+ 	if (is_handle_aborted(handle))
+ 		goto out;
++	if (!buffer_jbd(bh)) {
++		ret = -EUCLEAN;
++		goto out;
++	}
+ 
+ 	jbd_lock_bh_state(bh);
+ 
+@@ -1093,8 +1102,20 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
+ 	 */
+ 	if (jh->b_transaction == transaction && jh->b_jlist == BJ_Metadata) {
+ 		JBUFFER_TRACE(jh, "fastpath");
+-		J_ASSERT_JH(jh, jh->b_transaction ==
+-					journal->j_running_transaction);
++		if (unlikely(jh->b_transaction !=
++			     journal->j_running_transaction)) {
++			printk(KERN_EMERG "JBD: %s: "
++			       "jh->b_transaction (%llu, %p, %u) != "
++			       "journal->j_running_transaction (%p, %u)",
++			       journal->j_devname,
++			       (unsigned long long) bh->b_blocknr,
++			       jh->b_transaction,
++			       jh->b_transaction ? jh->b_transaction->t_tid : 0,
++			       journal->j_running_transaction,
++			       journal->j_running_transaction ?
++			       journal->j_running_transaction->t_tid : 0);
++			ret = -EINVAL;
++		}
+ 		goto out_unlock_bh;
+ 	}
+ 
+@@ -1108,9 +1129,32 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
+ 	 */
+ 	if (jh->b_transaction != transaction) {
+ 		JBUFFER_TRACE(jh, "already on other transaction");
+-		J_ASSERT_JH(jh, jh->b_transaction ==
+-					journal->j_committing_transaction);
+-		J_ASSERT_JH(jh, jh->b_next_transaction == transaction);
++		if (unlikely(jh->b_transaction !=
++			     journal->j_committing_transaction)) {
++			printk(KERN_EMERG "JBD: %s: "
++			       "jh->b_transaction (%llu, %p, %u) != "
++			       "journal->j_committing_transaction (%p, %u)",
++			       journal->j_devname,
++			       (unsigned long long) bh->b_blocknr,
++			       jh->b_transaction,
++			       jh->b_transaction ? jh->b_transaction->t_tid : 0,
++			       journal->j_committing_transaction,
++			       journal->j_committing_transaction ?
++			       journal->j_committing_transaction->t_tid : 0);
++			ret = -EINVAL;
++		}
++		if (unlikely(jh->b_next_transaction != transaction)) {
++			printk(KERN_EMERG "JBD: %s: "
++			       "jh->b_next_transaction (%llu, %p, %u) != "
++			       "transaction (%p, %u)",
++			       journal->j_devname,
++			       (unsigned long long) bh->b_blocknr,
++			       jh->b_next_transaction,
++			       jh->b_next_transaction ?
++			       jh->b_next_transaction->t_tid : 0,
++			       transaction, transaction->t_tid);
++			ret = -EINVAL;
++		}
+ 		/* And this case is illegal: we can't reuse another
+ 		 * transaction's data buffer, ever. */
+ 		goto out_unlock_bh;
+@@ -1127,7 +1171,9 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
+ 	jbd_unlock_bh_state(bh);
+ out:
+ 	JBUFFER_TRACE(jh, "exit");
+-	return 0;
++	if (ret)
++		__WARN();	/* All errors are bugs, so dump the stack */
++	return ret;
+ }
+ 
+ /*

commit 56889787cfa77dfd96f0b3a3e6a4f26c2e4a5134
+Author: Theodore Ts'o 
+Date:   Sat Sep 3 18:22:38 2011 -0400
+
+    ext4: improve handling of conflicting mount options
+    
+    If the user explicitly specifies conflicting mount options for
+    delalloc or dioread_nolock and data=journal, fail the mount, instead
+    of printing a warning and continuing (since many user's won't look at
+    dmesg and notice the warning).
+    
+    Also, print a single warning that data=journal implies that delayed
+    allocation is not on by default (since it's not supported), and
+    furthermore that O_DIRECT is not supported.  Improve the text in
+    Documentation/filesystems/ext4.txt so this is clear there as well.
+    
+    Similarly, if the dioread_nolock mount option is specified when the
+    file system block size != PAGE_SIZE, fail the mount instead of
+    printing a warning message and ignoring the mount option.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
+index 232a575a0c48..168242b5c045 100644
+--- a/Documentation/filesystems/ext4.txt
++++ b/Documentation/filesystems/ext4.txt
+@@ -160,7 +160,9 @@ noload			if the filesystem was not unmounted cleanly,
+                      	lead to any number of problems.
+ 
+ data=journal		All data are committed into the journal prior to being
+-			written into the main file system.
++			written into the main file system.  Enabling
++			this mode will disable delayed allocation and
++			O_DIRECT support.
+ 
+ data=ordered	(*)	All data are forced directly out to the main file
+ 			system prior to its metadata being committed to the
+@@ -419,8 +421,8 @@ written to the journal first, and then to its final location.
+ In the event of a crash, the journal can be replayed, bringing both data and
+ metadata into a consistent state.  This mode is the slowest except when data
+ needs to be read from and written to disk at the same time where it
+-outperforms all others modes.  Currently ext4 does not have delayed
+-allocation support if this data journalling mode is selected.
++outperforms all others modes.  Enabling this mode will disable delayed
++allocation and O_DIRECT support.
+ 
+ /proc entries
+ =============
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index ccfa81f33bb0..48ae98819d35 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -922,6 +922,9 @@ struct ext4_inode_info {
+ #define EXT4_MOUNT_DISCARD		0x40000000 /* Issue DISCARD requests */
+ #define EXT4_MOUNT_INIT_INODE_TABLE	0x80000000 /* Initialize uninitialized itables */
+ 
++#define EXT4_MOUNT2_EXPLICIT_DELALLOC	0x00000001 /* User explicitly
++						      specified delalloc */
++
+ #define clear_opt(sb, opt)		EXT4_SB(sb)->s_mount_opt &= \
+ 						~EXT4_MOUNT_##opt
+ #define set_opt(sb, opt)		EXT4_SB(sb)->s_mount_opt |= \
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 44d0c8db2239..ee2f74a7084d 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1801,6 +1801,7 @@ static int parse_options(char *options, struct super_block *sb,
+ 			break;
+ 		case Opt_nodelalloc:
+ 			clear_opt(sb, DELALLOC);
++			clear_opt2(sb, EXPLICIT_DELALLOC);
+ 			break;
+ 		case Opt_mblk_io_submit:
+ 			set_opt(sb, MBLK_IO_SUBMIT);
+@@ -1817,6 +1818,7 @@ static int parse_options(char *options, struct super_block *sb,
+ 			break;
+ 		case Opt_delalloc:
+ 			set_opt(sb, DELALLOC);
++			set_opt2(sb, EXPLICIT_DELALLOC);
+ 			break;
+ 		case Opt_block_validity:
+ 			set_opt(sb, BLOCK_VALIDITY);
+@@ -3224,6 +3226,33 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 			   &journal_ioprio, NULL, 0))
+ 		goto failed_mount;
+ 
++	if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
++		printk_once(KERN_WARNING "EXT4-fs: Warning: mounting "
++			    "with data=journal disables delayed "
++			    "allocation and O_DIRECT support!\n");
++		if (test_opt2(sb, EXPLICIT_DELALLOC)) {
++			ext4_msg(sb, KERN_ERR, "can't mount with "
++				 "both data=journal and delalloc");
++			goto failed_mount;
++		}
++		if (test_opt(sb, DIOREAD_NOLOCK)) {
++			ext4_msg(sb, KERN_ERR, "can't mount with "
++				 "both data=journal and delalloc");
++			goto failed_mount;
++		}
++		if (test_opt(sb, DELALLOC))
++			clear_opt(sb, DELALLOC);
++	}
++
++	blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);
++	if (test_opt(sb, DIOREAD_NOLOCK)) {
++		if (blocksize < PAGE_SIZE) {
++			ext4_msg(sb, KERN_ERR, "can't mount with "
++				 "dioread_nolock if block size != PAGE_SIZE");
++			goto failed_mount;
++		}
++	}
++
+ 	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
+ 		(test_opt(sb, POSIX_ACL) ? MS_POSIXACL : 0);
+ 
+@@ -3265,8 +3294,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	if (!ext4_feature_set_ok(sb, (sb->s_flags & MS_RDONLY)))
+ 		goto failed_mount;
+ 
+-	blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);
+-
+ 	if (blocksize < EXT4_MIN_BLOCK_SIZE ||
+ 	    blocksize > EXT4_MAX_BLOCK_SIZE) {
+ 		ext4_msg(sb, KERN_ERR,
+@@ -3679,25 +3706,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 			 "available");
+ 	}
+ 
+-	if (test_opt(sb, DELALLOC) &&
+-	    (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)) {
+-		ext4_msg(sb, KERN_WARNING, "Ignoring delalloc option - "
+-			 "requested data journaling mode");
+-		clear_opt(sb, DELALLOC);
+-	}
+-	if (test_opt(sb, DIOREAD_NOLOCK)) {
+-		if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
+-			ext4_msg(sb, KERN_WARNING, "Ignoring dioread_nolock "
+-				"option - requested data journaling mode");
+-			clear_opt(sb, DIOREAD_NOLOCK);
+-		}
+-		if (sb->s_blocksize < PAGE_SIZE) {
+-			ext4_msg(sb, KERN_WARNING, "Ignoring dioread_nolock "
+-				"option - block size is too small");
+-			clear_opt(sb, DIOREAD_NOLOCK);
+-		}
+-	}
+-
+ 	err = ext4_setup_system_zone(sb);
+ 	if (err) {
+ 		ext4_msg(sb, KERN_ERR, "failed to initialize system "

commit 5930ea643805feb50a2f8383ae12eb6f10935e49
+Author: Theodore Ts'o 
+Date:   Wed Aug 31 12:02:51 2011 -0400
+
+    ext4: call ext4_handle_dirty_metadata with correct inode in ext4_dx_add_entry
+    
+    ext4_dx_add_entry manipulates bh2 and frames[0].bh, which are two buffer_heads
+    that point to directory blocks assigned to the directory inode.  However, the
+    function calls ext4_handle_dirty_metadata with the inode of the file that's
+    being added to the directory, not the directory inode itself.  Therefore,
+    correct the code to dirty the directory buffers with the directory inode, not
+    the file inode.
+    
+    Signed-off-by: Darrick J. Wong 
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index f0abe4323136..a067835bbac1 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1585,7 +1585,7 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+ 			dxtrace(dx_show_index("node", frames[1].entries));
+ 			dxtrace(dx_show_index("node",
+ 			       ((struct dx_node *) bh2->b_data)->entries));
+-			err = ext4_handle_dirty_metadata(handle, inode, bh2);
++			err = ext4_handle_dirty_metadata(handle, dir, bh2);
+ 			if (err)
+ 				goto journal_error;
+ 			brelse (bh2);
+@@ -1611,7 +1611,7 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+ 			if (err)
+ 				goto journal_error;
+ 		}
+-		err = ext4_handle_dirty_metadata(handle, inode, frames[0].bh);
++		err = ext4_handle_dirty_metadata(handle, dir, frames[0].bh);
+ 		if (err) {
+ 			ext4_std_error(inode->i_sb, err);
+ 			goto cleanup;

commit 84ebd795613488992b273220c2937d575d27d2a9
+Author: Theodore Ts'o 
+Date:   Wed Aug 31 11:56:51 2011 -0400
+
+    ext4: fake direct I/O mode for data=journal
+    
+    Currently attempts to open a file with O_DIRECT in data=journal mode
+    causes the open to fail with -EINVAL.  This makes it very hard to test
+    data=journal mode.  So we will let the open succeed, but then always
+    fall back to O_DSYNC buffered writes.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 18d2558b7624..b84f127c085d 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2854,6 +2854,12 @@ static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb,
+ 	struct inode *inode = file->f_mapping->host;
+ 	ssize_t ret;
+ 
++	/*
++	 * If we are doing data journalling we don't support O_DIRECT
++	 */
++	if (ext4_should_journal_data(inode))
++		return 0;
++
+ 	trace_ext4_direct_IO_enter(inode, offset, iov_length(iov, nr_segs), rw);
+ 	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
+ 		ret = ext4_ext_direct_IO(rw, iocb, iov, offset, nr_segs);
+@@ -2923,6 +2929,7 @@ static const struct address_space_operations ext4_journalled_aops = {
+ 	.bmap			= ext4_bmap,
+ 	.invalidatepage		= ext4_invalidatepage,
+ 	.releasepage		= ext4_releasepage,
++	.direct_IO		= ext4_direct_IO,
+ 	.is_partially_uptodate  = block_is_partially_uptodate,
+ 	.error_remove_page	= generic_error_remove_page,
+ };

commit 1cd9f0976aa4606db8d6e3dc3edd0aca8019372a
+Author: Theodore Ts'o 
+Date:   Wed Aug 31 11:54:51 2011 -0400
+
+    ext2,ext3,ext4: don't inherit APPEND_FL or IMMUTABLE_FL for new inodes
+    
+    This doesn't make much sense, and it exposes a bug in the kernel where
+    attempts to create a new file in an append-only directory using
+    O_CREAT will fail (but still leave a zero-length file).  This was
+    discovered when xfstests #79 was generalized so it could run on all
+    file systems.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc:stable@kernel.org
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index b7d7bd0f066e..5c38120c389c 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -358,8 +358,7 @@ struct flex_groups {
+ 
+ /* Flags that should be inherited by new inodes from their parent. */
+ #define EXT4_FL_INHERITED (EXT4_SECRM_FL | EXT4_UNRM_FL | EXT4_COMPR_FL |\
+-			   EXT4_SYNC_FL | EXT4_IMMUTABLE_FL | EXT4_APPEND_FL |\
+-			   EXT4_NODUMP_FL | EXT4_NOATIME_FL |\
++			   EXT4_SYNC_FL | EXT4_NODUMP_FL | EXT4_NOATIME_FL |\
+ 			   EXT4_NOCOMPR_FL | EXT4_JOURNAL_DATA_FL |\
+ 			   EXT4_NOTAIL_FL | EXT4_DIRSYNC_FL)
+ 
+diff --git a/include/linux/ext2_fs.h b/include/linux/ext2_fs.h
+index 53792bf36c71..ce1b719e8bd4 100644
+--- a/include/linux/ext2_fs.h
++++ b/include/linux/ext2_fs.h
+@@ -197,8 +197,8 @@ struct ext2_group_desc
+ 
+ /* Flags that should be inherited by new inodes from their parent. */
+ #define EXT2_FL_INHERITED (EXT2_SECRM_FL | EXT2_UNRM_FL | EXT2_COMPR_FL |\
+-			   EXT2_SYNC_FL | EXT2_IMMUTABLE_FL | EXT2_APPEND_FL |\
+-			   EXT2_NODUMP_FL | EXT2_NOATIME_FL | EXT2_COMPRBLK_FL|\
++			   EXT2_SYNC_FL | EXT2_NODUMP_FL |\
++			   EXT2_NOATIME_FL | EXT2_COMPRBLK_FL |\
+ 			   EXT2_NOCOMP_FL | EXT2_JOURNAL_DATA_FL |\
+ 			   EXT2_NOTAIL_FL | EXT2_DIRSYNC_FL)
+ 
+diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
+index 67a803aee619..0244611eb2b8 100644
+--- a/include/linux/ext3_fs.h
++++ b/include/linux/ext3_fs.h
+@@ -180,8 +180,8 @@ struct ext3_group_desc
+ 
+ /* Flags that should be inherited by new inodes from their parent. */
+ #define EXT3_FL_INHERITED (EXT3_SECRM_FL | EXT3_UNRM_FL | EXT3_COMPR_FL |\
+-			   EXT3_SYNC_FL | EXT3_IMMUTABLE_FL | EXT3_APPEND_FL |\
+-			   EXT3_NODUMP_FL | EXT3_NOATIME_FL | EXT3_COMPRBLK_FL|\
++			   EXT3_SYNC_FL | EXT3_NODUMP_FL |\
++			   EXT3_NOATIME_FL | EXT3_COMPRBLK_FL |\
+ 			   EXT3_NOCOMPR_FL | EXT3_JOURNAL_DATA_FL |\
+ 			   EXT3_NOTAIL_FL | EXT3_DIRSYNC_FL)
+ 

commit b4ca46e4e82a0a5976fe5eab85be585d75f8202f
+Author: Andy Lutomirski 
+Date:   Thu Aug 25 16:10:33 2011 -0400
+
+    x86-32: Fix boot with CONFIG_X86_INVD_BUG
+    
+    entry_32.S contained a hardcoded alternative instruction entry, and the
+    format changed in commit 59e97e4d6fbc ("x86: Make alternative
+    instruction pointers relative").
+    
+    Replace the hardcoded entry with the altinstruction_entry macro.  This
+    fixes the 32-bit boot with CONFIG_X86_INVD_BUG=y.
+    
+    Reported-and-tested-by: Arnaud Lacombe 
+    Signed-off-by: Andy Lutomirski 
+    Cc: Peter Anvin 
+    Cc: Ingo Molnar 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
+index 5c1a91974918..f3f6f5344001 100644
+--- a/arch/x86/kernel/entry_32.S
++++ b/arch/x86/kernel/entry_32.S
+@@ -54,6 +54,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ /* Avoid __ASSEMBLER__'ifying  just for this.  */
+ #include 
+@@ -873,12 +874,7 @@ ENTRY(simd_coprocessor_error)
+ 661:	pushl_cfi $do_general_protection
+ 662:
+ .section .altinstructions,"a"
+-	.balign 4
+-	.long 661b
+-	.long 663f
+-	.word X86_FEATURE_XMM
+-	.byte 662b-661b
+-	.byte 664f-663f
++	altinstruction_entry 661b, 663f, X86_FEATURE_XMM, 662b-661b, 664f-663f
+ .previous
+ .section .altinstr_replacement,"ax"
+ 663:	pushl $do_simd_coprocessor_error

commit 7e49b1c8c6d64f55ac83e1f5901b22fa9e51ab80
+Author: Andy Lutomirski 
+Date:   Wed Aug 24 10:19:44 2011 -0400
+
+    x86-64, unistd: Remove bogus __IGNORE_getcpu
+    
+    The change:
+    
+    commit fce8dc06423d6fb2709469dc5c55b04e09c1d126
+    Author: Andy Lutomirski 
+    Date:   Wed Aug 10 11:15:31 2011 -0400
+    
+        x86-64: Wire up getcpu syscall
+    
+    added getcpu as a real syscall, so we shouldn't ignore it any more.
+    
+    Signed-off-by: Andy Lutomirski 
+    Link: http://lkml.kernel.org/r/b4cb60ef45db3a675a0e2b9d51bcb022b0a9ab9c.1314195481.git.luto@mit.edu
+    Reported-by: H.J. Lu 
+    Signed-off-by: H. Peter Anvin 
+
+diff --git a/arch/x86/include/asm/unistd_64.h b/arch/x86/include/asm/unistd_64.h
+index d92641cc7acc..940d7204b89d 100644
+--- a/arch/x86/include/asm/unistd_64.h
++++ b/arch/x86/include/asm/unistd_64.h
+@@ -624,7 +624,6 @@ __SYSCALL(__NR_vmsplice, sys_vmsplice)
+ __SYSCALL(__NR_move_pages, sys_move_pages)
+ #define __NR_utimensat				280
+ __SYSCALL(__NR_utimensat, sys_utimensat)
+-#define __IGNORE_getcpu		/* implemented as a vsyscall */
+ #define __NR_epoll_pwait			281
+ __SYSCALL(__NR_epoll_pwait, sys_epoll_pwait)
+ #define __NR_signalfd				282

commit d5c073caf050bc713271a02e016b1672d9b7b935
+Author: Geoffrey Thomas 
+Date:   Mon Aug 22 11:28:57 2011 -0700
+
+    net: Documentation: RFC 2553bis is now RFC 3493
+    
+    Signed-off-by: Geoffrey Thomas 
+    Signed-off-by: David S. Miller 
+
+diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
+index db2a4067013c..81546990f41c 100644
+--- a/Documentation/networking/ip-sysctl.txt
++++ b/Documentation/networking/ip-sysctl.txt
+@@ -992,7 +992,7 @@ bindv6only - BOOLEAN
+ 		TRUE: disable IPv4-mapped address feature
+ 		FALSE: enable IPv4-mapped address feature
+ 
+-	Default: FALSE (as specified in RFC2553bis)
++	Default: FALSE (as specified in RFC3493)
+ 
+ IPv6 Fragmentation:
+ 

commit 9dd75f1f1a02d656a11a7b9b9e6c2759b9c1e946
+Author: Theodore Ts'o 
+Date:   Sat Aug 13 12:58:21 2011 -0400
+
+    ext4: fix nomblk_io_submit option so it correctly converts uninit blocks
+    
+    Bug discovered by Jan Kara:
+    
+    Finally, commit 1449032be17abb69116dbc393f67ceb8bd034f92 returned back
+    the old IO submission code but apparently it forgot to return the old
+    handling of uninitialized buffers so we unconditionnaly call
+    block_write_full_page() without specifying end_io function. So AFAICS
+    we never convert unwritten extents to written in some cases. For
+    example when I mount the fs as: mount -t ext4 -o
+    nomblk_io_submit,dioread_nolock /dev/ubdb /mnt and do
+            int fd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC, 0600);
+            char buf[1024];
+            memset(buf, 'a', sizeof(buf));
+            fallocate(fd, 0, 0, 16384);
+            write(fd, buf, sizeof(buf));
+    
+    I get a file full of zeros (after remounting the filesystem so that
+    pagecache is dropped) instead of seeing the first KB contain 'a's.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 762e8037c888..c4da98a959ae 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1291,7 +1291,12 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd,
+ 			else if (test_opt(inode->i_sb, MBLK_IO_SUBMIT))
+ 				err = ext4_bio_write_page(&io_submit, page,
+ 							  len, mpd->wbc);
+-			else
++			else if (buffer_uninit(page_bufs)) {
++				ext4_set_bh_endio(page_bufs, inode);
++				err = block_write_full_page_endio(page,
++					noalloc_get_block_write,
++					mpd->wbc, ext4_end_io_buffer_write);
++			} else
+ 				err = block_write_full_page(page,
+ 					noalloc_get_block_write, mpd->wbc);
+ 

commit 3ae36655b97a03fa1decf72f04078ef945647c1a
+Author: Andy Lutomirski 
+Date:   Wed Aug 10 11:15:32 2011 -0400
+
+    x86-64: Rework vsyscall emulation and add vsyscall= parameter
+    
+    There are three choices:
+    
+    vsyscall=native: Vsyscalls are native code that issues the
+    corresponding syscalls.
+    
+    vsyscall=emulate (default): Vsyscalls are emulated by instruction
+    fault traps, tested in the bad_area path.  The actual contents of
+    the vsyscall page is the same as the vsyscall=native case except
+    that it's marked NX.  This way programs that make assumptions about
+    what the code in the page does will not be confused when they read
+    that code.
+    
+    vsyscall=none: Trying to execute a vsyscall will segfault.
+    
+    Signed-off-by: Andy Lutomirski 
+    Link: http://lkml.kernel.org/r/8449fb3abf89851fd6b2260972666a6f82542284.1312988155.git.luto@mit.edu
+    Signed-off-by: H. Peter Anvin 
+
+diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
+index aa47be71df4c..9cfd6bb9198e 100644
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -2657,6 +2657,27 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
+ 	vmpoff=		[KNL,S390] Perform z/VM CP command after power off.
+ 			Format: 
+ 
++	vsyscall=	[X86-64]
++			Controls the behavior of vsyscalls (i.e. calls to
++			fixed addresses of 0xffffffffff600x00 from legacy
++			code).  Most statically-linked binaries and older
++			versions of glibc use these calls.  Because these
++			functions are at fixed addresses, they make nice
++			targets for exploits that can control RIP.
++
++			emulate     [default] Vsyscalls turn into traps and are
++			            emulated reasonably safely.
++
++			native      Vsyscalls are native syscall instructions.
++			            This is a little bit faster than trapping
++			            and makes a few dynamic recompilers work
++			            better than they would in emulation mode.
++			            It also makes exploits much easier to write.
++
++			none        Vsyscalls don't work at all.  This makes
++			            them quite hard to use for exploits but
++			            might break your system.
++
+ 	vt.cur_default=	[VT] Default cursor shape.
+ 			Format: 0xCCBBAA, where AA, BB, and CC are the same as
+ 			the parameters of the [?A;B;Cc escape sequence;
+diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h
+index a563c509edcb..2c224e183b52 100644
+--- a/arch/x86/include/asm/irq_vectors.h
++++ b/arch/x86/include/asm/irq_vectors.h
+@@ -17,7 +17,6 @@
+  *  Vectors   0 ...  31 : system traps and exceptions - hardcoded events
+  *  Vectors  32 ... 127 : device interrupts
+  *  Vector  128         : legacy int80 syscall interface
+- *  Vector  204         : legacy x86_64 vsyscall emulation
+  *  Vectors 129 ... INVALIDATE_TLB_VECTOR_START-1 except 204 : device interrupts
+  *  Vectors INVALIDATE_TLB_VECTOR_START ... 255 : special interrupts
+  *
+@@ -51,9 +50,6 @@
+ #ifdef CONFIG_X86_32
+ # define SYSCALL_VECTOR			0x80
+ #endif
+-#ifdef CONFIG_X86_64
+-# define VSYSCALL_EMU_VECTOR		0xcc
+-#endif
+ 
+ /*
+  * Vectors 0x30-0x3f are used for ISA interrupts.
+diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h
+index 2bae0a513b40..0012d0902c5f 100644
+--- a/arch/x86/include/asm/traps.h
++++ b/arch/x86/include/asm/traps.h
+@@ -40,7 +40,6 @@ asmlinkage void alignment_check(void);
+ asmlinkage void machine_check(void);
+ #endif /* CONFIG_X86_MCE */
+ asmlinkage void simd_coprocessor_error(void);
+-asmlinkage void emulate_vsyscall(void);
+ 
+ dotraplinkage void do_divide_error(struct pt_regs *, long);
+ dotraplinkage void do_debug(struct pt_regs *, long);
+@@ -67,7 +66,6 @@ dotraplinkage void do_alignment_check(struct pt_regs *, long);
+ dotraplinkage void do_machine_check(struct pt_regs *, long);
+ #endif
+ dotraplinkage void do_simd_coprocessor_error(struct pt_regs *, long);
+-dotraplinkage void do_emulate_vsyscall(struct pt_regs *, long);
+ #ifdef CONFIG_X86_32
+ dotraplinkage void do_iret_error(struct pt_regs *, long);
+ #endif
+diff --git a/arch/x86/include/asm/vsyscall.h b/arch/x86/include/asm/vsyscall.h
+index 60107072c28b..eaea1d31f753 100644
+--- a/arch/x86/include/asm/vsyscall.h
++++ b/arch/x86/include/asm/vsyscall.h
+@@ -27,6 +27,12 @@ extern struct timezone sys_tz;
+ 
+ extern void map_vsyscall(void);
+ 
++/*
++ * Called on instruction fetch fault in vsyscall page.
++ * Returns true if handled.
++ */
++extern bool emulate_vsyscall(struct pt_regs *regs, unsigned long address);
++
+ #endif /* __KERNEL__ */
+ 
+ #endif /* _ASM_X86_VSYSCALL_H */
+diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
+index e949793d6b93..46792d900018 100644
+--- a/arch/x86/kernel/entry_64.S
++++ b/arch/x86/kernel/entry_64.S
+@@ -1123,7 +1123,6 @@ zeroentry spurious_interrupt_bug do_spurious_interrupt_bug
+ zeroentry coprocessor_error do_coprocessor_error
+ errorentry alignment_check do_alignment_check
+ zeroentry simd_coprocessor_error do_simd_coprocessor_error
+-zeroentry emulate_vsyscall do_emulate_vsyscall
+ 
+ 
+ 	/* Reload gs selector with exception handling */
+diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
+index fbc097a085ca..b9b67166f9de 100644
+--- a/arch/x86/kernel/traps.c
++++ b/arch/x86/kernel/traps.c
+@@ -872,12 +872,6 @@ void __init trap_init(void)
+ 	set_bit(SYSCALL_VECTOR, used_vectors);
+ #endif
+ 
+-#ifdef CONFIG_X86_64
+-	BUG_ON(test_bit(VSYSCALL_EMU_VECTOR, used_vectors));
+-	set_system_intr_gate(VSYSCALL_EMU_VECTOR, &emulate_vsyscall);
+-	set_bit(VSYSCALL_EMU_VECTOR, used_vectors);
+-#endif
+-
+ 	/*
+ 	 * Should be a barrier for any external CPU state:
+ 	 */
+diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
+index 8f3a265476d7..0f703f10901a 100644
+--- a/arch/x86/kernel/vmlinux.lds.S
++++ b/arch/x86/kernel/vmlinux.lds.S
+@@ -71,7 +71,6 @@ PHDRS {
+ 	text PT_LOAD FLAGS(5);          /* R_E */
+ 	data PT_LOAD FLAGS(6);          /* RW_ */
+ #ifdef CONFIG_X86_64
+-	user PT_LOAD FLAGS(5);          /* R_E */
+ #ifdef CONFIG_SMP
+ 	percpu PT_LOAD FLAGS(6);        /* RW_ */
+ #endif
+@@ -174,38 +173,6 @@ SECTIONS
+ 
+        . = ALIGN(__vvar_page + PAGE_SIZE, PAGE_SIZE);
+ 
+-#define VSYSCALL_ADDR (-10*1024*1024)
+-
+-#define VLOAD_OFFSET (VSYSCALL_ADDR - __vsyscall_0 + LOAD_OFFSET)
+-#define VLOAD(x) (ADDR(x) - VLOAD_OFFSET)
+-
+-#define VVIRT_OFFSET (VSYSCALL_ADDR - __vsyscall_0)
+-#define VVIRT(x) (ADDR(x) - VVIRT_OFFSET)
+-
+-	__vsyscall_0 = .;
+-
+-	. = VSYSCALL_ADDR;
+-	.vsyscall : AT(VLOAD(.vsyscall)) {
+-		/* work around gold bug 13023 */
+-		__vsyscall_beginning_hack = .;
+-		*(.vsyscall_0)
+-
+-		. = __vsyscall_beginning_hack + 1024;
+-		*(.vsyscall_1)
+-
+-		. = __vsyscall_beginning_hack + 2048;
+-		*(.vsyscall_2)
+-
+-		. = __vsyscall_beginning_hack + 4096;  /* Pad the whole page. */
+-	} :user =0xcc
+-	. = ALIGN(__vsyscall_0 + PAGE_SIZE, PAGE_SIZE);
+-
+-#undef VSYSCALL_ADDR
+-#undef VLOAD_OFFSET
+-#undef VLOAD
+-#undef VVIRT_OFFSET
+-#undef VVIRT
+-
+ #endif /* CONFIG_X86_64 */
+ 
+ 	/* Init code and data - will be freed after init */
+diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
+index bf8e9ffee6e9..18ae83dd1cd7 100644
+--- a/arch/x86/kernel/vsyscall_64.c
++++ b/arch/x86/kernel/vsyscall_64.c
+@@ -56,6 +56,27 @@ DEFINE_VVAR(struct vsyscall_gtod_data, vsyscall_gtod_data) =
+ 	.lock = __SEQLOCK_UNLOCKED(__vsyscall_gtod_data.lock),
+ };
+ 
++static enum { EMULATE, NATIVE, NONE } vsyscall_mode = EMULATE;
++
++static int __init vsyscall_setup(char *str)
++{
++	if (str) {
++		if (!strcmp("emulate", str))
++			vsyscall_mode = EMULATE;
++		else if (!strcmp("native", str))
++			vsyscall_mode = NATIVE;
++		else if (!strcmp("none", str))
++			vsyscall_mode = NONE;
++		else
++			return -EINVAL;
++
++		return 0;
++	}
++
++	return -EINVAL;
++}
++early_param("vsyscall", vsyscall_setup);
++
+ void update_vsyscall_tz(void)
+ {
+ 	unsigned long flags;
+@@ -100,7 +121,7 @@ static void warn_bad_vsyscall(const char *level, struct pt_regs *regs,
+ 
+ 	printk("%s%s[%d] %s ip:%lx cs:%lx sp:%lx ax:%lx si:%lx di:%lx\n",
+ 	       level, tsk->comm, task_pid_nr(tsk),
+-	       message, regs->ip - 2, regs->cs,
++	       message, regs->ip, regs->cs,
+ 	       regs->sp, regs->ax, regs->si, regs->di);
+ }
+ 
+@@ -118,45 +139,39 @@ static int addr_to_vsyscall_nr(unsigned long addr)
+ 	return nr;
+ }
+ 
+-void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)
++bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
+ {
+ 	struct task_struct *tsk;
+ 	unsigned long caller;
+ 	int vsyscall_nr;
+ 	long ret;
+ 
+-	local_irq_enable();
++	/*
++	 * No point in checking CS -- the only way to get here is a user mode
++	 * trap to a high address, which means that we're in 64-bit user code.
++	 */
+ 
+-	if (!user_64bit_mode(regs)) {
+-		/*
+-		 * If we trapped from kernel mode, we might as well OOPS now
+-		 * instead of returning to some random address and OOPSing
+-		 * then.
+-		 */
+-		BUG_ON(!user_mode(regs));
++	WARN_ON_ONCE(address != regs->ip);
+ 
+-		/* Compat mode and non-compat 32-bit CS should both segfault. */
+-		warn_bad_vsyscall(KERN_WARNING, regs,
+-				  "illegal int 0xcc from 32-bit mode");
+-		goto sigsegv;
++	if (vsyscall_mode == NONE) {
++		warn_bad_vsyscall(KERN_INFO, regs,
++				  "vsyscall attempted with vsyscall=none");
++		return false;
+ 	}
+ 
+-	/*
+-	 * x86-ism here: regs->ip points to the instruction after the int 0xcc,
+-	 * and int 0xcc is two bytes long.
+-	 */
+-	vsyscall_nr = addr_to_vsyscall_nr(regs->ip - 2);
++	vsyscall_nr = addr_to_vsyscall_nr(address);
+ 
+ 	trace_emulate_vsyscall(vsyscall_nr);
+ 
+ 	if (vsyscall_nr < 0) {
+ 		warn_bad_vsyscall(KERN_WARNING, regs,
+-				  "illegal int 0xcc (exploit attempt?)");
++				  "misaligned vsyscall (exploit attempt or buggy program) -- look up the vsyscall kernel parameter if you need a workaround");
+ 		goto sigsegv;
+ 	}
+ 
+ 	if (get_user(caller, (unsigned long __user *)regs->sp) != 0) {
+-		warn_bad_vsyscall(KERN_WARNING, regs, "int 0xcc with bad stack (exploit attempt?)");
++		warn_bad_vsyscall(KERN_WARNING, regs,
++				  "vsyscall with bad stack (exploit attempt?)");
+ 		goto sigsegv;
+ 	}
+ 
+@@ -201,13 +216,11 @@ void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)
+ 	regs->ip = caller;
+ 	regs->sp += 8;
+ 
+-	local_irq_disable();
+-	return;
++	return true;
+ 
+ sigsegv:
+-	regs->ip -= 2;  /* The faulting instruction should be the int 0xcc. */
+ 	force_sig(SIGSEGV, current);
+-	local_irq_disable();
++	return true;
+ }
+ 
+ /*
+@@ -255,15 +268,21 @@ cpu_vsyscall_notifier(struct notifier_block *n, unsigned long action, void *arg)
+ 
+ void __init map_vsyscall(void)
+ {
+-	extern char __vsyscall_0;
+-	unsigned long physaddr_page0 = __pa_symbol(&__vsyscall_0);
++	extern char __vsyscall_page;
++	unsigned long physaddr_vsyscall = __pa_symbol(&__vsyscall_page);
+ 	extern char __vvar_page;
+ 	unsigned long physaddr_vvar_page = __pa_symbol(&__vvar_page);
+ 
+-	/* Note that VSYSCALL_MAPPED_PAGES must agree with the code below. */
+-	__set_fixmap(VSYSCALL_FIRST_PAGE, physaddr_page0, PAGE_KERNEL_VSYSCALL);
++	__set_fixmap(VSYSCALL_FIRST_PAGE, physaddr_vsyscall,
++		     vsyscall_mode == NATIVE
++		     ? PAGE_KERNEL_VSYSCALL
++		     : PAGE_KERNEL_VVAR);
++	BUILD_BUG_ON((unsigned long)__fix_to_virt(VSYSCALL_FIRST_PAGE) !=
++		     (unsigned long)VSYSCALL_START);
++
+ 	__set_fixmap(VVAR_PAGE, physaddr_vvar_page, PAGE_KERNEL_VVAR);
+-	BUILD_BUG_ON((unsigned long)__fix_to_virt(VVAR_PAGE) != (unsigned long)VVAR_ADDRESS);
++	BUILD_BUG_ON((unsigned long)__fix_to_virt(VVAR_PAGE) !=
++		     (unsigned long)VVAR_ADDRESS);
+ }
+ 
+ static int __init vsyscall_init(void)
+diff --git a/arch/x86/kernel/vsyscall_emu_64.S b/arch/x86/kernel/vsyscall_emu_64.S
+index ffa845eae5ca..c9596a9af159 100644
+--- a/arch/x86/kernel/vsyscall_emu_64.S
++++ b/arch/x86/kernel/vsyscall_emu_64.S
+@@ -7,21 +7,31 @@
+  */
+ 
+ #include 
++
+ #include 
++#include 
++#include 
++
++__PAGE_ALIGNED_DATA
++	.globl __vsyscall_page
++	.balign PAGE_SIZE, 0xcc
++	.type __vsyscall_page, @object
++__vsyscall_page:
++
++	mov $__NR_gettimeofday, %rax
++	syscall
++	ret
+ 
+-/* The unused parts of the page are filled with 0xcc by the linker script. */
++	.balign 1024, 0xcc
++	mov $__NR_time, %rax
++	syscall
++	ret
+ 
+-.section .vsyscall_0, "a"
+-ENTRY(vsyscall_0)
+-	int $VSYSCALL_EMU_VECTOR
+-END(vsyscall_0)
++	.balign 1024, 0xcc
++	mov $__NR_getcpu, %rax
++	syscall
++	ret
+ 
+-.section .vsyscall_1, "a"
+-ENTRY(vsyscall_1)
+-	int $VSYSCALL_EMU_VECTOR
+-END(vsyscall_1)
++	.balign 4096, 0xcc
+ 
+-.section .vsyscall_2, "a"
+-ENTRY(vsyscall_2)
+-	int $VSYSCALL_EMU_VECTOR
+-END(vsyscall_2)
++	.size __vsyscall_page, 4096
+diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
+index c1d018238f32..e58935c25b94 100644
+--- a/arch/x86/mm/fault.c
++++ b/arch/x86/mm/fault.c
+@@ -720,6 +720,18 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
+ 		if (is_errata100(regs, address))
+ 			return;
+ 
++#ifdef CONFIG_X86_64
++		/*
++		 * Instruction fetch faults in the vsyscall page might need
++		 * emulation.
++		 */
++		if (unlikely((error_code & PF_INSTR) &&
++			     ((address & ~0xfff) == VSYSCALL_START))) {
++			if (emulate_vsyscall(regs, address))
++				return;
++		}
++#endif
++
+ 		if (unlikely(show_unhandled_signals))
+ 			show_signal_msg(regs, error_code, address, tsk);
+ 

commit fce8dc06423d6fb2709469dc5c55b04e09c1d126
+Author: Andy Lutomirski 
+Date:   Wed Aug 10 11:15:31 2011 -0400
+
+    x86-64: Wire up getcpu syscall
+    
+    getcpu is available as a vdso entry and an emulated vsyscall.
+    Programs that for some reason don't want to use the vdso should
+    still be able to call getcpu without relying on the slow emulated
+    vsyscall.  It costs almost nothing to expose it as a real syscall.
+    
+    We also need this for the following patch in vsyscall=native mode.
+    
+    Signed-off-by: Andy Lutomirski 
+    Link: http://lkml.kernel.org/r/6b19f55bdb06a0c32c2fa6dba9b6f222e1fde999.1312988155.git.luto@mit.edu
+    Signed-off-by: H. Peter Anvin 
+
+diff --git a/arch/x86/include/asm/unistd_64.h b/arch/x86/include/asm/unistd_64.h
+index 705bf139288c..d92641cc7acc 100644
+--- a/arch/x86/include/asm/unistd_64.h
++++ b/arch/x86/include/asm/unistd_64.h
+@@ -681,6 +681,8 @@ __SYSCALL(__NR_syncfs, sys_syncfs)
+ __SYSCALL(__NR_sendmmsg, sys_sendmmsg)
+ #define __NR_setns				308
+ __SYSCALL(__NR_setns, sys_setns)
++#define __NR_getcpu				309
++__SYSCALL(__NR_getcpu, sys_getcpu)
+ 
+ #ifndef __NO_STUBS
+ #define __ARCH_WANT_OLD_READDIR

commit f3fb5b7bb70d6e679c15fef85707810a067f5fb6
+Author: Andy Lutomirski 
+Date:   Wed Aug 10 11:15:30 2011 -0400
+
+    x86: Remove unnecessary compile flag tweaks for vsyscall code
+    
+    As of commit 98d0ac38ca7b1b7a552c9a2359174ff84decb600
+    Author: Andy Lutomirski 
+    Date:   Thu Jul 14 06:47:22 2011 -0400
+    
+        x86-64: Move vread_tsc and vread_hpet into the vDSO
+    
+    user code no longer directly calls into code in arch/x86/kernel/, so
+    we don't need compile flag hacks to make it safe.  All vdso code is
+    in the vdso directory now.
+    
+    Signed-off-by: Andy Lutomirski 
+    Link: http://lkml.kernel.org/r/835cd05a4c7740544d09723d6ba48f4406f9826c.1312988155.git.luto@mit.edu
+    Signed-off-by: H. Peter Anvin 
+
+diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
+index 2deef3d2435a..3d1ac3978707 100644
+--- a/arch/x86/kernel/Makefile
++++ b/arch/x86/kernel/Makefile
+@@ -17,19 +17,6 @@ CFLAGS_REMOVE_ftrace.o = -pg
+ CFLAGS_REMOVE_early_printk.o = -pg
+ endif
+ 
+-#
+-# vsyscalls (which work on the user stack) should have
+-# no stack-protector checks:
+-#
+-nostackp := $(call cc-option, -fno-stack-protector)
+-CFLAGS_vsyscall_64.o	:= $(PROFILING) -g0 $(nostackp)
+-CFLAGS_hpet.o		:= $(nostackp)
+-CFLAGS_paravirt.o	:= $(nostackp)
+-GCOV_PROFILE_vsyscall_64.o	:= n
+-GCOV_PROFILE_hpet.o		:= n
+-GCOV_PROFILE_tsc.o		:= n
+-GCOV_PROFILE_paravirt.o		:= n
+-
+ obj-y			:= process_$(BITS).o signal.o entry_$(BITS).o
+ obj-y			+= traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
+ obj-y			+= time.o ioport.o ldt.o dumpstack.o
+diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
+index 93a0d46d9569..bf8e9ffee6e9 100644
+--- a/arch/x86/kernel/vsyscall_64.c
++++ b/arch/x86/kernel/vsyscall_64.c
+@@ -18,9 +18,6 @@
+  *  use the vDSO.
+  */
+ 
+-/* Disable profiling for userspace code: */
+-#define DISABLE_BRANCH_PROFILING
+-
+ #include 
+ #include 
+ #include 

commit 9d8b9ec44234b2f6e0225300632d250210c04f11
+Author: Theodore Ts'o 
+Date:   Mon Aug 1 17:41:35 2011 -0400
+
+    ext4: use ext4_msg() instead of printk in mballoc
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index d5021e82f8cc..70d1b3e64284 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -493,10 +493,11 @@ static void mb_cmp_bitmaps(struct ext4_buddy *e4b, void *bitmap)
+ 		b2 = (unsigned char *) bitmap;
+ 		for (i = 0; i < e4b->bd_sb->s_blocksize; i++) {
+ 			if (b1[i] != b2[i]) {
+-				printk(KERN_ERR "corruption in group %u "
+-				       "at byte %u(%u): %x in copy != %x "
+-				       "on disk/prealloc\n",
+-				       e4b->bd_group, i, i * 8, b1[i], b2[i]);
++				ext4_msg(e4b->bd_sb, KERN_ERR,
++					 "corruption in group %u "
++					 "at byte %u(%u): %x in copy != %x "
++					 "on disk/prealloc",
++					 e4b->bd_group, i, i * 8, b1[i], b2[i]);
+ 				BUG();
+ 			}
+ 		}
+@@ -2224,8 +2225,8 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group,
+ 			EXT4_DESC_PER_BLOCK_BITS(sb);
+ 		meta_group_info = kmalloc(metalen, GFP_KERNEL);
+ 		if (meta_group_info == NULL) {
+-			printk(KERN_ERR "EXT4-fs: can't allocate mem for a "
+-			       "buddy group\n");
++			ext4_msg(sb, KERN_ERR, "EXT4-fs: can't allocate mem "
++				 "for a buddy group");
+ 			goto exit_meta_group_info;
+ 		}
+ 		sbi->s_group_info[group >> EXT4_DESC_PER_BLOCK_BITS(sb)] =
+@@ -2238,7 +2239,7 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group,
+ 
+ 	meta_group_info[i] = kmem_cache_alloc(cachep, GFP_KERNEL);
+ 	if (meta_group_info[i] == NULL) {
+-		printk(KERN_ERR "EXT4-fs: can't allocate buddy mem\n");
++		ext4_msg(sb, KERN_ERR, "EXT4-fs: can't allocate buddy mem");
+ 		goto exit_group_info;
+ 	}
+ 	memset(meta_group_info[i], 0, kmem_cache_size(cachep));
+@@ -2333,12 +2334,12 @@ static int ext4_mb_init_backend(struct super_block *sb)
+ 	 * So a two level scheme suffices for now. */
+ 	sbi->s_group_info = ext4_kvzalloc(array_size, GFP_KERNEL);
+ 	if (sbi->s_group_info == NULL) {
+-		printk(KERN_ERR "EXT4-fs: can't allocate buddy meta group\n");
++		ext4_msg(sb, KERN_ERR, "can't allocate buddy meta group");
+ 		return -ENOMEM;
+ 	}
+ 	sbi->s_buddy_cache = new_inode(sb);
+ 	if (sbi->s_buddy_cache == NULL) {
+-		printk(KERN_ERR "EXT4-fs: can't get new inode\n");
++		ext4_msg(sb, KERN_ERR, "can't get new inode");
+ 		goto err_freesgi;
+ 	}
+ 	sbi->s_buddy_cache->i_ino = get_next_ino();
+@@ -2346,8 +2347,7 @@ static int ext4_mb_init_backend(struct super_block *sb)
+ 	for (i = 0; i < ngroups; i++) {
+ 		desc = ext4_get_group_desc(sb, i, NULL);
+ 		if (desc == NULL) {
+-			printk(KERN_ERR
+-				"EXT4-fs: can't read descriptor %u\n", i);
++			ext4_msg(sb, KERN_ERR, "can't read descriptor %u", i);
+ 			goto err_freebuddy;
+ 		}
+ 		if (ext4_mb_add_groupinfo(sb, i, desc) != 0)
+@@ -2411,7 +2411,8 @@ static int ext4_groupinfo_create_slab(size_t size)
+ 
+ 	mutex_unlock(&ext4_grpinfo_slab_create_mutex);
+ 	if (!cachep) {
+-		printk(KERN_EMERG "EXT4: no memory for groupinfo slab cache\n");
++		printk(KERN_EMERG
++		       "EXT4-fs: no memory for groupinfo slab cache\n");
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -2566,25 +2567,25 @@ int ext4_mb_release(struct super_block *sb)
+ 	if (sbi->s_buddy_cache)
+ 		iput(sbi->s_buddy_cache);
+ 	if (sbi->s_mb_stats) {
+-		printk(KERN_INFO
+-		       "EXT4-fs: mballoc: %u blocks %u reqs (%u success)\n",
++		ext4_msg(sb, KERN_INFO,
++		       "mballoc: %u blocks %u reqs (%u success)",
+ 				atomic_read(&sbi->s_bal_allocated),
+ 				atomic_read(&sbi->s_bal_reqs),
+ 				atomic_read(&sbi->s_bal_success));
+-		printk(KERN_INFO
+-		      "EXT4-fs: mballoc: %u extents scanned, %u goal hits, "
+-				"%u 2^N hits, %u breaks, %u lost\n",
++		ext4_msg(sb, KERN_INFO,
++		      "mballoc: %u extents scanned, %u goal hits, "
++				"%u 2^N hits, %u breaks, %u lost",
+ 				atomic_read(&sbi->s_bal_ex_scanned),
+ 				atomic_read(&sbi->s_bal_goals),
+ 				atomic_read(&sbi->s_bal_2orders),
+ 				atomic_read(&sbi->s_bal_breaks),
+ 				atomic_read(&sbi->s_mb_lost_chunks));
+-		printk(KERN_INFO
+-		       "EXT4-fs: mballoc: %lu generated and it took %Lu\n",
++		ext4_msg(sb, KERN_INFO,
++		       "mballoc: %lu generated and it took %Lu",
+ 				sbi->s_mb_buddies_generated,
+ 				sbi->s_mb_generation_time);
+-		printk(KERN_INFO
+-		       "EXT4-fs: mballoc: %u preallocated, %u discarded\n",
++		ext4_msg(sb, KERN_INFO,
++		       "mballoc: %u preallocated, %u discarded",
+ 				atomic_read(&sbi->s_mb_preallocated),
+ 				atomic_read(&sbi->s_mb_discarded));
+ 	}
+@@ -3024,9 +3025,10 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
+ 
+ 	if (start + size <= ac->ac_o_ex.fe_logical &&
+ 			start > ac->ac_o_ex.fe_logical) {
+-		printk(KERN_ERR "start %lu, size %lu, fe_logical %lu\n",
+-			(unsigned long) start, (unsigned long) size,
+-			(unsigned long) ac->ac_o_ex.fe_logical);
++		ext4_msg(ac->ac_sb, KERN_ERR,
++			 "start %lu, size %lu, fe_logical %lu",
++			 (unsigned long) start, (unsigned long) size,
++			 (unsigned long) ac->ac_o_ex.fe_logical);
+ 	}
+ 	BUG_ON(start + size <= ac->ac_o_ex.fe_logical &&
+ 			start > ac->ac_o_ex.fe_logical);
+@@ -3607,10 +3609,11 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh,
+ 		bit = next + 1;
+ 	}
+ 	if (free != pa->pa_free) {
+-		printk(KERN_CRIT "pa %p: logic %lu, phys. %lu, len %lu\n",
+-			pa, (unsigned long) pa->pa_lstart,
+-			(unsigned long) pa->pa_pstart,
+-			(unsigned long) pa->pa_len);
++		ext4_msg(e4b->bd_sb, KERN_CRIT,
++			 "pa %p: logic %lu, phys. %lu, len %lu",
++			 pa, (unsigned long) pa->pa_lstart,
++			 (unsigned long) pa->pa_pstart,
++			 (unsigned long) pa->pa_len);
+ 		ext4_grp_locked_error(sb, group, 0, 0, "free %u, pa_free %u",
+ 					free, pa->pa_free);
+ 		/*
+@@ -3798,7 +3801,8 @@ void ext4_discard_preallocations(struct inode *inode)
+ 			 * use preallocation while we're discarding it */
+ 			spin_unlock(&pa->pa_lock);
+ 			spin_unlock(&ei->i_prealloc_lock);
+-			printk(KERN_ERR "uh-oh! used pa while discarding\n");
++			ext4_msg(sb, KERN_ERR,
++				 "uh-oh! used pa while discarding");
+ 			WARN_ON(1);
+ 			schedule_timeout_uninterruptible(HZ);
+ 			goto repeat;
+@@ -3875,12 +3879,13 @@ static void ext4_mb_show_ac(struct ext4_allocation_context *ac)
+ 	    (EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED))
+ 		return;
+ 
+-	printk(KERN_ERR "EXT4-fs: Can't allocate:"
+-			" Allocation context details:\n");
+-	printk(KERN_ERR "EXT4-fs: status %d flags %d\n",
++	ext4_msg(ac->ac_sb, KERN_ERR, "EXT4-fs: Can't allocate:"
++			" Allocation context details:");
++	ext4_msg(ac->ac_sb, KERN_ERR, "EXT4-fs: status %d flags %d",
+ 			ac->ac_status, ac->ac_flags);
+-	printk(KERN_ERR "EXT4-fs: orig %lu/%lu/%lu@%lu, goal %lu/%lu/%lu@%lu, "
+-			"best %lu/%lu/%lu@%lu cr %d\n",
++	ext4_msg(ac->ac_sb, KERN_ERR, "EXT4-fs: orig %lu/%lu/%lu@%lu, "
++		 	"goal %lu/%lu/%lu@%lu, "
++			"best %lu/%lu/%lu@%lu cr %d",
+ 			(unsigned long)ac->ac_o_ex.fe_group,
+ 			(unsigned long)ac->ac_o_ex.fe_start,
+ 			(unsigned long)ac->ac_o_ex.fe_len,
+@@ -3894,9 +3899,9 @@ static void ext4_mb_show_ac(struct ext4_allocation_context *ac)
+ 			(unsigned long)ac->ac_b_ex.fe_len,
+ 			(unsigned long)ac->ac_b_ex.fe_logical,
+ 			(int)ac->ac_criteria);
+-	printk(KERN_ERR "EXT4-fs: %lu scanned, %d found\n", ac->ac_ex_scanned,
+-		ac->ac_found);
+-	printk(KERN_ERR "EXT4-fs: groups: \n");
++	ext4_msg(ac->ac_sb, KERN_ERR, "EXT4-fs: %lu scanned, %d found",
++		 ac->ac_ex_scanned, ac->ac_found);
++	ext4_msg(ac->ac_sb, KERN_ERR, "EXT4-fs: groups: ");
+ 	ngroups = ext4_get_groups_count(sb);
+ 	for (i = 0; i < ngroups; i++) {
+ 		struct ext4_group_info *grp = ext4_get_group_info(sb, i);

commit f18a5f21c25707b4fe64b326e2b4d150565e7300
+Author: Theodore Ts'o 
+Date:   Mon Aug 1 08:45:38 2011 -0400
+
+    ext4: use ext4_kvzalloc()/ext4_kvmalloc() for s_group_desc and s_group_info
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index fa716c9b2455..d5021e82f8cc 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2331,7 +2331,7 @@ static int ext4_mb_init_backend(struct super_block *sb)
+ 	/* An 8TB filesystem with 64-bit pointers requires a 4096 byte
+ 	 * kmalloc. A 128kb malloc should suffice for a 256TB filesystem.
+ 	 * So a two level scheme suffices for now. */
+-	sbi->s_group_info = kzalloc(array_size, GFP_KERNEL);
++	sbi->s_group_info = ext4_kvzalloc(array_size, GFP_KERNEL);
+ 	if (sbi->s_group_info == NULL) {
+ 		printk(KERN_ERR "EXT4-fs: can't allocate buddy meta group\n");
+ 		return -ENOMEM;
+@@ -2365,7 +2365,7 @@ static int ext4_mb_init_backend(struct super_block *sb)
+ 		kfree(sbi->s_group_info[i]);
+ 	iput(sbi->s_buddy_cache);
+ err_freesgi:
+-	kfree(sbi->s_group_info);
++	ext4_kvfree(sbi->s_group_info);
+ 	return -ENOMEM;
+ }
+ 
+@@ -2559,7 +2559,7 @@ int ext4_mb_release(struct super_block *sb)
+ 			EXT4_DESC_PER_BLOCK_BITS(sb);
+ 		for (i = 0; i < num_meta_group_infos; i++)
+ 			kfree(sbi->s_group_info[i]);
+-		kfree(sbi->s_group_info);
++		ext4_kvfree(sbi->s_group_info);
+ 	}
+ 	kfree(sbi->s_mb_offsets);
+ 	kfree(sbi->s_mb_maxs);
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 71085df97bbd..707d3f16f7ce 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -467,12 +467,13 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ 	if (unlikely(err))
+ 		goto exit_dindj;
+ 
+-	n_group_desc = kmalloc((gdb_num + 1) * sizeof(struct buffer_head *),
+-			GFP_NOFS);
++	n_group_desc = ext4_kvmalloc((gdb_num + 1) *
++				     sizeof(struct buffer_head *),
++				     GFP_NOFS);
+ 	if (!n_group_desc) {
+ 		err = -ENOMEM;
+-		ext4_warning(sb,
+-			      "not enough memory for %lu groups", gdb_num + 1);
++		ext4_warning(sb, "not enough memory for %lu groups",
++			     gdb_num + 1);
+ 		goto exit_inode;
+ 	}
+ 
+@@ -507,7 +508,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ 	n_group_desc[gdb_num] = gdb_bh;
+ 	EXT4_SB(sb)->s_group_desc = n_group_desc;
+ 	EXT4_SB(sb)->s_gdb_count++;
+-	kfree(o_group_desc);
++	ext4_kvfree(o_group_desc);
+ 
+ 	le16_add_cpu(&es->s_reserved_gdt_blocks, -1);
+ 	err = ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh);
+@@ -517,7 +518,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ 	return err;
+ 
+ exit_inode:
+-	kfree(n_group_desc);
++	ext4_kvfree(n_group_desc);
+ 	/* ext4_handle_release_buffer(handle, iloc.bh); */
+ 	brelse(iloc.bh);
+ exit_dindj:
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 658f5864e9cf..e2d88baf91d3 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -819,7 +819,7 @@ static void ext4_put_super(struct super_block *sb)
+ 
+ 	for (i = 0; i < sbi->s_gdb_count; i++)
+ 		brelse(sbi->s_group_desc[i]);
+-	kfree(sbi->s_group_desc);
++	ext4_kvfree(sbi->s_group_desc);
+ 	ext4_kvfree(sbi->s_flex_groups);
+ 	percpu_counter_destroy(&sbi->s_freeblocks_counter);
+ 	percpu_counter_destroy(&sbi->s_freeinodes_counter);
+@@ -3439,8 +3439,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 			(EXT4_MAX_BLOCK_FILE_PHYS / EXT4_BLOCKS_PER_GROUP(sb)));
+ 	db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) /
+ 		   EXT4_DESC_PER_BLOCK(sb);
+-	sbi->s_group_desc = kmalloc(db_count * sizeof(struct buffer_head *),
+-				    GFP_KERNEL);
++	sbi->s_group_desc = ext4_kvmalloc(db_count *
++					  sizeof(struct buffer_head *),
++					  GFP_KERNEL);
+ 	if (sbi->s_group_desc == NULL) {
+ 		ext4_msg(sb, KERN_ERR, "not enough memory");
+ 		goto failed_mount;
+@@ -3783,7 +3784,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ failed_mount2:
+ 	for (i = 0; i < db_count; i++)
+ 		brelse(sbi->s_group_desc[i]);
+-	kfree(sbi->s_group_desc);
++	ext4_kvfree(sbi->s_group_desc);
+ failed_mount:
+ 	if (sbi->s_proc) {
+ 		remove_proc_entry(sb->s_id, ext4_proc_root);

commit 9933fc0ac1ac14b795819cd63d05ea92112f690a
+Author: Theodore Ts'o 
+Date:   Mon Aug 1 08:45:02 2011 -0400
+
+    ext4: introduce ext4_kvmalloc(), ext4_kzalloc(), and ext4_kvfree()
+    
+    Introduce new helper functions which try kmalloc, and then fall back
+    to vmalloc if necessary, and use them for allocating and deallocating
+    s_flex_groups.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index ba2009b49a55..db9feadf53a0 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1874,6 +1874,9 @@ extern int ext4_group_extend(struct super_block *sb,
+ 				ext4_fsblk_t n_blocks_count);
+ 
+ /* super.c */
++extern void *ext4_kvmalloc(size_t size, gfp_t flags);
++extern void *ext4_kvzalloc(size_t size, gfp_t flags);
++extern void ext4_kvfree(void *ptr);
+ extern void __ext4_error(struct super_block *, const char *, unsigned int,
+ 			 const char *, ...)
+ 	__attribute__ ((format (printf, 4, 5)));
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index cfe9f39c4ba2..658f5864e9cf 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -110,6 +110,35 @@ static struct file_system_type ext3_fs_type = {
+ #define IS_EXT3_SB(sb) (0)
+ #endif
+ 
++void *ext4_kvmalloc(size_t size, gfp_t flags)
++{
++	void *ret;
++
++	ret = kmalloc(size, flags);
++	if (!ret)
++		ret = __vmalloc(size, flags, PAGE_KERNEL);
++	return ret;
++}
++
++void *ext4_kvzalloc(size_t size, gfp_t flags)
++{
++	void *ret;
++
++	ret = kmalloc(size, flags);
++	if (!ret)
++		ret = __vmalloc(size, flags | __GFP_ZERO, PAGE_KERNEL);
++	return ret;
++}
++
++void ext4_kvfree(void *ptr)
++{
++	if (is_vmalloc_addr(ptr))
++		vfree(ptr);
++	else
++		kfree(ptr);
++
++}
++
+ ext4_fsblk_t ext4_block_bitmap(struct super_block *sb,
+ 			       struct ext4_group_desc *bg)
+ {
+@@ -791,10 +820,7 @@ static void ext4_put_super(struct super_block *sb)
+ 	for (i = 0; i < sbi->s_gdb_count; i++)
+ 		brelse(sbi->s_group_desc[i]);
+ 	kfree(sbi->s_group_desc);
+-	if (is_vmalloc_addr(sbi->s_flex_groups))
+-		vfree(sbi->s_flex_groups);
+-	else
+-		kfree(sbi->s_flex_groups);
++	ext4_kvfree(sbi->s_flex_groups);
+ 	percpu_counter_destroy(&sbi->s_freeblocks_counter);
+ 	percpu_counter_destroy(&sbi->s_freeinodes_counter);
+ 	percpu_counter_destroy(&sbi->s_dirs_counter);
+@@ -1977,15 +2003,11 @@ static int ext4_fill_flex_info(struct super_block *sb)
+ 			((le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) + 1) <<
+ 			      EXT4_DESC_PER_BLOCK_BITS(sb))) / groups_per_flex;
+ 	size = flex_group_count * sizeof(struct flex_groups);
+-	sbi->s_flex_groups = kzalloc(size, GFP_KERNEL);
++	sbi->s_flex_groups = ext4_kvzalloc(size, GFP_KERNEL);
+ 	if (sbi->s_flex_groups == NULL) {
+-		sbi->s_flex_groups = vzalloc(size);
+-		if (sbi->s_flex_groups == NULL) {
+-			ext4_msg(sb, KERN_ERR,
+-				 "not enough memory for %u flex groups",
+-				 flex_group_count);
+-			goto failed;
+-		}
++		ext4_msg(sb, KERN_ERR, "not enough memory for %u flex groups",
++			 flex_group_count);
++		goto failed;
+ 	}
+ 
+ 	for (i = 0; i < sbi->s_groups_count; i++) {
+@@ -3750,12 +3772,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	}
+ failed_mount3:
+ 	del_timer(&sbi->s_err_report);
+-	if (sbi->s_flex_groups) {
+-		if (is_vmalloc_addr(sbi->s_flex_groups))
+-			vfree(sbi->s_flex_groups);
+-		else
+-			kfree(sbi->s_flex_groups);
+-	}
++	if (sbi->s_flex_groups)
++		ext4_kvfree(sbi->s_flex_groups);
+ 	percpu_counter_destroy(&sbi->s_freeblocks_counter);
+ 	percpu_counter_destroy(&sbi->s_freeinodes_counter);
+ 	percpu_counter_destroy(&sbi->s_dirs_counter);

commit 59be8e7280c10fd8f078ba6dc2bcdc2b1453b6ab
+Author: Theodore Ts'o 
+Date:   Sat Jul 30 12:38:46 2011 -0400
+
+    ext4: change umode_t in tracepoint headers to be an explicit __u16
+    
+    As requested by Al Viro, since umode_t may be changing to a u32 for
+    some architectures.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Al Viro 
+
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index 51d88139eb8c..bf5518d50423 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -23,7 +23,7 @@ TRACE_EVENT(ext4_free_inode,
+ 	TP_STRUCT__entry(
+ 		__field(	dev_t,	dev			)
+ 		__field(	ino_t,	ino			)
+-		__field(	umode_t, mode			)
++		__field(	__u16, mode			)
+ 		__field(	uid_t,	uid			)
+ 		__field(	gid_t,	gid			)
+ 		__field(	__u64, blocks			)
+@@ -52,7 +52,7 @@ TRACE_EVENT(ext4_request_inode,
+ 	TP_STRUCT__entry(
+ 		__field(	dev_t,	dev			)
+ 		__field(	ino_t,	dir			)
+-		__field(	umode_t, mode			)
++		__field(	__u16, mode			)
+ 	),
+ 
+ 	TP_fast_assign(
+@@ -75,7 +75,7 @@ TRACE_EVENT(ext4_allocate_inode,
+ 		__field(	dev_t,	dev			)
+ 		__field(	ino_t,	ino			)
+ 		__field(	ino_t,	dir			)
+-		__field(	umode_t, mode			)
++		__field(	__u16,	mode			)
+ 	),
+ 
+ 	TP_fast_assign(
+@@ -727,7 +727,7 @@ TRACE_EVENT(ext4_free_blocks,
+ 	TP_STRUCT__entry(
+ 		__field(	dev_t,	dev			)
+ 		__field(	ino_t,	ino			)
+-		__field(	umode_t, mode			)
++		__field(	__u16,	mode			)
+ 		__field(	__u64,	block			)
+ 		__field(	unsigned long,	count		)
+ 		__field(	int,	flags			)
+@@ -1014,7 +1014,7 @@ TRACE_EVENT(ext4_forget,
+ 	TP_STRUCT__entry(
+ 		__field(	dev_t,	dev			)
+ 		__field(	ino_t,	ino			)
+-		__field(	umode_t, mode			)
++		__field(	__u16,	mode			)
+ 		__field(	int,	is_metadata		)
+ 		__field(	__u64,	block			)
+ 	),
+@@ -1041,7 +1041,7 @@ TRACE_EVENT(ext4_da_update_reserve_space,
+ 	TP_STRUCT__entry(
+ 		__field(	dev_t,	dev			)
+ 		__field(	ino_t,	ino			)
+-		__field(	umode_t, mode			)
++		__field(	__u16,	mode			)
+ 		__field(	__u64,	i_blocks		)
+ 		__field(	int,	used_blocks		)
+ 		__field(	int,	reserved_data_blocks	)
+@@ -1078,7 +1078,7 @@ TRACE_EVENT(ext4_da_reserve_space,
+ 	TP_STRUCT__entry(
+ 		__field(	dev_t,	dev			)
+ 		__field(	ino_t,	ino			)
+-		__field(	umode_t, mode			)
++		__field(	__u16,  mode			)
+ 		__field(	__u64,	i_blocks		)
+ 		__field(	int,	md_needed		)
+ 		__field(	int,	reserved_data_blocks	)
+@@ -1112,7 +1112,7 @@ TRACE_EVENT(ext4_da_release_space,
+ 	TP_STRUCT__entry(
+ 		__field(	dev_t,	dev			)
+ 		__field(	ino_t,	ino			)
+-		__field(	umode_t, mode			)
++		__field(	__u16,  mode			)
+ 		__field(	__u64,	i_blocks		)
+ 		__field(	int,	freed_blocks		)
+ 		__field(	int,	reserved_data_blocks	)

commit d59729f4e794f814b25ccd2aebfbe606242c4544
+Author: Theodore Ts'o 
+Date:   Sat Jul 30 12:34:19 2011 -0400
+
+    ext4: fix races in ext4_sync_parent()
+    
+    Fix problems if fsync() races against a rename of a parent directory
+    as pointed out by Al Viro in his own inimitable way:
+    
+    >While we are at it, could somebody please explain what the hell is ext4
+    >doing in
+    >static int ext4_sync_parent(struct inode *inode)
+    >{
+    >        struct writeback_control wbc;
+    >        struct dentry *dentry = NULL;
+    >        int ret = 0;
+    >
+    >        while (inode && ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) {
+    >                ext4_clear_inode_state(inode, EXT4_STATE_NEWENTRY);
+    >                dentry = list_entry(inode->i_dentry.next,
+    >                                    struct dentry, d_alias);
+    >                if (!dentry || !dentry->d_parent || !dentry->d_parent->d_inode)
+    >                        break;
+    >                inode = dentry->d_parent->d_inode;
+    >                ret = sync_mapping_buffers(inode->i_mapping);
+    >                ...
+    >Note that dentry obviously can't be NULL there.  dentry->d_parent is never
+    >NULL.  And dentry->d_parent would better not be negative, for crying out
+    >loud!  What's worse, there's no guarantees that dentry->d_parent will
+    >remain our parent over that sync_mapping_buffers() *and* that inode won't
+    >just be freed under us (after rename() and memory pressure leading to
+    >eviction of what used to be our dentry->d_parent)......
+    
+    Reported-by: Al Viro 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
+index ce66d2fe826c..f9dbe33cde5e 100644
+--- a/fs/ext4/fsync.c
++++ b/fs/ext4/fsync.c
+@@ -129,15 +129,30 @@ static int ext4_sync_parent(struct inode *inode)
+ {
+ 	struct writeback_control wbc;
+ 	struct dentry *dentry = NULL;
++	struct inode *next;
+ 	int ret = 0;
+ 
+-	while (inode && ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) {
++	if (!ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY))
++		return 0;
++	inode = igrab(inode);
++	while (ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) {
+ 		ext4_clear_inode_state(inode, EXT4_STATE_NEWENTRY);
+-		dentry = list_entry(inode->i_dentry.next,
+-				    struct dentry, d_alias);
+-		if (!dentry || !dentry->d_parent || !dentry->d_parent->d_inode)
++		dentry = NULL;
++		spin_lock(&inode->i_lock);
++		if (!list_empty(&inode->i_dentry)) {
++			dentry = list_first_entry(&inode->i_dentry,
++						  struct dentry, d_alias);
++			dget(dentry);
++		}
++		spin_unlock(&inode->i_lock);
++		if (!dentry)
++			break;
++		next = igrab(dentry->d_parent->d_inode);
++		dput(dentry);
++		if (!next)
+ 			break;
+-		inode = dentry->d_parent->d_inode;
++		iput(inode);
++		inode = next;
+ 		ret = sync_mapping_buffers(inode->i_mapping);
+ 		if (ret)
+ 			break;
+@@ -148,6 +163,7 @@ static int ext4_sync_parent(struct inode *inode)
+ 		if (ret)
+ 			break;
+ 	}
++	iput(inode);
+ 	return ret;
+ }
+ 

commit aafade242ff24fac3aabf61c7861dfa44a3c2445
+Author: Andy Lutomirski 
+Date:   Thu Jul 21 15:47:10 2011 -0400
+
+    x86-64, vdso: Do not allocate memory for the vDSO
+    
+    We can map the vDSO straight from kernel data, saving a few page
+    allocations.  As an added bonus, the deleted code contained a memory
+    leak.
+    
+    Signed-off-by: Andy Lutomirski 
+    Link: http://lkml.kernel.org/r/2c4ed5c2c2e93603790229e0c3403ae506ccc0cb.1311277573.git.luto@mit.edu
+    Signed-off-by: H. Peter Anvin 
+
+diff --git a/arch/x86/vdso/vdso.S b/arch/x86/vdso/vdso.S
+index 1d3aa6b87181..1b979c12ba85 100644
+--- a/arch/x86/vdso/vdso.S
++++ b/arch/x86/vdso/vdso.S
+@@ -1,10 +1,21 @@
++#include 
++#include 
+ #include 
+ 
+-__INITDATA
++__PAGE_ALIGNED_DATA
+ 
+ 	.globl vdso_start, vdso_end
++	.align PAGE_SIZE
+ vdso_start:
+ 	.incbin "arch/x86/vdso/vdso.so"
+ vdso_end:
+ 
+-__FINIT
++.previous
++
++	.globl vdso_pages
++	.bss
++	.align 8
++	.type vdso_pages, @object
++vdso_pages:
++	.zero (vdso_end - vdso_start + PAGE_SIZE - 1) / PAGE_SIZE * 8
++	.size vdso_pages, .-vdso_pages
+diff --git a/arch/x86/vdso/vma.c b/arch/x86/vdso/vma.c
+index c39938d1332f..316fbca3490e 100644
+--- a/arch/x86/vdso/vma.c
++++ b/arch/x86/vdso/vma.c
+@@ -14,13 +14,14 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ unsigned int __read_mostly vdso_enabled = 1;
+ 
+ extern char vdso_start[], vdso_end[];
+ extern unsigned short vdso_sync_cpuid;
+ 
+-static struct page **vdso_pages;
++extern struct page *vdso_pages[];
+ static unsigned vdso_size;
+ 
+ static void __init patch_vdso(void *vdso, size_t len)
+@@ -54,7 +55,7 @@ static void __init patch_vdso(void *vdso, size_t len)
+ 	apply_alternatives(alt_data, alt_data + alt_sec->sh_size);
+ }
+ 
+-static int __init init_vdso_vars(void)
++static int __init init_vdso(void)
+ {
+ 	int npages = (vdso_end - vdso_start + PAGE_SIZE - 1) / PAGE_SIZE;
+ 	int i;
+@@ -62,26 +63,12 @@ static int __init init_vdso_vars(void)
+ 	patch_vdso(vdso_start, vdso_end - vdso_start);
+ 
+ 	vdso_size = npages << PAGE_SHIFT;
+-	vdso_pages = kmalloc(sizeof(struct page *) * npages, GFP_KERNEL);
+-	if (!vdso_pages)
+-		goto oom;
+-	for (i = 0; i < npages; i++) {
+-		struct page *p;
+-		p = alloc_page(GFP_KERNEL);
+-		if (!p)
+-			goto oom;
+-		vdso_pages[i] = p;
+-		copy_page(page_address(p), vdso_start + i*PAGE_SIZE);
+-	}
++	for (i = 0; i < npages; i++)
++		vdso_pages[i] = virt_to_page(vdso_start + i*PAGE_SIZE);
+ 
+ 	return 0;
+-
+- oom:
+-	printk("Cannot allocate vdso\n");
+-	vdso_enabled = 0;
+-	return -ENOMEM;
+ }
+-subsys_initcall(init_vdso_vars);
++subsys_initcall(init_vdso);
+ 
+ struct linux_binprm;
+ 

commit 98eedc3a9dbf90cecb91093d2a7fa083942b7d13
+Author: Andy Lutomirski 
+Date:   Wed Jul 13 09:24:16 2011 -0400
+
+    Document the vDSO and add a reference parser
+    
+    It turns out that parsing the vDSO is nontrivial if you don't already
+    have an ELF dynamic loader around.  So document it in Documentation/ABI
+    and add a reference CC0-licenced parser.
+    
+    This code is dedicated to Go issue 1933:
+    http://code.google.com/p/go/issues/detail?id=1933
+    
+    Signed-off-by: Andy Lutomirski 
+    Link: http://lkml.kernel.org/r/a315a9514cd71bcf29436cc31e35aada21a5ff21.1310563276.git.luto@mit.edu
+    Signed-off-by: H. Peter Anvin 
+
+diff --git a/Documentation/ABI/stable/vdso b/Documentation/ABI/stable/vdso
+new file mode 100644
+index 000000000000..8a1cbb594497
+--- /dev/null
++++ b/Documentation/ABI/stable/vdso
+@@ -0,0 +1,27 @@
++On some architectures, when the kernel loads any userspace program it
++maps an ELF DSO into that program's address space.  This DSO is called
++the vDSO and it often contains useful and highly-optimized alternatives
++to real syscalls.
++
++These functions are called just like ordinary C function according to
++your platform's ABI.  Call them from a sensible context.  (For example,
++if you set CS on x86 to something strange, the vDSO functions are
++within their rights to crash.)  In addition, if you pass a bad
++pointer to a vDSO function, you might get SIGSEGV instead of -EFAULT.
++
++To find the DSO, parse the auxiliary vector passed to the program's
++entry point.  The AT_SYSINFO_EHDR entry will point to the vDSO.
++
++The vDSO uses symbol versioning; whenever you request a symbol from the
++vDSO, specify the version you are expecting.
++
++Programs that dynamically link to glibc will use the vDSO automatically.
++Otherwise, you can use the reference parser in Documentation/vDSO/parse_vdso.c.
++
++Unless otherwise noted, the set of symbols with any given version and the
++ABI of those symbols is considered stable.  It may vary across architectures,
++though.
++
++(As of this writing, this ABI documentation as been confirmed for x86_64.
++ The maintainers of the other vDSO-using architectures should confirm
++ that it is correct for their architecture.)
+\ No newline at end of file
+diff --git a/Documentation/vDSO/parse_vdso.c b/Documentation/vDSO/parse_vdso.c
+new file mode 100644
+index 000000000000..85870208edcf
+--- /dev/null
++++ b/Documentation/vDSO/parse_vdso.c
+@@ -0,0 +1,256 @@
++/*
++ * parse_vdso.c: Linux reference vDSO parser
++ * Written by Andrew Lutomirski, 2011.
++ *
++ * This code is meant to be linked in to various programs that run on Linux.
++ * As such, it is available with as few restrictions as possible.  This file
++ * is licensed under the Creative Commons Zero License, version 1.0,
++ * available at http://creativecommons.org/publicdomain/zero/1.0/legalcode
++ *
++ * The vDSO is a regular ELF DSO that the kernel maps into user space when
++ * it starts a program.  It works equally well in statically and dynamically
++ * linked binaries.
++ *
++ * This code is tested on x86_64.  In principle it should work on any 64-bit
++ * architecture that has a vDSO.
++ */
++
++#include 
++#include 
++#include 
++#include 
++
++/*
++ * To use this vDSO parser, first call one of the vdso_init_* functions.
++ * If you've already parsed auxv, then pass the value of AT_SYSINFO_EHDR
++ * to vdso_init_from_sysinfo_ehdr.  Otherwise pass auxv to vdso_init_from_auxv.
++ * Then call vdso_sym for each symbol you want.  For example, to look up
++ * gettimeofday on x86_64, use:
++ *
++ *      = vdso_sym("LINUX_2.6", "gettimeofday");
++ * or
++ *      = vdso_sym("LINUX_2.6", "__vdso_gettimeofday");
++ *
++ * vdso_sym will return 0 if the symbol doesn't exist or if the init function
++ * failed or was not called.  vdso_sym is a little slow, so its return value
++ * should be cached.
++ *
++ * vdso_sym is threadsafe; the init functions are not.
++ *
++ * These are the prototypes:
++ */
++extern void vdso_init_from_auxv(void *auxv);
++extern void vdso_init_from_sysinfo_ehdr(uintptr_t base);
++extern void *vdso_sym(const char *version, const char *name);
++
++
++/* And here's the code. */
++
++#ifndef __x86_64__
++# error Not yet ported to non-x86_64 architectures
++#endif
++
++static struct vdso_info
++{
++	bool valid;
++
++	/* Load information */
++	uintptr_t load_addr;
++	uintptr_t load_offset;  /* load_addr - recorded vaddr */
++
++	/* Symbol table */
++	Elf64_Sym *symtab;
++	const char *symstrings;
++	Elf64_Word *bucket, *chain;
++	Elf64_Word nbucket, nchain;
++
++	/* Version table */
++	Elf64_Versym *versym;
++	Elf64_Verdef *verdef;
++} vdso_info;
++
++/* Straight from the ELF specification. */
++static unsigned long elf_hash(const unsigned char *name)
++{
++	unsigned long h = 0, g;
++	while (*name)
++	{
++		h = (h << 4) + *name++;
++		if (g = h & 0xf0000000)
++			h ^= g >> 24;
++		h &= ~g;
++	}
++	return h;
++}
++
++void vdso_init_from_sysinfo_ehdr(uintptr_t base)
++{
++	size_t i;
++	bool found_vaddr = false;
++
++	vdso_info.valid = false;
++
++	vdso_info.load_addr = base;
++
++	Elf64_Ehdr *hdr = (Elf64_Ehdr*)base;
++	Elf64_Phdr *pt = (Elf64_Phdr*)(vdso_info.load_addr + hdr->e_phoff);
++	Elf64_Dyn *dyn = 0;
++
++	/*
++	 * We need two things from the segment table: the load offset
++	 * and the dynamic table.
++	 */
++	for (i = 0; i < hdr->e_phnum; i++)
++	{
++		if (pt[i].p_type == PT_LOAD && !found_vaddr) {
++			found_vaddr = true;
++			vdso_info.load_offset =	base
++				+ (uintptr_t)pt[i].p_offset
++				- (uintptr_t)pt[i].p_vaddr;
++		} else if (pt[i].p_type == PT_DYNAMIC) {
++			dyn = (Elf64_Dyn*)(base + pt[i].p_offset);
++		}
++	}
++
++	if (!found_vaddr || !dyn)
++		return;  /* Failed */
++
++	/*
++	 * Fish out the useful bits of the dynamic table.
++	 */
++	Elf64_Word *hash = 0;
++	vdso_info.symstrings = 0;
++	vdso_info.symtab = 0;
++	vdso_info.versym = 0;
++	vdso_info.verdef = 0;
++	for (i = 0; dyn[i].d_tag != DT_NULL; i++) {
++		switch (dyn[i].d_tag) {
++		case DT_STRTAB:
++			vdso_info.symstrings = (const char *)
++				((uintptr_t)dyn[i].d_un.d_ptr
++				 + vdso_info.load_offset);
++			break;
++		case DT_SYMTAB:
++			vdso_info.symtab = (Elf64_Sym *)
++				((uintptr_t)dyn[i].d_un.d_ptr
++				 + vdso_info.load_offset);
++			break;
++		case DT_HASH:
++			hash = (Elf64_Word *)
++				((uintptr_t)dyn[i].d_un.d_ptr
++				 + vdso_info.load_offset);
++			break;
++		case DT_VERSYM:
++			vdso_info.versym = (Elf64_Versym *)
++				((uintptr_t)dyn[i].d_un.d_ptr
++				 + vdso_info.load_offset);
++			break;
++		case DT_VERDEF:
++			vdso_info.verdef = (Elf64_Verdef *)
++				((uintptr_t)dyn[i].d_un.d_ptr
++				 + vdso_info.load_offset);
++			break;
++		}
++	}
++	if (!vdso_info.symstrings || !vdso_info.symtab || !hash)
++		return;  /* Failed */
++
++	if (!vdso_info.verdef)
++		vdso_info.versym = 0;
++
++	/* Parse the hash table header. */
++	vdso_info.nbucket = hash[0];
++	vdso_info.nchain = hash[1];
++	vdso_info.bucket = &hash[2];
++	vdso_info.chain = &hash[vdso_info.nbucket + 2];
++
++	/* That's all we need. */
++	vdso_info.valid = true;
++}
++
++static bool vdso_match_version(Elf64_Versym ver,
++			       const char *name, Elf64_Word hash)
++{
++	/*
++	 * This is a helper function to check if the version indexed by
++	 * ver matches name (which hashes to hash).
++	 *
++	 * The version definition table is a mess, and I don't know how
++	 * to do this in better than linear time without allocating memory
++	 * to build an index.  I also don't know why the table has
++	 * variable size entries in the first place.
++	 *
++	 * For added fun, I can't find a comprehensible specification of how
++	 * to parse all the weird flags in the table.
++	 *
++	 * So I just parse the whole table every time.
++	 */
++
++	/* First step: find the version definition */
++	ver &= 0x7fff;  /* Apparently bit 15 means "hidden" */
++	Elf64_Verdef *def = vdso_info.verdef;
++	while(true) {
++		if ((def->vd_flags & VER_FLG_BASE) == 0
++		    && (def->vd_ndx & 0x7fff) == ver)
++			break;
++
++		if (def->vd_next == 0)
++			return false;  /* No definition. */
++
++		def = (Elf64_Verdef *)((char *)def + def->vd_next);
++	}
++
++	/* Now figure out whether it matches. */
++	Elf64_Verdaux *aux = (Elf64_Verdaux*)((char *)def + def->vd_aux);
++	return def->vd_hash == hash
++		&& !strcmp(name, vdso_info.symstrings + aux->vda_name);
++}
++
++void *vdso_sym(const char *version, const char *name)
++{
++	unsigned long ver_hash;
++	if (!vdso_info.valid)
++		return 0;
++
++	ver_hash = elf_hash(version);
++	Elf64_Word chain = vdso_info.bucket[elf_hash(name) % vdso_info.nbucket];
++
++	for (; chain != STN_UNDEF; chain = vdso_info.chain[chain]) {
++		Elf64_Sym *sym = &vdso_info.symtab[chain];
++
++		/* Check for a defined global or weak function w/ right name. */
++		if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC)
++			continue;
++		if (ELF64_ST_BIND(sym->st_info) != STB_GLOBAL &&
++		    ELF64_ST_BIND(sym->st_info) != STB_WEAK)
++			continue;
++		if (sym->st_shndx == SHN_UNDEF)
++			continue;
++		if (strcmp(name, vdso_info.symstrings + sym->st_name))
++			continue;
++
++		/* Check symbol version. */
++		if (vdso_info.versym
++		    && !vdso_match_version(vdso_info.versym[chain],
++					   version, ver_hash))
++			continue;
++
++		return (void *)(vdso_info.load_offset + sym->st_value);
++	}
++
++	return 0;
++}
++
++void vdso_init_from_auxv(void *auxv)
++{
++	Elf64_auxv_t *elf_auxv = auxv;
++	for (int i = 0; elf_auxv[i].a_type != AT_NULL; i++)
++	{
++		if (elf_auxv[i].a_type == AT_SYSINFO_EHDR) {
++			vdso_init_from_sysinfo_ehdr(elf_auxv[i].a_un.a_val);
++			return;
++		}
++	}
++
++	vdso_info.valid = false;
++}
+diff --git a/Documentation/vDSO/vdso_test.c b/Documentation/vDSO/vdso_test.c
+new file mode 100644
+index 000000000000..fff633432dff
+--- /dev/null
++++ b/Documentation/vDSO/vdso_test.c
+@@ -0,0 +1,111 @@
++/*
++ * vdso_test.c: Sample code to test parse_vdso.c on x86_64
++ * Copyright (c) 2011 Andy Lutomirski
++ * Subject to the GNU General Public License, version 2
++ *
++ * You can amuse yourself by compiling with:
++ * gcc -std=gnu99 -nostdlib
++ *     -Os -fno-asynchronous-unwind-tables -flto
++ *      vdso_test.c parse_vdso.c -o vdso_test
++ * to generate a small binary with no dependencies at all.
++ */
++
++#include 
++#include 
++#include 
++#include 
++
++extern void *vdso_sym(const char *version, const char *name);
++extern void vdso_init_from_sysinfo_ehdr(uintptr_t base);
++extern void vdso_init_from_auxv(void *auxv);
++
++/* We need a libc functions... */
++int strcmp(const char *a, const char *b)
++{
++	/* This implementation is buggy: it never returns -1. */
++	while (*a || *b) {
++		if (*a != *b)
++			return 1;
++		if (*a == 0 || *b == 0)
++			return 1;
++		a++;
++		b++;
++	}
++
++	return 0;
++}
++
++/* ...and two syscalls.  This is x86_64-specific. */
++static inline long linux_write(int fd, const void *data, size_t len)
++{
++
++	long ret;
++	asm volatile ("syscall" : "=a" (ret) : "a" (__NR_write),
++		      "D" (fd), "S" (data), "d" (len) :
++		      "cc", "memory", "rcx",
++		      "r8", "r9", "r10", "r11" );
++	return ret;
++}
++
++static inline void linux_exit(int code)
++{
++	asm volatile ("syscall" : : "a" (__NR_exit), "D" (code));
++}
++
++void to_base10(char *lastdig, uint64_t n)
++{
++	while (n) {
++		*lastdig = (n % 10) + '0';
++		n /= 10;
++		lastdig--;
++	}
++}
++
++__attribute__((externally_visible)) void c_main(void **stack)
++{
++	/* Parse the stack */
++	long argc = (long)*stack;
++	stack += argc + 2;
++
++	/* Now we're pointing at the environment.  Skip it. */
++	while(*stack)
++		stack++;
++	stack++;
++
++	/* Now we're pointing at auxv.  Initialize the vDSO parser. */
++	vdso_init_from_auxv((void *)stack);
++
++	/* Find gettimeofday. */
++	typedef long (*gtod_t)(struct timeval *tv, struct timezone *tz);
++	gtod_t gtod = (gtod_t)vdso_sym("LINUX_2.6", "__vdso_gettimeofday");
++
++	if (!gtod)
++		linux_exit(1);
++
++	struct timeval tv;
++	long ret = gtod(&tv, 0);
++
++	if (ret == 0) {
++		char buf[] = "The time is                     .000000\n";
++		to_base10(buf + 31, tv.tv_sec);
++		to_base10(buf + 38, tv.tv_usec);
++		linux_write(1, buf, sizeof(buf) - 1);
++	} else {
++		linux_exit(ret);
++	}
++
++	linux_exit(0);
++}
++
++/*
++ * This is the real entry point.  It passes the initial stack into
++ * the C entry point.
++ */
++asm (
++	".text\n"
++	".global _start\n"
++        ".type _start,@function\n"
++        "_start:\n\t"
++        "mov %rsp,%rdi\n\t"
++        "jmp c_main"
++	);

commit 574c44fa8fa6262ffd5939789ef51a6e98ed62d7
+Author: Andy Lutomirski 
+Date:   Wed Jul 13 09:24:15 2011 -0400
+
+    ia64: Replace clocksource.fsys_mmio with generic arch data
+    
+    Now that clocksource.archdata is available, use it for ia64-specific
+    code.
+    
+    Cc: Clemens Ladisch 
+    Cc: linux-ia64@vger.kernel.org
+    Cc: Tony Luck 
+    Cc: Fenghua Yu 
+    Cc: John Stultz 
+    Cc: Thomas Gleixner 
+    Signed-off-by: Andy Lutomirski 
+    Link: http://lkml.kernel.org/r/d31de0ee0842a0e322fb6441571c2b0adb323fa2.1310563276.git.luto@mit.edu
+    Signed-off-by: H. Peter Anvin 
+
+diff --git a/arch/ia64/include/asm/clocksource.h b/arch/ia64/include/asm/clocksource.h
+new file mode 100644
+index 000000000000..00eb549a59b0
+--- /dev/null
++++ b/arch/ia64/include/asm/clocksource.h
+@@ -0,0 +1,12 @@
++/* IA64-specific clocksource additions */
++
++#ifndef _ASM_IA64_CLOCKSOURCE_H
++#define _ASM_IA64_CLOCKSOURCE_H
++
++#define __ARCH_HAS_CLOCKSOURCE_DATA
++
++struct arch_clocksource_data {
++	void *fsys_mmio;        /* used by fsyscall asm code */
++};
++
++#endif /* _ASM_IA64_CLOCKSOURCE_H */
+diff --git a/arch/ia64/kernel/cyclone.c b/arch/ia64/kernel/cyclone.c
+index f64097b5118a..4826ff957a3d 100644
+--- a/arch/ia64/kernel/cyclone.c
++++ b/arch/ia64/kernel/cyclone.c
+@@ -115,7 +115,7 @@ int __init init_cyclone_clock(void)
+ 	}
+ 	/* initialize last tick */
+ 	cyclone_mc = cyclone_timer;
+-	clocksource_cyclone.fsys_mmio = cyclone_timer;
++	clocksource_cyclone.archdata.fsys_mmio = cyclone_timer;
+ 	clocksource_register_hz(&clocksource_cyclone, CYCLONE_TIMER_FREQ);
+ 
+ 	return 0;
+diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
+index 85118dfe9bb5..43920de425f1 100644
+--- a/arch/ia64/kernel/time.c
++++ b/arch/ia64/kernel/time.c
+@@ -468,7 +468,7 @@ void update_vsyscall(struct timespec *wall, struct timespec *wtm,
+         fsyscall_gtod_data.clk_mask = c->mask;
+         fsyscall_gtod_data.clk_mult = mult;
+         fsyscall_gtod_data.clk_shift = c->shift;
+-        fsyscall_gtod_data.clk_fsys_mmio = c->fsys_mmio;
++        fsyscall_gtod_data.clk_fsys_mmio = c->archdata.fsys_mmio;
+         fsyscall_gtod_data.clk_cycle_last = c->cycle_last;
+ 
+ 	/* copy kernel time structures */
+diff --git a/arch/ia64/sn/kernel/sn2/timer.c b/arch/ia64/sn/kernel/sn2/timer.c
+index c34efda122e1..0f8844e49363 100644
+--- a/arch/ia64/sn/kernel/sn2/timer.c
++++ b/arch/ia64/sn/kernel/sn2/timer.c
+@@ -54,7 +54,7 @@ ia64_sn_udelay (unsigned long usecs)
+ 
+ void __init sn_timer_init(void)
+ {
+-	clocksource_sn2.fsys_mmio = RTC_COUNTER_ADDR;
++	clocksource_sn2.archdata.fsys_mmio = RTC_COUNTER_ADDR;
+ 	clocksource_register_hz(&clocksource_sn2, sn_rtc_cycles_per_second);
+ 
+ 	ia64_udelay = &ia64_sn_udelay;
+diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
+index 051474c65b78..055765147dc2 100644
+--- a/drivers/char/hpet.c
++++ b/drivers/char/hpet.c
+@@ -931,7 +931,7 @@ int hpet_alloc(struct hpet_data *hdp)
+ #ifdef CONFIG_IA64
+ 	if (!hpet_clocksource) {
+ 		hpet_mctr = (void __iomem *)&hpetp->hp_hpet->hpet_mc;
+-		CLKSRC_FSYS_MMIO_SET(clocksource_hpet.fsys_mmio, hpet_mctr);
++		clocksource_hpet.archdata.fsys_mmio = hpet_mctr;
+ 		clocksource_register_hz(&clocksource_hpet, hpetp->hp_tick_freq);
+ 		hpetp->hp_clocksource = &clocksource_hpet;
+ 		hpet_clocksource = &clocksource_hpet;
+diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
+index 0fb83c224471..6bb69702c4fa 100644
+--- a/include/linux/clocksource.h
++++ b/include/linux/clocksource.h
+@@ -171,13 +171,6 @@ struct clocksource {
+ 	u32 shift;
+ 	u64 max_idle_ns;
+ 
+-#ifdef CONFIG_IA64
+-	void *fsys_mmio;        /* used by fsyscall asm code */
+-#define CLKSRC_FSYS_MMIO_SET(mmio, addr)      ((mmio) = (addr))
+-#else
+-#define CLKSRC_FSYS_MMIO_SET(mmio, addr)      do { } while (0)
+-#endif
+-
+ #ifdef __ARCH_HAS_CLOCKSOURCE_DATA
+ 	struct arch_clocksource_data archdata;
+ #endif

commit 98d0ac38ca7b1b7a552c9a2359174ff84decb600
+Author: Andy Lutomirski 
+Date:   Thu Jul 14 06:47:22 2011 -0400
+
+    x86-64: Move vread_tsc and vread_hpet into the vDSO
+    
+    The vsyscall page now consists entirely of trap instructions.
+    
+    Cc: John Stultz 
+    Signed-off-by: Andy Lutomirski 
+    Link: http://lkml.kernel.org/r/637648f303f2ef93af93bae25186e9a1bea093f5.1310639973.git.luto@mit.edu
+    Signed-off-by: H. Peter Anvin 
+
+diff --git a/arch/x86/include/asm/clocksource.h b/arch/x86/include/asm/clocksource.h
+index a5df33f614c9..3882c65dc19b 100644
+--- a/arch/x86/include/asm/clocksource.h
++++ b/arch/x86/include/asm/clocksource.h
+@@ -7,8 +7,12 @@
+ 
+ #define __ARCH_HAS_CLOCKSOURCE_DATA
+ 
++#define VCLOCK_NONE 0  /* No vDSO clock available.	*/
++#define VCLOCK_TSC  1  /* vDSO should use vread_tsc.	*/
++#define VCLOCK_HPET 2  /* vDSO should use vread_hpet.	*/
++
+ struct arch_clocksource_data {
+-	cycle_t (*vread)(void);
++	int vclock_mode;
+ };
+ 
+ #endif /* CONFIG_X86_64 */
+diff --git a/arch/x86/include/asm/tsc.h b/arch/x86/include/asm/tsc.h
+index 9db5583b6d38..83e2efd181e2 100644
+--- a/arch/x86/include/asm/tsc.h
++++ b/arch/x86/include/asm/tsc.h
+@@ -51,10 +51,6 @@ extern int unsynchronized_tsc(void);
+ extern int check_tsc_unstable(void);
+ extern unsigned long native_calibrate_tsc(void);
+ 
+-#ifdef CONFIG_X86_64
+-extern cycles_t vread_tsc(void);
+-#endif
+-
+ /*
+  * Boot-time check whether the TSCs are synchronized across
+  * all CPUs/cores:
+diff --git a/arch/x86/include/asm/vgtod.h b/arch/x86/include/asm/vgtod.h
+index aa5add855a91..815285bcaceb 100644
+--- a/arch/x86/include/asm/vgtod.h
++++ b/arch/x86/include/asm/vgtod.h
+@@ -13,7 +13,7 @@ struct vsyscall_gtod_data {
+ 
+ 	struct timezone sys_tz;
+ 	struct { /* extract of a clocksource struct */
+-		cycle_t (*vread)(void);
++		int vclock_mode;
+ 		cycle_t	cycle_last;
+ 		cycle_t	mask;
+ 		u32	mult;
+diff --git a/arch/x86/include/asm/vsyscall.h b/arch/x86/include/asm/vsyscall.h
+index d55597351f6a..60107072c28b 100644
+--- a/arch/x86/include/asm/vsyscall.h
++++ b/arch/x86/include/asm/vsyscall.h
+@@ -16,10 +16,6 @@ enum vsyscall_num {
+ #ifdef __KERNEL__
+ #include 
+ 
+-/* Definitions for CONFIG_GENERIC_TIME definitions */
+-#define __vsyscall_fn \
+-	__attribute__ ((unused, __section__(".vsyscall_fn"))) notrace
+-
+ #define VGETCPU_RDTSCP	1
+ #define VGETCPU_LSL	2
+ 
+diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
+index cc0469a65120..2deef3d2435a 100644
+--- a/arch/x86/kernel/Makefile
++++ b/arch/x86/kernel/Makefile
+@@ -24,17 +24,12 @@ endif
+ nostackp := $(call cc-option, -fno-stack-protector)
+ CFLAGS_vsyscall_64.o	:= $(PROFILING) -g0 $(nostackp)
+ CFLAGS_hpet.o		:= $(nostackp)
+-CFLAGS_vread_tsc_64.o	:= $(nostackp)
+ CFLAGS_paravirt.o	:= $(nostackp)
+ GCOV_PROFILE_vsyscall_64.o	:= n
+ GCOV_PROFILE_hpet.o		:= n
+ GCOV_PROFILE_tsc.o		:= n
+-GCOV_PROFILE_vread_tsc_64.o	:= n
+ GCOV_PROFILE_paravirt.o		:= n
+ 
+-# vread_tsc_64 is hot and should be fully optimized:
+-CFLAGS_REMOVE_vread_tsc_64.o = -pg -fno-optimize-sibling-calls
+-
+ obj-y			:= process_$(BITS).o signal.o entry_$(BITS).o
+ obj-y			+= traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
+ obj-y			+= time.o ioport.o ldt.o dumpstack.o
+@@ -43,7 +38,7 @@ obj-$(CONFIG_IRQ_WORK)  += irq_work.o
+ obj-y			+= probe_roms.o
+ obj-$(CONFIG_X86_32)	+= sys_i386_32.o i386_ksyms_32.o
+ obj-$(CONFIG_X86_64)	+= sys_x86_64.o x8664_ksyms_64.o
+-obj-$(CONFIG_X86_64)	+= syscall_64.o vsyscall_64.o vread_tsc_64.o
++obj-$(CONFIG_X86_64)	+= syscall_64.o vsyscall_64.o
+ obj-$(CONFIG_X86_64)	+= vsyscall_emu_64.o
+ obj-y			+= bootflag.o e820.o
+ obj-y			+= pci-dma.o quirks.o topology.o kdebugfs.o
+diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
+index ddb207bb5f91..c63822816249 100644
+--- a/arch/x86/kernel/alternative.c
++++ b/arch/x86/kernel/alternative.c
+@@ -14,7 +14,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ #include 
+ #include 
+ #include 
+@@ -250,7 +249,6 @@ static void __init_or_module add_nops(void *insns, unsigned int len)
+ 
+ extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
+ extern s32 __smp_locks[], __smp_locks_end[];
+-extern char __vsyscall_0;
+ void *text_poke_early(void *addr, const void *opcode, size_t len);
+ 
+ /* Replace instructions with better alternatives for this CPU type.
+@@ -294,12 +292,6 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
+ 		add_nops(insnbuf + a->replacementlen,
+ 			 a->instrlen - a->replacementlen);
+ 
+-#ifdef CONFIG_X86_64
+-		/* vsyscall code is not mapped yet. resolve it manually. */
+-		if (instr >= (u8 *)VSYSCALL_START && instr < (u8*)VSYSCALL_END) {
+-			instr = __va(instr - (u8*)VSYSCALL_START + (u8*)__pa_symbol(&__vsyscall_0));
+-		}
+-#endif
+ 		text_poke_early(instr, insnbuf, a->instrlen);
+ 	}
+ }
+diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
+index 0e07257bb389..d10cc009845f 100644
+--- a/arch/x86/kernel/hpet.c
++++ b/arch/x86/kernel/hpet.c
+@@ -738,13 +738,6 @@ static cycle_t read_hpet(struct clocksource *cs)
+ 	return (cycle_t)hpet_readl(HPET_COUNTER);
+ }
+ 
+-#ifdef CONFIG_X86_64
+-static cycle_t __vsyscall_fn vread_hpet(void)
+-{
+-	return readl((const void __iomem *)fix_to_virt(VSYSCALL_HPET) + 0xf0);
+-}
+-#endif
+-
+ static struct clocksource clocksource_hpet = {
+ 	.name		= "hpet",
+ 	.rating		= 250,
+@@ -753,7 +746,7 @@ static struct clocksource clocksource_hpet = {
+ 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+ 	.resume		= hpet_resume_counter,
+ #ifdef CONFIG_X86_64
+-	.archdata	= { .vread = vread_hpet },
++	.archdata	= { .vclock_mode = VCLOCK_HPET },
+ #endif
+ };
+ 
+diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
+index e7a74b889ab3..56c633a5db72 100644
+--- a/arch/x86/kernel/tsc.c
++++ b/arch/x86/kernel/tsc.c
+@@ -777,7 +777,7 @@ static struct clocksource clocksource_tsc = {
+ 	.flags                  = CLOCK_SOURCE_IS_CONTINUOUS |
+ 				  CLOCK_SOURCE_MUST_VERIFY,
+ #ifdef CONFIG_X86_64
+-	.archdata               = { .vread = vread_tsc },
++	.archdata               = { .vclock_mode = VCLOCK_TSC },
+ #endif
+ };
+ 
+diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
+index 80174719910c..4aa9c54a9b76 100644
+--- a/arch/x86/kernel/vmlinux.lds.S
++++ b/arch/x86/kernel/vmlinux.lds.S
+@@ -169,9 +169,6 @@ SECTIONS
+ 	.vsyscall : AT(VLOAD(.vsyscall)) {
+ 		*(.vsyscall_0)
+ 
+-		. = ALIGN(L1_CACHE_BYTES);
+-		*(.vsyscall_fn)
+-
+ 		. = 1024;
+ 		*(.vsyscall_1)
+ 
+diff --git a/arch/x86/kernel/vread_tsc_64.c b/arch/x86/kernel/vread_tsc_64.c
+deleted file mode 100644
+index a81aa9e9894c..000000000000
+--- a/arch/x86/kernel/vread_tsc_64.c
++++ /dev/null
+@@ -1,36 +0,0 @@
+-/* This code runs in userspace. */
+-
+-#define DISABLE_BRANCH_PROFILING
+-#include 
+-
+-notrace cycle_t __vsyscall_fn vread_tsc(void)
+-{
+-	cycle_t ret;
+-	u64 last;
+-
+-	/*
+-	 * Empirically, a fence (of type that depends on the CPU)
+-	 * before rdtsc is enough to ensure that rdtsc is ordered
+-	 * with respect to loads.  The various CPU manuals are unclear
+-	 * as to whether rdtsc can be reordered with later loads,
+-	 * but no one has ever seen it happen.
+-	 */
+-	rdtsc_barrier();
+-	ret = (cycle_t)vget_cycles();
+-
+-	last = VVAR(vsyscall_gtod_data).clock.cycle_last;
+-
+-	if (likely(ret >= last))
+-		return ret;
+-
+-	/*
+-	 * GCC likes to generate cmov here, but this branch is extremely
+-	 * predictable (it's just a funciton of time and the likely is
+-	 * very likely) and there's a data dependence, so force GCC
+-	 * to generate a branch instead.  I don't barrier() because
+-	 * we don't actually need a barrier, and if this function
+-	 * ever gets inlined it will generate worse code.
+-	 */
+-	asm volatile ("");
+-	return last;
+-}
+diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
+index 12d488fd95d9..dda7dff9cef7 100644
+--- a/arch/x86/kernel/vsyscall_64.c
++++ b/arch/x86/kernel/vsyscall_64.c
+@@ -74,7 +74,7 @@ void update_vsyscall(struct timespec *wall_time, struct timespec *wtm,
+ 	write_seqlock_irqsave(&vsyscall_gtod_data.lock, flags);
+ 
+ 	/* copy vsyscall data */
+-	vsyscall_gtod_data.clock.vread		= clock->archdata.vread;
++	vsyscall_gtod_data.clock.vclock_mode	= clock->archdata.vclock_mode;
+ 	vsyscall_gtod_data.clock.cycle_last	= clock->cycle_last;
+ 	vsyscall_gtod_data.clock.mask		= clock->mask;
+ 	vsyscall_gtod_data.clock.mult		= mult;
+diff --git a/arch/x86/vdso/vclock_gettime.c b/arch/x86/vdso/vclock_gettime.c
+index cf54813ac527..8792d6e0a2c3 100644
+--- a/arch/x86/vdso/vclock_gettime.c
++++ b/arch/x86/vdso/vclock_gettime.c
+@@ -17,6 +17,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -25,6 +26,43 @@
+ 
+ #define gtod (&VVAR(vsyscall_gtod_data))
+ 
++notrace static cycle_t vread_tsc(void)
++{
++	cycle_t ret;
++	u64 last;
++
++	/*
++	 * Empirically, a fence (of type that depends on the CPU)
++	 * before rdtsc is enough to ensure that rdtsc is ordered
++	 * with respect to loads.  The various CPU manuals are unclear
++	 * as to whether rdtsc can be reordered with later loads,
++	 * but no one has ever seen it happen.
++	 */
++	rdtsc_barrier();
++	ret = (cycle_t)vget_cycles();
++
++	last = VVAR(vsyscall_gtod_data).clock.cycle_last;
++
++	if (likely(ret >= last))
++		return ret;
++
++	/*
++	 * GCC likes to generate cmov here, but this branch is extremely
++	 * predictable (it's just a funciton of time and the likely is
++	 * very likely) and there's a data dependence, so force GCC
++	 * to generate a branch instead.  I don't barrier() because
++	 * we don't actually need a barrier, and if this function
++	 * ever gets inlined it will generate worse code.
++	 */
++	asm volatile ("");
++	return last;
++}
++
++static notrace cycle_t vread_hpet(void)
++{
++	return readl((const void __iomem *)fix_to_virt(VSYSCALL_HPET) + 0xf0);
++}
++
+ notrace static long vdso_fallback_gettime(long clock, struct timespec *ts)
+ {
+ 	long ret;
+@@ -36,9 +74,12 @@ notrace static long vdso_fallback_gettime(long clock, struct timespec *ts)
+ notrace static inline long vgetns(void)
+ {
+ 	long v;
+-	cycles_t (*vread)(void);
+-	vread = gtod->clock.vread;
+-	v = (vread() - gtod->clock.cycle_last) & gtod->clock.mask;
++	cycles_t cycles;
++	if (gtod->clock.vclock_mode == VCLOCK_TSC)
++		cycles = vread_tsc();
++	else
++		cycles = vread_hpet();
++	v = (cycles - gtod->clock.cycle_last) & gtod->clock.mask;
+ 	return (v * gtod->clock.mult) >> gtod->clock.shift;
+ }
+ 
+@@ -118,11 +159,11 @@ notrace int __vdso_clock_gettime(clockid_t clock, struct timespec *ts)
+ {
+ 	switch (clock) {
+ 	case CLOCK_REALTIME:
+-		if (likely(gtod->clock.vread))
++		if (likely(gtod->clock.vclock_mode != VCLOCK_NONE))
+ 			return do_realtime(ts);
+ 		break;
+ 	case CLOCK_MONOTONIC:
+-		if (likely(gtod->clock.vread))
++		if (likely(gtod->clock.vclock_mode != VCLOCK_NONE))
+ 			return do_monotonic(ts);
+ 		break;
+ 	case CLOCK_REALTIME_COARSE:
+@@ -139,7 +180,7 @@ int clock_gettime(clockid_t, struct timespec *)
+ notrace int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
+ {
+ 	long ret;
+-	if (likely(gtod->clock.vread)) {
++	if (likely(gtod->clock.vclock_mode != VCLOCK_NONE)) {
+ 		if (likely(tv != NULL)) {
+ 			BUILD_BUG_ON(offsetof(struct timeval, tv_usec) !=
+ 				     offsetof(struct timespec, tv_nsec) ||

commit 433bd805e5fd2c731b3a9025b034f066272d336e
+Author: Andy Lutomirski 
+Date:   Wed Jul 13 09:24:13 2011 -0400
+
+    clocksource: Replace vread with generic arch data
+    
+    The vread field was bloating struct clocksource everywhere except
+    x86_64, and I want to change the way this works on x86_64, so let's
+    split it out into per-arch data.
+    
+    Cc: x86@kernel.org
+    Cc: Clemens Ladisch 
+    Cc: linux-ia64@vger.kernel.org
+    Cc: Tony Luck 
+    Cc: Fenghua Yu 
+    Cc: John Stultz 
+    Cc: Thomas Gleixner 
+    Signed-off-by: Andy Lutomirski 
+    Link: http://lkml.kernel.org/r/3ae5ec76a168eaaae63f08a2a1060b91aa0b7759.1310563276.git.luto@mit.edu
+    Signed-off-by: H. Peter Anvin 
+
+diff --git a/arch/x86/include/asm/clocksource.h b/arch/x86/include/asm/clocksource.h
+new file mode 100644
+index 000000000000..a5df33f614c9
+--- /dev/null
++++ b/arch/x86/include/asm/clocksource.h
+@@ -0,0 +1,16 @@
++/* x86-specific clocksource additions */
++
++#ifndef _ASM_X86_CLOCKSOURCE_H
++#define _ASM_X86_CLOCKSOURCE_H
++
++#ifdef CONFIG_X86_64
++
++#define __ARCH_HAS_CLOCKSOURCE_DATA
++
++struct arch_clocksource_data {
++	cycle_t (*vread)(void);
++};
++
++#endif /* CONFIG_X86_64 */
++
++#endif /* _ASM_X86_CLOCKSOURCE_H */
+diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
+index e9f5605e4748..0e07257bb389 100644
+--- a/arch/x86/kernel/hpet.c
++++ b/arch/x86/kernel/hpet.c
+@@ -753,7 +753,7 @@ static struct clocksource clocksource_hpet = {
+ 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+ 	.resume		= hpet_resume_counter,
+ #ifdef CONFIG_X86_64
+-	.vread		= vread_hpet,
++	.archdata	= { .vread = vread_hpet },
+ #endif
+ };
+ 
+diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
+index 6cc6922262af..e7a74b889ab3 100644
+--- a/arch/x86/kernel/tsc.c
++++ b/arch/x86/kernel/tsc.c
+@@ -777,7 +777,7 @@ static struct clocksource clocksource_tsc = {
+ 	.flags                  = CLOCK_SOURCE_IS_CONTINUOUS |
+ 				  CLOCK_SOURCE_MUST_VERIFY,
+ #ifdef CONFIG_X86_64
+-	.vread                  = vread_tsc,
++	.archdata               = { .vread = vread_tsc },
+ #endif
+ };
+ 
+diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
+index a262400c3479..12d488fd95d9 100644
+--- a/arch/x86/kernel/vsyscall_64.c
++++ b/arch/x86/kernel/vsyscall_64.c
+@@ -74,7 +74,7 @@ void update_vsyscall(struct timespec *wall_time, struct timespec *wtm,
+ 	write_seqlock_irqsave(&vsyscall_gtod_data.lock, flags);
+ 
+ 	/* copy vsyscall data */
+-	vsyscall_gtod_data.clock.vread		= clock->vread;
++	vsyscall_gtod_data.clock.vread		= clock->archdata.vread;
+ 	vsyscall_gtod_data.clock.cycle_last	= clock->cycle_last;
+ 	vsyscall_gtod_data.clock.mask		= clock->mask;
+ 	vsyscall_gtod_data.clock.mult		= mult;
+diff --git a/include/asm-generic/clocksource.h b/include/asm-generic/clocksource.h
+new file mode 100644
+index 000000000000..0a462d3fb05e
+--- /dev/null
++++ b/include/asm-generic/clocksource.h
+@@ -0,0 +1,4 @@
++/*
++ * Architectures should override this file to add private userspace
++ * clock magic if needed.
++ */
+diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
+index d4646b48dc4a..0fb83c224471 100644
+--- a/include/linux/clocksource.h
++++ b/include/linux/clocksource.h
+@@ -22,6 +22,8 @@
+ typedef u64 cycle_t;
+ struct clocksource;
+ 
++#include 
++
+ /**
+  * struct cyclecounter - hardware abstraction for a free running counter
+  *	Provides completely state-free accessors to the underlying hardware.
+@@ -153,7 +155,7 @@ extern u64 timecounter_cyc2time(struct timecounter *tc,
+  * @shift:		cycle to nanosecond divisor (power of two)
+  * @max_idle_ns:	max idle time permitted by the clocksource (nsecs)
+  * @flags:		flags describing special properties
+- * @vread:		vsyscall based read
++ * @archdata:		arch-specific data
+  * @suspend:		suspend function for the clocksource, if necessary
+  * @resume:		resume function for the clocksource, if necessary
+  */
+@@ -175,10 +177,14 @@ struct clocksource {
+ #else
+ #define CLKSRC_FSYS_MMIO_SET(mmio, addr)      do { } while (0)
+ #endif
++
++#ifdef __ARCH_HAS_CLOCKSOURCE_DATA
++	struct arch_clocksource_data archdata;
++#endif
++
+ 	const char *name;
+ 	struct list_head list;
+ 	int rating;
+-	cycle_t (*vread)(void);
+ 	int (*enable)(struct clocksource *cs);
+ 	void (*disable)(struct clocksource *cs);
+ 	unsigned long flags;

commit 7f79ad15f33cf4968cafb0e3d2beba427de01d3a
+Author: Andy Lutomirski 
+Date:   Wed Jul 13 09:24:12 2011 -0400
+
+    x86-64: Add --no-undefined to vDSO build
+    
+    This gives much nicer diagnostics when something goes wrong.  It's
+    supported at least as far back as binutils 2.15.
+    
+    Signed-off-by: Andy Lutomirski 
+    Link: http://lkml.kernel.org/r/de0b50920469ff6359c529526e7639fdd36fa83c.1310563276.git.luto@mit.edu
+    Signed-off-by: H. Peter Anvin 
+
+diff --git a/arch/x86/vdso/Makefile b/arch/x86/vdso/Makefile
+index bef0bc962400..5d179502a52c 100644
+--- a/arch/x86/vdso/Makefile
++++ b/arch/x86/vdso/Makefile
+@@ -26,6 +26,7 @@ targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y)
+ export CPPFLAGS_vdso.lds += -P -C
+ 
+ VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
++			-Wl,--no-undefined \
+ 		      	-Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
+ 
+ $(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so

commit 1b3f2a72bbcfdf92e368a44448c45eb639b05b5e
+Author: Andy Lutomirski 
+Date:   Wed Jul 13 09:24:11 2011 -0400
+
+    x86-64: Allow alternative patching in the vDSO
+    
+    This code is short enough and different enough from the module
+    loader that it's not worth trying to share anything.
+    
+    Signed-off-by: Andy Lutomirski 
+    Link: http://lkml.kernel.org/r/e73112e4381fff29e31b882c2d0856822edaea53.1310563276.git.luto@mit.edu
+    Signed-off-by: H. Peter Anvin 
+
+diff --git a/arch/x86/vdso/vma.c b/arch/x86/vdso/vma.c
+index 7abd2be0f9b9..c39938d1332f 100644
+--- a/arch/x86/vdso/vma.c
++++ b/arch/x86/vdso/vma.c
+@@ -23,11 +23,44 @@ extern unsigned short vdso_sync_cpuid;
+ static struct page **vdso_pages;
+ static unsigned vdso_size;
+ 
++static void __init patch_vdso(void *vdso, size_t len)
++{
++	Elf64_Ehdr *hdr = vdso;
++	Elf64_Shdr *sechdrs, *alt_sec = 0;
++	char *secstrings;
++	void *alt_data;
++	int i;
++
++	BUG_ON(len < sizeof(Elf64_Ehdr));
++	BUG_ON(memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0);
++
++	sechdrs = (void *)hdr + hdr->e_shoff;
++	secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
++
++	for (i = 1; i < hdr->e_shnum; i++) {
++		Elf64_Shdr *shdr = &sechdrs[i];
++		if (!strcmp(secstrings + shdr->sh_name, ".altinstructions")) {
++			alt_sec = shdr;
++			goto found;
++		}
++	}
++
++	/* If we get here, it's probably a bug. */
++	pr_warning("patch_vdso: .altinstructions not found\n");
++	return;  /* nothing to patch */
++
++found:
++	alt_data = (void *)hdr + alt_sec->sh_offset;
++	apply_alternatives(alt_data, alt_data + alt_sec->sh_size);
++}
++
+ static int __init init_vdso_vars(void)
+ {
+ 	int npages = (vdso_end - vdso_start + PAGE_SIZE - 1) / PAGE_SIZE;
+ 	int i;
+ 
++	patch_vdso(vdso_start, vdso_end - vdso_start);
++
+ 	vdso_size = npages << PAGE_SHIFT;
+ 	vdso_pages = kmalloc(sizeof(struct page *) * npages, GFP_KERNEL);
+ 	if (!vdso_pages)

commit 59e97e4d6fbcd5b74a94cb48bcbfc6f8478a5e93
+Author: Andy Lutomirski 
+Date:   Wed Jul 13 09:24:10 2011 -0400
+
+    x86: Make alternative instruction pointers relative
+    
+    This save a few bytes on x86-64 and means that future patches can
+    apply alternatives to unrelocated code.
+    
+    Signed-off-by: Andy Lutomirski 
+    Link: http://lkml.kernel.org/r/ff64a6b9a1a3860ca4a7b8b6dc7b4754f9491cd7.1310563276.git.luto@mit.edu
+    Signed-off-by: H. Peter Anvin 
+
+diff --git a/arch/x86/include/asm/alternative-asm.h b/arch/x86/include/asm/alternative-asm.h
+index 94d420b360d1..4554cc6fb96a 100644
+--- a/arch/x86/include/asm/alternative-asm.h
++++ b/arch/x86/include/asm/alternative-asm.h
+@@ -17,8 +17,8 @@
+ 
+ .macro altinstruction_entry orig alt feature orig_len alt_len
+ 	.align 8
+-	.quad \orig
+-	.quad \alt
++	.long \orig - .
++	.long \alt - .
+ 	.word \feature
+ 	.byte \orig_len
+ 	.byte \alt_len
+diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h
+index bf535f947e8c..23fb6d79f209 100644
+--- a/arch/x86/include/asm/alternative.h
++++ b/arch/x86/include/asm/alternative.h
+@@ -43,8 +43,8 @@
+ #endif
+ 
+ struct alt_instr {
+-	u8 *instr;		/* original instruction */
+-	u8 *replacement;
++	s32 instr_offset;	/* original instruction */
++	s32 repl_offset;	/* offset to replacement instruction */
+ 	u16 cpuid;		/* cpuid bit set for replacement */
+ 	u8  instrlen;		/* length of original instruction */
+ 	u8  replacementlen;	/* length of new instruction, <= instrlen */
+@@ -84,8 +84,8 @@ static inline int alternatives_text_reserved(void *start, void *end)
+       "661:\n\t" oldinstr "\n662:\n"					\
+       ".section .altinstructions,\"a\"\n"				\
+       _ASM_ALIGN "\n"							\
+-      _ASM_PTR "661b\n"				/* label           */	\
+-      _ASM_PTR "663f\n"				/* new instruction */	\
++      "	 .long 661b - .\n"			/* label           */	\
++      "	 .long 663f - .\n"			/* new instruction */	\
+       "	 .word " __stringify(feature) "\n"	/* feature bit     */	\
+       "	 .byte 662b-661b\n"			/* sourcelen       */	\
+       "	 .byte 664f-663f\n"			/* replacementlen  */	\
+diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
+index 71cc3800712c..9929b35929ff 100644
+--- a/arch/x86/include/asm/cpufeature.h
++++ b/arch/x86/include/asm/cpufeature.h
+@@ -331,8 +331,8 @@ static __always_inline __pure bool __static_cpu_has(u16 bit)
+ 			 "2:\n"
+ 			 ".section .altinstructions,\"a\"\n"
+ 			 _ASM_ALIGN "\n"
+-			 _ASM_PTR "1b\n"
+-			 _ASM_PTR "0\n" 	/* no replacement */
++			 " .long 1b - .\n"
++			 " .long 0\n"		/* no replacement */
+ 			 " .word %P0\n"		/* feature bit */
+ 			 " .byte 2b - 1b\n"	/* source len */
+ 			 " .byte 0\n"		/* replacement len */
+@@ -349,8 +349,8 @@ static __always_inline __pure bool __static_cpu_has(u16 bit)
+ 			     "2:\n"
+ 			     ".section .altinstructions,\"a\"\n"
+ 			     _ASM_ALIGN "\n"
+-			     _ASM_PTR "1b\n"
+-			     _ASM_PTR "3f\n"
++			     " .long 1b - .\n"
++			     " .long 3f - .\n"
+ 			     " .word %P1\n"		/* feature bit */
+ 			     " .byte 2b - 1b\n"		/* source len */
+ 			     " .byte 4f - 3f\n"		/* replacement len */
+diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
+index a81f2d52f869..ddb207bb5f91 100644
+--- a/arch/x86/kernel/alternative.c
++++ b/arch/x86/kernel/alternative.c
+@@ -263,6 +263,7 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
+ 					 struct alt_instr *end)
+ {
+ 	struct alt_instr *a;
++	u8 *instr, *replacement;
+ 	u8 insnbuf[MAX_PATCH_LEN];
+ 
+ 	DPRINTK("%s: alt table %p -> %p\n", __func__, start, end);
+@@ -276,25 +277,29 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
+ 	 * order.
+ 	 */
+ 	for (a = start; a < end; a++) {
+-		u8 *instr = a->instr;
++		instr = (u8 *)&a->instr_offset + a->instr_offset;
++		replacement = (u8 *)&a->repl_offset + a->repl_offset;
+ 		BUG_ON(a->replacementlen > a->instrlen);
+ 		BUG_ON(a->instrlen > sizeof(insnbuf));
+ 		BUG_ON(a->cpuid >= NCAPINTS*32);
+ 		if (!boot_cpu_has(a->cpuid))
+ 			continue;
++
++		memcpy(insnbuf, replacement, a->replacementlen);
++
++		/* 0xe8 is a relative jump; fix the offset. */
++		if (*insnbuf == 0xe8 && a->replacementlen == 5)
++		    *(s32 *)(insnbuf + 1) += replacement - instr;
++
++		add_nops(insnbuf + a->replacementlen,
++			 a->instrlen - a->replacementlen);
++
+ #ifdef CONFIG_X86_64
+ 		/* vsyscall code is not mapped yet. resolve it manually. */
+ 		if (instr >= (u8 *)VSYSCALL_START && instr < (u8*)VSYSCALL_END) {
+ 			instr = __va(instr - (u8*)VSYSCALL_START + (u8*)__pa_symbol(&__vsyscall_0));
+-			DPRINTK("%s: vsyscall fixup: %p => %p\n",
+-				__func__, a->instr, instr);
+ 		}
+ #endif
+-		memcpy(insnbuf, a->replacement, a->replacementlen);
+-		if (*insnbuf == 0xe8 && a->replacementlen == 5)
+-		    *(s32 *)(insnbuf + 1) += a->replacement - a->instr;
+-		add_nops(insnbuf + a->replacementlen,
+-			 a->instrlen - a->replacementlen);
+ 		text_poke_early(instr, insnbuf, a->instrlen);
+ 	}
+ }
+diff --git a/arch/x86/lib/copy_page_64.S b/arch/x86/lib/copy_page_64.S
+index 6fec2d1cebe1..01c805ba5359 100644
+--- a/arch/x86/lib/copy_page_64.S
++++ b/arch/x86/lib/copy_page_64.S
+@@ -2,6 +2,7 @@
+ 
+ #include 
+ #include 
++#include 
+ 
+ 	ALIGN
+ copy_page_c:
+@@ -110,10 +111,6 @@ ENDPROC(copy_page)
+ 2:
+ 	.previous
+ 	.section .altinstructions,"a"
+-	.align 8
+-	.quad copy_page
+-	.quad 1b
+-	.word X86_FEATURE_REP_GOOD
+-	.byte .Lcopy_page_end - copy_page
+-	.byte 2b - 1b
++	altinstruction_entry copy_page, 1b, X86_FEATURE_REP_GOOD,	\
++		.Lcopy_page_end-copy_page, 2b-1b
+ 	.previous
+diff --git a/arch/x86/lib/memmove_64.S b/arch/x86/lib/memmove_64.S
+index d0ec9c2936d7..ee164610ec46 100644
+--- a/arch/x86/lib/memmove_64.S
++++ b/arch/x86/lib/memmove_64.S
+@@ -9,6 +9,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #undef memmove
+ 
+@@ -214,11 +215,9 @@ ENTRY(memmove)
+ 	.previous
+ 
+ 	.section .altinstructions,"a"
+-	.align 8
+-	.quad .Lmemmove_begin_forward
+-	.quad .Lmemmove_begin_forward_efs
+-	.word X86_FEATURE_ERMS
+-	.byte .Lmemmove_end_forward-.Lmemmove_begin_forward
+-	.byte .Lmemmove_end_forward_efs-.Lmemmove_begin_forward_efs
++	altinstruction_entry .Lmemmove_begin_forward,		\
++		.Lmemmove_begin_forward_efs,X86_FEATURE_ERMS,	\
++		.Lmemmove_end_forward-.Lmemmove_begin_forward,	\
++		.Lmemmove_end_forward_efs-.Lmemmove_begin_forward_efs
+ 	.previous
+ ENDPROC(memmove)

commit c9712944b2a12373cb6ff8059afcfb7e826a6c54
+Author: Andy Lutomirski 
+Date:   Wed Jul 13 09:24:09 2011 -0400
+
+    x86-64: Improve vsyscall emulation CS and RIP handling
+    
+    Three fixes here:
+     - Send SIGSEGV if called from compat code or with a funny CS.
+     - Don't BUG on impossible addresses.
+     - Add a missing local_irq_disable.
+    
+    This patch also removes an unused variable.
+    
+    Signed-off-by: Andy Lutomirski 
+    Link: http://lkml.kernel.org/r/6fb2b13ab39b743d1e4f466eef13425854912f7f.1310563276.git.luto@mit.edu
+    Signed-off-by: H. Peter Anvin 
+
+diff --git a/arch/x86/include/asm/vsyscall.h b/arch/x86/include/asm/vsyscall.h
+index bb710cb0cdc1..d55597351f6a 100644
+--- a/arch/x86/include/asm/vsyscall.h
++++ b/arch/x86/include/asm/vsyscall.h
+@@ -31,18 +31,6 @@ extern struct timezone sys_tz;
+ 
+ extern void map_vsyscall(void);
+ 
+-/* Emulation */
+-
+-static inline bool is_vsyscall_entry(unsigned long addr)
+-{
+-	return (addr & ~0xC00UL) == VSYSCALL_START;
+-}
+-
+-static inline int vsyscall_entry_nr(unsigned long addr)
+-{
+-	return (addr & 0xC00UL) >> 10;
+-}
+-
+ #endif /* __KERNEL__ */
+ 
+ #endif /* _ASM_X86_VSYSCALL_H */
+diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
+index 10cd8ac3395a..a262400c3479 100644
+--- a/arch/x86/kernel/vsyscall_64.c
++++ b/arch/x86/kernel/vsyscall_64.c
+@@ -38,6 +38,7 @@
+ 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -97,33 +98,63 @@ static void warn_bad_vsyscall(const char *level, struct pt_regs *regs,
+ 
+ 	tsk = current;
+ 
+-	printk("%s%s[%d] %s ip:%lx sp:%lx ax:%lx si:%lx di:%lx\n",
++	printk("%s%s[%d] %s ip:%lx cs:%lx sp:%lx ax:%lx si:%lx di:%lx\n",
+ 	       level, tsk->comm, task_pid_nr(tsk),
+-	       message, regs->ip - 2, regs->sp, regs->ax, regs->si, regs->di);
++	       message, regs->ip - 2, regs->cs,
++	       regs->sp, regs->ax, regs->si, regs->di);
++}
++
++static int addr_to_vsyscall_nr(unsigned long addr)
++{
++	int nr;
++
++	if ((addr & ~0xC00UL) != VSYSCALL_START)
++		return -EINVAL;
++
++	nr = (addr & 0xC00UL) >> 10;
++	if (nr >= 3)
++		return -EINVAL;
++
++	return nr;
+ }
+ 
+ void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)
+ {
+-	const char *vsyscall_name;
+ 	struct task_struct *tsk;
+ 	unsigned long caller;
+ 	int vsyscall_nr;
+ 	long ret;
+ 
+-	/* Kernel code must never get here. */
+-	BUG_ON(!user_mode(regs));
+-
+ 	local_irq_enable();
+ 
++	/*
++	 * Real 64-bit user mode code has cs == __USER_CS.  Anything else
++	 * is bogus.
++	 */
++	if (regs->cs != __USER_CS) {
++		/*
++		 * If we trapped from kernel mode, we might as well OOPS now
++		 * instead of returning to some random address and OOPSing
++		 * then.
++		 */
++		BUG_ON(!user_mode(regs));
++
++		/* Compat mode and non-compat 32-bit CS should both segfault. */
++		warn_bad_vsyscall(KERN_WARNING, regs,
++				  "illegal int 0xcc from 32-bit mode");
++		goto sigsegv;
++	}
++
+ 	/*
+ 	 * x86-ism here: regs->ip points to the instruction after the int 0xcc,
+ 	 * and int 0xcc is two bytes long.
+ 	 */
+-	if (!is_vsyscall_entry(regs->ip - 2)) {
+-		warn_bad_vsyscall(KERN_WARNING, regs, "illegal int 0xcc (exploit attempt?)");
++	vsyscall_nr = addr_to_vsyscall_nr(regs->ip - 2);
++	if (vsyscall_nr < 0) {
++		warn_bad_vsyscall(KERN_WARNING, regs,
++				  "illegal int 0xcc (exploit attempt?)");
+ 		goto sigsegv;
+ 	}
+-	vsyscall_nr = vsyscall_entry_nr(regs->ip - 2);
+ 
+ 	if (get_user(caller, (unsigned long __user *)regs->sp) != 0) {
+ 		warn_bad_vsyscall(KERN_WARNING, regs, "int 0xcc with bad stack (exploit attempt?)");
+@@ -136,31 +167,20 @@ void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)
+ 
+ 	switch (vsyscall_nr) {
+ 	case 0:
+-		vsyscall_name = "gettimeofday";
+ 		ret = sys_gettimeofday(
+ 			(struct timeval __user *)regs->di,
+ 			(struct timezone __user *)regs->si);
+ 		break;
+ 
+ 	case 1:
+-		vsyscall_name = "time";
+ 		ret = sys_time((time_t __user *)regs->di);
+ 		break;
+ 
+ 	case 2:
+-		vsyscall_name = "getcpu";
+ 		ret = sys_getcpu((unsigned __user *)regs->di,
+ 				 (unsigned __user *)regs->si,
+ 				 0);
+ 		break;
+-
+-	default:
+-		/*
+-		 * If we get here, then vsyscall_nr indicates that int 0xcc
+-		 * happened at an address in the vsyscall page that doesn't
+-		 * contain int 0xcc.  That can't happen.
+-		 */
+-		BUG();
+ 	}
+ 
+ 	if (ret == -EFAULT) {
+@@ -188,6 +208,7 @@ void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)
+ sigsegv:
+ 	regs->ip -= 2;  /* The faulting instruction should be the int 0xcc. */
+ 	force_sig(SIGSEGV, current);
++	local_irq_disable();
+ }
+ 
+ /*

commit 12706394bcaa48e3d5e19c97d7b4e5683ebb12fb
+Author: Theodore Ts'o 
+Date:   Sun Jul 10 22:37:50 2011 -0400
+
+    ext4: add tracepoint for ext4_journal_start
+    
+    This will help debug who is responsible for starting a jbd2 transaction.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 9ea71aa864b3..7910e61809e7 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -269,6 +269,7 @@ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks)
+ 	journal_t *journal;
+ 	handle_t  *handle;
+ 
++	trace_ext4_journal_start(sb, nblocks, _RET_IP_);
+ 	if (sb->s_flags & MS_RDONLY)
+ 		return ERR_PTR(-EROFS);
+ 
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index 5ce2b2f5f524..6f27a59fc90d 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -1520,6 +1520,28 @@ TRACE_EVENT(ext4_load_inode,
+ 		  (unsigned long) __entry->ino)
+ );
+ 
++TRACE_EVENT(ext4_journal_start,
++	TP_PROTO(struct super_block *sb, int nblocks, unsigned long IP),
++
++	TP_ARGS(sb, nblocks, IP),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	  int, 	nblocks			)
++		__field(unsigned long,	ip			)
++	),
++
++	TP_fast_assign(
++		__entry->dev	 = sb->s_dev;
++		__entry->nblocks = nblocks;
++		__entry->ip	 = IP;
++	),
++
++	TP_printk("dev %d,%d nblocks %d caller %pF",
++		  MAJOR(__entry->dev), MINOR(__entry->dev),
++		  __entry->nblocks, (void *)__entry->ip)
++);
++
+ #endif /* _TRACE_EXT4_H */
+ 
+ /* This part must be outside protection */

commit 4862fd6047ed02e2726667c54d35f538eecc56aa
+Author: Theodore Ts'o 
+Date:   Sun Jul 10 22:05:08 2011 -0400
+
+    jbd2: remove jbd2_dev_to_name() from jbd2 tracepoints
+    
+    Using function calls in TP_printk causes perf heartburn, so print the
+    MAJOR/MINOR device numbers instead.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 0dfa5b598e68..f24df13adc4e 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -2390,73 +2390,6 @@ static void __exit journal_exit(void)
+ 	jbd2_journal_destroy_caches();
+ }
+ 
+-/* 
+- * jbd2_dev_to_name is a utility function used by the jbd2 and ext4 
+- * tracing infrastructure to map a dev_t to a device name.
+- *
+- * The caller should use rcu_read_lock() in order to make sure the
+- * device name stays valid until its done with it.  We use
+- * rcu_read_lock() as well to make sure we're safe in case the caller
+- * gets sloppy, and because rcu_read_lock() is cheap and can be safely
+- * nested.
+- */
+-struct devname_cache {
+-	struct rcu_head	rcu;
+-	dev_t		device;
+-	char		devname[BDEVNAME_SIZE];
+-};
+-#define CACHE_SIZE_BITS 6
+-static struct devname_cache *devcache[1 << CACHE_SIZE_BITS];
+-static DEFINE_SPINLOCK(devname_cache_lock);
+-
+-static void free_devcache(struct rcu_head *rcu)
+-{
+-	kfree(rcu);
+-}
+-
+-const char *jbd2_dev_to_name(dev_t device)
+-{
+-	int	i = hash_32(device, CACHE_SIZE_BITS);
+-	char	*ret;
+-	struct block_device *bd;
+-	static struct devname_cache *new_dev;
+-
+-	rcu_read_lock();
+-	if (devcache[i] && devcache[i]->device == device) {
+-		ret = devcache[i]->devname;
+-		rcu_read_unlock();
+-		return ret;
+-	}
+-	rcu_read_unlock();
+-
+-	new_dev = kmalloc(sizeof(struct devname_cache), GFP_KERNEL);
+-	if (!new_dev)
+-		return "NODEV-ALLOCFAILURE"; /* Something non-NULL */
+-	bd = bdget(device);
+-	spin_lock(&devname_cache_lock);
+-	if (devcache[i]) {
+-		if (devcache[i]->device == device) {
+-			kfree(new_dev);
+-			bdput(bd);
+-			ret = devcache[i]->devname;
+-			spin_unlock(&devname_cache_lock);
+-			return ret;
+-		}
+-		call_rcu(&devcache[i]->rcu, free_devcache);
+-	}
+-	devcache[i] = new_dev;
+-	devcache[i]->device = device;
+-	if (bd) {
+-		bdevname(bd, devcache[i]->devname);
+-		bdput(bd);
+-	} else
+-		__bdevname(device, devcache[i]->devname);
+-	ret = devcache[i]->devname;
+-	spin_unlock(&devname_cache_lock);
+-	return ret;
+-}
+-EXPORT_SYMBOL(jbd2_dev_to_name);
+-
+ MODULE_LICENSE("GPL");
+ module_init(journal_init);
+ module_exit(journal_exit);
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index d087c2e7b2aa..38f307b8c334 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -1329,12 +1329,6 @@ extern int jbd_blocks_per_page(struct inode *inode);
+ #define BUFFER_TRACE2(bh, bh2, info)	do {} while (0)
+ #define JBUFFER_TRACE(jh, info)	do {} while (0)
+ 
+-/* 
+- * jbd2_dev_to_name is a utility function used by the jbd2 and ext4 
+- * tracing infrastructure to map a dev_t to a device name.
+- */
+-extern const char *jbd2_dev_to_name(dev_t device);
+-
+ #endif	/* __KERNEL__ */
+ 
+ #endif	/* _LINUX_JBD2_H */
+diff --git a/include/trace/events/jbd2.h b/include/trace/events/jbd2.h
+index bf16545cc977..75964412ddbb 100644
+--- a/include/trace/events/jbd2.h
++++ b/include/trace/events/jbd2.h
+@@ -26,8 +26,8 @@ TRACE_EVENT(jbd2_checkpoint,
+ 		__entry->result		= result;
+ 	),
+ 
+-	TP_printk("dev %s result %d",
+-		  jbd2_dev_to_name(__entry->dev), __entry->result)
++	TP_printk("dev %d,%d result %d",
++		  MAJOR(__entry->dev), MINOR(__entry->dev), __entry->result)
+ );
+ 
+ DECLARE_EVENT_CLASS(jbd2_commit,
+@@ -48,9 +48,9 @@ DECLARE_EVENT_CLASS(jbd2_commit,
+ 		__entry->transaction	= commit_transaction->t_tid;
+ 	),
+ 
+-	TP_printk("dev %s transaction %d sync %d",
+-		  jbd2_dev_to_name(__entry->dev), __entry->transaction,
+-		  __entry->sync_commit)
++	TP_printk("dev %d,%d transaction %d sync %d",
++		  MAJOR(__entry->dev), MINOR(__entry->dev),
++		  __entry->transaction, __entry->sync_commit)
+ );
+ 
+ DEFINE_EVENT(jbd2_commit, jbd2_start_commit,
+@@ -100,9 +100,9 @@ TRACE_EVENT(jbd2_end_commit,
+ 		__entry->head		= journal->j_tail_sequence;
+ 	),
+ 
+-	TP_printk("dev %s transaction %d sync %d head %d",
+-		  jbd2_dev_to_name(__entry->dev), __entry->transaction,
+-		  __entry->sync_commit, __entry->head)
++	TP_printk("dev %d,%d transaction %d sync %d head %d",
++		  MAJOR(__entry->dev), MINOR(__entry->dev),
++		  __entry->transaction, __entry->sync_commit, __entry->head)
+ );
+ 
+ TRACE_EVENT(jbd2_submit_inode_data,
+@@ -120,8 +120,9 @@ TRACE_EVENT(jbd2_submit_inode_data,
+ 		__entry->ino	= inode->i_ino;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu",
+-		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino)
++	TP_printk("dev %d,%d ino %lu",
++		  MAJOR(__entry->dev), MINOR(__entry->dev),
++		  (unsigned long) __entry->ino)
+ );
+ 
+ TRACE_EVENT(jbd2_run_stats,
+@@ -156,9 +157,9 @@ TRACE_EVENT(jbd2_run_stats,
+ 		__entry->blocks_logged	= stats->rs_blocks_logged;
+ 	),
+ 
+-	TP_printk("dev %s tid %lu wait %u running %u locked %u flushing %u "
++	TP_printk("dev %d,%d tid %lu wait %u running %u locked %u flushing %u "
+ 		  "logging %u handle_count %u blocks %u blocks_logged %u",
+-		  jbd2_dev_to_name(__entry->dev), __entry->tid,
++		  MAJOR(__entry->dev), MINOR(__entry->dev), __entry->tid,
+ 		  jiffies_to_msecs(__entry->wait),
+ 		  jiffies_to_msecs(__entry->running),
+ 		  jiffies_to_msecs(__entry->locked),
+@@ -192,9 +193,9 @@ TRACE_EVENT(jbd2_checkpoint_stats,
+ 		__entry->dropped	= stats->cs_dropped;
+ 	),
+ 
+-	TP_printk("dev %s tid %lu chp_time %u forced_to_close %u "
++	TP_printk("dev %d,%d tid %lu chp_time %u forced_to_close %u "
+ 		  "written %u dropped %u",
+-		  jbd2_dev_to_name(__entry->dev), __entry->tid,
++		  MAJOR(__entry->dev), MINOR(__entry->dev), __entry->tid,
+ 		  jiffies_to_msecs(__entry->chp_time),
+ 		  __entry->forced_to_close, __entry->written, __entry->dropped)
+ );
+@@ -222,9 +223,10 @@ TRACE_EVENT(jbd2_cleanup_journal_tail,
+ 		__entry->freed		= freed;
+ 	),
+ 
+-	TP_printk("dev %s from %u to %u offset %lu freed %lu",
+-		  jbd2_dev_to_name(__entry->dev), __entry->tail_sequence,
+-		  __entry->first_tid, __entry->block_nr, __entry->freed)
++	TP_printk("dev %d,%d from %u to %u offset %lu freed %lu",
++		  MAJOR(__entry->dev), MINOR(__entry->dev),
++		  __entry->tail_sequence, __entry->first_tid,
++		  __entry->block_nr, __entry->freed)
+ );
+ 
+ #endif /* _TRACE_JBD2_H */

commit 275d3ba6b40d0f098693b9089c6fee9bd4e55d74
+Author: Theodore Ts'o 
+Date:   Wed Jun 29 21:44:45 2011 -0400
+
+    ext4: remove loop around bio_alloc()
+    
+    These days, bio_alloc() is guaranteed to never fail (as long as nvecs
+    is less than BIO_MAX_PAGES), so we don't need the loop around the
+    struct bio allocation.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
+index 7bb8f76d470a..430c401d0895 100644
+--- a/fs/ext4/page-io.c
++++ b/fs/ext4/page-io.c
+@@ -285,11 +285,7 @@ static int io_submit_init(struct ext4_io_submit *io,
+ 	io_end = ext4_init_io_end(inode, GFP_NOFS);
+ 	if (!io_end)
+ 		return -ENOMEM;
+-	do {
+-		bio = bio_alloc(GFP_NOIO, nvecs);
+-		nvecs >>= 1;
+-	} while (bio == NULL);
+-
++	bio = bio_alloc(GFP_NOIO, min(nvecs, BIO_MAX_PAGES));
+ 	bio->bi_sector = bh->b_blocknr * (bh->b_size >> 9);
+ 	bio->bi_bdev = bh->b_bdev;
+ 	bio->bi_private = io->io_end = io_end;

commit 9f125d641beb898f5bf2fe69583192c18043517a
+Author: Theodore Ts'o 
+Date:   Mon Jun 27 19:16:04 2011 -0400
+
+    ext4: move common truncate functions to header file
+    
+    Move two functions that will be needed by the indirect functions to be
+    moved to indirect.c as well as inode.c to truncate.h as inline
+    functions, so that we can avoid having duplicate copies of the
+    function (which can be a maintenance problem) without having to expose
+    them as globally functions.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 3dca5264ccff..9b82ac7b0f55 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -47,6 +47,7 @@
+ #include "xattr.h"
+ #include "acl.h"
+ #include "ext4_extents.h"
++#include "truncate.h"
+ 
+ #include 
+ 
+@@ -88,33 +89,6 @@ static int ext4_inode_is_fast_symlink(struct inode *inode)
+ 	return (S_ISLNK(inode->i_mode) && inode->i_blocks - ea_blocks == 0);
+ }
+ 
+-/*
+- * Work out how many blocks we need to proceed with the next chunk of a
+- * truncate transaction.
+- */
+-static unsigned long blocks_for_truncate(struct inode *inode)
+-{
+-	ext4_lblk_t needed;
+-
+-	needed = inode->i_blocks >> (inode->i_sb->s_blocksize_bits - 9);
+-
+-	/* Give ourselves just enough room to cope with inodes in which
+-	 * i_blocks is corrupt: we've seen disk corruptions in the past
+-	 * which resulted in random data in an inode which looked enough
+-	 * like a regular file for ext4 to try to delete it.  Things
+-	 * will go a bit crazy if that happens, but at least we should
+-	 * try not to panic the whole kernel. */
+-	if (needed < 2)
+-		needed = 2;
+-
+-	/* But we need to bound the transaction so we don't overflow the
+-	 * journal. */
+-	if (needed > EXT4_MAX_TRANS_DATA)
+-		needed = EXT4_MAX_TRANS_DATA;
+-
+-	return EXT4_DATA_TRANS_BLOCKS(inode->i_sb) + needed;
+-}
+-
+ /*
+  * Truncate transactions can be complex and absolutely huge.  So we need to
+  * be able to restart the transaction at a conventient checkpoint to make
+@@ -129,7 +103,7 @@ static handle_t *start_transaction(struct inode *inode)
+ {
+ 	handle_t *result;
+ 
+-	result = ext4_journal_start(inode, blocks_for_truncate(inode));
++	result = ext4_journal_start(inode, ext4_blocks_for_truncate(inode));
+ 	if (!IS_ERR(result))
+ 		return result;
+ 
+@@ -149,7 +123,7 @@ static int try_to_extend_transaction(handle_t *handle, struct inode *inode)
+ 		return 0;
+ 	if (ext4_handle_has_enough_credits(handle, EXT4_RESERVE_TRANS_BLOCKS+1))
+ 		return 0;
+-	if (!ext4_journal_extend(handle, blocks_for_truncate(inode)))
++	if (!ext4_journal_extend(handle, ext4_blocks_for_truncate(inode)))
+ 		return 0;
+ 	return 1;
+ }
+@@ -204,7 +178,7 @@ void ext4_evict_inode(struct inode *inode)
+ 	if (is_bad_inode(inode))
+ 		goto no_delete;
+ 
+-	handle = ext4_journal_start(inode, blocks_for_truncate(inode)+3);
++	handle = ext4_journal_start(inode, ext4_blocks_for_truncate(inode)+3);
+ 	if (IS_ERR(handle)) {
+ 		ext4_std_error(inode->i_sb, PTR_ERR(handle));
+ 		/*
+@@ -1555,16 +1529,6 @@ static int do_journal_get_write_access(handle_t *handle,
+ 	return ret;
+ }
+ 
+-/*
+- * Truncate blocks that were not used by write. We have to truncate the
+- * pagecache as well so that corresponding buffers get properly unmapped.
+- */
+-static void ext4_truncate_failed_write(struct inode *inode)
+-{
+-	truncate_inode_pages(inode->i_mapping, inode->i_size);
+-	ext4_truncate(inode);
+-}
+-
+ static int ext4_get_block_write(struct inode *inode, sector_t iblock,
+ 		   struct buffer_head *bh_result, int create);
+ static int ext4_write_begin(struct file *file, struct address_space *mapping,
+@@ -4134,7 +4098,7 @@ static int ext4_clear_blocks(handle_t *handle, struct inode *inode,
+ 		if (unlikely(err))
+ 			goto out_err;
+ 		err = ext4_truncate_restart_trans(handle, inode,
+-						  blocks_for_truncate(inode));
++					ext4_blocks_for_truncate(inode));
+ 		if (unlikely(err))
+ 			goto out_err;
+ 		if (bh) {
+@@ -4329,7 +4293,7 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
+ 			if (try_to_extend_transaction(handle, inode)) {
+ 				ext4_mark_inode_dirty(handle, inode);
+ 				ext4_truncate_restart_trans(handle, inode,
+-					    blocks_for_truncate(inode));
++					    ext4_blocks_for_truncate(inode));
+ 			}
+ 
+ 			/*
+diff --git a/fs/ext4/truncate.h b/fs/ext4/truncate.h
+new file mode 100644
+index 000000000000..011ba6670d99
+--- /dev/null
++++ b/fs/ext4/truncate.h
+@@ -0,0 +1,43 @@
++/*
++ * linux/fs/ext4/truncate.h
++ *
++ * Common inline functions needed for truncate support
++ */
++
++/*
++ * Truncate blocks that were not used by write. We have to truncate the
++ * pagecache as well so that corresponding buffers get properly unmapped.
++ */
++static inline void ext4_truncate_failed_write(struct inode *inode)
++{
++	truncate_inode_pages(inode->i_mapping, inode->i_size);
++	ext4_truncate(inode);
++}
++
++/*
++ * Work out how many blocks we need to proceed with the next chunk of a
++ * truncate transaction.
++ */
++static inline unsigned long ext4_blocks_for_truncate(struct inode *inode)
++{
++	ext4_lblk_t needed;
++
++	needed = inode->i_blocks >> (inode->i_sb->s_blocksize_bits - 9);
++
++	/* Give ourselves just enough room to cope with inodes in which
++	 * i_blocks is corrupt: we've seen disk corruptions in the past
++	 * which resulted in random data in an inode which looked enough
++	 * like a regular file for ext4 to try to delete it.  Things
++	 * will go a bit crazy if that happens, but at least we should
++	 * try not to panic the whole kernel. */
++	if (needed < 2)
++		needed = 2;
++
++	/* But we need to bound the transaction so we don't overflow the
++	 * journal. */
++	if (needed > EXT4_MAX_TRANS_DATA)
++		needed = EXT4_MAX_TRANS_DATA;
++
++	return EXT4_DATA_TRANS_BLOCKS(inode->i_sb) + needed;
++}
++

commit 1f7d1e77419050831a905353683807fa69a26625
+Author: Theodore Ts'o 
+Date:   Mon Jun 27 19:16:02 2011 -0400
+
+    ext4: move __ext4_check_blockref to block_validity.c
+    
+    In preparation for moving the indirect functions to a separate file,
+    move __ext4_check_blockref() to block_validity.c and rename it to
+    ext4_check_blockref() which is exported as globally visible function.
+    
+    Also, rename the cpp macro ext4_check_inode_blockref() to
+    ext4_ind_check_inode(), to make it clear that it is only valid for use
+    with non-extent mapped inodes.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/block_validity.c b/fs/ext4/block_validity.c
+index fac90f3fba80..af103be491b0 100644
+--- a/fs/ext4/block_validity.c
++++ b/fs/ext4/block_validity.c
+@@ -246,3 +246,23 @@ int ext4_data_block_valid(struct ext4_sb_info *sbi, ext4_fsblk_t start_blk,
+ 	return 1;
+ }
+ 
++int ext4_check_blockref(const char *function, unsigned int line,
++			struct inode *inode, __le32 *p, unsigned int max)
++{
++	struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
++	__le32 *bref = p;
++	unsigned int blk;
++
++	while (bref < p+max) {
++		blk = le32_to_cpu(*bref++);
++		if (blk &&
++		    unlikely(!ext4_data_block_valid(EXT4_SB(inode->i_sb),
++						    blk, 1))) {
++			es->s_last_error_block = cpu_to_le64(blk);
++			ext4_error_inode(inode, function, line, blk,
++					 "invalid block");
++			return -EIO;
++		}
++	}
++	return 0;
++}
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 8532dd43d320..82ba7eb7c4a5 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2124,6 +2124,19 @@ static inline void ext4_mark_super_dirty(struct super_block *sb)
+ 		sb->s_dirt =1;
+ }
+ 
++/*
++ * Block validity checking
++ */
++#define ext4_check_indirect_blockref(inode, bh)				\
++	ext4_check_blockref(__func__, __LINE__, inode,			\
++			    (__le32 *)(bh)->b_data,			\
++			    EXT4_ADDR_PER_BLOCK((inode)->i_sb))
++
++#define ext4_ind_check_inode(inode)					\
++	ext4_check_blockref(__func__, __LINE__, inode,			\
++			    EXT4_I(inode)->i_data,			\
++			    EXT4_NDIR_BLOCKS)
++
+ /*
+  * Inodes and files operations
+  */
+@@ -2153,6 +2166,8 @@ extern void ext4_exit_system_zone(void);
+ extern int ext4_data_block_valid(struct ext4_sb_info *sbi,
+ 				 ext4_fsblk_t start_blk,
+ 				 unsigned int count);
++extern int ext4_check_blockref(const char *, unsigned int,
++			       struct inode *, __le32 *, unsigned int);
+ 
+ /* extents.c */
+ extern int ext4_ext_tree_init(handle_t *handle, struct inode *);
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 6c1d28e37235..3dca5264ccff 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -360,39 +360,6 @@ static int ext4_block_to_path(struct inode *inode,
+ 	return n;
+ }
+ 
+-static int __ext4_check_blockref(const char *function, unsigned int line,
+-				 struct inode *inode,
+-				 __le32 *p, unsigned int max)
+-{
+-	struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
+-	__le32 *bref = p;
+-	unsigned int blk;
+-
+-	while (bref < p+max) {
+-		blk = le32_to_cpu(*bref++);
+-		if (blk &&
+-		    unlikely(!ext4_data_block_valid(EXT4_SB(inode->i_sb),
+-						    blk, 1))) {
+-			es->s_last_error_block = cpu_to_le64(blk);
+-			ext4_error_inode(inode, function, line, blk,
+-					 "invalid block");
+-			return -EIO;
+-		}
+-	}
+-	return 0;
+-}
+-
+-
+-#define ext4_check_indirect_blockref(inode, bh)                         \
+-	__ext4_check_blockref(__func__, __LINE__, inode,		\
+-			      (__le32 *)(bh)->b_data,			\
+-			      EXT4_ADDR_PER_BLOCK((inode)->i_sb))
+-
+-#define ext4_check_inode_blockref(inode)                                \
+-	__ext4_check_blockref(__func__, __LINE__, inode,		\
+-			      EXT4_I(inode)->i_data,			\
+-			      EXT4_NDIR_BLOCKS)
+-
+ /**
+  *	ext4_get_branch - read the chain of indirect blocks leading to data
+  *	@inode: inode in question
+@@ -5010,7 +4977,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 		   (S_ISLNK(inode->i_mode) &&
+ 		    !ext4_inode_is_fast_symlink(inode))) {
+ 		/* Validate block references which are part of inode */
+-		ret = ext4_check_inode_blockref(inode);
++		ret = ext4_ind_check_inode(inode);
+ 	}
+ 	if (ret)
+ 		goto bad_inode;

commit e6bc45d65df8599fdbae73be9cec4ceed274db53
+Author: Theodore Ts'o 
+Date:   Mon Jun 6 19:19:40 2011 -0400
+
+    vfs: make unlink() and rmdir() return ENOENT in preference to EROFS
+    
+    If user space attempts to remove a non-existent file or directory, and
+    the file system is mounted read-only, return ENOENT instead of EROFS.
+    Either error code is arguably valid/correct, but ENOENT is a more
+    specific error message.
+    
+    Reported-by: Michael Tokarev 
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Al Viro 
+
+diff --git a/fs/namei.c b/fs/namei.c
+index e2e4e8d032ee..9802345df5e7 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -2624,6 +2624,10 @@ static long do_rmdir(int dfd, const char __user *pathname)
+ 	error = PTR_ERR(dentry);
+ 	if (IS_ERR(dentry))
+ 		goto exit2;
++	if (!dentry->d_inode) {
++		error = -ENOENT;
++		goto exit3;
++	}
+ 	error = mnt_want_write(nd.path.mnt);
+ 	if (error)
+ 		goto exit3;
+@@ -2709,11 +2713,10 @@ static long do_unlinkat(int dfd, const char __user *pathname)
+ 	error = PTR_ERR(dentry);
+ 	if (!IS_ERR(dentry)) {
+ 		/* Why not before? Because we want correct error value */
+-		if (nd.last.name[nd.last.len])
+-			goto slashes;
+ 		inode = dentry->d_inode;
+-		if (inode)
+-			ihold(inode);
++		if (nd.last.name[nd.last.len] || !inode)
++			goto slashes;
++		ihold(inode);
+ 		error = mnt_want_write(nd.path.mnt);
+ 		if (error)
+ 			goto exit2;

commit bb5fe2f78eadf5a52d8dcbf9a57728fd107af97b
+Author: Andy Lutomirski 
+Date:   Sun Jun 5 13:50:22 2011 -0400
+
+    x86-64: Remove vsyscall number 3 (venosys)
+    
+    It just segfaults since April 2008 (a4928cff), so I'm pretty
+    sure that nothing uses it.  And having an empty section makes
+    the linker script a bit fragile.
+    
+    Signed-off-by: Andy Lutomirski 
+    Cc: Jesper Juhl 
+    Cc: Borislav Petkov 
+    Cc: Linus Torvalds 
+    Cc: Arjan van de Ven 
+    Cc: Jan Beulich 
+    Cc: richard -rw- weinberger 
+    Cc: Mikael Pettersson 
+    Cc: Andi Kleen 
+    Cc: Brian Gerst 
+    Cc: Louis Rilling 
+    Cc: Valdis.Kletnieks@vt.edu
+    Cc: pageexec@freemail.hu
+    Link: http://lkml.kernel.org/r/4a4abcf47ecadc269f2391a313576fe6d06acef7.1307292171.git.luto@mit.edu
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
+index 98b378dc7f86..4f90082fd640 100644
+--- a/arch/x86/kernel/vmlinux.lds.S
++++ b/arch/x86/kernel/vmlinux.lds.S
+@@ -182,10 +182,6 @@ SECTIONS
+ 		*(.vsyscall_2)
+ 	}
+ 
+-	.vsyscall_3 ADDR(.vsyscall_0) + 3072: AT(VLOAD(.vsyscall_3)) {
+-		*(.vsyscall_3)
+-	}
+-
+ 	. = ALIGN(__vsyscall_0 + PAGE_SIZE, PAGE_SIZE);
+ 
+ #undef VSYSCALL_ADDR
+diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
+index 9b2f3f51bc91..70a5f6eebd6c 100644
+--- a/arch/x86/kernel/vsyscall_64.c
++++ b/arch/x86/kernel/vsyscall_64.c
+@@ -209,11 +209,6 @@ vgetcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache)
+ 	return 0;
+ }
+ 
+-static long __vsyscall(3) venosys_1(void)
+-{
+-	return -ENOSYS;
+-}
+-
+ /* Assume __initcall executes before all user space. Hopefully kmod
+    doesn't violate that. We'll find out if it does. */
+ static void __cpuinit vsyscall_set_cpu(int cpu)

commit d319bb79afa4039bda6f85661d6bf0c13299ce93
+Author: Andy Lutomirski 
+Date:   Sun Jun 5 13:50:21 2011 -0400
+
+    x86-64: Map the HPET NX
+    
+    Currently the HPET mapping is a user-accessible syscall
+    instruction at a fixed address some of the time.
+    
+    A sufficiently determined hacker might be able to guess when.
+    
+    Signed-off-by: Andy Lutomirski 
+    Cc: Jesper Juhl 
+    Cc: Borislav Petkov 
+    Cc: Linus Torvalds 
+    Cc: Arjan van de Ven 
+    Cc: Jan Beulich 
+    Cc: richard -rw- weinberger 
+    Cc: Mikael Pettersson 
+    Cc: Andi Kleen 
+    Cc: Brian Gerst 
+    Cc: Louis Rilling 
+    Cc: Valdis.Kletnieks@vt.edu
+    Cc: pageexec@freemail.hu
+    Link: http://lkml.kernel.org/r/ab41b525a4ca346b1ca1145d16fb8d181861a8aa.1307292171.git.luto@mit.edu
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
+index 6a29aed65902..013286a10c2c 100644
+--- a/arch/x86/include/asm/pgtable_types.h
++++ b/arch/x86/include/asm/pgtable_types.h
+@@ -107,8 +107,8 @@
+ #define __PAGE_KERNEL_NOCACHE		(__PAGE_KERNEL | _PAGE_PCD | _PAGE_PWT)
+ #define __PAGE_KERNEL_UC_MINUS		(__PAGE_KERNEL | _PAGE_PCD)
+ #define __PAGE_KERNEL_VSYSCALL		(__PAGE_KERNEL_RX | _PAGE_USER)
+-#define __PAGE_KERNEL_VSYSCALL_NOCACHE	(__PAGE_KERNEL_VSYSCALL | _PAGE_PCD | _PAGE_PWT)
+ #define __PAGE_KERNEL_VVAR		(__PAGE_KERNEL_RO | _PAGE_USER)
++#define __PAGE_KERNEL_VVAR_NOCACHE	(__PAGE_KERNEL_VVAR | _PAGE_PCD | _PAGE_PWT)
+ #define __PAGE_KERNEL_LARGE		(__PAGE_KERNEL | _PAGE_PSE)
+ #define __PAGE_KERNEL_LARGE_NOCACHE	(__PAGE_KERNEL | _PAGE_CACHE_UC | _PAGE_PSE)
+ #define __PAGE_KERNEL_LARGE_EXEC	(__PAGE_KERNEL_EXEC | _PAGE_PSE)
+@@ -130,8 +130,8 @@
+ #define PAGE_KERNEL_LARGE_NOCACHE	__pgprot(__PAGE_KERNEL_LARGE_NOCACHE)
+ #define PAGE_KERNEL_LARGE_EXEC		__pgprot(__PAGE_KERNEL_LARGE_EXEC)
+ #define PAGE_KERNEL_VSYSCALL		__pgprot(__PAGE_KERNEL_VSYSCALL)
+-#define PAGE_KERNEL_VSYSCALL_NOCACHE	__pgprot(__PAGE_KERNEL_VSYSCALL_NOCACHE)
+ #define PAGE_KERNEL_VVAR		__pgprot(__PAGE_KERNEL_VVAR)
++#define PAGE_KERNEL_VVAR_NOCACHE	__pgprot(__PAGE_KERNEL_VVAR_NOCACHE)
+ 
+ #define PAGE_KERNEL_IO			__pgprot(__PAGE_KERNEL_IO)
+ #define PAGE_KERNEL_IO_NOCACHE		__pgprot(__PAGE_KERNEL_IO_NOCACHE)
+diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
+index 6781765b3a0d..e9f5605e4748 100644
+--- a/arch/x86/kernel/hpet.c
++++ b/arch/x86/kernel/hpet.c
+@@ -71,7 +71,7 @@ static inline void hpet_set_mapping(void)
+ {
+ 	hpet_virt_address = ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
+ #ifdef CONFIG_X86_64
+-	__set_fixmap(VSYSCALL_HPET, hpet_address, PAGE_KERNEL_VSYSCALL_NOCACHE);
++	__set_fixmap(VSYSCALL_HPET, hpet_address, PAGE_KERNEL_VVAR_NOCACHE);
+ #endif
+ }
+ 

commit 6879eb2deed7171a81b2f904c9ad14b9648689a7
+Author: Andy Lutomirski 
+Date:   Sun Jun 5 13:50:17 2011 -0400
+
+    x86-64: Fix alignment of jiffies variable
+    
+    It's declared __attribute__((aligned(16)) but it's explicitly
+    not aligned.  This is probably harmless but it's a bit
+    embarrassing.
+    
+    Signed-off-by: Andy Lutomirski 
+    Cc: Jesper Juhl 
+    Cc: Borislav Petkov 
+    Cc: Linus Torvalds 
+    Cc: Arjan van de Ven 
+    Cc: Jan Beulich 
+    Cc: richard -rw- weinberger 
+    Cc: Mikael Pettersson 
+    Cc: Andi Kleen 
+    Cc: Brian Gerst 
+    Cc: Louis Rilling 
+    Cc: Valdis.Kletnieks@vt.edu
+    Cc: pageexec@freemail.hu
+    Link: http://lkml.kernel.org/r/5f3bc5542e9aaa9382d53f153f54373165cdef89.1307292171.git.luto@mit.edu
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/x86/include/asm/vvar.h b/arch/x86/include/asm/vvar.h
+index 341b3559452b..a4eaca4a6133 100644
+--- a/arch/x86/include/asm/vvar.h
++++ b/arch/x86/include/asm/vvar.h
+@@ -45,7 +45,7 @@
+ /* DECLARE_VVAR(offset, type, name) */
+ 
+ DECLARE_VVAR(0, volatile unsigned long, jiffies)
+-DECLARE_VVAR(8, int, vgetcpu_mode)
++DECLARE_VVAR(16, int, vgetcpu_mode)
+ DECLARE_VVAR(128, struct vsyscall_gtod_data, vsyscall_gtod_data)
+ 
+ #undef DECLARE_VVAR

commit d183e11a4a66d80e10d60b0918a47cf073135379
+Author: Theodore Ts'o 
+Date:   Thu May 26 09:53:09 2011 -0400
+
+    jbd2: Add MAINTAINERS entry
+    
+    Create a separate MAINTAINERS entry for jbd2
+    
+    Cc: Jan Kara 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 649600cb8ec9..0682c0e82e9e 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -3552,9 +3552,16 @@ M:	Andrew Morton 
+ M:	Jan Kara 
+ L:	linux-ext4@vger.kernel.org
+ S:	Maintained
+-F:	fs/jbd*/
+-F:	include/linux/ext*jbd*.h
+-F:	include/linux/jbd*.h
++F:	fs/jbd/
++F:	include/linux/ext3_jbd.h
++F:	include/linux/jbd.h
++
++JOURNALLING LAYER FOR BLOCK DEVICES (JBD2)
++M:	"Theodore Ts'o" 
++L:	linux-ext4@vger.kernel.org
++S:	Maintained
++F:	fs/jbd2/
++F:	include/linux/jbd2.h
+ 
+ JSM Neo PCI based serial card
+ M:	Breno Leitao 

commit 072bd7ea74d4b60149a33967d29666bbd84e7709
+Author: Theodore Ts'o 
+Date:   Mon May 23 15:13:02 2011 -0400
+
+    ext4: use truncate_setsize() unconditionally
+    
+    In commit c8d46e41 (ext4: Add flag to files with blocks intentionally
+    past EOF), if the EOFBLOCKS_FL flag is set, we call ext4_truncate()
+    before calling vmtruncate().  This caused any allocated but unwritten
+    blocks created by calling fallocate() with the FALLOC_FL_KEEP_SIZE
+    flag to be dropped.  This was done to make to make sure that
+    EOFBLOCKS_FL would not be cleared while still leaving blocks past
+    i_size allocated.  This was not necessary, since ext4_truncate()
+    guarantees that blocks past i_size will be dropped, even in the case
+    where truncate() has increased i_size before calling ext4_truncate().
+    
+    So fix this by removing the EOFBLOCKS_FL special case treatment in
+    ext4_setattr().  In addition, use truncate_setsize() followed by a
+    call to ext4_truncate() instead of using vmtruncate().  This is more
+    efficient since it skips the call to inode_newsize_ok(), which has
+    been checked already by inode_change_ok().  This is also in a win in
+    the case where EOFBLOCKS_FL is set since it avoids calling
+    ext4_truncate() twice.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 6348c1f610c2..d98b033dd4a4 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -5309,8 +5309,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
+ 
+ 	if (S_ISREG(inode->i_mode) &&
+ 	    attr->ia_valid & ATTR_SIZE &&
+-	    (attr->ia_size < inode->i_size ||
+-	     (ext4_test_inode_flag(inode, EXT4_INODE_EOFBLOCKS)))) {
++	    (attr->ia_size < inode->i_size)) {
+ 		handle_t *handle;
+ 
+ 		handle = ext4_journal_start(inode, 3);
+@@ -5344,14 +5343,15 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
+ 				goto err_out;
+ 			}
+ 		}
+-		/* ext4_truncate will clear the flag */
+-		if ((ext4_test_inode_flag(inode, EXT4_INODE_EOFBLOCKS)))
+-			ext4_truncate(inode);
+ 	}
+ 
+-	if ((attr->ia_valid & ATTR_SIZE) &&
+-	    attr->ia_size != i_size_read(inode))
+-		rc = vmtruncate(inode, attr->ia_size);
++	if (attr->ia_valid & ATTR_SIZE) {
++		if (attr->ia_size != i_size_read(inode)) {
++			truncate_setsize(inode, attr->ia_size);
++			ext4_truncate(inode);
++		} else if (ext4_test_inode_flag(inode, EXT4_INODE_EOFBLOCKS))
++			ext4_truncate(inode);
++	}
+ 
+ 	if (!rc) {
+ 		setattr_copy(inode, attr);

commit 373cd5c53d5ea6622c319ecd84e29e2737d488bd
+Author: Theodore Ts'o 
+Date:   Sun May 22 16:12:35 2011 -0400
+
+    ext4: don't show mount options in /proc/mounts if there is no journal
+    
+    After creating an ext4 file system without a journal:
+    
+      # mke2fs -t ext4 -O ^has_journal /dev/sda
+      # mount -t ext4 /dev/sda /test
+    
+    the /proc/mounts will show:
+    "/dev/sda /test ext4 rw,relatime,user_xattr,acl,barrier=1,data=writeback 0 0"
+    which can fool users into thinking that the fs is using writeback mode.
+    
+    So don't set the writeback option when the journal has not been
+    enabled; we don't depend on the writeback option being set, since
+    ext4_should_writeback_data() in ext4_jbd2.h tests to see if the
+    journal is not present before returning true.
+    
+    Reported-by: Robin Dong 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index ed5e80ef48c4..fdce4eebce0c 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3485,7 +3485,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		goto failed_mount_wq;
+ 	} else {
+ 		clear_opt(sb, DATA_FLAGS);
+-		set_opt(sb, WRITEBACK_DATA);
+ 		sbi->s_journal = NULL;
+ 		needs_recovery = 0;
+ 		goto no_journal;

commit d9b01934d56a96d9f4ae2d6204d4ea78a36f5f36
+Author: Ted Ts'o 
+Date:   Sat Apr 30 13:17:11 2011 -0400
+
+    jbd: fix fsync() tid wraparound bug
+    
+    If an application program does not make any changes to the indirect
+    blocks or extent tree, i_datasync_tid will not get updated.  If there
+    are enough commits (i.e., 2**31) such that tid_geq()'s calculations
+    wrap, and there isn't a currently active transaction at the time of
+    the fdatasync() call, this can end up triggering a BUG_ON in
+    fs/jbd/commit.c:
+    
+            J_ASSERT(journal->j_running_transaction != NULL);
+    
+    It's pretty rare that this can happen, since it requires the use of
+    fdatasync() plus *very* frequent and excessive use of fsync().  But
+    with the right workload, it can.
+    
+    We fix this by replacing the use of tid_geq() with an equality test,
+    since there's only one valid transaction id that is valid for us to
+    start: namely, the currently running transaction (if it exists).
+    
+    CC: stable@kernel.org
+    Reported-by: Martin_Zielinski@McAfee.com
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Jan Kara 
+
+diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
+index b3713afaaa9e..e2d4285fbe90 100644
+--- a/fs/jbd/journal.c
++++ b/fs/jbd/journal.c
+@@ -437,9 +437,12 @@ int __log_space_left(journal_t *journal)
+ int __log_start_commit(journal_t *journal, tid_t target)
+ {
+ 	/*
+-	 * Are we already doing a recent enough commit?
++	 * The only transaction we can possibly wait upon is the
++	 * currently running transaction (if it exists).  Otherwise,
++	 * the target tid must be an old one.
+ 	 */
+-	if (!tid_geq(journal->j_commit_request, target)) {
++	if (journal->j_running_transaction &&
++	    journal->j_running_transaction->t_tid == target) {
+ 		/*
+ 		 * We want a new commit: OK, mark the request and wakeup the
+ 		 * commit thread.  We do _not_ do the commit ourselves.
+@@ -451,7 +454,14 @@ int __log_start_commit(journal_t *journal, tid_t target)
+ 			  journal->j_commit_sequence);
+ 		wake_up(&journal->j_wait_commit);
+ 		return 1;
+-	}
++	} else if (!tid_geq(journal->j_commit_request, target))
++		/* This should never happen, but if it does, preserve
++		   the evidence before kjournald goes into a loop and
++		   increments j_commit_sequence beyond all recognition. */
++		WARN_ONCE(1, "jbd: bad log_start_commit: %u %u %u %u\n",
++		    journal->j_commit_request, journal->j_commit_sequence,
++		    target, journal->j_running_transaction ?
++		    journal->j_running_transaction->t_tid : 0);
+ 	return 0;
+ }
+ 

commit b23b64516500df6b70fcafb820970f18538252cf
+Author: Andy Lutomirski 
+Date:   Mon May 16 15:12:47 2011 +1000
+
+    crypto: aesni-intel - Merge with fpu.ko
+    
+    Loading fpu without aesni-intel does nothing.  Loading aesni-intel
+    without fpu causes modes like xts to fail.  (Unloading
+    aesni-intel will restore those modes.)
+    
+    One solution would be to make aesni-intel depend on fpu, but it
+    seems cleaner to just combine the modules.
+    
+    This is probably responsible for bugs like:
+    https://bugzilla.redhat.com/show_bug.cgi?id=589390
+    
+    Signed-off-by: Andy Lutomirski 
+    Signed-off-by: Herbert Xu 
+
+diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile
+index 1a58ad89fdf7..c04f1b7a9139 100644
+--- a/arch/x86/crypto/Makefile
++++ b/arch/x86/crypto/Makefile
+@@ -2,8 +2,6 @@
+ # Arch-specific CryptoAPI modules.
+ #
+ 
+-obj-$(CONFIG_CRYPTO_FPU) += fpu.o
+-
+ obj-$(CONFIG_CRYPTO_AES_586) += aes-i586.o
+ obj-$(CONFIG_CRYPTO_TWOFISH_586) += twofish-i586.o
+ obj-$(CONFIG_CRYPTO_SALSA20_586) += salsa20-i586.o
+@@ -24,6 +22,6 @@ aes-x86_64-y := aes-x86_64-asm_64.o aes_glue.o
+ twofish-x86_64-y := twofish-x86_64-asm_64.o twofish_glue.o
+ salsa20-x86_64-y := salsa20-x86_64-asm_64.o salsa20_glue.o
+ 
+-aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o
++aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o fpu.o
+ 
+ ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o
+diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c
+index 2577613fb32b..cbc60ef359bc 100644
+--- a/arch/x86/crypto/aesni-intel_glue.c
++++ b/arch/x86/crypto/aesni-intel_glue.c
+@@ -140,6 +140,9 @@ asmlinkage void aesni_gcm_dec(void *ctx, u8 *out,
+ 			u8 *hash_subkey, const u8 *aad, unsigned long aad_len,
+ 			u8 *auth_tag, unsigned long auth_tag_len);
+ 
++int crypto_fpu_init(void);
++void crypto_fpu_exit(void);
++
+ static inline struct
+ aesni_rfc4106_gcm_ctx *aesni_rfc4106_gcm_ctx_get(struct crypto_aead *tfm)
+ {
+@@ -1257,6 +1260,8 @@ static int __init aesni_init(void)
+ 		return -ENODEV;
+ 	}
+ 
++	if ((err = crypto_fpu_init()))
++		goto fpu_err;
+ 	if ((err = crypto_register_alg(&aesni_alg)))
+ 		goto aes_err;
+ 	if ((err = crypto_register_alg(&__aesni_alg)))
+@@ -1334,6 +1339,7 @@ static int __init aesni_init(void)
+ __aes_err:
+ 	crypto_unregister_alg(&aesni_alg);
+ aes_err:
++fpu_err:
+ 	return err;
+ }
+ 
+@@ -1363,6 +1369,8 @@ static void __exit aesni_exit(void)
+ 	crypto_unregister_alg(&blk_ecb_alg);
+ 	crypto_unregister_alg(&__aesni_alg);
+ 	crypto_unregister_alg(&aesni_alg);
++
++	crypto_fpu_exit();
+ }
+ 
+ module_init(aesni_init);
+diff --git a/arch/x86/crypto/fpu.c b/arch/x86/crypto/fpu.c
+index 1a8f8649c035..98d7a188f46b 100644
+--- a/arch/x86/crypto/fpu.c
++++ b/arch/x86/crypto/fpu.c
+@@ -150,18 +150,12 @@ static struct crypto_template crypto_fpu_tmpl = {
+ 	.module = THIS_MODULE,
+ };
+ 
+-static int __init crypto_fpu_module_init(void)
++int __init crypto_fpu_init(void)
+ {
+ 	return crypto_register_template(&crypto_fpu_tmpl);
+ }
+ 
+-static void __exit crypto_fpu_module_exit(void)
++void __exit crypto_fpu_exit(void)
+ {
+ 	crypto_unregister_template(&crypto_fpu_tmpl);
+ }
+-
+-module_init(crypto_fpu_module_init);
+-module_exit(crypto_fpu_module_exit);
+-
+-MODULE_LICENSE("GPL");
+-MODULE_DESCRIPTION("FPU block cipher wrapper");
+diff --git a/crypto/Kconfig b/crypto/Kconfig
+index 4b7cb0e691cd..87b22ca9c223 100644
+--- a/crypto/Kconfig
++++ b/crypto/Kconfig
+@@ -264,11 +264,6 @@ config CRYPTO_XTS
+ 	  key size 256, 384 or 512 bits. This implementation currently
+ 	  can't handle a sectorsize which is not a multiple of 16 bytes.
+ 
+-config CRYPTO_FPU
+-	tristate
+-	select CRYPTO_BLKCIPHER
+-	select CRYPTO_MANAGER
+-
+ comment "Hash modes"
+ 
+ config CRYPTO_HMAC
+@@ -543,7 +538,6 @@ config CRYPTO_AES_NI_INTEL
+ 	select CRYPTO_AES_586 if !64BIT
+ 	select CRYPTO_CRYPTD
+ 	select CRYPTO_ALGAPI
+-	select CRYPTO_FPU
+ 	help
+ 	  Use Intel AES-NI instructions for AES algorithm.
+ 

commit 8eea1be174a1ea4b86323167bbadc8a6abdca613
+Author: Andy Lutomirski 
+Date:   Fri May 13 12:14:54 2011 -0400
+
+    drm/i915: Revert i915.semaphore=1 default from 47ae63e0
+    
+    My Q67 / i7-2600 box has rev09 Sandy Bridge graphics.  It hangs
+    instantly when GNOME loads and it hangs so hard the reset button
+    doesn't work.  Setting i915.semaphore=0 fixes it.
+    
+    Semaphores were disabled in a1656b9090f7008d2941c314f5a64724bea2ae37
+    in 2.6.38 and were re-enabled by
+    
+    commit 47ae63e0c2e5fdb582d471dc906eb29be94c732f
+    Merge: c59a333 467cffb
+    Author: Chris Wilson 
+    Date:   Mon Mar 7 12:32:44 2011 +0000
+    
+        Merge branch 'drm-intel-fixes' into drm-intel-next
+    
+        Apply the trivial conflicting regression fixes, but keep GPU semaphores
+        enabled.
+    
+        Conflicts:
+            drivers/gpu/drm/i915/i915_drv.h
+            drivers/gpu/drm/i915/i915_gem_execbuffer.c
+    
+    (It's worth noting that the offending change is i915_drv.c,
+     which is not a conflict.)
+    
+    Signed-off-by: Andy Lutomirski 
+    Acked-by: Keith Packard 
+    Signed-off-by: Dave Airlie 
+
+diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
+index c34a8dd31d02..32d1b3e829c8 100644
+--- a/drivers/gpu/drm/i915/i915_drv.c
++++ b/drivers/gpu/drm/i915/i915_drv.c
+@@ -49,7 +49,7 @@ module_param_named(panel_ignore_lid, i915_panel_ignore_lid, int, 0600);
+ unsigned int i915_powersave = 1;
+ module_param_named(powersave, i915_powersave, int, 0600);
+ 
+-unsigned int i915_semaphores = 1;
++unsigned int i915_semaphores = 0;
+ module_param_named(semaphores, i915_semaphores, int, 0600);
+ 
+ unsigned int i915_enable_rc6 = 0;

commit 087fbc9962e10a65fb0b542ecfc116ebf6cf1735
+Author: Andy Lutomirski 
+Date:   Fri May 13 12:14:54 2011 -0400
+
+    drm/i915: Revert i915.semaphore=1 default from i915 merge
+    
+    My Q67 / i7-2600 box has rev09 Sandy Bridge graphics.  It hangs
+    instantly when GNOME loads and it hangs so hard the reset button
+    doesn't work.  Setting i915.semaphore=0 fixes it.
+    
+    Semaphores were disabled in a1656b9090f7 ("drm/i915: Disable GPU
+    semaphores by default") in 2.6.38 but were then re-enabled (by mistake?)
+    by the merge 47ae63e0c2e5 ("Merge branch 'drm-intel-fixes' into
+    drm-intel-next").
+    
+    (It's worth noting that the offending change is i915_drv.c, which was
+    not marked as a conflict - although a 'git show --cc' on the merge does
+    show that neither parent had it set to 1)
+    
+    Signed-off-by: Andy Lutomirski 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
+index c34a8dd31d02..32d1b3e829c8 100644
+--- a/drivers/gpu/drm/i915/i915_drv.c
++++ b/drivers/gpu/drm/i915/i915_drv.c
+@@ -49,7 +49,7 @@ module_param_named(panel_ignore_lid, i915_panel_ignore_lid, int, 0600);
+ unsigned int i915_powersave = 1;
+ module_param_named(powersave, i915_powersave, int, 0600);
+ 
+-unsigned int i915_semaphores = 1;
++unsigned int i915_semaphores = 0;
+ module_param_named(semaphores, i915_semaphores, int, 0600);
+ 
+ unsigned int i915_enable_rc6 = 0;

commit 2cd05cc39347ddd8994b7f63ab5cb886f042477f
+Author: Theodore Ts'o 
+Date:   Mon May 9 10:58:45 2011 -0400
+
+    ext4: remove unneeded ext4_journal_get_undo_access
+    
+    The block allocation code used to use jbd2_journal_get_undo_access as
+    a way to make changes that wouldn't show up until the commit took
+    place.  The new multi-block allocation code has a its own way of
+    preventing newly freed blocks from getting reused until the commit
+    takes place (it avoids updating the buddy bitmaps until the commit is
+    done), so we don't need to use jbd2_journal_get_undo_access(), which
+    has extra overhead compared to jbd2_journal_get_write_access().
+    
+    There was one last vestigal use of ext4_journal_get_undo_access() in
+    ext4_add_groupblocks(); change it to use ext4_journal_get_write_access()
+    and then remove the ext4_journal_get_undo_access() support.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
+index 6e272ef6ba96..f5240aa15601 100644
+--- a/fs/ext4/ext4_jbd2.c
++++ b/fs/ext4/ext4_jbd2.c
+@@ -6,20 +6,6 @@
+ 
+ #include 
+ 
+-int __ext4_journal_get_undo_access(const char *where, unsigned int line,
+-				   handle_t *handle, struct buffer_head *bh)
+-{
+-	int err = 0;
+-
+-	if (ext4_handle_valid(handle)) {
+-		err = jbd2_journal_get_undo_access(handle, bh);
+-		if (err)
+-			ext4_journal_abort_handle(where, line, __func__, bh,
+-						  handle, err);
+-	}
+-	return err;
+-}
+-
+ int __ext4_journal_get_write_access(const char *where, unsigned int line,
+ 				    handle_t *handle, struct buffer_head *bh)
+ {
+diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
+index d0f53538a57f..bb85757689b6 100644
+--- a/fs/ext4/ext4_jbd2.h
++++ b/fs/ext4/ext4_jbd2.h
+@@ -126,9 +126,6 @@ void ext4_journal_abort_handle(const char *caller, unsigned int line,
+ 			       const char *err_fn,
+ 		struct buffer_head *bh, handle_t *handle, int err);
+ 
+-int __ext4_journal_get_undo_access(const char *where, unsigned int line,
+-				   handle_t *handle, struct buffer_head *bh);
+-
+ int __ext4_journal_get_write_access(const char *where, unsigned int line,
+ 				    handle_t *handle, struct buffer_head *bh);
+ 
+@@ -146,8 +143,6 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
+ int __ext4_handle_dirty_super(const char *where, unsigned int line,
+ 			      handle_t *handle, struct super_block *sb);
+ 
+-#define ext4_journal_get_undo_access(handle, bh) \
+-	__ext4_journal_get_undo_access(__func__, __LINE__, (handle), (bh))
+ #define ext4_journal_get_write_access(handle, bh) \
+ 	__ext4_journal_get_write_access(__func__, __LINE__, (handle), (bh))
+ #define ext4_forget(handle, is_metadata, inode, bh, block_nr) \
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 92aa05ddef66..307d447bbc43 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -4732,9 +4732,9 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
+ 	 * Check to see if we are freeing blocks across a group
+ 	 * boundary.
+ 	 */
+-	if (bit + count > EXT4_BLOCKS_PER_GROUP(sb)) {
++	if (bit + count > EXT4_BLOCKS_PER_GROUP(sb))
+ 		goto error_return;
+-	}
++
+ 	bitmap_bh = ext4_read_block_bitmap(sb, block_group);
+ 	if (!bitmap_bh)
+ 		goto error_return;
+@@ -4753,12 +4753,8 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
+ 		goto error_return;
+ 	}
+ 
+-	/*
+-	 * We are about to add blocks to the bitmap,
+-	 * so we need undo access.
+-	 */
+-	BUFFER_TRACE(bitmap_bh, "getting undo access");
+-	err = ext4_journal_get_undo_access(handle, bitmap_bh);
++	BUFFER_TRACE(bitmap_bh, "getting write access");
++	err = ext4_journal_get_write_access(handle, bitmap_bh);
+ 	if (err)
+ 		goto error_return;
+ 

commit 1be2add685181ba31554ffefa428b0f80a408bff
+Author: Theodore Ts'o 
+Date:   Sun May 8 19:37:54 2011 -0400
+
+    jbd2: only print the debugging information for tid wraparound once
+    
+    If we somehow wrap, we don't want to keep printing the warning message
+    over and over again.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 8c10004f7876..cd2d341f602e 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -500,10 +500,11 @@ int __jbd2_log_start_commit(journal_t *journal, tid_t target)
+ 		/* This should never happen, but if it does, preserve
+ 		   the evidence before kjournald goes into a loop and
+ 		   increments j_commit_sequence beyond all recognition. */
+-		WARN(1, "jbd: bad log_start_commit: %u %u %u %u\n",
+-		     journal->j_commit_request, journal->j_commit_sequence,
+-		     target, journal->j_running_transaction ? 
+-		     journal->j_running_transaction->t_tid : 0);
++		WARN_ONCE(1, "jbd: bad log_start_commit: %u %u %u %u\n",
++			  journal->j_commit_request,
++			  journal->j_commit_sequence,
++			  target, journal->j_running_transaction ? 
++			  journal->j_running_transaction->t_tid : 0);
+ 	return 0;
+ }
+ 

commit 74e4e6db38918620bdf8a46e94982ead2b228d43
+Author: Theodore Ts'o 
+Date:   Tue May 3 09:34:42 2011 -0400
+
+    ext4: set extents flag when migrating file to use extents
+    
+    Fix a typo that was introduced in commit 07a038245b (in 2.6.36) which
+    caused the extents flag not to be set at the conclusion of converting
+    an inode to use extents.
+    
+    Reported-by: Peter Uchno 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
+index 92816b4e0f16..b57b98fb44d1 100644
+--- a/fs/ext4/migrate.c
++++ b/fs/ext4/migrate.c
+@@ -376,7 +376,7 @@ static int ext4_ext_swap_inode_data(handle_t *handle, struct inode *inode,
+ 	 * We have the extent map build with the tmp inode.
+ 	 * Now copy the i_data across
+ 	 */
+-	ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS);
++	ext4_set_inode_flag(inode, EXT4_INODE_EXTENTS);
+ 	memcpy(ei->i_data, tmp_ei->i_data, sizeof(ei->i_data));
+ 
+ 	/*

commit deeeaf13b291420fe4a4a52606b9fc9128387340
+Author: Theodore Ts'o 
+Date:   Sun May 1 18:16:26 2011 -0400
+
+    jbd2: fix fsync() tid wraparound bug
+    
+    If an application program does not make any changes to the indirect
+    blocks or extent tree, i_datasync_tid will not get updated.  If there
+    are enough commits (i.e., 2**31) such that tid_geq()'s calculations
+    wrap, and there isn't a currently active transaction at the time of
+    the fdatasync() call, this can end up triggering a BUG_ON in
+    fs/jbd2/commit.c:
+    
+            J_ASSERT(journal->j_running_transaction != NULL);
+    
+    It's pretty rare that this can happen, since it requires the use of
+    fdatasync() plus *very* frequent and excessive use of fsync().  But
+    with the right workload, it can.
+    
+    We fix this by replacing the use of tid_geq() with an equality test,
+    since there's only one valid transaction id that we is valid for us to
+    wait until it is commited: namely, the currently running transaction
+    (if it exists).
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index e0ec3db1c395..8c10004f7876 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -479,9 +479,12 @@ int __jbd2_log_space_left(journal_t *journal)
+ int __jbd2_log_start_commit(journal_t *journal, tid_t target)
+ {
+ 	/*
+-	 * Are we already doing a recent enough commit?
++	 * The only transaction we can possibly wait upon is the
++	 * currently running transaction (if it exists).  Otherwise,
++	 * the target tid must be an old one.
+ 	 */
+-	if (!tid_geq(journal->j_commit_request, target)) {
++	if (journal->j_running_transaction &&
++	    journal->j_running_transaction->t_tid == target) {
+ 		/*
+ 		 * We want a new commit: OK, mark the request and wakeup the
+ 		 * commit thread.  We do _not_ do the commit ourselves.
+@@ -493,7 +496,14 @@ int __jbd2_log_start_commit(journal_t *journal, tid_t target)
+ 			  journal->j_commit_sequence);
+ 		wake_up(&journal->j_wait_commit);
+ 		return 1;
+-	}
++	} else if (!tid_geq(journal->j_commit_request, target))
++		/* This should never happen, but if it does, preserve
++		   the evidence before kjournald goes into a loop and
++		   increments j_commit_sequence beyond all recognition. */
++		WARN(1, "jbd: bad log_start_commit: %u %u %u %u\n",
++		     journal->j_commit_request, journal->j_commit_sequence,
++		     target, journal->j_running_transaction ? 
++		     journal->j_running_transaction->t_tid : 0);
+ 	return 0;
+ }
+ 

commit 59802db0745ddfe5cfd0d965e9d489f1b4713868
+Author: Theodore Ts'o 
+Date:   Sun May 1 18:14:26 2011 -0400
+
+    ext4: remove obsolete mount options from ext4's documentation
+    
+    The block reservation code from ext3 was removed long ago...
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
+index c79ec58fd7f6..3ae9bc94352a 100644
+--- a/Documentation/filesystems/ext4.txt
++++ b/Documentation/filesystems/ext4.txt
+@@ -226,10 +226,6 @@ acl			Enables POSIX Access Control Lists support.
+ noacl			This option disables POSIX Access Control List
+ 			support.
+ 
+-reservation
+-
+-noreservation
+-
+ bsddf		(*)	Make 'df' act like BSD.
+ minixdf			Make 'df' act like Minix.
+ 

commit d9f34504e6952e909a6932c5b2d1857716606380
+Author: Theodore Ts'o 
+Date:   Sat Apr 30 13:47:24 2011 -0400
+
+    ext4: ignore errors when issuing discards
+    
+    This is an effective revert of commit a30eec2a8: "ext4: stop issuing
+    discards if not supported by device".  The problem is that there are
+    some devices that may return errors in response to a discard request
+    some times but not others.  (One example would be a hybrid dm device
+    which concatenates an SSD and an HDD device).
+    
+    By this logic, I also removed the error checking from ext4's FITRIM
+    code; so that an error from a discard will not stop the FITRIM from
+    trying to trim the rest of the file system.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 15bfa44abd29..730c1a72a959 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2661,7 +2661,7 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn)
+ 	struct super_block *sb = journal->j_private;
+ 	struct ext4_buddy e4b;
+ 	struct ext4_group_info *db;
+-	int err, ret, count = 0, count2 = 0;
++	int err, count = 0, count2 = 0;
+ 	struct ext4_free_data *entry;
+ 	struct list_head *l, *ltmp;
+ 
+@@ -2671,15 +2671,9 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn)
+ 		mb_debug(1, "gonna free %u blocks in group %u (0x%p):",
+ 			 entry->count, entry->group, entry);
+ 
+-		if (test_opt(sb, DISCARD)) {
+-			ret = ext4_issue_discard(sb, entry->group,
+-					entry->start_blk, entry->count);
+-			if (unlikely(ret == -EOPNOTSUPP)) {
+-				ext4_warning(sb, "discard not supported, "
+-						 "disabling");
+-				clear_opt(sb, DISCARD);
+-			}
+-		}
++		if (test_opt(sb, DISCARD))
++			ext4_issue_discard(sb, entry->group,
++					   entry->start_blk, entry->count);
+ 
+ 		err = ext4_mb_load_buddy(sb, entry->group, &e4b);
+ 		/* we expect to find existing buddy because it's pinned */
+@@ -4717,11 +4711,10 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+  * one will allocate those blocks, mark it as used in buddy bitmap. This must
+  * be called with under the group lock.
+  */
+-static int ext4_trim_extent(struct super_block *sb, int start, int count,
+-		ext4_group_t group, struct ext4_buddy *e4b)
++static void ext4_trim_extent(struct super_block *sb, int start, int count,
++			     ext4_group_t group, struct ext4_buddy *e4b)
+ {
+ 	struct ext4_free_extent ex;
+-	int ret = 0;
+ 
+ 	assert_spin_locked(ext4_group_lock_ptr(sb, group));
+ 
+@@ -4735,12 +4728,9 @@ static int ext4_trim_extent(struct super_block *sb, int start, int count,
+ 	 */
+ 	mb_mark_used(e4b, &ex);
+ 	ext4_unlock_group(sb, group);
+-
+-	ret = ext4_issue_discard(sb, group, start, count);
+-
++	ext4_issue_discard(sb, group, start, count);
+ 	ext4_lock_group(sb, group);
+ 	mb_free_blocks(NULL, e4b, start, ex.fe_len);
+-	return ret;
+ }
+ 
+ /**
+@@ -4768,7 +4758,6 @@ ext4_trim_all_free(struct super_block *sb, struct ext4_buddy *e4b,
+ 	void *bitmap;
+ 	ext4_grpblk_t next, count = 0;
+ 	ext4_group_t group;
+-	int ret = 0;
+ 
+ 	BUG_ON(e4b == NULL);
+ 
+@@ -4785,10 +4774,8 @@ ext4_trim_all_free(struct super_block *sb, struct ext4_buddy *e4b,
+ 		next = mb_find_next_bit(bitmap, max, start);
+ 
+ 		if ((next - start) >= minblocks) {
+-			ret = ext4_trim_extent(sb, start,
+-				next - start, group, e4b);
+-			if (ret < 0)
+-				break;
++			ext4_trim_extent(sb, start,
++					 next - start, group, e4b);
+ 			count += next - start;
+ 		}
+ 		start = next + 1;
+@@ -4812,9 +4799,6 @@ ext4_trim_all_free(struct super_block *sb, struct ext4_buddy *e4b,
+ 	ext4_debug("trimmed %d blocks in the group %d\n",
+ 		count, group);
+ 
+-	if (ret < 0)
+-		count = ret;
+-
+ 	return count;
+ }
+ 

commit 2035e776050aea57fb5255557216473e82793f2c
+Author: Theodore Ts'o 
+Date:   Mon Apr 18 17:29:14 2011 -0400
+
+    ext4: check for ext[23] file system features when mounting as ext[23]
+    
+    Provide better emulation for ext[23] mode by enforcing that the file
+    system does not have any unsupported file system features as defined
+    by ext[23] when emulating the ext[23] file system driver when
+    CONFIG_EXT4_USE_FOR_EXT23 is defined.
+    
+    This causes the file system type information in /proc/mounts to be
+    correct for the automatically mounted root file system.  This also
+    means that "mount -t ext2 /dev/sda /mnt" will fail if /dev/sda
+    contains an ext3 or ext4 file system, just as one would expect if the
+    original ext2 file system driver were in use.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 4daaf2b753f4..076c5d212a3c 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1351,6 +1351,21 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei)
+ #define EXT4_FEATURE_INCOMPAT_EA_INODE		0x0400 /* EA in inode */
+ #define EXT4_FEATURE_INCOMPAT_DIRDATA		0x1000 /* data in dirent */
+ 
++#define EXT2_FEATURE_COMPAT_SUPP	EXT4_FEATURE_COMPAT_EXT_ATTR
++#define EXT2_FEATURE_INCOMPAT_SUPP	(EXT4_FEATURE_INCOMPAT_FILETYPE| \
++					 EXT4_FEATURE_INCOMPAT_META_BG)
++#define EXT2_FEATURE_RO_COMPAT_SUPP	(EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \
++					 EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \
++					 EXT4_FEATURE_RO_COMPAT_BTREE_DIR)
++
++#define EXT3_FEATURE_COMPAT_SUPP	EXT4_FEATURE_COMPAT_EXT_ATTR
++#define EXT3_FEATURE_INCOMPAT_SUPP	(EXT4_FEATURE_INCOMPAT_FILETYPE| \
++					 EXT4_FEATURE_INCOMPAT_RECOVER| \
++					 EXT4_FEATURE_INCOMPAT_META_BG)
++#define EXT3_FEATURE_RO_COMPAT_SUPP	(EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \
++					 EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \
++					 EXT4_FEATURE_RO_COMPAT_BTREE_DIR)
++
+ #define EXT4_FEATURE_COMPAT_SUPP	EXT2_FEATURE_COMPAT_EXT_ATTR
+ #define EXT4_FEATURE_INCOMPAT_SUPP	(EXT4_FEATURE_INCOMPAT_FILETYPE| \
+ 					 EXT4_FEATURE_INCOMPAT_RECOVER| \
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 8553dfb310af..cb22783a4377 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -75,11 +75,27 @@ static void ext4_write_super(struct super_block *sb);
+ static int ext4_freeze(struct super_block *sb);
+ static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags,
+ 		       const char *dev_name, void *data);
++static inline int ext2_feature_set_ok(struct super_block *sb);
++static inline int ext3_feature_set_ok(struct super_block *sb);
+ static int ext4_feature_set_ok(struct super_block *sb, int readonly);
+ static void ext4_destroy_lazyinit_thread(void);
+ static void ext4_unregister_li_request(struct super_block *sb);
+ static void ext4_clear_request_list(void);
+ 
++#if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23)
++static struct file_system_type ext2_fs_type = {
++	.owner		= THIS_MODULE,
++	.name		= "ext2",
++	.mount		= ext4_mount,
++	.kill_sb	= kill_block_super,
++	.fs_flags	= FS_REQUIRES_DEV,
++};
++#define IS_EXT2_SB(sb) ((sb)->s_bdev->bd_holder == &ext2_fs_type)
++#else
++#define IS_EXT2_SB(sb) (0)
++#endif
++
++
+ #if !defined(CONFIG_EXT3_FS) && !defined(CONFIG_EXT3_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23)
+ static struct file_system_type ext3_fs_type = {
+ 	.owner		= THIS_MODULE,
+@@ -3187,6 +3203,28 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		       "feature flags set on rev 0 fs, "
+ 		       "running e2fsck is recommended");
+ 
++	if (IS_EXT2_SB(sb)) {
++		if (ext2_feature_set_ok(sb))
++			ext4_msg(sb, KERN_INFO, "mounting ext2 file system "
++				 "using the ext4 subsystem");
++		else {
++			ext4_msg(sb, KERN_ERR, "couldn't mount as ext2 due "
++				 "to feature incompatibilities");
++			goto failed_mount;
++		}
++	}
++
++	if (IS_EXT3_SB(sb)) {
++		if (ext3_feature_set_ok(sb))
++			ext4_msg(sb, KERN_INFO, "mounting ext3 file system "
++				 "using the ext4 subsystem");
++		else {
++			ext4_msg(sb, KERN_ERR, "couldn't mount as ext3 due "
++				 "to feature incompatibilities");
++			goto failed_mount;
++		}
++	}
++
+ 	/*
+ 	 * Check feature flags regardless of the revision level, since we
+ 	 * previously didn't change the revision level when setting the flags,
+@@ -4772,14 +4810,6 @@ static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags,
+ }
+ 
+ #if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23)
+-static struct file_system_type ext2_fs_type = {
+-	.owner		= THIS_MODULE,
+-	.name		= "ext2",
+-	.mount		= ext4_mount,
+-	.kill_sb	= kill_block_super,
+-	.fs_flags	= FS_REQUIRES_DEV,
+-};
+-
+ static inline void register_as_ext2(void)
+ {
+ 	int err = register_filesystem(&ext2_fs_type);
+@@ -4792,10 +4822,22 @@ static inline void unregister_as_ext2(void)
+ {
+ 	unregister_filesystem(&ext2_fs_type);
+ }
++
++static inline int ext2_feature_set_ok(struct super_block *sb)
++{
++	if (EXT4_HAS_INCOMPAT_FEATURE(sb, ~EXT2_FEATURE_INCOMPAT_SUPP))
++		return 0;
++	if (sb->s_flags & MS_RDONLY)
++		return 1;
++	if (EXT4_HAS_RO_COMPAT_FEATURE(sb, ~EXT2_FEATURE_RO_COMPAT_SUPP))
++		return 0;
++	return 1;
++}
+ MODULE_ALIAS("ext2");
+ #else
+ static inline void register_as_ext2(void) { }
+ static inline void unregister_as_ext2(void) { }
++static inline int ext2_feature_set_ok(struct super_block *sb) { return 0; }
+ #endif
+ 
+ #if !defined(CONFIG_EXT3_FS) && !defined(CONFIG_EXT3_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23)
+@@ -4811,10 +4853,24 @@ static inline void unregister_as_ext3(void)
+ {
+ 	unregister_filesystem(&ext3_fs_type);
+ }
++
++static inline int ext3_feature_set_ok(struct super_block *sb)
++{
++	if (EXT4_HAS_INCOMPAT_FEATURE(sb, ~EXT3_FEATURE_INCOMPAT_SUPP))
++		return 0;
++	if (!EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL))
++		return 0;
++	if (sb->s_flags & MS_RDONLY)
++		return 1;
++	if (EXT4_HAS_RO_COMPAT_FEATURE(sb, ~EXT3_FEATURE_RO_COMPAT_SUPP))
++		return 0;
++	return 1;
++}
+ MODULE_ALIAS("ext3");
+ #else
+ static inline void register_as_ext3(void) { }
+ static inline void unregister_as_ext3(void) { }
++static inline int ext3_feature_set_ok(struct super_block *sb) { return 0; }
+ #endif
+ 
+ static struct file_system_type ext4_fs_type = {
+@@ -4898,8 +4954,8 @@ static int __init ext4_init_fs(void)
+ 	err = init_inodecache();
+ 	if (err)
+ 		goto out1;
+-	register_as_ext2();
+ 	register_as_ext3();
++	register_as_ext2();
+ 	err = register_filesystem(&ext4_fs_type);
+ 	if (err)
+ 		goto out;

commit c8205636029fc869278c55b7336053b3e7ae3ef4
+Author: Theodore Ts'o 
+Date:   Sun Apr 10 22:30:07 2011 -0400
+
+    ext4: fix data corruption regression by reverting commit 6de9843dab3f
+    
+    Revert commit 6de9843dab3f2a1d4d66d80aa9e5782f80977d20, since it
+    caused a data corruption regression with BitTorrent downloads.  Thanks
+    to Damien for discovering and bisecting to find the problem commit.
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=32972
+    
+    Reported-by: Damien Grassart 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 5560f78690ac..9c8cf811d93a 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2502,6 +2502,7 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock,
+ 		 * for partial write.
+ 		 */
+ 		set_buffer_new(bh);
++		set_buffer_mapped(bh);
+ 	}
+ 	return 0;
+ }

commit 6c6804fb2cef2d6aceb38b0eb0803210d77ff390
+Author: Andrew Lutomirski 
+Date:   Thu Mar 24 00:36:56 2011 -0400
+
+    perf symbols: Fix vsyscall symbol lookup
+    
+    Perf can't currently trace into the vsyscall page.  It looks like it was
+    meant to work.
+    
+    Tested on 2.6.38 and today's -git.
+    
+    The bug is easy to reproduce.  Compile this:
+    
+    int main()
+    {
+            int i;
+            struct timespec t;
+            for(i = 0; i < 10000000; i++)
+                    clock_gettime(CLOCK_MONOTONIC, &t);
+            return 0;
+    }
+    
+    and run it through perf record; perf report.  The top entry shows
+    "[unknown]" and you can't zoom in.
+    
+    It looks like there are two issues.  The first is a that a test for user
+    mode executing in kernel space is backwards.  (That's the first hunk
+    below).  The second (I think) is that something's wrong with the code
+    that generates lots of little struct dso objects for different sections
+    -- when it runs on vmlinux it results in bogus long_name values which
+    cause objdump to fail.
+    
+    Cc: Ingo Molnar 
+    Cc: Paul Mackerras 
+    Cc: Peter Zijlstra 
+    LPU-Reference: 
+    Signed-off-by: Andy Lutomirski 
+    Signed-off-by: Arnaldo Carvalho de Melo 
+
+diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
+index 2b15c362ef56..1023f67633a4 100644
+--- a/tools/perf/util/event.c
++++ b/tools/perf/util/event.c
+@@ -710,7 +710,7 @@ void thread__find_addr_map(struct thread *self,
+ 		 * in the whole kernel symbol list.
+ 		 */
+ 		if ((long long)al->addr < 0 &&
+-		    cpumode == PERF_RECORD_MISC_KERNEL &&
++		    cpumode == PERF_RECORD_MISC_USER &&
+ 		    machine && mg != &machine->kmaps) {
+ 			mg = &machine->kmaps;
+ 			goto try_again;
+diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
+index 17df793c8924..8f73907a959e 100644
+--- a/tools/perf/util/symbol.c
++++ b/tools/perf/util/symbol.c
+@@ -1196,6 +1196,8 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
+ 				if (curr_dso == NULL)
+ 					goto out_elf_end;
+ 				curr_dso->kernel = self->kernel;
++				curr_dso->long_name = self->long_name;
++				curr_dso->long_name_len = self->long_name_len;
+ 				curr_map = map__new2(start, curr_dso,
+ 						     map->type);
+ 				if (curr_map == NULL) {
+@@ -1842,6 +1844,7 @@ int dso__load_vmlinux(struct dso *self, struct map *map,
+ 	if (fd < 0)
+ 		return -1;
+ 
++	dso__set_long_name(self, (char *)vmlinux);
+ 	dso__set_loaded(self, map->type);
+ 	err = dso__load_sym(self, map, symfs_vmlinux, fd, filter, 0, 0);
+ 	close(fd);

commit 688f869ce3bdc892daa993534dc6df18c95df931
+Author: Theodore Ts'o 
+Date:   Wed Mar 16 17:16:31 2011 -0400
+
+    ext4: Initialize fsync transaction ids in ext4_new_inode()
+    
+    When allocating a new inode, we need to make sure i_sync_tid and
+    i_datasync_tid are initialized.  Otherwise, one or both of these two
+    values could be left initialized to zero, which could potentially
+    result in BUG_ON in jbd2_journal_commit_transaction.
+    
+    (This could happen by having journal->commit_request getting set to
+    zero, which could wake up the kjournald process even though there is
+    no running transaction, which then causes a BUG_ON via the
+    J_ASSERT(j_ruinning_transaction != NULL) statement.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 2fd3b0e41787..a679a482c986 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -1054,6 +1054,11 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
+ 		}
+ 	}
+ 
++	if (ext4_handle_valid(handle)) {
++		ei->i_sync_tid = handle->h_transaction->t_tid;
++		ei->i_datasync_tid = handle->h_transaction->t_tid;
++	}
++
+ 	err = ext4_mark_inode_dirty(handle, inode);
+ 	if (err) {
+ 		ext4_std_error(sb, err);

commit b616844310a6c8a4ab405d3436bbb6e53cfd852f
+Author: Theodore Ts'o 
+Date:   Mon Feb 28 13:12:38 2011 -0500
+
+    ext4: optimize ext4_bio_write_page() when no extent conversion is needed
+    
+    If no extent conversion is required, wake up any processes waiting for
+    the page's writeback to be complete and free the ext4_io_end structure
+    directly in ext4_end_bio() instead of dropping it on the linked list
+    (which requires taking a spinlock to queue and dequeue the io_end
+    structure), and waiting for the workqueue to do this work.
+    
+    This removes an extra scheduling delay before process waiting for an
+    fsync() to complete gets woken up, and it also reduces the CPU
+    overhead for a random write workload.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
+index d5c391ffad7a..0cfd03e19d7d 100644
+--- a/fs/ext4/page-io.c
++++ b/fs/ext4/page-io.c
+@@ -259,6 +259,11 @@ static void ext4_end_bio(struct bio *bio, int error)
+ 			     bi_sector >> (inode->i_blkbits - 9));
+ 	}
+ 
++	if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) {
++		ext4_free_io_end(io_end);
++		return;
++	}
++
+ 	/* Add the io_end to per-inode completed io list*/
+ 	spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags);
+ 	list_add_tail(&io_end->list, &EXT4_I(inode)->i_completed_io_list);

commit 4dd89fc6251a6bda2c18e71e7d266e983806579d
+Author: Theodore Ts'o 
+Date:   Sun Feb 27 17:23:47 2011 -0500
+
+    ext4: suppress verbose debugging information if malloc-debug is off
+    
+    If CONFIG_EXT4_DEBUG is enabled, then if a block allocation fails due
+    to disk being full, a verbose debugging message is printed, even if
+    the malloc-debug switch has not been enabled.  Suppress the debugging
+    message so that nothing is printed unless malloc-debug has been turned
+    on.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 66bee7274d6a..2f6f0dd08fca 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -3912,7 +3912,8 @@ static void ext4_mb_show_ac(struct ext4_allocation_context *ac)
+ 	struct super_block *sb = ac->ac_sb;
+ 	ext4_group_t ngroups, i;
+ 
+-	if (EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED)
++	if (!mb_enable_debug ||
++	    (EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED))
+ 		return;
+ 
+ 	printk(KERN_ERR "EXT4-fs: Can't allocate:"

commit a54aa76108619e5d8290b49081c2aaaeff5be9a2
+Author: Theodore Ts'o 
+Date:   Sun Feb 27 16:43:24 2011 -0500
+
+    ext4: don't leave PageWriteback set after memory failure
+    
+    In ext4_bio_write_page(), if the memory allocation for the struct
+    ext4_io_page fails, it returns with the page's PageWriteback flag set.
+    This will end up causing the page not to skip writeback in
+    WB_SYNC_NONE mode, and in WB_SYNC_ALL mode (i.e., on a sync, fsync, or
+    umount) the writeback daemon will get stuck forever on the
+    wait_on_page_writeback() function in write_cache_pages_da().
+    
+    Or, if journalling is enabled and the file gets deleted, it the
+    journal thread can get stuck in journal_finish_inode_data_buffers()
+    call to filemap_fdatawait().
+    
+    Another place where things can get hung up is in
+    truncate_inode_pages(), called out of ext4_evict_inode().
+    
+    Fix this by not setting PageWriteback until after we have successfully
+    allocated the struct ext4_io_page.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
+index 68d92a8f71d7..d5c391ffad7a 100644
+--- a/fs/ext4/page-io.c
++++ b/fs/ext4/page-io.c
+@@ -381,8 +381,6 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
+ 
+ 	BUG_ON(!PageLocked(page));
+ 	BUG_ON(PageWriteback(page));
+-	set_page_writeback(page);
+-	ClearPageError(page);
+ 
+ 	io_page = kmem_cache_alloc(io_page_cachep, GFP_NOFS);
+ 	if (!io_page) {
+@@ -393,6 +391,8 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
+ 	io_page->p_page = page;
+ 	atomic_set(&io_page->p_count, 1);
+ 	get_page(page);
++	set_page_writeback(page);
++	ClearPageError(page);
+ 
+ 	for (bh = head = page_buffers(page), block_start = 0;
+ 	     bh != head || !block_start;

commit 168fc0223c0e944957b1f31d88c2334fc904baf1
+Author: Theodore Ts'o 
+Date:   Sat Feb 26 14:09:20 2011 -0500
+
+    ext4: move setup of the mpd structure to write_cache_pages_da()
+    
+    Move the initialization of all of the fields of the mpd structure to
+    write_cache_pages_da().  This simplifies the code considerably.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index c2e6af338234..dcc2287433b6 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2714,7 +2714,8 @@ static int ext4_da_writepages_trans_blocks(struct inode *inode)
+ /*
+  * write_cache_pages_da - walk the list of dirty pages of the given
+  * address space and accumulate pages that need writing, and call
+- * mpage_da_map_and_submit to map the pages and then write them.
++ * mpage_da_map_and_submit to map a single contiguous memory region
++ * and then write them.
+  */
+ static int write_cache_pages_da(struct address_space *mapping,
+ 				struct writeback_control *wbc,
+@@ -2722,7 +2723,7 @@ static int write_cache_pages_da(struct address_space *mapping,
+ 				pgoff_t *done_index)
+ {
+ 	struct buffer_head	*bh, *head;
+-	struct inode		*inode = mpd->inode;
++	struct inode		*inode = mapping->host;
+ 	struct pagevec		pvec;
+ 	unsigned int		nr_pages;
+ 	sector_t		logical;
+@@ -2730,6 +2731,9 @@ static int write_cache_pages_da(struct address_space *mapping,
+ 	long			nr_to_write = wbc->nr_to_write;
+ 	int			i, tag, ret = 0;
+ 
++	memset(mpd, 0, sizeof(struct mpage_da_data));
++	mpd->wbc = wbc;
++	mpd->inode = inode;
+ 	pagevec_init(&pvec, 0);
+ 	index = wbc->range_start >> PAGE_CACHE_SHIFT;
+ 	end = wbc->range_end >> PAGE_CACHE_SHIFT;
+@@ -2794,16 +2798,8 @@ static int write_cache_pages_da(struct address_space *mapping,
+ 
+ 			BUG_ON(PageWriteback(page));
+ 
+-			if (mpd->next_page != page->index) {
+-				/*
+-				 * Start next extent of pages and blocks
+-				 */
++			if (mpd->next_page != page->index)
+ 				mpd->first_page = page->index;
+-				mpd->b_size = 0;
+-				mpd->b_state = 0;
+-				mpd->b_blocknr = 0;
+-			}
+-
+ 			mpd->next_page = page->index + 1;
+ 			logical = (sector_t) page->index <<
+ 				(PAGE_CACHE_SHIFT - inode->i_blkbits);
+@@ -2975,9 +2971,6 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 		wbc->nr_to_write = desired_nr_to_write;
+ 	}
+ 
+-	mpd.wbc = wbc;
+-	mpd.inode = mapping->host;
+-
+ retry:
+ 	if (wbc->sync_mode == WB_SYNC_ALL)
+ 		tag_pages_for_writeback(mapping, index, end);
+@@ -3008,14 +3001,6 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 		 * contiguous region of logical blocks that need
+ 		 * blocks to be allocated by ext4 and submit them.
+ 		 */
+-		mpd.b_size = 0;
+-		mpd.b_state = 0;
+-		mpd.b_blocknr = 0;
+-		mpd.first_page = 0;
+-		mpd.next_page = 0;
+-		mpd.io_done = 0;
+-		mpd.pages_written = 0;
+-		mpd.retval = 0;
+ 		ret = write_cache_pages_da(mapping, wbc, &mpd, &done_index);
+ 		/*
+ 		 * If we have a contiguous extent of pages and we

commit 78aaced3408141bb7c836f2db0ca435790399da5
+Author: Theodore Ts'o 
+Date:   Sat Feb 26 14:09:14 2011 -0500
+
+    ext4: don't lock the next page in write_cache_pages if not needed
+    
+    If we have accumulated a contiguous region of memory to be written
+    out, and the next page can added to this region, don't bother locking
+    (and then unlocking the page) before writing out the memory.  In the
+    unlikely event that the next page was being written back by some other
+    CPU, we can also skip waiting that page to finish writeback.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 617c9cbba182..c2e6af338234 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2761,6 +2761,16 @@ static int write_cache_pages_da(struct address_space *mapping,
+ 
+ 			*done_index = page->index + 1;
+ 
++			/*
++			 * If we can't merge this page, and we have
++			 * accumulated an contiguous region, write it
++			 */
++			if ((mpd->next_page != page->index) &&
++			    (mpd->next_page != mpd->first_page)) {
++				mpage_da_map_and_submit(mpd);
++				goto ret_extent_tail;
++			}
++
+ 			lock_page(page);
+ 
+ 			/*
+@@ -2784,24 +2794,7 @@ static int write_cache_pages_da(struct address_space *mapping,
+ 
+ 			BUG_ON(PageWriteback(page));
+ 
+-			/*
+-			 * Can we merge this page to current extent?
+-			 */
+ 			if (mpd->next_page != page->index) {
+-				/*
+-				 * Nope, we can't. So, we map
+-				 * non-allocated blocks and start IO
+-				 * on them
+-				 */
+-				if (mpd->next_page != mpd->first_page) {
+-					mpage_da_map_and_submit(mpd);
+-					/*
+-					 * skip rest of the page in the page_vec
+-					 */
+-					unlock_page(page);
+-					goto ret_extent_tail;
+-				}
+-
+ 				/*
+ 				 * Start next extent of pages and blocks
+ 				 */

commit ee6ecbcc5d73672217fdea420d182ecb0cdf310c
+Author: Theodore Ts'o 
+Date:   Sat Feb 26 14:08:11 2011 -0500
+
+    ext4: remove page_skipped hackery in ext4_da_writepages()
+    
+    Because the ext4 page writeback codepath had been prematurely calling
+    clear_page_dirty_for_io(), if it turned out that a particular page
+    couldn't be written out during a particular pass of
+    write_cache_pages_da(), the page would have to get redirtied by
+    calling redirty_pages_for_writeback().  Not only was this wasted work,
+    but redirty_page_for_writeback() would increment wbc->pages_skipped to
+    signal to writeback_sb_inodes() that buffers were locked, and that it
+    should skip this inode until later.
+    
+    Since this signal was incorrect in ext4's case --- which was caused by
+    ext4's historically incorrect use of write_cache_pages() ---
+    ext4_da_writepages() saved and restored wbc->skipped_pages to avoid
+    confusing writeback_sb_inodes().
+    
+    Now that we've fixed ext4 to call clear_page_dirty_for_io() right
+    before initiating the page I/O, we can nuke the page_skipped
+    save/restore hackery, and breathe a sigh of relief.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index ae6e2f43d873..617c9cbba182 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2900,7 +2900,6 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 	struct mpage_da_data mpd;
+ 	struct inode *inode = mapping->host;
+ 	int pages_written = 0;
+-	long pages_skipped;
+ 	unsigned int max_pages;
+ 	int range_cyclic, cycled = 1, io_done = 0;
+ 	int needed_blocks, ret = 0;
+@@ -2986,8 +2985,6 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 	mpd.wbc = wbc;
+ 	mpd.inode = mapping->host;
+ 
+-	pages_skipped = wbc->pages_skipped;
+-
+ retry:
+ 	if (wbc->sync_mode == WB_SYNC_ALL)
+ 		tag_pages_for_writeback(mapping, index, end);
+@@ -3047,7 +3044,6 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 			 * and try again
+ 			 */
+ 			jbd2_journal_force_commit_nested(sbi->s_journal);
+-			wbc->pages_skipped = pages_skipped;
+ 			ret = 0;
+ 		} else if (ret == MPAGE_DA_EXTENT_TAIL) {
+ 			/*
+@@ -3055,7 +3051,6 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 			 * rest of the pages
+ 			 */
+ 			pages_written += mpd.pages_written;
+-			wbc->pages_skipped = pages_skipped;
+ 			ret = 0;
+ 			io_done = 1;
+ 		} else if (wbc->nr_to_write)
+@@ -3073,11 +3068,6 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 		wbc->range_end  = mapping->writeback_index - 1;
+ 		goto retry;
+ 	}
+-	if (pages_skipped != wbc->pages_skipped)
+-		ext4_msg(inode->i_sb, KERN_CRIT,
+-			 "This should not happen leaving %s "
+-			 "with nr_to_write = %ld ret = %d",
+-			 __func__, wbc->nr_to_write, ret);
+ 
+ 	/* Update index */
+ 	wbc->range_cyclic = range_cyclic;

commit 9749895644a817cfd28a535bc3ae60e4267bdc50
+Author: Theodore Ts'o 
+Date:   Sat Feb 26 14:08:01 2011 -0500
+
+    ext4: clear the dirty bit for a page in writeback at the last minute
+    
+    Move when we call clear_page_dirty_for_io() to just before we actually
+    write the page.  This simplifies the code somewhat, and avoids marking
+    pages as clean and then needing to remark them as dirty later.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 1e718e87f466..ae6e2f43d873 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2060,7 +2060,7 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd,
+ 		if (nr_pages == 0)
+ 			break;
+ 		for (i = 0; i < nr_pages; i++) {
+-			int commit_write = 0, redirty_page = 0;
++			int commit_write = 0, skip_page = 0;
+ 			struct page *page = pvec.pages[i];
+ 
+ 			index = page->index;
+@@ -2086,14 +2086,12 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd,
+ 			 * If the page does not have buffers (for
+ 			 * whatever reason), try to create them using
+ 			 * __block_write_begin.  If this fails,
+-			 * redirty the page and move on.
++			 * skip the page and move on.
+ 			 */
+ 			if (!page_has_buffers(page)) {
+ 				if (__block_write_begin(page, 0, len,
+ 						noalloc_get_block_write)) {
+-				redirty_page:
+-					redirty_page_for_writepage(mpd->wbc,
+-								   page);
++				skip_page:
+ 					unlock_page(page);
+ 					continue;
+ 				}
+@@ -2104,7 +2102,7 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd,
+ 			block_start = 0;
+ 			do {
+ 				if (!bh)
+-					goto redirty_page;
++					goto skip_page;
+ 				if (map && (cur_logical >= map->m_lblk) &&
+ 				    (cur_logical <= (map->m_lblk +
+ 						     (map->m_len - 1)))) {
+@@ -2120,22 +2118,23 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd,
+ 					clear_buffer_unwritten(bh);
+ 				}
+ 
+-				/* redirty page if block allocation undone */
++				/* skip page if block allocation undone */
+ 				if (buffer_delay(bh) || buffer_unwritten(bh))
+-					redirty_page = 1;
++					skip_page = 1;
+ 				bh = bh->b_this_page;
+ 				block_start += bh->b_size;
+ 				cur_logical++;
+ 				pblock++;
+ 			} while (bh != page_bufs);
+ 
+-			if (redirty_page)
+-				goto redirty_page;
++			if (skip_page)
++				goto skip_page;
+ 
+ 			if (commit_write)
+ 				/* mark the buffer_heads as dirty & uptodate */
+ 				block_commit_write(page, 0, len);
+ 
++			clear_page_dirty_for_io(page);
+ 			/*
+ 			 * Delalloc doesn't support data journalling,
+ 			 * but eventually maybe we'll lift this
+@@ -2277,9 +2276,8 @@ static void mpage_da_map_and_submit(struct mpage_da_data *mpd)
+ 		err = blks;
+ 		/*
+ 		 * If get block returns EAGAIN or ENOSPC and there
+-		 * appears to be free blocks we will call
+-		 * ext4_writepage() for all of the pages which will
+-		 * just redirty the pages.
++		 * appears to be free blocks we will just let
++		 * mpage_da_submit_io() unlock all of the pages.
+ 		 */
+ 		if (err == -EAGAIN)
+ 			goto submit_io;
+@@ -2777,7 +2775,6 @@ static int write_cache_pages_da(struct address_space *mapping,
+ 			    (PageWriteback(page) &&
+ 			     (wbc->sync_mode == WB_SYNC_NONE)) ||
+ 			    unlikely(page->mapping != mapping)) {
+-			continue_unlock:
+ 				unlock_page(page);
+ 				continue;
+ 			}
+@@ -2786,8 +2783,6 @@ static int write_cache_pages_da(struct address_space *mapping,
+ 				wait_on_page_writeback(page);
+ 
+ 			BUG_ON(PageWriteback(page));
+-			if (!clear_page_dirty_for_io(page))
+-				goto continue_unlock;
+ 
+ 			/*
+ 			 * Can we merge this page to current extent?
+@@ -2803,7 +2798,6 @@ static int write_cache_pages_da(struct address_space *mapping,
+ 					/*
+ 					 * skip rest of the page in the page_vec
+ 					 */
+-					redirty_page_for_writepage(wbc, page);
+ 					unlock_page(page);
+ 					goto ret_extent_tail;
+ 				}

commit 4f01b02c8c4e4111bd1adbcafb5741e8e991f5fd
+Author: Theodore Ts'o 
+Date:   Sat Feb 26 14:07:37 2011 -0500
+
+    ext4: simple cleanups to write_cache_pages_da()
+    
+    Eliminate duplicate code, unneeded variables, etc., to make it easier
+    to understand the code.  No behavioral changes were made in this patch.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index fcd08ca0643b..1e718e87f466 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2723,17 +2723,14 @@ static int write_cache_pages_da(struct address_space *mapping,
+ 				struct mpage_da_data *mpd,
+ 				pgoff_t *done_index)
+ {
+-	struct inode *inode = mpd->inode;
+-	struct buffer_head *bh, *head;
+-	sector_t logical;
+-	int ret = 0;
+-	int done = 0;
+-	struct pagevec pvec;
+-	unsigned nr_pages;
+-	pgoff_t index;
+-	pgoff_t end;		/* Inclusive */
+-	long nr_to_write = wbc->nr_to_write;
+-	int tag;
++	struct buffer_head	*bh, *head;
++	struct inode		*inode = mpd->inode;
++	struct pagevec		pvec;
++	unsigned int		nr_pages;
++	sector_t		logical;
++	pgoff_t			index, end;
++	long			nr_to_write = wbc->nr_to_write;
++	int			i, tag, ret = 0;
+ 
+ 	pagevec_init(&pvec, 0);
+ 	index = wbc->range_start >> PAGE_CACHE_SHIFT;
+@@ -2745,13 +2742,11 @@ static int write_cache_pages_da(struct address_space *mapping,
+ 		tag = PAGECACHE_TAG_DIRTY;
+ 
+ 	*done_index = index;
+-	while (!done && (index <= end)) {
+-		int i;
+-
++	while (index <= end) {
+ 		nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, tag,
+ 			      min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1);
+ 		if (nr_pages == 0)
+-			break;
++			return 0;
+ 
+ 		for (i = 0; i < nr_pages; i++) {
+ 			struct page *page = pvec.pages[i];
+@@ -2763,47 +2758,37 @@ static int write_cache_pages_da(struct address_space *mapping,
+ 			 * mapping. However, page->index will not change
+ 			 * because we have a reference on the page.
+ 			 */
+-			if (page->index > end) {
+-				done = 1;
+-				break;
+-			}
++			if (page->index > end)
++				goto out;
+ 
+ 			*done_index = page->index + 1;
+ 
+ 			lock_page(page);
+ 
+ 			/*
+-			 * Page truncated or invalidated. We can freely skip it
+-			 * then, even for data integrity operations: the page
+-			 * has disappeared concurrently, so there could be no
+-			 * real expectation of this data interity operation
+-			 * even if there is now a new, dirty page at the same
+-			 * pagecache address.
++			 * If the page is no longer dirty, or its
++			 * mapping no longer corresponds to inode we
++			 * are writing (which means it has been
++			 * truncated or invalidated), or the page is
++			 * already under writeback and we are not
++			 * doing a data integrity writeback, skip the page
+ 			 */
+-			if (unlikely(page->mapping != mapping)) {
+-continue_unlock:
++			if (!PageDirty(page) ||
++			    (PageWriteback(page) &&
++			     (wbc->sync_mode == WB_SYNC_NONE)) ||
++			    unlikely(page->mapping != mapping)) {
++			continue_unlock:
+ 				unlock_page(page);
+ 				continue;
+ 			}
+ 
+-			if (!PageDirty(page)) {
+-				/* someone wrote it for us */
+-				goto continue_unlock;
+-			}
+-
+-			if (PageWriteback(page)) {
+-				if (wbc->sync_mode != WB_SYNC_NONE)
+-					wait_on_page_writeback(page);
+-				else
+-					goto continue_unlock;
+-			}
++			if (PageWriteback(page))
++				wait_on_page_writeback(page);
+ 
+ 			BUG_ON(PageWriteback(page));
+ 			if (!clear_page_dirty_for_io(page))
+ 				goto continue_unlock;
+ 
+-			/* BEGIN __mpage_da_writepage */
+-
+ 			/*
+ 			 * Can we merge this page to current extent?
+ 			 */
+@@ -2820,8 +2805,7 @@ static int write_cache_pages_da(struct address_space *mapping,
+ 					 */
+ 					redirty_page_for_writepage(wbc, page);
+ 					unlock_page(page);
+-					ret = MPAGE_DA_EXTENT_TAIL;
+-					goto out;
++					goto ret_extent_tail;
+ 				}
+ 
+ 				/*
+@@ -2838,15 +2822,15 @@ static int write_cache_pages_da(struct address_space *mapping,
+ 				(PAGE_CACHE_SHIFT - inode->i_blkbits);
+ 
+ 			if (!page_has_buffers(page)) {
+-				mpage_add_bh_to_extent(mpd, logical, PAGE_CACHE_SIZE,
++				mpage_add_bh_to_extent(mpd, logical,
++						       PAGE_CACHE_SIZE,
+ 						       (1 << BH_Dirty) | (1 << BH_Uptodate));
+-				if (mpd->io_done) {
+-					ret = MPAGE_DA_EXTENT_TAIL;
+-					goto out;
+-				}
++				if (mpd->io_done)
++					goto ret_extent_tail;
+ 			} else {
+ 				/*
+-				 * Page with regular buffer heads, just add all dirty ones
++				 * Page with regular buffer heads,
++				 * just add all dirty ones
+ 				 */
+ 				head = page_buffers(page);
+ 				bh = head;
+@@ -2862,18 +2846,19 @@ static int write_cache_pages_da(struct address_space *mapping,
+ 						mpage_add_bh_to_extent(mpd, logical,
+ 								       bh->b_size,
+ 								       bh->b_state);
+-						if (mpd->io_done) {
+-							ret = MPAGE_DA_EXTENT_TAIL;
+-							goto out;
+-						}
++						if (mpd->io_done)
++							goto ret_extent_tail;
+ 					} else if (buffer_dirty(bh) && (buffer_mapped(bh))) {
+ 						/*
+-						 * mapped dirty buffer. We need to update
+-						 * the b_state because we look at
+-						 * b_state in mpage_da_map_blocks. We don't
+-						 * update b_size because if we find an
+-						 * unmapped buffer_head later we need to
+-						 * use the b_state flag of that buffer_head.
++						 * mapped dirty buffer. We need
++						 * to update the b_state
++						 * because we look at b_state
++						 * in mpage_da_map_blocks.  We
++						 * don't update b_size because
++						 * if we find an unmapped
++						 * buffer_head later we need to
++						 * use the b_state flag of that
++						 * buffer_head.
+ 						 */
+ 						if (mpd->b_size == 0)
+ 							mpd->b_state = bh->b_state & BH_FLAGS;
+@@ -2882,14 +2867,10 @@ static int write_cache_pages_da(struct address_space *mapping,
+ 				} while ((bh = bh->b_this_page) != head);
+ 			}
+ 
+-			ret = 0;
+-
+-			/* END __mpage_da_writepage */
+-
+ 			if (nr_to_write > 0) {
+ 				nr_to_write--;
+ 				if (nr_to_write == 0 &&
+-				    wbc->sync_mode == WB_SYNC_NONE) {
++				    wbc->sync_mode == WB_SYNC_NONE)
+ 					/*
+ 					 * We stop writing back only if we are
+ 					 * not doing integrity sync. In case of
+@@ -2900,15 +2881,15 @@ static int write_cache_pages_da(struct address_space *mapping,
+ 					 * pages, but have not synced all of the
+ 					 * old dirty pages.
+ 					 */
+-					done = 1;
+-					break;
+-				}
++					goto out;
+ 			}
+ 		}
+ 		pagevec_release(&pvec);
+ 		cond_resched();
+ 	}
+-	return ret;
++	return 0;
++ret_extent_tail:
++	ret = MPAGE_DA_EXTENT_TAIL;
+ out:
+ 	pagevec_release(&pvec);
+ 	cond_resched();

commit 8eb9e5ce211de1b98bc84e93258b7db0860a103c
+Author: Theodore Ts'o 
+Date:   Sat Feb 26 14:07:31 2011 -0500
+
+    ext4: fold __mpage_da_writepage() into write_cache_pages_da()
+    
+    Fold the __mpage_da_writepage() function into write_cache_pages_da().
+    This will give us opportunities to clean up and simplify the resulting
+    code.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index e878c3a7aaf0..fcd08ca0643b 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2437,102 +2437,6 @@ static int ext4_bh_delay_or_unwritten(handle_t *handle, struct buffer_head *bh)
+ 	return (buffer_delay(bh) || buffer_unwritten(bh)) && buffer_dirty(bh);
+ }
+ 
+-/*
+- * __mpage_da_writepage - finds extent of pages and blocks
+- *
+- * @page: page to consider
+- * @wbc: not used, we just follow rules
+- * @data: context
+- *
+- * The function finds extents of pages and scan them for all blocks.
+- */
+-static int __mpage_da_writepage(struct page *page,
+-				struct writeback_control *wbc,
+-				struct mpage_da_data *mpd)
+-{
+-	struct inode *inode = mpd->inode;
+-	struct buffer_head *bh, *head;
+-	sector_t logical;
+-
+-	/*
+-	 * Can we merge this page to current extent?
+-	 */
+-	if (mpd->next_page != page->index) {
+-		/*
+-		 * Nope, we can't. So, we map non-allocated blocks
+-		 * and start IO on them
+-		 */
+-		if (mpd->next_page != mpd->first_page) {
+-			mpage_da_map_and_submit(mpd);
+-			/*
+-			 * skip rest of the page in the page_vec
+-			 */
+-			redirty_page_for_writepage(wbc, page);
+-			unlock_page(page);
+-			return MPAGE_DA_EXTENT_TAIL;
+-		}
+-
+-		/*
+-		 * Start next extent of pages ...
+-		 */
+-		mpd->first_page = page->index;
+-
+-		/*
+-		 * ... and blocks
+-		 */
+-		mpd->b_size = 0;
+-		mpd->b_state = 0;
+-		mpd->b_blocknr = 0;
+-	}
+-
+-	mpd->next_page = page->index + 1;
+-	logical = (sector_t) page->index <<
+-		  (PAGE_CACHE_SHIFT - inode->i_blkbits);
+-
+-	if (!page_has_buffers(page)) {
+-		mpage_add_bh_to_extent(mpd, logical, PAGE_CACHE_SIZE,
+-				       (1 << BH_Dirty) | (1 << BH_Uptodate));
+-		if (mpd->io_done)
+-			return MPAGE_DA_EXTENT_TAIL;
+-	} else {
+-		/*
+-		 * Page with regular buffer heads, just add all dirty ones
+-		 */
+-		head = page_buffers(page);
+-		bh = head;
+-		do {
+-			BUG_ON(buffer_locked(bh));
+-			/*
+-			 * We need to try to allocate
+-			 * unmapped blocks in the same page.
+-			 * Otherwise we won't make progress
+-			 * with the page in ext4_writepage
+-			 */
+-			if (ext4_bh_delay_or_unwritten(NULL, bh)) {
+-				mpage_add_bh_to_extent(mpd, logical,
+-						       bh->b_size,
+-						       bh->b_state);
+-				if (mpd->io_done)
+-					return MPAGE_DA_EXTENT_TAIL;
+-			} else if (buffer_dirty(bh) && (buffer_mapped(bh))) {
+-				/*
+-				 * mapped dirty buffer. We need to update
+-				 * the b_state because we look at
+-				 * b_state in mpage_da_map_blocks. We don't
+-				 * update b_size because if we find an
+-				 * unmapped buffer_head later we need to
+-				 * use the b_state flag of that buffer_head.
+-				 */
+-				if (mpd->b_size == 0)
+-					mpd->b_state = bh->b_state & BH_FLAGS;
+-			}
+-			logical++;
+-		} while ((bh = bh->b_this_page) != head);
+-	}
+-
+-	return 0;
+-}
+-
+ /*
+  * This is a special get_blocks_t callback which is used by
+  * ext4_da_write_begin().  It will either return mapped block or
+@@ -2811,18 +2715,17 @@ static int ext4_da_writepages_trans_blocks(struct inode *inode)
+ 
+ /*
+  * write_cache_pages_da - walk the list of dirty pages of the given
+- * address space and call the callback function (which usually writes
+- * the pages).
+- *
+- * This is a forked version of write_cache_pages().  Differences:
+- *	Range cyclic is ignored.
+- *	no_nrwrite_index_update is always presumed true
++ * address space and accumulate pages that need writing, and call
++ * mpage_da_map_and_submit to map the pages and then write them.
+  */
+ static int write_cache_pages_da(struct address_space *mapping,
+ 				struct writeback_control *wbc,
+ 				struct mpage_da_data *mpd,
+ 				pgoff_t *done_index)
+ {
++	struct inode *inode = mpd->inode;
++	struct buffer_head *bh, *head;
++	sector_t logical;
+ 	int ret = 0;
+ 	int done = 0;
+ 	struct pagevec pvec;
+@@ -2899,17 +2802,90 @@ static int write_cache_pages_da(struct address_space *mapping,
+ 			if (!clear_page_dirty_for_io(page))
+ 				goto continue_unlock;
+ 
+-			ret = __mpage_da_writepage(page, wbc, mpd);
+-			if (unlikely(ret)) {
+-				if (ret == AOP_WRITEPAGE_ACTIVATE) {
++			/* BEGIN __mpage_da_writepage */
++
++			/*
++			 * Can we merge this page to current extent?
++			 */
++			if (mpd->next_page != page->index) {
++				/*
++				 * Nope, we can't. So, we map
++				 * non-allocated blocks and start IO
++				 * on them
++				 */
++				if (mpd->next_page != mpd->first_page) {
++					mpage_da_map_and_submit(mpd);
++					/*
++					 * skip rest of the page in the page_vec
++					 */
++					redirty_page_for_writepage(wbc, page);
+ 					unlock_page(page);
+-					ret = 0;
+-				} else {
+-					done = 1;
+-					break;
++					ret = MPAGE_DA_EXTENT_TAIL;
++					goto out;
+ 				}
++
++				/*
++				 * Start next extent of pages and blocks
++				 */
++				mpd->first_page = page->index;
++				mpd->b_size = 0;
++				mpd->b_state = 0;
++				mpd->b_blocknr = 0;
++			}
++
++			mpd->next_page = page->index + 1;
++			logical = (sector_t) page->index <<
++				(PAGE_CACHE_SHIFT - inode->i_blkbits);
++
++			if (!page_has_buffers(page)) {
++				mpage_add_bh_to_extent(mpd, logical, PAGE_CACHE_SIZE,
++						       (1 << BH_Dirty) | (1 << BH_Uptodate));
++				if (mpd->io_done) {
++					ret = MPAGE_DA_EXTENT_TAIL;
++					goto out;
++				}
++			} else {
++				/*
++				 * Page with regular buffer heads, just add all dirty ones
++				 */
++				head = page_buffers(page);
++				bh = head;
++				do {
++					BUG_ON(buffer_locked(bh));
++					/*
++					 * We need to try to allocate
++					 * unmapped blocks in the same page.
++					 * Otherwise we won't make progress
++					 * with the page in ext4_writepage
++					 */
++					if (ext4_bh_delay_or_unwritten(NULL, bh)) {
++						mpage_add_bh_to_extent(mpd, logical,
++								       bh->b_size,
++								       bh->b_state);
++						if (mpd->io_done) {
++							ret = MPAGE_DA_EXTENT_TAIL;
++							goto out;
++						}
++					} else if (buffer_dirty(bh) && (buffer_mapped(bh))) {
++						/*
++						 * mapped dirty buffer. We need to update
++						 * the b_state because we look at
++						 * b_state in mpage_da_map_blocks. We don't
++						 * update b_size because if we find an
++						 * unmapped buffer_head later we need to
++						 * use the b_state flag of that buffer_head.
++						 */
++						if (mpd->b_size == 0)
++							mpd->b_state = bh->b_state & BH_FLAGS;
++					}
++					logical++;
++				} while ((bh = bh->b_this_page) != head);
+ 			}
+ 
++			ret = 0;
++
++			/* END __mpage_da_writepage */
++
+ 			if (nr_to_write > 0) {
+ 				nr_to_write--;
+ 				if (nr_to_write == 0 &&
+@@ -2933,6 +2909,10 @@ static int write_cache_pages_da(struct address_space *mapping,
+ 		cond_resched();
+ 	}
+ 	return ret;
++out:
++	pagevec_release(&pvec);
++	cond_resched();
++	return ret;
+ }
+ 
+ 
+@@ -3059,13 +3039,9 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 		}
+ 
+ 		/*
+-		 * Now call __mpage_da_writepage to find the next
++		 * Now call write_cache_pages_da() to find the next
+ 		 * contiguous region of logical blocks that need
+-		 * blocks to be allocated by ext4.  We don't actually
+-		 * submit the blocks for I/O here, even though
+-		 * write_cache_pages thinks it will, and will set the
+-		 * pages as clean for write before calling
+-		 * __mpage_da_writepage().
++		 * blocks to be allocated by ext4 and submit them.
+ 		 */
+ 		mpd.b_size = 0;
+ 		mpd.b_state = 0;

commit 6fd7a46781999c32f423025767e43b349b967d57
+Author: Theodore Ts'o 
+Date:   Sat Feb 26 13:53:09 2011 -0500
+
+    ext4: enable mblk_io_submit by default
+    
+    Now that we've fixed the file corruption bug in commit d50bdd5aa55,
+    it's time to enable mblk_io_submit by default.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index a665d2fb70c1..33c398785e53 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1038,8 +1038,8 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
+ 	    !(def_mount_opts & EXT4_DEFM_NODELALLOC))
+ 		seq_puts(seq, ",nodelalloc");
+ 
+-	if (test_opt(sb, MBLK_IO_SUBMIT))
+-		seq_puts(seq, ",mblk_io_submit");
++	if (!test_opt(sb, MBLK_IO_SUBMIT))
++		seq_puts(seq, ",nomblk_io_submit");
+ 	if (sbi->s_stripe)
+ 		seq_printf(seq, ",stripe=%lu", sbi->s_stripe);
+ 	/*
+@@ -3099,6 +3099,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ #ifdef CONFIG_EXT4_FS_POSIX_ACL
+ 	set_opt(sb, POSIX_ACL);
+ #endif
++	set_opt(sb, MBLK_IO_SUBMIT);
+ 	if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_DATA)
+ 		set_opt(sb, JOURNAL_DATA);
+ 	else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_ORDERED)

commit da488945f4bf4096f4ab6091938469bd8822cfec
+Author: Theodore Ts'o 
+Date:   Mon Feb 21 20:39:58 2011 -0500
+
+    ext4: fix compile warnings with EXT4FS_DEBUG enabled
+    
+    Compile 2.6.38-rc1 with turning EXT4FS_DEBUG on,
+    we get following compile warnings. This patch fixes them.
+    
+      CC      fs/ext4/hash.o
+      CC      fs/ext4/resize.o
+    fs/ext4/resize.c: In function 'setup_new_group_blocks':
+    fs/ext4/resize.c:233:2: warning: format '%#04llx' expects type 'long long
+    unsigned int', but argument 3 has type 'long unsigned int'
+    fs/ext4/resize.c:251:2: warning: format '%#04llx' expects type 'long long
+    unsigned int', but argument 3 has type 'long unsigned int'
+      CC      fs/ext4/extents.o
+      CC      fs/ext4/ext4_jbd2.o
+      CC      fs/ext4/migrate.o
+    
+    Reported-by: Akira Fujita 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 3ecc6e45d2f9..66fec4ee76fa 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -230,7 +230,7 @@ static int setup_new_group_blocks(struct super_block *sb,
+ 	}
+ 
+ 	/* Zero out all of the reserved backup group descriptor table blocks */
+-	ext4_debug("clear inode table blocks %#04llx -> %#04llx\n",
++	ext4_debug("clear inode table blocks %#04llx -> %#04lx\n",
+ 			block, sbi->s_itb_per_group);
+ 	err = sb_issue_zeroout(sb, gdblocks + start + 1, reserved_gdb,
+ 			       GFP_NOFS);
+@@ -248,7 +248,7 @@ static int setup_new_group_blocks(struct super_block *sb,
+ 
+ 	/* Zero out all of the inode table blocks */
+ 	block = input->inode_table;
+-	ext4_debug("clear inode table blocks %#04llx -> %#04llx\n",
++	ext4_debug("clear inode table blocks %#04llx -> %#04lx\n",
+ 			block, sbi->s_itb_per_group);
+ 	err = sb_issue_zeroout(sb, block, sbi->s_itb_per_group, GFP_NOFS);
+ 	if (err)

commit e44718318004a5618d1dfe2d080e2862532d8e5f
+Author: Theodore Ts'o 
+Date:   Sat Feb 12 08:18:24 2011 -0500
+
+    jbd2: call __jbd2_log_start_commit with j_state_lock write locked
+    
+    On an SMP ARM system running ext4, I've received a report that the
+    first J_ASSERT in jbd2_journal_commit_transaction has been triggering:
+    
+            J_ASSERT(journal->j_running_transaction != NULL);
+    
+    While investigating possible causes for this problem, I noticed that
+    __jbd2_log_start_commit() is getting called with j_state_lock only
+    read-locked, in spite of the fact that it's possible for it might
+    j_commit_request.  Fix this by grabbing the necessary information so
+    we can test to see if we need to start a new transaction before
+    dropping the read lock, and then calling jbd2_log_start_commit() which
+    will grab the write lock.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 9e4686900f18..97e73469b2c4 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -473,7 +473,8 @@ int __jbd2_log_space_left(journal_t *journal)
+ }
+ 
+ /*
+- * Called under j_state_lock.  Returns true if a transaction commit was started.
++ * Called with j_state_lock locked for writing.
++ * Returns true if a transaction commit was started.
+  */
+ int __jbd2_log_start_commit(journal_t *journal, tid_t target)
+ {
+@@ -520,11 +521,13 @@ int jbd2_journal_force_commit_nested(journal_t *journal)
+ {
+ 	transaction_t *transaction = NULL;
+ 	tid_t tid;
++	int need_to_start = 0;
+ 
+ 	read_lock(&journal->j_state_lock);
+ 	if (journal->j_running_transaction && !current->journal_info) {
+ 		transaction = journal->j_running_transaction;
+-		__jbd2_log_start_commit(journal, transaction->t_tid);
++		if (!tid_geq(journal->j_commit_request, transaction->t_tid))
++			need_to_start = 1;
+ 	} else if (journal->j_committing_transaction)
+ 		transaction = journal->j_committing_transaction;
+ 
+@@ -535,6 +538,8 @@ int jbd2_journal_force_commit_nested(journal_t *journal)
+ 
+ 	tid = transaction->t_tid;
+ 	read_unlock(&journal->j_state_lock);
++	if (need_to_start)
++		jbd2_log_start_commit(journal, tid);
+ 	jbd2_log_wait_commit(journal, tid);
+ 	return 1;
+ }
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index faad2bd787c7..1d1191050f99 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -117,10 +117,10 @@ static inline void update_t_max_wait(transaction_t *transaction)
+ static int start_this_handle(journal_t *journal, handle_t *handle,
+ 			     int gfp_mask)
+ {
+-	transaction_t *transaction;
+-	int needed;
+-	int nblocks = handle->h_buffer_credits;
+-	transaction_t *new_transaction = NULL;
++	transaction_t	*transaction, *new_transaction = NULL;
++	tid_t		tid;
++	int		needed, need_to_start;
++	int		nblocks = handle->h_buffer_credits;
+ 
+ 	if (nblocks > journal->j_max_transaction_buffers) {
+ 		printk(KERN_ERR "JBD: %s wants too many credits (%d > %d)\n",
+@@ -222,8 +222,11 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
+ 		atomic_sub(nblocks, &transaction->t_outstanding_credits);
+ 		prepare_to_wait(&journal->j_wait_transaction_locked, &wait,
+ 				TASK_UNINTERRUPTIBLE);
+-		__jbd2_log_start_commit(journal, transaction->t_tid);
++		tid = transaction->t_tid;
++		need_to_start = !tid_geq(journal->j_commit_request, tid);
+ 		read_unlock(&journal->j_state_lock);
++		if (need_to_start)
++			jbd2_log_start_commit(journal, tid);
+ 		schedule();
+ 		finish_wait(&journal->j_wait_transaction_locked, &wait);
+ 		goto repeat;
+@@ -442,7 +445,8 @@ int jbd2__journal_restart(handle_t *handle, int nblocks, int gfp_mask)
+ {
+ 	transaction_t *transaction = handle->h_transaction;
+ 	journal_t *journal = transaction->t_journal;
+-	int ret;
++	tid_t		tid;
++	int		need_to_start, ret;
+ 
+ 	/* If we've had an abort of any type, don't even think about
+ 	 * actually doing the restart! */
+@@ -465,8 +469,11 @@ int jbd2__journal_restart(handle_t *handle, int nblocks, int gfp_mask)
+ 	spin_unlock(&transaction->t_handle_lock);
+ 
+ 	jbd_debug(2, "restarting handle %p\n", handle);
+-	__jbd2_log_start_commit(journal, transaction->t_tid);
++	tid = transaction->t_tid;
++	need_to_start = !tid_geq(journal->j_commit_request, tid);
+ 	read_unlock(&journal->j_state_lock);
++	if (need_to_start)
++		jbd2_log_start_commit(journal, tid);
+ 
+ 	lock_map_release(&handle->h_lockdep_map);
+ 	handle->h_buffer_credits = nblocks;

commit dd68314ccf3fb918c1fb6471817edbc60ece4b52
+Author: Theodore Ts'o 
+Date:   Thu Feb 3 14:33:49 2011 -0500
+
+    ext4: fix up ext4 error handling
+    
+    Make sure we the correct cleanup happens if we die while trying to
+    load the ext4 file system.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 4898cb1ff606..86b05486dc63 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4810,13 +4810,17 @@ static int __init ext4_init_fs(void)
+ 		return err;
+ 	err = ext4_init_system_zone();
+ 	if (err)
+-		goto out5;
++		goto out7;
+ 	ext4_kset = kset_create_and_add("ext4", NULL, fs_kobj);
+ 	if (!ext4_kset)
+-		goto out4;
++		goto out6;
+ 	ext4_proc_root = proc_mkdir("fs/ext4", NULL);
++	if (!ext4_proc_root)
++		goto out5;
+ 
+ 	err = ext4_init_feat_adverts();
++	if (err)
++		goto out4;
+ 
+ 	err = ext4_init_mballoc();
+ 	if (err)
+@@ -4847,11 +4851,13 @@ static int __init ext4_init_fs(void)
+ 	ext4_exit_mballoc();
+ out3:
+ 	ext4_exit_feat_adverts();
++out4:
+ 	remove_proc_entry("fs/ext4", NULL);
++out5:
+ 	kset_unregister(ext4_kset);
+-out4:
++out6:
+ 	ext4_exit_system_zone();
+-out5:
++out7:
+ 	ext4_exit_pageio();
+ 	return err;
+ }

commit 0a2179b169089f871e071c74316371ed43e6c8eb
+Author: Theodore Ts'o 
+Date:   Tue Jan 11 14:42:29 2011 -0500
+
+    ext4: revert buggy trim overflow patch
+    
+    This reverts commit 4f531501e44: ext4: fix possible overflow in
+    ext4_trim_fs()
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index cd5214f75397..cc1297e15f1b 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -4804,7 +4804,6 @@ ext4_grpblk_t ext4_trim_all_free(struct super_block *sb, struct ext4_buddy *e4b,
+ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
+ {
+ 	struct ext4_buddy e4b;
+-	ext4_fsblk_t blocks_count = ext4_blocks_count(EXT4_SB(sb)->s_es);
+ 	ext4_group_t first_group, last_group;
+ 	ext4_group_t group, ngroups = ext4_get_groups_count(sb);
+ 	ext4_grpblk_t cnt = 0, first_block, last_block;
+@@ -4816,11 +4815,6 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
+ 	minlen = range->minlen >> sb->s_blocksize_bits;
+ 	trimmed = 0;
+ 
+-	if (start >= blocks_count)
+-		return -EINVAL;
+-	if (start + len > blocks_count)
+-		len = blocks_count - start;
+-
+ 	if (unlikely(minlen > EXT4_BLOCKS_PER_GROUP(sb)))
+ 		return -EINVAL;
+ 

commit 1c5b9e9065567876c2d4a7a16d78f0fed154a5bf
+Author: Theodore Ts'o 
+Date:   Mon Jan 10 12:51:28 2011 -0500
+
+    ext4: fix memory leak in ext4_free_branches
+    
+    Commit 40389687 moved a call to ext4_forget() out of
+    ext4_free_branches and let ext4_free_blocks() handle calling
+    bforget().  But that change unfortunately did not replace the call to
+    ext4_forget() with brelse(), which was needed to drop the in-use count
+    of the indirect block's buffer head, which lead to a memory leak when
+    deleting files that used indirect blocks.  Fix this.
+    
+    Thanks to Hugh Dickins for pointing this out.
+    
+    Cc: stable@kernel.org
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 84b616269265..e80fc513eacc 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4378,6 +4378,7 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
+ 					(__le32 *) bh->b_data,
+ 					(__le32 *) bh->b_data + addr_per_block,
+ 					depth);
++			brelse(bh);
+ 
+ 			/*
+ 			 * Everything below this this pointer has been

commit a5196f8cdfbf6ccb20f093aaf48852d6d23b4e0b
+Author: Theodore Ts'o 
+Date:   Mon Jan 10 12:47:07 2011 -0500
+
+    ext4: remove ext4_mb_return_to_preallocation()
+    
+    This function was never implemented, except for a BUG_ON which was
+    tripping when ext4 is run without a journal.  The problem is that
+    although the comment asserts that "truncate (which is the only way to
+    free block) discards all preallocations", ext4_free_blocks() is also
+    called in various error recovery paths when blocks have been
+    allocated, but for various reasons, we were not able to use those data
+    blocks (for example, because we ran out of memory while trying to
+    manipulate the extent tree, or some other similar situation).
+    
+    In addition to the fact that this function isn't implemented except
+    for the incorrect BUG_ON, the single caller of this function,
+    ext4_free_blocks(), doesn't use it all if the journal is enabled.
+    
+    So remove the (stub) function entirely for now.  If we decide it's
+    better to add it back, it's only going to be useful with a relatively
+    large number of code changes anyway.
+    
+    Google-Bug-Id: 3236408
+    
+    Cc: Jiaying Zhang 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 21ee30b86de5..cd5214f75397 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -3881,19 +3881,6 @@ void ext4_discard_preallocations(struct inode *inode)
+ 	}
+ }
+ 
+-/*
+- * finds all preallocated spaces and return blocks being freed to them
+- * if preallocated space becomes full (no block is used from the space)
+- * then the function frees space in buddy
+- * XXX: at the moment, truncate (which is the only way to free blocks)
+- * discards all preallocations
+- */
+-static void ext4_mb_return_to_preallocation(struct inode *inode,
+-					struct ext4_buddy *e4b,
+-					sector_t block, int count)
+-{
+-	BUG_ON(!list_empty(&EXT4_I(inode)->i_prealloc_list));
+-}
+ #ifdef CONFIG_EXT4_DEBUG
+ static void ext4_mb_show_ac(struct ext4_allocation_context *ac)
+ {
+@@ -4648,7 +4635,6 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 		ext4_lock_group(sb, block_group);
+ 		mb_clear_bits(bitmap_bh->b_data, bit, count);
+ 		mb_free_blocks(inode, &e4b, bit, count);
+-		ext4_mb_return_to_preallocation(inode, &e4b, block, count);
+ 	}
+ 
+ 	ret = ext4_free_blks_count(sb, gdp) + count;

commit b40971426a837e9dc9c66e1b6bbcb3874eafe4e0
+Author: Theodore Ts'o 
+Date:   Mon Jan 10 12:46:59 2011 -0500
+
+    ext4: add error checking to calls to ext4_handle_dirty_metadata()
+    
+    Call ext4_std_error() in various places when we can't bail out
+    cleanly, so the file system can be marked as in error.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 2693fcda30d8..84b616269265 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4185,6 +4185,7 @@ static int ext4_clear_blocks(handle_t *handle, struct inode *inode,
+ {
+ 	__le32 *p;
+ 	int	flags = EXT4_FREE_BLOCKS_FORGET | EXT4_FREE_BLOCKS_VALIDATED;
++	int	err;
+ 
+ 	if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+ 		flags |= EXT4_FREE_BLOCKS_METADATA;
+@@ -4200,11 +4201,23 @@ static int ext4_clear_blocks(handle_t *handle, struct inode *inode,
+ 	if (try_to_extend_transaction(handle, inode)) {
+ 		if (bh) {
+ 			BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
+-			ext4_handle_dirty_metadata(handle, inode, bh);
++			err = ext4_handle_dirty_metadata(handle, inode, bh);
++			if (unlikely(err)) {
++				ext4_std_error(inode->i_sb, err);
++				return 1;
++			}
++		}
++		err = ext4_mark_inode_dirty(handle, inode);
++		if (unlikely(err)) {
++			ext4_std_error(inode->i_sb, err);
++			return 1;
++		}
++		err = ext4_truncate_restart_trans(handle, inode,
++						  blocks_for_truncate(inode));
++		if (unlikely(err)) {
++			ext4_std_error(inode->i_sb, err);
++			return 1;
+ 		}
+-		ext4_mark_inode_dirty(handle, inode);
+-		ext4_truncate_restart_trans(handle, inode,
+-					    blocks_for_truncate(inode));
+ 		if (bh) {
+ 			BUFFER_TRACE(bh, "retaking write access");
+ 			ext4_journal_get_write_access(handle, bh);
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 6dfc5b9de3e6..5485390d32c5 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1602,7 +1602,11 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+ 			if (err)
+ 				goto journal_error;
+ 		}
+-		ext4_handle_dirty_metadata(handle, inode, frames[0].bh);
++		err = ext4_handle_dirty_metadata(handle, inode, frames[0].bh);
++		if (err) {
++			ext4_std_error(inode->i_sb, err);
++			goto cleanup;
++		}
+ 	}
+ 	de = do_split(handle, dir, &bh, frame, &hinfo, &err);
+ 	if (!de)
+@@ -1630,7 +1634,7 @@ static int ext4_delete_entry(handle_t *handle,
+ {
+ 	struct ext4_dir_entry_2 *de, *pde;
+ 	unsigned int blocksize = dir->i_sb->s_blocksize;
+-	int i;
++	int i, err;
+ 
+ 	i = 0;
+ 	pde = NULL;
+@@ -1640,7 +1644,11 @@ static int ext4_delete_entry(handle_t *handle,
+ 			return -EIO;
+ 		if (de == de_del)  {
+ 			BUFFER_TRACE(bh, "get_write_access");
+-			ext4_journal_get_write_access(handle, bh);
++			err = ext4_journal_get_write_access(handle, bh);
++			if (unlikely(err)) {
++				ext4_std_error(dir->i_sb, err);
++				return err;
++			}
+ 			if (pde)
+ 				pde->rec_len = ext4_rec_len_to_disk(
+ 					ext4_rec_len_from_disk(pde->rec_len,
+@@ -1652,7 +1660,11 @@ static int ext4_delete_entry(handle_t *handle,
+ 				de->inode = 0;
+ 			dir->i_version++;
+ 			BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
+-			ext4_handle_dirty_metadata(handle, dir, bh);
++			err = ext4_handle_dirty_metadata(handle, dir, bh);
++			if (unlikely(err)) {
++				ext4_std_error(dir->i_sb, err);
++				return err;
++			}
+ 			return 0;
+ 		}
+ 		i += ext4_rec_len_from_disk(de->rec_len, blocksize);
+@@ -2414,7 +2426,11 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 					ext4_current_time(new_dir);
+ 		ext4_mark_inode_dirty(handle, new_dir);
+ 		BUFFER_TRACE(new_bh, "call ext4_handle_dirty_metadata");
+-		ext4_handle_dirty_metadata(handle, new_dir, new_bh);
++		retval = ext4_handle_dirty_metadata(handle, new_dir, new_bh);
++		if (unlikely(retval)) {
++			ext4_std_error(new_dir->i_sb, retval);
++			goto end_rename;
++		}
+ 		brelse(new_bh);
+ 		new_bh = NULL;
+ 	}
+@@ -2466,7 +2482,11 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 		PARENT_INO(dir_bh->b_data, new_dir->i_sb->s_blocksize) =
+ 						cpu_to_le32(new_dir->i_ino);
+ 		BUFFER_TRACE(dir_bh, "call ext4_handle_dirty_metadata");
+-		ext4_handle_dirty_metadata(handle, old_dir, dir_bh);
++		retval = ext4_handle_dirty_metadata(handle, old_dir, dir_bh);
++		if (retval) {
++			ext4_std_error(old_dir->i_sb, retval);
++			goto end_rename;
++		}
+ 		ext4_dec_count(handle, old_dir);
+ 		if (new_inode) {
+ 			/* checked empty_dir above, can't have another parent,
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index dc963929de65..7faf47dde7fb 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -220,7 +220,11 @@ static int setup_new_group_blocks(struct super_block *sb,
+ 		memcpy(gdb->b_data, sbi->s_group_desc[i]->b_data, gdb->b_size);
+ 		set_buffer_uptodate(gdb);
+ 		unlock_buffer(gdb);
+-		ext4_handle_dirty_metadata(handle, NULL, gdb);
++		err = ext4_handle_dirty_metadata(handle, NULL, gdb);
++		if (unlikely(err)) {
++			brelse(gdb);
++			goto exit_bh;
++		}
+ 		ext4_set_bit(bit, bh->b_data);
+ 		brelse(gdb);
+ 	}
+@@ -253,7 +257,11 @@ static int setup_new_group_blocks(struct super_block *sb,
+ 
+ 	ext4_mark_bitmap_end(input->blocks_count, sb->s_blocksize * 8,
+ 			     bh->b_data);
+-	ext4_handle_dirty_metadata(handle, NULL, bh);
++	err = ext4_handle_dirty_metadata(handle, NULL, bh);
++	if (unlikely(err)) {
++		ext4_std_error(sb, err);
++		goto exit_bh;
++	}
+ 	brelse(bh);
+ 	/* Mark unused entries in inode bitmap used */
+ 	ext4_debug("clear inode bitmap %#04llx (+%llu)\n",
+@@ -265,7 +273,9 @@ static int setup_new_group_blocks(struct super_block *sb,
+ 
+ 	ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), sb->s_blocksize * 8,
+ 			     bh->b_data);
+-	ext4_handle_dirty_metadata(handle, NULL, bh);
++	err = ext4_handle_dirty_metadata(handle, NULL, bh);
++	if (unlikely(err))
++		ext4_std_error(sb, err);
+ exit_bh:
+ 	brelse(bh);
+ 
+@@ -417,17 +427,21 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ 		goto exit_dind;
+ 	}
+ 
+-	if ((err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh)))
++	err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh);
++	if (unlikely(err))
+ 		goto exit_dind;
+ 
+-	if ((err = ext4_journal_get_write_access(handle, *primary)))
++	err = ext4_journal_get_write_access(handle, *primary);
++	if (unlikely(err))
+ 		goto exit_sbh;
+ 
+-	if ((err = ext4_journal_get_write_access(handle, dind)))
+-		goto exit_primary;
++	err = ext4_journal_get_write_access(handle, dind);
++	if (unlikely(err))
++		ext4_std_error(sb, err);
+ 
+ 	/* ext4_reserve_inode_write() gets a reference on the iloc */
+-	if ((err = ext4_reserve_inode_write(handle, inode, &iloc)))
++	err = ext4_reserve_inode_write(handle, inode, &iloc);
++	if (unlikely(err))
+ 		goto exit_dindj;
+ 
+ 	n_group_desc = kmalloc((gdb_num + 1) * sizeof(struct buffer_head *),
+@@ -449,12 +463,20 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ 	 * reserved inode, and will become GDT blocks (primary and backup).
+ 	 */
+ 	data[gdb_num % EXT4_ADDR_PER_BLOCK(sb)] = 0;
+-	ext4_handle_dirty_metadata(handle, NULL, dind);
+-	brelse(dind);
++	err = ext4_handle_dirty_metadata(handle, NULL, dind);
++	if (unlikely(err)) {
++		ext4_std_error(sb, err);
++		goto exit_inode;
++	}
+ 	inode->i_blocks -= (gdbackups + 1) * sb->s_blocksize >> 9;
+ 	ext4_mark_iloc_dirty(handle, inode, &iloc);
+ 	memset((*primary)->b_data, 0, sb->s_blocksize);
+-	ext4_handle_dirty_metadata(handle, NULL, *primary);
++	err = ext4_handle_dirty_metadata(handle, NULL, *primary);
++	if (unlikely(err)) {
++		ext4_std_error(sb, err);
++		goto exit_inode;
++	}
++	brelse(dind);
+ 
+ 	o_group_desc = EXT4_SB(sb)->s_group_desc;
+ 	memcpy(n_group_desc, o_group_desc,
+@@ -465,19 +487,19 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ 	kfree(o_group_desc);
+ 
+ 	le16_add_cpu(&es->s_reserved_gdt_blocks, -1);
+-	ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh);
++	err = ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh);
++	if (err)
++		ext4_std_error(sb, err);
+ 
+-	return 0;
++	return err;
+ 
+ exit_inode:
+ 	/* ext4_journal_release_buffer(handle, iloc.bh); */
+ 	brelse(iloc.bh);
+ exit_dindj:
+ 	/* ext4_journal_release_buffer(handle, dind); */
+-exit_primary:
+-	/* ext4_journal_release_buffer(handle, *primary); */
+ exit_sbh:
+-	/* ext4_journal_release_buffer(handle, *primary); */
++	/* ext4_journal_release_buffer(handle, EXT4_SB(sb)->s_sbh); */
+ exit_dind:
+ 	brelse(dind);
+ exit_bh:
+@@ -660,7 +682,9 @@ static void update_backups(struct super_block *sb,
+ 			memset(bh->b_data + size, 0, rest);
+ 		set_buffer_uptodate(bh);
+ 		unlock_buffer(bh);
+-		ext4_handle_dirty_metadata(handle, NULL, bh);
++		err = ext4_handle_dirty_metadata(handle, NULL, bh);
++		if (unlikely(err))
++			ext4_std_error(sb, err);
+ 		brelse(bh);
+ 	}
+ 	if ((err2 = ext4_journal_stop(handle)) && !err)
+@@ -878,7 +902,11 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
+ 	/* Update the global fs size fields */
+ 	sbi->s_groups_count++;
+ 
+-	ext4_handle_dirty_metadata(handle, NULL, primary);
++	err = ext4_handle_dirty_metadata(handle, NULL, primary);
++	if (unlikely(err)) {
++		ext4_std_error(sb, err);
++		goto exit_journal;
++	}
+ 
+ 	/* Update the reserved block counts only once the new group is
+ 	 * active. */

commit 8aefcd557d26d0023a36f9ec5afbf55e59f8f26b
+Author: Theodore Ts'o 
+Date:   Mon Jan 10 12:29:43 2011 -0500
+
+    ext4: dynamically allocate the jbd2_inode in ext4_inode_info as necessary
+    
+    Replace the jbd2_inode structure (which is 48 bytes) with a pointer
+    and only allocate the jbd2_inode when it is needed --- that is, when
+    the file system has a journal present and the inode has been opened
+    for writing.  This allows us to further slim down the ext4_inode_info
+    structure.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 2fb531cfd48b..32b7daa41a42 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -811,7 +811,7 @@ struct ext4_inode_info {
+ 	 */
+ 	struct rw_semaphore i_data_sem;
+ 	struct inode vfs_inode;
+-	struct jbd2_inode jinode;
++	struct jbd2_inode *jinode;
+ 
+ 	struct ext4_ext_cache i_cached_extent;
+ 	/*
+diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
+index b0bd792c58c5..d8b992e658c1 100644
+--- a/fs/ext4/ext4_jbd2.h
++++ b/fs/ext4/ext4_jbd2.h
+@@ -253,7 +253,7 @@ static inline int ext4_journal_force_commit(journal_t *journal)
+ static inline int ext4_jbd2_file_inode(handle_t *handle, struct inode *inode)
+ {
+ 	if (ext4_handle_valid(handle))
+-		return jbd2_journal_file_inode(handle, &EXT4_I(inode)->jinode);
++		return jbd2_journal_file_inode(handle, EXT4_I(inode)->jinode);
+ 	return 0;
+ }
+ 
+diff --git a/fs/ext4/file.c b/fs/ext4/file.c
+index 5a5c55ddceef..bb003dc9ffff 100644
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -104,6 +104,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
+ {
+ 	struct super_block *sb = inode->i_sb;
+ 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
++	struct ext4_inode_info *ei = EXT4_I(inode);
+ 	struct vfsmount *mnt = filp->f_path.mnt;
+ 	struct path path;
+ 	char buf[64], *cp;
+@@ -127,6 +128,27 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
+ 			ext4_mark_super_dirty(sb);
+ 		}
+ 	}
++	/*
++	 * Set up the jbd2_inode if we are opening the inode for
++	 * writing and the journal is present
++	 */
++	if (sbi->s_journal && !ei->jinode && (filp->f_mode & FMODE_WRITE)) {
++		struct jbd2_inode *jinode = jbd2_alloc_inode(GFP_KERNEL);
++
++		spin_lock(&inode->i_lock);
++		if (!ei->jinode) {
++			if (!jinode) {
++				spin_unlock(&inode->i_lock);
++				return -ENOMEM;
++			}
++			ei->jinode = jinode;
++			jbd2_journal_init_jbd_inode(ei->jinode, inode);
++			jinode = NULL;
++		}
++		spin_unlock(&inode->i_lock);
++		if (unlikely(jinode != NULL))
++			jbd2_free_inode(jinode);
++	}
+ 	return dquot_file_open(inode, filp);
+ }
+ 
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 0801ee6a173e..2693fcda30d8 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -55,10 +55,17 @@ static inline int ext4_begin_ordered_truncate(struct inode *inode,
+ 					      loff_t new_size)
+ {
+ 	trace_ext4_begin_ordered_truncate(inode, new_size);
+-	return jbd2_journal_begin_ordered_truncate(
+-					EXT4_SB(inode->i_sb)->s_journal,
+-					&EXT4_I(inode)->jinode,
+-					new_size);
++	/*
++	 * If jinode is zero, then we never opened the file for
++	 * writing, so there's no need to call
++	 * jbd2_journal_begin_ordered_truncate() since there's no
++	 * outstanding writes we need to flush.
++	 */
++	if (!EXT4_I(inode)->jinode)
++		return 0;
++	return jbd2_journal_begin_ordered_truncate(EXT4_JOURNAL(inode),
++						   EXT4_I(inode)->jinode,
++						   new_size);
+ }
+ 
+ static void ext4_invalidatepage(struct page *page, unsigned long offset);
+@@ -4054,7 +4061,7 @@ int ext4_block_truncate_page(handle_t *handle,
+ 	if (ext4_should_journal_data(inode)) {
+ 		err = ext4_handle_dirty_metadata(handle, inode, bh);
+ 	} else {
+-		if (ext4_should_order_data(inode))
++		if (ext4_should_order_data(inode) && EXT4_I(inode)->jinode)
+ 			err = ext4_jbd2_file_inode(handle, inode);
+ 		mark_buffer_dirty(bh);
+ 	}
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index f5960d673e4e..1cd4326c530b 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -818,12 +818,6 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
+ 	memset(&ei->i_cached_extent, 0, sizeof(struct ext4_ext_cache));
+ 	INIT_LIST_HEAD(&ei->i_prealloc_list);
+ 	spin_lock_init(&ei->i_prealloc_lock);
+-	/*
+-	 * Note:  We can be called before EXT4_SB(sb)->s_journal is set,
+-	 * therefore it can be null here.  Don't check it, just initialize
+-	 * jinode.
+-	 */
+-	jbd2_journal_init_jbd_inode(&ei->jinode, &ei->vfs_inode);
+ 	ei->i_reserved_data_blocks = 0;
+ 	ei->i_reserved_meta_blocks = 0;
+ 	ei->i_allocated_meta_blocks = 0;
+@@ -832,6 +826,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
+ #ifdef CONFIG_QUOTA
+ 	ei->i_reserved_quota = 0;
+ #endif
++	ei->jinode = NULL;
+ 	INIT_LIST_HEAD(&ei->i_completed_io_list);
+ 	spin_lock_init(&ei->i_completed_io_lock);
+ 	ei->cur_aio_dio = NULL;
+@@ -900,9 +895,12 @@ void ext4_clear_inode(struct inode *inode)
+ 	end_writeback(inode);
+ 	dquot_drop(inode);
+ 	ext4_discard_preallocations(inode);
+-	if (EXT4_JOURNAL(inode))
+-		jbd2_journal_release_jbd_inode(EXT4_SB(inode->i_sb)->s_journal,
+-				       &EXT4_I(inode)->jinode);
++	if (EXT4_I(inode)->jinode) {
++		jbd2_journal_release_jbd_inode(EXT4_JOURNAL(inode),
++					       EXT4_I(inode)->jinode);
++		jbd2_free_inode(EXT4_I(inode)->jinode);
++		EXT4_I(inode)->jinode = NULL;
++	}
+ }
+ 
+ static inline void ext4_show_quota_options(struct seq_file *seq,
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 2447bd86f801..9e4686900f18 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -94,6 +94,7 @@ EXPORT_SYMBOL(jbd2_journal_file_inode);
+ EXPORT_SYMBOL(jbd2_journal_init_jbd_inode);
+ EXPORT_SYMBOL(jbd2_journal_release_jbd_inode);
+ EXPORT_SYMBOL(jbd2_journal_begin_ordered_truncate);
++EXPORT_SYMBOL(jbd2_inode_cache);
+ 
+ static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *);
+ static void __journal_abort_soft (journal_t *journal, int errno);
+@@ -2286,17 +2287,19 @@ static void __exit jbd2_remove_jbd_stats_proc_entry(void)
+ 
+ #endif
+ 
+-struct kmem_cache *jbd2_handle_cache;
++struct kmem_cache *jbd2_handle_cache, *jbd2_inode_cache;
+ 
+ static int __init journal_init_handle_cache(void)
+ {
+-	jbd2_handle_cache = kmem_cache_create("jbd2_journal_handle",
+-				sizeof(handle_t),
+-				0,		/* offset */
+-				SLAB_TEMPORARY,	/* flags */
+-				NULL);		/* ctor */
++	jbd2_handle_cache = KMEM_CACHE(jbd2_journal_handle, SLAB_TEMPORARY);
+ 	if (jbd2_handle_cache == NULL) {
+-		printk(KERN_EMERG "JBD: failed to create handle cache\n");
++		printk(KERN_EMERG "JBD2: failed to create handle cache\n");
++		return -ENOMEM;
++	}
++	jbd2_inode_cache = KMEM_CACHE(jbd2_inode, 0);
++	if (jbd2_inode_cache == NULL) {
++		printk(KERN_EMERG "JBD2: failed to create inode cache\n");
++		kmem_cache_destroy(jbd2_handle_cache);
+ 		return -ENOMEM;
+ 	}
+ 	return 0;
+@@ -2306,6 +2309,9 @@ static void jbd2_journal_destroy_handle_cache(void)
+ {
+ 	if (jbd2_handle_cache)
+ 		kmem_cache_destroy(jbd2_handle_cache);
++	if (jbd2_inode_cache)
++		kmem_cache_destroy(jbd2_inode_cache);
++
+ }
+ 
+ /*
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index 2ae86aa21fce..27e79c27ba08 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -94,7 +94,7 @@ extern void jbd2_free(void *ptr, size_t size);
+  *
+  * This is an opaque datatype.
+  **/
+-typedef struct handle_s		handle_t;	/* Atomic operation type */
++typedef struct jbd2_journal_handle handle_t;	/* Atomic operation type */
+ 
+ 
+ /**
+@@ -416,7 +416,7 @@ struct jbd2_revoke_table_s;
+  * in so it can be fixed later.
+  */
+ 
+-struct handle_s
++struct jbd2_journal_handle
+ {
+ 	/* Which compound transaction is this update a part of? */
+ 	transaction_t		*h_transaction;
+@@ -1158,6 +1158,22 @@ static inline void jbd2_free_handle(handle_t *handle)
+ 	kmem_cache_free(jbd2_handle_cache, handle);
+ }
+ 
++/*
++ * jbd2_inode management (optional, for those file systems that want to use
++ * dynamically allocated jbd2_inode structures)
++ */
++extern struct kmem_cache *jbd2_inode_cache;
++
++static inline struct jbd2_inode *jbd2_alloc_inode(gfp_t gfp_flags)
++{
++	return kmem_cache_alloc(jbd2_inode_cache, gfp_flags);
++}
++
++static inline void jbd2_free_inode(struct jbd2_inode *jinode)
++{
++	kmem_cache_free(jbd2_inode_cache, jinode);
++}
++
+ /* Primary revoke support */
+ #define JOURNAL_REVOKE_DEFAULT_HASH 256
+ extern int	   jbd2_journal_init_revoke(journal_t *, int);

commit 353eb83c1422c6326eaab30ce044a179c6018169
+Author: Theodore Ts'o 
+Date:   Mon Jan 10 12:18:25 2011 -0500
+
+    ext4: drop i_state_flags on architectures with 64-bit longs
+    
+    We can store the dynamic inode state flags in the high bits of
+    EXT4_I(inode)->i_flags, and eliminate i_state_flags.  This saves 8
+    bytes from the size of ext4_inode_info structure, which when
+    multiplied by the number of the number of in the inode cache, can save
+    a lot of memory.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 50e3d24483fb..2fb531cfd48b 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -764,7 +764,9 @@ struct ext4_inode_info {
+ 	 */
+ 	ext4_group_t	i_block_group;
+ 	ext4_lblk_t	i_dir_start_lookup;
++#if (BITS_PER_LONG < 64)
+ 	unsigned long	i_state_flags;		/* Dynamic state flags */
++#endif
+ 	unsigned long	i_flags;
+ 
+ #ifdef CONFIG_EXT4_FS_XATTR
+@@ -1239,22 +1241,36 @@ enum {
+ 	EXT4_STATE_DELALLOC_RESERVED,	/* blks already reserved for delalloc */
+ };
+ 
+-#define EXT4_INODE_BIT_FNS(name, field)					\
++#define EXT4_INODE_BIT_FNS(name, field, offset)				\
+ static inline int ext4_test_inode_##name(struct inode *inode, int bit)	\
+ {									\
+-	return test_bit(bit, &EXT4_I(inode)->i_##field);		\
++	return test_bit(bit + (offset), &EXT4_I(inode)->i_##field);	\
+ }									\
+ static inline void ext4_set_inode_##name(struct inode *inode, int bit)	\
+ {									\
+-	set_bit(bit, &EXT4_I(inode)->i_##field);			\
++	set_bit(bit + (offset), &EXT4_I(inode)->i_##field);		\
+ }									\
+ static inline void ext4_clear_inode_##name(struct inode *inode, int bit) \
+ {									\
+-	clear_bit(bit, &EXT4_I(inode)->i_##field);			\
++	clear_bit(bit + (offset), &EXT4_I(inode)->i_##field);		\
+ }
+ 
+-EXT4_INODE_BIT_FNS(flag, flags)
+-EXT4_INODE_BIT_FNS(state, state_flags)
++EXT4_INODE_BIT_FNS(flag, flags, 0)
++#if (BITS_PER_LONG < 64)
++EXT4_INODE_BIT_FNS(state, state_flags, 0)
++
++static inline void ext4_clear_state_flags(struct ext4_inode_info *ei)
++{
++	(ei)->i_state_flags = 0;
++}
++#else
++EXT4_INODE_BIT_FNS(state, flags, 32)
++
++static inline void ext4_clear_state_flags(struct ext4_inode_info *ei)
++{
++	/* We depend on the fact that callers will set i_flags */
++}
++#endif
+ #else
+ /* Assume that user mode programs are passing in an ext4fs superblock, not
+  * a kernel struct super_block.  This will allow us to call the feature-test
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 1ce240a23ebb..eb9097aec6f0 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -1027,7 +1027,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
+ 	inode->i_generation = sbi->s_next_generation++;
+ 	spin_unlock(&sbi->s_next_gen_lock);
+ 
+-	ei->i_state_flags = 0;
++	ext4_clear_state_flags(ei); /* Only relevant on 32-bit archs */
+ 	ext4_set_inode_state(inode, EXT4_STATE_NEW);
+ 
+ 	ei->i_extra_isize = EXT4_SB(sb)->s_want_extra_isize;
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 3ae83137cf34..0801ee6a173e 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4868,7 +4868,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 	}
+ 	inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
+ 
+-	ei->i_state_flags = 0;
++	ext4_clear_state_flags(ei);	/* Only relevant on 32-bit archs */
+ 	ei->i_dir_start_lookup = 0;
+ 	ei->i_dtime = le32_to_cpu(raw_inode->i_dtime);
+ 	/* We now have enough fields to check if the inode was active or not.
+@@ -5127,7 +5127,7 @@ static int ext4_do_update_inode(handle_t *handle,
+ 	if (ext4_inode_blocks_set(handle, raw_inode, ei))
+ 		goto out_brelse;
+ 	raw_inode->i_dtime = cpu_to_le32(ei->i_dtime);
+-	raw_inode->i_flags = cpu_to_le32(ei->i_flags);
++	raw_inode->i_flags = cpu_to_le32(ei->i_flags & 0xFFFFFFFF);
+ 	if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=
+ 	    cpu_to_le32(EXT4_OS_HURD))
+ 		raw_inode->i_file_acl_high =

commit 8a2005d3f84457b7d7d8646ab5195341d9e5f06a
+Author: Theodore Ts'o 
+Date:   Mon Jan 10 12:13:42 2011 -0500
+
+    ext4: reorder ext4_inode_info structure elements to remove unneeded padding
+    
+    By reordering the elements in the ext4_inode_info structure, we can
+    reduce the padding needed on an x86_64 system by 16 bytes.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index de937fc10503..50e3d24483fb 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -763,10 +763,10 @@ struct ext4_inode_info {
+ 	 * near to their parent directory's inode.
+ 	 */
+ 	ext4_group_t	i_block_group;
++	ext4_lblk_t	i_dir_start_lookup;
+ 	unsigned long	i_state_flags;		/* Dynamic state flags */
+ 	unsigned long	i_flags;
+ 
+-	ext4_lblk_t		i_dir_start_lookup;
+ #ifdef CONFIG_EXT4_FS_XATTR
+ 	/*
+ 	 * Extended attributes can be read independently of the main file
+@@ -835,7 +835,6 @@ struct ext4_inode_info {
+ 	/* on-disk additional length */
+ 	__u16 i_extra_isize;
+ 
+-	spinlock_t i_block_reservation_lock;
+ #ifdef CONFIG_QUOTA
+ 	/* quota space reservation, managed internally by quota code */
+ 	qsize_t i_reserved_quota;
+@@ -844,9 +843,11 @@ struct ext4_inode_info {
+ 	/* completed IOs that might need unwritten extents handling */
+ 	struct list_head i_completed_io_list;
+ 	spinlock_t i_completed_io_lock;
++	atomic_t i_ioend_count;	/* Number of outstanding io_end structs */
+ 	/* current io_end structure for async DIO write*/
+ 	ext4_io_end_t *cur_aio_dio;
+-	atomic_t i_ioend_count;	/* Number of outstanding io_end structs */
++
++	spinlock_t i_block_reservation_lock;
+ 
+ 	/*
+ 	 * Transactions that contain inode's metadata needed to complete

commit b05e6ae58a13b56e3e11882c1fc71948c9b29760
+Author: Theodore Ts'o 
+Date:   Mon Jan 10 12:13:26 2011 -0500
+
+    ext4: drop ec_type from the ext4_ext_cache structure
+    
+    We can encode the ec_type information by using ee_len == 0 to denote
+    EXT4_EXT_CACHE_NO, ee_start == 0 to denote EXT4_EXT_CACHE_GAP, and if
+    neither is true, then the cache type must be EXT4_EXT_CACHE_EXTENT.
+    This allows us to reduce the size of ext4_ext_inode by another 8
+    bytes.  (ec_type is 4 bytes, plus another 4 bytes of padding)
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 746a59853a07..de937fc10503 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -738,12 +738,13 @@ do {									       \
+ 
+ /*
+  * storage for cached extent
++ * If ec_len == 0, then the cache is invalid.
++ * If ec_start == 0, then the cache represents a gap (null mapping)
+  */
+ struct ext4_ext_cache {
+ 	ext4_fsblk_t	ec_start;
+ 	ext4_lblk_t	ec_block;
+ 	__u32		ec_len; /* must be 32bit to return holes */
+-	__u32		ec_type;
+ };
+ 
+ /*
+diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h
+index dfdda1766927..2e29abb30f76 100644
+--- a/fs/ext4/ext4_extents.h
++++ b/fs/ext4/ext4_extents.h
+@@ -119,10 +119,6 @@ struct ext4_ext_path {
+  * structure for external API
+  */
+ 
+-#define EXT4_EXT_CACHE_NO	0
+-#define EXT4_EXT_CACHE_GAP	1
+-#define EXT4_EXT_CACHE_EXTENT	2
+-
+ /*
+  * to be called by ext4_ext_walk_space()
+  * negative retcode - error
+@@ -197,7 +193,7 @@ static inline unsigned short ext_depth(struct inode *inode)
+ static inline void
+ ext4_ext_invalidate_cache(struct inode *inode)
+ {
+-	EXT4_I(inode)->i_cached_extent.ec_type = EXT4_EXT_CACHE_NO;
++	EXT4_I(inode)->i_cached_extent.ec_len = 0;
+ }
+ 
+ static inline void ext4_ext_mark_uninitialized(struct ext4_extent *ext)
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index f1a4354ea3cf..9081d1060a5f 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -1894,12 +1894,10 @@ static int ext4_ext_walk_space(struct inode *inode, ext4_lblk_t block,
+ 			cbex.ec_block = start;
+ 			cbex.ec_len = end - start;
+ 			cbex.ec_start = 0;
+-			cbex.ec_type = EXT4_EXT_CACHE_GAP;
+ 		} else {
+ 			cbex.ec_block = le32_to_cpu(ex->ee_block);
+ 			cbex.ec_len = ext4_ext_get_actual_len(ex);
+ 			cbex.ec_start = ext4_ext_pblock(ex);
+-			cbex.ec_type = EXT4_EXT_CACHE_EXTENT;
+ 		}
+ 
+ 		if (unlikely(cbex.ec_len == 0)) {
+@@ -1939,13 +1937,12 @@ static int ext4_ext_walk_space(struct inode *inode, ext4_lblk_t block,
+ 
+ static void
+ ext4_ext_put_in_cache(struct inode *inode, ext4_lblk_t block,
+-			__u32 len, ext4_fsblk_t start, int type)
++			__u32 len, ext4_fsblk_t start)
+ {
+ 	struct ext4_ext_cache *cex;
+ 	BUG_ON(len == 0);
+ 	spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
+ 	cex = &EXT4_I(inode)->i_cached_extent;
+-	cex->ec_type = type;
+ 	cex->ec_block = block;
+ 	cex->ec_len = len;
+ 	cex->ec_start = start;
+@@ -1998,15 +1995,18 @@ ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path,
+ 	}
+ 
+ 	ext_debug(" -> %u:%lu\n", lblock, len);
+-	ext4_ext_put_in_cache(inode, lblock, len, 0, EXT4_EXT_CACHE_GAP);
++	ext4_ext_put_in_cache(inode, lblock, len, 0);
+ }
+ 
++/*
++ * Return 0 if cache is invalid; 1 if the cache is valid
++ */
+ static int
+ ext4_ext_in_cache(struct inode *inode, ext4_lblk_t block,
+ 			struct ext4_extent *ex)
+ {
+ 	struct ext4_ext_cache *cex;
+-	int ret = EXT4_EXT_CACHE_NO;
++	int ret = 0;
+ 
+ 	/*
+ 	 * We borrow i_block_reservation_lock to protect i_cached_extent
+@@ -2015,11 +2015,9 @@ ext4_ext_in_cache(struct inode *inode, ext4_lblk_t block,
+ 	cex = &EXT4_I(inode)->i_cached_extent;
+ 
+ 	/* has cache valid data? */
+-	if (cex->ec_type == EXT4_EXT_CACHE_NO)
++	if (cex->ec_len == 0)
+ 		goto errout;
+ 
+-	BUG_ON(cex->ec_type != EXT4_EXT_CACHE_GAP &&
+-			cex->ec_type != EXT4_EXT_CACHE_EXTENT);
+ 	if (in_range(block, cex->ec_block, cex->ec_len)) {
+ 		ex->ee_block = cpu_to_le32(cex->ec_block);
+ 		ext4_ext_store_pblock(ex, cex->ec_start);
+@@ -2027,7 +2025,7 @@ ext4_ext_in_cache(struct inode *inode, ext4_lblk_t block,
+ 		ext_debug("%u cached by %u:%u:%llu\n",
+ 				block,
+ 				cex->ec_block, cex->ec_len, cex->ec_start);
+-		ret = cex->ec_type;
++		ret = 1;
+ 	}
+ errout:
+ 	spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+@@ -3298,7 +3296,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 	struct ext4_extent_header *eh;
+ 	struct ext4_extent newex, *ex;
+ 	ext4_fsblk_t newblock;
+-	int err = 0, depth, ret, cache_type;
++	int err = 0, depth, ret;
+ 	unsigned int allocated = 0;
+ 	struct ext4_allocation_request ar;
+ 	ext4_io_end_t *io = EXT4_I(inode)->cur_aio_dio;
+@@ -3307,9 +3305,8 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 		  map->m_lblk, map->m_len, inode->i_ino);
+ 
+ 	/* check in cache */
+-	cache_type = ext4_ext_in_cache(inode, map->m_lblk, &newex);
+-	if (cache_type) {
+-		if (cache_type == EXT4_EXT_CACHE_GAP) {
++	if (ext4_ext_in_cache(inode, map->m_lblk, &newex)) {
++		if (!newex.ee_start_lo && !newex.ee_start_hi) {
+ 			if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) {
+ 				/*
+ 				 * block isn't allocated yet and
+@@ -3318,7 +3315,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 				goto out2;
+ 			}
+ 			/* we should allocate requested block */
+-		} else if (cache_type == EXT4_EXT_CACHE_EXTENT) {
++		} else {
+ 			/* block is already allocated */
+ 			newblock = map->m_lblk
+ 				   - le32_to_cpu(newex.ee_block)
+@@ -3327,8 +3324,6 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 			allocated = ext4_ext_get_actual_len(&newex) -
+ 				(map->m_lblk - le32_to_cpu(newex.ee_block));
+ 			goto out;
+-		} else {
+-			BUG();
+ 		}
+ 	}
+ 
+@@ -3379,8 +3374,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 			/* Do not put uninitialized extent in the cache */
+ 			if (!ext4_ext_is_uninitialized(ex)) {
+ 				ext4_ext_put_in_cache(inode, ee_block,
+-							ee_len, ee_start,
+-							EXT4_EXT_CACHE_EXTENT);
++							ee_len, ee_start);
+ 				goto out;
+ 			}
+ 			ret = ext4_ext_handle_uninitialized_extents(handle,
+@@ -3512,8 +3506,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 	 * when it is _not_ an uninitialized extent.
+ 	 */
+ 	if ((flags & EXT4_GET_BLOCKS_UNINIT_EXT) == 0) {
+-		ext4_ext_put_in_cache(inode, map->m_lblk, allocated, newblock,
+-						EXT4_EXT_CACHE_EXTENT);
++		ext4_ext_put_in_cache(inode, map->m_lblk, allocated, newblock);
+ 		ext4_update_inode_fsync_trans(handle, inode, 1);
+ 	} else
+ 		ext4_update_inode_fsync_trans(handle, inode, 0);
+@@ -3789,7 +3782,7 @@ static int ext4_ext_fiemap_cb(struct inode *inode, struct ext4_ext_path *path,
+ 
+ 	logical =  (__u64)newex->ec_block << blksize_bits;
+ 
+-	if (newex->ec_type == EXT4_EXT_CACHE_GAP) {
++	if (newex->ec_start == 0) {
+ 		pgoff_t offset;
+ 		struct page *page;
+ 		struct buffer_head *bh = NULL;

commit 01f49d0b9d0209dc1194255b11601e4b94447b36
+Author: Theodore Ts'o 
+Date:   Mon Jan 10 12:13:03 2011 -0500
+
+    ext4: use ext4_lblk_t instead of sector_t for logical blocks
+    
+    This fixes a number of places where we used sector_t instead of
+    ext4_lblk_t for logical blocks, which for ext4 are still 32-bit data
+    types.  No point wasting space in the ext4_inode_info structure, and
+    requiring 64-bit arithmetic on 32-bit systems, when it isn't
+    necessary.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index b7ee66ff9962..746a59853a07 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -828,7 +828,7 @@ struct ext4_inode_info {
+ 	unsigned int i_reserved_data_blocks;
+ 	unsigned int i_reserved_meta_blocks;
+ 	unsigned int i_allocated_meta_blocks;
+-	sector_t i_da_metadata_calc_last_lblock;
++	ext4_lblk_t i_da_metadata_calc_last_lblock;
+ 	int i_da_metadata_calc_len;
+ 
+ 	/* on-disk additional length */
+diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h
+index 28ce70fd9cd0..dfdda1766927 100644
+--- a/fs/ext4/ext4_extents.h
++++ b/fs/ext4/ext4_extents.h
+@@ -278,7 +278,7 @@ static inline void ext4_idx_store_pblock(struct ext4_extent_idx *ix,
+ }
+ 
+ extern int ext4_ext_calc_metadata_amount(struct inode *inode,
+-					 sector_t lblocks);
++					 ext4_lblk_t lblocks);
+ extern int ext4_extent_tree_init(handle_t *, struct inode *);
+ extern int ext4_ext_calc_credits_for_single_extent(struct inode *inode,
+ 						   int num,
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index d53e20f53103..f1a4354ea3cf 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -266,7 +266,7 @@ static inline int ext4_ext_space_root_idx(struct inode *inode, int check)
+  * to allocate @blocks
+  * Worse case is one block per extent
+  */
+-int ext4_ext_calc_metadata_amount(struct inode *inode, sector_t lblock)
++int ext4_ext_calc_metadata_amount(struct inode *inode, ext4_lblk_t lblock)
+ {
+ 	struct ext4_inode_info *ei = EXT4_I(inode);
+ 	int idxs, num = 0;
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index ac08460921aa..3ae83137cf34 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1091,7 +1091,7 @@ static int ext4_indirect_calc_metadata_amount(struct inode *inode,
+  * Calculate the number of metadata blocks need to reserve
+  * to allocate a block located at @lblock
+  */
+-static int ext4_calc_metadata_amount(struct inode *inode, sector_t lblock)
++static int ext4_calc_metadata_amount(struct inode *inode, ext4_lblk_t lblock)
+ {
+ 	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
+ 		return ext4_ext_calc_metadata_amount(inode, lblock);
+@@ -1888,7 +1888,7 @@ static int ext4_journalled_write_end(struct file *file,
+ /*
+  * Reserve a single block located at lblock
+  */
+-static int ext4_da_reserve_space(struct inode *inode, sector_t lblock)
++static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock)
+ {
+ 	int retries = 0;
+ 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);

commit f232109773ff5b0c840a6761d74940b9cf0d66ec
+Author: Theodore Ts'o 
+Date:   Mon Jan 10 12:12:36 2011 -0500
+
+    ext4: replace i_delalloc_reserved_flag with EXT4_STATE_DELALLOC_RESERVED
+    
+    Remove the short element i_delalloc_reserved_flag from the
+    ext4_inode_info structure and replace it a new bit in i_state_flags.
+    Since we have an ext4_inode_info for every ext4 inode cached in the
+    inode cache, any savings we can produce here is a very good thing from
+    a memory utilization perspective.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 14c3af26c671..adf96b822781 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -592,7 +592,8 @@ ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
+ 	 * Account for the allocated meta blocks.  We will never
+ 	 * fail EDQUOT for metdata, but we do account for it.
+ 	 */
+-	if (!(*errp) && EXT4_I(inode)->i_delalloc_reserved_flag) {
++	if (!(*errp) &&
++	    ext4_test_inode_state(inode, EXT4_STATE_DELALLOC_RESERVED)) {
+ 		spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
+ 		EXT4_I(inode)->i_allocated_meta_blocks += ar.len;
+ 		spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 2a739255ee05..b7ee66ff9962 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -828,7 +828,6 @@ struct ext4_inode_info {
+ 	unsigned int i_reserved_data_blocks;
+ 	unsigned int i_reserved_meta_blocks;
+ 	unsigned int i_allocated_meta_blocks;
+-	unsigned short i_delalloc_reserved_flag;
+ 	sector_t i_da_metadata_calc_last_lblock;
+ 	int i_da_metadata_calc_len;
+ 
+@@ -1235,6 +1234,7 @@ enum {
+ 	EXT4_STATE_EXT_MIGRATE,		/* Inode is migrating */
+ 	EXT4_STATE_DIO_UNWRITTEN,	/* need convert on dio done*/
+ 	EXT4_STATE_NEWENTRY,		/* File just added to dir */
++	EXT4_STATE_DELALLOC_RESERVED,	/* blks already reserved for delalloc */
+ };
+ 
+ #define EXT4_INODE_BIT_FNS(name, field)					\
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index c0fe426d444a..ac08460921aa 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1330,7 +1330,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
+ 	 * avoid double accounting
+ 	 */
+ 	if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
+-		EXT4_I(inode)->i_delalloc_reserved_flag = 1;
++		ext4_set_inode_state(inode, EXT4_STATE_DELALLOC_RESERVED);
+ 	/*
+ 	 * We need to check for EXT4 here because migrate
+ 	 * could have changed the inode type in between
+@@ -1360,7 +1360,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
+ 			ext4_da_update_reserve_space(inode, retval, 1);
+ 	}
+ 	if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
+-		EXT4_I(inode)->i_delalloc_reserved_flag = 0;
++		ext4_clear_inode_state(inode, EXT4_STATE_DELALLOC_RESERVED);
+ 
+ 	up_write((&EXT4_I(inode)->i_data_sem));
+ 	if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) {
+@@ -2249,7 +2249,7 @@ static void mpage_da_map_and_submit(struct mpage_da_data *mpd)
+ 	 * affects functions in many different parts of the allocation
+ 	 * call path.  This flag exists primarily because we don't
+ 	 * want to change *many* call functions, so ext4_map_blocks()
+-	 * will set the magic i_delalloc_reserved_flag once the
++	 * will set the EXT4_STATE_DELALLOC_RESERVED flag once the
+ 	 * inode's allocation semaphore is taken.
+ 	 *
+ 	 * If the blocks in questions were delalloc blocks, set
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 12b604abc2fe..d47a80ec231d 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -4283,7 +4283,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
+ 	 * EDQUOT check, as blocks and quotas have been already
+ 	 * reserved when data being copied into pagecache.
+ 	 */
+-	if (EXT4_I(ar->inode)->i_delalloc_reserved_flag)
++	if (ext4_test_inode_state(ar->inode, EXT4_STATE_DELALLOC_RESERVED))
+ 		ar->flags |= EXT4_MB_DELALLOC_RESERVED;
+ 	else {
+ 		/* Without delayed allocation we need to verify
+@@ -4380,7 +4380,8 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
+ 	if (inquota && ar->len < inquota)
+ 		dquot_free_block(ar->inode, inquota - ar->len);
+ 	if (!ar->len) {
+-		if (!EXT4_I(ar->inode)->i_delalloc_reserved_flag)
++		if (!ext4_test_inode_state(ar->inode,
++					   EXT4_STATE_DELALLOC_RESERVED))
+ 			/* release all the reserved blocks if non delalloc */
+ 			percpu_counter_sub(&sbi->s_dirtyblocks_counter,
+ 						reserv_blks);
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 7728a4ca3d6c..f5960d673e4e 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -828,7 +828,6 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
+ 	ei->i_reserved_meta_blocks = 0;
+ 	ei->i_allocated_meta_blocks = 0;
+ 	ei->i_da_metadata_calc_len = 0;
+-	ei->i_delalloc_reserved_flag = 0;
+ 	spin_lock_init(&(ei->i_block_reservation_lock));
+ #ifdef CONFIG_QUOTA
+ 	ei->i_reserved_quota = 0;

commit f7c21177af0b32a2cd9ee36189637f0c1f0e1e17
+Author: Theodore Ts'o 
+Date:   Mon Jan 10 12:10:55 2011 -0500
+
+    ext4: Use ext4_error_file() to print the pathname to the corrupted inode
+    
+    Where the file pointer is available, use ext4_error_file() instead of
+    ext4_error_inode().
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index bd5d74d06399..164c56092e58 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -66,7 +66,7 @@ static unsigned char get_dtype(struct super_block *sb, int filetype)
+  * Note: this is the opposite of what ext2 and ext3 historically returned...
+  */
+ int __ext4_check_dir_entry(const char *function, unsigned int line,
+-			   struct inode *dir,
++			   struct inode *dir, struct file *filp,
+ 			   struct ext4_dir_entry_2 *de,
+ 			   struct buffer_head *bh,
+ 			   unsigned int offset)
+@@ -90,12 +90,21 @@ int __ext4_check_dir_entry(const char *function, unsigned int line,
+ 	else
+ 		return 0;
+ 
+-	ext4_error_inode(dir, function, line, bh->b_blocknr,
+-			 "bad entry in directory: %s - "
+-			 "offset=%u(%u), inode=%u, rec_len=%d, name_len=%d",
+-			 error_msg, (unsigned) (offset%bh->b_size), offset,
+-			 le32_to_cpu(de->inode),
+-			 rlen, de->name_len);
++	if (filp)
++		ext4_error_file(filp, function, line, bh ? bh->b_blocknr : 0,
++				"bad entry in directory: %s - offset=%u(%u), "
++				"inode=%u, rec_len=%d, name_len=%d",
++				error_msg, (unsigned) (offset%bh->b_size),
++				offset, le32_to_cpu(de->inode),
++				rlen, de->name_len);
++	else
++		ext4_error_inode(dir, function, line, bh ? bh->b_blocknr : 0,
++				"bad entry in directory: %s - offset=%u(%u), "
++				"inode=%u, rec_len=%d, name_len=%d",
++				error_msg, (unsigned) (offset%bh->b_size),
++				offset, le32_to_cpu(de->inode),
++				rlen, de->name_len);
++
+ 	return 1;
+ }
+ 
+@@ -158,8 +167,9 @@ static int ext4_readdir(struct file *filp,
+ 		 */
+ 		if (!bh) {
+ 			if (!dir_has_error) {
+-				EXT4_ERROR_INODE(inode, "directory "
+-					   "contains a hole at offset %Lu",
++				EXT4_ERROR_FILE(filp, 0,
++						"directory contains a "
++						"hole at offset %llu",
+ 					   (unsigned long long) filp->f_pos);
+ 				dir_has_error = 1;
+ 			}
+@@ -200,7 +210,7 @@ static int ext4_readdir(struct file *filp,
+ 		while (!error && filp->f_pos < inode->i_size
+ 		       && offset < sb->s_blocksize) {
+ 			de = (struct ext4_dir_entry_2 *) (bh->b_data + offset);
+-			if (ext4_check_dir_entry(inode, de,
++			if (ext4_check_dir_entry(inode, filp, de,
+ 						 bh, offset)) {
+ 				/*
+ 				 * On error, skip the f_pos to the next block
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 8104ab7eb7d4..2a739255ee05 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -62,8 +62,8 @@
+ #define EXT4_ERROR_INODE_BLOCK(inode, block, fmt, a...)			\
+ 	ext4_error_inode((inode), __func__, __LINE__, (block), (fmt), ## a)
+ 
+-#define EXT4_ERROR_FILE(file, fmt, a...)	\
+-	ext4_error_file(__func__, __LINE__, (file), (fmt), ## a)
++#define EXT4_ERROR_FILE(file, block, fmt, a...)				\
++	ext4_error_file((file), __func__, __LINE__, (block), (fmt), ## a)
+ 
+ /* data type for block offset of block group */
+ typedef int ext4_grpblk_t;
+@@ -1640,11 +1640,12 @@ extern unsigned ext4_init_block_bitmap(struct super_block *sb,
+ 
+ /* dir.c */
+ extern int __ext4_check_dir_entry(const char *, unsigned int, struct inode *,
++				  struct file *,
+ 				  struct ext4_dir_entry_2 *,
+ 				  struct buffer_head *, unsigned int);
+-#define ext4_check_dir_entry(dir, de, bh, offset) \
+-	unlikely(__ext4_check_dir_entry(__func__, __LINE__, (dir), (de), \
+-					(bh), (offset)))
++#define ext4_check_dir_entry(dir, filp, de, bh, offset)			\
++	unlikely(__ext4_check_dir_entry(__func__, __LINE__, (dir), (filp), \
++					(de), (bh), (offset)))
+ extern int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
+ 				    __u32 minor_hash,
+ 				    struct ext4_dir_entry_2 *dirent);
+@@ -1751,8 +1752,8 @@ extern void ext4_error_inode(struct inode *, const char *, unsigned int,
+ 			     ext4_fsblk_t, const char *, ...)
+ 	__attribute__ ((format (printf, 5, 6)));
+ extern void ext4_error_file(struct file *, const char *, unsigned int,
+-			    const char *, ...)
+-	__attribute__ ((format (printf, 4, 5)));
++			    ext4_fsblk_t, const char *, ...)
++	__attribute__ ((format (printf, 5, 6)));
+ extern void __ext4_std_error(struct super_block *, const char *,
+ 			     unsigned int, int);
+ extern void __ext4_abort(struct super_block *, const char *, unsigned int,
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index e275464f7754..96a594d86a19 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -581,7 +581,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
+ 					   dir->i_sb->s_blocksize -
+ 					   EXT4_DIR_REC_LEN(0));
+ 	for (; de < top; de = ext4_next_entry(de, dir->i_sb->s_blocksize)) {
+-		if (ext4_check_dir_entry(dir, de, bh,
++		if (ext4_check_dir_entry(dir, NULL, de, bh,
+ 				(block<i_sb))
+ 					 + ((char *)de - bh->b_data))) {
+ 			/* On error, skip the f_pos to the next block. */
+@@ -820,7 +820,7 @@ static inline int search_dirblock(struct buffer_head *bh,
+ 		if ((char *) de + namelen <= dlimit &&
+ 		    ext4_match (namelen, name, de)) {
+ 			/* found a match - just to be sure, do a full check */
+-			if (ext4_check_dir_entry(dir, de, bh, offset))
++			if (ext4_check_dir_entry(dir, NULL, de, bh, offset))
+ 				return -1;
+ 			*res_dir = de;
+ 			return 1;
+@@ -1269,7 +1269,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
+ 		de = (struct ext4_dir_entry_2 *)bh->b_data;
+ 		top = bh->b_data + blocksize - reclen;
+ 		while ((char *) de <= top) {
+-			if (ext4_check_dir_entry(dir, de, bh, offset))
++			if (ext4_check_dir_entry(dir, NULL, de, bh, offset))
+ 				return -EIO;
+ 			if (ext4_match(namelen, name, de))
+ 				return -EEXIST;
+@@ -1636,7 +1636,7 @@ static int ext4_delete_entry(handle_t *handle,
+ 	pde = NULL;
+ 	de = (struct ext4_dir_entry_2 *) bh->b_data;
+ 	while (i < bh->b_size) {
+-		if (ext4_check_dir_entry(dir, de, bh, i))
++		if (ext4_check_dir_entry(dir, NULL, de, bh, i))
+ 			return -EIO;
+ 		if (de == de_del)  {
+ 			BUFFER_TRACE(bh, "get_write_access");
+@@ -1919,7 +1919,7 @@ static int empty_dir(struct inode *inode)
+ 			}
+ 			de = (struct ext4_dir_entry_2 *) bh->b_data;
+ 		}
+-		if (ext4_check_dir_entry(inode, de, bh, offset)) {
++		if (ext4_check_dir_entry(inode, NULL, de, bh, offset)) {
+ 			de = (struct ext4_dir_entry_2 *)(bh->b_data +
+ 							 sb->s_blocksize);
+ 			offset = (offset | (sb->s_blocksize - 1)) + 1;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index d49e3b1ec41e..7728a4ca3d6c 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -406,28 +406,31 @@ void ext4_error_inode(struct inode *inode, const char *function,
+ 		      const char *fmt, ...)
+ {
+ 	va_list args;
++	struct va_format vaf;
+ 	struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
+ 
+ 	es->s_last_error_ino = cpu_to_le32(inode->i_ino);
+ 	es->s_last_error_block = cpu_to_le64(block);
+ 	save_error_info(inode->i_sb, function, line);
+ 	va_start(args, fmt);
++	vaf.fmt = fmt;
++	vaf.va = &args;
+ 	printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: inode #%lu: ",
+ 	       inode->i_sb->s_id, function, line, inode->i_ino);
+ 	if (block)
+-		printk("block %llu: ", block);
+-	printk("comm %s: ", current->comm);
+-	vprintk(fmt, args);
+-	printk("\n");
++		printk(KERN_CONT "block %llu: ", block);
++	printk(KERN_CONT "comm %s: %pV\n", current->comm, &vaf);
+ 	va_end(args);
+ 
+ 	ext4_handle_error(inode->i_sb);
+ }
+ 
+ void ext4_error_file(struct file *file, const char *function,
+-		     unsigned int line, const char *fmt, ...)
++		     unsigned int line, ext4_fsblk_t block,
++		     const char *fmt, ...)
+ {
+ 	va_list args;
++	struct va_format vaf;
+ 	struct ext4_super_block *es;
+ 	struct inode *inode = file->f_dentry->d_inode;
+ 	char pathname[80], *path;
+@@ -435,17 +438,18 @@ void ext4_error_file(struct file *file, const char *function,
+ 	es = EXT4_SB(inode->i_sb)->s_es;
+ 	es->s_last_error_ino = cpu_to_le32(inode->i_ino);
+ 	save_error_info(inode->i_sb, function, line);
+-	va_start(args, fmt);
+ 	path = d_path(&(file->f_path), pathname, sizeof(pathname));
+ 	if (IS_ERR(path))
+ 		path = "(unknown)";
+ 	printk(KERN_CRIT
+-	       "EXT4-fs error (device %s): %s:%d: inode #%lu "
+-	       "(comm %s path %s): ",
+-	       inode->i_sb->s_id, function, line, inode->i_ino,
+-	       current->comm, path);
+-	vprintk(fmt, args);
+-	printk("\n");
++	       "EXT4-fs error (device %s): %s:%d: inode #%lu: ",
++	       inode->i_sb->s_id, function, line, inode->i_ino);
++	if (block)
++		printk(KERN_CONT "block %llu: ", block);
++	va_start(args, fmt);
++	vaf.fmt = fmt;
++	vaf.va = &args;
++	printk(KERN_CONT "comm %s: path %s: %pV\n", current->comm, path, &vaf);
+ 	va_end(args);
+ 
+ 	ext4_handle_error(inode->i_sb);

commit eaeef86718249f5c75b1370f77a9bc11f196a01c
+Author: Theodore Ts'o 
+Date:   Mon Jan 10 12:10:07 2011 -0500
+
+    ext4: clean up ext4_xattr_list()'s error code checking and return strategy
+    
+    Any time you see code that tries to add error codes together, you
+    should want to claw your eyes out...
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index fa4b899da4b3..ca6ca14a827d 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -427,23 +427,23 @@ ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size)
+ static int
+ ext4_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
+ {
+-	int i_error, b_error;
++	int ret, ret2;
+ 
+ 	down_read(&EXT4_I(dentry->d_inode)->xattr_sem);
+-	i_error = ext4_xattr_ibody_list(dentry, buffer, buffer_size);
+-	if (i_error < 0) {
+-		b_error = 0;
+-	} else {
+-		if (buffer) {
+-			buffer += i_error;
+-			buffer_size -= i_error;
+-		}
+-		b_error = ext4_xattr_block_list(dentry, buffer, buffer_size);
+-		if (b_error < 0)
+-			i_error = 0;
++	ret = ret2 = ext4_xattr_ibody_list(dentry, buffer, buffer_size);
++	if (ret < 0)
++		goto errout;
++	if (buffer) {
++		buffer += ret;
++		buffer_size -= ret;
+ 	}
++	ret = ext4_xattr_block_list(dentry, buffer, buffer_size);
++	if (ret < 0)
++		goto errout;
++	ret += ret2;
++errout:
+ 	up_read(&EXT4_I(dentry->d_inode)->xattr_sem);
+-	return i_error + b_error;
++	return ret;
+ }
+ 
+ /*

commit 5026e90b86684bc878e4db0a8cd043fed769719c
+Author: Theodore Ts'o 
+Date:   Sat Oct 16 19:37:00 2010 -0400
+
+    ext3: Use search_dirblock() in ext3_dx_find_entry()
+    
+    Use the search_dirblock() in ext3_dx_find_entry().  It makes the code
+    easier to read, and it takes advantage of common code.  It also saves
+    100 bytes or so of text space.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Brad Spengler 
+    Signed-off-by: Jan Kara 
+
+diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
+index d093cbbe38b7..9cc0b2c9664f 100644
+--- a/fs/ext3/namei.c
++++ b/fs/ext3/namei.c
+@@ -975,12 +975,9 @@ static struct buffer_head * ext3_dx_find_entry(struct inode *dir,
+ 	struct super_block *sb = dir->i_sb;
+ 	struct dx_hash_info	hinfo;
+ 	struct dx_frame frames[2], *frame;
+-	struct ext3_dir_entry_2 *de, *top;
+ 	struct buffer_head *bh;
+ 	unsigned long block;
+ 	int retval;
+-	int namelen = entry->len;
+-	const u8 *name = entry->name;
+ 
+ 	if (!(frame = dx_probe(entry, dir, &hinfo, frames, err)))
+ 		return NULL;
+@@ -988,26 +985,20 @@ static struct buffer_head * ext3_dx_find_entry(struct inode *dir,
+ 		block = dx_get_block(frame->at);
+ 		if (!(bh = ext3_bread (NULL,dir, block, 0, err)))
+ 			goto errout;
+-		de = (struct ext3_dir_entry_2 *) bh->b_data;
+-		top = (struct ext3_dir_entry_2 *) ((char *) de + sb->s_blocksize -
+-				       EXT3_DIR_REC_LEN(0));
+-		for (; de < top; de = ext3_next_entry(de)) {
+-			int off = (block << EXT3_BLOCK_SIZE_BITS(sb))
+-				  + ((char *) de - bh->b_data);
+-
+-			if (!ext3_check_dir_entry(__func__, dir, de, bh, off)) {
+-				brelse(bh);
+-				*err = ERR_BAD_DX_DIR;
+-				goto errout;
+-			}
+ 
+-			if (ext3_match(namelen, name, de)) {
+-				*res_dir = de;
+-				dx_release(frames);
+-				return bh;
+-			}
++		retval = search_dirblock(bh, dir, entry,
++					 block << EXT3_BLOCK_SIZE_BITS(sb),
++					 res_dir);
++		if (retval == 1) {
++			dx_release(frames);
++			return bh;
+ 		}
+-		brelse (bh);
++		brelse(bh);
++		if (retval == -1) {
++			*err = ERR_BAD_DX_DIR;
++			goto errout;
++		}
++
+ 		/* Check to see if we should continue to search */
+ 		retval = ext3_htree_next_block(dir, hinfo.hash, frame,
+ 					       frames, NULL);

commit f0cad89f5e8ef8b6d0c065115565524137e44f0b
+Author: Theodore Ts'o 
+Date:   Sat Oct 16 19:36:59 2010 -0400
+
+    ext3: Avoid uninitialized memory references with a corrupted htree directory
+    
+    If the first htree directory is missing '.' or '..' but is otherwise a
+    valid directory, and we do a lookup for '.' or '..', it's possible to
+    dereference an uninitialized memory pointer in ext3_htree_next_block().
+    Avoid this.
+    
+    We avoid this by moving the special case from ext3_dx_find_entry() to
+    ext3_find_entry(); this also means we can optimize ext3_find_entry()
+    slightly when NFS looks up "..".
+    
+    Thanks to Brad Spengler for pointing a Clang warning that led me to
+    look more closely at this code.  The warning was harmless, but it was
+    useful in pointing out code that was too ugly to live.  This warning was
+    also reported by Roman Borisov.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Jan Kara 
+    Cc: Brad Spengler 
+    Signed-off-by: Jan Kara 
+
+diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
+index 672cea16a8b9..d093cbbe38b7 100644
+--- a/fs/ext3/namei.c
++++ b/fs/ext3/namei.c
+@@ -858,6 +858,7 @@ static struct buffer_head *ext3_find_entry(struct inode *dir,
+ 	struct buffer_head * bh_use[NAMEI_RA_SIZE];
+ 	struct buffer_head * bh, *ret = NULL;
+ 	unsigned long start, block, b;
++	const u8 *name = entry->name;
+ 	int ra_max = 0;		/* Number of bh's in the readahead
+ 				   buffer, bh_use[] */
+ 	int ra_ptr = 0;		/* Current index into readahead
+@@ -871,6 +872,16 @@ static struct buffer_head *ext3_find_entry(struct inode *dir,
+ 	namelen = entry->len;
+ 	if (namelen > EXT3_NAME_LEN)
+ 		return NULL;
++	if ((namelen <= 2) && (name[0] == '.') &&
++	    (name[1] == '.' || name[1] == 0)) {
++		/*
++		 * "." or ".." will only be in the first block
++		 * NFS may look up ".."; "." should be handled by the VFS
++		 */
++		block = start = 0;
++		nblocks = 1;
++		goto restart;
++	}
+ 	if (is_dx(dir)) {
+ 		bh = ext3_dx_find_entry(dir, entry, res_dir, &err);
+ 		/*
+@@ -961,9 +972,8 @@ static struct buffer_head * ext3_dx_find_entry(struct inode *dir,
+ 			struct qstr *entry, struct ext3_dir_entry_2 **res_dir,
+ 			int *err)
+ {
+-	struct super_block * sb;
++	struct super_block *sb = dir->i_sb;
+ 	struct dx_hash_info	hinfo;
+-	u32 hash;
+ 	struct dx_frame frames[2], *frame;
+ 	struct ext3_dir_entry_2 *de, *top;
+ 	struct buffer_head *bh;
+@@ -972,18 +982,8 @@ static struct buffer_head * ext3_dx_find_entry(struct inode *dir,
+ 	int namelen = entry->len;
+ 	const u8 *name = entry->name;
+ 
+-	sb = dir->i_sb;
+-	/* NFS may look up ".." - look at dx_root directory block */
+-	if (namelen > 2 || name[0] != '.'|| (namelen == 2 && name[1] != '.')) {
+-		if (!(frame = dx_probe(entry, dir, &hinfo, frames, err)))
+-			return NULL;
+-	} else {
+-		frame = frames;
+-		frame->bh = NULL;			/* for dx_release() */
+-		frame->at = (struct dx_entry *)frames;	/* hack for zero entry*/
+-		dx_set_block(frame->at, 0);		/* dx_root block is 0 */
+-	}
+-	hash = hinfo.hash;
++	if (!(frame = dx_probe(entry, dir, &hinfo, frames, err)))
++		return NULL;
+ 	do {
+ 		block = dx_get_block(frame->at);
+ 		if (!(bh = ext3_bread (NULL,dir, block, 0, err)))
+@@ -1009,7 +1009,7 @@ static struct buffer_head * ext3_dx_find_entry(struct inode *dir,
+ 		}
+ 		brelse (bh);
+ 		/* Check to see if we should continue to search */
+-		retval = ext3_htree_next_block(dir, hash, frame,
++		retval = ext3_htree_next_block(dir, hinfo.hash, frame,
+ 					       frames, NULL);
+ 		if (retval < 0) {
+ 			ext3_warning(sb, __func__,

commit cd8d60a20a4516016c117ac0f1ac7b06ff606f7e
+Author: Theodore Ts'o 
+Date:   Fri Dec 24 09:42:10 2010 -0500
+
+    kbuild: create linux-headers package in deb-pkg
+    
+    Create a linux-headers-$KVER.deb package which can be used to build
+    external modules without having the source tree around.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Michal Marek 
+
+diff --git a/scripts/package/builddeb b/scripts/package/builddeb
+index ffe24194b763..5fc1e6f71838 100644
+--- a/scripts/package/builddeb
++++ b/scripts/package/builddeb
+@@ -76,15 +76,17 @@ else
+ fi
+ tmpdir="$objtree/debian/tmp"
+ fwdir="$objtree/debian/fwtmp"
++hdrdir="$objtree/debian/hdrtmp"
+ packagename=linux-image-$version
+ fwpackagename=linux-firmware-image
++hdrpackagename=linux-headers-$version
+ 
+ if [ "$ARCH" = "um" ] ; then
+ 	packagename=user-mode-linux-$version
+ fi
+ 
+ # Setup the directory structure
+-rm -rf "$tmpdir" "$fwdir"
++rm -rf "$tmpdir" "$fwdir" "$hdrdir"
+ mkdir -m 755 -p "$tmpdir/DEBIAN"
+ mkdir -p  "$tmpdir/lib" "$tmpdir/boot" "$tmpdir/usr/share/doc/$packagename"
+ mkdir -m 755 -p "$fwdir/DEBIAN"
+@@ -226,6 +228,30 @@ EOF
+ 
+ fi
+ 
++# Build header package
++find . -name Makefile -o -name Kconfig\* -o -name \*.pl > /tmp/files$$
++find arch/x86/include include scripts -type f >> /tmp/files$$
++(cd $objtree; find .config Module.symvers include scripts -type f >> /tmp/objfiles$$)
++destdir=$hdrdir/usr/src/linux-headers-$version
++mkdir -p "$destdir" "$hdrdir/DEBIAN" "$hdrdir/usr/share/doc/$hdrpackagename"
++tar -c -f - -T /tmp/files$$ | (cd $destdir; tar -xf -)
++(cd $objtree; tar -c -f - -T /tmp/objfiles$$) | (cd $destdir; tar -xf -)
++rm -f /tmp/files$$ /tmp/objfiles$$
++arch=$(dpkg --print-architecture)
++
++cat <> debian/control
++
++Package: $hdrpackagename
++Provides: linux-headers, linux-headers-2.6
++Architecture: $arch
++Description: Linux kernel headers for $KERNELRELEASE on $arch
++ This package provides kernel header files for $KERNELRELEASE on $arch
++ .
++ This is useful for people who need to build external modules
++EOF
++
++create_package "$hdrpackagename" "$hdrdir"
++
+ # Do we have firmware? Move it out of the way and build it into a package.
+ if [ -e "$tmpdir/lib/firmware" ]; then
+ 	mv "$tmpdir/lib/firmware" "$fwdir/lib/"

commit 8a7411a24350bac141271755c66f40c56b0535ae
+Author: Theodore Ts'o 
+Date:   Mon Dec 20 22:30:36 2010 -0500
+
+    ext4: fix on-line resizing regression
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=25352
+    
+    This regression was caused by commit a31437b85: "ext4: use
+    sb_issue_zeroout in setup_new_group_blocks", by accidentally dropping
+    the code which reserved the block group descriptor and inode table
+    blocks.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index dc963929de65..981c8477adab 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -232,6 +232,8 @@ static int setup_new_group_blocks(struct super_block *sb,
+ 			       GFP_NOFS);
+ 	if (err)
+ 		goto exit_bh;
++	for (i = 0, bit = gdblocks + 1; i < reserved_gdb; i++, bit++)
++		ext4_set_bit(bit, bh->b_data);
+ 
+ 	ext4_debug("mark block bitmap %#04llx (+%llu)\n", input->block_bitmap,
+ 		   input->block_bitmap - start);
+@@ -247,6 +249,9 @@ static int setup_new_group_blocks(struct super_block *sb,
+ 	err = sb_issue_zeroout(sb, block, sbi->s_itb_per_group, GFP_NOFS);
+ 	if (err)
+ 		goto exit_bh;
++	for (i = 0, bit = input->inode_table - start;
++	     i < sbi->s_itb_per_group; i++, bit++)
++		ext4_set_bit(bit, bh->b_data);
+ 
+ 	if ((err = extend_or_restart_transaction(handle, 2, bh)))
+ 		goto exit_bh;

commit b72143ab3ed566a12560fa4411a1f02c276dcc39
+Author: Theodore Ts'o 
+Date:   Mon Dec 20 07:26:59 2010 -0500
+
+    ext4: Add error checking to kmem_cache_alloc() call in ext4_free_blocks()
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 731b6f738a03..46d5414f59c1 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -4626,7 +4626,11 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 		 * blocks being freed are metadata. these blocks shouldn't
+ 		 * be used until this transaction is committed
+ 		 */
+-		new_entry  = kmem_cache_alloc(ext4_free_ext_cachep, GFP_NOFS);
++		new_entry = kmem_cache_alloc(ext4_free_ext_cachep, GFP_NOFS);
++		if (!new_entry) {
++			err = -ENOMEM;
++			goto error_return;
++		}
+ 		new_entry->start_blk = bit;
+ 		new_entry->group  = block_group;
+ 		new_entry->count = count;

commit cad3f00763dcf9dfc62cbddf4bd714ab5a71a0eb
+Author: Theodore Ts'o 
+Date:   Sun Dec 19 22:07:02 2010 -0500
+
+    ext4: optimize ext4_check_dir_entry() with unlikely() annotations
+    
+    This function gets called a lot for large directories, and the answer
+    is almost always "no, no, there's no problem".  This means using
+    unlikely() is a good thing.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index ece76fb6a40c..bd5d74d06399 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -60,7 +60,11 @@ static unsigned char get_dtype(struct super_block *sb, int filetype)
+ 	return (ext4_filetype_table[filetype]);
+ }
+ 
+-
++/*
++ * Return 0 if the directory entry is OK, and 1 if there is a problem
++ *
++ * Note: this is the opposite of what ext2 and ext3 historically returned...
++ */
+ int __ext4_check_dir_entry(const char *function, unsigned int line,
+ 			   struct inode *dir,
+ 			   struct ext4_dir_entry_2 *de,
+@@ -71,26 +75,28 @@ int __ext4_check_dir_entry(const char *function, unsigned int line,
+ 	const int rlen = ext4_rec_len_from_disk(de->rec_len,
+ 						dir->i_sb->s_blocksize);
+ 
+-	if (rlen < EXT4_DIR_REC_LEN(1))
++	if (unlikely(rlen < EXT4_DIR_REC_LEN(1)))
+ 		error_msg = "rec_len is smaller than minimal";
+-	else if (rlen % 4 != 0)
++	else if (unlikely(rlen % 4 != 0))
+ 		error_msg = "rec_len % 4 != 0";
+-	else if (rlen < EXT4_DIR_REC_LEN(de->name_len))
++	else if (unlikely(rlen < EXT4_DIR_REC_LEN(de->name_len)))
+ 		error_msg = "rec_len is too small for name_len";
+-	else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize)
++	else if (unlikely(((char *) de - bh->b_data) + rlen >
++			  dir->i_sb->s_blocksize))
+ 		error_msg = "directory entry across blocks";
+-	else if (le32_to_cpu(de->inode) >
+-			le32_to_cpu(EXT4_SB(dir->i_sb)->s_es->s_inodes_count))
++	else if (unlikely(le32_to_cpu(de->inode) >
++			le32_to_cpu(EXT4_SB(dir->i_sb)->s_es->s_inodes_count)))
+ 		error_msg = "inode out of bounds";
++	else
++		return 0;
+ 
+-	if (error_msg != NULL)
+-		ext4_error_inode(dir, function, line, bh->b_blocknr,
+-			"bad entry in directory: %s - "
+-			"offset=%u(%u), inode=%u, rec_len=%d, name_len=%d",
+-			error_msg, (unsigned) (offset%bh->b_size), offset,
+-			le32_to_cpu(de->inode),
+-			rlen, de->name_len);
+-	return error_msg == NULL ? 1 : 0;
++	ext4_error_inode(dir, function, line, bh->b_blocknr,
++			 "bad entry in directory: %s - "
++			 "offset=%u(%u), inode=%u, rec_len=%d, name_len=%d",
++			 error_msg, (unsigned) (offset%bh->b_size), offset,
++			 le32_to_cpu(de->inode),
++			 rlen, de->name_len);
++	return 1;
+ }
+ 
+ static int ext4_readdir(struct file *filp,
+@@ -194,8 +200,8 @@ static int ext4_readdir(struct file *filp,
+ 		while (!error && filp->f_pos < inode->i_size
+ 		       && offset < sb->s_blocksize) {
+ 			de = (struct ext4_dir_entry_2 *) (bh->b_data + offset);
+-			if (!ext4_check_dir_entry(inode, de,
+-						  bh, offset)) {
++			if (ext4_check_dir_entry(inode, de,
++						 bh, offset)) {
+ 				/*
+ 				 * On error, skip the f_pos to the next block
+ 				 */
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 17baecbf8cda..49f1ceaac57d 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1639,7 +1639,8 @@ extern int __ext4_check_dir_entry(const char *, unsigned int, struct inode *,
+ 				  struct ext4_dir_entry_2 *,
+ 				  struct buffer_head *, unsigned int);
+ #define ext4_check_dir_entry(dir, de, bh, offset) \
+-	__ext4_check_dir_entry(__func__, __LINE__, (dir), (de), (bh), (offset))
++	unlikely(__ext4_check_dir_entry(__func__, __LINE__, (dir), (de), \
++					(bh), (offset)))
+ extern int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
+ 				    __u32 minor_hash,
+ 				    struct ext4_dir_entry_2 *dirent);
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 203086498caa..e275464f7754 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -581,9 +581,9 @@ static int htree_dirblock_to_tree(struct file *dir_file,
+ 					   dir->i_sb->s_blocksize -
+ 					   EXT4_DIR_REC_LEN(0));
+ 	for (; de < top; de = ext4_next_entry(de, dir->i_sb->s_blocksize)) {
+-		if (!ext4_check_dir_entry(dir, de, bh,
+-					(block<i_sb))
+-						+((char *)de - bh->b_data))) {
++		if (ext4_check_dir_entry(dir, de, bh,
++				(block<i_sb))
++					 + ((char *)de - bh->b_data))) {
+ 			/* On error, skip the f_pos to the next block. */
+ 			dir_file->f_pos = (dir_file->f_pos |
+ 					(dir->i_sb->s_blocksize - 1)) + 1;
+@@ -820,7 +820,7 @@ static inline int search_dirblock(struct buffer_head *bh,
+ 		if ((char *) de + namelen <= dlimit &&
+ 		    ext4_match (namelen, name, de)) {
+ 			/* found a match - just to be sure, do a full check */
+-			if (!ext4_check_dir_entry(dir, de, bh, offset))
++			if (ext4_check_dir_entry(dir, de, bh, offset))
+ 				return -1;
+ 			*res_dir = de;
+ 			return 1;
+@@ -1269,7 +1269,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
+ 		de = (struct ext4_dir_entry_2 *)bh->b_data;
+ 		top = bh->b_data + blocksize - reclen;
+ 		while ((char *) de <= top) {
+-			if (!ext4_check_dir_entry(dir, de, bh, offset))
++			if (ext4_check_dir_entry(dir, de, bh, offset))
+ 				return -EIO;
+ 			if (ext4_match(namelen, name, de))
+ 				return -EEXIST;
+@@ -1636,7 +1636,7 @@ static int ext4_delete_entry(handle_t *handle,
+ 	pde = NULL;
+ 	de = (struct ext4_dir_entry_2 *) bh->b_data;
+ 	while (i < bh->b_size) {
+-		if (!ext4_check_dir_entry(dir, de, bh, i))
++		if (ext4_check_dir_entry(dir, de, bh, i))
+ 			return -EIO;
+ 		if (de == de_del)  {
+ 			BUFFER_TRACE(bh, "get_write_access");
+@@ -1919,7 +1919,7 @@ static int empty_dir(struct inode *inode)
+ 			}
+ 			de = (struct ext4_dir_entry_2 *) bh->b_data;
+ 		}
+-		if (!ext4_check_dir_entry(inode, de, bh, offset)) {
++		if (ext4_check_dir_entry(inode, de, bh, offset)) {
+ 			de = (struct ext4_dir_entry_2 *)(bh->b_data +
+ 							 sb->s_blocksize);
+ 			offset = (offset | (sb->s_blocksize - 1)) + 1;

commit b7271b0a39947f757d7969f6150dcb16c1976b91
+Author: Theodore Ts'o 
+Date:   Sat Dec 18 13:39:38 2010 -0500
+
+    jbd2: simplify return path of journal_init_common
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 06dfd778cae5..2447bd86f801 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -828,7 +828,7 @@ static journal_t * journal_init_common (void)
+ 
+ 	journal = kzalloc(sizeof(*journal), GFP_KERNEL);
+ 	if (!journal)
+-		goto fail;
++		return NULL;
+ 
+ 	init_waitqueue_head(&journal->j_wait_transaction_locked);
+ 	init_waitqueue_head(&journal->j_wait_logspace);
+@@ -853,14 +853,12 @@ static journal_t * journal_init_common (void)
+ 	err = jbd2_journal_init_revoke(journal, JOURNAL_REVOKE_DEFAULT_HASH);
+ 	if (err) {
+ 		kfree(journal);
+-		goto fail;
++		return NULL;
+ 	}
+ 
+ 	spin_lock_init(&journal->j_history_lock);
+ 
+ 	return journal;
+-fail:
+-	return NULL;
+ }
+ 
+ /* jbd2_journal_init_dev and jbd2_journal_init_inode:

commit 9a4f6271b68b9693290963b97b320d2e6e6f3446
+Author: Theodore Ts'o 
+Date:   Sat Dec 18 13:36:33 2010 -0500
+
+    jbd2: move debug message into debug #ifdef
+    
+    This is a port to jbd2 of a patch which Namhyung Kim 
+    originally made to fs/jbd.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
+index 2bc4d5f116f1..1cad869494f0 100644
+--- a/fs/jbd2/recovery.c
++++ b/fs/jbd2/recovery.c
+@@ -299,10 +299,10 @@ int jbd2_journal_skip_recovery(journal_t *journal)
+ #ifdef CONFIG_JBD2_DEBUG
+ 		int dropped = info.end_transaction - 
+ 			be32_to_cpu(journal->j_superblock->s_sequence);
+-#endif
+ 		jbd_debug(1,
+ 			  "JBD: ignoring %d transaction%s from the journal.\n",
+ 			  dropped, (dropped == 1) ? "" : "s");
++#endif
+ 		journal->j_transaction_sequence = ++info.end_transaction;
+ 	}
+ 

commit ae00b267f3827ba88309fb74bdf7527396f0acf9
+Author: Theodore Ts'o 
+Date:   Sat Dec 18 13:34:20 2010 -0500
+
+    jbd2: remove unnecessary goto statement
+    
+    This is a port to jbd2 of a patch which Namhyung Kim 
+    originally made to fs/jbd.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index 80f9b2a3880b..394893242ae3 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -340,9 +340,7 @@ handle_t *jbd2__journal_start(journal_t *journal, int nblocks, int gfp_mask)
+ 		jbd2_free_handle(handle);
+ 		current->journal_info = NULL;
+ 		handle = ERR_PTR(err);
+-		goto out;
+ 	}
+-out:
+ 	return handle;
+ }
+ EXPORT_SYMBOL(jbd2__journal_start);

commit a1dd53318409ed6a27a8ce4fecf52e1326a100c0
+Author: Theodore Ts'o 
+Date:   Sat Dec 18 13:13:40 2010 -0500
+
+    jbd2: use offset_in_page() instead of manual calculation
+    
+    This is a port to jbd2 of a patch which Namhyung Kim 
+    originally made to fs/jbd.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index 10b5e3b1ca8b..80f9b2a3880b 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -774,7 +774,7 @@ do_get_write_access(handle_t *handle, struct journal_head *jh,
+ 		J_EXPECT_JH(jh, buffer_uptodate(jh2bh(jh)),
+ 			    "Possible IO failure.\n");
+ 		page = jh2bh(jh)->b_page;
+-		offset = ((unsigned long) jh2bh(jh)->b_data) & ~PAGE_MASK;
++		offset = offset_in_page(jh2bh(jh)->b_data);
+ 		source = kmap_atomic(page, KM_USER0);
+ 		/* Fire data frozen trigger just before we copy the data */
+ 		jbd2_buffer_frozen_trigger(jh, source + offset,

commit cfef2c6a559b1e37cbc7e7c1b51f82d26abf24ec
+Author: Theodore Ts'o 
+Date:   Sat Dec 18 13:07:34 2010 -0500
+
+    jbd2: Fix a debug message in do_get_write_access()
+    
+    'buffer_head' should be 'journal_head'
+    
+    This is a port of a patch which Namhyung Kim  made
+    to fs/jbd to jbd2.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index 6bf0a242613e..10b5e3b1ca8b 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -589,7 +589,7 @@ do_get_write_access(handle_t *handle, struct journal_head *jh,
+ 	transaction = handle->h_transaction;
+ 	journal = transaction->t_journal;
+ 
+-	jbd_debug(5, "buffer_head %p, force_copy %d\n", jh, force_copy);
++	jbd_debug(5, "journal_head %p, force_copy %d\n", jh, force_copy);
+ 
+ 	JBUFFER_TRACE(jh, "entry");
+ repeat:

commit 670be5a78ac7c80f0d6009d648c84c65a03f373a
+Author: Theodore Ts'o 
+Date:   Fri Dec 17 10:44:16 2010 -0500
+
+    jbd2: Use pr_notice_ratelimited() in journal_alloc_journal_head()
+    
+    We had an open-coded version of printk_ratelimited(); use the provided
+    abstraction to make the code cleaner and easier to understand.
+    
+    Based on a similar patch for fs/jbd from Namhyung Kim 
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index f837ba953529..06dfd778cae5 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -43,6 +43,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #define CREATE_TRACE_POINTS
+ #include 
+@@ -1982,7 +1983,6 @@ static void jbd2_journal_destroy_jbd2_journal_head_cache(void)
+ static struct journal_head *journal_alloc_journal_head(void)
+ {
+ 	struct journal_head *ret;
+-	static unsigned long last_warning;
+ 
+ #ifdef CONFIG_JBD2_DEBUG
+ 	atomic_inc(&nr_journal_heads);
+@@ -1990,11 +1990,7 @@ static struct journal_head *journal_alloc_journal_head(void)
+ 	ret = kmem_cache_alloc(jbd2_journal_head_cache, GFP_NOFS);
+ 	if (!ret) {
+ 		jbd_debug(1, "out of memory for journal_head\n");
+-		if (time_after(jiffies, last_warning + 5*HZ)) {
+-			printk(KERN_NOTICE "ENOMEM in %s, retrying.\n",
+-			       __func__);
+-			last_warning = jiffies;
+-		}
++		pr_notice_ratelimited("ENOMEM in %s, retrying.\n", __func__);
+ 		while (!ret) {
+ 			yield();
+ 			ret = kmem_cache_alloc(jbd2_journal_head_cache, GFP_NOFS);

commit a8901d34872dafcafa23efa0865dcecfd4fddf8c
+Author: Theodore Ts'o 
+Date:   Fri Dec 17 10:40:47 2010 -0500
+
+    ext4: Use pr_warning_ratelimited() instead of printk_ratelimit()
+    
+    printk_ratelimit() is deprecated since it is a global instead of a
+    per-printk ratelimit.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index db3cc913ee8f..c0fe426d444a 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -40,6 +40,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include "ext4_jbd2.h"
+ #include "xattr.h"
+@@ -3729,8 +3730,7 @@ static int ext4_set_bh_endio(struct buffer_head *bh, struct inode *inode)
+ retry:
+ 	io_end = ext4_init_io_end(inode, GFP_ATOMIC);
+ 	if (!io_end) {
+-		if (printk_ratelimit())
+-			printk(KERN_WARNING "%s: allocation fail\n", __func__);
++		pr_warning_ratelimited("%s: allocation fail\n", __func__);
+ 		schedule();
+ 		goto retry;
+ 	}

commit 225db7d35c33f076115a583abec238a696f4467e
+Author: Theodore Ts'o 
+Date:   Thu Dec 16 16:38:26 2010 -0500
+
+    ext4: Fix up comments in inode.c
+    
+    This fixes up some broken argument descriptions that Namhyung Kim had
+    originally submitted for ext3.  This fixes the comments that were
+    still applicable in ext4.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index e659597b690b..db3cc913ee8f 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -552,7 +552,7 @@ static ext4_fsblk_t ext4_find_goal(struct inode *inode, ext4_lblk_t block,
+ }
+ 
+ /**
+- *	ext4_blks_to_allocate: Look up the block map and count the number
++ *	ext4_blks_to_allocate - Look up the block map and count the number
+  *	of direct blocks need to be allocated for the given branch.
+  *
+  *	@branch: chain of indirect blocks
+@@ -591,13 +591,19 @@ static int ext4_blks_to_allocate(Indirect *branch, int k, unsigned int blks,
+ 
+ /**
+  *	ext4_alloc_blocks: multiple allocate blocks needed for a branch
++ *	@handle: handle for this transaction
++ *	@inode: inode which needs allocated blocks
++ *	@iblock: the logical block to start allocated at
++ *	@goal: preferred physical block of allocation
+  *	@indirect_blks: the number of blocks need to allocate for indirect
+  *			blocks
+- *
++ *	@blks: number of desired blocks
+  *	@new_blocks: on return it will store the new block numbers for
+  *	the indirect blocks(if needed) and the first direct block,
+- *	@blks:	on return it will store the total number of allocated
+- *		direct blocks
++ *	@err: on return it will store the error code
++ *
++ *	This function will return the number of blocks allocated as
++ *	requested by the passed-in parameters.
+  */
+ static int ext4_alloc_blocks(handle_t *handle, struct inode *inode,
+ 			     ext4_lblk_t iblock, ext4_fsblk_t goal,
+@@ -711,9 +717,11 @@ static int ext4_alloc_blocks(handle_t *handle, struct inode *inode,
+ 
+ /**
+  *	ext4_alloc_branch - allocate and set up a chain of blocks.
++ *	@handle: handle for this transaction
+  *	@inode: owner
+  *	@indirect_blks: number of allocated indirect blocks
+  *	@blks: number of allocated direct blocks
++ *	@goal: preferred place for allocation
+  *	@offsets: offsets (in the blocks) to store the pointers to next.
+  *	@branch: place to store the chain in.
+  *
+@@ -826,6 +834,7 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
+ 
+ /**
+  * ext4_splice_branch - splice the allocated branch onto inode.
++ * @handle: handle for this transaction
+  * @inode: owner
+  * @block: (logical) number of block we are adding
+  * @chain: chain of indirect blocks (with a missing link - see

commit a2595b8aa67011419dae26b47e474f46df902989
+Author: Theodore Ts'o 
+Date:   Wed Dec 15 20:30:48 2010 -0500
+
+    ext4: Add second mount options field since the s_mount_opt is full up
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index ddae3c435138..17baecbf8cda 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -908,6 +908,13 @@ struct ext4_inode_info {
+ #define test_opt(sb, opt)		(EXT4_SB(sb)->s_mount_opt & \
+ 					 EXT4_MOUNT_##opt)
+ 
++#define clear_opt2(sb, opt)		EXT4_SB(sb)->s_mount_opt2 &= \
++						~EXT4_MOUNT2_##opt
++#define set_opt2(sb, opt)		EXT4_SB(sb)->s_mount_opt2 |= \
++						EXT4_MOUNT2_##opt
++#define test_opt2(sb, opt)		(EXT4_SB(sb)->s_mount_opt2 & \
++					 EXT4_MOUNT2_##opt)
++
+ #define ext4_set_bit			ext2_set_bit
+ #define ext4_set_bit_atomic		ext2_set_bit_atomic
+ #define ext4_clear_bit			ext2_clear_bit
+@@ -1073,6 +1080,7 @@ struct ext4_sb_info {
+ 	struct ext4_super_block *s_es;	/* Pointer to the super block in the buffer */
+ 	struct buffer_head **s_group_desc;
+ 	unsigned int s_mount_opt;
++	unsigned int s_mount_opt2;
+ 	unsigned int s_mount_flags;
+ 	ext4_fsblk_t s_sb_block;
+ 	uid_t s_resuid;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 7aa3a790363a..072ff973ff2b 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1895,12 +1895,12 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
+ 	ext4_commit_super(sb, 1);
+ 	if (test_opt(sb, DEBUG))
+ 		printk(KERN_INFO "[EXT4 FS bs=%lu, gc=%u, "
+-				"bpg=%lu, ipg=%lu, mo=%04x]\n",
++				"bpg=%lu, ipg=%lu, mo=%04x, mo2=%04x]\n",
+ 			sb->s_blocksize,
+ 			sbi->s_groups_count,
+ 			EXT4_BLOCKS_PER_GROUP(sb),
+ 			EXT4_INODES_PER_GROUP(sb),
+-			sbi->s_mount_opt);
++			sbi->s_mount_opt, sbi->s_mount_opt2);
+ 
+ 	return res;
+ }
+@@ -4171,6 +4171,7 @@ static int ext4_unfreeze(struct super_block *sb)
+  */
+ struct ext4_mount_options {
+ 	unsigned long s_mount_opt;
++	unsigned long s_mount_opt2;
+ 	uid_t s_resuid;
+ 	gid_t s_resgid;
+ 	unsigned long s_commit_interval;
+@@ -4201,6 +4202,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 	lock_super(sb);
+ 	old_sb_flags = sb->s_flags;
+ 	old_opts.s_mount_opt = sbi->s_mount_opt;
++	old_opts.s_mount_opt2 = sbi->s_mount_opt2;
+ 	old_opts.s_resuid = sbi->s_resuid;
+ 	old_opts.s_resgid = sbi->s_resgid;
+ 	old_opts.s_commit_interval = sbi->s_commit_interval;
+@@ -4354,6 +4356,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ restore_opts:
+ 	sb->s_flags = old_sb_flags;
+ 	sbi->s_mount_opt = old_opts.s_mount_opt;
++	sbi->s_mount_opt2 = old_opts.s_mount_opt2;
+ 	sbi->s_resuid = old_opts.s_resuid;
+ 	sbi->s_resgid = old_opts.s_resgid;
+ 	sbi->s_commit_interval = old_opts.s_commit_interval;

commit 673c610033a8202c037ecd068c7a235495acda17
+Author: Theodore Ts'o 
+Date:   Wed Dec 15 20:28:48 2010 -0500
+
+    ext4: Move struct ext4_mount_options from ext4.h to super.c
+    
+    Move the ext4_mount_options structure definition from ext4.h, since it
+    is only used in super.c.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 2d93620d092e..ddae3c435138 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -561,22 +561,6 @@ struct ext4_new_group_data {
+ #define EXT4_IOC32_SETVERSION_OLD	FS_IOC32_SETVERSION
+ #endif
+ 
+-
+-/*
+- *  Mount options
+- */
+-struct ext4_mount_options {
+-	unsigned long s_mount_opt;
+-	uid_t s_resuid;
+-	gid_t s_resgid;
+-	unsigned long s_commit_interval;
+-	u32 s_min_batch_time, s_max_batch_time;
+-#ifdef CONFIG_QUOTA
+-	int s_jquota_fmt;
+-	char *s_qf_names[MAXQUOTAS];
+-#endif
+-};
+-
+ /* Max physical block we can addres w/o extents */
+ #define EXT4_MAX_BLOCK_FILE_PHYS	0xFFFFFFFF
+ 
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index cf7d9131d785..7aa3a790363a 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4166,6 +4166,21 @@ static int ext4_unfreeze(struct super_block *sb)
+ 	return 0;
+ }
+ 
++/*
++ * Structure to save mount options for ext4_remount's benefit
++ */
++struct ext4_mount_options {
++	unsigned long s_mount_opt;
++	uid_t s_resuid;
++	gid_t s_resgid;
++	unsigned long s_commit_interval;
++	u32 s_min_batch_time, s_max_batch_time;
++#ifdef CONFIG_QUOTA
++	int s_jquota_fmt;
++	char *s_qf_names[MAXQUOTAS];
++#endif
++};
++
+ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ {
+ 	struct ext4_super_block *es;

commit fd8c37eccdda21153298997417144b38b1623196
+Author: Theodore Ts'o 
+Date:   Wed Dec 15 20:26:48 2010 -0500
+
+    ext4: Simplify the usage of clear_opt() and set_opt() macros
+    
+    Change clear_opt() and set_opt() to take a superblock pointer instead
+    of a pointer to EXT4_SB(sb)->s_mount_opt.  This makes it easier for us
+    to support a second mount option field.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 94ce3d7a1c4b..2d93620d092e 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -917,8 +917,10 @@ struct ext4_inode_info {
+ #define EXT4_MOUNT_DISCARD		0x40000000 /* Issue DISCARD requests */
+ #define EXT4_MOUNT_INIT_INODE_TABLE	0x80000000 /* Initialize uninitialized itables */
+ 
+-#define clear_opt(o, opt)		o &= ~EXT4_MOUNT_##opt
+-#define set_opt(o, opt)			o |= EXT4_MOUNT_##opt
++#define clear_opt(sb, opt)		EXT4_SB(sb)->s_mount_opt &= \
++						~EXT4_MOUNT_##opt
++#define set_opt(sb, opt)		EXT4_SB(sb)->s_mount_opt |= \
++						EXT4_MOUNT_##opt
+ #define test_opt(sb, opt)		(EXT4_SB(sb)->s_mount_opt & \
+ 					 EXT4_MOUNT_##opt)
+ 
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 5b4d4e3a4d58..731b6f738a03 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2617,7 +2617,7 @@ static inline int ext4_issue_discard(struct super_block *sb,
+ 	ret = sb_issue_discard(sb, discard_block, count, GFP_NOFS, 0);
+ 	if (ret == -EOPNOTSUPP) {
+ 		ext4_warning(sb, "discard not supported, disabling");
+-		clear_opt(EXT4_SB(sb)->s_mount_opt, DISCARD);
++		clear_opt(sb, DISCARD);
+ 	}
+ 	return ret;
+ }
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index fb15c9c0be74..cf7d9131d785 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1386,7 +1386,7 @@ static int set_qf_name(struct super_block *sb, int qtype, substring_t *args)
+ 		sbi->s_qf_names[qtype] = NULL;
+ 		return 0;
+ 	}
+-	set_opt(sbi->s_mount_opt, QUOTA);
++	set_opt(sb, QUOTA);
+ 	return 1;
+ }
+ 
+@@ -1441,21 +1441,21 @@ static int parse_options(char *options, struct super_block *sb,
+ 		switch (token) {
+ 		case Opt_bsd_df:
+ 			ext4_msg(sb, KERN_WARNING, deprecated_msg, p, "2.6.38");
+-			clear_opt(sbi->s_mount_opt, MINIX_DF);
++			clear_opt(sb, MINIX_DF);
+ 			break;
+ 		case Opt_minix_df:
+ 			ext4_msg(sb, KERN_WARNING, deprecated_msg, p, "2.6.38");
+-			set_opt(sbi->s_mount_opt, MINIX_DF);
++			set_opt(sb, MINIX_DF);
+ 
+ 			break;
+ 		case Opt_grpid:
+ 			ext4_msg(sb, KERN_WARNING, deprecated_msg, p, "2.6.38");
+-			set_opt(sbi->s_mount_opt, GRPID);
++			set_opt(sb, GRPID);
+ 
+ 			break;
+ 		case Opt_nogrpid:
+ 			ext4_msg(sb, KERN_WARNING, deprecated_msg, p, "2.6.38");
+-			clear_opt(sbi->s_mount_opt, GRPID);
++			clear_opt(sb, GRPID);
+ 
+ 			break;
+ 		case Opt_resuid:
+@@ -1473,38 +1473,38 @@ static int parse_options(char *options, struct super_block *sb,
+ 			/* *sb_block = match_int(&args[0]); */
+ 			break;
+ 		case Opt_err_panic:
+-			clear_opt(sbi->s_mount_opt, ERRORS_CONT);
+-			clear_opt(sbi->s_mount_opt, ERRORS_RO);
+-			set_opt(sbi->s_mount_opt, ERRORS_PANIC);
++			clear_opt(sb, ERRORS_CONT);
++			clear_opt(sb, ERRORS_RO);
++			set_opt(sb, ERRORS_PANIC);
+ 			break;
+ 		case Opt_err_ro:
+-			clear_opt(sbi->s_mount_opt, ERRORS_CONT);
+-			clear_opt(sbi->s_mount_opt, ERRORS_PANIC);
+-			set_opt(sbi->s_mount_opt, ERRORS_RO);
++			clear_opt(sb, ERRORS_CONT);
++			clear_opt(sb, ERRORS_PANIC);
++			set_opt(sb, ERRORS_RO);
+ 			break;
+ 		case Opt_err_cont:
+-			clear_opt(sbi->s_mount_opt, ERRORS_RO);
+-			clear_opt(sbi->s_mount_opt, ERRORS_PANIC);
+-			set_opt(sbi->s_mount_opt, ERRORS_CONT);
++			clear_opt(sb, ERRORS_RO);
++			clear_opt(sb, ERRORS_PANIC);
++			set_opt(sb, ERRORS_CONT);
+ 			break;
+ 		case Opt_nouid32:
+-			set_opt(sbi->s_mount_opt, NO_UID32);
++			set_opt(sb, NO_UID32);
+ 			break;
+ 		case Opt_debug:
+-			set_opt(sbi->s_mount_opt, DEBUG);
++			set_opt(sb, DEBUG);
+ 			break;
+ 		case Opt_oldalloc:
+-			set_opt(sbi->s_mount_opt, OLDALLOC);
++			set_opt(sb, OLDALLOC);
+ 			break;
+ 		case Opt_orlov:
+-			clear_opt(sbi->s_mount_opt, OLDALLOC);
++			clear_opt(sb, OLDALLOC);
+ 			break;
+ #ifdef CONFIG_EXT4_FS_XATTR
+ 		case Opt_user_xattr:
+-			set_opt(sbi->s_mount_opt, XATTR_USER);
++			set_opt(sb, XATTR_USER);
+ 			break;
+ 		case Opt_nouser_xattr:
+-			clear_opt(sbi->s_mount_opt, XATTR_USER);
++			clear_opt(sb, XATTR_USER);
+ 			break;
+ #else
+ 		case Opt_user_xattr:
+@@ -1514,10 +1514,10 @@ static int parse_options(char *options, struct super_block *sb,
+ #endif
+ #ifdef CONFIG_EXT4_FS_POSIX_ACL
+ 		case Opt_acl:
+-			set_opt(sbi->s_mount_opt, POSIX_ACL);
++			set_opt(sb, POSIX_ACL);
+ 			break;
+ 		case Opt_noacl:
+-			clear_opt(sbi->s_mount_opt, POSIX_ACL);
++			clear_opt(sb, POSIX_ACL);
+ 			break;
+ #else
+ 		case Opt_acl:
+@@ -1536,7 +1536,7 @@ static int parse_options(char *options, struct super_block *sb,
+ 					 "Cannot specify journal on remount");
+ 				return 0;
+ 			}
+-			set_opt(sbi->s_mount_opt, UPDATE_JOURNAL);
++			set_opt(sb, UPDATE_JOURNAL);
+ 			break;
+ 		case Opt_journal_dev:
+ 			if (is_remount) {
+@@ -1549,14 +1549,14 @@ static int parse_options(char *options, struct super_block *sb,
+ 			*journal_devnum = option;
+ 			break;
+ 		case Opt_journal_checksum:
+-			set_opt(sbi->s_mount_opt, JOURNAL_CHECKSUM);
++			set_opt(sb, JOURNAL_CHECKSUM);
+ 			break;
+ 		case Opt_journal_async_commit:
+-			set_opt(sbi->s_mount_opt, JOURNAL_ASYNC_COMMIT);
+-			set_opt(sbi->s_mount_opt, JOURNAL_CHECKSUM);
++			set_opt(sb, JOURNAL_ASYNC_COMMIT);
++			set_opt(sb, JOURNAL_CHECKSUM);
+ 			break;
+ 		case Opt_noload:
+-			set_opt(sbi->s_mount_opt, NOLOAD);
++			set_opt(sb, NOLOAD);
+ 			break;
+ 		case Opt_commit:
+ 			if (match_int(&args[0], &option))
+@@ -1599,15 +1599,15 @@ static int parse_options(char *options, struct super_block *sb,
+ 					return 0;
+ 				}
+ 			} else {
+-				clear_opt(sbi->s_mount_opt, DATA_FLAGS);
++				clear_opt(sb, DATA_FLAGS);
+ 				sbi->s_mount_opt |= data_opt;
+ 			}
+ 			break;
+ 		case Opt_data_err_abort:
+-			set_opt(sbi->s_mount_opt, DATA_ERR_ABORT);
++			set_opt(sb, DATA_ERR_ABORT);
+ 			break;
+ 		case Opt_data_err_ignore:
+-			clear_opt(sbi->s_mount_opt, DATA_ERR_ABORT);
++			clear_opt(sb, DATA_ERR_ABORT);
+ 			break;
+ #ifdef CONFIG_QUOTA
+ 		case Opt_usrjquota:
+@@ -1647,12 +1647,12 @@ static int parse_options(char *options, struct super_block *sb,
+ 			break;
+ 		case Opt_quota:
+ 		case Opt_usrquota:
+-			set_opt(sbi->s_mount_opt, QUOTA);
+-			set_opt(sbi->s_mount_opt, USRQUOTA);
++			set_opt(sb, QUOTA);
++			set_opt(sb, USRQUOTA);
+ 			break;
+ 		case Opt_grpquota:
+-			set_opt(sbi->s_mount_opt, QUOTA);
+-			set_opt(sbi->s_mount_opt, GRPQUOTA);
++			set_opt(sb, QUOTA);
++			set_opt(sb, GRPQUOTA);
+ 			break;
+ 		case Opt_noquota:
+ 			if (sb_any_quota_loaded(sb)) {
+@@ -1660,9 +1660,9 @@ static int parse_options(char *options, struct super_block *sb,
+ 					"options when quota turned on");
+ 				return 0;
+ 			}
+-			clear_opt(sbi->s_mount_opt, QUOTA);
+-			clear_opt(sbi->s_mount_opt, USRQUOTA);
+-			clear_opt(sbi->s_mount_opt, GRPQUOTA);
++			clear_opt(sb, QUOTA);
++			clear_opt(sb, USRQUOTA);
++			clear_opt(sb, GRPQUOTA);
+ 			break;
+ #else
+ 		case Opt_quota:
+@@ -1688,7 +1688,7 @@ static int parse_options(char *options, struct super_block *sb,
+ 			sbi->s_mount_flags |= EXT4_MF_FS_ABORTED;
+ 			break;
+ 		case Opt_nobarrier:
+-			clear_opt(sbi->s_mount_opt, BARRIER);
++			clear_opt(sb, BARRIER);
+ 			break;
+ 		case Opt_barrier:
+ 			if (args[0].from) {
+@@ -1697,9 +1697,9 @@ static int parse_options(char *options, struct super_block *sb,
+ 			} else
+ 				option = 1;	/* No argument, default to 1 */
+ 			if (option)
+-				set_opt(sbi->s_mount_opt, BARRIER);
++				set_opt(sb, BARRIER);
+ 			else
+-				clear_opt(sbi->s_mount_opt, BARRIER);
++				clear_opt(sb, BARRIER);
+ 			break;
+ 		case Opt_ignore:
+ 			break;
+@@ -1723,17 +1723,17 @@ static int parse_options(char *options, struct super_block *sb,
+ 				 "Ignoring deprecated bh option");
+ 			break;
+ 		case Opt_i_version:
+-			set_opt(sbi->s_mount_opt, I_VERSION);
++			set_opt(sb, I_VERSION);
+ 			sb->s_flags |= MS_I_VERSION;
+ 			break;
+ 		case Opt_nodelalloc:
+-			clear_opt(sbi->s_mount_opt, DELALLOC);
++			clear_opt(sb, DELALLOC);
+ 			break;
+ 		case Opt_mblk_io_submit:
+-			set_opt(sbi->s_mount_opt, MBLK_IO_SUBMIT);
++			set_opt(sb, MBLK_IO_SUBMIT);
+ 			break;
+ 		case Opt_nomblk_io_submit:
+-			clear_opt(sbi->s_mount_opt, MBLK_IO_SUBMIT);
++			clear_opt(sb, MBLK_IO_SUBMIT);
+ 			break;
+ 		case Opt_stripe:
+ 			if (match_int(&args[0], &option))
+@@ -1743,13 +1743,13 @@ static int parse_options(char *options, struct super_block *sb,
+ 			sbi->s_stripe = option;
+ 			break;
+ 		case Opt_delalloc:
+-			set_opt(sbi->s_mount_opt, DELALLOC);
++			set_opt(sb, DELALLOC);
+ 			break;
+ 		case Opt_block_validity:
+-			set_opt(sbi->s_mount_opt, BLOCK_VALIDITY);
++			set_opt(sb, BLOCK_VALIDITY);
+ 			break;
+ 		case Opt_noblock_validity:
+-			clear_opt(sbi->s_mount_opt, BLOCK_VALIDITY);
++			clear_opt(sb, BLOCK_VALIDITY);
+ 			break;
+ 		case Opt_inode_readahead_blks:
+ 			if (match_int(&args[0], &option))
+@@ -1773,7 +1773,7 @@ static int parse_options(char *options, struct super_block *sb,
+ 							    option);
+ 			break;
+ 		case Opt_noauto_da_alloc:
+-			set_opt(sbi->s_mount_opt,NO_AUTO_DA_ALLOC);
++			set_opt(sb, NO_AUTO_DA_ALLOC);
+ 			break;
+ 		case Opt_auto_da_alloc:
+ 			if (args[0].from) {
+@@ -1782,24 +1782,24 @@ static int parse_options(char *options, struct super_block *sb,
+ 			} else
+ 				option = 1;	/* No argument, default to 1 */
+ 			if (option)
+-				clear_opt(sbi->s_mount_opt, NO_AUTO_DA_ALLOC);
++				clear_opt(sb, NO_AUTO_DA_ALLOC);
+ 			else
+-				set_opt(sbi->s_mount_opt,NO_AUTO_DA_ALLOC);
++				set_opt(sb,NO_AUTO_DA_ALLOC);
+ 			break;
+ 		case Opt_discard:
+-			set_opt(sbi->s_mount_opt, DISCARD);
++			set_opt(sb, DISCARD);
+ 			break;
+ 		case Opt_nodiscard:
+-			clear_opt(sbi->s_mount_opt, DISCARD);
++			clear_opt(sb, DISCARD);
+ 			break;
+ 		case Opt_dioread_nolock:
+-			set_opt(sbi->s_mount_opt, DIOREAD_NOLOCK);
++			set_opt(sb, DIOREAD_NOLOCK);
+ 			break;
+ 		case Opt_dioread_lock:
+-			clear_opt(sbi->s_mount_opt, DIOREAD_NOLOCK);
++			clear_opt(sb, DIOREAD_NOLOCK);
+ 			break;
+ 		case Opt_init_inode_table:
+-			set_opt(sbi->s_mount_opt, INIT_INODE_TABLE);
++			set_opt(sb, INIT_INODE_TABLE);
+ 			if (args[0].from) {
+ 				if (match_int(&args[0], &option))
+ 					return 0;
+@@ -1810,7 +1810,7 @@ static int parse_options(char *options, struct super_block *sb,
+ 			sbi->s_li_wait_mult = option;
+ 			break;
+ 		case Opt_noinit_inode_table:
+-			clear_opt(sbi->s_mount_opt, INIT_INODE_TABLE);
++			clear_opt(sb, INIT_INODE_TABLE);
+ 			break;
+ 		default:
+ 			ext4_msg(sb, KERN_ERR,
+@@ -1822,10 +1822,10 @@ static int parse_options(char *options, struct super_block *sb,
+ #ifdef CONFIG_QUOTA
+ 	if (sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]) {
+ 		if (test_opt(sb, USRQUOTA) && sbi->s_qf_names[USRQUOTA])
+-			clear_opt(sbi->s_mount_opt, USRQUOTA);
++			clear_opt(sb, USRQUOTA);
+ 
+ 		if (test_opt(sb, GRPQUOTA) && sbi->s_qf_names[GRPQUOTA])
+-			clear_opt(sbi->s_mount_opt, GRPQUOTA);
++			clear_opt(sb, GRPQUOTA);
+ 
+ 		if (test_opt(sb, GRPQUOTA) || test_opt(sb, USRQUOTA)) {
+ 			ext4_msg(sb, KERN_ERR, "old and new quota "
+@@ -3071,41 +3071,41 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 
+ 	/* Set defaults before we parse the mount options */
+ 	def_mount_opts = le32_to_cpu(es->s_default_mount_opts);
+-	set_opt(sbi->s_mount_opt, INIT_INODE_TABLE);
++	set_opt(sb, INIT_INODE_TABLE);
+ 	if (def_mount_opts & EXT4_DEFM_DEBUG)
+-		set_opt(sbi->s_mount_opt, DEBUG);
++		set_opt(sb, DEBUG);
+ 	if (def_mount_opts & EXT4_DEFM_BSDGROUPS) {
+ 		ext4_msg(sb, KERN_WARNING, deprecated_msg, "bsdgroups",
+ 			"2.6.38");
+-		set_opt(sbi->s_mount_opt, GRPID);
++		set_opt(sb, GRPID);
+ 	}
+ 	if (def_mount_opts & EXT4_DEFM_UID16)
+-		set_opt(sbi->s_mount_opt, NO_UID32);
++		set_opt(sb, NO_UID32);
+ #ifdef CONFIG_EXT4_FS_XATTR
+ 	if (def_mount_opts & EXT4_DEFM_XATTR_USER)
+-		set_opt(sbi->s_mount_opt, XATTR_USER);
++		set_opt(sb, XATTR_USER);
+ #endif
+ #ifdef CONFIG_EXT4_FS_POSIX_ACL
+ 	if (def_mount_opts & EXT4_DEFM_ACL)
+-		set_opt(sbi->s_mount_opt, POSIX_ACL);
++		set_opt(sb, POSIX_ACL);
+ #endif
+ 	if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_DATA)
+-		set_opt(sbi->s_mount_opt, JOURNAL_DATA);
++		set_opt(sb, JOURNAL_DATA);
+ 	else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_ORDERED)
+-		set_opt(sbi->s_mount_opt, ORDERED_DATA);
++		set_opt(sb, ORDERED_DATA);
+ 	else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_WBACK)
+-		set_opt(sbi->s_mount_opt, WRITEBACK_DATA);
++		set_opt(sb, WRITEBACK_DATA);
+ 
+ 	if (le16_to_cpu(sbi->s_es->s_errors) == EXT4_ERRORS_PANIC)
+-		set_opt(sbi->s_mount_opt, ERRORS_PANIC);
++		set_opt(sb, ERRORS_PANIC);
+ 	else if (le16_to_cpu(sbi->s_es->s_errors) == EXT4_ERRORS_CONTINUE)
+-		set_opt(sbi->s_mount_opt, ERRORS_CONT);
++		set_opt(sb, ERRORS_CONT);
+ 	else
+-		set_opt(sbi->s_mount_opt, ERRORS_RO);
++		set_opt(sb, ERRORS_RO);
+ 	if (def_mount_opts & EXT4_DEFM_BLOCK_VALIDITY)
+-		set_opt(sbi->s_mount_opt, BLOCK_VALIDITY);
++		set_opt(sb, BLOCK_VALIDITY);
+ 	if (def_mount_opts & EXT4_DEFM_DISCARD)
+-		set_opt(sbi->s_mount_opt, DISCARD);
++		set_opt(sb, DISCARD);
+ 
+ 	sbi->s_resuid = le16_to_cpu(es->s_def_resuid);
+ 	sbi->s_resgid = le16_to_cpu(es->s_def_resgid);
+@@ -3114,7 +3114,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	sbi->s_max_batch_time = EXT4_DEF_MAX_BATCH_TIME;
+ 
+ 	if ((def_mount_opts & EXT4_DEFM_NOBARRIER) == 0)
+-		set_opt(sbi->s_mount_opt, BARRIER);
++		set_opt(sb, BARRIER);
+ 
+ 	/*
+ 	 * enable delayed allocation by default
+@@ -3122,7 +3122,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	 */
+ 	if (!IS_EXT3_SB(sb) &&
+ 	    ((def_mount_opts & EXT4_DEFM_NODELALLOC) == 0))
+-		set_opt(sbi->s_mount_opt, DELALLOC);
++		set_opt(sb, DELALLOC);
+ 
+ 	if (!parse_options((char *) sbi->s_es->s_mount_opts, sb,
+ 			   &journal_devnum, &journal_ioprio, NULL, 0)) {
+@@ -3425,8 +3425,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		       "suppressed and not mounted read-only");
+ 		goto failed_mount_wq;
+ 	} else {
+-		clear_opt(sbi->s_mount_opt, DATA_FLAGS);
+-		set_opt(sbi->s_mount_opt, WRITEBACK_DATA);
++		clear_opt(sb, DATA_FLAGS);
++		set_opt(sb, WRITEBACK_DATA);
+ 		sbi->s_journal = NULL;
+ 		needs_recovery = 0;
+ 		goto no_journal;
+@@ -3464,9 +3464,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		 */
+ 		if (jbd2_journal_check_available_features
+ 		    (sbi->s_journal, 0, 0, JBD2_FEATURE_INCOMPAT_REVOKE))
+-			set_opt(sbi->s_mount_opt, ORDERED_DATA);
++			set_opt(sb, ORDERED_DATA);
+ 		else
+-			set_opt(sbi->s_mount_opt, JOURNAL_DATA);
++			set_opt(sb, JOURNAL_DATA);
+ 		break;
+ 
+ 	case EXT4_MOUNT_ORDERED_DATA:
+@@ -3556,18 +3556,18 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	    (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)) {
+ 		ext4_msg(sb, KERN_WARNING, "Ignoring delalloc option - "
+ 			 "requested data journaling mode");
+-		clear_opt(sbi->s_mount_opt, DELALLOC);
++		clear_opt(sb, DELALLOC);
+ 	}
+ 	if (test_opt(sb, DIOREAD_NOLOCK)) {
+ 		if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
+ 			ext4_msg(sb, KERN_WARNING, "Ignoring dioread_nolock "
+ 				"option - requested data journaling mode");
+-			clear_opt(sbi->s_mount_opt, DIOREAD_NOLOCK);
++			clear_opt(sb, DIOREAD_NOLOCK);
+ 		}
+ 		if (sb->s_blocksize < PAGE_SIZE) {
+ 			ext4_msg(sb, KERN_WARNING, "Ignoring dioread_nolock "
+ 				"option - block size is too small");
+-			clear_opt(sbi->s_mount_opt, DIOREAD_NOLOCK);
++			clear_opt(sb, DIOREAD_NOLOCK);
+ 		}
+ 	}
+ 

commit 1449032be17abb69116dbc393f67ceb8bd034f92
+Author: Theodore Ts'o 
+Date:   Tue Dec 14 15:27:50 2010 -0500
+
+    ext4: Turn off multiple page-io submission by default
+    
+    Jon Nelson has found a test case which causes postgresql to fail with
+    the error:
+    
+    psql:t.sql:4: ERROR: invalid page header in block 38269 of relation base/16384/16581
+    
+    Under memory pressure, it looks like part of a file can end up getting
+    replaced by zero's.  Until we can figure out the cause, we'll roll
+    back the change and use block_write_full_page() instead of
+    ext4_bio_write_page().  The new, more efficient writing function can
+    be used via the mount option mblk_io_submit, so we can test and fix
+    the new page I/O code.
+    
+    To reproduce the problem, install postgres 8.4 or 9.0, and pin enough
+    memory such that the system just at the end of triggering writeback
+    before running the following sql script:
+    
+    begin;
+    create temporary table foo as select x as a, ARRAY[x] as b FROM
+    generate_series(1, 10000000 ) AS x;
+    create index foo_a_idx on foo (a);
+    create index foo_b_idx on foo USING GIN (b);
+    rollback;
+    
+    If the temporary table is created on a hard drive partition which is
+    encrypted using dm_crypt, then under memory pressure, approximately
+    30-40% of the time, pgsql will issue the above failure.
+    
+    This patch should fix this problem, and the problem will come back if
+    the file system is mounted with the mblk_io_submit mount option.
+    
+    Reported-by: Jon Nelson 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 6a5edea2d70b..94ce3d7a1c4b 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -910,6 +910,7 @@ struct ext4_inode_info {
+ #define EXT4_MOUNT_JOURNAL_CHECKSUM	0x800000 /* Journal checksums */
+ #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT	0x1000000 /* Journal Async Commit */
+ #define EXT4_MOUNT_I_VERSION            0x2000000 /* i_version support */
++#define EXT4_MOUNT_MBLK_IO_SUBMIT	0x4000000 /* multi-block io submits */
+ #define EXT4_MOUNT_DELALLOC		0x8000000 /* Delalloc support */
+ #define EXT4_MOUNT_DATA_ERR_ABORT	0x10000000 /* Abort on file data write */
+ #define EXT4_MOUNT_BLOCK_VALIDITY	0x20000000 /* Block validity checking */
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index bdbe69902207..e659597b690b 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2125,9 +2125,12 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd,
+ 			 */
+ 			if (unlikely(journal_data && PageChecked(page)))
+ 				err = __ext4_journalled_writepage(page, len);
+-			else
++			else if (test_opt(inode->i_sb, MBLK_IO_SUBMIT))
+ 				err = ext4_bio_write_page(&io_submit, page,
+ 							  len, mpd->wbc);
++			else
++				err = block_write_full_page(page,
++					noalloc_get_block_write, mpd->wbc);
+ 
+ 			if (!err)
+ 				mpd->pages_written++;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index e32195d6aac3..fb15c9c0be74 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1026,6 +1026,8 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
+ 	    !(def_mount_opts & EXT4_DEFM_NODELALLOC))
+ 		seq_puts(seq, ",nodelalloc");
+ 
++	if (test_opt(sb, MBLK_IO_SUBMIT))
++		seq_puts(seq, ",mblk_io_submit");
+ 	if (sbi->s_stripe)
+ 		seq_printf(seq, ",stripe=%lu", sbi->s_stripe);
+ 	/*
+@@ -1239,8 +1241,8 @@ enum {
+ 	Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota,
+ 	Opt_noquota, Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err,
+ 	Opt_resize, Opt_usrquota, Opt_grpquota, Opt_i_version,
+-	Opt_stripe, Opt_delalloc, Opt_nodelalloc,
+-	Opt_block_validity, Opt_noblock_validity,
++	Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_mblk_io_submit,
++	Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity,
+ 	Opt_inode_readahead_blks, Opt_journal_ioprio,
+ 	Opt_dioread_nolock, Opt_dioread_lock,
+ 	Opt_discard, Opt_nodiscard,
+@@ -1304,6 +1306,8 @@ static const match_table_t tokens = {
+ 	{Opt_resize, "resize"},
+ 	{Opt_delalloc, "delalloc"},
+ 	{Opt_nodelalloc, "nodelalloc"},
++	{Opt_mblk_io_submit, "mblk_io_submit"},
++	{Opt_nomblk_io_submit, "nomblk_io_submit"},
+ 	{Opt_block_validity, "block_validity"},
+ 	{Opt_noblock_validity, "noblock_validity"},
+ 	{Opt_inode_readahead_blks, "inode_readahead_blks=%u"},
+@@ -1725,6 +1729,12 @@ static int parse_options(char *options, struct super_block *sb,
+ 		case Opt_nodelalloc:
+ 			clear_opt(sbi->s_mount_opt, DELALLOC);
+ 			break;
++		case Opt_mblk_io_submit:
++			set_opt(sbi->s_mount_opt, MBLK_IO_SUBMIT);
++			break;
++		case Opt_nomblk_io_submit:
++			clear_opt(sbi->s_mount_opt, MBLK_IO_SUBMIT);
++			break;
+ 		case Opt_stripe:
+ 			if (match_int(&args[0], &option))
+ 				return 0;

commit ab838338a2a9e0cb8346eb0cab9977be13e8dce5
+Author: Andy Lutomirski 
+Date:   Tue Nov 16 18:40:52 2010 -0500
+
+    nouveau: Acknowledge HPD irq in handler, not bottom half
+    
+    The old code generated an interrupt storm bad enough to completely
+    take down my system.
+    
+    Signed-off-by: Andy Lutomirski 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
+index 10a8d4e78e58..1c7db64c03bf 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
++++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
+@@ -584,6 +584,12 @@ struct drm_nouveau_private {
+ 	struct work_struct irq_work;
+ 	struct work_struct hpd_work;
+ 
++	struct {
++		spinlock_t lock;
++		uint32_t hpd0_bits;
++		uint32_t hpd1_bits;
++	} hpd_state;
++
+ 	struct list_head vbl_waiting;
+ 
+ 	struct {
+diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c
+index e2f2d59be3ea..7bfd9e6c9d67 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_irq.c
++++ b/drivers/gpu/drm/nouveau/nouveau_irq.c
+@@ -60,6 +60,7 @@ nouveau_irq_preinstall(struct drm_device *dev)
+ 	if (dev_priv->card_type >= NV_50) {
+ 		INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh);
+ 		INIT_WORK(&dev_priv->hpd_work, nv50_display_irq_hotplug_bh);
++		spin_lock_init(&dev_priv->hpd_state.lock);
+ 		INIT_LIST_HEAD(&dev_priv->vbl_waiting);
+ 	}
+ }
+diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
+index 55c9663ef2bf..f624c611ddea 100644
+--- a/drivers/gpu/drm/nouveau/nv50_display.c
++++ b/drivers/gpu/drm/nouveau/nv50_display.c
+@@ -1032,11 +1032,18 @@ nv50_display_irq_hotplug_bh(struct work_struct *work)
+ 	struct drm_connector *connector;
+ 	const uint32_t gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 };
+ 	uint32_t unplug_mask, plug_mask, change_mask;
+-	uint32_t hpd0, hpd1 = 0;
++	uint32_t hpd0, hpd1;
+ 
+-	hpd0 = nv_rd32(dev, 0xe054) & nv_rd32(dev, 0xe050);
++	spin_lock_irq(&dev_priv->hpd_state.lock);
++	hpd0 = dev_priv->hpd_state.hpd0_bits;
++	dev_priv->hpd_state.hpd0_bits = 0;
++	hpd1 = dev_priv->hpd_state.hpd1_bits;
++	dev_priv->hpd_state.hpd1_bits = 0;
++	spin_unlock_irq(&dev_priv->hpd_state.lock);
++
++	hpd0 &= nv_rd32(dev, 0xe050);
+ 	if (dev_priv->chipset >= 0x90)
+-		hpd1 = nv_rd32(dev, 0xe074) & nv_rd32(dev, 0xe070);
++		hpd1 &= nv_rd32(dev, 0xe070);
+ 
+ 	plug_mask   = (hpd0 & 0x0000ffff) | (hpd1 << 16);
+ 	unplug_mask = (hpd0 >> 16) | (hpd1 & 0xffff0000);
+@@ -1078,10 +1085,6 @@ nv50_display_irq_hotplug_bh(struct work_struct *work)
+ 			helper->dpms(connector->encoder, DRM_MODE_DPMS_OFF);
+ 	}
+ 
+-	nv_wr32(dev, 0xe054, nv_rd32(dev, 0xe054));
+-	if (dev_priv->chipset >= 0x90)
+-		nv_wr32(dev, 0xe074, nv_rd32(dev, 0xe074));
+-
+ 	drm_helper_hpd_irq_event(dev);
+ }
+ 
+@@ -1092,8 +1095,22 @@ nv50_display_irq_handler(struct drm_device *dev)
+ 	uint32_t delayed = 0;
+ 
+ 	if (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_HOTPLUG) {
+-		if (!work_pending(&dev_priv->hpd_work))
+-			queue_work(dev_priv->wq, &dev_priv->hpd_work);
++		uint32_t hpd0_bits, hpd1_bits = 0;
++
++		hpd0_bits = nv_rd32(dev, 0xe054);
++		nv_wr32(dev, 0xe054, hpd0_bits);
++
++		if (dev_priv->chipset >= 0x90) {
++			hpd1_bits = nv_rd32(dev, 0xe074);
++			nv_wr32(dev, 0xe074, hpd1_bits);
++		}
++
++		spin_lock(&dev_priv->hpd_state.lock);
++		dev_priv->hpd_state.hpd0_bits |= hpd0_bits;
++		dev_priv->hpd_state.hpd1_bits |= hpd1_bits;
++		spin_unlock(&dev_priv->hpd_state.lock);
++
++		queue_work(dev_priv->wq, &dev_priv->hpd_work);
+ 	}
+ 
+ 	while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) {

commit 7ff9c073dd4d7200399076554f7ab9b876f196f6
+Author: Theodore Ts'o 
+Date:   Mon Nov 8 13:51:33 2010 -0500
+
+    ext4: Add new ext4 inode tracepoints
+    
+    Add ext4_evict_inode, ext4_drop_inode, ext4_mark_inode_dirty, and
+    ext4_begin_ordered_truncate()
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 191616470466..846e1e9db434 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -53,6 +53,7 @@
+ static inline int ext4_begin_ordered_truncate(struct inode *inode,
+ 					      loff_t new_size)
+ {
++	trace_ext4_begin_ordered_truncate(inode, new_size);
+ 	return jbd2_journal_begin_ordered_truncate(
+ 					EXT4_SB(inode->i_sb)->s_journal,
+ 					&EXT4_I(inode)->jinode,
+@@ -178,6 +179,7 @@ void ext4_evict_inode(struct inode *inode)
+ 	handle_t *handle;
+ 	int err;
+ 
++	trace_ext4_evict_inode(inode);
+ 	if (inode->i_nlink) {
+ 		truncate_inode_pages(&inode->i_data, 0);
+ 		goto no_delete;
+@@ -5649,6 +5651,7 @@ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode)
+ 	int err, ret;
+ 
+ 	might_sleep();
++	trace_ext4_mark_inode_dirty(inode, _RET_IP_);
+ 	err = ext4_reserve_inode_write(handle, inode, &iloc);
+ 	if (ext4_handle_valid(handle) &&
+ 	    EXT4_I(inode)->i_extra_isize < sbi->s_want_extra_isize &&
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index ee91e29ddf95..61182fe6254e 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -833,6 +833,14 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
+ 	return &ei->vfs_inode;
+ }
+ 
++static int ext4_drop_inode(struct inode *inode)
++{
++	int drop = generic_drop_inode(inode);
++
++	trace_ext4_drop_inode(inode, drop);
++	return drop;
++}
++
+ static void ext4_destroy_inode(struct inode *inode)
+ {
+ 	ext4_ioend_wait(inode);
+@@ -1175,6 +1183,7 @@ static const struct super_operations ext4_sops = {
+ 	.destroy_inode	= ext4_destroy_inode,
+ 	.write_inode	= ext4_write_inode,
+ 	.dirty_inode	= ext4_dirty_inode,
++	.drop_inode	= ext4_drop_inode,
+ 	.evict_inode	= ext4_evict_inode,
+ 	.put_super	= ext4_put_super,
+ 	.sync_fs	= ext4_sync_fs,
+@@ -1196,6 +1205,7 @@ static const struct super_operations ext4_nojournal_sops = {
+ 	.destroy_inode	= ext4_destroy_inode,
+ 	.write_inode	= ext4_write_inode,
+ 	.dirty_inode	= ext4_dirty_inode,
++	.drop_inode	= ext4_drop_inode,
+ 	.evict_inode	= ext4_evict_inode,
+ 	.write_super	= ext4_write_super,
+ 	.put_super	= ext4_put_super,
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index 289010d3270b..e5e345fb2a5c 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -98,6 +98,103 @@ TRACE_EVENT(ext4_allocate_inode,
+ 		  (unsigned long) __entry->dir, __entry->mode)
+ );
+ 
++TRACE_EVENT(ext4_evict_inode,
++	TP_PROTO(struct inode *inode),
++
++	TP_ARGS(inode),
++
++	TP_STRUCT__entry(
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
++		__field(	ino_t,	ino			)
++		__field(	int,	nlink			)
++	),
++
++	TP_fast_assign(
++		__entry->dev_major = MAJOR(inode->i_sb->s_dev);
++		__entry->dev_minor = MINOR(inode->i_sb->s_dev);
++		__entry->ino	= inode->i_ino;
++		__entry->nlink	= inode->i_nlink;
++	),
++
++	TP_printk("dev %d,%d ino %lu nlink %d",
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->ino, __entry->nlink)
++);
++
++TRACE_EVENT(ext4_drop_inode,
++	TP_PROTO(struct inode *inode, int drop),
++
++	TP_ARGS(inode, drop),
++
++	TP_STRUCT__entry(
++		__field(	int,	dev_major		)
++		__field(	int,	dev_minor		)
++		__field(	ino_t,	ino			)
++		__field(	int,	drop			)
++	),
++
++	TP_fast_assign(
++		__entry->dev_major = MAJOR(inode->i_sb->s_dev);
++		__entry->dev_minor = MINOR(inode->i_sb->s_dev);
++		__entry->ino	= inode->i_ino;
++		__entry->drop	= drop;
++	),
++
++	TP_printk("dev %d,%d ino %lu drop %d",
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->ino, __entry->drop)
++);
++
++TRACE_EVENT(ext4_mark_inode_dirty,
++	TP_PROTO(struct inode *inode, unsigned long IP),
++
++	TP_ARGS(inode, IP),
++
++	TP_STRUCT__entry(
++		__field(	int,	dev_major		)
++		__field(	int,	dev_minor		)
++		__field(	ino_t,	ino			)
++		__field(unsigned long,	ip			)
++	),
++
++	TP_fast_assign(
++		__entry->dev_major = MAJOR(inode->i_sb->s_dev);
++		__entry->dev_minor = MINOR(inode->i_sb->s_dev);
++		__entry->ino	= inode->i_ino;
++		__entry->ip	= IP;
++	),
++
++	TP_printk("dev %d,%d ino %lu caller %pF",
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->ino, (void *)__entry->ip)
++);
++
++TRACE_EVENT(ext4_begin_ordered_truncate,
++	TP_PROTO(struct inode *inode, loff_t new_size),
++
++	TP_ARGS(inode, new_size),
++
++	TP_STRUCT__entry(
++		__field(	int,	dev_major		)
++		__field(	int,	dev_minor		)
++		__field(	ino_t,	ino			)
++		__field(	loff_t,	new_size		)
++	),
++
++	TP_fast_assign(
++		__entry->dev_major	= MAJOR(inode->i_sb->s_dev);
++		__entry->dev_minor	= MINOR(inode->i_sb->s_dev);
++		__entry->ino		= inode->i_ino;
++		__entry->new_size	= new_size;
++	),
++
++	TP_printk("dev %d,%d ino %lu new_size %lld",
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->ino,
++		  (long long) __entry->new_size)
++);
++
+ DECLARE_EVENT_CLASS(ext4__write_begin,
+ 
+ 	TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,

commit b56ff9d397cecdaad6c98c9d57cc6fea475e1f50
+Author: Theodore Ts'o 
+Date:   Mon Nov 8 13:49:33 2010 -0500
+
+    ext4: Don't call sb_issue_discard() in ext4_free_blocks()
+    
+    Commit 5c521830cf (ext4: Support discard requests when running in
+    no-journal mode) attempts to add sb_issue_discard() for data blocks
+    (in data=writeback mode) and in no-journal mode.  Unfortunately, this
+    no longer works, because in commit dd3932eddf (block: remove
+    BLKDEV_IFL_WAIT), sb_issue_discard() only presents a synchronous
+    interface, and there are times when we call ext4_free_blocks() when we
+    are are holding a spinlock, or are otherwise in an atomic context.
+    
+    For now, I've removed the call to sb_issue_discard() to prevent a
+    deadlock or (if spinlock debugging is enabled) failures like this:
+    
+    BUG: scheduling while atomic: rc.sysinit/1376/0x00000002
+    Pid: 1376, comm: rc.sysinit Not tainted 2.6.36-ARCH #1
+    Call Trace:
+    [] __schedule_bug+0x5e/0x70
+    [] schedule+0x950/0xa70
+    [] ? insert_work+0x7d/0x90
+    [] ? queue_work_on+0x1d/0x30
+    [] ? queue_work+0x37/0x60
+    [] schedule_timeout+0x21d/0x360
+    [] ? generic_make_request+0x2c3/0x540
+    [] wait_for_common+0xc0/0x150
+    [] ? default_wake_function+0x0/0x10
+    [] ? submit_bio+0x7c/0x100
+    [] ? wake_bit_function+0x0/0x40
+    [] wait_for_completion+0x18/0x20
+    [] blkdev_issue_discard+0x1b9/0x210
+    [] ext4_free_blocks+0x68e/0xb60
+    [] ? __ext4_handle_dirty_metadata+0x110/0x120
+    [] ext4_ext_truncate+0x8cc/0xa70
+    [] ? pagevec_lookup+0x1e/0x30
+    [] ext4_truncate+0x178/0x5d0
+    [] ? unmap_mapping_range+0xab/0x280
+    [] vmtruncate+0x56/0x70
+    [] ext4_setattr+0x14b/0x460
+    [] notify_change+0x194/0x380
+    [] do_truncate+0x60/0x90
+    [] ? security_inode_permission+0x1a/0x20
+    [] ? tomoyo_path_truncate+0x11/0x20
+    [] do_last+0x5d9/0x770
+    [] do_filp_open+0x1ed/0x680
+    [] ? page_fault+0x1f/0x30
+    [] ? alloc_fd+0xec/0x140
+    [] do_sys_open+0x61/0x120
+    [] sys_open+0x1b/0x20
+    [] system_call_fastpath+0x16/0x1b
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=22302
+    
+    Reported-by: Mathias Burén 
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: jiayingz@google.com
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index c58eba34724a..5b4d4e3a4d58 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -4640,8 +4640,6 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 		 * with group lock held. generate_buddy look at
+ 		 * them with group lock_held
+ 		 */
+-		if (test_opt(sb, DISCARD))
+-			ext4_issue_discard(sb, block_group, bit, count);
+ 		ext4_lock_group(sb, block_group);
+ 		mb_clear_bits(bitmap_bh->b_data, bit, count);
+ 		mb_free_blocks(inode, &e4b, bit, count);

commit 83668e7141c7a0aa4035bde94344b81f9cf966ab
+Author: Theodore Ts'o 
+Date:   Mon Nov 8 13:45:33 2010 -0500
+
+    ext4: fix potential race when freeing ext4_io_page structures
+    
+    Use an atomic_t and make sure we don't free the structure while we
+    might still be submitting I/O for that page.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 670d1343f914..6a5edea2d70b 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -177,7 +177,7 @@ struct mpage_da_data {
+ 
+ struct ext4_io_page {
+ 	struct page	*p_page;
+-	int		p_count;
++	atomic_t	p_count;
+ };
+ 
+ #define MAX_IO_PAGES 128
+diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
+index a24c8cca7370..7f5451cd1d38 100644
+--- a/fs/ext4/page-io.c
++++ b/fs/ext4/page-io.c
+@@ -67,6 +67,15 @@ void ext4_ioend_wait(struct inode *inode)
+ 	wait_event(*wq, (atomic_read(&EXT4_I(inode)->i_ioend_count) == 0));
+ }
+ 
++static void put_io_page(struct ext4_io_page *io_page)
++{
++	if (atomic_dec_and_test(&io_page->p_count)) {
++		end_page_writeback(io_page->p_page);
++		put_page(io_page->p_page);
++		kmem_cache_free(io_page_cachep, io_page);
++	}
++}
++
+ void ext4_free_io_end(ext4_io_end_t *io)
+ {
+ 	int i;
+@@ -75,15 +84,8 @@ void ext4_free_io_end(ext4_io_end_t *io)
+ 	BUG_ON(!io);
+ 	if (io->page)
+ 		put_page(io->page);
+-	for (i = 0; i < io->num_io_pages; i++) {
+-		if (--io->pages[i]->p_count == 0) {
+-			struct page *page = io->pages[i]->p_page;
+-
+-			end_page_writeback(page);
+-			put_page(page);
+-			kmem_cache_free(io_page_cachep, io->pages[i]);
+-		}
+-	}
++	for (i = 0; i < io->num_io_pages; i++)
++		put_io_page(io->pages[i]);
+ 	io->num_io_pages = 0;
+ 	wq = to_ioend_wq(io->inode);
+ 	if (atomic_dec_and_test(&EXT4_I(io->inode)->i_ioend_count) &&
+@@ -235,13 +237,7 @@ static void ext4_end_bio(struct bio *bio, int error)
+ 			} while (bh != head);
+ 		}
+ 
+-		if (--io_end->pages[i]->p_count == 0) {
+-			struct page *page = io_end->pages[i]->p_page;
+-
+-			end_page_writeback(page);
+-			put_page(page);
+-			kmem_cache_free(io_page_cachep, io_end->pages[i]);
+-		}
++		put_io_page(io_end->pages[i]);
+ 
+ 		/*
+ 		 * If this is a partial write which happened to make
+@@ -369,7 +365,7 @@ static int io_submit_add_bh(struct ext4_io_submit *io,
+ 	if ((io_end->num_io_pages == 0) ||
+ 	    (io_end->pages[io_end->num_io_pages-1] != io_page)) {
+ 		io_end->pages[io_end->num_io_pages++] = io_page;
+-		io_page->p_count++;
++		atomic_inc(&io_page->p_count);
+ 	}
+ 	return 0;
+ }
+@@ -398,7 +394,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
+ 		return -ENOMEM;
+ 	}
+ 	io_page->p_page = page;
+-	io_page->p_count = 0;
++	atomic_set(&io_page->p_count, 1);
+ 	get_page(page);
+ 
+ 	for (bh = head = page_buffers(page), block_start = 0;
+@@ -430,10 +426,6 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
+ 	 * PageWriteback bit from the page to prevent the system from
+ 	 * wedging later on.
+ 	 */
+-	if (io_page->p_count == 0) {
+-		put_page(page);
+-		end_page_writeback(page);
+-		kmem_cache_free(io_page_cachep, io_page);
+-	}
++	put_io_page(io_page);
+ 	return ret;
+ }

commit f7ad6d2e9201a6e1c9ee6530a291452eb695feb8
+Author: Theodore Ts'o 
+Date:   Mon Nov 8 13:43:33 2010 -0500
+
+    ext4: handle writeback of inodes which are being freed
+    
+    The following BUG can occur when an inode which is getting freed when
+    it still has dirty pages outstanding, and it gets deleted (in this
+    because it was the target of a rename).  In ordered mode, we need to
+    make sure the data pages are written just in case we crash before the
+    rename (or unlink) is committed.  If the inode is being freed then
+    when we try to igrab the inode, we end up tripping the BUG_ON at
+    fs/ext4/page-io.c:146.
+    
+    To solve this problem, we need to keep track of the number of io
+    callbacks which are pending, and avoid destroying the inode until they
+    have all been completed.  That way we don't have to bump the inode
+    count to keep the inode from being destroyed; an approach which
+    doesn't work because the count could have already been dropped down to
+    zero before the inode writeback has started (at which point we're not
+    allowed to bump the count back up to 1, since it's already started
+    getting freed).
+    
+    Thanks to Dave Chinner for suggesting this approach, which is also
+    used by XFS.
+    
+      kernel BUG at /scratch_space/linux-2.6/fs/ext4/page-io.c:146!
+      Call Trace:
+       [] ext4_bio_write_page+0x172/0x307
+       [] mpage_da_submit_io+0x2f9/0x37b
+       [] mpage_da_map_and_submit+0x2cc/0x2e2
+       [] mpage_add_bh_to_extent+0xc6/0xd5
+       [] write_cache_pages_da+0x2a4/0x3ac
+       [] ext4_da_writepages+0x2d6/0x44d
+       [] do_writepages+0x1c/0x25
+       [] __filemap_fdatawrite_range+0x4b/0x4d
+       [] filemap_fdatawrite_range+0xe/0x10
+       [] jbd2_journal_begin_ordered_truncate+0x7b/0xa2
+       [] ext4_evict_inode+0x57/0x24c
+       [] evict+0x22/0x92
+       [] iput+0x212/0x249
+       [] dentry_iput+0xa1/0xb9
+       [] d_kill+0x3d/0x5d
+       [] dput+0x13a/0x147
+       [] sys_renameat+0x1b5/0x258
+       [] ? _atomic_dec_and_lock+0x2d/0x4c
+       [] ? cp_new_stat+0xde/0xea
+       [] ? sys_newlstat+0x2d/0x38
+       [] sys_rename+0x16/0x18
+       [] system_call_fastpath+0x16/0x1b
+    
+    Reported-by: Nick Bowler 
+    Signed-off-by: "Theodore Ts'o" 
+    Tested-by: Nick Bowler 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 8b5dd6369f82..670d1343f914 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -858,6 +858,7 @@ struct ext4_inode_info {
+ 	spinlock_t i_completed_io_lock;
+ 	/* current io_end structure for async DIO write*/
+ 	ext4_io_end_t *cur_aio_dio;
++	atomic_t i_ioend_count;	/* Number of outstanding io_end structs */
+ 
+ 	/*
+ 	 * Transactions that contain inode's metadata needed to complete
+@@ -2060,6 +2061,7 @@ extern int ext4_move_extents(struct file *o_filp, struct file *d_filp,
+ /* page-io.c */
+ extern int __init ext4_init_pageio(void);
+ extern void ext4_exit_pageio(void);
++extern void ext4_ioend_wait(struct inode *);
+ extern void ext4_free_io_end(ext4_io_end_t *io);
+ extern ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags);
+ extern int ext4_end_io_nolock(ext4_io_end_t *io);
+diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
+index 46a7d6a9d976..a24c8cca7370 100644
+--- a/fs/ext4/page-io.c
++++ b/fs/ext4/page-io.c
+@@ -32,8 +32,14 @@
+ 
+ static struct kmem_cache *io_page_cachep, *io_end_cachep;
+ 
++#define WQ_HASH_SZ		37
++#define to_ioend_wq(v)	(&ioend_wq[((unsigned long)v) % WQ_HASH_SZ])
++static wait_queue_head_t ioend_wq[WQ_HASH_SZ];
++
+ int __init ext4_init_pageio(void)
+ {
++	int i;
++
+ 	io_page_cachep = KMEM_CACHE(ext4_io_page, SLAB_RECLAIM_ACCOUNT);
+ 	if (io_page_cachep == NULL)
+ 		return -ENOMEM;
+@@ -42,6 +48,8 @@ int __init ext4_init_pageio(void)
+ 		kmem_cache_destroy(io_page_cachep);
+ 		return -ENOMEM;
+ 	}
++	for (i = 0; i < WQ_HASH_SZ; i++)
++		init_waitqueue_head(&ioend_wq[i]);
+ 
+ 	return 0;
+ }
+@@ -52,9 +60,17 @@ void ext4_exit_pageio(void)
+ 	kmem_cache_destroy(io_page_cachep);
+ }
+ 
++void ext4_ioend_wait(struct inode *inode)
++{
++	wait_queue_head_t *wq = to_ioend_wq(inode);
++
++	wait_event(*wq, (atomic_read(&EXT4_I(inode)->i_ioend_count) == 0));
++}
++
+ void ext4_free_io_end(ext4_io_end_t *io)
+ {
+ 	int i;
++	wait_queue_head_t *wq;
+ 
+ 	BUG_ON(!io);
+ 	if (io->page)
+@@ -69,7 +85,10 @@ void ext4_free_io_end(ext4_io_end_t *io)
+ 		}
+ 	}
+ 	io->num_io_pages = 0;
+-	iput(io->inode);
++	wq = to_ioend_wq(io->inode);
++	if (atomic_dec_and_test(&EXT4_I(io->inode)->i_ioend_count) &&
++	    waitqueue_active(wq))
++		wake_up_all(wq);
+ 	kmem_cache_free(io_end_cachep, io);
+ }
+ 
+@@ -142,8 +161,8 @@ ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags)
+ 	io = kmem_cache_alloc(io_end_cachep, flags);
+ 	if (io) {
+ 		memset(io, 0, sizeof(*io));
+-		io->inode = igrab(inode);
+-		BUG_ON(!io->inode);
++		atomic_inc(&EXT4_I(inode)->i_ioend_count);
++		io->inode = inode;
+ 		INIT_WORK(&io->work, ext4_end_io_work);
+ 		INIT_LIST_HEAD(&io->list);
+ 	}
+@@ -171,35 +190,15 @@ static void ext4_end_bio(struct bio *bio, int error)
+ 	struct workqueue_struct *wq;
+ 	struct inode *inode;
+ 	unsigned long flags;
+-	ext4_fsblk_t err_block;
+ 	int i;
+ 
+ 	BUG_ON(!io_end);
+-	inode = io_end->inode;
+ 	bio->bi_private = NULL;
+ 	bio->bi_end_io = NULL;
+ 	if (test_bit(BIO_UPTODATE, &bio->bi_flags))
+ 		error = 0;
+-	err_block = bio->bi_sector >> (inode->i_blkbits - 9);
+ 	bio_put(bio);
+ 
+-	if (!(inode->i_sb->s_flags & MS_ACTIVE)) {
+-		pr_err("sb umounted, discard end_io request for inode %lu\n",
+-			io_end->inode->i_ino);
+-		ext4_free_io_end(io_end);
+-		return;
+-	}
+-
+-	if (error) {
+-		io_end->flag |= EXT4_IO_END_ERROR;
+-		ext4_warning(inode->i_sb, "I/O error writing to inode %lu "
+-			     "(offset %llu size %ld starting block %llu)",
+-			     inode->i_ino,
+-			     (unsigned long long) io_end->offset,
+-			     (long) io_end->size,
+-			     (unsigned long long) err_block);
+-	}
+-
+ 	for (i = 0; i < io_end->num_io_pages; i++) {
+ 		struct page *page = io_end->pages[i]->p_page;
+ 		struct buffer_head *bh, *head;
+@@ -254,8 +253,19 @@ static void ext4_end_bio(struct bio *bio, int error)
+ 		if (!partial_write)
+ 			SetPageUptodate(page);
+ 	}
+-
+ 	io_end->num_io_pages = 0;
++	inode = io_end->inode;
++
++	if (error) {
++		io_end->flag |= EXT4_IO_END_ERROR;
++		ext4_warning(inode->i_sb, "I/O error writing to inode %lu "
++			     "(offset %llu size %ld starting block %llu)",
++			     inode->i_ino,
++			     (unsigned long long) io_end->offset,
++			     (long) io_end->size,
++			     (unsigned long long)
++			     bio->bi_sector >> (inode->i_blkbits - 9));
++	}
+ 
+ 	/* Add the io_end to per-inode completed io list*/
+ 	spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags);
+@@ -305,7 +315,6 @@ static int io_submit_init(struct ext4_io_submit *io,
+ 	bio->bi_private = io->io_end = io_end;
+ 	bio->bi_end_io = ext4_end_bio;
+ 
+-	io_end->inode = inode;
+ 	io_end->offset = (page->index << PAGE_CACHE_SHIFT) + bh_offset(bh);
+ 
+ 	io->io_bio = bio;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 04352e9729d0..45653af88953 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -828,12 +828,14 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
+ 	ei->cur_aio_dio = NULL;
+ 	ei->i_sync_tid = 0;
+ 	ei->i_datasync_tid = 0;
++	atomic_set(&ei->i_ioend_count, 0);
+ 
+ 	return &ei->vfs_inode;
+ }
+ 
+ static void ext4_destroy_inode(struct inode *inode)
+ {
++	ext4_ioend_wait(inode);
+ 	if (!list_empty(&(EXT4_I(inode)->i_orphan))) {
+ 		ext4_msg(inode->i_sb, KERN_ERR,
+ 			 "Inode %lu (%p): orphan list check failed!",

commit ce7e010aef63dc6b37a2354f7c9f5f4aedb37978
+Author: Theodore Ts'o 
+Date:   Wed Nov 3 12:03:21 2010 -0400
+
+    ext4: initialize the percpu counters before replaying the journal
+    
+    We now initialize the percpu counters before replaying the journal,
+    but after the journal, we recalculate the global counters, to deal
+    with the possibility of the per-blockgroup counts getting updated by
+    the journal replay.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 4d7ef31eacb1..04352e9729d0 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3347,6 +3347,24 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	get_random_bytes(&sbi->s_next_generation, sizeof(u32));
+ 	spin_lock_init(&sbi->s_next_gen_lock);
+ 
++	err = percpu_counter_init(&sbi->s_freeblocks_counter,
++			ext4_count_free_blocks(sb));
++	if (!err) {
++		err = percpu_counter_init(&sbi->s_freeinodes_counter,
++				ext4_count_free_inodes(sb));
++	}
++	if (!err) {
++		err = percpu_counter_init(&sbi->s_dirs_counter,
++				ext4_count_dirs(sb));
++	}
++	if (!err) {
++		err = percpu_counter_init(&sbi->s_dirtyblocks_counter, 0);
++	}
++	if (err) {
++		ext4_msg(sb, KERN_ERR, "insufficient memory");
++		goto failed_mount3;
++	}
++
+ 	sbi->s_stripe = ext4_get_stripe_size(sbi);
+ 	sbi->s_max_writeback_mb_bump = 128;
+ 
+@@ -3445,22 +3463,19 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	}
+ 	set_task_ioprio(sbi->s_journal->j_task, journal_ioprio);
+ 
+-no_journal:
+-	err = percpu_counter_init(&sbi->s_freeblocks_counter,
+-				  ext4_count_free_blocks(sb));
+-	if (!err)
+-		err = percpu_counter_init(&sbi->s_freeinodes_counter,
+-					  ext4_count_free_inodes(sb));
+-	if (!err)
+-		err = percpu_counter_init(&sbi->s_dirs_counter,
+-					  ext4_count_dirs(sb));
+-	if (!err)
+-		err = percpu_counter_init(&sbi->s_dirtyblocks_counter, 0);
+-	if (err) {
+-		ext4_msg(sb, KERN_ERR, "insufficient memory");
+-		goto failed_mount_wq;
+-	}
++	/*
++	 * The journal may have updated the bg summary counts, so we
++	 * need to update the global counters.
++	 */
++	percpu_counter_set(&sbi->s_freeblocks_counter,
++			   ext4_count_free_blocks(sb));
++	percpu_counter_set(&sbi->s_freeinodes_counter,
++			   ext4_count_free_inodes(sb));
++	percpu_counter_set(&sbi->s_dirs_counter,
++			   ext4_count_dirs(sb));
++	percpu_counter_set(&sbi->s_dirtyblocks_counter, 0);
+ 
++no_journal:
+ 	EXT4_SB(sb)->dio_unwritten_wq = create_workqueue("ext4-dio-unwritten");
+ 	if (!EXT4_SB(sb)->dio_unwritten_wq) {
+ 		printk(KERN_ERR "EXT4-fs: failed to create DIO workqueue\n");
+@@ -3610,10 +3625,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		jbd2_journal_destroy(sbi->s_journal);
+ 		sbi->s_journal = NULL;
+ 	}
+-	percpu_counter_destroy(&sbi->s_freeblocks_counter);
+-	percpu_counter_destroy(&sbi->s_freeinodes_counter);
+-	percpu_counter_destroy(&sbi->s_dirs_counter);
+-	percpu_counter_destroy(&sbi->s_dirtyblocks_counter);
+ failed_mount3:
+ 	if (sbi->s_flex_groups) {
+ 		if (is_vmalloc_addr(sbi->s_flex_groups))
+@@ -3621,6 +3632,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		else
+ 			kfree(sbi->s_flex_groups);
+ 	}
++	percpu_counter_destroy(&sbi->s_freeblocks_counter);
++	percpu_counter_destroy(&sbi->s_freeinodes_counter);
++	percpu_counter_destroy(&sbi->s_dirs_counter);
++	percpu_counter_destroy(&sbi->s_dirtyblocks_counter);
+ failed_mount2:
+ 	for (i = 0; i < db_count; i++)
+ 		brelse(sbi->s_group_desc[i]);
+@@ -3948,13 +3963,11 @@ static int ext4_commit_super(struct super_block *sb, int sync)
+ 	else
+ 		es->s_kbytes_written =
+ 			cpu_to_le64(EXT4_SB(sb)->s_kbytes_written);
+-	if (percpu_counter_initialized(&EXT4_SB(sb)->s_freeblocks_counter))
+-		ext4_free_blocks_count_set(es, percpu_counter_sum_positive(
+-					&EXT4_SB(sb)->s_freeblocks_counter));
+-	if (percpu_counter_initialized(&EXT4_SB(sb)->s_freeinodes_counter))
+-		es->s_free_inodes_count =
+-			cpu_to_le32(percpu_counter_sum_positive(
+-					&EXT4_SB(sb)->s_freeinodes_counter));
++	ext4_free_blocks_count_set(es, percpu_counter_sum_positive(
++					   &EXT4_SB(sb)->s_freeblocks_counter));
++	es->s_free_inodes_count =
++		cpu_to_le32(percpu_counter_sum_positive(
++				&EXT4_SB(sb)->s_freeinodes_counter));
+ 	sb->s_dirt = 0;
+ 	BUFFER_TRACE(sbh, "marking dirty");
+ 	mark_buffer_dirty(sbh);

commit b2c78cd09b6ef78c8f20190f0b3e6df1d3651b70
+Author: Theodore Ts'o 
+Date:   Tue Nov 2 14:19:30 2010 -0400
+
+    ext4: "ret" may be used uninitialized in ext4_lazyinit_thread()
+    
+    Newer GCC's reported the following build warning:
+    
+       fs/ext4/super.c: In function 'ext4_lazyinit_thread':
+       fs/ext4/super.c:2702: warning: 'ret' may be used uninitialized in this function
+    
+    Fix it by removing the need for the ret variable in the first place.
+    
+    Signed-off-by: "Lukas Czerner" 
+    Reported-by: "Stefan Richter" 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 8d1d9423ce9a..4d7ef31eacb1 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2699,7 +2699,6 @@ static int ext4_lazyinit_thread(void *arg)
+ 	struct ext4_li_request *elr;
+ 	unsigned long next_wakeup;
+ 	DEFINE_WAIT(wait);
+-	int ret;
+ 
+ 	BUG_ON(NULL == eli);
+ 
+@@ -2723,13 +2722,12 @@ static int ext4_lazyinit_thread(void *arg)
+ 			elr = list_entry(pos, struct ext4_li_request,
+ 					 lr_request);
+ 
+-			if (time_after_eq(jiffies, elr->lr_next_sched))
+-				ret = ext4_run_li_request(elr);
+-
+-			if (ret) {
+-				ret = 0;
+-				ext4_remove_li_request(elr);
+-				continue;
++			if (time_after_eq(jiffies, elr->lr_next_sched)) {
++				if (ext4_run_li_request(elr) != 0) {
++					/* error, remove the lazy_init job */
++					ext4_remove_li_request(elr);
++					continue;
++				}
+ 			}
+ 
+ 			if (time_before(elr->lr_next_sched, next_wakeup))

commit eb8abb927ae2fd1730e24ea94cd9527f3c086292
+Author: Theodore Ts'o 
+Date:   Tue Nov 2 09:34:50 2010 -0400
+
+    ext4: Remove useless spinlock in ext4_getattr()
+    
+    Linus noted, and complained to me, that doing while lots of "git diff"'s
+    of kernel sources, these spinlocks were responsible for 27% of the
+    spinlock cost on his two-processor system as reported by perf.
+    
+    Git was doing lots of parallel stats, and this was putting a lot of
+    pressure on ext4_getattr().  A spinlock to protect a single
+    memory-to-memory copy is pointless, so remove it.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 191616470466..4d78342f3bf0 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -5410,9 +5410,7 @@ int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ 	 * will return the blocks that include the delayed allocation
+ 	 * blocks for this file.
+ 	 */
+-	spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
+ 	delalloc_blocks = EXT4_I(inode)->i_reserved_data_blocks;
+-	spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+ 
+ 	stat->blocks += (delalloc_blocks << inode->i_sb->s_blocksize_bits)>>9;
+ 	return 0;

commit b1142e8fec6a594723e5054055a7b53379b90490
+Author: Theodore Ts'o 
+Date:   Thu Oct 28 17:33:57 2010 -0400
+
+    ext4: BUG_ON fix: check if page has buffers before calling page_buffers()
+    
+    We need to make check if a page does not have buffes by checking
+    page_has_buffers(page) before calling page_buffers(page) in
+    ext4_writepage().  Otherwise page_buffers() could throw a BUG_ON.
+    
+    Thanks also to Markus Trippelsdorf and Avinash Kurup who also reported
+    the problem.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reported-by: Sedat Dilek 
+    Tested-by: Sedat Dilek 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 2d6c6c8c036d..191616470466 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2718,7 +2718,7 @@ static int ext4_writepage(struct page *page,
+ 	 * try to create them using __block_write_begin.  If this
+ 	 * fails, redirty the page and move on.
+ 	 */
+-	if (!page_buffers(page)) {
++	if (!page_has_buffers(page)) {
+ 		if (__block_write_begin(page, 0, len,
+ 					noalloc_get_block_write)) {
+ 		redirty_page:
+@@ -2732,12 +2732,10 @@ static int ext4_writepage(struct page *page,
+ 	if (walk_page_buffers(NULL, page_bufs, 0, len, NULL,
+ 			      ext4_bh_delay_or_unwritten)) {
+ 		/*
+-		 * We don't want to do block allocation So redirty the
+-		 * page and return We may reach here when we do a
+-		 * journal commit via
+-		 * journal_submit_inode_data_buffers.  If we don't
+-		 * have mapping block we just ignore them. We can also
+-		 * reach here via shrink_page_list
++		 * We don't want to do block allocation, so redirty
++		 * the page and return.  We may reach here when we do
++		 * a journal commit via journal_submit_inode_data_buffers.
++		 * We can also reach here via shrink_page_list
+ 		 */
+ 		goto redirty_page;
+ 	}

commit a107e5a3a473a2ea62bd5af24e11b84adf1486ff
+Merge: e3e1288e86a0 a269029d0e21
+Author: Theodore Ts'o 
+Date:   Wed Oct 27 23:44:47 2010 -0400
+
+    Merge branch 'next' into upstream-merge
+    
+    Conflicts:
+            fs/ext4/inode.c
+            fs/ext4/mballoc.c
+            include/trace/events/ext4.h
+
+diff --cc fs/ext4/extents.c
+index 06328d3e5717,a17a676a3106..0554c48cb1fd
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@@ -2538,74 -2491,19 +2491,18 @@@ void ext4_ext_release(struct super_bloc
+  /* FIXME!! we need to try to merge to left or right after zero-out  */
+  static int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex)
+  {
++ 	ext4_fsblk_t ee_pblock;
++ 	unsigned int ee_len;
+  	int ret;
+- 	struct bio *bio;
+- 	int blkbits, blocksize;
+- 	sector_t ee_pblock;
+- 	struct completion event;
+- 	unsigned int ee_len, len, done, offset;
+  
+- 
+- 	blkbits   = inode->i_blkbits;
+- 	blocksize = inode->i_sb->s_blocksize;
+  	ee_len    = ext4_ext_get_actual_len(ex);
+- 	ee_pblock = ext_pblock(ex);
+- 
+- 	/* convert ee_pblock to 512 byte sectors */
+- 	ee_pblock = ee_pblock << (blkbits - 9);
+- 
+- 	while (ee_len > 0) {
+- 
+- 		if (ee_len > BIO_MAX_PAGES)
+- 			len = BIO_MAX_PAGES;
+- 		else
+- 			len = ee_len;
+- 
+- 		bio = bio_alloc(GFP_NOIO, len);
+- 		if (!bio)
+- 			return -ENOMEM;
++ 	ee_pblock = ext4_ext_pblock(ex);
+  
+- 		bio->bi_sector = ee_pblock;
+- 		bio->bi_bdev   = inode->i_sb->s_bdev;
+ -	ret = sb_issue_zeroout(inode->i_sb, ee_pblock, ee_len,
+ -			       GFP_NOFS, BLKDEV_IFL_WAIT);
+++	ret = sb_issue_zeroout(inode->i_sb, ee_pblock, ee_len, GFP_NOFS);
++ 	if (ret > 0)
++ 		ret = 0;
+  
+- 		done = 0;
+- 		offset = 0;
+- 		while (done < len) {
+- 			ret = bio_add_page(bio, ZERO_PAGE(0),
+- 							blocksize, offset);
+- 			if (ret != blocksize) {
+- 				/*
+- 				 * We can't add any more pages because of
+- 				 * hardware limitations.  Start a new bio.
+- 				 */
+- 				break;
+- 			}
+- 			done++;
+- 			offset += blocksize;
+- 			if (offset >= PAGE_CACHE_SIZE)
+- 				offset = 0;
+- 		}
+- 
+- 		init_completion(&event);
+- 		bio->bi_private = &event;
+- 		bio->bi_end_io = bi_complete;
+- 		submit_bio(WRITE, bio);
+- 		wait_for_completion(&event);
+- 
+- 		if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) {
+- 			bio_put(bio);
+- 			return -EIO;
+- 		}
+- 		bio_put(bio);
+- 		ee_len    -= done;
+- 		ee_pblock += done  << (blkbits - 9);
+- 	}
+- 	return 0;
++ 	return ret;
+  }
+  
+  #define EXT4_EXT_ZERO_LEN 7
+diff --cc fs/ext4/ialloc.c
+index 45853e0d1f21,509f429f71e8..1ce240a23ebb
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@@ -1205,3 -1220,110 +1220,109 @@@ unsigned long ext4_count_dirs(struct su
+  	}
+  	return count;
+  }
++ 
++ /*
++  * Zeroes not yet zeroed inode table - just write zeroes through the whole
++  * inode table. Must be called without any spinlock held. The only place
++  * where it is called from on active part of filesystem is ext4lazyinit
++  * thread, so we do not need any special locks, however we have to prevent
++  * inode allocation from the current group, so we take alloc_sem lock, to
++  * block ext4_claim_inode until we are finished.
++  */
++ extern int ext4_init_inode_table(struct super_block *sb, ext4_group_t group,
++ 				 int barrier)
++ {
++ 	struct ext4_group_info *grp = ext4_get_group_info(sb, group);
++ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
++ 	struct ext4_group_desc *gdp = NULL;
++ 	struct buffer_head *group_desc_bh;
++ 	handle_t *handle;
++ 	ext4_fsblk_t blk;
++ 	int num, ret = 0, used_blks = 0;
+ -	unsigned long flags = BLKDEV_IFL_WAIT;
++ 
++ 	/* This should not happen, but just to be sure check this */
++ 	if (sb->s_flags & MS_RDONLY) {
++ 		ret = 1;
++ 		goto out;
++ 	}
++ 
++ 	gdp = ext4_get_group_desc(sb, group, &group_desc_bh);
++ 	if (!gdp)
++ 		goto out;
++ 
++ 	/*
++ 	 * We do not need to lock this, because we are the only one
++ 	 * handling this flag.
++ 	 */
++ 	if (gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED))
++ 		goto out;
++ 
++ 	handle = ext4_journal_start_sb(sb, 1);
++ 	if (IS_ERR(handle)) {
++ 		ret = PTR_ERR(handle);
++ 		goto out;
++ 	}
++ 
++ 	down_write(&grp->alloc_sem);
++ 	/*
++ 	 * If inode bitmap was already initialized there may be some
++ 	 * used inodes so we need to skip blocks with used inodes in
++ 	 * inode table.
++ 	 */
++ 	if (!(gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)))
++ 		used_blks = DIV_ROUND_UP((EXT4_INODES_PER_GROUP(sb) -
++ 			    ext4_itable_unused_count(sb, gdp)),
++ 			    sbi->s_inodes_per_block);
++ 
++ 	if ((used_blks < 0) || (used_blks > sbi->s_itb_per_group)) {
++ 		ext4_error(sb, "Something is wrong with group %u\n"
++ 			   "Used itable blocks: %d"
++ 			   "itable unused count: %u\n",
++ 			   group, used_blks,
++ 			   ext4_itable_unused_count(sb, gdp));
++ 		ret = 1;
++ 		goto out;
++ 	}
++ 
++ 	blk = ext4_inode_table(sb, gdp) + used_blks;
++ 	num = sbi->s_itb_per_group - used_blks;
++ 
++ 	BUFFER_TRACE(group_desc_bh, "get_write_access");
++ 	ret = ext4_journal_get_write_access(handle,
++ 					    group_desc_bh);
++ 	if (ret)
++ 		goto err_out;
++ 
++ 	/*
++ 	 * Skip zeroout if the inode table is full. But we set the ZEROED
++ 	 * flag anyway, because obviously, when it is full it does not need
++ 	 * further zeroing.
++ 	 */
++ 	if (unlikely(num == 0))
++ 		goto skip_zeroout;
++ 
++ 	ext4_debug("going to zero out inode table in group %d\n",
++ 		   group);
+ -	if (barrier)
+ -		flags |= BLKDEV_IFL_BARRIER;
+ -	ret = sb_issue_zeroout(sb, blk, num, GFP_NOFS, flags);
+++	ret = sb_issue_zeroout(sb, blk, num, GFP_NOFS);
++ 	if (ret < 0)
++ 		goto err_out;
+++	if (barrier)
+++		blkdev_issue_flush(sb->s_bdev, GFP_NOFS, NULL);
++ 
++ skip_zeroout:
++ 	ext4_lock_group(sb, group);
++ 	gdp->bg_flags |= cpu_to_le16(EXT4_BG_INODE_ZEROED);
++ 	gdp->bg_checksum = ext4_group_desc_csum(sbi, group, gdp);
++ 	ext4_unlock_group(sb, group);
++ 
++ 	BUFFER_TRACE(group_desc_bh,
++ 		     "call ext4_handle_dirty_metadata");
++ 	ret = ext4_handle_dirty_metadata(handle, NULL,
++ 					 group_desc_bh);
++ 
++ err_out:
++ 	up_write(&grp->alloc_sem);
++ 	ext4_journal_stop(handle);
++ out:
++ 	return ret;
++ }
+diff --cc fs/ext4/inode.c
+index 49635ef236f8,3ba237b0b2aa..2d6c6c8c036d
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@@ -2030,86 -2062,32 +2062,32 @@@ static int mpage_da_submit_io(struct mp
+  			BUG_ON(!PageLocked(page));
+  			BUG_ON(PageWriteback(page));
+  
+- 			pages_skipped = mpd->wbc->pages_skipped;
+- 			err = mapping->a_ops->writepage(page, mpd->wbc);
+- 			if (!err && (pages_skipped == mpd->wbc->pages_skipped))
+- 				/*
+- 				 * have successfully written the page
+- 				 * without skipping the same
+- 				 */
+- 				mpd->pages_written++;
+  			/*
+- 			 * In error case, we have to continue because
+- 			 * remaining pages are still locked
+- 			 * XXX: unlock and re-dirty them?
++ 			 * If the page does not have buffers (for
++ 			 * whatever reason), try to create them using
+ -			 * block_prepare_write.  If this fails,
+++			 * __block_write_begin.  If this fails,
++ 			 * redirty the page and move on.
+  			 */
+- 			if (ret == 0)
+- 				ret = err;
+- 		}
+- 		pagevec_release(&pvec);
+- 	}
+- 	return ret;
+- }
+- 
+- /*
+-  * mpage_put_bnr_to_bhs - walk blocks and assign them actual numbers
+-  *
+-  * the function goes through all passed space and put actual disk
+-  * block numbers into buffer heads, dropping BH_Delay and BH_Unwritten
+-  */
+- static void mpage_put_bnr_to_bhs(struct mpage_da_data *mpd,
+- 				 struct ext4_map_blocks *map)
+- {
+- 	struct inode *inode = mpd->inode;
+- 	struct address_space *mapping = inode->i_mapping;
+- 	int blocks = map->m_len;
+- 	sector_t pblock = map->m_pblk, cur_logical;
+- 	struct buffer_head *head, *bh;
+- 	pgoff_t index, end;
+- 	struct pagevec pvec;
+- 	int nr_pages, i;
+- 
+- 	index = map->m_lblk >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
+- 	end = (map->m_lblk + blocks - 1) >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
+- 	cur_logical = index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
+- 
+- 	pagevec_init(&pvec, 0);
+- 
+- 	while (index <= end) {
+- 		/* XXX: optimize tail */
+- 		nr_pages = pagevec_lookup(&pvec, mapping, index, PAGEVEC_SIZE);
+- 		if (nr_pages == 0)
+- 			break;
+- 		for (i = 0; i < nr_pages; i++) {
+- 			struct page *page = pvec.pages[i];
+- 
+- 			index = page->index;
+- 			if (index > end)
+- 				break;
+- 			index++;
+- 
+- 			BUG_ON(!PageLocked(page));
+- 			BUG_ON(PageWriteback(page));
+- 			BUG_ON(!page_has_buffers(page));
+- 
+- 			bh = page_buffers(page);
+- 			head = bh;
+- 
+- 			/* skip blocks out of the range */
+- 			do {
+- 				if (cur_logical >= map->m_lblk)
+- 					break;
+- 				cur_logical++;
+- 			} while ((bh = bh->b_this_page) != head);
++ 			if (!page_has_buffers(page)) {
+ -				if (block_prepare_write(page, 0, len,
+++				if (__block_write_begin(page, 0, len,
++ 						noalloc_get_block_write)) {
++ 				redirty_page:
++ 					redirty_page_for_writepage(mpd->wbc,
++ 								   page);
++ 					unlock_page(page);
++ 					continue;
++ 				}
++ 				commit_write = 1;
++ 			}
+  
++ 			bh = page_bufs = page_buffers(page);
++ 			block_start = 0;
+  			do {
+- 				if (cur_logical >= map->m_lblk + blocks)
+- 					break;
+- 
+- 				if (buffer_delay(bh) || buffer_unwritten(bh)) {
+- 
+- 					BUG_ON(bh->b_bdev != inode->i_sb->s_bdev);
+- 
++ 				if (!bh)
++ 					goto redirty_page;
++ 				if (map && (cur_logical >= map->m_lblk) &&
++ 				    (cur_logical <= (map->m_lblk +
++ 						     (map->m_len - 1)))) {
+  					if (buffer_delay(bh)) {
+  						clear_buffer_delay(bh);
+  						bh->b_blocknr = pblock;
+@@@ -2712,18 -2714,15 +2713,15 @@@ static int ext4_writepage(struct page *
+  	else
+  		len = PAGE_CACHE_SIZE;
+  
+- 	if (page_has_buffers(page)) {
+- 		page_bufs = page_buffers(page);
+- 		if (walk_page_buffers(NULL, page_bufs, 0, len, NULL,
+- 					ext4_bh_delay_or_unwritten)) {
+- 			/*
+- 			 * We don't want to do  block allocation
+- 			 * So redirty the page and return
+- 			 * We may reach here when we do a journal commit
+- 			 * via journal_submit_inode_data_buffers.
+- 			 * If we don't have mapping block we just ignore
+- 			 * them. We can also reach here via shrink_page_list
+- 			 */
++ 	/*
++ 	 * If the page does not have buffers (for whatever reason),
+ -	 * try to create them using block_prepare_write.  If this
+++	 * try to create them using __block_write_begin.  If this
++ 	 * fails, redirty the page and move on.
++ 	 */
++ 	if (!page_buffers(page)) {
+ -		if (block_prepare_write(page, 0, len,
+++		if (__block_write_begin(page, 0, len,
++ 					noalloc_get_block_write)) {
++ 		redirty_page:
+  			redirty_page_for_writepage(wbc, page);
+  			unlock_page(page);
+  			return 0;
+diff --cc fs/ext4/mballoc.c
+index 42f77b1dc72d,328ea9cec57b..c58eba34724a
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@@ -2567,8 -2613,8 +2614,8 @@@ static inline int ext4_issue_discard(st
+  	discard_block = block + ext4_group_first_block_no(sb, block_group);
+  	trace_ext4_discard_blocks(sb,
+  			(unsigned long long) discard_block, count);
+ -	ret = sb_issue_discard(sb, discard_block, count);
+ +	ret = sb_issue_discard(sb, discard_block, count, GFP_NOFS, 0);
+- 	if (ret == EOPNOTSUPP) {
++ 	if (ret == -EOPNOTSUPP) {
+  		ext4_warning(sb, "discard not supported, disabling");
+  		clear_opt(EXT4_SB(sb)->s_mount_opt, DISCARD);
+  	}
+diff --cc fs/ext4/resize.c
+index ca5c8aa00a2f,f398474e2784..dc963929de65
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@@ -226,23 -226,13 +226,13 @@@ static int setup_new_group_blocks(struc
+  	}
+  
+  	/* Zero out all of the reserved backup group descriptor table blocks */
+- 	for (i = 0, bit = gdblocks + 1, block = start + bit;
+- 	     i < reserved_gdb; i++, block++, bit++) {
+- 		struct buffer_head *gdb;
+- 
+- 		ext4_debug("clear reserved block %#04llx (+%d)\n", block, bit);
+- 
+- 		if ((err = extend_or_restart_transaction(handle, 1, bh)))
+- 			goto exit_bh;
++ 	ext4_debug("clear inode table blocks %#04llx -> %#04llx\n",
++ 			block, sbi->s_itb_per_group);
++ 	err = sb_issue_zeroout(sb, gdblocks + start + 1, reserved_gdb,
+ -			       GFP_NOFS, BLKDEV_IFL_WAIT);
+++			       GFP_NOFS);
++ 	if (err)
++ 		goto exit_bh;
+  
+- 		if (IS_ERR(gdb = bclean(handle, sb, block))) {
+- 			err = PTR_ERR(gdb);
+- 			goto exit_bh;
+- 		}
+- 		ext4_handle_dirty_metadata(handle, NULL, gdb);
+- 		ext4_set_bit(bit, bh->b_data);
+- 		brelse(gdb);
+- 	}
+  	ext4_debug("mark block bitmap %#04llx (+%llu)\n", input->block_bitmap,
+  		   input->block_bitmap - start);
+  	ext4_set_bit(input->block_bitmap - start, bh->b_data);
+@@@ -251,23 -241,13 +241,12 @@@
+  	ext4_set_bit(input->inode_bitmap - start, bh->b_data);
+  
+  	/* Zero out all of the inode table blocks */
+- 	for (i = 0, block = input->inode_table, bit = block - start;
+- 	     i < sbi->s_itb_per_group; i++, bit++, block++) {
+- 		struct buffer_head *it;
+- 
+- 		ext4_debug("clear inode block %#04llx (+%d)\n", block, bit);
+- 
+- 		if ((err = extend_or_restart_transaction(handle, 1, bh)))
+- 			goto exit_bh;
+- 
+- 		if (IS_ERR(it = bclean(handle, sb, block))) {
+- 			err = PTR_ERR(it);
+- 			goto exit_bh;
+- 		}
+- 		ext4_handle_dirty_metadata(handle, NULL, it);
+- 		brelse(it);
+- 		ext4_set_bit(bit, bh->b_data);
+- 	}
++ 	block = input->inode_table;
++ 	ext4_debug("clear inode table blocks %#04llx -> %#04llx\n",
++ 			block, sbi->s_itb_per_group);
+ -	err = sb_issue_zeroout(sb, block, sbi->s_itb_per_group,
+ -			       GFP_NOFS, BLKDEV_IFL_WAIT);
+++	err = sb_issue_zeroout(sb, block, sbi->s_itb_per_group, GFP_NOFS);
++ 	if (err)
++ 		goto exit_bh;
+  
+  	if ((err = extend_or_restart_transaction(handle, 2, bh)))
+  		goto exit_bh;
+diff --cc include/linux/blkdev.h
+index 646b462d04df,e5cb4d029689..5027a599077d
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@@ -883,14 -932,23 +883,22 @@@ extern int blkdev_issue_flush(struct bl
+  extern int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
+  		sector_t nr_sects, gfp_t gfp_mask, unsigned long flags);
+  extern int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
+ -			sector_t nr_sects, gfp_t gfp_mask, unsigned long flags);
+ -static inline int sb_issue_discard(struct super_block *sb,
+ -				   sector_t block, sector_t nr_blocks)
+ +			sector_t nr_sects, gfp_t gfp_mask);
+ +static inline int sb_issue_discard(struct super_block *sb, sector_t block,
+ +		sector_t nr_blocks, gfp_t gfp_mask, unsigned long flags)
+  {
+ -	block <<= (sb->s_blocksize_bits - 9);
+ -	nr_blocks <<= (sb->s_blocksize_bits - 9);
+ -	return blkdev_issue_discard(sb->s_bdev, block, nr_blocks, GFP_NOFS,
+ -				   BLKDEV_IFL_WAIT | BLKDEV_IFL_BARRIER);
+ +	return blkdev_issue_discard(sb->s_bdev, block << (sb->s_blocksize_bits - 9),
+ +				    nr_blocks << (sb->s_blocksize_bits - 9),
+ +				    gfp_mask, flags);
+  }
++ static inline int sb_issue_zeroout(struct super_block *sb, sector_t block,
+ -		sector_t nr_blocks, gfp_t gfp_mask, unsigned long flags)
+++		sector_t nr_blocks, gfp_t gfp_mask)
++ {
++ 	return blkdev_issue_zeroout(sb->s_bdev,
++ 				    block << (sb->s_blocksize_bits - 9),
++ 				    nr_blocks << (sb->s_blocksize_bits - 9),
+ -				    gfp_mask, flags);
+++				    gfp_mask);
++ }
+  
+  extern int blk_verify_command(unsigned char *cmd, fmode_t has_write_perm);
+  
+diff --cc include/linux/fs.h
+index b2a6009cba10,7008268e9b5a..6ed7ace74b7c
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@@ -32,11 -32,17 +32,17 @@@
+  #define SEEK_END	2	/* seek relative to end of file */
+  #define SEEK_MAX	SEEK_END
+  
++ struct fstrim_range {
++ 	uint64_t start;
++ 	uint64_t len;
++ 	uint64_t minlen;
++ };
++ 
+  /* And dynamically-tunable limits and defaults: */
+  struct files_stat_struct {
+ -	int nr_files;		/* read only */
+ -	int nr_free_files;	/* read only */
+ -	int max_files;		/* tunable */
+ +	unsigned long nr_files;		/* read only */
+ +	unsigned long nr_free_files;	/* read only */
+ +	unsigned long max_files;		/* tunable */
+  };
+  
+  struct inodes_stat_t {
+diff --cc include/trace/events/ext4.h
+index 6bcb00645de4,8f59db107bbb..289010d3270b
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@@ -228,7 -245,7 +245,6 @@@ TRACE_EVENT(ext4_da_writepages
+  		__field(	long,	pages_skipped		)
+  		__field(	loff_t,	range_start		)
+  		__field(	loff_t,	range_end		)
+--		__field(	char,	nonblocking		)
+  		__field(	char,	for_kupdate		)
+  		__field(	char,	for_reclaim		)
+  		__field(	char,	range_cyclic		)
+@@@ -248,14 -267,11 +265,14 @@@
+  		__entry->writeback_index = inode->i_mapping->writeback_index;
+  	),
+  
+- 	TP_printk("dev %s ino %lu nr_to_write %ld pages_skipped %ld "
+ -	TP_printk("dev %d,%d ino %lu nr_to_write %ld pages_skipped %ld range_start %llu range_end %llu nonblocking %d for_kupdate %d for_reclaim %d range_cyclic %d writeback_index %lu",
+++	TP_printk("dev %d,%d ino %lu nr_to_write %ld pages_skipped %ld "
+ +		  "range_start %llu range_end %llu "
+ +		  "for_kupdate %d for_reclaim %d "
+ +		  "range_cyclic %d writeback_index %lu",
+- 		  jbd2_dev_to_name(__entry->dev),
++ 		  __entry->dev_major, __entry->dev_minor,
+  		  (unsigned long) __entry->ino, __entry->nr_to_write,
+  		  __entry->pages_skipped, __entry->range_start,
+ -		  __entry->range_end, __entry->nonblocking,
+ +		  __entry->range_end,
+  		  __entry->for_kupdate, __entry->for_reclaim,
+  		  __entry->range_cyclic,
+  		  (unsigned long) __entry->writeback_index)

commit a269029d0e2192046be4c07ed78a45022469ee4c
+Author: Theodore Ts'o 
+Date:   Wed Oct 27 22:08:50 2010 -0400
+
+    ext4,jbd2: convert tracepoints to use major/minor numbers
+    
+    Unfortunately perf can't deal with anything other than direct structure
+    accesses in the TP_printk() section.  It will drop dead when it sees
+    jbd2_dev_to_name() in the "print fmt" section of the tracepoint.
+    
+    Addresses-Google-Bug: 3138508
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index b5f4938d612d..8f59db107bbb 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -21,7 +21,8 @@ TRACE_EVENT(ext4_free_inode,
+ 	TP_ARGS(inode),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	ino_t,	ino			)
+ 		__field(	umode_t, mode			)
+ 		__field(	uid_t,	uid			)
+@@ -30,7 +31,8 @@ TRACE_EVENT(ext4_free_inode,
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev	= inode->i_sb->s_dev;
++		__entry->dev_major = MAJOR(inode->i_sb->s_dev);
++		__entry->dev_minor = MINOR(inode->i_sb->s_dev);
+ 		__entry->ino	= inode->i_ino;
+ 		__entry->mode	= inode->i_mode;
+ 		__entry->uid	= inode->i_uid;
+@@ -38,9 +40,10 @@ TRACE_EVENT(ext4_free_inode,
+ 		__entry->blocks	= inode->i_blocks;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu mode 0%o uid %u gid %u blocks %llu",
+-		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
+-		  __entry->mode, __entry->uid, __entry->gid,
++	TP_printk("dev %d,%d ino %lu mode 0%o uid %u gid %u blocks %llu",
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->ino, __entry->mode,
++		  __entry->uid, __entry->gid,
+ 		  (unsigned long long) __entry->blocks)
+ );
+ 
+@@ -50,20 +53,22 @@ TRACE_EVENT(ext4_request_inode,
+ 	TP_ARGS(dir, mode),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	ino_t,	dir			)
+ 		__field(	umode_t, mode			)
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev	= dir->i_sb->s_dev;
++		__entry->dev_major = MAJOR(dir->i_sb->s_dev);
++		__entry->dev_minor = MINOR(dir->i_sb->s_dev);
+ 		__entry->dir	= dir->i_ino;
+ 		__entry->mode	= mode;
+ 	),
+ 
+-	TP_printk("dev %s dir %lu mode 0%o",
+-		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->dir,
+-		  __entry->mode)
++	TP_printk("dev %d,%d dir %lu mode 0%o",
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->dir, __entry->mode)
+ );
+ 
+ TRACE_EVENT(ext4_allocate_inode,
+@@ -72,21 +77,24 @@ TRACE_EVENT(ext4_allocate_inode,
+ 	TP_ARGS(inode, dir, mode),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	ino_t,	ino			)
+ 		__field(	ino_t,	dir			)
+ 		__field(	umode_t, mode			)
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev	= inode->i_sb->s_dev;
++		__entry->dev_major = MAJOR(inode->i_sb->s_dev);
++		__entry->dev_minor = MINOR(inode->i_sb->s_dev);
+ 		__entry->ino	= inode->i_ino;
+ 		__entry->dir	= dir->i_ino;
+ 		__entry->mode	= mode;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu dir %lu mode 0%o",
+-		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++	TP_printk("dev %d,%d ino %lu dir %lu mode 0%o",
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->ino,
+ 		  (unsigned long) __entry->dir, __entry->mode)
+ );
+ 
+@@ -98,7 +106,8 @@ DECLARE_EVENT_CLASS(ext4__write_begin,
+ 	TP_ARGS(inode, pos, len, flags),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	ino_t,	ino			)
+ 		__field(	loff_t,	pos			)
+ 		__field(	unsigned int, len		)
+@@ -106,15 +115,17 @@ DECLARE_EVENT_CLASS(ext4__write_begin,
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev	= inode->i_sb->s_dev;
++		__entry->dev_major = MAJOR(inode->i_sb->s_dev);
++		__entry->dev_minor = MINOR(inode->i_sb->s_dev);
+ 		__entry->ino	= inode->i_ino;
+ 		__entry->pos	= pos;
+ 		__entry->len	= len;
+ 		__entry->flags	= flags;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu pos %llu len %u flags %u",
+-		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++	TP_printk("dev %d,%d ino %lu pos %llu len %u flags %u",
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->ino,
+ 		  __entry->pos, __entry->len, __entry->flags)
+ );
+ 
+@@ -141,7 +152,8 @@ DECLARE_EVENT_CLASS(ext4__write_end,
+ 	TP_ARGS(inode, pos, len, copied),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	ino_t,	ino			)
+ 		__field(	loff_t,	pos			)
+ 		__field(	unsigned int, len		)
+@@ -149,16 +161,18 @@ DECLARE_EVENT_CLASS(ext4__write_end,
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev	= inode->i_sb->s_dev;
++		__entry->dev_major = MAJOR(inode->i_sb->s_dev);
++		__entry->dev_minor = MINOR(inode->i_sb->s_dev);
+ 		__entry->ino	= inode->i_ino;
+ 		__entry->pos	= pos;
+ 		__entry->len	= len;
+ 		__entry->copied	= copied;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu pos %llu len %u copied %u",
+-		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
+-		  __entry->pos, __entry->len, __entry->copied)
++	TP_printk("dev %d,%d ino %lu pos %llu len %u copied %u",
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->ino, __entry->pos,
++		  __entry->len, __entry->copied)
+ );
+ 
+ DEFINE_EVENT(ext4__write_end, ext4_ordered_write_end,
+@@ -199,21 +213,23 @@ TRACE_EVENT(ext4_writepage,
+ 	TP_ARGS(inode, page),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	ino_t,	ino			)
+ 		__field(	pgoff_t, index			)
+ 
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev	= inode->i_sb->s_dev;
++		__entry->dev_major = MAJOR(inode->i_sb->s_dev);
++		__entry->dev_minor = MINOR(inode->i_sb->s_dev);
+ 		__entry->ino	= inode->i_ino;
+ 		__entry->index	= page->index;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu page_index %lu",
+-		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
+-		  __entry->index)
++	TP_printk("dev %d,%d ino %lu page_index %lu",
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->ino, __entry->index)
+ );
+ 
+ TRACE_EVENT(ext4_da_writepages,
+@@ -222,7 +238,8 @@ TRACE_EVENT(ext4_da_writepages,
+ 	TP_ARGS(inode, wbc),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	ino_t,	ino			)
+ 		__field(	long,	nr_to_write		)
+ 		__field(	long,	pages_skipped		)
+@@ -236,7 +253,8 @@ TRACE_EVENT(ext4_da_writepages,
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev		= inode->i_sb->s_dev;
++		__entry->dev_major	= MAJOR(inode->i_sb->s_dev);
++		__entry->dev_minor	= MINOR(inode->i_sb->s_dev);
+ 		__entry->ino		= inode->i_ino;
+ 		__entry->nr_to_write	= wbc->nr_to_write;
+ 		__entry->pages_skipped	= wbc->pages_skipped;
+@@ -249,8 +267,8 @@ TRACE_EVENT(ext4_da_writepages,
+ 		__entry->writeback_index = inode->i_mapping->writeback_index;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu nr_to_write %ld pages_skipped %ld range_start %llu range_end %llu nonblocking %d for_kupdate %d for_reclaim %d range_cyclic %d writeback_index %lu",
+-		  jbd2_dev_to_name(__entry->dev),
++	TP_printk("dev %d,%d ino %lu nr_to_write %ld pages_skipped %ld range_start %llu range_end %llu nonblocking %d for_kupdate %d for_reclaim %d range_cyclic %d writeback_index %lu",
++		  __entry->dev_major, __entry->dev_minor,
+ 		  (unsigned long) __entry->ino, __entry->nr_to_write,
+ 		  __entry->pages_skipped, __entry->range_start,
+ 		  __entry->range_end, __entry->nonblocking,
+@@ -265,7 +283,8 @@ TRACE_EVENT(ext4_da_write_pages,
+ 	TP_ARGS(inode, mpd),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	ino_t,	ino			)
+ 		__field(	__u64,	b_blocknr		)
+ 		__field(	__u32,	b_size			)
+@@ -276,7 +295,8 @@ TRACE_EVENT(ext4_da_write_pages,
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev		= inode->i_sb->s_dev;
++		__entry->dev_major	= MAJOR(inode->i_sb->s_dev);
++		__entry->dev_minor	= MINOR(inode->i_sb->s_dev);
+ 		__entry->ino		= inode->i_ino;
+ 		__entry->b_blocknr	= mpd->b_blocknr;
+ 		__entry->b_size		= mpd->b_size;
+@@ -286,8 +306,9 @@ TRACE_EVENT(ext4_da_write_pages,
+ 		__entry->pages_written	= mpd->pages_written;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu b_blocknr %llu b_size %u b_state 0x%04x first_page %lu io_done %d pages_written %d",
+-		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++	TP_printk("dev %d,%d ino %lu b_blocknr %llu b_size %u b_state 0x%04x first_page %lu io_done %d pages_written %d",
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->ino,
+ 		  __entry->b_blocknr, __entry->b_size,
+ 		  __entry->b_state, __entry->first_page,
+ 		  __entry->io_done, __entry->pages_written)
+@@ -300,7 +321,8 @@ TRACE_EVENT(ext4_da_writepages_result,
+ 	TP_ARGS(inode, wbc, ret, pages_written),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	ino_t,	ino			)
+ 		__field(	int,	ret			)
+ 		__field(	int,	pages_written		)
+@@ -310,7 +332,8 @@ TRACE_EVENT(ext4_da_writepages_result,
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev		= inode->i_sb->s_dev;
++		__entry->dev_major	= MAJOR(inode->i_sb->s_dev);
++		__entry->dev_minor	= MINOR(inode->i_sb->s_dev);
+ 		__entry->ino		= inode->i_ino;
+ 		__entry->ret		= ret;
+ 		__entry->pages_written	= pages_written;
+@@ -319,8 +342,8 @@ TRACE_EVENT(ext4_da_writepages_result,
+ 		__entry->writeback_index = inode->i_mapping->writeback_index;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu ret %d pages_written %d pages_skipped %ld more_io %d writeback_index %lu",
+-		  jbd2_dev_to_name(__entry->dev),
++	TP_printk("dev %d,%d ino %lu ret %d pages_written %d pages_skipped %ld more_io %d writeback_index %lu",
++		  __entry->dev_major, __entry->dev_minor,
+ 		  (unsigned long) __entry->ino, __entry->ret,
+ 		  __entry->pages_written, __entry->pages_skipped,
+ 		  __entry->more_io,
+@@ -334,20 +357,23 @@ TRACE_EVENT(ext4_discard_blocks,
+ 	TP_ARGS(sb, blk, count),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	__u64,	blk			)
+ 		__field(	__u64,	count			)
+ 
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev	= sb->s_dev;
++		__entry->dev_major = MAJOR(sb->s_dev);
++		__entry->dev_minor = MINOR(sb->s_dev);
+ 		__entry->blk	= blk;
+ 		__entry->count	= count;
+ 	),
+ 
+-	TP_printk("dev %s blk %llu count %llu",
+-		  jbd2_dev_to_name(__entry->dev), __entry->blk, __entry->count)
++	TP_printk("dev %d,%d blk %llu count %llu",
++		  __entry->dev_major, __entry->dev_minor,
++		  __entry->blk, __entry->count)
+ );
+ 
+ DECLARE_EVENT_CLASS(ext4__mb_new_pa,
+@@ -357,7 +383,8 @@ DECLARE_EVENT_CLASS(ext4__mb_new_pa,
+ 	TP_ARGS(ac, pa),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	ino_t,	ino			)
+ 		__field(	__u64,	pa_pstart		)
+ 		__field(	__u32,	pa_len			)
+@@ -366,16 +393,18 @@ DECLARE_EVENT_CLASS(ext4__mb_new_pa,
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev		= ac->ac_sb->s_dev;
++		__entry->dev_major	= MAJOR(ac->ac_sb->s_dev);
++		__entry->dev_minor	= MINOR(ac->ac_sb->s_dev);
+ 		__entry->ino		= ac->ac_inode->i_ino;
+ 		__entry->pa_pstart	= pa->pa_pstart;
+ 		__entry->pa_len		= pa->pa_len;
+ 		__entry->pa_lstart	= pa->pa_lstart;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu pstart %llu len %u lstart %llu",
+-		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
+-		  __entry->pa_pstart, __entry->pa_len, __entry->pa_lstart)
++	TP_printk("dev %d,%d ino %lu pstart %llu len %u lstart %llu",
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->ino, __entry->pa_pstart,
++		  __entry->pa_len, __entry->pa_lstart)
+ );
+ 
+ DEFINE_EVENT(ext4__mb_new_pa, ext4_mb_new_inode_pa,
+@@ -403,7 +432,8 @@ TRACE_EVENT(ext4_mb_release_inode_pa,
+ 	TP_ARGS(sb, inode, pa, block, count),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	ino_t,	ino			)
+ 		__field(	__u64,	block			)
+ 		__field(	__u32,	count			)
+@@ -411,15 +441,16 @@ TRACE_EVENT(ext4_mb_release_inode_pa,
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev		= sb->s_dev;
++		__entry->dev_major	= MAJOR(sb->s_dev);
++		__entry->dev_minor	= MINOR(sb->s_dev);
+ 		__entry->ino		= inode->i_ino;
+ 		__entry->block		= block;
+ 		__entry->count		= count;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu block %llu count %u",
+-		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
+-		  __entry->block, __entry->count)
++	TP_printk("dev %d,%d ino %lu block %llu count %u",
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->ino, __entry->block, __entry->count)
+ );
+ 
+ TRACE_EVENT(ext4_mb_release_group_pa,
+@@ -429,20 +460,23 @@ TRACE_EVENT(ext4_mb_release_group_pa,
+ 	TP_ARGS(sb, pa),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	__u64,	pa_pstart		)
+ 		__field(	__u32,	pa_len			)
+ 
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev		= sb->s_dev;
++		__entry->dev_major	= MAJOR(sb->s_dev);
++		__entry->dev_minor	= MINOR(sb->s_dev);
+ 		__entry->pa_pstart	= pa->pa_pstart;
+ 		__entry->pa_len		= pa->pa_len;
+ 	),
+ 
+-	TP_printk("dev %s pstart %llu len %u",
+-		  jbd2_dev_to_name(__entry->dev), __entry->pa_pstart, __entry->pa_len)
++	TP_printk("dev %d,%d pstart %llu len %u",
++		  __entry->dev_major, __entry->dev_minor,
++		  __entry->pa_pstart, __entry->pa_len)
+ );
+ 
+ TRACE_EVENT(ext4_discard_preallocations,
+@@ -451,18 +485,21 @@ TRACE_EVENT(ext4_discard_preallocations,
+ 	TP_ARGS(inode),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	ino_t,	ino			)
+ 
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev	= inode->i_sb->s_dev;
++		__entry->dev_major = MAJOR(inode->i_sb->s_dev);
++		__entry->dev_minor = MINOR(inode->i_sb->s_dev);
+ 		__entry->ino	= inode->i_ino;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu",
+-		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino)
++	TP_printk("dev %d,%d ino %lu",
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->ino)
+ );
+ 
+ TRACE_EVENT(ext4_mb_discard_preallocations,
+@@ -471,18 +508,20 @@ TRACE_EVENT(ext4_mb_discard_preallocations,
+ 	TP_ARGS(sb, needed),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	int,	needed			)
+ 
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev	= sb->s_dev;
++		__entry->dev_major = MAJOR(sb->s_dev);
++		__entry->dev_minor = MINOR(sb->s_dev);
+ 		__entry->needed	= needed;
+ 	),
+ 
+-	TP_printk("dev %s needed %d",
+-		  jbd2_dev_to_name(__entry->dev), __entry->needed)
++	TP_printk("dev %d,%d needed %d",
++		  __entry->dev_major, __entry->dev_minor, __entry->needed)
+ );
+ 
+ TRACE_EVENT(ext4_request_blocks,
+@@ -491,7 +530,8 @@ TRACE_EVENT(ext4_request_blocks,
+ 	TP_ARGS(ar),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	ino_t,	ino			)
+ 		__field(	unsigned int, flags		)
+ 		__field(	unsigned int, len		)
+@@ -504,7 +544,8 @@ TRACE_EVENT(ext4_request_blocks,
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev	= ar->inode->i_sb->s_dev;
++		__entry->dev_major = MAJOR(ar->inode->i_sb->s_dev);
++		__entry->dev_minor = MINOR(ar->inode->i_sb->s_dev);
+ 		__entry->ino	= ar->inode->i_ino;
+ 		__entry->flags	= ar->flags;
+ 		__entry->len	= ar->len;
+@@ -516,8 +557,9 @@ TRACE_EVENT(ext4_request_blocks,
+ 		__entry->pright	= ar->pright;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu flags %u len %u lblk %llu goal %llu lleft %llu lright %llu pleft %llu pright %llu ",
+-		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++	TP_printk("dev %d,%d ino %lu flags %u len %u lblk %llu goal %llu lleft %llu lright %llu pleft %llu pright %llu ",
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->ino,
+ 		  __entry->flags, __entry->len,
+ 		  (unsigned long long) __entry->logical,
+ 		  (unsigned long long) __entry->goal,
+@@ -533,7 +575,8 @@ TRACE_EVENT(ext4_allocate_blocks,
+ 	TP_ARGS(ar, block),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	ino_t,	ino			)
+ 		__field(	__u64,	block			)
+ 		__field(	unsigned int, flags		)
+@@ -547,7 +590,8 @@ TRACE_EVENT(ext4_allocate_blocks,
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev	= ar->inode->i_sb->s_dev;
++		__entry->dev_major = MAJOR(ar->inode->i_sb->s_dev);
++		__entry->dev_minor = MINOR(ar->inode->i_sb->s_dev);
+ 		__entry->ino	= ar->inode->i_ino;
+ 		__entry->block	= block;
+ 		__entry->flags	= ar->flags;
+@@ -560,9 +604,10 @@ TRACE_EVENT(ext4_allocate_blocks,
+ 		__entry->pright	= ar->pright;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu flags %u len %u block %llu lblk %llu goal %llu lleft %llu lright %llu pleft %llu pright %llu ",
+-		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
+-		  __entry->flags, __entry->len, __entry->block,
++	TP_printk("dev %d,%d ino %lu flags %u len %u block %llu lblk %llu goal %llu lleft %llu lright %llu pleft %llu pright %llu ",
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->ino, __entry->flags,
++		  __entry->len, __entry->block,
+ 		  (unsigned long long) __entry->logical,
+ 		  (unsigned long long) __entry->goal,
+ 		  (unsigned long long) __entry->lleft,
+@@ -578,7 +623,8 @@ TRACE_EVENT(ext4_free_blocks,
+ 	TP_ARGS(inode, block, count, flags),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	ino_t,	ino			)
+ 		__field(      umode_t, mode			)
+ 		__field(	__u64,	block			)
+@@ -587,7 +633,8 @@ TRACE_EVENT(ext4_free_blocks,
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev		= inode->i_sb->s_dev;
++		__entry->dev_major	= MAJOR(inode->i_sb->s_dev);
++		__entry->dev_minor	= MINOR(inode->i_sb->s_dev);
+ 		__entry->ino		= inode->i_ino;
+ 		__entry->mode		= inode->i_mode;
+ 		__entry->block		= block;
+@@ -595,8 +642,9 @@ TRACE_EVENT(ext4_free_blocks,
+ 		__entry->flags		= flags;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu mode 0%o block %llu count %lu flags %d",
+-		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++	TP_printk("dev %d,%d ino %lu mode 0%o block %llu count %lu flags %d",
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->ino,
+ 		  __entry->mode, __entry->block, __entry->count,
+ 		  __entry->flags)
+ );
+@@ -607,7 +655,8 @@ TRACE_EVENT(ext4_sync_file,
+ 	TP_ARGS(file, datasync),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	ino_t,	ino			)
+ 		__field(	ino_t,	parent			)
+ 		__field(	int,	datasync		)
+@@ -616,14 +665,16 @@ TRACE_EVENT(ext4_sync_file,
+ 	TP_fast_assign(
+ 		struct dentry *dentry = file->f_path.dentry;
+ 
+-		__entry->dev		= dentry->d_inode->i_sb->s_dev;
++		__entry->dev_major	= MAJOR(dentry->d_inode->i_sb->s_dev);
++		__entry->dev_minor	= MINOR(dentry->d_inode->i_sb->s_dev);
+ 		__entry->ino		= dentry->d_inode->i_ino;
+ 		__entry->datasync	= datasync;
+ 		__entry->parent		= dentry->d_parent->d_inode->i_ino;
+ 	),
+ 
+-	TP_printk("dev %s ino %ld parent %ld datasync %d ",
+-		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++	TP_printk("dev %d,%d ino %ld parent %ld datasync %d ",
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->ino,
+ 		  (unsigned long) __entry->parent, __entry->datasync)
+ );
+ 
+@@ -633,18 +684,20 @@ TRACE_EVENT(ext4_sync_fs,
+ 	TP_ARGS(sb, wait),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	int,	wait			)
+ 
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev	= sb->s_dev;
++		__entry->dev_major = MAJOR(sb->s_dev);
++		__entry->dev_minor = MINOR(sb->s_dev);
+ 		__entry->wait	= wait;
+ 	),
+ 
+-	TP_printk("dev %s wait %d", jbd2_dev_to_name(__entry->dev),
+-		  __entry->wait)
++	TP_printk("dev %d,%d wait %d", __entry->dev_major,
++		  __entry->dev_minor, __entry->wait)
+ );
+ 
+ TRACE_EVENT(ext4_alloc_da_blocks,
+@@ -653,21 +706,24 @@ TRACE_EVENT(ext4_alloc_da_blocks,
+ 	TP_ARGS(inode),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	ino_t,	ino			)
+ 		__field( unsigned int,	data_blocks	)
+ 		__field( unsigned int,	meta_blocks	)
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev	= inode->i_sb->s_dev;
++		__entry->dev_major = MAJOR(inode->i_sb->s_dev);
++		__entry->dev_minor = MINOR(inode->i_sb->s_dev);
+ 		__entry->ino	= inode->i_ino;
+ 		__entry->data_blocks = EXT4_I(inode)->i_reserved_data_blocks;
+ 		__entry->meta_blocks = EXT4_I(inode)->i_reserved_meta_blocks;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu data_blocks %u meta_blocks %u",
+-		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++	TP_printk("dev %d,%d ino %lu data_blocks %u meta_blocks %u",
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->ino,
+ 		  __entry->data_blocks, __entry->meta_blocks)
+ );
+ 
+@@ -677,7 +733,8 @@ TRACE_EVENT(ext4_mballoc_alloc,
+ 	TP_ARGS(ac),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	ino_t,	ino			)
+ 		__field(	__u16,	found			)
+ 		__field(	__u16,	groups			)
+@@ -700,7 +757,8 @@ TRACE_EVENT(ext4_mballoc_alloc,
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev		= ac->ac_inode->i_sb->s_dev;
++		__entry->dev_major	= MAJOR(ac->ac_inode->i_sb->s_dev);
++		__entry->dev_minor	= MINOR(ac->ac_inode->i_sb->s_dev);
+ 		__entry->ino		= ac->ac_inode->i_ino;
+ 		__entry->found		= ac->ac_found;
+ 		__entry->flags		= ac->ac_flags;
+@@ -722,10 +780,11 @@ TRACE_EVENT(ext4_mballoc_alloc,
+ 		__entry->result_len	= ac->ac_f_ex.fe_len;
+ 	),
+ 
+-	TP_printk("dev %s inode %lu orig %u/%d/%u@%u goal %u/%d/%u@%u "
++	TP_printk("dev %d,%d inode %lu orig %u/%d/%u@%u goal %u/%d/%u@%u "
+ 		  "result %u/%d/%u@%u blks %u grps %u cr %u flags 0x%04x "
+ 		  "tail %u broken %u",
+-		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->ino,
+ 		  __entry->orig_group, __entry->orig_start,
+ 		  __entry->orig_len, __entry->orig_logical,
+ 		  __entry->goal_group, __entry->goal_start,
+@@ -743,7 +802,8 @@ TRACE_EVENT(ext4_mballoc_prealloc,
+ 	TP_ARGS(ac),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	ino_t,	ino			)
+ 		__field(	__u32, 	orig_logical		)
+ 		__field(	  int,	orig_start		)
+@@ -756,7 +816,8 @@ TRACE_EVENT(ext4_mballoc_prealloc,
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev		= ac->ac_inode->i_sb->s_dev;
++		__entry->dev_major	= MAJOR(ac->ac_inode->i_sb->s_dev);
++		__entry->dev_minor	= MINOR(ac->ac_inode->i_sb->s_dev);
+ 		__entry->ino		= ac->ac_inode->i_ino;
+ 		__entry->orig_logical	= ac->ac_o_ex.fe_logical;
+ 		__entry->orig_start	= ac->ac_o_ex.fe_start;
+@@ -768,8 +829,9 @@ TRACE_EVENT(ext4_mballoc_prealloc,
+ 		__entry->result_len	= ac->ac_b_ex.fe_len;
+ 	),
+ 
+-	TP_printk("dev %s inode %lu orig %u/%d/%u@%u result %u/%d/%u@%u",
+-		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++	TP_printk("dev %d,%d inode %lu orig %u/%d/%u@%u result %u/%d/%u@%u",
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->ino,
+ 		  __entry->orig_group, __entry->orig_start,
+ 		  __entry->orig_len, __entry->orig_logical,
+ 		  __entry->result_group, __entry->result_start,
+@@ -786,7 +848,8 @@ DECLARE_EVENT_CLASS(ext4__mballoc,
+ 	TP_ARGS(sb, inode, group, start, len),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	ino_t,	ino			)
+ 		__field(	  int,	result_start		)
+ 		__field(	__u32, 	result_group		)
+@@ -794,15 +857,17 @@ DECLARE_EVENT_CLASS(ext4__mballoc,
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev		= sb->s_dev;
++		__entry->dev_major	= MAJOR(sb->s_dev);
++		__entry->dev_minor	= MINOR(sb->s_dev);
+ 		__entry->ino		= inode ? inode->i_ino : 0;
+ 		__entry->result_start	= start;
+ 		__entry->result_group	= group;
+ 		__entry->result_len	= len;
+ 	),
+ 
+-	TP_printk("dev %s inode %lu extent %u/%d/%u ",
+-		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++	TP_printk("dev %d,%d inode %lu extent %u/%d/%u ",
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->ino,
+ 		  __entry->result_group, __entry->result_start,
+ 		  __entry->result_len)
+ );
+@@ -835,7 +900,8 @@ TRACE_EVENT(ext4_forget,
+ 	TP_ARGS(inode, is_metadata, block),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	ino_t,	ino			)
+ 		__field(	umode_t, mode			)
+ 		__field(	int,	is_metadata		)
+@@ -843,16 +909,18 @@ TRACE_EVENT(ext4_forget,
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev	= inode->i_sb->s_dev;
++		__entry->dev_major = MAJOR(inode->i_sb->s_dev);
++		__entry->dev_minor = MINOR(inode->i_sb->s_dev);
+ 		__entry->ino	= inode->i_ino;
+ 		__entry->mode	= inode->i_mode;
+ 		__entry->is_metadata = is_metadata;
+ 		__entry->block	= block;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu mode 0%o is_metadata %d block %llu",
+-		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
+-		  __entry->mode, __entry->is_metadata, __entry->block)
++	TP_printk("dev %d,%d ino %lu mode 0%o is_metadata %d block %llu",
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->ino, __entry->mode,
++		  __entry->is_metadata, __entry->block)
+ );
+ 
+ TRACE_EVENT(ext4_da_update_reserve_space,
+@@ -861,7 +929,8 @@ TRACE_EVENT(ext4_da_update_reserve_space,
+ 	TP_ARGS(inode, used_blocks),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	ino_t,	ino			)
+ 		__field(	umode_t, mode			)
+ 		__field(	__u64,	i_blocks		)
+@@ -872,7 +941,8 @@ TRACE_EVENT(ext4_da_update_reserve_space,
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev	= inode->i_sb->s_dev;
++		__entry->dev_major = MAJOR(inode->i_sb->s_dev);
++		__entry->dev_minor = MINOR(inode->i_sb->s_dev);
+ 		__entry->ino	= inode->i_ino;
+ 		__entry->mode	= inode->i_mode;
+ 		__entry->i_blocks = inode->i_blocks;
+@@ -882,9 +952,10 @@ TRACE_EVENT(ext4_da_update_reserve_space,
+ 		__entry->allocated_meta_blocks = EXT4_I(inode)->i_allocated_meta_blocks;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu mode 0%o i_blocks %llu used_blocks %d reserved_data_blocks %d reserved_meta_blocks %d allocated_meta_blocks %d",
+-		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
+-		  __entry->mode,  (unsigned long long) __entry->i_blocks,
++	TP_printk("dev %d,%d ino %lu mode 0%o i_blocks %llu used_blocks %d reserved_data_blocks %d reserved_meta_blocks %d allocated_meta_blocks %d",
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->ino, __entry->mode,
++		  (unsigned long long) __entry->i_blocks,
+ 		  __entry->used_blocks, __entry->reserved_data_blocks,
+ 		  __entry->reserved_meta_blocks, __entry->allocated_meta_blocks)
+ );
+@@ -895,7 +966,8 @@ TRACE_EVENT(ext4_da_reserve_space,
+ 	TP_ARGS(inode, md_needed),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	ino_t,	ino			)
+ 		__field(	umode_t, mode			)
+ 		__field(	__u64,	i_blocks		)
+@@ -905,7 +977,8 @@ TRACE_EVENT(ext4_da_reserve_space,
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev	= inode->i_sb->s_dev;
++		__entry->dev_major = MAJOR(inode->i_sb->s_dev);
++		__entry->dev_minor = MINOR(inode->i_sb->s_dev);
+ 		__entry->ino	= inode->i_ino;
+ 		__entry->mode	= inode->i_mode;
+ 		__entry->i_blocks = inode->i_blocks;
+@@ -914,8 +987,9 @@ TRACE_EVENT(ext4_da_reserve_space,
+ 		__entry->reserved_meta_blocks = EXT4_I(inode)->i_reserved_meta_blocks;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu mode 0%o i_blocks %llu md_needed %d reserved_data_blocks %d reserved_meta_blocks %d",
+-		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++	TP_printk("dev %d,%d ino %lu mode 0%o i_blocks %llu md_needed %d reserved_data_blocks %d reserved_meta_blocks %d",
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->ino,
+ 		  __entry->mode, (unsigned long long) __entry->i_blocks,
+ 		  __entry->md_needed, __entry->reserved_data_blocks,
+ 		  __entry->reserved_meta_blocks)
+@@ -927,7 +1001,8 @@ TRACE_EVENT(ext4_da_release_space,
+ 	TP_ARGS(inode, freed_blocks),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	ino_t,	ino			)
+ 		__field(	umode_t, mode			)
+ 		__field(	__u64,	i_blocks		)
+@@ -938,7 +1013,8 @@ TRACE_EVENT(ext4_da_release_space,
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev	= inode->i_sb->s_dev;
++		__entry->dev_major = MAJOR(inode->i_sb->s_dev);
++		__entry->dev_minor = MINOR(inode->i_sb->s_dev);
+ 		__entry->ino	= inode->i_ino;
+ 		__entry->mode	= inode->i_mode;
+ 		__entry->i_blocks = inode->i_blocks;
+@@ -948,8 +1024,9 @@ TRACE_EVENT(ext4_da_release_space,
+ 		__entry->allocated_meta_blocks = EXT4_I(inode)->i_allocated_meta_blocks;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu mode 0%o i_blocks %llu freed_blocks %d reserved_data_blocks %d reserved_meta_blocks %d allocated_meta_blocks %d",
+-		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++	TP_printk("dev %d,%d ino %lu mode 0%o i_blocks %llu freed_blocks %d reserved_data_blocks %d reserved_meta_blocks %d allocated_meta_blocks %d",
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->ino,
+ 		  __entry->mode, (unsigned long long) __entry->i_blocks,
+ 		  __entry->freed_blocks, __entry->reserved_data_blocks,
+ 		  __entry->reserved_meta_blocks, __entry->allocated_meta_blocks)
+@@ -961,18 +1038,20 @@ DECLARE_EVENT_CLASS(ext4__bitmap_load,
+ 	TP_ARGS(sb, group),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	__u32,	group			)
+ 
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev	= sb->s_dev;
++		__entry->dev_major = MAJOR(sb->s_dev);
++		__entry->dev_minor = MINOR(sb->s_dev);
+ 		__entry->group	= group;
+ 	),
+ 
+-	TP_printk("dev %s group %u",
+-		  jbd2_dev_to_name(__entry->dev), __entry->group)
++	TP_printk("dev %d,%d group %u",
++		  __entry->dev_major, __entry->dev_minor, __entry->group)
+ );
+ 
+ DEFINE_EVENT(ext4__bitmap_load, ext4_mb_bitmap_load,
+diff --git a/include/trace/events/jbd2.h b/include/trace/events/jbd2.h
+index bf16545cc977..7447ea9305b5 100644
+--- a/include/trace/events/jbd2.h
++++ b/include/trace/events/jbd2.h
+@@ -17,17 +17,19 @@ TRACE_EVENT(jbd2_checkpoint,
+ 	TP_ARGS(journal, result),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,	dev_major		)
++		__field(	int,	dev_minor		)
+ 		__field(	int,	result			)
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev		= journal->j_fs_dev->bd_dev;
++		__entry->dev_major	= MAJOR(journal->j_fs_dev->bd_dev);
++		__entry->dev_minor	= MINOR(journal->j_fs_dev->bd_dev);
+ 		__entry->result		= result;
+ 	),
+ 
+-	TP_printk("dev %s result %d",
+-		  jbd2_dev_to_name(__entry->dev), __entry->result)
++	TP_printk("dev %d,%d result %d",
++		  __entry->dev_major, __entry->dev_minor, __entry->result)
+ );
+ 
+ DECLARE_EVENT_CLASS(jbd2_commit,
+@@ -37,20 +39,22 @@ DECLARE_EVENT_CLASS(jbd2_commit,
+ 	TP_ARGS(journal, commit_transaction),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	char,	sync_commit		  )
+ 		__field(	int,	transaction		  )
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev		= journal->j_fs_dev->bd_dev;
++		__entry->dev_major	= MAJOR(journal->j_fs_dev->bd_dev);
++		__entry->dev_minor	= MINOR(journal->j_fs_dev->bd_dev);
+ 		__entry->sync_commit = commit_transaction->t_synchronous_commit;
+ 		__entry->transaction	= commit_transaction->t_tid;
+ 	),
+ 
+-	TP_printk("dev %s transaction %d sync %d",
+-		  jbd2_dev_to_name(__entry->dev), __entry->transaction,
+-		  __entry->sync_commit)
++	TP_printk("dev %d,%d transaction %d sync %d",
++		  __entry->dev_major, __entry->dev_minor,
++		  __entry->transaction, __entry->sync_commit)
+ );
+ 
+ DEFINE_EVENT(jbd2_commit, jbd2_start_commit,
+@@ -87,22 +91,24 @@ TRACE_EVENT(jbd2_end_commit,
+ 	TP_ARGS(journal, commit_transaction),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	char,	sync_commit		  )
+ 		__field(	int,	transaction		  )
+ 		__field(	int,	head		  	  )
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev		= journal->j_fs_dev->bd_dev;
++		__entry->dev_major	= MAJOR(journal->j_fs_dev->bd_dev);
++		__entry->dev_minor	= MINOR(journal->j_fs_dev->bd_dev);
+ 		__entry->sync_commit = commit_transaction->t_synchronous_commit;
+ 		__entry->transaction	= commit_transaction->t_tid;
+ 		__entry->head		= journal->j_tail_sequence;
+ 	),
+ 
+-	TP_printk("dev %s transaction %d sync %d head %d",
+-		  jbd2_dev_to_name(__entry->dev), __entry->transaction,
+-		  __entry->sync_commit, __entry->head)
++	TP_printk("dev %d,%d transaction %d sync %d head %d",
++		  __entry->dev_major, __entry->dev_minor,
++		  __entry->transaction, __entry->sync_commit, __entry->head)
+ );
+ 
+ TRACE_EVENT(jbd2_submit_inode_data,
+@@ -111,17 +117,20 @@ TRACE_EVENT(jbd2_submit_inode_data,
+ 	TP_ARGS(inode),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	ino_t,	ino			)
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev	= inode->i_sb->s_dev;
++		__entry->dev_major = MAJOR(inode->i_sb->s_dev);
++		__entry->dev_minor = MINOR(inode->i_sb->s_dev);
+ 		__entry->ino	= inode->i_ino;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu",
+-		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino)
++	TP_printk("dev %d,%d ino %lu",
++		  __entry->dev_major, __entry->dev_minor,
++		  (unsigned long) __entry->ino)
+ );
+ 
+ TRACE_EVENT(jbd2_run_stats,
+@@ -131,7 +140,8 @@ TRACE_EVENT(jbd2_run_stats,
+ 	TP_ARGS(dev, tid, stats),
+ 
+ 	TP_STRUCT__entry(
+-		__field(		dev_t,	dev		)
++		__field(		  int,	dev_major	)
++		__field(		  int,	dev_minor	)
+ 		__field(	unsigned long,	tid		)
+ 		__field(	unsigned long,	wait		)
+ 		__field(	unsigned long,	running		)
+@@ -144,7 +154,8 @@ TRACE_EVENT(jbd2_run_stats,
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev		= dev;
++		__entry->dev_major	= MAJOR(dev);
++		__entry->dev_minor	= MINOR(dev);
+ 		__entry->tid		= tid;
+ 		__entry->wait		= stats->rs_wait;
+ 		__entry->running	= stats->rs_running;
+@@ -156,9 +167,9 @@ TRACE_EVENT(jbd2_run_stats,
+ 		__entry->blocks_logged	= stats->rs_blocks_logged;
+ 	),
+ 
+-	TP_printk("dev %s tid %lu wait %u running %u locked %u flushing %u "
++	TP_printk("dev %d,%d tid %lu wait %u running %u locked %u flushing %u "
+ 		  "logging %u handle_count %u blocks %u blocks_logged %u",
+-		  jbd2_dev_to_name(__entry->dev), __entry->tid,
++		  __entry->dev_major, __entry->dev_minor, __entry->tid,
+ 		  jiffies_to_msecs(__entry->wait),
+ 		  jiffies_to_msecs(__entry->running),
+ 		  jiffies_to_msecs(__entry->locked),
+@@ -175,7 +186,8 @@ TRACE_EVENT(jbd2_checkpoint_stats,
+ 	TP_ARGS(dev, tid, stats),
+ 
+ 	TP_STRUCT__entry(
+-		__field(		dev_t,	dev		)
++		__field(		  int,	dev_major	)
++		__field(		  int,	dev_minor	)
+ 		__field(	unsigned long,	tid		)
+ 		__field(	unsigned long,	chp_time	)
+ 		__field(		__u32,	forced_to_close	)
+@@ -184,7 +196,8 @@ TRACE_EVENT(jbd2_checkpoint_stats,
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev		= dev;
++		__entry->dev_major	= MAJOR(dev);
++		__entry->dev_minor	= MINOR(dev);
+ 		__entry->tid		= tid;
+ 		__entry->chp_time	= stats->cs_chp_time;
+ 		__entry->forced_to_close= stats->cs_forced_to_close;
+@@ -192,9 +205,9 @@ TRACE_EVENT(jbd2_checkpoint_stats,
+ 		__entry->dropped	= stats->cs_dropped;
+ 	),
+ 
+-	TP_printk("dev %s tid %lu chp_time %u forced_to_close %u "
++	TP_printk("dev %d,%d tid %lu chp_time %u forced_to_close %u "
+ 		  "written %u dropped %u",
+-		  jbd2_dev_to_name(__entry->dev), __entry->tid,
++		  __entry->dev_major, __entry->dev_minor, __entry->tid,
+ 		  jiffies_to_msecs(__entry->chp_time),
+ 		  __entry->forced_to_close, __entry->written, __entry->dropped)
+ );
+@@ -207,7 +220,8 @@ TRACE_EVENT(jbd2_cleanup_journal_tail,
+ 	TP_ARGS(journal, first_tid, block_nr, freed),
+ 
+ 	TP_STRUCT__entry(
+-		__field(	dev_t,	dev			)
++		__field(	int,   dev_major                )
++		__field(	int,   dev_minor                )
+ 		__field(	tid_t,	tail_sequence		)
+ 		__field(	tid_t,	first_tid		)
+ 		__field(unsigned long,	block_nr		)
+@@ -215,16 +229,18 @@ TRACE_EVENT(jbd2_cleanup_journal_tail,
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev		= journal->j_fs_dev->bd_dev;
++		__entry->dev_major	= MAJOR(journal->j_fs_dev->bd_dev);
++		__entry->dev_minor	= MINOR(journal->j_fs_dev->bd_dev);
+ 		__entry->tail_sequence	= journal->j_tail_sequence;
+ 		__entry->first_tid	= first_tid;
+ 		__entry->block_nr	= block_nr;
+ 		__entry->freed		= freed;
+ 	),
+ 
+-	TP_printk("dev %s from %u to %u offset %lu freed %lu",
+-		  jbd2_dev_to_name(__entry->dev), __entry->tail_sequence,
+-		  __entry->first_tid, __entry->block_nr, __entry->freed)
++	TP_printk("dev %d,%d from %u to %u offset %lu freed %lu",
++		  __entry->dev_major, __entry->dev_minor,
++		  __entry->tail_sequence, __entry->first_tid,
++		  __entry->block_nr, __entry->freed)
+ );
+ 
+ #endif /* _TRACE_JBD2_H */

commit 61d08673de1fe68bfba86203258377bf39f234b6
+Author: Theodore Ts'o 
+Date:   Wed Oct 27 21:30:15 2010 -0400
+
+    ext4: rename mark_bitmap_end() to ext4_mark_bitmap_end()
+    
+    Fix a namespace leak from fs/ext4
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index a12cefc20c76..14c3af26c671 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -171,7 +171,8 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
+ 		 * less than the blocksize * 8 ( which is the size
+ 		 * of bitmap ), set rest of the block bitmap to 1
+ 		 */
+-		mark_bitmap_end(group_blocks, sb->s_blocksize * 8, bh->b_data);
++		ext4_mark_bitmap_end(group_blocks, sb->s_blocksize * 8,
++				     bh->b_data);
+ 	}
+ 	return free_blocks - ext4_group_used_meta_blocks(sb, block_group, gdp);
+ }
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index c0570a68a2bc..202668c5607d 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1664,7 +1664,7 @@ extern struct inode * ext4_orphan_get(struct super_block *, unsigned long);
+ extern unsigned long ext4_count_free_inodes(struct super_block *);
+ extern unsigned long ext4_count_dirs(struct super_block *);
+ extern void ext4_check_inodes_bitmap(struct super_block *);
+-extern void mark_bitmap_end(int start_bit, int end_bit, char *bitmap);
++extern void ext4_mark_bitmap_end(int start_bit, int end_bit, char *bitmap);
+ extern int ext4_init_inode_table(struct super_block *sb,
+ 				 ext4_group_t group, int barrier);
+ 
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 9666e4c6efb4..509f429f71e8 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -50,7 +50,7 @@
+  * need to use it within a single byte (to ensure we get endianness right).
+  * We can use memset for the rest of the bitmap as there are no other users.
+  */
+-void mark_bitmap_end(int start_bit, int end_bit, char *bitmap)
++void ext4_mark_bitmap_end(int start_bit, int end_bit, char *bitmap)
+ {
+ 	int i;
+ 
+@@ -86,7 +86,7 @@ static unsigned ext4_init_inode_bitmap(struct super_block *sb,
+ 	}
+ 
+ 	memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8);
+-	mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), sb->s_blocksize * 8,
++	ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), sb->s_blocksize * 8,
+ 			bh->b_data);
+ 
+ 	return EXT4_INODES_PER_GROUP(sb);
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 2f5e347de48b..f398474e2784 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -252,7 +252,8 @@ static int setup_new_group_blocks(struct super_block *sb,
+ 	if ((err = extend_or_restart_transaction(handle, 2, bh)))
+ 		goto exit_bh;
+ 
+-	mark_bitmap_end(input->blocks_count, sb->s_blocksize * 8, bh->b_data);
++	ext4_mark_bitmap_end(input->blocks_count, sb->s_blocksize * 8,
++			     bh->b_data);
+ 	ext4_handle_dirty_metadata(handle, NULL, bh);
+ 	brelse(bh);
+ 	/* Mark unused entries in inode bitmap used */
+@@ -263,8 +264,8 @@ static int setup_new_group_blocks(struct super_block *sb,
+ 		goto exit_journal;
+ 	}
+ 
+-	mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), sb->s_blocksize * 8,
+-			bh->b_data);
++	ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), sb->s_blocksize * 8,
++			     bh->b_data);
+ 	ext4_handle_dirty_metadata(handle, NULL, bh);
+ exit_bh:
+ 	brelse(bh);

commit 4a873a472b3bbcfd425d7ae210afdec28c04e2e5
+Author: Theodore Ts'o 
+Date:   Wed Oct 27 21:30:14 2010 -0400
+
+    ext4: move flush_completed_IO to fs/ext4/fsync.c and make it static
+    
+    Fix a namespace leak by moving the function to the file where it is
+    used and making it static.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index ac1afc148b36..c0570a68a2bc 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1721,7 +1721,6 @@ extern int ext4_block_truncate_page(handle_t *handle,
+ 		struct address_space *mapping, loff_t from);
+ extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf);
+ extern qsize_t *ext4_get_reserved_space(struct inode *inode);
+-extern int flush_completed_IO(struct inode *inode);
+ extern void ext4_da_update_reserve_space(struct inode *inode,
+ 					int used, int quota_claim);
+ /* ioctl.c */
+diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
+index 592adf2e546e..1c701f635961 100644
+--- a/fs/ext4/fsync.c
++++ b/fs/ext4/fsync.c
+@@ -34,6 +34,89 @@
+ 
+ #include 
+ 
++static void dump_completed_IO(struct inode * inode)
++{
++#ifdef	EXT4_DEBUG
++	struct list_head *cur, *before, *after;
++	ext4_io_end_t *io, *io0, *io1;
++	unsigned long flags;
++
++	if (list_empty(&EXT4_I(inode)->i_completed_io_list)){
++		ext4_debug("inode %lu completed_io list is empty\n", inode->i_ino);
++		return;
++	}
++
++	ext4_debug("Dump inode %lu completed_io list \n", inode->i_ino);
++	spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags);
++	list_for_each_entry(io, &EXT4_I(inode)->i_completed_io_list, list){
++		cur = &io->list;
++		before = cur->prev;
++		io0 = container_of(before, ext4_io_end_t, list);
++		after = cur->next;
++		io1 = container_of(after, ext4_io_end_t, list);
++
++		ext4_debug("io 0x%p from inode %lu,prev 0x%p,next 0x%p\n",
++			    io, inode->i_ino, io0, io1);
++	}
++	spin_unlock_irqrestore(&EXT4_I(inode)->i_completed_io_lock, flags);
++#endif
++}
++
++/*
++ * This function is called from ext4_sync_file().
++ *
++ * When IO is completed, the work to convert unwritten extents to
++ * written is queued on workqueue but may not get immediately
++ * scheduled. When fsync is called, we need to ensure the
++ * conversion is complete before fsync returns.
++ * The inode keeps track of a list of pending/completed IO that
++ * might needs to do the conversion. This function walks through
++ * the list and convert the related unwritten extents for completed IO
++ * to written.
++ * The function return the number of pending IOs on success.
++ */
++static int flush_completed_IO(struct inode *inode)
++{
++	ext4_io_end_t *io;
++	struct ext4_inode_info *ei = EXT4_I(inode);
++	unsigned long flags;
++	int ret = 0;
++	int ret2 = 0;
++
++	if (list_empty(&ei->i_completed_io_list))
++		return ret;
++
++	dump_completed_IO(inode);
++	spin_lock_irqsave(&ei->i_completed_io_lock, flags);
++	while (!list_empty(&ei->i_completed_io_list)){
++		io = list_entry(ei->i_completed_io_list.next,
++				ext4_io_end_t, list);
++		/*
++		 * Calling ext4_end_io_nolock() to convert completed
++		 * IO to written.
++		 *
++		 * When ext4_sync_file() is called, run_queue() may already
++		 * about to flush the work corresponding to this io structure.
++		 * It will be upset if it founds the io structure related
++		 * to the work-to-be schedule is freed.
++		 *
++		 * Thus we need to keep the io structure still valid here after
++		 * convertion finished. The io structure has a flag to
++		 * avoid double converting from both fsync and background work
++		 * queue work.
++		 */
++		spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
++		ret = ext4_end_io_nolock(io);
++		spin_lock_irqsave(&ei->i_completed_io_lock, flags);
++		if (ret < 0)
++			ret2 = ret;
++		else
++			list_del_init(&io->list);
++	}
++	spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
++	return (ret2 < 0) ? ret2 : 0;
++}
++
+ /*
+  * If we're not journaling and this is a just-created file, we have to
+  * sync our parent directory (if it was freshly created) since
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 7a83c2793956..9e60d0b8fa75 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -3626,89 +3626,6 @@ static int ext4_get_block_write(struct inode *inode, sector_t iblock,
+ 			       EXT4_GET_BLOCKS_IO_CREATE_EXT);
+ }
+ 
+-static void dump_completed_IO(struct inode * inode)
+-{
+-#ifdef	EXT4_DEBUG
+-	struct list_head *cur, *before, *after;
+-	ext4_io_end_t *io, *io0, *io1;
+-	unsigned long flags;
+-
+-	if (list_empty(&EXT4_I(inode)->i_completed_io_list)){
+-		ext4_debug("inode %lu completed_io list is empty\n", inode->i_ino);
+-		return;
+-	}
+-
+-	ext4_debug("Dump inode %lu completed_io list \n", inode->i_ino);
+-	spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags);
+-	list_for_each_entry(io, &EXT4_I(inode)->i_completed_io_list, list){
+-		cur = &io->list;
+-		before = cur->prev;
+-		io0 = container_of(before, ext4_io_end_t, list);
+-		after = cur->next;
+-		io1 = container_of(after, ext4_io_end_t, list);
+-
+-		ext4_debug("io 0x%p from inode %lu,prev 0x%p,next 0x%p\n",
+-			    io, inode->i_ino, io0, io1);
+-	}
+-	spin_unlock_irqrestore(&EXT4_I(inode)->i_completed_io_lock, flags);
+-#endif
+-}
+-
+-/*
+- * This function is called from ext4_sync_file().
+- *
+- * When IO is completed, the work to convert unwritten extents to
+- * written is queued on workqueue but may not get immediately
+- * scheduled. When fsync is called, we need to ensure the
+- * conversion is complete before fsync returns.
+- * The inode keeps track of a list of pending/completed IO that
+- * might needs to do the conversion. This function walks through
+- * the list and convert the related unwritten extents for completed IO
+- * to written.
+- * The function return the number of pending IOs on success.
+- */
+-int flush_completed_IO(struct inode *inode)
+-{
+-	ext4_io_end_t *io;
+-	struct ext4_inode_info *ei = EXT4_I(inode);
+-	unsigned long flags;
+-	int ret = 0;
+-	int ret2 = 0;
+-
+-	if (list_empty(&ei->i_completed_io_list))
+-		return ret;
+-
+-	dump_completed_IO(inode);
+-	spin_lock_irqsave(&ei->i_completed_io_lock, flags);
+-	while (!list_empty(&ei->i_completed_io_list)){
+-		io = list_entry(ei->i_completed_io_list.next,
+-				ext4_io_end_t, list);
+-		/*
+-		 * Calling ext4_end_io_nolock() to convert completed
+-		 * IO to written.
+-		 *
+-		 * When ext4_sync_file() is called, run_queue() may already
+-		 * about to flush the work corresponding to this io structure.
+-		 * It will be upset if it founds the io structure related
+-		 * to the work-to-be schedule is freed.
+-		 *
+-		 * Thus we need to keep the io structure still valid here after
+-		 * convertion finished. The io structure has a flag to
+-		 * avoid double converting from both fsync and background work
+-		 * queue work.
+-		 */
+-		spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
+-		ret = ext4_end_io_nolock(io);
+-		spin_lock_irqsave(&ei->i_completed_io_lock, flags);
+-		if (ret < 0)
+-			ret2 = ret;
+-		else
+-			list_del_init(&io->list);
+-	}
+-	spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
+-	return (ret2 < 0) ? ret2 : 0;
+-}
+-
+ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
+ 			    ssize_t size, void *private, int ret,
+ 			    bool is_async)

commit bf89d16f6ef5389f1b9d8046e838ec87b9b3f8b9
+Author: Theodore Ts'o 
+Date:   Wed Oct 27 21:30:14 2010 -0400
+
+    ext4: rename {ext,idx}_pblock and inline small extent functions
+    
+    Cleanup namespace leaks from fs/ext4 and the inline trivial functions
+    ext4_{ext,idx}_pblock() and ext4_{ext,idx}_store_pblock() since the
+    code size actually shrinks when we make these functions inline,
+    they're so trivial.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h
+index e427082e9ffc..28ce70fd9cd0 100644
+--- a/fs/ext4/ext4_extents.h
++++ b/fs/ext4/ext4_extents.h
+@@ -225,11 +225,60 @@ static inline void ext4_ext_mark_initialized(struct ext4_extent *ext)
+ 	ext->ee_len = cpu_to_le16(ext4_ext_get_actual_len(ext));
+ }
+ 
++/*
++ * ext4_ext_pblock:
++ * combine low and high parts of physical block number into ext4_fsblk_t
++ */
++static inline ext4_fsblk_t ext4_ext_pblock(struct ext4_extent *ex)
++{
++	ext4_fsblk_t block;
++
++	block = le32_to_cpu(ex->ee_start_lo);
++	block |= ((ext4_fsblk_t) le16_to_cpu(ex->ee_start_hi) << 31) << 1;
++	return block;
++}
++
++/*
++ * ext4_idx_pblock:
++ * combine low and high parts of a leaf physical block number into ext4_fsblk_t
++ */
++static inline ext4_fsblk_t ext4_idx_pblock(struct ext4_extent_idx *ix)
++{
++	ext4_fsblk_t block;
++
++	block = le32_to_cpu(ix->ei_leaf_lo);
++	block |= ((ext4_fsblk_t) le16_to_cpu(ix->ei_leaf_hi) << 31) << 1;
++	return block;
++}
++
++/*
++ * ext4_ext_store_pblock:
++ * stores a large physical block number into an extent struct,
++ * breaking it into parts
++ */
++static inline void ext4_ext_store_pblock(struct ext4_extent *ex,
++					 ext4_fsblk_t pb)
++{
++	ex->ee_start_lo = cpu_to_le32((unsigned long) (pb & 0xffffffff));
++	ex->ee_start_hi = cpu_to_le16((unsigned long) ((pb >> 31) >> 1) &
++				      0xffff);
++}
++
++/*
++ * ext4_idx_store_pblock:
++ * stores a large physical block number into an index struct,
++ * breaking it into parts
++ */
++static inline void ext4_idx_store_pblock(struct ext4_extent_idx *ix,
++					 ext4_fsblk_t pb)
++{
++	ix->ei_leaf_lo = cpu_to_le32((unsigned long) (pb & 0xffffffff));
++	ix->ei_leaf_hi = cpu_to_le16((unsigned long) ((pb >> 31) >> 1) &
++				     0xffff);
++}
++
+ extern int ext4_ext_calc_metadata_amount(struct inode *inode,
+ 					 sector_t lblocks);
+-extern ext4_fsblk_t ext_pblock(struct ext4_extent *ex);
+-extern ext4_fsblk_t idx_pblock(struct ext4_extent_idx *);
+-extern void ext4_ext_store_pblock(struct ext4_extent *, ext4_fsblk_t);
+ extern int ext4_extent_tree_init(handle_t *, struct inode *);
+ extern int ext4_ext_calc_credits_for_single_extent(struct inode *inode,
+ 						   int num,
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index bd95375314ab..20e6c3c65fa1 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -44,55 +44,6 @@
+ #include "ext4_jbd2.h"
+ #include "ext4_extents.h"
+ 
+-
+-/*
+- * ext_pblock:
+- * combine low and high parts of physical block number into ext4_fsblk_t
+- */
+-ext4_fsblk_t ext_pblock(struct ext4_extent *ex)
+-{
+-	ext4_fsblk_t block;
+-
+-	block = le32_to_cpu(ex->ee_start_lo);
+-	block |= ((ext4_fsblk_t) le16_to_cpu(ex->ee_start_hi) << 31) << 1;
+-	return block;
+-}
+-
+-/*
+- * idx_pblock:
+- * combine low and high parts of a leaf physical block number into ext4_fsblk_t
+- */
+-ext4_fsblk_t idx_pblock(struct ext4_extent_idx *ix)
+-{
+-	ext4_fsblk_t block;
+-
+-	block = le32_to_cpu(ix->ei_leaf_lo);
+-	block |= ((ext4_fsblk_t) le16_to_cpu(ix->ei_leaf_hi) << 31) << 1;
+-	return block;
+-}
+-
+-/*
+- * ext4_ext_store_pblock:
+- * stores a large physical block number into an extent struct,
+- * breaking it into parts
+- */
+-void ext4_ext_store_pblock(struct ext4_extent *ex, ext4_fsblk_t pb)
+-{
+-	ex->ee_start_lo = cpu_to_le32((unsigned long) (pb & 0xffffffff));
+-	ex->ee_start_hi = cpu_to_le16((unsigned long) ((pb >> 31) >> 1) & 0xffff);
+-}
+-
+-/*
+- * ext4_idx_store_pblock:
+- * stores a large physical block number into an index struct,
+- * breaking it into parts
+- */
+-static void ext4_idx_store_pblock(struct ext4_extent_idx *ix, ext4_fsblk_t pb)
+-{
+-	ix->ei_leaf_lo = cpu_to_le32((unsigned long) (pb & 0xffffffff));
+-	ix->ei_leaf_hi = cpu_to_le16((unsigned long) ((pb >> 31) >> 1) & 0xffff);
+-}
+-
+ static int ext4_ext_truncate_extend_restart(handle_t *handle,
+ 					    struct inode *inode,
+ 					    int needed)
+@@ -169,7 +120,8 @@ static ext4_fsblk_t ext4_ext_find_goal(struct inode *inode,
+ 		/* try to predict block placement */
+ 		ex = path[depth].p_ext;
+ 		if (ex)
+-			return ext_pblock(ex)+(block-le32_to_cpu(ex->ee_block));
++			return (ext4_ext_pblock(ex) +
++				(block - le32_to_cpu(ex->ee_block)));
+ 
+ 		/* it looks like index is empty;
+ 		 * try to find starting block from index itself */
+@@ -354,7 +306,7 @@ ext4_ext_max_entries(struct inode *inode, int depth)
+ 
+ static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext)
+ {
+-	ext4_fsblk_t block = ext_pblock(ext);
++	ext4_fsblk_t block = ext4_ext_pblock(ext);
+ 	int len = ext4_ext_get_actual_len(ext);
+ 
+ 	return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, len);
+@@ -363,7 +315,7 @@ static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext)
+ static int ext4_valid_extent_idx(struct inode *inode,
+ 				struct ext4_extent_idx *ext_idx)
+ {
+-	ext4_fsblk_t block = idx_pblock(ext_idx);
++	ext4_fsblk_t block = ext4_idx_pblock(ext_idx);
+ 
+ 	return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, 1);
+ }
+@@ -463,13 +415,13 @@ static void ext4_ext_show_path(struct inode *inode, struct ext4_ext_path *path)
+ 	for (k = 0; k <= l; k++, path++) {
+ 		if (path->p_idx) {
+ 		  ext_debug("  %d->%llu", le32_to_cpu(path->p_idx->ei_block),
+-			    idx_pblock(path->p_idx));
++			    ext4_idx_pblock(path->p_idx));
+ 		} else if (path->p_ext) {
+ 			ext_debug("  %d:[%d]%d:%llu ",
+ 				  le32_to_cpu(path->p_ext->ee_block),
+ 				  ext4_ext_is_uninitialized(path->p_ext),
+ 				  ext4_ext_get_actual_len(path->p_ext),
+-				  ext_pblock(path->p_ext));
++				  ext4_ext_pblock(path->p_ext));
+ 		} else
+ 			ext_debug("  []");
+ 	}
+@@ -494,7 +446,7 @@ static void ext4_ext_show_leaf(struct inode *inode, struct ext4_ext_path *path)
+ 	for (i = 0; i < le16_to_cpu(eh->eh_entries); i++, ex++) {
+ 		ext_debug("%d:[%d]%d:%llu ", le32_to_cpu(ex->ee_block),
+ 			  ext4_ext_is_uninitialized(ex),
+-			  ext4_ext_get_actual_len(ex), ext_pblock(ex));
++			  ext4_ext_get_actual_len(ex), ext4_ext_pblock(ex));
+ 	}
+ 	ext_debug("\n");
+ }
+@@ -545,7 +497,7 @@ ext4_ext_binsearch_idx(struct inode *inode,
+ 
+ 	path->p_idx = l - 1;
+ 	ext_debug("  -> %d->%lld ", le32_to_cpu(path->p_idx->ei_block),
+-		  idx_pblock(path->p_idx));
++		  ext4_idx_pblock(path->p_idx));
+ 
+ #ifdef CHECK_BINSEARCH
+ 	{
+@@ -614,7 +566,7 @@ ext4_ext_binsearch(struct inode *inode,
+ 	path->p_ext = l - 1;
+ 	ext_debug("  -> %d:%llu:[%d]%d ",
+ 			le32_to_cpu(path->p_ext->ee_block),
+-			ext_pblock(path->p_ext),
++			ext4_ext_pblock(path->p_ext),
+ 			ext4_ext_is_uninitialized(path->p_ext),
+ 			ext4_ext_get_actual_len(path->p_ext));
+ 
+@@ -682,7 +634,7 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
+ 			  ppos, le16_to_cpu(eh->eh_entries), le16_to_cpu(eh->eh_max));
+ 
+ 		ext4_ext_binsearch_idx(inode, path + ppos, block);
+-		path[ppos].p_block = idx_pblock(path[ppos].p_idx);
++		path[ppos].p_block = ext4_idx_pblock(path[ppos].p_idx);
+ 		path[ppos].p_depth = i;
+ 		path[ppos].p_ext = NULL;
+ 
+@@ -721,7 +673,7 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
+ 	ext4_ext_binsearch(inode, path + ppos, block);
+ 	/* if not an empty leaf */
+ 	if (path[ppos].p_ext)
+-		path[ppos].p_block = ext_pblock(path[ppos].p_ext);
++		path[ppos].p_block = ext4_ext_pblock(path[ppos].p_ext);
+ 
+ 	ext4_ext_show_path(inode, path);
+ 
+@@ -917,7 +869,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
+ 			EXT_MAX_EXTENT(path[depth].p_hdr)) {
+ 		ext_debug("move %d:%llu:[%d]%d in new leaf %llu\n",
+ 				le32_to_cpu(path[depth].p_ext->ee_block),
+-				ext_pblock(path[depth].p_ext),
++				ext4_ext_pblock(path[depth].p_ext),
+ 				ext4_ext_is_uninitialized(path[depth].p_ext),
+ 				ext4_ext_get_actual_len(path[depth].p_ext),
+ 				newblock);
+@@ -1007,7 +959,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
+ 		while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) {
+ 			ext_debug("%d: move %d:%llu in new index %llu\n", i,
+ 					le32_to_cpu(path[i].p_idx->ei_block),
+-					idx_pblock(path[i].p_idx),
++					ext4_idx_pblock(path[i].p_idx),
+ 					newblock);
+ 			/*memmove(++fidx, path[i].p_idx++,
+ 					sizeof(struct ext4_extent_idx));
+@@ -1146,7 +1098,7 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
+ 	ext_debug("new root: num %d(%d), lblock %d, ptr %llu\n",
+ 		  le16_to_cpu(neh->eh_entries), le16_to_cpu(neh->eh_max),
+ 		  le32_to_cpu(EXT_FIRST_INDEX(neh)->ei_block),
+-		  idx_pblock(EXT_FIRST_INDEX(neh)));
++		  ext4_idx_pblock(EXT_FIRST_INDEX(neh)));
+ 
+ 	neh->eh_depth = cpu_to_le16(path->p_depth + 1);
+ 	err = ext4_ext_dirty(handle, inode, curp);
+@@ -1286,7 +1238,7 @@ static int ext4_ext_search_left(struct inode *inode,
+ 	}
+ 
+ 	*logical = le32_to_cpu(ex->ee_block) + ee_len - 1;
+-	*phys = ext_pblock(ex) + ee_len - 1;
++	*phys = ext4_ext_pblock(ex) + ee_len - 1;
+ 	return 0;
+ }
+ 
+@@ -1342,7 +1294,7 @@ static int ext4_ext_search_right(struct inode *inode,
+ 			}
+ 		}
+ 		*logical = le32_to_cpu(ex->ee_block);
+-		*phys = ext_pblock(ex);
++		*phys = ext4_ext_pblock(ex);
+ 		return 0;
+ 	}
+ 
+@@ -1357,7 +1309,7 @@ static int ext4_ext_search_right(struct inode *inode,
+ 		/* next allocated block in this leaf */
+ 		ex++;
+ 		*logical = le32_to_cpu(ex->ee_block);
+-		*phys = ext_pblock(ex);
++		*phys = ext4_ext_pblock(ex);
+ 		return 0;
+ 	}
+ 
+@@ -1376,7 +1328,7 @@ static int ext4_ext_search_right(struct inode *inode,
+ 	 * follow it and find the closest allocated
+ 	 * block to the right */
+ 	ix++;
+-	block = idx_pblock(ix);
++	block = ext4_idx_pblock(ix);
+ 	while (++depth < path->p_depth) {
+ 		bh = sb_bread(inode->i_sb, block);
+ 		if (bh == NULL)
+@@ -1388,7 +1340,7 @@ static int ext4_ext_search_right(struct inode *inode,
+ 			return -EIO;
+ 		}
+ 		ix = EXT_FIRST_INDEX(eh);
+-		block = idx_pblock(ix);
++		block = ext4_idx_pblock(ix);
+ 		put_bh(bh);
+ 	}
+ 
+@@ -1402,7 +1354,7 @@ static int ext4_ext_search_right(struct inode *inode,
+ 	}
+ 	ex = EXT_FIRST_EXTENT(eh);
+ 	*logical = le32_to_cpu(ex->ee_block);
+-	*phys = ext_pblock(ex);
++	*phys = ext4_ext_pblock(ex);
+ 	put_bh(bh);
+ 	return 0;
+ }
+@@ -1573,7 +1525,7 @@ ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1,
+ 		return 0;
+ #endif
+ 
+-	if (ext_pblock(ex1) + ext1_ee_len == ext_pblock(ex2))
++	if (ext4_ext_pblock(ex1) + ext1_ee_len == ext4_ext_pblock(ex2))
+ 		return 1;
+ 	return 0;
+ }
+@@ -1706,11 +1658,12 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+ 	if (ex && !(flag & EXT4_GET_BLOCKS_PRE_IO)
+ 		&& ext4_can_extents_be_merged(inode, ex, newext)) {
+ 		ext_debug("append [%d]%d block to %d:[%d]%d (from %llu)\n",
+-				ext4_ext_is_uninitialized(newext),
+-				ext4_ext_get_actual_len(newext),
+-				le32_to_cpu(ex->ee_block),
+-				ext4_ext_is_uninitialized(ex),
+-				ext4_ext_get_actual_len(ex), ext_pblock(ex));
++			  ext4_ext_is_uninitialized(newext),
++			  ext4_ext_get_actual_len(newext),
++			  le32_to_cpu(ex->ee_block),
++			  ext4_ext_is_uninitialized(ex),
++			  ext4_ext_get_actual_len(ex),
++			  ext4_ext_pblock(ex));
+ 		err = ext4_ext_get_access(handle, inode, path + depth);
+ 		if (err)
+ 			return err;
+@@ -1780,7 +1733,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+ 		/* there is no extent in this leaf, create first one */
+ 		ext_debug("first extent in the leaf: %d:%llu:[%d]%d\n",
+ 				le32_to_cpu(newext->ee_block),
+-				ext_pblock(newext),
++				ext4_ext_pblock(newext),
+ 				ext4_ext_is_uninitialized(newext),
+ 				ext4_ext_get_actual_len(newext));
+ 		path[depth].p_ext = EXT_FIRST_EXTENT(eh);
+@@ -1794,7 +1747,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+ 			ext_debug("insert %d:%llu:[%d]%d after: nearest 0x%p, "
+ 					"move %d from 0x%p to 0x%p\n",
+ 					le32_to_cpu(newext->ee_block),
+-					ext_pblock(newext),
++					ext4_ext_pblock(newext),
+ 					ext4_ext_is_uninitialized(newext),
+ 					ext4_ext_get_actual_len(newext),
+ 					nearex, len, nearex + 1, nearex + 2);
+@@ -1808,7 +1761,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+ 		ext_debug("insert %d:%llu:[%d]%d before: nearest 0x%p, "
+ 				"move %d from 0x%p to 0x%p\n",
+ 				le32_to_cpu(newext->ee_block),
+-				ext_pblock(newext),
++				ext4_ext_pblock(newext),
+ 				ext4_ext_is_uninitialized(newext),
+ 				ext4_ext_get_actual_len(newext),
+ 				nearex, len, nearex + 1, nearex + 2);
+@@ -1819,7 +1772,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+ 	le16_add_cpu(&eh->eh_entries, 1);
+ 	nearex = path[depth].p_ext;
+ 	nearex->ee_block = newext->ee_block;
+-	ext4_ext_store_pblock(nearex, ext_pblock(newext));
++	ext4_ext_store_pblock(nearex, ext4_ext_pblock(newext));
+ 	nearex->ee_len = newext->ee_len;
+ 
+ merge:
+@@ -1923,7 +1876,7 @@ static int ext4_ext_walk_space(struct inode *inode, ext4_lblk_t block,
+ 		} else {
+ 			cbex.ec_block = le32_to_cpu(ex->ee_block);
+ 			cbex.ec_len = ext4_ext_get_actual_len(ex);
+-			cbex.ec_start = ext_pblock(ex);
++			cbex.ec_start = ext4_ext_pblock(ex);
+ 			cbex.ec_type = EXT4_EXT_CACHE_EXTENT;
+ 		}
+ 
+@@ -2073,7 +2026,7 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode,
+ 
+ 	/* free index block */
+ 	path--;
+-	leaf = idx_pblock(path->p_idx);
++	leaf = ext4_idx_pblock(path->p_idx);
+ 	if (unlikely(path->p_hdr->eh_entries == 0)) {
+ 		EXT4_ERROR_INODE(inode, "path->p_hdr->eh_entries == 0");
+ 		return -EIO;
+@@ -2181,7 +2134,7 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
+ 		ext4_fsblk_t start;
+ 
+ 		num = le32_to_cpu(ex->ee_block) + ee_len - from;
+-		start = ext_pblock(ex) + ee_len - num;
++		start = ext4_ext_pblock(ex) + ee_len - num;
+ 		ext_debug("free last %u blocks starting %llu\n", num, start);
+ 		ext4_free_blocks(handle, inode, 0, start, num, flags);
+ 	} else if (from == le32_to_cpu(ex->ee_block)
+@@ -2310,7 +2263,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
+ 			goto out;
+ 
+ 		ext_debug("new extent: %u:%u:%llu\n", block, num,
+-				ext_pblock(ex));
++				ext4_ext_pblock(ex));
+ 		ex--;
+ 		ex_ee_block = le32_to_cpu(ex->ee_block);
+ 		ex_ee_len = ext4_ext_get_actual_len(ex);
+@@ -2421,9 +2374,9 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start)
+ 			struct buffer_head *bh;
+ 			/* go to the next level */
+ 			ext_debug("move to level %d (block %llu)\n",
+-				  i + 1, idx_pblock(path[i].p_idx));
++				  i + 1, ext4_idx_pblock(path[i].p_idx));
+ 			memset(path + i + 1, 0, sizeof(*path));
+-			bh = sb_bread(sb, idx_pblock(path[i].p_idx));
++			bh = sb_bread(sb, ext4_idx_pblock(path[i].p_idx));
+ 			if (!bh) {
+ 				/* should we reset i_size? */
+ 				err = -EIO;
+@@ -2543,7 +2496,7 @@ static int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex)
+ 	int ret;
+ 
+ 	ee_len    = ext4_ext_get_actual_len(ex);
+-	ee_pblock = ext_pblock(ex);
++	ee_pblock = ext4_ext_pblock(ex);
+ 
+ 	ret = sb_issue_zeroout(inode->i_sb, ee_pblock, ee_len,
+ 			       GFP_NOFS, BLKDEV_IFL_WAIT);
+@@ -2596,12 +2549,12 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 	ee_block = le32_to_cpu(ex->ee_block);
+ 	ee_len = ext4_ext_get_actual_len(ex);
+ 	allocated = ee_len - (map->m_lblk - ee_block);
+-	newblock = map->m_lblk - ee_block + ext_pblock(ex);
++	newblock = map->m_lblk - ee_block + ext4_ext_pblock(ex);
+ 
+ 	ex2 = ex;
+ 	orig_ex.ee_block = ex->ee_block;
+ 	orig_ex.ee_len   = cpu_to_le16(ee_len);
+-	ext4_ext_store_pblock(&orig_ex, ext_pblock(ex));
++	ext4_ext_store_pblock(&orig_ex, ext4_ext_pblock(ex));
+ 
+ 	/*
+ 	 * It is safe to convert extent to initialized via explicit
+@@ -2620,7 +2573,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 		/* update the extent length and mark as initialized */
+ 		ex->ee_block = orig_ex.ee_block;
+ 		ex->ee_len   = orig_ex.ee_len;
+-		ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
++		ext4_ext_store_pblock(ex, ext4_ext_pblock(&orig_ex));
+ 		ext4_ext_dirty(handle, inode, path + depth);
+ 		/* zeroed the full extent */
+ 		return allocated;
+@@ -2655,7 +2608,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 			ex->ee_block = orig_ex.ee_block;
+ 			ex->ee_len   = cpu_to_le16(ee_len - allocated);
+ 			ext4_ext_mark_uninitialized(ex);
+-			ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
++			ext4_ext_store_pblock(ex, ext4_ext_pblock(&orig_ex));
+ 			ext4_ext_dirty(handle, inode, path + depth);
+ 
+ 			ex3 = &newex;
+@@ -2670,7 +2623,8 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 					goto fix_extent_len;
+ 				ex->ee_block = orig_ex.ee_block;
+ 				ex->ee_len   = orig_ex.ee_len;
+-				ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
++				ext4_ext_store_pblock(ex,
++					ext4_ext_pblock(&orig_ex));
+ 				ext4_ext_dirty(handle, inode, path + depth);
+ 				/* blocks available from map->m_lblk */
+ 				return allocated;
+@@ -2727,7 +2681,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 			/* update the extent length and mark as initialized */
+ 			ex->ee_block = orig_ex.ee_block;
+ 			ex->ee_len   = orig_ex.ee_len;
+-			ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
++			ext4_ext_store_pblock(ex, ext4_ext_pblock(&orig_ex));
+ 			ext4_ext_dirty(handle, inode, path + depth);
+ 			/* zeroed the full extent */
+ 			/* blocks available from map->m_lblk */
+@@ -2778,7 +2732,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 			/* update the extent length and mark as initialized */
+ 			ex->ee_block = orig_ex.ee_block;
+ 			ex->ee_len   = orig_ex.ee_len;
+-			ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
++			ext4_ext_store_pblock(ex, ext4_ext_pblock(&orig_ex));
+ 			ext4_ext_dirty(handle, inode, path + depth);
+ 			/* zero out the first half */
+ 			/* blocks available from map->m_lblk */
+@@ -2847,7 +2801,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 		/* update the extent length and mark as initialized */
+ 		ex->ee_block = orig_ex.ee_block;
+ 		ex->ee_len   = orig_ex.ee_len;
+-		ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
++		ext4_ext_store_pblock(ex, ext4_ext_pblock(&orig_ex));
+ 		ext4_ext_dirty(handle, inode, path + depth);
+ 		/* zero out the first half */
+ 		return allocated;
+@@ -2860,7 +2814,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ fix_extent_len:
+ 	ex->ee_block = orig_ex.ee_block;
+ 	ex->ee_len   = orig_ex.ee_len;
+-	ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
++	ext4_ext_store_pblock(ex, ext4_ext_pblock(&orig_ex));
+ 	ext4_ext_mark_uninitialized(ex);
+ 	ext4_ext_dirty(handle, inode, path + depth);
+ 	return err;
+@@ -2918,12 +2872,12 @@ static int ext4_split_unwritten_extents(handle_t *handle,
+ 	ee_block = le32_to_cpu(ex->ee_block);
+ 	ee_len = ext4_ext_get_actual_len(ex);
+ 	allocated = ee_len - (map->m_lblk - ee_block);
+-	newblock = map->m_lblk - ee_block + ext_pblock(ex);
++	newblock = map->m_lblk - ee_block + ext4_ext_pblock(ex);
+ 
+ 	ex2 = ex;
+ 	orig_ex.ee_block = ex->ee_block;
+ 	orig_ex.ee_len   = cpu_to_le16(ee_len);
+-	ext4_ext_store_pblock(&orig_ex, ext_pblock(ex));
++	ext4_ext_store_pblock(&orig_ex, ext4_ext_pblock(ex));
+ 
+ 	/*
+ 	 * It is safe to convert extent to initialized via explicit
+@@ -2972,7 +2926,7 @@ static int ext4_split_unwritten_extents(handle_t *handle,
+ 			/* update the extent length and mark as initialized */
+ 			ex->ee_block = orig_ex.ee_block;
+ 			ex->ee_len   = orig_ex.ee_len;
+-			ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
++			ext4_ext_store_pblock(ex, ext4_ext_pblock(&orig_ex));
+ 			ext4_ext_dirty(handle, inode, path + depth);
+ 			/* zeroed the full extent */
+ 			/* blocks available from map->m_lblk */
+@@ -3044,7 +2998,7 @@ static int ext4_split_unwritten_extents(handle_t *handle,
+ 		/* update the extent length and mark as initialized */
+ 		ex->ee_block = orig_ex.ee_block;
+ 		ex->ee_len   = orig_ex.ee_len;
+-		ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
++		ext4_ext_store_pblock(ex, ext4_ext_pblock(&orig_ex));
+ 		ext4_ext_dirty(handle, inode, path + depth);
+ 		/* zero out the first half */
+ 		return allocated;
+@@ -3057,7 +3011,7 @@ static int ext4_split_unwritten_extents(handle_t *handle,
+ fix_extent_len:
+ 	ex->ee_block = orig_ex.ee_block;
+ 	ex->ee_len   = orig_ex.ee_len;
+-	ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
++	ext4_ext_store_pblock(ex, ext4_ext_pblock(&orig_ex));
+ 	ext4_ext_mark_uninitialized(ex);
+ 	ext4_ext_dirty(handle, inode, path + depth);
+ 	return err;
+@@ -3347,7 +3301,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 			/* block is already allocated */
+ 			newblock = map->m_lblk
+ 				   - le32_to_cpu(newex.ee_block)
+-				   + ext_pblock(&newex);
++				   + ext4_ext_pblock(&newex);
+ 			/* number of remaining blocks in the extent */
+ 			allocated = ext4_ext_get_actual_len(&newex) -
+ 				(map->m_lblk - le32_to_cpu(newex.ee_block));
+@@ -3385,7 +3339,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 	ex = path[depth].p_ext;
+ 	if (ex) {
+ 		ext4_lblk_t ee_block = le32_to_cpu(ex->ee_block);
+-		ext4_fsblk_t ee_start = ext_pblock(ex);
++		ext4_fsblk_t ee_start = ext4_ext_pblock(ex);
+ 		unsigned short ee_len;
+ 
+ 		/*
+@@ -3513,13 +3467,13 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 		/* not a good idea to call discard here directly,
+ 		 * but otherwise we'd need to call it every free() */
+ 		ext4_discard_preallocations(inode);
+-		ext4_free_blocks(handle, inode, 0, ext_pblock(&newex),
++		ext4_free_blocks(handle, inode, 0, ext4_ext_pblock(&newex),
+ 				 ext4_ext_get_actual_len(&newex), 0);
+ 		goto out2;
+ 	}
+ 
+ 	/* previous routine could use block we allocated */
+-	newblock = ext_pblock(&newex);
++	newblock = ext4_ext_pblock(&newex);
+ 	allocated = ext4_ext_get_actual_len(&newex);
+ 	if (allocated > map->m_len)
+ 		allocated = map->m_len;
+diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
+index 1765c2c50a9b..25f3a974b725 100644
+--- a/fs/ext4/migrate.c
++++ b/fs/ext4/migrate.c
+@@ -412,7 +412,7 @@ static int free_ext_idx(handle_t *handle, struct inode *inode,
+ 	struct buffer_head *bh;
+ 	struct ext4_extent_header *eh;
+ 
+-	block = idx_pblock(ix);
++	block = ext4_idx_pblock(ix);
+ 	bh = sb_bread(inode->i_sb, block);
+ 	if (!bh)
+ 		return -EIO;
+diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
+index 5f1ed9fc913c..b9f3e7862f13 100644
+--- a/fs/ext4/move_extent.c
++++ b/fs/ext4/move_extent.c
+@@ -85,7 +85,7 @@ mext_next_extent(struct inode *inode, struct ext4_ext_path *path,
+ 	if (EXT_LAST_EXTENT(path[ppos].p_hdr) > path[ppos].p_ext) {
+ 		/* leaf block */
+ 		*extent = ++path[ppos].p_ext;
+-		path[ppos].p_block = ext_pblock(path[ppos].p_ext);
++		path[ppos].p_block = ext4_ext_pblock(path[ppos].p_ext);
+ 		return 0;
+ 	}
+ 
+@@ -96,7 +96,7 @@ mext_next_extent(struct inode *inode, struct ext4_ext_path *path,
+ 
+ 			/* index block */
+ 			path[ppos].p_idx++;
+-			path[ppos].p_block = idx_pblock(path[ppos].p_idx);
++			path[ppos].p_block = ext4_idx_pblock(path[ppos].p_idx);
+ 			if (path[ppos+1].p_bh)
+ 				brelse(path[ppos+1].p_bh);
+ 			path[ppos+1].p_bh =
+@@ -111,7 +111,7 @@ mext_next_extent(struct inode *inode, struct ext4_ext_path *path,
+ 				path[cur_ppos].p_idx =
+ 					EXT_FIRST_INDEX(path[cur_ppos].p_hdr);
+ 				path[cur_ppos].p_block =
+-					idx_pblock(path[cur_ppos].p_idx);
++					ext4_idx_pblock(path[cur_ppos].p_idx);
+ 				if (path[cur_ppos+1].p_bh)
+ 					brelse(path[cur_ppos+1].p_bh);
+ 				path[cur_ppos+1].p_bh = sb_bread(inode->i_sb,
+@@ -133,7 +133,7 @@ mext_next_extent(struct inode *inode, struct ext4_ext_path *path,
+ 			path[leaf_ppos].p_ext = *extent =
+ 				EXT_FIRST_EXTENT(path[leaf_ppos].p_hdr);
+ 			path[leaf_ppos].p_block =
+-					ext_pblock(path[leaf_ppos].p_ext);
++					ext4_ext_pblock(path[leaf_ppos].p_ext);
+ 			return 0;
+ 		}
+ 	}
+@@ -249,7 +249,7 @@ mext_insert_across_blocks(handle_t *handle, struct inode *orig_inode,
+ 			 */
+ 			o_end->ee_block = end_ext->ee_block;
+ 			o_end->ee_len = end_ext->ee_len;
+-			ext4_ext_store_pblock(o_end, ext_pblock(end_ext));
++			ext4_ext_store_pblock(o_end, ext4_ext_pblock(end_ext));
+ 		}
+ 
+ 		o_start->ee_len = start_ext->ee_len;
+@@ -276,7 +276,7 @@ mext_insert_across_blocks(handle_t *handle, struct inode *orig_inode,
+ 		 */
+ 		o_end->ee_block = end_ext->ee_block;
+ 		o_end->ee_len = end_ext->ee_len;
+-		ext4_ext_store_pblock(o_end, ext_pblock(end_ext));
++		ext4_ext_store_pblock(o_end, ext4_ext_pblock(end_ext));
+ 
+ 		/*
+ 		 * Set 0 to the extent block if new_ext was
+@@ -361,7 +361,7 @@ mext_insert_inside_block(struct ext4_extent *o_start,
+ 	/* Insert new entry */
+ 	if (new_ext->ee_len) {
+ 		o_start[i] = *new_ext;
+-		ext4_ext_store_pblock(&o_start[i++], ext_pblock(new_ext));
++		ext4_ext_store_pblock(&o_start[i++], ext4_ext_pblock(new_ext));
+ 	}
+ 
+ 	/* Insert end entry */
+@@ -488,7 +488,7 @@ mext_leaf_block(handle_t *handle, struct inode *orig_inode,
+ 	start_ext.ee_len = end_ext.ee_len = 0;
+ 
+ 	new_ext.ee_block = cpu_to_le32(*from);
+-	ext4_ext_store_pblock(&new_ext, ext_pblock(dext));
++	ext4_ext_store_pblock(&new_ext, ext4_ext_pblock(dext));
+ 	new_ext.ee_len = dext->ee_len;
+ 	new_ext_alen = ext4_ext_get_actual_len(&new_ext);
+ 	new_ext_end = le32_to_cpu(new_ext.ee_block) + new_ext_alen - 1;
+@@ -553,7 +553,7 @@ mext_leaf_block(handle_t *handle, struct inode *orig_inode,
+ 		copy_extent_status(oext, &end_ext);
+ 		end_ext_alen = ext4_ext_get_actual_len(&end_ext);
+ 		ext4_ext_store_pblock(&end_ext,
+-			(ext_pblock(o_end) + oext_alen - end_ext_alen));
++			(ext4_ext_pblock(o_end) + oext_alen - end_ext_alen));
+ 		end_ext.ee_block =
+ 			cpu_to_le32(le32_to_cpu(o_end->ee_block) +
+ 			oext_alen - end_ext_alen);
+@@ -604,7 +604,7 @@ mext_calc_swap_extents(struct ext4_extent *tmp_dext,
+ 	/* When tmp_dext is too large, pick up the target range. */
+ 	diff = donor_off - le32_to_cpu(tmp_dext->ee_block);
+ 
+-	ext4_ext_store_pblock(tmp_dext, ext_pblock(tmp_dext) + diff);
++	ext4_ext_store_pblock(tmp_dext, ext4_ext_pblock(tmp_dext) + diff);
+ 	tmp_dext->ee_block =
+ 			cpu_to_le32(le32_to_cpu(tmp_dext->ee_block) + diff);
+ 	tmp_dext->ee_len = cpu_to_le16(le16_to_cpu(tmp_dext->ee_len) - diff);
+@@ -613,7 +613,7 @@ mext_calc_swap_extents(struct ext4_extent *tmp_dext,
+ 		tmp_dext->ee_len = cpu_to_le16(max_count);
+ 
+ 	orig_diff = orig_off - le32_to_cpu(tmp_oext->ee_block);
+-	ext4_ext_store_pblock(tmp_oext, ext_pblock(tmp_oext) + orig_diff);
++	ext4_ext_store_pblock(tmp_oext, ext4_ext_pblock(tmp_oext) + orig_diff);
+ 
+ 	/* Adjust extent length if donor extent is larger than orig */
+ 	if (ext4_ext_get_actual_len(tmp_dext) >

commit 1f109d5a17b438c4a54cbf6fd87a249e3d72fb21
+Author: Theodore Ts'o 
+Date:   Wed Oct 27 21:30:14 2010 -0400
+
+    ext4: make various ext4 functions be static
+    
+    These functions have no need to be exported beyond file context.
+    
+    No functions needed to be moved for this commit; just some function
+    declarations changed to be static and removed from header files.
+    
+    (A similar patch was submitted by Eric Sandeen, but I wanted to handle
+    code movement in separate patches to make sure code changes didn't
+    accidentally get dropped.)
+    
+    Signed-off-by: Eric Sandeen 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index bd30799a43ed..a12cefc20c76 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -489,7 +489,7 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
+  * Check if filesystem has nblocks free & available for allocation.
+  * On success return 1, return 0 on failure.
+  */
+-int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks)
++static int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks)
+ {
+ 	s64 free_blocks, dirty_blocks, root_blocks;
+ 	struct percpu_counter *fbc = &sbi->s_freeblocks_counter;
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 5d72c261d7e9..ac1afc148b36 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1558,8 +1558,6 @@ ext4_group_first_block_no(struct super_block *sb, ext4_group_t group_no)
+ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
+ 			ext4_group_t *blockgrpp, ext4_grpblk_t *offsetp);
+ 
+-extern struct proc_dir_entry *ext4_proc_root;
+-
+ /*
+  * Timeout and state flag for lazy initialization inode thread.
+  */
+@@ -1623,7 +1621,6 @@ extern unsigned long ext4_bg_num_gdb(struct super_block *sb,
+ extern ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
+ 			ext4_fsblk_t goal, unsigned long *count, int *errp);
+ extern int ext4_claim_free_blocks(struct ext4_sb_info *sbi, s64 nblocks);
+-extern int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks);
+ extern void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
+ 				ext4_fsblk_t block, unsigned long count);
+ extern ext4_fsblk_t ext4_count_free_blocks(struct super_block *);
+@@ -1667,10 +1664,6 @@ extern struct inode * ext4_orphan_get(struct super_block *, unsigned long);
+ extern unsigned long ext4_count_free_inodes(struct super_block *);
+ extern unsigned long ext4_count_dirs(struct super_block *);
+ extern void ext4_check_inodes_bitmap(struct super_block *);
+-extern unsigned ext4_init_inode_bitmap(struct super_block *sb,
+-				       struct buffer_head *bh,
+-				       ext4_group_t group,
+-				       struct ext4_group_desc *desc);
+ extern void mark_bitmap_end(int start_bit, int end_bit, char *bitmap);
+ extern int ext4_init_inode_table(struct super_block *sb,
+ 				 ext4_group_t group, int barrier);
+@@ -1723,7 +1716,6 @@ extern void ext4_get_inode_flags(struct ext4_inode_info *);
+ extern int ext4_alloc_da_blocks(struct inode *inode);
+ extern void ext4_set_aops(struct inode *inode);
+ extern int ext4_writepage_trans_blocks(struct inode *);
+-extern int ext4_meta_trans_blocks(struct inode *, int nrblocks, int idxblocks);
+ extern int ext4_chunk_trans_blocks(struct inode *, int nrblocks);
+ extern int ext4_block_truncate_page(handle_t *handle,
+ 		struct address_space *mapping, loff_t from);
+diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h
+index bdb6ce7e2eb4..e427082e9ffc 100644
+--- a/fs/ext4/ext4_extents.h
++++ b/fs/ext4/ext4_extents.h
+@@ -237,19 +237,9 @@ extern int ext4_ext_calc_credits_for_single_extent(struct inode *inode,
+ extern int ext4_can_extents_be_merged(struct inode *inode,
+ 				      struct ext4_extent *ex1,
+ 				      struct ext4_extent *ex2);
+-extern int ext4_ext_try_to_merge(struct inode *inode,
+-				 struct ext4_ext_path *path,
+-				 struct ext4_extent *);
+-extern unsigned int ext4_ext_check_overlap(struct inode *, struct ext4_extent *, struct ext4_ext_path *);
+ extern int ext4_ext_insert_extent(handle_t *, struct inode *, struct ext4_ext_path *, struct ext4_extent *, int);
+-extern int ext4_ext_walk_space(struct inode *, ext4_lblk_t, ext4_lblk_t,
+-							ext_prepare_callback, void *);
+ extern struct ext4_ext_path *ext4_ext_find_extent(struct inode *, ext4_lblk_t,
+ 							struct ext4_ext_path *);
+-extern int ext4_ext_search_left(struct inode *, struct ext4_ext_path *,
+-						ext4_lblk_t *, ext4_fsblk_t *);
+-extern int ext4_ext_search_right(struct inode *, struct ext4_ext_path *,
+-						ext4_lblk_t *, ext4_fsblk_t *);
+ extern void ext4_ext_drop_refs(struct ext4_ext_path *);
+ extern int ext4_ext_check_inode(struct inode *inode);
+ #endif /* _EXT4_EXTENTS */
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index a1e20c8c4e0c..bd95375314ab 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -739,9 +739,9 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
+  * insert new index [@logical;@ptr] into the block at @curp;
+  * check where to insert: before @curp or after @curp
+  */
+-int ext4_ext_insert_index(handle_t *handle, struct inode *inode,
+-				struct ext4_ext_path *curp,
+-				int logical, ext4_fsblk_t ptr)
++static int ext4_ext_insert_index(handle_t *handle, struct inode *inode,
++				 struct ext4_ext_path *curp,
++				 int logical, ext4_fsblk_t ptr)
+ {
+ 	struct ext4_extent_idx *ix;
+ 	int len, err;
+@@ -1232,9 +1232,9 @@ static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
+  * returns 0 at @phys
+  * return value contains 0 (success) or error code
+  */
+-int
+-ext4_ext_search_left(struct inode *inode, struct ext4_ext_path *path,
+-			ext4_lblk_t *logical, ext4_fsblk_t *phys)
++static int ext4_ext_search_left(struct inode *inode,
++				struct ext4_ext_path *path,
++				ext4_lblk_t *logical, ext4_fsblk_t *phys)
+ {
+ 	struct ext4_extent_idx *ix;
+ 	struct ext4_extent *ex;
+@@ -1297,9 +1297,9 @@ ext4_ext_search_left(struct inode *inode, struct ext4_ext_path *path,
+  * returns 0 at @phys
+  * return value contains 0 (success) or error code
+  */
+-int
+-ext4_ext_search_right(struct inode *inode, struct ext4_ext_path *path,
+-			ext4_lblk_t *logical, ext4_fsblk_t *phys)
++static int ext4_ext_search_right(struct inode *inode,
++				 struct ext4_ext_path *path,
++				 ext4_lblk_t *logical, ext4_fsblk_t *phys)
+ {
+ 	struct buffer_head *bh = NULL;
+ 	struct ext4_extent_header *eh;
+@@ -1585,9 +1585,9 @@ ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1,
+  * Returns 0 if the extents (ex and ex+1) were _not_ merged and returns
+  * 1 if they got merged.
+  */
+-int ext4_ext_try_to_merge(struct inode *inode,
+-			  struct ext4_ext_path *path,
+-			  struct ext4_extent *ex)
++static int ext4_ext_try_to_merge(struct inode *inode,
++				 struct ext4_ext_path *path,
++				 struct ext4_extent *ex)
+ {
+ 	struct ext4_extent_header *eh;
+ 	unsigned int depth, len;
+@@ -1632,9 +1632,9 @@ int ext4_ext_try_to_merge(struct inode *inode,
+  * such that there will be no overlap, and then returns 1.
+  * If there is no overlap found, it returns 0.
+  */
+-unsigned int ext4_ext_check_overlap(struct inode *inode,
+-				    struct ext4_extent *newext,
+-				    struct ext4_ext_path *path)
++static unsigned int ext4_ext_check_overlap(struct inode *inode,
++					   struct ext4_extent *newext,
++					   struct ext4_ext_path *path)
+ {
+ 	ext4_lblk_t b1, b2;
+ 	unsigned int depth, len1;
+@@ -1845,9 +1845,9 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+ 	return err;
+ }
+ 
+-int ext4_ext_walk_space(struct inode *inode, ext4_lblk_t block,
+-			ext4_lblk_t num, ext_prepare_callback func,
+-			void *cbdata)
++static int ext4_ext_walk_space(struct inode *inode, ext4_lblk_t block,
++			       ext4_lblk_t num, ext_prepare_callback func,
++			       void *cbdata)
+ {
+ 	struct ext4_ext_path *path = NULL;
+ 	struct ext4_ext_cache cbex;
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 87d228aae6b0..9666e4c6efb4 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -65,9 +65,10 @@ void mark_bitmap_end(int start_bit, int end_bit, char *bitmap)
+ }
+ 
+ /* Initializes an uninitialized inode bitmap */
+-unsigned ext4_init_inode_bitmap(struct super_block *sb, struct buffer_head *bh,
+-				ext4_group_t block_group,
+-				struct ext4_group_desc *gdp)
++static unsigned ext4_init_inode_bitmap(struct super_block *sb,
++				       struct buffer_head *bh,
++				       ext4_group_t block_group,
++				       struct ext4_group_desc *gdp)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 
+@@ -414,8 +415,8 @@ struct orlov_stats {
+  * for a particular block group or flex_bg.  If flex_size is 1, then g
+  * is a block group number; otherwise it is flex_bg number.
+  */
+-void get_orlov_stats(struct super_block *sb, ext4_group_t g,
+-		       int flex_size, struct orlov_stats *stats)
++static void get_orlov_stats(struct super_block *sb, ext4_group_t g,
++			    int flex_size, struct orlov_stats *stats)
+ {
+ 	struct ext4_group_desc *desc;
+ 	struct flex_groups *flex_group = EXT4_SB(sb)->s_flex_groups;
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 45fc5bdb7d67..7a83c2793956 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -5543,7 +5543,7 @@ static int ext4_index_trans_blocks(struct inode *inode, int nrblocks, int chunk)
+  *
+  * Also account for superblock, inode, quota and xattr blocks
+  */
+-int ext4_meta_trans_blocks(struct inode *inode, int nrblocks, int chunk)
++static int ext4_meta_trans_blocks(struct inode *inode, int nrblocks, int chunk)
+ {
+ 	ext4_group_t groups, ngroups = ext4_get_groups_count(inode->i_sb);
+ 	int gdpblocks;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 94e60038e05d..158d1bca8769 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -53,7 +53,7 @@
+ #define CREATE_TRACE_POINTS
+ #include 
+ 
+-struct proc_dir_entry *ext4_proc_root;
++static struct proc_dir_entry *ext4_proc_root;
+ static struct kset *ext4_kset;
+ struct ext4_lazy_init *ext4_li_info;
+ struct mutex ext4_li_mtx;

commit 5dabfc78dcedbe46cb2e4872dde448de3cec2979
+Author: Theodore Ts'o 
+Date:   Wed Oct 27 21:30:14 2010 -0400
+
+    ext4: rename {exit,init}_ext4_*() to ext4_{exit,init}_*()
+    
+    This is a cleanup to avoid namespace leaks out of fs/ext4
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/block_validity.c b/fs/ext4/block_validity.c
+index 68bab70dd139..fac90f3fba80 100644
+--- a/fs/ext4/block_validity.c
++++ b/fs/ext4/block_validity.c
+@@ -29,7 +29,7 @@ struct ext4_system_zone {
+ 
+ static struct kmem_cache *ext4_system_zone_cachep;
+ 
+-int __init init_ext4_system_zone(void)
++int __init ext4_init_system_zone(void)
+ {
+ 	ext4_system_zone_cachep = KMEM_CACHE(ext4_system_zone, 0);
+ 	if (ext4_system_zone_cachep == NULL)
+@@ -37,7 +37,7 @@ int __init init_ext4_system_zone(void)
+ 	return 0;
+ }
+ 
+-void exit_ext4_system_zone(void)
++void ext4_exit_system_zone(void)
+ {
+ 	kmem_cache_destroy(ext4_system_zone_cachep);
+ }
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 98dde2b7dd6f..5d72c261d7e9 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1684,8 +1684,8 @@ extern ext4_fsblk_t ext4_mb_new_blocks(handle_t *,
+ 				struct ext4_allocation_request *, int *);
+ extern int ext4_mb_reserve_blocks(struct super_block *, int);
+ extern void ext4_discard_preallocations(struct inode *);
+-extern int __init init_ext4_mballoc(void);
+-extern void exit_ext4_mballoc(void);
++extern int __init ext4_init_mballoc(void);
++extern void ext4_exit_mballoc(void);
+ extern void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 			     struct buffer_head *bh, ext4_fsblk_t block,
+ 			     unsigned long count, int flags);
+@@ -2040,8 +2040,8 @@ extern const struct inode_operations ext4_fast_symlink_inode_operations;
+ /* block_validity */
+ extern void ext4_release_system_zone(struct super_block *sb);
+ extern int ext4_setup_system_zone(struct super_block *sb);
+-extern int __init init_ext4_system_zone(void);
+-extern void exit_ext4_system_zone(void);
++extern int __init ext4_init_system_zone(void);
++extern void ext4_exit_system_zone(void);
+ extern int ext4_data_block_valid(struct ext4_sb_info *sbi,
+ 				 ext4_fsblk_t start_blk,
+ 				 unsigned int count);
+@@ -2070,8 +2070,8 @@ extern int ext4_move_extents(struct file *o_filp, struct file *d_filp,
+ 			     __u64 len, __u64 *moved_len);
+ 
+ /* page-io.c */
+-extern int __init init_ext4_pageio(void);
+-extern void exit_ext4_pageio(void);
++extern int __init ext4_init_pageio(void);
++extern void ext4_exit_pageio(void);
+ extern void ext4_free_io_end(ext4_io_end_t *io);
+ extern ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags);
+ extern int ext4_end_io_nolock(ext4_io_end_t *io);
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index e3bcc06b4906..381ac565786a 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2705,7 +2705,7 @@ static void ext4_remove_debugfs_entry(void)
+ 
+ #endif
+ 
+-int __init init_ext4_mballoc(void)
++int __init ext4_init_mballoc(void)
+ {
+ 	ext4_pspace_cachep = KMEM_CACHE(ext4_prealloc_space,
+ 					SLAB_RECLAIM_ACCOUNT);
+@@ -2730,7 +2730,7 @@ int __init init_ext4_mballoc(void)
+ 	return 0;
+ }
+ 
+-void exit_ext4_mballoc(void)
++void ext4_exit_mballoc(void)
+ {
+ 	int i;
+ 	/*
+diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
+index b972ca50f851..46a7d6a9d976 100644
+--- a/fs/ext4/page-io.c
++++ b/fs/ext4/page-io.c
+@@ -32,7 +32,7 @@
+ 
+ static struct kmem_cache *io_page_cachep, *io_end_cachep;
+ 
+-int __init init_ext4_pageio(void)
++int __init ext4_init_pageio(void)
+ {
+ 	io_page_cachep = KMEM_CACHE(ext4_io_page, SLAB_RECLAIM_ACCOUNT);
+ 	if (io_page_cachep == NULL)
+@@ -46,7 +46,7 @@ int __init init_ext4_pageio(void)
+ 	return 0;
+ }
+ 
+-void exit_ext4_pageio(void)
++void ext4_exit_pageio(void)
+ {
+ 	kmem_cache_destroy(io_end_cachep);
+ 	kmem_cache_destroy(io_page_cachep);
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index c9e06c647ce8..94e60038e05d 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4770,15 +4770,15 @@ int __init ext4_init_feat_adverts(void)
+ 	return ret;
+ }
+ 
+-static int __init init_ext4_fs(void)
++static int __init ext4_init_fs(void)
+ {
+ 	int err;
+ 
+ 	ext4_check_flag_values();
+-	err = init_ext4_pageio();
++	err = ext4_init_pageio();
+ 	if (err)
+ 		return err;
+-	err = init_ext4_system_zone();
++	err = ext4_init_system_zone();
+ 	if (err)
+ 		goto out5;
+ 	ext4_kset = kset_create_and_add("ext4", NULL, fs_kobj);
+@@ -4788,11 +4788,11 @@ static int __init init_ext4_fs(void)
+ 
+ 	err = ext4_init_feat_adverts();
+ 
+-	err = init_ext4_mballoc();
++	err = ext4_init_mballoc();
+ 	if (err)
+ 		goto out3;
+ 
+-	err = init_ext4_xattr();
++	err = ext4_init_xattr();
+ 	if (err)
+ 		goto out2;
+ 	err = init_inodecache();
+@@ -4812,37 +4812,37 @@ static int __init init_ext4_fs(void)
+ 	unregister_as_ext3();
+ 	destroy_inodecache();
+ out1:
+-	exit_ext4_xattr();
++	ext4_exit_xattr();
+ out2:
+-	exit_ext4_mballoc();
++	ext4_exit_mballoc();
+ out3:
+ 	kfree(ext4_feat);
+ 	remove_proc_entry("fs/ext4", NULL);
+ 	kset_unregister(ext4_kset);
+ out4:
+-	exit_ext4_system_zone();
++	ext4_exit_system_zone();
+ out5:
+-	exit_ext4_pageio();
++	ext4_exit_pageio();
+ 	return err;
+ }
+ 
+-static void __exit exit_ext4_fs(void)
++static void __exit ext4_exit_fs(void)
+ {
+ 	ext4_destroy_lazyinit_thread();
+ 	unregister_as_ext2();
+ 	unregister_as_ext3();
+ 	unregister_filesystem(&ext4_fs_type);
+ 	destroy_inodecache();
+-	exit_ext4_xattr();
+-	exit_ext4_mballoc();
++	ext4_exit_xattr();
++	ext4_exit_mballoc();
+ 	remove_proc_entry("fs/ext4", NULL);
+ 	kset_unregister(ext4_kset);
+-	exit_ext4_system_zone();
+-	exit_ext4_pageio();
++	ext4_exit_system_zone();
++	ext4_exit_pageio();
+ }
+ 
+ MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
+ MODULE_DESCRIPTION("Fourth Extended Filesystem");
+ MODULE_LICENSE("GPL");
+-module_init(init_ext4_fs)
+-module_exit(exit_ext4_fs)
++module_init(ext4_init_fs)
++module_exit(ext4_exit_fs)
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 3a8cd8dff1ad..fa4b899da4b3 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -1588,7 +1588,7 @@ static void ext4_xattr_rehash(struct ext4_xattr_header *header,
+ #undef BLOCK_HASH_SHIFT
+ 
+ int __init
+-init_ext4_xattr(void)
++ext4_init_xattr(void)
+ {
+ 	ext4_xattr_cache = mb_cache_create("ext4_xattr", 6);
+ 	if (!ext4_xattr_cache)
+@@ -1597,7 +1597,7 @@ init_ext4_xattr(void)
+ }
+ 
+ void
+-exit_ext4_xattr(void)
++ext4_exit_xattr(void)
+ {
+ 	if (ext4_xattr_cache)
+ 		mb_cache_destroy(ext4_xattr_cache);
+diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
+index 518e96e43905..281dd8353652 100644
+--- a/fs/ext4/xattr.h
++++ b/fs/ext4/xattr.h
+@@ -83,8 +83,8 @@ extern void ext4_xattr_put_super(struct super_block *);
+ extern int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
+ 			    struct ext4_inode *raw_inode, handle_t *handle);
+ 
+-extern int init_ext4_xattr(void);
+-extern void exit_ext4_xattr(void);
++extern int __init ext4_init_xattr(void);
++extern void ext4_exit_xattr(void);
+ 
+ extern const struct xattr_handler *ext4_xattr_handlers[];
+ 
+@@ -121,14 +121,14 @@ ext4_xattr_put_super(struct super_block *sb)
+ {
+ }
+ 
+-static inline int
++static __init inline int
+ init_ext4_xattr(void)
+ {
+ 	return 0;
+ }
+ 
+ static inline void
+-exit_ext4_xattr(void)
++ext4_exit_xattr(void)
+ {
+ }
+ 

commit 7f93cff90fa9be6ed45f6189e136153d1d8631b0
+Author: Theodore Ts'o 
+Date:   Wed Oct 27 21:30:13 2010 -0400
+
+    ext4: fix kernel oops if the journal superblock has a non-zero j_errno
+    
+    Commit 84061e0 fixed an accounting bug only to introduce the
+    possibility of a kernel OOPS if the journal has a non-zero j_errno
+    field indicating that the file system had detected a fs inconsistency.
+    After the journal replay, if the journal superblock indicates that the
+    file system has an error, this indication is transfered to the file
+    system and then ext4_commit_super() is called to write this to the
+    disk.
+    
+    But since the percpu counters are now initialized after the journal
+    replay, the call to ext4_commit_super() will cause a kernel oops since
+    it needs to use the percpu counters the ext4 superblock structure.
+    
+    The fix is to skip setting the ext4 free block and free inode fields
+    if the percpu counter has not been set.
+    
+    Thanks to Ken Sumrall for reporting and analyzing the root causes of
+    this bug.
+    
+    Addresses-Google-Bug: #3054080
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 9ce3b67b7269..c9e06c647ce8 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3964,9 +3964,12 @@ static int ext4_commit_super(struct super_block *sb, int sync)
+ 	else
+ 		es->s_kbytes_written =
+ 			cpu_to_le64(EXT4_SB(sb)->s_kbytes_written);
+-	ext4_free_blocks_count_set(es, percpu_counter_sum_positive(
++	if (percpu_counter_initialized(&EXT4_SB(sb)->s_freeblocks_counter))
++		ext4_free_blocks_count_set(es, percpu_counter_sum_positive(
+ 					&EXT4_SB(sb)->s_freeblocks_counter));
+-	es->s_free_inodes_count = cpu_to_le32(percpu_counter_sum_positive(
++	if (percpu_counter_initialized(&EXT4_SB(sb)->s_freeinodes_counter))
++		es->s_free_inodes_count =
++			cpu_to_le32(percpu_counter_sum_positive(
+ 					&EXT4_SB(sb)->s_freeinodes_counter));
+ 	sb->s_dirt = 0;
+ 	BUFFER_TRACE(sbh, "marking dirty");
+diff --git a/include/linux/percpu_counter.h b/include/linux/percpu_counter.h
+index 8a7d510ffa9c..46f6ba56fa91 100644
+--- a/include/linux/percpu_counter.h
++++ b/include/linux/percpu_counter.h
+@@ -78,6 +78,11 @@ static inline s64 percpu_counter_read_positive(struct percpu_counter *fbc)
+ 	return 1;
+ }
+ 
++static inline int percpu_counter_initialized(struct percpu_counter *fbc)
++{
++	return (fbc->counters != NULL);
++}
++
+ #else
+ 
+ struct percpu_counter {
+@@ -143,6 +148,11 @@ static inline s64 percpu_counter_sum(struct percpu_counter *fbc)
+ 	return percpu_counter_read(fbc);
+ }
+ 
++static inline int percpu_counter_initialized(struct percpu_counter *fbc)
++{
++	return 1;
++}
++
+ #endif	/* CONFIG_SMP */
+ 
+ static inline void percpu_counter_inc(struct percpu_counter *fbc)

commit bd2d0210cf22f2bd0cef72eb97cf94fc7d31d8cc
+Author: Theodore Ts'o 
+Date:   Wed Oct 27 21:30:10 2010 -0400
+
+    ext4: use bio layer instead of buffer layer in mpage_da_submit_io
+    
+    Call the block I/O layer directly instad of going through the buffer
+    layer.  This should give us much better performance and scalability,
+    as well as lowering our CPU utilization when doing buffered writeback.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
+index 8867b2a1e5fe..c947e36eda6c 100644
+--- a/fs/ext4/Makefile
++++ b/fs/ext4/Makefile
+@@ -4,7 +4,7 @@
+ 
+ obj-$(CONFIG_EXT4_FS) += ext4.o
+ 
+-ext4-y	:= balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
++ext4-y	:= balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o page-io.o \
+ 		ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \
+ 		ext4_jbd2.o migrate.o mballoc.o block_validity.o move_extent.o
+ 
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 22833691e98c..ca9fda64dd4f 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -168,7 +168,20 @@ struct mpage_da_data {
+ 	int pages_written;
+ 	int retval;
+ };
+-#define	EXT4_IO_UNWRITTEN	0x1
++
++/*
++ * Flags for ext4_io_end->flags
++ */
++#define	EXT4_IO_END_UNWRITTEN	0x0001
++#define EXT4_IO_END_ERROR	0x0002
++
++struct ext4_io_page {
++	struct page	*p_page;
++	int		p_count;
++};
++
++#define MAX_IO_PAGES 128
++
+ typedef struct ext4_io_end {
+ 	struct list_head	list;		/* per-file finished IO list */
+ 	struct inode		*inode;		/* file being written to */
+@@ -179,8 +192,18 @@ typedef struct ext4_io_end {
+ 	struct work_struct	work;		/* data work queue */
+ 	struct kiocb		*iocb;		/* iocb struct for AIO */
+ 	int			result;		/* error value for AIO */
++	int			num_io_pages;
++	struct ext4_io_page	*pages[MAX_IO_PAGES];
+ } ext4_io_end_t;
+ 
++struct ext4_io_submit {
++	int			io_op;
++	struct bio		*io_bio;
++	ext4_io_end_t		*io_end;
++	struct ext4_io_page	*io_page;
++	sector_t		io_next_block;
++};
++
+ /*
+  * Special inodes numbers
+  */
+@@ -2044,6 +2067,17 @@ extern int ext4_move_extents(struct file *o_filp, struct file *d_filp,
+ 			     __u64 start_orig, __u64 start_donor,
+ 			     __u64 len, __u64 *moved_len);
+ 
++/* page-io.c */
++extern int __init init_ext4_pageio(void);
++extern void exit_ext4_pageio(void);
++extern void ext4_free_io_end(ext4_io_end_t *io);
++extern ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags);
++extern int ext4_end_io_nolock(ext4_io_end_t *io);
++extern void ext4_io_submit(struct ext4_io_submit *io);
++extern int ext4_bio_write_page(struct ext4_io_submit *io,
++			       struct page *page,
++			       int len,
++			       struct writeback_control *wbc);
+ 
+ /* BH_Uninit flag: blocks are allocated but uninitialized on disk */
+ enum ext4_state_bits {
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index a0e623055955..a1e20c8c4e0c 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -3202,7 +3202,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
+ 		 * completed
+ 		 */
+ 		if (io)
+-			io->flag = EXT4_IO_UNWRITTEN;
++			io->flag = EXT4_IO_END_UNWRITTEN;
+ 		else
+ 			ext4_set_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN);
+ 		if (ext4_should_dioread_nolock(inode))
+@@ -3494,7 +3494,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 		 */
+ 		if ((flags & EXT4_GET_BLOCKS_PRE_IO)) {
+ 			if (io)
+-				io->flag = EXT4_IO_UNWRITTEN;
++				io->flag = EXT4_IO_END_UNWRITTEN;
+ 			else
+ 				ext4_set_inode_state(inode,
+ 						     EXT4_STATE_DIO_UNWRITTEN);
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index c65d647378f9..58604fe11f4f 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2016,8 +2016,10 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd,
+ 	struct buffer_head *bh, *page_bufs = NULL;
+ 	int journal_data = ext4_should_journal_data(inode);
+ 	sector_t pblock = 0, cur_logical = 0;
++	struct ext4_io_submit io_submit;
+ 
+ 	BUG_ON(mpd->next_page <= mpd->first_page);
++	memset(&io_submit, 0, sizeof(io_submit));
+ 	/*
+ 	 * We need to start from the first_page to the next_page - 1
+ 	 * to make sure we also write the mapped dirty buffer_heads.
+@@ -2109,16 +2111,16 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd,
+ 				/* mark the buffer_heads as dirty & uptodate */
+ 				block_commit_write(page, 0, len);
+ 
+-			if (journal_data && PageChecked(page))
++			/*
++			 * Delalloc doesn't support data journalling,
++			 * but eventually maybe we'll lift this
++			 * restriction.
++			 */
++			if (unlikely(journal_data && PageChecked(page)))
+ 				err = __ext4_journalled_writepage(page, len);
+-			else if (buffer_uninit(page_bufs)) {
+-				ext4_set_bh_endio(page_bufs, inode);
+-				err = block_write_full_page_endio(page,
+-					noalloc_get_block_write,
+-					mpd->wbc, ext4_end_io_buffer_write);
+-			} else
+-				err = block_write_full_page(page,
+-					    noalloc_get_block_write, mpd->wbc);
++			else
++				err = ext4_bio_write_page(&io_submit, page,
++							  len, mpd->wbc);
+ 
+ 			if (!err)
+ 				mpd->pages_written++;
+@@ -2131,6 +2133,7 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd,
+ 		}
+ 		pagevec_release(&pvec);
+ 	}
++	ext4_io_submit(&io_submit);
+ 	return ret;
+ }
+ 
+@@ -3426,15 +3429,6 @@ ext4_readpages(struct file *file, struct address_space *mapping,
+ 	return mpage_readpages(mapping, pages, nr_pages, ext4_get_block);
+ }
+ 
+-static void ext4_free_io_end(ext4_io_end_t *io)
+-{
+-	BUG_ON(!io);
+-	if (io->page)
+-		put_page(io->page);
+-	iput(io->inode);
+-	kfree(io);
+-}
+-
+ static void ext4_invalidatepage_free_endio(struct page *page, unsigned long offset)
+ {
+ 	struct buffer_head *head, *bh;
+@@ -3639,68 +3633,6 @@ static void dump_completed_IO(struct inode * inode)
+ #endif
+ }
+ 
+-/*
+- * check a range of space and convert unwritten extents to written.
+- */
+-static int ext4_end_io_nolock(ext4_io_end_t *io)
+-{
+-	struct inode *inode = io->inode;
+-	loff_t offset = io->offset;
+-	ssize_t size = io->size;
+-	int ret = 0;
+-
+-	ext4_debug("ext4_end_io_nolock: io 0x%p from inode %lu,list->next 0x%p,"
+-		   "list->prev 0x%p\n",
+-	           io, inode->i_ino, io->list.next, io->list.prev);
+-
+-	if (list_empty(&io->list))
+-		return ret;
+-
+-	if (io->flag != EXT4_IO_UNWRITTEN)
+-		return ret;
+-
+-	ret = ext4_convert_unwritten_extents(inode, offset, size);
+-	if (ret < 0) {
+-		printk(KERN_EMERG "%s: failed to convert unwritten"
+-			"extents to written extents, error is %d"
+-			" io is still on inode %lu aio dio list\n",
+-                       __func__, ret, inode->i_ino);
+-		return ret;
+-	}
+-
+-	if (io->iocb)
+-		aio_complete(io->iocb, io->result, 0);
+-	/* clear the DIO AIO unwritten flag */
+-	io->flag = 0;
+-	return ret;
+-}
+-
+-/*
+- * work on completed aio dio IO, to convert unwritten extents to extents
+- */
+-static void ext4_end_io_work(struct work_struct *work)
+-{
+-	ext4_io_end_t		*io = container_of(work, ext4_io_end_t, work);
+-	struct inode		*inode = io->inode;
+-	struct ext4_inode_info	*ei = EXT4_I(inode);
+-	unsigned long		flags;
+-	int			ret;
+-
+-	mutex_lock(&inode->i_mutex);
+-	ret = ext4_end_io_nolock(io);
+-	if (ret < 0) {
+-		mutex_unlock(&inode->i_mutex);
+-		return;
+-	}
+-
+-	spin_lock_irqsave(&ei->i_completed_io_lock, flags);
+-	if (!list_empty(&io->list))
+-		list_del_init(&io->list);
+-	spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
+-	mutex_unlock(&inode->i_mutex);
+-	ext4_free_io_end(io);
+-}
+-
+ /*
+  * This function is called from ext4_sync_file().
+  *
+@@ -3756,28 +3688,6 @@ int flush_completed_IO(struct inode *inode)
+ 	return (ret2 < 0) ? ret2 : 0;
+ }
+ 
+-static ext4_io_end_t *ext4_init_io_end (struct inode *inode, gfp_t flags)
+-{
+-	ext4_io_end_t *io = NULL;
+-
+-	io = kmalloc(sizeof(*io), flags);
+-
+-	if (io) {
+-		igrab(inode);
+-		io->inode = inode;
+-		io->flag = 0;
+-		io->offset = 0;
+-		io->size = 0;
+-		io->page = NULL;
+-		io->iocb = NULL;
+-		io->result = 0;
+-		INIT_WORK(&io->work, ext4_end_io_work);
+-		INIT_LIST_HEAD(&io->list);
+-	}
+-
+-	return io;
+-}
+-
+ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
+ 			    ssize_t size, void *private, int ret,
+ 			    bool is_async)
+@@ -3797,7 +3707,7 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
+ 		  size);
+ 
+ 	/* if not aio dio with unwritten extents, just free io and return */
+-	if (io_end->flag != EXT4_IO_UNWRITTEN){
++	if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) {
+ 		ext4_free_io_end(io_end);
+ 		iocb->private = NULL;
+ out:
+@@ -3842,7 +3752,7 @@ static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate)
+ 		goto out;
+ 	}
+ 
+-	io_end->flag = EXT4_IO_UNWRITTEN;
++	io_end->flag = EXT4_IO_END_UNWRITTEN;
+ 	inode = io_end->inode;
+ 
+ 	/* Add the io_end to per-inode completed io list*/
+diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
+new file mode 100644
+index 000000000000..b972ca50f851
+--- /dev/null
++++ b/fs/ext4/page-io.c
+@@ -0,0 +1,430 @@
++/*
++ * linux/fs/ext4/page-io.c
++ *
++ * This contains the new page_io functions for ext4
++ *
++ * Written by Theodore Ts'o, 2010.
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include "ext4_jbd2.h"
++#include "xattr.h"
++#include "acl.h"
++#include "ext4_extents.h"
++
++static struct kmem_cache *io_page_cachep, *io_end_cachep;
++
++int __init init_ext4_pageio(void)
++{
++	io_page_cachep = KMEM_CACHE(ext4_io_page, SLAB_RECLAIM_ACCOUNT);
++	if (io_page_cachep == NULL)
++		return -ENOMEM;
++	io_end_cachep = KMEM_CACHE(ext4_io_end, SLAB_RECLAIM_ACCOUNT);
++	if (io_page_cachep == NULL) {
++		kmem_cache_destroy(io_page_cachep);
++		return -ENOMEM;
++	}
++
++	return 0;
++}
++
++void exit_ext4_pageio(void)
++{
++	kmem_cache_destroy(io_end_cachep);
++	kmem_cache_destroy(io_page_cachep);
++}
++
++void ext4_free_io_end(ext4_io_end_t *io)
++{
++	int i;
++
++	BUG_ON(!io);
++	if (io->page)
++		put_page(io->page);
++	for (i = 0; i < io->num_io_pages; i++) {
++		if (--io->pages[i]->p_count == 0) {
++			struct page *page = io->pages[i]->p_page;
++
++			end_page_writeback(page);
++			put_page(page);
++			kmem_cache_free(io_page_cachep, io->pages[i]);
++		}
++	}
++	io->num_io_pages = 0;
++	iput(io->inode);
++	kmem_cache_free(io_end_cachep, io);
++}
++
++/*
++ * check a range of space and convert unwritten extents to written.
++ */
++int ext4_end_io_nolock(ext4_io_end_t *io)
++{
++	struct inode *inode = io->inode;
++	loff_t offset = io->offset;
++	ssize_t size = io->size;
++	int ret = 0;
++
++	ext4_debug("ext4_end_io_nolock: io 0x%p from inode %lu,list->next 0x%p,"
++		   "list->prev 0x%p\n",
++		   io, inode->i_ino, io->list.next, io->list.prev);
++
++	if (list_empty(&io->list))
++		return ret;
++
++	if (!(io->flag & EXT4_IO_END_UNWRITTEN))
++		return ret;
++
++	ret = ext4_convert_unwritten_extents(inode, offset, size);
++	if (ret < 0) {
++		printk(KERN_EMERG "%s: failed to convert unwritten "
++			"extents to written extents, error is %d "
++			"io is still on inode %lu aio dio list\n",
++		       __func__, ret, inode->i_ino);
++		return ret;
++	}
++
++	if (io->iocb)
++		aio_complete(io->iocb, io->result, 0);
++	/* clear the DIO AIO unwritten flag */
++	io->flag &= ~EXT4_IO_END_UNWRITTEN;
++	return ret;
++}
++
++/*
++ * work on completed aio dio IO, to convert unwritten extents to extents
++ */
++static void ext4_end_io_work(struct work_struct *work)
++{
++	ext4_io_end_t		*io = container_of(work, ext4_io_end_t, work);
++	struct inode		*inode = io->inode;
++	struct ext4_inode_info	*ei = EXT4_I(inode);
++	unsigned long		flags;
++	int			ret;
++
++	mutex_lock(&inode->i_mutex);
++	ret = ext4_end_io_nolock(io);
++	if (ret < 0) {
++		mutex_unlock(&inode->i_mutex);
++		return;
++	}
++
++	spin_lock_irqsave(&ei->i_completed_io_lock, flags);
++	if (!list_empty(&io->list))
++		list_del_init(&io->list);
++	spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
++	mutex_unlock(&inode->i_mutex);
++	ext4_free_io_end(io);
++}
++
++ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags)
++{
++	ext4_io_end_t *io = NULL;
++
++	io = kmem_cache_alloc(io_end_cachep, flags);
++	if (io) {
++		memset(io, 0, sizeof(*io));
++		io->inode = igrab(inode);
++		BUG_ON(!io->inode);
++		INIT_WORK(&io->work, ext4_end_io_work);
++		INIT_LIST_HEAD(&io->list);
++	}
++	return io;
++}
++
++/*
++ * Print an buffer I/O error compatible with the fs/buffer.c.  This
++ * provides compatibility with dmesg scrapers that look for a specific
++ * buffer I/O error message.  We really need a unified error reporting
++ * structure to userspace ala Digital Unix's uerf system, but it's
++ * probably not going to happen in my lifetime, due to LKML politics...
++ */
++static void buffer_io_error(struct buffer_head *bh)
++{
++	char b[BDEVNAME_SIZE];
++	printk(KERN_ERR "Buffer I/O error on device %s, logical block %llu\n",
++			bdevname(bh->b_bdev, b),
++			(unsigned long long)bh->b_blocknr);
++}
++
++static void ext4_end_bio(struct bio *bio, int error)
++{
++	ext4_io_end_t *io_end = bio->bi_private;
++	struct workqueue_struct *wq;
++	struct inode *inode;
++	unsigned long flags;
++	ext4_fsblk_t err_block;
++	int i;
++
++	BUG_ON(!io_end);
++	inode = io_end->inode;
++	bio->bi_private = NULL;
++	bio->bi_end_io = NULL;
++	if (test_bit(BIO_UPTODATE, &bio->bi_flags))
++		error = 0;
++	err_block = bio->bi_sector >> (inode->i_blkbits - 9);
++	bio_put(bio);
++
++	if (!(inode->i_sb->s_flags & MS_ACTIVE)) {
++		pr_err("sb umounted, discard end_io request for inode %lu\n",
++			io_end->inode->i_ino);
++		ext4_free_io_end(io_end);
++		return;
++	}
++
++	if (error) {
++		io_end->flag |= EXT4_IO_END_ERROR;
++		ext4_warning(inode->i_sb, "I/O error writing to inode %lu "
++			     "(offset %llu size %ld starting block %llu)",
++			     inode->i_ino,
++			     (unsigned long long) io_end->offset,
++			     (long) io_end->size,
++			     (unsigned long long) err_block);
++	}
++
++	for (i = 0; i < io_end->num_io_pages; i++) {
++		struct page *page = io_end->pages[i]->p_page;
++		struct buffer_head *bh, *head;
++		int partial_write = 0;
++
++		head = page_buffers(page);
++		if (error)
++			SetPageError(page);
++		BUG_ON(!head);
++		if (head->b_size == PAGE_CACHE_SIZE)
++			clear_buffer_dirty(head);
++		else {
++			loff_t offset;
++			loff_t io_end_offset = io_end->offset + io_end->size;
++
++			offset = (sector_t) page->index << PAGE_CACHE_SHIFT;
++			bh = head;
++			do {
++				if ((offset >= io_end->offset) &&
++				    (offset+bh->b_size <= io_end_offset)) {
++					if (error)
++						buffer_io_error(bh);
++
++					clear_buffer_dirty(bh);
++				}
++				if (buffer_delay(bh))
++					partial_write = 1;
++				else if (!buffer_mapped(bh))
++					clear_buffer_dirty(bh);
++				else if (buffer_dirty(bh))
++					partial_write = 1;
++				offset += bh->b_size;
++				bh = bh->b_this_page;
++			} while (bh != head);
++		}
++
++		if (--io_end->pages[i]->p_count == 0) {
++			struct page *page = io_end->pages[i]->p_page;
++
++			end_page_writeback(page);
++			put_page(page);
++			kmem_cache_free(io_page_cachep, io_end->pages[i]);
++		}
++
++		/*
++		 * If this is a partial write which happened to make
++		 * all buffers uptodate then we can optimize away a
++		 * bogus readpage() for the next read(). Here we
++		 * 'discover' whether the page went uptodate as a
++		 * result of this (potentially partial) write.
++		 */
++		if (!partial_write)
++			SetPageUptodate(page);
++	}
++
++	io_end->num_io_pages = 0;
++
++	/* Add the io_end to per-inode completed io list*/
++	spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags);
++	list_add_tail(&io_end->list, &EXT4_I(inode)->i_completed_io_list);
++	spin_unlock_irqrestore(&EXT4_I(inode)->i_completed_io_lock, flags);
++
++	wq = EXT4_SB(inode->i_sb)->dio_unwritten_wq;
++	/* queue the work to convert unwritten extents to written */
++	queue_work(wq, &io_end->work);
++}
++
++void ext4_io_submit(struct ext4_io_submit *io)
++{
++	struct bio *bio = io->io_bio;
++
++	if (bio) {
++		bio_get(io->io_bio);
++		submit_bio(io->io_op, io->io_bio);
++		BUG_ON(bio_flagged(io->io_bio, BIO_EOPNOTSUPP));
++		bio_put(io->io_bio);
++	}
++	io->io_bio = 0;
++	io->io_op = 0;
++	io->io_end = 0;
++}
++
++static int io_submit_init(struct ext4_io_submit *io,
++			  struct inode *inode,
++			  struct writeback_control *wbc,
++			  struct buffer_head *bh)
++{
++	ext4_io_end_t *io_end;
++	struct page *page = bh->b_page;
++	int nvecs = bio_get_nr_vecs(bh->b_bdev);
++	struct bio *bio;
++
++	io_end = ext4_init_io_end(inode, GFP_NOFS);
++	if (!io_end)
++		return -ENOMEM;
++	do {
++		bio = bio_alloc(GFP_NOIO, nvecs);
++		nvecs >>= 1;
++	} while (bio == NULL);
++
++	bio->bi_sector = bh->b_blocknr * (bh->b_size >> 9);
++	bio->bi_bdev = bh->b_bdev;
++	bio->bi_private = io->io_end = io_end;
++	bio->bi_end_io = ext4_end_bio;
++
++	io_end->inode = inode;
++	io_end->offset = (page->index << PAGE_CACHE_SHIFT) + bh_offset(bh);
++
++	io->io_bio = bio;
++	io->io_op = (wbc->sync_mode == WB_SYNC_ALL ?
++			WRITE_SYNC_PLUG : WRITE);
++	io->io_next_block = bh->b_blocknr;
++	return 0;
++}
++
++static int io_submit_add_bh(struct ext4_io_submit *io,
++			    struct ext4_io_page *io_page,
++			    struct inode *inode,
++			    struct writeback_control *wbc,
++			    struct buffer_head *bh)
++{
++	ext4_io_end_t *io_end;
++	int ret;
++
++	if (buffer_new(bh)) {
++		clear_buffer_new(bh);
++		unmap_underlying_metadata(bh->b_bdev, bh->b_blocknr);
++	}
++
++	if (!buffer_mapped(bh) || buffer_delay(bh)) {
++		if (!buffer_mapped(bh))
++			clear_buffer_dirty(bh);
++		if (io->io_bio)
++			ext4_io_submit(io);
++		return 0;
++	}
++
++	if (io->io_bio && bh->b_blocknr != io->io_next_block) {
++submit_and_retry:
++		ext4_io_submit(io);
++	}
++	if (io->io_bio == NULL) {
++		ret = io_submit_init(io, inode, wbc, bh);
++		if (ret)
++			return ret;
++	}
++	io_end = io->io_end;
++	if ((io_end->num_io_pages >= MAX_IO_PAGES) &&
++	    (io_end->pages[io_end->num_io_pages-1] != io_page))
++		goto submit_and_retry;
++	if (buffer_uninit(bh))
++		io->io_end->flag |= EXT4_IO_END_UNWRITTEN;
++	io->io_end->size += bh->b_size;
++	io->io_next_block++;
++	ret = bio_add_page(io->io_bio, bh->b_page, bh->b_size, bh_offset(bh));
++	if (ret != bh->b_size)
++		goto submit_and_retry;
++	if ((io_end->num_io_pages == 0) ||
++	    (io_end->pages[io_end->num_io_pages-1] != io_page)) {
++		io_end->pages[io_end->num_io_pages++] = io_page;
++		io_page->p_count++;
++	}
++	return 0;
++}
++
++int ext4_bio_write_page(struct ext4_io_submit *io,
++			struct page *page,
++			int len,
++			struct writeback_control *wbc)
++{
++	struct inode *inode = page->mapping->host;
++	unsigned block_start, block_end, blocksize;
++	struct ext4_io_page *io_page;
++	struct buffer_head *bh, *head;
++	int ret = 0;
++
++	blocksize = 1 << inode->i_blkbits;
++
++	BUG_ON(PageWriteback(page));
++	set_page_writeback(page);
++	ClearPageError(page);
++
++	io_page = kmem_cache_alloc(io_page_cachep, GFP_NOFS);
++	if (!io_page) {
++		set_page_dirty(page);
++		unlock_page(page);
++		return -ENOMEM;
++	}
++	io_page->p_page = page;
++	io_page->p_count = 0;
++	get_page(page);
++
++	for (bh = head = page_buffers(page), block_start = 0;
++	     bh != head || !block_start;
++	     block_start = block_end, bh = bh->b_this_page) {
++		block_end = block_start + blocksize;
++		if (block_start >= len) {
++			clear_buffer_dirty(bh);
++			set_buffer_uptodate(bh);
++			continue;
++		}
++		ret = io_submit_add_bh(io, io_page, inode, wbc, bh);
++		if (ret) {
++			/*
++			 * We only get here on ENOMEM.  Not much else
++			 * we can do but mark the page as dirty, and
++			 * better luck next time.
++			 */
++			set_page_dirty(page);
++			break;
++		}
++	}
++	unlock_page(page);
++	/*
++	 * If the page was truncated before we could do the writeback,
++	 * or we had a memory allocation error while trying to write
++	 * the first buffer head, we won't have submitted any pages for
++	 * I/O.  In that case we need to make sure we've cleared the
++	 * PageWriteback bit from the page to prevent the system from
++	 * wedging later on.
++	 */
++	if (io_page->p_count == 0) {
++		put_page(page);
++		end_page_writeback(page);
++		kmem_cache_free(io_page_cachep, io_page);
++	}
++	return ret;
++}
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 8a24e9be7cb0..e13b3c3534d7 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4769,9 +4769,12 @@ static int __init init_ext4_fs(void)
+ 	int err;
+ 
+ 	ext4_check_flag_values();
+-	err = init_ext4_system_zone();
++	err = init_ext4_pageio();
+ 	if (err)
+ 		return err;
++	err = init_ext4_system_zone();
++	if (err)
++		goto out5;
+ 	ext4_kset = kset_create_and_add("ext4", NULL, fs_kobj);
+ 	if (!ext4_kset)
+ 		goto out4;
+@@ -4812,6 +4815,8 @@ static int __init init_ext4_fs(void)
+ 	kset_unregister(ext4_kset);
+ out4:
+ 	exit_ext4_system_zone();
++out5:
++	exit_ext4_pageio();
+ 	return err;
+ }
+ 
+@@ -4827,6 +4832,7 @@ static void __exit exit_ext4_fs(void)
+ 	remove_proc_entry("fs/ext4", NULL);
+ 	kset_unregister(ext4_kset);
+ 	exit_ext4_system_zone();
++	exit_ext4_pageio();
+ }
+ 
+ MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");

commit 1de3e3df917459422cb2aecac440febc8879d410
+Author: Theodore Ts'o 
+Date:   Wed Oct 27 21:30:10 2010 -0400
+
+    ext4: move mpage_put_bnr_to_bhs()'s functionality to mpage_da_submit_io()
+    
+    This massively simplifies the ext4_da_writepages() code path by
+    completely removing mpage_put_bnr_bhs(), which is almost 100 lines of
+    code iterating over a set of pages using pagevec_lookup(), and folds
+    that functionality into mpage_da_submit_io()'s existing
+    pagevec_lookup() loop.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 5da6cfcecd83..c65d647378f9 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2003,7 +2003,8 @@ static void ext4_da_page_release_reservation(struct page *page,
+  *
+  * As pages are already locked by write_cache_pages(), we can't use it
+  */
+-static int mpage_da_submit_io(struct mpage_da_data *mpd)
++static int mpage_da_submit_io(struct mpage_da_data *mpd,
++			      struct ext4_map_blocks *map)
+ {
+ 	struct pagevec pvec;
+ 	unsigned long index, end;
+@@ -2014,6 +2015,7 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd)
+ 	unsigned int len, block_start;
+ 	struct buffer_head *bh, *page_bufs = NULL;
+ 	int journal_data = ext4_should_journal_data(inode);
++	sector_t pblock = 0, cur_logical = 0;
+ 
+ 	BUG_ON(mpd->next_page <= mpd->first_page);
+ 	/*
+@@ -2031,7 +2033,7 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd)
+ 		if (nr_pages == 0)
+ 			break;
+ 		for (i = 0; i < nr_pages; i++) {
+-			int commit_write = 0;
++			int commit_write = 0, redirty_page = 0;
+ 			struct page *page = pvec.pages[i];
+ 
+ 			index = page->index;
+@@ -2042,6 +2044,12 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd)
+ 				len = size & ~PAGE_CACHE_MASK;
+ 			else
+ 				len = PAGE_CACHE_SIZE;
++			if (map) {
++				cur_logical = index << (PAGE_CACHE_SHIFT -
++							inode->i_blkbits);
++				pblock = map->m_pblk + (cur_logical -
++							map->m_lblk);
++			}
+ 			index++;
+ 
+ 			BUG_ON(!PageLocked(page));
+@@ -2068,13 +2076,34 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd)
+ 			bh = page_bufs = page_buffers(page);
+ 			block_start = 0;
+ 			do {
+-				/* redirty page if block allocation undone */
+-				if (!bh || buffer_delay(bh) ||
+-				    buffer_unwritten(bh))
++				if (!bh)
+ 					goto redirty_page;
++				if (map && (cur_logical >= map->m_lblk) &&
++				    (cur_logical <= (map->m_lblk +
++						     (map->m_len - 1)))) {
++					if (buffer_delay(bh)) {
++						clear_buffer_delay(bh);
++						bh->b_blocknr = pblock;
++					}
++					if (buffer_unwritten(bh) ||
++					    buffer_mapped(bh))
++						BUG_ON(bh->b_blocknr != pblock);
++					if (map->m_flags & EXT4_MAP_UNINIT)
++						set_buffer_uninit(bh);
++					clear_buffer_unwritten(bh);
++				}
++
++				/* redirty page if block allocation undone */
++				if (buffer_delay(bh) || buffer_unwritten(bh))
++					redirty_page = 1;
+ 				bh = bh->b_this_page;
+ 				block_start += bh->b_size;
+-			} while ((bh != page_bufs) && (block_start < len));
++				cur_logical++;
++				pblock++;
++			} while (bh != page_bufs);
++
++			if (redirty_page)
++				goto redirty_page;
+ 
+ 			if (commit_write)
+ 				/* mark the buffer_heads as dirty & uptodate */
+@@ -2105,91 +2134,6 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd)
+ 	return ret;
+ }
+ 
+-/*
+- * mpage_put_bnr_to_bhs - walk blocks and assign them actual numbers
+- *
+- * the function goes through all passed space and put actual disk
+- * block numbers into buffer heads, dropping BH_Delay and BH_Unwritten
+- */
+-static void mpage_put_bnr_to_bhs(struct mpage_da_data *mpd,
+-				 struct ext4_map_blocks *map)
+-{
+-	struct inode *inode = mpd->inode;
+-	struct address_space *mapping = inode->i_mapping;
+-	int blocks = map->m_len;
+-	sector_t pblock = map->m_pblk, cur_logical;
+-	struct buffer_head *head, *bh;
+-	pgoff_t index, end;
+-	struct pagevec pvec;
+-	int nr_pages, i;
+-
+-	index = map->m_lblk >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
+-	end = (map->m_lblk + blocks - 1) >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
+-	cur_logical = index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
+-
+-	pagevec_init(&pvec, 0);
+-
+-	while (index <= end) {
+-		/* XXX: optimize tail */
+-		nr_pages = pagevec_lookup(&pvec, mapping, index, PAGEVEC_SIZE);
+-		if (nr_pages == 0)
+-			break;
+-		for (i = 0; i < nr_pages; i++) {
+-			struct page *page = pvec.pages[i];
+-
+-			index = page->index;
+-			if (index > end)
+-				break;
+-			index++;
+-
+-			BUG_ON(!PageLocked(page));
+-			BUG_ON(PageWriteback(page));
+-			BUG_ON(!page_has_buffers(page));
+-
+-			bh = page_buffers(page);
+-			head = bh;
+-
+-			/* skip blocks out of the range */
+-			do {
+-				if (cur_logical >= map->m_lblk)
+-					break;
+-				cur_logical++;
+-			} while ((bh = bh->b_this_page) != head);
+-
+-			do {
+-				if (cur_logical > map->m_lblk + (blocks - 1))
+-					break;
+-
+-				if (buffer_delay(bh) || buffer_unwritten(bh)) {
+-
+-					BUG_ON(bh->b_bdev != inode->i_sb->s_bdev);
+-
+-					if (buffer_delay(bh)) {
+-						clear_buffer_delay(bh);
+-						bh->b_blocknr = pblock;
+-					} else {
+-						/*
+-						 * unwritten already should have
+-						 * blocknr assigned. Verify that
+-						 */
+-						clear_buffer_unwritten(bh);
+-						BUG_ON(bh->b_blocknr != pblock);
+-					}
+-
+-				} else if (buffer_mapped(bh))
+-					BUG_ON(bh->b_blocknr != pblock);
+-
+-				if (map->m_flags & EXT4_MAP_UNINIT)
+-					set_buffer_uninit(bh);
+-				cur_logical++;
+-				pblock++;
+-			} while ((bh = bh->b_this_page) != head);
+-		}
+-		pagevec_release(&pvec);
+-	}
+-}
+-
+-
+ static void ext4_da_block_invalidatepages(struct mpage_da_data *mpd,
+ 					sector_t logical, long blk_cnt)
+ {
+@@ -2252,7 +2196,7 @@ static void ext4_print_free_blocks(struct inode *inode)
+ static void mpage_da_map_and_submit(struct mpage_da_data *mpd)
+ {
+ 	int err, blks, get_blocks_flags;
+-	struct ext4_map_blocks map;
++	struct ext4_map_blocks map, *mapp = NULL;
+ 	sector_t next = mpd->b_blocknr;
+ 	unsigned max_blocks = mpd->b_size >> mpd->inode->i_blkbits;
+ 	loff_t disksize = EXT4_I(mpd->inode)->i_disksize;
+@@ -2343,6 +2287,7 @@ static void mpage_da_map_and_submit(struct mpage_da_data *mpd)
+ 	}
+ 	BUG_ON(blks == 0);
+ 
++	mapp = ↦
+ 	if (map.m_flags & EXT4_MAP_NEW) {
+ 		struct block_device *bdev = mpd->inode->i_sb->s_bdev;
+ 		int i;
+@@ -2351,14 +2296,6 @@ static void mpage_da_map_and_submit(struct mpage_da_data *mpd)
+ 			unmap_underlying_metadata(bdev, map.m_pblk + i);
+ 	}
+ 
+-	/*
+-	 * If blocks are delayed marked, we need to
+-	 * put actual blocknr and drop delayed bit
+-	 */
+-	if ((mpd->b_state & (1 << BH_Delay)) ||
+-	    (mpd->b_state & (1 << BH_Unwritten)))
+-		mpage_put_bnr_to_bhs(mpd, &map);
+-
+ 	if (ext4_should_order_data(mpd->inode)) {
+ 		err = ext4_jbd2_file_inode(handle, mpd->inode);
+ 		if (err)
+@@ -2382,7 +2319,7 @@ static void mpage_da_map_and_submit(struct mpage_da_data *mpd)
+ 	}
+ 
+ submit_io:
+-	mpage_da_submit_io(mpd);
++	mpage_da_submit_io(mpd, mapp);
+ 	mpd->io_done = 1;
+ }
+ 

commit 3ecdb3a193a5f224f084c04a63aa28cdccf4d7d0
+Author: Theodore Ts'o 
+Date:   Wed Oct 27 21:30:10 2010 -0400
+
+    ext4: inline walk_page_buffers() into mpage_da_submit_io
+    
+    Expand the call:
+    
+      if (walk_page_buffers(NULL, page_bufs, 0, len, NULL,
+                            ext4_bh_delay_or_unwritten))
+            goto redirty_page
+    
+    into mpage_da_submit_io().
+    
+    This will allow us to merge in mpage_put_bnr_to_bhs() in the next
+    patch.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 97a0c35219ae..5da6cfcecd83 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2011,8 +2011,8 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd)
+ 	struct inode *inode = mpd->inode;
+ 	struct address_space *mapping = inode->i_mapping;
+ 	loff_t size = i_size_read(inode);
+-	unsigned int len;
+-	struct buffer_head *page_bufs = NULL;
++	unsigned int len, block_start;
++	struct buffer_head *bh, *page_bufs = NULL;
+ 	int journal_data = ext4_should_journal_data(inode);
+ 
+ 	BUG_ON(mpd->next_page <= mpd->first_page);
+@@ -2064,15 +2064,17 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd)
+ 				}
+ 				commit_write = 1;
+ 			}
+-			page_bufs = page_buffers(page);
+-			if (walk_page_buffers(NULL, page_bufs, 0, len, NULL,
+-					      ext4_bh_delay_or_unwritten)) {
+-				/*
+-				 * We couldn't do block allocation for
+-				 * some reason.
+-				 */
+-				goto redirty_page;
+-			}
++
++			bh = page_bufs = page_buffers(page);
++			block_start = 0;
++			do {
++				/* redirty page if block allocation undone */
++				if (!bh || buffer_delay(bh) ||
++				    buffer_unwritten(bh))
++					goto redirty_page;
++				bh = bh->b_this_page;
++				block_start += bh->b_size;
++			} while ((bh != page_bufs) && (block_start < len));
+ 
+ 			if (commit_write)
+ 				/* mark the buffer_heads as dirty & uptodate */

commit cb20d5188366f04d96d2e07b1240cc92170ade40
+Author: Theodore Ts'o 
+Date:   Wed Oct 27 21:30:09 2010 -0400
+
+    ext4: inline ext4_writepage() into mpage_da_submit_io()
+    
+    As a prepratory step to switching to bio_submit, inline
+    ext4_writepage() into mpage_da_submit() and then simplify things a
+    bit.  This makes it clearer what mpage_da_submit needs to do.
+    
+    Also, move the ClearPageChecked(page) call into
+    __ext4_journalled_writepage(), as a minor bit of cleanup refactoring.
+    
+    This also allows us to pull i_size_read() and
+    ext4_should_journal_data() out of the loop, which should be a very
+    minor CPU savings.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index a08ec795995f..97a0c35219ae 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -60,7 +60,12 @@ static inline int ext4_begin_ordered_truncate(struct inode *inode,
+ }
+ 
+ static void ext4_invalidatepage(struct page *page, unsigned long offset);
+-static int ext4_writepage(struct page *page, struct writeback_control *wbc);
++static int noalloc_get_block_write(struct inode *inode, sector_t iblock,
++				   struct buffer_head *bh_result, int create);
++static int ext4_set_bh_endio(struct buffer_head *bh, struct inode *inode);
++static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate);
++static int __ext4_journalled_writepage(struct page *page, unsigned int len);
++static int ext4_bh_delay_or_unwritten(handle_t *handle, struct buffer_head *bh);
+ 
+ /*
+  * Test whether an inode is a fast symlink.
+@@ -2000,12 +2005,15 @@ static void ext4_da_page_release_reservation(struct page *page,
+  */
+ static int mpage_da_submit_io(struct mpage_da_data *mpd)
+ {
+-	long pages_skipped;
+ 	struct pagevec pvec;
+ 	unsigned long index, end;
+ 	int ret = 0, err, nr_pages, i;
+ 	struct inode *inode = mpd->inode;
+ 	struct address_space *mapping = inode->i_mapping;
++	loff_t size = i_size_read(inode);
++	unsigned int len;
++	struct buffer_head *page_bufs = NULL;
++	int journal_data = ext4_should_journal_data(inode);
+ 
+ 	BUG_ON(mpd->next_page <= mpd->first_page);
+ 	/*
+@@ -2023,28 +2031,69 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd)
+ 		if (nr_pages == 0)
+ 			break;
+ 		for (i = 0; i < nr_pages; i++) {
++			int commit_write = 0;
+ 			struct page *page = pvec.pages[i];
+ 
+ 			index = page->index;
+ 			if (index > end)
+ 				break;
++
++			if (index == size >> PAGE_CACHE_SHIFT)
++				len = size & ~PAGE_CACHE_MASK;
++			else
++				len = PAGE_CACHE_SIZE;
+ 			index++;
+ 
+ 			BUG_ON(!PageLocked(page));
+ 			BUG_ON(PageWriteback(page));
+ 
+-			pages_skipped = mpd->wbc->pages_skipped;
+-			err = ext4_writepage(page, mpd->wbc);
+-			if (!err && (pages_skipped == mpd->wbc->pages_skipped))
++			/*
++			 * If the page does not have buffers (for
++			 * whatever reason), try to create them using
++			 * block_prepare_write.  If this fails,
++			 * redirty the page and move on.
++			 */
++			if (!page_has_buffers(page)) {
++				if (block_prepare_write(page, 0, len,
++						noalloc_get_block_write)) {
++				redirty_page:
++					redirty_page_for_writepage(mpd->wbc,
++								   page);
++					unlock_page(page);
++					continue;
++				}
++				commit_write = 1;
++			}
++			page_bufs = page_buffers(page);
++			if (walk_page_buffers(NULL, page_bufs, 0, len, NULL,
++					      ext4_bh_delay_or_unwritten)) {
+ 				/*
+-				 * have successfully written the page
+-				 * without skipping the same
++				 * We couldn't do block allocation for
++				 * some reason.
+ 				 */
++				goto redirty_page;
++			}
++
++			if (commit_write)
++				/* mark the buffer_heads as dirty & uptodate */
++				block_commit_write(page, 0, len);
++
++			if (journal_data && PageChecked(page))
++				err = __ext4_journalled_writepage(page, len);
++			else if (buffer_uninit(page_bufs)) {
++				ext4_set_bh_endio(page_bufs, inode);
++				err = block_write_full_page_endio(page,
++					noalloc_get_block_write,
++					mpd->wbc, ext4_end_io_buffer_write);
++			} else
++				err = block_write_full_page(page,
++					    noalloc_get_block_write, mpd->wbc);
++
++			if (!err)
+ 				mpd->pages_written++;
+ 			/*
+ 			 * In error case, we have to continue because
+ 			 * remaining pages are still locked
+-			 * XXX: unlock and re-dirty them?
+ 			 */
+ 			if (ret == 0)
+ 				ret = err;
+@@ -2627,6 +2676,7 @@ static int __ext4_journalled_writepage(struct page *page,
+ 	int ret = 0;
+ 	int err;
+ 
++	ClearPageChecked(page);
+ 	page_bufs = page_buffers(page);
+ 	BUG_ON(!page_bufs);
+ 	walk_page_buffers(handle, page_bufs, 0, len, NULL, bget_one);
+@@ -2749,14 +2799,12 @@ static int ext4_writepage(struct page *page,
+ 		/* now mark the buffer_heads as dirty and uptodate */
+ 		block_commit_write(page, 0, len);
+ 
+-	if (PageChecked(page) && ext4_should_journal_data(inode)) {
++	if (PageChecked(page) && ext4_should_journal_data(inode))
+ 		/*
+ 		 * It's mmapped pagecache.  Add buffers and journal it.  There
+ 		 * doesn't seem much point in redirtying the page here.
+ 		 */
+-		ClearPageChecked(page);
+ 		return __ext4_journalled_writepage(page, len);
+-	}
+ 
+ 	if (buffer_uninit(page_bufs)) {
+ 		ext4_set_bh_endio(page_bufs, inode);

commit a42afc5f56f319107e987aa6adf2f65d93d527c7
+Author: Theodore Ts'o 
+Date:   Wed Oct 27 21:30:09 2010 -0400
+
+    ext4: simplify ext4_writepage()
+    
+    The actual code in ext4_writepage() is unnecessarily convoluted.
+    Simplify it so it is easier to understand, but otherwise logically
+    equivalent.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 55961ff4efc2..a08ec795995f 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2704,7 +2704,7 @@ static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate);
+ static int ext4_writepage(struct page *page,
+ 			  struct writeback_control *wbc)
+ {
+-	int ret = 0;
++	int ret = 0, commit_write = 0;
+ 	loff_t size;
+ 	unsigned int len;
+ 	struct buffer_head *page_bufs = NULL;
+@@ -2717,60 +2717,37 @@ static int ext4_writepage(struct page *page,
+ 	else
+ 		len = PAGE_CACHE_SIZE;
+ 
+-	if (page_has_buffers(page)) {
+-		page_bufs = page_buffers(page);
+-		if (walk_page_buffers(NULL, page_bufs, 0, len, NULL,
+-					ext4_bh_delay_or_unwritten)) {
+-			/*
+-			 * We don't want to do  block allocation
+-			 * So redirty the page and return
+-			 * We may reach here when we do a journal commit
+-			 * via journal_submit_inode_data_buffers.
+-			 * If we don't have mapping block we just ignore
+-			 * them. We can also reach here via shrink_page_list
+-			 */
++	/*
++	 * If the page does not have buffers (for whatever reason),
++	 * try to create them using block_prepare_write.  If this
++	 * fails, redirty the page and move on.
++	 */
++	if (!page_buffers(page)) {
++		if (block_prepare_write(page, 0, len,
++					noalloc_get_block_write)) {
++		redirty_page:
+ 			redirty_page_for_writepage(wbc, page);
+ 			unlock_page(page);
+ 			return 0;
+ 		}
+-	} else {
++		commit_write = 1;
++	}
++	page_bufs = page_buffers(page);
++	if (walk_page_buffers(NULL, page_bufs, 0, len, NULL,
++			      ext4_bh_delay_or_unwritten)) {
+ 		/*
+-		 * The test for page_has_buffers() is subtle:
+-		 * We know the page is dirty but it lost buffers. That means
+-		 * that at some moment in time after write_begin()/write_end()
+-		 * has been called all buffers have been clean and thus they
+-		 * must have been written at least once. So they are all
+-		 * mapped and we can happily proceed with mapping them
+-		 * and writing the page.
+-		 *
+-		 * Try to initialize the buffer_heads and check whether
+-		 * all are mapped and non delay. We don't want to
+-		 * do block allocation here.
++		 * We don't want to do block allocation So redirty the
++		 * page and return We may reach here when we do a
++		 * journal commit via
++		 * journal_submit_inode_data_buffers.  If we don't
++		 * have mapping block we just ignore them. We can also
++		 * reach here via shrink_page_list
+ 		 */
+-		ret = block_prepare_write(page, 0, len,
+-					  noalloc_get_block_write);
+-		if (!ret) {
+-			page_bufs = page_buffers(page);
+-			/* check whether all are mapped and non delay */
+-			if (walk_page_buffers(NULL, page_bufs, 0, len, NULL,
+-						ext4_bh_delay_or_unwritten)) {
+-				redirty_page_for_writepage(wbc, page);
+-				unlock_page(page);
+-				return 0;
+-			}
+-		} else {
+-			/*
+-			 * We can't do block allocation here
+-			 * so just redity the page and unlock
+-			 * and return
+-			 */
+-			redirty_page_for_writepage(wbc, page);
+-			unlock_page(page);
+-			return 0;
+-		}
++		goto redirty_page;
++	}
++	if (commit_write)
+ 		/* now mark the buffer_heads as dirty and uptodate */
+ 		block_commit_write(page, 0, len);
+-	}
+ 
+ 	if (PageChecked(page) && ext4_should_journal_data(inode)) {
+ 		/*
+@@ -2781,7 +2758,7 @@ static int ext4_writepage(struct page *page,
+ 		return __ext4_journalled_writepage(page, len);
+ 	}
+ 
+-	if (page_bufs && buffer_uninit(page_bufs)) {
++	if (buffer_uninit(page_bufs)) {
+ 		ext4_set_bh_endio(page_bufs, inode);
+ 		ret = block_write_full_page_endio(page, noalloc_get_block_write,
+ 					    wbc, ext4_end_io_buffer_write);

commit 5a87b7a5da250c9be6d757758425dfeaf8ed3179
+Author: Theodore Ts'o 
+Date:   Wed Oct 27 21:30:09 2010 -0400
+
+    ext4: call mpage_da_submit_io() from mpage_da_map_blocks()
+    
+    Eventually we need to completely reorganize the ext4 writepage
+    callpath, but for now, we simplify things a little by calling
+    mpage_da_submit_io() from mpage_da_map_blocks(), since all of the
+    places where we call mpage_da_map_blocks() it is followed up by a call
+    to mpage_da_submit_io().
+    
+    We're also a wee bit better with respect to error handling, but there
+    are still a number of issues where it's not clear what the right thing
+    is to do with ext4 functions deep in the writeback codepath fails.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 670ab15e4f9a..55961ff4efc2 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -60,6 +60,7 @@ static inline int ext4_begin_ordered_truncate(struct inode *inode,
+ }
+ 
+ static void ext4_invalidatepage(struct page *page, unsigned long offset);
++static int ext4_writepage(struct page *page, struct writeback_control *wbc);
+ 
+ /*
+  * Test whether an inode is a fast symlink.
+@@ -2033,7 +2034,7 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd)
+ 			BUG_ON(PageWriteback(page));
+ 
+ 			pages_skipped = mpd->wbc->pages_skipped;
+-			err = mapping->a_ops->writepage(page, mpd->wbc);
++			err = ext4_writepage(page, mpd->wbc);
+ 			if (!err && (pages_skipped == mpd->wbc->pages_skipped))
+ 				/*
+ 				 * have successfully written the page
+@@ -2189,14 +2190,15 @@ static void ext4_print_free_blocks(struct inode *inode)
+ }
+ 
+ /*
+- * mpage_da_map_blocks - go through given space
++ * mpage_da_map_and_submit - go through given space, map them
++ *       if necessary, and then submit them for I/O
+  *
+  * @mpd - bh describing space
+  *
+  * The function skips space we know is already mapped to disk blocks.
+  *
+  */
+-static int mpage_da_map_blocks(struct mpage_da_data *mpd)
++static void mpage_da_map_and_submit(struct mpage_da_data *mpd)
+ {
+ 	int err, blks, get_blocks_flags;
+ 	struct ext4_map_blocks map;
+@@ -2206,18 +2208,14 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
+ 	handle_t *handle = NULL;
+ 
+ 	/*
+-	 * We consider only non-mapped and non-allocated blocks
++	 * If the blocks are mapped already, or we couldn't accumulate
++	 * any blocks, then proceed immediately to the submission stage.
+ 	 */
+-	if ((mpd->b_state  & (1 << BH_Mapped)) &&
+-		!(mpd->b_state & (1 << BH_Delay)) &&
+-		!(mpd->b_state & (1 << BH_Unwritten)))
+-		return 0;
+-
+-	/*
+-	 * If we didn't accumulate anything to write simply return
+-	 */
+-	if (!mpd->b_size)
+-		return 0;
++	if ((mpd->b_size == 0) ||
++	    ((mpd->b_state  & (1 << BH_Mapped)) &&
++	     !(mpd->b_state & (1 << BH_Delay)) &&
++	     !(mpd->b_state & (1 << BH_Unwritten))))
++		goto submit_io;
+ 
+ 	handle = ext4_journal_current_handle();
+ 	BUG_ON(!handle);
+@@ -2254,17 +2252,18 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
+ 
+ 		err = blks;
+ 		/*
+-		 * If get block returns with error we simply
+-		 * return. Later writepage will redirty the page and
+-		 * writepages will find the dirty page again
++		 * If get block returns EAGAIN or ENOSPC and there
++		 * appears to be free blocks we will call
++		 * ext4_writepage() for all of the pages which will
++		 * just redirty the pages.
+ 		 */
+ 		if (err == -EAGAIN)
+-			return 0;
++			goto submit_io;
+ 
+ 		if (err == -ENOSPC &&
+ 		    ext4_count_free_blocks(sb)) {
+ 			mpd->retval = err;
+-			return 0;
++			goto submit_io;
+ 		}
+ 
+ 		/*
+@@ -2289,7 +2288,7 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
+ 		/* invalidate all the pages */
+ 		ext4_da_block_invalidatepages(mpd, next,
+ 				mpd->b_size >> mpd->inode->i_blkbits);
+-		return err;
++		return;
+ 	}
+ 	BUG_ON(blks == 0);
+ 
+@@ -2312,7 +2311,8 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
+ 	if (ext4_should_order_data(mpd->inode)) {
+ 		err = ext4_jbd2_file_inode(handle, mpd->inode);
+ 		if (err)
+-			return err;
++			/* This only happens if the journal is aborted */
++			return;
+ 	}
+ 
+ 	/*
+@@ -2323,10 +2323,16 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
+ 		disksize = i_size_read(mpd->inode);
+ 	if (disksize > EXT4_I(mpd->inode)->i_disksize) {
+ 		ext4_update_i_disksize(mpd->inode, disksize);
+-		return ext4_mark_inode_dirty(handle, mpd->inode);
++		err = ext4_mark_inode_dirty(handle, mpd->inode);
++		if (err)
++			ext4_error(mpd->inode->i_sb,
++				   "Failed to mark inode %lu dirty",
++				   mpd->inode->i_ino);
+ 	}
+ 
+-	return 0;
++submit_io:
++	mpage_da_submit_io(mpd);
++	mpd->io_done = 1;
+ }
+ 
+ #define BH_FLAGS ((1 << BH_Uptodate) | (1 << BH_Mapped) | \
+@@ -2403,9 +2409,7 @@ static void mpage_add_bh_to_extent(struct mpage_da_data *mpd,
+ 	 * We couldn't merge the block to our extent, so we
+ 	 * need to flush current  extent and start new one
+ 	 */
+-	if (mpage_da_map_blocks(mpd) == 0)
+-		mpage_da_submit_io(mpd);
+-	mpd->io_done = 1;
++	mpage_da_map_and_submit(mpd);
+ 	return;
+ }
+ 
+@@ -2437,15 +2441,13 @@ static int __mpage_da_writepage(struct page *page,
+ 	if (mpd->next_page != page->index) {
+ 		/*
+ 		 * Nope, we can't. So, we map non-allocated blocks
+-		 * and start IO on them using writepage()
++		 * and start IO on them
+ 		 */
+ 		if (mpd->next_page != mpd->first_page) {
+-			if (mpage_da_map_blocks(mpd) == 0)
+-				mpage_da_submit_io(mpd);
++			mpage_da_map_and_submit(mpd);
+ 			/*
+ 			 * skip rest of the page in the page_vec
+ 			 */
+-			mpd->io_done = 1;
+ 			redirty_page_for_writepage(wbc, page);
+ 			unlock_page(page);
+ 			return MPAGE_DA_EXTENT_TAIL;
+@@ -3071,9 +3073,7 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 		 * them for I/O.
+ 		 */
+ 		if (!mpd.io_done && mpd.next_page != mpd.first_page) {
+-			if (mpage_da_map_blocks(&mpd) == 0)
+-				mpage_da_submit_io(&mpd);
+-			mpd.io_done = 1;
++			mpage_da_map_and_submit(&mpd);
+ 			ret = MPAGE_DA_EXTENT_TAIL;
+ 		}
+ 		trace_ext4_da_write_pages(inode, &mpd);

commit 16828088f9e518158edecb6cde7e6fa38e4c889b
+Author: Theodore Ts'o 
+Date:   Wed Oct 27 21:30:09 2010 -0400
+
+    ext4: use KMEM_CACHE instead of kmem_cache_create
+    
+    Also remove the SLAB_RECLAIM_ACCOUNT flag from the system zone kmem
+    cache.  This slab tends to be fairly static, so it shouldn't be marked
+    as likely to have free pages that can be reclaimed.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/block_validity.c b/fs/ext4/block_validity.c
+index 3db5084db9bd..68bab70dd139 100644
+--- a/fs/ext4/block_validity.c
++++ b/fs/ext4/block_validity.c
+@@ -31,8 +31,7 @@ static struct kmem_cache *ext4_system_zone_cachep;
+ 
+ int __init init_ext4_system_zone(void)
+ {
+-	ext4_system_zone_cachep = KMEM_CACHE(ext4_system_zone,
+-					     SLAB_RECLAIM_ACCOUNT);
++	ext4_system_zone_cachep = KMEM_CACHE(ext4_system_zone, 0);
+ 	if (ext4_system_zone_cachep == NULL)
+ 		return -ENOMEM;
+ 	return 0;
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 3f62df50f483..d732ef5a835d 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2706,26 +2706,20 @@ static void ext4_remove_debugfs_entry(void)
+ 
+ int __init init_ext4_mballoc(void)
+ {
+-	ext4_pspace_cachep =
+-		kmem_cache_create("ext4_prealloc_space",
+-				     sizeof(struct ext4_prealloc_space),
+-				     0, SLAB_RECLAIM_ACCOUNT, NULL);
++	ext4_pspace_cachep = KMEM_CACHE(ext4_prealloc_space,
++					SLAB_RECLAIM_ACCOUNT);
+ 	if (ext4_pspace_cachep == NULL)
+ 		return -ENOMEM;
+ 
+-	ext4_ac_cachep =
+-		kmem_cache_create("ext4_alloc_context",
+-				     sizeof(struct ext4_allocation_context),
+-				     0, SLAB_RECLAIM_ACCOUNT, NULL);
++	ext4_ac_cachep = KMEM_CACHE(ext4_allocation_context,
++				    SLAB_RECLAIM_ACCOUNT);
+ 	if (ext4_ac_cachep == NULL) {
+ 		kmem_cache_destroy(ext4_pspace_cachep);
+ 		return -ENOMEM;
+ 	}
+ 
+-	ext4_free_ext_cachep =
+-		kmem_cache_create("ext4_free_block_extents",
+-				     sizeof(struct ext4_free_data),
+-				     0, SLAB_RECLAIM_ACCOUNT, NULL);
++	ext4_free_ext_cachep = KMEM_CACHE(ext4_free_data,
++					  SLAB_RECLAIM_ACCOUNT);
+ 	if (ext4_free_ext_cachep == NULL) {
+ 		kmem_cache_destroy(ext4_pspace_cachep);
+ 		kmem_cache_destroy(ext4_ac_cachep);

commit 7845c0497536c566bfef08db1a38ae1ad2c25464
+Author: Theodore Ts'o 
+Date:   Wed Oct 27 21:30:08 2010 -0400
+
+    ext4: use search_dirblock() in ext4_dx_find_entry()
+    
+    Use the search_dirblock() in ext4_dx_find_entry().  It makes the code
+    easier to read, and it takes advantage of common code.  It also saves
+    100 bytes or so of text space.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Brad Spengler 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 213523803dff..86a7870babbd 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -974,39 +974,30 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q
+ 	struct super_block * sb = dir->i_sb;
+ 	struct dx_hash_info	hinfo;
+ 	struct dx_frame frames[2], *frame;
+-	struct ext4_dir_entry_2 *de, *top;
+ 	struct buffer_head *bh;
+ 	ext4_lblk_t block;
+ 	int retval;
+-	int namelen = d_name->len;
+-	const u8 *name = d_name->name;
+ 
+ 	if (!(frame = dx_probe(d_name, dir, &hinfo, frames, err)))
+ 		return NULL;
+ 	do {
+ 		block = dx_get_block(frame->at);
+-		if (!(bh = ext4_bread (NULL,dir, block, 0, err)))
++		if (!(bh = ext4_bread(NULL, dir, block, 0, err)))
+ 			goto errout;
+-		de = (struct ext4_dir_entry_2 *) bh->b_data;
+-		top = (struct ext4_dir_entry_2 *) ((char *) de + sb->s_blocksize -
+-				       EXT4_DIR_REC_LEN(0));
+-		for (; de < top; de = ext4_next_entry(de, sb->s_blocksize)) {
+-			int off = (block << EXT4_BLOCK_SIZE_BITS(sb))
+-				  + ((char *) de - bh->b_data);
+-
+-			if (!ext4_check_dir_entry(dir, de, bh, off)) {
+-				brelse(bh);
+-				*err = ERR_BAD_DX_DIR;
+-				goto errout;
+-			}
+ 
+-			if (ext4_match(namelen, name, de)) {
+-				*res_dir = de;
+-				dx_release(frames);
+-				return bh;
+-			}
++		retval = search_dirblock(bh, dir, d_name,
++					 block << EXT4_BLOCK_SIZE_BITS(sb),
++					 res_dir);
++		if (retval == 1) { 	/* Success! */
++			dx_release(frames);
++			return bh;
+ 		}
+ 		brelse(bh);
++		if (retval == -1) {
++			*err = ERR_BAD_DX_DIR;
++			goto errout;
++		}
++
+ 		/* Check to see if we should continue to search */
+ 		retval = ext4_htree_next_block(dir, hinfo.hash, frame,
+ 					       frames, NULL);

commit 8941ec8bb6443d28d5c25311870aeaa809cf1538
+Author: Theodore Ts'o 
+Date:   Wed Oct 27 21:30:08 2010 -0400
+
+    ext4: avoid uninitialized memory references in ext3_htree_next_block()
+    
+    If the first block of htree directory is missing '.' or '..' but is
+    otherwise a valid directory, and we do a lookup for '.' or '..', it's
+    possible to dereference an uninitialized memory pointer in
+    ext4_htree_next_block().
+    
+    We avoid this by moving the special case from ext4_dx_find_entry() to
+    ext4_find_entry(); this also means we can optimize ext4_find_entry()
+    slightly when NFS looks up "..".
+    
+    Thanks to Brad Spengler for pointing a Clang warning that led me to
+    look more closely at this code.  The warning was harmless, but it was
+    useful in pointing out code that was too ugly to live.  This warning was
+    also reported by Roman Borisov.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Brad Spengler 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 314c0d3b3fa9..213523803dff 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -856,6 +856,7 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
+ 	struct buffer_head *bh_use[NAMEI_RA_SIZE];
+ 	struct buffer_head *bh, *ret = NULL;
+ 	ext4_lblk_t start, block, b;
++	const u8 *name = d_name->name;
+ 	int ra_max = 0;		/* Number of bh's in the readahead
+ 				   buffer, bh_use[] */
+ 	int ra_ptr = 0;		/* Current index into readahead
+@@ -870,6 +871,16 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
+ 	namelen = d_name->len;
+ 	if (namelen > EXT4_NAME_LEN)
+ 		return NULL;
++	if ((namelen <= 2) && (name[0] == '.') &&
++	    (name[1] == '.' || name[1] == '0')) {
++		/*
++		 * "." or ".." will only be in the first block
++		 * NFS may look up ".."; "." should be handled by the VFS
++		 */
++		block = start = 0;
++		nblocks = 1;
++		goto restart;
++	}
+ 	if (is_dx(dir)) {
+ 		bh = ext4_dx_find_entry(dir, d_name, res_dir, &err);
+ 		/*
+@@ -960,9 +971,8 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
+ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct qstr *d_name,
+ 		       struct ext4_dir_entry_2 **res_dir, int *err)
+ {
+-	struct super_block * sb;
++	struct super_block * sb = dir->i_sb;
+ 	struct dx_hash_info	hinfo;
+-	u32 hash;
+ 	struct dx_frame frames[2], *frame;
+ 	struct ext4_dir_entry_2 *de, *top;
+ 	struct buffer_head *bh;
+@@ -971,18 +981,8 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q
+ 	int namelen = d_name->len;
+ 	const u8 *name = d_name->name;
+ 
+-	sb = dir->i_sb;
+-	/* NFS may look up ".." - look at dx_root directory block */
+-	if (namelen > 2 || name[0] != '.'||(name[1] != '.' && name[1] != '\0')){
+-		if (!(frame = dx_probe(d_name, dir, &hinfo, frames, err)))
+-			return NULL;
+-	} else {
+-		frame = frames;
+-		frame->bh = NULL;			/* for dx_release() */
+-		frame->at = (struct dx_entry *)frames;	/* hack for zero entry*/
+-		dx_set_block(frame->at, 0);		/* dx_root block is 0 */
+-	}
+-	hash = hinfo.hash;
++	if (!(frame = dx_probe(d_name, dir, &hinfo, frames, err)))
++		return NULL;
+ 	do {
+ 		block = dx_get_block(frame->at);
+ 		if (!(bh = ext4_bread (NULL,dir, block, 0, err)))
+@@ -1008,7 +1008,7 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q
+ 		}
+ 		brelse(bh);
+ 		/* Check to see if we should continue to search */
+-		retval = ext4_htree_next_block(dir, hash, frame,
++		retval = ext4_htree_next_block(dir, hinfo.hash, frame,
+ 					       frames, NULL);
+ 		if (retval < 0) {
+ 			ext4_warning(sb,

commit 5c2178e785244341d1e6f2bc3b62f20a337cc44f
+Author: Theodore Ts'o 
+Date:   Wed Oct 27 21:30:04 2010 -0400
+
+    jbd2: Add sanity check for attempts to start handle during umount
+    
+    An attempt to modify the file system during the call to
+    jbd2_destroy_journal() can lead to a system lockup.  So add some
+    checking to make it much more obvious when this happens to and to
+    determine where the offending code is located.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
+index 5247e7ffdcb4..524800dce207 100644
+--- a/fs/jbd2/checkpoint.c
++++ b/fs/jbd2/checkpoint.c
+@@ -299,6 +299,16 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
+ 		transaction->t_chp_stats.cs_forced_to_close++;
+ 		spin_unlock(&journal->j_list_lock);
+ 		jbd_unlock_bh_state(bh);
++		if (unlikely(journal->j_flags & JBD2_UNMOUNT))
++			/*
++			 * The journal thread is dead; so starting and
++			 * waiting for a commit to finish will cause
++			 * us to wait for a _very_ long time.
++			 */
++			printk(KERN_ERR "JBD2: %s: "
++			       "Waiting for Godot: block %llu\n",
++			       journal->j_devname,
++			       (unsigned long long) bh->b_blocknr);
+ 		jbd2_log_start_commit(journal, tid);
+ 		jbd2_log_wait_commit(journal, tid);
+ 		ret = 1;
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index f3479d6e0a83..6bf0a242613e 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -156,6 +156,7 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
+ 	 */
+ repeat:
+ 	read_lock(&journal->j_state_lock);
++	BUG_ON(journal->j_flags & JBD2_UNMOUNT);
+ 	if (is_journal_aborted(journal) ||
+ 	    (journal->j_errno != 0 && !(journal->j_flags & JBD2_ACK_ERR))) {
+ 		read_unlock(&journal->j_state_lock);

commit 58590b06d79f7ce5ab64ff3b6d537180fa50dc84
+Author: Theodore Ts'o 
+Date:   Wed Oct 27 21:23:12 2010 -0400
+
+    ext4: fix EOFBLOCKS_FL handling
+    
+    It turns out we have several problems with how EOFBLOCKS_FL is
+    handled.  First of all, there was a fencepost error where we were not
+    clearing the EOFBLOCKS_FL when fill in the last uninitialized block,
+    but rather when we allocate the next block _after_ the uninitalized
+    block.  Secondly we were not testing to see if we needed to clear the
+    EOFBLOCKS_FL when writing to the file O_DIRECT or when were converting
+    an uninitialized block (which is the most common case).
+    
+    Google-Bug-Id: 2928259
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 06328d3e5717..820278410220 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -3180,6 +3180,57 @@ static void unmap_underlying_metadata_blocks(struct block_device *bdev,
+                 unmap_underlying_metadata(bdev, block + i);
+ }
+ 
++/*
++ * Handle EOFBLOCKS_FL flag, clearing it if necessary
++ */
++static int check_eofblocks_fl(handle_t *handle, struct inode *inode,
++			      struct ext4_map_blocks *map,
++			      struct ext4_ext_path *path,
++			      unsigned int len)
++{
++	int i, depth;
++	struct ext4_extent_header *eh;
++	struct ext4_extent *ex, *last_ex;
++
++	if (!ext4_test_inode_flag(inode, EXT4_INODE_EOFBLOCKS))
++		return 0;
++
++	depth = ext_depth(inode);
++	eh = path[depth].p_hdr;
++	ex = path[depth].p_ext;
++
++	if (unlikely(!eh->eh_entries)) {
++		EXT4_ERROR_INODE(inode, "eh->eh_entries == 0 and "
++				 "EOFBLOCKS_FL set");
++		return -EIO;
++	}
++	last_ex = EXT_LAST_EXTENT(eh);
++	/*
++	 * We should clear the EOFBLOCKS_FL flag if we are writing the
++	 * last block in the last extent in the file.  We test this by
++	 * first checking to see if the caller to
++	 * ext4_ext_get_blocks() was interested in the last block (or
++	 * a block beyond the last block) in the current extent.  If
++	 * this turns out to be false, we can bail out from this
++	 * function immediately.
++	 */
++	if (map->m_lblk + len < le32_to_cpu(last_ex->ee_block) +
++	    ext4_ext_get_actual_len(last_ex))
++		return 0;
++	/*
++	 * If the caller does appear to be planning to write at or
++	 * beyond the end of the current extent, we then test to see
++	 * if the current extent is the last extent in the file, by
++	 * checking to make sure it was reached via the rightmost node
++	 * at each level of the tree.
++	 */
++	for (i = depth-1; i >= 0; i--)
++		if (path[i].p_idx != EXT_LAST_INDEX(path[i].p_hdr))
++			return 0;
++	ext4_clear_inode_flag(inode, EXT4_INODE_EOFBLOCKS);
++	return ext4_mark_inode_dirty(handle, inode);
++}
++
+ static int
+ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
+ 			struct ext4_map_blocks *map,
+@@ -3217,8 +3268,12 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
+ 	if ((flags & EXT4_GET_BLOCKS_CONVERT)) {
+ 		ret = ext4_convert_unwritten_extents_endio(handle, inode,
+ 							path);
+-		if (ret >= 0)
++		if (ret >= 0) {
+ 			ext4_update_inode_fsync_trans(handle, inode, 1);
++			err = check_eofblocks_fl(handle, inode, map, path,
++						 map->m_len);
++		} else
++			err = ret;
+ 		goto out2;
+ 	}
+ 	/* buffered IO case */
+@@ -3244,8 +3299,13 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
+ 
+ 	/* buffered write, writepage time, convert*/
+ 	ret = ext4_ext_convert_to_initialized(handle, inode, map, path);
+-	if (ret >= 0)
++	if (ret >= 0) {
+ 		ext4_update_inode_fsync_trans(handle, inode, 1);
++		err = check_eofblocks_fl(handle, inode, map, path, map->m_len);
++		if (err < 0)
++			goto out2;
++	}
++
+ out:
+ 	if (ret <= 0) {
+ 		err = ret;
+@@ -3292,6 +3352,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
+ 	}
+ 	return err ? err : allocated;
+ }
++
+ /*
+  * Block allocation/map/preallocation routine for extents based files
+  *
+@@ -3315,9 +3376,9 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ {
+ 	struct ext4_ext_path *path = NULL;
+ 	struct ext4_extent_header *eh;
+-	struct ext4_extent newex, *ex, *last_ex;
++	struct ext4_extent newex, *ex;
+ 	ext4_fsblk_t newblock;
+-	int i, err = 0, depth, ret, cache_type;
++	int err = 0, depth, ret, cache_type;
+ 	unsigned int allocated = 0;
+ 	struct ext4_allocation_request ar;
+ 	ext4_io_end_t *io = EXT4_I(inode)->cur_aio_dio;
+@@ -3497,31 +3558,10 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 			map->m_flags |= EXT4_MAP_UNINIT;
+ 	}
+ 
+-	if (unlikely(ext4_test_inode_flag(inode, EXT4_INODE_EOFBLOCKS))) {
+-		if (unlikely(!eh->eh_entries)) {
+-			EXT4_ERROR_INODE(inode,
+-					 "eh->eh_entries == 0 and "
+-					 "EOFBLOCKS_FL set");
+-			err = -EIO;
+-			goto out2;
+-		}
+-		last_ex = EXT_LAST_EXTENT(eh);
+-		/*
+-		 * If the current leaf block was reached by looking at
+-		 * the last index block all the way down the tree, and
+-		 * we are extending the inode beyond the last extent
+-		 * in the current leaf block, then clear the
+-		 * EOFBLOCKS_FL flag.
+-		 */
+-		for (i = depth-1; i >= 0; i--) {
+-			if (path[i].p_idx != EXT_LAST_INDEX(path[i].p_hdr))
+-				break;
+-		}
+-		if ((i < 0) &&
+-		    (map->m_lblk + ar.len > le32_to_cpu(last_ex->ee_block) +
+-		     ext4_ext_get_actual_len(last_ex)))
+-			ext4_clear_inode_flag(inode, EXT4_INODE_EOFBLOCKS);
+-	}
++	err = check_eofblocks_fl(handle, inode, map, path, ar.len);
++	if (err)
++		goto out2;
++
+ 	err = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
+ 	if (err) {
+ 		/* free data blocks we just allocated */

commit 6d0bf00512b3b1b5d09d9a44919983eec1cc6fd0
+Author: Theodore Ts'o 
+Date:   Mon Aug 9 17:28:38 2010 -0400
+
+    ext4: clean up compiler warning in start_this_handle()
+    
+    Fix the compiler warning:
+    
+      fs/jbd2/transaction.c: In function ‘start_this_handle’:
+      fs/jbd2/transaction.c:98: warning: unused variable ‘ts’
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index d95cc9d0401d..f3479d6e0a83 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -81,6 +81,32 @@ jbd2_get_transaction(journal_t *journal, transaction_t *transaction)
+  * of that one update.
+  */
+ 
++/*
++ * Update transiaction's maximum wait time, if debugging is enabled.
++ *
++ * In order for t_max_wait to be reliable, it must be protected by a
++ * lock.  But doing so will mean that start_this_handle() can not be
++ * run in parallel on SMP systems, which limits our scalability.  So
++ * unless debugging is enabled, we no longer update t_max_wait, which
++ * means that maximum wait time reported by the jbd2_run_stats
++ * tracepoint will always be zero.
++ */
++static inline void update_t_max_wait(transaction_t *transaction)
++{
++#ifdef CONFIG_JBD2_DEBUG
++	unsigned long ts = jiffies;
++
++	if (jbd2_journal_enable_debug &&
++	    time_after(transaction->t_start, ts)) {
++		ts = jbd2_time_diff(ts, transaction->t_start);
++		spin_lock(&transaction->t_handle_lock);
++		if (ts > transaction->t_max_wait)
++			transaction->t_max_wait = ts;
++		spin_unlock(&transaction->t_handle_lock);
++	}
++#endif
++}
++
+ /*
+  * start_this_handle: Given a handle, deal with any locking or stalling
+  * needed to make sure that there is enough journal space for the handle
+@@ -95,7 +121,6 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
+ 	int needed;
+ 	int nblocks = handle->h_buffer_credits;
+ 	transaction_t *new_transaction = NULL;
+-	unsigned long ts = jiffies;
+ 
+ 	if (nblocks > journal->j_max_transaction_buffers) {
+ 		printk(KERN_ERR "JBD: %s wants too many credits (%d > %d)\n",
+@@ -241,25 +266,8 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
+ 
+ 	/* OK, account for the buffers that this operation expects to
+ 	 * use and add the handle to the running transaction. 
+-	 *
+-	 * In order for t_max_wait to be reliable, it must be
+-	 * protected by a lock.  But doing so will mean that
+-	 * start_this_handle() can not be run in parallel on SMP
+-	 * systems, which limits our scalability.  So we only enable
+-	 * it when debugging is enabled.  We may want to use a
+-	 * separate flag, eventually, so we can enable this
+-	 * independently of debugging.
+ 	 */
+-#ifdef CONFIG_JBD2_DEBUG
+-	if (jbd2_journal_enable_debug &&
+-	    time_after(transaction->t_start, ts)) {
+-		ts = jbd2_time_diff(ts, transaction->t_start);
+-		spin_lock(&transaction->t_handle_lock);
+-		if (ts > transaction->t_max_wait)
+-			transaction->t_max_wait = ts;
+-		spin_unlock(&transaction->t_handle_lock);
+-	}
+-#endif
++	update_t_max_wait(transaction);
+ 	handle->h_transaction = transaction;
+ 	atomic_inc(&transaction->t_updates);
+ 	atomic_inc(&transaction->t_handle_count);

commit 8dd420466c7bfc459fa04680bd5690bfc41a4553
+Author: Theodore Ts'o 
+Date:   Tue Aug 3 21:38:29 2010 -0400
+
+    jbd2: Remove t_handle_lock from start_this_handle()
+    
+    This should remove the last exclusive lock from start_this_handle(),
+    so that we should now be able to start multiple transactions at the
+    same time on large SMP systems.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index 67bb0a2f35e5..f52e5e8049f1 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -1004,7 +1004,8 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	 * File the transaction statistics
+ 	 */
+ 	stats.ts_tid = commit_transaction->t_tid;
+-	stats.run.rs_handle_count = commit_transaction->t_handle_count;
++	stats.run.rs_handle_count =
++		atomic_read(&commit_transaction->t_handle_count);
+ 	trace_jbd2_run_stats(journal->j_fs_dev->bd_dev,
+ 			     commit_transaction->t_tid, &stats.run);
+ 
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index 663065142b42..0752bcda535f 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -57,6 +57,7 @@ jbd2_get_transaction(journal_t *journal, transaction_t *transaction)
+ 	spin_lock_init(&transaction->t_handle_lock);
+ 	atomic_set(&transaction->t_updates, 0);
+ 	atomic_set(&transaction->t_outstanding_credits, 0);
++	atomic_set(&transaction->t_handle_count, 0);
+ 	INIT_LIST_HEAD(&transaction->t_inode_list);
+ 	INIT_LIST_HEAD(&transaction->t_private_list);
+ 
+@@ -180,8 +181,8 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
+ 	 * buffers requested by this operation, we need to stall pending a log
+ 	 * checkpoint to free some more log space.
+ 	 */
+-	spin_lock(&transaction->t_handle_lock);
+-	needed = atomic_read(&transaction->t_outstanding_credits) + nblocks;
++	needed = atomic_add_return(nblocks,
++				   &transaction->t_outstanding_credits);
+ 
+ 	if (needed > journal->j_max_transaction_buffers) {
+ 		/*
+@@ -192,7 +193,7 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
+ 		DEFINE_WAIT(wait);
+ 
+ 		jbd_debug(2, "Handle %p starting new commit...\n", handle);
+-		spin_unlock(&transaction->t_handle_lock);
++		atomic_sub(nblocks, &transaction->t_outstanding_credits);
+ 		prepare_to_wait(&journal->j_wait_transaction_locked, &wait,
+ 				TASK_UNINTERRUPTIBLE);
+ 		__jbd2_log_start_commit(journal, transaction->t_tid);
+@@ -229,7 +230,7 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
+ 	 */
+ 	if (__jbd2_log_space_left(journal) < jbd_space_needed(journal)) {
+ 		jbd_debug(2, "Handle %p waiting for checkpoint...\n", handle);
+-		spin_unlock(&transaction->t_handle_lock);
++		atomic_sub(nblocks, &transaction->t_outstanding_credits);
+ 		read_unlock(&journal->j_state_lock);
+ 		write_lock(&journal->j_state_lock);
+ 		if (__jbd2_log_space_left(journal) < jbd_space_needed(journal))
+@@ -239,23 +240,33 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
+ 	}
+ 
+ 	/* OK, account for the buffers that this operation expects to
+-	 * use and add the handle to the running transaction. */
+-
+-	if (time_after(transaction->t_start, ts)) {
++	 * use and add the handle to the running transaction. 
++	 *
++	 * In order for t_max_wait to be reliable, it must be
++	 * protected by a lock.  But doing so will mean that
++	 * start_this_handle() can not be run in parallel on SMP
++	 * systems, which limits our scalability.  So we only enable
++	 * it when debugging is enabled.  We may want to use a
++	 * separate flag, eventually, so we can enable this
++	 * independently of debugging.
++	 */
++#ifdef CONFIG_JBD2_DEBUG
++	if (jbd2_journal_enable_debug &&
++	    time_after(transaction->t_start, ts)) {
+ 		ts = jbd2_time_diff(ts, transaction->t_start);
++		spin_lock(&transaction->t_handle_lock);
+ 		if (ts > transaction->t_max_wait)
+ 			transaction->t_max_wait = ts;
++		spin_unlock(&transaction->t_handle_lock);
+ 	}
+-
++#endif
+ 	handle->h_transaction = transaction;
+-	atomic_add(nblocks, &transaction->t_outstanding_credits);
+ 	atomic_inc(&transaction->t_updates);
+-	transaction->t_handle_count++;
++	atomic_inc(&transaction->t_handle_count);
+ 	jbd_debug(4, "Handle %p given %d credits (total %d, free %d)\n",
+ 		  handle, nblocks,
+ 		  atomic_read(&transaction->t_outstanding_credits),
+ 		  __jbd2_log_space_left(journal));
+-	spin_unlock(&transaction->t_handle_lock);
+ 	read_unlock(&journal->j_state_lock);
+ 
+ 	lock_map_acquire(&handle->h_lockdep_map);
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index 15d5743ccfbb..01743b5446ff 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -629,7 +629,7 @@ struct transaction_s
+ 	/*
+ 	 * How many handles used this transaction? [t_handle_lock]
+ 	 */
+-	int t_handle_count;
++	atomic_t		t_handle_count;
+ 
+ 	/*
+ 	 * This transaction is being forced and some process is

commit a931da6ac9331a6c80dd91c199105806f2336188
+Author: Theodore Ts'o 
+Date:   Tue Aug 3 21:35:12 2010 -0400
+
+    jbd2: Change j_state_lock to be a rwlock_t
+    
+    Lockstat reports have shown that j_state_lock is a major source of
+    lock contention, especially on systems with more than 4 CPU cores.  So
+    change it to be a read/write spinlock.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 533b607f9cb5..ab2247d642c6 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -5066,7 +5066,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 		transaction_t *transaction;
+ 		tid_t tid;
+ 
+-		spin_lock(&journal->j_state_lock);
++		read_lock(&journal->j_state_lock);
+ 		if (journal->j_running_transaction)
+ 			transaction = journal->j_running_transaction;
+ 		else
+@@ -5075,7 +5075,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 			tid = transaction->t_tid;
+ 		else
+ 			tid = journal->j_commit_sequence;
+-		spin_unlock(&journal->j_state_lock);
++		read_unlock(&journal->j_state_lock);
+ 		ei->i_sync_tid = tid;
+ 		ei->i_datasync_tid = tid;
+ 	}
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 3fd65eb66ccd..81cb3fc1218e 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3232,7 +3232,7 @@ static void ext4_init_journal_params(struct super_block *sb, journal_t *journal)
+ 	journal->j_min_batch_time = sbi->s_min_batch_time;
+ 	journal->j_max_batch_time = sbi->s_max_batch_time;
+ 
+-	spin_lock(&journal->j_state_lock);
++	write_lock(&journal->j_state_lock);
+ 	if (test_opt(sb, BARRIER))
+ 		journal->j_flags |= JBD2_BARRIER;
+ 	else
+@@ -3241,7 +3241,7 @@ static void ext4_init_journal_params(struct super_block *sb, journal_t *journal)
+ 		journal->j_flags |= JBD2_ABORT_ON_SYNCDATA_ERR;
+ 	else
+ 		journal->j_flags &= ~JBD2_ABORT_ON_SYNCDATA_ERR;
+-	spin_unlock(&journal->j_state_lock);
++	write_unlock(&journal->j_state_lock);
+ }
+ 
+ static journal_t *ext4_get_journal(struct super_block *sb,
+diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
+index f8cdc02520f9..1c23a0f4e8a3 100644
+--- a/fs/jbd2/checkpoint.c
++++ b/fs/jbd2/checkpoint.c
+@@ -118,13 +118,13 @@ static int __try_to_free_cp_buf(struct journal_head *jh)
+ void __jbd2_log_wait_for_space(journal_t *journal)
+ {
+ 	int nblocks, space_left;
+-	assert_spin_locked(&journal->j_state_lock);
++	/* assert_spin_locked(&journal->j_state_lock); */
+ 
+ 	nblocks = jbd_space_needed(journal);
+ 	while (__jbd2_log_space_left(journal) < nblocks) {
+ 		if (journal->j_flags & JBD2_ABORT)
+ 			return;
+-		spin_unlock(&journal->j_state_lock);
++		write_unlock(&journal->j_state_lock);
+ 		mutex_lock(&journal->j_checkpoint_mutex);
+ 
+ 		/*
+@@ -138,7 +138,7 @@ void __jbd2_log_wait_for_space(journal_t *journal)
+ 		 * filesystem, so abort the journal and leave a stack
+ 		 * trace for forensic evidence.
+ 		 */
+-		spin_lock(&journal->j_state_lock);
++		write_lock(&journal->j_state_lock);
+ 		spin_lock(&journal->j_list_lock);
+ 		nblocks = jbd_space_needed(journal);
+ 		space_left = __jbd2_log_space_left(journal);
+@@ -149,7 +149,7 @@ void __jbd2_log_wait_for_space(journal_t *journal)
+ 			if (journal->j_committing_transaction)
+ 				tid = journal->j_committing_transaction->t_tid;
+ 			spin_unlock(&journal->j_list_lock);
+-			spin_unlock(&journal->j_state_lock);
++			write_unlock(&journal->j_state_lock);
+ 			if (chkpt) {
+ 				jbd2_log_do_checkpoint(journal);
+ 			} else if (jbd2_cleanup_journal_tail(journal) == 0) {
+@@ -167,7 +167,7 @@ void __jbd2_log_wait_for_space(journal_t *journal)
+ 				WARN_ON(1);
+ 				jbd2_journal_abort(journal, 0);
+ 			}
+-			spin_lock(&journal->j_state_lock);
++			write_lock(&journal->j_state_lock);
+ 		} else {
+ 			spin_unlock(&journal->j_list_lock);
+ 		}
+@@ -474,7 +474,7 @@ int jbd2_cleanup_journal_tail(journal_t *journal)
+ 	 * next transaction ID we will write, and where it will
+ 	 * start. */
+ 
+-	spin_lock(&journal->j_state_lock);
++	write_lock(&journal->j_state_lock);
+ 	spin_lock(&journal->j_list_lock);
+ 	transaction = journal->j_checkpoint_transactions;
+ 	if (transaction) {
+@@ -496,7 +496,7 @@ int jbd2_cleanup_journal_tail(journal_t *journal)
+ 	/* If the oldest pinned transaction is at the tail of the log
+            already then there's not much we can do right now. */
+ 	if (journal->j_tail_sequence == first_tid) {
+-		spin_unlock(&journal->j_state_lock);
++		write_unlock(&journal->j_state_lock);
+ 		return 1;
+ 	}
+ 
+@@ -516,7 +516,7 @@ int jbd2_cleanup_journal_tail(journal_t *journal)
+ 	journal->j_free += freed;
+ 	journal->j_tail_sequence = first_tid;
+ 	journal->j_tail = blocknr;
+-	spin_unlock(&journal->j_state_lock);
++	write_unlock(&journal->j_state_lock);
+ 
+ 	/*
+ 	 * If there is an external journal, we need to make sure that
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index fbd2c564e916..67bb0a2f35e5 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -152,9 +152,9 @@ static int journal_submit_commit_record(journal_t *journal,
+ 		printk(KERN_WARNING
+ 		       "JBD2: Disabling barriers on %s, "
+ 		       "not supported by device\n", journal->j_devname);
+-		spin_lock(&journal->j_state_lock);
++		write_lock(&journal->j_state_lock);
+ 		journal->j_flags &= ~JBD2_BARRIER;
+-		spin_unlock(&journal->j_state_lock);
++		write_unlock(&journal->j_state_lock);
+ 
+ 		/* And try again, without the barrier */
+ 		lock_buffer(bh);
+@@ -182,9 +182,9 @@ static int journal_wait_on_commit_record(journal_t *journal,
+ 		printk(KERN_WARNING
+ 		       "JBD2: %s: disabling barries on %s - not supported "
+ 		       "by device\n", __func__, journal->j_devname);
+-		spin_lock(&journal->j_state_lock);
++		write_lock(&journal->j_state_lock);
+ 		journal->j_flags &= ~JBD2_BARRIER;
+-		spin_unlock(&journal->j_state_lock);
++		write_unlock(&journal->j_state_lock);
+ 
+ 		lock_buffer(bh);
+ 		clear_buffer_dirty(bh);
+@@ -400,7 +400,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	jbd_debug(1, "JBD: starting commit of transaction %d\n",
+ 			commit_transaction->t_tid);
+ 
+-	spin_lock(&journal->j_state_lock);
++	write_lock(&journal->j_state_lock);
+ 	commit_transaction->t_state = T_LOCKED;
+ 
+ 	/*
+@@ -424,9 +424,9 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 					TASK_UNINTERRUPTIBLE);
+ 		if (atomic_read(&commit_transaction->t_updates)) {
+ 			spin_unlock(&commit_transaction->t_handle_lock);
+-			spin_unlock(&journal->j_state_lock);
++			write_unlock(&journal->j_state_lock);
+ 			schedule();
+-			spin_lock(&journal->j_state_lock);
++			write_lock(&journal->j_state_lock);
+ 			spin_lock(&commit_transaction->t_handle_lock);
+ 		}
+ 		finish_wait(&journal->j_wait_updates, &wait);
+@@ -497,7 +497,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	start_time = ktime_get();
+ 	commit_transaction->t_log_start = journal->j_head;
+ 	wake_up(&journal->j_wait_transaction_locked);
+-	spin_unlock(&journal->j_state_lock);
++	write_unlock(&journal->j_state_lock);
+ 
+ 	jbd_debug (3, "JBD: commit phase 2\n");
+ 
+@@ -519,9 +519,9 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	 * transaction!  Now comes the tricky part: we need to write out
+ 	 * metadata.  Loop over the transaction's entire buffer list:
+ 	 */
+-	spin_lock(&journal->j_state_lock);
++	write_lock(&journal->j_state_lock);
+ 	commit_transaction->t_state = T_COMMIT;
+-	spin_unlock(&journal->j_state_lock);
++	write_unlock(&journal->j_state_lock);
+ 
+ 	trace_jbd2_commit_logging(journal, commit_transaction);
+ 	stats.run.rs_logging = jiffies;
+@@ -978,7 +978,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	 * __jbd2_journal_drop_transaction(). Otherwise we could race with
+ 	 * other checkpointing code processing the transaction...
+ 	 */
+-	spin_lock(&journal->j_state_lock);
++	write_lock(&journal->j_state_lock);
+ 	spin_lock(&journal->j_list_lock);
+ 	/*
+ 	 * Now recheck if some buffers did not get attached to the transaction
+@@ -986,7 +986,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	 */
+ 	if (commit_transaction->t_forget) {
+ 		spin_unlock(&journal->j_list_lock);
+-		spin_unlock(&journal->j_state_lock);
++		write_unlock(&journal->j_state_lock);
+ 		goto restart_loop;
+ 	}
+ 
+@@ -1038,7 +1038,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 				journal->j_average_commit_time*3) / 4;
+ 	else
+ 		journal->j_average_commit_time = commit_time;
+-	spin_unlock(&journal->j_state_lock);
++	write_unlock(&journal->j_state_lock);
+ 
+ 	if (commit_transaction->t_checkpoint_list == NULL &&
+ 	    commit_transaction->t_checkpoint_io_list == NULL) {
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index a79d3345b55a..e7bf0fd9cec7 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -142,7 +142,7 @@ static int kjournald2(void *arg)
+ 	/*
+ 	 * And now, wait forever for commit wakeup events.
+ 	 */
+-	spin_lock(&journal->j_state_lock);
++	write_lock(&journal->j_state_lock);
+ 
+ loop:
+ 	if (journal->j_flags & JBD2_UNMOUNT)
+@@ -153,10 +153,10 @@ static int kjournald2(void *arg)
+ 
+ 	if (journal->j_commit_sequence != journal->j_commit_request) {
+ 		jbd_debug(1, "OK, requests differ\n");
+-		spin_unlock(&journal->j_state_lock);
++		write_unlock(&journal->j_state_lock);
+ 		del_timer_sync(&journal->j_commit_timer);
+ 		jbd2_journal_commit_transaction(journal);
+-		spin_lock(&journal->j_state_lock);
++		write_lock(&journal->j_state_lock);
+ 		goto loop;
+ 	}
+ 
+@@ -168,9 +168,9 @@ static int kjournald2(void *arg)
+ 		 * be already stopped.
+ 		 */
+ 		jbd_debug(1, "Now suspending kjournald2\n");
+-		spin_unlock(&journal->j_state_lock);
++		write_unlock(&journal->j_state_lock);
+ 		refrigerator();
+-		spin_lock(&journal->j_state_lock);
++		write_lock(&journal->j_state_lock);
+ 	} else {
+ 		/*
+ 		 * We assume on resume that commits are already there,
+@@ -190,9 +190,9 @@ static int kjournald2(void *arg)
+ 		if (journal->j_flags & JBD2_UNMOUNT)
+ 			should_sleep = 0;
+ 		if (should_sleep) {
+-			spin_unlock(&journal->j_state_lock);
++			write_unlock(&journal->j_state_lock);
+ 			schedule();
+-			spin_lock(&journal->j_state_lock);
++			write_lock(&journal->j_state_lock);
+ 		}
+ 		finish_wait(&journal->j_wait_commit, &wait);
+ 	}
+@@ -210,7 +210,7 @@ static int kjournald2(void *arg)
+ 	goto loop;
+ 
+ end_loop:
+-	spin_unlock(&journal->j_state_lock);
++	write_unlock(&journal->j_state_lock);
+ 	del_timer_sync(&journal->j_commit_timer);
+ 	journal->j_task = NULL;
+ 	wake_up(&journal->j_wait_done_commit);
+@@ -233,16 +233,16 @@ static int jbd2_journal_start_thread(journal_t *journal)
+ 
+ static void journal_kill_thread(journal_t *journal)
+ {
+-	spin_lock(&journal->j_state_lock);
++	write_lock(&journal->j_state_lock);
+ 	journal->j_flags |= JBD2_UNMOUNT;
+ 
+ 	while (journal->j_task) {
+ 		wake_up(&journal->j_wait_commit);
+-		spin_unlock(&journal->j_state_lock);
++		write_unlock(&journal->j_state_lock);
+ 		wait_event(journal->j_wait_done_commit, journal->j_task == NULL);
+-		spin_lock(&journal->j_state_lock);
++		write_lock(&journal->j_state_lock);
+ 	}
+-	spin_unlock(&journal->j_state_lock);
++	write_unlock(&journal->j_state_lock);
+ }
+ 
+ /*
+@@ -452,7 +452,7 @@ int __jbd2_log_space_left(journal_t *journal)
+ {
+ 	int left = journal->j_free;
+ 
+-	assert_spin_locked(&journal->j_state_lock);
++	/* assert_spin_locked(&journal->j_state_lock); */
+ 
+ 	/*
+ 	 * Be pessimistic here about the number of those free blocks which
+@@ -497,9 +497,9 @@ int jbd2_log_start_commit(journal_t *journal, tid_t tid)
+ {
+ 	int ret;
+ 
+-	spin_lock(&journal->j_state_lock);
++	write_lock(&journal->j_state_lock);
+ 	ret = __jbd2_log_start_commit(journal, tid);
+-	spin_unlock(&journal->j_state_lock);
++	write_unlock(&journal->j_state_lock);
+ 	return ret;
+ }
+ 
+@@ -518,7 +518,7 @@ int jbd2_journal_force_commit_nested(journal_t *journal)
+ 	transaction_t *transaction = NULL;
+ 	tid_t tid;
+ 
+-	spin_lock(&journal->j_state_lock);
++	read_lock(&journal->j_state_lock);
+ 	if (journal->j_running_transaction && !current->journal_info) {
+ 		transaction = journal->j_running_transaction;
+ 		__jbd2_log_start_commit(journal, transaction->t_tid);
+@@ -526,12 +526,12 @@ int jbd2_journal_force_commit_nested(journal_t *journal)
+ 		transaction = journal->j_committing_transaction;
+ 
+ 	if (!transaction) {
+-		spin_unlock(&journal->j_state_lock);
++		read_unlock(&journal->j_state_lock);
+ 		return 0;	/* Nothing to retry */
+ 	}
+ 
+ 	tid = transaction->t_tid;
+-	spin_unlock(&journal->j_state_lock);
++	read_unlock(&journal->j_state_lock);
+ 	jbd2_log_wait_commit(journal, tid);
+ 	return 1;
+ }
+@@ -545,7 +545,7 @@ int jbd2_journal_start_commit(journal_t *journal, tid_t *ptid)
+ {
+ 	int ret = 0;
+ 
+-	spin_lock(&journal->j_state_lock);
++	write_lock(&journal->j_state_lock);
+ 	if (journal->j_running_transaction) {
+ 		tid_t tid = journal->j_running_transaction->t_tid;
+ 
+@@ -564,7 +564,7 @@ int jbd2_journal_start_commit(journal_t *journal, tid_t *ptid)
+ 			*ptid = journal->j_committing_transaction->t_tid;
+ 		ret = 1;
+ 	}
+-	spin_unlock(&journal->j_state_lock);
++	write_unlock(&journal->j_state_lock);
+ 	return ret;
+ }
+ 
+@@ -576,26 +576,24 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid)
+ {
+ 	int err = 0;
+ 
++	read_lock(&journal->j_state_lock);
+ #ifdef CONFIG_JBD2_DEBUG
+-	spin_lock(&journal->j_state_lock);
+ 	if (!tid_geq(journal->j_commit_request, tid)) {
+ 		printk(KERN_EMERG
+ 		       "%s: error: j_commit_request=%d, tid=%d\n",
+ 		       __func__, journal->j_commit_request, tid);
+ 	}
+-	spin_unlock(&journal->j_state_lock);
+ #endif
+-	spin_lock(&journal->j_state_lock);
+ 	while (tid_gt(tid, journal->j_commit_sequence)) {
+ 		jbd_debug(1, "JBD: want %d, j_commit_sequence=%d\n",
+ 				  tid, journal->j_commit_sequence);
+ 		wake_up(&journal->j_wait_commit);
+-		spin_unlock(&journal->j_state_lock);
++		read_unlock(&journal->j_state_lock);
+ 		wait_event(journal->j_wait_done_commit,
+ 				!tid_gt(tid, journal->j_commit_sequence));
+-		spin_lock(&journal->j_state_lock);
++		read_lock(&journal->j_state_lock);
+ 	}
+-	spin_unlock(&journal->j_state_lock);
++	read_unlock(&journal->j_state_lock);
+ 
+ 	if (unlikely(is_journal_aborted(journal))) {
+ 		printk(KERN_EMERG "journal commit I/O error\n");
+@@ -612,7 +610,7 @@ int jbd2_journal_next_log_block(journal_t *journal, unsigned long long *retp)
+ {
+ 	unsigned long blocknr;
+ 
+-	spin_lock(&journal->j_state_lock);
++	write_lock(&journal->j_state_lock);
+ 	J_ASSERT(journal->j_free > 1);
+ 
+ 	blocknr = journal->j_head;
+@@ -620,7 +618,7 @@ int jbd2_journal_next_log_block(journal_t *journal, unsigned long long *retp)
+ 	journal->j_free--;
+ 	if (journal->j_head == journal->j_last)
+ 		journal->j_head = journal->j_first;
+-	spin_unlock(&journal->j_state_lock);
++	write_unlock(&journal->j_state_lock);
+ 	return jbd2_journal_bmap(journal, blocknr, retp);
+ }
+ 
+@@ -840,7 +838,7 @@ static journal_t * journal_init_common (void)
+ 	mutex_init(&journal->j_checkpoint_mutex);
+ 	spin_lock_init(&journal->j_revoke_lock);
+ 	spin_lock_init(&journal->j_list_lock);
+-	spin_lock_init(&journal->j_state_lock);
++	rwlock_init(&journal->j_state_lock);
+ 
+ 	journal->j_commit_interval = (HZ * JBD2_DEFAULT_MAX_COMMIT_AGE);
+ 	journal->j_min_batch_time = 0;
+@@ -1106,14 +1104,14 @@ void jbd2_journal_update_superblock(journal_t *journal, int wait)
+ 		set_buffer_uptodate(bh);
+ 	}
+ 
+-	spin_lock(&journal->j_state_lock);
++	read_lock(&journal->j_state_lock);
+ 	jbd_debug(1,"JBD: updating superblock (start %ld, seq %d, errno %d)\n",
+ 		  journal->j_tail, journal->j_tail_sequence, journal->j_errno);
+ 
+ 	sb->s_sequence = cpu_to_be32(journal->j_tail_sequence);
+ 	sb->s_start    = cpu_to_be32(journal->j_tail);
+ 	sb->s_errno    = cpu_to_be32(journal->j_errno);
+-	spin_unlock(&journal->j_state_lock);
++	read_unlock(&journal->j_state_lock);
+ 
+ 	BUFFER_TRACE(bh, "marking dirty");
+ 	mark_buffer_dirty(bh);
+@@ -1134,12 +1132,12 @@ void jbd2_journal_update_superblock(journal_t *journal, int wait)
+ 	 * any future commit will have to be careful to update the
+ 	 * superblock again to re-record the true start of the log. */
+ 
+-	spin_lock(&journal->j_state_lock);
++	write_lock(&journal->j_state_lock);
+ 	if (sb->s_start)
+ 		journal->j_flags &= ~JBD2_FLUSHED;
+ 	else
+ 		journal->j_flags |= JBD2_FLUSHED;
+-	spin_unlock(&journal->j_state_lock);
++	write_unlock(&journal->j_state_lock);
+ }
+ 
+ /*
+@@ -1551,7 +1549,7 @@ int jbd2_journal_flush(journal_t *journal)
+ 	transaction_t *transaction = NULL;
+ 	unsigned long old_tail;
+ 
+-	spin_lock(&journal->j_state_lock);
++	write_lock(&journal->j_state_lock);
+ 
+ 	/* Force everything buffered to the log... */
+ 	if (journal->j_running_transaction) {
+@@ -1564,10 +1562,10 @@ int jbd2_journal_flush(journal_t *journal)
+ 	if (transaction) {
+ 		tid_t tid = transaction->t_tid;
+ 
+-		spin_unlock(&journal->j_state_lock);
++		write_unlock(&journal->j_state_lock);
+ 		jbd2_log_wait_commit(journal, tid);
+ 	} else {
+-		spin_unlock(&journal->j_state_lock);
++		write_unlock(&journal->j_state_lock);
+ 	}
+ 
+ 	/* ...and flush everything in the log out to disk. */
+@@ -1591,12 +1589,12 @@ int jbd2_journal_flush(journal_t *journal)
+ 	 * the magic code for a fully-recovered superblock.  Any future
+ 	 * commits of data to the journal will restore the current
+ 	 * s_start value. */
+-	spin_lock(&journal->j_state_lock);
++	write_lock(&journal->j_state_lock);
+ 	old_tail = journal->j_tail;
+ 	journal->j_tail = 0;
+-	spin_unlock(&journal->j_state_lock);
++	write_unlock(&journal->j_state_lock);
+ 	jbd2_journal_update_superblock(journal, 1);
+-	spin_lock(&journal->j_state_lock);
++	write_lock(&journal->j_state_lock);
+ 	journal->j_tail = old_tail;
+ 
+ 	J_ASSERT(!journal->j_running_transaction);
+@@ -1604,7 +1602,7 @@ int jbd2_journal_flush(journal_t *journal)
+ 	J_ASSERT(!journal->j_checkpoint_transactions);
+ 	J_ASSERT(journal->j_head == journal->j_tail);
+ 	J_ASSERT(journal->j_tail_sequence == journal->j_transaction_sequence);
+-	spin_unlock(&journal->j_state_lock);
++	write_unlock(&journal->j_state_lock);
+ 	return 0;
+ }
+ 
+@@ -1668,12 +1666,12 @@ void __jbd2_journal_abort_hard(journal_t *journal)
+ 	printk(KERN_ERR "Aborting journal on device %s.\n",
+ 	       journal->j_devname);
+ 
+-	spin_lock(&journal->j_state_lock);
++	write_lock(&journal->j_state_lock);
+ 	journal->j_flags |= JBD2_ABORT;
+ 	transaction = journal->j_running_transaction;
+ 	if (transaction)
+ 		__jbd2_log_start_commit(journal, transaction->t_tid);
+-	spin_unlock(&journal->j_state_lock);
++	write_unlock(&journal->j_state_lock);
+ }
+ 
+ /* Soft abort: record the abort error status in the journal superblock,
+@@ -1758,12 +1756,12 @@ int jbd2_journal_errno(journal_t *journal)
+ {
+ 	int err;
+ 
+-	spin_lock(&journal->j_state_lock);
++	read_lock(&journal->j_state_lock);
+ 	if (journal->j_flags & JBD2_ABORT)
+ 		err = -EROFS;
+ 	else
+ 		err = journal->j_errno;
+-	spin_unlock(&journal->j_state_lock);
++	read_unlock(&journal->j_state_lock);
+ 	return err;
+ }
+ 
+@@ -1778,12 +1776,12 @@ int jbd2_journal_clear_err(journal_t *journal)
+ {
+ 	int err = 0;
+ 
+-	spin_lock(&journal->j_state_lock);
++	write_lock(&journal->j_state_lock);
+ 	if (journal->j_flags & JBD2_ABORT)
+ 		err = -EROFS;
+ 	else
+ 		journal->j_errno = 0;
+-	spin_unlock(&journal->j_state_lock);
++	write_unlock(&journal->j_state_lock);
+ 	return err;
+ }
+ 
+@@ -1796,10 +1794,10 @@ int jbd2_journal_clear_err(journal_t *journal)
+  */
+ void jbd2_journal_ack_err(journal_t *journal)
+ {
+-	spin_lock(&journal->j_state_lock);
++	write_lock(&journal->j_state_lock);
+ 	if (journal->j_errno)
+ 		journal->j_flags |= JBD2_ACK_ERR;
+-	spin_unlock(&journal->j_state_lock);
++	write_unlock(&journal->j_state_lock);
+ }
+ 
+ int jbd2_journal_blocks_per_page(struct inode *inode)
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index 9c64c7ec48d4..663065142b42 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -124,36 +124,38 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
+ 
+ 	jbd_debug(3, "New handle %p going live.\n", handle);
+ 
+-repeat:
+-
+ 	/*
+ 	 * We need to hold j_state_lock until t_updates has been incremented,
+ 	 * for proper journal barrier handling
+ 	 */
+-	spin_lock(&journal->j_state_lock);
+-repeat_locked:
++repeat:
++	read_lock(&journal->j_state_lock);
+ 	if (is_journal_aborted(journal) ||
+ 	    (journal->j_errno != 0 && !(journal->j_flags & JBD2_ACK_ERR))) {
+-		spin_unlock(&journal->j_state_lock);
++		read_unlock(&journal->j_state_lock);
+ 		kfree(new_transaction);
+ 		return -EROFS;
+ 	}
+ 
+ 	/* Wait on the journal's transaction barrier if necessary */
+ 	if (journal->j_barrier_count) {
+-		spin_unlock(&journal->j_state_lock);
++		read_unlock(&journal->j_state_lock);
+ 		wait_event(journal->j_wait_transaction_locked,
+ 				journal->j_barrier_count == 0);
+ 		goto repeat;
+ 	}
+ 
+ 	if (!journal->j_running_transaction) {
+-		if (!new_transaction) {
+-			spin_unlock(&journal->j_state_lock);
++		read_unlock(&journal->j_state_lock);
++		if (!new_transaction)
+ 			goto alloc_transaction;
++		write_lock(&journal->j_state_lock);
++		if (!journal->j_running_transaction) {
++			jbd2_get_transaction(journal, new_transaction);
++			new_transaction = NULL;
+ 		}
+-		jbd2_get_transaction(journal, new_transaction);
+-		new_transaction = NULL;
++		write_unlock(&journal->j_state_lock);
++		goto repeat;
+ 	}
+ 
+ 	transaction = journal->j_running_transaction;
+@@ -167,7 +169,7 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
+ 
+ 		prepare_to_wait(&journal->j_wait_transaction_locked,
+ 					&wait, TASK_UNINTERRUPTIBLE);
+-		spin_unlock(&journal->j_state_lock);
++		read_unlock(&journal->j_state_lock);
+ 		schedule();
+ 		finish_wait(&journal->j_wait_transaction_locked, &wait);
+ 		goto repeat;
+@@ -194,7 +196,7 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
+ 		prepare_to_wait(&journal->j_wait_transaction_locked, &wait,
+ 				TASK_UNINTERRUPTIBLE);
+ 		__jbd2_log_start_commit(journal, transaction->t_tid);
+-		spin_unlock(&journal->j_state_lock);
++		read_unlock(&journal->j_state_lock);
+ 		schedule();
+ 		finish_wait(&journal->j_wait_transaction_locked, &wait);
+ 		goto repeat;
+@@ -228,8 +230,12 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
+ 	if (__jbd2_log_space_left(journal) < jbd_space_needed(journal)) {
+ 		jbd_debug(2, "Handle %p waiting for checkpoint...\n", handle);
+ 		spin_unlock(&transaction->t_handle_lock);
+-		__jbd2_log_wait_for_space(journal);
+-		goto repeat_locked;
++		read_unlock(&journal->j_state_lock);
++		write_lock(&journal->j_state_lock);
++		if (__jbd2_log_space_left(journal) < jbd_space_needed(journal))
++			__jbd2_log_wait_for_space(journal);
++		write_unlock(&journal->j_state_lock);
++		goto repeat;
+ 	}
+ 
+ 	/* OK, account for the buffers that this operation expects to
+@@ -250,7 +256,7 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
+ 		  atomic_read(&transaction->t_outstanding_credits),
+ 		  __jbd2_log_space_left(journal));
+ 	spin_unlock(&transaction->t_handle_lock);
+-	spin_unlock(&journal->j_state_lock);
++	read_unlock(&journal->j_state_lock);
+ 
+ 	lock_map_acquire(&handle->h_lockdep_map);
+ 	kfree(new_transaction);
+@@ -362,7 +368,7 @@ int jbd2_journal_extend(handle_t *handle, int nblocks)
+ 
+ 	result = 1;
+ 
+-	spin_lock(&journal->j_state_lock);
++	read_lock(&journal->j_state_lock);
+ 
+ 	/* Don't extend a locked-down transaction! */
+ 	if (handle->h_transaction->t_state != T_RUNNING) {
+@@ -394,7 +400,7 @@ int jbd2_journal_extend(handle_t *handle, int nblocks)
+ unlock:
+ 	spin_unlock(&transaction->t_handle_lock);
+ error_out:
+-	spin_unlock(&journal->j_state_lock);
++	read_unlock(&journal->j_state_lock);
+ out:
+ 	return result;
+ }
+@@ -432,7 +438,7 @@ int jbd2__journal_restart(handle_t *handle, int nblocks, int gfp_mask)
+ 	J_ASSERT(atomic_read(&transaction->t_updates) > 0);
+ 	J_ASSERT(journal_current_handle() == handle);
+ 
+-	spin_lock(&journal->j_state_lock);
++	read_lock(&journal->j_state_lock);
+ 	spin_lock(&transaction->t_handle_lock);
+ 	atomic_sub(handle->h_buffer_credits,
+ 		   &transaction->t_outstanding_credits);
+@@ -442,7 +448,7 @@ int jbd2__journal_restart(handle_t *handle, int nblocks, int gfp_mask)
+ 
+ 	jbd_debug(2, "restarting handle %p\n", handle);
+ 	__jbd2_log_start_commit(journal, transaction->t_tid);
+-	spin_unlock(&journal->j_state_lock);
++	read_unlock(&journal->j_state_lock);
+ 
+ 	lock_map_release(&handle->h_lockdep_map);
+ 	handle->h_buffer_credits = nblocks;
+@@ -472,7 +478,7 @@ void jbd2_journal_lock_updates(journal_t *journal)
+ {
+ 	DEFINE_WAIT(wait);
+ 
+-	spin_lock(&journal->j_state_lock);
++	write_lock(&journal->j_state_lock);
+ 	++journal->j_barrier_count;
+ 
+ 	/* Wait until there are no running updates */
+@@ -490,12 +496,12 @@ void jbd2_journal_lock_updates(journal_t *journal)
+ 		prepare_to_wait(&journal->j_wait_updates, &wait,
+ 				TASK_UNINTERRUPTIBLE);
+ 		spin_unlock(&transaction->t_handle_lock);
+-		spin_unlock(&journal->j_state_lock);
++		write_unlock(&journal->j_state_lock);
+ 		schedule();
+ 		finish_wait(&journal->j_wait_updates, &wait);
+-		spin_lock(&journal->j_state_lock);
++		write_lock(&journal->j_state_lock);
+ 	}
+-	spin_unlock(&journal->j_state_lock);
++	write_unlock(&journal->j_state_lock);
+ 
+ 	/*
+ 	 * We have now established a barrier against other normal updates, but
+@@ -519,9 +525,9 @@ void jbd2_journal_unlock_updates (journal_t *journal)
+ 	J_ASSERT(journal->j_barrier_count != 0);
+ 
+ 	mutex_unlock(&journal->j_barrier);
+-	spin_lock(&journal->j_state_lock);
++	write_lock(&journal->j_state_lock);
+ 	--journal->j_barrier_count;
+-	spin_unlock(&journal->j_state_lock);
++	write_unlock(&journal->j_state_lock);
+ 	wake_up(&journal->j_wait_transaction_locked);
+ }
+ 
+@@ -1314,9 +1320,9 @@ int jbd2_journal_stop(handle_t *handle)
+ 
+ 		journal->j_last_sync_writer = pid;
+ 
+-		spin_lock(&journal->j_state_lock);
++		read_lock(&journal->j_state_lock);
+ 		commit_time = journal->j_average_commit_time;
+-		spin_unlock(&journal->j_state_lock);
++		read_unlock(&journal->j_state_lock);
+ 
+ 		trans_time = ktime_to_ns(ktime_sub(ktime_get(),
+ 						   transaction->t_start_time));
+@@ -1748,7 +1754,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh)
+ 		goto zap_buffer_unlocked;
+ 
+ 	/* OK, we have data buffer in journaled mode */
+-	spin_lock(&journal->j_state_lock);
++	write_lock(&journal->j_state_lock);
+ 	jbd_lock_bh_state(bh);
+ 	spin_lock(&journal->j_list_lock);
+ 
+@@ -1801,7 +1807,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh)
+ 			jbd2_journal_put_journal_head(jh);
+ 			spin_unlock(&journal->j_list_lock);
+ 			jbd_unlock_bh_state(bh);
+-			spin_unlock(&journal->j_state_lock);
++			write_unlock(&journal->j_state_lock);
+ 			return ret;
+ 		} else {
+ 			/* There is no currently-running transaction. So the
+@@ -1815,7 +1821,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh)
+ 				jbd2_journal_put_journal_head(jh);
+ 				spin_unlock(&journal->j_list_lock);
+ 				jbd_unlock_bh_state(bh);
+-				spin_unlock(&journal->j_state_lock);
++				write_unlock(&journal->j_state_lock);
+ 				return ret;
+ 			} else {
+ 				/* The orphan record's transaction has
+@@ -1839,7 +1845,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh)
+ 		jbd2_journal_put_journal_head(jh);
+ 		spin_unlock(&journal->j_list_lock);
+ 		jbd_unlock_bh_state(bh);
+-		spin_unlock(&journal->j_state_lock);
++		write_unlock(&journal->j_state_lock);
+ 		return 0;
+ 	} else {
+ 		/* Good, the buffer belongs to the running transaction.
+@@ -1858,7 +1864,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh)
+ zap_buffer_no_jh:
+ 	spin_unlock(&journal->j_list_lock);
+ 	jbd_unlock_bh_state(bh);
+-	spin_unlock(&journal->j_state_lock);
++	write_unlock(&journal->j_state_lock);
+ zap_buffer_unlocked:
+ 	clear_buffer_dirty(bh);
+ 	J_ASSERT_BH(bh, !buffer_jbddirty(bh));
+@@ -2165,9 +2171,9 @@ int jbd2_journal_begin_ordered_truncate(journal_t *journal,
+ 	/* Locks are here just to force reading of recent values, it is
+ 	 * enough that the transaction was not committing before we started
+ 	 * a transaction adding the inode to orphan list */
+-	spin_lock(&journal->j_state_lock);
++	read_lock(&journal->j_state_lock);
+ 	commit_trans = journal->j_committing_transaction;
+-	spin_unlock(&journal->j_state_lock);
++	read_unlock(&journal->j_state_lock);
+ 	spin_lock(&journal->j_list_lock);
+ 	inode_trans = jinode->i_transaction;
+ 	spin_unlock(&journal->j_list_lock);
+diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
+index 47878cf16418..9c1b92ebeb94 100644
+--- a/fs/ocfs2/journal.c
++++ b/fs/ocfs2/journal.c
+@@ -760,13 +760,13 @@ void ocfs2_set_journal_params(struct ocfs2_super *osb)
+ 	if (osb->osb_commit_interval)
+ 		commit_interval = osb->osb_commit_interval;
+ 
+-	spin_lock(&journal->j_state_lock);
++	write_lock(&journal->j_state_lock);
+ 	journal->j_commit_interval = commit_interval;
+ 	if (osb->s_mount_opt & OCFS2_MOUNT_BARRIER)
+ 		journal->j_flags |= JBD2_BARRIER;
+ 	else
+ 		journal->j_flags &= ~JBD2_BARRIER;
+-	spin_unlock(&journal->j_state_lock);
++	write_unlock(&journal->j_state_lock);
+ }
+ 
+ int ocfs2_journal_init(struct ocfs2_journal *journal, int *dirty)
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index a72ce21de0e1..15d5743ccfbb 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -764,7 +764,7 @@ struct journal_s
+ 	/*
+ 	 * Protect the various scalars in the journal
+ 	 */
+-	spinlock_t		j_state_lock;
++	rwlock_t		j_state_lock;
+ 
+ 	/*
+ 	 * Number of processes waiting to create a barrier lock [j_state_lock]

commit a51dca9cd3bb4ec5a05bfb6feabf024a5c808a37
+Author: Theodore Ts'o 
+Date:   Mon Aug 2 08:43:25 2010 -0400
+
+    jbd2: Use atomic variables to avoid taking t_handle_lock in jbd2_journal_stop
+    
+    By using an atomic_t for t_updates and t_outstanding credits, this
+    should allow us to not need to take transaction t_handle_lock in
+    jbd2_journal_stop().
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
+index 076d1cc44f95..f8cdc02520f9 100644
+--- a/fs/jbd2/checkpoint.c
++++ b/fs/jbd2/checkpoint.c
+@@ -775,7 +775,7 @@ void __jbd2_journal_drop_transaction(journal_t *journal, transaction_t *transact
+ 	J_ASSERT(transaction->t_log_list == NULL);
+ 	J_ASSERT(transaction->t_checkpoint_list == NULL);
+ 	J_ASSERT(transaction->t_checkpoint_io_list == NULL);
+-	J_ASSERT(transaction->t_updates == 0);
++	J_ASSERT(atomic_read(&transaction->t_updates) == 0);
+ 	J_ASSERT(journal->j_committing_transaction != transaction);
+ 	J_ASSERT(journal->j_running_transaction != transaction);
+ 
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index af056810acb6..fbd2c564e916 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -417,12 +417,12 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 					      stats.run.rs_locked);
+ 
+ 	spin_lock(&commit_transaction->t_handle_lock);
+-	while (commit_transaction->t_updates) {
++	while (atomic_read(&commit_transaction->t_updates)) {
+ 		DEFINE_WAIT(wait);
+ 
+ 		prepare_to_wait(&journal->j_wait_updates, &wait,
+ 					TASK_UNINTERRUPTIBLE);
+-		if (commit_transaction->t_updates) {
++		if (atomic_read(&commit_transaction->t_updates)) {
+ 			spin_unlock(&commit_transaction->t_handle_lock);
+ 			spin_unlock(&journal->j_state_lock);
+ 			schedule();
+@@ -433,7 +433,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	}
+ 	spin_unlock(&commit_transaction->t_handle_lock);
+ 
+-	J_ASSERT (commit_transaction->t_outstanding_credits <=
++	J_ASSERT (atomic_read(&commit_transaction->t_outstanding_credits) <=
+ 			journal->j_max_transaction_buffers);
+ 
+ 	/*
+@@ -527,11 +527,12 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	stats.run.rs_logging = jiffies;
+ 	stats.run.rs_flushing = jbd2_time_diff(stats.run.rs_flushing,
+ 					       stats.run.rs_logging);
+-	stats.run.rs_blocks = commit_transaction->t_outstanding_credits;
++	stats.run.rs_blocks =
++		atomic_read(&commit_transaction->t_outstanding_credits);
+ 	stats.run.rs_blocks_logged = 0;
+ 
+ 	J_ASSERT(commit_transaction->t_nr_buffers <=
+-		 commit_transaction->t_outstanding_credits);
++		 atomic_read(&commit_transaction->t_outstanding_credits));
+ 
+ 	err = 0;
+ 	descriptor = NULL;
+@@ -616,7 +617,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 		 * the free space in the log, but this counter is changed
+ 		 * by jbd2_journal_next_log_block() also.
+ 		 */
+-		commit_transaction->t_outstanding_credits--;
++		atomic_dec(&commit_transaction->t_outstanding_credits);
+ 
+ 		/* Bump b_count to prevent truncate from stumbling over
+                    the shadowed buffer!  @@@ This can go if we ever get
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index 001e95fb0fe1..9c64c7ec48d4 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -55,6 +55,8 @@ jbd2_get_transaction(journal_t *journal, transaction_t *transaction)
+ 	transaction->t_tid = journal->j_transaction_sequence++;
+ 	transaction->t_expires = jiffies + journal->j_commit_interval;
+ 	spin_lock_init(&transaction->t_handle_lock);
++	atomic_set(&transaction->t_updates, 0);
++	atomic_set(&transaction->t_outstanding_credits, 0);
+ 	INIT_LIST_HEAD(&transaction->t_inode_list);
+ 	INIT_LIST_HEAD(&transaction->t_private_list);
+ 
+@@ -177,7 +179,7 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
+ 	 * checkpoint to free some more log space.
+ 	 */
+ 	spin_lock(&transaction->t_handle_lock);
+-	needed = transaction->t_outstanding_credits + nblocks;
++	needed = atomic_read(&transaction->t_outstanding_credits) + nblocks;
+ 
+ 	if (needed > journal->j_max_transaction_buffers) {
+ 		/*
+@@ -240,11 +242,12 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
+ 	}
+ 
+ 	handle->h_transaction = transaction;
+-	transaction->t_outstanding_credits += nblocks;
+-	transaction->t_updates++;
++	atomic_add(nblocks, &transaction->t_outstanding_credits);
++	atomic_inc(&transaction->t_updates);
+ 	transaction->t_handle_count++;
+ 	jbd_debug(4, "Handle %p given %d credits (total %d, free %d)\n",
+-		  handle, nblocks, transaction->t_outstanding_credits,
++		  handle, nblocks,
++		  atomic_read(&transaction->t_outstanding_credits),
+ 		  __jbd2_log_space_left(journal));
+ 	spin_unlock(&transaction->t_handle_lock);
+ 	spin_unlock(&journal->j_state_lock);
+@@ -369,7 +372,7 @@ int jbd2_journal_extend(handle_t *handle, int nblocks)
+ 	}
+ 
+ 	spin_lock(&transaction->t_handle_lock);
+-	wanted = transaction->t_outstanding_credits + nblocks;
++	wanted = atomic_read(&transaction->t_outstanding_credits) + nblocks;
+ 
+ 	if (wanted > journal->j_max_transaction_buffers) {
+ 		jbd_debug(3, "denied handle %p %d blocks: "
+@@ -384,7 +387,7 @@ int jbd2_journal_extend(handle_t *handle, int nblocks)
+ 	}
+ 
+ 	handle->h_buffer_credits += nblocks;
+-	transaction->t_outstanding_credits += nblocks;
++	atomic_add(nblocks, &transaction->t_outstanding_credits);
+ 	result = 0;
+ 
+ 	jbd_debug(3, "extended handle %p by %d\n", handle, nblocks);
+@@ -426,15 +429,14 @@ int jbd2__journal_restart(handle_t *handle, int nblocks, int gfp_mask)
+ 	 * First unlink the handle from its current transaction, and start the
+ 	 * commit on that.
+ 	 */
+-	J_ASSERT(transaction->t_updates > 0);
++	J_ASSERT(atomic_read(&transaction->t_updates) > 0);
+ 	J_ASSERT(journal_current_handle() == handle);
+ 
+ 	spin_lock(&journal->j_state_lock);
+ 	spin_lock(&transaction->t_handle_lock);
+-	transaction->t_outstanding_credits -= handle->h_buffer_credits;
+-	transaction->t_updates--;
+-
+-	if (!transaction->t_updates)
++	atomic_sub(handle->h_buffer_credits,
++		   &transaction->t_outstanding_credits);
++	if (atomic_dec_and_test(&transaction->t_updates))
+ 		wake_up(&journal->j_wait_updates);
+ 	spin_unlock(&transaction->t_handle_lock);
+ 
+@@ -481,7 +483,7 @@ void jbd2_journal_lock_updates(journal_t *journal)
+ 			break;
+ 
+ 		spin_lock(&transaction->t_handle_lock);
+-		if (!transaction->t_updates) {
++		if (!atomic_read(&transaction->t_updates)) {
+ 			spin_unlock(&transaction->t_handle_lock);
+ 			break;
+ 		}
+@@ -1258,7 +1260,8 @@ int jbd2_journal_stop(handle_t *handle)
+ {
+ 	transaction_t *transaction = handle->h_transaction;
+ 	journal_t *journal = transaction->t_journal;
+-	int err;
++	int err, wait_for_commit = 0;
++	tid_t tid;
+ 	pid_t pid;
+ 
+ 	J_ASSERT(journal_current_handle() == handle);
+@@ -1266,7 +1269,7 @@ int jbd2_journal_stop(handle_t *handle)
+ 	if (is_handle_aborted(handle))
+ 		err = -EIO;
+ 	else {
+-		J_ASSERT(transaction->t_updates > 0);
++		J_ASSERT(atomic_read(&transaction->t_updates) > 0);
+ 		err = 0;
+ 	}
+ 
+@@ -1334,14 +1337,8 @@ int jbd2_journal_stop(handle_t *handle)
+ 	if (handle->h_sync)
+ 		transaction->t_synchronous_commit = 1;
+ 	current->journal_info = NULL;
+-	spin_lock(&transaction->t_handle_lock);
+-	transaction->t_outstanding_credits -= handle->h_buffer_credits;
+-	transaction->t_updates--;
+-	if (!transaction->t_updates) {
+-		wake_up(&journal->j_wait_updates);
+-		if (journal->j_barrier_count)
+-			wake_up(&journal->j_wait_transaction_locked);
+-	}
++	atomic_sub(handle->h_buffer_credits,
++		   &transaction->t_outstanding_credits);
+ 
+ 	/*
+ 	 * If the handle is marked SYNC, we need to set another commit
+@@ -1350,15 +1347,13 @@ int jbd2_journal_stop(handle_t *handle)
+ 	 * transaction is too old now.
+ 	 */
+ 	if (handle->h_sync ||
+-			transaction->t_outstanding_credits >
+-				journal->j_max_transaction_buffers ||
+-			time_after_eq(jiffies, transaction->t_expires)) {
++	    (atomic_read(&transaction->t_outstanding_credits) >
++	     journal->j_max_transaction_buffers) ||
++	    time_after_eq(jiffies, transaction->t_expires)) {
+ 		/* Do this even for aborted journals: an abort still
+ 		 * completes the commit thread, it just doesn't write
+ 		 * anything to disk. */
+-		tid_t tid = transaction->t_tid;
+ 
+-		spin_unlock(&transaction->t_handle_lock);
+ 		jbd_debug(2, "transaction too old, requesting commit for "
+ 					"handle %p\n", handle);
+ 		/* This is non-blocking */
+@@ -1369,11 +1364,25 @@ int jbd2_journal_stop(handle_t *handle)
+ 		 * to wait for the commit to complete.
+ 		 */
+ 		if (handle->h_sync && !(current->flags & PF_MEMALLOC))
+-			err = jbd2_log_wait_commit(journal, tid);
+-	} else {
+-		spin_unlock(&transaction->t_handle_lock);
++			wait_for_commit = 1;
+ 	}
+ 
++	/*
++	 * Once we drop t_updates, if it goes to zero the transaction
++	 * could start commiting on us and eventually disappear.  So
++	 * once we do this, we must not dereference transaction
++	 * pointer again.
++	 */
++	tid = transaction->t_tid;
++	if (atomic_dec_and_test(&transaction->t_updates)) {
++		wake_up(&journal->j_wait_updates);
++		if (journal->j_barrier_count)
++			wake_up(&journal->j_wait_transaction_locked);
++	}
++
++	if (wait_for_commit)
++		err = jbd2_log_wait_commit(journal, tid);
++
+ 	lock_map_release(&handle->h_lockdep_map);
+ 
+ 	jbd2_free_handle(handle);
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index 5a72bc75b273..a72ce21de0e1 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -601,13 +601,13 @@ struct transaction_s
+ 	 * Number of outstanding updates running on this transaction
+ 	 * [t_handle_lock]
+ 	 */
+-	int			t_updates;
++	atomic_t		t_updates;
+ 
+ 	/*
+ 	 * Number of buffers reserved for use by all handles in this transaction
+ 	 * handle but not yet modified. [t_handle_lock]
+ 	 */
+-	int			t_outstanding_credits;
++	atomic_t		t_outstanding_credits;
+ 
+ 	/*
+ 	 * Forward and backward links for the circular list of all transactions
+@@ -1258,8 +1258,8 @@ static inline int jbd_space_needed(journal_t *journal)
+ {
+ 	int nblocks = journal->j_max_transaction_buffers;
+ 	if (journal->j_committing_transaction)
+-		nblocks += journal->j_committing_transaction->
+-					t_outstanding_credits;
++		nblocks += atomic_read(&journal->j_committing_transaction->
++				       t_outstanding_credits);
+ 	return nblocks;
+ }
+ 

commit 8b67f04ab9de5d8f3a71aef72bf02c995a506db5
+Author: Theodore Ts'o 
+Date:   Sun Aug 1 23:14:20 2010 -0400
+
+    ext4: Add mount options in superblock
+    
+    Allow mount options to be stored in the superblock.  Also add default
+    mount option bits for nobarrier, block_validity, discard, and nodelalloc.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 9ca3637eca5f..ed14e1db0832 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1025,8 +1025,9 @@ struct ext4_super_block {
+ 	__le32	s_last_error_line;	/* line number where error happened */
+ 	__le64	s_last_error_block;	/* block involved of last error */
+ 	__u8	s_last_error_func[32];	/* function where the error happened */
+-#define EXT4_S_ERR_END offsetof(struct ext4_super_block, s_reserved)
+-	__le32   s_reserved[128];        /* Padding to the end of the block */
++#define EXT4_S_ERR_END offsetof(struct ext4_super_block, s_mount_opts)
++	__u8	s_mount_opts[64];
++	__le32	s_reserved[112];        /* Padding to the end of the block */
+ };
+ 
+ #define EXT4_S_ERR_LEN (EXT4_S_ERR_END - EXT4_S_ERR_START)
+@@ -1341,6 +1342,10 @@ EXT4_INODE_BIT_FNS(state, state_flags)
+ #define EXT4_DEFM_JMODE_DATA	0x0020
+ #define EXT4_DEFM_JMODE_ORDERED	0x0040
+ #define EXT4_DEFM_JMODE_WBACK	0x0060
++#define EXT4_DEFM_NOBARRIER	0x0100
++#define EXT4_DEFM_BLOCK_VALIDITY 0x0200
++#define EXT4_DEFM_DISCARD	0x0400
++#define EXT4_DEFM_NODELALLOC	0x0800
+ 
+ /*
+  * Default journal batch times
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 3e3f6484c223..3fd65eb66ccd 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1003,10 +1003,10 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
+ 		seq_puts(seq, ",journal_checksum");
+ 	if (test_opt(sb, I_VERSION))
+ 		seq_puts(seq, ",i_version");
+-	if (!test_opt(sb, DELALLOC))
++	if (!test_opt(sb, DELALLOC) &&
++	    !(def_mount_opts & EXT4_DEFM_NODELALLOC))
+ 		seq_puts(seq, ",nodelalloc");
+ 
+-
+ 	if (sbi->s_stripe)
+ 		seq_printf(seq, ",stripe=%lu", sbi->s_stripe);
+ 	/*
+@@ -1030,7 +1030,7 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
+ 	if (test_opt(sb, NO_AUTO_DA_ALLOC))
+ 		seq_puts(seq, ",noauto_da_alloc");
+ 
+-	if (test_opt(sb, DISCARD))
++	if (test_opt(sb, DISCARD) && !(def_mount_opts & EXT4_DEFM_DISCARD))
+ 		seq_puts(seq, ",discard");
+ 
+ 	if (test_opt(sb, NOLOAD))
+@@ -1039,6 +1039,10 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
+ 	if (test_opt(sb, DIOREAD_NOLOCK))
+ 		seq_puts(seq, ",dioread_nolock");
+ 
++	if (test_opt(sb, BLOCK_VALIDITY) &&
++	    !(def_mount_opts & EXT4_DEFM_BLOCK_VALIDITY))
++		seq_puts(seq, ",block_validity");
++
+ 	ext4_show_quota_options(seq, sb);
+ 
+ 	return 0;
+@@ -2655,6 +2659,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		set_opt(sbi->s_mount_opt, ERRORS_CONT);
+ 	else
+ 		set_opt(sbi->s_mount_opt, ERRORS_RO);
++	if (def_mount_opts & EXT4_DEFM_BLOCK_VALIDITY)
++		set_opt(sbi->s_mount_opt, BLOCK_VALIDITY);
++	if (def_mount_opts & EXT4_DEFM_DISCARD)
++		set_opt(sbi->s_mount_opt, DISCARD);
+ 
+ 	sbi->s_resuid = le16_to_cpu(es->s_def_resuid);
+ 	sbi->s_resgid = le16_to_cpu(es->s_def_resgid);
+@@ -2662,15 +2670,23 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	sbi->s_min_batch_time = EXT4_DEF_MIN_BATCH_TIME;
+ 	sbi->s_max_batch_time = EXT4_DEF_MAX_BATCH_TIME;
+ 
+-	set_opt(sbi->s_mount_opt, BARRIER);
++	if ((def_mount_opts & EXT4_DEFM_NOBARRIER) == 0)
++		set_opt(sbi->s_mount_opt, BARRIER);
+ 
+ 	/*
+ 	 * enable delayed allocation by default
+ 	 * Use -o nodelalloc to turn it off
+ 	 */
+-	if (!IS_EXT3_SB(sb))
++	if (!IS_EXT3_SB(sb) &&
++	    ((def_mount_opts & EXT4_DEFM_NODELALLOC) == 0))
+ 		set_opt(sbi->s_mount_opt, DELALLOC);
+ 
++	if (!parse_options((char *) sbi->s_es->s_mount_opts, sb,
++			   &journal_devnum, &journal_ioprio, NULL, 0)) {
++		ext4_msg(sb, KERN_WARNING,
++			 "failed to parse options in superblock: %s",
++			 sbi->s_es->s_mount_opts);
++	}
+ 	if (!parse_options((char *) data, sb, &journal_devnum,
+ 			   &journal_ioprio, NULL, 0))
+ 		goto failed_mount;
+@@ -3141,7 +3157,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		descr = "out journal";
+ 
+ 	ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. "
+-		"Opts: %s", descr, orig_data);
++		 "Opts: %s%s%s", descr, sbi->s_es->s_mount_opts,
++		 *sbi->s_es->s_mount_opts ? "; " : "", orig_data);
+ 
+ 	init_timer(&sbi->s_err_report);
+ 	sbi->s_err_report.function = print_daily_error_info;

commit 4538821993f4486c76090dfb377c60c0a0e71ba3
+Author: Theodore Ts'o 
+Date:   Thu Jul 29 15:06:10 2010 -0400
+
+    ext4: drop inode from orphan list if ext4_delete_inode() fails
+    
+    There were some error paths in ext4_delete_inode() which was not
+    dropping the inode from the orphan list.  This could lead to a BUG_ON
+    on umount when the orphan list is discovered to be non-empty.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index a52d5af99187..533b607f9cb5 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -221,6 +221,7 @@ void ext4_delete_inode(struct inode *inode)
+ 				     "couldn't extend journal (err %d)", err);
+ 		stop_handle:
+ 			ext4_journal_stop(handle);
++			ext4_orphan_del(NULL, inode);
+ 			goto no_delete;
+ 		}
+ 	}

commit f613dfcb3345dacb8cf99b7bb359acc1c18a1157
+Author: Theodore Ts'o 
+Date:   Tue Jul 27 11:56:08 2010 -0400
+
+    ext4: check to make make sure bd_dev is set before dereferencing it
+    
+    There are some drivers which may not set bdev->bd_dev.  So make sure
+    it is non-NULL before dereferencing it.
+    
+    Google-Bug-Id: 1773557
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index c1036bc8a539..e046eba24782 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2304,6 +2304,8 @@ static ssize_t session_write_kbytes_show(struct ext4_attr *a,
+ {
+ 	struct super_block *sb = sbi->s_buddy_cache->i_sb;
+ 
++	if (!sb->s_bdev->bd_part)
++		return snprintf(buf, PAGE_SIZE, "0\n");
+ 	return snprintf(buf, PAGE_SIZE, "%lu\n",
+ 			(part_stat_read(sb->s_bdev->bd_part, sectors[1]) -
+ 			 sbi->s_sectors_written_start) >> 1);
+@@ -2314,6 +2316,8 @@ static ssize_t lifetime_write_kbytes_show(struct ext4_attr *a,
+ {
+ 	struct super_block *sb = sbi->s_buddy_cache->i_sb;
+ 
++	if (!sb->s_bdev->bd_part)
++		return snprintf(buf, PAGE_SIZE, "0\n");
+ 	return snprintf(buf, PAGE_SIZE, "%llu\n",
+ 			(unsigned long long)(sbi->s_kbytes_written +
+ 			((part_stat_read(sb->s_bdev->bd_part, sectors[1]) -
+@@ -2575,8 +2579,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	sbi->s_resgid = EXT4_DEF_RESGID;
+ 	sbi->s_inode_readahead_blks = EXT4_DEF_INODE_READAHEAD_BLKS;
+ 	sbi->s_sb_block = sb_block;
+-	sbi->s_sectors_written_start = part_stat_read(sb->s_bdev->bd_part,
+-						      sectors[1]);
++	if (sb->s_bdev->bd_part)
++		sbi->s_sectors_written_start =
++			part_stat_read(sb->s_bdev->bd_part, sectors[1]);
+ 
+ 	unlock_kernel();
+ 
+@@ -3492,10 +3497,14 @@ static int ext4_commit_super(struct super_block *sb, int sync)
+ 	 */
+ 	if (!(sb->s_flags & MS_RDONLY))
+ 		es->s_wtime = cpu_to_le32(get_seconds());
+-	es->s_kbytes_written =
+-		cpu_to_le64(EXT4_SB(sb)->s_kbytes_written +
++	if (sb->s_bdev->bd_part)
++		es->s_kbytes_written =
++			cpu_to_le64(EXT4_SB(sb)->s_kbytes_written +
+ 			    ((part_stat_read(sb->s_bdev->bd_part, sectors[1]) -
+ 			      EXT4_SB(sb)->s_sectors_written_start) >> 1));
++	else
++		es->s_kbytes_written =
++			cpu_to_le64(EXT4_SB(sb)->s_kbytes_written);
+ 	ext4_free_blocks_count_set(es, percpu_counter_sum_positive(
+ 					&EXT4_SB(sb)->s_freeblocks_counter));
+ 	es->s_free_inodes_count = cpu_to_le32(percpu_counter_sum_positive(

commit 0c095c7f113e9fd05913d6e1b2cccbe356be039e
+Author: Theodore Ts'o 
+Date:   Tue Jul 27 11:56:06 2010 -0400
+
+    ext4: Don't error out the fs if the user tries to make a file too big
+    
+    If the user attempts to make a non-extent-mapped file to be too large,
+    return EFBIG, but don't call ext4_std_err() which will end up marking
+    the file system as containing an error.
+    
+    Thanks to Toshiyuki Okajima-san at Fujitsu for pointing this out.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 46d2079373c9..38ec77fc3279 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -5472,10 +5472,8 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
+ 		if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) {
+ 			struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+ 
+-			if (attr->ia_size > sbi->s_bitmap_maxbytes) {
+-				error = -EFBIG;
+-				goto err_out;
+-			}
++			if (attr->ia_size > sbi->s_bitmap_maxbytes)
++				return -EFBIG;
+ 		}
+ 	}
+ 

commit 47def82672b3ba4e7c5e9a4fe48a556f8684d0d6
+Author: Theodore Ts'o 
+Date:   Tue Jul 27 11:56:05 2010 -0400
+
+    jbd2: Remove __GFP_NOFAIL from jbd2 layer
+    
+    __GFP_NOFAIL is going away, so add our own retry loop.  Also add
+    jbd2__journal_start() and jbd2__journal_restart() which take a gfp
+    mask, so that file systems can optionally (re)start transaction
+    handles using GFP_KERNEL.  If they do this, then they need to be
+    prepared to handle receiving an PTR_ERR(-ENOMEM) error, and be ready
+    to reflect that error up to userspace.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index f7bf15787d68..a79d3345b55a 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -41,6 +41,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #define CREATE_TRACE_POINTS
+ #include 
+@@ -48,8 +49,6 @@
+ #include 
+ #include 
+ 
+-EXPORT_SYMBOL(jbd2_journal_start);
+-EXPORT_SYMBOL(jbd2_journal_restart);
+ EXPORT_SYMBOL(jbd2_journal_extend);
+ EXPORT_SYMBOL(jbd2_journal_stop);
+ EXPORT_SYMBOL(jbd2_journal_lock_updates);
+@@ -311,7 +310,17 @@ int jbd2_journal_write_metadata_buffer(transaction_t *transaction,
+ 	 */
+ 	J_ASSERT_BH(bh_in, buffer_jbddirty(bh_in));
+ 
+-	new_bh = alloc_buffer_head(GFP_NOFS|__GFP_NOFAIL);
++retry_alloc:
++	new_bh = alloc_buffer_head(GFP_NOFS);
++	if (!new_bh) {
++		/*
++		 * Failure is not an option, but __GFP_NOFAIL is going
++		 * away; so we retry ourselves here.
++		 */
++		congestion_wait(BLK_RW_ASYNC, HZ/50);
++		goto retry_alloc;
++	}
++
+ 	/* keep subsequent assertions sane */
+ 	new_bh->b_state = 0;
+ 	init_buffer(new_bh, NULL, NULL);
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index e214d68620ac..001e95fb0fe1 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -26,6 +26,8 @@
+ #include 
+ #include 
+ #include 
++#include 
++#include 
+ 
+ static void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh);
+ 
+@@ -83,30 +85,38 @@ jbd2_get_transaction(journal_t *journal, transaction_t *transaction)
+  * transaction's buffer credits.
+  */
+ 
+-static int start_this_handle(journal_t *journal, handle_t *handle)
++static int start_this_handle(journal_t *journal, handle_t *handle,
++			     int gfp_mask)
+ {
+ 	transaction_t *transaction;
+ 	int needed;
+ 	int nblocks = handle->h_buffer_credits;
+ 	transaction_t *new_transaction = NULL;
+-	int ret = 0;
+ 	unsigned long ts = jiffies;
+ 
+ 	if (nblocks > journal->j_max_transaction_buffers) {
+ 		printk(KERN_ERR "JBD: %s wants too many credits (%d > %d)\n",
+ 		       current->comm, nblocks,
+ 		       journal->j_max_transaction_buffers);
+-		ret = -ENOSPC;
+-		goto out;
++		return -ENOSPC;
+ 	}
+ 
+ alloc_transaction:
+ 	if (!journal->j_running_transaction) {
+-		new_transaction = kzalloc(sizeof(*new_transaction),
+-						GFP_NOFS|__GFP_NOFAIL);
++		new_transaction = kzalloc(sizeof(*new_transaction), gfp_mask);
+ 		if (!new_transaction) {
+-			ret = -ENOMEM;
+-			goto out;
++			/*
++			 * If __GFP_FS is not present, then we may be
++			 * being called from inside the fs writeback
++			 * layer, so we MUST NOT fail.  Since
++			 * __GFP_NOFAIL is going away, we will arrange
++			 * to retry the allocation ourselves.
++			 */
++			if ((gfp_mask & __GFP_FS) == 0) {
++				congestion_wait(BLK_RW_ASYNC, HZ/50);
++				goto alloc_transaction;
++			}
++			return -ENOMEM;
+ 		}
+ 	}
+ 
+@@ -123,8 +133,8 @@ static int start_this_handle(journal_t *journal, handle_t *handle)
+ 	if (is_journal_aborted(journal) ||
+ 	    (journal->j_errno != 0 && !(journal->j_flags & JBD2_ACK_ERR))) {
+ 		spin_unlock(&journal->j_state_lock);
+-		ret = -EROFS;
+-		goto out;
++		kfree(new_transaction);
++		return -EROFS;
+ 	}
+ 
+ 	/* Wait on the journal's transaction barrier if necessary */
+@@ -240,10 +250,8 @@ static int start_this_handle(journal_t *journal, handle_t *handle)
+ 	spin_unlock(&journal->j_state_lock);
+ 
+ 	lock_map_acquire(&handle->h_lockdep_map);
+-out:
+-	if (unlikely(new_transaction))		/* It's usually NULL */
+-		kfree(new_transaction);
+-	return ret;
++	kfree(new_transaction);
++	return 0;
+ }
+ 
+ static struct lock_class_key jbd2_handle_key;
+@@ -278,7 +286,7 @@ static handle_t *new_handle(int nblocks)
+  *
+  * Return a pointer to a newly allocated handle, or NULL on failure
+  */
+-handle_t *jbd2_journal_start(journal_t *journal, int nblocks)
++handle_t *jbd2__journal_start(journal_t *journal, int nblocks, int gfp_mask)
+ {
+ 	handle_t *handle = journal_current_handle();
+ 	int err;
+@@ -298,7 +306,7 @@ handle_t *jbd2_journal_start(journal_t *journal, int nblocks)
+ 
+ 	current->journal_info = handle;
+ 
+-	err = start_this_handle(journal, handle);
++	err = start_this_handle(journal, handle, gfp_mask);
+ 	if (err < 0) {
+ 		jbd2_free_handle(handle);
+ 		current->journal_info = NULL;
+@@ -308,6 +316,15 @@ handle_t *jbd2_journal_start(journal_t *journal, int nblocks)
+ out:
+ 	return handle;
+ }
++EXPORT_SYMBOL(jbd2__journal_start);
++
++
++handle_t *jbd2_journal_start(journal_t *journal, int nblocks)
++{
++	return jbd2__journal_start(journal, nblocks, GFP_NOFS);
++}
++EXPORT_SYMBOL(jbd2_journal_start);
++
+ 
+ /**
+  * int jbd2_journal_extend() - extend buffer credits.
+@@ -394,8 +411,7 @@ int jbd2_journal_extend(handle_t *handle, int nblocks)
+  * transaction capabable of guaranteeing the requested number of
+  * credits.
+  */
+-
+-int jbd2_journal_restart(handle_t *handle, int nblocks)
++int jbd2__journal_restart(handle_t *handle, int nblocks, int gfp_mask)
+ {
+ 	transaction_t *transaction = handle->h_transaction;
+ 	journal_t *journal = transaction->t_journal;
+@@ -428,10 +444,17 @@ int jbd2_journal_restart(handle_t *handle, int nblocks)
+ 
+ 	lock_map_release(&handle->h_lockdep_map);
+ 	handle->h_buffer_credits = nblocks;
+-	ret = start_this_handle(journal, handle);
++	ret = start_this_handle(journal, handle, gfp_mask);
+ 	return ret;
+ }
++EXPORT_SYMBOL(jbd2__journal_restart);
++
+ 
++int jbd2_journal_restart(handle_t *handle, int nblocks)
++{
++	return jbd2__journal_restart(handle, nblocks, GFP_NOFS);
++}
++EXPORT_SYMBOL(jbd2_journal_restart);
+ 
+ /**
+  * void jbd2_journal_lock_updates () - establish a transaction barrier.
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index a4d2e9f7088a..5a72bc75b273 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -1081,7 +1081,9 @@ static inline handle_t *journal_current_handle(void)
+  */
+ 
+ extern handle_t *jbd2_journal_start(journal_t *, int nblocks);
+-extern int	 jbd2_journal_restart (handle_t *, int nblocks);
++extern handle_t *jbd2__journal_start(journal_t *, int nblocks, int gfp_mask);
++extern int	 jbd2_journal_restart(handle_t *, int nblocks);
++extern int	 jbd2__journal_restart(handle_t *, int nblocks, int gfp_mask);
+ extern int	 jbd2_journal_extend (handle_t *, int nblocks);
+ extern int	 jbd2_journal_get_write_access(handle_t *, struct buffer_head *);
+ extern int	 jbd2_journal_get_create_access (handle_t *, struct buffer_head *);

commit e5880d76aea443b04e07da19830da0f6f7494eef
+Author: Theodore Ts'o 
+Date:   Tue Jul 27 11:56:04 2010 -0400
+
+    ext4: fix potential NULL dereference while tracing
+    
+    The allocation_context pointer can be NULL.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 3dfad95f0f98..8b3b9344a595 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -3575,7 +3575,7 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh,
+ 			trace_ext4_mballoc_discard(ac);
+ 		}
+ 
+-		trace_ext4_mb_release_inode_pa(ac, pa, grp_blk_start + bit,
++		trace_ext4_mb_release_inode_pa(sb, ac, pa, grp_blk_start + bit,
+ 					       next - bit);
+ 		mb_free_blocks(pa->pa_inode, e4b, bit, next - bit);
+ 		bit = next + 1;
+@@ -3606,7 +3606,7 @@ ext4_mb_release_group_pa(struct ext4_buddy *e4b,
+ 	ext4_group_t group;
+ 	ext4_grpblk_t bit;
+ 
+-	trace_ext4_mb_release_group_pa(ac, pa);
++	trace_ext4_mb_release_group_pa(sb, ac, pa);
+ 	BUG_ON(pa->pa_deleted == 0);
+ 	ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit);
+ 	BUG_ON(group != e4b->bd_group && pa->pa_len != 0);
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index f3865c7b4166..01e9e0076a92 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -395,11 +395,12 @@ DEFINE_EVENT(ext4__mb_new_pa, ext4_mb_new_group_pa,
+ );
+ 
+ TRACE_EVENT(ext4_mb_release_inode_pa,
+-	TP_PROTO(struct ext4_allocation_context *ac,
++	TP_PROTO(struct super_block *sb,
++		 struct ext4_allocation_context *ac,
+ 		 struct ext4_prealloc_space *pa,
+ 		 unsigned long long block, unsigned int count),
+ 
+-	TP_ARGS(ac, pa, block, count),
++	TP_ARGS(sb, ac, pa, block, count),
+ 
+ 	TP_STRUCT__entry(
+ 		__field(	dev_t,	dev			)
+@@ -410,8 +411,9 @@ TRACE_EVENT(ext4_mb_release_inode_pa,
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev		= ac->ac_sb->s_dev;
+-		__entry->ino		= ac->ac_inode->i_ino;
++		__entry->dev		= sb->s_dev;
++		__entry->ino		= (ac && ac->ac_inode) ? 
++						ac->ac_inode->i_ino : 0;
+ 		__entry->block		= block;
+ 		__entry->count		= count;
+ 	),
+@@ -422,10 +424,11 @@ TRACE_EVENT(ext4_mb_release_inode_pa,
+ );
+ 
+ TRACE_EVENT(ext4_mb_release_group_pa,
+-	TP_PROTO(struct ext4_allocation_context *ac,
++	TP_PROTO(struct super_block *sb,
++		 struct ext4_allocation_context *ac,
+ 		 struct ext4_prealloc_space *pa),
+ 
+-	TP_ARGS(ac, pa),
++	TP_ARGS(sb, ac, pa),
+ 
+ 	TP_STRUCT__entry(
+ 		__field(	dev_t,	dev			)
+@@ -436,8 +439,9 @@ TRACE_EVENT(ext4_mb_release_group_pa,
+ 	),
+ 
+ 	TP_fast_assign(
+-		__entry->dev		= ac->ac_sb->s_dev;
+-		__entry->ino		= ac->ac_inode->i_ino;
++		__entry->dev		= sb->s_dev;
++		__entry->ino		= (ac && ac->ac_inode) ?
++						ac->ac_inode->i_ino : 0;
+ 		__entry->pa_pstart	= pa->pa_pstart;
+ 		__entry->pa_len		= pa->pa_len;
+ 	),

commit 89eeddf03327e19cfcbb18efa98e5470e2f5c563
+Author: Theodore Ts'o 
+Date:   Tue Jul 27 11:56:04 2010 -0400
+
+    ext4: Define s_jnl_backup_type in superblock
+    
+    This has been in use by e2fsprogs for a while; define it to keep the
+    super block fields in sync.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 5d3d768d9503..4c7d4727d6ba 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -984,7 +984,7 @@ struct ext4_super_block {
+ 	__le32	s_last_orphan;		/* start of list of inodes to delete */
+ 	__le32	s_hash_seed[4];		/* HTREE hash seed */
+ 	__u8	s_def_hash_version;	/* Default hash version to use */
+-	__u8	s_reserved_char_pad;
++	__u8	s_jnl_backup_type;
+ 	__le16  s_desc_size;		/* size of group descriptor */
+ /*100*/	__le32	s_default_mount_opts;
+ 	__le32	s_first_meta_bg;	/* First metablock block group */
+@@ -1002,7 +1002,7 @@ struct ext4_super_block {
+ 	__le64  s_mmp_block;            /* Block for multi-mount protection */
+ 	__le32  s_raid_stripe_width;    /* blocks on all data disks (N*stride)*/
+ 	__u8	s_log_groups_per_flex;  /* FLEX_BG group size */
+-	__u8	s_reserved_char_pad2;
++	__u8	s_reserved_char_pad;
+ 	__le16  s_reserved_pad;
+ 	__le64	s_kbytes_written;	/* nr of lifetime kilobytes written */
+ 	__le32	s_snapshot_inum;	/* Inode number of active snapshot */

commit 66e61a9e9504f61b9a928c9055368c81da613a50
+Author: Theodore Ts'o 
+Date:   Tue Jul 27 11:56:04 2010 -0400
+
+    ext4: Once a day, printk file system error information to dmesg
+    
+    This allows us to grab any file system error messages by scraping
+    /var/log/messages.  This will make it easy for us to do error analysis
+    across the very large number of machines as we deploy ext4 across the
+    fleet.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 6b96125e7255..5d3d768d9503 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1166,6 +1166,9 @@ struct ext4_sb_info {
+ 
+ 	/* workqueue for dio unwritten */
+ 	struct workqueue_struct *dio_unwritten_wq;
++
++	/* timer for periodic error stats printing */
++	struct timer_list s_err_report;
+ };
+ 
+ static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb)
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index a94d3f56898f..ed00c14d7081 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -325,6 +325,12 @@ static void __save_error_info(struct super_block *sb, const char *func,
+ 		es->s_first_error_ino = es->s_last_error_ino;
+ 		es->s_first_error_block = es->s_last_error_block;
+ 	}
++	/*
++	 * Start the daily error reporting function if it hasn't been
++	 * started already
++	 */
++	if (!es->s_error_count)
++		mod_timer(&EXT4_SB(sb)->s_err_report, jiffies + 24*60*60*HZ);
+ 	es->s_error_count = cpu_to_le32(le32_to_cpu(es->s_error_count) + 1);
+ }
+ 
+@@ -2480,6 +2486,53 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly)
+ 	return 1;
+ }
+ 
++/*
++ * This function is called once a day if we have errors logged
++ * on the file system
++ */
++static void print_daily_error_info(unsigned long arg)
++{
++	struct super_block *sb = (struct super_block *) arg;
++	struct ext4_sb_info *sbi;
++	struct ext4_super_block *es;
++
++	sbi = EXT4_SB(sb);
++	es = sbi->s_es;
++
++	if (es->s_error_count)
++		ext4_msg(sb, KERN_NOTICE, "error count: %u",
++			 le32_to_cpu(es->s_error_count));
++	if (es->s_first_error_time) {
++		printk(KERN_NOTICE "EXT4-fs (%s): initial error at %u: %.*s:%d",
++		       sb->s_id, le32_to_cpu(es->s_first_error_time),
++		       (int) sizeof(es->s_first_error_func),
++		       es->s_first_error_func,
++		       le32_to_cpu(es->s_first_error_line));
++		if (es->s_first_error_ino)
++			printk(": inode %u",
++			       le32_to_cpu(es->s_first_error_ino));
++		if (es->s_first_error_block)
++			printk(": block %llu", (unsigned long long)
++			       le64_to_cpu(es->s_first_error_block));
++		printk("\n");
++	}
++	if (es->s_last_error_time) {
++		printk(KERN_NOTICE "EXT4-fs (%s): last error at %u: %.*s:%d",
++		       sb->s_id, le32_to_cpu(es->s_last_error_time),
++		       (int) sizeof(es->s_last_error_func),
++		       es->s_last_error_func,
++		       le32_to_cpu(es->s_last_error_line));
++		if (es->s_last_error_ino)
++			printk(": inode %u",
++			       le32_to_cpu(es->s_last_error_ino));
++		if (es->s_last_error_block)
++			printk(": block %llu", (unsigned long long)
++			       le64_to_cpu(es->s_last_error_block));
++		printk("\n");
++	}
++	mod_timer(&sbi->s_err_report, jiffies + 24*60*60*HZ);  /* Once a day */
++}
++
+ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 				__releases(kernel_lock)
+ 				__acquires(kernel_lock)
+@@ -3083,6 +3136,12 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. "
+ 		"Opts: %s", descr, orig_data);
+ 
++	init_timer(&sbi->s_err_report);
++	sbi->s_err_report.function = print_daily_error_info;
++	sbi->s_err_report.data = (unsigned long) sb;
++	if (es->s_error_count)
++		mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */
++
+ 	lock_kernel();
+ 	kfree(orig_data);
+ 	return 0;

commit 1c13d5c0872870cca3e612aa045d492ead9ab004
+Author: Theodore Ts'o 
+Date:   Tue Jul 27 11:56:03 2010 -0400
+
+    ext4: Save error information to the superblock for analysis
+    
+    Save number of file system errors, and the time function name, line
+    number, block number, and inode number of the first and most recent
+    errors reported on the file system in the superblock.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/block_validity.c b/fs/ext4/block_validity.c
+index 5b6973fbf1bd..3db5084db9bd 100644
+--- a/fs/ext4/block_validity.c
++++ b/fs/ext4/block_validity.c
+@@ -229,16 +229,20 @@ int ext4_data_block_valid(struct ext4_sb_info *sbi, ext4_fsblk_t start_blk,
+ 
+ 	if ((start_blk <= le32_to_cpu(sbi->s_es->s_first_data_block)) ||
+ 	    (start_blk + count < start_blk) ||
+-	    (start_blk + count > ext4_blocks_count(sbi->s_es)))
++	    (start_blk + count > ext4_blocks_count(sbi->s_es))) {
++		sbi->s_es->s_last_error_block = cpu_to_le64(start_blk);
+ 		return 0;
++	}
+ 	while (n) {
+ 		entry = rb_entry(n, struct ext4_system_zone, node);
+ 		if (start_blk + count - 1 < entry->start_blk)
+ 			n = n->rb_left;
+ 		else if (start_blk >= (entry->start_blk + entry->count))
+ 			n = n->rb_right;
+-		else
++		else {
++			sbi->s_es->s_last_error_block = cpu_to_le64(start_blk);
+ 			return 0;
++		}
+ 	}
+ 	return 1;
+ }
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 088938148f5c..6b96125e7255 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1011,9 +1011,24 @@ struct ext4_super_block {
+ 					      snapshot's future use */
+ 	__le32	s_snapshot_list;	/* inode number of the head of the
+ 					   on-disk snapshot list */
+-	__u32   s_reserved[155];        /* Padding to the end of the block */
++#define EXT4_S_ERR_START offsetof(struct ext4_super_block, s_error_count)
++	__le32	s_error_count;		/* number of fs errors */
++	__le32	s_first_error_time;	/* first time an error happened */
++	__le32	s_first_error_ino;	/* inode involved in first error */
++	__le64	s_first_error_block;	/* block involved of first error */
++	__u8	s_first_error_func[32];	/* function where the error happened */
++	__le32	s_first_error_line;	/* line number where error happened */
++	__le32	s_last_error_time;	/* most recent time of an error */
++	__le32	s_last_error_ino;	/* inode involved in last error */
++	__le32	s_last_error_line;	/* line number where error happened */
++	__le64	s_last_error_block;	/* block involved of last error */
++	__u8	s_last_error_func[32];	/* function where the error happened */
++#define EXT4_S_ERR_END offsetof(struct ext4_super_block, s_reserved)
++	__le32   s_reserved[128];        /* Padding to the end of the block */
+ };
+ 
++#define EXT4_S_ERR_LEN (EXT4_S_ERR_END - EXT4_S_ERR_START)
++
+ #ifdef __KERNEL__
+ 
+ /*
+diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
+index 23425cd68daa..6e272ef6ba96 100644
+--- a/fs/ext4/ext4_jbd2.c
++++ b/fs/ext4/ext4_jbd2.c
+@@ -134,6 +134,11 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
+ 		if (inode && inode_needs_sync(inode)) {
+ 			sync_dirty_buffer(bh);
+ 			if (buffer_req(bh) && !buffer_uptodate(bh)) {
++				struct ext4_super_block *es;
++
++				es = EXT4_SB(inode->i_sb)->s_es;
++				es->s_last_error_block =
++					cpu_to_le64(bh->b_blocknr);
+ 				ext4_error_inode(inode, where, line,
+ 						 bh->b_blocknr,
+ 					"IO error syncing itable block");
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 69ea663ef03e..755ba8682233 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -341,6 +341,7 @@ static int __ext4_check_blockref(const char *function, unsigned int line,
+ 				 struct inode *inode,
+ 				 __le32 *p, unsigned int max)
+ {
++	struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
+ 	__le32 *bref = p;
+ 	unsigned int blk;
+ 
+@@ -349,6 +350,7 @@ static int __ext4_check_blockref(const char *function, unsigned int line,
+ 		if (blk &&
+ 		    unlikely(!ext4_data_block_valid(EXT4_SB(inode->i_sb),
+ 						    blk, 1))) {
++			es->s_last_error_block = cpu_to_le64(blk);
+ 			ext4_error_inode(inode, function, line, blk,
+ 					 "invalid block");
+ 			return -EIO;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index bcf74b31d014..a94d3f56898f 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -307,6 +307,35 @@ void ext4_journal_abort_handle(const char *caller, unsigned int line,
+ 	jbd2_journal_abort_handle(handle);
+ }
+ 
++static void __save_error_info(struct super_block *sb, const char *func,
++			    unsigned int line)
++{
++	struct ext4_super_block *es = EXT4_SB(sb)->s_es;
++
++	EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
++	es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
++	es->s_last_error_time = cpu_to_le32(get_seconds());
++	strncpy(es->s_last_error_func, func, sizeof(es->s_last_error_func));
++	es->s_last_error_line = cpu_to_le32(line);
++	if (!es->s_first_error_time) {
++		es->s_first_error_time = es->s_last_error_time;
++		strncpy(es->s_first_error_func, func,
++			sizeof(es->s_first_error_func));
++		es->s_first_error_line = cpu_to_le32(line);
++		es->s_first_error_ino = es->s_last_error_ino;
++		es->s_first_error_block = es->s_last_error_block;
++	}
++	es->s_error_count = cpu_to_le32(le32_to_cpu(es->s_error_count) + 1);
++}
++
++static void save_error_info(struct super_block *sb, const char *func,
++			    unsigned int line)
++{
++	__save_error_info(sb, func, line);
++	ext4_commit_super(sb, 1);
++}
++
++
+ /* Deal with the reporting of failure conditions on a filesystem such as
+  * inconsistencies detected or read IO failures.
+  *
+@@ -324,11 +353,6 @@ void ext4_journal_abort_handle(const char *caller, unsigned int line,
+ 
+ static void ext4_handle_error(struct super_block *sb)
+ {
+-	struct ext4_super_block *es = EXT4_SB(sb)->s_es;
+-
+-	EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
+-	es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
+-
+ 	if (sb->s_flags & MS_RDONLY)
+ 		return;
+ 
+@@ -343,7 +367,6 @@ static void ext4_handle_error(struct super_block *sb)
+ 		ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
+ 		sb->s_flags |= MS_RDONLY;
+ 	}
+-	ext4_commit_super(sb, 1);
+ 	if (test_opt(sb, ERRORS_PANIC))
+ 		panic("EXT4-fs (device %s): panic forced after error\n",
+ 			sb->s_id);
+@@ -369,7 +392,11 @@ void ext4_error_inode(struct inode *inode, const char *function,
+ 		      const char *fmt, ...)
+ {
+ 	va_list args;
++	struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
+ 
++	es->s_last_error_ino = cpu_to_le32(inode->i_ino);
++	es->s_last_error_block = cpu_to_le64(block);
++	save_error_info(inode->i_sb, function, line);
+ 	va_start(args, fmt);
+ 	printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: inode #%lu: ",
+ 	       inode->i_sb->s_id, function, line, inode->i_ino);
+@@ -387,9 +414,13 @@ void ext4_error_file(struct file *file, const char *function,
+ 		     unsigned int line, const char *fmt, ...)
+ {
+ 	va_list args;
++	struct ext4_super_block *es;
+ 	struct inode *inode = file->f_dentry->d_inode;
+ 	char pathname[80], *path;
+ 
++	es = EXT4_SB(inode->i_sb)->s_es;
++	es->s_last_error_ino = cpu_to_le32(inode->i_ino);
++	save_error_info(inode->i_sb, function, line);
+ 	va_start(args, fmt);
+ 	path = d_path(&(file->f_path), pathname, sizeof(pathname));
+ 	if (!path)
+@@ -459,6 +490,7 @@ void __ext4_std_error(struct super_block *sb, const char *function,
+ 	errstr = ext4_decode_error(sb, errno, nbuf);
+ 	printk(KERN_CRIT "EXT4-fs error (device %s) in %s:%d: %s\n",
+ 	       sb->s_id, function, line, errstr);
++	save_error_info(sb, function, line);
+ 
+ 	ext4_handle_error(sb);
+ }
+@@ -478,6 +510,7 @@ void __ext4_abort(struct super_block *sb, const char *function,
+ {
+ 	va_list args;
+ 
++	save_error_info(sb, function, line);
+ 	va_start(args, fmt);
+ 	printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: ", sb->s_id,
+ 	       function, line);
+@@ -485,18 +518,16 @@ void __ext4_abort(struct super_block *sb, const char *function,
+ 	printk("\n");
+ 	va_end(args);
+ 
++	if ((sb->s_flags & MS_RDONLY) == 0) {
++		ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
++		sb->s_flags |= MS_RDONLY;
++		EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED;
++		if (EXT4_SB(sb)->s_journal)
++			jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO);
++		save_error_info(sb, function, line);
++	}
+ 	if (test_opt(sb, ERRORS_PANIC))
+ 		panic("EXT4-fs panic from previous error\n");
+-
+-	if (sb->s_flags & MS_RDONLY)
+-		return;
+-
+-	ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
+-	EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
+-	sb->s_flags |= MS_RDONLY;
+-	EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED;
+-	if (EXT4_SB(sb)->s_journal)
+-		jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO);
+ }
+ 
+ void ext4_msg (struct super_block * sb, const char *prefix,
+@@ -534,6 +565,9 @@ __acquires(bitlock)
+ 	va_list args;
+ 	struct ext4_super_block *es = EXT4_SB(sb)->s_es;
+ 
++	es->s_last_error_ino = cpu_to_le32(ino);
++	es->s_last_error_block = cpu_to_le64(block);
++	__save_error_info(sb, function, line);
+ 	va_start(args, fmt);
+ 	printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: group %u",
+ 	       sb->s_id, function, line, grp);
+@@ -546,11 +580,10 @@ __acquires(bitlock)
+ 	va_end(args);
+ 
+ 	if (test_opt(sb, ERRORS_CONT)) {
+-		EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
+-		es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
+ 		ext4_commit_super(sb, 0);
+ 		return;
+ 	}
++
+ 	ext4_unlock_group(sb, grp);
+ 	ext4_handle_error(sb);
+ 	/*
+@@ -3332,8 +3365,17 @@ static int ext4_load_journal(struct super_block *sb,
+ 
+ 	if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER))
+ 		err = jbd2_journal_wipe(journal, !really_read_only);
+-	if (!err)
++	if (!err) {
++		char *save = kmalloc(EXT4_S_ERR_LEN, GFP_KERNEL);
++		if (save)
++			memcpy(save, ((char *) es) +
++			       EXT4_S_ERR_START, EXT4_S_ERR_LEN);
+ 		err = jbd2_journal_load(journal);
++		if (save)
++			memcpy(((char *) es) + EXT4_S_ERR_START,
++			       save, EXT4_S_ERR_LEN);
++		kfree(save);
++	}
+ 
+ 	if (err) {
+ 		ext4_msg(sb, KERN_ERR, "error loading journal");

commit c398eda0e43a791be0fca6f197a1e2bbb9f16070
+Author: Theodore Ts'o 
+Date:   Tue Jul 27 11:56:40 2010 -0400
+
+    ext4: Pass line numbers to ext4_error() and friends
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index af581f08fe3a..62e8af04ed1e 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -84,11 +84,10 @@ int __ext4_check_dir_entry(const char *function, unsigned int line,
+ 		error_msg = "inode out of bounds";
+ 
+ 	if (error_msg != NULL)
+-		ext4_error_inode(function, dir,
+-			"bad entry in directory: %s - block=%llu"
++		ext4_error_inode(dir, function, line, bh->b_blocknr,
++			"bad entry in directory: %s - "
+ 			"offset=%u(%u), inode=%u, rec_len=%d, name_len=%d",
+-			error_msg, (unsigned long long) bh->b_blocknr,
+-			(unsigned) (offset%bh->b_size), offset,
++			error_msg, (unsigned) (offset%bh->b_size), offset,
+ 			le32_to_cpu(de->inode),
+ 			rlen, de->name_len);
+ 	return error_msg == NULL ? 1 : 0;
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 73465b26976d..088938148f5c 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -57,10 +57,13 @@
+ #endif
+ 
+ #define EXT4_ERROR_INODE(inode, fmt, a...) \
+-	ext4_error_inode(__func__, (inode), (fmt), ## a)
++	ext4_error_inode((inode), __func__, __LINE__, 0, (fmt), ## a)
++
++#define EXT4_ERROR_INODE_BLOCK(inode, block, fmt, a...)			\
++	ext4_error_inode((inode), __func__, __LINE__, (block), (fmt), ## a)
+ 
+ #define EXT4_ERROR_FILE(file, fmt, a...)	\
+-	ext4_error_file(__func__, (file), (fmt), ## a)
++	ext4_error_file(__func__, __LINE__, (file), (fmt), ## a)
+ 
+ /* data type for block offset of block group */
+ typedef int ext4_grpblk_t;
+@@ -1623,22 +1626,29 @@ extern int ext4_group_extend(struct super_block *sb,
+ 				ext4_fsblk_t n_blocks_count);
+ 
+ /* super.c */
+-extern void __ext4_error(struct super_block *, const char *, const char *, ...)
+-	__attribute__ ((format (printf, 3, 4)));
+-#define ext4_error(sb, message...)	__ext4_error(sb, __func__, ## message)
+-extern void ext4_error_inode(const char *, struct inode *, const char *, ...)
+-	__attribute__ ((format (printf, 3, 4)));
+-extern void ext4_error_file(const char *, struct file *, const char *, ...)
+-	__attribute__ ((format (printf, 3, 4)));
+-extern void __ext4_std_error(struct super_block *, const char *, int);
+-extern void __ext4_abort(struct super_block *, const char *, const char *, ...)
+-	__attribute__ ((format (printf, 3, 4)));
++extern void __ext4_error(struct super_block *, const char *, unsigned int,
++			 const char *, ...)
++	__attribute__ ((format (printf, 4, 5)));
++#define ext4_error(sb, message...)	__ext4_error(sb, __func__,	\
++						     __LINE__, ## message)
++extern void ext4_error_inode(struct inode *, const char *, unsigned int,
++			     ext4_fsblk_t, const char *, ...)
++	__attribute__ ((format (printf, 5, 6)));
++extern void ext4_error_file(struct file *, const char *, unsigned int,
++			    const char *, ...)
++	__attribute__ ((format (printf, 4, 5)));
++extern void __ext4_std_error(struct super_block *, const char *,
++			     unsigned int, int);
++extern void __ext4_abort(struct super_block *, const char *, unsigned int,
++		       const char *, ...)
++	__attribute__ ((format (printf, 4, 5)));
+ #define ext4_abort(sb, message...)	__ext4_abort(sb, __func__, \
+-						     ## message)
+-extern void __ext4_warning(struct super_block *, const char *,
++						       __LINE__, ## message)
++extern void __ext4_warning(struct super_block *, const char *, unsigned int,
+ 			  const char *, ...)
+-	__attribute__ ((format (printf, 3, 4)));
+-#define ext4_warning(sb, message...)	__ext4_warning(sb, __func__, ## message)
++	__attribute__ ((format (printf, 4, 5)));
++#define ext4_warning(sb, message...)	__ext4_warning(sb, __func__, \
++						       __LINE__, ## message)
+ extern void ext4_msg(struct super_block *, const char *, const char *, ...)
+ 	__attribute__ ((format (printf, 3, 4)));
+ extern void __ext4_grp_locked_error(const char *, unsigned int, \
+@@ -1781,7 +1791,7 @@ static inline unsigned int ext4_flex_bg_size(struct ext4_sb_info *sbi)
+ #define ext4_std_error(sb, errno)				\
+ do {								\
+ 	if ((errno))						\
+-		__ext4_std_error((sb), __func__, (errno));	\
++		__ext4_std_error((sb), __func__, __LINE__, (errno));	\
+ } while (0)
+ 
+ #ifdef CONFIG_SMP
+diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
+index 9de37b9e177a..23425cd68daa 100644
+--- a/fs/ext4/ext4_jbd2.c
++++ b/fs/ext4/ext4_jbd2.c
+@@ -94,8 +94,8 @@ int __ext4_forget(const char *where, unsigned int line, handle_t *handle,
+ 	if (err) {
+ 		ext4_journal_abort_handle(where, line, __func__,
+ 					  bh, handle, err);
+-		__ext4_abort(inode->i_sb, where,
+-			     "error %d when attempting revoke", err);
++		__ext4_abort(inode->i_sb, where, line,
++			   "error %d when attempting revoke", err);
+ 	}
+ 	BUFFER_TRACE(bh, "exit");
+ 	return err;
+@@ -134,11 +134,9 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
+ 		if (inode && inode_needs_sync(inode)) {
+ 			sync_dirty_buffer(bh);
+ 			if (buffer_req(bh) && !buffer_uptodate(bh)) {
+-				ext4_error(inode->i_sb,
+-					   "IO error syncing inode, "
+-					   "inode=%lu, block=%llu",
+-					   inode->i_ino,
+-					   (unsigned long long) bh->b_blocknr);
++				ext4_error_inode(inode, where, line,
++						 bh->b_blocknr,
++					"IO error syncing itable block");
+ 				err = -EIO;
+ 			}
+ 		}
+diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
+index 6883c6be5b8d..b0bd792c58c5 100644
+--- a/fs/ext4/ext4_jbd2.h
++++ b/fs/ext4/ext4_jbd2.h
+@@ -162,7 +162,7 @@ int __ext4_handle_dirty_super(const char *where, unsigned int line,
+ 	__ext4_handle_dirty_super(__func__, __LINE__, (handle), (sb))
+ 
+ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks);
+-int __ext4_journal_stop(const char *where, handle_t *handle);
++int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle);
+ 
+ #define EXT4_NOJOURNAL_MAX_REF_COUNT ((unsigned long) 4096)
+ 
+@@ -215,7 +215,7 @@ static inline handle_t *ext4_journal_start(struct inode *inode, int nblocks)
+ }
+ 
+ #define ext4_journal_stop(handle) \
+-	__ext4_journal_stop(__func__, (handle))
++	__ext4_journal_stop(__func__, __LINE__, (handle))
+ 
+ static inline handle_t *ext4_journal_current_handle(void)
+ {
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 346de3daab79..2c01d7391f1e 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -401,9 +401,9 @@ static int ext4_valid_extent_entries(struct inode *inode,
+ 	return 1;
+ }
+ 
+-static int __ext4_ext_check(const char *function, struct inode *inode,
+-					struct ext4_extent_header *eh,
+-					int depth)
++static int __ext4_ext_check(const char *function, unsigned int line,
++			    struct inode *inode, struct ext4_extent_header *eh,
++			    int depth)
+ {
+ 	const char *error_msg;
+ 	int max = 0;
+@@ -436,7 +436,7 @@ static int __ext4_ext_check(const char *function, struct inode *inode,
+ 	return 0;
+ 
+ corrupted:
+-	ext4_error_inode(function, inode,
++	ext4_error_inode(inode, function, line, 0,
+ 			"bad header/extent: %s - magic %x, "
+ 			"entries %u, max %u(%u), depth %u(%u)",
+ 			error_msg, le16_to_cpu(eh->eh_magic),
+@@ -447,7 +447,7 @@ static int __ext4_ext_check(const char *function, struct inode *inode,
+ }
+ 
+ #define ext4_ext_check(inode, eh, depth)	\
+-	__ext4_ext_check(__func__, inode, eh, depth)
++	__ext4_ext_check(__func__, __LINE__, inode, eh, depth)
+ 
+ int ext4_ext_check_inode(struct inode *inode)
+ {
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 64baadb4956d..69ea663ef03e 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -337,7 +337,8 @@ static int ext4_block_to_path(struct inode *inode,
+ 	return n;
+ }
+ 
+-static int __ext4_check_blockref(const char *function, struct inode *inode,
++static int __ext4_check_blockref(const char *function, unsigned int line,
++				 struct inode *inode,
+ 				 __le32 *p, unsigned int max)
+ {
+ 	__le32 *bref = p;
+@@ -348,8 +349,8 @@ static int __ext4_check_blockref(const char *function, struct inode *inode,
+ 		if (blk &&
+ 		    unlikely(!ext4_data_block_valid(EXT4_SB(inode->i_sb),
+ 						    blk, 1))) {
+-			ext4_error_inode(function, inode,
+-					 "invalid block reference %u", blk);
++			ext4_error_inode(inode, function, line, blk,
++					 "invalid block");
+ 			return -EIO;
+ 		}
+ 	}
+@@ -358,11 +359,13 @@ static int __ext4_check_blockref(const char *function, struct inode *inode,
+ 
+ 
+ #define ext4_check_indirect_blockref(inode, bh)                         \
+-	__ext4_check_blockref(__func__, inode, (__le32 *)(bh)->b_data,  \
++	__ext4_check_blockref(__func__, __LINE__, inode,		\
++			      (__le32 *)(bh)->b_data,			\
+ 			      EXT4_ADDR_PER_BLOCK((inode)->i_sb))
+ 
+ #define ext4_check_inode_blockref(inode)                                \
+-	__ext4_check_blockref(__func__, inode, EXT4_I(inode)->i_data,   \
++	__ext4_check_blockref(__func__, __LINE__, inode,		\
++			      EXT4_I(inode)->i_data,			\
+ 			      EXT4_NDIR_BLOCKS)
+ 
+ /**
+@@ -1129,21 +1132,22 @@ void ext4_da_update_reserve_space(struct inode *inode,
+ }
+ 
+ static int __check_block_validity(struct inode *inode, const char *func,
+-				  struct ext4_map_blocks *map)
++				unsigned int line,
++				struct ext4_map_blocks *map)
+ {
+ 	if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), map->m_pblk,
+ 				   map->m_len)) {
+-		ext4_error_inode(func, inode,
+-			   "lblock %lu mapped to illegal pblock %llu "
+-			   "(length %d)", (unsigned long) map->m_lblk,
+-				 map->m_pblk, map->m_len);
++		ext4_error_inode(inode, func, line, map->m_pblk,
++				 "lblock %lu mapped to illegal pblock "
++				 "(length %d)", (unsigned long) map->m_lblk,
++				 map->m_len);
+ 		return -EIO;
+ 	}
+ 	return 0;
+ }
+ 
+ #define check_block_validity(inode, map)	\
+-	__check_block_validity((inode), __func__, (map))
++	__check_block_validity((inode), __func__, __LINE__, (map))
+ 
+ /*
+  * Return the number of contiguous dirty pages in a given inode
+@@ -4471,9 +4475,8 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
+ 			 * (should be rare).
+ 			 */
+ 			if (!bh) {
+-				EXT4_ERROR_INODE(inode,
+-						 "Read failure block=%llu",
+-						 (unsigned long long) nr);
++				EXT4_ERROR_INODE_BLOCK(inode, nr,
++						       "Read failure");
+ 				continue;
+ 			}
+ 
+@@ -4788,8 +4791,8 @@ static int __ext4_get_inode_loc(struct inode *inode,
+ 
+ 	bh = sb_getblk(sb, block);
+ 	if (!bh) {
+-		EXT4_ERROR_INODE(inode, "unable to read inode block - "
+-				 "block %llu", block);
++		EXT4_ERROR_INODE_BLOCK(inode, block,
++				       "unable to read itable block");
+ 		return -EIO;
+ 	}
+ 	if (!buffer_uptodate(bh)) {
+@@ -4887,8 +4890,8 @@ static int __ext4_get_inode_loc(struct inode *inode,
+ 		submit_bh(READ_META, bh);
+ 		wait_on_buffer(bh);
+ 		if (!buffer_uptodate(bh)) {
+-			EXT4_ERROR_INODE(inode, "unable to read inode "
+-					 "block %llu", block);
++			EXT4_ERROR_INODE_BLOCK(inode, block,
++					       "unable to read itable block");
+ 			brelse(bh);
+ 			return -EIO;
+ 		}
+@@ -5389,9 +5392,8 @@ int ext4_write_inode(struct inode *inode, struct writeback_control *wbc)
+ 		if (wbc->sync_mode == WB_SYNC_ALL)
+ 			sync_dirty_buffer(iloc.bh);
+ 		if (buffer_req(iloc.bh) && !buffer_uptodate(iloc.bh)) {
+-			EXT4_ERROR_INODE(inode,
+-				"IO error syncing inode (block=%llu)",
+-				(unsigned long long) iloc.bh->b_blocknr);
++			EXT4_ERROR_INODE_BLOCK(inode, iloc.bh->b_blocknr,
++					 "IO error syncing inode");
+ 			err = -EIO;
+ 		}
+ 		brelse(iloc.bh);
+diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
+index 52abfa12762a..5f1ed9fc913c 100644
+--- a/fs/ext4/move_extent.c
++++ b/fs/ext4/move_extent.c
+@@ -148,17 +148,17 @@ mext_next_extent(struct inode *inode, struct ext4_ext_path *path,
+  */
+ static int
+ mext_check_null_inode(struct inode *inode1, struct inode *inode2,
+-		const char *function)
++		      const char *function, unsigned int line)
+ {
+ 	int ret = 0;
+ 
+ 	if (inode1 == NULL) {
+-		__ext4_error(inode2->i_sb, function,
++		__ext4_error(inode2->i_sb, function, line,
+ 			"Both inodes should not be NULL: "
+ 			"inode1 NULL inode2 %lu", inode2->i_ino);
+ 		ret = -EIO;
+ 	} else if (inode2 == NULL) {
+-		__ext4_error(inode1->i_sb, function,
++		__ext4_error(inode1->i_sb, function, line,
+ 			"Both inodes should not be NULL: "
+ 			"inode1 %lu inode2 NULL", inode1->i_ino);
+ 		ret = -EIO;
+@@ -1084,7 +1084,7 @@ mext_inode_double_lock(struct inode *inode1, struct inode *inode2)
+ 
+ 	BUG_ON(inode1 == NULL && inode2 == NULL);
+ 
+-	ret = mext_check_null_inode(inode1, inode2, __func__);
++	ret = mext_check_null_inode(inode1, inode2, __func__, __LINE__);
+ 	if (ret < 0)
+ 		goto out;
+ 
+@@ -1121,7 +1121,7 @@ mext_inode_double_unlock(struct inode *inode1, struct inode *inode2)
+ 
+ 	BUG_ON(inode1 == NULL && inode2 == NULL);
+ 
+-	ret = mext_check_null_inode(inode1, inode2, __func__);
++	ret = mext_check_null_inode(inode1, inode2, __func__, __LINE__);
+ 	if (ret < 0)
+ 		goto out;
+ 
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 87db5ecfccb4..bcf74b31d014 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -262,7 +262,7 @@ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks)
+  * that sync() will call the filesystem's write_super callback if
+  * appropriate.
+  */
+-int __ext4_journal_stop(const char *where, handle_t *handle)
++int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle)
+ {
+ 	struct super_block *sb;
+ 	int err;
+@@ -279,7 +279,7 @@ int __ext4_journal_stop(const char *where, handle_t *handle)
+ 	if (!err)
+ 		err = rc;
+ 	if (err)
+-		__ext4_std_error(sb, where, err);
++		__ext4_std_error(sb, where, line, err);
+ 	return err;
+ }
+ 
+@@ -350,12 +350,13 @@ static void ext4_handle_error(struct super_block *sb)
+ }
+ 
+ void __ext4_error(struct super_block *sb, const char *function,
+-		const char *fmt, ...)
++		  unsigned int line, const char *fmt, ...)
+ {
+ 	va_list args;
+ 
+ 	va_start(args, fmt);
+-	printk(KERN_CRIT "EXT4-fs error (device %s): %s: ", sb->s_id, function);
++	printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: comm %s: ",
++	       sb->s_id, function, line, current->comm);
+ 	vprintk(fmt, args);
+ 	printk("\n");
+ 	va_end(args);
+@@ -363,14 +364,18 @@ void __ext4_error(struct super_block *sb, const char *function,
+ 	ext4_handle_error(sb);
+ }
+ 
+-void ext4_error_inode(const char *function, struct inode *inode,
++void ext4_error_inode(struct inode *inode, const char *function,
++		      unsigned int line, ext4_fsblk_t block,
+ 		      const char *fmt, ...)
+ {
+ 	va_list args;
+ 
+ 	va_start(args, fmt);
+-	printk(KERN_CRIT "EXT4-fs error (device %s): %s: inode #%lu: (comm %s) ",
+-	       inode->i_sb->s_id, function, inode->i_ino, current->comm);
++	printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: inode #%lu: ",
++	       inode->i_sb->s_id, function, line, inode->i_ino);
++	if (block)
++		printk("block %llu: ", block);
++	printk("comm %s: ", current->comm);
+ 	vprintk(fmt, args);
+ 	printk("\n");
+ 	va_end(args);
+@@ -378,8 +383,8 @@ void ext4_error_inode(const char *function, struct inode *inode,
+ 	ext4_handle_error(inode->i_sb);
+ }
+ 
+-void ext4_error_file(const char *function, struct file *file,
+-		     const char *fmt, ...)
++void ext4_error_file(struct file *file, const char *function,
++		     unsigned int line, const char *fmt, ...)
+ {
+ 	va_list args;
+ 	struct inode *inode = file->f_dentry->d_inode;
+@@ -390,8 +395,10 @@ void ext4_error_file(const char *function, struct file *file,
+ 	if (!path)
+ 		path = "(unknown)";
+ 	printk(KERN_CRIT
+-	       "EXT4-fs error (device %s): %s: inode #%lu (comm %s path %s): ",
+-	       inode->i_sb->s_id, function, inode->i_ino, current->comm, path);
++	       "EXT4-fs error (device %s): %s:%d: inode #%lu "
++	       "(comm %s path %s): ",
++	       inode->i_sb->s_id, function, line, inode->i_ino,
++	       current->comm, path);
+ 	vprintk(fmt, args);
+ 	printk("\n");
+ 	va_end(args);
+@@ -436,7 +443,8 @@ static const char *ext4_decode_error(struct super_block *sb, int errno,
+ /* __ext4_std_error decodes expected errors from journaling functions
+  * automatically and invokes the appropriate error response.  */
+ 
+-void __ext4_std_error(struct super_block *sb, const char *function, int errno)
++void __ext4_std_error(struct super_block *sb, const char *function,
++		      unsigned int line, int errno)
+ {
+ 	char nbuf[16];
+ 	const char *errstr;
+@@ -449,8 +457,8 @@ void __ext4_std_error(struct super_block *sb, const char *function, int errno)
+ 		return;
+ 
+ 	errstr = ext4_decode_error(sb, errno, nbuf);
+-	printk(KERN_CRIT "EXT4-fs error (device %s) in %s: %s\n",
+-	       sb->s_id, function, errstr);
++	printk(KERN_CRIT "EXT4-fs error (device %s) in %s:%d: %s\n",
++	       sb->s_id, function, line, errstr);
+ 
+ 	ext4_handle_error(sb);
+ }
+@@ -466,12 +474,13 @@ void __ext4_std_error(struct super_block *sb, const char *function, int errno)
+  */
+ 
+ void __ext4_abort(struct super_block *sb, const char *function,
+-		  const char *fmt, ...)
++		unsigned int line, const char *fmt, ...)
+ {
+ 	va_list args;
+ 
+ 	va_start(args, fmt);
+-	printk(KERN_CRIT "EXT4-fs error (device %s): %s: ", sb->s_id, function);
++	printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: ", sb->s_id,
++	       function, line);
+ 	vprintk(fmt, args);
+ 	printk("\n");
+ 	va_end(args);
+@@ -503,13 +512,13 @@ void ext4_msg (struct super_block * sb, const char *prefix,
+ }
+ 
+ void __ext4_warning(struct super_block *sb, const char *function,
+-		  const char *fmt, ...)
++		    unsigned int line, const char *fmt, ...)
+ {
+ 	va_list args;
+ 
+ 	va_start(args, fmt);
+-	printk(KERN_WARNING "EXT4-fs warning (device %s): %s: ",
+-	       sb->s_id, function);
++	printk(KERN_WARNING "EXT4-fs warning (device %s): %s:%d: ",
++	       sb->s_id, function, line);
+ 	vprintk(fmt, args);
+ 	printk("\n");
+ 	va_end(args);

commit 60fd4da34d55a9cc0d857fc76dc12cf8cab4ed02
+Author: Theodore Ts'o 
+Date:   Tue Jul 27 11:54:40 2010 -0400
+
+    ext4: Cleanup ext4_check_dir_entry so __func__ is now implicit
+    
+    Also start passing the line number to ext4_check_dir since we're going
+    to need it in upcoming patch.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index 2965c39d4183..af581f08fe3a 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -61,10 +61,11 @@ static unsigned char get_dtype(struct super_block *sb, int filetype)
+ }
+ 
+ 
+-int ext4_check_dir_entry(const char *function, struct inode *dir,
+-			 struct ext4_dir_entry_2 *de,
+-			 struct buffer_head *bh,
+-			 unsigned int offset)
++int __ext4_check_dir_entry(const char *function, unsigned int line,
++			   struct inode *dir,
++			   struct ext4_dir_entry_2 *de,
++			   struct buffer_head *bh,
++			   unsigned int offset)
+ {
+ 	const char *error_msg = NULL;
+ 	const int rlen = ext4_rec_len_from_disk(de->rec_len,
+@@ -194,7 +195,7 @@ static int ext4_readdir(struct file *filp,
+ 		while (!error && filp->f_pos < inode->i_size
+ 		       && offset < sb->s_blocksize) {
+ 			de = (struct ext4_dir_entry_2 *) (bh->b_data + offset);
+-			if (!ext4_check_dir_entry("ext4_readdir", inode, de,
++			if (!ext4_check_dir_entry(inode, de,
+ 						  bh, offset)) {
+ 				/*
+ 				 * On error, skip the f_pos to the next block
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 5a41881cafca..73465b26976d 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1515,9 +1515,11 @@ extern unsigned ext4_init_block_bitmap(struct super_block *sb,
+ 		ext4_init_block_bitmap(sb, NULL, group, desc)
+ 
+ /* dir.c */
+-extern int ext4_check_dir_entry(const char *, struct inode *,
+-				struct ext4_dir_entry_2 *,
+-				struct buffer_head *, unsigned int);
++extern int __ext4_check_dir_entry(const char *, unsigned int, struct inode *,
++				  struct ext4_dir_entry_2 *,
++				  struct buffer_head *, unsigned int);
++#define ext4_check_dir_entry(dir, de, bh, offset) \
++	__ext4_check_dir_entry(__func__, __LINE__, (dir), (de), (bh), (offset))
+ extern int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
+ 				    __u32 minor_hash,
+ 				    struct ext4_dir_entry_2 *dirent);
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 5a61f77e7d7c..ea8b59d96213 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -605,7 +605,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
+ 					   dir->i_sb->s_blocksize -
+ 					   EXT4_DIR_REC_LEN(0));
+ 	for (; de < top; de = ext4_next_entry(de, dir->i_sb->s_blocksize)) {
+-		if (!ext4_check_dir_entry("htree_dirblock_to_tree", dir, de, bh,
++		if (!ext4_check_dir_entry(dir, de, bh,
+ 					(block<i_sb))
+ 						+((char *)de - bh->b_data))) {
+ 			/* On error, skip the f_pos to the next block. */
+@@ -844,8 +844,7 @@ static inline int search_dirblock(struct buffer_head *bh,
+ 		if ((char *) de + namelen <= dlimit &&
+ 		    ext4_match (namelen, name, de)) {
+ 			/* found a match - just to be sure, do a full check */
+-			if (!ext4_check_dir_entry("ext4_find_entry",
+-						  dir, de, bh, offset))
++			if (!ext4_check_dir_entry(dir, de, bh, offset))
+ 				return -1;
+ 			*res_dir = de;
+ 			return 1;
+@@ -1019,7 +1018,7 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q
+ 			int off = (block << EXT4_BLOCK_SIZE_BITS(sb))
+ 				  + ((char *) de - bh->b_data);
+ 
+-			if (!ext4_check_dir_entry(__func__, dir, de, bh, off)) {
++			if (!ext4_check_dir_entry(dir, de, bh, off)) {
+ 				brelse(bh);
+ 				*err = ERR_BAD_DX_DIR;
+ 				goto errout;
+@@ -1303,8 +1302,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
+ 		de = (struct ext4_dir_entry_2 *)bh->b_data;
+ 		top = bh->b_data + blocksize - reclen;
+ 		while ((char *) de <= top) {
+-			if (!ext4_check_dir_entry("ext4_add_entry", dir, de,
+-						  bh, offset))
++			if (!ext4_check_dir_entry(dir, de, bh, offset))
+ 				return -EIO;
+ 			if (ext4_match(namelen, name, de))
+ 				return -EEXIST;
+@@ -1671,7 +1669,7 @@ static int ext4_delete_entry(handle_t *handle,
+ 	pde = NULL;
+ 	de = (struct ext4_dir_entry_2 *) bh->b_data;
+ 	while (i < bh->b_size) {
+-		if (!ext4_check_dir_entry("ext4_delete_entry", dir, de, bh, i))
++		if (!ext4_check_dir_entry(dir, de, bh, i))
+ 			return -EIO;
+ 		if (de == de_del)  {
+ 			BUFFER_TRACE(bh, "get_write_access");
+@@ -1954,7 +1952,7 @@ static int empty_dir(struct inode *inode)
+ 			}
+ 			de = (struct ext4_dir_entry_2 *) bh->b_data;
+ 		}
+-		if (!ext4_check_dir_entry("empty_dir", inode, de, bh, offset)) {
++		if (!ext4_check_dir_entry(inode, de, bh, offset)) {
+ 			de = (struct ext4_dir_entry_2 *)(bh->b_data +
+ 							 sb->s_blocksize);
+ 			offset = (offset | (sb->s_blocksize - 1)) + 1;

commit 90c7201b97bb7ac5a4e2605abc0efb5fdfb957f0
+Author: Theodore Ts'o 
+Date:   Tue Jun 29 14:53:24 2010 -0400
+
+    ext4: Pass line number to ext4_journal_abort_handle()
+    
+    This allows the error messages to include the line number
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
+index df26a015d043..9de37b9e177a 100644
+--- a/fs/ext4/ext4_jbd2.c
++++ b/fs/ext4/ext4_jbd2.c
+@@ -6,29 +6,29 @@
+ 
+ #include 
+ 
+-int __ext4_journal_get_undo_access(const char *where, handle_t *handle,
+-				struct buffer_head *bh)
++int __ext4_journal_get_undo_access(const char *where, unsigned int line,
++				   handle_t *handle, struct buffer_head *bh)
+ {
+ 	int err = 0;
+ 
+ 	if (ext4_handle_valid(handle)) {
+ 		err = jbd2_journal_get_undo_access(handle, bh);
+ 		if (err)
+-			ext4_journal_abort_handle(where, __func__, bh,
++			ext4_journal_abort_handle(where, line, __func__, bh,
+ 						  handle, err);
+ 	}
+ 	return err;
+ }
+ 
+-int __ext4_journal_get_write_access(const char *where, handle_t *handle,
+-				struct buffer_head *bh)
++int __ext4_journal_get_write_access(const char *where, unsigned int line,
++				    handle_t *handle, struct buffer_head *bh)
+ {
+ 	int err = 0;
+ 
+ 	if (ext4_handle_valid(handle)) {
+ 		err = jbd2_journal_get_write_access(handle, bh);
+ 		if (err)
+-			ext4_journal_abort_handle(where, __func__, bh,
++			ext4_journal_abort_handle(where, line, __func__, bh,
+ 						  handle, err);
+ 	}
+ 	return err;
+@@ -46,9 +46,9 @@ int __ext4_journal_get_write_access(const char *where, handle_t *handle,
+  * If the handle isn't valid we're not journaling, but we still need to
+  * call into ext4_journal_revoke() to put the buffer head.
+  */
+-int __ext4_forget(const char *where, handle_t *handle, int is_metadata,
+-		  struct inode *inode, struct buffer_head *bh,
+-		  ext4_fsblk_t blocknr)
++int __ext4_forget(const char *where, unsigned int line, handle_t *handle,
++		  int is_metadata, struct inode *inode,
++		  struct buffer_head *bh, ext4_fsblk_t blocknr)
+ {
+ 	int err;
+ 
+@@ -79,8 +79,8 @@ int __ext4_forget(const char *where, handle_t *handle, int is_metadata,
+ 			BUFFER_TRACE(bh, "call jbd2_journal_forget");
+ 			err = jbd2_journal_forget(handle, bh);
+ 			if (err)
+-				ext4_journal_abort_handle(where, __func__, bh,
+-							  handle, err);
++				ext4_journal_abort_handle(where, line, __func__,
++							  bh, handle, err);
+ 			return err;
+ 		}
+ 		return 0;
+@@ -92,7 +92,8 @@ int __ext4_forget(const char *where, handle_t *handle, int is_metadata,
+ 	BUFFER_TRACE(bh, "call jbd2_journal_revoke");
+ 	err = jbd2_journal_revoke(handle, blocknr, bh);
+ 	if (err) {
+-		ext4_journal_abort_handle(where, __func__, bh, handle, err);
++		ext4_journal_abort_handle(where, line, __func__,
++					  bh, handle, err);
+ 		__ext4_abort(inode->i_sb, where,
+ 			     "error %d when attempting revoke", err);
+ 	}
+@@ -100,7 +101,7 @@ int __ext4_forget(const char *where, handle_t *handle, int is_metadata,
+ 	return err;
+ }
+ 
+-int __ext4_journal_get_create_access(const char *where,
++int __ext4_journal_get_create_access(const char *where, unsigned int line,
+ 				handle_t *handle, struct buffer_head *bh)
+ {
+ 	int err = 0;
+@@ -108,22 +109,23 @@ int __ext4_journal_get_create_access(const char *where,
+ 	if (ext4_handle_valid(handle)) {
+ 		err = jbd2_journal_get_create_access(handle, bh);
+ 		if (err)
+-			ext4_journal_abort_handle(where, __func__, bh,
+-						  handle, err);
++			ext4_journal_abort_handle(where, line, __func__,
++						  bh, handle, err);
+ 	}
+ 	return err;
+ }
+ 
+-int __ext4_handle_dirty_metadata(const char *where, handle_t *handle,
+-				 struct inode *inode, struct buffer_head *bh)
++int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
++				 handle_t *handle, struct inode *inode,
++				 struct buffer_head *bh)
+ {
+ 	int err = 0;
+ 
+ 	if (ext4_handle_valid(handle)) {
+ 		err = jbd2_journal_dirty_metadata(handle, bh);
+ 		if (err)
+-			ext4_journal_abort_handle(where, __func__, bh,
+-						  handle, err);
++			ext4_journal_abort_handle(where, line, __func__,
++						  bh, handle, err);
+ 	} else {
+ 		if (inode)
+ 			mark_buffer_dirty_inode(bh, inode);
+@@ -144,8 +146,8 @@ int __ext4_handle_dirty_metadata(const char *where, handle_t *handle,
+ 	return err;
+ }
+ 
+-int __ext4_handle_dirty_super(const char *where, handle_t *handle,
+-			      struct super_block *sb)
++int __ext4_handle_dirty_super(const char *where, unsigned int line,
++			      handle_t *handle, struct super_block *sb)
+ {
+ 	struct buffer_head *bh = EXT4_SB(sb)->s_sbh;
+ 	int err = 0;
+@@ -153,8 +155,8 @@ int __ext4_handle_dirty_super(const char *where, handle_t *handle,
+ 	if (ext4_handle_valid(handle)) {
+ 		err = jbd2_journal_dirty_metadata(handle, bh);
+ 		if (err)
+-			ext4_journal_abort_handle(where, __func__, bh,
+-						  handle, err);
++			ext4_journal_abort_handle(where, line, __func__,
++						  bh, handle, err);
+ 	} else
+ 		sb->s_dirt = 1;
+ 	return err;
+diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
+index 38d1e66e5843..6883c6be5b8d 100644
+--- a/fs/ext4/ext4_jbd2.h
++++ b/fs/ext4/ext4_jbd2.h
+@@ -122,41 +122,44 @@ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode);
+ /*
+  * Wrapper functions with which ext4 calls into JBD.
+  */
+-void ext4_journal_abort_handle(const char *caller, const char *err_fn,
++void ext4_journal_abort_handle(const char *caller, unsigned int line,
++			       const char *err_fn,
+ 		struct buffer_head *bh, handle_t *handle, int err);
+ 
+-int __ext4_journal_get_undo_access(const char *where, handle_t *handle,
+-				struct buffer_head *bh);
++int __ext4_journal_get_undo_access(const char *where, unsigned int line,
++				   handle_t *handle, struct buffer_head *bh);
+ 
+-int __ext4_journal_get_write_access(const char *where, handle_t *handle,
+-				struct buffer_head *bh);
++int __ext4_journal_get_write_access(const char *where, unsigned int line,
++				    handle_t *handle, struct buffer_head *bh);
+ 
+-int __ext4_forget(const char *where, handle_t *handle, int is_metadata,
+-		  struct inode *inode, struct buffer_head *bh,
+-		  ext4_fsblk_t blocknr);
++int __ext4_forget(const char *where, unsigned int line, handle_t *handle,
++		  int is_metadata, struct inode *inode,
++		  struct buffer_head *bh, ext4_fsblk_t blocknr);
+ 
+-int __ext4_journal_get_create_access(const char *where,
++int __ext4_journal_get_create_access(const char *where, unsigned int line,
+ 				handle_t *handle, struct buffer_head *bh);
+ 
+-int __ext4_handle_dirty_metadata(const char *where, handle_t *handle,
+-				 struct inode *inode, struct buffer_head *bh);
++int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
++				 handle_t *handle, struct inode *inode,
++				 struct buffer_head *bh);
+ 
+-int __ext4_handle_dirty_super(const char *where, handle_t *handle,
+-			      struct super_block *sb);
++int __ext4_handle_dirty_super(const char *where, unsigned int line,
++			      handle_t *handle, struct super_block *sb);
+ 
+ #define ext4_journal_get_undo_access(handle, bh) \
+-	__ext4_journal_get_undo_access(__func__, (handle), (bh))
++	__ext4_journal_get_undo_access(__func__, __LINE__, (handle), (bh))
+ #define ext4_journal_get_write_access(handle, bh) \
+-	__ext4_journal_get_write_access(__func__, (handle), (bh))
++	__ext4_journal_get_write_access(__func__, __LINE__, (handle), (bh))
+ #define ext4_forget(handle, is_metadata, inode, bh, block_nr) \
+-	__ext4_forget(__func__, (handle), (is_metadata), (inode), (bh),\
+-		      (block_nr))
++	__ext4_forget(__func__, __LINE__, (handle), (is_metadata), (inode), \
++		      (bh), (block_nr))
+ #define ext4_journal_get_create_access(handle, bh) \
+-	__ext4_journal_get_create_access(__func__, (handle), (bh))
++	__ext4_journal_get_create_access(__func__, __LINE__, (handle), (bh))
+ #define ext4_handle_dirty_metadata(handle, inode, bh) \
+-	__ext4_handle_dirty_metadata(__func__, (handle), (inode), (bh))
++	__ext4_handle_dirty_metadata(__func__, __LINE__, (handle), (inode), \
++				     (bh))
+ #define ext4_handle_dirty_super(handle, sb) \
+-	__ext4_handle_dirty_super(__func__, (handle), (sb))
++	__ext4_handle_dirty_super(__func__, __LINE__, (handle), (sb))
+ 
+ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks);
+ int __ext4_journal_stop(const char *where, handle_t *handle);
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 39aeb454bf2c..87db5ecfccb4 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -283,8 +283,9 @@ int __ext4_journal_stop(const char *where, handle_t *handle)
+ 	return err;
+ }
+ 
+-void ext4_journal_abort_handle(const char *caller, const char *err_fn,
+-		struct buffer_head *bh, handle_t *handle, int err)
++void ext4_journal_abort_handle(const char *caller, unsigned int line,
++			       const char *err_fn, struct buffer_head *bh,
++			       handle_t *handle, int err)
+ {
+ 	char nbuf[16];
+ 	const char *errstr = ext4_decode_error(NULL, err, nbuf);
+@@ -300,8 +301,8 @@ void ext4_journal_abort_handle(const char *caller, const char *err_fn,
+ 	if (is_handle_aborted(handle))
+ 		return;
+ 
+-	printk(KERN_ERR "%s: aborting transaction: %s in %s\n",
+-	       caller, errstr, err_fn);
++	printk(KERN_ERR "%s:%d: aborting transaction: %s in %s\n",
++	       caller, line, errstr, err_fn);
+ 
+ 	jbd2_journal_abort_handle(handle);
+ }

commit e29136f80e775b0310273932b4297a62f5574a29
+Author: Theodore Ts'o 
+Date:   Tue Jun 29 12:54:28 2010 -0400
+
+    ext4: Enhance ext4_grp_locked_error() to take block and function numbers
+    
+    Also use a macro definition so that __func__ and __LINE__ is implicit.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index d8ec824f5a25..5a41881cafca 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1639,9 +1639,13 @@ extern void __ext4_warning(struct super_block *, const char *,
+ #define ext4_warning(sb, message...)	__ext4_warning(sb, __func__, ## message)
+ extern void ext4_msg(struct super_block *, const char *, const char *, ...)
+ 	__attribute__ ((format (printf, 3, 4)));
+-extern void ext4_grp_locked_error(struct super_block *, ext4_group_t,
+-				const char *, const char *, ...)
+-	__attribute__ ((format (printf, 4, 5)));
++extern void __ext4_grp_locked_error(const char *, unsigned int, \
++				    struct super_block *, ext4_group_t, \
++				    unsigned long, ext4_fsblk_t, \
++				    const char *, ...)
++	__attribute__ ((format (printf, 7, 8)));
++#define ext4_grp_locked_error(sb, grp, message...) \
++	__ext4_grp_locked_error(__func__, __LINE__, (sb), (grp), ## message)
+ extern void ext4_update_dynamic_rev(struct super_block *sb);
+ extern int ext4_update_compat_feature(handle_t *handle, struct super_block *sb,
+ 					__u32 compat);
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index b485987f0146..64baadb4956d 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1128,8 +1128,8 @@ void ext4_da_update_reserve_space(struct inode *inode,
+ 		ext4_discard_preallocations(inode);
+ }
+ 
+-static int check_block_validity(struct inode *inode, const char *func,
+-				struct ext4_map_blocks *map)
++static int __check_block_validity(struct inode *inode, const char *func,
++				  struct ext4_map_blocks *map)
+ {
+ 	if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), map->m_pblk,
+ 				   map->m_len)) {
+@@ -1142,6 +1142,9 @@ static int check_block_validity(struct inode *inode, const char *func,
+ 	return 0;
+ }
+ 
++#define check_block_validity(inode, map)	\
++	__check_block_validity((inode), __func__, (map))
++
+ /*
+  * Return the number of contiguous dirty pages in a given inode
+  * starting at page frame idx.
+@@ -1244,7 +1247,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
+ 	up_read((&EXT4_I(inode)->i_data_sem));
+ 
+ 	if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) {
+-		int ret = check_block_validity(inode, __func__, map);
++		int ret = check_block_validity(inode, map);
+ 		if (ret != 0)
+ 			return ret;
+ 	}
+@@ -1324,9 +1327,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
+ 
+ 	up_write((&EXT4_I(inode)->i_data_sem));
+ 	if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) {
+-		int ret = check_block_validity(inode,
+-					       "ext4_map_blocks_after_alloc",
+-					       map);
++		int ret = check_block_validity(inode, map);
+ 		if (ret != 0)
+ 			return ret;
+ 	}
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index b2948b047973..3dfad95f0f98 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -446,10 +446,11 @@ static void mb_free_blocks_double(struct inode *inode, struct ext4_buddy *e4b,
+ 			blocknr = ext4_group_first_block_no(sb, e4b->bd_group);
+ 			blocknr += first + i;
+ 			ext4_grp_locked_error(sb, e4b->bd_group,
+-				   __func__, "double-free of inode"
+-				   " %lu's block %llu(bit %u in group %u)",
+-				   inode ? inode->i_ino : 0, blocknr,
+-				   first + i, e4b->bd_group);
++					      inode ? inode->i_ino : 0,
++					      blocknr,
++					      "freeing block already freed "
++					      "(bit %u)",
++					      first + i);
+ 		}
+ 		mb_clear_bit(first + i, e4b->bd_info->bb_bitmap);
+ 	}
+@@ -712,9 +713,9 @@ void ext4_mb_generate_buddy(struct super_block *sb,
+ 	grp->bb_fragments = fragments;
+ 
+ 	if (free != grp->bb_free) {
+-		ext4_grp_locked_error(sb, group,  __func__,
+-			"EXT4-fs: group %u: %u blocks in bitmap, %u in gd",
+-			group, free, grp->bb_free);
++		ext4_grp_locked_error(sb, group, 0, 0,
++				      "%u blocks in bitmap, %u in gd",
++				      free, grp->bb_free);
+ 		/*
+ 		 * If we intent to continue, we consider group descritor
+ 		 * corrupt and update bb_free using bitmap value
+@@ -1296,10 +1297,10 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
+ 			blocknr = ext4_group_first_block_no(sb, e4b->bd_group);
+ 			blocknr += block;
+ 			ext4_grp_locked_error(sb, e4b->bd_group,
+-				   __func__, "double-free of inode"
+-				   " %lu's block %llu(bit %u in group %u)",
+-				   inode ? inode->i_ino : 0, blocknr, block,
+-				   e4b->bd_group);
++					      inode ? inode->i_ino : 0,
++					      blocknr,
++					      "freeing already freed block "
++					      "(bit %u)", block);
+ 		}
+ 		mb_clear_bit(block, EXT4_MB_BITMAP(e4b));
+ 		e4b->bd_info->bb_counters[order]++;
+@@ -1788,8 +1789,8 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
+ 			 * free blocks even though group info says we
+ 			 * we have free blocks
+ 			 */
+-			ext4_grp_locked_error(sb, e4b->bd_group,
+-					__func__, "%d free blocks as per "
++			ext4_grp_locked_error(sb, e4b->bd_group, 0, 0,
++					"%d free blocks as per "
+ 					"group info. But bitmap says 0",
+ 					free);
+ 			break;
+@@ -1798,8 +1799,8 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
+ 		mb_find_extent(e4b, 0, i, ac->ac_g_ex.fe_len, &ex);
+ 		BUG_ON(ex.fe_len <= 0);
+ 		if (free < ex.fe_len) {
+-			ext4_grp_locked_error(sb, e4b->bd_group,
+-					__func__, "%d free blocks as per "
++			ext4_grp_locked_error(sb, e4b->bd_group, 0, 0,
++					"%d free blocks as per "
+ 					"group info. But got %d blocks",
+ 					free, ex.fe_len);
+ 			/*
+@@ -3584,8 +3585,7 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh,
+ 			pa, (unsigned long) pa->pa_lstart,
+ 			(unsigned long) pa->pa_pstart,
+ 			(unsigned long) pa->pa_len);
+-		ext4_grp_locked_error(sb, group,
+-					__func__, "free %u, pa_free %u",
++		ext4_grp_locked_error(sb, group, 0, 0, "free %u, pa_free %u",
+ 					free, pa->pa_free);
+ 		/*
+ 		 * pa is already deleted so we use the value obtained
+@@ -4395,6 +4395,7 @@ static noinline_for_stack int
+ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
+ 		      struct ext4_free_data *new_entry)
+ {
++	ext4_group_t group = e4b->bd_group;
+ 	ext4_grpblk_t block;
+ 	struct ext4_free_data *entry;
+ 	struct ext4_group_info *db = e4b->bd_info;
+@@ -4427,9 +4428,9 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
+ 		else if (block >= (entry->start_blk + entry->count))
+ 			n = &(*n)->rb_right;
+ 		else {
+-			ext4_grp_locked_error(sb, e4b->bd_group, __func__,
+-					"Double free of blocks %d (%d %d)",
+-					block, entry->start_blk, entry->count);
++			ext4_grp_locked_error(sb, group, 0,
++				ext4_group_first_block_no(sb, group) + block,
++				"Block already on to-be-freed list");
+ 			return 0;
+ 		}
+ 	}
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 11441e483b62..39aeb454bf2c 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -514,8 +514,10 @@ void __ext4_warning(struct super_block *sb, const char *function,
+ 	va_end(args);
+ }
+ 
+-void ext4_grp_locked_error(struct super_block *sb, ext4_group_t grp,
+-			   const char *function, const char *fmt, ...)
++void __ext4_grp_locked_error(const char *function, unsigned int line,
++			     struct super_block *sb, ext4_group_t grp,
++			     unsigned long ino, ext4_fsblk_t block,
++			     const char *fmt, ...)
+ __releases(bitlock)
+ __acquires(bitlock)
+ {
+@@ -523,7 +525,12 @@ __acquires(bitlock)
+ 	struct ext4_super_block *es = EXT4_SB(sb)->s_es;
+ 
+ 	va_start(args, fmt);
+-	printk(KERN_CRIT "EXT4-fs error (device %s): %s: ", sb->s_id, function);
++	printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: group %u",
++	       sb->s_id, function, line, grp);
++	if (ino)
++		printk("inode %lu: ", ino);
++	if (block)
++		printk("block %llu:", (unsigned long long) block);
+ 	vprintk(fmt, args);
+ 	printk("\n");
+ 	va_end(args);

commit c67d859e39896e4286249da89c4ca0ef8bd949cb
+Author: Theodore Ts'o 
+Date:   Tue Jun 29 11:07:07 2010 -0400
+
+    ext4: clean up ext4_abort() so __func__ is now implicit
+    
+    Use a macro definition for ext4_abort() to clean up the .c files a wee
+    bit.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 3864a2775458..d8ec824f5a25 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1629,8 +1629,10 @@ extern void ext4_error_inode(const char *, struct inode *, const char *, ...)
+ extern void ext4_error_file(const char *, struct file *, const char *, ...)
+ 	__attribute__ ((format (printf, 3, 4)));
+ extern void __ext4_std_error(struct super_block *, const char *, int);
+-extern void ext4_abort(struct super_block *, const char *, const char *, ...)
++extern void __ext4_abort(struct super_block *, const char *, const char *, ...)
+ 	__attribute__ ((format (printf, 3, 4)));
++#define ext4_abort(sb, message...)	__ext4_abort(sb, __func__, \
++						     ## message)
+ extern void __ext4_warning(struct super_block *, const char *,
+ 			  const char *, ...)
+ 	__attribute__ ((format (printf, 3, 4)));
+diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
+index cfd27b38fa15..df26a015d043 100644
+--- a/fs/ext4/ext4_jbd2.c
++++ b/fs/ext4/ext4_jbd2.c
+@@ -93,8 +93,8 @@ int __ext4_forget(const char *where, handle_t *handle, int is_metadata,
+ 	err = jbd2_journal_revoke(handle, blocknr, bh);
+ 	if (err) {
+ 		ext4_journal_abort_handle(where, __func__, bh, handle, err);
+-		ext4_abort(inode->i_sb, __func__,
+-			   "error %d when attempting revoke", err);
++		__ext4_abort(inode->i_sb, where,
++			     "error %d when attempting revoke", err);
+ 	}
+ 	BUFFER_TRACE(bh, "exit");
+ 	return err;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 422a4ce66778..11441e483b62 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -248,7 +248,7 @@ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks)
+ 	journal = EXT4_SB(sb)->s_journal;
+ 	if (journal) {
+ 		if (is_journal_aborted(journal)) {
+-			ext4_abort(sb, __func__, "Detected aborted journal");
++			ext4_abort(sb, "Detected aborted journal");
+ 			return ERR_PTR(-EROFS);
+ 		}
+ 		return jbd2_journal_start(journal, nblocks);
+@@ -464,8 +464,8 @@ void __ext4_std_error(struct super_block *sb, const char *function, int errno)
+  * case we take the easy way out and panic immediately.
+  */
+ 
+-void ext4_abort(struct super_block *sb, const char *function,
+-		const char *fmt, ...)
++void __ext4_abort(struct super_block *sb, const char *function,
++		  const char *fmt, ...)
+ {
+ 	va_list args;
+ 
+@@ -660,8 +660,7 @@ static void ext4_put_super(struct super_block *sb)
+ 		err = jbd2_journal_destroy(sbi->s_journal);
+ 		sbi->s_journal = NULL;
+ 		if (err < 0)
+-			ext4_abort(sb, __func__,
+-				   "Couldn't clean up the journal");
++			ext4_abort(sb, "Couldn't clean up the journal");
+ 	}
+ 
+ 	ext4_release_system_zone(sb);
+@@ -3605,7 +3604,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 	}
+ 
+ 	if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED)
+-		ext4_abort(sb, __func__, "Abort forced by user");
++		ext4_abort(sb, "Abort forced by user");
+ 
+ 	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
+ 		(test_opt(sb, POSIX_ACL) ? MS_POSIXACL : 0);

commit 4a9cdec73f79b2858e9ecf0b6cfac7f6b200bf3a
+Author: Theodore Ts'o 
+Date:   Tue Jun 29 11:00:23 2010 -0400
+
+    ext4: Add new superblock fields reserved for the Next3 snapshot feature
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 8b6d297c8c73..3864a2775458 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1002,7 +1002,13 @@ struct ext4_super_block {
+ 	__u8	s_reserved_char_pad2;
+ 	__le16  s_reserved_pad;
+ 	__le64	s_kbytes_written;	/* nr of lifetime kilobytes written */
+-	__u32   s_reserved[160];        /* Padding to the end of the block */
++	__le32	s_snapshot_inum;	/* Inode number of active snapshot */
++	__le32	s_snapshot_id;		/* sequential ID of active snapshot */
++	__le64	s_snapshot_r_blocks_count; /* reserved blocks for active
++					      snapshot's future use */
++	__le32	s_snapshot_list;	/* inode number of the head of the
++					   on-disk snapshot list */
++	__u32   s_reserved[155];        /* Padding to the end of the block */
+ };
+ 
+ #ifdef __KERNEL__

commit 07a038245b28df9196ffb2e8cc626e9b956a4e23
+Author: Theodore Ts'o 
+Date:   Mon Jun 14 09:54:48 2010 -0400
+
+    ext4: Convert more i_flags references to use accessor functions
+    
+    These changes are not ones which are likely to result in races, but
+    they should be fixed.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index ea5e6cb7e2a5..2965c39d4183 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -121,7 +121,8 @@ static int ext4_readdir(struct file *filp,
+ 		 * We don't set the inode dirty flag since it's not
+ 		 * critical that it get flushed back to the disk.
+ 		 */
+-		ext4_clear_inode_flag(filp->f_path.dentry->d_inode, EXT4_INODE_INDEX);
++		ext4_clear_inode_flag(filp->f_path.dentry->d_inode,
++				      EXT4_INODE_INDEX);
+ 	}
+ 	stored = 0;
+ 	offset = filp->f_pos & (sb->s_blocksize - 1);
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 42272d67955a..6c6614cae9e6 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4976,7 +4976,7 @@ static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode,
+ 		/* we are using combined 48 bit field */
+ 		i_blocks = ((u64)le16_to_cpu(raw_inode->i_blocks_high)) << 32 |
+ 					le32_to_cpu(raw_inode->i_blocks_lo);
+-		if (ei->i_flags & EXT4_HUGE_FILE_FL) {
++		if (ext4_test_inode_flag(inode, EXT4_INODE_HUGE_FILE)) {
+ 			/* i_blocks represent file system block size */
+ 			return i_blocks  << (inode->i_blkbits - 9);
+ 		} else {
+@@ -5126,7 +5126,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 				 ei->i_file_acl);
+ 		ret = -EIO;
+ 		goto bad_inode;
+-	} else if (ei->i_flags & EXT4_EXTENTS_FL) {
++	} else if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {
+ 		if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+ 		    (S_ISLNK(inode->i_mode) &&
+ 		     !ext4_inode_is_fast_symlink(inode)))
+diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
+index 6f3a27ec30bf..1765c2c50a9b 100644
+--- a/fs/ext4/migrate.c
++++ b/fs/ext4/migrate.c
+@@ -376,7 +376,7 @@ static int ext4_ext_swap_inode_data(handle_t *handle, struct inode *inode,
+ 	 * We have the extent map build with the tmp inode.
+ 	 * Now copy the i_data across
+ 	 */
+-	ei->i_flags |= EXT4_EXTENTS_FL;
++	ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS);
+ 	memcpy(ei->i_data, tmp_ei->i_data, sizeof(ei->i_data));
+ 
+ 	/*

commit a0375156ca1041574b5d47cc7e32f10b891151b0
+Author: Theodore Ts'o 
+Date:   Fri Jun 11 23:14:04 2010 -0400
+
+    ext4: Clean up s_dirt handling
+    
+    We don't need to set s_dirt in most of the ext4 code when journaling
+    is enabled.  In ext3/4 some of the summary statistics for # of free
+    inodes, blocks, and directories are calculated from the per-block
+    group statistics when the file system is mounted or unmounted.  As a
+    result the superblock doesn't have to be updated, either via the
+    journal or by setting s_dirt.  There are a few exceptions, most
+    notably when resizing the file system, where the superblock needs to
+    be modified --- and in that case it should be done as a journalled
+    operation if possible, and s_dirt set only in no-journal mode.
+    
+    This patch will optimize out some unneeded disk writes when using ext4
+    with a journal.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 95b7594c76f9..bd30799a43ed 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -377,14 +377,11 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
+ 	ext4_grpblk_t bit;
+ 	unsigned int i;
+ 	struct ext4_group_desc *desc;
+-	struct ext4_super_block *es;
+-	struct ext4_sb_info *sbi;
++	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	int err = 0, ret, blk_free_count;
+ 	ext4_grpblk_t blocks_freed;
+ 	struct ext4_group_info *grp;
+ 
+-	sbi = EXT4_SB(sb);
+-	es = sbi->s_es;
+ 	ext4_debug("Adding block(s) %llu-%llu\n", block, block + count - 1);
+ 
+ 	ext4_get_group_no_and_offset(sb, block, &block_group, &bit);
+@@ -477,7 +474,6 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
+ 	ret = ext4_handle_dirty_metadata(handle, NULL, gd_bh);
+ 	if (!err)
+ 		err = ret;
+-	sb->s_dirt = 1;
+ 
+ error_return:
+ 	brelse(bitmap_bh);
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 19a4de57128a..8b56b53328eb 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1860,6 +1860,12 @@ static inline void ext4_unlock_group(struct super_block *sb,
+ 	spin_unlock(ext4_group_lock_ptr(sb, group));
+ }
+ 
++static inline void ext4_mark_super_dirty(struct super_block *sb)
++{
++	if (EXT4_SB(sb)->s_journal == NULL)
++		sb->s_dirt =1;
++}
++
+ /*
+  * Inodes and files operations
+  */
+diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
+index 53d2764d71ca..cfd27b38fa15 100644
+--- a/fs/ext4/ext4_jbd2.c
++++ b/fs/ext4/ext4_jbd2.c
+@@ -143,3 +143,19 @@ int __ext4_handle_dirty_metadata(const char *where, handle_t *handle,
+ 	}
+ 	return err;
+ }
++
++int __ext4_handle_dirty_super(const char *where, handle_t *handle,
++			      struct super_block *sb)
++{
++	struct buffer_head *bh = EXT4_SB(sb)->s_sbh;
++	int err = 0;
++
++	if (ext4_handle_valid(handle)) {
++		err = jbd2_journal_dirty_metadata(handle, bh);
++		if (err)
++			ext4_journal_abort_handle(where, __func__, bh,
++						  handle, err);
++	} else
++		sb->s_dirt = 1;
++	return err;
++}
+diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
+index dade0c024797..8ae8168900bf 100644
+--- a/fs/ext4/ext4_jbd2.h
++++ b/fs/ext4/ext4_jbd2.h
+@@ -141,6 +141,9 @@ int __ext4_journal_get_create_access(const char *where,
+ int __ext4_handle_dirty_metadata(const char *where, handle_t *handle,
+ 				 struct inode *inode, struct buffer_head *bh);
+ 
++int __ext4_handle_dirty_super(const char *where, handle_t *handle,
++			      struct super_block *sb);
++
+ #define ext4_journal_get_undo_access(handle, bh) \
+ 	__ext4_journal_get_undo_access(__func__, (handle), (bh))
+ #define ext4_journal_get_write_access(handle, bh) \
+@@ -152,6 +155,8 @@ int __ext4_handle_dirty_metadata(const char *where, handle_t *handle,
+ 	__ext4_journal_get_create_access(__func__, (handle), (bh))
+ #define ext4_handle_dirty_metadata(handle, inode, bh) \
+ 	__ext4_handle_dirty_metadata(__func__, (handle), (inode), (bh))
++#define ext4_handle_dirty_super(handle, sb) \
++	__ext4_handle_dirty_super(__func__, (handle), (sb))
+ 
+ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks);
+ int __ext4_journal_stop(const char *where, handle_t *handle);
+diff --git a/fs/ext4/file.c b/fs/ext4/file.c
+index 5313ae4cda2d..bd411c12d63d 100644
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -123,7 +123,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
+ 		if (!IS_ERR(cp)) {
+ 			memcpy(sbi->s_es->s_last_mounted, cp,
+ 			       sizeof(sbi->s_es->s_last_mounted));
+-			sb->s_dirt = 1;
++			ext4_mark_super_dirty(sb);
+ 		}
+ 	}
+ 	return dquot_file_open(inode, filp);
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 25c4b3173fd9..ac377505ed57 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -279,7 +279,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
+ 		err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
+ 		if (!fatal)
+ 			fatal = err;
+-		sb->s_dirt = 1;
++		ext4_mark_super_dirty(sb);
+ 	} else
+ 		ext4_error(sb, "bit already cleared for inode %lu", ino);
+ 
+@@ -965,7 +965,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
+ 	percpu_counter_dec(&sbi->s_freeinodes_counter);
+ 	if (S_ISDIR(mode))
+ 		percpu_counter_inc(&sbi->s_dirs_counter);
+-	sb->s_dirt = 1;
++	ext4_mark_super_dirty(sb);
+ 
+ 	if (sbi->s_log_groups_per_flex) {
+ 		flex_group = ext4_flex_group(sbi, group);
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 12b3bc026a68..d9d267181ddc 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2812,7 +2812,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
+ 	err = ext4_handle_dirty_metadata(handle, NULL, gdp_bh);
+ 
+ out_err:
+-	sb->s_dirt = 1;
++	ext4_mark_super_dirty(sb);
+ 	brelse(bitmap_bh);
+ 	return err;
+ }
+@@ -4680,7 +4680,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 		put_bh(bitmap_bh);
+ 		goto do_more;
+ 	}
+-	sb->s_dirt = 1;
++	ext4_mark_super_dirty(sb);
+ error_return:
+ 	if (freed)
+ 		dquot_free_block(inode, freed);
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 6df797eb9aeb..27527ae466ea 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -921,8 +921,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
+ 			   &sbi->s_flex_groups[flex_group].free_inodes);
+ 	}
+ 
+-	ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);
+-	sb->s_dirt = 1;
++	ext4_handle_dirty_super(handle, sb);
+ 
+ exit_journal:
+ 	mutex_unlock(&sbi->s_resize_lock);
+@@ -1045,13 +1044,12 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
+ 		goto exit_put;
+ 	}
+ 	ext4_blocks_count_set(es, o_blocks_count + add);
+-	ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh);
+-	sb->s_dirt = 1;
+ 	mutex_unlock(&EXT4_SB(sb)->s_resize_lock);
+ 	ext4_debug("freeing blocks %llu through %llu\n", o_blocks_count,
+ 		   o_blocks_count + add);
+ 	/* We add the blocks to the bitmap and set the group need init bit */
+ 	ext4_add_groupblocks(handle, sb, o_blocks_count, add);
++	ext4_handle_dirty_super(handle, sb);
+ 	ext4_debug("freed blocks %llu through %llu\n", o_blocks_count,
+ 		   o_blocks_count + add);
+ 	if ((err = ext4_journal_stop(handle)))
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 04338009793a..a6f314249574 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -458,8 +458,7 @@ static void ext4_xattr_update_super_block(handle_t *handle,
+ 
+ 	if (ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh) == 0) {
+ 		EXT4_SET_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_EXT_ATTR);
+-		sb->s_dirt = 1;
+-		ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh);
++		ext4_handle_dirty_super(handle, sb);
+ 	}
+ }
+ 

commit 1f5a81e41f8b1a782c68d3843e9ec1bfaadf7d72
+Author: Theodore Ts'o 
+Date:   Wed Jun 2 22:04:39 2010 -0400
+
+    ext4: Make sure the MOVE_EXT ioctl can't overwrite append-only files
+    
+    Dan Roseberg has reported a problem with the MOVE_EXT ioctl.  If the
+    donor file is an append-only file, we should not allow the operation
+    to proceed, lest we end up overwriting the contents of an append-only
+    file.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Dan Rosenberg 
+
+diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
+index 3a6c92ac131c..52abfa12762a 100644
+--- a/fs/ext4/move_extent.c
++++ b/fs/ext4/move_extent.c
+@@ -960,6 +960,9 @@ mext_check_arguments(struct inode *orig_inode,
+ 		return -EINVAL;
+ 	}
+ 
++	if (IS_IMMUTABLE(donor_inode) || IS_APPEND(donor_inode))
++		return -EPERM;
++
+ 	/* Ext4 move extent does not support swapfile */
+ 	if (IS_SWAPFILE(orig_inode) || IS_SWAPFILE(donor_inode)) {
+ 		ext4_debug("ext4 move extent: The argument files should "

commit 60e6679e28518ccd67169c4a539d8cc7490eb8a6
+Author: Theodore Ts'o 
+Date:   Mon May 17 07:00:00 2010 -0400
+
+    ext4: Drop whitespace at end of lines
+    
+    This patch was generated using:
+    
+    #!/usr/bin/perl -i
+    while (<>) {
+        s/[         ]+$//;
+        print;
+    }
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/block_validity.c b/fs/ext4/block_validity.c
+index 538c48655084..5b6973fbf1bd 100644
+--- a/fs/ext4/block_validity.c
++++ b/fs/ext4/block_validity.c
+@@ -72,9 +72,9 @@ static int add_system_zone(struct ext4_sb_info *sbi,
+ 		else if (start_blk >= (entry->start_blk + entry->count))
+ 			n = &(*n)->rb_right;
+ 		else {
+-			if (start_blk + count > (entry->start_blk + 
++			if (start_blk + count > (entry->start_blk +
+ 						 entry->count))
+-				entry->count = (start_blk + count - 
++				entry->count = (start_blk + count -
+ 						entry->start_blk);
+ 			new_node = *n;
+ 			new_entry = rb_entry(new_node, struct ext4_system_zone,
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 2c1165f731ac..124ef771a618 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -75,7 +75,7 @@ typedef __u32 ext4_lblk_t;
+ typedef unsigned int ext4_group_t;
+ 
+ /*
+- * Flags used in mballoc's allocation_context flags field.  
++ * Flags used in mballoc's allocation_context flags field.
+  *
+  * Also used to show what's going on for debugging purposes when the
+  * flag field is exported via the traceport interface
+@@ -470,7 +470,7 @@ struct ext4_new_group_data {
+ #define EXT4_GET_BLOCKS_CREATE_UNINIT_EXT	(EXT4_GET_BLOCKS_UNINIT_EXT|\
+ 						 EXT4_GET_BLOCKS_CREATE)
+ 	/* Caller is from the delayed allocation writeout path,
+-	   so set the magic i_delalloc_reserve_flag after taking the 
++	   so set the magic i_delalloc_reserve_flag after taking the
+ 	   inode allocation semaphore for */
+ #define EXT4_GET_BLOCKS_DELALLOC_RESERVE	0x0004
+ 	/* caller is from the direct IO path, request to creation of an
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 0a47becf668a..377309c1af65 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -182,10 +182,10 @@ static ext4_fsblk_t ext4_ext_find_goal(struct inode *inode,
+ 	if (flex_size >= EXT4_FLEX_SIZE_DIR_ALLOC_SCHEME) {
+ 		/*
+ 		 * If there are at least EXT4_FLEX_SIZE_DIR_ALLOC_SCHEME
+-		 * block groups per flexgroup, reserve the first block 
+-		 * group for directories and special files.  Regular 
++		 * block groups per flexgroup, reserve the first block
++		 * group for directories and special files.  Regular
+ 		 * files will start at the second block group.  This
+-		 * tends to speed up directory access and improves 
++		 * tends to speed up directory access and improves
+ 		 * fsck times.
+ 		 */
+ 		block_group &= ~(flex_size-1);
+@@ -2034,7 +2034,7 @@ ext4_ext_in_cache(struct inode *inode, ext4_lblk_t block,
+ 	struct ext4_ext_cache *cex;
+ 	int ret = EXT4_EXT_CACHE_NO;
+ 
+-	/* 
++	/*
+ 	 * We borrow i_block_reservation_lock to protect i_cached_extent
+ 	 */
+ 	spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
+diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
+index 42bd94a942c9..6ca7b6e59d83 100644
+--- a/fs/ext4/fsync.c
++++ b/fs/ext4/fsync.c
+@@ -66,7 +66,7 @@ int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync)
+ 	ret = flush_completed_IO(inode);
+ 	if (ret < 0)
+ 		return ret;
+-	
++
+ 	if (!journal)
+ 		return simple_fsync(file, dentry, datasync);
+ 
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 8e45331b6560..502b07dc70d0 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -784,7 +784,7 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
+ 	/* Allocation failed, free what we already allocated */
+ 	ext4_free_blocks(handle, inode, 0, new_blocks[0], 1, 0);
+ 	for (i = 1; i <= n ; i++) {
+-		/* 
++		/*
+ 		 * branch[i].bh is newly allocated, so there is no
+ 		 * need to revoke the block, which is why we don't
+ 		 * need to set EXT4_FREE_BLOCKS_METADATA.
+@@ -874,7 +874,7 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
+ 
+ err_out:
+ 	for (i = 1; i <= num; i++) {
+-		/* 
++		/*
+ 		 * branch[i].bh is newly allocated, so there is no
+ 		 * need to revoke the block, which is why we don't
+ 		 * need to set EXT4_FREE_BLOCKS_METADATA.
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index 6ddec84846cd..bf5ae883b1bd 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -258,7 +258,7 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 		if (me.moved_len > 0)
+ 			file_remove_suid(donor_filp);
+ 
+-		if (copy_to_user((struct move_extent __user *)arg, 
++		if (copy_to_user((struct move_extent __user *)arg,
+ 				 &me, sizeof(me)))
+ 			err = -EFAULT;
+ mext_out:
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index a93f554b6803..12b3bc026a68 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2691,7 +2691,7 @@ int __init init_ext4_mballoc(void)
+ 
+ void exit_ext4_mballoc(void)
+ {
+-	/* 
++	/*
+ 	 * Wait for completion of call_rcu()'s on ext4_pspace_cachep
+ 	 * before destroying the slab cache.
+ 	 */
+@@ -3330,7 +3330,7 @@ static void ext4_mb_put_pa(struct ext4_allocation_context *ac,
+ 	spin_unlock(&pa->pa_lock);
+ 
+ 	grp_blk = pa->pa_pstart;
+-	/* 
++	/*
+ 	 * If doing group-based preallocation, pa_pstart may be in the
+ 	 * next group when pa is used up
+ 	 */
+@@ -4534,12 +4534,12 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 			if (!bh)
+ 				tbh = sb_find_get_block(inode->i_sb,
+ 							block + i);
+-			ext4_forget(handle, flags & EXT4_FREE_BLOCKS_METADATA, 
++			ext4_forget(handle, flags & EXT4_FREE_BLOCKS_METADATA,
+ 				    inode, tbh, block + i);
+ 		}
+ 	}
+ 
+-	/* 
++	/*
+ 	 * We need to make sure we don't reuse the freed block until
+ 	 * after the transaction is committed, which we can do by
+ 	 * treating the block as metadata, below.  We make an
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 7b4bf8feae4e..83be743c8d1f 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -187,7 +187,7 @@ unsigned int ext4_rec_len_from_disk(__le16 dlen, unsigned blocksize)
+ 		return blocksize;
+ 	return (len & 65532) | ((len & 3) << 16);
+ }
+-  
++
+ __le16 ext4_rec_len_to_disk(unsigned len, unsigned blocksize)
+ {
+ 	if ((len > blocksize) || (blocksize > (1 << 18)) || (len & 3))
+@@ -197,7 +197,7 @@ __le16 ext4_rec_len_to_disk(unsigned len, unsigned blocksize)
+ 	if (len == blocksize) {
+ 		if (blocksize == 65536)
+ 			return cpu_to_le16(EXT4_MAX_REC_LEN);
+-		else 
++		else
+ 			return cpu_to_le16(0);
+ 	}
+ 	return cpu_to_le16((len & 65532) | ((len >> 16) & 3));
+@@ -349,7 +349,7 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir,
+ 		brelse(bh);
+ 	}
+ 	if (bcount)
+-		printk(KERN_DEBUG "%snames %u, fullness %u (%u%%)\n", 
++		printk(KERN_DEBUG "%snames %u, fullness %u (%u%%)\n",
+ 		       levels ? "" : "   ", names, space/bcount,
+ 		       (space/bcount)*100/blocksize);
+ 	return (struct stats) { names, space, bcount};
+@@ -653,7 +653,7 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
+ 	int ret, err;
+ 	__u32 hashval;
+ 
+-	dxtrace(printk(KERN_DEBUG "In htree_fill_tree, start hash: %x:%x\n", 
++	dxtrace(printk(KERN_DEBUG "In htree_fill_tree, start hash: %x:%x\n",
+ 		       start_hash, start_minor_hash));
+ 	dir = dir_file->f_path.dentry->d_inode;
+ 	if (!(ext4_test_inode_flag(dir, EXT4_INODE_INDEX))) {
+@@ -1141,7 +1141,7 @@ dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count,
+ 	unsigned rec_len = 0;
+ 
+ 	while (count--) {
+-		struct ext4_dir_entry_2 *de = (struct ext4_dir_entry_2 *) 
++		struct ext4_dir_entry_2 *de = (struct ext4_dir_entry_2 *)
+ 						(from + (map->offs<<2));
+ 		rec_len = EXT4_DIR_REC_LEN(de->name_len);
+ 		memcpy (to, de, rec_len);
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 9766b2ae6cdc..49d88c0597c4 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2216,7 +2216,7 @@ static unsigned long ext4_get_stripe_size(struct ext4_sb_info *sbi)
+ struct ext4_attr {
+ 	struct attribute attr;
+ 	ssize_t (*show)(struct ext4_attr *, struct ext4_sb_info *, char *);
+-	ssize_t (*store)(struct ext4_attr *, struct ext4_sb_info *, 
++	ssize_t (*store)(struct ext4_attr *, struct ext4_sb_info *,
+ 			 const char *, size_t);
+ 	int offset;
+ };
+@@ -3383,7 +3383,7 @@ static int ext4_commit_super(struct super_block *sb, int sync)
+ 	if (!(sb->s_flags & MS_RDONLY))
+ 		es->s_wtime = cpu_to_le32(get_seconds());
+ 	es->s_kbytes_written =
+-		cpu_to_le64(EXT4_SB(sb)->s_kbytes_written + 
++		cpu_to_le64(EXT4_SB(sb)->s_kbytes_written +
+ 			    ((part_stat_read(sb->s_bdev->bd_part, sectors[1]) -
+ 			      EXT4_SB(sb)->s_sectors_written_start) >> 1));
+ 	ext4_free_blocks_count_set(es, percpu_counter_sum_positive(

commit f307333e14f6b18045eb4198fe646d9b6028f3ed
+Author: Theodore Ts'o 
+Date:   Mon May 17 03:00:00 2010 -0400
+
+    ext4: Add new tracepoints to track mballoc's buddy bitmap loads
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 0bdc0188e5e2..a93f554b6803 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -890,6 +890,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
+ 			BUG_ON(incore == NULL);
+ 			mb_debug(1, "put buddy for group %u in page %lu/%x\n",
+ 				group, page->index, i * blocksize);
++			trace_ext4_mb_buddy_bitmap_load(sb, group);
+ 			grinfo = ext4_get_group_info(sb, group);
+ 			grinfo->bb_fragments = 0;
+ 			memset(grinfo->bb_counters, 0,
+@@ -907,6 +908,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
+ 			BUG_ON(incore != NULL);
+ 			mb_debug(1, "put bitmap for group %u in page %lu/%x\n",
+ 				group, page->index, i * blocksize);
++			trace_ext4_mb_bitmap_load(sb, group);
+ 
+ 			/* see comments in ext4_mb_put_pa() */
+ 			ext4_lock_group(sb, group);
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index 2aa6aa3e8f61..99fbf1d0a6b9 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -974,6 +974,39 @@ TRACE_EVENT(ext4_da_release_space,
+ 		  __entry->reserved_meta_blocks, __entry->allocated_meta_blocks)
+ );
+ 
++DECLARE_EVENT_CLASS(ext4__bitmap_load,
++	TP_PROTO(struct super_block *sb, unsigned long group),
++
++	TP_ARGS(sb, group),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	__u32,	group			)
++
++	),
++
++	TP_fast_assign(
++		__entry->dev	= sb->s_dev;
++		__entry->group	= group;
++	),
++
++	TP_printk("dev %s group %u",
++		  jbd2_dev_to_name(__entry->dev), __entry->group)
++);
++
++DEFINE_EVENT(ext4__bitmap_load, ext4_mb_bitmap_load,
++
++	TP_PROTO(struct super_block *sb, unsigned long group),
++
++	TP_ARGS(sb, group)
++);
++
++DEFINE_EVENT(ext4__bitmap_load, ext4_mb_buddy_bitmap_load,
++
++	TP_PROTO(struct super_block *sb, unsigned long group),
++
++	TP_ARGS(sb, group)
++);
+ 
+ #endif /* _TRACE_EXT4_H */
+ 

commit 786ec7915e530936b9eb2e3d12274145cab7aa7d
+Author: Theodore Ts'o 
+Date:   Mon May 17 00:00:00 2010 -0400
+
+    ext4: Clear the EXT4_EOFBLOCKS_FL flag only when warranted
+    
+    Dimitry Monakhov discovered an edge case where it was possible for the
+    EXT4_EOFBLOCKS_FL flag could get cleared unnecessarily.  This is true;
+    I have a test case that can be exercised via downloading and
+    decompressing the file:
+    
+    wget ftp://ftp.kernel.org/pub/linux/kernel/people/tytso/ext4-testcases/eofblocks-fl-test-case.img.bz2
+    bunzip2 eofblocks-fl-test-case.img
+    dd if=/dev/zero of=eofblocks-fl-test-case.img bs=1k seek=17925 bs=1k count=1 conv=notrunc
+    
+    However, triggering it in real life is highly unlikely since it
+    requires an extremely fragmented sparse file with a hole in exactly
+    the right place in the extent tree.  (It actually took quite a bit of
+    work to generate this test case.)  Still, it's nice to get even
+    extreme corner cases to be correct, so this patch makes sure that we
+    don't clear the EXT4_EOFBLOCKS_FL incorrectly even in this corner
+    case.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index e40d2b793f2d..ffcaa1137def 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -3319,7 +3319,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 	struct ext4_extent_header *eh;
+ 	struct ext4_extent newex, *ex, *last_ex;
+ 	ext4_fsblk_t newblock;
+-	int err = 0, depth, ret, cache_type;
++	int i, err = 0, depth, ret, cache_type;
+ 	unsigned int allocated = 0;
+ 	struct ext4_allocation_request ar;
+ 	ext4_io_end_t *io = EXT4_I(inode)->cur_aio_dio;
+@@ -3508,8 +3508,20 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 			goto out2;
+ 		}
+ 		last_ex = EXT_LAST_EXTENT(eh);
+-		if (map->m_lblk + ar.len > le32_to_cpu(last_ex->ee_block)
+-		    + ext4_ext_get_actual_len(last_ex))
++		/*
++		 * If the current leaf block was reached by looking at
++		 * the last index block all the way down the tree, and
++		 * we are extending the inode beyond the last extent
++		 * in the current leaf block, then clear the
++		 * EOFBLOCKS_FL flag.
++		 */
++		for (i = depth-1; i >= 0; i--) {
++			if (path[i].p_idx != EXT_LAST_INDEX(path[i].p_hdr))
++				break;
++		}
++		if ((i < 0) &&
++		    (map->m_lblk + ar.len > le32_to_cpu(last_ex->ee_block) +
++		     ext4_ext_get_actual_len(last_ex)))
+ 			ext4_clear_inode_flag(inode, EXT4_INODE_EOFBLOCKS);
+ 	}
+ 	err = ext4_ext_insert_extent(handle, inode, path, &newex, flags);

commit f70f362b4a6fe47c239dbfb3efc0cc2c10e4f09c
+Author: Theodore Ts'o 
+Date:   Sun May 16 23:00:00 2010 -0400
+
+    ext4: Avoid crashing on NULL ptr dereference on a filesystem error
+    
+    If the EOFBLOCK_FL flag is set when it should not be and the inode is
+    zero length, then eh_entries is zero, and ex is NULL, so dereferencing
+    ex to print ex->ee_block causes a kernel OOPS in
+    ext4_ext_map_blocks().
+    
+    On top of that, the error message which is printed isn't very helpful.
+    So we fix this by printing something more explanatory which doesn't
+    involve trying to print ex->ee_block.
+    
+    Addresses-Google-Bug: #2655740
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 42d8ce91adbd..e40d2b793f2d 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -3370,8 +3370,9 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 	 */
+ 	if (unlikely(path[depth].p_ext == NULL && depth != 0)) {
+ 		EXT4_ERROR_INODE(inode, "bad extent address "
+-				 "iblock: %d, depth: %d pblock %lld",
+-				 map->m_lblk, depth, path[depth].p_block);
++				 "lblock: %lu, depth: %d pblock %lld",
++				 (unsigned long) map->m_lblk, depth,
++				 path[depth].p_block);
+ 		err = -EIO;
+ 		goto out2;
+ 	}
+@@ -3501,8 +3502,8 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ 	if (unlikely(ext4_test_inode_flag(inode, EXT4_INODE_EOFBLOCKS))) {
+ 		if (unlikely(!eh->eh_entries)) {
+ 			EXT4_ERROR_INODE(inode,
+-					 "eh->eh_entries == 0 ee_block %d",
+-					 ex->ee_block);
++					 "eh->eh_entries == 0 and "
++					 "EOFBLOCKS_FL set");
+ 			err = -EIO;
+ 			goto out2;
+ 		}

commit 24676da469f50f433baa347845639662c561d1f6
+Author: Theodore Ts'o 
+Date:   Sun May 16 21:00:00 2010 -0400
+
+    ext4: Convert calls of ext4_error() to EXT4_ERROR_INODE()
+    
+    EXT4_ERROR_INODE() tends to provide better error information and in a
+    more consistent format.  Some errors were not even identifying the inode
+    or directory which was corrupted, which made them not very useful.
+    
+    Addresses-Google-Bug: #2507977
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index e3f2700b8be7..6a2b8bcff641 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -83,11 +83,10 @@ int ext4_check_dir_entry(const char *function, struct inode *dir,
+ 		error_msg = "inode out of bounds";
+ 
+ 	if (error_msg != NULL)
+-		__ext4_error(dir->i_sb, function,
+-			"bad entry in directory #%lu: %s - block=%llu"
++		ext4_error_inode(function, dir,
++			"bad entry in directory: %s - block=%llu"
+ 			"offset=%u(%u), inode=%u, rec_len=%d, name_len=%d",
+-			dir->i_ino, error_msg, 
+-			(unsigned long long) bh->b_blocknr,     
++			error_msg, (unsigned long long) bh->b_blocknr,
+ 			(unsigned) (offset%bh->b_size), offset,
+ 			le32_to_cpu(de->inode),
+ 			rlen, de->name_len);
+@@ -152,9 +151,8 @@ static int ext4_readdir(struct file *filp,
+ 		 */
+ 		if (!bh) {
+ 			if (!dir_has_error) {
+-				ext4_error(sb, "directory #%lu "
++				EXT4_ERROR_INODE(inode, "directory "
+ 					   "contains a hole at offset %Lu",
+-					   inode->i_ino,
+ 					   (unsigned long long) filp->f_pos);
+ 				dir_has_error = 1;
+ 			}
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 57fc0e5c0918..413321ff1e20 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -54,10 +54,10 @@
+ #endif
+ 
+ #define EXT4_ERROR_INODE(inode, fmt, a...) \
+-	ext4_error_inode(__func__, (inode), (fmt), ## a);
++	ext4_error_inode(__func__, (inode), (fmt), ## a)
+ 
+ #define EXT4_ERROR_FILE(file, fmt, a...)	\
+-	ext4_error_file(__func__, (file), (fmt), ## a);
++	ext4_error_file(__func__, (file), (fmt), ## a)
+ 
+ /* data type for block offset of block group */
+ typedef int ext4_grpblk_t;
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index d6801eb7232b..91c3873970e4 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -439,10 +439,10 @@ static int __ext4_ext_check(const char *function, struct inode *inode,
+ 	return 0;
+ 
+ corrupted:
+-	__ext4_error(inode->i_sb, function,
+-			"bad header/extent in inode #%lu: %s - magic %x, "
++	ext4_error_inode(function, inode,
++			"bad header/extent: %s - magic %x, "
+ 			"entries %u, max %u(%u), depth %u(%u)",
+-			inode->i_ino, error_msg, le16_to_cpu(eh->eh_magic),
++			error_msg, le16_to_cpu(eh->eh_magic),
+ 			le16_to_cpu(eh->eh_entries), le16_to_cpu(eh->eh_max),
+ 			max, le16_to_cpu(eh->eh_depth), depth);
+ 
+@@ -1622,9 +1622,7 @@ int ext4_ext_try_to_merge(struct inode *inode,
+ 		merge_done = 1;
+ 		WARN_ON(eh->eh_entries == 0);
+ 		if (!eh->eh_entries)
+-			ext4_error(inode->i_sb,
+-				   "inode#%lu, eh->eh_entries = 0!",
+-				   inode->i_ino);
++			EXT4_ERROR_INODE(inode, "eh->eh_entries = 0!");
+ 	}
+ 
+ 	return merge_done;
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 0b1d7c89f93f..3b6877257580 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -348,9 +348,8 @@ static int __ext4_check_blockref(const char *function, struct inode *inode,
+ 		if (blk &&
+ 		    unlikely(!ext4_data_block_valid(EXT4_SB(inode->i_sb),
+ 						    blk, 1))) {
+-			__ext4_error(inode->i_sb, function,
+-				   "invalid block reference %u "
+-				   "in inode #%lu", blk, inode->i_ino);
++			ext4_error_inode(function, inode,
++					 "invalid block reference %u", blk);
+ 			return -EIO;
+ 		}
+ 	}
+@@ -1129,15 +1128,15 @@ void ext4_da_update_reserve_space(struct inode *inode,
+ 		ext4_discard_preallocations(inode);
+ }
+ 
+-static int check_block_validity(struct inode *inode, const char *msg,
+-				sector_t logical, sector_t phys, int len)
++static int check_block_validity(struct inode *inode, const char *func,
++				struct ext4_map_blocks *map)
+ {
+-	if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), phys, len)) {
+-		__ext4_error(inode->i_sb, msg,
+-			   "inode #%lu logical block %llu mapped to %llu "
+-			   "(size %d)", inode->i_ino,
+-			   (unsigned long long) logical,
+-			   (unsigned long long) phys, len);
++	if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), map->m_pblk,
++				   map->m_len)) {
++		ext4_error_inode(func, inode,
++			   "lblock %lu mapped to illegal pblock %llu "
++			   "(length %d)", (unsigned long) map->m_lblk,
++				 map->m_pblk, map->m_len);
+ 		return -EIO;
+ 	}
+ 	return 0;
+@@ -1245,8 +1244,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
+ 	up_read((&EXT4_I(inode)->i_data_sem));
+ 
+ 	if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) {
+-		int ret = check_block_validity(inode, "file system corruption",
+-					map->m_lblk, map->m_pblk, retval);
++		int ret = check_block_validity(inode, __func__, map);
+ 		if (ret != 0)
+ 			return ret;
+ 	}
+@@ -1326,10 +1324,9 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
+ 
+ 	up_write((&EXT4_I(inode)->i_data_sem));
+ 	if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) {
+-		int ret = check_block_validity(inode, "file system "
+-					       "corruption after allocation",
+-					       map->m_lblk, map->m_pblk,
+-					       retval);
++		int ret = check_block_validity(inode,
++					       "ext4_map_blocks_after_alloc",
++					       map);
+ 		if (ret != 0)
+ 			return ret;
+ 	}
+@@ -4327,10 +4324,9 @@ static int ext4_clear_blocks(handle_t *handle, struct inode *inode,
+ 
+ 	if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), block_to_free,
+ 				   count)) {
+-		ext4_error(inode->i_sb, "inode #%lu: "
+-			   "attempt to clear blocks %llu len %lu, invalid",
+-			   inode->i_ino, (unsigned long long) block_to_free,
+-			   count);
++		EXT4_ERROR_INODE(inode, "attempt to clear invalid "
++				 "blocks %llu len %lu",
++				 (unsigned long long) block_to_free, count);
+ 		return 1;
+ 	}
+ 
+@@ -4435,11 +4431,10 @@ static void ext4_free_data(handle_t *handle, struct inode *inode,
+ 		if ((EXT4_JOURNAL(inode) == NULL) || bh2jh(this_bh))
+ 			ext4_handle_dirty_metadata(handle, inode, this_bh);
+ 		else
+-			ext4_error(inode->i_sb,
+-				   "circular indirect block detected, "
+-				   "inode=%lu, block=%llu",
+-				   inode->i_ino,
+-				   (unsigned long long) this_bh->b_blocknr);
++			EXT4_ERROR_INODE(inode,
++					 "circular indirect block detected at "
++					 "block %llu",
++				(unsigned long long) this_bh->b_blocknr);
+ 	}
+ }
+ 
+@@ -4477,11 +4472,10 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
+ 
+ 			if (!ext4_data_block_valid(EXT4_SB(inode->i_sb),
+ 						   nr, 1)) {
+-				ext4_error(inode->i_sb,
+-					   "indirect mapped block in inode "
+-					   "#%lu invalid (level %d, blk #%lu)",
+-					   inode->i_ino, depth,
+-					   (unsigned long) nr);
++				EXT4_ERROR_INODE(inode,
++						 "invalid indirect mapped "
++						 "block %lu (level %d)",
++						 (unsigned long) nr, depth);
+ 				break;
+ 			}
+ 
+@@ -4493,9 +4487,9 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
+ 			 * (should be rare).
+ 			 */
+ 			if (!bh) {
+-				ext4_error(inode->i_sb,
+-					   "Read failure, inode=%lu, block=%llu",
+-					   inode->i_ino, nr);
++				EXT4_ERROR_INODE(inode,
++						 "Read failure block=%llu",
++						 (unsigned long long) nr);
+ 				continue;
+ 			}
+ 
+@@ -4810,8 +4804,8 @@ static int __ext4_get_inode_loc(struct inode *inode,
+ 
+ 	bh = sb_getblk(sb, block);
+ 	if (!bh) {
+-		ext4_error(sb, "unable to read inode block - "
+-			   "inode=%lu, block=%llu", inode->i_ino, block);
++		EXT4_ERROR_INODE(inode, "unable to read inode block - "
++				 "block %llu", block);
+ 		return -EIO;
+ 	}
+ 	if (!buffer_uptodate(bh)) {
+@@ -4909,8 +4903,8 @@ static int __ext4_get_inode_loc(struct inode *inode,
+ 		submit_bh(READ_META, bh);
+ 		wait_on_buffer(bh);
+ 		if (!buffer_uptodate(bh)) {
+-			ext4_error(sb, "unable to read inode block - inode=%lu,"
+-				   " block=%llu", inode->i_ino, block);
++			EXT4_ERROR_INODE(inode, "unable to read inode "
++					 "block %llu", block);
+ 			brelse(bh);
+ 			return -EIO;
+ 		}
+@@ -5121,8 +5115,8 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 	ret = 0;
+ 	if (ei->i_file_acl &&
+ 	    !ext4_data_block_valid(EXT4_SB(sb), ei->i_file_acl, 1)) {
+-		ext4_error(sb, "bad extended attribute block %llu inode #%lu",
+-			   ei->i_file_acl, inode->i_ino);
++		EXT4_ERROR_INODE(inode, "bad extended attribute block %llu",
++				 ei->i_file_acl);
+ 		ret = -EIO;
+ 		goto bad_inode;
+ 	} else if (ei->i_flags & EXT4_EXTENTS_FL) {
+@@ -5167,8 +5161,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 			   new_decode_dev(le32_to_cpu(raw_inode->i_block[1])));
+ 	} else {
+ 		ret = -EIO;
+-		ext4_error(inode->i_sb, "bogus i_mode (%o) for inode=%lu",
+-			   inode->i_mode, inode->i_ino);
++		EXT4_ERROR_INODE(inode, "bogus i_mode (%o)", inode->i_mode);
+ 		goto bad_inode;
+ 	}
+ 	brelse(iloc.bh);
+@@ -5406,9 +5399,9 @@ int ext4_write_inode(struct inode *inode, struct writeback_control *wbc)
+ 		if (wbc->sync_mode == WB_SYNC_ALL)
+ 			sync_dirty_buffer(iloc.bh);
+ 		if (buffer_req(iloc.bh) && !buffer_uptodate(iloc.bh)) {
+-			ext4_error(inode->i_sb, "IO error syncing inode, "
+-				   "inode=%lu, block=%llu", inode->i_ino,
+-				   (unsigned long long)iloc.bh->b_blocknr);
++			EXT4_ERROR_INODE(inode,
++				"IO error syncing inode (block=%llu)",
++				(unsigned long long) iloc.bh->b_blocknr);
+ 			err = -EIO;
+ 		}
+ 		brelse(iloc.bh);
+diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
+index 82621a360932..b8b8ea1ceda8 100644
+--- a/fs/ext4/move_extent.c
++++ b/fs/ext4/move_extent.c
+@@ -530,7 +530,7 @@ mext_leaf_block(handle_t *handle, struct inode *orig_inode,
+ 	 * new_ext       |-------|
+ 	 */
+ 	if (le32_to_cpu(oext->ee_block) + oext_alen - 1 < new_ext_end) {
+-		ext4_error(orig_inode->i_sb,
++		EXT4_ERROR_INODE(orig_inode,
+ 			"new_ext_end(%u) should be less than or equal to "
+ 			"oext->ee_block(%u) + oext_alen(%d) - 1",
+ 			new_ext_end, le32_to_cpu(oext->ee_block),
+@@ -693,12 +693,12 @@ mext_replace_branches(handle_t *handle, struct inode *orig_inode,
+ 	while (1) {
+ 		/* The extent for donor must be found. */
+ 		if (!dext) {
+-			ext4_error(donor_inode->i_sb,
++			EXT4_ERROR_INODE(donor_inode,
+ 				   "The extent for donor must be found");
+ 			*err = -EIO;
+ 			goto out;
+ 		} else if (donor_off != le32_to_cpu(tmp_dext.ee_block)) {
+-			ext4_error(donor_inode->i_sb,
++			EXT4_ERROR_INODE(donor_inode,
+ 				"Donor offset(%u) and the first block of donor "
+ 				"extent(%u) should be equal",
+ 				donor_off,
+@@ -1355,7 +1355,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp,
+ 			if (ret1 < 0)
+ 				break;
+ 			if (*moved_len > len) {
+-				ext4_error(orig_inode->i_sb,
++				EXT4_ERROR_INODE(orig_inode,
+ 					"We replaced blocks too much! "
+ 					"sum of replaced: %llu requested: %llu",
+ 					*moved_len, len);
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 0c070fabd108..bff77b04f0d1 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -943,8 +943,8 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
+ 		wait_on_buffer(bh);
+ 		if (!buffer_uptodate(bh)) {
+ 			/* read error, skip block & hope for the best */
+-			ext4_error(sb, "reading directory #%lu offset %lu",
+-				   dir->i_ino, (unsigned long)block);
++			EXT4_ERROR_INODE(dir, "reading directory lblock %lu",
++					 (unsigned long) block);
+ 			brelse(bh);
+ 			goto next;
+ 		}
+@@ -1066,15 +1066,15 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, stru
+ 		__u32 ino = le32_to_cpu(de->inode);
+ 		brelse(bh);
+ 		if (!ext4_valid_inum(dir->i_sb, ino)) {
+-			ext4_error(dir->i_sb, "bad inode number: %u", ino);
++			EXT4_ERROR_INODE(dir, "bad inode number: %u", ino);
+ 			return ERR_PTR(-EIO);
+ 		}
+ 		inode = ext4_iget(dir->i_sb, ino);
+ 		if (unlikely(IS_ERR(inode))) {
+ 			if (PTR_ERR(inode) == -ESTALE) {
+-				ext4_error(dir->i_sb,
+-						"deleted inode referenced: %u",
+-						ino);
++				EXT4_ERROR_INODE(dir,
++						 "deleted inode referenced: %u",
++						 ino);
+ 				return ERR_PTR(-EIO);
+ 			} else {
+ 				return ERR_CAST(inode);
+@@ -1104,8 +1104,8 @@ struct dentry *ext4_get_parent(struct dentry *child)
+ 	brelse(bh);
+ 
+ 	if (!ext4_valid_inum(child->d_inode->i_sb, ino)) {
+-		ext4_error(child->d_inode->i_sb,
+-			   "bad inode number: %u", ino);
++		EXT4_ERROR_INODE(child->d_inode,
++				 "bad parent inode number: %u", ino);
+ 		return ERR_PTR(-EIO);
+ 	}
+ 
+@@ -1404,9 +1404,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
+ 	de = (struct ext4_dir_entry_2 *)((char *)fde +
+ 		ext4_rec_len_from_disk(fde->rec_len, blocksize));
+ 	if ((char *) de >= (((char *) root) + blocksize)) {
+-		ext4_error(dir->i_sb,
+-			   "invalid rec_len for '..' in inode %lu",
+-			   dir->i_ino);
++		EXT4_ERROR_INODE(dir, "invalid rec_len for '..'");
+ 		brelse(bh);
+ 		return -EIO;
+ 	}
+@@ -1915,9 +1913,8 @@ static int empty_dir(struct inode *inode)
+ 	if (inode->i_size < EXT4_DIR_REC_LEN(1) + EXT4_DIR_REC_LEN(2) ||
+ 	    !(bh = ext4_bread(NULL, inode, 0, 0, &err))) {
+ 		if (err)
+-			ext4_error(inode->i_sb,
+-				   "error %d reading directory #%lu offset 0",
+-				   err, inode->i_ino);
++			EXT4_ERROR_INODE(inode,
++				"error %d reading directory lblock 0", err);
+ 		else
+ 			ext4_warning(inode->i_sb,
+ 				     "bad directory (dir #%lu) - no data block",
+@@ -1941,17 +1938,17 @@ static int empty_dir(struct inode *inode)
+ 	de = ext4_next_entry(de1, sb->s_blocksize);
+ 	while (offset < inode->i_size) {
+ 		if (!bh ||
+-			(void *) de >= (void *) (bh->b_data+sb->s_blocksize)) {
++		    (void *) de >= (void *) (bh->b_data+sb->s_blocksize)) {
++			unsigned int lblock;
+ 			err = 0;
+ 			brelse(bh);
+-			bh = ext4_bread(NULL, inode,
+-				offset >> EXT4_BLOCK_SIZE_BITS(sb), 0, &err);
++			lblock = offset >> EXT4_BLOCK_SIZE_BITS(sb);
++			bh = ext4_bread(NULL, inode, lblock, 0, &err);
+ 			if (!bh) {
+ 				if (err)
+-					ext4_error(sb,
+-						   "error %d reading directory"
+-						   " #%lu offset %u",
+-						   err, inode->i_ino, offset);
++					EXT4_ERROR_INODE(inode,
++						"error %d reading directory "
++						"lblock %u", err, lblock);
+ 				offset += sb->s_blocksize;
+ 				continue;
+ 			}
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index b4c5aa8489d8..0a09a2e96f0a 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -228,9 +228,8 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
+ 		atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
+ 	if (ext4_xattr_check_block(bh)) {
+ bad_block:
+-		ext4_error(inode->i_sb,
+-			   "inode %lu: bad block %llu", inode->i_ino,
+-			   EXT4_I(inode)->i_file_acl);
++		EXT4_ERROR_INODE(inode, "bad block %llu",
++				 EXT4_I(inode)->i_file_acl);
+ 		error = -EIO;
+ 		goto cleanup;
+ 	}
+@@ -372,9 +371,8 @@ ext4_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size)
+ 	ea_bdebug(bh, "b_count=%d, refcount=%d",
+ 		atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
+ 	if (ext4_xattr_check_block(bh)) {
+-		ext4_error(inode->i_sb,
+-			   "inode %lu: bad block %llu", inode->i_ino,
+-			   EXT4_I(inode)->i_file_acl);
++		EXT4_ERROR_INODE(inode, "bad block %llu",
++				 EXT4_I(inode)->i_file_acl);
+ 		error = -EIO;
+ 		goto cleanup;
+ 	}
+@@ -666,8 +664,8 @@ ext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i,
+ 			atomic_read(&(bs->bh->b_count)),
+ 			le32_to_cpu(BHDR(bs->bh)->h_refcount));
+ 		if (ext4_xattr_check_block(bs->bh)) {
+-			ext4_error(sb, "inode %lu: bad block %llu",
+-				   inode->i_ino, EXT4_I(inode)->i_file_acl);
++			EXT4_ERROR_INODE(inode, "bad block %llu",
++					 EXT4_I(inode)->i_file_acl);
+ 			error = -EIO;
+ 			goto cleanup;
+ 		}
+@@ -880,8 +878,8 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
+ 	goto cleanup;
+ 
+ bad_block:
+-	ext4_error(inode->i_sb, "inode %lu: bad block %llu",
+-		   inode->i_ino, EXT4_I(inode)->i_file_acl);
++	EXT4_ERROR_INODE(inode, "bad block %llu",
++			 EXT4_I(inode)->i_file_acl);
+ 	goto cleanup;
+ 
+ #undef header
+@@ -1194,8 +1192,8 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
+ 		if (!bh)
+ 			goto cleanup;
+ 		if (ext4_xattr_check_block(bh)) {
+-			ext4_error(inode->i_sb, "inode %lu: bad block %llu",
+-				   inode->i_ino, EXT4_I(inode)->i_file_acl);
++			EXT4_ERROR_INODE(inode, "bad block %llu",
++					 EXT4_I(inode)->i_file_acl);
+ 			error = -EIO;
+ 			goto cleanup;
+ 		}
+@@ -1372,14 +1370,14 @@ ext4_xattr_delete_inode(handle_t *handle, struct inode *inode)
+ 		goto cleanup;
+ 	bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
+ 	if (!bh) {
+-		ext4_error(inode->i_sb, "inode %lu: block %llu read error",
+-			   inode->i_ino, EXT4_I(inode)->i_file_acl);
++		EXT4_ERROR_INODE(inode, "block %llu read error",
++				 EXT4_I(inode)->i_file_acl);
+ 		goto cleanup;
+ 	}
+ 	if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) ||
+ 	    BHDR(bh)->h_blocks != cpu_to_le32(1)) {
+-		ext4_error(inode->i_sb, "inode %lu: bad block %llu",
+-			   inode->i_ino, EXT4_I(inode)->i_file_acl);
++		EXT4_ERROR_INODE(inode, "bad block %llu",
++				 EXT4_I(inode)->i_file_acl);
+ 		goto cleanup;
+ 	}
+ 	ext4_xattr_release_block(handle, inode, bh);
+@@ -1504,9 +1502,8 @@ ext4_xattr_cache_find(struct inode *inode, struct ext4_xattr_header *header,
+ 		}
+ 		bh = sb_bread(inode->i_sb, ce->e_block);
+ 		if (!bh) {
+-			ext4_error(inode->i_sb,
+-				"inode %lu: block %lu read error",
+-				inode->i_ino, (unsigned long) ce->e_block);
++			EXT4_ERROR_INODE(inode, "block %lu read error",
++					 (unsigned long) ce->e_block);
+ 		} else if (le32_to_cpu(BHDR(bh)->h_refcount) >=
+ 				EXT4_XATTR_REFCOUNT_MAX) {
+ 			ea_idebug(inode, "block %lu refcount %d>=%d",

commit 2ed886852adfcb070bf350e66a0da0d98b2f3ab5
+Author: Theodore Ts'o 
+Date:   Sun May 16 20:00:00 2010 -0400
+
+    ext4: Convert callers of ext4_get_blocks() to use ext4_map_blocks()
+    
+    This saves a huge amount of stack space by avoiding unnecesary struct
+    buffer_head's from being allocated on the stack.
+    
+    In addition, to make the code easier to understand, collapse and
+    refactor ext4_get_block(), ext4_get_block_write(),
+    noalloc_get_block_write(), into a single function.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index 86cb6d86a048..e3f2700b8be7 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -128,14 +128,14 @@ static int ext4_readdir(struct file *filp,
+ 	offset = filp->f_pos & (sb->s_blocksize - 1);
+ 
+ 	while (!error && !stored && filp->f_pos < inode->i_size) {
+-		ext4_lblk_t blk = filp->f_pos >> EXT4_BLOCK_SIZE_BITS(sb);
+-		struct buffer_head map_bh;
++		struct ext4_map_blocks map;
+ 		struct buffer_head *bh = NULL;
+ 
+-		map_bh.b_state = 0;
+-		err = ext4_get_blocks(NULL, inode, blk, 1, &map_bh, 0);
++		map.m_lblk = filp->f_pos >> EXT4_BLOCK_SIZE_BITS(sb);
++		map.m_len = 1;
++		err = ext4_map_blocks(NULL, inode, &map, 0);
+ 		if (err > 0) {
+-			pgoff_t index = map_bh.b_blocknr >>
++			pgoff_t index = map.m_pblk >>
+ 					(PAGE_CACHE_SHIFT - inode->i_blkbits);
+ 			if (!ra_has_index(&filp->f_ra, index))
+ 				page_cache_sync_readahead(
+@@ -143,7 +143,7 @@ static int ext4_readdir(struct file *filp,
+ 					&filp->f_ra, filp,
+ 					index, 1);
+ 			filp->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT;
+-			bh = ext4_bread(NULL, inode, blk, 0, &err);
++			bh = ext4_bread(NULL, inode, map.m_lblk, 0, &err);
+ 		}
+ 
+ 		/*
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 37f938789344..d6801eb7232b 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -3667,13 +3667,12 @@ static void ext4_falloc_update_inode(struct inode *inode,
+ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len)
+ {
+ 	handle_t *handle;
+-	ext4_lblk_t block;
+ 	loff_t new_size;
+ 	unsigned int max_blocks;
+ 	int ret = 0;
+ 	int ret2 = 0;
+ 	int retries = 0;
+-	struct buffer_head map_bh;
++	struct ext4_map_blocks map;
+ 	unsigned int credits, blkbits = inode->i_blkbits;
+ 
+ 	/*
+@@ -3687,13 +3686,13 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len)
+ 	if (S_ISDIR(inode->i_mode))
+ 		return -ENODEV;
+ 
+-	block = offset >> blkbits;
++	map.m_lblk = offset >> blkbits;
+ 	/*
+ 	 * We can't just convert len to max_blocks because
+ 	 * If blocksize = 4096 offset = 3072 and len = 2048
+ 	 */
+ 	max_blocks = (EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits)
+-							- block;
++		- map.m_lblk;
+ 	/*
+ 	 * credits to insert 1 extent into extent tree
+ 	 */
+@@ -3706,16 +3705,14 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len)
+ 	}
+ retry:
+ 	while (ret >= 0 && ret < max_blocks) {
+-		block = block + ret;
+-		max_blocks = max_blocks - ret;
++		map.m_lblk = map.m_lblk + ret;
++		map.m_len = max_blocks = max_blocks - ret;
+ 		handle = ext4_journal_start(inode, credits);
+ 		if (IS_ERR(handle)) {
+ 			ret = PTR_ERR(handle);
+ 			break;
+ 		}
+-		map_bh.b_state = 0;
+-		ret = ext4_get_blocks(handle, inode, block,
+-				      max_blocks, &map_bh,
++		ret = ext4_map_blocks(handle, inode, &map,
+ 				      EXT4_GET_BLOCKS_CREATE_UNINIT_EXT);
+ 		if (ret <= 0) {
+ #ifdef EXT4FS_DEBUG
+@@ -3729,14 +3726,14 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len)
+ 			ret2 = ext4_journal_stop(handle);
+ 			break;
+ 		}
+-		if ((block + ret) >= (EXT4_BLOCK_ALIGN(offset + len,
++		if ((map.m_lblk + ret) >= (EXT4_BLOCK_ALIGN(offset + len,
+ 						blkbits) >> blkbits))
+ 			new_size = offset + len;
+ 		else
+-			new_size = (block + ret) << blkbits;
++			new_size = (map.m_lblk + ret) << blkbits;
+ 
+ 		ext4_falloc_update_inode(inode, mode, new_size,
+-						buffer_new(&map_bh));
++					 (map.m_flags & EXT4_MAP_NEW));
+ 		ext4_mark_inode_dirty(handle, inode);
+ 		ret2 = ext4_journal_stop(handle);
+ 		if (ret2)
+@@ -3765,42 +3762,39 @@ int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset,
+ 				    ssize_t len)
+ {
+ 	handle_t *handle;
+-	ext4_lblk_t block;
+ 	unsigned int max_blocks;
+ 	int ret = 0;
+ 	int ret2 = 0;
+-	struct buffer_head map_bh;
++	struct ext4_map_blocks map;
+ 	unsigned int credits, blkbits = inode->i_blkbits;
+ 
+-	block = offset >> blkbits;
++	map.m_lblk = offset >> blkbits;
+ 	/*
+ 	 * We can't just convert len to max_blocks because
+ 	 * If blocksize = 4096 offset = 3072 and len = 2048
+ 	 */
+-	max_blocks = (EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits)
+-							- block;
++	max_blocks = ((EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits) -
++		      map.m_lblk);
+ 	/*
+ 	 * credits to insert 1 extent into extent tree
+ 	 */
+ 	credits = ext4_chunk_trans_blocks(inode, max_blocks);
+ 	while (ret >= 0 && ret < max_blocks) {
+-		block = block + ret;
+-		max_blocks = max_blocks - ret;
++		map.m_lblk += ret;
++		map.m_len = (max_blocks -= ret);
+ 		handle = ext4_journal_start(inode, credits);
+ 		if (IS_ERR(handle)) {
+ 			ret = PTR_ERR(handle);
+ 			break;
+ 		}
+-		map_bh.b_state = 0;
+-		ret = ext4_get_blocks(handle, inode, block,
+-				      max_blocks, &map_bh,
++		ret = ext4_map_blocks(handle, inode, &map,
+ 				      EXT4_GET_BLOCKS_IO_CONVERT_EXT);
+ 		if (ret <= 0) {
+ 			WARN_ON(ret <= 0);
+ 			printk(KERN_ERR "%s: ext4_ext_map_blocks "
+ 				    "returned error inode#%lu, block=%u, "
+ 				    "max_blocks=%u", __func__,
+-				    inode->i_ino, block, max_blocks);
++				    inode->i_ino, map.m_lblk, map.m_len);
+ 		}
+ 		ext4_mark_inode_dirty(handle, inode);
+ 		ret2 = ext4_journal_stop(handle);
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index ff2f5fd681b5..0b1d7c89f93f 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1336,133 +1336,112 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
+ 	return retval;
+ }
+ 
+-int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block,
+-		    unsigned int max_blocks, struct buffer_head *bh,
+-		    int flags)
+-{
+-	struct ext4_map_blocks map;
+-	int ret;
+-
+-	map.m_lblk = block;
+-	map.m_len = max_blocks;
+-
+-	ret = ext4_map_blocks(handle, inode, &map, flags);
+-	if (ret < 0)
+-		return ret;
+-
+-	bh->b_blocknr = map.m_pblk;
+-	bh->b_size = inode->i_sb->s_blocksize * map.m_len;
+-	bh->b_bdev = inode->i_sb->s_bdev;
+-	bh->b_state = (bh->b_state & ~EXT4_MAP_FLAGS) | map.m_flags;
+-	return ret;
+-}
+-
+ /* Maximum number of blocks we map for direct IO at once. */
+ #define DIO_MAX_BLOCKS 4096
+ 
+-int ext4_get_block(struct inode *inode, sector_t iblock,
+-		   struct buffer_head *bh_result, int create)
++static int _ext4_get_block(struct inode *inode, sector_t iblock,
++			   struct buffer_head *bh, int flags)
+ {
+ 	handle_t *handle = ext4_journal_current_handle();
++	struct ext4_map_blocks map;
+ 	int ret = 0, started = 0;
+-	unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
+ 	int dio_credits;
+ 
+-	if (create && !handle) {
++	map.m_lblk = iblock;
++	map.m_len = bh->b_size >> inode->i_blkbits;
++
++	if (flags && !handle) {
+ 		/* Direct IO write... */
+-		if (max_blocks > DIO_MAX_BLOCKS)
+-			max_blocks = DIO_MAX_BLOCKS;
+-		dio_credits = ext4_chunk_trans_blocks(inode, max_blocks);
++		if (map.m_len > DIO_MAX_BLOCKS)
++			map.m_len = DIO_MAX_BLOCKS;
++		dio_credits = ext4_chunk_trans_blocks(inode, map.m_len);
+ 		handle = ext4_journal_start(inode, dio_credits);
+ 		if (IS_ERR(handle)) {
+ 			ret = PTR_ERR(handle);
+-			goto out;
++			return ret;
+ 		}
+ 		started = 1;
+ 	}
+ 
+-	ret = ext4_get_blocks(handle, inode, iblock, max_blocks, bh_result,
+-			      create ? EXT4_GET_BLOCKS_CREATE : 0);
++	ret = ext4_map_blocks(handle, inode, &map, flags);
+ 	if (ret > 0) {
+-		bh_result->b_size = (ret << inode->i_blkbits);
++		map_bh(bh, inode->i_sb, map.m_pblk);
++		bh->b_state = (bh->b_state & ~EXT4_MAP_FLAGS) | map.m_flags;
++		bh->b_size = inode->i_sb->s_blocksize * map.m_len;
+ 		ret = 0;
+ 	}
+ 	if (started)
+ 		ext4_journal_stop(handle);
+-out:
+ 	return ret;
+ }
+ 
++int ext4_get_block(struct inode *inode, sector_t iblock,
++		   struct buffer_head *bh, int create)
++{
++	return _ext4_get_block(inode, iblock, bh,
++			       create ? EXT4_GET_BLOCKS_CREATE : 0);
++}
++
+ /*
+  * `handle' can be NULL if create is zero
+  */
+ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
+ 				ext4_lblk_t block, int create, int *errp)
+ {
+-	struct buffer_head dummy;
++	struct ext4_map_blocks map;
++	struct buffer_head *bh;
+ 	int fatal = 0, err;
+-	int flags = 0;
+ 
+ 	J_ASSERT(handle != NULL || create == 0);
+ 
+-	dummy.b_state = 0;
+-	dummy.b_blocknr = -1000;
+-	buffer_trace_init(&dummy.b_history);
+-	if (create)
+-		flags |= EXT4_GET_BLOCKS_CREATE;
+-	err = ext4_get_blocks(handle, inode, block, 1, &dummy, flags);
+-	/*
+-	 * ext4_get_blocks() returns number of blocks mapped. 0 in
+-	 * case of a HOLE.
+-	 */
+-	if (err > 0) {
+-		if (err > 1)
+-			WARN_ON(1);
+-		err = 0;
++	map.m_lblk = block;
++	map.m_len = 1;
++	err = ext4_map_blocks(handle, inode, &map,
++			      create ? EXT4_GET_BLOCKS_CREATE : 0);
++
++	if (err < 0)
++		*errp = err;
++	if (err <= 0)
++		return NULL;
++	*errp = 0;
++
++	bh = sb_getblk(inode->i_sb, map.m_pblk);
++	if (!bh) {
++		*errp = -EIO;
++		return NULL;
+ 	}
+-	*errp = err;
+-	if (!err && buffer_mapped(&dummy)) {
+-		struct buffer_head *bh;
+-		bh = sb_getblk(inode->i_sb, dummy.b_blocknr);
+-		if (!bh) {
+-			*errp = -EIO;
+-			goto err;
+-		}
+-		if (buffer_new(&dummy)) {
+-			J_ASSERT(create != 0);
+-			J_ASSERT(handle != NULL);
++	if (map.m_flags & EXT4_MAP_NEW) {
++		J_ASSERT(create != 0);
++		J_ASSERT(handle != NULL);
+ 
+-			/*
+-			 * Now that we do not always journal data, we should
+-			 * keep in mind whether this should always journal the
+-			 * new buffer as metadata.  For now, regular file
+-			 * writes use ext4_get_block instead, so it's not a
+-			 * problem.
+-			 */
+-			lock_buffer(bh);
+-			BUFFER_TRACE(bh, "call get_create_access");
+-			fatal = ext4_journal_get_create_access(handle, bh);
+-			if (!fatal && !buffer_uptodate(bh)) {
+-				memset(bh->b_data, 0, inode->i_sb->s_blocksize);
+-				set_buffer_uptodate(bh);
+-			}
+-			unlock_buffer(bh);
+-			BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
+-			err = ext4_handle_dirty_metadata(handle, inode, bh);
+-			if (!fatal)
+-				fatal = err;
+-		} else {
+-			BUFFER_TRACE(bh, "not a new buffer");
+-		}
+-		if (fatal) {
+-			*errp = fatal;
+-			brelse(bh);
+-			bh = NULL;
++		/*
++		 * Now that we do not always journal data, we should
++		 * keep in mind whether this should always journal the
++		 * new buffer as metadata.  For now, regular file
++		 * writes use ext4_get_block instead, so it's not a
++		 * problem.
++		 */
++		lock_buffer(bh);
++		BUFFER_TRACE(bh, "call get_create_access");
++		fatal = ext4_journal_get_create_access(handle, bh);
++		if (!fatal && !buffer_uptodate(bh)) {
++			memset(bh->b_data, 0, inode->i_sb->s_blocksize);
++			set_buffer_uptodate(bh);
+ 		}
+-		return bh;
++		unlock_buffer(bh);
++		BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
++		err = ext4_handle_dirty_metadata(handle, inode, bh);
++		if (!fatal)
++			fatal = err;
++	} else {
++		BUFFER_TRACE(bh, "not a new buffer");
+ 	}
+-err:
+-	return NULL;
++	if (fatal) {
++		*errp = fatal;
++		brelse(bh);
++		bh = NULL;
++	}
++	return bh;
+ }
+ 
+ struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode,
+@@ -2050,28 +2029,23 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd)
+ /*
+  * mpage_put_bnr_to_bhs - walk blocks and assign them actual numbers
+  *
+- * @mpd->inode - inode to walk through
+- * @exbh->b_blocknr - first block on a disk
+- * @exbh->b_size - amount of space in bytes
+- * @logical - first logical block to start assignment with
+- *
+  * the function goes through all passed space and put actual disk
+  * block numbers into buffer heads, dropping BH_Delay and BH_Unwritten
+  */
+-static void mpage_put_bnr_to_bhs(struct mpage_da_data *mpd, sector_t logical,
+-				 struct buffer_head *exbh)
++static void mpage_put_bnr_to_bhs(struct mpage_da_data *mpd,
++				 struct ext4_map_blocks *map)
+ {
+ 	struct inode *inode = mpd->inode;
+ 	struct address_space *mapping = inode->i_mapping;
+-	int blocks = exbh->b_size >> inode->i_blkbits;
+-	sector_t pblock = exbh->b_blocknr, cur_logical;
++	int blocks = map->m_len;
++	sector_t pblock = map->m_pblk, cur_logical;
+ 	struct buffer_head *head, *bh;
+ 	pgoff_t index, end;
+ 	struct pagevec pvec;
+ 	int nr_pages, i;
+ 
+-	index = logical >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
+-	end = (logical + blocks - 1) >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
++	index = map->m_lblk >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
++	end = (map->m_lblk + blocks - 1) >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
+ 	cur_logical = index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
+ 
+ 	pagevec_init(&pvec, 0);
+@@ -2098,17 +2072,16 @@ static void mpage_put_bnr_to_bhs(struct mpage_da_data *mpd, sector_t logical,
+ 
+ 			/* skip blocks out of the range */
+ 			do {
+-				if (cur_logical >= logical)
++				if (cur_logical >= map->m_lblk)
+ 					break;
+ 				cur_logical++;
+ 			} while ((bh = bh->b_this_page) != head);
+ 
+ 			do {
+-				if (cur_logical >= logical + blocks)
++				if (cur_logical >= map->m_lblk + blocks)
+ 					break;
+ 
+-				if (buffer_delay(bh) ||
+-						buffer_unwritten(bh)) {
++				if (buffer_delay(bh) || buffer_unwritten(bh)) {
+ 
+ 					BUG_ON(bh->b_bdev != inode->i_sb->s_bdev);
+ 
+@@ -2127,7 +2100,7 @@ static void mpage_put_bnr_to_bhs(struct mpage_da_data *mpd, sector_t logical,
+ 				} else if (buffer_mapped(bh))
+ 					BUG_ON(bh->b_blocknr != pblock);
+ 
+-				if (buffer_uninit(exbh))
++				if (map->m_flags & EXT4_MAP_UNINIT)
+ 					set_buffer_uninit(bh);
+ 				cur_logical++;
+ 				pblock++;
+@@ -2138,21 +2111,6 @@ static void mpage_put_bnr_to_bhs(struct mpage_da_data *mpd, sector_t logical,
+ }
+ 
+ 
+-/*
+- * __unmap_underlying_blocks - just a helper function to unmap
+- * set of blocks described by @bh
+- */
+-static inline void __unmap_underlying_blocks(struct inode *inode,
+-					     struct buffer_head *bh)
+-{
+-	struct block_device *bdev = inode->i_sb->s_bdev;
+-	int blocks, i;
+-
+-	blocks = bh->b_size >> inode->i_blkbits;
+-	for (i = 0; i < blocks; i++)
+-		unmap_underlying_metadata(bdev, bh->b_blocknr + i);
+-}
+-
+ static void ext4_da_block_invalidatepages(struct mpage_da_data *mpd,
+ 					sector_t logical, long blk_cnt)
+ {
+@@ -2214,7 +2172,7 @@ static void ext4_print_free_blocks(struct inode *inode)
+ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
+ {
+ 	int err, blks, get_blocks_flags;
+-	struct buffer_head new;
++	struct ext4_map_blocks map;
+ 	sector_t next = mpd->b_blocknr;
+ 	unsigned max_blocks = mpd->b_size >> mpd->inode->i_blkbits;
+ 	loff_t disksize = EXT4_I(mpd->inode)->i_disksize;
+@@ -2255,15 +2213,15 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
+ 	 * EXT4_GET_BLOCKS_DELALLOC_RESERVE so the delalloc accounting
+ 	 * variables are updated after the blocks have been allocated.
+ 	 */
+-	new.b_state = 0;
++	map.m_lblk = next;
++	map.m_len = max_blocks;
+ 	get_blocks_flags = EXT4_GET_BLOCKS_CREATE;
+ 	if (ext4_should_dioread_nolock(mpd->inode))
+ 		get_blocks_flags |= EXT4_GET_BLOCKS_IO_CREATE_EXT;
+ 	if (mpd->b_state & (1 << BH_Delay))
+ 		get_blocks_flags |= EXT4_GET_BLOCKS_DELALLOC_RESERVE;
+ 
+-	blks = ext4_get_blocks(handle, mpd->inode, next, max_blocks,
+-			       &new, get_blocks_flags);
++	blks = ext4_map_blocks(handle, mpd->inode, &map, get_blocks_flags);
+ 	if (blks < 0) {
+ 		err = blks;
+ 		/*
+@@ -2305,10 +2263,13 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
+ 	}
+ 	BUG_ON(blks == 0);
+ 
+-	new.b_size = (blks << mpd->inode->i_blkbits);
++	if (map.m_flags & EXT4_MAP_NEW) {
++		struct block_device *bdev = mpd->inode->i_sb->s_bdev;
++		int i;
+ 
+-	if (buffer_new(&new))
+-		__unmap_underlying_blocks(mpd->inode, &new);
++		for (i = 0; i < map.m_len; i++)
++			unmap_underlying_metadata(bdev, map.m_pblk + i);
++	}
+ 
+ 	/*
+ 	 * If blocks are delayed marked, we need to
+@@ -2316,7 +2277,7 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
+ 	 */
+ 	if ((mpd->b_state & (1 << BH_Delay)) ||
+ 	    (mpd->b_state & (1 << BH_Unwritten)))
+-		mpage_put_bnr_to_bhs(mpd, next, &new);
++		mpage_put_bnr_to_bhs(mpd, &map);
+ 
+ 	if (ext4_should_order_data(mpd->inode)) {
+ 		err = ext4_jbd2_file_inode(handle, mpd->inode);
+@@ -2534,8 +2495,9 @@ static int __mpage_da_writepage(struct page *page,
+  * initialized properly.
+  */
+ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock,
+-				  struct buffer_head *bh_result, int create)
++				  struct buffer_head *bh, int create)
+ {
++	struct ext4_map_blocks map;
+ 	int ret = 0;
+ 	sector_t invalid_block = ~((sector_t) 0xffff);
+ 
+@@ -2543,16 +2505,22 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock,
+ 		invalid_block = ~0;
+ 
+ 	BUG_ON(create == 0);
+-	BUG_ON(bh_result->b_size != inode->i_sb->s_blocksize);
++	BUG_ON(bh->b_size != inode->i_sb->s_blocksize);
++
++	map.m_lblk = iblock;
++	map.m_len = 1;
+ 
+ 	/*
+ 	 * first, we need to know whether the block is allocated already
+ 	 * preallocated blocks are unmapped but should treated
+ 	 * the same as allocated blocks.
+ 	 */
+-	ret = ext4_get_blocks(NULL, inode, iblock, 1,  bh_result, 0);
+-	if ((ret == 0) && !buffer_delay(bh_result)) {
+-		/* the block isn't (pre)allocated yet, let's reserve space */
++	ret = ext4_map_blocks(NULL, inode, &map, 0);
++	if (ret < 0)
++		return ret;
++	if (ret == 0) {
++		if (buffer_delay(bh))
++			return 0; /* Not sure this could or should happen */
+ 		/*
+ 		 * XXX: __block_prepare_write() unmaps passed block,
+ 		 * is it OK?
+@@ -2562,26 +2530,26 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock,
+ 			/* not enough space to reserve */
+ 			return ret;
+ 
+-		map_bh(bh_result, inode->i_sb, invalid_block);
+-		set_buffer_new(bh_result);
+-		set_buffer_delay(bh_result);
+-	} else if (ret > 0) {
+-		bh_result->b_size = (ret << inode->i_blkbits);
+-		if (buffer_unwritten(bh_result)) {
+-			/* A delayed write to unwritten bh should
+-			 * be marked new and mapped.  Mapped ensures
+-			 * that we don't do get_block multiple times
+-			 * when we write to the same offset and new
+-			 * ensures that we do proper zero out for
+-			 * partial write.
+-			 */
+-			set_buffer_new(bh_result);
+-			set_buffer_mapped(bh_result);
+-		}
+-		ret = 0;
++		map_bh(bh, inode->i_sb, invalid_block);
++		set_buffer_new(bh);
++		set_buffer_delay(bh);
++		return 0;
+ 	}
+ 
+-	return ret;
++	map_bh(bh, inode->i_sb, map.m_pblk);
++	bh->b_state = (bh->b_state & ~EXT4_MAP_FLAGS) | map.m_flags;
++
++	if (buffer_unwritten(bh)) {
++		/* A delayed write to unwritten bh should be marked
++		 * new and mapped.  Mapped ensures that we don't do
++		 * get_block multiple times when we write to the same
++		 * offset and new ensures that we do proper zero out
++		 * for partial write.
++		 */
++		set_buffer_new(bh);
++		set_buffer_mapped(bh);
++	}
++	return 0;
+ }
+ 
+ /*
+@@ -2603,21 +2571,8 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock,
+ static int noalloc_get_block_write(struct inode *inode, sector_t iblock,
+ 				   struct buffer_head *bh_result, int create)
+ {
+-	int ret = 0;
+-	unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
+-
+ 	BUG_ON(bh_result->b_size != inode->i_sb->s_blocksize);
+-
+-	/*
+-	 * we don't want to do block allocation in writepage
+-	 * so call get_block_wrap with create = 0
+-	 */
+-	ret = ext4_get_blocks(NULL, inode, iblock, max_blocks, bh_result, 0);
+-	if (ret > 0) {
+-		bh_result->b_size = (ret << inode->i_blkbits);
+-		ret = 0;
+-	}
+-	return ret;
++	return _ext4_get_block(inode, iblock, bh_result, 0);
+ }
+ 
+ static int bget_one(handle_t *handle, struct buffer_head *bh)
+@@ -3644,46 +3599,18 @@ static ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb,
+ 	return ret;
+ }
+ 
++/*
++ * ext4_get_block used when preparing for a DIO write or buffer write.
++ * We allocate an uinitialized extent if blocks haven't been allocated.
++ * The extent will be converted to initialized after the IO is complete.
++ */
+ static int ext4_get_block_write(struct inode *inode, sector_t iblock,
+ 		   struct buffer_head *bh_result, int create)
+ {
+-	handle_t *handle = ext4_journal_current_handle();
+-	int ret = 0;
+-	unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
+-	int dio_credits;
+-	int started = 0;
+-
+ 	ext4_debug("ext4_get_block_write: inode %lu, create flag %d\n",
+ 		   inode->i_ino, create);
+-	/*
+-	 * ext4_get_block in prepare for a DIO write or buffer write.
+-	 * We allocate an uinitialized extent if blocks haven't been allocated.
+-	 * The extent will be converted to initialized after IO complete.
+-	 */
+-	create = EXT4_GET_BLOCKS_IO_CREATE_EXT;
+-
+-	if (!handle) {
+-		if (max_blocks > DIO_MAX_BLOCKS)
+-			max_blocks = DIO_MAX_BLOCKS;
+-		dio_credits = ext4_chunk_trans_blocks(inode, max_blocks);
+-		handle = ext4_journal_start(inode, dio_credits);
+-		if (IS_ERR(handle)) {
+-			ret = PTR_ERR(handle);
+-			goto out;
+-		}
+-		started = 1;
+-	}
+-
+-	ret = ext4_get_blocks(handle, inode, iblock, max_blocks, bh_result,
+-			      create);
+-	if (ret > 0) {
+-		bh_result->b_size = (ret << inode->i_blkbits);
+-		ret = 0;
+-	}
+-	if (started)
+-		ext4_journal_stop(handle);
+-out:
+-	return ret;
++	return _ext4_get_block(inode, iblock, bh_result,
++			       EXT4_GET_BLOCKS_IO_CREATE_EXT);
+ }
+ 
+ static void dump_completed_IO(struct inode * inode)

commit e35fd6609b2fee54484d520deccb8f18bf7d38f3
+Author: Theodore Ts'o 
+Date:   Sun May 16 19:00:00 2010 -0400
+
+    ext4: Add new abstraction ext4_map_blocks() underneath ext4_get_blocks()
+    
+    Jack up ext4_get_blocks() and add a new function, ext4_map_blocks()
+    which uses a much smaller structure, struct ext4_map_blocks which is
+    20 bytes, as opposed to a struct buffer_head, which nearly 5 times
+    bigger on an x86_64 machine.  By switching things to use
+    ext4_map_blocks(), we can save stack space by using ext4_map_blocks()
+    since we can avoid allocating a struct buffer_head on the stack.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index d266003cac3e..57fc0e5c0918 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -125,6 +125,29 @@ struct ext4_allocation_request {
+ 	unsigned int flags;
+ };
+ 
++/*
++ * Logical to physical block mapping, used by ext4_map_blocks()
++ *
++ * This structure is used to pass requests into ext4_map_blocks() as
++ * well as to store the information returned by ext4_map_blocks().  It
++ * takes less room on the stack than a struct buffer_head.
++ */
++#define EXT4_MAP_NEW		(1 << BH_New)
++#define EXT4_MAP_MAPPED		(1 << BH_Mapped)
++#define EXT4_MAP_UNWRITTEN	(1 << BH_Unwritten)
++#define EXT4_MAP_BOUNDARY	(1 << BH_Boundary)
++#define EXT4_MAP_UNINIT		(1 << BH_Uninit)
++#define EXT4_MAP_FLAGS		(EXT4_MAP_NEW | EXT4_MAP_MAPPED |\
++				 EXT4_MAP_UNWRITTEN | EXT4_MAP_BOUNDARY |\
++				 EXT4_MAP_UNINIT)
++
++struct ext4_map_blocks {
++	ext4_fsblk_t m_pblk;
++	ext4_lblk_t m_lblk;
++	unsigned int m_len;
++	unsigned int m_flags;
++};
++
+ /*
+  * For delayed allocation tracking
+  */
+@@ -1773,9 +1796,8 @@ extern int ext4_ext_tree_init(handle_t *handle, struct inode *);
+ extern int ext4_ext_writepage_trans_blocks(struct inode *, int);
+ extern int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks,
+ 				       int chunk);
+-extern int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+-			       ext4_lblk_t iblock, unsigned int max_blocks,
+-			       struct buffer_head *bh_result, int flags);
++extern int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
++			       struct ext4_map_blocks *map, int flags);
+ extern void ext4_ext_truncate(struct inode *);
+ extern void ext4_ext_init(struct super_block *);
+ extern void ext4_ext_release(struct super_block *);
+@@ -1783,6 +1805,8 @@ extern long ext4_fallocate(struct inode *inode, int mode, loff_t offset,
+ 			  loff_t len);
+ extern int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset,
+ 			  ssize_t len);
++extern int ext4_map_blocks(handle_t *handle, struct inode *inode,
++			   struct ext4_map_blocks *map, int flags);
+ extern int ext4_get_blocks(handle_t *handle, struct inode *inode,
+ 			   sector_t block, unsigned int max_blocks,
+ 			   struct buffer_head *bh, int flags);
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 8a8f9f0be911..37f938789344 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -2611,7 +2611,7 @@ static int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex)
+ 
+ #define EXT4_EXT_ZERO_LEN 7
+ /*
+- * This function is called by ext4_ext_get_blocks() if someone tries to write
++ * This function is called by ext4_ext_map_blocks() if someone tries to write
+  * to an uninitialized extent. It may result in splitting the uninitialized
+  * extent into multiple extents (upto three - one initialized and two
+  * uninitialized).
+@@ -2621,10 +2621,9 @@ static int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex)
+  *   c> Splits in three extents: Somone is writing in middle of the extent
+  */
+ static int ext4_ext_convert_to_initialized(handle_t *handle,
+-						struct inode *inode,
+-						struct ext4_ext_path *path,
+-						ext4_lblk_t iblock,
+-						unsigned int max_blocks)
++					   struct inode *inode,
++					   struct ext4_map_blocks *map,
++					   struct ext4_ext_path *path)
+ {
+ 	struct ext4_extent *ex, newex, orig_ex;
+ 	struct ext4_extent *ex1 = NULL;
+@@ -2640,20 +2639,20 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 
+ 	ext_debug("ext4_ext_convert_to_initialized: inode %lu, logical"
+ 		"block %llu, max_blocks %u\n", inode->i_ino,
+-		(unsigned long long)iblock, max_blocks);
++		(unsigned long long)map->m_lblk, map->m_len);
+ 
+ 	eof_block = (inode->i_size + inode->i_sb->s_blocksize - 1) >>
+ 		inode->i_sb->s_blocksize_bits;
+-	if (eof_block < iblock + max_blocks)
+-		eof_block = iblock + max_blocks;
++	if (eof_block < map->m_lblk + map->m_len)
++		eof_block = map->m_lblk + map->m_len;
+ 
+ 	depth = ext_depth(inode);
+ 	eh = path[depth].p_hdr;
+ 	ex = path[depth].p_ext;
+ 	ee_block = le32_to_cpu(ex->ee_block);
+ 	ee_len = ext4_ext_get_actual_len(ex);
+-	allocated = ee_len - (iblock - ee_block);
+-	newblock = iblock - ee_block + ext_pblock(ex);
++	allocated = ee_len - (map->m_lblk - ee_block);
++	newblock = map->m_lblk - ee_block + ext_pblock(ex);
+ 
+ 	ex2 = ex;
+ 	orig_ex.ee_block = ex->ee_block;
+@@ -2683,10 +2682,10 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 		return allocated;
+ 	}
+ 
+-	/* ex1: ee_block to iblock - 1 : uninitialized */
+-	if (iblock > ee_block) {
++	/* ex1: ee_block to map->m_lblk - 1 : uninitialized */
++	if (map->m_lblk > ee_block) {
+ 		ex1 = ex;
+-		ex1->ee_len = cpu_to_le16(iblock - ee_block);
++		ex1->ee_len = cpu_to_le16(map->m_lblk - ee_block);
+ 		ext4_ext_mark_uninitialized(ex1);
+ 		ex2 = &newex;
+ 	}
+@@ -2695,15 +2694,15 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 	 * we insert ex3, if ex1 is NULL. This is to avoid temporary
+ 	 * overlap of blocks.
+ 	 */
+-	if (!ex1 && allocated > max_blocks)
+-		ex2->ee_len = cpu_to_le16(max_blocks);
++	if (!ex1 && allocated > map->m_len)
++		ex2->ee_len = cpu_to_le16(map->m_len);
+ 	/* ex3: to ee_block + ee_len : uninitialised */
+-	if (allocated > max_blocks) {
++	if (allocated > map->m_len) {
+ 		unsigned int newdepth;
+ 		/* If extent has less than EXT4_EXT_ZERO_LEN zerout directly */
+ 		if (allocated <= EXT4_EXT_ZERO_LEN && may_zeroout) {
+ 			/*
+-			 * iblock == ee_block is handled by the zerouout
++			 * map->m_lblk == ee_block is handled by the zerouout
+ 			 * at the beginning.
+ 			 * Mark first half uninitialized.
+ 			 * Mark second half initialized and zero out the
+@@ -2716,7 +2715,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 			ext4_ext_dirty(handle, inode, path + depth);
+ 
+ 			ex3 = &newex;
+-			ex3->ee_block = cpu_to_le32(iblock);
++			ex3->ee_block = cpu_to_le32(map->m_lblk);
+ 			ext4_ext_store_pblock(ex3, newblock);
+ 			ex3->ee_len = cpu_to_le16(allocated);
+ 			err = ext4_ext_insert_extent(handle, inode, path,
+@@ -2729,7 +2728,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 				ex->ee_len   = orig_ex.ee_len;
+ 				ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
+ 				ext4_ext_dirty(handle, inode, path + depth);
+-				/* blocks available from iblock */
++				/* blocks available from map->m_lblk */
+ 				return allocated;
+ 
+ 			} else if (err)
+@@ -2751,8 +2750,8 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 				 */
+ 				depth = ext_depth(inode);
+ 				ext4_ext_drop_refs(path);
+-				path = ext4_ext_find_extent(inode,
+-								iblock, path);
++				path = ext4_ext_find_extent(inode, map->m_lblk,
++							    path);
+ 				if (IS_ERR(path)) {
+ 					err = PTR_ERR(path);
+ 					return err;
+@@ -2772,9 +2771,9 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 			return allocated;
+ 		}
+ 		ex3 = &newex;
+-		ex3->ee_block = cpu_to_le32(iblock + max_blocks);
+-		ext4_ext_store_pblock(ex3, newblock + max_blocks);
+-		ex3->ee_len = cpu_to_le16(allocated - max_blocks);
++		ex3->ee_block = cpu_to_le32(map->m_lblk + map->m_len);
++		ext4_ext_store_pblock(ex3, newblock + map->m_len);
++		ex3->ee_len = cpu_to_le16(allocated - map->m_len);
+ 		ext4_ext_mark_uninitialized(ex3);
+ 		err = ext4_ext_insert_extent(handle, inode, path, ex3, 0);
+ 		if (err == -ENOSPC && may_zeroout) {
+@@ -2787,7 +2786,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 			ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
+ 			ext4_ext_dirty(handle, inode, path + depth);
+ 			/* zeroed the full extent */
+-			/* blocks available from iblock */
++			/* blocks available from map->m_lblk */
+ 			return allocated;
+ 
+ 		} else if (err)
+@@ -2807,7 +2806,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 
+ 		depth = newdepth;
+ 		ext4_ext_drop_refs(path);
+-		path = ext4_ext_find_extent(inode, iblock, path);
++		path = ext4_ext_find_extent(inode, map->m_lblk, path);
+ 		if (IS_ERR(path)) {
+ 			err = PTR_ERR(path);
+ 			goto out;
+@@ -2821,14 +2820,14 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 		if (err)
+ 			goto out;
+ 
+-		allocated = max_blocks;
++		allocated = map->m_len;
+ 
+ 		/* If extent has less than EXT4_EXT_ZERO_LEN and we are trying
+ 		 * to insert a extent in the middle zerout directly
+ 		 * otherwise give the extent a chance to merge to left
+ 		 */
+ 		if (le16_to_cpu(orig_ex.ee_len) <= EXT4_EXT_ZERO_LEN &&
+-			iblock != ee_block && may_zeroout) {
++			map->m_lblk != ee_block && may_zeroout) {
+ 			err =  ext4_ext_zeroout(inode, &orig_ex);
+ 			if (err)
+ 				goto fix_extent_len;
+@@ -2838,7 +2837,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 			ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
+ 			ext4_ext_dirty(handle, inode, path + depth);
+ 			/* zero out the first half */
+-			/* blocks available from iblock */
++			/* blocks available from map->m_lblk */
+ 			return allocated;
+ 		}
+ 	}
+@@ -2849,12 +2848,12 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 	 */
+ 	if (ex1 && ex1 != ex) {
+ 		ex1 = ex;
+-		ex1->ee_len = cpu_to_le16(iblock - ee_block);
++		ex1->ee_len = cpu_to_le16(map->m_lblk - ee_block);
+ 		ext4_ext_mark_uninitialized(ex1);
+ 		ex2 = &newex;
+ 	}
+-	/* ex2: iblock to iblock + maxblocks-1 : initialised */
+-	ex2->ee_block = cpu_to_le32(iblock);
++	/* ex2: map->m_lblk to map->m_lblk + maxblocks-1 : initialised */
++	ex2->ee_block = cpu_to_le32(map->m_lblk);
+ 	ext4_ext_store_pblock(ex2, newblock);
+ 	ex2->ee_len = cpu_to_le16(allocated);
+ 	if (ex2 != ex)
+@@ -2924,7 +2923,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ }
+ 
+ /*
+- * This function is called by ext4_ext_get_blocks() from
++ * This function is called by ext4_ext_map_blocks() from
+  * ext4_get_blocks_dio_write() when DIO to write
+  * to an uninitialized extent.
+  *
+@@ -2947,9 +2946,8 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+  */
+ static int ext4_split_unwritten_extents(handle_t *handle,
+ 					struct inode *inode,
++					struct ext4_map_blocks *map,
+ 					struct ext4_ext_path *path,
+-					ext4_lblk_t iblock,
+-					unsigned int max_blocks,
+ 					int flags)
+ {
+ 	struct ext4_extent *ex, newex, orig_ex;
+@@ -2965,20 +2963,20 @@ static int ext4_split_unwritten_extents(handle_t *handle,
+ 
+ 	ext_debug("ext4_split_unwritten_extents: inode %lu, logical"
+ 		"block %llu, max_blocks %u\n", inode->i_ino,
+-		(unsigned long long)iblock, max_blocks);
++		(unsigned long long)map->m_lblk, map->m_len);
+ 
+ 	eof_block = (inode->i_size + inode->i_sb->s_blocksize - 1) >>
+ 		inode->i_sb->s_blocksize_bits;
+-	if (eof_block < iblock + max_blocks)
+-		eof_block = iblock + max_blocks;
++	if (eof_block < map->m_lblk + map->m_len)
++		eof_block = map->m_lblk + map->m_len;
+ 
+ 	depth = ext_depth(inode);
+ 	eh = path[depth].p_hdr;
+ 	ex = path[depth].p_ext;
+ 	ee_block = le32_to_cpu(ex->ee_block);
+ 	ee_len = ext4_ext_get_actual_len(ex);
+-	allocated = ee_len - (iblock - ee_block);
+-	newblock = iblock - ee_block + ext_pblock(ex);
++	allocated = ee_len - (map->m_lblk - ee_block);
++	newblock = map->m_lblk - ee_block + ext_pblock(ex);
+ 
+ 	ex2 = ex;
+ 	orig_ex.ee_block = ex->ee_block;
+@@ -2996,16 +2994,16 @@ static int ext4_split_unwritten_extents(handle_t *handle,
+  	 * block where the write begins, and the write completely
+  	 * covers the extent, then we don't need to split it.
+  	 */
+-	if ((iblock == ee_block) && (allocated <= max_blocks))
++	if ((map->m_lblk == ee_block) && (allocated <= map->m_len))
+ 		return allocated;
+ 
+ 	err = ext4_ext_get_access(handle, inode, path + depth);
+ 	if (err)
+ 		goto out;
+-	/* ex1: ee_block to iblock - 1 : uninitialized */
+-	if (iblock > ee_block) {
++	/* ex1: ee_block to map->m_lblk - 1 : uninitialized */
++	if (map->m_lblk > ee_block) {
+ 		ex1 = ex;
+-		ex1->ee_len = cpu_to_le16(iblock - ee_block);
++		ex1->ee_len = cpu_to_le16(map->m_lblk - ee_block);
+ 		ext4_ext_mark_uninitialized(ex1);
+ 		ex2 = &newex;
+ 	}
+@@ -3014,15 +3012,15 @@ static int ext4_split_unwritten_extents(handle_t *handle,
+ 	 * we insert ex3, if ex1 is NULL. This is to avoid temporary
+ 	 * overlap of blocks.
+ 	 */
+-	if (!ex1 && allocated > max_blocks)
+-		ex2->ee_len = cpu_to_le16(max_blocks);
++	if (!ex1 && allocated > map->m_len)
++		ex2->ee_len = cpu_to_le16(map->m_len);
+ 	/* ex3: to ee_block + ee_len : uninitialised */
+-	if (allocated > max_blocks) {
++	if (allocated > map->m_len) {
+ 		unsigned int newdepth;
+ 		ex3 = &newex;
+-		ex3->ee_block = cpu_to_le32(iblock + max_blocks);
+-		ext4_ext_store_pblock(ex3, newblock + max_blocks);
+-		ex3->ee_len = cpu_to_le16(allocated - max_blocks);
++		ex3->ee_block = cpu_to_le32(map->m_lblk + map->m_len);
++		ext4_ext_store_pblock(ex3, newblock + map->m_len);
++		ex3->ee_len = cpu_to_le16(allocated - map->m_len);
+ 		ext4_ext_mark_uninitialized(ex3);
+ 		err = ext4_ext_insert_extent(handle, inode, path, ex3, flags);
+ 		if (err == -ENOSPC && may_zeroout) {
+@@ -3035,7 +3033,7 @@ static int ext4_split_unwritten_extents(handle_t *handle,
+ 			ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
+ 			ext4_ext_dirty(handle, inode, path + depth);
+ 			/* zeroed the full extent */
+-			/* blocks available from iblock */
++			/* blocks available from map->m_lblk */
+ 			return allocated;
+ 
+ 		} else if (err)
+@@ -3055,7 +3053,7 @@ static int ext4_split_unwritten_extents(handle_t *handle,
+ 
+ 		depth = newdepth;
+ 		ext4_ext_drop_refs(path);
+-		path = ext4_ext_find_extent(inode, iblock, path);
++		path = ext4_ext_find_extent(inode, map->m_lblk, path);
+ 		if (IS_ERR(path)) {
+ 			err = PTR_ERR(path);
+ 			goto out;
+@@ -3069,7 +3067,7 @@ static int ext4_split_unwritten_extents(handle_t *handle,
+ 		if (err)
+ 			goto out;
+ 
+-		allocated = max_blocks;
++		allocated = map->m_len;
+ 	}
+ 	/*
+ 	 * If there was a change of depth as part of the
+@@ -3078,15 +3076,15 @@ static int ext4_split_unwritten_extents(handle_t *handle,
+ 	 */
+ 	if (ex1 && ex1 != ex) {
+ 		ex1 = ex;
+-		ex1->ee_len = cpu_to_le16(iblock - ee_block);
++		ex1->ee_len = cpu_to_le16(map->m_lblk - ee_block);
+ 		ext4_ext_mark_uninitialized(ex1);
+ 		ex2 = &newex;
+ 	}
+ 	/*
+-	 * ex2: iblock to iblock + maxblocks-1 : to be direct IO written,
+-	 * uninitialised still.
++	 * ex2: map->m_lblk to map->m_lblk + map->m_len-1 : to be written
++	 * using direct I/O, uninitialised still.
+ 	 */
+-	ex2->ee_block = cpu_to_le32(iblock);
++	ex2->ee_block = cpu_to_le32(map->m_lblk);
+ 	ext4_ext_store_pblock(ex2, newblock);
+ 	ex2->ee_len = cpu_to_le16(allocated);
+ 	ext4_ext_mark_uninitialized(ex2);
+@@ -3188,10 +3186,9 @@ static void unmap_underlying_metadata_blocks(struct block_device *bdev,
+ 
+ static int
+ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
+-			ext4_lblk_t iblock, unsigned int max_blocks,
++			struct ext4_map_blocks *map,
+ 			struct ext4_ext_path *path, int flags,
+-			unsigned int allocated, struct buffer_head *bh_result,
+-			ext4_fsblk_t newblock)
++			unsigned int allocated, ext4_fsblk_t newblock)
+ {
+ 	int ret = 0;
+ 	int err = 0;
+@@ -3199,15 +3196,14 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
+ 
+ 	ext_debug("ext4_ext_handle_uninitialized_extents: inode %lu, logical"
+ 		  "block %llu, max_blocks %u, flags %d, allocated %u",
+-		  inode->i_ino, (unsigned long long)iblock, max_blocks,
++		  inode->i_ino, (unsigned long long)map->m_lblk, map->m_len,
+ 		  flags, allocated);
+ 	ext4_ext_show_leaf(inode, path);
+ 
+ 	/* get_block() before submit the IO, split the extent */
+ 	if ((flags & EXT4_GET_BLOCKS_PRE_IO)) {
+-		ret = ext4_split_unwritten_extents(handle,
+-						inode, path, iblock,
+-						max_blocks, flags);
++		ret = ext4_split_unwritten_extents(handle, inode, map,
++						   path, flags);
+ 		/*
+ 		 * Flag the inode(non aio case) or end_io struct (aio case)
+ 		 * that this IO needs to convertion to written when IO is
+@@ -3218,7 +3214,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
+ 		else
+ 			ext4_set_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN);
+ 		if (ext4_should_dioread_nolock(inode))
+-			set_buffer_uninit(bh_result);
++			map->m_flags |= EXT4_MAP_UNINIT;
+ 		goto out;
+ 	}
+ 	/* IO end_io complete, convert the filled extent to written */
+@@ -3246,14 +3242,12 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
+ 		 * the buffer head will be unmapped so that
+ 		 * a read from the block returns 0s.
+ 		 */
+-		set_buffer_unwritten(bh_result);
++		map->m_flags |= EXT4_MAP_UNWRITTEN;
+ 		goto out1;
+ 	}
+ 
+ 	/* buffered write, writepage time, convert*/
+-	ret = ext4_ext_convert_to_initialized(handle, inode,
+-						path, iblock,
+-						max_blocks);
++	ret = ext4_ext_convert_to_initialized(handle, inode, map, path);
+ 	if (ret >= 0)
+ 		ext4_update_inode_fsync_trans(handle, inode, 1);
+ out:
+@@ -3262,7 +3256,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
+ 		goto out2;
+ 	} else
+ 		allocated = ret;
+-	set_buffer_new(bh_result);
++	map->m_flags |= EXT4_MAP_NEW;
+ 	/*
+ 	 * if we allocated more blocks than requested
+ 	 * we need to make sure we unmap the extra block
+@@ -3270,11 +3264,11 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
+ 	 * unmapped later when we find the buffer_head marked
+ 	 * new.
+ 	 */
+-	if (allocated > max_blocks) {
++	if (allocated > map->m_len) {
+ 		unmap_underlying_metadata_blocks(inode->i_sb->s_bdev,
+-					newblock + max_blocks,
+-					allocated - max_blocks);
+-		allocated = max_blocks;
++					newblock + map->m_len,
++					allocated - map->m_len);
++		allocated = map->m_len;
+ 	}
+ 
+ 	/*
+@@ -3288,13 +3282,13 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
+ 		ext4_da_update_reserve_space(inode, allocated, 0);
+ 
+ map_out:
+-	set_buffer_mapped(bh_result);
++	map->m_flags |= EXT4_MAP_MAPPED;
+ out1:
+-	if (allocated > max_blocks)
+-		allocated = max_blocks;
++	if (allocated > map->m_len)
++		allocated = map->m_len;
+ 	ext4_ext_show_leaf(inode, path);
+-	bh_result->b_bdev = inode->i_sb->s_bdev;
+-	bh_result->b_blocknr = newblock;
++	map->m_pblk = newblock;
++	map->m_len = allocated;
+ out2:
+ 	if (path) {
+ 		ext4_ext_drop_refs(path);
+@@ -3320,10 +3314,8 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
+  *
+  * return < 0, error case.
+  */
+-int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+-			ext4_lblk_t iblock,
+-			unsigned int max_blocks, struct buffer_head *bh_result,
+-			int flags)
++int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
++			struct ext4_map_blocks *map, int flags)
+ {
+ 	struct ext4_ext_path *path = NULL;
+ 	struct ext4_extent_header *eh;
+@@ -3334,12 +3326,11 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 	struct ext4_allocation_request ar;
+ 	ext4_io_end_t *io = EXT4_I(inode)->cur_aio_dio;
+ 
+-	__clear_bit(BH_New, &bh_result->b_state);
+ 	ext_debug("blocks %u/%u requested for inode %lu\n",
+-			iblock, max_blocks, inode->i_ino);
++		  map->m_lblk, map->m_len, inode->i_ino);
+ 
+ 	/* check in cache */
+-	cache_type = ext4_ext_in_cache(inode, iblock, &newex);
++	cache_type = ext4_ext_in_cache(inode, map->m_lblk, &newex);
+ 	if (cache_type) {
+ 		if (cache_type == EXT4_EXT_CACHE_GAP) {
+ 			if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) {
+@@ -3352,12 +3343,12 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 			/* we should allocate requested block */
+ 		} else if (cache_type == EXT4_EXT_CACHE_EXTENT) {
+ 			/* block is already allocated */
+-			newblock = iblock
++			newblock = map->m_lblk
+ 				   - le32_to_cpu(newex.ee_block)
+ 				   + ext_pblock(&newex);
+ 			/* number of remaining blocks in the extent */
+ 			allocated = ext4_ext_get_actual_len(&newex) -
+-					(iblock - le32_to_cpu(newex.ee_block));
++				(map->m_lblk - le32_to_cpu(newex.ee_block));
+ 			goto out;
+ 		} else {
+ 			BUG();
+@@ -3365,7 +3356,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 	}
+ 
+ 	/* find extent for this block */
+-	path = ext4_ext_find_extent(inode, iblock, NULL);
++	path = ext4_ext_find_extent(inode, map->m_lblk, NULL);
+ 	if (IS_ERR(path)) {
+ 		err = PTR_ERR(path);
+ 		path = NULL;
+@@ -3382,7 +3373,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 	if (unlikely(path[depth].p_ext == NULL && depth != 0)) {
+ 		EXT4_ERROR_INODE(inode, "bad extent address "
+ 				 "iblock: %d, depth: %d pblock %lld",
+-				 iblock, depth, path[depth].p_block);
++				 map->m_lblk, depth, path[depth].p_block);
+ 		err = -EIO;
+ 		goto out2;
+ 	}
+@@ -3400,12 +3391,12 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 		 */
+ 		ee_len = ext4_ext_get_actual_len(ex);
+ 		/* if found extent covers block, simply return it */
+-		if (in_range(iblock, ee_block, ee_len)) {
+-			newblock = iblock - ee_block + ee_start;
++		if (in_range(map->m_lblk, ee_block, ee_len)) {
++			newblock = map->m_lblk - ee_block + ee_start;
+ 			/* number of remaining blocks in the extent */
+-			allocated = ee_len - (iblock - ee_block);
+-			ext_debug("%u fit into %u:%d -> %llu\n", iblock,
+-					ee_block, ee_len, newblock);
++			allocated = ee_len - (map->m_lblk - ee_block);
++			ext_debug("%u fit into %u:%d -> %llu\n", map->m_lblk,
++				  ee_block, ee_len, newblock);
+ 
+ 			/* Do not put uninitialized extent in the cache */
+ 			if (!ext4_ext_is_uninitialized(ex)) {
+@@ -3415,8 +3406,8 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 				goto out;
+ 			}
+ 			ret = ext4_ext_handle_uninitialized_extents(handle,
+-					inode, iblock, max_blocks, path,
+-					flags, allocated, bh_result, newblock);
++					inode, map, path, flags, allocated,
++					newblock);
+ 			return ret;
+ 		}
+ 	}
+@@ -3430,7 +3421,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 		 * put just found gap into cache to speed up
+ 		 * subsequent requests
+ 		 */
+-		ext4_ext_put_gap_in_cache(inode, path, iblock);
++		ext4_ext_put_gap_in_cache(inode, path, map->m_lblk);
+ 		goto out2;
+ 	}
+ 	/*
+@@ -3438,11 +3429,11 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 	 */
+ 
+ 	/* find neighbour allocated blocks */
+-	ar.lleft = iblock;
++	ar.lleft = map->m_lblk;
+ 	err = ext4_ext_search_left(inode, path, &ar.lleft, &ar.pleft);
+ 	if (err)
+ 		goto out2;
+-	ar.lright = iblock;
++	ar.lright = map->m_lblk;
+ 	err = ext4_ext_search_right(inode, path, &ar.lright, &ar.pright);
+ 	if (err)
+ 		goto out2;
+@@ -3453,26 +3444,26 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 	 * EXT_INIT_MAX_LEN and for an uninitialized extent this limit is
+ 	 * EXT_UNINIT_MAX_LEN.
+ 	 */
+-	if (max_blocks > EXT_INIT_MAX_LEN &&
++	if (map->m_len > EXT_INIT_MAX_LEN &&
+ 	    !(flags & EXT4_GET_BLOCKS_UNINIT_EXT))
+-		max_blocks = EXT_INIT_MAX_LEN;
+-	else if (max_blocks > EXT_UNINIT_MAX_LEN &&
++		map->m_len = EXT_INIT_MAX_LEN;
++	else if (map->m_len > EXT_UNINIT_MAX_LEN &&
+ 		 (flags & EXT4_GET_BLOCKS_UNINIT_EXT))
+-		max_blocks = EXT_UNINIT_MAX_LEN;
++		map->m_len = EXT_UNINIT_MAX_LEN;
+ 
+-	/* Check if we can really insert (iblock)::(iblock+max_blocks) extent */
+-	newex.ee_block = cpu_to_le32(iblock);
+-	newex.ee_len = cpu_to_le16(max_blocks);
++	/* Check if we can really insert (m_lblk)::(m_lblk + m_len) extent */
++	newex.ee_block = cpu_to_le32(map->m_lblk);
++	newex.ee_len = cpu_to_le16(map->m_len);
+ 	err = ext4_ext_check_overlap(inode, &newex, path);
+ 	if (err)
+ 		allocated = ext4_ext_get_actual_len(&newex);
+ 	else
+-		allocated = max_blocks;
++		allocated = map->m_len;
+ 
+ 	/* allocate new block */
+ 	ar.inode = inode;
+-	ar.goal = ext4_ext_find_goal(inode, path, iblock);
+-	ar.logical = iblock;
++	ar.goal = ext4_ext_find_goal(inode, path, map->m_lblk);
++	ar.logical = map->m_lblk;
+ 	ar.len = allocated;
+ 	if (S_ISREG(inode->i_mode))
+ 		ar.flags = EXT4_MB_HINT_DATA;
+@@ -3506,7 +3497,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 						     EXT4_STATE_DIO_UNWRITTEN);
+ 		}
+ 		if (ext4_should_dioread_nolock(inode))
+-			set_buffer_uninit(bh_result);
++			map->m_flags |= EXT4_MAP_UNINIT;
+ 	}
+ 
+ 	if (unlikely(EXT4_I(inode)->i_flags & EXT4_EOFBLOCKS_FL)) {
+@@ -3518,7 +3509,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 			goto out2;
+ 		}
+ 		last_ex = EXT_LAST_EXTENT(eh);
+-		if (iblock + ar.len > le32_to_cpu(last_ex->ee_block)
++		if (map->m_lblk + ar.len > le32_to_cpu(last_ex->ee_block)
+ 		    + ext4_ext_get_actual_len(last_ex))
+ 			EXT4_I(inode)->i_flags &= ~EXT4_EOFBLOCKS_FL;
+ 	}
+@@ -3536,9 +3527,9 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 	/* previous routine could use block we allocated */
+ 	newblock = ext_pblock(&newex);
+ 	allocated = ext4_ext_get_actual_len(&newex);
+-	if (allocated > max_blocks)
+-		allocated = max_blocks;
+-	set_buffer_new(bh_result);
++	if (allocated > map->m_len)
++		allocated = map->m_len;
++	map->m_flags |= EXT4_MAP_NEW;
+ 
+ 	/*
+ 	 * Update reserved blocks/metadata blocks after successful
+@@ -3552,18 +3543,18 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 	 * when it is _not_ an uninitialized extent.
+ 	 */
+ 	if ((flags & EXT4_GET_BLOCKS_UNINIT_EXT) == 0) {
+-		ext4_ext_put_in_cache(inode, iblock, allocated, newblock,
++		ext4_ext_put_in_cache(inode, map->m_lblk, allocated, newblock,
+ 						EXT4_EXT_CACHE_EXTENT);
+ 		ext4_update_inode_fsync_trans(handle, inode, 1);
+ 	} else
+ 		ext4_update_inode_fsync_trans(handle, inode, 0);
+ out:
+-	if (allocated > max_blocks)
+-		allocated = max_blocks;
++	if (allocated > map->m_len)
++		allocated = map->m_len;
+ 	ext4_ext_show_leaf(inode, path);
+-	set_buffer_mapped(bh_result);
+-	bh_result->b_bdev = inode->i_sb->s_bdev;
+-	bh_result->b_blocknr = newblock;
++	map->m_flags |= EXT4_MAP_MAPPED;
++	map->m_pblk = newblock;
++	map->m_len = allocated;
+ out2:
+ 	if (path) {
+ 		ext4_ext_drop_refs(path);
+@@ -3729,7 +3720,7 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len)
+ 		if (ret <= 0) {
+ #ifdef EXT4FS_DEBUG
+ 			WARN_ON(ret <= 0);
+-			printk(KERN_ERR "%s: ext4_ext_get_blocks "
++			printk(KERN_ERR "%s: ext4_ext_map_blocks "
+ 				    "returned error inode#%lu, block=%u, "
+ 				    "max_blocks=%u", __func__,
+ 				    inode->i_ino, block, max_blocks);
+@@ -3806,7 +3797,7 @@ int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset,
+ 				      EXT4_GET_BLOCKS_IO_CONVERT_EXT);
+ 		if (ret <= 0) {
+ 			WARN_ON(ret <= 0);
+-			printk(KERN_ERR "%s: ext4_ext_get_blocks "
++			printk(KERN_ERR "%s: ext4_ext_map_blocks "
+ 				    "returned error inode#%lu, block=%u, "
+ 				    "max_blocks=%u", __func__,
+ 				    inode->i_ino, block, max_blocks);
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 830336d3911b..ff2f5fd681b5 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -149,7 +149,7 @@ int ext4_truncate_restart_trans(handle_t *handle, struct inode *inode,
+ 	int ret;
+ 
+ 	/*
+-	 * Drop i_data_sem to avoid deadlock with ext4_get_blocks At this
++	 * Drop i_data_sem to avoid deadlock with ext4_map_blocks.  At this
+ 	 * moment, get_block can be called only for blocks inside i_size since
+ 	 * page cache has been already dropped and writes are blocked by
+ 	 * i_mutex. So we can safely drop the i_data_sem here.
+@@ -890,9 +890,9 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
+ }
+ 
+ /*
+- * The ext4_ind_get_blocks() function handles non-extents inodes
++ * The ext4_ind_map_blocks() function handles non-extents inodes
+  * (i.e., using the traditional indirect/double-indirect i_blocks
+- * scheme) for ext4_get_blocks().
++ * scheme) for ext4_map_blocks().
+  *
+  * Allocation strategy is simple: if we have to allocate something, we will
+  * have to go the whole way to leaf. So let's do it before attaching anything
+@@ -917,9 +917,8 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
+  * down_read(&EXT4_I(inode)->i_data_sem) if not allocating file system
+  * blocks.
+  */
+-static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode,
+-			       ext4_lblk_t iblock, unsigned int maxblocks,
+-			       struct buffer_head *bh_result,
++static int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
++			       struct ext4_map_blocks *map,
+ 			       int flags)
+ {
+ 	int err = -EIO;
+@@ -935,7 +934,7 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode,
+ 
+ 	J_ASSERT(!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL));
+ 	J_ASSERT(handle != NULL || (flags & EXT4_GET_BLOCKS_CREATE) == 0);
+-	depth = ext4_block_to_path(inode, iblock, offsets,
++	depth = ext4_block_to_path(inode, map->m_lblk, offsets,
+ 				   &blocks_to_boundary);
+ 
+ 	if (depth == 0)
+@@ -946,10 +945,9 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode,
+ 	/* Simplest case - block found, no allocation needed */
+ 	if (!partial) {
+ 		first_block = le32_to_cpu(chain[depth - 1].key);
+-		clear_buffer_new(bh_result);
+ 		count++;
+ 		/*map more blocks*/
+-		while (count < maxblocks && count <= blocks_to_boundary) {
++		while (count < map->m_len && count <= blocks_to_boundary) {
+ 			ext4_fsblk_t blk;
+ 
+ 			blk = le32_to_cpu(*(chain[depth-1].p + count));
+@@ -969,7 +967,7 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode,
+ 	/*
+ 	 * Okay, we need to do block allocation.
+ 	*/
+-	goal = ext4_find_goal(inode, iblock, partial);
++	goal = ext4_find_goal(inode, map->m_lblk, partial);
+ 
+ 	/* the number of blocks need to allocate for [d,t]indirect blocks */
+ 	indirect_blks = (chain + depth) - partial - 1;
+@@ -979,11 +977,11 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode,
+ 	 * direct blocks to allocate for this branch.
+ 	 */
+ 	count = ext4_blks_to_allocate(partial, indirect_blks,
+-					maxblocks, blocks_to_boundary);
++				      map->m_len, blocks_to_boundary);
+ 	/*
+ 	 * Block out ext4_truncate while we alter the tree
+ 	 */
+-	err = ext4_alloc_branch(handle, inode, iblock, indirect_blks,
++	err = ext4_alloc_branch(handle, inode, map->m_lblk, indirect_blks,
+ 				&count, goal,
+ 				offsets + (partial - chain), partial);
+ 
+@@ -995,18 +993,20 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode,
+ 	 * may need to return -EAGAIN upwards in the worst case.  --sct
+ 	 */
+ 	if (!err)
+-		err = ext4_splice_branch(handle, inode, iblock,
++		err = ext4_splice_branch(handle, inode, map->m_lblk,
+ 					 partial, indirect_blks, count);
+ 	if (err)
+ 		goto cleanup;
+ 
+-	set_buffer_new(bh_result);
++	map->m_flags |= EXT4_MAP_NEW;
+ 
+ 	ext4_update_inode_fsync_trans(handle, inode, 1);
+ got_it:
+-	map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key));
++	map->m_flags |= EXT4_MAP_MAPPED;
++	map->m_pblk = le32_to_cpu(chain[depth-1].key);
++	map->m_len = count;
+ 	if (count > blocks_to_boundary)
+-		set_buffer_boundary(bh_result);
++		map->m_flags |= EXT4_MAP_BOUNDARY;
+ 	err = count;
+ 	/* Clean up and exit */
+ 	partial = chain + depth - 1;	/* the whole chain */
+@@ -1016,7 +1016,6 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode,
+ 		brelse(partial->bh);
+ 		partial--;
+ 	}
+-	BUFFER_TRACE(bh_result, "returned");
+ out:
+ 	return err;
+ }
+@@ -1203,15 +1202,15 @@ static pgoff_t ext4_num_dirty_pages(struct inode *inode, pgoff_t idx,
+ }
+ 
+ /*
+- * The ext4_get_blocks() function tries to look up the requested blocks,
++ * The ext4_map_blocks() function tries to look up the requested blocks,
+  * and returns if the blocks are already mapped.
+  *
+  * Otherwise it takes the write lock of the i_data_sem and allocate blocks
+  * and store the allocated blocks in the result buffer head and mark it
+  * mapped.
+  *
+- * If file type is extents based, it will call ext4_ext_get_blocks(),
+- * Otherwise, call with ext4_ind_get_blocks() to handle indirect mapping
++ * If file type is extents based, it will call ext4_ext_map_blocks(),
++ * Otherwise, call with ext4_ind_map_blocks() to handle indirect mapping
+  * based files
+  *
+  * On success, it returns the number of blocks being mapped or allocate.
+@@ -1224,35 +1223,30 @@ static pgoff_t ext4_num_dirty_pages(struct inode *inode, pgoff_t idx,
+  *
+  * It returns the error in case of allocation failure.
+  */
+-int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block,
+-		    unsigned int max_blocks, struct buffer_head *bh,
+-		    int flags)
++int ext4_map_blocks(handle_t *handle, struct inode *inode,
++		    struct ext4_map_blocks *map, int flags)
+ {
+ 	int retval;
+ 
+-	clear_buffer_mapped(bh);
+-	clear_buffer_unwritten(bh);
+-
+-	ext_debug("ext4_get_blocks(): inode %lu, flag %d, max_blocks %u,"
+-		  "logical block %lu\n", inode->i_ino, flags, max_blocks,
+-		  (unsigned long)block);
++	map->m_flags = 0;
++	ext_debug("ext4_map_blocks(): inode %lu, flag %d, max_blocks %u,"
++		  "logical block %lu\n", inode->i_ino, flags, map->m_len,
++		  (unsigned long) map->m_lblk);
+ 	/*
+ 	 * Try to see if we can get the block without requesting a new
+ 	 * file system block.
+ 	 */
+ 	down_read((&EXT4_I(inode)->i_data_sem));
+ 	if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) {
+-		retval =  ext4_ext_get_blocks(handle, inode, block, max_blocks,
+-				bh, 0);
++		retval = ext4_ext_map_blocks(handle, inode, map, 0);
+ 	} else {
+-		retval = ext4_ind_get_blocks(handle, inode, block, max_blocks,
+-					     bh, 0);
++		retval = ext4_ind_map_blocks(handle, inode, map, 0);
+ 	}
+ 	up_read((&EXT4_I(inode)->i_data_sem));
+ 
+-	if (retval > 0 && buffer_mapped(bh)) {
++	if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) {
+ 		int ret = check_block_validity(inode, "file system corruption",
+-					       block, bh->b_blocknr, retval);
++					map->m_lblk, map->m_pblk, retval);
+ 		if (ret != 0)
+ 			return ret;
+ 	}
+@@ -1268,7 +1262,7 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block,
+ 	 * ext4_ext_get_block() returns th create = 0
+ 	 * with buffer head unmapped.
+ 	 */
+-	if (retval > 0 && buffer_mapped(bh))
++	if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED)
+ 		return retval;
+ 
+ 	/*
+@@ -1281,7 +1275,7 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block,
+ 	 * of BH_Unwritten and BH_Mapped flags being simultaneously
+ 	 * set on the buffer_head.
+ 	 */
+-	clear_buffer_unwritten(bh);
++	map->m_flags &= ~EXT4_MAP_UNWRITTEN;
+ 
+ 	/*
+ 	 * New blocks allocate and/or writing to uninitialized extent
+@@ -1304,13 +1298,11 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block,
+ 	 * could have changed the inode type in between
+ 	 */
+ 	if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) {
+-		retval =  ext4_ext_get_blocks(handle, inode, block, max_blocks,
+-					      bh, flags);
++		retval = ext4_ext_map_blocks(handle, inode, map, flags);
+ 	} else {
+-		retval = ext4_ind_get_blocks(handle, inode, block,
+-					     max_blocks, bh, flags);
++		retval = ext4_ind_map_blocks(handle, inode, map, flags);
+ 
+-		if (retval > 0 && buffer_new(bh)) {
++		if (retval > 0 && map->m_flags & EXT4_MAP_NEW) {
+ 			/*
+ 			 * We allocated new blocks which will result in
+ 			 * i_data's format changing.  Force the migrate
+@@ -1333,16 +1325,38 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block,
+ 		EXT4_I(inode)->i_delalloc_reserved_flag = 0;
+ 
+ 	up_write((&EXT4_I(inode)->i_data_sem));
+-	if (retval > 0 && buffer_mapped(bh)) {
++	if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) {
+ 		int ret = check_block_validity(inode, "file system "
+ 					       "corruption after allocation",
+-					       block, bh->b_blocknr, retval);
++					       map->m_lblk, map->m_pblk,
++					       retval);
+ 		if (ret != 0)
+ 			return ret;
+ 	}
+ 	return retval;
+ }
+ 
++int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block,
++		    unsigned int max_blocks, struct buffer_head *bh,
++		    int flags)
++{
++	struct ext4_map_blocks map;
++	int ret;
++
++	map.m_lblk = block;
++	map.m_len = max_blocks;
++
++	ret = ext4_map_blocks(handle, inode, &map, flags);
++	if (ret < 0)
++		return ret;
++
++	bh->b_blocknr = map.m_pblk;
++	bh->b_size = inode->i_sb->s_blocksize * map.m_len;
++	bh->b_bdev = inode->i_sb->s_bdev;
++	bh->b_state = (bh->b_state & ~EXT4_MAP_FLAGS) | map.m_flags;
++	return ret;
++}
++
+ /* Maximum number of blocks we map for direct IO at once. */
+ #define DIO_MAX_BLOCKS 4096
+ 

commit 8e48dcfbd7c0892b4cfd064d682cc4c95a29df32
+Author: Theodore Ts'o 
+Date:   Sun May 16 18:00:00 2010 -0400
+
+    ext4: Use our own write_cache_pages()
+    
+    Make a copy of write_cache_pages() for the benefit of
+    ext4_da_writepages().  This allows us to simplify the code some, and
+    will allow us to further customize the code in future patches.
+    
+    There are some nasty hacks in write_cache_pages(), which Linus has
+    (correctly) characterized as vile.  I've just copied it into
+    write_cache_pages_da(), without trying to clean those bits up lest I
+    break something in the ext4's delalloc implementation, which is a bit
+    fragile right now.  This will allow Dave Chinner to clean up
+    write_cache_pages() in mm/page-writeback.c, without worrying about
+    breaking ext4.  Eventually write_cache_pages_da() will go away when I
+    rewrite ext4's delayed allocation and create a general
+    ext4_writepages() which is used for all of ext4's writeback.  Until
+    now this is the lowest risk way to clean up the core
+    write_cache_pages() function.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Dave Chinner 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 6aa0442811d2..830336d3911b 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2426,17 +2426,6 @@ static int __mpage_da_writepage(struct page *page,
+ 	struct buffer_head *bh, *head;
+ 	sector_t logical;
+ 
+-	if (mpd->io_done) {
+-		/*
+-		 * Rest of the page in the page_vec
+-		 * redirty then and skip then. We will
+-		 * try to write them again after
+-		 * starting a new transaction
+-		 */
+-		redirty_page_for_writepage(wbc, page);
+-		unlock_page(page);
+-		return MPAGE_DA_EXTENT_TAIL;
+-	}
+ 	/*
+ 	 * Can we merge this page to current extent?
+ 	 */
+@@ -2831,6 +2820,124 @@ static int ext4_da_writepages_trans_blocks(struct inode *inode)
+ 	return ext4_chunk_trans_blocks(inode, max_blocks);
+ }
+ 
++/*
++ * write_cache_pages_da - walk the list of dirty pages of the given
++ * address space and call the callback function (which usually writes
++ * the pages).
++ *
++ * This is a forked version of write_cache_pages().  Differences:
++ *	Range cyclic is ignored.
++ *	no_nrwrite_index_update is always presumed true
++ */
++static int write_cache_pages_da(struct address_space *mapping,
++				struct writeback_control *wbc,
++				struct mpage_da_data *mpd)
++{
++	int ret = 0;
++	int done = 0;
++	struct pagevec pvec;
++	int nr_pages;
++	pgoff_t index;
++	pgoff_t end;		/* Inclusive */
++	long nr_to_write = wbc->nr_to_write;
++
++	pagevec_init(&pvec, 0);
++	index = wbc->range_start >> PAGE_CACHE_SHIFT;
++	end = wbc->range_end >> PAGE_CACHE_SHIFT;
++
++	while (!done && (index <= end)) {
++		int i;
++
++		nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
++			      PAGECACHE_TAG_DIRTY,
++			      min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1);
++		if (nr_pages == 0)
++			break;
++
++		for (i = 0; i < nr_pages; i++) {
++			struct page *page = pvec.pages[i];
++
++			/*
++			 * At this point, the page may be truncated or
++			 * invalidated (changing page->mapping to NULL), or
++			 * even swizzled back from swapper_space to tmpfs file
++			 * mapping. However, page->index will not change
++			 * because we have a reference on the page.
++			 */
++			if (page->index > end) {
++				done = 1;
++				break;
++			}
++
++			lock_page(page);
++
++			/*
++			 * Page truncated or invalidated. We can freely skip it
++			 * then, even for data integrity operations: the page
++			 * has disappeared concurrently, so there could be no
++			 * real expectation of this data interity operation
++			 * even if there is now a new, dirty page at the same
++			 * pagecache address.
++			 */
++			if (unlikely(page->mapping != mapping)) {
++continue_unlock:
++				unlock_page(page);
++				continue;
++			}
++
++			if (!PageDirty(page)) {
++				/* someone wrote it for us */
++				goto continue_unlock;
++			}
++
++			if (PageWriteback(page)) {
++				if (wbc->sync_mode != WB_SYNC_NONE)
++					wait_on_page_writeback(page);
++				else
++					goto continue_unlock;
++			}
++
++			BUG_ON(PageWriteback(page));
++			if (!clear_page_dirty_for_io(page))
++				goto continue_unlock;
++
++			ret = __mpage_da_writepage(page, wbc, mpd);
++			if (unlikely(ret)) {
++				if (ret == AOP_WRITEPAGE_ACTIVATE) {
++					unlock_page(page);
++					ret = 0;
++				} else {
++					done = 1;
++					break;
++				}
++			}
++
++			if (nr_to_write > 0) {
++				nr_to_write--;
++				if (nr_to_write == 0 &&
++				    wbc->sync_mode == WB_SYNC_NONE) {
++					/*
++					 * We stop writing back only if we are
++					 * not doing integrity sync. In case of
++					 * integrity sync we have to keep going
++					 * because someone may be concurrently
++					 * dirtying pages, and we might have
++					 * synced a lot of newly appeared dirty
++					 * pages, but have not synced all of the
++					 * old dirty pages.
++					 */
++					done = 1;
++					break;
++				}
++			}
++		}
++		pagevec_release(&pvec);
++		cond_resched();
++	}
++	return ret;
++}
++
++
+ static int ext4_da_writepages(struct address_space *mapping,
+ 			      struct writeback_control *wbc)
+ {
+@@ -2839,7 +2946,6 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 	handle_t *handle = NULL;
+ 	struct mpage_da_data mpd;
+ 	struct inode *inode = mapping->host;
+-	int no_nrwrite_index_update;
+ 	int pages_written = 0;
+ 	long pages_skipped;
+ 	unsigned int max_pages;
+@@ -2919,12 +3025,6 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 	mpd.wbc = wbc;
+ 	mpd.inode = mapping->host;
+ 
+-	/*
+-	 * we don't want write_cache_pages to update
+-	 * nr_to_write and writeback_index
+-	 */
+-	no_nrwrite_index_update = wbc->no_nrwrite_index_update;
+-	wbc->no_nrwrite_index_update = 1;
+ 	pages_skipped = wbc->pages_skipped;
+ 
+ retry:
+@@ -2966,8 +3066,7 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 		mpd.io_done = 0;
+ 		mpd.pages_written = 0;
+ 		mpd.retval = 0;
+-		ret = write_cache_pages(mapping, wbc, __mpage_da_writepage,
+-					&mpd);
++		ret = write_cache_pages_da(mapping, wbc, &mpd);
+ 		/*
+ 		 * If we have a contiguous extent of pages and we
+ 		 * haven't done the I/O yet, map the blocks and submit
+@@ -3033,8 +3132,6 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 		mapping->writeback_index = index;
+ 
+ out_writepages:
+-	if (!no_nrwrite_index_update)
+-		wbc->no_nrwrite_index_update = 0;
+ 	wbc->nr_to_write -= nr_to_writebump;
+ 	wbc->range_start = range_start;
+ 	trace_ext4_da_writepages_result(inode, wbc, ret, pages_written);

commit c35a56a090eacefca07afeb994029b57d8dd8025
+Author: Theodore Ts'o 
+Date:   Sun May 16 05:00:00 2010 -0400
+
+    jbd2: Improve scalability by not taking j_state_lock in jbd2_journal_stop()
+    
+    One of the most contended locks in the jbd2 layer is j_state_lock when
+    running dbench.  This is especially true if using the real-time kernel
+    with its "sleeping spinlocks" patch that replaces spinlocks with
+    priority inheriting mutexes --- but it also shows up on large SMP
+    benchmarks.
+    
+    Thanks to John Stultz for pointing this out.
+    
+    Reviewed by Mingming Cao and Jan Kara.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index bfc70f57900f..e214d68620ac 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -1311,7 +1311,6 @@ int jbd2_journal_stop(handle_t *handle)
+ 	if (handle->h_sync)
+ 		transaction->t_synchronous_commit = 1;
+ 	current->journal_info = NULL;
+-	spin_lock(&journal->j_state_lock);
+ 	spin_lock(&transaction->t_handle_lock);
+ 	transaction->t_outstanding_credits -= handle->h_buffer_credits;
+ 	transaction->t_updates--;
+@@ -1340,8 +1339,7 @@ int jbd2_journal_stop(handle_t *handle)
+ 		jbd_debug(2, "transaction too old, requesting commit for "
+ 					"handle %p\n", handle);
+ 		/* This is non-blocking */
+-		__jbd2_log_start_commit(journal, transaction->t_tid);
+-		spin_unlock(&journal->j_state_lock);
++		jbd2_log_start_commit(journal, transaction->t_tid);
+ 
+ 		/*
+ 		 * Special case: JBD2_SYNC synchronous updates require us
+@@ -1351,7 +1349,6 @@ int jbd2_journal_stop(handle_t *handle)
+ 			err = jbd2_log_wait_commit(journal, tid);
+ 	} else {
+ 		spin_unlock(&transaction->t_handle_lock);
+-		spin_unlock(&journal->j_state_lock);
+ 	}
+ 
+ 	lock_map_release(&handle->h_lockdep_map);

commit b90f687018e6d6c77d981b09203780f7001407e5
+Author: Theodore Ts'o 
+Date:   Tue Apr 20 16:51:59 2010 -0400
+
+    ext4: Issue the discard operation *before* releasing the blocks to be reused
+    
+    Otherwise, we can end up having data corruption because the blocks
+    could get reused and then discarded!
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=15579
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 54df209d2eed..e5ab41b559c0 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2534,6 +2534,17 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn)
+ 		mb_debug(1, "gonna free %u blocks in group %u (0x%p):",
+ 			 entry->count, entry->group, entry);
+ 
++		if (test_opt(sb, DISCARD)) {
++			ext4_fsblk_t discard_block;
++
++			discard_block = entry->start_blk +
++				ext4_group_first_block_no(sb, entry->group);
++			trace_ext4_discard_blocks(sb,
++					(unsigned long long)discard_block,
++					entry->count);
++			sb_issue_discard(sb, discard_block, entry->count);
++		}
++
+ 		err = ext4_mb_load_buddy(sb, entry->group, &e4b);
+ 		/* we expect to find existing buddy because it's pinned */
+ 		BUG_ON(err != 0);
+@@ -2555,16 +2566,6 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn)
+ 			page_cache_release(e4b.bd_bitmap_page);
+ 		}
+ 		ext4_unlock_group(sb, entry->group);
+-		if (test_opt(sb, DISCARD)) {
+-			ext4_fsblk_t discard_block;
+-
+-			discard_block = entry->start_blk +
+-				ext4_group_first_block_no(sb, entry->group);
+-			trace_ext4_discard_blocks(sb,
+-					(unsigned long long)discard_block,
+-					entry->count);
+-			sb_issue_discard(sb, discard_block, entry->count);
+-		}
+ 		kmem_cache_free(ext4_free_ext_cachep, entry);
+ 		ext4_mb_release_desc(&e4b);
+ 	}

commit 37f328eb60a94779dd020084209fc4db2d6444a0
+Author: Theodore Ts'o 
+Date:   Wed Mar 24 20:06:41 2010 -0400
+
+    ext4: Fix spelling of CONTIG_FS_EXT3 to CONFIG_FS_EXT3
+    
+    Oops.  (Blush.)
+    
+    Thanks to Sedat Dilek for pointing this out.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index ce84a6ed4a48..f4b038f51f31 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4068,7 +4068,7 @@ static int ext4_get_sb(struct file_system_type *fs_type, int flags,
+ 	return get_sb_bdev(fs_type, flags, dev_name, data, ext4_fill_super,mnt);
+ }
+ 
+-#if !defined(CONTIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23)
++#if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23)
+ static struct file_system_type ext2_fs_type = {
+ 	.owner		= THIS_MODULE,
+ 	.name		= "ext2",
+@@ -4095,7 +4095,7 @@ static inline void register_as_ext2(void) { }
+ static inline void unregister_as_ext2(void) { }
+ #endif
+ 
+-#if !defined(CONTIG_EXT3_FS) && !defined(CONFIG_EXT3_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23)
++#if !defined(CONFIG_EXT3_FS) && !defined(CONFIG_EXT3_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23)
+ static struct file_system_type ext3_fs_type = {
+ 	.owner		= THIS_MODULE,
+ 	.name		= "ext3",

commit f710b4b96ba292dfed2153afc47e9063b0abfd89
+Author: Theodore Ts'o 
+Date:   Mon Jan 25 03:31:32 2010 -0500
+
+    ext4: Reserve INCOMPAT_EA_INODE and INCOMPAT_DIRDATA feature codepoints
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index ffe1334c891e..61cf3b3cde4e 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -284,6 +284,7 @@ struct flex_groups {
+ #define EXT4_TOPDIR_FL			0x00020000 /* Top of directory hierarchies*/
+ #define EXT4_HUGE_FILE_FL               0x00040000 /* Set to each huge file */
+ #define EXT4_EXTENTS_FL			0x00080000 /* Inode uses extents */
++#define EXT4_EA_INODE_FL	        0x00200000 /* Inode used for large EA */
+ #define EXT4_RESERVED_FL		0x80000000 /* reserved for ext4 lib */
+ 
+ #define EXT4_FL_USER_VISIBLE		0x000BDFFF /* User visible flags */
+@@ -1144,6 +1145,8 @@ static inline void ext4_clear_inode_state(struct inode *inode, int bit)
+ #define EXT4_FEATURE_INCOMPAT_64BIT		0x0080
+ #define EXT4_FEATURE_INCOMPAT_MMP               0x0100
+ #define EXT4_FEATURE_INCOMPAT_FLEX_BG		0x0200
++#define EXT4_FEATURE_INCOMPAT_EA_INODE		0x0400 /* EA in inode */
++#define EXT4_FEATURE_INCOMPAT_DIRDATA		0x1000 /* data in dirent */
+ 
+ #define EXT4_FEATURE_COMPAT_SUPP	EXT2_FEATURE_COMPAT_EXT_ATTR
+ #define EXT4_FEATURE_INCOMPAT_SUPP	(EXT4_FEATURE_INCOMPAT_FILETYPE| \

commit 19f5fb7ad679bb361222c7916086435020c37cce
+Author: Theodore Ts'o 
+Date:   Sun Jan 24 14:34:07 2010 -0500
+
+    ext4: Use bitops to read/modify EXT4_I(inode)->i_state
+    
+    At several places we modify EXT4_I(inode)->i_state without holding
+    i_mutex (ext4_release_file, ext4_bmap, ext4_journalled_writepage,
+    ext4_do_update_inode, ...). These modifications are racy and we can
+    lose updates to i_state. So convert handling of i_state to use bitops
+    which are atomic.
+    
+    Cc: Jan Kara 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 307ecd13a762..ffe1334c891e 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -313,17 +313,6 @@ static inline __u32 ext4_mask_flags(umode_t mode, __u32 flags)
+ 		return flags & EXT4_OTHER_FLMASK;
+ }
+ 
+-/*
+- * Inode dynamic state flags
+- */
+-#define EXT4_STATE_JDATA		0x00000001 /* journaled data exists */
+-#define EXT4_STATE_NEW			0x00000002 /* inode is newly created */
+-#define EXT4_STATE_XATTR		0x00000004 /* has in-inode xattrs */
+-#define EXT4_STATE_NO_EXPAND		0x00000008 /* No space for expansion */
+-#define EXT4_STATE_DA_ALLOC_CLOSE	0x00000010 /* Alloc DA blks on close */
+-#define EXT4_STATE_EXT_MIGRATE		0x00000020 /* Inode is migrating */
+-#define EXT4_STATE_DIO_UNWRITTEN	0x00000040 /* need convert on dio done*/
+-
+ /* Used to pass group descriptor data when online resize is done */
+ struct ext4_new_group_input {
+ 	__u32 group;		/* Group number for this data */
+@@ -631,7 +620,7 @@ struct ext4_inode_info {
+ 	 * near to their parent directory's inode.
+ 	 */
+ 	ext4_group_t	i_block_group;
+-	__u32	i_state;		/* Dynamic state flags for ext4 */
++	unsigned long	i_state_flags;		/* Dynamic state flags */
+ 
+ 	ext4_lblk_t		i_dir_start_lookup;
+ #ifdef CONFIG_EXT4_FS_XATTR
+@@ -1051,6 +1040,34 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
+ 		(ino >= EXT4_FIRST_INO(sb) &&
+ 		 ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count));
+ }
++
++/*
++ * Inode dynamic state flags
++ */
++enum {
++	EXT4_STATE_JDATA,		/* journaled data exists */
++	EXT4_STATE_NEW,			/* inode is newly created */
++	EXT4_STATE_XATTR,		/* has in-inode xattrs */
++	EXT4_STATE_NO_EXPAND,		/* No space for expansion */
++	EXT4_STATE_DA_ALLOC_CLOSE,	/* Alloc DA blks on close */
++	EXT4_STATE_EXT_MIGRATE,		/* Inode is migrating */
++	EXT4_STATE_DIO_UNWRITTEN,	/* need convert on dio done*/
++};
++
++static inline int ext4_test_inode_state(struct inode *inode, int bit)
++{
++	return test_bit(bit, &EXT4_I(inode)->i_state_flags);
++}
++
++static inline void ext4_set_inode_state(struct inode *inode, int bit)
++{
++	set_bit(bit, &EXT4_I(inode)->i_state_flags);
++}
++
++static inline void ext4_clear_inode_state(struct inode *inode, int bit)
++{
++	clear_bit(bit, &EXT4_I(inode)->i_state_flags);
++}
+ #else
+ /* Assume that user mode programs are passing in an ext4fs superblock, not
+  * a kernel struct super_block.  This will allow us to call the feature-test
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index c56877972b0e..54616157c0f3 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -3076,7 +3076,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
+ 		if (io)
+ 			io->flag = DIO_AIO_UNWRITTEN;
+ 		else
+-			EXT4_I(inode)->i_state |= EXT4_STATE_DIO_UNWRITTEN;
++			ext4_set_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN);
+ 		goto out;
+ 	}
+ 	/* async DIO end_io complete, convert the filled extent to written */
+@@ -3362,8 +3362,8 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 			if (io)
+ 				io->flag = DIO_AIO_UNWRITTEN;
+ 			else
+-				EXT4_I(inode)->i_state |=
+-					EXT4_STATE_DIO_UNWRITTEN;;
++				ext4_set_inode_state(inode,
++						     EXT4_STATE_DIO_UNWRITTEN);
+ 		}
+ 	}
+ 	err = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
+@@ -3739,7 +3739,7 @@ static int ext4_xattr_fiemap(struct inode *inode,
+ 	int error = 0;
+ 
+ 	/* in-inode? */
+-	if (EXT4_I(inode)->i_state & EXT4_STATE_XATTR) {
++	if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) {
+ 		struct ext4_iloc iloc;
+ 		int offset;	/* offset of xattr in inode */
+ 
+diff --git a/fs/ext4/file.c b/fs/ext4/file.c
+index 9630583cef28..f6071ce0b155 100644
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -35,9 +35,9 @@
+  */
+ static int ext4_release_file(struct inode *inode, struct file *filp)
+ {
+-	if (EXT4_I(inode)->i_state & EXT4_STATE_DA_ALLOC_CLOSE) {
++	if (ext4_test_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE)) {
+ 		ext4_alloc_da_blocks(inode);
+-		EXT4_I(inode)->i_state &= ~EXT4_STATE_DA_ALLOC_CLOSE;
++		ext4_clear_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE);
+ 	}
+ 	/* if we are the last writer on the inode, drop the block reservation */
+ 	if ((filp->f_mode & FMODE_WRITE) &&
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index f3624ead4f6c..2fab5adae1e2 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -1029,7 +1029,8 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
+ 	inode->i_generation = sbi->s_next_generation++;
+ 	spin_unlock(&sbi->s_next_gen_lock);
+ 
+-	ei->i_state = EXT4_STATE_NEW;
++	ei->i_state_flags = 0;
++	ext4_set_inode_state(inode, EXT4_STATE_NEW);
+ 
+ 	ei->i_extra_isize = EXT4_SB(sb)->s_want_extra_isize;
+ 
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 1a3d7b232cd7..3e530119d7f0 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1307,7 +1307,7 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block,
+ 			 * i_data's format changing.  Force the migrate
+ 			 * to fail by clearing migrate flags
+ 			 */
+-			EXT4_I(inode)->i_state &= ~EXT4_STATE_EXT_MIGRATE;
++			ext4_clear_inode_state(inode, EXT4_STATE_EXT_MIGRATE);
+ 		}
+ 
+ 		/*
+@@ -1794,7 +1794,7 @@ static int ext4_journalled_write_end(struct file *file,
+ 	new_i_size = pos + copied;
+ 	if (new_i_size > inode->i_size)
+ 		i_size_write(inode, pos+copied);
+-	EXT4_I(inode)->i_state |= EXT4_STATE_JDATA;
++	ext4_set_inode_state(inode, EXT4_STATE_JDATA);
+ 	if (new_i_size > EXT4_I(inode)->i_disksize) {
+ 		ext4_update_i_disksize(inode, new_i_size);
+ 		ret2 = ext4_mark_inode_dirty(handle, inode);
+@@ -2632,7 +2632,7 @@ static int __ext4_journalled_writepage(struct page *page,
+ 		ret = err;
+ 
+ 	walk_page_buffers(handle, page_bufs, 0, len, NULL, bput_one);
+-	EXT4_I(inode)->i_state |= EXT4_STATE_JDATA;
++	ext4_set_inode_state(inode, EXT4_STATE_JDATA);
+ out:
+ 	return ret;
+ }
+@@ -3303,7 +3303,8 @@ static sector_t ext4_bmap(struct address_space *mapping, sector_t block)
+ 		filemap_write_and_wait(mapping);
+ 	}
+ 
+-	if (EXT4_JOURNAL(inode) && EXT4_I(inode)->i_state & EXT4_STATE_JDATA) {
++	if (EXT4_JOURNAL(inode) &&
++	    ext4_test_inode_state(inode, EXT4_STATE_JDATA)) {
+ 		/*
+ 		 * This is a REALLY heavyweight approach, but the use of
+ 		 * bmap on dirty files is expected to be extremely rare:
+@@ -3322,7 +3323,7 @@ static sector_t ext4_bmap(struct address_space *mapping, sector_t block)
+ 		 * everything they get.
+ 		 */
+ 
+-		EXT4_I(inode)->i_state &= ~EXT4_STATE_JDATA;
++		ext4_clear_inode_state(inode, EXT4_STATE_JDATA);
+ 		journal = EXT4_JOURNAL(inode);
+ 		jbd2_journal_lock_updates(journal);
+ 		err = jbd2_journal_flush(journal);
+@@ -3790,8 +3791,8 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
+ 		if (ret != -EIOCBQUEUED && ret <= 0 && iocb->private) {
+ 			ext4_free_io_end(iocb->private);
+ 			iocb->private = NULL;
+-		} else if (ret > 0 && (EXT4_I(inode)->i_state &
+-				       EXT4_STATE_DIO_UNWRITTEN)) {
++		} else if (ret > 0 && ext4_test_inode_state(inode,
++						EXT4_STATE_DIO_UNWRITTEN)) {
+ 			int err;
+ 			/*
+ 			 * for non AIO case, since the IO is already
+@@ -3801,7 +3802,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
+ 							     offset, ret);
+ 			if (err < 0)
+ 				ret = err;
+-			EXT4_I(inode)->i_state &= ~EXT4_STATE_DIO_UNWRITTEN;
++			ext4_clear_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN);
+ 		}
+ 		return ret;
+ 	}
+@@ -4457,7 +4458,7 @@ void ext4_truncate(struct inode *inode)
+ 		return;
+ 
+ 	if (inode->i_size == 0 && !test_opt(inode->i_sb, NO_AUTO_DA_ALLOC))
+-		ei->i_state |= EXT4_STATE_DA_ALLOC_CLOSE;
++		ext4_set_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE);
+ 
+ 	if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) {
+ 		ext4_ext_truncate(inode);
+@@ -4743,7 +4744,7 @@ int ext4_get_inode_loc(struct inode *inode, struct ext4_iloc *iloc)
+ {
+ 	/* We have all inode data except xattrs in memory here. */
+ 	return __ext4_get_inode_loc(inode, iloc,
+-		!(EXT4_I(inode)->i_state & EXT4_STATE_XATTR));
++		!ext4_test_inode_state(inode, EXT4_STATE_XATTR));
+ }
+ 
+ void ext4_set_inode_flags(struct inode *inode)
+@@ -4837,7 +4838,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 	}
+ 	inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
+ 
+-	ei->i_state = 0;
++	ei->i_state_flags = 0;
+ 	ei->i_dir_start_lookup = 0;
+ 	ei->i_dtime = le32_to_cpu(raw_inode->i_dtime);
+ 	/* We now have enough fields to check if the inode was active or not.
+@@ -4920,7 +4921,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 					EXT4_GOOD_OLD_INODE_SIZE +
+ 					ei->i_extra_isize;
+ 			if (*magic == cpu_to_le32(EXT4_XATTR_MAGIC))
+-				ei->i_state |= EXT4_STATE_XATTR;
++				ext4_set_inode_state(inode, EXT4_STATE_XATTR);
+ 		}
+ 	} else
+ 		ei->i_extra_isize = 0;
+@@ -5060,7 +5061,7 @@ static int ext4_do_update_inode(handle_t *handle,
+ 
+ 	/* For fields not not tracking in the in-memory inode,
+ 	 * initialise them to zero for new inodes. */
+-	if (ei->i_state & EXT4_STATE_NEW)
++	if (ext4_test_inode_state(inode, EXT4_STATE_NEW))
+ 		memset(raw_inode, 0, EXT4_SB(inode->i_sb)->s_inode_size);
+ 
+ 	ext4_get_inode_flags(ei);
+@@ -5156,7 +5157,7 @@ static int ext4_do_update_inode(handle_t *handle,
+ 	rc = ext4_handle_dirty_metadata(handle, inode, bh);
+ 	if (!err)
+ 		err = rc;
+-	ei->i_state &= ~EXT4_STATE_NEW;
++	ext4_clear_inode_state(inode, EXT4_STATE_NEW);
+ 
+ 	ext4_update_inode_fsync_trans(handle, inode, 0);
+ out_brelse:
+@@ -5580,8 +5581,8 @@ static int ext4_expand_extra_isize(struct inode *inode,
+ 	entry = IFIRST(header);
+ 
+ 	/* No extended attributes present */
+-	if (!(EXT4_I(inode)->i_state & EXT4_STATE_XATTR) ||
+-		header->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC)) {
++	if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR) ||
++	    header->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC)) {
+ 		memset((void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE, 0,
+ 			new_extra_isize);
+ 		EXT4_I(inode)->i_extra_isize = new_extra_isize;
+@@ -5625,7 +5626,7 @@ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode)
+ 	err = ext4_reserve_inode_write(handle, inode, &iloc);
+ 	if (ext4_handle_valid(handle) &&
+ 	    EXT4_I(inode)->i_extra_isize < sbi->s_want_extra_isize &&
+-	    !(EXT4_I(inode)->i_state & EXT4_STATE_NO_EXPAND)) {
++	    !ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND)) {
+ 		/*
+ 		 * We need extra buffer credits since we may write into EA block
+ 		 * with this same handle. If journal_extend fails, then it will
+@@ -5639,7 +5640,8 @@ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode)
+ 						      sbi->s_want_extra_isize,
+ 						      iloc, handle);
+ 			if (ret) {
+-				EXT4_I(inode)->i_state |= EXT4_STATE_NO_EXPAND;
++				ext4_set_inode_state(inode,
++						     EXT4_STATE_NO_EXPAND);
+ 				if (mnt_count !=
+ 					le16_to_cpu(sbi->s_es->s_mnt_count)) {
+ 					ext4_warning(inode->i_sb, __func__,
+diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
+index 81415814b00b..46a4101e0aec 100644
+--- a/fs/ext4/migrate.c
++++ b/fs/ext4/migrate.c
+@@ -365,12 +365,12 @@ static int ext4_ext_swap_inode_data(handle_t *handle, struct inode *inode,
+ 	 * happened after we started the migrate. We need to
+ 	 * fail the migrate
+ 	 */
+-	if (!(EXT4_I(inode)->i_state & EXT4_STATE_EXT_MIGRATE)) {
++	if (!ext4_test_inode_state(inode, EXT4_STATE_EXT_MIGRATE)) {
+ 		retval = -EAGAIN;
+ 		up_write(&EXT4_I(inode)->i_data_sem);
+ 		goto err_out;
+ 	} else
+-		EXT4_I(inode)->i_state &= ~EXT4_STATE_EXT_MIGRATE;
++		ext4_clear_inode_state(inode, EXT4_STATE_EXT_MIGRATE);
+ 	/*
+ 	 * We have the extent map build with the tmp inode.
+ 	 * Now copy the i_data across
+@@ -533,7 +533,7 @@ int ext4_ext_migrate(struct inode *inode)
+ 	 * allocation.
+ 	 */
+ 	down_read((&EXT4_I(inode)->i_data_sem));
+-	EXT4_I(inode)->i_state |= EXT4_STATE_EXT_MIGRATE;
++	ext4_set_inode_state(inode, EXT4_STATE_EXT_MIGRATE);
+ 	up_read((&EXT4_I(inode)->i_data_sem));
+ 
+ 	handle = ext4_journal_start(inode, 1);
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index f3a2f7ed45aa..c619a7ea670d 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -267,7 +267,7 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
+ 	void *end;
+ 	int error;
+ 
+-	if (!(EXT4_I(inode)->i_state & EXT4_STATE_XATTR))
++	if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR))
+ 		return -ENODATA;
+ 	error = ext4_get_inode_loc(inode, &iloc);
+ 	if (error)
+@@ -396,7 +396,7 @@ ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size)
+ 	void *end;
+ 	int error;
+ 
+-	if (!(EXT4_I(inode)->i_state & EXT4_STATE_XATTR))
++	if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR))
+ 		return 0;
+ 	error = ext4_get_inode_loc(inode, &iloc);
+ 	if (error)
+@@ -908,7 +908,7 @@ ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i,
+ 	is->s.base = is->s.first = IFIRST(header);
+ 	is->s.here = is->s.first;
+ 	is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
+-	if (EXT4_I(inode)->i_state & EXT4_STATE_XATTR) {
++	if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) {
+ 		error = ext4_xattr_check_names(IFIRST(header), is->s.end);
+ 		if (error)
+ 			return error;
+@@ -940,10 +940,10 @@ ext4_xattr_ibody_set(handle_t *handle, struct inode *inode,
+ 	header = IHDR(inode, ext4_raw_inode(&is->iloc));
+ 	if (!IS_LAST_ENTRY(s->first)) {
+ 		header->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC);
+-		EXT4_I(inode)->i_state |= EXT4_STATE_XATTR;
++		ext4_set_inode_state(inode, EXT4_STATE_XATTR);
+ 	} else {
+ 		header->h_magic = cpu_to_le32(0);
+-		EXT4_I(inode)->i_state &= ~EXT4_STATE_XATTR;
++		ext4_clear_inode_state(inode, EXT4_STATE_XATTR);
+ 	}
+ 	return 0;
+ }
+@@ -986,8 +986,8 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
+ 	if (strlen(name) > 255)
+ 		return -ERANGE;
+ 	down_write(&EXT4_I(inode)->xattr_sem);
+-	no_expand = EXT4_I(inode)->i_state & EXT4_STATE_NO_EXPAND;
+-	EXT4_I(inode)->i_state |= EXT4_STATE_NO_EXPAND;
++	no_expand = ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND);
++	ext4_set_inode_state(inode, EXT4_STATE_NO_EXPAND);
+ 
+ 	error = ext4_get_inode_loc(inode, &is.iloc);
+ 	if (error)
+@@ -997,10 +997,10 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
+ 	if (error)
+ 		goto cleanup;
+ 
+-	if (EXT4_I(inode)->i_state & EXT4_STATE_NEW) {
++	if (ext4_test_inode_state(inode, EXT4_STATE_NEW)) {
+ 		struct ext4_inode *raw_inode = ext4_raw_inode(&is.iloc);
+ 		memset(raw_inode, 0, EXT4_SB(inode->i_sb)->s_inode_size);
+-		EXT4_I(inode)->i_state &= ~EXT4_STATE_NEW;
++		ext4_clear_inode_state(inode, EXT4_STATE_NEW);
+ 	}
+ 
+ 	error = ext4_xattr_ibody_find(inode, &i, &is);
+@@ -1052,7 +1052,7 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
+ 		ext4_xattr_update_super_block(handle, inode->i_sb);
+ 		inode->i_ctime = ext4_current_time(inode);
+ 		if (!value)
+-			EXT4_I(inode)->i_state &= ~EXT4_STATE_NO_EXPAND;
++			ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND);
+ 		error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);
+ 		/*
+ 		 * The bh is consumed by ext4_mark_iloc_dirty, even with
+@@ -1067,7 +1067,7 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
+ 	brelse(is.iloc.bh);
+ 	brelse(bs.bh);
+ 	if (no_expand == 0)
+-		EXT4_I(inode)->i_state &= ~EXT4_STATE_NO_EXPAND;
++		ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND);
+ 	up_write(&EXT4_I(inode)->xattr_sem);
+ 	return error;
+ }

commit 1d3c36ad4122651018599d4e3c9be0cccfbfb939
+Author: Andrew Lutomirski 
+Date:   Mon Dec 21 10:10:22 2009 -0500
+
+    drm/i915: Fix RC6 suspend/resume
+    
+    We restored RC6 twice on resume, even with modesetting off.  Instead,
+    only restore it once and skip RC6 initialization entirely in non-KMS mode.
+    
+    Signed-off-by: Andy Lutomirski 
+    Tested-by: Jeff Chua 
+    Signed-off-by: Eric Anholt 
+
+diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
+index 7eb4ad51034d..29dd67626967 100644
+--- a/drivers/gpu/drm/i915/i915_drv.h
++++ b/drivers/gpu/drm/i915/i915_drv.h
+@@ -307,8 +307,6 @@ typedef struct drm_i915_private {
+ 	u32 saveDSPACNTR;
+ 	u32 saveDSPBCNTR;
+ 	u32 saveDSPARB;
+-	u32 saveRENDERSTANDBY;
+-	u32 savePWRCTXA;
+ 	u32 saveHWS;
+ 	u32 savePIPEACONF;
+ 	u32 savePIPEBCONF;
+diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
+index d5ebb00a9d49..a3b90c9561dc 100644
+--- a/drivers/gpu/drm/i915/i915_suspend.c
++++ b/drivers/gpu/drm/i915/i915_suspend.c
+@@ -732,12 +732,6 @@ int i915_save_state(struct drm_device *dev)
+ 
+ 	pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
+ 
+-	/* Render Standby */
+-	if (I915_HAS_RC6(dev)) {
+-		dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY);
+-		dev_priv->savePWRCTXA = I915_READ(PWRCTXA);
+-	}
+-
+ 	/* Hardware status page */
+ 	dev_priv->saveHWS = I915_READ(HWS_PGA);
+ 
+@@ -793,12 +787,6 @@ int i915_restore_state(struct drm_device *dev)
+ 
+ 	pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB);
+ 
+-	/* Render Standby */
+-	if (I915_HAS_RC6(dev)) {
+-		I915_WRITE(MCHBAR_RENDER_STANDBY, dev_priv->saveRENDERSTANDBY);
+-		I915_WRITE(PWRCTXA, dev_priv->savePWRCTXA);
+-	}
+-
+ 	/* Hardware status page */
+ 	I915_WRITE(HWS_PGA, dev_priv->saveHWS);
+ 
+diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
+index c21dede6461c..089b1df5448b 100644
+--- a/drivers/gpu/drm/i915/intel_display.c
++++ b/drivers/gpu/drm/i915/intel_display.c
+@@ -4593,7 +4593,7 @@ void intel_init_clock_gating(struct drm_device *dev)
+ 	 * GPU can automatically power down the render unit if given a page
+ 	 * to save state.
+ 	 */
+-	if (I915_HAS_RC6(dev)) {
++	if (I915_HAS_RC6(dev) && drm_core_check_feature(dev, DRIVER_MODESET)) {
+ 		struct drm_gem_object *pwrctx;
+ 		struct drm_i915_gem_object *obj_priv;
+ 		int ret;

commit 9d0be50230b333005635967f7ecd4897dbfd181b
+Author: Theodore Ts'o 
+Date:   Fri Jan 1 02:41:30 2010 -0500
+
+    ext4: Calculate metadata requirements more accurately
+    
+    In the past, ext4_calc_metadata_amount(), and its sub-functions
+    ext4_ext_calc_metadata_amount() and ext4_indirect_calc_metadata_amount()
+    badly over-estimated the number of metadata blocks that might be
+    required for delayed allocation blocks.  This didn't matter as much
+    when functions which managed the reserved metadata blocks were more
+    aggressive about dropping reserved metadata blocks as delayed
+    allocation blocks were written, but unfortunately they were too
+    aggressive.  This was fixed in commit 0637c6f, but as a result the
+    over-estimation by ext4_calc_metadata_amount() would lead to reserving
+    2-3 times the number of pending delayed allocation blocks as
+    potentially required metadata blocks.  So if there are 1 megabytes of
+    blocks which have been not yet been allocation, up to 3 megabytes of
+    space would get reserved out of the user's quota and from the file
+    system free space pool until all of the inode's data blocks have been
+    allocated.
+    
+    This commit addresses this problem by much more accurately estimating
+    the number of metadata blocks that will be required.  It will still
+    somewhat over-estimate the number of blocks needed, since it must make
+    a worst case estimate not knowing which physical blocks will be
+    needed, but it is much more accurate than before.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 56f9271ee8cc..af7b62699ea9 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -699,6 +699,8 @@ struct ext4_inode_info {
+ 	unsigned int i_reserved_meta_blocks;
+ 	unsigned int i_allocated_meta_blocks;
+ 	unsigned short i_delalloc_reserved_flag;
++	sector_t i_da_metadata_calc_last_lblock;
++	int i_da_metadata_calc_len;
+ 
+ 	/* on-disk additional length */
+ 	__u16 i_extra_isize;
+diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h
+index 2ca686454e87..bdb6ce7e2eb4 100644
+--- a/fs/ext4/ext4_extents.h
++++ b/fs/ext4/ext4_extents.h
+@@ -225,7 +225,8 @@ static inline void ext4_ext_mark_initialized(struct ext4_extent *ext)
+ 	ext->ee_len = cpu_to_le16(ext4_ext_get_actual_len(ext));
+ }
+ 
+-extern int ext4_ext_calc_metadata_amount(struct inode *inode, int blocks);
++extern int ext4_ext_calc_metadata_amount(struct inode *inode,
++					 sector_t lblocks);
+ extern ext4_fsblk_t ext_pblock(struct ext4_extent *ex);
+ extern ext4_fsblk_t idx_pblock(struct ext4_extent_idx *);
+ extern void ext4_ext_store_pblock(struct ext4_extent *, ext4_fsblk_t);
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 91ae46098ea4..7d7b74e94687 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -296,29 +296,44 @@ static inline int ext4_ext_space_root_idx(struct inode *inode, int check)
+  * to allocate @blocks
+  * Worse case is one block per extent
+  */
+-int ext4_ext_calc_metadata_amount(struct inode *inode, int blocks)
++int ext4_ext_calc_metadata_amount(struct inode *inode, sector_t lblock)
+ {
+-	int lcap, icap, rcap, leafs, idxs, num;
+-	int newextents = blocks;
+-
+-	rcap = ext4_ext_space_root_idx(inode, 0);
+-	lcap = ext4_ext_space_block(inode, 0);
+-	icap = ext4_ext_space_block_idx(inode, 0);
++	struct ext4_inode_info *ei = EXT4_I(inode);
++	int idxs, num = 0;
+ 
+-	/* number of new leaf blocks needed */
+-	num = leafs = (newextents + lcap - 1) / lcap;
++	idxs = ((inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header))
++		/ sizeof(struct ext4_extent_idx));
+ 
+ 	/*
+-	 * Worse case, we need separate index block(s)
+-	 * to link all new leaf blocks
++	 * If the new delayed allocation block is contiguous with the
++	 * previous da block, it can share index blocks with the
++	 * previous block, so we only need to allocate a new index
++	 * block every idxs leaf blocks.  At ldxs**2 blocks, we need
++	 * an additional index block, and at ldxs**3 blocks, yet
++	 * another index blocks.
+ 	 */
+-	idxs = (leafs + icap - 1) / icap;
+-	do {
+-		num += idxs;
+-		idxs = (idxs + icap - 1) / icap;
+-	} while (idxs > rcap);
++	if (ei->i_da_metadata_calc_len &&
++	    ei->i_da_metadata_calc_last_lblock+1 == lblock) {
++		if ((ei->i_da_metadata_calc_len % idxs) == 0)
++			num++;
++		if ((ei->i_da_metadata_calc_len % (idxs*idxs)) == 0)
++			num++;
++		if ((ei->i_da_metadata_calc_len % (idxs*idxs*idxs)) == 0) {
++			num++;
++			ei->i_da_metadata_calc_len = 0;
++		} else
++			ei->i_da_metadata_calc_len++;
++		ei->i_da_metadata_calc_last_lblock++;
++		return num;
++	}
+ 
+-	return num;
++	/*
++	 * In the worst case we need a new set of index blocks at
++	 * every level of the inode's extent tree.
++	 */
++	ei->i_da_metadata_calc_len = 1;
++	ei->i_da_metadata_calc_last_lblock = lblock;
++	return ext_depth(inode) + 1;
+ }
+ 
+ static int
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index bdaa92a29e0e..c818972c8302 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1009,38 +1009,44 @@ qsize_t *ext4_get_reserved_space(struct inode *inode)
+ 	return &EXT4_I(inode)->i_reserved_quota;
+ }
+ #endif
++
+ /*
+  * Calculate the number of metadata blocks need to reserve
+- * to allocate @blocks for non extent file based file
++ * to allocate a new block at @lblocks for non extent file based file
+  */
+-static int ext4_indirect_calc_metadata_amount(struct inode *inode, int blocks)
++static int ext4_indirect_calc_metadata_amount(struct inode *inode,
++					      sector_t lblock)
+ {
+-	int icap = EXT4_ADDR_PER_BLOCK(inode->i_sb);
+-	int ind_blks, dind_blks, tind_blks;
+-
+-	/* number of new indirect blocks needed */
+-	ind_blks = (blocks + icap - 1) / icap;
++	struct ext4_inode_info *ei = EXT4_I(inode);
++	int dind_mask = EXT4_ADDR_PER_BLOCK(inode->i_sb) - 1;
++	int blk_bits;
+ 
+-	dind_blks = (ind_blks + icap - 1) / icap;
++	if (lblock < EXT4_NDIR_BLOCKS)
++		return 0;
+ 
+-	tind_blks = 1;
++	lblock -= EXT4_NDIR_BLOCKS;
+ 
+-	return ind_blks + dind_blks + tind_blks;
++	if (ei->i_da_metadata_calc_len &&
++	    (lblock & dind_mask) == ei->i_da_metadata_calc_last_lblock) {
++		ei->i_da_metadata_calc_len++;
++		return 0;
++	}
++	ei->i_da_metadata_calc_last_lblock = lblock & dind_mask;
++	ei->i_da_metadata_calc_len = 1;
++	blk_bits = roundup_pow_of_two(lblock + 1);
++	return (blk_bits / EXT4_ADDR_PER_BLOCK_BITS(inode->i_sb)) + 1;
+ }
+ 
+ /*
+  * Calculate the number of metadata blocks need to reserve
+- * to allocate given number of blocks
++ * to allocate a block located at @lblock
+  */
+-static int ext4_calc_metadata_amount(struct inode *inode, int blocks)
++static int ext4_calc_metadata_amount(struct inode *inode, sector_t lblock)
+ {
+-	if (!blocks)
+-		return 0;
+-
+ 	if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)
+-		return ext4_ext_calc_metadata_amount(inode, blocks);
++		return ext4_ext_calc_metadata_amount(inode, lblock);
+ 
+-	return ext4_indirect_calc_metadata_amount(inode, blocks);
++	return ext4_indirect_calc_metadata_amount(inode, lblock);
+ }
+ 
+ /*
+@@ -1078,6 +1084,7 @@ static void ext4_da_update_reserve_space(struct inode *inode, int used)
+ 		 */
+ 		mdb_free = ei->i_reserved_meta_blocks;
+ 		ei->i_reserved_meta_blocks = 0;
++		ei->i_da_metadata_calc_len = 0;
+ 		percpu_counter_sub(&sbi->s_dirtyblocks_counter, mdb_free);
+ 	}
+ 	spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+@@ -1802,12 +1809,15 @@ static int ext4_journalled_write_end(struct file *file,
+ 	return ret ? ret : copied;
+ }
+ 
+-static int ext4_da_reserve_space(struct inode *inode, int nrblocks)
++/*
++ * Reserve a single block located at lblock
++ */
++static int ext4_da_reserve_space(struct inode *inode, sector_t lblock)
+ {
+ 	int retries = 0;
+ 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+ 	struct ext4_inode_info *ei = EXT4_I(inode);
+-	unsigned long md_needed, md_reserved, total = 0;
++	unsigned long md_needed, md_reserved;
+ 
+ 	/*
+ 	 * recalculate the amount of metadata blocks to reserve
+@@ -1817,8 +1827,7 @@ static int ext4_da_reserve_space(struct inode *inode, int nrblocks)
+ repeat:
+ 	spin_lock(&ei->i_block_reservation_lock);
+ 	md_reserved = ei->i_reserved_meta_blocks;
+-	md_needed = ext4_calc_metadata_amount(inode, nrblocks);
+-	total = md_needed + nrblocks;
++	md_needed = ext4_calc_metadata_amount(inode, lblock);
+ 	spin_unlock(&ei->i_block_reservation_lock);
+ 
+ 	/*
+@@ -1826,7 +1835,7 @@ static int ext4_da_reserve_space(struct inode *inode, int nrblocks)
+ 	 * later. Real quota accounting is done at pages writeout
+ 	 * time.
+ 	 */
+-	if (vfs_dq_reserve_block(inode, total)) {
++	if (vfs_dq_reserve_block(inode, md_needed + 1)) {
+ 		/* 
+ 		 * We tend to badly over-estimate the amount of
+ 		 * metadata blocks which are needed, so if we have
+@@ -1838,8 +1847,8 @@ static int ext4_da_reserve_space(struct inode *inode, int nrblocks)
+ 		return -EDQUOT;
+ 	}
+ 
+-	if (ext4_claim_free_blocks(sbi, total)) {
+-		vfs_dq_release_reservation_block(inode, total);
++	if (ext4_claim_free_blocks(sbi, md_needed + 1)) {
++		vfs_dq_release_reservation_block(inode, md_needed + 1);
+ 		if (ext4_should_retry_alloc(inode->i_sb, &retries)) {
+ 		retry:
+ 			if (md_reserved)
+@@ -1850,7 +1859,7 @@ static int ext4_da_reserve_space(struct inode *inode, int nrblocks)
+ 		return -ENOSPC;
+ 	}
+ 	spin_lock(&ei->i_block_reservation_lock);
+-	ei->i_reserved_data_blocks += nrblocks;
++	ei->i_reserved_data_blocks++;
+ 	ei->i_reserved_meta_blocks += md_needed;
+ 	spin_unlock(&ei->i_block_reservation_lock);
+ 
+@@ -1891,6 +1900,7 @@ static void ext4_da_release_space(struct inode *inode, int to_free)
+ 		 */
+ 		to_free += ei->i_reserved_meta_blocks;
+ 		ei->i_reserved_meta_blocks = 0;
++		ei->i_da_metadata_calc_len = 0;
+ 	}
+ 
+ 	/* update fs dirty blocks counter */
+@@ -2504,7 +2514,7 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock,
+ 		 * XXX: __block_prepare_write() unmaps passed block,
+ 		 * is it OK?
+ 		 */
+-		ret = ext4_da_reserve_space(inode, 1);
++		ret = ext4_da_reserve_space(inode, iblock);
+ 		if (ret)
+ 			/* not enough space to reserve */
+ 			return ret;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 7cccb35c0f4d..735c20d5fd56 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -702,6 +702,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
+ 	ei->i_reserved_data_blocks = 0;
+ 	ei->i_reserved_meta_blocks = 0;
+ 	ei->i_allocated_meta_blocks = 0;
++	ei->i_da_metadata_calc_len = 0;
+ 	ei->i_delalloc_reserved_flag = 0;
+ 	spin_lock_init(&(ei->i_block_reservation_lock));
+ #ifdef CONFIG_QUOTA

commit ee5f4d9cdf32fd99172d11665c592a288c2b1ff4
+Author: Theodore Ts'o 
+Date:   Fri Jan 1 02:36:15 2010 -0500
+
+    ext4: Fix accounting of reserved metadata blocks
+    
+    Commit 0637c6f had a typo which caused the reserved metadata blocks to
+    not be released correctly.   Fix this.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 84eeb8f515a3..bdaa92a29e0e 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1076,9 +1076,9 @@ static void ext4_da_update_reserve_space(struct inode *inode, int used)
+ 		 * only when we have written all of the delayed
+ 		 * allocation blocks.
+ 		 */
+-		mdb_free = ei->i_allocated_meta_blocks;
++		mdb_free = ei->i_reserved_meta_blocks;
++		ei->i_reserved_meta_blocks = 0;
+ 		percpu_counter_sub(&sbi->s_dirtyblocks_counter, mdb_free);
+-		ei->i_allocated_meta_blocks = 0;
+ 	}
+ 	spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+ 
+@@ -1889,8 +1889,8 @@ static void ext4_da_release_space(struct inode *inode, int to_free)
+ 		 * only when we have written all of the delayed
+ 		 * allocation blocks.
+ 		 */
+-		to_free += ei->i_allocated_meta_blocks;
+-		ei->i_allocated_meta_blocks = 0;
++		to_free += ei->i_reserved_meta_blocks;
++		ei->i_reserved_meta_blocks = 0;
+ 	}
+ 
+ 	/* update fs dirty blocks counter */

commit 0637c6f4135f592f094207c7c21e7c0fc5557834
+Author: Theodore Ts'o 
+Date:   Wed Dec 30 14:20:45 2009 -0500
+
+    ext4: Patch up how we claim metadata blocks for quota purposes
+    
+    As reported in Kernel Bugzilla #14936, commit d21cd8f triggered a BUG
+    in the function ext4_da_update_reserve_space() found in
+    fs/ext4/inode.c.  The root cause of this BUG() was caused by the fact
+    that ext4_calc_metadata_amount() can severely over-estimate how many
+    metadata blocks will be needed, especially when using direct
+    block-mapped files.
+    
+    In addition, it can also badly *under* estimate how much space is
+    needed, since ext4_calc_metadata_amount() assumes that the blocks are
+    contiguous, and this is not always true.  If the application is
+    writing blocks to a sparse file, the number of metadata blocks
+    necessary can be severly underestimated by the functions
+    ext4_da_reserve_space(), ext4_da_update_reserve_space() and
+    ext4_da_release_space().  This was the cause of the dq_claim_space
+    reports found on kerneloops.org.
+    
+    Unfortunately, doing this right means that we need to massively
+    over-estimate the amount of free space needed.  So in some cases we
+    may need to force the inode to be written to disk asynchronously in
+    to avoid spurious quota failures.
+    
+    http://bugzilla.kernel.org/show_bug.cgi?id=14936
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 3e3b45458ef8..84eeb8f515a3 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1043,43 +1043,47 @@ static int ext4_calc_metadata_amount(struct inode *inode, int blocks)
+ 	return ext4_indirect_calc_metadata_amount(inode, blocks);
+ }
+ 
++/*
++ * Called with i_data_sem down, which is important since we can call
++ * ext4_discard_preallocations() from here.
++ */
+ static void ext4_da_update_reserve_space(struct inode *inode, int used)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+-	int total, mdb, mdb_free, mdb_claim = 0;
+-
+-	spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
+-	/* recalculate the number of metablocks still need to be reserved */
+-	total = EXT4_I(inode)->i_reserved_data_blocks - used;
+-	mdb = ext4_calc_metadata_amount(inode, total);
+-
+-	/* figure out how many metablocks to release */
+-	BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks);
+-	mdb_free = EXT4_I(inode)->i_reserved_meta_blocks - mdb;
+-
+-	if (mdb_free) {
+-		/* Account for allocated meta_blocks */
+-		mdb_claim = EXT4_I(inode)->i_allocated_meta_blocks;
+-		BUG_ON(mdb_free < mdb_claim);
+-		mdb_free -= mdb_claim;
+-
+-		/* update fs dirty blocks counter */
++	struct ext4_inode_info *ei = EXT4_I(inode);
++	int mdb_free = 0;
++
++	spin_lock(&ei->i_block_reservation_lock);
++	if (unlikely(used > ei->i_reserved_data_blocks)) {
++		ext4_msg(inode->i_sb, KERN_NOTICE, "%s: ino %lu, used %d "
++			 "with only %d reserved data blocks\n",
++			 __func__, inode->i_ino, used,
++			 ei->i_reserved_data_blocks);
++		WARN_ON(1);
++		used = ei->i_reserved_data_blocks;
++	}
++
++	/* Update per-inode reservations */
++	ei->i_reserved_data_blocks -= used;
++	used += ei->i_allocated_meta_blocks;
++	ei->i_reserved_meta_blocks -= ei->i_allocated_meta_blocks;
++	ei->i_allocated_meta_blocks = 0;
++	percpu_counter_sub(&sbi->s_dirtyblocks_counter, used);
++
++	if (ei->i_reserved_data_blocks == 0) {
++		/*
++		 * We can release all of the reserved metadata blocks
++		 * only when we have written all of the delayed
++		 * allocation blocks.
++		 */
++		mdb_free = ei->i_allocated_meta_blocks;
+ 		percpu_counter_sub(&sbi->s_dirtyblocks_counter, mdb_free);
+-		EXT4_I(inode)->i_allocated_meta_blocks = 0;
+-		EXT4_I(inode)->i_reserved_meta_blocks = mdb;
++		ei->i_allocated_meta_blocks = 0;
+ 	}
+-
+-	/* update per-inode reservations */
+-	BUG_ON(used  > EXT4_I(inode)->i_reserved_data_blocks);
+-	EXT4_I(inode)->i_reserved_data_blocks -= used;
+-	percpu_counter_sub(&sbi->s_dirtyblocks_counter, used + mdb_claim);
+ 	spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+ 
+-	vfs_dq_claim_block(inode, used + mdb_claim);
+-
+-	/*
+-	 * free those over-booking quota for metadata blocks
+-	 */
++	/* Update quota subsystem */
++	vfs_dq_claim_block(inode, used);
+ 	if (mdb_free)
+ 		vfs_dq_release_reservation_block(inode, mdb_free);
+ 
+@@ -1088,7 +1092,8 @@ static void ext4_da_update_reserve_space(struct inode *inode, int used)
+ 	 * there aren't any writers on the inode, we can discard the
+ 	 * inode's preallocations.
+ 	 */
+-	if (!total && (atomic_read(&inode->i_writecount) == 0))
++	if ((ei->i_reserved_data_blocks == 0) &&
++	    (atomic_read(&inode->i_writecount) == 0))
+ 		ext4_discard_preallocations(inode);
+ }
+ 
+@@ -1801,7 +1806,8 @@ static int ext4_da_reserve_space(struct inode *inode, int nrblocks)
+ {
+ 	int retries = 0;
+ 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+-	unsigned long md_needed, mdblocks, total = 0;
++	struct ext4_inode_info *ei = EXT4_I(inode);
++	unsigned long md_needed, md_reserved, total = 0;
+ 
+ 	/*
+ 	 * recalculate the amount of metadata blocks to reserve
+@@ -1809,35 +1815,44 @@ static int ext4_da_reserve_space(struct inode *inode, int nrblocks)
+ 	 * worse case is one extent per block
+ 	 */
+ repeat:
+-	spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
+-	total = EXT4_I(inode)->i_reserved_data_blocks + nrblocks;
+-	mdblocks = ext4_calc_metadata_amount(inode, total);
+-	BUG_ON(mdblocks < EXT4_I(inode)->i_reserved_meta_blocks);
+-
+-	md_needed = mdblocks - EXT4_I(inode)->i_reserved_meta_blocks;
++	spin_lock(&ei->i_block_reservation_lock);
++	md_reserved = ei->i_reserved_meta_blocks;
++	md_needed = ext4_calc_metadata_amount(inode, nrblocks);
+ 	total = md_needed + nrblocks;
+-	spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
++	spin_unlock(&ei->i_block_reservation_lock);
+ 
+ 	/*
+ 	 * Make quota reservation here to prevent quota overflow
+ 	 * later. Real quota accounting is done at pages writeout
+ 	 * time.
+ 	 */
+-	if (vfs_dq_reserve_block(inode, total))
++	if (vfs_dq_reserve_block(inode, total)) {
++		/* 
++		 * We tend to badly over-estimate the amount of
++		 * metadata blocks which are needed, so if we have
++		 * reserved any metadata blocks, try to force out the
++		 * inode and see if we have any better luck.
++		 */
++		if (md_reserved && retries++ <= 3)
++			goto retry;
+ 		return -EDQUOT;
++	}
+ 
+ 	if (ext4_claim_free_blocks(sbi, total)) {
+ 		vfs_dq_release_reservation_block(inode, total);
+ 		if (ext4_should_retry_alloc(inode->i_sb, &retries)) {
++		retry:
++			if (md_reserved)
++				write_inode_now(inode, (retries == 3));
+ 			yield();
+ 			goto repeat;
+ 		}
+ 		return -ENOSPC;
+ 	}
+-	spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
+-	EXT4_I(inode)->i_reserved_data_blocks += nrblocks;
+-	EXT4_I(inode)->i_reserved_meta_blocks += md_needed;
+-	spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
++	spin_lock(&ei->i_block_reservation_lock);
++	ei->i_reserved_data_blocks += nrblocks;
++	ei->i_reserved_meta_blocks += md_needed;
++	spin_unlock(&ei->i_block_reservation_lock);
+ 
+ 	return 0;       /* success */
+ }
+@@ -1845,49 +1860,45 @@ static int ext4_da_reserve_space(struct inode *inode, int nrblocks)
+ static void ext4_da_release_space(struct inode *inode, int to_free)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+-	int total, mdb, mdb_free, release;
++	struct ext4_inode_info *ei = EXT4_I(inode);
+ 
+ 	if (!to_free)
+ 		return;		/* Nothing to release, exit */
+ 
+ 	spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
+ 
+-	if (!EXT4_I(inode)->i_reserved_data_blocks) {
++	if (unlikely(to_free > ei->i_reserved_data_blocks)) {
+ 		/*
+-		 * if there is no reserved blocks, but we try to free some
+-		 * then the counter is messed up somewhere.
+-		 * but since this function is called from invalidate
+-		 * page, it's harmless to return without any action
++		 * if there aren't enough reserved blocks, then the
++		 * counter is messed up somewhere.  Since this
++		 * function is called from invalidate page, it's
++		 * harmless to return without any action.
+ 		 */
+-		printk(KERN_INFO "ext4 delalloc try to release %d reserved "
+-			    "blocks for inode %lu, but there is no reserved "
+-			    "data blocks\n", to_free, inode->i_ino);
+-		spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+-		return;
++		ext4_msg(inode->i_sb, KERN_NOTICE, "ext4_da_release_space: "
++			 "ino %lu, to_free %d with only %d reserved "
++			 "data blocks\n", inode->i_ino, to_free,
++			 ei->i_reserved_data_blocks);
++		WARN_ON(1);
++		to_free = ei->i_reserved_data_blocks;
+ 	}
++	ei->i_reserved_data_blocks -= to_free;
+ 
+-	/* recalculate the number of metablocks still need to be reserved */
+-	total = EXT4_I(inode)->i_reserved_data_blocks - to_free;
+-	mdb = ext4_calc_metadata_amount(inode, total);
+-
+-	/* figure out how many metablocks to release */
+-	BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks);
+-	mdb_free = EXT4_I(inode)->i_reserved_meta_blocks - mdb;
+-
+-	release = to_free + mdb_free;
+-
+-	/* update fs dirty blocks counter for truncate case */
+-	percpu_counter_sub(&sbi->s_dirtyblocks_counter, release);
++	if (ei->i_reserved_data_blocks == 0) {
++		/*
++		 * We can release all of the reserved metadata blocks
++		 * only when we have written all of the delayed
++		 * allocation blocks.
++		 */
++		to_free += ei->i_allocated_meta_blocks;
++		ei->i_allocated_meta_blocks = 0;
++	}
+ 
+-	/* update per-inode reservations */
+-	BUG_ON(to_free > EXT4_I(inode)->i_reserved_data_blocks);
+-	EXT4_I(inode)->i_reserved_data_blocks -= to_free;
++	/* update fs dirty blocks counter */
++	percpu_counter_sub(&sbi->s_dirtyblocks_counter, to_free);
+ 
+-	BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks);
+-	EXT4_I(inode)->i_reserved_meta_blocks = mdb;
+ 	spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+ 
+-	vfs_dq_release_reservation_block(inode, release);
++	vfs_dq_release_reservation_block(inode, to_free);
+ }
+ 
+ static void ext4_da_page_release_reservation(struct page *page,

commit cc3e1bea5d87635c519da657303690f5538bb4eb
+Author: Theodore Ts'o 
+Date:   Wed Dec 23 06:52:08 2009 -0500
+
+    ext4, jbd2: Add barriers for file systems with exernal journals
+    
+    This is a bit complicated because we are trying to optimize when we
+    send barriers to the fs data disk.  We could just throw in an extra
+    barrier to the data disk whenever we send a barrier to the journal
+    disk, but that's not always strictly necessary.
+    
+    We only need to send a barrier during a commit when there are data
+    blocks which are must be written out due to an inode written in
+    ordered mode, or if fsync() depends on the commit to force data blocks
+    to disk.  Finally, before we drop transactions from the beginning of
+    the journal during a checkpoint operation, we need to guarantee that
+    any blocks that were flushed out to the data disk are firmly on the
+    rust platter before we drop the transaction from the journal.
+    
+    Thanks to Oleg Drokin for pointing out this flaw in ext3/ext4.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
+index 0b22497d92e1..98bd140aad01 100644
+--- a/fs/ext4/fsync.c
++++ b/fs/ext4/fsync.c
+@@ -88,9 +88,21 @@ int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync)
+ 		return ext4_force_commit(inode->i_sb);
+ 
+ 	commit_tid = datasync ? ei->i_datasync_tid : ei->i_sync_tid;
+-	if (jbd2_log_start_commit(journal, commit_tid))
++	if (jbd2_log_start_commit(journal, commit_tid)) {
++		/*
++		 * When the journal is on a different device than the
++		 * fs data disk, we need to issue the barrier in
++		 * writeback mode.  (In ordered mode, the jbd2 layer
++		 * will take care of issuing the barrier.  In
++		 * data=journal, all of the data blocks are written to
++		 * the journal device.)
++		 */
++		if (ext4_should_writeback_data(inode) &&
++		    (journal->j_fs_dev != journal->j_dev) &&
++		    (journal->j_flags & JBD2_BARRIER))
++			blkdev_issue_flush(inode->i_sb->s_bdev, NULL);
+ 		jbd2_log_wait_commit(journal, commit_tid);
+-	else if (journal->j_flags & JBD2_BARRIER)
++	} else if (journal->j_flags & JBD2_BARRIER)
+ 		blkdev_issue_flush(inode->i_sb->s_bdev, NULL);
+ 	return ret;
+ }
+diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
+index ca0f5eb62b20..886849370950 100644
+--- a/fs/jbd2/checkpoint.c
++++ b/fs/jbd2/checkpoint.c
+@@ -22,6 +22,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ 
+ /*
+@@ -515,6 +516,20 @@ int jbd2_cleanup_journal_tail(journal_t *journal)
+ 	journal->j_tail_sequence = first_tid;
+ 	journal->j_tail = blocknr;
+ 	spin_unlock(&journal->j_state_lock);
++
++	/*
++	 * If there is an external journal, we need to make sure that
++	 * any data blocks that were recently written out --- perhaps
++	 * by jbd2_log_do_checkpoint() --- are flushed out before we
++	 * drop the transactions from the external journal.  It's
++	 * unlikely this will be necessary, especially with a
++	 * appropriately sized journal, but we need this to guarantee
++	 * correctness.  Fortunately jbd2_cleanup_journal_tail()
++	 * doesn't get called all that often.
++	 */
++	if ((journal->j_fs_dev != journal->j_dev) &&
++	    (journal->j_flags & JBD2_BARRIER))
++		blkdev_issue_flush(journal->j_fs_dev, NULL);
+ 	if (!(journal->j_flags & JBD2_ABORT))
+ 		jbd2_journal_update_superblock(journal, 1);
+ 	return 0;
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index 6a10238d2c63..1bc74b6f26d2 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -259,6 +259,7 @@ static int journal_submit_data_buffers(journal_t *journal,
+ 			ret = err;
+ 		spin_lock(&journal->j_list_lock);
+ 		J_ASSERT(jinode->i_transaction == commit_transaction);
++		commit_transaction->t_flushed_data_blocks = 1;
+ 		jinode->i_flags &= ~JI_COMMIT_RUNNING;
+ 		wake_up_bit(&jinode->i_flags, __JI_COMMIT_RUNNING);
+ 	}
+@@ -708,8 +709,17 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 		}
+ 	}
+ 
+-	/* Done it all: now write the commit record asynchronously. */
++	/* 
++	 * If the journal is not located on the file system device,
++	 * then we must flush the file system device before we issue
++	 * the commit record
++	 */
++	if (commit_transaction->t_flushed_data_blocks &&
++	    (journal->j_fs_dev != journal->j_dev) &&
++	    (journal->j_flags & JBD2_BARRIER))
++		blkdev_issue_flush(journal->j_fs_dev, NULL);
+ 
++	/* Done it all: now write the commit record asynchronously. */
+ 	if (JBD2_HAS_INCOMPAT_FEATURE(journal,
+ 				      JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) {
+ 		err = journal_submit_commit_record(journal, commit_transaction,
+@@ -720,13 +730,6 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 			blkdev_issue_flush(journal->j_dev, NULL);
+ 	}
+ 
+-	/*
+-	 * This is the right place to wait for data buffers both for ASYNC
+-	 * and !ASYNC commit. If commit is ASYNC, we need to wait only after
+-	 * the commit block went to disk (which happens above). If commit is
+-	 * SYNC, we need to wait for data buffers before we start writing
+-	 * commit block, which happens below in such setting.
+-	 */
+ 	err = journal_finish_inode_data_buffers(journal, commit_transaction);
+ 	if (err) {
+ 		printk(KERN_WARNING
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index f1011f7f3d41..638ce4554c76 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -653,6 +653,7 @@ struct transaction_s
+ 	 * waiting for it to finish.
+ 	 */
+ 	unsigned int t_synchronous_commit:1;
++	unsigned int t_flushed_data_blocks:1;
+ 
+ 	/*
+ 	 * For use by the filesystem to store fs-specific data

commit 7bf0dc9b0ca9e9b6524b1f70e0898c7f11eb10be
+Author: Theodore Ts'o 
+Date:   Tue Dec 15 16:46:48 2009 -0800
+
+    ext2: avoid WARN() messages when failing to write to the superblock
+    
+    This fixes a common warning reported by kerneloops.org
+    
+    [Kernel summit hacking hour]
+    [akpm@linux-foundation.org: coding-style fixes]
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/ext2/super.c b/fs/ext2/super.c
+index 1388802b7803..f9cb54a585ce 100644
+--- a/fs/ext2/super.c
++++ b/fs/ext2/super.c
+@@ -1105,9 +1105,30 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
+ 	return ret;
+ }
+ 
++static void ext2_clear_super_error(struct super_block *sb)
++{
++	struct buffer_head *sbh = EXT2_SB(sb)->s_sbh;
++
++	if (buffer_write_io_error(sbh)) {
++		/*
++		 * Oh, dear.  A previous attempt to write the
++		 * superblock failed.  This could happen because the
++		 * USB device was yanked out.  Or it could happen to
++		 * be a transient write error and maybe the block will
++		 * be remapped.  Nothing we can do but to retry the
++		 * write and hope for the best.
++		 */
++		printk(KERN_ERR "EXT2-fs: %s previous I/O error to "
++		       "superblock detected", sb->s_id);
++		clear_buffer_write_io_error(sbh);
++		set_buffer_uptodate(sbh);
++	}
++}
++
+ static void ext2_commit_super (struct super_block * sb,
+ 			       struct ext2_super_block * es)
+ {
++	ext2_clear_super_error(sb);
+ 	es->s_wtime = cpu_to_le32(get_seconds());
+ 	mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
+ 	sb->s_dirt = 0;
+@@ -1115,6 +1136,7 @@ static void ext2_commit_super (struct super_block * sb,
+ 
+ static void ext2_sync_super(struct super_block *sb, struct ext2_super_block *es)
+ {
++	ext2_clear_super_error(sb);
+ 	es->s_free_blocks_count = cpu_to_le32(ext2_count_free_blocks(sb));
+ 	es->s_free_inodes_count = cpu_to_le32(ext2_count_free_inodes(sb));
+ 	es->s_wtime = cpu_to_le32(get_seconds());

commit 51b7e3c9fbe7d22d4e355101e9a73b44fc5c9feb
+Author: Theodore Ts'o 
+Date:   Mon Dec 21 10:56:09 2009 -0500
+
+    ext4: add module aliases for ext2 and ext3
+    
+    Add module aliases for ext2 and ext3 when CONFIG_EXT4_USE_FOR_EXT23 is
+    set.  This makes the existing user-space stuff like mkinitrd working
+    as is.
+    
+    Signed-off-by: Takashi Iwai 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 6ed9aa91f27d..0a06fe6f2bc2 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4005,6 +4005,7 @@ static inline void unregister_as_ext2(void)
+ {
+ 	unregister_filesystem(&ext2_fs_type);
+ }
++MODULE_ALIAS("ext2");
+ #else
+ static inline void register_as_ext2(void) { }
+ static inline void unregister_as_ext2(void) { }
+@@ -4031,6 +4032,7 @@ static inline void unregister_as_ext3(void)
+ {
+ 	unregister_filesystem(&ext3_fs_type);
+ }
++MODULE_ALIAS("ext3");
+ #else
+ static inline void register_as_ext3(void) { }
+ static inline void unregister_as_ext3(void) { }

commit fab3a549e204172236779f502eccb4f9bf0dc87d
+Author: Theodore Ts'o 
+Date:   Wed Dec 9 21:30:02 2009 -0500
+
+    ext4: Fix potential fiemap deadlock (mmap_sem vs. i_data_sem)
+    
+    Fix the following potential circular locking dependency between
+    mm->mmap_sem and ei->i_data_sem:
+    
+        =======================================================
+        [ INFO: possible circular locking dependency detected ]
+        2.6.32-04115-gec044c5 #37
+        -------------------------------------------------------
+        ureadahead/1855 is trying to acquire lock:
+         (&mm->mmap_sem){++++++}, at: [] might_fault+0x5c/0xac
+    
+        but task is already holding lock:
+         (&ei->i_data_sem){++++..}, at: [] ext4_fiemap+0x11b/0x159
+    
+        which lock already depends on the new lock.
+    
+        the existing dependency chain (in reverse order) is:
+    
+        -> #1 (&ei->i_data_sem){++++..}:
+               [] __lock_acquire+0xb67/0xd0f
+               [] lock_acquire+0xdc/0x102
+               [] down_read+0x51/0x84
+               [] ext4_get_blocks+0x50/0x2a5
+               [] ext4_get_block+0xab/0xef
+               [] do_mpage_readpage+0x198/0x48d
+               [] mpage_readpages+0xd0/0x114
+               [] ext4_readpages+0x1d/0x1f
+               [] __do_page_cache_readahead+0x12f/0x1bc
+               [] ra_submit+0x21/0x25
+               [] filemap_fault+0x19f/0x32c
+               [] __do_fault+0x55/0x3a2
+               [] handle_mm_fault+0x327/0x734
+               [] do_page_fault+0x292/0x2aa
+               [] page_fault+0x25/0x30
+               [] clear_user+0x38/0x3c
+               [] padzero+0x20/0x31
+               [] load_elf_binary+0x8bc/0x17ed
+               [] search_binary_handler+0xc2/0x259
+               [] load_script+0x1b8/0x1cc
+               [] search_binary_handler+0xc2/0x259
+               [] do_execve+0x1ce/0x2cf
+               [] sys_execve+0x43/0x5a
+               [] stub_execve+0x6a/0xc0
+    
+        -> #0 (&mm->mmap_sem){++++++}:
+               [] __lock_acquire+0xa11/0xd0f
+               [] lock_acquire+0xdc/0x102
+               [] might_fault+0x89/0xac
+               [] fiemap_fill_next_extent+0x95/0xda
+               [] ext4_ext_fiemap_cb+0x138/0x157
+               [] ext4_ext_walk_space+0x178/0x1f1
+               [] ext4_fiemap+0x13c/0x159
+               [] do_vfs_ioctl+0x348/0x4d6
+               [] sys_ioctl+0x56/0x79
+               [] system_call_fastpath+0x16/0x1b
+    
+        other info that might help us debug this:
+    
+        1 lock held by ureadahead/1855:
+         #0:  (&ei->i_data_sem){++++..}, at: [] ext4_fiemap+0x11b/0x159
+    
+        stack backtrace:
+        Pid: 1855, comm: ureadahead Not tainted 2.6.32-04115-gec044c5 #37
+        Call Trace:
+         [] print_circular_bug+0xa8/0xb7
+         [] __lock_acquire+0xa11/0xd0f
+         [] ? sched_clock+0x9/0xd
+         [] lock_acquire+0xdc/0x102
+         [] ? might_fault+0x5c/0xac
+         [] might_fault+0x89/0xac
+         [] ? might_fault+0x5c/0xac
+         [] ? __kmalloc+0x13b/0x18c
+         [] fiemap_fill_next_extent+0x95/0xda
+         [] ext4_ext_fiemap_cb+0x138/0x157
+         [] ? ext4_ext_fiemap_cb+0x0/0x157
+         [] ext4_ext_walk_space+0x178/0x1f1
+         [] ext4_fiemap+0x13c/0x159
+         [] ? might_fault+0x5c/0xac
+         [] do_vfs_ioctl+0x348/0x4d6
+         [] ? __up_read+0x8d/0x95
+         [] ? retint_swapgs+0x13/0x1b
+         [] sys_ioctl+0x56/0x79
+         [] system_call_fastpath+0x16/0x1b
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 700206e525da..3a7928f825e4 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -1762,7 +1762,9 @@ int ext4_ext_walk_space(struct inode *inode, ext4_lblk_t block,
+ 	while (block < last && block != EXT_MAX_BLOCK) {
+ 		num = last - block;
+ 		/* find extent for this block */
++		down_read(&EXT4_I(inode)->i_data_sem);
+ 		path = ext4_ext_find_extent(inode, block, path);
++		up_read(&EXT4_I(inode)->i_data_sem);
+ 		if (IS_ERR(path)) {
+ 			err = PTR_ERR(path);
+ 			path = NULL;
+@@ -3724,10 +3726,8 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ 		 * Walk the extent tree gathering extent information.
+ 		 * ext4_ext_fiemap_cb will push extents back to user.
+ 		 */
+-		down_read(&EXT4_I(inode)->i_data_sem);
+ 		error = ext4_ext_walk_space(inode, start_blk, len_blks,
+ 					  ext4_ext_fiemap_cb, fieinfo);
+-		up_read(&EXT4_I(inode)->i_data_sem);
+ 	}
+ 
+ 	return error;

commit a214238d3bb03723f820b0a398928d8e1637c987
+Author: Theodore Ts'o 
+Date:   Wed Dec 9 21:09:58 2009 -0500
+
+    ext4: Do not override ext2 or ext3 if built they are built as modules
+    
+    The CONFIG_EXT4_USE_FOR_EXT23 option must not try to take over the
+    ext2 or ext3 file systems if the those file system drivers are
+    configured to be built as mdoules.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
+index a6b4e93833d6..9acf7e808139 100644
+--- a/fs/ext4/Kconfig
++++ b/fs/ext4/Kconfig
+@@ -28,7 +28,7 @@ config EXT4_FS
+ 
+ config EXT4_USE_FOR_EXT23
+ 	bool "Use ext4 for ext2/ext3 file systems"
+-	depends on !EXT3_FS || !EXT2_FS
++	depends on EXT3_FS=n || EXT2_FS=n
+ 	default y
+ 	help
+ 	  Allow the ext4 file system driver code to be used for ext2 or
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 2b13dcfcf775..8b58a144c31b 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3964,7 +3964,7 @@ static int ext4_get_sb(struct file_system_type *fs_type, int flags,
+ 	return get_sb_bdev(fs_type, flags, dev_name, data, ext4_fill_super,mnt);
+ }
+ 
+-#if !defined(CONTIG_EXT2_FS) && defined(CONFIG_EXT4_USE_FOR_EXT23)
++#if !defined(CONTIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23)
+ static struct file_system_type ext2_fs_type = {
+ 	.owner		= THIS_MODULE,
+ 	.name		= "ext2",
+@@ -3990,7 +3990,7 @@ static inline void register_as_ext2(void) { }
+ static inline void unregister_as_ext2(void) { }
+ #endif
+ 
+-#if !defined(CONTIG_EXT3_FS) && defined(CONFIG_EXT4_USE_FOR_EXT23)
++#if !defined(CONTIG_EXT3_FS) && !defined(CONFIG_EXT3_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23)
+ static struct file_system_type ext3_fs_type = {
+ 	.owner		= THIS_MODULE,
+ 	.name		= "ext3",

commit 3b799d15f2622c44bae93961892d90ab012ea2be
+Author: Theodore Ts'o 
+Date:   Wed Dec 9 20:42:53 2009 -0500
+
+    jbd2: Export jbd2_log_start_commit to fix ext4 build
+    
+        This fixes:
+        ERROR: "jbd2_log_start_commit" [fs/ext4/ext4.ko] undefined!
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 3f473faa4660..b7ca3a92a4db 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -78,6 +78,7 @@ EXPORT_SYMBOL(jbd2_journal_errno);
+ EXPORT_SYMBOL(jbd2_journal_ack_err);
+ EXPORT_SYMBOL(jbd2_journal_clear_err);
+ EXPORT_SYMBOL(jbd2_log_wait_commit);
++EXPORT_SYMBOL(jbd2_log_start_commit);
+ EXPORT_SYMBOL(jbd2_journal_start_commit);
+ EXPORT_SYMBOL(jbd2_journal_force_commit_nested);
+ EXPORT_SYMBOL(jbd2_journal_wipe);

commit 7e8b60faea972604c315634cff62d44803731ea9
+Author: Andrew Lutomirski 
+Date:   Sun Nov 8 13:49:51 2009 -0500
+
+    drm/i915: restore render clock gating on resume
+    
+    Rather than restoring just a few clock gating registers on resume,
+    just reinitialize the whole thing.
+    
+    Signed-off-by: Andy Lutomirski 
+    [anholt: Fixed up for RC6 support landed since the patch was written]
+    Signed-off-by: Eric Anholt 
+
+diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
+index e28d6c9a0ae9..1d6171087298 100644
+--- a/drivers/gpu/drm/i915/i915_drv.h
++++ b/drivers/gpu/drm/i915/i915_drv.h
+@@ -381,8 +381,6 @@ typedef struct drm_i915_private {
+ 	u32 saveFDI_RXA_IMR;
+ 	u32 saveFDI_RXB_IMR;
+ 	u32 saveCACHE_MODE_0;
+-	u32 saveD_STATE;
+-	u32 saveDSPCLK_GATE_D;
+ 	u32 saveMI_ARB_STATE;
+ 	u32 saveSWF0[16];
+ 	u32 saveSWF1[16];
+diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
+index 402a7eb2922c..00f6d97c7cc5 100644
+--- a/drivers/gpu/drm/i915/i915_suspend.c
++++ b/drivers/gpu/drm/i915/i915_suspend.c
+@@ -722,10 +722,6 @@ int i915_save_state(struct drm_device *dev)
+ 		dev_priv->saveIMR = I915_READ(IMR);
+ 	}
+ 
+-	/* Clock gating state */
+-	dev_priv->saveD_STATE = I915_READ(D_STATE);
+-	dev_priv->saveDSPCLK_GATE_D = I915_READ(DSPCLK_GATE_D); /* Not sure about this */
+-
+ 	/* Cache mode state */
+ 	dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
+ 
+@@ -800,8 +796,7 @@ int i915_restore_state(struct drm_device *dev)
+ 	}
+ 
+ 	/* Clock gating state */
+-	I915_WRITE (D_STATE, dev_priv->saveD_STATE);
+-	I915_WRITE (DSPCLK_GATE_D, dev_priv->saveDSPCLK_GATE_D);
++	intel_init_clock_gating(dev);
+ 
+ 	/* Cache mode state */
+ 	I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
+diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
+index 902cc5386f19..279dc96e3eb2 100644
+--- a/drivers/gpu/drm/i915/intel_display.c
++++ b/drivers/gpu/drm/i915/intel_display.c
+@@ -4584,28 +4584,33 @@ void intel_init_clock_gating(struct drm_device *dev)
+ 		struct drm_i915_gem_object *obj_priv;
+ 		int ret;
+ 
+-		pwrctx = drm_gem_object_alloc(dev, 4096);
+-		if (!pwrctx) {
+-			DRM_DEBUG("failed to alloc power context, RC6 disabled\n");
+-			goto out;
+-		}
++		if (dev_priv->pwrctx) {
++			obj_priv = dev_priv->pwrctx->driver_private;
++		} else {
++			pwrctx = drm_gem_object_alloc(dev, 4096);
++			if (!pwrctx) {
++				DRM_DEBUG("failed to alloc power context, "
++					  "RC6 disabled\n");
++				goto out;
++			}
+ 
+-		ret = i915_gem_object_pin(pwrctx, 4096);
+-		if (ret) {
+-			DRM_ERROR("failed to pin power context: %d\n", ret);
+-			drm_gem_object_unreference(pwrctx);
+-			goto out;
+-		}
++			ret = i915_gem_object_pin(pwrctx, 4096);
++			if (ret) {
++				DRM_ERROR("failed to pin power context: %d\n",
++					  ret);
++				drm_gem_object_unreference(pwrctx);
++				goto out;
++			}
+ 
+-		i915_gem_object_set_to_gtt_domain(pwrctx, 1);
++			i915_gem_object_set_to_gtt_domain(pwrctx, 1);
+ 
+-		obj_priv = pwrctx->driver_private;
++			dev_priv->pwrctx = pwrctx;
++			obj_priv = pwrctx->driver_private;
++		}
+ 
+ 		I915_WRITE(PWRCTXA, obj_priv->gtt_offset | PWRCTX_EN);
+ 		I915_WRITE(MCHBAR_RENDER_STANDBY,
+ 			   I915_READ(MCHBAR_RENDER_STANDBY) & ~RCX_SW_EXIT);
+-
+-		dev_priv->pwrctx = pwrctx;
+ 	}
+ 
+ out:
+diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
+index 9ffa31e13eb3..a51573da1ff6 100644
+--- a/drivers/gpu/drm/i915/intel_drv.h
++++ b/drivers/gpu/drm/i915/intel_drv.h
+@@ -208,6 +208,7 @@ extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
+ 				    u16 blue, int regno);
+ extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
+ 				    u16 *blue, int regno);
++extern void intel_init_clock_gating(struct drm_device *dev);
+ 
+ extern int intel_framebuffer_create(struct drm_device *dev,
+ 				    struct drm_mode_fb_cmd *mode_cmd,

commit d2eecb03936878ec574ade5532fa83df7d75dde7
+Author: Theodore Ts'o 
+Date:   Mon Dec 7 10:36:20 2009 -0500
+
+    ext4: Use slab allocator for sub-page sized allocations
+    
+    Now that the SLUB seems to be fixed so that it respects the requested
+    alignment, use kmem_cache_alloc() to allocator if the block size of
+    the buffer heads to be allocated is less than the page size.
+    Previously, we were using 16k page on a Power system for each buffer,
+    even when the file system was using 1k or 4k block size.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index ac0d027595d0..c03d4dce4d76 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -39,6 +39,8 @@
+ #include 
+ #include 
+ #include 
++#include 
++#include 
+ 
+ #define CREATE_TRACE_POINTS
+ #include 
+@@ -93,6 +95,7 @@ EXPORT_SYMBOL(jbd2_journal_begin_ordered_truncate);
+ 
+ static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *);
+ static void __journal_abort_soft (journal_t *journal, int errno);
++static int jbd2_journal_create_slab(size_t slab_size);
+ 
+ /*
+  * Helper function used to manage commit timeouts
+@@ -1248,6 +1251,13 @@ int jbd2_journal_load(journal_t *journal)
+ 		}
+ 	}
+ 
++	/*
++	 * Create a slab for this blocksize
++	 */
++	err = jbd2_journal_create_slab(be32_to_cpu(sb->s_blocksize));
++	if (err)
++		return err;
++
+ 	/* Let the recovery code check whether it needs to recover any
+ 	 * data from the journal. */
+ 	if (jbd2_journal_recover(journal))
+@@ -1806,6 +1816,127 @@ size_t journal_tag_bytes(journal_t *journal)
+ 		return JBD2_TAG_SIZE32;
+ }
+ 
++/*
++ * JBD memory management
++ *
++ * These functions are used to allocate block-sized chunks of memory
++ * used for making copies of buffer_head data.  Very often it will be
++ * page-sized chunks of data, but sometimes it will be in
++ * sub-page-size chunks.  (For example, 16k pages on Power systems
++ * with a 4k block file system.)  For blocks smaller than a page, we
++ * use a SLAB allocator.  There are slab caches for each block size,
++ * which are allocated at mount time, if necessary, and we only free
++ * (all of) the slab caches when/if the jbd2 module is unloaded.  For
++ * this reason we don't need to a mutex to protect access to
++ * jbd2_slab[] allocating or releasing memory; only in
++ * jbd2_journal_create_slab().
++ */
++#define JBD2_MAX_SLABS 8
++static struct kmem_cache *jbd2_slab[JBD2_MAX_SLABS];
++static DECLARE_MUTEX(jbd2_slab_create_sem);
++
++static const char *jbd2_slab_names[JBD2_MAX_SLABS] = {
++	"jbd2_1k", "jbd2_2k", "jbd2_4k", "jbd2_8k",
++	"jbd2_16k", "jbd2_32k", "jbd2_64k", "jbd2_128k"
++};
++
++
++static void jbd2_journal_destroy_slabs(void)
++{
++	int i;
++
++	for (i = 0; i < JBD2_MAX_SLABS; i++) {
++		if (jbd2_slab[i])
++			kmem_cache_destroy(jbd2_slab[i]);
++		jbd2_slab[i] = NULL;
++	}
++}
++
++static int jbd2_journal_create_slab(size_t size)
++{
++	int i = order_base_2(size) - 10;
++	size_t slab_size;
++
++	if (size == PAGE_SIZE)
++		return 0;
++
++	if (i >= JBD2_MAX_SLABS)
++		return -EINVAL;
++
++	if (unlikely(i < 0))
++		i = 0;
++	down(&jbd2_slab_create_sem);
++	if (jbd2_slab[i]) {
++		up(&jbd2_slab_create_sem);
++		return 0;	/* Already created */
++	}
++
++	slab_size = 1 << (i+10);
++	jbd2_slab[i] = kmem_cache_create(jbd2_slab_names[i], slab_size,
++					 slab_size, 0, NULL);
++	up(&jbd2_slab_create_sem);
++	if (!jbd2_slab[i]) {
++		printk(KERN_EMERG "JBD2: no memory for jbd2_slab cache\n");
++		return -ENOMEM;
++	}
++	return 0;
++}
++
++static struct kmem_cache *get_slab(size_t size)
++{
++	int i = order_base_2(size) - 10;
++
++	BUG_ON(i >= JBD2_MAX_SLABS);
++	if (unlikely(i < 0))
++		i = 0;
++	BUG_ON(jbd2_slab[i] == 0);
++	return jbd2_slab[i];
++}
++
++void *jbd2_alloc(size_t size, gfp_t flags)
++{
++	void *ptr;
++
++	BUG_ON(size & (size-1)); /* Must be a power of 2 */
++
++	flags |= __GFP_REPEAT;
++	if (size == PAGE_SIZE)
++		ptr = (void *)__get_free_pages(flags, 0);
++	else if (size > PAGE_SIZE) {
++		int order = get_order(size);
++
++		if (order < 3)
++			ptr = (void *)__get_free_pages(flags, order);
++		else
++			ptr = vmalloc(size);
++	} else
++		ptr = kmem_cache_alloc(get_slab(size), flags);
++
++	/* Check alignment; SLUB has gotten this wrong in the past,
++	 * and this can lead to user data corruption! */
++	BUG_ON(((unsigned long) ptr) & (size-1));
++
++	return ptr;
++}
++
++void jbd2_free(void *ptr, size_t size)
++{
++	if (size == PAGE_SIZE) {
++		free_pages((unsigned long)ptr, 0);
++		return;
++	}
++	if (size > PAGE_SIZE) {
++		int order = get_order(size);
++
++		if (order < 3)
++			free_pages((unsigned long)ptr, order);
++		else
++			vfree(ptr);
++		return;
++	}
++	kmem_cache_free(get_slab(size), ptr);
++};
++
+ /*
+  * Journal_head storage management
+  */
+@@ -2204,6 +2335,7 @@ static void jbd2_journal_destroy_caches(void)
+ 	jbd2_journal_destroy_revoke_caches();
+ 	jbd2_journal_destroy_jbd2_journal_head_cache();
+ 	jbd2_journal_destroy_handle_cache();
++	jbd2_journal_destroy_slabs();
+ }
+ 
+ static int __init journal_init(void)
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index 638ce4554c76..8ada2a129d08 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -69,15 +69,8 @@ extern u8 jbd2_journal_enable_debug;
+ #define jbd_debug(f, a...)	/**/
+ #endif
+ 
+-static inline void *jbd2_alloc(size_t size, gfp_t flags)
+-{
+-	return (void *)__get_free_pages(flags, get_order(size));
+-}
+-
+-static inline void jbd2_free(void *ptr, size_t size)
+-{
+-	free_pages((unsigned long)ptr, get_order(size));
+-};
++extern void *jbd2_alloc(size_t size, gfp_t flags);
++extern void jbd2_free(void *ptr, size_t size);
+ 
+ #define JBD2_MIN_JOURNAL_BLOCKS 1024
+ 

commit f8ec9d6837241865cf99bed97bb99f4399fd5a03
+Author: Theodore Ts'o 
+Date:   Fri Jan 1 01:00:21 2010 -0500
+
+    ext4: Add new tracepoints to debug delayed allocation space functions
+    
+    Add tracepoints for ext4_da_reserve_space(),
+    ext4_da_update_reserve_space(), and ext4_da_release_space().
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 3e8afd969236..1a3d7b232cd7 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1061,6 +1061,7 @@ void ext4_da_update_reserve_space(struct inode *inode,
+ 	int mdb_free = 0, allocated_meta_blocks = 0;
+ 
+ 	spin_lock(&ei->i_block_reservation_lock);
++	trace_ext4_da_update_reserve_space(inode, used);
+ 	if (unlikely(used > ei->i_reserved_data_blocks)) {
+ 		ext4_msg(inode->i_sb, KERN_NOTICE, "%s: ino %lu, used %d "
+ 			 "with only %d reserved data blocks\n",
+@@ -1846,6 +1847,7 @@ static int ext4_da_reserve_space(struct inode *inode, sector_t lblock)
+ 	spin_lock(&ei->i_block_reservation_lock);
+ 	md_reserved = ei->i_reserved_meta_blocks;
+ 	md_needed = ext4_calc_metadata_amount(inode, lblock);
++	trace_ext4_da_reserve_space(inode, md_needed);
+ 	spin_unlock(&ei->i_block_reservation_lock);
+ 
+ 	/*
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index d0b6cd3afb2f..2aa6aa3e8f61 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -874,6 +874,107 @@ TRACE_EVENT(ext4_forget,
+ 		  __entry->mode, __entry->is_metadata, __entry->block)
+ );
+ 
++TRACE_EVENT(ext4_da_update_reserve_space,
++	TP_PROTO(struct inode *inode, int used_blocks),
++
++	TP_ARGS(inode, used_blocks),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	umode_t, mode			)
++		__field(	__u64,	i_blocks		)
++		__field(	int,	used_blocks		)
++		__field(	int,	reserved_data_blocks	)
++		__field(	int,	reserved_meta_blocks	)
++		__field(	int,	allocated_meta_blocks	)
++	),
++
++	TP_fast_assign(
++		__entry->dev	= inode->i_sb->s_dev;
++		__entry->ino	= inode->i_ino;
++		__entry->mode	= inode->i_mode;
++		__entry->i_blocks = inode->i_blocks;
++		__entry->used_blocks = used_blocks;
++		__entry->reserved_data_blocks = EXT4_I(inode)->i_reserved_data_blocks;
++		__entry->reserved_meta_blocks = EXT4_I(inode)->i_reserved_meta_blocks;
++		__entry->allocated_meta_blocks = EXT4_I(inode)->i_allocated_meta_blocks;
++	),
++
++	TP_printk("dev %s ino %lu mode 0%o i_blocks %llu used_blocks %d reserved_data_blocks %d reserved_meta_blocks %d allocated_meta_blocks %d",
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++		  __entry->mode,  (unsigned long long) __entry->i_blocks,
++		  __entry->used_blocks, __entry->reserved_data_blocks,
++		  __entry->reserved_meta_blocks, __entry->allocated_meta_blocks)
++);
++
++TRACE_EVENT(ext4_da_reserve_space,
++	TP_PROTO(struct inode *inode, int md_needed),
++
++	TP_ARGS(inode, md_needed),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	umode_t, mode			)
++		__field(	__u64,	i_blocks		)
++		__field(	int,	md_needed		)
++		__field(	int,	reserved_data_blocks	)
++		__field(	int,	reserved_meta_blocks	)
++	),
++
++	TP_fast_assign(
++		__entry->dev	= inode->i_sb->s_dev;
++		__entry->ino	= inode->i_ino;
++		__entry->mode	= inode->i_mode;
++		__entry->i_blocks = inode->i_blocks;
++		__entry->md_needed = md_needed;
++		__entry->reserved_data_blocks = EXT4_I(inode)->i_reserved_data_blocks;
++		__entry->reserved_meta_blocks = EXT4_I(inode)->i_reserved_meta_blocks;
++	),
++
++	TP_printk("dev %s ino %lu mode 0%o i_blocks %llu md_needed %d reserved_data_blocks %d reserved_meta_blocks %d",
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++		  __entry->mode, (unsigned long long) __entry->i_blocks,
++		  __entry->md_needed, __entry->reserved_data_blocks,
++		  __entry->reserved_meta_blocks)
++);
++
++TRACE_EVENT(ext4_da_release_space,
++	TP_PROTO(struct inode *inode, int freed_blocks),
++
++	TP_ARGS(inode, freed_blocks),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	umode_t, mode			)
++		__field(	__u64,	i_blocks		)
++		__field(	int,	freed_blocks		)
++		__field(	int,	reserved_data_blocks	)
++		__field(	int,	reserved_meta_blocks	)
++		__field(	int,	allocated_meta_blocks	)
++	),
++
++	TP_fast_assign(
++		__entry->dev	= inode->i_sb->s_dev;
++		__entry->ino	= inode->i_ino;
++		__entry->mode	= inode->i_mode;
++		__entry->i_blocks = inode->i_blocks;
++		__entry->freed_blocks = freed_blocks;
++		__entry->reserved_data_blocks = EXT4_I(inode)->i_reserved_data_blocks;
++		__entry->reserved_meta_blocks = EXT4_I(inode)->i_reserved_meta_blocks;
++		__entry->allocated_meta_blocks = EXT4_I(inode)->i_allocated_meta_blocks;
++	),
++
++	TP_printk("dev %s ino %lu mode 0%o i_blocks %llu freed_blocks %d reserved_data_blocks %d reserved_meta_blocks %d allocated_meta_blocks %d",
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++		  __entry->mode, (unsigned long long) __entry->i_blocks,
++		  __entry->freed_blocks, __entry->reserved_data_blocks,
++		  __entry->reserved_meta_blocks, __entry->allocated_meta_blocks)
++);
++
++
+ #endif /* _TRACE_EXT4_H */
+ 
+ /* This part must be outside protection */

commit 71f2be213a0009098819e5c04f75ff19f84f2122
+Author: Theodore Ts'o 
+Date:   Wed Dec 23 07:45:44 2009 -0500
+
+    ext4: Add new tracepoint for jbd2_cleanup_journal_tail
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
+index 886849370950..30beb11ef928 100644
+--- a/fs/jbd2/checkpoint.c
++++ b/fs/jbd2/checkpoint.c
+@@ -507,6 +507,7 @@ int jbd2_cleanup_journal_tail(journal_t *journal)
+ 	if (blocknr < journal->j_tail)
+ 		freed = freed + journal->j_last - journal->j_first;
+ 
++	trace_jbd2_cleanup_journal_tail(journal, first_tid, blocknr, freed);
+ 	jbd_debug(1,
+ 		  "Cleaning journal tail from %d to %d (offset %lu), "
+ 		  "freeing %lu\n",
+diff --git a/include/trace/events/jbd2.h b/include/trace/events/jbd2.h
+index 96b370a050de..bf16545cc977 100644
+--- a/include/trace/events/jbd2.h
++++ b/include/trace/events/jbd2.h
+@@ -199,6 +199,34 @@ TRACE_EVENT(jbd2_checkpoint_stats,
+ 		  __entry->forced_to_close, __entry->written, __entry->dropped)
+ );
+ 
++TRACE_EVENT(jbd2_cleanup_journal_tail,
++
++	TP_PROTO(journal_t *journal, tid_t first_tid,
++		 unsigned long block_nr, unsigned long freed),
++
++	TP_ARGS(journal, first_tid, block_nr, freed),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	tid_t,	tail_sequence		)
++		__field(	tid_t,	first_tid		)
++		__field(unsigned long,	block_nr		)
++		__field(unsigned long,	freed			)
++	),
++
++	TP_fast_assign(
++		__entry->dev		= journal->j_fs_dev->bd_dev;
++		__entry->tail_sequence	= journal->j_tail_sequence;
++		__entry->first_tid	= first_tid;
++		__entry->block_nr	= block_nr;
++		__entry->freed		= freed;
++	),
++
++	TP_printk("dev %s from %u to %u offset %lu freed %lu",
++		  jbd2_dev_to_name(__entry->dev), __entry->tail_sequence,
++		  __entry->first_tid, __entry->block_nr, __entry->freed)
++);
++
+ #endif /* _TRACE_JBD2_H */
+ 
+ /* This part must be outside protection */

commit 1f2acb6017d8528135ec3b01ab7cd2be6ea0630b
+Author: Theodore Ts'o 
+Date:   Fri Jan 22 17:40:42 2010 -0500
+
+    ext4: Add block validity check when truncating indirect block mapped inodes
+    
+    Add checks to ext4_free_branches() to make sure a block number found
+    in an indirect block are valid before trying to free it.  If a bad
+    block number is found, stop freeing the indirect block immediately,
+    since the file system is corrupt and we will need to run fsck anyway.
+    This also avoids spamming the logs, and specifically avoids
+    driver-level "attempt to access beyond end of device" errors obscure
+    what is really going on.
+    
+    If you get *really*, *really*, *really* unlucky, without this patch, a
+    supposed indirect block containing garbage might contain a reference
+    to a primary block group descriptor, in which case
+    ext4_free_branches() could end up zero'ing out a block group
+    descriptor block, and if then one of the block bitmaps for a block
+    group described by that bg descriptor block is not in memory, and is
+    read in by ext4_read_block_bitmap().  This function calls
+    ext4_valid_block_bitmap(), which assumes that bg_inode_table() was
+    validated at mount time and hasn't been modified since.  Since this
+    assumption is no longer valid, it's possible for the value
+    (ext4_inode_table(sb, desc) - group_first_block) to go negative, which
+    will cause ext4_find_next_zero_bit() to trigger a kernel GPF.
+    
+    Addresses-Google-Bug: #2220436
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 602d5ad6f5e7..307ecd13a762 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -377,6 +377,7 @@ struct ext4_new_group_data {
+  */
+ #define EXT4_FREE_BLOCKS_METADATA	0x0001
+ #define EXT4_FREE_BLOCKS_FORGET		0x0002
++#define EXT4_FREE_BLOCKS_VALIDATED	0x0004
+ 
+ /*
+  * ioctl commands
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 2059c34ac4c8..3e8afd969236 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4130,18 +4130,27 @@ static Indirect *ext4_find_shared(struct inode *inode, int depth,
+  * We release `count' blocks on disk, but (last - first) may be greater
+  * than `count' because there can be holes in there.
+  */
+-static void ext4_clear_blocks(handle_t *handle, struct inode *inode,
+-			      struct buffer_head *bh,
+-			      ext4_fsblk_t block_to_free,
+-			      unsigned long count, __le32 *first,
+-			      __le32 *last)
++static int ext4_clear_blocks(handle_t *handle, struct inode *inode,
++			     struct buffer_head *bh,
++			     ext4_fsblk_t block_to_free,
++			     unsigned long count, __le32 *first,
++			     __le32 *last)
+ {
+ 	__le32 *p;
+-	int	flags = EXT4_FREE_BLOCKS_FORGET;
++	int	flags = EXT4_FREE_BLOCKS_FORGET | EXT4_FREE_BLOCKS_VALIDATED;
+ 
+ 	if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+ 		flags |= EXT4_FREE_BLOCKS_METADATA;
+ 
++	if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), block_to_free,
++				   count)) {
++		ext4_error(inode->i_sb, __func__, "inode #%lu: "
++			   "attempt to clear blocks %llu len %lu, invalid",
++			   inode->i_ino, (unsigned long long) block_to_free,
++			   count);
++		return 1;
++	}
++
+ 	if (try_to_extend_transaction(handle, inode)) {
+ 		if (bh) {
+ 			BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
+@@ -4160,6 +4169,7 @@ static void ext4_clear_blocks(handle_t *handle, struct inode *inode,
+ 		*p = 0;
+ 
+ 	ext4_free_blocks(handle, inode, 0, block_to_free, count, flags);
++	return 0;
+ }
+ 
+ /**
+@@ -4215,9 +4225,10 @@ static void ext4_free_data(handle_t *handle, struct inode *inode,
+ 			} else if (nr == block_to_free + count) {
+ 				count++;
+ 			} else {
+-				ext4_clear_blocks(handle, inode, this_bh,
+-						  block_to_free,
+-						  count, block_to_free_p, p);
++				if (ext4_clear_blocks(handle, inode, this_bh,
++						      block_to_free, count,
++						      block_to_free_p, p))
++					break;
+ 				block_to_free = nr;
+ 				block_to_free_p = p;
+ 				count = 1;
+@@ -4281,6 +4292,16 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
+ 			if (!nr)
+ 				continue;		/* A hole */
+ 
++			if (!ext4_data_block_valid(EXT4_SB(inode->i_sb),
++						   nr, 1)) {
++				ext4_error(inode->i_sb, __func__,
++					   "indirect mapped block in inode "
++					   "#%lu invalid (level %d, blk #%lu)",
++					   inode->i_ino, depth,
++					   (unsigned long) nr);
++				break;
++			}
++
+ 			/* Go read the buffer for the next level down */
+ 			bh = sb_bread(inode->i_sb, nr);
+ 
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index d34afad3e137..d129c1039f1d 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -4476,10 +4476,11 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 
+ 	sbi = EXT4_SB(sb);
+ 	es = EXT4_SB(sb)->s_es;
+-	if (!ext4_data_block_valid(sbi, block, count)) {
++	if (!(flags & EXT4_FREE_BLOCKS_VALIDATED) &&
++	    !ext4_data_block_valid(sbi, block, count)) {
+ 		ext4_error(sb, __func__,
+-			    "Freeing blocks not in datazone - "
+-			    "block = %llu, count = %lu", block, count);
++			   "Freeing blocks not in datazone - "
++			   "block = %llu, count = %lu", block, count);
+ 		goto error_return;
+ 	}
+ 

commit 24b584240a0006ea7436cd35f5e8983eb76f1e6f
+Author: Theodore Ts'o 
+Date:   Mon Dec 7 14:08:51 2009 -0500
+
+    ext4: Use ext4 file system driver for ext2/ext3 file system mounts
+    
+    Add a new config option, CONFIG_EXT4_USE_FOR_EXT23 which if enabled,
+    will cause ext4 to be used for either ext2 or ext3 file system mounts
+    when ext2 or ext3 is not enabled in the configuration.
+    
+    This allows minimalist kernel fanatics to drop to file system drivers
+    from their compiled kernel with out losing functionality.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
+index 9f2d45d75b1a..a6b4e93833d6 100644
+--- a/fs/ext4/Kconfig
++++ b/fs/ext4/Kconfig
+@@ -26,6 +26,16 @@ config EXT4_FS
+ 
+ 	  If unsure, say N.
+ 
++config EXT4_USE_FOR_EXT23
++	bool "Use ext4 for ext2/ext3 file systems"
++	depends on !EXT3_FS || !EXT2_FS
++	default y
++	help
++	  Allow the ext4 file system driver code to be used for ext2 or
++	  ext3 file system mounts.  This allows users to reduce their
++	  compiled kernel size by using one file system driver for
++	  ext2, ext3, and ext4 file systems.
++
+ config EXT4_FS_XATTR
+ 	bool "Ext4 extended attributes"
+ 	depends on EXT4_FS
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 5a2db612950b..30476daf966e 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3960,6 +3960,58 @@ static int ext4_get_sb(struct file_system_type *fs_type, int flags,
+ 	return get_sb_bdev(fs_type, flags, dev_name, data, ext4_fill_super,mnt);
+ }
+ 
++#if !defined(CONTIG_EXT2_FS) && defined(CONFIG_EXT4_USE_FOR_EXT23)
++static struct file_system_type ext2_fs_type = {
++	.owner		= THIS_MODULE,
++	.name		= "ext2",
++	.get_sb		= ext4_get_sb,
++	.kill_sb	= kill_block_super,
++	.fs_flags	= FS_REQUIRES_DEV,
++};
++
++static inline void register_as_ext2(void)
++{
++	int err = register_filesystem(&ext2_fs_type);
++	if (err)
++		printk(KERN_WARNING
++		       "EXT4-fs: Unable to register as ext2 (%d)\n", err);
++}
++
++static inline void unregister_as_ext2(void)
++{
++	unregister_filesystem(&ext2_fs_type);
++}
++#else
++static inline void register_as_ext2(void) { }
++static inline void unregister_as_ext2(void) { }
++#endif
++
++#if !defined(CONTIG_EXT3_FS) && defined(CONFIG_EXT4_USE_FOR_EXT23)
++static struct file_system_type ext3_fs_type = {
++	.owner		= THIS_MODULE,
++	.name		= "ext3",
++	.get_sb		= ext4_get_sb,
++	.kill_sb	= kill_block_super,
++	.fs_flags	= FS_REQUIRES_DEV,
++};
++
++static inline void register_as_ext3(void)
++{
++	int err = register_filesystem(&ext3_fs_type);
++	if (err)
++		printk(KERN_WARNING
++		       "EXT4-fs: Unable to register as ext3 (%d)\n", err);
++}
++
++static inline void unregister_as_ext3(void)
++{
++	unregister_filesystem(&ext3_fs_type);
++}
++#else
++static inline void register_as_ext3(void) { }
++static inline void unregister_as_ext3(void) { }
++#endif
++
+ static struct file_system_type ext4_fs_type = {
+ 	.owner		= THIS_MODULE,
+ 	.name		= "ext4",
+@@ -3989,11 +4041,15 @@ static int __init init_ext4_fs(void)
+ 	err = init_inodecache();
+ 	if (err)
+ 		goto out1;
++	register_as_ext2();
++	register_as_ext3();
+ 	err = register_filesystem(&ext4_fs_type);
+ 	if (err)
+ 		goto out;
+ 	return 0;
+ out:
++	unregister_as_ext2();
++	unregister_as_ext3();
+ 	destroy_inodecache();
+ out1:
+ 	exit_ext4_xattr();
+@@ -4009,6 +4065,8 @@ static int __init init_ext4_fs(void)
+ 
+ static void __exit exit_ext4_fs(void)
+ {
++	unregister_as_ext2();
++	unregister_as_ext3();
+ 	unregister_filesystem(&ext4_fs_type);
+ 	destroy_inodecache();
+ 	exit_ext4_xattr();

commit e6ec116b67f46e0e7808276476554727b2e6240b
+Author: Theodore Ts'o 
+Date:   Tue Dec 1 09:04:42 2009 -0500
+
+    jbd2: Add ENOMEM checking in and for jbd2_journal_write_metadata_buffer()
+    
+    OOM happens.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index d4cfd6d2779e..8896c1d4febe 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -636,6 +636,10 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 		JBUFFER_TRACE(jh, "ph3: write metadata");
+ 		flags = jbd2_journal_write_metadata_buffer(commit_transaction,
+ 						      jh, &new_jh, blocknr);
++		if (flags < 0) {
++			jbd2_journal_abort(journal, flags);
++			continue;
++		}
+ 		set_bit(BH_JWrite, &jh2bh(new_jh)->b_state);
+ 		wbuf[bufs++] = jh2bh(new_jh);
+ 
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index af60d98ddd22..3f473faa4660 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -358,6 +358,10 @@ int jbd2_journal_write_metadata_buffer(transaction_t *transaction,
+ 
+ 		jbd_unlock_bh_state(bh_in);
+ 		tmp = jbd2_alloc(bh_in->b_size, GFP_NOFS);
++		if (!tmp) {
++			jbd2_journal_put_journal_head(new_jh);
++			return -ENOMEM;
++		}
+ 		jbd_lock_bh_state(bh_in);
+ 		if (jh_in->b_frozen_data) {
+ 			jbd2_free(tmp, bh_in->b_size);

commit 9084d4719784b00ff0bf9c9580007fac8277dbcb
+Author: Theodore Ts'o 
+Date:   Sun Nov 22 20:48:42 2009 -0500
+
+    ext4: use ext4_data_block_valid() in ext4_free_blocks()
+    
+    The block validity framework does a more comprehensive set of checks,
+    and it saves object code space to use the ext4_data_block_valid() than
+    the limited open-coded version that had been in ext4_free_blocks().
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 78de5d3c5dce..ab2dad1dfb7e 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -4463,9 +4463,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 
+ 	sbi = EXT4_SB(sb);
+ 	es = EXT4_SB(sb)->s_es;
+-	if (block < le32_to_cpu(es->s_first_data_block) ||
+-	    block + count < block ||
+-	    block + count > ext4_blocks_count(es)) {
++	if (!ext4_data_block_valid(sbi, block, count)) {
+ 		ext4_error(sb, __func__,
+ 			    "Freeing blocks not in datazone - "
+ 			    "block = %llu, count = %lu", block, count);

commit 1585d8d89ae1791d8f957731f5655700fbcc5664
+Author: Theodore Ts'o 
+Date:   Sun Nov 22 20:48:34 2009 -0500
+
+    ext4: add check for wraparound in ext4_data_block_valid()
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/block_validity.c b/fs/ext4/block_validity.c
+index dc79b75d8f70..4df8621ec31c 100644
+--- a/fs/ext4/block_validity.c
++++ b/fs/ext4/block_validity.c
+@@ -228,6 +228,7 @@ int ext4_data_block_valid(struct ext4_sb_info *sbi, ext4_fsblk_t start_blk,
+ 	struct rb_node *n = sbi->system_blks.rb_node;
+ 
+ 	if ((start_blk <= le32_to_cpu(sbi->s_es->s_first_data_block)) ||
++	    (start_blk + count < start_blk) ||
+ 	    (start_blk + count > ext4_blocks_count(sbi->s_es)))
+ 		return 0;
+ 	while (n) {

commit 6eebee625544ac4ef1d805da942f463275bd6caa
+Author: Theodore Ts'o 
+Date:   Sun Nov 22 20:23:31 2009 -0500
+
+    ext4: print i_mode in octal in ext4 tracepoints
+    
+    Inode permissions are much easier to understand if they are printed in
+    octal.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index 74f628bfdd1b..287347ca71b4 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -38,7 +38,7 @@ TRACE_EVENT(ext4_free_inode,
+ 		__entry->blocks	= inode->i_blocks;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu mode %d uid %u gid %u blocks %llu",
++	TP_printk("dev %s ino %lu mode 0%o uid %u gid %u blocks %llu",
+ 		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
+ 		  __entry->mode, __entry->uid, __entry->gid,
+ 		  (unsigned long long) __entry->blocks)
+@@ -61,7 +61,7 @@ TRACE_EVENT(ext4_request_inode,
+ 		__entry->mode	= mode;
+ 	),
+ 
+-	TP_printk("dev %s dir %lu mode %d",
++	TP_printk("dev %s dir %lu mode 0%o",
+ 		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->dir,
+ 		  __entry->mode)
+ );
+@@ -85,7 +85,7 @@ TRACE_EVENT(ext4_allocate_inode,
+ 		__entry->mode	= mode;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu dir %lu mode %d",
++	TP_printk("dev %s ino %lu dir %lu mode 0%o",
+ 		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
+ 		  (unsigned long) __entry->dir, __entry->mode)
+ );
+@@ -930,7 +930,7 @@ TRACE_EVENT(ext4_forget,
+ 		__entry->block	= block;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu mode %d is_metadata %d block %llu",
++	TP_printk("dev %s ino %lu mode 0%o is_metadata %d block %llu",
+ 		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
+ 		  __entry->mode, __entry->is_metadata, __entry->block)
+ );

commit e6362609b6c71c5b802026be9cf263bbdd67a50e
+Author: Theodore Ts'o 
+Date:   Mon Nov 23 07:17:05 2009 -0500
+
+    ext4: call ext4_forget() from ext4_free_blocks()
+    
+    Add the facility for ext4_forget() to be called from
+    ext4_free_blocks().  This simplifies the code in a large number of
+    places, and centralizes most of the work of calling ext4_forget() into
+    a single place.
+    
+    Also fix a bug in the extents migration code; it wasn't calling
+    ext4_forget() when releasing the indirect blocks during the
+    conversion.  As a result, if the system cashed during or shortly after
+    the extents migration, and the released indirect blocks get reused as
+    data blocks, the journal replay would corrupt the data blocks.  With
+    this new patch, fixing this bug was as simple as adding the
+    EXT4_FREE_BLOCKS_FORGET flags to the call to ext4_free_blocks().
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: "Aneesh Kumar K.V" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 210e1b53e91f..4cfc2f0edb3f 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -375,6 +375,12 @@ struct ext4_new_group_data {
+ #define EXT4_GET_BLOCKS_DIO_CONVERT_EXT		(EXT4_GET_BLOCKS_CONVERT|\
+ 					 EXT4_GET_BLOCKS_DIO_CREATE_EXT)
+ 
++/*
++ * Flags used by ext4_free_blocks
++ */
++#define EXT4_FREE_BLOCKS_METADATA	0x0001
++#define EXT4_FREE_BLOCKS_FORGET		0x0002
++
+ /*
+  * ioctl commands
+  */
+@@ -1384,8 +1390,8 @@ extern void ext4_discard_preallocations(struct inode *);
+ extern int __init init_ext4_mballoc(void);
+ extern void exit_ext4_mballoc(void);
+ extern void ext4_free_blocks(handle_t *handle, struct inode *inode,
+-			     ext4_fsblk_t block, unsigned long count,
+-			     int metadata);
++			     struct buffer_head *bh, ext4_fsblk_t block,
++			     unsigned long count, int flags);
+ extern int ext4_mb_add_groupinfo(struct super_block *sb,
+ 		ext4_group_t i, struct ext4_group_desc *desc);
+ extern int ext4_mb_get_buddy_cache_lock(struct super_block *, ext4_group_t);
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 74dcff84c3a8..2c4a9321fb14 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -1007,7 +1007,8 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
+ 		for (i = 0; i < depth; i++) {
+ 			if (!ablocks[i])
+ 				continue;
+-			ext4_free_blocks(handle, inode, ablocks[i], 1, 1);
++			ext4_free_blocks(handle, inode, 0, ablocks[i], 1,
++					 EXT4_FREE_BLOCKS_METADATA);
+ 		}
+ 	}
+ 	kfree(ablocks);
+@@ -1957,7 +1958,6 @@ ext4_ext_in_cache(struct inode *inode, ext4_lblk_t block,
+ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode,
+ 			struct ext4_ext_path *path)
+ {
+-	struct buffer_head *bh;
+ 	int err;
+ 	ext4_fsblk_t leaf;
+ 
+@@ -1973,9 +1973,8 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode,
+ 	if (err)
+ 		return err;
+ 	ext_debug("index is empty, remove it, free block %llu\n", leaf);
+-	bh = sb_find_get_block(inode->i_sb, leaf);
+-	ext4_forget(handle, 1, inode, bh, leaf);
+-	ext4_free_blocks(handle, inode, leaf, 1, 1);
++	ext4_free_blocks(handle, inode, 0, leaf, 1,
++			 EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET);
+ 	return err;
+ }
+ 
+@@ -2042,12 +2041,11 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
+ 				struct ext4_extent *ex,
+ 				ext4_lblk_t from, ext4_lblk_t to)
+ {
+-	struct buffer_head *bh;
+ 	unsigned short ee_len =  ext4_ext_get_actual_len(ex);
+-	int i, metadata = 0;
++	int flags = EXT4_FREE_BLOCKS_FORGET;
+ 
+ 	if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+-		metadata = 1;
++		flags |= EXT4_FREE_BLOCKS_METADATA;
+ #ifdef EXTENTS_STATS
+ 	{
+ 		struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+@@ -2072,11 +2070,7 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
+ 		num = le32_to_cpu(ex->ee_block) + ee_len - from;
+ 		start = ext_pblock(ex) + ee_len - num;
+ 		ext_debug("free last %u blocks starting %llu\n", num, start);
+-		for (i = 0; i < num; i++) {
+-			bh = sb_find_get_block(inode->i_sb, start + i);
+-			ext4_forget(handle, metadata, inode, bh, start + i);
+-		}
+-		ext4_free_blocks(handle, inode, start, num, metadata);
++		ext4_free_blocks(handle, inode, 0, start, num, flags);
+ 	} else if (from == le32_to_cpu(ex->ee_block)
+ 		   && to <= le32_to_cpu(ex->ee_block) + ee_len - 1) {
+ 		printk(KERN_INFO "strange request: removal %u-%u from %u:%u\n",
+@@ -3319,8 +3313,8 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 		/* not a good idea to call discard here directly,
+ 		 * but otherwise we'd need to call it every free() */
+ 		ext4_discard_preallocations(inode);
+-		ext4_free_blocks(handle, inode, ext_pblock(&newex),
+-					ext4_ext_get_actual_len(&newex), 0);
++		ext4_free_blocks(handle, inode, 0, ext_pblock(&newex),
++				 ext4_ext_get_actual_len(&newex), 0);
+ 		goto out2;
+ 	}
+ 
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 72c694323492..3b28e1fbfc90 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -669,7 +669,7 @@ static int ext4_alloc_blocks(handle_t *handle, struct inode *inode,
+ 	return ret;
+ failed_out:
+ 	for (i = 0; i < index; i++)
+-		ext4_free_blocks(handle, inode, new_blocks[i], 1, 0);
++		ext4_free_blocks(handle, inode, 0, new_blocks[i], 1, 0);
+ 	return ret;
+ }
+ 
+@@ -765,20 +765,20 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
+ 	return err;
+ failed:
+ 	/* Allocation failed, free what we already allocated */
++	ext4_free_blocks(handle, inode, 0, new_blocks[0], 1, 0);
+ 	for (i = 1; i <= n ; i++) {
+-		BUFFER_TRACE(branch[i].bh, "call jbd2_journal_forget");
+ 		/* 
+-		 * Note: is_metadata is 0 because branch[i].bh is
+-		 * newly allocated, so there is no need to revoke the
+-		 * block.  If we do, it's harmless, but not necessary.
++		 * branch[i].bh is newly allocated, so there is no
++		 * need to revoke the block, which is why we don't
++		 * need to set EXT4_FREE_BLOCKS_METADATA.
+ 		 */
+-		ext4_forget(handle, 0, inode, branch[i].bh,
+-			    branch[i].bh->b_blocknr);
++		ext4_free_blocks(handle, inode, 0, new_blocks[i], 1,
++				 EXT4_FREE_BLOCKS_FORGET);
+ 	}
+-	for (i = 0; i < indirect_blks; i++)
+-		ext4_free_blocks(handle, inode, new_blocks[i], 1, 0);
++	for (i = n+1; i < indirect_blks; i++)
++		ext4_free_blocks(handle, inode, 0, new_blocks[i], 1, 0);
+ 
+-	ext4_free_blocks(handle, inode, new_blocks[i], num, 0);
++	ext4_free_blocks(handle, inode, 0, new_blocks[i], num, 0);
+ 
+ 	return err;
+ }
+@@ -857,18 +857,16 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
+ 
+ err_out:
+ 	for (i = 1; i <= num; i++) {
+-		BUFFER_TRACE(where[i].bh, "call jbd2_journal_forget");
+ 		/* 
+-		 * Note: is_metadata is 0 because branch[i].bh is
+-		 * newly allocated, so there is no need to revoke the
+-		 * block.  If we do, it's harmless, but not necessary.
++		 * branch[i].bh is newly allocated, so there is no
++		 * need to revoke the block, which is why we don't
++		 * need to set EXT4_FREE_BLOCKS_METADATA.
+ 		 */
+-		ext4_forget(handle, 0, inode, where[i].bh,
+-			    where[i].bh->b_blocknr);
+-		ext4_free_blocks(handle, inode,
+-					le32_to_cpu(where[i-1].key), 1, 0);
++		ext4_free_blocks(handle, inode, where[i].bh, 0, 1,
++				 EXT4_FREE_BLOCKS_FORGET);
+ 	}
+-	ext4_free_blocks(handle, inode, le32_to_cpu(where[num].key), blks, 0);
++	ext4_free_blocks(handle, inode, 0, le32_to_cpu(where[num].key),
++			 blks, 0);
+ 
+ 	return err;
+ }
+@@ -4080,7 +4078,10 @@ static void ext4_clear_blocks(handle_t *handle, struct inode *inode,
+ 			      __le32 *last)
+ {
+ 	__le32 *p;
+-	int	is_metadata = S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode);
++	int	flags = EXT4_FREE_BLOCKS_FORGET;
++
++	if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
++		flags |= EXT4_FREE_BLOCKS_METADATA;
+ 
+ 	if (try_to_extend_transaction(handle, inode)) {
+ 		if (bh) {
+@@ -4096,27 +4097,10 @@ static void ext4_clear_blocks(handle_t *handle, struct inode *inode,
+ 		}
+ 	}
+ 
+-	/*
+-	 * Any buffers which are on the journal will be in memory. We
+-	 * find them on the hash table so jbd2_journal_revoke() will
+-	 * run jbd2_journal_forget() on them.  We've already detached
+-	 * each block from the file, so bforget() in
+-	 * jbd2_journal_forget() should be safe.
+-	 *
+-	 * AKPM: turn on bforget in jbd2_journal_forget()!!!
+-	 */
+-	for (p = first; p < last; p++) {
+-		u32 nr = le32_to_cpu(*p);
+-		if (nr) {
+-			struct buffer_head *tbh;
+-
+-			*p = 0;
+-			tbh = sb_find_get_block(inode->i_sb, nr);
+-			ext4_forget(handle, is_metadata, inode, tbh, nr);
+-		}
+-	}
++	for (p = first; p < last; p++)
++		*p = 0;
+ 
+-	ext4_free_blocks(handle, inode, block_to_free, count, is_metadata);
++	ext4_free_blocks(handle, inode, 0, block_to_free, count, flags);
+ }
+ 
+ /**
+@@ -4304,7 +4288,8 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
+ 					    blocks_for_truncate(inode));
+ 			}
+ 
+-			ext4_free_blocks(handle, inode, nr, 1, 1);
++			ext4_free_blocks(handle, inode, 0, nr, 1,
++					 EXT4_FREE_BLOCKS_METADATA);
+ 
+ 			if (parent_bh) {
+ 				/*
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 0dca90be1afb..78de5d3c5dce 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -4436,8 +4436,8 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
+  * @metadata: 		Are these metadata blocks
+  */
+ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+-		      ext4_fsblk_t block, unsigned long count,
+-		      int metadata)
++		      struct buffer_head *bh, ext4_fsblk_t block,
++		      unsigned long count, int flags)
+ {
+ 	struct buffer_head *bitmap_bh = NULL;
+ 	struct super_block *sb = inode->i_sb;
+@@ -4454,15 +4454,12 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 	int err = 0;
+ 	int ret;
+ 
+-	/* 
+-	 * We need to make sure we don't reuse the freed block until
+-	 * after the transaction is committed, which we can do by
+-	 * treating the block as metadata, below.  We make an
+-	 * exception if the inode is to be written in writeback mode
+-	 * since writeback mode has weak data consistency guarantees.
+-	 */
+-	if (!ext4_should_writeback_data(inode))
+-		metadata = 1;
++	if (bh) {
++		if (block)
++			BUG_ON(block != bh->b_blocknr);
++		else
++			block = bh->b_blocknr;
++	}
+ 
+ 	sbi = EXT4_SB(sb);
+ 	es = EXT4_SB(sb)->s_es;
+@@ -4476,7 +4473,32 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 	}
+ 
+ 	ext4_debug("freeing block %llu\n", block);
+-	trace_ext4_free_blocks(inode, block, count, metadata);
++	trace_ext4_free_blocks(inode, block, count, flags);
++
++	if (flags & EXT4_FREE_BLOCKS_FORGET) {
++		struct buffer_head *tbh = bh;
++		int i;
++
++		BUG_ON(bh && (count > 1));
++
++		for (i = 0; i < count; i++) {
++			if (!bh)
++				tbh = sb_find_get_block(inode->i_sb,
++							block + i);
++			ext4_forget(handle, flags & EXT4_FREE_BLOCKS_METADATA, 
++				    inode, tbh, block + i);
++		}
++	}
++
++	/* 
++	 * We need to make sure we don't reuse the freed block until
++	 * after the transaction is committed, which we can do by
++	 * treating the block as metadata, below.  We make an
++	 * exception if the inode is to be written in writeback mode
++	 * since writeback mode has weak data consistency guarantees.
++	 */
++	if (!ext4_should_writeback_data(inode))
++		flags |= EXT4_FREE_BLOCKS_METADATA;
+ 
+ 	ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
+ 	if (ac) {
+@@ -4552,7 +4574,8 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 	err = ext4_mb_load_buddy(sb, block_group, &e4b);
+ 	if (err)
+ 		goto error_return;
+-	if (metadata && ext4_handle_valid(handle)) {
++
++	if ((flags & EXT4_FREE_BLOCKS_METADATA) && ext4_handle_valid(handle)) {
+ 		struct ext4_free_data *new_entry;
+ 		/*
+ 		 * blocks being freed are metadata. these blocks shouldn't
+diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
+index a93d5b80f3e2..d641e13e740e 100644
+--- a/fs/ext4/migrate.c
++++ b/fs/ext4/migrate.c
+@@ -262,13 +262,17 @@ static int free_dind_blocks(handle_t *handle,
+ 	for (i = 0; i < max_entries; i++) {
+ 		if (tmp_idata[i]) {
+ 			extend_credit_for_blkdel(handle, inode);
+-			ext4_free_blocks(handle, inode,
+-					le32_to_cpu(tmp_idata[i]), 1, 1);
++			ext4_free_blocks(handle, inode, 0,
++					 le32_to_cpu(tmp_idata[i]), 1,
++					 EXT4_FREE_BLOCKS_METADATA |
++					 EXT4_FREE_BLOCKS_FORGET);
+ 		}
+ 	}
+ 	put_bh(bh);
+ 	extend_credit_for_blkdel(handle, inode);
+-	ext4_free_blocks(handle, inode, le32_to_cpu(i_data), 1, 1);
++	ext4_free_blocks(handle, inode, 0, le32_to_cpu(i_data), 1,
++			 EXT4_FREE_BLOCKS_METADATA |
++			 EXT4_FREE_BLOCKS_FORGET);
+ 	return 0;
+ }
+ 
+@@ -297,7 +301,9 @@ static int free_tind_blocks(handle_t *handle,
+ 	}
+ 	put_bh(bh);
+ 	extend_credit_for_blkdel(handle, inode);
+-	ext4_free_blocks(handle, inode, le32_to_cpu(i_data), 1, 1);
++	ext4_free_blocks(handle, inode, 0, le32_to_cpu(i_data), 1,
++			 EXT4_FREE_BLOCKS_METADATA |
++			 EXT4_FREE_BLOCKS_FORGET);
+ 	return 0;
+ }
+ 
+@@ -308,8 +314,10 @@ static int free_ind_block(handle_t *handle, struct inode *inode, __le32 *i_data)
+ 	/* ei->i_data[EXT4_IND_BLOCK] */
+ 	if (i_data[0]) {
+ 		extend_credit_for_blkdel(handle, inode);
+-		ext4_free_blocks(handle, inode,
+-				le32_to_cpu(i_data[0]), 1, 1);
++		ext4_free_blocks(handle, inode, 0,
++				le32_to_cpu(i_data[0]), 1,
++				 EXT4_FREE_BLOCKS_METADATA |
++				 EXT4_FREE_BLOCKS_FORGET);
+ 	}
+ 
+ 	/* ei->i_data[EXT4_DIND_BLOCK] */
+@@ -419,7 +427,8 @@ static int free_ext_idx(handle_t *handle, struct inode *inode,
+ 	}
+ 	put_bh(bh);
+ 	extend_credit_for_blkdel(handle, inode);
+-	ext4_free_blocks(handle, inode, block, 1, 1);
++	ext4_free_blocks(handle, inode, 0, block, 1,
++			 EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET);
+ 	return retval;
+ }
+ 
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 025701926f9a..910bf9a59cb3 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -482,9 +482,10 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode,
+ 		ea_bdebug(bh, "refcount now=0; freeing");
+ 		if (ce)
+ 			mb_cache_entry_free(ce);
+-		ext4_free_blocks(handle, inode, bh->b_blocknr, 1, 1);
+ 		get_bh(bh);
+-		ext4_forget(handle, 1, inode, bh, bh->b_blocknr);
++		ext4_free_blocks(handle, inode, bh, 0, 1,
++				 EXT4_FREE_BLOCKS_METADATA |
++				 EXT4_FREE_BLOCKS_FORGET);
+ 	} else {
+ 		le32_add_cpu(&BHDR(bh)->h_refcount, -1);
+ 		error = ext4_handle_dirty_metadata(handle, inode, bh);
+@@ -832,7 +833,8 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
+ 			new_bh = sb_getblk(sb, block);
+ 			if (!new_bh) {
+ getblk_failed:
+-				ext4_free_blocks(handle, inode, block, 1, 1);
++				ext4_free_blocks(handle, inode, 0, block, 1,
++						 EXT4_FREE_BLOCKS_METADATA);
+ 				error = -EIO;
+ 				goto cleanup;
+ 			}
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index b390e1fc4a7b..74f628bfdd1b 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -650,30 +650,32 @@ TRACE_EVENT(ext4_allocate_blocks,
+ 
+ TRACE_EVENT(ext4_free_blocks,
+ 	TP_PROTO(struct inode *inode, __u64 block, unsigned long count,
+-			int metadata),
++		 int flags),
+ 
+-	TP_ARGS(inode, block, count, metadata),
++	TP_ARGS(inode, block, count, flags),
+ 
+ 	TP_STRUCT__entry(
+ 		__field(	dev_t,	dev			)
+ 		__field(	ino_t,	ino			)
++		__field(      umode_t, mode			)
+ 		__field(	__u64,	block			)
+ 		__field(	unsigned long,	count		)
+-		__field(	int,	metadata		)
+-
++		__field(	 int,	flags			)
+ 	),
+ 
+ 	TP_fast_assign(
+ 		__entry->dev		= inode->i_sb->s_dev;
+ 		__entry->ino		= inode->i_ino;
++		__entry->mode		= inode->i_mode;
+ 		__entry->block		= block;
+ 		__entry->count		= count;
+-		__entry->metadata	= metadata;
++		__entry->flags		= flags;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu block %llu count %lu metadata %d",
++	TP_printk("dev %s ino %lu mode 0%o block %llu count %lu flags %d",
+ 		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
+-		  __entry->block, __entry->count, __entry->metadata)
++		  __entry->mode, __entry->block, __entry->count,
++		  __entry->flags)
+ );
+ 
+ TRACE_EVENT(ext4_sync_file,

commit 4433871130f36585fde38e7dd817433296648945
+Author: Theodore Ts'o 
+Date:   Sun Nov 22 07:44:56 2009 -0500
+
+    ext4: fold ext4_free_blocks() and ext4_mb_free_blocks()
+    
+    ext4_mb_free_blocks() is only called by ext4_free_blocks(), and the
+    latter function doesn't really do much.  So merge the two functions
+    together, such that ext4_free_blocks() is now found in
+    fs/ext4/mballoc.c.  This saves about 200 bytes of compiled text space.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index f3032c919a22..22bc7435d913 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -498,44 +498,6 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
+ 	return;
+ }
+ 
+-/**
+- * ext4_free_blocks() -- Free given blocks and update quota
+- * @handle:		handle for this transaction
+- * @inode:		inode
+- * @block:		start physical block to free
+- * @count:		number of blocks to count
+- * @metadata: 		Are these metadata blocks
+- */
+-void ext4_free_blocks(handle_t *handle, struct inode *inode,
+-			ext4_fsblk_t block, unsigned long count,
+-			int metadata)
+-{
+-	struct super_block *sb;
+-	unsigned long dquot_freed_blocks;
+-
+-	/* this isn't the right place to decide whether block is metadata
+-	 * inode.c/extents.c knows better, but for safety ... */
+-	if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+-		metadata = 1;
+-
+-	/* We need to make sure we don't reuse
+-	 * block released untill the transaction commit.
+-	 * writeback mode have weak data consistency so
+-	 * don't force data as metadata when freeing block
+-	 * for writeback mode.
+-	 */
+-	if (metadata == 0 && !ext4_should_writeback_data(inode))
+-		metadata = 1;
+-
+-	sb = inode->i_sb;
+-
+-	ext4_mb_free_blocks(handle, inode, block, count,
+-			    metadata, &dquot_freed_blocks);
+-	if (dquot_freed_blocks)
+-		vfs_dq_free_block(inode, dquot_freed_blocks);
+-	return;
+-}
+-
+ /**
+  * ext4_has_free_blocks()
+  * @sbi:	in-core super block structure.
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 57c4e03afa0a..210e1b53e91f 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1325,8 +1325,6 @@ extern ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
+ 			ext4_fsblk_t goal, unsigned long *count, int *errp);
+ extern int ext4_claim_free_blocks(struct ext4_sb_info *sbi, s64 nblocks);
+ extern int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks);
+-extern void ext4_free_blocks(handle_t *handle, struct inode *inode,
+-			ext4_fsblk_t block, unsigned long count, int metadata);
+ extern void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
+ 				ext4_fsblk_t block, unsigned long count);
+ extern ext4_fsblk_t ext4_count_free_blocks(struct super_block *);
+@@ -1385,8 +1383,9 @@ extern int ext4_mb_reserve_blocks(struct super_block *, int);
+ extern void ext4_discard_preallocations(struct inode *);
+ extern int __init init_ext4_mballoc(void);
+ extern void exit_ext4_mballoc(void);
+-extern void ext4_mb_free_blocks(handle_t *, struct inode *,
+-		ext4_fsblk_t, unsigned long, int, unsigned long *);
++extern void ext4_free_blocks(handle_t *handle, struct inode *inode,
++			     ext4_fsblk_t block, unsigned long count,
++			     int metadata);
+ extern int ext4_mb_add_groupinfo(struct super_block *sb,
+ 		ext4_group_t i, struct ext4_group_desc *desc);
+ extern int ext4_mb_get_buddy_cache_lock(struct super_block *, ext4_group_t);
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 6e5a23a2cc25..0dca90be1afb 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -4427,18 +4427,24 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
+ 	return 0;
+ }
+ 
+-/*
+- * Main entry point into mballoc to free blocks
++/**
++ * ext4_free_blocks() -- Free given blocks and update quota
++ * @handle:		handle for this transaction
++ * @inode:		inode
++ * @block:		start physical block to free
++ * @count:		number of blocks to count
++ * @metadata: 		Are these metadata blocks
+  */
+-void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
+-			ext4_fsblk_t block, unsigned long count,
+-			int metadata, unsigned long *freed)
++void ext4_free_blocks(handle_t *handle, struct inode *inode,
++		      ext4_fsblk_t block, unsigned long count,
++		      int metadata)
+ {
+ 	struct buffer_head *bitmap_bh = NULL;
+ 	struct super_block *sb = inode->i_sb;
+ 	struct ext4_allocation_context *ac = NULL;
+ 	struct ext4_group_desc *gdp;
+ 	struct ext4_super_block *es;
++	unsigned long freed = 0;
+ 	unsigned int overflow;
+ 	ext4_grpblk_t bit;
+ 	struct buffer_head *gd_bh;
+@@ -4448,7 +4454,15 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
+ 	int err = 0;
+ 	int ret;
+ 
+-	*freed = 0;
++	/* 
++	 * We need to make sure we don't reuse the freed block until
++	 * after the transaction is committed, which we can do by
++	 * treating the block as metadata, below.  We make an
++	 * exception if the inode is to be written in writeback mode
++	 * since writeback mode has weak data consistency guarantees.
++	 */
++	if (!ext4_should_writeback_data(inode))
++		metadata = 1;
+ 
+ 	sbi = EXT4_SB(sb);
+ 	es = EXT4_SB(sb)->s_es;
+@@ -4577,7 +4591,7 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
+ 
+ 	ext4_mb_release_desc(&e4b);
+ 
+-	*freed += count;
++	freed += count;
+ 
+ 	/* We dirtied the bitmap block */
+ 	BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
+@@ -4597,6 +4611,8 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
+ 	}
+ 	sb->s_dirt = 1;
+ error_return:
++	if (freed)
++		vfs_dq_free_block(inode, freed);
+ 	brelse(bitmap_bh);
+ 	ext4_std_error(sb, err);
+ 	if (ac)

commit b7e57e7c2a41826e51fe060fae5158bfc7a04e81
+Author: Theodore Ts'o 
+Date:   Sun Nov 22 21:00:13 2009 -0500
+
+    ext4: fold ext4_journal_forget() into ext4_forget()
+    
+    Convert the last two callers of ext4_journal_forget() to use
+    ext4_forget() instead, and then fold ext4_journal_forget() into
+    ext4_forget().  This reduces are code complexity and shortens our call
+    stack.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
+index 92c88a8f734d..b57e5c711b6d 100644
+--- a/fs/ext4/ext4_jbd2.c
++++ b/fs/ext4/ext4_jbd2.c
+@@ -34,22 +34,6 @@ int __ext4_journal_get_write_access(const char *where, handle_t *handle,
+ 	return err;
+ }
+ 
+-int __ext4_journal_forget(const char *where, handle_t *handle,
+-				struct buffer_head *bh)
+-{
+-	int err = 0;
+-
+-	if (ext4_handle_valid(handle)) {
+-		err = jbd2_journal_forget(handle, bh);
+-		if (err)
+-			ext4_journal_abort_handle(where, __func__, bh,
+-						  handle, err);
+-	}
+-	else
+-		bforget(bh);
+-	return err;
+-}
+-
+ /*
+  * The ext4 forget function must perform a revoke if we are freeing data
+  * which has been journaled.  Metadata (eg. indirect blocks) must be
+@@ -93,7 +77,11 @@ int __ext4_forget(const char *where, handle_t *handle, int is_metadata,
+ 	    (!is_metadata && !ext4_should_journal_data(inode))) {
+ 		if (bh) {
+ 			BUFFER_TRACE(bh, "call jbd2_journal_forget");
+-			return __ext4_journal_forget(where, handle, bh);
++			err = jbd2_journal_forget(handle, bh);
++			if (err)
++				ext4_journal_abort_handle(where, __func__, bh,
++							  handle, err);
++			return err;
+ 		}
+ 		return 0;
+ 	}
+diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
+index f9fb4bb69577..84bc98ab9f0d 100644
+--- a/fs/ext4/ext4_jbd2.h
++++ b/fs/ext4/ext4_jbd2.h
+@@ -127,10 +127,6 @@ int __ext4_journal_get_undo_access(const char *where, handle_t *handle,
+ int __ext4_journal_get_write_access(const char *where, handle_t *handle,
+ 				struct buffer_head *bh);
+ 
+-/* When called with an invalid handle, this will still do a put on the BH */
+-int __ext4_journal_forget(const char *where, handle_t *handle,
+-				struct buffer_head *bh);
+-
+ int __ext4_forget(const char *where, handle_t *handle, int is_metadata,
+ 		  struct inode *inode, struct buffer_head *bh,
+ 		  ext4_fsblk_t blocknr);
+@@ -150,8 +146,6 @@ int __ext4_handle_dirty_metadata(const char *where, handle_t *handle,
+ 		      (block_nr))
+ #define ext4_journal_get_create_access(handle, bh) \
+ 	__ext4_journal_get_create_access(__func__, (handle), (bh))
+-#define ext4_journal_forget(handle, bh) \
+-	__ext4_journal_forget(__func__, (handle), (bh))
+ #define ext4_handle_dirty_metadata(handle, inode, bh) \
+ 	__ext4_handle_dirty_metadata(__func__, (handle), (inode), (bh))
+ 
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index fa37f9504ece..72c694323492 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -767,7 +767,13 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
+ 	/* Allocation failed, free what we already allocated */
+ 	for (i = 1; i <= n ; i++) {
+ 		BUFFER_TRACE(branch[i].bh, "call jbd2_journal_forget");
+-		ext4_journal_forget(handle, branch[i].bh);
++		/* 
++		 * Note: is_metadata is 0 because branch[i].bh is
++		 * newly allocated, so there is no need to revoke the
++		 * block.  If we do, it's harmless, but not necessary.
++		 */
++		ext4_forget(handle, 0, inode, branch[i].bh,
++			    branch[i].bh->b_blocknr);
+ 	}
+ 	for (i = 0; i < indirect_blks; i++)
+ 		ext4_free_blocks(handle, inode, new_blocks[i], 1, 0);
+@@ -852,7 +858,13 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
+ err_out:
+ 	for (i = 1; i <= num; i++) {
+ 		BUFFER_TRACE(where[i].bh, "call jbd2_journal_forget");
+-		ext4_journal_forget(handle, where[i].bh);
++		/* 
++		 * Note: is_metadata is 0 because branch[i].bh is
++		 * newly allocated, so there is no need to revoke the
++		 * block.  If we do, it's harmless, but not necessary.
++		 */
++		ext4_forget(handle, 0, inode, where[i].bh,
++			    where[i].bh->b_blocknr);
+ 		ext4_free_blocks(handle, inode,
+ 					le32_to_cpu(where[i-1].key), 1, 0);
+ 	}

commit e4684b3fbb848446683feecb4aee133344c93933
+Author: Theodore Ts'o 
+Date:   Tue Nov 24 11:05:59 2009 -0500
+
+    ext4: fold ext4_journal_revoke() into ext4_forget()
+    
+    The only caller of ext4_journal_revoke() is ext4_forget(), so we can
+    fold ext4_journal_revoke() into ext4_forget() to simplify the code and
+    shorten the call stack.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
+index 913f85715433..92c88a8f734d 100644
+--- a/fs/ext4/ext4_jbd2.c
++++ b/fs/ext4/ext4_jbd2.c
+@@ -50,22 +50,6 @@ int __ext4_journal_forget(const char *where, handle_t *handle,
+ 	return err;
+ }
+ 
+-int __ext4_journal_revoke(const char *where, handle_t *handle,
+-				ext4_fsblk_t blocknr, struct buffer_head *bh)
+-{
+-	int err = 0;
+-
+-	if (ext4_handle_valid(handle)) {
+-		err = jbd2_journal_revoke(handle, blocknr, bh);
+-		if (err)
+-			ext4_journal_abort_handle(where, __func__, bh,
+-						  handle, err);
+-	}
+-	else
+-		bforget(bh);
+-	return err;
+-}
+-
+ /*
+  * The ext4 forget function must perform a revoke if we are freeing data
+  * which has been journaled.  Metadata (eg. indirect blocks) must be
+@@ -94,6 +78,12 @@ int __ext4_forget(const char *where, handle_t *handle, int is_metadata,
+ 		  bh, is_metadata, inode->i_mode,
+ 		  test_opt(inode->i_sb, DATA_FLAGS));
+ 
++	/* In the no journal case, we can just do a bforget and return */
++	if (!ext4_handle_valid(handle)) {
++		bforget(bh);
++		return 0;
++	}
++
+ 	/* Never use the revoke function if we are doing full data
+ 	 * journaling: there is no need to, and a V1 superblock won't
+ 	 * support it.  Otherwise, only skip the revoke on un-journaled
+@@ -111,11 +101,13 @@ int __ext4_forget(const char *where, handle_t *handle, int is_metadata,
+ 	/*
+ 	 * data!=journal && (is_metadata || should_journal_data(inode))
+ 	 */
+-	BUFFER_TRACE(bh, "call ext4_journal_revoke");
+-	err = __ext4_journal_revoke(where, handle, blocknr, bh);
+-	if (err)
++	BUFFER_TRACE(bh, "call jbd2_journal_revoke");
++	err = jbd2_journal_revoke(handle, blocknr, bh);
++	if (err) {
++		ext4_journal_abort_handle(where, __func__, bh, handle, err);
+ 		ext4_abort(inode->i_sb, __func__,
+ 			   "error %d when attempting revoke", err);
++	}
+ 	BUFFER_TRACE(bh, "exit");
+ 	return err;
+ }
+diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
+index dc0b34a903eb..f9fb4bb69577 100644
+--- a/fs/ext4/ext4_jbd2.h
++++ b/fs/ext4/ext4_jbd2.h
+@@ -116,12 +116,8 @@ int ext4_reserve_inode_write(handle_t *handle, struct inode *inode,
+ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode);
+ 
+ /*
+- * Wrapper functions with which ext4 calls into JBD.  The intent here is
+- * to allow these to be turned into appropriate stubs so ext4 can control
+- * ext2 filesystems, so ext2+ext4 systems only nee one fs.  This work hasn't
+- * been done yet.
++ * Wrapper functions with which ext4 calls into JBD.
+  */
+-
+ void ext4_journal_abort_handle(const char *caller, const char *err_fn,
+ 		struct buffer_head *bh, handle_t *handle, int err);
+ 
+@@ -135,10 +131,6 @@ int __ext4_journal_get_write_access(const char *where, handle_t *handle,
+ int __ext4_journal_forget(const char *where, handle_t *handle,
+ 				struct buffer_head *bh);
+ 
+-/* When called with an invalid handle, this will still do a put on the BH */
+-int __ext4_journal_revoke(const char *where, handle_t *handle,
+-				ext4_fsblk_t blocknr, struct buffer_head *bh);
+-
+ int __ext4_forget(const char *where, handle_t *handle, int is_metadata,
+ 		  struct inode *inode, struct buffer_head *bh,
+ 		  ext4_fsblk_t blocknr);
+@@ -153,8 +145,6 @@ int __ext4_handle_dirty_metadata(const char *where, handle_t *handle,
+ 	__ext4_journal_get_undo_access(__func__, (handle), (bh))
+ #define ext4_journal_get_write_access(handle, bh) \
+ 	__ext4_journal_get_write_access(__func__, (handle), (bh))
+-#define ext4_journal_revoke(handle, blocknr, bh) \
+-	__ext4_journal_revoke(__func__, (handle), (blocknr), (bh))
+ #define ext4_forget(handle, is_metadata, inode, bh, block_nr) \
+ 	__ext4_forget(__func__, (handle), (is_metadata), (inode), (bh),\
+ 		      (block_nr))

commit d6797d14b1640d088652c72508b529a3aea479e3
+Author: Theodore Ts'o 
+Date:   Sun Nov 22 20:52:12 2009 -0500
+
+    ext4: move ext4_forget() to ext4_jbd2.c
+    
+    The ext4_forget() function better belongs in ext4_jbd2.c.  This will
+    allow us to do some cleanup of the ext4_journal_revoke() and
+    ext4_journal_forget() functions, as well as giving us better error
+    reporting since we can report the caller of ext4_forget() when things
+    go wrong.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 05ce38b981cb..57c4e03afa0a 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1393,8 +1393,6 @@ extern int ext4_mb_get_buddy_cache_lock(struct super_block *, ext4_group_t);
+ extern void ext4_mb_put_buddy_cache_lock(struct super_block *,
+ 						ext4_group_t, int);
+ /* inode.c */
+-int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode,
+-		struct buffer_head *bh, ext4_fsblk_t blocknr);
+ struct buffer_head *ext4_getblk(handle_t *, struct inode *,
+ 						ext4_lblk_t, int, int *);
+ struct buffer_head *ext4_bread(handle_t *, struct inode *,
+diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
+index 6a9409920dee..913f85715433 100644
+--- a/fs/ext4/ext4_jbd2.c
++++ b/fs/ext4/ext4_jbd2.c
+@@ -4,6 +4,8 @@
+ 
+ #include "ext4_jbd2.h"
+ 
++#include 
++
+ int __ext4_journal_get_undo_access(const char *where, handle_t *handle,
+ 				struct buffer_head *bh)
+ {
+@@ -64,6 +66,60 @@ int __ext4_journal_revoke(const char *where, handle_t *handle,
+ 	return err;
+ }
+ 
++/*
++ * The ext4 forget function must perform a revoke if we are freeing data
++ * which has been journaled.  Metadata (eg. indirect blocks) must be
++ * revoked in all cases.
++ *
++ * "bh" may be NULL: a metadata block may have been freed from memory
++ * but there may still be a record of it in the journal, and that record
++ * still needs to be revoked.
++ *
++ * If the handle isn't valid we're not journaling, but we still need to
++ * call into ext4_journal_revoke() to put the buffer head.
++ */
++int __ext4_forget(const char *where, handle_t *handle, int is_metadata,
++		  struct inode *inode, struct buffer_head *bh,
++		  ext4_fsblk_t blocknr)
++{
++	int err;
++
++	might_sleep();
++
++	trace_ext4_forget(inode, is_metadata, blocknr);
++	BUFFER_TRACE(bh, "enter");
++
++	jbd_debug(4, "forgetting bh %p: is_metadata = %d, mode %o, "
++		  "data mode %x\n",
++		  bh, is_metadata, inode->i_mode,
++		  test_opt(inode->i_sb, DATA_FLAGS));
++
++	/* Never use the revoke function if we are doing full data
++	 * journaling: there is no need to, and a V1 superblock won't
++	 * support it.  Otherwise, only skip the revoke on un-journaled
++	 * data blocks. */
++
++	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ||
++	    (!is_metadata && !ext4_should_journal_data(inode))) {
++		if (bh) {
++			BUFFER_TRACE(bh, "call jbd2_journal_forget");
++			return __ext4_journal_forget(where, handle, bh);
++		}
++		return 0;
++	}
++
++	/*
++	 * data!=journal && (is_metadata || should_journal_data(inode))
++	 */
++	BUFFER_TRACE(bh, "call ext4_journal_revoke");
++	err = __ext4_journal_revoke(where, handle, blocknr, bh);
++	if (err)
++		ext4_abort(inode->i_sb, __func__,
++			   "error %d when attempting revoke", err);
++	BUFFER_TRACE(bh, "exit");
++	return err;
++}
++
+ int __ext4_journal_get_create_access(const char *where,
+ 				handle_t *handle, struct buffer_head *bh)
+ {
+diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
+index a2865980342f..dc0b34a903eb 100644
+--- a/fs/ext4/ext4_jbd2.h
++++ b/fs/ext4/ext4_jbd2.h
+@@ -139,6 +139,10 @@ int __ext4_journal_forget(const char *where, handle_t *handle,
+ int __ext4_journal_revoke(const char *where, handle_t *handle,
+ 				ext4_fsblk_t blocknr, struct buffer_head *bh);
+ 
++int __ext4_forget(const char *where, handle_t *handle, int is_metadata,
++		  struct inode *inode, struct buffer_head *bh,
++		  ext4_fsblk_t blocknr);
++
+ int __ext4_journal_get_create_access(const char *where,
+ 				handle_t *handle, struct buffer_head *bh);
+ 
+@@ -151,6 +155,9 @@ int __ext4_handle_dirty_metadata(const char *where, handle_t *handle,
+ 	__ext4_journal_get_write_access(__func__, (handle), (bh))
+ #define ext4_journal_revoke(handle, blocknr, bh) \
+ 	__ext4_journal_revoke(__func__, (handle), (blocknr), (bh))
++#define ext4_forget(handle, is_metadata, inode, bh, block_nr) \
++	__ext4_forget(__func__, (handle), (is_metadata), (inode), (bh),\
++		      (block_nr))
+ #define ext4_journal_get_create_access(handle, bh) \
+ 	__ext4_journal_get_create_access(__func__, (handle), (bh))
+ #define ext4_journal_forget(handle, bh) \
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 3673ec7b1c98..fa37f9504ece 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -70,59 +70,6 @@ static int ext4_inode_is_fast_symlink(struct inode *inode)
+ 	return (S_ISLNK(inode->i_mode) && inode->i_blocks - ea_blocks == 0);
+ }
+ 
+-/*
+- * The ext4 forget function must perform a revoke if we are freeing data
+- * which has been journaled.  Metadata (eg. indirect blocks) must be
+- * revoked in all cases.
+- *
+- * "bh" may be NULL: a metadata block may have been freed from memory
+- * but there may still be a record of it in the journal, and that record
+- * still needs to be revoked.
+- *
+- * If the handle isn't valid we're not journaling, but we still need to
+- * call into ext4_journal_revoke() to put the buffer head.
+- */
+-int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode,
+-		struct buffer_head *bh, ext4_fsblk_t blocknr)
+-{
+-	int err;
+-
+-	might_sleep();
+-
+-	trace_ext4_forget(inode, is_metadata, blocknr);
+-	BUFFER_TRACE(bh, "enter");
+-
+-	jbd_debug(4, "forgetting bh %p: is_metadata = %d, mode %o, "
+-		  "data mode %x\n",
+-		  bh, is_metadata, inode->i_mode,
+-		  test_opt(inode->i_sb, DATA_FLAGS));
+-
+-	/* Never use the revoke function if we are doing full data
+-	 * journaling: there is no need to, and a V1 superblock won't
+-	 * support it.  Otherwise, only skip the revoke on un-journaled
+-	 * data blocks. */
+-
+-	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ||
+-	    (!is_metadata && !ext4_should_journal_data(inode))) {
+-		if (bh) {
+-			BUFFER_TRACE(bh, "call jbd2_journal_forget");
+-			return ext4_journal_forget(handle, bh);
+-		}
+-		return 0;
+-	}
+-
+-	/*
+-	 * data!=journal && (is_metadata || should_journal_data(inode))
+-	 */
+-	BUFFER_TRACE(bh, "call ext4_journal_revoke");
+-	err = ext4_journal_revoke(handle, blocknr, bh);
+-	if (err)
+-		ext4_abort(inode->i_sb, __func__,
+-			   "error %d when attempting revoke", err);
+-	BUFFER_TRACE(bh, "exit");
+-	return err;
+-}
+-
+ /*
+  * Work out how many blocks we need to proceed with the next chunk of a
+  * truncate transaction.

commit 6b17d902fdd241adfa4ce780df20547b28bf5801
+Author: Theodore Ts'o 
+Date:   Mon Nov 23 07:24:57 2009 -0500
+
+    ext4: avoid issuing unnecessary barriers
+    
+    We don't to issue an I/O barrier on an error or if we force commit
+    because we are doing data journaling.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Jan Kara 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
+index 2b1531266ee2..a3c25076aef1 100644
+--- a/fs/ext4/fsync.c
++++ b/fs/ext4/fsync.c
+@@ -60,7 +60,7 @@ int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync)
+ 
+ 	ret = flush_aio_dio_completed_IO(inode);
+ 	if (ret < 0)
+-		goto out;
++		return ret;
+ 	/*
+ 	 * data=writeback:
+ 	 *  The caller's filemap_fdatawrite()/wait will sync the data.
+@@ -79,10 +79,8 @@ int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync)
+ 	 *  (they were dirtied by commit).  But that's OK - the blocks are
+ 	 *  safe in-journal, which is all fsync() needs to ensure.
+ 	 */
+-	if (ext4_should_journal_data(inode)) {
+-		ret = ext4_force_commit(inode->i_sb);
+-		goto out;
+-	}
++	if (ext4_should_journal_data(inode))
++		return ext4_force_commit(inode->i_sb);
+ 
+ 	if (!journal)
+ 		ret = sync_mapping_buffers(inode->i_mapping);

commit 1032988c71f3f85483b2b4319684d1205a704c02
+Author: Theodore Ts'o 
+Date:   Sun Nov 15 15:29:56 2009 -0500
+
+    ext4: fix block validity checks so they work correctly with meta_bg
+    
+    The block validity checks used by ext4_data_block_valid() wasn't
+    correctly written to check file systems with the meta_bg feature.  Fix
+    this.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/block_validity.c b/fs/ext4/block_validity.c
+index 50784ef07563..dc79b75d8f70 100644
+--- a/fs/ext4/block_validity.c
++++ b/fs/ext4/block_validity.c
+@@ -160,7 +160,7 @@ int ext4_setup_system_zone(struct super_block *sb)
+ 		if (ext4_bg_has_super(sb, i) &&
+ 		    ((i < 5) || ((i % flex_size) == 0)))
+ 			add_system_zone(sbi, ext4_group_first_block_no(sb, i),
+-					sbi->s_gdb_count + 1);
++					ext4_bg_num_gdb(sb, i) + 1);
+ 		gdp = ext4_get_group_desc(sb, i, NULL);
+ 		ret = add_system_zone(sbi, ext4_block_bitmap(sb, gdp), 1);
+ 		if (ret)
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 9c097489af89..0c0ddc1401e4 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4884,10 +4884,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 
+ 	ret = 0;
+ 	if (ei->i_file_acl &&
+-	    ((ei->i_file_acl <
+-	      (le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block) +
+-	       EXT4_SB(sb)->s_gdb_count)) ||
+-	     (ei->i_file_acl >= ext4_blocks_count(EXT4_SB(sb)->s_es)))) {
++	    !ext4_data_block_valid(EXT4_SB(sb), ei->i_file_acl, 1)) {
+ 		ext4_error(sb, __func__,
+ 			   "bad extended attribute block %llu in inode #%lu",
+ 			   ei->i_file_acl, inode->i_ino);

commit 8dadb198cb70ef811916668fe67eeec82e8858dd
+Author: Theodore Ts'o 
+Date:   Mon Nov 23 07:24:38 2009 -0500
+
+    ext4: fix uninit block bitmap initialization when s_meta_first_bg is non-zero
+    
+    The number of old-style block group descriptor blocks is
+    s_meta_first_bg when the meta_bg feature flag is set.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 1d0418980f8d..f3032c919a22 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -761,7 +761,13 @@ static unsigned long ext4_bg_num_gdb_meta(struct super_block *sb,
+ static unsigned long ext4_bg_num_gdb_nometa(struct super_block *sb,
+ 					ext4_group_t group)
+ {
+-	return ext4_bg_has_super(sb, group) ? EXT4_SB(sb)->s_gdb_count : 0;
++	if (!ext4_bg_has_super(sb, group))
++		return 0;
++
++	if (EXT4_HAS_INCOMPAT_FEATURE(sb,EXT4_FEATURE_INCOMPAT_META_BG))
++		return le32_to_cpu(EXT4_SB(sb)->s_es->s_first_meta_bg);
++	else
++		return EXT4_SB(sb)->s_gdb_count;
+ }
+ 
+ /**

commit 3f8fb9490efbd300887470a2a880a64e04dcc3f5
+Author: Theodore Ts'o 
+Date:   Mon Nov 23 07:24:52 2009 -0500
+
+    ext4: don't update the superblock in ext4_statfs()
+    
+    commit a71ce8c6c9bf269b192f352ea555217815cf027e updated ext4_statfs()
+    to update the on-disk superblock counters, but modified this buffer
+    directly without any journaling of the change.  This is one of the
+    accesses that was causing the crc errors in journal replay as seen in
+    kernel.org bugzilla #14354.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 04c66907b2fe..f2d5ec77c1e9 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3648,13 +3648,11 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
+ 	buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last;
+ 	buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter) -
+ 		       percpu_counter_sum_positive(&sbi->s_dirtyblocks_counter);
+-	ext4_free_blocks_count_set(es, buf->f_bfree);
+ 	buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es);
+ 	if (buf->f_bfree < ext4_r_blocks_count(es))
+ 		buf->f_bavail = 0;
+ 	buf->f_files = le32_to_cpu(es->s_inodes_count);
+ 	buf->f_ffree = percpu_counter_sum_positive(&sbi->s_freeinodes_counter);
+-	es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
+ 	buf->f_namelen = EXT4_NAME_LEN;
+ 	fsid = le64_to_cpup((void *)es->s_uuid) ^
+ 	       le64_to_cpup((void *)es->s_uuid + sizeof(u64));

commit 50689696867d95b38d9c7be640a311494a04fb86
+Author: Theodore Ts'o 
+Date:   Mon Nov 23 07:17:34 2009 -0500
+
+    ext4: make sure directory and symlink blocks are revoked
+    
+    When an inode gets unlinked, the functions ext4_clear_blocks() and
+    ext4_remove_blocks() call ext4_forget() for all the buffer heads
+    corresponding to the deleted inode's data blocks.  If the inode is a
+    directory or a symlink, the is_metadata parameter must be non-zero so
+    ext4_forget() will revoke them via jbd2_journal_revoke().  Otherwise,
+    if these blocks are reused for a data file, and the system crashes
+    before a journal checkpoint, the journal replay could end up
+    corrupting these data blocks.
+    
+    Thanks to Curt Wohlgemuth for pointing out potential problems in this
+    area.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 715264b4bae4..74dcff84c3a8 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -2074,7 +2074,7 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
+ 		ext_debug("free last %u blocks starting %llu\n", num, start);
+ 		for (i = 0; i < num; i++) {
+ 			bh = sb_find_get_block(inode->i_sb, start + i);
+-			ext4_forget(handle, 0, inode, bh, start + i);
++			ext4_forget(handle, metadata, inode, bh, start + i);
+ 		}
+ 		ext4_free_blocks(handle, inode, start, num, metadata);
+ 	} else if (from == le32_to_cpu(ex->ee_block)
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 13de1dd751f5..c420aaba6e9c 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4121,6 +4121,8 @@ static void ext4_clear_blocks(handle_t *handle, struct inode *inode,
+ 			      __le32 *last)
+ {
+ 	__le32 *p;
++	int	is_metadata = S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode);
++
+ 	if (try_to_extend_transaction(handle, inode)) {
+ 		if (bh) {
+ 			BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
+@@ -4151,11 +4153,11 @@ static void ext4_clear_blocks(handle_t *handle, struct inode *inode,
+ 
+ 			*p = 0;
+ 			tbh = sb_find_get_block(inode->i_sb, nr);
+-			ext4_forget(handle, 0, inode, tbh, nr);
++			ext4_forget(handle, is_metadata, inode, tbh, nr);
+ 		}
+ 	}
+ 
+-	ext4_free_blocks(handle, inode, block_to_free, count, 0);
++	ext4_free_blocks(handle, inode, block_to_free, count, is_metadata);
+ }
+ 
+ /**

commit beac2da7565e42be59963824899825d0cc624295
+Author: Theodore Ts'o 
+Date:   Mon Nov 23 07:25:08 2009 -0500
+
+    ext4: add tracepoint for ext4_forget()
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 554c6798597c..13de1dd751f5 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -89,6 +89,7 @@ int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode,
+ 
+ 	might_sleep();
+ 
++	trace_ext4_forget(inode, is_metadata, blocknr);
+ 	BUFFER_TRACE(bh, "enter");
+ 
+ 	jbd_debug(4, "forgetting bh %p: is_metadata = %d, mode %o, "
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index d09550bf3f95..b390e1fc4a7b 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -907,6 +907,32 @@ TRACE_EVENT(ext4_mballoc_free,
+ 		  __entry->result_len, __entry->result_logical)
+ );
+ 
++TRACE_EVENT(ext4_forget,
++	TP_PROTO(struct inode *inode, int is_metadata, __u64 block),
++
++	TP_ARGS(inode, is_metadata, block),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	umode_t, mode			)
++		__field(	int,	is_metadata		)
++		__field(	__u64,	block			)
++	),
++
++	TP_fast_assign(
++		__entry->dev	= inode->i_sb->s_dev;
++		__entry->ino	= inode->i_ino;
++		__entry->mode	= inode->i_mode;
++		__entry->is_metadata = is_metadata;
++		__entry->block	= block;
++	),
++
++	TP_printk("dev %s ino %lu mode %d is_metadata %d block %llu",
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++		  __entry->mode, __entry->is_metadata, __entry->block)
++);
++
+ #endif /* _TRACE_EXT4_H */
+ 
+ /* This part must be outside protection */

commit cf40db137cc2b2a1b3f6850247ac2b181d9d3847
+Author: Theodore Ts'o 
+Date:   Sun Nov 22 21:00:01 2009 -0500
+
+    ext4: remove failed journal checksum check
+    
+    Now that we are checking for failed journal checksums in the jbd2
+    layer, we don't need to check in the ext4 mount path --- since a
+    checksum fail will result in ext4_load_journal() returning an error,
+    causing the file system to refuse to be mounted until e2fsck can deal
+    with the problem.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 8662b2e6e9f9..04c66907b2fe 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2721,26 +2721,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	    EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)) {
+ 		if (ext4_load_journal(sb, es, journal_devnum))
+ 			goto failed_mount3;
+-		if (!(sb->s_flags & MS_RDONLY) &&
+-		    EXT4_SB(sb)->s_journal->j_failed_commit) {
+-			ext4_msg(sb, KERN_CRIT, "error: "
+-			       "ext4_fill_super: Journal transaction "
+-			       "%u is corrupt",
+-			       EXT4_SB(sb)->s_journal->j_failed_commit);
+-			if (test_opt(sb, ERRORS_RO)) {
+-				ext4_msg(sb, KERN_CRIT,
+-				       "Mounting filesystem read-only");
+-				sb->s_flags |= MS_RDONLY;
+-				EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
+-				es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
+-			}
+-			if (test_opt(sb, ERRORS_PANIC)) {
+-				EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
+-				es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
+-				ext4_commit_super(sb, 1);
+-				goto failed_mount4;
+-			}
+-		}
+ 	} else if (test_opt(sb, NOLOAD) && !(sb->s_flags & MS_RDONLY) &&
+ 	      EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)) {
+ 		ext4_msg(sb, KERN_ERR, "required journal recovery "

commit e6a47428de84e19fda52f21ab73fde2906c40d09
+Author: Theodore Ts'o 
+Date:   Sun Nov 15 15:31:37 2009 -0500
+
+    jbd2: don't wipe the journal on a failed journal checksum
+    
+    If there is a failed journal checksum, don't reset the journal.  This
+    allows for userspace programs to decide how to recover from this
+    situation.  It may be that ignoring the journal checksum failure might
+    be a better way of recovering the file system.  Once we add per-block
+    checksums, we can definitely do better.  Until then, a system
+    administrator can try backing up the file system image (or taking a
+    snapshot) and and trying to determine experimentally whether ignoring
+    the checksum failure or aborting the journal replay results in less
+    data loss.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@kernel.org
+
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index fed85388ee86..af60d98ddd22 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -1248,6 +1248,13 @@ int jbd2_journal_load(journal_t *journal)
+ 	if (jbd2_journal_recover(journal))
+ 		goto recovery_error;
+ 
++	if (journal->j_failed_commit) {
++		printk(KERN_ERR "JBD2: journal transaction %u on %s "
++		       "is corrupt.\n", journal->j_failed_commit,
++		       journal->j_devname);
++		return -EIO;
++	}
++
+ 	/* OK, we've finished with the dynamic journal bits:
+ 	 * reinitialise the dynamic contents of the superblock in memory
+ 	 * and reset them on disk. */

commit 567f3e9a70d71e5c9be03701b8578be77857293b
+Author: Theodore Ts'o 
+Date:   Sat Nov 14 08:19:05 2009 -0500
+
+    ext4: plug a buffer_head leak in an error path of ext4_iget()
+    
+    One of the invalid error paths in ext4_iget() forgot to brelse() the
+    inode buffer head.  Fix it by adding a brelse() in the common error
+    return path, which also simplifies function.
+    
+    Thanks to Andi Kleen  reporting the problem.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 2c8caa51addb..554c6798597c 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4781,7 +4781,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 	struct ext4_iloc iloc;
+ 	struct ext4_inode *raw_inode;
+ 	struct ext4_inode_info *ei;
+-	struct buffer_head *bh;
+ 	struct inode *inode;
+ 	long ret;
+ 	int block;
+@@ -4793,11 +4792,11 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 		return inode;
+ 
+ 	ei = EXT4_I(inode);
++	iloc.bh = 0;
+ 
+ 	ret = __ext4_get_inode_loc(inode, &iloc, 0);
+ 	if (ret < 0)
+ 		goto bad_inode;
+-	bh = iloc.bh;
+ 	raw_inode = ext4_raw_inode(&iloc);
+ 	inode->i_mode = le16_to_cpu(raw_inode->i_mode);
+ 	inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low);
+@@ -4820,7 +4819,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 		if (inode->i_mode == 0 ||
+ 		    !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) {
+ 			/* this inode is deleted */
+-			brelse(bh);
+ 			ret = -ESTALE;
+ 			goto bad_inode;
+ 		}
+@@ -4852,7 +4850,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 		ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize);
+ 		if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize >
+ 		    EXT4_INODE_SIZE(inode->i_sb)) {
+-			brelse(bh);
+ 			ret = -EIO;
+ 			goto bad_inode;
+ 		}
+@@ -4905,10 +4902,8 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 		/* Validate block references which are part of inode */
+ 		ret = ext4_check_inode_blockref(inode);
+ 	}
+-	if (ret) {
+-		brelse(bh);
++	if (ret)
+ 		goto bad_inode;
+-	}
+ 
+ 	if (S_ISREG(inode->i_mode)) {
+ 		inode->i_op = &ext4_file_inode_operations;
+@@ -4936,7 +4931,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 			init_special_inode(inode, inode->i_mode,
+ 			   new_decode_dev(le32_to_cpu(raw_inode->i_block[1])));
+ 	} else {
+-		brelse(bh);
+ 		ret = -EIO;
+ 		ext4_error(inode->i_sb, __func__,
+ 			   "bogus i_mode (%o) for inode=%lu",
+@@ -4949,6 +4943,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 	return inode;
+ 
+ bad_inode:
++	brelse(iloc.bh);
+ 	iget_failed(inode);
+ 	return ERR_PTR(ret);
+ }

commit 503358ae01b70ce6909d19dd01287093f6b6271c
+Author: Theodore Ts'o 
+Date:   Mon Nov 23 07:24:46 2009 -0500
+
+    ext4: avoid divide by zero when trying to mount a corrupted file system
+    
+    If s_log_groups_per_flex is greater than 31, then groups_per_flex will
+    will overflow and cause a divide by zero error.  This can cause kernel
+    BUG if such a file system is mounted.
+    
+    Thanks to Nageswara R Sastry for analyzing the failure and providing
+    an initial patch.
+    
+    http://bugzilla.kernel.org/show_bug.cgi?id=14287
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index d4ca92aab514..8662b2e6e9f9 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1673,14 +1673,14 @@ static int ext4_fill_flex_info(struct super_block *sb)
+ 	size_t size;
+ 	int i;
+ 
+-	if (!sbi->s_es->s_log_groups_per_flex) {
++	sbi->s_log_groups_per_flex = sbi->s_es->s_log_groups_per_flex;
++	groups_per_flex = 1 << sbi->s_log_groups_per_flex;
++
++	if (groups_per_flex < 2) {
+ 		sbi->s_log_groups_per_flex = 0;
+ 		return 1;
+ 	}
+ 
+-	sbi->s_log_groups_per_flex = sbi->s_es->s_log_groups_per_flex;
+-	groups_per_flex = 1 << sbi->s_log_groups_per_flex;
+-
+ 	/* We allocate both existing and potentially added groups */
+ 	flex_group_count = ((sbi->s_groups_count + groups_per_flex - 1) +
+ 			((le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) + 1) <<

commit 2de770a406b06dfc619faabbf5d85c835ed3f2e1
+Author: Theodore Ts'o 
+Date:   Mon Nov 23 07:25:49 2009 -0500
+
+    ext4: fix potential buffer head leak when add_dirent_to_buf() returns ENOSPC
+    
+    Previously add_dirent_to_buf() did not free its passed-in buffer head
+    in the case of ENOSPC, since in some cases the caller still needed it.
+    However, this led to potential buffer head leaks since not all callers
+    dealt with this correctly.  Fix this by making simplifying the freeing
+    convention; now add_dirent_to_buf() *never* frees the passed-in buffer
+    head, and leaves that to the responsibility of its caller.  This makes
+    things cleaner and easier to prove that the code is neither leaking
+    buffer heads or calling brelse() one time too many.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Curt Wohlgemuth 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 6d2c1b897fc7..fde08c919d12 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1292,9 +1292,6 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
+  * add_dirent_to_buf will attempt search the directory block for
+  * space.  It will return -ENOSPC if no space is available, and -EIO
+  * and -EEXIST if directory entry already exists.
+- *
+- * NOTE!  bh is NOT released in the case where ENOSPC is returned.  In
+- * all other cases bh is released.
+  */
+ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
+ 			     struct inode *inode, struct ext4_dir_entry_2 *de,
+@@ -1315,14 +1312,10 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
+ 		top = bh->b_data + blocksize - reclen;
+ 		while ((char *) de <= top) {
+ 			if (!ext4_check_dir_entry("ext4_add_entry", dir, de,
+-						  bh, offset)) {
+-				brelse(bh);
++						  bh, offset))
+ 				return -EIO;
+-			}
+-			if (ext4_match(namelen, name, de)) {
+-				brelse(bh);
++			if (ext4_match(namelen, name, de))
+ 				return -EEXIST;
+-			}
+ 			nlen = EXT4_DIR_REC_LEN(de->name_len);
+ 			rlen = ext4_rec_len_from_disk(de->rec_len, blocksize);
+ 			if ((de->inode? rlen - nlen: rlen) >= reclen)
+@@ -1337,7 +1330,6 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
+ 	err = ext4_journal_get_write_access(handle, bh);
+ 	if (err) {
+ 		ext4_std_error(dir->i_sb, err);
+-		brelse(bh);
+ 		return err;
+ 	}
+ 
+@@ -1377,7 +1369,6 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
+ 	err = ext4_handle_dirty_metadata(handle, dir, bh);
+ 	if (err)
+ 		ext4_std_error(dir->i_sb, err);
+-	brelse(bh);
+ 	return 0;
+ }
+ 
+@@ -1471,7 +1462,9 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
+ 	if (!(de))
+ 		return retval;
+ 
+-	return add_dirent_to_buf(handle, dentry, inode, de, bh);
++	retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
++	brelse(bh);
++	return retval;
+ }
+ 
+ /*
+@@ -1514,8 +1507,10 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
+ 		if(!bh)
+ 			return retval;
+ 		retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh);
+-		if (retval != -ENOSPC)
++		if (retval != -ENOSPC) {
++			brelse(bh);
+ 			return retval;
++		}
+ 
+ 		if (blocks == 1 && !dx_fallback &&
+ 		    EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX))
+@@ -1528,7 +1523,9 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
+ 	de = (struct ext4_dir_entry_2 *) bh->b_data;
+ 	de->inode = 0;
+ 	de->rec_len = ext4_rec_len_to_disk(blocksize, blocksize);
+-	return add_dirent_to_buf(handle, dentry, inode, de, bh);
++	retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
++	brelse(bh);
++	return retval;
+ }
+ 
+ /*
+@@ -1561,10 +1558,8 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+ 		goto journal_error;
+ 
+ 	err = add_dirent_to_buf(handle, dentry, inode, NULL, bh);
+-	if (err != -ENOSPC) {
+-		bh = NULL;
++	if (err != -ENOSPC)
+ 		goto cleanup;
+-	}
+ 
+ 	/* Block full, should compress but for now just split */
+ 	dxtrace(printk(KERN_DEBUG "using %u of %u node entries\n",
+@@ -1657,7 +1652,6 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+ 	if (!de)
+ 		goto cleanup;
+ 	err = add_dirent_to_buf(handle, dentry, inode, de, bh);
+-	bh = NULL;
+ 	goto cleanup;
+ 
+ journal_error:

commit 1e424a348303694fabdf8b1efbfcb1a892dfa63a
+Author: Theodore Ts'o 
+Date:   Sun Nov 8 15:45:44 2009 -0500
+
+    ext4: partial revert to fix double brelse WARNING()
+    
+    This is a partial revert of commit 6487a9d (only the changes made to
+    fs/ext4/namei.c), since it is causing the following brelse()
+    double-free warning when running fsstress on a file system with 1k
+    blocksize and we run into a block allocation failure while converting
+    a single-block directory to a multi-block hash-tree indexed directory.
+    
+    WARNING: at fs/buffer.c:1197 __brelse+0x2e/0x33()
+    Hardware name:
+    VFS: brelse: Trying to free free buffer
+    Modules linked in:
+    Pid: 2226, comm: jbd2/sdd-8 Not tainted 2.6.32-rc6-00577-g0003f55 #101
+    Call Trace:
+     [] warn_slowpath_common+0x65/0x95
+     [] warn_slowpath_fmt+0x29/0x2c
+     [] __brelse+0x2e/0x33
+     [] jbd2_journal_refile_buffer+0x67/0x6c
+     [] jbd2_journal_commit_transaction+0x319/0x14d8
+     [] ? try_to_del_timer_sync+0x58/0x60
+     [] ? sched_clock_cpu+0x12a/0x13e
+     [] ? trace_hardirqs_off+0xb/0xd
+     [] ? cpu_clock+0x3f/0x5b
+     [] ? lock_release_holdtime+0x36/0x137
+     [] ? _spin_unlock_irqrestore+0x44/0x51
+     [] ? trace_hardirqs_on_caller+0x103/0x124
+     [] ? trace_hardirqs_on+0xb/0xd
+     [] ? try_to_del_timer_sync+0x58/0x60
+     [] kjournald2+0x11a/0x310
+     [] ? autoremove_wake_function+0x0/0x38
+     [] ? kjournald2+0x0/0x310
+     [] kthread+0x66/0x6b
+     [] ? kthread+0x0/0x6b
+     [] kernel_thread_helper+0x7/0x10
+    ---[ end trace 5579351b86af61e3 ]---
+    
+    Commit 6487a9d was an attempt some buffer head leaks in an ENOSPC
+    error path, but in some cases it actually results in an excess ENOSPC,
+    as shown above.  Fixing this means cleaning up who is responsible for
+    releasing the buffer heads from the callee to the caller of
+    add_dirent_to_buf().
+    
+    Since that's a relatively complex change, and we're late in the rcX
+    development cycle, I'm reverting this now, and holding back a more
+    complete fix until after 2.6.32 ships.  We've lived with this
+    buffer_head leak on ENOSPC in ext3 and ext4 for a very long time; a
+    few more months won't kill us.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Curt Wohlgemuth 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 7c8fe80bacdd..6d2c1b897fc7 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1518,12 +1518,8 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
+ 			return retval;
+ 
+ 		if (blocks == 1 && !dx_fallback &&
+-		    EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) {
+-			retval = make_indexed_dir(handle, dentry, inode, bh);
+-			if (retval == -ENOSPC)
+-				brelse(bh);
+-			return retval;
+-		}
++		    EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX))
++			return make_indexed_dir(handle, dentry, inode, bh);
+ 		brelse(bh);
+ 	}
+ 	bh = ext4_append(handle, dir, &block, &retval);
+@@ -1532,10 +1528,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
+ 	de = (struct ext4_dir_entry_2 *) bh->b_data;
+ 	de->inode = 0;
+ 	de->rec_len = ext4_rec_len_to_disk(blocksize, blocksize);
+-	retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
+-	if (retval == -ENOSPC)
+-		brelse(bh);
+-	return retval;
++	return add_dirent_to_buf(handle, dentry, inode, de, bh);
+ }
+ 
+ /*
+@@ -1664,8 +1657,7 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+ 	if (!de)
+ 		goto cleanup;
+ 	err = add_dirent_to_buf(handle, dentry, inode, de, bh);
+-	if (err != -ENOSPC)
+-		bh = NULL;
++	bh = NULL;
+ 	goto cleanup;
+ 
+ journal_error:

commit 181a5336d6cc836f05507410d66988c483ad0154
+Author: Andy Lutomirski 
+Date:   Tue Oct 13 10:40:52 2009 -0700
+
+    drm/i915: Fix render reclock availability detection.
+    
+    If the device didn't support EDP, we would bail out too soon.
+    
+    Signed-off-by: Andy Lutomirski 
+    [anholt: Pulled this patch out of the patch for adding quirks to
+    enable reclocking.]
+    Signed-off-by: Eric Anholt 
+
+diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
+index 4337414846b6..96cd256e60e6 100644
+--- a/drivers/gpu/drm/i915/intel_bios.c
++++ b/drivers/gpu/drm/i915/intel_bios.c
+@@ -351,20 +351,18 @@ parse_driver_features(struct drm_i915_private *dev_priv,
+ 	struct drm_device *dev = dev_priv->dev;
+ 	struct bdb_driver_features *driver;
+ 
+-	/* set default for chips without eDP */
+-	if (!SUPPORTS_EDP(dev)) {
+-		dev_priv->edp_support = 0;
+-		return;
+-	}
+-
+ 	driver = find_section(bdb, BDB_DRIVER_FEATURES);
+ 	if (!driver)
+ 		return;
+ 
+-	if (driver->lvds_config == BDB_DRIVER_FEATURE_EDP)
++	if (driver && SUPPORTS_EDP(dev) &&
++	    driver->lvds_config == BDB_DRIVER_FEATURE_EDP) {
+ 		dev_priv->edp_support = 1;
++	} else {
++		dev_priv->edp_support = 0;
++	}
+ 
+-	if (driver->dual_frequency)
++	if (driver && driver->dual_frequency)
+ 		dev_priv->render_reclock_avail = true;
+ }
+ 

commit 96ec2e0a719fd61791dd2b0dd01325c5d20e1233
+Author: Theodore Ts'o 
+Date:   Wed Sep 16 11:21:13 2009 -0400
+
+    ext3: Don't update superblock write time when filesystem is read-only
+    
+    This avoids updating the superblock write time when we are mounting
+    the root file system read/only but we need to replay the journal; at
+    that point, for people who are east of GMT and who make their clock
+    tick in localtime for Windows bug-for-bug compatibility, and this will
+    cause e2fsck to complain and force a full file system check.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Jan Kara 
+
+diff --git a/fs/ext3/super.c b/fs/ext3/super.c
+index 72743d360509..7a520a862f49 100644
+--- a/fs/ext3/super.c
++++ b/fs/ext3/super.c
+@@ -2321,7 +2321,18 @@ static int ext3_commit_super(struct super_block *sb,
+ 
+ 	if (!sbh)
+ 		return error;
+-	es->s_wtime = cpu_to_le32(get_seconds());
++	/*
++	 * If the file system is mounted read-only, don't update the
++	 * superblock write time.  This avoids updating the superblock
++	 * write time when we are mounting the root file system
++	 * read/only but we need to replay the journal; at that point,
++	 * for people who are east of GMT and who make their clock
++	 * tick in localtime for Windows bug-for-bug compatibility,
++	 * the clock is set in the future, and this will cause e2fsck
++	 * to complain and force a full file system check.
++	 */
++	if (!(sb->s_flags & MS_RDONLY))
++		es->s_wtime = cpu_to_le32(get_seconds());
+ 	es->s_free_blocks_count = cpu_to_le32(ext3_count_free_blocks(sb));
+ 	es->s_free_inodes_count = cpu_to_le32(ext3_count_free_inodes(sb));
+ 	BUFFER_TRACE(sbh, "marking dirty");

commit 1f94533d9cd75f6d2826018d54a971b9cc085992
+Author: Theodore Ts'o 
+Date:   Wed Sep 30 22:57:41 2009 -0400
+
+    ext4: fix a BUG_ON crash by checking that page has buffers attached to it
+    
+    In ext4_num_dirty_pages() we were calling page_buffers() before
+    checking to see if the page actually had pages attached to it; this
+    would cause a BUG check crash in the inline function page_buffers().
+    
+    Thanks to Markus Trippelsdorf for reporting this bug.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index ec367bce7215..6e65d0e25ed3 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1146,8 +1146,8 @@ static int check_block_validity(struct inode *inode, const char *msg,
+ }
+ 
+ /*
+- * Return the number of dirty pages in the given inode starting at
+- * page frame idx.
++ * Return the number of contiguous dirty pages in a given inode
++ * starting at page frame idx.
+  */
+ static pgoff_t ext4_num_dirty_pages(struct inode *inode, pgoff_t idx,
+ 				    unsigned int max_pages)
+@@ -1181,15 +1181,15 @@ static pgoff_t ext4_num_dirty_pages(struct inode *inode, pgoff_t idx,
+ 				unlock_page(page);
+ 				break;
+ 			}
+-			head = page_buffers(page);
+-			bh = head;
+-			do {
+-				if (!buffer_delay(bh) &&
+-				    !buffer_unwritten(bh)) {
+-					done = 1;
+-					break;
+-				}
+-			} while ((bh = bh->b_this_page) != head);
++			if (page_has_buffers(page)) {
++				bh = head = page_buffers(page);
++				do {
++					if (!buffer_delay(bh) &&
++					    !buffer_unwritten(bh))
++						done = 1;
++					bh = bh->b_this_page;
++				} while (!done && (bh != head));
++			}
+ 			unlock_page(page);
+ 			if (done)
+ 				break;

commit c1fccc0696bcaff6008c11865091f5ec4b0937ab
+Author: Theodore Ts'o 
+Date:   Wed Sep 30 01:13:55 2009 -0400
+
+    ext4: Fix time encoding with extra epoch bits
+    
+    "Looking at ext4.h, I think the setting of extra time fields forgets to
+    mask the epoch bits so the epoch part overwrites nsec part. The second
+    change is only for coherency (2 -> EXT4_EPOCH_BITS)."
+    
+    Thanks to Damien Guibouret for pointing out this problem.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index c508cf7be75c..984ca0cb38c3 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -525,8 +525,8 @@ struct move_extent {
+ static inline __le32 ext4_encode_extra_time(struct timespec *time)
+ {
+        return cpu_to_le32((sizeof(time->tv_sec) > 4 ?
+-			   time->tv_sec >> 32 : 0) |
+-			   ((time->tv_nsec << 2) & EXT4_NSEC_MASK));
++			   (time->tv_sec >> 32) & EXT4_EPOCH_MASK : 0) |
++                          ((time->tv_nsec << EXT4_EPOCH_BITS) & EXT4_NSEC_MASK));
+ }
+ 
+ static inline void ext4_decode_extra_time(struct timespec *time, __le32 extra)
+@@ -534,7 +534,7 @@ static inline void ext4_decode_extra_time(struct timespec *time, __le32 extra)
+        if (sizeof(time->tv_sec) > 4)
+ 	       time->tv_sec |= (__u64)(le32_to_cpu(extra) & EXT4_EPOCH_MASK)
+ 			       << 32;
+-       time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> 2;
++       time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS;
+ }
+ 
+ #define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode)			       \

commit bf6993276f74d46776f35c45ddef29b981b1d1c6
+Author: Theodore Ts'o 
+Date:   Wed Sep 30 00:32:06 2009 -0400
+
+    jbd2: Use tracepoints for history file
+    
+    The /proc/fs/jbd2//history was maintained manually; by using
+    tracepoints, we can get all of the existing functionality of the /proc
+    file plus extra capabilities thanks to the ftrace infrastructure.  We
+    save memory as a bonus.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
+index 5d70b3e6d49b..ca0f5eb62b20 100644
+--- a/fs/jbd2/checkpoint.c
++++ b/fs/jbd2/checkpoint.c
+@@ -643,6 +643,7 @@ int __jbd2_journal_clean_checkpoint_list(journal_t *journal)
+ 
+ int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
+ {
++	struct transaction_chp_stats_s *stats;
+ 	transaction_t *transaction;
+ 	journal_t *journal;
+ 	int ret = 0;
+@@ -679,6 +680,12 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
+ 
+ 	/* OK, that was the last buffer for the transaction: we can now
+ 	   safely remove this transaction from the log */
++	stats = &transaction->t_chp_stats;
++	if (stats->cs_chp_time)
++		stats->cs_chp_time = jbd2_time_diff(stats->cs_chp_time,
++						    jiffies);
++	trace_jbd2_checkpoint_stats(journal->j_fs_dev->bd_dev,
++				    transaction->t_tid, stats);
+ 
+ 	__jbd2_journal_drop_transaction(journal, transaction);
+ 	kfree(transaction);
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index 26d991ddc1e6..d4cfd6d2779e 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -410,10 +410,10 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	if (commit_transaction->t_synchronous_commit)
+ 		write_op = WRITE_SYNC_PLUG;
+ 	trace_jbd2_commit_locking(journal, commit_transaction);
+-	stats.u.run.rs_wait = commit_transaction->t_max_wait;
+-	stats.u.run.rs_locked = jiffies;
+-	stats.u.run.rs_running = jbd2_time_diff(commit_transaction->t_start,
+-						stats.u.run.rs_locked);
++	stats.run.rs_wait = commit_transaction->t_max_wait;
++	stats.run.rs_locked = jiffies;
++	stats.run.rs_running = jbd2_time_diff(commit_transaction->t_start,
++					      stats.run.rs_locked);
+ 
+ 	spin_lock(&commit_transaction->t_handle_lock);
+ 	while (commit_transaction->t_updates) {
+@@ -486,9 +486,9 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	jbd2_journal_switch_revoke_table(journal);
+ 
+ 	trace_jbd2_commit_flushing(journal, commit_transaction);
+-	stats.u.run.rs_flushing = jiffies;
+-	stats.u.run.rs_locked = jbd2_time_diff(stats.u.run.rs_locked,
+-					       stats.u.run.rs_flushing);
++	stats.run.rs_flushing = jiffies;
++	stats.run.rs_locked = jbd2_time_diff(stats.run.rs_locked,
++					     stats.run.rs_flushing);
+ 
+ 	commit_transaction->t_state = T_FLUSH;
+ 	journal->j_committing_transaction = commit_transaction;
+@@ -523,11 +523,11 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	spin_unlock(&journal->j_state_lock);
+ 
+ 	trace_jbd2_commit_logging(journal, commit_transaction);
+-	stats.u.run.rs_logging = jiffies;
+-	stats.u.run.rs_flushing = jbd2_time_diff(stats.u.run.rs_flushing,
+-						 stats.u.run.rs_logging);
+-	stats.u.run.rs_blocks = commit_transaction->t_outstanding_credits;
+-	stats.u.run.rs_blocks_logged = 0;
++	stats.run.rs_logging = jiffies;
++	stats.run.rs_flushing = jbd2_time_diff(stats.run.rs_flushing,
++					       stats.run.rs_logging);
++	stats.run.rs_blocks = commit_transaction->t_outstanding_credits;
++	stats.run.rs_blocks_logged = 0;
+ 
+ 	J_ASSERT(commit_transaction->t_nr_buffers <=
+ 		 commit_transaction->t_outstanding_credits);
+@@ -695,7 +695,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 				submit_bh(write_op, bh);
+ 			}
+ 			cond_resched();
+-			stats.u.run.rs_blocks_logged += bufs;
++			stats.run.rs_blocks_logged += bufs;
+ 
+ 			/* Force a new descriptor to be generated next
+                            time round the loop. */
+@@ -988,33 +988,30 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	J_ASSERT(commit_transaction->t_state == T_COMMIT);
+ 
+ 	commit_transaction->t_start = jiffies;
+-	stats.u.run.rs_logging = jbd2_time_diff(stats.u.run.rs_logging,
+-						commit_transaction->t_start);
++	stats.run.rs_logging = jbd2_time_diff(stats.run.rs_logging,
++					      commit_transaction->t_start);
+ 
+ 	/*
+-	 * File the transaction for history
++	 * File the transaction statistics
+ 	 */
+-	stats.ts_type = JBD2_STATS_RUN;
+ 	stats.ts_tid = commit_transaction->t_tid;
+-	stats.u.run.rs_handle_count = commit_transaction->t_handle_count;
+-	spin_lock(&journal->j_history_lock);
+-	memcpy(journal->j_history + journal->j_history_cur, &stats,
+-			sizeof(stats));
+-	if (++journal->j_history_cur == journal->j_history_max)
+-		journal->j_history_cur = 0;
++	stats.run.rs_handle_count = commit_transaction->t_handle_count;
++	trace_jbd2_run_stats(journal->j_fs_dev->bd_dev,
++			     commit_transaction->t_tid, &stats.run);
+ 
+ 	/*
+ 	 * Calculate overall stats
+ 	 */
++	spin_lock(&journal->j_history_lock);
+ 	journal->j_stats.ts_tid++;
+-	journal->j_stats.u.run.rs_wait += stats.u.run.rs_wait;
+-	journal->j_stats.u.run.rs_running += stats.u.run.rs_running;
+-	journal->j_stats.u.run.rs_locked += stats.u.run.rs_locked;
+-	journal->j_stats.u.run.rs_flushing += stats.u.run.rs_flushing;
+-	journal->j_stats.u.run.rs_logging += stats.u.run.rs_logging;
+-	journal->j_stats.u.run.rs_handle_count += stats.u.run.rs_handle_count;
+-	journal->j_stats.u.run.rs_blocks += stats.u.run.rs_blocks;
+-	journal->j_stats.u.run.rs_blocks_logged += stats.u.run.rs_blocks_logged;
++	journal->j_stats.run.rs_wait += stats.run.rs_wait;
++	journal->j_stats.run.rs_running += stats.run.rs_running;
++	journal->j_stats.run.rs_locked += stats.run.rs_locked;
++	journal->j_stats.run.rs_flushing += stats.run.rs_flushing;
++	journal->j_stats.run.rs_logging += stats.run.rs_logging;
++	journal->j_stats.run.rs_handle_count += stats.run.rs_handle_count;
++	journal->j_stats.run.rs_blocks += stats.run.rs_blocks;
++	journal->j_stats.run.rs_blocks_logged += stats.run.rs_blocks_logged;
+ 	spin_unlock(&journal->j_history_lock);
+ 
+ 	commit_transaction->t_state = T_FINISHED;
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 977a8dafb76d..761af77491f5 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -676,153 +676,6 @@ struct jbd2_stats_proc_session {
+ 	int max;
+ };
+ 
+-static void *jbd2_history_skip_empty(struct jbd2_stats_proc_session *s,
+-					struct transaction_stats_s *ts,
+-					int first)
+-{
+-	if (ts == s->stats + s->max)
+-		ts = s->stats;
+-	if (!first && ts == s->stats + s->start)
+-		return NULL;
+-	while (ts->ts_type == 0) {
+-		ts++;
+-		if (ts == s->stats + s->max)
+-			ts = s->stats;
+-		if (ts == s->stats + s->start)
+-			return NULL;
+-	}
+-	return ts;
+-
+-}
+-
+-static void *jbd2_seq_history_start(struct seq_file *seq, loff_t *pos)
+-{
+-	struct jbd2_stats_proc_session *s = seq->private;
+-	struct transaction_stats_s *ts;
+-	int l = *pos;
+-
+-	if (l == 0)
+-		return SEQ_START_TOKEN;
+-	ts = jbd2_history_skip_empty(s, s->stats + s->start, 1);
+-	if (!ts)
+-		return NULL;
+-	l--;
+-	while (l) {
+-		ts = jbd2_history_skip_empty(s, ++ts, 0);
+-		if (!ts)
+-			break;
+-		l--;
+-	}
+-	return ts;
+-}
+-
+-static void *jbd2_seq_history_next(struct seq_file *seq, void *v, loff_t *pos)
+-{
+-	struct jbd2_stats_proc_session *s = seq->private;
+-	struct transaction_stats_s *ts = v;
+-
+-	++*pos;
+-	if (v == SEQ_START_TOKEN)
+-		return jbd2_history_skip_empty(s, s->stats + s->start, 1);
+-	else
+-		return jbd2_history_skip_empty(s, ++ts, 0);
+-}
+-
+-static int jbd2_seq_history_show(struct seq_file *seq, void *v)
+-{
+-	struct transaction_stats_s *ts = v;
+-	if (v == SEQ_START_TOKEN) {
+-		seq_printf(seq, "%-4s %-5s %-5s %-5s %-5s %-5s %-5s %-6s %-5s "
+-				"%-5s %-5s %-5s %-5s %-5s\n", "R/C", "tid",
+-				"wait", "run", "lock", "flush", "log", "hndls",
+-				"block", "inlog", "ctime", "write", "drop",
+-				"close");
+-		return 0;
+-	}
+-	if (ts->ts_type == JBD2_STATS_RUN)
+-		seq_printf(seq, "%-4s %-5lu %-5u %-5u %-5u %-5u %-5u "
+-				"%-6lu %-5lu %-5lu\n", "R", ts->ts_tid,
+-				jiffies_to_msecs(ts->u.run.rs_wait),
+-				jiffies_to_msecs(ts->u.run.rs_running),
+-				jiffies_to_msecs(ts->u.run.rs_locked),
+-				jiffies_to_msecs(ts->u.run.rs_flushing),
+-				jiffies_to_msecs(ts->u.run.rs_logging),
+-				ts->u.run.rs_handle_count,
+-				ts->u.run.rs_blocks,
+-				ts->u.run.rs_blocks_logged);
+-	else if (ts->ts_type == JBD2_STATS_CHECKPOINT)
+-		seq_printf(seq, "%-4s %-5lu %48s %-5u %-5lu %-5lu %-5lu\n",
+-				"C", ts->ts_tid, " ",
+-				jiffies_to_msecs(ts->u.chp.cs_chp_time),
+-				ts->u.chp.cs_written, ts->u.chp.cs_dropped,
+-				ts->u.chp.cs_forced_to_close);
+-	else
+-		J_ASSERT(0);
+-	return 0;
+-}
+-
+-static void jbd2_seq_history_stop(struct seq_file *seq, void *v)
+-{
+-}
+-
+-static const struct seq_operations jbd2_seq_history_ops = {
+-	.start  = jbd2_seq_history_start,
+-	.next   = jbd2_seq_history_next,
+-	.stop   = jbd2_seq_history_stop,
+-	.show   = jbd2_seq_history_show,
+-};
+-
+-static int jbd2_seq_history_open(struct inode *inode, struct file *file)
+-{
+-	journal_t *journal = PDE(inode)->data;
+-	struct jbd2_stats_proc_session *s;
+-	int rc, size;
+-
+-	s = kmalloc(sizeof(*s), GFP_KERNEL);
+-	if (s == NULL)
+-		return -ENOMEM;
+-	size = sizeof(struct transaction_stats_s) * journal->j_history_max;
+-	s->stats = kmalloc(size, GFP_KERNEL);
+-	if (s->stats == NULL) {
+-		kfree(s);
+-		return -ENOMEM;
+-	}
+-	spin_lock(&journal->j_history_lock);
+-	memcpy(s->stats, journal->j_history, size);
+-	s->max = journal->j_history_max;
+-	s->start = journal->j_history_cur % s->max;
+-	spin_unlock(&journal->j_history_lock);
+-
+-	rc = seq_open(file, &jbd2_seq_history_ops);
+-	if (rc == 0) {
+-		struct seq_file *m = file->private_data;
+-		m->private = s;
+-	} else {
+-		kfree(s->stats);
+-		kfree(s);
+-	}
+-	return rc;
+-
+-}
+-
+-static int jbd2_seq_history_release(struct inode *inode, struct file *file)
+-{
+-	struct seq_file *seq = file->private_data;
+-	struct jbd2_stats_proc_session *s = seq->private;
+-
+-	kfree(s->stats);
+-	kfree(s);
+-	return seq_release(inode, file);
+-}
+-
+-static struct file_operations jbd2_seq_history_fops = {
+-	.owner		= THIS_MODULE,
+-	.open           = jbd2_seq_history_open,
+-	.read           = seq_read,
+-	.llseek         = seq_lseek,
+-	.release        = jbd2_seq_history_release,
+-};
+-
+ static void *jbd2_seq_info_start(struct seq_file *seq, loff_t *pos)
+ {
+ 	return *pos ? NULL : SEQ_START_TOKEN;
+@@ -839,29 +692,29 @@ static int jbd2_seq_info_show(struct seq_file *seq, void *v)
+ 
+ 	if (v != SEQ_START_TOKEN)
+ 		return 0;
+-	seq_printf(seq, "%lu transaction, each upto %u blocks\n",
++	seq_printf(seq, "%lu transaction, each up to %u blocks\n",
+ 			s->stats->ts_tid,
+ 			s->journal->j_max_transaction_buffers);
+ 	if (s->stats->ts_tid == 0)
+ 		return 0;
+ 	seq_printf(seq, "average: \n  %ums waiting for transaction\n",
+-	    jiffies_to_msecs(s->stats->u.run.rs_wait / s->stats->ts_tid));
++	    jiffies_to_msecs(s->stats->run.rs_wait / s->stats->ts_tid));
+ 	seq_printf(seq, "  %ums running transaction\n",
+-	    jiffies_to_msecs(s->stats->u.run.rs_running / s->stats->ts_tid));
++	    jiffies_to_msecs(s->stats->run.rs_running / s->stats->ts_tid));
+ 	seq_printf(seq, "  %ums transaction was being locked\n",
+-	    jiffies_to_msecs(s->stats->u.run.rs_locked / s->stats->ts_tid));
++	    jiffies_to_msecs(s->stats->run.rs_locked / s->stats->ts_tid));
+ 	seq_printf(seq, "  %ums flushing data (in ordered mode)\n",
+-	    jiffies_to_msecs(s->stats->u.run.rs_flushing / s->stats->ts_tid));
++	    jiffies_to_msecs(s->stats->run.rs_flushing / s->stats->ts_tid));
+ 	seq_printf(seq, "  %ums logging transaction\n",
+-	    jiffies_to_msecs(s->stats->u.run.rs_logging / s->stats->ts_tid));
++	    jiffies_to_msecs(s->stats->run.rs_logging / s->stats->ts_tid));
+ 	seq_printf(seq, "  %lluus average transaction commit time\n",
+ 		   div_u64(s->journal->j_average_commit_time, 1000));
+ 	seq_printf(seq, "  %lu handles per transaction\n",
+-	    s->stats->u.run.rs_handle_count / s->stats->ts_tid);
++	    s->stats->run.rs_handle_count / s->stats->ts_tid);
+ 	seq_printf(seq, "  %lu blocks per transaction\n",
+-	    s->stats->u.run.rs_blocks / s->stats->ts_tid);
++	    s->stats->run.rs_blocks / s->stats->ts_tid);
+ 	seq_printf(seq, "  %lu logged blocks per transaction\n",
+-	    s->stats->u.run.rs_blocks_logged / s->stats->ts_tid);
++	    s->stats->run.rs_blocks_logged / s->stats->ts_tid);
+ 	return 0;
+ }
+ 
+@@ -931,8 +784,6 @@ static void jbd2_stats_proc_init(journal_t *journal)
+ {
+ 	journal->j_proc_entry = proc_mkdir(journal->j_devname, proc_jbd2_stats);
+ 	if (journal->j_proc_entry) {
+-		proc_create_data("history", S_IRUGO, journal->j_proc_entry,
+-				 &jbd2_seq_history_fops, journal);
+ 		proc_create_data("info", S_IRUGO, journal->j_proc_entry,
+ 				 &jbd2_seq_info_fops, journal);
+ 	}
+@@ -941,27 +792,9 @@ static void jbd2_stats_proc_init(journal_t *journal)
+ static void jbd2_stats_proc_exit(journal_t *journal)
+ {
+ 	remove_proc_entry("info", journal->j_proc_entry);
+-	remove_proc_entry("history", journal->j_proc_entry);
+ 	remove_proc_entry(journal->j_devname, proc_jbd2_stats);
+ }
+ 
+-static void journal_init_stats(journal_t *journal)
+-{
+-	int size;
+-
+-	if (!proc_jbd2_stats)
+-		return;
+-
+-	journal->j_history_max = 100;
+-	size = sizeof(struct transaction_stats_s) * journal->j_history_max;
+-	journal->j_history = kzalloc(size, GFP_KERNEL);
+-	if (!journal->j_history) {
+-		journal->j_history_max = 0;
+-		return;
+-	}
+-	spin_lock_init(&journal->j_history_lock);
+-}
+-
+ /*
+  * Management for journal control blocks: functions to create and
+  * destroy journal_t structures, and to initialise and read existing
+@@ -1006,7 +839,7 @@ static journal_t * journal_init_common (void)
+ 		goto fail;
+ 	}
+ 
+-	journal_init_stats(journal);
++	spin_lock_init(&journal->j_history_lock);
+ 
+ 	return journal;
+ fail:
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index 52695d3dfd0b..f1011f7f3d41 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -464,9 +464,9 @@ struct handle_s
+  */
+ struct transaction_chp_stats_s {
+ 	unsigned long		cs_chp_time;
+-	unsigned long		cs_forced_to_close;
+-	unsigned long		cs_written;
+-	unsigned long		cs_dropped;
++	__u32			cs_forced_to_close;
++	__u32			cs_written;
++	__u32			cs_dropped;
+ };
+ 
+ /* The transaction_t type is the guts of the journaling mechanism.  It
+@@ -668,23 +668,16 @@ struct transaction_run_stats_s {
+ 	unsigned long		rs_flushing;
+ 	unsigned long		rs_logging;
+ 
+-	unsigned long		rs_handle_count;
+-	unsigned long		rs_blocks;
+-	unsigned long		rs_blocks_logged;
++	__u32			rs_handle_count;
++	__u32			rs_blocks;
++	__u32			rs_blocks_logged;
+ };
+ 
+ struct transaction_stats_s {
+-	int 			ts_type;
+ 	unsigned long		ts_tid;
+-	union {
+-		struct transaction_run_stats_s run;
+-		struct transaction_chp_stats_s chp;
+-	} u;
++	struct transaction_run_stats_s run;
+ };
+ 
+-#define JBD2_STATS_RUN		1
+-#define JBD2_STATS_CHECKPOINT	2
+-
+ static inline unsigned long
+ jbd2_time_diff(unsigned long start, unsigned long end)
+ {
+@@ -988,12 +981,6 @@ struct journal_s
+ 	/*
+ 	 * Journal statistics
+ 	 */
+-	struct transaction_stats_s *j_history;
+-	int			j_history_max;
+-	int			j_history_cur;
+-	/*
+-	 * Protect the transactions statistics history
+-	 */
+ 	spinlock_t		j_history_lock;
+ 	struct proc_dir_entry	*j_proc_entry;
+ 	struct transaction_stats_s j_stats;
+diff --git a/include/trace/events/jbd2.h b/include/trace/events/jbd2.h
+index b851f0b4701c..3c60b75adb9e 100644
+--- a/include/trace/events/jbd2.h
++++ b/include/trace/events/jbd2.h
+@@ -7,6 +7,9 @@
+ #include 
+ #include 
+ 
++struct transaction_chp_stats_s;
++struct transaction_run_stats_s;
++
+ TRACE_EVENT(jbd2_checkpoint,
+ 
+ 	TP_PROTO(journal_t *journal, int result),
+@@ -162,6 +165,81 @@ TRACE_EVENT(jbd2_submit_inode_data,
+ 		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino)
+ );
+ 
++TRACE_EVENT(jbd2_run_stats,
++	TP_PROTO(dev_t dev, unsigned long tid,
++		 struct transaction_run_stats_s *stats),
++
++	TP_ARGS(dev, tid, stats),
++
++	TP_STRUCT__entry(
++		__field(		dev_t,	dev		)
++		__field(	unsigned long,	tid		)
++		__field(	unsigned long,	wait		)
++		__field(	unsigned long,	running		)
++		__field(	unsigned long,	locked		)
++		__field(	unsigned long,	flushing	)
++		__field(	unsigned long,	logging		)
++		__field(		__u32,	handle_count	)
++		__field(		__u32,	blocks		)
++		__field(		__u32,	blocks_logged	)
++	),
++
++	TP_fast_assign(
++		__entry->dev		= dev;
++		__entry->tid		= tid;
++		__entry->wait		= stats->rs_wait;
++		__entry->running	= stats->rs_running;
++		__entry->locked		= stats->rs_locked;
++		__entry->flushing	= stats->rs_flushing;
++		__entry->logging	= stats->rs_logging;
++		__entry->handle_count	= stats->rs_handle_count;
++		__entry->blocks		= stats->rs_blocks;
++		__entry->blocks_logged	= stats->rs_blocks_logged;
++	),
++
++	TP_printk("dev %s tid %lu wait %u running %u locked %u flushing %u "
++		  "logging %u handle_count %u blocks %u blocks_logged %u",
++		  jbd2_dev_to_name(__entry->dev), __entry->tid,
++		  jiffies_to_msecs(__entry->wait),
++		  jiffies_to_msecs(__entry->running),
++		  jiffies_to_msecs(__entry->locked),
++		  jiffies_to_msecs(__entry->flushing),
++		  jiffies_to_msecs(__entry->logging),
++		  __entry->handle_count, __entry->blocks,
++		  __entry->blocks_logged)
++);
++
++TRACE_EVENT(jbd2_checkpoint_stats,
++	TP_PROTO(dev_t dev, unsigned long tid,
++		 struct transaction_chp_stats_s *stats),
++
++	TP_ARGS(dev, tid, stats),
++
++	TP_STRUCT__entry(
++		__field(		dev_t,	dev		)
++		__field(	unsigned long,	tid		)
++		__field(	unsigned long,	chp_time	)
++		__field(		__u32,	forced_to_close	)
++		__field(		__u32,	written		)
++		__field(		__u32,	dropped		)
++	),
++
++	TP_fast_assign(
++		__entry->dev		= dev;
++		__entry->tid		= tid;
++		__entry->chp_time	= stats->cs_chp_time;
++		__entry->forced_to_close= stats->cs_forced_to_close;
++		__entry->written	= stats->cs_written;
++		__entry->dropped	= stats->cs_dropped;
++	),
++
++	TP_printk("dev %s tid %lu chp_time %u forced_to_close %u "
++		  "written %u dropped %u",
++		  jbd2_dev_to_name(__entry->dev), __entry->tid,
++		  jiffies_to_msecs(__entry->chp_time),
++		  __entry->forced_to_close, __entry->written, __entry->dropped)
++);
++
+ #endif /* _TRACE_JBD2_H */
+ 
+ /* This part must be outside protection */

commit 296c355cd6443d89fa251885a8d78778fe111dc4
+Author: Theodore Ts'o 
+Date:   Wed Sep 30 00:32:42 2009 -0400
+
+    ext4: Use tracepoints for mb_history trace file
+    
+    The /proc/fs/ext4//mb_history was maintained manually, and had a
+    number of problems: it required a largish amount of memory to be
+    allocated for each ext4 filesystem, and the s_mb_history_lock
+    introduced a CPU contention problem.
+    
+    By ripping out the mb_history code and replacing it with ftrace
+    tracepoints, and we get more functionality: timestamps, event
+    filtering, the ability to correlate mballoc history with other ext4
+    tracepoints, etc.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
+index b5aee7838a00..2c48f945546b 100644
+--- a/Documentation/filesystems/proc.txt
++++ b/Documentation/filesystems/proc.txt
+@@ -1113,7 +1113,6 @@ Table 1-12: Files in /proc/fs/ext4/
+ ..............................................................................
+  File            Content                                        
+  mb_groups       details of multiblock allocator buddy cache of free blocks
+- mb_history      multiblock allocation history
+ ..............................................................................
+ 
+ 
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index b491576e11c3..c508cf7be75c 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -65,6 +65,12 @@ typedef __u32 ext4_lblk_t;
+ /* data type for block group number */
+ typedef unsigned int ext4_group_t;
+ 
++/*
++ * Flags used in mballoc's allocation_context flags field.  
++ *
++ * Also used to show what's going on for debugging purposes when the
++ * flag field is exported via the traceport interface
++ */
+ 
+ /* prefer goal again. length */
+ #define EXT4_MB_HINT_MERGE		0x0001
+@@ -971,14 +977,6 @@ struct ext4_sb_info {
+ 	unsigned long s_mb_last_group;
+ 	unsigned long s_mb_last_start;
+ 
+-	/* history to debug policy */
+-	struct ext4_mb_history *s_mb_history;
+-	int s_mb_history_cur;
+-	int s_mb_history_max;
+-	int s_mb_history_num;
+-	spinlock_t s_mb_history_lock;
+-	int s_mb_history_filter;
+-
+ 	/* stats for buddy allocator */
+ 	spinlock_t s_mb_pa_lock;
+ 	atomic_t s_bal_reqs;	/* number of reqs with len > 1 */
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 3e2320e66721..bba12824defa 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2096,207 +2096,6 @@ ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
+ 	return err;
+ }
+ 
+-#ifdef EXT4_MB_HISTORY
+-struct ext4_mb_proc_session {
+-	struct ext4_mb_history *history;
+-	struct super_block *sb;
+-	int start;
+-	int max;
+-};
+-
+-static void *ext4_mb_history_skip_empty(struct ext4_mb_proc_session *s,
+-					struct ext4_mb_history *hs,
+-					int first)
+-{
+-	if (hs == s->history + s->max)
+-		hs = s->history;
+-	if (!first && hs == s->history + s->start)
+-		return NULL;
+-	while (hs->orig.fe_len == 0) {
+-		hs++;
+-		if (hs == s->history + s->max)
+-			hs = s->history;
+-		if (hs == s->history + s->start)
+-			return NULL;
+-	}
+-	return hs;
+-}
+-
+-static void *ext4_mb_seq_history_start(struct seq_file *seq, loff_t *pos)
+-{
+-	struct ext4_mb_proc_session *s = seq->private;
+-	struct ext4_mb_history *hs;
+-	int l = *pos;
+-
+-	if (l == 0)
+-		return SEQ_START_TOKEN;
+-	hs = ext4_mb_history_skip_empty(s, s->history + s->start, 1);
+-	if (!hs)
+-		return NULL;
+-	while (--l && (hs = ext4_mb_history_skip_empty(s, ++hs, 0)) != NULL);
+-	return hs;
+-}
+-
+-static void *ext4_mb_seq_history_next(struct seq_file *seq, void *v,
+-				      loff_t *pos)
+-{
+-	struct ext4_mb_proc_session *s = seq->private;
+-	struct ext4_mb_history *hs = v;
+-
+-	++*pos;
+-	if (v == SEQ_START_TOKEN)
+-		return ext4_mb_history_skip_empty(s, s->history + s->start, 1);
+-	else
+-		return ext4_mb_history_skip_empty(s, ++hs, 0);
+-}
+-
+-static int ext4_mb_seq_history_show(struct seq_file *seq, void *v)
+-{
+-	char buf[25], buf2[25], buf3[25], *fmt;
+-	struct ext4_mb_history *hs = v;
+-
+-	if (v == SEQ_START_TOKEN) {
+-		seq_printf(seq, "%-5s %-8s %-23s %-23s %-23s %-5s "
+-				"%-5s %-2s %-6s %-5s %-5s %-6s\n",
+-			  "pid", "inode", "original", "goal", "result", "found",
+-			   "grps", "cr", "flags", "merge", "tail", "broken");
+-		return 0;
+-	}
+-
+-	if (hs->op == EXT4_MB_HISTORY_ALLOC) {
+-		fmt = "%-5u %-8u %-23s %-23s %-23s %-5u %-5u %-2u "
+-			"0x%04x %-5s %-5u %-6u\n";
+-		sprintf(buf2, "%u/%d/%u@%u", hs->result.fe_group,
+-			hs->result.fe_start, hs->result.fe_len,
+-			hs->result.fe_logical);
+-		sprintf(buf, "%u/%d/%u@%u", hs->orig.fe_group,
+-			hs->orig.fe_start, hs->orig.fe_len,
+-			hs->orig.fe_logical);
+-		sprintf(buf3, "%u/%d/%u@%u", hs->goal.fe_group,
+-			hs->goal.fe_start, hs->goal.fe_len,
+-			hs->goal.fe_logical);
+-		seq_printf(seq, fmt, hs->pid, hs->ino, buf, buf3, buf2,
+-				hs->found, hs->groups, hs->cr, hs->flags,
+-				hs->merged ? "M" : "", hs->tail,
+-				hs->buddy ? 1 << hs->buddy : 0);
+-	} else if (hs->op == EXT4_MB_HISTORY_PREALLOC) {
+-		fmt = "%-5u %-8u %-23s %-23s %-23s\n";
+-		sprintf(buf2, "%u/%d/%u@%u", hs->result.fe_group,
+-			hs->result.fe_start, hs->result.fe_len,
+-			hs->result.fe_logical);
+-		sprintf(buf, "%u/%d/%u@%u", hs->orig.fe_group,
+-			hs->orig.fe_start, hs->orig.fe_len,
+-			hs->orig.fe_logical);
+-		seq_printf(seq, fmt, hs->pid, hs->ino, buf, "", buf2);
+-	} else if (hs->op == EXT4_MB_HISTORY_DISCARD) {
+-		sprintf(buf2, "%u/%d/%u", hs->result.fe_group,
+-			hs->result.fe_start, hs->result.fe_len);
+-		seq_printf(seq, "%-5u %-8u %-23s discard\n",
+-				hs->pid, hs->ino, buf2);
+-	} else if (hs->op == EXT4_MB_HISTORY_FREE) {
+-		sprintf(buf2, "%u/%d/%u", hs->result.fe_group,
+-			hs->result.fe_start, hs->result.fe_len);
+-		seq_printf(seq, "%-5u %-8u %-23s free\n",
+-				hs->pid, hs->ino, buf2);
+-	}
+-	return 0;
+-}
+-
+-static void ext4_mb_seq_history_stop(struct seq_file *seq, void *v)
+-{
+-}
+-
+-static const struct seq_operations ext4_mb_seq_history_ops = {
+-	.start  = ext4_mb_seq_history_start,
+-	.next   = ext4_mb_seq_history_next,
+-	.stop   = ext4_mb_seq_history_stop,
+-	.show   = ext4_mb_seq_history_show,
+-};
+-
+-static int ext4_mb_seq_history_open(struct inode *inode, struct file *file)
+-{
+-	struct super_block *sb = PDE(inode)->data;
+-	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-	struct ext4_mb_proc_session *s;
+-	int rc;
+-	int size;
+-
+-	if (unlikely(sbi->s_mb_history == NULL))
+-		return -ENOMEM;
+-	s = kmalloc(sizeof(*s), GFP_KERNEL);
+-	if (s == NULL)
+-		return -ENOMEM;
+-	s->sb = sb;
+-	size = sizeof(struct ext4_mb_history) * sbi->s_mb_history_max;
+-	s->history = kmalloc(size, GFP_KERNEL);
+-	if (s->history == NULL) {
+-		kfree(s);
+-		return -ENOMEM;
+-	}
+-
+-	spin_lock(&sbi->s_mb_history_lock);
+-	memcpy(s->history, sbi->s_mb_history, size);
+-	s->max = sbi->s_mb_history_max;
+-	s->start = sbi->s_mb_history_cur % s->max;
+-	spin_unlock(&sbi->s_mb_history_lock);
+-
+-	rc = seq_open(file, &ext4_mb_seq_history_ops);
+-	if (rc == 0) {
+-		struct seq_file *m = (struct seq_file *)file->private_data;
+-		m->private = s;
+-	} else {
+-		kfree(s->history);
+-		kfree(s);
+-	}
+-	return rc;
+-
+-}
+-
+-static int ext4_mb_seq_history_release(struct inode *inode, struct file *file)
+-{
+-	struct seq_file *seq = (struct seq_file *)file->private_data;
+-	struct ext4_mb_proc_session *s = seq->private;
+-	kfree(s->history);
+-	kfree(s);
+-	return seq_release(inode, file);
+-}
+-
+-static ssize_t ext4_mb_seq_history_write(struct file *file,
+-				const char __user *buffer,
+-				size_t count, loff_t *ppos)
+-{
+-	struct seq_file *seq = (struct seq_file *)file->private_data;
+-	struct ext4_mb_proc_session *s = seq->private;
+-	struct super_block *sb = s->sb;
+-	char str[32];
+-	int value;
+-
+-	if (count >= sizeof(str)) {
+-		printk(KERN_ERR "EXT4-fs: %s string too long, max %u bytes\n",
+-				"mb_history", (int)sizeof(str));
+-		return -EOVERFLOW;
+-	}
+-
+-	if (copy_from_user(str, buffer, count))
+-		return -EFAULT;
+-
+-	value = simple_strtol(str, NULL, 0);
+-	if (value < 0)
+-		return -ERANGE;
+-	EXT4_SB(sb)->s_mb_history_filter = value;
+-
+-	return count;
+-}
+-
+-static const struct file_operations ext4_mb_seq_history_fops = {
+-	.owner		= THIS_MODULE,
+-	.open		= ext4_mb_seq_history_open,
+-	.read		= seq_read,
+-	.write		= ext4_mb_seq_history_write,
+-	.llseek		= seq_lseek,
+-	.release	= ext4_mb_seq_history_release,
+-};
+-
+ static void *ext4_mb_seq_groups_start(struct seq_file *seq, loff_t *pos)
+ {
+ 	struct super_block *sb = seq->private;
+@@ -2396,82 +2195,6 @@ static const struct file_operations ext4_mb_seq_groups_fops = {
+ 	.release	= seq_release,
+ };
+ 
+-static void ext4_mb_history_release(struct super_block *sb)
+-{
+-	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-
+-	if (sbi->s_proc != NULL) {
+-		remove_proc_entry("mb_groups", sbi->s_proc);
+-		if (sbi->s_mb_history_max)
+-			remove_proc_entry("mb_history", sbi->s_proc);
+-	}
+-	kfree(sbi->s_mb_history);
+-}
+-
+-static void ext4_mb_history_init(struct super_block *sb)
+-{
+-	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-	int i;
+-
+-	if (sbi->s_proc != NULL) {
+-		if (sbi->s_mb_history_max)
+-			proc_create_data("mb_history", S_IRUGO, sbi->s_proc,
+-					 &ext4_mb_seq_history_fops, sb);
+-		proc_create_data("mb_groups", S_IRUGO, sbi->s_proc,
+-				 &ext4_mb_seq_groups_fops, sb);
+-	}
+-
+-	sbi->s_mb_history_cur = 0;
+-	spin_lock_init(&sbi->s_mb_history_lock);
+-	i = sbi->s_mb_history_max * sizeof(struct ext4_mb_history);
+-	sbi->s_mb_history = i ? kzalloc(i, GFP_KERNEL) : NULL;
+-	/* if we can't allocate history, then we simple won't use it */
+-}
+-
+-static noinline_for_stack void
+-ext4_mb_store_history(struct ext4_allocation_context *ac)
+-{
+-	struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);
+-	struct ext4_mb_history h;
+-
+-	if (sbi->s_mb_history == NULL)
+-		return;
+-
+-	if (!(ac->ac_op & sbi->s_mb_history_filter))
+-		return;
+-
+-	h.op = ac->ac_op;
+-	h.pid = current->pid;
+-	h.ino = ac->ac_inode ? ac->ac_inode->i_ino : 0;
+-	h.orig = ac->ac_o_ex;
+-	h.result = ac->ac_b_ex;
+-	h.flags = ac->ac_flags;
+-	h.found = ac->ac_found;
+-	h.groups = ac->ac_groups_scanned;
+-	h.cr = ac->ac_criteria;
+-	h.tail = ac->ac_tail;
+-	h.buddy = ac->ac_buddy;
+-	h.merged = 0;
+-	if (ac->ac_op == EXT4_MB_HISTORY_ALLOC) {
+-		if (ac->ac_g_ex.fe_start == ac->ac_b_ex.fe_start &&
+-				ac->ac_g_ex.fe_group == ac->ac_b_ex.fe_group)
+-			h.merged = 1;
+-		h.goal = ac->ac_g_ex;
+-		h.result = ac->ac_f_ex;
+-	}
+-
+-	spin_lock(&sbi->s_mb_history_lock);
+-	memcpy(sbi->s_mb_history + sbi->s_mb_history_cur, &h, sizeof(h));
+-	if (++sbi->s_mb_history_cur >= sbi->s_mb_history_max)
+-		sbi->s_mb_history_cur = 0;
+-	spin_unlock(&sbi->s_mb_history_lock);
+-}
+-
+-#else
+-#define ext4_mb_history_release(sb)
+-#define ext4_mb_history_init(sb)
+-#endif
+-
+ 
+ /* Create and initialize ext4_group_info data for the given group. */
+ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group,
+@@ -2690,7 +2413,6 @@ int ext4_mb_init(struct super_block *sb, int needs_recovery)
+ 	sbi->s_mb_stats = MB_DEFAULT_STATS;
+ 	sbi->s_mb_stream_request = MB_DEFAULT_STREAM_THRESHOLD;
+ 	sbi->s_mb_order2_reqs = MB_DEFAULT_ORDER2_REQS;
+-	sbi->s_mb_history_filter = EXT4_MB_HISTORY_DEFAULT;
+ 	sbi->s_mb_group_prealloc = MB_DEFAULT_GROUP_PREALLOC;
+ 
+ 	sbi->s_locality_groups = alloc_percpu(struct ext4_locality_group);
+@@ -2708,7 +2430,9 @@ int ext4_mb_init(struct super_block *sb, int needs_recovery)
+ 		spin_lock_init(&lg->lg_prealloc_lock);
+ 	}
+ 
+-	ext4_mb_history_init(sb);
++	if (sbi->s_proc)
++		proc_create_data("mb_groups", S_IRUGO, sbi->s_proc,
++				 &ext4_mb_seq_groups_fops, sb);
+ 
+ 	if (sbi->s_journal)
+ 		sbi->s_journal->j_commit_callback = release_blocks_on_commit;
+@@ -2788,7 +2512,8 @@ int ext4_mb_release(struct super_block *sb)
+ 	}
+ 
+ 	free_percpu(sbi->s_locality_groups);
+-	ext4_mb_history_release(sb);
++	if (sbi->s_proc)
++		remove_proc_entry("mb_groups", sbi->s_proc);
+ 
+ 	return 0;
+ }
+@@ -3274,7 +2999,10 @@ static void ext4_mb_collect_stats(struct ext4_allocation_context *ac)
+ 			atomic_inc(&sbi->s_bal_breaks);
+ 	}
+ 
+-	ext4_mb_store_history(ac);
++	if (ac->ac_op == EXT4_MB_HISTORY_ALLOC)
++		trace_ext4_mballoc_alloc(ac);
++	else
++		trace_ext4_mballoc_prealloc(ac);
+ }
+ 
+ /*
+@@ -3774,7 +3502,6 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh,
+ 	if (ac) {
+ 		ac->ac_sb = sb;
+ 		ac->ac_inode = pa->pa_inode;
+-		ac->ac_op = EXT4_MB_HISTORY_DISCARD;
+ 	}
+ 
+ 	while (bit < end) {
+@@ -3794,7 +3521,7 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh,
+ 			ac->ac_b_ex.fe_start = bit;
+ 			ac->ac_b_ex.fe_len = next - bit;
+ 			ac->ac_b_ex.fe_logical = 0;
+-			ext4_mb_store_history(ac);
++			trace_ext4_mballoc_discard(ac);
+ 		}
+ 
+ 		trace_ext4_mb_release_inode_pa(ac, pa, grp_blk_start + bit,
+@@ -3829,9 +3556,6 @@ ext4_mb_release_group_pa(struct ext4_buddy *e4b,
+ 	ext4_group_t group;
+ 	ext4_grpblk_t bit;
+ 
+-	if (ac)
+-		ac->ac_op = EXT4_MB_HISTORY_DISCARD;
+-
+ 	trace_ext4_mb_release_group_pa(ac, pa);
+ 	BUG_ON(pa->pa_deleted == 0);
+ 	ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit);
+@@ -3846,7 +3570,7 @@ ext4_mb_release_group_pa(struct ext4_buddy *e4b,
+ 		ac->ac_b_ex.fe_start = bit;
+ 		ac->ac_b_ex.fe_len = pa->pa_len;
+ 		ac->ac_b_ex.fe_logical = 0;
+-		ext4_mb_store_history(ac);
++		trace_ext4_mballoc_discard(ac);
+ 	}
+ 
+ 	return 0;
+@@ -4737,7 +4461,6 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
+ 
+ 	ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
+ 	if (ac) {
+-		ac->ac_op = EXT4_MB_HISTORY_FREE;
+ 		ac->ac_inode = inode;
+ 		ac->ac_sb = sb;
+ 	}
+@@ -4804,7 +4527,7 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
+ 		ac->ac_b_ex.fe_group = block_group;
+ 		ac->ac_b_ex.fe_start = bit;
+ 		ac->ac_b_ex.fe_len = count;
+-		ext4_mb_store_history(ac);
++		trace_ext4_mballoc_free(ac);
+ 	}
+ 
+ 	err = ext4_mb_load_buddy(sb, block_group, &e4b);
+diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
+index 14f25f253112..0ca811061bc7 100644
+--- a/fs/ext4/mballoc.h
++++ b/fs/ext4/mballoc.h
+@@ -52,18 +52,8 @@ extern u8 mb_enable_debug;
+ #define mb_debug(n, fmt, a...)
+ #endif
+ 
+-/*
+- * with EXT4_MB_HISTORY mballoc stores last N allocations in memory
+- * and you can monitor it in /proc/fs/ext4//mb_history
+- */
+-#define EXT4_MB_HISTORY
+ #define EXT4_MB_HISTORY_ALLOC		1	/* allocation */
+ #define EXT4_MB_HISTORY_PREALLOC	2	/* preallocated blocks used */
+-#define EXT4_MB_HISTORY_DISCARD		4	/* preallocation discarded */
+-#define EXT4_MB_HISTORY_FREE		8	/* free */
+-
+-#define EXT4_MB_HISTORY_DEFAULT		(EXT4_MB_HISTORY_ALLOC | \
+-					 EXT4_MB_HISTORY_PREALLOC)
+ 
+ /*
+  * How long mballoc can look for a best extent (in found extents)
+@@ -217,22 +207,6 @@ struct ext4_allocation_context {
+ #define AC_STATUS_FOUND		2
+ #define AC_STATUS_BREAK		3
+ 
+-struct ext4_mb_history {
+-	struct ext4_free_extent orig;	/* orig allocation */
+-	struct ext4_free_extent goal;	/* goal allocation */
+-	struct ext4_free_extent result;	/* result allocation */
+-	unsigned pid;
+-	unsigned ino;
+-	__u16 found;	/* how many extents have been found */
+-	__u16 groups;	/* how many groups have been scanned */
+-	__u16 tail;	/* what tail broke some buddy */
+-	__u16 buddy;	/* buddy the tail ^^^ broke */
+-	__u16 flags;
+-	__u8 cr:3;	/* which phase the result extent was found at */
+-	__u8 op:4;
+-	__u8 merged:1;
+-};
+-
+ struct ext4_buddy {
+ 	struct page *bd_buddy_page;
+ 	void *bd_buddy;
+@@ -247,13 +221,6 @@ struct ext4_buddy {
+ #define EXT4_MB_BITMAP(e4b)	((e4b)->bd_bitmap)
+ #define EXT4_MB_BUDDY(e4b)	((e4b)->bd_buddy)
+ 
+-#ifndef EXT4_MB_HISTORY
+-static inline void ext4_mb_store_history(struct ext4_allocation_context *ac)
+-{
+-	return;
+-}
+-#endif
+-
+ #define in_range(b, first, len)	((b) >= (first) && (b) <= (first) + (len) - 1)
+ 
+ static inline ext4_fsblk_t ext4_grp_offs_to_block(struct super_block *sb,
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index e5b206a043a5..12e726a7073f 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -50,13 +50,6 @@
+ #define CREATE_TRACE_POINTS
+ #include 
+ 
+-static int default_mb_history_length = 1000;
+-
+-module_param_named(default_mb_history_length, default_mb_history_length,
+-		   int, 0644);
+-MODULE_PARM_DESC(default_mb_history_length,
+-		 "Default number of entries saved for mb_history");
+-
+ struct proc_dir_entry *ext4_proc_root;
+ static struct kset *ext4_kset;
+ 
+@@ -1079,7 +1072,7 @@ enum {
+ 	Opt_journal_update, Opt_journal_dev,
+ 	Opt_journal_checksum, Opt_journal_async_commit,
+ 	Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
+-	Opt_data_err_abort, Opt_data_err_ignore, Opt_mb_history_length,
++	Opt_data_err_abort, Opt_data_err_ignore,
+ 	Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
+ 	Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
+ 	Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err, Opt_resize,
+@@ -1126,7 +1119,6 @@ static const match_table_t tokens = {
+ 	{Opt_data_writeback, "data=writeback"},
+ 	{Opt_data_err_abort, "data_err=abort"},
+ 	{Opt_data_err_ignore, "data_err=ignore"},
+-	{Opt_mb_history_length, "mb_history_length=%u"},
+ 	{Opt_offusrjquota, "usrjquota="},
+ 	{Opt_usrjquota, "usrjquota=%s"},
+ 	{Opt_offgrpjquota, "grpjquota="},
+@@ -1367,13 +1359,6 @@ static int parse_options(char *options, struct super_block *sb,
+ 		case Opt_data_err_ignore:
+ 			clear_opt(sbi->s_mount_opt, DATA_ERR_ABORT);
+ 			break;
+-		case Opt_mb_history_length:
+-			if (match_int(&args[0], &option))
+-				return 0;
+-			if (option < 0)
+-				return 0;
+-			sbi->s_mb_history_max = option;
+-			break;
+ #ifdef CONFIG_QUOTA
+ 		case Opt_usrjquota:
+ 			qtype = USRQUOTA;
+@@ -2435,7 +2420,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	sbi->s_commit_interval = JBD2_DEFAULT_MAX_COMMIT_AGE * HZ;
+ 	sbi->s_min_batch_time = EXT4_DEF_MIN_BATCH_TIME;
+ 	sbi->s_max_batch_time = EXT4_DEF_MAX_BATCH_TIME;
+-	sbi->s_mb_history_max = default_mb_history_length;
+ 
+ 	set_opt(sbi->s_mount_opt, BARRIER);
+ 
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index 7c6bbb7198a3..b8320256dc5d 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -743,6 +743,169 @@ TRACE_EVENT(ext4_alloc_da_blocks,
+ 		  __entry->data_blocks, __entry->meta_blocks)
+ );
+ 
++TRACE_EVENT(ext4_mballoc_alloc,
++	TP_PROTO(struct ext4_allocation_context *ac),
++
++	TP_ARGS(ac),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	__u16,	found			)
++		__field(	__u16,	groups			)
++		__field(	__u16,	buddy			)
++		__field(	__u16,	flags			)
++		__field(	__u16,	tail			)
++		__field(	__u8,	cr			)
++		__field(	__u32, 	orig_logical		)
++		__field(	  int,	orig_start		)
++		__field(	__u32, 	orig_group		)
++		__field(	  int,	orig_len		)
++		__field(	__u32, 	goal_logical		)
++		__field(	  int,	goal_start		)
++		__field(	__u32, 	goal_group		)
++		__field(	  int,	goal_len		)
++		__field(	__u32, 	result_logical		)
++		__field(	  int,	result_start		)
++		__field(	__u32, 	result_group		)
++		__field(	  int,	result_len		)
++	),
++
++	TP_fast_assign(
++		__entry->dev		= ac->ac_inode->i_sb->s_dev;
++		__entry->ino		= ac->ac_inode->i_ino;
++		__entry->found		= ac->ac_found;
++		__entry->flags		= ac->ac_flags;
++		__entry->groups		= ac->ac_groups_scanned;
++		__entry->buddy		= ac->ac_buddy;
++		__entry->tail		= ac->ac_tail;
++		__entry->cr		= ac->ac_criteria;
++		__entry->orig_logical	= ac->ac_o_ex.fe_logical;
++		__entry->orig_start	= ac->ac_o_ex.fe_start;
++		__entry->orig_group	= ac->ac_o_ex.fe_group;
++		__entry->orig_len	= ac->ac_o_ex.fe_len;
++		__entry->goal_logical	= ac->ac_g_ex.fe_logical;
++		__entry->goal_start	= ac->ac_g_ex.fe_start;
++		__entry->goal_group	= ac->ac_g_ex.fe_group;
++		__entry->goal_len	= ac->ac_g_ex.fe_len;
++		__entry->result_logical	= ac->ac_f_ex.fe_logical;
++		__entry->result_start	= ac->ac_f_ex.fe_start;
++		__entry->result_group	= ac->ac_f_ex.fe_group;
++		__entry->result_len	= ac->ac_f_ex.fe_len;
++	),
++
++	TP_printk("dev %s inode %lu orig %u/%d/%u@%u goal %u/%d/%u@%u "
++		  "result %u/%d/%u@%u blks %u grps %u cr %u flags 0x%04x "
++		  "tail %u broken %u",
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++		  __entry->orig_group, __entry->orig_start,
++		  __entry->orig_len, __entry->orig_logical,
++		  __entry->goal_group, __entry->goal_start,
++		  __entry->goal_len, __entry->goal_logical,
++		  __entry->result_group, __entry->result_start,
++		  __entry->result_len, __entry->result_logical,
++		  __entry->found, __entry->groups, __entry->cr,
++		  __entry->flags, __entry->tail,
++		  __entry->buddy ? 1 << __entry->buddy : 0)
++);
++
++TRACE_EVENT(ext4_mballoc_prealloc,
++	TP_PROTO(struct ext4_allocation_context *ac),
++
++	TP_ARGS(ac),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	__u32, 	orig_logical		)
++		__field(	  int,	orig_start		)
++		__field(	__u32, 	orig_group		)
++		__field(	  int,	orig_len		)
++		__field(	__u32, 	result_logical		)
++		__field(	  int,	result_start		)
++		__field(	__u32, 	result_group		)
++		__field(	  int,	result_len		)
++	),
++
++	TP_fast_assign(
++		__entry->dev		= ac->ac_inode->i_sb->s_dev;
++		__entry->ino		= ac->ac_inode->i_ino;
++		__entry->orig_logical	= ac->ac_o_ex.fe_logical;
++		__entry->orig_start	= ac->ac_o_ex.fe_start;
++		__entry->orig_group	= ac->ac_o_ex.fe_group;
++		__entry->orig_len	= ac->ac_o_ex.fe_len;
++		__entry->result_logical	= ac->ac_b_ex.fe_logical;
++		__entry->result_start	= ac->ac_b_ex.fe_start;
++		__entry->result_group	= ac->ac_b_ex.fe_group;
++		__entry->result_len	= ac->ac_b_ex.fe_len;
++	),
++
++	TP_printk("dev %s inode %lu orig %u/%d/%u@%u result %u/%d/%u@%u",
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++		  __entry->orig_group, __entry->orig_start,
++		  __entry->orig_len, __entry->orig_logical,
++		  __entry->result_group, __entry->result_start,
++		  __entry->result_len, __entry->result_logical)
++);
++
++TRACE_EVENT(ext4_mballoc_discard,
++	TP_PROTO(struct ext4_allocation_context *ac),
++
++	TP_ARGS(ac),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	__u32, 	result_logical		)
++		__field(	  int,	result_start		)
++		__field(	__u32, 	result_group		)
++		__field(	  int,	result_len		)
++	),
++
++	TP_fast_assign(
++		__entry->dev		= ac->ac_inode->i_sb->s_dev;
++		__entry->ino		= ac->ac_inode->i_ino;
++		__entry->result_logical	= ac->ac_b_ex.fe_logical;
++		__entry->result_start	= ac->ac_b_ex.fe_start;
++		__entry->result_group	= ac->ac_b_ex.fe_group;
++		__entry->result_len	= ac->ac_b_ex.fe_len;
++	),
++
++	TP_printk("dev %s inode %lu extent %u/%d/%u@%u ",
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++		  __entry->result_group, __entry->result_start,
++		  __entry->result_len, __entry->result_logical)
++);
++
++TRACE_EVENT(ext4_mballoc_free,
++	TP_PROTO(struct ext4_allocation_context *ac),
++
++	TP_ARGS(ac),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	__u32, 	result_logical		)
++		__field(	  int,	result_start		)
++		__field(	__u32, 	result_group		)
++		__field(	  int,	result_len		)
++	),
++
++	TP_fast_assign(
++		__entry->dev		= ac->ac_inode->i_sb->s_dev;
++		__entry->ino		= ac->ac_inode->i_ino;
++		__entry->result_logical	= ac->ac_b_ex.fe_logical;
++		__entry->result_start	= ac->ac_b_ex.fe_start;
++		__entry->result_group	= ac->ac_b_ex.fe_group;
++		__entry->result_len	= ac->ac_b_ex.fe_len;
++	),
++
++	TP_printk("dev %s inode %lu extent %u/%d/%u@%u ",
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++		  __entry->result_group, __entry->result_start,
++		  __entry->result_len, __entry->result_logical)
++);
++
+ #endif /* _TRACE_EXT4_H */
+ 
+ /* This part must be outside protection */

commit 90576c0b9a0b5323fc4bd7f23f49be0d234f36d1
+Author: Theodore Ts'o 
+Date:   Tue Sep 29 15:51:30 2009 -0400
+
+    ext4, jbd2: Drop unneeded printks at mount and unmount time
+    
+    There are a number of kernel printk's which are printed when an ext4
+    filesystem is mounted and unmounted.  Disable them to economize space
+    in the system logs.  In addition, disabling the mballoc stats by
+    default saves a number of unneeded atomic operations for every block
+    allocation or deallocation.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 10a63096a95a..10539e364283 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -2380,6 +2380,7 @@ void ext4_ext_init(struct super_block *sb)
+ 	 */
+ 
+ 	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
++#if defined(AGGRESSIVE_TEST) || defined(CHECK_BINSEARCH) || defined(EXTENTS_STATS)
+ 		printk(KERN_INFO "EXT4-fs: file extents enabled");
+ #ifdef AGGRESSIVE_TEST
+ 		printk(", aggressive tests");
+@@ -2391,6 +2392,7 @@ void ext4_ext_init(struct super_block *sb)
+ 		printk(", stats");
+ #endif
+ 		printk("\n");
++#endif
+ #ifdef EXTENTS_STATS
+ 		spin_lock_init(&EXT4_SB(sb)->s_ext_stats_lock);
+ 		EXT4_SB(sb)->s_ext_min = 1 << 30;
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index c73d43995b13..3e2320e66721 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2712,8 +2712,6 @@ int ext4_mb_init(struct super_block *sb, int needs_recovery)
+ 
+ 	if (sbi->s_journal)
+ 		sbi->s_journal->j_commit_callback = release_blocks_on_commit;
+-
+-	printk(KERN_INFO "EXT4-fs: mballoc enabled\n");
+ 	return 0;
+ }
+ 
+diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
+index 188d3d709b24..14f25f253112 100644
+--- a/fs/ext4/mballoc.h
++++ b/fs/ext4/mballoc.h
+@@ -84,7 +84,7 @@ extern u8 mb_enable_debug;
+  * with 'ext4_mb_stats' allocator will collect stats that will be
+  * shown at umount. The collecting costs though!
+  */
+-#define MB_DEFAULT_STATS		1
++#define MB_DEFAULT_STATS		0
+ 
+ /*
+  * files smaller than MB_DEFAULT_STREAM_THRESHOLD are served
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 3f7e7010c098..e5b206a043a5 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1673,13 +1673,6 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
+ 			EXT4_INODES_PER_GROUP(sb),
+ 			sbi->s_mount_opt);
+ 
+-	if (EXT4_SB(sb)->s_journal) {
+-		ext4_msg(sb, KERN_INFO, "%s journal on %s",
+-		       EXT4_SB(sb)->s_journal->j_inode ? "internal" :
+-		       "external", EXT4_SB(sb)->s_journal->j_devname);
+-	} else {
+-		ext4_msg(sb, KERN_INFO, "no journal");
+-	}
+ 	return res;
+ }
+ 
+@@ -2885,12 +2878,12 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 			 "available");
+ 	}
+ 
+-	if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
++	if (test_opt(sb, DELALLOC) &&
++	    (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)) {
+ 		ext4_msg(sb, KERN_WARNING, "Ignoring delalloc option - "
+ 			 "requested data journaling mode");
+ 		clear_opt(sbi->s_mount_opt, DELALLOC);
+-	} else if (test_opt(sb, DELALLOC))
+-		ext4_msg(sb, KERN_INFO, "delayed allocation enabled");
++	}
+ 
+ 	err = ext4_setup_system_zone(sb);
+ 	if (err) {
+@@ -3202,9 +3195,7 @@ static int ext4_load_journal(struct super_block *sb,
+ 			return -EINVAL;
+ 	}
+ 
+-	if (journal->j_flags & JBD2_BARRIER)
+-		ext4_msg(sb, KERN_INFO, "barriers enabled");
+-	else
++	if (!(journal->j_flags & JBD2_BARRIER))
+ 		ext4_msg(sb, KERN_INFO, "barriers disabled");
+ 
+ 	if (!really_read_only && test_opt(sb, UPDATE_JOURNAL)) {
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 53b86e16e5fe..977a8dafb76d 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -136,10 +136,6 @@ static int kjournald2(void *arg)
+ 	journal->j_task = current;
+ 	wake_up(&journal->j_wait_done_commit);
+ 
+-	printk(KERN_INFO "kjournald2 starting: pid %d, dev %s, "
+-	       "commit interval %ld seconds\n", current->pid,
+-	       journal->j_devname, journal->j_commit_interval / HZ);
+-
+ 	/*
+ 	 * And now, wait forever for commit wakeup events.
+ 	 */
+@@ -223,7 +219,8 @@ static int jbd2_journal_start_thread(journal_t *journal)
+ {
+ 	struct task_struct *t;
+ 
+-	t = kthread_run(kjournald2, journal, "kjournald2");
++	t = kthread_run(kjournald2, journal, "jbd2/%s",
++			journal->j_devname);
+ 	if (IS_ERR(t))
+ 		return PTR_ERR(t);
+ 
+@@ -1115,7 +1112,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode)
+ 	while ((p = strchr(p, '/')))
+ 		*p = '!';
+ 	p = journal->j_devname + strlen(journal->j_devname);
+-	sprintf(p, ":%lu", journal->j_inode->i_ino);
++	sprintf(p, "-%lu", journal->j_inode->i_ino);
+ 	jbd_debug(1,
+ 		  "journal %p: inode %s/%ld, size %Ld, bits %d, blksize %ld\n",
+ 		  journal, inode->i_sb->s_id, inode->i_ino,

commit f3ce8064b388ccf420012c5a4907aae4f13fe9d0
+Author: Theodore Ts'o 
+Date:   Mon Sep 28 15:58:29 2009 -0400
+
+    ext4: EXT4_IOC_MOVE_EXT: Check for different original and donor inodes first
+    
+    Move the check to make sure the original and donor inodes are
+    different earlier, to avoid a potential deadlock by trying to lock the
+    same inode twice.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
+index 5332fd4c4028..25b6b1457360 100644
+--- a/fs/ext4/move_extent.c
++++ b/fs/ext4/move_extent.c
+@@ -1001,14 +1001,6 @@ mext_check_arguments(struct inode *orig_inode,
+ 		return -EINVAL;
+ 	}
+ 
+-	/* orig and donor should be different file */
+-	if (orig_inode->i_ino == donor_inode->i_ino) {
+-		ext4_debug("ext4 move extent: The argument files should not "
+-			"be same file [ino:orig %lu, donor %lu]\n",
+-			orig_inode->i_ino, donor_inode->i_ino);
+-		return -EINVAL;
+-	}
+-
+ 	/* Ext4 move extent supports only extent based file */
+ 	if (!(EXT4_I(orig_inode)->i_flags & EXT4_EXTENTS_FL)) {
+ 		ext4_debug("ext4 move extent: orig file is not extents "
+@@ -1232,6 +1224,14 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp,
+ 	int block_len_in_page;
+ 	int uninit;
+ 
++	/* orig and donor should be different file */
++	if (orig_inode->i_ino == donor_inode->i_ino) {
++		ext4_debug("ext4 move extent: The argument files should not "
++			"be same file [ino:orig %lu, donor %lu]\n",
++			orig_inode->i_ino, donor_inode->i_ino);
++		return -EINVAL;
++	}
++
+ 	/* protect orig and donor against a truncate */
+ 	ret1 = mext_inode_double_lock(orig_inode, donor_inode);
+ 	if (ret1 < 0)

commit 55138e0bc29c0751e2152df9ad35deea542f29b3
+Author: Theodore Ts'o 
+Date:   Tue Sep 29 13:31:31 2009 -0400
+
+    ext4: Adjust ext4_da_writepages() to write out larger contiguous chunks
+    
+    Work around problems in the writeback code to force out writebacks in
+    larger chunks than just 4mb, which is just too small.  This also works
+    around limitations in the ext4 block allocator, which can't allocate
+    more than 2048 blocks at a time.  So we need to defeat the round-robin
+    characteristics of the writeback code and try to write out as many
+    blocks in one inode before allowing the writeback code to move on to
+    another inode.  We add a a new per-filesystem tunable,
+    max_writeback_mb_bump, which caps this to a default of 128mb per
+    inode.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index e227eea23f05..a58438e18d0b 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -942,6 +942,7 @@ struct ext4_sb_info {
+ 	unsigned int s_mb_stats;
+ 	unsigned int s_mb_order2_reqs;
+ 	unsigned int s_mb_group_prealloc;
++	unsigned int s_max_writeback_mb_bump;
+ 	/* where last allocation was done - for stream allocation */
+ 	unsigned long s_mb_last_group;
+ 	unsigned long s_mb_last_start;
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 5fb72a98ccbe..20e2d704dc2e 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1144,6 +1144,64 @@ static int check_block_validity(struct inode *inode, const char *msg,
+ 	return 0;
+ }
+ 
++/*
++ * Return the number of dirty pages in the given inode starting at
++ * page frame idx.
++ */
++static pgoff_t ext4_num_dirty_pages(struct inode *inode, pgoff_t idx,
++				    unsigned int max_pages)
++{
++	struct address_space *mapping = inode->i_mapping;
++	pgoff_t	index;
++	struct pagevec pvec;
++	pgoff_t num = 0;
++	int i, nr_pages, done = 0;
++
++	if (max_pages == 0)
++		return 0;
++	pagevec_init(&pvec, 0);
++	while (!done) {
++		index = idx;
++		nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
++					      PAGECACHE_TAG_DIRTY,
++					      (pgoff_t)PAGEVEC_SIZE);
++		if (nr_pages == 0)
++			break;
++		for (i = 0; i < nr_pages; i++) {
++			struct page *page = pvec.pages[i];
++			struct buffer_head *bh, *head;
++
++			lock_page(page);
++			if (unlikely(page->mapping != mapping) ||
++			    !PageDirty(page) ||
++			    PageWriteback(page) ||
++			    page->index != idx) {
++				done = 1;
++				unlock_page(page);
++				break;
++			}
++			head = page_buffers(page);
++			bh = head;
++			do {
++				if (!buffer_delay(bh) &&
++				    !buffer_unwritten(bh)) {
++					done = 1;
++					break;
++				}
++			} while ((bh = bh->b_this_page) != head);
++			unlock_page(page);
++			if (done)
++				break;
++			idx++;
++			num++;
++			if (num >= max_pages)
++				break;
++		}
++		pagevec_release(&pvec);
++	}
++	return num;
++}
++
+ /*
+  * The ext4_get_blocks() function tries to look up the requested blocks,
+  * and returns if the blocks are already mapped.
+@@ -2743,8 +2801,10 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 	int no_nrwrite_index_update;
+ 	int pages_written = 0;
+ 	long pages_skipped;
++	unsigned int max_pages;
+ 	int range_cyclic, cycled = 1, io_done = 0;
+-	int needed_blocks, ret = 0, nr_to_writebump = 0;
++	int needed_blocks, ret = 0;
++	long desired_nr_to_write, nr_to_writebump = 0;
+ 	loff_t range_start = wbc->range_start;
+ 	struct ext4_sb_info *sbi = EXT4_SB(mapping->host->i_sb);
+ 
+@@ -2771,16 +2831,6 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 	if (unlikely(sbi->s_mount_flags & EXT4_MF_FS_ABORTED))
+ 		return -EROFS;
+ 
+-	/*
+-	 * Make sure nr_to_write is >= sbi->s_mb_stream_request
+-	 * This make sure small files blocks are allocated in
+-	 * single attempt. This ensure that small files
+-	 * get less fragmented.
+-	 */
+-	if (wbc->nr_to_write < sbi->s_mb_stream_request) {
+-		nr_to_writebump = sbi->s_mb_stream_request - wbc->nr_to_write;
+-		wbc->nr_to_write = sbi->s_mb_stream_request;
+-	}
+ 	if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
+ 		range_whole = 1;
+ 
+@@ -2795,6 +2845,36 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 	} else
+ 		index = wbc->range_start >> PAGE_CACHE_SHIFT;
+ 
++	/*
++	 * This works around two forms of stupidity.  The first is in
++	 * the writeback code, which caps the maximum number of pages
++	 * written to be 1024 pages.  This is wrong on multiple
++	 * levels; different architectues have a different page size,
++	 * which changes the maximum amount of data which gets
++	 * written.  Secondly, 4 megabytes is way too small.  XFS
++	 * forces this value to be 16 megabytes by multiplying
++	 * nr_to_write parameter by four, and then relies on its
++	 * allocator to allocate larger extents to make them
++	 * contiguous.  Unfortunately this brings us to the second
++	 * stupidity, which is that ext4's mballoc code only allocates
++	 * at most 2048 blocks.  So we force contiguous writes up to
++	 * the number of dirty blocks in the inode, or
++	 * sbi->max_writeback_mb_bump whichever is smaller.
++	 */
++	max_pages = sbi->s_max_writeback_mb_bump << (20 - PAGE_CACHE_SHIFT);
++	if (!range_cyclic && range_whole)
++		desired_nr_to_write = wbc->nr_to_write * 8;
++	else
++		desired_nr_to_write = ext4_num_dirty_pages(inode, index,
++							   max_pages);
++	if (desired_nr_to_write > max_pages)
++		desired_nr_to_write = max_pages;
++
++	if (wbc->nr_to_write < desired_nr_to_write) {
++		nr_to_writebump = desired_nr_to_write - wbc->nr_to_write;
++		wbc->nr_to_write = desired_nr_to_write;
++	}
++
+ 	mpd.wbc = wbc;
+ 	mpd.inode = mapping->host;
+ 
+@@ -2914,7 +2994,8 @@ static int ext4_da_writepages(struct address_space *mapping,
+ out_writepages:
+ 	if (!no_nrwrite_index_update)
+ 		wbc->no_nrwrite_index_update = 0;
+-	wbc->nr_to_write -= nr_to_writebump;
++	if (wbc->nr_to_write > nr_to_writebump)
++		wbc->nr_to_write -= nr_to_writebump;
+ 	wbc->range_start = range_start;
+ 	trace_ext4_da_writepages_result(inode, wbc, ret, pages_written);
+ 	return ret;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index df539ba27779..16817737ba52 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2197,6 +2197,7 @@ EXT4_RW_ATTR_SBI_UI(mb_min_to_scan, s_mb_min_to_scan);
+ EXT4_RW_ATTR_SBI_UI(mb_order2_req, s_mb_order2_reqs);
+ EXT4_RW_ATTR_SBI_UI(mb_stream_req, s_mb_stream_request);
+ EXT4_RW_ATTR_SBI_UI(mb_group_prealloc, s_mb_group_prealloc);
++EXT4_RW_ATTR_SBI_UI(max_writeback_mb_bump, s_max_writeback_mb_bump);
+ 
+ static struct attribute *ext4_attrs[] = {
+ 	ATTR_LIST(delayed_allocation_blocks),
+@@ -2210,6 +2211,7 @@ static struct attribute *ext4_attrs[] = {
+ 	ATTR_LIST(mb_order2_req),
+ 	ATTR_LIST(mb_stream_req),
+ 	ATTR_LIST(mb_group_prealloc),
++	ATTR_LIST(max_writeback_mb_bump),
+ 	NULL,
+ };
+ 
+@@ -2679,6 +2681,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	}
+ 
+ 	sbi->s_stripe = ext4_get_stripe_size(sbi);
++	sbi->s_max_writeback_mb_bump = 128;
+ 
+ 	/*
+ 	 * set up enough so that it can read an inode
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index c1bd8f1e8b94..7c6bbb7198a3 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -236,6 +236,7 @@ TRACE_EVENT(ext4_da_writepages,
+ 		__field(	char,	for_kupdate		)
+ 		__field(	char,	for_reclaim		)
+ 		__field(	char,	range_cyclic		)
++		__field(       pgoff_t,	writeback_index		)
+ 	),
+ 
+ 	TP_fast_assign(
+@@ -249,15 +250,17 @@ TRACE_EVENT(ext4_da_writepages,
+ 		__entry->for_kupdate	= wbc->for_kupdate;
+ 		__entry->for_reclaim	= wbc->for_reclaim;
+ 		__entry->range_cyclic	= wbc->range_cyclic;
++		__entry->writeback_index = inode->i_mapping->writeback_index;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu nr_to_write %ld pages_skipped %ld range_start %llu range_end %llu nonblocking %d for_kupdate %d for_reclaim %d range_cyclic %d",
++	TP_printk("dev %s ino %lu nr_to_write %ld pages_skipped %ld range_start %llu range_end %llu nonblocking %d for_kupdate %d for_reclaim %d range_cyclic %d writeback_index %lu",
+ 		  jbd2_dev_to_name(__entry->dev),
+ 		  (unsigned long) __entry->ino, __entry->nr_to_write,
+ 		  __entry->pages_skipped, __entry->range_start,
+ 		  __entry->range_end, __entry->nonblocking,
+ 		  __entry->for_kupdate, __entry->for_reclaim,
+-		  __entry->range_cyclic)
++		  __entry->range_cyclic,
++		  (unsigned long) __entry->writeback_index)
+ );
+ 
+ TRACE_EVENT(ext4_da_write_pages,
+@@ -309,6 +312,7 @@ TRACE_EVENT(ext4_da_writepages_result,
+ 		__field(	char,	encountered_congestion	)
+ 		__field(	char,	more_io			)	
+ 		__field(	char,	no_nrwrite_index_update )
++		__field(       pgoff_t,	writeback_index		)
+ 	),
+ 
+ 	TP_fast_assign(
+@@ -320,14 +324,16 @@ TRACE_EVENT(ext4_da_writepages_result,
+ 		__entry->encountered_congestion	= wbc->encountered_congestion;
+ 		__entry->more_io	= wbc->more_io;
+ 		__entry->no_nrwrite_index_update = wbc->no_nrwrite_index_update;
++		__entry->writeback_index = inode->i_mapping->writeback_index;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu ret %d pages_written %d pages_skipped %ld congestion %d more_io %d no_nrwrite_index_update %d",
++	TP_printk("dev %s ino %lu ret %d pages_written %d pages_skipped %ld congestion %d more_io %d no_nrwrite_index_update %d writeback_index %lu",
+ 		  jbd2_dev_to_name(__entry->dev),
+ 		  (unsigned long) __entry->ino, __entry->ret,
+ 		  __entry->pages_written, __entry->pages_skipped,
+ 		  __entry->encountered_congestion, __entry->more_io,
+-		  __entry->no_nrwrite_index_update)
++		  __entry->no_nrwrite_index_update,
++		  (unsigned long) __entry->writeback_index)
+ );
+ 
+ TRACE_EVENT(ext4_da_write_begin,

commit 71780577306fd1e76c7a92e3b308db624d03adb9
+Author: Theodore Ts'o 
+Date:   Mon Sep 28 00:06:20 2009 -0400
+
+    ext4: Fix hueristic which avoids group preallocation for closed files
+    
+    The hueristic was designed to avoid using locality group preallocation
+    when writing the last segment of a closed file.  Fix it by move
+    setting size to the maximum of size and isize until after we check
+    whether size == isize.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index e9c61896d605..c73d43995b13 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -4189,7 +4189,6 @@ static void ext4_mb_group_or_file(struct ext4_allocation_context *ac)
+ 	size = ac->ac_o_ex.fe_logical + ac->ac_o_ex.fe_len;
+ 	isize = (i_size_read(ac->ac_inode) + ac->ac_sb->s_blocksize - 1)
+ 		>> bsbits;
+-	size = max(size, isize);
+ 
+ 	if ((size == isize) &&
+ 	    !ext4_fs_is_busy(sbi) &&
+@@ -4199,6 +4198,7 @@ static void ext4_mb_group_or_file(struct ext4_allocation_context *ac)
+ 	}
+ 
+ 	/* don't use group allocation for large files */
++	size = max(size, isize);
+ 	if (size >= sbi->s_mb_stream_request) {
+ 		ac->ac_flags |= EXT4_MB_STREAM_ALLOC;
+ 		return;

commit 1693918e0b6988cf5eb93b7da34f30e94360a379
+Author: Theodore Ts'o 
+Date:   Sat Sep 26 17:43:59 2009 -0400
+
+    ext4: Use ext4_msg() for ext4_da_writepage() errors
+    
+    This allows the user to see what filesystem was involved with a
+    particular ext4_da_writepage() error.  Also, use KERN_CRIT which is
+    more appropriate than KERN_EMERG.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 064746fad581..5fb72a98ccbe 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2092,18 +2092,18 @@ static void ext4_da_block_invalidatepages(struct mpage_da_data *mpd,
+ static void ext4_print_free_blocks(struct inode *inode)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+-	printk(KERN_EMERG "Total free blocks count %lld\n",
+-			ext4_count_free_blocks(inode->i_sb));
+-	printk(KERN_EMERG "Free/Dirty block details\n");
+-	printk(KERN_EMERG "free_blocks=%lld\n",
+-			(long long)percpu_counter_sum(&sbi->s_freeblocks_counter));
+-	printk(KERN_EMERG "dirty_blocks=%lld\n",
+-			(long long)percpu_counter_sum(&sbi->s_dirtyblocks_counter));
+-	printk(KERN_EMERG "Block reservation details\n");
+-	printk(KERN_EMERG "i_reserved_data_blocks=%u\n",
+-			EXT4_I(inode)->i_reserved_data_blocks);
+-	printk(KERN_EMERG "i_reserved_meta_blocks=%u\n",
+-			EXT4_I(inode)->i_reserved_meta_blocks);
++	printk(KERN_CRIT "Total free blocks count %lld\n",
++	       ext4_count_free_blocks(inode->i_sb));
++	printk(KERN_CRIT "Free/Dirty block details\n");
++	printk(KERN_CRIT "free_blocks=%lld\n",
++	       (long long) percpu_counter_sum(&sbi->s_freeblocks_counter));
++	printk(KERN_CRIT "dirty_blocks=%lld\n",
++	       (long long) percpu_counter_sum(&sbi->s_dirtyblocks_counter));
++	printk(KERN_CRIT "Block reservation details\n");
++	printk(KERN_CRIT "i_reserved_data_blocks=%u\n",
++	       EXT4_I(inode)->i_reserved_data_blocks);
++	printk(KERN_CRIT "i_reserved_meta_blocks=%u\n",
++	       EXT4_I(inode)->i_reserved_meta_blocks);
+ 	return;
+ }
+ 
+@@ -2189,14 +2189,14 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
+ 		 * writepage and writepages will again try to write
+ 		 * the same.
+ 		 */
+-		printk(KERN_EMERG "%s block allocation failed for inode %lu "
+-				  "at logical offset %llu with max blocks "
+-				  "%zd with error %d\n",
+-				  __func__, mpd->inode->i_ino,
+-				  (unsigned long long)next,
+-				  mpd->b_size >> mpd->inode->i_blkbits, err);
+-		printk(KERN_EMERG "This should not happen.!! "
+-					"Data will be lost\n");
++		ext4_msg(mpd->inode->i_sb, KERN_CRIT,
++			 "delayed block allocation failed for inode %lu at "
++			 "logical offset %llu with max blocks %zd with "
++			 "error %d\n", mpd->inode->i_ino,
++			 (unsigned long long) next,
++			 mpd->b_size >> mpd->inode->i_blkbits, err);
++		printk(KERN_CRIT "This should not happen!!  "
++		       "Data will be lost\n");
+ 		if (err == -ENOSPC) {
+ 			ext4_print_free_blocks(mpd->inode);
+ 		}
+@@ -2822,10 +2822,9 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 		handle = ext4_journal_start(inode, needed_blocks);
+ 		if (IS_ERR(handle)) {
+ 			ret = PTR_ERR(handle);
+-			printk(KERN_CRIT "%s: jbd2_start: "
++			ext4_msg(inode->i_sb, KERN_CRIT, "%s: jbd2_start: "
+ 			       "%ld pages, ino %lu; err %d\n", __func__,
+ 				wbc->nr_to_write, inode->i_ino, ret);
+-			dump_stack();
+ 			goto out_writepages;
+ 		}
+ 
+@@ -2897,9 +2896,10 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 		goto retry;
+ 	}
+ 	if (pages_skipped != wbc->pages_skipped)
+-		printk(KERN_EMERG "This should not happen leaving %s "
+-				"with nr_to_write = %ld ret = %d\n",
+-				__func__, wbc->nr_to_write, ret);
++		ext4_msg(inode->i_sb, KERN_CRIT,
++			 "This should not happen leaving %s "
++			 "with nr_to_write = %ld ret = %d\n",
++			 __func__, wbc->nr_to_write, ret);
+ 
+ 	/* Update index */
+ 	index += pages_written;

commit 5534fb5bb35a62a94e0bd1fa2421f7fb6e894f10
+Author: Theodore Ts'o 
+Date:   Thu Sep 17 09:34:16 2009 -0400
+
+    ext4: Fix the alloc on close after a truncate hueristic
+    
+    In an attempt to avoid doing an unneeded flush after opening a
+    (previously non-existent) file with O_CREAT|O_TRUNC, the code only
+    triggered the hueristic if ei->disksize was non-zero.  Turns out that
+    the VFS doesn't call ->truncate() if the file doesn't exist, and
+    ei->disksize is always zero even if the file previously existed.  So
+    remove the test, since it isn't necessary and in fact disabled the
+    hueristic.
+    
+    Thanks to Clemens Eisserer that he was seeing problems with files
+    written using kwrite and eclipse after sudden crashes caused by a
+    buggy Intel video driver.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 9887a0c562d5..4abd683b963d 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -3973,8 +3973,7 @@ void ext4_truncate(struct inode *inode)
+ 	if (!ext4_can_truncate(inode))
+ 		return;
+ 
+-	if (ei->i_disksize && inode->i_size == 0 &&
+-	    !test_opt(inode->i_sb, NO_AUTO_DA_ALLOC))
++	if (inode->i_size == 0 && !test_opt(inode->i_sb, NO_AUTO_DA_ALLOC))
+ 		ei->i_state |= EXT4_STATE_DA_ALLOC_CLOSE;
+ 
+ 	if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) {

commit fb40ba0d98968bc3454731360363d725b4f1064c
+Author: Theodore Ts'o 
+Date:   Wed Sep 16 19:30:40 2009 -0400
+
+    ext4: Add a tracepoint for ext4_alloc_da_blocks()
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index a5b4ce40cc66..9887a0c562d5 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -3128,6 +3128,8 @@ static void ext4_da_invalidatepage(struct page *page, unsigned long offset)
+  */
+ int ext4_alloc_da_blocks(struct inode *inode)
+ {
++	trace_ext4_alloc_da_blocks(inode);
++
+ 	if (!EXT4_I(inode)->i_reserved_data_blocks &&
+ 	    !EXT4_I(inode)->i_reserved_meta_blocks)
+ 		return 0;
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index 6fe6ce9ee071..c1bd8f1e8b94 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -10,6 +10,9 @@
+ struct ext4_allocation_context;
+ struct ext4_allocation_request;
+ struct ext4_prealloc_space;
++struct ext4_inode_info;
++
++#define EXT4_I(inode) (container_of(inode, struct ext4_inode_info, vfs_inode))
+ 
+ TRACE_EVENT(ext4_free_inode,
+ 	TP_PROTO(struct inode *inode),
+@@ -710,6 +713,30 @@ TRACE_EVENT(ext4_sync_fs,
+ 		  __entry->wait)
+ );
+ 
++TRACE_EVENT(ext4_alloc_da_blocks,
++	TP_PROTO(struct inode *inode),
++
++	TP_ARGS(inode),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field( unsigned int,	data_blocks	)
++		__field( unsigned int,	meta_blocks	)
++	),
++
++	TP_fast_assign(
++		__entry->dev	= inode->i_sb->s_dev;
++		__entry->ino	= inode->i_ino;
++		__entry->data_blocks = EXT4_I(inode)->i_reserved_data_blocks;
++		__entry->meta_blocks = EXT4_I(inode)->i_reserved_meta_blocks;
++	),
++
++	TP_printk("dev %s ino %lu data_blocks %u meta_blocks %u",
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++		  __entry->data_blocks, __entry->meta_blocks)
++);
++
+ #endif /* _TRACE_EXT4_H */
+ 
+ /* This part must be outside protection */

commit 1b9c12f44c1eb614fd3b8822bfe8f1f5d8e53737
+Author: Theodore Ts'o 
+Date:   Thu Sep 17 08:32:22 2009 -0400
+
+    ext4: store EXT4_EXT_MIGRATE in i_state instead of i_flags
+    
+    EXT4_EXT_MIGRATE is only intended to be used for an in-memory flag,
+    and the hex value assigned to it collides with FS_DIRECTIO_FL (which
+    is also stored in i_flags).  There's no reason for the
+    EXT4_EXT_MIGRATE bit to be stored in i_flags, so we switch it to use
+    i_state instead.
+    
+    Cc: "Aneesh Kumar K.V" 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 2a0f75d55fad..84e7f1d00a83 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -268,7 +268,6 @@ struct flex_groups {
+ #define EXT4_TOPDIR_FL			0x00020000 /* Top of directory hierarchies*/
+ #define EXT4_HUGE_FILE_FL               0x00040000 /* Set to each huge file */
+ #define EXT4_EXTENTS_FL			0x00080000 /* Inode uses extents */
+-#define EXT4_EXT_MIGRATE		0x00100000 /* Inode is migrating */
+ #define EXT4_RESERVED_FL		0x80000000 /* reserved for ext4 lib */
+ 
+ #define EXT4_FL_USER_VISIBLE		0x000BDFFF /* User visible flags */
+@@ -306,6 +305,7 @@ static inline __u32 ext4_mask_flags(umode_t mode, __u32 flags)
+ #define EXT4_STATE_XATTR		0x00000004 /* has in-inode xattrs */
+ #define EXT4_STATE_NO_EXPAND		0x00000008 /* No space for expansion */
+ #define EXT4_STATE_DA_ALLOC_CLOSE	0x00000010 /* Alloc DA blks on close */
++#define EXT4_STATE_EXT_MIGRATE		0x00000020 /* Inode is migrating */
+ 
+ /* Used to pass group descriptor data when online resize is done */
+ struct ext4_new_group_input {
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 5a8979259c9a..a5b4ce40cc66 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1255,8 +1255,7 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block,
+ 			 * i_data's format changing.  Force the migrate
+ 			 * to fail by clearing migrate flags
+ 			 */
+-			EXT4_I(inode)->i_flags = EXT4_I(inode)->i_flags &
+-							~EXT4_EXT_MIGRATE;
++			EXT4_I(inode)->i_state &= ~EXT4_STATE_EXT_MIGRATE;
+ 		}
+ 	}
+ 
+@@ -4596,8 +4595,7 @@ static int ext4_do_update_inode(handle_t *handle,
+ 	if (ext4_inode_blocks_set(handle, raw_inode, ei))
+ 		goto out_brelse;
+ 	raw_inode->i_dtime = cpu_to_le32(ei->i_dtime);
+-	/* clear the migrate flag in the raw_inode */
+-	raw_inode->i_flags = cpu_to_le32(ei->i_flags & ~EXT4_EXT_MIGRATE);
++	raw_inode->i_flags = cpu_to_le32(ei->i_flags);
+ 	if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=
+ 	    cpu_to_le32(EXT4_OS_HURD))
+ 		raw_inode->i_file_acl_high =
+diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
+index 05361ad5b80a..bf519f239ae6 100644
+--- a/fs/ext4/migrate.c
++++ b/fs/ext4/migrate.c
+@@ -353,17 +353,16 @@ static int ext4_ext_swap_inode_data(handle_t *handle, struct inode *inode,
+ 
+ 	down_write(&EXT4_I(inode)->i_data_sem);
+ 	/*
+-	 * if EXT4_EXT_MIGRATE is cleared a block allocation
++	 * if EXT4_STATE_EXT_MIGRATE is cleared a block allocation
+ 	 * happened after we started the migrate. We need to
+ 	 * fail the migrate
+ 	 */
+-	if (!(EXT4_I(inode)->i_flags & EXT4_EXT_MIGRATE)) {
++	if (!(EXT4_I(inode)->i_state & EXT4_STATE_EXT_MIGRATE)) {
+ 		retval = -EAGAIN;
+ 		up_write(&EXT4_I(inode)->i_data_sem);
+ 		goto err_out;
+ 	} else
+-		EXT4_I(inode)->i_flags = EXT4_I(inode)->i_flags &
+-							~EXT4_EXT_MIGRATE;
++		EXT4_I(inode)->i_state &= ~EXT4_STATE_EXT_MIGRATE;
+ 	/*
+ 	 * We have the extent map build with the tmp inode.
+ 	 * Now copy the i_data across
+@@ -517,14 +516,15 @@ int ext4_ext_migrate(struct inode *inode)
+ 	 * when we add extents we extent the journal
+ 	 */
+ 	/*
+-	 * Even though we take i_mutex we can still cause block allocation
+-	 * via mmap write to holes. If we have allocated new blocks we fail
+-	 * migrate.  New block allocation will clear EXT4_EXT_MIGRATE flag.
+-	 * The flag is updated with i_data_sem held to prevent racing with
+-	 * block allocation.
++	 * Even though we take i_mutex we can still cause block
++	 * allocation via mmap write to holes. If we have allocated
++	 * new blocks we fail migrate.  New block allocation will
++	 * clear EXT4_STATE_EXT_MIGRATE flag.  The flag is updated
++	 * with i_data_sem held to prevent racing with block
++	 * allocation.
+ 	 */
+ 	down_read((&EXT4_I(inode)->i_data_sem));
+-	EXT4_I(inode)->i_flags = EXT4_I(inode)->i_flags | EXT4_EXT_MIGRATE;
++	EXT4_I(inode)->i_state |= EXT4_STATE_EXT_MIGRATE;
+ 	up_read((&EXT4_I(inode)->i_data_sem));
+ 
+ 	handle = ext4_journal_start(inode, 1);

commit 3661d28615ea580c1db02a972fd4d3898df1cb01
+Author: Theodore Ts'o 
+Date:   Mon Sep 14 22:59:50 2009 -0400
+
+    ext4: Fix include/trace/events/ext4.h to work with Systemtap
+    
+    Using relative pathnames in #include statements interacts badly with
+    SystemTap, since the fs/ext4/*.h header files are not packaged up as
+    part of a distribution kernel's header files.  Since systemtap doesn't
+    use TP_fast_assign(), we can use a blind structure definition and then
+    make sure the needed header files are defined before the ext4 source
+    files #include the trace/events/ext4.h header file.
+    
+    https://bugzilla.redhat.com/show_bug.cgi?id=512478
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 04c693357336..af95dd8ba54b 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -45,6 +45,7 @@
+ #include "ext4_jbd2.h"
+ #include "xattr.h"
+ #include "acl.h"
++#include "mballoc.h"
+ 
+ #define CREATE_TRACE_POINTS
+ #include 
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index 68b53c7ef8a7..6fe6ce9ee071 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -5,10 +5,12 @@
+ #define _TRACE_EXT4_H
+ 
+ #include 
+-#include "../../../fs/ext4/ext4.h"
+-#include "../../../fs/ext4/mballoc.h"
+ #include 
+ 
++struct ext4_allocation_context;
++struct ext4_allocation_request;
++struct ext4_prealloc_space;
++
+ TRACE_EVENT(ext4_free_inode,
+ 	TP_PROTO(struct inode *inode),
+ 

commit 7ad9bb651fc2036ea94bed94da76a4b08959a911
+Author: Theodore Ts'o 
+Date:   Fri Sep 11 16:51:28 2009 -0400
+
+    ext4: Fix initalization of s_flex_groups
+    
+    The s_flex_groups array should have been initialized using atomic_add
+    to sum up the free counts from the block groups that make up a
+    flex_bg.  By using atomic_set, the value of the s_flex_groups array
+    was set to the values of the last block group in the flex_bg.
+    
+    The impact of this bug is that the block and inode allocation
+    algorithms might not pick the best flex_bg for new allocation.
+    
+    Thanks to Damien Guibouret for pointing out this problem!
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 9f6fa3f74629..04c693357336 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1694,12 +1694,12 @@ static int ext4_fill_flex_info(struct super_block *sb)
+ 		gdp = ext4_get_group_desc(sb, i, NULL);
+ 
+ 		flex_group = ext4_flex_group(sbi, i);
+-		atomic_set(&sbi->s_flex_groups[flex_group].free_inodes,
+-			   ext4_free_inodes_count(sb, gdp));
+-		atomic_set(&sbi->s_flex_groups[flex_group].free_blocks,
+-			   ext4_free_blks_count(sb, gdp));
+-		atomic_set(&sbi->s_flex_groups[flex_group].used_dirs,
+-			   ext4_used_dirs_count(sb, gdp));
++		atomic_add(ext4_free_inodes_count(sb, gdp),
++			   &sbi->s_flex_groups[flex_group].free_inodes);
++		atomic_add(ext4_free_blks_count(sb, gdp),
++			   &sbi->s_flex_groups[flex_group].free_blocks);
++		atomic_add(ext4_used_dirs_count(sb, gdp),
++			   &sbi->s_flex_groups[flex_group].used_dirs);
+ 	}
+ 
+ 	return 1;

commit 0e3d2a6313d03413d93327202a60256d1d726fdc
+Author: Theodore Ts'o 
+Date:   Fri Sep 11 09:30:12 2009 -0400
+
+    ext4: Fix async commit mode to be safe by using a barrier
+    
+    Previously the journal_async_commit mount option was equivalent to
+    using barrier=0 (and just as unsafe).  This patch fixes it so that we
+    eliminate the barrier before the commit block (by not using ordered
+    mode), and explicitly issuing an empty barrier bio after writing the
+    commit block.  Because of the journal checksum, it is safe to do this;
+    if the journal blocks are not all written before a power failure, the
+    checksum in the commit block will prevent the last transaction from
+    being replayed.
+    
+    Using the fs_mark benchmark, using journal_async_commit shows a 50%
+    improvement:
+    
+    FSUse%        Count         Size    Files/sec     App Overhead
+         8         1000        10240         30.5            28242
+    
+    vs.
+    
+    FSUse%        Count         Size    Files/sec     App Overhead
+         8         1000        10240         45.8            28620
+    
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index 0df600e9162d..26d991ddc1e6 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -25,6 +25,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ 
+ /*
+@@ -133,8 +134,8 @@ static int journal_submit_commit_record(journal_t *journal,
+ 	bh->b_end_io = journal_end_buffer_io_sync;
+ 
+ 	if (journal->j_flags & JBD2_BARRIER &&
+-		!JBD2_HAS_INCOMPAT_FEATURE(journal,
+-					 JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) {
++	    !JBD2_HAS_INCOMPAT_FEATURE(journal,
++				       JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) {
+ 		set_buffer_ordered(bh);
+ 		barrier_done = 1;
+ 	}
+@@ -706,11 +707,13 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	/* Done it all: now write the commit record asynchronously. */
+ 
+ 	if (JBD2_HAS_INCOMPAT_FEATURE(journal,
+-		JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) {
++				      JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) {
+ 		err = journal_submit_commit_record(journal, commit_transaction,
+ 						 &cbh, crc32_sum);
+ 		if (err)
+ 			__jbd2_journal_abort_hard(journal);
++		if (journal->j_flags & JBD2_BARRIER)
++			blkdev_issue_flush(journal->j_dev, NULL);
+ 	}
+ 
+ 	/*
+@@ -833,7 +836,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	jbd_debug(3, "JBD: commit phase 5\n");
+ 
+ 	if (!JBD2_HAS_INCOMPAT_FEATURE(journal,
+-		JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) {
++				       JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) {
+ 		err = journal_submit_commit_record(journal, commit_transaction,
+ 						&cbh, crc32_sum);
+ 		if (err)

commit 71290b368ad5e1e0b0b300c9d5638490a9fd1a2d
+Author: Theodore Ts'o 
+Date:   Thu Sep 10 17:31:04 2009 -0400
+
+    ext4: Don't update superblock write time when filesystem is read-only
+    
+    This avoids updating the superblock write time when we are mounting
+    the root file system read/only but we need to replay the journal; at
+    that point, for people who are east of GMT and who make their clock
+    tick in localtime for Windows bug-for-bug compatibility, and this will
+    cause e2fsck to complain and force a full file system check.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index f1815d3bcfd5..9f6fa3f74629 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3222,7 +3222,18 @@ static int ext4_commit_super(struct super_block *sb, int sync)
+ 		clear_buffer_write_io_error(sbh);
+ 		set_buffer_uptodate(sbh);
+ 	}
+-	es->s_wtime = cpu_to_le32(get_seconds());
++	/*
++	 * If the file system is mounted read-only, don't update the
++	 * superblock write time.  This avoids updating the superblock
++	 * write time when we are mounting the root file system
++	 * read/only but we need to replay the journal; at that point,
++	 * for people who are east of GMT and who make their clock
++	 * tick in localtime for Windows bug-for-bug compatibility,
++	 * the clock is set in the future, and this will cause e2fsck
++	 * to complain and force a full file system check.
++	 */
++	if (!(sb->s_flags & MS_RDONLY))
++		es->s_wtime = cpu_to_le32(get_seconds());
+ 	es->s_kbytes_written =
+ 		cpu_to_le64(EXT4_SB(sb)->s_kbytes_written + 
+ 			    ((part_stat_read(sb->s_bdev->bd_part, sectors[1]) -

commit fe188c0e084bdf3038dc0ac963c21d764f53f7da
+Author: Theodore Ts'o 
+Date:   Sat Sep 12 13:41:55 2009 -0400
+
+    ext4: Assure that metadata blocks are written during fsync in no journal mode
+    
+    When there is no journal present, we must attach buffer heads
+    associated with extent tree and indirect blocks to the inode's
+    mapping->private_list via mark_buffer_dirty_inode() so that
+    ext4_sync_file() --- which is called to service fsync() and
+    fdatasync() system calls --- can write out the inode's metadata blocks
+    by calling sync_mapping_buffers().
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
+index ecb9ca455fd5..6a9409920dee 100644
+--- a/fs/ext4/ext4_jbd2.c
++++ b/fs/ext4/ext4_jbd2.c
+@@ -89,7 +89,10 @@ int __ext4_handle_dirty_metadata(const char *where, handle_t *handle,
+ 			ext4_journal_abort_handle(where, __func__, bh,
+ 						  handle, err);
+ 	} else {
+-		mark_buffer_dirty(bh);
++		if (inode && bh)
++			mark_buffer_dirty_inode(bh, inode);
++		else
++			mark_buffer_dirty(bh);
+ 		if (inode && inode_needs_sync(inode)) {
+ 			sync_dirty_buffer(bh);
+ 			if (buffer_req(bh) && !buffer_uptodate(bh)) {
+diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
+index ab418c0f502d..07475740b512 100644
+--- a/fs/ext4/fsync.c
++++ b/fs/ext4/fsync.c
+@@ -50,7 +50,7 @@ int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync)
+ {
+ 	struct inode *inode = dentry->d_inode;
+ 	journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
+-	int ret = 0;
++	int err, ret = 0;
+ 
+ 	J_ASSERT(ext4_journal_current_handle() == NULL);
+ 
+@@ -79,6 +79,9 @@ int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync)
+ 		goto out;
+ 	}
+ 
++	if (!journal)
++		ret = sync_mapping_buffers(inode->i_mapping);
++
+ 	if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
+ 		goto out;
+ 
+@@ -91,7 +94,9 @@ int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync)
+ 			.sync_mode = WB_SYNC_ALL,
+ 			.nr_to_write = 0, /* sys_fsync did this */
+ 		};
+-		ret = sync_inode(inode, &wbc);
++		err = sync_inode(inode, &wbc);
++		if (ret == 0)
++			ret = err;
+ 	}
+ out:
+ 	if (journal && (journal->j_flags & JBD2_BARRIER))

commit c7acb4c16646943180bd221c167a077e0a084f9c
+Author: Theodore Ts'o 
+Date:   Wed Sep 9 21:32:41 2009 -0400
+
+    ext4: Use bforget() in no journal mode for ext4_journal_{forget,revoke}()
+    
+    When ext4 is using a journal, a metadata block which is deallocated
+    must be passed into the journal layer so it can be dropped from the
+    current transaction and/or revoked.  This is done by calling the
+    functions ext4_journal_forget() and ext4_journal_revoke(), which call
+    jbd2_journal_forget(), and jbd2_journal_revoke(), respectively.
+    
+    Since the jbd2_journal_forget() and jbd2_journal_revoke() call
+    bforget(), if ext4 is not using a journal, ext4_journal_forget() and
+    ext4_journal_revoke() must call bforget() to avoid a dirty metadata
+    block overwriting a block after it has been reallocated and reused for
+    another inode's data block.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
+index eb27fd0f2ee8..ecb9ca455fd5 100644
+--- a/fs/ext4/ext4_jbd2.c
++++ b/fs/ext4/ext4_jbd2.c
+@@ -44,7 +44,7 @@ int __ext4_journal_forget(const char *where, handle_t *handle,
+ 						  handle, err);
+ 	}
+ 	else
+-		brelse(bh);
++		bforget(bh);
+ 	return err;
+ }
+ 
+@@ -60,7 +60,7 @@ int __ext4_journal_revoke(const char *where, handle_t *handle,
+ 						  handle, err);
+ 	}
+ 	else
+-		brelse(bh);
++		bforget(bh);
+ 	return err;
+ }
+ 

commit 80e42468d65475e92651e62175bb7807773321d0
+Author: Theodore Ts'o 
+Date:   Tue Sep 8 08:21:26 2009 -0400
+
+    ext4: print more sysadmin-friendly message in check_block_validity()
+    
+    Drop the WARN_ON(1), as he stack trace is not appropriate, since it is
+    triggered by file system corruption, and it misleads users into
+    thinking there is a kernel bug.  In addition, change the message
+    displayed by ext4_error() to make it clear that this is a file system
+    corruption problem.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 5c0d17066f4a..6253ecdac67f 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1121,16 +1121,15 @@ static void ext4_da_update_reserve_space(struct inode *inode, int used)
+ 		ext4_discard_preallocations(inode);
+ }
+ 
+-static int check_block_validity(struct inode *inode, sector_t logical,
+-				sector_t phys, int len)
++static int check_block_validity(struct inode *inode, const char *msg,
++				sector_t logical, sector_t phys, int len)
+ {
+ 	if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), phys, len)) {
+-		ext4_error(inode->i_sb, "check_block_validity",
++		ext4_error(inode->i_sb, msg,
+ 			   "inode #%lu logical block %llu mapped to %llu "
+ 			   "(size %d)", inode->i_ino,
+ 			   (unsigned long long) logical,
+ 			   (unsigned long long) phys, len);
+-		WARN_ON(1);
+ 		return -EIO;
+ 	}
+ 	return 0;
+@@ -1182,8 +1181,8 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block,
+ 	up_read((&EXT4_I(inode)->i_data_sem));
+ 
+ 	if (retval > 0 && buffer_mapped(bh)) {
+-		int ret = check_block_validity(inode, block,
+-					       bh->b_blocknr, retval);
++		int ret = check_block_validity(inode, "file system corruption",
++					       block, bh->b_blocknr, retval);
+ 		if (ret != 0)
+ 			return ret;
+ 	}
+@@ -1264,8 +1263,9 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block,
+ 
+ 	up_write((&EXT4_I(inode)->i_data_sem));
+ 	if (retval > 0 && buffer_mapped(bh)) {
+-		int ret = check_block_validity(inode, block,
+-					       bh->b_blocknr, retval);
++		int ret = check_block_validity(inode, "file system "
++					       "corruption after allocation",
++					       block, bh->b_blocknr, retval);
+ 		if (ret != 0)
+ 			return ret;
+ 	}

commit d0646f7b636d067d715fab52a2ba9c6f0f46b0d7
+Author: Theodore Ts'o 
+Date:   Sat Sep 5 12:50:43 2009 -0400
+
+    ext4: Remove journal_checksum mount option and enable it by default
+    
+    There's no real cost for the journal checksum feature, and we should
+    make sure it is enabled all the time.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
+index 7be02ac5fa36..3e329dbac785 100644
+--- a/Documentation/filesystems/ext4.txt
++++ b/Documentation/filesystems/ext4.txt
+@@ -134,15 +134,9 @@ ro                   	Mount filesystem read only. Note that ext4 will
+                      	mount options "ro,noload" can be used to prevent
+ 		     	writes to the filesystem.
+ 
+-journal_checksum	Enable checksumming of the journal transactions.
+-			This will allow the recovery code in e2fsck and the
+-			kernel to detect corruption in the kernel.  It is a
+-			compatible change and will be ignored by older kernels.
+-
+ journal_async_commit	Commit block can be written to disk without waiting
+ 			for descriptor blocks. If enabled older kernels cannot
+-			mount the device. This will enable 'journal_checksum'
+-			internally.
++			mount the device.
+ 
+ journal=update		Update the ext4 file system's journal to the current
+ 			format.
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 81014f4ed22d..4dc64ed58d26 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -711,7 +711,6 @@ struct ext4_inode_info {
+ #define EXT4_MOUNT_QUOTA		0x80000 /* Some quota option set */
+ #define EXT4_MOUNT_USRQUOTA		0x100000 /* "old" user quota */
+ #define EXT4_MOUNT_GRPQUOTA		0x200000 /* "old" group quota */
+-#define EXT4_MOUNT_JOURNAL_CHECKSUM	0x800000 /* Journal checksums */
+ #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT	0x1000000 /* Journal Async Commit */
+ #define EXT4_MOUNT_I_VERSION            0x2000000 /* i_version support */
+ #define EXT4_MOUNT_DELALLOC		0x8000000 /* Delalloc support */
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 4037fe0b5a5c..f1815d3bcfd5 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1280,11 +1280,9 @@ static int parse_options(char *options, struct super_block *sb,
+ 			*journal_devnum = option;
+ 			break;
+ 		case Opt_journal_checksum:
+-			set_opt(sbi->s_mount_opt, JOURNAL_CHECKSUM);
+-			break;
++			break;	/* Kept for backwards compatibility */
+ 		case Opt_journal_async_commit:
+ 			set_opt(sbi->s_mount_opt, JOURNAL_ASYNC_COMMIT);
+-			set_opt(sbi->s_mount_opt, JOURNAL_CHECKSUM);
+ 			break;
+ 		case Opt_noload:
+ 			set_opt(sbi->s_mount_opt, NOLOAD);
+@@ -2751,20 +2749,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		goto failed_mount4;
+ 	}
+ 
+-	if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) {
+-		jbd2_journal_set_features(sbi->s_journal,
+-				JBD2_FEATURE_COMPAT_CHECKSUM, 0,
++	jbd2_journal_set_features(sbi->s_journal,
++				  JBD2_FEATURE_COMPAT_CHECKSUM, 0, 0);
++	if (test_opt(sb, JOURNAL_ASYNC_COMMIT))
++		jbd2_journal_set_features(sbi->s_journal, 0, 0,
+ 				JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT);
+-	} else if (test_opt(sb, JOURNAL_CHECKSUM)) {
+-		jbd2_journal_set_features(sbi->s_journal,
+-				JBD2_FEATURE_COMPAT_CHECKSUM, 0, 0);
++	else
+ 		jbd2_journal_clear_features(sbi->s_journal, 0, 0,
+ 				JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT);
+-	} else {
+-		jbd2_journal_clear_features(sbi->s_journal,
+-				JBD2_FEATURE_COMPAT_CHECKSUM, 0,
+-				JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT);
+-	}
+ 
+ 	/* We have now updated the journal if required, so we can
+ 	 * validate the data journaling mode. */

commit a3710fd1ee8cd542c5de63cf2c39f8912031f867
+Author: Theodore Ts'o 
+Date:   Thu Sep 17 08:50:18 2009 -0400
+
+    ext4: fix tracepoint format string warnings
+    
+    Unlike on some other architectures ino_t is an unsigned int on s390.
+    So add an explicit cast to avoid lots of compile warnings:
+    
+    In file included from include/trace/ftrace.h:285,
+                     from include/trace/define_trace.h:61,
+                     from include/trace/events/ext4.h:711,
+                     from fs/ext4/super.c:50:
+    include/trace/events/ext4.h: In function 'ftrace_raw_output_ext4_free_inode':
+    include/trace/events/ext4.h:12: warning: format '%lu' expects type 'long unsigned int', but argument 4 has type 'ino_t'
+    
+    Signed-off-by: Heiko Carstens 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index dd43399288ea..68b53c7ef8a7 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -33,8 +33,8 @@ TRACE_EVENT(ext4_free_inode,
+ 	),
+ 
+ 	TP_printk("dev %s ino %lu mode %d uid %u gid %u blocks %llu",
+-		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->mode,
+-		  __entry->uid, __entry->gid,
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++		  __entry->mode, __entry->uid, __entry->gid,
+ 		  (unsigned long long) __entry->blocks)
+ );
+ 
+@@ -56,7 +56,8 @@ TRACE_EVENT(ext4_request_inode,
+ 	),
+ 
+ 	TP_printk("dev %s dir %lu mode %d",
+-		  jbd2_dev_to_name(__entry->dev), __entry->dir, __entry->mode)
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->dir,
++		  __entry->mode)
+ );
+ 
+ TRACE_EVENT(ext4_allocate_inode,
+@@ -79,7 +80,8 @@ TRACE_EVENT(ext4_allocate_inode,
+ 	),
+ 
+ 	TP_printk("dev %s ino %lu dir %lu mode %d",
+-		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->dir, __entry->mode)
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++		  (unsigned long) __entry->dir, __entry->mode)
+ );
+ 
+ TRACE_EVENT(ext4_write_begin,
+@@ -106,8 +108,8 @@ TRACE_EVENT(ext4_write_begin,
+ 	),
+ 
+ 	TP_printk("dev %s ino %lu pos %llu len %u flags %u",
+-		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->pos, __entry->len,
+-		  __entry->flags)
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++		  __entry->pos, __entry->len, __entry->flags)
+ );
+ 
+ TRACE_EVENT(ext4_ordered_write_end,
+@@ -133,8 +135,8 @@ TRACE_EVENT(ext4_ordered_write_end,
+ 	),
+ 
+ 	TP_printk("dev %s ino %lu pos %llu len %u copied %u",
+-		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->pos, __entry->len,
+-		  __entry->copied)
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++		  __entry->pos, __entry->len, __entry->copied)
+ );
+ 
+ TRACE_EVENT(ext4_writeback_write_end,
+@@ -160,8 +162,8 @@ TRACE_EVENT(ext4_writeback_write_end,
+ 	),
+ 
+ 	TP_printk("dev %s ino %lu pos %llu len %u copied %u",
+-		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->pos, __entry->len,
+-		  __entry->copied)
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++		  __entry->pos, __entry->len, __entry->copied)
+ );
+ 
+ TRACE_EVENT(ext4_journalled_write_end,
+@@ -186,8 +188,8 @@ TRACE_EVENT(ext4_journalled_write_end,
+ 	),
+ 
+ 	TP_printk("dev %s ino %lu pos %llu len %u copied %u",
+-		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->pos, __entry->len,
+-		  __entry->copied)
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++		  __entry->pos, __entry->len, __entry->copied)
+ );
+ 
+ TRACE_EVENT(ext4_writepage,
+@@ -209,7 +211,8 @@ TRACE_EVENT(ext4_writepage,
+ 	),
+ 
+ 	TP_printk("dev %s ino %lu page_index %lu",
+-		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->index)
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++		  __entry->index)
+ );
+ 
+ TRACE_EVENT(ext4_da_writepages,
+@@ -244,7 +247,8 @@ TRACE_EVENT(ext4_da_writepages,
+ 	),
+ 
+ 	TP_printk("dev %s ino %lu nr_to_write %ld pages_skipped %ld range_start %llu range_end %llu nonblocking %d for_kupdate %d for_reclaim %d range_cyclic %d",
+-		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->nr_to_write,
++		  jbd2_dev_to_name(__entry->dev),
++		  (unsigned long) __entry->ino, __entry->nr_to_write,
+ 		  __entry->pages_skipped, __entry->range_start,
+ 		  __entry->range_end, __entry->nonblocking,
+ 		  __entry->for_kupdate, __entry->for_reclaim,
+@@ -279,7 +283,7 @@ TRACE_EVENT(ext4_da_write_pages,
+ 	),
+ 
+ 	TP_printk("dev %s ino %lu b_blocknr %llu b_size %u b_state 0x%04x first_page %lu io_done %d pages_written %d",
+-		  jbd2_dev_to_name(__entry->dev), __entry->ino,
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
+ 		  __entry->b_blocknr, __entry->b_size,
+ 		  __entry->b_state, __entry->first_page,
+ 		  __entry->io_done, __entry->pages_written)
+@@ -314,7 +318,8 @@ TRACE_EVENT(ext4_da_writepages_result,
+ 	),
+ 
+ 	TP_printk("dev %s ino %lu ret %d pages_written %d pages_skipped %ld congestion %d more_io %d no_nrwrite_index_update %d",
+-		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->ret,
++		  jbd2_dev_to_name(__entry->dev),
++		  (unsigned long) __entry->ino, __entry->ret,
+ 		  __entry->pages_written, __entry->pages_skipped,
+ 		  __entry->encountered_congestion, __entry->more_io,
+ 		  __entry->no_nrwrite_index_update)
+@@ -343,8 +348,8 @@ TRACE_EVENT(ext4_da_write_begin,
+ 	),
+ 
+ 	TP_printk("dev %s ino %lu pos %llu len %u flags %u",
+-		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->pos, __entry->len,
+-		  __entry->flags)
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++		  __entry->pos, __entry->len, __entry->flags)
+ );
+ 
+ TRACE_EVENT(ext4_da_write_end,
+@@ -370,8 +375,8 @@ TRACE_EVENT(ext4_da_write_end,
+ 	),
+ 
+ 	TP_printk("dev %s ino %lu pos %llu len %u copied %u",
+-		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->pos, __entry->len,
+-		  __entry->copied)
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++		  __entry->pos, __entry->len, __entry->copied)
+ );
+ 
+ TRACE_EVENT(ext4_discard_blocks,
+@@ -421,8 +426,8 @@ TRACE_EVENT(ext4_mb_new_inode_pa,
+ 	),
+ 
+ 	TP_printk("dev %s ino %lu pstart %llu len %u lstart %llu",
+-		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->pa_pstart,
+-		  __entry->pa_len, __entry->pa_lstart)
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++		  __entry->pa_pstart, __entry->pa_len, __entry->pa_lstart)
+ );
+ 
+ TRACE_EVENT(ext4_mb_new_group_pa,
+@@ -449,8 +454,8 @@ TRACE_EVENT(ext4_mb_new_group_pa,
+ 	),
+ 
+ 	TP_printk("dev %s ino %lu pstart %llu len %u lstart %llu",
+-		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->pa_pstart,
+-		  __entry->pa_len, __entry->pa_lstart)
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++		  __entry->pa_pstart, __entry->pa_len, __entry->pa_lstart)
+ );
+ 
+ TRACE_EVENT(ext4_mb_release_inode_pa,
+@@ -476,8 +481,8 @@ TRACE_EVENT(ext4_mb_release_inode_pa,
+ 	),
+ 
+ 	TP_printk("dev %s ino %lu block %llu count %u",
+-		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->block,
+-		  __entry->count)
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++		  __entry->block, __entry->count)
+ );
+ 
+ TRACE_EVENT(ext4_mb_release_group_pa,
+@@ -522,7 +527,7 @@ TRACE_EVENT(ext4_discard_preallocations,
+ 	),
+ 
+ 	TP_printk("dev %s ino %lu",
+-		  jbd2_dev_to_name(__entry->dev), __entry->ino)
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino)
+ );
+ 
+ TRACE_EVENT(ext4_mb_discard_preallocations,
+@@ -577,8 +582,8 @@ TRACE_EVENT(ext4_request_blocks,
+ 	),
+ 
+ 	TP_printk("dev %s ino %lu flags %u len %u lblk %llu goal %llu lleft %llu lright %llu pleft %llu pright %llu ",
+-		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->flags,
+-		  __entry->len,
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++		  __entry->flags, __entry->len,
+ 		  (unsigned long long) __entry->logical,
+ 		  (unsigned long long) __entry->goal,
+ 		  (unsigned long long) __entry->lleft,
+@@ -621,8 +626,8 @@ TRACE_EVENT(ext4_allocate_blocks,
+ 	),
+ 
+ 	TP_printk("dev %s ino %lu flags %u len %u block %llu lblk %llu goal %llu lleft %llu lright %llu pleft %llu pright %llu ",
+-		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->flags,
+-		  __entry->len, __entry->block,
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++		  __entry->flags, __entry->len, __entry->block,
+ 		  (unsigned long long) __entry->logical,
+ 		  (unsigned long long) __entry->goal,
+ 		  (unsigned long long) __entry->lleft,
+@@ -655,8 +660,8 @@ TRACE_EVENT(ext4_free_blocks,
+ 	),
+ 
+ 	TP_printk("dev %s ino %lu block %llu count %lu metadata %d",
+-		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->block,
+-		  __entry->count, __entry->metadata)
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++		  __entry->block, __entry->count, __entry->metadata)
+ );
+ 
+ TRACE_EVENT(ext4_sync_file,
+@@ -679,8 +684,8 @@ TRACE_EVENT(ext4_sync_file,
+ 	),
+ 
+ 	TP_printk("dev %s ino %ld parent %ld datasync %d ",
+-		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->parent,
+-		  __entry->datasync)
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
++		  (unsigned long) __entry->parent, __entry->datasync)
+ );
+ 
+ TRACE_EVENT(ext4_sync_fs,
+diff --git a/include/trace/events/jbd2.h b/include/trace/events/jbd2.h
+index 10813fa0c8d0..b851f0b4701c 100644
+--- a/include/trace/events/jbd2.h
++++ b/include/trace/events/jbd2.h
+@@ -159,7 +159,7 @@ TRACE_EVENT(jbd2_submit_inode_data,
+ 	),
+ 
+ 	TP_printk("dev %s ino %lu",
+-		  jbd2_dev_to_name(__entry->dev), __entry->ino)
++		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino)
+ );
+ 
+ #endif /* _TRACE_JBD2_H */

commit b3a3ca8ca0c3c29abc5b2bfe94bb14f3f4590df9
+Author: Theodore Ts'o 
+Date:   Mon Aug 31 23:13:11 2009 -0400
+
+    ext4: Add new tracepoint: trace_ext4_da_write_pages()
+    
+    Add a new tracepoint which shows the pages that will be written using
+    write_cache_pages() by ext4_da_writepages().
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 41a76e163b99..81014f4ed22d 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -113,6 +113,21 @@ struct ext4_allocation_request {
+ 	unsigned int flags;
+ };
+ 
++/*
++ * For delayed allocation tracking
++ */
++struct mpage_da_data {
++	struct inode *inode;
++	sector_t b_blocknr;		/* start block number of extent */
++	size_t b_size;			/* size of extent */
++	unsigned long b_state;		/* state of the extent */
++	unsigned long first_page, next_page;	/* extent of pages */
++	struct writeback_control *wbc;
++	int io_done;
++	int pages_written;
++	int retval;
++};
++
+ /*
+  * Special inodes numbers
+  */
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index ff659e757578..17802a96af9f 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1875,18 +1875,6 @@ static void ext4_da_page_release_reservation(struct page *page,
+  * Delayed allocation stuff
+  */
+ 
+-struct mpage_da_data {
+-	struct inode *inode;
+-	sector_t b_blocknr;		/* start block number of extent */
+-	size_t b_size;			/* size of extent */
+-	unsigned long b_state;		/* state of the extent */
+-	unsigned long first_page, next_page;	/* extent of pages */
+-	struct writeback_control *wbc;
+-	int io_done;
+-	int pages_written;
+-	int retval;
+-};
+-
+ /*
+  * mpage_da_submit_io - walks through extent of pages and try to write
+  * them with writepage() call back
+@@ -2863,6 +2851,7 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 			mpd.io_done = 1;
+ 			ret = MPAGE_DA_EXTENT_TAIL;
+ 		}
++		trace_ext4_da_write_pages(inode, &mpd);
+ 		wbc->nr_to_write -= mpd.pages_written;
+ 
+ 		ext4_journal_stop(handle);
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index 15051d2d1219..dd43399288ea 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -251,6 +251,40 @@ TRACE_EVENT(ext4_da_writepages,
+ 		  __entry->range_cyclic)
+ );
+ 
++TRACE_EVENT(ext4_da_write_pages,
++	TP_PROTO(struct inode *inode, struct mpage_da_data *mpd),
++
++	TP_ARGS(inode, mpd),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	__u64,	b_blocknr		)
++		__field(	__u32,	b_size			)
++		__field(	__u32,	b_state			)
++		__field(	unsigned long,	first_page	)
++		__field(	int,	io_done			)
++		__field(	int,	pages_written		)
++	),
++
++	TP_fast_assign(
++		__entry->dev		= inode->i_sb->s_dev;
++		__entry->ino		= inode->i_ino;
++		__entry->b_blocknr	= mpd->b_blocknr;
++		__entry->b_size		= mpd->b_size;
++		__entry->b_state	= mpd->b_state;
++		__entry->first_page	= mpd->first_page;
++		__entry->io_done	= mpd->io_done;
++		__entry->pages_written	= mpd->pages_written;
++	),
++
++	TP_printk("dev %s ino %lu b_blocknr %llu b_size %u b_state 0x%04x first_page %lu io_done %d pages_written %d",
++		  jbd2_dev_to_name(__entry->dev), __entry->ino,
++		  __entry->b_blocknr, __entry->b_size,
++		  __entry->b_state, __entry->first_page,
++		  __entry->io_done, __entry->pages_written)
++);
++
+ TRACE_EVENT(ext4_da_writepages_result,
+ 	TP_PROTO(struct inode *inode, struct writeback_control *wbc,
+ 			int ret, int pages_written),

commit de89de6e0cf4b1eb13f27137cf2aa40d287aabdf
+Author: Theodore Ts'o 
+Date:   Mon Aug 31 17:00:59 2009 -0400
+
+    ext4: Restore wbc->range_start in ext4_da_writepages()
+    
+    To solve a lock inversion problem, we implement part of the
+    range_cyclic algorithm in ext4_da_writepages().  (See commit 2acf2c26
+    for more details.)
+    
+    As part of that change wbc->range_start was modified by ext4's
+    writepages function, which causes its callers to get confused since
+    they aren't expecting the filesystem to modify it.  The simplest fix
+    is to save and restore wbc->range_start in ext4_da_writepages.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index d61fb523308f..ff659e757578 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2749,6 +2749,7 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 	long pages_skipped;
+ 	int range_cyclic, cycled = 1, io_done = 0;
+ 	int needed_blocks, ret = 0, nr_to_writebump = 0;
++	loff_t range_start = wbc->range_start;
+ 	struct ext4_sb_info *sbi = EXT4_SB(mapping->host->i_sb);
+ 
+ 	trace_ext4_da_writepages(inode, wbc);
+@@ -2917,6 +2918,7 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 	if (!no_nrwrite_index_update)
+ 		wbc->no_nrwrite_index_update = 0;
+ 	wbc->nr_to_write -= nr_to_writebump;
++	wbc->range_start = range_start;
+ 	trace_ext4_da_writepages_result(inode, wbc, ret, pages_written);
+ 	return ret;
+ }

commit 98a56ab382079f777e261e14512cbd4fb2107af4
+Author: Theodore Ts'o 
+Date:   Thu Sep 17 08:48:28 2009 -0400
+
+    ext4: Fix spelling typo in the trace format for trace_ext4_da_writepages()
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index 8d433c4e3709..15051d2d1219 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -243,7 +243,7 @@ TRACE_EVENT(ext4_da_writepages,
+ 		__entry->range_cyclic	= wbc->range_cyclic;
+ 	),
+ 
+-	TP_printk("dev %s ino %lu nr_t_write %ld pages_skipped %ld range_start %llu range_end %llu nonblocking %d for_kupdate %d for_reclaim %d range_cyclic %d",
++	TP_printk("dev %s ino %lu nr_to_write %ld pages_skipped %ld range_start %llu range_end %llu nonblocking %d for_kupdate %d for_reclaim %d range_cyclic %d",
+ 		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->nr_to_write,
+ 		  __entry->pages_skipped, __entry->range_start,
+ 		  __entry->range_end, __entry->nonblocking,

commit b05ab1dc3795e6f997fb0d34f38fce5012533c3e
+Author: Theodore Ts'o 
+Date:   Sat Aug 29 21:08:08 2009 -0400
+
+    ext4: Limit number of links that can be created by ext4_link()
+    
+    In ext4_link we need to check using EXT4_LINK_MAX, and not
+    EXT4_DIR_LINK_MAX(), since ext4_link() is creating hard links of
+    regular files, and not directories.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index ba91bd0f7916..f27c8164c1fe 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -2318,7 +2318,7 @@ static int ext4_link(struct dentry *old_dentry,
+ 	struct inode *inode = old_dentry->d_inode;
+ 	int err, retries = 0;
+ 
+-	if (EXT4_DIR_LINK_MAX(inode))
++	if (inode->i_nlink >= EXT4_LINK_MAX)
+ 		return -EMLINK;
+ 
+ 	/*

commit 55ad63bf3a30936aced50f13452735c2f58b234c
+Author: Theodore Ts'o 
+Date:   Fri Aug 28 10:40:33 2009 -0400
+
+    ext4: fix extent sanity checking code with AGGRESSIVE_TEST
+    
+    The extents sanity-checking code depends on the ext4_ext_space_*()
+    functions returning the maximum alloable size for eh_max; however,
+    when the debugging #ifdef AGGRESSIVE_TEST is enabled to test the
+    extent tree handling code, this prevents a normally created ext4
+    filesystem from being mounted with the errors:
+    
+    Aug 26 15:43:50 bsd086 kernel: [   96.070277] EXT4-fs error (device sda8): ext4_ext_check_inode: bad header/extent in inode #8: too large eh_max - magic f30a, entries 1, max 4(3), depth 0(0)
+    Aug 26 15:43:50 bsd086 kernel: [   96.070526] EXT4-fs (sda8): no journal found
+    
+    Bug reported by Akira Fujita.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 8c20caf4aa5c..7a3832577923 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -229,57 +229,65 @@ ext4_ext_new_meta_block(handle_t *handle, struct inode *inode,
+ 	return newblock;
+ }
+ 
+-static int ext4_ext_space_block(struct inode *inode)
++static inline int ext4_ext_space_block(struct inode *inode, int check)
+ {
+ 	int size;
+ 
+ 	size = (inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header))
+ 			/ sizeof(struct ext4_extent);
++	if (!check) {
+ #ifdef AGGRESSIVE_TEST
+-	if (size > 6)
+-		size = 6;
++		if (size > 6)
++			size = 6;
+ #endif
++	}
+ 	return size;
+ }
+ 
+-static int ext4_ext_space_block_idx(struct inode *inode)
++static inline int ext4_ext_space_block_idx(struct inode *inode, int check)
+ {
+ 	int size;
+ 
+ 	size = (inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header))
+ 			/ sizeof(struct ext4_extent_idx);
++	if (!check) {
+ #ifdef AGGRESSIVE_TEST
+-	if (size > 5)
+-		size = 5;
++		if (size > 5)
++			size = 5;
+ #endif
++	}
+ 	return size;
+ }
+ 
+-static int ext4_ext_space_root(struct inode *inode)
++static inline int ext4_ext_space_root(struct inode *inode, int check)
+ {
+ 	int size;
+ 
+ 	size = sizeof(EXT4_I(inode)->i_data);
+ 	size -= sizeof(struct ext4_extent_header);
+ 	size /= sizeof(struct ext4_extent);
++	if (!check) {
+ #ifdef AGGRESSIVE_TEST
+-	if (size > 3)
+-		size = 3;
++		if (size > 3)
++			size = 3;
+ #endif
++	}
+ 	return size;
+ }
+ 
+-static int ext4_ext_space_root_idx(struct inode *inode)
++static inline int ext4_ext_space_root_idx(struct inode *inode, int check)
+ {
+ 	int size;
+ 
+ 	size = sizeof(EXT4_I(inode)->i_data);
+ 	size -= sizeof(struct ext4_extent_header);
+ 	size /= sizeof(struct ext4_extent_idx);
++	if (!check) {
+ #ifdef AGGRESSIVE_TEST
+-	if (size > 4)
+-		size = 4;
++		if (size > 4)
++			size = 4;
+ #endif
++	}
+ 	return size;
+ }
+ 
+@@ -293,9 +301,9 @@ int ext4_ext_calc_metadata_amount(struct inode *inode, int blocks)
+ 	int lcap, icap, rcap, leafs, idxs, num;
+ 	int newextents = blocks;
+ 
+-	rcap = ext4_ext_space_root_idx(inode);
+-	lcap = ext4_ext_space_block(inode);
+-	icap = ext4_ext_space_block_idx(inode);
++	rcap = ext4_ext_space_root_idx(inode, 0);
++	lcap = ext4_ext_space_block(inode, 0);
++	icap = ext4_ext_space_block_idx(inode, 0);
+ 
+ 	/* number of new leaf blocks needed */
+ 	num = leafs = (newextents + lcap - 1) / lcap;
+@@ -320,14 +328,14 @@ ext4_ext_max_entries(struct inode *inode, int depth)
+ 
+ 	if (depth == ext_depth(inode)) {
+ 		if (depth == 0)
+-			max = ext4_ext_space_root(inode);
++			max = ext4_ext_space_root(inode, 1);
+ 		else
+-			max = ext4_ext_space_root_idx(inode);
++			max = ext4_ext_space_root_idx(inode, 1);
+ 	} else {
+ 		if (depth == 0)
+-			max = ext4_ext_space_block(inode);
++			max = ext4_ext_space_block(inode, 1);
+ 		else
+-			max = ext4_ext_space_block_idx(inode);
++			max = ext4_ext_space_block_idx(inode, 1);
+ 	}
+ 
+ 	return max;
+@@ -626,7 +634,7 @@ int ext4_ext_tree_init(handle_t *handle, struct inode *inode)
+ 	eh->eh_depth = 0;
+ 	eh->eh_entries = 0;
+ 	eh->eh_magic = EXT4_EXT_MAGIC;
+-	eh->eh_max = cpu_to_le16(ext4_ext_space_root(inode));
++	eh->eh_max = cpu_to_le16(ext4_ext_space_root(inode, 0));
+ 	ext4_mark_inode_dirty(handle, inode);
+ 	ext4_ext_invalidate_cache(inode);
+ 	return 0;
+@@ -851,7 +859,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
+ 
+ 	neh = ext_block_hdr(bh);
+ 	neh->eh_entries = 0;
+-	neh->eh_max = cpu_to_le16(ext4_ext_space_block(inode));
++	neh->eh_max = cpu_to_le16(ext4_ext_space_block(inode, 0));
+ 	neh->eh_magic = EXT4_EXT_MAGIC;
+ 	neh->eh_depth = 0;
+ 	ex = EXT_FIRST_EXTENT(neh);
+@@ -927,7 +935,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
+ 		neh = ext_block_hdr(bh);
+ 		neh->eh_entries = cpu_to_le16(1);
+ 		neh->eh_magic = EXT4_EXT_MAGIC;
+-		neh->eh_max = cpu_to_le16(ext4_ext_space_block_idx(inode));
++		neh->eh_max = cpu_to_le16(ext4_ext_space_block_idx(inode, 0));
+ 		neh->eh_depth = cpu_to_le16(depth - i);
+ 		fidx = EXT_FIRST_INDEX(neh);
+ 		fidx->ei_block = border;
+@@ -1052,9 +1060,9 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
+ 	/* old root could have indexes or leaves
+ 	 * so calculate e_max right way */
+ 	if (ext_depth(inode))
+-	  neh->eh_max = cpu_to_le16(ext4_ext_space_block_idx(inode));
++		neh->eh_max = cpu_to_le16(ext4_ext_space_block_idx(inode, 0));
+ 	else
+-	  neh->eh_max = cpu_to_le16(ext4_ext_space_block(inode));
++		neh->eh_max = cpu_to_le16(ext4_ext_space_block(inode, 0));
+ 	neh->eh_magic = EXT4_EXT_MAGIC;
+ 	set_buffer_uptodate(bh);
+ 	unlock_buffer(bh);
+@@ -1069,7 +1077,7 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
+ 		goto out;
+ 
+ 	curp->p_hdr->eh_magic = EXT4_EXT_MAGIC;
+-	curp->p_hdr->eh_max = cpu_to_le16(ext4_ext_space_root_idx(inode));
++	curp->p_hdr->eh_max = cpu_to_le16(ext4_ext_space_root_idx(inode, 0));
+ 	curp->p_hdr->eh_entries = cpu_to_le16(1);
+ 	curp->p_idx = EXT_FIRST_INDEX(curp->p_hdr);
+ 
+@@ -2348,7 +2356,7 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start)
+ 		if (err == 0) {
+ 			ext_inode_hdr(inode)->eh_depth = 0;
+ 			ext_inode_hdr(inode)->eh_max =
+-				cpu_to_le16(ext4_ext_space_root(inode));
++				cpu_to_le16(ext4_ext_space_root(inode, 0));
+ 			err = ext4_ext_dirty(handle, inode, path);
+ 		}
+ 	}

commit 6d41807614151829ae17a3a58bff8572af5e407e
+Author: Theodore Ts'o 
+Date:   Mon Aug 10 16:03:43 2009 -0400
+
+    ext3: Update Kconfig description of EXT3_DEFAULTS_TO_ORDERED
+    
+    The old description for this configuration option was perhaps not
+    completely balanced in terms of describing the tradeoffs of using a
+    default of data=writeback vs. data=ordered.  Despite the fact that old
+    description very strongly recomended disabling this feature, all of
+    the major distributions have elected to preserve the existing 'legacy'
+    default, which is a strong hint that it perhaps wasn't telling the
+    whole story.
+    
+    This revised description has been vetted by a number of ext3
+    developers as being better at informing the user about the tradeoffs
+    of enabling or disabling this configuration feature.
+    
+    Cc: linux-ext4@vger.kernel.org
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Jan Kara 
+
+diff --git a/fs/ext3/Kconfig b/fs/ext3/Kconfig
+index fb3c1a21b135..522b15498f45 100644
+--- a/fs/ext3/Kconfig
++++ b/fs/ext3/Kconfig
+@@ -29,23 +29,25 @@ config EXT3_FS
+ 	  module will be called ext3.
+ 
+ config EXT3_DEFAULTS_TO_ORDERED
+-	bool "Default to 'data=ordered' in ext3 (legacy option)"
++	bool "Default to 'data=ordered' in ext3"
+ 	depends on EXT3_FS
+ 	help
+-	  If a filesystem does not explicitly specify a data ordering
+-	  mode, and the journal capability allowed it, ext3 used to
+-	  historically default to 'data=ordered'.
+-
+-	  That was a rather unfortunate choice, because it leads to all
+-	  kinds of latency problems, and the 'data=writeback' mode is more
+-	  appropriate these days.
+-
+-	  You should probably always answer 'n' here, and if you really
+-	  want to use 'data=ordered' mode, set it in the filesystem itself
+-	  with 'tune2fs -o journal_data_ordered'.
+-
+-	  But if you really want to enable the legacy default, you can do
+-	  so by answering 'y' to this question.
++	  The journal mode options for ext3 have different tradeoffs
++	  between when data is guaranteed to be on disk and
++	  performance.	The use of "data=writeback" can cause
++	  unwritten data to appear in files after an system crash or
++	  power failure, which can be a security issue.	 However,
++	  "data=ordered" mode can also result in major performance
++	  problems, including seconds-long delays before an fsync()
++	  call returns.	 For details, see:
++
++	  http://ext4.wiki.kernel.org/index.php/Ext3_data_mode_tradeoffs
++
++	  If you have been historically happy with ext3's performance,
++	  data=ordered mode will be a safe choice and you should
++	  answer 'y' here.  If you understand the reliability and data
++	  privacy issues of data=writeback and are willing to make
++	  that trade off, answer 'n'.
+ 
+ config EXT3_FS_XATTR
+ 	bool "Ext3 extended attributes"

commit 50797481a7bdee548589506d7d7b48b08bc14dcd
+Author: Theodore Ts'o 
+Date:   Fri Sep 18 13:34:02 2009 -0400
+
+    ext4: Avoid group preallocation for closed files
+    
+    Currently the group preallocation code tries to find a large (512)
+    free block from which to do per-cpu group allocation for small files.
+    The problem with this scheme is that it leaves the filesystem horribly
+    fragmented.  In the worst case, if the filesystem is unmounted and
+    remounted (after a system shutdown, for example) we forget the fact
+    that wee were using a particular (now-partially filled) 512 block
+    extent.  So the next time we try to allocate space for a small file,
+    we will find *another* completely free 512 block chunk to allocate
+    small files.  Given that there are 32,768 blocks in a block group,
+    after 64 iterations of "mount, write one 4k file in a directory,
+    unmount", the block group will have 64 files, each separated by 511
+    blocks, and the block group will no longer have any free 512
+    completely free chunks of blocks for group preallocation space.
+    
+    So if we try to allocate blocks for a file that has been closed, such
+    that we know the final size of the file, and the filesystem is not
+    busy, avoid using group preallocation.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 70aa951ecb3c..2e9a2036c114 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -952,6 +952,7 @@ struct ext4_sb_info {
+ 	atomic_t s_mb_lost_chunks;
+ 	atomic_t s_mb_preallocated;
+ 	atomic_t s_mb_discarded;
++	atomic_t s_lock_busy;
+ 
+ 	/* locality groups */
+ 	struct ext4_locality_group *s_locality_groups;
+@@ -1593,15 +1594,42 @@ struct ext4_group_info {
+ #define EXT4_MB_GRP_NEED_INIT(grp)	\
+ 	(test_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &((grp)->bb_state)))
+ 
++#define EXT4_MAX_CONTENTION		8
++#define EXT4_CONTENTION_THRESHOLD	2
++
+ static inline spinlock_t *ext4_group_lock_ptr(struct super_block *sb,
+ 					      ext4_group_t group)
+ {
+ 	return bgl_lock_ptr(EXT4_SB(sb)->s_blockgroup_lock, group);
+ }
+ 
++/*
++ * Returns true if the filesystem is busy enough that attempts to
++ * access the block group locks has run into contention.
++ */
++static inline int ext4_fs_is_busy(struct ext4_sb_info *sbi)
++{
++	return (atomic_read(&sbi->s_lock_busy) > EXT4_CONTENTION_THRESHOLD);
++}
++
+ static inline void ext4_lock_group(struct super_block *sb, ext4_group_t group)
+ {
+-	spin_lock(ext4_group_lock_ptr(sb, group));
++	spinlock_t *lock = ext4_group_lock_ptr(sb, group);
++	if (spin_trylock(lock))
++		/*
++		 * We're able to grab the lock right away, so drop the
++		 * lock contention counter.
++		 */
++		atomic_add_unless(&EXT4_SB(sb)->s_lock_busy, -1, 0);
++	else {
++		/*
++		 * The lock is busy, so bump the contention counter,
++		 * and then wait on the spin lock.
++		 */
++		atomic_add_unless(&EXT4_SB(sb)->s_lock_busy, 1,
++				  EXT4_MAX_CONTENTION);
++		spin_lock(lock);
++	}
+ }
+ 
+ static inline void ext4_unlock_group(struct super_block *sb,
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 90a30ce822fc..faf5bd056a93 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -4191,9 +4191,17 @@ static void ext4_mb_group_or_file(struct ext4_allocation_context *ac)
+ 		return;
+ 
+ 	size = ac->ac_o_ex.fe_logical + ac->ac_o_ex.fe_len;
+-	isize = i_size_read(ac->ac_inode) >> bsbits;
++	isize = (i_size_read(ac->ac_inode) + ac->ac_sb->s_blocksize - 1)
++		>> bsbits;
+ 	size = max(size, isize);
+ 
++	if ((size == isize) &&
++	    !ext4_fs_is_busy(sbi) &&
++	    (atomic_read(&ac->ac_inode->i_writecount) == 0)) {
++		ac->ac_flags |= EXT4_MB_HINT_NOPREALLOC;
++		return;
++	}
++
+ 	/* don't use group allocation for large files */
+ 	if (size >= sbi->s_mb_stream_request) {
+ 		ac->ac_flags |= EXT4_MB_STREAM_ALLOC;

commit 4ba74d00a20256e22f159cb288ff34b587608917
+Author: Theodore Ts'o 
+Date:   Sun Aug 9 22:01:13 2009 -0400
+
+    ext4: Fix bugs in mballoc's stream allocation mode
+    
+    The logic around sbi->s_mb_last_group and sbi->s_mb_last_start was all
+    screwed up.  These fields were getting unconditionally all the time,
+    set even when stream allocation had not taken place, and if they were
+    being used when the file was smaller than s_mb_stream_request, which
+    is when the allocation should _not_ be doing stream allocation.
+    
+    Fix this by determining whether or not we stream allocation should
+    take place once, in ext4_mb_group_or_file(), and setting a flag which
+    gets used in ext4_mb_regular_allocator() and ext4_mb_use_best_found().
+    This simplifies the code and assures that we are consistently using
+    (or not using) the stream allocation logic.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index e267727cc62d..70aa951ecb3c 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -88,6 +88,8 @@ typedef unsigned int ext4_group_t;
+ #define EXT4_MB_HINT_TRY_GOAL		0x0200
+ /* blocks already pre-reserved by delayed allocation */
+ #define EXT4_MB_DELALLOC_RESERVED	0x0400
++/* We are doing stream allocation */
++#define EXT4_MB_STREAM_ALLOC		0x0800
+ 
+ 
+ struct ext4_allocation_request {
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 3434c603432d..90a30ce822fc 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -1361,7 +1361,7 @@ static void ext4_mb_use_best_found(struct ext4_allocation_context *ac,
+ 	ac->alloc_semp =  e4b->alloc_semp;
+ 	e4b->alloc_semp = NULL;
+ 	/* store last allocated for subsequent stream allocation */
+-	if ((ac->ac_flags & EXT4_MB_HINT_DATA)) {
++	if (ac->ac_flags & EXT4_MB_STREAM_ALLOC) {
+ 		spin_lock(&sbi->s_md_lock);
+ 		sbi->s_mb_last_group = ac->ac_f_ex.fe_group;
+ 		sbi->s_mb_last_start = ac->ac_f_ex.fe_start;
+@@ -1939,7 +1939,6 @@ ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
+ 	struct ext4_sb_info *sbi;
+ 	struct super_block *sb;
+ 	struct ext4_buddy e4b;
+-	loff_t size, isize;
+ 
+ 	sb = ac->ac_sb;
+ 	sbi = EXT4_SB(sb);
+@@ -1975,20 +1974,16 @@ ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
+ 	}
+ 
+ 	bsbits = ac->ac_sb->s_blocksize_bits;
+-	/* if stream allocation is enabled, use global goal */
+-	size = ac->ac_o_ex.fe_logical + ac->ac_o_ex.fe_len;
+-	isize = i_size_read(ac->ac_inode) >> bsbits;
+-	if (size < isize)
+-		size = isize;
+ 
+-	if (size < sbi->s_mb_stream_request &&
+-			(ac->ac_flags & EXT4_MB_HINT_DATA)) {
++	/* if stream allocation is enabled, use global goal */
++	if (ac->ac_flags & EXT4_MB_STREAM_ALLOC) {
+ 		/* TBD: may be hot point */
+ 		spin_lock(&sbi->s_md_lock);
+ 		ac->ac_g_ex.fe_group = sbi->s_mb_last_group;
+ 		ac->ac_g_ex.fe_start = sbi->s_mb_last_start;
+ 		spin_unlock(&sbi->s_md_lock);
+ 	}
++
+ 	/* Let's just scan groups to find more-less suitable blocks */
+ 	cr = ac->ac_2order ? 0 : 1;
+ 	/*
+@@ -4192,16 +4187,18 @@ static void ext4_mb_group_or_file(struct ext4_allocation_context *ac)
+ 	if (!(ac->ac_flags & EXT4_MB_HINT_DATA))
+ 		return;
+ 
++	if (unlikely(ac->ac_flags & EXT4_MB_HINT_GOAL_ONLY))
++		return;
++
+ 	size = ac->ac_o_ex.fe_logical + ac->ac_o_ex.fe_len;
+ 	isize = i_size_read(ac->ac_inode) >> bsbits;
+ 	size = max(size, isize);
+ 
+ 	/* don't use group allocation for large files */
+-	if (size >= sbi->s_mb_stream_request)
+-		return;
+-
+-	if (unlikely(ac->ac_flags & EXT4_MB_HINT_GOAL_ONLY))
++	if (size >= sbi->s_mb_stream_request) {
++		ac->ac_flags |= EXT4_MB_STREAM_ALLOC;
+ 		return;
++	}
+ 
+ 	BUG_ON(ac->ac_lg != NULL);
+ 	/*

commit 0ef90db93a4ddfc300af288c2a1bfc1e6c79da64
+Author: Theodore Ts'o 
+Date:   Sun Aug 9 16:46:13 2009 -0400
+
+    ext4: Display the mballoc flags in mb_history in hex instead of decimal
+    
+    Displaying the flags in base 16 makes it easier to see which flags
+    have been set.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 9714db393efe..e267727cc62d 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -67,27 +67,27 @@ typedef unsigned int ext4_group_t;
+ 
+ 
+ /* prefer goal again. length */
+-#define EXT4_MB_HINT_MERGE		1
++#define EXT4_MB_HINT_MERGE		0x0001
+ /* blocks already reserved */
+-#define EXT4_MB_HINT_RESERVED		2
++#define EXT4_MB_HINT_RESERVED		0x0002
+ /* metadata is being allocated */
+-#define EXT4_MB_HINT_METADATA		4
++#define EXT4_MB_HINT_METADATA		0x0004
+ /* first blocks in the file */
+-#define EXT4_MB_HINT_FIRST		8
++#define EXT4_MB_HINT_FIRST		0x0008
+ /* search for the best chunk */
+-#define EXT4_MB_HINT_BEST		16
++#define EXT4_MB_HINT_BEST		0x0010
+ /* data is being allocated */
+-#define EXT4_MB_HINT_DATA		32
++#define EXT4_MB_HINT_DATA		0x0020
+ /* don't preallocate (for tails) */
+-#define EXT4_MB_HINT_NOPREALLOC		64
++#define EXT4_MB_HINT_NOPREALLOC		0x0040
+ /* allocate for locality group */
+-#define EXT4_MB_HINT_GROUP_ALLOC	128
++#define EXT4_MB_HINT_GROUP_ALLOC	0x0080
+ /* allocate goal blocks or none */
+-#define EXT4_MB_HINT_GOAL_ONLY		256
++#define EXT4_MB_HINT_GOAL_ONLY		0x0100
+ /* goal is meaningful */
+-#define EXT4_MB_HINT_TRY_GOAL		512
++#define EXT4_MB_HINT_TRY_GOAL		0x0200
+ /* blocks already pre-reserved by delayed allocation */
+-#define EXT4_MB_DELALLOC_RESERVED      1024
++#define EXT4_MB_DELALLOC_RESERVED	0x0400
+ 
+ 
+ struct ext4_allocation_request {
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index d80b300c1779..3434c603432d 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2157,7 +2157,7 @@ static int ext4_mb_seq_history_show(struct seq_file *seq, void *v)
+ 
+ 	if (v == SEQ_START_TOKEN) {
+ 		seq_printf(seq, "%-5s %-8s %-23s %-23s %-23s %-5s "
+-				"%-5s %-2s %-5s %-5s %-5s %-6s\n",
++				"%-5s %-2s %-6s %-5s %-5s %-6s\n",
+ 			  "pid", "inode", "original", "goal", "result", "found",
+ 			   "grps", "cr", "flags", "merge", "tail", "broken");
+ 		return 0;
+@@ -2165,7 +2165,7 @@ static int ext4_mb_seq_history_show(struct seq_file *seq, void *v)
+ 
+ 	if (hs->op == EXT4_MB_HISTORY_ALLOC) {
+ 		fmt = "%-5u %-8u %-23s %-23s %-23s %-5u %-5u %-2u "
+-			"%-5u %-5s %-5u %-6u\n";
++			"0x%04x %-5s %-5u %-6u\n";
+ 		sprintf(buf2, "%u/%d/%u@%u", hs->result.fe_group,
+ 			hs->result.fe_start, hs->result.fe_len,
+ 			hs->result.fe_logical);

commit 6ba495e9259cd9a0b40ebd6c315143535c92542f
+Author: Theodore Ts'o 
+Date:   Fri Sep 18 13:38:55 2009 -0400
+
+    ext4: Add configurable run-time mballoc debugging
+    
+    Allow mballoc debugging to be enabled at run-time instead of just at
+    compile time.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
+index 152304624644..d5c0ea2e8f2d 100644
+--- a/fs/ext4/Kconfig
++++ b/fs/ext4/Kconfig
+@@ -77,3 +77,12 @@ config EXT4_FS_SECURITY
+ 
+ 	  If you are not using a security module that requires using
+ 	  extended attributes for file security labels, say N.
++
++config EXT4_DEBUG
++	bool "EXT4 debugging support"
++	depends on EXT4_FS
++	help
++	  Enables run-time debugging support for the ext4 filesystem.
++
++	  If you select Y here, then you will be able to turn on debugging
++	  with a command such as "echo 1 > /sys/kernel/debug/ext4/mballoc-debug"
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 68cde598b3bf..d80b300c1779 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -22,6 +22,7 @@
+  */
+ 
+ #include "mballoc.h"
++#include 
+ #include 
+ 
+ /*
+@@ -743,7 +744,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
+ 	char *data;
+ 	char *bitmap;
+ 
+-	mb_debug("init page %lu\n", page->index);
++	mb_debug(1, "init page %lu\n", page->index);
+ 
+ 	inode = page->mapping->host;
+ 	sb = inode->i_sb;
+@@ -822,7 +823,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
+ 		set_bitmap_uptodate(bh[i]);
+ 		bh[i]->b_end_io = end_buffer_read_sync;
+ 		submit_bh(READ, bh[i]);
+-		mb_debug("read bitmap for group %u\n", first_group + i);
++		mb_debug(1, "read bitmap for group %u\n", first_group + i);
+ 	}
+ 
+ 	/* wait for I/O completion */
+@@ -862,7 +863,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
+ 		if ((first_block + i) & 1) {
+ 			/* this is block of buddy */
+ 			BUG_ON(incore == NULL);
+-			mb_debug("put buddy for group %u in page %lu/%x\n",
++			mb_debug(1, "put buddy for group %u in page %lu/%x\n",
+ 				group, page->index, i * blocksize);
+ 			grinfo = ext4_get_group_info(sb, group);
+ 			grinfo->bb_fragments = 0;
+@@ -878,7 +879,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
+ 		} else {
+ 			/* this is block of bitmap */
+ 			BUG_ON(incore != NULL);
+-			mb_debug("put bitmap for group %u in page %lu/%x\n",
++			mb_debug(1, "put bitmap for group %u in page %lu/%x\n",
+ 				group, page->index, i * blocksize);
+ 
+ 			/* see comments in ext4_mb_put_pa() */
+@@ -922,7 +923,7 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group,
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	struct inode *inode = sbi->s_buddy_cache;
+ 
+-	mb_debug("load group %u\n", group);
++	mb_debug(1, "load group %u\n", group);
+ 
+ 	blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize;
+ 	grp = ext4_get_group_info(sb, group);
+@@ -1851,7 +1852,7 @@ int ext4_mb_init_group(struct super_block *sb, ext4_group_t group)
+ 	struct inode *inode = sbi->s_buddy_cache;
+ 	struct page *page = NULL, *bitmap_page = NULL;
+ 
+-	mb_debug("init group %u\n", group);
++	mb_debug(1, "init group %u\n", group);
+ 	blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize;
+ 	this_grp = ext4_get_group_info(sb, group);
+ 	/*
+@@ -2739,7 +2740,7 @@ static void ext4_mb_cleanup_pa(struct ext4_group_info *grp)
+ 		kmem_cache_free(ext4_pspace_cachep, pa);
+ 	}
+ 	if (count)
+-		mb_debug("mballoc: %u PAs left\n", count);
++		mb_debug(1, "mballoc: %u PAs left\n", count);
+ 
+ }
+ 
+@@ -2820,7 +2821,7 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn)
+ 	list_for_each_safe(l, ltmp, &txn->t_private_list) {
+ 		entry = list_entry(l, struct ext4_free_data, list);
+ 
+-		mb_debug("gonna free %u blocks in group %u (0x%p):",
++		mb_debug(1, "gonna free %u blocks in group %u (0x%p):",
+ 			 entry->count, entry->group, entry);
+ 
+ 		err = ext4_mb_load_buddy(sb, entry->group, &e4b);
+@@ -2855,9 +2856,43 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn)
+ 		ext4_mb_release_desc(&e4b);
+ 	}
+ 
+-	mb_debug("freed %u blocks in %u structures\n", count, count2);
++	mb_debug(1, "freed %u blocks in %u structures\n", count, count2);
+ }
+ 
++#ifdef CONFIG_EXT4_DEBUG
++u8 mb_enable_debug __read_mostly;
++
++static struct dentry *debugfs_dir;
++static struct dentry *debugfs_debug;
++
++static void __init ext4_create_debugfs_entry(void)
++{
++	debugfs_dir = debugfs_create_dir("ext4", NULL);
++	if (debugfs_dir)
++		debugfs_debug = debugfs_create_u8("mballoc-debug",
++						  S_IRUGO | S_IWUSR,
++						  debugfs_dir,
++						  &mb_enable_debug);
++}
++
++static void ext4_remove_debugfs_entry(void)
++{
++	debugfs_remove(debugfs_debug);
++	debugfs_remove(debugfs_dir);
++}
++
++#else
++
++static void __init ext4_create_debugfs_entry(void)
++{
++}
++
++static void ext4_remove_debugfs_entry(void)
++{
++}
++
++#endif
++
+ int __init init_ext4_mballoc(void)
+ {
+ 	ext4_pspace_cachep =
+@@ -2885,6 +2920,7 @@ int __init init_ext4_mballoc(void)
+ 		kmem_cache_destroy(ext4_ac_cachep);
+ 		return -ENOMEM;
+ 	}
++	ext4_create_debugfs_entry();
+ 	return 0;
+ }
+ 
+@@ -2898,6 +2934,7 @@ void exit_ext4_mballoc(void)
+ 	kmem_cache_destroy(ext4_pspace_cachep);
+ 	kmem_cache_destroy(ext4_ac_cachep);
+ 	kmem_cache_destroy(ext4_free_ext_cachep);
++	ext4_remove_debugfs_entry();
+ }
+ 
+ 
+@@ -3042,7 +3079,7 @@ static void ext4_mb_normalize_group_request(struct ext4_allocation_context *ac)
+ 		ac->ac_g_ex.fe_len = EXT4_SB(sb)->s_stripe;
+ 	else
+ 		ac->ac_g_ex.fe_len = EXT4_SB(sb)->s_mb_group_prealloc;
+-	mb_debug("#%u: goal %u blocks for locality group\n",
++	mb_debug(1, "#%u: goal %u blocks for locality group\n",
+ 		current->pid, ac->ac_g_ex.fe_len);
+ }
+ 
+@@ -3232,7 +3269,7 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
+ 		ac->ac_flags |= EXT4_MB_HINT_TRY_GOAL;
+ 	}
+ 
+-	mb_debug("goal: %u(was %u) blocks at %u\n", (unsigned) size,
++	mb_debug(1, "goal: %u(was %u) blocks at %u\n", (unsigned) size,
+ 		(unsigned) orig_size, (unsigned) start);
+ }
+ 
+@@ -3281,7 +3318,7 @@ static void ext4_mb_use_inode_pa(struct ext4_allocation_context *ac,
+ 	BUG_ON(pa->pa_free < len);
+ 	pa->pa_free -= len;
+ 
+-	mb_debug("use %llu/%u from inode pa %p\n", start, len, pa);
++	mb_debug(1, "use %llu/%u from inode pa %p\n", start, len, pa);
+ }
+ 
+ /*
+@@ -3305,7 +3342,7 @@ static void ext4_mb_use_group_pa(struct ext4_allocation_context *ac,
+ 	 * in on-disk bitmap -- see ext4_mb_release_context()
+ 	 * Other CPUs are prevented from allocating from this pa by lg_mutex
+ 	 */
+-	mb_debug("use %u/%u from group pa %p\n", pa->pa_lstart-len, len, pa);
++	mb_debug(1, "use %u/%u from group pa %p\n", pa->pa_lstart-len, len, pa);
+ }
+ 
+ /*
+@@ -3484,7 +3521,7 @@ void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap,
+ 		preallocated += len;
+ 		count++;
+ 	}
+-	mb_debug("prellocated %u for group %u\n", preallocated, group);
++	mb_debug(1, "prellocated %u for group %u\n", preallocated, group);
+ }
+ 
+ static void ext4_mb_pa_callback(struct rcu_head *head)
+@@ -3619,7 +3656,7 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
+ 	pa->pa_deleted = 0;
+ 	pa->pa_type = MB_INODE_PA;
+ 
+-	mb_debug("new inode pa %p: %llu/%u for %u\n", pa,
++	mb_debug(1, "new inode pa %p: %llu/%u for %u\n", pa,
+ 			pa->pa_pstart, pa->pa_len, pa->pa_lstart);
+ 	trace_ext4_mb_new_inode_pa(ac, pa);
+ 
+@@ -3679,7 +3716,7 @@ ext4_mb_new_group_pa(struct ext4_allocation_context *ac)
+ 	pa->pa_deleted = 0;
+ 	pa->pa_type = MB_GROUP_PA;
+ 
+-	mb_debug("new group pa %p: %llu/%u for %u\n", pa,
++	mb_debug(1, "new group pa %p: %llu/%u for %u\n", pa,
+ 			pa->pa_pstart, pa->pa_len, pa->pa_lstart);
+ 	trace_ext4_mb_new_group_pa(ac, pa);
+ 
+@@ -3758,7 +3795,7 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh,
+ 		next = mb_find_next_bit(bitmap_bh->b_data, end, bit);
+ 		start = group * EXT4_BLOCKS_PER_GROUP(sb) + bit +
+ 				le32_to_cpu(sbi->s_es->s_first_data_block);
+-		mb_debug("    free preallocated %u/%u in group %u\n",
++		mb_debug(1, "    free preallocated %u/%u in group %u\n",
+ 				(unsigned) start, (unsigned) next - bit,
+ 				(unsigned) group);
+ 		free += next - bit;
+@@ -3849,7 +3886,7 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
+ 	int busy = 0;
+ 	int free = 0;
+ 
+-	mb_debug("discard preallocation for group %u\n", group);
++	mb_debug(1, "discard preallocation for group %u\n", group);
+ 
+ 	if (list_empty(&grp->bb_prealloc_list))
+ 		return 0;
+@@ -3973,7 +4010,7 @@ void ext4_discard_preallocations(struct inode *inode)
+ 		return;
+ 	}
+ 
+-	mb_debug("discard preallocation for inode %lu\n", inode->i_ino);
++	mb_debug(1, "discard preallocation for inode %lu\n", inode->i_ino);
+ 	trace_ext4_discard_preallocations(inode);
+ 
+ 	INIT_LIST_HEAD(&list);
+@@ -4078,7 +4115,7 @@ static void ext4_mb_return_to_preallocation(struct inode *inode,
+ {
+ 	BUG_ON(!list_empty(&EXT4_I(inode)->i_prealloc_list));
+ }
+-#ifdef MB_DEBUG
++#ifdef CONFIG_EXT4_DEBUG
+ static void ext4_mb_show_ac(struct ext4_allocation_context *ac)
+ {
+ 	struct super_block *sb = ac->ac_sb;
+@@ -4227,7 +4264,7 @@ ext4_mb_initialize_context(struct ext4_allocation_context *ac,
+ 	 * locality group. this is a policy, actually */
+ 	ext4_mb_group_or_file(ac);
+ 
+-	mb_debug("init ac: %u blocks @ %u, goal %u, flags %x, 2^%d, "
++	mb_debug(1, "init ac: %u blocks @ %u, goal %u, flags %x, 2^%d, "
+ 			"left: %u/%u, right %u/%u to %swritable\n",
+ 			(unsigned) ar->len, (unsigned) ar->logical,
+ 			(unsigned) ar->goal, ac->ac_flags, ac->ac_2order,
+@@ -4249,7 +4286,7 @@ ext4_mb_discard_lg_preallocations(struct super_block *sb,
+ 	struct ext4_prealloc_space *pa, *tmp;
+ 	struct ext4_allocation_context *ac;
+ 
+-	mb_debug("discard locality group preallocation\n");
++	mb_debug(1, "discard locality group preallocation\n");
+ 
+ 	INIT_LIST_HEAD(&discard_list);
+ 	ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
+diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
+index c96bb19f58f9..9db890d4d275 100644
+--- a/fs/ext4/mballoc.h
++++ b/fs/ext4/mballoc.h
+@@ -37,11 +37,19 @@
+ 
+ /*
+  */
+-#define MB_DEBUG__
+-#ifdef MB_DEBUG
+-#define mb_debug(fmt, a...)	printk(fmt, ##a)
++#ifdef CONFIG_EXT4_DEBUG
++extern u8 mb_enable_debug;
++
++#define mb_debug(n, fmt, a...)	                                        \
++	do {								\
++		if ((n) <= mb_enable_debug) {		        	\
++			printk(KERN_DEBUG "(%s, %d): %s: ",		\
++			       __FILE__, __LINE__, __func__);		\
++			printk(fmt, ## a);				\
++		}							\
++	} while (0)
+ #else
+-#define mb_debug(fmt, a...)
++#define mb_debug(n, fmt, a...)
+ #endif
+ 
+ /*

commit 833576b362e15c38be3bfe43942cda693e56287c
+Author: Theodore Ts'o 
+Date:   Mon Jul 13 09:45:52 2009 -0400
+
+    ext4: Fix ext4_mb_initialize_context() to initialize all fields
+    
+    Pavel Roskin pointed out that kmemcheck indicated that
+    ext4_mb_store_history() was accessing uninitialized values of
+    ac->ac_tail and ac->ac_buddy leading to garbage in the mballoc
+    history.  Fix this by initializing the entire structure to all zeros
+    first.
+    
+    Also, two fields were getting doubly initialized by the caller of
+    ext4_mb_initialize_context, so remove them for efficiency's sake.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 2fcaf286f1de..cd258463e2a9 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -4227,14 +4227,9 @@ ext4_mb_initialize_context(struct ext4_allocation_context *ac,
+ 	ext4_get_group_no_and_offset(sb, goal, &group, &block);
+ 
+ 	/* set up allocation goals */
++	memset(ac, 0, sizeof(struct ext4_allocation_context));
+ 	ac->ac_b_ex.fe_logical = ar->logical;
+-	ac->ac_b_ex.fe_group = 0;
+-	ac->ac_b_ex.fe_start = 0;
+-	ac->ac_b_ex.fe_len = 0;
+ 	ac->ac_status = AC_STATUS_CONTINUE;
+-	ac->ac_groups_scanned = 0;
+-	ac->ac_ex_scanned = 0;
+-	ac->ac_found = 0;
+ 	ac->ac_sb = sb;
+ 	ac->ac_inode = ar->inode;
+ 	ac->ac_o_ex.fe_logical = ar->logical;
+@@ -4245,15 +4240,7 @@ ext4_mb_initialize_context(struct ext4_allocation_context *ac,
+ 	ac->ac_g_ex.fe_group = group;
+ 	ac->ac_g_ex.fe_start = block;
+ 	ac->ac_g_ex.fe_len = len;
+-	ac->ac_f_ex.fe_len = 0;
+ 	ac->ac_flags = ar->flags;
+-	ac->ac_2order = 0;
+-	ac->ac_criteria = 0;
+-	ac->ac_pa = NULL;
+-	ac->ac_bitmap_page = NULL;
+-	ac->ac_buddy_page = NULL;
+-	ac->alloc_semp = NULL;
+-	ac->ac_lg = NULL;
+ 
+ 	/* we have to define context: we'll we work with a file or
+ 	 * locality group. this is a policy, actually */
+@@ -4521,10 +4508,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
+ 	}
+ 
+ 	ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
+-	if (ac) {
+-		ac->ac_sb = sb;
+-		ac->ac_inode = ar->inode;
+-	} else {
++	if (!ac) {
+ 		ar->len = 0;
+ 		*errp = -ENOMEM;
+ 		goto out1;

commit 78f1ddbb498283c2445c11b0dfa666424c301803
+Author: Theodore Ts'o 
+Date:   Mon Jul 27 23:09:47 2009 -0400
+
+    ext4: Avoid null pointer dereference when decoding EROFS w/o a journal
+    
+    We need to check to make sure a journal is present before checking the
+    journal flags in ext4_decode_error().
+    
+    Signed-off-by: Eric Sesterhenn 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 8f4f079e6b9a..fe3f376b7df2 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -344,7 +344,8 @@ static const char *ext4_decode_error(struct super_block *sb, int errno,
+ 		errstr = "Out of memory";
+ 		break;
+ 	case -EROFS:
+-		if (!sb || EXT4_SB(sb)->s_journal->j_flags & JBD2_ABORT)
++		if (!sb || (EXT4_SB(sb)->s_journal &&
++			    EXT4_SB(sb)->s_journal->j_flags & JBD2_ABORT))
+ 			errstr = "Journal has aborted";
+ 		else
+ 			errstr = "Readonly filesystem";

commit 210ad6aedb332e73167ece5af9bd47f0da8c2aca
+Author: Theodore Ts'o 
+Date:   Mon Jun 8 15:22:25 2009 -0400
+
+    ext4: avoid unnecessary spinlock in critical POSIX ACL path
+    
+    If a filesystem supports POSIX ACL's, the VFS layer expects the filesystem
+    to do POSIX ACL checks on any files not owned by the caller, and it does
+    this for every single pathname component that it looks up.
+    
+    That obviously can be pretty expensive if the filesystem isn't careful
+    about it, especially with locking. That's doubly sad, since the common
+    case tends to be that there are no ACL's associated with the files in
+    question.
+    
+    ext4 already caches the ACL data so that it doesn't have to look it up
+    over and over again, but it does so by taking the inode->i_lock spinlock
+    on every lookup. Which is a noticeable overhead even if it's a private
+    lock, especially on CPU's where the serialization is expensive (eg Intel
+    Netburst aka 'P4').
+    
+    For the special case of not actually having any ACL's, all that locking is
+    unnecessary. Even if somebody else were to be changing the ACL's on
+    another CPU, we simply don't care - if we've seen a NULL ACL, we might as
+    well use it.
+    
+    So just load the ACL speculatively without any locking, and if it was
+    NULL, just use it. If it's non-NULL (either because we had a cached
+    entry, or because the cache hasn't been filled in at all), it means that
+    we'll need to get the lock and re-load it properly.
+    
+    (This commit was ported from a patch originally authored by Linus for
+    ext3.)
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Al Viro 
+
+diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
+index 647e0d65a284..605aeed96d68 100644
+--- a/fs/ext4/acl.c
++++ b/fs/ext4/acl.c
+@@ -129,12 +129,15 @@ ext4_acl_to_disk(const struct posix_acl *acl, size_t *size)
+ static inline struct posix_acl *
+ ext4_iget_acl(struct inode *inode, struct posix_acl **i_acl)
+ {
+-	struct posix_acl *acl = EXT4_ACL_NOT_CACHED;
++	struct posix_acl *acl = ACCESS_ONCE(*i_acl);
+ 
+-	spin_lock(&inode->i_lock);
+-	if (*i_acl != EXT4_ACL_NOT_CACHED)
+-		acl = posix_acl_dup(*i_acl);
+-	spin_unlock(&inode->i_lock);
++	if (acl) {
++		spin_lock(&inode->i_lock);
++		acl = *i_acl;
++		if (acl != EXT4_ACL_NOT_CACHED)
++			acl = posix_acl_dup(acl);
++		spin_unlock(&inode->i_lock);
++	}
+ 
+ 	return acl;
+ }

commit 4159175058987cb68aefd0e9eec2598b795363b4
+Author: Theodore Ts'o 
+Date:   Mon Jun 15 03:41:23 2009 -0400
+
+    ext4: Don't update ctime for non-extent-mapped inodes
+    
+    The VFS handles updating ctime, so we don't need to update the inode's
+    ctime in ext4_splace_branch() to update the direct or indirect blocks.
+    This was harmless when we did this in ext3, but in ext4, thanks to
+    delayed allocation, updating the ctime in ext4_splice_branch() can
+    cause the ctime to mysteriously jump when the blocks are finally
+    allocated.
+    
+    Thanks to Björn Steinbrink for pointing out this problem on the git
+    mailing list.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 8d0908afbd5b..7c17ae275af4 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -856,10 +856,6 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
+ 	}
+ 
+ 	/* We are done with atomic stuff, now do the rest of housekeeping */
+-
+-	inode->i_ctime = ext4_current_time(inode);
+-	ext4_mark_inode_dirty(handle, inode);
+-
+ 	/* had we spliced it onto indirect block? */
+ 	if (where->bh) {
+ 		/*
+@@ -878,8 +874,8 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
+ 	} else {
+ 		/*
+ 		 * OK, we spliced it into the inode itself on a direct block.
+-		 * Inode was dirtied above.
+ 		 */
++		ext4_mark_inode_dirty(handle, inode);
+ 		jbd_debug(5, "splicing direct\n");
+ 	}
+ 	return err;

commit de9a55b841132f7ae097f6e31ccebad2d5030cf5
+Author: Theodore Ts'o 
+Date:   Sun Jun 14 17:45:34 2009 -0400
+
+    ext4: Fix up whitespace issues in fs/ext4/inode.c
+    
+    This is a pure cleanup patch.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 5f927f6a1289..8d0908afbd5b 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -81,7 +81,7 @@ static int ext4_inode_is_fast_symlink(struct inode *inode)
+  * If the handle isn't valid we're not journaling so there's nothing to do.
+  */
+ int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode,
+-			struct buffer_head *bh, ext4_fsblk_t blocknr)
++		struct buffer_head *bh, ext4_fsblk_t blocknr)
+ {
+ 	int err;
+ 
+@@ -332,8 +332,8 @@ static inline void add_chain(Indirect *p, struct buffer_head *bh, __le32 *v)
+  */
+ 
+ static int ext4_block_to_path(struct inode *inode,
+-			ext4_lblk_t i_block,
+-			ext4_lblk_t offsets[4], int *boundary)
++			      ext4_lblk_t i_block,
++			      ext4_lblk_t offsets[4], int *boundary)
+ {
+ 	int ptrs = EXT4_ADDR_PER_BLOCK(inode->i_sb);
+ 	int ptrs_bits = EXT4_ADDR_PER_BLOCK_BITS(inode->i_sb);
+@@ -365,9 +365,9 @@ static int ext4_block_to_path(struct inode *inode,
+ 		final = ptrs;
+ 	} else {
+ 		ext4_warning(inode->i_sb, "ext4_block_to_path",
+-				"block %lu > max in inode %lu",
+-				i_block + direct_blocks +
+-				indirect_blocks + double_blocks, inode->i_ino);
++			     "block %lu > max in inode %lu",
++			     i_block + direct_blocks +
++			     indirect_blocks + double_blocks, inode->i_ino);
+ 	}
+ 	if (boundary)
+ 		*boundary = final - 1 - (i_block & (ptrs - 1));
+@@ -382,25 +382,25 @@ static int __ext4_check_blockref(const char *function, struct inode *inode,
+ 
+ 	while (bref < p+max) {
+ 		blk = le32_to_cpu(*bref++);
+-		if (blk && 
+-		    unlikely(!ext4_data_block_valid(EXT4_SB(inode->i_sb), 
++		if (blk &&
++		    unlikely(!ext4_data_block_valid(EXT4_SB(inode->i_sb),
+ 						    blk, 1))) {
+ 			ext4_error(inode->i_sb, function,
+ 				   "invalid block reference %u "
+ 				   "in inode #%lu", blk, inode->i_ino);
+- 			return -EIO;
+- 		}
+- 	}
+- 	return 0;
++			return -EIO;
++		}
++	}
++	return 0;
+ }
+ 
+ 
+ #define ext4_check_indirect_blockref(inode, bh)                         \
+-        __ext4_check_blockref(__func__, inode, (__le32 *)(bh)->b_data,  \
++	__ext4_check_blockref(__func__, inode, (__le32 *)(bh)->b_data,  \
+ 			      EXT4_ADDR_PER_BLOCK((inode)->i_sb))
+ 
+ #define ext4_check_inode_blockref(inode)                                \
+-        __ext4_check_blockref(__func__, inode, EXT4_I(inode)->i_data,   \
++	__ext4_check_blockref(__func__, inode, EXT4_I(inode)->i_data,   \
+ 			      EXT4_NDIR_BLOCKS)
+ 
+ /**
+@@ -450,7 +450,7 @@ static Indirect *ext4_get_branch(struct inode *inode, int depth,
+ 		bh = sb_getblk(sb, le32_to_cpu(p->key));
+ 		if (unlikely(!bh))
+ 			goto failure;
+-                  
++
+ 		if (!bh_uptodate_or_lock(bh)) {
+ 			if (bh_submit_read(bh) < 0) {
+ 				put_bh(bh);
+@@ -462,7 +462,7 @@ static Indirect *ext4_get_branch(struct inode *inode, int depth,
+ 				goto failure;
+ 			}
+ 		}
+-		
++
+ 		add_chain(++p, bh, (__le32 *)bh->b_data + *++offsets);
+ 		/* Reader: end */
+ 		if (!p->key)
+@@ -555,7 +555,7 @@ static ext4_fsblk_t ext4_find_near(struct inode *inode, Indirect *ind)
+  *	returns it.
+  */
+ static ext4_fsblk_t ext4_find_goal(struct inode *inode, ext4_lblk_t block,
+-		Indirect *partial)
++				   Indirect *partial)
+ {
+ 	/*
+ 	 * XXX need to get goal block from mballoc's data structures
+@@ -577,7 +577,7 @@ static ext4_fsblk_t ext4_find_goal(struct inode *inode, ext4_lblk_t block,
+  *	direct and indirect blocks.
+  */
+ static int ext4_blks_to_allocate(Indirect *branch, int k, unsigned int blks,
+-		int blocks_to_boundary)
++				 int blocks_to_boundary)
+ {
+ 	unsigned int count = 0;
+ 
+@@ -613,9 +613,9 @@ static int ext4_blks_to_allocate(Indirect *branch, int k, unsigned int blks,
+  *		direct blocks
+  */
+ static int ext4_alloc_blocks(handle_t *handle, struct inode *inode,
+-				ext4_lblk_t iblock, ext4_fsblk_t goal,
+-				int indirect_blks, int blks,
+-				ext4_fsblk_t new_blocks[4], int *err)
++			     ext4_lblk_t iblock, ext4_fsblk_t goal,
++			     int indirect_blks, int blks,
++			     ext4_fsblk_t new_blocks[4], int *err)
+ {
+ 	struct ext4_allocation_request ar;
+ 	int target, i;
+@@ -686,10 +686,10 @@ static int ext4_alloc_blocks(handle_t *handle, struct inode *inode,
+ 	}
+ 	if (!*err) {
+ 		if (target == blks) {
+-		/*
+-		 * save the new block number
+-		 * for the first direct block
+-		 */
++			/*
++			 * save the new block number
++			 * for the first direct block
++			 */
+ 			new_blocks[index] = current_block;
+ 		}
+ 		blk_allocated += ar.len;
+@@ -731,9 +731,9 @@ static int ext4_alloc_blocks(handle_t *handle, struct inode *inode,
+  *	as described above and return 0.
+  */
+ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
+-				ext4_lblk_t iblock, int indirect_blks,
+-				int *blks, ext4_fsblk_t goal,
+-				ext4_lblk_t *offsets, Indirect *branch)
++			     ext4_lblk_t iblock, int indirect_blks,
++			     int *blks, ext4_fsblk_t goal,
++			     ext4_lblk_t *offsets, Indirect *branch)
+ {
+ 	int blocksize = inode->i_sb->s_blocksize;
+ 	int i, n = 0;
+@@ -780,7 +780,7 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
+ 			 * the chain to point to the new allocated
+ 			 * data blocks numbers
+ 			 */
+-			for (i=1; i < num; i++)
++			for (i = 1; i < num; i++)
+ 				*(branch[n].p + i) = cpu_to_le32(++current_block);
+ 		}
+ 		BUFFER_TRACE(bh, "marking uptodate");
+@@ -823,7 +823,8 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
+  * chain to new block and return 0.
+  */
+ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
+-			ext4_lblk_t block, Indirect *where, int num, int blks)
++			      ext4_lblk_t block, Indirect *where, int num,
++			      int blks)
+ {
+ 	int i;
+ 	int err = 0;
+@@ -924,9 +925,9 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
+  * blocks.
+  */
+ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode,
+-				  ext4_lblk_t iblock, unsigned int maxblocks,
+-				  struct buffer_head *bh_result,
+-				  int flags)
++			       ext4_lblk_t iblock, unsigned int maxblocks,
++			       struct buffer_head *bh_result,
++			       int flags)
+ {
+ 	int err = -EIO;
+ 	ext4_lblk_t offsets[4];
+@@ -942,7 +943,7 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode,
+ 	J_ASSERT(!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL));
+ 	J_ASSERT(handle != NULL || (flags & EXT4_GET_BLOCKS_CREATE) == 0);
+ 	depth = ext4_block_to_path(inode, iblock, offsets,
+-					&blocks_to_boundary);
++				   &blocks_to_boundary);
+ 
+ 	if (depth == 0)
+ 		goto out;
+@@ -990,8 +991,8 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode,
+ 	 * Block out ext4_truncate while we alter the tree
+ 	 */
+ 	err = ext4_alloc_branch(handle, inode, iblock, indirect_blks,
+-					&count, goal,
+-					offsets + (partial - chain), partial);
++				&count, goal,
++				offsets + (partial - chain), partial);
+ 
+ 	/*
+ 	 * The ext4_splice_branch call will free and forget any buffers
+@@ -1002,8 +1003,8 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode,
+ 	 */
+ 	if (!err)
+ 		err = ext4_splice_branch(handle, inode, iblock,
+-					partial, indirect_blks, count);
+-	else 
++					 partial, indirect_blks, count);
++	else
+ 		goto cleanup;
+ 
+ 	set_buffer_new(bh_result);
+@@ -1175,7 +1176,7 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block,
+ 	up_read((&EXT4_I(inode)->i_data_sem));
+ 
+ 	if (retval > 0 && buffer_mapped(bh)) {
+-		int ret = check_block_validity(inode, block, 
++		int ret = check_block_validity(inode, block,
+ 					       bh->b_blocknr, retval);
+ 		if (ret != 0)
+ 			return ret;
+@@ -1257,7 +1258,7 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block,
+ 
+ 	up_write((&EXT4_I(inode)->i_data_sem));
+ 	if (retval > 0 && buffer_mapped(bh)) {
+-		int ret = check_block_validity(inode, block, 
++		int ret = check_block_validity(inode, block,
+ 					       bh->b_blocknr, retval);
+ 		if (ret != 0)
+ 			return ret;
+@@ -1408,8 +1409,7 @@ static int walk_page_buffers(handle_t *handle,
+ 
+ 	for (bh = head, block_start = 0;
+ 	     ret == 0 && (bh != head || !block_start);
+-	     block_start = block_end, bh = next)
+-	{
++	     block_start = block_end, bh = next) {
+ 		next = bh->b_this_page;
+ 		block_end = block_start + blocksize;
+ 		if (block_end <= from || block_start >= to) {
+@@ -1450,7 +1450,7 @@ static int walk_page_buffers(handle_t *handle,
+  * write.
+  */
+ static int do_journal_get_write_access(handle_t *handle,
+-					struct buffer_head *bh)
++				       struct buffer_head *bh)
+ {
+ 	if (!buffer_mapped(bh) || buffer_freed(bh))
+ 		return 0;
+@@ -1458,15 +1458,15 @@ static int do_journal_get_write_access(handle_t *handle,
+ }
+ 
+ static int ext4_write_begin(struct file *file, struct address_space *mapping,
+-				loff_t pos, unsigned len, unsigned flags,
+-				struct page **pagep, void **fsdata)
++			    loff_t pos, unsigned len, unsigned flags,
++			    struct page **pagep, void **fsdata)
+ {
+ 	struct inode *inode = mapping->host;
+ 	int ret, needed_blocks;
+ 	handle_t *handle;
+ 	int retries = 0;
+ 	struct page *page;
+- 	pgoff_t index;
++	pgoff_t index;
+ 	unsigned from, to;
+ 
+ 	trace_ext4_write_begin(inode, pos, len, flags);
+@@ -1475,7 +1475,7 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
+ 	 * we allocate blocks but write fails for some reason
+ 	 */
+ 	needed_blocks = ext4_writepage_trans_blocks(inode) + 1;
+- 	index = pos >> PAGE_CACHE_SHIFT;
++	index = pos >> PAGE_CACHE_SHIFT;
+ 	from = pos & (PAGE_CACHE_SIZE - 1);
+ 	to = from + len;
+ 
+@@ -1523,7 +1523,7 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
+ 		ext4_journal_stop(handle);
+ 		if (pos + len > inode->i_size) {
+ 			vmtruncate(inode, inode->i_size);
+-			/* 
++			/*
+ 			 * If vmtruncate failed early the inode might
+ 			 * still be on the orphan list; we need to
+ 			 * make sure the inode is removed from the
+@@ -1550,9 +1550,9 @@ static int write_end_fn(handle_t *handle, struct buffer_head *bh)
+ }
+ 
+ static int ext4_generic_write_end(struct file *file,
+-				struct address_space *mapping,
+-				loff_t pos, unsigned len, unsigned copied,
+-				struct page *page, void *fsdata)
++				  struct address_space *mapping,
++				  loff_t pos, unsigned len, unsigned copied,
++				  struct page *page, void *fsdata)
+ {
+ 	int i_size_changed = 0;
+ 	struct inode *inode = mapping->host;
+@@ -1603,9 +1603,9 @@ static int ext4_generic_write_end(struct file *file,
+  * buffers are managed internally.
+  */
+ static int ext4_ordered_write_end(struct file *file,
+-				struct address_space *mapping,
+-				loff_t pos, unsigned len, unsigned copied,
+-				struct page *page, void *fsdata)
++				  struct address_space *mapping,
++				  loff_t pos, unsigned len, unsigned copied,
++				  struct page *page, void *fsdata)
+ {
+ 	handle_t *handle = ext4_journal_current_handle();
+ 	struct inode *inode = mapping->host;
+@@ -1633,7 +1633,7 @@ static int ext4_ordered_write_end(struct file *file,
+ 
+ 	if (pos + len > inode->i_size) {
+ 		vmtruncate(inode, inode->i_size);
+-		/* 
++		/*
+ 		 * If vmtruncate failed early the inode might still be
+ 		 * on the orphan list; we need to make sure the inode
+ 		 * is removed from the orphan list in that case.
+@@ -1647,9 +1647,9 @@ static int ext4_ordered_write_end(struct file *file,
+ }
+ 
+ static int ext4_writeback_write_end(struct file *file,
+-				struct address_space *mapping,
+-				loff_t pos, unsigned len, unsigned copied,
+-				struct page *page, void *fsdata)
++				    struct address_space *mapping,
++				    loff_t pos, unsigned len, unsigned copied,
++				    struct page *page, void *fsdata)
+ {
+ 	handle_t *handle = ext4_journal_current_handle();
+ 	struct inode *inode = mapping->host;
+@@ -1675,7 +1675,7 @@ static int ext4_writeback_write_end(struct file *file,
+ 
+ 	if (pos + len > inode->i_size) {
+ 		vmtruncate(inode, inode->i_size);
+-		/* 
++		/*
+ 		 * If vmtruncate failed early the inode might still be
+ 		 * on the orphan list; we need to make sure the inode
+ 		 * is removed from the orphan list in that case.
+@@ -1688,9 +1688,9 @@ static int ext4_writeback_write_end(struct file *file,
+ }
+ 
+ static int ext4_journalled_write_end(struct file *file,
+-				struct address_space *mapping,
+-				loff_t pos, unsigned len, unsigned copied,
+-				struct page *page, void *fsdata)
++				     struct address_space *mapping,
++				     loff_t pos, unsigned len, unsigned copied,
++				     struct page *page, void *fsdata)
+ {
+ 	handle_t *handle = ext4_journal_current_handle();
+ 	struct inode *inode = mapping->host;
+@@ -1738,7 +1738,7 @@ static int ext4_journalled_write_end(struct file *file,
+ 		ret = ret2;
+ 	if (pos + len > inode->i_size) {
+ 		vmtruncate(inode, inode->i_size);
+-		/* 
++		/*
+ 		 * If vmtruncate failed early the inode might still be
+ 		 * on the orphan list; we need to make sure the inode
+ 		 * is removed from the orphan list in that case.
+@@ -1845,7 +1845,7 @@ static void ext4_da_release_space(struct inode *inode, int to_free)
+ }
+ 
+ static void ext4_da_page_release_reservation(struct page *page,
+-						unsigned long offset)
++					     unsigned long offset)
+ {
+ 	int to_release = 0;
+ 	struct buffer_head *head, *bh;
+@@ -2854,8 +2854,8 @@ static int ext4_nonda_switch(struct super_block *sb)
+ }
+ 
+ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
+-				loff_t pos, unsigned len, unsigned flags,
+-				struct page **pagep, void **fsdata)
++			       loff_t pos, unsigned len, unsigned flags,
++			       struct page **pagep, void **fsdata)
+ {
+ 	int ret, retries = 0;
+ 	struct page *page;
+@@ -2925,7 +2925,7 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
+  * when write to the end of file but not require block allocation
+  */
+ static int ext4_da_should_update_i_disksize(struct page *page,
+-					 unsigned long offset)
++					    unsigned long offset)
+ {
+ 	struct buffer_head *bh;
+ 	struct inode *inode = page->mapping->host;
+@@ -2944,9 +2944,9 @@ static int ext4_da_should_update_i_disksize(struct page *page,
+ }
+ 
+ static int ext4_da_write_end(struct file *file,
+-				struct address_space *mapping,
+-				loff_t pos, unsigned len, unsigned copied,
+-				struct page *page, void *fsdata)
++			     struct address_space *mapping,
++			     loff_t pos, unsigned len, unsigned copied,
++			     struct page *page, void *fsdata)
+ {
+ 	struct inode *inode = mapping->host;
+ 	int ret = 0, ret2;
+@@ -3044,7 +3044,7 @@ int ext4_alloc_da_blocks(struct inode *inode)
+ 	 * not strictly speaking necessary (and for users of
+ 	 * laptop_mode, not even desirable).  However, to do otherwise
+ 	 * would require replicating code paths in:
+-	 * 
++	 *
+ 	 * ext4_da_writepages() ->
+ 	 *    write_cache_pages() ---> (via passed in callback function)
+ 	 *        __mpage_da_writepage() -->
+@@ -3064,7 +3064,7 @@ int ext4_alloc_da_blocks(struct inode *inode)
+ 	 * write out the pages, but rather only collect contiguous
+ 	 * logical block extents, call the multi-block allocator, and
+ 	 * then update the buffer heads with the block allocations.
+-	 * 
++	 *
+ 	 * For now, though, we'll cheat by calling filemap_flush(),
+ 	 * which will map the blocks, and start the I/O, but not
+ 	 * actually wait for the I/O to complete.
+@@ -3200,7 +3200,7 @@ static int bput_one(handle_t *handle, struct buffer_head *bh)
+  *
+  */
+ static int __ext4_normal_writepage(struct page *page,
+-				struct writeback_control *wbc)
++				   struct writeback_control *wbc)
+ {
+ 	struct inode *inode = page->mapping->host;
+ 
+@@ -3212,7 +3212,7 @@ static int __ext4_normal_writepage(struct page *page,
+ }
+ 
+ static int ext4_normal_writepage(struct page *page,
+-				struct writeback_control *wbc)
++				 struct writeback_control *wbc)
+ {
+ 	struct inode *inode = page->mapping->host;
+ 	loff_t size = i_size_read(inode);
+@@ -3248,7 +3248,7 @@ static int ext4_normal_writepage(struct page *page,
+ }
+ 
+ static int __ext4_journalled_writepage(struct page *page,
+-				struct writeback_control *wbc)
++				       struct writeback_control *wbc)
+ {
+ 	struct address_space *mapping = page->mapping;
+ 	struct inode *inode = mapping->host;
+@@ -3298,7 +3298,7 @@ static int __ext4_journalled_writepage(struct page *page,
+ }
+ 
+ static int ext4_journalled_writepage(struct page *page,
+-				struct writeback_control *wbc)
++				     struct writeback_control *wbc)
+ {
+ 	struct inode *inode = page->mapping->host;
+ 	loff_t size = i_size_read(inode);
+@@ -3401,8 +3401,8 @@ static int ext4_releasepage(struct page *page, gfp_t wait)
+  * VFS code falls back into buffered path in that case so we are safe.
+  */
+ static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb,
+-			const struct iovec *iov, loff_t offset,
+-			unsigned long nr_segs)
++			      const struct iovec *iov, loff_t offset,
++			      unsigned long nr_segs)
+ {
+ 	struct file *file = iocb->ki_filp;
+ 	struct inode *inode = file->f_mapping->host;
+@@ -3722,7 +3722,8 @@ static inline int all_zeroes(__le32 *p, __le32 *q)
+  *			(no partially truncated stuff there).  */
+ 
+ static Indirect *ext4_find_shared(struct inode *inode, int depth,
+-			ext4_lblk_t offsets[4], Indirect chain[4], __le32 *top)
++				  ext4_lblk_t offsets[4], Indirect chain[4],
++				  __le32 *top)
+ {
+ 	Indirect *partial, *p;
+ 	int k, err;
+@@ -3778,8 +3779,10 @@ static Indirect *ext4_find_shared(struct inode *inode, int depth,
+  * than `count' because there can be holes in there.
+  */
+ static void ext4_clear_blocks(handle_t *handle, struct inode *inode,
+-		struct buffer_head *bh, ext4_fsblk_t block_to_free,
+-		unsigned long count, __le32 *first, __le32 *last)
++			      struct buffer_head *bh,
++			      ext4_fsblk_t block_to_free,
++			      unsigned long count, __le32 *first,
++			      __le32 *last)
+ {
+ 	__le32 *p;
+ 	if (try_to_extend_transaction(handle, inode)) {
+@@ -3796,10 +3799,11 @@ static void ext4_clear_blocks(handle_t *handle, struct inode *inode,
+ 	}
+ 
+ 	/*
+-	 * Any buffers which are on the journal will be in memory. We find
+-	 * them on the hash table so jbd2_journal_revoke() will run jbd2_journal_forget()
+-	 * on them.  We've already detached each block from the file, so
+-	 * bforget() in jbd2_journal_forget() should be safe.
++	 * Any buffers which are on the journal will be in memory. We
++	 * find them on the hash table so jbd2_journal_revoke() will
++	 * run jbd2_journal_forget() on them.  We've already detached
++	 * each block from the file, so bforget() in
++	 * jbd2_journal_forget() should be safe.
+ 	 *
+ 	 * AKPM: turn on bforget in jbd2_journal_forget()!!!
+ 	 */
+@@ -4171,7 +4175,7 @@ void ext4_truncate(struct inode *inode)
+ 				   (__le32*)partial->bh->b_data+addr_per_block,
+ 				   (chain+n-1) - partial);
+ 		BUFFER_TRACE(partial->bh, "call brelse");
+-		brelse (partial->bh);
++		brelse(partial->bh);
+ 		partial--;
+ 	}
+ do_indirects:
+@@ -4412,8 +4416,9 @@ void ext4_get_inode_flags(struct ext4_inode_info *ei)
+ 	if (flags & S_DIRSYNC)
+ 		ei->i_flags |= EXT4_DIRSYNC_FL;
+ }
++
+ static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode,
+-					struct ext4_inode_info *ei)
++				  struct ext4_inode_info *ei)
+ {
+ 	blkcnt_t i_blocks ;
+ 	struct inode *inode = &(ei->vfs_inode);
+@@ -4528,7 +4533,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 					EXT4_GOOD_OLD_INODE_SIZE +
+ 					ei->i_extra_isize;
+ 			if (*magic == cpu_to_le32(EXT4_XATTR_MAGIC))
+-				 ei->i_state |= EXT4_STATE_XATTR;
++				ei->i_state |= EXT4_STATE_XATTR;
+ 		}
+ 	} else
+ 		ei->i_extra_isize = 0;
+@@ -4547,7 +4552,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 
+ 	ret = 0;
+ 	if (ei->i_file_acl &&
+-	    ((ei->i_file_acl < 
++	    ((ei->i_file_acl <
+ 	      (le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block) +
+ 	       EXT4_SB(sb)->s_gdb_count)) ||
+ 	     (ei->i_file_acl >= ext4_blocks_count(EXT4_SB(sb)->s_es)))) {
+@@ -4562,15 +4567,15 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 		     !ext4_inode_is_fast_symlink(inode)))
+ 			/* Validate extent which is part of inode */
+ 			ret = ext4_ext_check_inode(inode);
+- 	} else if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
++	} else if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+ 		   (S_ISLNK(inode->i_mode) &&
+ 		    !ext4_inode_is_fast_symlink(inode))) {
+-	 	/* Validate block references which are part of inode */
++		/* Validate block references which are part of inode */
+ 		ret = ext4_check_inode_blockref(inode);
+ 	}
+ 	if (ret) {
+- 		brelse(bh);
+- 		goto bad_inode;
++		brelse(bh);
++		goto bad_inode;
+ 	}
+ 
+ 	if (S_ISREG(inode->i_mode)) {
+@@ -4601,7 +4606,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 	} else {
+ 		brelse(bh);
+ 		ret = -EIO;
+-		ext4_error(inode->i_sb, __func__, 
++		ext4_error(inode->i_sb, __func__,
+ 			   "bogus i_mode (%o) for inode=%lu",
+ 			   inode->i_mode, inode->i_ino);
+ 		goto bad_inode;
+@@ -4754,8 +4759,9 @@ static int ext4_do_update_inode(handle_t *handle,
+ 				cpu_to_le32(new_encode_dev(inode->i_rdev));
+ 			raw_inode->i_block[2] = 0;
+ 		}
+-	} else for (block = 0; block < EXT4_N_BLOCKS; block++)
+-		raw_inode->i_block[block] = ei->i_data[block];
++	} else
++		for (block = 0; block < EXT4_N_BLOCKS; block++)
++			raw_inode->i_block[block] = ei->i_data[block];
+ 
+ 	raw_inode->i_disk_version = cpu_to_le32(inode->i_version);
+ 	if (ei->i_extra_isize) {
+@@ -5109,7 +5115,7 @@ int ext4_chunk_trans_blocks(struct inode *inode, int nrblocks)
+  * Give this, we know that the caller already has write access to iloc->bh.
+  */
+ int ext4_mark_iloc_dirty(handle_t *handle,
+-		struct inode *inode, struct ext4_iloc *iloc)
++			 struct inode *inode, struct ext4_iloc *iloc)
+ {
+ 	int err = 0;
+ 

commit 0610b6e99939828b77eec020ead0e1f44cba38ca
+Author: Theodore Ts'o 
+Date:   Mon Jun 15 03:45:05 2009 -0400
+
+    ext4: Fix 64-bit block type problem on 32-bit platforms
+    
+    The function ext4_mb_free_blocks() was using an "unsigned long" to
+    pass a block number; this will cause 64-bit block numbers to get
+    truncated on x86 and other 32-bit platforms.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Eric Sandeen 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 746cdcba969d..17b9998680e3 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1341,7 +1341,7 @@ extern void ext4_discard_preallocations(struct inode *);
+ extern int __init init_ext4_mballoc(void);
+ extern void exit_ext4_mballoc(void);
+ extern void ext4_mb_free_blocks(handle_t *, struct inode *,
+-		unsigned long, unsigned long, int, unsigned long *);
++		ext4_fsblk_t, unsigned long, int, unsigned long *);
+ extern int ext4_mb_add_groupinfo(struct super_block *sb,
+ 		ext4_group_t i, struct ext4_group_desc *desc);
+ extern void ext4_mb_update_group_info(struct ext4_group_info *grp,
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 8d98070b48fb..519a0a686d94 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -4689,7 +4689,7 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
+  * Main entry point into mballoc to free blocks
+  */
+ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
+-			unsigned long block, unsigned long count,
++			ext4_fsblk_t block, unsigned long count,
+ 			int metadata, unsigned long *freed)
+ {
+ 	struct buffer_head *bitmap_bh = NULL;
+@@ -4715,11 +4715,11 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
+ 	    block + count > ext4_blocks_count(es)) {
+ 		ext4_error(sb, __func__,
+ 			    "Freeing blocks not in datazone - "
+-			    "block = %lu, count = %lu", block, count);
++			    "block = %llu, count = %lu", block, count);
+ 		goto error_return;
+ 	}
+ 
+-	ext4_debug("freeing block %lu\n", block);
++	ext4_debug("freeing block %llu\n", block);
+ 	trace_ext4_free_blocks(inode, block, count, metadata);
+ 
+ 	ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
+@@ -4761,7 +4761,7 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
+ 
+ 		ext4_error(sb, __func__,
+ 			   "Freeing blocks in system zone - "
+-			   "Block = %lu, count = %lu", block, count);
++			   "Block = %llu, count = %lu", block, count);
+ 		/* err = 0. ext4_std_error should be a no op */
+ 		goto error_return;
+ 	}

commit f157a4aa98a18bd3817a72bea90d48494e2586e7
+Author: Theodore Ts'o 
+Date:   Sat Jun 13 11:09:42 2009 -0400
+
+    ext4: Use a hash of the topdir directory name for the Orlov parent group
+    
+    Instead of using a random number to determine the goal parent grop for
+    the Orlov top directories, use a hash of the directory name.  This
+    allows for repeatable results when trying to benchmark filesystem
+    layout algorithms.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 06ee5a582917..d035cf149e0e 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1315,7 +1315,8 @@ extern int ext4fs_dirhash(const char *name, int len, struct
+ 			  dx_hash_info *hinfo);
+ 
+ /* ialloc.c */
+-extern struct inode * ext4_new_inode(handle_t *, struct inode *, int);
++extern struct inode *ext4_new_inode(handle_t *, struct inode *, int,
++				    const struct qstr *qstr);
+ extern void ext4_free_inode(handle_t *, struct inode *);
+ extern struct inode * ext4_orphan_get(struct super_block *, unsigned long);
+ extern unsigned long ext4_count_free_inodes(struct super_block *);
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 7d502f3be914..3f98ee712ff4 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -470,7 +470,8 @@ void get_orlov_stats(struct super_block *sb, ext4_group_t g,
+  */
+ 
+ static int find_group_orlov(struct super_block *sb, struct inode *parent,
+-			    ext4_group_t *group, int mode)
++			    ext4_group_t *group, int mode,
++			    const struct qstr *qstr)
+ {
+ 	ext4_group_t parent_group = EXT4_I(parent)->i_block_group;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+@@ -485,6 +486,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
+ 	struct ext4_group_desc *desc;
+ 	struct orlov_stats stats;
+ 	int flex_size = ext4_flex_bg_size(sbi);
++	struct dx_hash_info hinfo;
+ 
+ 	ngroups = real_ngroups;
+ 	if (flex_size > 1) {
+@@ -506,7 +508,13 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
+ 		int best_ndir = inodes_per_group;
+ 		int ret = -1;
+ 
+-		get_random_bytes(&grp, sizeof(grp));
++		if (qstr) {
++			hinfo.hash_version = DX_HASH_HALF_MD4;
++			hinfo.seed = sbi->s_hash_seed;
++			ext4fs_dirhash(qstr->name, qstr->len, &hinfo);
++			grp = hinfo.hash;
++		} else
++			get_random_bytes(&grp, sizeof(grp));
+ 		parent_group = (unsigned)grp % ngroups;
+ 		for (i = 0; i < ngroups; i++) {
+ 			g = (parent_group + i) % ngroups;
+@@ -649,7 +657,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent,
+ 		*group = parent_group + flex_size;
+ 		if (*group > ngroups)
+ 			*group = 0;
+-		return find_group_orlov(sb, parent, group, mode);
++		return find_group_orlov(sb, parent, group, mode, 0);
+ 	}
+ 
+ 	/*
+@@ -790,7 +798,8 @@ static int ext4_claim_inode(struct super_block *sb,
+  * For other inodes, search forward from the parent directory's block
+  * group to find a free inode.
+  */
+-struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
++struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
++			     const struct qstr *qstr)
+ {
+ 	struct super_block *sb;
+ 	struct buffer_head *inode_bitmap_bh = NULL;
+@@ -839,7 +848,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
+ 		if (test_opt(sb, OLDALLOC))
+ 			ret2 = find_group_dir(sb, dir, &group);
+ 		else
+-			ret2 = find_group_orlov(sb, dir, &group, mode);
++			ret2 = find_group_orlov(sb, dir, &group, mode, qstr);
+ 	} else
+ 		ret2 = find_group_other(sb, dir, &group, mode);
+ 
+diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
+index fe64d9f79852..80d075b8aeaf 100644
+--- a/fs/ext4/migrate.c
++++ b/fs/ext4/migrate.c
+@@ -483,9 +483,8 @@ int ext4_ext_migrate(struct inode *inode)
+ 		retval = PTR_ERR(handle);
+ 		return retval;
+ 	}
+-	tmp_inode = ext4_new_inode(handle,
+-				inode->i_sb->s_root->d_inode,
+-				S_IFREG);
++	tmp_inode = ext4_new_inode(handle, inode->i_sb->s_root->d_inode,
++				   S_IFREG, 0);
+ 	if (IS_ERR(tmp_inode)) {
+ 		retval = -ENOMEM;
+ 		ext4_journal_stop(handle);
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 07eb6649e4fa..5f00d2418a83 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1782,7 +1782,7 @@ static int ext4_create(struct inode *dir, struct dentry *dentry, int mode,
+ 	if (IS_DIRSYNC(dir))
+ 		ext4_handle_sync(handle);
+ 
+-	inode = ext4_new_inode (handle, dir, mode);
++	inode = ext4_new_inode(handle, dir, mode, &dentry->d_name);
+ 	err = PTR_ERR(inode);
+ 	if (!IS_ERR(inode)) {
+ 		inode->i_op = &ext4_file_inode_operations;
+@@ -1816,7 +1816,7 @@ static int ext4_mknod(struct inode *dir, struct dentry *dentry,
+ 	if (IS_DIRSYNC(dir))
+ 		ext4_handle_sync(handle);
+ 
+-	inode = ext4_new_inode(handle, dir, mode);
++	inode = ext4_new_inode(handle, dir, mode, &dentry->d_name);
+ 	err = PTR_ERR(inode);
+ 	if (!IS_ERR(inode)) {
+ 		init_special_inode(inode, inode->i_mode, rdev);
+@@ -1853,7 +1853,7 @@ static int ext4_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+ 	if (IS_DIRSYNC(dir))
+ 		ext4_handle_sync(handle);
+ 
+-	inode = ext4_new_inode(handle, dir, S_IFDIR | mode);
++	inode = ext4_new_inode(handle, dir, S_IFDIR | mode, &dentry->d_name);
+ 	err = PTR_ERR(inode);
+ 	if (IS_ERR(inode))
+ 		goto out_stop;
+@@ -2264,7 +2264,7 @@ static int ext4_symlink(struct inode *dir,
+ 	if (IS_DIRSYNC(dir))
+ 		ext4_handle_sync(handle);
+ 
+-	inode = ext4_new_inode(handle, dir, S_IFLNK|S_IRWXUGO);
++	inode = ext4_new_inode(handle, dir, S_IFLNK|S_IRWXUGO, &dentry->d_name);
+ 	err = PTR_ERR(inode);
+ 	if (IS_ERR(inode))
+ 		goto out_stop;

commit 8a8a2050c844d9de224ff591e91bda3f77bd6eda
+Author: Theodore Ts'o 
+Date:   Sat Jun 13 10:08:59 2009 -0400
+
+    ext4: document the "abort" mount option
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
+index 608fdba97b72..7be02ac5fa36 100644
+--- a/Documentation/filesystems/ext4.txt
++++ b/Documentation/filesystems/ext4.txt
+@@ -235,6 +235,10 @@ minixdf			Make 'df' act like Minix.
+ 
+ debug			Extra debugging information is sent to syslog.
+ 
++abort			Simulate the effects of calling ext4_abort() for
++			debugging purposes.  This is normally used while
++			remounting a filesystem which is already mounted.
++
+ errors=remount-ro	Remount the filesystem read-only on an error.
+ errors=continue		Keep going on a filesystem error.
+ errors=panic		Panic and halt the machine if an error occurs.

commit 4ab2f15b7f709c3626a7eed075a7225b4c775c7e
+Author: Theodore Ts'o 
+Date:   Sat Jun 13 10:09:36 2009 -0400
+
+    ext4: move the abort flag from s_mount_opts to s_mount_flags
+    
+    We're running out of space in the mount options word, and
+    EXT4_MOUNT_ABORT isn't really a mount option, but a run-time flag.  So
+    move it to become EXT4_MF_FS_ABORTED in s_mount_flags.
+    
+    Also remove bogus ext2_fs.h / ext4.h simultaneous #include protection,
+    which can never happen.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 9e268c97eeca..06ee5a582917 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -684,7 +684,6 @@ struct ext4_inode_info {
+ #define EXT4_MOUNT_ERRORS_PANIC		0x00040	/* Panic on errors */
+ #define EXT4_MOUNT_MINIX_DF		0x00080	/* Mimics the Minix statfs */
+ #define EXT4_MOUNT_NOLOAD		0x00100	/* Don't use existing journal*/
+-#define EXT4_MOUNT_ABORT		0x00200	/* Fatal error detected */
+ #define EXT4_MOUNT_DATA_FLAGS		0x00C00	/* Mode for data writes: */
+ #define EXT4_MOUNT_JOURNAL_DATA		0x00400	/* Write data to journal */
+ #define EXT4_MOUNT_ORDERED_DATA		0x00800	/* Flush data before commit */
+@@ -706,17 +705,10 @@ struct ext4_inode_info {
+ #define EXT4_MOUNT_DATA_ERR_ABORT	0x10000000 /* Abort on file data write */
+ #define EXT4_MOUNT_BLOCK_VALIDITY	0x20000000 /* Block validity checking */
+ 
+-/* Compatibility, for having both ext2_fs.h and ext4_fs.h included at once */
+-#ifndef _LINUX_EXT2_FS_H
+ #define clear_opt(o, opt)		o &= ~EXT4_MOUNT_##opt
+ #define set_opt(o, opt)			o |= EXT4_MOUNT_##opt
+ #define test_opt(sb, opt)		(EXT4_SB(sb)->s_mount_opt & \
+ 					 EXT4_MOUNT_##opt)
+-#else
+-#define EXT2_MOUNT_NOLOAD		EXT4_MOUNT_NOLOAD
+-#define EXT2_MOUNT_ABORT		EXT4_MOUNT_ABORT
+-#define EXT2_MOUNT_DATA_FLAGS		EXT4_MOUNT_DATA_FLAGS
+-#endif
+ 
+ #define ext4_set_bit			ext2_set_bit
+ #define ext4_set_bit_atomic		ext2_set_bit_atomic
+@@ -836,9 +828,10 @@ struct ext4_super_block {
+ #ifdef __KERNEL__
+ 
+ /*
+- * Mount flags
++ * run-time mount flags
+  */
+ #define EXT4_MF_MNTDIR_SAMPLED	0x0001
++#define EXT4_MF_FS_ABORTED	0x0002	/* Fatal error detected */
+ 
+ /*
+  * fourth extended-fs super-block data in memory
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index f8325a2bc897..5f927f6a1289 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2670,13 +2670,13 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 	 * If the filesystem has aborted, it is read-only, so return
+ 	 * right away instead of dumping stack traces later on that
+ 	 * will obscure the real source of the problem.  We test
+-	 * EXT4_MOUNT_ABORT instead of sb->s_flag's MS_RDONLY because
++	 * EXT4_MF_FS_ABORTED instead of sb->s_flag's MS_RDONLY because
+ 	 * the latter could be true if the filesystem is mounted
+ 	 * read-only, and in that case, ext4_da_writepages should
+ 	 * *never* be called, so if that ever happens, we would want
+ 	 * the stack trace.
+ 	 */
+-	if (unlikely(sbi->s_mount_opt & EXT4_MOUNT_ABORT))
++	if (unlikely(sbi->s_mount_flags & EXT4_MF_FS_ABORTED))
+ 		return -EROFS;
+ 
+ 	/*
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 4c364ae7aeb1..04486a53469f 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -303,7 +303,7 @@ static void ext4_handle_error(struct super_block *sb)
+ 	if (!test_opt(sb, ERRORS_CONT)) {
+ 		journal_t *journal = EXT4_SB(sb)->s_journal;
+ 
+-		EXT4_SB(sb)->s_mount_opt |= EXT4_MOUNT_ABORT;
++		EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED;
+ 		if (journal)
+ 			jbd2_journal_abort(journal, -EIO);
+ 	}
+@@ -416,7 +416,7 @@ void ext4_abort(struct super_block *sb, const char *function,
+ 	ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
+ 	EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
+ 	sb->s_flags |= MS_RDONLY;
+-	EXT4_SB(sb)->s_mount_opt |= EXT4_MOUNT_ABORT;
++	EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED;
+ 	if (EXT4_SB(sb)->s_journal)
+ 		jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO);
+ }
+@@ -1476,7 +1476,7 @@ static int parse_options(char *options, struct super_block *sb,
+ 			break;
+ #endif
+ 		case Opt_abort:
+-			set_opt(sbi->s_mount_opt, ABORT);
++			sbi->s_mount_flags |= EXT4_MF_FS_ABORTED;
+ 			break;
+ 		case Opt_nobarrier:
+ 			clear_opt(sbi->s_mount_opt, BARRIER);
+@@ -3452,7 +3452,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 		goto restore_opts;
+ 	}
+ 
+-	if (sbi->s_mount_opt & EXT4_MOUNT_ABORT)
++	if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED)
+ 		ext4_abort(sb, __func__, "Abort forced by user");
+ 
+ 	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
+@@ -3467,7 +3467,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 
+ 	if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY) ||
+ 		n_blocks_count > ext4_blocks_count(es)) {
+-		if (sbi->s_mount_opt & EXT4_MOUNT_ABORT) {
++		if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED) {
+ 			err = -EROFS;
+ 			goto restore_opts;
+ 		}

commit bc0b0d6d69ee9022f18ae264e62beb30ddeb322a
+Author: Theodore Ts'o 
+Date:   Sat Jun 13 10:09:48 2009 -0400
+
+    ext4: update the s_last_mounted field in the superblock
+    
+    This field can be very helpful when a system administrator is trying
+    to sort through large numbers of block devices or filesystem images.
+    What is stored in this field can be ambiguous if multiple filesystem
+    namespaces are in play; what we store in practice is the mountpoint
+    interpreted by the process's namespace which first opens a file in the
+    filesystem.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 569f527080bf..9e268c97eeca 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -834,6 +834,12 @@ struct ext4_super_block {
+ };
+ 
+ #ifdef __KERNEL__
++
++/*
++ * Mount flags
++ */
++#define EXT4_MF_MNTDIR_SAMPLED	0x0001
++
+ /*
+  * fourth extended-fs super-block data in memory
+  */
+@@ -853,6 +859,7 @@ struct ext4_sb_info {
+ 	struct ext4_super_block *s_es;	/* Pointer to the super block in the buffer */
+ 	struct buffer_head **s_group_desc;
+ 	unsigned int s_mount_opt;
++	unsigned int s_mount_flags;
+ 	ext4_fsblk_t s_sb_block;
+ 	uid_t s_resuid;
+ 	gid_t s_resgid;
+diff --git a/fs/ext4/file.c b/fs/ext4/file.c
+index 588af8c77246..3f1873fef1c6 100644
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -21,6 +21,8 @@
+ #include 
+ #include 
+ #include 
++#include 
++#include 
+ #include "ext4.h"
+ #include "ext4_jbd2.h"
+ #include "xattr.h"
+@@ -145,6 +147,38 @@ static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma)
+ 	return 0;
+ }
+ 
++static int ext4_file_open(struct inode * inode, struct file * filp)
++{
++	struct super_block *sb = inode->i_sb;
++	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
++	struct vfsmount *mnt = filp->f_path.mnt;
++	struct path path;
++	char buf[64], *cp;
++
++	if (unlikely(!(sbi->s_mount_flags & EXT4_MF_MNTDIR_SAMPLED) &&
++		     !(sb->s_flags & MS_RDONLY))) {
++		sbi->s_mount_flags |= EXT4_MF_MNTDIR_SAMPLED;
++		/*
++		 * Sample where the filesystem has been mounted and
++		 * store it in the superblock for sysadmin convenience
++		 * when trying to sort through large numbers of block
++		 * devices or filesystem images.
++		 */
++		memset(buf, 0, sizeof(buf));
++		path.mnt = mnt->mnt_parent;
++		path.dentry = mnt->mnt_mountpoint;
++		path_get(&path);
++		cp = d_path(&path, buf, sizeof(buf));
++		path_put(&path);
++		if (!IS_ERR(cp)) {
++			memcpy(sbi->s_es->s_last_mounted, cp,
++			       sizeof(sbi->s_es->s_last_mounted));
++			sb->s_dirt = 1;
++		}
++	}
++	return generic_file_open(inode, filp);
++}
++
+ const struct file_operations ext4_file_operations = {
+ 	.llseek		= generic_file_llseek,
+ 	.read		= do_sync_read,
+@@ -156,7 +190,7 @@ const struct file_operations ext4_file_operations = {
+ 	.compat_ioctl	= ext4_compat_ioctl,
+ #endif
+ 	.mmap		= ext4_file_mmap,
+-	.open		= generic_file_open,
++	.open		= ext4_file_open,
+ 	.release	= ext4_release_file,
+ 	.fsync		= ext4_sync_file,
+ 	.splice_read	= generic_file_splice_read,

commit 7f4520cc6242780ce720aa440ad4b391f998b558
+Author: Theodore Ts'o 
+Date:   Sat Jun 13 10:09:41 2009 -0400
+
+    ext4: change s_mount_opt to be an unsigned int
+    
+    We can only fit 32 options in s_mount_opt because an unsigned long is
+    32-bits on a x86 machine.  So use an unsigned int to save space on
+    64-bit platforms.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 276a26f117e6..569f527080bf 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -852,7 +852,7 @@ struct ext4_sb_info {
+ 	struct buffer_head * s_sbh;	/* Buffer containing the super block */
+ 	struct ext4_super_block *s_es;	/* Pointer to the super block in the buffer */
+ 	struct buffer_head **s_group_desc;
+-	unsigned long  s_mount_opt;
++	unsigned int s_mount_opt;
+ 	ext4_fsblk_t s_sb_block;
+ 	uid_t s_resuid;
+ 	gid_t s_resgid;
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 2418ad36eab5..f8325a2bc897 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -93,7 +93,7 @@ int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode,
+ 	BUFFER_TRACE(bh, "enter");
+ 
+ 	jbd_debug(4, "forgetting bh %p: is_metadata = %d, mode %o, "
+-		  "data mode %lx\n",
++		  "data mode %x\n",
+ 		  bh, is_metadata, inode->i_mode,
+ 		  test_opt(inode->i_sb, DATA_FLAGS));
+ 
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index e8f0b2af4607..4c364ae7aeb1 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1655,7 +1655,7 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
+ 	ext4_commit_super(sb, 1);
+ 	if (test_opt(sb, DEBUG))
+ 		printk(KERN_INFO "[EXT4 FS bs=%lu, gc=%u, "
+-				"bpg=%lu, ipg=%lu, mo=%04lx]\n",
++				"bpg=%lu, ipg=%lu, mo=%04x]\n",
+ 			sb->s_blocksize,
+ 			sbi->s_groups_count,
+ 			EXT4_BLOCKS_PER_GROUP(sb),

commit 28ad0c118b0ed98b042d362acfe0017591921138
+Author: Theodore Ts'o 
+Date:   Thu May 21 16:01:02 2009 -0400
+
+    fs: Rearrange inode structure elements to avoid waste due to padding
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: linux-fsdevel@vger.kernel.org
+    Signed-off-by: Al Viro 
+
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index bcd63706db87..d883aa1fc2eb 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -729,8 +729,8 @@ struct inode {
+ 	struct timespec		i_atime;
+ 	struct timespec		i_mtime;
+ 	struct timespec		i_ctime;
+-	unsigned int		i_blkbits;
+ 	blkcnt_t		i_blocks;
++	unsigned int		i_blkbits;
+ 	unsigned short          i_bytes;
+ 	umode_t			i_mode;
+ 	spinlock_t		i_lock;	/* i_blocks, i_bytes, maybe i_size */

commit 9fd5746fd3d7838bf6ff991d50f1257057d1156f
+Author: Theodore Ts'o 
+Date:   Thu May 21 16:01:00 2009 -0400
+
+    fs: Remove i_cindex from struct inode
+    
+    The only user of the i_cindex element in the inode structure is used
+    is by the firewire drivers.  As part of an attempt to slim down the
+    inode structure to save memory --- since a typical Linux system will
+    have hundreds of thousands if not millions of inodes cached, a
+    reduction in the size inode has high leverage.
+    
+    The firewire driver does not need i_cindex in any fast path, so it's
+    simple enough to calculate when it is needed, instead of wasting space
+    in the inode structure.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: krh@redhat.com
+    Cc: stefanr@s5r6.in-berlin.de
+    Cc: linux-fsdevel@vger.kernel.org
+    Signed-off-by: Al Viro 
+
+diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
+index 823a6297a1af..2cd00b5b45b4 100644
+--- a/drivers/ieee1394/dv1394.c
++++ b/drivers/ieee1394/dv1394.c
+@@ -1789,12 +1789,13 @@ static int dv1394_open(struct inode *inode, struct file *file)
+ 	} else {
+ 		/* look up the card by ID */
+ 		unsigned long flags;
++		int idx = ieee1394_file_to_instance(file);
+ 
+ 		spin_lock_irqsave(&dv1394_cards_lock, flags);
+ 		if (!list_empty(&dv1394_cards)) {
+ 			struct video_card *p;
+ 			list_for_each_entry(p, &dv1394_cards, list) {
+-				if ((p->id) == ieee1394_file_to_instance(file)) {
++				if ((p->id) == idx) {
+ 					video = p;
+ 					break;
+ 				}
+@@ -1803,7 +1804,7 @@ static int dv1394_open(struct inode *inode, struct file *file)
+ 		spin_unlock_irqrestore(&dv1394_cards_lock, flags);
+ 
+ 		if (!video) {
+-			debug_printk("dv1394: OHCI card %d not found", ieee1394_file_to_instance(file));
++			debug_printk("dv1394: OHCI card %d not found", idx);
+ 			return -ENODEV;
+ 		}
+ 
+diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
+index 21d50f73a210..28b9f58bafd2 100644
+--- a/drivers/ieee1394/ieee1394_core.h
++++ b/drivers/ieee1394/ieee1394_core.h
+@@ -5,6 +5,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ 
+ #include "hosts.h"
+@@ -155,7 +156,10 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
+  */
+ static inline unsigned char ieee1394_file_to_instance(struct file *file)
+ {
+-	return file->f_path.dentry->d_inode->i_cindex;
++	int idx = cdev_index(file->f_path.dentry->d_inode);
++	if (idx < 0)
++		idx = 0;
++	return idx;
+ }
+ 
+ extern int hpsb_disable_irm;
+diff --git a/fs/char_dev.c b/fs/char_dev.c
+index 38f71222a552..b7c9d5187a75 100644
+--- a/fs/char_dev.c
++++ b/fs/char_dev.c
+@@ -375,7 +375,6 @@ static int chrdev_open(struct inode *inode, struct file *filp)
+ 		p = inode->i_cdev;
+ 		if (!p) {
+ 			inode->i_cdev = p = new;
+-			inode->i_cindex = idx;
+ 			list_add(&inode->i_devices, &p->list);
+ 			new = NULL;
+ 		} else if (!cdev_get(p))
+@@ -405,6 +404,18 @@ static int chrdev_open(struct inode *inode, struct file *filp)
+ 	return ret;
+ }
+ 
++int cdev_index(struct inode *inode)
++{
++	int idx;
++	struct kobject *kobj;
++
++	kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx);
++	if (!kobj)
++		return -1;
++	kobject_put(kobj);
++	return idx;
++}
++
+ void cd_forget(struct inode *inode)
+ {
+ 	spin_lock(&cdev_lock);
+@@ -557,6 +568,7 @@ EXPORT_SYMBOL(cdev_init);
+ EXPORT_SYMBOL(cdev_alloc);
+ EXPORT_SYMBOL(cdev_del);
+ EXPORT_SYMBOL(cdev_add);
++EXPORT_SYMBOL(cdev_index);
+ EXPORT_SYMBOL(register_chrdev);
+ EXPORT_SYMBOL(unregister_chrdev);
+ EXPORT_SYMBOL(directly_mappable_cdev_bdi);
+diff --git a/include/linux/cdev.h b/include/linux/cdev.h
+index fb4591977b03..f389e319a454 100644
+--- a/include/linux/cdev.h
++++ b/include/linux/cdev.h
+@@ -28,6 +28,8 @@ int cdev_add(struct cdev *, dev_t, unsigned);
+ 
+ void cdev_del(struct cdev *);
+ 
++int cdev_index(struct inode *inode);
++
+ void cd_forget(struct inode *);
+ 
+ extern struct backing_dev_info directly_mappable_cdev_bdi;
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index e7833ef5d1d6..bcd63706db87 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -751,7 +751,6 @@ struct inode {
+ 		struct block_device	*i_bdev;
+ 		struct cdev		*i_cdev;
+ 	};
+-	int			i_cindex;
+ 
+ 	__u32			i_generation;
+ 

commit 0eab928221bac8895a0b494a16a8810002bd8645
+Author: Theodore Ts'o 
+Date:   Tue Jun 9 09:54:40 2009 -0400
+
+    ext4: Don't treat a truncation of a zero-length file as replace-via-truncate
+    
+    If a non-existent file is opened via O_WRONLY|O_CREAT|O_TRUNC, there's
+    no need to treat this as a true file truncation, so we shouldn't
+    activate the replace-via-truncate hueristic.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 2c10d346f7a3..875db944b22f 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4127,7 +4127,8 @@ void ext4_truncate(struct inode *inode)
+ 	if (!ext4_can_truncate(inode))
+ 		return;
+ 
+-	if (inode->i_size == 0 && !test_opt(inode->i_sb, NO_AUTO_DA_ALLOC))
++	if (ei->i_disksize && inode->i_size == 0 &&
++	    !test_opt(inode->i_sb, NO_AUTO_DA_ALLOC))
+ 		ei->i_state |= EXT4_STATE_DA_ALLOC_CLOSE;
+ 
+ 	if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) {

commit 460bcf57b128ce1c0dd553d905fedc097f9955c6
+Author: Theodore Ts'o 
+Date:   Tue May 12 07:37:56 2009 -0400
+
+    Fix nobh_truncate_page() to not pass stack garbage to get_block()
+    
+    The nobh_truncate_page() function is used by ext2, exofs, and jfs.  Of
+    these three, only ext2 and jfs's get_block() function pays attention
+    to bh->b_size --- which is normally always the filesystem blocksize
+    except when the get_block() function is called by either
+    mpage_readpage(), mpage_readpages(), or the direct I/O routines in
+    fs/direct_io.c.
+    
+    Unfortunately, nobh_truncate_page() does not initialize map_bh before
+    calling the filesystem-supplied get_block() function.  So ext2 and jfs
+    will try to calculate the number of blocks to map by taking stack
+    garbage and shifting it left by inode->i_blkbits.  This should be
+    *mostly* harmless (except the filesystem will do some unnneeded work)
+    unless the stack garbage is less than filesystem's blocksize, in which
+    case maxblocks will be zero, and the attempt to find out whether or
+    not the filesystem has a hole at a given logical block will fail, and
+    the page cache entry might not get zero'ed out.
+    
+    Also if the stack garbage in in map_bh->state happens to have the
+    BH_Mapped bit set, there could be an attempt to call readpage() on a
+    non-existent page, which could cause nobh_truncate_page() to return an
+    error when it should not.
+    
+    Fix this by initializing map_bh->state and map_bh->size.
+    
+    Fortunately, it's probably fairly unlikely that ext2 and jfs users
+    mount with nobh these days.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Dave Kleikamp 
+    Cc: linux-fsdevel@vger.kernel.org
+    Signed-off-by: Al Viro 
+
+diff --git a/fs/buffer.c b/fs/buffer.c
+index aed297739eb0..49106127a4aa 100644
+--- a/fs/buffer.c
++++ b/fs/buffer.c
+@@ -2736,6 +2736,8 @@ int nobh_truncate_page(struct address_space *mapping,
+ 		pos += blocksize;
+ 	}
+ 
++	map_bh.b_size = blocksize;
++	map_bh.b_state = 0;
+ 	err = get_block(inode, iblock, &map_bh, 0);
+ 	if (err)
+ 		goto unlock;

commit 2ae19acaa50a09c1099956efb895c0aca74ab050
+Author: Theodore Ts'o 
+Date:   Thu Apr 16 07:44:45 2009 -0400
+
+    Documentation: Add "how to write a good patch summary" to SubmittingPatches
+    
+    Unfortunately many patch submissions are arriving with painfully poor
+    patch descriptions.   As a result of the discussion on LKML:
+    
+          http://lkml.org/lkml/2009/4/15/296
+    
+    explain how to submit a better patch description, in the (perhaps
+    vain) hope that maintainers won't end up having to rewrite the git
+    commit logs as often as they do today.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Ingo Molnar 
+    Signed-off-by: Jonathan Corbet 
+
+diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
+index 71b6da2b7175..6c456835c1fd 100644
+--- a/Documentation/SubmittingPatches
++++ b/Documentation/SubmittingPatches
+@@ -91,6 +91,10 @@ Be as specific as possible.  The WORST descriptions possible include
+ things like "update driver X", "bug fix for driver X", or "this patch
+ includes updates for subsystem X.  Please apply."
+ 
++The maintainer will thank you if you write your patch description in a
++form which can be easily pulled into Linux's source code management
++system, git, as a "commit log".  See #15, below.
++
+ If your description starts to get long, that's a sign that you probably
+ need to split up your patch.  See #3, next.
+ 
+@@ -492,12 +496,33 @@ phrase" should not be a filename.  Do not use the same "summary
+ phrase" for every patch in a whole patch series (where a "patch
+ series" is an ordered sequence of multiple, related patches).
+ 
+-Bear in mind that the "summary phrase" of your email becomes
+-a globally-unique identifier for that patch.  It propagates
+-all the way into the git changelog.  The "summary phrase" may
+-later be used in developer discussions which refer to the patch.
+-People will want to google for the "summary phrase" to read
+-discussion regarding that patch.
++Bear in mind that the "summary phrase" of your email becomes a
++globally-unique identifier for that patch.  It propagates all the way
++into the git changelog.  The "summary phrase" may later be used in
++developer discussions which refer to the patch.  People will want to
++google for the "summary phrase" to read discussion regarding that
++patch.  It will also be the only thing that people may quickly see
++when, two or three months later, they are going through perhaps
++thousands of patches using tools such as "gitk" or "git log
++--oneline".
++
++For these reasons, the "summary" must be no more than 70-75
++characters, and it must describe both what the patch changes, as well
++as why the patch might be necessary.  It is challenging to be both
++succinct and descriptive, but that is what a well-written summary
++should do.
++
++The "summary phrase" may be prefixed by tags enclosed in square
++brackets: "Subject: [PATCH tag] ".  The tags are not
++considered part of the summary phrase, but describe how the patch
++should be treated.  Common tags might include a version descriptor if
++the multiple versions of the patch have been sent out in response to
++comments (i.e., "v1, v2, v3"), or "RFC" to indicate a request for
++comments.  If there are four patches in a patch series the individual
++patches may be numbered like this: 1/4, 2/4, 3/4, 4/4.  This assures
++that developers understand the order in which the patches should be
++applied and that they have reviewed or applied all of the patches in
++the patch series.
+ 
+ A couple of example Subjects:
+ 
+@@ -517,19 +542,31 @@ the patch author in the changelog.
+ The explanation body will be committed to the permanent source
+ changelog, so should make sense to a competent reader who has long
+ since forgotten the immediate details of the discussion that might
+-have led to this patch.
++have led to this patch.  Including symptoms of the failure which the
++patch addresses (kernel log messages, oops messages, etc.) is
++especially useful for people who might be searching the commit logs
++looking for the applicable patch.  If a patch fixes a compile failure,
++it may not be necessary to include _all_ of the compile failures; just
++enough that it is likely that someone searching for the patch can find
++it.  As in the "summary phrase", it is important to be both succinct as
++well as descriptive.
+ 
+ The "---" marker line serves the essential purpose of marking for patch
+ handling tools where the changelog message ends.
+ 
+ One good use for the additional comments after the "---" marker is for
+-a diffstat, to show what files have changed, and the number of inserted
+-and deleted lines per file.  A diffstat is especially useful on bigger
+-patches.  Other comments relevant only to the moment or the maintainer,
+-not suitable for the permanent changelog, should also go here.
+-Use diffstat options "-p 1 -w 70" so that filenames are listed from the
+-top of the kernel source tree and don't use too much horizontal space
+-(easily fit in 80 columns, maybe with some indentation).
++a diffstat, to show what files have changed, and the number of
++inserted and deleted lines per file.  A diffstat is especially useful
++on bigger patches.  Other comments relevant only to the moment or the
++maintainer, not suitable for the permanent changelog, should also go
++here.  A good example of such comments might be "patch changelogs"
++which describe what has changed between the v1 and v2 version of the
++patch.
++
++If you are going to include a diffstat after the "---" marker, please
++use diffstat options "-p 1 -w 70" so that filenames are listed from
++the top of the kernel source tree and don't use too much horizontal
++space (easily fit in 80 columns, maybe with some indentation).
+ 
+ See more details on the proper patch format in the following
+ references.

commit 5adfee9c17314c1411095c23191c3cb0c2d25f9f
+Author: Theodore Ts'o 
+Date:   Wed Jul 8 17:11:24 2009 -0400
+
+    ext4: fix no journal corruption with locale-gen
+    
+    If there is no journal, ext4_should_writeback_data() should return
+    TRUE.  This will fix ext4_set_aops() to set ext4_da_ops in the case of
+    delayed allocation; otherwise ext4_journaled_aops gets used by
+    default, which doesn't handle delayed allocation properly.
+    
+    The advantage of using ext4_should_writeback_data() approach is that
+    it should handle nobh better as well.
+    
+    Thanks to Curt Wohlgemuth for investigating this problem, and Aneesh
+    Kumar for suggesting this approach.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
+index be2f426f6805..d574a85aca56 100644
+--- a/fs/ext4/ext4_jbd2.h
++++ b/fs/ext4/ext4_jbd2.h
+@@ -281,10 +281,10 @@ static inline int ext4_should_order_data(struct inode *inode)
+ 
+ static inline int ext4_should_writeback_data(struct inode *inode)
+ {
+-	if (EXT4_JOURNAL(inode) == NULL)
+-		return 0;
+ 	if (!S_ISREG(inode->i_mode))
+ 		return 0;
++	if (EXT4_JOURNAL(inode) == NULL)
++		return 1;
+ 	if (EXT4_I(inode)->i_flags & EXT4_JOURNAL_DATA_FL)
+ 		return 0;
+ 	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)

commit f4a01017d678fe4baecf480e79d7c4f4b7ebc772
+Author: Theodore Ts'o 
+Date:   Sun Jul 5 22:08:16 2009 -0400
+
+    ext4: Fix potential reclaim deadlock when truncating partial block
+    
+    The ext4_block_truncate_page() function previously called
+    grab_cache_page(), which called find_or_create_page() with the
+    __GFP_FS flag potentially set.  This could cause a deadlock if the
+    system is low on memory and it attempts a memory reclaim, which could
+    potentially call back into ext4.  So we need to call
+    find_or_create_page() directly, and remove the __GFP_FP flag to avoid
+    this potential deadlock.
+    
+    Thanks to Roland Dreier for reporting a lockdep warning which showed
+    this problem.
+    
+    [20786.363249] =================================
+    [20786.363257] [ INFO: inconsistent lock state ]
+    [20786.363265] 2.6.31-2-generic #14~rbd4gitd960eea9
+    [20786.363270] ---------------------------------
+    [20786.363276] inconsistent {IN-RECLAIM_FS-W} -> {RECLAIM_FS-ON-W} usage.
+    [20786.363285] http/8397 [HC0[0]:SC0[0]:HE1:SE1] takes:
+    [20786.363291]  (jbd2_handle){+.+.?.}, at: [] jbd2_journal_start+0xdb/0x150
+    [20786.363314] {IN-RECLAIM_FS-W} state was registered at:
+    [20786.363320]   [] mark_irqflags+0xc6/0x1a0
+    [20786.363334]   [] __lock_acquire+0x287/0x430
+    [20786.363345]   [] lock_acquire+0xa5/0x150
+    [20786.363355]   [] jbd2_journal_start+0xfa/0x150
+    [20786.363365]   [] ext4_journal_start_sb+0x58/0x90
+    [20786.363377]   [] ext4_delete_inode+0xc5/0x2c0
+    [20786.363389]   [] generic_delete_inode+0xd3/0x1a0
+    [20786.363401]   [] generic_drop_inode+0x25/0x30
+    [20786.363411]   [] iput+0x62/0x70
+    [20786.363420]   [] dentry_iput+0x98/0x110
+    [20786.363429]   [] d_kill+0x50/0x80
+    [20786.363438]   [] dput+0x95/0x180
+    [20786.363447]   [] ecryptfs_d_release+0x2b/0x70
+    [20786.363459]   [] d_free+0x28/0x60
+    [20786.363468]   [] d_kill+0x68/0x80
+    [20786.363477]   [] prune_one_dentry+0xa3/0xc0
+    [20786.363487]   [] __shrink_dcache_sb+0x271/0x290
+    [20786.363497]   [] prune_dcache+0x109/0x1b0
+    [20786.363506]   [] shrink_dcache_memory+0x3f/0x50
+    [20786.363516]   [] shrink_slab+0x12d/0x190
+    [20786.363527]   [] balance_pgdat+0x4d7/0x640
+    [20786.363537]   [] kswapd+0x117/0x170
+    [20786.363546]   [] kthread+0x9e/0xb0
+    [20786.363558]   [] child_rip+0xa/0x20
+    [20786.363569]   [] 0xffffffffffffffff
+    [20786.363598] irq event stamp: 15997
+    [20786.363603] hardirqs last  enabled at (15997): [] kmem_cache_alloc+0xfd/0x1a0
+    [20786.363617] hardirqs last disabled at (15996): [] kmem_cache_alloc+0x61/0x1a0
+    [20786.363628] softirqs last  enabled at (15966): [] __do_softirq+0x14a/0x220
+    [20786.363641] softirqs last disabled at (15861): [] call_softirq+0x1c/0x30
+    [20786.363651]
+    [20786.363653] other info that might help us debug this:
+    [20786.363660] 3 locks held by http/8397:
+    [20786.363665]  #0:  (&sb->s_type->i_mutex_key#8){+.+.+.}, at: [] do_truncate+0x64/0x90
+    [20786.363685]  #1:  (&sb->s_type->i_alloc_sem_key#5){+++++.}, at: [] notify_change+0x250/0x350
+    [20786.363707]  #2:  (jbd2_handle){+.+.?.}, at: [] jbd2_journal_start+0xdb/0x150
+    [20786.363724]
+    [20786.363726] stack backtrace:
+    [20786.363734] Pid: 8397, comm: http Tainted: G         C 2.6.31-2-generic #14~rbd4gitd960eea9
+    [20786.363741] Call Trace:
+    [20786.363752]  [] print_usage_bug+0x18c/0x1a0
+    [20786.363763]  [] ? check_usage_backwards+0x0/0xb0
+    [20786.363773]  [] mark_lock_irq+0xf2/0x280
+    [20786.363783]  [] mark_lock+0x137/0x1d0
+    [20786.363793]  [] mark_held_locks+0x6c/0xa0
+    [20786.363803]  [] lockdep_trace_alloc+0xaf/0xe0
+    [20786.363813]  [] __alloc_pages_nodemask+0x7c/0x180
+    [20786.363824]  [] ? find_get_page+0x91/0xf0
+    [20786.363835]  [] alloc_pages_current+0x87/0xd0
+    [20786.363845]  [] __page_cache_alloc+0x67/0x70
+    [20786.363856]  [] find_or_create_page+0x4f/0xb0
+    [20786.363867]  [] ext4_block_truncate_page+0x3e/0x460
+    [20786.363876]  [] ? jbd2_journal_start+0xfa/0x150
+    [20786.363885]  [] ? jbd2_journal_start+0xdb/0x150
+    [20786.363895]  [] ? ext4_meta_trans_blocks+0x75/0xf0
+    [20786.363905]  [] ext4_ext_truncate+0x1bb/0x1e0
+    [20786.363916]  [] ? unmap_mapping_range+0x75/0x290
+    [20786.363926]  [] ext4_truncate+0x498/0x630
+    [20786.363938]  [] ? _raw_spin_unlock+0x5e/0xb0
+    [20786.363947]  [] ? unmap_mapping_range+0xb6/0x290
+    [20786.363957]  [] ? trace_hardirqs_on+0xd/0x10
+    [20786.363966]  [] ? jbd2_journal_stop+0x1f8/0x2e0
+    [20786.363976]  [] vmtruncate+0xb0/0x110
+    [20786.363986]  [] inode_setattr+0x35/0x170
+    [20786.363995]  [] ext4_setattr+0x186/0x370
+    [20786.364005]  [] notify_change+0x16b/0x350
+    [20786.364014]  [] do_truncate+0x70/0x90
+    [20786.364021]  [] T.657+0xeb/0x110
+    [20786.364021]  [] sys_ftruncate+0xe/0x10
+    [20786.364021]  [] system_call_fastpath+0x16/0x1b
+    
+    Reported-by: Roland Dreier 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 60a26f3a6f8b..9760ba09275e 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -3583,7 +3583,8 @@ int ext4_block_truncate_page(handle_t *handle,
+ 	struct page *page;
+ 	int err = 0;
+ 
+-	page = grab_cache_page(mapping, from >> PAGE_CACHE_SHIFT);
++	page = find_or_create_page(mapping, from >> PAGE_CACHE_SHIFT,
++				   mapping_gfp_mask(mapping) & ~__GFP_FS);
+ 	if (!page)
+ 		return -EINVAL;
+ 

commit b574480507460b8e31b8d38dd4642219fc3b9a10
+Author: Theodore Ts'o 
+Date:   Sat Jun 20 23:34:44 2009 -0400
+
+    jbd2: Remove GFP_ATOMIC kmalloc from inside spinlock critical region
+    
+    Fix jbd2_dev_to_name(), a function used when pretty-printting jbd2 and
+    ext4 tracepoints.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 18bfd5dab642..7b545c3b3942 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -2410,6 +2410,7 @@ const char *jbd2_dev_to_name(dev_t device)
+ 	int	i = hash_32(device, CACHE_SIZE_BITS);
+ 	char	*ret;
+ 	struct block_device *bd;
++	static struct devname_cache *new_dev;
+ 
+ 	rcu_read_lock();
+ 	if (devcache[i] && devcache[i]->device == device) {
+@@ -2419,20 +2420,20 @@ const char *jbd2_dev_to_name(dev_t device)
+ 	}
+ 	rcu_read_unlock();
+ 
++	new_dev = kmalloc(sizeof(struct devname_cache), GFP_KERNEL);
++	if (!new_dev)
++		return "NODEV-ALLOCFAILURE"; /* Something non-NULL */
+ 	spin_lock(&devname_cache_lock);
+ 	if (devcache[i]) {
+ 		if (devcache[i]->device == device) {
++			kfree(new_dev);
+ 			ret = devcache[i]->devname;
+ 			spin_unlock(&devname_cache_lock);
+ 			return ret;
+ 		}
+ 		call_rcu(&devcache[i]->rcu, free_devcache);
+ 	}
+-	devcache[i] = kmalloc(sizeof(struct devname_cache), GFP_KERNEL);
+-	if (!devcache[i]) {
+-		spin_unlock(&devname_cache_lock);
+-		return "NODEV-ALLOCFAILURE"; /* Something non-NULL */
+-	}
++	devcache[i] = new_dev;
+ 	devcache[i]->device = device;
+ 	bd = bdget(device);
+ 	if (bd) {

commit 627ad9fd0733f0a31a266ff98a4a933eee710f0b
+Author: Theodore Ts'o 
+Date:   Sat Jun 20 23:21:41 2009 -0400
+
+    ext4: Fix type warning on 64-bit platforms in tracing events header
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+index acf4cc9cd36d..b456fb0a3c57 100644
+--- a/include/trace/events/ext4.h
++++ b/include/trace/events/ext4.h
+@@ -34,7 +34,8 @@ TRACE_EVENT(ext4_free_inode,
+ 
+ 	TP_printk("dev %s ino %lu mode %d uid %u gid %u blocks %llu",
+ 		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->mode,
+-		  __entry->uid, __entry->gid, __entry->blocks)
++		  __entry->uid, __entry->gid,
++		  (unsigned long long) __entry->blocks)
+ );
+ 
+ TRACE_EVENT(ext4_request_inode,

commit 88b6edd17c62b7d346d21f4087893ce7d4ef828a
+Author: Theodore Ts'o 
+Date:   Mon May 25 11:50:39 2009 -0400
+
+    ext4: Clean up calls to ext4_get_group_desc()
+    
+    If the caller isn't planning on modifying the block group descriptors,
+    there's no need to pass in a pointer to a struct buffer_head.  Nuking
+    this saves a tiny amount of CPU time and stack space usage.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 82f7d1d7eae0..3743bd849bce 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -347,7 +347,6 @@ static int find_group_flex(struct super_block *sb, struct inode *parent,
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	struct ext4_group_desc *desc;
+-	struct buffer_head *bh;
+ 	struct flex_groups *flex_group = sbi->s_flex_groups;
+ 	ext4_group_t parent_group = EXT4_I(parent)->i_block_group;
+ 	ext4_group_t parent_fbg_group = ext4_flex_group(sbi, parent_group);
+@@ -402,7 +401,7 @@ static int find_group_flex(struct super_block *sb, struct inode *parent,
+ found_flexbg:
+ 	for (i = best_flex * flex_size; i < ngroups &&
+ 		     i < (best_flex + 1) * flex_size; i++) {
+-		desc = ext4_get_group_desc(sb, i, &bh);
++		desc = ext4_get_group_desc(sb, i, NULL);
+ 		if (ext4_free_inodes_count(sb, desc)) {
+ 			*best_group = i;
+ 			goto out;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index eca6c057b119..91b98b58ccb9 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1660,7 +1660,6 @@ static int ext4_fill_flex_info(struct super_block *sb)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	struct ext4_group_desc *gdp = NULL;
+-	struct buffer_head *bh;
+ 	ext4_group_t flex_group_count;
+ 	ext4_group_t flex_group;
+ 	int groups_per_flex = 0;
+@@ -1693,7 +1692,7 @@ static int ext4_fill_flex_info(struct super_block *sb)
+ 	}
+ 
+ 	for (i = 0; i < sbi->s_groups_count; i++) {
+-		gdp = ext4_get_group_desc(sb, i, &bh);
++		gdp = ext4_get_group_desc(sb, i, NULL);
+ 
+ 		flex_group = ext4_flex_group(sbi, i);
+ 		atomic_set(&sbi->s_flex_groups[flex_group].free_inodes,

commit 759d427aa5a9d88a81afd11817cdeb40aea85234
+Author: Theodore Ts'o 
+Date:   Mon May 25 11:51:00 2009 -0400
+
+    ext4: remove unused function __ext4_write_dirty_metadata
+    
+    The __ext4_write_dirty_metadata() function was introduced by commit
+    0390131b, "ext4: Allow ext4 to run without a journal", but nothing
+    ever used the function, either then or since.  So let's remove it and
+    save a bit of space.
+    
+    Cc: Frank Mayhar 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index dadd3f995db5..14c00fff3713 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4790,25 +4790,6 @@ int ext4_write_inode(struct inode *inode, int wait)
+ 	return ext4_force_commit(inode->i_sb);
+ }
+ 
+-int __ext4_write_dirty_metadata(struct inode *inode, struct buffer_head *bh)
+-{
+-	int err = 0;
+-
+-	mark_buffer_dirty(bh);
+-	if (inode && inode_needs_sync(inode)) {
+-		sync_dirty_buffer(bh);
+-		if (buffer_req(bh) && !buffer_uptodate(bh)) {
+-			ext4_error(inode->i_sb, __func__,
+-				   "IO error syncing inode, "
+-				   "inode=%lu, block=%llu",
+-				   inode->i_ino,
+-				   (unsigned long long)bh->b_blocknr);
+-			err = -EIO;
+-		}
+-	}
+-	return err;
+-}
+-
+ /*
+  * ext4_setattr()
+  *

commit 0568c518937ee3a9b6a94d18bae9c150fe5d6832
+Author: Theodore Ts'o 
+Date:   Sun May 17 23:31:23 2009 -0400
+
+    ext4: down i_data_sem only for read when walking tree for fiemap
+    
+    Not sure why I put this in as down_write originally; all we are
+    doing is walking the tree, nothing will change under us and
+    concurrent reads should be no problem.
+    
+    Signed-off-by: Eric Sandeen 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index d04b779b780e..d4e99e96fddb 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -3312,10 +3312,10 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ 		 * Walk the extent tree gathering extent information.
+ 		 * ext4_ext_fiemap_cb will push extents back to user.
+ 		 */
+-		down_write(&EXT4_I(inode)->i_data_sem);
++		down_read(&EXT4_I(inode)->i_data_sem);
+ 		error = ext4_ext_walk_space(inode, start_blk, len_blks,
+ 					  ext4_ext_fiemap_cb, fieinfo);
+-		up_write(&EXT4_I(inode)->i_data_sem);
++		up_read(&EXT4_I(inode)->i_data_sem);
+ 	}
+ 
+ 	return error;

commit 6fd058f7791087648c683eb8572edf3be3c4c23c
+Author: Theodore Ts'o 
+Date:   Sun May 17 15:38:01 2009 -0400
+
+    ext4: Add a comprehensive block validity check to ext4_get_blocks()
+    
+    To catch filesystem bugs or corruption which could lead to the
+    filesystem getting severly damaged, this patch adds a facility for
+    tracking all of the filesystem metadata blocks by contiguous regions
+    in a red-black tree.  This allows quick searching of the tree to
+    locate extents which might overlap with filesystem metadata blocks.
+    
+    This facility is also used by the multi-block allocator to assure that
+    it is not allocating blocks out of the system zone, as well as by the
+    routines used when reading indirect blocks and extents information
+    from disk to make sure their contents are valid.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
+index a8ff003a00f7..8a34710ecf40 100644
+--- a/fs/ext4/Makefile
++++ b/fs/ext4/Makefile
+@@ -5,8 +5,8 @@
+ obj-$(CONFIG_EXT4_FS) += ext4.o
+ 
+ ext4-y	:= balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
+-		   ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \
+-		   ext4_jbd2.o migrate.o mballoc.o
++		ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \
++		ext4_jbd2.o migrate.o mballoc.o block_validity.o
+ 
+ ext4-$(CONFIG_EXT4_FS_XATTR)		+= xattr.o xattr_user.o xattr_trusted.o
+ ext4-$(CONFIG_EXT4_FS_POSIX_ACL)	+= acl.o
+diff --git a/fs/ext4/block_validity.c b/fs/ext4/block_validity.c
+new file mode 100644
+index 000000000000..50784ef07563
+--- /dev/null
++++ b/fs/ext4/block_validity.c
+@@ -0,0 +1,244 @@
++/*
++ *  linux/fs/ext4/block_validity.c
++ *
++ * Copyright (C) 2009
++ * Theodore Ts'o (tytso@mit.edu)
++ *
++ * Track which blocks in the filesystem are metadata blocks that
++ * should never be used as data blocks by files or directories.
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include "ext4.h"
++
++struct ext4_system_zone {
++	struct rb_node	node;
++	ext4_fsblk_t	start_blk;
++	unsigned int	count;
++};
++
++static struct kmem_cache *ext4_system_zone_cachep;
++
++int __init init_ext4_system_zone(void)
++{
++	ext4_system_zone_cachep = KMEM_CACHE(ext4_system_zone,
++					     SLAB_RECLAIM_ACCOUNT);
++	if (ext4_system_zone_cachep == NULL)
++		return -ENOMEM;
++	return 0;
++}
++
++void exit_ext4_system_zone(void)
++{
++	kmem_cache_destroy(ext4_system_zone_cachep);
++}
++
++static inline int can_merge(struct ext4_system_zone *entry1,
++		     struct ext4_system_zone *entry2)
++{
++	if ((entry1->start_blk + entry1->count) == entry2->start_blk)
++		return 1;
++	return 0;
++}
++
++/*
++ * Mark a range of blocks as belonging to the "system zone" --- that
++ * is, filesystem metadata blocks which should never be used by
++ * inodes.
++ */
++static int add_system_zone(struct ext4_sb_info *sbi,
++			   ext4_fsblk_t start_blk,
++			   unsigned int count)
++{
++	struct ext4_system_zone *new_entry = NULL, *entry;
++	struct rb_node **n = &sbi->system_blks.rb_node, *node;
++	struct rb_node *parent = NULL, *new_node = NULL;
++
++	while (*n) {
++		parent = *n;
++		entry = rb_entry(parent, struct ext4_system_zone, node);
++		if (start_blk < entry->start_blk)
++			n = &(*n)->rb_left;
++		else if (start_blk >= (entry->start_blk + entry->count))
++			n = &(*n)->rb_right;
++		else {
++			if (start_blk + count > (entry->start_blk + 
++						 entry->count))
++				entry->count = (start_blk + count - 
++						entry->start_blk);
++			new_node = *n;
++			new_entry = rb_entry(new_node, struct ext4_system_zone,
++					     node);
++			break;
++		}
++	}
++
++	if (!new_entry) {
++		new_entry = kmem_cache_alloc(ext4_system_zone_cachep,
++					     GFP_KERNEL);
++		if (!new_entry)
++			return -ENOMEM;
++		new_entry->start_blk = start_blk;
++		new_entry->count = count;
++		new_node = &new_entry->node;
++
++		rb_link_node(new_node, parent, n);
++		rb_insert_color(new_node, &sbi->system_blks);
++	}
++
++	/* Can we merge to the left? */
++	node = rb_prev(new_node);
++	if (node) {
++		entry = rb_entry(node, struct ext4_system_zone, node);
++		if (can_merge(entry, new_entry)) {
++			new_entry->start_blk = entry->start_blk;
++			new_entry->count += entry->count;
++			rb_erase(node, &sbi->system_blks);
++			kmem_cache_free(ext4_system_zone_cachep, entry);
++		}
++	}
++
++	/* Can we merge to the right? */
++	node = rb_next(new_node);
++	if (node) {
++		entry = rb_entry(node, struct ext4_system_zone, node);
++		if (can_merge(new_entry, entry)) {
++			new_entry->count += entry->count;
++			rb_erase(node, &sbi->system_blks);
++			kmem_cache_free(ext4_system_zone_cachep, entry);
++		}
++	}
++	return 0;
++}
++
++static void debug_print_tree(struct ext4_sb_info *sbi)
++{
++	struct rb_node *node;
++	struct ext4_system_zone *entry;
++	int first = 1;
++
++	printk(KERN_INFO "System zones: ");
++	node = rb_first(&sbi->system_blks);
++	while (node) {
++		entry = rb_entry(node, struct ext4_system_zone, node);
++		printk("%s%llu-%llu", first ? "" : ", ",
++		       entry->start_blk, entry->start_blk + entry->count - 1);
++		first = 0;
++		node = rb_next(node);
++	}
++	printk("\n");
++}
++
++int ext4_setup_system_zone(struct super_block *sb)
++{
++	ext4_group_t ngroups = ext4_get_groups_count(sb);
++	struct ext4_sb_info *sbi = EXT4_SB(sb);
++	struct ext4_group_desc *gdp;
++	ext4_group_t i;
++	int flex_size = ext4_flex_bg_size(sbi);
++	int ret;
++
++	if (!test_opt(sb, BLOCK_VALIDITY)) {
++		if (EXT4_SB(sb)->system_blks.rb_node)
++			ext4_release_system_zone(sb);
++		return 0;
++	}
++	if (EXT4_SB(sb)->system_blks.rb_node)
++		return 0;
++
++	for (i=0; i < ngroups; i++) {
++		if (ext4_bg_has_super(sb, i) &&
++		    ((i < 5) || ((i % flex_size) == 0)))
++			add_system_zone(sbi, ext4_group_first_block_no(sb, i),
++					sbi->s_gdb_count + 1);
++		gdp = ext4_get_group_desc(sb, i, NULL);
++		ret = add_system_zone(sbi, ext4_block_bitmap(sb, gdp), 1);
++		if (ret)
++			return ret;
++		ret = add_system_zone(sbi, ext4_inode_bitmap(sb, gdp), 1);
++		if (ret)
++			return ret;
++		ret = add_system_zone(sbi, ext4_inode_table(sb, gdp),
++				sbi->s_itb_per_group);
++		if (ret)
++			return ret;
++	}
++
++	if (test_opt(sb, DEBUG))
++		debug_print_tree(EXT4_SB(sb));
++	return 0;
++}
++
++/* Called when the filesystem is unmounted */
++void ext4_release_system_zone(struct super_block *sb)
++{
++	struct rb_node	*n = EXT4_SB(sb)->system_blks.rb_node;
++	struct rb_node	*parent;
++	struct ext4_system_zone	*entry;
++
++	while (n) {
++		/* Do the node's children first */
++		if (n->rb_left) {
++			n = n->rb_left;
++			continue;
++		}
++		if (n->rb_right) {
++			n = n->rb_right;
++			continue;
++		}
++		/*
++		 * The node has no children; free it, and then zero
++		 * out parent's link to it.  Finally go to the
++		 * beginning of the loop and try to free the parent
++		 * node.
++		 */
++		parent = rb_parent(n);
++		entry = rb_entry(n, struct ext4_system_zone, node);
++		kmem_cache_free(ext4_system_zone_cachep, entry);
++		if (!parent)
++			EXT4_SB(sb)->system_blks.rb_node = NULL;
++		else if (parent->rb_left == n)
++			parent->rb_left = NULL;
++		else if (parent->rb_right == n)
++			parent->rb_right = NULL;
++		n = parent;
++	}
++	EXT4_SB(sb)->system_blks.rb_node = NULL;
++}
++
++/*
++ * Returns 1 if the passed-in block region (start_blk,
++ * start_blk+count) is valid; 0 if some part of the block region
++ * overlaps with filesystem metadata blocks.
++ */
++int ext4_data_block_valid(struct ext4_sb_info *sbi, ext4_fsblk_t start_blk,
++			  unsigned int count)
++{
++	struct ext4_system_zone *entry;
++	struct rb_node *n = sbi->system_blks.rb_node;
++
++	if ((start_blk <= le32_to_cpu(sbi->s_es->s_first_data_block)) ||
++	    (start_blk + count > ext4_blocks_count(sbi->s_es)))
++		return 0;
++	while (n) {
++		entry = rb_entry(n, struct ext4_system_zone, node);
++		if (start_blk + count - 1 < entry->start_blk)
++			n = n->rb_left;
++		else if (start_blk >= (entry->start_blk + entry->count))
++			n = n->rb_right;
++		else
++			return 0;
++	}
++	return 1;
++}
++
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index d164f1294e5f..4311cc85b534 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -696,6 +696,7 @@ struct ext4_inode_info {
+ #define EXT4_MOUNT_I_VERSION            0x2000000 /* i_version support */
+ #define EXT4_MOUNT_DELALLOC		0x8000000 /* Delalloc support */
+ #define EXT4_MOUNT_DATA_ERR_ABORT	0x10000000 /* Abort on file data write */
++#define EXT4_MOUNT_BLOCK_VALIDITY	0x20000000 /* Block validity checking */
+ 
+ /* Compatibility, for having both ext2_fs.h and ext4_fs.h included at once */
+ #ifndef _LINUX_EXT2_FS_H
+@@ -887,6 +888,7 @@ struct ext4_sb_info {
+ 	int s_jquota_fmt;			/* Format of quota to use */
+ #endif
+ 	unsigned int s_want_extra_isize; /* New inodes should reserve # bytes */
++	struct rb_root system_blks;
+ 
+ #ifdef EXTENTS_STATS
+ 	/* ext4 extents stats */
+@@ -1618,6 +1620,15 @@ extern struct dentry *ext4_get_parent(struct dentry *child);
+ extern const struct inode_operations ext4_symlink_inode_operations;
+ extern const struct inode_operations ext4_fast_symlink_inode_operations;
+ 
++/* block_validity */
++extern void ext4_release_system_zone(struct super_block *sb);
++extern int ext4_setup_system_zone(struct super_block *sb);
++extern int __init init_ext4_system_zone(void);
++extern void exit_ext4_system_zone(void);
++extern int ext4_data_block_valid(struct ext4_sb_info *sbi,
++				 ext4_fsblk_t start_blk,
++				 unsigned int count);
++
+ /* extents.c */
+ extern int ext4_ext_tree_init(handle_t *handle, struct inode *);
+ extern int ext4_ext_writepage_trans_blocks(struct inode *, int);
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 27c383c7b43c..d04b779b780e 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -326,32 +326,18 @@ ext4_ext_max_entries(struct inode *inode, int depth)
+ 
+ static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext)
+ {
+-	ext4_fsblk_t block = ext_pblock(ext), valid_block;
++	ext4_fsblk_t block = ext_pblock(ext);
+ 	int len = ext4_ext_get_actual_len(ext);
+-	struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
+ 
+-	valid_block = le32_to_cpu(es->s_first_data_block) +
+-		EXT4_SB(inode->i_sb)->s_gdb_count;
+-	if (unlikely(block <= valid_block ||
+-		     ((block + len) > ext4_blocks_count(es))))
+-		return 0;
+-	else
+-		return 1;
++	return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, len);
+ }
+ 
+ static int ext4_valid_extent_idx(struct inode *inode,
+ 				struct ext4_extent_idx *ext_idx)
+ {
+-	ext4_fsblk_t block = idx_pblock(ext_idx), valid_block;
+-	struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
++	ext4_fsblk_t block = idx_pblock(ext_idx);
+ 
+-	valid_block = le32_to_cpu(es->s_first_data_block) +
+-		EXT4_SB(inode->i_sb)->s_gdb_count;
+-	if (unlikely(block <= valid_block ||
+-		     (block >= ext4_blocks_count(es))))
+-		return 0;
+-	else
+-		return 1;
++	return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, 1);
+ }
+ 
+ static int ext4_valid_extent_entries(struct inode *inode,
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index d7b7480682b9..dadd3f995db5 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -372,20 +372,21 @@ static int ext4_block_to_path(struct inode *inode,
+ }
+ 
+ static int __ext4_check_blockref(const char *function, struct inode *inode,
+-				 __le32 *p, unsigned int max) {
+-
+-	unsigned int maxblocks = ext4_blocks_count(EXT4_SB(inode->i_sb)->s_es);
++				 __le32 *p, unsigned int max)
++{
+ 	__le32 *bref = p;
++	unsigned int blk;
++
+ 	while (bref < p+max) {
+-		if (unlikely(le32_to_cpu(*bref) >= maxblocks)) {
++		blk = le32_to_cpu(*bref++);
++		if (blk && 
++		    unlikely(!ext4_data_block_valid(EXT4_SB(inode->i_sb), 
++						    blk, 1))) {
+ 			ext4_error(inode->i_sb, function,
+-				   "block reference %u >= max (%u) "
+-				   "in inode #%lu, offset=%d",
+-				   le32_to_cpu(*bref), maxblocks,
+-				   inode->i_ino, (int)(bref-p));
++				   "invalid block reference %u "
++				   "in inode #%lu", blk, inode->i_ino);
+  			return -EIO;
+  		}
+-		bref++;
+  	}
+  	return 0;
+ }
+@@ -1125,6 +1126,21 @@ static void ext4_da_update_reserve_space(struct inode *inode, int used)
+ 		ext4_discard_preallocations(inode);
+ }
+ 
++static int check_block_validity(struct inode *inode, sector_t logical,
++				sector_t phys, int len)
++{
++	if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), phys, len)) {
++		ext4_error(inode->i_sb, "check_block_validity",
++			   "inode #%lu logical block %llu mapped to %llu "
++			   "(size %d)", inode->i_ino,
++			   (unsigned long long) logical,
++			   (unsigned long long) phys, len);
++		WARN_ON(1);
++		return -EIO;
++	}
++	return 0;
++}
++
+ /*
+  * The ext4_get_blocks() function tries to look up the requested blocks,
+  * and returns if the blocks are already mapped.
+@@ -1170,6 +1186,13 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block,
+ 	}
+ 	up_read((&EXT4_I(inode)->i_data_sem));
+ 
++	if (retval > 0 && buffer_mapped(bh)) {
++		int ret = check_block_validity(inode, block, 
++					       bh->b_blocknr, retval);
++		if (ret != 0)
++			return ret;
++	}
++
+ 	/* If it is only a block(s) look up */
+ 	if ((flags & EXT4_GET_BLOCKS_CREATE) == 0)
+ 		return retval;
+@@ -1245,6 +1268,12 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block,
+ 		ext4_da_update_reserve_space(inode, retval);
+ 
+ 	up_write((&EXT4_I(inode)->i_data_sem));
++	if (retval > 0 && buffer_mapped(bh)) {
++		int ret = check_block_validity(inode, block, 
++					       bh->b_blocknr, retval);
++		if (ret != 0)
++			return ret;
++	}
+ 	return retval;
+ }
+ 
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 541bd9adffa2..ed8482e22c0e 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2961,15 +2961,10 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
+ 		+ le32_to_cpu(es->s_first_data_block);
+ 
+ 	len = ac->ac_b_ex.fe_len;
+-	if (in_range(ext4_block_bitmap(sb, gdp), block, len) ||
+-	    in_range(ext4_inode_bitmap(sb, gdp), block, len) ||
+-	    in_range(block, ext4_inode_table(sb, gdp),
+-		     EXT4_SB(sb)->s_itb_per_group) ||
+-	    in_range(block + len - 1, ext4_inode_table(sb, gdp),
+-		     EXT4_SB(sb)->s_itb_per_group)) {
++	if (!ext4_data_block_valid(sbi, block, len)) {
+ 		ext4_error(sb, __func__,
+-			   "Allocating block %llu in system zone of %d group\n",
+-			   block, ac->ac_b_ex.fe_group);
++			   "Allocating blocks %llu-%llu which overlap "
++			   "fs metadata\n", block, block+len);
+ 		/* File system mounted not to panic on error
+ 		 * Fix the bitmap and repeat the block allocation
+ 		 * We leak some of the blocks here.
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index dc34ed3d1327..600b7ad699b5 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -568,6 +568,7 @@ static void ext4_put_super(struct super_block *sb)
+ 	struct ext4_super_block *es = sbi->s_es;
+ 	int i, err;
+ 
++	ext4_release_system_zone(sb);
+ 	ext4_mb_release(sb);
+ 	ext4_ext_release(sb);
+ 	ext4_xattr_put_super(sb);
+@@ -1055,6 +1056,7 @@ enum {
+ 	Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err, Opt_resize,
+ 	Opt_usrquota, Opt_grpquota, Opt_i_version,
+ 	Opt_stripe, Opt_delalloc, Opt_nodelalloc,
++	Opt_block_validity, Opt_noblock_validity,
+ 	Opt_inode_readahead_blks, Opt_journal_ioprio
+ };
+ 
+@@ -1114,6 +1116,8 @@ static const match_table_t tokens = {
+ 	{Opt_resize, "resize"},
+ 	{Opt_delalloc, "delalloc"},
+ 	{Opt_nodelalloc, "nodelalloc"},
++	{Opt_block_validity, "block_validity"},
++	{Opt_noblock_validity, "noblock_validity"},
+ 	{Opt_inode_readahead_blks, "inode_readahead_blks=%u"},
+ 	{Opt_journal_ioprio, "journal_ioprio=%u"},
+ 	{Opt_auto_da_alloc, "auto_da_alloc=%u"},
+@@ -1508,6 +1512,12 @@ static int parse_options(char *options, struct super_block *sb,
+ 		case Opt_delalloc:
+ 			set_opt(sbi->s_mount_opt, DELALLOC);
+ 			break;
++		case Opt_block_validity:
++			set_opt(sbi->s_mount_opt, BLOCK_VALIDITY);
++			break;
++		case Opt_noblock_validity:
++			clear_opt(sbi->s_mount_opt, BLOCK_VALIDITY);
++			break;
+ 		case Opt_inode_readahead_blks:
+ 			if (match_int(&args[0], &option))
+ 				return 0;
+@@ -2826,6 +2836,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	} else if (test_opt(sb, DELALLOC))
+ 		printk(KERN_INFO "EXT4-fs: delayed allocation enabled\n");
+ 
++	err = ext4_setup_system_zone(sb);
++	if (err) {
++		printk(KERN_ERR "EXT4-fs: failed to initialize system "
++		       "zone (%d)\n", err);
++		goto failed_mount4;
++	}
++
+ 	ext4_ext_init(sb);
+ 	err = ext4_mb_init(sb, needs_recovery);
+ 	if (err) {
+@@ -2875,6 +2892,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 
+ failed_mount4:
+ 	printk(KERN_ERR "EXT4-fs (device %s): mount failed\n", sb->s_id);
++	ext4_release_system_zone(sb);
+ 	if (sbi->s_journal) {
+ 		jbd2_journal_destroy(sbi->s_journal);
+ 		sbi->s_journal = NULL;
+@@ -3515,6 +3533,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 				sb->s_flags &= ~MS_RDONLY;
+ 		}
+ 	}
++	ext4_setup_system_zone(sb);
+ 	if (sbi->s_journal == NULL)
+ 		ext4_commit_super(sb, 1);
+ 
+@@ -3927,13 +3946,16 @@ static int __init init_ext4_fs(void)
+ {
+ 	int err;
+ 
++	err = init_ext4_system_zone();
++	if (err)
++		return err;
+ 	ext4_kset = kset_create_and_add("ext4", NULL, fs_kobj);
+ 	if (!ext4_kset)
+-		return -ENOMEM;
++		goto out4;
+ 	ext4_proc_root = proc_mkdir("fs/ext4", NULL);
+ 	err = init_ext4_mballoc();
+ 	if (err)
+-		return err;
++		goto out3;
+ 
+ 	err = init_ext4_xattr();
+ 	if (err)
+@@ -3958,6 +3980,11 @@ static int __init init_ext4_fs(void)
+ 	exit_ext4_xattr();
+ out2:
+ 	exit_ext4_mballoc();
++out3:
++	remove_proc_entry("fs/ext4", NULL);
++	kset_unregister(ext4_kset);
++out4:
++	exit_ext4_system_zone();
+ 	return err;
+ }
+ 
+@@ -3972,6 +3999,7 @@ static void __exit exit_ext4_fs(void)
+ 	exit_ext4_mballoc();
+ 	remove_proc_entry("fs/ext4", NULL);
+ 	kset_unregister(ext4_kset);
++	exit_ext4_system_zone();
+ }
+ 
+ MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");

commit 2ec0ae3acec47f628179ee95fe2c4da01b5e9fc4
+Author: Theodore Ts'o 
+Date:   Fri May 15 09:07:28 2009 -0400
+
+    ext4: Fix race in ext4_inode_info.i_cached_extent
+    
+    If two CPU's simultaneously call ext4_ext_get_blocks() at the same
+    time, there is nothing protecting the i_cached_extent structure from
+    being used and updated at the same time.  This could potentially cause
+    the wrong location on disk to be read or written to, including
+    potentially causing the corruption of the block group descriptors
+    and/or inode table.
+    
+    This bug has been in the ext4 code since almost the very beginning of
+    ext4's development.  Fortunately once the data is stored in the page
+    cache cache, ext4_get_blocks() doesn't need to be called, so trying to
+    replicate this problem to the point where we could identify its root
+    cause was *extremely* difficult.  Many thanks to Kevin Shanahan for
+    working over several months to be able to reproduce this easily so we
+    could finally nail down the cause of the corruption.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: "Aneesh Kumar K.V" 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 172656c2a3bd..e3a55eb8b26a 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -1841,11 +1841,13 @@ ext4_ext_put_in_cache(struct inode *inode, ext4_lblk_t block,
+ {
+ 	struct ext4_ext_cache *cex;
+ 	BUG_ON(len == 0);
++	spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
+ 	cex = &EXT4_I(inode)->i_cached_extent;
+ 	cex->ec_type = type;
+ 	cex->ec_block = block;
+ 	cex->ec_len = len;
+ 	cex->ec_start = start;
++	spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+ }
+ 
+ /*
+@@ -1902,12 +1904,17 @@ ext4_ext_in_cache(struct inode *inode, ext4_lblk_t block,
+ 			struct ext4_extent *ex)
+ {
+ 	struct ext4_ext_cache *cex;
++	int ret = EXT4_EXT_CACHE_NO;
+ 
++	/* 
++	 * We borrow i_block_reservation_lock to protect i_cached_extent
++	 */
++	spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
+ 	cex = &EXT4_I(inode)->i_cached_extent;
+ 
+ 	/* has cache valid data? */
+ 	if (cex->ec_type == EXT4_EXT_CACHE_NO)
+-		return EXT4_EXT_CACHE_NO;
++		goto errout;
+ 
+ 	BUG_ON(cex->ec_type != EXT4_EXT_CACHE_GAP &&
+ 			cex->ec_type != EXT4_EXT_CACHE_EXTENT);
+@@ -1918,11 +1925,11 @@ ext4_ext_in_cache(struct inode *inode, ext4_lblk_t block,
+ 		ext_debug("%u cached by %u:%u:%llu\n",
+ 				block,
+ 				cex->ec_block, cex->ec_len, cex->ec_start);
+-		return cex->ec_type;
++		ret = cex->ec_type;
+ 	}
+-
+-	/* not in cache */
+-	return EXT4_EXT_CACHE_NO;
++errout:
++	spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
++	return ret;
+ }
+ 
+ /*

commit 2ac3b6e00acb46406c993d57921f86a594aafe08
+Author: Theodore Ts'o 
+Date:   Thu May 14 13:57:08 2009 -0400
+
+    ext4: Clean up ext4_get_blocks() so it does not depend on bh_result->b_state
+    
+    The ext4_get_blocks() function was depending on the value of
+    bh_result->b_state as an input parameter to decide whether or not
+    update the delalloc accounting statistics by calling
+    ext4_da_update_reserve_space().  We now use a separate flag,
+    EXT4_GET_BLOCKS_UPDATE_RESERVE_SPACE, to requests this update, so that
+    all callers of ext4_get_blocks() can clear map_bh.b_state before
+    calling ext4_get_blocks() without worrying about any consistency
+    issues.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 17feb4ac633a..d164f1294e5f 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -318,16 +318,21 @@ struct ext4_new_group_data {
+  */
+ 	/* Allocate any needed blocks and/or convert an unitialized
+ 	   extent to be an initialized ext4 */
+-#define EXT4_GET_BLOCKS_CREATE			1
++#define EXT4_GET_BLOCKS_CREATE			0x0001
+ 	/* Request the creation of an unitialized extent */
+-#define EXT4_GET_BLOCKS_UNINIT_EXT		2
++#define EXT4_GET_BLOCKS_UNINIT_EXT		0x0002
+ #define EXT4_GET_BLOCKS_CREATE_UNINIT_EXT	(EXT4_GET_BLOCKS_UNINIT_EXT|\
+ 						 EXT4_GET_BLOCKS_CREATE)
+ 	/* Update the ext4_inode_info i_disksize field */
+-#define EXT4_GET_BLOCKS_EXTEND_DISKSIZE		4
++#define EXT4_GET_BLOCKS_EXTEND_DISKSIZE		0x0004
+ 	/* Caller is from the delayed allocation writeout path,
+-	   so the filesystem blocks have already been accounted for */
+-#define EXT4_GET_BLOCKS_DELALLOC_RESERVE	8
++	   so set the magic i_delalloc_reserve_flag after taking the 
++	   inode allocation semaphore for */
++#define EXT4_GET_BLOCKS_DELALLOC_RESERVE	0x0008
++	/* Call ext4_da_update_reserve_space() after successfully 
++	   allocating the blocks */
++#define EXT4_GET_BLOCKS_UPDATE_RESERVE_SPACE	0x0010
++
+ 
+ /*
+  * ioctl commands
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index bfe50a22363b..d7b7480682b9 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1234,16 +1234,15 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block,
+ 		}
+ 	}
+ 
+-	if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) {
++	if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
+ 		EXT4_I(inode)->i_delalloc_reserved_flag = 0;
+-		/*
+-		 * Update reserved blocks/metadata blocks
+-		 * after successful block allocation
+-		 * which were deferred till now
+-		 */
+-		if ((retval > 0) && buffer_delay(bh))
+-			ext4_da_update_reserve_space(inode, retval);
+-	}
++
++	/*
++	 * Update reserved blocks/metadata blocks after successful
++	 * block allocation which had been deferred till now.
++	 */
++	if ((retval > 0) && (flags & EXT4_GET_BLOCKS_UPDATE_RESERVE_SPACE))
++		ext4_da_update_reserve_space(inode, retval);
+ 
+ 	up_write((&EXT4_I(inode)->i_data_sem));
+ 	return retval;
+@@ -2015,7 +2014,7 @@ static void ext4_print_free_blocks(struct inode *inode)
+  */
+ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
+ {
+-	int err, blks;
++	int err, blks, get_blocks_flags;
+ 	struct buffer_head new;
+ 	sector_t next = mpd->b_blocknr;
+ 	unsigned max_blocks = mpd->b_size >> mpd->inode->i_blkbits;
+@@ -2040,23 +2039,30 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
+ 	BUG_ON(!handle);
+ 
+ 	/*
+-	 * We need to make sure the BH_Delay flag is passed down to
+-	 * ext4_da_get_block_write(), since it calls ext4_get_blocks()
+-	 * with the EXT4_GET_BLOCKS_DELALLOC_RESERVE flag.  This flag
+-	 * causes ext4_get_blocks() to call
+-	 * ext4_da_update_reserve_space() if the passed buffer head
+-	 * has the BH_Delay flag set.  In the future, once we clean up
+-	 * the interfaces to ext4_get_blocks(), we should pass in a
+-	 * separate flag which requests that the delayed allocation
+-	 * statistics should be updated, instead of depending on the
+-	 * state information getting passed down via the map_bh's
+-	 * state bitmasks plus the magic
+-	 * EXT4_GET_BLOCKS_DELALLOC_RESERVE flag.
++	 * Call ext4_get_blocks() to allocate any delayed allocation
++	 * blocks, or to convert an uninitialized extent to be
++	 * initialized (in the case where we have written into
++	 * one or more preallocated blocks).
++	 *
++	 * We pass in the magic EXT4_GET_BLOCKS_DELALLOC_RESERVE to
++	 * indicate that we are on the delayed allocation path.  This
++	 * affects functions in many different parts of the allocation
++	 * call path.  This flag exists primarily because we don't
++	 * want to change *many* call functions, so ext4_get_blocks()
++	 * will set the magic i_delalloc_reserved_flag once the
++	 * inode's allocation semaphore is taken.
++	 *
++	 * If the blocks in questions were delalloc blocks, set
++	 * EXT4_GET_BLOCKS_DELALLOC_RESERVE so the delalloc accounting
++	 * variables are updated after the blocks have been allocated.
+ 	 */
+-	new.b_state = mpd->b_state & (1 << BH_Delay);
++	new.b_state = 0;
++	get_blocks_flags = (EXT4_GET_BLOCKS_CREATE |
++			    EXT4_GET_BLOCKS_DELALLOC_RESERVE);
++	if (mpd->b_state & (1 << BH_Delay))
++		get_blocks_flags |= EXT4_GET_BLOCKS_UPDATE_RESERVE_SPACE;
+ 	blks = ext4_get_blocks(handle, mpd->inode, next, max_blocks,
+-			       &new, EXT4_GET_BLOCKS_CREATE|
+-			       EXT4_GET_BLOCKS_DELALLOC_RESERVE);
++			       &new, get_blocks_flags);
+ 	if (blks < 0) {
+ 		err = blks;
+ 		/*

commit 2fa3cdfb319055fd8b25abdafa413e16f00ad493
+Author: Theodore Ts'o 
+Date:   Thu May 14 09:29:45 2009 -0400
+
+    ext4: Merge ext4_da_get_block_write() into mpage_da_map_blocks()
+    
+    The static function ext4_da_get_block_write() was only used by
+    mpage_da_map_blocks().  So to simplify the code, merge that function
+    into mpage_da_map_blocks().
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index e6113c3a126f..bfe50a22363b 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2005,57 +2005,6 @@ static void ext4_print_free_blocks(struct inode *inode)
+ 	return;
+ }
+ 
+-/*
+- * This function is used by mpage_da_map_blocks().  We separate it out
+- * as a separate function just to make life easier, and because
+- * mpage_da_map_blocks() used to be a generic function that took a
+- * get_block_t.
+- */
+-static int ext4_da_get_block_write(struct inode *inode, sector_t iblock,
+-				   struct buffer_head *bh_result)
+-{
+-	int ret;
+-	unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
+-	loff_t disksize = EXT4_I(inode)->i_disksize;
+-	handle_t *handle = NULL;
+-
+-	handle = ext4_journal_current_handle();
+-	BUG_ON(!handle);
+-	ret = ext4_get_blocks(handle, inode, iblock, max_blocks,
+-			      bh_result, EXT4_GET_BLOCKS_CREATE|
+-			      EXT4_GET_BLOCKS_DELALLOC_RESERVE);
+-	if (ret <= 0)
+-		return ret;
+-
+-	bh_result->b_size = (ret << inode->i_blkbits);
+-
+-	if (ext4_should_order_data(inode)) {
+-		int retval;
+-		retval = ext4_jbd2_file_inode(handle, inode);
+-		if (retval)
+-			/*
+-			 * Failed to add inode for ordered mode. Don't
+-			 * update file size
+-			 */
+-			return retval;
+-	}
+-
+-	/*
+-	 * Update on-disk size along with block allocation we don't
+-	 * use EXT4_GET_BLOCKS_EXTEND_DISKSIZE as size may change
+-	 * within already allocated block -bzzz
+-	 */
+-	disksize = ((loff_t) iblock + ret) << inode->i_blkbits;
+-	if (disksize > i_size_read(inode))
+-		disksize = i_size_read(inode);
+-	if (disksize > EXT4_I(inode)->i_disksize) {
+-		ext4_update_i_disksize(inode, disksize);
+-		ret = ext4_mark_inode_dirty(handle, inode);
+-		return ret;
+-	}
+-	return 0;
+-}
+-
+ /*
+  * mpage_da_map_blocks - go through given space
+  *
+@@ -2066,9 +2015,12 @@ static int ext4_da_get_block_write(struct inode *inode, sector_t iblock,
+  */
+ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
+ {
+-	int err = 0;
++	int err, blks;
+ 	struct buffer_head new;
+-	sector_t next;
++	sector_t next = mpd->b_blocknr;
++	unsigned max_blocks = mpd->b_size >> mpd->inode->i_blkbits;
++	loff_t disksize = EXT4_I(mpd->inode)->i_disksize;
++	handle_t *handle = NULL;
+ 
+ 	/*
+ 	 * We consider only non-mapped and non-allocated blocks
+@@ -2077,6 +2029,16 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
+ 		!(mpd->b_state & (1 << BH_Delay)) &&
+ 		!(mpd->b_state & (1 << BH_Unwritten)))
+ 		return 0;
++
++	/*
++	 * If we didn't accumulate anything to write simply return
++	 */
++	if (!mpd->b_size)
++		return 0;
++
++	handle = ext4_journal_current_handle();
++	BUG_ON(!handle);
++
+ 	/*
+ 	 * We need to make sure the BH_Delay flag is passed down to
+ 	 * ext4_da_get_block_write(), since it calls ext4_get_blocks()
+@@ -2092,18 +2054,11 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
+ 	 * EXT4_GET_BLOCKS_DELALLOC_RESERVE flag.
+ 	 */
+ 	new.b_state = mpd->b_state & (1 << BH_Delay);
+-	new.b_blocknr = 0;
+-	new.b_size = mpd->b_size;
+-	next = mpd->b_blocknr;
+-	/*
+-	 * If we didn't accumulate anything
+-	 * to write simply return
+-	 */
+-	if (!new.b_size)
+-		return 0;
+-
+-	err = ext4_da_get_block_write(mpd->inode, next, &new);
+-	if (err) {
++	blks = ext4_get_blocks(handle, mpd->inode, next, max_blocks,
++			       &new, EXT4_GET_BLOCKS_CREATE|
++			       EXT4_GET_BLOCKS_DELALLOC_RESERVE);
++	if (blks < 0) {
++		err = blks;
+ 		/*
+ 		 * If get block returns with error we simply
+ 		 * return. Later writepage will redirty the page and
+@@ -2136,12 +2091,14 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
+ 		if (err == -ENOSPC) {
+ 			ext4_print_free_blocks(mpd->inode);
+ 		}
+-		/* invlaidate all the pages */
++		/* invalidate all the pages */
+ 		ext4_da_block_invalidatepages(mpd, next,
+ 				mpd->b_size >> mpd->inode->i_blkbits);
+ 		return err;
+ 	}
+-	BUG_ON(new.b_size == 0);
++	BUG_ON(blks == 0);
++
++	new.b_size = (blks << mpd->inode->i_blkbits);
+ 
+ 	if (buffer_new(&new))
+ 		__unmap_underlying_blocks(mpd->inode, &new);
+@@ -2154,6 +2111,25 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
+ 	    (mpd->b_state & (1 << BH_Unwritten)))
+ 		mpage_put_bnr_to_bhs(mpd, next, &new);
+ 
++	if (ext4_should_order_data(mpd->inode)) {
++		err = ext4_jbd2_file_inode(handle, mpd->inode);
++		if (err)
++			return err;
++	}
++
++	/*
++	 * Update on-disk size along with block allocation we don't
++	 * use EXT4_GET_BLOCKS_EXTEND_DISKSIZE as size may change
++	 * within already allocated block -bzzz
++	 */
++	disksize = ((loff_t) next + blks) << mpd->inode->i_blkbits;
++	if (disksize > i_size_read(mpd->inode))
++		disksize = i_size_read(mpd->inode);
++	if (disksize > EXT4_I(mpd->inode)->i_disksize) {
++		ext4_update_i_disksize(mpd->inode, disksize);
++		return ext4_mark_inode_dirty(handle, mpd->inode);
++	}
++
+ 	return 0;
+ }
+ 

commit a2dc52b5d1d8cc280b3e795abf1c80ac8c49f30c
+Author: Theodore Ts'o 
+Date:   Tue May 12 13:51:29 2009 -0400
+
+    ext4: Add BUG_ON debugging checks to noalloc_get_block_write()
+    
+    Enforce that noalloc_get_block_write() is only called to map one block
+    at a time, and that it always is successful in finding a mapping for
+    given an inode's logical block block number if it is called with
+    create == 1.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index fd5f27a9b81b..e6113c3a126f 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2433,11 +2433,14 @@ static int noalloc_get_block_write(struct inode *inode, sector_t iblock,
+ 	int ret = 0;
+ 	unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
+ 
++	BUG_ON(bh_result->b_size != inode->i_sb->s_blocksize);
++
+ 	/*
+ 	 * we don't want to do block allocation in writepage
+ 	 * so call get_block_wrap with create = 0
+ 	 */
+ 	ret = ext4_get_blocks(NULL, inode, iblock, max_blocks, bh_result, 0);
++	BUG_ON(create && ret == 0);
+ 	if (ret > 0) {
+ 		bh_result->b_size = (ret << inode->i_blkbits);
+ 		ret = 0;

commit b920c75502cb2c48654ef196d647c8eb81ab608a
+Author: Theodore Ts'o 
+Date:   Thu May 14 00:54:29 2009 -0400
+
+    ext4: Add documentation to the ext4_*get_block* functions
+    
+    This adds more documentation to various internal functions in
+    fs/ext4/inode.c, most notably ext4_ind_get_blocks(),
+    ext4_da_get_block_write(), ext4_da_get_block_prep(),
+    ext4_normal_get_block_write().
+    
+    In addition, the static function ext4_normal_get_block_write() has
+    been renamed noalloc_get_block_write(), since it is used in many
+    places far beyond ext4_normal_writepage().
+    
+    Plenty of warnings have been added to the noalloc_get_block_write()
+    function, since the way it is used is amazingly fragile.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 8b7564dfacdf..fd5f27a9b81b 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -892,6 +892,10 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
+ }
+ 
+ /*
++ * The ext4_ind_get_blocks() function handles non-extents inodes
++ * (i.e., using the traditional indirect/double-indirect i_blocks
++ * scheme) for ext4_get_blocks().
++ *
+  * Allocation strategy is simple: if we have to allocate something, we will
+  * have to go the whole way to leaf. So let's do it before attaching anything
+  * to tree, set linkage between the newborn blocks, write them if sync is
+@@ -909,10 +913,11 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
+  * return = 0, if plain lookup failed.
+  * return < 0, error case.
+  *
+- *
+- * Need to be called with
+- * down_read(&EXT4_I(inode)->i_data_sem) if not allocating file system block
+- * (ie, create is zero). Otherwise down_write(&EXT4_I(inode)->i_data_sem)
++ * The ext4_ind_get_blocks() function should be called with
++ * down_write(&EXT4_I(inode)->i_data_sem) if allocating filesystem
++ * blocks (i.e., flags has EXT4_GET_BLOCKS_CREATE set) or
++ * down_read(&EXT4_I(inode)->i_data_sem) if not allocating file system
++ * blocks.
+  */
+ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode,
+ 				  ext4_lblk_t iblock, unsigned int maxblocks,
+@@ -1152,8 +1157,8 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block,
+ 	clear_buffer_unwritten(bh);
+ 
+ 	/*
+-	 * Try to see if we can get  the block without requesting
+-	 * for new file system block.
++	 * Try to see if we can get the block without requesting a new
++	 * file system block.
+ 	 */
+ 	down_read((&EXT4_I(inode)->i_data_sem));
+ 	if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) {
+@@ -2000,6 +2005,12 @@ static void ext4_print_free_blocks(struct inode *inode)
+ 	return;
+ }
+ 
++/*
++ * This function is used by mpage_da_map_blocks().  We separate it out
++ * as a separate function just to make life easier, and because
++ * mpage_da_map_blocks() used to be a generic function that took a
++ * get_block_t.
++ */
+ static int ext4_da_get_block_write(struct inode *inode, sector_t iblock,
+ 				   struct buffer_head *bh_result)
+ {
+@@ -2031,8 +2042,8 @@ static int ext4_da_get_block_write(struct inode *inode, sector_t iblock,
+ 
+ 	/*
+ 	 * Update on-disk size along with block allocation we don't
+-	 * use 'extend_disksize' as size may change within already
+-	 * allocated block -bzzz
++	 * use EXT4_GET_BLOCKS_EXTEND_DISKSIZE as size may change
++	 * within already allocated block -bzzz
+ 	 */
+ 	disksize = ((loff_t) iblock + ret) << inode->i_blkbits;
+ 	if (disksize > i_size_read(inode))
+@@ -2338,8 +2349,9 @@ static int __mpage_da_writepage(struct page *page,
+ }
+ 
+ /*
+- * this is a special callback for ->write_begin() only
+- * it's intention is to return mapped block or reserve space
++ * This is a special get_blocks_t callback which is used by
++ * ext4_da_write_begin().  It will either return mapped block or
++ * reserve space for a single block.
+  *
+  * For delayed buffer_head we have BH_Mapped, BH_New, BH_Delay set.
+  * We also have b_blocknr = -1 and b_bdev initialized properly
+@@ -2347,7 +2359,6 @@ static int __mpage_da_writepage(struct page *page,
+  * For unwritten buffer_head we have BH_Mapped, BH_New, BH_Unwritten set.
+  * We also have b_blocknr = physicalblock mapping unwritten extent and b_bdev
+  * initialized properly.
+- *
+  */
+ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock,
+ 				  struct buffer_head *bh_result, int create)
+@@ -2400,7 +2411,23 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock,
+ 	return ret;
+ }
+ 
+-static int ext4_normal_get_block_write(struct inode *inode, sector_t iblock,
++/*
++ * This function is used as a standard get_block_t calback function
++ * when there is no desire to allocate any blocks.  It is used as a
++ * callback function for block_prepare_write(), nobh_writepage(), and
++ * block_write_full_page().  These functions should only try to map a
++ * single block at a time.
++ *
++ * Since this function doesn't do block allocations even if the caller
++ * requests it by passing in create=1, it is critically important that
++ * any caller checks to make sure that any buffer heads are returned
++ * by this function are either all already mapped or marked for
++ * delayed allocation before calling nobh_writepage() or
++ * block_write_full_page().  Otherwise, b_blocknr could be left
++ * unitialized, and the page write functions will be taken by
++ * surprise.
++ */
++static int noalloc_get_block_write(struct inode *inode, sector_t iblock,
+ 				   struct buffer_head *bh_result, int create)
+ {
+ 	int ret = 0;
+@@ -2419,10 +2446,11 @@ static int ext4_normal_get_block_write(struct inode *inode, sector_t iblock,
+ }
+ 
+ /*
+- * get called vi ext4_da_writepages after taking page lock (have journal handle)
+- * get called via journal_submit_inode_data_buffers (no journal handle)
+- * get called via shrink_page_list via pdflush (no journal handle)
+- * or grab_page_cache when doing write_begin (have journal handle)
++ * This function can get called via...
++ *   - ext4_da_writepages after taking page lock (have journal handle)
++ *   - journal_submit_inode_data_buffers (no journal handle)
++ *   - shrink_page_list via pdflush (no journal handle)
++ *   - grab_page_cache when doing write_begin (have journal handle)
+  */
+ static int ext4_da_writepage(struct page *page,
+ 				struct writeback_control *wbc)
+@@ -2473,7 +2501,7 @@ static int ext4_da_writepage(struct page *page,
+ 		 * do block allocation here.
+ 		 */
+ 		ret = block_prepare_write(page, 0, PAGE_CACHE_SIZE,
+-						ext4_normal_get_block_write);
++					  noalloc_get_block_write);
+ 		if (!ret) {
+ 			page_bufs = page_buffers(page);
+ 			/* check whether all are mapped and non delay */
+@@ -2498,11 +2526,10 @@ static int ext4_da_writepage(struct page *page,
+ 	}
+ 
+ 	if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode))
+-		ret = nobh_writepage(page, ext4_normal_get_block_write, wbc);
++		ret = nobh_writepage(page, noalloc_get_block_write, wbc);
+ 	else
+-		ret = block_write_full_page(page,
+-						ext4_normal_get_block_write,
+-						wbc);
++		ret = block_write_full_page(page, noalloc_get_block_write,
++					    wbc);
+ 
+ 	return ret;
+ }
+@@ -2814,7 +2841,7 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
+ 	*pagep = page;
+ 
+ 	ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+-							ext4_da_get_block_prep);
++				ext4_da_get_block_prep);
+ 	if (ret < 0) {
+ 		unlock_page(page);
+ 		ext4_journal_stop(handle);
+@@ -3122,12 +3149,10 @@ static int __ext4_normal_writepage(struct page *page,
+ 	struct inode *inode = page->mapping->host;
+ 
+ 	if (test_opt(inode->i_sb, NOBH))
+-		return nobh_writepage(page,
+-					ext4_normal_get_block_write, wbc);
++		return nobh_writepage(page, noalloc_get_block_write, wbc);
+ 	else
+-		return block_write_full_page(page,
+-						ext4_normal_get_block_write,
+-						wbc);
++		return block_write_full_page(page, noalloc_get_block_write,
++					     wbc);
+ }
+ 
+ static int ext4_normal_writepage(struct page *page,
+@@ -3179,7 +3204,7 @@ static int __ext4_journalled_writepage(struct page *page,
+ 	int err;
+ 
+ 	ret = block_prepare_write(page, 0, PAGE_CACHE_SIZE,
+-					ext4_normal_get_block_write);
++				  noalloc_get_block_write);
+ 	if (ret != 0)
+ 		goto out_unlock;
+ 
+@@ -3264,9 +3289,8 @@ static int ext4_journalled_writepage(struct page *page,
+ 		 * really know unless we go poke around in the buffer_heads.
+ 		 * But block_write_full_page will do the right thing.
+ 		 */
+-		return block_write_full_page(page,
+-						ext4_normal_get_block_write,
+-						wbc);
++		return block_write_full_page(page, noalloc_get_block_write,
++					     wbc);
+ 	}
+ no_write:
+ 	redirty_page_for_writepage(wbc, page);

commit c21770573319922e3f3fcb331cfaa290c49f1c81
+Author: Theodore Ts'o 
+Date:   Thu May 14 00:58:52 2009 -0400
+
+    ext4: Define a new set of flags for ext4_get_blocks()
+    
+    The functions ext4_get_blocks(), ext4_ext_get_blocks(), and
+    ext4_ind_get_blocks() used an ad-hoc set of integer variables used as
+    boolean flags passed in as arguments.  Use a single flags parameter
+    and a setandard set of bitfield flags instead.  This saves space on
+    the call stack, and it also makes the code a bit more understandable.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index 052d6378f997..9dc93168e262 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -131,7 +131,7 @@ static int ext4_readdir(struct file *filp,
+ 		struct buffer_head *bh = NULL;
+ 
+ 		map_bh.b_state = 0;
+-		err = ext4_get_blocks(NULL, inode, blk, 1, &map_bh, 0, 0, 0);
++		err = ext4_get_blocks(NULL, inode, blk, 1, &map_bh, 0);
+ 		if (err > 0) {
+ 			pgoff_t index = map_bh.b_blocknr >>
+ 					(PAGE_CACHE_SHIFT - inode->i_blkbits);
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 5dc8368e46bc..17feb4ac633a 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -314,10 +314,20 @@ struct ext4_new_group_data {
+ };
+ 
+ /*
+- * Following is used by preallocation code to tell get_blocks() that we
+- * want uninitialzed extents.
++ * Flags used by ext4_get_blocks()
+  */
+-#define EXT4_CREATE_UNINITIALIZED_EXT		2
++	/* Allocate any needed blocks and/or convert an unitialized
++	   extent to be an initialized ext4 */
++#define EXT4_GET_BLOCKS_CREATE			1
++	/* Request the creation of an unitialized extent */
++#define EXT4_GET_BLOCKS_UNINIT_EXT		2
++#define EXT4_GET_BLOCKS_CREATE_UNINIT_EXT	(EXT4_GET_BLOCKS_UNINIT_EXT|\
++						 EXT4_GET_BLOCKS_CREATE)
++	/* Update the ext4_inode_info i_disksize field */
++#define EXT4_GET_BLOCKS_EXTEND_DISKSIZE		4
++	/* Caller is from the delayed allocation writeout path,
++	   so the filesystem blocks have already been accounted for */
++#define EXT4_GET_BLOCKS_DELALLOC_RESERVE	8
+ 
+ /*
+  * ioctl commands
+@@ -1610,8 +1620,7 @@ extern int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks,
+ 				       int chunk);
+ extern int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 			       ext4_lblk_t iblock, unsigned int max_blocks,
+-			       struct buffer_head *bh_result,
+-			       int create, int extend_disksize);
++			       struct buffer_head *bh_result, int flags);
+ extern void ext4_ext_truncate(struct inode *);
+ extern void ext4_ext_init(struct super_block *);
+ extern void ext4_ext_release(struct super_block *);
+@@ -1619,8 +1628,7 @@ extern long ext4_fallocate(struct inode *inode, int mode, loff_t offset,
+ 			  loff_t len);
+ extern int ext4_get_blocks(handle_t *handle, struct inode *inode,
+ 			   sector_t block, unsigned int max_blocks,
+-			   struct buffer_head *bh, int create,
+-			   int extend_disksize, int flag);
++			   struct buffer_head *bh, int flags);
+ extern int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ 			__u64 start, __u64 len);
+ 
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 7e7d02dd2739..27c383c7b43c 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -2784,7 +2784,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 			ext4_lblk_t iblock,
+ 			unsigned int max_blocks, struct buffer_head *bh_result,
+-			int create, int extend_disksize)
++			int flags)
+ {
+ 	struct ext4_ext_path *path = NULL;
+ 	struct ext4_extent_header *eh;
+@@ -2803,7 +2803,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 	cache_type = ext4_ext_in_cache(inode, iblock, &newex);
+ 	if (cache_type) {
+ 		if (cache_type == EXT4_EXT_CACHE_GAP) {
+-			if (!create) {
++			if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) {
+ 				/*
+ 				 * block isn't allocated yet and
+ 				 * user doesn't want to allocate it
+@@ -2869,9 +2869,9 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 							EXT4_EXT_CACHE_EXTENT);
+ 				goto out;
+ 			}
+-			if (create == EXT4_CREATE_UNINITIALIZED_EXT)
++			if (flags & EXT4_GET_BLOCKS_UNINIT_EXT)
+ 				goto out;
+-			if (!create) {
++			if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) {
+ 				if (allocated > max_blocks)
+ 					allocated = max_blocks;
+ 				/*
+@@ -2903,7 +2903,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 	 * requested block isn't allocated yet;
+ 	 * we couldn't try to create block if create flag is zero
+ 	 */
+-	if (!create) {
++	if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) {
+ 		/*
+ 		 * put just found gap into cache to speed up
+ 		 * subsequent requests
+@@ -2932,10 +2932,10 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 	 * EXT_UNINIT_MAX_LEN.
+ 	 */
+ 	if (max_blocks > EXT_INIT_MAX_LEN &&
+-	    create != EXT4_CREATE_UNINITIALIZED_EXT)
++	    !(flags & EXT4_GET_BLOCKS_UNINIT_EXT))
+ 		max_blocks = EXT_INIT_MAX_LEN;
+ 	else if (max_blocks > EXT_UNINIT_MAX_LEN &&
+-		 create == EXT4_CREATE_UNINITIALIZED_EXT)
++		 (flags & EXT4_GET_BLOCKS_UNINIT_EXT))
+ 		max_blocks = EXT_UNINIT_MAX_LEN;
+ 
+ 	/* Check if we can really insert (iblock)::(iblock+max_blocks) extent */
+@@ -2966,7 +2966,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 	/* try to insert new extent into found leaf and return */
+ 	ext4_ext_store_pblock(&newex, newblock);
+ 	newex.ee_len = cpu_to_le16(ar.len);
+-	if (create == EXT4_CREATE_UNINITIALIZED_EXT)  /* Mark uninitialized */
++	if (flags & EXT4_GET_BLOCKS_UNINIT_EXT)  /* Mark uninitialized */
+ 		ext4_ext_mark_uninitialized(&newex);
+ 	err = ext4_ext_insert_extent(handle, inode, path, &newex);
+ 	if (err) {
+@@ -2983,7 +2983,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 	newblock = ext_pblock(&newex);
+ 	allocated = ext4_ext_get_actual_len(&newex);
+ outnew:
+-	if (extend_disksize) {
++	if (flags & EXT4_GET_BLOCKS_EXTEND_DISKSIZE) {
+ 		disksize = ((loff_t) iblock + ar.len) << inode->i_blkbits;
+ 		if (disksize > i_size_read(inode))
+ 			disksize = i_size_read(inode);
+@@ -2994,7 +2994,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 	set_buffer_new(bh_result);
+ 
+ 	/* Cache only when it is _not_ an uninitialized extent */
+-	if (create != EXT4_CREATE_UNINITIALIZED_EXT)
++	if ((flags & EXT4_GET_BLOCKS_UNINIT_EXT) == 0)
+ 		ext4_ext_put_in_cache(inode, iblock, allocated, newblock,
+ 						EXT4_EXT_CACHE_EXTENT);
+ out:
+@@ -3153,7 +3153,7 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len)
+ 		map_bh.b_state = 0;
+ 		ret = ext4_get_blocks(handle, inode, block,
+ 				      max_blocks, &map_bh,
+-				      EXT4_CREATE_UNINITIALIZED_EXT, 0, 0);
++				      EXT4_GET_BLOCKS_CREATE_UNINIT_EXT);
+ 		if (ret <= 0) {
+ #ifdef EXT4FS_DEBUG
+ 			WARN_ON(ret <= 0);
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index a9a9b9b77e8e..8b7564dfacdf 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -917,7 +917,7 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
+ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode,
+ 				  ext4_lblk_t iblock, unsigned int maxblocks,
+ 				  struct buffer_head *bh_result,
+-				  int create, int extend_disksize)
++				  int flags)
+ {
+ 	int err = -EIO;
+ 	ext4_lblk_t offsets[4];
+@@ -934,7 +934,7 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode,
+ 
+ 
+ 	J_ASSERT(!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL));
+-	J_ASSERT(handle != NULL || create == 0);
++	J_ASSERT(handle != NULL || (flags & EXT4_GET_BLOCKS_CREATE) == 0);
+ 	depth = ext4_block_to_path(inode, iblock, offsets,
+ 					&blocks_to_boundary);
+ 
+@@ -963,7 +963,7 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode,
+ 	}
+ 
+ 	/* Next simple case - plain lookup or failed read of indirect block */
+-	if (!create || err == -EIO)
++	if ((flags & EXT4_GET_BLOCKS_CREATE) == 0 || err == -EIO)
+ 		goto cleanup;
+ 
+ 	/*
+@@ -1002,7 +1002,7 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode,
+ 	 * protect it if you're about to implement concurrent
+ 	 * ext4_get_block() -bzzz
+ 	*/
+-	if (!err && extend_disksize) {
++	if (!err && (flags & EXT4_GET_BLOCKS_EXTEND_DISKSIZE)) {
+ 		disksize = ((loff_t) iblock + count) << inode->i_blkbits;
+ 		if (disksize > i_size_read(inode))
+ 			disksize = i_size_read(inode);
+@@ -1144,7 +1144,7 @@ static void ext4_da_update_reserve_space(struct inode *inode, int used)
+  */
+ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block,
+ 		    unsigned int max_blocks, struct buffer_head *bh,
+-		    int create, int extend_disksize, int flag)
++		    int flags)
+ {
+ 	int retval;
+ 
+@@ -1158,15 +1158,15 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block,
+ 	down_read((&EXT4_I(inode)->i_data_sem));
+ 	if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) {
+ 		retval =  ext4_ext_get_blocks(handle, inode, block, max_blocks,
+-				bh, 0, 0);
++				bh, 0);
+ 	} else {
+ 		retval = ext4_ind_get_blocks(handle, inode, block, max_blocks,
+-					     bh, 0, 0);
++					     bh, 0);
+ 	}
+ 	up_read((&EXT4_I(inode)->i_data_sem));
+ 
+ 	/* If it is only a block(s) look up */
+-	if (!create)
++	if ((flags & EXT4_GET_BLOCKS_CREATE) == 0)
+ 		return retval;
+ 
+ 	/*
+@@ -1205,7 +1205,7 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block,
+ 	 * let the underlying get_block() function know to
+ 	 * avoid double accounting
+ 	 */
+-	if (flag)
++	if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
+ 		EXT4_I(inode)->i_delalloc_reserved_flag = 1;
+ 	/*
+ 	 * We need to check for EXT4 here because migrate
+@@ -1213,10 +1213,10 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block,
+ 	 */
+ 	if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) {
+ 		retval =  ext4_ext_get_blocks(handle, inode, block, max_blocks,
+-				bh, create, extend_disksize);
++					      bh, flags);
+ 	} else {
+ 		retval = ext4_ind_get_blocks(handle, inode, block,
+-				max_blocks, bh, create, extend_disksize);
++					     max_blocks, bh, flags);
+ 
+ 		if (retval > 0 && buffer_new(bh)) {
+ 			/*
+@@ -1229,7 +1229,7 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block,
+ 		}
+ 	}
+ 
+-	if (flag) {
++	if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) {
+ 		EXT4_I(inode)->i_delalloc_reserved_flag = 0;
+ 		/*
+ 		 * Update reserved blocks/metadata blocks
+@@ -1269,7 +1269,7 @@ int ext4_get_block(struct inode *inode, sector_t iblock,
+ 	}
+ 
+ 	ret = ext4_get_blocks(handle, inode, iblock, max_blocks, bh_result,
+-			      create, 0, 0);
++			      create ? EXT4_GET_BLOCKS_CREATE : 0);
+ 	if (ret > 0) {
+ 		bh_result->b_size = (ret << inode->i_blkbits);
+ 		ret = 0;
+@@ -1288,16 +1288,19 @@ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
+ {
+ 	struct buffer_head dummy;
+ 	int fatal = 0, err;
++	int flags = EXT4_GET_BLOCKS_EXTEND_DISKSIZE;
+ 
+ 	J_ASSERT(handle != NULL || create == 0);
+ 
+ 	dummy.b_state = 0;
+ 	dummy.b_blocknr = -1000;
+ 	buffer_trace_init(&dummy.b_history);
+-	err = ext4_get_blocks(handle, inode, block, 1, &dummy, create, 1, 0);
++	if (create)
++		flags |= EXT4_GET_BLOCKS_CREATE;
++	err = ext4_get_blocks(handle, inode, block, 1, &dummy, flags);
+ 	/*
+-	 * ext4_get_blocks() returns number of blocks
+-	 * mapped. 0 in case of a HOLE.
++	 * ext4_get_blocks() returns number of blocks mapped. 0 in
++	 * case of a HOLE.
+ 	 */
+ 	if (err > 0) {
+ 		if (err > 1)
+@@ -1997,7 +2000,6 @@ static void ext4_print_free_blocks(struct inode *inode)
+ 	return;
+ }
+ 
+-#define		EXT4_DELALLOC_RSVED	1
+ static int ext4_da_get_block_write(struct inode *inode, sector_t iblock,
+ 				   struct buffer_head *bh_result)
+ {
+@@ -2009,7 +2011,8 @@ static int ext4_da_get_block_write(struct inode *inode, sector_t iblock,
+ 	handle = ext4_journal_current_handle();
+ 	BUG_ON(!handle);
+ 	ret = ext4_get_blocks(handle, inode, iblock, max_blocks,
+-			      bh_result, 1, 0, EXT4_DELALLOC_RSVED);
++			      bh_result, EXT4_GET_BLOCKS_CREATE|
++			      EXT4_GET_BLOCKS_DELALLOC_RESERVE);
+ 	if (ret <= 0)
+ 		return ret;
+ 
+@@ -2065,16 +2068,17 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
+ 		return 0;
+ 	/*
+ 	 * We need to make sure the BH_Delay flag is passed down to
+-	 * ext4_da_get_block_write(), since it calls
+-	 * ext4_get_blocks() with the EXT4_DELALLOC_RSVED flag.
+-	 * This flag causes ext4_get_blocks() to call
++	 * ext4_da_get_block_write(), since it calls ext4_get_blocks()
++	 * with the EXT4_GET_BLOCKS_DELALLOC_RESERVE flag.  This flag
++	 * causes ext4_get_blocks() to call
+ 	 * ext4_da_update_reserve_space() if the passed buffer head
+ 	 * has the BH_Delay flag set.  In the future, once we clean up
+-	 * the interfaces to ext4_get_blocks(), we should pass in
+-	 * a separate flag which requests that the delayed allocation
++	 * the interfaces to ext4_get_blocks(), we should pass in a
++	 * separate flag which requests that the delayed allocation
+ 	 * statistics should be updated, instead of depending on the
+ 	 * state information getting passed down via the map_bh's
+-	 * state bitmasks plus the magic EXT4_DELALLOC_RSVED flag.
++	 * state bitmasks plus the magic
++	 * EXT4_GET_BLOCKS_DELALLOC_RESERVE flag.
+ 	 */
+ 	new.b_state = mpd->b_state & (1 << BH_Delay);
+ 	new.b_blocknr = 0;
+@@ -2362,7 +2366,7 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock,
+ 	 * preallocated blocks are unmapped but should treated
+ 	 * the same as allocated blocks.
+ 	 */
+-	ret = ext4_get_blocks(NULL, inode, iblock, 1,  bh_result, 0, 0, 0);
++	ret = ext4_get_blocks(NULL, inode, iblock, 1,  bh_result, 0);
+ 	if ((ret == 0) && !buffer_delay(bh_result)) {
+ 		/* the block isn't (pre)allocated yet, let's reserve space */
+ 		/*
+@@ -2406,8 +2410,7 @@ static int ext4_normal_get_block_write(struct inode *inode, sector_t iblock,
+ 	 * we don't want to do block allocation in writepage
+ 	 * so call get_block_wrap with create = 0
+ 	 */
+-	ret = ext4_get_blocks(NULL, inode, iblock, max_blocks,
+-			      bh_result, 0, 0, 0);
++	ret = ext4_get_blocks(NULL, inode, iblock, max_blocks, bh_result, 0);
+ 	if (ret > 0) {
+ 		bh_result->b_size = (ret << inode->i_blkbits);
+ 		ret = 0;

commit 12b7ac176831df1aa58a787e67c3e5d698b30163
+Author: Theodore Ts'o 
+Date:   Thu May 14 00:57:44 2009 -0400
+
+    ext4: Rename ext4_get_blocks_wrap() to be ext4_get_blocks()
+    
+    Another function rename for clarity's sake.  The _wrap prefix simply
+    confuses people, and didn't add much people trying to follow the code
+    paths.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index b64789929a65..052d6378f997 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -131,8 +131,7 @@ static int ext4_readdir(struct file *filp,
+ 		struct buffer_head *bh = NULL;
+ 
+ 		map_bh.b_state = 0;
+-		err = ext4_get_blocks_wrap(NULL, inode, blk, 1, &map_bh,
+-						0, 0, 0);
++		err = ext4_get_blocks(NULL, inode, blk, 1, &map_bh, 0, 0, 0);
+ 		if (err > 0) {
+ 			pgoff_t index = map_bh.b_blocknr >>
+ 					(PAGE_CACHE_SHIFT - inode->i_blkbits);
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 89190ae671f6..5dc8368e46bc 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1617,10 +1617,10 @@ extern void ext4_ext_init(struct super_block *);
+ extern void ext4_ext_release(struct super_block *);
+ extern long ext4_fallocate(struct inode *inode, int mode, loff_t offset,
+ 			  loff_t len);
+-extern int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode,
+-			sector_t block, unsigned int max_blocks,
+-			struct buffer_head *bh, int create,
+-			int extend_disksize, int flag);
++extern int ext4_get_blocks(handle_t *handle, struct inode *inode,
++			   sector_t block, unsigned int max_blocks,
++			   struct buffer_head *bh, int create,
++			   int extend_disksize, int flag);
+ extern int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ 			__u64 start, __u64 len);
+ 
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 4fec6b746382..7e7d02dd2739 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -3151,9 +3151,9 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len)
+ 			break;
+ 		}
+ 		map_bh.b_state = 0;
+-		ret = ext4_get_blocks_wrap(handle, inode, block,
+-					  max_blocks, &map_bh,
+-					  EXT4_CREATE_UNINITIALIZED_EXT, 0, 0);
++		ret = ext4_get_blocks(handle, inode, block,
++				      max_blocks, &map_bh,
++				      EXT4_CREATE_UNINITIALIZED_EXT, 0, 0);
+ 		if (ret <= 0) {
+ #ifdef EXT4FS_DEBUG
+ 			WARN_ON(ret <= 0);
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index f758e8021d1a..a9a9b9b77e8e 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1121,7 +1121,7 @@ static void ext4_da_update_reserve_space(struct inode *inode, int used)
+ }
+ 
+ /*
+- * The ext4_get_blocks_wrap() function try to look up the requested blocks,
++ * The ext4_get_blocks() function tries to look up the requested blocks,
+  * and returns if the blocks are already mapped.
+  *
+  * Otherwise it takes the write lock of the i_data_sem and allocate blocks
+@@ -1142,9 +1142,9 @@ static void ext4_da_update_reserve_space(struct inode *inode, int used)
+  *
+  * It returns the error in case of allocation failure.
+  */
+-int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block,
+-			unsigned int max_blocks, struct buffer_head *bh,
+-			int create, int extend_disksize, int flag)
++int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block,
++		    unsigned int max_blocks, struct buffer_head *bh,
++		    int create, int extend_disksize, int flag)
+ {
+ 	int retval;
+ 
+@@ -1268,8 +1268,8 @@ int ext4_get_block(struct inode *inode, sector_t iblock,
+ 		started = 1;
+ 	}
+ 
+-	ret = ext4_get_blocks_wrap(handle, inode, iblock,
+-					max_blocks, bh_result, create, 0, 0);
++	ret = ext4_get_blocks(handle, inode, iblock, max_blocks, bh_result,
++			      create, 0, 0);
+ 	if (ret > 0) {
+ 		bh_result->b_size = (ret << inode->i_blkbits);
+ 		ret = 0;
+@@ -1294,10 +1294,9 @@ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
+ 	dummy.b_state = 0;
+ 	dummy.b_blocknr = -1000;
+ 	buffer_trace_init(&dummy.b_history);
+-	err = ext4_get_blocks_wrap(handle, inode, block, 1,
+-					&dummy, create, 1, 0);
++	err = ext4_get_blocks(handle, inode, block, 1, &dummy, create, 1, 0);
+ 	/*
+-	 * ext4_get_blocks_wrap() returns number of blocks
++	 * ext4_get_blocks() returns number of blocks
+ 	 * mapped. 0 in case of a HOLE.
+ 	 */
+ 	if (err > 0) {
+@@ -2009,8 +2008,8 @@ static int ext4_da_get_block_write(struct inode *inode, sector_t iblock,
+ 
+ 	handle = ext4_journal_current_handle();
+ 	BUG_ON(!handle);
+-	ret = ext4_get_blocks_wrap(handle, inode, iblock, max_blocks,
+-				   bh_result, 1, 0, EXT4_DELALLOC_RSVED);
++	ret = ext4_get_blocks(handle, inode, iblock, max_blocks,
++			      bh_result, 1, 0, EXT4_DELALLOC_RSVED);
+ 	if (ret <= 0)
+ 		return ret;
+ 
+@@ -2067,11 +2066,11 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
+ 	/*
+ 	 * We need to make sure the BH_Delay flag is passed down to
+ 	 * ext4_da_get_block_write(), since it calls
+-	 * ext4_get_blocks_wrap() with the EXT4_DELALLOC_RSVED flag.
+-	 * This flag causes ext4_get_blocks_wrap() to call
++	 * ext4_get_blocks() with the EXT4_DELALLOC_RSVED flag.
++	 * This flag causes ext4_get_blocks() to call
+ 	 * ext4_da_update_reserve_space() if the passed buffer head
+ 	 * has the BH_Delay flag set.  In the future, once we clean up
+-	 * the interfaces to ext4_get_blocks_wrap(), we should pass in
++	 * the interfaces to ext4_get_blocks(), we should pass in
+ 	 * a separate flag which requests that the delayed allocation
+ 	 * statistics should be updated, instead of depending on the
+ 	 * state information getting passed down via the map_bh's
+@@ -2363,7 +2362,7 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock,
+ 	 * preallocated blocks are unmapped but should treated
+ 	 * the same as allocated blocks.
+ 	 */
+-	ret = ext4_get_blocks_wrap(NULL, inode, iblock, 1,  bh_result, 0, 0, 0);
++	ret = ext4_get_blocks(NULL, inode, iblock, 1,  bh_result, 0, 0, 0);
+ 	if ((ret == 0) && !buffer_delay(bh_result)) {
+ 		/* the block isn't (pre)allocated yet, let's reserve space */
+ 		/*
+@@ -2407,8 +2406,8 @@ static int ext4_normal_get_block_write(struct inode *inode, sector_t iblock,
+ 	 * we don't want to do block allocation in writepage
+ 	 * so call get_block_wrap with create = 0
+ 	 */
+-	ret = ext4_get_blocks_wrap(NULL, inode, iblock, max_blocks,
+-				   bh_result, 0, 0, 0);
++	ret = ext4_get_blocks(NULL, inode, iblock, max_blocks,
++			      bh_result, 0, 0, 0);
+ 	if (ret > 0) {
+ 		bh_result->b_size = (ret << inode->i_blkbits);
+ 		ret = 0;
+@@ -5034,7 +5033,7 @@ int ext4_writepage_trans_blocks(struct inode *inode)
+  * Calculate the journal credits for a chunk of data modification.
+  *
+  * This is called from DIO, fallocate or whoever calling
+- * ext4_get_blocks_wrap() to map/allocate a chunk of contigous disk blocks.
++ * ext4_get_blocks() to map/allocate a chunk of contigous disk blocks.
+  *
+  * journal buffers for data blocks are not included here, as DIO
+  * and fallocate do no need to journal data buffers.

commit e4d996ca806e93dddb5d76c0d3d859b494c559f6
+Author: Theodore Ts'o 
+Date:   Tue May 12 00:25:28 2009 -0400
+
+    ext4: Rename ext4_get_blocks_handle() to be ext4_ind_get_blocks()
+    
+    The static function ext4_get_blocks_handle() is badly named.  Of
+    *course* it takes a handle.  Since its counterpart for extent-based
+    file is ext4_ext_get_blocks(), rename it to be ext4_ind_get_blocks().
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 476d843610ac..f758e8021d1a 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -914,7 +914,7 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
+  * down_read(&EXT4_I(inode)->i_data_sem) if not allocating file system block
+  * (ie, create is zero). Otherwise down_write(&EXT4_I(inode)->i_data_sem)
+  */
+-static int ext4_get_blocks_handle(handle_t *handle, struct inode *inode,
++static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode,
+ 				  ext4_lblk_t iblock, unsigned int maxblocks,
+ 				  struct buffer_head *bh_result,
+ 				  int create, int extend_disksize)
+@@ -1129,7 +1129,7 @@ static void ext4_da_update_reserve_space(struct inode *inode, int used)
+  * mapped.
+  *
+  * If file type is extents based, it will call ext4_ext_get_blocks(),
+- * Otherwise, call with ext4_get_blocks_handle() to handle indirect mapping
++ * Otherwise, call with ext4_ind_get_blocks() to handle indirect mapping
+  * based files
+  *
+  * On success, it returns the number of blocks being mapped or allocate.
+@@ -1160,8 +1160,8 @@ int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block,
+ 		retval =  ext4_ext_get_blocks(handle, inode, block, max_blocks,
+ 				bh, 0, 0);
+ 	} else {
+-		retval = ext4_get_blocks_handle(handle,
+-				inode, block, max_blocks, bh, 0, 0);
++		retval = ext4_ind_get_blocks(handle, inode, block, max_blocks,
++					     bh, 0, 0);
+ 	}
+ 	up_read((&EXT4_I(inode)->i_data_sem));
+ 
+@@ -1215,7 +1215,7 @@ int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block,
+ 		retval =  ext4_ext_get_blocks(handle, inode, block, max_blocks,
+ 				bh, create, extend_disksize);
+ 	} else {
+-		retval = ext4_get_blocks_handle(handle, inode, block,
++		retval = ext4_ind_get_blocks(handle, inode, block,
+ 				max_blocks, bh, create, extend_disksize);
+ 
+ 		if (retval > 0 && buffer_new(bh)) {
+@@ -1297,7 +1297,7 @@ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
+ 	err = ext4_get_blocks_wrap(handle, inode, block, 1,
+ 					&dummy, create, 1, 0);
+ 	/*
+-	 * ext4_get_blocks_handle() returns number of blocks
++	 * ext4_get_blocks_wrap() returns number of blocks
+ 	 * mapped. 0 in case of a HOLE.
+ 	 */
+ 	if (err > 0) {

commit f888e652d758bfe0c04c209b72a05972daeba386
+Author: Theodore Ts'o 
+Date:   Tue May 12 00:21:29 2009 -0400
+
+    ext4: Simplify function signature for ext4_da_get_block_write()
+    
+    The function ext4_da_get_block_write() is called in exactly one write,
+    and the last argument, create, is always 1.  Remove it to simplify the
+    code slightly.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 4e7f363e3030..476d843610ac 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2000,7 +2000,7 @@ static void ext4_print_free_blocks(struct inode *inode)
+ 
+ #define		EXT4_DELALLOC_RSVED	1
+ static int ext4_da_get_block_write(struct inode *inode, sector_t iblock,
+-				   struct buffer_head *bh_result, int create)
++				   struct buffer_head *bh_result)
+ {
+ 	int ret;
+ 	unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
+@@ -2010,7 +2010,7 @@ static int ext4_da_get_block_write(struct inode *inode, sector_t iblock,
+ 	handle = ext4_journal_current_handle();
+ 	BUG_ON(!handle);
+ 	ret = ext4_get_blocks_wrap(handle, inode, iblock, max_blocks,
+-				   bh_result, create, 0, EXT4_DELALLOC_RSVED);
++				   bh_result, 1, 0, EXT4_DELALLOC_RSVED);
+ 	if (ret <= 0)
+ 		return ret;
+ 
+@@ -2088,7 +2088,7 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
+ 	if (!new.b_size)
+ 		return 0;
+ 
+-	err = ext4_da_get_block_write(mpd->inode, next, &new, 1);
++	err = ext4_da_get_block_write(mpd->inode, next, &new);
+ 	if (err) {
+ 		/*
+ 		 * If get block returns with error we simply

commit eefd7f03b86b8a319890e7fac5a6fcc7f8694b76
+Author: Theodore Ts'o 
+Date:   Sat May 2 19:05:37 2009 -0400
+
+    ext4: fix the length returned by fiemap for an unallocated extent
+    
+    If the file's blocks have not yet been allocated because of delayed
+    allocation, the length of the extent returned by fiemap is incorrect.
+    This commit fixes this bug.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 5f7295287de1..4fec6b746382 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -3244,8 +3244,15 @@ static int ext4_ext_fiemap_cb(struct inode *inode, struct ext4_ext_path *path,
+ 	 * XXX this might miss a single-block extent at EXT_MAX_BLOCK
+ 	 */
+ 	if (ext4_ext_next_allocated_block(path) == EXT_MAX_BLOCK ||
+-	    newex->ec_block + newex->ec_len - 1 == EXT_MAX_BLOCK)
++	    newex->ec_block + newex->ec_len - 1 == EXT_MAX_BLOCK) {
++		loff_t size = i_size_read(inode);
++		loff_t bs = EXT4_BLOCK_SIZE(inode->i_sb);
++
+ 		flags |= FIEMAP_EXTENT_LAST;
++		if ((flags & FIEMAP_EXTENT_DELALLOC) &&
++		    logical+length > size)
++			length = (size - logical + bs - 1) & ~(bs-1);
++	}
+ 
+ 	error = fiemap_fill_next_extent(fieinfo, logical, physical,
+ 					length, flags);

commit bb23c20a851a5038b255a3c0d0aa56093c1da3f8
+Author: Theodore Ts'o 
+Date:   Fri May 1 19:44:44 2009 -0400
+
+    ext4: Move fs/ext4/group.h into ext4.h
+    
+    Move the function prototypes in group.h into ext4.h so they are all
+    defined in one place.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index a5ba039850c5..92f557d957d9 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -19,7 +19,6 @@
+ #include 
+ #include "ext4.h"
+ #include "ext4_jbd2.h"
+-#include "group.h"
+ #include "mballoc.h"
+ 
+ /*
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index d9c5251d082c..5973f3261b0c 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1270,6 +1270,14 @@ extern struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
+ 						    ext4_group_t block_group,
+ 						    struct buffer_head ** bh);
+ extern int ext4_should_retry_alloc(struct super_block *sb, int *retries);
++struct buffer_head *ext4_read_block_bitmap(struct super_block *sb,
++				      ext4_group_t block_group);
++extern unsigned ext4_init_block_bitmap(struct super_block *sb,
++				       struct buffer_head *bh,
++				       ext4_group_t group,
++				       struct ext4_group_desc *desc);
++#define ext4_free_blocks_after_init(sb, group, desc)			\
++		ext4_init_block_bitmap(sb, NULL, group, desc)
+ 
+ /* dir.c */
+ extern int ext4_check_dir_entry(const char *, struct inode *,
+@@ -1294,6 +1302,11 @@ extern struct inode * ext4_orphan_get(struct super_block *, unsigned long);
+ extern unsigned long ext4_count_free_inodes(struct super_block *);
+ extern unsigned long ext4_count_dirs(struct super_block *);
+ extern void ext4_check_inodes_bitmap(struct super_block *);
++extern unsigned ext4_init_inode_bitmap(struct super_block *sb,
++				       struct buffer_head *bh,
++				       ext4_group_t group,
++				       struct ext4_group_desc *desc);
++extern void mark_bitmap_end(int start_bit, int end_bit, char *bitmap);
+ 
+ /* mballoc.c */
+ extern long ext4_mb_stats;
+@@ -1417,6 +1430,10 @@ extern void ext4_used_dirs_set(struct super_block *sb,
+ 				struct ext4_group_desc *bg, __u32 count);
+ extern void ext4_itable_unused_set(struct super_block *sb,
+ 				   struct ext4_group_desc *bg, __u32 count);
++extern __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 group,
++				   struct ext4_group_desc *gdp);
++extern int ext4_group_desc_csum_verify(struct ext4_sb_info *sbi, __u32 group,
++				       struct ext4_group_desc *gdp);
+ 
+ static inline ext4_fsblk_t ext4_blocks_count(struct ext4_super_block *es)
+ {
+diff --git a/fs/ext4/group.h b/fs/ext4/group.h
+deleted file mode 100644
+index c2c0a8d06d0e..000000000000
+--- a/fs/ext4/group.h
++++ /dev/null
+@@ -1,29 +0,0 @@
+-/*
+- *  linux/fs/ext4/group.h
+- *
+- * Copyright (C) 2007 Cluster File Systems, Inc
+- *
+- * Author: Andreas Dilger 
+- */
+-
+-#ifndef _LINUX_EXT4_GROUP_H
+-#define _LINUX_EXT4_GROUP_H
+-
+-extern __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 group,
+-				   struct ext4_group_desc *gdp);
+-extern int ext4_group_desc_csum_verify(struct ext4_sb_info *sbi, __u32 group,
+-				       struct ext4_group_desc *gdp);
+-struct buffer_head *ext4_read_block_bitmap(struct super_block *sb,
+-				      ext4_group_t block_group);
+-extern unsigned ext4_init_block_bitmap(struct super_block *sb,
+-				       struct buffer_head *bh,
+-				       ext4_group_t group,
+-				       struct ext4_group_desc *desc);
+-#define ext4_free_blocks_after_init(sb, group, desc)			\
+-		ext4_init_block_bitmap(sb, NULL, group, desc)
+-extern unsigned ext4_init_inode_bitmap(struct super_block *sb,
+-				       struct buffer_head *bh,
+-				       ext4_group_t group,
+-				       struct ext4_group_desc *desc);
+-extern void mark_bitmap_end(int start_bit, int end_bit, char *bitmap);
+-#endif /* _LINUX_EXT4_GROUP_H */
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 55ba419ca00b..916d05c881ca 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -27,7 +27,6 @@
+ #include "ext4_jbd2.h"
+ #include "xattr.h"
+ #include "acl.h"
+-#include "group.h"
+ 
+ /*
+  * ialloc.c contains the inodes allocation and deallocation routines
+diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
+index dd9e6cd5f6cf..75e34f69215b 100644
+--- a/fs/ext4/mballoc.h
++++ b/fs/ext4/mballoc.h
+@@ -23,7 +23,6 @@
+ #include 
+ #include "ext4_jbd2.h"
+ #include "ext4.h"
+-#include "group.h"
+ 
+ /*
+  * with AGGRESSIVE_CHECK allocator runs consistency checks over
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index e8ded13b5cb1..27eb289eea37 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -15,7 +15,6 @@
+ #include 
+ 
+ #include "ext4_jbd2.h"
+-#include "group.h"
+ 
+ #define outside(b, first, last)	((b) < (first) || (b) >= (last))
+ #define inside(b, first, last)	((b) >= (first) && (b) < (last))
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index d79e1c428b4a..7903f20c8075 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -46,7 +46,6 @@
+ #include "ext4_jbd2.h"
+ #include "xattr.h"
+ #include "acl.h"
+-#include "group.h"
+ 
+ struct proc_dir_entry *ext4_proc_root;
+ static struct kset *ext4_kset;

commit 596397b77c895d0fa3674f579c94ad5ea88ef01d
+Author: Theodore Ts'o 
+Date:   Fri May 1 13:49:15 2009 -0400
+
+    ext4: Move fs/ext4/namei.h into ext4.h
+    
+    The fs/ext4/namei.h header file had only a single function
+    declaration, and should have never been a standalone file.  Move it
+    into ext4.h, where should have been from the beginning.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index af3c906e705b..d9c5251d082c 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1594,6 +1594,7 @@ extern const struct file_operations ext4_file_operations;
+ /* namei.c */
+ extern const struct inode_operations ext4_dir_inode_operations;
+ extern const struct inode_operations ext4_special_inode_operations;
++extern struct dentry *ext4_get_parent(struct dentry *child);
+ 
+ /* symlink.c */
+ extern const struct inode_operations ext4_symlink_inode_operations;
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 8018e49a7287..c9690b250e5e 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -37,7 +37,6 @@
+ #include "ext4.h"
+ #include "ext4_jbd2.h"
+ 
+-#include "namei.h"
+ #include "xattr.h"
+ #include "acl.h"
+ 
+diff --git a/fs/ext4/namei.h b/fs/ext4/namei.h
+deleted file mode 100644
+index 5e4dfff36a00..000000000000
+--- a/fs/ext4/namei.h
++++ /dev/null
+@@ -1,8 +0,0 @@
+-/*  linux/fs/ext4/namei.h
+- *
+- * Copyright (C) 2005 Simtec Electronics
+- *	Ben Dooks 
+- *
+-*/
+-
+-extern struct dentry *ext4_get_parent(struct dentry *child);
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 1fbf0906ae2e..d79e1c428b4a 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -46,7 +46,6 @@
+ #include "ext4_jbd2.h"
+ #include "xattr.h"
+ #include "acl.h"
+-#include "namei.h"
+ #include "group.h"
+ 
+ struct proc_dir_entry *ext4_proc_root;

commit ca0faba0e8ac844dc0279825eb8db876b5962ea5
+Author: Theodore Ts'o 
+Date:   Sun May 3 16:33:44 2009 -0400
+
+    ext4: Move the ext4_sb.h header file into ext4.h
+    
+    There is no longer a reason for a separate ext4_sb.h header file, so
+    move it into ext4.h just to make life easier for developers to find
+    the relevant data structures and typedefs.  Should also speed up
+    compiles slightly, too.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index ba57d669cb65..af3c906e705b 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -25,6 +25,10 @@
+ #include 
+ #include 
+ #include 
++#include 
++#include 
++#include 
++#include 
+ 
+ /*
+  * The fourth extended filesystem constants/structures
+@@ -195,9 +199,6 @@ struct flex_groups {
+ #define EXT4_BG_BLOCK_UNINIT	0x0002 /* Block bitmap not in use */
+ #define EXT4_BG_INODE_ZEROED	0x0004 /* On-disk itable initialized to zero */
+ 
+-#ifdef __KERNEL__
+-#include "ext4_sb.h"
+-#endif
+ /*
+  * Macro-instructions used to manage group descriptors
+  */
+@@ -809,6 +810,136 @@ struct ext4_super_block {
+ };
+ 
+ #ifdef __KERNEL__
++/*
++ * fourth extended-fs super-block data in memory
++ */
++struct ext4_sb_info {
++	unsigned long s_desc_size;	/* Size of a group descriptor in bytes */
++	unsigned long s_inodes_per_block;/* Number of inodes per block */
++	unsigned long s_blocks_per_group;/* Number of blocks in a group */
++	unsigned long s_inodes_per_group;/* Number of inodes in a group */
++	unsigned long s_itb_per_group;	/* Number of inode table blocks per group */
++	unsigned long s_gdb_count;	/* Number of group descriptor blocks */
++	unsigned long s_desc_per_block;	/* Number of group descriptors per block */
++	ext4_group_t s_groups_count;	/* Number of groups in the fs */
++	unsigned long s_overhead_last;  /* Last calculated overhead */
++	unsigned long s_blocks_last;    /* Last seen block count */
++	loff_t s_bitmap_maxbytes;	/* max bytes for bitmap files */
++	struct buffer_head * s_sbh;	/* Buffer containing the super block */
++	struct ext4_super_block *s_es;	/* Pointer to the super block in the buffer */
++	struct buffer_head **s_group_desc;
++	unsigned long  s_mount_opt;
++	ext4_fsblk_t s_sb_block;
++	uid_t s_resuid;
++	gid_t s_resgid;
++	unsigned short s_mount_state;
++	unsigned short s_pad;
++	int s_addr_per_block_bits;
++	int s_desc_per_block_bits;
++	int s_inode_size;
++	int s_first_ino;
++	unsigned int s_inode_readahead_blks;
++	spinlock_t s_next_gen_lock;
++	u32 s_next_generation;
++	u32 s_hash_seed[4];
++	int s_def_hash_version;
++	int s_hash_unsigned;	/* 3 if hash should be signed, 0 if not */
++	struct percpu_counter s_freeblocks_counter;
++	struct percpu_counter s_freeinodes_counter;
++	struct percpu_counter s_dirs_counter;
++	struct percpu_counter s_dirtyblocks_counter;
++	struct blockgroup_lock *s_blockgroup_lock;
++	struct proc_dir_entry *s_proc;
++	struct kobject s_kobj;
++	struct completion s_kobj_unregister;
++
++	/* Journaling */
++	struct inode *s_journal_inode;
++	struct journal_s *s_journal;
++	struct list_head s_orphan;
++	struct mutex s_orphan_lock;
++	struct mutex s_resize_lock;
++	unsigned long s_commit_interval;
++	u32 s_max_batch_time;
++	u32 s_min_batch_time;
++	struct block_device *journal_bdev;
++#ifdef CONFIG_JBD2_DEBUG
++	struct timer_list turn_ro_timer;	/* For turning read-only (crash simulation) */
++	wait_queue_head_t ro_wait_queue;	/* For people waiting for the fs to go read-only */
++#endif
++#ifdef CONFIG_QUOTA
++	char *s_qf_names[MAXQUOTAS];		/* Names of quota files with journalled quota */
++	int s_jquota_fmt;			/* Format of quota to use */
++#endif
++	unsigned int s_want_extra_isize; /* New inodes should reserve # bytes */
++
++#ifdef EXTENTS_STATS
++	/* ext4 extents stats */
++	unsigned long s_ext_min;
++	unsigned long s_ext_max;
++	unsigned long s_depth_max;
++	spinlock_t s_ext_stats_lock;
++	unsigned long s_ext_blocks;
++	unsigned long s_ext_extents;
++#endif
++
++	/* for buddy allocator */
++	struct ext4_group_info ***s_group_info;
++	struct inode *s_buddy_cache;
++	long s_blocks_reserved;
++	spinlock_t s_reserve_lock;
++	spinlock_t s_md_lock;
++	tid_t s_last_transaction;
++	unsigned short *s_mb_offsets;
++	unsigned int *s_mb_maxs;
++
++	/* tunables */
++	unsigned long s_stripe;
++	unsigned int s_mb_stream_request;
++	unsigned int s_mb_max_to_scan;
++	unsigned int s_mb_min_to_scan;
++	unsigned int s_mb_stats;
++	unsigned int s_mb_order2_reqs;
++	unsigned int s_mb_group_prealloc;
++	/* where last allocation was done - for stream allocation */
++	unsigned long s_mb_last_group;
++	unsigned long s_mb_last_start;
++
++	/* history to debug policy */
++	struct ext4_mb_history *s_mb_history;
++	int s_mb_history_cur;
++	int s_mb_history_max;
++	int s_mb_history_num;
++	spinlock_t s_mb_history_lock;
++	int s_mb_history_filter;
++
++	/* stats for buddy allocator */
++	spinlock_t s_mb_pa_lock;
++	atomic_t s_bal_reqs;	/* number of reqs with len > 1 */
++	atomic_t s_bal_success;	/* we found long enough chunks */
++	atomic_t s_bal_allocated;	/* in blocks */
++	atomic_t s_bal_ex_scanned;	/* total extents scanned */
++	atomic_t s_bal_goals;	/* goal hits */
++	atomic_t s_bal_breaks;	/* too long searches */
++	atomic_t s_bal_2orders;	/* 2^order hits */
++	spinlock_t s_bal_lock;
++	unsigned long s_mb_buddies_generated;
++	unsigned long long s_mb_generation_time;
++	atomic_t s_mb_lost_chunks;
++	atomic_t s_mb_preallocated;
++	atomic_t s_mb_discarded;
++
++	/* locality groups */
++	struct ext4_locality_group *s_locality_groups;
++
++	/* for write statistics */
++	unsigned long s_sectors_written_start;
++	u64 s_kbytes_written;
++
++	unsigned int s_log_groups_per_flex;
++	struct flex_groups *s_flex_groups;
++};
++
+ static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb)
+ {
+ 	return sb->s_fs_info;
+@@ -824,7 +955,6 @@ static inline struct timespec ext4_current_time(struct inode *inode)
+ 		current_fs_time(inode->i_sb) : CURRENT_TIME_SEC;
+ }
+ 
+-
+ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
+ {
+ 	return ino == EXT4_ROOT_INO ||
+@@ -833,6 +963,12 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
+ 		(ino >= EXT4_FIRST_INO(sb) &&
+ 		 ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count));
+ }
++
++static inline spinlock_t *
++sb_bgl_lock(struct ext4_sb_info *sbi, unsigned int block_group)
++{
++	return bgl_lock_ptr(sbi->s_blockgroup_lock, block_group);
++}
+ #else
+ /* Assume that user mode programs are passing in an ext4fs superblock, not
+  * a kernel struct super_block.  This will allow us to call the feature-test
+diff --git a/fs/ext4/ext4_sb.h b/fs/ext4/ext4_sb.h
+deleted file mode 100644
+index 2d36223d5f57..000000000000
+--- a/fs/ext4/ext4_sb.h
++++ /dev/null
+@@ -1,163 +0,0 @@
+-/*
+- *  ext4_sb.h
+- *
+- * Copyright (C) 1992, 1993, 1994, 1995
+- * Remy Card (card@masi.ibp.fr)
+- * Laboratoire MASI - Institut Blaise Pascal
+- * Universite Pierre et Marie Curie (Paris VI)
+- *
+- *  from
+- *
+- *  linux/include/linux/minix_fs_sb.h
+- *
+- *  Copyright (C) 1991, 1992  Linus Torvalds
+- */
+-
+-#ifndef _EXT4_SB
+-#define _EXT4_SB
+-
+-#ifdef __KERNEL__
+-#include 
+-#include 
+-#include 
+-#include 
+-#endif
+-#include 
+-
+-/*
+- * fourth extended-fs super-block data in memory
+- */
+-struct ext4_sb_info {
+-	unsigned long s_desc_size;	/* Size of a group descriptor in bytes */
+-	unsigned long s_inodes_per_block;/* Number of inodes per block */
+-	unsigned long s_blocks_per_group;/* Number of blocks in a group */
+-	unsigned long s_inodes_per_group;/* Number of inodes in a group */
+-	unsigned long s_itb_per_group;	/* Number of inode table blocks per group */
+-	unsigned long s_gdb_count;	/* Number of group descriptor blocks */
+-	unsigned long s_desc_per_block;	/* Number of group descriptors per block */
+-	ext4_group_t s_groups_count;	/* Number of groups in the fs */
+-	unsigned long s_overhead_last;  /* Last calculated overhead */
+-	unsigned long s_blocks_last;    /* Last seen block count */
+-	loff_t s_bitmap_maxbytes;	/* max bytes for bitmap files */
+-	struct buffer_head * s_sbh;	/* Buffer containing the super block */
+-	struct ext4_super_block *s_es;	/* Pointer to the super block in the buffer */
+-	struct buffer_head **s_group_desc;
+-	unsigned long  s_mount_opt;
+-	ext4_fsblk_t s_sb_block;
+-	uid_t s_resuid;
+-	gid_t s_resgid;
+-	unsigned short s_mount_state;
+-	unsigned short s_pad;
+-	int s_addr_per_block_bits;
+-	int s_desc_per_block_bits;
+-	int s_inode_size;
+-	int s_first_ino;
+-	unsigned int s_inode_readahead_blks;
+-	spinlock_t s_next_gen_lock;
+-	u32 s_next_generation;
+-	u32 s_hash_seed[4];
+-	int s_def_hash_version;
+-	int s_hash_unsigned;	/* 3 if hash should be signed, 0 if not */
+-	struct percpu_counter s_freeblocks_counter;
+-	struct percpu_counter s_freeinodes_counter;
+-	struct percpu_counter s_dirs_counter;
+-	struct percpu_counter s_dirtyblocks_counter;
+-	struct blockgroup_lock *s_blockgroup_lock;
+-	struct proc_dir_entry *s_proc;
+-	struct kobject s_kobj;
+-	struct completion s_kobj_unregister;
+-
+-	/* Journaling */
+-	struct inode *s_journal_inode;
+-	struct journal_s *s_journal;
+-	struct list_head s_orphan;
+-	struct mutex s_orphan_lock;
+-	struct mutex s_resize_lock;
+-	unsigned long s_commit_interval;
+-	u32 s_max_batch_time;
+-	u32 s_min_batch_time;
+-	struct block_device *journal_bdev;
+-#ifdef CONFIG_JBD2_DEBUG
+-	struct timer_list turn_ro_timer;	/* For turning read-only (crash simulation) */
+-	wait_queue_head_t ro_wait_queue;	/* For people waiting for the fs to go read-only */
+-#endif
+-#ifdef CONFIG_QUOTA
+-	char *s_qf_names[MAXQUOTAS];		/* Names of quota files with journalled quota */
+-	int s_jquota_fmt;			/* Format of quota to use */
+-#endif
+-	unsigned int s_want_extra_isize; /* New inodes should reserve # bytes */
+-
+-#ifdef EXTENTS_STATS
+-	/* ext4 extents stats */
+-	unsigned long s_ext_min;
+-	unsigned long s_ext_max;
+-	unsigned long s_depth_max;
+-	spinlock_t s_ext_stats_lock;
+-	unsigned long s_ext_blocks;
+-	unsigned long s_ext_extents;
+-#endif
+-
+-	/* for buddy allocator */
+-	struct ext4_group_info ***s_group_info;
+-	struct inode *s_buddy_cache;
+-	long s_blocks_reserved;
+-	spinlock_t s_reserve_lock;
+-	spinlock_t s_md_lock;
+-	tid_t s_last_transaction;
+-	unsigned short *s_mb_offsets;
+-	unsigned int *s_mb_maxs;
+-
+-	/* tunables */
+-	unsigned long s_stripe;
+-	unsigned int s_mb_stream_request;
+-	unsigned int s_mb_max_to_scan;
+-	unsigned int s_mb_min_to_scan;
+-	unsigned int s_mb_stats;
+-	unsigned int s_mb_order2_reqs;
+-	unsigned int s_mb_group_prealloc;
+-	/* where last allocation was done - for stream allocation */
+-	unsigned long s_mb_last_group;
+-	unsigned long s_mb_last_start;
+-
+-	/* history to debug policy */
+-	struct ext4_mb_history *s_mb_history;
+-	int s_mb_history_cur;
+-	int s_mb_history_max;
+-	int s_mb_history_num;
+-	spinlock_t s_mb_history_lock;
+-	int s_mb_history_filter;
+-
+-	/* stats for buddy allocator */
+-	spinlock_t s_mb_pa_lock;
+-	atomic_t s_bal_reqs;	/* number of reqs with len > 1 */
+-	atomic_t s_bal_success;	/* we found long enough chunks */
+-	atomic_t s_bal_allocated;	/* in blocks */
+-	atomic_t s_bal_ex_scanned;	/* total extents scanned */
+-	atomic_t s_bal_goals;	/* goal hits */
+-	atomic_t s_bal_breaks;	/* too long searches */
+-	atomic_t s_bal_2orders;	/* 2^order hits */
+-	spinlock_t s_bal_lock;
+-	unsigned long s_mb_buddies_generated;
+-	unsigned long long s_mb_generation_time;
+-	atomic_t s_mb_lost_chunks;
+-	atomic_t s_mb_preallocated;
+-	atomic_t s_mb_discarded;
+-
+-	/* locality groups */
+-	struct ext4_locality_group *s_locality_groups;
+-
+-	/* for write statistics */
+-	unsigned long s_sectors_written_start;
+-	u64 s_kbytes_written;
+-
+-	unsigned int s_log_groups_per_flex;
+-	struct flex_groups *s_flex_groups;
+-};
+-
+-static inline spinlock_t *
+-sb_bgl_lock(struct ext4_sb_info *sbi, unsigned int block_group)
+-{
+-	return bgl_lock_ptr(sbi->s_blockgroup_lock, block_group);
+-}
+-
+-#endif	/* _EXT4_SB */

commit d444c3c38189b3f18337a213855ac1c07af4e2d9
+Author: Theodore Ts'o 
+Date:   Fri May 1 13:44:33 2009 -0400
+
+    ext4: Move the ext4_i.h header file into ext4.h
+    
+    There is no longer a reason for a separate ext4_i.h header file, so
+    move it into ext4.h just to make life easier for developers to find
+    the relevant data structures and typedefs.  Should also speed up
+    compiles slightly, too.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 02ec44bf38e6..ba57d669cb65 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -21,7 +21,10 @@
+ #include 
+ #include 
+ #include 
+-#include "ext4_i.h"
++#include 
++#include 
++#include 
++#include 
+ 
+ /*
+  * The fourth extended filesystem constants/structures
+@@ -46,6 +49,19 @@
+ #define ext4_debug(f, a...)	do {} while (0)
+ #endif
+ 
++/* data type for block offset of block group */
++typedef int ext4_grpblk_t;
++
++/* data type for filesystem-wide blocks number */
++typedef unsigned long long ext4_fsblk_t;
++
++/* data type for file logical block number */
++typedef __u32 ext4_lblk_t;
++
++/* data type for block group number */
++typedef unsigned int ext4_group_t;
++
++
+ /* prefer goal again. length */
+ #define EXT4_MB_HINT_MERGE		1
+ /* blocks already reserved */
+@@ -515,6 +531,110 @@ do {									       \
+ 
+ #endif /* defined(__KERNEL__) || defined(__linux__) */
+ 
++/*
++ * storage for cached extent
++ */
++struct ext4_ext_cache {
++	ext4_fsblk_t	ec_start;
++	ext4_lblk_t	ec_block;
++	__u32		ec_len; /* must be 32bit to return holes */
++	__u32		ec_type;
++};
++
++/*
++ * fourth extended file system inode data in memory
++ */
++struct ext4_inode_info {
++	__le32	i_data[15];	/* unconverted */
++	__u32	i_flags;
++	ext4_fsblk_t	i_file_acl;
++	__u32	i_dtime;
++
++	/*
++	 * i_block_group is the number of the block group which contains
++	 * this file's inode.  Constant across the lifetime of the inode,
++	 * it is ued for making block allocation decisions - we try to
++	 * place a file's data blocks near its inode block, and new inodes
++	 * near to their parent directory's inode.
++	 */
++	ext4_group_t	i_block_group;
++	__u32	i_state;		/* Dynamic state flags for ext4 */
++
++	ext4_lblk_t		i_dir_start_lookup;
++#ifdef CONFIG_EXT4_FS_XATTR
++	/*
++	 * Extended attributes can be read independently of the main file
++	 * data. Taking i_mutex even when reading would cause contention
++	 * between readers of EAs and writers of regular file data, so
++	 * instead we synchronize on xattr_sem when reading or changing
++	 * EAs.
++	 */
++	struct rw_semaphore xattr_sem;
++#endif
++#ifdef CONFIG_EXT4_FS_POSIX_ACL
++	struct posix_acl	*i_acl;
++	struct posix_acl	*i_default_acl;
++#endif
++
++	struct list_head i_orphan;	/* unlinked but open inodes */
++
++	/*
++	 * i_disksize keeps track of what the inode size is ON DISK, not
++	 * in memory.  During truncate, i_size is set to the new size by
++	 * the VFS prior to calling ext4_truncate(), but the filesystem won't
++	 * set i_disksize to 0 until the truncate is actually under way.
++	 *
++	 * The intent is that i_disksize always represents the blocks which
++	 * are used by this file.  This allows recovery to restart truncate
++	 * on orphans if we crash during truncate.  We actually write i_disksize
++	 * into the on-disk inode when writing inodes out, instead of i_size.
++	 *
++	 * The only time when i_disksize and i_size may be different is when
++	 * a truncate is in progress.  The only things which change i_disksize
++	 * are ext4_get_block (growth) and ext4_truncate (shrinkth).
++	 */
++	loff_t	i_disksize;
++
++	/*
++	 * i_data_sem is for serialising ext4_truncate() against
++	 * ext4_getblock().  In the 2.4 ext2 design, great chunks of inode's
++	 * data tree are chopped off during truncate. We can't do that in
++	 * ext4 because whenever we perform intermediate commits during
++	 * truncate, the inode and all the metadata blocks *must* be in a
++	 * consistent state which allows truncation of the orphans to restart
++	 * during recovery.  Hence we must fix the get_block-vs-truncate race
++	 * by other means, so we have i_data_sem.
++	 */
++	struct rw_semaphore i_data_sem;
++	struct inode vfs_inode;
++	struct jbd2_inode jinode;
++
++	struct ext4_ext_cache i_cached_extent;
++	/*
++	 * File creation time. Its function is same as that of
++	 * struct timespec i_{a,c,m}time in the generic inode.
++	 */
++	struct timespec i_crtime;
++
++	/* mballoc */
++	struct list_head i_prealloc_list;
++	spinlock_t i_prealloc_lock;
++
++	/* ialloc */
++	ext4_group_t	i_last_alloc_group;
++
++	/* allocation reservation info for delalloc */
++	unsigned int i_reserved_data_blocks;
++	unsigned int i_reserved_meta_blocks;
++	unsigned int i_allocated_meta_blocks;
++	unsigned short i_delalloc_reserved_flag;
++
++	/* on-disk additional length */
++	__u16 i_extra_isize;
++
++	spinlock_t i_block_reservation_lock;
++};
++
+ /*
+  * File system states
+  */
+diff --git a/fs/ext4/ext4_i.h b/fs/ext4/ext4_i.h
+deleted file mode 100644
+index 4ce2187123aa..000000000000
+--- a/fs/ext4/ext4_i.h
++++ /dev/null
+@@ -1,140 +0,0 @@
+-/*
+- *  ext4_i.h
+- *
+- * Copyright (C) 1992, 1993, 1994, 1995
+- * Remy Card (card@masi.ibp.fr)
+- * Laboratoire MASI - Institut Blaise Pascal
+- * Universite Pierre et Marie Curie (Paris VI)
+- *
+- *  from
+- *
+- *  linux/include/linux/minix_fs_i.h
+- *
+- *  Copyright (C) 1991, 1992  Linus Torvalds
+- */
+-
+-#ifndef _EXT4_I
+-#define _EXT4_I
+-
+-#include 
+-#include 
+-#include 
+-#include 
+-
+-/* data type for block offset of block group */
+-typedef int ext4_grpblk_t;
+-
+-/* data type for filesystem-wide blocks number */
+-typedef unsigned long long ext4_fsblk_t;
+-
+-/* data type for file logical block number */
+-typedef __u32 ext4_lblk_t;
+-
+-/* data type for block group number */
+-typedef unsigned int ext4_group_t;
+-
+-/*
+- * storage for cached extent
+- */
+-struct ext4_ext_cache {
+-	ext4_fsblk_t	ec_start;
+-	ext4_lblk_t	ec_block;
+-	__u32		ec_len; /* must be 32bit to return holes */
+-	__u32		ec_type;
+-};
+-
+-/*
+- * fourth extended file system inode data in memory
+- */
+-struct ext4_inode_info {
+-	__le32	i_data[15];	/* unconverted */
+-	__u32	i_flags;
+-	ext4_fsblk_t	i_file_acl;
+-	__u32	i_dtime;
+-
+-	/*
+-	 * i_block_group is the number of the block group which contains
+-	 * this file's inode.  Constant across the lifetime of the inode,
+-	 * it is ued for making block allocation decisions - we try to
+-	 * place a file's data blocks near its inode block, and new inodes
+-	 * near to their parent directory's inode.
+-	 */
+-	ext4_group_t	i_block_group;
+-	__u32	i_state;		/* Dynamic state flags for ext4 */
+-
+-	ext4_lblk_t		i_dir_start_lookup;
+-#ifdef CONFIG_EXT4_FS_XATTR
+-	/*
+-	 * Extended attributes can be read independently of the main file
+-	 * data. Taking i_mutex even when reading would cause contention
+-	 * between readers of EAs and writers of regular file data, so
+-	 * instead we synchronize on xattr_sem when reading or changing
+-	 * EAs.
+-	 */
+-	struct rw_semaphore xattr_sem;
+-#endif
+-#ifdef CONFIG_EXT4_FS_POSIX_ACL
+-	struct posix_acl	*i_acl;
+-	struct posix_acl	*i_default_acl;
+-#endif
+-
+-	struct list_head i_orphan;	/* unlinked but open inodes */
+-
+-	/*
+-	 * i_disksize keeps track of what the inode size is ON DISK, not
+-	 * in memory.  During truncate, i_size is set to the new size by
+-	 * the VFS prior to calling ext4_truncate(), but the filesystem won't
+-	 * set i_disksize to 0 until the truncate is actually under way.
+-	 *
+-	 * The intent is that i_disksize always represents the blocks which
+-	 * are used by this file.  This allows recovery to restart truncate
+-	 * on orphans if we crash during truncate.  We actually write i_disksize
+-	 * into the on-disk inode when writing inodes out, instead of i_size.
+-	 *
+-	 * The only time when i_disksize and i_size may be different is when
+-	 * a truncate is in progress.  The only things which change i_disksize
+-	 * are ext4_get_block (growth) and ext4_truncate (shrinkth).
+-	 */
+-	loff_t	i_disksize;
+-
+-	/*
+-	 * i_data_sem is for serialising ext4_truncate() against
+-	 * ext4_getblock().  In the 2.4 ext2 design, great chunks of inode's
+-	 * data tree are chopped off during truncate. We can't do that in
+-	 * ext4 because whenever we perform intermediate commits during
+-	 * truncate, the inode and all the metadata blocks *must* be in a
+-	 * consistent state which allows truncation of the orphans to restart
+-	 * during recovery.  Hence we must fix the get_block-vs-truncate race
+-	 * by other means, so we have i_data_sem.
+-	 */
+-	struct rw_semaphore i_data_sem;
+-	struct inode vfs_inode;
+-	struct jbd2_inode jinode;
+-
+-	struct ext4_ext_cache i_cached_extent;
+-	/*
+-	 * File creation time. Its function is same as that of
+-	 * struct timespec i_{a,c,m}time in the generic inode.
+-	 */
+-	struct timespec i_crtime;
+-
+-	/* mballoc */
+-	struct list_head i_prealloc_list;
+-	spinlock_t i_prealloc_lock;
+-
+-	/* ialloc */
+-	ext4_group_t	i_last_alloc_group;
+-
+-	/* allocation reservation info for delalloc */
+-	unsigned int i_reserved_data_blocks;
+-	unsigned int i_reserved_meta_blocks;
+-	unsigned int i_allocated_meta_blocks;
+-	unsigned short i_delalloc_reserved_flag;
+-
+-	/* on-disk additional length */
+-	__u16 i_extra_isize;
+-
+-	spinlock_t i_block_reservation_lock;
+-};
+-
+-#endif	/* _EXT4_I */

commit 75507efb1372b6acf1aa6bf00ebd49ce196fd994
+Author: Theodore Ts'o 
+Date:   Fri May 1 12:58:36 2009 -0400
+
+    ext4: Don't avoid using BLOCK_UNINIT block groups in mballoc
+    
+    By avoiding the use of not-yet-used block groups (i.e., block groups
+    with the BLOCK_UNINIT flag), mballoc had a tendency to create large
+    files with large non-contiguous gaps.  In addition avoiding the use of
+    new block groups had a tendency to push regular file data into the
+    first block group in a flex_bg group, which slows down the speed of
+    e2fsck pass 2, since it has a tendency to seek much more.  For
+    example:
+    
+                   Before Patch                       After Patch
+                  Time in seconds                   Time in seconds
+                Real /  User/  Sys   MB/s      Real /  User/  Sys    MB/s
+    Pass 1      8.52 / 2.21 / 0.46  20.43      8.84 / 4.97 / 1.11   19.68
+    Pass 2     21.16 / 1.02 / 1.86  11.30      6.54 / 1.77 / 1.78   36.39
+    Pass 3      0.01 / 0.00 / 0.00 139.00      0.01 / 0.01 / 0.00  128.90
+    Pass 4      0.16 / 0.15 / 0.00   0.00      0.17 / 0.17 / 0.00    0.00
+    Pass 5      2.52 / 1.99 / 0.09   0.79      2.31 / 1.78 / 0.06    0.86
+    Total      32.40 / 5.11 / 2.49  12.81     17.99 / 8.75 / 2.98   23.01
+    
+    This was on a sample 80 gig root filesystem which was approximately
+    50% full.  Note the improved e2fsck pass 2 performance, by over a
+    factor of 3, due to a decreased number of seeks.  (The total amount of
+    I/O in pass 2 was unchanged; the layout of the directory blocks was
+    simply much better from e2fsck's's perspective.)
+    
+    Other changes as a result of this patch on this sample filesystem:
+    
+                                 Before Patch    After Patch
+    # of non-contig files           762             779
+    # of non-contig directories     571             570
+    # of BLOCK_UNINIT bg's          307             293
+    # of INODE_UNINIT bg's          503             503
+    
+    Out of 640 block groups, of which 333 were in use, this patch caused
+    an extra 14 block groups to be utilized.  The number of non-contiguous
+    files did go up slightly, but when measured against the 99.9% of the
+    files (603,154) which were contiguously allocated, this is pretty
+    insignificant.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Andreas Dilger 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index c3af9e6b6668..dbd47eac13ec 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -1728,7 +1728,6 @@ static int ext4_mb_good_group(struct ext4_allocation_context *ac,
+ 	unsigned free, fragments;
+ 	unsigned i, bits;
+ 	int flex_size = ext4_flex_bg_size(EXT4_SB(ac->ac_sb));
+-	struct ext4_group_desc *desc;
+ 	struct ext4_group_info *grp = ext4_get_group_info(ac->ac_sb, group);
+ 
+ 	BUG_ON(cr < 0 || cr >= 4);
+@@ -1744,10 +1743,6 @@ static int ext4_mb_good_group(struct ext4_allocation_context *ac,
+ 	switch (cr) {
+ 	case 0:
+ 		BUG_ON(ac->ac_2order == 0);
+-		/* If this group is uninitialized, skip it initially */
+-		desc = ext4_get_group_desc(ac->ac_sb, group, NULL);
+-		if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))
+-			return 0;
+ 
+ 		/* Avoid using the first bg of a flexgroup for data files */
+ 		if ((ac->ac_flags & EXT4_MB_HINT_DATA) &&
+@@ -2067,9 +2062,7 @@ ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
+ 
+ 			ac->ac_groups_scanned++;
+ 			desc = ext4_get_group_desc(sb, group, NULL);
+-			if (cr == 0 || (desc->bg_flags &
+-					cpu_to_le16(EXT4_BG_BLOCK_UNINIT) &&
+-					ac->ac_2order != 0))
++			if (cr == 0)
+ 				ext4_mb_simple_scan_group(ac, &e4b);
+ 			else if (cr == 1 &&
+ 					ac->ac_g_ex.fe_len == sbi->s_stripe)

commit b614a697dc17dff82f140d72d21a095f810fa7fb
+Author: Anders Kaseorg 
+Date:   Thu Apr 23 16:49:33 2009 -0400
+
+    kbuild, modpost: Check the section flags, to catch missing "ax"/"aw"
+    
+    When you put
+      .section ".foo"
+    in an assembly file instead of
+      .section "foo", "ax"
+    , one of the possible symptoms is that modpost will see an
+    ld-generated section name ".foo.1" in section_rel() or section_rela().
+    But this heuristic has two problems: it will miss a bad section that
+    has no relocations, and it will incorrectly flag many gcc-generated
+    sections as bad when compiling with -ffunction-sections
+    -fdata-sections.
+    
+    On mips it fixes a lot of bogus warnings with gcc 4.4.0 lije this one:
+    WARNING: crypto/cryptd.o (.text.T.349): unexpected section name.
+    
+    So instead of checking whether the section name matches a particular
+    pattern, we directly check for a missing SHF_ALLOC in the section
+    flags.
+    
+    Signed-off-by: Anders Kaseorg 
+    Tested-by: Ralf Baechle 
+    Signed-off-by: Sam Ravnborg 
+
+diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
+index e5ae695458eb..936b6f8e46ff 100644
+--- a/scripts/mod/modpost.c
++++ b/scripts/mod/modpost.c
+@@ -716,41 +716,27 @@ int match(const char *sym, const char * const pat[])
+ 
+ /* sections that we do not want to do full section mismatch check on */
+ static const char *section_white_list[] =
+-	{ ".debug*", ".stab*", ".note*", ".got*", ".toc*", NULL };
++	{ ".comment", ".debug*", ".stab*", ".note*", ".got*", ".toc*", NULL };
+ 
+ /*
+- * Is this section one we do not want to check?
+- * This is often debug sections.
+- * If we are going to check this section then
+- * test if section name ends with a dot and a number.
+- * This is used to find sections where the linker have
+- * appended a dot-number to make the name unique.
++ * This is used to find sections missing the SHF_ALLOC flag.
+  * The cause of this is often a section specified in assembler
+- * without "ax" / "aw" and the same section used in .c
+- * code where gcc add these.
++ * without "ax" / "aw".
+  */
+-static int check_section(const char *modname, const char *sec)
+-{
+-	const char *e = sec + strlen(sec) - 1;
+-	if (match(sec, section_white_list))
+-		return 1;
+-
+-	if (*e && isdigit(*e)) {
+-		/* consume all digits */
+-		while (*e && e != sec && isdigit(*e))
+-			e--;
+-		if (*e == '.' && !strstr(sec, ".linkonce")) {
+-			warn("%s (%s): unexpected section name.\n"
+-			     "The (.[number]+) following section name are "
+-			     "ld generated and not expected.\n"
+-			     "Did you forget to use \"ax\"/\"aw\" "
+-			     "in a .S file?\n"
+-			     "Note that for example  contains\n"
+-			     "section definitions for use in .S files.\n\n",
+-			     modname, sec);
+-		}
++static void check_section(const char *modname, struct elf_info *elf,
++                          Elf_Shdr *sechdr)
++{
++	const char *sec = sech_name(elf, sechdr);
++
++	if (sechdr->sh_type == SHT_PROGBITS &&
++	    !(sechdr->sh_flags & SHF_ALLOC) &&
++	    !match(sec, section_white_list)) {
++		warn("%s (%s): unexpected non-allocatable section.\n"
++		     "Did you forget to use \"ax\"/\"aw\" in a .S file?\n"
++		     "Note that for example  contains\n"
++		     "section definitions for use in .S files.\n\n",
++		     modname, sec);
+ 	}
+-	return 0;
+ }
+ 
+ 
+@@ -1358,7 +1344,7 @@ static void section_rela(const char *modname, struct elf_info *elf,
+ 	fromsec = sech_name(elf, sechdr);
+ 	fromsec += strlen(".rela");
+ 	/* if from section (name) is know good then skip it */
+-	if (check_section(modname, fromsec))
++	if (match(fromsec, section_white_list))
+ 		return;
+ 
+ 	for (rela = start; rela < stop; rela++) {
+@@ -1402,7 +1388,7 @@ static void section_rel(const char *modname, struct elf_info *elf,
+ 	fromsec = sech_name(elf, sechdr);
+ 	fromsec += strlen(".rel");
+ 	/* if from section (name) is know good then skip it */
+-	if (check_section(modname, fromsec))
++	if (match(fromsec, section_white_list))
+ 		return;
+ 
+ 	for (rel = start; rel < stop; rel++) {
+@@ -1465,6 +1451,7 @@ static void check_sec_ref(struct module *mod, const char *modname,
+ 
+ 	/* Walk through all sections */
+ 	for (i = 0; i < elf->hdr->e_shnum; i++) {
++		check_section(modname, elf, &elf->sechdrs[i]);
+ 		/* We want to process only relocation sections and not .init */
+ 		if (sechdrs[i].sh_type == SHT_RELA)
+ 			section_rela(modname, elf, &elf->sechdrs[i]);

commit 8b0f9e8f78bd0a65fa001bf18f2c47eef2893a10
+Author: Theodore Ts'o 
+Date:   Mon Apr 27 17:33:23 2009 -0400
+
+    ext4: avoid unnecessary spinlock in critical POSIX ACL path
+    
+    If a filesystem supports POSIX ACL's, the VFS layer expects the filesystem
+    to do POSIX ACL checks on any files not owned by the caller, and it does
+    this for every single pathname component that it looks up.
+    
+    That obviously can be pretty expensive if the filesystem isn't careful
+    about it, especially with locking. That's doubly sad, since the common
+    case tends to be that there are no ACL's associated with the files in
+    question.
+    
+    ext4 already caches the ACL data so that it doesn't have to look it up
+    over and over again, but it does so by taking the inode->i_lock spinlock
+    on every lookup. Which is a noticeable overhead even if it's a private
+    lock, especially on CPU's where the serialization is expensive (eg Intel
+    Netburst aka 'P4').
+    
+    For the special case of not actually having any ACL's, all that locking is
+    unnecessary. Even if somebody else were to be changing the ACL's on
+    another CPU, we simply don't care - if we've seen a NULL ACL, we might as
+    well use it.
+    
+    So just load the ACL speculatively without any locking, and if it was
+    NULL, just use it. If it's non-NULL (either because we had a cached
+    entry, or because the cache hasn't been filled in at all), it means that
+    we'll need to get the lock and re-load it properly.
+    
+    (This commit was ported from a patch originally authored by Linus for
+    ext3.)
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
+index 647e0d65a284..605aeed96d68 100644
+--- a/fs/ext4/acl.c
++++ b/fs/ext4/acl.c
+@@ -129,12 +129,15 @@ ext4_acl_to_disk(const struct posix_acl *acl, size_t *size)
+ static inline struct posix_acl *
+ ext4_iget_acl(struct inode *inode, struct posix_acl **i_acl)
+ {
+-	struct posix_acl *acl = EXT4_ACL_NOT_CACHED;
++	struct posix_acl *acl = ACCESS_ONCE(*i_acl);
+ 
+-	spin_lock(&inode->i_lock);
+-	if (*i_acl != EXT4_ACL_NOT_CACHED)
+-		acl = posix_acl_dup(*i_acl);
+-	spin_unlock(&inode->i_lock);
++	if (acl) {
++		spin_lock(&inode->i_lock);
++		acl = *i_acl;
++		if (acl != EXT4_ACL_NOT_CACHED)
++			acl = posix_acl_dup(acl);
++		spin_unlock(&inode->i_lock);
++	}
+ 
+ 	return acl;
+ }

commit 9bffad1ed2a003a355ed1b42424a0ae3575275ed
+Author: Theodore Ts'o 
+Date:   Wed Jun 17 11:48:11 2009 -0400
+
+    ext4: convert instrumentation from markers to tracepoints
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
+index 5afe4370840b..83cf6415f599 100644
+--- a/fs/ext4/fsync.c
++++ b/fs/ext4/fsync.c
+@@ -28,10 +28,12 @@
+ #include 
+ #include 
+ #include 
+-#include 
++
+ #include "ext4.h"
+ #include "ext4_jbd2.h"
+ 
++#include 
++
+ /*
+  * akpm: A new design for ext4_sync_file().
+  *
+@@ -52,9 +54,7 @@ int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync)
+ 
+ 	J_ASSERT(ext4_journal_current_handle() == NULL);
+ 
+-	trace_mark(ext4_sync_file, "dev %s datasync %d ino %ld parent %ld",
+-		   inode->i_sb->s_id, datasync, inode->i_ino,
+-		   dentry->d_parent->d_inode->i_ino);
++	trace_ext4_sync_file(file, dentry, datasync);
+ 
+ 	/*
+ 	 * data=writeback:
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 3743bd849bce..7d502f3be914 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -23,11 +23,14 @@
+ #include 
+ #include 
+ #include 
++
+ #include "ext4.h"
+ #include "ext4_jbd2.h"
+ #include "xattr.h"
+ #include "acl.h"
+ 
++#include 
++
+ /*
+  * ialloc.c contains the inodes allocation and deallocation routines
+  */
+@@ -208,11 +211,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
+ 
+ 	ino = inode->i_ino;
+ 	ext4_debug("freeing inode %lu\n", ino);
+-	trace_mark(ext4_free_inode,
+-		   "dev %s ino %lu mode %d uid %lu gid %lu bocks %llu",
+-		   sb->s_id, inode->i_ino, inode->i_mode,
+-		   (unsigned long) inode->i_uid, (unsigned long) inode->i_gid,
+-		   (unsigned long long) inode->i_blocks);
++	trace_ext4_free_inode(inode);
+ 
+ 	/*
+ 	 * Note: we must free any quota before locking the superblock,
+@@ -815,8 +814,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
+ 
+ 	sb = dir->i_sb;
+ 	ngroups = ext4_get_groups_count(sb);
+-	trace_mark(ext4_request_inode, "dev %s dir %lu mode %d", sb->s_id,
+-		   dir->i_ino, mode);
++	trace_ext4_request_inode(dir, mode);
+ 	inode = new_inode(sb);
+ 	if (!inode)
+ 		return ERR_PTR(-ENOMEM);
+@@ -1047,8 +1045,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
+ 	}
+ 
+ 	ext4_debug("allocating inode %lu\n", inode->i_ino);
+-	trace_mark(ext4_allocate_inode, "dev %s ino %lu dir %lu mode %d",
+-		   sb->s_id, inode->i_ino, dir->i_ino, mode);
++	trace_ext4_allocate_inode(inode, dir, mode);
+ 	goto really_out;
+ fail:
+ 	ext4_std_error(sb, err);
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 875db944b22f..2418ad36eab5 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -37,11 +37,14 @@
+ #include 
+ #include 
+ #include 
++
+ #include "ext4_jbd2.h"
+ #include "xattr.h"
+ #include "acl.h"
+ #include "ext4_extents.h"
+ 
++#include 
++
+ #define MPAGE_DA_EXTENT_TAIL 0x01
+ 
+ static inline int ext4_begin_ordered_truncate(struct inode *inode,
+@@ -1466,10 +1469,7 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
+  	pgoff_t index;
+ 	unsigned from, to;
+ 
+-	trace_mark(ext4_write_begin,
+-		   "dev %s ino %lu pos %llu len %u flags %u",
+-		   inode->i_sb->s_id, inode->i_ino,
+-		   (unsigned long long) pos, len, flags);
++	trace_ext4_write_begin(inode, pos, len, flags);
+ 	/*
+ 	 * Reserve one block more for addition to orphan list in case
+ 	 * we allocate blocks but write fails for some reason
+@@ -1611,10 +1611,7 @@ static int ext4_ordered_write_end(struct file *file,
+ 	struct inode *inode = mapping->host;
+ 	int ret = 0, ret2;
+ 
+-	trace_mark(ext4_ordered_write_end,
+-		   "dev %s ino %lu pos %llu len %u copied %u",
+-		   inode->i_sb->s_id, inode->i_ino,
+-		   (unsigned long long) pos, len, copied);
++	trace_ext4_ordered_write_end(inode, pos, len, copied);
+ 	ret = ext4_jbd2_file_inode(handle, inode);
+ 
+ 	if (ret == 0) {
+@@ -1658,10 +1655,7 @@ static int ext4_writeback_write_end(struct file *file,
+ 	struct inode *inode = mapping->host;
+ 	int ret = 0, ret2;
+ 
+-	trace_mark(ext4_writeback_write_end,
+-		   "dev %s ino %lu pos %llu len %u copied %u",
+-		   inode->i_sb->s_id, inode->i_ino,
+-		   (unsigned long long) pos, len, copied);
++	trace_ext4_writeback_write_end(inode, pos, len, copied);
+ 	ret2 = ext4_generic_write_end(file, mapping, pos, len, copied,
+ 							page, fsdata);
+ 	copied = ret2;
+@@ -1705,10 +1699,7 @@ static int ext4_journalled_write_end(struct file *file,
+ 	unsigned from, to;
+ 	loff_t new_i_size;
+ 
+-	trace_mark(ext4_journalled_write_end,
+-		   "dev %s ino %lu pos %llu len %u copied %u",
+-		   inode->i_sb->s_id, inode->i_ino,
+-		   (unsigned long long) pos, len, copied);
++	trace_ext4_journalled_write_end(inode, pos, len, copied);
+ 	from = pos & (PAGE_CACHE_SIZE - 1);
+ 	to = from + len;
+ 
+@@ -2554,9 +2545,7 @@ static int ext4_da_writepage(struct page *page,
+ 	struct buffer_head *page_bufs;
+ 	struct inode *inode = page->mapping->host;
+ 
+-	trace_mark(ext4_da_writepage,
+-		   "dev %s ino %lu page_index %lu",
+-		   inode->i_sb->s_id, inode->i_ino, page->index);
++	trace_ext4_da_writepage(inode, page);
+ 	size = i_size_read(inode);
+ 	if (page->index == size >> PAGE_CACHE_SHIFT)
+ 		len = size & ~PAGE_CACHE_MASK;
+@@ -2667,19 +2656,7 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 	int needed_blocks, ret = 0, nr_to_writebump = 0;
+ 	struct ext4_sb_info *sbi = EXT4_SB(mapping->host->i_sb);
+ 
+-	trace_mark(ext4_da_writepages,
+-		   "dev %s ino %lu nr_t_write %ld "
+-		   "pages_skipped %ld range_start %llu "
+-		   "range_end %llu nonblocking %d "
+-		   "for_kupdate %d for_reclaim %d "
+-		   "for_writepages %d range_cyclic %d",
+-		   inode->i_sb->s_id, inode->i_ino,
+-		   wbc->nr_to_write, wbc->pages_skipped,
+-		   (unsigned long long) wbc->range_start,
+-		   (unsigned long long) wbc->range_end,
+-		   wbc->nonblocking, wbc->for_kupdate,
+-		   wbc->for_reclaim, wbc->for_writepages,
+-		   wbc->range_cyclic);
++	trace_ext4_da_writepages(inode, wbc);
+ 
+ 	/*
+ 	 * No pages to write? This is mainly a kludge to avoid starting
+@@ -2845,14 +2822,7 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 	if (!no_nrwrite_index_update)
+ 		wbc->no_nrwrite_index_update = 0;
+ 	wbc->nr_to_write -= nr_to_writebump;
+-	trace_mark(ext4_da_writepage_result,
+-		   "dev %s ino %lu ret %d pages_written %d "
+-		   "pages_skipped %ld congestion %d "
+-		   "more_io %d no_nrwrite_index_update %d",
+-		   inode->i_sb->s_id, inode->i_ino, ret,
+-		   pages_written, wbc->pages_skipped,
+-		   wbc->encountered_congestion, wbc->more_io,
+-		   wbc->no_nrwrite_index_update);
++	trace_ext4_da_writepages_result(inode, wbc, ret, pages_written);
+ 	return ret;
+ }
+ 
+@@ -2904,11 +2874,7 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
+ 					len, flags, pagep, fsdata);
+ 	}
+ 	*fsdata = (void *)0;
+-
+-	trace_mark(ext4_da_write_begin,
+-		   "dev %s ino %lu pos %llu len %u flags %u",
+-		   inode->i_sb->s_id, inode->i_ino,
+-		   (unsigned long long) pos, len, flags);
++	trace_ext4_da_write_begin(inode, pos, len, flags);
+ retry:
+ 	/*
+ 	 * With delayed allocation, we don't log the i_disksize update
+@@ -3001,10 +2967,7 @@ static int ext4_da_write_end(struct file *file,
+ 		}
+ 	}
+ 
+-	trace_mark(ext4_da_write_end,
+-		   "dev %s ino %lu pos %llu len %u copied %u",
+-		   inode->i_sb->s_id, inode->i_ino,
+-		   (unsigned long long) pos, len, copied);
++	trace_ext4_da_write_end(inode, pos, len, copied);
+ 	start = pos & (PAGE_CACHE_SIZE - 1);
+ 	end = start + copied - 1;
+ 
+@@ -3255,9 +3218,7 @@ static int ext4_normal_writepage(struct page *page,
+ 	loff_t size = i_size_read(inode);
+ 	loff_t len;
+ 
+-	trace_mark(ext4_normal_writepage,
+-		   "dev %s ino %lu page_index %lu",
+-		   inode->i_sb->s_id, inode->i_ino, page->index);
++	trace_ext4_normal_writepage(inode, page);
+ 	J_ASSERT(PageLocked(page));
+ 	if (page->index == size >> PAGE_CACHE_SHIFT)
+ 		len = size & ~PAGE_CACHE_MASK;
+@@ -3343,9 +3304,7 @@ static int ext4_journalled_writepage(struct page *page,
+ 	loff_t size = i_size_read(inode);
+ 	loff_t len;
+ 
+-	trace_mark(ext4_journalled_writepage,
+-		   "dev %s ino %lu page_index %lu",
+-		   inode->i_sb->s_id, inode->i_ino, page->index);
++	trace_ext4_journalled_writepage(inode, page);
+ 	J_ASSERT(PageLocked(page));
+ 	if (page->index == size >> PAGE_CACHE_SHIFT)
+ 		len = size & ~PAGE_CACHE_MASK;
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index ed8482e22c0e..8d98070b48fb 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -22,6 +22,8 @@
+  */
+ 
+ #include "mballoc.h"
++#include 
++
+ /*
+  * MUSTDO:
+  *   - test ext4_ext_search_left() and ext4_ext_search_right()
+@@ -340,8 +342,6 @@ static void ext4_mb_generate_from_freelist(struct super_block *sb, void *bitmap,
+ 						ext4_group_t group);
+ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn);
+ 
+-
+-
+ static inline void *mb_correct_addr_and_bit(int *bit, void *addr)
+ {
+ #if BITS_PER_LONG == 64
+@@ -2859,9 +2859,8 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn)
+ 		discard_block = (ext4_fsblk_t) entry->group * EXT4_BLOCKS_PER_GROUP(sb)
+ 			+ entry->start_blk
+ 			+ le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
+-		trace_mark(ext4_discard_blocks, "dev %s blk %llu count %u",
+-			   sb->s_id, (unsigned long long) discard_block,
+-			   entry->count);
++		trace_ext4_discard_blocks(sb, (unsigned long long)discard_block,
++					  entry->count);
+ 		sb_issue_discard(sb, discard_block, entry->count);
+ 
+ 		kmem_cache_free(ext4_free_ext_cachep, entry);
+@@ -3629,10 +3628,7 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
+ 
+ 	mb_debug("new inode pa %p: %llu/%u for %u\n", pa,
+ 			pa->pa_pstart, pa->pa_len, pa->pa_lstart);
+-	trace_mark(ext4_mb_new_inode_pa,
+-		   "dev %s ino %lu pstart %llu len %u lstart %u",
+-		   sb->s_id, ac->ac_inode->i_ino,
+-		   pa->pa_pstart, pa->pa_len, pa->pa_lstart);
++	trace_ext4_mb_new_inode_pa(ac, pa);
+ 
+ 	ext4_mb_use_inode_pa(ac, pa);
+ 	atomic_add(pa->pa_free, &EXT4_SB(sb)->s_mb_preallocated);
+@@ -3691,9 +3687,8 @@ ext4_mb_new_group_pa(struct ext4_allocation_context *ac)
+ 	pa->pa_type = MB_GROUP_PA;
+ 
+ 	mb_debug("new group pa %p: %llu/%u for %u\n", pa,
+-		 pa->pa_pstart, pa->pa_len, pa->pa_lstart);
+-	trace_mark(ext4_mb_new_group_pa, "dev %s pstart %llu len %u lstart %u",
+-		   sb->s_id, pa->pa_pstart, pa->pa_len, pa->pa_lstart);
++			pa->pa_pstart, pa->pa_len, pa->pa_lstart);
++	trace_ext4_mb_new_group_pa(ac, pa);
+ 
+ 	ext4_mb_use_group_pa(ac, pa);
+ 	atomic_add(pa->pa_free, &EXT4_SB(sb)->s_mb_preallocated);
+@@ -3783,10 +3778,8 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh,
+ 			ext4_mb_store_history(ac);
+ 		}
+ 
+-		trace_mark(ext4_mb_release_inode_pa,
+-			   "dev %s ino %lu block %llu count %u",
+-			   sb->s_id, pa->pa_inode->i_ino, grp_blk_start + bit,
+-			   next - bit);
++		trace_ext4_mb_release_inode_pa(ac, pa, grp_blk_start + bit,
++					       next - bit);
+ 		mb_free_blocks(pa->pa_inode, e4b, bit, next - bit);
+ 		bit = next + 1;
+ 	}
+@@ -3820,8 +3813,7 @@ ext4_mb_release_group_pa(struct ext4_buddy *e4b,
+ 	if (ac)
+ 		ac->ac_op = EXT4_MB_HISTORY_DISCARD;
+ 
+-	trace_mark(ext4_mb_release_group_pa, "dev %s pstart %llu len %d",
+-		   sb->s_id, pa->pa_pstart, pa->pa_len);
++	trace_ext4_mb_release_group_pa(ac, pa);
+ 	BUG_ON(pa->pa_deleted == 0);
+ 	ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit);
+ 	BUG_ON(group != e4b->bd_group && pa->pa_len != 0);
+@@ -3889,6 +3881,8 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
+ 
+ 	INIT_LIST_HEAD(&list);
+ 	ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
++	if (ac)
++		ac->ac_sb = sb;
+ repeat:
+ 	ext4_lock_group(sb, group);
+ 	list_for_each_entry_safe(pa, tmp,
+@@ -3987,12 +3981,15 @@ void ext4_discard_preallocations(struct inode *inode)
+ 	}
+ 
+ 	mb_debug("discard preallocation for inode %lu\n", inode->i_ino);
+-	trace_mark(ext4_discard_preallocations, "dev %s ino %lu", sb->s_id,
+-		   inode->i_ino);
++	trace_ext4_discard_preallocations(inode);
+ 
+ 	INIT_LIST_HEAD(&list);
+ 
+ 	ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
++	if (ac) {
++		ac->ac_sb = sb;
++		ac->ac_inode = inode;
++	}
+ repeat:
+ 	/* first, collect all pa's in the inode */
+ 	spin_lock(&ei->i_prealloc_lock);
+@@ -4276,6 +4273,8 @@ ext4_mb_discard_lg_preallocations(struct super_block *sb,
+ 
+ 	INIT_LIST_HEAD(&discard_list);
+ 	ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
++	if (ac)
++		ac->ac_sb = sb;
+ 
+ 	spin_lock(&lg->lg_prealloc_lock);
+ 	list_for_each_entry_rcu(pa, &lg->lg_prealloc_list[order],
+@@ -4445,8 +4444,7 @@ static int ext4_mb_discard_preallocations(struct super_block *sb, int needed)
+ 	int ret;
+ 	int freed = 0;
+ 
+-	trace_mark(ext4_mb_discard_preallocations, "dev %s needed %d",
+-		   sb->s_id, needed);
++	trace_ext4_mb_discard_preallocations(sb, needed);
+ 	for (i = 0; i < ngroups && needed > 0; i++) {
+ 		ret = ext4_mb_discard_group_preallocations(sb, i, needed);
+ 		freed += ret;
+@@ -4475,17 +4473,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
+ 	sb = ar->inode->i_sb;
+ 	sbi = EXT4_SB(sb);
+ 
+-	trace_mark(ext4_request_blocks, "dev %s flags %u len %u ino %lu "
+-		   "lblk %llu goal %llu lleft %llu lright %llu "
+-		   "pleft %llu pright %llu ",
+-		   sb->s_id, ar->flags, ar->len,
+-		   ar->inode ? ar->inode->i_ino : 0,
+-		   (unsigned long long) ar->logical,
+-		   (unsigned long long) ar->goal,
+-		   (unsigned long long) ar->lleft,
+-		   (unsigned long long) ar->lright,
+-		   (unsigned long long) ar->pleft,
+-		   (unsigned long long) ar->pright);
++	trace_ext4_request_blocks(ar);
+ 
+ 	/*
+ 	 * For delayed allocation, we could skip the ENOSPC and
+@@ -4521,7 +4509,10 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
+ 	}
+ 
+ 	ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
+-	if (!ac) {
++	if (ac) {
++		ac->ac_sb = sb;
++		ac->ac_inode = ar->inode;
++	} else {
+ 		ar->len = 0;
+ 		*errp = -ENOMEM;
+ 		goto out1;
+@@ -4594,18 +4585,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
+ 						reserv_blks);
+ 	}
+ 
+-	trace_mark(ext4_allocate_blocks,
+-		   "dev %s block %llu flags %u len %u ino %lu "
+-		   "logical %llu goal %llu lleft %llu lright %llu "
+-		   "pleft %llu pright %llu ",
+-		   sb->s_id, (unsigned long long) block,
+-		   ar->flags, ar->len, ar->inode ? ar->inode->i_ino : 0,
+-		   (unsigned long long) ar->logical,
+-		   (unsigned long long) ar->goal,
+-		   (unsigned long long) ar->lleft,
+-		   (unsigned long long) ar->lright,
+-		   (unsigned long long) ar->pleft,
+-		   (unsigned long long) ar->pright);
++	trace_ext4_allocate_blocks(ar, (unsigned long long)block);
+ 
+ 	return block;
+ }
+@@ -4740,10 +4720,7 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
+ 	}
+ 
+ 	ext4_debug("freeing block %lu\n", block);
+-	trace_mark(ext4_free_blocks,
+-		   "dev %s block %llu count %lu metadata %d ino %lu",
+-		   sb->s_id, (unsigned long long) block, count, metadata,
+-		   inode ? inode->i_ino : 0);
++	trace_ext4_free_blocks(inode, block, count, metadata);
+ 
+ 	ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
+ 	if (ac) {
+diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
+index 75e34f69215b..c96bb19f58f9 100644
+--- a/fs/ext4/mballoc.h
++++ b/fs/ext4/mballoc.h
+@@ -19,7 +19,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ #include 
+ #include "ext4_jbd2.h"
+ #include "ext4.h"
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 012c4251397e..e8f0b2af4607 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -37,7 +37,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ #include 
+ #include 
+ #include 
+@@ -47,6 +46,9 @@
+ #include "xattr.h"
+ #include "acl.h"
+ 
++#define CREATE_TRACE_POINTS
++#include 
++
+ static int default_mb_history_length = 1000;
+ 
+ module_param_named(default_mb_history_length, default_mb_history_length,
+@@ -3346,7 +3348,7 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
+ 	int ret = 0;
+ 	tid_t target;
+ 
+-	trace_mark(ext4_sync_fs, "dev %s wait %d", sb->s_id, wait);
++	trace_ext4_sync_fs(sb, wait);
+ 	if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, &target)) {
+ 		if (wait)
+ 			jbd2_log_wait_commit(EXT4_SB(sb)->s_journal, target);
+diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
+new file mode 100644
+index 000000000000..acf4cc9cd36d
+--- /dev/null
++++ b/include/trace/events/ext4.h
+@@ -0,0 +1,719 @@
++#if !defined(_TRACE_EXT4_H) || defined(TRACE_HEADER_MULTI_READ)
++#define _TRACE_EXT4_H
++
++#undef TRACE_SYSTEM
++#define TRACE_SYSTEM ext4
++
++#include 
++#include "../../../fs/ext4/ext4.h"
++#include "../../../fs/ext4/mballoc.h"
++#include 
++
++TRACE_EVENT(ext4_free_inode,
++	TP_PROTO(struct inode *inode),
++
++	TP_ARGS(inode),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	umode_t, mode			)
++		__field(	uid_t,	uid			)
++		__field(	gid_t,	gid			)
++		__field(	blkcnt_t, blocks		)
++	),
++
++	TP_fast_assign(
++		__entry->dev	= inode->i_sb->s_dev;
++		__entry->ino	= inode->i_ino;
++		__entry->mode	= inode->i_mode;
++		__entry->uid	= inode->i_uid;
++		__entry->gid	= inode->i_gid;
++		__entry->blocks	= inode->i_blocks;
++	),
++
++	TP_printk("dev %s ino %lu mode %d uid %u gid %u blocks %llu",
++		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->mode,
++		  __entry->uid, __entry->gid, __entry->blocks)
++);
++
++TRACE_EVENT(ext4_request_inode,
++	TP_PROTO(struct inode *dir, int mode),
++
++	TP_ARGS(dir, mode),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	dir			)
++		__field(	umode_t, mode			)
++	),
++
++	TP_fast_assign(
++		__entry->dev	= dir->i_sb->s_dev;
++		__entry->dir	= dir->i_ino;
++		__entry->mode	= mode;
++	),
++
++	TP_printk("dev %s dir %lu mode %d",
++		  jbd2_dev_to_name(__entry->dev), __entry->dir, __entry->mode)
++);
++
++TRACE_EVENT(ext4_allocate_inode,
++	TP_PROTO(struct inode *inode, struct inode *dir, int mode),
++
++	TP_ARGS(inode, dir, mode),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	ino_t,	dir			)
++		__field(	umode_t, mode			)
++	),
++
++	TP_fast_assign(
++		__entry->dev	= inode->i_sb->s_dev;
++		__entry->ino	= inode->i_ino;
++		__entry->dir	= dir->i_ino;
++		__entry->mode	= mode;
++	),
++
++	TP_printk("dev %s ino %lu dir %lu mode %d",
++		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->dir, __entry->mode)
++);
++
++TRACE_EVENT(ext4_write_begin,
++
++	TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
++		 unsigned int flags),
++
++	TP_ARGS(inode, pos, len, flags),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	loff_t,	pos			)
++		__field(	unsigned int, len		)
++		__field(	unsigned int, flags		)
++	),
++
++	TP_fast_assign(
++		__entry->dev	= inode->i_sb->s_dev;
++		__entry->ino	= inode->i_ino;
++		__entry->pos	= pos;
++		__entry->len	= len;
++		__entry->flags	= flags;
++	),
++
++	TP_printk("dev %s ino %lu pos %llu len %u flags %u",
++		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->pos, __entry->len,
++		  __entry->flags)
++);
++
++TRACE_EVENT(ext4_ordered_write_end,
++	TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
++			unsigned int copied),
++
++	TP_ARGS(inode, pos, len, copied),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	loff_t,	pos			)
++		__field(	unsigned int, len		)
++		__field(	unsigned int, copied		)
++	),
++
++	TP_fast_assign(
++		__entry->dev	= inode->i_sb->s_dev;
++		__entry->ino	= inode->i_ino;
++		__entry->pos	= pos;
++		__entry->len	= len;
++		__entry->copied	= copied;
++	),
++
++	TP_printk("dev %s ino %lu pos %llu len %u copied %u",
++		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->pos, __entry->len,
++		  __entry->copied)
++);
++
++TRACE_EVENT(ext4_writeback_write_end,
++	TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
++		 unsigned int copied),
++
++	TP_ARGS(inode, pos, len, copied),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	loff_t,	pos			)
++		__field(	unsigned int, len		)
++		__field(	unsigned int, copied		)
++	),
++
++	TP_fast_assign(
++		__entry->dev	= inode->i_sb->s_dev;
++		__entry->ino	= inode->i_ino;
++		__entry->pos	= pos;
++		__entry->len	= len;
++		__entry->copied	= copied;
++	),
++
++	TP_printk("dev %s ino %lu pos %llu len %u copied %u",
++		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->pos, __entry->len,
++		  __entry->copied)
++);
++
++TRACE_EVENT(ext4_journalled_write_end,
++	TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
++		 unsigned int copied),
++	TP_ARGS(inode, pos, len, copied),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	loff_t,	pos			)
++		__field(	unsigned int, len		)
++		__field(	unsigned int, copied		)
++	),
++
++	TP_fast_assign(
++		__entry->dev	= inode->i_sb->s_dev;
++		__entry->ino	= inode->i_ino;
++		__entry->pos	= pos;
++		__entry->len	= len;
++		__entry->copied	= copied;
++	),
++
++	TP_printk("dev %s ino %lu pos %llu len %u copied %u",
++		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->pos, __entry->len,
++		  __entry->copied)
++);
++
++TRACE_EVENT(ext4_da_writepage,
++	TP_PROTO(struct inode *inode, struct page *page),
++
++	TP_ARGS(inode, page),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	pgoff_t, index			)
++
++	),
++
++	TP_fast_assign(
++		__entry->dev	= inode->i_sb->s_dev;
++		__entry->ino	= inode->i_ino;
++		__entry->index	= page->index;
++	),
++
++	TP_printk("dev %s ino %lu page_index %lu",
++		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->index)
++);
++
++TRACE_EVENT(ext4_da_writepages,
++	TP_PROTO(struct inode *inode, struct writeback_control *wbc),
++
++	TP_ARGS(inode, wbc),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	long,	nr_to_write		)
++		__field(	long,	pages_skipped		)
++		__field(	loff_t,	range_start		)
++		__field(	loff_t,	range_end		)
++		__field(	char,	nonblocking		)
++		__field(	char,	for_kupdate		)
++		__field(	char,	for_reclaim		)
++		__field(	char,	for_writepages		)
++		__field(	char,	range_cyclic		)
++	),
++
++	TP_fast_assign(
++		__entry->dev		= inode->i_sb->s_dev;
++		__entry->ino		= inode->i_ino;
++		__entry->nr_to_write	= wbc->nr_to_write;
++		__entry->pages_skipped	= wbc->pages_skipped;
++		__entry->range_start	= wbc->range_start;
++		__entry->range_end	= wbc->range_end;
++		__entry->nonblocking	= wbc->nonblocking;
++		__entry->for_kupdate	= wbc->for_kupdate;
++		__entry->for_reclaim	= wbc->for_reclaim;
++		__entry->for_writepages	= wbc->for_writepages;
++		__entry->range_cyclic	= wbc->range_cyclic;
++	),
++
++	TP_printk("dev %s ino %lu nr_t_write %ld pages_skipped %ld range_start %llu range_end %llu nonblocking %d for_kupdate %d for_reclaim %d for_writepages %d range_cyclic %d",
++		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->nr_to_write,
++		  __entry->pages_skipped, __entry->range_start,
++		  __entry->range_end, __entry->nonblocking,
++		  __entry->for_kupdate, __entry->for_reclaim,
++		  __entry->for_writepages, __entry->range_cyclic)
++);
++
++TRACE_EVENT(ext4_da_writepages_result,
++	TP_PROTO(struct inode *inode, struct writeback_control *wbc,
++			int ret, int pages_written),
++
++	TP_ARGS(inode, wbc, ret, pages_written),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	int,	ret			)
++		__field(	int,	pages_written		)
++		__field(	long,	pages_skipped		)
++		__field(	char,	encountered_congestion	)
++		__field(	char,	more_io			)	
++		__field(	char,	no_nrwrite_index_update )
++	),
++
++	TP_fast_assign(
++		__entry->dev		= inode->i_sb->s_dev;
++		__entry->ino		= inode->i_ino;
++		__entry->ret		= ret;
++		__entry->pages_written	= pages_written;
++		__entry->pages_skipped	= wbc->pages_skipped;
++		__entry->encountered_congestion	= wbc->encountered_congestion;
++		__entry->more_io	= wbc->more_io;
++		__entry->no_nrwrite_index_update = wbc->no_nrwrite_index_update;
++	),
++
++	TP_printk("dev %s ino %lu ret %d pages_written %d pages_skipped %ld congestion %d more_io %d no_nrwrite_index_update %d",
++		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->ret,
++		  __entry->pages_written, __entry->pages_skipped,
++		  __entry->encountered_congestion, __entry->more_io,
++		  __entry->no_nrwrite_index_update)
++);
++
++TRACE_EVENT(ext4_da_write_begin,
++	TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
++			unsigned int flags),
++
++	TP_ARGS(inode, pos, len, flags),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	loff_t,	pos			)
++		__field(	unsigned int, len		)
++		__field(	unsigned int, flags		)
++	),
++
++	TP_fast_assign(
++		__entry->dev	= inode->i_sb->s_dev;
++		__entry->ino	= inode->i_ino;
++		__entry->pos	= pos;
++		__entry->len	= len;
++		__entry->flags	= flags;
++	),
++
++	TP_printk("dev %s ino %lu pos %llu len %u flags %u",
++		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->pos, __entry->len,
++		  __entry->flags)
++);
++
++TRACE_EVENT(ext4_da_write_end,
++	TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
++			unsigned int copied),
++
++	TP_ARGS(inode, pos, len, copied),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	loff_t,	pos			)
++		__field(	unsigned int, len		)
++		__field(	unsigned int, copied		)
++	),
++
++	TP_fast_assign(
++		__entry->dev	= inode->i_sb->s_dev;
++		__entry->ino	= inode->i_ino;
++		__entry->pos	= pos;
++		__entry->len	= len;
++		__entry->copied	= copied;
++	),
++
++	TP_printk("dev %s ino %lu pos %llu len %u copied %u",
++		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->pos, __entry->len,
++		  __entry->copied)
++);
++
++TRACE_EVENT(ext4_normal_writepage,
++	TP_PROTO(struct inode *inode, struct page *page),
++
++	TP_ARGS(inode, page),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	pgoff_t, index			)
++	),
++
++	TP_fast_assign(
++		__entry->dev	= inode->i_sb->s_dev;
++		__entry->ino	= inode->i_ino;
++		__entry->index	= page->index;
++	),
++
++	TP_printk("dev %s ino %lu page_index %lu",
++		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->index)
++);
++
++TRACE_EVENT(ext4_journalled_writepage,
++	TP_PROTO(struct inode *inode, struct page *page),
++
++	TP_ARGS(inode, page),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	pgoff_t, index			)
++
++	),
++
++	TP_fast_assign(
++		__entry->dev	= inode->i_sb->s_dev;
++		__entry->ino	= inode->i_ino;
++		__entry->index	= page->index;
++	),
++
++	TP_printk("dev %s ino %lu page_index %lu",
++		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->index)
++);
++
++TRACE_EVENT(ext4_discard_blocks,
++	TP_PROTO(struct super_block *sb, unsigned long long blk,
++			unsigned long long count),
++
++	TP_ARGS(sb, blk, count),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	__u64,	blk			)
++		__field(	__u64,	count			)
++
++	),
++
++	TP_fast_assign(
++		__entry->dev	= sb->s_dev;
++		__entry->blk	= blk;
++		__entry->count	= count;
++	),
++
++	TP_printk("dev %s blk %llu count %llu",
++		  jbd2_dev_to_name(__entry->dev), __entry->blk, __entry->count)
++);
++
++TRACE_EVENT(ext4_mb_new_inode_pa,
++	TP_PROTO(struct ext4_allocation_context *ac,
++		 struct ext4_prealloc_space *pa),
++
++	TP_ARGS(ac, pa),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	__u64,	pa_pstart		)
++		__field(	__u32,	pa_len			)
++		__field(	__u64,	pa_lstart		)
++
++	),
++
++	TP_fast_assign(
++		__entry->dev		= ac->ac_sb->s_dev;
++		__entry->ino		= ac->ac_inode->i_ino;
++		__entry->pa_pstart	= pa->pa_pstart;
++		__entry->pa_len		= pa->pa_len;
++		__entry->pa_lstart	= pa->pa_lstart;
++	),
++
++	TP_printk("dev %s ino %lu pstart %llu len %u lstart %llu",
++		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->pa_pstart,
++		  __entry->pa_len, __entry->pa_lstart)
++);
++
++TRACE_EVENT(ext4_mb_new_group_pa,
++	TP_PROTO(struct ext4_allocation_context *ac,
++		 struct ext4_prealloc_space *pa),
++
++	TP_ARGS(ac, pa),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	__u64,	pa_pstart		)
++		__field(	__u32,	pa_len			)
++		__field(	__u64,	pa_lstart		)
++
++	),
++
++	TP_fast_assign(
++		__entry->dev		= ac->ac_sb->s_dev;
++		__entry->ino		= ac->ac_inode->i_ino;
++		__entry->pa_pstart	= pa->pa_pstart;
++		__entry->pa_len		= pa->pa_len;
++		__entry->pa_lstart	= pa->pa_lstart;
++	),
++
++	TP_printk("dev %s ino %lu pstart %llu len %u lstart %llu",
++		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->pa_pstart,
++		  __entry->pa_len, __entry->pa_lstart)
++);
++
++TRACE_EVENT(ext4_mb_release_inode_pa,
++	TP_PROTO(struct ext4_allocation_context *ac,
++		 struct ext4_prealloc_space *pa,
++		 unsigned long long block, unsigned int count),
++
++	TP_ARGS(ac, pa, block, count),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	__u64,	block			)
++		__field(	__u32,	count			)
++
++	),
++
++	TP_fast_assign(
++		__entry->dev		= ac->ac_sb->s_dev;
++		__entry->ino		= ac->ac_inode->i_ino;
++		__entry->block		= block;
++		__entry->count		= count;
++	),
++
++	TP_printk("dev %s ino %lu block %llu count %u",
++		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->block,
++		  __entry->count)
++);
++
++TRACE_EVENT(ext4_mb_release_group_pa,
++	TP_PROTO(struct ext4_allocation_context *ac,
++		 struct ext4_prealloc_space *pa),
++
++	TP_ARGS(ac, pa),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	__u64,	pa_pstart		)
++		__field(	__u32,	pa_len			)
++
++	),
++
++	TP_fast_assign(
++		__entry->dev		= ac->ac_sb->s_dev;
++		__entry->ino		= ac->ac_inode->i_ino;
++		__entry->pa_pstart	= pa->pa_pstart;
++		__entry->pa_len		= pa->pa_len;
++	),
++
++	TP_printk("dev %s pstart %llu len %u",
++		  jbd2_dev_to_name(__entry->dev), __entry->pa_pstart, __entry->pa_len)
++);
++
++TRACE_EVENT(ext4_discard_preallocations,
++	TP_PROTO(struct inode *inode),
++
++	TP_ARGS(inode),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++
++	),
++
++	TP_fast_assign(
++		__entry->dev	= inode->i_sb->s_dev;
++		__entry->ino	= inode->i_ino;
++	),
++
++	TP_printk("dev %s ino %lu",
++		  jbd2_dev_to_name(__entry->dev), __entry->ino)
++);
++
++TRACE_EVENT(ext4_mb_discard_preallocations,
++	TP_PROTO(struct super_block *sb, int needed),
++
++	TP_ARGS(sb, needed),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	int,	needed			)
++
++	),
++
++	TP_fast_assign(
++		__entry->dev	= sb->s_dev;
++		__entry->needed	= needed;
++	),
++
++	TP_printk("dev %s needed %d",
++		  jbd2_dev_to_name(__entry->dev), __entry->needed)
++);
++
++TRACE_EVENT(ext4_request_blocks,
++	TP_PROTO(struct ext4_allocation_request *ar),
++
++	TP_ARGS(ar),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	unsigned int, flags		)
++		__field(	unsigned int, len		)
++		__field(	__u64,  logical			)
++		__field(	__u64,	goal			)
++		__field(	__u64,	lleft			)
++		__field(	__u64,	lright			)
++		__field(	__u64,	pleft			)
++		__field(	__u64,	pright			)
++	),
++
++	TP_fast_assign(
++		__entry->dev	= ar->inode->i_sb->s_dev;
++		__entry->ino	= ar->inode->i_ino;
++		__entry->flags	= ar->flags;
++		__entry->len	= ar->len;
++		__entry->logical = ar->logical;
++		__entry->goal	= ar->goal;
++		__entry->lleft	= ar->lleft;
++		__entry->lright	= ar->lright;
++		__entry->pleft	= ar->pleft;
++		__entry->pright	= ar->pright;
++	),
++
++	TP_printk("dev %s ino %lu flags %u len %u lblk %llu goal %llu lleft %llu lright %llu pleft %llu pright %llu ",
++		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->flags,
++		  __entry->len,
++		  (unsigned long long) __entry->logical,
++		  (unsigned long long) __entry->goal,
++		  (unsigned long long) __entry->lleft,
++		  (unsigned long long) __entry->lright,
++		  (unsigned long long) __entry->pleft,
++		  (unsigned long long) __entry->pright)
++);
++
++TRACE_EVENT(ext4_allocate_blocks,
++	TP_PROTO(struct ext4_allocation_request *ar, unsigned long long block),
++
++	TP_ARGS(ar, block),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	__u64,	block			)
++		__field(	unsigned int, flags		)
++		__field(	unsigned int, len		)
++		__field(	__u64,  logical			)
++		__field(	__u64,	goal			)
++		__field(	__u64,	lleft			)
++		__field(	__u64,	lright			)
++		__field(	__u64,	pleft			)
++		__field(	__u64,	pright			)
++	),
++
++	TP_fast_assign(
++		__entry->dev	= ar->inode->i_sb->s_dev;
++		__entry->ino	= ar->inode->i_ino;
++		__entry->block	= block;
++		__entry->flags	= ar->flags;
++		__entry->len	= ar->len;
++		__entry->logical = ar->logical;
++		__entry->goal	= ar->goal;
++		__entry->lleft	= ar->lleft;
++		__entry->lright	= ar->lright;
++		__entry->pleft	= ar->pleft;
++		__entry->pright	= ar->pright;
++	),
++
++	TP_printk("dev %s ino %lu flags %u len %u block %llu lblk %llu goal %llu lleft %llu lright %llu pleft %llu pright %llu ",
++		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->flags,
++		  __entry->len, __entry->block,
++		  (unsigned long long) __entry->logical,
++		  (unsigned long long) __entry->goal,
++		  (unsigned long long) __entry->lleft,
++		  (unsigned long long) __entry->lright,
++		  (unsigned long long) __entry->pleft,
++		  (unsigned long long) __entry->pright)
++);
++
++TRACE_EVENT(ext4_free_blocks,
++	TP_PROTO(struct inode *inode, __u64 block, unsigned long count,
++			int metadata),
++
++	TP_ARGS(inode, block, count, metadata),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	__u64,	block			)
++		__field(	unsigned long,	count		)
++		__field(	int,	metadata		)
++
++	),
++
++	TP_fast_assign(
++		__entry->dev		= inode->i_sb->s_dev;
++		__entry->ino		= inode->i_ino;
++		__entry->block		= block;
++		__entry->count		= count;
++		__entry->metadata	= metadata;
++	),
++
++	TP_printk("dev %s ino %lu block %llu count %lu metadata %d",
++		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->block,
++		  __entry->count, __entry->metadata)
++);
++
++TRACE_EVENT(ext4_sync_file,
++	TP_PROTO(struct file *file, struct dentry *dentry, int datasync),
++
++	TP_ARGS(file, dentry, datasync),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++		__field(	ino_t,	parent			)
++		__field(	int,	datasync		)
++	),
++
++	TP_fast_assign(
++		__entry->dev		= dentry->d_inode->i_sb->s_dev;
++		__entry->ino		= dentry->d_inode->i_ino;
++		__entry->datasync	= datasync;
++		__entry->parent		= dentry->d_parent->d_inode->i_ino;
++	),
++
++	TP_printk("dev %s ino %ld parent %ld datasync %d ",
++		  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->parent,
++		  __entry->datasync)
++);
++
++TRACE_EVENT(ext4_sync_fs,
++	TP_PROTO(struct super_block *sb, int wait),
++
++	TP_ARGS(sb, wait),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	int,	wait			)
++
++	),
++
++	TP_fast_assign(
++		__entry->dev	= sb->s_dev;
++		__entry->wait	= wait;
++	),
++
++	TP_printk("dev %s wait %d", jbd2_dev_to_name(__entry->dev),
++		  __entry->wait)
++);
++
++#endif /* _TRACE_EXT4_H */
++
++/* This part must be outside protection */
++#include 

commit 879c5e6b7cb4c689d08ca9b2e353d8ab3dc425d5
+Author: Theodore Ts'o 
+Date:   Wed Jun 17 11:47:48 2009 -0400
+
+    jbd2: convert instrumentation from markers to tracepoints
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
+index 17159cacbd9e..5d70b3e6d49b 100644
+--- a/fs/jbd2/checkpoint.c
++++ b/fs/jbd2/checkpoint.c
+@@ -20,9 +20,9 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ #include 
+ #include 
++#include 
+ 
+ /*
+  * Unlink a buffer from a transaction checkpoint list.
+@@ -358,8 +358,7 @@ int jbd2_log_do_checkpoint(journal_t *journal)
+ 	 * journal straight away.
+ 	 */
+ 	result = jbd2_cleanup_journal_tail(journal);
+-	trace_mark(jbd2_checkpoint, "dev %s need_checkpoint %d",
+-		   journal->j_devname, result);
++	trace_jbd2_checkpoint(journal, result);
+ 	jbd_debug(1, "cleanup_journal_tail returned %d\n", result);
+ 	if (result <= 0)
+ 		return result;
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index 0b7d3b8226fd..7b4088b2364d 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -16,7 +16,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ #include 
+ #include 
+ #include 
+@@ -26,6 +25,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ /*
+  * Default IO end handler for temporary BJ_IO buffer_heads.
+@@ -253,6 +253,7 @@ static int journal_submit_data_buffers(journal_t *journal,
+ 		 * block allocation  with delalloc. We need to write
+ 		 * only allocated blocks here.
+ 		 */
++		trace_jbd2_submit_inode_data(jinode->i_vfs_inode);
+ 		err = journal_submit_inode_data_buffers(mapping);
+ 		if (!ret)
+ 			ret = err;
+@@ -394,8 +395,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	commit_transaction = journal->j_running_transaction;
+ 	J_ASSERT(commit_transaction->t_state == T_RUNNING);
+ 
+-	trace_mark(jbd2_start_commit, "dev %s transaction %d",
+-		   journal->j_devname, commit_transaction->t_tid);
++	trace_jbd2_start_commit(journal, commit_transaction);
+ 	jbd_debug(1, "JBD: starting commit of transaction %d\n",
+ 			commit_transaction->t_tid);
+ 
+@@ -409,6 +409,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	 */
+ 	if (commit_transaction->t_synchronous_commit)
+ 		write_op = WRITE_SYNC_PLUG;
++	trace_jbd2_commit_locking(journal, commit_transaction);
+ 	stats.u.run.rs_wait = commit_transaction->t_max_wait;
+ 	stats.u.run.rs_locked = jiffies;
+ 	stats.u.run.rs_running = jbd2_time_diff(commit_transaction->t_start,
+@@ -484,6 +485,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	 */
+ 	jbd2_journal_switch_revoke_table(journal);
+ 
++	trace_jbd2_commit_flushing(journal, commit_transaction);
+ 	stats.u.run.rs_flushing = jiffies;
+ 	stats.u.run.rs_locked = jbd2_time_diff(stats.u.run.rs_locked,
+ 					       stats.u.run.rs_flushing);
+@@ -520,6 +522,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	commit_transaction->t_state = T_COMMIT;
+ 	spin_unlock(&journal->j_state_lock);
+ 
++	trace_jbd2_commit_logging(journal, commit_transaction);
+ 	stats.u.run.rs_logging = jiffies;
+ 	stats.u.run.rs_flushing = jbd2_time_diff(stats.u.run.rs_flushing,
+ 						 stats.u.run.rs_logging);
+@@ -1054,9 +1057,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	if (journal->j_commit_callback)
+ 		journal->j_commit_callback(journal, commit_transaction);
+ 
+-	trace_mark(jbd2_end_commit, "dev %s transaction %d head %d",
+-		   journal->j_devname, commit_transaction->t_tid,
+-		   journal->j_tail_sequence);
++	trace_jbd2_end_commit(journal, commit_transaction);
+ 	jbd_debug(1, "JBD: commit %d complete, head %d\n",
+ 		  journal->j_commit_sequence, journal->j_tail_sequence);
+ 	if (to_free)
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 62be7d294ec2..18bfd5dab642 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -38,6 +38,10 @@
+ #include 
+ #include 
+ #include 
++#include 
++
++#define CREATE_TRACE_POINTS
++#include 
+ 
+ #include 
+ #include 
+@@ -2377,6 +2381,71 @@ static void __exit journal_exit(void)
+ 	jbd2_journal_destroy_caches();
+ }
+ 
++/* 
++ * jbd2_dev_to_name is a utility function used by the jbd2 and ext4 
++ * tracing infrastructure to map a dev_t to a device name.
++ *
++ * The caller should use rcu_read_lock() in order to make sure the
++ * device name stays valid until its done with it.  We use
++ * rcu_read_lock() as well to make sure we're safe in case the caller
++ * gets sloppy, and because rcu_read_lock() is cheap and can be safely
++ * nested.
++ */
++struct devname_cache {
++	struct rcu_head	rcu;
++	dev_t		device;
++	char		devname[BDEVNAME_SIZE];
++};
++#define CACHE_SIZE_BITS 6
++static struct devname_cache *devcache[1 << CACHE_SIZE_BITS];
++static DEFINE_SPINLOCK(devname_cache_lock);
++
++static void free_devcache(struct rcu_head *rcu)
++{
++	kfree(rcu);
++}
++
++const char *jbd2_dev_to_name(dev_t device)
++{
++	int	i = hash_32(device, CACHE_SIZE_BITS);
++	char	*ret;
++	struct block_device *bd;
++
++	rcu_read_lock();
++	if (devcache[i] && devcache[i]->device == device) {
++		ret = devcache[i]->devname;
++		rcu_read_unlock();
++		return ret;
++	}
++	rcu_read_unlock();
++
++	spin_lock(&devname_cache_lock);
++	if (devcache[i]) {
++		if (devcache[i]->device == device) {
++			ret = devcache[i]->devname;
++			spin_unlock(&devname_cache_lock);
++			return ret;
++		}
++		call_rcu(&devcache[i]->rcu, free_devcache);
++	}
++	devcache[i] = kmalloc(sizeof(struct devname_cache), GFP_KERNEL);
++	if (!devcache[i]) {
++		spin_unlock(&devname_cache_lock);
++		return "NODEV-ALLOCFAILURE"; /* Something non-NULL */
++	}
++	devcache[i]->device = device;
++	bd = bdget(device);
++	if (bd) {
++		bdevname(bd, devcache[i]->devname);
++		bdput(bd);
++	} else
++		__bdevname(device, devcache[i]->devname);
++	ret = devcache[i]->devname;
++	spin_unlock(&devname_cache_lock);
++	return ret;
++}
++EXPORT_SYMBOL(jbd2_dev_to_name);
++
+ MODULE_LICENSE("GPL");
+ module_init(journal_init);
+ module_exit(journal_exit);
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index cc02393bfce8..d97eb652d6ca 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -1315,6 +1315,12 @@ extern int jbd_blocks_per_page(struct inode *inode);
+ #define BUFFER_TRACE2(bh, bh2, info)	do {} while (0)
+ #define JBUFFER_TRACE(jh, info)	do {} while (0)
+ 
++/* 
++ * jbd2_dev_to_name is a utility function used by the jbd2 and ext4 
++ * tracing infrastructure to map a dev_t to a device name.
++ */
++extern const char *jbd2_dev_to_name(dev_t device);
++
+ #endif	/* __KERNEL__ */
+ 
+ #endif	/* _LINUX_JBD2_H */
+diff --git a/include/trace/events/jbd2.h b/include/trace/events/jbd2.h
+new file mode 100644
+index 000000000000..845b0b4b48fd
+--- /dev/null
++++ b/include/trace/events/jbd2.h
+@@ -0,0 +1,168 @@
++#if !defined(_TRACE_JBD2_H) || defined(TRACE_HEADER_MULTI_READ)
++#define _TRACE_JBD2_H
++
++#include 
++#include 
++
++#undef TRACE_SYSTEM
++#define TRACE_SYSTEM jbd2
++
++TRACE_EVENT(jbd2_checkpoint,
++
++	TP_PROTO(journal_t *journal, int result),
++
++	TP_ARGS(journal, result),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	int,	result			)
++	),
++
++	TP_fast_assign(
++		__entry->dev		= journal->j_fs_dev->bd_dev;
++		__entry->result		= result;
++	),
++
++	TP_printk("dev %s result %d",
++		  jbd2_dev_to_name(__entry->dev), __entry->result)
++);
++
++TRACE_EVENT(jbd2_start_commit,
++
++	TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
++
++	TP_ARGS(journal, commit_transaction),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	char,	sync_commit		  )
++		__field(	int,	transaction		  )
++	),
++
++	TP_fast_assign(
++		__entry->dev		= journal->j_fs_dev->bd_dev;
++		__entry->sync_commit = commit_transaction->t_synchronous_commit;
++		__entry->transaction	= commit_transaction->t_tid;
++	),
++
++	TP_printk("dev %s transaction %d sync %d",
++		  jbd2_dev_to_name(__entry->dev), __entry->transaction,
++		  __entry->sync_commit)
++);
++
++TRACE_EVENT(jbd2_commit_locking,
++
++	TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
++
++	TP_ARGS(journal, commit_transaction),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	char,	sync_commit		  )
++		__field(	int,	transaction		  )
++	),
++
++	TP_fast_assign(
++		__entry->dev		= journal->j_fs_dev->bd_dev;
++		__entry->sync_commit = commit_transaction->t_synchronous_commit;
++		__entry->transaction	= commit_transaction->t_tid;
++	),
++
++	TP_printk("dev %s transaction %d sync %d",
++		  jbd2_dev_to_name(__entry->dev), __entry->transaction,
++		  __entry->sync_commit)
++);
++
++TRACE_EVENT(jbd2_commit_flushing,
++
++	TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
++
++	TP_ARGS(journal, commit_transaction),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	char,	sync_commit		  )
++		__field(	int,	transaction		  )
++	),
++
++	TP_fast_assign(
++		__entry->dev		= journal->j_fs_dev->bd_dev;
++		__entry->sync_commit = commit_transaction->t_synchronous_commit;
++		__entry->transaction	= commit_transaction->t_tid;
++	),
++
++	TP_printk("dev %s transaction %d sync %d",
++		  jbd2_dev_to_name(__entry->dev), __entry->transaction,
++		  __entry->sync_commit)
++);
++
++TRACE_EVENT(jbd2_commit_logging,
++
++	TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
++
++	TP_ARGS(journal, commit_transaction),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	char,	sync_commit		  )
++		__field(	int,	transaction		  )
++	),
++
++	TP_fast_assign(
++		__entry->dev		= journal->j_fs_dev->bd_dev;
++		__entry->sync_commit = commit_transaction->t_synchronous_commit;
++		__entry->transaction	= commit_transaction->t_tid;
++	),
++
++	TP_printk("dev %s transaction %d sync %d",
++		  jbd2_dev_to_name(__entry->dev), __entry->transaction,
++		  __entry->sync_commit)
++);
++
++TRACE_EVENT(jbd2_end_commit,
++	TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
++
++	TP_ARGS(journal, commit_transaction),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	char,	sync_commit		  )
++		__field(	int,	transaction		  )
++		__field(	int,	head		  	  )
++	),
++
++	TP_fast_assign(
++		__entry->dev		= journal->j_fs_dev->bd_dev;
++		__entry->sync_commit = commit_transaction->t_synchronous_commit;
++		__entry->transaction	= commit_transaction->t_tid;
++		__entry->head		= journal->j_tail_sequence;
++	),
++
++	TP_printk("dev %s transaction %d sync %d head %d",
++		  jbd2_dev_to_name(__entry->dev), __entry->transaction,
++		  __entry->sync_commit, __entry->head)
++);
++
++TRACE_EVENT(jbd2_submit_inode_data,
++	TP_PROTO(struct inode *inode),
++
++	TP_ARGS(inode),
++
++	TP_STRUCT__entry(
++		__field(	dev_t,	dev			)
++		__field(	ino_t,	ino			)
++	),
++
++	TP_fast_assign(
++		__entry->dev	= inode->i_sb->s_dev;
++		__entry->ino	= inode->i_ino;
++	),
++
++	TP_printk("dev %s ino %lu",
++		  jbd2_dev_to_name(__entry->dev), __entry->ino)
++);
++
++#endif /* _TRACE_JBD2_H */
++
++/* This part must be outside protection */
++#include 

commit 32ed5058ce90024efcd811254b4b1de0468099df
+Author: Theodore Ts'o 
+Date:   Sat Apr 25 22:53:39 2009 -0400
+
+    ext4: Replace lock/unlock_super() with an explicit lock for resizing
+    
+    Use a separate lock to protect s_groups_count and the other block
+    group descriptors which get changed via an on-line resize operation,
+    so we can stop overloading the use of lock_super().
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4_sb.h b/fs/ext4/ext4_sb.h
+index 4bda2f75d426..2d36223d5f57 100644
+--- a/fs/ext4/ext4_sb.h
++++ b/fs/ext4/ext4_sb.h
+@@ -72,6 +72,7 @@ struct ext4_sb_info {
+ 	struct journal_s *s_journal;
+ 	struct list_head s_orphan;
+ 	struct mutex s_orphan_lock;
++	struct mutex s_resize_lock;
+ 	unsigned long s_commit_interval;
+ 	u32 s_max_batch_time;
+ 	u32 s_min_batch_time;
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 546c7dd869e1..e8ded13b5cb1 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -193,7 +193,7 @@ static int setup_new_group_blocks(struct super_block *sb,
+ 	if (IS_ERR(handle))
+ 		return PTR_ERR(handle);
+ 
+-	lock_super(sb);
++	mutex_lock(&sbi->s_resize_lock);
+ 	if (input->group != sbi->s_groups_count) {
+ 		err = -EBUSY;
+ 		goto exit_journal;
+@@ -302,7 +302,7 @@ static int setup_new_group_blocks(struct super_block *sb,
+ 	brelse(bh);
+ 
+ exit_journal:
+-	unlock_super(sb);
++	mutex_unlock(&sbi->s_resize_lock);
+ 	if ((err2 = ext4_journal_stop(handle)) && !err)
+ 		err = err2;
+ 
+@@ -643,11 +643,12 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
+  * important part is that the new block and inode counts are in the backup
+  * superblocks, and the location of the new group metadata in the GDT backups.
+  *
+- * We do not need lock_super() for this, because these blocks are not
+- * otherwise touched by the filesystem code when it is mounted.  We don't
+- * need to worry about last changing from sbi->s_groups_count, because the
+- * worst that can happen is that we do not copy the full number of backups
+- * at this time.  The resize which changed s_groups_count will backup again.
++ * We do not need take the s_resize_lock for this, because these
++ * blocks are not otherwise touched by the filesystem code when it is
++ * mounted.  We don't need to worry about last changing from
++ * sbi->s_groups_count, because the worst that can happen is that we
++ * do not copy the full number of backups at this time.  The resize
++ * which changed s_groups_count will backup again.
+  */
+ static void update_backups(struct super_block *sb,
+ 			   int blk_off, char *data, int size)
+@@ -809,7 +810,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
+ 		goto exit_put;
+ 	}
+ 
+-	lock_super(sb);
++	mutex_lock(&sbi->s_resize_lock);
+ 	if (input->group != sbi->s_groups_count) {
+ 		ext4_warning(sb, __func__,
+ 			     "multiple resizers run on filesystem!");
+@@ -840,7 +841,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
+         /*
+          * OK, now we've set up the new group.  Time to make it active.
+          *
+-         * Current kernels don't lock all allocations via lock_super(),
++         * We do not lock all allocations via s_resize_lock
+          * so we have to be safe wrt. concurrent accesses the group
+          * data.  So we need to be careful to set all of the relevant
+          * group descriptor data etc. *before* we enable the group.
+@@ -900,12 +901,12 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
+ 	 *
+ 	 * The precise rules we use are:
+ 	 *
+-	 * * Writers of s_groups_count *must* hold lock_super
++	 * * Writers of s_groups_count *must* hold s_resize_lock
+ 	 * AND
+ 	 * * Writers must perform a smp_wmb() after updating all dependent
+ 	 *   data and before modifying the groups count
+ 	 *
+-	 * * Readers must hold lock_super() over the access
++	 * * Readers must hold s_resize_lock over the access
+ 	 * OR
+ 	 * * Readers must perform an smp_rmb() after reading the groups count
+ 	 *   and before reading any dependent data.
+@@ -948,7 +949,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
+ 	sb->s_dirt = 1;
+ 
+ exit_journal:
+-	unlock_super(sb);
++	mutex_unlock(&sbi->s_resize_lock);
+ 	if ((err2 = ext4_journal_stop(handle)) && !err)
+ 		err = err2;
+ 	if (!err) {
+@@ -986,7 +987,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
+ 
+ 	/* We don't need to worry about locking wrt other resizers just
+ 	 * yet: we're going to revalidate es->s_blocks_count after
+-	 * taking lock_super() below. */
++	 * taking the s_resize_lock below. */
+ 	o_blocks_count = ext4_blocks_count(es);
+ 	o_groups_count = EXT4_SB(sb)->s_groups_count;
+ 
+@@ -1056,11 +1057,11 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
+ 		goto exit_put;
+ 	}
+ 
+-	lock_super(sb);
++	mutex_lock(&EXT4_SB(sb)->s_resize_lock);
+ 	if (o_blocks_count != ext4_blocks_count(es)) {
+ 		ext4_warning(sb, __func__,
+ 			     "multiple resizers run on filesystem!");
+-		unlock_super(sb);
++		mutex_unlock(&EXT4_SB(sb)->s_resize_lock);
+ 		ext4_journal_stop(handle);
+ 		err = -EBUSY;
+ 		goto exit_put;
+@@ -1070,14 +1071,14 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
+ 						 EXT4_SB(sb)->s_sbh))) {
+ 		ext4_warning(sb, __func__,
+ 			     "error %d on journal write access", err);
+-		unlock_super(sb);
++		mutex_unlock(&EXT4_SB(sb)->s_resize_lock);
+ 		ext4_journal_stop(handle);
+ 		goto exit_put;
+ 	}
+ 	ext4_blocks_count_set(es, o_blocks_count + add);
+ 	ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh);
+ 	sb->s_dirt = 1;
+-	unlock_super(sb);
++	mutex_unlock(&EXT4_SB(sb)->s_resize_lock);
+ 	ext4_debug("freeing blocks %llu through %llu\n", o_blocks_count,
+ 		   o_blocks_count + add);
+ 	/* We add the blocks to the bitmap and set the group need init bit */
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 7f43fde9554b..1fbf0906ae2e 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2646,6 +2646,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ #endif
+ 	INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
+ 	mutex_init(&sbi->s_orphan_lock);
++	mutex_init(&sbi->s_resize_lock);
+ 
+ 	sb->s_root = NULL;
+ 

commit 3b9d4ed26680771295d904a6b83e88e620780893
+Author: Theodore Ts'o 
+Date:   Sat Apr 25 22:54:04 2009 -0400
+
+    ext4: Replace lock/unlock_super() with an explicit lock for the orphan list
+    
+    Use a separate lock to protect the orphan list, so we can stop
+    overloading the use of lock_super().
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4_sb.h b/fs/ext4/ext4_sb.h
+index 57b71fefbccf..4bda2f75d426 100644
+--- a/fs/ext4/ext4_sb.h
++++ b/fs/ext4/ext4_sb.h
+@@ -71,6 +71,7 @@ struct ext4_sb_info {
+ 	struct inode *s_journal_inode;
+ 	struct journal_s *s_journal;
+ 	struct list_head s_orphan;
++	struct mutex s_orphan_lock;
+ 	unsigned long s_commit_interval;
+ 	u32 s_max_batch_time;
+ 	u32 s_min_batch_time;
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 22098e1cd085..8018e49a7287 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1997,7 +1997,7 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode)
+ 	if (!ext4_handle_valid(handle))
+ 		return 0;
+ 
+-	lock_super(sb);
++	mutex_lock(&EXT4_SB(sb)->s_orphan_lock);
+ 	if (!list_empty(&EXT4_I(inode)->i_orphan))
+ 		goto out_unlock;
+ 
+@@ -2006,9 +2006,13 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode)
+ 
+ 	/* @@@ FIXME: Observation from aviro:
+ 	 * I think I can trigger J_ASSERT in ext4_orphan_add().  We block
+-	 * here (on lock_super()), so race with ext4_link() which might bump
++	 * here (on s_orphan_lock), so race with ext4_link() which might bump
+ 	 * ->i_nlink. For, say it, character device. Not a regular file,
+ 	 * not a directory, not a symlink and ->i_nlink > 0.
++	 *
++	 * tytso, 4/25/2009: I'm not sure how that could happen;
++	 * shouldn't the fs core protect us from these sort of
++	 * unlink()/link() races?
+ 	 */
+ 	J_ASSERT((S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+ 		  S_ISLNK(inode->i_mode)) || inode->i_nlink == 0);
+@@ -2045,7 +2049,7 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode)
+ 	jbd_debug(4, "orphan inode %lu will point to %d\n",
+ 			inode->i_ino, NEXT_ORPHAN(inode));
+ out_unlock:
+-	unlock_super(sb);
++	mutex_unlock(&EXT4_SB(sb)->s_orphan_lock);
+ 	ext4_std_error(inode->i_sb, err);
+ 	return err;
+ }
+@@ -2066,11 +2070,9 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode)
+ 	if (!ext4_handle_valid(handle))
+ 		return 0;
+ 
+-	lock_super(inode->i_sb);
+-	if (list_empty(&ei->i_orphan)) {
+-		unlock_super(inode->i_sb);
+-		return 0;
+-	}
++	mutex_lock(&EXT4_SB(inode->i_sb)->s_orphan_lock);
++	if (list_empty(&ei->i_orphan))
++		goto out;
+ 
+ 	ino_next = NEXT_ORPHAN(inode);
+ 	prev = ei->i_orphan.prev;
+@@ -2120,7 +2122,7 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode)
+ out_err:
+ 	ext4_std_error(inode->i_sb, err);
+ out:
+-	unlock_super(inode->i_sb);
++	mutex_unlock(&EXT4_SB(inode->i_sb)->s_orphan_lock);
+ 	return err;
+ 
+ out_brelse:
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 45d0ada9bfce..7f43fde9554b 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2645,6 +2645,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	sb->dq_op = &ext4_quota_operations;
+ #endif
+ 	INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
++	mutex_init(&sbi->s_orphan_lock);
+ 
+ 	sb->s_root = NULL;
+ 

commit a63c9eb2ce6f5028da90f282798232c4f398ceb8
+Author: Theodore Ts'o 
+Date:   Fri May 1 01:59:42 2009 -0400
+
+    ext4: ext4_mark_recovery_complete() doesn't need to use lock_super
+    
+    The function ext4_mark_recovery_complete() is called from two call
+    paths: either (a) while mounting the filesystem, in which case there's
+    no danger of any other CPU calling write_super() until the mount is
+    completed, and (b) while remounting the filesystem read-write, in
+    which case the fs core has already locked the superblock.  This also
+    allows us to take out a very vile unlock_super()/lock_super() pair in
+    ext4_remount().
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index e3b35f26d5fe..45d0ada9bfce 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3219,13 +3219,11 @@ static void ext4_mark_recovery_complete(struct super_block *sb,
+ 	if (jbd2_journal_flush(journal) < 0)
+ 		goto out;
+ 
+-	lock_super(sb);
+ 	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER) &&
+ 	    sb->s_flags & MS_RDONLY) {
+ 		EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+ 		ext4_commit_super(sb, 1);
+ 	}
+-	unlock_super(sb);
+ 
+ out:
+ 	jbd2_journal_unlock_updates(journal);
+@@ -3436,15 +3434,8 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 			    (sbi->s_mount_state & EXT4_VALID_FS))
+ 				es->s_state = cpu_to_le16(sbi->s_mount_state);
+ 
+-			/*
+-			 * We have to unlock super so that we can wait for
+-			 * transactions.
+-			 */
+-			if (sbi->s_journal) {
+-				unlock_super(sb);
++			if (sbi->s_journal)
+ 				ext4_mark_recovery_complete(sb, es);
+-				lock_super(sb);
+-			}
+ 		} else {
+ 			int ret;
+ 			if ((ret = EXT4_HAS_RO_COMPAT_FEATURE(sb,

commit 114e9fc90703bd6aac0229fb559e97caa6c49770
+Author: Theodore Ts'o 
+Date:   Sat Apr 25 15:48:07 2009 -0400
+
+    ext4: Remove outdated comment about lock_super()
+    
+    ext4_fill_super() is no longer called by read_super(), and it is no
+    longer called with the superblock locked.  The
+    unlock_super()/lock_super() is no longer present, so this comment is
+    entirely superfluous.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index fcd7b24c6df3..e3b35f26d5fe 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2828,14 +2828,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		goto failed_mount4;
+ 	};
+ 
+-	/*
+-	 * akpm: core read_super() calls in here with the superblock locked.
+-	 * That deadlocks, because orphan cleanup needs to lock the superblock
+-	 * in numerous places.  Here we just pop the lock - it's relatively
+-	 * harmless, because we are now ready to accept write_super() requests,
+-	 * and aviro says that's the only reason for hanging onto the
+-	 * superblock lock.
+-	 */
+ 	EXT4_SB(sb)->s_mount_state |= EXT4_ORPHAN_FS;
+ 	ext4_orphan_cleanup(sb, es);
+ 	EXT4_SB(sb)->s_mount_state &= ~EXT4_ORPHAN_FS;

commit 8df9675f8b498d0bfa1f0b5b06f56bf1ff366dd5
+Author: Theodore Ts'o 
+Date:   Fri May 1 08:50:38 2009 -0400
+
+    ext4: Avoid races caused by on-line resizing and SMP memory reordering
+    
+    Ext4's on-line resizing adds a new block group and then, only at the
+    last step adjusts s_groups_count.  However, it's possible on SMP
+    systems that another CPU could see the updated the s_group_count and
+    not see the newly initialized data structures for the just-added block
+    group.  For this reason, it's important to insert a SMP read barrier
+    after reading s_groups_count and before reading any (for example) the
+    new block group descriptors allowed by the increased value of
+    s_groups_count.
+    
+    Unfortunately, we rather blatently violate this locking protocol
+    documented in fs/ext4/resize.c.  Fortunately, (1) on-line resizes
+    happen relatively rarely, and (2) it seems rare that the filesystem
+    code will immediately try to use just-added block group before any
+    memory ordering issues resolve themselves.  So apparently problems
+    here are relatively hard to hit, since ext3 has been vulnerable to the
+    same issue for years with no one apparently complaining.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 53c72ad85877..a5ba039850c5 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -88,6 +88,7 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
+ 		 ext4_group_t block_group, struct ext4_group_desc *gdp)
+ {
+ 	int bit, bit_max;
++	ext4_group_t ngroups = ext4_get_groups_count(sb);
+ 	unsigned free_blocks, group_blocks;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 
+@@ -123,7 +124,7 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
+ 		bit_max += ext4_bg_num_gdb(sb, block_group);
+ 	}
+ 
+-	if (block_group == sbi->s_groups_count - 1) {
++	if (block_group == ngroups - 1) {
+ 		/*
+ 		 * Even though mke2fs always initialize first and last group
+ 		 * if some other tool enabled the EXT4_BG_BLOCK_UNINIT we need
+@@ -131,7 +132,7 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
+ 		 */
+ 		group_blocks = ext4_blocks_count(sbi->s_es) -
+ 			le32_to_cpu(sbi->s_es->s_first_data_block) -
+-			(EXT4_BLOCKS_PER_GROUP(sb) * (sbi->s_groups_count - 1));
++			(EXT4_BLOCKS_PER_GROUP(sb) * (ngroups - 1));
+ 	} else {
+ 		group_blocks = EXT4_BLOCKS_PER_GROUP(sb);
+ 	}
+@@ -205,18 +206,18 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
+ {
+ 	unsigned int group_desc;
+ 	unsigned int offset;
++	ext4_group_t ngroups = ext4_get_groups_count(sb);
+ 	struct ext4_group_desc *desc;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 
+-	if (block_group >= sbi->s_groups_count) {
++	if (block_group >= ngroups) {
+ 		ext4_error(sb, "ext4_get_group_desc",
+ 			   "block_group >= groups_count - "
+ 			   "block_group = %u, groups_count = %u",
+-			   block_group, sbi->s_groups_count);
++			   block_group, ngroups);
+ 
+ 		return NULL;
+ 	}
+-	smp_rmb();
+ 
+ 	group_desc = block_group >> EXT4_DESC_PER_BLOCK_BITS(sb);
+ 	offset = block_group & (EXT4_DESC_PER_BLOCK(sb) - 1);
+@@ -665,7 +666,7 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
+ 	ext4_fsblk_t desc_count;
+ 	struct ext4_group_desc *gdp;
+ 	ext4_group_t i;
+-	ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count;
++	ext4_group_t ngroups = ext4_get_groups_count(sb);
+ #ifdef EXT4FS_DEBUG
+ 	struct ext4_super_block *es;
+ 	ext4_fsblk_t bitmap_count;
+@@ -677,7 +678,6 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
+ 	bitmap_count = 0;
+ 	gdp = NULL;
+ 
+-	smp_rmb();
+ 	for (i = 0; i < ngroups; i++) {
+ 		gdp = ext4_get_group_desc(sb, i, NULL);
+ 		if (!gdp)
+@@ -700,7 +700,6 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
+ 	return bitmap_count;
+ #else
+ 	desc_count = 0;
+-	smp_rmb();
+ 	for (i = 0; i < ngroups; i++) {
+ 		gdp = ext4_get_group_desc(sb, i, NULL);
+ 		if (!gdp)
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index d0f15ef56de1..02ec44bf38e6 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1228,6 +1228,18 @@ struct ext4_group_info *ext4_get_group_info(struct super_block *sb,
+ 	 return grp_info[indexv][indexh];
+ }
+ 
++/*
++ * Reading s_groups_count requires using smp_rmb() afterwards.  See
++ * the locking protocol documented in the comments of ext4_group_add()
++ * in resize.c
++ */
++static inline ext4_group_t ext4_get_groups_count(struct super_block *sb)
++{
++	ext4_group_t	ngroups = EXT4_SB(sb)->s_groups_count;
++
++	smp_rmb();
++	return ngroups;
++}
+ 
+ static inline ext4_group_t ext4_flex_group(struct ext4_sb_info *sbi,
+ 					     ext4_group_t block_group)
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index f18e0a08a6b5..55ba419ca00b 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -316,7 +316,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
+ static int find_group_dir(struct super_block *sb, struct inode *parent,
+ 				ext4_group_t *best_group)
+ {
+-	ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count;
++	ext4_group_t ngroups = ext4_get_groups_count(sb);
+ 	unsigned int freei, avefreei;
+ 	struct ext4_group_desc *desc, *best_desc = NULL;
+ 	ext4_group_t group;
+@@ -353,7 +353,7 @@ static int find_group_flex(struct super_block *sb, struct inode *parent,
+ 	struct flex_groups *flex_group = sbi->s_flex_groups;
+ 	ext4_group_t parent_group = EXT4_I(parent)->i_block_group;
+ 	ext4_group_t parent_fbg_group = ext4_flex_group(sbi, parent_group);
+-	ext4_group_t ngroups = sbi->s_groups_count;
++	ext4_group_t ngroups = ext4_get_groups_count(sb);
+ 	int flex_size = ext4_flex_bg_size(sbi);
+ 	ext4_group_t best_flex = parent_fbg_group;
+ 	int blocks_per_flex = sbi->s_blocks_per_group * flex_size;
+@@ -362,7 +362,7 @@ static int find_group_flex(struct super_block *sb, struct inode *parent,
+ 	ext4_group_t n_fbg_groups;
+ 	ext4_group_t i;
+ 
+-	n_fbg_groups = (sbi->s_groups_count + flex_size - 1) >>
++	n_fbg_groups = (ngroups + flex_size - 1) >>
+ 		sbi->s_log_groups_per_flex;
+ 
+ find_close_to_parent:
+@@ -478,20 +478,21 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
+ {
+ 	ext4_group_t parent_group = EXT4_I(parent)->i_block_group;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-	ext4_group_t ngroups = sbi->s_groups_count;
++	ext4_group_t real_ngroups = ext4_get_groups_count(sb);
+ 	int inodes_per_group = EXT4_INODES_PER_GROUP(sb);
+ 	unsigned int freei, avefreei;
+ 	ext4_fsblk_t freeb, avefreeb;
+ 	unsigned int ndirs;
+ 	int max_dirs, min_inodes;
+ 	ext4_grpblk_t min_blocks;
+-	ext4_group_t i, grp, g;
++	ext4_group_t i, grp, g, ngroups;
+ 	struct ext4_group_desc *desc;
+ 	struct orlov_stats stats;
+ 	int flex_size = ext4_flex_bg_size(sbi);
+ 
++	ngroups = real_ngroups;
+ 	if (flex_size > 1) {
+-		ngroups = (ngroups + flex_size - 1) >>
++		ngroups = (real_ngroups + flex_size - 1) >>
+ 			sbi->s_log_groups_per_flex;
+ 		parent_group >>= sbi->s_log_groups_per_flex;
+ 	}
+@@ -543,7 +544,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
+ 		 */
+ 		grp *= flex_size;
+ 		for (i = 0; i < flex_size; i++) {
+-			if (grp+i >= sbi->s_groups_count)
++			if (grp+i >= real_ngroups)
+ 				break;
+ 			desc = ext4_get_group_desc(sb, grp+i, NULL);
+ 			if (desc && ext4_free_inodes_count(sb, desc)) {
+@@ -583,7 +584,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
+ 	}
+ 
+ fallback:
+-	ngroups = sbi->s_groups_count;
++	ngroups = real_ngroups;
+ 	avefreei = freei / ngroups;
+ fallback_retry:
+ 	parent_group = EXT4_I(parent)->i_block_group;
+@@ -613,9 +614,8 @@ static int find_group_other(struct super_block *sb, struct inode *parent,
+ 			    ext4_group_t *group, int mode)
+ {
+ 	ext4_group_t parent_group = EXT4_I(parent)->i_block_group;
+-	ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count;
++	ext4_group_t i, last, ngroups = ext4_get_groups_count(sb);
+ 	struct ext4_group_desc *desc;
+-	ext4_group_t i, last;
+ 	int flex_size = ext4_flex_bg_size(EXT4_SB(sb));
+ 
+ 	/*
+@@ -799,11 +799,10 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
+ 	struct super_block *sb;
+ 	struct buffer_head *inode_bitmap_bh = NULL;
+ 	struct buffer_head *group_desc_bh;
+-	ext4_group_t group = 0;
++	ext4_group_t ngroups, group = 0;
+ 	unsigned long ino = 0;
+ 	struct inode *inode;
+ 	struct ext4_group_desc *gdp = NULL;
+-	struct ext4_super_block *es;
+ 	struct ext4_inode_info *ei;
+ 	struct ext4_sb_info *sbi;
+ 	int ret2, err = 0;
+@@ -818,15 +817,14 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
+ 		return ERR_PTR(-EPERM);
+ 
+ 	sb = dir->i_sb;
++	ngroups = ext4_get_groups_count(sb);
+ 	trace_mark(ext4_request_inode, "dev %s dir %lu mode %d", sb->s_id,
+ 		   dir->i_ino, mode);
+ 	inode = new_inode(sb);
+ 	if (!inode)
+ 		return ERR_PTR(-ENOMEM);
+ 	ei = EXT4_I(inode);
+-
+ 	sbi = EXT4_SB(sb);
+-	es = sbi->s_es;
+ 
+ 	if (sbi->s_log_groups_per_flex && test_opt(sb, OLDALLOC)) {
+ 		ret2 = find_group_flex(sb, dir, &group);
+@@ -856,7 +854,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
+ 	if (ret2 == -1)
+ 		goto out;
+ 
+-	for (i = 0; i < sbi->s_groups_count; i++) {
++	for (i = 0; i < ngroups; i++) {
+ 		err = -EIO;
+ 
+ 		gdp = ext4_get_group_desc(sb, group, &group_desc_bh);
+@@ -917,7 +915,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
+ 		 * group descriptor metadata has not yet been updated.
+ 		 * So we just go onto the next blockgroup.
+ 		 */
+-		if (++group == sbi->s_groups_count)
++		if (++group == ngroups)
+ 			group = 0;
+ 	}
+ 	err = -ENOSPC;
+@@ -1158,7 +1156,7 @@ unsigned long ext4_count_free_inodes(struct super_block *sb)
+ {
+ 	unsigned long desc_count;
+ 	struct ext4_group_desc *gdp;
+-	ext4_group_t i;
++	ext4_group_t i, ngroups = ext4_get_groups_count(sb);
+ #ifdef EXT4FS_DEBUG
+ 	struct ext4_super_block *es;
+ 	unsigned long bitmap_count, x;
+@@ -1168,7 +1166,7 @@ unsigned long ext4_count_free_inodes(struct super_block *sb)
+ 	desc_count = 0;
+ 	bitmap_count = 0;
+ 	gdp = NULL;
+-	for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) {
++	for (i = 0; i < ngroups; i++) {
+ 		gdp = ext4_get_group_desc(sb, i, NULL);
+ 		if (!gdp)
+ 			continue;
+@@ -1190,7 +1188,7 @@ unsigned long ext4_count_free_inodes(struct super_block *sb)
+ 	return desc_count;
+ #else
+ 	desc_count = 0;
+-	for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) {
++	for (i = 0; i < ngroups; i++) {
+ 		gdp = ext4_get_group_desc(sb, i, NULL);
+ 		if (!gdp)
+ 			continue;
+@@ -1205,9 +1203,9 @@ unsigned long ext4_count_free_inodes(struct super_block *sb)
+ unsigned long ext4_count_dirs(struct super_block * sb)
+ {
+ 	unsigned long count = 0;
+-	ext4_group_t i;
++	ext4_group_t i, ngroups = ext4_get_groups_count(sb);
+ 
+-	for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) {
++	for (i = 0; i < ngroups; i++) {
+ 		struct ext4_group_desc *gdp = ext4_get_group_desc(sb, i, NULL);
+ 		if (!gdp)
+ 			continue;
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 96f3366f59f6..4e7f363e3030 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4965,7 +4965,8 @@ static int ext4_index_trans_blocks(struct inode *inode, int nrblocks, int chunk)
+  */
+ int ext4_meta_trans_blocks(struct inode *inode, int nrblocks, int chunk)
+ {
+-	int groups, gdpblocks;
++	ext4_group_t groups, ngroups = ext4_get_groups_count(inode->i_sb);
++	int gdpblocks;
+ 	int idxblocks;
+ 	int ret = 0;
+ 
+@@ -4992,8 +4993,8 @@ int ext4_meta_trans_blocks(struct inode *inode, int nrblocks, int chunk)
+ 		groups += nrblocks;
+ 
+ 	gdpblocks = groups;
+-	if (groups > EXT4_SB(inode->i_sb)->s_groups_count)
+-		groups = EXT4_SB(inode->i_sb)->s_groups_count;
++	if (groups > ngroups)
++		groups = ngroups;
+ 	if (groups > EXT4_SB(inode->i_sb)->s_gdb_count)
+ 		gdpblocks = EXT4_SB(inode->i_sb)->s_gdb_count;
+ 
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index f871677a7984..c3af9e6b6668 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -739,6 +739,7 @@ static void ext4_mb_generate_buddy(struct super_block *sb,
+ 
+ static int ext4_mb_init_cache(struct page *page, char *incore)
+ {
++	ext4_group_t ngroups;
+ 	int blocksize;
+ 	int blocks_per_page;
+ 	int groups_per_page;
+@@ -757,6 +758,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
+ 
+ 	inode = page->mapping->host;
+ 	sb = inode->i_sb;
++	ngroups = ext4_get_groups_count(sb);
+ 	blocksize = 1 << inode->i_blkbits;
+ 	blocks_per_page = PAGE_CACHE_SIZE / blocksize;
+ 
+@@ -780,7 +782,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
+ 	for (i = 0; i < groups_per_page; i++) {
+ 		struct ext4_group_desc *desc;
+ 
+-		if (first_group + i >= EXT4_SB(sb)->s_groups_count)
++		if (first_group + i >= ngroups)
+ 			break;
+ 
+ 		err = -EIO;
+@@ -852,7 +854,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
+ 		struct ext4_group_info *grinfo;
+ 
+ 		group = (first_block + i) >> 1;
+-		if (group >= EXT4_SB(sb)->s_groups_count)
++		if (group >= ngroups)
+ 			break;
+ 
+ 		/*
+@@ -1788,6 +1790,7 @@ int ext4_mb_get_buddy_cache_lock(struct super_block *sb, ext4_group_t group)
+ 	int block, pnum;
+ 	int blocks_per_page;
+ 	int groups_per_page;
++	ext4_group_t ngroups = ext4_get_groups_count(sb);
+ 	ext4_group_t first_group;
+ 	struct ext4_group_info *grp;
+ 
+@@ -1807,7 +1810,7 @@ int ext4_mb_get_buddy_cache_lock(struct super_block *sb, ext4_group_t group)
+ 	/* read all groups the page covers into the cache */
+ 	for (i = 0; i < groups_per_page; i++) {
+ 
+-		if ((first_group + i) >= EXT4_SB(sb)->s_groups_count)
++		if ((first_group + i) >= ngroups)
+ 			break;
+ 		grp = ext4_get_group_info(sb, first_group + i);
+ 		/* take all groups write allocation
+@@ -1945,8 +1948,7 @@ static int ext4_mb_init_group(struct super_block *sb, ext4_group_t group)
+ static noinline_for_stack int
+ ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
+ {
+-	ext4_group_t group;
+-	ext4_group_t i;
++	ext4_group_t ngroups, group, i;
+ 	int cr;
+ 	int err = 0;
+ 	int bsbits;
+@@ -1957,6 +1959,7 @@ ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
+ 
+ 	sb = ac->ac_sb;
+ 	sbi = EXT4_SB(sb);
++	ngroups = ext4_get_groups_count(sb);
+ 	BUG_ON(ac->ac_status == AC_STATUS_FOUND);
+ 
+ 	/* first, try the goal */
+@@ -2017,11 +2020,11 @@ ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
+ 		 */
+ 		group = ac->ac_g_ex.fe_group;
+ 
+-		for (i = 0; i < EXT4_SB(sb)->s_groups_count; group++, i++) {
++		for (i = 0; i < ngroups; group++, i++) {
+ 			struct ext4_group_info *grp;
+ 			struct ext4_group_desc *desc;
+ 
+-			if (group == EXT4_SB(sb)->s_groups_count)
++			if (group == ngroups)
+ 				group = 0;
+ 
+ 			/* quick check to skip empty groups */
+@@ -2315,12 +2318,10 @@ static struct file_operations ext4_mb_seq_history_fops = {
+ static void *ext4_mb_seq_groups_start(struct seq_file *seq, loff_t *pos)
+ {
+ 	struct super_block *sb = seq->private;
+-	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	ext4_group_t group;
+ 
+-	if (*pos < 0 || *pos >= sbi->s_groups_count)
++	if (*pos < 0 || *pos >= ext4_get_groups_count(sb))
+ 		return NULL;
+-
+ 	group = *pos + 1;
+ 	return (void *) ((unsigned long) group);
+ }
+@@ -2328,11 +2329,10 @@ static void *ext4_mb_seq_groups_start(struct seq_file *seq, loff_t *pos)
+ static void *ext4_mb_seq_groups_next(struct seq_file *seq, void *v, loff_t *pos)
+ {
+ 	struct super_block *sb = seq->private;
+-	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	ext4_group_t group;
+ 
+ 	++*pos;
+-	if (*pos < 0 || *pos >= sbi->s_groups_count)
++	if (*pos < 0 || *pos >= ext4_get_groups_count(sb))
+ 		return NULL;
+ 	group = *pos + 1;
+ 	return (void *) ((unsigned long) group);
+@@ -2587,6 +2587,7 @@ void ext4_mb_update_group_info(struct ext4_group_info *grp, ext4_grpblk_t add)
+ 
+ static int ext4_mb_init_backend(struct super_block *sb)
+ {
++	ext4_group_t ngroups = ext4_get_groups_count(sb);
+ 	ext4_group_t i;
+ 	int metalen;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+@@ -2598,7 +2599,7 @@ static int ext4_mb_init_backend(struct super_block *sb)
+ 	struct ext4_group_desc *desc;
+ 
+ 	/* This is the number of blocks used by GDT */
+-	num_meta_group_infos = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) -
++	num_meta_group_infos = (ngroups + EXT4_DESC_PER_BLOCK(sb) -
+ 				1) >> EXT4_DESC_PER_BLOCK_BITS(sb);
+ 
+ 	/*
+@@ -2644,7 +2645,7 @@ static int ext4_mb_init_backend(struct super_block *sb)
+ 	for (i = 0; i < num_meta_group_infos; i++) {
+ 		if ((i + 1) == num_meta_group_infos)
+ 			metalen = sizeof(*meta_group_info) *
+-				(sbi->s_groups_count -
++				(ngroups -
+ 					(i << EXT4_DESC_PER_BLOCK_BITS(sb)));
+ 		meta_group_info = kmalloc(metalen, GFP_KERNEL);
+ 		if (meta_group_info == NULL) {
+@@ -2655,7 +2656,7 @@ static int ext4_mb_init_backend(struct super_block *sb)
+ 		sbi->s_group_info[i] = meta_group_info;
+ 	}
+ 
+-	for (i = 0; i < sbi->s_groups_count; i++) {
++	for (i = 0; i < ngroups; i++) {
+ 		desc = ext4_get_group_desc(sb, i, NULL);
+ 		if (desc == NULL) {
+ 			printk(KERN_ERR
+@@ -2781,13 +2782,14 @@ static void ext4_mb_cleanup_pa(struct ext4_group_info *grp)
+ 
+ int ext4_mb_release(struct super_block *sb)
+ {
++	ext4_group_t ngroups = ext4_get_groups_count(sb);
+ 	ext4_group_t i;
+ 	int num_meta_group_infos;
+ 	struct ext4_group_info *grinfo;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 
+ 	if (sbi->s_group_info) {
+-		for (i = 0; i < sbi->s_groups_count; i++) {
++		for (i = 0; i < ngroups; i++) {
+ 			grinfo = ext4_get_group_info(sb, i);
+ #ifdef DOUBLE_CHECK
+ 			kfree(grinfo->bb_bitmap);
+@@ -2797,7 +2799,7 @@ int ext4_mb_release(struct super_block *sb)
+ 			ext4_unlock_group(sb, i);
+ 			kfree(grinfo);
+ 		}
+-		num_meta_group_infos = (sbi->s_groups_count +
++		num_meta_group_infos = (ngroups +
+ 				EXT4_DESC_PER_BLOCK(sb) - 1) >>
+ 			EXT4_DESC_PER_BLOCK_BITS(sb);
+ 		for (i = 0; i < num_meta_group_infos; i++)
+@@ -4121,7 +4123,7 @@ static void ext4_mb_return_to_preallocation(struct inode *inode,
+ static void ext4_mb_show_ac(struct ext4_allocation_context *ac)
+ {
+ 	struct super_block *sb = ac->ac_sb;
+-	ext4_group_t i;
++	ext4_group_t ngroups, i;
+ 
+ 	printk(KERN_ERR "EXT4-fs: Can't allocate:"
+ 			" Allocation context details:\n");
+@@ -4145,7 +4147,8 @@ static void ext4_mb_show_ac(struct ext4_allocation_context *ac)
+ 	printk(KERN_ERR "EXT4-fs: %lu scanned, %d found\n", ac->ac_ex_scanned,
+ 		ac->ac_found);
+ 	printk(KERN_ERR "EXT4-fs: groups: \n");
+-	for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) {
++	ngroups = ext4_get_groups_count(sb);
++	for (i = 0; i < ngroups; i++) {
+ 		struct ext4_group_info *grp = ext4_get_group_info(sb, i);
+ 		struct ext4_prealloc_space *pa;
+ 		ext4_grpblk_t start;
+@@ -4469,13 +4472,13 @@ static int ext4_mb_release_context(struct ext4_allocation_context *ac)
+ 
+ static int ext4_mb_discard_preallocations(struct super_block *sb, int needed)
+ {
+-	ext4_group_t i;
++	ext4_group_t i, ngroups = ext4_get_groups_count(sb);
+ 	int ret;
+ 	int freed = 0;
+ 
+ 	trace_mark(ext4_mb_discard_preallocations, "dev %s needed %d",
+ 		   sb->s_id, needed);
+-	for (i = 0; i < EXT4_SB(sb)->s_groups_count && needed > 0; i++) {
++	for (i = 0; i < ngroups && needed > 0; i++) {
+ 		ret = ext4_mb_discard_group_preallocations(sb, i, needed);
+ 		freed += ret;
+ 		needed -= ret;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 68c3a44c4a97..fcd7b24c6df3 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3557,9 +3557,8 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
+ 	if (test_opt(sb, MINIX_DF)) {
+ 		sbi->s_overhead_last = 0;
+ 	} else if (sbi->s_blocks_last != ext4_blocks_count(es)) {
+-		ext4_group_t ngroups = sbi->s_groups_count, i;
++		ext4_group_t i, ngroups = ext4_get_groups_count(sb);
+ 		ext4_fsblk_t overhead = 0;
+-		smp_rmb();
+ 
+ 		/*
+ 		 * Compute the overhead (FS structures).  This is constant

commit 9ca92389c5312a51e819c15c762f0abdc7f3129b
+Author: Theodore Ts'o 
+Date:   Fri May 1 12:52:25 2009 -0400
+
+    ext4: Use separate super_operations structure for no_journal filesystems
+    
+    By using a separate super_operations structure for filesystems that
+    have and don't have journals, we can simply ext4_write_super() ---
+    which is only needed when no journal is present --- and ext4_freeze(),
+    ext4_unfreeze(), and ext4_sync_fs(), which are only needed when the
+    journal is present.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 7c7a08af1200..68c3a44c4a97 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -995,7 +995,6 @@ static const struct super_operations ext4_sops = {
+ 	.dirty_inode	= ext4_dirty_inode,
+ 	.delete_inode	= ext4_delete_inode,
+ 	.put_super	= ext4_put_super,
+-	.write_super	= ext4_write_super,
+ 	.sync_fs	= ext4_sync_fs,
+ 	.freeze_fs	= ext4_freeze,
+ 	.unfreeze_fs	= ext4_unfreeze,
+@@ -1010,6 +1009,25 @@ static const struct super_operations ext4_sops = {
+ 	.bdev_try_to_free_page = bdev_try_to_free_page,
+ };
+ 
++static const struct super_operations ext4_nojournal_sops = {
++	.alloc_inode	= ext4_alloc_inode,
++	.destroy_inode	= ext4_destroy_inode,
++	.write_inode	= ext4_write_inode,
++	.dirty_inode	= ext4_dirty_inode,
++	.delete_inode	= ext4_delete_inode,
++	.write_super	= ext4_write_super,
++	.put_super	= ext4_put_super,
++	.statfs		= ext4_statfs,
++	.remount_fs	= ext4_remount,
++	.clear_inode	= ext4_clear_inode,
++	.show_options	= ext4_show_options,
++#ifdef CONFIG_QUOTA
++	.quota_read	= ext4_quota_read,
++	.quota_write	= ext4_quota_write,
++#endif
++	.bdev_try_to_free_page = bdev_try_to_free_page,
++};
++
+ static const struct export_operations ext4_export_ops = {
+ 	.fh_to_dentry = ext4_fh_to_dentry,
+ 	.fh_to_parent = ext4_fh_to_parent,
+@@ -2615,7 +2633,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	/*
+ 	 * set up enough so that it can read an inode
+ 	 */
+-	sb->s_op = &ext4_sops;
++	if (!test_opt(sb, NOLOAD) &&
++	    EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL))
++		sb->s_op = &ext4_sops;
++	else
++		sb->s_op = &ext4_nojournal_sops;
+ 	sb->s_export_op = &ext4_export_ops;
+ 	sb->s_xattr = ext4_xattr_handlers;
+ #ifdef CONFIG_QUOTA
+@@ -3275,19 +3297,9 @@ int ext4_force_commit(struct super_block *sb)
+ 	return ret;
+ }
+ 
+-/*
+- * Ext4 always journals updates to the superblock itself, so we don't
+- * have to propagate any other updates to the superblock on disk at this
+- * point if the journalling is enabled.
+- */
+ static void ext4_write_super(struct super_block *sb)
+ {
+-	if (EXT4_SB(sb)->s_journal) {
+-		if (mutex_trylock(&sb->s_lock) != 0)
+-			BUG();
+-	} else {
+-		ext4_commit_super(sb, 1);
+-	}
++	ext4_commit_super(sb, 1);
+ }
+ 
+ static int ext4_sync_fs(struct super_block *sb, int wait)
+@@ -3296,15 +3308,9 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
+ 	tid_t target;
+ 
+ 	trace_mark(ext4_sync_fs, "dev %s wait %d", sb->s_id, wait);
+-	if (EXT4_SB(sb)->s_journal) {
+-		if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal,
+-					      &target)) {
+-			if (wait)
+-				jbd2_log_wait_commit(EXT4_SB(sb)->s_journal,
+-						     target);
+-		}
+-	} else {
+-		ext4_commit_super(sb, wait);
++	if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, &target)) {
++		if (wait)
++			jbd2_log_wait_commit(EXT4_SB(sb)->s_journal, target);
+ 	}
+ 	return ret;
+ }
+@@ -3318,32 +3324,31 @@ static int ext4_freeze(struct super_block *sb)
+ 	int error = 0;
+ 	journal_t *journal;
+ 
+-	if (!(sb->s_flags & MS_RDONLY)) {
+-		journal = EXT4_SB(sb)->s_journal;
++	if (sb->s_flags & MS_RDONLY)
++		return 0;
+ 
+-		if (journal) {
+-			/* Now we set up the journal barrier. */
+-			jbd2_journal_lock_updates(journal);
++	journal = EXT4_SB(sb)->s_journal;
+ 
+-			/*
+-			 * We don't want to clear needs_recovery flag when we
+-			 * failed to flush the journal.
+-			 */
+-			error = jbd2_journal_flush(journal);
+-			if (error < 0)
+-				goto out;
+-		}
++	/* Now we set up the journal barrier. */
++	jbd2_journal_lock_updates(journal);
+ 
+-		/* Journal blocked and flushed, clear needs_recovery flag. */
+-		EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+-		error = ext4_commit_super(sb, 1);
+-		if (error)
+-			goto out;
++	/*
++	 * Don't clear the needs_recovery flag if we failed to flush
++	 * the journal.
++	 */
++	error = jbd2_journal_flush(journal);
++	if (error < 0) {
++	out:
++		jbd2_journal_unlock_updates(journal);
++		return error;
+ 	}
++
++	/* Journal blocked and flushed, clear needs_recovery flag. */
++	EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
++	error = ext4_commit_super(sb, 1);
++	if (error)
++		goto out;
+ 	return 0;
+-out:
+-	jbd2_journal_unlock_updates(journal);
+-	return error;
+ }
+ 
+ /*
+@@ -3352,14 +3357,15 @@ static int ext4_freeze(struct super_block *sb)
+  */
+ static int ext4_unfreeze(struct super_block *sb)
+ {
+-	if (EXT4_SB(sb)->s_journal && !(sb->s_flags & MS_RDONLY)) {
+-		lock_super(sb);
+-		/* Reser the needs_recovery flag before the fs is unlocked. */
+-		EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+-		ext4_commit_super(sb, 1);
+-		unlock_super(sb);
+-		jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
+-	}
++	if (sb->s_flags & MS_RDONLY)
++		return 0;
++
++	lock_super(sb);
++	/* Reset the needs_recovery flag before the fs is unlocked. */
++	EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
++	ext4_commit_super(sb, 1);
++	unlock_super(sb);
++	jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
+ 	return 0;
+ }
+ 

commit 7234ab2a55e77784b44cf2d862136d9e41b8d98a
+Author: Theodore Ts'o 
+Date:   Thu Apr 30 21:24:04 2009 -0400
+
+    ext4: Fix and simplify s_dirt handling
+    
+    The s_dirt flag wasn't completely handled correctly, but it didn't
+    really matter when journalling was enabled.  It turns out that when
+    ext4 runs without a journal, we don't clear s_dirt in places where we
+    should have, with the result that the high-level write_super()
+    function was writing the superblock when it wasn't necessary.
+    
+    So we fix this by making ext4_commit_super() clear the s_dirt flag,
+    and removing many of the other places where s_dirt is manipulated.
+    When journalling is enabled, the s_dirt flag might be left set more
+    often, but s_dirt really doesn't matter when journalling is enabled.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index ad4c9be4abdc..7c7a08af1200 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3128,7 +3128,6 @@ static int ext4_load_journal(struct super_block *sb,
+ 	if (journal_devnum &&
+ 	    journal_devnum != le32_to_cpu(es->s_journal_dev)) {
+ 		es->s_journal_dev = cpu_to_le32(journal_devnum);
+-		sb->s_dirt = 1;
+ 
+ 		/* Make sure we flush the recovery flag to disk. */
+ 		ext4_commit_super(sb, 1);
+@@ -3168,7 +3167,7 @@ static int ext4_commit_super(struct super_block *sb, int sync)
+ 					&EXT4_SB(sb)->s_freeblocks_counter));
+ 	es->s_free_inodes_count = cpu_to_le32(percpu_counter_sum_positive(
+ 					&EXT4_SB(sb)->s_freeinodes_counter));
+-
++	sb->s_dirt = 0;
+ 	BUFFER_TRACE(sbh, "marking dirty");
+ 	mark_buffer_dirty(sbh);
+ 	if (sync) {
+@@ -3210,7 +3209,6 @@ static void ext4_mark_recovery_complete(struct super_block *sb,
+ 	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER) &&
+ 	    sb->s_flags & MS_RDONLY) {
+ 		EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+-		sb->s_dirt = 0;
+ 		ext4_commit_super(sb, 1);
+ 	}
+ 	unlock_super(sb);
+@@ -3271,10 +3269,8 @@ int ext4_force_commit(struct super_block *sb)
+ 		return 0;
+ 
+ 	journal = EXT4_SB(sb)->s_journal;
+-	if (journal) {
+-		sb->s_dirt = 0;
++	if (journal)
+ 		ret = ext4_journal_force_commit(journal);
+-	}
+ 
+ 	return ret;
+ }
+@@ -3282,15 +3278,13 @@ int ext4_force_commit(struct super_block *sb)
+ /*
+  * Ext4 always journals updates to the superblock itself, so we don't
+  * have to propagate any other updates to the superblock on disk at this
+- * point.  (We can probably nuke this function altogether, and remove
+- * any mention to sb->s_dirt in all of fs/ext4; eventual cleanup...)
++ * point if the journalling is enabled.
+  */
+ static void ext4_write_super(struct super_block *sb)
+ {
+ 	if (EXT4_SB(sb)->s_journal) {
+ 		if (mutex_trylock(&sb->s_lock) != 0)
+ 			BUG();
+-		sb->s_dirt = 0;
+ 	} else {
+ 		ext4_commit_super(sb, 1);
+ 	}
+@@ -3302,7 +3296,6 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
+ 	tid_t target;
+ 
+ 	trace_mark(ext4_sync_fs, "dev %s wait %d", sb->s_id, wait);
+-	sb->s_dirt = 0;
+ 	if (EXT4_SB(sb)->s_journal) {
+ 		if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal,
+ 					      &target)) {
+@@ -3324,7 +3317,6 @@ static int ext4_freeze(struct super_block *sb)
+ {
+ 	int error = 0;
+ 	journal_t *journal;
+-	sb->s_dirt = 0;
+ 
+ 	if (!(sb->s_flags & MS_RDONLY)) {
+ 		journal = EXT4_SB(sb)->s_journal;

commit e2d670523c6c4ccb0fca9f3ab1b8f066d9aa57d6
+Author: Theodore Ts'o 
+Date:   Fri May 1 00:33:44 2009 -0400
+
+    ext4: Simplify ext4_commit_super()'s function signature
+    
+    The ext4_commit_super() function took both a struct super_block * and
+    a struct ext4_super_block *, but the struct ext4_super_block can be
+    derived from the struct super_block.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 3e509bc647e3..ad4c9be4abdc 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -54,8 +54,7 @@ static struct kset *ext4_kset;
+ 
+ static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
+ 			     unsigned long journal_devnum);
+-static int ext4_commit_super(struct super_block *sb,
+-			      struct ext4_super_block *es, int sync);
++static int ext4_commit_super(struct super_block *sb, int sync);
+ static void ext4_mark_recovery_complete(struct super_block *sb,
+ 					struct ext4_super_block *es);
+ static void ext4_clear_journal_err(struct super_block *sb,
+@@ -306,7 +305,7 @@ static void ext4_handle_error(struct super_block *sb)
+ 		printk(KERN_CRIT "Remounting filesystem read-only\n");
+ 		sb->s_flags |= MS_RDONLY;
+ 	}
+-	ext4_commit_super(sb, es, 1);
++	ext4_commit_super(sb, 1);
+ 	if (test_opt(sb, ERRORS_PANIC))
+ 		panic("EXT4-fs (device %s): panic forced after error\n",
+ 			sb->s_id);
+@@ -448,7 +447,7 @@ __acquires(bitlock)
+ 	if (test_opt(sb, ERRORS_CONT)) {
+ 		EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
+ 		es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
+-		ext4_commit_super(sb, es, 0);
++		ext4_commit_super(sb, 0);
+ 		return;
+ 	}
+ 	ext4_unlock_group(sb, grp);
+@@ -577,7 +576,7 @@ static void ext4_put_super(struct super_block *sb)
+ 	if (!(sb->s_flags & MS_RDONLY)) {
+ 		EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+ 		es->s_state = cpu_to_le16(sbi->s_mount_state);
+-		ext4_commit_super(sb, es, 1);
++		ext4_commit_super(sb, 1);
+ 	}
+ 	if (sbi->s_proc) {
+ 		remove_proc_entry(sb->s_id, ext4_proc_root);
+@@ -1596,7 +1595,7 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
+ 	if (sbi->s_journal)
+ 		EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+ 
+-	ext4_commit_super(sb, es, 1);
++	ext4_commit_super(sb, 1);
+ 	if (test_opt(sb, DEBUG))
+ 		printk(KERN_INFO "[EXT4 FS bs=%lu, gc=%u, "
+ 				"bpg=%lu, ipg=%lu, mo=%04lx]\n",
+@@ -2655,7 +2654,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 			if (test_opt(sb, ERRORS_PANIC)) {
+ 				EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
+ 				es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
+-				ext4_commit_super(sb, es, 1);
++				ext4_commit_super(sb, 1);
+ 				goto failed_mount4;
+ 			}
+ 		}
+@@ -3132,15 +3131,15 @@ static int ext4_load_journal(struct super_block *sb,
+ 		sb->s_dirt = 1;
+ 
+ 		/* Make sure we flush the recovery flag to disk. */
+-		ext4_commit_super(sb, es, 1);
++		ext4_commit_super(sb, 1);
+ 	}
+ 
+ 	return 0;
+ }
+ 
+-static int ext4_commit_super(struct super_block *sb,
+-			      struct ext4_super_block *es, int sync)
++static int ext4_commit_super(struct super_block *sb, int sync)
+ {
++	struct ext4_super_block *es = EXT4_SB(sb)->s_es;
+ 	struct buffer_head *sbh = EXT4_SB(sb)->s_sbh;
+ 	int error = 0;
+ 
+@@ -3212,7 +3211,7 @@ static void ext4_mark_recovery_complete(struct super_block *sb,
+ 	    sb->s_flags & MS_RDONLY) {
+ 		EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+ 		sb->s_dirt = 0;
+-		ext4_commit_super(sb, es, 1);
++		ext4_commit_super(sb, 1);
+ 	}
+ 	unlock_super(sb);
+ 
+@@ -3253,7 +3252,7 @@ static void ext4_clear_journal_err(struct super_block *sb,
+ 
+ 		EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
+ 		es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
+-		ext4_commit_super(sb, es, 1);
++		ext4_commit_super(sb, 1);
+ 
+ 		jbd2_journal_clear_err(journal);
+ 	}
+@@ -3293,7 +3292,7 @@ static void ext4_write_super(struct super_block *sb)
+ 			BUG();
+ 		sb->s_dirt = 0;
+ 	} else {
+-		ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1);
++		ext4_commit_super(sb, 1);
+ 	}
+ }
+ 
+@@ -3312,7 +3311,7 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
+ 						     target);
+ 		}
+ 	} else {
+-		ext4_commit_super(sb, EXT4_SB(sb)->s_es, wait);
++		ext4_commit_super(sb, wait);
+ 	}
+ 	return ret;
+ }
+@@ -3345,7 +3344,7 @@ static int ext4_freeze(struct super_block *sb)
+ 
+ 		/* Journal blocked and flushed, clear needs_recovery flag. */
+ 		EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+-		error = ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1);
++		error = ext4_commit_super(sb, 1);
+ 		if (error)
+ 			goto out;
+ 	}
+@@ -3365,7 +3364,7 @@ static int ext4_unfreeze(struct super_block *sb)
+ 		lock_super(sb);
+ 		/* Reser the needs_recovery flag before the fs is unlocked. */
+ 		EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+-		ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1);
++		ext4_commit_super(sb, 1);
+ 		unlock_super(sb);
+ 		jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
+ 	}
+@@ -3520,7 +3519,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 		}
+ 	}
+ 	if (sbi->s_journal == NULL)
+-		ext4_commit_super(sb, es, 1);
++		ext4_commit_super(sb, 1);
+ 
+ #ifdef CONFIG_QUOTA
+ 	/* Release old quota file names */

commit f7c439504ccba0cca43271e651013ab97a221c62
+Author: Theodore Ts'o 
+Date:   Fri Apr 24 23:31:59 2009 -0400
+
+    ext4: Use is_power_of_2() for clarity
+    
+    Signed-off-by: Robert P. J. Day 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 3f4475daa66d..3e509bc647e3 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1483,7 +1483,7 @@ static int parse_options(char *options, struct super_block *sb,
+ 				return 0;
+ 			if (option < 0 || option > (1 << 30))
+ 				return 0;
+-			if (option & (option - 1)) {
++			if (!is_power_of_2(option)) {
+ 				printk(KERN_ERR "EXT4-fs: inode_readahead_blks"
+ 				       " must be a power of 2\n");
+ 				return 0;
+@@ -2101,8 +2101,7 @@ static ssize_t inode_readahead_blks_store(struct ext4_attr *a,
+ 	if (parse_strtoul(buf, 0x40000000, &t))
+ 		return -EINVAL;
+ 
+-	/* inode_readahead_blks must be a power of 2 */
+-	if (t & (t-1))
++	if (!is_power_of_2(t))
+ 		return -EINVAL;
+ 
+ 	sbi->s_inode_readahead_blks = t;

commit c5ca7c7636fa689a9746b6032f83aa7fffec31c6
+Author: Theodore Ts'o 
+Date:   Mon Apr 27 22:48:48 2009 -0400
+
+    ext4: Fallback to vmalloc if kmalloc can't allocate s_flex_groups array
+    
+    For very large filesystems, the s_flex_groups array can get quite big.
+    For example, a filesystem that can be resized up to 16TB will have
+    8192 flex groups (assuming the default flex_bg size of 16), so the
+    array is 96k, which is *very* marginal for kmalloc().  On the other
+    hand, a 160GB filesystem without the resize_inode feature will only
+    require 960 bytes.  So we try to allocate the array first using
+    kmalloc(), and if that fails, we'll try to use vmalloc() instead.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 2958f4e6f222..3f4475daa66d 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -20,6 +20,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -586,7 +587,10 @@ static void ext4_put_super(struct super_block *sb)
+ 	for (i = 0; i < sbi->s_gdb_count; i++)
+ 		brelse(sbi->s_group_desc[i]);
+ 	kfree(sbi->s_group_desc);
+-	kfree(sbi->s_flex_groups);
++	if (is_vmalloc_addr(sbi->s_flex_groups))
++		vfree(sbi->s_flex_groups);
++	else
++		kfree(sbi->s_flex_groups);
+ 	percpu_counter_destroy(&sbi->s_freeblocks_counter);
+ 	percpu_counter_destroy(&sbi->s_freeinodes_counter);
+ 	percpu_counter_destroy(&sbi->s_dirs_counter);
+@@ -1620,6 +1624,7 @@ static int ext4_fill_flex_info(struct super_block *sb)
+ 	ext4_group_t flex_group_count;
+ 	ext4_group_t flex_group;
+ 	int groups_per_flex = 0;
++	size_t size;
+ 	int i;
+ 
+ 	if (!sbi->s_es->s_log_groups_per_flex) {
+@@ -1634,8 +1639,13 @@ static int ext4_fill_flex_info(struct super_block *sb)
+ 	flex_group_count = ((sbi->s_groups_count + groups_per_flex - 1) +
+ 			((le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) + 1) <<
+ 			      EXT4_DESC_PER_BLOCK_BITS(sb))) / groups_per_flex;
+-	sbi->s_flex_groups = kzalloc(flex_group_count *
+-				     sizeof(struct flex_groups), GFP_KERNEL);
++	size = flex_group_count * sizeof(struct flex_groups);
++	sbi->s_flex_groups = kzalloc(size, GFP_KERNEL);
++	if (sbi->s_flex_groups == NULL) {
++		sbi->s_flex_groups = vmalloc(size);
++		if (sbi->s_flex_groups)
++			memset(sbi->s_flex_groups, 0, size);
++	}
+ 	if (sbi->s_flex_groups == NULL) {
+ 		printk(KERN_ERR "EXT4-fs: not enough memory for "
+ 				"%u flex groups\n", flex_group_count);
+@@ -2842,6 +2852,12 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		sbi->s_journal = NULL;
+ 	}
+ failed_mount3:
++	if (sbi->s_flex_groups) {
++		if (is_vmalloc_addr(sbi->s_flex_groups))
++			vfree(sbi->s_flex_groups);
++		else
++			kfree(sbi->s_flex_groups);
++	}
+ 	percpu_counter_destroy(&sbi->s_freeblocks_counter);
+ 	percpu_counter_destroy(&sbi->s_freeinodes_counter);
+ 	percpu_counter_destroy(&sbi->s_dirs_counter);

commit c4b5a614316c505922a522b2e35ba05ea3e08a7c
+Author: Theodore Ts'o 
+Date:   Fri Apr 24 18:45:35 2009 -0400
+
+    ext4: Do not try to validate extents on special files
+    
+    The EXTENTS_FL flag should never be set on special files, but if it
+    is, don't bother trying to validate that the extents tree is valid,
+    since only files, directories, and non-fast symlinks will ever have an
+    extent data structure.  We perhaps should flag the filesystem as being
+    corrupted if we see a special file (named pipes, device nodes, Unix
+    domain sockets, etc.) with the EXTENTS_FL flag, but e2fsck doesn't
+    currently check this case, so we'll just ignore this for now, since
+    it's harmless.
+    
+    Without this fix, a special device with the extents flag is flagged as
+    an error by the kernel, so it is impossible to access or delete the
+    inode, but e2fsck doesn't see it as a problem, leading to
+    confused/frustrated users.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 11460037ea9d..e91f978c7f12 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4407,6 +4407,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 			(__u64)(le32_to_cpu(raw_inode->i_version_hi)) << 32;
+ 	}
+ 
++	ret = 0;
+ 	if (ei->i_file_acl &&
+ 	    ((ei->i_file_acl < 
+ 	      (le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block) +
+@@ -4418,8 +4419,11 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 		ret = -EIO;
+ 		goto bad_inode;
+ 	} else if (ei->i_flags & EXT4_EXTENTS_FL) {
+-		/* Validate extent which is part of inode */
+-		ret = ext4_ext_check_inode(inode);
++		if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
++		    (S_ISLNK(inode->i_mode) &&
++		     !ext4_inode_is_fast_symlink(inode)))
++			/* Validate extent which is part of inode */
++			ret = ext4_ext_check_inode(inode);
+  	} else if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+ 		   (S_ISLNK(inode->i_mode) &&
+ 		    !ext4_inode_is_fast_symlink(inode))) {

commit a9e817425dc0baede8ebe5fbc9984a640257432b
+Author: Theodore Ts'o 
+Date:   Fri Apr 24 16:11:18 2009 -0400
+
+    ext4: Ignore i_file_acl_high unless EXT4_FEATURE_INCOMPAT_64BIT is present
+    
+    Don't try to look at i_file_acl_high unless the INCOMPAT_64BIT feature
+    bit is set.  The field is normally zero, but older versions of e2fsck
+    didn't automatically check to make sure of this, so in the spirit of
+    "be liberal in what you accept", don't look at i_file_acl_high unless
+    we are using a 64-bit filesystem.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index cab75bbcd57b..11460037ea9d 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4357,11 +4357,9 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 	ei->i_flags = le32_to_cpu(raw_inode->i_flags);
+ 	inode->i_blocks = ext4_inode_blocks(raw_inode, ei);
+ 	ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl_lo);
+-	if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=
+-	    cpu_to_le32(EXT4_OS_HURD)) {
++	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_64BIT))
+ 		ei->i_file_acl |=
+ 			((__u64)le16_to_cpu(raw_inode->i_file_acl_high)) << 32;
+-	}
+ 	inode->i_size = ext4_isize(raw_inode);
+ 	ei->i_disksize = inode->i_size;
+ 	inode->i_generation = le32_to_cpu(raw_inode->i_generation);

commit 485c26ec70f823f2a9cf45982b724893e53a859e
+Author: Theodore Ts'o 
+Date:   Fri Apr 24 13:43:20 2009 -0400
+
+    ext4: Fix softlockup caused by illegal i_file_acl value in on-disk inode
+    
+    If the block containing external extended attributes (which is stored
+    in i_file_acl and i_file_acl_high) is larger than the on-disk
+    filesystem, the process which tried to access the extended attributes
+    will endlessly issue kernel printks complaining that
+    "__find_get_block_slow() failed", locking up that CPU until the system
+    is forcibly rebooted.
+    
+    So when we read in the inode, make sure the i_file_acl value is legal,
+    and if not, flag the filesystem as being corrupted.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index c6bd6ced3bb7..cab75bbcd57b 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4409,7 +4409,17 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 			(__u64)(le32_to_cpu(raw_inode->i_version_hi)) << 32;
+ 	}
+ 
+-	if (ei->i_flags & EXT4_EXTENTS_FL) {
++	if (ei->i_file_acl &&
++	    ((ei->i_file_acl < 
++	      (le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block) +
++	       EXT4_SB(sb)->s_gdb_count)) ||
++	     (ei->i_file_acl >= ext4_blocks_count(EXT4_SB(sb)->s_es)))) {
++		ext4_error(sb, __func__,
++			   "bad extended attribute block %llu in inode #%lu",
++			   ei->i_file_acl, inode->i_ino);
++		ret = -EIO;
++		goto bad_inode;
++	} else if (ei->i_flags & EXT4_EXTENTS_FL) {
+ 		/* Validate extent which is part of inode */
+ 		ret = ext4_ext_check_inode(inode);
+  	} else if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||

commit b5451f7b2694b04d9f912f6cf09db1729f291996
+Author: Theodore Ts'o 
+Date:   Wed Apr 22 21:00:36 2009 -0400
+
+    ext4: Fix potential inode allocation soft lockup in Orlov allocator
+    
+    If the Orlov allocator is having trouble finding an appropriate block
+    group, the fallback code could loop forever, causing a soft lockup
+    warning in find_group_orlov():
+    
+    BUG: soft lockup - CPU#0 stuck for 61s! [cp:11728]
+         ...
+    Pid: 11728, comm: cp Not tainted (2.6.30-rc1-dirty #77) Lenovo
+    EIP: 0060:[] EFLAGS: 00000246 CPU: 0
+    EIP is at ext4_get_group_desc+0x54/0x9d
+        ...
+    Call Trace:
+     [] find_group_orlov+0x2ee/0x334
+     [] ? sched_clock+0x8/0xb
+     [] ext4_new_inode+0x2cf/0xb1a
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index cbce5aa6b927..f18e0a08a6b5 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -585,6 +585,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
+ fallback:
+ 	ngroups = sbi->s_groups_count;
+ 	avefreei = freei / ngroups;
++fallback_retry:
+ 	parent_group = EXT4_I(parent)->i_block_group;
+ 	for (i = 0; i < ngroups; i++) {
+ 		grp = (parent_group + i) % ngroups;
+@@ -602,7 +603,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
+ 		 * filesystems the above test can fail to find any blockgroups
+ 		 */
+ 		avefreei = 0;
+-		goto fallback;
++		goto fallback_retry;
+ 	}
+ 
+ 	return -1;

commit e84a26ce178345498a7eca0590852bcc36f1092f
+Author: Theodore Ts'o 
+Date:   Wed Apr 22 20:52:25 2009 -0400
+
+    ext4: Make the extent validity check more paranoid
+    
+    Instead of just checking that the extent block number is greater or
+    equal than s_first_data_block, make sure it it is not pointing into
+    the block group descriptors, since that is clearly wrong.  This helps
+    prevent filesystem from getting very badly corrupted in case an extent
+    block is corrupted.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 6132353dcf62..c28ffe259506 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -326,11 +326,14 @@ ext4_ext_max_entries(struct inode *inode, int depth)
+ 
+ static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext)
+ {
+-	ext4_fsblk_t block = ext_pblock(ext);
++	ext4_fsblk_t block = ext_pblock(ext), valid_block;
+ 	int len = ext4_ext_get_actual_len(ext);
+ 	struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
+-	if (unlikely(block < le32_to_cpu(es->s_first_data_block) ||
+-			((block + len) > ext4_blocks_count(es))))
++
++	valid_block = le32_to_cpu(es->s_first_data_block) +
++		EXT4_SB(inode->i_sb)->s_gdb_count;
++	if (unlikely(block <= valid_block ||
++		     ((block + len) > ext4_blocks_count(es))))
+ 		return 0;
+ 	else
+ 		return 1;
+@@ -339,10 +342,13 @@ static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext)
+ static int ext4_valid_extent_idx(struct inode *inode,
+ 				struct ext4_extent_idx *ext_idx)
+ {
+-	ext4_fsblk_t block = idx_pblock(ext_idx);
++	ext4_fsblk_t block = idx_pblock(ext_idx), valid_block;
+ 	struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
+-	if (unlikely(block < le32_to_cpu(es->s_first_data_block) ||
+-			(block >= ext4_blocks_count(es))))
++
++	valid_block = le32_to_cpu(es->s_first_data_block) +
++		EXT4_SB(inode->i_sb)->s_gdb_count;
++	if (unlikely(block <= valid_block ||
++		     (block >= ext4_blocks_count(es))))
+ 		return 0;
+ 	else
+ 		return 1;

commit 38d726d153cfe5efe5fe22d28d36ab382dda3a5c
+Author: Theodore Ts'o 
+Date:   Tue Apr 14 10:10:47 2009 -0400
+
+    jbd: use SWRITE_SYNC_PLUG when writing synchronous revoke records
+    
+    The revoke records must be written using the same way as the rest of
+    the blocks during the commit process; that is, either marked as
+    synchronous writes or as asynchornous writes.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
+index a8e8513a78a9..06560c520f49 100644
+--- a/fs/jbd/commit.c
++++ b/fs/jbd/commit.c
+@@ -502,7 +502,7 @@ void journal_commit_transaction(journal_t *journal)
+ 		err = 0;
+ 	}
+ 
+-	journal_write_revoke_records(journal, commit_transaction);
++	journal_write_revoke_records(journal, commit_transaction, write_op);
+ 
+ 	/*
+ 	 * If we found any dirty or locked buffers, then we should have
+diff --git a/fs/jbd/revoke.c b/fs/jbd/revoke.c
+index c7bd649bbbdc..1b1a06e1c836 100644
+--- a/fs/jbd/revoke.c
++++ b/fs/jbd/revoke.c
+@@ -67,6 +67,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #endif
+ #include 
+ 
+@@ -99,8 +100,8 @@ struct jbd_revoke_table_s
+ #ifdef __KERNEL__
+ static void write_one_revoke_record(journal_t *, transaction_t *,
+ 				    struct journal_head **, int *,
+-				    struct jbd_revoke_record_s *);
+-static void flush_descriptor(journal_t *, struct journal_head *, int);
++				    struct jbd_revoke_record_s *, int);
++static void flush_descriptor(journal_t *, struct journal_head *, int, int);
+ #endif
+ 
+ /* Utility functions to maintain the revoke table */
+@@ -486,7 +487,7 @@ void journal_switch_revoke_table(journal_t *journal)
+  */
+ 
+ void journal_write_revoke_records(journal_t *journal,
+-				  transaction_t *transaction)
++				  transaction_t *transaction, int write_op)
+ {
+ 	struct journal_head *descriptor;
+ 	struct jbd_revoke_record_s *record;
+@@ -510,14 +511,14 @@ void journal_write_revoke_records(journal_t *journal,
+ 				hash_list->next;
+ 			write_one_revoke_record(journal, transaction,
+ 						&descriptor, &offset,
+-						record);
++						record, write_op);
+ 			count++;
+ 			list_del(&record->hash);
+ 			kmem_cache_free(revoke_record_cache, record);
+ 		}
+ 	}
+ 	if (descriptor)
+-		flush_descriptor(journal, descriptor, offset);
++		flush_descriptor(journal, descriptor, offset, write_op);
+ 	jbd_debug(1, "Wrote %d revoke records\n", count);
+ }
+ 
+@@ -530,7 +531,8 @@ static void write_one_revoke_record(journal_t *journal,
+ 				    transaction_t *transaction,
+ 				    struct journal_head **descriptorp,
+ 				    int *offsetp,
+-				    struct jbd_revoke_record_s *record)
++				    struct jbd_revoke_record_s *record,
++				    int write_op)
+ {
+ 	struct journal_head *descriptor;
+ 	int offset;
+@@ -549,7 +551,7 @@ static void write_one_revoke_record(journal_t *journal,
+ 	/* Make sure we have a descriptor with space left for the record */
+ 	if (descriptor) {
+ 		if (offset == journal->j_blocksize) {
+-			flush_descriptor(journal, descriptor, offset);
++			flush_descriptor(journal, descriptor, offset, write_op);
+ 			descriptor = NULL;
+ 		}
+ 	}
+@@ -586,7 +588,7 @@ static void write_one_revoke_record(journal_t *journal,
+ 
+ static void flush_descriptor(journal_t *journal,
+ 			     struct journal_head *descriptor,
+-			     int offset)
++			     int offset, int write_op)
+ {
+ 	journal_revoke_header_t *header;
+ 	struct buffer_head *bh = jh2bh(descriptor);
+@@ -601,7 +603,7 @@ static void flush_descriptor(journal_t *journal,
+ 	set_buffer_jwrite(bh);
+ 	BUFFER_TRACE(bh, "write");
+ 	set_buffer_dirty(bh);
+-	ll_rw_block(SWRITE, 1, &bh);
++	ll_rw_block((write_op == WRITE) ? SWRITE : SWRITE_SYNC_PLUG, 1, &bh);
+ }
+ #endif
+ 
+diff --git a/include/linux/jbd.h b/include/linux/jbd.h
+index 53ae4399da2d..c2049a04fa0b 100644
+--- a/include/linux/jbd.h
++++ b/include/linux/jbd.h
+@@ -978,7 +978,8 @@ extern void	   journal_destroy_revoke(journal_t *);
+ extern int	   journal_revoke (handle_t *,
+ 				unsigned long, struct buffer_head *);
+ extern int	   journal_cancel_revoke(handle_t *, struct journal_head *);
+-extern void	   journal_write_revoke_records(journal_t *, transaction_t *);
++extern void	   journal_write_revoke_records(journal_t *,
++						transaction_t *, int);
+ 
+ /* Recovery revoke support */
+ extern int	journal_set_revoke(journal_t *, unsigned long, tid_t);

commit 67c457a8c378a006a34d92f9bd3078a80a92f250
+Author: Theodore Ts'o 
+Date:   Tue Apr 14 07:50:56 2009 -0400
+
+    jbd2: use SWRITE_SYNC_PLUG when writing synchronous revoke records
+    
+    The revoke records must be written using the same way as the rest of
+    the blocks during the commit process; that is, either marked as
+    synchronous writes or as asynchornous writes.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index 073c8c3df7cd..0b7d3b8226fd 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -506,7 +506,8 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	if (err)
+ 		jbd2_journal_abort(journal, err);
+ 
+-	jbd2_journal_write_revoke_records(journal, commit_transaction);
++	jbd2_journal_write_revoke_records(journal, commit_transaction,
++					  write_op);
+ 
+ 	jbd_debug(3, "JBD: commit phase 2\n");
+ 
+diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c
+index bbe6d592d8b3..a360b06af2e3 100644
+--- a/fs/jbd2/revoke.c
++++ b/fs/jbd2/revoke.c
+@@ -86,6 +86,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #endif
+ #include 
+ 
+@@ -118,8 +119,8 @@ struct jbd2_revoke_table_s
+ #ifdef __KERNEL__
+ static void write_one_revoke_record(journal_t *, transaction_t *,
+ 				    struct journal_head **, int *,
+-				    struct jbd2_revoke_record_s *);
+-static void flush_descriptor(journal_t *, struct journal_head *, int);
++				    struct jbd2_revoke_record_s *, int);
++static void flush_descriptor(journal_t *, struct journal_head *, int, int);
+ #endif
+ 
+ /* Utility functions to maintain the revoke table */
+@@ -499,7 +500,8 @@ void jbd2_journal_switch_revoke_table(journal_t *journal)
+  * revoke hash, deleting the entries as we go.
+  */
+ void jbd2_journal_write_revoke_records(journal_t *journal,
+-				  transaction_t *transaction)
++				       transaction_t *transaction,
++				       int write_op)
+ {
+ 	struct journal_head *descriptor;
+ 	struct jbd2_revoke_record_s *record;
+@@ -523,14 +525,14 @@ void jbd2_journal_write_revoke_records(journal_t *journal,
+ 				hash_list->next;
+ 			write_one_revoke_record(journal, transaction,
+ 						&descriptor, &offset,
+-						record);
++						record, write_op);
+ 			count++;
+ 			list_del(&record->hash);
+ 			kmem_cache_free(jbd2_revoke_record_cache, record);
+ 		}
+ 	}
+ 	if (descriptor)
+-		flush_descriptor(journal, descriptor, offset);
++		flush_descriptor(journal, descriptor, offset, write_op);
+ 	jbd_debug(1, "Wrote %d revoke records\n", count);
+ }
+ 
+@@ -543,7 +545,8 @@ static void write_one_revoke_record(journal_t *journal,
+ 				    transaction_t *transaction,
+ 				    struct journal_head **descriptorp,
+ 				    int *offsetp,
+-				    struct jbd2_revoke_record_s *record)
++				    struct jbd2_revoke_record_s *record,
++				    int write_op)
+ {
+ 	struct journal_head *descriptor;
+ 	int offset;
+@@ -562,7 +565,7 @@ static void write_one_revoke_record(journal_t *journal,
+ 	/* Make sure we have a descriptor with space left for the record */
+ 	if (descriptor) {
+ 		if (offset == journal->j_blocksize) {
+-			flush_descriptor(journal, descriptor, offset);
++			flush_descriptor(journal, descriptor, offset, write_op);
+ 			descriptor = NULL;
+ 		}
+ 	}
+@@ -607,7 +610,7 @@ static void write_one_revoke_record(journal_t *journal,
+ 
+ static void flush_descriptor(journal_t *journal,
+ 			     struct journal_head *descriptor,
+-			     int offset)
++			     int offset, int write_op)
+ {
+ 	jbd2_journal_revoke_header_t *header;
+ 	struct buffer_head *bh = jh2bh(descriptor);
+@@ -622,7 +625,7 @@ static void flush_descriptor(journal_t *journal,
+ 	set_buffer_jwrite(bh);
+ 	BUFFER_TRACE(bh, "write");
+ 	set_buffer_dirty(bh);
+-	ll_rw_block(SWRITE, 1, &bh);
++	ll_rw_block((write_op == WRITE) ? SWRITE : SWRITE_SYNC_PLUG, 1, &bh);
+ }
+ #endif
+ 
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index 8815a3456b3b..cc02393bfce8 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -1193,7 +1193,8 @@ extern int	   jbd2_journal_init_revoke_caches(void);
+ extern void	   jbd2_journal_destroy_revoke(journal_t *);
+ extern int	   jbd2_journal_revoke (handle_t *, unsigned long long, struct buffer_head *);
+ extern int	   jbd2_journal_cancel_revoke(handle_t *, struct journal_head *);
+-extern void	   jbd2_journal_write_revoke_records(journal_t *, transaction_t *);
++extern void	   jbd2_journal_write_revoke_records(journal_t *,
++						     transaction_t *, int);
+ 
+ /* Recovery revoke support */
+ extern int	jbd2_journal_set_revoke(journal_t *, unsigned long long, tid_t);

commit abd41443ac76d3e9c29a8c1d9e9a3312306cc55e
+Author: Theodore Ts'o 
+Date:   Sat Apr 11 15:51:18 2009 -0400
+
+    tracing: Document the event tracing system
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Theodore Ts'o 
+    Cc: Steven Rostedt 
+    LKML-Reference: <1239479479-2603-3-git-send-email-tytso@mit.edu>
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/Documentation/trace/events.txt b/Documentation/trace/events.txt
+new file mode 100644
+index 000000000000..abdee664c0f6
+--- /dev/null
++++ b/Documentation/trace/events.txt
+@@ -0,0 +1,135 @@
++			     Event Tracing
++
++		Documentation written by Theodore Ts'o
++
++Introduction
++============
++
++Tracepoints (see Documentation/trace/tracepoints.txt) can be used
++without creating custom kernel modules to register probe functions
++using the event tracing infrastructure.
++
++Not all tracepoints can be traced using the event tracing system;
++the kernel developer must provide code snippets which define how the
++tracing information is saved into the tracing buffer, and how the
++the tracing information should be printed.
++
++Using Event Tracing
++===================
++
++The events which are available for tracing can be found in the file
++/sys/kernel/debug/tracing/available_events.
++
++To enable a particular event, such as 'sched_wakeup', simply echo it
++to /sys/debug/tracing/set_event. For example:
++
++	# echo sched_wakeup > /sys/kernel/debug/tracing/set_event
++
++[ Note: events can also be enabled/disabled via the 'enabled' toggle
++  found in the /sys/kernel/tracing/events/ hierarchy of directories. ]
++
++To disable an event, echo the event name to the set_event file prefixed
++with an exclamation point:
++
++	# echo '!sched_wakeup' >> /sys/kernel/debug/tracing/set_event
++
++To disable events, echo an empty line to the set_event file:
++
++	# echo > /sys/kernel/debug/tracing/set_event
++
++The events are organized into subsystems, such as ext4, irq, sched,
++etc., and a full event name looks like this: :.  The
++subsystem name is optional, but it is displayed in the available_events
++file.  All of the events in a subsystem can be specified via the syntax
++":*"; for example, to enable all irq events, you can use the
++command:
++
++	# echo 'irq:*' > /sys/kernel/debug/tracing/set_event
++
++Defining an event-enabled tracepoint
++------------------------------------
++
++A kernel developer which wishes to define an event-enabled tracepoint
++must declare the tracepoint using TRACE_EVENT instead of DECLARE_TRACE.
++This is done via two header files in include/trace.  For example, to
++event-enable the jbd2 subsystem, we must create two files,
++include/trace/jbd2.h and include/trace/jbd2_event_types.h.  The
++include/trace/jbd2.h file should be included by kernel source files that
++will have a tracepoint inserted, and might look like this:
++
++#ifndef _TRACE_JBD2_H
++#define _TRACE_JBD2_H
++
++#include 
++#include 
++
++#include 
++
++#endif
++
++In a file that utilizes a jbd2 tracepoint, this header file would be
++included.  Note that you still have to use DEFINE_TRACE().  So for
++example, if fs/jbd2/commit.c planned to use the jbd2_start_commit
++tracepoint, it would have the following near the beginning of the file:
++
++#include 
++
++DEFINE_TRACE(jbd2_start_commit);
++
++Then in the function that would call the tracepoint, it would call the
++tracepoint function.  (For more information, please see the tracepoint
++documentation in Documentation/trace/tracepoints.txt):
++
++	trace_jbd2_start_commit(journal, commit_transaction);
++
++The code snippets which allow jbd2_start_commit to be an event-enabled
++tracepoint are placed in the file include/trace/jbd2_event_types.h:
++
++/* use  instead */
++#ifndef TRACE_EVENT
++# error Do not include this file directly.
++# error Unless you know what you are doing.
++#endif
++
++#undef TRACE_SYSTEM
++#define TRACE_SYSTEM jbd2
++
++#include 
++
++TRACE_EVENT(jbd2_start_commit,
++	TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
++	TP_ARGS(journal, commit_transaction),
++	TP_STRUCT__entry(
++		__array(	char,	devname, BDEVNAME_SIZE+24 )
++		__field(	int,	transaction		  )
++	),
++	TP_fast_assign(
++		memcpy(__entry->devname, journal->j_devname, BDEVNAME_SIZE+24);
++		__entry->transaction	= commit_transaction->t_tid;
++	),
++	TP_printk("dev %s transaction %d",
++		  __entry->devname, __entry->transaction)
++);
++
++The TP_PROTO and TP_ARGS are unchanged from DECLARE_TRACE.  The new
++arguments to TRACE_EVENT are TP_STRUCT__entry, TP_fast_assign, and
++TP_printk.
++
++TP_STRUCT__entry defines the data structure which will be stored in the
++trace buffer.  Normally, fields in __entry will be arrays or simple
++types.  It is possible to place data structures in __entry --- however,
++pointers in the data structure can not be trusted, since they will be
++accessed sometime later by TP_printk, and if the data structure contains
++fields that will not or cannot be used by TP_printk, this will waste
++space in the trace buffer.  In general, data structures should be
++avoided, unless they do only contain non-pointer types and all of the
++fields will be used by TP_printk.
++
++TP_fast_assign defines the code snippet which saves information into the
++__entry data structure, using the passed-in arguments defined in
++TP_PROTO and TP_ARGS.
++
++Finally, TP_printk will print the __entry data structure.  At the time
++when the code snippet defined by TP_printk is executed, it will not have
++access to the TP_ARGS arguments; it can only use the information saved
++in the __entry data structure.

commit 56c49951747f250d8398582509e02ae5ce1d36d1
+Author: Theodore Ts'o 
+Date:   Sat Apr 11 15:51:19 2009 -0400
+
+    tracing: Add documentation for the power tracer
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Acked-by: Arjan van de Ven 
+    Cc: Frederic Weisbecker 
+    Cc: Steven Rostedt 
+    LKML-Reference: <1239479479-2603-4-git-send-email-tytso@mit.edu>
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/Documentation/trace/power.txt b/Documentation/trace/power.txt
+new file mode 100644
+index 000000000000..cd805e16dc27
+--- /dev/null
++++ b/Documentation/trace/power.txt
+@@ -0,0 +1,17 @@
++The power tracer collects detailed information about C-state and P-state
++transitions, instead of just looking at the high-level "average"
++information.
++
++There is a helper script found in scrips/tracing/power.pl in the kernel
++sources which can be used to parse this information and create a
++Scalable Vector Graphics (SVG) picture from the trace data.
++
++To use this tracer:
++
++	echo 0 > /sys/kernel/debug/tracing/tracing_enabled
++	echo power > /sys/kernel/debug/tracing/current_tracer
++	echo 1 > /sys/kernel/debug/tracing/tracing_enabled
++	sleep 1
++	echo 0 > /sys/kernel/debug/tracing/tracing_enabled
++	cat /sys/kernel/debug/tracing/trace | \
++		perl scripts/tracing/power.pl > out.sv

commit 6e34eeddf7deec1444bbddab533f03f520d8458c
+Author: Theodore Ts'o 
+Date:   Tue Apr 7 18:12:43 2009 -0400
+
+    block_write_full_page: switch synchronous writes to use WRITE_SYNC_PLUG
+    
+    Now that we have a distinction between WRITE_SYNC and WRITE_SYNC_PLUG,
+    use WRITE_SYNC_PLUG in __block_write_full_page() to avoid unplugging
+    the block device I/O queue between each page that gets flushed out.
+    
+    Otherwise, when we run sync() or fsync() and we need to write out a
+    large number of pages, the block device queue will get unplugged
+    between for every page that is flushed out, which will be a pretty
+    serious performance regression caused by commit a64c8610.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/buffer.c b/fs/buffer.c
+index 6e35762b6169..13edf7ad3ff1 100644
+--- a/fs/buffer.c
++++ b/fs/buffer.c
+@@ -1596,6 +1596,16 @@ EXPORT_SYMBOL(unmap_underlying_metadata);
+  * locked buffer.   This only can happen if someone has written the buffer
+  * directly, with submit_bh().  At the address_space level PageWriteback
+  * prevents this contention from occurring.
++ *
++ * If block_write_full_page() is called with wbc->sync_mode ==
++ * WB_SYNC_ALL, the writes are posted using WRITE_SYNC_PLUG; this
++ * causes the writes to be flagged as synchronous writes, but the
++ * block device queue will NOT be unplugged, since usually many pages
++ * will be pushed to the out before the higher-level caller actually
++ * waits for the writes to be completed.  The various wait functions,
++ * such as wait_on_writeback_range() will ultimately call sync_page()
++ * which will ultimately call blk_run_backing_dev(), which will end up
++ * unplugging the device queue.
+  */
+ static int __block_write_full_page(struct inode *inode, struct page *page,
+ 			get_block_t *get_block, struct writeback_control *wbc)
+@@ -1606,7 +1616,8 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
+ 	struct buffer_head *bh, *head;
+ 	const unsigned blocksize = 1 << inode->i_blkbits;
+ 	int nr_underway = 0;
+-	int write_op = (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE);
++	int write_op = (wbc->sync_mode == WB_SYNC_ALL ?
++			WRITE_SYNC_PLUG : WRITE);
+ 
+ 	BUG_ON(!PageLocked(page));
+ 

commit e7c8f5079ed9ec9e6eb1abe3defc5fb4ebfdf1cb
+Author: Theodore Ts'o 
+Date:   Fri Apr 3 01:34:49 2009 -0400
+
+    ext3: Add replace-on-rename hueristics for data=writeback mode
+    
+    In data=writeback mode, start an asynchronous flush when renaming a
+    file on top of an already-existing file.  This lowers the probability
+    of data loss in the case of applications that attempt to replace a
+    file via using rename().
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
+index 4db4ffa1edad..ab98a66ab8c7 100644
+--- a/fs/ext3/namei.c
++++ b/fs/ext3/namei.c
+@@ -2265,7 +2265,7 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
+ 	struct inode * old_inode, * new_inode;
+ 	struct buffer_head * old_bh, * new_bh, * dir_bh;
+ 	struct ext3_dir_entry_2 * old_de, * new_de;
+-	int retval;
++	int retval, flush_file = 0;
+ 
+ 	old_bh = new_bh = dir_bh = NULL;
+ 
+@@ -2401,6 +2401,8 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
+ 		ext3_mark_inode_dirty(handle, new_inode);
+ 		if (!new_inode->i_nlink)
+ 			ext3_orphan_add(handle, new_inode);
++		if (ext3_should_writeback_data(new_inode))
++			flush_file = 1;
+ 	}
+ 	retval = 0;
+ 
+@@ -2409,6 +2411,8 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
+ 	brelse (old_bh);
+ 	brelse (new_bh);
+ 	ext3_journal_stop(handle);
++	if (retval == 0 && flush_file)
++		filemap_flush(old_inode->i_mapping);
+ 	return retval;
+ }
+ 

commit f7ab34ea723ed304b19698efca85d6f40cecd99b
+Author: Theodore Ts'o 
+Date:   Fri Apr 3 01:34:35 2009 -0400
+
+    ext3: Add replace-on-truncate hueristics for data=writeback mode
+    
+    In data=writeback mode, start an asynchronous flush when closing a
+    file which had been previously truncated down to zero.  This lowers
+    the probability of data loss in the case of applications that attempt
+    to replace a file using truncate.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext3/file.c b/fs/ext3/file.c
+index 3be1e0689c9a..4a04cbb1c231 100644
+--- a/fs/ext3/file.c
++++ b/fs/ext3/file.c
+@@ -33,6 +33,10 @@
+  */
+ static int ext3_release_file (struct inode * inode, struct file * filp)
+ {
++	if (EXT3_I(inode)->i_state & EXT3_STATE_FLUSH_ON_CLOSE) {
++		filemap_flush(inode->i_mapping);
++		EXT3_I(inode)->i_state &= ~EXT3_STATE_FLUSH_ON_CLOSE;
++	}
+ 	/* if we are the last writer on the inode, drop the block reservation */
+ 	if ((filp->f_mode & FMODE_WRITE) &&
+ 			(atomic_read(&inode->i_writecount) == 1))
+diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
+index 5fa453b49a64..0f5bca0d82fc 100644
+--- a/fs/ext3/inode.c
++++ b/fs/ext3/inode.c
+@@ -2346,6 +2346,9 @@ void ext3_truncate(struct inode *inode)
+ 	if (!ext3_can_truncate(inode))
+ 		return;
+ 
++	if (inode->i_size == 0 && ext3_should_writeback_data(inode))
++		ei->i_state |= EXT3_STATE_FLUSH_ON_CLOSE;
++
+ 	/*
+ 	 * We have to lock the EOF page here, because lock_page() nests
+ 	 * outside journal_start().
+diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
+index dd495b8c3091..d2630c56cb34 100644
+--- a/include/linux/ext3_fs.h
++++ b/include/linux/ext3_fs.h
+@@ -208,6 +208,7 @@ static inline __u32 ext3_mask_flags(umode_t mode, __u32 flags)
+ #define EXT3_STATE_JDATA		0x00000001 /* journaled data exists */
+ #define EXT3_STATE_NEW			0x00000002 /* inode is newly created */
+ #define EXT3_STATE_XATTR		0x00000004 /* has in-inode xattrs */
++#define EXT3_STATE_FLUSH_ON_CLOSE	0x00000008
+ 
+ /* Used to pass group descriptor data when online resize is done */
+ struct ext3_new_group_input {

commit c6b37801911d7f4663c99cad8aa230bc934cea82
+Author: Tim Abbott 
+Date:   Fri Dec 5 19:03:59 2008 -0500
+
+    module: Export symbols needed for Ksplice
+    
+    Impact: Expose some module.c symbols
+    
+    Ksplice uses several functions from module.c in order to resolve
+    symbols and implement dependency handling.  Calling these functions
+    requires holding module_mutex, so it is exported.
+    
+    (This is just the module part of a bigger add-exports patch from Tim).
+    
+    Cc: Anders Kaseorg 
+    Cc: Jeff Arnold 
+    Signed-off-by: Tim Abbott 
+    Signed-off-by: Rusty Russell 
+
+diff --git a/include/linux/module.h b/include/linux/module.h
+index c3d3fc4ffb18..d246da0b0f8c 100644
+--- a/include/linux/module.h
++++ b/include/linux/module.h
+@@ -354,6 +354,8 @@ struct module
+ #define MODULE_ARCH_INIT {}
+ #endif
+ 
++extern struct mutex module_mutex;
++
+ /* FIXME: It'd be nice to isolate modules during init, too, so they
+    aren't used before they (may) fail.  But presently too much code
+    (IDE & SCSI) require entry into the module during init.*/
+@@ -379,6 +381,31 @@ static inline int within_module_init(unsigned long addr, struct module *mod)
+ 	       addr < (unsigned long)mod->module_init + mod->init_size;
+ }
+ 
++/* Search for module by name: must hold module_mutex. */
++struct module *find_module(const char *name);
++
++struct symsearch {
++	const struct kernel_symbol *start, *stop;
++	const unsigned long *crcs;
++	enum {
++		NOT_GPL_ONLY,
++		GPL_ONLY,
++		WILL_BE_GPL_ONLY,
++	} licence;
++	bool unused;
++};
++
++/* Search for an exported symbol by name. */
++const struct kernel_symbol *find_symbol(const char *name,
++					struct module **owner,
++					const unsigned long **crc,
++					bool gplok,
++					bool warn);
++
++/* Walk the exported symbol table */
++bool each_symbol(bool (*fn)(const struct symsearch *arr, struct module *owner,
++			    unsigned int symnum, void *data), void *data);
++
+ /* Returns 0 and fills in value, defined and namebuf, or -ERANGE if
+    symnum out of range. */
+ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
+@@ -452,6 +479,7 @@ static inline void __module_get(struct module *module)
+ #define symbol_put_addr(p) do { } while(0)
+ 
+ #endif /* CONFIG_MODULE_UNLOAD */
++int use_module(struct module *a, struct module *b);
+ 
+ /* This is a #define so the string doesn't get put in every .o file */
+ #define module_name(mod)			\
+diff --git a/kernel/module.c b/kernel/module.c
+index dd4389be9152..5fd00766a4dc 100644
+--- a/kernel/module.c
++++ b/kernel/module.c
+@@ -68,7 +68,8 @@
+ 
+ /* List of modules, protected by module_mutex or preempt_disable
+  * (delete uses stop_machine/add uses RCU list operations). */
+-static DEFINE_MUTEX(module_mutex);
++DEFINE_MUTEX(module_mutex);
++EXPORT_SYMBOL_GPL(module_mutex);
+ static LIST_HEAD(modules);
+ 
+ /* Waiting for a module to finish initializing? */
+@@ -186,17 +187,6 @@ extern const unsigned long __start___kcrctab_unused_gpl[];
+ #define symversion(base, idx) ((base != NULL) ? ((base) + (idx)) : NULL)
+ #endif
+ 
+-struct symsearch {
+-	const struct kernel_symbol *start, *stop;
+-	const unsigned long *crcs;
+-	enum {
+-		NOT_GPL_ONLY,
+-		GPL_ONLY,
+-		WILL_BE_GPL_ONLY,
+-	} licence;
+-	bool unused;
+-};
+-
+ static bool each_symbol_in_section(const struct symsearch *arr,
+ 				   unsigned int arrsize,
+ 				   struct module *owner,
+@@ -217,10 +207,8 @@ static bool each_symbol_in_section(const struct symsearch *arr,
+ }
+ 
+ /* Returns true as soon as fn returns true, otherwise false. */
+-static bool each_symbol(bool (*fn)(const struct symsearch *arr,
+-				   struct module *owner,
+-				   unsigned int symnum, void *data),
+-			void *data)
++bool each_symbol(bool (*fn)(const struct symsearch *arr, struct module *owner,
++			    unsigned int symnum, void *data), void *data)
+ {
+ 	struct module *mod;
+ 	const struct symsearch arr[] = {
+@@ -273,6 +261,7 @@ static bool each_symbol(bool (*fn)(const struct symsearch *arr,
+ 	}
+ 	return false;
+ }
++EXPORT_SYMBOL_GPL(each_symbol);
+ 
+ struct find_symbol_arg {
+ 	/* Input */
+@@ -330,11 +319,11 @@ static bool find_symbol_in_section(const struct symsearch *syms,
+ 
+ /* Find a symbol and return it, along with, (optional) crc and
+  * (optional) module which owns it */
+-static const struct kernel_symbol *find_symbol(const char *name,
+-					       struct module **owner,
+-					       const unsigned long **crc,
+-					       bool gplok,
+-					       bool warn)
++const struct kernel_symbol *find_symbol(const char *name,
++					struct module **owner,
++					const unsigned long **crc,
++					bool gplok,
++					bool warn)
+ {
+ 	struct find_symbol_arg fsa;
+ 
+@@ -353,9 +342,10 @@ static const struct kernel_symbol *find_symbol(const char *name,
+ 	DEBUGP("Failed to find symbol %s\n", name);
+ 	return NULL;
+ }
++EXPORT_SYMBOL_GPL(find_symbol);
+ 
+ /* Search for module by name: must hold module_mutex. */
+-static struct module *find_module(const char *name)
++struct module *find_module(const char *name)
+ {
+ 	struct module *mod;
+ 
+@@ -365,6 +355,7 @@ static struct module *find_module(const char *name)
+ 	}
+ 	return NULL;
+ }
++EXPORT_SYMBOL_GPL(find_module);
+ 
+ #ifdef CONFIG_SMP
+ 
+@@ -641,7 +632,7 @@ static int already_uses(struct module *a, struct module *b)
+ }
+ 
+ /* Module a uses b */
+-static int use_module(struct module *a, struct module *b)
++int use_module(struct module *a, struct module *b)
+ {
+ 	struct module_use *use;
+ 	int no_warn, err;
+@@ -674,6 +665,7 @@ static int use_module(struct module *a, struct module *b)
+ 	no_warn = sysfs_create_link(b->holders_dir, &a->mkobj.kobj, a->name);
+ 	return 1;
+ }
++EXPORT_SYMBOL_GPL(use_module);
+ 
+ /* Clear the unload stuff of the module. */
+ static void module_unload_free(struct module *mod)
+@@ -951,10 +943,11 @@ static inline void module_unload_free(struct module *mod)
+ {
+ }
+ 
+-static inline int use_module(struct module *a, struct module *b)
++int use_module(struct module *a, struct module *b)
+ {
+ 	return strong_try_module_get(b) == 0;
+ }
++EXPORT_SYMBOL_GPL(use_module);
+ 
+ static inline void module_unload_init(struct module *mod)
+ {
+@@ -2803,6 +2796,7 @@ __notrace_funcgraph struct module *__module_address(unsigned long addr)
+ 			return mod;
+ 	return NULL;
+ }
++EXPORT_SYMBOL_GPL(__module_address);
+ 
+ /*
+  * is_module_text_address - is this address inside module code?
+@@ -2841,6 +2835,7 @@ struct module *__module_text_address(unsigned long addr)
+ 	}
+ 	return mod;
+ }
++EXPORT_SYMBOL_GPL(__module_text_address);
+ 
+ /* Don't grab lock, we're oopsing. */
+ void print_modules(void)

commit 75a66614db21007bcc8c37f9c5d5b922981387b9
+Author: Anders Kaseorg 
+Date:   Fri Dec 5 19:03:58 2008 -0500
+
+    Ksplice: Add functions for walking kallsyms symbols
+    
+    Impact: New API
+    
+    kallsyms_lookup_name only returns the first match that it finds.  Ksplice
+    needs information about all symbols with a given name in order to correctly
+    resolve local symbols.
+    
+    kallsyms_on_each_symbol provides a generic mechanism for iterating over the
+    kallsyms table.
+    
+    Cc: Jeff Arnold 
+    Cc: Tim Abbott 
+    Signed-off-by: Anders Kaseorg 
+    Signed-off-by: Rusty Russell 
+
+diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h
+index f3fe34391d8e..792274269f2b 100644
+--- a/include/linux/kallsyms.h
++++ b/include/linux/kallsyms.h
+@@ -13,10 +13,17 @@
+ #define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + (KSYM_NAME_LEN - 1) + \
+ 			 2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + 1)
+ 
++struct module;
++
+ #ifdef CONFIG_KALLSYMS
+ /* Lookup the address for a symbol. Returns 0 if not found. */
+ unsigned long kallsyms_lookup_name(const char *name);
+ 
++/* Call a function on each kallsyms symbol in the core kernel */
++int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
++				      unsigned long),
++			    void *data);
++
+ extern int kallsyms_lookup_size_offset(unsigned long addr,
+ 				  unsigned long *symbolsize,
+ 				  unsigned long *offset);
+@@ -43,6 +50,14 @@ static inline unsigned long kallsyms_lookup_name(const char *name)
+ 	return 0;
+ }
+ 
++static inline int kallsyms_on_each_symbol(int (*fn)(void *, const char *,
++						    struct module *,
++						    unsigned long),
++					  void *data)
++{
++	return 0;
++}
++
+ static inline int kallsyms_lookup_size_offset(unsigned long addr,
+ 					      unsigned long *symbolsize,
+ 					      unsigned long *offset)
+diff --git a/include/linux/module.h b/include/linux/module.h
+index 69761ce0dbf0..c3d3fc4ffb18 100644
+--- a/include/linux/module.h
++++ b/include/linux/module.h
+@@ -387,6 +387,10 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
+ /* Look for this name: can be of form module:name. */
+ unsigned long module_kallsyms_lookup_name(const char *name);
+ 
++int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
++					     struct module *, unsigned long),
++				   void *data);
++
+ extern void __module_put_and_exit(struct module *mod, long code)
+ 	__attribute__((noreturn));
+ #define module_put_and_exit(code) __module_put_and_exit(THIS_MODULE, code);
+@@ -566,6 +570,14 @@ static inline unsigned long module_kallsyms_lookup_name(const char *name)
+ 	return 0;
+ }
+ 
++static inline int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
++							   struct module *,
++							   unsigned long),
++						 void *data)
++{
++	return 0;
++}
++
+ static inline int register_module_notifier(struct notifier_block * nb)
+ {
+ 	/* no events will happen anyway, so this can always succeed */
+diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
+index 7b8b0f21a5b1..374faf9bfdc7 100644
+--- a/kernel/kallsyms.c
++++ b/kernel/kallsyms.c
+@@ -161,6 +161,25 @@ unsigned long kallsyms_lookup_name(const char *name)
+ 	return module_kallsyms_lookup_name(name);
+ }
+ 
++int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
++				      unsigned long),
++			    void *data)
++{
++	char namebuf[KSYM_NAME_LEN];
++	unsigned long i;
++	unsigned int off;
++	int ret;
++
++	for (i = 0, off = 0; i < kallsyms_num_syms; i++) {
++		off = kallsyms_expand_symbol(off, namebuf);
++		ret = fn(data, namebuf, NULL, kallsyms_addresses[i]);
++		if (ret != 0)
++			return ret;
++	}
++	return module_kallsyms_on_each_symbol(fn, data);
++}
++EXPORT_SYMBOL_GPL(kallsyms_on_each_symbol);
++
+ static unsigned long get_symbol_pos(unsigned long addr,
+ 				    unsigned long *symbolsize,
+ 				    unsigned long *offset)
+diff --git a/kernel/module.c b/kernel/module.c
+index 8ddca629e079..dd4389be9152 100644
+--- a/kernel/module.c
++++ b/kernel/module.c
+@@ -2612,6 +2612,25 @@ unsigned long module_kallsyms_lookup_name(const char *name)
+ 	preempt_enable();
+ 	return ret;
+ }
++
++int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
++					     struct module *, unsigned long),
++				   void *data)
++{
++	struct module *mod;
++	unsigned int i;
++	int ret;
++
++	list_for_each_entry(mod, &modules, list) {
++		for (i = 0; i < mod->num_symtab; i++) {
++			ret = fn(data, mod->strtab + mod->symtab[i].st_name,
++				 mod, mod->symtab[i].st_value);
++			if (ret != 0)
++				return ret;
++		}
++	}
++	return 0;
++}
+ #endif /* CONFIG_KALLSYMS */
+ 
+ static char *module_flags(struct module *mod, char *buf)

commit 414fd31b2553aaf160ca9b9afe45aa0372b01b92
+Author: Tim Abbott 
+Date:   Fri Dec 5 19:03:56 2008 -0500
+
+    module: Make find_symbol return a struct kernel_symbol
+    
+    Impact: Cleanup, internal API change
+    
+    Ksplice needs access to the kernel_symbol structure in order to support
+    modifications to the exported symbol table.
+    
+    Cc: Anders Kaseorg 
+    Cc: Jeff Arnold 
+    Signed-off-by: Tim Abbott 
+    Signed-off-by: Rusty Russell  (bugfix and style)
+
+diff --git a/kernel/module.c b/kernel/module.c
+index 7af72bbe4cc0..2f0fddf3c114 100644
+--- a/kernel/module.c
++++ b/kernel/module.c
+@@ -283,7 +283,7 @@ struct find_symbol_arg {
+ 	/* Output */
+ 	struct module *owner;
+ 	const unsigned long *crc;
+-	unsigned long value;
++	const struct kernel_symbol *sym;
+ };
+ 
+ static bool find_symbol_in_section(const struct symsearch *syms,
+@@ -324,17 +324,17 @@ static bool find_symbol_in_section(const struct symsearch *syms,
+ 
+ 	fsa->owner = owner;
+ 	fsa->crc = symversion(syms->crcs, symnum);
+-	fsa->value = syms->start[symnum].value;
++	fsa->sym = &syms->start[symnum];
+ 	return true;
+ }
+ 
+-/* Find a symbol, return value, (optional) crc and (optional) module
+- * which owns it */
+-static unsigned long find_symbol(const char *name,
+-				 struct module **owner,
+-				 const unsigned long **crc,
+-				 bool gplok,
+-				 bool warn)
++/* Find a symbol and return it, along with, (optional) crc and
++ * (optional) module which owns it */
++static const struct kernel_symbol *find_symbol(const char *name,
++					       struct module **owner,
++					       const unsigned long **crc,
++					       bool gplok,
++					       bool warn)
+ {
+ 	struct find_symbol_arg fsa;
+ 
+@@ -347,11 +347,11 @@ static unsigned long find_symbol(const char *name,
+ 			*owner = fsa.owner;
+ 		if (crc)
+ 			*crc = fsa.crc;
+-		return fsa.value;
++		return fsa.sym;
+ 	}
+ 
+ 	DEBUGP("Failed to find symbol %s\n", name);
+-	return -ENOENT;
++	return NULL;
+ }
+ 
+ /* Search for module by name: must hold module_mutex. */
+@@ -894,7 +894,7 @@ void __symbol_put(const char *symbol)
+ 	struct module *owner;
+ 
+ 	preempt_disable();
+-	if (IS_ERR_VALUE(find_symbol(symbol, &owner, NULL, true, false)))
++	if (!find_symbol(symbol, &owner, NULL, true, false))
+ 		BUG();
+ 	module_put(owner);
+ 	preempt_enable();
+@@ -1057,7 +1057,7 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs,
+ {
+ 	const unsigned long *crc;
+ 
+-	if (IS_ERR_VALUE(find_symbol("struct_module", NULL, &crc, true, false)))
++	if (!find_symbol("struct_module", NULL, &crc, true, false))
+ 		BUG();
+ 	return check_version(sechdrs, versindex, "struct_module", mod, crc);
+ }
+@@ -1098,25 +1098,25 @@ static inline int same_magic(const char *amagic, const char *bmagic,
+ 
+ /* Resolve a symbol for this module.  I.e. if we find one, record usage.
+    Must be holding module_mutex. */
+-static unsigned long resolve_symbol(Elf_Shdr *sechdrs,
+-				    unsigned int versindex,
+-				    const char *name,
+-				    struct module *mod)
++static const struct kernel_symbol *resolve_symbol(Elf_Shdr *sechdrs,
++						  unsigned int versindex,
++						  const char *name,
++						  struct module *mod)
+ {
+ 	struct module *owner;
+-	unsigned long ret;
++	const struct kernel_symbol *sym;
+ 	const unsigned long *crc;
+ 
+-	ret = find_symbol(name, &owner, &crc,
++	sym = find_symbol(name, &owner, &crc,
+ 			  !(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true);
+-	if (!IS_ERR_VALUE(ret)) {
+-		/* use_module can fail due to OOM,
+-		   or module initialization or unloading */
++	/* use_module can fail due to OOM,
++	   or module initialization or unloading */
++	if (sym) {
+ 		if (!check_version(sechdrs, versindex, name, mod, crc) ||
+ 		    !use_module(mod, owner))
+-			ret = -EINVAL;
++			sym = NULL;
+ 	}
+-	return ret;
++	return sym;
+ }
+ 
+ /*
+@@ -1516,17 +1516,15 @@ static void free_module(struct module *mod)
+ void *__symbol_get(const char *symbol)
+ {
+ 	struct module *owner;
+-	unsigned long value;
++	const struct kernel_symbol *sym;
+ 
+ 	preempt_disable();
+-	value = find_symbol(symbol, &owner, NULL, true, true);
+-	if (IS_ERR_VALUE(value))
+-		value = 0;
+-	else if (strong_try_module_get(owner))
+-		value = 0;
++	sym = find_symbol(symbol, &owner, NULL, true, true);
++	if (sym && strong_try_module_get(owner))
++		sym = NULL;
+ 	preempt_enable();
+ 
+-	return (void *)value;
++	return sym ? (void *)sym->value : NULL;
+ }
+ EXPORT_SYMBOL_GPL(__symbol_get);
+ 
+@@ -1554,8 +1552,7 @@ static int verify_export_symbols(struct module *mod)
+ 
+ 	for (i = 0; i < ARRAY_SIZE(arr); i++) {
+ 		for (s = arr[i].sym; s < arr[i].sym + arr[i].num; s++) {
+-			if (!IS_ERR_VALUE(find_symbol(s->name, &owner,
+-						      NULL, true, false))) {
++			if (find_symbol(s->name, &owner, NULL, true, false)) {
+ 				printk(KERN_ERR
+ 				       "%s: exports duplicate symbol %s"
+ 				       " (owned by %s)\n",
+@@ -1579,6 +1576,7 @@ static int simplify_symbols(Elf_Shdr *sechdrs,
+ 	unsigned long secbase;
+ 	unsigned int i, n = sechdrs[symindex].sh_size / sizeof(Elf_Sym);
+ 	int ret = 0;
++	const struct kernel_symbol *ksym;
+ 
+ 	for (i = 1; i < n; i++) {
+ 		switch (sym[i].st_shndx) {
+@@ -1598,13 +1596,14 @@ static int simplify_symbols(Elf_Shdr *sechdrs,
+ 			break;
+ 
+ 		case SHN_UNDEF:
+-			sym[i].st_value
+-			  = resolve_symbol(sechdrs, versindex,
+-					   strtab + sym[i].st_name, mod);
+-
++			ksym = resolve_symbol(sechdrs, versindex,
++					      strtab + sym[i].st_name, mod);
+ 			/* Ok if resolved.  */
+-			if (!IS_ERR_VALUE(sym[i].st_value))
++			if (ksym) {
++				sym[i].st_value = ksym->value;
+ 				break;
++			}
++
+ 			/* Ok if weak.  */
+ 			if (ELF_ST_BIND(sym[i].st_info) == STB_WEAK)
+ 				break;

commit 06705bff9114531a997a7d0c2520bea0f2927410
+Author: Theodore Ts'o 
+Date:   Sat Mar 28 10:59:57 2009 -0400
+
+    ext4: Regularize mount options
+    
+    Add support for using the mount options "barrier" and "nobarrier", and
+    "auto_da_alloc" and "noauto_da_alloc", which is more consistent than
+    "barrier=<0|1>" or "auto_da_alloc=<0|1>".  Most other ext3/ext4 mount
+    options use the foo/nofoo naming convention.  We allow the old forms
+    of these mount options for backwards compatibility.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
+index 5c484aec2bab..97882df04865 100644
+--- a/Documentation/filesystems/ext4.txt
++++ b/Documentation/filesystems/ext4.txt
+@@ -183,8 +183,8 @@ commit=nrsec	(*)	Ext4 can be told to sync all its data and metadata
+ 			performance.
+ 
+ barrier=<0|1(*)>	This enables/disables the use of write barriers in
+-			the jbd code.  barrier=0 disables, barrier=1 enables.
+-			This also requires an IO stack which can support
++barrier(*)		the jbd code.  barrier=0 disables, barrier=1 enables.
++nobarrier		This also requires an IO stack which can support
+ 			barriers, and if jbd gets an error on a barrier
+ 			write, it will disable again with a warning.
+ 			Write barriers enforce proper on-disk ordering
+@@ -192,6 +192,9 @@ barrier=<0|1(*)>	This enables/disables the use of write barriers in
+ 			safe to use, at some performance penalty.  If
+ 			your disks are battery-backed in one way or another,
+ 			disabling barriers may safely improve performance.
++			The mount options "barrier" and "nobarrier" can
++			also be used to enable or disable barriers, for
++			consistency with other ext4 mount options.
+ 
+ inode_readahead=n	This tuning parameter controls the maximum
+ 			number of inode table blocks that ext4's inode
+@@ -313,6 +316,24 @@ journal_ioprio=prio	The I/O priority (from 0 to 7, where 0 is the
+ 			a slightly higher priority than the default I/O
+ 			priority.
+ 
++auto_da_alloc(*)	Many broken applications don't use fsync() when 
++noauto_da_alloc		replacing existing files via patterns such as
++			fd = open("foo.new")/write(fd,..)/close(fd)/
++			rename("foo.new", "foo"), or worse yet,
++			fd = open("foo", O_TRUNC)/write(fd,..)/close(fd).
++			If auto_da_alloc is enabled, ext4 will detect
++			the replace-via-rename and replace-via-truncate
++			patterns and force that any delayed allocation
++			blocks are allocated such that at the next
++			journal commit, in the default data=ordered
++			mode, the data blocks of the new file are forced
++			to disk before the rename() operation is
++			commited.  This provides roughly the same level
++			of guarantees as ext3, and avoids the
++			"zero-length" problem that can happen when a
++			system crashes before the delayed allocation
++			blocks are forced to disk.
++
+ Data Mode
+ =========
+ There are 3 different data modes:
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 45d07cf9df34..9987bba99db3 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -867,7 +867,7 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
+ 		seq_puts(seq, ",data_err=abort");
+ 
+ 	if (test_opt(sb, NO_AUTO_DA_ALLOC))
+-		seq_puts(seq, ",auto_da_alloc=0");
++		seq_puts(seq, ",noauto_da_alloc");
+ 
+ 	ext4_show_quota_options(seq, sb);
+ 	return 0;
+@@ -1018,7 +1018,7 @@ enum {
+ 	Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro,
+ 	Opt_nouid32, Opt_debug, Opt_oldalloc, Opt_orlov,
+ 	Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
+-	Opt_auto_da_alloc, Opt_noload, Opt_nobh, Opt_bh,
++	Opt_auto_da_alloc, Opt_noauto_da_alloc, Opt_noload, Opt_nobh, Opt_bh,
+ 	Opt_commit, Opt_min_batch_time, Opt_max_batch_time,
+ 	Opt_journal_update, Opt_journal_dev,
+ 	Opt_journal_checksum, Opt_journal_async_commit,
+@@ -1026,8 +1026,8 @@ enum {
+ 	Opt_data_err_abort, Opt_data_err_ignore,
+ 	Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
+ 	Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
+-	Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
+-	Opt_grpquota, Opt_i_version,
++	Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err, Opt_resize,
++	Opt_usrquota, Opt_grpquota, Opt_i_version,
+ 	Opt_stripe, Opt_delalloc, Opt_nodelalloc,
+ 	Opt_inode_readahead_blks, Opt_journal_ioprio
+ };
+@@ -1080,6 +1080,8 @@ static const match_table_t tokens = {
+ 	{Opt_quota, "quota"},
+ 	{Opt_usrquota, "usrquota"},
+ 	{Opt_barrier, "barrier=%u"},
++	{Opt_barrier, "barrier"},
++	{Opt_nobarrier, "nobarrier"},
+ 	{Opt_i_version, "i_version"},
+ 	{Opt_stripe, "stripe=%u"},
+ 	{Opt_resize, "resize"},
+@@ -1088,6 +1090,8 @@ static const match_table_t tokens = {
+ 	{Opt_inode_readahead_blks, "inode_readahead_blks=%u"},
+ 	{Opt_journal_ioprio, "journal_ioprio=%u"},
+ 	{Opt_auto_da_alloc, "auto_da_alloc=%u"},
++	{Opt_auto_da_alloc, "auto_da_alloc"},
++	{Opt_noauto_da_alloc, "noauto_da_alloc"},
+ 	{Opt_err, NULL},
+ };
+ 
+@@ -1422,9 +1426,14 @@ static int parse_options(char *options, struct super_block *sb,
+ 		case Opt_abort:
+ 			set_opt(sbi->s_mount_opt, ABORT);
+ 			break;
++		case Opt_nobarrier:
++			clear_opt(sbi->s_mount_opt, BARRIER);
++			break;
+ 		case Opt_barrier:
+-			if (match_int(&args[0], &option))
+-				return 0;
++			if (match_int(&args[0], &option)) {
++				set_opt(sbi->s_mount_opt, BARRIER);
++				break;
++			}
+ 			if (option)
+ 				set_opt(sbi->s_mount_opt, BARRIER);
+ 			else
+@@ -1485,9 +1494,14 @@ static int parse_options(char *options, struct super_block *sb,
+ 			*journal_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE,
+ 							    option);
+ 			break;
++		case Opt_noauto_da_alloc:
++			set_opt(sbi->s_mount_opt,NO_AUTO_DA_ALLOC);
++			break;
+ 		case Opt_auto_da_alloc:
+-			if (match_int(&args[0], &option))
+-				return 0;
++			if (match_int(&args[0], &option)) {
++				clear_opt(sbi->s_mount_opt, NO_AUTO_DA_ALLOC);
++				break;
++			}
+ 			if (option)
+ 				clear_opt(sbi->s_mount_opt, NO_AUTO_DA_ALLOC);
+ 			else

commit 512a004382f2c60d5c4f855476ba965adc00250c
+Author: Theodore Ts'o 
+Date:   Fri Mar 27 22:14:27 2009 -0400
+
+    ext3: Use WRITE_SYNC for commits which are caused by fsync()
+    
+    If a commit is triggered by fsync(), set a flag indicating the journal
+    blocks associated with the transaction should be flushed out using
+    WRITE_SYNC.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Acked-by: Jan Kara 
+
+diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
+index 3fbffb1ea714..f8077b9c8981 100644
+--- a/fs/jbd/commit.c
++++ b/fs/jbd/commit.c
+@@ -20,6 +20,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ /*
+  * Default IO end handler for temporary BJ_IO buffer_heads.
+@@ -171,14 +172,15 @@ static int journal_write_commit_record(journal_t *journal,
+ 	return (ret == -EIO);
+ }
+ 
+-static void journal_do_submit_data(struct buffer_head **wbuf, int bufs)
++static void journal_do_submit_data(struct buffer_head **wbuf, int bufs,
++				   int write_op)
+ {
+ 	int i;
+ 
+ 	for (i = 0; i < bufs; i++) {
+ 		wbuf[i]->b_end_io = end_buffer_write_sync;
+ 		/* We use-up our safety reference in submit_bh() */
+-		submit_bh(WRITE, wbuf[i]);
++		submit_bh(write_op, wbuf[i]);
+ 	}
+ }
+ 
+@@ -186,7 +188,8 @@ static void journal_do_submit_data(struct buffer_head **wbuf, int bufs)
+  *  Submit all the data buffers to disk
+  */
+ static int journal_submit_data_buffers(journal_t *journal,
+-				transaction_t *commit_transaction)
++				       transaction_t *commit_transaction,
++				       int write_op)
+ {
+ 	struct journal_head *jh;
+ 	struct buffer_head *bh;
+@@ -225,7 +228,7 @@ static int journal_submit_data_buffers(journal_t *journal,
+ 				BUFFER_TRACE(bh, "needs blocking lock");
+ 				spin_unlock(&journal->j_list_lock);
+ 				/* Write out all data to prevent deadlocks */
+-				journal_do_submit_data(wbuf, bufs);
++				journal_do_submit_data(wbuf, bufs, write_op);
+ 				bufs = 0;
+ 				lock_buffer(bh);
+ 				spin_lock(&journal->j_list_lock);
+@@ -256,7 +259,7 @@ static int journal_submit_data_buffers(journal_t *journal,
+ 			jbd_unlock_bh_state(bh);
+ 			if (bufs == journal->j_wbufsize) {
+ 				spin_unlock(&journal->j_list_lock);
+-				journal_do_submit_data(wbuf, bufs);
++				journal_do_submit_data(wbuf, bufs, write_op);
+ 				bufs = 0;
+ 				goto write_out_data;
+ 			}
+@@ -286,7 +289,7 @@ static int journal_submit_data_buffers(journal_t *journal,
+ 		}
+ 	}
+ 	spin_unlock(&journal->j_list_lock);
+-	journal_do_submit_data(wbuf, bufs);
++	journal_do_submit_data(wbuf, bufs, write_op);
+ 
+ 	return err;
+ }
+@@ -315,6 +318,7 @@ void journal_commit_transaction(journal_t *journal)
+ 	int first_tag = 0;
+ 	int tag_flag;
+ 	int i;
++	int write_op = WRITE;
+ 
+ 	/*
+ 	 * First job: lock down the current transaction and wait for
+@@ -347,6 +351,8 @@ void journal_commit_transaction(journal_t *journal)
+ 	spin_lock(&journal->j_state_lock);
+ 	commit_transaction->t_state = T_LOCKED;
+ 
++	if (commit_transaction->t_synchronous_commit)
++		write_op = WRITE_SYNC;
+ 	spin_lock(&commit_transaction->t_handle_lock);
+ 	while (commit_transaction->t_updates) {
+ 		DEFINE_WAIT(wait);
+@@ -431,7 +437,8 @@ void journal_commit_transaction(journal_t *journal)
+ 	 * Now start flushing things to disk, in the order they appear
+ 	 * on the transaction lists.  Data blocks go first.
+ 	 */
+-	err = journal_submit_data_buffers(journal, commit_transaction);
++	err = journal_submit_data_buffers(journal, commit_transaction,
++					  write_op);
+ 
+ 	/*
+ 	 * Wait for all previously submitted IO to complete.
+@@ -660,7 +667,7 @@ void journal_commit_transaction(journal_t *journal)
+ 				clear_buffer_dirty(bh);
+ 				set_buffer_uptodate(bh);
+ 				bh->b_end_io = journal_end_buffer_io_sync;
+-				submit_bh(WRITE, bh);
++				submit_bh(write_op, bh);
+ 			}
+ 			cond_resched();
+ 
+diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
+index e6a117431277..ed886e6db399 100644
+--- a/fs/jbd/transaction.c
++++ b/fs/jbd/transaction.c
+@@ -1440,6 +1440,8 @@ int journal_stop(handle_t *handle)
+ 		}
+ 	}
+ 
++	if (handle->h_sync)
++		transaction->t_synchronous_commit = 1;
+ 	current->journal_info = NULL;
+ 	spin_lock(&journal->j_state_lock);
+ 	spin_lock(&transaction->t_handle_lock);
+diff --git a/include/linux/jbd.h b/include/linux/jbd.h
+index 64246dce5663..2c6943152c21 100644
+--- a/include/linux/jbd.h
++++ b/include/linux/jbd.h
+@@ -552,6 +552,11 @@ struct transaction_s
+ 	 */
+ 	int t_handle_count;
+ 
++	/*
++	 * This transaction is being forced and some process is
++	 * waiting for it to finish.
++	 */
++	int t_synchronous_commit:1;
+ };
+ 
+ /**

commit a64c8610bd3b753c6aff58f51c04cdf0ae478c18
+Author: Theodore Ts'o 
+Date:   Fri Mar 27 22:14:10 2009 -0400
+
+    block_write_full_page: Use synchronous writes for WBC_SYNC_ALL writebacks
+    
+    When doing synchronous writes because wbc->sync_mode is set to
+    WBC_SYNC_ALL, send the write request using WRITE_SYNC, so that we
+    don't unduly block system calls such as fsync().
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Acked-by: Jan Kara 
+
+diff --git a/fs/buffer.c b/fs/buffer.c
+index 891e1c78e4f1..e7ebd95e0c68 100644
+--- a/fs/buffer.c
++++ b/fs/buffer.c
+@@ -1714,6 +1714,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
+ 	struct buffer_head *bh, *head;
+ 	const unsigned blocksize = 1 << inode->i_blkbits;
+ 	int nr_underway = 0;
++	int write_op = (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE);
+ 
+ 	BUG_ON(!PageLocked(page));
+ 
+@@ -1805,7 +1806,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
+ 	do {
+ 		struct buffer_head *next = bh->b_this_page;
+ 		if (buffer_async_write(bh)) {
+-			submit_bh(WRITE, bh);
++			submit_bh(write_op, bh);
+ 			nr_underway++;
+ 		}
+ 		bh = next;
+@@ -1859,7 +1860,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
+ 		struct buffer_head *next = bh->b_this_page;
+ 		if (buffer_async_write(bh)) {
+ 			clear_buffer_dirty(bh);
+-			submit_bh(WRITE, bh);
++			submit_bh(write_op, bh);
+ 			nr_underway++;
+ 		}
+ 		bh = next;

commit e7c9e3e99adf6c49c5d593a51375916acc039d1e
+Author: Theodore Ts'o 
+Date:   Fri Mar 27 19:43:21 2009 -0400
+
+    ext4: fix locking typo in mballoc which could cause soft lockup hangs
+    
+    Smatch (http://repo.or.cz/w/smatch.git/) complains about the locking in
+    ext4_mb_add_n_trim() from fs/ext4/mballoc.c
+    
+      4438          list_for_each_entry_rcu(tmp_pa, &lg->lg_prealloc_list[order],
+      4439                                                  pa_inode_list) {
+      4440                  spin_lock(&tmp_pa->pa_lock);
+      4441                  if (tmp_pa->pa_deleted) {
+      4442                          spin_unlock(&pa->pa_lock);
+      4443                          continue;
+      4444                  }
+    
+    Brown paper bag time...
+    
+    Reported-by: Dan Carpenter 
+    Reviewed-by: Eric Sandeen 
+    Reviewed-by: Aneesh Kumar K.V 
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 5f3e3a3a38d6..f871677a7984 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -4392,7 +4392,7 @@ static void ext4_mb_add_n_trim(struct ext4_allocation_context *ac)
+ 						pa_inode_list) {
+ 		spin_lock(&tmp_pa->pa_lock);
+ 		if (tmp_pa->pa_deleted) {
+-			spin_unlock(&pa->pa_lock);
++			spin_unlock(&tmp_pa->pa_lock);
+ 			continue;
+ 		}
+ 		if (!added && pa->pa_free < tmp_pa->pa_free) {

commit 563bdd61fe4dbd6b58cf7eb06f8d8f14479ae1dc
+Author: Theodore Ts'o 
+Date:   Thu Mar 26 00:06:19 2009 -0400
+
+    ext4: Check for an valid i_mode when reading the inode from disk
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index bed4a0abd0d1..c7d9250fbc3f 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4394,7 +4394,8 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 			inode->i_op = &ext4_symlink_inode_operations;
+ 			ext4_set_aops(inode);
+ 		}
+-	} else {
++	} else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
++	      S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
+ 		inode->i_op = &ext4_special_inode_operations;
+ 		if (raw_inode->i_block[0])
+ 			init_special_inode(inode, inode->i_mode,
+@@ -4402,6 +4403,13 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 		else
+ 			init_special_inode(inode, inode->i_mode,
+ 			   new_decode_dev(le32_to_cpu(raw_inode->i_block[1])));
++	} else {
++		brelse(bh);
++		ret = -EIO;
++		ext4_error(inode->i_sb, __func__, 
++			   "bogus i_mode (%o) for inode=%lu",
++			   inode->i_mode, inode->i_ino);
++		goto bad_inode;
+ 	}
+ 	brelse(iloc.bh);
+ 	ext4_set_inode_flags(inode);

commit 7058548cd50e5bda8db086bb2e5c1d82f746d047
+Author: Theodore Ts'o 
+Date:   Wed Mar 25 23:35:46 2009 -0400
+
+    ext4: Use WRITE_SYNC for commits which are caused by fsync()
+    
+    If a commit is triggered by fsync(), set a flag indicating the journal
+    blocks associated with the transaction should be flushed out using
+    WRITE_SYNC.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index 62804e57a44c..4ea72377c7a2 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -367,6 +367,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	int tag_bytes = journal_tag_bytes(journal);
+ 	struct buffer_head *cbh = NULL; /* For transactional checksums */
+ 	__u32 crc32_sum = ~0;
++	int write_op = WRITE;
+ 
+ 	/*
+ 	 * First job: lock down the current transaction and wait for
+@@ -401,6 +402,8 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	spin_lock(&journal->j_state_lock);
+ 	commit_transaction->t_state = T_LOCKED;
+ 
++	if (commit_transaction->t_synchronous_commit)
++		write_op = WRITE_SYNC;
+ 	stats.u.run.rs_wait = commit_transaction->t_max_wait;
+ 	stats.u.run.rs_locked = jiffies;
+ 	stats.u.run.rs_running = jbd2_time_diff(commit_transaction->t_start,
+@@ -680,7 +683,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 				clear_buffer_dirty(bh);
+ 				set_buffer_uptodate(bh);
+ 				bh->b_end_io = journal_end_buffer_io_sync;
+-				submit_bh(WRITE, bh);
++				submit_bh(write_op, bh);
+ 			}
+ 			cond_resched();
+ 			stats.u.run.rs_blocks_logged += bufs;
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index 28ce21d8598e..996ffda06bf3 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -1315,6 +1315,8 @@ int jbd2_journal_stop(handle_t *handle)
+ 		}
+ 	}
+ 
++	if (handle->h_sync)
++		transaction->t_synchronous_commit = 1;
+ 	current->journal_info = NULL;
+ 	spin_lock(&journal->j_state_lock);
+ 	spin_lock(&transaction->t_handle_lock);
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index 4d248b3f1323..8815a3456b3b 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -648,6 +648,12 @@ struct transaction_s
+ 	 */
+ 	int t_handle_count;
+ 
++	/*
++	 * This transaction is being forced and some process is
++	 * waiting for it to finish.
++	 */
++	int t_synchronous_commit:1;
++
+ 	/*
+ 	 * For use by the filesystem to store fs-specific data
+ 	 * structures associated with the transaction

commit afd4672dc7610b7feef5190168aa917cc2e417e4
+Author: Theodore Ts'o 
+Date:   Mon Mar 16 23:12:23 2009 -0400
+
+    ext4: Add auto_da_alloc mount option
+    
+    Add a mount option which allows the user to disable automatic
+    allocation of blocks whose allocation by delayed allocation when the
+    file was originally truncated or when the file is renamed over an
+    existing file.  This feature is intended to save users from the
+    effects of naive application writers, but it reduces the effectiveness
+    of the delayed allocation code.  This mount option disables this
+    safety feature, which may be desirable for prodcutions systems where
+    the risk of unclean shutdowns or unexpected system crashes is low.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 46aaaa2ed4c5..a004699e7296 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -549,7 +549,7 @@ do {									       \
+ #define EXT4_MOUNT_NO_UID32		0x02000  /* Disable 32-bit UIDs */
+ #define EXT4_MOUNT_XATTR_USER		0x04000	/* Extended user attributes */
+ #define EXT4_MOUNT_POSIX_ACL		0x08000	/* POSIX Access Control Lists */
+-#define EXT4_MOUNT_RESERVATION		0x10000	/* Preallocation */
++#define EXT4_MOUNT_NO_AUTO_DA_ALLOC	0x10000	/* No auto delalloc mapping */
+ #define EXT4_MOUNT_BARRIER		0x20000 /* Use block barriers */
+ #define EXT4_MOUNT_NOBH			0x40000 /* No bufferheads */
+ #define EXT4_MOUNT_QUOTA		0x80000 /* Some quota option set */
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index d3118d1acc39..bed4a0abd0d1 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -3908,7 +3908,7 @@ void ext4_truncate(struct inode *inode)
+ 	if (!ext4_can_truncate(inode))
+ 		return;
+ 
+-	if (inode->i_size == 0)
++	if (inode->i_size == 0 && !test_opt(inode->i_sb, NO_AUTO_DA_ALLOC))
+ 		ei->i_state |= EXT4_STATE_DA_ALLOC_CLOSE;
+ 
+ 	if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) {
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index eb20246c8965..22098e1cd085 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -2497,7 +2497,8 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 		ext4_mark_inode_dirty(handle, new_inode);
+ 		if (!new_inode->i_nlink)
+ 			ext4_orphan_add(handle, new_inode);
+-		force_da_alloc = 1;
++		if (!test_opt(new_dir->i_sb, NO_AUTO_DA_ALLOC))
++			force_da_alloc = 1;
+ 	}
+ 	retval = 0;
+ 
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index b9aefceb41e7..45d07cf9df34 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -816,8 +816,6 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
+ 	if (!test_opt(sb, POSIX_ACL) && (def_mount_opts & EXT4_DEFM_ACL))
+ 		seq_puts(seq, ",noacl");
+ #endif
+-	if (!test_opt(sb, RESERVATION))
+-		seq_puts(seq, ",noreservation");
+ 	if (sbi->s_commit_interval != JBD2_DEFAULT_MAX_COMMIT_AGE*HZ) {
+ 		seq_printf(seq, ",commit=%u",
+ 			   (unsigned) (sbi->s_commit_interval / HZ));
+@@ -868,6 +866,9 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
+ 	if (test_opt(sb, DATA_ERR_ABORT))
+ 		seq_puts(seq, ",data_err=abort");
+ 
++	if (test_opt(sb, NO_AUTO_DA_ALLOC))
++		seq_puts(seq, ",auto_da_alloc=0");
++
+ 	ext4_show_quota_options(seq, sb);
+ 	return 0;
+ }
+@@ -1017,7 +1018,7 @@ enum {
+ 	Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro,
+ 	Opt_nouid32, Opt_debug, Opt_oldalloc, Opt_orlov,
+ 	Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
+-	Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh,
++	Opt_auto_da_alloc, Opt_noload, Opt_nobh, Opt_bh,
+ 	Opt_commit, Opt_min_batch_time, Opt_max_batch_time,
+ 	Opt_journal_update, Opt_journal_dev,
+ 	Opt_journal_checksum, Opt_journal_async_commit,
+@@ -1052,8 +1053,6 @@ static const match_table_t tokens = {
+ 	{Opt_nouser_xattr, "nouser_xattr"},
+ 	{Opt_acl, "acl"},
+ 	{Opt_noacl, "noacl"},
+-	{Opt_reservation, "reservation"},
+-	{Opt_noreservation, "noreservation"},
+ 	{Opt_noload, "noload"},
+ 	{Opt_nobh, "nobh"},
+ 	{Opt_bh, "bh"},
+@@ -1088,6 +1087,7 @@ static const match_table_t tokens = {
+ 	{Opt_nodelalloc, "nodelalloc"},
+ 	{Opt_inode_readahead_blks, "inode_readahead_blks=%u"},
+ 	{Opt_journal_ioprio, "journal_ioprio=%u"},
++	{Opt_auto_da_alloc, "auto_da_alloc=%u"},
+ 	{Opt_err, NULL},
+ };
+ 
+@@ -1220,12 +1220,6 @@ static int parse_options(char *options, struct super_block *sb,
+ 			       "not supported\n");
+ 			break;
+ #endif
+-		case Opt_reservation:
+-			set_opt(sbi->s_mount_opt, RESERVATION);
+-			break;
+-		case Opt_noreservation:
+-			clear_opt(sbi->s_mount_opt, RESERVATION);
+-			break;
+ 		case Opt_journal_update:
+ 			/* @@@ FIXME */
+ 			/* Eventually we will want to be able to create
+@@ -1491,6 +1485,14 @@ static int parse_options(char *options, struct super_block *sb,
+ 			*journal_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE,
+ 							    option);
+ 			break;
++		case Opt_auto_da_alloc:
++			if (match_int(&args[0], &option))
++				return 0;
++			if (option)
++				clear_opt(sbi->s_mount_opt, NO_AUTO_DA_ALLOC);
++			else
++				set_opt(sbi->s_mount_opt,NO_AUTO_DA_ALLOC);
++			break;
+ 		default:
+ 			printk(KERN_ERR
+ 			       "EXT4-fs: Unrecognized mount option \"%s\" "
+@@ -2306,7 +2308,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	sbi->s_min_batch_time = EXT4_DEF_MIN_BATCH_TIME;
+ 	sbi->s_max_batch_time = EXT4_DEF_MAX_BATCH_TIME;
+ 
+-	set_opt(sbi->s_mount_opt, RESERVATION);
+ 	set_opt(sbi->s_mount_opt, BARRIER);
+ 
+ 	/*

commit 2842c3b5449f31470b61db716f1926b594fb6156
+Author: Theodore Ts'o 
+Date:   Thu Mar 12 12:20:01 2009 -0400
+
+    ext4: Print the find_group_flex() warning only once
+    
+    This is a short-term warning, and even printk_ratelimit() can result
+    in too much noise in system logs.  So only print it once as a warning.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 627f8c3337a3..2d2b3585ee91 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -698,6 +698,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
+ 	struct inode *ret;
+ 	ext4_group_t i;
+ 	int free = 0;
++	static int once = 1;
+ 	ext4_group_t flex_group;
+ 
+ 	/* Cannot create files in a deleted directory */
+@@ -719,7 +720,8 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
+ 		ret2 = find_group_flex(sb, dir, &group);
+ 		if (ret2 == -1) {
+ 			ret2 = find_group_other(sb, dir, &group);
+-			if (ret2 == 0 && printk_ratelimit())
++			if (ret2 == 0 && once)
++				once = 0;
+ 				printk(KERN_NOTICE "ext4: find_group_flex "
+ 				       "failed, fallback succeeded dir %lu\n",
+ 				       dir->i_ino);

commit 7d39db14a42cbd719c7515b9da8f85a2eb6a0633
+Author: Theodore Ts'o 
+Date:   Wed Mar 4 19:31:53 2009 -0500
+
+    ext4: Use struct flex_groups to calculate get_orlov_stats()
+    
+    Instead of looping over all of the block groups in a flex group
+    summing their summary statistics, start tracking used_dirs in struct
+    flex_groups, and use struct flex_groups instead.  This should save a
+    bit of CPU for mkdir-heavy workloads.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index e52b48f86ed4..46aaaa2ed4c5 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -172,6 +172,7 @@ struct ext4_group_desc
+ struct flex_groups {
+ 	atomic_t free_inodes;
+ 	atomic_t free_blocks;
++	atomic_t used_dirs;
+ };
+ 
+ #define EXT4_BG_INODE_UNINIT	0x0001 /* Inode table/bitmap not in use */
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 5f393927fd25..47b84e8df568 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -267,6 +267,13 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
+ 			if (is_directory) {
+ 				count = ext4_used_dirs_count(sb, gdp) - 1;
+ 				ext4_used_dirs_set(sb, gdp, count);
++				if (sbi->s_log_groups_per_flex) {
++					ext4_group_t f;
++
++					f = ext4_flex_group(sbi, block_group);
++					atomic_dec(&sbi->s_flex_groups[f].free_inodes);
++				}
++
+ 			}
+ 			gdp->bg_checksum = ext4_group_desc_csum(sbi,
+ 							block_group, gdp);
+@@ -424,25 +431,24 @@ void get_orlov_stats(struct super_block *sb, ext4_group_t g,
+ 		       int flex_size, struct orlov_stats *stats)
+ {
+ 	struct ext4_group_desc *desc;
+-	ext4_group_t		ngroups = EXT4_SB(sb)->s_groups_count;
+-	int			i;
+-
+-	stats->free_inodes = 0;
+-	stats->free_blocks = 0;
+-	stats->used_dirs = 0;
++	struct flex_groups *flex_group = EXT4_SB(sb)->s_flex_groups;
+ 
+-	g *= flex_size;
+-
+-	for (i = 0; i < flex_size; i++) {
+-		if (g >= ngroups)
+-			break;
+-		desc = ext4_get_group_desc(sb, g++, NULL);
+-		if (!desc)
+-			continue;
++	if (flex_size > 1) {
++		stats->free_inodes = atomic_read(&flex_group[g].free_inodes);
++		stats->free_blocks = atomic_read(&flex_group[g].free_blocks);
++		stats->used_dirs = atomic_read(&flex_group[g].used_dirs);
++		return;
++	}
+ 
+-		stats->free_inodes += ext4_free_inodes_count(sb, desc);
+-		stats->free_blocks += ext4_free_blks_count(sb, desc);
+-		stats->used_dirs += ext4_used_dirs_count(sb, desc);
++	desc = ext4_get_group_desc(sb, g, NULL);
++	if (desc) {
++		stats->free_inodes = ext4_free_inodes_count(sb, desc);
++		stats->free_blocks = ext4_free_blks_count(sb, desc);
++		stats->used_dirs = ext4_used_dirs_count(sb, desc);
++	} else {
++		stats->free_inodes = 0;
++		stats->free_blocks = 0;
++		stats->used_dirs = 0;
+ 	}
+ }
+ 
+@@ -765,6 +771,11 @@ static int ext4_claim_inode(struct super_block *sb,
+ 	if (S_ISDIR(mode)) {
+ 		count = ext4_used_dirs_count(sb, gdp) + 1;
+ 		ext4_used_dirs_set(sb, gdp, count);
++		if (sbi->s_log_groups_per_flex) {
++			ext4_group_t f = ext4_flex_group(sbi, group);
++
++			atomic_inc(&sbi->s_flex_groups[f].free_inodes);
++		}
+ 	}
+ 	gdp->bg_checksum = ext4_group_desc_csum(sbi, group, gdp);
+ err_ret:
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 6b5d5c6399fa..b9aefceb41e7 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1634,6 +1634,8 @@ static int ext4_fill_flex_info(struct super_block *sb)
+ 			   ext4_free_inodes_count(sb, gdp));
+ 		atomic_set(&sbi->s_flex_groups[flex_group].free_blocks,
+ 			   ext4_free_blks_count(sb, gdp));
++		atomic_set(&sbi->s_flex_groups[flex_group].used_dirs,
++			   ext4_used_dirs_count(sb, gdp));
+ 	}
+ 
+ 	return 1;

commit 9f24e4208f7ee2748f157368b63287dc903fcf60
+Author: Theodore Ts'o 
+Date:   Wed Mar 4 19:09:10 2009 -0500
+
+    ext4: Use atomic_t's in struct flex_groups
+    
+    Reduce pressure on the sb_bgl_lock family of locks by using atomic_t's
+    to track the number of free blocks and inodes in each flex_group.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index b37b12875582..53c72ad85877 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -470,9 +470,8 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
+ 
+ 	if (sbi->s_log_groups_per_flex) {
+ 		ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
+-		spin_lock(sb_bgl_lock(sbi, flex_group));
+-		sbi->s_flex_groups[flex_group].free_blocks += blocks_freed;
+-		spin_unlock(sb_bgl_lock(sbi, flex_group));
++		atomic_add(blocks_freed,
++			   &sbi->s_flex_groups[flex_group].free_blocks);
+ 	}
+ 	/*
+ 	 * request to reload the buddy with the
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index e5c273ff928b..e52b48f86ed4 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -170,8 +170,8 @@ struct ext4_group_desc
+  */
+ 
+ struct flex_groups {
+-	__u32 free_inodes;
+-	__u32 free_blocks;
++	atomic_t free_inodes;
++	atomic_t free_blocks;
+ };
+ 
+ #define EXT4_BG_INODE_UNINIT	0x0001 /* Inode table/bitmap not in use */
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 617f5a2d800a..5f393927fd25 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -189,7 +189,6 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
+ 	struct ext4_super_block *es;
+ 	struct ext4_sb_info *sbi;
+ 	int fatal = 0, err, count, cleared;
+-	ext4_group_t flex_group;
+ 
+ 	if (atomic_read(&inode->i_count) > 1) {
+ 		printk(KERN_ERR "ext4_free_inode: inode has count=%d\n",
+@@ -277,10 +276,10 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
+ 				percpu_counter_dec(&sbi->s_dirs_counter);
+ 
+ 			if (sbi->s_log_groups_per_flex) {
+-				flex_group = ext4_flex_group(sbi, block_group);
+-				spin_lock(sb_bgl_lock(sbi, flex_group));
+-				sbi->s_flex_groups[flex_group].free_inodes++;
+-				spin_unlock(sb_bgl_lock(sbi, flex_group));
++				ext4_group_t f;
++
++				f = ext4_flex_group(sbi, block_group);
++				atomic_inc(&sbi->s_flex_groups[f].free_inodes);
+ 			}
+ 		}
+ 		BUFFER_TRACE(bh2, "call ext4_handle_dirty_metadata");
+@@ -360,9 +359,9 @@ static int find_group_flex(struct super_block *sb, struct inode *parent,
+ 		sbi->s_log_groups_per_flex;
+ 
+ find_close_to_parent:
+-	flexbg_free_blocks = flex_group[best_flex].free_blocks;
++	flexbg_free_blocks = atomic_read(&flex_group[best_flex].free_blocks);
+ 	flex_freeb_ratio = flexbg_free_blocks * 100 / blocks_per_flex;
+-	if (flex_group[best_flex].free_inodes &&
++	if (atomic_read(&flex_group[best_flex].free_inodes) &&
+ 	    flex_freeb_ratio > free_block_ratio)
+ 		goto found_flexbg;
+ 
+@@ -375,24 +374,24 @@ static int find_group_flex(struct super_block *sb, struct inode *parent,
+ 		if (i == parent_fbg_group || i == parent_fbg_group - 1)
+ 			continue;
+ 
+-		flexbg_free_blocks = flex_group[i].free_blocks;
++		flexbg_free_blocks = atomic_read(&flex_group[i].free_blocks);
+ 		flex_freeb_ratio = flexbg_free_blocks * 100 / blocks_per_flex;
+ 
+ 		if (flex_freeb_ratio > free_block_ratio &&
+-		    flex_group[i].free_inodes) {
++		    (atomic_read(&flex_group[i].free_inodes))) {
+ 			best_flex = i;
+ 			goto found_flexbg;
+ 		}
+ 
+-		if (flex_group[best_flex].free_inodes == 0 ||
+-		    (flex_group[i].free_blocks >
+-		     flex_group[best_flex].free_blocks &&
+-		     flex_group[i].free_inodes))
++		if ((atomic_read(&flex_group[best_flex].free_inodes) == 0) ||
++		    ((atomic_read(&flex_group[i].free_blocks) >
++		      atomic_read(&flex_group[best_flex].free_blocks)) &&
++		     atomic_read(&flex_group[i].free_inodes)))
+ 			best_flex = i;
+ 	}
+ 
+-	if (!flex_group[best_flex].free_inodes ||
+-	    !flex_group[best_flex].free_blocks)
++	if (!atomic_read(&flex_group[best_flex].free_inodes) ||
++	    !atomic_read(&flex_group[best_flex].free_blocks))
+ 		return -1;
+ 
+ found_flexbg:
+@@ -960,9 +959,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
+ 
+ 	if (sbi->s_log_groups_per_flex) {
+ 		flex_group = ext4_flex_group(sbi, group);
+-		spin_lock(sb_bgl_lock(sbi, flex_group));
+-		sbi->s_flex_groups[flex_group].free_inodes--;
+-		spin_unlock(sb_bgl_lock(sbi, flex_group));
++		atomic_dec(&sbi->s_flex_groups[flex_group].free_inodes);
+ 	}
+ 
+ 	inode->i_uid = current_fsuid();
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index c4c430977622..e72c72a0b807 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -3044,9 +3044,8 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
+ 	if (sbi->s_log_groups_per_flex) {
+ 		ext4_group_t flex_group = ext4_flex_group(sbi,
+ 							  ac->ac_b_ex.fe_group);
+-		spin_lock(sb_bgl_lock(sbi, flex_group));
+-		sbi->s_flex_groups[flex_group].free_blocks -= ac->ac_b_ex.fe_len;
+-		spin_unlock(sb_bgl_lock(sbi, flex_group));
++		atomic_sub(ac->ac_b_ex.fe_len,
++			   &sbi->s_flex_groups[flex_group].free_blocks);
+ 	}
+ 
+ 	err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
+@@ -4884,9 +4883,7 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
+ 
+ 	if (sbi->s_log_groups_per_flex) {
+ 		ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
+-		spin_lock(sb_bgl_lock(sbi, flex_group));
+-		sbi->s_flex_groups[flex_group].free_blocks += count;
+-		spin_unlock(sb_bgl_lock(sbi, flex_group));
++		atomic_add(count, &sbi->s_flex_groups[flex_group].free_blocks);
+ 	}
+ 
+ 	ext4_mb_release_desc(&e4b);
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index c06886abd658..546c7dd869e1 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -938,10 +938,10 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
+ 	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
+ 		ext4_group_t flex_group;
+ 		flex_group = ext4_flex_group(sbi, input->group);
+-		sbi->s_flex_groups[flex_group].free_blocks +=
+-			input->free_blocks_count;
+-		sbi->s_flex_groups[flex_group].free_inodes +=
+-			EXT4_INODES_PER_GROUP(sb);
++		atomic_add(input->free_blocks_count,
++			   &sbi->s_flex_groups[flex_group].free_blocks);
++		atomic_add(EXT4_INODES_PER_GROUP(sb),
++			   &sbi->s_flex_groups[flex_group].free_inodes);
+ 	}
+ 
+ 	ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 1ec554cc107a..6b5d5c6399fa 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1630,10 +1630,10 @@ static int ext4_fill_flex_info(struct super_block *sb)
+ 		gdp = ext4_get_group_desc(sb, i, &bh);
+ 
+ 		flex_group = ext4_flex_group(sbi, i);
+-		sbi->s_flex_groups[flex_group].free_inodes +=
+-			ext4_free_inodes_count(sb, gdp);
+-		sbi->s_flex_groups[flex_group].free_blocks +=
+-			ext4_free_blks_count(sb, gdp);
++		atomic_set(&sbi->s_flex_groups[flex_group].free_inodes,
++			   ext4_free_inodes_count(sb, gdp));
++		atomic_set(&sbi->s_flex_groups[flex_group].free_blocks,
++			   ext4_free_blks_count(sb, gdp));
+ 	}
+ 
+ 	return 1;

commit b713a5ec55bf73c833f9883cdd761b20ee61a1ab
+Author: Theodore Ts'o 
+Date:   Tue Mar 31 09:11:14 2009 -0400
+
+    ext4: remove /proc tuning knobs
+    
+    Remove tuning knobs in /proc/fs/ext4//*.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
+index 830bad7cce0f..efc4fd9f40ce 100644
+--- a/Documentation/filesystems/proc.txt
++++ b/Documentation/filesystems/proc.txt
+@@ -940,27 +940,6 @@ Table 1-10: Files in /proc/fs/ext4/
+  File            Content                                        
+  mb_groups       details of multiblock allocator buddy cache of free blocks
+  mb_history      multiblock allocation history
+- stats           controls whether the multiblock allocator should start
+-                 collecting statistics, which are shown during the unmount
+- group_prealloc  the multiblock allocator will round up allocation
+-                 requests to a multiple of this tuning parameter if the
+-                 stripe size is not set in the ext4 superblock
+- max_to_scan     The maximum number of extents the multiblock allocator
+-                 will search to find the best extent
+- min_to_scan     The minimum number of extents the multiblock allocator
+-                 will search to find the best extent
+- order2_req      Tuning parameter which controls the minimum size for 
+-                 requests (as a power of 2) where the buddy cache is
+-                 used
+- stream_req      Files which have fewer blocks than this tunable
+-                 parameter will have their blocks allocated out of a
+-                 block group specific preallocation pool, so that small
+-                 files are packed closely together.  Each large file
+-                 will have its blocks allocated out of its own unique
+-                 preallocation pool.
+-inode_readahead  Tuning parameter which controls the maximum number of
+-                 inode table blocks that ext4's inode table readahead
+-                 algorithm will pre-read into the buffer cache
+ ..............................................................................
+ 
+ 
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 0bd39188531c..e5c273ff928b 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -976,22 +976,6 @@ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
+ 
+ extern struct proc_dir_entry *ext4_proc_root;
+ 
+-#ifdef CONFIG_PROC_FS
+-extern const struct file_operations ext4_ui_proc_fops;
+-
+-#define	EXT4_PROC_HANDLER(name, var)					\
+-do {									\
+-	proc = proc_create_data(name, mode, sbi->s_proc,		\
+-				&ext4_ui_proc_fops, &sbi->s_##var);	\
+-	if (proc == NULL) {						\
+-		printk(KERN_ERR "EXT4-fs: can't create %s\n", name);	\
+-		goto err_out;						\
+-	}								\
+-} while (0)
+-#else
+-#define EXT4_PROC_HANDLER(name, var)
+-#endif
+-
+ /*
+  * Function prototypes
+  */
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 7dcac9d7e491..d3118d1acc39 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4153,12 +4153,7 @@ static int __ext4_get_inode_loc(struct inode *inode,
+ 			unsigned num;
+ 
+ 			table = ext4_inode_table(sb, gdp);
+-			/* Make sure s_inode_readahead_blks is a power of 2 */
+-			while (EXT4_SB(sb)->s_inode_readahead_blks &
+-			       (EXT4_SB(sb)->s_inode_readahead_blks-1))
+-				EXT4_SB(sb)->s_inode_readahead_blks = 
+-				   (EXT4_SB(sb)->s_inode_readahead_blks &
+-				    (EXT4_SB(sb)->s_inode_readahead_blks-1));
++			/* s_inode_readahead_blks is always a power of 2 */
+ 			b = block & ~(EXT4_SB(sb)->s_inode_readahead_blks-1);
+ 			if (table > b)
+ 				b = table;
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index b0d6022eaa67..c4c430977622 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -46,22 +46,23 @@
+  * The allocation request involve request for multiple number of blocks
+  * near to the goal(block) value specified.
+  *
+- * During initialization phase of the allocator we decide to use the group
+- * preallocation or inode preallocation depending on the size file. The
+- * size of the file could be the resulting file size we would have after
+- * allocation or the current file size which ever is larger. If the size is
+- * less that sbi->s_mb_stream_request we select the group
+- * preallocation. The default value of s_mb_stream_request is 16
+- * blocks. This can also be tuned via
+- * /proc/fs/ext4//stream_req. The value is represented in terms
+- * of number of blocks.
++ * During initialization phase of the allocator we decide to use the
++ * group preallocation or inode preallocation depending on the size of
++ * the file. The size of the file could be the resulting file size we
++ * would have after allocation, or the current file size, which ever
++ * is larger. If the size is less than sbi->s_mb_stream_request we
++ * select to use the group preallocation. The default value of
++ * s_mb_stream_request is 16 blocks. This can also be tuned via
++ * /sys/fs/ext4//mb_stream_req. The value is represented in
++ * terms of number of blocks.
+  *
+  * The main motivation for having small file use group preallocation is to
+- * ensure that we have small file closer in the disk.
++ * ensure that we have small files closer together on the disk.
+  *
+- * First stage the allocator looks at the inode prealloc list
+- * ext4_inode_info->i_prealloc_list contain list of prealloc spaces for
+- * this particular inode. The inode prealloc space is represented as:
++ * First stage the allocator looks at the inode prealloc list,
++ * ext4_inode_info->i_prealloc_list, which contains list of prealloc
++ * spaces for this particular inode. The inode prealloc space is
++ * represented as:
+  *
+  * pa_lstart -> the logical start block for this prealloc space
+  * pa_pstart -> the physical start block for this prealloc space
+@@ -121,29 +122,29 @@
+  * list. In case of inode preallocation we follow a list of heuristics
+  * based on file size. This can be found in ext4_mb_normalize_request. If
+  * we are doing a group prealloc we try to normalize the request to
+- * sbi->s_mb_group_prealloc. Default value of s_mb_group_prealloc is set to
++ * sbi->s_mb_group_prealloc. Default value of s_mb_group_prealloc is
+  * 512 blocks. This can be tuned via
+- * /proc/fs/ext4/ option the group prealloc request is normalized to the
+  * stripe value (sbi->s_stripe)
+  *
+- * The regular allocator(using the buddy cache) support few tunables.
++ * The regular allocator(using the buddy cache) supports few tunables.
+  *
+- * /proc/fs/ext4//min_to_scan
+- * /proc/fs/ext4//max_to_scan
+- * /proc/fs/ext4//order2_req
++ * /sys/fs/ext4//mb_min_to_scan
++ * /sys/fs/ext4//mb_max_to_scan
++ * /sys/fs/ext4//mb_order2_req
+  *
+- * The regular allocator use buddy scan only if the request len is power of
++ * The regular allocator uses buddy scan only if the request len is power of
+  * 2 blocks and the order of allocation is >= sbi->s_mb_order2_reqs. The
+  * value of s_mb_order2_reqs can be tuned via
+- * /proc/fs/ext4//order2_req.  If the request len is equal to
++ * /sys/fs/ext4//mb_order2_req.  If the request len is equal to
+  * stripe size (sbi->s_stripe), we try to search for contigous block in
+- * stripe size. This should result in better allocation on RAID setup. If
+- * not we search in the specific group using bitmap for best extents. The
+- * tunable min_to_scan and max_to_scan controll the behaviour here.
++ * stripe size. This should result in better allocation on RAID setups. If
++ * not, we search in the specific group using bitmap for best extents. The
++ * tunable min_to_scan and max_to_scan control the behaviour here.
+  * min_to_scan indicate how long the mballoc __must__ look for a best
+- * extent and max_to_scanindicate how long the mballoc __can__ look for a
++ * extent and max_to_scan indicates how long the mballoc __can__ look for a
+  * best extent in the found extents. Searching for the blocks starts with
+  * the group specified as the goal value in allocation context via
+  * ac_g_ex. Each group is first checked based on the criteria whether it
+@@ -337,8 +338,6 @@ static void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap,
+ 					ext4_group_t group);
+ static void ext4_mb_generate_from_freelist(struct super_block *sb, void *bitmap,
+ 						ext4_group_t group);
+-static int ext4_mb_init_per_dev_proc(struct super_block *sb);
+-static int ext4_mb_destroy_per_dev_proc(struct super_block *sb);
+ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn);
+ 
+ 
+@@ -1978,7 +1977,7 @@ ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
+ 	/*
+ 	 * We search using buddy data only if the order of the request
+ 	 * is greater than equal to the sbi_s_mb_order2_reqs
+-	 * You can tune it via /proc/fs/ext4//order2_req
++	 * You can tune it via /sys/fs/ext4//mb_order2_req
+ 	 */
+ 	if (i >= sbi->s_mb_order2_reqs) {
+ 		/*
+@@ -2753,7 +2752,6 @@ int ext4_mb_init(struct super_block *sb, int needs_recovery)
+ 		spin_lock_init(&lg->lg_prealloc_lock);
+ 	}
+ 
+-	ext4_mb_init_per_dev_proc(sb);
+ 	ext4_mb_history_init(sb);
+ 
+ 	if (sbi->s_journal)
+@@ -2836,7 +2834,6 @@ int ext4_mb_release(struct super_block *sb)
+ 
+ 	free_percpu(sbi->s_locality_groups);
+ 	ext4_mb_history_release(sb);
+-	ext4_mb_destroy_per_dev_proc(sb);
+ 
+ 	return 0;
+ }
+@@ -2897,62 +2894,6 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn)
+ 	mb_debug("freed %u blocks in %u structures\n", count, count2);
+ }
+ 
+-#define EXT4_MB_STATS_NAME		"stats"
+-#define EXT4_MB_MAX_TO_SCAN_NAME	"max_to_scan"
+-#define EXT4_MB_MIN_TO_SCAN_NAME	"min_to_scan"
+-#define EXT4_MB_ORDER2_REQ		"order2_req"
+-#define EXT4_MB_STREAM_REQ		"stream_req"
+-#define EXT4_MB_GROUP_PREALLOC		"group_prealloc"
+-
+-static int ext4_mb_init_per_dev_proc(struct super_block *sb)
+-{
+-#ifdef CONFIG_PROC_FS
+-	mode_t mode = S_IFREG | S_IRUGO | S_IWUSR;
+-	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-	struct proc_dir_entry *proc;
+-
+-	if (sbi->s_proc == NULL)
+-		return -EINVAL;
+-
+-	EXT4_PROC_HANDLER(EXT4_MB_STATS_NAME, mb_stats);
+-	EXT4_PROC_HANDLER(EXT4_MB_MAX_TO_SCAN_NAME, mb_max_to_scan);
+-	EXT4_PROC_HANDLER(EXT4_MB_MIN_TO_SCAN_NAME, mb_min_to_scan);
+-	EXT4_PROC_HANDLER(EXT4_MB_ORDER2_REQ, mb_order2_reqs);
+-	EXT4_PROC_HANDLER(EXT4_MB_STREAM_REQ, mb_stream_request);
+-	EXT4_PROC_HANDLER(EXT4_MB_GROUP_PREALLOC, mb_group_prealloc);
+-	return 0;
+-
+-err_out:
+-	remove_proc_entry(EXT4_MB_GROUP_PREALLOC, sbi->s_proc);
+-	remove_proc_entry(EXT4_MB_STREAM_REQ, sbi->s_proc);
+-	remove_proc_entry(EXT4_MB_ORDER2_REQ, sbi->s_proc);
+-	remove_proc_entry(EXT4_MB_MIN_TO_SCAN_NAME, sbi->s_proc);
+-	remove_proc_entry(EXT4_MB_MAX_TO_SCAN_NAME, sbi->s_proc);
+-	remove_proc_entry(EXT4_MB_STATS_NAME, sbi->s_proc);
+-	return -ENOMEM;
+-#else
+-	return 0;
+-#endif
+-}
+-
+-static int ext4_mb_destroy_per_dev_proc(struct super_block *sb)
+-{
+-#ifdef CONFIG_PROC_FS
+-	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-
+-	if (sbi->s_proc == NULL)
+-		return -EINVAL;
+-
+-	remove_proc_entry(EXT4_MB_GROUP_PREALLOC, sbi->s_proc);
+-	remove_proc_entry(EXT4_MB_STREAM_REQ, sbi->s_proc);
+-	remove_proc_entry(EXT4_MB_ORDER2_REQ, sbi->s_proc);
+-	remove_proc_entry(EXT4_MB_MIN_TO_SCAN_NAME, sbi->s_proc);
+-	remove_proc_entry(EXT4_MB_MAX_TO_SCAN_NAME, sbi->s_proc);
+-	remove_proc_entry(EXT4_MB_STATS_NAME, sbi->s_proc);
+-#endif
+-	return 0;
+-}
+-
+ int __init init_ext4_mballoc(void)
+ {
+ 	ext4_pspace_cachep =
+@@ -3123,7 +3064,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
+  * here we normalize request for locality group
+  * Group request are normalized to s_strip size if we set the same via mount
+  * option. If not we set it to s_mb_group_prealloc which can be configured via
+- * /proc/fs/ext4//group_prealloc
++ * /sys/fs/ext4//mb_group_prealloc
+  *
+  * XXX: should we try to preallocate more than the group has now?
+  */
+@@ -4239,7 +4180,7 @@ static inline void ext4_mb_show_ac(struct ext4_allocation_context *ac)
+  * file is determined by the current size or the resulting size after
+  * allocation which ever is larger
+  *
+- * One can tune this size via /proc/fs/ext4//stream_req
++ * One can tune this size via /sys/fs/ext4//mb_stream_req
+  */
+ static void ext4_mb_group_or_file(struct ext4_allocation_context *ac)
+ {
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 2883d4318c22..1ec554cc107a 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -579,7 +579,6 @@ static void ext4_put_super(struct super_block *sb)
+ 		ext4_commit_super(sb, es, 1);
+ 	}
+ 	if (sbi->s_proc) {
+-		remove_proc_entry("inode_readahead_blks", sbi->s_proc);
+ 		remove_proc_entry(sb->s_id, ext4_proc_root);
+ 	}
+ 	kobject_del(&sbi->s_kobj);
+@@ -2529,11 +2528,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ #ifdef CONFIG_PROC_FS
+ 	if (ext4_proc_root)
+ 		sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root);
+-
+-	if (sbi->s_proc)
+-		proc_create_data("inode_readahead_blks", 0644, sbi->s_proc,
+-				 &ext4_ui_proc_fops,
+-				 &sbi->s_inode_readahead_blks);
+ #endif
+ 
+ 	bgl_lock_init(sbi->s_blockgroup_lock);
+@@ -2832,7 +2826,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	kfree(sbi->s_group_desc);
+ failed_mount:
+ 	if (sbi->s_proc) {
+-		remove_proc_entry("inode_readahead_blks", sbi->s_proc);
+ 		remove_proc_entry(sb->s_id, ext4_proc_root);
+ 	}
+ #ifdef CONFIG_QUOTA
+@@ -3865,45 +3858,6 @@ static int ext4_get_sb(struct file_system_type *fs_type,
+ 	return get_sb_bdev(fs_type, flags, dev_name, data, ext4_fill_super, mnt);
+ }
+ 
+-#ifdef CONFIG_PROC_FS
+-static int ext4_ui_proc_show(struct seq_file *m, void *v)
+-{
+-	unsigned int *p = m->private;
+-
+-	seq_printf(m, "%u\n", *p);
+-	return 0;
+-}
+-
+-static int ext4_ui_proc_open(struct inode *inode, struct file *file)
+-{
+-	return single_open(file, ext4_ui_proc_show, PDE(inode)->data);
+-}
+-
+-static ssize_t ext4_ui_proc_write(struct file *file, const char __user *buf,
+-			       size_t cnt, loff_t *ppos)
+-{
+-	unsigned long *p = PDE(file->f_path.dentry->d_inode)->data;
+-	char str[32];
+-
+-	if (cnt >= sizeof(str))
+-		return -EINVAL;
+-	if (copy_from_user(str, buf, cnt))
+-		return -EFAULT;
+-
+-	*p = simple_strtoul(str, NULL, 0);
+-	return cnt;
+-}
+-
+-const struct file_operations ext4_ui_proc_fops = {
+-	.owner		= THIS_MODULE,
+-	.open		= ext4_ui_proc_open,
+-	.read		= seq_read,
+-	.llseek		= seq_lseek,
+-	.release	= single_release,
+-	.write		= ext4_ui_proc_write,
+-};
+-#endif
+-
+ static struct file_system_type ext4_fs_type = {
+ 	.owner		= THIS_MODULE,
+ 	.name		= "ext4",

commit 3197ebdb130473a92760100cbfe0d7e671838f48
+Author: Theodore Ts'o 
+Date:   Tue Mar 31 09:10:09 2009 -0400
+
+    ext4: Add sysfs support
+    
+    Add basic sysfs support so that information about the mounted
+    filesystem and various tuning parameters can be accessed via
+    /sys/fs/ext4//*.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/Documentation/ABI/testing/sysfs-fs-ext4 b/Documentation/ABI/testing/sysfs-fs-ext4
+new file mode 100644
+index 000000000000..4e79074de282
+--- /dev/null
++++ b/Documentation/ABI/testing/sysfs-fs-ext4
+@@ -0,0 +1,81 @@
++What:		/sys/fs/ext4//mb_stats
++Date:		March 2008
++Contact:	"Theodore Ts'o" 
++Description:
++		 Controls whether the multiblock allocator should
++		 collect statistics, which are shown during the unmount.
++		 1 means to collect statistics, 0 means not to collect
++		 statistics
++
++What:		/sys/fs/ext4//mb_group_prealloc
++Date:		March 2008
++Contact:	"Theodore Ts'o" 
++Description:
++		The multiblock allocator will round up allocation
++		requests to a multiple of this tuning parameter if the
++		stripe size is not set in the ext4 superblock
++
++What:		/sys/fs/ext4//mb_max_to_scan
++Date:		March 2008
++Contact:	"Theodore Ts'o" 
++Description:
++		The maximum number of extents the multiblock allocator
++		will search to find the best extent
++
++What:		/sys/fs/ext4//mb_min_to_scan
++Date:		March 2008
++Contact:	"Theodore Ts'o" 
++Description:
++		The minimum number of extents the multiblock allocator
++		will search to find the best extent
++
++What:		/sys/fs/ext4//mb_order2_req
++Date:		March 2008
++Contact:	"Theodore Ts'o" 
++Description:
++		Tuning parameter which controls the minimum size for 
++		requests (as a power of 2) where the buddy cache is
++		used
++
++What:		/sys/fs/ext4//mb_stream_req
++Date:		March 2008
++Contact:	"Theodore Ts'o" 
++Description:
++		Files which have fewer blocks than this tunable
++		parameter will have their blocks allocated out of a
++		block group specific preallocation pool, so that small
++		files are packed closely together.  Each large file
++		 will have its blocks allocated out of its own unique
++		 preallocation pool.
++
++What:		/sys/fs/ext4//inode_readahead
++Date:		March 2008
++Contact:	"Theodore Ts'o" 
++Description:
++		Tuning parameter which controls the maximum number of
++		inode table blocks that ext4's inode table readahead
++		algorithm will pre-read into the buffer cache
++
++What:		/sys/fs/ext4//delayed_allocation_blocks
++Date:		March 2008
++Contact:	"Theodore Ts'o" 
++Description:
++		This file is read-only and shows the number of blocks
++		that are dirty in the page cache, but which do not
++		have their location in the filesystem allocated yet.
++
++What:		/sys/fs/ext4//lifetime_write_kbytes
++Date:		March 2008
++Contact:	"Theodore Ts'o" 
++Description:
++		This file is read-only and shows the number of kilobytes
++		of data that have been written to this filesystem since it was
++		created.
++
++What:		/sys/fs/ext4//session_write_kbytes
++Date:		March 2008
++Contact:	"Theodore Ts'o" 
++Description:
++		This file is read-only and shows the number of
++		kilobytes of data that have been written to this
++		filesystem since it was mounted.
+diff --git a/fs/ext4/ext4_sb.h b/fs/ext4/ext4_sb.h
+index 50ab1169c378..57b71fefbccf 100644
+--- a/fs/ext4/ext4_sb.h
++++ b/fs/ext4/ext4_sb.h
+@@ -64,6 +64,8 @@ struct ext4_sb_info {
+ 	struct percpu_counter s_dirtyblocks_counter;
+ 	struct blockgroup_lock *s_blockgroup_lock;
+ 	struct proc_dir_entry *s_proc;
++	struct kobject s_kobj;
++	struct completion s_kobj_unregister;
+ 
+ 	/* Journaling */
+ 	struct inode *s_journal_inode;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 30fc27cdf8fc..2883d4318c22 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -35,6 +35,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -48,6 +49,7 @@
+ #include "group.h"
+ 
+ struct proc_dir_entry *ext4_proc_root;
++static struct kset *ext4_kset;
+ 
+ static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
+ 			     unsigned long journal_devnum);
+@@ -580,6 +582,7 @@ static void ext4_put_super(struct super_block *sb)
+ 		remove_proc_entry("inode_readahead_blks", sbi->s_proc);
+ 		remove_proc_entry(sb->s_id, ext4_proc_root);
+ 	}
++	kobject_del(&sbi->s_kobj);
+ 
+ 	for (i = 0; i < sbi->s_gdb_count; i++)
+ 		brelse(sbi->s_group_desc[i]);
+@@ -615,6 +618,16 @@ static void ext4_put_super(struct super_block *sb)
+ 		ext4_blkdev_remove(sbi);
+ 	}
+ 	sb->s_fs_info = NULL;
++	/*
++	 * Now that we are completely done shutting down the
++	 * superblock, we need to actually destroy the kobject.
++	 */
++	unlock_kernel();
++	unlock_super(sb);
++	kobject_put(&sbi->s_kobj);
++	wait_for_completion(&sbi->s_kobj_unregister);
++	lock_super(sb);
++	lock_kernel();
+ 	kfree(sbi->s_blockgroup_lock);
+ 	kfree(sbi);
+ 	return;
+@@ -1464,6 +1477,11 @@ static int parse_options(char *options, struct super_block *sb,
+ 				return 0;
+ 			if (option < 0 || option > (1 << 30))
+ 				return 0;
++			if (option & (option - 1)) {
++				printk(KERN_ERR "EXT4-fs: inode_readahead_blks"
++				       " must be a power of 2\n");
++				return 0;
++			}
+ 			sbi->s_inode_readahead_blks = option;
+ 			break;
+ 		case Opt_journal_ioprio:
+@@ -1992,6 +2010,181 @@ static unsigned long ext4_get_stripe_size(struct ext4_sb_info *sbi)
+ 	return 0;
+ }
+ 
++/* sysfs supprt */
++
++struct ext4_attr {
++	struct attribute attr;
++	ssize_t (*show)(struct ext4_attr *, struct ext4_sb_info *, char *);
++	ssize_t (*store)(struct ext4_attr *, struct ext4_sb_info *, 
++			 const char *, size_t);
++	int offset;
++};
++
++static int parse_strtoul(const char *buf,
++		unsigned long max, unsigned long *value)
++{
++	char *endp;
++
++	while (*buf && isspace(*buf))
++		buf++;
++	*value = simple_strtoul(buf, &endp, 0);
++	while (*endp && isspace(*endp))
++		endp++;
++	if (*endp || *value > max)
++		return -EINVAL;
++
++	return 0;
++}
++
++static ssize_t delayed_allocation_blocks_show(struct ext4_attr *a,
++					      struct ext4_sb_info *sbi,
++					      char *buf)
++{
++	return snprintf(buf, PAGE_SIZE, "%llu\n",
++			(s64) percpu_counter_sum(&sbi->s_dirtyblocks_counter));
++}
++
++static ssize_t session_write_kbytes_show(struct ext4_attr *a,
++					 struct ext4_sb_info *sbi, char *buf)
++{
++	struct super_block *sb = sbi->s_buddy_cache->i_sb;
++
++	return snprintf(buf, PAGE_SIZE, "%lu\n",
++			(part_stat_read(sb->s_bdev->bd_part, sectors[1]) -
++			 sbi->s_sectors_written_start) >> 1);
++}
++
++static ssize_t lifetime_write_kbytes_show(struct ext4_attr *a,
++					  struct ext4_sb_info *sbi, char *buf)
++{
++	struct super_block *sb = sbi->s_buddy_cache->i_sb;
++
++	return snprintf(buf, PAGE_SIZE, "%llu\n",
++			sbi->s_kbytes_written + 
++			((part_stat_read(sb->s_bdev->bd_part, sectors[1]) -
++			  EXT4_SB(sb)->s_sectors_written_start) >> 1));
++}
++
++static ssize_t inode_readahead_blks_store(struct ext4_attr *a,
++					  struct ext4_sb_info *sbi,
++					  const char *buf, size_t count)
++{
++	unsigned long t;
++
++	if (parse_strtoul(buf, 0x40000000, &t))
++		return -EINVAL;
++
++	/* inode_readahead_blks must be a power of 2 */
++	if (t & (t-1))
++		return -EINVAL;
++
++	sbi->s_inode_readahead_blks = t;
++	return count;
++}
++
++static ssize_t sbi_ui_show(struct ext4_attr *a,
++				struct ext4_sb_info *sbi, char *buf)
++{
++	unsigned int *ui = (unsigned int *) (((char *) sbi) + a->offset);
++
++	return snprintf(buf, PAGE_SIZE, "%u\n", *ui);
++}
++
++static ssize_t sbi_ui_store(struct ext4_attr *a,
++			    struct ext4_sb_info *sbi,
++			    const char *buf, size_t count)
++{
++	unsigned int *ui = (unsigned int *) (((char *) sbi) + a->offset);
++	unsigned long t;
++
++	if (parse_strtoul(buf, 0xffffffff, &t))
++		return -EINVAL;
++	*ui = t;
++	return count;
++}
++
++#define EXT4_ATTR_OFFSET(_name,_mode,_show,_store,_elname) \
++static struct ext4_attr ext4_attr_##_name = {			\
++	.attr = {.name = __stringify(_name), .mode = _mode },	\
++	.show	= _show,					\
++	.store	= _store,					\
++	.offset = offsetof(struct ext4_sb_info, _elname),	\
++}
++#define EXT4_ATTR(name, mode, show, store) \
++static struct ext4_attr ext4_attr_##name = __ATTR(name, mode, show, store)
++
++#define EXT4_RO_ATTR(name) EXT4_ATTR(name, 0444, name##_show, NULL)
++#define EXT4_RW_ATTR(name) EXT4_ATTR(name, 0644, name##_show, name##_store)
++#define EXT4_RW_ATTR_SBI_UI(name, elname)	\
++	EXT4_ATTR_OFFSET(name, 0644, sbi_ui_show, sbi_ui_store, elname)
++#define ATTR_LIST(name) &ext4_attr_##name.attr
++
++EXT4_RO_ATTR(delayed_allocation_blocks);
++EXT4_RO_ATTR(session_write_kbytes);
++EXT4_RO_ATTR(lifetime_write_kbytes);
++EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show,
++		 inode_readahead_blks_store, s_inode_readahead_blks);
++EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats);
++EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan);
++EXT4_RW_ATTR_SBI_UI(mb_min_to_scan, s_mb_min_to_scan);
++EXT4_RW_ATTR_SBI_UI(mb_order2_req, s_mb_order2_reqs);
++EXT4_RW_ATTR_SBI_UI(mb_stream_req, s_mb_stream_request);
++EXT4_RW_ATTR_SBI_UI(mb_group_prealloc, s_mb_group_prealloc);
++
++static struct attribute *ext4_attrs[] = {
++	ATTR_LIST(delayed_allocation_blocks),
++	ATTR_LIST(session_write_kbytes),
++	ATTR_LIST(lifetime_write_kbytes),
++	ATTR_LIST(inode_readahead_blks),
++	ATTR_LIST(mb_stats),
++	ATTR_LIST(mb_max_to_scan),
++	ATTR_LIST(mb_min_to_scan),
++	ATTR_LIST(mb_order2_req),
++	ATTR_LIST(mb_stream_req),
++	ATTR_LIST(mb_group_prealloc),
++	NULL,
++};
++
++static ssize_t ext4_attr_show(struct kobject *kobj,
++			      struct attribute *attr, char *buf)
++{
++	struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info,
++						s_kobj);
++	struct ext4_attr *a = container_of(attr, struct ext4_attr, attr);
++
++	return a->show ? a->show(a, sbi, buf) : 0;
++}
++
++static ssize_t ext4_attr_store(struct kobject *kobj,
++			       struct attribute *attr,
++			       const char *buf, size_t len)
++{
++	struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info,
++						s_kobj);
++	struct ext4_attr *a = container_of(attr, struct ext4_attr, attr);
++
++	return a->store ? a->store(a, sbi, buf, len) : 0;
++}
++
++static void ext4_sb_release(struct kobject *kobj)
++{
++	struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info,
++						s_kobj);
++	complete(&sbi->s_kobj_unregister);
++}
++
++
++static struct sysfs_ops ext4_attr_ops = {
++	.show	= ext4_attr_show,
++	.store	= ext4_attr_store,
++};
++
++static struct kobj_type ext4_ktype = {
++	.default_attrs	= ext4_attrs,
++	.sysfs_ops	= &ext4_attr_ops,
++	.release	= ext4_sb_release,
++};
++
+ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 				__releases(kernel_lock)
+ 				__acquires(kernel_lock)
+@@ -2575,6 +2768,16 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		goto failed_mount4;
+ 	}
+ 
++	sbi->s_kobj.kset = ext4_kset;
++	init_completion(&sbi->s_kobj_unregister);
++	err = kobject_init_and_add(&sbi->s_kobj, &ext4_ktype, NULL,
++				   "%s", sb->s_id);
++	if (err) {
++		ext4_mb_release(sb);
++		ext4_ext_release(sb);
++		goto failed_mount4;
++	};
++
+ 	/*
+ 	 * akpm: core read_super() calls in here with the superblock locked.
+ 	 * That deadlocks, because orphan cleanup needs to lock the superblock
+@@ -3734,6 +3937,9 @@ static int __init init_ext4_fs(void)
+ {
+ 	int err;
+ 
++	ext4_kset = kset_create_and_add("ext4", NULL, fs_kobj);
++	if (!ext4_kset)
++		return -ENOMEM;
+ 	ext4_proc_root = proc_mkdir("fs/ext4", NULL);
+ 	err = init_ext4_mballoc();
+ 	if (err)
+@@ -3775,6 +3981,7 @@ static void __exit exit_ext4_fs(void)
+ 	exit_ext4_xattr();
+ 	exit_ext4_mballoc();
+ 	remove_proc_entry("fs/ext4", NULL);
++	kset_unregister(ext4_kset);
+ }
+ 
+ MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");

commit afc32f7ee9febc020c73da61402351d4c90437f3
+Author: Theodore Ts'o 
+Date:   Sat Feb 28 19:39:58 2009 -0500
+
+    ext4: Track lifetime disk writes
+    
+    Add a new superblock value which tracks the lifetime amount of writes
+    to the filesystem.  This is useful in estimating the amount of wear on
+    solid state drives (SSD's) caused by writes to the filesystem.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 1b0c17364631..0bd39188531c 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -683,7 +683,8 @@ struct ext4_super_block {
+ 	__u8	s_log_groups_per_flex;  /* FLEX_BG group size */
+ 	__u8	s_reserved_char_pad2;
+ 	__le16  s_reserved_pad;
+-	__u32   s_reserved[162];        /* Padding to the end of the block */
++	__le64	s_kbytes_written;	/* nr of lifetime kilobytes written */
++	__u32   s_reserved[160];        /* Padding to the end of the block */
+ };
+ 
+ #ifdef __KERNEL__
+diff --git a/fs/ext4/ext4_sb.h b/fs/ext4/ext4_sb.h
+index 4e4d9cc3f40d..50ab1169c378 100644
+--- a/fs/ext4/ext4_sb.h
++++ b/fs/ext4/ext4_sb.h
+@@ -142,6 +142,10 @@ struct ext4_sb_info {
+ 	/* locality groups */
+ 	struct ext4_locality_group *s_locality_groups;
+ 
++	/* for write statistics */
++	unsigned long s_sectors_written_start;
++	u64 s_kbytes_written;
++
+ 	unsigned int s_log_groups_per_flex;
+ 	struct flex_groups *s_flex_groups;
+ };
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index a3768709ce05..30fc27cdf8fc 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2035,6 +2035,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	sbi->s_resgid = EXT4_DEF_RESGID;
+ 	sbi->s_inode_readahead_blks = EXT4_DEF_INODE_READAHEAD_BLKS;
+ 	sbi->s_sb_block = sb_block;
++	sbi->s_sectors_written_start = part_stat_read(sb->s_bdev->bd_part,
++						      sectors[1]);
+ 
+ 	unlock_kernel();
+ 
+@@ -2072,6 +2074,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	sb->s_magic = le16_to_cpu(es->s_magic);
+ 	if (sb->s_magic != EXT4_SUPER_MAGIC)
+ 		goto cantfind_ext4;
++	sbi->s_kbytes_written = le64_to_cpu(es->s_kbytes_written);
+ 
+ 	/* Set defaults before we parse the mount options */
+ 	def_mount_opts = le32_to_cpu(es->s_default_mount_opts);
+@@ -2921,6 +2924,10 @@ static int ext4_commit_super(struct super_block *sb,
+ 		set_buffer_uptodate(sbh);
+ 	}
+ 	es->s_wtime = cpu_to_le32(get_seconds());
++	es->s_kbytes_written =
++		cpu_to_le64(EXT4_SB(sb)->s_kbytes_written + 
++			    ((part_stat_read(sb->s_bdev->bd_part, sectors[1]) -
++			      EXT4_SB(sb)->s_sectors_written_start) >> 1));
+ 	ext4_free_blocks_count_set(es, percpu_counter_sum_positive(
+ 					&EXT4_SB(sb)->s_freeblocks_counter));
+ 	es->s_free_inodes_count = cpu_to_le32(percpu_counter_sum_positive(

commit d8ae4601a4b7ea1fa17fa395c3468c0e144d1275
+Author: Theodore Ts'o 
+Date:   Sat Feb 28 09:50:01 2009 -0500
+
+    ext4: Reorder fs/Makefile so that ext2 root fs's are mounted using ext2
+    
+    In fs/Makefile, ext3 was placed before ext2 so that a root filesystem
+    that possessed a journal, it would be mounted as ext3 instead of ext2.
+    This was necessary because a cleanly unmounted ext3 filesystem was
+    fully backwards compatible with ext2, and could be mounted by ext2 ---
+    but it was desirable that it be mounted with ext3 so that the
+    journaling would be enabled.
+    
+    The ext4 filesystem supports new incompatible features, so there is no
+    danger of an ext4 filesystem being mistaken for an ext2 filesystem.
+    At that point, the relative ordering of ext4 with respect to ext2
+    didn't matter until ext4 gained the ability to mount filesystems
+    without a journal starting in 2.6.29-rc1.  Now that this is the case,
+    given that ext4 is before ext2, it means that root filesystems that
+    were using the plain-jane ext2 format are getting mounted using the
+    ext4 filesystem driver, which is a change in behavior which could be
+    surprising to users.
+    
+    It's doubtful that there are that many ext2-only root filesystem users
+    that would also have ext4 compiled into the kernel, but to adhere to
+    the principle of least surprise, the correct ordering in fs/Makefile
+    is ext3, followed by ext2, and finally ext4.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/Makefile b/fs/Makefile
+index 38bc735c67ad..dc20db348679 100644
+--- a/fs/Makefile
++++ b/fs/Makefile
+@@ -69,10 +69,12 @@ obj-$(CONFIG_DLM)		+= dlm/
+ # Do not add any filesystems before this line
+ obj-$(CONFIG_REISERFS_FS)	+= reiserfs/
+ obj-$(CONFIG_EXT3_FS)		+= ext3/ # Before ext2 so root fs can be ext3
+-obj-$(CONFIG_EXT4_FS)		+= ext4/ # Before ext2 so root fs can be ext4
++obj-$(CONFIG_EXT2_FS)		+= ext2/
++# We place ext4 after ext2 so plain ext2 root fs's are mounted using ext2
++# unless explicitly requested by rootfstype
++obj-$(CONFIG_EXT4_FS)		+= ext4/
+ obj-$(CONFIG_JBD)		+= jbd/
+ obj-$(CONFIG_JBD2)		+= jbd2/
+-obj-$(CONFIG_EXT2_FS)		+= ext2/
+ obj-$(CONFIG_CRAMFS)		+= cramfs/
+ obj-$(CONFIG_SQUASHFS)		+= squashfs/
+ obj-y				+= ramfs/

commit 8b1a8ff8b321a9384304aeea4dbdb9747daf7ee8
+Author: Theodore Ts'o 
+Date:   Sat Feb 28 00:08:53 2009 -0500
+
+    ext4: Remove duplicate call to ext4_commit_super() in ext4_freeze()
+    
+    Commit c4be0c1d added error checking to ext4_freeze() when calling
+    ext4_commit_super().  Unfortunately the patch failed to remove the
+    original call to ext4_commit_super(), with the net result that when
+    freezing the filesystem, the superblock gets written twice, the first
+    time without error checking.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index a5732c58f676..39d1993cfa13 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3091,7 +3091,6 @@ static int ext4_freeze(struct super_block *sb)
+ 
+ 		/* Journal blocked and flushed, clear needs_recovery flag. */
+ 		EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+-		ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1);
+ 		error = ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1);
+ 		if (error)
+ 			goto out;

commit 8750c6d5fcbd3342b3d908d157f81d345c5325a7
+Author: Theodore Ts'o 
+Date:   Mon Feb 23 23:05:27 2009 -0500
+
+    ext4: Automatically allocate delay allocated blocks on rename
+    
+    When renaming a file such that a link to another inode is overwritten,
+    force any delay allocated blocks that to be allocated so that if the
+    filesystem is mounted with data=ordered, the data blocks will be
+    pushed out to disk along with the journal commit.  Many application
+    programs expect this, so we do this to avoid zero length files if the
+    system crashes unexpectedly.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 6e1ad68cdc7a..eb20246c8965 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -2357,7 +2357,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 	struct inode *old_inode, *new_inode;
+ 	struct buffer_head *old_bh, *new_bh, *dir_bh;
+ 	struct ext4_dir_entry_2 *old_de, *new_de;
+-	int retval;
++	int retval, force_da_alloc = 0;
+ 
+ 	old_bh = new_bh = dir_bh = NULL;
+ 
+@@ -2497,6 +2497,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 		ext4_mark_inode_dirty(handle, new_inode);
+ 		if (!new_inode->i_nlink)
+ 			ext4_orphan_add(handle, new_inode);
++		force_da_alloc = 1;
+ 	}
+ 	retval = 0;
+ 
+@@ -2505,6 +2506,8 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 	brelse(old_bh);
+ 	brelse(new_bh);
+ 	ext4_journal_stop(handle);
++	if (retval == 0 && force_da_alloc)
++		ext4_alloc_da_blocks(old_inode);
+ 	return retval;
+ }
+ 

commit 7d8f9f7d150dded7b68e61ca6403a1f166fb4edf
+Author: Theodore Ts'o 
+Date:   Tue Feb 24 08:21:14 2009 -0500
+
+    ext4: Automatically allocate delay allocated blocks on close
+    
+    When closing a file that had been previously truncated, force any
+    delay allocated blocks that to be allocated so that if the filesystem
+    is mounted with data=ordered, the data blocks will be pushed out to
+    disk along with the journal commit.  Many application programs expect
+    this, so we do this to avoid zero length files if the system crashes
+    unexpectedly.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index b0ea70cc94db..1b0c17364631 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -270,6 +270,7 @@ static inline __u32 ext4_mask_flags(umode_t mode, __u32 flags)
+ #define EXT4_STATE_NEW			0x00000002 /* inode is newly created */
+ #define EXT4_STATE_XATTR		0x00000004 /* has in-inode xattrs */
+ #define EXT4_STATE_NO_EXPAND		0x00000008 /* No space for expansion */
++#define EXT4_STATE_DA_ALLOC_CLOSE	0x00000010 /* Alloc DA blks on close */
+ 
+ /* Used to pass group descriptor data when online resize is done */
+ struct ext4_new_group_input {
+diff --git a/fs/ext4/file.c b/fs/ext4/file.c
+index f731cb545a03..06df8272c639 100644
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -33,6 +33,10 @@
+  */
+ static int ext4_release_file(struct inode *inode, struct file *filp)
+ {
++	if (EXT4_I(inode)->i_state & EXT4_STATE_DA_ALLOC_CLOSE) {
++		ext4_alloc_da_blocks(inode);
++		EXT4_I(inode)->i_state &= ~EXT4_STATE_DA_ALLOC_CLOSE;
++	}
+ 	/* if we are the last writer on the inode, drop the block reservation */
+ 	if ((filp->f_mode & FMODE_WRITE) &&
+ 			(atomic_read(&inode->i_writecount) == 1))
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 8dd3d5de5861..80ed6dc9c9d2 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -3901,6 +3901,9 @@ void ext4_truncate(struct inode *inode)
+ 	if (!ext4_can_truncate(inode))
+ 		return;
+ 
++	if (inode->i_size == 0)
++		ei->i_state |= EXT4_STATE_DA_ALLOC_CLOSE;
++
+ 	if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) {
+ 		ext4_ext_truncate(inode);
+ 		return;

commit ccd2506bd43113659aa904d5bea5d1300605e2a6
+Author: Theodore Ts'o 
+Date:   Thu Feb 26 01:04:07 2009 -0500
+
+    ext4: add EXT4_IOC_ALLOC_DA_BLKS ioctl
+    
+    Add an ioctl which forces all of the delay allocated blocks to be
+    allocated.  This also provides a function ext4_alloc_da_blocks() which
+    will be used by the following commits to force files to be fully
+    allocated to preserve application-expected ext3 behaviour.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 096456c8559b..b0ea70cc94db 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -317,7 +317,9 @@ struct ext4_new_group_data {
+ #define EXT4_IOC_GROUP_EXTEND		_IOW('f', 7, unsigned long)
+ #define EXT4_IOC_GROUP_ADD		_IOW('f', 8, struct ext4_new_group_input)
+ #define EXT4_IOC_MIGRATE		_IO('f', 9)
++ /* note ioctl 10 reserved for an early version of the FIEMAP ioctl */
+  /* note ioctl 11 reserved for filesystem-independent FIEMAP ioctl */
++#define EXT4_IOC_ALLOC_DA_BLKS		_IO('f', 12)
+ 
+ /*
+  * ioctl commands in 32 bit emulation
+@@ -1094,6 +1096,7 @@ extern int ext4_can_truncate(struct inode *inode);
+ extern void ext4_truncate(struct inode *);
+ extern void ext4_set_inode_flags(struct inode *);
+ extern void ext4_get_inode_flags(struct ext4_inode_info *);
++extern int ext4_alloc_da_blocks(struct inode *inode);
+ extern void ext4_set_aops(struct inode *inode);
+ extern int ext4_writepage_trans_blocks(struct inode *);
+ extern int ext4_meta_trans_blocks(struct inode *, int nrblocks, int idxblocks);
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 24d0f9d2b320..8dd3d5de5861 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2837,6 +2837,48 @@ static void ext4_da_invalidatepage(struct page *page, unsigned long offset)
+ 	return;
+ }
+ 
++/*
++ * Force all delayed allocation blocks to be allocated for a given inode.
++ */
++int ext4_alloc_da_blocks(struct inode *inode)
++{
++	if (!EXT4_I(inode)->i_reserved_data_blocks &&
++	    !EXT4_I(inode)->i_reserved_meta_blocks)
++		return 0;
++
++	/*
++	 * We do something simple for now.  The filemap_flush() will
++	 * also start triggering a write of the data blocks, which is
++	 * not strictly speaking necessary (and for users of
++	 * laptop_mode, not even desirable).  However, to do otherwise
++	 * would require replicating code paths in:
++	 * 
++	 * ext4_da_writepages() ->
++	 *    write_cache_pages() ---> (via passed in callback function)
++	 *        __mpage_da_writepage() -->
++	 *           mpage_add_bh_to_extent()
++	 *           mpage_da_map_blocks()
++	 *
++	 * The problem is that write_cache_pages(), located in
++	 * mm/page-writeback.c, marks pages clean in preparation for
++	 * doing I/O, which is not desirable if we're not planning on
++	 * doing I/O at all.
++	 *
++	 * We could call write_cache_pages(), and then redirty all of
++	 * the pages by calling redirty_page_for_writeback() but that
++	 * would be ugly in the extreme.  So instead we would need to
++	 * replicate parts of the code in the above functions,
++	 * simplifying them becuase we wouldn't actually intend to
++	 * write out the pages, but rather only collect contiguous
++	 * logical block extents, call the multi-block allocator, and
++	 * then update the buffer heads with the block allocations.
++	 * 
++	 * For now, though, we'll cheat by calling filemap_flush(),
++	 * which will map the blocks, and start the I/O, but not
++	 * actually wait for the I/O to complete.
++	 */
++	return filemap_flush(inode->i_mapping);
++}
+ 
+ /*
+  * bmap() is special.  It gets used by applications such as lilo and by
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index 22dd29f3ebc9..91e75f7a9e73 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -262,6 +262,20 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 		return err;
+ 	}
+ 
++	case EXT4_IOC_ALLOC_DA_BLKS:
++	{
++		int err;
++		if (!is_owner_or_cap(inode))
++			return -EACCES;
++
++		err = mnt_want_write(filp->f_path.mnt);
++		if (err)
++			return err;
++		err = ext4_alloc_da_blocks(inode);
++		mnt_drop_write(filp->f_path.mnt);
++		return err;
++	}
++
+ 	default:
+ 		return -ENOTTY;
+ 	}

commit f63e6005bc63acc0a6bc3bdb8f971dcfbd827185
+Author: Theodore Ts'o 
+Date:   Mon Feb 23 16:42:39 2009 -0500
+
+    ext4: Simplify delalloc code by removing mpage_da_writepages()
+    
+    The mpage_da_writepages() function is only used in one place, so
+    inline it to simplify the call stack and make the code easier to
+    understand.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 008b28a859d0..24d0f9d2b320 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2241,47 +2241,6 @@ static int __mpage_da_writepage(struct page *page,
+ 	return 0;
+ }
+ 
+-/*
+- * mpage_da_writepages - walk the list of dirty pages of the given
+- * address space, allocates non-allocated blocks, maps newly-allocated
+- * blocks to existing bhs and issue IO them
+- *
+- * @mapping: address space structure to write
+- * @wbc: subtract the number of written pages from *@wbc->nr_to_write
+- *
+- * This is a library function, which implements the writepages()
+- * address_space_operation.
+- */
+-static int mpage_da_writepages(struct address_space *mapping,
+-			       struct writeback_control *wbc,
+-			       struct mpage_da_data *mpd)
+-{
+-	int ret;
+-
+-	mpd->b_size = 0;
+-	mpd->b_state = 0;
+-	mpd->b_blocknr = 0;
+-	mpd->first_page = 0;
+-	mpd->next_page = 0;
+-	mpd->io_done = 0;
+-	mpd->pages_written = 0;
+-	mpd->retval = 0;
+-
+-	ret = write_cache_pages(mapping, wbc, __mpage_da_writepage, mpd);
+-	/*
+-	 * Handle last extent of pages
+-	 */
+-	if (!mpd->io_done && mpd->next_page != mpd->first_page) {
+-		if (mpage_da_map_blocks(mpd) == 0)
+-			mpage_da_submit_io(mpd);
+-
+-		mpd->io_done = 1;
+-		ret = MPAGE_DA_EXTENT_TAIL;
+-	}
+-	wbc->nr_to_write -= mpd->pages_written;
+-	return ret;
+-}
+-
+ /*
+  * this is a special callback for ->write_begin() only
+  * it's intention is to return mapped block or reserve space
+@@ -2571,7 +2530,38 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 			dump_stack();
+ 			goto out_writepages;
+ 		}
+-		ret = mpage_da_writepages(mapping, wbc, &mpd);
++
++		/*
++		 * Now call __mpage_da_writepage to find the next
++		 * contiguous region of logical blocks that need
++		 * blocks to be allocated by ext4.  We don't actually
++		 * submit the blocks for I/O here, even though
++		 * write_cache_pages thinks it will, and will set the
++		 * pages as clean for write before calling
++		 * __mpage_da_writepage().
++		 */
++		mpd.b_size = 0;
++		mpd.b_state = 0;
++		mpd.b_blocknr = 0;
++		mpd.first_page = 0;
++		mpd.next_page = 0;
++		mpd.io_done = 0;
++		mpd.pages_written = 0;
++		mpd.retval = 0;
++		ret = write_cache_pages(mapping, wbc, __mpage_da_writepage,
++					&mpd);
++		/*
++		 * If we have a contigous extent of pages and we
++		 * haven't done the I/O yet, map the blocks and submit
++		 * them for I/O.
++		 */
++		if (!mpd.io_done && mpd.next_page != mpd.first_page) {
++			if (mpage_da_map_blocks(&mpd) == 0)
++				mpage_da_submit_io(&mpd);
++			mpd.io_done = 1;
++			ret = MPAGE_DA_EXTENT_TAIL;
++		}
++		wbc->nr_to_write -= mpd.pages_written;
+ 
+ 		ext4_journal_stop(handle);
+ 

commit 8dc207c0e7a259e7122ddfaf56b8bbbc3c92d685
+Author: Theodore Ts'o 
+Date:   Mon Feb 23 06:46:01 2009 -0500
+
+    ext4: Save stack space by removing fake buffer heads
+    
+    Struct mpage_da_data and mpage_add_bh_to_extent() use a fake struct
+    buffer_head which is 104 bytes on an x86_64 system, but only use 24
+    bytes of the structure.  On systems that use a spinlock for atomic_t,
+    the stack savings will be even greater.
+    
+    It turns out that using a fake struct buffer_head doesn't even save
+    that much code, and it makes the code more confusing since it's not
+    used as a "real" buffer head.  So just store pass b_size and b_state
+    in mpage_add_bh_to_extent(), and store b_size, b_state, and b_block_nr
+    in the mpage_da_data structure.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 924ba8afc227..008b28a859d0 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1703,7 +1703,9 @@ static void ext4_da_page_release_reservation(struct page *page,
+ 
+ struct mpage_da_data {
+ 	struct inode *inode;
+-	struct buffer_head lbh;			/* extent of blocks */
++	sector_t b_blocknr;		/* start block number of extent */
++	size_t b_size;			/* size of extent */
++	unsigned long b_state;		/* state of the extent */
+ 	unsigned long first_page, next_page;	/* extent of pages */
+ 	struct writeback_control *wbc;
+ 	int io_done;
+@@ -1737,7 +1739,7 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd)
+ 	/*
+ 	 * We need to start from the first_page to the next_page - 1
+ 	 * to make sure we also write the mapped dirty buffer_heads.
+-	 * If we look at mpd->lbh.b_blocknr we would only be looking
++	 * If we look at mpd->b_blocknr we would only be looking
+ 	 * at the currently mapped buffer_heads.
+ 	 */
+ 	index = mpd->first_page;
+@@ -1975,7 +1977,7 @@ static int ext4_da_get_block_write(struct inode *inode, sector_t iblock,
+ /*
+  * mpage_da_map_blocks - go through given space
+  *
+- * @mpd->lbh - bh describing space
++ * @mpd - bh describing space
+  *
+  * The function skips space we know is already mapped to disk blocks.
+  *
+@@ -1984,18 +1986,18 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
+ {
+ 	int err = 0;
+ 	struct buffer_head new;
+-	struct buffer_head *lbh = &mpd->lbh;
+ 	sector_t next;
+ 
+ 	/*
+ 	 * We consider only non-mapped and non-allocated blocks
+ 	 */
+-	if (buffer_mapped(lbh) && !buffer_delay(lbh))
++	if ((mpd->b_state  & (1 << BH_Mapped)) &&
++	    !(mpd->b_state & (1 << BH_Delay)))
+ 		return 0;
+-	new.b_state = lbh->b_state;
++	new.b_state = mpd->b_state;
+ 	new.b_blocknr = 0;
+-	new.b_size = lbh->b_size;
+-	next = lbh->b_blocknr;
++	new.b_size = mpd->b_size;
++	next = mpd->b_blocknr;
+ 	/*
+ 	 * If we didn't accumulate anything
+ 	 * to write simply return
+@@ -2031,7 +2033,7 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
+ 				  "%zd with error %d\n",
+ 				  __func__, mpd->inode->i_ino,
+ 				  (unsigned long long)next,
+-				  lbh->b_size >> mpd->inode->i_blkbits, err);
++				  mpd->b_size >> mpd->inode->i_blkbits, err);
+ 		printk(KERN_EMERG "This should not happen.!! "
+ 					"Data will be lost\n");
+ 		if (err == -ENOSPC) {
+@@ -2039,7 +2041,7 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
+ 		}
+ 		/* invlaidate all the pages */
+ 		ext4_da_block_invalidatepages(mpd, next,
+-				lbh->b_size >> mpd->inode->i_blkbits);
++				mpd->b_size >> mpd->inode->i_blkbits);
+ 		return err;
+ 	}
+ 	BUG_ON(new.b_size == 0);
+@@ -2051,7 +2053,8 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
+ 	 * If blocks are delayed marked, we need to
+ 	 * put actual blocknr and drop delayed bit
+ 	 */
+-	if (buffer_delay(lbh) || buffer_unwritten(lbh))
++	if ((mpd->b_state & (1 << BH_Delay)) ||
++	    (mpd->b_state & (1 << BH_Unwritten)))
+ 		mpage_put_bnr_to_bhs(mpd, next, &new);
+ 
+ 	return 0;
+@@ -2070,12 +2073,11 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
+  * the function is used to collect contig. blocks in same state
+  */
+ static void mpage_add_bh_to_extent(struct mpage_da_data *mpd,
+-				   sector_t logical, struct buffer_head *bh)
++				   sector_t logical, size_t b_size,
++				   unsigned long b_state)
+ {
+ 	sector_t next;
+-	size_t b_size = bh->b_size;
+-	struct buffer_head *lbh = &mpd->lbh;
+-	int nrblocks = lbh->b_size >> mpd->inode->i_blkbits;
++	int nrblocks = mpd->b_size >> mpd->inode->i_blkbits;
+ 
+ 	/* check if thereserved journal credits might overflow */
+ 	if (!(EXT4_I(mpd->inode)->i_flags & EXT4_EXTENTS_FL)) {
+@@ -2102,19 +2104,19 @@ static void mpage_add_bh_to_extent(struct mpage_da_data *mpd,
+ 	/*
+ 	 * First block in the extent
+ 	 */
+-	if (lbh->b_size == 0) {
+-		lbh->b_blocknr = logical;
+-		lbh->b_size = b_size;
+-		lbh->b_state = bh->b_state & BH_FLAGS;
++	if (mpd->b_size == 0) {
++		mpd->b_blocknr = logical;
++		mpd->b_size = b_size;
++		mpd->b_state = b_state & BH_FLAGS;
+ 		return;
+ 	}
+ 
+-	next = lbh->b_blocknr + nrblocks;
++	next = mpd->b_blocknr + nrblocks;
+ 	/*
+ 	 * Can we merge the block to our big extent?
+ 	 */
+-	if (logical == next && (bh->b_state & BH_FLAGS) == lbh->b_state) {
+-		lbh->b_size += b_size;
++	if (logical == next && (b_state & BH_FLAGS) == mpd->b_state) {
++		mpd->b_size += b_size;
+ 		return;
+ 	}
+ 
+@@ -2143,7 +2145,7 @@ static int __mpage_da_writepage(struct page *page,
+ {
+ 	struct mpage_da_data *mpd = data;
+ 	struct inode *inode = mpd->inode;
+-	struct buffer_head *bh, *head, fake;
++	struct buffer_head *bh, *head;
+ 	sector_t logical;
+ 
+ 	if (mpd->io_done) {
+@@ -2185,9 +2187,9 @@ static int __mpage_da_writepage(struct page *page,
+ 		/*
+ 		 * ... and blocks
+ 		 */
+-		mpd->lbh.b_size = 0;
+-		mpd->lbh.b_state = 0;
+-		mpd->lbh.b_blocknr = 0;
++		mpd->b_size = 0;
++		mpd->b_state = 0;
++		mpd->b_blocknr = 0;
+ 	}
+ 
+ 	mpd->next_page = page->index + 1;
+@@ -2195,16 +2197,8 @@ static int __mpage_da_writepage(struct page *page,
+ 		  (PAGE_CACHE_SHIFT - inode->i_blkbits);
+ 
+ 	if (!page_has_buffers(page)) {
+-		/*
+-		 * There is no attached buffer heads yet (mmap?)
+-		 * we treat the page asfull of dirty blocks
+-		 */
+-		bh = &fake;
+-		bh->b_size = PAGE_CACHE_SIZE;
+-		bh->b_state = 0;
+-		set_buffer_dirty(bh);
+-		set_buffer_uptodate(bh);
+-		mpage_add_bh_to_extent(mpd, logical, bh);
++		mpage_add_bh_to_extent(mpd, logical, PAGE_CACHE_SIZE,
++				       (1 << BH_Dirty) | (1 << BH_Uptodate));
+ 		if (mpd->io_done)
+ 			return MPAGE_DA_EXTENT_TAIL;
+ 	} else {
+@@ -2222,8 +2216,10 @@ static int __mpage_da_writepage(struct page *page,
+ 			 * with the page in ext4_da_writepage
+ 			 */
+ 			if (buffer_dirty(bh) &&
+-				(!buffer_mapped(bh) || buffer_delay(bh))) {
+-				mpage_add_bh_to_extent(mpd, logical, bh);
++			    (!buffer_mapped(bh) || buffer_delay(bh))) {
++				mpage_add_bh_to_extent(mpd, logical,
++						       bh->b_size,
++						       bh->b_state);
+ 				if (mpd->io_done)
+ 					return MPAGE_DA_EXTENT_TAIL;
+ 			} else if (buffer_dirty(bh) && (buffer_mapped(bh))) {
+@@ -2235,9 +2231,8 @@ static int __mpage_da_writepage(struct page *page,
+ 				 * unmapped buffer_head later we need to
+ 				 * use the b_state flag of that buffer_head.
+ 				 */
+-				if (mpd->lbh.b_size == 0)
+-					mpd->lbh.b_state =
+-						bh->b_state & BH_FLAGS;
++				if (mpd->b_size == 0)
++					mpd->b_state = bh->b_state & BH_FLAGS;
+ 			}
+ 			logical++;
+ 		} while ((bh = bh->b_this_page) != head);
+@@ -2263,9 +2258,9 @@ static int mpage_da_writepages(struct address_space *mapping,
+ {
+ 	int ret;
+ 
+-	mpd->lbh.b_size = 0;
+-	mpd->lbh.b_state = 0;
+-	mpd->lbh.b_blocknr = 0;
++	mpd->b_size = 0;
++	mpd->b_state = 0;
++	mpd->b_blocknr = 0;
+ 	mpd->first_page = 0;
+ 	mpd->next_page = 0;
+ 	mpd->io_done = 0;

commit ed5bde0bf8995d7d8c0b5a9c33e624a945f333ef
+Author: Theodore Ts'o 
+Date:   Mon Feb 23 10:48:07 2009 -0500
+
+    ext4: Simplify delalloc implementation by removing mpd.get_block
+    
+    This parameter was always set to ext4_da_get_block_write().
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index cd0399db0ef1..924ba8afc227 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1705,7 +1705,6 @@ struct mpage_da_data {
+ 	struct inode *inode;
+ 	struct buffer_head lbh;			/* extent of blocks */
+ 	unsigned long first_page, next_page;	/* extent of pages */
+-	get_block_t *get_block;
+ 	struct writeback_control *wbc;
+ 	int io_done;
+ 	int pages_written;
+@@ -1719,7 +1718,6 @@ struct mpage_da_data {
+  * @mpd->inode: inode
+  * @mpd->first_page: first page of the extent
+  * @mpd->next_page: page after the last page of the extent
+- * @mpd->get_block: the filesystem's block mapper function
+  *
+  * By the time mpage_da_submit_io() is called we expect all blocks
+  * to be allocated. this may be wrong if allocation failed.
+@@ -1929,16 +1927,60 @@ static void ext4_print_free_blocks(struct inode *inode)
+ 	return;
+ }
+ 
++#define		EXT4_DELALLOC_RSVED	1
++static int ext4_da_get_block_write(struct inode *inode, sector_t iblock,
++				   struct buffer_head *bh_result, int create)
++{
++	int ret;
++	unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
++	loff_t disksize = EXT4_I(inode)->i_disksize;
++	handle_t *handle = NULL;
++
++	handle = ext4_journal_current_handle();
++	BUG_ON(!handle);
++	ret = ext4_get_blocks_wrap(handle, inode, iblock, max_blocks,
++				   bh_result, create, 0, EXT4_DELALLOC_RSVED);
++	if (ret <= 0)
++		return ret;
++
++	bh_result->b_size = (ret << inode->i_blkbits);
++
++	if (ext4_should_order_data(inode)) {
++		int retval;
++		retval = ext4_jbd2_file_inode(handle, inode);
++		if (retval)
++			/*
++			 * Failed to add inode for ordered mode. Don't
++			 * update file size
++			 */
++			return retval;
++	}
++
++	/*
++	 * Update on-disk size along with block allocation we don't
++	 * use 'extend_disksize' as size may change within already
++	 * allocated block -bzzz
++	 */
++	disksize = ((loff_t) iblock + ret) << inode->i_blkbits;
++	if (disksize > i_size_read(inode))
++		disksize = i_size_read(inode);
++	if (disksize > EXT4_I(inode)->i_disksize) {
++		ext4_update_i_disksize(inode, disksize);
++		ret = ext4_mark_inode_dirty(handle, inode);
++		return ret;
++	}
++	return 0;
++}
++
+ /*
+  * mpage_da_map_blocks - go through given space
+  *
+  * @mpd->lbh - bh describing space
+- * @mpd->get_block - the filesystem's block mapper function
+  *
+  * The function skips space we know is already mapped to disk blocks.
+  *
+  */
+-static int  mpage_da_map_blocks(struct mpage_da_data *mpd)
++static int mpage_da_map_blocks(struct mpage_da_data *mpd)
+ {
+ 	int err = 0;
+ 	struct buffer_head new;
+@@ -1960,30 +2002,29 @@ static int  mpage_da_map_blocks(struct mpage_da_data *mpd)
+ 	 */
+ 	if (!new.b_size)
+ 		return 0;
+-	err = mpd->get_block(mpd->inode, next, &new, 1);
+-	if (err) {
+ 
+-		/* If get block returns with error
+-		 * we simply return. Later writepage
+-		 * will redirty the page and writepages
+-		 * will find the dirty page again
++	err = ext4_da_get_block_write(mpd->inode, next, &new, 1);
++	if (err) {
++		/*
++		 * If get block returns with error we simply
++		 * return. Later writepage will redirty the page and
++		 * writepages will find the dirty page again
+ 		 */
+ 		if (err == -EAGAIN)
+ 			return 0;
+ 
+ 		if (err == -ENOSPC &&
+-				ext4_count_free_blocks(mpd->inode->i_sb)) {
++		    ext4_count_free_blocks(mpd->inode->i_sb)) {
+ 			mpd->retval = err;
+ 			return 0;
+ 		}
+ 
+ 		/*
+-		 * get block failure will cause us
+-		 * to loop in writepages. Because
+-		 * a_ops->writepage won't be able to
+-		 * make progress. The page will be redirtied
+-		 * by writepage and writepages will again
+-		 * try to write the same.
++		 * get block failure will cause us to loop in
++		 * writepages, because a_ops->writepage won't be able
++		 * to make progress. The page will be redirtied by
++		 * writepage and writepages will again try to write
++		 * the same.
+ 		 */
+ 		printk(KERN_EMERG "%s block allocation failed for inode %lu "
+ 				  "at logical offset %llu with max blocks "
+@@ -2212,7 +2253,6 @@ static int __mpage_da_writepage(struct page *page,
+  *
+  * @mapping: address space structure to write
+  * @wbc: subtract the number of written pages from *@wbc->nr_to_write
+- * @get_block: the filesystem's block mapper function.
+  *
+  * This is a library function, which implements the writepages()
+  * address_space_operation.
+@@ -2223,9 +2263,6 @@ static int mpage_da_writepages(struct address_space *mapping,
+ {
+ 	int ret;
+ 
+-	if (!mpd->get_block)
+-		return generic_writepages(mapping, wbc);
+-
+ 	mpd->lbh.b_size = 0;
+ 	mpd->lbh.b_state = 0;
+ 	mpd->lbh.b_blocknr = 0;
+@@ -2289,51 +2326,6 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock,
+ 
+ 	return ret;
+ }
+-#define		EXT4_DELALLOC_RSVED	1
+-static int ext4_da_get_block_write(struct inode *inode, sector_t iblock,
+-				   struct buffer_head *bh_result, int create)
+-{
+-	int ret;
+-	unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
+-	loff_t disksize = EXT4_I(inode)->i_disksize;
+-	handle_t *handle = NULL;
+-
+-	handle = ext4_journal_current_handle();
+-	BUG_ON(!handle);
+-	ret = ext4_get_blocks_wrap(handle, inode, iblock, max_blocks,
+-			bh_result, create, 0, EXT4_DELALLOC_RSVED);
+-	if (ret > 0) {
+-
+-		bh_result->b_size = (ret << inode->i_blkbits);
+-
+-		if (ext4_should_order_data(inode)) {
+-			int retval;
+-			retval = ext4_jbd2_file_inode(handle, inode);
+-			if (retval)
+-				/*
+-				 * Failed to add inode for ordered
+-				 * mode. Don't update file size
+-				 */
+-				return retval;
+-		}
+-
+-		/*
+-		 * Update on-disk size along with block allocation
+-		 * we don't use 'extend_disksize' as size may change
+-		 * within already allocated block -bzzz
+-		 */
+-		disksize = ((loff_t) iblock + ret) << inode->i_blkbits;
+-		if (disksize > i_size_read(inode))
+-			disksize = i_size_read(inode);
+-		if (disksize > EXT4_I(inode)->i_disksize) {
+-			ext4_update_i_disksize(inode, disksize);
+-			ret = ext4_mark_inode_dirty(handle, inode);
+-			return ret;
+-		}
+-		ret = 0;
+-	}
+-	return ret;
+-}
+ 
+ static int ext4_bh_unmapped_or_delay(handle_t *handle, struct buffer_head *bh)
+ {
+@@ -2584,7 +2576,6 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 			dump_stack();
+ 			goto out_writepages;
+ 		}
+-		mpd.get_block = ext4_da_get_block_write;
+ 		ret = mpage_da_writepages(mapping, wbc, &mpd);
+ 
+ 		ext4_journal_stop(handle);

commit 722bde6875bfb49a0c84e5601eb82dd7ac02d27c
+Author: Theodore Ts'o 
+Date:   Mon Feb 23 00:51:57 2009 -0500
+
+    ext4: Add fine print for the 32000 subdirectory limit
+    
+    Some poeple are reading the ext4 feature list too literally and create
+    dubious test cases involving very long filenames and 1k blocksize and
+    then complain when they run into an htree-imposed limit.  So add fine
+    print to the "fix 32000 subdirectory limit" ext4 feature.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
+index cec829bc7291..5c484aec2bab 100644
+--- a/Documentation/filesystems/ext4.txt
++++ b/Documentation/filesystems/ext4.txt
+@@ -85,7 +85,7 @@ Note: More extensive information for getting started with ext4 can be
+ * extent format more robust in face of on-disk corruption due to magics,
+ * internal redundancy in tree
+ * improved file allocation (multi-block alloc)
+-* fix 32000 subdirectory limit
++* lift 32000 subdirectory limit imposed by i_links_count[1]
+ * nsec timestamps for mtime, atime, ctime, create time
+ * inode version field on disk (NFSv4, Lustre)
+ * reduced e2fsck time via uninit_bg feature
+@@ -100,6 +100,9 @@ Note: More extensive information for getting started with ext4 can be
+ * efficent new ordered mode in JBD2 and ext4(avoid using buffer head to force
+   the ordering)
+ 
++[1] Filesystems with a block size of 1k may see a limit imposed by the
++directory hash tree having a maximum depth of two.
++
+ 2.2 Candidate features for future inclusion
+ 
+ * Online defrag (patches available but not well tested)

commit a4912123b688e057084e6557cef8924f7ae5bbde
+Author: Theodore Ts'o 
+Date:   Thu Mar 12 12:18:34 2009 -0400
+
+    ext4: New inode/block allocation algorithms for flex_bg filesystems
+    
+    The find_group_flex() inode allocator is now only used if the
+    filesystem is mounted using the "oldalloc" mount option.  It is
+    replaced with the original Orlov allocator that has been updated for
+    flex_bg filesystems (it should behave the same way if flex_bg is
+    disabled).  The inode allocator now functions by taking into account
+    each flex_bg group, instead of each block group, when deciding whether
+    or not it's time to allocate a new directory into a fresh flex_bg.
+    
+    The block allocator has also been changed so that the first block
+    group in each flex_bg is preferred for use for storing directory
+    blocks.  This keeps directory blocks close together, which is good for
+    speeding up e2fsck since large directories are more likely to look
+    like this:
+    
+    debugfs:  stat /home/tytso/Maildir/cur
+    Inode: 1844562   Type: directory    Mode:  0700   Flags: 0x81000
+    Generation: 1132745781    Version: 0x00000000:0000ad71
+    User: 15806   Group: 15806   Size: 1060864
+    File ACL: 0    Directory ACL: 0
+    Links: 2   Blockcount: 2072
+    Fragment:  Address: 0    Number: 0    Size: 0
+     ctime: 0x499c0ff4:164961f4 -- Wed Feb 18 08:41:08 2009
+     atime: 0x499c0ff4:00000000 -- Wed Feb 18 08:41:08 2009
+     mtime: 0x49957f51:00000000 -- Fri Feb 13 09:10:25 2009
+    crtime: 0x499c0f57:00d51440 -- Wed Feb 18 08:38:31 2009
+    Size of extra inode fields: 28
+    BLOCKS:
+    (0):7348651, (1-258):7348654-7348911
+    TOTAL: 259
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 2cbfc0b04d37..096456c8559b 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -827,6 +827,12 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
+ #define EXT4_DEF_MIN_BATCH_TIME	0
+ #define EXT4_DEF_MAX_BATCH_TIME	15000 /* 15ms */
+ 
++/*
++ * Minimum number of groups in a flexgroup before we separate out
++ * directories into the first block group of a flexgroup
++ */
++#define EXT4_FLEX_SIZE_DIR_ALLOC_SCHEME	4
++
+ /*
+  * Structure of a directory entry
+  */
+diff --git a/fs/ext4/ext4_i.h b/fs/ext4/ext4_i.h
+index 2d516c0a22af..4ce2187123aa 100644
+--- a/fs/ext4/ext4_i.h
++++ b/fs/ext4/ext4_i.h
+@@ -122,6 +122,9 @@ struct ext4_inode_info {
+ 	struct list_head i_prealloc_list;
+ 	spinlock_t i_prealloc_lock;
+ 
++	/* ialloc */
++	ext4_group_t	i_last_alloc_group;
++
+ 	/* allocation reservation info for delalloc */
+ 	unsigned int i_reserved_data_blocks;
+ 	unsigned int i_reserved_meta_blocks;
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index e0aa4fe4f596..aa3431856c9a 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -152,6 +152,8 @@ static ext4_fsblk_t ext4_ext_find_goal(struct inode *inode,
+ 	ext4_fsblk_t bg_start;
+ 	ext4_fsblk_t last_block;
+ 	ext4_grpblk_t colour;
++	ext4_group_t block_group;
++	int flex_size = ext4_flex_bg_size(EXT4_SB(inode->i_sb));
+ 	int depth;
+ 
+ 	if (path) {
+@@ -170,10 +172,31 @@ static ext4_fsblk_t ext4_ext_find_goal(struct inode *inode,
+ 	}
+ 
+ 	/* OK. use inode's group */
+-	bg_start = (ei->i_block_group * EXT4_BLOCKS_PER_GROUP(inode->i_sb)) +
++	block_group = ei->i_block_group;
++	if (flex_size >= EXT4_FLEX_SIZE_DIR_ALLOC_SCHEME) {
++		/*
++		 * If there are at least EXT4_FLEX_SIZE_DIR_ALLOC_SCHEME
++		 * block groups per flexgroup, reserve the first block 
++		 * group for directories and special files.  Regular 
++		 * files will start at the second block group.  This
++		 * tends to speed up directory access and improves 
++		 * fsck times.
++		 */
++		block_group &= ~(flex_size-1);
++		if (S_ISREG(inode->i_mode))
++			block_group++;
++	}
++	bg_start = (block_group * EXT4_BLOCKS_PER_GROUP(inode->i_sb)) +
+ 		le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_first_data_block);
+ 	last_block = ext4_blocks_count(EXT4_SB(inode->i_sb)->s_es) - 1;
+ 
++	/*
++	 * If we are doing delayed allocation, we don't need take
++	 * colour into account.
++	 */
++	if (test_opt(inode->i_sb, DELALLOC))
++		return bg_start;
++
+ 	if (bg_start + EXT4_BLOCKS_PER_GROUP(inode->i_sb) <= last_block)
+ 		colour = (current->pid % 16) *
+ 			(EXT4_BLOCKS_PER_GROUP(inode->i_sb) / 16);
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index ae3eb57dccdd..617f5a2d800a 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -410,6 +410,43 @@ static int find_group_flex(struct super_block *sb, struct inode *parent,
+ 	return 0;
+ }
+ 
++struct orlov_stats {
++	__u32 free_inodes;
++	__u32 free_blocks;
++	__u32 used_dirs;
++};
++
++/*
++ * Helper function for Orlov's allocator; returns critical information
++ * for a particular block group or flex_bg.  If flex_size is 1, then g
++ * is a block group number; otherwise it is flex_bg number.
++ */
++void get_orlov_stats(struct super_block *sb, ext4_group_t g,
++		       int flex_size, struct orlov_stats *stats)
++{
++	struct ext4_group_desc *desc;
++	ext4_group_t		ngroups = EXT4_SB(sb)->s_groups_count;
++	int			i;
++
++	stats->free_inodes = 0;
++	stats->free_blocks = 0;
++	stats->used_dirs = 0;
++
++	g *= flex_size;
++
++	for (i = 0; i < flex_size; i++) {
++		if (g >= ngroups)
++			break;
++		desc = ext4_get_group_desc(sb, g++, NULL);
++		if (!desc)
++			continue;
++
++		stats->free_inodes += ext4_free_inodes_count(sb, desc);
++		stats->free_blocks += ext4_free_blks_count(sb, desc);
++		stats->used_dirs += ext4_used_dirs_count(sb, desc);
++	}
++}
++
+ /*
+  * Orlov's allocator for directories.
+  *
+@@ -425,35 +462,34 @@ static int find_group_flex(struct super_block *sb, struct inode *parent,
+  * it has too many directories already (max_dirs) or
+  * it has too few free inodes left (min_inodes) or
+  * it has too few free blocks left (min_blocks) or
+- * it's already running too large debt (max_debt).
+  * Parent's group is preferred, if it doesn't satisfy these
+  * conditions we search cyclically through the rest. If none
+  * of the groups look good we just look for a group with more
+  * free inodes than average (starting at parent's group).
+- *
+- * Debt is incremented each time we allocate a directory and decremented
+- * when we allocate an inode, within 0--255.
+  */
+ 
+-#define INODE_COST 64
+-#define BLOCK_COST 256
+-
+ static int find_group_orlov(struct super_block *sb, struct inode *parent,
+-				ext4_group_t *group)
++			    ext4_group_t *group, int mode)
+ {
+ 	ext4_group_t parent_group = EXT4_I(parent)->i_block_group;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-	struct ext4_super_block *es = sbi->s_es;
+ 	ext4_group_t ngroups = sbi->s_groups_count;
+ 	int inodes_per_group = EXT4_INODES_PER_GROUP(sb);
+ 	unsigned int freei, avefreei;
+ 	ext4_fsblk_t freeb, avefreeb;
+-	ext4_fsblk_t blocks_per_dir;
+ 	unsigned int ndirs;
+-	int max_debt, max_dirs, min_inodes;
++	int max_dirs, min_inodes;
+ 	ext4_grpblk_t min_blocks;
+-	ext4_group_t i;
++	ext4_group_t i, grp, g;
+ 	struct ext4_group_desc *desc;
++	struct orlov_stats stats;
++	int flex_size = ext4_flex_bg_size(sbi);
++
++	if (flex_size > 1) {
++		ngroups = (ngroups + flex_size - 1) >>
++			sbi->s_log_groups_per_flex;
++		parent_group >>= sbi->s_log_groups_per_flex;
++	}
+ 
+ 	freei = percpu_counter_read_positive(&sbi->s_freeinodes_counter);
+ 	avefreei = freei / ngroups;
+@@ -462,71 +498,97 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
+ 	do_div(avefreeb, ngroups);
+ 	ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter);
+ 
+-	if ((parent == sb->s_root->d_inode) ||
+-	    (EXT4_I(parent)->i_flags & EXT4_TOPDIR_FL)) {
++	if (S_ISDIR(mode) &&
++	    ((parent == sb->s_root->d_inode) ||
++	     (EXT4_I(parent)->i_flags & EXT4_TOPDIR_FL))) {
+ 		int best_ndir = inodes_per_group;
+-		ext4_group_t grp;
+ 		int ret = -1;
+ 
+ 		get_random_bytes(&grp, sizeof(grp));
+ 		parent_group = (unsigned)grp % ngroups;
+ 		for (i = 0; i < ngroups; i++) {
+-			grp = (parent_group + i) % ngroups;
+-			desc = ext4_get_group_desc(sb, grp, NULL);
+-			if (!desc || !ext4_free_inodes_count(sb, desc))
++			g = (parent_group + i) % ngroups;
++			get_orlov_stats(sb, g, flex_size, &stats);
++			if (!stats.free_inodes)
+ 				continue;
+-			if (ext4_used_dirs_count(sb, desc) >= best_ndir)
++			if (stats.used_dirs >= best_ndir)
+ 				continue;
+-			if (ext4_free_inodes_count(sb, desc) < avefreei)
++			if (stats.free_inodes < avefreei)
+ 				continue;
+-			if (ext4_free_blks_count(sb, desc) < avefreeb)
++			if (stats.free_blocks < avefreeb)
+ 				continue;
+-			*group = grp;
++			grp = g;
+ 			ret = 0;
+-			best_ndir = ext4_used_dirs_count(sb, desc);
++			best_ndir = stats.used_dirs;
++		}
++		if (ret)
++			goto fallback;
++	found_flex_bg:
++		if (flex_size == 1) {
++			*group = grp;
++			return 0;
++		}
++
++		/*
++		 * We pack inodes at the beginning of the flexgroup's
++		 * inode tables.  Block allocation decisions will do
++		 * something similar, although regular files will
++		 * start at 2nd block group of the flexgroup.  See
++		 * ext4_ext_find_goal() and ext4_find_near().
++		 */
++		grp *= flex_size;
++		for (i = 0; i < flex_size; i++) {
++			if (grp+i >= sbi->s_groups_count)
++				break;
++			desc = ext4_get_group_desc(sb, grp+i, NULL);
++			if (desc && ext4_free_inodes_count(sb, desc)) {
++				*group = grp+i;
++				return 0;
++			}
+ 		}
+-		if (ret == 0)
+-			return ret;
+ 		goto fallback;
+ 	}
+ 
+-	blocks_per_dir = ext4_blocks_count(es) - freeb;
+-	do_div(blocks_per_dir, ndirs);
+-
+ 	max_dirs = ndirs / ngroups + inodes_per_group / 16;
+-	min_inodes = avefreei - inodes_per_group / 4;
+-	min_blocks = avefreeb - EXT4_BLOCKS_PER_GROUP(sb) / 4;
+-
+-	max_debt = EXT4_BLOCKS_PER_GROUP(sb);
+-	max_debt /= max_t(int, blocks_per_dir, BLOCK_COST);
+-	if (max_debt * INODE_COST > inodes_per_group)
+-		max_debt = inodes_per_group / INODE_COST;
+-	if (max_debt > 255)
+-		max_debt = 255;
+-	if (max_debt == 0)
+-		max_debt = 1;
++	min_inodes = avefreei - inodes_per_group*flex_size / 4;
++	if (min_inodes < 1)
++		min_inodes = 1;
++	min_blocks = avefreeb - EXT4_BLOCKS_PER_GROUP(sb)*flex_size / 4;
++
++	/*
++	 * Start looking in the flex group where we last allocated an
++	 * inode for this parent directory
++	 */
++	if (EXT4_I(parent)->i_last_alloc_group != ~0) {
++		parent_group = EXT4_I(parent)->i_last_alloc_group;
++		if (flex_size > 1)
++			parent_group >>= sbi->s_log_groups_per_flex;
++	}
+ 
+ 	for (i = 0; i < ngroups; i++) {
+-		*group = (parent_group + i) % ngroups;
+-		desc = ext4_get_group_desc(sb, *group, NULL);
+-		if (!desc || !ext4_free_inodes_count(sb, desc))
+-			continue;
+-		if (ext4_used_dirs_count(sb, desc) >= max_dirs)
++		grp = (parent_group + i) % ngroups;
++		get_orlov_stats(sb, grp, flex_size, &stats);
++		if (stats.used_dirs >= max_dirs)
+ 			continue;
+-		if (ext4_free_inodes_count(sb, desc) < min_inodes)
++		if (stats.free_inodes < min_inodes)
+ 			continue;
+-		if (ext4_free_blks_count(sb, desc) < min_blocks)
++		if (stats.free_blocks < min_blocks)
+ 			continue;
+-		return 0;
++		goto found_flex_bg;
+ 	}
+ 
+ fallback:
++	ngroups = sbi->s_groups_count;
++	avefreei = freei / ngroups;
++	parent_group = EXT4_I(parent)->i_block_group;
+ 	for (i = 0; i < ngroups; i++) {
+-		*group = (parent_group + i) % ngroups;
+-		desc = ext4_get_group_desc(sb, *group, NULL);
++		grp = (parent_group + i) % ngroups;
++		desc = ext4_get_group_desc(sb, grp, NULL);
+ 		if (desc && ext4_free_inodes_count(sb, desc) &&
+-			ext4_free_inodes_count(sb, desc) >= avefreei)
++		    ext4_free_inodes_count(sb, desc) >= avefreei) {
++			*group = grp;
+ 			return 0;
++		}
+ 	}
+ 
+ 	if (avefreei) {
+@@ -542,12 +604,51 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
+ }
+ 
+ static int find_group_other(struct super_block *sb, struct inode *parent,
+-				ext4_group_t *group)
++			    ext4_group_t *group, int mode)
+ {
+ 	ext4_group_t parent_group = EXT4_I(parent)->i_block_group;
+ 	ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count;
+ 	struct ext4_group_desc *desc;
+-	ext4_group_t i;
++	ext4_group_t i, last;
++	int flex_size = ext4_flex_bg_size(EXT4_SB(sb));
++
++	/*
++	 * Try to place the inode is the same flex group as its
++	 * parent.  If we can't find space, use the Orlov algorithm to
++	 * find another flex group, and store that information in the
++	 * parent directory's inode information so that use that flex
++	 * group for future allocations.
++	 */
++	if (flex_size > 1) {
++		int retry = 0;
++
++	try_again:
++		parent_group &= ~(flex_size-1);
++		last = parent_group + flex_size;
++		if (last > ngroups)
++			last = ngroups;
++		for  (i = parent_group; i < last; i++) {
++			desc = ext4_get_group_desc(sb, i, NULL);
++			if (desc && ext4_free_inodes_count(sb, desc)) {
++				*group = i;
++				return 0;
++			}
++		}
++		if (!retry && EXT4_I(parent)->i_last_alloc_group != ~0) {
++			retry = 1;
++			parent_group = EXT4_I(parent)->i_last_alloc_group;
++			goto try_again;
++		}
++		/*
++		 * If this didn't work, use the Orlov search algorithm
++		 * to find a new flex group; we pass in the mode to
++		 * avoid the topdir algorithms.
++		 */
++		*group = parent_group + flex_size;
++		if (*group > ngroups)
++			*group = 0;
++		return find_group_orlov(sb, parent, group, mode);
++	}
+ 
+ 	/*
+ 	 * Try to place the inode in its parent directory
+@@ -716,10 +817,10 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
+ 	sbi = EXT4_SB(sb);
+ 	es = sbi->s_es;
+ 
+-	if (sbi->s_log_groups_per_flex) {
++	if (sbi->s_log_groups_per_flex && test_opt(sb, OLDALLOC)) {
+ 		ret2 = find_group_flex(sb, dir, &group);
+ 		if (ret2 == -1) {
+-			ret2 = find_group_other(sb, dir, &group);
++			ret2 = find_group_other(sb, dir, &group, mode);
+ 			if (ret2 == 0 && once)
+ 				once = 0;
+ 				printk(KERN_NOTICE "ext4: find_group_flex "
+@@ -733,11 +834,12 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
+ 		if (test_opt(sb, OLDALLOC))
+ 			ret2 = find_group_dir(sb, dir, &group);
+ 		else
+-			ret2 = find_group_orlov(sb, dir, &group);
++			ret2 = find_group_orlov(sb, dir, &group, mode);
+ 	} else
+-		ret2 = find_group_other(sb, dir, &group);
++		ret2 = find_group_other(sb, dir, &group, mode);
+ 
+ got_group:
++	EXT4_I(dir)->i_last_alloc_group = group;
+ 	err = -ENOSPC;
+ 	if (ret2 == -1)
+ 		goto out;
+@@ -894,6 +996,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
+ 	ei->i_file_acl = 0;
+ 	ei->i_dtime = 0;
+ 	ei->i_block_group = group;
++	ei->i_last_alloc_group = ~0;
+ 
+ 	ext4_set_inode_flags(inode);
+ 	if (IS_DIRSYNC(inode))
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 71d3ecd5db79..25811507d2b0 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -459,6 +459,8 @@ static ext4_fsblk_t ext4_find_near(struct inode *inode, Indirect *ind)
+ 	ext4_fsblk_t bg_start;
+ 	ext4_fsblk_t last_block;
+ 	ext4_grpblk_t colour;
++	ext4_group_t block_group;
++	int flex_size = ext4_flex_bg_size(EXT4_SB(inode->i_sb));
+ 
+ 	/* Try to find previous block */
+ 	for (p = ind->p - 1; p >= start; p--) {
+@@ -474,9 +476,22 @@ static ext4_fsblk_t ext4_find_near(struct inode *inode, Indirect *ind)
+ 	 * It is going to be referred to from the inode itself? OK, just put it
+ 	 * into the same cylinder group then.
+ 	 */
+-	bg_start = ext4_group_first_block_no(inode->i_sb, ei->i_block_group);
++	block_group = ei->i_block_group;
++	if (flex_size >= EXT4_FLEX_SIZE_DIR_ALLOC_SCHEME) {
++		block_group &= ~(flex_size-1);
++		if (S_ISREG(inode->i_mode))
++			block_group++;
++	}
++	bg_start = ext4_group_first_block_no(inode->i_sb, block_group);
+ 	last_block = ext4_blocks_count(EXT4_SB(inode->i_sb)->s_es) - 1;
+ 
++	/*
++	 * If we are doing delayed allocation, we don't need take
++	 * colour into account.
++	 */
++	if (test_opt(inode->i_sb, DELALLOC))
++		return bg_start;
++
+ 	if (bg_start + EXT4_BLOCKS_PER_GROUP(inode->i_sb) <= last_block)
+ 		colour = (current->pid % 16) *
+ 			(EXT4_BLOCKS_PER_GROUP(inode->i_sb) / 16);
+@@ -4287,6 +4302,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 	ei->i_disksize = inode->i_size;
+ 	inode->i_generation = le32_to_cpu(raw_inode->i_generation);
+ 	ei->i_block_group = iloc.block_group;
++	ei->i_last_alloc_group = ~0;
+ 	/*
+ 	 * NOTE! The in-memory inode i_data array is in little-endian order
+ 	 * even on big-endian machines: we do NOT byteswap the block numbers!
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index b038188bd039..b0d6022eaa67 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -1726,6 +1726,7 @@ static int ext4_mb_good_group(struct ext4_allocation_context *ac,
+ {
+ 	unsigned free, fragments;
+ 	unsigned i, bits;
++	int flex_size = ext4_flex_bg_size(EXT4_SB(ac->ac_sb));
+ 	struct ext4_group_desc *desc;
+ 	struct ext4_group_info *grp = ext4_get_group_info(ac->ac_sb, group);
+ 
+@@ -1747,6 +1748,12 @@ static int ext4_mb_good_group(struct ext4_allocation_context *ac,
+ 		if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))
+ 			return 0;
+ 
++		/* Avoid using the first bg of a flexgroup for data files */
++		if ((ac->ac_flags & EXT4_MB_HINT_DATA) &&
++		    (flex_size >= EXT4_FLEX_SIZE_DIR_ALLOC_SCHEME) &&
++		    ((group % flex_size) == 0))
++			return 0;
++
+ 		bits = ac->ac_sb->s_blocksize_bits + 1;
+ 		for (i = ac->ac_2order; i <= bits; i++)
+ 			if (grp->bb_counters[i] > 0)

commit 05bf9e839d9de4e8a094274a0a2fd07beb47eaf1
+Author: Theodore Ts'o 
+Date:   Sat Feb 21 12:13:24 2009 -0500
+
+    ext4: Add fallback for find_group_flex
+    
+    This is a workaround for find_group_flex() which badly needs to be
+    replaced.  One of its problems (besides ignoring the Orlov algorithm)
+    is that it is a bit hyperactive about returning failure under
+    suspicious circumstances.  This can lead to spurious ENOSPC failures
+    even when there are inodes still available.
+    
+    Work around this for now by retrying the search using
+    find_group_other() if find_group_flex() returns -1.  If
+    find_group_other() succeeds when find_group_flex() has failed, log a
+    warning message.
+    
+    A better block/inode allocator that will fix this problem for real has
+    been queued up for the next merge window.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 4fb86a0061d0..f18a919be70b 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -715,6 +715,13 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
+ 
+ 	if (sbi->s_log_groups_per_flex) {
+ 		ret2 = find_group_flex(sb, dir, &group);
++		if (ret2 == -1) {
++			ret2 = find_group_other(sb, dir, &group);
++			if (ret2 == 0 && printk_ratelimit())
++				printk(KERN_NOTICE "ext4: find_group_flex "
++				       "failed, fallback succeeded dir %lu\n",
++				       dir->i_ino);
++		}
+ 		goto got_group;
+ 	}
+ 

commit 8bad4597c2d71365adfa846ea1ca6cf99161a455
+Author: Theodore Ts'o 
+Date:   Sat Feb 14 21:46:54 2009 -0500
+
+    ext4: Use unsigned int for blocksize in dx_make_map() and dx_pack_dirents()
+    
+    Signed-off-by: Wei Yongjun 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 83410244d3ee..04824958cba5 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -161,12 +161,12 @@ static struct dx_frame *dx_probe(const struct qstr *d_name,
+ 				 struct dx_frame *frame,
+ 				 int *err);
+ static void dx_release(struct dx_frame *frames);
+-static int dx_make_map(struct ext4_dir_entry_2 *de, int size,
++static int dx_make_map(struct ext4_dir_entry_2 *de, unsigned blocksize,
+ 		       struct dx_hash_info *hinfo, struct dx_map_entry map[]);
+ static void dx_sort_map(struct dx_map_entry *map, unsigned count);
+ static struct ext4_dir_entry_2 *dx_move_dirents(char *from, char *to,
+ 		struct dx_map_entry *offsets, int count);
+-static struct ext4_dir_entry_2* dx_pack_dirents(char *base, int size);
++static struct ext4_dir_entry_2* dx_pack_dirents(char *base, unsigned blocksize);
+ static void dx_insert_block(struct dx_frame *frame,
+ 					u32 hash, ext4_lblk_t block);
+ static int ext4_htree_next_block(struct inode *dir, __u32 hash,
+@@ -713,15 +713,15 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
+  * Create map of hash values, offsets, and sizes, stored at end of block.
+  * Returns number of entries mapped.
+  */
+-static int dx_make_map (struct ext4_dir_entry_2 *de, int size,
+-			struct dx_hash_info *hinfo, struct dx_map_entry *map_tail)
++static int dx_make_map(struct ext4_dir_entry_2 *de, unsigned blocksize,
++		       struct dx_hash_info *hinfo,
++		       struct dx_map_entry *map_tail)
+ {
+ 	int count = 0;
+ 	char *base = (char *) de;
+ 	struct dx_hash_info h = *hinfo;
+ 
+-	while ((char *) de < base + size)
+-	{
++	while ((char *) de < base + blocksize) {
+ 		if (de->name_len && de->inode) {
+ 			ext4fs_dirhash(de->name, de->name_len, &h);
+ 			map_tail--;
+@@ -1130,13 +1130,13 @@ dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count)
+  * Compact each dir entry in the range to the minimal rec_len.
+  * Returns pointer to last entry in range.
+  */
+-static struct ext4_dir_entry_2* dx_pack_dirents(char *base, int size)
++static struct ext4_dir_entry_2* dx_pack_dirents(char *base, unsigned blocksize)
+ {
+ 	struct ext4_dir_entry_2 *next, *to, *prev, *de = (struct ext4_dir_entry_2 *) base;
+ 	unsigned rec_len = 0;
+ 
+ 	prev = to = de;
+-	while ((char*)de < base + size) {
++	while ((char*)de < base + blocksize) {
+ 		next = ext4_next_entry(de);
+ 		if (de->inode && de->name_len) {
+ 			rec_len = EXT4_DIR_REC_LEN(de->name_len);

commit e187c6588d6ef3169db53c389b3de9dfde3b16cc
+Author: Theodore Ts'o 
+Date:   Fri Feb 6 16:23:37 2009 -0500
+
+    ext4: remove call to ext4_group_desc() in ext4_group_used_meta_blocks()
+    
+    The static function ext4_group_used_meta_blocks() only has one caller,
+    who already has access to the block group's group descriptor.  So it's
+    better to have ext4_init_block_bitmap() pass the group descriptor to
+    ext4_group_used_meta_blocks(), so it doesn't need to call
+    ext4_group_desc().  Previously this function did not check if
+    ext4_group_desc() returned NULL due to an error, potentially causing a
+    kernel OOPS report.  This avoids the issue entirely.
+    
+    Signed-off-by: Thadeu Lima de Souza Cascardo 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 38f40d55899c..b37b12875582 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -55,7 +55,8 @@ static int ext4_block_in_group(struct super_block *sb, ext4_fsblk_t block,
+ }
+ 
+ static int ext4_group_used_meta_blocks(struct super_block *sb,
+-				ext4_group_t block_group)
++				       ext4_group_t block_group,
++				       struct ext4_group_desc *gdp)
+ {
+ 	ext4_fsblk_t tmp;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+@@ -63,10 +64,6 @@ static int ext4_group_used_meta_blocks(struct super_block *sb,
+ 	int used_blocks = sbi->s_itb_per_group + 2;
+ 
+ 	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
+-		struct ext4_group_desc *gdp;
+-		struct buffer_head *bh;
+-
+-		gdp = ext4_get_group_desc(sb, block_group, &bh);
+ 		if (!ext4_block_in_group(sb, ext4_block_bitmap(sb, gdp),
+ 					block_group))
+ 			used_blocks--;
+@@ -177,7 +174,7 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
+ 		 */
+ 		mark_bitmap_end(group_blocks, sb->s_blocksize * 8, bh->b_data);
+ 	}
+-	return free_blocks - ext4_group_used_meta_blocks(sb, block_group);
++	return free_blocks - ext4_group_used_meta_blocks(sb, block_group, gdp);
+ }
+ 
+ 

commit dbdac9b71dff5d27885f82eb2cfca310861fdf9e
+Author: Theodore Ts'o 
+Date:   Tue Jan 13 15:27:32 2009 +0100
+
+    block: Fix documentation for blkdev_issue_flush()
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/blk-barrier.c b/block/blk-barrier.c
+index 8eba4e43bb0c..f7dae57e6cab 100644
+--- a/block/blk-barrier.c
++++ b/block/blk-barrier.c
+@@ -302,7 +302,7 @@ static void bio_end_empty_barrier(struct bio *bio, int err)
+  * Description:
+  *    Issue a flush for the block device in question. Caller can supply
+  *    room for storing the error offset in case of a flush error, if they
+- *    wish to.  Caller must run wait_for_completion() on its own.
++ *    wish to.
+  */
+ int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector)
+ {

commit b9ec63f78b425c0e16cc95605b5d4ff2dc228b97
+Author: Theodore Ts'o 
+Date:   Fri Jan 30 00:00:24 2009 -0500
+
+    ext4: Remove bogus BUG() check in ext4_bmap()
+    
+    The code to support journal-less ext4 operation added a BUG to
+    ext4_bmap() which fired if there was no journal and the
+    EXT4_STATE_JDATA bit was set in the i_state field.  This caused
+    running the filefrag program (which uses the FIMBAP ioctl) to trigger
+    a BUG().
+    
+    The EXT4_STATE_JDATA bit is only used for ext4_bmap(), and it's
+    harmless for the bit to be set.  We could add a check in
+    __ext4_journalled_writepage() and ext4_journalled_write_end() to only
+    set the EXT4_STATE_JDATA bit if the journal is present, but that adds
+    an extra test and jump instruction.  It's easier to simply remove the
+    BUG check.
+    
+    http://bugzilla.kernel.org/show_bug.cgi?id=12568
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index b4386dafeb0c..03ba20be1329 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2821,9 +2821,6 @@ static sector_t ext4_bmap(struct address_space *mapping, sector_t block)
+ 		filemap_write_and_wait(mapping);
+ 	}
+ 
+-	BUG_ON(!EXT4_JOURNAL(inode) &&
+-	       EXT4_I(inode)->i_state & EXT4_STATE_JDATA);
+-
+ 	if (EXT4_JOURNAL(inode) && EXT4_I(inode)->i_state & EXT4_STATE_JDATA) {
+ 		/*
+ 		 * This is a REALLY heavyweight approach, but the use of

commit fdff73f094e7220602cc3f8959c7230517976412
+Author: Theodore Ts'o 
+Date:   Mon Jan 26 19:06:41 2009 -0500
+
+    ext4: Initialize the new group descriptor when resizing the filesystem
+    
+    Make sure all of the fields of the group descriptor are properly
+    initialized.  Previously, we allowed bg_flags field to be contain
+    random garbage, which could trigger non-deterministic behavior,
+    including a kernel OOPS.
+    
+    http://bugzilla.kernel.org/show_bug.cgi?id=12433
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index c328be5d6885..c06886abd658 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -861,12 +861,13 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
+ 	gdp = (struct ext4_group_desc *)((char *)primary->b_data +
+ 					 gdb_off * EXT4_DESC_SIZE(sb));
+ 
++	memset(gdp, 0, EXT4_DESC_SIZE(sb));
+ 	ext4_block_bitmap_set(sb, gdp, input->block_bitmap); /* LV FIXME */
+ 	ext4_inode_bitmap_set(sb, gdp, input->inode_bitmap); /* LV FIXME */
+ 	ext4_inode_table_set(sb, gdp, input->inode_table); /* LV FIXME */
+ 	ext4_free_blks_set(sb, gdp, input->free_blocks_count);
+ 	ext4_free_inodes_set(sb, gdp, EXT4_INODES_PER_GROUP(sb));
+-	gdp->bg_flags |= cpu_to_le16(EXT4_BG_INODE_ZEROED);
++	gdp->bg_flags = cpu_to_le16(EXT4_BG_INODE_ZEROED);
+ 	gdp->bg_checksum = ext4_group_desc_csum(sbi, input->group, gdp);
+ 
+ 	/*

commit e7f07968c16bdd9480001c0a9de013ba56889cf9
+Author: Theodore Ts'o 
+Date:   Tue Jan 20 09:50:19 2009 -0500
+
+    ext4: Fix ext4_free_blocks() w/o a journal when files have indirect blocks
+    
+    When trying to unlink a file with indirect blocks on a filesystem
+    without a journal, the "circular indirect block" sanity test was
+    getting falsely triggered.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 49484ba801c9..b4386dafeb0c 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -3622,7 +3622,7 @@ static void ext4_free_data(handle_t *handle, struct inode *inode,
+ 		 * block pointed to itself, it would have been detached when
+ 		 * the block was cleared. Check for this instead of OOPSing.
+ 		 */
+-		if (bh2jh(this_bh))
++		if ((EXT4_JOURNAL(inode) == NULL) || bh2jh(this_bh))
+ 			ext4_handle_dirty_metadata(handle, inode, this_bh);
+ 		else
+ 			ext4_error(inode->i_sb, __func__,

commit 08ec8c3878cea0bf91f2ba3c0badf44b383752d0
+Author: Theodore Ts'o 
+Date:   Fri Jan 16 11:57:00 2009 -0500
+
+    jbd2: On a __journal_expect() assertion failure printk "JBD2", not "EXT3-fs"
+    
+    Otherwise it can be very confusing to find a "EXT3-fs: " failure in
+    the middle of EXT4-fs failures, and it makes it harder to track the
+    source of the failure.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index b45109c61fba..b28b37eb11c6 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -308,7 +308,8 @@ void buffer_assertion_failure(struct buffer_head *bh);
+ 		int val = (expr);					     \
+ 		if (!val) {						     \
+ 			printk(KERN_ERR					     \
+-				"EXT3-fs unexpected failure: %s;\n",# expr); \
++			       "JBD2 unexpected failure: %s: %s;\n",	     \
++			       __func__, #expr);			     \
+ 			printk(KERN_ERR why "\n");			     \
+ 		}							     \
+ 		val;							     \

commit a21102b55c4f8dfd3adb4a15a34cd62237b46039
+Author: Theodore Ts'o 
+Date:   Fri Jan 16 11:13:47 2009 -0500
+
+    ext3: Add sanity check to make_indexed_dir
+    
+    Make sure the rec_len field in the '..' entry is sane, lest we overrun
+    the directory block and cause a kernel oops on a purposefully
+    corrupted filesystem.
+    
+    This fixes a bug related to a bug originally reported by Sami Liedes
+    for ext4 at:
+    
+    http://bugzilla.kernel.org/show_bug.cgi?id=12430
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
+index 69a3d19ca9fd..4db4ffa1edad 100644
+--- a/fs/ext3/namei.c
++++ b/fs/ext3/namei.c
+@@ -1358,7 +1358,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
+ 	struct fake_dirent *fde;
+ 
+ 	blocksize =  dir->i_sb->s_blocksize;
+-	dxtrace(printk("Creating index\n"));
++	dxtrace(printk(KERN_DEBUG "Creating index: inode %lu\n", dir->i_ino));
+ 	retval = ext3_journal_get_write_access(handle, bh);
+ 	if (retval) {
+ 		ext3_std_error(dir->i_sb, retval);
+@@ -1367,6 +1367,19 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
+ 	}
+ 	root = (struct dx_root *) bh->b_data;
+ 
++	/* The 0th block becomes the root, move the dirents out */
++	fde = &root->dotdot;
++	de = (struct ext3_dir_entry_2 *)((char *)fde +
++			ext3_rec_len_from_disk(fde->rec_len));
++	if ((char *) de >= (((char *) root) + blocksize)) {
++		ext3_error(dir->i_sb, __func__,
++			   "invalid rec_len for '..' in inode %lu",
++			   dir->i_ino);
++		brelse(bh);
++		return -EIO;
++	}
++	len = ((char *) root) + blocksize - (char *) de;
++
+ 	bh2 = ext3_append (handle, dir, &block, &retval);
+ 	if (!(bh2)) {
+ 		brelse(bh);
+@@ -1375,11 +1388,6 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
+ 	EXT3_I(dir)->i_flags |= EXT3_INDEX_FL;
+ 	data1 = bh2->b_data;
+ 
+-	/* The 0th block becomes the root, move the dirents out */
+-	fde = &root->dotdot;
+-	de = (struct ext3_dir_entry_2 *)((char *)fde +
+-			ext3_rec_len_from_disk(fde->rec_len));
+-	len = ((char *) root) + blocksize - (char *) de;
+ 	memcpy (data1, de, len);
+ 	de = (struct ext3_dir_entry_2 *) data1;
+ 	top = data1 + len;

commit e6b8bc09ba2075cd91fbffefcd2778b1a00bd76f
+Author: Theodore Ts'o 
+Date:   Fri Jan 16 11:13:40 2009 -0500
+
+    ext4: Add sanity check to make_indexed_dir
+    
+    Make sure the rec_len field in the '..' entry is sane, lest we overrun
+    the directory block and cause a kernel oops on a purposefully
+    corrupted filesystem.
+    
+    Thanks to Sami Liedes for reporting this bug.
+    
+    http://bugzilla.kernel.org/show_bug.cgi?id=12430
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index fec0b4c2f5f1..ba702bd7910d 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1368,7 +1368,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
+ 	struct fake_dirent *fde;
+ 
+ 	blocksize =  dir->i_sb->s_blocksize;
+-	dxtrace(printk(KERN_DEBUG "Creating index\n"));
++	dxtrace(printk(KERN_DEBUG "Creating index: inode %lu\n", dir->i_ino));
+ 	retval = ext4_journal_get_write_access(handle, bh);
+ 	if (retval) {
+ 		ext4_std_error(dir->i_sb, retval);
+@@ -1377,6 +1377,20 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
+ 	}
+ 	root = (struct dx_root *) bh->b_data;
+ 
++	/* The 0th block becomes the root, move the dirents out */
++	fde = &root->dotdot;
++	de = (struct ext4_dir_entry_2 *)((char *)fde +
++		ext4_rec_len_from_disk(fde->rec_len));
++	if ((char *) de >= (((char *) root) + blocksize)) {
++		ext4_error(dir->i_sb, __func__,
++			   "invalid rec_len for '..' in inode %lu",
++			   dir->i_ino);
++		brelse(bh);
++		return -EIO;
++	}
++	len = ((char *) root) + blocksize - (char *) de;
++
++	/* Allocate new block for the 0th block's dirents */
+ 	bh2 = ext4_append(handle, dir, &block, &retval);
+ 	if (!(bh2)) {
+ 		brelse(bh);
+@@ -1385,11 +1399,6 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
+ 	EXT4_I(dir)->i_flags |= EXT4_INDEX_FL;
+ 	data1 = bh2->b_data;
+ 
+-	/* The 0th block becomes the root, move the dirents out */
+-	fde = &root->dotdot;
+-	de = (struct ext4_dir_entry_2 *)((char *)fde +
+-		ext4_rec_len_from_disk(fde->rec_len));
+-	len = ((char *) root) + blocksize - (char *) de;
+ 	memcpy (data1, de, len);
+ 	de = (struct ext4_dir_entry_2 *) data1;
+ 	top = data1 + len;

commit 06a279d636734da32bb62dd2f7b0ade666f65d7c
+Author: Theodore Ts'o 
+Date:   Sat Jan 17 18:41:37 2009 -0500
+
+    ext4: only use i_size_high for regular files
+    
+    Directories are not allowed to be bigger than 2GB, so don't use
+    i_size_high for anything other than regular files.  E2fsck should
+    complain about these inodes, but the simplest thing to do for the
+    kernel is to only use i_size_high for regular files.
+    
+    This prevents an intentially corrupted filesystem from causing the
+    kernel to burn a huge amount of CPU and issuing error messages such
+    as:
+    
+    EXT4-fs warning (device loop0): ext4_block_to_path: block 135090028 > max
+    
+    Thanks to David Maciejak from Fortinet's FortiGuard Global Security
+    Research Team for reporting this issue.
+    
+    http://bugzilla.kernel.org/show_bug.cgi?id=12375
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index c668e4377d76..aafc9eba1c25 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1206,8 +1206,11 @@ static inline void ext4_r_blocks_count_set(struct ext4_super_block *es,
+ 
+ static inline loff_t ext4_isize(struct ext4_inode *raw_inode)
+ {
+-	return ((loff_t)le32_to_cpu(raw_inode->i_size_high) << 32) |
+-		le32_to_cpu(raw_inode->i_size_lo);
++	if (S_ISREG(le16_to_cpu(raw_inode->i_mode)))
++		return ((loff_t)le32_to_cpu(raw_inode->i_size_high) << 32) |
++			le32_to_cpu(raw_inode->i_size_lo);
++	else
++		return (loff_t) le32_to_cpu(raw_inode->i_size_lo);
+ }
+ 
+ static inline void ext4_isize_set(struct ext4_inode *raw_inode, loff_t i_size)
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index a6444cee0c7e..49484ba801c9 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -360,9 +360,9 @@ static int ext4_block_to_path(struct inode *inode,
+ 		final = ptrs;
+ 	} else {
+ 		ext4_warning(inode->i_sb, "ext4_block_to_path",
+-				"block %lu > max",
++				"block %lu > max in inode %lu",
+ 				i_block + direct_blocks +
+-				indirect_blocks + double_blocks);
++				indirect_blocks + double_blocks, inode->i_ino);
+ 	}
+ 	if (boundary)
+ 		*boundary = final - 1 - (i_block & (ptrs - 1));

commit 83982b6f47201c4c7767210d24d7d8c99567a0b3
+Author: Theodore Ts'o 
+Date:   Tue Jan 6 14:53:16 2009 -0500
+
+    ext4: Remove "extents" mount option
+    
+    This mount option is largely superfluous, and in fact the way it was
+    implemented was buggy; if a filesystem which did not have the extents
+    feature flag was mounted -o extents, the filesystem would attempt to
+    create and use extents-based file even though the extents feature flag
+    was not eabled.  The simplest thing to do is to nuke the mount option
+    entirely.  It's not all that useful to force the non-creation of new
+    extent-based files if the filesystem can support it.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
+index 8938949b201e..cec829bc7291 100644
+--- a/Documentation/filesystems/ext4.txt
++++ b/Documentation/filesystems/ext4.txt
+@@ -131,11 +131,6 @@ ro                   	Mount filesystem read only. Note that ext4 will
+                      	mount options "ro,noload" can be used to prevent
+ 		     	writes to the filesystem.
+ 
+-extents		(*)	ext4 will use extents to address file data.  The
+-			file system will no longer be mountable by ext3.
+-
+-noextents		ext4 will not use extents for newly created files
+-
+ journal_checksum	Enable checksumming of the journal transactions.
+ 			This will allow the recovery code in e2fsck and the
+ 			kernel to detect corruption in the kernel.  It is a
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 695b45cc34e7..db1718833f58 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -536,7 +536,6 @@ do {									       \
+ #define EXT4_MOUNT_QUOTA		0x80000 /* Some quota option set */
+ #define EXT4_MOUNT_USRQUOTA		0x100000 /* "old" user quota */
+ #define EXT4_MOUNT_GRPQUOTA		0x200000 /* "old" group quota */
+-#define EXT4_MOUNT_EXTENTS		0x400000 /* Extents support */
+ #define EXT4_MOUNT_JOURNAL_CHECKSUM	0x800000 /* Journal checksums */
+ #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT	0x1000000 /* Journal Async Commit */
+ #define EXT4_MOUNT_I_VERSION            0x2000000 /* i_version support */
+diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
+index 663197adae56..be2f426f6805 100644
+--- a/fs/ext4/ext4_jbd2.h
++++ b/fs/ext4/ext4_jbd2.h
+@@ -32,8 +32,8 @@
+  * 5 levels of tree + root which are stored in the inode. */
+ 
+ #define EXT4_SINGLEDATA_TRANS_BLOCKS(sb)				\
+-	(EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)	\
+-		|| test_opt(sb, EXTENTS) ? 27U : 8U)
++	(EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)   \
++	 ? 27U : 8U)
+ 
+ /* Extended attribute operations touch at most two data buffers,
+  * two bitmap buffers, and two group summaries, in addition to the inode
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index c64080e49493..240cf0daad4b 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -2247,7 +2247,7 @@ void ext4_ext_init(struct super_block *sb)
+ 	 * possible initialization would be here
+ 	 */
+ 
+-	if (test_opt(sb, EXTENTS)) {
++	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
+ 		printk(KERN_INFO "EXT4-fs: file extents enabled");
+ #ifdef AGGRESSIVE_TEST
+ 		printk(", aggressive tests");
+@@ -2272,7 +2272,7 @@ void ext4_ext_init(struct super_block *sb)
+  */
+ void ext4_ext_release(struct super_block *sb)
+ {
+-	if (!test_opt(sb, EXTENTS))
++	if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS))
+ 		return;
+ 
+ #ifdef EXTENTS_STATS
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 369c34c64292..4fb86a0061d0 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -917,7 +917,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
+ 	if (err)
+ 		goto fail_free_drop;
+ 
+-	if (test_opt(sb, EXTENTS)) {
++	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
+ 		/* set extent flag only for directory, file and normal symlink*/
+ 		if (S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode)) {
+ 			EXT4_I(inode)->i_flags |= EXT4_EXTENTS_FL;
+diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
+index e7cd488da4bb..734abca25e35 100644
+--- a/fs/ext4/migrate.c
++++ b/fs/ext4/migrate.c
+@@ -459,13 +459,13 @@ int ext4_ext_migrate(struct inode *inode)
+ 	struct list_blocks_struct lb;
+ 	unsigned long max_entries;
+ 
+-	if (!test_opt(inode->i_sb, EXTENTS))
+-		/*
+-		 * if mounted with noextents we don't allow the migrate
+-		 */
+-		return -EINVAL;
+-
+-	if ((EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL))
++	/*
++	 * If the filesystem does not support extents, or the inode
++	 * already is extent-based, error out.
++	 */
++	if (!EXT4_HAS_INCOMPAT_FEATURE(inode->i_sb,
++				       EXT4_FEATURE_INCOMPAT_EXTENTS) ||
++	    (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL))
+ 		return -EINVAL;
+ 
+ 	if (S_ISLNK(inode->i_mode) && inode->i_blocks == 0)
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index b69d09203865..acb69c00fd42 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -829,8 +829,6 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
+ 		seq_puts(seq, ",journal_async_commit");
+ 	if (test_opt(sb, NOBH))
+ 		seq_puts(seq, ",nobh");
+-	if (!test_opt(sb, EXTENTS))
+-		seq_puts(seq, ",noextents");
+ 	if (test_opt(sb, I_VERSION))
+ 		seq_puts(seq, ",i_version");
+ 	if (!test_opt(sb, DELALLOC))
+@@ -1011,7 +1009,7 @@ enum {
+ 	Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
+ 	Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
+ 	Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
+-	Opt_grpquota, Opt_extents, Opt_noextents, Opt_i_version,
++	Opt_grpquota, Opt_i_version,
+ 	Opt_stripe, Opt_delalloc, Opt_nodelalloc,
+ 	Opt_inode_readahead_blks, Opt_journal_ioprio
+ };
+@@ -1066,8 +1064,6 @@ static const match_table_t tokens = {
+ 	{Opt_quota, "quota"},
+ 	{Opt_usrquota, "usrquota"},
+ 	{Opt_barrier, "barrier=%u"},
+-	{Opt_extents, "extents"},
+-	{Opt_noextents, "noextents"},
+ 	{Opt_i_version, "i_version"},
+ 	{Opt_stripe, "stripe=%u"},
+ 	{Opt_resize, "resize"},
+@@ -1115,7 +1111,6 @@ static int parse_options(char *options, struct super_block *sb,
+ 	int qtype, qfmt;
+ 	char *qname;
+ #endif
+-	ext4_fsblk_t last_block;
+ 
+ 	if (!options)
+ 		return 1;
+@@ -1445,33 +1440,6 @@ static int parse_options(char *options, struct super_block *sb,
+ 		case Opt_bh:
+ 			clear_opt(sbi->s_mount_opt, NOBH);
+ 			break;
+-		case Opt_extents:
+-			if (!EXT4_HAS_INCOMPAT_FEATURE(sb,
+-					EXT4_FEATURE_INCOMPAT_EXTENTS)) {
+-				ext4_warning(sb, __func__,
+-					"extents feature not enabled "
+-					"on this filesystem, use tune2fs");
+-				return 0;
+-			}
+-			set_opt(sbi->s_mount_opt, EXTENTS);
+-			break;
+-		case Opt_noextents:
+-			/*
+-			 * When e2fsprogs support resizing an already existing
+-			 * ext3 file system to greater than 2**32 we need to
+-			 * add support to block allocator to handle growing
+-			 * already existing block  mapped inode so that blocks
+-			 * allocated for them fall within 2**32
+-			 */
+-			last_block = ext4_blocks_count(sbi->s_es) - 1;
+-			if (last_block  > 0xffffffffULL) {
+-				printk(KERN_ERR "EXT4-fs: Filesystem too "
+-						"large to mount with "
+-						"-o noextents options\n");
+-				return 0;
+-			}
+-			clear_opt(sbi->s_mount_opt, EXTENTS);
+-			break;
+ 		case Opt_i_version:
+ 			set_opt(sbi->s_mount_opt, I_VERSION);
+ 			sb->s_flags |= MS_I_VERSION;
+@@ -2135,18 +2103,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	set_opt(sbi->s_mount_opt, RESERVATION);
+ 	set_opt(sbi->s_mount_opt, BARRIER);
+ 
+-	/*
+-	 * turn on extents feature by default in ext4 filesystem
+-	 * only if feature flag already set by mkfs or tune2fs.
+-	 * Use -o noextents to turn it off
+-	 */
+-	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS))
+-		set_opt(sbi->s_mount_opt, EXTENTS);
+-	else
+-		ext4_warning(sb, __func__,
+-			"extents feature not enabled on this filesystem, "
+-			"use tune2fs.");
+-
+ 	/*
+ 	 * enable delayed allocation by default
+ 	 * Use -o nodelalloc to turn it off
+@@ -3825,7 +3781,7 @@ static void __exit exit_ext4_fs(void)
+ }
+ 
+ MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
+-MODULE_DESCRIPTION("Fourth Extended Filesystem with extents");
++MODULE_DESCRIPTION("Fourth Extended Filesystem");
+ MODULE_LICENSE("GPL");
+ module_init(init_ext4_fs)
+ module_exit(exit_ext4_fs)

commit 4d783b093cd4f3e2738527365979cbd1c5101065
+Author: Theodore Ts'o 
+Date:   Tue Jan 6 15:16:33 2009 -0500
+
+    block: Add Kconfig help which notes that ext4 needs CONFIG_LBD
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Jens Axboe 
+
+diff --git a/block/Kconfig b/block/Kconfig
+index ac0956f77785..0cbb3b88b59a 100644
+--- a/block/Kconfig
++++ b/block/Kconfig
+@@ -36,6 +36,12 @@ config LBD
+ 	  This option also enables support for single files larger than
+ 	  2TB.
+ 
++	  The ext4 filesystem requires that this feature be enabled in
++	  order to support filesystems that have the huge_file feature
++	  enabled.    Otherwise, it will refuse to mount any filesystems
++	  that use the huge_file feature, which is enabled by default
++	  by mke2fs.ext4.   The GFS2 filesystem also requires this feature.
++
+ 	  If unsure, say N.
+ 
+ config BLK_DEV_IO_TRACE

commit abda14189251563a50f56da5ea2e37e904ac4cba
+Author: Theodore Ts'o 
+Date:   Tue Jan 6 00:20:32 2009 -0500
+
+    ext4: Make printk's consistently prefixed with "EXT4-fs: "
+    
+    Previously, some were "ext4: ", and some were "EXT4: "; change them to
+    be consistent with most ext4 printk's, which is to use "EXT4-fs: ".
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index cf3ccf4a94b0..2df2e40b01af 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -405,7 +405,7 @@ static int call_filldir(struct file *filp, void *dirent,
+ 	sb = inode->i_sb;
+ 
+ 	if (!fname) {
+-		printk(KERN_ERR "ext4: call_filldir: called with "
++		printk(KERN_ERR "EXT4-fs: call_filldir: called with "
+ 		       "null fname?!?\n");
+ 		return 0;
+ 	}
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 517c90ad25bd..b69d09203865 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -505,7 +505,7 @@ static struct block_device *ext4_blkdev_get(dev_t dev)
+ 	return bdev;
+ 
+ fail:
+-	printk(KERN_ERR "EXT4: failed to open journal device %s: %ld\n",
++	printk(KERN_ERR "EXT4-fs: failed to open journal device %s: %ld\n",
+ 			__bdevname(dev, b), PTR_ERR(bdev));
+ 	return NULL;
+ }
+@@ -2485,7 +2485,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	if (ext4_blocks_count(es) > 0xffffffffULL &&
+ 	    !jbd2_journal_set_features(EXT4_SB(sb)->s_journal, 0, 0,
+ 				       JBD2_FEATURE_INCOMPAT_64BIT)) {
+-		printk(KERN_ERR "ext4: Failed to set 64-bit journal feature\n");
++		printk(KERN_ERR "EXT4-fs: Failed to set 64-bit journal feature\n");
+ 		goto failed_mount4;
+ 	}
+ 
+@@ -2766,7 +2766,7 @@ static journal_t *ext4_get_dev_journal(struct super_block *sb,
+ 
+ 	if (bd_claim(bdev, sb)) {
+ 		printk(KERN_ERR
+-			"EXT4: failed to claim external journal device.\n");
++			"EXT4-fs: failed to claim external journal device.\n");
+ 		blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
+ 		return NULL;
+ 	}
+@@ -2949,7 +2949,7 @@ static void ext4_commit_super(struct super_block *sb,
+ 		 * be remapped.  Nothing we can do but to retry the
+ 		 * write and hope for the best.
+ 		 */
+-		printk(KERN_ERR "ext4: previous I/O error to "
++		printk(KERN_ERR "EXT4-fs: previous I/O error to "
+ 		       "superblock detected for %s.\n", sb->s_id);
+ 		clear_buffer_write_io_error(sbh);
+ 		set_buffer_uptodate(sbh);
+@@ -2965,7 +2965,7 @@ static void ext4_commit_super(struct super_block *sb,
+ 	if (sync) {
+ 		sync_dirty_buffer(sbh);
+ 		if (buffer_write_io_error(sbh)) {
+-			printk(KERN_ERR "ext4: I/O error while writing "
++			printk(KERN_ERR "EXT4-fs: I/O error while writing "
+ 			       "superblock for %s.\n", sb->s_id);
+ 			clear_buffer_write_io_error(sbh);
+ 			set_buffer_uptodate(sbh);

commit 4ec110281379826c5cf6ed14735e47027c3c5765
+Author: Theodore Ts'o 
+Date:   Tue Jan 6 14:53:26 2009 -0500
+
+    ext4: Add sanity checks for the superblock before mounting the filesystem
+    
+    This avoids insane superblock configurations that could lead to kernel
+    oops due to null pointer derefences.
+    
+    http://bugzilla.kernel.org/show_bug.cgi?id=12371
+    
+    Thanks to David Maciejak at Fortinet's FortiGuard Global Security
+    Research Team who discovered this bug independently (but at
+    approximately the same time) as Thiemo Nagel, who submitted the patch.
+    
+    Signed-off-by: Thiemo Nagel 
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@kernel.org
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 8ff8709828fd..517c90ad25bd 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2041,8 +2041,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	const char *descr;
+ 	int ret = -EINVAL;
+ 	int blocksize;
+-	int db_count;
+-	int i;
++	unsigned int db_count;
++	unsigned int i;
+ 	int needs_recovery, has_huge_files;
+ 	int features;
+ 	__u64 blocks_count;
+@@ -2331,20 +2331,30 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	if (EXT4_BLOCKS_PER_GROUP(sb) == 0)
+ 		goto cantfind_ext4;
+ 
+-	/* ensure blocks_count calculation below doesn't sign-extend */
+-	if (ext4_blocks_count(es) + EXT4_BLOCKS_PER_GROUP(sb) <
+-	    le32_to_cpu(es->s_first_data_block) + 1) {
+-		printk(KERN_WARNING "EXT4-fs: bad geometry: block count %llu, "
+-		       "first data block %u, blocks per group %lu\n",
+-			ext4_blocks_count(es),
+-			le32_to_cpu(es->s_first_data_block),
+-			EXT4_BLOCKS_PER_GROUP(sb));
++        /*
++         * It makes no sense for the first data block to be beyond the end
++         * of the filesystem.
++         */
++        if (le32_to_cpu(es->s_first_data_block) >= ext4_blocks_count(es)) {
++                printk(KERN_WARNING "EXT4-fs: bad geometry: first data"
++		       "block %u is beyond end of filesystem (%llu)\n",
++		       le32_to_cpu(es->s_first_data_block),
++		       ext4_blocks_count(es));
+ 		goto failed_mount;
+ 	}
+ 	blocks_count = (ext4_blocks_count(es) -
+ 			le32_to_cpu(es->s_first_data_block) +
+ 			EXT4_BLOCKS_PER_GROUP(sb) - 1);
+ 	do_div(blocks_count, EXT4_BLOCKS_PER_GROUP(sb));
++	if (blocks_count > ((uint64_t)1<<32) - EXT4_DESC_PER_BLOCK(sb)) {
++		printk(KERN_WARNING "EXT4-fs: groups count too large: %u "
++		       "(block count %llu, first data block %u, "
++		       "blocks per group %lu)\n", sbi->s_groups_count,
++		       ext4_blocks_count(es),
++		       le32_to_cpu(es->s_first_data_block),
++		       EXT4_BLOCKS_PER_GROUP(sb));
++		goto failed_mount;
++	}
+ 	sbi->s_groups_count = blocks_count;
+ 	db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) /
+ 		   EXT4_DESC_PER_BLOCK(sb);

commit b3881f74b31b7d47d0f1c4d89ac3e7f0b9c05e3e
+Author: Theodore Ts'o 
+Date:   Mon Jan 5 22:46:26 2009 -0500
+
+    ext4: Add mount option to set kjournald's I/O priority
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Jens Axboe 
+
+diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
+index 9ec29d86ff8b..8938949b201e 100644
+--- a/Documentation/filesystems/ext4.txt
++++ b/Documentation/filesystems/ext4.txt
+@@ -308,6 +308,13 @@ min_batch_time=usec	This parameter sets the commit time (as
+ 			multi-threaded, synchronous workloads on very
+ 			fast disks, at the cost of increasing latency.
+ 
++journal_ioprio=prio	The I/O priority (from 0 to 7, where 0 is the
++			highest priorty) which should be used for I/O
++			operations submitted by kjournald2 during a
++			commit operation.  This defaults to 3, which is
++			a slightly higher priority than the default I/O
++			priority.
++
+ Data Mode
+ =========
+ There are 3 different data modes:
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 8036392b2121..8ff8709828fd 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1013,7 +1013,7 @@ enum {
+ 	Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
+ 	Opt_grpquota, Opt_extents, Opt_noextents, Opt_i_version,
+ 	Opt_stripe, Opt_delalloc, Opt_nodelalloc,
+-	Opt_inode_readahead_blks
++	Opt_inode_readahead_blks, Opt_journal_ioprio
+ };
+ 
+ static const match_table_t tokens = {
+@@ -1074,6 +1074,7 @@ static const match_table_t tokens = {
+ 	{Opt_delalloc, "delalloc"},
+ 	{Opt_nodelalloc, "nodelalloc"},
+ 	{Opt_inode_readahead_blks, "inode_readahead_blks=%u"},
++	{Opt_journal_ioprio, "journal_ioprio=%u"},
+ 	{Opt_err, NULL},
+ };
+ 
+@@ -1098,8 +1099,11 @@ static ext4_fsblk_t get_sb_block(void **data)
+ 	return sb_block;
+ }
+ 
++#define DEFAULT_JOURNAL_IOPRIO (IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 3))
++
+ static int parse_options(char *options, struct super_block *sb,
+ 			 unsigned long *journal_devnum,
++			 unsigned int *journal_ioprio,
+ 			 ext4_fsblk_t *n_blocks_count, int is_remount)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+@@ -1492,6 +1496,14 @@ static int parse_options(char *options, struct super_block *sb,
+ 				return 0;
+ 			sbi->s_inode_readahead_blks = option;
+ 			break;
++		case Opt_journal_ioprio:
++			if (match_int(&args[0], &option))
++				return 0;
++			if (option < 0 || option > 7)
++				break;
++			*journal_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE,
++							    option);
++			break;
+ 		default:
+ 			printk(KERN_ERR
+ 			       "EXT4-fs: Unrecognized mount option \"%s\" "
+@@ -2035,6 +2047,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	int features;
+ 	__u64 blocks_count;
+ 	int err;
++	unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO;
+ 
+ 	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
+ 	if (!sbi)
+@@ -2141,7 +2154,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	set_opt(sbi->s_mount_opt, DELALLOC);
+ 
+ 
+-	if (!parse_options((char *) data, sb, &journal_devnum, NULL, 0))
++	if (!parse_options((char *) data, sb, &journal_devnum,
++			   &journal_ioprio, NULL, 0))
+ 		goto failed_mount;
+ 
+ 	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
+@@ -2506,6 +2520,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	default:
+ 		break;
+ 	}
++	set_task_ioprio(sbi->s_journal->j_task, journal_ioprio);
+ 
+ no_journal:
+ 
+@@ -3127,6 +3142,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 	unsigned long old_sb_flags;
+ 	struct ext4_mount_options old_opts;
+ 	ext4_group_t g;
++	unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO;
+ 	int err;
+ #ifdef CONFIG_QUOTA
+ 	int i;
+@@ -3145,11 +3161,14 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 	for (i = 0; i < MAXQUOTAS; i++)
+ 		old_opts.s_qf_names[i] = sbi->s_qf_names[i];
+ #endif
++	if (sbi->s_journal && sbi->s_journal->j_task->io_context)
++		journal_ioprio = sbi->s_journal->j_task->io_context->ioprio;
+ 
+ 	/*
+ 	 * Allow the "check" option to be passed as a remount option.
+ 	 */
+-	if (!parse_options(data, sb, NULL, &n_blocks_count, 1)) {
++	if (!parse_options(data, sb, NULL, &journal_ioprio,
++			   &n_blocks_count, 1)) {
+ 		err = -EINVAL;
+ 		goto restore_opts;
+ 	}
+@@ -3162,8 +3181,10 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 
+ 	es = sbi->s_es;
+ 
+-	if (sbi->s_journal)
++	if (sbi->s_journal) {
+ 		ext4_init_journal_params(sb, sbi->s_journal);
++		set_task_ioprio(sbi->s_journal->j_task, journal_ioprio);
++	}
+ 
+ 	if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY) ||
+ 		n_blocks_count > ext4_blocks_count(es)) {
+diff --git a/fs/ioprio.c b/fs/ioprio.c
+index 3569e0ad86a2..1a39ac370942 100644
+--- a/fs/ioprio.c
++++ b/fs/ioprio.c
+@@ -27,7 +27,7 @@
+ #include 
+ #include 
+ 
+-static int set_task_ioprio(struct task_struct *task, int ioprio)
++int set_task_ioprio(struct task_struct *task, int ioprio)
+ {
+ 	int err;
+ 	struct io_context *ioc;
+@@ -70,6 +70,7 @@ static int set_task_ioprio(struct task_struct *task, int ioprio)
+ 	task_unlock(task);
+ 	return err;
+ }
++EXPORT_SYMBOL_GPL(set_task_ioprio);
+ 
+ asmlinkage long sys_ioprio_set(int which, int who, int ioprio)
+ {
+diff --git a/include/linux/ioprio.h b/include/linux/ioprio.h
+index f98a656b17e5..76dad4808847 100644
+--- a/include/linux/ioprio.h
++++ b/include/linux/ioprio.h
+@@ -86,4 +86,6 @@ static inline int task_nice_ioclass(struct task_struct *task)
+  */
+ extern int ioprio_best(unsigned short aprio, unsigned short bprio);
+ 
++extern int set_task_ioprio(struct task_struct *task, int ioprio);
++
+ #endif

commit 40a1984d22294ab202f616e432bb8d3481897675
+Author: Theodore Ts'o 
+Date:   Sun Jan 4 19:55:57 2009 -0500
+
+    jbd2: Submit writes to the journal using WRITE_SYNC
+    
+    Since we will be waiting the write of the commit record to the journal
+    to complete in journal_submit_commit_record(), submit it using
+    WRITE_SYNC.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index 0ad84162c425..073124a29b8c 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -138,7 +138,7 @@ static int journal_submit_commit_record(journal_t *journal,
+ 		set_buffer_ordered(bh);
+ 		barrier_done = 1;
+ 	}
+-	ret = submit_bh(WRITE, bh);
++	ret = submit_bh(WRITE_SYNC, bh);
+ 	if (barrier_done)
+ 		clear_buffer_ordered(bh);
+ 
+@@ -159,7 +159,7 @@ static int journal_submit_commit_record(journal_t *journal,
+ 		lock_buffer(bh);
+ 		set_buffer_uptodate(bh);
+ 		clear_buffer_dirty(bh);
+-		ret = submit_bh(WRITE, bh);
++		ret = submit_bh(WRITE_SYNC, bh);
+ 	}
+ 	*cbh = bh;
+ 	return ret;

commit 4a9bf99b205448ec1f0cbdee1776a29f9c503ce4
+Author: Theodore Ts'o 
+Date:   Sat Jan 3 22:56:44 2009 -0500
+
+    jbd2: Add pid and journal device name to the "kjournald2 starting" message
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index b10d7283ba5b..fe20e40ee7c3 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -131,8 +131,9 @@ static int kjournald2(void *arg)
+ 	journal->j_task = current;
+ 	wake_up(&journal->j_wait_done_commit);
+ 
+-	printk(KERN_INFO "kjournald2 starting.  Commit interval %ld seconds\n",
+-			journal->j_commit_interval / HZ);
++	printk(KERN_INFO "kjournald2 starting: pid %d, dev %s, "
++	       "commit interval %ld seconds\n", current->pid,
++	       journal->j_devname, journal->j_commit_interval / HZ);
+ 
+ 	/*
+ 	 * And now, wait forever for commit wakeup events.

commit ba80b1019aa722b24506db1ee755e0bb2f513022
+Author: Theodore Ts'o 
+Date:   Sat Jan 3 20:03:21 2009 -0500
+
+    ext4: Add markers for better debuggability
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index e3aa3fa38608..369c34c64292 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -210,6 +210,11 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
+ 
+ 	ino = inode->i_ino;
+ 	ext4_debug("freeing inode %lu\n", ino);
++	trace_mark(ext4_free_inode,
++		   "dev %s ino %lu mode %d uid %lu gid %lu bocks %llu",
++		   sb->s_id, inode->i_ino, inode->i_mode,
++		   (unsigned long) inode->i_uid, (unsigned long) inode->i_gid,
++		   (unsigned long long) inode->i_blocks);
+ 
+ 	/*
+ 	 * Note: we must free any quota before locking the superblock,
+@@ -698,6 +703,8 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
+ 		return ERR_PTR(-EPERM);
+ 
+ 	sb = dir->i_sb;
++	trace_mark(ext4_request_inode, "dev %s dir %lu mode %d", sb->s_id,
++		   dir->i_ino, mode);
+ 	inode = new_inode(sb);
+ 	if (!inode)
+ 		return ERR_PTR(-ENOMEM);
+@@ -925,6 +932,8 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
+ 	}
+ 
+ 	ext4_debug("allocating inode %lu\n", inode->i_ino);
++	trace_mark(ext4_allocate_inode, "dev %s ino %lu dir %lu mode %d",
++		   sb->s_id, inode->i_ino, dir->i_ino, mode);
+ 	goto really_out;
+ fail:
+ 	ext4_std_error(sb, err);
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 56142accf5cd..4cac8da4e0c1 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1351,6 +1351,10 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
+  	pgoff_t index;
+ 	unsigned from, to;
+ 
++	trace_mark(ext4_write_begin,
++		   "dev %s ino %lu pos %llu len %u flags %u",
++		   inode->i_sb->s_id, inode->i_ino,
++		   (unsigned long long) pos, len, flags);
+  	index = pos >> PAGE_CACHE_SHIFT;
+ 	from = pos & (PAGE_CACHE_SIZE - 1);
+ 	to = from + len;
+@@ -1422,6 +1426,10 @@ static int ext4_ordered_write_end(struct file *file,
+ 	struct inode *inode = mapping->host;
+ 	int ret = 0, ret2;
+ 
++	trace_mark(ext4_ordered_write_end,
++		   "dev %s ino %lu pos %llu len %u copied %u",
++		   inode->i_sb->s_id, inode->i_ino,
++		   (unsigned long long) pos, len, copied);
+ 	ret = ext4_jbd2_file_inode(handle, inode);
+ 
+ 	if (ret == 0) {
+@@ -1460,6 +1468,10 @@ static int ext4_writeback_write_end(struct file *file,
+ 	int ret = 0, ret2;
+ 	loff_t new_i_size;
+ 
++	trace_mark(ext4_writeback_write_end,
++		   "dev %s ino %lu pos %llu len %u copied %u",
++		   inode->i_sb->s_id, inode->i_ino,
++		   (unsigned long long) pos, len, copied);
+ 	new_i_size = pos + copied;
+ 	if (new_i_size > EXT4_I(inode)->i_disksize) {
+ 		ext4_update_i_disksize(inode, new_i_size);
+@@ -1495,6 +1507,10 @@ static int ext4_journalled_write_end(struct file *file,
+ 	unsigned from, to;
+ 	loff_t new_i_size;
+ 
++	trace_mark(ext4_journalled_write_end,
++		   "dev %s ino %lu pos %llu len %u copied %u",
++		   inode->i_sb->s_id, inode->i_ino,
++		   (unsigned long long) pos, len, copied);
+ 	from = pos & (PAGE_CACHE_SIZE - 1);
+ 	to = from + len;
+ 
+@@ -2311,6 +2327,9 @@ static int ext4_da_writepage(struct page *page,
+ 	struct buffer_head *page_bufs;
+ 	struct inode *inode = page->mapping->host;
+ 
++	trace_mark(ext4_da_writepage,
++		   "dev %s ino %lu page_index %lu",
++		   inode->i_sb->s_id, inode->i_ino, page->index);
+ 	size = i_size_read(inode);
+ 	if (page->index == size >> PAGE_CACHE_SHIFT)
+ 		len = size & ~PAGE_CACHE_MASK;
+@@ -2421,6 +2440,20 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 	int needed_blocks, ret = 0, nr_to_writebump = 0;
+ 	struct ext4_sb_info *sbi = EXT4_SB(mapping->host->i_sb);
+ 
++	trace_mark(ext4_da_writepages,
++		   "dev %s ino %lu nr_t_write %ld "
++		   "pages_skipped %ld range_start %llu "
++		   "range_end %llu nonblocking %d "
++		   "for_kupdate %d for_reclaim %d "
++		   "for_writepages %d range_cyclic %d",
++		   inode->i_sb->s_id, inode->i_ino,
++		   wbc->nr_to_write, wbc->pages_skipped,
++		   (unsigned long long) wbc->range_start,
++		   (unsigned long long) wbc->range_end,
++		   wbc->nonblocking, wbc->for_kupdate,
++		   wbc->for_reclaim, wbc->for_writepages,
++		   wbc->range_cyclic);
++
+ 	/*
+ 	 * No pages to write? This is mainly a kludge to avoid starting
+ 	 * a transaction for special inodes like journal inode on last iput()
+@@ -2539,6 +2572,14 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 	if (!no_nrwrite_index_update)
+ 		wbc->no_nrwrite_index_update = 0;
+ 	wbc->nr_to_write -= nr_to_writebump;
++	trace_mark(ext4_da_writepage_result,
++		   "dev %s ino %lu ret %d pages_written %d "
++		   "pages_skipped %ld congestion %d "
++		   "more_io %d no_nrwrite_index_update %d",
++		   inode->i_sb->s_id, inode->i_ino, ret,
++		   pages_written, wbc->pages_skipped,
++		   wbc->encountered_congestion, wbc->more_io,
++		   wbc->no_nrwrite_index_update);
+ 	return ret;
+ }
+ 
+@@ -2590,6 +2631,11 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
+ 					len, flags, pagep, fsdata);
+ 	}
+ 	*fsdata = (void *)0;
++
++	trace_mark(ext4_da_write_begin,
++		   "dev %s ino %lu pos %llu len %u flags %u",
++		   inode->i_sb->s_id, inode->i_ino,
++		   (unsigned long long) pos, len, flags);
+ retry:
+ 	/*
+ 	 * With delayed allocation, we don't log the i_disksize update
+@@ -2679,6 +2725,10 @@ static int ext4_da_write_end(struct file *file,
+ 		}
+ 	}
+ 
++	trace_mark(ext4_da_write_end,
++		   "dev %s ino %lu pos %llu len %u copied %u",
++		   inode->i_sb->s_id, inode->i_ino,
++		   (unsigned long long) pos, len, copied);
+ 	start = pos & (PAGE_CACHE_SIZE - 1);
+ 	end = start + copied - 1;
+ 
+@@ -2892,6 +2942,9 @@ static int ext4_normal_writepage(struct page *page,
+ 	loff_t size = i_size_read(inode);
+ 	loff_t len;
+ 
++	trace_mark(ext4_normal_writepage,
++		   "dev %s ino %lu page_index %lu",
++		   inode->i_sb->s_id, inode->i_ino, page->index);
+ 	J_ASSERT(PageLocked(page));
+ 	if (page->index == size >> PAGE_CACHE_SHIFT)
+ 		len = size & ~PAGE_CACHE_MASK;
+@@ -2977,6 +3030,9 @@ static int ext4_journalled_writepage(struct page *page,
+ 	loff_t size = i_size_read(inode);
+ 	loff_t len;
+ 
++	trace_mark(ext4_journalled_writepage,
++		   "dev %s ino %lu page_index %lu",
++		   inode->i_sb->s_id, inode->i_ino, page->index);
+ 	J_ASSERT(PageLocked(page));
+ 	if (page->index == size >> PAGE_CACHE_SHIFT)
+ 		len = size & ~PAGE_CACHE_MASK;
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 05d9f81956c6..918aec0c8a11 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2878,8 +2878,9 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn)
+ 		discard_block = (ext4_fsblk_t) entry->group * EXT4_BLOCKS_PER_GROUP(sb)
+ 			+ entry->start_blk
+ 			+ le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
+-		trace_mark(ext4_discard_blocks, "dev %s blk %llu count %u", sb->s_id,
+-			   (unsigned long long) discard_block, entry->count);
++		trace_mark(ext4_discard_blocks, "dev %s blk %llu count %u",
++			   sb->s_id, (unsigned long long) discard_block,
++			   entry->count);
+ 		sb_issue_discard(sb, discard_block, entry->count);
+ 
+ 		kmem_cache_free(ext4_free_ext_cachep, entry);
+@@ -3697,6 +3698,10 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
+ 
+ 	mb_debug("new inode pa %p: %llu/%u for %u\n", pa,
+ 			pa->pa_pstart, pa->pa_len, pa->pa_lstart);
++	trace_mark(ext4_mb_new_inode_pa,
++		   "dev %s ino %lu pstart %llu len %u lstart %u",
++		   sb->s_id, ac->ac_inode->i_ino,
++		   pa->pa_pstart, pa->pa_len, pa->pa_lstart);
+ 
+ 	ext4_mb_use_inode_pa(ac, pa);
+ 	atomic_add(pa->pa_free, &EXT4_SB(sb)->s_mb_preallocated);
+@@ -3754,7 +3759,9 @@ ext4_mb_new_group_pa(struct ext4_allocation_context *ac)
+ 	pa->pa_linear = 1;
+ 
+ 	mb_debug("new group pa %p: %llu/%u for %u\n", pa,
+-			pa->pa_pstart, pa->pa_len, pa->pa_lstart);
++		 pa->pa_pstart, pa->pa_len, pa->pa_lstart);
++	trace_mark(ext4_mb_new_group_pa, "dev %s pstart %llu len %u lstart %u",
++		   sb->s_id, pa->pa_pstart, pa->pa_len, pa->pa_lstart);
+ 
+ 	ext4_mb_use_group_pa(ac, pa);
+ 	atomic_add(pa->pa_free, &EXT4_SB(sb)->s_mb_preallocated);
+@@ -3807,12 +3814,14 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh,
+ 	unsigned int next;
+ 	ext4_group_t group;
+ 	ext4_grpblk_t bit;
++	unsigned long long grp_blk_start;
+ 	sector_t start;
+ 	int err = 0;
+ 	int free = 0;
+ 
+ 	BUG_ON(pa->pa_deleted == 0);
+ 	ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit);
++	grp_blk_start = pa->pa_pstart - bit;
+ 	BUG_ON(group != e4b->bd_group && pa->pa_len != 0);
+ 	end = bit + pa->pa_len;
+ 
+@@ -3842,6 +3851,10 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh,
+ 			ext4_mb_store_history(ac);
+ 		}
+ 
++		trace_mark(ext4_mb_release_inode_pa,
++			   "dev %s ino %lu block %llu count %u",
++			   sb->s_id, pa->pa_inode->i_ino, grp_blk_start + bit,
++			   next - bit);
+ 		mb_free_blocks(pa->pa_inode, e4b, bit, next - bit);
+ 		bit = next + 1;
+ 	}
+@@ -3875,6 +3888,8 @@ ext4_mb_release_group_pa(struct ext4_buddy *e4b,
+ 	if (ac)
+ 		ac->ac_op = EXT4_MB_HISTORY_DISCARD;
+ 
++	trace_mark(ext4_mb_release_group_pa, "dev %s pstart %llu len %d",
++		   sb->s_id, pa->pa_pstart, pa->pa_len);
+ 	BUG_ON(pa->pa_deleted == 0);
+ 	ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit);
+ 	BUG_ON(group != e4b->bd_group && pa->pa_len != 0);
+@@ -4040,6 +4055,8 @@ void ext4_discard_preallocations(struct inode *inode)
+ 	}
+ 
+ 	mb_debug("discard preallocation for inode %lu\n", inode->i_ino);
++	trace_mark(ext4_discard_preallocations, "dev %s ino %lu", sb->s_id,
++		   inode->i_ino);
+ 
+ 	INIT_LIST_HEAD(&list);
+ 
+@@ -4492,6 +4509,8 @@ static int ext4_mb_discard_preallocations(struct super_block *sb, int needed)
+ 	int ret;
+ 	int freed = 0;
+ 
++	trace_mark(ext4_mb_discard_preallocations, "dev %s needed %d",
++		   sb->s_id, needed);
+ 	for (i = 0; i < EXT4_SB(sb)->s_groups_count && needed > 0; i++) {
+ 		ret = ext4_mb_discard_group_preallocations(sb, i, needed);
+ 		freed += ret;
+@@ -4520,6 +4539,18 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
+ 	sb = ar->inode->i_sb;
+ 	sbi = EXT4_SB(sb);
+ 
++	trace_mark(ext4_request_blocks, "dev %s flags %u len %u ino %lu "
++		   "lblk %llu goal %llu lleft %llu lright %llu "
++		   "pleft %llu pright %llu ",
++		   sb->s_id, ar->flags, ar->len,
++		   ar->inode ? ar->inode->i_ino : 0,
++		   (unsigned long long) ar->logical,
++		   (unsigned long long) ar->goal,
++		   (unsigned long long) ar->lleft,
++		   (unsigned long long) ar->lright,
++		   (unsigned long long) ar->pleft,
++		   (unsigned long long) ar->pright);
++
+ 	if (!EXT4_I(ar->inode)->i_delalloc_reserved_flag) {
+ 		/*
+ 		 * With delalloc we already reserved the blocks
+@@ -4622,6 +4653,19 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
+ 						reserv_blks);
+ 	}
+ 
++	trace_mark(ext4_allocate_blocks,
++		   "dev %s block %llu flags %u len %u ino %lu "
++		   "logical %llu goal %llu lleft %llu lright %llu "
++		   "pleft %llu pright %llu ",
++		   sb->s_id, (unsigned long long) block,
++		   ar->flags, ar->len, ar->inode ? ar->inode->i_ino : 0,
++		   (unsigned long long) ar->logical,
++		   (unsigned long long) ar->goal,
++		   (unsigned long long) ar->lleft,
++		   (unsigned long long) ar->lright,
++		   (unsigned long long) ar->pleft,
++		   (unsigned long long) ar->pright);
++
+ 	return block;
+ }
+ 
+@@ -4755,6 +4799,10 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
+ 	}
+ 
+ 	ext4_debug("freeing block %lu\n", block);
++	trace_mark(ext4_free_blocks,
++		   "dev %s block %llu count %lu metadata %d ino %lu",
++		   sb->s_id, (unsigned long long) block, count, metadata,
++		   inode ? inode->i_ino : 0);
+ 
+ 	ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
+ 	if (ac) {

commit c31910672376dfb8d020e32afa7249763bcd924a
+Author: Theodore Ts'o 
+Date:   Tue Jan 6 11:14:25 2009 -0500
+
+    ext4: Remove code to create the journal inode
+    
+    This code has been obsolete in quite some time, since the supported
+    method for adding a journal inode is to use tune2fs (or to creating
+    new filesystem with a journal via mke2fs or mkfs.ext4).
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
+index e3fcbea3ec8c..9ec29d86ff8b 100644
+--- a/Documentation/filesystems/ext4.txt
++++ b/Documentation/filesystems/ext4.txt
+@@ -149,10 +149,6 @@ journal_async_commit	Commit block can be written to disk without waiting
+ journal=update		Update the ext4 file system's journal to the current
+ 			format.
+ 
+-journal=inum		When a journal already exists, this option is ignored.
+-			Otherwise, it specifies the number of the inode which
+-			will represent the ext4 file system's journal file.
+-
+ journal_dev=devnum	When the external journal device's major/minor numbers
+ 			have changed, this option allows the user to specify
+ 			the new journal location.  The journal device is
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index e5ab520724da..8036392b2121 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -51,8 +51,6 @@ struct proc_dir_entry *ext4_proc_root;
+ 
+ static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
+ 			     unsigned long journal_devnum);
+-static int ext4_create_journal(struct super_block *, struct ext4_super_block *,
+-			       unsigned int);
+ static void ext4_commit_super(struct super_block *sb,
+ 			      struct ext4_super_block *es, int sync);
+ static void ext4_mark_recovery_complete(struct super_block *sb,
+@@ -1006,7 +1004,7 @@ enum {
+ 	Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
+ 	Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh,
+ 	Opt_commit, Opt_min_batch_time, Opt_max_batch_time,
+-	Opt_journal_update, Opt_journal_inum, Opt_journal_dev,
++	Opt_journal_update, Opt_journal_dev,
+ 	Opt_journal_checksum, Opt_journal_async_commit,
+ 	Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
+ 	Opt_data_err_abort, Opt_data_err_ignore,
+@@ -1048,7 +1046,6 @@ static const match_table_t tokens = {
+ 	{Opt_min_batch_time, "min_batch_time=%u"},
+ 	{Opt_max_batch_time, "max_batch_time=%u"},
+ 	{Opt_journal_update, "journal=update"},
+-	{Opt_journal_inum, "journal=%u"},
+ 	{Opt_journal_dev, "journal_dev=%u"},
+ 	{Opt_journal_checksum, "journal_checksum"},
+ 	{Opt_journal_async_commit, "journal_async_commit"},
+@@ -1102,7 +1099,7 @@ static ext4_fsblk_t get_sb_block(void **data)
+ }
+ 
+ static int parse_options(char *options, struct super_block *sb,
+-			 unsigned int *inum, unsigned long *journal_devnum,
++			 unsigned long *journal_devnum,
+ 			 ext4_fsblk_t *n_blocks_count, int is_remount)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+@@ -1226,16 +1223,6 @@ static int parse_options(char *options, struct super_block *sb,
+ 			}
+ 			set_opt(sbi->s_mount_opt, UPDATE_JOURNAL);
+ 			break;
+-		case Opt_journal_inum:
+-			if (is_remount) {
+-				printk(KERN_ERR "EXT4-fs: cannot specify "
+-				       "journal on remount\n");
+-				return 0;
+-			}
+-			if (match_int(&args[0], &option))
+-				return 0;
+-			*inum = option;
+-			break;
+ 		case Opt_journal_dev:
+ 			if (is_remount) {
+ 				printk(KERN_ERR "EXT4-fs: cannot specify "
+@@ -2035,7 +2022,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	ext4_fsblk_t sb_block = get_sb_block(&data);
+ 	ext4_fsblk_t logical_sb_block;
+ 	unsigned long offset = 0;
+-	unsigned int journal_inum = 0;
+ 	unsigned long journal_devnum = 0;
+ 	unsigned long def_mount_opts;
+ 	struct inode *root;
+@@ -2155,8 +2141,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	set_opt(sbi->s_mount_opt, DELALLOC);
+ 
+ 
+-	if (!parse_options((char *) data, sb, &journal_inum, &journal_devnum,
+-			   NULL, 0))
++	if (!parse_options((char *) data, sb, &journal_devnum, NULL, 0))
+ 		goto failed_mount;
+ 
+ 	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
+@@ -2460,9 +2445,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 				goto failed_mount4;
+ 			}
+ 		}
+-	} else if (journal_inum) {
+-		if (ext4_create_journal(sb, es, journal_inum))
+-			goto failed_mount3;
+ 	} else if (test_opt(sb, NOLOAD) && !(sb->s_flags & MS_RDONLY) &&
+ 	      EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)) {
+ 		printk(KERN_ERR "EXT4-fs: required journal recovery "
+@@ -2926,48 +2908,6 @@ static int ext4_load_journal(struct super_block *sb,
+ 	return 0;
+ }
+ 
+-static int ext4_create_journal(struct super_block *sb,
+-			       struct ext4_super_block *es,
+-			       unsigned int journal_inum)
+-{
+-	journal_t *journal;
+-	int err;
+-
+-	if (sb->s_flags & MS_RDONLY) {
+-		printk(KERN_ERR "EXT4-fs: readonly filesystem when trying to "
+-				"create journal.\n");
+-		return -EROFS;
+-	}
+-
+-	journal = ext4_get_journal(sb, journal_inum);
+-	if (!journal)
+-		return -EINVAL;
+-
+-	printk(KERN_INFO "EXT4-fs: creating new journal on inode %u\n",
+-	       journal_inum);
+-
+-	err = jbd2_journal_create(journal);
+-	if (err) {
+-		printk(KERN_ERR "EXT4-fs: error creating journal.\n");
+-		jbd2_journal_destroy(journal);
+-		return -EIO;
+-	}
+-
+-	EXT4_SB(sb)->s_journal = journal;
+-
+-	ext4_update_dynamic_rev(sb);
+-	EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+-	EXT4_SET_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL);
+-
+-	es->s_journal_inum = cpu_to_le32(journal_inum);
+-	sb->s_dirt = 1;
+-
+-	/* Make sure we flush the recovery flag to disk. */
+-	ext4_commit_super(sb, es, 1);
+-
+-	return 0;
+-}
+-
+ static void ext4_commit_super(struct super_block *sb,
+ 			      struct ext4_super_block *es, int sync)
+ {
+@@ -3209,7 +3149,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 	/*
+ 	 * Allow the "check" option to be passed as a remount option.
+ 	 */
+-	if (!parse_options(data, sb, NULL, NULL, &n_blocks_count, 1)) {
++	if (!parse_options(data, sb, NULL, &n_blocks_count, 1)) {
+ 		err = -EINVAL;
+ 		goto restore_opts;
+ 	}
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 34ef98057202..b10d7283ba5b 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -66,7 +66,6 @@ EXPORT_SYMBOL(jbd2_journal_update_format);
+ EXPORT_SYMBOL(jbd2_journal_check_used_features);
+ EXPORT_SYMBOL(jbd2_journal_check_available_features);
+ EXPORT_SYMBOL(jbd2_journal_set_features);
+-EXPORT_SYMBOL(jbd2_journal_create);
+ EXPORT_SYMBOL(jbd2_journal_load);
+ EXPORT_SYMBOL(jbd2_journal_destroy);
+ EXPORT_SYMBOL(jbd2_journal_abort);
+@@ -1162,77 +1161,6 @@ static int journal_reset(journal_t *journal)
+ 	return jbd2_journal_start_thread(journal);
+ }
+ 
+-/**
+- * int jbd2_journal_create() - Initialise the new journal file
+- * @journal: Journal to create. This structure must have been initialised
+- *
+- * Given a journal_t structure which tells us which disk blocks we can
+- * use, create a new journal superblock and initialise all of the
+- * journal fields from scratch.
+- **/
+-int jbd2_journal_create(journal_t *journal)
+-{
+-	unsigned long long blocknr;
+-	struct buffer_head *bh;
+-	journal_superblock_t *sb;
+-	int i, err;
+-
+-	if (journal->j_maxlen < JBD2_MIN_JOURNAL_BLOCKS) {
+-		printk (KERN_ERR "Journal length (%d blocks) too short.\n",
+-			journal->j_maxlen);
+-		journal_fail_superblock(journal);
+-		return -EINVAL;
+-	}
+-
+-	if (journal->j_inode == NULL) {
+-		/*
+-		 * We don't know what block to start at!
+-		 */
+-		printk(KERN_EMERG
+-		       "%s: creation of journal on external device!\n",
+-		       __func__);
+-		BUG();
+-	}
+-
+-	/* Zero out the entire journal on disk.  We cannot afford to
+-	   have any blocks on disk beginning with JBD2_MAGIC_NUMBER. */
+-	jbd_debug(1, "JBD: Zeroing out journal blocks...\n");
+-	for (i = 0; i < journal->j_maxlen; i++) {
+-		err = jbd2_journal_bmap(journal, i, &blocknr);
+-		if (err)
+-			return err;
+-		bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
+-		lock_buffer(bh);
+-		memset (bh->b_data, 0, journal->j_blocksize);
+-		BUFFER_TRACE(bh, "marking dirty");
+-		mark_buffer_dirty(bh);
+-		BUFFER_TRACE(bh, "marking uptodate");
+-		set_buffer_uptodate(bh);
+-		unlock_buffer(bh);
+-		__brelse(bh);
+-	}
+-
+-	sync_blockdev(journal->j_dev);
+-	jbd_debug(1, "JBD: journal cleared.\n");
+-
+-	/* OK, fill in the initial static fields in the new superblock */
+-	sb = journal->j_superblock;
+-
+-	sb->s_header.h_magic	 = cpu_to_be32(JBD2_MAGIC_NUMBER);
+-	sb->s_header.h_blocktype = cpu_to_be32(JBD2_SUPERBLOCK_V2);
+-
+-	sb->s_blocksize	= cpu_to_be32(journal->j_blocksize);
+-	sb->s_maxlen	= cpu_to_be32(journal->j_maxlen);
+-	sb->s_first	= cpu_to_be32(1);
+-
+-	journal->j_transaction_sequence = 1;
+-
+-	journal->j_flags &= ~JBD2_ABORT;
+-	journal->j_format_version = 2;
+-
+-	return journal_reset(journal);
+-}
+-
+ /**
+  * void jbd2_journal_update_superblock() - Update journal sb on disk.
+  * @journal: The journal to update.
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index 9d82084a1605..adef1c9940d3 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -1104,7 +1104,6 @@ extern int	   jbd2_journal_set_features
+ 		   (journal_t *, unsigned long, unsigned long, unsigned long);
+ extern void	   jbd2_journal_clear_features
+ 		   (journal_t *, unsigned long, unsigned long, unsigned long);
+-extern int	   jbd2_journal_create     (journal_t *);
+ extern int	   jbd2_journal_load       (journal_t *journal);
+ extern int	   jbd2_journal_destroy    (journal_t *);
+ extern int	   jbd2_journal_recover    (journal_t *journal);

commit 87d8fe1ee6b8d2f95076142d58c440dba4e7bdc2
+Author: Theodore Ts'o 
+Date:   Sat Jan 3 09:47:09 2009 -0500
+
+    add releasepage hooks to block devices which can be used by file systems
+    
+    Implement blkdev_releasepage() to release the buffer_heads and pages
+    after we release private data belonging to a mounted filesystem.
+    
+    Cc: Toshiyuki Okajima 
+    Cc: linux-fsdevel@vger.kernel.org
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/block_dev.c b/fs/block_dev.c
+index 349a26c10001..1dd07e66e98a 100644
+--- a/fs/block_dev.c
++++ b/fs/block_dev.c
+@@ -1220,6 +1220,20 @@ static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg)
+ 	return blkdev_ioctl(bdev, mode, cmd, arg);
+ }
+ 
++/*
++ * Try to release a page associated with block device when the system
++ * is under memory pressure.
++ */
++static int blkdev_releasepage(struct page *page, gfp_t wait)
++{
++	struct super_block *super = BDEV_I(page->mapping->host)->bdev.bd_super;
++
++	if (super && super->s_op->bdev_try_to_free_page)
++		return super->s_op->bdev_try_to_free_page(super, page, wait);
++
++	return try_to_free_buffers(page);
++}
++
+ static const struct address_space_operations def_blk_aops = {
+ 	.readpage	= blkdev_readpage,
+ 	.writepage	= blkdev_writepage,
+@@ -1227,6 +1241,7 @@ static const struct address_space_operations def_blk_aops = {
+ 	.write_begin	= blkdev_write_begin,
+ 	.write_end	= blkdev_write_end,
+ 	.writepages	= generic_writepages,
++	.releasepage	= blkdev_releasepage,
+ 	.direct_IO	= blkdev_direct_IO,
+ };
+ 
+diff --git a/fs/super.c b/fs/super.c
+index ddba069d7a99..d5fd4498548a 100644
+--- a/fs/super.c
++++ b/fs/super.c
+@@ -800,6 +800,7 @@ int get_sb_bdev(struct file_system_type *fs_type,
+ 		}
+ 
+ 		s->s_flags |= MS_ACTIVE;
++		bdev->bd_super = s;
+ 	}
+ 
+ 	return simple_set_mnt(mnt, s);
+@@ -819,6 +820,7 @@ void kill_block_super(struct super_block *sb)
+ 	struct block_device *bdev = sb->s_bdev;
+ 	fmode_t mode = sb->s_mode;
+ 
++	bdev->bd_super = 0;
+ 	generic_shutdown_super(sb);
+ 	sync_blockdev(bdev);
+ 	close_bdev_exclusive(bdev, mode);
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index f2a3010140e3..0f54ae0f0ccd 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -565,6 +565,7 @@ struct address_space {
+ struct block_device {
+ 	dev_t			bd_dev;  /* not a kdev_t - it's a search key */
+ 	struct inode *		bd_inode;	/* will die */
++	struct super_block *	bd_super;
+ 	int			bd_openers;
+ 	struct mutex		bd_mutex;	/* open/close mutex */
+ 	struct semaphore	bd_mount_sem;
+@@ -1385,6 +1386,7 @@ struct super_operations {
+ 	ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
+ 	ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
+ #endif
++	int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
+ };
+ 
+ /*

commit 6cdfcc275e40b89fb020da1088ead86a61d33115
+Author: Theodore Tso 
+Date:   Wed Nov 12 13:27:01 2008 -0800
+
+    ext3: Clean up outdated and incorrect comment for ext3_write_super()
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/ext3/super.c b/fs/ext3/super.c
+index 5dec6d1356c4..f6c94f232ec1 100644
+--- a/fs/ext3/super.c
++++ b/fs/ext3/super.c
+@@ -2375,12 +2375,9 @@ int ext3_force_commit(struct super_block *sb)
+ /*
+  * Ext3 always journals updates to the superblock itself, so we don't
+  * have to propagate any other updates to the superblock on disk at this
+- * point.  Just start an async writeback to get the buffers on their way
+- * to the disk.
+- *
+- * This implicitly triggers the writebehind on sync().
++ * point.  (We can probably nuke this function altogether, and remove
++ * any mention to sb->s_dirt in all of fs/ext3; eventual cleanup...)
+  */
+-
+ static void ext3_write_super (struct super_block * sb)
+ {
+ 	if (mutex_trylock(&sb->s_lock) != 0)

commit ac51d83705c2a38c71f39cde99708b14e6212a60
+Author: Theodore Ts'o 
+Date:   Thu Nov 6 16:49:36 2008 -0500
+
+    ext4: calculate journal credits correctly
+    
+    This fixes a 2.6.27 regression which was introduced in commit a02908f1.
+    
+    We weren't passing the chunk parameter down to the two subections,
+    ext4_indirect_trans_blocks() and ext4_ext_index_trans_blocks(), with
+    the result that massively overestimate the amount of credits needed by
+    ext4_da_writepages, especially in the non-extents case.  This causes
+    failures especially on /boot partitions, which tend to be small and
+    non-extent using since GRUB doesn't handle extents.
+    
+    This patch fixes the bug reported by Joseph Fannin at:
+    http://bugzilla.kernel.org/show_bug.cgi?id=11964
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 8dbf6953845b..5a130b56f1cf 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4580,9 +4580,10 @@ static int ext4_indirect_trans_blocks(struct inode *inode, int nrblocks,
+ static int ext4_index_trans_blocks(struct inode *inode, int nrblocks, int chunk)
+ {
+ 	if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL))
+-		return ext4_indirect_trans_blocks(inode, nrblocks, 0);
+-	return ext4_ext_index_trans_blocks(inode, nrblocks, 0);
++		return ext4_indirect_trans_blocks(inode, nrblocks, chunk);
++	return ext4_ext_index_trans_blocks(inode, nrblocks, chunk);
+ }
++
+ /*
+  * Account for index blocks, block groups bitmaps and block group
+  * descriptor blocks if modify datablocks and index blocks

commit 1a0d3786dd57dbd74f340322054c3d618b999dcf
+Author: Theodore Ts'o 
+Date:   Wed Nov 5 00:09:22 2008 -0500
+
+    jbd2: Remove a large array of bh's from the stack of the checkpoint routine
+    
+    jbd2_log_do_checkpoint()n is one of the kernel's largest stack users.
+    Move the array of buffer head's from the stack of jbd2_log_do_checkpoint()
+    to the in-core journal structure.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
+index 9497718fe920..adc08ec875ed 100644
+--- a/fs/jbd2/checkpoint.c
++++ b/fs/jbd2/checkpoint.c
+@@ -249,16 +249,14 @@ static int __wait_cp_io(journal_t *journal, transaction_t *transaction)
+ 	return ret;
+ }
+ 
+-#define NR_BATCH	64
+-
+ static void
+-__flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count)
++__flush_batch(journal_t *journal, int *batch_count)
+ {
+ 	int i;
+ 
+-	ll_rw_block(SWRITE, *batch_count, bhs);
++	ll_rw_block(SWRITE, *batch_count, journal->j_chkpt_bhs);
+ 	for (i = 0; i < *batch_count; i++) {
+-		struct buffer_head *bh = bhs[i];
++		struct buffer_head *bh = journal->j_chkpt_bhs[i];
+ 		clear_buffer_jwrite(bh);
+ 		BUFFER_TRACE(bh, "brelse");
+ 		__brelse(bh);
+@@ -277,8 +275,7 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count)
+  * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it
+  */
+ static int __process_buffer(journal_t *journal, struct journal_head *jh,
+-			struct buffer_head **bhs, int *batch_count,
+-			transaction_t *transaction)
++			    int *batch_count, transaction_t *transaction)
+ {
+ 	struct buffer_head *bh = jh2bh(jh);
+ 	int ret = 0;
+@@ -325,14 +322,14 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
+ 		get_bh(bh);
+ 		J_ASSERT_BH(bh, !buffer_jwrite(bh));
+ 		set_buffer_jwrite(bh);
+-		bhs[*batch_count] = bh;
++		journal->j_chkpt_bhs[*batch_count] = bh;
+ 		__buffer_relink_io(jh);
+ 		jbd_unlock_bh_state(bh);
+ 		transaction->t_chp_stats.cs_written++;
+ 		(*batch_count)++;
+-		if (*batch_count == NR_BATCH) {
++		if (*batch_count == JBD2_NR_BATCH) {
+ 			spin_unlock(&journal->j_list_lock);
+-			__flush_batch(journal, bhs, batch_count);
++			__flush_batch(journal, batch_count);
+ 			ret = 1;
+ 		}
+ 	}
+@@ -388,7 +385,6 @@ int jbd2_log_do_checkpoint(journal_t *journal)
+ 	if (journal->j_checkpoint_transactions == transaction &&
+ 			transaction->t_tid == this_tid) {
+ 		int batch_count = 0;
+-		struct buffer_head *bhs[NR_BATCH];
+ 		struct journal_head *jh;
+ 		int retry = 0, err;
+ 
+@@ -402,7 +398,7 @@ int jbd2_log_do_checkpoint(journal_t *journal)
+ 				retry = 1;
+ 				break;
+ 			}
+-			retry = __process_buffer(journal, jh, bhs, &batch_count,
++			retry = __process_buffer(journal, jh, &batch_count,
+ 						 transaction);
+ 			if (retry < 0 && !result)
+ 				result = retry;
+@@ -419,7 +415,7 @@ int jbd2_log_do_checkpoint(journal_t *journal)
+ 				spin_unlock(&journal->j_list_lock);
+ 				retry = 1;
+ 			}
+-			__flush_batch(journal, bhs, &batch_count);
++			__flush_batch(journal, &batch_count);
+ 		}
+ 
+ 		if (retry) {
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index fd1d7557a098..34ef98057202 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -1477,7 +1477,9 @@ int jbd2_journal_destroy(journal_t *journal)
+ 	spin_lock(&journal->j_list_lock);
+ 	while (journal->j_checkpoint_transactions != NULL) {
+ 		spin_unlock(&journal->j_list_lock);
++		mutex_lock(&journal->j_checkpoint_mutex);
+ 		jbd2_log_do_checkpoint(journal);
++		mutex_unlock(&journal->j_checkpoint_mutex);
+ 		spin_lock(&journal->j_list_lock);
+ 	}
+ 
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index a3cd647ea1bc..004c9a8d63ed 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -687,6 +687,8 @@ jbd2_time_diff(unsigned long start, unsigned long end)
+ 	return end + (MAX_JIFFY_OFFSET - start);
+ }
+ 
++#define JBD2_NR_BATCH	64
++
+ /**
+  * struct journal_s - The journal_s type is the concrete type associated with
+  *     journal_t.
+@@ -830,6 +832,14 @@ struct journal_s
+ 	/* Semaphore for locking against concurrent checkpoints */
+ 	struct mutex		j_checkpoint_mutex;
+ 
++	/*
++	 * List of buffer heads used by the checkpoint routine.  This
++	 * was moved from jbd2_log_do_checkpoint() to reduce stack
++	 * usage.  Access to this array is controlled by the
++	 * j_checkpoint_mutex.  [j_checkpoint_mutex]
++	 */
++	struct buffer_head	*j_chkpt_bhs[JBD2_NR_BATCH];
++	
+ 	/*
+ 	 * Journal head: identifies the first unused block in the journal.
+ 	 * [j_state_lock]

commit 498e5f24158da7bf8fa48074a70e370e22844492
+Author: Theodore Ts'o 
+Date:   Wed Nov 5 00:14:04 2008 -0500
+
+    ext4: Change unsigned long to unsigned int
+    
+    Convert the unsigned longs that are most responsible for bloating the
+    stack usage on 64-bit systems.
+    
+    Nearly all places in the ext3/4 code which uses "unsigned long" is
+    probably a bug, since on 32-bit systems a ulong a 32-bits, which means
+    we are wasting stack space on 64-bit systems.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index a711898923f0..a0c23b03a264 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -205,8 +205,8 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
+ 					     ext4_group_t block_group,
+ 					     struct buffer_head **bh)
+ {
+-	unsigned long group_desc;
+-	unsigned long offset;
++	unsigned int group_desc;
++	unsigned int offset;
+ 	struct ext4_group_desc *desc;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 
+@@ -225,7 +225,7 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
+ 	if (!sbi->s_group_desc[group_desc]) {
+ 		ext4_error(sb, "ext4_get_group_desc",
+ 			   "Group descriptor not loaded - "
+-			   "block_group = %u, group_desc = %lu, desc = %lu",
++			   "block_group = %u, group_desc = %u, desc = %u",
+ 			   block_group, group_desc, offset);
+ 		return NULL;
+ 	}
+@@ -372,8 +372,8 @@ void ext4_free_blocks_sb(handle_t *handle, struct super_block *sb,
+ 	struct buffer_head *gd_bh;
+ 	ext4_group_t block_group;
+ 	ext4_grpblk_t bit;
+-	unsigned long i;
+-	unsigned long overflow;
++	unsigned int i;
++	unsigned int overflow;
+ 	struct ext4_group_desc *desc;
+ 	struct ext4_super_block *es;
+ 	struct ext4_sb_info *sbi;
+@@ -720,7 +720,7 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
+ #ifdef EXT4FS_DEBUG
+ 	struct ext4_super_block *es;
+ 	ext4_fsblk_t bitmap_count;
+-	unsigned long x;
++	unsigned int x;
+ 	struct buffer_head *bitmap_bh = NULL;
+ 
+ 	es = EXT4_SB(sb)->s_es;
+@@ -740,7 +740,7 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
+ 			continue;
+ 
+ 		x = ext4_count_free(bitmap_bh, sb->s_blocksize);
+-		printk(KERN_DEBUG "group %lu: stored = %d, counted = %lu\n",
++		printk(KERN_DEBUG "group %lu: stored = %d, counted = %u\n",
+ 			i, le16_to_cpu(gdp->bg_free_blocks_count), x);
+ 		bitmap_count += x;
+ 	}
+diff --git a/fs/ext4/bitmap.c b/fs/ext4/bitmap.c
+index 0a7a6663c190..fa3af81ac565 100644
+--- a/fs/ext4/bitmap.c
++++ b/fs/ext4/bitmap.c
+@@ -15,10 +15,9 @@
+ 
+ static const int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
+ 
+-unsigned long ext4_count_free(struct buffer_head *map, unsigned int numchars)
++unsigned int ext4_count_free(struct buffer_head *map, unsigned int numchars)
+ {
+-	unsigned int i;
+-	unsigned long sum = 0;
++	unsigned int i, sum = 0;
+ 
+ 	if (!map)
+ 		return 0;
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index fed5b610df5a..cf3ccf4a94b0 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -64,7 +64,7 @@ static unsigned char get_dtype(struct super_block *sb, int filetype)
+ int ext4_check_dir_entry(const char *function, struct inode *dir,
+ 			 struct ext4_dir_entry_2 *de,
+ 			 struct buffer_head *bh,
+-			 unsigned long offset)
++			 unsigned int offset)
+ {
+ 	const char *error_msg = NULL;
+ 	const int rlen = ext4_rec_len_from_disk(de->rec_len);
+@@ -84,9 +84,9 @@ int ext4_check_dir_entry(const char *function, struct inode *dir,
+ 	if (error_msg != NULL)
+ 		ext4_error(dir->i_sb, function,
+ 			"bad entry in directory #%lu: %s - "
+-			"offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
++			"offset=%u, inode=%u, rec_len=%d, name_len=%d",
+ 			dir->i_ino, error_msg, offset,
+-			(unsigned long) le32_to_cpu(de->inode),
++			le32_to_cpu(de->inode),
+ 			rlen, de->name_len);
+ 	return error_msg == NULL ? 1 : 0;
+ }
+@@ -95,7 +95,7 @@ static int ext4_readdir(struct file *filp,
+ 			 void *dirent, filldir_t filldir)
+ {
+ 	int error = 0;
+-	unsigned long offset;
++	unsigned int offset;
+ 	int i, stored;
+ 	struct ext4_dir_entry_2 *de;
+ 	struct super_block *sb;
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index e9aacecfbf41..558545d1fead 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -94,9 +94,9 @@ struct ext4_allocation_request {
+ 	/* phys. block for ^^^ */
+ 	ext4_fsblk_t pright;
+ 	/* how many blocks we want to allocate */
+-	unsigned long len;
++	unsigned int len;
+ 	/* flags. see above EXT4_MB_HINT_* */
+-	unsigned long flags;
++	unsigned int flags;
+ };
+ 
+ /*
+@@ -997,6 +997,9 @@ do {									\
+ # define ATTRIB_NORET	__attribute__((noreturn))
+ # define NORET_AND	noreturn,
+ 
++/* bitmap.c */
++extern unsigned int ext4_count_free(struct buffer_head *, unsigned);
++
+ /* balloc.c */
+ extern unsigned int ext4_block_group(struct super_block *sb,
+ 			ext4_fsblk_t blocknr);
+@@ -1024,7 +1027,7 @@ extern int ext4_should_retry_alloc(struct super_block *sb, int *retries);
+ /* dir.c */
+ extern int ext4_check_dir_entry(const char *, struct inode *,
+ 				struct ext4_dir_entry_2 *,
+-				struct buffer_head *, unsigned long);
++				struct buffer_head *, unsigned int);
+ extern int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
+ 				    __u32 minor_hash,
+ 				    struct ext4_dir_entry_2 *dirent);
+@@ -1044,7 +1047,6 @@ extern struct inode * ext4_orphan_get(struct super_block *, unsigned long);
+ extern unsigned long ext4_count_free_inodes(struct super_block *);
+ extern unsigned long ext4_count_dirs(struct super_block *);
+ extern void ext4_check_inodes_bitmap(struct super_block *);
+-extern unsigned long ext4_count_free(struct buffer_head *, unsigned);
+ 
+ /* mballoc.c */
+ extern long ext4_mb_stats;
+@@ -1074,10 +1076,6 @@ struct buffer_head *ext4_bread(handle_t *, struct inode *,
+ 						ext4_lblk_t, int, int *);
+ int ext4_get_block(struct inode *inode, sector_t iblock,
+ 				struct buffer_head *bh_result, int create);
+-int ext4_get_blocks_handle(handle_t *handle, struct inode *inode,
+-				ext4_lblk_t iblock, unsigned long maxblocks,
+-				struct buffer_head *bh_result,
+-				int create, int extend_disksize);
+ 
+ extern struct inode *ext4_iget(struct super_block *, unsigned long);
+ extern int  ext4_write_inode(struct inode *, int);
+@@ -1276,16 +1274,16 @@ extern int ext4_ext_writepage_trans_blocks(struct inode *, int);
+ extern int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks,
+ 				       int chunk);
+ extern int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+-			ext4_lblk_t iblock,
+-			unsigned long max_blocks, struct buffer_head *bh_result,
+-			int create, int extend_disksize);
++			       ext4_lblk_t iblock, unsigned int max_blocks,
++			       struct buffer_head *bh_result,
++			       int create, int extend_disksize);
+ extern void ext4_ext_truncate(struct inode *);
+ extern void ext4_ext_init(struct super_block *);
+ extern void ext4_ext_release(struct super_block *);
+ extern long ext4_fallocate(struct inode *inode, int mode, loff_t offset,
+ 			  loff_t len);
+ extern int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode,
+-			sector_t block, unsigned long max_blocks,
++			sector_t block, unsigned int max_blocks,
+ 			struct buffer_head *bh, int create,
+ 			int extend_disksize, int flag);
+ #endif	/* __KERNEL__ */
+diff --git a/fs/ext4/ext4_i.h b/fs/ext4/ext4_i.h
+index 0a9ebe580195..e69acc16f5c4 100644
+--- a/fs/ext4/ext4_i.h
++++ b/fs/ext4/ext4_i.h
+@@ -100,9 +100,6 @@ struct ext4_inode_info {
+ 	 */
+ 	loff_t	i_disksize;
+ 
+-	/* on-disk additional length */
+-	__u16 i_extra_isize;
+-
+ 	/*
+ 	 * i_data_sem is for serialising ext4_truncate() against
+ 	 * ext4_getblock().  In the 2.4 ext2 design, great chunks of inode's
+@@ -129,10 +126,14 @@ struct ext4_inode_info {
+ 	spinlock_t i_prealloc_lock;
+ 
+ 	/* allocation reservation info for delalloc */
+-	unsigned long i_reserved_data_blocks;
+-	unsigned long i_reserved_meta_blocks;
+-	unsigned long i_allocated_meta_blocks;
++	unsigned int i_reserved_data_blocks;
++	unsigned int i_reserved_meta_blocks;
++	unsigned int i_allocated_meta_blocks;
+ 	unsigned short i_delalloc_reserved_flag;
++
++	/* on-disk additional length */
++	__u16 i_extra_isize;
++
+ 	spinlock_t i_block_reservation_lock;
+ };
+ 
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index b9e27bc31559..b92cb60737bd 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -2377,7 +2377,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+ 						struct inode *inode,
+ 						struct ext4_ext_path *path,
+ 						ext4_lblk_t iblock,
+-						unsigned long max_blocks)
++						unsigned int max_blocks)
+ {
+ 	struct ext4_extent *ex, newex, orig_ex;
+ 	struct ext4_extent *ex1 = NULL;
+@@ -2675,26 +2675,26 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
+  */
+ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 			ext4_lblk_t iblock,
+-			unsigned long max_blocks, struct buffer_head *bh_result,
++			unsigned int max_blocks, struct buffer_head *bh_result,
+ 			int create, int extend_disksize)
+ {
+ 	struct ext4_ext_path *path = NULL;
+ 	struct ext4_extent_header *eh;
+ 	struct ext4_extent newex, *ex;
+-	ext4_fsblk_t goal, newblock;
+-	int err = 0, depth, ret;
+-	unsigned long allocated = 0;
++	ext4_fsblk_t newblock;
++	int err = 0, depth, ret, cache_type;
++	unsigned int allocated = 0;
+ 	struct ext4_allocation_request ar;
+ 	loff_t disksize;
+ 
+ 	__clear_bit(BH_New, &bh_result->b_state);
+-	ext_debug("blocks %u/%lu requested for inode %u\n",
++	ext_debug("blocks %u/%u requested for inode %u\n",
+ 			iblock, max_blocks, inode->i_ino);
+ 
+ 	/* check in cache */
+-	goal = ext4_ext_in_cache(inode, iblock, &newex);
+-	if (goal) {
+-		if (goal == EXT4_EXT_CACHE_GAP) {
++	cache_type = ext4_ext_in_cache(inode, iblock, &newex);
++	if (cache_type) {
++		if (cache_type == EXT4_EXT_CACHE_GAP) {
+ 			if (!create) {
+ 				/*
+ 				 * block isn't allocated yet and
+@@ -2703,7 +2703,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 				goto out2;
+ 			}
+ 			/* we should allocate requested block */
+-		} else if (goal == EXT4_EXT_CACHE_EXTENT) {
++		} else if (cache_type == EXT4_EXT_CACHE_EXTENT) {
+ 			/* block is already allocated */
+ 			newblock = iblock
+ 				   - le32_to_cpu(newex.ee_block)
+@@ -2851,7 +2851,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 	if (!newblock)
+ 		goto out2;
+ 	ext_debug("allocate new block: goal %llu, found %llu/%lu\n",
+-			goal, newblock, allocated);
++		  ar.goal, newblock, allocated);
+ 
+ 	/* try to insert new extent into found leaf and return */
+ 	ext4_ext_store_pblock(&newex, newblock);
+@@ -3001,7 +3001,7 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len)
+ 	handle_t *handle;
+ 	ext4_lblk_t block;
+ 	loff_t new_size;
+-	unsigned long max_blocks;
++	unsigned int max_blocks;
+ 	int ret = 0;
+ 	int ret2 = 0;
+ 	int retries = 0;
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 45d0f70a1f04..91e06f88f08c 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -514,10 +514,10 @@ static ext4_fsblk_t ext4_find_goal(struct inode *inode, ext4_lblk_t block,
+  *	return the total number of blocks to be allocate, including the
+  *	direct and indirect blocks.
+  */
+-static int ext4_blks_to_allocate(Indirect *branch, int k, unsigned long blks,
++static int ext4_blks_to_allocate(Indirect *branch, int k, unsigned int blks,
+ 		int blocks_to_boundary)
+ {
+-	unsigned long count = 0;
++	unsigned int count = 0;
+ 
+ 	/*
+ 	 * Simple case, [t,d]Indirect block(s) has not allocated yet
+@@ -856,10 +856,10 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
+  * down_read(&EXT4_I(inode)->i_data_sem) if not allocating file system block
+  * (ie, create is zero). Otherwise down_write(&EXT4_I(inode)->i_data_sem)
+  */
+-int ext4_get_blocks_handle(handle_t *handle, struct inode *inode,
+-		ext4_lblk_t iblock, unsigned long maxblocks,
+-		struct buffer_head *bh_result,
+-		int create, int extend_disksize)
++static int ext4_get_blocks_handle(handle_t *handle, struct inode *inode,
++				  ext4_lblk_t iblock, unsigned int maxblocks,
++				  struct buffer_head *bh_result,
++				  int create, int extend_disksize)
+ {
+ 	int err = -EIO;
+ 	ext4_lblk_t offsets[4];
+@@ -1061,7 +1061,7 @@ static void ext4_da_update_reserve_space(struct inode *inode, int used)
+  * It returns the error in case of allocation failure.
+  */
+ int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block,
+-			unsigned long max_blocks, struct buffer_head *bh,
++			unsigned int max_blocks, struct buffer_head *bh,
+ 			int create, int extend_disksize, int flag)
+ {
+ 	int retval;
+@@ -1641,7 +1641,7 @@ struct mpage_da_data {
+ 	get_block_t *get_block;
+ 	struct writeback_control *wbc;
+ 	int io_done;
+-	long pages_written;
++	int pages_written;
+ 	int retval;
+ };
+ 
+@@ -1855,9 +1855,9 @@ static void ext4_print_free_blocks(struct inode *inode)
+ 	printk(KERN_EMERG "dirty_blocks=%lld\n",
+ 			(long long)percpu_counter_sum(&sbi->s_dirtyblocks_counter));
+ 	printk(KERN_EMERG "Block reservation details\n");
+-	printk(KERN_EMERG "i_reserved_data_blocks=%lu\n",
++	printk(KERN_EMERG "i_reserved_data_blocks=%u\n",
+ 			EXT4_I(inode)->i_reserved_data_blocks);
+-	printk(KERN_EMERG "i_reserved_meta_blocks=%lu\n",
++	printk(KERN_EMERG "i_reserved_meta_blocks=%u\n",
+ 			EXT4_I(inode)->i_reserved_meta_blocks);
+ 	return;
+ }
+@@ -2307,7 +2307,7 @@ static int ext4_da_writepage(struct page *page,
+ {
+ 	int ret = 0;
+ 	loff_t size;
+-	unsigned long len;
++	unsigned int len;
+ 	struct buffer_head *page_bufs;
+ 	struct inode *inode = page->mapping->host;
+ 
+@@ -2416,7 +2416,8 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 	struct mpage_da_data mpd;
+ 	struct inode *inode = mapping->host;
+ 	int no_nrwrite_index_update;
+-	long pages_written = 0, pages_skipped;
++	int pages_written = 0;
++	long pages_skipped;
+ 	int needed_blocks, ret = 0, nr_to_writebump = 0;
+ 	struct ext4_sb_info *sbi = EXT4_SB(mapping->host->i_sb);
+ 
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 6cfe68a7e070..1d78435ce388 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2796,7 +2796,7 @@ void exit_ext4_mballoc(void)
+  */
+ static noinline_for_stack int
+ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
+-				handle_t *handle, unsigned long reserv_blks)
++				handle_t *handle, unsigned int reserv_blks)
+ {
+ 	struct buffer_head *bitmap_bh = NULL;
+ 	struct ext4_super_block *es;
+@@ -3036,7 +3036,7 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
+ 	/* check we don't cross already preallocated blocks */
+ 	rcu_read_lock();
+ 	list_for_each_entry_rcu(pa, &ei->i_prealloc_list, pa_inode_list) {
+-		unsigned long pa_end;
++		ext4_lblk_t pa_end;
+ 
+ 		if (pa->pa_deleted)
+ 			continue;
+@@ -3080,7 +3080,7 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
+ 	/* XXX: extra loop to check we really don't overlap preallocations */
+ 	rcu_read_lock();
+ 	list_for_each_entry_rcu(pa, &ei->i_prealloc_list, pa_inode_list) {
+-		unsigned long pa_end;
++		ext4_lblk_t pa_end;
+ 		spin_lock(&pa->pa_lock);
+ 		if (pa->pa_deleted == 0) {
+ 			pa_end = pa->pa_lstart + pa->pa_len;
+@@ -3584,8 +3584,8 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh,
+ {
+ 	struct super_block *sb = e4b->bd_sb;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-	unsigned long end;
+-	unsigned long next;
++	unsigned int end;
++	unsigned int next;
+ 	ext4_group_t group;
+ 	ext4_grpblk_t bit;
+ 	sector_t start;
+@@ -4029,8 +4029,8 @@ ext4_mb_initialize_context(struct ext4_allocation_context *ac,
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	struct ext4_super_block *es = sbi->s_es;
+ 	ext4_group_t group;
+-	unsigned long len;
+-	unsigned long goal;
++	unsigned int len;
++	ext4_fsblk_t goal;
+ 	ext4_grpblk_t block;
+ 
+ 	/* we can't allocate > group size */
+@@ -4291,8 +4291,8 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
+ 	struct ext4_sb_info *sbi;
+ 	struct super_block *sb;
+ 	ext4_fsblk_t block = 0;
+-	unsigned long inquota;
+-	unsigned long reserv_blks = 0;
++	unsigned int inquota;
++	unsigned int reserv_blks = 0;
+ 
+ 	sb = ar->inode->i_sb;
+ 	sbi = EXT4_SB(sb);
+@@ -4504,7 +4504,7 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
+ 	struct ext4_allocation_context *ac = NULL;
+ 	struct ext4_group_desc *gdp;
+ 	struct ext4_super_block *es;
+-	unsigned long overflow;
++	unsigned int overflow;
+ 	ext4_grpblk_t bit;
+ 	struct buffer_head *gd_bh;
+ 	ext4_group_t block_group;
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 08873e938ab2..183a09a8b14e 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -811,7 +811,7 @@ static inline int ext4_match (int len, const char * const name,
+ static inline int search_dirblock(struct buffer_head *bh,
+ 				  struct inode *dir,
+ 				  const struct qstr *d_name,
+-				  unsigned long offset,
++				  unsigned int offset,
+ 				  struct ext4_dir_entry_2 ** res_dir)
+ {
+ 	struct ext4_dir_entry_2 * de;
+@@ -1048,11 +1048,11 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, stru
+ 	bh = ext4_find_entry(dir, &dentry->d_name, &de);
+ 	inode = NULL;
+ 	if (bh) {
+-		unsigned long ino = le32_to_cpu(de->inode);
++		__u32 ino = le32_to_cpu(de->inode);
+ 		brelse(bh);
+ 		if (!ext4_valid_inum(dir->i_sb, ino)) {
+ 			ext4_error(dir->i_sb, "ext4_lookup",
+-				   "bad inode number: %lu", ino);
++				   "bad inode number: %u", ino);
+ 			return ERR_PTR(-EIO);
+ 		}
+ 		inode = ext4_iget(dir->i_sb, ino);
+@@ -1065,7 +1065,7 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, stru
+ 
+ struct dentry *ext4_get_parent(struct dentry *child)
+ {
+-	unsigned long ino;
++	__u32 ino;
+ 	struct inode *inode;
+ 	static const struct qstr dotdot = {
+ 		.name = "..",
+@@ -1083,7 +1083,7 @@ struct dentry *ext4_get_parent(struct dentry *child)
+ 
+ 	if (!ext4_valid_inum(child->d_inode->i_sb, ino)) {
+ 		ext4_error(child->d_inode->i_sb, "ext4_get_parent",
+-			   "bad inode number: %lu", ino);
++			   "bad inode number: %u", ino);
+ 		return ERR_PTR(-EIO);
+ 	}
+ 
+@@ -1271,7 +1271,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
+ 	struct inode	*dir = dentry->d_parent->d_inode;
+ 	const char	*name = dentry->d_name.name;
+ 	int		namelen = dentry->d_name.len;
+-	unsigned long	offset = 0;
++	unsigned int	offset = 0;
+ 	unsigned short	reclen;
+ 	int		nlen, rlen, err;
+ 	char		*top;
+@@ -1444,7 +1444,6 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
+ 			  struct inode *inode)
+ {
+ 	struct inode *dir = dentry->d_parent->d_inode;
+-	unsigned long offset;
+ 	struct buffer_head *bh;
+ 	struct ext4_dir_entry_2 *de;
+ 	struct super_block *sb;
+@@ -1466,7 +1465,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
+ 		ext4_mark_inode_dirty(handle, dir);
+ 	}
+ 	blocks = dir->i_size >> sb->s_blocksize_bits;
+-	for (block = 0, offset = 0; block < blocks; block++) {
++	for (block = 0; block < blocks; block++) {
+ 		bh = ext4_bread(handle, dir, block, 0, &retval);
+ 		if(!bh)
+ 			return retval;
+@@ -1861,7 +1860,7 @@ static int ext4_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+  */
+ static int empty_dir(struct inode *inode)
+ {
+-	unsigned long offset;
++	unsigned int offset;
+ 	struct buffer_head *bh;
+ 	struct ext4_dir_entry_2 *de, *de1;
+ 	struct super_block *sb;
+@@ -1906,7 +1905,7 @@ static int empty_dir(struct inode *inode)
+ 				if (err)
+ 					ext4_error(sb, __func__,
+ 						   "error %d reading directory"
+-						   " #%lu offset %lu",
++						   " #%lu offset %u",
+ 						   err, inode->i_ino, offset);
+ 				offset += sb->s_blocksize;
+ 				continue;
+@@ -2009,7 +2008,7 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode)
+ 	struct list_head *prev;
+ 	struct ext4_inode_info *ei = EXT4_I(inode);
+ 	struct ext4_sb_info *sbi;
+-	unsigned long ino_next;
++	__u32 ino_next;
+ 	struct ext4_iloc iloc;
+ 	int err = 0;
+ 
+@@ -2042,7 +2041,7 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode)
+ 		goto out_err;
+ 
+ 	if (prev == &sbi->s_orphan) {
+-		jbd_debug(4, "superblock will point to %lu\n", ino_next);
++		jbd_debug(4, "superblock will point to %u\n", ino_next);
+ 		BUFFER_TRACE(sbi->s_sbh, "get_write_access");
+ 		err = ext4_journal_get_write_access(handle, sbi->s_sbh);
+ 		if (err)
+@@ -2054,7 +2053,7 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode)
+ 		struct inode *i_prev =
+ 			&list_entry(prev, struct ext4_inode_info, i_orphan)->vfs_inode;
+ 
+-		jbd_debug(4, "orphan inode %lu will point to %lu\n",
++		jbd_debug(4, "orphan inode %lu will point to %u\n",
+ 			  i_prev->i_ino, ino_next);
+ 		err = ext4_reserve_inode_write(handle, i_prev, &iloc2);
+ 		if (err)

commit a9df9a49102f3578909cba7bd33784eb3b9caaa4
+Author: Theodore Ts'o 
+Date:   Mon Jan 5 22:18:16 2009 -0500
+
+    ext4: Make ext4_group_t be an unsigned int
+    
+    Nearly all places in the ext3/4 code which uses "unsigned long" is
+    probably a bug, since on 32-bit systems a ulong a 32-bits, which means
+    we are wasting stack space on 64-bit systems.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 0cb1c4572f54..a711898923f0 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -100,7 +100,7 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
+ 		 * essentially implementing a per-group read-only flag. */
+ 		if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
+ 			ext4_error(sb, __func__,
+-				  "Checksum bad for group %lu", block_group);
++				  "Checksum bad for group %u", block_group);
+ 			gdp->bg_free_blocks_count = 0;
+ 			gdp->bg_free_inodes_count = 0;
+ 			gdp->bg_itable_unused = 0;
+@@ -213,7 +213,7 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
+ 	if (block_group >= sbi->s_groups_count) {
+ 		ext4_error(sb, "ext4_get_group_desc",
+ 			   "block_group >= groups_count - "
+-			   "block_group = %lu, groups_count = %lu",
++			   "block_group = %u, groups_count = %u",
+ 			   block_group, sbi->s_groups_count);
+ 
+ 		return NULL;
+@@ -225,7 +225,7 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
+ 	if (!sbi->s_group_desc[group_desc]) {
+ 		ext4_error(sb, "ext4_get_group_desc",
+ 			   "Group descriptor not loaded - "
+-			   "block_group = %lu, group_desc = %lu, desc = %lu",
++			   "block_group = %u, group_desc = %lu, desc = %lu",
+ 			   block_group, group_desc, offset);
+ 		return NULL;
+ 	}
+@@ -315,7 +315,7 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
+ 	if (unlikely(!bh)) {
+ 		ext4_error(sb, __func__,
+ 			    "Cannot read block bitmap - "
+-			    "block_group = %lu, block_bitmap = %llu",
++			    "block_group = %u, block_bitmap = %llu",
+ 			    block_group, bitmap_blk);
+ 		return NULL;
+ 	}
+@@ -337,7 +337,7 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
+ 		put_bh(bh);
+ 		ext4_error(sb, __func__,
+ 			    "Cannot read block bitmap - "
+-			    "block_group = %lu, block_bitmap = %llu",
++			    "block_group = %u, block_bitmap = %llu",
+ 			    block_group, bitmap_blk);
+ 		return NULL;
+ 	}
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 9ba9fd6d14da..e9aacecfbf41 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -965,7 +965,7 @@ ext4_group_first_block_no(struct super_block *sb, ext4_group_t group_no)
+ #define ERR_BAD_DX_DIR	-75000
+ 
+ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
+-			unsigned long *blockgrpp, ext4_grpblk_t *offsetp);
++			ext4_group_t *blockgrpp, ext4_grpblk_t *offsetp);
+ 
+ extern struct proc_dir_entry *ext4_proc_root;
+ 
+diff --git a/fs/ext4/ext4_i.h b/fs/ext4/ext4_i.h
+index acc0b726d8ab..0a9ebe580195 100644
+--- a/fs/ext4/ext4_i.h
++++ b/fs/ext4/ext4_i.h
+@@ -31,7 +31,7 @@ typedef unsigned long long ext4_fsblk_t;
+ typedef __u32 ext4_lblk_t;
+ 
+ /* data type for block group number */
+-typedef unsigned long ext4_group_t;
++typedef unsigned int ext4_group_t;
+ 
+ #define rsv_start rsv_window._rsv_start
+ #define rsv_end rsv_window._rsv_end
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 4794d2ce6130..cac3617ec780 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -74,7 +74,7 @@ unsigned ext4_init_inode_bitmap(struct super_block *sb, struct buffer_head *bh,
+ 	/* If checksum is bad mark all blocks and inodes use to prevent
+ 	 * allocation, essentially implementing a per-group read-only flag. */
+ 	if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
+-		ext4_error(sb, __func__, "Checksum bad for group %lu",
++		ext4_error(sb, __func__, "Checksum bad for group %u",
+ 			   block_group);
+ 		gdp->bg_free_blocks_count = 0;
+ 		gdp->bg_free_inodes_count = 0;
+@@ -111,7 +111,7 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
+ 	if (unlikely(!bh)) {
+ 		ext4_error(sb, __func__,
+ 			    "Cannot read inode bitmap - "
+-			    "block_group = %lu, inode_bitmap = %llu",
++			    "block_group = %u, inode_bitmap = %llu",
+ 			    block_group, bitmap_blk);
+ 		return NULL;
+ 	}
+@@ -133,7 +133,7 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
+ 		put_bh(bh);
+ 		ext4_error(sb, __func__,
+ 			    "Cannot read inode bitmap - "
+-			    "block_group = %lu, inode_bitmap = %llu",
++			    "block_group = %u, inode_bitmap = %llu",
+ 			    block_group, bitmap_blk);
+ 		return NULL;
+ 	}
+@@ -690,7 +690,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
+ 	    ino > EXT4_INODES_PER_GROUP(sb)) {
+ 		ext4_error(sb, __func__,
+ 			   "reserved inode or inode > inodes count - "
+-			   "block_group = %lu, inode=%lu", group,
++			   "block_group = %u, inode=%lu", group,
+ 			   ino + group * EXT4_INODES_PER_GROUP(sb));
+ 		err = -EIO;
+ 		goto fail;
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 6dea637b020a..6cfe68a7e070 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -447,7 +447,7 @@ static void mb_free_blocks_double(struct inode *inode, struct ext4_buddy *e4b,
+ 			    le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
+ 
+ 			ext4_error(sb, __func__, "double-free of inode"
+-				   " %lu's block %llu(bit %u in group %lu)",
++				   " %lu's block %llu(bit %u in group %u)",
+ 				   inode ? inode->i_ino : 0, blocknr,
+ 				   first + i, e4b->bd_group);
+ 		}
+@@ -477,7 +477,7 @@ static void mb_cmp_bitmaps(struct ext4_buddy *e4b, void *bitmap)
+ 		b2 = (unsigned char *) bitmap;
+ 		for (i = 0; i < e4b->bd_sb->s_blocksize; i++) {
+ 			if (b1[i] != b2[i]) {
+-				printk(KERN_ERR "corruption in group %lu "
++				printk(KERN_ERR "corruption in group %u "
+ 				       "at byte %u(%u): %x in copy != %x "
+ 				       "on disk/prealloc\n",
+ 				       e4b->bd_group, i, i * 8, b1[i], b2[i]);
+@@ -691,7 +691,7 @@ static void ext4_mb_generate_buddy(struct super_block *sb,
+ 
+ 	if (free != grp->bb_free) {
+ 		ext4_error(sb, __func__,
+-			"EXT4-fs: group %lu: %u blocks in bitmap, %u in gd",
++			"EXT4-fs: group %u: %u blocks in bitmap, %u in gd",
+ 			group, free, grp->bb_free);
+ 		/*
+ 		 * If we intent to continue, we consider group descritor
+@@ -800,7 +800,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
+ 		get_bh(bh[i]);
+ 		bh[i]->b_end_io = end_buffer_read_sync;
+ 		submit_bh(READ, bh[i]);
+-		mb_debug("read bitmap for group %lu\n", first_group + i);
++		mb_debug("read bitmap for group %u\n", first_group + i);
+ 	}
+ 
+ 	/* wait for I/O completion */
+@@ -895,7 +895,7 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group,
+ 	struct page *page;
+ 	int ret;
+ 
+-	mb_debug("load group %lu\n", group);
++	mb_debug("load group %u\n", group);
+ 
+ 	blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize;
+ 
+@@ -1096,7 +1096,7 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
+ 			    le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
+ 			ext4_unlock_group(sb, e4b->bd_group);
+ 			ext4_error(sb, __func__, "double-free of inode"
+-				   " %lu's block %llu(bit %u in group %lu)",
++				   " %lu's block %llu(bit %u in group %u)",
+ 				   inode ? inode->i_ino : 0, blocknr, block,
+ 				   e4b->bd_group);
+ 			ext4_lock_group(sb, e4b->bd_group);
+@@ -1934,13 +1934,13 @@ static int ext4_mb_seq_history_show(struct seq_file *seq, void *v)
+ 	if (hs->op == EXT4_MB_HISTORY_ALLOC) {
+ 		fmt = "%-5u %-8u %-23s %-23s %-23s %-5u %-5u %-2u "
+ 			"%-5u %-5s %-5u %-6u\n";
+-		sprintf(buf2, "%lu/%d/%u@%u", hs->result.fe_group,
++		sprintf(buf2, "%u/%d/%u@%u", hs->result.fe_group,
+ 			hs->result.fe_start, hs->result.fe_len,
+ 			hs->result.fe_logical);
+-		sprintf(buf, "%lu/%d/%u@%u", hs->orig.fe_group,
++		sprintf(buf, "%u/%d/%u@%u", hs->orig.fe_group,
+ 			hs->orig.fe_start, hs->orig.fe_len,
+ 			hs->orig.fe_logical);
+-		sprintf(buf3, "%lu/%d/%u@%u", hs->goal.fe_group,
++		sprintf(buf3, "%u/%d/%u@%u", hs->goal.fe_group,
+ 			hs->goal.fe_start, hs->goal.fe_len,
+ 			hs->goal.fe_logical);
+ 		seq_printf(seq, fmt, hs->pid, hs->ino, buf, buf3, buf2,
+@@ -1949,20 +1949,20 @@ static int ext4_mb_seq_history_show(struct seq_file *seq, void *v)
+ 				hs->buddy ? 1 << hs->buddy : 0);
+ 	} else if (hs->op == EXT4_MB_HISTORY_PREALLOC) {
+ 		fmt = "%-5u %-8u %-23s %-23s %-23s\n";
+-		sprintf(buf2, "%lu/%d/%u@%u", hs->result.fe_group,
++		sprintf(buf2, "%u/%d/%u@%u", hs->result.fe_group,
+ 			hs->result.fe_start, hs->result.fe_len,
+ 			hs->result.fe_logical);
+-		sprintf(buf, "%lu/%d/%u@%u", hs->orig.fe_group,
++		sprintf(buf, "%u/%d/%u@%u", hs->orig.fe_group,
+ 			hs->orig.fe_start, hs->orig.fe_len,
+ 			hs->orig.fe_logical);
+ 		seq_printf(seq, fmt, hs->pid, hs->ino, buf, "", buf2);
+ 	} else if (hs->op == EXT4_MB_HISTORY_DISCARD) {
+-		sprintf(buf2, "%lu/%d/%u", hs->result.fe_group,
++		sprintf(buf2, "%u/%d/%u", hs->result.fe_group,
+ 			hs->result.fe_start, hs->result.fe_len);
+ 		seq_printf(seq, "%-5u %-8u %-23s discard\n",
+ 				hs->pid, hs->ino, buf2);
+ 	} else if (hs->op == EXT4_MB_HISTORY_FREE) {
+-		sprintf(buf2, "%lu/%d/%u", hs->result.fe_group,
++		sprintf(buf2, "%u/%d/%u", hs->result.fe_group,
+ 			hs->result.fe_start, hs->result.fe_len);
+ 		seq_printf(seq, "%-5u %-8u %-23s free\n",
+ 				hs->pid, hs->ino, buf2);
+@@ -2075,7 +2075,7 @@ static void *ext4_mb_seq_groups_start(struct seq_file *seq, loff_t *pos)
+ 		return NULL;
+ 
+ 	group = *pos + 1;
+-	return (void *) group;
++	return (void *) ((unsigned long) group);
+ }
+ 
+ static void *ext4_mb_seq_groups_next(struct seq_file *seq, void *v, loff_t *pos)
+@@ -2088,13 +2088,13 @@ static void *ext4_mb_seq_groups_next(struct seq_file *seq, void *v, loff_t *pos)
+ 	if (*pos < 0 || *pos >= sbi->s_groups_count)
+ 		return NULL;
+ 	group = *pos + 1;
+-	return (void *) group;;
++	return (void *) ((unsigned long) group);
+ }
+ 
+ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v)
+ {
+ 	struct super_block *sb = seq->private;
+-	long group = (long) v;
++	ext4_group_t group = (ext4_group_t) ((unsigned long) v);
+ 	int i;
+ 	int err;
+ 	struct ext4_buddy e4b;
+@@ -2116,7 +2116,7 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v)
+ 		sizeof(struct ext4_group_info);
+ 	err = ext4_mb_load_buddy(sb, group, &e4b);
+ 	if (err) {
+-		seq_printf(seq, "#%-5lu: I/O error\n", group);
++		seq_printf(seq, "#%-5u: I/O error\n", group);
+ 		return 0;
+ 	}
+ 	ext4_lock_group(sb, group);
+@@ -2124,7 +2124,7 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v)
+ 	ext4_unlock_group(sb, group);
+ 	ext4_mb_release_desc(&e4b);
+ 
+-	seq_printf(seq, "#%-5lu: %-5u %-5u %-5u [", group, sg.info.bb_free,
++	seq_printf(seq, "#%-5u: %-5u %-5u %-5u [", group, sg.info.bb_free,
+ 			sg.info.bb_fragments, sg.info.bb_first_free);
+ 	for (i = 0; i <= 13; i++)
+ 		seq_printf(seq, " %-5u", i <= sb->s_blocksize_bits + 1 ?
+@@ -2459,7 +2459,7 @@ static int ext4_mb_init_backend(struct super_block *sb)
+ 		desc = ext4_get_group_desc(sb, i, NULL);
+ 		if (desc == NULL) {
+ 			printk(KERN_ERR
+-				"EXT4-fs: can't read descriptor %lu\n", i);
++				"EXT4-fs: can't read descriptor %u\n", i);
+ 			goto err_freebuddy;
+ 		}
+ 		if (ext4_mb_add_groupinfo(sb, i, desc) != 0)
+@@ -2657,7 +2657,7 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn)
+ 	list_for_each_safe(l, ltmp, &txn->t_private_list) {
+ 		entry = list_entry(l, struct ext4_free_data, list);
+ 
+-		mb_debug("gonna free %u blocks in group %lu (0x%p):",
++		mb_debug("gonna free %u blocks in group %u (0x%p):",
+ 			 entry->count, entry->group, entry);
+ 
+ 		err = ext4_mb_load_buddy(sb, entry->group, &e4b);
+@@ -2829,7 +2829,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
+ 	if (!gdp)
+ 		goto out_err;
+ 
+-	ext4_debug("using block group %lu(%d)\n", ac->ac_b_ex.fe_group,
++	ext4_debug("using block group %u(%d)\n", ac->ac_b_ex.fe_group,
+ 			gdp->bg_free_blocks_count);
+ 
+ 	err = ext4_journal_get_write_access(handle, gdp_bh);
+@@ -3351,7 +3351,7 @@ static void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap,
+ 		preallocated += len;
+ 		count++;
+ 	}
+-	mb_debug("prellocated %u for group %lu\n", preallocated, group);
++	mb_debug("prellocated %u for group %u\n", preallocated, group);
+ }
+ 
+ static void ext4_mb_pa_callback(struct rcu_head *head)
+@@ -3368,7 +3368,7 @@ static void ext4_mb_pa_callback(struct rcu_head *head)
+ static void ext4_mb_put_pa(struct ext4_allocation_context *ac,
+ 			struct super_block *sb, struct ext4_prealloc_space *pa)
+ {
+-	unsigned long grp;
++	ext4_group_t grp;
+ 
+ 	if (!atomic_dec_and_test(&pa->pa_count) || pa->pa_free != 0)
+ 		return;
+@@ -3697,7 +3697,7 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
+ 	int busy = 0;
+ 	int free = 0;
+ 
+-	mb_debug("discard preallocation for group %lu\n", group);
++	mb_debug("discard preallocation for group %u\n", group);
+ 
+ 	if (list_empty(&grp->bb_prealloc_list))
+ 		return 0;
+@@ -3705,14 +3705,14 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
+ 	bitmap_bh = ext4_read_block_bitmap(sb, group);
+ 	if (bitmap_bh == NULL) {
+ 		ext4_error(sb, __func__, "Error in reading block "
+-				"bitmap for %lu", group);
++				"bitmap for %u", group);
+ 		return 0;
+ 	}
+ 
+ 	err = ext4_mb_load_buddy(sb, group, &e4b);
+ 	if (err) {
+ 		ext4_error(sb, __func__, "Error in loading buddy "
+-				"information for %lu", group);
++				"information for %u", group);
+ 		put_bh(bitmap_bh);
+ 		return 0;
+ 	}
+@@ -3879,14 +3879,14 @@ void ext4_discard_preallocations(struct inode *inode)
+ 		err = ext4_mb_load_buddy(sb, group, &e4b);
+ 		if (err) {
+ 			ext4_error(sb, __func__, "Error in loading buddy "
+-					"information for %lu", group);
++					"information for %u", group);
+ 			continue;
+ 		}
+ 
+ 		bitmap_bh = ext4_read_block_bitmap(sb, group);
+ 		if (bitmap_bh == NULL) {
+ 			ext4_error(sb, __func__, "Error in reading block "
+-					"bitmap for %lu", group);
++					"bitmap for %u", group);
+ 			ext4_mb_release_desc(&e4b);
+ 			continue;
+ 		}
+@@ -4151,7 +4151,7 @@ ext4_mb_discard_lg_preallocations(struct super_block *sb,
+ 		ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, NULL);
+ 		if (ext4_mb_load_buddy(sb, group, &e4b)) {
+ 			ext4_error(sb, __func__, "Error in loading buddy "
+-					"information for %lu", group);
++					"information for %u", group);
+ 			continue;
+ 		}
+ 		ext4_lock_group(sb, group);
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 411338117443..1865d6a53de3 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -50,7 +50,7 @@ static int verify_group_input(struct super_block *sb,
+ 	ext4_get_group_no_and_offset(sb, start, NULL, &offset);
+ 	if (group != sbi->s_groups_count)
+ 		ext4_warning(sb, __func__,
+-			     "Cannot add at group %u (only %lu groups)",
++			     "Cannot add at group %u (only %u groups)",
+ 			     input->group, sbi->s_groups_count);
+ 	else if (offset != 0)
+ 			ext4_warning(sb, __func__, "Last group not full");
+@@ -716,7 +716,7 @@ static void update_backups(struct super_block *sb,
+ exit_err:
+ 	if (err) {
+ 		ext4_warning(sb, __func__,
+-			     "can't update backup for group %lu (err %d), "
++			     "can't update backup for group %u (err %d), "
+ 			     "forcing fsck on next reboot", group, err);
+ 		sbi->s_mount_state &= ~EXT4_VALID_FS;
+ 		sbi->s_es->s_state &= cpu_to_le16(~EXT4_VALID_FS);
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index da377f9521bb..8fa57be5040a 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1470,7 +1470,7 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
+ 
+ 	ext4_commit_super(sb, es, 1);
+ 	if (test_opt(sb, DEBUG))
+-		printk(KERN_INFO "[EXT4 FS bs=%lu, gc=%lu, "
++		printk(KERN_INFO "[EXT4 FS bs=%lu, gc=%u, "
+ 				"bpg=%lu, ipg=%lu, mo=%04lx]\n",
+ 			sb->s_blocksize,
+ 			sbi->s_groups_count,
+@@ -1514,7 +1514,7 @@ static int ext4_fill_flex_info(struct super_block *sb)
+ 				     sizeof(struct flex_groups), GFP_KERNEL);
+ 	if (sbi->s_flex_groups == NULL) {
+ 		printk(KERN_ERR "EXT4-fs: not enough memory for "
+-				"%lu flex groups\n", flex_group_count);
++				"%u flex groups\n", flex_group_count);
+ 		goto failed;
+ 	}
+ 
+@@ -1599,14 +1599,14 @@ static int ext4_check_descriptors(struct super_block *sb)
+ 		block_bitmap = ext4_block_bitmap(sb, gdp);
+ 		if (block_bitmap < first_block || block_bitmap > last_block) {
+ 			printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
+-			       "Block bitmap for group %lu not in group "
++			       "Block bitmap for group %u not in group "
+ 			       "(block %llu)!\n", i, block_bitmap);
+ 			return 0;
+ 		}
+ 		inode_bitmap = ext4_inode_bitmap(sb, gdp);
+ 		if (inode_bitmap < first_block || inode_bitmap > last_block) {
+ 			printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
+-			       "Inode bitmap for group %lu not in group "
++			       "Inode bitmap for group %u not in group "
+ 			       "(block %llu)!\n", i, inode_bitmap);
+ 			return 0;
+ 		}
+@@ -1614,14 +1614,14 @@ static int ext4_check_descriptors(struct super_block *sb)
+ 		if (inode_table < first_block ||
+ 		    inode_table + sbi->s_itb_per_group - 1 > last_block) {
+ 			printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
+-			       "Inode table for group %lu not in group "
++			       "Inode table for group %u not in group "
+ 			       "(block %llu)!\n", i, inode_table);
+ 			return 0;
+ 		}
+ 		spin_lock(sb_bgl_lock(sbi, i));
+ 		if (!ext4_group_desc_csum_verify(sbi, i, gdp)) {
+ 			printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
+-			       "Checksum for group %lu failed (%u!=%u)\n",
++			       "Checksum for group %u failed (%u!=%u)\n",
+ 			       i, le16_to_cpu(ext4_group_desc_csum(sbi, i,
+ 			       gdp)), le16_to_cpu(gdp->bg_checksum));
+ 			if (!(sb->s_flags & MS_RDONLY)) {
+@@ -3154,7 +3154,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 				if (!ext4_group_desc_csum_verify(sbi, g, gdp)) {
+ 					printk(KERN_ERR
+ 	       "EXT4-fs: ext4_remount: "
+-		"Checksum for group %lu failed (%u!=%u)\n",
++		"Checksum for group %u failed (%u!=%u)\n",
+ 		g, le16_to_cpu(ext4_group_desc_csum(sbi, g, gdp)),
+ 					       le16_to_cpu(gdp->bg_checksum));
+ 					err = -EINVAL;

commit cde6436004ad9cd8cab5a874b6fa8b01f1da91bf
+Author: Theodore Ts'o 
+Date:   Tue Nov 4 18:46:03 2008 -0500
+
+    ext4: Remove i_ext_generation from ext4_inode_info structure
+    
+    The i_ext_generation was incremented, but never used.  Remove it to
+    slim down the ext4_inode_info structure.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h
+index bec7ce59fc0d..18cb67b2cbbc 100644
+--- a/fs/ext4/ext4_extents.h
++++ b/fs/ext4/ext4_extents.h
+@@ -194,11 +194,6 @@ static inline unsigned short ext_depth(struct inode *inode)
+ 	return le16_to_cpu(ext_inode_hdr(inode)->eh_depth);
+ }
+ 
+-static inline void ext4_ext_tree_changed(struct inode *inode)
+-{
+-	EXT4_I(inode)->i_ext_generation++;
+-}
+-
+ static inline void
+ ext4_ext_invalidate_cache(struct inode *inode)
+ {
+diff --git a/fs/ext4/ext4_i.h b/fs/ext4/ext4_i.h
+index 5c124c0ac6d3..acc0b726d8ab 100644
+--- a/fs/ext4/ext4_i.h
++++ b/fs/ext4/ext4_i.h
+@@ -117,7 +117,6 @@ struct ext4_inode_info {
+ 	struct inode vfs_inode;
+ 	struct jbd2_inode jinode;
+ 
+-	unsigned long i_ext_generation;
+ 	struct ext4_ext_cache i_cached_extent;
+ 	/*
+ 	 * File creation time. Its function is same as that of
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 743e3feb3e50..b9e27bc31559 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -1621,7 +1621,6 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+ 		ext4_ext_drop_refs(npath);
+ 		kfree(npath);
+ 	}
+-	ext4_ext_tree_changed(inode);
+ 	ext4_ext_invalidate_cache(inode);
+ 	return err;
+ }
+@@ -2232,7 +2231,6 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start)
+ 		}
+ 	}
+ out:
+-	ext4_ext_tree_changed(inode);
+ 	ext4_ext_drop_refs(path);
+ 	kfree(path);
+ 	ext4_journal_stop(handle);

commit 30773840c19cea60dcef39545960d541b1ac1cf8
+Author: Theodore Ts'o 
+Date:   Sat Jan 3 20:27:38 2009 -0500
+
+    ext4: add fsync batch tuning knobs
+    
+    Add new mount options, min_batch_time and max_batch_time, which
+    controls how long the jbd2 layer should wait for additional filesystem
+    operations to get batched with a synchronous write transaction.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
+index f75ab101c00a..e3fcbea3ec8c 100644
+--- a/Documentation/filesystems/ext4.txt
++++ b/Documentation/filesystems/ext4.txt
+@@ -283,6 +283,35 @@ delalloc	(*)	Deferring block allocation until write-out time.
+ nodelalloc		Disable delayed allocation. Blocks are allocation
+ 			when data is copied from user to page cache.
+ 
++max_batch_time=usec	Maximum amount of time ext4 should wait for
++			additional filesystem operations to be batch
++			together with a synchronous write operation.
++			Since a synchronous write operation is going to
++			force a commit and then a wait for the I/O
++			complete, it doesn't cost much, and can be a
++			huge throughput win, we wait for a small amount
++			of time to see if any other transactions can
++			piggyback on the synchronous write.   The
++			algorithm used is designed to automatically tune
++			for the speed of the disk, by measuring the
++			amount of time (on average) that it takes to
++			finish committing a transaction.  Call this time
++			the "commit time".  If the time that the
++			transactoin has been running is less than the
++			commit time, ext4 will try sleeping for the
++			commit time to see if other operations will join
++			the transaction.   The commit time is capped by
++			the max_batch_time, which defaults to 15000us
++			(15ms).   This optimization can be turned off
++			entirely by setting max_batch_time to 0.
++
++min_batch_time=usec	This parameter sets the commit time (as
++			described above) to be at least min_batch_time.
++			It defaults to zero microseconds.  Increasing
++			this parameter may improve the throughput of
++			multi-threaded, synchronous workloads on very
++			fast disks, at the cost of increasing latency.
++
+ Data Mode
+ =========
+ There are 3 different data modes:
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index ac8551e0b70a..9ba9fd6d14da 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -328,6 +328,7 @@ struct ext4_mount_options {
+ 	uid_t s_resuid;
+ 	gid_t s_resgid;
+ 	unsigned long s_commit_interval;
++	u32 s_min_batch_time, s_max_batch_time;
+ #ifdef CONFIG_QUOTA
+ 	int s_jquota_fmt;
+ 	char *s_qf_names[MAXQUOTAS];
+@@ -805,6 +806,12 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
+ #define EXT4_DEFM_JMODE_ORDERED	0x0040
+ #define EXT4_DEFM_JMODE_WBACK	0x0060
+ 
++/*
++ * Default journal batch times
++ */
++#define EXT4_DEF_MIN_BATCH_TIME	0
++#define EXT4_DEF_MAX_BATCH_TIME	15000 /* 15ms */
++
+ /*
+  * Structure of a directory entry
+  */
+diff --git a/fs/ext4/ext4_sb.h b/fs/ext4/ext4_sb.h
+index 3db800f399a6..039b6ea1a042 100644
+--- a/fs/ext4/ext4_sb.h
++++ b/fs/ext4/ext4_sb.h
+@@ -74,6 +74,8 @@ struct ext4_sb_info {
+ 	struct journal_s *s_journal;
+ 	struct list_head s_orphan;
+ 	unsigned long s_commit_interval;
++	u32 s_max_batch_time;
++	u32 s_min_batch_time;
+ 	struct block_device *journal_bdev;
+ #ifdef CONFIG_JBD2_DEBUG
+ 	struct timer_list turn_ro_timer;	/* For turning read-only (crash simulation) */
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index dc27d4c613c0..da377f9521bb 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -705,10 +705,19 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
+ #endif
+ 	if (!test_opt(sb, RESERVATION))
+ 		seq_puts(seq, ",noreservation");
+-	if (sbi->s_commit_interval) {
++	if (sbi->s_commit_interval != JBD2_DEFAULT_MAX_COMMIT_AGE*HZ) {
+ 		seq_printf(seq, ",commit=%u",
+ 			   (unsigned) (sbi->s_commit_interval / HZ));
+ 	}
++	if (sbi->s_min_batch_time != EXT4_DEF_MIN_BATCH_TIME) {
++		seq_printf(seq, ",min_batch_time=%u",
++			   (unsigned) sbi->s_min_batch_time);
++	}
++	if (sbi->s_max_batch_time != EXT4_DEF_MAX_BATCH_TIME) {
++		seq_printf(seq, ",max_batch_time=%u",
++			   (unsigned) sbi->s_min_batch_time);
++	}
++
+ 	/*
+ 	 * We're changing the default of barrier mount option, so
+ 	 * let's always display its mount state so it's clear what its
+@@ -874,7 +883,8 @@ enum {
+ 	Opt_nouid32, Opt_debug, Opt_oldalloc, Opt_orlov,
+ 	Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
+ 	Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh,
+-	Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev,
++	Opt_commit, Opt_min_batch_time, Opt_max_batch_time,
++	Opt_journal_update, Opt_journal_inum, Opt_journal_dev,
+ 	Opt_journal_checksum, Opt_journal_async_commit,
+ 	Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
+ 	Opt_data_err_abort, Opt_data_err_ignore,
+@@ -913,6 +923,8 @@ static const match_table_t tokens = {
+ 	{Opt_nobh, "nobh"},
+ 	{Opt_bh, "bh"},
+ 	{Opt_commit, "commit=%u"},
++	{Opt_min_batch_time, "min_batch_time=%u"},
++	{Opt_max_batch_time, "max_batch_time=%u"},
+ 	{Opt_journal_update, "journal=update"},
+ 	{Opt_journal_inum, "journal=%u"},
+ 	{Opt_journal_dev, "journal_dev=%u"},
+@@ -1131,6 +1143,22 @@ static int parse_options(char *options, struct super_block *sb,
+ 				option = JBD2_DEFAULT_MAX_COMMIT_AGE;
+ 			sbi->s_commit_interval = HZ * option;
+ 			break;
++		case Opt_max_batch_time:
++			if (match_int(&args[0], &option))
++				return 0;
++			if (option < 0)
++				return 0;
++			if (option == 0)
++				option = EXT4_DEF_MAX_BATCH_TIME;
++			sbi->s_max_batch_time = option;
++			break;
++		case Opt_min_batch_time:
++			if (match_int(&args[0], &option))
++				return 0;
++			if (option < 0)
++				return 0;
++			sbi->s_min_batch_time = option;
++			break;
+ 		case Opt_data_journal:
+ 			data_opt = EXT4_MOUNT_JOURNAL_DATA;
+ 			goto datacheck;
+@@ -1979,6 +2007,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 
+ 	sbi->s_resuid = le16_to_cpu(es->s_def_resuid);
+ 	sbi->s_resgid = le16_to_cpu(es->s_def_resgid);
++	sbi->s_commit_interval = JBD2_DEFAULT_MAX_COMMIT_AGE * HZ;
++	sbi->s_min_batch_time = EXT4_DEF_MIN_BATCH_TIME;
++	sbi->s_max_batch_time = EXT4_DEF_MAX_BATCH_TIME;
+ 
+ 	set_opt(sbi->s_mount_opt, RESERVATION);
+ 	set_opt(sbi->s_mount_opt, BARRIER);
+@@ -2524,11 +2555,9 @@ static void ext4_init_journal_params(struct super_block *sb, journal_t *journal)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 
+-	if (sbi->s_commit_interval)
+-		journal->j_commit_interval = sbi->s_commit_interval;
+-	/* We could also set up an ext4-specific default for the commit
+-	 * interval here, but for now we'll just fall back to the jbd
+-	 * default. */
++	journal->j_commit_interval = sbi->s_commit_interval;
++	journal->j_min_batch_time = sbi->s_min_batch_time;
++	journal->j_max_batch_time = sbi->s_max_batch_time;
+ 
+ 	spin_lock(&journal->j_state_lock);
+ 	if (test_opt(sb, BARRIER))
+@@ -3042,6 +3071,8 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 	old_opts.s_resuid = sbi->s_resuid;
+ 	old_opts.s_resgid = sbi->s_resgid;
+ 	old_opts.s_commit_interval = sbi->s_commit_interval;
++	old_opts.s_min_batch_time = sbi->s_min_batch_time;
++	old_opts.s_max_batch_time = sbi->s_max_batch_time;
+ #ifdef CONFIG_QUOTA
+ 	old_opts.s_jquota_fmt = sbi->s_jquota_fmt;
+ 	for (i = 0; i < MAXQUOTAS; i++)
+@@ -3178,6 +3209,8 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ 	sbi->s_resuid = old_opts.s_resuid;
+ 	sbi->s_resgid = old_opts.s_resgid;
+ 	sbi->s_commit_interval = old_opts.s_commit_interval;
++	sbi->s_min_batch_time = old_opts.s_min_batch_time;
++	sbi->s_max_batch_time = old_opts.s_max_batch_time;
+ #ifdef CONFIG_QUOTA
+ 	sbi->s_jquota_fmt = old_opts.s_jquota_fmt;
+ 	for (i = 0; i < MAXQUOTAS; i++) {
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 74d87290381c..fd1d7557a098 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -964,6 +964,8 @@ static journal_t * journal_init_common (void)
+ 	spin_lock_init(&journal->j_state_lock);
+ 
+ 	journal->j_commit_interval = (HZ * JBD2_DEFAULT_MAX_COMMIT_AGE);
++	journal->j_min_batch_time = 0;
++	journal->j_max_batch_time = 15000; /* 15ms */
+ 
+ 	/* The journal is marked for error until we succeed with recovery! */
+ 	journal->j_flags = JBD2_ABORT;
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index 13dcbc990f41..48c21bac5a56 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -1255,8 +1255,10 @@ int jbd2_journal_stop(handle_t *handle)
+ 		trans_time = ktime_to_ns(ktime_sub(ktime_get(),
+ 						   transaction->t_start_time));
+ 
++		commit_time = max_t(u64, commit_time,
++				    1000*journal->j_min_batch_time);
+ 		commit_time = min_t(u64, commit_time,
+-				    1000*jiffies_to_usecs(1));
++				    1000*journal->j_max_batch_time);
+ 
+ 		if (trans_time < commit_time) {
+ 			ktime_t expires = ktime_add_ns(ktime_get(),
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index ab8cef130c28..a3cd647ea1bc 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -956,6 +956,14 @@ struct journal_s
+ 	 */
+ 	u64			j_average_commit_time;
+ 
++	/*
++	 * minimum and maximum times that we should wait for
++	 * additional filesystem operations to get batched into a
++	 * synchronous handle in microseconds
++	 */
++	u32			j_min_batch_time;
++	u32			j_max_batch_time;
++
+ 	/* This function is called when a transaction is closed */
+ 	void			(*j_commit_callback)(journal_t *,
+ 						     transaction_t *);

commit d7cfa4684d82f58e5d7cb73b8a3c88c169937f25
+Author: Theodore Ts'o 
+Date:   Wed Dec 17 00:20:45 2008 -0500
+
+    ext4: display average commit time
+    
+    Display the average commit time (which is used by the ext4 fsync
+    batching patch) in /proc/fs/jbd2/*/info for performance tuning
+    purposes.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index e70d657a19f8..74d87290381c 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -40,6 +40,7 @@
+ 
+ #include 
+ #include 
++#include 
+ 
+ EXPORT_SYMBOL(jbd2_journal_start);
+ EXPORT_SYMBOL(jbd2_journal_restart);
+@@ -824,6 +825,8 @@ static int jbd2_seq_info_show(struct seq_file *seq, void *v)
+ 	    jiffies_to_msecs(s->stats->u.run.rs_flushing / s->stats->ts_tid));
+ 	seq_printf(seq, "  %ums logging transaction\n",
+ 	    jiffies_to_msecs(s->stats->u.run.rs_logging / s->stats->ts_tid));
++	seq_printf(seq, "  %luus average transaction commit time\n",
++		   do_div(s->journal->j_average_commit_time, 1000));
+ 	seq_printf(seq, "  %lu handles per transaction\n",
+ 	    s->stats->u.run.rs_handle_count / s->stats->ts_tid);
+ 	seq_printf(seq, "  %lu blocks per transaction\n",

commit fde4d95ad8711c84a36735a17136c45b19746af9
+Author: Theodore Ts'o 
+Date:   Mon Jan 5 22:17:35 2009 -0500
+
+    ext4: remove extraneous newlines from calls to ext4_error() and ext4_warning()
+    
+    This removes annoying blank syslog entries emitted by ext4_error() or
+    ext4_warning(), since these functions add their own newline.
+    
+    Signed-off-by: Nick Warne 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 31ebeb5e7b07..0cb1c4572f54 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -100,7 +100,7 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
+ 		 * essentially implementing a per-group read-only flag. */
+ 		if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
+ 			ext4_error(sb, __func__,
+-				  "Checksum bad for group %lu\n", block_group);
++				  "Checksum bad for group %lu", block_group);
+ 			gdp->bg_free_blocks_count = 0;
+ 			gdp->bg_free_inodes_count = 0;
+ 			gdp->bg_itable_unused = 0;
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 9dd21b75f4bc..4794d2ce6130 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -74,7 +74,7 @@ unsigned ext4_init_inode_bitmap(struct super_block *sb, struct buffer_head *bh,
+ 	/* If checksum is bad mark all blocks and inodes use to prevent
+ 	 * allocation, essentially implementing a per-group read-only flag. */
+ 	if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
+-		ext4_error(sb, __func__, "Checksum bad for group %lu\n",
++		ext4_error(sb, __func__, "Checksum bad for group %lu",
+ 			   block_group);
+ 		gdp->bg_free_blocks_count = 0;
+ 		gdp->bg_free_inodes_count = 0;
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index edb512b2ec49..48d606cd740f 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -447,7 +447,7 @@ static void mb_free_blocks_double(struct inode *inode, struct ext4_buddy *e4b,
+ 			    le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
+ 
+ 			ext4_error(sb, __func__, "double-free of inode"
+-				   " %lu's block %llu(bit %u in group %lu)\n",
++				   " %lu's block %llu(bit %u in group %lu)",
+ 				   inode ? inode->i_ino : 0, blocknr,
+ 				   first + i, e4b->bd_group);
+ 		}
+@@ -691,7 +691,7 @@ static void ext4_mb_generate_buddy(struct super_block *sb,
+ 
+ 	if (free != grp->bb_free) {
+ 		ext4_error(sb, __func__,
+-			"EXT4-fs: group %lu: %u blocks in bitmap, %u in gd\n",
++			"EXT4-fs: group %lu: %u blocks in bitmap, %u in gd",
+ 			group, free, grp->bb_free);
+ 		/*
+ 		 * If we intent to continue, we consider group descritor
+@@ -1096,7 +1096,7 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
+ 			    le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
+ 			ext4_unlock_group(sb, e4b->bd_group);
+ 			ext4_error(sb, __func__, "double-free of inode"
+-				   " %lu's block %llu(bit %u in group %lu)\n",
++				   " %lu's block %llu(bit %u in group %lu)",
+ 				   inode ? inode->i_ino : 0, blocknr, block,
+ 				   e4b->bd_group);
+ 			ext4_lock_group(sb, e4b->bd_group);
+@@ -1576,7 +1576,7 @@ static void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
+ 			 * we have free blocks
+ 			 */
+ 			ext4_error(sb, __func__, "%d free blocks as per "
+-					"group info. But bitmap says 0\n",
++					"group info. But bitmap says 0",
+ 					free);
+ 			break;
+ 		}
+@@ -1585,7 +1585,7 @@ static void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
+ 		BUG_ON(ex.fe_len <= 0);
+ 		if (free < ex.fe_len) {
+ 			ext4_error(sb, __func__, "%d free blocks as per "
+-					"group info. But got %d blocks\n",
++					"group info. But got %d blocks",
+ 					free, ex.fe_len);
+ 			/*
+ 			 * The number of free blocks differs. This mostly
+@@ -3629,7 +3629,7 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh,
+ 			pa, (unsigned long) pa->pa_lstart,
+ 			(unsigned long) pa->pa_pstart,
+ 			(unsigned long) pa->pa_len);
+-		ext4_error(sb, __func__, "free %u, pa_free %u\n",
++		ext4_error(sb, __func__, "free %u, pa_free %u",
+ 						free, pa->pa_free);
+ 		/*
+ 		 * pa is already deleted so we use the value obtained
+@@ -3703,14 +3703,14 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
+ 	bitmap_bh = ext4_read_block_bitmap(sb, group);
+ 	if (bitmap_bh == NULL) {
+ 		ext4_error(sb, __func__, "Error in reading block "
+-				"bitmap for %lu\n", group);
++				"bitmap for %lu", group);
+ 		return 0;
+ 	}
+ 
+ 	err = ext4_mb_load_buddy(sb, group, &e4b);
+ 	if (err) {
+ 		ext4_error(sb, __func__, "Error in loading buddy "
+-				"information for %lu\n", group);
++				"information for %lu", group);
+ 		put_bh(bitmap_bh);
+ 		return 0;
+ 	}
+@@ -3877,14 +3877,14 @@ void ext4_discard_preallocations(struct inode *inode)
+ 		err = ext4_mb_load_buddy(sb, group, &e4b);
+ 		if (err) {
+ 			ext4_error(sb, __func__, "Error in loading buddy "
+-					"information for %lu\n", group);
++					"information for %lu", group);
+ 			continue;
+ 		}
+ 
+ 		bitmap_bh = ext4_read_block_bitmap(sb, group);
+ 		if (bitmap_bh == NULL) {
+ 			ext4_error(sb, __func__, "Error in reading block "
+-					"bitmap for %lu\n", group);
++					"bitmap for %lu", group);
+ 			ext4_mb_release_desc(&e4b);
+ 			continue;
+ 		}
+@@ -4149,7 +4149,7 @@ ext4_mb_discard_lg_preallocations(struct super_block *sb,
+ 		ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, NULL);
+ 		if (ext4_mb_load_buddy(sb, group, &e4b)) {
+ 			ext4_error(sb, __func__, "Error in loading buddy "
+-					"information for %lu\n", group);
++					"information for %lu", group);
+ 			continue;
+ 		}
+ 		ext4_lock_group(sb, group);
+@@ -4446,7 +4446,7 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
+ 		else {
+ 			ext4_unlock_group(sb, group);
+ 			ext4_error(sb, __func__,
+-			    "Double free of blocks %d (%d %d)\n",
++			    "Double free of blocks %d (%d %d)",
+ 			    block, entry->start_blk, entry->count);
+ 			return 0;
+ 		}
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 1665aa131d18..411338117443 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -762,13 +762,13 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
+ 
+ 	if (ext4_blocks_count(es) + input->blocks_count <
+ 	    ext4_blocks_count(es)) {
+-		ext4_warning(sb, __func__, "blocks_count overflow\n");
++		ext4_warning(sb, __func__, "blocks_count overflow");
+ 		return -EINVAL;
+ 	}
+ 
+ 	if (le32_to_cpu(es->s_inodes_count) + EXT4_INODES_PER_GROUP(sb) <
+ 	    le32_to_cpu(es->s_inodes_count)) {
+-		ext4_warning(sb, __func__, "inodes_count overflow\n");
++		ext4_warning(sb, __func__, "inodes_count overflow");
+ 		return -EINVAL;
+ 	}
+ 
+@@ -999,8 +999,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
+ 			" too large to resize to %llu blocks safely\n",
+ 			sb->s_id, n_blocks_count);
+ 		if (sizeof(sector_t) < 8)
+-			ext4_warning(sb, __func__,
+-			"CONFIG_LBD not enabled\n");
++			ext4_warning(sb, __func__, "CONFIG_LBD not enabled");
+ 		return -EINVAL;
+ 	}
+ 
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 9b9076d9c4f7..dc27d4c613c0 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1309,7 +1309,7 @@ static int parse_options(char *options, struct super_block *sb,
+ 					EXT4_FEATURE_INCOMPAT_EXTENTS)) {
+ 				ext4_warning(sb, __func__,
+ 					"extents feature not enabled "
+-					"on this filesystem, use tune2fs\n");
++					"on this filesystem, use tune2fs");
+ 				return 0;
+ 			}
+ 			set_opt(sbi->s_mount_opt, EXTENTS);
+@@ -1993,7 +1993,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	else
+ 		ext4_warning(sb, __func__,
+ 			"extents feature not enabled on this filesystem, "
+-			"use tune2fs.\n");
++			"use tune2fs.");
+ 
+ 	/*
+ 	 * enable delayed allocation by default

commit fd98496f467b3d26d05ab1498f41718b5ef13de5
+Author: Theodore Ts'o 
+Date:   Mon Jan 5 21:34:13 2009 -0500
+
+    jbd2: Add barrier not supported test to journal_wait_on_commit_record
+    
+    Xen doesn't report that barriers are not supported until buffer I/O is
+    reported as completed, instead of when the buffer I/O is submitted.
+    Add a check and a fallback codepath to journal_wait_on_commit_record()
+    to detect this case, so that attempts to mount ext4 filesystems on
+    LVM/devicemapper devices on Xen guests don't blow up with an "Aborting
+    journal on device XXX"; "Remounting filesystem read-only" error.
+    
+    Thanks to Andreas Sundstrom for reporting this issue.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: stable@kernel.org
+
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index ebc667bc54a8..6393fd0d804e 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -25,6 +25,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ /*
+  * Default IO end handler for temporary BJ_IO buffer_heads.
+@@ -168,12 +169,34 @@ static int journal_submit_commit_record(journal_t *journal,
+  * This function along with journal_submit_commit_record
+  * allows to write the commit record asynchronously.
+  */
+-static int journal_wait_on_commit_record(struct buffer_head *bh)
++static int journal_wait_on_commit_record(journal_t *journal,
++					 struct buffer_head *bh)
+ {
+ 	int ret = 0;
+ 
++retry:
+ 	clear_buffer_dirty(bh);
+ 	wait_on_buffer(bh);
++	if (buffer_eopnotsupp(bh) && (journal->j_flags & JBD2_BARRIER)) {
++		printk(KERN_WARNING
++		       "JBD2: wait_on_commit_record: sync failed on %s - "
++		       "disabling barriers\n", journal->j_devname);
++		spin_lock(&journal->j_state_lock);
++		journal->j_flags &= ~JBD2_BARRIER;
++		spin_unlock(&journal->j_state_lock);
++
++		lock_buffer(bh);
++		clear_buffer_dirty(bh);
++		set_buffer_uptodate(bh);
++		bh->b_end_io = journal_end_buffer_io_sync;
++
++		ret = submit_bh(WRITE_SYNC, bh);
++		if (ret) {
++			unlock_buffer(bh);
++			return ret;
++		}
++		goto retry;
++	}
+ 
+ 	if (unlikely(!buffer_uptodate(bh)))
+ 		ret = -EIO;
+@@ -799,7 +822,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 			__jbd2_journal_abort_hard(journal);
+ 	}
+ 	if (!err && !is_journal_aborted(journal))
+-		err = journal_wait_on_commit_record(cbh);
++		err = journal_wait_on_commit_record(journal, cbh);
+ 
+ 	if (err)
+ 		jbd2_journal_abort(journal, err);

commit 2a21e37e48b94388f2cc8c0392f104f5443d4bb8
+Author: Theodore Ts'o 
+Date:   Wed Nov 5 09:22:24 2008 -0500
+
+    ext4: tone down ext4_da_writepages warnings
+    
+    If the filesystem has errors, ext4_da_writepages() will return a *lot*
+    of errors, including lots and lots of stack dumps.  While it's true
+    that we are dropping user data on the floor, which is unfortunate, the
+    stack dumps aren't helpful, and they tend to obscure the true original
+    root cause of the problem.  So in the case where the filesystem has
+    aborted, return an EROFS right away.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 5120243024fb..ac97348f85b5 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2397,6 +2397,20 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 	 */
+ 	if (!mapping->nrpages || !mapping_tagged(mapping, PAGECACHE_TAG_DIRTY))
+ 		return 0;
++
++	/*
++	 * If the filesystem has aborted, it is read-only, so return
++	 * right away instead of dumping stack traces later on that
++	 * will obscure the real source of the problem.  We test
++	 * EXT4_MOUNT_ABORT instead of sb->s_flag's MS_RDONLY because
++	 * the latter could be true if the filesystem is mounted
++	 * read-only, and in that case, ext4_da_writepages should
++	 * *never* be called, so if that ever happens, we would want
++	 * the stack trace.
++	 */
++	if (unlikely(sbi->s_mount_opt & EXT4_MOUNT_ABORT))
++		return -EROFS;
++
+ 	/*
+ 	 * Make sure nr_to_write is >= sbi->s_mb_stream_request
+ 	 * This make sure small files blocks are allocated in
+@@ -2441,7 +2455,7 @@ static int ext4_da_writepages(struct address_space *mapping,
+ 		handle = ext4_journal_start(inode, needed_blocks);
+ 		if (IS_ERR(handle)) {
+ 			ret = PTR_ERR(handle);
+-			printk(KERN_EMERG "%s: jbd2_start: "
++			printk(KERN_CRIT "%s: jbd2_start: "
+ 			       "%ld pages, ino %lu; err %d\n", __func__,
+ 				wbc->nr_to_write, inode->i_ino, ret);
+ 			dump_stack();

commit 97df5d155dee478efe33b001f502e9630e1bba92
+Author: Theodore Ts'o 
+Date:   Fri Dec 12 12:41:28 2008 -0500
+
+    ext4: remove do_blk_alloc()
+    
+    The convenience function do_blk_alloc() is a static function with only
+    one caller, so fold it into ext4_new_meta_blocks() to simplify the
+    code and to make it easier to understand.
+    
+    To save more stack space, if count is a null pointer in
+    ext4_new_meta_blocks() assume that caller wanted a single block (and
+    if there is an error, no blocks were allocated).
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 98a97129fc5f..35f5f9a27722 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -666,59 +666,40 @@ int ext4_should_retry_alloc(struct super_block *sb, int *retries)
+ 	return jbd2_journal_force_commit_nested(EXT4_SB(sb)->s_journal);
+ }
+ 
+-#define EXT4_META_BLOCK 0x1
+-
+-static ext4_fsblk_t do_blk_alloc(handle_t *handle, struct inode *inode,
+-				ext4_lblk_t iblock, ext4_fsblk_t goal,
+-				unsigned long *count, int *errp, int flags)
+-{
+-	struct ext4_allocation_request ar;
+-	ext4_fsblk_t ret;
+-
+-	memset(&ar, 0, sizeof(ar));
+-	/* Fill with neighbour allocated blocks */
+-
+-	ar.inode = inode;
+-	ar.goal = goal;
+-	ar.len = *count;
+-	ar.logical = iblock;
+-
+-	if (S_ISREG(inode->i_mode) && !(flags & EXT4_META_BLOCK))
+-		/* enable in-core preallocation for data block allocation */
+-		ar.flags = EXT4_MB_HINT_DATA;
+-	else
+-		/* disable in-core preallocation for non-regular files */
+-		ar.flags = 0;
+-
+-	ret = ext4_mb_new_blocks(handle, &ar, errp);
+-	*count = ar.len;
+-	return ret;
+-}
+-
+ /*
+  * ext4_new_meta_blocks() -- allocate block for meta data (indexing) blocks
+  *
+  * @handle:             handle to this transaction
+  * @inode:              file inode
+  * @goal:               given target block(filesystem wide)
+- * @count:		total number of blocks need
++ * @count:		pointer to total number of blocks needed
+  * @errp:               error code
+  *
+- * Return 1st allocated block numberon success, *count stores total account
++ * Return 1st allocated block number on success, *count stores total account
+  * error stores in errp pointer
+  */
+ ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
+ 		ext4_fsblk_t goal, unsigned long *count, int *errp)
+ {
++	struct ext4_allocation_request ar;
+ 	ext4_fsblk_t ret;
+-	ret = do_blk_alloc(handle, inode, 0, goal,
+-				count, errp, EXT4_META_BLOCK);
++
++	memset(&ar, 0, sizeof(ar));
++	/* Fill with neighbour allocated blocks */
++	ar.inode = inode;
++	ar.goal = goal;
++	ar.len = count ? *count : 1;
++
++	ret = ext4_mb_new_blocks(handle, &ar, errp);
++	if (count)
++		*count = ar.len;
++
+ 	/*
+ 	 * Account for the allocated meta blocks
+ 	 */
+ 	if (!(*errp) && EXT4_I(inode)->i_delalloc_reserved_flag) {
+ 		spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
+-		EXT4_I(inode)->i_allocated_meta_blocks += *count;
++		EXT4_I(inode)->i_allocated_meta_blocks += ar.len;
+ 		spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+ 	}
+ 	return ret;
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index e5b169b44b4c..59401d057c69 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -189,10 +189,9 @@ ext4_ext_new_meta_block(handle_t *handle, struct inode *inode,
+ 			struct ext4_extent *ex, int *err)
+ {
+ 	ext4_fsblk_t goal, newblock;
+-	unsigned long count = 1;
+ 
+ 	goal = ext4_ext_find_goal(inode, path, le32_to_cpu(ex->ee_block));
+-	newblock = ext4_new_meta_blocks(handle, inode, goal, &count, err);
++	newblock = ext4_new_meta_blocks(handle, inode, goal, NULL, err);
+ 	return newblock;
+ }
+ 
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index f896e2c452f0..9b4a368c5728 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -689,7 +689,6 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
+ 		     struct ext4_xattr_info *i,
+ 		     struct ext4_xattr_block_find *bs)
+ {
+-	unsigned long count = 1;
+ 	struct super_block *sb = inode->i_sb;
+ 	struct buffer_head *new_bh = NULL;
+ 	struct ext4_xattr_search *s = &bs->s;
+@@ -812,7 +811,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
+ 			ext4_fsblk_t goal = ext4_group_first_block_no(sb,
+ 						EXT4_I(inode)->i_block_group);
+ 			ext4_fsblk_t block = ext4_new_meta_blocks(handle, inode,
+-						  goal, &count, &error);
++						  goal, NULL, &error);
+ 			if (error)
+ 				goto cleanup;
+ 			ea_idebug(inode, "creating block %d", block);

commit cfe82c856747b7841a3a00d591ce9ed46f579d27
+Author: Theodore Ts'o 
+Date:   Sun Dec 7 14:10:54 2008 -0500
+
+    ext4: remove ext4_new_meta_block()
+    
+    There were only two one callers of the function ext4_new_meta_block(),
+    which just a very simpler wrapper function around
+    ext4_new_meta_blocks().  Change those two functions to call
+    ext4_new_meta_blocks() directly, to save code and stack space usage.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 10ce275ebbf1..98a97129fc5f 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -724,23 +724,6 @@ ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
+ 	return ret;
+ }
+ 
+-/*
+- * ext4_new_meta_block() -- allocate block for meta data (indexing) blocks
+- *
+- * @handle:             handle to this transaction
+- * @inode:              file inode
+- * @goal:               given target block(filesystem wide)
+- * @errp:               error code
+- *
+- * Return allocated block number on success
+- */
+-ext4_fsblk_t ext4_new_meta_block(handle_t *handle, struct inode *inode,
+-		ext4_fsblk_t goal, int *errp)
+-{
+-	unsigned long count = 1;
+-	return ext4_new_meta_blocks(handle, inode, goal, &count, errp);
+-}
+-
+ /**
+  * ext4_count_free_blocks() -- count filesystem free blocks
+  * @sb:		superblock
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 74cb395e689f..ac8551e0b70a 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -998,8 +998,6 @@ extern ext4_grpblk_t ext4_block_group_offset(struct super_block *sb,
+ extern int ext4_bg_has_super(struct super_block *sb, ext4_group_t group);
+ extern unsigned long ext4_bg_num_gdb(struct super_block *sb,
+ 			ext4_group_t group);
+-extern ext4_fsblk_t ext4_new_meta_block(handle_t *handle, struct inode *inode,
+-			ext4_fsblk_t goal, int *errp);
+ extern ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
+ 			ext4_fsblk_t goal, unsigned long *count, int *errp);
+ extern int ext4_claim_free_blocks(struct ext4_sb_info *sbi, s64 nblocks);
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index ea2ce3c0ae66..e5b169b44b4c 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -189,9 +189,10 @@ ext4_ext_new_meta_block(handle_t *handle, struct inode *inode,
+ 			struct ext4_extent *ex, int *err)
+ {
+ 	ext4_fsblk_t goal, newblock;
++	unsigned long count = 1;
+ 
+ 	goal = ext4_ext_find_goal(inode, path, le32_to_cpu(ex->ee_block));
+-	newblock = ext4_new_meta_block(handle, inode, goal, err);
++	newblock = ext4_new_meta_blocks(handle, inode, goal, &count, err);
+ 	return newblock;
+ }
+ 
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 80626d516fee..f896e2c452f0 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -689,6 +689,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
+ 		     struct ext4_xattr_info *i,
+ 		     struct ext4_xattr_block_find *bs)
+ {
++	unsigned long count = 1;
+ 	struct super_block *sb = inode->i_sb;
+ 	struct buffer_head *new_bh = NULL;
+ 	struct ext4_xattr_search *s = &bs->s;
+@@ -810,8 +811,8 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
+ 			/* We need to allocate a new block */
+ 			ext4_fsblk_t goal = ext4_group_first_block_no(sb,
+ 						EXT4_I(inode)->i_block_group);
+-			ext4_fsblk_t block = ext4_new_meta_block(handle, inode,
+-							goal, &error);
++			ext4_fsblk_t block = ext4_new_meta_blocks(handle, inode,
++						  goal, &count, &error);
+ 			if (error)
+ 				goto cleanup;
+ 			ea_idebug(inode, "creating block %d", block);

commit 815a1130687ffac2c3e91513ce64aab629d6a54d
+Author: Theodore Ts'o 
+Date:   Thu Jan 1 23:59:43 2009 -0500
+
+    ext4: remove ext4_new_blocks() and call ext4_mb_new_blocks() directly
+    
+    There was only one caller of the compatibility function
+    ext4_new_blocks(), in balloc.c's ext4_alloc_blocks().  Change it to
+    call ext4_mb_new_blocks() directly, and remove ext4_new_blocks()
+    altogether.  This cleans up the code, by removing two extra functions
+    from the call chain, and hopefully saving some stack usage.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 152c390f3c3f..10ce275ebbf1 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -741,26 +741,6 @@ ext4_fsblk_t ext4_new_meta_block(handle_t *handle, struct inode *inode,
+ 	return ext4_new_meta_blocks(handle, inode, goal, &count, errp);
+ }
+ 
+-/*
+- * ext4_new_blocks() -- allocate data blocks
+- *
+- * @handle:             handle to this transaction
+- * @inode:              file inode
+- * @goal:               given target block(filesystem wide)
+- * @count:		total number of blocks need
+- * @errp:               error code
+- *
+- * Return 1st allocated block numberon success, *count stores total account
+- * error stores in errp pointer
+- */
+-
+-ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode,
+-				ext4_lblk_t iblock, ext4_fsblk_t goal,
+-				unsigned long *count, int *errp)
+-{
+-	return do_blk_alloc(handle, inode, iblock, goal, count, errp, 0);
+-}
+-
+ /**
+  * ext4_count_free_blocks() -- count filesystem free blocks
+  * @sb:		superblock
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 8370ffd2d62f..74cb395e689f 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1002,9 +1002,6 @@ extern ext4_fsblk_t ext4_new_meta_block(handle_t *handle, struct inode *inode,
+ 			ext4_fsblk_t goal, int *errp);
+ extern ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
+ 			ext4_fsblk_t goal, unsigned long *count, int *errp);
+-extern ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode,
+-					ext4_lblk_t iblock, ext4_fsblk_t goal,
+-					unsigned long *count, int *errp);
+ extern int ext4_claim_free_blocks(struct ext4_sb_info *sbi, s64 nblocks);
+ extern int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks);
+ extern void ext4_free_blocks(handle_t *handle, struct inode *inode,
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 5b088121686a..5120243024fb 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -547,6 +547,7 @@ static int ext4_alloc_blocks(handle_t *handle, struct inode *inode,
+ 				int indirect_blks, int blks,
+ 				ext4_fsblk_t new_blocks[4], int *err)
+ {
++	struct ext4_allocation_request ar;
+ 	int target, i;
+ 	unsigned long count = 0, blk_allocated = 0;
+ 	int index = 0;
+@@ -595,10 +596,17 @@ static int ext4_alloc_blocks(handle_t *handle, struct inode *inode,
+ 	if (!target)
+ 		goto allocated;
+ 	/* Now allocate data blocks */
+-	count = target;
+-	/* allocating blocks for data blocks */
+-	current_block = ext4_new_blocks(handle, inode, iblock,
+-						goal, &count, err);
++	memset(&ar, 0, sizeof(ar));
++	ar.inode = inode;
++	ar.goal = goal;
++	ar.len = target;
++	ar.logical = iblock;
++	if (S_ISREG(inode->i_mode))
++		/* enable in-core preallocation only for regular files */
++		ar.flags = EXT4_MB_HINT_DATA;
++
++	current_block = ext4_mb_new_blocks(handle, &ar, err);
++
+ 	if (*err && (target == blks)) {
+ 		/*
+ 		 * if the allocation failed and we didn't allocate
+@@ -614,7 +622,7 @@ static int ext4_alloc_blocks(handle_t *handle, struct inode *inode,
+ 		 */
+ 			new_blocks[index] = current_block;
+ 		}
+-		blk_allocated += count;
++		blk_allocated += ar.len;
+ 	}
+ allocated:
+ 	/* total number of blocks allocated for direct blocks */

commit 8e1a4857cd92e32e642b3e7184c7f6bf85c96e2e
+Author: Theodore Ts'o 
+Date:   Tue Jan 6 14:53:06 2009 -0500
+
+    Update Documentation/filesystems/ext4.txt
+    
+    Fix paragraph with recommendations on how to tune ext4 for benchmarks.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
+index 174eaff7ded9..f75ab101c00a 100644
+--- a/Documentation/filesystems/ext4.txt
++++ b/Documentation/filesystems/ext4.txt
+@@ -58,13 +58,22 @@ Note: More extensive information for getting started with ext4 can be
+ 
+ 	# mount -t ext4 /dev/hda1 /wherever
+ 
+-  - When comparing performance with other filesystems, remember that
+-    ext3/4 by default offers higher data integrity guarantees than most.
+-    So when comparing with a metadata-only journalling filesystem, such
+-    as ext3, use `mount -o data=writeback'.  And you might as well use
+-    `mount -o nobh' too along with it.  Making the journal larger than
+-    the mke2fs default often helps performance with metadata-intensive
+-    workloads.
++  - When comparing performance with other filesystems, it's always
++    important to try multiple workloads; very often a subtle change in a
++    workload parameter can completely change the ranking of which
++    filesystems do well compared to others.  When comparing versus ext3,
++    note that ext4 enables write barriers by default, while ext3 does
++    not enable write barriers by default.  So it is useful to use
++    explicitly specify whether barriers are enabled or not when via the
++    '-o barriers=[0|1]' mount option for both ext3 and ext4 filesystems
++    for a fair comparison.  When tuning ext3 for best benchmark numbers,
++    it is often worthwhile to try changing the data journaling mode; '-o
++    data=writeback,nobh' can be faster for some workloads.  (Note
++    however that running mounted with data=writeback can potentially
++    leave stale data exposed in recently written files in case of an
++    unclean shutdown, which could be a security exposure in some
++    situations.)  Configuring the filesystem with a large journal can
++    also be helpful for metadata-intensive workloads.
+ 
+ 2. Features
+ ===========
+@@ -74,7 +83,7 @@ Note: More extensive information for getting started with ext4 can be
+ * ability to use filesystems > 16TB (e2fsprogs support not available yet)
+ * extent format reduces metadata overhead (RAM, IO for access, transactions)
+ * extent format more robust in face of on-disk corruption due to magics,
+-* internal redunancy in tree
++* internal redundancy in tree
+ * improved file allocation (multi-block alloc)
+ * fix 32000 subdirectory limit
+ * nsec timestamps for mtime, atime, ctime, create time
+@@ -116,6 +125,12 @@ grouping of bitmaps and inode tables.  Some test results available here:
+ When mounting an ext4 filesystem, the following option are accepted:
+ (*) == default
+ 
++ro                   	Mount filesystem read only. Note that ext4 will
++                     	replay the journal (and thus write to the
++                     	partition) even when mounted "read only". The
++                     	mount options "ro,noload" can be used to prevent
++		     	writes to the filesystem.
++
+ extents		(*)	ext4 will use extents to address file data.  The
+ 			file system will no longer be mountable by ext3.
+ 
+@@ -144,7 +159,11 @@ journal_dev=devnum	When the external journal device's major/minor numbers
+ 			identified through its new major/minor numbers encoded
+ 			in devnum.
+ 
+-noload			Don't load the journal on mounting.
++noload			Don't load the journal on mounting.  Note that
++                     	if the filesystem was not unmounted cleanly,
++                     	skipping the journal replay will lead to the
++                     	filesystem containing inconsistencies that can
++                     	lead to any number of problems.
+ 
+ data=journal		All data are committed into the journal prior to being
+ 			written into the main file system.
+@@ -219,9 +238,12 @@ minixdf			Make 'df' act like Minix.
+ 
+ debug			Extra debugging information is sent to syslog.
+ 
+-errors=remount-ro(*)	Remount the filesystem read-only on an error.
++errors=remount-ro	Remount the filesystem read-only on an error.
+ errors=continue		Keep going on a filesystem error.
+ errors=panic		Panic and halt the machine if an error occurs.
++                        (These mount options override the errors behavior
++                        specified in the superblock, which can be configured
++                        using tune2fs)
+ 
+ data_err=ignore(*)	Just print an error message if an error occurs
+ 			in a file data buffer in ordered mode.

commit 59e315b4c410b00a9acd0f24a00dbadbe81ce692
+Author: Theodore Ts'o 
+Date:   Sat Dec 6 16:58:39 2008 -0500
+
+    ext3/4: Fix loop index in do_split() so it is signed
+    
+    This fixes a gcc warning but it doesn't appear able to result in a
+    failure, since the primary way the loop is exited is the first
+    conditional in the for loop, and at least for a consistent filesystem,
+    the signed/unsigned should in practice never be exposed.
+    
+    Signed-off-by: Roel Kluin 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
+index 287b304d42a7..2c2d700c1ccf 100644
+--- a/fs/ext3/namei.c
++++ b/fs/ext3/namei.c
+@@ -1161,9 +1161,9 @@ static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
+ 	u32 hash2;
+ 	struct dx_map_entry *map;
+ 	char *data1 = (*bh)->b_data, *data2;
+-	unsigned split, move, size, i;
++	unsigned split, move, size;
+ 	struct ext3_dir_entry_2 *de = NULL, *de2;
+-	int	err = 0;
++	int	err = 0, i;
+ 
+ 	bh2 = ext3_append (handle, dir, &newblock, &err);
+ 	if (!(bh2)) {
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 315858db8078..84a68ae623c1 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1171,9 +1171,9 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
+ 	u32 hash2;
+ 	struct dx_map_entry *map;
+ 	char *data1 = (*bh)->b_data, *data2;
+-	unsigned split, move, size, i;
++	unsigned split, move, size;
+ 	struct ext4_dir_entry_2 *de = NULL, *de2;
+-	int	err = 0;
++	int	err = 0, i;
+ 
+ 	bh2 = ext4_append (handle, dir, &newblock, &err);
+ 	if (!(bh2)) {

commit 14ce0cb411c88681ab8f3a4c9caa7f42e97a3184
+Author: Theodore Ts'o 
+Date:   Mon Nov 3 18:10:55 2008 -0500
+
+    ext4: wait on all pending commits in ext4_sync_fs()
+    
+    In ext4_sync_fs, we only wait for a commit to finish if we started it,
+    but there may be one already in progress which will not be synced.
+    
+    In the case of a data=ordered umount with pending long symlinks which
+    are delayed due to a long list of other I/O on the backing block
+    device, this causes the buffer associated with the long symlinks to
+    not be moved to the inode dirty list in the second phase of
+    fsync_super.  Then, before they can be dirtied again, kjournald exits,
+    seeing the UMOUNT flag and the dirty pages are never written to the
+    backing block device, causing long symlink corruption and exposing new
+    or previously freed block data to userspace.
+    
+    To ensure all commits are synced, we flush all journal commits now
+    when sync_fs'ing ext4.
+    
+    Signed-off-by: Arthur Jones 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Eric Sandeen 
+    Cc: 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index e27acd18b4b0..e4a241c65dbe 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2884,12 +2884,9 @@ int ext4_force_commit(struct super_block *sb)
+ /*
+  * Ext4 always journals updates to the superblock itself, so we don't
+  * have to propagate any other updates to the superblock on disk at this
+- * point.  Just start an async writeback to get the buffers on their way
+- * to the disk.
+- *
+- * This implicitly triggers the writebehind on sync().
++ * point.  (We can probably nuke this function altogether, and remove
++ * any mention to sb->s_dirt in all of fs/ext4; eventual cleanup...)
+  */
+-
+ static void ext4_write_super(struct super_block *sb)
+ {
+ 	if (mutex_trylock(&sb->s_lock) != 0)
+@@ -2899,15 +2896,15 @@ static void ext4_write_super(struct super_block *sb)
+ 
+ static int ext4_sync_fs(struct super_block *sb, int wait)
+ {
+-	tid_t target;
++	int ret = 0;
+ 
+ 	trace_mark(ext4_sync_fs, "dev %s wait %d", sb->s_id, wait);
+ 	sb->s_dirt = 0;
+-	if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, &target)) {
+-		if (wait)
+-			jbd2_log_wait_commit(EXT4_SB(sb)->s_journal, target);
+-	}
+-	return 0;
++	if (wait)
++		ret = ext4_force_commit(sb);
++	else
++		jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, NULL);
++	return ret;
+ }
+ 
+ /*

commit 8c3f25d8950c3e9fe6c9849f88679b3f2a071550
+Author: Theodore Ts'o 
+Date:   Thu Nov 6 22:38:07 2008 -0500
+
+    jbd2: don't give up looking for space so easily in __jbd2_log_wait_for_space
+    
+    Commit 23f8b79e introducd a regression because it assumed that if
+    there were no transactions ready to be checkpointed, that no progress
+    could be made on making space available in the journal, and so the
+    journal should be aborted.  This assumption is false; it could be the
+    case that simply calling jbd2_cleanup_journal_tail() will recover the
+    necessary space, or, for small journals, the currently committing
+    transaction could be responsible for chewing up the required space in
+    the log, so we need to wait for the currently committing transaction
+    to finish before trying to force a checkpoint operation.
+    
+    This patch fixes a bug reported by Mihai Harpau at:
+    https://bugzilla.redhat.com/show_bug.cgi?id=469582
+    
+    This patch fixes a bug reported by François Valenduc at:
+    http://bugzilla.kernel.org/show_bug.cgi?id=11840
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Duane Griffin 
+    Cc: Toshiyuki Okajima 
+
+diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
+index 9203c3332f17..9497718fe920 100644
+--- a/fs/jbd2/checkpoint.c
++++ b/fs/jbd2/checkpoint.c
+@@ -116,7 +116,7 @@ static int __try_to_free_cp_buf(struct journal_head *jh)
+  */
+ void __jbd2_log_wait_for_space(journal_t *journal)
+ {
+-	int nblocks;
++	int nblocks, space_left;
+ 	assert_spin_locked(&journal->j_state_lock);
+ 
+ 	nblocks = jbd_space_needed(journal);
+@@ -129,25 +129,43 @@ void __jbd2_log_wait_for_space(journal_t *journal)
+ 		/*
+ 		 * Test again, another process may have checkpointed while we
+ 		 * were waiting for the checkpoint lock. If there are no
+-		 * outstanding transactions there is nothing to checkpoint and
+-		 * we can't make progress. Abort the journal in this case.
++		 * transactions ready to be checkpointed, try to recover
++		 * journal space by calling cleanup_journal_tail(), and if
++		 * that doesn't work, by waiting for the currently committing
++		 * transaction to complete.  If there is absolutely no way
++		 * to make progress, this is either a BUG or corrupted
++		 * filesystem, so abort the journal and leave a stack
++		 * trace for forensic evidence.
+ 		 */
+ 		spin_lock(&journal->j_state_lock);
+ 		spin_lock(&journal->j_list_lock);
+ 		nblocks = jbd_space_needed(journal);
+-		if (__jbd2_log_space_left(journal) < nblocks) {
++		space_left = __jbd2_log_space_left(journal);
++		if (space_left < nblocks) {
+ 			int chkpt = journal->j_checkpoint_transactions != NULL;
++			tid_t tid = 0;
+ 
++			if (journal->j_committing_transaction)
++				tid = journal->j_committing_transaction->t_tid;
+ 			spin_unlock(&journal->j_list_lock);
+ 			spin_unlock(&journal->j_state_lock);
+ 			if (chkpt) {
+ 				jbd2_log_do_checkpoint(journal);
++			} else if (jbd2_cleanup_journal_tail(journal) == 0) {
++				/* We were able to recover space; yay! */
++				;
++			} else if (tid) {
++				jbd2_log_wait_commit(journal, tid);
+ 			} else {
+-				printk(KERN_ERR "%s: no transactions\n",
+-				       __func__);
++				printk(KERN_ERR "%s: needed %d blocks and "
++				       "only had %d space available\n",
++				       __func__, nblocks, space_left);
++				printk(KERN_ERR "%s: no way to get more "
++				       "journal space in %s\n", __func__,
++				       journal->j_devname);
++				WARN_ON(1);
+ 				jbd2_journal_abort(journal, 0);
+ 			}
+-
+ 			spin_lock(&journal->j_state_lock);
+ 		} else {
+ 			spin_unlock(&journal->j_list_lock);

commit e219cca082f52e7dfea41f3be264b7b5eb204227
+Author: Theodore Ts'o 
+Date:   Thu Nov 6 22:37:59 2008 -0500
+
+    jbd: don't give up looking for space so easily in __log_wait_for_space
+    
+    Commit be07c4ed introducd a regression because it assumed that if
+    there were no transactions ready to be checkpointed, that no progress
+    could be made on making space available in the journal, and so the
+    journal should be aborted.  This assumption is false; it could be the
+    case that simply calling cleanup_journal_tail() will recover the
+    necessary space, or, for small journals, the currently committing
+    transaction could be responsible for chewing up the required space in
+    the log, so we need to wait for the currently committing transaction
+    to finish before trying to force a checkpoint operation.
+    
+    This patch fixes the bug reported by Meelis Roos at:
+    http://bugzilla.kernel.org/show_bug.cgi?id=11937
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Duane Griffin 
+    Cc: Toshiyuki Okajima 
+
+diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c
+index 1bd8d4acc6f2..61f32f3868cd 100644
+--- a/fs/jbd/checkpoint.c
++++ b/fs/jbd/checkpoint.c
+@@ -115,7 +115,7 @@ static int __try_to_free_cp_buf(struct journal_head *jh)
+  */
+ void __log_wait_for_space(journal_t *journal)
+ {
+-	int nblocks;
++	int nblocks, space_left;
+ 	assert_spin_locked(&journal->j_state_lock);
+ 
+ 	nblocks = jbd_space_needed(journal);
+@@ -128,25 +128,42 @@ void __log_wait_for_space(journal_t *journal)
+ 		/*
+ 		 * Test again, another process may have checkpointed while we
+ 		 * were waiting for the checkpoint lock. If there are no
+-		 * outstanding transactions there is nothing to checkpoint and
+-		 * we can't make progress. Abort the journal in this case.
++		 * transactions ready to be checkpointed, try to recover
++		 * journal space by calling cleanup_journal_tail(), and if
++		 * that doesn't work, by waiting for the currently committing
++		 * transaction to complete.  If there is absolutely no way
++		 * to make progress, this is either a BUG or corrupted
++		 * filesystem, so abort the journal and leave a stack
++		 * trace for forensic evidence.
+ 		 */
+ 		spin_lock(&journal->j_state_lock);
+ 		spin_lock(&journal->j_list_lock);
+ 		nblocks = jbd_space_needed(journal);
+-		if (__log_space_left(journal) < nblocks) {
++		space_left = __log_space_left(journal);
++		if (space_left < nblocks) {
+ 			int chkpt = journal->j_checkpoint_transactions != NULL;
++			tid_t tid = 0;
+ 
++			if (journal->j_committing_transaction)
++				tid = journal->j_committing_transaction->t_tid;
+ 			spin_unlock(&journal->j_list_lock);
+ 			spin_unlock(&journal->j_state_lock);
+ 			if (chkpt) {
+ 				log_do_checkpoint(journal);
++			} else if (cleanup_journal_tail(journal) == 0) {
++				/* We were able to recover space; yay! */
++				;
++			} else if (tid) {
++				log_wait_commit(journal, tid);
+ 			} else {
+-				printk(KERN_ERR "%s: no transactions\n",
+-				       __func__);
++				printk(KERN_ERR "%s: needed %d blocks and "
++				       "only had %d space available\n",
++				       __func__, nblocks, space_left);
++				printk(KERN_ERR "%s: no way to get more "
++				       "journal space\n", __func__);
++				WARN_ON(1);
+ 				journal_abort(journal, 0);
+ 			}
+-
+ 			spin_lock(&journal->j_state_lock);
+ 		} else {
+ 			spin_unlock(&journal->j_list_lock);

commit f99b25897a86fcfff9140396a97261ae65fed872
+Author: Theodore Ts'o 
+Date:   Tue Oct 28 13:21:44 2008 -0400
+
+    ext4: Add support for non-native signed/unsigned htree hash algorithms
+    
+    The original ext3 hash algorithms assumed that variables of type char
+    were signed, as God and K&R intended.  Unfortunately, this assumption
+    is not true on some architectures.  Userspace support for marking
+    filesystems with non-native signed/unsigned chars was added two years
+    ago, but the kernel-side support was never added (until now).
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index b0537c827024..8370ffd2d62f 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -891,6 +891,9 @@ static inline __le16 ext4_rec_len_to_disk(unsigned len)
+ #define DX_HASH_LEGACY		0
+ #define DX_HASH_HALF_MD4	1
+ #define DX_HASH_TEA		2
++#define DX_HASH_LEGACY_UNSIGNED	3
++#define DX_HASH_HALF_MD4_UNSIGNED	4
++#define DX_HASH_TEA_UNSIGNED		5
+ 
+ #ifdef __KERNEL__
+ 
+diff --git a/fs/ext4/ext4_sb.h b/fs/ext4/ext4_sb.h
+index b21f16713db0..ad7ea09baa72 100644
+--- a/fs/ext4/ext4_sb.h
++++ b/fs/ext4/ext4_sb.h
+@@ -57,6 +57,7 @@ struct ext4_sb_info {
+ 	u32 s_next_generation;
+ 	u32 s_hash_seed[4];
+ 	int s_def_hash_version;
++	int s_hash_unsigned;	/* 3 if hash should be signed, 0 if not */
+ 	struct percpu_counter s_freeblocks_counter;
+ 	struct percpu_counter s_freeinodes_counter;
+ 	struct percpu_counter s_dirs_counter;
+diff --git a/fs/ext4/hash.c b/fs/ext4/hash.c
+index 556ca8eba3db..ac8f168c8ab4 100644
+--- a/fs/ext4/hash.c
++++ b/fs/ext4/hash.c
+@@ -35,23 +35,71 @@ static void TEA_transform(__u32 buf[4], __u32 const in[])
+ 
+ 
+ /* The old legacy hash */
+-static __u32 dx_hack_hash(const char *name, int len)
++static __u32 dx_hack_hash_unsigned(const char *name, int len)
+ {
+-	__u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
++	__u32 hash, hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
++	const unsigned char *ucp = (const unsigned char *) name;
++
++	while (len--) {
++		hash = hash1 + (hash0 ^ (((int) *ucp++) * 7152373));
++
++		if (hash & 0x80000000)
++			hash -= 0x7fffffff;
++		hash1 = hash0;
++		hash0 = hash;
++	}
++	return hash0 << 1;
++}
++
++static __u32 dx_hack_hash_signed(const char *name, int len)
++{
++	__u32 hash, hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
++	const signed char *scp = (const signed char *) name;
++
+ 	while (len--) {
+-		__u32 hash = hash1 + (hash0 ^ (*name++ * 7152373));
++		hash = hash1 + (hash0 ^ (((int) *scp++) * 7152373));
+ 
+-		if (hash & 0x80000000) hash -= 0x7fffffff;
++		if (hash & 0x80000000)
++			hash -= 0x7fffffff;
+ 		hash1 = hash0;
+ 		hash0 = hash;
+ 	}
+-	return (hash0 << 1);
++	return hash0 << 1;
++}
++
++static void str2hashbuf_signed(const char *msg, int len, __u32 *buf, int num)
++{
++	__u32	pad, val;
++	int	i;
++	const signed char *scp = (const signed char *) msg;
++
++	pad = (__u32)len | ((__u32)len << 8);
++	pad |= pad << 16;
++
++	val = pad;
++	if (len > num*4)
++		len = num * 4;
++	for (i = 0; i < len; i++) {
++		if ((i % 4) == 0)
++			val = pad;
++		val = ((int) scp[i]) + (val << 8);
++		if ((i % 4) == 3) {
++			*buf++ = val;
++			val = pad;
++			num--;
++		}
++	}
++	if (--num >= 0)
++		*buf++ = val;
++	while (--num >= 0)
++		*buf++ = pad;
+ }
+ 
+-static void str2hashbuf(const char *msg, int len, __u32 *buf, int num)
++static void str2hashbuf_unsigned(const char *msg, int len, __u32 *buf, int num)
+ {
+ 	__u32	pad, val;
+ 	int	i;
++	const unsigned char *ucp = (const unsigned char *) msg;
+ 
+ 	pad = (__u32)len | ((__u32)len << 8);
+ 	pad |= pad << 16;
+@@ -62,7 +110,7 @@ static void str2hashbuf(const char *msg, int len, __u32 *buf, int num)
+ 	for (i = 0; i < len; i++) {
+ 		if ((i % 4) == 0)
+ 			val = pad;
+-		val = msg[i] + (val << 8);
++		val = ((int) ucp[i]) + (val << 8);
+ 		if ((i % 4) == 3) {
+ 			*buf++ = val;
+ 			val = pad;
+@@ -95,6 +143,8 @@ int ext4fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo)
+ 	const char	*p;
+ 	int		i;
+ 	__u32		in[8], buf[4];
++	void		(*str2hashbuf)(const char *, int, __u32 *, int) =
++				str2hashbuf_signed;
+ 
+ 	/* Initialize the default seed for the hash checksum functions */
+ 	buf[0] = 0x67452301;
+@@ -113,13 +163,18 @@ int ext4fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo)
+ 	}
+ 
+ 	switch (hinfo->hash_version) {
++	case DX_HASH_LEGACY_UNSIGNED:
++		hash = dx_hack_hash_unsigned(name, len);
++		break;
+ 	case DX_HASH_LEGACY:
+-		hash = dx_hack_hash(name, len);
++		hash = dx_hack_hash_signed(name, len);
+ 		break;
++	case DX_HASH_HALF_MD4_UNSIGNED:
++		str2hashbuf = str2hashbuf_unsigned;
+ 	case DX_HASH_HALF_MD4:
+ 		p = name;
+ 		while (len > 0) {
+-			str2hashbuf(p, len, in, 8);
++			(*str2hashbuf)(p, len, in, 8);
+ 			half_md4_transform(buf, in);
+ 			len -= 32;
+ 			p += 32;
+@@ -127,10 +182,12 @@ int ext4fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo)
+ 		minor_hash = buf[2];
+ 		hash = buf[1];
+ 		break;
++	case DX_HASH_TEA_UNSIGNED:
++		str2hashbuf = str2hashbuf_unsigned;
+ 	case DX_HASH_TEA:
+ 		p = name;
+ 		while (len > 0) {
+-			str2hashbuf(p, len, in, 4);
++			(*str2hashbuf)(p, len, in, 4);
+ 			TEA_transform(buf, in);
+ 			len -= 16;
+ 			p += 16;
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 9fd2a5e1be4d..315858db8078 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -372,6 +372,8 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
+ 		goto fail;
+ 	}
+ 	hinfo->hash_version = root->info.hash_version;
++	if (hinfo->hash_version <= DX_HASH_TEA)
++		hinfo->hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned;
+ 	hinfo->seed = EXT4_SB(dir->i_sb)->s_hash_seed;
+ 	if (d_name)
+ 		ext4fs_dirhash(d_name->name, d_name->len, hinfo);
+@@ -641,6 +643,9 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
+ 	dir = dir_file->f_path.dentry->d_inode;
+ 	if (!(EXT4_I(dir)->i_flags & EXT4_INDEX_FL)) {
+ 		hinfo.hash_version = EXT4_SB(dir->i_sb)->s_def_hash_version;
++		if (hinfo.hash_version <= DX_HASH_TEA)
++			hinfo.hash_version +=
++				EXT4_SB(dir->i_sb)->s_hash_unsigned;
+ 		hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed;
+ 		count = htree_dirblock_to_tree(dir_file, dir, 0, &hinfo,
+ 					       start_hash, start_minor_hash);
+@@ -1408,6 +1413,8 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
+ 
+ 	/* Initialize as for dx_probe */
+ 	hinfo.hash_version = root->info.hash_version;
++	if (hinfo.hash_version <= DX_HASH_TEA)
++		hinfo.hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned;
+ 	hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed;
+ 	ext4fs_dirhash(name, namelen, &hinfo);
+ 	frame = frames;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 04158ad74dbb..08fc86a358d3 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2118,6 +2118,18 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	for (i = 0; i < 4; i++)
+ 		sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
+ 	sbi->s_def_hash_version = es->s_def_hash_version;
++	i = le32_to_cpu(es->s_flags);
++	if (i & EXT2_FLAGS_UNSIGNED_HASH)
++		sbi->s_hash_unsigned = 3;
++	else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) {
++#ifdef __CHAR_UNSIGNED__
++		es->s_flags |= cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH);
++		sbi->s_hash_unsigned = 3;
++#else
++		es->s_flags |= cpu_to_le32(EXT2_FLAGS_SIGNED_HASH);
++#endif
++		sb->s_dirt = 1;
++	}
+ 
+ 	if (sbi->s_blocks_per_group > blocksize * 8) {
+ 		printk(KERN_ERR

commit 5e1f8c9e20a92743eefc9a82c2db835213905e26
+Author: Theodore Ts'o 
+Date:   Tue Oct 28 13:21:55 2008 -0400
+
+    ext3: Add support for non-native signed/unsigned htree hash algorithms
+    
+    The original ext3 hash algorithms assumed that variables of type char
+    were signed, as God and K&R intended.  Unfortunately, this assumption
+    is not true on some architectures.  Userspace support for marking
+    filesystems with non-native signed/unsigned chars was added two years
+    ago, but the kernel-side support was never added (until now).
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: akpm@linux-foundation.org
+    Cc: linux-kernel@vger.kernel.org
+
+diff --git a/fs/ext3/hash.c b/fs/ext3/hash.c
+index c30e149fbd2e..7d215b4d4f2e 100644
+--- a/fs/ext3/hash.c
++++ b/fs/ext3/hash.c
+@@ -35,23 +35,71 @@ static void TEA_transform(__u32 buf[4], __u32 const in[])
+ 
+ 
+ /* The old legacy hash */
+-static __u32 dx_hack_hash (const char *name, int len)
++static __u32 dx_hack_hash_unsigned(const char *name, int len)
+ {
+-	__u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
++	__u32 hash, hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
++	const unsigned char *ucp = (const unsigned char *) name;
++
++	while (len--) {
++		hash = hash1 + (hash0 ^ (((int) *ucp++) * 7152373));
++
++		if (hash & 0x80000000)
++			hash -= 0x7fffffff;
++		hash1 = hash0;
++		hash0 = hash;
++	}
++	return hash0 << 1;
++}
++
++static __u32 dx_hack_hash_signed(const char *name, int len)
++{
++	__u32 hash, hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
++	const signed char *scp = (const signed char *) name;
++
+ 	while (len--) {
+-		__u32 hash = hash1 + (hash0 ^ (*name++ * 7152373));
++		hash = hash1 + (hash0 ^ (((int) *scp++) * 7152373));
+ 
+-		if (hash & 0x80000000) hash -= 0x7fffffff;
++		if (hash & 0x80000000)
++			hash -= 0x7fffffff;
+ 		hash1 = hash0;
+ 		hash0 = hash;
+ 	}
+-	return (hash0 << 1);
++	return hash0 << 1;
+ }
+ 
+-static void str2hashbuf(const char *msg, int len, __u32 *buf, int num)
++static void str2hashbuf_signed(const char *msg, int len, __u32 *buf, int num)
+ {
+ 	__u32	pad, val;
+ 	int	i;
++	const signed char *scp = (const signed char *) msg;
++
++	pad = (__u32)len | ((__u32)len << 8);
++	pad |= pad << 16;
++
++	val = pad;
++	if (len > num*4)
++		len = num * 4;
++	for (i = 0; i < len; i++) {
++		if ((i % 4) == 0)
++			val = pad;
++		val = ((int) scp[i]) + (val << 8);
++		if ((i % 4) == 3) {
++			*buf++ = val;
++			val = pad;
++			num--;
++		}
++	}
++	if (--num >= 0)
++		*buf++ = val;
++	while (--num >= 0)
++		*buf++ = pad;
++}
++
++static void str2hashbuf_unsigned(const char *msg, int len, __u32 *buf, int num)
++{
++	__u32	pad, val;
++	int	i;
++	const unsigned char *ucp = (const unsigned char *) msg;
+ 
+ 	pad = (__u32)len | ((__u32)len << 8);
+ 	pad |= pad << 16;
+@@ -62,7 +110,7 @@ static void str2hashbuf(const char *msg, int len, __u32 *buf, int num)
+ 	for (i=0; i < len; i++) {
+ 		if ((i % 4) == 0)
+ 			val = pad;
+-		val = msg[i] + (val << 8);
++		val = ((int) ucp[i]) + (val << 8);
+ 		if ((i % 4) == 3) {
+ 			*buf++ = val;
+ 			val = pad;
+@@ -95,6 +143,8 @@ int ext3fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo)
+ 	const char	*p;
+ 	int		i;
+ 	__u32		in[8], buf[4];
++	void		(*str2hashbuf)(const char *, int, __u32 *, int) =
++				str2hashbuf_signed;
+ 
+ 	/* Initialize the default seed for the hash checksum functions */
+ 	buf[0] = 0x67452301;
+@@ -113,13 +163,18 @@ int ext3fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo)
+ 	}
+ 
+ 	switch (hinfo->hash_version) {
++	case DX_HASH_LEGACY_UNSIGNED:
++		hash = dx_hack_hash_unsigned(name, len);
++		break;
+ 	case DX_HASH_LEGACY:
+-		hash = dx_hack_hash(name, len);
++		hash = dx_hack_hash_signed(name, len);
+ 		break;
++	case DX_HASH_HALF_MD4_UNSIGNED:
++		str2hashbuf = str2hashbuf_unsigned;
+ 	case DX_HASH_HALF_MD4:
+ 		p = name;
+ 		while (len > 0) {
+-			str2hashbuf(p, len, in, 8);
++			(*str2hashbuf)(p, len, in, 8);
+ 			half_md4_transform(buf, in);
+ 			len -= 32;
+ 			p += 32;
+@@ -127,10 +182,12 @@ int ext3fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo)
+ 		minor_hash = buf[2];
+ 		hash = buf[1];
+ 		break;
++	case DX_HASH_TEA_UNSIGNED:
++		str2hashbuf = str2hashbuf_unsigned;
+ 	case DX_HASH_TEA:
+ 		p = name;
+ 		while (len > 0) {
+-			str2hashbuf(p, len, in, 4);
++			(*str2hashbuf)(p, len, in, 4);
+ 			TEA_transform(buf, in);
+ 			len -= 16;
+ 			p += 16;
+diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
+index 1dd2abe6313e..287b304d42a7 100644
+--- a/fs/ext3/namei.c
++++ b/fs/ext3/namei.c
+@@ -368,6 +368,8 @@ dx_probe(struct qstr *entry, struct inode *dir,
+ 		goto fail;
+ 	}
+ 	hinfo->hash_version = root->info.hash_version;
++	if (hinfo->hash_version <= DX_HASH_TEA)
++		hinfo->hash_version += EXT3_SB(dir->i_sb)->s_hash_unsigned;
+ 	hinfo->seed = EXT3_SB(dir->i_sb)->s_hash_seed;
+ 	if (entry)
+ 		ext3fs_dirhash(entry->name, entry->len, hinfo);
+@@ -636,6 +638,9 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash,
+ 	dir = dir_file->f_path.dentry->d_inode;
+ 	if (!(EXT3_I(dir)->i_flags & EXT3_INDEX_FL)) {
+ 		hinfo.hash_version = EXT3_SB(dir->i_sb)->s_def_hash_version;
++		if (hinfo.hash_version <= DX_HASH_TEA)
++			hinfo.hash_version +=
++				EXT3_SB(dir->i_sb)->s_hash_unsigned;
+ 		hinfo.seed = EXT3_SB(dir->i_sb)->s_hash_seed;
+ 		count = htree_dirblock_to_tree(dir_file, dir, 0, &hinfo,
+ 					       start_hash, start_minor_hash);
+@@ -1398,6 +1403,8 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
+ 
+ 	/* Initialize as for dx_probe */
+ 	hinfo.hash_version = root->info.hash_version;
++	if (hinfo.hash_version <= DX_HASH_TEA)
++		hinfo.hash_version += EXT3_SB(dir->i_sb)->s_hash_unsigned;
+ 	hinfo.seed = EXT3_SB(dir->i_sb)->s_hash_seed;
+ 	ext3fs_dirhash(name, namelen, &hinfo);
+ 	frame = frames;
+diff --git a/fs/ext3/super.c b/fs/ext3/super.c
+index f6c94f232ec1..541d5e4f7f6e 100644
+--- a/fs/ext3/super.c
++++ b/fs/ext3/super.c
+@@ -1744,6 +1744,18 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
+ 	for (i=0; i < 4; i++)
+ 		sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
+ 	sbi->s_def_hash_version = es->s_def_hash_version;
++	i = le32_to_cpu(es->s_flags);
++	if (i & EXT2_FLAGS_UNSIGNED_HASH)
++		sbi->s_hash_unsigned = 3;
++	else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) {
++#ifdef __CHAR_UNSIGNED__
++		es->s_flags |= cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH);
++		sbi->s_hash_unsigned = 3;
++#else
++		es->s_flags |= cpu_to_le32(EXT2_FLAGS_SIGNED_HASH);
++#endif
++		sb->s_dirt = 1;
++	}
+ 
+ 	if (sbi->s_blocks_per_group > blocksize * 8) {
+ 		printk (KERN_ERR
+diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
+index d14f02918483..9004794a35fe 100644
+--- a/include/linux/ext3_fs.h
++++ b/include/linux/ext3_fs.h
+@@ -353,6 +353,13 @@ struct ext3_inode {
+ #define	EXT3_ERROR_FS			0x0002	/* Errors detected */
+ #define	EXT3_ORPHAN_FS			0x0004	/* Orphans being recovered */
+ 
++/*
++ * Misc. filesystem flags
++ */
++#define EXT2_FLAGS_SIGNED_HASH		0x0001  /* Signed dirhash in use */
++#define EXT2_FLAGS_UNSIGNED_HASH	0x0002  /* Unsigned dirhash in use */
++#define EXT2_FLAGS_TEST_FILESYS		0x0004	/* to test development code */
++
+ /*
+  * Mount flags
+  */
+@@ -489,7 +496,23 @@ struct ext3_super_block {
+ 	__u16	s_reserved_word_pad;
+ 	__le32	s_default_mount_opts;
+ 	__le32	s_first_meta_bg;	/* First metablock block group */
+-	__u32	s_reserved[190];	/* Padding to the end of the block */
++	__le32	s_mkfs_time;		/* When the filesystem was created */
++	__le32	s_jnl_blocks[17];	/* Backup of the journal inode */
++	/* 64bit support valid if EXT4_FEATURE_COMPAT_64BIT */
++/*150*/	__le32	s_blocks_count_hi;	/* Blocks count */
++	__le32	s_r_blocks_count_hi;	/* Reserved blocks count */
++	__le32	s_free_blocks_count_hi;	/* Free blocks count */
++	__le16	s_min_extra_isize;	/* All inodes have at least # bytes */
++	__le16	s_want_extra_isize; 	/* New inodes should reserve # bytes */
++	__le32	s_flags;		/* Miscellaneous flags */
++	__le16  s_raid_stride;		/* RAID stride */
++	__le16  s_mmp_interval;         /* # seconds to wait in MMP checking */
++	__le64  s_mmp_block;            /* Block for multi-mount protection */
++	__le32  s_raid_stripe_width;    /* blocks on all data disks (N*stride)*/
++	__u8	s_log_groups_per_flex;  /* FLEX_BG group size */
++	__u8	s_reserved_char_pad2;
++	__le16  s_reserved_pad;
++	__u32   s_reserved[162];        /* Padding to the end of the block */
+ };
+ 
+ #ifdef __KERNEL__
+@@ -694,6 +717,9 @@ static inline __le16 ext3_rec_len_to_disk(unsigned len)
+ #define DX_HASH_LEGACY		0
+ #define DX_HASH_HALF_MD4	1
+ #define DX_HASH_TEA		2
++#define DX_HASH_LEGACY_UNSIGNED	3
++#define DX_HASH_HALF_MD4_UNSIGNED	4
++#define DX_HASH_TEA_UNSIGNED		5
+ 
+ #ifdef __KERNEL__
+ 
+diff --git a/include/linux/ext3_fs_sb.h b/include/linux/ext3_fs_sb.h
+index e024e38248ff..a4e9216b3a6d 100644
+--- a/include/linux/ext3_fs_sb.h
++++ b/include/linux/ext3_fs_sb.h
+@@ -57,6 +57,7 @@ struct ext3_sb_info {
+ 	u32 s_next_generation;
+ 	u32 s_hash_seed[4];
+ 	int s_def_hash_version;
++	int s_hash_unsigned;	/* 3 if hash should be signed, 0 if not */
+ 	struct percpu_counter s_freeblocks_counter;
+ 	struct percpu_counter s_freeinodes_counter;
+ 	struct percpu_counter s_dirs_counter;

commit 6c20ec850360bc6e5c66a787f0523a80450d65ab
+Author: Theodore Ts'o 
+Date:   Tue Oct 28 21:08:20 2008 -0400
+
+    jbd2: Call the commit callback before the transaction could get dropped
+    
+    The transaction can potentially get dropped if there are no buffers
+    that need to be written.  Make sure we call the commit callback before
+    potentially deciding to drop the transaction.  Also avoid
+    dereferencing the commit_transaction pointer in the marker for the
+    same reason.
+    
+    This patch fixes the bug reported by Eric Paris at:
+    http://bugzilla.kernel.org/show_bug.cgi?id=11838
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Acked-by: Eric Sandeen 
+    Tested-by: Eric Paris 
+
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index 8b119e16aa36..ebc667bc54a8 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -974,6 +974,9 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	journal->j_committing_transaction = NULL;
+ 	spin_unlock(&journal->j_state_lock);
+ 
++	if (journal->j_commit_callback)
++		journal->j_commit_callback(journal, commit_transaction);
++
+ 	if (commit_transaction->t_checkpoint_list == NULL &&
+ 	    commit_transaction->t_checkpoint_io_list == NULL) {
+ 		__jbd2_journal_drop_transaction(journal, commit_transaction);
+@@ -995,11 +998,8 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	}
+ 	spin_unlock(&journal->j_list_lock);
+ 
+-	if (journal->j_commit_callback)
+-		journal->j_commit_callback(journal, commit_transaction);
+-
+ 	trace_mark(jbd2_end_commit, "dev %s transaction %d head %d",
+-		   journal->j_devname, commit_transaction->t_tid,
++		   journal->j_devname, journal->j_commit_sequence,
+ 		   journal->j_tail_sequence);
+ 	jbd_debug(1, "JBD: commit %d complete, head %d\n",
+ 		  journal->j_commit_sequence, journal->j_tail_sequence);

commit 3c37fc86d20fe35be656f070997d62f75c2e4874
+Author: Theodore Ts'o 
+Date:   Sat Oct 25 11:39:08 2008 -0400
+
+    ext4: Fix duplicate entries returned from getdents() system call
+    
+    Fix a regression caused by commit d0156417, "ext4: fix ext4_dx_readdir
+    hash collision handling", where deleting files in a large directory
+    (requiring more than one getdents system call), results in some
+    filenames being returned twice.  This was caused by a failure to
+    update info->curr_hash and info->curr_minor_hash, so that if the
+    directory had gotten modified since the last getdents() system call
+    (as would be the case if the user is running "rm -r" or "git clean"),
+    a directory entry would get returned twice to the userspace.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    
+    This patch fixes the bug reported by Markus Trippelsdorf at:
+    http://bugzilla.kernel.org/show_bug.cgi?id=11844
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Tested-by: Markus Trippelsdorf 
+
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index 3ca6a2b7632d..fed5b610df5a 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -459,17 +459,8 @@ static int ext4_dx_readdir(struct file *filp,
+ 	if (info->extra_fname) {
+ 		if (call_filldir(filp, dirent, filldir, info->extra_fname))
+ 			goto finished;
+-
+ 		info->extra_fname = NULL;
+-		info->curr_node = rb_next(info->curr_node);
+-		if (!info->curr_node) {
+-			if (info->next_hash == ~0) {
+-				filp->f_pos = EXT4_HTREE_EOF;
+-				goto finished;
+-			}
+-			info->curr_hash = info->next_hash;
+-			info->curr_minor_hash = 0;
+-		}
++		goto next_node;
+ 	} else if (!info->curr_node)
+ 		info->curr_node = rb_first(&info->root);
+ 
+@@ -501,9 +492,14 @@ static int ext4_dx_readdir(struct file *filp,
+ 		info->curr_minor_hash = fname->minor_hash;
+ 		if (call_filldir(filp, dirent, filldir, fname))
+ 			break;
+-
++	next_node:
+ 		info->curr_node = rb_next(info->curr_node);
+-		if (!info->curr_node) {
++		if (info->curr_node) {
++			fname = rb_entry(info->curr_node, struct fname,
++					 rb_hash);
++			info->curr_hash = fname->hash;
++			info->curr_minor_hash = fname->minor_hash;
++		} else {
+ 			if (info->next_hash == ~0) {
+ 				filp->f_pos = EXT4_HTREE_EOF;
+ 				break;

commit 8c9fa93d51123c5540762b1a9e1919d6f9c4af7c
+Author: Theodore Ts'o 
+Date:   Sat Oct 25 11:38:37 2008 -0400
+
+    ext3: Fix duplicate entries returned from getdents() system call
+    
+    Fix a regression caused by commit 6a897cf4, "ext3: fix ext3_dx_readdir
+    hash collision handling", where deleting files in a large directory
+    (requiring more than one getdents system call), results in some
+    filenames being returned twice.  This was caused by a failure to
+    update info->curr_hash and info->curr_minor_hash, so that if the
+    directory had gotten modified since the last getdents() system call
+    (as would be the case if the user is running "rm -r" or "git clean"),
+    a directory entry would get returned twice to the userspace.
+    
+    This patch fixes the bug reported by Markus Trippelsdorf at:
+    http://bugzilla.kernel.org/show_bug.cgi?id=11844
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Tested-by: Markus Trippelsdorf 
+
+diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c
+index 4c82531ea0a8..5853f4440af4 100644
+--- a/fs/ext3/dir.c
++++ b/fs/ext3/dir.c
+@@ -456,17 +456,8 @@ static int ext3_dx_readdir(struct file * filp,
+ 	if (info->extra_fname) {
+ 		if (call_filldir(filp, dirent, filldir, info->extra_fname))
+ 			goto finished;
+-
+ 		info->extra_fname = NULL;
+-		info->curr_node = rb_next(info->curr_node);
+-		if (!info->curr_node) {
+-			if (info->next_hash == ~0) {
+-				filp->f_pos = EXT3_HTREE_EOF;
+-				goto finished;
+-			}
+-			info->curr_hash = info->next_hash;
+-			info->curr_minor_hash = 0;
+-		}
++		goto next_node;
+ 	} else if (!info->curr_node)
+ 		info->curr_node = rb_first(&info->root);
+ 
+@@ -498,9 +489,14 @@ static int ext3_dx_readdir(struct file * filp,
+ 		info->curr_minor_hash = fname->minor_hash;
+ 		if (call_filldir(filp, dirent, filldir, fname))
+ 			break;
+-
++	next_node:
+ 		info->curr_node = rb_next(info->curr_node);
+-		if (!info->curr_node) {
++		if (info->curr_node) {
++			fname = rb_entry(info->curr_node, struct fname,
++					 rb_hash);
++			info->curr_hash = fname->hash;
++			info->curr_minor_hash = fname->minor_hash;
++		} else {
+ 			if (info->next_hash == ~0) {
+ 				filp->f_pos = EXT3_HTREE_EOF;
+ 				break;

commit f287a1a56130be5fdb96a4a62d1290bd064f308e
+Author: Theodore Ts'o 
+Date:   Thu Oct 16 22:50:48 2008 -0400
+
+    ext4: Remove automatic enabling of the HUGE_FILE feature flag
+    
+    If the HUGE_FILE feature flag is not set, don't allow the creation of
+    large files, instead of automatically enabling the feature flag.
+    Recent versions of mke2fs will set the HUGE_FILE flag automatically
+    anyway for ext4 filesystems.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 27fc6b951221..8dbf6953845b 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4194,7 +4194,6 @@ static int ext4_inode_blocks_set(handle_t *handle,
+ 	struct inode *inode = &(ei->vfs_inode);
+ 	u64 i_blocks = inode->i_blocks;
+ 	struct super_block *sb = inode->i_sb;
+-	int err = 0;
+ 
+ 	if (i_blocks <= ~0U) {
+ 		/*
+@@ -4204,36 +4203,27 @@ static int ext4_inode_blocks_set(handle_t *handle,
+ 		raw_inode->i_blocks_lo   = cpu_to_le32(i_blocks);
+ 		raw_inode->i_blocks_high = 0;
+ 		ei->i_flags &= ~EXT4_HUGE_FILE_FL;
+-	} else if (i_blocks <= 0xffffffffffffULL) {
++		return 0;
++	}
++	if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE))
++		return -EFBIG;
++
++	if (i_blocks <= 0xffffffffffffULL) {
+ 		/*
+ 		 * i_blocks can be represented in a 48 bit variable
+ 		 * as multiple of 512 bytes
+ 		 */
+-		err = ext4_update_rocompat_feature(handle, sb,
+-					    EXT4_FEATURE_RO_COMPAT_HUGE_FILE);
+-		if (err)
+-			goto  err_out;
+-		/* i_block is stored in the split  48 bit fields */
+ 		raw_inode->i_blocks_lo   = cpu_to_le32(i_blocks);
+ 		raw_inode->i_blocks_high = cpu_to_le16(i_blocks >> 32);
+ 		ei->i_flags &= ~EXT4_HUGE_FILE_FL;
+ 	} else {
+-		/*
+-		 * i_blocks should be represented in a 48 bit variable
+-		 * as multiple of  file system block size
+-		 */
+-		err = ext4_update_rocompat_feature(handle, sb,
+-					    EXT4_FEATURE_RO_COMPAT_HUGE_FILE);
+-		if (err)
+-			goto  err_out;
+ 		ei->i_flags |= EXT4_HUGE_FILE_FL;
+ 		/* i_block is stored in file system block size */
+ 		i_blocks = i_blocks >> (inode->i_blkbits - 9);
+ 		raw_inode->i_blocks_lo   = cpu_to_le32(i_blocks);
+ 		raw_inode->i_blocks_high = cpu_to_le16(i_blocks >> 32);
+ 	}
+-err_out:
+-	return err;
++	return 0;
+ }
+ 
+ /*
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 95127f03d1f6..9b2b2bc4ec17 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -374,66 +374,6 @@ void ext4_update_dynamic_rev(struct super_block *sb)
+ 	 */
+ }
+ 
+-int ext4_update_compat_feature(handle_t *handle,
+-					struct super_block *sb, __u32 compat)
+-{
+-	int err = 0;
+-	if (!EXT4_HAS_COMPAT_FEATURE(sb, compat)) {
+-		err = ext4_journal_get_write_access(handle,
+-				EXT4_SB(sb)->s_sbh);
+-		if (err)
+-			return err;
+-		EXT4_SET_COMPAT_FEATURE(sb, compat);
+-		sb->s_dirt = 1;
+-		handle->h_sync = 1;
+-		BUFFER_TRACE(EXT4_SB(sb)->s_sbh,
+-					"call ext4_journal_dirty_met adata");
+-		err = ext4_journal_dirty_metadata(handle,
+-				EXT4_SB(sb)->s_sbh);
+-	}
+-	return err;
+-}
+-
+-int ext4_update_rocompat_feature(handle_t *handle,
+-					struct super_block *sb, __u32 rocompat)
+-{
+-	int err = 0;
+-	if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, rocompat)) {
+-		err = ext4_journal_get_write_access(handle,
+-				EXT4_SB(sb)->s_sbh);
+-		if (err)
+-			return err;
+-		EXT4_SET_RO_COMPAT_FEATURE(sb, rocompat);
+-		sb->s_dirt = 1;
+-		handle->h_sync = 1;
+-		BUFFER_TRACE(EXT4_SB(sb)->s_sbh,
+-					"call ext4_journal_dirty_met adata");
+-		err = ext4_journal_dirty_metadata(handle,
+-				EXT4_SB(sb)->s_sbh);
+-	}
+-	return err;
+-}
+-
+-int ext4_update_incompat_feature(handle_t *handle,
+-					struct super_block *sb, __u32 incompat)
+-{
+-	int err = 0;
+-	if (!EXT4_HAS_INCOMPAT_FEATURE(sb, incompat)) {
+-		err = ext4_journal_get_write_access(handle,
+-				EXT4_SB(sb)->s_sbh);
+-		if (err)
+-			return err;
+-		EXT4_SET_INCOMPAT_FEATURE(sb, incompat);
+-		sb->s_dirt = 1;
+-		handle->h_sync = 1;
+-		BUFFER_TRACE(EXT4_SB(sb)->s_sbh,
+-					"call ext4_journal_dirty_met adata");
+-		err = ext4_journal_dirty_metadata(handle,
+-				EXT4_SB(sb)->s_sbh);
+-	}
+-	return err;
+-}
+-
+ /*
+  * Open the external journal device
+  */
+@@ -1771,13 +1711,13 @@ static void ext4_orphan_cleanup(struct super_block *sb,
+  *
+  * Note, this does *not* consider any metadata overhead for vfs i_blocks.
+  */
+-static loff_t ext4_max_size(int blkbits)
++static loff_t ext4_max_size(int blkbits, int has_huge_files)
+ {
+ 	loff_t res;
+ 	loff_t upper_limit = MAX_LFS_FILESIZE;
+ 
+ 	/* small i_blocks in vfs inode? */
+-	if (sizeof(blkcnt_t) < sizeof(u64)) {
++	if (!has_huge_files || sizeof(blkcnt_t) < sizeof(u64)) {
+ 		/*
+ 		 * CONFIG_LSF is not enabled implies the inode
+ 		 * i_block represent total blocks in 512 bytes
+@@ -1807,7 +1747,7 @@ static loff_t ext4_max_size(int blkbits)
+  * block limit, and also a limit of (2^48 - 1) 512-byte sectors in i_blocks.
+  * We need to be 1 filesystem block less than the 2^48 sector limit.
+  */
+-static loff_t ext4_max_bitmap_size(int bits)
++static loff_t ext4_max_bitmap_size(int bits, int has_huge_files)
+ {
+ 	loff_t res = EXT4_NDIR_BLOCKS;
+ 	int meta_blocks;
+@@ -1820,11 +1760,11 @@ static loff_t ext4_max_bitmap_size(int bits)
+ 	 * total number of  512 bytes blocks of the file
+ 	 */
+ 
+-	if (sizeof(blkcnt_t) < sizeof(u64)) {
++	if (!has_huge_files || sizeof(blkcnt_t) < sizeof(u64)) {
+ 		/*
+-		 * CONFIG_LSF is not enabled implies the inode
+-		 * i_block represent total blocks in 512 bytes
+-		 * 32 == size of vfs inode i_blocks * 8
++		 * !has_huge_files or CONFIG_LSF is not enabled
++		 * implies the inode i_block represent total blocks in
++		 * 512 bytes 32 == size of vfs inode i_blocks * 8
+ 		 */
+ 		upper_limit = (1LL << 32) - 1;
+ 
+@@ -1933,7 +1873,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	int blocksize;
+ 	int db_count;
+ 	int i;
+-	int needs_recovery;
++	int needs_recovery, has_huge_files;
+ 	__le32 features;
+ 	__u64 blocks_count;
+ 	int err;
+@@ -2074,7 +2014,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		       sb->s_id, le32_to_cpu(features));
+ 		goto failed_mount;
+ 	}
+-	if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
++	has_huge_files = EXT4_HAS_RO_COMPAT_FEATURE(sb,
++				    EXT4_FEATURE_RO_COMPAT_HUGE_FILE);
++	if (has_huge_files) {
+ 		/*
+ 		 * Large file size enabled file system can only be
+ 		 * mount if kernel is build with CONFIG_LSF
+@@ -2124,8 +2066,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		}
+ 	}
+ 
+-	sbi->s_bitmap_maxbytes = ext4_max_bitmap_size(sb->s_blocksize_bits);
+-	sb->s_maxbytes = ext4_max_size(sb->s_blocksize_bits);
++	sbi->s_bitmap_maxbytes = ext4_max_bitmap_size(sb->s_blocksize_bits,
++						      has_huge_files);
++	sb->s_maxbytes = ext4_max_size(sb->s_blocksize_bits, has_huge_files);
+ 
+ 	if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV) {
+ 		sbi->s_inode_size = EXT4_GOOD_OLD_INODE_SIZE;

commit 3e624fc72fba09b6f999a9fbb87b64efccd38036
+Author: Theodore Ts'o 
+Date:   Thu Oct 16 20:00:24 2008 -0400
+
+    ext4: Replace hackish ext4_mb_poll_new_transaction with commit callback
+    
+    The multiblock allocator needs to be able to release blocks (and issue
+    a blkdev discard request) when the transaction which freed those
+    blocks is committed.  Previously this was done via a polling mechanism
+    when blocks are allocated or freed.  A much better way of doing things
+    is to create a jbd2 callback function and attaching the list of blocks
+    to be freed directly to the transaction structure.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4_sb.h b/fs/ext4/ext4_sb.h
+index 6a0b40d43264..445fde603df8 100644
+--- a/fs/ext4/ext4_sb.h
++++ b/fs/ext4/ext4_sb.h
+@@ -99,9 +99,6 @@ struct ext4_sb_info {
+ 	struct inode *s_buddy_cache;
+ 	long s_blocks_reserved;
+ 	spinlock_t s_reserve_lock;
+-	struct list_head s_active_transaction;
+-	struct list_head s_closed_transaction;
+-	struct list_head s_committed_transaction;
+ 	spinlock_t s_md_lock;
+ 	tid_t s_last_transaction;
+ 	unsigned short *s_mb_offsets, *s_mb_maxs;
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index da1da1fe2b14..dfe17a134052 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2523,9 +2523,6 @@ int ext4_mb_init(struct super_block *sb, int needs_recovery)
+ 	}
+ 
+ 	spin_lock_init(&sbi->s_md_lock);
+-	INIT_LIST_HEAD(&sbi->s_active_transaction);
+-	INIT_LIST_HEAD(&sbi->s_closed_transaction);
+-	INIT_LIST_HEAD(&sbi->s_committed_transaction);
+ 	spin_lock_init(&sbi->s_bal_lock);
+ 
+ 	sbi->s_mb_max_to_scan = MB_DEFAULT_MAX_TO_SCAN;
+@@ -2554,6 +2551,8 @@ int ext4_mb_init(struct super_block *sb, int needs_recovery)
+ 	ext4_mb_init_per_dev_proc(sb);
+ 	ext4_mb_history_init(sb);
+ 
++	sbi->s_journal->j_commit_callback = release_blocks_on_commit;
++
+ 	printk(KERN_INFO "EXT4-fs: mballoc enabled\n");
+ 	return 0;
+ }
+@@ -2583,15 +2582,6 @@ int ext4_mb_release(struct super_block *sb)
+ 	struct ext4_group_info *grinfo;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 
+-	/* release freed, non-committed blocks */
+-	spin_lock(&sbi->s_md_lock);
+-	list_splice_init(&sbi->s_closed_transaction,
+-			&sbi->s_committed_transaction);
+-	list_splice_init(&sbi->s_active_transaction,
+-			&sbi->s_committed_transaction);
+-	spin_unlock(&sbi->s_md_lock);
+-	ext4_mb_free_committed_blocks(sb);
+-
+ 	if (sbi->s_group_info) {
+ 		for (i = 0; i < sbi->s_groups_count; i++) {
+ 			grinfo = ext4_get_group_info(sb, i);
+@@ -2645,36 +2635,25 @@ int ext4_mb_release(struct super_block *sb)
+ 	return 0;
+ }
+ 
+-static noinline_for_stack void
+-ext4_mb_free_committed_blocks(struct super_block *sb)
++/*
++ * This function is called by the jbd2 layer once the commit has finished,
++ * so we know we can free the blocks that were released with that commit.
++ */
++static void release_blocks_on_commit(journal_t *journal, transaction_t *txn)
+ {
++	struct super_block *sb = journal->j_private;
+ 	struct ext4_buddy e4b;
+ 	struct ext4_group_info *db;
+-	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	int err, count = 0, count2 = 0;
+ 	struct ext4_free_data *entry;
+ 	ext4_fsblk_t discard_block;
++	struct list_head *l, *ltmp;
+ 
+-	if (list_empty(&sbi->s_committed_transaction))
+-		return;
+-
+-	/* there is committed blocks to be freed yet */
+-	do {
+-		/* get next array of blocks */
+-		entry = NULL;
+-		spin_lock(&sbi->s_md_lock);
+-		if (!list_empty(&sbi->s_committed_transaction)) {
+-			entry = list_entry(sbi->s_committed_transaction.next,
+-					struct ext4_free_data, list);
+-			list_del(&entry->list);
+-		}
+-		spin_unlock(&sbi->s_md_lock);
+-
+-		if (entry == NULL)
+-			break;
++	list_for_each_safe(l, ltmp, &txn->t_private_list) {
++		entry = list_entry(l, struct ext4_free_data, list);
+ 
+ 		mb_debug("gonna free %u blocks in group %lu (0x%p):",
+-				entry->count, entry->group, entry);
++			 entry->count, entry->group, entry);
+ 
+ 		err = ext4_mb_load_buddy(sb, entry->group, &e4b);
+ 		/* we expect to find existing buddy because it's pinned */
+@@ -2706,7 +2685,7 @@ ext4_mb_free_committed_blocks(struct super_block *sb)
+ 
+ 		kmem_cache_free(ext4_free_ext_cachep, entry);
+ 		ext4_mb_release_desc(&e4b);
+-	} while (1);
++	}
+ 
+ 	mb_debug("freed %u blocks in %u structures\n", count, count2);
+ }
+@@ -4348,8 +4327,6 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
+ 		goto out1;
+ 	}
+ 
+-	ext4_mb_poll_new_transaction(sb, handle);
+-
+ 	*errp = ext4_mb_initialize_context(ac, ar);
+ 	if (*errp) {
+ 		ar->len = 0;
+@@ -4408,36 +4385,6 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
+ 
+ 	return block;
+ }
+-static void ext4_mb_poll_new_transaction(struct super_block *sb,
+-						handle_t *handle)
+-{
+-	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-
+-	if (sbi->s_last_transaction == handle->h_transaction->t_tid)
+-		return;
+-
+-	/* new transaction! time to close last one and free blocks for
+-	 * committed transaction. we know that only transaction can be
+-	 * active, so previos transaction can be being logged and we
+-	 * know that transaction before previous is known to be already
+-	 * logged. this means that now we may free blocks freed in all
+-	 * transactions before previous one. hope I'm clear enough ... */
+-
+-	spin_lock(&sbi->s_md_lock);
+-	if (sbi->s_last_transaction != handle->h_transaction->t_tid) {
+-		mb_debug("new transaction %lu, old %lu\n",
+-				(unsigned long) handle->h_transaction->t_tid,
+-				(unsigned long) sbi->s_last_transaction);
+-		list_splice_init(&sbi->s_closed_transaction,
+-				&sbi->s_committed_transaction);
+-		list_splice_init(&sbi->s_active_transaction,
+-				&sbi->s_closed_transaction);
+-		sbi->s_last_transaction = handle->h_transaction->t_tid;
+-	}
+-	spin_unlock(&sbi->s_md_lock);
+-
+-	ext4_mb_free_committed_blocks(sb);
+-}
+ 
+ /*
+  * We can merge two free data extents only if the physical blocks
+@@ -4531,9 +4478,9 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
+ 			kmem_cache_free(ext4_free_ext_cachep, entry);
+ 		}
+ 	}
+-	/* Add the extent to active_transaction list */
++	/* Add the extent to transaction's private list */
+ 	spin_lock(&sbi->s_md_lock);
+-	list_add(&new_entry->list, &sbi->s_active_transaction);
++	list_add(&new_entry->list, &handle->h_transaction->t_private_list);
+ 	spin_unlock(&sbi->s_md_lock);
+ 	ext4_unlock_group(sb, group);
+ 	return 0;
+@@ -4562,8 +4509,6 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
+ 
+ 	*freed = 0;
+ 
+-	ext4_mb_poll_new_transaction(sb, handle);
+-
+ 	sbi = EXT4_SB(sb);
+ 	es = EXT4_SB(sb)->s_es;
+ 	if (block < le32_to_cpu(es->s_first_data_block) ||
+diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
+index 94cb7b9fe3ee..b5dff1fff1e5 100644
+--- a/fs/ext4/mballoc.h
++++ b/fs/ext4/mballoc.h
+@@ -269,8 +269,6 @@ struct buffer_head *read_block_bitmap(struct super_block *, ext4_group_t);
+ 
+ static void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap,
+ 					ext4_group_t group);
+-static void ext4_mb_poll_new_transaction(struct super_block *, handle_t *);
+-static void ext4_mb_free_committed_blocks(struct super_block *);
+ static void ext4_mb_return_to_preallocation(struct inode *inode,
+ 					struct ext4_buddy *e4b, sector_t block,
+ 					int count);
+@@ -278,6 +276,7 @@ static void ext4_mb_put_pa(struct ext4_allocation_context *,
+ 			struct super_block *, struct ext4_prealloc_space *pa);
+ static int ext4_mb_init_per_dev_proc(struct super_block *sb);
+ static int ext4_mb_destroy_per_dev_proc(struct super_block *sb);
++static void release_blocks_on_commit(journal_t *journal, transaction_t *txn);
+ 
+ 
+ static inline void ext4_lock_group(struct super_block *sb, ext4_group_t group)
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index 0abe02c4242a..8b119e16aa36 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -995,6 +995,9 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	}
+ 	spin_unlock(&journal->j_list_lock);
+ 
++	if (journal->j_commit_callback)
++		journal->j_commit_callback(journal, commit_transaction);
++
+ 	trace_mark(jbd2_end_commit, "dev %s transaction %d head %d",
+ 		   journal->j_devname, commit_transaction->t_tid,
+ 		   journal->j_tail_sequence);
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index e5d540588fa9..39b7805a599a 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -52,6 +52,7 @@ jbd2_get_transaction(journal_t *journal, transaction_t *transaction)
+ 	transaction->t_expires = jiffies + journal->j_commit_interval;
+ 	spin_lock_init(&transaction->t_handle_lock);
+ 	INIT_LIST_HEAD(&transaction->t_inode_list);
++	INIT_LIST_HEAD(&transaction->t_private_list);
+ 
+ 	/* Set up the commit timer for the new transaction. */
+ 	journal->j_commit_timer.expires = round_jiffies(transaction->t_expires);
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index 463d6f10b64f..c7d106ef22e2 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -641,6 +641,11 @@ struct transaction_s
+ 	 */
+ 	int t_handle_count;
+ 
++	/*
++	 * For use by the filesystem to store fs-specific data
++	 * structures associated with the transaction
++	 */
++	struct list_head	t_private_list;
+ };
+ 
+ struct transaction_run_stats_s {
+@@ -935,6 +940,10 @@ struct journal_s
+ 
+ 	pid_t			j_last_sync_writer;
+ 
++	/* This function is called when a transaction is closed */
++	void			(*j_commit_callback)(journal_t *,
++						     transaction_t *);
++
+ 	/*
+ 	 * Journal statistics
+ 	 */

commit 01436ef2e4710317f826c4893b31c07b2d8df88c
+Author: Theodore Ts'o 
+Date:   Fri Oct 17 07:22:35 2008 -0400
+
+    ext4: Remove unused mount options: nomballoc, mballoc, nocheck
+    
+    These mount options don't actually do anything any more, so remove
+    them.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 6690a41cdd9f..4880cc3e6727 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -511,7 +511,6 @@ do {									       \
+ /*
+  * Mount flags
+  */
+-#define EXT4_MOUNT_CHECK		0x00001	/* Do mount-time checks */
+ #define EXT4_MOUNT_OLDALLOC		0x00002  /* Don't use the new Orlov allocator */
+ #define EXT4_MOUNT_GRPID		0x00004	/* Create files with directory's group */
+ #define EXT4_MOUNT_DEBUG		0x00008	/* Some debugging messages */
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index a97e9ebe3b60..95127f03d1f6 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -904,7 +904,7 @@ static const struct export_operations ext4_export_ops = {
+ enum {
+ 	Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid,
+ 	Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro,
+-	Opt_nouid32, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov,
++	Opt_nouid32, Opt_debug, Opt_oldalloc, Opt_orlov,
+ 	Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
+ 	Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh,
+ 	Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev,
+@@ -915,7 +915,7 @@ enum {
+ 	Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
+ 	Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
+ 	Opt_grpquota, Opt_extents, Opt_noextents, Opt_i_version,
+-	Opt_mballoc, Opt_nomballoc, Opt_stripe, Opt_delalloc, Opt_nodelalloc,
++	Opt_stripe, Opt_delalloc, Opt_nodelalloc,
+ 	Opt_inode_readahead_blks
+ };
+ 
+@@ -933,8 +933,6 @@ static const match_table_t tokens = {
+ 	{Opt_err_panic, "errors=panic"},
+ 	{Opt_err_ro, "errors=remount-ro"},
+ 	{Opt_nouid32, "nouid32"},
+-	{Opt_nocheck, "nocheck"},
+-	{Opt_nocheck, "check=none"},
+ 	{Opt_debug, "debug"},
+ 	{Opt_oldalloc, "oldalloc"},
+ 	{Opt_orlov, "orlov"},
+@@ -973,8 +971,6 @@ static const match_table_t tokens = {
+ 	{Opt_extents, "extents"},
+ 	{Opt_noextents, "noextents"},
+ 	{Opt_i_version, "i_version"},
+-	{Opt_mballoc, "mballoc"},
+-	{Opt_nomballoc, "nomballoc"},
+ 	{Opt_stripe, "stripe=%u"},
+ 	{Opt_resize, "resize"},
+ 	{Opt_delalloc, "delalloc"},
+@@ -1073,9 +1069,6 @@ static int parse_options(char *options, struct super_block *sb,
+ 		case Opt_nouid32:
+ 			set_opt(sbi->s_mount_opt, NO_UID32);
+ 			break;
+-		case Opt_nocheck:
+-			clear_opt(sbi->s_mount_opt, CHECK);
+-			break;
+ 		case Opt_debug:
+ 			set_opt(sbi->s_mount_opt, DEBUG);
+ 			break;

commit 8a0aba733db1adb5e1f0e828889a18f4c1c512de
+Author: Theodore Ts'o 
+Date:   Thu Oct 16 10:06:27 2008 -0400
+
+    ext4: let the block device know when unused blocks can be discarded
+    
+    Let the block device know when unused blocks can be discarded, using
+    the new sb_issue_discard() interface.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index bd9b011941a2..815a22ea6078 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2653,6 +2653,7 @@ ext4_mb_free_committed_blocks(struct super_block *sb)
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	int err, count = 0, count2 = 0;
+ 	struct ext4_free_data *entry;
++	ext4_fsblk_t discard_block;
+ 
+ 	if (list_empty(&sbi->s_committed_transaction))
+ 		return;
+@@ -2696,6 +2697,12 @@ ext4_mb_free_committed_blocks(struct super_block *sb)
+ 			page_cache_release(e4b.bd_bitmap_page);
+ 		}
+ 		ext4_unlock_group(sb, entry->group);
++		discard_block = (ext4_fsblk_t) entry->group * EXT4_BLOCKS_PER_GROUP(sb)
++			+ entry->start_blk
++			+ le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
++		trace_mark(ext4_discard_blocks, "dev %s blk %llu count %u", sb->s_id,
++			   (unsigned long long) discard_block, entry->count);
++		sb_issue_discard(sb, discard_block, entry->count);
+ 
+ 		kmem_cache_free(ext4_free_ext_cachep, entry);
+ 		ext4_mb_release_desc(&e4b);
+diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
+index 9e815c4e37df..94cb7b9fe3ee 100644
+--- a/fs/ext4/mballoc.h
++++ b/fs/ext4/mballoc.h
+@@ -18,6 +18,8 @@
+ #include 
+ #include 
+ #include 
++#include 
++#include 
+ #include "ext4_jbd2.h"
+ #include "ext4.h"
+ #include "group.h"

commit 03010a3350301baac2154fa66de925ae2981b7e3
+Author: Theodore Ts'o 
+Date:   Fri Oct 10 20:02:48 2008 -0400
+
+    ext4: Rename ext4dev to ext4
+    
+    The ext4 filesystem is getting stable enough that it's time to drop
+    the "dev" prefix.  Also remove the requirement for the TEST_FILESYS
+    flag.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
+index 289057958f90..74484e696405 100644
+--- a/Documentation/filesystems/ext4.txt
++++ b/Documentation/filesystems/ext4.txt
+@@ -32,9 +32,9 @@ Mailing list: linux-ext4@vger.kernel.org
+     you will need to merge your changes with the version from e2fsprogs
+     1.41.x.
+ 
+-  - Create a new filesystem using the ext4dev filesystem type:
++  - Create a new filesystem using the ext4 filesystem type:
+ 
+-    	# mke2fs -t ext4dev /dev/hda1
++    	# mke2fs -t ext4 /dev/hda1
+ 
+     Or configure an existing ext3 filesystem to support extents and set
+     the test_fs flag to indicate that it's ok for an in-development
+@@ -47,13 +47,13 @@ Mailing list: linux-ext4@vger.kernel.org
+ 
+         # tune2fs -I 256 /dev/hda1
+ 
+-    (Note: we currently do not have tools to convert an ext4dev
++    (Note: we currently do not have tools to convert an ext4
+     filesystem back to ext3; so please do not do try this on production
+     filesystems.)
+ 
+   - Mounting:
+ 
+-	# mount -t ext4dev /dev/hda1 /wherever
++	# mount -t ext4 /dev/hda1 /wherever
+ 
+   - When comparing performance with other filesystems, remember that
+     ext3/4 by default offers higher data integrity guarantees than most.
+diff --git a/fs/Kconfig b/fs/Kconfig
+index abccb5dab9a8..40183d94b683 100644
+--- a/fs/Kconfig
++++ b/fs/Kconfig
+@@ -136,37 +136,51 @@ config EXT3_FS_SECURITY
+ 	  If you are not using a security module that requires using
+ 	  extended attributes for file security labels, say N.
+ 
+-config EXT4DEV_FS
+-	tristate "Ext4dev/ext4 extended fs support development (EXPERIMENTAL)"
+-	depends on EXPERIMENTAL
++config EXT4_FS
++	tristate "The Extended 4 (ext4) filesystem"
+ 	select JBD2
+ 	select CRC16
+ 	help
+-	  Ext4dev is a predecessor filesystem of the next generation
+-	  extended fs ext4, based on ext3 filesystem code. It will be
+-	  renamed ext4 fs later, once ext4dev is mature and stabilized.
++	  This is the next generation of the ext3 filesystem.
+ 
+ 	  Unlike the change from ext2 filesystem to ext3 filesystem,
+-	  the on-disk format of ext4dev is not the same as ext3 any more:
+-	  it is based on extent maps and it supports 48-bit physical block
+-	  numbers. These combined on-disk format changes will allow
+-	  ext4dev/ext4 to handle more than 16 TB filesystem volumes --
+-	  a hard limit that ext3 cannot overcome without changing the
+-	  on-disk format.
+-
+-	  Other than extent maps and 48-bit block numbers, ext4dev also is
+-	  likely to have other new features such as persistent preallocation,
+-	  high resolution time stamps, and larger file support etc.  These
+-	  features will be added to ext4dev gradually.
++	  the on-disk format of ext4 is not forwards compatible with
++	  ext3; it is based on extent maps and it supports 48-bit
++	  physical block numbers.  The ext4 filesystem also supports delayed
++	  allocation, persistent preallocation, high resolution time stamps,
++	  and a number of other features to improve performance and speed
++	  up fsck time.  For more information, please see the web pages at
++	  http://ext4.wiki.kernel.org.
++
++	  The ext4 filesystem will support mounting an ext3
++	  filesystem; while there will be some performance gains from
++	  the delayed allocation and inode table readahead, the best
++	  performance gains will require enabling ext4 features in the
++	  filesystem, or formating a new filesystem as an ext4
++	  filesystem initially.
+ 
+ 	  To compile this file system support as a module, choose M here. The
+ 	  module will be called ext4dev.
+ 
+ 	  If unsure, say N.
+ 
+-config EXT4DEV_FS_XATTR
+-	bool "Ext4dev extended attributes"
+-	depends on EXT4DEV_FS
++config EXT4DEV_COMPAT
++	bool "Enable ext4dev compatibility"
++	depends on EXT4_FS
++	help
++	  Starting with 2.6.28, the name of the ext4 filesystem was
++	  renamed from ext4dev to ext4.  Unfortunately there are some
++	  lagecy userspace programs (such as klibc's fstype) have
++	  "ext4dev" hardcoded.  
++
++	  To enable backwards compatibility so that systems that are
++	  still expecting to mount ext4 filesystems using ext4dev,
++	  chose Y here.   This feature will go away by 2.6.31, so
++	  please arrange to get your userspace programs fixed!
++
++config EXT4_FS_XATTR
++	bool "Ext4 extended attributes"
++	depends on EXT4_FS
+ 	default y
+ 	help
+ 	  Extended attributes are name:value pairs associated with inodes by
+@@ -175,11 +189,11 @@ config EXT4DEV_FS_XATTR
+ 
+ 	  If unsure, say N.
+ 
+-	  You need this for POSIX ACL support on ext4dev/ext4.
++	  You need this for POSIX ACL support on ext4.
+ 
+-config EXT4DEV_FS_POSIX_ACL
+-	bool "Ext4dev POSIX Access Control Lists"
+-	depends on EXT4DEV_FS_XATTR
++config EXT4_FS_POSIX_ACL
++	bool "Ext4 POSIX Access Control Lists"
++	depends on EXT4_FS_XATTR
+ 	select FS_POSIX_ACL
+ 	help
+ 	  POSIX Access Control Lists (ACLs) support permissions for users and
+@@ -190,14 +204,14 @@ config EXT4DEV_FS_POSIX_ACL
+ 
+ 	  If you don't know what Access Control Lists are, say N
+ 
+-config EXT4DEV_FS_SECURITY
+-	bool "Ext4dev Security Labels"
+-	depends on EXT4DEV_FS_XATTR
++config EXT4_FS_SECURITY
++	bool "Ext4 Security Labels"
++	depends on EXT4_FS_XATTR
+ 	help
+ 	  Security labels support alternative access control models
+ 	  implemented by security modules like SELinux.  This option
+ 	  enables an extended attribute handler for file security
+-	  labels in the ext4dev/ext4 filesystem.
++	  labels in the ext4 filesystem.
+ 
+ 	  If you are not using a security module that requires using
+ 	  extended attributes for file security labels, say N.
+@@ -240,22 +254,22 @@ config JBD2
+ 	help
+ 	  This is a generic journaling layer for block devices that support
+ 	  both 32-bit and 64-bit block numbers.  It is currently used by
+-	  the ext4dev/ext4 filesystem, but it could also be used to add
++	  the ext4 filesystem, but it could also be used to add
+ 	  journal support to other file systems or block devices such
+ 	  as RAID or LVM.
+ 
+-	  If you are using ext4dev/ext4, you need to say Y here. If you are not
+-	  using ext4dev/ext4 then you will probably want to say N.
++	  If you are using ext4, you need to say Y here. If you are not
++	  using ext4 then you will probably want to say N.
+ 
+ 	  To compile this device as a module, choose M here. The module will be
+-	  called jbd2.  If you are compiling ext4dev/ext4 into the kernel,
++	  called jbd2.  If you are compiling ext4 into the kernel,
+ 	  you cannot compile this code as a module.
+ 
+ config JBD2_DEBUG
+-	bool "JBD2 (ext4dev/ext4) debugging support"
++	bool "JBD2 (ext4) debugging support"
+ 	depends on JBD2 && DEBUG_FS
+ 	help
+-	  If you are using the ext4dev/ext4 journaled file system (or
++	  If you are using the ext4 journaled file system (or
+ 	  potentially any other filesystem/device using JBD2), this option
+ 	  allows you to enable debugging output while the system is running,
+ 	  in order to help track down any problems you are having.
+@@ -270,9 +284,9 @@ config JBD2_DEBUG
+ config FS_MBCACHE
+ # Meta block cache for Extended Attributes (ext2/ext3/ext4)
+ 	tristate
+-	depends on EXT2_FS_XATTR || EXT3_FS_XATTR || EXT4DEV_FS_XATTR
+-	default y if EXT2_FS=y || EXT3_FS=y || EXT4DEV_FS=y
+-	default m if EXT2_FS=m || EXT3_FS=m || EXT4DEV_FS=m
++	depends on EXT2_FS_XATTR || EXT3_FS_XATTR || EXT4_FS_XATTR
++	default y if EXT2_FS=y || EXT3_FS=y || EXT4_FS=y
++	default m if EXT2_FS=m || EXT3_FS=m || EXT4_FS=m
+ 
+ config REISERFS_FS
+ 	tristate "Reiserfs support"
+diff --git a/fs/Makefile b/fs/Makefile
+index a1482a5eff15..de404b00eb0c 100644
+--- a/fs/Makefile
++++ b/fs/Makefile
+@@ -69,7 +69,7 @@ obj-$(CONFIG_DLM)		+= dlm/
+ # Do not add any filesystems before this line
+ obj-$(CONFIG_REISERFS_FS)	+= reiserfs/
+ obj-$(CONFIG_EXT3_FS)		+= ext3/ # Before ext2 so root fs can be ext3
+-obj-$(CONFIG_EXT4DEV_FS)	+= ext4/ # Before ext2 so root fs can be ext4dev
++obj-$(CONFIG_EXT4_FS)		+= ext4/ # Before ext2 so root fs can be ext4dev
+ obj-$(CONFIG_JBD)		+= jbd/
+ obj-$(CONFIG_JBD2)		+= jbd2/
+ obj-$(CONFIG_EXT2_FS)		+= ext2/
+diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
+index ac6fa8ca0a2f..a8ff003a00f7 100644
+--- a/fs/ext4/Makefile
++++ b/fs/ext4/Makefile
+@@ -2,12 +2,12 @@
+ # Makefile for the linux ext4-filesystem routines.
+ #
+ 
+-obj-$(CONFIG_EXT4DEV_FS) += ext4dev.o
++obj-$(CONFIG_EXT4_FS) += ext4.o
+ 
+-ext4dev-y	:= balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
++ext4-y	:= balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
+ 		   ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \
+ 		   ext4_jbd2.o migrate.o mballoc.o
+ 
+-ext4dev-$(CONFIG_EXT4DEV_FS_XATTR)	+= xattr.o xattr_user.o xattr_trusted.o
+-ext4dev-$(CONFIG_EXT4DEV_FS_POSIX_ACL)	+= acl.o
+-ext4dev-$(CONFIG_EXT4DEV_FS_SECURITY)	+= xattr_security.o
++ext4-$(CONFIG_EXT4_FS_XATTR)		+= xattr.o xattr_user.o xattr_trusted.o
++ext4-$(CONFIG_EXT4_FS_POSIX_ACL)	+= acl.o
++ext4-$(CONFIG_EXT4_FS_SECURITY)		+= xattr_security.o
+diff --git a/fs/ext4/acl.h b/fs/ext4/acl.h
+index 4c9948f69f8b..cb45257a246e 100644
+--- a/fs/ext4/acl.h
++++ b/fs/ext4/acl.h
+@@ -51,7 +51,7 @@ static inline int ext4_acl_count(size_t size)
+ 	}
+ }
+ 
+-#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
++#ifdef CONFIG_EXT4_FS_POSIX_ACL
+ 
+ /* Value for inode->u.ext4_i.i_acl and inode->u.ext4_i.i_default_acl
+    if the ACL has not been cached */
+@@ -62,7 +62,7 @@ extern int ext4_permission(struct inode *, int);
+ extern int ext4_acl_chmod(struct inode *);
+ extern int ext4_init_acl(handle_t *, struct inode *, struct inode *);
+ 
+-#else  /* CONFIG_EXT4DEV_FS_POSIX_ACL */
++#else  /* CONFIG_EXT4_FS_POSIX_ACL */
+ #include 
+ #define ext4_permission NULL
+ 
+@@ -77,5 +77,5 @@ ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
+ {
+ 	return 0;
+ }
+-#endif  /* CONFIG_EXT4DEV_FS_POSIX_ACL */
++#endif  /* CONFIG_EXT4_FS_POSIX_ACL */
+ 
+diff --git a/fs/ext4/ext4_i.h b/fs/ext4/ext4_i.h
+index 2875eeca1727..5c124c0ac6d3 100644
+--- a/fs/ext4/ext4_i.h
++++ b/fs/ext4/ext4_i.h
+@@ -66,7 +66,7 @@ struct ext4_inode_info {
+ 	__u32	i_state;		/* Dynamic state flags for ext4 */
+ 
+ 	ext4_lblk_t		i_dir_start_lookup;
+-#ifdef CONFIG_EXT4DEV_FS_XATTR
++#ifdef CONFIG_EXT4_FS_XATTR
+ 	/*
+ 	 * Extended attributes can be read independently of the main file
+ 	 * data. Taking i_mutex even when reading would cause contention
+@@ -76,7 +76,7 @@ struct ext4_inode_info {
+ 	 */
+ 	struct rw_semaphore xattr_sem;
+ #endif
+-#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
++#ifdef CONFIG_EXT4_FS_POSIX_ACL
+ 	struct posix_acl	*i_acl;
+ 	struct posix_acl	*i_default_acl;
+ #endif
+diff --git a/fs/ext4/file.c b/fs/ext4/file.c
+index 6d5be156202a..6bd11fba71f7 100644
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -165,7 +165,7 @@ const struct inode_operations ext4_file_inode_operations = {
+ 	.truncate	= ext4_truncate,
+ 	.setattr	= ext4_setattr,
+ 	.getattr	= ext4_getattr,
+-#ifdef CONFIG_EXT4DEV_FS_XATTR
++#ifdef CONFIG_EXT4_FS_XATTR
+ 	.setxattr	= generic_setxattr,
+ 	.getxattr	= generic_getxattr,
+ 	.listxattr	= ext4_listxattr,
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index a4747867411f..9b4ec9decfd1 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4041,7 +4041,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 		return inode;
+ 
+ 	ei = EXT4_I(inode);
+-#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
++#ifdef CONFIG_EXT4_FS_POSIX_ACL
+ 	ei->i_acl = EXT4_ACL_NOT_CACHED;
+ 	ei->i_default_acl = EXT4_ACL_NOT_CACHED;
+ #endif
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 5295a9225cf9..92db9e945147 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1773,7 +1773,7 @@ static int ext4_mknod(struct inode *dir, struct dentry *dentry,
+ 	err = PTR_ERR(inode);
+ 	if (!IS_ERR(inode)) {
+ 		init_special_inode(inode, inode->i_mode, rdev);
+-#ifdef CONFIG_EXT4DEV_FS_XATTR
++#ifdef CONFIG_EXT4_FS_XATTR
+ 		inode->i_op = &ext4_special_inode_operations;
+ #endif
+ 		err = ext4_add_nondir(handle, dentry, inode);
+@@ -2456,7 +2456,7 @@ const struct inode_operations ext4_dir_inode_operations = {
+ 	.mknod		= ext4_mknod,
+ 	.rename		= ext4_rename,
+ 	.setattr	= ext4_setattr,
+-#ifdef CONFIG_EXT4DEV_FS_XATTR
++#ifdef CONFIG_EXT4_FS_XATTR
+ 	.setxattr	= generic_setxattr,
+ 	.getxattr	= generic_getxattr,
+ 	.listxattr	= ext4_listxattr,
+@@ -2467,7 +2467,7 @@ const struct inode_operations ext4_dir_inode_operations = {
+ 
+ const struct inode_operations ext4_special_inode_operations = {
+ 	.setattr	= ext4_setattr,
+-#ifdef CONFIG_EXT4DEV_FS_XATTR
++#ifdef CONFIG_EXT4_FS_XATTR
+ 	.setxattr	= generic_setxattr,
+ 	.getxattr	= generic_getxattr,
+ 	.listxattr	= ext4_listxattr,
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 7d865608e817..0e661c569660 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -569,7 +569,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
+ 	ei = kmem_cache_alloc(ext4_inode_cachep, GFP_NOFS);
+ 	if (!ei)
+ 		return NULL;
+-#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
++#ifdef CONFIG_EXT4_FS_POSIX_ACL
+ 	ei->i_acl = EXT4_ACL_NOT_CACHED;
+ 	ei->i_default_acl = EXT4_ACL_NOT_CACHED;
+ #endif
+@@ -605,7 +605,7 @@ static void init_once(void *foo)
+ 	struct ext4_inode_info *ei = (struct ext4_inode_info *) foo;
+ 
+ 	INIT_LIST_HEAD(&ei->i_orphan);
+-#ifdef CONFIG_EXT4DEV_FS_XATTR
++#ifdef CONFIG_EXT4_FS_XATTR
+ 	init_rwsem(&ei->xattr_sem);
+ #endif
+ 	init_rwsem(&ei->i_data_sem);
+@@ -631,7 +631,7 @@ static void destroy_inodecache(void)
+ 
+ static void ext4_clear_inode(struct inode *inode)
+ {
+-#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
++#ifdef CONFIG_EXT4_FS_POSIX_ACL
+ 	if (EXT4_I(inode)->i_acl &&
+ 			EXT4_I(inode)->i_acl != EXT4_ACL_NOT_CACHED) {
+ 		posix_acl_release(EXT4_I(inode)->i_acl);
+@@ -720,7 +720,7 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
+ 		seq_puts(seq, ",debug");
+ 	if (test_opt(sb, OLDALLOC))
+ 		seq_puts(seq, ",oldalloc");
+-#ifdef CONFIG_EXT4DEV_FS_XATTR
++#ifdef CONFIG_EXT4_FS_XATTR
+ 	if (test_opt(sb, XATTR_USER) &&
+ 		!(def_mount_opts & EXT4_DEFM_XATTR_USER))
+ 		seq_puts(seq, ",user_xattr");
+@@ -729,7 +729,7 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
+ 		seq_puts(seq, ",nouser_xattr");
+ 	}
+ #endif
+-#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
++#ifdef CONFIG_EXT4_FS_POSIX_ACL
+ 	if (test_opt(sb, POSIX_ACL) && !(def_mount_opts & EXT4_DEFM_ACL))
+ 		seq_puts(seq, ",acl");
+ 	if (!test_opt(sb, POSIX_ACL) && (def_mount_opts & EXT4_DEFM_ACL))
+@@ -1078,7 +1078,7 @@ static int parse_options(char *options, struct super_block *sb,
+ 		case Opt_orlov:
+ 			clear_opt(sbi->s_mount_opt, OLDALLOC);
+ 			break;
+-#ifdef CONFIG_EXT4DEV_FS_XATTR
++#ifdef CONFIG_EXT4_FS_XATTR
+ 		case Opt_user_xattr:
+ 			set_opt(sbi->s_mount_opt, XATTR_USER);
+ 			break;
+@@ -1092,7 +1092,7 @@ static int parse_options(char *options, struct super_block *sb,
+ 			       "not supported\n");
+ 			break;
+ #endif
+-#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
++#ifdef CONFIG_EXT4_FS_POSIX_ACL
+ 		case Opt_acl:
+ 			set_opt(sbi->s_mount_opt, POSIX_ACL);
+ 			break;
+@@ -1987,11 +1987,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		set_opt(sbi->s_mount_opt, GRPID);
+ 	if (def_mount_opts & EXT4_DEFM_UID16)
+ 		set_opt(sbi->s_mount_opt, NO_UID32);
+-#ifdef CONFIG_EXT4DEV_FS_XATTR
++#ifdef CONFIG_EXT4_FS_XATTR
+ 	if (def_mount_opts & EXT4_DEFM_XATTR_USER)
+ 		set_opt(sbi->s_mount_opt, XATTR_USER);
+ #endif
+-#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
++#ifdef CONFIG_EXT4_FS_POSIX_ACL
+ 	if (def_mount_opts & EXT4_DEFM_ACL)
+ 		set_opt(sbi->s_mount_opt, POSIX_ACL);
+ #endif
+@@ -2049,16 +2049,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		       "EXT4-fs warning: feature flags set on rev 0 fs, "
+ 		       "running e2fsck is recommended\n");
+ 
+-	/*
+-	 * Since ext4 is still considered development code, we require
+-	 * that the TEST_FILESYS flag in s->flags be set.
+-	 */
+-	if (!(le32_to_cpu(es->s_flags) & EXT2_FLAGS_TEST_FILESYS)) {
+-		printk(KERN_WARNING "EXT4-fs: %s: not marked "
+-		       "OK to use with test code.\n", sb->s_id);
+-		goto failed_mount;
+-	}
+-
+ 	/*
+ 	 * Check feature flags regardless of the revision level, since we
+ 	 * previously didn't change the revision level when setting the flags,
+@@ -3580,13 +3570,34 @@ const struct file_operations ext4_ui_proc_fops = {
+ };
+ #endif
+ 
++static struct file_system_type ext4_fs_type = {
++	.owner		= THIS_MODULE,
++	.name		= "ext4",
++	.get_sb		= ext4_get_sb,
++	.kill_sb	= kill_block_super,
++	.fs_flags	= FS_REQUIRES_DEV,
++};
++
++#ifdef CONFIG_EXT4DEV_COMPAT
++static int ext4dev_get_sb(struct file_system_type *fs_type,
++	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
++{
++	printk(KERN_WARNING "EXT4-fs: Update your userspace programs "
++	       "to mount using ext4\n");
++	printk(KERN_WARNING "EXT4-fs: ext4dev backwards compatibility "
++	       "will go away by 2.6.31\n");
++	return get_sb_bdev(fs_type, flags, dev_name, data, ext4_fill_super, mnt);
++}
++
+ static struct file_system_type ext4dev_fs_type = {
+ 	.owner		= THIS_MODULE,
+ 	.name		= "ext4dev",
+-	.get_sb		= ext4_get_sb,
++	.get_sb		= ext4dev_get_sb,
+ 	.kill_sb	= kill_block_super,
+ 	.fs_flags	= FS_REQUIRES_DEV,
+ };
++MODULE_ALIAS("ext4dev");
++#endif
+ 
+ static int __init init_ext4_fs(void)
+ {
+@@ -3603,9 +3614,16 @@ static int __init init_ext4_fs(void)
+ 	err = init_inodecache();
+ 	if (err)
+ 		goto out1;
+-	err = register_filesystem(&ext4dev_fs_type);
++	err = register_filesystem(&ext4_fs_type);
+ 	if (err)
+ 		goto out;
++#ifdef CONFIG_EXT4DEV_COMPAT
++	err = register_filesystem(&ext4dev_fs_type);
++	if (err) {
++		unregister_filesystem(&ext4_fs_type);
++		goto out;
++	}
++#endif
+ 	return 0;
+ out:
+ 	destroy_inodecache();
+@@ -3618,7 +3636,10 @@ static int __init init_ext4_fs(void)
+ 
+ static void __exit exit_ext4_fs(void)
+ {
++	unregister_filesystem(&ext4_fs_type);
++#ifdef CONFIG_EXT4DEV_COMPAT
+ 	unregister_filesystem(&ext4dev_fs_type);
++#endif
+ 	destroy_inodecache();
+ 	exit_ext4_xattr();
+ 	exit_ext4_mballoc();
+diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
+index 0013d52f73bb..00740cb32be3 100644
+--- a/fs/ext4/symlink.c
++++ b/fs/ext4/symlink.c
+@@ -34,7 +34,7 @@ const struct inode_operations ext4_symlink_inode_operations = {
+ 	.readlink	= generic_readlink,
+ 	.follow_link	= page_follow_link_light,
+ 	.put_link	= page_put_link,
+-#ifdef CONFIG_EXT4DEV_FS_XATTR
++#ifdef CONFIG_EXT4_FS_XATTR
+ 	.setxattr	= generic_setxattr,
+ 	.getxattr	= generic_getxattr,
+ 	.listxattr	= ext4_listxattr,
+@@ -45,7 +45,7 @@ const struct inode_operations ext4_symlink_inode_operations = {
+ const struct inode_operations ext4_fast_symlink_inode_operations = {
+ 	.readlink	= generic_readlink,
+ 	.follow_link	= ext4_follow_link,
+-#ifdef CONFIG_EXT4DEV_FS_XATTR
++#ifdef CONFIG_EXT4_FS_XATTR
+ 	.setxattr	= generic_setxattr,
+ 	.getxattr	= generic_getxattr,
+ 	.listxattr	= ext4_listxattr,
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 362b0edd3dbe..80626d516fee 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -99,12 +99,12 @@ static struct mb_cache *ext4_xattr_cache;
+ 
+ static struct xattr_handler *ext4_xattr_handler_map[] = {
+ 	[EXT4_XATTR_INDEX_USER]		     = &ext4_xattr_user_handler,
+-#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
++#ifdef CONFIG_EXT4_FS_POSIX_ACL
+ 	[EXT4_XATTR_INDEX_POSIX_ACL_ACCESS]  = &ext4_xattr_acl_access_handler,
+ 	[EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT] = &ext4_xattr_acl_default_handler,
+ #endif
+ 	[EXT4_XATTR_INDEX_TRUSTED]	     = &ext4_xattr_trusted_handler,
+-#ifdef CONFIG_EXT4DEV_FS_SECURITY
++#ifdef CONFIG_EXT4_FS_SECURITY
+ 	[EXT4_XATTR_INDEX_SECURITY]	     = &ext4_xattr_security_handler,
+ #endif
+ };
+@@ -112,11 +112,11 @@ static struct xattr_handler *ext4_xattr_handler_map[] = {
+ struct xattr_handler *ext4_xattr_handlers[] = {
+ 	&ext4_xattr_user_handler,
+ 	&ext4_xattr_trusted_handler,
+-#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
++#ifdef CONFIG_EXT4_FS_POSIX_ACL
+ 	&ext4_xattr_acl_access_handler,
+ 	&ext4_xattr_acl_default_handler,
+ #endif
+-#ifdef CONFIG_EXT4DEV_FS_SECURITY
++#ifdef CONFIG_EXT4_FS_SECURITY
+ 	&ext4_xattr_security_handler,
+ #endif
+ 	NULL
+diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
+index 814ea58d4d57..8ede88b18c29 100644
+--- a/fs/ext4/xattr.h
++++ b/fs/ext4/xattr.h
+@@ -63,7 +63,7 @@ struct ext4_xattr_entry {
+ 		EXT4_I(inode)->i_extra_isize))
+ #define IFIRST(hdr) ((struct ext4_xattr_entry *)((hdr)+1))
+ 
+-# ifdef CONFIG_EXT4DEV_FS_XATTR
++# ifdef CONFIG_EXT4_FS_XATTR
+ 
+ extern struct xattr_handler ext4_xattr_user_handler;
+ extern struct xattr_handler ext4_xattr_trusted_handler;
+@@ -88,7 +88,7 @@ extern void exit_ext4_xattr(void);
+ 
+ extern struct xattr_handler *ext4_xattr_handlers[];
+ 
+-# else  /* CONFIG_EXT4DEV_FS_XATTR */
++# else  /* CONFIG_EXT4_FS_XATTR */
+ 
+ static inline int
+ ext4_xattr_get(struct inode *inode, int name_index, const char *name,
+@@ -141,9 +141,9 @@ ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
+ 
+ #define ext4_xattr_handlers	NULL
+ 
+-# endif  /* CONFIG_EXT4DEV_FS_XATTR */
++# endif  /* CONFIG_EXT4_FS_XATTR */
+ 
+-#ifdef CONFIG_EXT4DEV_FS_SECURITY
++#ifdef CONFIG_EXT4_FS_SECURITY
+ extern int ext4_init_security(handle_t *handle, struct inode *inode,
+ 				struct inode *dir);
+ #else

commit 08a225f143bf3415fef6f3360d922be35da40543
+Author: Theodore Ts'o 
+Date:   Mon Oct 6 20:58:09 2008 -0400
+
+    Update ext4 MAINTAINERS file
+    
+    The ext4 entry was copied from ext3 and was never correct.  Update it
+    so that Theodore Ts'o is listed as the maintainer, and point the
+    website to http://ext4.wiki.kernel.org.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 8dae4555f10e..dce9cb960e42 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -1639,9 +1639,10 @@ L:	linux-ext4@vger.kernel.org
+ S:	Maintained
+ 
+ EXT4 FILE SYSTEM
+-P:	Stephen Tweedie, Andrew Morton
+-M:	sct@redhat.com, akpm@linux-foundation.org, adilger@sun.com
++P:	Theodore Ts'o
++M:	tytso@mit.edu, adilger@sun.com
+ L:	linux-ext4@vger.kernel.org
++W:	http://ext4.wiki.kernel.org
+ S:	Maintained
+ 
+ F71805F HARDWARE MONITORING DRIVER

commit 45a90bfd90c1215bf824c0f705b409723f52361b
+Author: Theodore Ts'o 
+Date:   Mon Oct 6 12:04:02 2008 -0400
+
+    jbd2: Fix buffer head leak when writing the commit block
+    
+    Also make sure the buffer heads are marked clean before submitting bh
+    for writing.  The previous code was marking the buffer head dirty,
+    which would have forced an unneeded write (and seek) to the journal
+    for no good reason.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index e91f051a9859..0d3814a35ed1 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -127,8 +127,7 @@ static int journal_submit_commit_record(journal_t *journal,
+ 
+ 	JBUFFER_TRACE(descriptor, "submit commit block");
+ 	lock_buffer(bh);
+-	get_bh(bh);
+-	set_buffer_dirty(bh);
++	clear_buffer_dirty(bh);
+ 	set_buffer_uptodate(bh);
+ 	bh->b_end_io = journal_end_buffer_io_sync;
+ 
+@@ -158,7 +157,7 @@ static int journal_submit_commit_record(journal_t *journal,
+ 		/* And try again, without the barrier */
+ 		lock_buffer(bh);
+ 		set_buffer_uptodate(bh);
+-		set_buffer_dirty(bh);
++		clear_buffer_dirty(bh);
+ 		ret = submit_bh(WRITE, bh);
+ 	}
+ 	*cbh = bh;

commit ede86cc473defab74d778aeac14b19f43129d4d1
+Author: Theodore Ts'o 
+Date:   Sun Oct 5 20:50:06 2008 -0400
+
+    ext4: Add debugging markers that can be used by systemtap
+    
+    This debugging markers are designed to debug problems such as the
+    random filesystem latency problems reported by Arjan.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
+index c37d1e86f51a..5afe4370840b 100644
+--- a/fs/ext4/fsync.c
++++ b/fs/ext4/fsync.c
+@@ -28,6 +28,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include "ext4.h"
+ #include "ext4_jbd2.h"
+ 
+@@ -51,6 +52,10 @@ int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync)
+ 
+ 	J_ASSERT(ext4_journal_current_handle() == NULL);
+ 
++	trace_mark(ext4_sync_file, "dev %s datasync %d ino %ld parent %ld",
++		   inode->i_sb->s_id, datasync, inode->i_ino,
++		   dentry->d_parent->d_inode->i_ino);
++
+ 	/*
+ 	 * data=writeback:
+ 	 *  The caller's filemap_fdatawrite()/wait will sync the data.
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index dfcd41fafb9f..9c0214689de0 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -35,6 +35,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -2951,6 +2952,7 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
+ {
+ 	tid_t target;
+ 
++	trace_mark(ext4_sync_fs, "dev %s wait %d", sb->s_id, wait);
+ 	sb->s_dirt = 0;
+ 	if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, &target)) {
+ 		if (wait)
+diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
+index af4651bf3570..42895d369458 100644
+--- a/fs/jbd2/checkpoint.c
++++ b/fs/jbd2/checkpoint.c
+@@ -20,6 +20,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ 
+@@ -328,6 +329,8 @@ int jbd2_log_do_checkpoint(journal_t *journal)
+ 	 * journal straight away.
+ 	 */
+ 	result = jbd2_cleanup_journal_tail(journal);
++	trace_mark(jbd2_checkpoint, "dev %s need_checkpoint %d",
++		   journal->j_devname, result);
+ 	jbd_debug(1, "cleanup_journal_tail returned %d\n", result);
+ 	if (result <= 0)
+ 		return result;
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index b091e5378fe0..e91f051a9859 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -16,6 +16,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -368,6 +369,8 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	commit_transaction = journal->j_running_transaction;
+ 	J_ASSERT(commit_transaction->t_state == T_RUNNING);
+ 
++	trace_mark(jbd2_start_commit, "dev %s transaction %d",
++		   journal->j_devname, commit_transaction->t_tid);
+ 	jbd_debug(1, "JBD: starting commit of transaction %d\n",
+ 			commit_transaction->t_tid);
+ 
+@@ -985,6 +988,9 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	}
+ 	spin_unlock(&journal->j_list_lock);
+ 
++	trace_mark(jbd2_end_commit, "dev %s transaction %d head %d",
++		   journal->j_devname, commit_transaction->t_tid,
++		   journal->j_tail_sequence);
+ 	jbd_debug(1, "JBD: commit %d complete, head %d\n",
+ 		  journal->j_commit_sequence, journal->j_tail_sequence);
+ 

commit c2ea3fde61f1df1dbf062345f23277dcd6f01dfe
+Author: Theodore Ts'o 
+Date:   Fri Oct 10 09:40:52 2008 -0400
+
+    ext4: Remove old legacy block allocator
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index cca7fd53ad7b..59566c082f1b 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -83,6 +83,7 @@ static int ext4_group_used_meta_blocks(struct super_block *sb,
+ 	}
+ 	return used_blocks;
+ }
++
+ /* Initializes an uninitialized block bitmap if given, and returns the
+  * number of blocks free in the group. */
+ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
+@@ -345,303 +346,6 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
+ 	 */
+ 	return bh;
+ }
+-/*
+- * The reservation window structure operations
+- * --------------------------------------------
+- * Operations include:
+- * dump, find, add, remove, is_empty, find_next_reservable_window, etc.
+- *
+- * We use a red-black tree to represent per-filesystem reservation
+- * windows.
+- *
+- */
+-
+-/**
+- * __rsv_window_dump() -- Dump the filesystem block allocation reservation map
+- * @rb_root:		root of per-filesystem reservation rb tree
+- * @verbose:		verbose mode
+- * @fn:			function which wishes to dump the reservation map
+- *
+- * If verbose is turned on, it will print the whole block reservation
+- * windows(start, end).	Otherwise, it will only print out the "bad" windows,
+- * those windows that overlap with their immediate neighbors.
+- */
+-#if 1
+-static void __rsv_window_dump(struct rb_root *root, int verbose,
+-			      const char *fn)
+-{
+-	struct rb_node *n;
+-	struct ext4_reserve_window_node *rsv, *prev;
+-	int bad;
+-
+-restart:
+-	n = rb_first(root);
+-	bad = 0;
+-	prev = NULL;
+-
+-	printk(KERN_DEBUG "Block Allocation Reservation "
+-	       "Windows Map (%s):\n", fn);
+-	while (n) {
+-		rsv = rb_entry(n, struct ext4_reserve_window_node, rsv_node);
+-		if (verbose)
+-			printk(KERN_DEBUG "reservation window 0x%p "
+-			       "start:  %llu, end:  %llu\n",
+-			       rsv, rsv->rsv_start, rsv->rsv_end);
+-		if (rsv->rsv_start && rsv->rsv_start >= rsv->rsv_end) {
+-			printk(KERN_DEBUG "Bad reservation %p (start >= end)\n",
+-			       rsv);
+-			bad = 1;
+-		}
+-		if (prev && prev->rsv_end >= rsv->rsv_start) {
+-			printk(KERN_DEBUG "Bad reservation %p "
+-			       "(prev->end >= start)\n", rsv);
+-			bad = 1;
+-		}
+-		if (bad) {
+-			if (!verbose) {
+-				printk(KERN_DEBUG "Restarting reservation "
+-				       "walk in verbose mode\n");
+-				verbose = 1;
+-				goto restart;
+-			}
+-		}
+-		n = rb_next(n);
+-		prev = rsv;
+-	}
+-	printk(KERN_DEBUG "Window map complete.\n");
+-	BUG_ON(bad);
+-}
+-#define rsv_window_dump(root, verbose) \
+-	__rsv_window_dump((root), (verbose), __func__)
+-#else
+-#define rsv_window_dump(root, verbose) do {} while (0)
+-#endif
+-
+-/**
+- * goal_in_my_reservation()
+- * @rsv:		inode's reservation window
+- * @grp_goal:		given goal block relative to the allocation block group
+- * @group:		the current allocation block group
+- * @sb:			filesystem super block
+- *
+- * Test if the given goal block (group relative) is within the file's
+- * own block reservation window range.
+- *
+- * If the reservation window is outside the goal allocation group, return 0;
+- * grp_goal (given goal block) could be -1, which means no specific
+- * goal block. In this case, always return 1.
+- * If the goal block is within the reservation window, return 1;
+- * otherwise, return 0;
+- */
+-static int
+-goal_in_my_reservation(struct ext4_reserve_window *rsv, ext4_grpblk_t grp_goal,
+-			ext4_group_t group, struct super_block *sb)
+-{
+-	ext4_fsblk_t group_first_block, group_last_block;
+-
+-	group_first_block = ext4_group_first_block_no(sb, group);
+-	group_last_block = group_first_block + (EXT4_BLOCKS_PER_GROUP(sb) - 1);
+-
+-	if ((rsv->_rsv_start > group_last_block) ||
+-	    (rsv->_rsv_end < group_first_block))
+-		return 0;
+-	if ((grp_goal >= 0) && ((grp_goal + group_first_block < rsv->_rsv_start)
+-		|| (grp_goal + group_first_block > rsv->_rsv_end)))
+-		return 0;
+-	return 1;
+-}
+-
+-/**
+- * search_reserve_window()
+- * @rb_root:		root of reservation tree
+- * @goal:		target allocation block
+- *
+- * Find the reserved window which includes the goal, or the previous one
+- * if the goal is not in any window.
+- * Returns NULL if there are no windows or if all windows start after the goal.
+- */
+-static struct ext4_reserve_window_node *
+-search_reserve_window(struct rb_root *root, ext4_fsblk_t goal)
+-{
+-	struct rb_node *n = root->rb_node;
+-	struct ext4_reserve_window_node *rsv;
+-
+-	if (!n)
+-		return NULL;
+-
+-	do {
+-		rsv = rb_entry(n, struct ext4_reserve_window_node, rsv_node);
+-
+-		if (goal < rsv->rsv_start)
+-			n = n->rb_left;
+-		else if (goal > rsv->rsv_end)
+-			n = n->rb_right;
+-		else
+-			return rsv;
+-	} while (n);
+-	/*
+-	 * We've fallen off the end of the tree: the goal wasn't inside
+-	 * any particular node.  OK, the previous node must be to one
+-	 * side of the interval containing the goal.  If it's the RHS,
+-	 * we need to back up one.
+-	 */
+-	if (rsv->rsv_start > goal) {
+-		n = rb_prev(&rsv->rsv_node);
+-		rsv = rb_entry(n, struct ext4_reserve_window_node, rsv_node);
+-	}
+-	return rsv;
+-}
+-
+-/**
+- * ext4_rsv_window_add() -- Insert a window to the block reservation rb tree.
+- * @sb:			super block
+- * @rsv:		reservation window to add
+- *
+- * Must be called with rsv_lock hold.
+- */
+-void ext4_rsv_window_add(struct super_block *sb,
+-		    struct ext4_reserve_window_node *rsv)
+-{
+-	struct rb_root *root = &EXT4_SB(sb)->s_rsv_window_root;
+-	struct rb_node *node = &rsv->rsv_node;
+-	ext4_fsblk_t start = rsv->rsv_start;
+-
+-	struct rb_node **p = &root->rb_node;
+-	struct rb_node *parent = NULL;
+-	struct ext4_reserve_window_node *this;
+-
+-	while (*p)
+-	{
+-		parent = *p;
+-		this = rb_entry(parent, struct ext4_reserve_window_node, rsv_node);
+-
+-		if (start < this->rsv_start)
+-			p = &(*p)->rb_left;
+-		else if (start > this->rsv_end)
+-			p = &(*p)->rb_right;
+-		else {
+-			rsv_window_dump(root, 1);
+-			BUG();
+-		}
+-	}
+-
+-	rb_link_node(node, parent, p);
+-	rb_insert_color(node, root);
+-}
+-
+-/**
+- * ext4_rsv_window_remove() -- unlink a window from the reservation rb tree
+- * @sb:			super block
+- * @rsv:		reservation window to remove
+- *
+- * Mark the block reservation window as not allocated, and unlink it
+- * from the filesystem reservation window rb tree. Must be called with
+- * rsv_lock hold.
+- */
+-static void rsv_window_remove(struct super_block *sb,
+-			      struct ext4_reserve_window_node *rsv)
+-{
+-	rsv->rsv_start = EXT4_RESERVE_WINDOW_NOT_ALLOCATED;
+-	rsv->rsv_end = EXT4_RESERVE_WINDOW_NOT_ALLOCATED;
+-	rsv->rsv_alloc_hit = 0;
+-	rb_erase(&rsv->rsv_node, &EXT4_SB(sb)->s_rsv_window_root);
+-}
+-
+-/*
+- * rsv_is_empty() -- Check if the reservation window is allocated.
+- * @rsv:		given reservation window to check
+- *
+- * returns 1 if the end block is EXT4_RESERVE_WINDOW_NOT_ALLOCATED.
+- */
+-static inline int rsv_is_empty(struct ext4_reserve_window *rsv)
+-{
+-	/* a valid reservation end block could not be 0 */
+-	return rsv->_rsv_end == EXT4_RESERVE_WINDOW_NOT_ALLOCATED;
+-}
+-
+-/**
+- * ext4_init_block_alloc_info()
+- * @inode:		file inode structure
+- *
+- * Allocate and initialize the	reservation window structure, and
+- * link the window to the ext4 inode structure at last
+- *
+- * The reservation window structure is only dynamically allocated
+- * and linked to ext4 inode the first time the open file
+- * needs a new block. So, before every ext4_new_block(s) call, for
+- * regular files, we should check whether the reservation window
+- * structure exists or not. In the latter case, this function is called.
+- * Fail to do so will result in block reservation being turned off for that
+- * open file.
+- *
+- * This function is called from ext4_get_blocks_handle(), also called
+- * when setting the reservation window size through ioctl before the file
+- * is open for write (needs block allocation).
+- *
+- * Needs down_write(i_data_sem) protection prior to call this function.
+- */
+-void ext4_init_block_alloc_info(struct inode *inode)
+-{
+-	struct ext4_inode_info *ei = EXT4_I(inode);
+-	struct ext4_block_alloc_info *block_i = ei->i_block_alloc_info;
+-	struct super_block *sb = inode->i_sb;
+-
+-	block_i = kmalloc(sizeof(*block_i), GFP_NOFS);
+-	if (block_i) {
+-		struct ext4_reserve_window_node *rsv = &block_i->rsv_window_node;
+-
+-		rsv->rsv_start = EXT4_RESERVE_WINDOW_NOT_ALLOCATED;
+-		rsv->rsv_end = EXT4_RESERVE_WINDOW_NOT_ALLOCATED;
+-
+-		/*
+-		 * if filesystem is mounted with NORESERVATION, the goal
+-		 * reservation window size is set to zero to indicate
+-		 * block reservation is off
+-		 */
+-		if (!test_opt(sb, RESERVATION))
+-			rsv->rsv_goal_size = 0;
+-		else
+-			rsv->rsv_goal_size = EXT4_DEFAULT_RESERVE_BLOCKS;
+-		rsv->rsv_alloc_hit = 0;
+-		block_i->last_alloc_logical_block = 0;
+-		block_i->last_alloc_physical_block = 0;
+-	}
+-	ei->i_block_alloc_info = block_i;
+-}
+-
+-/**
+- * ext4_discard_reservation()
+- * @inode:		inode
+- *
+- * Discard(free) block reservation window on last file close, or truncate
+- * or at last iput().
+- *
+- * It is being called in three cases:
+- *	ext4_release_file(): last writer close the file
+- *	ext4_clear_inode(): last iput(), when nobody link to this file.
+- *	ext4_truncate(): when the block indirect map is about to change.
+- *
+- */
+-void ext4_discard_reservation(struct inode *inode)
+-{
+-	struct ext4_inode_info *ei = EXT4_I(inode);
+-	struct ext4_block_alloc_info *block_i = ei->i_block_alloc_info;
+-	struct ext4_reserve_window_node *rsv;
+-	spinlock_t *rsv_lock = &EXT4_SB(inode->i_sb)->s_rsv_window_lock;
+-
+-	ext4_mb_discard_inode_preallocations(inode);
+-
+-	if (!block_i)
+-		return;
+-
+-	rsv = &block_i->rsv_window_node;
+-	if (!rsv_is_empty(&rsv->rsv_window)) {
+-		spin_lock(rsv_lock);
+-		if (!rsv_is_empty(&rsv->rsv_window))
+-			rsv_window_remove(inode->i_sb, rsv);
+-		spin_unlock(rsv_lock);
+-	}
+-}
+ 
+ /**
+  * ext4_free_blocks_sb() -- Free given blocks and update quota
+@@ -650,6 +354,13 @@ void ext4_discard_reservation(struct inode *inode)
+  * @block:			start physcial block to free
+  * @count:			number of blocks to free
+  * @pdquot_freed_blocks:	pointer to quota
++ *
++ * XXX This function is only used by the on-line resizing code, which
++ * should probably be fixed up to call the mballoc variant.  There
++ * this needs to be cleaned up later; in fact, I'm not convinced this
++ * is 100% correct in the face of the mballoc code.  The online resizing
++ * code needs to be fixed up to more tightly (and correctly) interlock
++ * with the mballoc code.
+  */
+ void ext4_free_blocks_sb(handle_t *handle, struct super_block *sb,
+ 			 ext4_fsblk_t block, unsigned long count,
+@@ -861,747 +572,13 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 
+ 	sb = inode->i_sb;
+ 
+-	if (!test_opt(sb, MBALLOC) || !EXT4_SB(sb)->s_group_info)
+-		ext4_free_blocks_sb(handle, sb, block, count,
+-						&dquot_freed_blocks);
+-	else
+-		ext4_mb_free_blocks(handle, inode, block, count,
+-						metadata, &dquot_freed_blocks);
++	ext4_mb_free_blocks(handle, inode, block, count,
++			    metadata, &dquot_freed_blocks);
+ 	if (dquot_freed_blocks)
+ 		DQUOT_FREE_BLOCK(inode, dquot_freed_blocks);
+ 	return;
+ }
+ 
+-/**
+- * ext4_test_allocatable()
+- * @nr:			given allocation block group
+- * @bh:			bufferhead contains the bitmap of the given block group
+- *
+- * For ext4 allocations, we must not reuse any blocks which are
+- * allocated in the bitmap buffer's "last committed data" copy.  This
+- * prevents deletes from freeing up the page for reuse until we have
+- * committed the delete transaction.
+- *
+- * If we didn't do this, then deleting something and reallocating it as
+- * data would allow the old block to be overwritten before the
+- * transaction committed (because we force data to disk before commit).
+- * This would lead to corruption if we crashed between overwriting the
+- * data and committing the delete.
+- *
+- * @@@ We may want to make this allocation behaviour conditional on
+- * data-writes at some point, and disable it for metadata allocations or
+- * sync-data inodes.
+- */
+-static int ext4_test_allocatable(ext4_grpblk_t nr, struct buffer_head *bh)
+-{
+-	int ret;
+-	struct journal_head *jh = bh2jh(bh);
+-
+-	if (ext4_test_bit(nr, bh->b_data))
+-		return 0;
+-
+-	jbd_lock_bh_state(bh);
+-	if (!jh->b_committed_data)
+-		ret = 1;
+-	else
+-		ret = !ext4_test_bit(nr, jh->b_committed_data);
+-	jbd_unlock_bh_state(bh);
+-	return ret;
+-}
+-
+-/**
+- * bitmap_search_next_usable_block()
+- * @start:		the starting block (group relative) of the search
+- * @bh:			bufferhead contains the block group bitmap
+- * @maxblocks:		the ending block (group relative) of the reservation
+- *
+- * The bitmap search --- search forward alternately through the actual
+- * bitmap on disk and the last-committed copy in journal, until we find a
+- * bit free in both bitmaps.
+- */
+-static ext4_grpblk_t
+-bitmap_search_next_usable_block(ext4_grpblk_t start, struct buffer_head *bh,
+-					ext4_grpblk_t maxblocks)
+-{
+-	ext4_grpblk_t next;
+-	struct journal_head *jh = bh2jh(bh);
+-
+-	while (start < maxblocks) {
+-		next = ext4_find_next_zero_bit(bh->b_data, maxblocks, start);
+-		if (next >= maxblocks)
+-			return -1;
+-		if (ext4_test_allocatable(next, bh))
+-			return next;
+-		jbd_lock_bh_state(bh);
+-		if (jh->b_committed_data)
+-			start = ext4_find_next_zero_bit(jh->b_committed_data,
+-							maxblocks, next);
+-		jbd_unlock_bh_state(bh);
+-	}
+-	return -1;
+-}
+-
+-/**
+- * find_next_usable_block()
+- * @start:		the starting block (group relative) to find next
+- *			allocatable block in bitmap.
+- * @bh:			bufferhead contains the block group bitmap
+- * @maxblocks:		the ending block (group relative) for the search
+- *
+- * Find an allocatable block in a bitmap.  We honor both the bitmap and
+- * its last-committed copy (if that exists), and perform the "most
+- * appropriate allocation" algorithm of looking for a free block near
+- * the initial goal; then for a free byte somewhere in the bitmap; then
+- * for any free bit in the bitmap.
+- */
+-static ext4_grpblk_t
+-find_next_usable_block(ext4_grpblk_t start, struct buffer_head *bh,
+-			ext4_grpblk_t maxblocks)
+-{
+-	ext4_grpblk_t here, next;
+-	char *p, *r;
+-
+-	if (start > 0) {
+-		/*
+-		 * The goal was occupied; search forward for a free
+-		 * block within the next XX blocks.
+-		 *
+-		 * end_goal is more or less random, but it has to be
+-		 * less than EXT4_BLOCKS_PER_GROUP. Aligning up to the
+-		 * next 64-bit boundary is simple..
+-		 */
+-		ext4_grpblk_t end_goal = (start + 63) & ~63;
+-		if (end_goal > maxblocks)
+-			end_goal = maxblocks;
+-		here = ext4_find_next_zero_bit(bh->b_data, end_goal, start);
+-		if (here < end_goal && ext4_test_allocatable(here, bh))
+-			return here;
+-		ext4_debug("Bit not found near goal\n");
+-	}
+-
+-	here = start;
+-	if (here < 0)
+-		here = 0;
+-
+-	p = ((char *)bh->b_data) + (here >> 3);
+-	r = memscan(p, 0, ((maxblocks + 7) >> 3) - (here >> 3));
+-	next = (r - ((char *)bh->b_data)) << 3;
+-
+-	if (next < maxblocks && next >= start && ext4_test_allocatable(next, bh))
+-		return next;
+-
+-	/*
+-	 * The bitmap search --- search forward alternately through the actual
+-	 * bitmap and the last-committed copy until we find a bit free in
+-	 * both
+-	 */
+-	here = bitmap_search_next_usable_block(here, bh, maxblocks);
+-	return here;
+-}
+-
+-/**
+- * claim_block()
+- * @block:		the free block (group relative) to allocate
+- * @bh:			the bufferhead containts the block group bitmap
+- *
+- * We think we can allocate this block in this bitmap.  Try to set the bit.
+- * If that succeeds then check that nobody has allocated and then freed the
+- * block since we saw that is was not marked in b_committed_data.  If it _was_
+- * allocated and freed then clear the bit in the bitmap again and return
+- * zero (failure).
+- */
+-static inline int
+-claim_block(spinlock_t *lock, ext4_grpblk_t block, struct buffer_head *bh)
+-{
+-	struct journal_head *jh = bh2jh(bh);
+-	int ret;
+-
+-	if (ext4_set_bit_atomic(lock, block, bh->b_data))
+-		return 0;
+-	jbd_lock_bh_state(bh);
+-	if (jh->b_committed_data && ext4_test_bit(block, jh->b_committed_data)) {
+-		ext4_clear_bit_atomic(lock, block, bh->b_data);
+-		ret = 0;
+-	} else {
+-		ret = 1;
+-	}
+-	jbd_unlock_bh_state(bh);
+-	return ret;
+-}
+-
+-/**
+- * ext4_try_to_allocate()
+- * @sb:			superblock
+- * @handle:		handle to this transaction
+- * @group:		given allocation block group
+- * @bitmap_bh:		bufferhead holds the block bitmap
+- * @grp_goal:		given target block within the group
+- * @count:		target number of blocks to allocate
+- * @my_rsv:		reservation window
+- *
+- * Attempt to allocate blocks within a give range. Set the range of allocation
+- * first, then find the first free bit(s) from the bitmap (within the range),
+- * and at last, allocate the blocks by claiming the found free bit as allocated.
+- *
+- * To set the range of this allocation:
+- *	if there is a reservation window, only try to allocate block(s) from the
+- *	file's own reservation window;
+- *	Otherwise, the allocation range starts from the give goal block, ends at
+- *	the block group's last block.
+- *
+- * If we failed to allocate the desired block then we may end up crossing to a
+- * new bitmap.  In that case we must release write access to the old one via
+- * ext4_journal_release_buffer(), else we'll run out of credits.
+- */
+-static ext4_grpblk_t
+-ext4_try_to_allocate(struct super_block *sb, handle_t *handle,
+-			ext4_group_t group, struct buffer_head *bitmap_bh,
+-			ext4_grpblk_t grp_goal, unsigned long *count,
+-			struct ext4_reserve_window *my_rsv)
+-{
+-	ext4_fsblk_t group_first_block;
+-	ext4_grpblk_t start, end;
+-	unsigned long num = 0;
+-
+-	/* we do allocation within the reservation window if we have a window */
+-	if (my_rsv) {
+-		group_first_block = ext4_group_first_block_no(sb, group);
+-		if (my_rsv->_rsv_start >= group_first_block)
+-			start = my_rsv->_rsv_start - group_first_block;
+-		else
+-			/* reservation window cross group boundary */
+-			start = 0;
+-		end = my_rsv->_rsv_end - group_first_block + 1;
+-		if (end > EXT4_BLOCKS_PER_GROUP(sb))
+-			/* reservation window crosses group boundary */
+-			end = EXT4_BLOCKS_PER_GROUP(sb);
+-		if ((start <= grp_goal) && (grp_goal < end))
+-			start = grp_goal;
+-		else
+-			grp_goal = -1;
+-	} else {
+-		if (grp_goal > 0)
+-			start = grp_goal;
+-		else
+-			start = 0;
+-		end = EXT4_BLOCKS_PER_GROUP(sb);
+-	}
+-
+-	BUG_ON(start > EXT4_BLOCKS_PER_GROUP(sb));
+-
+-repeat:
+-	if (grp_goal < 0 || !ext4_test_allocatable(grp_goal, bitmap_bh)) {
+-		grp_goal = find_next_usable_block(start, bitmap_bh, end);
+-		if (grp_goal < 0)
+-			goto fail_access;
+-		if (!my_rsv) {
+-			int i;
+-
+-			for (i = 0; i < 7 && grp_goal > start &&
+-					ext4_test_allocatable(grp_goal - 1,
+-								bitmap_bh);
+-					i++, grp_goal--)
+-				;
+-		}
+-	}
+-	start = grp_goal;
+-
+-	if (!claim_block(sb_bgl_lock(EXT4_SB(sb), group),
+-		grp_goal, bitmap_bh)) {
+-		/*
+-		 * The block was allocated by another thread, or it was
+-		 * allocated and then freed by another thread
+-		 */
+-		start++;
+-		grp_goal++;
+-		if (start >= end)
+-			goto fail_access;
+-		goto repeat;
+-	}
+-	num++;
+-	grp_goal++;
+-	while (num < *count && grp_goal < end
+-		&& ext4_test_allocatable(grp_goal, bitmap_bh)
+-		&& claim_block(sb_bgl_lock(EXT4_SB(sb), group),
+-				grp_goal, bitmap_bh)) {
+-		num++;
+-		grp_goal++;
+-	}
+-	*count = num;
+-	return grp_goal - num;
+-fail_access:
+-	*count = num;
+-	return -1;
+-}
+-
+-/**
+- *	find_next_reservable_window():
+- *		find a reservable space within the given range.
+- *		It does not allocate the reservation window for now:
+- *		alloc_new_reservation() will do the work later.
+- *
+- *	@search_head: the head of the searching list;
+- *		This is not necessarily the list head of the whole filesystem
+- *
+- *		We have both head and start_block to assist the search
+- *		for the reservable space. The list starts from head,
+- *		but we will shift to the place where start_block is,
+- *		then start from there, when looking for a reservable space.
+- *
+- *	@size: the target new reservation window size
+- *
+- *	@group_first_block: the first block we consider to start
+- *			the real search from
+- *
+- *	@last_block:
+- *		the maximum block number that our goal reservable space
+- *		could start from. This is normally the last block in this
+- *		group. The search will end when we found the start of next
+- *		possible reservable space is out of this boundary.
+- *		This could handle the cross boundary reservation window
+- *		request.
+- *
+- *	basically we search from the given range, rather than the whole
+- *	reservation double linked list, (start_block, last_block)
+- *	to find a free region that is of my size and has not
+- *	been reserved.
+- *
+- */
+-static int find_next_reservable_window(
+-				struct ext4_reserve_window_node *search_head,
+-				struct ext4_reserve_window_node *my_rsv,
+-				struct super_block *sb,
+-				ext4_fsblk_t start_block,
+-				ext4_fsblk_t last_block)
+-{
+-	struct rb_node *next;
+-	struct ext4_reserve_window_node *rsv, *prev;
+-	ext4_fsblk_t cur;
+-	int size = my_rsv->rsv_goal_size;
+-
+-	/* TODO: make the start of the reservation window byte-aligned */
+-	/* cur = *start_block & ~7;*/
+-	cur = start_block;
+-	rsv = search_head;
+-	if (!rsv)
+-		return -1;
+-
+-	while (1) {
+-		if (cur <= rsv->rsv_end)
+-			cur = rsv->rsv_end + 1;
+-
+-		/* TODO?
+-		 * in the case we could not find a reservable space
+-		 * that is what is expected, during the re-search, we could
+-		 * remember what's the largest reservable space we could have
+-		 * and return that one.
+-		 *
+-		 * For now it will fail if we could not find the reservable
+-		 * space with expected-size (or more)...
+-		 */
+-		if (cur > last_block)
+-			return -1;		/* fail */
+-
+-		prev = rsv;
+-		next = rb_next(&rsv->rsv_node);
+-		rsv = rb_entry(next, struct ext4_reserve_window_node, rsv_node);
+-
+-		/*
+-		 * Reached the last reservation, we can just append to the
+-		 * previous one.
+-		 */
+-		if (!next)
+-			break;
+-
+-		if (cur + size <= rsv->rsv_start) {
+-			/*
+-			 * Found a reserveable space big enough.  We could
+-			 * have a reservation across the group boundary here
+-			 */
+-			break;
+-		}
+-	}
+-	/*
+-	 * we come here either :
+-	 * when we reach the end of the whole list,
+-	 * and there is empty reservable space after last entry in the list.
+-	 * append it to the end of the list.
+-	 *
+-	 * or we found one reservable space in the middle of the list,
+-	 * return the reservation window that we could append to.
+-	 * succeed.
+-	 */
+-
+-	if ((prev != my_rsv) && (!rsv_is_empty(&my_rsv->rsv_window)))
+-		rsv_window_remove(sb, my_rsv);
+-
+-	/*
+-	 * Let's book the whole avaliable window for now.  We will check the
+-	 * disk bitmap later and then, if there are free blocks then we adjust
+-	 * the window size if it's larger than requested.
+-	 * Otherwise, we will remove this node from the tree next time
+-	 * call find_next_reservable_window.
+-	 */
+-	my_rsv->rsv_start = cur;
+-	my_rsv->rsv_end = cur + size - 1;
+-	my_rsv->rsv_alloc_hit = 0;
+-
+-	if (prev != my_rsv)
+-		ext4_rsv_window_add(sb, my_rsv);
+-
+-	return 0;
+-}
+-
+-/**
+- *	alloc_new_reservation()--allocate a new reservation window
+- *
+- *		To make a new reservation, we search part of the filesystem
+- *		reservation list (the list that inside the group). We try to
+- *		allocate a new reservation window near the allocation goal,
+- *		or the beginning of the group, if there is no goal.
+- *
+- *		We first find a reservable space after the goal, then from
+- *		there, we check the bitmap for the first free block after
+- *		it. If there is no free block until the end of group, then the
+- *		whole group is full, we failed. Otherwise, check if the free
+- *		block is inside the expected reservable space, if so, we
+- *		succeed.
+- *		If the first free block is outside the reservable space, then
+- *		start from the first free block, we search for next available
+- *		space, and go on.
+- *
+- *	on succeed, a new reservation will be found and inserted into the list
+- *	It contains at least one free block, and it does not overlap with other
+- *	reservation windows.
+- *
+- *	failed: we failed to find a reservation window in this group
+- *
+- *	@rsv: the reservation
+- *
+- *	@grp_goal: The goal (group-relative).  It is where the search for a
+- *		free reservable space should start from.
+- *		if we have a grp_goal(grp_goal >0 ), then start from there,
+- *		no grp_goal(grp_goal = -1), we start from the first block
+- *		of the group.
+- *
+- *	@sb: the super block
+- *	@group: the group we are trying to allocate in
+- *	@bitmap_bh: the block group block bitmap
+- *
+- */
+-static int alloc_new_reservation(struct ext4_reserve_window_node *my_rsv,
+-		ext4_grpblk_t grp_goal, struct super_block *sb,
+-		ext4_group_t group, struct buffer_head *bitmap_bh)
+-{
+-	struct ext4_reserve_window_node *search_head;
+-	ext4_fsblk_t group_first_block, group_end_block, start_block;
+-	ext4_grpblk_t first_free_block;
+-	struct rb_root *fs_rsv_root = &EXT4_SB(sb)->s_rsv_window_root;
+-	unsigned long size;
+-	int ret;
+-	spinlock_t *rsv_lock = &EXT4_SB(sb)->s_rsv_window_lock;
+-
+-	group_first_block = ext4_group_first_block_no(sb, group);
+-	group_end_block = group_first_block + (EXT4_BLOCKS_PER_GROUP(sb) - 1);
+-
+-	if (grp_goal < 0)
+-		start_block = group_first_block;
+-	else
+-		start_block = grp_goal + group_first_block;
+-
+-	size = my_rsv->rsv_goal_size;
+-
+-	if (!rsv_is_empty(&my_rsv->rsv_window)) {
+-		/*
+-		 * if the old reservation is cross group boundary
+-		 * and if the goal is inside the old reservation window,
+-		 * we will come here when we just failed to allocate from
+-		 * the first part of the window. We still have another part
+-		 * that belongs to the next group. In this case, there is no
+-		 * point to discard our window and try to allocate a new one
+-		 * in this group(which will fail). we should
+-		 * keep the reservation window, just simply move on.
+-		 *
+-		 * Maybe we could shift the start block of the reservation
+-		 * window to the first block of next group.
+-		 */
+-
+-		if ((my_rsv->rsv_start <= group_end_block) &&
+-				(my_rsv->rsv_end > group_end_block) &&
+-				(start_block >= my_rsv->rsv_start))
+-			return -1;
+-
+-		if ((my_rsv->rsv_alloc_hit >
+-		     (my_rsv->rsv_end - my_rsv->rsv_start + 1) / 2)) {
+-			/*
+-			 * if the previously allocation hit ratio is
+-			 * greater than 1/2, then we double the size of
+-			 * the reservation window the next time,
+-			 * otherwise we keep the same size window
+-			 */
+-			size = size * 2;
+-			if (size > EXT4_MAX_RESERVE_BLOCKS)
+-				size = EXT4_MAX_RESERVE_BLOCKS;
+-			my_rsv->rsv_goal_size = size;
+-		}
+-	}
+-
+-	spin_lock(rsv_lock);
+-	/*
+-	 * shift the search start to the window near the goal block
+-	 */
+-	search_head = search_reserve_window(fs_rsv_root, start_block);
+-
+-	/*
+-	 * find_next_reservable_window() simply finds a reservable window
+-	 * inside the given range(start_block, group_end_block).
+-	 *
+-	 * To make sure the reservation window has a free bit inside it, we
+-	 * need to check the bitmap after we found a reservable window.
+-	 */
+-retry:
+-	ret = find_next_reservable_window(search_head, my_rsv, sb,
+-						start_block, group_end_block);
+-
+-	if (ret == -1) {
+-		if (!rsv_is_empty(&my_rsv->rsv_window))
+-			rsv_window_remove(sb, my_rsv);
+-		spin_unlock(rsv_lock);
+-		return -1;
+-	}
+-
+-	/*
+-	 * On success, find_next_reservable_window() returns the
+-	 * reservation window where there is a reservable space after it.
+-	 * Before we reserve this reservable space, we need
+-	 * to make sure there is at least a free block inside this region.
+-	 *
+-	 * searching the first free bit on the block bitmap and copy of
+-	 * last committed bitmap alternatively, until we found a allocatable
+-	 * block. Search start from the start block of the reservable space
+-	 * we just found.
+-	 */
+-	spin_unlock(rsv_lock);
+-	first_free_block = bitmap_search_next_usable_block(
+-			my_rsv->rsv_start - group_first_block,
+-			bitmap_bh, group_end_block - group_first_block + 1);
+-
+-	if (first_free_block < 0) {
+-		/*
+-		 * no free block left on the bitmap, no point
+-		 * to reserve the space. return failed.
+-		 */
+-		spin_lock(rsv_lock);
+-		if (!rsv_is_empty(&my_rsv->rsv_window))
+-			rsv_window_remove(sb, my_rsv);
+-		spin_unlock(rsv_lock);
+-		return -1;		/* failed */
+-	}
+-
+-	start_block = first_free_block + group_first_block;
+-	/*
+-	 * check if the first free block is within the
+-	 * free space we just reserved
+-	 */
+-	if (start_block >= my_rsv->rsv_start && start_block <= my_rsv->rsv_end)
+-		return 0;		/* success */
+-	/*
+-	 * if the first free bit we found is out of the reservable space
+-	 * continue search for next reservable space,
+-	 * start from where the free block is,
+-	 * we also shift the list head to where we stopped last time
+-	 */
+-	search_head = my_rsv;
+-	spin_lock(rsv_lock);
+-	goto retry;
+-}
+-
+-/**
+- * try_to_extend_reservation()
+- * @my_rsv:		given reservation window
+- * @sb:			super block
+- * @size:		the delta to extend
+- *
+- * Attempt to expand the reservation window large enough to have
+- * required number of free blocks
+- *
+- * Since ext4_try_to_allocate() will always allocate blocks within
+- * the reservation window range, if the window size is too small,
+- * multiple blocks allocation has to stop at the end of the reservation
+- * window. To make this more efficient, given the total number of
+- * blocks needed and the current size of the window, we try to
+- * expand the reservation window size if necessary on a best-effort
+- * basis before ext4_new_blocks() tries to allocate blocks,
+- */
+-static void try_to_extend_reservation(struct ext4_reserve_window_node *my_rsv,
+-			struct super_block *sb, int size)
+-{
+-	struct ext4_reserve_window_node *next_rsv;
+-	struct rb_node *next;
+-	spinlock_t *rsv_lock = &EXT4_SB(sb)->s_rsv_window_lock;
+-
+-	if (!spin_trylock(rsv_lock))
+-		return;
+-
+-	next = rb_next(&my_rsv->rsv_node);
+-
+-	if (!next)
+-		my_rsv->rsv_end += size;
+-	else {
+-		next_rsv = rb_entry(next, struct ext4_reserve_window_node, rsv_node);
+-
+-		if ((next_rsv->rsv_start - my_rsv->rsv_end - 1) >= size)
+-			my_rsv->rsv_end += size;
+-		else
+-			my_rsv->rsv_end = next_rsv->rsv_start - 1;
+-	}
+-	spin_unlock(rsv_lock);
+-}
+-
+-/**
+- * ext4_try_to_allocate_with_rsv()
+- * @sb:			superblock
+- * @handle:		handle to this transaction
+- * @group:		given allocation block group
+- * @bitmap_bh:		bufferhead holds the block bitmap
+- * @grp_goal:		given target block within the group
+- * @count:		target number of blocks to allocate
+- * @my_rsv:		reservation window
+- * @errp:		pointer to store the error code
+- *
+- * This is the main function used to allocate a new block and its reservation
+- * window.
+- *
+- * Each time when a new block allocation is need, first try to allocate from
+- * its own reservation.  If it does not have a reservation window, instead of
+- * looking for a free bit on bitmap first, then look up the reservation list to
+- * see if it is inside somebody else's reservation window, we try to allocate a
+- * reservation window for it starting from the goal first. Then do the block
+- * allocation within the reservation window.
+- *
+- * This will avoid keeping on searching the reservation list again and
+- * again when somebody is looking for a free block (without
+- * reservation), and there are lots of free blocks, but they are all
+- * being reserved.
+- *
+- * We use a red-black tree for the per-filesystem reservation list.
+- *
+- */
+-static ext4_grpblk_t
+-ext4_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
+-			ext4_group_t group, struct buffer_head *bitmap_bh,
+-			ext4_grpblk_t grp_goal,
+-			struct ext4_reserve_window_node *my_rsv,
+-			unsigned long *count, int *errp)
+-{
+-	ext4_fsblk_t group_first_block, group_last_block;
+-	ext4_grpblk_t ret = 0;
+-	int fatal;
+-	unsigned long num = *count;
+-
+-	*errp = 0;
+-
+-	/*
+-	 * Make sure we use undo access for the bitmap, because it is critical
+-	 * that we do the frozen_data COW on bitmap buffers in all cases even
+-	 * if the buffer is in BJ_Forget state in the committing transaction.
+-	 */
+-	BUFFER_TRACE(bitmap_bh, "get undo access for new block");
+-	fatal = ext4_journal_get_undo_access(handle, bitmap_bh);
+-	if (fatal) {
+-		*errp = fatal;
+-		return -1;
+-	}
+-
+-	/*
+-	 * we don't deal with reservation when
+-	 * filesystem is mounted without reservation
+-	 * or the file is not a regular file
+-	 * or last attempt to allocate a block with reservation turned on failed
+-	 */
+-	if (my_rsv == NULL) {
+-		ret = ext4_try_to_allocate(sb, handle, group, bitmap_bh,
+-						grp_goal, count, NULL);
+-		goto out;
+-	}
+-	/*
+-	 * grp_goal is a group relative block number (if there is a goal)
+-	 * 0 <= grp_goal < EXT4_BLOCKS_PER_GROUP(sb)
+-	 * first block is a filesystem wide block number
+-	 * first block is the block number of the first block in this group
+-	 */
+-	group_first_block = ext4_group_first_block_no(sb, group);
+-	group_last_block = group_first_block + (EXT4_BLOCKS_PER_GROUP(sb) - 1);
+-
+-	/*
+-	 * Basically we will allocate a new block from inode's reservation
+-	 * window.
+-	 *
+-	 * We need to allocate a new reservation window, if:
+-	 * a) inode does not have a reservation window; or
+-	 * b) last attempt to allocate a block from existing reservation
+-	 *    failed; or
+-	 * c) we come here with a goal and with a reservation window
+-	 *
+-	 * We do not need to allocate a new reservation window if we come here
+-	 * at the beginning with a goal and the goal is inside the window, or
+-	 * we don't have a goal but already have a reservation window.
+-	 * then we could go to allocate from the reservation window directly.
+-	 */
+-	while (1) {
+-		if (rsv_is_empty(&my_rsv->rsv_window) || (ret < 0) ||
+-			!goal_in_my_reservation(&my_rsv->rsv_window,
+-						grp_goal, group, sb)) {
+-			if (my_rsv->rsv_goal_size < *count)
+-				my_rsv->rsv_goal_size = *count;
+-			ret = alloc_new_reservation(my_rsv, grp_goal, sb,
+-							group, bitmap_bh);
+-			if (ret < 0)
+-				break;			/* failed */
+-
+-			if (!goal_in_my_reservation(&my_rsv->rsv_window,
+-							grp_goal, group, sb))
+-				grp_goal = -1;
+-		} else if (grp_goal >= 0) {
+-			int curr = my_rsv->rsv_end -
+-					(grp_goal + group_first_block) + 1;
+-
+-			if (curr < *count)
+-				try_to_extend_reservation(my_rsv, sb,
+-							*count - curr);
+-		}
+-
+-		if ((my_rsv->rsv_start > group_last_block) ||
+-				(my_rsv->rsv_end < group_first_block)) {
+-			rsv_window_dump(&EXT4_SB(sb)->s_rsv_window_root, 1);
+-			BUG();
+-		}
+-		ret = ext4_try_to_allocate(sb, handle, group, bitmap_bh,
+-					   grp_goal, &num, &my_rsv->rsv_window);
+-		if (ret >= 0) {
+-			my_rsv->rsv_alloc_hit += num;
+-			*count = num;
+-			break;				/* succeed */
+-		}
+-		num = *count;
+-	}
+-out:
+-	if (ret >= 0) {
+-		BUFFER_TRACE(bitmap_bh, "journal_dirty_metadata for "
+-					"bitmap block");
+-		fatal = ext4_journal_dirty_metadata(handle, bitmap_bh);
+-		if (fatal) {
+-			*errp = fatal;
+-			return -1;
+-		}
+-		return ret;
+-	}
+-
+-	BUFFER_TRACE(bitmap_bh, "journal_release_buffer");
+-	ext4_journal_release_buffer(handle, bitmap_bh);
+-	return ret;
+-}
+-
+ int ext4_claim_free_blocks(struct ext4_sb_info *sbi,
+ 						s64 nblocks)
+ {
+@@ -1702,313 +679,6 @@ int ext4_should_retry_alloc(struct super_block *sb, int *retries)
+ 	return jbd2_journal_force_commit_nested(EXT4_SB(sb)->s_journal);
+ }
+ 
+-/**
+- * ext4_old_new_blocks() -- core block bitmap based block allocation function
+- *
+- * @handle:		handle to this transaction
+- * @inode:		file inode
+- * @goal:		given target block(filesystem wide)
+- * @count:		target number of blocks to allocate
+- * @errp:		error code
+- *
+- * ext4_old_new_blocks uses a goal block to assist allocation and look up
+- * the block bitmap directly to do block allocation.  It tries to
+- * allocate block(s) from the block group contains the goal block first. If
+- * that fails, it will try to allocate block(s) from other block groups
+- * without any specific goal block.
+- *
+- * This function is called when -o nomballoc mount option is enabled
+- *
+- */
+-ext4_fsblk_t ext4_old_new_blocks(handle_t *handle, struct inode *inode,
+-			ext4_fsblk_t goal, unsigned long *count, int *errp)
+-{
+-	struct buffer_head *bitmap_bh = NULL;
+-	struct buffer_head *gdp_bh;
+-	ext4_group_t group_no;
+-	ext4_group_t goal_group;
+-	ext4_grpblk_t grp_target_blk;	/* blockgroup relative goal block */
+-	ext4_grpblk_t grp_alloc_blk;	/* blockgroup-relative allocated block*/
+-	ext4_fsblk_t ret_block;		/* filesyetem-wide allocated block */
+-	ext4_group_t bgi;			/* blockgroup iteration index */
+-	int fatal = 0, err;
+-	int performed_allocation = 0;
+-	ext4_grpblk_t free_blocks;	/* number of free blocks in a group */
+-	struct super_block *sb;
+-	struct ext4_group_desc *gdp;
+-	struct ext4_super_block *es;
+-	struct ext4_sb_info *sbi;
+-	struct ext4_reserve_window_node *my_rsv = NULL;
+-	struct ext4_block_alloc_info *block_i;
+-	unsigned short windowsz = 0;
+-	ext4_group_t ngroups;
+-	unsigned long num = *count;
+-
+-	sb = inode->i_sb;
+-	if (!sb) {
+-		*errp = -ENODEV;
+-		printk(KERN_ERR "ext4_new_block: nonexistent superblock");
+-		return 0;
+-	}
+-
+-	sbi = EXT4_SB(sb);
+-	if (!EXT4_I(inode)->i_delalloc_reserved_flag) {
+-		/*
+-		 * With delalloc we already reserved the blocks
+-		 */
+-		while (*count && ext4_claim_free_blocks(sbi, *count)) {
+-			/* let others to free the space */
+-			yield();
+-			*count = *count >> 1;
+-		}
+-		if (!*count) {
+-			*errp = -ENOSPC;
+-			return 0;	/*return with ENOSPC error */
+-		}
+-		num = *count;
+-	}
+-	/*
+-	 * Check quota for allocation of this block.
+-	 */
+-	if (DQUOT_ALLOC_BLOCK(inode, num)) {
+-		*errp = -EDQUOT;
+-		return 0;
+-	}
+-
+-	sbi = EXT4_SB(sb);
+-	es = EXT4_SB(sb)->s_es;
+-	ext4_debug("goal=%llu.\n", goal);
+-	/*
+-	 * Allocate a block from reservation only when
+-	 * filesystem is mounted with reservation(default,-o reservation), and
+-	 * it's a regular file, and
+-	 * the desired window size is greater than 0 (One could use ioctl
+-	 * command EXT4_IOC_SETRSVSZ to set the window size to 0 to turn off
+-	 * reservation on that particular file)
+-	 */
+-	block_i = EXT4_I(inode)->i_block_alloc_info;
+-	if (block_i && ((windowsz = block_i->rsv_window_node.rsv_goal_size) > 0))
+-		my_rsv = &block_i->rsv_window_node;
+-
+-	/*
+-	 * First, test whether the goal block is free.
+-	 */
+-	if (goal < le32_to_cpu(es->s_first_data_block) ||
+-	    goal >= ext4_blocks_count(es))
+-		goal = le32_to_cpu(es->s_first_data_block);
+-	ext4_get_group_no_and_offset(sb, goal, &group_no, &grp_target_blk);
+-	goal_group = group_no;
+-retry_alloc:
+-	gdp = ext4_get_group_desc(sb, group_no, &gdp_bh);
+-	if (!gdp)
+-		goto io_error;
+-
+-	free_blocks = le16_to_cpu(gdp->bg_free_blocks_count);
+-
+-	if (free_blocks > 0) {
+-		/*
+-		 * try to allocate with group target block
+-		 * in the goal group. If we have low free_blocks
+-		 * count turn off reservation
+-		 */
+-		if (my_rsv && (free_blocks < windowsz)
+-			&& (rsv_is_empty(&my_rsv->rsv_window)))
+-			my_rsv = NULL;
+-
+-		bitmap_bh = ext4_read_block_bitmap(sb, group_no);
+-		if (!bitmap_bh)
+-			goto io_error;
+-		grp_alloc_blk = ext4_try_to_allocate_with_rsv(sb, handle,
+-					group_no, bitmap_bh, grp_target_blk,
+-					my_rsv,	&num, &fatal);
+-		if (fatal)
+-			goto out;
+-		if (grp_alloc_blk >= 0)
+-			goto allocated;
+-	}
+-
+-	ngroups = EXT4_SB(sb)->s_groups_count;
+-	smp_rmb();
+-
+-	/*
+-	 * Now search the rest of the groups.  We assume that
+-	 * group_no and gdp correctly point to the last group visited.
+-	 */
+-	for (bgi = 0; bgi < ngroups; bgi++) {
+-		group_no++;
+-		if (group_no >= ngroups)
+-			group_no = 0;
+-		gdp = ext4_get_group_desc(sb, group_no, &gdp_bh);
+-		if (!gdp)
+-			goto io_error;
+-		free_blocks = le16_to_cpu(gdp->bg_free_blocks_count);
+-		/*
+-		 * skip this group if the number of
+-		 * free blocks is less than half of the reservation
+-		 * window size.
+-		 */
+-		if (my_rsv && (free_blocks <= (windowsz/2)))
+-			continue;
+-
+-		brelse(bitmap_bh);
+-		bitmap_bh = ext4_read_block_bitmap(sb, group_no);
+-		if (!bitmap_bh)
+-			goto io_error;
+-		/*
+-		 * try to allocate block(s) from this group, without a goal(-1).
+-		 */
+-		grp_alloc_blk = ext4_try_to_allocate_with_rsv(sb, handle,
+-					group_no, bitmap_bh, -1, my_rsv,
+-					&num, &fatal);
+-		if (fatal)
+-			goto out;
+-		if (grp_alloc_blk >= 0)
+-			goto allocated;
+-	}
+-	/*
+-	 * We may end up a bogus ealier ENOSPC error due to
+-	 * filesystem is "full" of reservations, but
+-	 * there maybe indeed free blocks avaliable on disk
+-	 * In this case, we just forget about the reservations
+-	 * just do block allocation as without reservations.
+-	 */
+-	if (my_rsv) {
+-		my_rsv = NULL;
+-		windowsz = 0;
+-		group_no = goal_group;
+-		goto retry_alloc;
+-	}
+-	/* No space left on the device */
+-	*errp = -ENOSPC;
+-	goto out;
+-
+-allocated:
+-
+-	ext4_debug("using block group %lu(%d)\n",
+-			group_no, gdp->bg_free_blocks_count);
+-
+-	BUFFER_TRACE(gdp_bh, "get_write_access");
+-	fatal = ext4_journal_get_write_access(handle, gdp_bh);
+-	if (fatal)
+-		goto out;
+-
+-	ret_block = grp_alloc_blk + ext4_group_first_block_no(sb, group_no);
+-
+-	if (in_range(ext4_block_bitmap(sb, gdp), ret_block, num) ||
+-	    in_range(ext4_inode_bitmap(sb, gdp), ret_block, num) ||
+-	    in_range(ret_block, ext4_inode_table(sb, gdp),
+-		     EXT4_SB(sb)->s_itb_per_group) ||
+-	    in_range(ret_block + num - 1, ext4_inode_table(sb, gdp),
+-		     EXT4_SB(sb)->s_itb_per_group)) {
+-		ext4_error(sb, "ext4_new_block",
+-			    "Allocating block in system zone - "
+-			    "blocks from %llu, length %lu",
+-			     ret_block, num);
+-		/*
+-		 * claim_block marked the blocks we allocated
+-		 * as in use. So we may want to selectively
+-		 * mark some of the blocks as free
+-		 */
+-		goto retry_alloc;
+-	}
+-
+-	performed_allocation = 1;
+-
+-#ifdef CONFIG_JBD2_DEBUG
+-	{
+-		struct buffer_head *debug_bh;
+-
+-		/* Record bitmap buffer state in the newly allocated block */
+-		debug_bh = sb_find_get_block(sb, ret_block);
+-		if (debug_bh) {
+-			BUFFER_TRACE(debug_bh, "state when allocated");
+-			BUFFER_TRACE2(debug_bh, bitmap_bh, "bitmap state");
+-			brelse(debug_bh);
+-		}
+-	}
+-	jbd_lock_bh_state(bitmap_bh);
+-	spin_lock(sb_bgl_lock(sbi, group_no));
+-	if (buffer_jbd(bitmap_bh) && bh2jh(bitmap_bh)->b_committed_data) {
+-		int i;
+-
+-		for (i = 0; i < num; i++) {
+-			if (ext4_test_bit(grp_alloc_blk+i,
+-					bh2jh(bitmap_bh)->b_committed_data)) {
+-				printk(KERN_ERR "%s: block was unexpectedly "
+-				       "set in b_committed_data\n", __func__);
+-			}
+-		}
+-	}
+-	ext4_debug("found bit %d\n", grp_alloc_blk);
+-	spin_unlock(sb_bgl_lock(sbi, group_no));
+-	jbd_unlock_bh_state(bitmap_bh);
+-#endif
+-
+-	if (ret_block + num - 1 >= ext4_blocks_count(es)) {
+-		ext4_error(sb, "ext4_new_block",
+-			    "block(%llu) >= blocks count(%llu) - "
+-			    "block_group = %lu, es == %p ", ret_block,
+-			ext4_blocks_count(es), group_no, es);
+-		goto out;
+-	}
+-
+-	/*
+-	 * It is up to the caller to add the new buffer to a journal
+-	 * list of some description.  We don't know in advance whether
+-	 * the caller wants to use it as metadata or data.
+-	 */
+-	spin_lock(sb_bgl_lock(sbi, group_no));
+-	if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))
+-		gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
+-	le16_add_cpu(&gdp->bg_free_blocks_count, -num);
+-	gdp->bg_checksum = ext4_group_desc_csum(sbi, group_no, gdp);
+-	spin_unlock(sb_bgl_lock(sbi, group_no));
+-	percpu_counter_sub(&sbi->s_freeblocks_counter, num);
+-	/*
+-	 * Now reduce the dirty block count also. Should not go negative
+-	 */
+-	if (!EXT4_I(inode)->i_delalloc_reserved_flag)
+-		percpu_counter_sub(&sbi->s_dirtyblocks_counter, *count);
+-	else
+-		percpu_counter_sub(&sbi->s_dirtyblocks_counter, num);
+-	if (sbi->s_log_groups_per_flex) {
+-		ext4_group_t flex_group = ext4_flex_group(sbi, group_no);
+-		spin_lock(sb_bgl_lock(sbi, flex_group));
+-		sbi->s_flex_groups[flex_group].free_blocks -= num;
+-		spin_unlock(sb_bgl_lock(sbi, flex_group));
+-	}
+-
+-	BUFFER_TRACE(gdp_bh, "journal_dirty_metadata for group descriptor");
+-	err = ext4_journal_dirty_metadata(handle, gdp_bh);
+-	if (!fatal)
+-		fatal = err;
+-
+-	sb->s_dirt = 1;
+-	if (fatal)
+-		goto out;
+-
+-	*errp = 0;
+-	brelse(bitmap_bh);
+-	DQUOT_FREE_BLOCK(inode, *count-num);
+-	*count = num;
+-	return ret_block;
+-
+-io_error:
+-	*errp = -EIO;
+-out:
+-	if (fatal) {
+-		*errp = fatal;
+-		ext4_std_error(sb, fatal);
+-	}
+-	/*
+-	 * Undo the block allocation
+-	 */
+-	if (!performed_allocation)
+-		DQUOT_FREE_BLOCK(inode, *count);
+-	brelse(bitmap_bh);
+-	return 0;
+-}
+-
+ #define EXT4_META_BLOCK 0x1
+ 
+ static ext4_fsblk_t do_blk_alloc(handle_t *handle, struct inode *inode,
+@@ -2018,10 +688,6 @@ static ext4_fsblk_t do_blk_alloc(handle_t *handle, struct inode *inode,
+ 	struct ext4_allocation_request ar;
+ 	ext4_fsblk_t ret;
+ 
+-	if (!test_opt(inode->i_sb, MBALLOC)) {
+-		return ext4_old_new_blocks(handle, inode, goal, count, errp);
+-	}
+-
+ 	memset(&ar, 0, sizeof(ar));
+ 	/* Fill with neighbour allocated blocks */
+ 
+@@ -2242,3 +908,4 @@ unsigned long ext4_bg_num_gdb(struct super_block *sb, ext4_group_t group)
+ 	return ext4_bg_num_gdb_meta(sb,group);
+ 
+ }
++
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 922d18720c9e..c50c04cc6d7b 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -539,7 +539,6 @@ do {									       \
+ #define EXT4_MOUNT_JOURNAL_CHECKSUM	0x800000 /* Journal checksums */
+ #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT	0x1000000 /* Journal Async Commit */
+ #define EXT4_MOUNT_I_VERSION            0x2000000 /* i_version support */
+-#define EXT4_MOUNT_MBALLOC		0x4000000 /* Buddy allocation support */
+ #define EXT4_MOUNT_DELALLOC		0x8000000 /* Delalloc support */
+ /* Compatibility, for having both ext2_fs.h and ext4_fs.h included at once */
+ #ifndef _LINUX_EXT2_FS_H
+@@ -1002,8 +1001,6 @@ extern ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
+ extern ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode,
+ 					ext4_lblk_t iblock, ext4_fsblk_t goal,
+ 					unsigned long *count, int *errp);
+-extern ext4_fsblk_t ext4_old_new_blocks(handle_t *handle, struct inode *inode,
+-			ext4_fsblk_t goal, unsigned long *count, int *errp);
+ extern int ext4_claim_free_blocks(struct ext4_sb_info *sbi, s64 nblocks);
+ extern ext4_fsblk_t ext4_has_free_blocks(struct ext4_sb_info *sbi,
+ 					 s64 nblocks);
+@@ -1018,8 +1015,6 @@ extern struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
+ 						    ext4_group_t block_group,
+ 						    struct buffer_head ** bh);
+ extern int ext4_should_retry_alloc(struct super_block *sb, int *retries);
+-extern void ext4_init_block_alloc_info(struct inode *);
+-extern void ext4_rsv_window_add(struct super_block *sb, struct ext4_reserve_window_node *rsv);
+ 
+ /* dir.c */
+ extern int ext4_check_dir_entry(const char *, struct inode *,
+@@ -1054,7 +1049,7 @@ extern int ext4_mb_release(struct super_block *);
+ extern ext4_fsblk_t ext4_mb_new_blocks(handle_t *,
+ 				struct ext4_allocation_request *, int *);
+ extern int ext4_mb_reserve_blocks(struct super_block *, int);
+-extern void ext4_mb_discard_inode_preallocations(struct inode *);
++extern void ext4_discard_preallocations(struct inode *);
+ extern int __init init_ext4_mballoc(void);
+ extern void exit_ext4_mballoc(void);
+ extern void ext4_mb_free_blocks(handle_t *, struct inode *,
+@@ -1084,7 +1079,6 @@ extern int  ext4_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ 				struct kstat *stat);
+ extern void ext4_delete_inode(struct inode *);
+ extern int  ext4_sync_inode(handle_t *, struct inode *);
+-extern void ext4_discard_reservation(struct inode *);
+ extern void ext4_dirty_inode(struct inode *);
+ extern int ext4_change_inode_journal_flag(struct inode *, int);
+ extern int ext4_get_inode_loc(struct inode *, struct ext4_iloc *);
+diff --git a/fs/ext4/ext4_i.h b/fs/ext4/ext4_i.h
+index ef7409f0e7e4..2875eeca1727 100644
+--- a/fs/ext4/ext4_i.h
++++ b/fs/ext4/ext4_i.h
+@@ -33,38 +33,6 @@ typedef __u32 ext4_lblk_t;
+ /* data type for block group number */
+ typedef unsigned long ext4_group_t;
+ 
+-struct ext4_reserve_window {
+-	ext4_fsblk_t	_rsv_start;	/* First byte reserved */
+-	ext4_fsblk_t	_rsv_end;	/* Last byte reserved or 0 */
+-};
+-
+-struct ext4_reserve_window_node {
+-	struct rb_node		rsv_node;
+-	__u32			rsv_goal_size;
+-	__u32			rsv_alloc_hit;
+-	struct ext4_reserve_window	rsv_window;
+-};
+-
+-struct ext4_block_alloc_info {
+-	/* information about reservation window */
+-	struct ext4_reserve_window_node rsv_window_node;
+-	/*
+-	 * was i_next_alloc_block in ext4_inode_info
+-	 * is the logical (file-relative) number of the
+-	 * most-recently-allocated block in this file.
+-	 * We use this for detecting linearly ascending allocation requests.
+-	 */
+-	ext4_lblk_t last_alloc_logical_block;
+-	/*
+-	 * Was i_next_alloc_goal in ext4_inode_info
+-	 * is the *physical* companion to i_next_alloc_block.
+-	 * it the physical block number of the block which was most-recentl
+-	 * allocated to this file.  This give us the goal (target) for the next
+-	 * allocation when we detect linearly ascending requests.
+-	 */
+-	ext4_fsblk_t last_alloc_physical_block;
+-};
+-
+ #define rsv_start rsv_window._rsv_start
+ #define rsv_end rsv_window._rsv_end
+ 
+@@ -97,9 +65,6 @@ struct ext4_inode_info {
+ 	ext4_group_t	i_block_group;
+ 	__u32	i_state;		/* Dynamic state flags for ext4 */
+ 
+-	/* block reservation info */
+-	struct ext4_block_alloc_info *i_block_alloc_info;
+-
+ 	ext4_lblk_t		i_dir_start_lookup;
+ #ifdef CONFIG_EXT4DEV_FS_XATTR
+ 	/*
+diff --git a/fs/ext4/ext4_sb.h b/fs/ext4/ext4_sb.h
+index 94e0757522a6..6a0b40d43264 100644
+--- a/fs/ext4/ext4_sb.h
++++ b/fs/ext4/ext4_sb.h
+@@ -67,7 +67,6 @@ struct ext4_sb_info {
+ 	/* root of the per fs reservation window tree */
+ 	spinlock_t s_rsv_window_lock;
+ 	struct rb_root s_rsv_window_root;
+-	struct ext4_reserve_window_node s_rsv_window_head;
+ 
+ 	/* Journaling */
+ 	struct inode *s_journal_inode;
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index e8758df2617b..c8f81f2fb28e 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -2697,11 +2697,8 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 		goto out2;
+ 	}
+ 	/*
+-	 * Okay, we need to do block allocation.  Lazily initialize the block
+-	 * allocation info here if necessary.
++	 * Okay, we need to do block allocation.
+ 	 */
+-	if (S_ISREG(inode->i_mode) && (!EXT4_I(inode)->i_block_alloc_info))
+-		ext4_init_block_alloc_info(inode);
+ 
+ 	/* find neighbour allocated blocks */
+ 	ar.lleft = iblock;
+@@ -2761,7 +2758,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
+ 		/* free data blocks we just allocated */
+ 		/* not a good idea to call discard here directly,
+ 		 * but otherwise we'd need to call it every free() */
+-		ext4_mb_discard_inode_preallocations(inode);
++		ext4_discard_preallocations(inode);
+ 		ext4_free_blocks(handle, inode, ext_pblock(&newex),
+ 					ext4_ext_get_actual_len(&newex), 0);
+ 		goto out2;
+@@ -2825,7 +2822,7 @@ void ext4_ext_truncate(struct inode *inode)
+ 	down_write(&EXT4_I(inode)->i_data_sem);
+ 	ext4_ext_invalidate_cache(inode);
+ 
+-	ext4_discard_reservation(inode);
++	ext4_discard_preallocations(inode);
+ 
+ 	/*
+ 	 * TODO: optimization is possible here.
+diff --git a/fs/ext4/file.c b/fs/ext4/file.c
+index 11b289f42b7d..62796b7e1d1b 100644
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -38,7 +38,7 @@ static int ext4_release_file(struct inode *inode, struct file *filp)
+ 			(atomic_read(&inode->i_writecount) == 1))
+ 	{
+ 		down_write(&EXT4_I(inode)->i_data_sem);
+-		ext4_discard_reservation(inode);
++		ext4_discard_preallocations(inode);
+ 		up_write(&EXT4_I(inode)->i_data_sem);
+ 	}
+ 	if (is_dx(inode) && filp->private_data)
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 5e66a2feef09..1343bf18825b 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -817,7 +817,6 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
+ 		ei->i_flags &= ~EXT4_DIRSYNC_FL;
+ 	ei->i_file_acl = 0;
+ 	ei->i_dtime = 0;
+-	ei->i_block_alloc_info = NULL;
+ 	ei->i_block_group = group;
+ 
+ 	ext4_set_inode_flags(inode);
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index ef4ca3d4abc0..bd770c360c14 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -486,18 +486,9 @@ static ext4_fsblk_t ext4_find_near(struct inode *inode, Indirect *ind)
+ static ext4_fsblk_t ext4_find_goal(struct inode *inode, ext4_lblk_t block,
+ 		Indirect *partial)
+ {
+-	struct ext4_block_alloc_info *block_i;
+-
+-	block_i =  EXT4_I(inode)->i_block_alloc_info;
+-
+ 	/*
+-	 * try the heuristic for sequential allocation,
+-	 * failing that at least try to get decent locality.
++	 * XXX need to get goal block from mballoc's data structures
+ 	 */
+-	if (block_i && (block == block_i->last_alloc_logical_block + 1)
+-		&& (block_i->last_alloc_physical_block != 0)) {
+-		return block_i->last_alloc_physical_block + 1;
+-	}
+ 
+ 	return ext4_find_near(inode, partial);
+ }
+@@ -757,10 +748,8 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
+ {
+ 	int i;
+ 	int err = 0;
+-	struct ext4_block_alloc_info *block_i;
+ 	ext4_fsblk_t current_block;
+ 
+-	block_i = EXT4_I(inode)->i_block_alloc_info;
+ 	/*
+ 	 * If we're splicing into a [td]indirect block (as opposed to the
+ 	 * inode) then we need to get write access to the [td]indirect block
+@@ -786,17 +775,6 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
+ 			*(where->p + i) = cpu_to_le32(current_block++);
+ 	}
+ 
+-	/*
+-	 * update the most recently allocated logical & physical block
+-	 * in i_block_alloc_info, to assist find the proper goal block for next
+-	 * allocation
+-	 */
+-	if (block_i) {
+-		block_i->last_alloc_logical_block = block + blks - 1;
+-		block_i->last_alloc_physical_block =
+-				le32_to_cpu(where[num].key) + blks - 1;
+-	}
+-
+ 	/* We are done with atomic stuff, now do the rest of housekeeping */
+ 
+ 	inode->i_ctime = ext4_current_time(inode);
+@@ -914,12 +892,8 @@ int ext4_get_blocks_handle(handle_t *handle, struct inode *inode,
+ 		goto cleanup;
+ 
+ 	/*
+-	 * Okay, we need to do block allocation.  Lazily initialize the block
+-	 * allocation info here if necessary
++	 * Okay, we need to do block allocation.
+ 	*/
+-	if (S_ISREG(inode->i_mode) && (!ei->i_block_alloc_info))
+-		ext4_init_block_alloc_info(inode);
+-
+ 	goal = ext4_find_goal(inode, iblock, partial);
+ 
+ 	/* the number of blocks need to allocate for [d,t]indirect blocks */
+@@ -3738,7 +3712,7 @@ void ext4_truncate(struct inode *inode)
+ 	 */
+ 	down_write(&ei->i_data_sem);
+ 
+-	ext4_discard_reservation(inode);
++	ext4_discard_preallocations(inode);
+ 
+ 	/*
+ 	 * The orphan list entry will now protect us from any crash which
+@@ -4071,7 +4045,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 	ei->i_acl = EXT4_ACL_NOT_CACHED;
+ 	ei->i_default_acl = EXT4_ACL_NOT_CACHED;
+ #endif
+-	ei->i_block_alloc_info = NULL;
+ 
+ 	ret = __ext4_get_inode_loc(inode, &iloc, 0);
+ 	if (ret < 0)
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index 3e14060b398e..ea27eaa0cfe5 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -23,7 +23,6 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 	struct inode *inode = filp->f_dentry->d_inode;
+ 	struct ext4_inode_info *ei = EXT4_I(inode);
+ 	unsigned int flags;
+-	unsigned short rsv_window_size;
+ 
+ 	ext4_debug("cmd = %u, arg = %lu\n", cmd, arg);
+ 
+@@ -190,49 +189,6 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 			return ret;
+ 		}
+ #endif
+-	case EXT4_IOC_GETRSVSZ:
+-		if (test_opt(inode->i_sb, RESERVATION)
+-			&& S_ISREG(inode->i_mode)
+-			&& ei->i_block_alloc_info) {
+-			rsv_window_size = ei->i_block_alloc_info->rsv_window_node.rsv_goal_size;
+-			return put_user(rsv_window_size, (int __user *)arg);
+-		}
+-		return -ENOTTY;
+-	case EXT4_IOC_SETRSVSZ: {
+-		int err;
+-
+-		if (!test_opt(inode->i_sb, RESERVATION) || !S_ISREG(inode->i_mode))
+-			return -ENOTTY;
+-
+-		if (!is_owner_or_cap(inode))
+-			return -EACCES;
+-
+-		if (get_user(rsv_window_size, (int __user *)arg))
+-			return -EFAULT;
+-
+-		err = mnt_want_write(filp->f_path.mnt);
+-		if (err)
+-			return err;
+-
+-		if (rsv_window_size > EXT4_MAX_RESERVE_BLOCKS)
+-			rsv_window_size = EXT4_MAX_RESERVE_BLOCKS;
+-
+-		/*
+-		 * need to allocate reservation structure for this inode
+-		 * before set the window size
+-		 */
+-		down_write(&ei->i_data_sem);
+-		if (!ei->i_block_alloc_info)
+-			ext4_init_block_alloc_info(inode);
+-
+-		if (ei->i_block_alloc_info){
+-			struct ext4_reserve_window_node *rsv = &ei->i_block_alloc_info->rsv_window_node;
+-			rsv->rsv_goal_size = rsv_window_size;
+-		}
+-		up_write(&ei->i_data_sem);
+-		mnt_drop_write(filp->f_path.mnt);
+-		return 0;
+-	}
+ 	case EXT4_IOC_GROUP_EXTEND: {
+ 		ext4_fsblk_t n_blocks_count;
+ 		struct super_block *sb = inode->i_sb;
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index b9118bb29939..335faee0c0f5 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -534,9 +534,6 @@ static int __mb_check_buddy(struct ext4_buddy *e4b, char *file,
+ 	void *buddy;
+ 	void *buddy2;
+ 
+-	if (!test_opt(sb, MBALLOC))
+-		return 0;
+-
+ 	{
+ 		static int mb_check_counter;
+ 		if (mb_check_counter++ % 100 != 0)
+@@ -2487,19 +2484,14 @@ int ext4_mb_init(struct super_block *sb, int needs_recovery)
+ 	unsigned max;
+ 	int ret;
+ 
+-	if (!test_opt(sb, MBALLOC))
+-		return 0;
+-
+ 	i = (sb->s_blocksize_bits + 2) * sizeof(unsigned short);
+ 
+ 	sbi->s_mb_offsets = kmalloc(i, GFP_KERNEL);
+ 	if (sbi->s_mb_offsets == NULL) {
+-		clear_opt(sbi->s_mount_opt, MBALLOC);
+ 		return -ENOMEM;
+ 	}
+ 	sbi->s_mb_maxs = kmalloc(i, GFP_KERNEL);
+ 	if (sbi->s_mb_maxs == NULL) {
+-		clear_opt(sbi->s_mount_opt, MBALLOC);
+ 		kfree(sbi->s_mb_maxs);
+ 		return -ENOMEM;
+ 	}
+@@ -2522,7 +2514,6 @@ int ext4_mb_init(struct super_block *sb, int needs_recovery)
+ 	/* init file for buddy data */
+ 	ret = ext4_mb_init_backend(sb);
+ 	if (ret != 0) {
+-		clear_opt(sbi->s_mount_opt, MBALLOC);
+ 		kfree(sbi->s_mb_offsets);
+ 		kfree(sbi->s_mb_maxs);
+ 		return ret;
+@@ -2544,7 +2535,6 @@ int ext4_mb_init(struct super_block *sb, int needs_recovery)
+ 
+ 	sbi->s_locality_groups = alloc_percpu(struct ext4_locality_group);
+ 	if (sbi->s_locality_groups == NULL) {
+-		clear_opt(sbi->s_mount_opt, MBALLOC);
+ 		kfree(sbi->s_mb_offsets);
+ 		kfree(sbi->s_mb_maxs);
+ 		return -ENOMEM;
+@@ -2590,9 +2580,6 @@ int ext4_mb_release(struct super_block *sb)
+ 	struct ext4_group_info *grinfo;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 
+-	if (!test_opt(sb, MBALLOC))
+-		return 0;
+-
+ 	/* release freed, non-committed blocks */
+ 	spin_lock(&sbi->s_md_lock);
+ 	list_splice_init(&sbi->s_closed_transaction,
+@@ -3805,7 +3792,7 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
+  *
+  * FIXME!! Make sure it is valid at all the call sites
+  */
+-void ext4_mb_discard_inode_preallocations(struct inode *inode)
++void ext4_discard_preallocations(struct inode *inode)
+ {
+ 	struct ext4_inode_info *ei = EXT4_I(inode);
+ 	struct super_block *sb = inode->i_sb;
+@@ -3817,7 +3804,7 @@ void ext4_mb_discard_inode_preallocations(struct inode *inode)
+ 	struct ext4_buddy e4b;
+ 	int err;
+ 
+-	if (!test_opt(sb, MBALLOC) || !S_ISREG(inode->i_mode)) {
++	if (!S_ISREG(inode->i_mode)) {
+ 		/*BUG_ON(!list_empty(&ei->i_prealloc_list));*/
+ 		return;
+ 	}
+@@ -4300,11 +4287,6 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
+ 	sb = ar->inode->i_sb;
+ 	sbi = EXT4_SB(sb);
+ 
+-	if (!test_opt(sb, MBALLOC)) {
+-		block = ext4_old_new_blocks(handle, ar->inode, ar->goal,
+-					    &(ar->len), errp);
+-		return block;
+-	}
+ 	if (!EXT4_I(ar->inode)->i_delalloc_reserved_flag) {
+ 		/*
+ 		 * With delalloc we already reserved the blocks
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index b60afbcd7e46..b6ec1843a015 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -870,11 +870,10 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
+ 	 * We can allocate memory for mb_alloc based on the new group
+ 	 * descriptor
+ 	 */
+-	if (test_opt(sb, MBALLOC)) {
+-		err = ext4_mb_add_more_groupinfo(sb, input->group, gdp);
+-		if (err)
+-			goto exit_journal;
+-	}
++	err = ext4_mb_add_more_groupinfo(sb, input->group, gdp);
++	if (err)
++		goto exit_journal;
++
+ 	/*
+ 	 * Make the new blocks and inodes valid next.  We do this before
+ 	 * increasing the group count so that once the group is enabled,
+@@ -1086,8 +1085,15 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
+ 	/*
+ 	 * Mark mballoc pages as not up to date so that they will be updated
+ 	 * next time they are loaded by ext4_mb_load_buddy.
++	 *
++	 * XXX Bad, Bad, BAD!!!  We should not be overloading the
++	 * Uptodate flag, particularly on thte bitmap bh, as way of
++	 * hinting to ext4_mb_load_buddy() that it needs to be
++	 * overloaded.  A user could take a LVM snapshot, then do an
++	 * on-line fsck, and clear the uptodate flag, and this would
++	 * not be a bug in userspace, but a bug in the kernel.  FIXME!!!
+ 	 */
+-	if (test_opt(sb, MBALLOC)) {
++	{
+ 		struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 		struct inode *inode = sbi->s_buddy_cache;
+ 		int blocks_per_page;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 6583aee5177f..dfcd41fafb9f 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -574,7 +574,6 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
+ 	ei->i_acl = EXT4_ACL_NOT_CACHED;
+ 	ei->i_default_acl = EXT4_ACL_NOT_CACHED;
+ #endif
+-	ei->i_block_alloc_info = NULL;
+ 	ei->vfs_inode.i_version = 1;
+ 	ei->vfs_inode.i_data.writeback_index = 0;
+ 	memset(&ei->i_cached_extent, 0, sizeof(struct ext4_ext_cache));
+@@ -633,7 +632,6 @@ static void destroy_inodecache(void)
+ 
+ static void ext4_clear_inode(struct inode *inode)
+ {
+-	struct ext4_block_alloc_info *rsv = EXT4_I(inode)->i_block_alloc_info;
+ #ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
+ 	if (EXT4_I(inode)->i_acl &&
+ 			EXT4_I(inode)->i_acl != EXT4_ACL_NOT_CACHED) {
+@@ -646,10 +644,7 @@ static void ext4_clear_inode(struct inode *inode)
+ 		EXT4_I(inode)->i_default_acl = EXT4_ACL_NOT_CACHED;
+ 	}
+ #endif
+-	ext4_discard_reservation(inode);
+-	EXT4_I(inode)->i_block_alloc_info = NULL;
+-	if (unlikely(rsv))
+-		kfree(rsv);
++	ext4_discard_preallocations(inode);
+ 	jbd2_journal_release_jbd_inode(EXT4_SB(inode->i_sb)->s_journal,
+ 				       &EXT4_I(inode)->jinode);
+ }
+@@ -760,8 +755,6 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
+ 		seq_puts(seq, ",nobh");
+ 	if (!test_opt(sb, EXTENTS))
+ 		seq_puts(seq, ",noextents");
+-	if (!test_opt(sb, MBALLOC))
+-		seq_puts(seq, ",nomballoc");
+ 	if (test_opt(sb, I_VERSION))
+ 		seq_puts(seq, ",i_version");
+ 	if (!test_opt(sb, DELALLOC))
+@@ -1373,12 +1366,6 @@ static int parse_options(char *options, struct super_block *sb,
+ 		case Opt_nodelalloc:
+ 			clear_opt(sbi->s_mount_opt, DELALLOC);
+ 			break;
+-		case Opt_mballoc:
+-			set_opt(sbi->s_mount_opt, MBALLOC);
+-			break;
+-		case Opt_nomballoc:
+-			clear_opt(sbi->s_mount_opt, MBALLOC);
+-			break;
+ 		case Opt_stripe:
+ 			if (match_int(&args[0], &option))
+ 				return 0;
+@@ -2040,11 +2027,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		ext4_warning(sb, __func__,
+ 			"extents feature not enabled on this filesystem, "
+ 			"use tune2fs.\n");
+-	/*
+-	 * turn on mballoc code by default in ext4 filesystem
+-	 * Use -o nomballoc to turn it off
+-	 */
+-	set_opt(sbi->s_mount_opt, MBALLOC);
+ 
+ 	/*
+ 	 * enable delayed allocation by default
+@@ -2301,19 +2283,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		goto failed_mount3;
+ 	}
+ 
+-	/* per fileystem reservation list head & lock */
+-	spin_lock_init(&sbi->s_rsv_window_lock);
+-	sbi->s_rsv_window_root = RB_ROOT;
+-	/* Add a single, static dummy reservation to the start of the
+-	 * reservation window list --- it gives us a placeholder for
+-	 * append-at-start-of-list which makes the allocation logic
+-	 * _much_ simpler. */
+-	sbi->s_rsv_window_head.rsv_start = EXT4_RESERVE_WINDOW_NOT_ALLOCATED;
+-	sbi->s_rsv_window_head.rsv_end = EXT4_RESERVE_WINDOW_NOT_ALLOCATED;
+-	sbi->s_rsv_window_head.rsv_alloc_hit = 0;
+-	sbi->s_rsv_window_head.rsv_goal_size = 0;
+-	ext4_rsv_window_add(sb, &sbi->s_rsv_window_head);
+-
+ 	sbi->s_stripe = ext4_get_stripe_size(sbi);
+ 
+ 	/*
+@@ -2510,7 +2479,12 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		printk(KERN_INFO "EXT4-fs: delayed allocation enabled\n");
+ 
+ 	ext4_ext_init(sb);
+-	ext4_mb_init(sb, needs_recovery);
++	err = ext4_mb_init(sb, needs_recovery);
++	if (err) {
++		printk(KERN_ERR "EXT4-fs: failed to initalize mballoc (%d)\n",
++		       err);
++		goto failed_mount4;
++	}
+ 
+ 	lock_kernel();
+ 	return 0;

commit 240799cdf22bd789ea6852653c3b879d35ad0a6c
+Author: Theodore Ts'o 
+Date:   Thu Oct 9 23:53:47 2008 -0400
+
+    ext4: Use readahead when reading an inode from the inode table
+    
+    With modern hard drives, reading 64k takes roughly the same time as
+    reading a 4k block.  So request readahead for adjacent inode table
+    blocks to reduce the time it takes when iterating over directories
+    (especially when doing this in htree sort order) in a cold cache case.
+    With this patch, the time it takes to run "git status" on a kernel
+    tree after flushing the caches via "echo 3 > /proc/sys/vm/drop_caches"
+    is reduced by 21%.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
+index 0d5394920a31..289057958f90 100644
+--- a/Documentation/filesystems/ext4.txt
++++ b/Documentation/filesystems/ext4.txt
+@@ -177,6 +177,11 @@ barrier=<0|1(*)>	This enables/disables the use of write barriers in
+ 			your disks are battery-backed in one way or another,
+ 			disabling barriers may safely improve performance.
+ 
++inode_readahead=n	This tuning parameter controls the maximum
++			number of inode table blocks that ext4's inode
++			table readahead algorithm will pre-read into
++			the buffer cache.  The default value is 32 blocks.
++
+ orlov		(*)	This enables the new Orlov block allocator. It is
+ 			enabled by default.
+ 
+@@ -252,6 +257,7 @@ stripe=n		Number of filesystem blocks that mballoc will try
+ delalloc	(*)	Deferring block allocation until write-out time.
+ nodelalloc		Disable delayed allocation. Blocks are allocation
+ 			when data is copied from user to page cache.
++
+ Data Mode
+ =========
+ There are 3 different data modes:
+diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
+index d9ac9706735b..d831d24d2a6c 100644
+--- a/Documentation/filesystems/proc.txt
++++ b/Documentation/filesystems/proc.txt
+@@ -956,6 +956,9 @@ Table 1-10: Files in /proc/fs/ext4/
+                  files are packed closely together.  Each large file
+                  will have its blocks allocated out of its own unique
+                  preallocation pool.
++inode_readahead  Tuning parameter which controls the maximum number of
++                 inode table blocks that ext4's inode table readahead
++                 algorithm will pre-read into the buffer cache
+ ..............................................................................
+ 
+ 
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 163c44527dde..922d18720c9e 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -790,6 +790,8 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
+ #define	EXT4_DEF_RESUID		0
+ #define	EXT4_DEF_RESGID		0
+ 
++#define EXT4_DEF_INODE_READAHEAD_BLKS	32
++
+ /*
+  * Default mount options
+  */
+diff --git a/fs/ext4/ext4_sb.h b/fs/ext4/ext4_sb.h
+index f92af01138d4..94e0757522a6 100644
+--- a/fs/ext4/ext4_sb.h
++++ b/fs/ext4/ext4_sb.h
+@@ -52,6 +52,7 @@ struct ext4_sb_info {
+ 	int s_desc_per_block_bits;
+ 	int s_inode_size;
+ 	int s_first_ino;
++	unsigned int s_inode_readahead_blks;
+ 	spinlock_t s_next_gen_lock;
+ 	u32 s_next_generation;
+ 	u32 s_hash_seed[4];
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 22fcbb67cd88..ef4ca3d4abc0 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -3833,41 +3833,6 @@ void ext4_truncate(struct inode *inode)
+ 	ext4_journal_stop(handle);
+ }
+ 
+-static ext4_fsblk_t ext4_get_inode_block(struct super_block *sb,
+-		unsigned long ino, struct ext4_iloc *iloc)
+-{
+-	ext4_group_t block_group;
+-	unsigned long offset;
+-	ext4_fsblk_t block;
+-	struct ext4_group_desc *gdp;
+-
+-	if (!ext4_valid_inum(sb, ino)) {
+-		/*
+-		 * This error is already checked for in namei.c unless we are
+-		 * looking at an NFS filehandle, in which case no error
+-		 * report is needed
+-		 */
+-		return 0;
+-	}
+-
+-	block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb);
+-	gdp = ext4_get_group_desc(sb, block_group, NULL);
+-	if (!gdp)
+-		return 0;
+-
+-	/*
+-	 * Figure out the offset within the block group inode table
+-	 */
+-	offset = ((ino - 1) % EXT4_INODES_PER_GROUP(sb)) *
+-		EXT4_INODE_SIZE(sb);
+-	block = ext4_inode_table(sb, gdp) +
+-		(offset >> EXT4_BLOCK_SIZE_BITS(sb));
+-
+-	iloc->block_group = block_group;
+-	iloc->offset = offset & (EXT4_BLOCK_SIZE(sb) - 1);
+-	return block;
+-}
+-
+ /*
+  * ext4_get_inode_loc returns with an extra refcount against the inode's
+  * underlying buffer_head on success. If 'in_mem' is true, we have all
+@@ -3877,19 +3842,35 @@ static ext4_fsblk_t ext4_get_inode_block(struct super_block *sb,
+ static int __ext4_get_inode_loc(struct inode *inode,
+ 				struct ext4_iloc *iloc, int in_mem)
+ {
+-	ext4_fsblk_t block;
+-	struct buffer_head *bh;
++	struct ext4_group_desc	*gdp;
++	struct buffer_head	*bh;
++	struct super_block	*sb = inode->i_sb;
++	ext4_fsblk_t		block;
++	int			inodes_per_block, inode_offset;
++
++	iloc->bh = 0;
++	if (!ext4_valid_inum(sb, inode->i_ino))
++		return -EIO;
+ 
+-	block = ext4_get_inode_block(inode->i_sb, inode->i_ino, iloc);
+-	if (!block)
++	iloc->block_group = (inode->i_ino - 1) / EXT4_INODES_PER_GROUP(sb);
++	gdp = ext4_get_group_desc(sb, iloc->block_group, NULL);
++	if (!gdp)
+ 		return -EIO;
+ 
+-	bh = sb_getblk(inode->i_sb, block);
++	/*
++	 * Figure out the offset within the block group inode table
++	 */
++	inodes_per_block = (EXT4_BLOCK_SIZE(sb) / EXT4_INODE_SIZE(sb));
++	inode_offset = ((inode->i_ino - 1) %
++			EXT4_INODES_PER_GROUP(sb));
++	block = ext4_inode_table(sb, gdp) + (inode_offset / inodes_per_block);
++	iloc->offset = (inode_offset % inodes_per_block) * EXT4_INODE_SIZE(sb);
++
++	bh = sb_getblk(sb, block);
+ 	if (!bh) {
+-		ext4_error (inode->i_sb, "ext4_get_inode_loc",
+-				"unable to read inode block - "
+-				"inode=%lu, block=%llu",
+-				 inode->i_ino, block);
++		ext4_error(sb, "ext4_get_inode_loc", "unable to read "
++			   "inode block - inode=%lu, block=%llu",
++			   inode->i_ino, block);
+ 		return -EIO;
+ 	}
+ 	if (!buffer_uptodate(bh)) {
+@@ -3917,28 +3898,12 @@ static int __ext4_get_inode_loc(struct inode *inode,
+ 		 */
+ 		if (in_mem) {
+ 			struct buffer_head *bitmap_bh;
+-			struct ext4_group_desc *desc;
+-			int inodes_per_buffer;
+-			int inode_offset, i;
+-			ext4_group_t block_group;
+-			int start;
+-
+-			block_group = (inode->i_ino - 1) /
+-					EXT4_INODES_PER_GROUP(inode->i_sb);
+-			inodes_per_buffer = bh->b_size /
+-				EXT4_INODE_SIZE(inode->i_sb);
+-			inode_offset = ((inode->i_ino - 1) %
+-					EXT4_INODES_PER_GROUP(inode->i_sb));
+-			start = inode_offset & ~(inodes_per_buffer - 1);
++			int i, start;
+ 
+-			/* Is the inode bitmap in cache? */
+-			desc = ext4_get_group_desc(inode->i_sb,
+-						block_group, NULL);
+-			if (!desc)
+-				goto make_io;
++			start = inode_offset & ~(inodes_per_block - 1);
+ 
+-			bitmap_bh = sb_getblk(inode->i_sb,
+-				ext4_inode_bitmap(inode->i_sb, desc));
++			/* Is the inode bitmap in cache? */
++			bitmap_bh = sb_getblk(sb, ext4_inode_bitmap(sb, gdp));
+ 			if (!bitmap_bh)
+ 				goto make_io;
+ 
+@@ -3951,14 +3916,14 @@ static int __ext4_get_inode_loc(struct inode *inode,
+ 				brelse(bitmap_bh);
+ 				goto make_io;
+ 			}
+-			for (i = start; i < start + inodes_per_buffer; i++) {
++			for (i = start; i < start + inodes_per_block; i++) {
+ 				if (i == inode_offset)
+ 					continue;
+ 				if (ext4_test_bit(i, bitmap_bh->b_data))
+ 					break;
+ 			}
+ 			brelse(bitmap_bh);
+-			if (i == start + inodes_per_buffer) {
++			if (i == start + inodes_per_block) {
+ 				/* all other inodes are free, so skip I/O */
+ 				memset(bh->b_data, 0, bh->b_size);
+ 				set_buffer_uptodate(bh);
+@@ -3968,6 +3933,36 @@ static int __ext4_get_inode_loc(struct inode *inode,
+ 		}
+ 
+ make_io:
++		/*
++		 * If we need to do any I/O, try to pre-readahead extra
++		 * blocks from the inode table.
++		 */
++		if (EXT4_SB(sb)->s_inode_readahead_blks) {
++			ext4_fsblk_t b, end, table;
++			unsigned num;
++
++			table = ext4_inode_table(sb, gdp);
++			/* Make sure s_inode_readahead_blks is a power of 2 */
++			while (EXT4_SB(sb)->s_inode_readahead_blks &
++			       (EXT4_SB(sb)->s_inode_readahead_blks-1))
++				EXT4_SB(sb)->s_inode_readahead_blks = 
++				   (EXT4_SB(sb)->s_inode_readahead_blks &
++				    (EXT4_SB(sb)->s_inode_readahead_blks-1));
++			b = block & ~(EXT4_SB(sb)->s_inode_readahead_blks-1);
++			if (table > b)
++				b = table;
++			end = b + EXT4_SB(sb)->s_inode_readahead_blks;
++			num = EXT4_INODES_PER_GROUP(sb);
++			if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
++				       EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
++				num -= le16_to_cpu(gdp->bg_itable_unused);
++			table += num / inodes_per_block;
++			if (end > table)
++				end = table;
++			while (b <= end)
++				sb_breadahead(sb, b++);
++		}
++
+ 		/*
+ 		 * There are other valid inodes in the buffer, this inode
+ 		 * has in-inode xattrs, or we don't have this inode in memory.
+@@ -3978,10 +3973,9 @@ static int __ext4_get_inode_loc(struct inode *inode,
+ 		submit_bh(READ_META, bh);
+ 		wait_on_buffer(bh);
+ 		if (!buffer_uptodate(bh)) {
+-			ext4_error(inode->i_sb, "ext4_get_inode_loc",
+-					"unable to read inode block - "
+-					"inode=%lu, block=%llu",
+-					inode->i_ino, block);
++			ext4_error(sb, __func__,
++				   "unable to read inode block - inode=%lu, "
++				   "block=%llu", inode->i_ino, block);
+ 			brelse(bh);
+ 			return -EIO;
+ 		}
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 9f5468fb06da..6583aee5177f 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -515,8 +515,10 @@ static void ext4_put_super(struct super_block *sb)
+ 		mark_buffer_dirty(sbi->s_sbh);
+ 		ext4_commit_super(sb, es, 1);
+ 	}
+-	if (sbi->s_proc)
++	if (sbi->s_proc) {
++		remove_proc_entry("inode_readahead_blks", sbi->s_proc);
+ 		remove_proc_entry(sb->s_id, ext4_proc_root);
++	}
+ 
+ 	for (i = 0; i < sbi->s_gdb_count; i++)
+ 		brelse(sbi->s_group_desc[i]);
+@@ -779,6 +781,10 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
+ 	else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
+ 		seq_puts(seq, ",data=writeback");
+ 
++	if (sbi->s_inode_readahead_blks != EXT4_DEF_INODE_READAHEAD_BLKS)
++		seq_printf(seq, ",inode_readahead_blks=%u",
++			   sbi->s_inode_readahead_blks);
++
+ 	ext4_show_quota_options(seq, sb);
+ 	return 0;
+ }
+@@ -913,6 +919,7 @@ enum {
+ 	Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
+ 	Opt_grpquota, Opt_extents, Opt_noextents, Opt_i_version,
+ 	Opt_mballoc, Opt_nomballoc, Opt_stripe, Opt_delalloc, Opt_nodelalloc,
++	Opt_inode_readahead_blks
+ };
+ 
+ static match_table_t tokens = {
+@@ -973,6 +980,7 @@ static match_table_t tokens = {
+ 	{Opt_resize, "resize"},
+ 	{Opt_delalloc, "delalloc"},
+ 	{Opt_nodelalloc, "nodelalloc"},
++	{Opt_inode_readahead_blks, "inode_readahead_blks=%u"},
+ 	{Opt_err, NULL},
+ };
+ 
+@@ -1381,6 +1389,13 @@ static int parse_options(char *options, struct super_block *sb,
+ 		case Opt_delalloc:
+ 			set_opt(sbi->s_mount_opt, DELALLOC);
+ 			break;
++		case Opt_inode_readahead_blks:
++			if (match_int(&args[0], &option))
++				return 0;
++			if (option < 0 || option > (1 << 30))
++				return 0;
++			sbi->s_inode_readahead_blks = option;
++			break;
+ 		default:
+ 			printk(KERN_ERR
+ 			       "EXT4-fs: Unrecognized mount option \"%s\" "
+@@ -1938,6 +1953,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	sbi->s_mount_opt = 0;
+ 	sbi->s_resuid = EXT4_DEF_RESUID;
+ 	sbi->s_resgid = EXT4_DEF_RESGID;
++	sbi->s_inode_readahead_blks = EXT4_DEF_INODE_READAHEAD_BLKS;
+ 	sbi->s_sb_block = sb_block;
+ 
+ 	unlock_kernel();
+@@ -2234,6 +2250,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	if (ext4_proc_root)
+ 		sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root);
+ 
++	if (sbi->s_proc)
++		proc_create_data("inode_readahead_blks", 0644, sbi->s_proc,
++				 &ext4_ui_proc_fops,
++				 &sbi->s_inode_readahead_blks);
++
+ 	bgl_lock_init(&sbi->s_blockgroup_lock);
+ 
+ 	for (i = 0; i < db_count; i++) {
+@@ -2513,8 +2534,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		brelse(sbi->s_group_desc[i]);
+ 	kfree(sbi->s_group_desc);
+ failed_mount:
+-	if (sbi->s_proc)
++	if (sbi->s_proc) {
++		remove_proc_entry("inode_readahead_blks", sbi->s_proc);
+ 		remove_proc_entry(sb->s_id, ext4_proc_root);
++	}
+ #ifdef CONFIG_QUOTA
+ 	for (i = 0; i < MAXQUOTAS; i++)
+ 		kfree(sbi->s_qf_names[i]);

commit 37515facd001942221d68171c81c1f46d54ffdd0
+Author: Theodore Ts'o 
+Date:   Thu Oct 9 23:21:54 2008 -0400
+
+    ext4: Improve the documentation for ext4's /proc tunables
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Alex Tomas 
+    Cc: Andreas Dilger 
+
+diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
+index f566ad9bcb7b..d9ac9706735b 100644
+--- a/Documentation/filesystems/proc.txt
++++ b/Documentation/filesystems/proc.txt
+@@ -923,45 +923,41 @@ CPUs.
+ The   "procs_blocked" line gives  the  number of  processes currently blocked,
+ waiting for I/O to complete.
+ 
++
+ 1.9 Ext4 file system parameters
+ ------------------------------
+-Ext4 file system have one directory per partition under /proc/fs/ext4/
+-# ls /proc/fs/ext4/hdc/
+-group_prealloc  max_to_scan  mb_groups  mb_history  min_to_scan  order2_req
+-stats  stream_req
+-
+-mb_groups:
+-This file gives the details of multiblock allocator buddy cache of free blocks
+-
+-mb_history:
+-Multiblock allocation history.
+-
+-stats:
+-This file indicate whether the multiblock allocator should start collecting
+-statistics. The statistics are shown during unmount
+-
+-group_prealloc:
+-The multiblock allocator normalize the block allocation request to
+-group_prealloc filesystem blocks if we don't have strip value set.
+-The stripe value can be specified at mount time or during mke2fs.
+-
+-max_to_scan:
+-How long multiblock allocator can look for a best extent (in found extents)
+-
+-min_to_scan:
+-How long multiblock allocator  must look for a best extent
+-
+-order2_req:
+-Multiblock allocator use  2^N search using buddies only for requests greater
+-than or equal to order2_req. The request size is specfied in file system
+-blocks. A value of 2 indicate only if the requests are greater than or equal
+-to 4 blocks.
+-
+-stream_req:
+-Files smaller than stream_req are served by the stream allocator, whose
+-purpose is to pack requests as close each to other as possible to
+-produce smooth I/O traffic. Avalue of 16 indicate that file smaller than 16
+-filesystem block size will use group based preallocation.
++
++Information about mounted ext4 file systems can be found in
++/proc/fs/ext4.  Each mounted filesystem will have a directory in
++/proc/fs/ext4 based on its device name (i.e., /proc/fs/ext4/hdc or
++/proc/fs/ext4/dm-0).   The files in each per-device directory are shown
++in Table 1-10, below.
++
++Table 1-10: Files in /proc/fs/ext4/
++..............................................................................
++ File            Content                                        
++ mb_groups       details of multiblock allocator buddy cache of free blocks
++ mb_history      multiblock allocation history
++ stats           controls whether the multiblock allocator should start
++                 collecting statistics, which are shown during the unmount
++ group_prealloc  the multiblock allocator will round up allocation
++                 requests to a multiple of this tuning parameter if the
++                 stripe size is not set in the ext4 superblock
++ max_to_scan     The maximum number of extents the multiblock allocator
++                 will search to find the best extent
++ min_to_scan     The minimum number of extents the multiblock allocator
++                 will search to find the best extent
++ order2_req      Tuning parameter which controls the minimum size for 
++                 requests (as a power of 2) where the buddy cache is
++                 used
++ stream_req      Files which have fewer blocks than this tunable
++                 parameter will have their blocks allocated out of a
++                 block group specific preallocation pool, so that small
++                 files are packed closely together.  Each large file
++                 will have its blocks allocated out of its own unique
++                 preallocation pool.
++..............................................................................
++
+ 
+ ------------------------------------------------------------------------------
+ Summary

commit 5e8814f2f74f53d58aa5679bf32b38a7940033fe
+Author: Theodore Ts'o 
+Date:   Tue Sep 23 18:07:35 2008 -0400
+
+    ext4: Combine proc file handling into a single set of functions
+    
+    Previously mballoc created a separate set of functions for each proc
+    file.  This combines the tunables into a single set of functions which
+    gets used for all of the per-superblock proc files, saving
+    approximately 2k of compiled object code.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index b9c9371d8164..163c44527dde 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -957,6 +957,22 @@ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
+ 
+ extern struct proc_dir_entry *ext4_proc_root;
+ 
++#ifdef CONFIG_PROC_FS
++extern const struct file_operations ext4_ui_proc_fops;
++
++#define	EXT4_PROC_HANDLER(name, var)					\
++do {									\
++	proc = proc_create_data(name, mode, sbi->s_proc,		\
++				&ext4_ui_proc_fops, &sbi->s_##var);	\
++	if (proc == NULL) {						\
++		printk(KERN_ERR "EXT4-fs: can't create %s\n", name);	\
++		goto err_out;						\
++	}								\
++} while (0)
++#else
++#define EXT4_PROC_HANDLER(name, var)
++#endif
++
+ /*
+  * Function prototypes
+  */
+diff --git a/fs/ext4/ext4_sb.h b/fs/ext4/ext4_sb.h
+index 95e046e77cb1..f92af01138d4 100644
+--- a/fs/ext4/ext4_sb.h
++++ b/fs/ext4/ext4_sb.h
+@@ -108,12 +108,12 @@ struct ext4_sb_info {
+ 
+ 	/* tunables */
+ 	unsigned long s_stripe;
+-	unsigned long s_mb_stream_request;
+-	unsigned long s_mb_max_to_scan;
+-	unsigned long s_mb_min_to_scan;
+-	unsigned long s_mb_stats;
+-	unsigned long s_mb_order2_reqs;
+-	unsigned long s_mb_group_prealloc;
++	unsigned int s_mb_stream_request;
++	unsigned int s_mb_max_to_scan;
++	unsigned int s_mb_min_to_scan;
++	unsigned int s_mb_stats;
++	unsigned int s_mb_order2_reqs;
++	unsigned int s_mb_group_prealloc;
+ 	/* where last allocation was done - for stream allocation */
+ 	unsigned long s_mb_last_group;
+ 	unsigned long s_mb_last_start;
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 842d4017006e..b9118bb29939 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2721,63 +2721,6 @@ ext4_mb_free_committed_blocks(struct super_block *sb)
+ #define EXT4_MB_STREAM_REQ		"stream_req"
+ #define EXT4_MB_GROUP_PREALLOC		"group_prealloc"
+ 
+-#define MB_PROC_FOPS(name)					\
+-static int ext4_mb_##name##_proc_show(struct seq_file *m, void *v)	\
+-{								\
+-	struct ext4_sb_info *sbi = m->private;			\
+-								\
+-	seq_printf(m, "%ld\n", sbi->s_mb_##name);		\
+-	return 0;						\
+-}								\
+-								\
+-static int ext4_mb_##name##_proc_open(struct inode *inode, struct file *file)\
+-{								\
+-	return single_open(file, ext4_mb_##name##_proc_show, PDE(inode)->data);\
+-}								\
+-								\
+-static ssize_t ext4_mb_##name##_proc_write(struct file *file,	\
+-		const char __user *buf, size_t cnt, loff_t *ppos)	\
+-{								\
+-	struct ext4_sb_info *sbi = PDE(file->f_path.dentry->d_inode)->data;\
+-	char str[32];						\
+-	long value;						\
+-	if (cnt >= sizeof(str))					\
+-		return -EINVAL;					\
+-	if (copy_from_user(str, buf, cnt))			\
+-		return -EFAULT;					\
+-	value = simple_strtol(str, NULL, 0);			\
+-	if (value <= 0)						\
+-		return -ERANGE;					\
+-	sbi->s_mb_##name = value;				\
+-	return cnt;						\
+-}								\
+-								\
+-static const struct file_operations ext4_mb_##name##_proc_fops = {	\
+-	.owner		= THIS_MODULE,				\
+-	.open		= ext4_mb_##name##_proc_open,		\
+-	.read		= seq_read,				\
+-	.llseek		= seq_lseek,				\
+-	.release	= single_release,			\
+-	.write		= ext4_mb_##name##_proc_write,		\
+-};
+-
+-MB_PROC_FOPS(stats);
+-MB_PROC_FOPS(max_to_scan);
+-MB_PROC_FOPS(min_to_scan);
+-MB_PROC_FOPS(order2_reqs);
+-MB_PROC_FOPS(stream_request);
+-MB_PROC_FOPS(group_prealloc);
+-
+-#define	MB_PROC_HANDLER(name, var)					\
+-do {									\
+-	proc = proc_create_data(name, mode, sbi->s_proc,		\
+-				&ext4_mb_##var##_proc_fops, sbi);	\
+-	if (proc == NULL) {						\
+-		printk(KERN_ERR "EXT4-fs: can't to create %s\n", name);	\
+-		goto err_out;						\
+-	}								\
+-} while (0)
+-
+ static int ext4_mb_init_per_dev_proc(struct super_block *sb)
+ {
+ 	mode_t mode = S_IFREG | S_IRUGO | S_IWUSR;
+@@ -2787,12 +2730,12 @@ static int ext4_mb_init_per_dev_proc(struct super_block *sb)
+ 	if (sbi->s_proc == NULL)
+ 		return -EINVAL;
+ 
+-	MB_PROC_HANDLER(EXT4_MB_STATS_NAME, stats);
+-	MB_PROC_HANDLER(EXT4_MB_MAX_TO_SCAN_NAME, max_to_scan);
+-	MB_PROC_HANDLER(EXT4_MB_MIN_TO_SCAN_NAME, min_to_scan);
+-	MB_PROC_HANDLER(EXT4_MB_ORDER2_REQ, order2_reqs);
+-	MB_PROC_HANDLER(EXT4_MB_STREAM_REQ, stream_request);
+-	MB_PROC_HANDLER(EXT4_MB_GROUP_PREALLOC, group_prealloc);
++	EXT4_PROC_HANDLER(EXT4_MB_STATS_NAME, mb_stats);
++	EXT4_PROC_HANDLER(EXT4_MB_MAX_TO_SCAN_NAME, mb_max_to_scan);
++	EXT4_PROC_HANDLER(EXT4_MB_MIN_TO_SCAN_NAME, mb_min_to_scan);
++	EXT4_PROC_HANDLER(EXT4_MB_ORDER2_REQ, mb_order2_reqs);
++	EXT4_PROC_HANDLER(EXT4_MB_STREAM_REQ, mb_stream_request);
++	EXT4_PROC_HANDLER(EXT4_MB_GROUP_PREALLOC, mb_group_prealloc);
+ 	return 0;
+ 
+ err_out:
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 7feeec6f7c39..9f5468fb06da 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3541,6 +3541,48 @@ static int ext4_get_sb(struct file_system_type *fs_type,
+ 	return get_sb_bdev(fs_type, flags, dev_name, data, ext4_fill_super, mnt);
+ }
+ 
++#ifdef CONFIG_PROC_FS
++static int ext4_ui_proc_show(struct seq_file *m, void *v)
++{
++	unsigned int *p = m->private;
++
++	seq_printf(m, "%u\n", *p);
++	return 0;
++}
++
++static int ext4_ui_proc_open(struct inode *inode, struct file *file)
++{
++	return single_open(file, ext4_ui_proc_show, PDE(inode)->data);
++}
++
++static ssize_t ext4_ui_proc_write(struct file *file, const char __user *buf,
++			       size_t cnt, loff_t *ppos)
++{
++	unsigned int *p = PDE(file->f_path.dentry->d_inode)->data;
++	char str[32];
++	unsigned long value;
++
++	if (cnt >= sizeof(str))
++		return -EINVAL;
++	if (copy_from_user(str, buf, cnt))
++		return -EFAULT;
++	value = simple_strtol(str, NULL, 0);
++	if (value < 0)
++		return -ERANGE;
++	*p = value;
++	return cnt;
++}
++
++const struct file_operations ext4_ui_proc_fops = {
++	.owner		= THIS_MODULE,
++	.open		= ext4_ui_proc_open,
++	.read		= seq_read,
++	.llseek		= seq_lseek,
++	.release	= single_release,
++	.write		= ext4_ui_proc_write,
++};
++#endif
++
+ static struct file_system_type ext4dev_fs_type = {
+ 	.owner		= THIS_MODULE,
+ 	.name		= "ext4dev",

commit 9f6200bbfc962d8f926278cf5d5ddb90a228c322
+Author: Theodore Ts'o 
+Date:   Tue Sep 23 09:18:24 2008 -0400
+
+    ext4: move /proc setup and teardown out of mballoc.c
+    
+    ...and into the core setup/teardown code in fs/ext4/super.c so that
+    other parts of ext4 can define tuning parameters.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 50a4846c7e71..b9c9371d8164 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -955,6 +955,8 @@ ext4_group_first_block_no(struct super_block *sb, ext4_group_t group_no)
+ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
+ 			unsigned long *blockgrpp, ext4_grpblk_t *offsetp);
+ 
++extern struct proc_dir_entry *ext4_proc_root;
++
+ /*
+  * Function prototypes
+  */
+diff --git a/fs/ext4/ext4_sb.h b/fs/ext4/ext4_sb.h
+index a5577e0ccd3b..95e046e77cb1 100644
+--- a/fs/ext4/ext4_sb.h
++++ b/fs/ext4/ext4_sb.h
+@@ -61,6 +61,7 @@ struct ext4_sb_info {
+ 	struct percpu_counter s_dirs_counter;
+ 	struct percpu_counter s_dirtyblocks_counter;
+ 	struct blockgroup_lock s_blockgroup_lock;
++	struct proc_dir_entry *s_proc;
+ 
+ 	/* root of the per fs reservation window tree */
+ 	spinlock_t s_rsv_window_lock;
+@@ -122,7 +123,6 @@ struct ext4_sb_info {
+ 	int s_mb_history_cur;
+ 	int s_mb_history_max;
+ 	int s_mb_history_num;
+-	struct proc_dir_entry *s_mb_proc;
+ 	spinlock_t s_mb_history_lock;
+ 	int s_mb_history_filter;
+ 
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 14ebd572bea8..842d4017006e 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2170,9 +2170,10 @@ static void ext4_mb_history_release(struct super_block *sb)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 
+-	remove_proc_entry("mb_groups", sbi->s_mb_proc);
+-	remove_proc_entry("mb_history", sbi->s_mb_proc);
+-
++	if (sbi->s_proc != NULL) {
++		remove_proc_entry("mb_groups", sbi->s_proc);
++		remove_proc_entry("mb_history", sbi->s_proc);
++	}
+ 	kfree(sbi->s_mb_history);
+ }
+ 
+@@ -2181,10 +2182,10 @@ static void ext4_mb_history_init(struct super_block *sb)
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	int i;
+ 
+-	if (sbi->s_mb_proc != NULL) {
+-		proc_create_data("mb_history", S_IRUGO, sbi->s_mb_proc,
++	if (sbi->s_proc != NULL) {
++		proc_create_data("mb_history", S_IRUGO, sbi->s_proc,
+ 				 &ext4_mb_seq_history_fops, sb);
+-		proc_create_data("mb_groups", S_IRUGO, sbi->s_mb_proc,
++		proc_create_data("mb_groups", S_IRUGO, sbi->s_proc,
+ 				 &ext4_mb_seq_groups_fops, sb);
+ 	}
+ 
+@@ -2720,8 +2721,6 @@ ext4_mb_free_committed_blocks(struct super_block *sb)
+ #define EXT4_MB_STREAM_REQ		"stream_req"
+ #define EXT4_MB_GROUP_PREALLOC		"group_prealloc"
+ 
+-
+-
+ #define MB_PROC_FOPS(name)					\
+ static int ext4_mb_##name##_proc_show(struct seq_file *m, void *v)	\
+ {								\
+@@ -2771,7 +2770,7 @@ MB_PROC_FOPS(group_prealloc);
+ 
+ #define	MB_PROC_HANDLER(name, var)					\
+ do {									\
+-	proc = proc_create_data(name, mode, sbi->s_mb_proc,		\
++	proc = proc_create_data(name, mode, sbi->s_proc,		\
+ 				&ext4_mb_##var##_proc_fops, sbi);	\
+ 	if (proc == NULL) {						\
+ 		printk(KERN_ERR "EXT4-fs: can't to create %s\n", name);	\
+@@ -2784,20 +2783,9 @@ static int ext4_mb_init_per_dev_proc(struct super_block *sb)
+ 	mode_t mode = S_IFREG | S_IRUGO | S_IWUSR;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	struct proc_dir_entry *proc;
+-	char devname[BDEVNAME_SIZE], *p;
+ 
+-	if (proc_root_ext4 == NULL) {
+-		sbi->s_mb_proc = NULL;
++	if (sbi->s_proc == NULL)
+ 		return -EINVAL;
+-	}
+-	bdevname(sb->s_bdev, devname);
+-	p = devname;
+-	while ((p = strchr(p, '/')))
+-		*p = '!';
+-
+-	sbi->s_mb_proc = proc_mkdir(devname, proc_root_ext4);
+-	if (!sbi->s_mb_proc)
+-		goto err_create_dir;
+ 
+ 	MB_PROC_HANDLER(EXT4_MB_STATS_NAME, stats);
+ 	MB_PROC_HANDLER(EXT4_MB_MAX_TO_SCAN_NAME, max_to_scan);
+@@ -2805,43 +2793,31 @@ static int ext4_mb_init_per_dev_proc(struct super_block *sb)
+ 	MB_PROC_HANDLER(EXT4_MB_ORDER2_REQ, order2_reqs);
+ 	MB_PROC_HANDLER(EXT4_MB_STREAM_REQ, stream_request);
+ 	MB_PROC_HANDLER(EXT4_MB_GROUP_PREALLOC, group_prealloc);
+-
+ 	return 0;
+ 
+ err_out:
+-	remove_proc_entry(EXT4_MB_GROUP_PREALLOC, sbi->s_mb_proc);
+-	remove_proc_entry(EXT4_MB_STREAM_REQ, sbi->s_mb_proc);
+-	remove_proc_entry(EXT4_MB_ORDER2_REQ, sbi->s_mb_proc);
+-	remove_proc_entry(EXT4_MB_MIN_TO_SCAN_NAME, sbi->s_mb_proc);
+-	remove_proc_entry(EXT4_MB_MAX_TO_SCAN_NAME, sbi->s_mb_proc);
+-	remove_proc_entry(EXT4_MB_STATS_NAME, sbi->s_mb_proc);
+-	remove_proc_entry(devname, proc_root_ext4);
+-	sbi->s_mb_proc = NULL;
+-err_create_dir:
+-	printk(KERN_ERR "EXT4-fs: Unable to create %s\n", devname);
+-
++	remove_proc_entry(EXT4_MB_GROUP_PREALLOC, sbi->s_proc);
++	remove_proc_entry(EXT4_MB_STREAM_REQ, sbi->s_proc);
++	remove_proc_entry(EXT4_MB_ORDER2_REQ, sbi->s_proc);
++	remove_proc_entry(EXT4_MB_MIN_TO_SCAN_NAME, sbi->s_proc);
++	remove_proc_entry(EXT4_MB_MAX_TO_SCAN_NAME, sbi->s_proc);
++	remove_proc_entry(EXT4_MB_STATS_NAME, sbi->s_proc);
+ 	return -ENOMEM;
+ }
+ 
+ static int ext4_mb_destroy_per_dev_proc(struct super_block *sb)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-	char devname[BDEVNAME_SIZE], *p;
+ 
+-	if (sbi->s_mb_proc == NULL)
++	if (sbi->s_proc == NULL)
+ 		return -EINVAL;
+ 
+-	bdevname(sb->s_bdev, devname);
+-	p = devname;
+-	while ((p = strchr(p, '/')))
+-		*p = '!';
+-	remove_proc_entry(EXT4_MB_GROUP_PREALLOC, sbi->s_mb_proc);
+-	remove_proc_entry(EXT4_MB_STREAM_REQ, sbi->s_mb_proc);
+-	remove_proc_entry(EXT4_MB_ORDER2_REQ, sbi->s_mb_proc);
+-	remove_proc_entry(EXT4_MB_MIN_TO_SCAN_NAME, sbi->s_mb_proc);
+-	remove_proc_entry(EXT4_MB_MAX_TO_SCAN_NAME, sbi->s_mb_proc);
+-	remove_proc_entry(EXT4_MB_STATS_NAME, sbi->s_mb_proc);
+-	remove_proc_entry(devname, proc_root_ext4);
++	remove_proc_entry(EXT4_MB_GROUP_PREALLOC, sbi->s_proc);
++	remove_proc_entry(EXT4_MB_STREAM_REQ, sbi->s_proc);
++	remove_proc_entry(EXT4_MB_ORDER2_REQ, sbi->s_proc);
++	remove_proc_entry(EXT4_MB_MIN_TO_SCAN_NAME, sbi->s_proc);
++	remove_proc_entry(EXT4_MB_MAX_TO_SCAN_NAME, sbi->s_proc);
++	remove_proc_entry(EXT4_MB_STATS_NAME, sbi->s_proc);
+ 
+ 	return 0;
+ }
+@@ -2863,11 +2839,6 @@ int __init init_ext4_mballoc(void)
+ 		kmem_cache_destroy(ext4_pspace_cachep);
+ 		return -ENOMEM;
+ 	}
+-#ifdef CONFIG_PROC_FS
+-	proc_root_ext4 = proc_mkdir("fs/ext4", NULL);
+-	if (proc_root_ext4 == NULL)
+-		printk(KERN_ERR "EXT4-fs: Unable to create fs/ext4\n");
+-#endif
+ 	return 0;
+ }
+ 
+@@ -2876,9 +2847,6 @@ void exit_ext4_mballoc(void)
+ 	/* XXX: synchronize_rcu(); */
+ 	kmem_cache_destroy(ext4_pspace_cachep);
+ 	kmem_cache_destroy(ext4_ac_cachep);
+-#ifdef CONFIG_PROC_FS
+-	remove_proc_entry("fs/ext4", NULL);
+-#endif
+ }
+ 
+ 
+diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
+index c7c9906c2a75..b3b4828f8b89 100644
+--- a/fs/ext4/mballoc.h
++++ b/fs/ext4/mballoc.h
+@@ -257,7 +257,6 @@ static void ext4_mb_store_history(struct ext4_allocation_context *ac);
+ 
+ #define in_range(b, first, len)	((b) >= (first) && (b) <= (first) + (len) - 1)
+ 
+-static struct proc_dir_entry *proc_root_ext4;
+ struct buffer_head *read_block_bitmap(struct super_block *, ext4_group_t);
+ 
+ static void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap,
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index fb5766e2bffe..7feeec6f7c39 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -34,6 +34,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -45,6 +46,8 @@
+ #include "namei.h"
+ #include "group.h"
+ 
++struct proc_dir_entry *ext4_proc_root;
++
+ static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
+ 			     unsigned long journal_devnum);
+ static int ext4_create_journal(struct super_block *, struct ext4_super_block *,
+@@ -512,6 +515,8 @@ static void ext4_put_super(struct super_block *sb)
+ 		mark_buffer_dirty(sbi->s_sbh);
+ 		ext4_commit_super(sb, es, 1);
+ 	}
++	if (sbi->s_proc)
++		remove_proc_entry(sb->s_id, ext4_proc_root);
+ 
+ 	for (i = 0; i < sbi->s_gdb_count; i++)
+ 		brelse(sbi->s_group_desc[i]);
+@@ -1916,6 +1921,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 	unsigned long journal_devnum = 0;
+ 	unsigned long def_mount_opts;
+ 	struct inode *root;
++	char *cp;
+ 	int ret = -EINVAL;
+ 	int blocksize;
+ 	int db_count;
+@@ -1936,6 +1942,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 
+ 	unlock_kernel();
+ 
++	/* Cleanup superblock name */
++	for (cp = sb->s_id; (cp = strchr(cp, '/'));)
++		*cp = '!';
++
+ 	blocksize = sb_min_blocksize(sb, EXT4_MIN_BLOCK_SIZE);
+ 	if (!blocksize) {
+ 		printk(KERN_ERR "EXT4-fs: unable to set blocksize\n");
+@@ -2221,6 +2231,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		goto failed_mount;
+ 	}
+ 
++	if (ext4_proc_root)
++		sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root);
++
+ 	bgl_lock_init(&sbi->s_blockgroup_lock);
+ 
+ 	for (i = 0; i < db_count; i++) {
+@@ -2500,6 +2513,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 		brelse(sbi->s_group_desc[i]);
+ 	kfree(sbi->s_group_desc);
+ failed_mount:
++	if (sbi->s_proc)
++		remove_proc_entry(sb->s_id, ext4_proc_root);
+ #ifdef CONFIG_QUOTA
+ 	for (i = 0; i < MAXQUOTAS; i++)
+ 		kfree(sbi->s_qf_names[i]);
+@@ -3538,6 +3553,7 @@ static int __init init_ext4_fs(void)
+ {
+ 	int err;
+ 
++	ext4_proc_root = proc_mkdir("fs/ext4", NULL);
+ 	err = init_ext4_mballoc();
+ 	if (err)
+ 		return err;
+@@ -3567,6 +3583,7 @@ static void __exit exit_ext4_fs(void)
+ 	destroy_inodecache();
+ 	exit_ext4_xattr();
+ 	exit_ext4_mballoc();
++	remove_proc_entry("fs/ext4", NULL);
+ }
+ 
+ MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");

commit f702ba0fd7d50b5f5f5aea5317875a10d40b869f
+Author: Theodore Ts'o 
+Date:   Mon Sep 22 15:21:01 2008 -0400
+
+    ext4: Don't use 'struct dentry' for internal lookups
+    
+    This is a port of a patch from Linus which fixes a 200+ byte stack
+    usage problem in ext4_get_parent().
+    
+    It's more efficient to pass down only the actual parts of the dentry
+    that matter: the parent inode and the name, instead of allocating a
+    struct dentry on the stack.
+    
+    Signed-off-by: Linus Torvalds 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index a1f72d217c7c..5295a9225cf9 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -159,7 +159,7 @@ static void dx_set_count(struct dx_entry *entries, unsigned value);
+ static void dx_set_limit(struct dx_entry *entries, unsigned value);
+ static unsigned dx_root_limit(struct inode *dir, unsigned infosize);
+ static unsigned dx_node_limit(struct inode *dir);
+-static struct dx_frame *dx_probe(struct dentry *dentry,
++static struct dx_frame *dx_probe(const struct qstr *d_name,
+ 				 struct inode *dir,
+ 				 struct dx_hash_info *hinfo,
+ 				 struct dx_frame *frame,
+@@ -177,8 +177,10 @@ static int ext4_htree_next_block(struct inode *dir, __u32 hash,
+ 				 struct dx_frame *frame,
+ 				 struct dx_frame *frames,
+ 				 __u32 *start_hash);
+-static struct buffer_head * ext4_dx_find_entry(struct dentry *dentry,
+-		       struct ext4_dir_entry_2 **res_dir, int *err);
++static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
++		const struct qstr *d_name,
++		struct ext4_dir_entry_2 **res_dir,
++		int *err);
+ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+ 			     struct inode *inode);
+ 
+@@ -345,7 +347,7 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir,
+  * back to userspace.
+  */
+ static struct dx_frame *
+-dx_probe(struct dentry *dentry, struct inode *dir,
++dx_probe(const struct qstr *d_name, struct inode *dir,
+ 	 struct dx_hash_info *hinfo, struct dx_frame *frame_in, int *err)
+ {
+ 	unsigned count, indirect;
+@@ -356,8 +358,6 @@ dx_probe(struct dentry *dentry, struct inode *dir,
+ 	u32 hash;
+ 
+ 	frame->bh = NULL;
+-	if (dentry)
+-		dir = dentry->d_parent->d_inode;
+ 	if (!(bh = ext4_bread (NULL,dir, 0, 0, err)))
+ 		goto fail;
+ 	root = (struct dx_root *) bh->b_data;
+@@ -373,8 +373,8 @@ dx_probe(struct dentry *dentry, struct inode *dir,
+ 	}
+ 	hinfo->hash_version = root->info.hash_version;
+ 	hinfo->seed = EXT4_SB(dir->i_sb)->s_hash_seed;
+-	if (dentry)
+-		ext4fs_dirhash(dentry->d_name.name, dentry->d_name.len, hinfo);
++	if (d_name)
++		ext4fs_dirhash(d_name->name, d_name->len, hinfo);
+ 	hash = hinfo->hash;
+ 
+ 	if (root->info.unused_flags & 1) {
+@@ -649,7 +649,7 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
+ 	}
+ 	hinfo.hash = start_hash;
+ 	hinfo.minor_hash = 0;
+-	frame = dx_probe(NULL, dir_file->f_path.dentry->d_inode, &hinfo, frames, &err);
++	frame = dx_probe(NULL, dir, &hinfo, frames, &err);
+ 	if (!frame)
+ 		return err;
+ 
+@@ -805,15 +805,15 @@ static inline int ext4_match (int len, const char * const name,
+  */
+ static inline int search_dirblock(struct buffer_head *bh,
+ 				  struct inode *dir,
+-				  struct dentry *dentry,
++				  const struct qstr *d_name,
+ 				  unsigned long offset,
+ 				  struct ext4_dir_entry_2 ** res_dir)
+ {
+ 	struct ext4_dir_entry_2 * de;
+ 	char * dlimit;
+ 	int de_len;
+-	const char *name = dentry->d_name.name;
+-	int namelen = dentry->d_name.len;
++	const char *name = d_name->name;
++	int namelen = d_name->len;
+ 
+ 	de = (struct ext4_dir_entry_2 *) bh->b_data;
+ 	dlimit = bh->b_data + dir->i_sb->s_blocksize;
+@@ -852,7 +852,8 @@ static inline int search_dirblock(struct buffer_head *bh,
+  * The returned buffer_head has ->b_count elevated.  The caller is expected
+  * to brelse() it when appropriate.
+  */
+-static struct buffer_head * ext4_find_entry (struct dentry *dentry,
++static struct buffer_head * ext4_find_entry (struct inode *dir,
++					const struct qstr *d_name,
+ 					struct ext4_dir_entry_2 ** res_dir)
+ {
+ 	struct super_block *sb;
+@@ -866,16 +867,15 @@ static struct buffer_head * ext4_find_entry (struct dentry *dentry,
+ 	int num = 0;
+ 	ext4_lblk_t  nblocks;
+ 	int i, err;
+-	struct inode *dir = dentry->d_parent->d_inode;
+ 	int namelen;
+ 
+ 	*res_dir = NULL;
+ 	sb = dir->i_sb;
+-	namelen = dentry->d_name.len;
++	namelen = d_name->len;
+ 	if (namelen > EXT4_NAME_LEN)
+ 		return NULL;
+ 	if (is_dx(dir)) {
+-		bh = ext4_dx_find_entry(dentry, res_dir, &err);
++		bh = ext4_dx_find_entry(dir, d_name, res_dir, &err);
+ 		/*
+ 		 * On success, or if the error was file not found,
+ 		 * return.  Otherwise, fall back to doing a search the
+@@ -928,7 +928,7 @@ static struct buffer_head * ext4_find_entry (struct dentry *dentry,
+ 			brelse(bh);
+ 			goto next;
+ 		}
+-		i = search_dirblock(bh, dir, dentry,
++		i = search_dirblock(bh, dir, d_name,
+ 			    block << EXT4_BLOCK_SIZE_BITS(sb), res_dir);
+ 		if (i == 1) {
+ 			EXT4_I(dir)->i_dir_start_lookup = block;
+@@ -962,7 +962,7 @@ static struct buffer_head * ext4_find_entry (struct dentry *dentry,
+ 	return ret;
+ }
+ 
+-static struct buffer_head * ext4_dx_find_entry(struct dentry *dentry,
++static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct qstr *d_name,
+ 		       struct ext4_dir_entry_2 **res_dir, int *err)
+ {
+ 	struct super_block * sb;
+@@ -973,14 +973,13 @@ static struct buffer_head * ext4_dx_find_entry(struct dentry *dentry,
+ 	struct buffer_head *bh;
+ 	ext4_lblk_t block;
+ 	int retval;
+-	int namelen = dentry->d_name.len;
+-	const u8 *name = dentry->d_name.name;
+-	struct inode *dir = dentry->d_parent->d_inode;
++	int namelen = d_name->len;
++	const u8 *name = d_name->name;
+ 
+ 	sb = dir->i_sb;
+ 	/* NFS may look up ".." - look at dx_root directory block */
+ 	if (namelen > 2 || name[0] != '.'||(name[1] != '.' && name[1] != '\0')){
+-		if (!(frame = dx_probe(dentry, NULL, &hinfo, frames, err)))
++		if (!(frame = dx_probe(d_name, dir, &hinfo, frames, err)))
+ 			return NULL;
+ 	} else {
+ 		frame = frames;
+@@ -1041,7 +1040,7 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, stru
+ 	if (dentry->d_name.len > EXT4_NAME_LEN)
+ 		return ERR_PTR(-ENAMETOOLONG);
+ 
+-	bh = ext4_find_entry(dentry, &de);
++	bh = ext4_find_entry(dir, &dentry->d_name, &de);
+ 	inode = NULL;
+ 	if (bh) {
+ 		unsigned long ino = le32_to_cpu(de->inode);
+@@ -1064,15 +1063,14 @@ struct dentry *ext4_get_parent(struct dentry *child)
+ 	unsigned long ino;
+ 	struct dentry *parent;
+ 	struct inode *inode;
+-	struct dentry dotdot;
++	static const struct qstr dotdot = {
++		.name = "..",
++		.len = 2,
++	};
+ 	struct ext4_dir_entry_2 * de;
+ 	struct buffer_head *bh;
+ 
+-	dotdot.d_name.name = "..";
+-	dotdot.d_name.len = 2;
+-	dotdot.d_parent = child; /* confusing, isn't it! */
+-
+-	bh = ext4_find_entry(&dotdot, &de);
++	bh = ext4_find_entry(child->d_inode, &dotdot, &de);
+ 	inode = NULL;
+ 	if (!bh)
+ 		return ERR_PTR(-ENOENT);
+@@ -1508,7 +1506,7 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+ 	struct ext4_dir_entry_2 *de;
+ 	int err;
+ 
+-	frame = dx_probe(dentry, NULL, &hinfo, frames, &err);
++	frame = dx_probe(&dentry->d_name, dir, &hinfo, frames, &err);
+ 	if (!frame)
+ 		return err;
+ 	entries = frame->entries;
+@@ -2089,7 +2087,7 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
+ 		return PTR_ERR(handle);
+ 
+ 	retval = -ENOENT;
+-	bh = ext4_find_entry(dentry, &de);
++	bh = ext4_find_entry(dir, &dentry->d_name, &de);
+ 	if (!bh)
+ 		goto end_rmdir;
+ 
+@@ -2151,7 +2149,7 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
+ 		handle->h_sync = 1;
+ 
+ 	retval = -ENOENT;
+-	bh = ext4_find_entry(dentry, &de);
++	bh = ext4_find_entry(dir, &dentry->d_name, &de);
+ 	if (!bh)
+ 		goto end_unlink;
+ 
+@@ -2312,7 +2310,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 	if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir))
+ 		handle->h_sync = 1;
+ 
+-	old_bh = ext4_find_entry(old_dentry, &old_de);
++	old_bh = ext4_find_entry(old_dir, &old_dentry->d_name, &old_de);
+ 	/*
+ 	 *  Check for inode number is _not_ due to possible IO errors.
+ 	 *  We might rmdir the source, keep it as pwd of some process
+@@ -2325,7 +2323,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 		goto end_rename;
+ 
+ 	new_inode = new_dentry->d_inode;
+-	new_bh = ext4_find_entry(new_dentry, &new_de);
++	new_bh = ext4_find_entry(new_dir, &new_dentry->d_name, &new_de);
+ 	if (new_bh) {
+ 		if (!new_inode) {
+ 			brelse(new_bh);
+@@ -2392,7 +2390,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 		struct buffer_head *old_bh2;
+ 		struct ext4_dir_entry_2 *old_de2;
+ 
+-		old_bh2 = ext4_find_entry(old_dentry, &old_de2);
++		old_bh2 = ext4_find_entry(old_dir, &old_dentry->d_name, &old_de2);
+ 		if (old_bh2) {
+ 			retval = ext4_delete_entry(handle, old_dir,
+ 						   old_de2, old_bh2);

commit 914258bf2cb22bf4336a1b1d90c551b4b11ca5aa
+Author: Theodore Ts'o 
+Date:   Mon Oct 6 21:35:40 2008 -0400
+
+    ext4/jbd2: Avoid WARN() messages when failing to write to the superblock
+    
+    This fixes some very common warnings reported by kerneloops.org
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 8175318abd84..fb5766e2bffe 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2810,13 +2810,34 @@ static void ext4_commit_super(struct super_block *sb,
+ 
+ 	if (!sbh)
+ 		return;
++	if (buffer_write_io_error(sbh)) {
++		/*
++		 * Oh, dear.  A previous attempt to write the
++		 * superblock failed.  This could happen because the
++		 * USB device was yanked out.  Or it could happen to
++		 * be a transient write error and maybe the block will
++		 * be remapped.  Nothing we can do but to retry the
++		 * write and hope for the best.
++		 */
++		printk(KERN_ERR "ext4: previous I/O error to "
++		       "superblock detected for %s.\n", sb->s_id);
++		clear_buffer_write_io_error(sbh);
++		set_buffer_uptodate(sbh);
++	}
+ 	es->s_wtime = cpu_to_le32(get_seconds());
+ 	ext4_free_blocks_count_set(es, ext4_count_free_blocks(sb));
+ 	es->s_free_inodes_count = cpu_to_le32(ext4_count_free_inodes(sb));
+ 	BUFFER_TRACE(sbh, "marking dirty");
+ 	mark_buffer_dirty(sbh);
+-	if (sync)
++	if (sync) {
+ 		sync_dirty_buffer(sbh);
++		if (buffer_write_io_error(sbh)) {
++			printk(KERN_ERR "ext4: I/O error while writing "
++			       "superblock for %s.\n", sb->s_id);
++			clear_buffer_write_io_error(sbh);
++			set_buffer_uptodate(sbh);
++		}
++	}
+ }
+ 
+ 
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 81186a29742e..01c3901c3a07 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -1255,6 +1255,22 @@ void jbd2_journal_update_superblock(journal_t *journal, int wait)
+ 		goto out;
+ 	}
+ 
++	if (buffer_write_io_error(bh)) {
++		/*
++		 * Oh, dear.  A previous attempt to write the journal
++		 * superblock failed.  This could happen because the
++		 * USB device was yanked out.  Or it could happen to
++		 * be a transient write error and maybe the block will
++		 * be remapped.  Nothing we can do but to retry the
++		 * write and hope for the best.
++		 */
++		printk(KERN_ERR "JBD2: previous I/O error detected "
++		       "for journal superblock update for %s.\n",
++		       journal->j_devname);
++		clear_buffer_write_io_error(bh);
++		set_buffer_uptodate(bh);
++	}
++
+ 	spin_lock(&journal->j_state_lock);
+ 	jbd_debug(1,"JBD: updating superblock (start %ld, seq %d, errno %d)\n",
+ 		  journal->j_tail, journal->j_tail_sequence, journal->j_errno);
+@@ -1266,9 +1282,16 @@ void jbd2_journal_update_superblock(journal_t *journal, int wait)
+ 
+ 	BUFFER_TRACE(bh, "marking dirty");
+ 	mark_buffer_dirty(bh);
+-	if (wait)
++	if (wait) {
+ 		sync_dirty_buffer(bh);
+-	else
++		if (buffer_write_io_error(bh)) {
++			printk(KERN_ERR "JBD2: I/O error detected "
++			       "when updating journal superblock for %s.\n",
++			       journal->j_devname);
++			clear_buffer_write_io_error(bh);
++			set_buffer_uptodate(bh);
++		}
++	} else
+ 		ll_rw_block(SWRITE, 1, &bh);
+ 
+ out:

commit 8eea80d52b9d87cfd771055534bd2c24f73704d7
+Author: Theodore Ts'o 
+Date:   Sat Sep 13 19:54:35 2008 -0400
+
+    ext4: Renumber EXT4_IOC_MIGRATE
+    
+    Pick an ioctl number for EXT4_IOC_MIGRATE that won't conflict with
+    other ext4 ioctl's.  Since there haven't been any major userspace
+    users of this ioctl, we can afford to change this now, to avoid
+    potential problems later.
+    
+    Also, reorder the ioctl numbers in ext4.h to avoid this sort of
+    mistake in the future.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 068adc1d5607..50a4846c7e71 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -291,8 +291,6 @@ struct ext4_new_group_data {
+ #define	EXT4_IOC_SETFLAGS		FS_IOC_SETFLAGS
+ #define	EXT4_IOC_GETVERSION		_IOR('f', 3, long)
+ #define	EXT4_IOC_SETVERSION		_IOW('f', 4, long)
+-#define EXT4_IOC_GROUP_EXTEND		_IOW('f', 7, unsigned long)
+-#define EXT4_IOC_GROUP_ADD		_IOW('f', 8, struct ext4_new_group_input)
+ #define	EXT4_IOC_GETVERSION_OLD		FS_IOC_GETVERSION
+ #define	EXT4_IOC_SETVERSION_OLD		FS_IOC_SETVERSION
+ #ifdef CONFIG_JBD2_DEBUG
+@@ -300,7 +298,10 @@ struct ext4_new_group_data {
+ #endif
+ #define EXT4_IOC_GETRSVSZ		_IOR('f', 5, long)
+ #define EXT4_IOC_SETRSVSZ		_IOW('f', 6, long)
+-#define EXT4_IOC_MIGRATE		_IO('f', 7)
++#define EXT4_IOC_GROUP_EXTEND		_IOW('f', 7, unsigned long)
++#define EXT4_IOC_GROUP_ADD		_IOW('f', 8, struct ext4_new_group_input)
++#define EXT4_IOC_MIGRATE		_IO('f', 9)
++ /* note ioctl 11 reserved for filesystem-independent FIEMAP ioctl */
+ 
+ /*
+  * ioctl commands in 32 bit emulation

commit 05496769e5da83ce22ed97345afd9c7b71d6bd24
+Author: Theodore Ts'o 
+Date:   Tue Sep 16 14:36:17 2008 -0400
+
+    jbd2: clean up how the journal device name is printed
+    
+    Calculate the journal device name once and stash it away in the
+    journal_s structure.  This avoids needing to call bdevname()
+    everywhere and reduces stack usage by not needing to allocate an
+    on-stack buffer.  In addition, we eliminate the '/' that can appear in
+    device names (e.g. "cciss/c0d0p9" --- see kernel bugzilla #11321) that
+    can cause problems when creating proc directory names, and include the
+    inode number to support ocfs2 which creates multiple journals with
+    different inode numbers.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index f58cc0309dc9..64e1c21eb5d2 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1476,15 +1476,9 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
+ 			EXT4_INODES_PER_GROUP(sb),
+ 			sbi->s_mount_opt);
+ 
+-	if (EXT4_SB(sb)->s_journal->j_inode == NULL) {
+-		char b[BDEVNAME_SIZE];
+-
+-		printk(KERN_INFO "EXT4 FS on %s, external journal on %s\n",
+-		       sb->s_id, bdevname(EXT4_SB(sb)->s_journal->j_dev, b));
+-	} else {
+-		printk(KERN_INFO "EXT4 FS on %s, internal journal\n",
+-		       sb->s_id);
+-	}
++	printk(KERN_INFO "EXT4 FS on %s, %s journal on %s\n",
++	       sb->s_id, EXT4_SB(sb)->s_journal->j_inode ? "internal" :
++	       "external", EXT4_SB(sb)->s_journal->j_devname);
+ 	return res;
+ }
+ 
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index f2ad061e95ec..b091e5378fe0 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -147,12 +147,9 @@ static int journal_submit_commit_record(journal_t *journal,
+ 	 * to remember if we sent a barrier request
+ 	 */
+ 	if (ret == -EOPNOTSUPP && barrier_done) {
+-		char b[BDEVNAME_SIZE];
+-
+ 		printk(KERN_WARNING
+-			"JBD: barrier-based sync failed on %s - "
+-			"disabling barriers\n",
+-			bdevname(journal->j_dev, b));
++		       "JBD: barrier-based sync failed on %s - "
++		       "disabling barriers\n", journal->j_devname);
+ 		spin_lock(&journal->j_state_lock);
+ 		journal->j_flags &= ~JBD2_BARRIER;
+ 		spin_unlock(&journal->j_state_lock);
+@@ -681,11 +678,9 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+ 	 */
+ 	err = journal_finish_inode_data_buffers(journal, commit_transaction);
+ 	if (err) {
+-		char b[BDEVNAME_SIZE];
+-
+ 		printk(KERN_WARNING
+ 			"JBD2: Detected IO errors while flushing file data "
+-			"on %s\n", bdevname(journal->j_fs_dev, b));
++		       "on %s\n", journal->j_devname);
+ 		err = 0;
+ 	}
+ 
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 8207a01c4edb..81186a29742e 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -597,13 +597,9 @@ int jbd2_journal_bmap(journal_t *journal, unsigned long blocknr,
+ 		if (ret)
+ 			*retp = ret;
+ 		else {
+-			char b[BDEVNAME_SIZE];
+-
+ 			printk(KERN_ALERT "%s: journal block not found "
+ 					"at offset %lu on %s\n",
+-				__func__,
+-				blocknr,
+-				bdevname(journal->j_dev, b));
++			       __func__, blocknr, journal->j_devname);
+ 			err = -EIO;
+ 			__journal_abort_soft(journal, err);
+ 		}
+@@ -901,10 +897,7 @@ static struct proc_dir_entry *proc_jbd2_stats;
+ 
+ static void jbd2_stats_proc_init(journal_t *journal)
+ {
+-	char name[BDEVNAME_SIZE];
+-
+-	bdevname(journal->j_dev, name);
+-	journal->j_proc_entry = proc_mkdir(name, proc_jbd2_stats);
++	journal->j_proc_entry = proc_mkdir(journal->j_devname, proc_jbd2_stats);
+ 	if (journal->j_proc_entry) {
+ 		proc_create_data("history", S_IRUGO, journal->j_proc_entry,
+ 				 &jbd2_seq_history_fops, journal);
+@@ -915,12 +908,9 @@ static void jbd2_stats_proc_init(journal_t *journal)
+ 
+ static void jbd2_stats_proc_exit(journal_t *journal)
+ {
+-	char name[BDEVNAME_SIZE];
+-
+-	bdevname(journal->j_dev, name);
+ 	remove_proc_entry("info", journal->j_proc_entry);
+ 	remove_proc_entry("history", journal->j_proc_entry);
+-	remove_proc_entry(name, proc_jbd2_stats);
++	remove_proc_entry(journal->j_devname, proc_jbd2_stats);
+ }
+ 
+ static void journal_init_stats(journal_t *journal)
+@@ -1018,6 +1008,7 @@ journal_t * jbd2_journal_init_dev(struct block_device *bdev,
+ {
+ 	journal_t *journal = journal_init_common();
+ 	struct buffer_head *bh;
++	char *p;
+ 	int n;
+ 
+ 	if (!journal)
+@@ -1039,6 +1030,10 @@ journal_t * jbd2_journal_init_dev(struct block_device *bdev,
+ 	journal->j_fs_dev = fs_dev;
+ 	journal->j_blk_offset = start;
+ 	journal->j_maxlen = len;
++	bdevname(journal->j_dev, journal->j_devname);
++	p = journal->j_devname;
++	while ((p = strchr(p, '/')))
++		*p = '!';
+ 	jbd2_stats_proc_init(journal);
+ 
+ 	bh = __getblk(journal->j_dev, start, journal->j_blocksize);
+@@ -1061,6 +1056,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode)
+ {
+ 	struct buffer_head *bh;
+ 	journal_t *journal = journal_init_common();
++	char *p;
+ 	int err;
+ 	int n;
+ 	unsigned long long blocknr;
+@@ -1070,6 +1066,12 @@ journal_t * jbd2_journal_init_inode (struct inode *inode)
+ 
+ 	journal->j_dev = journal->j_fs_dev = inode->i_sb->s_bdev;
+ 	journal->j_inode = inode;
++	bdevname(journal->j_dev, journal->j_devname);
++	p = journal->j_devname;
++	while ((p = strchr(p, '/')))
++		*p = '!';
++	p = journal->j_devname + strlen(journal->j_devname);
++	sprintf(p, ":%lu", journal->j_inode->i_ino);
+ 	jbd_debug(1,
+ 		  "journal %p: inode %s/%ld, size %Ld, bits %d, blksize %ld\n",
+ 		  journal, inode->i_sb->s_id, inode->i_ino,
+@@ -1760,23 +1762,6 @@ int jbd2_journal_wipe(journal_t *journal, int write)
+ 	return err;
+ }
+ 
+-/*
+- * journal_dev_name: format a character string to describe on what
+- * device this journal is present.
+- */
+-
+-static const char *journal_dev_name(journal_t *journal, char *buffer)
+-{
+-	struct block_device *bdev;
+-
+-	if (journal->j_inode)
+-		bdev = journal->j_inode->i_sb->s_bdev;
+-	else
+-		bdev = journal->j_dev;
+-
+-	return bdevname(bdev, buffer);
+-}
+-
+ /*
+  * Journal abort has very specific semantics, which we describe
+  * for journal abort.
+@@ -1793,13 +1778,12 @@ static const char *journal_dev_name(journal_t *journal, char *buffer)
+ void __jbd2_journal_abort_hard(journal_t *journal)
+ {
+ 	transaction_t *transaction;
+-	char b[BDEVNAME_SIZE];
+ 
+ 	if (journal->j_flags & JBD2_ABORT)
+ 		return;
+ 
+ 	printk(KERN_ERR "Aborting journal on device %s.\n",
+-		journal_dev_name(journal, b));
++	       journal->j_devname);
+ 
+ 	spin_lock(&journal->j_state_lock);
+ 	journal->j_flags |= JBD2_ABORT;
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index 3dd209007098..66c3499478b5 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -850,7 +850,8 @@ struct journal_s
+ 	 */
+ 	struct block_device	*j_dev;
+ 	int			j_blocksize;
+-	unsigned long long		j_blk_offset;
++	unsigned long long	j_blk_offset;
++	char			j_devname[BDEVNAME_SIZE+24];
+ 
+ 	/*
+ 	 * Device which holds the client fs.  For internal journal this will be

commit af5bc92dded4d98dfeabc8b5b9812571345b263d
+Author: Theodore Ts'o 
+Date:   Mon Sep 8 22:25:24 2008 -0400
+
+    ext4: Fix whitespace checkpatch warnings/errors
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/acl.h b/fs/ext4/acl.h
+index cd2b855a07d6..4c9948f69f8b 100644
+--- a/fs/ext4/acl.h
++++ b/fs/ext4/acl.h
+@@ -58,9 +58,9 @@ static inline int ext4_acl_count(size_t size)
+ #define EXT4_ACL_NOT_CACHED ((void *)-1)
+ 
+ /* acl.c */
+-extern int ext4_permission (struct inode *, int);
+-extern int ext4_acl_chmod (struct inode *);
+-extern int ext4_init_acl (handle_t *, struct inode *, struct inode *);
++extern int ext4_permission(struct inode *, int);
++extern int ext4_acl_chmod(struct inode *);
++extern int ext4_init_acl(handle_t *, struct inode *, struct inode *);
+ 
+ #else  /* CONFIG_EXT4DEV_FS_POSIX_ACL */
+ #include 
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 7aac2025ba9c..58005c01abb8 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -132,7 +132,7 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
+ 		 */
+ 		group_blocks = ext4_blocks_count(sbi->s_es) -
+ 			le32_to_cpu(sbi->s_es->s_first_data_block) -
+-			(EXT4_BLOCKS_PER_GROUP(sb) * (sbi->s_groups_count -1));
++			(EXT4_BLOCKS_PER_GROUP(sb) * (sbi->s_groups_count - 1));
+ 	} else {
+ 		group_blocks = EXT4_BLOCKS_PER_GROUP(sb);
+ 	}
+@@ -200,20 +200,20 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
+  * @bh:			pointer to the buffer head to store the block
+  *			group descriptor
+  */
+-struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
++struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
+ 					     ext4_group_t block_group,
+-					     struct buffer_head ** bh)
++					     struct buffer_head **bh)
+ {
+ 	unsigned long group_desc;
+ 	unsigned long offset;
+-	struct ext4_group_desc * desc;
++	struct ext4_group_desc *desc;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 
+ 	if (block_group >= sbi->s_groups_count) {
+-		ext4_error (sb, "ext4_get_group_desc",
+-			    "block_group >= groups_count - "
+-			    "block_group = %lu, groups_count = %lu",
+-			    block_group, sbi->s_groups_count);
++		ext4_error(sb, "ext4_get_group_desc",
++			   "block_group >= groups_count - "
++			   "block_group = %lu, groups_count = %lu",
++			   block_group, sbi->s_groups_count);
+ 
+ 		return NULL;
+ 	}
+@@ -222,10 +222,10 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
+ 	group_desc = block_group >> EXT4_DESC_PER_BLOCK_BITS(sb);
+ 	offset = block_group & (EXT4_DESC_PER_BLOCK(sb) - 1);
+ 	if (!sbi->s_group_desc[group_desc]) {
+-		ext4_error (sb, "ext4_get_group_desc",
+-			    "Group descriptor not loaded - "
+-			    "block_group = %lu, group_desc = %lu, desc = %lu",
+-			     block_group, group_desc, offset);
++		ext4_error(sb, "ext4_get_group_desc",
++			   "Group descriptor not loaded - "
++			   "block_group = %lu, group_desc = %lu, desc = %lu",
++			   block_group, group_desc, offset);
+ 		return NULL;
+ 	}
+ 
+@@ -302,8 +302,8 @@ static int ext4_valid_block_bitmap(struct super_block *sb,
+ struct buffer_head *
+ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
+ {
+-	struct ext4_group_desc * desc;
+-	struct buffer_head * bh = NULL;
++	struct ext4_group_desc *desc;
++	struct buffer_head *bh = NULL;
+ 	ext4_fsblk_t bitmap_blk;
+ 
+ 	desc = ext4_get_group_desc(sb, block_group, NULL);
+@@ -506,8 +506,8 @@ void ext4_rsv_window_add(struct super_block *sb,
+ 	struct rb_node *node = &rsv->rsv_node;
+ 	ext4_fsblk_t start = rsv->rsv_start;
+ 
+-	struct rb_node ** p = &root->rb_node;
+-	struct rb_node * parent = NULL;
++	struct rb_node **p = &root->rb_node;
++	struct rb_node *parent = NULL;
+ 	struct ext4_reserve_window_node *this;
+ 
+ 	while (*p)
+@@ -661,8 +661,8 @@ void ext4_free_blocks_sb(handle_t *handle, struct super_block *sb,
+ 	ext4_grpblk_t bit;
+ 	unsigned long i;
+ 	unsigned long overflow;
+-	struct ext4_group_desc * desc;
+-	struct ext4_super_block * es;
++	struct ext4_group_desc *desc;
++	struct ext4_super_block *es;
+ 	struct ext4_sb_info *sbi;
+ 	int err = 0, ret;
+ 	ext4_grpblk_t group_freed;
+@@ -673,13 +673,13 @@ void ext4_free_blocks_sb(handle_t *handle, struct super_block *sb,
+ 	if (block < le32_to_cpu(es->s_first_data_block) ||
+ 	    block + count < block ||
+ 	    block + count > ext4_blocks_count(es)) {
+-		ext4_error (sb, "ext4_free_blocks",
+-			    "Freeing blocks not in datazone - "
+-			    "block = %llu, count = %lu", block, count);
++		ext4_error(sb, "ext4_free_blocks",
++			   "Freeing blocks not in datazone - "
++			   "block = %llu, count = %lu", block, count);
+ 		goto error_return;
+ 	}
+ 
+-	ext4_debug ("freeing block(s) %llu-%llu\n", block, block + count - 1);
++	ext4_debug("freeing block(s) %llu-%llu\n", block, block + count - 1);
+ 
+ do_more:
+ 	overflow = 0;
+@@ -696,7 +696,7 @@ void ext4_free_blocks_sb(handle_t *handle, struct super_block *sb,
+ 	bitmap_bh = ext4_read_block_bitmap(sb, block_group);
+ 	if (!bitmap_bh)
+ 		goto error_return;
+-	desc = ext4_get_group_desc (sb, block_group, &gd_bh);
++	desc = ext4_get_group_desc(sb, block_group, &gd_bh);
+ 	if (!desc)
+ 		goto error_return;
+ 
+@@ -705,10 +705,10 @@ void ext4_free_blocks_sb(handle_t *handle, struct super_block *sb,
+ 	    in_range(block, ext4_inode_table(sb, desc), sbi->s_itb_per_group) ||
+ 	    in_range(block + count - 1, ext4_inode_table(sb, desc),
+ 		     sbi->s_itb_per_group)) {
+-		ext4_error (sb, "ext4_free_blocks",
+-			    "Freeing blocks in system zones - "
+-			    "Block = %llu, count = %lu",
+-			    block, count);
++		ext4_error(sb, "ext4_free_blocks",
++			   "Freeing blocks in system zones - "
++			   "Block = %llu, count = %lu",
++			   block, count);
+ 		goto error_return;
+ 	}
+ 
+@@ -850,7 +850,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 			ext4_fsblk_t block, unsigned long count,
+ 			int metadata)
+ {
+-	struct super_block * sb;
++	struct super_block *sb;
+ 	unsigned long dquot_freed_blocks;
+ 
+ 	/* this isn't the right place to decide whether block is metadata
+@@ -1019,7 +1019,7 @@ claim_block(spinlock_t *lock, ext4_grpblk_t block, struct buffer_head *bh)
+ 	if (ext4_set_bit_atomic(lock, block, bh->b_data))
+ 		return 0;
+ 	jbd_lock_bh_state(bh);
+-	if (jh->b_committed_data && ext4_test_bit(block,jh->b_committed_data)) {
++	if (jh->b_committed_data && ext4_test_bit(block, jh->b_committed_data)) {
+ 		ext4_clear_bit_atomic(lock, block, bh->b_data);
+ 		ret = 0;
+ 	} else {
+@@ -1170,7 +1170,7 @@ ext4_try_to_allocate(struct super_block *sb, handle_t *handle,
+ static int find_next_reservable_window(
+ 				struct ext4_reserve_window_node *search_head,
+ 				struct ext4_reserve_window_node *my_rsv,
+-				struct super_block * sb,
++				struct super_block *sb,
+ 				ext4_fsblk_t start_block,
+ 				ext4_fsblk_t last_block)
+ {
+@@ -1204,7 +1204,7 @@ static int find_next_reservable_window(
+ 
+ 		prev = rsv;
+ 		next = rb_next(&rsv->rsv_node);
+-		rsv = rb_entry(next,struct ext4_reserve_window_node,rsv_node);
++		rsv = rb_entry(next, struct ext4_reserve_window_node, rsv_node);
+ 
+ 		/*
+ 		 * Reached the last reservation, we can just append to the
+@@ -1342,7 +1342,7 @@ static int alloc_new_reservation(struct ext4_reserve_window_node *my_rsv,
+ 			size = size * 2;
+ 			if (size > EXT4_MAX_RESERVE_BLOCKS)
+ 				size = EXT4_MAX_RESERVE_BLOCKS;
+-			my_rsv->rsv_goal_size= size;
++			my_rsv->rsv_goal_size = size;
+ 		}
+ 	}
+ 
+@@ -1491,7 +1491,7 @@ static ext4_grpblk_t
+ ext4_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
+ 			ext4_group_t group, struct buffer_head *bitmap_bh,
+ 			ext4_grpblk_t grp_goal,
+-			struct ext4_reserve_window_node * my_rsv,
++			struct ext4_reserve_window_node *my_rsv,
+ 			unsigned long *count, int *errp)
+ {
+ 	ext4_fsblk_t group_first_block, group_last_block;
+@@ -1519,7 +1519,7 @@ ext4_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
+ 	 * or the file is not a regular file
+ 	 * or last attempt to allocate a block with reservation turned on failed
+ 	 */
+-	if (my_rsv == NULL ) {
++	if (my_rsv == NULL) {
+ 		ret = ext4_try_to_allocate(sb, handle, group, bitmap_bh,
+ 						grp_goal, count, NULL);
+ 		goto out;
+@@ -2184,7 +2184,7 @@ unsigned long ext4_bg_num_gdb(struct super_block *sb, ext4_group_t group)
+ 
+ 	if (!EXT4_HAS_INCOMPAT_FEATURE(sb,EXT4_FEATURE_INCOMPAT_META_BG) ||
+ 			metagroup < first_meta_bg)
+-		return ext4_bg_num_gdb_nometa(sb,group);
++		return ext4_bg_num_gdb_nometa(sb, group);
+ 
+ 	return ext4_bg_num_gdb_meta(sb,group);
+ 
+diff --git a/fs/ext4/bitmap.c b/fs/ext4/bitmap.c
+index d37ea6750454..0a7a6663c190 100644
+--- a/fs/ext4/bitmap.c
++++ b/fs/ext4/bitmap.c
+@@ -15,17 +15,17 @@
+ 
+ static const int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
+ 
+-unsigned long ext4_count_free (struct buffer_head * map, unsigned int numchars)
++unsigned long ext4_count_free(struct buffer_head *map, unsigned int numchars)
+ {
+ 	unsigned int i;
+ 	unsigned long sum = 0;
+ 
+ 	if (!map)
+-		return (0);
++		return 0;
+ 	for (i = 0; i < numchars; i++)
+ 		sum += nibblemap[map->b_data[i] & 0xf] +
+ 			nibblemap[(map->b_data[i] >> 4) & 0xf];
+-	return (sum);
++	return sum;
+ }
+ 
+ #endif  /*  EXT4FS_DEBUG  */
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index ac873dbf0dd0..d40da316921d 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -33,10 +33,10 @@ static unsigned char ext4_filetype_table[] = {
+ };
+ 
+ static int ext4_readdir(struct file *, void *, filldir_t);
+-static int ext4_dx_readdir(struct file * filp,
+-			   void * dirent, filldir_t filldir);
+-static int ext4_release_dir (struct inode * inode,
+-				struct file * filp);
++static int ext4_dx_readdir(struct file *filp,
++			   void *dirent, filldir_t filldir);
++static int ext4_release_dir(struct inode *inode,
++				struct file *filp);
+ 
+ const struct file_operations ext4_dir_operations = {
+ 	.llseek		= generic_file_llseek,
+@@ -61,12 +61,12 @@ static unsigned char get_dtype(struct super_block *sb, int filetype)
+ }
+ 
+ 
+-int ext4_check_dir_entry (const char * function, struct inode * dir,
+-			  struct ext4_dir_entry_2 * de,
+-			  struct buffer_head * bh,
+-			  unsigned long offset)
++int ext4_check_dir_entry(const char *function, struct inode *dir,
++			 struct ext4_dir_entry_2 *de,
++			 struct buffer_head *bh,
++			 unsigned long offset)
+ {
+-	const char * error_msg = NULL;
++	const char *error_msg = NULL;
+ 	const int rlen = ext4_rec_len_from_disk(de->rec_len);
+ 
+ 	if (rlen < EXT4_DIR_REC_LEN(1))
+@@ -82,7 +82,7 @@ int ext4_check_dir_entry (const char * function, struct inode * dir,
+ 		error_msg = "inode out of bounds";
+ 
+ 	if (error_msg != NULL)
+-		ext4_error (dir->i_sb, function,
++		ext4_error(dir->i_sb, function,
+ 			"bad entry in directory #%lu: %s - "
+ 			"offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
+ 			dir->i_ino, error_msg, offset,
+@@ -91,8 +91,8 @@ int ext4_check_dir_entry (const char * function, struct inode * dir,
+ 	return error_msg == NULL ? 1 : 0;
+ }
+ 
+-static int ext4_readdir(struct file * filp,
+-			 void * dirent, filldir_t filldir)
++static int ext4_readdir(struct file *filp,
++			 void *dirent, filldir_t filldir)
+ {
+ 	int error = 0;
+ 	unsigned long offset;
+@@ -148,7 +148,7 @@ static int ext4_readdir(struct file * filp,
+ 		 * of recovering data when there's a bad sector
+ 		 */
+ 		if (!bh) {
+-			ext4_error (sb, "ext4_readdir",
++			ext4_error(sb, "ext4_readdir",
+ 				"directory #%lu contains a hole at offset %lu",
+ 				inode->i_ino, (unsigned long)filp->f_pos);
+ 			/* corrupt size?  Maybe no more blocks to read */
+@@ -187,14 +187,14 @@ static int ext4_readdir(struct file * filp,
+ 		while (!error && filp->f_pos < inode->i_size
+ 		       && offset < sb->s_blocksize) {
+ 			de = (struct ext4_dir_entry_2 *) (bh->b_data + offset);
+-			if (!ext4_check_dir_entry ("ext4_readdir", inode, de,
+-						   bh, offset)) {
++			if (!ext4_check_dir_entry("ext4_readdir", inode, de,
++						  bh, offset)) {
+ 				/*
+ 				 * On error, skip the f_pos to the next block
+ 				 */
+ 				filp->f_pos = (filp->f_pos |
+ 						(sb->s_blocksize - 1)) + 1;
+-				brelse (bh);
++				brelse(bh);
+ 				ret = stored;
+ 				goto out;
+ 			}
+@@ -218,12 +218,12 @@ static int ext4_readdir(struct file * filp,
+ 					break;
+ 				if (version != filp->f_version)
+ 					goto revalidate;
+-				stored ++;
++				stored++;
+ 			}
+ 			filp->f_pos += ext4_rec_len_from_disk(de->rec_len);
+ 		}
+ 		offset = 0;
+-		brelse (bh);
++		brelse(bh);
+ 	}
+ out:
+ 	return ret;
+@@ -290,9 +290,9 @@ static void free_rb_tree_fname(struct rb_root *root)
+ 		parent = rb_parent(n);
+ 		fname = rb_entry(n, struct fname, rb_hash);
+ 		while (fname) {
+-			struct fname * old = fname;
++			struct fname *old = fname;
+ 			fname = fname->next;
+-			kfree (old);
++			kfree(old);
+ 		}
+ 		if (!parent)
+ 			root->rb_node = NULL;
+@@ -331,7 +331,7 @@ int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
+ 			     struct ext4_dir_entry_2 *dirent)
+ {
+ 	struct rb_node **p, *parent = NULL;
+-	struct fname * fname, *new_fn;
++	struct fname *fname, *new_fn;
+ 	struct dir_private_info *info;
+ 	int len;
+ 
+@@ -388,13 +388,13 @@ int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
+  * for all entres on the fname linked list.  (Normally there is only
+  * one entry on the linked list, unless there are 62 bit hash collisions.)
+  */
+-static int call_filldir(struct file * filp, void * dirent,
++static int call_filldir(struct file *filp, void *dirent,
+ 			filldir_t filldir, struct fname *fname)
+ {
+ 	struct dir_private_info *info = filp->private_data;
+ 	loff_t	curr_pos;
+ 	struct inode *inode = filp->f_path.dentry->d_inode;
+-	struct super_block * sb;
++	struct super_block *sb;
+ 	int error;
+ 
+ 	sb = inode->i_sb;
+@@ -420,8 +420,8 @@ static int call_filldir(struct file * filp, void * dirent,
+ 	return 0;
+ }
+ 
+-static int ext4_dx_readdir(struct file * filp,
+-			 void * dirent, filldir_t filldir)
++static int ext4_dx_readdir(struct file *filp,
++			 void *dirent, filldir_t filldir)
+ {
+ 	struct dir_private_info *info = filp->private_data;
+ 	struct inode *inode = filp->f_path.dentry->d_inode;
+@@ -512,7 +512,7 @@ static int ext4_dx_readdir(struct file * filp,
+ 	return 0;
+ }
+ 
+-static int ext4_release_dir (struct inode * inode, struct file * filp)
++static int ext4_release_dir(struct inode *inode, struct file *filp)
+ {
+ 	if (filp->private_data)
+ 		ext4_htree_free_dir_info(filp->private_data);
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 295003241d3d..8c701318844d 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -44,9 +44,9 @@
+ #ifdef EXT4FS_DEBUG
+ #define ext4_debug(f, a...)						\
+ 	do {								\
+-		printk (KERN_DEBUG "EXT4-fs DEBUG (%s, %d): %s:",	\
++		printk(KERN_DEBUG "EXT4-fs DEBUG (%s, %d): %s:",	\
+ 			__FILE__, __LINE__, __func__);			\
+-		printk (KERN_DEBUG f, ## a);				\
++		printk(KERN_DEBUG f, ## a);				\
+ 	} while (0)
+ #else
+ #define ext4_debug(f, a...)	do {} while (0)
+@@ -128,7 +128,7 @@ struct ext4_allocation_request {
+ #else
+ # define EXT4_BLOCK_SIZE(s)		(EXT4_MIN_BLOCK_SIZE << (s)->s_log_block_size)
+ #endif
+-#define	EXT4_ADDR_PER_BLOCK(s)		(EXT4_BLOCK_SIZE(s) / sizeof (__u32))
++#define	EXT4_ADDR_PER_BLOCK(s)		(EXT4_BLOCK_SIZE(s) / sizeof(__u32))
+ #ifdef __KERNEL__
+ # define EXT4_BLOCK_SIZE_BITS(s)	((s)->s_blocksize_bits)
+ #else
+@@ -292,7 +292,7 @@ struct ext4_new_group_data {
+ #define	EXT4_IOC_GETVERSION		_IOR('f', 3, long)
+ #define	EXT4_IOC_SETVERSION		_IOW('f', 4, long)
+ #define EXT4_IOC_GROUP_EXTEND		_IOW('f', 7, unsigned long)
+-#define EXT4_IOC_GROUP_ADD		_IOW('f', 8,struct ext4_new_group_input)
++#define EXT4_IOC_GROUP_ADD		_IOW('f', 8, struct ext4_new_group_input)
+ #define	EXT4_IOC_GETVERSION_OLD		FS_IOC_GETVERSION
+ #define	EXT4_IOC_SETVERSION_OLD		FS_IOC_SETVERSION
+ #ifdef CONFIG_JBD2_DEBUG
+@@ -667,7 +667,7 @@ struct ext4_super_block {
+ };
+ 
+ #ifdef __KERNEL__
+-static inline struct ext4_sb_info * EXT4_SB(struct super_block *sb)
++static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb)
+ {
+ 	return sb->s_fs_info;
+ }
+@@ -725,11 +725,11 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
+  */
+ 
+ #define EXT4_HAS_COMPAT_FEATURE(sb,mask)			\
+-	( EXT4_SB(sb)->s_es->s_feature_compat & cpu_to_le32(mask) )
++	(EXT4_SB(sb)->s_es->s_feature_compat & cpu_to_le32(mask))
+ #define EXT4_HAS_RO_COMPAT_FEATURE(sb,mask)			\
+-	( EXT4_SB(sb)->s_es->s_feature_ro_compat & cpu_to_le32(mask) )
++	(EXT4_SB(sb)->s_es->s_feature_ro_compat & cpu_to_le32(mask))
+ #define EXT4_HAS_INCOMPAT_FEATURE(sb,mask)			\
+-	( EXT4_SB(sb)->s_es->s_feature_incompat & cpu_to_le32(mask) )
++	(EXT4_SB(sb)->s_es->s_feature_incompat & cpu_to_le32(mask))
+ #define EXT4_SET_COMPAT_FEATURE(sb,mask)			\
+ 	EXT4_SB(sb)->s_es->s_feature_compat |= cpu_to_le32(mask)
+ #define EXT4_SET_RO_COMPAT_FEATURE(sb,mask)			\
+@@ -985,13 +985,13 @@ extern ext4_fsblk_t ext4_old_new_blocks(handle_t *handle, struct inode *inode,
+ 			ext4_fsblk_t goal, unsigned long *count, int *errp);
+ extern ext4_fsblk_t ext4_has_free_blocks(struct ext4_sb_info *sbi,
+ 						ext4_fsblk_t nblocks);
+-extern void ext4_free_blocks (handle_t *handle, struct inode *inode,
++extern void ext4_free_blocks(handle_t *handle, struct inode *inode,
+ 			ext4_fsblk_t block, unsigned long count, int metadata);
+-extern void ext4_free_blocks_sb (handle_t *handle, struct super_block *sb,
+-				 ext4_fsblk_t block, unsigned long count,
++extern void ext4_free_blocks_sb(handle_t *handle, struct super_block *sb,
++				ext4_fsblk_t block, unsigned long count,
+ 				unsigned long *pdquot_freed_blocks);
+-extern ext4_fsblk_t ext4_count_free_blocks (struct super_block *);
+-extern void ext4_check_blocks_bitmap (struct super_block *);
++extern ext4_fsblk_t ext4_count_free_blocks(struct super_block *);
++extern void ext4_check_blocks_bitmap(struct super_block *);
+ extern struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
+ 						    ext4_group_t block_group,
+ 						    struct buffer_head ** bh);
+@@ -1009,20 +1009,20 @@ extern int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
+ extern void ext4_htree_free_dir_info(struct dir_private_info *p);
+ 
+ /* fsync.c */
+-extern int ext4_sync_file (struct file *, struct dentry *, int);
++extern int ext4_sync_file(struct file *, struct dentry *, int);
+ 
+ /* hash.c */
+ extern int ext4fs_dirhash(const char *name, int len, struct
+ 			  dx_hash_info *hinfo);
+ 
+ /* ialloc.c */
+-extern struct inode * ext4_new_inode (handle_t *, struct inode *, int);
+-extern void ext4_free_inode (handle_t *, struct inode *);
+-extern struct inode * ext4_orphan_get (struct super_block *, unsigned long);
+-extern unsigned long ext4_count_free_inodes (struct super_block *);
+-extern unsigned long ext4_count_dirs (struct super_block *);
+-extern void ext4_check_inodes_bitmap (struct super_block *);
+-extern unsigned long ext4_count_free (struct buffer_head *, unsigned);
++extern struct inode * ext4_new_inode(handle_t *, struct inode *, int);
++extern void ext4_free_inode(handle_t *, struct inode *);
++extern struct inode * ext4_orphan_get(struct super_block *, unsigned long);
++extern unsigned long ext4_count_free_inodes(struct super_block *);
++extern unsigned long ext4_count_dirs(struct super_block *);
++extern void ext4_check_inodes_bitmap(struct super_block *);
++extern unsigned long ext4_count_free(struct buffer_head *, unsigned);
+ 
+ /* mballoc.c */
+ extern long ext4_mb_stats;
+@@ -1056,18 +1056,18 @@ int ext4_get_blocks_handle(handle_t *handle, struct inode *inode,
+ 				int create, int extend_disksize);
+ 
+ extern struct inode *ext4_iget(struct super_block *, unsigned long);
+-extern int  ext4_write_inode (struct inode *, int);
+-extern int  ext4_setattr (struct dentry *, struct iattr *);
++extern int  ext4_write_inode(struct inode *, int);
++extern int  ext4_setattr(struct dentry *, struct iattr *);
+ extern int  ext4_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ 				struct kstat *stat);
+-extern void ext4_delete_inode (struct inode *);
+-extern int  ext4_sync_inode (handle_t *, struct inode *);
+-extern void ext4_discard_reservation (struct inode *);
++extern void ext4_delete_inode(struct inode *);
++extern int  ext4_sync_inode(handle_t *, struct inode *);
++extern void ext4_discard_reservation(struct inode *);
+ extern void ext4_dirty_inode(struct inode *);
+ extern int ext4_change_inode_journal_flag(struct inode *, int);
+ extern int ext4_get_inode_loc(struct inode *, struct ext4_iloc *);
+ extern int ext4_can_truncate(struct inode *inode);
+-extern void ext4_truncate (struct inode *);
++extern void ext4_truncate(struct inode *);
+ extern void ext4_set_inode_flags(struct inode *);
+ extern void ext4_get_inode_flags(struct ext4_inode_info *);
+ extern void ext4_set_aops(struct inode *inode);
+@@ -1080,7 +1080,7 @@ extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct page *page);
+ 
+ /* ioctl.c */
+ extern long ext4_ioctl(struct file *, unsigned int, unsigned long);
+-extern long ext4_compat_ioctl (struct file *, unsigned int, unsigned long);
++extern long ext4_compat_ioctl(struct file *, unsigned int, unsigned long);
+ 
+ /* migrate.c */
+ extern int ext4_ext_migrate(struct inode *, struct file *, unsigned int,
+@@ -1099,14 +1099,14 @@ extern int ext4_group_extend(struct super_block *sb,
+ 				ext4_fsblk_t n_blocks_count);
+ 
+ /* super.c */
+-extern void ext4_error (struct super_block *, const char *, const char *, ...)
++extern void ext4_error(struct super_block *, const char *, const char *, ...)
+ 	__attribute__ ((format (printf, 3, 4)));
+-extern void __ext4_std_error (struct super_block *, const char *, int);
+-extern void ext4_abort (struct super_block *, const char *, const char *, ...)
++extern void __ext4_std_error(struct super_block *, const char *, int);
++extern void ext4_abort(struct super_block *, const char *, const char *, ...)
+ 	__attribute__ ((format (printf, 3, 4)));
+-extern void ext4_warning (struct super_block *, const char *, const char *, ...)
++extern void ext4_warning(struct super_block *, const char *, const char *, ...)
+ 	__attribute__ ((format (printf, 3, 4)));
+-extern void ext4_update_dynamic_rev (struct super_block *sb);
++extern void ext4_update_dynamic_rev(struct super_block *sb);
+ extern int ext4_update_compat_feature(handle_t *handle, struct super_block *sb,
+ 					__u32 compat);
+ extern int ext4_update_rocompat_feature(handle_t *handle,
+@@ -1179,7 +1179,7 @@ static inline void ext4_isize_set(struct ext4_inode *raw_inode, loff_t i_size)
+ 
+ static inline
+ struct ext4_group_info *ext4_get_group_info(struct super_block *sb,
+-							ext4_group_t group)
++					    ext4_group_t group)
+ {
+ 	 struct ext4_group_info ***grp_info;
+ 	 long indexv, indexh;
+diff --git a/fs/ext4/ext4_sb.h b/fs/ext4/ext4_sb.h
+index 6300226d5531..69810a252539 100644
+--- a/fs/ext4/ext4_sb.h
++++ b/fs/ext4/ext4_sb.h
+@@ -40,8 +40,8 @@ struct ext4_sb_info {
+ 	unsigned long s_blocks_last;    /* Last seen block count */
+ 	loff_t s_bitmap_maxbytes;	/* max bytes for bitmap files */
+ 	struct buffer_head * s_sbh;	/* Buffer containing the super block */
+-	struct ext4_super_block * s_es;	/* Pointer to the super block in the buffer */
+-	struct buffer_head ** s_group_desc;
++	struct ext4_super_block *s_es;	/* Pointer to the super block in the buffer */
++	struct buffer_head **s_group_desc;
+ 	unsigned long  s_mount_opt;
+ 	ext4_fsblk_t s_sb_block;
+ 	uid_t s_resuid;
+@@ -67,8 +67,8 @@ struct ext4_sb_info {
+ 	struct ext4_reserve_window_node s_rsv_window_head;
+ 
+ 	/* Journaling */
+-	struct inode * s_journal_inode;
+-	struct journal_s * s_journal;
++	struct inode *s_journal_inode;
++	struct journal_s *s_journal;
+ 	struct list_head s_orphan;
+ 	unsigned long s_commit_interval;
+ 	struct block_device *journal_bdev;
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index a8db7fdf9cb7..797f0602a68f 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -383,8 +383,8 @@ static void ext4_ext_show_leaf(struct inode *inode, struct ext4_ext_path *path)
+ 	ext_debug("\n");
+ }
+ #else
+-#define ext4_ext_show_path(inode,path)
+-#define ext4_ext_show_leaf(inode,path)
++#define ext4_ext_show_path(inode, path)
++#define ext4_ext_show_leaf(inode, path)
+ #endif
+ 
+ void ext4_ext_drop_refs(struct ext4_ext_path *path)
+@@ -1476,7 +1476,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+ 				struct ext4_ext_path *path,
+ 				struct ext4_extent *newext)
+ {
+-	struct ext4_extent_header * eh;
++	struct ext4_extent_header *eh;
+ 	struct ext4_extent *ex, *fex;
+ 	struct ext4_extent *nearex; /* nearest extent */
+ 	struct ext4_ext_path *npath = NULL;
+diff --git a/fs/ext4/file.c b/fs/ext4/file.c
+index 430eb7978db4..11b289f42b7d 100644
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -31,7 +31,7 @@
+  * from ext4_file_open: open gets called at every open, but release
+  * gets called only when /all/ the files are closed.
+  */
+-static int ext4_release_file (struct inode * inode, struct file * filp)
++static int ext4_release_file(struct inode *inode, struct file *filp)
+ {
+ 	/* if we are the last writer on the inode, drop the block reservation */
+ 	if ((filp->f_mode & FMODE_WRITE) &&
+diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
+index a45c3737ad31..c37d1e86f51a 100644
+--- a/fs/ext4/fsync.c
++++ b/fs/ext4/fsync.c
+@@ -43,7 +43,7 @@
+  * inode to disk.
+  */
+ 
+-int ext4_sync_file(struct file * file, struct dentry *dentry, int datasync)
++int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync)
+ {
+ 	struct inode *inode = dentry->d_inode;
+ 	journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
+diff --git a/fs/ext4/hash.c b/fs/ext4/hash.c
+index 1d6329dbe390..556ca8eba3db 100644
+--- a/fs/ext4/hash.c
++++ b/fs/ext4/hash.c
+@@ -27,7 +27,7 @@ static void TEA_transform(__u32 buf[4], __u32 const in[])
+ 		sum += DELTA;
+ 		b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
+ 		b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
+-	} while(--n);
++	} while (--n);
+ 
+ 	buf[0] += b0;
+ 	buf[1] += b1;
+@@ -35,7 +35,7 @@ static void TEA_transform(__u32 buf[4], __u32 const in[])
+ 
+ 
+ /* The old legacy hash */
+-static __u32 dx_hack_hash (const char *name, int len)
++static __u32 dx_hack_hash(const char *name, int len)
+ {
+ 	__u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
+ 	while (len--) {
+@@ -59,7 +59,7 @@ static void str2hashbuf(const char *msg, int len, __u32 *buf, int num)
+ 	val = pad;
+ 	if (len > num*4)
+ 		len = num * 4;
+-	for (i=0; i < len; i++) {
++	for (i = 0; i < len; i++) {
+ 		if ((i % 4) == 0)
+ 			val = pad;
+ 		val = msg[i] + (val << 8);
+@@ -104,7 +104,7 @@ int ext4fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo)
+ 
+ 	/* Check to see if the seed is all zero's */
+ 	if (hinfo->seed) {
+-		for (i=0; i < 4; i++) {
++		for (i = 0; i < 4; i++) {
+ 			if (hinfo->seed[i])
+ 				break;
+ 		}
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 45c66a03f182..5e66a2feef09 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -154,17 +154,17 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
+  * though), and then we'd have two inodes sharing the
+  * same inode number and space on the harddisk.
+  */
+-void ext4_free_inode (handle_t *handle, struct inode * inode)
++void ext4_free_inode(handle_t *handle, struct inode *inode)
+ {
+-	struct super_block * sb = inode->i_sb;
++	struct super_block *sb = inode->i_sb;
+ 	int is_directory;
+ 	unsigned long ino;
+ 	struct buffer_head *bitmap_bh = NULL;
+ 	struct buffer_head *bh2;
+ 	ext4_group_t block_group;
+ 	unsigned long bit;
+-	struct ext4_group_desc * gdp;
+-	struct ext4_super_block * es;
++	struct ext4_group_desc *gdp;
++	struct ext4_super_block *es;
+ 	struct ext4_sb_info *sbi;
+ 	int fatal = 0, err;
+ 	ext4_group_t flex_group;
+@@ -187,7 +187,7 @@ void ext4_free_inode (handle_t *handle, struct inode * inode)
+ 	sbi = EXT4_SB(sb);
+ 
+ 	ino = inode->i_ino;
+-	ext4_debug ("freeing inode %lu\n", ino);
++	ext4_debug("freeing inode %lu\n", ino);
+ 
+ 	/*
+ 	 * Note: we must free any quota before locking the superblock,
+@@ -201,12 +201,12 @@ void ext4_free_inode (handle_t *handle, struct inode * inode)
+ 	is_directory = S_ISDIR(inode->i_mode);
+ 
+ 	/* Do this BEFORE marking the inode not in use or returning an error */
+-	clear_inode (inode);
++	clear_inode(inode);
+ 
+ 	es = EXT4_SB(sb)->s_es;
+ 	if (ino < EXT4_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) {
+-		ext4_error (sb, "ext4_free_inode",
+-			    "reserved or nonexistent inode %lu", ino);
++		ext4_error(sb, "ext4_free_inode",
++			   "reserved or nonexistent inode %lu", ino);
+ 		goto error_return;
+ 	}
+ 	block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb);
+@@ -223,10 +223,10 @@ void ext4_free_inode (handle_t *handle, struct inode * inode)
+ 	/* Ok, now we can actually update the inode bitmaps.. */
+ 	if (!ext4_clear_bit_atomic(sb_bgl_lock(sbi, block_group),
+ 					bit, bitmap_bh->b_data))
+-		ext4_error (sb, "ext4_free_inode",
+-			      "bit already cleared for inode %lu", ino);
++		ext4_error(sb, "ext4_free_inode",
++			   "bit already cleared for inode %lu", ino);
+ 	else {
+-		gdp = ext4_get_group_desc (sb, block_group, &bh2);
++		gdp = ext4_get_group_desc(sb, block_group, &bh2);
+ 
+ 		BUFFER_TRACE(bh2, "get_write_access");
+ 		fatal = ext4_journal_get_write_access(handle, bh2);
+@@ -288,7 +288,7 @@ static int find_group_dir(struct super_block *sb, struct inode *parent,
+ 	avefreei = freei / ngroups;
+ 
+ 	for (group = 0; group < ngroups; group++) {
+-		desc = ext4_get_group_desc (sb, group, NULL);
++		desc = ext4_get_group_desc(sb, group, NULL);
+ 		if (!desc || !desc->bg_free_inodes_count)
+ 			continue;
+ 		if (le16_to_cpu(desc->bg_free_inodes_count) < avefreei)
+@@ -577,16 +577,16 @@ static int find_group_other(struct super_block *sb, struct inode *parent,
+  * For other inodes, search forward from the parent directory's block
+  * group to find a free inode.
+  */
+-struct inode *ext4_new_inode(handle_t *handle, struct inode * dir, int mode)
++struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
+ {
+ 	struct super_block *sb;
+ 	struct buffer_head *bitmap_bh = NULL;
+ 	struct buffer_head *bh2;
+ 	ext4_group_t group = 0;
+ 	unsigned long ino = 0;
+-	struct inode * inode;
+-	struct ext4_group_desc * gdp = NULL;
+-	struct ext4_super_block * es;
++	struct inode *inode;
++	struct ext4_group_desc *gdp = NULL;
++	struct ext4_super_block *es;
+ 	struct ext4_inode_info *ei;
+ 	struct ext4_sb_info *sbi;
+ 	int ret2, err = 0;
+@@ -614,7 +614,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode * dir, int mode)
+ 	}
+ 
+ 	if (S_ISDIR(mode)) {
+-		if (test_opt (sb, OLDALLOC))
++		if (test_opt(sb, OLDALLOC))
+ 			ret2 = find_group_dir(sb, dir, &group);
+ 		else
+ 			ret2 = find_group_orlov(sb, dir, &group);
+@@ -784,7 +784,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode * dir, int mode)
+ 	}
+ 
+ 	inode->i_uid = current->fsuid;
+-	if (test_opt (sb, GRPID))
++	if (test_opt(sb, GRPID))
+ 		inode->i_gid = dir->i_gid;
+ 	else if (dir->i_mode & S_ISGID) {
+ 		inode->i_gid = dir->i_gid;
+@@ -833,7 +833,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode * dir, int mode)
+ 	ei->i_extra_isize = EXT4_SB(sb)->s_want_extra_isize;
+ 
+ 	ret = inode;
+-	if(DQUOT_ALLOC_INODE(inode)) {
++	if (DQUOT_ALLOC_INODE(inode)) {
+ 		err = -EDQUOT;
+ 		goto fail_drop;
+ 	}
+@@ -842,7 +842,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode * dir, int mode)
+ 	if (err)
+ 		goto fail_free_drop;
+ 
+-	err = ext4_init_security(handle,inode, dir);
++	err = ext4_init_security(handle, inode, dir);
+ 	if (err)
+ 		goto fail_free_drop;
+ 
+@@ -960,7 +960,7 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
+ 	return ERR_PTR(err);
+ }
+ 
+-unsigned long ext4_count_free_inodes (struct super_block * sb)
++unsigned long ext4_count_free_inodes(struct super_block *sb)
+ {
+ 	unsigned long desc_count;
+ 	struct ext4_group_desc *gdp;
+@@ -975,7 +975,7 @@ unsigned long ext4_count_free_inodes (struct super_block * sb)
+ 	bitmap_count = 0;
+ 	gdp = NULL;
+ 	for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) {
+-		gdp = ext4_get_group_desc (sb, i, NULL);
++		gdp = ext4_get_group_desc(sb, i, NULL);
+ 		if (!gdp)
+ 			continue;
+ 		desc_count += le16_to_cpu(gdp->bg_free_inodes_count);
+@@ -997,7 +997,7 @@ unsigned long ext4_count_free_inodes (struct super_block * sb)
+ #else
+ 	desc_count = 0;
+ 	for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) {
+-		gdp = ext4_get_group_desc (sb, i, NULL);
++		gdp = ext4_get_group_desc(sb, i, NULL);
+ 		if (!gdp)
+ 			continue;
+ 		desc_count += le16_to_cpu(gdp->bg_free_inodes_count);
+@@ -1008,13 +1008,13 @@ unsigned long ext4_count_free_inodes (struct super_block * sb)
+ }
+ 
+ /* Called at mount-time, super-block is locked */
+-unsigned long ext4_count_dirs (struct super_block * sb)
++unsigned long ext4_count_dirs(struct super_block * sb)
+ {
+ 	unsigned long count = 0;
+ 	ext4_group_t i;
+ 
+ 	for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) {
+-		struct ext4_group_desc *gdp = ext4_get_group_desc (sb, i, NULL);
++		struct ext4_group_desc *gdp = ext4_get_group_desc(sb, i, NULL);
+ 		if (!gdp)
+ 			continue;
+ 		count += le16_to_cpu(gdp->bg_used_dirs_count);
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 7e91913e325b..89c92c0f8297 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -190,7 +190,7 @@ static int ext4_journal_test_restart(handle_t *handle, struct inode *inode)
+ /*
+  * Called at the last iput() if i_nlink is zero.
+  */
+-void ext4_delete_inode (struct inode * inode)
++void ext4_delete_inode(struct inode *inode)
+ {
+ 	handle_t *handle;
+ 	int err;
+@@ -330,11 +330,11 @@ static int ext4_block_to_path(struct inode *inode,
+ 	int final = 0;
+ 
+ 	if (i_block < 0) {
+-		ext4_warning (inode->i_sb, "ext4_block_to_path", "block < 0");
++		ext4_warning(inode->i_sb, "ext4_block_to_path", "block < 0");
+ 	} else if (i_block < direct_blocks) {
+ 		offsets[n++] = i_block;
+ 		final = direct_blocks;
+-	} else if ( (i_block -= direct_blocks) < indirect_blocks) {
++	} else if ((i_block -= direct_blocks) < indirect_blocks) {
+ 		offsets[n++] = EXT4_IND_BLOCK;
+ 		offsets[n++] = i_block;
+ 		final = ptrs;
+@@ -400,14 +400,14 @@ static Indirect *ext4_get_branch(struct inode *inode, int depth,
+ 
+ 	*err = 0;
+ 	/* i_data is not going away, no lock needed */
+-	add_chain (chain, NULL, EXT4_I(inode)->i_data + *offsets);
++	add_chain(chain, NULL, EXT4_I(inode)->i_data + *offsets);
+ 	if (!p->key)
+ 		goto no_block;
+ 	while (--depth) {
+ 		bh = sb_bread(sb, le32_to_cpu(p->key));
+ 		if (!bh)
+ 			goto failure;
+-		add_chain(++p, bh, (__le32*)bh->b_data + *++offsets);
++		add_chain(++p, bh, (__le32 *)bh->b_data + *++offsets);
+ 		/* Reader: end */
+ 		if (!p->key)
+ 			goto no_block;
+@@ -443,7 +443,7 @@ static Indirect *ext4_get_branch(struct inode *inode, int depth,
+ static ext4_fsblk_t ext4_find_near(struct inode *inode, Indirect *ind)
+ {
+ 	struct ext4_inode_info *ei = EXT4_I(inode);
+-	__le32 *start = ind->bh ? (__le32*) ind->bh->b_data : ei->i_data;
++	__le32 *start = ind->bh ? (__le32 *) ind->bh->b_data : ei->i_data;
+ 	__le32 *p;
+ 	ext4_fsblk_t bg_start;
+ 	ext4_fsblk_t last_block;
+@@ -630,7 +630,7 @@ static int ext4_alloc_blocks(handle_t *handle, struct inode *inode,
+ 	*err = 0;
+ 	return ret;
+ failed_out:
+-	for (i = 0; i b_data + offsets[n];
+ 		branch[n].key = cpu_to_le32(new_blocks[n]);
+ 		*branch[n].p = branch[n].key;
+-		if ( n == indirect_blks) {
++		if (n == indirect_blks) {
+ 			current_block = new_blocks[n];
+ 			/*
+ 			 * End of chain, update the last new metablock of
+@@ -730,7 +730,7 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
+ 		BUFFER_TRACE(branch[i].bh, "call jbd2_journal_forget");
+ 		ext4_journal_forget(handle, branch[i].bh);
+ 	}
+-	for (i = 0; i  1) {
+ 		current_block = le32_to_cpu(where->key) + 1;
+ 		for (i = 1; i < blks; i++)
+-			*(where->p + i ) = cpu_to_le32(current_block++);
++			*(where->p + i) = cpu_to_le32(current_block++);
+ 	}
+ 
+ 	/*
+@@ -1241,7 +1241,7 @@ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
+ 			BUFFER_TRACE(bh, "call get_create_access");
+ 			fatal = ext4_journal_get_create_access(handle, bh);
+ 			if (!fatal && !buffer_uptodate(bh)) {
+-				memset(bh->b_data,0,inode->i_sb->s_blocksize);
++				memset(bh->b_data, 0, inode->i_sb->s_blocksize);
+ 				set_buffer_uptodate(bh);
+ 			}
+ 			unlock_buffer(bh);
+@@ -1266,7 +1266,7 @@ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
+ struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode,
+ 			       ext4_lblk_t block, int create, int *err)
+ {
+-	struct buffer_head * bh;
++	struct buffer_head *bh;
+ 
+ 	bh = ext4_getblk(handle, inode, block, create, err);
+ 	if (!bh)
+@@ -1282,13 +1282,13 @@ struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode,
+ 	return NULL;
+ }
+ 
+-static int walk_page_buffers(	handle_t *handle,
+-				struct buffer_head *head,
+-				unsigned from,
+-				unsigned to,
+-				int *partial,
+-				int (*fn)(	handle_t *handle,
+-						struct buffer_head *bh))
++static int walk_page_buffers(handle_t *handle,
++			     struct buffer_head *head,
++			     unsigned from,
++			     unsigned to,
++			     int *partial,
++			     int (*fn)(handle_t *handle,
++				       struct buffer_head *bh))
+ {
+ 	struct buffer_head *bh;
+ 	unsigned block_start, block_end;
+@@ -1296,9 +1296,9 @@ static int walk_page_buffers(	handle_t *handle,
+ 	int err, ret = 0;
+ 	struct buffer_head *next;
+ 
+-	for (	bh = head, block_start = 0;
+-		ret == 0 && (bh != head || !block_start);
+-		block_start = block_end, bh = next)
++	for (bh = head, block_start = 0;
++	     ret == 0 && (bh != head || !block_start);
++	     block_start = block_end, bh = next)
+ 	{
+ 		next = bh->b_this_page;
+ 		block_end = block_start + blocksize;
+@@ -1351,23 +1351,23 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
+ 				loff_t pos, unsigned len, unsigned flags,
+ 				struct page **pagep, void **fsdata)
+ {
+- 	struct inode *inode = mapping->host;
++	struct inode *inode = mapping->host;
+ 	int ret, needed_blocks = ext4_writepage_trans_blocks(inode);
+ 	handle_t *handle;
+ 	int retries = 0;
+- 	struct page *page;
++	struct page *page;
+  	pgoff_t index;
+- 	unsigned from, to;
++	unsigned from, to;
+ 
+  	index = pos >> PAGE_CACHE_SHIFT;
+- 	from = pos & (PAGE_CACHE_SIZE - 1);
+- 	to = from + len;
++	from = pos & (PAGE_CACHE_SIZE - 1);
++	to = from + len;
+ 
+ retry:
+-  	handle = ext4_journal_start(inode, needed_blocks);
+-  	if (IS_ERR(handle)) {
+-  		ret = PTR_ERR(handle);
+-  		goto out;
++	handle = ext4_journal_start(inode, needed_blocks);
++	if (IS_ERR(handle)) {
++		ret = PTR_ERR(handle);
++		goto out;
+ 	}
+ 
+ 	page = __grab_cache_page(mapping, index);
+@@ -1387,9 +1387,9 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
+ 	}
+ 
+ 	if (ret) {
+- 		unlock_page(page);
++		unlock_page(page);
+ 		ext4_journal_stop(handle);
+- 		page_cache_release(page);
++		page_cache_release(page);
+ 	}
+ 
+ 	if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
+@@ -2456,7 +2456,7 @@ static int ext4_da_should_update_i_disksize(struct page *page,
+ 	bh = page_buffers(page);
+ 	idx = offset >> inode->i_blkbits;
+ 
+-	for (i=0; i < idx; i++)
++	for (i = 0; i < idx; i++)
+ 		bh = bh->b_this_page;
+ 
+ 	if (!buffer_mapped(bh) || (buffer_delay(bh)))
+@@ -2476,7 +2476,7 @@ static int ext4_da_write_end(struct file *file,
+ 	unsigned long start, end;
+ 
+ 	start = pos & (PAGE_CACHE_SIZE - 1);
+-	end = start + copied -1;
++	end = start + copied - 1;
+ 
+ 	/*
+ 	 * generic_write_end() will run mark_inode_dirty() if i_size
+@@ -2591,7 +2591,7 @@ static sector_t ext4_bmap(struct address_space *mapping, sector_t block)
+ 			return 0;
+ 	}
+ 
+-	return generic_block_bmap(mapping,block,ext4_get_block);
++	return generic_block_bmap(mapping, block, ext4_get_block);
+ }
+ 
+ static int bget_one(handle_t *handle, struct buffer_head *bh)
+@@ -3197,7 +3197,7 @@ static Indirect *ext4_find_shared(struct inode *inode, int depth,
+ 	if (!partial->key && *partial->p)
+ 		/* Writer: end */
+ 		goto no_top;
+-	for (p=partial; p>chain && all_zeroes((__le32*)p->bh->b_data,p->p); p--)
++	for (p = partial; (p > chain) && all_zeroes((__le32 *) p->bh->b_data, p->p); p--)
+ 		;
+ 	/*
+ 	 * OK, we've found the last block that must survive. The rest of our
+@@ -3216,7 +3216,7 @@ static Indirect *ext4_find_shared(struct inode *inode, int depth,
+ 	}
+ 	/* Writer: end */
+ 
+-	while(partial > p) {
++	while (partial > p) {
+ 		brelse(partial->bh);
+ 		partial--;
+ 	}
+@@ -3408,9 +3408,9 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
+ 			/* This zaps the entire block.  Bottom up. */
+ 			BUFFER_TRACE(bh, "free child branches");
+ 			ext4_free_branches(handle, inode, bh,
+-					   (__le32*)bh->b_data,
+-					   (__le32*)bh->b_data + addr_per_block,
+-					   depth);
++					(__le32 *) bh->b_data,
++					(__le32 *) bh->b_data + addr_per_block,
++					depth);
+ 
+ 			/*
+ 			 * We've probably journalled the indirect block several
+@@ -3927,7 +3927,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 	inode->i_mode = le16_to_cpu(raw_inode->i_mode);
+ 	inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low);
+ 	inode->i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low);
+-	if(!(test_opt (inode->i_sb, NO_UID32))) {
++	if (!(test_opt(inode->i_sb, NO_UID32))) {
+ 		inode->i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16;
+ 		inode->i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16;
+ 	}
+@@ -3945,7 +3945,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 		if (inode->i_mode == 0 ||
+ 		    !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) {
+ 			/* this inode is deleted */
+-			brelse (bh);
++			brelse(bh);
+ 			ret = -ESTALE;
+ 			goto bad_inode;
+ 		}
+@@ -3978,7 +3978,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 		ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize);
+ 		if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize >
+ 		    EXT4_INODE_SIZE(inode->i_sb)) {
+-			brelse (bh);
++			brelse(bh);
+ 			ret = -EIO;
+ 			goto bad_inode;
+ 		}
+@@ -4031,7 +4031,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
+ 			init_special_inode(inode, inode->i_mode,
+ 			   new_decode_dev(le32_to_cpu(raw_inode->i_block[1])));
+ 	}
+-	brelse (iloc.bh);
++	brelse(iloc.bh);
+ 	ext4_set_inode_flags(inode);
+ 	unlock_new_inode(inode);
+ 	return inode;
+@@ -4113,14 +4113,14 @@ static int ext4_do_update_inode(handle_t *handle,
+ 
+ 	ext4_get_inode_flags(ei);
+ 	raw_inode->i_mode = cpu_to_le16(inode->i_mode);
+-	if(!(test_opt(inode->i_sb, NO_UID32))) {
++	if (!(test_opt(inode->i_sb, NO_UID32))) {
+ 		raw_inode->i_uid_low = cpu_to_le16(low_16_bits(inode->i_uid));
+ 		raw_inode->i_gid_low = cpu_to_le16(low_16_bits(inode->i_gid));
+ /*
+  * Fix up interoperability with old kernels. Otherwise, old inodes get
+  * re-used with the upper 16 bits of the uid/gid intact
+  */
+-		if(!ei->i_dtime) {
++		if (!ei->i_dtime) {
+ 			raw_inode->i_uid_high =
+ 				cpu_to_le16(high_16_bits(inode->i_uid));
+ 			raw_inode->i_gid_high =
+@@ -4208,7 +4208,7 @@ static int ext4_do_update_inode(handle_t *handle,
+ 	ei->i_state &= ~EXT4_STATE_NEW;
+ 
+ out_brelse:
+-	brelse (bh);
++	brelse(bh);
+ 	ext4_std_error(inode->i_sb, err);
+ 	return err;
+ }
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index 7a6c2f1faba6..ca09dd1039ec 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -25,7 +25,7 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 	unsigned int flags;
+ 	unsigned short rsv_window_size;
+ 
+-	ext4_debug ("cmd = %u, arg = %lu\n", cmd, arg);
++	ext4_debug("cmd = %u, arg = %lu\n", cmd, arg);
+ 
+ 	switch (cmd) {
+ 	case EXT4_IOC_GETFLAGS:
+@@ -186,7 +186,7 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 	case EXT4_IOC_SETRSVSZ: {
+ 		int err;
+ 
+-		if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode))
++		if (!test_opt(inode->i_sb, RESERVATION) || !S_ISREG(inode->i_mode))
+ 			return -ENOTTY;
+ 
+ 		if (!is_owner_or_cap(inode))
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 978b57f8630d..a1f72d217c7c 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -151,26 +151,26 @@ struct dx_map_entry
+ 
+ static inline ext4_lblk_t dx_get_block(struct dx_entry *entry);
+ static void dx_set_block(struct dx_entry *entry, ext4_lblk_t value);
+-static inline unsigned dx_get_hash (struct dx_entry *entry);
+-static void dx_set_hash (struct dx_entry *entry, unsigned value);
+-static unsigned dx_get_count (struct dx_entry *entries);
+-static unsigned dx_get_limit (struct dx_entry *entries);
+-static void dx_set_count (struct dx_entry *entries, unsigned value);
+-static void dx_set_limit (struct dx_entry *entries, unsigned value);
+-static unsigned dx_root_limit (struct inode *dir, unsigned infosize);
+-static unsigned dx_node_limit (struct inode *dir);
++static inline unsigned dx_get_hash(struct dx_entry *entry);
++static void dx_set_hash(struct dx_entry *entry, unsigned value);
++static unsigned dx_get_count(struct dx_entry *entries);
++static unsigned dx_get_limit(struct dx_entry *entries);
++static void dx_set_count(struct dx_entry *entries, unsigned value);
++static void dx_set_limit(struct dx_entry *entries, unsigned value);
++static unsigned dx_root_limit(struct inode *dir, unsigned infosize);
++static unsigned dx_node_limit(struct inode *dir);
+ static struct dx_frame *dx_probe(struct dentry *dentry,
+ 				 struct inode *dir,
+ 				 struct dx_hash_info *hinfo,
+ 				 struct dx_frame *frame,
+ 				 int *err);
+-static void dx_release (struct dx_frame *frames);
+-static int dx_make_map (struct ext4_dir_entry_2 *de, int size,
+-			struct dx_hash_info *hinfo, struct dx_map_entry map[]);
++static void dx_release(struct dx_frame *frames);
++static int dx_make_map(struct ext4_dir_entry_2 *de, int size,
++		       struct dx_hash_info *hinfo, struct dx_map_entry map[]);
+ static void dx_sort_map(struct dx_map_entry *map, unsigned count);
+-static struct ext4_dir_entry_2 *dx_move_dirents (char *from, char *to,
++static struct ext4_dir_entry_2 *dx_move_dirents(char *from, char *to,
+ 		struct dx_map_entry *offsets, int count);
+-static struct ext4_dir_entry_2* dx_pack_dirents (char *base, int size);
++static struct ext4_dir_entry_2* dx_pack_dirents(char *base, int size);
+ static void dx_insert_block(struct dx_frame *frame,
+ 					u32 hash, ext4_lblk_t block);
+ static int ext4_htree_next_block(struct inode *dir, __u32 hash,
+@@ -207,44 +207,44 @@ static inline void dx_set_block(struct dx_entry *entry, ext4_lblk_t value)
+ 	entry->block = cpu_to_le32(value);
+ }
+ 
+-static inline unsigned dx_get_hash (struct dx_entry *entry)
++static inline unsigned dx_get_hash(struct dx_entry *entry)
+ {
+ 	return le32_to_cpu(entry->hash);
+ }
+ 
+-static inline void dx_set_hash (struct dx_entry *entry, unsigned value)
++static inline void dx_set_hash(struct dx_entry *entry, unsigned value)
+ {
+ 	entry->hash = cpu_to_le32(value);
+ }
+ 
+-static inline unsigned dx_get_count (struct dx_entry *entries)
++static inline unsigned dx_get_count(struct dx_entry *entries)
+ {
+ 	return le16_to_cpu(((struct dx_countlimit *) entries)->count);
+ }
+ 
+-static inline unsigned dx_get_limit (struct dx_entry *entries)
++static inline unsigned dx_get_limit(struct dx_entry *entries)
+ {
+ 	return le16_to_cpu(((struct dx_countlimit *) entries)->limit);
+ }
+ 
+-static inline void dx_set_count (struct dx_entry *entries, unsigned value)
++static inline void dx_set_count(struct dx_entry *entries, unsigned value)
+ {
+ 	((struct dx_countlimit *) entries)->count = cpu_to_le16(value);
+ }
+ 
+-static inline void dx_set_limit (struct dx_entry *entries, unsigned value)
++static inline void dx_set_limit(struct dx_entry *entries, unsigned value)
+ {
+ 	((struct dx_countlimit *) entries)->limit = cpu_to_le16(value);
+ }
+ 
+-static inline unsigned dx_root_limit (struct inode *dir, unsigned infosize)
++static inline unsigned dx_root_limit(struct inode *dir, unsigned infosize)
+ {
+ 	unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(1) -
+ 		EXT4_DIR_REC_LEN(2) - infosize;
+ 	return entry_space / sizeof(struct dx_entry);
+ }
+ 
+-static inline unsigned dx_node_limit (struct inode *dir)
++static inline unsigned dx_node_limit(struct inode *dir)
+ {
+ 	unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(0);
+ 	return entry_space / sizeof(struct dx_entry);
+@@ -306,7 +306,7 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir,
+ 			     struct dx_entry *entries, int levels)
+ {
+ 	unsigned blocksize = dir->i_sb->s_blocksize;
+-	unsigned count = dx_get_count (entries), names = 0, space = 0, i;
++	unsigned count = dx_get_count(entries), names = 0, space = 0, i;
+ 	unsigned bcount = 0;
+ 	struct buffer_head *bh;
+ 	int err;
+@@ -325,7 +325,7 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir,
+ 		names += stats.names;
+ 		space += stats.space;
+ 		bcount += stats.bcount;
+-		brelse (bh);
++		brelse(bh);
+ 	}
+ 	if (bcount)
+ 		printk(KERN_DEBUG "%snames %u, fullness %u (%u%%)\n", 
+@@ -407,7 +407,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
+ 		goto fail;
+ 	}
+ 
+-	dxtrace (printk("Look up %x", hash));
++	dxtrace(printk("Look up %x", hash));
+ 	while (1)
+ 	{
+ 		count = dx_get_count(entries);
+@@ -556,7 +556,7 @@ static int ext4_htree_next_block(struct inode *dir, __u32 hash,
+ 				      0, &err)))
+ 			return err; /* Failure */
+ 		p++;
+-		brelse (p->bh);
++		brelse(p->bh);
+ 		p->bh = bh;
+ 		p->at = p->entries = ((struct dx_node *) bh->b_data)->entries;
+ 	}
+@@ -594,7 +594,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
+ 			/* On error, skip the f_pos to the next block. */
+ 			dir_file->f_pos = (dir_file->f_pos |
+ 					(dir->i_sb->s_blocksize - 1)) + 1;
+-			brelse (bh);
++			brelse(bh);
+ 			return count;
+ 		}
+ 		ext4fs_dirhash(de->name, de->name_len, hinfo);
+@@ -803,7 +803,7 @@ static inline int ext4_match (int len, const char * const name,
+ /*
+  * Returns 0 if not found, -1 on failure, and 1 on success
+  */
+-static inline int search_dirblock(struct buffer_head * bh,
++static inline int search_dirblock(struct buffer_head *bh,
+ 				  struct inode *dir,
+ 				  struct dentry *dentry,
+ 				  unsigned long offset,
+@@ -855,9 +855,9 @@ static inline int search_dirblock(struct buffer_head * bh,
+ static struct buffer_head * ext4_find_entry (struct dentry *dentry,
+ 					struct ext4_dir_entry_2 ** res_dir)
+ {
+-	struct super_block * sb;
+-	struct buffer_head * bh_use[NAMEI_RA_SIZE];
+-	struct buffer_head * bh, *ret = NULL;
++	struct super_block *sb;
++	struct buffer_head *bh_use[NAMEI_RA_SIZE];
++	struct buffer_head *bh, *ret = NULL;
+ 	ext4_lblk_t start, block, b;
+ 	int ra_max = 0;		/* Number of bh's in the readahead
+ 				   buffer, bh_use[] */
+@@ -958,7 +958,7 @@ static struct buffer_head * ext4_find_entry (struct dentry *dentry,
+ cleanup_and_exit:
+ 	/* Clean up the read-ahead blocks */
+ 	for (; ra_ptr < ra_max; ra_ptr++)
+-		brelse (bh_use[ra_ptr]);
++		brelse(bh_use[ra_ptr]);
+ 	return ret;
+ }
+ 
+@@ -1012,7 +1012,7 @@ static struct buffer_head * ext4_dx_find_entry(struct dentry *dentry,
+ 				return bh;
+ 			}
+ 		}
+-		brelse (bh);
++		brelse(bh);
+ 		/* Check to see if we should continue to search */
+ 		retval = ext4_htree_next_block(dir, hash, frame,
+ 					       frames, NULL);
+@@ -1032,11 +1032,11 @@ static struct buffer_head * ext4_dx_find_entry(struct dentry *dentry,
+ 	return NULL;
+ }
+ 
+-static struct dentry *ext4_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
++static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+ {
+-	struct inode * inode;
+-	struct ext4_dir_entry_2 * de;
+-	struct buffer_head * bh;
++	struct inode *inode;
++	struct ext4_dir_entry_2 *de;
++	struct buffer_head *bh;
+ 
+ 	if (dentry->d_name.len > EXT4_NAME_LEN)
+ 		return ERR_PTR(-ENAMETOOLONG);
+@@ -1045,7 +1045,7 @@ static struct dentry *ext4_lookup(struct inode * dir, struct dentry *dentry, str
+ 	inode = NULL;
+ 	if (bh) {
+ 		unsigned long ino = le32_to_cpu(de->inode);
+-		brelse (bh);
++		brelse(bh);
+ 		if (!ext4_valid_inum(dir->i_sb, ino)) {
+ 			ext4_error(dir->i_sb, "ext4_lookup",
+ 				   "bad inode number: %lu", ino);
+@@ -1203,10 +1203,10 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
+ 
+ 	/* create map in the end of data2 block */
+ 	map = (struct dx_map_entry *) (data2 + blocksize);
+-	count = dx_make_map ((struct ext4_dir_entry_2 *) data1,
++	count = dx_make_map((struct ext4_dir_entry_2 *) data1,
+ 			     blocksize, hinfo, map);
+ 	map -= count;
+-	dx_sort_map (map, count);
++	dx_sort_map(map, count);
+ 	/* Split the existing block in the middle, size-wise */
+ 	size = 0;
+ 	move = 0;
+@@ -1227,7 +1227,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
+ 
+ 	/* Fancy dance to stay within two buffers */
+ 	de2 = dx_move_dirents(data1, data2, map + split, count - split);
+-	de = dx_pack_dirents(data1,blocksize);
++	de = dx_pack_dirents(data1, blocksize);
+ 	de->rec_len = ext4_rec_len_to_disk(data1 + blocksize - (char *) de);
+ 	de2->rec_len = ext4_rec_len_to_disk(data2 + blocksize - (char *) de2);
+ 	dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data1, blocksize, 1));
+@@ -1239,15 +1239,15 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
+ 		swap(*bh, bh2);
+ 		de = de2;
+ 	}
+-	dx_insert_block (frame, hash2 + continued, newblock);
+-	err = ext4_journal_dirty_metadata (handle, bh2);
++	dx_insert_block(frame, hash2 + continued, newblock);
++	err = ext4_journal_dirty_metadata(handle, bh2);
+ 	if (err)
+ 		goto journal_error;
+-	err = ext4_journal_dirty_metadata (handle, frame->bh);
++	err = ext4_journal_dirty_metadata(handle, frame->bh);
+ 	if (err)
+ 		goto journal_error;
+-	brelse (bh2);
+-	dxtrace(dx_show_index ("frame", frame->entries));
++	brelse(bh2);
++	dxtrace(dx_show_index("frame", frame->entries));
+ 	return de;
+ 
+ journal_error:
+@@ -1273,7 +1273,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
+  */
+ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
+ 			     struct inode *inode, struct ext4_dir_entry_2 *de,
+-			     struct buffer_head * bh)
++			     struct buffer_head *bh)
+ {
+ 	struct inode	*dir = dentry->d_parent->d_inode;
+ 	const char	*name = dentry->d_name.name;
+@@ -1290,11 +1290,11 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
+ 		while ((char *) de <= top) {
+ 			if (!ext4_check_dir_entry("ext4_add_entry", dir, de,
+ 						  bh, offset)) {
+-				brelse (bh);
++				brelse(bh);
+ 				return -EIO;
+ 			}
+-			if (ext4_match (namelen, name, de)) {
+-				brelse (bh);
++			if (ext4_match(namelen, name, de)) {
++				brelse(bh);
+ 				return -EEXIST;
+ 			}
+ 			nlen = EXT4_DIR_REC_LEN(de->name_len);
+@@ -1331,7 +1331,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
+ 	} else
+ 		de->inode = 0;
+ 	de->name_len = namelen;
+-	memcpy (de->name, name, namelen);
++	memcpy(de->name, name, namelen);
+ 	/*
+ 	 * XXX shouldn't update any times until successful
+ 	 * completion of syscall, but too many callers depend
+@@ -1388,7 +1388,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
+ 	}
+ 	root = (struct dx_root *) bh->b_data;
+ 
+-	bh2 = ext4_append (handle, dir, &block, &retval);
++	bh2 = ext4_append(handle, dir, &block, &retval);
+ 	if (!(bh2)) {
+ 		brelse(bh);
+ 		return retval;
+@@ -1414,9 +1414,9 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
+ 	root->info.info_length = sizeof(root->info);
+ 	root->info.hash_version = EXT4_SB(dir->i_sb)->s_def_hash_version;
+ 	entries = root->entries;
+-	dx_set_block (entries, 1);
+-	dx_set_count (entries, 1);
+-	dx_set_limit (entries, dx_root_limit(dir, sizeof(root->info)));
++	dx_set_block(entries, 1);
++	dx_set_count(entries, 1);
++	dx_set_limit(entries, dx_root_limit(dir, sizeof(root->info)));
+ 
+ 	/* Initialize as for dx_probe */
+ 	hinfo.hash_version = root->info.hash_version;
+@@ -1445,14 +1445,14 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
+  * may not sleep between calling this and putting something into
+  * the entry, as someone else might have used it while you slept.
+  */
+-static int ext4_add_entry (handle_t *handle, struct dentry *dentry,
+-	struct inode *inode)
++static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
++			  struct inode *inode)
+ {
+ 	struct inode *dir = dentry->d_parent->d_inode;
+ 	unsigned long offset;
+-	struct buffer_head * bh;
++	struct buffer_head *bh;
+ 	struct ext4_dir_entry_2 *de;
+-	struct super_block * sb;
++	struct super_block *sb;
+ 	int	retval;
+ 	int	dx_fallback=0;
+ 	unsigned blocksize;
+@@ -1502,9 +1502,9 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+ 	struct dx_frame frames[2], *frame;
+ 	struct dx_entry *entries, *at;
+ 	struct dx_hash_info hinfo;
+-	struct buffer_head * bh;
++	struct buffer_head *bh;
+ 	struct inode *dir = dentry->d_parent->d_inode;
+-	struct super_block * sb = dir->i_sb;
++	struct super_block *sb = dir->i_sb;
+ 	struct ext4_dir_entry_2 *de;
+ 	int err;
+ 
+@@ -1570,11 +1570,11 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+ 			if (err)
+ 				goto journal_error;
+ 
+-			memcpy ((char *) entries2, (char *) (entries + icount1),
+-				icount2 * sizeof(struct dx_entry));
+-			dx_set_count (entries, icount1);
+-			dx_set_count (entries2, icount2);
+-			dx_set_limit (entries2, dx_node_limit(dir));
++			memcpy((char *) entries2, (char *) (entries + icount1),
++			       icount2 * sizeof(struct dx_entry));
++			dx_set_count(entries, icount1);
++			dx_set_count(entries2, icount2);
++			dx_set_limit(entries2, dx_node_limit(dir));
+ 
+ 			/* Which index block gets the new entry? */
+ 			if (at - entries >= icount1) {
+@@ -1582,9 +1582,9 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+ 				frame->entries = entries = entries2;
+ 				swap(frame->bh, bh2);
+ 			}
+-			dx_insert_block (frames + 0, hash2, newblock);
+-			dxtrace(dx_show_index ("node", frames[1].entries));
+-			dxtrace(dx_show_index ("node",
++			dx_insert_block(frames + 0, hash2, newblock);
++			dxtrace(dx_show_index("node", frames[1].entries));
++			dxtrace(dx_show_index("node",
+ 			       ((struct dx_node *) bh2->b_data)->entries));
+ 			err = ext4_journal_dirty_metadata(handle, bh2);
+ 			if (err)
+@@ -1634,12 +1634,12 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+  * ext4_delete_entry deletes a directory entry by merging it with the
+  * previous entry
+  */
+-static int ext4_delete_entry (handle_t *handle,
+-			      struct inode * dir,
+-			      struct ext4_dir_entry_2 * de_del,
+-			      struct buffer_head * bh)
++static int ext4_delete_entry(handle_t *handle,
++			     struct inode *dir,
++			     struct ext4_dir_entry_2 *de_del,
++			     struct buffer_head *bh)
+ {
+-	struct ext4_dir_entry_2 * de, * pde;
++	struct ext4_dir_entry_2 *de, *pde;
+ 	int i;
+ 
+ 	i = 0;
+@@ -1720,11 +1720,11 @@ static int ext4_add_nondir(handle_t *handle,
+  * If the create succeeds, we fill in the inode information
+  * with d_instantiate().
+  */
+-static int ext4_create (struct inode * dir, struct dentry * dentry, int mode,
+-		struct nameidata *nd)
++static int ext4_create(struct inode *dir, struct dentry *dentry, int mode,
++		       struct nameidata *nd)
+ {
+ 	handle_t *handle;
+-	struct inode * inode;
++	struct inode *inode;
+ 	int err, retries = 0;
+ 
+ retry:
+@@ -1751,8 +1751,8 @@ static int ext4_create (struct inode * dir, struct dentry * dentry, int mode,
+ 	return err;
+ }
+ 
+-static int ext4_mknod (struct inode * dir, struct dentry *dentry,
+-			int mode, dev_t rdev)
++static int ext4_mknod(struct inode *dir, struct dentry *dentry,
++		      int mode, dev_t rdev)
+ {
+ 	handle_t *handle;
+ 	struct inode *inode;
+@@ -1771,7 +1771,7 @@ static int ext4_mknod (struct inode * dir, struct dentry *dentry,
+ 	if (IS_DIRSYNC(dir))
+ 		handle->h_sync = 1;
+ 
+-	inode = ext4_new_inode (handle, dir, mode);
++	inode = ext4_new_inode(handle, dir, mode);
+ 	err = PTR_ERR(inode);
+ 	if (!IS_ERR(inode)) {
+ 		init_special_inode(inode, inode->i_mode, rdev);
+@@ -1786,12 +1786,12 @@ static int ext4_mknod (struct inode * dir, struct dentry *dentry,
+ 	return err;
+ }
+ 
+-static int ext4_mkdir(struct inode * dir, struct dentry * dentry, int mode)
++static int ext4_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+ {
+ 	handle_t *handle;
+-	struct inode * inode;
+-	struct buffer_head * dir_block;
+-	struct ext4_dir_entry_2 * de;
++	struct inode *inode;
++	struct buffer_head *dir_block;
++	struct ext4_dir_entry_2 *de;
+ 	int err, retries = 0;
+ 
+ 	if (EXT4_DIR_LINK_MAX(dir))
+@@ -1807,7 +1807,7 @@ static int ext4_mkdir(struct inode * dir, struct dentry * dentry, int mode)
+ 	if (IS_DIRSYNC(dir))
+ 		handle->h_sync = 1;
+ 
+-	inode = ext4_new_inode (handle, dir, S_IFDIR | mode);
++	inode = ext4_new_inode(handle, dir, S_IFDIR | mode);
+ 	err = PTR_ERR(inode);
+ 	if (IS_ERR(inode))
+ 		goto out_stop;
+@@ -1815,7 +1815,7 @@ static int ext4_mkdir(struct inode * dir, struct dentry * dentry, int mode)
+ 	inode->i_op = &ext4_dir_inode_operations;
+ 	inode->i_fop = &ext4_dir_operations;
+ 	inode->i_size = EXT4_I(inode)->i_disksize = inode->i_sb->s_blocksize;
+-	dir_block = ext4_bread (handle, inode, 0, 1, &err);
++	dir_block = ext4_bread(handle, inode, 0, 1, &err);
+ 	if (!dir_block)
+ 		goto out_clear_inode;
+ 	BUFFER_TRACE(dir_block, "get_write_access");
+@@ -1824,26 +1824,26 @@ static int ext4_mkdir(struct inode * dir, struct dentry * dentry, int mode)
+ 	de->inode = cpu_to_le32(inode->i_ino);
+ 	de->name_len = 1;
+ 	de->rec_len = ext4_rec_len_to_disk(EXT4_DIR_REC_LEN(de->name_len));
+-	strcpy (de->name, ".");
++	strcpy(de->name, ".");
+ 	ext4_set_de_type(dir->i_sb, de, S_IFDIR);
+ 	de = ext4_next_entry(de);
+ 	de->inode = cpu_to_le32(dir->i_ino);
+ 	de->rec_len = ext4_rec_len_to_disk(inode->i_sb->s_blocksize -
+ 						EXT4_DIR_REC_LEN(1));
+ 	de->name_len = 2;
+-	strcpy (de->name, "..");
++	strcpy(de->name, "..");
+ 	ext4_set_de_type(dir->i_sb, de, S_IFDIR);
+ 	inode->i_nlink = 2;
+ 	BUFFER_TRACE(dir_block, "call ext4_journal_dirty_metadata");
+ 	ext4_journal_dirty_metadata(handle, dir_block);
+-	brelse (dir_block);
++	brelse(dir_block);
+ 	ext4_mark_inode_dirty(handle, inode);
+-	err = ext4_add_entry (handle, dentry, inode);
++	err = ext4_add_entry(handle, dentry, inode);
+ 	if (err) {
+ out_clear_inode:
+ 		clear_nlink(inode);
+ 		ext4_mark_inode_dirty(handle, inode);
+-		iput (inode);
++		iput(inode);
+ 		goto out_stop;
+ 	}
+ 	ext4_inc_count(handle, dir);
+@@ -1860,17 +1860,17 @@ static int ext4_mkdir(struct inode * dir, struct dentry * dentry, int mode)
+ /*
+  * routine to check that the specified directory is empty (for rmdir)
+  */
+-static int empty_dir (struct inode * inode)
++static int empty_dir(struct inode *inode)
+ {
+ 	unsigned long offset;
+-	struct buffer_head * bh;
+-	struct ext4_dir_entry_2 * de, * de1;
+-	struct super_block * sb;
++	struct buffer_head *bh;
++	struct ext4_dir_entry_2 *de, *de1;
++	struct super_block *sb;
+ 	int err = 0;
+ 
+ 	sb = inode->i_sb;
+ 	if (inode->i_size < EXT4_DIR_REC_LEN(1) + EXT4_DIR_REC_LEN(2) ||
+-	    !(bh = ext4_bread (NULL, inode, 0, 0, &err))) {
++	    !(bh = ext4_bread(NULL, inode, 0, 0, &err))) {
+ 		if (err)
+ 			ext4_error(inode->i_sb, __func__,
+ 				   "error %d reading directory #%lu offset 0",
+@@ -1885,23 +1885,23 @@ static int empty_dir (struct inode * inode)
+ 	de1 = ext4_next_entry(de);
+ 	if (le32_to_cpu(de->inode) != inode->i_ino ||
+ 			!le32_to_cpu(de1->inode) ||
+-			strcmp (".", de->name) ||
+-			strcmp ("..", de1->name)) {
+-		ext4_warning (inode->i_sb, "empty_dir",
+-			      "bad directory (dir #%lu) - no `.' or `..'",
+-			      inode->i_ino);
+-		brelse (bh);
++			strcmp(".", de->name) ||
++			strcmp("..", de1->name)) {
++		ext4_warning(inode->i_sb, "empty_dir",
++			     "bad directory (dir #%lu) - no `.' or `..'",
++			     inode->i_ino);
++		brelse(bh);
+ 		return 1;
+ 	}
+ 	offset = ext4_rec_len_from_disk(de->rec_len) +
+ 		 ext4_rec_len_from_disk(de1->rec_len);
+ 	de = ext4_next_entry(de1);
+-	while (offset < inode->i_size ) {
++	while (offset < inode->i_size) {
+ 		if (!bh ||
+ 			(void *) de >= (void *) (bh->b_data+sb->s_blocksize)) {
+ 			err = 0;
+-			brelse (bh);
+-			bh = ext4_bread (NULL, inode,
++			brelse(bh);
++			bh = ext4_bread(NULL, inode,
+ 				offset >> EXT4_BLOCK_SIZE_BITS(sb), 0, &err);
+ 			if (!bh) {
+ 				if (err)
+@@ -1921,13 +1921,13 @@ static int empty_dir (struct inode * inode)
+ 			continue;
+ 		}
+ 		if (le32_to_cpu(de->inode)) {
+-			brelse (bh);
++			brelse(bh);
+ 			return 0;
+ 		}
+ 		offset += ext4_rec_len_from_disk(de->rec_len);
+ 		de = ext4_next_entry(de);
+ 	}
+-	brelse (bh);
++	brelse(bh);
+ 	return 1;
+ }
+ 
+@@ -1958,8 +1958,8 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode)
+ 	 * ->i_nlink. For, say it, character device. Not a regular file,
+ 	 * not a directory, not a symlink and ->i_nlink > 0.
+ 	 */
+-	J_ASSERT ((S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+-		S_ISLNK(inode->i_mode)) || inode->i_nlink == 0);
++	J_ASSERT((S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
++		  S_ISLNK(inode->i_mode)) || inode->i_nlink == 0);
+ 
+ 	BUFFER_TRACE(EXT4_SB(sb)->s_sbh, "get_write_access");
+ 	err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh);
+@@ -2073,12 +2073,12 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode)
+ 	goto out_err;
+ }
+ 
+-static int ext4_rmdir (struct inode * dir, struct dentry *dentry)
++static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
+ {
+ 	int retval;
+-	struct inode * inode;
+-	struct buffer_head * bh;
+-	struct ext4_dir_entry_2 * de;
++	struct inode *inode;
++	struct buffer_head *bh;
++	struct ext4_dir_entry_2 *de;
+ 	handle_t *handle;
+ 
+ 	/* Initialize quotas before so that eventual writes go in
+@@ -2089,7 +2089,7 @@ static int ext4_rmdir (struct inode * dir, struct dentry *dentry)
+ 		return PTR_ERR(handle);
+ 
+ 	retval = -ENOENT;
+-	bh = ext4_find_entry (dentry, &de);
++	bh = ext4_find_entry(dentry, &de);
+ 	if (!bh)
+ 		goto end_rmdir;
+ 
+@@ -2103,16 +2103,16 @@ static int ext4_rmdir (struct inode * dir, struct dentry *dentry)
+ 		goto end_rmdir;
+ 
+ 	retval = -ENOTEMPTY;
+-	if (!empty_dir (inode))
++	if (!empty_dir(inode))
+ 		goto end_rmdir;
+ 
+ 	retval = ext4_delete_entry(handle, dir, de, bh);
+ 	if (retval)
+ 		goto end_rmdir;
+ 	if (!EXT4_DIR_LINK_EMPTY(inode))
+-		ext4_warning (inode->i_sb, "ext4_rmdir",
+-			      "empty directory has too many links (%d)",
+-			      inode->i_nlink);
++		ext4_warning(inode->i_sb, "ext4_rmdir",
++			     "empty directory has too many links (%d)",
++			     inode->i_nlink);
+ 	inode->i_version++;
+ 	clear_nlink(inode);
+ 	/* There's no need to set i_disksize: the fact that i_nlink is
+@@ -2128,16 +2128,16 @@ static int ext4_rmdir (struct inode * dir, struct dentry *dentry)
+ 
+ end_rmdir:
+ 	ext4_journal_stop(handle);
+-	brelse (bh);
++	brelse(bh);
+ 	return retval;
+ }
+ 
+-static int ext4_unlink(struct inode * dir, struct dentry *dentry)
++static int ext4_unlink(struct inode *dir, struct dentry *dentry)
+ {
+ 	int retval;
+-	struct inode * inode;
+-	struct buffer_head * bh;
+-	struct ext4_dir_entry_2 * de;
++	struct inode *inode;
++	struct buffer_head *bh;
++	struct ext4_dir_entry_2 *de;
+ 	handle_t *handle;
+ 
+ 	/* Initialize quotas before so that eventual writes go
+@@ -2151,7 +2151,7 @@ static int ext4_unlink(struct inode * dir, struct dentry *dentry)
+ 		handle->h_sync = 1;
+ 
+ 	retval = -ENOENT;
+-	bh = ext4_find_entry (dentry, &de);
++	bh = ext4_find_entry(dentry, &de);
+ 	if (!bh)
+ 		goto end_unlink;
+ 
+@@ -2162,9 +2162,9 @@ static int ext4_unlink(struct inode * dir, struct dentry *dentry)
+ 		goto end_unlink;
+ 
+ 	if (!inode->i_nlink) {
+-		ext4_warning (inode->i_sb, "ext4_unlink",
+-			      "Deleting nonexistent file (%lu), %d",
+-			      inode->i_ino, inode->i_nlink);
++		ext4_warning(inode->i_sb, "ext4_unlink",
++			     "Deleting nonexistent file (%lu), %d",
++			     inode->i_ino, inode->i_nlink);
+ 		inode->i_nlink = 1;
+ 	}
+ 	retval = ext4_delete_entry(handle, dir, de, bh);
+@@ -2182,15 +2182,15 @@ static int ext4_unlink(struct inode * dir, struct dentry *dentry)
+ 
+ end_unlink:
+ 	ext4_journal_stop(handle);
+-	brelse (bh);
++	brelse(bh);
+ 	return retval;
+ }
+ 
+-static int ext4_symlink (struct inode * dir,
+-		struct dentry *dentry, const char * symname)
++static int ext4_symlink(struct inode *dir,
++			struct dentry *dentry, const char *symname)
+ {
+ 	handle_t *handle;
+-	struct inode * inode;
++	struct inode *inode;
+ 	int l, err, retries = 0;
+ 
+ 	l = strlen(symname)+1;
+@@ -2207,12 +2207,12 @@ static int ext4_symlink (struct inode * dir,
+ 	if (IS_DIRSYNC(dir))
+ 		handle->h_sync = 1;
+ 
+-	inode = ext4_new_inode (handle, dir, S_IFLNK|S_IRWXUGO);
++	inode = ext4_new_inode(handle, dir, S_IFLNK|S_IRWXUGO);
+ 	err = PTR_ERR(inode);
+ 	if (IS_ERR(inode))
+ 		goto out_stop;
+ 
+-	if (l > sizeof (EXT4_I(inode)->i_data)) {
++	if (l > sizeof(EXT4_I(inode)->i_data)) {
+ 		inode->i_op = &ext4_symlink_inode_operations;
+ 		ext4_set_aops(inode);
+ 		/*
+@@ -2225,14 +2225,14 @@ static int ext4_symlink (struct inode * dir,
+ 		if (err) {
+ 			clear_nlink(inode);
+ 			ext4_mark_inode_dirty(handle, inode);
+-			iput (inode);
++			iput(inode);
+ 			goto out_stop;
+ 		}
+ 	} else {
+ 		/* clear the extent format for fast symlink */
+ 		EXT4_I(inode)->i_flags &= ~EXT4_EXTENTS_FL;
+ 		inode->i_op = &ext4_fast_symlink_inode_operations;
+-		memcpy((char*)&EXT4_I(inode)->i_data,symname,l);
++		memcpy((char *)&EXT4_I(inode)->i_data, symname, l);
+ 		inode->i_size = l-1;
+ 	}
+ 	EXT4_I(inode)->i_disksize = inode->i_size;
+@@ -2244,8 +2244,8 @@ static int ext4_symlink (struct inode * dir,
+ 	return err;
+ }
+ 
+-static int ext4_link (struct dentry * old_dentry,
+-		struct inode * dir, struct dentry *dentry)
++static int ext4_link(struct dentry *old_dentry,
++		     struct inode *dir, struct dentry *dentry)
+ {
+ 	handle_t *handle;
+ 	struct inode *inode = old_dentry->d_inode;
+@@ -2288,13 +2288,13 @@ static int ext4_link (struct dentry * old_dentry,
+  * Anybody can rename anything with this: the permission checks are left to the
+  * higher-level routines.
+  */
+-static int ext4_rename (struct inode * old_dir, struct dentry *old_dentry,
+-			   struct inode * new_dir,struct dentry *new_dentry)
++static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
++		       struct inode *new_dir, struct dentry *new_dentry)
+ {
+ 	handle_t *handle;
+-	struct inode * old_inode, * new_inode;
+-	struct buffer_head * old_bh, * new_bh, * dir_bh;
+-	struct ext4_dir_entry_2 * old_de, * new_de;
++	struct inode *old_inode, *new_inode;
++	struct buffer_head *old_bh, *new_bh, *dir_bh;
++	struct ext4_dir_entry_2 *old_de, *new_de;
+ 	int retval;
+ 
+ 	old_bh = new_bh = dir_bh = NULL;
+@@ -2312,7 +2312,7 @@ static int ext4_rename (struct inode * old_dir, struct dentry *old_dentry,
+ 	if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir))
+ 		handle->h_sync = 1;
+ 
+-	old_bh = ext4_find_entry (old_dentry, &old_de);
++	old_bh = ext4_find_entry(old_dentry, &old_de);
+ 	/*
+ 	 *  Check for inode number is _not_ due to possible IO errors.
+ 	 *  We might rmdir the source, keep it as pwd of some process
+@@ -2325,32 +2325,32 @@ static int ext4_rename (struct inode * old_dir, struct dentry *old_dentry,
+ 		goto end_rename;
+ 
+ 	new_inode = new_dentry->d_inode;
+-	new_bh = ext4_find_entry (new_dentry, &new_de);
++	new_bh = ext4_find_entry(new_dentry, &new_de);
+ 	if (new_bh) {
+ 		if (!new_inode) {
+-			brelse (new_bh);
++			brelse(new_bh);
+ 			new_bh = NULL;
+ 		}
+ 	}
+ 	if (S_ISDIR(old_inode->i_mode)) {
+ 		if (new_inode) {
+ 			retval = -ENOTEMPTY;
+-			if (!empty_dir (new_inode))
++			if (!empty_dir(new_inode))
+ 				goto end_rename;
+ 		}
+ 		retval = -EIO;
+-		dir_bh = ext4_bread (handle, old_inode, 0, 0, &retval);
++		dir_bh = ext4_bread(handle, old_inode, 0, 0, &retval);
+ 		if (!dir_bh)
+ 			goto end_rename;
+ 		if (le32_to_cpu(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino)
+ 			goto end_rename;
+ 		retval = -EMLINK;
+-		if (!new_inode && new_dir!=old_dir &&
++		if (!new_inode && new_dir != old_dir &&
+ 				new_dir->i_nlink >= EXT4_LINK_MAX)
+ 			goto end_rename;
+ 	}
+ 	if (!new_bh) {
+-		retval = ext4_add_entry (handle, new_dentry, old_inode);
++		retval = ext4_add_entry(handle, new_dentry, old_inode);
+ 		if (retval)
+ 			goto end_rename;
+ 	} else {
+@@ -2437,9 +2437,9 @@ static int ext4_rename (struct inode * old_dir, struct dentry *old_dentry,
+ 	retval = 0;
+ 
+ end_rename:
+-	brelse (dir_bh);
+-	brelse (old_bh);
+-	brelse (new_bh);
++	brelse(dir_bh);
++	brelse(old_bh);
++	brelse(new_bh);
+ 	ext4_journal_stop(handle);
+ 	return retval;
+ }
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index b3d35604ea18..4392e3fd0f0f 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -416,8 +416,8 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ 		       "EXT4-fs: ext4_add_new_gdb: adding group block %lu\n",
+ 		       gdb_num);
+ 
+-        /*
+-         * If we are not using the primary superblock/GDT copy don't resize,
++	/*
++	 * If we are not using the primary superblock/GDT copy don't resize,
+          * because the user tools have no way of handling this.  Probably a
+          * bad time to do it anyways.
+          */
+@@ -964,7 +964,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
+ 	ext4_group_t o_groups_count;
+ 	ext4_grpblk_t last;
+ 	ext4_grpblk_t add;
+-	struct buffer_head * bh;
++	struct buffer_head *bh;
+ 	handle_t *handle;
+ 	int err;
+ 	unsigned long freed_blocks;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index c10aaf7d83c3..7de6ca0c9e9b 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -654,7 +654,7 @@ static inline void ext4_show_quota_options(struct seq_file *seq,
+ 
+ 	if (sbi->s_jquota_fmt)
+ 		seq_printf(seq, ",jqfmt=%s",
+-		(sbi->s_jquota_fmt == QFMT_VFS_OLD) ? "vfsold": "vfsv0");
++		(sbi->s_jquota_fmt == QFMT_VFS_OLD) ? "vfsold" : "vfsv0");
+ 
+ 	if (sbi->s_qf_names[USRQUOTA])
+ 		seq_printf(seq, ",usrjquota=%s", sbi->s_qf_names[USRQUOTA]);
+@@ -822,7 +822,7 @@ static struct dentry *ext4_fh_to_parent(struct super_block *sb, struct fid *fid,
+ }
+ 
+ #ifdef CONFIG_QUOTA
+-#define QTYPE2NAME(t) ((t) == USRQUOTA?"user":"group")
++#define QTYPE2NAME(t) ((t) == USRQUOTA ? "user" : "group")
+ #define QTYPE2MOPT(on, t) ((t) == USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA))
+ 
+ static int ext4_dquot_initialize(struct inode *inode, int type);
+@@ -1586,7 +1586,7 @@ static int ext4_check_descriptors(struct super_block *sb)
+ 	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG))
+ 		flexbg_flag = 1;
+ 
+-	ext4_debug ("Checking group descriptors");
++	ext4_debug("Checking group descriptors");
+ 
+ 	for (i = 0; i < sbi->s_groups_count; i++) {
+ 		struct ext4_group_desc *gdp = ext4_get_group_desc(sb, i, NULL);
+diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
+index e9178643dc01..0013d52f73bb 100644
+--- a/fs/ext4/symlink.c
++++ b/fs/ext4/symlink.c
+@@ -23,10 +23,10 @@
+ #include "ext4.h"
+ #include "xattr.h"
+ 
+-static void * ext4_follow_link(struct dentry *dentry, struct nameidata *nd)
++static void *ext4_follow_link(struct dentry *dentry, struct nameidata *nd)
+ {
+ 	struct ext4_inode_info *ei = EXT4_I(dentry->d_inode);
+-	nd_set_link(nd, (char*)ei->i_data);
++	nd_set_link(nd, (char *) ei->i_data);
+ 	return NULL;
+ }
+ 
+diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
+index 5992fe979bb9..814ea58d4d57 100644
+--- a/fs/ext4/xattr.h
++++ b/fs/ext4/xattr.h
+@@ -51,8 +51,8 @@ struct ext4_xattr_entry {
+ 	(((name_len) + EXT4_XATTR_ROUND + \
+ 	sizeof(struct ext4_xattr_entry)) & ~EXT4_XATTR_ROUND)
+ #define EXT4_XATTR_NEXT(entry) \
+-	( (struct ext4_xattr_entry *)( \
+-	  (char *)(entry) + EXT4_XATTR_LEN((entry)->e_name_len)) )
++	((struct ext4_xattr_entry *)( \
++	 (char *)(entry) + EXT4_XATTR_LEN((entry)->e_name_len)))
+ #define EXT4_XATTR_SIZE(size) \
+ 	(((size) + EXT4_XATTR_ROUND) & ~EXT4_XATTR_ROUND)
+ 

commit e5f8eab8851dff162e7ade46f084cb8575dc45f7
+Author: Theodore Ts'o 
+Date:   Mon Sep 8 22:25:04 2008 -0400
+
+    ext4: Fix long long checkpatch warnings
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index ee8695464957..c10aaf7d83c3 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1716,9 +1716,9 @@ static void ext4_orphan_cleanup(struct super_block *sb,
+ 		DQUOT_INIT(inode);
+ 		if (inode->i_nlink) {
+ 			printk(KERN_DEBUG
+-				"%s: truncating inode %lu to %Ld bytes\n",
++				"%s: truncating inode %lu to %lld bytes\n",
+ 				__func__, inode->i_ino, inode->i_size);
+-			jbd_debug(2, "truncating inode %lu to %Ld bytes\n",
++			jbd_debug(2, "truncating inode %lu to %lld bytes\n",
+ 				  inode->i_ino, inode->i_size);
+ 			ext4_truncate(inode);
+ 			nr_truncates++;
+@@ -2554,7 +2554,7 @@ static journal_t *ext4_get_journal(struct super_block *sb,
+ 		return NULL;
+ 	}
+ 
+-	jbd_debug(2, "Journal inode found at %p: %Ld bytes\n",
++	jbd_debug(2, "Journal inode found at %p: %lld bytes\n",
+ 		  journal_inode, journal_inode->i_size);
+ 	if (!S_ISREG(journal_inode->i_mode)) {
+ 		printk(KERN_ERR "EXT4-fs: invalid journal inode.\n");
+@@ -3439,7 +3439,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
+ 	handle_t *handle = journal_current_handle();
+ 
+ 	if (!handle) {
+-		printk(KERN_WARNING "EXT4-fs: Quota write (off=%Lu, len=%Lu)"
++		printk(KERN_WARNING "EXT4-fs: Quota write (off=%llu, len=%llu)"
+ 			" cancelled because transaction is not started.\n",
+ 			(unsigned long long)off, (unsigned long long)len);
+ 		return -EIO;

commit 4776004f54e4190e104caf620fd0fa5909412236
+Author: Theodore Ts'o 
+Date:   Mon Sep 8 23:00:52 2008 -0400
+
+    ext4: Add printk priority levels to clean up checkpatch warnings
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index 00a94d5866c2..7aac2025ba9c 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -379,26 +379,28 @@ static void __rsv_window_dump(struct rb_root *root, int verbose,
+ 	bad = 0;
+ 	prev = NULL;
+ 
+-	printk("Block Allocation Reservation Windows Map (%s):\n", fn);
++	printk(KERN_DEBUG "Block Allocation Reservation "
++	       "Windows Map (%s):\n", fn);
+ 	while (n) {
+ 		rsv = rb_entry(n, struct ext4_reserve_window_node, rsv_node);
+ 		if (verbose)
+-			printk("reservation window 0x%p "
++			printk(KERN_DEBUG "reservation window 0x%p "
+ 			       "start:  %llu, end:  %llu\n",
+ 			       rsv, rsv->rsv_start, rsv->rsv_end);
+ 		if (rsv->rsv_start && rsv->rsv_start >= rsv->rsv_end) {
+-			printk("Bad reservation %p (start >= end)\n",
++			printk(KERN_DEBUG "Bad reservation %p (start >= end)\n",
+ 			       rsv);
+ 			bad = 1;
+ 		}
+ 		if (prev && prev->rsv_end >= rsv->rsv_start) {
+-			printk("Bad reservation %p (prev->end >= start)\n",
+-			       rsv);
++			printk(KERN_DEBUG "Bad reservation %p "
++			       "(prev->end >= start)\n", rsv);
+ 			bad = 1;
+ 		}
+ 		if (bad) {
+ 			if (!verbose) {
+-				printk("Restarting reservation walk in verbose mode\n");
++				printk(KERN_DEBUG "Restarting reservation "
++				       "walk in verbose mode\n");
+ 				verbose = 1;
+ 				goto restart;
+ 			}
+@@ -406,7 +408,7 @@ static void __rsv_window_dump(struct rb_root *root, int verbose,
+ 		n = rb_next(n);
+ 		prev = rsv;
+ 	}
+-	printk("Window map complete.\n");
++	printk(KERN_DEBUG "Window map complete.\n");
+ 	BUG_ON(bad);
+ }
+ #define rsv_window_dump(root, verbose) \
+@@ -1702,7 +1704,7 @@ ext4_fsblk_t ext4_old_new_blocks(handle_t *handle, struct inode *inode,
+ 	sb = inode->i_sb;
+ 	if (!sb) {
+ 		*errp = -ENODEV;
+-		printk("ext4_new_block: nonexistent device");
++		printk(KERN_ERR "ext4_new_block: nonexistent superblock");
+ 		return 0;
+ 	}
+ 
+@@ -1884,8 +1886,8 @@ ext4_fsblk_t ext4_old_new_blocks(handle_t *handle, struct inode *inode,
+ 		for (i = 0; i < num; i++) {
+ 			if (ext4_test_bit(grp_alloc_blk+i,
+ 					bh2jh(bitmap_bh)->b_committed_data)) {
+-				printk("%s: block was unexpectedly set in "
+-					"b_committed_data\n", __func__);
++				printk(KERN_ERR "%s: block was unexpectedly "
++				       "set in b_committed_data\n", __func__);
+ 			}
+ 		}
+ 	}
+@@ -2093,10 +2095,9 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
+ 		bitmap_count += x;
+ 	}
+ 	brelse(bitmap_bh);
+-	printk("ext4_count_free_blocks: stored = %llu"
+-		", computed = %llu, %llu\n",
+-		ext4_free_blocks_count(es),
+-		desc_count, bitmap_count);
++	printk(KERN_DEBUG "ext4_count_free_blocks: stored = %llu"
++		", computed = %llu, %llu\n", ext4_free_blocks_count(es),
++	       desc_count, bitmap_count);
+ 	return bitmap_count;
+ #else
+ 	desc_count = 0;
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index ec8e33b45219..ac873dbf0dd0 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -400,7 +400,8 @@ static int call_filldir(struct file * filp, void * dirent,
+ 	sb = inode->i_sb;
+ 
+ 	if (!fname) {
+-		printk("call_filldir: called with null fname?!?\n");
++		printk(KERN_ERR "ext4: call_filldir: called with "
++		       "null fname?!?\n");
+ 		return 0;
+ 	}
+ 	curr_pos = hash2pos(fname->hash, fname->minor_hash);
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index b24d3c53f20c..a8db7fdf9cb7 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -440,9 +440,10 @@ ext4_ext_binsearch_idx(struct inode *inode,
+ 		for (k = 0; k < le16_to_cpu(eh->eh_entries); k++, ix++) {
+ 		  if (k != 0 &&
+ 		      le32_to_cpu(ix->ei_block) <= le32_to_cpu(ix[-1].ei_block)) {
+-				printk("k=%d, ix=0x%p, first=0x%p\n", k,
+-					ix, EXT_FIRST_INDEX(eh));
+-				printk("%u <= %u\n",
++				printk(KERN_DEBUG "k=%d, ix=0x%p, "
++				       "first=0x%p\n", k,
++				       ix, EXT_FIRST_INDEX(eh));
++				printk(KERN_DEBUG "%u <= %u\n",
+ 				       le32_to_cpu(ix->ei_block),
+ 				       le32_to_cpu(ix[-1].ei_block));
+ 			}
+@@ -2142,7 +2143,7 @@ void ext4_ext_init(struct super_block *sb)
+ 	 */
+ 
+ 	if (test_opt(sb, EXTENTS)) {
+-		printk("EXT4-fs: file extents enabled");
++		printk(KERN_INFO "EXT4-fs: file extents enabled");
+ #ifdef AGGRESSIVE_TEST
+ 		printk(", aggressive tests");
+ #endif
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index f344834bbf58..45c66a03f182 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -170,17 +170,18 @@ void ext4_free_inode (handle_t *handle, struct inode * inode)
+ 	ext4_group_t flex_group;
+ 
+ 	if (atomic_read(&inode->i_count) > 1) {
+-		printk ("ext4_free_inode: inode has count=%d\n",
+-					atomic_read(&inode->i_count));
++		printk(KERN_ERR "ext4_free_inode: inode has count=%d\n",
++		       atomic_read(&inode->i_count));
+ 		return;
+ 	}
+ 	if (inode->i_nlink) {
+-		printk ("ext4_free_inode: inode has nlink=%d\n",
+-			inode->i_nlink);
++		printk(KERN_ERR "ext4_free_inode: inode has nlink=%d\n",
++		       inode->i_nlink);
+ 		return;
+ 	}
+ 	if (!sb) {
+-		printk("ext4_free_inode: inode on nonexistent device\n");
++		printk(KERN_ERR "ext4_free_inode: inode on "
++		       "nonexistent device\n");
+ 		return;
+ 	}
+ 	sbi = EXT4_SB(sb);
+@@ -989,8 +990,9 @@ unsigned long ext4_count_free_inodes (struct super_block * sb)
+ 		bitmap_count += x;
+ 	}
+ 	brelse(bitmap_bh);
+-	printk("ext4_count_free_inodes: stored = %u, computed = %lu, %lu\n",
+-		le32_to_cpu(es->s_free_inodes_count), desc_count, bitmap_count);
++	printk(KERN_DEBUG "ext4_count_free_inodes: "
++	       "stored = %u, computed = %lu, %lu\n",
++	       le32_to_cpu(es->s_free_inodes_count), desc_count, bitmap_count);
+ 	return desc_count;
+ #else
+ 	desc_count = 0;
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index e0e3a5eb1ddb..0db2ccfa0dad 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -477,9 +477,10 @@ static void mb_cmp_bitmaps(struct ext4_buddy *e4b, void *bitmap)
+ 		b2 = (unsigned char *) bitmap;
+ 		for (i = 0; i < e4b->bd_sb->s_blocksize; i++) {
+ 			if (b1[i] != b2[i]) {
+-				printk("corruption in group %lu at byte %u(%u):"
+-				       " %x in copy != %x on disk/prealloc\n",
+-					e4b->bd_group, i, i * 8, b1[i], b2[i]);
++				printk(KERN_ERR "corruption in group %lu "
++				       "at byte %u(%u): %x in copy != %x "
++				       "on disk/prealloc\n",
++				       e4b->bd_group, i, i * 8, b1[i], b2[i]);
+ 				BUG();
+ 			}
+ 		}
+@@ -2560,7 +2561,7 @@ int ext4_mb_init(struct super_block *sb, int needs_recovery)
+ 	ext4_mb_init_per_dev_proc(sb);
+ 	ext4_mb_history_init(sb);
+ 
+-	printk("EXT4-fs: mballoc enabled\n");
++	printk(KERN_INFO "EXT4-fs: mballoc enabled\n");
+ 	return 0;
+ }
+ 
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 387ad98350c3..978b57f8630d 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -254,12 +254,12 @@ static inline unsigned dx_node_limit (struct inode *dir)
+  * Debug
+  */
+ #ifdef DX_DEBUG
+-static void dx_show_index (char * label, struct dx_entry *entries)
++static void dx_show_index(char * label, struct dx_entry *entries)
+ {
+ 	int i, n = dx_get_count (entries);
+-	printk("%s index ", label);
++	printk(KERN_DEBUG "%s index ", label);
+ 	for (i = 0; i < n; i++) {
+-		printk("%x->%lu ", i? dx_get_hash(entries + i) :
++		printk("%x->%lu ", i ? dx_get_hash(entries + i) :
+ 				0, (unsigned long)dx_get_block(entries + i));
+ 	}
+ 	printk("\n");
+@@ -328,8 +328,9 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir,
+ 		brelse (bh);
+ 	}
+ 	if (bcount)
+-		printk("%snames %u, fullness %u (%u%%)\n", levels?"":"   ",
+-			names, space/bcount,(space/bcount)*100/blocksize);
++		printk(KERN_DEBUG "%snames %u, fullness %u (%u%%)\n", 
++		       levels ? "" : "   ", names, space/bcount,
++		       (space/bcount)*100/blocksize);
+ 	return (struct stats) { names, space, bcount};
+ }
+ #endif /* DX_DEBUG */
+@@ -635,8 +636,8 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
+ 	int ret, err;
+ 	__u32 hashval;
+ 
+-	dxtrace(printk("In htree_fill_tree, start hash: %x:%x\n", start_hash,
+-		       start_minor_hash));
++	dxtrace(printk(KERN_DEBUG "In htree_fill_tree, start hash: %x:%x\n", 
++		       start_hash, start_minor_hash));
+ 	dir = dir_file->f_path.dentry->d_inode;
+ 	if (!(EXT4_I(dir)->i_flags & EXT4_INDEX_FL)) {
+ 		hinfo.hash_version = EXT4_SB(dir->i_sb)->s_def_hash_version;
+@@ -694,8 +695,8 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
+ 			break;
+ 	}
+ 	dx_release(frames);
+-	dxtrace(printk("Fill tree: returned %d entries, next hash: %x\n",
+-		       count, *next_hash));
++	dxtrace(printk(KERN_DEBUG "Fill tree: returned %d entries, "
++		       "next hash: %x\n", count, *next_hash));
+ 	return count;
+ errout:
+ 	dx_release(frames);
+@@ -882,7 +883,8 @@ static struct buffer_head * ext4_find_entry (struct dentry *dentry,
+ 		 */
+ 		if (bh || (err != ERR_BAD_DX_DIR))
+ 			return bh;
+-		dxtrace(printk("ext4_find_entry: dx failed, falling back\n"));
++		dxtrace(printk(KERN_DEBUG "ext4_find_entry: dx failed, "
++			       "falling back\n"));
+ 	}
+ 	nblocks = dir->i_size >> EXT4_BLOCK_SIZE_BITS(sb);
+ 	start = EXT4_I(dir)->i_dir_start_lookup;
+@@ -1025,7 +1027,7 @@ static struct buffer_head * ext4_dx_find_entry(struct dentry *dentry,
+ 
+ 	*err = -ENOENT;
+ errout:
+-	dxtrace(printk("%s not found\n", name));
++	dxtrace(printk(KERN_DEBUG "%s not found\n", name));
+ 	dx_release (frames);
+ 	return NULL;
+ }
+@@ -1377,7 +1379,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
+ 	struct fake_dirent *fde;
+ 
+ 	blocksize =  dir->i_sb->s_blocksize;
+-	dxtrace(printk("Creating index\n"));
++	dxtrace(printk(KERN_DEBUG "Creating index\n"));
+ 	retval = ext4_journal_get_write_access(handle, bh);
+ 	if (retval) {
+ 		ext4_std_error(dir->i_sb, retval);
+@@ -1527,7 +1529,7 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+ 	}
+ 
+ 	/* Block full, should compress but for now just split */
+-	dxtrace(printk("using %u of %u node entries\n",
++	dxtrace(printk(KERN_DEBUG "using %u of %u node entries\n",
+ 		       dx_get_count(entries), dx_get_limit(entries)));
+ 	/* Need to split index? */
+ 	if (dx_get_count(entries) == dx_get_limit(entries)) {
+@@ -1559,7 +1561,8 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+ 		if (levels) {
+ 			unsigned icount1 = icount/2, icount2 = icount - icount1;
+ 			unsigned hash2 = dx_get_hash(entries + icount1);
+-			dxtrace(printk("Split index %i/%i\n", icount1, icount2));
++			dxtrace(printk(KERN_DEBUG "Split index %i/%i\n",
++				       icount1, icount2));
+ 
+ 			BUFFER_TRACE(frame->bh, "get_write_access"); /* index root */
+ 			err = ext4_journal_get_write_access(handle,
+@@ -1588,7 +1591,8 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
+ 				goto journal_error;
+ 			brelse (bh2);
+ 		} else {
+-			dxtrace(printk("Creating second level index...\n"));
++			dxtrace(printk(KERN_DEBUG
++				       "Creating second level index...\n"));
+ 			memcpy((char *) entries2, (char *) entries,
+ 			       icount * sizeof(struct dx_entry));
+ 			dx_set_limit(entries2, dx_node_limit(dir));
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 566344b926b7..ee8695464957 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -981,7 +981,7 @@ static ext4_fsblk_t get_sb_block(void **data)
+ 	/*todo: use simple_strtoll with >32bit ext4 */
+ 	sb_block = simple_strtoul(options, &options, 0);
+ 	if (*options && *options != ',') {
+-		printk("EXT4-fs: Invalid sb specification: %s\n",
++		printk(KERN_ERR "EXT4-fs: Invalid sb specification: %s\n",
+ 		       (char *) *data);
+ 		return 1;
+ 	}
+@@ -1082,7 +1082,8 @@ static int parse_options(char *options, struct super_block *sb,
+ #else
+ 		case Opt_user_xattr:
+ 		case Opt_nouser_xattr:
+-			printk("EXT4 (no)user_xattr options not supported\n");
++			printk(KERN_ERR "EXT4 (no)user_xattr options "
++			       "not supported\n");
+ 			break;
+ #endif
+ #ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
+@@ -1095,7 +1096,8 @@ static int parse_options(char *options, struct super_block *sb,
+ #else
+ 		case Opt_acl:
+ 		case Opt_noacl:
+-			printk("EXT4 (no)acl options not supported\n");
++			printk(KERN_ERR "EXT4 (no)acl options "
++			       "not supported\n");
+ 			break;
+ #endif
+ 		case Opt_reservation:
+@@ -1189,8 +1191,8 @@ static int parse_options(char *options, struct super_block *sb,
+ 			     sb_any_quota_suspended(sb)) &&
+ 			    !sbi->s_qf_names[qtype]) {
+ 				printk(KERN_ERR
+-					"EXT4-fs: Cannot change journaled "
+-					"quota options when quota turned on.\n");
++				       "EXT4-fs: Cannot change journaled "
++				       "quota options when quota turned on.\n");
+ 				return 0;
+ 			}
+ 			qname = match_strdup(&args[0]);
+@@ -1473,14 +1475,14 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
+ 			EXT4_INODES_PER_GROUP(sb),
+ 			sbi->s_mount_opt);
+ 
+-	printk(KERN_INFO "EXT4 FS on %s, ", sb->s_id);
+ 	if (EXT4_SB(sb)->s_journal->j_inode == NULL) {
+ 		char b[BDEVNAME_SIZE];
+ 
+-		printk("external journal on %s\n",
+-			bdevname(EXT4_SB(sb)->s_journal->j_dev, b));
++		printk(KERN_INFO "EXT4 FS on %s, external journal on %s\n",
++		       sb->s_id, bdevname(EXT4_SB(sb)->s_journal->j_dev, b));
+ 	} else {
+-		printk("internal journal\n");
++		printk(KERN_INFO "EXT4 FS on %s, internal journal\n",
++		       sb->s_id);
+ 	}
+ 	return res;
+ }
+@@ -2715,6 +2717,11 @@ static int ext4_load_journal(struct super_block *sb,
+ 			return -EINVAL;
+ 	}
+ 
++	if (journal->j_flags & JBD2_BARRIER)
++		printk(KERN_INFO "EXT4-fs: barriers enabled\n");
++	else
++		printk(KERN_INFO "EXT4-fs: barriers disabled\n");
++
+ 	if (!really_read_only && test_opt(sb, UPDATE_JOURNAL)) {
+ 		err = jbd2_journal_update_format(journal);
+ 		if (err)  {

commit 4537398d91e6e03811ba971d959b762137058c1a
+Author: Theodore Ts'o 
+Date:   Sun Jul 27 19:59:21 2008 -0400
+
+    ext4: Update documentation to remind users to update mke2fs.conf
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
+index 80e193d82e2e..0d5394920a31 100644
+--- a/Documentation/filesystems/ext4.txt
++++ b/Documentation/filesystems/ext4.txt
+@@ -26,6 +26,12 @@ Mailing list: linux-ext4@vger.kernel.org
+ 
+     git://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git
+ 
++  - Note that it is highly important to install the mke2fs.conf file
++    that comes with the e2fsprogs 1.41.x sources in /etc/mke2fs.conf. If
++    you have edited the /etc/mke2fs.conf file installed on your system,
++    you will need to merge your changes with the version from e2fsprogs
++    1.41.x.
++
+   - Create a new filesystem using the ext4dev filesystem type:
+ 
+     	# mke2fs -t ext4dev /dev/hda1

commit 88aa3cff4e9a38b953de9fbc54c96e619a2bb9f9
+Author: Theodore Ts'o 
+Date:   Sat Aug 16 07:57:35 2008 -0400
+
+    ext4: Use ext4_discard_reservations instead of mballoc-specific call
+    
+    In ext4_ext_truncate(), we should use the more generic
+    ext4_discard_reservations() call so we do the right thing when the
+    filesystem is mounted with the nomballoc option.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Reviewed-by: Mingming Cao 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 612c3d2c3824..7212947a8ca3 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -2819,7 +2819,7 @@ void ext4_ext_truncate(struct inode *inode)
+ 	down_write(&EXT4_I(inode)->i_data_sem);
+ 	ext4_ext_invalidate_cache(inode);
+ 
+-	ext4_mb_discard_inode_preallocations(inode);
++	ext4_discard_reservation(inode);
+ 
+ 	/*
+ 	 * TODO: optimization is possible here.

commit d015641734cde55d2fce48a6db3983c8a029fe05
+Author: Theodore Ts'o 
+Date:   Tue Aug 19 21:57:43 2008 -0400
+
+    ext4: Fix ext4_dx_readdir hash collision handling
+    
+    This fixes a bug where readdir() would return a directory entry twice
+    if there was a hash collision in an hash tree indexed directory.
+    
+    Signed-off-by: Eugene Dashevsky 
+    Signed-off-by: Mike Snitzer 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index d3d23d73c08b..ec8e33b45219 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -411,7 +411,7 @@ static int call_filldir(struct file * filp, void * dirent,
+ 				get_dtype(sb, fname->file_type));
+ 		if (error) {
+ 			filp->f_pos = curr_pos;
+-			info->extra_fname = fname->next;
++			info->extra_fname = fname;
+ 			return error;
+ 		}
+ 		fname = fname->next;
+@@ -450,11 +450,21 @@ static int ext4_dx_readdir(struct file * filp,
+ 	 * If there are any leftover names on the hash collision
+ 	 * chain, return them first.
+ 	 */
+-	if (info->extra_fname &&
+-	    call_filldir(filp, dirent, filldir, info->extra_fname))
+-		goto finished;
++	if (info->extra_fname) {
++		if (call_filldir(filp, dirent, filldir, info->extra_fname))
++			goto finished;
+ 
+-	if (!info->curr_node)
++		info->extra_fname = NULL;
++		info->curr_node = rb_next(info->curr_node);
++		if (!info->curr_node) {
++			if (info->next_hash == ~0) {
++				filp->f_pos = EXT4_HTREE_EOF;
++				goto finished;
++			}
++			info->curr_hash = info->next_hash;
++			info->curr_minor_hash = 0;
++		}
++	} else if (!info->curr_node)
+ 		info->curr_node = rb_first(&info->root);
+ 
+ 	while (1) {

commit b4df2030858bde986cb6ff2e4b45945f84649e32
+Author: Theodore Ts'o 
+Date:   Wed Aug 13 21:44:34 2008 -0400
+
+    ext4: Fix potential truncate BUG due to i_prealloc_list being non-empty
+    
+    We need to call ext4_discard_reservation() earlier in ext4_truncate(),
+    to avoid a BUG() in ext4_mb_return_to_preallocation(), which is called
+    (ultimately) by ext4_free_blocks().  So we must ditch the blocks on
+    i_prealloc_list before we start freeing the data blocks.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index a1c7d7623213..2d54c822c4c3 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -3494,6 +3494,9 @@ void ext4_truncate(struct inode *inode)
+ 	 * modify the block allocation tree.
+ 	 */
+ 	down_write(&ei->i_data_sem);
++
++	ext4_discard_reservation(inode);
++
+ 	/*
+ 	 * The orphan list entry will now protect us from any crash which
+ 	 * occurs before the truncate completes, so it is now safe to propagate
+@@ -3563,8 +3566,6 @@ void ext4_truncate(struct inode *inode)
+ 		;
+ 	}
+ 
+-	ext4_discard_reservation(inode);
+-
+ 	up_write(&ei->i_data_sem);
+ 	inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
+ 	ext4_mark_inode_dirty(handle, inode);

commit 00b32b7fb671e797bdd2736524a497f18a8df7bf
+Author: Theodore Ts'o 
+Date:   Sat Jul 26 17:33:53 2008 -0400
+
+    ext4: unexport jbd2_journal_update_superblock
+    
+    Remove the unused EXPORT_SYMBOL(jbd2_journal_update_superblock).
+    
+    Signed-off-by: Adrian Bunk 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index b26c6d9fe6ae..8207a01c4edb 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -68,7 +68,6 @@ EXPORT_SYMBOL(jbd2_journal_set_features);
+ EXPORT_SYMBOL(jbd2_journal_create);
+ EXPORT_SYMBOL(jbd2_journal_load);
+ EXPORT_SYMBOL(jbd2_journal_destroy);
+-EXPORT_SYMBOL(jbd2_journal_update_superblock);
+ EXPORT_SYMBOL(jbd2_journal_abort);
+ EXPORT_SYMBOL(jbd2_journal_errno);
+ EXPORT_SYMBOL(jbd2_journal_ack_err);

commit 2b2d6d019724de6e51ac5bcf22b5ef969daefa8b
+Author: Theodore Ts'o 
+Date:   Sat Jul 26 16:15:44 2008 -0400
+
+    ext4: Cleanup whitespace and other miscellaneous style issues
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
+index c7d04e165446..694ed6fadcc8 100644
+--- a/fs/ext4/acl.c
++++ b/fs/ext4/acl.c
+@@ -40,34 +40,35 @@ ext4_acl_from_disk(const void *value, size_t size)
+ 	acl = posix_acl_alloc(count, GFP_NOFS);
+ 	if (!acl)
+ 		return ERR_PTR(-ENOMEM);
+-	for (n=0; n < count; n++) {
++	for (n = 0; n < count; n++) {
+ 		ext4_acl_entry *entry =
+ 			(ext4_acl_entry *)value;
+ 		if ((char *)value + sizeof(ext4_acl_entry_short) > end)
+ 			goto fail;
+ 		acl->a_entries[n].e_tag  = le16_to_cpu(entry->e_tag);
+ 		acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm);
+-		switch(acl->a_entries[n].e_tag) {
+-			case ACL_USER_OBJ:
+-			case ACL_GROUP_OBJ:
+-			case ACL_MASK:
+-			case ACL_OTHER:
+-				value = (char *)value +
+-					sizeof(ext4_acl_entry_short);
+-				acl->a_entries[n].e_id = ACL_UNDEFINED_ID;
+-				break;
+-
+-			case ACL_USER:
+-			case ACL_GROUP:
+-				value = (char *)value + sizeof(ext4_acl_entry);
+-				if ((char *)value > end)
+-					goto fail;
+-				acl->a_entries[n].e_id =
+-					le32_to_cpu(entry->e_id);
+-				break;
+-
+-			default:
++
++		switch (acl->a_entries[n].e_tag) {
++		case ACL_USER_OBJ:
++		case ACL_GROUP_OBJ:
++		case ACL_MASK:
++		case ACL_OTHER:
++			value = (char *)value +
++				sizeof(ext4_acl_entry_short);
++			acl->a_entries[n].e_id = ACL_UNDEFINED_ID;
++			break;
++
++		case ACL_USER:
++		case ACL_GROUP:
++			value = (char *)value + sizeof(ext4_acl_entry);
++			if ((char *)value > end)
+ 				goto fail;
++			acl->a_entries[n].e_id =
++				le32_to_cpu(entry->e_id);
++			break;
++
++		default:
++			goto fail;
+ 		}
+ 	}
+ 	if (value != end)
+@@ -96,27 +97,26 @@ ext4_acl_to_disk(const struct posix_acl *acl, size_t *size)
+ 		return ERR_PTR(-ENOMEM);
+ 	ext_acl->a_version = cpu_to_le32(EXT4_ACL_VERSION);
+ 	e = (char *)ext_acl + sizeof(ext4_acl_header);
+-	for (n=0; n < acl->a_count; n++) {
++	for (n = 0; n < acl->a_count; n++) {
+ 		ext4_acl_entry *entry = (ext4_acl_entry *)e;
+ 		entry->e_tag  = cpu_to_le16(acl->a_entries[n].e_tag);
+ 		entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm);
+-		switch(acl->a_entries[n].e_tag) {
+-			case ACL_USER:
+-			case ACL_GROUP:
+-				entry->e_id =
+-					cpu_to_le32(acl->a_entries[n].e_id);
+-				e += sizeof(ext4_acl_entry);
+-				break;
+-
+-			case ACL_USER_OBJ:
+-			case ACL_GROUP_OBJ:
+-			case ACL_MASK:
+-			case ACL_OTHER:
+-				e += sizeof(ext4_acl_entry_short);
+-				break;
+-
+-			default:
+-				goto fail;
++		switch (acl->a_entries[n].e_tag) {
++		case ACL_USER:
++		case ACL_GROUP:
++			entry->e_id = cpu_to_le32(acl->a_entries[n].e_id);
++			e += sizeof(ext4_acl_entry);
++			break;
++
++		case ACL_USER_OBJ:
++		case ACL_GROUP_OBJ:
++		case ACL_MASK:
++		case ACL_OTHER:
++			e += sizeof(ext4_acl_entry_short);
++			break;
++
++		default:
++			goto fail;
+ 		}
+ 	}
+ 	return (char *)ext_acl;
+@@ -167,23 +167,23 @@ ext4_get_acl(struct inode *inode, int type)
+ 	if (!test_opt(inode->i_sb, POSIX_ACL))
+ 		return NULL;
+ 
+-	switch(type) {
+-		case ACL_TYPE_ACCESS:
+-			acl = ext4_iget_acl(inode, &ei->i_acl);
+-			if (acl != EXT4_ACL_NOT_CACHED)
+-				return acl;
+-			name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS;
+-			break;
+-
+-		case ACL_TYPE_DEFAULT:
+-			acl = ext4_iget_acl(inode, &ei->i_default_acl);
+-			if (acl != EXT4_ACL_NOT_CACHED)
+-				return acl;
+-			name_index = EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT;
+-			break;
+-
+-		default:
+-			return ERR_PTR(-EINVAL);
++	switch (type) {
++	case ACL_TYPE_ACCESS:
++		acl = ext4_iget_acl(inode, &ei->i_acl);
++		if (acl != EXT4_ACL_NOT_CACHED)
++			return acl;
++		name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS;
++		break;
++
++	case ACL_TYPE_DEFAULT:
++		acl = ext4_iget_acl(inode, &ei->i_default_acl);
++		if (acl != EXT4_ACL_NOT_CACHED)
++			return acl;
++		name_index = EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT;
++		break;
++
++	default:
++		return ERR_PTR(-EINVAL);
+ 	}
+ 	retval = ext4_xattr_get(inode, name_index, "", NULL, 0);
+ 	if (retval > 0) {
+@@ -201,14 +201,14 @@ ext4_get_acl(struct inode *inode, int type)
+ 	kfree(value);
+ 
+ 	if (!IS_ERR(acl)) {
+-		switch(type) {
+-			case ACL_TYPE_ACCESS:
+-				ext4_iset_acl(inode, &ei->i_acl, acl);
+-				break;
+-
+-			case ACL_TYPE_DEFAULT:
+-				ext4_iset_acl(inode, &ei->i_default_acl, acl);
+-				break;
++		switch (type) {
++		case ACL_TYPE_ACCESS:
++			ext4_iset_acl(inode, &ei->i_acl, acl);
++			break;
++
++		case ACL_TYPE_DEFAULT:
++			ext4_iset_acl(inode, &ei->i_default_acl, acl);
++			break;
+ 		}
+ 	}
+ 	return acl;
+@@ -232,31 +232,31 @@ ext4_set_acl(handle_t *handle, struct inode *inode, int type,
+ 	if (S_ISLNK(inode->i_mode))
+ 		return -EOPNOTSUPP;
+ 
+-	switch(type) {
+-		case ACL_TYPE_ACCESS:
+-			name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS;
+-			if (acl) {
+-				mode_t mode = inode->i_mode;
+-				error = posix_acl_equiv_mode(acl, &mode);
+-				if (error < 0)
+-					return error;
+-				else {
+-					inode->i_mode = mode;
+-					ext4_mark_inode_dirty(handle, inode);
+-					if (error == 0)
+-						acl = NULL;
+-				}
++	switch (type) {
++	case ACL_TYPE_ACCESS:
++		name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS;
++		if (acl) {
++			mode_t mode = inode->i_mode;
++			error = posix_acl_equiv_mode(acl, &mode);
++			if (error < 0)
++				return error;
++			else {
++				inode->i_mode = mode;
++				ext4_mark_inode_dirty(handle, inode);
++				if (error == 0)
++					acl = NULL;
+ 			}
+-			break;
++		}
++		break;
+ 
+-		case ACL_TYPE_DEFAULT:
+-			name_index = EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT;
+-			if (!S_ISDIR(inode->i_mode))
+-				return acl ? -EACCES : 0;
+-			break;
++	case ACL_TYPE_DEFAULT:
++		name_index = EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT;
++		if (!S_ISDIR(inode->i_mode))
++			return acl ? -EACCES : 0;
++		break;
+ 
+-		default:
+-			return -EINVAL;
++	default:
++		return -EINVAL;
+ 	}
+ 	if (acl) {
+ 		value = ext4_acl_to_disk(acl, &size);
+@@ -269,14 +269,14 @@ ext4_set_acl(handle_t *handle, struct inode *inode, int type,
+ 
+ 	kfree(value);
+ 	if (!error) {
+-		switch(type) {
+-			case ACL_TYPE_ACCESS:
+-				ext4_iset_acl(inode, &ei->i_acl, acl);
+-				break;
+-
+-			case ACL_TYPE_DEFAULT:
+-				ext4_iset_acl(inode, &ei->i_default_acl, acl);
+-				break;
++		switch (type) {
++		case ACL_TYPE_ACCESS:
++			ext4_iset_acl(inode, &ei->i_acl, acl);
++			break;
++
++		case ACL_TYPE_DEFAULT:
++			ext4_iset_acl(inode, &ei->i_default_acl, acl);
++			break;
+ 		}
+ 	}
+ 	return error;
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index f7529e27d791..612c3d2c3824 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -1441,7 +1441,7 @@ unsigned int ext4_ext_check_overlap(struct inode *inode,
+ 
+ 	/*
+ 	 * get the next allocated block if the extent in the path
+-	 * is before the requested block(s) 
++	 * is before the requested block(s)
+ 	 */
+ 	if (b2 < b1) {
+ 		b2 = ext4_ext_next_allocated_block(path);
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 85a862c9c4cc..0080999d2cd4 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1054,10 +1054,9 @@ static void ext4_da_update_reserve_space(struct inode *inode, int used)
+ 
+ 
+ /*
++ * The ext4_get_blocks_wrap() function try to look up the requested blocks,
++ * and returns if the blocks are already mapped.
+  *
+- *
+- * ext4_ext4 get_block() wrapper function
+- * It will do a look up first, and returns if the blocks already mapped.
+  * Otherwise it takes the write lock of the i_data_sem and allocate blocks
+  * and store the allocated blocks in the result buffer head and mark it
+  * mapped.
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index f000fbe2cd93..0a9265164265 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -73,7 +73,7 @@ static int verify_group_input(struct super_block *sb,
+ 			     "Inode bitmap not in group (block %llu)",
+ 			     (unsigned long long)input->inode_bitmap);
+ 	else if (outside(input->inode_table, start, end) ||
+-	         outside(itend - 1, start, end))
++		 outside(itend - 1, start, end))
+ 		ext4_warning(sb, __func__,
+ 			     "Inode table not in group (blocks %llu-%llu)",
+ 			     (unsigned long long)input->inode_table, itend - 1);
+@@ -104,7 +104,7 @@ static int verify_group_input(struct super_block *sb,
+ 			     (unsigned long long)input->inode_bitmap,
+ 			     start, metaend - 1);
+ 	else if (inside(input->inode_table, start, metaend) ||
+-	         inside(itend - 1, start, metaend))
++		 inside(itend - 1, start, metaend))
+ 		ext4_warning(sb, __func__,
+ 			     "Inode table (%llu-%llu) overlaps"
+ 			     "GDT table (%llu-%llu)",
+@@ -158,9 +158,9 @@ static int extend_or_restart_transaction(handle_t *handle, int thresh,
+ 	if (err) {
+ 		if ((err = ext4_journal_restart(handle, EXT4_MAX_TRANS_DATA)))
+ 			return err;
+-	        if ((err = ext4_journal_get_write_access(handle, bh)))
++		if ((err = ext4_journal_get_write_access(handle, bh)))
+ 			return err;
+-        }
++	}
+ 
+ 	return 0;
+ }
+@@ -416,11 +416,11 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ 		       "EXT4-fs: ext4_add_new_gdb: adding group block %lu\n",
+ 		       gdb_num);
+ 
+-	/*
+-	 * If we are not using the primary superblock/GDT copy don't resize,
+-	 * because the user tools have no way of handling this.  Probably a
+-	 * bad time to do it anyways.
+-	 */
++        /*
++         * If we are not using the primary superblock/GDT copy don't resize,
++         * because the user tools have no way of handling this.  Probably a
++         * bad time to do it anyways.
++         */
+ 	if (EXT4_SB(sb)->s_sbh->b_blocknr !=
+ 	    le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block)) {
+ 		ext4_warning(sb, __func__,
+@@ -507,14 +507,14 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ 	return 0;
+ 
+ exit_inode:
+-	//ext4_journal_release_buffer(handle, iloc.bh);
++	/* ext4_journal_release_buffer(handle, iloc.bh); */
+ 	brelse(iloc.bh);
+ exit_dindj:
+-	//ext4_journal_release_buffer(handle, dind);
++	/* ext4_journal_release_buffer(handle, dind); */
+ exit_primary:
+-	//ext4_journal_release_buffer(handle, *primary);
++	/* ext4_journal_release_buffer(handle, *primary); */
+ exit_sbh:
+-	//ext4_journal_release_buffer(handle, *primary);
++	/* ext4_journal_release_buffer(handle, *primary); */
+ exit_dind:
+ 	brelse(dind);
+ exit_bh:
+@@ -818,12 +818,12 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
+ 	if ((err = ext4_journal_get_write_access(handle, sbi->s_sbh)))
+ 		goto exit_journal;
+ 
+-	/*
+-	 * We will only either add reserved group blocks to a backup group
+-	 * or remove reserved blocks for the first group in a new group block.
+-	 * Doing both would be mean more complex code, and sane people don't
+-	 * use non-sparse filesystems anymore.  This is already checked above.
+-	 */
++        /*
++         * We will only either add reserved group blocks to a backup group
++         * or remove reserved blocks for the first group in a new group block.
++         * Doing both would be mean more complex code, and sane people don't
++         * use non-sparse filesystems anymore.  This is already checked above.
++         */
+ 	if (gdb_off) {
+ 		primary = sbi->s_group_desc[gdb_num];
+ 		if ((err = ext4_journal_get_write_access(handle, primary)))
+@@ -835,24 +835,24 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
+ 	} else if ((err = add_new_gdb(handle, inode, input, &primary)))
+ 		goto exit_journal;
+ 
+-	/*
+-	 * OK, now we've set up the new group.  Time to make it active.
+-	 *
+-	 * Current kernels don't lock all allocations via lock_super(),
+-	 * so we have to be safe wrt. concurrent accesses the group
+-	 * data.  So we need to be careful to set all of the relevant
+-	 * group descriptor data etc. *before* we enable the group.
+-	 *
+-	 * The key field here is sbi->s_groups_count: as long as
+-	 * that retains its old value, nobody is going to access the new
+-	 * group.
+-	 *
+-	 * So first we update all the descriptor metadata for the new
+-	 * group; then we update the total disk blocks count; then we
+-	 * update the groups count to enable the group; then finally we
+-	 * update the free space counts so that the system can start
+-	 * using the new disk blocks.
+-	 */
++        /*
++         * OK, now we've set up the new group.  Time to make it active.
++         *
++         * Current kernels don't lock all allocations via lock_super(),
++         * so we have to be safe wrt. concurrent accesses the group
++         * data.  So we need to be careful to set all of the relevant
++         * group descriptor data etc. *before* we enable the group.
++         *
++         * The key field here is sbi->s_groups_count: as long as
++         * that retains its old value, nobody is going to access the new
++         * group.
++         *
++         * So first we update all the descriptor metadata for the new
++         * group; then we update the total disk blocks count; then we
++         * update the groups count to enable the group; then finally we
++         * update the free space counts so that the system can start
++         * using the new disk blocks.
++         */
+ 
+ 	/* Update group descriptor block for new group */
+ 	gdp = (struct ext4_group_desc *)((char *)primary->b_data +
+@@ -946,7 +946,8 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
+ 	return err;
+ } /* ext4_group_add */
+ 
+-/* Extend the filesystem to the new number of blocks specified.  This entry
++/*
++ * Extend the filesystem to the new number of blocks specified.  This entry
+  * point is only used to extend the current filesystem to the end of the last
+  * existing group.  It can be accessed via ioctl, or by "remount,resize="
+  * for emergencies (because it has no dependencies on reserved blocks).
+@@ -1024,7 +1025,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
+ 			     o_blocks_count + add, add);
+ 
+ 	/* See if the device is actually as big as what was requested */
+-	bh = sb_bread(sb, o_blocks_count + add -1);
++	bh = sb_bread(sb, o_blocks_count + add - 1);
+ 	if (!bh) {
+ 		ext4_warning(sb, __func__,
+ 			     "can't read last block, resize aborted");
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index e34fc2d6dbf5..09e3c56782a7 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -49,20 +49,19 @@ static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
+ 			     unsigned long journal_devnum);
+ static int ext4_create_journal(struct super_block *, struct ext4_super_block *,
+ 			       unsigned int);
+-static void ext4_commit_super (struct super_block * sb,
+-			       struct ext4_super_block * es,
+-			       int sync);
+-static void ext4_mark_recovery_complete(struct super_block * sb,
+-					struct ext4_super_block * es);
+-static void ext4_clear_journal_err(struct super_block * sb,
+-				   struct ext4_super_block * es);
++static void ext4_commit_super(struct super_block *sb,
++			      struct ext4_super_block *es, int sync);
++static void ext4_mark_recovery_complete(struct super_block *sb,
++					struct ext4_super_block *es);
++static void ext4_clear_journal_err(struct super_block *sb,
++				   struct ext4_super_block *es);
+ static int ext4_sync_fs(struct super_block *sb, int wait);
+-static const char *ext4_decode_error(struct super_block * sb, int errno,
++static const char *ext4_decode_error(struct super_block *sb, int errno,
+ 				     char nbuf[16]);
+-static int ext4_remount (struct super_block * sb, int * flags, char * data);
+-static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf);
++static int ext4_remount(struct super_block *sb, int *flags, char *data);
++static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf);
+ static void ext4_unlockfs(struct super_block *sb);
+-static void ext4_write_super (struct super_block * sb);
++static void ext4_write_super(struct super_block *sb);
+ static void ext4_write_super_lockfs(struct super_block *sb);
+ 
+ 
+@@ -211,15 +210,15 @@ static void ext4_handle_error(struct super_block *sb)
+ 	if (sb->s_flags & MS_RDONLY)
+ 		return;
+ 
+-	if (!test_opt (sb, ERRORS_CONT)) {
++	if (!test_opt(sb, ERRORS_CONT)) {
+ 		journal_t *journal = EXT4_SB(sb)->s_journal;
+ 
+ 		EXT4_SB(sb)->s_mount_opt |= EXT4_MOUNT_ABORT;
+ 		if (journal)
+ 			jbd2_journal_abort(journal, -EIO);
+ 	}
+-	if (test_opt (sb, ERRORS_RO)) {
+-		printk (KERN_CRIT "Remounting filesystem read-only\n");
++	if (test_opt(sb, ERRORS_RO)) {
++		printk(KERN_CRIT "Remounting filesystem read-only\n");
+ 		sb->s_flags |= MS_RDONLY;
+ 	}
+ 	ext4_commit_super(sb, es, 1);
+@@ -228,13 +227,13 @@ static void ext4_handle_error(struct super_block *sb)
+ 			sb->s_id);
+ }
+ 
+-void ext4_error (struct super_block * sb, const char * function,
+-		 const char * fmt, ...)
++void ext4_error(struct super_block *sb, const char *function,
++		const char *fmt, ...)
+ {
+ 	va_list args;
+ 
+ 	va_start(args, fmt);
+-	printk(KERN_CRIT "EXT4-fs error (device %s): %s: ",sb->s_id, function);
++	printk(KERN_CRIT "EXT4-fs error (device %s): %s: ", sb->s_id, function);
+ 	vprintk(fmt, args);
+ 	printk("\n");
+ 	va_end(args);
+@@ -242,7 +241,7 @@ void ext4_error (struct super_block * sb, const char * function,
+ 	ext4_handle_error(sb);
+ }
+ 
+-static const char *ext4_decode_error(struct super_block * sb, int errno,
++static const char *ext4_decode_error(struct super_block *sb, int errno,
+ 				     char nbuf[16])
+ {
+ 	char *errstr = NULL;
+@@ -278,8 +277,7 @@ static const char *ext4_decode_error(struct super_block * sb, int errno,
+ /* __ext4_std_error decodes expected errors from journaling functions
+  * automatically and invokes the appropriate error response.  */
+ 
+-void __ext4_std_error (struct super_block * sb, const char * function,
+-		       int errno)
++void __ext4_std_error(struct super_block *sb, const char *function, int errno)
+ {
+ 	char nbuf[16];
+ 	const char *errstr;
+@@ -292,8 +290,8 @@ void __ext4_std_error (struct super_block * sb, const char * function,
+ 		return;
+ 
+ 	errstr = ext4_decode_error(sb, errno, nbuf);
+-	printk (KERN_CRIT "EXT4-fs error (device %s) in %s: %s\n",
+-		sb->s_id, function, errstr);
++	printk(KERN_CRIT "EXT4-fs error (device %s) in %s: %s\n",
++	       sb->s_id, function, errstr);
+ 
+ 	ext4_handle_error(sb);
+ }
+@@ -308,15 +306,15 @@ void __ext4_std_error (struct super_block * sb, const char * function,
+  * case we take the easy way out and panic immediately.
+  */
+ 
+-void ext4_abort (struct super_block * sb, const char * function,
+-		 const char * fmt, ...)
++void ext4_abort(struct super_block *sb, const char *function,
++		const char *fmt, ...)
+ {
+ 	va_list args;
+ 
+-	printk (KERN_CRIT "ext4_abort called.\n");
++	printk(KERN_CRIT "ext4_abort called.\n");
+ 
+ 	va_start(args, fmt);
+-	printk(KERN_CRIT "EXT4-fs error (device %s): %s: ",sb->s_id, function);
++	printk(KERN_CRIT "EXT4-fs error (device %s): %s: ", sb->s_id, function);
+ 	vprintk(fmt, args);
+ 	printk("\n");
+ 	va_end(args);
+@@ -334,8 +332,8 @@ void ext4_abort (struct super_block * sb, const char * function,
+ 	jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO);
+ }
+ 
+-void ext4_warning (struct super_block * sb, const char * function,
+-		   const char * fmt, ...)
++void ext4_warning(struct super_block *sb, const char *function,
++		  const char *fmt, ...)
+ {
+ 	va_list args;
+ 
+@@ -496,7 +494,7 @@ static void dump_orphan_list(struct super_block *sb, struct ext4_sb_info *sbi)
+ 	}
+ }
+ 
+-static void ext4_put_super (struct super_block * sb)
++static void ext4_put_super(struct super_block *sb)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	struct ext4_super_block *es = sbi->s_es;
+@@ -647,7 +645,8 @@ static void ext4_clear_inode(struct inode *inode)
+ 				       &EXT4_I(inode)->jinode);
+ }
+ 
+-static inline void ext4_show_quota_options(struct seq_file *seq, struct super_block *sb)
++static inline void ext4_show_quota_options(struct seq_file *seq,
++					   struct super_block *sb)
+ {
+ #if defined(CONFIG_QUOTA)
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+@@ -822,8 +821,8 @@ static struct dentry *ext4_fh_to_parent(struct super_block *sb, struct fid *fid,
+ }
+ 
+ #ifdef CONFIG_QUOTA
+-#define QTYPE2NAME(t) ((t)==USRQUOTA?"user":"group")
+-#define QTYPE2MOPT(on, t) ((t)==USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA))
++#define QTYPE2NAME(t) ((t) == USRQUOTA?"user":"group")
++#define QTYPE2MOPT(on, t) ((t) == USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA))
+ 
+ static int ext4_dquot_initialize(struct inode *inode, int type);
+ static int ext4_dquot_drop(struct inode *inode);
+@@ -991,12 +990,12 @@ static ext4_fsblk_t get_sb_block(void **data)
+ 	return sb_block;
+ }
+ 
+-static int parse_options (char *options, struct super_block *sb,
+-			  unsigned int *inum, unsigned long *journal_devnum,
+-			  ext4_fsblk_t *n_blocks_count, int is_remount)
++static int parse_options(char *options, struct super_block *sb,
++			 unsigned int *inum, unsigned long *journal_devnum,
++			 ext4_fsblk_t *n_blocks_count, int is_remount)
+ {
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-	char * p;
++	char *p;
+ 	substring_t args[MAX_OPT_ARGS];
+ 	int data_opt = 0;
+ 	int option;
+@@ -1009,7 +1008,7 @@ static int parse_options (char *options, struct super_block *sb,
+ 	if (!options)
+ 		return 1;
+ 
+-	while ((p = strsep (&options, ",")) != NULL) {
++	while ((p = strsep(&options, ",")) != NULL) {
+ 		int token;
+ 		if (!*p)
+ 			continue;
+@@ -1017,16 +1016,16 @@ static int parse_options (char *options, struct super_block *sb,
+ 		token = match_token(p, tokens, args);
+ 		switch (token) {
+ 		case Opt_bsd_df:
+-			clear_opt (sbi->s_mount_opt, MINIX_DF);
++			clear_opt(sbi->s_mount_opt, MINIX_DF);
+ 			break;
+ 		case Opt_minix_df:
+-			set_opt (sbi->s_mount_opt, MINIX_DF);
++			set_opt(sbi->s_mount_opt, MINIX_DF);
+ 			break;
+ 		case Opt_grpid:
+-			set_opt (sbi->s_mount_opt, GRPID);
++			set_opt(sbi->s_mount_opt, GRPID);
+ 			break;
+ 		case Opt_nogrpid:
+-			clear_opt (sbi->s_mount_opt, GRPID);
++			clear_opt(sbi->s_mount_opt, GRPID);
+ 			break;
+ 		case Opt_resuid:
+ 			if (match_int(&args[0], &option))
+@@ -1043,41 +1042,41 @@ static int parse_options (char *options, struct super_block *sb,
+ 			/* *sb_block = match_int(&args[0]); */
+ 			break;
+ 		case Opt_err_panic:
+-			clear_opt (sbi->s_mount_opt, ERRORS_CONT);
+-			clear_opt (sbi->s_mount_opt, ERRORS_RO);
+-			set_opt (sbi->s_mount_opt, ERRORS_PANIC);
++			clear_opt(sbi->s_mount_opt, ERRORS_CONT);
++			clear_opt(sbi->s_mount_opt, ERRORS_RO);
++			set_opt(sbi->s_mount_opt, ERRORS_PANIC);
+ 			break;
+ 		case Opt_err_ro:
+-			clear_opt (sbi->s_mount_opt, ERRORS_CONT);
+-			clear_opt (sbi->s_mount_opt, ERRORS_PANIC);
+-			set_opt (sbi->s_mount_opt, ERRORS_RO);
++			clear_opt(sbi->s_mount_opt, ERRORS_CONT);
++			clear_opt(sbi->s_mount_opt, ERRORS_PANIC);
++			set_opt(sbi->s_mount_opt, ERRORS_RO);
+ 			break;
+ 		case Opt_err_cont:
+-			clear_opt (sbi->s_mount_opt, ERRORS_RO);
+-			clear_opt (sbi->s_mount_opt, ERRORS_PANIC);
+-			set_opt (sbi->s_mount_opt, ERRORS_CONT);
++			clear_opt(sbi->s_mount_opt, ERRORS_RO);
++			clear_opt(sbi->s_mount_opt, ERRORS_PANIC);
++			set_opt(sbi->s_mount_opt, ERRORS_CONT);
+ 			break;
+ 		case Opt_nouid32:
+-			set_opt (sbi->s_mount_opt, NO_UID32);
++			set_opt(sbi->s_mount_opt, NO_UID32);
+ 			break;
+ 		case Opt_nocheck:
+-			clear_opt (sbi->s_mount_opt, CHECK);
++			clear_opt(sbi->s_mount_opt, CHECK);
+ 			break;
+ 		case Opt_debug:
+-			set_opt (sbi->s_mount_opt, DEBUG);
++			set_opt(sbi->s_mount_opt, DEBUG);
+ 			break;
+ 		case Opt_oldalloc:
+-			set_opt (sbi->s_mount_opt, OLDALLOC);
++			set_opt(sbi->s_mount_opt, OLDALLOC);
+ 			break;
+ 		case Opt_orlov:
+-			clear_opt (sbi->s_mount_opt, OLDALLOC);
++			clear_opt(sbi->s_mount_opt, OLDALLOC);
+ 			break;
+ #ifdef CONFIG_EXT4DEV_FS_XATTR
+ 		case Opt_user_xattr:
+-			set_opt (sbi->s_mount_opt, XATTR_USER);
++			set_opt(sbi->s_mount_opt, XATTR_USER);
+ 			break;
+ 		case Opt_nouser_xattr:
+-			clear_opt (sbi->s_mount_opt, XATTR_USER);
++			clear_opt(sbi->s_mount_opt, XATTR_USER);
+ 			break;
+ #else
+ 		case Opt_user_xattr:
+@@ -1115,7 +1114,7 @@ static int parse_options (char *options, struct super_block *sb,
+ 				       "journal on remount\n");
+ 				return 0;
+ 			}
+-			set_opt (sbi->s_mount_opt, UPDATE_JOURNAL);
++			set_opt(sbi->s_mount_opt, UPDATE_JOURNAL);
+ 			break;
+ 		case Opt_journal_inum:
+ 			if (is_remount) {
+@@ -1145,7 +1144,7 @@ static int parse_options (char *options, struct super_block *sb,
+ 			set_opt(sbi->s_mount_opt, JOURNAL_CHECKSUM);
+ 			break;
+ 		case Opt_noload:
+-			set_opt (sbi->s_mount_opt, NOLOAD);
++			set_opt(sbi->s_mount_opt, NOLOAD);
+ 			break;
+ 		case Opt_commit:
+ 			if (match_int(&args[0], &option))
+@@ -1331,7 +1330,7 @@ static int parse_options (char *options, struct super_block *sb,
+ 					"on this filesystem, use tune2fs\n");
+ 				return 0;
+ 			}
+-			set_opt (sbi->s_mount_opt, EXTENTS);
++			set_opt(sbi->s_mount_opt, EXTENTS);
+ 			break;
+ 		case Opt_noextents:
+ 			/*
+@@ -1348,7 +1347,7 @@ static int parse_options (char *options, struct super_block *sb,
+ 						"-o noextents options\n");
+ 				return 0;
+ 			}
+-			clear_opt (sbi->s_mount_opt, EXTENTS);
++			clear_opt(sbi->s_mount_opt, EXTENTS);
+ 			break;
+ 		case Opt_i_version:
+ 			set_opt(sbi->s_mount_opt, I_VERSION);
+@@ -1374,9 +1373,9 @@ static int parse_options (char *options, struct super_block *sb,
+ 			set_opt(sbi->s_mount_opt, DELALLOC);
+ 			break;
+ 		default:
+-			printk (KERN_ERR
+-				"EXT4-fs: Unrecognized mount option \"%s\" "
+-				"or missing value\n", p);
++			printk(KERN_ERR
++			       "EXT4-fs: Unrecognized mount option \"%s\" "
++			       "or missing value\n", p);
+ 			return 0;
+ 		}
+ 	}
+@@ -1423,31 +1422,31 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
+ 	int res = 0;
+ 
+ 	if (le32_to_cpu(es->s_rev_level) > EXT4_MAX_SUPP_REV) {
+-		printk (KERN_ERR "EXT4-fs warning: revision level too high, "
+-			"forcing read-only mode\n");
++		printk(KERN_ERR "EXT4-fs warning: revision level too high, "
++		       "forcing read-only mode\n");
+ 		res = MS_RDONLY;
+ 	}
+ 	if (read_only)
+ 		return res;
+ 	if (!(sbi->s_mount_state & EXT4_VALID_FS))
+-		printk (KERN_WARNING "EXT4-fs warning: mounting unchecked fs, "
+-			"running e2fsck is recommended\n");
++		printk(KERN_WARNING "EXT4-fs warning: mounting unchecked fs, "
++		       "running e2fsck is recommended\n");
+ 	else if ((sbi->s_mount_state & EXT4_ERROR_FS))
+-		printk (KERN_WARNING
+-			"EXT4-fs warning: mounting fs with errors, "
+-			"running e2fsck is recommended\n");
++		printk(KERN_WARNING
++		       "EXT4-fs warning: mounting fs with errors, "
++		       "running e2fsck is recommended\n");
+ 	else if ((__s16) le16_to_cpu(es->s_max_mnt_count) >= 0 &&
+ 		 le16_to_cpu(es->s_mnt_count) >=
+ 		 (unsigned short) (__s16) le16_to_cpu(es->s_max_mnt_count))
+-		printk (KERN_WARNING
+-			"EXT4-fs warning: maximal mount count reached, "
+-			"running e2fsck is recommended\n");
++		printk(KERN_WARNING
++		       "EXT4-fs warning: maximal mount count reached, "
++		       "running e2fsck is recommended\n");
+ 	else if (le32_to_cpu(es->s_checkinterval) &&
+ 		(le32_to_cpu(es->s_lastcheck) +
+ 			le32_to_cpu(es->s_checkinterval) <= get_seconds()))
+-		printk (KERN_WARNING
+-			"EXT4-fs warning: checktime reached, "
+-			"running e2fsck is recommended\n");
++		printk(KERN_WARNING
++		       "EXT4-fs warning: checktime reached, "
++		       "running e2fsck is recommended\n");
+ #if 0
+ 		/* @@@ We _will_ want to clear the valid bit if we find
+ 		 * inconsistencies, to force a fsck at reboot.  But for
+@@ -1596,16 +1595,14 @@ static int ext4_check_descriptors(struct super_block *sb)
+ 				(EXT4_BLOCKS_PER_GROUP(sb) - 1);
+ 
+ 		block_bitmap = ext4_block_bitmap(sb, gdp);
+-		if (block_bitmap < first_block || block_bitmap > last_block)
+-		{
++		if (block_bitmap < first_block || block_bitmap > last_block) {
+ 			printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
+ 			       "Block bitmap for group %lu not in group "
+ 			       "(block %llu)!", i, block_bitmap);
+ 			return 0;
+ 		}
+ 		inode_bitmap = ext4_inode_bitmap(sb, gdp);
+-		if (inode_bitmap < first_block || inode_bitmap > last_block)
+-		{
++		if (inode_bitmap < first_block || inode_bitmap > last_block) {
+ 			printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
+ 			       "Inode bitmap for group %lu not in group "
+ 			       "(block %llu)!", i, inode_bitmap);
+@@ -1613,8 +1610,7 @@ static int ext4_check_descriptors(struct super_block *sb)
+ 		}
+ 		inode_table = ext4_inode_table(sb, gdp);
+ 		if (inode_table < first_block ||
+-		    inode_table + sbi->s_itb_per_group - 1 > last_block)
+-		{
++		    inode_table + sbi->s_itb_per_group - 1 > last_block) {
+ 			printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
+ 			       "Inode table for group %lu not in group "
+ 			       "(block %llu)!", i, inode_table);
+@@ -1635,7 +1631,7 @@ static int ext4_check_descriptors(struct super_block *sb)
+ 	}
+ 
+ 	ext4_free_blocks_count_set(sbi->s_es, ext4_count_free_blocks(sb));
+-	sbi->s_es->s_free_inodes_count=cpu_to_le32(ext4_count_free_inodes(sb));
++	sbi->s_es->s_free_inodes_count = cpu_to_le32(ext4_count_free_inodes(sb));
+ 	return 1;
+ }
+ 
+@@ -1656,8 +1652,8 @@ static int ext4_check_descriptors(struct super_block *sb)
+  * e2fsck was run on this filesystem, and it must have already done the orphan
+  * inode cleanup for us, so we can safely abort without any further action.
+  */
+-static void ext4_orphan_cleanup (struct super_block * sb,
+-				 struct ext4_super_block * es)
++static void ext4_orphan_cleanup(struct super_block *sb,
++				struct ext4_super_block *es)
+ {
+ 	unsigned int s_flags = sb->s_flags;
+ 	int nr_orphans = 0, nr_truncates = 0;
+@@ -1734,7 +1730,7 @@ static void ext4_orphan_cleanup (struct super_block * sb,
+ 		iput(inode);  /* The delete magic happens here! */
+ 	}
+ 
+-#define PLURAL(x) (x), ((x)==1) ? "" : "s"
++#define PLURAL(x) (x), ((x) == 1) ? "" : "s"
+ 
+ 	if (nr_orphans)
+ 		printk(KERN_INFO "EXT4-fs: %s: %d orphan inode%s deleted\n",
+@@ -1901,12 +1897,12 @@ static unsigned long ext4_get_stripe_size(struct ext4_sb_info *sbi)
+ 	return 0;
+ }
+ 
+-static int ext4_fill_super (struct super_block *sb, void *data, int silent)
++static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ 				__releases(kernel_lock)
+ 				__acquires(kernel_lock)
+ 
+ {
+-	struct buffer_head * bh;
++	struct buffer_head *bh;
+ 	struct ext4_super_block *es = NULL;
+ 	struct ext4_sb_info *sbi;
+ 	ext4_fsblk_t block;
+@@ -1955,7 +1951,7 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
+ 	}
+ 
+ 	if (!(bh = sb_bread(sb, logical_sb_block))) {
+-		printk (KERN_ERR "EXT4-fs: unable to read superblock\n");
++		printk(KERN_ERR "EXT4-fs: unable to read superblock\n");
+ 		goto out_fail;
+ 	}
+ 	/*
+@@ -2028,8 +2024,8 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
+ 	set_opt(sbi->s_mount_opt, DELALLOC);
+ 
+ 
+-	if (!parse_options ((char *) data, sb, &journal_inum, &journal_devnum,
+-			    NULL, 0))
++	if (!parse_options((char *) data, sb, &journal_inum, &journal_devnum,
++			   NULL, 0))
+ 		goto failed_mount;
+ 
+ 	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
+@@ -2104,7 +2100,7 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
+ 			goto failed_mount;
+ 		}
+ 
+-		brelse (bh);
++		brelse(bh);
+ 		logical_sb_block = sb_block * EXT4_MIN_BLOCK_SIZE;
+ 		offset = do_div(logical_sb_block, blocksize);
+ 		bh = sb_bread(sb, logical_sb_block);
+@@ -2116,8 +2112,8 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
+ 		es = (struct ext4_super_block *)(((char *)bh->b_data) + offset);
+ 		sbi->s_es = es;
+ 		if (es->s_magic != cpu_to_le16(EXT4_SUPER_MAGIC)) {
+-			printk (KERN_ERR
+-				"EXT4-fs: Magic mismatch, very weird !\n");
++			printk(KERN_ERR
++			       "EXT4-fs: Magic mismatch, very weird !\n");
+ 			goto failed_mount;
+ 		}
+ 	}
+@@ -2134,9 +2130,9 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
+ 		if ((sbi->s_inode_size < EXT4_GOOD_OLD_INODE_SIZE) ||
+ 		    (!is_power_of_2(sbi->s_inode_size)) ||
+ 		    (sbi->s_inode_size > blocksize)) {
+-			printk (KERN_ERR
+-				"EXT4-fs: unsupported inode size: %d\n",
+-				sbi->s_inode_size);
++			printk(KERN_ERR
++			       "EXT4-fs: unsupported inode size: %d\n",
++			       sbi->s_inode_size);
+ 			goto failed_mount;
+ 		}
+ 		if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE)
+@@ -2168,20 +2164,20 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
+ 	sbi->s_mount_state = le16_to_cpu(es->s_state);
+ 	sbi->s_addr_per_block_bits = ilog2(EXT4_ADDR_PER_BLOCK(sb));
+ 	sbi->s_desc_per_block_bits = ilog2(EXT4_DESC_PER_BLOCK(sb));
+-	for (i=0; i < 4; i++)
++	for (i = 0; i < 4; i++)
+ 		sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
+ 	sbi->s_def_hash_version = es->s_def_hash_version;
+ 
+ 	if (sbi->s_blocks_per_group > blocksize * 8) {
+-		printk (KERN_ERR
+-			"EXT4-fs: #blocks per group too big: %lu\n",
+-			sbi->s_blocks_per_group);
++		printk(KERN_ERR
++		       "EXT4-fs: #blocks per group too big: %lu\n",
++		       sbi->s_blocks_per_group);
+ 		goto failed_mount;
+ 	}
+ 	if (sbi->s_inodes_per_group > blocksize * 8) {
+-		printk (KERN_ERR
+-			"EXT4-fs: #inodes per group too big: %lu\n",
+-			sbi->s_inodes_per_group);
++		printk(KERN_ERR
++		       "EXT4-fs: #inodes per group too big: %lu\n",
++		       sbi->s_inodes_per_group);
+ 		goto failed_mount;
+ 	}
+ 
+@@ -2215,10 +2211,10 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
+ 	sbi->s_groups_count = blocks_count;
+ 	db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) /
+ 		   EXT4_DESC_PER_BLOCK(sb);
+-	sbi->s_group_desc = kmalloc(db_count * sizeof (struct buffer_head *),
++	sbi->s_group_desc = kmalloc(db_count * sizeof(struct buffer_head *),
+ 				    GFP_KERNEL);
+ 	if (sbi->s_group_desc == NULL) {
+-		printk (KERN_ERR "EXT4-fs: not enough memory\n");
++		printk(KERN_ERR "EXT4-fs: not enough memory\n");
+ 		goto failed_mount;
+ 	}
+ 
+@@ -2228,13 +2224,13 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
+ 		block = descriptor_loc(sb, logical_sb_block, i);
+ 		sbi->s_group_desc[i] = sb_bread(sb, block);
+ 		if (!sbi->s_group_desc[i]) {
+-			printk (KERN_ERR "EXT4-fs: "
+-				"can't read group descriptor %d\n", i);
++			printk(KERN_ERR "EXT4-fs: "
++			       "can't read group descriptor %d\n", i);
+ 			db_count = i;
+ 			goto failed_mount2;
+ 		}
+ 	}
+-	if (!ext4_check_descriptors (sb)) {
++	if (!ext4_check_descriptors(sb)) {
+ 		printk(KERN_ERR "EXT4-fs: group descriptors corrupted!\n");
+ 		goto failed_mount2;
+ 	}
+@@ -2310,11 +2306,11 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
+ 		    EXT4_SB(sb)->s_journal->j_failed_commit) {
+ 			printk(KERN_CRIT "EXT4-fs error (device %s): "
+ 			       "ext4_fill_super: Journal transaction "
+-			       "%u is corrupt\n", sb->s_id, 
++			       "%u is corrupt\n", sb->s_id,
+ 			       EXT4_SB(sb)->s_journal->j_failed_commit);
+-			if (test_opt (sb, ERRORS_RO)) {
+-				printk (KERN_CRIT
+-					"Mounting filesystem read-only\n");
++			if (test_opt(sb, ERRORS_RO)) {
++				printk(KERN_CRIT
++				       "Mounting filesystem read-only\n");
+ 				sb->s_flags |= MS_RDONLY;
+ 				EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
+ 				es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
+@@ -2334,9 +2330,9 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
+ 			goto failed_mount3;
+ 	} else {
+ 		if (!silent)
+-			printk (KERN_ERR
+-				"ext4: No journal on filesystem on %s\n",
+-				sb->s_id);
++			printk(KERN_ERR
++			       "ext4: No journal on filesystem on %s\n",
++			       sb->s_id);
+ 		goto failed_mount3;
+ 	}
+ 
+@@ -2420,7 +2416,7 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
+ 		goto failed_mount4;
+ 	}
+ 
+-	ext4_setup_super (sb, es, sb->s_flags & MS_RDONLY);
++	ext4_setup_super(sb, es, sb->s_flags & MS_RDONLY);
+ 
+ 	/* determine the minimum size of new large inodes, if present */
+ 	if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE) {
+@@ -2459,12 +2455,12 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
+ 	ext4_orphan_cleanup(sb, es);
+ 	EXT4_SB(sb)->s_mount_state &= ~EXT4_ORPHAN_FS;
+ 	if (needs_recovery)
+-		printk (KERN_INFO "EXT4-fs: recovery complete.\n");
++		printk(KERN_INFO "EXT4-fs: recovery complete.\n");
+ 	ext4_mark_recovery_complete(sb, es);
+-	printk (KERN_INFO "EXT4-fs: mounted filesystem with %s data mode.\n",
+-		test_opt(sb,DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ? "journal":
+-		test_opt(sb,DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA ? "ordered":
+-		"writeback");
++	printk(KERN_INFO "EXT4-fs: mounted filesystem with %s data mode.\n",
++	       test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ? "journal":
++	       test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA ? "ordered":
++	       "writeback");
+ 
+ 	if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
+ 		printk(KERN_WARNING "EXT4-fs: Ignoring delalloc option - "
+@@ -2577,14 +2573,14 @@ static journal_t *ext4_get_journal(struct super_block *sb,
+ static journal_t *ext4_get_dev_journal(struct super_block *sb,
+ 				       dev_t j_dev)
+ {
+-	struct buffer_head * bh;
++	struct buffer_head *bh;
+ 	journal_t *journal;
+ 	ext4_fsblk_t start;
+ 	ext4_fsblk_t len;
+ 	int hblock, blocksize;
+ 	ext4_fsblk_t sb_block;
+ 	unsigned long offset;
+-	struct ext4_super_block * es;
++	struct ext4_super_block *es;
+ 	struct block_device *bdev;
+ 
+ 	bdev = ext4_blkdev_get(j_dev);
+@@ -2699,8 +2695,8 @@ static int ext4_load_journal(struct super_block *sb,
+ 					"unavailable, cannot proceed.\n");
+ 				return -EROFS;
+ 			}
+-			printk (KERN_INFO "EXT4-fs: write access will "
+-					"be enabled during recovery.\n");
++			printk(KERN_INFO "EXT4-fs: write access will "
++			       "be enabled during recovery.\n");
+ 		}
+ 	}
+ 
+@@ -2753,8 +2749,8 @@ static int ext4_load_journal(struct super_block *sb,
+ 	return 0;
+ }
+ 
+-static int ext4_create_journal(struct super_block * sb,
+-			       struct ext4_super_block * es,
++static int ext4_create_journal(struct super_block *sb,
++			       struct ext4_super_block *es,
+ 			       unsigned int journal_inum)
+ {
+ 	journal_t *journal;
+@@ -2795,9 +2791,8 @@ static int ext4_create_journal(struct super_block * sb,
+ 	return 0;
+ }
+ 
+-static void ext4_commit_super (struct super_block * sb,
+-			       struct ext4_super_block * es,
+-			       int sync)
++static void ext4_commit_super(struct super_block *sb,
++			      struct ext4_super_block *es, int sync)
+ {
+ 	struct buffer_head *sbh = EXT4_SB(sb)->s_sbh;
+ 
+@@ -2818,8 +2813,8 @@ static void ext4_commit_super (struct super_block * sb,
+  * remounting) the filesystem readonly, then we will end up with a
+  * consistent fs on disk.  Record that fact.
+  */
+-static void ext4_mark_recovery_complete(struct super_block * sb,
+-					struct ext4_super_block * es)
++static void ext4_mark_recovery_complete(struct super_block *sb,
++					struct ext4_super_block *es)
+ {
+ 	journal_t *journal = EXT4_SB(sb)->s_journal;
+ 
+@@ -2841,8 +2836,8 @@ static void ext4_mark_recovery_complete(struct super_block * sb,
+  * has recorded an error from a previous lifetime, move that error to the
+  * main filesystem now.
+  */
+-static void ext4_clear_journal_err(struct super_block * sb,
+-				   struct ext4_super_block * es)
++static void ext4_clear_journal_err(struct super_block *sb,
++				   struct ext4_super_block *es)
+ {
+ 	journal_t *journal;
+ 	int j_errno;
+@@ -2867,7 +2862,7 @@ static void ext4_clear_journal_err(struct super_block * sb,
+ 
+ 		EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
+ 		es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
+-		ext4_commit_super (sb, es, 1);
++		ext4_commit_super(sb, es, 1);
+ 
+ 		jbd2_journal_clear_err(journal);
+ 	}
+@@ -2900,7 +2895,7 @@ int ext4_force_commit(struct super_block *sb)
+  * This implicitly triggers the writebehind on sync().
+  */
+ 
+-static void ext4_write_super (struct super_block * sb)
++static void ext4_write_super(struct super_block *sb)
+ {
+ 	if (mutex_trylock(&sb->s_lock) != 0)
+ 		BUG();
+@@ -2956,9 +2951,9 @@ static void ext4_unlockfs(struct super_block *sb)
+ 	}
+ }
+ 
+-static int ext4_remount (struct super_block * sb, int * flags, char * data)
++static int ext4_remount(struct super_block *sb, int *flags, char *data)
+ {
+-	struct ext4_super_block * es;
++	struct ext4_super_block *es;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+ 	ext4_fsblk_t n_blocks_count = 0;
+ 	unsigned long old_sb_flags;
+@@ -3086,7 +3081,7 @@ static int ext4_remount (struct super_block * sb, int * flags, char * data)
+ 			sbi->s_mount_state = le16_to_cpu(es->s_state);
+ 			if ((err = ext4_group_extend(sb, es, n_blocks_count)))
+ 				goto restore_opts;
+-			if (!ext4_setup_super (sb, es, 0))
++			if (!ext4_setup_super(sb, es, 0))
+ 				sb->s_flags &= ~MS_RDONLY;
+ 		}
+ 	}
+@@ -3116,7 +3111,7 @@ static int ext4_remount (struct super_block * sb, int * flags, char * data)
+ 	return err;
+ }
+ 
+-static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf)
++static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
+ {
+ 	struct super_block *sb = dentry->d_sb;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+@@ -3354,12 +3349,12 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
+ 	}
+ 	/* Journaling quota? */
+ 	if (EXT4_SB(sb)->s_qf_names[type]) {
+-		/* Quotafile not of fs root? */
++		/* Quotafile not in fs root? */
+ 		if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode)
+ 			printk(KERN_WARNING
+ 				"EXT4-fs: Quota file not on filesystem root. "
+ 				"Journaled quota will not work.\n");
+- 	}
++	}
+ 
+ 	/*
+ 	 * When we journal data on quota file, we have to flush journal to see
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 93c5fdcdad2e..8954208b4893 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -1512,7 +1512,7 @@ static inline void ext4_xattr_hash_entry(struct ext4_xattr_header *header,
+ 	char *name = entry->e_name;
+ 	int n;
+ 
+-	for (n=0; n < entry->e_name_len; n++) {
++	for (n = 0; n < entry->e_name_len; n++) {
+ 		hash = (hash << NAME_HASH_SHIFT) ^
+ 		       (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
+ 		       *name++;

commit 34071da71a665d8c81e3b3467c9a2e7c56386fec
+Author: Theodore Ts'o 
+Date:   Fri Aug 1 21:59:19 2008 -0400
+
+    ext4: don't assume extents can't cross block groups when truncating
+    
+    With the FLEX_BG layout, there is no reason why extents can't cross
+    block groups, so make the truncate code reserve enough credits so we
+    don't BUG if we come across such an extent.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index f554703eb924..f7529e27d791 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -1910,9 +1910,13 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
+ 			BUG_ON(b != ex_ee_block + ex_ee_len - 1);
+ 		}
+ 
+-		/* at present, extent can't cross block group: */
+-		/* leaf + bitmap + group desc + sb + inode */
+-		credits = 5;
++		/*
++		 * 3 for leaf, sb, and inode plus 2 (bmap and group
++		 * descriptor) for each block group; assume two block
++		 * groups plus ex_ee_len/blocks_per_block_group for
++		 * the worst case
++		 */
++		credits = 7 + 2*(ex_ee_len/EXT4_BLOCKS_PER_GROUP(inode->i_sb));
+ 		if (ex == EXT_FIRST_EXTENT(eh)) {
+ 			correct_index = 1;
+ 			credits += (ext_depth(inode)) + 1;

commit bc965ab3f2b4b7bb898b11d61d25295c2053b8ac
+Author: Theodore Ts'o 
+Date:   Sat Aug 2 21:10:38 2008 -0400
+
+    ext4: Fix lack of credits BUG() when deleting a badly fragmented inode
+    
+    The extents codepath for ext4_truncate() requests journal transaction
+    credits in very small chunks, requesting only what is needed.  This
+    means there may not be enough credits left on the transaction handle
+    after ext4_truncate() returns and then when ext4_delete_inode() tries
+    finish up its work, it may not have enough transaction credits,
+    causing a BUG() oops in the jbd2 core.
+    
+    Also, reserve an extra 2 blocks when starting an ext4_delete_inode()
+    since we need to update the inode bitmap, as well as update the
+    orphaned inode linked list.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 37f834bc7cd6..2697eaf0368f 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -191,6 +191,7 @@ static int ext4_journal_test_restart(handle_t *handle, struct inode *inode)
+ void ext4_delete_inode (struct inode * inode)
+ {
+ 	handle_t *handle;
++	int err;
+ 
+ 	if (ext4_should_order_data(inode))
+ 		ext4_begin_ordered_truncate(inode, 0);
+@@ -199,8 +200,9 @@ void ext4_delete_inode (struct inode * inode)
+ 	if (is_bad_inode(inode))
+ 		goto no_delete;
+ 
+-	handle = start_transaction(inode);
++	handle = ext4_journal_start(inode, blocks_for_truncate(inode)+3);
+ 	if (IS_ERR(handle)) {
++		ext4_std_error(inode->i_sb, PTR_ERR(handle));
+ 		/*
+ 		 * If we're going to skip the normal cleanup, we still need to
+ 		 * make sure that the in-core orphan linked list is properly
+@@ -213,8 +215,34 @@ void ext4_delete_inode (struct inode * inode)
+ 	if (IS_SYNC(inode))
+ 		handle->h_sync = 1;
+ 	inode->i_size = 0;
++	err = ext4_mark_inode_dirty(handle, inode);
++	if (err) {
++		ext4_warning(inode->i_sb, __func__,
++			     "couldn't mark inode dirty (err %d)", err);
++		goto stop_handle;
++	}
+ 	if (inode->i_blocks)
+ 		ext4_truncate(inode);
++
++	/*
++	 * ext4_ext_truncate() doesn't reserve any slop when it
++	 * restarts journal transactions; therefore there may not be
++	 * enough credits left in the handle to remove the inode from
++	 * the orphan list and set the dtime field.
++	 */
++	if (handle->h_buffer_credits < 3) {
++		err = ext4_journal_extend(handle, 3);
++		if (err > 0)
++			err = ext4_journal_restart(handle, 3);
++		if (err != 0) {
++			ext4_warning(inode->i_sb, __func__,
++				     "couldn't extend journal (err %d)", err);
++		stop_handle:
++			ext4_journal_stop(handle);
++			goto no_delete;
++		}
++	}
++
+ 	/*
+ 	 * Kill off the orphan record which ext4_truncate created.
+ 	 * AKPM: I think this can be inside the above `if'.

commit 0123c93998511978556b03d2bb023af92aa24d55
+Author: Theodore Ts'o 
+Date:   Fri Aug 1 20:57:54 2008 -0400
+
+    ext4: Fix ext4_ext_journal_restart()
+    
+    The ext4_ext_journal_restart() is a convenience function which checks
+    to see if the requested number of credits is present, and if so it
+    closes the current transaction and attaches the current handle to the
+    new transaction.  Unfortunately, it wasn't proprely checking the
+    return value from ext4_journal_extend(), so it was starting a new
+    transaction when one was not necessary, and returning an error when
+    all that was necessary was to restart the handle with a new
+    transaction.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 8ee1fa54a4e1..f554703eb924 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -99,7 +99,7 @@ static int ext4_ext_journal_restart(handle_t *handle, int needed)
+ 	if (handle->h_buffer_credits > needed)
+ 		return 0;
+ 	err = ext4_journal_extend(handle, needed);
+-	if (err)
++	if (err <= 0)
+ 		return err;
+ 	return ext4_journal_restart(handle, needed);
+ }

commit 8a266467b8c4841ca994d0fe59f39e584650e3df
+Author: Theodore Ts'o 
+Date:   Sat Jul 26 14:34:21 2008 -0400
+
+    ext4: Allow read/only mounts with corrupted block group checksums
+    
+    If the block group checksums are corrupted, still allow the mount to
+    succeed, so e2fsck can have a chance to try to fix things up.  Add
+    code in the remount r/w path to make sure the block group checksums
+    are valid before allowing the filesystem to be remounted read/write.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index b5479b1dff14..876e1c620365 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1626,7 +1626,8 @@ static int ext4_check_descriptors(struct super_block *sb)
+ 			       "Checksum for group %lu failed (%u!=%u)\n",
+ 			       i, le16_to_cpu(ext4_group_desc_csum(sbi, i,
+ 			       gdp)), le16_to_cpu(gdp->bg_checksum));
+-			return 0;
++			if (!(sb->s_flags & MS_RDONLY))
++				return 0;
+ 		}
+ 		if (!flexbg_flag)
+ 			first_block += EXT4_BLOCKS_PER_GROUP(sb);
+@@ -2961,6 +2962,7 @@ static int ext4_remount (struct super_block * sb, int * flags, char * data)
+ 	ext4_fsblk_t n_blocks_count = 0;
+ 	unsigned long old_sb_flags;
+ 	struct ext4_mount_options old_opts;
++	ext4_group_t g;
+ 	int err;
+ #ifdef CONFIG_QUOTA
+ 	int i;
+@@ -3038,6 +3040,26 @@ static int ext4_remount (struct super_block * sb, int * flags, char * data)
+ 				goto restore_opts;
+ 			}
+ 
++			/*
++			 * Make sure the group descriptor checksums
++			 * are sane.  If they aren't, refuse to
++			 * remount r/w.
++			 */
++			for (g = 0; g < sbi->s_groups_count; g++) {
++				struct ext4_group_desc *gdp =
++					ext4_get_group_desc(sb, g, NULL);
++
++				if (!ext4_group_desc_csum_verify(sbi, g, gdp)) {
++					printk(KERN_ERR
++	       "EXT4-fs: ext4_remount: "
++		"Checksum for group %lu failed (%u!=%u)\n",
++		g, le16_to_cpu(ext4_group_desc_csum(sbi, g, gdp)),
++					       le16_to_cpu(gdp->bg_checksum));
++					err = -EINVAL;
++					goto restore_opts;
++				}
++			}
++
+ 			/*
+ 			 * If we have an unprocessed orphan list hanging
+ 			 * around from a previously readonly bdev mount,

commit 736603ab297506f4396cb5af592004499950fcfd
+Author: Theodore Ts'o 
+Date:   Fri Jul 11 19:27:31 2008 -0400
+
+    jbd2: Add commit time into the commit block
+    
+    Carlo Wood has demonstrated that it's possible to recover deleted
+    files from the journal.  Something that will make this easier is if we
+    can put the time of the commit into commit block.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index a2ed72f7ceee..92b6ac3df8ab 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -112,6 +112,7 @@ static int journal_submit_commit_record(journal_t *journal,
+ 	struct buffer_head *bh;
+ 	int ret;
+ 	int barrier_done = 0;
++	struct timespec now = current_kernel_time();
+ 
+ 	if (is_journal_aborted(journal))
+ 		return 0;
+@@ -126,6 +127,8 @@ static int journal_submit_commit_record(journal_t *journal,
+ 	tmp->h_magic = cpu_to_be32(JBD2_MAGIC_NUMBER);
+ 	tmp->h_blocktype = cpu_to_be32(JBD2_COMMIT_BLOCK);
+ 	tmp->h_sequence = cpu_to_be32(commit_transaction->t_tid);
++	tmp->h_commit_sec = cpu_to_be64(now.tv_sec);
++	tmp->h_commit_nsec = cpu_to_be32(now.tv_nsec);
+ 
+ 	if (JBD2_HAS_COMPAT_FEATURE(journal,
+ 				    JBD2_FEATURE_COMPAT_CHECKSUM)) {
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index d147f0f90360..ec9cadf58227 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -168,6 +168,8 @@ struct commit_header {
+ 	unsigned char   h_chksum_size;
+ 	unsigned char 	h_padding[2];
+ 	__be32 		h_chksum[JBD2_CHECKSUM_BYTES];
++	__be64		h_commit_sec;
++	__be32		h_commit_nsec;
+ };
+ 
+ /*

commit 7ad72ca60b6be3c79f90a81ce5883e12a2c6e667
+Author: Theodore Ts'o 
+Date:   Fri Jul 11 19:27:31 2008 -0400
+
+    ext4: Remove unused variable from ext4_show_options
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 02bf24343979..588cfb408642 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -671,7 +671,6 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
+ 	unsigned long def_mount_opts;
+ 	struct super_block *sb = vfs->mnt_sb;
+ 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+-	journal_t *journal = sbi->s_journal;
+ 	struct ext4_super_block *es = sbi->s_es;
+ 
+ 	def_mount_opts = le32_to_cpu(es->s_default_mount_opts);

commit 574ca174c97f790086e3e6f2251381420ad38fd0
+Author: Theodore Ts'o 
+Date:   Fri Jul 11 19:27:31 2008 -0400
+
+    ext4: Rename read_block_bitmap() to ext4_read_block_bitmap()
+    
+    Since this a non-static function, make it be ext4 specific to avoid
+    conflicts with potentially other filesystems.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
+index c29d774abe55..ba411233cc25 100644
+--- a/fs/ext4/balloc.c
++++ b/fs/ext4/balloc.c
+@@ -295,7 +295,7 @@ static int ext4_valid_block_bitmap(struct super_block *sb,
+ 	return 0;
+ }
+ /**
+- * read_block_bitmap()
++ * ext4_read_block_bitmap()
+  * @sb:			super block
+  * @block_group:	given block group
+  *
+@@ -305,7 +305,7 @@ static int ext4_valid_block_bitmap(struct super_block *sb,
+  * Return buffer_head on success or NULL in case of failure.
+  */
+ struct buffer_head *
+-read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
++ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
+ {
+ 	struct ext4_group_desc * desc;
+ 	struct buffer_head * bh = NULL;
+@@ -693,7 +693,7 @@ void ext4_free_blocks_sb(handle_t *handle, struct super_block *sb,
+ 		count -= overflow;
+ 	}
+ 	brelse(bitmap_bh);
+-	bitmap_bh = read_block_bitmap(sb, block_group);
++	bitmap_bh = ext4_read_block_bitmap(sb, block_group);
+ 	if (!bitmap_bh)
+ 		goto error_return;
+ 	desc = ext4_get_group_desc (sb, block_group, &gd_bh);
+@@ -1733,7 +1733,7 @@ ext4_fsblk_t ext4_new_blocks_old(handle_t *handle, struct inode *inode,
+ 		my_rsv = NULL;
+ 
+ 	if (free_blocks > 0) {
+-		bitmap_bh = read_block_bitmap(sb, group_no);
++		bitmap_bh = ext4_read_block_bitmap(sb, group_no);
+ 		if (!bitmap_bh)
+ 			goto io_error;
+ 		grp_alloc_blk = ext4_try_to_allocate_with_rsv(sb, handle,
+@@ -1769,7 +1769,7 @@ ext4_fsblk_t ext4_new_blocks_old(handle_t *handle, struct inode *inode,
+ 			continue;
+ 
+ 		brelse(bitmap_bh);
+-		bitmap_bh = read_block_bitmap(sb, group_no);
++		bitmap_bh = ext4_read_block_bitmap(sb, group_no);
+ 		if (!bitmap_bh)
+ 			goto io_error;
+ 		/*
+@@ -1985,7 +1985,7 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
+ 			continue;
+ 		desc_count += le16_to_cpu(gdp->bg_free_blocks_count);
+ 		brelse(bitmap_bh);
+-		bitmap_bh = read_block_bitmap(sb, i);
++		bitmap_bh = ext4_read_block_bitmap(sb, i);
+ 		if (bitmap_bh == NULL)
+ 			continue;
+ 
+diff --git a/fs/ext4/group.h b/fs/ext4/group.h
+index 7eb0604e7eea..c2c0a8d06d0e 100644
+--- a/fs/ext4/group.h
++++ b/fs/ext4/group.h
+@@ -13,7 +13,7 @@ extern __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 group,
+ 				   struct ext4_group_desc *gdp);
+ extern int ext4_group_desc_csum_verify(struct ext4_sb_info *sbi, __u32 group,
+ 				       struct ext4_group_desc *gdp);
+-struct buffer_head *read_block_bitmap(struct super_block *sb,
++struct buffer_head *ext4_read_block_bitmap(struct super_block *sb,
+ 				      ext4_group_t block_group);
+ extern unsigned ext4_init_block_bitmap(struct super_block *sb,
+ 				       struct buffer_head *bh,
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 11cafe14aa27..b30cc79b9fcb 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -600,7 +600,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode * dir, int mode)
+ 	/* We may have to initialize the block bitmap if it isn't already */
+ 	if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM) &&
+ 	    gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
+-		struct buffer_head *block_bh = read_block_bitmap(sb, group);
++		struct buffer_head *block_bh = ext4_read_block_bitmap(sb, group);
+ 
+ 		BUFFER_TRACE(block_bh, "get block bitmap access");
+ 		err = ext4_journal_get_write_access(handle, block_bh);
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 6d69dd92aadb..21ee6d42ee7b 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2326,7 +2326,7 @@ static int ext4_mb_init_backend(struct super_block *sb)
+ 			meta_group_info[j]->bb_bitmap =
+ 				kmalloc(sb->s_blocksize, GFP_KERNEL);
+ 			BUG_ON(meta_group_info[j]->bb_bitmap == NULL);
+-			bh = read_block_bitmap(sb, i);
++			bh = ext4_read_block_bitmap(sb, i);
+ 			BUG_ON(bh == NULL);
+ 			memcpy(meta_group_info[j]->bb_bitmap, bh->b_data,
+ 					sb->s_blocksize);
+@@ -2769,7 +2769,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
+ 
+ 
+ 	err = -EIO;
+-	bitmap_bh = read_block_bitmap(sb, ac->ac_b_ex.fe_group);
++	bitmap_bh = ext4_read_block_bitmap(sb, ac->ac_b_ex.fe_group);
+ 	if (!bitmap_bh)
+ 		goto out_err;
+ 
+@@ -3589,7 +3589,7 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
+ 	if (list_empty(&grp->bb_prealloc_list))
+ 		return 0;
+ 
+-	bitmap_bh = read_block_bitmap(sb, group);
++	bitmap_bh = ext4_read_block_bitmap(sb, group);
+ 	if (bitmap_bh == NULL) {
+ 		/* error handling here */
+ 		ext4_mb_release_desc(&e4b);
+@@ -3763,7 +3763,7 @@ void ext4_mb_discard_inode_preallocations(struct inode *inode)
+ 		err = ext4_mb_load_buddy(sb, group, &e4b);
+ 		BUG_ON(err != 0); /* error handling here */
+ 
+-		bitmap_bh = read_block_bitmap(sb, group);
++		bitmap_bh = ext4_read_block_bitmap(sb, group);
+ 		if (bitmap_bh == NULL) {
+ 			/* error handling here */
+ 			ext4_mb_release_desc(&e4b);
+@@ -4262,7 +4262,7 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
+ 		overflow = bit + count - EXT4_BLOCKS_PER_GROUP(sb);
+ 		count -= overflow;
+ 	}
+-	bitmap_bh = read_block_bitmap(sb, block_group);
++	bitmap_bh = ext4_read_block_bitmap(sb, block_group);
+ 	if (!bitmap_bh)
+ 		goto error_return;
+ 	gdp = ext4_get_group_desc(sb, block_group, &gd_bh);

commit 034772b068be62a79470d6c1b81b01fbe27793ac
+Author: Theodore Ts'o 
+Date:   Tue Jun 3 22:31:11 2008 -0400
+
+    jbd2: Fix barrier fallback code to re-lock the buffer head
+    
+    If the device doesn't support write barriers, the write is retried
+    without ordered mode.  But the buffer head needs to be re-locked or
+    submit_bh will fail with on BUG(!buffer_locked(bh)).
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index 4d99685fdce4..a2ed72f7ceee 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -168,6 +168,7 @@ static int journal_submit_commit_record(journal_t *journal,
+ 		spin_unlock(&journal->j_state_lock);
+ 
+ 		/* And try again, without the barrier */
++		lock_buffer(bh);
+ 		set_buffer_uptodate(bh);
+ 		set_buffer_dirty(bh);
+ 		ret = submit_bh(WRITE, bh);

commit cd0b6a39a1d68b61b1073662f40f747c8b728f98
+Author: Theodore Ts'o 
+Date:   Mon May 26 10:28:28 2008 -0400
+
+    ext4: Display the journal_async_commit mount option in /proc/mounts
+    
+    Cc: Andreas Dilger 
+    Cc: Girish Shilamkar 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index d01a32e8b50a..ba92c606ad9a 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -731,6 +731,8 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
+ 	}
+ 	if (test_opt(sb, BARRIER))
+ 		seq_puts(seq, ",barrier=1");
++	if (test_opt(sb, JOURNAL_ASYNC_COMMIT))
++		seq_puts(seq, ",journal_async_commit");
+ 	if (test_opt(sb, NOBH))
+ 		seq_puts(seq, ",nobh");
+ 	if (!test_opt(sb, EXTENTS))

commit 624080eded68738daee041ad64672a9d2614754f
+Author: Theodore Ts'o 
+Date:   Fri Jun 6 17:50:40 2008 -0400
+
+    jbd2: If a journal checksum error is detected, propagate the error to ext4
+    
+    If a journal checksum error is detected, the ext4 filesystem will call
+    ext4_error(), and the mount will either continue, become a read-only
+    mount, or cause a kernel panic based on the superblock flags
+    indicating the user's preference of what to do in case of filesystem
+    corruption being detected.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 09d9359c8055..d01a32e8b50a 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2189,6 +2189,29 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
+ 	    EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)) {
+ 		if (ext4_load_journal(sb, es, journal_devnum))
+ 			goto failed_mount3;
++		if (!(sb->s_flags & MS_RDONLY) &&
++		    EXT4_SB(sb)->s_journal->j_failed_commit) {
++			printk(KERN_CRIT "EXT4-fs error (device %s): "
++			       "ext4_fill_super: Journal transaction "
++			       "%u is corrupt\n", sb->s_id, 
++			       EXT4_SB(sb)->s_journal->j_failed_commit);
++			if (test_opt (sb, ERRORS_RO)) {
++				printk (KERN_CRIT
++					"Mounting filesystem read-only\n");
++				sb->s_flags |= MS_RDONLY;
++				EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
++				es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
++			}
++			if (test_opt(sb, ERRORS_PANIC)) {
++				EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
++				es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
++				ext4_commit_super(sb, es, 1);
++				printk(KERN_CRIT
++				       "EXT4-fs (device %s): mount failed\n",
++				      sb->s_id);
++				goto failed_mount4;
++			}
++		}
+ 	} else if (journal_inum) {
+ 		if (ext4_create_journal(sb, es, journal_inum))
+ 			goto failed_mount3;
+diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
+index 7199db52b2fd..058f50f65b76 100644
+--- a/fs/jbd2/recovery.c
++++ b/fs/jbd2/recovery.c
+@@ -611,9 +611,8 @@ static int do_one_pass(journal_t *journal,
+ 				chksum_err = chksum_seen = 0;
+ 
+ 				if (info->end_transaction) {
+-					printk(KERN_ERR "JBD: Transaction %u "
+-						"found to be corrupt.\n",
+-						next_commit_ID - 1);
++					journal->j_failed_commit =
++						info->end_transaction;
+ 					brelse(bh);
+ 					break;
+ 				}
+@@ -644,10 +643,8 @@ static int do_one_pass(journal_t *journal,
+ 
+ 					if (!JBD2_HAS_INCOMPAT_FEATURE(journal,
+ 					   JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)){
+-						printk(KERN_ERR
+-						       "JBD: Transaction %u "
+-						       "found to be corrupt.\n",
+-						       next_commit_ID);
++						journal->j_failed_commit =
++							next_commit_ID;
+ 						brelse(bh);
+ 						break;
+ 					}
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index 05e2b307161a..d147f0f90360 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -919,6 +919,9 @@ struct journal_s
+ 	struct proc_dir_entry	*j_proc_entry;
+ 	struct transaction_stats_s j_stats;
+ 
++	/* Failed journal commit ID */
++	unsigned int		j_failed_commit;
++
+ 	/*
+ 	 * An opaque pointer to fs-private information.  ext3 puts its
+ 	 * superblock pointer here

commit 8ea76900be3b4522396e2021260d2818a27b3a5b
+Author: Theodore Ts'o 
+Date:   Mon May 26 10:28:09 2008 -0400
+
+    jbd2: Fix memory leak when verifying checksums in the journal
+    
+    Cc: Andreas Dilger 
+    Cc: Girish Shilamkar 
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
+index 5d0405a9e7ca..7199db52b2fd 100644
+--- a/fs/jbd2/recovery.c
++++ b/fs/jbd2/recovery.c
+@@ -344,6 +344,7 @@ static int calc_chksums(journal_t *journal, struct buffer_head *bh,
+ 			*crc32_sum = crc32_be(*crc32_sum, (void *)obh->b_data,
+ 				     obh->b_size);
+ 		}
++		put_bh(obh);
+ 	}
+ 	return 0;
+ }

commit 07dc42f632e335a03c0e780805dc9dc141f83e63
+Author: Theodore Ts'o 
+Date:   Thu Mar 13 07:24:31 2008 +1100
+
+    [POWERPC] Export empty_zero_page
+    
+    Once again, this time with feeling....
+    
+                                                    - Ted
+    
+    >From c91cfaabc17f8a53807a2f31f067a732e34a1550 Mon Sep 17 00:00:00 2001
+    From: Theodore Ts'o 
+    Date: Wed, 12 Mar 2008 11:50:39 -0400
+    Subject: Export empty_zero_page
+    
+    The empty_zero_page symbol is exported by most other architectures
+    (s390, ia64, x86, um), and an upcoming ext4 patch needs it because
+    ZERO_PAGE() references empty_zero_page, and we need it to zero out an
+    unitialized extents in ext4 files.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Paul Mackerras 
+
+diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
+index 3e52122c5073..9c98424277a8 100644
+--- a/arch/powerpc/kernel/ppc_ksyms.c
++++ b/arch/powerpc/kernel/ppc_ksyms.c
+@@ -58,6 +58,7 @@ extern void program_check_exception(struct pt_regs *regs);
+ extern void single_step_exception(struct pt_regs *regs);
+ extern int sys_sigreturn(struct pt_regs *regs);
+ 
++EXPORT_SYMBOL(empty_zero_page);
+ EXPORT_SYMBOL(clear_pages);
+ EXPORT_SYMBOL(copy_page);
+ EXPORT_SYMBOL(ISA_DMA_THRESHOLD);

commit 825f1481ead4ce40671089bae7412ac3519e8caa
+Author: Theodore Ts'o 
+Date:   Fri Feb 15 15:00:38 2008 -0500
+
+    ext4: Don't use ext4_dec_count() if not needed
+    
+    The ext4_dec_count() function is only needed when dropping the i_nlink
+    count on inodes which are (or which could be) directories.  If we
+    *know* that the inode in question can't possibly be a directory, use
+    drop_nlink or clear_nlink() if we know i_nlink is 1.
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index fffd0807a01b..5a79c6b6dc69 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -2161,7 +2161,7 @@ static int ext4_unlink(struct inode * dir, struct dentry *dentry)
+ 	dir->i_ctime = dir->i_mtime = ext4_current_time(dir);
+ 	ext4_update_dx_flag(dir);
+ 	ext4_mark_inode_dirty(handle, dir);
+-	ext4_dec_count(handle, inode);
++	drop_nlink(inode);
+ 	if (!inode->i_nlink)
+ 		ext4_orphan_add(handle, inode);
+ 	inode->i_ctime = ext4_current_time(inode);
+@@ -2211,7 +2211,7 @@ static int ext4_symlink (struct inode * dir,
+ 		err = __page_symlink(inode, symname, l,
+ 				mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
+ 		if (err) {
+-			ext4_dec_count(handle, inode);
++			clear_nlink(inode);
+ 			ext4_mark_inode_dirty(handle, inode);
+ 			iput (inode);
+ 			goto out_stop;
+@@ -2404,7 +2404,7 @@ static int ext4_rename (struct inode * old_dir, struct dentry *old_dentry,
+ 		ext4_dec_count(handle, old_dir);
+ 		if (new_inode) {
+ 			/* checked empty_dir above, can't have another parent,
+-			 * ext3_dec_count() won't work for many-linked dirs */
++			 * ext4_dec_count() won't work for many-linked dirs */
+ 			new_inode->i_nlink = 0;
+ 		} else {
+ 			ext4_inc_count(handle, new_dir);

commit b052ce4c840e2da3c72ab7dadb97d1094f6e3a89
+Author: Theodore Ts'o 
+Date:   Fri Nov 2 21:53:01 2007 -0400
+
+    kbuild: fix false positive -dirty tag caused by make-kpkg
+    
+    make-kpkg modifies scripts/package/Makefile and deletes
+    scripts/package/builddeb as part of its build process.  Ignore these
+    changes so the tree isn't marked as -dirty, when it is just an
+    artifact of make-kpkg.  (make-kpkg clean restores the files to their
+    original state, and these helper scripts won't affect the final
+    compiled kernel in any way.)
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Sam Ravnborg 
+
+diff --git a/scripts/setlocalversion b/scripts/setlocalversion
+index acce8ebc5d40..52f032e409a3 100644
+--- a/scripts/setlocalversion
++++ b/scripts/setlocalversion
+@@ -17,7 +17,8 @@ if head=`git rev-parse --verify HEAD 2>/dev/null`; then
+ 
+ 	# Are there uncommitted changes?
+ 	git update-index --refresh --unmerged > /dev/null
+-	if git diff-index HEAD | read dummy; then
++	if git diff-index --name-only HEAD | grep -v "^scripts/package" \
++	    | read dummy; then
+ 		printf '%s' -dirty
+ 	fi
+ 

commit 4e7434ff028c4280bed620f28fdbf9f4d77d77ce
+Author: Theodore Ts'o 
+Date:   Fri Nov 2 21:53:00 2007 -0400
+
+    kbuild: fix scripts/setlocalversion to avoid erroneous -dirty tag
+    
+    If git's index file is out of date, and some files have been touched
+    such that their timestamp doesn't what is in the index, "git
+    diff-index HEAD" may show that a particular file is dirty, when in
+    fact it really isn't.  Running "git update-index" will update the
+    index to avoid these false positives.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Sam Ravnborg 
+
+diff --git a/scripts/setlocalversion b/scripts/setlocalversion
+index 1b31da843672..acce8ebc5d40 100644
+--- a/scripts/setlocalversion
++++ b/scripts/setlocalversion
+@@ -16,6 +16,7 @@ if head=`git rev-parse --verify HEAD 2>/dev/null`; then
+ 	fi
+ 
+ 	# Are there uncommitted changes?
++	git update-index --refresh --unmerged > /dev/null
+ 	if git diff-index HEAD | read dummy; then
+ 		printf '%s' -dirty
+ 	fi

commit d882421f4e08ddf0a94245cdbe516db260aa6f41
+Author: Theodore Ts'o 
+Date:   Fri Nov 2 21:52:59 2007 -0400
+
+    kbuild: change CONFIG_LOCALVERSION_AUTO to use a git-describe-ish format
+    
+    Change the automatic local version to have the form -nnnnn-gSHA1SUMID,
+    where 'nnnnn' is the number of commits since the last tag (i.e.,
+    2.6.21-rc7).  This makes it much more likely that the package names created
+    for the kernel will look "newer" to a package manager.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Sam Ravnborg 
+
+diff --git a/scripts/setlocalversion b/scripts/setlocalversion
+index a80d6ea8a5bf..1b31da843672 100644
+--- a/scripts/setlocalversion
++++ b/scripts/setlocalversion
+@@ -12,7 +12,7 @@ cd "${1:-.}" || usage
+ if head=`git rev-parse --verify HEAD 2>/dev/null`; then
+ 	# Do we have an untagged version?
+ 	if git name-rev --tags HEAD | grep -E '^HEAD[[:space:]]+(.*~[0-9]*|undefined)$' > /dev/null; then
+-		printf '%s%s' -g `echo "$head" | cut -c1-8`
++	        git describe | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'
+ 	fi
+ 
+ 	# Are there uncommitted changes?

commit 8232fd625217dc641ed05dd238a8bb5c82828082
+Author: Theodore Ts'o 
+Date:   Mon Nov 26 20:42:19 2007 +0100
+
+    x86: export the symbol empty_zero_page on the 32-bit x86 architecture
+    
+    The latest KVM driver wants to use the empty_zero_page symbol, and it's
+    not exported in 32-bit x86 (although it is exported by x86_64, s390, and
+    uml architectures).
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: tglx@linutronix.de
+    Cc: linux-kernel@vger.kernel.com
+    Cc: kvm-devel@lists.sourceforge.net
+    Signed-off-by: Thomas Gleixner 
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/x86/kernel/i386_ksyms_32.c b/arch/x86/kernel/i386_ksyms_32.c
+index edd39ccf139e..02112fcc0de7 100644
+--- a/arch/x86/kernel/i386_ksyms_32.c
++++ b/arch/x86/kernel/i386_ksyms_32.c
+@@ -2,6 +2,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ EXPORT_SYMBOL(__down_failed);
+ EXPORT_SYMBOL(__down_failed_interruptible);
+@@ -29,3 +30,4 @@ EXPORT_SYMBOL(__read_lock_failed);
+ #endif
+ 
+ EXPORT_SYMBOL(csum_partial);
++EXPORT_SYMBOL(empty_zero_page);

commit 436bd75e47cf804dfe89f805106bb53ff577e99a
+Author: Theodore Ts'o 
+Date:   Thu May 31 12:43:28 2007 -0400
+
+    Define/reserve new ext4 superblock fields
+    
+    Signed-off-by: "Theodore Ts'o" 
+
+diff --git a/include/linux/ext4_fs.h b/include/linux/ext4_fs.h
+index 14886847a04c..de1f9f78625a 100644
+--- a/include/linux/ext4_fs.h
++++ b/include/linux/ext4_fs.h
+@@ -513,7 +513,14 @@ struct ext4_super_block {
+ /*150*/	__le32	s_blocks_count_hi;	/* Blocks count */
+ 	__le32	s_r_blocks_count_hi;	/* Reserved blocks count */
+ 	__le32	s_free_blocks_count_hi;	/* Free blocks count */
+-	__u32	s_reserved[169];	/* Padding to the end of the block */
++	__u16	s_min_extra_isize;	/* All inodes have at least # bytes */
++	__u16	s_want_extra_isize; 	/* New inodes should reserve # bytes */
++	__u32	s_flags;		/* Miscellaneous flags */
++	__u16   s_raid_stride;		/* RAID stride */
++	__u16   s_mmp_interval;         /* # seconds to wait in MMP checking */
++	__u64   s_mmp_block;            /* Block for multi-mount protection */
++	__u32   s_raid_stripe_width;    /* blocks on all data disks (N*stride)*/
++	__u32   s_reserved[163];        /* Padding to the end of the block */
+ };
+ 
+ #ifdef __KERNEL__

commit 34f5a39899f3f3e815da64f48ddb72942d86c366
+Author: Theodore Ts'o 
+Date:   Sat Feb 10 01:45:24 2007 -0800
+
+    [PATCH] Add TAINT_USER and ability to set taint flags from userspace
+    
+    Allow taint flags to be set from userspace by writing to
+    /proc/sys/kernel/tainted, and add a new taint flag, TAINT_USER, to be used
+    when userspace has potentially done something dangerous that might
+    compromise the kernel.  This will allow support personnel to ask further
+    questions about what may have caused the user taint flag to have been set.
+    
+    For example, they might examine the logs of the realtime JVM to see if the
+    Java program has used the really silly, stupid, dangerous, and
+    completely-non-portable direct access to physical memory feature which MUST
+    be implemented according to the Real-Time Specification for Java (RTSJ).
+    Sigh.  What were those silly people at Sun thinking?
+    
+    [akpm@osdl.org: build fix]
+    [bunk@stusta.de: cleanup]
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Adrian Bunk 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/kernel.h b/include/linux/kernel.h
+index 63fb18dcac30..e1a429ada97f 100644
+--- a/include/linux/kernel.h
++++ b/include/linux/kernel.h
+@@ -200,6 +200,7 @@ extern enum system_states {
+ #define TAINT_FORCED_RMMOD		(1<<3)
+ #define TAINT_MACHINE_CHECK		(1<<4)
+ #define TAINT_BAD_PAGE			(1<<5)
++#define TAINT_USER			(1<<6)
+ 
+ extern void dump_stack(void);
+ 
+diff --git a/kernel/panic.c b/kernel/panic.c
+index 525e365f7239..623d1828259a 100644
+--- a/kernel/panic.c
++++ b/kernel/panic.c
+@@ -150,6 +150,7 @@ EXPORT_SYMBOL(panic);
+  *  'R' - User forced a module unload.
+  *  'M' - Machine had a machine check experience.
+  *  'B' - System has hit bad_page.
++ *  'U' - Userspace-defined naughtiness.
+  *
+  *	The string is overwritten by the next call to print_taint().
+  */
+@@ -158,13 +159,14 @@ const char *print_tainted(void)
+ {
+ 	static char buf[20];
+ 	if (tainted) {
+-		snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c",
++		snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c%c",
+ 			tainted & TAINT_PROPRIETARY_MODULE ? 'P' : 'G',
+ 			tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
+ 			tainted & TAINT_UNSAFE_SMP ? 'S' : ' ',
+ 			tainted & TAINT_FORCED_RMMOD ? 'R' : ' ',
+  			tainted & TAINT_MACHINE_CHECK ? 'M' : ' ',
+-			tainted & TAINT_BAD_PAGE ? 'B' : ' ');
++			tainted & TAINT_BAD_PAGE ? 'B' : ' ',
++			tainted & TAINT_USER ? 'U' : ' ');
+ 	}
+ 	else
+ 		snprintf(buf, sizeof(buf), "Not tainted");
+diff --git a/kernel/sysctl.c b/kernel/sysctl.c
+index 16ef870fa75a..7733ef58aaca 100644
+--- a/kernel/sysctl.c
++++ b/kernel/sysctl.c
+@@ -151,6 +151,8 @@ static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
+ #ifdef CONFIG_PROC_SYSCTL
+ static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp,
+ 		  void __user *buffer, size_t *lenp, loff_t *ppos);
++static int proc_dointvec_taint(ctl_table *table, int write, struct file *filp,
++			       void __user *buffer, size_t *lenp, loff_t *ppos);
+ #endif
+ 
+ static ctl_table root_table[];
+@@ -174,6 +176,7 @@ extern ctl_table inotify_table[];
+ int sysctl_legacy_va_layout;
+ #endif
+ 
++
+ static void *get_uts(ctl_table *table, int write)
+ {
+ 	char *which = table->data;
+@@ -344,14 +347,16 @@ static ctl_table kern_table[] = {
+ 		.proc_handler	= &proc_dostring,
+ 		.strategy	= &sysctl_string,
+ 	},
++#ifdef CONFIG_PROC_SYSCTL
+ 	{
+ 		.ctl_name	= KERN_TAINTED,
+ 		.procname	= "tainted",
+ 		.data		= &tainted,
+ 		.maxlen		= sizeof(int),
+-		.mode		= 0444,
+-		.proc_handler	= &proc_dointvec,
++		.mode		= 0644,
++		.proc_handler	= &proc_dointvec_taint,
+ 	},
++#endif
+ 	{
+ 		.ctl_name	= KERN_CAP_BSET,
+ 		.procname	= "cap-bound",
+@@ -1927,6 +1932,7 @@ int proc_dointvec(ctl_table *table, int write, struct file *filp,
+ 
+ #define OP_SET	0
+ #define OP_AND	1
++#define OP_OR	2
+ 
+ static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
+ 				      int *valp,
+@@ -1938,6 +1944,7 @@ static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
+ 		switch(op) {
+ 		case OP_SET:	*valp = val; break;
+ 		case OP_AND:	*valp &= val; break;
++		case OP_OR:	*valp |= val; break;
+ 		}
+ 	} else {
+ 		int val = *valp;
+@@ -1970,6 +1977,22 @@ int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
+ 				do_proc_dointvec_bset_conv,&op);
+ }
+ 
++/*
++ *	Taint values can only be increased
++ */
++static int proc_dointvec_taint(ctl_table *table, int write, struct file *filp,
++			       void __user *buffer, size_t *lenp, loff_t *ppos)
++{
++	int op;
++
++	if (!capable(CAP_SYS_ADMIN))
++		return -EPERM;
++
++	op = OP_OR;
++	return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
++				do_proc_dointvec_bset_conv,&op);
++}
++
+ struct do_proc_dointvec_minmax_conv_param {
+ 	int *min;
+ 	int *max;

commit 825f9075d74028d11d7f5932f04e1b5db3022b51
+Author: Theodore Ts'o 
+Date:   Wed Sep 27 01:50:32 2006 -0700
+
+    [GFS2] inode-diet: Eliminate i_blksize from the inode structure
+    
+    This eliminates the i_blksize field from struct inode.  Filesystems that want
+    to provide a per-inode st_blksize can do so by providing their own getattr
+    routine instead of using the generic_fillattr() function.
+    
+    Note that some filesystems were providing pretty much random (and incorrect)
+    values for i_blksize.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Steven Whitehouse 
+    Signed-off-by: Andrew Morton 
+
+diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
+index 784d145058cb..57a4c8b68587 100644
+--- a/fs/gfs2/inode.c
++++ b/fs/gfs2/inode.c
+@@ -72,7 +72,6 @@ void gfs2_inode_attr_in(struct gfs2_inode *ip)
+ 	inode->i_atime.tv_nsec = 0;
+ 	inode->i_mtime.tv_nsec = 0;
+ 	inode->i_ctime.tv_nsec = 0;
+-	inode->i_blksize = PAGE_SIZE;
+ 	inode->i_blocks = di->di_blocks <<
+ 		(GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT);
+ 

commit bba9dfd83587017de1c55a94c077983e0dfa0251
+Author: Theodore Ts'o 
+Date:   Wed Sep 27 01:50:31 2006 -0700
+
+    [GFS2] inode_diet: Replace inode.u.generic_ip with inode.i_private (gfs)
+    
+    The following patches reduce the size of the VFS inode structure by 28 bytes
+    on a UP x86.  (It would be more on an x86_64 system).  This is a 10% reduction
+    in the inode size on a UP kernel that is configured in a production mode
+    (i.e., with no spinlock or other debugging functions enabled; if you want to
+    save memory taken up by in-core inodes, the first thing you should do is
+    disable the debugging options; they are responsible for a huge amount of bloat
+    in the VFS inode structure).
+    
+    This patch:
+    
+    The filesystem or device-specific pointer in the inode is inside a union,
+    which is pretty pointless given that all 30+ users of this field have been
+    using the void pointer.  Get rid of the union and rename it to i_private, with
+    a comment to explain who is allowed to use the void pointer.  This is just a
+    cleanup, but it allows us to reuse the union 'u' for something something where
+    the union will actually be used.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Steven Whitehouse 
+    Signed-off-by: Andrew Morton 
+
+diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c
+index 9c3aeddc8667..ca94a837a5bb 100644
+--- a/fs/dlm/debug_fs.c
++++ b/fs/dlm/debug_fs.c
+@@ -282,7 +282,7 @@ static int rsb_open(struct inode *inode, struct file *file)
+ 		return ret;
+ 
+ 	seq = file->private_data;
+-	seq->private = inode->u.generic_ip;
++	seq->private = inode->i_private;
+ 
+ 	return 0;
+ }
+@@ -301,7 +301,7 @@ static struct file_operations rsb_fops = {
+ 
+ static int waiters_open(struct inode *inode, struct file *file)
+ {
+-	file->private_data = inode->u.generic_ip;
++	file->private_data = inode->i_private;
+ 	return 0;
+ }
+ 
+diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
+index ac9535be304f..784d145058cb 100644
+--- a/fs/gfs2/inode.c
++++ b/fs/gfs2/inode.c
+@@ -160,7 +160,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum *inum,
+ 	if (inode->i_state & I_NEW) {
+ 		struct gfs2_sbd *sdp = GFS2_SB(inode);
+ 		umode_t mode = DT2IF(type);
+-		inode->u.generic_ip = ip;
++		inode->i_private = ip;
+ 		inode->i_mode = mode;
+ 
+ 		if (S_ISREG(mode)) {
+diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
+index d3708af0a4d1..731799153187 100644
+--- a/fs/gfs2/meta_io.c
++++ b/fs/gfs2/meta_io.c
+@@ -78,7 +78,7 @@ struct inode *gfs2_aspace_get(struct gfs2_sbd *sdp)
+ 		mapping_set_gfp_mask(aspace->i_mapping, GFP_NOFS);
+ 		aspace->i_mapping->a_ops = &aspace_aops;
+ 		aspace->i_size = ~0ULL;
+-		aspace->u.generic_ip = NULL;
++		aspace->i_private = NULL;
+ 		insert_inode_hash(aspace);
+ 	}
+ 	return aspace;
+diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c
+index 8cfda6452139..06f06f7773d0 100644
+--- a/fs/gfs2/ops_super.c
++++ b/fs/gfs2/ops_super.c
+@@ -53,7 +53,7 @@ static int gfs2_write_inode(struct inode *inode, int sync)
+ 	struct gfs2_inode *ip = GFS2_I(inode);
+ 
+ 	/* Check this is a "normal" inode */
+-	if (inode->u.generic_ip) {
++	if (inode->i_private) {
+ 		if (current->flags & PF_MEMALLOC)
+ 			return 0;
+ 		if (sync)
+@@ -280,7 +280,7 @@ static void gfs2_clear_inode(struct inode *inode)
+ 	 * serves to contain an address space (see rgrp.c, meta_io.c)
+ 	 * which therefore doesn't have its own glocks.
+ 	 */
+-	if (inode->u.generic_ip) {
++	if (inode->i_private) {
+ 		struct gfs2_inode *ip = GFS2_I(inode);
+ 		gfs2_glock_inode_squish(inode);
+ 		gfs2_assert(inode->i_sb->s_fs_info, ip->i_gl->gl_state == LM_ST_UNLOCKED);
+@@ -381,7 +381,7 @@ static void gfs2_delete_inode(struct inode *inode)
+ 	struct gfs2_holder gh;
+ 	int error;
+ 
+-	if (!inode->u.generic_ip)
++	if (!inode->i_private)
+ 		goto out;
+ 
+ 	error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &gh);

commit ba52de123d454b57369f291348266d86f4b35070
+Author: Theodore Ts'o 
+Date:   Wed Sep 27 01:50:49 2006 -0700
+
+    [PATCH] inode-diet: Eliminate i_blksize from the inode structure
+    
+    This eliminates the i_blksize field from struct inode.  Filesystems that want
+    to provide a per-inode st_blksize can do so by providing their own getattr
+    routine instead of using the generic_fillattr() function.
+    
+    Note that some filesystems were providing pretty much random (and incorrect)
+    values for i_blksize.
+    
+    [bunk@stusta.de: cleanup]
+    [akpm@osdl.org: generic_fillattr() fix]
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Adrian Bunk 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
+index b837f12a84ae..3950ddccb2c8 100644
+--- a/arch/powerpc/platforms/cell/spufs/inode.c
++++ b/arch/powerpc/platforms/cell/spufs/inode.c
+@@ -82,7 +82,6 @@ spufs_new_inode(struct super_block *sb, int mode)
+ 	inode->i_mode = mode;
+ 	inode->i_uid = current->fsuid;
+ 	inode->i_gid = current->fsgid;
+-	inode->i_blksize = PAGE_CACHE_SIZE;
+ 	inode->i_blocks = 0;
+ 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ out:
+diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
+index 8735024d235b..813fc21358f9 100644
+--- a/arch/s390/hypfs/inode.c
++++ b/arch/s390/hypfs/inode.c
+@@ -91,7 +91,6 @@ static struct inode *hypfs_make_inode(struct super_block *sb, int mode)
+ 		ret->i_mode = mode;
+ 		ret->i_uid = hypfs_info->uid;
+ 		ret->i_gid = hypfs_info->gid;
+-		ret->i_blksize = PAGE_CACHE_SIZE;
+ 		ret->i_blocks = 0;
+ 		ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
+ 		if (mode & S_IFDIR)
+diff --git a/drivers/block/loop.c b/drivers/block/loop.c
+index 7b3b94ddddcc..c774121684d7 100644
+--- a/drivers/block/loop.c
++++ b/drivers/block/loop.c
+@@ -662,7 +662,8 @@ static void do_loop_switch(struct loop_device *lo, struct switch_request *p)
+ 
+ 	mapping_set_gfp_mask(old_file->f_mapping, lo->old_gfp_mask);
+ 	lo->lo_backing_file = file;
+-	lo->lo_blocksize = mapping->host->i_blksize;
++	lo->lo_blocksize = S_ISBLK(mapping->host->i_mode) ?
++		mapping->host->i_bdev->bd_block_size : PAGE_SIZE;
+ 	lo->old_gfp_mask = mapping_gfp_mask(mapping);
+ 	mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
+ 	complete(&p->wait);
+@@ -794,7 +795,9 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
+ 		if (!(lo_flags & LO_FLAGS_USE_AOPS) && !file->f_op->write)
+ 			lo_flags |= LO_FLAGS_READ_ONLY;
+ 
+-		lo_blocksize = inode->i_blksize;
++		lo_blocksize = S_ISBLK(inode->i_mode) ?
++			inode->i_bdev->bd_block_size : PAGE_SIZE;
++
+ 		error = 0;
+ 	} else {
+ 		goto out_putf;
+diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
+index 055cdd089b28..c8a8af0fe471 100644
+--- a/drivers/infiniband/hw/ipath/ipath_fs.c
++++ b/drivers/infiniband/hw/ipath/ipath_fs.c
+@@ -61,7 +61,6 @@ static int ipathfs_mknod(struct inode *dir, struct dentry *dentry,
+ 	inode->i_mode = mode;
+ 	inode->i_uid = 0;
+ 	inode->i_gid = 0;
+-	inode->i_blksize = PAGE_CACHE_SIZE;
+ 	inode->i_blocks = 0;
+ 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ 	inode->i_private = data;
+diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c
+index 9ea6bd0ddc35..2dd1b57b0ba4 100644
+--- a/drivers/isdn/capi/capifs.c
++++ b/drivers/isdn/capi/capifs.c
+@@ -104,7 +104,6 @@ capifs_fill_super(struct super_block *s, void *data, int silent)
+ 	inode->i_ino = 1;
+ 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ 	inode->i_blocks = 0;
+-	inode->i_blksize = 1024;
+ 	inode->i_uid = inode->i_gid = 0;
+ 	inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
+ 	inode->i_op = &simple_dir_inode_operations;
+@@ -149,7 +148,6 @@ void capifs_new_ncci(unsigned int number, dev_t device)
+ 	if (!inode)
+ 		return;
+ 	inode->i_ino = number+2;
+-	inode->i_blksize = 1024;
+ 	inode->i_uid = config.setuid ? config.uid : current->fsuid;
+ 	inode->i_gid = config.setgid ? config.gid : current->fsgid;
+ 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c
+index 0e909b617226..b99dc507de2e 100644
+--- a/drivers/misc/ibmasm/ibmasmfs.c
++++ b/drivers/misc/ibmasm/ibmasmfs.c
+@@ -147,7 +147,6 @@ static struct inode *ibmasmfs_make_inode(struct super_block *sb, int mode)
+ 	if (ret) {
+ 		ret->i_mode = mode;
+ 		ret->i_uid = ret->i_gid = 0;
+-		ret->i_blksize = PAGE_CACHE_SIZE;
+ 		ret->i_blocks = 0;
+ 		ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
+ 	}
+diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c
+index deb37354785b..5756401fb15b 100644
+--- a/drivers/oprofile/oprofilefs.c
++++ b/drivers/oprofile/oprofilefs.c
+@@ -31,7 +31,6 @@ static struct inode * oprofilefs_get_inode(struct super_block * sb, int mode)
+ 		inode->i_mode = mode;
+ 		inode->i_uid = 0;
+ 		inode->i_gid = 0;
+-		inode->i_blksize = PAGE_CACHE_SIZE;
+ 		inode->i_blocks = 0;
+ 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ 	}
+diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
+index 482f253085e5..58b4b1012120 100644
+--- a/drivers/usb/core/inode.c
++++ b/drivers/usb/core/inode.c
+@@ -249,7 +249,6 @@ static struct inode *usbfs_get_inode (struct super_block *sb, int mode, dev_t de
+ 		inode->i_mode = mode;
+ 		inode->i_uid = current->fsuid;
+ 		inode->i_gid = current->fsgid;
+-		inode->i_blksize = PAGE_CACHE_SIZE;
+ 		inode->i_blocks = 0;
+ 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ 		switch (mode & S_IFMT) {
+diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
+index ffaa8c1afad8..2a7162d89799 100644
+--- a/drivers/usb/gadget/inode.c
++++ b/drivers/usb/gadget/inode.c
+@@ -1966,7 +1966,6 @@ gadgetfs_make_inode (struct super_block *sb,
+ 		inode->i_mode = mode;
+ 		inode->i_uid = default_uid;
+ 		inode->i_gid = default_gid;
+-		inode->i_blksize = PAGE_CACHE_SIZE;
+ 		inode->i_blocks = 0;
+ 		inode->i_atime = inode->i_mtime = inode->i_ctime
+ 				= CURRENT_TIME;
+diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
+index eae50c9d6dc4..7a7ec2d1d2f4 100644
+--- a/fs/9p/vfs_inode.c
++++ b/fs/9p/vfs_inode.c
+@@ -204,7 +204,6 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
+ 		inode->i_mode = mode;
+ 		inode->i_uid = current->fsuid;
+ 		inode->i_gid = current->fsgid;
+-		inode->i_blksize = sb->s_blocksize;
+ 		inode->i_blocks = 0;
+ 		inode->i_rdev = 0;
+ 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+@@ -950,9 +949,8 @@ v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode,
+ 
+ 	inode->i_size = stat->length;
+ 
+-	inode->i_blksize = sb->s_blocksize;
+ 	inode->i_blocks =
+-	    (inode->i_size + inode->i_blksize - 1) >> sb->s_blocksize_bits;
++	    (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+ }
+ 
+ /**
+diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c
+index 534f3eecc985..7e7a04be1278 100644
+--- a/fs/adfs/inode.c
++++ b/fs/adfs/inode.c
+@@ -269,7 +269,6 @@ adfs_iget(struct super_block *sb, struct object_info *obj)
+ 	inode->i_ino	 = obj->file_id;
+ 	inode->i_size	 = obj->size;
+ 	inode->i_nlink	 = 2;
+-	inode->i_blksize = PAGE_SIZE;
+ 	inode->i_blocks	 = (inode->i_size + sb->s_blocksize - 1) >>
+ 			    sb->s_blocksize_bits;
+ 
+diff --git a/fs/afs/inode.c b/fs/afs/inode.c
+index 4ebb30a50ed5..6f37754906c2 100644
+--- a/fs/afs/inode.c
++++ b/fs/afs/inode.c
+@@ -72,7 +72,6 @@ static int afs_inode_map_status(struct afs_vnode *vnode)
+ 	inode->i_ctime.tv_sec	= vnode->status.mtime_server;
+ 	inode->i_ctime.tv_nsec	= 0;
+ 	inode->i_atime		= inode->i_mtime = inode->i_ctime;
+-	inode->i_blksize	= PAGE_CACHE_SIZE;
+ 	inode->i_blocks		= 0;
+ 	inode->i_version	= vnode->fid.unique;
+ 	inode->i_mapping->a_ops	= &afs_fs_aops;
+diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
+index d39d2acd9b38..2c9759baad61 100644
+--- a/fs/autofs/inode.c
++++ b/fs/autofs/inode.c
+@@ -216,7 +216,6 @@ static void autofs_read_inode(struct inode *inode)
+ 	inode->i_nlink = 2;
+ 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ 	inode->i_blocks = 0;
+-	inode->i_blksize = 1024;
+ 
+ 	if ( ino == AUTOFS_ROOT_INO ) {
+ 		inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
+diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
+index 11a6a9ae51b7..800ce876caec 100644
+--- a/fs/autofs4/inode.c
++++ b/fs/autofs4/inode.c
+@@ -447,7 +447,6 @@ struct inode *autofs4_get_inode(struct super_block *sb,
+ 		inode->i_uid = 0;
+ 		inode->i_gid = 0;
+ 	}
+-	inode->i_blksize = PAGE_CACHE_SIZE;
+ 	inode->i_blocks = 0;
+ 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ 
+diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
+index f6676fbe9484..57020c7a7e65 100644
+--- a/fs/befs/linuxvfs.c
++++ b/fs/befs/linuxvfs.c
+@@ -365,7 +365,6 @@ befs_read_inode(struct inode *inode)
+ 	inode->i_mtime.tv_nsec = 0;   /* lower 16 bits are not a time */	
+ 	inode->i_ctime = inode->i_mtime;
+ 	inode->i_atime = inode->i_mtime;
+-	inode->i_blksize = befs_sb->block_size;
+ 
+ 	befs_ino->i_inode_num = fsrun_to_cpu(sb, raw_inode->inode_num);
+ 	befs_ino->i_parent = fsrun_to_cpu(sb, raw_inode->parent);
+diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
+index 26fad9621738..dcf04cb13283 100644
+--- a/fs/bfs/dir.c
++++ b/fs/bfs/dir.c
+@@ -102,7 +102,7 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode,
+ 	inode->i_uid = current->fsuid;
+ 	inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
+ 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
+-	inode->i_blocks = inode->i_blksize = 0;
++	inode->i_blocks = 0;
+ 	inode->i_op = &bfs_file_inops;
+ 	inode->i_fop = &bfs_file_operations;
+ 	inode->i_mapping->a_ops = &bfs_aops;
+diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
+index 8fc2e8e49dbe..ed27ffb3459e 100644
+--- a/fs/bfs/inode.c
++++ b/fs/bfs/inode.c
+@@ -76,7 +76,6 @@ static void bfs_read_inode(struct inode * inode)
+ 	inode->i_size = BFS_FILESIZE(di);
+ 	inode->i_blocks = BFS_FILEBLOCKS(di);
+         if (inode->i_size || inode->i_blocks) dprintf("Registered inode with %lld size, %ld blocks\n", inode->i_size, inode->i_blocks);
+-	inode->i_blksize = PAGE_SIZE;
+ 	inode->i_atime.tv_sec =  le32_to_cpu(di->i_atime);
+ 	inode->i_mtime.tv_sec =  le32_to_cpu(di->i_mtime);
+ 	inode->i_ctime.tv_sec =  le32_to_cpu(di->i_ctime);
+diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
+index 6759b9839ce8..66ba137f8661 100644
+--- a/fs/binfmt_misc.c
++++ b/fs/binfmt_misc.c
+@@ -507,7 +507,6 @@ static struct inode *bm_get_inode(struct super_block *sb, int mode)
+ 		inode->i_mode = mode;
+ 		inode->i_uid = 0;
+ 		inode->i_gid = 0;
+-		inode->i_blksize = PAGE_CACHE_SIZE;
+ 		inode->i_blocks = 0;
+ 		inode->i_atime = inode->i_mtime = inode->i_ctime =
+ 			current_fs_time(inode->i_sb);
+diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
+index 4197a5043f13..22bcf4d7e7ae 100644
+--- a/fs/cifs/cifsfs.c
++++ b/fs/cifs/cifsfs.c
+@@ -253,7 +253,6 @@ cifs_alloc_inode(struct super_block *sb)
+ 	file data or metadata */
+ 	cifs_inode->clientCanCacheRead = FALSE;
+ 	cifs_inode->clientCanCacheAll = FALSE;
+-	cifs_inode->vfs_inode.i_blksize = CIFS_MAX_MSGSIZE;
+ 	cifs_inode->vfs_inode.i_blkbits = 14;  /* 2**14 = CIFS_MAX_MSGSIZE */
+ 	cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME;
+ 	INIT_LIST_HEAD(&cifs_inode->openFileList);
+diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
+index 9aeb58a7d369..b27b34537bf2 100644
+--- a/fs/cifs/readdir.c
++++ b/fs/cifs/readdir.c
+@@ -216,10 +216,9 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
+ 
+ 	if (allocation_size < end_of_file)
+ 		cFYI(1, ("May be sparse file, allocation less than file size"));
+-	cFYI(1, ("File Size %ld and blocks %llu and blocksize %ld",
++	cFYI(1, ("File Size %ld and blocks %llu",
+ 		(unsigned long)tmp_inode->i_size,
+-		(unsigned long long)tmp_inode->i_blocks,
+-		tmp_inode->i_blksize));
++		(unsigned long long)tmp_inode->i_blocks));
+ 	if (S_ISREG(tmp_inode->i_mode)) {
+ 		cFYI(1, ("File inode"));
+ 		tmp_inode->i_op = &cifs_file_inode_ops;
+diff --git a/fs/coda/coda_linux.c b/fs/coda/coda_linux.c
+index 5597080cb811..95a54253c047 100644
+--- a/fs/coda/coda_linux.c
++++ b/fs/coda/coda_linux.c
+@@ -110,8 +110,6 @@ void coda_vattr_to_iattr(struct inode *inode, struct coda_vattr *attr)
+ 	        inode->i_nlink = attr->va_nlink;
+ 	if (attr->va_size != -1)
+ 	        inode->i_size = attr->va_size;
+-	if (attr->va_blocksize != -1)
+-		inode->i_blksize = attr->va_blocksize;
+ 	if (attr->va_size != -1)
+ 		inode->i_blocks = (attr->va_size + 511) >> 9;
+ 	if (attr->va_atime.tv_sec != -1) 
+diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c
+index 5047e6a7581e..fb18917954a9 100644
+--- a/fs/configfs/inode.c
++++ b/fs/configfs/inode.c
+@@ -135,7 +135,6 @@ struct inode * configfs_new_inode(mode_t mode, struct configfs_dirent * sd)
+ {
+ 	struct inode * inode = new_inode(configfs_sb);
+ 	if (inode) {
+-		inode->i_blksize = PAGE_CACHE_SIZE;
+ 		inode->i_blocks = 0;
+ 		inode->i_mapping->a_ops = &configfs_aops;
+ 		inode->i_mapping->backing_dev_info = &configfs_backing_dev_info;
+diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
+index d09b6777c41a..ad96b6990715 100644
+--- a/fs/cramfs/inode.c
++++ b/fs/cramfs/inode.c
+@@ -73,7 +73,6 @@ static int cramfs_iget5_set(struct inode *inode, void *opaque)
+ 	inode->i_uid = cramfs_inode->uid;
+ 	inode->i_size = cramfs_inode->size;
+ 	inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1;
+-	inode->i_blksize = PAGE_CACHE_SIZE;
+ 	inode->i_gid = cramfs_inode->gid;
+ 	/* Struct copy intentional */
+ 	inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime;
+diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
+index 717f4821ed02..269e649e6dc6 100644
+--- a/fs/debugfs/inode.c
++++ b/fs/debugfs/inode.c
+@@ -40,7 +40,6 @@ static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t d
+ 		inode->i_mode = mode;
+ 		inode->i_uid = 0;
+ 		inode->i_gid = 0;
+-		inode->i_blksize = PAGE_CACHE_SIZE;
+ 		inode->i_blocks = 0;
+ 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ 		switch (mode & S_IFMT) {
+diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
+index 5bf06a10dddf..5f7b5a6025bf 100644
+--- a/fs/devpts/inode.c
++++ b/fs/devpts/inode.c
+@@ -113,7 +113,6 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
+ 	inode->i_ino = 1;
+ 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ 	inode->i_blocks = 0;
+-	inode->i_blksize = 1024;
+ 	inode->i_uid = inode->i_gid = 0;
+ 	inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
+ 	inode->i_op = &simple_dir_inode_operations;
+@@ -172,7 +171,6 @@ int devpts_pty_new(struct tty_struct *tty)
+ 		return -ENOMEM;
+ 
+ 	inode->i_ino = number+2;
+-	inode->i_blksize = 1024;
+ 	inode->i_uid = config.setuid ? config.uid : current->fsuid;
+ 	inode->i_gid = config.setgid ? config.gid : current->fsgid;
+ 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+diff --git a/fs/eventpoll.c b/fs/eventpoll.c
+index 3a3567433b92..8d544334bcd2 100644
+--- a/fs/eventpoll.c
++++ b/fs/eventpoll.c
+@@ -1590,7 +1590,6 @@ static struct inode *ep_eventpoll_inode(void)
+ 	inode->i_uid = current->fsuid;
+ 	inode->i_gid = current->fsgid;
+ 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+-	inode->i_blksize = PAGE_SIZE;
+ 	return inode;
+ 
+ eexit_1:
+diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
+index 695f69ccf908..2cb545bf0f3c 100644
+--- a/fs/ext2/ialloc.c
++++ b/fs/ext2/ialloc.c
+@@ -574,7 +574,6 @@ struct inode *ext2_new_inode(struct inode *dir, int mode)
+ 	inode->i_mode = mode;
+ 
+ 	inode->i_ino = ino;
+-	inode->i_blksize = PAGE_SIZE;	/* This is the optimal IO size (for stat), not the fs block size */
+ 	inode->i_blocks = 0;
+ 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
+ 	memset(ei->i_data, 0, sizeof(ei->i_data));
+diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
+index fb4d3220eb8d..dd4e14c221e0 100644
+--- a/fs/ext2/inode.c
++++ b/fs/ext2/inode.c
+@@ -1094,7 +1094,6 @@ void ext2_read_inode (struct inode * inode)
+ 		brelse (bh);
+ 		goto bad_inode;
+ 	}
+-	inode->i_blksize = PAGE_SIZE;	/* This is the optimal IO size (for stat), not the fs block size */
+ 	inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);
+ 	ei->i_flags = le32_to_cpu(raw_inode->i_flags);
+ 	ei->i_faddr = le32_to_cpu(raw_inode->i_faddr);
+diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
+index 1e4ded8aa3cd..e45dbd651736 100644
+--- a/fs/ext3/ialloc.c
++++ b/fs/ext3/ialloc.c
+@@ -559,7 +559,6 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode)
+ 
+ 	inode->i_ino = ino;
+ 	/* This is the optimal IO size (for stat), not the fs block size */
+-	inode->i_blksize = PAGE_SIZE;
+ 	inode->i_blocks = 0;
+ 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
+ 
+diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
+index c9fc15f8b609..dcf4f1dd108b 100644
+--- a/fs/ext3/inode.c
++++ b/fs/ext3/inode.c
+@@ -2632,9 +2632,6 @@ void ext3_read_inode(struct inode * inode)
+ 		 * recovery code: that's fine, we're about to complete
+ 		 * the process of deleting those. */
+ 	}
+-	inode->i_blksize = PAGE_SIZE;	/* This is the optimal IO size
+-					 * (for stat), not the fs block
+-					 * size */  
+ 	inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);
+ 	ei->i_flags = le32_to_cpu(raw_inode->i_flags);
+ #ifdef EXT3_FRAGMENTS
+diff --git a/fs/fat/inode.c b/fs/fat/inode.c
+index e1035a590664..ab96ae823753 100644
+--- a/fs/fat/inode.c
++++ b/fs/fat/inode.c
+@@ -370,8 +370,6 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
+ 			inode->i_flags |= S_IMMUTABLE;
+ 	}
+ 	MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED;
+-	/* this is as close to the truth as we can get ... */
+-	inode->i_blksize = sbi->cluster_size;
+ 	inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1))
+ 			   & ~((loff_t)sbi->cluster_size - 1)) >> 9;
+ 	inode->i_mtime.tv_sec =
+@@ -1131,7 +1129,6 @@ static int fat_read_root(struct inode *inode)
+ 		MSDOS_I(inode)->i_start = 0;
+ 		inode->i_size = sbi->dir_entries * sizeof(struct msdos_dir_entry);
+ 	}
+-	inode->i_blksize = sbi->cluster_size;
+ 	inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1))
+ 			   & ~((loff_t)sbi->cluster_size - 1)) >> 9;
+ 	MSDOS_I(inode)->i_logstart = 0;
+diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
+index 32a82ed108e4..4786d51ad3bd 100644
+--- a/fs/freevxfs/vxfs_inode.c
++++ b/fs/freevxfs/vxfs_inode.c
+@@ -239,7 +239,6 @@ vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip)
+ 	ip->i_ctime.tv_nsec = 0;
+ 	ip->i_mtime.tv_nsec = 0;
+ 
+-	ip->i_blksize = PAGE_SIZE;
+ 	ip->i_blocks = vip->vii_blocks;
+ 	ip->i_generation = vip->vii_gen;
+ 
+diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
+index 7d25092262ae..cb7cadb0b790 100644
+--- a/fs/fuse/inode.c
++++ b/fs/fuse/inode.c
+@@ -118,7 +118,6 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr)
+ 	inode->i_uid     = attr->uid;
+ 	inode->i_gid     = attr->gid;
+ 	i_size_write(inode, attr->size);
+-	inode->i_blksize = PAGE_CACHE_SIZE;
+ 	inode->i_blocks  = attr->blocks;
+ 	inode->i_atime.tv_sec   = attr->atime;
+ 	inode->i_atime.tv_nsec  = attr->atimensec;
+diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
+index 315cf44a90b2..d05641c35fc9 100644
+--- a/fs/hfs/inode.c
++++ b/fs/hfs/inode.c
+@@ -154,7 +154,6 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, int mode)
+ 	inode->i_gid = current->fsgid;
+ 	inode->i_nlink = 1;
+ 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
+-	inode->i_blksize = HFS_SB(sb)->alloc_blksz;
+ 	HFS_I(inode)->flags = 0;
+ 	HFS_I(inode)->rsrc_inode = NULL;
+ 	HFS_I(inode)->fs_blocks = 0;
+@@ -284,7 +283,6 @@ static int hfs_read_inode(struct inode *inode, void *data)
+ 	inode->i_uid = hsb->s_uid;
+ 	inode->i_gid = hsb->s_gid;
+ 	inode->i_nlink = 1;
+-	inode->i_blksize = HFS_SB(inode->i_sb)->alloc_blksz;
+ 
+ 	if (idata->key)
+ 		HFS_I(inode)->cat_key = *idata->key;
+diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
+index 924ecdef8091..0eb1a6092668 100644
+--- a/fs/hfsplus/inode.c
++++ b/fs/hfsplus/inode.c
+@@ -304,7 +304,6 @@ struct inode *hfsplus_new_inode(struct super_block *sb, int mode)
+ 	inode->i_gid = current->fsgid;
+ 	inode->i_nlink = 1;
+ 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
+-	inode->i_blksize = HFSPLUS_SB(sb).alloc_blksz;
+ 	INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
+ 	init_MUTEX(&HFSPLUS_I(inode).extents_lock);
+ 	atomic_set(&HFSPLUS_I(inode).opencnt, 0);
+@@ -407,7 +406,6 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
+ 	type = hfs_bnode_read_u16(fd->bnode, fd->entryoffset);
+ 
+ 	HFSPLUS_I(inode).dev = 0;
+-	inode->i_blksize = HFSPLUS_SB(inode->i_sb).alloc_blksz;
+ 	if (type == HFSPLUS_FOLDER) {
+ 		struct hfsplus_cat_folder *folder = &entry.folder;
+ 
+diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
+index b82e3d9c8790..322e876c35ed 100644
+--- a/fs/hostfs/hostfs_kern.c
++++ b/fs/hostfs/hostfs_kern.c
+@@ -156,7 +156,6 @@ static int read_name(struct inode *ino, char *name)
+ 	ino->i_mode = i_mode;
+ 	ino->i_nlink = i_nlink;
+ 	ino->i_size = i_size;
+-	ino->i_blksize = i_blksize;
+ 	ino->i_blocks = i_blocks;
+ 	return(0);
+ }
+diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c
+index 56f2c338c4d9..bcf6ee36e065 100644
+--- a/fs/hpfs/inode.c
++++ b/fs/hpfs/inode.c
+@@ -17,7 +17,6 @@ void hpfs_init_inode(struct inode *i)
+ 	i->i_gid = hpfs_sb(sb)->sb_gid;
+ 	i->i_mode = hpfs_sb(sb)->sb_mode;
+ 	hpfs_inode->i_conv = hpfs_sb(sb)->sb_conv;
+-	i->i_blksize = 512;
+ 	i->i_size = -1;
+ 	i->i_blocks = -1;
+ 	
+diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c
+index 3a9bdf58166f..dcb6d2e988b8 100644
+--- a/fs/hppfs/hppfs_kern.c
++++ b/fs/hppfs/hppfs_kern.c
+@@ -152,7 +152,6 @@ static void hppfs_read_inode(struct inode *ino)
+ 	ino->i_mode = proc_ino->i_mode;
+ 	ino->i_nlink = proc_ino->i_nlink;
+ 	ino->i_size = proc_ino->i_size;
+-	ino->i_blksize = proc_ino->i_blksize;
+ 	ino->i_blocks = proc_ino->i_blocks;
+ }
+ 
+diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
+index c3920c96dadf..e025a31b4c64 100644
+--- a/fs/hugetlbfs/inode.c
++++ b/fs/hugetlbfs/inode.c
+@@ -357,7 +357,6 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid,
+ 		inode->i_mode = mode;
+ 		inode->i_uid = uid;
+ 		inode->i_gid = gid;
+-		inode->i_blksize = HPAGE_SIZE;
+ 		inode->i_blocks = 0;
+ 		inode->i_mapping->a_ops = &hugetlbfs_aops;
+ 		inode->i_mapping->backing_dev_info =&hugetlbfs_backing_dev_info;
+diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
+index 10e47897bac7..4527692f432b 100644
+--- a/fs/isofs/inode.c
++++ b/fs/isofs/inode.c
+@@ -1235,7 +1235,7 @@ static void isofs_read_inode(struct inode *inode)
+ 	}
+ 	inode->i_uid = sbi->s_uid;
+ 	inode->i_gid = sbi->s_gid;
+-	inode->i_blocks = inode->i_blksize = 0;
++	inode->i_blocks = 0;
+ 
+ 	ei->i_format_parm[0] = 0;
+ 	ei->i_format_parm[1] = 0;
+@@ -1291,7 +1291,6 @@ static void isofs_read_inode(struct inode *inode)
+ 			      isonum_711 (de->ext_attr_length));
+ 
+ 	/* Set the number of blocks for stat() - should be done before RR */
+-	inode->i_blksize = PAGE_CACHE_SIZE; /* For stat() only */
+ 	inode->i_blocks  = (inode->i_size + 511) >> 9;
+ 
+ 	/*
+diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
+index 7358ef87f16b..f5cf9c93e243 100644
+--- a/fs/jffs/inode-v23.c
++++ b/fs/jffs/inode-v23.c
+@@ -364,7 +364,6 @@ jffs_new_inode(const struct inode * dir, struct jffs_raw_inode *raw_inode,
+ 	inode->i_ctime.tv_nsec = 0;
+ 	inode->i_mtime.tv_nsec = 0;
+ 	inode->i_atime.tv_nsec = 0;
+-	inode->i_blksize = PAGE_SIZE;
+ 	inode->i_blocks = (inode->i_size + 511) >> 9;
+ 
+ 	f = jffs_find_file(c, raw_inode->ino);
+@@ -1706,7 +1705,6 @@ jffs_read_inode(struct inode *inode)
+ 	inode->i_mtime.tv_nsec = 
+ 	inode->i_ctime.tv_nsec = 0;
+ 
+-	inode->i_blksize = PAGE_SIZE;
+ 	inode->i_blocks = (inode->i_size + 511) >> 9;
+ 	if (S_ISREG(inode->i_mode)) {
+ 		inode->i_op = &jffs_file_inode_operations;
+diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
+index 4780f82825d6..72d9909d95ff 100644
+--- a/fs/jffs2/fs.c
++++ b/fs/jffs2/fs.c
+@@ -263,7 +263,6 @@ void jffs2_read_inode (struct inode *inode)
+ 
+ 	inode->i_nlink = f->inocache->nlink;
+ 
+-	inode->i_blksize = PAGE_SIZE;
+ 	inode->i_blocks = (inode->i_size + 511) >> 9;
+ 
+ 	switch (inode->i_mode & S_IFMT) {
+@@ -449,7 +448,6 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i
+ 	inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
+ 	ri->atime = ri->mtime = ri->ctime = cpu_to_je32(I_SEC(inode->i_mtime));
+ 
+-	inode->i_blksize = PAGE_SIZE;
+ 	inode->i_blocks = 0;
+ 	inode->i_size = 0;
+ 
+diff --git a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c
+index 4d52593a5fc6..4c74f0944f7e 100644
+--- a/fs/jfs/jfs_extent.c
++++ b/fs/jfs/jfs_extent.c
+@@ -468,7 +468,7 @@ int extRecord(struct inode *ip, xad_t * xp)
+ int extFill(struct inode *ip, xad_t * xp)
+ {
+ 	int rc, nbperpage = JFS_SBI(ip->i_sb)->nbperpage;
+-	s64 blkno = offsetXAD(xp) >> ip->i_blksize;
++	s64 blkno = offsetXAD(xp) >> ip->i_blkbits;
+ 
+ //      assert(ISSPARSE(ip));
+ 
+diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
+index ccbe60aff83d..369d7f39c040 100644
+--- a/fs/jfs/jfs_imap.c
++++ b/fs/jfs/jfs_imap.c
+@@ -3115,7 +3115,6 @@ static int copy_from_dinode(struct dinode * dip, struct inode *ip)
+ 	ip->i_mtime.tv_nsec = le32_to_cpu(dip->di_mtime.tv_nsec);
+ 	ip->i_ctime.tv_sec = le32_to_cpu(dip->di_ctime.tv_sec);
+ 	ip->i_ctime.tv_nsec = le32_to_cpu(dip->di_ctime.tv_nsec);
+-	ip->i_blksize = ip->i_sb->s_blocksize;
+ 	ip->i_blocks = LBLK2PBLK(ip->i_sb, le64_to_cpu(dip->di_nblocks));
+ 	ip->i_generation = le32_to_cpu(dip->di_gen);
+ 
+diff --git a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c
+index 495df402916d..bffaca9ae3a2 100644
+--- a/fs/jfs/jfs_inode.c
++++ b/fs/jfs/jfs_inode.c
+@@ -115,7 +115,6 @@ struct inode *ialloc(struct inode *parent, umode_t mode)
+ 	}
+ 	jfs_inode->mode2 |= mode;
+ 
+-	inode->i_blksize = sb->s_blocksize;
+ 	inode->i_blocks = 0;
+ 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ 	jfs_inode->otime = inode->i_ctime.tv_sec;
+diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
+index e1e0a6e6ebdf..f5afc129d6b1 100644
+--- a/fs/jfs/jfs_metapage.c
++++ b/fs/jfs/jfs_metapage.c
+@@ -257,7 +257,7 @@ static sector_t metapage_get_blocks(struct inode *inode, sector_t lblock,
+ 	int rc = 0;
+ 	int xflag;
+ 	s64 xaddr;
+-	sector_t file_blocks = (inode->i_size + inode->i_blksize - 1) >>
++	sector_t file_blocks = (inode->i_size + inode->i_sb->s_blocksize - 1) >>
+ 			       inode->i_blkbits;
+ 
+ 	if (lblock >= file_blocks)
+diff --git a/fs/libfs.c b/fs/libfs.c
+index 2751793beeaa..8db5afb7b0a7 100644
+--- a/fs/libfs.c
++++ b/fs/libfs.c
+@@ -383,7 +383,6 @@ int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files
+ 		return -ENOMEM;
+ 	inode->i_mode = S_IFDIR | 0755;
+ 	inode->i_uid = inode->i_gid = 0;
+-	inode->i_blksize = PAGE_CACHE_SIZE;
+ 	inode->i_blocks = 0;
+ 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ 	inode->i_op = &simple_dir_inode_operations;
+@@ -405,7 +404,6 @@ int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files
+ 			goto out;
+ 		inode->i_mode = S_IFREG | files->mode;
+ 		inode->i_uid = inode->i_gid = 0;
+-		inode->i_blksize = PAGE_CACHE_SIZE;
+ 		inode->i_blocks = 0;
+ 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ 		inode->i_fop = files->ops;
+diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c
+index 4a6abc49418e..df6b1075b549 100644
+--- a/fs/minix/bitmap.c
++++ b/fs/minix/bitmap.c
+@@ -254,7 +254,7 @@ struct inode * minix_new_inode(const struct inode * dir, int * error)
+ 	inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
+ 	inode->i_ino = j;
+ 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
+-	inode->i_blocks = inode->i_blksize = 0;
++	inode->i_blocks = 0;
+ 	memset(&minix_i(inode)->u, 0, sizeof(minix_i(inode)->u));
+ 	insert_inode_hash(inode);
+ 	mark_inode_dirty(inode);
+diff --git a/fs/minix/inode.c b/fs/minix/inode.c
+index 826b9d830650..c11a4b9fb863 100644
+--- a/fs/minix/inode.c
++++ b/fs/minix/inode.c
+@@ -396,7 +396,7 @@ static void V1_minix_read_inode(struct inode * inode)
+ 	inode->i_mtime.tv_nsec = 0;
+ 	inode->i_atime.tv_nsec = 0;
+ 	inode->i_ctime.tv_nsec = 0;
+-	inode->i_blocks = inode->i_blksize = 0;
++	inode->i_blocks = 0;
+ 	for (i = 0; i < 9; i++)
+ 		minix_inode->u.i1_data[i] = raw_inode->i_zone[i];
+ 	minix_set_inode(inode, old_decode_dev(raw_inode->i_zone[0]));
+@@ -429,7 +429,7 @@ static void V2_minix_read_inode(struct inode * inode)
+ 	inode->i_mtime.tv_nsec = 0;
+ 	inode->i_atime.tv_nsec = 0;
+ 	inode->i_ctime.tv_nsec = 0;
+-	inode->i_blocks = inode->i_blksize = 0;
++	inode->i_blocks = 0;
+ 	for (i = 0; i < 10; i++)
+ 		minix_inode->u.i2_data[i] = raw_inode->i_zone[i];
+ 	minix_set_inode(inode, old_decode_dev(raw_inode->i_zone[0]));
+diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
+index 8244710e97dd..42e3bef270c9 100644
+--- a/fs/ncpfs/inode.c
++++ b/fs/ncpfs/inode.c
+@@ -223,7 +223,6 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
+ 	inode->i_nlink = 1;
+ 	inode->i_uid = server->m.uid;
+ 	inode->i_gid = server->m.gid;
+-	inode->i_blksize = NCP_BLOCK_SIZE;
+ 
+ 	ncp_update_dates(inode, &nwinfo->i);
+ 	ncp_update_inode(inode, nwinfo);
+diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
+index 931f52a19579..bc9376ca86cd 100644
+--- a/fs/nfs/inode.c
++++ b/fs/nfs/inode.c
+@@ -277,10 +277,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
+ 			 * report the blocks in 512byte units
+ 			 */
+ 			inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used);
+-			inode->i_blksize = inode->i_sb->s_blocksize;
+ 		} else {
+ 			inode->i_blocks = fattr->du.nfs2.blocks;
+-			inode->i_blksize = fattr->du.nfs2.blocksize;
+ 		}
+ 		nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
+ 		nfsi->attrtimeo_timestamp = jiffies;
+@@ -969,10 +967,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
+ 		 * report the blocks in 512byte units
+ 		 */
+ 		inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used);
+-		inode->i_blksize = inode->i_sb->s_blocksize;
+  	} else {
+  		inode->i_blocks = fattr->du.nfs2.blocks;
+- 		inode->i_blksize = fattr->du.nfs2.blocksize;
+  	}
+ 
+ 	if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 &&
+diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
+index 31852121b3f5..933dbd89c2a4 100644
+--- a/fs/ntfs/inode.c
++++ b/fs/ntfs/inode.c
+@@ -556,8 +556,6 @@ static int ntfs_read_locked_inode(struct inode *vi)
+ 
+ 	/* Setup the generic vfs inode parts now. */
+ 
+-	/* This is the optimal IO size (for stat), not the fs block size. */
+-	vi->i_blksize = PAGE_CACHE_SIZE;
+ 	/*
+ 	 * This is for checking whether an inode has changed w.r.t. a file so
+ 	 * that the file can be updated if necessary (compare with f_version).
+@@ -1234,7 +1232,6 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
+ 	base_ni = NTFS_I(base_vi);
+ 
+ 	/* Just mirror the values from the base inode. */
+-	vi->i_blksize	= base_vi->i_blksize;
+ 	vi->i_version	= base_vi->i_version;
+ 	vi->i_uid	= base_vi->i_uid;
+ 	vi->i_gid	= base_vi->i_gid;
+@@ -1504,7 +1501,6 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)
+ 	ni	= NTFS_I(vi);
+ 	base_ni = NTFS_I(base_vi);
+ 	/* Just mirror the values from the base inode. */
+-	vi->i_blksize	= base_vi->i_blksize;
+ 	vi->i_version	= base_vi->i_version;
+ 	vi->i_uid	= base_vi->i_uid;
+ 	vi->i_gid	= base_vi->i_gid;
+diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c
+index 578fb3d5e803..584260fd6848 100644
+--- a/fs/ntfs/mft.c
++++ b/fs/ntfs/mft.c
+@@ -2637,11 +2637,6 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, const int mode,
+ 			goto undo_mftbmp_alloc;
+ 		}
+ 		vi->i_ino = bit;
+-		/*
+-		 * This is the optimal IO size (for stat), not the fs block
+-		 * size.
+-		 */
+-		vi->i_blksize = PAGE_CACHE_SIZE;
+ 		/*
+ 		 * This is for checking whether an inode has changed w.r.t. a
+ 		 * file so that the file can be updated if necessary (compare
+diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c
+index 0ff0898a0b9c..0368c6402182 100644
+--- a/fs/ocfs2/dlm/dlmfs.c
++++ b/fs/ocfs2/dlm/dlmfs.c
+@@ -335,7 +335,6 @@ static struct inode *dlmfs_get_root_inode(struct super_block *sb)
+ 		inode->i_mode = mode;
+ 		inode->i_uid = current->fsuid;
+ 		inode->i_gid = current->fsgid;
+-		inode->i_blksize = PAGE_CACHE_SIZE;
+ 		inode->i_blocks = 0;
+ 		inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
+ 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+@@ -362,7 +361,6 @@ static struct inode *dlmfs_get_inode(struct inode *parent,
+ 	inode->i_mode = mode;
+ 	inode->i_uid = current->fsuid;
+ 	inode->i_gid = current->fsgid;
+-	inode->i_blksize = PAGE_CACHE_SIZE;
+ 	inode->i_blocks = 0;
+ 	inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
+ 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
+index 69d3db569166..16e8e74dc966 100644
+--- a/fs/ocfs2/inode.c
++++ b/fs/ocfs2/inode.c
+@@ -269,7 +269,6 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
+ 	inode->i_mode = le16_to_cpu(fe->i_mode);
+ 	inode->i_uid = le32_to_cpu(fe->i_uid);
+ 	inode->i_gid = le32_to_cpu(fe->i_gid);
+-	inode->i_blksize = (u32)osb->s_clustersize;
+ 
+ 	/* Fast symlinks will have i_size but no allocated clusters. */
+ 	if (S_ISLNK(inode->i_mode) && !fe->i_clusters)
+@@ -1258,8 +1257,6 @@ int ocfs2_mark_inode_dirty(struct ocfs2_journal_handle *handle,
+ void ocfs2_refresh_inode(struct inode *inode,
+ 			 struct ocfs2_dinode *fe)
+ {
+-	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+-
+ 	spin_lock(&OCFS2_I(inode)->ip_lock);
+ 
+ 	OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters);
+@@ -1270,7 +1267,6 @@ void ocfs2_refresh_inode(struct inode *inode,
+ 	inode->i_uid = le32_to_cpu(fe->i_uid);
+ 	inode->i_gid = le32_to_cpu(fe->i_gid);
+ 	inode->i_mode = le16_to_cpu(fe->i_mode);
+-	inode->i_blksize = (u32) osb->s_clustersize;
+ 	if (S_ISLNK(inode->i_mode) && le32_to_cpu(fe->i_clusters) == 0)
+ 		inode->i_blocks = 0;
+ 	else
+diff --git a/fs/pipe.c b/fs/pipe.c
+index 20352573e025..f3b6f71e9d0b 100644
+--- a/fs/pipe.c
++++ b/fs/pipe.c
+@@ -879,7 +879,6 @@ static struct inode * get_pipe_inode(void)
+ 	inode->i_uid = current->fsuid;
+ 	inode->i_gid = current->fsgid;
+ 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+-	inode->i_blksize = PAGE_SIZE;
+ 
+ 	return inode;
+ 
+diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
+index fddbd61c68d0..5a41db2a218d 100644
+--- a/fs/qnx4/inode.c
++++ b/fs/qnx4/inode.c
+@@ -496,7 +496,6 @@ static void qnx4_read_inode(struct inode *inode)
+ 	inode->i_ctime.tv_sec   = le32_to_cpu(raw_inode->di_ctime);
+ 	inode->i_ctime.tv_nsec = 0;
+ 	inode->i_blocks  = le32_to_cpu(raw_inode->di_first_xtnt.xtnt_size);
+-	inode->i_blksize = QNX4_DIR_ENTRY_SIZE;
+ 
+ 	memcpy(qnx4_inode, raw_inode, QNX4_DIR_ENTRY_SIZE);
+ 	if (S_ISREG(inode->i_mode)) {
+diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
+index b9677335cc8d..bc0e51662424 100644
+--- a/fs/ramfs/inode.c
++++ b/fs/ramfs/inode.c
+@@ -58,7 +58,6 @@ struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
+ 		inode->i_mode = mode;
+ 		inode->i_uid = current->fsuid;
+ 		inode->i_gid = current->fsgid;
+-		inode->i_blksize = PAGE_CACHE_SIZE;
+ 		inode->i_blocks = 0;
+ 		inode->i_mapping->a_ops = &ramfs_aops;
+ 		inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info;
+diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
+index 52f1e2136546..8810fda0da46 100644
+--- a/fs/reiserfs/inode.c
++++ b/fs/reiserfs/inode.c
+@@ -17,8 +17,6 @@
+ #include 
+ #include 
+ 
+-extern int reiserfs_default_io_size;	/* default io size devuned in super.c */
+-
+ static int reiserfs_commit_write(struct file *f, struct page *page,
+ 				 unsigned from, unsigned to);
+ static int reiserfs_prepare_write(struct file *f, struct page *page,
+@@ -1122,7 +1120,6 @@ static void init_inode(struct inode *inode, struct path *path)
+ 	ih = PATH_PITEM_HEAD(path);
+ 
+ 	copy_key(INODE_PKEY(inode), &(ih->ih_key));
+-	inode->i_blksize = reiserfs_default_io_size;
+ 
+ 	INIT_LIST_HEAD(&(REISERFS_I(inode)->i_prealloc_list));
+ 	REISERFS_I(inode)->i_flags = 0;
+@@ -1877,7 +1874,6 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
+ 	}
+ 	// these do not go to on-disk stat data
+ 	inode->i_ino = le32_to_cpu(ih.ih_key.k_objectid);
+-	inode->i_blksize = reiserfs_default_io_size;
+ 
+ 	// store in in-core inode the key of stat data and version all
+ 	// object items will have (directory items will have old offset
+diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
+index 92cf60aa6121..2c122ee83adb 100644
+--- a/fs/smbfs/inode.c
++++ b/fs/smbfs/inode.c
+@@ -166,7 +166,6 @@ smb_get_inode_attr(struct inode *inode, struct smb_fattr *fattr)
+ 	fattr->f_mtime	= inode->i_mtime;
+ 	fattr->f_ctime	= inode->i_ctime;
+ 	fattr->f_atime	= inode->i_atime;
+-	fattr->f_blksize= inode->i_blksize;
+ 	fattr->f_blocks	= inode->i_blocks;
+ 
+ 	fattr->attr	= SMB_I(inode)->attr;
+@@ -200,7 +199,6 @@ smb_set_inode_attr(struct inode *inode, struct smb_fattr *fattr)
+ 	inode->i_uid	= fattr->f_uid;
+ 	inode->i_gid	= fattr->f_gid;
+ 	inode->i_ctime	= fattr->f_ctime;
+-	inode->i_blksize= fattr->f_blksize;
+ 	inode->i_blocks = fattr->f_blocks;
+ 	inode->i_size	= fattr->f_size;
+ 	inode->i_mtime	= fattr->f_mtime;
+diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c
+index c3495059889d..40e174db9872 100644
+--- a/fs/smbfs/proc.c
++++ b/fs/smbfs/proc.c
+@@ -1826,7 +1826,6 @@ smb_init_dirent(struct smb_sb_info *server, struct smb_fattr *fattr)
+ 	fattr->f_nlink = 1;
+ 	fattr->f_uid = server->mnt->uid;
+ 	fattr->f_gid = server->mnt->gid;
+-	fattr->f_blksize = SMB_ST_BLKSIZE;
+ 	fattr->f_unix = 0;
+ }
+ 
+diff --git a/fs/stat.c b/fs/stat.c
+index 3a44dcf97da2..60a31d5e5966 100644
+--- a/fs/stat.c
++++ b/fs/stat.c
+@@ -14,6 +14,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ #include 
+@@ -32,7 +33,7 @@ void generic_fillattr(struct inode *inode, struct kstat *stat)
+ 	stat->ctime = inode->i_ctime;
+ 	stat->size = i_size_read(inode);
+ 	stat->blocks = inode->i_blocks;
+-	stat->blksize = inode->i_blksize;
++	stat->blksize = (1 << inode->i_blkbits);
+ }
+ 
+ EXPORT_SYMBOL(generic_fillattr);
+diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
+index fd7cd5f843d2..e79e38d52c00 100644
+--- a/fs/sysfs/inode.c
++++ b/fs/sysfs/inode.c
+@@ -125,7 +125,6 @@ struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent * sd)
+ {
+ 	struct inode * inode = new_inode(sysfs_sb);
+ 	if (inode) {
+-		inode->i_blksize = PAGE_CACHE_SIZE;
+ 		inode->i_blocks = 0;
+ 		inode->i_mapping->a_ops = &sysfs_aops;
+ 		inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
+diff --git a/fs/sysv/ialloc.c b/fs/sysv/ialloc.c
+index 9b585d1081c0..115ab0d6f4bc 100644
+--- a/fs/sysv/ialloc.c
++++ b/fs/sysv/ialloc.c
+@@ -170,7 +170,7 @@ struct inode * sysv_new_inode(const struct inode * dir, mode_t mode)
+ 	inode->i_uid = current->fsuid;
+ 	inode->i_ino = fs16_to_cpu(sbi, ino);
+ 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
+-	inode->i_blocks = inode->i_blksize = 0;
++	inode->i_blocks = 0;
+ 	memset(SYSV_I(inode)->i_data, 0, sizeof(SYSV_I(inode)->i_data));
+ 	SYSV_I(inode)->i_dir_start_lookup = 0;
+ 	insert_inode_hash(inode);
+diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
+index 58b2d22142ba..d63c5e48b050 100644
+--- a/fs/sysv/inode.c
++++ b/fs/sysv/inode.c
+@@ -201,7 +201,7 @@ static void sysv_read_inode(struct inode *inode)
+ 	inode->i_ctime.tv_nsec = 0;
+ 	inode->i_atime.tv_nsec = 0;
+ 	inode->i_mtime.tv_nsec = 0;
+-	inode->i_blocks = inode->i_blksize = 0;
++	inode->i_blocks = 0;
+ 
+ 	si = SYSV_I(inode);
+ 	for (block = 0; block < 10+1+1+1; block++)
+diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c
+index d1d38238ce65..8206983f2ebf 100644
+--- a/fs/udf/ialloc.c
++++ b/fs/udf/ialloc.c
+@@ -121,7 +121,6 @@ struct inode * udf_new_inode (struct inode *dir, int mode, int * err)
+ 	UDF_I_LOCATION(inode).logicalBlockNum = block;
+ 	UDF_I_LOCATION(inode).partitionReferenceNum = UDF_I_LOCATION(dir).partitionReferenceNum;
+ 	inode->i_ino = udf_get_lb_pblock(sb, UDF_I_LOCATION(inode), 0);
+-	inode->i_blksize = PAGE_SIZE;
+ 	inode->i_blocks = 0;
+ 	UDF_I_LENEATTR(inode) = 0;
+ 	UDF_I_LENALLOC(inode) = 0;
+diff --git a/fs/udf/inode.c b/fs/udf/inode.c
+index 605f5111b6d8..b223b32db991 100644
+--- a/fs/udf/inode.c
++++ b/fs/udf/inode.c
+@@ -916,8 +916,6 @@ __udf_read_inode(struct inode *inode)
+ 	 *      i_nlink = 1
+ 	 *      i_op = NULL;
+ 	 */
+-	inode->i_blksize = PAGE_SIZE;
+-
+ 	bh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 0, &ident);
+ 
+ 	if (!bh)
+diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c
+index 9501dcd3b213..2ad1259c6eca 100644
+--- a/fs/ufs/ialloc.c
++++ b/fs/ufs/ialloc.c
+@@ -255,7 +255,6 @@ struct inode * ufs_new_inode(struct inode * dir, int mode)
+ 		inode->i_gid = current->fsgid;
+ 
+ 	inode->i_ino = cg * uspi->s_ipg + bit;
+-	inode->i_blksize = PAGE_SIZE;	/* This is the optimal IO size (for stat), not the fs block size */
+ 	inode->i_blocks = 0;
+ 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
+ 	ufsi->i_flags = UFS_I(dir)->i_flags;
+diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
+index 30c6e8a9446c..ee1eaa6f4ec2 100644
+--- a/fs/ufs/inode.c
++++ b/fs/ufs/inode.c
+@@ -741,7 +741,6 @@ void ufs_read_inode(struct inode * inode)
+ 		ufs1_read_inode(inode, ufs_inode + ufs_inotofsbo(inode->i_ino));
+ 	}
+ 
+-	inode->i_blksize = PAGE_SIZE;/*This is the optimal IO size (for stat)*/
+ 	inode->i_version++;
+ 	ufsi->i_lastfrag =
+ 		(inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift;
+diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
+index 4754f342a5d3..9df9ed37d219 100644
+--- a/fs/xfs/linux-2.6/xfs_super.c
++++ b/fs/xfs/linux-2.6/xfs_super.c
+@@ -171,7 +171,6 @@ xfs_revalidate_inode(
+ 		break;
+ 	}
+ 
+-	inode->i_blksize = xfs_preferred_iosize(mp);
+ 	inode->i_generation = ip->i_d.di_gen;
+ 	i_size_write(inode, ip->i_d.di_size);
+ 	inode->i_blocks =
+diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c
+index 6628d96b6fd6..553fa731ade5 100644
+--- a/fs/xfs/linux-2.6/xfs_vnode.c
++++ b/fs/xfs/linux-2.6/xfs_vnode.c
+@@ -122,7 +122,6 @@ vn_revalidate_core(
+ 	inode->i_blocks	    = vap->va_nblocks;
+ 	inode->i_mtime	    = vap->va_mtime;
+ 	inode->i_ctime	    = vap->va_ctime;
+-	inode->i_blksize    = vap->va_blocksize;
+ 	if (vap->va_xflags & XFS_XFLAG_IMMUTABLE)
+ 		inode->i_flags |= S_IMMUTABLE;
+ 	else
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 192e69bb55b5..8f74dfbb2edd 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -512,7 +512,6 @@ struct inode {
+ 	struct timespec		i_mtime;
+ 	struct timespec		i_ctime;
+ 	unsigned int		i_blkbits;
+-	unsigned long		i_blksize;
+ 	unsigned long		i_version;
+ 	blkcnt_t		i_blocks;
+ 	unsigned short          i_bytes;
+diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h
+index f9edcd2ff3c8..31a3cb617ce0 100644
+--- a/include/linux/nfsd/nfsfh.h
++++ b/include/linux/nfsd/nfsfh.h
+@@ -269,14 +269,8 @@ fill_post_wcc(struct svc_fh *fhp)
+ 	fhp->fh_post_uid	= inode->i_uid;
+ 	fhp->fh_post_gid	= inode->i_gid;
+ 	fhp->fh_post_size       = inode->i_size;
+-	if (inode->i_blksize) {
+-		fhp->fh_post_blksize    = inode->i_blksize;
+-		fhp->fh_post_blocks     = inode->i_blocks;
+-	} else {
+-		fhp->fh_post_blksize    = BLOCK_SIZE;
+-		/* how much do we care for accuracy with MinixFS? */
+-		fhp->fh_post_blocks     = (inode->i_size+511) >> 9;
+-	}
++	fhp->fh_post_blksize    = BLOCK_SIZE;
++	fhp->fh_post_blocks     = inode->i_blocks;
+ 	fhp->fh_post_rdev[0]    = htonl((u32)imajor(inode));
+ 	fhp->fh_post_rdev[1]    = htonl((u32)iminor(inode));
+ 	fhp->fh_post_atime      = inode->i_atime;
+diff --git a/include/linux/smb.h b/include/linux/smb.h
+index 6df3b1501559..f098dff93f6b 100644
+--- a/include/linux/smb.h
++++ b/include/linux/smb.h
+@@ -89,7 +89,6 @@ struct smb_fattr {
+ 	struct timespec	f_atime;
+ 	struct timespec f_mtime;
+ 	struct timespec f_ctime;
+-	unsigned long	f_blksize;
+ 	unsigned long	f_blocks;
+ 	int		f_unix;
+ };
+diff --git a/ipc/mqueue.c b/ipc/mqueue.c
+index f8381f0660b2..840f8a6fb85f 100644
+--- a/ipc/mqueue.c
++++ b/ipc/mqueue.c
+@@ -115,7 +115,6 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode,
+ 		inode->i_mode = mode;
+ 		inode->i_uid = current->fsuid;
+ 		inode->i_gid = current->fsgid;
+-		inode->i_blksize = PAGE_CACHE_SIZE;
+ 		inode->i_blocks = 0;
+ 		inode->i_mtime = inode->i_ctime = inode->i_atime =
+ 				CURRENT_TIME;
+diff --git a/kernel/cpuset.c b/kernel/cpuset.c
+index cff41511269f..1b32c2c04c15 100644
+--- a/kernel/cpuset.c
++++ b/kernel/cpuset.c
+@@ -289,7 +289,6 @@ static struct inode *cpuset_new_inode(mode_t mode)
+ 		inode->i_mode = mode;
+ 		inode->i_uid = current->fsuid;
+ 		inode->i_gid = current->fsgid;
+-		inode->i_blksize = PAGE_CACHE_SIZE;
+ 		inode->i_blocks = 0;
+ 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ 		inode->i_mapping->backing_dev_info = &cpuset_backing_dev_info;
+diff --git a/mm/shmem.c b/mm/shmem.c
+index 0a8e29cf87e0..eda907c3a86a 100644
+--- a/mm/shmem.c
++++ b/mm/shmem.c
+@@ -1351,7 +1351,6 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
+ 		inode->i_mode = mode;
+ 		inode->i_uid = current->fsuid;
+ 		inode->i_gid = current->fsgid;
+-		inode->i_blksize = PAGE_CACHE_SIZE;
+ 		inode->i_blocks = 0;
+ 		inode->i_mapping->a_ops = &shmem_aops;
+ 		inode->i_mapping->backing_dev_info = &shmem_backing_dev_info;
+diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
+index f65bea74734d..700c6e061a04 100644
+--- a/net/sunrpc/rpc_pipe.c
++++ b/net/sunrpc/rpc_pipe.c
+@@ -488,7 +488,6 @@ rpc_get_inode(struct super_block *sb, int mode)
+ 		return NULL;
+ 	inode->i_mode = mode;
+ 	inode->i_uid = inode->i_gid = 0;
+-	inode->i_blksize = PAGE_CACHE_SIZE;
+ 	inode->i_blocks = 0;
+ 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ 	switch(mode & S_IFMT) {
+diff --git a/security/inode.c b/security/inode.c
+index 176aacea8ca4..49ee51529396 100644
+--- a/security/inode.c
++++ b/security/inode.c
+@@ -64,7 +64,6 @@ static struct inode *get_inode(struct super_block *sb, int mode, dev_t dev)
+ 		inode->i_mode = mode;
+ 		inode->i_uid = 0;
+ 		inode->i_gid = 0;
+-		inode->i_blksize = PAGE_CACHE_SIZE;
+ 		inode->i_blocks = 0;
+ 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ 		switch (mode & S_IFMT) {
+diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
+index 00534c302ba2..bab7b386cb8d 100644
+--- a/security/selinux/selinuxfs.c
++++ b/security/selinux/selinuxfs.c
+@@ -771,7 +771,6 @@ static struct inode *sel_make_inode(struct super_block *sb, int mode)
+ 	if (ret) {
+ 		ret->i_mode = mode;
+ 		ret->i_uid = ret->i_gid = 0;
+-		ret->i_blksize = PAGE_CACHE_SIZE;
+ 		ret->i_blocks = 0;
+ 		ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
+ 	}

commit 577c4eb09d1034d0739e3135fd2cff50588024be
+Author: Theodore Ts'o 
+Date:   Wed Sep 27 01:50:49 2006 -0700
+
+    [PATCH] inode-diet: Move i_cdev into a union
+    
+    Move the i_cdev pointer in struct inode into a union.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/file_table.c b/fs/file_table.c
+index 0131ba06e1ee..bc35a40417d7 100644
+--- a/fs/file_table.c
++++ b/fs/file_table.c
+@@ -169,7 +169,7 @@ void fastcall __fput(struct file *file)
+ 	if (file->f_op && file->f_op->release)
+ 		file->f_op->release(inode, file);
+ 	security_file_free(file);
+-	if (unlikely(inode->i_cdev != NULL))
++	if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL))
+ 		cdev_put(inode->i_cdev);
+ 	fops_put(file->f_op);
+ 	if (file->f_mode & FMODE_WRITE)
+diff --git a/fs/inode.c b/fs/inode.c
+index 41b462232f7f..f5c04dd9ae8a 100644
+--- a/fs/inode.c
++++ b/fs/inode.c
+@@ -256,7 +256,7 @@ void clear_inode(struct inode *inode)
+ 		inode->i_sb->s_op->clear_inode(inode);
+ 	if (S_ISBLK(inode->i_mode) && inode->i_bdev)
+ 		bd_forget(inode);
+-	if (inode->i_cdev)
++	if (S_ISCHR(inode->i_mode) && inode->i_cdev)
+ 		cd_forget(inode);
+ 	inode->i_state = I_CLEAR;
+ }
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 98ff684a5b1c..192e69bb55b5 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -532,8 +532,8 @@ struct inode {
+ 	union {
+ 		struct pipe_inode_info	*i_pipe;
+ 		struct block_device	*i_bdev;
++		struct cdev		*i_cdev;
+ 	};
+-	struct cdev		*i_cdev;
+ 	int			i_cindex;
+ 
+ 	__u32			i_generation;

commit eaf796e7ef6014f208c409b2b14fddcfaafe7e3a
+Author: Theodore Ts'o 
+Date:   Wed Sep 27 01:50:48 2006 -0700
+
+    [PATCH] inode-diet: Move i_bdev into a union
+    
+    Move the i_bdev pointer in struct inode into a union.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/inode.c b/fs/inode.c
+index 77e254792025..41b462232f7f 100644
+--- a/fs/inode.c
++++ b/fs/inode.c
+@@ -254,7 +254,7 @@ void clear_inode(struct inode *inode)
+ 	DQUOT_DROP(inode);
+ 	if (inode->i_sb && inode->i_sb->s_op->clear_inode)
+ 		inode->i_sb->s_op->clear_inode(inode);
+-	if (inode->i_bdev)
++	if (S_ISBLK(inode->i_mode) && inode->i_bdev)
+ 		bd_forget(inode);
+ 	if (inode->i_cdev)
+ 		cd_forget(inode);
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index ca695fc8d69c..98ff684a5b1c 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -531,8 +531,8 @@ struct inode {
+ 	struct list_head	i_devices;
+ 	union {
+ 		struct pipe_inode_info	*i_pipe;
++		struct block_device	*i_bdev;
+ 	};
+-	struct block_device	*i_bdev;
+ 	struct cdev		*i_cdev;
+ 	int			i_cindex;
+ 

commit 4c1541680f8d189d21dd07b053bc12996574646e
+Author: Theodore Ts'o 
+Date:   Wed Sep 27 01:50:47 2006 -0700
+
+    [PATCH] inode-diet: Move i_pipe into a union
+    
+    Move the i_pipe pointer into a union that will be shared with i_bdev and
+    i_cdev.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 4f77ec9c3353..ca695fc8d69c 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -528,9 +528,10 @@ struct inode {
+ #ifdef CONFIG_QUOTA
+ 	struct dquot		*i_dquot[MAXQUOTAS];
+ #endif
+-	/* These three should probably be a union */
+ 	struct list_head	i_devices;
+-	struct pipe_inode_info	*i_pipe;
++	union {
++		struct pipe_inode_info	*i_pipe;
++	};
+ 	struct block_device	*i_bdev;
+ 	struct cdev		*i_cdev;
+ 	int			i_cindex;

commit 8e18e2941c53416aa219708e7dcad21fb4bd6794
+Author: Theodore Ts'o 
+Date:   Wed Sep 27 01:50:46 2006 -0700
+
+    [PATCH] inode_diet: Replace inode.u.generic_ip with inode.i_private
+    
+    The following patches reduce the size of the VFS inode structure by 28 bytes
+    on a UP x86.  (It would be more on an x86_64 system).  This is a 10% reduction
+    in the inode size on a UP kernel that is configured in a production mode
+    (i.e., with no spinlock or other debugging functions enabled; if you want to
+    save memory taken up by in-core inodes, the first thing you should do is
+    disable the debugging options; they are responsible for a huge amount of bloat
+    in the VFS inode structure).
+    
+    This patch:
+    
+    The filesystem or device-specific pointer in the inode is inside a union,
+    which is pretty pointless given that all 30+ users of this field have been
+    using the void pointer.  Get rid of the union and rename it to i_private, with
+    a comment to explain who is allowed to use the void pointer.  This is just a
+    cleanup, but it allows us to reuse the union 'u' for something something where
+    the union will actually be used.
+    
+    [judith@osdl.org: powerpc build fix]
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Judith Lebzelter 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
+index 7b4572805db9..b837f12a84ae 100644
+--- a/arch/powerpc/platforms/cell/spufs/inode.c
++++ b/arch/powerpc/platforms/cell/spufs/inode.c
+@@ -120,7 +120,7 @@ spufs_new_file(struct super_block *sb, struct dentry *dentry,
+ 	ret = 0;
+ 	inode->i_op = &spufs_file_iops;
+ 	inode->i_fop = fops;
+-	inode->u.generic_ip = SPUFS_I(inode)->i_ctx = get_spu_context(ctx);
++	inode->i_private = SPUFS_I(inode)->i_ctx = get_spu_context(ctx);
+ 	d_add(dentry, inode);
+ out:
+ 	return ret;
+diff --git a/arch/powerpc/platforms/pseries/hvCall_inst.c b/arch/powerpc/platforms/pseries/hvCall_inst.c
+index 641e6511cf06..446e17d162a5 100644
+--- a/arch/powerpc/platforms/pseries/hvCall_inst.c
++++ b/arch/powerpc/platforms/pseries/hvCall_inst.c
+@@ -85,7 +85,7 @@ static int hcall_inst_seq_open(struct inode *inode, struct file *file)
+ 
+ 	rc = seq_open(file, &hcall_inst_seq_ops);
+ 	seq = file->private_data;
+-	seq->private = file->f_dentry->d_inode->u.generic_ip;
++	seq->private = file->f_dentry->d_inode->i_private;
+ 
+ 	return rc;
+ }
+diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
+index bdade5f2e325..8735024d235b 100644
+--- a/arch/s390/hypfs/inode.c
++++ b/arch/s390/hypfs/inode.c
+@@ -104,13 +104,13 @@ static struct inode *hypfs_make_inode(struct super_block *sb, int mode)
+ 
+ static void hypfs_drop_inode(struct inode *inode)
+ {
+-	kfree(inode->u.generic_ip);
++	kfree(inode->i_private);
+ 	generic_delete_inode(inode);
+ }
+ 
+ static int hypfs_open(struct inode *inode, struct file *filp)
+ {
+-	char *data = filp->f_dentry->d_inode->u.generic_ip;
++	char *data = filp->f_dentry->d_inode->i_private;
+ 	struct hypfs_sb_info *fs_info;
+ 
+ 	if (filp->f_mode & FMODE_WRITE) {
+@@ -352,7 +352,7 @@ static struct dentry *hypfs_create_file(struct super_block *sb,
+ 		parent->d_inode->i_nlink++;
+ 	} else
+ 		BUG();
+-	inode->u.generic_ip = data;
++	inode->i_private = data;
+ 	d_instantiate(dentry, inode);
+ 	dget(dentry);
+ 	return dentry;
+diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
+index 7ba20922a535..43f3d0c7e132 100644
+--- a/arch/s390/kernel/debug.c
++++ b/arch/s390/kernel/debug.c
+@@ -603,7 +603,7 @@ debug_open(struct inode *inode, struct file *file)
+ 	debug_info_t *debug_info, *debug_info_snapshot;
+ 
+ 	down(&debug_lock);
+-	debug_info = (struct debug_info*)file->f_dentry->d_inode->u.generic_ip;
++	debug_info = file->f_dentry->d_inode->i_private;
+ 	/* find debug view */
+ 	for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
+ 		if (!debug_info->views[i])
+diff --git a/block/blktrace.c b/block/blktrace.c
+index 265f7a830619..2b4ef2b89b8d 100644
+--- a/block/blktrace.c
++++ b/block/blktrace.c
+@@ -217,7 +217,7 @@ static int blk_trace_remove(request_queue_t *q)
+ 
+ static int blk_dropped_open(struct inode *inode, struct file *filp)
+ {
+-	filp->private_data = inode->u.generic_ip;
++	filp->private_data = inode->i_private;
+ 
+ 	return 0;
+ }
+diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
+index 0be6fd6a267d..6a7578217177 100644
+--- a/drivers/i2c/chips/tps65010.c
++++ b/drivers/i2c/chips/tps65010.c
+@@ -305,7 +305,7 @@ static int dbg_show(struct seq_file *s, void *_)
+ 
+ static int dbg_tps_open(struct inode *inode, struct file *file)
+ {
+-	return single_open(file, dbg_show, inode->u.generic_ip);
++	return single_open(file, dbg_show, inode->i_private);
+ }
+ 
+ static struct file_operations debug_fops = {
+diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
+index a5eb30a06a5c..055cdd089b28 100644
+--- a/drivers/infiniband/hw/ipath/ipath_fs.c
++++ b/drivers/infiniband/hw/ipath/ipath_fs.c
+@@ -64,7 +64,7 @@ static int ipathfs_mknod(struct inode *dir, struct dentry *dentry,
+ 	inode->i_blksize = PAGE_CACHE_SIZE;
+ 	inode->i_blocks = 0;
+ 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+-	inode->u.generic_ip = data;
++	inode->i_private = data;
+ 	if ((mode & S_IFMT) == S_IFDIR) {
+ 		inode->i_op = &simple_dir_inode_operations;
+ 		inode->i_nlink++;
+@@ -119,7 +119,7 @@ static ssize_t atomic_counters_read(struct file *file, char __user *buf,
+ 	u16 i;
+ 	struct ipath_devdata *dd;
+ 
+-	dd = file->f_dentry->d_inode->u.generic_ip;
++	dd = file->f_dentry->d_inode->i_private;
+ 
+ 	for (i = 0; i < NUM_COUNTERS; i++)
+ 		counters[i] = ipath_snap_cntr(dd, i);
+@@ -139,7 +139,7 @@ static ssize_t atomic_node_info_read(struct file *file, char __user *buf,
+ 	struct ipath_devdata *dd;
+ 	u64 guid;
+ 
+-	dd = file->f_dentry->d_inode->u.generic_ip;
++	dd = file->f_dentry->d_inode->i_private;
+ 
+ 	guid = be64_to_cpu(dd->ipath_guid);
+ 
+@@ -178,7 +178,7 @@ static ssize_t atomic_port_info_read(struct file *file, char __user *buf,
+ 	u32 tmp, tmp2;
+ 	struct ipath_devdata *dd;
+ 
+-	dd = file->f_dentry->d_inode->u.generic_ip;
++	dd = file->f_dentry->d_inode->i_private;
+ 
+ 	/* so we only initialize non-zero fields. */
+ 	memset(portinfo, 0, sizeof portinfo);
+@@ -325,7 +325,7 @@ static ssize_t flash_read(struct file *file, char __user *buf,
+ 		goto bail;
+ 	}
+ 
+-	dd = file->f_dentry->d_inode->u.generic_ip;
++	dd = file->f_dentry->d_inode->i_private;
+ 	if (ipath_eeprom_read(dd, pos, tmp, count)) {
+ 		ipath_dev_err(dd, "failed to read from flash\n");
+ 		ret = -ENXIO;
+@@ -381,7 +381,7 @@ static ssize_t flash_write(struct file *file, const char __user *buf,
+ 		goto bail_tmp;
+ 	}
+ 
+-	dd = file->f_dentry->d_inode->u.generic_ip;
++	dd = file->f_dentry->d_inode->i_private;
+ 	if (ipath_eeprom_write(dd, pos, tmp, count)) {
+ 		ret = -ENXIO;
+ 		ipath_dev_err(dd, "failed to write to flash\n");
+diff --git a/drivers/infiniband/ulp/ipoib/ipoib_fs.c b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
+index 5dde380e8dbe..f1cb83688b31 100644
+--- a/drivers/infiniband/ulp/ipoib/ipoib_fs.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
+@@ -141,7 +141,7 @@ static int ipoib_mcg_open(struct inode *inode, struct file *file)
+ 		return ret;
+ 
+ 	seq = file->private_data;
+-	seq->private = inode->u.generic_ip;
++	seq->private = inode->i_private;
+ 
+ 	return 0;
+ }
+@@ -247,7 +247,7 @@ static int ipoib_path_open(struct inode *inode, struct file *file)
+ 		return ret;
+ 
+ 	seq = file->private_data;
+-	seq->private = inode->u.generic_ip;
++	seq->private = inode->i_private;
+ 
+ 	return 0;
+ }
+diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c
+index 4a35caff5d02..0e909b617226 100644
+--- a/drivers/misc/ibmasm/ibmasmfs.c
++++ b/drivers/misc/ibmasm/ibmasmfs.c
+@@ -175,7 +175,7 @@ static struct dentry *ibmasmfs_create_file (struct super_block *sb,
+ 	}
+ 
+ 	inode->i_fop = fops;
+-	inode->u.generic_ip = data;
++	inode->i_private = data;
+ 
+ 	d_add(dentry, inode);
+ 	return dentry;
+@@ -244,7 +244,7 @@ static int command_file_open(struct inode *inode, struct file *file)
+ {
+ 	struct ibmasmfs_command_data *command_data;
+ 
+-	if (!inode->u.generic_ip)
++	if (!inode->i_private)
+ 		return -ENODEV;
+ 
+ 	command_data = kmalloc(sizeof(struct ibmasmfs_command_data), GFP_KERNEL);
+@@ -252,7 +252,7 @@ static int command_file_open(struct inode *inode, struct file *file)
+ 		return -ENOMEM;
+ 
+ 	command_data->command = NULL;
+-	command_data->sp = inode->u.generic_ip;
++	command_data->sp = inode->i_private;
+ 	file->private_data = command_data;
+ 	return 0;
+ }
+@@ -351,10 +351,10 @@ static int event_file_open(struct inode *inode, struct file *file)
+ 	struct ibmasmfs_event_data *event_data;
+ 	struct service_processor *sp; 
+ 
+-	if (!inode->u.generic_ip)
++	if (!inode->i_private)
+ 		return -ENODEV;
+ 
+-	sp = inode->u.generic_ip;
++	sp = inode->i_private;
+ 
+ 	event_data = kmalloc(sizeof(struct ibmasmfs_event_data), GFP_KERNEL);
+ 	if (!event_data)
+@@ -439,14 +439,14 @@ static int r_heartbeat_file_open(struct inode *inode, struct file *file)
+ {
+ 	struct ibmasmfs_heartbeat_data *rhbeat;
+ 
+-	if (!inode->u.generic_ip)
++	if (!inode->i_private)
+ 		return -ENODEV;
+ 
+ 	rhbeat = kmalloc(sizeof(struct ibmasmfs_heartbeat_data), GFP_KERNEL);
+ 	if (!rhbeat)
+ 		return -ENOMEM;
+ 
+-	rhbeat->sp = (struct service_processor *)inode->u.generic_ip;
++	rhbeat->sp = inode->i_private;
+ 	rhbeat->active = 0;
+ 	ibmasm_init_reverse_heartbeat(rhbeat->sp, &rhbeat->heartbeat);
+ 	file->private_data = rhbeat;
+@@ -508,7 +508,7 @@ static ssize_t r_heartbeat_file_write(struct file *file, const char __user *buf,
+ 
+ static int remote_settings_file_open(struct inode *inode, struct file *file)
+ {
+-	file->private_data = inode->u.generic_ip;
++	file->private_data = inode->i_private;
+ 	return 0;
+ }
+ 
+diff --git a/drivers/net/irda/vlsi_ir.h b/drivers/net/irda/vlsi_ir.h
+index a82a4ba8de4f..c37f0bc4c7f9 100644
+--- a/drivers/net/irda/vlsi_ir.h
++++ b/drivers/net/irda/vlsi_ir.h
+@@ -58,7 +58,7 @@ typedef void irqreturn_t;
+ 
+ /* PDE() introduced in 2.5.4 */
+ #ifdef CONFIG_PROC_FS
+-#define PDE(inode) ((inode)->u.generic_ip)
++#define PDE(inode) ((inode)->i_private)
+ #endif
+ 
+ /* irda crc16 calculation exported in 2.5.42 */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
+index 923275ea0789..b9df06a06ea9 100644
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
++++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
+@@ -54,7 +54,7 @@ static ssize_t write_file_dummy(struct file *file, const char __user *buf,
+ 
+ static int open_file_generic(struct inode *inode, struct file *file)
+ {
+-	file->private_data = inode->u.generic_ip;
++	file->private_data = inode->i_private;
+ 	return 0;
+ }
+ 
+diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c
+index 71c2da277d6e..deb37354785b 100644
+--- a/drivers/oprofile/oprofilefs.c
++++ b/drivers/oprofile/oprofilefs.c
+@@ -110,8 +110,8 @@ static ssize_t ulong_write_file(struct file * file, char const __user * buf, siz
+ 
+ static int default_open(struct inode * inode, struct file * filp)
+ {
+-	if (inode->u.generic_ip)
+-		filp->private_data = inode->u.generic_ip;
++	if (inode->i_private)
++		filp->private_data = inode->i_private;
+ 	return 0;
+ }
+ 
+@@ -158,7 +158,7 @@ int oprofilefs_create_ulong(struct super_block * sb, struct dentry * root,
+ 	if (!d)
+ 		return -EFAULT;
+ 
+-	d->d_inode->u.generic_ip = val;
++	d->d_inode->i_private = val;
+ 	return 0;
+ }
+ 
+@@ -171,7 +171,7 @@ int oprofilefs_create_ro_ulong(struct super_block * sb, struct dentry * root,
+ 	if (!d)
+ 		return -EFAULT;
+ 
+-	d->d_inode->u.generic_ip = val;
++	d->d_inode->i_private = val;
+ 	return 0;
+ }
+ 
+@@ -197,7 +197,7 @@ int oprofilefs_create_ro_atomic(struct super_block * sb, struct dentry * root,
+ 	if (!d)
+ 		return -EFAULT;
+ 
+-	d->d_inode->u.generic_ip = val;
++	d->d_inode->i_private = val;
+ 	return 0;
+ }
+ 
+diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c
+index 8b3da007e859..5bab666cd67e 100644
+--- a/drivers/pci/hotplug/cpqphp_sysfs.c
++++ b/drivers/pci/hotplug/cpqphp_sysfs.c
+@@ -140,7 +140,7 @@ struct ctrl_dbg {
+ 
+ static int open(struct inode *inode, struct file *file)
+ {
+-	struct controller *ctrl = inode->u.generic_ip;
++	struct controller *ctrl = inode->i_private;
+ 	struct ctrl_dbg *dbg;
+ 	int retval = -ENOMEM;
+ 
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 218621b9958e..32e03000420c 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -555,7 +555,7 @@ static int usbdev_open(struct inode *inode, struct file *file)
+ 	if (imajor(inode) == USB_DEVICE_MAJOR)
+ 		dev = usbdev_lookup_minor(iminor(inode));
+ 	if (!dev)
+-		dev = inode->u.generic_ip;
++		dev = inode->i_private;
+ 	if (!dev) {
+ 		kfree(ps);
+ 		goto out;
+diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
+index 3182c2224ba2..482f253085e5 100644
+--- a/drivers/usb/core/inode.c
++++ b/drivers/usb/core/inode.c
+@@ -402,8 +402,8 @@ static loff_t default_file_lseek (struct file *file, loff_t offset, int orig)
+ 
+ static int default_open (struct inode *inode, struct file *file)
+ {
+-	if (inode->u.generic_ip)
+-		file->private_data = inode->u.generic_ip;
++	if (inode->i_private)
++		file->private_data = inode->i_private;
+ 
+ 	return 0;
+ }
+@@ -509,7 +509,7 @@ static struct dentry *fs_create_file (const char *name, mode_t mode,
+ 	} else {
+ 		if (dentry->d_inode) {
+ 			if (data)
+-				dentry->d_inode->u.generic_ip = data;
++				dentry->d_inode->i_private = data;
+ 			if (fops)
+ 				dentry->d_inode->i_fop = fops;
+ 			dentry->d_inode->i_uid = uid;
+diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
+index 3bdc5e3ba234..ffaa8c1afad8 100644
+--- a/drivers/usb/gadget/inode.c
++++ b/drivers/usb/gadget/inode.c
+@@ -844,7 +844,7 @@ ep_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
+ static int
+ ep_open (struct inode *inode, struct file *fd)
+ {
+-	struct ep_data		*data = inode->u.generic_ip;
++	struct ep_data		*data = inode->i_private;
+ 	int			value = -EBUSY;
+ 
+ 	if (down_interruptible (&data->lock) != 0)
+@@ -1909,7 +1909,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
+ static int
+ dev_open (struct inode *inode, struct file *fd)
+ {
+-	struct dev_data		*dev = inode->u.generic_ip;
++	struct dev_data		*dev = inode->i_private;
+ 	int			value = -EBUSY;
+ 
+ 	if (dev->state == STATE_DEV_DISABLED) {
+@@ -1970,7 +1970,7 @@ gadgetfs_make_inode (struct super_block *sb,
+ 		inode->i_blocks = 0;
+ 		inode->i_atime = inode->i_mtime = inode->i_ctime
+ 				= CURRENT_TIME;
+-		inode->u.generic_ip = data;
++		inode->i_private = data;
+ 		inode->i_fop = fops;
+ 	}
+ 	return inode;
+diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
+index 5147ed4a6662..8c6b38a0b5bb 100644
+--- a/drivers/usb/host/isp116x-hcd.c
++++ b/drivers/usb/host/isp116x-hcd.c
+@@ -1204,7 +1204,7 @@ static int isp116x_show_dbg(struct seq_file *s, void *unused)
+ 
+ static int isp116x_open_seq(struct inode *inode, struct file *file)
+ {
+-	return single_open(file, isp116x_show_dbg, inode->u.generic_ip);
++	return single_open(file, isp116x_show_dbg, inode->i_private);
+ }
+ 
+ static struct file_operations isp116x_debug_fops = {
+diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
+index dc286a48cafd..d1372cb27f33 100644
+--- a/drivers/usb/host/uhci-debug.c
++++ b/drivers/usb/host/uhci-debug.c
+@@ -428,7 +428,7 @@ struct uhci_debug {
+ 
+ static int uhci_debug_open(struct inode *inode, struct file *file)
+ {
+-	struct uhci_hcd *uhci = inode->u.generic_ip;
++	struct uhci_hcd *uhci = inode->i_private;
+ 	struct uhci_debug *up;
+ 	int ret = -ENOMEM;
+ 	unsigned long flags;
+diff --git a/drivers/usb/mon/mon_stat.c b/drivers/usb/mon/mon_stat.c
+index 1fe01d994a79..86ad2b381c4b 100644
+--- a/drivers/usb/mon/mon_stat.c
++++ b/drivers/usb/mon/mon_stat.c
+@@ -28,7 +28,7 @@ static int mon_stat_open(struct inode *inode, struct file *file)
+ 	if ((sp = kmalloc(sizeof(struct snap), GFP_KERNEL)) == NULL)
+ 		return -ENOMEM;
+ 
+-	mbus = inode->u.generic_ip;
++	mbus = inode->i_private;
+ 
+ 	sp->slen = snprintf(sp->str, STAT_BUF_SIZE,
+ 	    "nreaders %d events %u text_lost %u\n",
+diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
+index f961a770cee2..2fd39b4fa166 100644
+--- a/drivers/usb/mon/mon_text.c
++++ b/drivers/usb/mon/mon_text.c
+@@ -238,7 +238,7 @@ static int mon_text_open(struct inode *inode, struct file *file)
+ 	int rc;
+ 
+ 	mutex_lock(&mon_lock);
+-	mbus = inode->u.generic_ip;
++	mbus = inode->i_private;
+ 	ubus = mbus->u_bus;
+ 
+ 	rp = kzalloc(sizeof(struct mon_reader_text), GFP_KERNEL);
+@@ -401,7 +401,7 @@ static int mon_text_release(struct inode *inode, struct file *file)
+ 	struct mon_event_text *ep;
+ 
+ 	mutex_lock(&mon_lock);
+-	mbus = inode->u.generic_ip;
++	mbus = inode->i_private;
+ 
+ 	if (mbus->nreaders <= 0) {
+ 		printk(KERN_ERR TAG ": consistency error on close\n");
+diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
+index c81d6b8c2828..d39d2acd9b38 100644
+--- a/fs/autofs/inode.c
++++ b/fs/autofs/inode.c
+@@ -241,7 +241,7 @@ static void autofs_read_inode(struct inode *inode)
+ 		
+ 		inode->i_op = &autofs_symlink_inode_operations;
+ 		sl = &sbi->symlink[n];
+-		inode->u.generic_ip = sl;
++		inode->i_private = sl;
+ 		inode->i_mode = S_IFLNK | S_IRWXUGO;
+ 		inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = sl->mtime;
+ 		inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 0;
+diff --git a/fs/autofs/symlink.c b/fs/autofs/symlink.c
+index 52e8772b066e..c74f2eb65775 100644
+--- a/fs/autofs/symlink.c
++++ b/fs/autofs/symlink.c
+@@ -15,7 +15,7 @@
+ /* Nothing to release.. */
+ static void *autofs_follow_link(struct dentry *dentry, struct nameidata *nd)
+ {
+-	char *s=((struct autofs_symlink *)dentry->d_inode->u.generic_ip)->data;
++	char *s=((struct autofs_symlink *)dentry->d_inode->i_private)->data;
+ 	nd_set_link(nd, s);
+ 	return NULL;
+ }
+diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
+index 34ebbc191e46..6759b9839ce8 100644
+--- a/fs/binfmt_misc.c
++++ b/fs/binfmt_misc.c
+@@ -517,7 +517,7 @@ static struct inode *bm_get_inode(struct super_block *sb, int mode)
+ 
+ static void bm_clear_inode(struct inode *inode)
+ {
+-	kfree(inode->u.generic_ip);
++	kfree(inode->i_private);
+ }
+ 
+ static void kill_node(Node *e)
+@@ -545,7 +545,7 @@ static void kill_node(Node *e)
+ static ssize_t
+ bm_entry_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos)
+ {
+-	Node *e = file->f_dentry->d_inode->u.generic_ip;
++	Node *e = file->f_dentry->d_inode->i_private;
+ 	loff_t pos = *ppos;
+ 	ssize_t res;
+ 	char *page;
+@@ -579,7 +579,7 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
+ 				size_t count, loff_t *ppos)
+ {
+ 	struct dentry *root;
+-	Node *e = file->f_dentry->d_inode->u.generic_ip;
++	Node *e = file->f_dentry->d_inode->i_private;
+ 	int res = parse_command(buffer, count);
+ 
+ 	switch (res) {
+@@ -646,7 +646,7 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer,
+ 	}
+ 
+ 	e->dentry = dget(dentry);
+-	inode->u.generic_ip = e;
++	inode->i_private = e;
+ 	inode->i_fop = &bm_entry_operations;
+ 
+ 	d_instantiate(dentry, inode);
+diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
+index e4b430552c88..bf3901ab1744 100644
+--- a/fs/debugfs/file.c
++++ b/fs/debugfs/file.c
+@@ -32,8 +32,8 @@ static ssize_t default_write_file(struct file *file, const char __user *buf,
+ 
+ static int default_open(struct inode *inode, struct file *file)
+ {
+-	if (inode->u.generic_ip)
+-		file->private_data = inode->u.generic_ip;
++	if (inode->i_private)
++		file->private_data = inode->i_private;
+ 
+ 	return 0;
+ }
+diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
+index 3ca268d2e5a2..717f4821ed02 100644
+--- a/fs/debugfs/inode.c
++++ b/fs/debugfs/inode.c
+@@ -168,7 +168,7 @@ static int debugfs_create_by_name(const char *name, mode_t mode,
+  *          directory dentry if set.  If this paramater is NULL, then the
+  *          file will be created in the root of the debugfs filesystem.
+  * @data: a pointer to something that the caller will want to get to later
+- *        on.  The inode.u.generic_ip pointer will point to this value on
++ *        on.  The inode.i_private pointer will point to this value on
+  *        the open() call.
+  * @fops: a pointer to a struct file_operations that should be used for
+  *        this file.
+@@ -209,7 +209,7 @@ struct dentry *debugfs_create_file(const char *name, mode_t mode,
+ 
+ 	if (dentry->d_inode) {
+ 		if (data)
+-			dentry->d_inode->u.generic_ip = data;
++			dentry->d_inode->i_private = data;
+ 		if (fops)
+ 			dentry->d_inode->i_fop = fops;
+ 	}
+diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
+index f7aef5bb584a..5bf06a10dddf 100644
+--- a/fs/devpts/inode.c
++++ b/fs/devpts/inode.c
+@@ -177,7 +177,7 @@ int devpts_pty_new(struct tty_struct *tty)
+ 	inode->i_gid = config.setgid ? config.gid : current->fsgid;
+ 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ 	init_special_inode(inode, S_IFCHR|config.mode, device);
+-	inode->u.generic_ip = tty;
++	inode->i_private = tty;
+ 
+ 	dentry = get_node(number);
+ 	if (!IS_ERR(dentry) && !dentry->d_inode)
+@@ -196,7 +196,7 @@ struct tty_struct *devpts_get_tty(int number)
+ 	tty = NULL;
+ 	if (!IS_ERR(dentry)) {
+ 		if (dentry->d_inode)
+-			tty = dentry->d_inode->u.generic_ip;
++			tty = dentry->d_inode->i_private;
+ 		dput(dentry);
+ 	}
+ 
+diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h
+index d35979a58743..c8a92652612a 100644
+--- a/fs/freevxfs/vxfs.h
++++ b/fs/freevxfs/vxfs.h
+@@ -252,7 +252,7 @@ enum {
+  * Get filesystem private data from VFS inode.
+  */
+ #define VXFS_INO(ip) \
+-	((struct vxfs_inode_info *)(ip)->u.generic_ip)
++	((struct vxfs_inode_info *)(ip)->i_private)
+ 
+ /*
+  * Get filesystem private data from VFS superblock.
+diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
+index ca6a39714771..32a82ed108e4 100644
+--- a/fs/freevxfs/vxfs_inode.c
++++ b/fs/freevxfs/vxfs_inode.c
+@@ -243,7 +243,7 @@ vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip)
+ 	ip->i_blocks = vip->vii_blocks;
+ 	ip->i_generation = vip->vii_gen;
+ 
+-	ip->u.generic_ip = (void *)vip;
++	ip->i_private = vip;
+ 	
+ }
+ 
+@@ -338,5 +338,5 @@ vxfs_read_inode(struct inode *ip)
+ void
+ vxfs_clear_inode(struct inode *ip)
+ {
+-	kmem_cache_free(vxfs_inode_cachep, ip->u.generic_ip);
++	kmem_cache_free(vxfs_inode_cachep, ip->i_private);
+ }
+diff --git a/fs/fuse/control.c b/fs/fuse/control.c
+index 46fe60b2da23..79ec1f23d4d2 100644
+--- a/fs/fuse/control.c
++++ b/fs/fuse/control.c
+@@ -23,7 +23,7 @@ static struct fuse_conn *fuse_ctl_file_conn_get(struct file *file)
+ {
+ 	struct fuse_conn *fc;
+ 	mutex_lock(&fuse_mutex);
+-	fc = file->f_dentry->d_inode->u.generic_ip;
++	fc = file->f_dentry->d_inode->i_private;
+ 	if (fc)
+ 		fc = fuse_conn_get(fc);
+ 	mutex_unlock(&fuse_mutex);
+@@ -98,7 +98,7 @@ static struct dentry *fuse_ctl_add_dentry(struct dentry *parent,
+ 		inode->i_op = iop;
+ 	inode->i_fop = fop;
+ 	inode->i_nlink = nlink;
+-	inode->u.generic_ip = fc;
++	inode->i_private = fc;
+ 	d_add(dentry, inode);
+ 	return dentry;
+ }
+@@ -150,7 +150,7 @@ void fuse_ctl_remove_conn(struct fuse_conn *fc)
+ 
+ 	for (i = fc->ctl_ndents - 1; i >= 0; i--) {
+ 		struct dentry *dentry = fc->ctl_dentry[i];
+-		dentry->d_inode->u.generic_ip = NULL;
++		dentry->d_inode->i_private = NULL;
+ 		d_drop(dentry);
+ 		dput(dentry);
+ 	}
+diff --git a/fs/inode.c b/fs/inode.c
+index 0bf9f0444a96..77e254792025 100644
+--- a/fs/inode.c
++++ b/fs/inode.c
+@@ -163,7 +163,7 @@ static struct inode *alloc_inode(struct super_block *sb)
+ 				bdi = sb->s_bdev->bd_inode->i_mapping->backing_dev_info;
+ 			mapping->backing_dev_info = bdi;
+ 		}
+-		memset(&inode->u, 0, sizeof(inode->u));
++		inode->i_private = 0;
+ 		inode->i_mapping = mapping;
+ 	}
+ 	return inode;
+diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
+index b59553d28d13..7358ef87f16b 100644
+--- a/fs/jffs/inode-v23.c
++++ b/fs/jffs/inode-v23.c
+@@ -369,7 +369,7 @@ jffs_new_inode(const struct inode * dir, struct jffs_raw_inode *raw_inode,
+ 
+ 	f = jffs_find_file(c, raw_inode->ino);
+ 
+-	inode->u.generic_ip = (void *)f;
++	inode->i_private = (void *)f;
+ 	insert_inode_hash(inode);
+ 
+ 	return inode;
+@@ -442,7 +442,7 @@ jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 	});
+ 
+ 	result = -ENOTDIR;
+-	if (!(old_dir_f = (struct jffs_file *)old_dir->u.generic_ip)) {
++	if (!(old_dir_f = old_dir->i_private)) {
+ 		D(printk("jffs_rename(): Old dir invalid.\n"));
+ 		goto jffs_rename_end;
+ 	}
+@@ -456,7 +456,7 @@ jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 
+ 	/* Find the new directory.  */
+ 	result = -ENOTDIR;
+-	if (!(new_dir_f = (struct jffs_file *)new_dir->u.generic_ip)) {
++	if (!(new_dir_f = new_dir->i_private)) {
+ 		D(printk("jffs_rename(): New dir invalid.\n"));
+ 		goto jffs_rename_end;
+ 	}
+@@ -593,7 +593,7 @@ jffs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ 		}
+ 		else {
+ 			ddino = ((struct jffs_file *)
+-				 inode->u.generic_ip)->pino;
++				 inode->i_private)->pino;
+ 		}
+ 		D3(printk("jffs_readdir(): \"..\" %u\n", ddino));
+ 		if (filldir(dirent, "..", 2, filp->f_pos, ddino, DT_DIR) < 0) {
+@@ -604,7 +604,7 @@ jffs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ 		}
+ 		filp->f_pos++;
+ 	}
+-	f = ((struct jffs_file *)inode->u.generic_ip)->children;
++	f = ((struct jffs_file *)inode->i_private)->children;
+ 
+ 	j = 2;
+ 	while(f && (f->deleted || j++ < filp->f_pos )) {
+@@ -668,7 +668,7 @@ jffs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+ 	}
+ 
+ 	r = -EACCES;
+-	if (!(d = (struct jffs_file *)dir->u.generic_ip)) {
++	if (!(d = (struct jffs_file *)dir->i_private)) {
+ 		D(printk("jffs_lookup(): No such inode! (%lu)\n",
+ 			 dir->i_ino));
+ 		goto jffs_lookup_end;
+@@ -739,7 +739,7 @@ jffs_do_readpage_nolock(struct file *file, struct page *page)
+ 	unsigned long read_len;
+ 	int result;
+ 	struct inode *inode = (struct inode*)page->mapping->host;
+-	struct jffs_file *f = (struct jffs_file *)inode->u.generic_ip;
++	struct jffs_file *f = (struct jffs_file *)inode->i_private;
+ 	struct jffs_control *c = (struct jffs_control *)inode->i_sb->s_fs_info;
+ 	int r;
+ 	loff_t offset;
+@@ -828,7 +828,7 @@ jffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+ 	});
+ 
+ 	lock_kernel();
+-	dir_f = (struct jffs_file *)dir->u.generic_ip;
++	dir_f = dir->i_private;
+ 
+ 	ASSERT(if (!dir_f) {
+ 		printk(KERN_ERR "jffs_mkdir(): No reference to a "
+@@ -972,7 +972,7 @@ jffs_remove(struct inode *dir, struct dentry *dentry, int type)
+ 		kfree(_name);
+ 	});
+ 
+-	dir_f = (struct jffs_file *) dir->u.generic_ip;
++	dir_f = dir->i_private;
+ 	c = dir_f->c;
+ 
+ 	result = -ENOENT;
+@@ -1082,7 +1082,7 @@ jffs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
+ 	if (!old_valid_dev(rdev))
+ 		return -EINVAL;
+ 	lock_kernel();
+-	dir_f = (struct jffs_file *)dir->u.generic_ip;
++	dir_f = dir->i_private;
+ 	c = dir_f->c;
+ 
+ 	D3(printk (KERN_NOTICE "mknod(): down biglock\n"));
+@@ -1186,7 +1186,7 @@ jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
+ 		kfree(_symname);
+ 	});
+ 
+-	dir_f = (struct jffs_file *)dir->u.generic_ip;
++	dir_f = dir->i_private;
+ 	ASSERT(if (!dir_f) {
+ 		printk(KERN_ERR "jffs_symlink(): No reference to a "
+ 		       "jffs_file struct in inode.\n");
+@@ -1289,7 +1289,7 @@ jffs_create(struct inode *dir, struct dentry *dentry, int mode,
+ 		kfree(s);
+ 	});
+ 
+-	dir_f = (struct jffs_file *)dir->u.generic_ip;
++	dir_f = dir->i_private;
+ 	ASSERT(if (!dir_f) {
+ 		printk(KERN_ERR "jffs_create(): No reference to a "
+ 		       "jffs_file struct in inode.\n");
+@@ -1403,9 +1403,9 @@ jffs_file_write(struct file *filp, const char *buf, size_t count,
+ 		goto out_isem;
+ 	}
+ 
+-	if (!(f = (struct jffs_file *)inode->u.generic_ip)) {
+-		D(printk("jffs_file_write(): inode->u.generic_ip = 0x%p\n",
+-				inode->u.generic_ip));
++	if (!(f = inode->i_private)) {
++		D(printk("jffs_file_write(): inode->i_private = 0x%p\n",
++				inode->i_private));
+ 		goto out_isem;
+ 	}
+ 
+@@ -1693,7 +1693,7 @@ jffs_read_inode(struct inode *inode)
+ 		mutex_unlock(&c->fmc->biglock);
+ 		return;
+ 	}
+-	inode->u.generic_ip = (void *)f;
++	inode->i_private = f;
+ 	inode->i_mode = f->mode;
+ 	inode->i_nlink = f->nlink;
+ 	inode->i_uid = f->uid;
+@@ -1748,7 +1748,7 @@ jffs_delete_inode(struct inode *inode)
+ 	lock_kernel();
+ 	inode->i_size = 0;
+ 	inode->i_blocks = 0;
+-	inode->u.generic_ip = NULL;
++	inode->i_private = NULL;
+ 	clear_inode(inode);
+ 	if (inode->i_nlink == 0) {
+ 		c = (struct jffs_control *) inode->i_sb->s_fs_info;
+diff --git a/fs/libfs.c b/fs/libfs.c
+index ac02ea602c3d..2751793beeaa 100644
+--- a/fs/libfs.c
++++ b/fs/libfs.c
+@@ -547,7 +547,7 @@ int simple_attr_open(struct inode *inode, struct file *file,
+ 
+ 	attr->get = get;
+ 	attr->set = set;
+-	attr->data = inode->u.generic_ip;
++	attr->data = inode->i_private;
+ 	attr->fmt = fmt;
+ 	mutex_init(&attr->mutex);
+ 
+diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
+index de887063dcfc..8801e41afe80 100644
+--- a/fs/ocfs2/dlmglue.c
++++ b/fs/ocfs2/dlmglue.c
+@@ -2052,7 +2052,7 @@ static int ocfs2_dlm_debug_open(struct inode *inode, struct file *file)
+ 		mlog_errno(ret);
+ 		goto out;
+ 	}
+-	osb = (struct ocfs2_super *) inode->u.generic_ip;
++	osb = inode->i_private;
+ 	ocfs2_get_dlm_debug(osb->osb_dlm_debug);
+ 	priv->p_dlm_debug = osb->osb_dlm_debug;
+ 	INIT_LIST_HEAD(&priv->p_iter_res.l_debug_list);
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 1d3e601ece73..4f77ec9c3353 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -554,9 +554,7 @@ struct inode {
+ 
+ 	atomic_t		i_writecount;
+ 	void			*i_security;
+-	union {
+-		void		*generic_ip;
+-	} u;
++	void			*i_private; /* fs or device private pointer */
+ #ifdef __NEED_I_SIZE_ORDERED
+ 	seqcount_t		i_size_seqcount;
+ #endif
+diff --git a/kernel/relay.c b/kernel/relay.c
+index 33345e73485c..85786ff2a4f9 100644
+--- a/kernel/relay.c
++++ b/kernel/relay.c
+@@ -669,7 +669,7 @@ EXPORT_SYMBOL_GPL(relay_flush);
+  */
+ static int relay_file_open(struct inode *inode, struct file *filp)
+ {
+-	struct rchan_buf *buf = inode->u.generic_ip;
++	struct rchan_buf *buf = inode->i_private;
+ 	kref_get(&buf->kref);
+ 	filp->private_data = buf;
+ 
+diff --git a/security/inode.c b/security/inode.c
+index 47eb63480dac..176aacea8ca4 100644
+--- a/security/inode.c
++++ b/security/inode.c
+@@ -44,8 +44,8 @@ static ssize_t default_write_file(struct file *file, const char __user *buf,
+ 
+ static int default_open(struct inode *inode, struct file *file)
+ {
+-	if (inode->u.generic_ip)
+-		file->private_data = inode->u.generic_ip;
++	if (inode->i_private)
++		file->private_data = inode->i_private;
+ 
+ 	return 0;
+ }
+@@ -194,7 +194,7 @@ static int create_by_name(const char *name, mode_t mode,
+  *          directory dentry if set.  If this paramater is NULL, then the
+  *          file will be created in the root of the securityfs filesystem.
+  * @data: a pointer to something that the caller will want to get to later
+- *        on.  The inode.u.generic_ip pointer will point to this value on
++ *        on.  The inode.i_private pointer will point to this value on
+  *        the open() call.
+  * @fops: a pointer to a struct file_operations that should be used for
+  *        this file.
+@@ -240,7 +240,7 @@ struct dentry *securityfs_create_file(const char *name, mode_t mode,
+ 		if (fops)
+ 			dentry->d_inode->i_fop = fops;
+ 		if (data)
+-			dentry->d_inode->u.generic_ip = data;
++			dentry->d_inode->i_private = data;
+ 	}
+ exit:
+ 	return dentry;

commit c61a8416ed3db84481651270032696a4781cac17
+Author: Theodore Tso 
+Date:   Mon Jul 3 00:24:09 2006 -0700
+
+    [PATCH] uml build fix
+    
+    This is needed to fix UML compilation given that alternatives_smp_module_add
+    and alternatives_smp_module_del are null inline functions if !CONFIG_SMP.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Cc: Jeff Dike 
+    Cc: Paolo 'Blaisorblade' Giarrusso 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
+index 7d51dd7201c3..37cfe7701f06 100644
+--- a/arch/um/kernel/um_arch.c
++++ b/arch/um/kernel/um_arch.c
+@@ -495,6 +495,7 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
+ {
+ }
+ 
++#ifdef CONFIG_SMP
+ void alternatives_smp_module_add(struct module *mod, char *name,
+ 				 void *locks, void *locks_end,
+ 				 void *text,  void *text_end)
+@@ -504,3 +505,4 @@ void alternatives_smp_module_add(struct module *mod, char *name,
+ void alternatives_smp_module_del(struct module *mod)
+ {
+ }
++#endif

commit d2e5b13c4a7c68fdbcf389c9fffc12cfa2c185af
+Author: Theodore Ts'o 
+Date:   Sun Jun 25 05:47:52 2006 -0700
+
+    [PATCH] ext3: remove inconsistent space before exclamation point in mount code
+    
+    This was reported as Debian bug #336604.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/ext3/super.c b/fs/ext3/super.c
+index df98a7709252..e0fc0c83be90 100644
+--- a/fs/ext3/super.c
++++ b/fs/ext3/super.c
+@@ -1603,7 +1603,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
+ 		}
+ 	}
+ 	if (!ext3_check_descriptors (sb)) {
+-		printk (KERN_ERR "EXT3-fs: group descriptors corrupted !\n");
++		printk(KERN_ERR "EXT3-fs: group descriptors corrupted!\n");
+ 		goto failed_mount2;
+ 	}
+ 	sbi->s_gdb_count = db_count;

commit e8f1c6227a0bc9b1e3a7e87cd31f650a909f647f
+Author: Theodore Ts'o 
+Date:   Sun Jun 25 05:47:51 2006 -0700
+
+    [PATCH] ext3: fix memory leak when the journal file is corrupted
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/jbd/recovery.c b/fs/jbd/recovery.c
+index 80d7f53fd0a7..de5bafb4e853 100644
+--- a/fs/jbd/recovery.c
++++ b/fs/jbd/recovery.c
+@@ -531,6 +531,7 @@ static int do_one_pass(journal_t *journal,
+ 		default:
+ 			jbd_debug(3, "Unrecognised magic %d, end of scan.\n",
+ 				  blocktype);
++			brelse(bh);
+ 			goto done;
+ 		}
+ 	}

commit f16fdadba28add689b567cf03c21dd6dec8e43be
+Author: Theodore Ts'o 
+Date:   Sun Jun 25 05:47:50 2006 -0700
+
+    [PATCH] ext2: clean up dead code from mount code
+    
+    The variable i is guaranteed to be the same as db_count given the previous
+    for loop.  So get rid of it since it's dead code.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/ext2/super.c b/fs/ext2/super.c
+index ee4ba759581e..fec55ff23dea 100644
+--- a/fs/ext2/super.c
++++ b/fs/ext2/super.c
+@@ -854,7 +854,6 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
+ 	}
+ 	if (!ext2_check_descriptors (sb)) {
+ 		printk ("EXT2-fs: group descriptors corrupted!\n");
+-		db_count = i;
+ 		goto failed_mount2;
+ 	}
+ 	sbi->s_gdb_count = db_count;

commit ac031f26e89cc04fc7504f31ae137857eb83a051
+Author: Theodore Ts'o 
+Date:   Wed Jun 21 20:53:09 2006 -0400
+
+    kbuild: add option for stripping modules while installing them
+    
+    Add option for stripping modules while installing them.
+    
+    This function adds support for stripping modules while they are being
+    installed.  CONFIG_DEBUG_KERNEL (which will probably become more
+    popular as developers use kdump) causes the size of the installed
+    modules to grow by a factor of 9 or so.
+    
+    Some kernel package systems solve this problem by stripping the debug
+    information from /lib/modules after running "make modules_install",
+    but that may not work for people who are installing directly into
+    /lib/modules --- root partitions that were sized to handle 16 megs
+    worth of modules may not be quite so happy with 145 megs of modules,
+    so the "make modules_install" never succeeds.
+    
+    This patch allows such users to request modules_install to strip the
+    modules as they are installed.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Sam Ravnborg 
+
+diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
+index a9c00facdf40..14ef3868a328 100644
+--- a/Documentation/kbuild/makefiles.txt
++++ b/Documentation/kbuild/makefiles.txt
+@@ -1123,6 +1123,14 @@ The top Makefile exports the following variables:
+ 	$(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE).  The user may
+ 	override this value on the command line if desired.
+ 
++    INSTALL_MOD_STRIP
++
++	If this variable is specified, will cause modules to be stripped
++	after they are installed.  If INSTALL_MOD_STRIP is '1', then the
++	default option --strip-debug will be used.  Otherwise,
++	INSTALL_MOD_STRIP will used as the option(s) to the strip command.
++
++
+ === 8 Makefile language
+ 
+ The kernel Makefiles are designed to run with GNU Make.  The Makefiles
+diff --git a/Makefile b/Makefile
+index 1b2fd97f503a..d810d6cb4d08 100644
+--- a/Makefile
++++ b/Makefile
+@@ -512,6 +512,23 @@ export	INSTALL_PATH ?= /boot
+ MODLIB	= $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
+ export MODLIB
+ 
++#
++#  INSTALL_MOD_STRIP, if defined, will cause modules to be
++#  stripped after they are installed.  If INSTALL_MOD_STRIP is '1', then
++#  the default option --strip-debug will be used.  Otherwise,
++#  INSTALL_MOD_STRIP will used as the options to the strip command.
++
++ifdef INSTALL_MOD_STRIP
++ifeq ($(INSTALL_MOD_STRIP),1)
++mod_strip_cmd = $STRIP) --strip-debug
++else
++mod_strip_cmd = $(STRIP) $(INSTALL_MOD_STRIP)
++endif # INSTALL_MOD_STRIP=1
++else
++mod_strip_cmd = true
++endif # INSTALL_MOD_STRIP
++export mod_strip_cmd
++
+ 
+ ifeq ($(KBUILD_EXTMOD),)
+ core-y		+= kernel/ mm/ fs/ ipc/ security/ crypto/ block/
+diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst
+index 2686dd5dce8c..f0ff248f5e6f 100644
+--- a/scripts/Makefile.modinst
++++ b/scripts/Makefile.modinst
+@@ -17,7 +17,7 @@ __modinst: $(modules)
+ 	@:
+ 
+ quiet_cmd_modules_install = INSTALL $@
+-      cmd_modules_install = mkdir -p $(2); cp $@ $(2)
++      cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@)
+ 
+ # Modules built outside the kernel source tree go into extra by default
+ INSTALL_MOD_DIR ?= extra

commit ae0718f8e3fcfa3e4863f63db90d24bbec6b14a2
+Author: Theodore Tso 
+Date:   Sat May 20 15:00:13 2006 -0700
+
+    [PATCH] Update ext2/ext3/jbd MAINTAINERS entries
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 89c066be5489..bd10b2af2223 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -978,7 +978,7 @@ S:	Maintained
+ EXT3 FILE SYSTEM
+ P:	Stephen Tweedie, Andrew Morton
+ M:	sct@redhat.com, akpm@osdl.org, adilger@clusterfs.com
+-L:	ext3-users@redhat.com
++L:	ext2-devel@lists.sourceforge.net
+ S:	Maintained
+ 
+ F71805F HARDWARE MONITORING DRIVER
+@@ -1539,6 +1539,12 @@ W:	http://jfs.sourceforge.net/
+ T:	git kernel.org:/pub/scm/linux/kernel/git/shaggy/jfs-2.6.git
+ S:	Supported
+ 
++JOURNALLING LAYER FOR BLOCK DEVICS (JBD)
++P:	Stephen Tweedie, Andrew Morton
++M:	sct@redhat.com, akpm@osdl.org
++L:	ext2-devel@lists.sourceforge.net
++S:	Maintained
++
+ KCONFIG
+ P:	Roman Zippel
+ M:	zippel@linux-m68k.org

commit 9b04c997b1120feefa1e6ee8e2902270bc055cd2
+Author: Theodore Ts'o 
+Date:   Fri Mar 24 03:15:10 2006 -0800
+
+    [PATCH] vfs: MS_VERBOSE should be MS_SILENT
+    
+    The meaning of MS_VERBOSE is backwards; if the bit is set, it really means,
+    "don't be verbose".  This is confusing and counter-intuitive.
+    
+    In addition, there is also no way to set the MS_VERBOSE flag in the
+    mount(8) program in util-linux, but interesting, it does define options
+    which would do the right thing if MS_SILENT were defined, which
+    unfortunately we do not:
+    
+    #ifdef MS_SILENT
+      { "quiet",    0, 0, MS_SILENT    },   /* be quiet  */
+      { "loud",     0, 1, MS_SILENT    },   /* print out messages. */
+    #endif
+    
+    So the obvious fix is to deprecate the use of MS_VERBOSE and replace it
+    with MS_SILENT.
+    
+    Signed-off-by: "Theodore Ts'o" 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/afs/super.c b/fs/afs/super.c
+index d6fa8e5999df..53c56e7231ab 100644
+--- a/fs/afs/super.c
++++ b/fs/afs/super.c
+@@ -341,7 +341,7 @@ static struct super_block *afs_get_sb(struct file_system_type *fs_type,
+ 
+ 	sb->s_flags = flags;
+ 
+-	ret = afs_fill_super(sb, ¶ms, flags & MS_VERBOSE ? 1 : 0);
++	ret = afs_fill_super(sb, ¶ms, flags & MS_SILENT ? 1 : 0);
+ 	if (ret < 0) {
+ 		up_write(&sb->s_umount);
+ 		deactivate_super(sb);
+diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
+index 79eeccd0437f..1cd044ce82a6 100644
+--- a/fs/cifs/cifsfs.c
++++ b/fs/cifs/cifsfs.c
+@@ -479,7 +479,7 @@ cifs_get_sb(struct file_system_type *fs_type,
+ 
+ 	sb->s_flags = flags;
+ 
+-	rc = cifs_read_super(sb, data, dev_name, flags & MS_VERBOSE ? 1 : 0);
++	rc = cifs_read_super(sb, data, dev_name, flags & MS_SILENT ? 1 : 0);
+ 	if (rc) {
+ 		up_write(&sb->s_umount);
+ 		deactivate_super(sb);
+diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
+index 93883817cbd0..c8fac352a4cf 100644
+--- a/fs/jffs2/super.c
++++ b/fs/jffs2/super.c
+@@ -152,7 +152,7 @@ static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type,
+ 	sb->s_op = &jffs2_super_operations;
+ 	sb->s_flags = flags | MS_NOATIME;
+ 
+-	ret = jffs2_do_fill_super(sb, data, (flags&MS_VERBOSE)?1:0);
++	ret = jffs2_do_fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
+ 
+ 	if (ret) {
+ 		/* Failure case... */
+@@ -257,7 +257,7 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type,
+ 	}
+ 
+ 	if (imajor(nd.dentry->d_inode) != MTD_BLOCK_MAJOR) {
+-		if (!(flags & MS_VERBOSE)) /* Yes I mean this. Strangely */
++		if (!(flags & MS_SILENT))
+ 			printk(KERN_NOTICE "Attempt to mount non-MTD device \"%s\" as JFFS2\n",
+ 			       dev_name);
+ 		goto out;
+diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
+index a77ee95b7efb..37e55c328ebc 100644
+--- a/fs/nfs/inode.c
++++ b/fs/nfs/inode.c
+@@ -1679,7 +1679,7 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
+ 
+ 	s->s_flags = flags;
+ 
+-	error = nfs_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
++	error = nfs_fill_super(s, data, flags & MS_SILENT ? 1 : 0);
+ 	if (error) {
+ 		up_write(&s->s_umount);
+ 		deactivate_super(s);
+@@ -1996,7 +1996,7 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
+ 
+ 	s->s_flags = flags;
+ 
+-	error = nfs4_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
++	error = nfs4_fill_super(s, data, flags & MS_SILENT ? 1 : 0);
+ 	if (error) {
+ 		up_write(&s->s_umount);
+ 		deactivate_super(s);
+diff --git a/fs/super.c b/fs/super.c
+index 425861cb1caa..37554b876182 100644
+--- a/fs/super.c
++++ b/fs/super.c
+@@ -712,7 +712,7 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type,
+ 		s->s_flags = flags;
+ 		strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));
+ 		sb_set_blocksize(s, block_size(bdev));
+-		error = fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
++		error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
+ 		if (error) {
+ 			up_write(&s->s_umount);
+ 			deactivate_super(s);
+@@ -756,7 +756,7 @@ struct super_block *get_sb_nodev(struct file_system_type *fs_type,
+ 
+ 	s->s_flags = flags;
+ 
+-	error = fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
++	error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
+ 	if (error) {
+ 		up_write(&s->s_umount);
+ 		deactivate_super(s);
+@@ -785,7 +785,7 @@ struct super_block *get_sb_single(struct file_system_type *fs_type,
+ 		return s;
+ 	if (!s->s_root) {
+ 		s->s_flags = flags;
+-		error = fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
++		error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
+ 		if (error) {
+ 			up_write(&s->s_umount);
+ 			deactivate_super(s);
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 9b34a1b03455..65e6df247ea5 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -103,7 +103,9 @@ extern int dir_notify_enable;
+ #define MS_BIND		4096
+ #define MS_MOVE		8192
+ #define MS_REC		16384
+-#define MS_VERBOSE	32768
++#define MS_VERBOSE	32768	/* War is peace. Verbosity is silence.
++				   MS_VERBOSE is deprecated. */
++#define MS_SILENT	32768
+ #define MS_POSIXACL	(1<<16)	/* VFS does not apply the umask */
+ #define MS_UNBINDABLE	(1<<17)	/* change to unbindable */
+ #define MS_PRIVATE	(1<<18)	/* change to private */
+diff --git a/init/do_mounts.c b/init/do_mounts.c
+index b27c11064409..8b671fe68afa 100644
+--- a/init/do_mounts.c
++++ b/init/do_mounts.c
+@@ -19,7 +19,7 @@ extern int get_filesystem_list(char * buf);
+ 
+ int __initdata rd_doload;	/* 1 = load RAM disk, 0 = don't load */
+ 
+-int root_mountflags = MS_RDONLY | MS_VERBOSE;
++int root_mountflags = MS_RDONLY | MS_SILENT;
+ char * __initdata root_device_name;
+ static char __initdata saved_root_name[64];
+ 

commit e4e5d324b9c5586f408a72d1534474c449dd5212
+Author: Bryan Ford 
+Date:   Sat Nov 5 17:25:54 2005 +0100
+
+    [PATCH] x86_64: Save/restore CS in 64bit signal handlers and force __USER_CS for CS
+    
+    This allows to run 64bit signal handlers in 64bit processes that run small
+    code snippets in compat mode.
+    
+    Signed-off-by: Andi Kleen 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c
+index d642fbf3da29..5876df116c92 100644
+--- a/arch/x86_64/kernel/signal.c
++++ b/arch/x86_64/kernel/signal.c
+@@ -110,6 +110,15 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned
+ 	COPY(r14);
+ 	COPY(r15);
+ 
++	/* Kernel saves and restores only the CS segment register on signals,
++	 * which is the bare minimum needed to allow mixed 32/64-bit code.
++	 * App's signal handler can save/restore other segments if needed. */
++	{
++		unsigned cs;
++		err |= __get_user(cs, &sc->cs);
++		regs->cs = cs | 3;	/* Force into user mode */
++	}
++
+ 	{
+ 		unsigned int tmpflags;
+ 		err |= __get_user(tmpflags, &sc->eflags);
+@@ -187,6 +196,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned lo
+ {
+ 	int err = 0;
+ 
++	err |= __put_user(regs->cs, &sc->cs);
+ 	err |= __put_user(0, &sc->gs);
+ 	err |= __put_user(0, &sc->fs);
+ 
+@@ -318,7 +328,14 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ 
+ 	regs->rsp = (unsigned long)frame;
+ 
++	/* Set up the CS register to run signal handlers in 64-bit mode,
++	   even if the handler happens to be interrupting 32-bit code. */
++	regs->cs = __USER_CS;
++
++	/* This, by contrast, has nothing to do with segment registers -
++	   see include/asm-x86_64/uaccess.h for details. */
+ 	set_fs(USER_DS);
++
+ 	regs->eflags &= ~TF_MASK;
+ 	if (test_thread_flag(TIF_SINGLESTEP))
+ 		ptrace_notify(SIGTRAP);

commit 52609c0b56d7c8dfb6e16ec0a715adf8fcbdae36
+Author: David Chau 
+Date:   Tue Jul 5 15:11:06 2005 -0700
+
+    [NET]: improve readability of dev_set_promiscuity() in net/core/dev.c
+    
+    A trivial patch to improve the readability of dev_set_promiscuity()
+    in net/core/dev.c. New code does exactly the same thing as original
+    code.
+    
+    Signed-off-by: David Chau 
+    Signed-off-by: Domen Puncer 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/core/dev.c b/net/core/dev.c
+index 7016e0c36b3d..7f5f62c65115 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -2089,10 +2089,11 @@ void dev_set_promiscuity(struct net_device *dev, int inc)
+ {
+ 	unsigned short old_flags = dev->flags;
+ 
+-	dev->flags |= IFF_PROMISC;
+ 	if ((dev->promiscuity += inc) == 0)
+ 		dev->flags &= ~IFF_PROMISC;
+-	if (dev->flags ^ old_flags) {
++	else
++		dev->flags |= IFF_PROMISC;
++	if (dev->flags != old_flags) {
+ 		dev_mc_upload(dev);
+ 		printk(KERN_INFO "device %s %s promiscuous mode\n",
+ 		       dev->name, (dev->flags & IFF_PROMISC) ? "entered" :

commit e31a5c5cfeab70d3554e237daf9e319265cbb411
+Author: Srivatsa S. Bhat (VMware) 
+Date:   Fri May 12 09:49:56 2023 -0700
+
+    MAINTAINERS: Update Srivatsa S. Bhat's maintained areas
+    
+    I have decided to change employers and I'm not sure if I'll be able to
+    spend as much time on the subsystems/drivers I maintain. So, I would
+    like to remove myself from the maintainer role.
+    
+    Remove Srivatsa from the maintainers entry and add Ajay Kaher as an
+    additional reviewer/maintainer for the respective areas. Also, add an
+    entry to CREDITS for Srivatsa.
+    
+      [ bp: Merge all three into one patch, adjust commit message. ]
+    
+    Signed-off-by: Srivatsa S. Bhat (VMware) 
+    Signed-off-by: Borislav Petkov (AMD) 
+    Acked-by: Alexey Makhalov 
+    Acked-by: Ajay Kaher 
+    Acked-by: Juergen Gross 
+    Link: https://lore.kernel.org/r/20230512164958.575174-1-srivatsa@csail.mit.edu
+
+diff --git a/CREDITS b/CREDITS
+index 2d9da9a7defa..670c256aff5d 100644
+--- a/CREDITS
++++ b/CREDITS
+@@ -383,6 +383,12 @@ E: tomas@nocrew.org
+ W: http://tomas.nocrew.org/
+ D: dsp56k device driver
+ 
++N: Srivatsa S. Bhat
++E: srivatsa@csail.mit.edu
++D: Maintainer of Generic Paravirt-Ops subsystem
++D: Maintainer of VMware hypervisor interface
++D: Maintainer of VMware virtual PTP clock driver (ptp_vmw)
++
+ N: Ross Biro
+ E: ross.biro@gmail.com
+ D: Original author of the Linux networking code
+diff --git a/MAINTAINERS b/MAINTAINERS
+index e0ad886d3163..a00bea4d7438 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -15929,7 +15929,7 @@ F:	include/uapi/linux/ppdev.h
+ 
+ PARAVIRT_OPS INTERFACE
+ M:	Juergen Gross 
+-M:	Srivatsa S. Bhat (VMware) 
++R:	Ajay Kaher 
+ R:	Alexey Makhalov 
+ R:	VMware PV-Drivers Reviewers 
+ L:	virtualization@lists.linux-foundation.org
+@@ -22493,7 +22493,7 @@ S:	Supported
+ F:	drivers/misc/vmw_balloon.c
+ 
+ VMWARE HYPERVISOR INTERFACE
+-M:	Srivatsa S. Bhat (VMware) 
++M:	Ajay Kaher 
+ M:	Alexey Makhalov 
+ R:	VMware PV-Drivers Reviewers 
+ L:	virtualization@lists.linux-foundation.org
+@@ -22520,8 +22520,8 @@ F:	drivers/scsi/vmw_pvscsi.c
+ F:	drivers/scsi/vmw_pvscsi.h
+ 
+ VMWARE VIRTUAL PTP CLOCK DRIVER
+-M:	Srivatsa S. Bhat (VMware) 
+ M:	Deep Shah 
++R:	Ajay Kaher 
+ R:	Alexey Makhalov 
+ R:	VMware PV-Drivers Reviewers 
+ L:	netdev@vger.kernel.org

commit fcb3a81d221750d2a54b4e3a82b3efbbeab8780c
+Author: Srivatsa S. Bhat (VMware) 
+Date:   Fri Jan 27 16:37:51 2023 -0800
+
+    x86/hotplug: Remove incorrect comment about mwait_play_dead()
+    
+    The comment that says mwait_play_dead() returns only on failure is a bit
+    misleading because mwait_play_dead() could actually return for valid
+    reasons (such as mwait not being supported by the platform) that do not
+    indicate a failure of the CPU offline operation. So, remove the comment.
+    
+    Suggested-by: Thomas Gleixner 
+    Signed-off-by: Srivatsa S. Bhat (VMware) 
+    Signed-off-by: Thomas Gleixner 
+    Link: https://lore.kernel.org/r/20230128003751.141317-1-srivatsa@csail.mit.edu
+
+diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
+index 55cad72715d9..9013bb28255a 100644
+--- a/arch/x86/kernel/smpboot.c
++++ b/arch/x86/kernel/smpboot.c
+@@ -1833,7 +1833,7 @@ void native_play_dead(void)
+ 	play_dead_common();
+ 	tboot_shutdown(TB_SHUTDOWN_WFS);
+ 
+-	mwait_play_dead();	/* Only returns on failure */
++	mwait_play_dead();
+ 	if (cpuidle_play_dead())
+ 		hlt_play_dead();
+ }

commit 558016722e9d5bc0ac79c246ccd14a8a4eb028d4
+Author: Srivatsa S. Bhat (VMware) 
+Date:   Tue Jan 3 14:09:41 2023 -0800
+
+    MAINTAINERS: Update maintainers for ptp_vmw driver
+    
+    Vivek has decided to transfer the maintainership of the VMware virtual
+    PTP clock driver (ptp_vmw) to Srivatsa and Deep. Update the
+    MAINTAINERS file to reflect this change, and also add Alexey as a
+    reviewer for the driver.
+    
+    Signed-off-by: Srivatsa S. Bhat (VMware) 
+    Acked-by: Vivek Thampi 
+    Acked-by: Deep Shah 
+    Acked-by: Alexey Makhalov 
+    Signed-off-by: David S. Miller 
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 7f0b7181e60a..758878c0eddf 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -22243,7 +22243,9 @@ F:	drivers/scsi/vmw_pvscsi.c
+ F:	drivers/scsi/vmw_pvscsi.h
+ 
+ VMWARE VIRTUAL PTP CLOCK DRIVER
+-M:	Vivek Thampi 
++M:	Srivatsa S. Bhat (VMware) 
++M:	Deep Shah 
++R:	Alexey Makhalov 
+ R:	VMware PV-Drivers Reviewers 
+ L:	netdev@vger.kernel.org
+ S:	Supported

commit 686016f732420f88dd2e1d67cf4bb5dffdb93c82
+Author: Srivatsa S. Bhat (VMware) 
+Date:   Thu Feb 24 14:24:49 2022 -0800
+
+    MAINTAINERS: Mark VMware mailing list entries as email aliases
+    
+    VMware mailing lists in the MAINTAINERS file are private lists meant
+    for VMware-internal review/notification for patches to the respective
+    subsystems. Anyone can post to these addresses, but there is no public
+    read access like open mailing lists, which makes them more like email
+    aliases instead (to reach out to reviewers).
+    
+    So update all the VMware mailing list references in the MAINTAINERS
+    file to mark them as such, using "R: email-alias@vmware.com".
+    
+    Signed-off-by: Srivatsa S. Bhat (VMware) 
+    Signed-off-by: Borislav Petkov 
+    Acked-by: Juergen Gross 
+    Acked-by: Joe Perches 
+    Acked-by: Zack Rusin 
+    Link: https://lore.kernel.org/r/164574148378.654750.15832494349474144706.stgit@csail.mit.edu
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 630ac98da03e..e6e5466ec188 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -6301,8 +6301,8 @@ T:	git git://anongit.freedesktop.org/drm/drm-misc
+ F:	drivers/gpu/drm/vboxvideo/
+ 
+ DRM DRIVER FOR VMWARE VIRTUAL GPU
+-M:	"VMware Graphics" 
+ M:	Zack Rusin 
++R:	VMware Graphics Reviewers 
+ L:	dri-devel@lists.freedesktop.org
+ S:	Supported
+ T:	git git://anongit.freedesktop.org/drm/drm-misc
+@@ -14578,7 +14578,7 @@ PARAVIRT_OPS INTERFACE
+ M:	Juergen Gross 
+ M:	Srivatsa S. Bhat (VMware) 
+ R:	Alexey Makhalov 
+-M:	"VMware, Inc." 
++R:	VMware PV-Drivers Reviewers 
+ L:	virtualization@lists.linux-foundation.org
+ L:	x86@kernel.org
+ S:	Supported
+@@ -20580,7 +20580,7 @@ F:	tools/testing/vsock/
+ 
+ VMWARE BALLOON DRIVER
+ M:	Nadav Amit 
+-M:	"VMware, Inc." 
++R:	VMware PV-Drivers Reviewers 
+ L:	linux-kernel@vger.kernel.org
+ S:	Maintained
+ F:	drivers/misc/vmw_balloon.c
+@@ -20588,7 +20588,7 @@ F:	drivers/misc/vmw_balloon.c
+ VMWARE HYPERVISOR INTERFACE
+ M:	Srivatsa S. Bhat (VMware) 
+ M:	Alexey Makhalov 
+-M:	"VMware, Inc." 
++R:	VMware PV-Drivers Reviewers 
+ L:	virtualization@lists.linux-foundation.org
+ L:	x86@kernel.org
+ S:	Supported
+@@ -20599,14 +20599,14 @@ F:	arch/x86/kernel/cpu/vmware.c
+ VMWARE PVRDMA DRIVER
+ M:	Bryan Tan 
+ M:	Vishnu Dasa 
+-M:	VMware PV-Drivers 
++R:	VMware PV-Drivers Reviewers 
+ L:	linux-rdma@vger.kernel.org
+ S:	Maintained
+ F:	drivers/infiniband/hw/vmw_pvrdma/
+ 
+ VMware PVSCSI driver
+ M:	Vishal Bhakta 
+-M:	VMware PV-Drivers 
++R:	VMware PV-Drivers Reviewers 
+ L:	linux-scsi@vger.kernel.org
+ S:	Maintained
+ F:	drivers/scsi/vmw_pvscsi.c
+@@ -20614,7 +20614,7 @@ F:	drivers/scsi/vmw_pvscsi.h
+ 
+ VMWARE VIRTUAL PTP CLOCK DRIVER
+ M:	Vivek Thampi 
+-M:	"VMware, Inc." 
++R:	VMware PV-Drivers Reviewers 
+ L:	netdev@vger.kernel.org
+ S:	Supported
+ F:	drivers/ptp/ptp_vmw.c
+@@ -20622,15 +20622,15 @@ F:	drivers/ptp/ptp_vmw.c
+ VMWARE VMCI DRIVER
+ M:	Jorgen Hansen 
+ M:	Vishnu Dasa 
++R:	VMware PV-Drivers Reviewers 
+ L:	linux-kernel@vger.kernel.org
+-L:	pv-drivers@vmware.com (private)
+ S:	Maintained
+ F:	drivers/misc/vmw_vmci/
+ 
+ VMWARE VMMOUSE SUBDRIVER
+ M:	Zack Rusin 
+-M:	"VMware Graphics" 
+-M:	"VMware, Inc." 
++R:	VMware Graphics Reviewers 
++R:	VMware PV-Drivers Reviewers 
+ L:	linux-input@vger.kernel.org
+ S:	Maintained
+ F:	drivers/input/mouse/vmmouse.c
+@@ -20638,7 +20638,7 @@ F:	drivers/input/mouse/vmmouse.h
+ 
+ VMWARE VMXNET3 ETHERNET DRIVER
+ M:	Ronak Doshi 
+-M:	pv-drivers@vmware.com
++R:	VMware PV-Drivers Reviewers 
+ L:	netdev@vger.kernel.org
+ S:	Maintained
+ F:	drivers/net/vmxnet3/

commit d69079d04f9319bfd4e90b788f19927142c55901
+Author: Srivatsa S. Bhat (VMware) 
+Date:   Thu Feb 24 14:24:36 2022 -0800
+
+    MAINTAINERS: Add Zack as maintainer of vmmouse driver
+    
+    Zack Rusin will be taking over the maintainership of the VMware
+    vmmouse driver. Update the MAINTAINERS file to reflect this change.
+    
+    Signed-off-by: Srivatsa S. Bhat (VMware) 
+    Signed-off-by: Borislav Petkov 
+    Acked-by: Zack Rusin 
+    Link: https://lore.kernel.org/r/164574146977.654750.10918397477833459687.stgit@csail.mit.edu
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 4f81c3dd782f..630ac98da03e 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -20628,6 +20628,7 @@ S:	Maintained
+ F:	drivers/misc/vmw_vmci/
+ 
+ VMWARE VMMOUSE SUBDRIVER
++M:	Zack Rusin 
+ M:	"VMware Graphics" 
+ M:	"VMware, Inc." 
+ L:	linux-input@vger.kernel.org

commit 01683580c65ffe0ce72d52cfb5225b80b477c598
+Author: Srivatsa S. Bhat (VMware) 
+Date:   Thu Feb 24 14:24:22 2022 -0800
+
+    MAINTAINERS: Update maintainers for paravirt ops and VMware hypervisor interface
+    
+    Deep has decided to transfer the joint-maintainership of paravirt ops
+    to Srivatsa, and the maintainership of the VMware hypervisor interface
+    to Srivatsa and Alexey. Update the MAINTAINERS file to reflect this
+    change, and also add Alexey as a reviewer for paravirt ops.
+    
+    Signed-off-by: Srivatsa S. Bhat (VMware) 
+    Signed-off-by: Borislav Petkov 
+    Acked-by: Alexey Makhalov 
+    Acked-by: Deep Shah 
+    Acked-by: Juergen Gross 
+    Link: https://lore.kernel.org/r/164574143710.654750.17342470717937593195.stgit@csail.mit.edu
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index ea3e6c914384..4f81c3dd782f 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -14576,7 +14576,8 @@ F:	include/uapi/linux/ppdev.h
+ 
+ PARAVIRT_OPS INTERFACE
+ M:	Juergen Gross 
+-M:	Deep Shah 
++M:	Srivatsa S. Bhat (VMware) 
++R:	Alexey Makhalov 
+ M:	"VMware, Inc." 
+ L:	virtualization@lists.linux-foundation.org
+ L:	x86@kernel.org
+@@ -20585,10 +20586,13 @@ S:	Maintained
+ F:	drivers/misc/vmw_balloon.c
+ 
+ VMWARE HYPERVISOR INTERFACE
+-M:	Deep Shah 
++M:	Srivatsa S. Bhat (VMware) 
++M:	Alexey Makhalov 
+ M:	"VMware, Inc." 
+ L:	virtualization@lists.linux-foundation.org
++L:	x86@kernel.org
+ S:	Supported
++T:	git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/vmware
+ F:	arch/x86/include/asm/vmware.h
+ F:	arch/x86/kernel/cpu/vmware.c
+ 

commit 0c3c86bdc691c794a6154f8515b7fa82c82dfc4d
+Author: Srivatsa S. Bhat (VMware) 
+Date:   Thu Oct 10 11:51:17 2019 -0700
+
+    tracing/hwlat: Fix a few trivial nits
+    
+    Update the source file name in the comments, and fix a grammatical
+    error.
+    
+    Link: http://lkml.kernel.org/r/157073346821.17189.8946944856026592247.stgit@srivatsa-ubuntu
+    
+    Signed-off-by: Srivatsa S. Bhat (VMware) 
+    Signed-off-by: Steven Rostedt (VMware) 
+
+diff --git a/kernel/trace/trace_hwlat.c b/kernel/trace/trace_hwlat.c
+index 63526670605a..6638d63f0921 100644
+--- a/kernel/trace/trace_hwlat.c
++++ b/kernel/trace/trace_hwlat.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0
+ /*
+- * trace_hwlatdetect.c - A simple Hardware Latency detector.
++ * trace_hwlat.c - A simple Hardware Latency detector.
+  *
+  * Use this tracer to detect large system latencies induced by the behavior of
+  * certain underlying system hardware or firmware, independent of Linux itself.
+@@ -279,7 +279,7 @@ static void move_to_next_cpu(void)
+ 		return;
+ 	/*
+ 	 * If for some reason the user modifies the CPU affinity
+-	 * of this thread, than stop migrating for the duration
++	 * of this thread, then stop migrating for the duration
+ 	 * of the current test.
+ 	 */
+ 	if (!cpumask_equal(current_mask, current->cpus_ptr))

commit d61ca3c25e0330c44d9a18b2a767197f10c0cd16
+Author: Srivatsa S. Bhat (VMware) 
+Date:   Fri Oct 25 16:02:07 2019 -0700
+
+    sched/Kconfig: Fix spelling mistake in user-visible help text
+    
+    Fix a spelling mistake in the help text for PREEMPT_RT.
+    
+    Signed-off-by: Srivatsa S. Bhat (VMware) 
+    Signed-off-by: Thomas Gleixner 
+    Link: https://lkml.kernel.org/r/157204450499.10518.4542293884417101528.stgit@srivatsa-ubuntu
+
+diff --git a/kernel/Kconfig.preempt b/kernel/Kconfig.preempt
+index deff97217496..bf82259cff96 100644
+--- a/kernel/Kconfig.preempt
++++ b/kernel/Kconfig.preempt
+@@ -65,7 +65,7 @@ config PREEMPT_RT
+ 	  preemptible priority-inheritance aware variants, enforcing
+ 	  interrupt threading and introducing mechanisms to break up long
+ 	  non-preemptible sections. This makes the kernel, except for very
+-	  low level and critical code pathes (entry code, scheduler, low
++	  low level and critical code paths (entry code, scheduler, low
+ 	  level interrupt handling) fully preemptible and brings most
+ 	  execution contexts under scheduler control.
+ 

commit fc64e4ad80d4b72efce116f87b3174f0b7196f8e
+Author: Srivatsa S. Bhat (VMware) 
+Date:   Thu Oct 10 11:51:01 2019 -0700
+
+    tracing/hwlat: Don't ignore outer-loop duration when calculating max_latency
+    
+    max_latency is intended to record the maximum ever observed hardware
+    latency, which may occur in either part of the loop (inner/outer). So
+    we need to also consider the outer-loop sample when updating
+    max_latency.
+    
+    Link: http://lkml.kernel.org/r/157073345463.17189.18124025522664682811.stgit@srivatsa-ubuntu
+    
+    Fixes: e7c15cd8a113 ("tracing: Added hardware latency tracer")
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Srivatsa S. Bhat (VMware) 
+    Signed-off-by: Steven Rostedt (VMware) 
+
+diff --git a/kernel/trace/trace_hwlat.c b/kernel/trace/trace_hwlat.c
+index a0251a78807d..862f4b0139fc 100644
+--- a/kernel/trace/trace_hwlat.c
++++ b/kernel/trace/trace_hwlat.c
+@@ -256,6 +256,8 @@ static int get_sample(void)
+ 		/* Keep a running maximum ever recorded hardware latency */
+ 		if (sample > tr->max_latency)
+ 			tr->max_latency = sample;
++		if (outer_sample > tr->max_latency)
++			tr->max_latency = outer_sample;
+ 	}
+ 
+ out:

commit 98dc19c11470ee6048aba723d77079ad2cda8a52
+Author: Srivatsa S. Bhat (VMware) 
+Date:   Thu Oct 10 11:50:46 2019 -0700
+
+    tracing/hwlat: Report total time spent in all NMIs during the sample
+    
+    nmi_total_ts is supposed to record the total time spent in *all* NMIs
+    that occur on the given CPU during the (active portion of the)
+    sampling window. However, the code seems to be overwriting this
+    variable for each NMI, thereby only recording the time spent in the
+    most recent NMI. Fix it by accumulating the duration instead.
+    
+    Link: http://lkml.kernel.org/r/157073343544.17189.13911783866738671133.stgit@srivatsa-ubuntu
+    
+    Fixes: 7b2c86250122 ("tracing: Add NMI tracing in hwlat detector")
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Srivatsa S. Bhat (VMware) 
+    Signed-off-by: Steven Rostedt (VMware) 
+
+diff --git a/kernel/trace/trace_hwlat.c b/kernel/trace/trace_hwlat.c
+index fa95139445b2..a0251a78807d 100644
+--- a/kernel/trace/trace_hwlat.c
++++ b/kernel/trace/trace_hwlat.c
+@@ -150,7 +150,7 @@ void trace_hwlat_callback(bool enter)
+ 		if (enter)
+ 			nmi_ts_start = time_get();
+ 		else
+-			nmi_total_ts = time_get() - nmi_ts_start;
++			nmi_total_ts += time_get() - nmi_ts_start;
+ 	}
+ 
+ 	if (enter)

commit b9416997603ef7e17d4de10b6408f19da2feb72c
+Author: Srivatsa S. Bhat (VMware) 
+Date:   Mon Jan 28 17:55:53 2019 -0800
+
+    tracing: Fix documentation about disabling options using trace_options
+    
+    To disable a tracing option using the trace_options file, the option
+    name needs to be prefixed with 'no', and not suffixed, as the README
+    states. Fix it.
+    
+    Link: http://lkml.kernel.org/r/154872690031.47356.5739053380942044586.stgit@srivatsa-ubuntu
+    
+    Signed-off-by: Srivatsa S. Bhat (VMware) 
+    Signed-off-by: Steven Rostedt (VMware) 
+
+diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
+index 4269af5905e4..a3a6945a7732 100644
+--- a/kernel/trace/trace.c
++++ b/kernel/trace/trace.c
+@@ -4755,7 +4755,7 @@ static const char readme_msg[] =
+ 	"  instances\t\t- Make sub-buffers with: mkdir instances/foo\n"
+ 	"\t\t\t  Remove sub-buffer with rmdir\n"
+ 	"  trace_options\t\t- Set format or modify how tracing happens\n"
+-	"\t\t\t  Disable an option by adding a suffix 'no' to the\n"
++	"\t\t\t  Disable an option by prefixing 'no' to the\n"
+ 	"\t\t\t  option name\n"
+ 	"  saved_cmdlines_size\t- echo command number in here to store comm-pid list\n"
+ #ifdef CONFIG_DYNAMIC_FTRACE

commit f33ff110ef31bd250bb8a16cfc4e883aa2b36767
+Author: Srivatsa S. Bhat 
+Date:   Mon Feb 5 18:25:27 2018 -0800
+
+    block, char_dev: Use correct format specifier for unsigned ints
+    
+    register_blkdev() and __register_chrdev_region() treat the major
+    number as an unsigned int. So print it the same way to avoid
+    absurd error statements such as:
+    "... major requested (-1) is greater than the maximum (511) ..."
+    (and also fix off-by-one bugs in the error prints).
+    
+    While at it, also update the comment describing register_blkdev().
+    
+    Signed-off-by: Srivatsa S. Bhat 
+    Reviewed-by: Logan Gunthorpe 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/block/genhd.c b/block/genhd.c
+index 9656f9e9f99e..dc7e089373b9 100644
+--- a/block/genhd.c
++++ b/block/genhd.c
+@@ -308,19 +308,22 @@ void blkdev_show(struct seq_file *seqf, off_t offset)
+ /**
+  * register_blkdev - register a new block device
+  *
+- * @major: the requested major device number [1..255]. If @major = 0, try to
+- *         allocate any unused major number.
++ * @major: the requested major device number [1..BLKDEV_MAJOR_MAX-1]. If
++ *         @major = 0, try to allocate any unused major number.
+  * @name: the name of the new block device as a zero terminated string
+  *
+  * The @name must be unique within the system.
+  *
+  * The return value depends on the @major input parameter:
+  *
+- *  - if a major device number was requested in range [1..255] then the
+- *    function returns zero on success, or a negative error code
++ *  - if a major device number was requested in range [1..BLKDEV_MAJOR_MAX-1]
++ *    then the function returns zero on success, or a negative error code
+  *  - if any unused major number was requested with @major = 0 parameter
+  *    then the return value is the allocated major number in range
+- *    [1..255] or a negative error code otherwise
++ *    [1..BLKDEV_MAJOR_MAX-1] or a negative error code otherwise
++ *
++ * See Documentation/admin-guide/devices.txt for the list of allocated
++ * major numbers.
+  */
+ int register_blkdev(unsigned int major, const char *name)
+ {
+@@ -347,8 +350,8 @@ int register_blkdev(unsigned int major, const char *name)
+ 	}
+ 
+ 	if (major >= BLKDEV_MAJOR_MAX) {
+-		pr_err("register_blkdev: major requested (%d) is greater than the maximum (%d) for %s\n",
+-		       major, BLKDEV_MAJOR_MAX, name);
++		pr_err("register_blkdev: major requested (%u) is greater than the maximum (%u) for %s\n",
++		       major, BLKDEV_MAJOR_MAX-1, name);
+ 
+ 		ret = -EINVAL;
+ 		goto out;
+@@ -375,7 +378,7 @@ int register_blkdev(unsigned int major, const char *name)
+ 		ret = -EBUSY;
+ 
+ 	if (ret < 0) {
+-		printk("register_blkdev: cannot get major %d for %s\n",
++		printk("register_blkdev: cannot get major %u for %s\n",
+ 		       major, name);
+ 		kfree(p);
+ 	}
+diff --git a/fs/char_dev.c b/fs/char_dev.c
+index 33c938542160..a279c58fe360 100644
+--- a/fs/char_dev.c
++++ b/fs/char_dev.c
+@@ -121,8 +121,8 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor,
+ 	}
+ 
+ 	if (major >= CHRDEV_MAJOR_MAX) {
+-		pr_err("CHRDEV \"%s\" major requested (%d) is greater than the maximum (%d)\n",
+-		       name, major, CHRDEV_MAJOR_MAX);
++		pr_err("CHRDEV \"%s\" major requested (%u) is greater than the maximum (%u)\n",
++		       name, major, CHRDEV_MAJOR_MAX-1);
+ 		ret = -EINVAL;
+ 		goto out;
+ 	}

commit 652d703b21eb1caf2673c10bd58e4b0121dc7c50
+Author: Srivatsa S. Bhat 
+Date:   Mon Feb 5 18:25:09 2018 -0800
+
+    char_dev: Fix off-by-one bugs in find_dynamic_major()
+    
+    CHRDEV_MAJOR_DYN_END and CHRDEV_MAJOR_DYN_EXT_END are valid major
+    numbers. So fix the loop iteration to include them in the search for
+    free major numbers.
+    
+    While at it, also remove a redundant if condition ("cd->major != i"),
+    as it will never be true.
+    
+    Signed-off-by: Srivatsa S. Bhat 
+    Reviewed-by: Logan Gunthorpe 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/fs/char_dev.c b/fs/char_dev.c
+index a65e4a56318c..33c938542160 100644
+--- a/fs/char_dev.c
++++ b/fs/char_dev.c
+@@ -67,18 +67,18 @@ static int find_dynamic_major(void)
+ 	int i;
+ 	struct char_device_struct *cd;
+ 
+-	for (i = ARRAY_SIZE(chrdevs)-1; i > CHRDEV_MAJOR_DYN_END; i--) {
++	for (i = ARRAY_SIZE(chrdevs)-1; i >= CHRDEV_MAJOR_DYN_END; i--) {
+ 		if (chrdevs[i] == NULL)
+ 			return i;
+ 	}
+ 
+ 	for (i = CHRDEV_MAJOR_DYN_EXT_START;
+-	     i > CHRDEV_MAJOR_DYN_EXT_END; i--) {
++	     i >= CHRDEV_MAJOR_DYN_EXT_END; i--) {
+ 		for (cd = chrdevs[major_to_index(i)]; cd; cd = cd->next)
+ 			if (cd->major == i)
+ 				break;
+ 
+-		if (cd == NULL || cd->major != i)
++		if (cd == NULL)
+ 			return i;
+ 	}
+ 

commit bb71b14d80bde8484ae63ee09d969c72d8615e0c
+Author: Nickolai Zeldovich 
+Date:   Mon Jan 7 22:28:05 2013 -0300
+
+    [media] drivers/media/pci: use memmove for overlapping regions
+    
+    Change several memcpy() to memmove() in cases when the regions are
+    definitely overlapping; memcpy() of overlapping regions is undefined
+    behavior in C and can produce different results depending on the compiler,
+    the memcpy implementation, etc.
+    
+    Cc: Andy Walls 
+    Signed-off-by: Nickolai Zeldovich 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/pci/bt8xx/dst_ca.c b/drivers/media/pci/bt8xx/dst_ca.c
+index 7d96fab7d246..0e788fca992c 100644
+--- a/drivers/media/pci/bt8xx/dst_ca.c
++++ b/drivers/media/pci/bt8xx/dst_ca.c
+@@ -180,11 +180,11 @@ static int ca_get_app_info(struct dst_state *state)
+ 	put_command_and_length(&state->messages[0], CA_APP_INFO, length);
+ 
+ 	// Copy application_type, application_manufacturer and manufacturer_code
+-	memcpy(&state->messages[4], &state->messages[7], 5);
++	memmove(&state->messages[4], &state->messages[7], 5);
+ 
+ 	// Set string length and copy string
+ 	state->messages[9] = str_length;
+-	memcpy(&state->messages[10], &state->messages[12], str_length);
++	memmove(&state->messages[10], &state->messages[12], str_length);
+ 
+ 	return 0;
+ }
+diff --git a/drivers/media/pci/cx18/cx18-vbi.c b/drivers/media/pci/cx18/cx18-vbi.c
+index 6d3121ff45a2..add99642f1e2 100644
+--- a/drivers/media/pci/cx18/cx18-vbi.c
++++ b/drivers/media/pci/cx18/cx18-vbi.c
+@@ -84,7 +84,7 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp)
+ 		   (the max size of the VBI data is 36 * 43 + 4 bytes).
+ 		   So in this case we use the magic number 'ITV0'. */
+ 		memcpy(dst + sd, "ITV0", 4);
+-		memcpy(dst + sd + 4, dst + sd + 12, line * 43);
++		memmove(dst + sd + 4, dst + sd + 12, line * 43);
+ 		size = 4 + ((43 * line + 3) & ~3);
+ 	} else {
+ 		memcpy(dst + sd, "itv0", 4);
+diff --git a/drivers/media/pci/ivtv/ivtv-vbi.c b/drivers/media/pci/ivtv/ivtv-vbi.c
+index 293db806d936..3c156bc70fb4 100644
+--- a/drivers/media/pci/ivtv/ivtv-vbi.c
++++ b/drivers/media/pci/ivtv/ivtv-vbi.c
+@@ -224,7 +224,7 @@ static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp)
+ 		   (the max size of the VBI data is 36 * 43 + 4 bytes).
+ 		   So in this case we use the magic number 'ITV0'. */
+ 		memcpy(dst + sd, "ITV0", 4);
+-		memcpy(dst + sd + 4, dst + sd + 12, line * 43);
++		memmove(dst + sd + 4, dst + sd + 12, line * 43);
+ 		size = 4 + ((43 * line + 3) & ~3);
+ 	} else {
+ 		memcpy(dst + sd, "itv0", 4);
+@@ -532,7 +532,7 @@ void ivtv_vbi_work_handler(struct ivtv *itv)
+ 		while (vi->cc_payload_idx) {
+ 			cc = vi->cc_payload[0];
+ 
+-			memcpy(vi->cc_payload, vi->cc_payload + 1,
++			memmove(vi->cc_payload, vi->cc_payload + 1,
+ 					sizeof(vi->cc_payload) - sizeof(vi->cc_payload[0]));
+ 			vi->cc_payload_idx--;
+ 			if (vi->cc_payload_idx && cc.odd[0] == 0x80 && cc.odd[1] == 0x80)

commit a46edeb0f6098088f316c3543474784f8108508e
+Author: Nickolai Zeldovich 
+Date:   Sun Jan 6 21:52:03 2013 -0300
+
+    [media] media: cx18, ivtv: eliminate unnecessary array index checks
+    
+    The idx values passed to cx18_i2c_register() and ivtv_i2c_register()
+    by cx18_init_subdevs() and ivtv_load_and_init_modules() respectively
+    are always in-range, based on how the hw_all bitmask is populated.
+    Previously, the checks were already ineffective because arrays were
+    being dereferenced using the index before the check.
+    
+    Acked-by: Andy Walls 
+    Signed-off-by: Nickolai Zeldovich 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/pci/cx18/cx18-i2c.c b/drivers/media/pci/cx18/cx18-i2c.c
+index d61ac6393e7e..4af8cd6df95d 100644
+--- a/drivers/media/pci/cx18/cx18-i2c.c
++++ b/drivers/media/pci/cx18/cx18-i2c.c
+@@ -116,9 +116,6 @@ int cx18_i2c_register(struct cx18 *cx, unsigned idx)
+ 	const char *type = hw_devicenames[idx];
+ 	u32 hw = 1 << idx;
+ 
+-	if (idx >= ARRAY_SIZE(hw_addrs))
+-		return -1;
+-
+ 	if (hw == CX18_HW_TUNER) {
+ 		/* special tuner group handling */
+ 		sd = v4l2_i2c_new_subdev(&cx->v4l2_dev,
+diff --git a/drivers/media/pci/ivtv/ivtv-i2c.c b/drivers/media/pci/ivtv/ivtv-i2c.c
+index a1811054fde4..ceed2d87abfd 100644
+--- a/drivers/media/pci/ivtv/ivtv-i2c.c
++++ b/drivers/media/pci/ivtv/ivtv-i2c.c
+@@ -267,8 +267,6 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx)
+ 	const char *type = hw_devicenames[idx];
+ 	u32 hw = 1 << idx;
+ 
+-	if (idx >= ARRAY_SIZE(hw_addrs))
+-		return -1;
+ 	if (hw == IVTV_HW_TUNER) {
+ 		/* special tuner handling */
+ 		sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, type, 0,

commit 7e20f6bfc47992d93b36f4ed068782f8726b75a3
+Author: Nickolai Zeldovich 
+Date:   Sat Jan 5 15:13:05 2013 -0300
+
+    [media] drivers/media/usb/dvb-usb/dib0700_core.c: fix left shift
+    
+    Fix bug introduced in 7757ddda6f4febbc52342d82440dd4f7a7d4f14f, where
+    instead of bit-negating the bitmask, the bit position was bit-negated
+    instead.
+    
+    Signed-off-by: Nickolai Zeldovich 
+    Cc: Olivier Grenie 
+    Cc: Patrick Boettcher 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c
+index bf2a908d74cf..bd6a43785d5e 100644
+--- a/drivers/media/usb/dvb-usb/dib0700_core.c
++++ b/drivers/media/usb/dvb-usb/dib0700_core.c
+@@ -584,7 +584,7 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+ 		if (onoff)
+ 			st->channel_state |=	1 << (adap->id);
+ 		else
+-			st->channel_state |=	1 << ~(adap->id);
++			st->channel_state &=  ~(1 << (adap->id));
+ 	} else {
+ 		if (onoff)
+ 			st->channel_state |=	1 << (adap->fe_adap[0].stream.props.endpoint-2);

commit ba7b5c22d33136a5612ca5ef8d31564dcc501126
+Author: Nickolai Zeldovich 
+Date:   Mon Jan 7 22:39:31 2013 -0500
+
+    drivers: xhci: fix incorrect bit test
+    
+    Fix incorrect bit test that originally showed up in
+    4ee823b83bc9851743fab756c76b27d6a1e2472b "USB/xHCI: Support
+    device-initiated USB 3.0 resume."
+    
+    Use '&' instead of '&&'.
+    
+    This should be backported to kernels as old as 3.4.
+    
+    Signed-off-by: Nickolai Zeldovich 
+    Signed-off-by: Sarah Sharp 
+    Cc: stable@vger.kernel.org
+
+diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
+index 80ef717ec5b8..151204642a6e 100644
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1698,7 +1698,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
+ 				faked_port_index + 1);
+ 		if (slot_id && xhci->devs[slot_id])
+ 			xhci_ring_device(xhci, slot_id);
+-		if (bus_state->port_remote_wakeup && (1 << faked_port_index)) {
++		if (bus_state->port_remote_wakeup & (1 << faked_port_index)) {
+ 			bus_state->port_remote_wakeup &=
+ 				~(1 << faked_port_index);
+ 			xhci_test_and_clear_bit(xhci, port_array,

commit e3e2775cedc9d6294b7bc7cbe9f59c62f9472871
+Author: Nickolai Zeldovich 
+Date:   Wed Jan 16 21:36:17 2013 -0500
+
+    cifs: fix srcip_matches() for ipv6
+    
+    srcip_matches() previously had code like this:
+    
+      srcip_matches(..., struct sockaddr *rhs) {
+        /* ... */
+        struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *) &rhs;
+        return ipv6_addr_equal(..., &vaddr6->sin6_addr);
+      }
+    
+    which interpreted the values on the stack after the 'rhs' pointer as an
+    ipv6 address.  The correct thing to do is to use 'rhs', not '&rhs'.
+    
+    Signed-off-by: Nickolai Zeldovich 
+    Reviewed-by: Jeff Layton 
+    Signed-off-by: Steve French 
+
+diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
+index 17c3643e5950..12b3da39733b 100644
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -1917,7 +1917,7 @@ srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
+ 	}
+ 	case AF_INET6: {
+ 		struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
+-		struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)&rhs;
++		struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
+ 		return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
+ 	}
+ 	default:

commit e2f6725917ed525f4111c33c31ab53397b70f9d2
+Author: Nickolai Zeldovich 
+Date:   Thu Jan 17 13:58:28 2013 -0500
+
+    net/xfrm/xfrm_replay: avoid division by zero
+    
+    All of the xfrm_replay->advance functions in xfrm_replay.c check if
+    x->replay_esn->replay_window is zero (and return if so).  However,
+    one of them, xfrm_replay_advance_bmp(), divides by that value (in the
+    '%' operator) before doing the check, which can potentially trigger
+    a divide-by-zero exception.  Some compilers will also assume that the
+    earlier division means the value cannot be zero later, and thus will
+    eliminate the subsequent zero check as dead code.
+    
+    This patch moves the division to after the check.
+    
+    Signed-off-by: Nickolai Zeldovich 
+    Signed-off-by: Steffen Klassert 
+
+diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c
+index 765f6fe951eb..35754cc8a9e5 100644
+--- a/net/xfrm/xfrm_replay.c
++++ b/net/xfrm/xfrm_replay.c
+@@ -242,11 +242,13 @@ static void xfrm_replay_advance_bmp(struct xfrm_state *x, __be32 net_seq)
+ 	u32 diff;
+ 	struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
+ 	u32 seq = ntohl(net_seq);
+-	u32 pos = (replay_esn->seq - 1) % replay_esn->replay_window;
++	u32 pos;
+ 
+ 	if (!replay_esn->replay_window)
+ 		return;
+ 
++	pos = (replay_esn->seq - 1) % replay_esn->replay_window;
++
+ 	if (seq > replay_esn->seq) {
+ 		diff = seq - replay_esn->seq;
+ 

commit 13b6d2e6c25dd33f94873b771ad7de3550da5125
+Author: Nickolai Zeldovich 
+Date:   Thu Jan 17 07:18:29 2013 +0000
+
+    3c574_cs: fix operator precedence between << and &
+    
+    The code to print the FIFO size in tc574_config computes it as:
+    
+      8 << config & Ram_size
+    
+    which evaluates the '<<' first, but the actual intent is to evaluate the
+    '&' first.  Add parentheses to enforce desired evaluation order.
+    
+    Signed-off-by: Nickolai Zeldovich 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/3com/3c574_cs.c b/drivers/net/ethernet/3com/3c574_cs.c
+index 66df93638085..ffd8de28a76a 100644
+--- a/drivers/net/ethernet/3com/3c574_cs.c
++++ b/drivers/net/ethernet/3com/3c574_cs.c
+@@ -432,7 +432,7 @@ static int tc574_config(struct pcmcia_device *link)
+ 	netdev_info(dev, "%s at io %#3lx, irq %d, hw_addr %pM\n",
+ 		    cardname, dev->base_addr, dev->irq, dev->dev_addr);
+ 	netdev_info(dev, " %dK FIFO split %s Rx:Tx, %sMII interface.\n",
+-		    8 << config & Ram_size,
++		    8 << (config & Ram_size),
+ 		    ram_split[(config & Ram_split) >> Ram_split_shift],
+ 		    config & Autoselect ? "autoselect " : "");
+ 

commit ae428655b826f2755a8101b27beda42a275ef8ad
+Author: Nickolai Zeldovich 
+Date:   Sat Jan 5 14:17:45 2013 -0500
+
+    staging: speakup: avoid out-of-range access in synth_init()
+    
+    Check that array index is in-bounds before accessing the synths[] array.
+    
+    Signed-off-by: Nickolai Zeldovich 
+    Cc: stable 
+    Cc: Samuel Thibault 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/speakup/synth.c b/drivers/staging/speakup/synth.c
+index df9533798095..b91d22b6330f 100644
+--- a/drivers/staging/speakup/synth.c
++++ b/drivers/staging/speakup/synth.c
+@@ -342,7 +342,7 @@ int synth_init(char *synth_name)
+ 
+ 	mutex_lock(&spk_mutex);
+ 	/* First, check if we already have it loaded. */
+-	for (i = 0; synths[i] != NULL && i < MAXSYNTHS; i++)
++	for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++)
+ 		if (strcmp(synths[i]->name, synth_name) == 0)
+ 			synth = synths[i];
+ 

commit c4f74d35cac7cbc44877313b69550e2f5aeae77d
+Author: Nickolai Zeldovich 
+Date:   Sun Jan 6 20:27:22 2013 -0500
+
+    drivers/net/wireless/mwl8k.c: avoid use-after-free
+    
+    Do not dereference p->station_id after kfree(cmd) because p
+    points into the cmd data structure.
+    
+    Signed-off-by: Nickolai Zeldovich 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
+index f221b95b90b3..83564d36e801 100644
+--- a/drivers/net/wireless/mwl8k.c
++++ b/drivers/net/wireless/mwl8k.c
+@@ -4250,9 +4250,11 @@ static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw,
+ 	p->amsdu_enabled = 0;
+ 
+ 	rc = mwl8k_post_cmd(hw, &cmd->header);
++	if (!rc)
++		rc = p->station_id;
+ 	kfree(cmd);
+ 
+-	return rc ? rc : p->station_id;
++	return rc;
+ }
+ 
+ static int mwl8k_cmd_update_stadb_del(struct ieee80211_hw *hw,

commit 9d48017bce890b19e3bba649850bdbc8a6f95903
+Author: Nickolai Zeldovich 
+Date:   Sat Jan 5 14:19:21 2013 -0500
+
+    jfs: avoid undefined behavior from left-shifting by 32 bits
+    
+    Shifting a 32-bit int by 32 bits is undefined behavior in C, and
+    results in different behavior on different architectures (e.g., x86
+    and PowerPC).  diAlloc() in fs/jfs/jfs_imap.c computes a mask using
+    0xffffffffu<<(32-bitno), which can left-shift by 32 bits.  To avoid
+    unexpected behavior, explicitly check for bitno==0 and use a 0 mask.
+    
+    Signed-off-by: Nickolai Zeldovich 
+    Signed-off-by: Dave Kleikamp 
+
+diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
+index 6ba4006e011b..f7e042b63ddb 100644
+--- a/fs/jfs/jfs_imap.c
++++ b/fs/jfs/jfs_imap.c
+@@ -1493,7 +1493,7 @@ int diAlloc(struct inode *pip, bool dir, struct inode *ip)
+ 		/* mask any prior bits for the starting words of the
+ 		 * summary map.
+ 		 */
+-		mask = ONES << (EXTSPERSUM - bitno);
++		mask = (bitno == 0) ? 0 : (ONES << (EXTSPERSUM - bitno));
+ 		inosmap = le32_to_cpu(iagp->inosmap[sword]) | mask;
+ 		extsmap = le32_to_cpu(iagp->extsmap[sword]) | mask;
+ 

commit 61ed1dca1645d2dd64c83a01f728dfd59fa789b6
+Author: Nickolai Zeldovich 
+Date:   Sat Jan 5 14:14:08 2013 -0500
+
+    ALSA: au88x0: fix incorrect left shift
+    
+    vortex_wt_setdsout performs bit-negation on the bit position (wt&0x1f)
+    rather than on the resulting bitmask.  This code is never actually
+    invoked (vortex_wt_setdsout is always called with en=1), so this does
+    not currently cause any problem, and this patch is simply cleanup.
+    
+    Signed-off-by: Nickolai Zeldovich 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/au88x0/au88x0_synth.c b/sound/pci/au88x0/au88x0_synth.c
+index 2805e34bd41d..8bef47311e45 100644
+--- a/sound/pci/au88x0/au88x0_synth.c
++++ b/sound/pci/au88x0/au88x0_synth.c
+@@ -58,7 +58,7 @@ static void vortex_wt_setdsout(vortex_t * vortex, u32 wt, int en)
+ 	if (en)
+ 		temp |= (1 << (wt & 0x1f));
+ 	else
+-		temp &= (1 << ~(wt & 0x1f));
++		temp &= ~(1 << (wt & 0x1f));
+ 	hwwrite(vortex->mmio, WT_DSREG((wt >= 0x20) ? 1 : 0), temp);
+ }
+ 

commit c4f3422630464d231c14c8b9e585c23fcfe3436c
+Author: Nickolai Zeldovich 
+Date:   Sat Jan 5 14:14:51 2013 -0500
+
+    da9052-battery: Avoid out-of-range array access
+    
+    Avoid accessing vc_tbl_ref[3], which is one past the end of that array, in
+    da9052_determine_vc_tbl_index(), by adjusting the loop bound.
+    
+    (Hint: there is 'i + 1' inside the loop.)
+    
+    Signed-off-by: Nickolai Zeldovich 
+    Signed-off-by: Anton Vorontsov 
+
+diff --git a/drivers/power/da9052-battery.c b/drivers/power/da9052-battery.c
+index 3c5c2e459d73..08193feb3b08 100644
+--- a/drivers/power/da9052-battery.c
++++ b/drivers/power/da9052-battery.c
+@@ -337,7 +337,7 @@ static unsigned char da9052_determine_vc_tbl_index(unsigned char adc_temp)
+ 	if (adc_temp > vc_tbl_ref[DA9052_VC_TBL_REF_SZ - 1])
+ 		return DA9052_VC_TBL_REF_SZ - 1;
+ 
+-	for (i = 0; i < DA9052_VC_TBL_REF_SZ; i++) {
++	for (i = 0; i < DA9052_VC_TBL_REF_SZ - 1; i++) {
+ 		if ((adc_temp > vc_tbl_ref[i]) &&
+ 		    (adc_temp <= DA9052_MEAN(vc_tbl_ref[i], vc_tbl_ref[i + 1])))
+ 				return i;

commit bec7a4bbecf7da86b6e64bb78d22c92ea1ba4afe
+Author: Nickolai Zeldovich 
+Date:   Sat Jan 5 14:38:17 2013 -0800
+
+    Input: lm8323 - fix checking PWM interrupt status
+    
+    INT_PWM1 is already a bitmask, not the bit number, so shifting by INT_PWM1 is
+    incorrect.
+    
+    Signed-off-by: Nickolai Zeldovich 
+    Signed-off-by: Dmitry Torokhov 
+
+diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c
+index 93c812662134..0de23f41b2d3 100644
+--- a/drivers/input/keyboard/lm8323.c
++++ b/drivers/input/keyboard/lm8323.c
+@@ -398,7 +398,7 @@ static irqreturn_t lm8323_irq(int irq, void *_lm)
+ 			lm8323_configure(lm);
+ 		}
+ 		for (i = 0; i < LM8323_NUM_PWMS; i++) {
+-			if (ints & (1 << (INT_PWM1 + i))) {
++			if (ints & (INT_PWM1 << i)) {
+ 				dev_vdbg(&lm->client->dev,
+ 					 "pwm%d engine completed\n", i);
+ 				pwm_done(&lm->pwm[i]);

commit ecf0eb9edbb607d74f74b73c14af8b43f3729528
+Author: Nickolai Zeldovich 
+Date:   Sat Jan 5 14:19:51 2013 -0500
+
+    nfs: avoid dereferencing null pointer in initiate_bulk_draining
+    
+    Fix an inverted null pointer check in initiate_bulk_draining().
+    
+    Signed-off-by: Nickolai Zeldovich 
+    Signed-off-by: Trond Myklebust 
+    Cc: stable@vger.kernel.org [>= 3.7]
+
+diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
+index c89b26bc9759..264d1aa935f2 100644
+--- a/fs/nfs/callback_proc.c
++++ b/fs/nfs/callback_proc.c
+@@ -206,7 +206,7 @@ static u32 initiate_bulk_draining(struct nfs_client *clp,
+ 
+ 		list_for_each_entry(lo, &server->layouts, plh_layouts) {
+ 			ino = igrab(lo->plh_inode);
+-			if (ino)
++			if (!ino)
+ 				continue;
+ 			spin_lock(&ino->i_lock);
+ 			/* Is this layout in the process of being freed? */

commit d4b06c2d4cce466e2d62163c0a954e1b2ce96f8b
+Author: Nickolai Zeldovich 
+Date:   Sat Dec 15 06:34:37 2012 -0500
+
+    kvm: fix i8254 counter 0 wraparound
+    
+    The kvm i8254 emulation for counter 0 (but not for counters 1 and 2)
+    has at least two bugs in mode 0:
+    
+    1. The OUT bit, computed by pit_get_out(), is never set high.
+    
+    2. The counter value, computed by pit_get_count(), wraps back around to
+       the initial counter value, rather than wrapping back to 0xFFFF
+       (which is the behavior described in the comment in __kpit_elapsed,
+       the behavior implemented by qemu, and the behavior observed on AMD
+       hardware).
+    
+    The bug stems from __kpit_elapsed computing the elapsed time mod the
+    initial counter value (stored as nanoseconds in ps->period).  This is both
+    unnecessary (none of the callers of kpit_elapsed expect the value to be
+    at most the initial counter value) and incorrect (it causes pit_get_count
+    to appear to wrap around to the initial counter value rather than 0xFFFF).
+    Removing this mod from __kpit_elapsed fixes both of the above bugs.
+    
+    Signed-off-by: Nickolai Zeldovich 
+    Reviewed-by: Marcelo Tosatti 
+    Signed-off-by: Gleb Natapov 
+
+diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
+index 11300d2fa714..c1d30b2fc9bb 100644
+--- a/arch/x86/kvm/i8254.c
++++ b/arch/x86/kvm/i8254.c
+@@ -122,7 +122,6 @@ static s64 __kpit_elapsed(struct kvm *kvm)
+ 	 */
+ 	remaining = hrtimer_get_remaining(&ps->timer);
+ 	elapsed = ps->period - ktime_to_ns(remaining);
+-	elapsed = mod_64(elapsed, ps->period);
+ 
+ 	return elapsed;
+ }

commit bd6e07e72f37f34535bec7eebc807e5fcfe37b43
+Author: Ilia Mirkin 
+Date:   Sun Mar 7 12:48:53 2021 -0500
+
+    drm/nouveau/kms/nv04: use vzalloc for nv04_display
+    
+    The struct is giant, and triggers an order-7 allocation (512K). There is
+    no reason for this to be kmalloc-type memory, so switch to vmalloc. This
+    should help loading nouveau on low-memory and/or long-running systems.
+    
+    Reported-by: Nathan E. Egge 
+    Signed-off-by: Ilia Mirkin 
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Ben Skeggs 
+    Reviewed-by: Karol Herbst 
+    Signed-off-by: Karol Herbst 
+    Link: https://gitlab.freedesktop.org/drm/nouveau/-/merge_requests/10
+
+diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c
+index 7739f46470d3..99fee4d8cd31 100644
+--- a/drivers/gpu/drm/nouveau/dispnv04/disp.c
++++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c
+@@ -205,7 +205,7 @@ nv04_display_destroy(struct drm_device *dev)
+ 	nvif_notify_dtor(&disp->flip);
+ 
+ 	nouveau_display(dev)->priv = NULL;
+-	kfree(disp);
++	vfree(disp);
+ 
+ 	nvif_object_unmap(&drm->client.device.object);
+ }
+@@ -223,7 +223,7 @@ nv04_display_create(struct drm_device *dev)
+ 	struct nv04_display *disp;
+ 	int i, ret;
+ 
+-	disp = kzalloc(sizeof(*disp), GFP_KERNEL);
++	disp = vzalloc(sizeof(*disp));
+ 	if (!disp)
+ 		return -ENOMEM;
+ 

commit 4af0e6e39b7ed77796a41537db91d717fedd0ac3
+Author: Arvind Sankar 
+Date:   Wed Nov 11 11:09:46 2020 -0500
+
+    x86/mm: Remove duplicate definition of _PAGE_PAT_LARGE
+    
+    _PAGE_PAT_LARGE is already defined next to _PAGE_PAT. Remove the
+    duplicate.
+    
+    Fixes: 4efb56649132 ("x86/mm: Tabulate the page table encoding definitions")
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Borislav Petkov 
+    Acked-by: Dave Hansen 
+    Link: https://lkml.kernel.org/r/20201111160946.147341-2-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
+index 394757ee030a..f24d7ef8fffa 100644
+--- a/arch/x86/include/asm/pgtable_types.h
++++ b/arch/x86/include/asm/pgtable_types.h
+@@ -177,8 +177,6 @@ enum page_cache_mode {
+ #define __pgprot(x)		((pgprot_t) { (x) } )
+ #define __pg(x)			__pgprot(x)
+ 
+-#define _PAGE_PAT_LARGE		(_AT(pteval_t, 1) << _PAGE_BIT_PAT_LARGE)
+-
+ #define PAGE_NONE	     __pg(   0|   0|   0|___A|   0|   0|   0|___G)
+ #define PAGE_SHARED	     __pg(__PP|__RW|_USR|___A|__NX|   0|   0|   0)
+ #define PAGE_SHARED_EXEC     __pg(__PP|__RW|_USR|___A|   0|   0|   0|   0)

commit 29ac40cbed2bc06fa218ca25d7f5e280d3d08a25
+Author: Arvind Sankar 
+Date:   Wed Nov 11 11:09:45 2020 -0500
+
+    x86/mm/mem_encrypt: Fix definition of PMD_FLAGS_DEC_WP
+    
+    The PAT bit is in different locations for 4k and 2M/1G page table
+    entries.
+    
+    Add a definition for _PAGE_LARGE_CACHE_MASK to represent the three
+    caching bits (PWT, PCD, PAT), similar to _PAGE_CACHE_MASK for 4k pages,
+    and use it in the definition of PMD_FLAGS_DEC_WP to get the correct PAT
+    index for write-protected pages.
+    
+    Fixes: 6ebcb060713f ("x86/mm: Add support to encrypt the kernel in-place")
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Borislav Petkov 
+    Tested-by: Tom Lendacky 
+    Cc: stable@vger.kernel.org
+    Link: https://lkml.kernel.org/r/20201111160946.147341-1-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
+index 816b31c68550..394757ee030a 100644
+--- a/arch/x86/include/asm/pgtable_types.h
++++ b/arch/x86/include/asm/pgtable_types.h
+@@ -155,6 +155,7 @@ enum page_cache_mode {
+ #define _PAGE_ENC		(_AT(pteval_t, sme_me_mask))
+ 
+ #define _PAGE_CACHE_MASK	(_PAGE_PWT | _PAGE_PCD | _PAGE_PAT)
++#define _PAGE_LARGE_CACHE_MASK	(_PAGE_PWT | _PAGE_PCD | _PAGE_PAT_LARGE)
+ 
+ #define _PAGE_NOCACHE		(cachemode2protval(_PAGE_CACHE_MODE_UC))
+ #define _PAGE_CACHE_WP		(cachemode2protval(_PAGE_CACHE_MODE_WP))
+diff --git a/arch/x86/mm/mem_encrypt_identity.c b/arch/x86/mm/mem_encrypt_identity.c
+index 733b983f3a89..6c5eb6f3f14f 100644
+--- a/arch/x86/mm/mem_encrypt_identity.c
++++ b/arch/x86/mm/mem_encrypt_identity.c
+@@ -45,8 +45,8 @@
+ #define PMD_FLAGS_LARGE		(__PAGE_KERNEL_LARGE_EXEC & ~_PAGE_GLOBAL)
+ 
+ #define PMD_FLAGS_DEC		PMD_FLAGS_LARGE
+-#define PMD_FLAGS_DEC_WP	((PMD_FLAGS_DEC & ~_PAGE_CACHE_MASK) | \
+-				 (_PAGE_PAT | _PAGE_PWT))
++#define PMD_FLAGS_DEC_WP	((PMD_FLAGS_DEC & ~_PAGE_LARGE_CACHE_MASK) | \
++				 (_PAGE_PAT_LARGE | _PAGE_PWT))
+ 
+ #define PMD_FLAGS_ENC		(PMD_FLAGS_LARGE | _PAGE_ENC)
+ 

commit 262bd5724afdefd4c48a260d6100e78cc43ee06b
+Author: Arvind Sankar 
+Date:   Fri Nov 27 12:13:24 2020 -0500
+
+    x86/cpu/amd: Remove dead code for TSEG region remapping
+    
+    Commit
+    
+      26bfa5f89486 ("x86, amd: Cleanup init_amd")
+    
+    moved the code that remaps the TSEG region using 4k pages from
+    init_amd() to bsp_init_amd().
+    
+    However, bsp_init_amd() is executed well before the direct mapping is
+    actually created:
+    
+      setup_arch()
+        -> early_cpu_init()
+          -> early_identify_cpu()
+            -> this_cpu->c_bsp_init()
+              -> bsp_init_amd()
+        ...
+        -> init_mem_mapping()
+    
+    So the change effectively disabled the 4k remapping, because
+    pfn_range_is_mapped() is always false at this point.
+    
+    It has been over six years since the commit, and no-one seems to have
+    noticed this, so just remove the code. The original code was also
+    incomplete, since it doesn't check how large the TSEG address range
+    actually is, so it might remap only part of it in any case.
+    
+    Hygon has copied the incorrect version, so the code has never run on it
+    since the cpu support was added two years ago. Remove it from there as
+    well.
+    
+    Committer notes:
+    
+    This workaround is incomplete anyway:
+    
+    1. The code must check MSRC001_0113.TValid (SMM TSeg Mask MSR) first, to
+    check whether the TSeg address range is enabled.
+    
+    2. The code must check whether the range is not 2M aligned - if it is,
+    there's nothing to work around.
+    
+    3. In all the BIOSes tested, the TSeg range is in a e820 reserved area
+    and those are not mapped anymore, after
+    
+      66520ebc2df3 ("x86, mm: Only direct map addresses that are marked as E820_RAM")
+    
+    which means, there's nothing to be worked around either.
+    
+    So let's rip it out.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Borislav Petkov 
+    Link: https://lkml.kernel.org/r/20201127171324.1846019-1-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
+index 1f71c7616917..f8ca66f3d861 100644
+--- a/arch/x86/kernel/cpu/amd.c
++++ b/arch/x86/kernel/cpu/amd.c
+@@ -23,7 +23,6 @@
+ 
+ #ifdef CONFIG_X86_64
+ # include 
+-# include 
+ #endif
+ 
+ #include "cpu.h"
+@@ -509,26 +508,6 @@ static void early_init_amd_mc(struct cpuinfo_x86 *c)
+ 
+ static void bsp_init_amd(struct cpuinfo_x86 *c)
+ {
+-
+-#ifdef CONFIG_X86_64
+-	if (c->x86 >= 0xf) {
+-		unsigned long long tseg;
+-
+-		/*
+-		 * Split up direct mapping around the TSEG SMM area.
+-		 * Don't do it for gbpages because there seems very little
+-		 * benefit in doing so.
+-		 */
+-		if (!rdmsrl_safe(MSR_K8_TSEG_ADDR, &tseg)) {
+-			unsigned long pfn = tseg >> PAGE_SHIFT;
+-
+-			pr_debug("tseg: %010llx\n", tseg);
+-			if (pfn_range_is_mapped(pfn, pfn + 1))
+-				set_memory_4k((unsigned long)__va(tseg), 1);
+-		}
+-	}
+-#endif
+-
+ 	if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
+ 
+ 		if (c->x86 > 0x10 ||
+diff --git a/arch/x86/kernel/cpu/hygon.c b/arch/x86/kernel/cpu/hygon.c
+index dc0840aae26c..ae59115d18f9 100644
+--- a/arch/x86/kernel/cpu/hygon.c
++++ b/arch/x86/kernel/cpu/hygon.c
+@@ -14,9 +14,6 @@
+ #include 
+ #include 
+ #include 
+-#ifdef CONFIG_X86_64
+-# include 
+-#endif
+ 
+ #include "cpu.h"
+ 
+@@ -203,23 +200,6 @@ static void early_init_hygon_mc(struct cpuinfo_x86 *c)
+ 
+ static void bsp_init_hygon(struct cpuinfo_x86 *c)
+ {
+-#ifdef CONFIG_X86_64
+-	unsigned long long tseg;
+-
+-	/*
+-	 * Split up direct mapping around the TSEG SMM area.
+-	 * Don't do it for gbpages because there seems very little
+-	 * benefit in doing so.
+-	 */
+-	if (!rdmsrl_safe(MSR_K8_TSEG_ADDR, &tseg)) {
+-		unsigned long pfn = tseg >> PAGE_SHIFT;
+-
+-		pr_debug("tseg: %010llx\n", tseg);
+-		if (pfn_range_is_mapped(pfn, pfn + 1))
+-			set_memory_4k((unsigned long)__va(tseg), 1);
+-	}
+-#endif
+-
+ 	if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
+ 		u64 val;
+ 

commit 31d8546033053b98de00846ede8088bdbe38651d
+Author: Arvind Sankar 
+Date:   Mon Oct 5 11:12:08 2020 -0400
+
+    x86/head/64: Remove unused GET_CR2_INTO() macro
+    
+    Commit
+    
+      4b47cdbda6f1 ("x86/head/64: Move early exception dispatch to C code")
+    
+    removed the usage of GET_CR2_INTO().
+    
+    Drop the definition as well, and related definitions in paravirt.h and
+    asm-offsets.h
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Borislav Petkov 
+    Link: https://lkml.kernel.org/r/20201005151208.2212886-3-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
+index d25cc6830e89..f8dce11d2bc1 100644
+--- a/arch/x86/include/asm/paravirt.h
++++ b/arch/x86/include/asm/paravirt.h
+@@ -812,17 +812,6 @@ extern void default_banner(void);
+ #endif /* CONFIG_PARAVIRT_XXL */
+ #endif	/* CONFIG_X86_64 */
+ 
+-#ifdef CONFIG_PARAVIRT_XXL
+-
+-#define GET_CR2_INTO_AX							\
+-	PARA_SITE(PARA_PATCH(PV_MMU_read_cr2),				\
+-		  ANNOTATE_RETPOLINE_SAFE;				\
+-		  call PARA_INDIRECT(pv_ops+PV_MMU_read_cr2);		\
+-		 )
+-
+-#endif /* CONFIG_PARAVIRT_XXL */
+-
+-
+ #endif /* __ASSEMBLY__ */
+ #else  /* CONFIG_PARAVIRT */
+ # define default_banner x86_init_noop
+diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
+index 70b7154f4bdd..60b9f42ce3c1 100644
+--- a/arch/x86/kernel/asm-offsets.c
++++ b/arch/x86/kernel/asm-offsets.c
+@@ -66,7 +66,6 @@ static void __used common(void)
+ 	OFFSET(PV_IRQ_irq_disable, paravirt_patch_template, irq.irq_disable);
+ 	OFFSET(PV_IRQ_irq_enable, paravirt_patch_template, irq.irq_enable);
+ 	OFFSET(PV_CPU_iret, paravirt_patch_template, cpu.iret);
+-	OFFSET(PV_MMU_read_cr2, paravirt_patch_template, mmu.read_cr2);
+ #endif
+ 
+ #ifdef CONFIG_XEN
+diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
+index 7eb2a1c87969..2215d4cff38b 100644
+--- a/arch/x86/kernel/head_64.S
++++ b/arch/x86/kernel/head_64.S
+@@ -26,15 +26,6 @@
+ #include 
+ #include 
+ 
+-#ifdef CONFIG_PARAVIRT_XXL
+-#include 
+-#include 
+-#define GET_CR2_INTO(reg) GET_CR2_INTO_AX ; _ASM_MOV %_ASM_AX, reg
+-#else
+-#define INTERRUPT_RETURN iretq
+-#define GET_CR2_INTO(reg) _ASM_MOV %cr2, reg
+-#endif
+-
+ /*
+  * We are not able to switch in one step to the final KERNEL ADDRESS SPACE
+  * because we need identity-mapped pages.

commit 0ac317e89791b76055ef11b952625ef77a1d2eba
+Author: Arvind Sankar 
+Date:   Mon Oct 5 11:12:07 2020 -0400
+
+    x86/boot: Remove unused finalize_identity_maps()
+    
+    Commit
+    
+      8570978ea030 ("x86/boot/compressed/64: Don't pre-map memory in KASLR code")
+    
+    removed all the references to finalize_identity_maps(), but neglected to
+    delete the actual function. Remove it.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Borislav Petkov 
+    Link: https://lkml.kernel.org/r/20201005151208.2212886-2-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/ident_map_64.c b/arch/x86/boot/compressed/ident_map_64.c
+index a5e5db6ada3c..6bf20223dc0f 100644
+--- a/arch/x86/boot/compressed/ident_map_64.c
++++ b/arch/x86/boot/compressed/ident_map_64.c
+@@ -167,16 +167,6 @@ void initialize_identity_maps(void *rmode)
+ 	write_cr3(top_level_pgt);
+ }
+ 
+-/*
+- * This switches the page tables to the new level4 that has been built
+- * via calls to add_identity_map() above. If booted via startup_32(),
+- * this is effectively a no-op.
+- */
+-void finalize_identity_maps(void)
+-{
+-	write_cr3(top_level_pgt);
+-}
+-
+ static pte_t *split_large_pmd(struct x86_mapping_info *info,
+ 			      pmd_t *pmdp, unsigned long __address)
+ {

commit 3347acc6fcd4ee71ad18a9ff9d9dac176b517329
+Author: Arvind Sankar 
+Date:   Fri Nov 13 22:51:59 2020 -0800
+
+    compiler.h: fix barrier_data() on clang
+    
+    Commit 815f0ddb346c ("include/linux/compiler*.h: make compiler-*.h
+    mutually exclusive") neglected to copy barrier_data() from
+    compiler-gcc.h into compiler-clang.h.
+    
+    The definition in compiler-gcc.h was really to work around clang's more
+    aggressive optimization, so this broke barrier_data() on clang, and
+    consequently memzero_explicit() as well.
+    
+    For example, this results in at least the memzero_explicit() call in
+    lib/crypto/sha256.c:sha256_transform() being optimized away by clang.
+    
+    Fix this by moving the definition of barrier_data() into compiler.h.
+    
+    Also move the gcc/clang definition of barrier() into compiler.h,
+    __memory_barrier() is icc-specific (and barrier() is already defined
+    using it in compiler-intel.h) and doesn't belong in compiler.h.
+    
+    [rdunlap@infradead.org: fix ALPHA builds when SMP is not enabled]
+    
+    Link: https://lkml.kernel.org/r/20201101231835.4589-1-rdunlap@infradead.org
+    Fixes: 815f0ddb346c ("include/linux/compiler*.h: make compiler-*.h mutually exclusive")
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Randy Dunlap 
+    Signed-off-by: Andrew Morton 
+    Tested-by: Nick Desaulniers 
+    Reviewed-by: Nick Desaulniers 
+    Reviewed-by: Kees Cook 
+    Cc: 
+    Link: https://lkml.kernel.org/r/20201014212631.207844-1-nivedita@alum.mit.edu
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/asm-generic/barrier.h b/include/asm-generic/barrier.h
+index 798027bb89be..640f09479bdf 100644
+--- a/include/asm-generic/barrier.h
++++ b/include/asm-generic/barrier.h
+@@ -13,6 +13,7 @@
+ 
+ #ifndef __ASSEMBLY__
+ 
++#include 
+ #include 
+ 
+ #ifndef nop
+diff --git a/include/linux/compiler-clang.h b/include/linux/compiler-clang.h
+index 230604e7f057..dd7233c48bf3 100644
+--- a/include/linux/compiler-clang.h
++++ b/include/linux/compiler-clang.h
+@@ -60,12 +60,6 @@
+ #define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
+ #endif
+ 
+-/* The following are for compatibility with GCC, from compiler-gcc.h,
+- * and may be redefined here because they should not be shared with other
+- * compilers, like ICC.
+- */
+-#define barrier() __asm__ __volatile__("" : : : "memory")
+-
+ #if __has_feature(shadow_call_stack)
+ # define __noscs	__attribute__((__no_sanitize__("shadow-call-stack")))
+ #endif
+diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
+index 5deb37024574..74c6c0486eed 100644
+--- a/include/linux/compiler-gcc.h
++++ b/include/linux/compiler-gcc.h
+@@ -15,25 +15,6 @@
+ # error Sorry, your version of GCC is too old - please use 4.9 or newer.
+ #endif
+ 
+-/* Optimization barrier */
+-
+-/* The "volatile" is due to gcc bugs */
+-#define barrier() __asm__ __volatile__("": : :"memory")
+-/*
+- * This version is i.e. to prevent dead stores elimination on @ptr
+- * where gcc and llvm may behave differently when otherwise using
+- * normal barrier(): while gcc behavior gets along with a normal
+- * barrier(), llvm needs an explicit input variable to be assumed
+- * clobbered. The issue is as follows: while the inline asm might
+- * access any memory it wants, the compiler could have fit all of
+- * @ptr into memory registers instead, and since @ptr never escaped
+- * from that, it proved that the inline asm wasn't touching any of
+- * it. This version works well with both compilers, i.e. we're telling
+- * the compiler that the inline asm absolutely may see the contents
+- * of @ptr. See also: https://llvm.org/bugs/show_bug.cgi?id=15495
+- */
+-#define barrier_data(ptr) __asm__ __volatile__("": :"r"(ptr) :"memory")
+-
+ /*
+  * This macro obfuscates arithmetic on a variable address so that gcc
+  * shouldn't recognize the original var, and make assumptions about it.
+diff --git a/include/linux/compiler.h b/include/linux/compiler.h
+index e512f5505dad..b8fe0c23cfff 100644
+--- a/include/linux/compiler.h
++++ b/include/linux/compiler.h
+@@ -80,11 +80,25 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
+ 
+ /* Optimization barrier */
+ #ifndef barrier
+-# define barrier() __memory_barrier()
++/* The "volatile" is due to gcc bugs */
++# define barrier() __asm__ __volatile__("": : :"memory")
+ #endif
+ 
+ #ifndef barrier_data
+-# define barrier_data(ptr) barrier()
++/*
++ * This version is i.e. to prevent dead stores elimination on @ptr
++ * where gcc and llvm may behave differently when otherwise using
++ * normal barrier(): while gcc behavior gets along with a normal
++ * barrier(), llvm needs an explicit input variable to be assumed
++ * clobbered. The issue is as follows: while the inline asm might
++ * access any memory it wants, the compiler could have fit all of
++ * @ptr into memory registers instead, and since @ptr never escaped
++ * from that, it proved that the inline asm wasn't touching any of
++ * it. This version works well with both compilers, i.e. we're telling
++ * the compiler that the inline asm absolutely may see the contents
++ * of @ptr. See also: https://llvm.org/bugs/show_bug.cgi?id=15495
++ */
++# define barrier_data(ptr) __asm__ __volatile__("": :"r"(ptr) :"memory")
+ #endif
+ 
+ /* workaround for GCC PR82365 if needed */

commit c2fe61d8be491ff8188edaf22e838f819999146b
+Author: Arvind Sankar 
+Date:   Tue Nov 10 11:39:19 2020 -0500
+
+    efi/x86: Free efi_pgd with free_pages()
+    
+    Commit
+    
+      d9e9a6418065 ("x86/mm/pti: Allocate a separate user PGD")
+    
+    changed the PGD allocation to allocate PGD_ALLOCATION_ORDER pages, so in
+    the error path it should be freed using free_pages() rather than
+    free_page().
+    
+    Commit
+    
+        06ace26f4e6f ("x86/efi: Free efi_pgd with free_pages()")
+    
+    fixed one instance of this, but missed another.
+    
+    Move the freeing out-of-line to avoid code duplication and fix this bug.
+    
+    Fixes: d9e9a6418065 ("x86/mm/pti: Allocate a separate user PGD")
+    Link: https://lore.kernel.org/r/20201110163919.1134431-1-nivedita@alum.mit.edu
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
+index 8f5759df7776..e1e8d4e3a213 100644
+--- a/arch/x86/platform/efi/efi_64.c
++++ b/arch/x86/platform/efi/efi_64.c
+@@ -78,28 +78,30 @@ int __init efi_alloc_page_tables(void)
+ 	gfp_mask = GFP_KERNEL | __GFP_ZERO;
+ 	efi_pgd = (pgd_t *)__get_free_pages(gfp_mask, PGD_ALLOCATION_ORDER);
+ 	if (!efi_pgd)
+-		return -ENOMEM;
++		goto fail;
+ 
+ 	pgd = efi_pgd + pgd_index(EFI_VA_END);
+ 	p4d = p4d_alloc(&init_mm, pgd, EFI_VA_END);
+-	if (!p4d) {
+-		free_page((unsigned long)efi_pgd);
+-		return -ENOMEM;
+-	}
++	if (!p4d)
++		goto free_pgd;
+ 
+ 	pud = pud_alloc(&init_mm, p4d, EFI_VA_END);
+-	if (!pud) {
+-		if (pgtable_l5_enabled())
+-			free_page((unsigned long) pgd_page_vaddr(*pgd));
+-		free_pages((unsigned long)efi_pgd, PGD_ALLOCATION_ORDER);
+-		return -ENOMEM;
+-	}
++	if (!pud)
++		goto free_p4d;
+ 
+ 	efi_mm.pgd = efi_pgd;
+ 	mm_init_cpumask(&efi_mm);
+ 	init_new_context(NULL, &efi_mm);
+ 
+ 	return 0;
++
++free_p4d:
++	if (pgtable_l5_enabled())
++		free_page((unsigned long)pgd_page_vaddr(*pgd));
++free_pgd:
++	free_pages((unsigned long)efi_pgd, PGD_ALLOCATION_ORDER);
++fail:
++	return -ENOMEM;
+ }
+ 
+ /*

commit 18d05ca4486fe38991c3166b1f4df26b8a029665
+Author: Arvind Sankar 
+Date:   Sun Oct 25 10:31:19 2020 -0400
+
+    crypto: lib/sha256 - Unroll LOAD and BLEND loops
+    
+    Unrolling the LOAD and BLEND loops improves performance by ~8% on x86_64
+    (tested on Broadwell Xeon) while not increasing code size too much.
+    
+    Signed-off-by: Arvind Sankar 
+    Reviewed-by: Eric Biggers 
+    Acked-by: Ard Biesheuvel 
+    Signed-off-by: Herbert Xu 
+
+diff --git a/lib/crypto/sha256.c b/lib/crypto/sha256.c
+index e2e29d9b0ccd..cdef37c05972 100644
+--- a/lib/crypto/sha256.c
++++ b/lib/crypto/sha256.c
+@@ -76,12 +76,28 @@ static void sha256_transform(u32 *state, const u8 *input, u32 *W)
+ 	int i;
+ 
+ 	/* load the input */
+-	for (i = 0; i < 16; i++)
+-		LOAD_OP(i, W, input);
++	for (i = 0; i < 16; i += 8) {
++		LOAD_OP(i + 0, W, input);
++		LOAD_OP(i + 1, W, input);
++		LOAD_OP(i + 2, W, input);
++		LOAD_OP(i + 3, W, input);
++		LOAD_OP(i + 4, W, input);
++		LOAD_OP(i + 5, W, input);
++		LOAD_OP(i + 6, W, input);
++		LOAD_OP(i + 7, W, input);
++	}
+ 
+ 	/* now blend */
+-	for (i = 16; i < 64; i++)
+-		BLEND_OP(i, W);
++	for (i = 16; i < 64; i += 8) {
++		BLEND_OP(i + 0, W);
++		BLEND_OP(i + 1, W);
++		BLEND_OP(i + 2, W);
++		BLEND_OP(i + 3, W);
++		BLEND_OP(i + 4, W);
++		BLEND_OP(i + 5, W);
++		BLEND_OP(i + 6, W);
++		BLEND_OP(i + 7, W);
++	}
+ 
+ 	/* load the state into our registers */
+ 	a = state[0];  b = state[1];  c = state[2];  d = state[3];

commit 63642d5c141f1bcbe97f7895467a724ad2e3f346
+Author: Arvind Sankar 
+Date:   Sun Oct 25 10:31:18 2020 -0400
+
+    crypto: lib/sha256 - Unroll SHA256 loop 8 times intead of 64
+    
+    This reduces code size substantially (on x86_64 with gcc-10 the size of
+    sha256_update() goes from 7593 bytes to 1952 bytes including the new
+    SHA256_K array), and on x86 is slightly faster than the full unroll
+    (tested on Broadwell Xeon).
+    
+    Signed-off-by: Arvind Sankar 
+    Reviewed-by: Eric Biggers 
+    Acked-by: Ard Biesheuvel 
+    Signed-off-by: Herbert Xu 
+
+diff --git a/lib/crypto/sha256.c b/lib/crypto/sha256.c
+index c6bfeacc5b81..e2e29d9b0ccd 100644
+--- a/lib/crypto/sha256.c
++++ b/lib/crypto/sha256.c
+@@ -18,6 +18,25 @@
+ #include 
+ #include 
+ 
++static const u32 SHA256_K[] = {
++	0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
++	0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
++	0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
++	0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
++	0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
++	0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
++	0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
++	0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
++	0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
++	0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
++	0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
++	0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
++	0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
++	0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
++	0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
++	0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
++};
++
+ static inline u32 Ch(u32 x, u32 y, u32 z)
+ {
+ 	return z ^ (x & (y ^ z));
+@@ -43,9 +62,17 @@ static inline void BLEND_OP(int I, u32 *W)
+ 	W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
+ }
+ 
++#define SHA256_ROUND(i, a, b, c, d, e, f, g, h) do {		\
++	u32 t1, t2;						\
++	t1 = h + e1(e) + Ch(e, f, g) + SHA256_K[i] + W[i];	\
++	t2 = e0(a) + Maj(a, b, c);				\
++	d += t1;						\
++	h = t1 + t2;						\
++} while (0)
++
+ static void sha256_transform(u32 *state, const u8 *input, u32 *W)
+ {
+-	u32 a, b, c, d, e, f, g, h, t1, t2;
++	u32 a, b, c, d, e, f, g, h;
+ 	int i;
+ 
+ 	/* load the input */
+@@ -61,141 +88,16 @@ static void sha256_transform(u32 *state, const u8 *input, u32 *W)
+ 	e = state[4];  f = state[5];  g = state[6];  h = state[7];
+ 
+ 	/* now iterate */
+-	t1 = h + e1(e) + Ch(e, f, g) + 0x428a2f98 + W[0];
+-	t2 = e0(a) + Maj(a, b, c);    d += t1;    h = t1 + t2;
+-	t1 = g + e1(d) + Ch(d, e, f) + 0x71374491 + W[1];
+-	t2 = e0(h) + Maj(h, a, b);    c += t1;    g = t1 + t2;
+-	t1 = f + e1(c) + Ch(c, d, e) + 0xb5c0fbcf + W[2];
+-	t2 = e0(g) + Maj(g, h, a);    b += t1;    f = t1 + t2;
+-	t1 = e + e1(b) + Ch(b, c, d) + 0xe9b5dba5 + W[3];
+-	t2 = e0(f) + Maj(f, g, h);    a += t1;    e = t1 + t2;
+-	t1 = d + e1(a) + Ch(a, b, c) + 0x3956c25b + W[4];
+-	t2 = e0(e) + Maj(e, f, g);    h += t1;    d = t1 + t2;
+-	t1 = c + e1(h) + Ch(h, a, b) + 0x59f111f1 + W[5];
+-	t2 = e0(d) + Maj(d, e, f);    g += t1;    c = t1 + t2;
+-	t1 = b + e1(g) + Ch(g, h, a) + 0x923f82a4 + W[6];
+-	t2 = e0(c) + Maj(c, d, e);    f += t1;    b = t1 + t2;
+-	t1 = a + e1(f) + Ch(f, g, h) + 0xab1c5ed5 + W[7];
+-	t2 = e0(b) + Maj(b, c, d);    e += t1;    a = t1 + t2;
+-
+-	t1 = h + e1(e) + Ch(e, f, g) + 0xd807aa98 + W[8];
+-	t2 = e0(a) + Maj(a, b, c);    d += t1;    h = t1 + t2;
+-	t1 = g + e1(d) + Ch(d, e, f) + 0x12835b01 + W[9];
+-	t2 = e0(h) + Maj(h, a, b);    c += t1;    g = t1 + t2;
+-	t1 = f + e1(c) + Ch(c, d, e) + 0x243185be + W[10];
+-	t2 = e0(g) + Maj(g, h, a);    b += t1;    f = t1 + t2;
+-	t1 = e + e1(b) + Ch(b, c, d) + 0x550c7dc3 + W[11];
+-	t2 = e0(f) + Maj(f, g, h);    a += t1;    e = t1 + t2;
+-	t1 = d + e1(a) + Ch(a, b, c) + 0x72be5d74 + W[12];
+-	t2 = e0(e) + Maj(e, f, g);    h += t1;    d = t1 + t2;
+-	t1 = c + e1(h) + Ch(h, a, b) + 0x80deb1fe + W[13];
+-	t2 = e0(d) + Maj(d, e, f);    g += t1;    c = t1 + t2;
+-	t1 = b + e1(g) + Ch(g, h, a) + 0x9bdc06a7 + W[14];
+-	t2 = e0(c) + Maj(c, d, e);    f += t1;    b = t1 + t2;
+-	t1 = a + e1(f) + Ch(f, g, h) + 0xc19bf174 + W[15];
+-	t2 = e0(b) + Maj(b, c, d);    e += t1;    a = t1 + t2;
+-
+-	t1 = h + e1(e) + Ch(e, f, g) + 0xe49b69c1 + W[16];
+-	t2 = e0(a) + Maj(a, b, c);    d += t1;    h = t1 + t2;
+-	t1 = g + e1(d) + Ch(d, e, f) + 0xefbe4786 + W[17];
+-	t2 = e0(h) + Maj(h, a, b);    c += t1;    g = t1 + t2;
+-	t1 = f + e1(c) + Ch(c, d, e) + 0x0fc19dc6 + W[18];
+-	t2 = e0(g) + Maj(g, h, a);    b += t1;    f = t1 + t2;
+-	t1 = e + e1(b) + Ch(b, c, d) + 0x240ca1cc + W[19];
+-	t2 = e0(f) + Maj(f, g, h);    a += t1;    e = t1 + t2;
+-	t1 = d + e1(a) + Ch(a, b, c) + 0x2de92c6f + W[20];
+-	t2 = e0(e) + Maj(e, f, g);    h += t1;    d = t1 + t2;
+-	t1 = c + e1(h) + Ch(h, a, b) + 0x4a7484aa + W[21];
+-	t2 = e0(d) + Maj(d, e, f);    g += t1;    c = t1 + t2;
+-	t1 = b + e1(g) + Ch(g, h, a) + 0x5cb0a9dc + W[22];
+-	t2 = e0(c) + Maj(c, d, e);    f += t1;    b = t1 + t2;
+-	t1 = a + e1(f) + Ch(f, g, h) + 0x76f988da + W[23];
+-	t2 = e0(b) + Maj(b, c, d);    e += t1;    a = t1 + t2;
+-
+-	t1 = h + e1(e) + Ch(e, f, g) + 0x983e5152 + W[24];
+-	t2 = e0(a) + Maj(a, b, c);    d += t1;    h = t1 + t2;
+-	t1 = g + e1(d) + Ch(d, e, f) + 0xa831c66d + W[25];
+-	t2 = e0(h) + Maj(h, a, b);    c += t1;    g = t1 + t2;
+-	t1 = f + e1(c) + Ch(c, d, e) + 0xb00327c8 + W[26];
+-	t2 = e0(g) + Maj(g, h, a);    b += t1;    f = t1 + t2;
+-	t1 = e + e1(b) + Ch(b, c, d) + 0xbf597fc7 + W[27];
+-	t2 = e0(f) + Maj(f, g, h);    a += t1;    e = t1 + t2;
+-	t1 = d + e1(a) + Ch(a, b, c) + 0xc6e00bf3 + W[28];
+-	t2 = e0(e) + Maj(e, f, g);    h += t1;    d = t1 + t2;
+-	t1 = c + e1(h) + Ch(h, a, b) + 0xd5a79147 + W[29];
+-	t2 = e0(d) + Maj(d, e, f);    g += t1;    c = t1 + t2;
+-	t1 = b + e1(g) + Ch(g, h, a) + 0x06ca6351 + W[30];
+-	t2 = e0(c) + Maj(c, d, e);    f += t1;    b = t1 + t2;
+-	t1 = a + e1(f) + Ch(f, g, h) + 0x14292967 + W[31];
+-	t2 = e0(b) + Maj(b, c, d);    e += t1;    a = t1 + t2;
+-
+-	t1 = h + e1(e) + Ch(e, f, g) + 0x27b70a85 + W[32];
+-	t2 = e0(a) + Maj(a, b, c);    d += t1;    h = t1 + t2;
+-	t1 = g + e1(d) + Ch(d, e, f) + 0x2e1b2138 + W[33];
+-	t2 = e0(h) + Maj(h, a, b);    c += t1;    g = t1 + t2;
+-	t1 = f + e1(c) + Ch(c, d, e) + 0x4d2c6dfc + W[34];
+-	t2 = e0(g) + Maj(g, h, a);    b += t1;    f = t1 + t2;
+-	t1 = e + e1(b) + Ch(b, c, d) + 0x53380d13 + W[35];
+-	t2 = e0(f) + Maj(f, g, h);    a += t1;    e = t1 + t2;
+-	t1 = d + e1(a) + Ch(a, b, c) + 0x650a7354 + W[36];
+-	t2 = e0(e) + Maj(e, f, g);    h += t1;    d = t1 + t2;
+-	t1 = c + e1(h) + Ch(h, a, b) + 0x766a0abb + W[37];
+-	t2 = e0(d) + Maj(d, e, f);    g += t1;    c = t1 + t2;
+-	t1 = b + e1(g) + Ch(g, h, a) + 0x81c2c92e + W[38];
+-	t2 = e0(c) + Maj(c, d, e);    f += t1;    b = t1 + t2;
+-	t1 = a + e1(f) + Ch(f, g, h) + 0x92722c85 + W[39];
+-	t2 = e0(b) + Maj(b, c, d);    e += t1;    a = t1 + t2;
+-
+-	t1 = h + e1(e) + Ch(e, f, g) + 0xa2bfe8a1 + W[40];
+-	t2 = e0(a) + Maj(a, b, c);    d += t1;    h = t1 + t2;
+-	t1 = g + e1(d) + Ch(d, e, f) + 0xa81a664b + W[41];
+-	t2 = e0(h) + Maj(h, a, b);    c += t1;    g = t1 + t2;
+-	t1 = f + e1(c) + Ch(c, d, e) + 0xc24b8b70 + W[42];
+-	t2 = e0(g) + Maj(g, h, a);    b += t1;    f = t1 + t2;
+-	t1 = e + e1(b) + Ch(b, c, d) + 0xc76c51a3 + W[43];
+-	t2 = e0(f) + Maj(f, g, h);    a += t1;    e = t1 + t2;
+-	t1 = d + e1(a) + Ch(a, b, c) + 0xd192e819 + W[44];
+-	t2 = e0(e) + Maj(e, f, g);    h += t1;    d = t1 + t2;
+-	t1 = c + e1(h) + Ch(h, a, b) + 0xd6990624 + W[45];
+-	t2 = e0(d) + Maj(d, e, f);    g += t1;    c = t1 + t2;
+-	t1 = b + e1(g) + Ch(g, h, a) + 0xf40e3585 + W[46];
+-	t2 = e0(c) + Maj(c, d, e);    f += t1;    b = t1 + t2;
+-	t1 = a + e1(f) + Ch(f, g, h) + 0x106aa070 + W[47];
+-	t2 = e0(b) + Maj(b, c, d);    e += t1;    a = t1 + t2;
+-
+-	t1 = h + e1(e) + Ch(e, f, g) + 0x19a4c116 + W[48];
+-	t2 = e0(a) + Maj(a, b, c);    d += t1;    h = t1 + t2;
+-	t1 = g + e1(d) + Ch(d, e, f) + 0x1e376c08 + W[49];
+-	t2 = e0(h) + Maj(h, a, b);    c += t1;    g = t1 + t2;
+-	t1 = f + e1(c) + Ch(c, d, e) + 0x2748774c + W[50];
+-	t2 = e0(g) + Maj(g, h, a);    b += t1;    f = t1 + t2;
+-	t1 = e + e1(b) + Ch(b, c, d) + 0x34b0bcb5 + W[51];
+-	t2 = e0(f) + Maj(f, g, h);    a += t1;    e = t1 + t2;
+-	t1 = d + e1(a) + Ch(a, b, c) + 0x391c0cb3 + W[52];
+-	t2 = e0(e) + Maj(e, f, g);    h += t1;    d = t1 + t2;
+-	t1 = c + e1(h) + Ch(h, a, b) + 0x4ed8aa4a + W[53];
+-	t2 = e0(d) + Maj(d, e, f);    g += t1;    c = t1 + t2;
+-	t1 = b + e1(g) + Ch(g, h, a) + 0x5b9cca4f + W[54];
+-	t2 = e0(c) + Maj(c, d, e);    f += t1;    b = t1 + t2;
+-	t1 = a + e1(f) + Ch(f, g, h) + 0x682e6ff3 + W[55];
+-	t2 = e0(b) + Maj(b, c, d);    e += t1;    a = t1 + t2;
+-
+-	t1 = h + e1(e) + Ch(e, f, g) + 0x748f82ee + W[56];
+-	t2 = e0(a) + Maj(a, b, c);    d += t1;    h = t1 + t2;
+-	t1 = g + e1(d) + Ch(d, e, f) + 0x78a5636f + W[57];
+-	t2 = e0(h) + Maj(h, a, b);    c += t1;    g = t1 + t2;
+-	t1 = f + e1(c) + Ch(c, d, e) + 0x84c87814 + W[58];
+-	t2 = e0(g) + Maj(g, h, a);    b += t1;    f = t1 + t2;
+-	t1 = e + e1(b) + Ch(b, c, d) + 0x8cc70208 + W[59];
+-	t2 = e0(f) + Maj(f, g, h);    a += t1;    e = t1 + t2;
+-	t1 = d + e1(a) + Ch(a, b, c) + 0x90befffa + W[60];
+-	t2 = e0(e) + Maj(e, f, g);    h += t1;    d = t1 + t2;
+-	t1 = c + e1(h) + Ch(h, a, b) + 0xa4506ceb + W[61];
+-	t2 = e0(d) + Maj(d, e, f);    g += t1;    c = t1 + t2;
+-	t1 = b + e1(g) + Ch(g, h, a) + 0xbef9a3f7 + W[62];
+-	t2 = e0(c) + Maj(c, d, e);    f += t1;    b = t1 + t2;
+-	t1 = a + e1(f) + Ch(f, g, h) + 0xc67178f2 + W[63];
+-	t2 = e0(b) + Maj(b, c, d);    e += t1;    a = t1 + t2;
++	for (i = 0; i < 64; i += 8) {
++		SHA256_ROUND(i + 0, a, b, c, d, e, f, g, h);
++		SHA256_ROUND(i + 1, h, a, b, c, d, e, f, g);
++		SHA256_ROUND(i + 2, g, h, a, b, c, d, e, f);
++		SHA256_ROUND(i + 3, f, g, h, a, b, c, d, e);
++		SHA256_ROUND(i + 4, e, f, g, h, a, b, c, d);
++		SHA256_ROUND(i + 5, d, e, f, g, h, a, b, c);
++		SHA256_ROUND(i + 6, c, d, e, f, g, h, a, b);
++		SHA256_ROUND(i + 7, b, c, d, e, f, g, h, a);
++	}
+ 
+ 	state[0] += a; state[1] += b; state[2] += c; state[3] += d;
+ 	state[4] += e; state[5] += f; state[6] += g; state[7] += h;

commit b8399819b2dd6f29195ed7535217b66c01b1e57d
+Author: Arvind Sankar 
+Date:   Sun Oct 25 10:31:17 2020 -0400
+
+    crypto: lib/sha256 - Clear W[] in sha256_update() instead of sha256_transform()
+    
+    The temporary W[] array is currently zeroed out once every call to
+    sha256_transform(), i.e. once every 64 bytes of input data. Moving it to
+    sha256_update() instead so that it is cleared only once per update can
+    save about 2-3% of the total time taken to compute the digest, with a
+    reasonable memset() implementation, and considerably more (~20%) with a
+    bad one (eg the x86 purgatory currently uses a memset() coded in C).
+    
+    Signed-off-by: Arvind Sankar 
+    Reviewed-by: Eric Biggers 
+    Acked-by: Ard Biesheuvel 
+    Signed-off-by: Herbert Xu 
+
+diff --git a/lib/crypto/sha256.c b/lib/crypto/sha256.c
+index 099cd11f83c1..c6bfeacc5b81 100644
+--- a/lib/crypto/sha256.c
++++ b/lib/crypto/sha256.c
+@@ -43,10 +43,9 @@ static inline void BLEND_OP(int I, u32 *W)
+ 	W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
+ }
+ 
+-static void sha256_transform(u32 *state, const u8 *input)
++static void sha256_transform(u32 *state, const u8 *input, u32 *W)
+ {
+ 	u32 a, b, c, d, e, f, g, h, t1, t2;
+-	u32 W[64];
+ 	int i;
+ 
+ 	/* load the input */
+@@ -200,15 +199,13 @@ static void sha256_transform(u32 *state, const u8 *input)
+ 
+ 	state[0] += a; state[1] += b; state[2] += c; state[3] += d;
+ 	state[4] += e; state[5] += f; state[6] += g; state[7] += h;
+-
+-	/* clear any sensitive info... */
+-	memzero_explicit(W, 64 * sizeof(u32));
+ }
+ 
+ void sha256_update(struct sha256_state *sctx, const u8 *data, unsigned int len)
+ {
+ 	unsigned int partial, done;
+ 	const u8 *src;
++	u32 W[64];
+ 
+ 	partial = sctx->count & 0x3f;
+ 	sctx->count += len;
+@@ -223,11 +220,13 @@ void sha256_update(struct sha256_state *sctx, const u8 *data, unsigned int len)
+ 		}
+ 
+ 		do {
+-			sha256_transform(sctx->state, src);
++			sha256_transform(sctx->state, src, W);
+ 			done += 64;
+ 			src = data + done;
+ 		} while (done + 63 < len);
+ 
++		memzero_explicit(W, sizeof(W));
++
+ 		partial = 0;
+ 	}
+ 	memcpy(sctx->buf + partial, src, len - done);

commit 7a4295f6c9d54e082474667e552a227606b4a085
+Author: Arvind Sankar 
+Date:   Sun Oct 25 10:31:16 2020 -0400
+
+    crypto: lib/sha256 - Don't clear temporary variables
+    
+    The assignments to clear a through h and t1/t2 are optimized out by the
+    compiler because they are unused after the assignments.
+    
+    Clearing individual scalar variables is unlikely to be useful, as they
+    may have been assigned to registers, and even if stack spilling was
+    required, there may be compiler-generated temporaries that are
+    impossible to clear in any case.
+    
+    So drop the clearing of a through h and t1/t2.
+    
+    Signed-off-by: Arvind Sankar 
+    Reviewed-by: Eric Biggers 
+    Acked-by: Ard Biesheuvel 
+    Signed-off-by: Herbert Xu 
+
+diff --git a/lib/crypto/sha256.c b/lib/crypto/sha256.c
+index d43bc39ab05e..099cd11f83c1 100644
+--- a/lib/crypto/sha256.c
++++ b/lib/crypto/sha256.c
+@@ -202,7 +202,6 @@ static void sha256_transform(u32 *state, const u8 *input)
+ 	state[4] += e; state[5] += f; state[6] += g; state[7] += h;
+ 
+ 	/* clear any sensitive info... */
+-	a = b = c = d = e = f = g = h = t1 = t2 = 0;
+ 	memzero_explicit(W, 64 * sizeof(u32));
+ }
+ 

commit 458c0480dcb338d7b72e89b2e88a622965adcea4
+Author: Arvind Sankar 
+Date:   Sun Oct 25 10:31:15 2020 -0400
+
+    crypto: hash - Use memzero_explicit() for clearing state
+    
+    Without the barrier_data() inside memzero_explicit(), the compiler may
+    optimize away the state-clearing if it can tell that the state is not
+    used afterwards.
+    
+    Signed-off-by: Arvind Sankar 
+    Acked-by: Ard Biesheuvel 
+    Signed-off-by: Herbert Xu 
+
+diff --git a/arch/arm64/crypto/ghash-ce-glue.c b/arch/arm64/crypto/ghash-ce-glue.c
+index 8536008e3e35..2427e2f3a9a1 100644
+--- a/arch/arm64/crypto/ghash-ce-glue.c
++++ b/arch/arm64/crypto/ghash-ce-glue.c
+@@ -168,7 +168,7 @@ static int ghash_final(struct shash_desc *desc, u8 *dst)
+ 	put_unaligned_be64(ctx->digest[1], dst);
+ 	put_unaligned_be64(ctx->digest[0], dst + 8);
+ 
+-	*ctx = (struct ghash_desc_ctx){};
++	memzero_explicit(ctx, sizeof(*ctx));
+ 	return 0;
+ }
+ 
+diff --git a/arch/arm64/crypto/poly1305-glue.c b/arch/arm64/crypto/poly1305-glue.c
+index f33ada70c4ed..683de671741a 100644
+--- a/arch/arm64/crypto/poly1305-glue.c
++++ b/arch/arm64/crypto/poly1305-glue.c
+@@ -177,7 +177,7 @@ void poly1305_final_arch(struct poly1305_desc_ctx *dctx, u8 *dst)
+ 	}
+ 
+ 	poly1305_emit(&dctx->h, dst, dctx->s);
+-	*dctx = (struct poly1305_desc_ctx){};
++	memzero_explicit(dctx, sizeof(*dctx));
+ }
+ EXPORT_SYMBOL(poly1305_final_arch);
+ 
+diff --git a/arch/arm64/crypto/sha3-ce-glue.c b/arch/arm64/crypto/sha3-ce-glue.c
+index 9a4bbfc45f40..e5a2936f0886 100644
+--- a/arch/arm64/crypto/sha3-ce-glue.c
++++ b/arch/arm64/crypto/sha3-ce-glue.c
+@@ -94,7 +94,7 @@ static int sha3_final(struct shash_desc *desc, u8 *out)
+ 	if (digest_size & 4)
+ 		put_unaligned_le32(sctx->st[i], (__le32 *)digest);
+ 
+-	*sctx = (struct sha3_state){};
++	memzero_explicit(sctx, sizeof(*sctx));
+ 	return 0;
+ }
+ 
+diff --git a/arch/x86/crypto/poly1305_glue.c b/arch/x86/crypto/poly1305_glue.c
+index e508dbd91813..64d09520d279 100644
+--- a/arch/x86/crypto/poly1305_glue.c
++++ b/arch/x86/crypto/poly1305_glue.c
+@@ -209,7 +209,7 @@ void poly1305_final_arch(struct poly1305_desc_ctx *dctx, u8 *dst)
+ 	}
+ 
+ 	poly1305_simd_emit(&dctx->h, dst, dctx->s);
+-	*dctx = (struct poly1305_desc_ctx){};
++	memzero_explicit(dctx, sizeof(*dctx));
+ }
+ EXPORT_SYMBOL(poly1305_final_arch);
+ 
+diff --git a/include/crypto/sha1_base.h b/include/crypto/sha1_base.h
+index 20fd1f7468af..a5d6033efef7 100644
+--- a/include/crypto/sha1_base.h
++++ b/include/crypto/sha1_base.h
+@@ -12,6 +12,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ 
+@@ -101,7 +102,7 @@ static inline int sha1_base_finish(struct shash_desc *desc, u8 *out)
+ 	for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(__be32); i++)
+ 		put_unaligned_be32(sctx->state[i], digest++);
+ 
+-	*sctx = (struct sha1_state){};
++	memzero_explicit(sctx, sizeof(*sctx));
+ 	return 0;
+ }
+ 
+diff --git a/include/crypto/sha256_base.h b/include/crypto/sha256_base.h
+index 6ded110783ae..93f9fd21cc06 100644
+--- a/include/crypto/sha256_base.h
++++ b/include/crypto/sha256_base.h
+@@ -12,6 +12,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ 
+@@ -105,7 +106,7 @@ static inline int sha256_base_finish(struct shash_desc *desc, u8 *out)
+ 	for (i = 0; digest_size > 0; i++, digest_size -= sizeof(__be32))
+ 		put_unaligned_be32(sctx->state[i], digest++);
+ 
+-	*sctx = (struct sha256_state){};
++	memzero_explicit(sctx, sizeof(*sctx));
+ 	return 0;
+ }
+ 
+diff --git a/include/crypto/sha512_base.h b/include/crypto/sha512_base.h
+index fb19c77494dc..93ab73baa38e 100644
+--- a/include/crypto/sha512_base.h
++++ b/include/crypto/sha512_base.h
+@@ -12,6 +12,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ 
+@@ -126,7 +127,7 @@ static inline int sha512_base_finish(struct shash_desc *desc, u8 *out)
+ 	for (i = 0; digest_size > 0; i++, digest_size -= sizeof(__be64))
+ 		put_unaligned_be64(sctx->state[i], digest++);
+ 
+-	*sctx = (struct sha512_state){};
++	memzero_explicit(sctx, sizeof(*sctx));
+ 	return 0;
+ }
+ 
+diff --git a/include/crypto/sm3_base.h b/include/crypto/sm3_base.h
+index 1cbf9aa1fe52..2f3a32ab97bb 100644
+--- a/include/crypto/sm3_base.h
++++ b/include/crypto/sm3_base.h
+@@ -13,6 +13,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ 
+ typedef void (sm3_block_fn)(struct sm3_state *sst, u8 const *src, int blocks);
+@@ -104,7 +105,7 @@ static inline int sm3_base_finish(struct shash_desc *desc, u8 *out)
+ 	for (i = 0; i < SM3_DIGEST_SIZE / sizeof(__be32); i++)
+ 		put_unaligned_be32(sctx->state[i], digest++);
+ 
+-	*sctx = (struct sm3_state){};
++	memzero_explicit(sctx, sizeof(*sctx));
+ 	return 0;
+ }
+ 

commit 1762818f25f3f99c5083caa13d69e5e5aa2e4b6f
+Author: Arvind Sankar 
+Date:   Sun Oct 25 10:31:14 2020 -0400
+
+    crypto: lib/sha256 - Use memzero_explicit() for clearing state
+    
+    Without the barrier_data() inside memzero_explicit(), the compiler may
+    optimize away the state-clearing if it can tell that the state is not
+    used afterwards. At least in lib/crypto/sha256.c:__sha256_final(), the
+    function can get inlined into sha256(), in which case the memset is
+    optimized away.
+    
+    Signed-off-by: Arvind Sankar 
+    Reviewed-by: Eric Biggers 
+    Acked-by: Ard Biesheuvel 
+    Signed-off-by: Herbert Xu 
+
+diff --git a/lib/crypto/sha256.c b/lib/crypto/sha256.c
+index 2321f6cb322f..d43bc39ab05e 100644
+--- a/lib/crypto/sha256.c
++++ b/lib/crypto/sha256.c
+@@ -265,7 +265,7 @@ static void __sha256_final(struct sha256_state *sctx, u8 *out, int digest_words)
+ 		put_unaligned_be32(sctx->state[i], &dst[i]);
+ 
+ 	/* Zeroize sensitive information. */
+-	memset(sctx, 0, sizeof(*sctx));
++	memzero_explicit(sctx, sizeof(*sctx));
+ }
+ 
+ void sha256_final(struct sha256_state *sctx, u8 *out)

commit ea3186b9572a1b0299448697cfc44920061872cf
+Author: Arvind Sankar 
+Date:   Thu Oct 29 12:19:03 2020 -0400
+
+    x86/build: Fix vmlinux size check on 64-bit
+    
+    Commit
+    
+      b4e0409a36f4 ("x86: check vmlinux limits, 64-bit")
+    
+    added a check that the size of the 64-bit kernel is less than
+    KERNEL_IMAGE_SIZE.
+    
+    The check uses (_end - _text), but this is not enough. The initial
+    PMD used in startup_64() (level2_kernel_pgt) can only map upto
+    KERNEL_IMAGE_SIZE from __START_KERNEL_map, not from _text, and the
+    modules area (MODULES_VADDR) starts at KERNEL_IMAGE_SIZE.
+    
+    The correct check is what is currently done for 32-bit, since
+    LOAD_OFFSET is defined appropriately for the two architectures. Just
+    check (_end - LOAD_OFFSET) against KERNEL_IMAGE_SIZE unconditionally.
+    
+    Note that on 32-bit, the limit is not strict: KERNEL_IMAGE_SIZE is not
+    really used by the main kernel. The higher the kernel is located, the
+    less the space available for the vmalloc area. However, it is used by
+    KASLR in the compressed stub to limit the maximum address of the kernel
+    to a safe value.
+    
+    Clean up various comments to clarify that despite the name,
+    KERNEL_IMAGE_SIZE is not a limit on the size of the kernel image, but a
+    limit on the maximum virtual address that the image can occupy.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Borislav Petkov 
+    Link: https://lkml.kernel.org/r/20201029161903.2553528-1-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/include/asm/page_32_types.h b/arch/x86/include/asm/page_32_types.h
+index f462895a33e4..faf9cc1c14bb 100644
+--- a/arch/x86/include/asm/page_32_types.h
++++ b/arch/x86/include/asm/page_32_types.h
+@@ -53,7 +53,13 @@
+ #define STACK_TOP_MAX		STACK_TOP
+ 
+ /*
+- * Kernel image size is limited to 512 MB (see in arch/x86/kernel/head_32.S)
++ * In spite of the name, KERNEL_IMAGE_SIZE is a limit on the maximum virtual
++ * address for the kernel image, rather than the limit on the size itself. On
++ * 32-bit, this is not a strict limit, but this value is used to limit the
++ * link-time virtual address range of the kernel, and by KASLR to limit the
++ * randomized address from which the kernel is executed. A relocatable kernel
++ * can be loaded somewhat higher than KERNEL_IMAGE_SIZE as long as enough space
++ * remains for the vmalloc area.
+  */
+ #define KERNEL_IMAGE_SIZE	(512 * 1024 * 1024)
+ 
+diff --git a/arch/x86/include/asm/page_64_types.h b/arch/x86/include/asm/page_64_types.h
+index 3f49dac03617..645bd1d0ee07 100644
+--- a/arch/x86/include/asm/page_64_types.h
++++ b/arch/x86/include/asm/page_64_types.h
+@@ -98,8 +98,10 @@
+ #define STACK_TOP_MAX		TASK_SIZE_MAX
+ 
+ /*
+- * Maximum kernel image size is limited to 1 GiB, due to the fixmap living
+- * in the next 1 GiB (see level2_kernel_pgt in arch/x86/kernel/head_64.S).
++ * In spite of the name, KERNEL_IMAGE_SIZE is a limit on the maximum virtual
++ * address for the kernel image, rather than the limit on the size itself.
++ * This can be at most 1 GiB, due to the fixmap living in the next 1 GiB (see
++ * level2_kernel_pgt in arch/x86/kernel/head_64.S).
+  *
+  * On KASLR use 1 GiB by default, leaving 1 GiB for modules once the
+  * page tables are fully set up.
+diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h
+index d7acae4120d5..7c9c968a42ef 100644
+--- a/arch/x86/include/asm/pgtable_32.h
++++ b/arch/x86/include/asm/pgtable_32.h
+@@ -57,19 +57,13 @@ do {						\
+ #endif
+ 
+ /*
+- * This is how much memory in addition to the memory covered up to
+- * and including _end we need mapped initially.
+- * We need:
+- *     (KERNEL_IMAGE_SIZE/4096) / 1024 pages (worst case, non PAE)
+- *     (KERNEL_IMAGE_SIZE/4096) / 512 + 4 pages (worst case for PAE)
++ * This is used to calculate the .brk reservation for initial pagetables.
++ * Enough space is reserved to allocate pagetables sufficient to cover all
++ * of LOWMEM_PAGES, which is an upper bound on the size of the direct map of
++ * lowmem.
+  *
+- * Modulo rounding, each megabyte assigned here requires a kilobyte of
+- * memory, which is currently unreclaimed.
+- *
+- * This should be a multiple of a page.
+- *
+- * KERNEL_IMAGE_SIZE should be greater than pa(_end)
+- * and small than max_low_pfn, otherwise will waste some page table entries
++ * With PAE paging (PTRS_PER_PMD > 1), we allocate PTRS_PER_PGD == 4 pages for
++ * the PMD's in addition to the pages required for the last level pagetables.
+  */
+ #if PTRS_PER_PMD > 1
+ #define PAGE_TABLE_SIZE(pages) (((pages) / PTRS_PER_PMD) + PTRS_PER_PGD)
+diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
+index 7eb2a1c87969..d41fa5bb77fe 100644
+--- a/arch/x86/kernel/head_64.S
++++ b/arch/x86/kernel/head_64.S
+@@ -524,21 +524,19 @@ SYM_DATA_END(level3_kernel_pgt)
+ 
+ SYM_DATA_START_PAGE_ALIGNED(level2_kernel_pgt)
+ 	/*
+-	 * 512 MB kernel mapping. We spend a full page on this pagetable
+-	 * anyway.
++	 * Kernel high mapping.
+ 	 *
+-	 * The kernel code+data+bss must not be bigger than that.
++	 * The kernel code+data+bss must be located below KERNEL_IMAGE_SIZE in
++	 * virtual address space, which is 1 GiB if RANDOMIZE_BASE is enabled,
++	 * 512 MiB otherwise.
+ 	 *
+-	 * (NOTE: at +512MB starts the module area, see MODULES_VADDR.
+-	 *  If you want to increase this then increase MODULES_VADDR
+-	 *  too.)
++	 * (NOTE: after that starts the module area, see MODULES_VADDR.)
+ 	 *
+-	 *  This table is eventually used by the kernel during normal
+-	 *  runtime.  Care must be taken to clear out undesired bits
+-	 *  later, like _PAGE_RW or _PAGE_GLOBAL in some cases.
++	 * This table is eventually used by the kernel during normal runtime.
++	 * Care must be taken to clear out undesired bits later, like _PAGE_RW
++	 * or _PAGE_GLOBAL in some cases.
+ 	 */
+-	PMDS(0, __PAGE_KERNEL_LARGE_EXEC,
+-		KERNEL_IMAGE_SIZE/PMD_SIZE)
++	PMDS(0, __PAGE_KERNEL_LARGE_EXEC, KERNEL_IMAGE_SIZE/PMD_SIZE)
+ SYM_DATA_END(level2_kernel_pgt)
+ 
+ SYM_DATA_START_PAGE_ALIGNED(level2_fixmap_pgt)
+diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
+index bf9e0adb5b7e..efd9e9ea17f2 100644
+--- a/arch/x86/kernel/vmlinux.lds.S
++++ b/arch/x86/kernel/vmlinux.lds.S
+@@ -454,13 +454,13 @@ SECTIONS
+ 	ASSERT(SIZEOF(.rela.dyn) == 0, "Unexpected run-time relocations (.rela) detected!")
+ }
+ 
+-#ifdef CONFIG_X86_32
+ /*
+  * The ASSERT() sink to . is intentional, for binutils 2.14 compatibility:
+  */
+ . = ASSERT((_end - LOAD_OFFSET <= KERNEL_IMAGE_SIZE),
+ 	   "kernel image bigger than KERNEL_IMAGE_SIZE");
+-#else
++
++#ifdef CONFIG_X86_64
+ /*
+  * Per-cpu symbols which need to be offset from __per_cpu_load
+  * for the boot processor.
+@@ -470,18 +470,12 @@ INIT_PER_CPU(gdt_page);
+ INIT_PER_CPU(fixed_percpu_data);
+ INIT_PER_CPU(irq_stack_backing_store);
+ 
+-/*
+- * Build-time check on the image size:
+- */
+-. = ASSERT((_end - _text <= KERNEL_IMAGE_SIZE),
+-	   "kernel image bigger than KERNEL_IMAGE_SIZE");
+-
+ #ifdef CONFIG_SMP
+ . = ASSERT((fixed_percpu_data == 0),
+            "fixed_percpu_data is not at start of per-cpu area");
+ #endif
+ 
+-#endif /* CONFIG_X86_32 */
++#endif /* CONFIG_X86_64 */
+ 
+ #ifdef CONFIG_KEXEC_CORE
+ #include 

commit 1fcd009102ee02e217f2e7635ab65517d785da8e
+Author: Arvind Sankar 
+Date:   Tue Oct 27 19:06:48 2020 -0400
+
+    x86/mm/ident_map: Check for errors from ident_pud_init()
+    
+    Commit
+    
+      ea3b5e60ce80 ("x86/mm/ident_map: Add 5-level paging support")
+    
+    added ident_p4d_init() to support 5-level paging, but this function
+    doesn't check and return errors from ident_pud_init().
+    
+    For example, the decompressor stub uses this code to create an identity
+    mapping. If it runs out of pages while trying to allocate a PMD
+    pagetable, the error will be currently ignored.
+    
+    Fix this to propagate errors.
+    
+     [ bp: Space out statements for better readability. ]
+    
+    Fixes: ea3b5e60ce80 ("x86/mm/ident_map: Add 5-level paging support")
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Borislav Petkov 
+    Reviewed-by: Joerg Roedel 
+    Acked-by: Kirill A. Shutemov 
+    Link: https://lkml.kernel.org/r/20201027230648.1885111-1-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/mm/ident_map.c b/arch/x86/mm/ident_map.c
+index fe7a12599d8e..968d7005f4a7 100644
+--- a/arch/x86/mm/ident_map.c
++++ b/arch/x86/mm/ident_map.c
+@@ -62,6 +62,7 @@ static int ident_p4d_init(struct x86_mapping_info *info, p4d_t *p4d_page,
+ 			  unsigned long addr, unsigned long end)
+ {
+ 	unsigned long next;
++	int result;
+ 
+ 	for (; addr < end; addr = next) {
+ 		p4d_t *p4d = p4d_page + p4d_index(addr);
+@@ -73,13 +74,20 @@ static int ident_p4d_init(struct x86_mapping_info *info, p4d_t *p4d_page,
+ 
+ 		if (p4d_present(*p4d)) {
+ 			pud = pud_offset(p4d, 0);
+-			ident_pud_init(info, pud, addr, next);
++			result = ident_pud_init(info, pud, addr, next);
++			if (result)
++				return result;
++
+ 			continue;
+ 		}
+ 		pud = (pud_t *)info->alloc_pgt_page(info->context);
+ 		if (!pud)
+ 			return -ENOMEM;
+-		ident_pud_init(info, pud, addr, next);
++
++		result = ident_pud_init(info, pud, addr, next);
++		if (result)
++			return result;
++
+ 		set_p4d(p4d, __p4d(__pa(pud) | info->kernpg_flag));
+ 	}
+ 

commit 688eb28211abdf82a3f51e8997f1c8137947227d
+Author: Arvind Sankar 
+Date:   Sun Oct 11 10:20:12 2020 -0400
+
+    efi/x86: Only copy the compressed kernel image in efi_relocate_kernel()
+    
+    The image_size argument to efi_relocate_kernel() is currently specified
+    as init_size, but this is unnecessarily large. The compressed kernel is
+    much smaller, in fact, its image only extends up to the start of _bss,
+    since at this point, the .bss section is still uninitialized.
+    
+    Depending on compression level, this can reduce the amount of data
+    copied by 4-5x.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20201011142012.96493-1-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
+index 3672539cb96e..f14c4ff5839f 100644
+--- a/drivers/firmware/efi/libstub/x86-stub.c
++++ b/drivers/firmware/efi/libstub/x86-stub.c
+@@ -715,8 +715,11 @@ unsigned long efi_main(efi_handle_t handle,
+ 	    (IS_ENABLED(CONFIG_X86_32) && buffer_end > KERNEL_IMAGE_SIZE)    ||
+ 	    (IS_ENABLED(CONFIG_X86_64) && buffer_end > MAXMEM_X86_64_4LEVEL) ||
+ 	    (image_offset == 0)) {
++		extern char _bss[];
++
+ 		status = efi_relocate_kernel(&bzimage_addr,
+-					     hdr->init_size, hdr->init_size,
++					     (unsigned long)_bss - bzimage_addr,
++					     hdr->init_size,
+ 					     hdr->pref_address,
+ 					     hdr->kernel_alignment,
+ 					     LOAD_PHYSICAL_ADDR);

commit b17a45b6e53f6613118b2e5cfc4a992cc50deb2c
+Author: Arvind Sankar 
+Date:   Fri Oct 16 16:04:01 2020 -0400
+
+    x86/boot/64: Explicitly map boot_params and command line
+    
+    Commits
+    
+      ca0e22d4f011 ("x86/boot/compressed/64: Always switch to own page table")
+      8570978ea030 ("x86/boot/compressed/64: Don't pre-map memory in KASLR code")
+    
+    set up a new page table in the decompressor stub, but without explicit
+    mappings for boot_params and the kernel command line, relying on the #PF
+    handler instead.
+    
+    This is fragile, as boot_params and the command line mappings are
+    required for the main kernel. If EARLY_PRINTK and RANDOMIZE_BASE are
+    disabled, a QEMU/OVMF boot never accesses the command line in the
+    decompressor stub, and so it never gets mapped. The main kernel accesses
+    it from the identity mapping if AMD_MEM_ENCRYPT is enabled, and will
+    crash.
+    
+    Fix this by adding back the explicit mapping of boot_params and the
+    command line.
+    
+    Note: the changes also removed the explicit mapping of the main kernel,
+    with the result that .bss and .brk may not be in the identity mapping,
+    but those don't get accessed by the main kernel before it switches to
+    its own page tables.
+    
+     [ bp: Pass boot_params with a MOV %rsp... instead of PUSH/POP. Use
+       block formatting for the comment. ]
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Borislav Petkov 
+    Reviewed-by: Joerg Roedel 
+    Link: https://lkml.kernel.org/r/20201016200404.1615994-1-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index 1c80f1738fd9..017de6cc87dc 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -544,6 +544,9 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
+ 	pushq	%rsi
+ 	call	set_sev_encryption_mask
+ 	call	load_stage2_idt
++
++	/* Pass boot_params to initialize_identity_maps() */
++	movq	(%rsp), %rdi
+ 	call	initialize_identity_maps
+ 	popq	%rsi
+ 
+diff --git a/arch/x86/boot/compressed/ident_map_64.c b/arch/x86/boot/compressed/ident_map_64.c
+index c6f7aef7e85a..a5e5db6ada3c 100644
+--- a/arch/x86/boot/compressed/ident_map_64.c
++++ b/arch/x86/boot/compressed/ident_map_64.c
+@@ -33,6 +33,12 @@
+ #define __PAGE_OFFSET __PAGE_OFFSET_BASE
+ #include "../../mm/ident_map.c"
+ 
++#define _SETUP
++#include 	/* For COMMAND_LINE_SIZE */
++#undef _SETUP
++
++extern unsigned long get_cmd_line_ptr(void);
++
+ /* Used by PAGE_KERN* macros: */
+ pteval_t __default_kernel_pte_mask __read_mostly = ~0;
+ 
+@@ -101,8 +107,10 @@ static void add_identity_map(unsigned long start, unsigned long end)
+ }
+ 
+ /* Locates and clears a region for a new top level page table. */
+-void initialize_identity_maps(void)
++void initialize_identity_maps(void *rmode)
+ {
++	unsigned long cmdline;
++
+ 	/* Exclude the encryption mask from __PHYSICAL_MASK */
+ 	physical_mask &= ~sme_me_mask;
+ 
+@@ -143,10 +151,19 @@ void initialize_identity_maps(void)
+ 	}
+ 
+ 	/*
+-	 * New page-table is set up - map the kernel image and load it
+-	 * into cr3.
++	 * New page-table is set up - map the kernel image, boot_params and the
++	 * command line. The uncompressed kernel requires boot_params and the
++	 * command line to be mapped in the identity mapping. Map them
++	 * explicitly here in case the compressed kernel does not touch them,
++	 * or does not touch all the pages covering them.
+ 	 */
+ 	add_identity_map((unsigned long)_head, (unsigned long)_end);
++	boot_params = rmode;
++	add_identity_map((unsigned long)boot_params, (unsigned long)(boot_params + 1));
++	cmdline = get_cmd_line_ptr();
++	add_identity_map(cmdline, cmdline + COMMAND_LINE_SIZE);
++
++	/* Load the new page-table. */
+ 	write_cr3(top_level_pgt);
+ }
+ 

commit 103a4908ad4da9decdf9bc7216ec5a4861edf703
+Author: Arvind Sankar 
+Date:   Thu Oct 8 15:16:23 2020 -0400
+
+    x86/head/64: Disable stack protection for head$(BITS).o
+    
+    On 64-bit, the startup_64_setup_env() function added in
+    
+      866b556efa12 ("x86/head/64: Install startup GDT")
+    
+    has stack protection enabled because of set_bringup_idt_handler().
+    This happens when CONFIG_STACKPROTECTOR_STRONG is enabled. It
+    also currently needs CONFIG_AMD_MEM_ENCRYPT enabled because then
+    set_bringup_idt_handler() is not an empty stub but that might change in
+    the future, when the other vendor adds their similar technology.
+    
+    At this point, %gs is not yet initialized, and this doesn't cause a
+    crash only because the #PF handler from the decompressor stub is still
+    installed and handles the page fault.
+    
+    Disable stack protection for the whole file, and do it on 32-bit as
+    well to avoid surprises.
+    
+     [ bp: Extend commit message with the exact explanation how it happens. ]
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Borislav Petkov 
+    Reviewed-by: Joerg Roedel 
+    Link: https://lkml.kernel.org/r/20201008191623.2881677-6-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
+index 04ceea8f4a89..68608bd892c0 100644
+--- a/arch/x86/kernel/Makefile
++++ b/arch/x86/kernel/Makefile
+@@ -47,6 +47,8 @@ endif
+ # non-deterministic coverage.
+ KCOV_INSTRUMENT		:= n
+ 
++CFLAGS_head$(BITS).o	+= -fno-stack-protector
++
+ CFLAGS_irq.o := -I $(srctree)/$(src)/../include/asm/trace
+ 
+ obj-y			:= process_$(BITS).o signal.o

commit e5ceb9a02402b984feecb95a82239be151c9f4e2
+Author: Arvind Sankar 
+Date:   Sat Oct 10 15:11:10 2020 -0400
+
+    x86/boot/64: Initialize 5-level paging variables earlier
+    
+    Commit
+    
+      ca0e22d4f011 ("x86/boot/compressed/64: Always switch to own page table")
+    
+    started using a new set of pagetables even without KASLR.
+    
+    After that commit, initialize_identity_maps() is called before the
+    5-level paging variables are setup in choose_random_location(), which
+    will not work if 5-level paging is actually enabled.
+    
+    Fix this by moving the initialization of __pgtable_l5_enabled,
+    pgdir_shift and ptrs_per_p4d into cleanup_trampoline(), which is called
+    immediately after the finalization of whether the kernel is executing
+    with 4- or 5-level paging. This will be earlier than anything that might
+    require those variables, and keeps the 4- vs 5-level paging code all in
+    one place.
+    
+    Fixes: ca0e22d4f011 ("x86/boot/compressed/64: Always switch to own page table")
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Borislav Petkov 
+    Reviewed-by: Joerg Roedel 
+    Tested-by: Joerg Roedel 
+    Tested-by: Kirill A. Shutemov 
+    Link: https://lkml.kernel.org/r/20201010191110.4060905-1-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/ident_map_64.c b/arch/x86/boot/compressed/ident_map_64.c
+index 063a60edcf99..c6f7aef7e85a 100644
+--- a/arch/x86/boot/compressed/ident_map_64.c
++++ b/arch/x86/boot/compressed/ident_map_64.c
+@@ -33,12 +33,6 @@
+ #define __PAGE_OFFSET __PAGE_OFFSET_BASE
+ #include "../../mm/ident_map.c"
+ 
+-#ifdef CONFIG_X86_5LEVEL
+-unsigned int __pgtable_l5_enabled;
+-unsigned int pgdir_shift = 39;
+-unsigned int ptrs_per_p4d = 1;
+-#endif
+-
+ /* Used by PAGE_KERN* macros: */
+ pteval_t __default_kernel_pte_mask __read_mostly = ~0;
+ 
+diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
+index b59547ce5b19..b92fffbe761f 100644
+--- a/arch/x86/boot/compressed/kaslr.c
++++ b/arch/x86/boot/compressed/kaslr.c
+@@ -840,14 +840,6 @@ void choose_random_location(unsigned long input,
+ 		return;
+ 	}
+ 
+-#ifdef CONFIG_X86_5LEVEL
+-	if (__read_cr4() & X86_CR4_LA57) {
+-		__pgtable_l5_enabled = 1;
+-		pgdir_shift = 48;
+-		ptrs_per_p4d = 512;
+-	}
+-#endif
+-
+ 	boot_params->hdr.loadflags |= KASLR_FLAG;
+ 
+ 	if (IS_ENABLED(CONFIG_X86_32))
+diff --git a/arch/x86/boot/compressed/pgtable_64.c b/arch/x86/boot/compressed/pgtable_64.c
+index 7d0394f4ebf9..5def1674d6f1 100644
+--- a/arch/x86/boot/compressed/pgtable_64.c
++++ b/arch/x86/boot/compressed/pgtable_64.c
+@@ -8,6 +8,13 @@
+ #define BIOS_START_MIN		0x20000U	/* 128K, less than this is insane */
+ #define BIOS_START_MAX		0x9f000U	/* 640K, absolute maximum */
+ 
++#ifdef CONFIG_X86_5LEVEL
++/* __pgtable_l5_enabled needs to be in .data to avoid being cleared along with .bss */
++unsigned int __section(.data) __pgtable_l5_enabled;
++unsigned int __section(.data) pgdir_shift = 39;
++unsigned int __section(.data) ptrs_per_p4d = 1;
++#endif
++
+ struct paging_config {
+ 	unsigned long trampoline_start;
+ 	unsigned long l5_required;
+@@ -198,4 +205,13 @@ void cleanup_trampoline(void *pgtable)
+ 
+ 	/* Restore trampoline memory */
+ 	memcpy(trampoline_32bit, trampoline_save, TRAMPOLINE_32BIT_SIZE);
++
++	/* Initialize variables for 5-level paging */
++#ifdef CONFIG_X86_5LEVEL
++	if (__read_cr4() & X86_CR4_LA57) {
++		__pgtable_l5_enabled = 1;
++		pgdir_shift = 48;
++		ptrs_per_p4d = 512;
++	}
++#endif
+ }

commit aa5cacdc29d76a005cbbee018a47faa6e724dd2d
+Author: Arvind Sankar 
+Date:   Wed Sep 2 19:21:52 2020 -0400
+
+    x86/asm: Replace __force_order with a memory clobber
+    
+    The CRn accessor functions use __force_order as a dummy operand to
+    prevent the compiler from reordering CRn reads/writes with respect to
+    each other.
+    
+    The fact that the asm is volatile should be enough to prevent this:
+    volatile asm statements should be executed in program order. However GCC
+    4.9.x and 5.x have a bug that might result in reordering. This was fixed
+    in 8.1, 7.3 and 6.5. Versions prior to these, including 5.x and 4.9.x,
+    may reorder volatile asm statements with respect to each other.
+    
+    There are some issues with __force_order as implemented:
+    - It is used only as an input operand for the write functions, and hence
+      doesn't do anything additional to prevent reordering writes.
+    - It allows memory accesses to be cached/reordered across write
+      functions, but CRn writes affect the semantics of memory accesses, so
+      this could be dangerous.
+    - __force_order is not actually defined in the kernel proper, but the
+      LLVM toolchain can in some cases require a definition: LLVM (as well
+      as GCC 4.9) requires it for PIE code, which is why the compressed
+      kernel has a definition, but also the clang integrated assembler may
+      consider the address of __force_order to be significant, resulting in
+      a reference that requires a definition.
+    
+    Fix this by:
+    - Using a memory clobber for the write functions to additionally prevent
+      caching/reordering memory accesses across CRn writes.
+    - Using a dummy input operand with an arbitrary constant address for the
+      read functions, instead of a global variable. This will prevent reads
+      from being reordered across writes, while allowing memory loads to be
+      cached/reordered across CRn reads, which should be safe.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Borislav Petkov 
+    Reviewed-by: Kees Cook 
+    Reviewed-by: Miguel Ojeda 
+    Tested-by: Nathan Chancellor 
+    Tested-by: Sedat Dilek 
+    Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82602
+    Link: https://lore.kernel.org/lkml/20200527135329.1172644-1-arnd@arndb.de/
+    Link: https://lkml.kernel.org/r/20200902232152.3709896-1-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/pgtable_64.c b/arch/x86/boot/compressed/pgtable_64.c
+index c8862696a47b..7d0394f4ebf9 100644
+--- a/arch/x86/boot/compressed/pgtable_64.c
++++ b/arch/x86/boot/compressed/pgtable_64.c
+@@ -5,15 +5,6 @@
+ #include "pgtable.h"
+ #include "../string.h"
+ 
+-/*
+- * __force_order is used by special_insns.h asm code to force instruction
+- * serialization.
+- *
+- * It is not referenced from the code, but GCC < 5 with -fPIE would fail
+- * due to an undefined symbol. Define it to make these ancient GCCs work.
+- */
+-unsigned long __force_order;
+-
+ #define BIOS_START_MIN		0x20000U	/* 128K, less than this is insane */
+ #define BIOS_START_MAX		0x9f000U	/* 640K, absolute maximum */
+ 
+diff --git a/arch/x86/include/asm/special_insns.h b/arch/x86/include/asm/special_insns.h
+index 59a3e13204c3..d6e3bb9363d2 100644
+--- a/arch/x86/include/asm/special_insns.h
++++ b/arch/x86/include/asm/special_insns.h
+@@ -11,45 +11,47 @@
+ #include 
+ 
+ /*
+- * Volatile isn't enough to prevent the compiler from reordering the
+- * read/write functions for the control registers and messing everything up.
+- * A memory clobber would solve the problem, but would prevent reordering of
+- * all loads stores around it, which can hurt performance. Solution is to
+- * use a variable and mimic reads and writes to it to enforce serialization
++ * The compiler should not reorder volatile asm statements with respect to each
++ * other: they should execute in program order. However GCC 4.9.x and 5.x have
++ * a bug (which was fixed in 8.1, 7.3 and 6.5) where they might reorder
++ * volatile asm. The write functions are not affected since they have memory
++ * clobbers preventing reordering. To prevent reads from being reordered with
++ * respect to writes, use a dummy memory operand.
+  */
+-extern unsigned long __force_order;
++
++#define __FORCE_ORDER "m"(*(unsigned int *)0x1000UL)
+ 
+ void native_write_cr0(unsigned long val);
+ 
+ static inline unsigned long native_read_cr0(void)
+ {
+ 	unsigned long val;
+-	asm volatile("mov %%cr0,%0\n\t" : "=r" (val), "=m" (__force_order));
++	asm volatile("mov %%cr0,%0\n\t" : "=r" (val) : __FORCE_ORDER);
+ 	return val;
+ }
+ 
+ static __always_inline unsigned long native_read_cr2(void)
+ {
+ 	unsigned long val;
+-	asm volatile("mov %%cr2,%0\n\t" : "=r" (val), "=m" (__force_order));
++	asm volatile("mov %%cr2,%0\n\t" : "=r" (val) : __FORCE_ORDER);
+ 	return val;
+ }
+ 
+ static __always_inline void native_write_cr2(unsigned long val)
+ {
+-	asm volatile("mov %0,%%cr2": : "r" (val), "m" (__force_order));
++	asm volatile("mov %0,%%cr2": : "r" (val) : "memory");
+ }
+ 
+ static inline unsigned long __native_read_cr3(void)
+ {
+ 	unsigned long val;
+-	asm volatile("mov %%cr3,%0\n\t" : "=r" (val), "=m" (__force_order));
++	asm volatile("mov %%cr3,%0\n\t" : "=r" (val) : __FORCE_ORDER);
+ 	return val;
+ }
+ 
+ static inline void native_write_cr3(unsigned long val)
+ {
+-	asm volatile("mov %0,%%cr3": : "r" (val), "m" (__force_order));
++	asm volatile("mov %0,%%cr3": : "r" (val) : "memory");
+ }
+ 
+ static inline unsigned long native_read_cr4(void)
+@@ -64,10 +66,10 @@ static inline unsigned long native_read_cr4(void)
+ 	asm volatile("1: mov %%cr4, %0\n"
+ 		     "2:\n"
+ 		     _ASM_EXTABLE(1b, 2b)
+-		     : "=r" (val), "=m" (__force_order) : "0" (0));
++		     : "=r" (val) : "0" (0), __FORCE_ORDER);
+ #else
+ 	/* CR4 always exists on x86_64. */
+-	asm volatile("mov %%cr4,%0\n\t" : "=r" (val), "=m" (__force_order));
++	asm volatile("mov %%cr4,%0\n\t" : "=r" (val) : __FORCE_ORDER);
+ #endif
+ 	return val;
+ }
+diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
+index c5d6f17d9b9d..178499f90366 100644
+--- a/arch/x86/kernel/cpu/common.c
++++ b/arch/x86/kernel/cpu/common.c
+@@ -359,7 +359,7 @@ void native_write_cr0(unsigned long val)
+ 	unsigned long bits_missing = 0;
+ 
+ set_register:
+-	asm volatile("mov %0,%%cr0": "+r" (val), "+m" (__force_order));
++	asm volatile("mov %0,%%cr0": "+r" (val) : : "memory");
+ 
+ 	if (static_branch_likely(&cr_pinning)) {
+ 		if (unlikely((val & X86_CR0_WP) != X86_CR0_WP)) {
+@@ -378,7 +378,7 @@ void native_write_cr4(unsigned long val)
+ 	unsigned long bits_changed = 0;
+ 
+ set_register:
+-	asm volatile("mov %0,%%cr4": "+r" (val), "+m" (cr4_pinned_bits));
++	asm volatile("mov %0,%%cr4": "+r" (val) : : "memory");
+ 
+ 	if (static_branch_likely(&cr_pinning)) {
+ 		if (unlikely((val & cr4_pinned_mask) != cr4_pinned_bits)) {

commit 4a568ce29d3f48df95919f82a80e4b9be7ea0dc1
+Author: Arvind Sankar 
+Date:   Mon Sep 14 17:35:35 2020 -0400
+
+    efi/x86: Add a quirk to support command line arguments on Dell EFI firmware
+    
+    At least some versions of Dell EFI firmware pass the entire
+    EFI_LOAD_OPTION descriptor, rather than just the OptionalData part, to
+    the loaded image. This was verified with firmware revision 2.15.0 on a
+    Dell Precision T3620 by Jacobo Pantoja.
+    
+    To handle this, add a quirk to check if the options look like a valid
+    EFI_LOAD_OPTION descriptor, and if so, use the OptionalData part as the
+    command line.
+    
+    Signed-off-by: Arvind Sankar 
+    Reported-by: Jacobo Pantoja 
+    Link: https://lore.kernel.org/linux-efi/20200907170021.GA2284449@rani.riverdale.lan/
+    Link: https://lore.kernel.org/r/20200914213535.933454-2-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
+index 6bca70bbb43d..4dbf04cc8930 100644
+--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
++++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
+@@ -230,6 +230,102 @@ efi_status_t efi_parse_options(char const *cmdline)
+ 	return EFI_SUCCESS;
+ }
+ 
++/*
++ * The EFI_LOAD_OPTION descriptor has the following layout:
++ *	u32 Attributes;
++ *	u16 FilePathListLength;
++ *	u16 Description[];
++ *	efi_device_path_protocol_t FilePathList[];
++ *	u8 OptionalData[];
++ *
++ * This function validates and unpacks the variable-size data fields.
++ */
++static
++bool efi_load_option_unpack(efi_load_option_unpacked_t *dest,
++			    const efi_load_option_t *src, size_t size)
++{
++	const void *pos;
++	u16 c;
++	efi_device_path_protocol_t header;
++	const efi_char16_t *description;
++	const efi_device_path_protocol_t *file_path_list;
++
++	if (size < offsetof(efi_load_option_t, variable_data))
++		return false;
++	pos = src->variable_data;
++	size -= offsetof(efi_load_option_t, variable_data);
++
++	if ((src->attributes & ~EFI_LOAD_OPTION_MASK) != 0)
++		return false;
++
++	/* Scan description. */
++	description = pos;
++	do {
++		if (size < sizeof(c))
++			return false;
++		c = *(const u16 *)pos;
++		pos += sizeof(c);
++		size -= sizeof(c);
++	} while (c != L'\0');
++
++	/* Scan file_path_list. */
++	file_path_list = pos;
++	do {
++		if (size < sizeof(header))
++			return false;
++		header = *(const efi_device_path_protocol_t *)pos;
++		if (header.length < sizeof(header))
++			return false;
++		if (size < header.length)
++			return false;
++		pos += header.length;
++		size -= header.length;
++	} while ((header.type != EFI_DEV_END_PATH && header.type != EFI_DEV_END_PATH2) ||
++		 (header.sub_type != EFI_DEV_END_ENTIRE));
++	if (pos != (const void *)file_path_list + src->file_path_list_length)
++		return false;
++
++	dest->attributes = src->attributes;
++	dest->file_path_list_length = src->file_path_list_length;
++	dest->description = description;
++	dest->file_path_list = file_path_list;
++	dest->optional_data_size = size;
++	dest->optional_data = size ? pos : NULL;
++
++	return true;
++}
++
++/*
++ * At least some versions of Dell firmware pass the entire contents of the
++ * Boot#### variable, i.e. the EFI_LOAD_OPTION descriptor, rather than just the
++ * OptionalData field.
++ *
++ * Detect this case and extract OptionalData.
++ */
++void efi_apply_loadoptions_quirk(const void **load_options, int *load_options_size)
++{
++	const efi_load_option_t *load_option = *load_options;
++	efi_load_option_unpacked_t load_option_unpacked;
++
++	if (!IS_ENABLED(CONFIG_X86))
++		return;
++	if (!load_option)
++		return;
++	if (*load_options_size < sizeof(*load_option))
++		return;
++	if ((load_option->attributes & ~EFI_LOAD_OPTION_BOOT_MASK) != 0)
++		return;
++
++	if (!efi_load_option_unpack(&load_option_unpacked, load_option, *load_options_size))
++		return;
++
++	efi_warn_once(FW_BUG "LoadOptions is an EFI_LOAD_OPTION descriptor\n");
++	efi_warn_once(FW_BUG "Using OptionalData as a workaround\n");
++
++	*load_options = load_option_unpacked.optional_data;
++	*load_options_size = load_option_unpacked.optional_data_size;
++}
++
+ /*
+  * Convert the unicode UEFI command line to ASCII to pass to kernel.
+  * Size of memory allocated return in *cmd_line_len.
+@@ -239,12 +335,15 @@ char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len)
+ {
+ 	const u16 *s2;
+ 	unsigned long cmdline_addr = 0;
+-	int options_chars = efi_table_attr(image, load_options_size) / 2;
++	int options_chars = efi_table_attr(image, load_options_size);
+ 	const u16 *options = efi_table_attr(image, load_options);
+ 	int options_bytes = 0, safe_options_bytes = 0;  /* UTF-8 bytes */
+ 	bool in_quote = false;
+ 	efi_status_t status;
+ 
++	efi_apply_loadoptions_quirk((const void **)&options, &options_chars);
++	options_chars /= sizeof(*options);
++
+ 	if (options) {
+ 		s2 = options;
+ 		while (options_bytes < COMMAND_LINE_SIZE && options_chars--) {
+diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
+index 9ea87a28d303..2d7abcd99de9 100644
+--- a/drivers/firmware/efi/libstub/efistub.h
++++ b/drivers/firmware/efi/libstub/efistub.h
+@@ -708,6 +708,35 @@ union efi_load_file_protocol {
+ 	} mixed_mode;
+ };
+ 
++typedef struct {
++	u32 attributes;
++	u16 file_path_list_length;
++	u8 variable_data[];
++	// efi_char16_t description[];
++	// efi_device_path_protocol_t file_path_list[];
++	// u8 optional_data[];
++} __packed efi_load_option_t;
++
++#define EFI_LOAD_OPTION_ACTIVE		0x0001U
++#define EFI_LOAD_OPTION_FORCE_RECONNECT	0x0002U
++#define EFI_LOAD_OPTION_HIDDEN		0x0008U
++#define EFI_LOAD_OPTION_CATEGORY	0x1f00U
++#define   EFI_LOAD_OPTION_CATEGORY_BOOT	0x0000U
++#define   EFI_LOAD_OPTION_CATEGORY_APP	0x0100U
++
++#define EFI_LOAD_OPTION_BOOT_MASK \
++	(EFI_LOAD_OPTION_ACTIVE|EFI_LOAD_OPTION_HIDDEN|EFI_LOAD_OPTION_CATEGORY)
++#define EFI_LOAD_OPTION_MASK (EFI_LOAD_OPTION_FORCE_RECONNECT|EFI_LOAD_OPTION_BOOT_MASK)
++
++typedef struct {
++	u32 attributes;
++	u16 file_path_list_length;
++	const efi_char16_t *description;
++	const efi_device_path_protocol_t *file_path_list;
++	size_t optional_data_size;
++	const void *optional_data;
++} efi_load_option_unpacked_t;
++
+ void efi_pci_disable_bridge_busmaster(void);
+ 
+ typedef efi_status_t (*efi_exit_boot_map_processing)(
+@@ -750,6 +779,8 @@ __printf(1, 2) int efi_printk(char const *fmt, ...);
+ 
+ void efi_free(unsigned long size, unsigned long addr);
+ 
++void efi_apply_loadoptions_quirk(const void **load_options, int *load_options_size);
++
+ char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len);
+ 
+ efi_status_t efi_get_memory_map(struct efi_boot_memmap *map);
+diff --git a/drivers/firmware/efi/libstub/file.c b/drivers/firmware/efi/libstub/file.c
+index 630caa6b1f4c..4e81c6077188 100644
+--- a/drivers/firmware/efi/libstub/file.c
++++ b/drivers/firmware/efi/libstub/file.c
+@@ -136,7 +136,7 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
+ 				  unsigned long *load_size)
+ {
+ 	const efi_char16_t *cmdline = image->load_options;
+-	int cmdline_len = image->load_options_size / 2;
++	int cmdline_len = image->load_options_size;
+ 	unsigned long efi_chunk_size = ULONG_MAX;
+ 	efi_file_protocol_t *volume = NULL;
+ 	efi_file_protocol_t *file;
+@@ -148,6 +148,9 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
+ 	if (!load_addr || !load_size)
+ 		return EFI_INVALID_PARAMETER;
+ 
++	efi_apply_loadoptions_quirk((const void **)&cmdline, &cmdline_len);
++	cmdline_len /= sizeof(*cmdline);
++
+ 	if (IS_ENABLED(CONFIG_X86) && !efi_nochunk)
+ 		efi_chunk_size = EFI_READ_CHUNK_SIZE;
+ 

commit c1df5e0c5796f775e60d1aec0b52f6d03d66ccd4
+Author: Arvind Sankar 
+Date:   Mon Sep 14 17:35:34 2020 -0400
+
+    efi/libstub: Add efi_warn and *_once logging helpers
+    
+    Add an efi_warn logging helper for warnings, and implement an analog of
+    printk_once for once-only logging.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200914213535.933454-1-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
+index 27cdcb11714d..9ea87a28d303 100644
+--- a/drivers/firmware/efi/libstub/efistub.h
++++ b/drivers/firmware/efi/libstub/efistub.h
+@@ -52,11 +52,34 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
+ 
+ #define efi_info(fmt, ...) \
+ 	efi_printk(KERN_INFO fmt, ##__VA_ARGS__)
++#define efi_warn(fmt, ...) \
++	efi_printk(KERN_WARNING "WARNING: " fmt, ##__VA_ARGS__)
+ #define efi_err(fmt, ...) \
+ 	efi_printk(KERN_ERR "ERROR: " fmt, ##__VA_ARGS__)
+ #define efi_debug(fmt, ...) \
+ 	efi_printk(KERN_DEBUG "DEBUG: " fmt, ##__VA_ARGS__)
+ 
++#define efi_printk_once(fmt, ...) 		\
++({						\
++	static bool __print_once;		\
++	bool __ret_print_once = !__print_once;	\
++						\
++	if (!__print_once) {			\
++		__print_once = true;		\
++		efi_printk(fmt, ##__VA_ARGS__);	\
++	}					\
++	__ret_print_once;			\
++})
++
++#define efi_info_once(fmt, ...) \
++	efi_printk_once(KERN_INFO fmt, ##__VA_ARGS__)
++#define efi_warn_once(fmt, ...) \
++	efi_printk_once(KERN_WARNING "WARNING: " fmt, ##__VA_ARGS__)
++#define efi_err_once(fmt, ...) \
++	efi_printk_once(KERN_ERR "ERROR: " fmt, ##__VA_ARGS__)
++#define efi_debug_once(fmt, ...) \
++	efi_printk_once(KERN_DEBUG "DEBUG: " fmt, ##__VA_ARGS__)
++
+ /* Helper macros for the usual case of using simple C variables: */
+ #ifndef fdt_setprop_inplace_var
+ #define fdt_setprop_inplace_var(fdt, node_offset, name, var) \

commit 09e43968db40c33a73e9ddbfd937f46d5c334924
+Author: Arvind Sankar 
+Date:   Tue Aug 11 20:43:08 2020 -0400
+
+    x86/boot/compressed: Disable relocation relaxation
+    
+    The x86-64 psABI [0] specifies special relocation types
+    (R_X86_64_[REX_]GOTPCRELX) for indirection through the Global Offset
+    Table, semantically equivalent to R_X86_64_GOTPCREL, which the linker
+    can take advantage of for optimization (relaxation) at link time. This
+    is supported by LLD and binutils versions 2.26 onwards.
+    
+    The compressed kernel is position-independent code, however, when using
+    LLD or binutils versions before 2.27, it must be linked without the -pie
+    option. In this case, the linker may optimize certain instructions into
+    a non-position-independent form, by converting foo@GOTPCREL(%rip) to $foo.
+    
+    This potential issue has been present with LLD and binutils-2.26 for a
+    long time, but it has never manifested itself before now:
+    
+    - LLD and binutils-2.26 only relax
+            movq    foo@GOTPCREL(%rip), %reg
+      to
+            leaq    foo(%rip), %reg
+      which is still position-independent, rather than
+            mov     $foo, %reg
+      which is permitted by the psABI when -pie is not enabled.
+    
+    - GCC happens to only generate GOTPCREL relocations on mov instructions.
+    
+    - CLang does generate GOTPCREL relocations on non-mov instructions, but
+      when building the compressed kernel, it uses its integrated assembler
+      (due to the redefinition of KBUILD_CFLAGS dropping -no-integrated-as),
+      which has so far defaulted to not generating the GOTPCRELX
+      relocations.
+    
+    Nick Desaulniers reports [1,2]:
+    
+      "A recent change [3] to a default value of configuration variable
+       (ENABLE_X86_RELAX_RELOCATIONS OFF -> ON) in LLVM now causes Clang's
+       integrated assembler to emit R_X86_64_GOTPCRELX/R_X86_64_REX_GOTPCRELX
+       relocations. LLD will relax instructions with these relocations based
+       on whether the image is being linked as position independent or not.
+       When not, then LLD will relax these instructions to use absolute
+       addressing mode (R_RELAX_GOT_PC_NOPIC). This causes kernels built with
+       Clang and linked with LLD to fail to boot."
+    
+    Patch series [4] is a solution to allow the compressed kernel to be
+    linked with -pie unconditionally, but even if merged is unlikely to be
+    backported. As a simple solution that can be applied to stable as well,
+    prevent the assembler from generating the relaxed relocation types using
+    the -mrelax-relocations=no option. For ease of backporting, do this
+    unconditionally.
+    
+    [0] https://gitlab.com/x86-psABIs/x86-64-ABI/-/blob/master/x86-64-ABI/linker-optimization.tex#L65
+    [1] https://lore.kernel.org/lkml/20200807194100.3570838-1-ndesaulniers@google.com/
+    [2] https://github.com/ClangBuiltLinux/linux/issues/1121
+    [3] https://reviews.llvm.org/rGc41a18cf61790fc898dcda1055c3efbf442c14c0
+    [4] https://lore.kernel.org/lkml/20200731202738.2577854-1-nivedita@alum.mit.edu/
+    
+    Reported-by: Nick Desaulniers 
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ingo Molnar 
+    Tested-by: Nick Desaulniers 
+    Tested-by: Sedat Dilek 
+    Acked-by: Ard Biesheuvel 
+    Reviewed-by: Nick Desaulniers 
+    Cc: stable@vger.kernel.org
+    Link: https://lore.kernel.org/r/20200812004308.1448603-1-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
+index 3962f592633d..ff7894f39e0e 100644
+--- a/arch/x86/boot/compressed/Makefile
++++ b/arch/x86/boot/compressed/Makefile
+@@ -43,6 +43,8 @@ KBUILD_CFLAGS += -Wno-pointer-sign
+ KBUILD_CFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=)
+ KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
+ KBUILD_CFLAGS += -D__DISABLE_EXPORTS
++# Disable relocation relaxation in case the link is not PIE.
++KBUILD_CFLAGS += $(call as-option,-Wa$(comma)-mrelax-relocations=no)
+ 
+ KBUILD_AFLAGS  := $(KBUILD_CFLAGS) -D__ASSEMBLY__
+ GCOV_PROFILE := n

commit 0a4bb5e5507a585532cc413125b921c8546fc39f
+Author: Arvind Sankar 
+Date:   Mon Sep 7 17:39:19 2020 -0400
+
+    x86/fpu: Allow multiple bits in clearcpuid= parameter
+    
+    Commit
+    
+      0c2a3913d6f5 ("x86/fpu: Parse clearcpuid= as early XSAVE argument")
+    
+    changed clearcpuid parsing from __setup() to cmdline_find_option().
+    While the __setup() function would have been called for each clearcpuid=
+    parameter on the command line, cmdline_find_option() will only return
+    the last one, so the change effectively made it impossible to disable
+    more than one bit.
+    
+    Allow a comma-separated list of bit numbers as the argument for
+    clearcpuid to allow multiple bits to be disabled again. Log the bits
+    being disabled for informational purposes.
+    
+    Also fix the check on the return value of cmdline_find_option(). It
+    returns -1 when the option is not found, so testing as a boolean is
+    incorrect.
+    
+    Fixes: 0c2a3913d6f5 ("x86/fpu: Parse clearcpuid= as early XSAVE argument")
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Borislav Petkov 
+    Link: https://lkml.kernel.org/r/20200907213919.2423441-1-nivedita@alum.mit.edu
+
+diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
+index a1068742a6df..ffe864390c5a 100644
+--- a/Documentation/admin-guide/kernel-parameters.txt
++++ b/Documentation/admin-guide/kernel-parameters.txt
+@@ -577,7 +577,7 @@
+ 			loops can be debugged more effectively on production
+ 			systems.
+ 
+-	clearcpuid=BITNUM [X86]
++	clearcpuid=BITNUM[,BITNUM...] [X86]
+ 			Disable CPUID feature X for the kernel. See
+ 			arch/x86/include/asm/cpufeatures.h for the valid bit
+ 			numbers. Note the Linux specific bits are not necessarily
+diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c
+index 61ddc3a5e5c2..f8ff895aaf7e 100644
+--- a/arch/x86/kernel/fpu/init.c
++++ b/arch/x86/kernel/fpu/init.c
+@@ -243,9 +243,9 @@ static void __init fpu__init_system_ctx_switch(void)
+  */
+ static void __init fpu__init_parse_early_param(void)
+ {
+-	char arg[32];
++	char arg[128];
+ 	char *argptr = arg;
+-	int bit;
++	int arglen, res, bit;
+ 
+ #ifdef CONFIG_X86_32
+ 	if (cmdline_find_option_bool(boot_command_line, "no387"))
+@@ -268,12 +268,26 @@ static void __init fpu__init_parse_early_param(void)
+ 	if (cmdline_find_option_bool(boot_command_line, "noxsaves"))
+ 		setup_clear_cpu_cap(X86_FEATURE_XSAVES);
+ 
+-	if (cmdline_find_option(boot_command_line, "clearcpuid", arg,
+-				sizeof(arg)) &&
+-	    get_option(&argptr, &bit) &&
+-	    bit >= 0 &&
+-	    bit < NCAPINTS * 32)
+-		setup_clear_cpu_cap(bit);
++	arglen = cmdline_find_option(boot_command_line, "clearcpuid", arg, sizeof(arg));
++	if (arglen <= 0)
++		return;
++
++	pr_info("Clearing CPUID bits:");
++	do {
++		res = get_option(&argptr, &bit);
++		if (res == 0 || res == 3)
++			break;
++
++		/* If the argument was too long, the last bit may be cut off */
++		if (res == 1 && arglen >= sizeof(arg))
++			break;
++
++		if (bit >= 0 && bit < NCAPINTS * 32) {
++			pr_cont(" " X86_CAP_FMT, x86_cap_flag(bit));
++			setup_clear_cpu_cap(bit);
++		}
++	} while (res == 2);
++	pr_cont("\n");
+ }
+ 
+ /*

commit aef0148f3606117352053c015cb33734e9ee7397
+Author: Arvind Sankar 
+Date:   Wed Sep 2 22:30:56 2020 -0400
+
+    x86/cmdline: Disable jump tables for cmdline.c
+    
+    When CONFIG_RETPOLINE is disabled, Clang uses a jump table for the
+    switch statement in cmdline_find_option (jump tables are disabled when
+    CONFIG_RETPOLINE is enabled). This function is called very early in boot
+    from sme_enable() if CONFIG_AMD_MEM_ENCRYPT is enabled. At this time,
+    the kernel is still executing out of the identity mapping, but the jump
+    table will contain virtual addresses.
+    
+    Fix this by disabling jump tables for cmdline.c when AMD_MEM_ENCRYPT is
+    enabled.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200903023056.3914690-1-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
+index d46fff11f06f..aa067859a70b 100644
+--- a/arch/x86/lib/Makefile
++++ b/arch/x86/lib/Makefile
+@@ -24,7 +24,7 @@ ifdef CONFIG_FUNCTION_TRACER
+ CFLAGS_REMOVE_cmdline.o = -pg
+ endif
+ 
+-CFLAGS_cmdline.o := -fno-stack-protector
++CFLAGS_cmdline.o := -fno-stack-protector -fno-jump-tables
+ endif
+ 
+ inat_tables_script = $(srctree)/arch/x86/tools/gen-insn-attr-x86.awk

commit 8a8a3237a78cbc0557f0eb16a89f16d616323e99
+Author: Arvind Sankar 
+Date:   Thu Aug 13 14:58:11 2020 -0400
+
+    efi/libstub: Handle unterminated cmdline
+    
+    Make the command line parsing more robust, by handling the case it is
+    not NUL-terminated.
+    
+    Use strnlen instead of strlen, and make sure that the temporary copy is
+    NUL-terminated before parsing.
+    
+    Cc: 
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200813185811.554051-4-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
+index f53652a3a106..f735db55adc0 100644
+--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
++++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
+@@ -194,12 +194,14 @@ efi_status_t efi_parse_options(char const *cmdline)
+ 	if (!cmdline)
+ 		return EFI_SUCCESS;
+ 
+-	len = strlen(cmdline) + 1;
++	len = strnlen(cmdline, COMMAND_LINE_SIZE - 1) + 1;
+ 	status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, len, (void **)&buf);
+ 	if (status != EFI_SUCCESS)
+ 		return status;
+ 
+-	str = skip_spaces(memcpy(buf, cmdline, len));
++	memcpy(buf, cmdline, len - 1);
++	buf[len - 1] = '\0';
++	str = skip_spaces(buf);
+ 
+ 	while (*str) {
+ 		char *param, *val;

commit a37ca6a2af9df2972372b918f09390c9303acfbd
+Author: Arvind Sankar 
+Date:   Wed Jul 29 15:33:00 2020 -0400
+
+    efi/libstub: Handle NULL cmdline
+    
+    Treat a NULL cmdline the same as empty. Although this is unlikely to
+    happen in practice, the x86 kernel entry does check for NULL cmdline and
+    handles it, so do it here as well.
+    
+    Cc: 
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200729193300.598448-1-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
+index 37ff34e7b85e..f53652a3a106 100644
+--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
++++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
+@@ -187,10 +187,14 @@ int efi_printk(const char *fmt, ...)
+  */
+ efi_status_t efi_parse_options(char const *cmdline)
+ {
+-	size_t len = strlen(cmdline) + 1;
++	size_t len;
+ 	efi_status_t status;
+ 	char *str, *buf;
+ 
++	if (!cmdline)
++		return EFI_SUCCESS;
++
++	len = strlen(cmdline) + 1;
+ 	status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, len, (void **)&buf);
+ 	if (status != EFI_SUCCESS)
+ 		return status;

commit 1fd9717d75df68e3c3509b8e7b1138ca63472f88
+Author: Arvind Sankar 
+Date:   Sat Jul 25 11:59:16 2020 -0400
+
+    efi/libstub: Stop parsing arguments at "--"
+    
+    Arguments after "--" are arguments for init, not for the kernel.
+    
+    Cc: 
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200725155916.1376773-1-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
+index 6bca70bbb43d..37ff34e7b85e 100644
+--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
++++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
+@@ -201,6 +201,8 @@ efi_status_t efi_parse_options(char const *cmdline)
+ 		char *param, *val;
+ 
+ 		str = next_arg(str, ¶m, &val);
++		if (!val && !strcmp(param, "--"))
++			break;
+ 
+ 		if (!strcmp(param, "nokaslr")) {
+ 			efi_nokaslr = true;

commit c8502eb2d43b6b9b1dc382299a4d37031be63876
+Author: Arvind Sankar 
+Date:   Fri Jul 17 15:45:26 2020 -0400
+
+    efi/x86: Mark kernel rodata non-executable for mixed mode
+    
+    When remapping the kernel rodata section RO in the EFI pagetables, the
+    protection flags that were used for the text section are being reused,
+    but the rodata section should not be marked executable.
+    
+    Cc: 
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200717194526.3452089-1-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
+index 413583f904a6..6af4da1149ba 100644
+--- a/arch/x86/platform/efi/efi_64.c
++++ b/arch/x86/platform/efi/efi_64.c
+@@ -259,6 +259,8 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
+ 	npages = (__end_rodata - __start_rodata) >> PAGE_SHIFT;
+ 	rodata = __pa(__start_rodata);
+ 	pfn = rodata >> PAGE_SHIFT;
++
++	pf = _PAGE_NX | _PAGE_ENC;
+ 	if (kernel_map_pages_in_pgd(pgd, pfn, rodata, npages, pf)) {
+ 		pr_err("Failed to map kernel rodata 1:1\n");
+ 		return 1;

commit 33d0f96ffd7394ffb208bb366be312d12dfd24a4
+Author: Arvind Sankar 
+Date:   Wed Aug 19 10:08:16 2020 -0400
+
+    lib/string.c: Use freestanding environment
+    
+    gcc can transform the loop in a naive implementation of memset/memcpy
+    etc into a call to the function itself.  This optimization is enabled by
+    -ftree-loop-distribute-patterns.
+    
+    This has been the case for a while, but gcc-10.x enables this option at
+    -O2 rather than -O3 as in previous versions.
+    
+    Add -ffreestanding, which implicitly disables this optimization with
+    gcc.  It is unclear whether clang performs such optimizations, but
+    hopefully it will also not do so in a freestanding environment.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56888
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/lib/Makefile b/lib/Makefile
+index e290fc5707ea..a4a4c6864f51 100644
+--- a/lib/Makefile
++++ b/lib/Makefile
+@@ -15,11 +15,16 @@ KCOV_INSTRUMENT_debugobjects.o := n
+ KCOV_INSTRUMENT_dynamic_debug.o := n
+ KCOV_INSTRUMENT_fault-inject.o := n
+ 
++# string.o implements standard library functions like memset/memcpy etc.
++# Use -ffreestanding to ensure that the compiler does not try to "optimize"
++# them into calls to themselves.
++CFLAGS_string.o := -ffreestanding
++
+ # Early boot use of cmdline, don't instrument it
+ ifdef CONFIG_AMD_MEM_ENCRYPT
+ KASAN_SANITIZE_string.o := n
+ 
+-CFLAGS_string.o := -fno-stack-protector
++CFLAGS_string.o += -fno-stack-protector
+ endif
+ 
+ # Used by KCSAN while enabled, avoid recursion.

commit 394b19d6cb58ae292c0e1ad6b893fed8ece477ce
+Author: Arvind Sankar 
+Date:   Tue Aug 4 19:48:17 2020 -0400
+
+    x86/boot/compressed: Use builtin mem functions for decompressor
+    
+    Since commits
+    
+      c041b5ad8640 ("x86, boot: Create a separate string.h file to provide standard string functions")
+      fb4cac573ef6 ("x86, boot: Move memcmp() into string.h and string.c")
+    
+    the decompressor stub has been using the compiler's builtin memcpy,
+    memset and memcmp functions, _except_ where it would likely have the
+    largest impact, in the decompression code itself.
+    
+    Remove the #undef's of memcpy and memset in misc.c so that the
+    decompressor code also uses the compiler builtins.
+    
+    The rationale given in the comment doesn't really apply: just because
+    some functions use the out-of-line version is no reason to not use the
+    builtin version in the rest.
+    
+    Replace the comment with an explanation of why memzero and memmove are
+    being #define'd.
+    
+    Drop the suggestion to #undef in boot/string.h as well: the out-of-line
+    versions are not really optimized versions, they're generic code that's
+    good enough for the preboot environment. The compiler will likely
+    generate better code for constant-size memcpy/memset/memcmp if it is
+    allowed to.
+    
+    Most decompressors' performance is unchanged, with the exception of LZ4
+    and 64-bit ZSTD.
+    
+            Before  After ARCH
+    LZ4       73ms   10ms   32
+    LZ4      120ms   10ms   64
+    ZSTD      90ms   74ms   64
+    
+    Measurements on QEMU on 2.2GHz Broadwell Xeon, using defconfig kernels.
+    
+    Decompressor code size has small differences, with the largest being
+    that 64-bit ZSTD decreases just over 2k. The largest code size increase
+    was on 64-bit XZ, of about 400 bytes.
+    
+    Signed-off-by: Arvind Sankar 
+    Suggested-by: Nick Terrell 
+    Tested-by: Nick Terrell 
+    Acked-by: Kees Cook 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
+index 39e592d0e0b4..e478e40fbe5a 100644
+--- a/arch/x86/boot/compressed/misc.c
++++ b/arch/x86/boot/compressed/misc.c
+@@ -30,12 +30,9 @@
+ #define STATIC		static
+ 
+ /*
+- * Use normal definitions of mem*() from string.c. There are already
+- * included header files which expect a definition of memset() and by
+- * the time we define memset macro, it is too late.
++ * Provide definitions of memzero and memmove as some of the decompressors will
++ * try to define their own functions if these are not defined as macros.
+  */
+-#undef memcpy
+-#undef memset
+ #define memzero(s, n)	memset((s), 0, (n))
+ #define memmove		memmove
+ 
+diff --git a/arch/x86/boot/string.h b/arch/x86/boot/string.h
+index 995f7b7ad512..a232da487cd2 100644
+--- a/arch/x86/boot/string.h
++++ b/arch/x86/boot/string.h
+@@ -11,10 +11,7 @@ void *memcpy(void *dst, const void *src, size_t len);
+ void *memset(void *dst, int c, size_t len);
+ int memcmp(const void *s1, const void *s2, size_t len);
+ 
+-/*
+- * Access builtin version by default. If one needs to use optimized version,
+- * do "undef memcpy" in .c file and link against right string.c
+- */
++/* Access builtin version by default. */
+ #define memcpy(d,s,l) __builtin_memcpy(d,s,l)
+ #define memset(d,c,l) __builtin_memset(d,c,l)
+ #define memcmp	__builtin_memcmp

commit 527afc212231ea9d585b7709c0ab73263ecf0c85
+Author: Arvind Sankar 
+Date:   Fri Jul 31 16:07:51 2020 -0700
+
+    x86/boot: Check that there are no run-time relocations
+    
+    Add a linker script check that there are no run-time relocations, and
+    remove the old one that tries to check via looking for specially-named
+    sections in the object files.
+    
+    Drop the tests for -fPIE compiler option and -pie linker option, as they
+    are available in all supported gcc and binutils versions (as well as
+    clang and lld).
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Kees Cook 
+    Signed-off-by: Ingo Molnar 
+    Tested-by: Nick Desaulniers 
+    Tested-by: Sedat Dilek 
+    Reviewed-by: Kees Cook 
+    Reviewed-by: Ard Biesheuvel 
+    Reviewed-by: Fangrui Song 
+    Reviewed-by: Sedat Dilek 
+    Link: https://lore.kernel.org/r/20200731230820.1742553-8-keescook@chromium.org
+
+diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
+index 7d25089c5a7b..753d57266757 100644
+--- a/arch/x86/boot/compressed/Makefile
++++ b/arch/x86/boot/compressed/Makefile
+@@ -29,7 +29,7 @@ targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma \
+ 	vmlinux.bin.xz vmlinux.bin.lzo vmlinux.bin.lz4 vmlinux.bin.zst
+ 
+ KBUILD_CFLAGS := -m$(BITS) -O2
+-KBUILD_CFLAGS += -fno-strict-aliasing $(call cc-option, -fPIE, -fPIC)
++KBUILD_CFLAGS += -fno-strict-aliasing -fPIE
+ KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
+ cflags-$(CONFIG_X86_32) := -march=i386
+ cflags-$(CONFIG_X86_64) := -mcmodel=small
+@@ -52,7 +52,7 @@ UBSAN_SANITIZE :=n
+ KBUILD_LDFLAGS := -m elf_$(UTS_MACHINE)
+ # Compressed kernel should be built as PIE since it may be loaded at any
+ # address by the bootloader.
+-LDFLAGS_vmlinux := $(call ld-option, -pie) $(call ld-option, --no-dynamic-linker)
++LDFLAGS_vmlinux := -pie $(call ld-option, --no-dynamic-linker)
+ LDFLAGS_vmlinux += -T
+ 
+ hostprogs	:= mkpiggy
+@@ -87,30 +87,8 @@ vmlinux-objs-$(CONFIG_ACPI) += $(obj)/acpi.o
+ vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_thunk_$(BITS).o
+ efi-obj-$(CONFIG_EFI_STUB) = $(objtree)/drivers/firmware/efi/libstub/lib.a
+ 
+-# The compressed kernel is built with -fPIC/-fPIE so that a boot loader
+-# can place it anywhere in memory and it will still run. However, since
+-# it is executed as-is without any ELF relocation processing performed
+-# (and has already had all relocation sections stripped from the binary),
+-# none of the code can use data relocations (e.g. static assignments of
+-# pointer values), since they will be meaningless at runtime. This check
+-# will refuse to link the vmlinux if any of these relocations are found.
+-quiet_cmd_check_data_rel = DATAREL $@
+-define cmd_check_data_rel
+-	for obj in $(filter %.o,$^); do \
+-		$(READELF) -S $$obj | grep -qF .rel.local && { \
+-			echo "error: $$obj has data relocations!" >&2; \
+-			exit 1; \
+-		} || true; \
+-	done
+-endef
+-
+-# We need to run two commands under "if_changed", so merge them into a
+-# single invocation.
+-quiet_cmd_check-and-link-vmlinux = LD      $@
+-      cmd_check-and-link-vmlinux = $(cmd_check_data_rel); $(cmd_ld)
+-
+ $(obj)/vmlinux: $(vmlinux-objs-y) $(efi-obj-y) FORCE
+-	$(call if_changed,check-and-link-vmlinux)
++	$(call if_changed,ld)
+ 
+ OBJCOPYFLAGS_vmlinux.bin :=  -R .comment -S
+ $(obj)/vmlinux.bin: vmlinux FORCE
+diff --git a/arch/x86/boot/compressed/vmlinux.lds.S b/arch/x86/boot/compressed/vmlinux.lds.S
+index a4a4a59a2628..29df99b6cc64 100644
+--- a/arch/x86/boot/compressed/vmlinux.lds.S
++++ b/arch/x86/boot/compressed/vmlinux.lds.S
+@@ -42,6 +42,12 @@ SECTIONS
+ 		*(.rodata.*)
+ 		_erodata = . ;
+ 	}
++	.rel.dyn : {
++		*(.rel.*)
++	}
++	.rela.dyn : {
++		*(.rela.*)
++	}
+ 	.got : {
+ 		*(.got)
+ 	}
+@@ -85,3 +91,5 @@ ASSERT(SIZEOF(.got.plt) == 0 || SIZEOF(.got.plt) == 0x18, "Unexpected GOT/PLT en
+ #else
+ ASSERT(SIZEOF(.got.plt) == 0 || SIZEOF(.got.plt) == 0xc, "Unexpected GOT/PLT entries detected!")
+ #endif
++
++ASSERT(SIZEOF(.rel.dyn) == 0 && SIZEOF(.rela.dyn) == 0, "Unexpected run-time relocations detected!")

commit 3f086189cd3641d212949ff044d8e4486c93d55e
+Author: Arvind Sankar 
+Date:   Fri Jul 31 16:07:50 2020 -0700
+
+    x86/boot: Remove run-time relocations from head_{32,64}.S
+    
+    The BFD linker generates run-time relocations for z_input_len and
+    z_output_len, even though they are absolute symbols.
+    
+    This is fixed for binutils-2.35 [1]. Work around this for earlier
+    versions by defining two variables input_len and output_len in addition
+    to the symbols, and use them via position-independent references.
+    
+    This eliminates the last two run-time relocations in the head code and
+    allows us to drop the -z noreloc-overflow flag to the linker.
+    
+    Move the -pie and --no-dynamic-linker LDFLAGS to LDFLAGS_vmlinux instead
+    of KBUILD_LDFLAGS. There shouldn't be anything else getting linked, but
+    this is the more logical location for these flags, and modversions might
+    call the linker if an EXPORT_SYMBOL is left over accidentally in one of
+    the decompressors.
+    
+    [1] https://sourceware.org/bugzilla/show_bug.cgi?id=25754
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Kees Cook 
+    Signed-off-by: Ingo Molnar 
+    Tested-by: Nick Desaulniers 
+    Tested-by: Sedat Dilek 
+    Reviewed-by: Kees Cook 
+    Reviewed-by: Ard Biesheuvel 
+    Reviewed-by: Fangrui Song 
+    Link: https://lore.kernel.org/r/20200731230820.1742553-7-keescook@chromium.org
+
+diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
+index 7c687a770537..7d25089c5a7b 100644
+--- a/arch/x86/boot/compressed/Makefile
++++ b/arch/x86/boot/compressed/Makefile
+@@ -52,16 +52,8 @@ UBSAN_SANITIZE :=n
+ KBUILD_LDFLAGS := -m elf_$(UTS_MACHINE)
+ # Compressed kernel should be built as PIE since it may be loaded at any
+ # address by the bootloader.
+-ifeq ($(CONFIG_X86_32),y)
+-KBUILD_LDFLAGS += $(call ld-option, -pie) $(call ld-option, --no-dynamic-linker)
+-else
+-# To build 64-bit compressed kernel as PIE, we disable relocation
+-# overflow check to avoid relocation overflow error with a new linker
+-# command-line option, -z noreloc-overflow.
+-KBUILD_LDFLAGS += $(shell $(LD) --help 2>&1 | grep -q "\-z noreloc-overflow" \
+-	&& echo "-z noreloc-overflow -pie --no-dynamic-linker")
+-endif
+-LDFLAGS_vmlinux := -T
++LDFLAGS_vmlinux := $(call ld-option, -pie) $(call ld-option, --no-dynamic-linker)
++LDFLAGS_vmlinux += -T
+ 
+ hostprogs	:= mkpiggy
+ HOST_EXTRACFLAGS += -I$(srctree)/tools/include
+diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
+index 8c1a4f5610f5..659fad53ca82 100644
+--- a/arch/x86/boot/compressed/head_32.S
++++ b/arch/x86/boot/compressed/head_32.S
+@@ -178,18 +178,17 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
+ /*
+  * Do the extraction, and jump to the new kernel..
+  */
+-				/* push arguments for extract_kernel: */
+-	pushl	$z_output_len	/* decompressed length, end of relocs */
++	/* push arguments for extract_kernel: */
+ 
+-	pushl	%ebp		/* output address */
+-
+-	pushl	$z_input_len	/* input_len */
++	pushl	output_len@GOTOFF(%ebx)	/* decompressed length, end of relocs */
++	pushl	%ebp			/* output address */
++	pushl	input_len@GOTOFF(%ebx)	/* input_len */
+ 	leal	input_data@GOTOFF(%ebx), %eax
+-	pushl	%eax		/* input_data */
++	pushl	%eax			/* input_data */
+ 	leal	boot_heap@GOTOFF(%ebx), %eax
+-	pushl	%eax		/* heap area */
+-	pushl	%esi		/* real mode pointer */
+-	call	extract_kernel	/* returns kernel location in %eax */
++	pushl	%eax			/* heap area */
++	pushl	%esi			/* real mode pointer */
++	call	extract_kernel		/* returns kernel location in %eax */
+ 	addl	$24, %esp
+ 
+ /*
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index 11429092c224..9e46729cf162 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -534,9 +534,9 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
+ 	movq	%rsi, %rdi		/* real mode address */
+ 	leaq	boot_heap(%rip), %rsi	/* malloc area for uncompression */
+ 	leaq	input_data(%rip), %rdx  /* input_data */
+-	movl	$z_input_len, %ecx	/* input_len */
++	movl	input_len(%rip), %ecx	/* input_len */
+ 	movq	%rbp, %r8		/* output target address */
+-	movl	$z_output_len, %r9d	/* decompressed length, end of relocs */
++	movl	output_len(%rip), %r9d	/* decompressed length, end of relocs */
+ 	call	extract_kernel		/* returns kernel location in %rax */
+ 	popq	%rsi
+ 
+diff --git a/arch/x86/boot/compressed/mkpiggy.c b/arch/x86/boot/compressed/mkpiggy.c
+index 7e01248765b2..52aa56cdbacc 100644
+--- a/arch/x86/boot/compressed/mkpiggy.c
++++ b/arch/x86/boot/compressed/mkpiggy.c
+@@ -60,6 +60,12 @@ int main(int argc, char *argv[])
+ 	printf(".incbin \"%s\"\n", argv[1]);
+ 	printf("input_data_end:\n");
+ 
++	printf(".section \".rodata\",\"a\",@progbits\n");
++	printf(".globl input_len\n");
++	printf("input_len:\n\t.long %lu\n", ilen);
++	printf(".globl output_len\n");
++	printf("output_len:\n\t.long %lu\n", (unsigned long)olen);
++
+ 	retval = 0;
+ bail:
+ 	if (f)

commit a2c4fc4d4e2c40b07534094810d915c7354d84a7
+Author: Arvind Sankar 
+Date:   Fri Jul 31 16:07:49 2020 -0700
+
+    x86/boot: Remove run-time relocations from .head.text code
+    
+    The assembly code in head_{32,64}.S, while meant to be
+    position-independent, generates run-time relocations because it uses
+    instructions such as:
+    
+            leal    gdt(%edx), %eax
+    
+    which make the assembler and linker think that the code is using %edx as
+    an index into gdt, and hence gdt needs to be relocated to its run-time
+    address.
+    
+    On 32-bit, with lld Dmitry Golovin reports that this results in a
+    link-time error with default options (i.e. unless -z notext is
+    explicitly passed):
+    
+      LD      arch/x86/boot/compressed/vmlinux
+      ld.lld: error: can't create dynamic relocation R_386_32 against local
+      symbol in readonly segment; recompile object files with -fPIC or pass
+      '-Wl,-z,notext' to allow text relocations in the output
+    
+    With the BFD linker, this generates a warning during the build, if
+    --warn-shared-textrel is enabled, which at least Gentoo enables by
+    default:
+    
+      LD      arch/x86/boot/compressed/vmlinux
+      ld: arch/x86/boot/compressed/head_32.o: warning: relocation in read-only section `.head.text'
+      ld: warning: creating a DT_TEXTREL in object
+    
+    On 64-bit, it is not possible to link the kernel as -pie with lld, and
+    it is only possible with a BFD linker that supports -z noreloc-overflow,
+    i.e. versions >2.26. This is because these instructions cannot really be
+    relocated: the displacement field is only 32-bits wide, and thus cannot
+    be relocated for a 64-bit load address. The -z noreloc-overflow option
+    simply overrides the linker error, and results in R_X86_64_RELATIVE
+    relocations that apply a 64-bit relocation to a 32-bit field anyway.
+    This happens to work because nothing will process these run-time
+    relocations.
+    
+    Start fixing this by removing relocations from .head.text:
+    
+    - On 32-bit, use a base register that holds the address of the GOT and
+      reference symbol addresses using @GOTOFF, i.e.
+            leal    gdt@GOTOFF(%edx), %eax
+    
+    - On 64-bit, most of the code can (and already does) use %rip-relative
+      addressing, however the .code32 bits can't, and the 64-bit code also
+      needs to reference symbol addresses as they will be after moving the
+      compressed kernel to the end of the decompression buffer.
+      For these cases, reference the symbols as an offset to startup_32 to
+      avoid creating relocations, i.e.:
+    
+            leal    (gdt-startup_32)(%bp), %eax
+    
+      This only works in .head.text as the subtraction cannot be represented
+      as a PC-relative relocation unless startup_32 is in the same section
+      as the code. Move efi32_pe_entry into .head.text so that it can use
+      the same method to avoid relocations.
+    
+    Reported-by: Dmitry Golovin 
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Kees Cook 
+    Signed-off-by: Ingo Molnar 
+    Tested-by: Nick Desaulniers 
+    Tested-by: Sedat Dilek 
+    Reviewed-by: Kees Cook 
+    Reviewed-by: Ard Biesheuvel 
+    Reviewed-by: Fangrui Song 
+    Link: https://lore.kernel.org/r/20200731230820.1742553-6-keescook@chromium.org
+
+diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
+index 39f0bb43218f..8c1a4f5610f5 100644
+--- a/arch/x86/boot/compressed/head_32.S
++++ b/arch/x86/boot/compressed/head_32.S
+@@ -33,26 +33,10 @@
+ #include 
+ 
+ /*
+- * The 32-bit x86 assembler in binutils 2.26 will generate R_386_GOT32X
+- * relocation to get the symbol address in PIC.  When the compressed x86
+- * kernel isn't built as PIC, the linker optimizes R_386_GOT32X
+- * relocations to their fixed symbol addresses.  However, when the
+- * compressed x86 kernel is loaded at a different address, it leads
+- * to the following load failure:
+- *
+- *   Failed to allocate space for phdrs
+- *
+- * during the decompression stage.
+- *
+- * If the compressed x86 kernel is relocatable at run-time, it should be
+- * compiled with -fPIE, instead of -fPIC, if possible and should be built as
+- * Position Independent Executable (PIE) so that linker won't optimize
+- * R_386_GOT32X relocation to its fixed symbol address.  Older
+- * linkers generate R_386_32 relocations against locally defined symbols,
+- * _bss, _ebss and _end, in PIE.  It isn't wrong, just less optimal than
+- * R_386_RELATIVE.  But the x86 kernel fails to properly handle R_386_32
+- * relocations when relocating the kernel.  To generate R_386_RELATIVE
+- * relocations, we mark _bss, _ebss and _end as hidden:
++ * These symbols needed to be marked as .hidden to prevent the BFD linker from
++ * generating R_386_32 (rather than R_386_RELATIVE) relocations for them when
++ * the 32-bit compressed kernel is linked as PIE. This is no longer necessary,
++ * but it doesn't hurt to keep them .hidden.
+  */
+ 	.hidden _bss
+ 	.hidden _ebss
+@@ -74,10 +58,10 @@ SYM_FUNC_START(startup_32)
+ 	leal	(BP_scratch+4)(%esi), %esp
+ 	call	1f
+ 1:	popl	%edx
+-	subl	$1b, %edx
++	addl	$_GLOBAL_OFFSET_TABLE_+(.-1b), %edx
+ 
+ 	/* Load new GDT */
+-	leal	gdt(%edx), %eax
++	leal	gdt@GOTOFF(%edx), %eax
+ 	movl	%eax, 2(%eax)
+ 	lgdt	(%eax)
+ 
+@@ -90,14 +74,16 @@ SYM_FUNC_START(startup_32)
+ 	movl	%eax, %ss
+ 
+ /*
+- * %edx contains the address we are loaded at by the boot loader and %ebx
+- * contains the address where we should move the kernel image temporarily
+- * for safe in-place decompression. %ebp contains the address that the kernel
+- * will be decompressed to.
++ * %edx contains the address we are loaded at by the boot loader (plus the
++ * offset to the GOT).  The below code calculates %ebx to be the address where
++ * we should move the kernel image temporarily for safe in-place decompression
++ * (again, plus the offset to the GOT).
++ *
++ * %ebp is calculated to be the address that the kernel will be decompressed to.
+  */
+ 
+ #ifdef CONFIG_RELOCATABLE
+-	movl	%edx, %ebx
++	leal	startup_32@GOTOFF(%edx), %ebx
+ 
+ #ifdef CONFIG_EFI_STUB
+ /*
+@@ -108,7 +94,7 @@ SYM_FUNC_START(startup_32)
+  *	image_offset = startup_32 - image_base
+  * Otherwise image_offset will be zero and has no effect on the calculations.
+  */
+-	subl    image_offset(%edx), %ebx
++	subl    image_offset@GOTOFF(%edx), %ebx
+ #endif
+ 
+ 	movl	BP_kernel_alignment(%esi), %eax
+@@ -125,10 +111,10 @@ SYM_FUNC_START(startup_32)
+ 	movl	%ebx, %ebp	// Save the output address for later
+ 	/* Target address to relocate to for decompression */
+ 	addl    BP_init_size(%esi), %ebx
+-	subl    $_end, %ebx
++	subl    $_end@GOTOFF, %ebx
+ 
+ 	/* Set up the stack */
+-	leal	boot_stack_end(%ebx), %esp
++	leal	boot_stack_end@GOTOFF(%ebx), %esp
+ 
+ 	/* Zero EFLAGS */
+ 	pushl	$0
+@@ -139,8 +125,8 @@ SYM_FUNC_START(startup_32)
+  * where decompression in place becomes safe.
+  */
+ 	pushl	%esi
+-	leal	(_bss-4)(%edx), %esi
+-	leal	(_bss-4)(%ebx), %edi
++	leal	(_bss@GOTOFF-4)(%edx), %esi
++	leal	(_bss@GOTOFF-4)(%ebx), %edi
+ 	movl	$(_bss - startup_32), %ecx
+ 	shrl	$2, %ecx
+ 	std
+@@ -153,14 +139,14 @@ SYM_FUNC_START(startup_32)
+ 	 * during extract_kernel below. To avoid any issues, repoint the GDTR
+ 	 * to the new copy of the GDT.
+ 	 */
+-	leal	gdt(%ebx), %eax
++	leal	gdt@GOTOFF(%ebx), %eax
+ 	movl	%eax, 2(%eax)
+ 	lgdt	(%eax)
+ 
+ /*
+  * Jump to the relocated address.
+  */
+-	leal	.Lrelocated(%ebx), %eax
++	leal	.Lrelocated@GOTOFF(%ebx), %eax
+ 	jmp	*%eax
+ SYM_FUNC_END(startup_32)
+ 
+@@ -170,7 +156,7 @@ SYM_FUNC_START_ALIAS(efi_stub_entry)
+ 	add	$0x4, %esp
+ 	movl	8(%esp), %esi	/* save boot_params pointer */
+ 	call	efi_main
+-	leal	startup_32(%eax), %eax
++	/* efi_main returns the possibly relocated address of startup_32 */
+ 	jmp	*%eax
+ SYM_FUNC_END(efi32_stub_entry)
+ SYM_FUNC_END_ALIAS(efi_stub_entry)
+@@ -183,8 +169,8 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
+  * Clear BSS (stack is currently empty)
+  */
+ 	xorl	%eax, %eax
+-	leal	_bss(%ebx), %edi
+-	leal	_ebss(%ebx), %ecx
++	leal	_bss@GOTOFF(%ebx), %edi
++	leal	_ebss@GOTOFF(%ebx), %ecx
+ 	subl	%edi, %ecx
+ 	shrl	$2, %ecx
+ 	rep	stosl
+@@ -198,9 +184,9 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
+ 	pushl	%ebp		/* output address */
+ 
+ 	pushl	$z_input_len	/* input_len */
+-	leal	input_data(%ebx), %eax
++	leal	input_data@GOTOFF(%ebx), %eax
+ 	pushl	%eax		/* input_data */
+-	leal	boot_heap(%ebx), %eax
++	leal	boot_heap@GOTOFF(%ebx), %eax
+ 	pushl	%eax		/* heap area */
+ 	pushl	%esi		/* real mode pointer */
+ 	call	extract_kernel	/* returns kernel location in %eax */
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index bf1ab30acc5b..11429092c224 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -43,6 +43,32 @@
+ 	.hidden _end
+ 
+ 	__HEAD
++
++/*
++ * This macro gives the relative virtual address of X, i.e. the offset of X
++ * from startup_32. This is the same as the link-time virtual address of X,
++ * since startup_32 is at 0, but defining it this way tells the
++ * assembler/linker that we do not want the actual run-time address of X. This
++ * prevents the linker from trying to create unwanted run-time relocation
++ * entries for the reference when the compressed kernel is linked as PIE.
++ *
++ * A reference X(%reg) will result in the link-time VA of X being stored with
++ * the instruction, and a run-time R_X86_64_RELATIVE relocation entry that
++ * adds the 64-bit base address where the kernel is loaded.
++ *
++ * Replacing it with (X-startup_32)(%reg) results in the offset being stored,
++ * and no run-time relocation.
++ *
++ * The macro should be used as a displacement with a base register containing
++ * the run-time address of startup_32 [i.e. rva(X)(%reg)], or as an immediate
++ * [$ rva(X)].
++ *
++ * This macro can only be used from within the .head.text section, since the
++ * expression requires startup_32 to be in the same section as the code being
++ * assembled.
++ */
++#define rva(X) ((X) - startup_32)
++
+ 	.code32
+ SYM_FUNC_START(startup_32)
+ 	/*
+@@ -65,10 +91,10 @@ SYM_FUNC_START(startup_32)
+ 	leal	(BP_scratch+4)(%esi), %esp
+ 	call	1f
+ 1:	popl	%ebp
+-	subl	$1b, %ebp
++	subl	$ rva(1b), %ebp
+ 
+ 	/* Load new GDT with the 64bit segments using 32bit descriptor */
+-	leal	gdt(%ebp), %eax
++	leal	rva(gdt)(%ebp), %eax
+ 	movl	%eax, 2(%eax)
+ 	lgdt	(%eax)
+ 
+@@ -81,7 +107,7 @@ SYM_FUNC_START(startup_32)
+ 	movl	%eax, %ss
+ 
+ /* setup a stack and make sure cpu supports long mode. */
+-	leal	boot_stack_end(%ebp), %esp
++	leal	rva(boot_stack_end)(%ebp), %esp
+ 
+ 	call	verify_cpu
+ 	testl	%eax, %eax
+@@ -108,7 +134,7 @@ SYM_FUNC_START(startup_32)
+  *	image_offset = startup_32 - image_base
+  * Otherwise image_offset will be zero and has no effect on the calculations.
+  */
+-	subl    image_offset(%ebp), %ebx
++	subl    rva(image_offset)(%ebp), %ebx
+ #endif
+ 
+ 	movl	BP_kernel_alignment(%esi), %eax
+@@ -124,7 +150,7 @@ SYM_FUNC_START(startup_32)
+ 
+ 	/* Target address to relocate to for decompression */
+ 	addl	BP_init_size(%esi), %ebx
+-	subl	$_end, %ebx
++	subl	$ rva(_end), %ebx
+ 
+ /*
+  * Prepare for entering 64 bit mode
+@@ -152,19 +178,19 @@ SYM_FUNC_START(startup_32)
+ 1:
+ 
+ 	/* Initialize Page tables to 0 */
+-	leal	pgtable(%ebx), %edi
++	leal	rva(pgtable)(%ebx), %edi
+ 	xorl	%eax, %eax
+ 	movl	$(BOOT_INIT_PGT_SIZE/4), %ecx
+ 	rep	stosl
+ 
+ 	/* Build Level 4 */
+-	leal	pgtable + 0(%ebx), %edi
++	leal	rva(pgtable + 0)(%ebx), %edi
+ 	leal	0x1007 (%edi), %eax
+ 	movl	%eax, 0(%edi)
+ 	addl	%edx, 4(%edi)
+ 
+ 	/* Build Level 3 */
+-	leal	pgtable + 0x1000(%ebx), %edi
++	leal	rva(pgtable + 0x1000)(%ebx), %edi
+ 	leal	0x1007(%edi), %eax
+ 	movl	$4, %ecx
+ 1:	movl	%eax, 0x00(%edi)
+@@ -175,7 +201,7 @@ SYM_FUNC_START(startup_32)
+ 	jnz	1b
+ 
+ 	/* Build Level 2 */
+-	leal	pgtable + 0x2000(%ebx), %edi
++	leal	rva(pgtable + 0x2000)(%ebx), %edi
+ 	movl	$0x00000183, %eax
+ 	movl	$2048, %ecx
+ 1:	movl	%eax, 0(%edi)
+@@ -186,7 +212,7 @@ SYM_FUNC_START(startup_32)
+ 	jnz	1b
+ 
+ 	/* Enable the boot page tables */
+-	leal	pgtable(%ebx), %eax
++	leal	rva(pgtable)(%ebx), %eax
+ 	movl	%eax, %cr3
+ 
+ 	/* Enable Long mode in EFER (Extended Feature Enable Register) */
+@@ -211,14 +237,14 @@ SYM_FUNC_START(startup_32)
+ 	 * We place all of the values on our mini stack so lret can
+ 	 * used to perform that far jump.
+ 	 */
+-	leal	startup_64(%ebp), %eax
++	leal	rva(startup_64)(%ebp), %eax
+ #ifdef CONFIG_EFI_MIXED
+-	movl	efi32_boot_args(%ebp), %edi
++	movl	rva(efi32_boot_args)(%ebp), %edi
+ 	cmp	$0, %edi
+ 	jz	1f
+-	leal	efi64_stub_entry(%ebp), %eax
+-	movl	efi32_boot_args+4(%ebp), %esi
+-	movl	efi32_boot_args+8(%ebp), %edx	// saved bootparams pointer
++	leal	rva(efi64_stub_entry)(%ebp), %eax
++	movl	rva(efi32_boot_args+4)(%ebp), %esi
++	movl	rva(efi32_boot_args+8)(%ebp), %edx	// saved bootparams pointer
+ 	cmpl	$0, %edx
+ 	jnz	1f
+ 	/*
+@@ -229,7 +255,7 @@ SYM_FUNC_START(startup_32)
+ 	 * the correct stack alignment for entry.
+ 	 */
+ 	subl	$40, %esp
+-	leal	efi_pe_entry(%ebp), %eax
++	leal	rva(efi_pe_entry)(%ebp), %eax
+ 	movl	%edi, %ecx			// MS calling convention
+ 	movl	%esi, %edx
+ 1:
+@@ -255,18 +281,18 @@ SYM_FUNC_START(efi32_stub_entry)
+ 
+ 	call	1f
+ 1:	pop	%ebp
+-	subl	$1b, %ebp
++	subl	$ rva(1b), %ebp
+ 
+-	movl	%esi, efi32_boot_args+8(%ebp)
++	movl	%esi, rva(efi32_boot_args+8)(%ebp)
+ SYM_INNER_LABEL(efi32_pe_stub_entry, SYM_L_LOCAL)
+-	movl	%ecx, efi32_boot_args(%ebp)
+-	movl	%edx, efi32_boot_args+4(%ebp)
+-	movb	$0, efi_is64(%ebp)
++	movl	%ecx, rva(efi32_boot_args)(%ebp)
++	movl	%edx, rva(efi32_boot_args+4)(%ebp)
++	movb	$0, rva(efi_is64)(%ebp)
+ 
+ 	/* Save firmware GDTR and code/data selectors */
+-	sgdtl	efi32_boot_gdt(%ebp)
+-	movw	%cs, efi32_boot_cs(%ebp)
+-	movw	%ds, efi32_boot_ds(%ebp)
++	sgdtl	rva(efi32_boot_gdt)(%ebp)
++	movw	%cs, rva(efi32_boot_cs)(%ebp)
++	movw	%ds, rva(efi32_boot_ds)(%ebp)
+ 
+ 	/* Disable paging */
+ 	movl	%cr0, %eax
+@@ -345,11 +371,11 @@ SYM_CODE_START(startup_64)
+ 
+ 	/* Target address to relocate to for decompression */
+ 	movl	BP_init_size(%rsi), %ebx
+-	subl	$_end, %ebx
++	subl	$ rva(_end), %ebx
+ 	addq	%rbp, %rbx
+ 
+ 	/* Set up the stack */
+-	leaq	boot_stack_end(%rbx), %rsp
++	leaq	rva(boot_stack_end)(%rbx), %rsp
+ 
+ 	/*
+ 	 * At this point we are in long mode with 4-level paging enabled,
+@@ -423,7 +449,7 @@ SYM_CODE_START(startup_64)
+ 	lretq
+ trampoline_return:
+ 	/* Restore the stack, the 32-bit trampoline uses its own stack */
+-	leaq	boot_stack_end(%rbx), %rsp
++	leaq	rva(boot_stack_end)(%rbx), %rsp
+ 
+ 	/*
+ 	 * cleanup_trampoline() would restore trampoline memory.
+@@ -435,7 +461,7 @@ trampoline_return:
+ 	 * this function call.
+ 	 */
+ 	pushq	%rsi
+-	leaq	top_pgtable(%rbx), %rdi
++	leaq	rva(top_pgtable)(%rbx), %rdi
+ 	call	cleanup_trampoline
+ 	popq	%rsi
+ 
+@@ -449,9 +475,9 @@ trampoline_return:
+  */
+ 	pushq	%rsi
+ 	leaq	(_bss-8)(%rip), %rsi
+-	leaq	(_bss-8)(%rbx), %rdi
+-	movq	$_bss /* - $startup_32 */, %rcx
+-	shrq	$3, %rcx
++	leaq	rva(_bss-8)(%rbx), %rdi
++	movl	$(_bss - startup_32), %ecx
++	shrl	$3, %ecx
+ 	std
+ 	rep	movsq
+ 	cld
+@@ -462,15 +488,15 @@ trampoline_return:
+ 	 * during extract_kernel below. To avoid any issues, repoint the GDTR
+ 	 * to the new copy of the GDT.
+ 	 */
+-	leaq	gdt64(%rbx), %rax
+-	leaq	gdt(%rbx), %rdx
++	leaq	rva(gdt64)(%rbx), %rax
++	leaq	rva(gdt)(%rbx), %rdx
+ 	movq	%rdx, 2(%rax)
+ 	lgdt	(%rax)
+ 
+ /*
+  * Jump to the relocated address.
+  */
+-	leaq	.Lrelocated(%rbx), %rax
++	leaq	rva(.Lrelocated)(%rbx), %rax
+ 	jmp	*%rax
+ SYM_CODE_END(startup_64)
+ 
+@@ -482,7 +508,7 @@ SYM_FUNC_START_ALIAS(efi_stub_entry)
+ 	movq	%rdx, %rbx			/* save boot_params pointer */
+ 	call	efi_main
+ 	movq	%rbx,%rsi
+-	leaq	startup_64(%rax), %rax
++	leaq	rva(startup_64)(%rax), %rax
+ 	jmp	*%rax
+ SYM_FUNC_END(efi64_stub_entry)
+ SYM_FUNC_END_ALIAS(efi_stub_entry)
+@@ -645,7 +671,7 @@ SYM_DATA(efi_is64, .byte 1)
+ #define BS32_handle_protocol	88 // offsetof(efi_boot_services_32_t, handle_protocol)
+ #define LI32_image_base		32 // offsetof(efi_loaded_image_32_t, image_base)
+ 
+-	.text
++	__HEAD
+ 	.code32
+ SYM_FUNC_START(efi32_pe_entry)
+ /*
+@@ -667,12 +693,12 @@ SYM_FUNC_START(efi32_pe_entry)
+ 
+ 	call	1f
+ 1:	pop	%ebx
+-	subl	$1b, %ebx
++	subl	$ rva(1b), %ebx
+ 
+ 	/* Get the loaded image protocol pointer from the image handle */
+ 	leal	-4(%ebp), %eax
+ 	pushl	%eax				// &loaded_image
+-	leal	loaded_image_proto(%ebx), %eax
++	leal	rva(loaded_image_proto)(%ebx), %eax
+ 	pushl	%eax				// pass the GUID address
+ 	pushl	8(%ebp)				// pass the image handle
+ 
+@@ -707,7 +733,7 @@ SYM_FUNC_START(efi32_pe_entry)
+ 	 * use it before we get to the 64-bit efi_pe_entry() in C code.
+ 	 */
+ 	subl	%esi, %ebx
+-	movl	%ebx, image_offset(%ebp)	// save image_offset
++	movl	%ebx, rva(image_offset)(%ebp)	// save image_offset
+ 	jmp	efi32_pe_stub_entry
+ 
+ 2:	popl	%edi				// restore callee-save registers

commit 2e7a858ba843d2e6ceab1ba996805411de51b340
+Author: Arvind Sankar 
+Date:   Fri Jul 31 16:07:48 2020 -0700
+
+    x86/boot: Add .text.* to setup.ld
+    
+    GCC puts the main function into .text.startup when compiled with -Os (or
+    -O2). This results in arch/x86/boot/main.c having a .text.startup
+    section which is currently not included explicitly in the linker script
+    setup.ld in the same directory.
+    
+    The BFD linker places this orphan section immediately after .text, so
+    this still works. However, LLD git, since [1], is choosing to place it
+    immediately after the .bstext section instead (this is the first code
+    section). This plays havoc with the section layout that setup.elf
+    requires to create the setup header, for eg on 64-bit:
+    
+        LD      arch/x86/boot/setup.elf
+      ld.lld: error: section .text.startup file range overlaps with .header
+      >>> .text.startup range is [0x200040, 0x2001FE]
+      >>> .header range is [0x2001EF, 0x20026B]
+    
+      ld.lld: error: section .header file range overlaps with .bsdata
+      >>> .header range is [0x2001EF, 0x20026B]
+      >>> .bsdata range is [0x2001FF, 0x200398]
+    
+      ld.lld: error: section .bsdata file range overlaps with .entrytext
+      >>> .bsdata range is [0x2001FF, 0x200398]
+      >>> .entrytext range is [0x20026C, 0x2002D3]
+    
+      ld.lld: error: section .text.startup virtual address range overlaps
+      with .header
+      >>> .text.startup range is [0x40, 0x1FE]
+      >>> .header range is [0x1EF, 0x26B]
+    
+      ld.lld: error: section .header virtual address range overlaps with
+      .bsdata
+      >>> .header range is [0x1EF, 0x26B]
+      >>> .bsdata range is [0x1FF, 0x398]
+    
+      ld.lld: error: section .bsdata virtual address range overlaps with
+      .entrytext
+      >>> .bsdata range is [0x1FF, 0x398]
+      >>> .entrytext range is [0x26C, 0x2D3]
+    
+      ld.lld: error: section .text.startup load address range overlaps with
+      .header
+      >>> .text.startup range is [0x40, 0x1FE]
+      >>> .header range is [0x1EF, 0x26B]
+    
+      ld.lld: error: section .header load address range overlaps with
+      .bsdata
+      >>> .header range is [0x1EF, 0x26B]
+      >>> .bsdata range is [0x1FF, 0x398]
+    
+      ld.lld: error: section .bsdata load address range overlaps with
+      .entrytext
+      >>> .bsdata range is [0x1FF, 0x398]
+      >>> .entrytext range is [0x26C, 0x2D3]
+    
+    Add .text.* to the .text output section to fix this, and also prevent
+    any future surprises if the compiler decides to create other such
+    sections.
+    
+    [1] https://reviews.llvm.org/D75225
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Kees Cook 
+    Signed-off-by: Ingo Molnar 
+    Tested-by: Nick Desaulniers 
+    Tested-by: Sedat Dilek 
+    Reviewed-by: Kees Cook 
+    Reviewed-by: Ard Biesheuvel 
+    Reviewed-by: Fangrui Song 
+    Link: https://lore.kernel.org/r/20200731230820.1742553-5-keescook@chromium.org
+
+diff --git a/arch/x86/boot/setup.ld b/arch/x86/boot/setup.ld
+index 24c95522f231..49546c247ae2 100644
+--- a/arch/x86/boot/setup.ld
++++ b/arch/x86/boot/setup.ld
+@@ -20,7 +20,7 @@ SECTIONS
+ 	.initdata	: { *(.initdata) }
+ 	__end_init = .;
+ 
+-	.text		: { *(.text) }
++	.text		: { *(.text .text.*) }
+ 	.text32		: { *(.text32) }
+ 
+ 	. = ALIGN(16);

commit 376653435dacf84a8aca87e66aff94079a817cf2
+Author: Arvind Sankar 
+Date:   Tue Aug 11 18:34:16 2020 -0700
+
+    kernel.h: remove duplicate include of asm/div64.h
+    
+    This seems to have been added inadvertently in commit
+      72deb455b5ec ("block: remove CONFIG_LBDAF")
+    
+    Fixes: 72deb455b5ec ("block: remove CONFIG_LBDAF")
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Andrew Morton 
+    Reviewed-by: Christoph Hellwig 
+    Link: http://lkml.kernel.org/r/20200727034852.2813453-1-nivedita@alum.mit.edu
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/kernel.h b/include/linux/kernel.h
+index 7339a00c895e..e19c13616666 100644
+--- a/include/linux/kernel.h
++++ b/include/linux/kernel.h
+@@ -17,7 +17,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ 
+ #define STACK_MAGIC	0xdeadbeef
+ 

commit 6f8c00ff5aa88c847af9af35131d72fae480b566
+Author: Arvind Sankar 
+Date:   Tue Aug 11 18:32:46 2020 -0700
+
+    sparc: drop unused MAX_PHYSADDR_BITS
+    
+    The macro is not used anywhere, so remove the definition.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Andrew Morton 
+    Reviewed-by: Andrew Morton 
+    Reviewed-by: David Hildenbrand 
+    Acked-by: Dave Hansen 
+    Acked-by: David S. Miller 
+    Acked-by: Mike Rapoport 
+    Link: http://lkml.kernel.org/r/20200723231544.17274-4-nivedita@alum.mit.edu
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/sparc/include/asm/sparsemem.h b/arch/sparc/include/asm/sparsemem.h
+index 1dd1b61432db..aa9a676bc341 100644
+--- a/arch/sparc/include/asm/sparsemem.h
++++ b/arch/sparc/include/asm/sparsemem.h
+@@ -7,7 +7,6 @@
+ #include 
+ 
+ #define SECTION_SIZE_BITS       30
+-#define MAX_PHYSADDR_BITS       MAX_PHYS_ADDRESS_BITS
+ #define MAX_PHYSMEM_BITS        MAX_PHYS_ADDRESS_BITS
+ 
+ #endif /* !(__KERNEL__) */

commit c56771b3095d4f1af82847081b6781fc03a13904
+Author: Arvind Sankar 
+Date:   Tue Aug 11 18:32:43 2020 -0700
+
+    sh/mm: drop unused MAX_PHYSADDR_BITS
+    
+    The macro is not used anywhere, so remove the definition.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Andrew Morton 
+    Reviewed-by: Andrew Morton 
+    Reviewed-by: David Hildenbrand 
+    Acked-by: Dave Hansen 
+    Acked-by: Mike Rapoport 
+    Link: http://lkml.kernel.org/r/20200723231544.17274-3-nivedita@alum.mit.edu
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/sh/include/asm/sparsemem.h b/arch/sh/include/asm/sparsemem.h
+index 4eb899751e45..084706bb8cca 100644
+--- a/arch/sh/include/asm/sparsemem.h
++++ b/arch/sh/include/asm/sparsemem.h
+@@ -5,11 +5,9 @@
+ #ifdef __KERNEL__
+ /*
+  * SECTION_SIZE_BITS		2^N: how big each section will be
+- * MAX_PHYSADDR_BITS		2^N: how much physical address space we have
+- * MAX_PHYSMEM_BITS		2^N: how much memory we can have in that space
++ * MAX_PHYSMEM_BITS		2^N: how much physical address space we have
+  */
+ #define SECTION_SIZE_BITS	26
+-#define MAX_PHYSADDR_BITS	32
+ #define MAX_PHYSMEM_BITS	32
+ 
+ #endif

commit 76167e5c5457aee8fba3edc5b8554183696fc94d
+Author: Arvind Sankar 
+Date:   Sun Aug 2 21:15:34 2020 -0400
+
+    x86/kaslr: Replace strlen() with strnlen()
+    
+    strnlen is safer in case the command line is not NUL-terminated.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200803011534.730645-2-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
+index 735fcb2a8b7b..6d397435ccad 100644
+--- a/arch/x86/boot/compressed/kaslr.c
++++ b/arch/x86/boot/compressed/kaslr.c
+@@ -43,6 +43,10 @@
+ #define STATIC
+ #include 
+ 
++#define _SETUP
++#include 	/* For COMMAND_LINE_SIZE */
++#undef _SETUP
++
+ #ifdef CONFIG_X86_5LEVEL
+ unsigned int __pgtable_l5_enabled;
+ unsigned int pgdir_shift __ro_after_init = 39;
+@@ -278,7 +282,7 @@ static void handle_mem_options(void)
+ 	if (!args)
+ 		return;
+ 
+-	len = strlen(args);
++	len = strnlen(args, COMMAND_LINE_SIZE-1);
+ 	tmp_cmdline = malloc(len + 1);
+ 	if (!tmp_cmdline)
+ 		error("Failed to allocate space for tmp_cmdline");
+@@ -425,7 +429,7 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size,
+ 	cmd_line = get_cmd_line_ptr();
+ 	/* Calculate size of cmd_line. */
+ 	if (cmd_line) {
+-		cmd_line_size = strlen((char *)cmd_line) + 1;
++		cmd_line_size = strnlen((char *)cmd_line, COMMAND_LINE_SIZE-1) + 1;
+ 		mem_avoid[MEM_AVOID_CMDLINE].start = cmd_line;
+ 		mem_avoid[MEM_AVOID_CMDLINE].size = cmd_line_size;
+ 		add_identity_map(mem_avoid[MEM_AVOID_CMDLINE].start,

commit f49236ae424d499d02ee3ce35fb9130ddf95b03f
+Author: Arvind Sankar 
+Date:   Tue Jul 28 18:57:22 2020 -0400
+
+    x86/kaslr: Add a check that the random address is in range
+    
+    Check in find_random_phys_addr() that the chosen address is inside the
+    range that was required.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200728225722.67457-22-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
+index 80cdd2071305..735fcb2a8b7b 100644
+--- a/arch/x86/boot/compressed/kaslr.c
++++ b/arch/x86/boot/compressed/kaslr.c
+@@ -803,6 +803,8 @@ static void process_e820_entries(unsigned long minimum,
+ static unsigned long find_random_phys_addr(unsigned long minimum,
+ 					   unsigned long image_size)
+ {
++	u64 phys_addr;
++
+ 	/* Bail out early if it's impossible to succeed. */
+ 	if (minimum + image_size > mem_limit)
+ 		return 0;
+@@ -816,7 +818,15 @@ static unsigned long find_random_phys_addr(unsigned long minimum,
+ 	if (!process_efi_entries(minimum, image_size))
+ 		process_e820_entries(minimum, image_size);
+ 
+-	return slots_fetch_random();
++	phys_addr = slots_fetch_random();
++
++	/* Perform a final check to make sure the address is in range. */
++	if (phys_addr < minimum || phys_addr + image_size > mem_limit) {
++		warn("Invalid physical address chosen!\n");
++		return 0;
++	}
++
++	return (unsigned long)phys_addr;
+ }
+ 
+ static unsigned long find_random_virt_addr(unsigned long minimum,

commit 0eb1a8af01d6264cf948d67c8bff15e2eb859355
+Author: Arvind Sankar 
+Date:   Tue Jul 28 18:57:21 2020 -0400
+
+    x86/kaslr: Make local variables 64-bit
+    
+    Change the type of local variables/fields that store mem_vector
+    addresses to u64 to make it less likely that 32-bit overflow will cause
+    issues on 32-bit.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200728225722.67457-21-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
+index db8589c2b548..80cdd2071305 100644
+--- a/arch/x86/boot/compressed/kaslr.c
++++ b/arch/x86/boot/compressed/kaslr.c
+@@ -461,7 +461,7 @@ static bool mem_avoid_overlap(struct mem_vector *img,
+ {
+ 	int i;
+ 	struct setup_data *ptr;
+-	unsigned long earliest = img->start + img->size;
++	u64 earliest = img->start + img->size;
+ 	bool is_overlapping = false;
+ 
+ 	for (i = 0; i < MEM_AVOID_MAX; i++) {
+@@ -506,7 +506,7 @@ static bool mem_avoid_overlap(struct mem_vector *img,
+ }
+ 
+ struct slot_area {
+-	unsigned long addr;
++	u64 addr;
+ 	unsigned long num;
+ };
+ 
+@@ -537,7 +537,8 @@ static void store_slot_info(struct mem_vector *region, unsigned long image_size)
+ static void
+ process_gb_huge_pages(struct mem_vector *region, unsigned long image_size)
+ {
+-	unsigned long pud_start, pud_end, gb_huge_pages;
++	u64 pud_start, pud_end;
++	unsigned long gb_huge_pages;
+ 	struct mem_vector tmp;
+ 
+ 	if (!IS_ENABLED(CONFIG_X86_64) || !max_gb_huge_pages) {
+@@ -579,7 +580,7 @@ process_gb_huge_pages(struct mem_vector *region, unsigned long image_size)
+ 	}
+ }
+ 
+-static unsigned long slots_fetch_random(void)
++static u64 slots_fetch_random(void)
+ {
+ 	unsigned long slot;
+ 	unsigned int i;
+@@ -595,7 +596,7 @@ static unsigned long slots_fetch_random(void)
+ 			slot -= slot_areas[i].num;
+ 			continue;
+ 		}
+-		return slot_areas[i].addr + slot * CONFIG_PHYSICAL_ALIGN;
++		return slot_areas[i].addr + ((u64)slot * CONFIG_PHYSICAL_ALIGN);
+ 	}
+ 
+ 	if (i == slot_area_index)
+@@ -608,7 +609,7 @@ static void __process_mem_region(struct mem_vector *entry,
+ 				 unsigned long image_size)
+ {
+ 	struct mem_vector region, overlap;
+-	unsigned long region_end;
++	u64 region_end;
+ 
+ 	/* Enforce minimum and memory limit. */
+ 	region.start = max_t(u64, entry->start, minimum);

commit 3a066990a35eb289d54036637d2793d4743b8f07
+Author: Arvind Sankar 
+Date:   Tue Jul 28 18:57:20 2020 -0400
+
+    x86/kaslr: Replace 'unsigned long long' with 'u64'
+    
+    No functional change.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200728225722.67457-20-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
+index 3244f5b865e0..db8589c2b548 100644
+--- a/arch/x86/boot/compressed/kaslr.c
++++ b/arch/x86/boot/compressed/kaslr.c
+@@ -98,7 +98,7 @@ static bool memmap_too_large;
+  * Store memory limit: MAXMEM on 64-bit and KERNEL_IMAGE_SIZE on 32-bit.
+  * It may be reduced by "mem=nn[KMG]" or "memmap=nn[KMG]" command line options.
+  */
+-static unsigned long long mem_limit;
++static u64 mem_limit;
+ 
+ /* Number of immovable memory regions */
+ static int num_immovable_mem;
+@@ -141,8 +141,7 @@ enum parse_mode {
+ };
+ 
+ static int
+-parse_memmap(char *p, unsigned long long *start, unsigned long long *size,
+-		enum parse_mode mode)
++parse_memmap(char *p, u64 *start, u64 *size, enum parse_mode mode)
+ {
+ 	char *oldp;
+ 
+@@ -172,7 +171,7 @@ parse_memmap(char *p, unsigned long long *start, unsigned long long *size,
+ 			 */
+ 			*size = 0;
+ 		} else {
+-			unsigned long long flags;
++			u64 flags;
+ 
+ 			/*
+ 			 * efi_fake_mem=nn@ss:attr the attr specifies
+@@ -211,7 +210,7 @@ static void mem_avoid_memmap(enum parse_mode mode, char *str)
+ 
+ 	while (str && (i < MAX_MEMMAP_REGIONS)) {
+ 		int rc;
+-		unsigned long long start, size;
++		u64 start, size;
+ 		char *k = strchr(str, ',');
+ 
+ 		if (k)
+@@ -612,7 +611,7 @@ static void __process_mem_region(struct mem_vector *entry,
+ 	unsigned long region_end;
+ 
+ 	/* Enforce minimum and memory limit. */
+-	region.start = max_t(unsigned long long, entry->start, minimum);
++	region.start = max_t(u64, entry->start, minimum);
+ 	region_end = min(entry->start + entry->size, mem_limit);
+ 
+ 	/* Give up if slot area array is full. */
+@@ -673,7 +672,7 @@ static bool process_mem_region(struct mem_vector *region,
+ 	 * immovable memory and @region.
+ 	 */
+ 	for (i = 0; i < num_immovable_mem; i++) {
+-		unsigned long long start, end, entry_end, region_end;
++		u64 start, end, entry_end, region_end;
+ 		struct mem_vector entry;
+ 
+ 		if (!mem_overlaps(region, &immovable_mem[i]))
+diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
+index 726e264410ff..3efce27ba35c 100644
+--- a/arch/x86/boot/compressed/misc.h
++++ b/arch/x86/boot/compressed/misc.h
+@@ -70,8 +70,8 @@ int cmdline_find_option(const char *option, char *buffer, int bufsize);
+ int cmdline_find_option_bool(const char *option);
+ 
+ struct mem_vector {
+-	unsigned long long start;
+-	unsigned long long size;
++	u64 start;
++	u64 size;
+ };
+ 
+ #if CONFIG_RANDOMIZE_BASE

commit e4cb955bf173474a61f56200610004aacc7a62ff
+Author: Arvind Sankar 
+Date:   Tue Jul 28 18:57:19 2020 -0400
+
+    x86/kaslr: Make minimum/image_size 'unsigned long'
+    
+    Change type of minimum/image_size arguments in process_mem_region to
+    'unsigned long'. These actually can never be above 4G (even on x86_64),
+    and they're 'unsigned long' in every other function except this one.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200728225722.67457-19-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
+index ecdf33da2a97..3244f5b865e0 100644
+--- a/arch/x86/boot/compressed/kaslr.c
++++ b/arch/x86/boot/compressed/kaslr.c
+@@ -649,8 +649,8 @@ static void __process_mem_region(struct mem_vector *entry,
+ }
+ 
+ static bool process_mem_region(struct mem_vector *region,
+-			       unsigned long long minimum,
+-			       unsigned long long image_size)
++			       unsigned long minimum,
++			       unsigned long image_size)
+ {
+ 	int i;
+ 	/*

commit 4268b4da572f8bde8bc2f3243927ff5795687a6f
+Author: Arvind Sankar 
+Date:   Tue Jul 28 18:57:18 2020 -0400
+
+    x86/kaslr: Small cleanup of find_random_phys_addr()
+    
+    Just a trivial rearrangement to do all the processing together, and only
+    have one call to slots_fetch_random() in the source.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200728225722.67457-18-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
+index ce34a05ccdc4..ecdf33da2a97 100644
+--- a/arch/x86/boot/compressed/kaslr.c
++++ b/arch/x86/boot/compressed/kaslr.c
+@@ -813,10 +813,9 @@ static unsigned long find_random_phys_addr(unsigned long minimum,
+ 		return 0;
+ 	}
+ 
+-	if (process_efi_entries(minimum, image_size))
+-		return slots_fetch_random();
++	if (!process_efi_entries(minimum, image_size))
++		process_e820_entries(minimum, image_size);
+ 
+-	process_e820_entries(minimum, image_size);
+ 	return slots_fetch_random();
+ }
+ 

commit eb38be6db516fb72ccf7282628b545a185b3bc7a
+Author: Arvind Sankar 
+Date:   Tue Jul 28 18:57:17 2020 -0400
+
+    x86/kaslr: Drop unnecessary alignment in find_random_virt_addr()
+    
+    Drop unnecessary alignment of image_size to CONFIG_PHYSICAL_ALIGN in
+    find_random_virt_addr, it cannot change the result: the largest valid
+    slot is the largest n that satisfies
+    
+      minimum + n * CONFIG_PHYSICAL_ALIGN + image_size <= KERNEL_IMAGE_SIZE
+    
+    (since minimum is already aligned) and so n is equal to
+    
+      (KERNEL_IMAGE_SIZE - minimum - image_size) / CONFIG_PHYSICAL_ALIGN
+    
+    even if image_size is not aligned to CONFIG_PHYSICAL_ALIGN.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200728225722.67457-17-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
+index 0c64026a0951..ce34a05ccdc4 100644
+--- a/arch/x86/boot/compressed/kaslr.c
++++ b/arch/x86/boot/compressed/kaslr.c
+@@ -825,16 +825,12 @@ static unsigned long find_random_virt_addr(unsigned long minimum,
+ {
+ 	unsigned long slots, random_addr;
+ 
+-	/* Align image_size for easy slot calculations. */
+-	image_size = ALIGN(image_size, CONFIG_PHYSICAL_ALIGN);
+-
+ 	/*
+ 	 * There are how many CONFIG_PHYSICAL_ALIGN-sized slots
+ 	 * that can hold image_size within the range of minimum to
+ 	 * KERNEL_IMAGE_SIZE?
+ 	 */
+-	slots = (KERNEL_IMAGE_SIZE - minimum - image_size) /
+-		 CONFIG_PHYSICAL_ALIGN + 1;
++	slots = 1 + (KERNEL_IMAGE_SIZE - minimum - image_size) / CONFIG_PHYSICAL_ALIGN;
+ 
+ 	random_addr = kaslr_get_random_long("Virtual") % slots;
+ 

commit 46a5b29a4a63a3ba987cbb5467774a4b5787618e
+Author: Arvind Sankar 
+Date:   Tue Jul 28 18:57:16 2020 -0400
+
+    x86/kaslr: Drop redundant check in store_slot_info()
+    
+    Drop unnecessary check that number of slots is not zero in
+    store_slot_info, it's guaranteed to be at least 1 by the calculation.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200728225722.67457-16-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
+index 5c7457cc58f6..0c64026a0951 100644
+--- a/arch/x86/boot/compressed/kaslr.c
++++ b/arch/x86/boot/compressed/kaslr.c
+@@ -525,13 +525,10 @@ static void store_slot_info(struct mem_vector *region, unsigned long image_size)
+ 		return;
+ 
+ 	slot_area.addr = region->start;
+-	slot_area.num = (region->size - image_size) /
+-			CONFIG_PHYSICAL_ALIGN + 1;
++	slot_area.num = 1 + (region->size - image_size) / CONFIG_PHYSICAL_ALIGN;
+ 
+-	if (slot_area.num > 0) {
+-		slot_areas[slot_area_index++] = slot_area;
+-		slot_max += slot_area.num;
+-	}
++	slot_areas[slot_area_index++] = slot_area;
++	slot_max += slot_area.num;
+ }
+ 
+ /*

commit d6d0f36c735367ed7cf42b5ba454ba5858e17816
+Author: Arvind Sankar 
+Date:   Tue Jul 28 18:57:15 2020 -0400
+
+    x86/kaslr: Make the type of number of slots/slot areas consistent
+    
+    The number of slots can be 'unsigned int', since on 64-bit, the maximum
+    amount of memory is 2^52, the minimum alignment is 2^21, so the slot
+    number cannot be greater than 2^31. But in case future processors have
+    more than 52 physical address bits, make it 'unsigned long'.
+    
+    The slot areas are limited by MAX_SLOT_AREA, currently 100. It is
+    indexed by an int, but the number of areas is stored as 'unsigned long'.
+    Change both to 'unsigned int' for consistency.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200728225722.67457-15-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
+index bd13dc5e64b7..5c7457cc58f6 100644
+--- a/arch/x86/boot/compressed/kaslr.c
++++ b/arch/x86/boot/compressed/kaslr.c
+@@ -508,17 +508,15 @@ static bool mem_avoid_overlap(struct mem_vector *img,
+ 
+ struct slot_area {
+ 	unsigned long addr;
+-	int num;
++	unsigned long num;
+ };
+ 
+ #define MAX_SLOT_AREA 100
+ 
+ static struct slot_area slot_areas[MAX_SLOT_AREA];
+-
++static unsigned int slot_area_index;
+ static unsigned long slot_max;
+ 
+-static unsigned long slot_area_index;
+-
+ static void store_slot_info(struct mem_vector *region, unsigned long image_size)
+ {
+ 	struct slot_area slot_area;
+@@ -588,7 +586,7 @@ process_gb_huge_pages(struct mem_vector *region, unsigned long image_size)
+ static unsigned long slots_fetch_random(void)
+ {
+ 	unsigned long slot;
+-	int i;
++	unsigned int i;
+ 
+ 	/* Handle case of no slots stored. */
+ 	if (slot_max == 0)

commit 3870d971791f13df88a7a656e3fd6e2df8686097
+Author: Arvind Sankar 
+Date:   Tue Jul 28 18:57:14 2020 -0400
+
+    x86/kaslr: Drop test for command-line parameters before parsing
+    
+    This check doesn't save anything. In the case when none of the
+    parameters are present, each strstr will scan args twice (once to find
+    the length and then for searching), six scans in total. Just going ahead
+    and parsing the arguments only requires three scans: strlen, memcpy, and
+    parsing. This will be the first malloc, so free will actually free up
+    the memory, so the check doesn't save heap space either.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200728225722.67457-14-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
+index 00ef84b689f6..bd13dc5e64b7 100644
+--- a/arch/x86/boot/compressed/kaslr.c
++++ b/arch/x86/boot/compressed/kaslr.c
+@@ -279,10 +279,6 @@ static void handle_mem_options(void)
+ 	if (!args)
+ 		return;
+ 
+-	if (!strstr(args, "memmap=") && !strstr(args, "mem=") &&
+-		!strstr(args, "hugepages"))
+-		return;
+-
+ 	len = strlen(args);
+ 	tmp_cmdline = malloc(len + 1);
+ 	if (!tmp_cmdline)

commit be9e8d9541a95bdfac1c13d112cc032ea7fc745f
+Author: Arvind Sankar 
+Date:   Tue Jul 28 18:57:13 2020 -0400
+
+    x86/kaslr: Simplify process_gb_huge_pages()
+    
+    Replace the loop to determine the number of 1Gb pages with arithmetic.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200728225722.67457-13-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
+index 3727e9708690..00ef84b689f6 100644
+--- a/arch/x86/boot/compressed/kaslr.c
++++ b/arch/x86/boot/compressed/kaslr.c
+@@ -547,49 +547,44 @@ static void store_slot_info(struct mem_vector *region, unsigned long image_size)
+ static void
+ process_gb_huge_pages(struct mem_vector *region, unsigned long image_size)
+ {
+-	unsigned long addr, size = 0;
++	unsigned long pud_start, pud_end, gb_huge_pages;
+ 	struct mem_vector tmp;
+-	int i = 0;
+ 
+ 	if (!IS_ENABLED(CONFIG_X86_64) || !max_gb_huge_pages) {
+ 		store_slot_info(region, image_size);
+ 		return;
+ 	}
+ 
+-	addr = ALIGN(region->start, PUD_SIZE);
+-	/* Did we raise the address above the passed in memory entry? */
+-	if (addr < region->start + region->size)
+-		size = region->size - (addr - region->start);
+-
+-	/* Check how many 1GB huge pages can be filtered out: */
+-	while (size >= PUD_SIZE && max_gb_huge_pages) {
+-		size -= PUD_SIZE;
+-		max_gb_huge_pages--;
+-		i++;
+-	}
++	/* Are there any 1GB pages in the region? */
++	pud_start = ALIGN(region->start, PUD_SIZE);
++	pud_end = ALIGN_DOWN(region->start + region->size, PUD_SIZE);
+ 
+ 	/* No good 1GB huge pages found: */
+-	if (!i) {
++	if (pud_start >= pud_end) {
+ 		store_slot_info(region, image_size);
+ 		return;
+ 	}
+ 
+-	/*
+-	 * Skip those 'i'*1GB good huge pages, and continue checking and
+-	 * processing the remaining head or tail part of the passed region
+-	 * if available.
+-	 */
+-
+-	if (addr >= region->start + image_size) {
++	/* Check if the head part of the region is usable. */
++	if (pud_start >= region->start + image_size) {
+ 		tmp.start = region->start;
+-		tmp.size = addr - region->start;
++		tmp.size = pud_start - region->start;
+ 		store_slot_info(&tmp, image_size);
+ 	}
+ 
+-	size  = region->size - (addr - region->start) - i * PUD_SIZE;
+-	if (size >= image_size) {
+-		tmp.start = addr + i * PUD_SIZE;
+-		tmp.size = size;
++	/* Skip the good 1GB pages. */
++	gb_huge_pages = (pud_end - pud_start) >> PUD_SHIFT;
++	if (gb_huge_pages > max_gb_huge_pages) {
++		pud_end = pud_start + (max_gb_huge_pages << PUD_SHIFT);
++		max_gb_huge_pages = 0;
++	} else {
++		max_gb_huge_pages -= gb_huge_pages;
++	}
++
++	/* Check if the tail part of the region is usable. */
++	if (region->start + region->size >= pud_end + image_size) {
++		tmp.start = pud_end;
++		tmp.size = region->start + region->size - pud_end;
+ 		store_slot_info(&tmp, image_size);
+ 	}
+ }

commit 50def2693a900dfb1d91872056dc8164245820fc
+Author: Arvind Sankar 
+Date:   Tue Jul 28 18:57:12 2020 -0400
+
+    x86/kaslr: Short-circuit gb_huge_pages on x86-32
+    
+    32-bit does not have GB pages, so don't bother checking for them. Using
+    the IS_ENABLED() macro allows the compiler to completely remove the
+    gb_huge_pages code.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200728225722.67457-12-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
+index 0df513e3e2ce..3727e9708690 100644
+--- a/arch/x86/boot/compressed/kaslr.c
++++ b/arch/x86/boot/compressed/kaslr.c
+@@ -303,7 +303,7 @@ static void handle_mem_options(void)
+ 
+ 		if (!strcmp(param, "memmap")) {
+ 			mem_avoid_memmap(PARSE_MEMMAP, val);
+-		} else if (strstr(param, "hugepages")) {
++		} else if (IS_ENABLED(CONFIG_X86_64) && strstr(param, "hugepages")) {
+ 			parse_gb_huge_pages(param, val);
+ 		} else if (!strcmp(param, "mem")) {
+ 			char *p = val;
+@@ -551,7 +551,7 @@ process_gb_huge_pages(struct mem_vector *region, unsigned long image_size)
+ 	struct mem_vector tmp;
+ 	int i = 0;
+ 
+-	if (!max_gb_huge_pages) {
++	if (!IS_ENABLED(CONFIG_X86_64) || !max_gb_huge_pages) {
+ 		store_slot_info(region, image_size);
+ 		return;
+ 	}

commit 79c2fd2afe55944098047721c33e06fd48654e57
+Author: Arvind Sankar 
+Date:   Tue Jul 28 18:57:11 2020 -0400
+
+    x86/kaslr: Fix off-by-one error in process_gb_huge_pages()
+    
+    If the remaining size of the region is exactly 1Gb, there is still one
+    hugepage that can be reserved.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200728225722.67457-11-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
+index d074986e8061..0df513e3e2ce 100644
+--- a/arch/x86/boot/compressed/kaslr.c
++++ b/arch/x86/boot/compressed/kaslr.c
+@@ -562,7 +562,7 @@ process_gb_huge_pages(struct mem_vector *region, unsigned long image_size)
+ 		size = region->size - (addr - region->start);
+ 
+ 	/* Check how many 1GB huge pages can be filtered out: */
+-	while (size > PUD_SIZE && max_gb_huge_pages) {
++	while (size >= PUD_SIZE && max_gb_huge_pages) {
+ 		size -= PUD_SIZE;
+ 		max_gb_huge_pages--;
+ 		i++;

commit bf457be1548eee6d106daf9604e029b36fed2b11
+Author: Arvind Sankar 
+Date:   Tue Jul 28 18:57:10 2020 -0400
+
+    x86/kaslr: Drop some redundant checks from __process_mem_region()
+    
+    Clip the start and end of the region to minimum and mem_limit prior to
+    the loop. region.start can only increase during the loop, so raising it
+    to minimum before the loop is enough.
+    
+    A region that becomes empty due to this will get checked in
+    the first iteration of the loop.
+    
+    Drop the check for overlap extending beyond the end of the region. This
+    will get checked in the next loop iteration anyway.
+    
+    Rename end to region_end for symmetry with region.start.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200728225722.67457-10-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
+index 8cc47faea56d..d074986e8061 100644
+--- a/arch/x86/boot/compressed/kaslr.c
++++ b/arch/x86/boot/compressed/kaslr.c
+@@ -623,34 +623,23 @@ static void __process_mem_region(struct mem_vector *entry,
+ 				 unsigned long image_size)
+ {
+ 	struct mem_vector region, overlap;
+-	unsigned long end;
++	unsigned long region_end;
+ 
+-	/* Ignore entries entirely below our minimum. */
+-	if (entry->start + entry->size < minimum)
+-		return;
+-
+-	/* Ignore entries above memory limit */
+-	end = min(entry->size + entry->start, mem_limit);
+-	if (entry->start >= end)
+-		return;
+-
+-	region.start = entry->start;
++	/* Enforce minimum and memory limit. */
++	region.start = max_t(unsigned long long, entry->start, minimum);
++	region_end = min(entry->start + entry->size, mem_limit);
+ 
+ 	/* Give up if slot area array is full. */
+ 	while (slot_area_index < MAX_SLOT_AREA) {
+-		/* Potentially raise address to minimum location. */
+-		if (region.start < minimum)
+-			region.start = minimum;
+-
+ 		/* Potentially raise address to meet alignment needs. */
+ 		region.start = ALIGN(region.start, CONFIG_PHYSICAL_ALIGN);
+ 
+ 		/* Did we raise the address above the passed in memory entry? */
+-		if (region.start > end)
++		if (region.start > region_end)
+ 			return;
+ 
+ 		/* Reduce size by any delta from the original address. */
+-		region.size = end - region.start;
++		region.size = region_end - region.start;
+ 
+ 		/* Return if region can't contain decompressed kernel */
+ 		if (region.size < image_size)
+@@ -668,10 +657,6 @@ static void __process_mem_region(struct mem_vector *entry,
+ 			process_gb_huge_pages(®ion, image_size);
+ 		}
+ 
+-		/* Return if overlap extends to or past end of region. */
+-		if (overlap.start + overlap.size >= region.start + region.size)
+-			return;
+-
+ 		/* Clip off the overlapping region and start over. */
+ 		region.start = overlap.start + overlap.size;
+ 	}

commit ef7b07d59e2f18042622cecde0c7a89b60f33a89
+Author: Arvind Sankar 
+Date:   Tue Jul 28 18:57:09 2020 -0400
+
+    x86/kaslr: Drop redundant variable in __process_mem_region()
+    
+    region.size can be trimmed to store the portion of the region before the
+    overlap, instead of a separate mem_vector variable.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200728225722.67457-9-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
+index e978c3508814..8cc47faea56d 100644
+--- a/arch/x86/boot/compressed/kaslr.c
++++ b/arch/x86/boot/compressed/kaslr.c
+@@ -664,11 +664,8 @@ static void __process_mem_region(struct mem_vector *entry,
+ 
+ 		/* Store beginning of region if holds at least image_size. */
+ 		if (overlap.start >= region.start + image_size) {
+-			struct mem_vector beginning;
+-
+-			beginning.start = region.start;
+-			beginning.size = overlap.start - region.start;
+-			process_gb_huge_pages(&beginning, image_size);
++			region.size = overlap.start - region.start;
++			process_gb_huge_pages(®ion, image_size);
+ 		}
+ 
+ 		/* Return if overlap extends to or past end of region. */

commit ee435ee6490d147c1b9963cc8b331665e4cea634
+Author: Arvind Sankar 
+Date:   Tue Jul 28 18:57:08 2020 -0400
+
+    x86/kaslr: Eliminate 'start_orig' local variable from __process_mem_region()
+    
+    Set the region.size within the loop, which removes the need for
+    start_orig.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200728225722.67457-8-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
+index f2454eef5790..e978c3508814 100644
+--- a/arch/x86/boot/compressed/kaslr.c
++++ b/arch/x86/boot/compressed/kaslr.c
+@@ -623,7 +623,7 @@ static void __process_mem_region(struct mem_vector *entry,
+ 				 unsigned long image_size)
+ {
+ 	struct mem_vector region, overlap;
+-	unsigned long start_orig, end;
++	unsigned long end;
+ 
+ 	/* Ignore entries entirely below our minimum. */
+ 	if (entry->start + entry->size < minimum)
+@@ -635,12 +635,9 @@ static void __process_mem_region(struct mem_vector *entry,
+ 		return;
+ 
+ 	region.start = entry->start;
+-	region.size = end - entry->start;
+ 
+ 	/* Give up if slot area array is full. */
+ 	while (slot_area_index < MAX_SLOT_AREA) {
+-		start_orig = region.start;
+-
+ 		/* Potentially raise address to minimum location. */
+ 		if (region.start < minimum)
+ 			region.start = minimum;
+@@ -653,7 +650,7 @@ static void __process_mem_region(struct mem_vector *entry,
+ 			return;
+ 
+ 		/* Reduce size by any delta from the original address. */
+-		region.size -= region.start - start_orig;
++		region.size = end - region.start;
+ 
+ 		/* Return if region can't contain decompressed kernel */
+ 		if (region.size < image_size)
+@@ -679,7 +676,6 @@ static void __process_mem_region(struct mem_vector *entry,
+ 			return;
+ 
+ 		/* Clip off the overlapping region and start over. */
+-		region.size -= overlap.start - region.start + overlap.size;
+ 		region.start = overlap.start + overlap.size;
+ 	}
+ }

commit 3f9412c73053a5be311607e42560c1303a873be7
+Author: Arvind Sankar 
+Date:   Tue Jul 28 18:57:07 2020 -0400
+
+    x86/kaslr: Drop redundant cur_entry from __process_mem_region()
+    
+    cur_entry is only used as cur_entry.start + cur_entry.size, which is
+    always equal to end.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200728225722.67457-7-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
+index 848346fc0dbb..f2454eef5790 100644
+--- a/arch/x86/boot/compressed/kaslr.c
++++ b/arch/x86/boot/compressed/kaslr.c
+@@ -624,7 +624,6 @@ static void __process_mem_region(struct mem_vector *entry,
+ {
+ 	struct mem_vector region, overlap;
+ 	unsigned long start_orig, end;
+-	struct mem_vector cur_entry;
+ 
+ 	/* Ignore entries entirely below our minimum. */
+ 	if (entry->start + entry->size < minimum)
+@@ -634,11 +633,9 @@ static void __process_mem_region(struct mem_vector *entry,
+ 	end = min(entry->size + entry->start, mem_limit);
+ 	if (entry->start >= end)
+ 		return;
+-	cur_entry.start = entry->start;
+-	cur_entry.size = end - entry->start;
+ 
+-	region.start = cur_entry.start;
+-	region.size = cur_entry.size;
++	region.start = entry->start;
++	region.size = end - entry->start;
+ 
+ 	/* Give up if slot area array is full. */
+ 	while (slot_area_index < MAX_SLOT_AREA) {
+@@ -652,7 +649,7 @@ static void __process_mem_region(struct mem_vector *entry,
+ 		region.start = ALIGN(region.start, CONFIG_PHYSICAL_ALIGN);
+ 
+ 		/* Did we raise the address above the passed in memory entry? */
+-		if (region.start > cur_entry.start + cur_entry.size)
++		if (region.start > end)
+ 			return;
+ 
+ 		/* Reduce size by any delta from the original address. */

commit 8d1cf8595860f4807f4ff1f8f1fc53e7576e0d71
+Author: Arvind Sankar 
+Date:   Tue Jul 28 18:57:06 2020 -0400
+
+    x86/kaslr: Fix off-by-one error in __process_mem_region()
+    
+    In case of an overlap, the beginning of the region should be used even
+    if it is exactly image_size, not just strictly larger.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200728225722.67457-6-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
+index da45e66cb6e4..848346fc0dbb 100644
+--- a/arch/x86/boot/compressed/kaslr.c
++++ b/arch/x86/boot/compressed/kaslr.c
+@@ -669,7 +669,7 @@ static void __process_mem_region(struct mem_vector *entry,
+ 		}
+ 
+ 		/* Store beginning of region if holds at least image_size. */
+-		if (overlap.start > region.start + image_size) {
++		if (overlap.start >= region.start + image_size) {
+ 			struct mem_vector beginning;
+ 
+ 			beginning.start = region.start;

commit 451286940d95778e83fa7f97006316d995b4c4a8
+Author: Arvind Sankar 
+Date:   Mon Jul 27 19:07:57 2020 -0400
+
+    x86/kaslr: Initialize mem_limit to the real maximum address
+    
+    On 64-bit, the kernel must be placed below MAXMEM (64TiB with 4-level
+    paging or 4PiB with 5-level paging). This is currently not enforced by
+    KASLR, which thus implicitly relies on physical memory being limited to
+    less than 64TiB.
+    
+    On 32-bit, the limit is KERNEL_IMAGE_SIZE (512MiB). This is enforced by
+    special checks in __process_mem_region().
+    
+    Initialize mem_limit to the maximum (depending on architecture), instead
+    of ULLONG_MAX, and make sure the command-line arguments can only
+    decrease it. This makes the enforcement explicit on 64-bit, and
+    eliminates the 32-bit specific checks to keep the kernel below 512M.
+    
+    Check upfront to make sure the minimum address is below the limit before
+    doing any work.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ingo Molnar 
+    Acked-by: Kees Cook 
+    Link: https://lore.kernel.org/r/20200727230801.3468620-5-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
+index 1ab67a84a781..da45e66cb6e4 100644
+--- a/arch/x86/boot/compressed/kaslr.c
++++ b/arch/x86/boot/compressed/kaslr.c
+@@ -94,8 +94,11 @@ static unsigned long get_boot_seed(void)
+ static bool memmap_too_large;
+ 
+ 
+-/* Store memory limit specified by "mem=nn[KMG]" or "memmap=nn[KMG]" */
+-static unsigned long long mem_limit = ULLONG_MAX;
++/*
++ * Store memory limit: MAXMEM on 64-bit and KERNEL_IMAGE_SIZE on 32-bit.
++ * It may be reduced by "mem=nn[KMG]" or "memmap=nn[KMG]" command line options.
++ */
++static unsigned long long mem_limit;
+ 
+ /* Number of immovable memory regions */
+ static int num_immovable_mem;
+@@ -221,7 +224,7 @@ static void mem_avoid_memmap(enum parse_mode mode, char *str)
+ 
+ 		if (start == 0) {
+ 			/* Store the specified memory limit if size > 0 */
+-			if (size > 0)
++			if (size > 0 && size < mem_limit)
+ 				mem_limit = size;
+ 
+ 			continue;
+@@ -311,7 +314,8 @@ static void handle_mem_options(void)
+ 			if (mem_size == 0)
+ 				break;
+ 
+-			mem_limit = mem_size;
++			if (mem_size < mem_limit)
++				mem_limit = mem_size;
+ 		} else if (!strcmp(param, "efi_fake_mem")) {
+ 			mem_avoid_memmap(PARSE_EFI, val);
+ 		}
+@@ -322,7 +326,9 @@ static void handle_mem_options(void)
+ }
+ 
+ /*
+- * In theory, KASLR can put the kernel anywhere in the range of [16M, 64T).
++ * In theory, KASLR can put the kernel anywhere in the range of [16M, MAXMEM)
++ * on 64-bit, and [16M, KERNEL_IMAGE_SIZE) on 32-bit.
++ *
+  * The mem_avoid array is used to store the ranges that need to be avoided
+  * when KASLR searches for an appropriate random address. We must avoid any
+  * regions that are unsafe to overlap with during decompression, and other
+@@ -620,10 +626,6 @@ static void __process_mem_region(struct mem_vector *entry,
+ 	unsigned long start_orig, end;
+ 	struct mem_vector cur_entry;
+ 
+-	/* On 32-bit, ignore entries entirely above our maximum. */
+-	if (IS_ENABLED(CONFIG_X86_32) && entry->start >= KERNEL_IMAGE_SIZE)
+-		return;
+-
+ 	/* Ignore entries entirely below our minimum. */
+ 	if (entry->start + entry->size < minimum)
+ 		return;
+@@ -656,11 +658,6 @@ static void __process_mem_region(struct mem_vector *entry,
+ 		/* Reduce size by any delta from the original address. */
+ 		region.size -= region.start - start_orig;
+ 
+-		/* On 32-bit, reduce region size to fit within max size. */
+-		if (IS_ENABLED(CONFIG_X86_32) &&
+-		    region.start + region.size > KERNEL_IMAGE_SIZE)
+-			region.size = KERNEL_IMAGE_SIZE - region.start;
+-
+ 		/* Return if region can't contain decompressed kernel */
+ 		if (region.size < image_size)
+ 			return;
+@@ -845,15 +842,16 @@ static void process_e820_entries(unsigned long minimum,
+ static unsigned long find_random_phys_addr(unsigned long minimum,
+ 					   unsigned long image_size)
+ {
++	/* Bail out early if it's impossible to succeed. */
++	if (minimum + image_size > mem_limit)
++		return 0;
++
+ 	/* Check if we had too many memmaps. */
+ 	if (memmap_too_large) {
+ 		debug_putstr("Aborted memory entries scan (more than 4 memmap= args)!\n");
+ 		return 0;
+ 	}
+ 
+-	/* Make sure minimum is aligned. */
+-	minimum = ALIGN(minimum, CONFIG_PHYSICAL_ALIGN);
+-
+ 	if (process_efi_entries(minimum, image_size))
+ 		return slots_fetch_random();
+ 
+@@ -866,8 +864,6 @@ static unsigned long find_random_virt_addr(unsigned long minimum,
+ {
+ 	unsigned long slots, random_addr;
+ 
+-	/* Make sure minimum is aligned. */
+-	minimum = ALIGN(minimum, CONFIG_PHYSICAL_ALIGN);
+ 	/* Align image_size for easy slot calculations. */
+ 	image_size = ALIGN(image_size, CONFIG_PHYSICAL_ALIGN);
+ 
+@@ -914,6 +910,11 @@ void choose_random_location(unsigned long input,
+ 	/* Prepare to add new identity pagetables on demand. */
+ 	initialize_identity_maps();
+ 
++	if (IS_ENABLED(CONFIG_X86_32))
++		mem_limit = KERNEL_IMAGE_SIZE;
++	else
++		mem_limit = MAXMEM;
++
+ 	/* Record the various known unsafe memory ranges. */
+ 	mem_avoid_init(input, input_size, *output);
+ 
+@@ -923,6 +924,8 @@ void choose_random_location(unsigned long input,
+ 	 * location:
+ 	 */
+ 	min_addr = min(*output, 512UL << 20);
++	/* Make sure minimum is aligned. */
++	min_addr = ALIGN(min_addr, CONFIG_PHYSICAL_ALIGN);
+ 
+ 	/* Walk available memory entries to find a random address. */
+ 	random_addr = find_random_phys_addr(min_addr, output_size);

commit 08705365560a352d3f5b4f1f52270b4d4ff7911e
+Author: Arvind Sankar 
+Date:   Mon Jul 27 19:07:56 2020 -0400
+
+    x86/kaslr: Fix process_efi_entries comment
+    
+    Since commit:
+    
+      0982adc74673 ("x86/boot/KASLR: Work around firmware bugs by excluding EFI_BOOT_SERVICES_* and EFI_LOADER_* from KASLR's choice")
+    
+    process_efi_entries() will return true if we have an EFI memmap, not just
+    if it contained EFI_MEMORY_MORE_RELIABLE regions.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ingo Molnar 
+    Reviewed-by: Kees Cook 
+    Link: https://lore.kernel.org/r/20200727230801.3468620-4-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
+index c31f3a5ab9e4..1ab67a84a781 100644
+--- a/arch/x86/boot/compressed/kaslr.c
++++ b/arch/x86/boot/compressed/kaslr.c
+@@ -742,8 +742,8 @@ static bool process_mem_region(struct mem_vector *region,
+ 
+ #ifdef CONFIG_EFI
+ /*
+- * Returns true if mirror region found (and must have been processed
+- * for slots adding)
++ * Returns true if we processed the EFI memmap, which we prefer over the E820
++ * table if it is available.
+  */
+ static bool
+ process_efi_entries(unsigned long minimum, unsigned long image_size)

commit e2ee6173162b28053cb76b25887a0be9331c9e21
+Author: Arvind Sankar 
+Date:   Mon Jul 27 19:07:55 2020 -0400
+
+    x86/kaslr: Remove bogus warning and unnecessary goto
+    
+    Drop the warning on seeing "--" in handle_mem_options(). This will trigger
+    whenever one of the memory options is present in the command line
+    together with "--", but there's no problem if that is the case.
+    
+    Replace goto with break.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ingo Molnar 
+    Reviewed-by: Kees Cook 
+    Link: https://lore.kernel.org/r/20200727230801.3468620-3-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
+index e0f69f3625ae..c31f3a5ab9e4 100644
+--- a/arch/x86/boot/compressed/kaslr.c
++++ b/arch/x86/boot/compressed/kaslr.c
+@@ -295,10 +295,8 @@ static void handle_mem_options(void)
+ 	while (*args) {
+ 		args = next_arg(args, ¶m, &val);
+ 		/* Stop at -- */
+-		if (!val && strcmp(param, "--") == 0) {
+-			warn("Only '--' specified in cmdline");
+-			goto out;
+-		}
++		if (!val && strcmp(param, "--") == 0)
++			break;
+ 
+ 		if (!strcmp(param, "memmap")) {
+ 			mem_avoid_memmap(PARSE_MEMMAP, val);
+@@ -311,7 +309,7 @@ static void handle_mem_options(void)
+ 				continue;
+ 			mem_size = memparse(p, &p);
+ 			if (mem_size == 0)
+-				goto out;
++				break;
+ 
+ 			mem_limit = mem_size;
+ 		} else if (!strcmp(param, "efi_fake_mem")) {
+@@ -319,7 +317,6 @@ static void handle_mem_options(void)
+ 		}
+ 	}
+ 
+-out:
+ 	free(tmp_cmdline);
+ 	return;
+ }

commit 709709ac6410f4a14ded158a4b23b979e33e10fb
+Author: Arvind Sankar 
+Date:   Mon Jul 27 19:07:54 2020 -0400
+
+    x86/kaslr: Make command line handling safer
+    
+    Handle the possibility that the command line is NULL.
+    
+    Replace open-coded strlen with a function call.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ingo Molnar 
+    Reviewed-by: Kees Cook 
+    Link: https://lore.kernel.org/r/20200727230801.3468620-2-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
+index d7408af55738..e0f69f3625ae 100644
+--- a/arch/x86/boot/compressed/kaslr.c
++++ b/arch/x86/boot/compressed/kaslr.c
+@@ -268,15 +268,19 @@ static void parse_gb_huge_pages(char *param, char *val)
+ static void handle_mem_options(void)
+ {
+ 	char *args = (char *)get_cmd_line_ptr();
+-	size_t len = strlen((char *)args);
++	size_t len;
+ 	char *tmp_cmdline;
+ 	char *param, *val;
+ 	u64 mem_size;
+ 
++	if (!args)
++		return;
++
+ 	if (!strstr(args, "memmap=") && !strstr(args, "mem=") &&
+ 		!strstr(args, "hugepages"))
+ 		return;
+ 
++	len = strlen(args);
+ 	tmp_cmdline = malloc(len + 1);
+ 	if (!tmp_cmdline)
+ 		error("Failed to allocate space for tmp_cmdline");
+@@ -399,8 +403,7 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size,
+ {
+ 	unsigned long init_size = boot_params->hdr.init_size;
+ 	u64 initrd_start, initrd_size;
+-	u64 cmd_line, cmd_line_size;
+-	char *ptr;
++	unsigned long cmd_line, cmd_line_size;
+ 
+ 	/*
+ 	 * Avoid the region that is unsafe to overlap during
+@@ -421,16 +424,15 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size,
+ 	/* No need to set mapping for initrd, it will be handled in VO. */
+ 
+ 	/* Avoid kernel command line. */
+-	cmd_line  = (u64)boot_params->ext_cmd_line_ptr << 32;
+-	cmd_line |= boot_params->hdr.cmd_line_ptr;
++	cmd_line = get_cmd_line_ptr();
+ 	/* Calculate size of cmd_line. */
+-	ptr = (char *)(unsigned long)cmd_line;
+-	for (cmd_line_size = 0; ptr[cmd_line_size++];)
+-		;
+-	mem_avoid[MEM_AVOID_CMDLINE].start = cmd_line;
+-	mem_avoid[MEM_AVOID_CMDLINE].size = cmd_line_size;
+-	add_identity_map(mem_avoid[MEM_AVOID_CMDLINE].start,
+-			 mem_avoid[MEM_AVOID_CMDLINE].size);
++	if (cmd_line) {
++		cmd_line_size = strlen((char *)cmd_line) + 1;
++		mem_avoid[MEM_AVOID_CMDLINE].start = cmd_line;
++		mem_avoid[MEM_AVOID_CMDLINE].size = cmd_line_size;
++		add_identity_map(mem_avoid[MEM_AVOID_CMDLINE].start,
++				 mem_avoid[MEM_AVOID_CMDLINE].size);
++	}
+ 
+ 	/* Avoid boot parameters. */
+ 	mem_avoid[MEM_AVOID_BOOTPARAMS].start = (unsigned long)boot_params;

commit 587af649bcc04eb016822f209a975005c0092151
+Author: Arvind Sankar 
+Date:   Wed Jul 22 14:43:34 2020 -0400
+
+    x86/build: Move max-page-size option to LDFLAGS_vmlinux
+    
+    This option is only required for vmlinux on 64-bit, to enforce 2MiB
+    alignment, so set it in LDFLAGS_vmlinux instead of KBUILD_LDFLAGS. Also
+    drop the ld-option check: this option was added in binutils-2.18 and all
+    the other places that use it already don't have the check.
+    
+    This reduces the size of the intermediate ELF files
+    arch/x86/boot/setup.elf and arch/x86/realmode/rm/realmode.elf by about
+    2MiB each. The binary versions are unchanged.
+    
+    Move the LDFLAGS settings to all be together and just after CFLAGS
+    settings are done.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ingo Molnar 
+    Tested-by: Sedat Dilek 
+    Cc: Masahiro Yamada 
+    Cc: Michal Marek 
+    Link: https://lore.kernel.org/r/20200722184334.3785418-1-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/Makefile b/arch/x86/Makefile
+index 00e378de8bc0..1e634d7ee6eb 100644
+--- a/arch/x86/Makefile
++++ b/arch/x86/Makefile
+@@ -47,10 +47,6 @@ export REALMODE_CFLAGS
+ # e.g.: obj-y += foo_$(BITS).o
+ export BITS
+ 
+-ifdef CONFIG_X86_NEED_RELOCS
+-        LDFLAGS_vmlinux := --emit-relocs --discard-none
+-endif
+-
+ #
+ # Prevent GCC from generating any FP code by mistake.
+ #
+@@ -177,17 +173,6 @@ ifeq ($(ACCUMULATE_OUTGOING_ARGS), 1)
+ 	KBUILD_CFLAGS += $(call cc-option,-maccumulate-outgoing-args,)
+ endif
+ 
+-KBUILD_LDFLAGS := -m elf_$(UTS_MACHINE)
+-
+-#
+-# The 64-bit kernel must be aligned to 2MB.  Pass -z max-page-size=0x200000 to
+-# the linker to force 2MB page size regardless of the default page size used
+-# by the linker.
+-#
+-ifdef CONFIG_X86_64
+-KBUILD_LDFLAGS += $(call ld-option, -z max-page-size=0x200000)
+-endif
+-
+ # Workaround for a gcc prelease that unfortunately was shipped in a suse release
+ KBUILD_CFLAGS += -Wno-sign-compare
+ #
+@@ -207,6 +192,23 @@ ifdef CONFIG_RETPOLINE
+   endif
+ endif
+ 
++KBUILD_LDFLAGS := -m elf_$(UTS_MACHINE)
++
++ifdef CONFIG_X86_NEED_RELOCS
++LDFLAGS_vmlinux := --emit-relocs --discard-none
++else
++LDFLAGS_vmlinux :=
++endif
++
++#
++# The 64-bit kernel must be aligned to 2MB.  Pass -z max-page-size=0x200000 to
++# the linker to force 2MB page size regardless of the default page size used
++# by the linker.
++#
++ifdef CONFIG_X86_64
++LDFLAGS_vmlinux += -z max-page-size=0x200000
++endif
++
+ archscripts: scripts_basic
+ 	$(Q)$(MAKE) $(build)=arch/x86/tools relocs
+ 

commit 0a787b28b7a375ad9d5c77bc3922ae1a8305239e
+Author: Arvind Sankar 
+Date:   Thu Jul 23 19:15:42 2020 -0400
+
+    x86/mm: Drop unused MAX_PHYSADDR_BITS
+    
+    The macro is not used anywhere, and has an incorrect value (going by the
+    comment) on x86_64 since commit c898faf91b3e ("x86: 46 bit physical address
+    support on 64 bits")
+    
+    To avoid confusion, just remove the definition.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Thomas Gleixner 
+    Link: https://lkml.kernel.org/r/20200723231544.17274-2-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/include/asm/sparsemem.h b/arch/x86/include/asm/sparsemem.h
+index 199218719a86..6bfc878f6771 100644
+--- a/arch/x86/include/asm/sparsemem.h
++++ b/arch/x86/include/asm/sparsemem.h
+@@ -10,24 +10,20 @@
+  *    field of the struct page
+  *
+  * SECTION_SIZE_BITS		2^n: size of each section
+- * MAX_PHYSADDR_BITS		2^n: max size of physical address space
+- * MAX_PHYSMEM_BITS		2^n: how much memory we can have in that space
++ * MAX_PHYSMEM_BITS		2^n: max size of physical address space
+  *
+  */
+ 
+ #ifdef CONFIG_X86_32
+ # ifdef CONFIG_X86_PAE
+ #  define SECTION_SIZE_BITS	29
+-#  define MAX_PHYSADDR_BITS	36
+ #  define MAX_PHYSMEM_BITS	36
+ # else
+ #  define SECTION_SIZE_BITS	26
+-#  define MAX_PHYSADDR_BITS	32
+ #  define MAX_PHYSMEM_BITS	32
+ # endif
+ #else /* CONFIG_X86_32 */
+ # define SECTION_SIZE_BITS	27 /* matt - 128 is convenient right now */
+-# define MAX_PHYSADDR_BITS	(pgtable_l5_enabled() ? 52 : 44)
+ # define MAX_PHYSMEM_BITS	(pgtable_l5_enabled() ? 52 : 46)
+ #endif
+ 

commit da05b143a308bd6a7a444401f9732678ae63fc70
+Author: Arvind Sankar 
+Date:   Tue Jul 14 23:26:31 2020 -0400
+
+    x86/boot: Don't add the EFI stub to targets
+    
+    vmlinux-objs-y is added to targets, which currently means that the EFI
+    stub gets added to the targets as well. It shouldn't be added since it
+    is built elsewhere.
+    
+    This confuses Makefile.build which interprets the EFI stub as a target
+            $(obj)/$(objtree)/drivers/firmware/efi/libstub/lib.a
+    and will create drivers/firmware/efi/libstub/ underneath
+    arch/x86/boot/compressed, to hold this supposed target, if building
+    out-of-tree. [0]
+    
+    Fix this by pulling the stub out of vmlinux-objs-y into efi-obj-y.
+    
+    [0] See scripts/Makefile.build near the end:
+        # Create directories for object files if they do not exist
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Thomas Gleixner 
+    Reviewed-by: Masahiro Yamada 
+    Acked-by: Ard Biesheuvel 
+    Link: https://lkml.kernel.org/r/20200715032631.1562882-1-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
+index 7619742f91c9..5a828fde7a42 100644
+--- a/arch/x86/boot/compressed/Makefile
++++ b/arch/x86/boot/compressed/Makefile
+@@ -90,8 +90,8 @@ endif
+ 
+ vmlinux-objs-$(CONFIG_ACPI) += $(obj)/acpi.o
+ 
+-vmlinux-objs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
+ vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_thunk_$(BITS).o
++efi-obj-$(CONFIG_EFI_STUB) = $(objtree)/drivers/firmware/efi/libstub/lib.a
+ 
+ # The compressed kernel is built with -fPIC/-fPIE so that a boot loader
+ # can place it anywhere in memory and it will still run. However, since
+@@ -115,7 +115,7 @@ endef
+ quiet_cmd_check-and-link-vmlinux = LD      $@
+       cmd_check-and-link-vmlinux = $(cmd_check_data_rel); $(cmd_ld)
+ 
+-$(obj)/vmlinux: $(vmlinux-objs-y) FORCE
++$(obj)/vmlinux: $(vmlinux-objs-y) $(efi-obj-y) FORCE
+ 	$(call if_changed,check-and-link-vmlinux)
+ 
+ OBJCOPYFLAGS_vmlinux.bin :=  -R .comment -S

commit 59476f80d8781a84e25f0cbcf378ccab1ad7abf8
+Author: Arvind Sankar 
+Date:   Thu Jun 18 16:43:15 2020 -0400
+
+    efi/x86: Only copy upto the end of setup_header
+    
+    When copying the setup_header into the boot_params buffer, only the data
+    that is actually part of the setup_header should be copied.
+    
+    efi_pe_entry() currently copies the entire second sector, which
+    initializes some of the fields in boot_params beyond the setup_header
+    with garbage (i.e. part of the real-mode boot code gets copied into
+    those fields).
+    
+    This does not cause any issues currently because the fields that are
+    overwritten are padding, BIOS EDD information that won't get used, and
+    the E820 table which will get properly filled in later.
+    
+    Fix this to only copy data that is actually part of the setup_header
+    structure.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
+index 37e82bf397aa..3672539cb96e 100644
+--- a/drivers/firmware/efi/libstub/x86-stub.c
++++ b/drivers/firmware/efi/libstub/x86-stub.c
+@@ -8,6 +8,7 @@
+ 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ #include 
+@@ -388,8 +389,9 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
+ 
+ 	hdr = &boot_params->hdr;
+ 
+-	/* Copy the second sector to boot_params */
+-	memcpy(&hdr->jump, image_base + 512, 512);
++	/* Copy the setup header from the second sector to boot_params */
++	memcpy(&hdr->jump, image_base + 512,
++	       sizeof(struct setup_header) - offsetof(struct setup_header, jump));
+ 
+ 	/*
+ 	 * Fill out some of the header fields ourselves because the

commit 0bda49f30ca48998102eb0a0b53970c3a3558be0
+Author: Arvind Sankar 
+Date:   Thu Jun 18 15:10:59 2020 -0400
+
+    efi/x86: Remove unused variables
+    
+    Commit
+    
+      987053a30016 ("efi/x86: Move command-line initrd loading to efi_main")
+    
+    made the ramdisk_addr/ramdisk_size variables in efi_pe_entry unused, but
+    neglected to delete them.
+    
+    Delete these unused variables.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
+index 5a48d996ed71..37e82bf397aa 100644
+--- a/drivers/firmware/efi/libstub/x86-stub.c
++++ b/drivers/firmware/efi/libstub/x86-stub.c
+@@ -361,8 +361,6 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
+ 	int options_size = 0;
+ 	efi_status_t status;
+ 	char *cmdline_ptr;
+-	unsigned long ramdisk_addr;
+-	unsigned long ramdisk_size;
+ 
+ 	efi_system_table = sys_table_arg;
+ 

commit 41d90b0c1108d1e46c48cf79964636c553844f4c
+Author: Arvind Sankar 
+Date:   Wed Jun 17 09:19:57 2020 -0400
+
+    efi/x86: Setup stack correctly for efi_pe_entry
+    
+    Commit
+    
+      17054f492dfd ("efi/x86: Implement mixed mode boot without the handover protocol")
+    
+    introduced a new entry point for the EFI stub to be booted in mixed mode
+    on 32-bit firmware.
+    
+    When entered via efi32_pe_entry, control is first transferred to
+    startup_32 to setup for the switch to long mode, and then the EFI stub
+    proper is entered via efi_pe_entry. efi_pe_entry is an MS ABI function,
+    and the ABI requires 32 bytes of shadow stack space to be allocated by
+    the caller, as well as the stack being aligned to 8 mod 16 on entry.
+    
+    Allocate 40 bytes on the stack before switching to 64-bit mode when
+    calling efi_pe_entry to account for this.
+    
+    For robustness, explicitly align boot_stack_end to 16 bytes. It is
+    currently implicitly aligned since .bss is cacheline-size aligned,
+    head_64.o is the first object file with a .bss section, and the heap and
+    boot sizes are aligned.
+    
+    Fixes: 17054f492dfd ("efi/x86: Implement mixed mode boot without the handover protocol")
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200617131957.2507632-1-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index e821a7d7d5c4..97d37f0a34f5 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -213,7 +213,6 @@ SYM_FUNC_START(startup_32)
+ 	 * We place all of the values on our mini stack so lret can
+ 	 * used to perform that far jump.
+ 	 */
+-	pushl	$__KERNEL_CS
+ 	leal	startup_64(%ebp), %eax
+ #ifdef CONFIG_EFI_MIXED
+ 	movl	efi32_boot_args(%ebp), %edi
+@@ -224,11 +223,20 @@ SYM_FUNC_START(startup_32)
+ 	movl	efi32_boot_args+8(%ebp), %edx	// saved bootparams pointer
+ 	cmpl	$0, %edx
+ 	jnz	1f
++	/*
++	 * efi_pe_entry uses MS calling convention, which requires 32 bytes of
++	 * shadow space on the stack even if all arguments are passed in
++	 * registers. We also need an additional 8 bytes for the space that
++	 * would be occupied by the return address, and this also results in
++	 * the correct stack alignment for entry.
++	 */
++	subl	$40, %esp
+ 	leal	efi_pe_entry(%ebp), %eax
+ 	movl	%edi, %ecx			// MS calling convention
+ 	movl	%esi, %edx
+ 1:
+ #endif
++	pushl	$__KERNEL_CS
+ 	pushl	%eax
+ 
+ 	/* Enter paged protected Mode, activating Long Mode */
+@@ -784,6 +792,7 @@ SYM_DATA_LOCAL(boot_heap,	.fill BOOT_HEAP_SIZE, 1, 0)
+ 
+ SYM_DATA_START_LOCAL(boot_stack)
+ 	.fill BOOT_STACK_SIZE, 1, 0
++	.balign 16
+ SYM_DATA_END_LABEL(boot_stack, SYM_L_LOCAL, boot_stack_end)
+ 
+ /*

commit ff58155ca4fa7e931f34d948fa09fe14c6a66116
+Author: Arvind Sankar 
+Date:   Tue Jun 16 18:25:47 2020 -0400
+
+    x86/purgatory: Add -fno-stack-protector
+    
+    The purgatory Makefile removes -fstack-protector options if they were
+    configured in, but does not currently add -fno-stack-protector.
+    
+    If gcc was configured with the --enable-default-ssp configure option,
+    this results in the stack protector still being enabled for the
+    purgatory (absent distro-specific specs files that might disable it
+    again for freestanding compilations), if the main kernel is being
+    compiled with stack protection enabled (if it's disabled for the main
+    kernel, the top-level Makefile will add -fno-stack-protector).
+    
+    This will break the build since commit
+      e4160b2e4b02 ("x86/purgatory: Fail the build if purgatory.ro has missing symbols")
+    and prior to that would have caused runtime failure when trying to use
+    kexec.
+    
+    Explicitly add -fno-stack-protector to avoid this, as done in other
+    Makefiles that need to disable the stack protector.
+    
+    Reported-by: Gabriel C 
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile
+index b04e6e72a592..088bd764e0b7 100644
+--- a/arch/x86/purgatory/Makefile
++++ b/arch/x86/purgatory/Makefile
+@@ -34,6 +34,7 @@ KCOV_INSTRUMENT := n
+ PURGATORY_CFLAGS_REMOVE := -mcmodel=kernel
+ PURGATORY_CFLAGS := -mcmodel=large -ffreestanding -fno-zero-initialized-in-bss
+ PURGATORY_CFLAGS += $(DISABLE_STACKLEAK_PLUGIN) -DDISABLE_BRANCH_PROFILING
++PURGATORY_CFLAGS += $(call cc-option,-fno-stack-protector)
+ 
+ # Default KBUILD_CFLAGS can have -pg option set when FTRACE is enabled. That
+ # in turn leaves some undefined symbols like __fentry__ in purgatory and not

commit 5435f73d5c4a1b7504356876e69ba52de83f4975
+Author: Arvind Sankar 
+Date:   Fri Jun 5 11:06:38 2020 -0400
+
+    efi/x86: Fix build with gcc 4
+    
+    Commit
+    
+      bbf8e8b0fe04 ("efi/libstub: Optimize for size instead of speed")
+    
+    changed the optimization level for the EFI stub to -Os from -O2.
+    
+    Andrey Ignatov reports that this breaks the build with gcc 4.8.5.
+    
+    Testing on godbolt.org, the combination of -Os,
+    -fno-asynchronous-unwind-tables, and ms_abi functions doesn't work,
+    failing with the error:
+      sorry, unimplemented: ms_abi attribute requires
+      -maccumulate-outgoing-args or subtarget optimization implying it
+    
+    This does appear to work with gcc 4.9 onwards.
+    
+    Add -maccumulate-outgoing-args explicitly to unbreak the build with
+    pre-4.9 versions of gcc.
+    
+    Reported-by: Andrey Ignatov 
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200605150638.1011637-1-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
+index 75daaf20374e..4cce372edaf4 100644
+--- a/drivers/firmware/efi/libstub/Makefile
++++ b/drivers/firmware/efi/libstub/Makefile
+@@ -6,7 +6,8 @@
+ # enabled, even if doing so doesn't break the build.
+ #
+ cflags-$(CONFIG_X86_32)		:= -march=i386
+-cflags-$(CONFIG_X86_64)		:= -mcmodel=small
++cflags-$(CONFIG_X86_64)		:= -mcmodel=small \
++				   $(call cc-option,-maccumulate-outgoing-args)
+ cflags-$(CONFIG_X86)		+= -m$(BITS) -D__KERNEL__ \
+ 				   -fPIC -fno-strict-aliasing -mno-red-zone \
+ 				   -mno-mmx -mno-sse -fshort-wchar \

commit 7b16994437c7359832dd51d66c5c387995a91438
+Author: Arvind Sankar 
+Date:   Thu Jun 11 18:03:39 2020 -0400
+
+    Makefile: Improve compressed debug info support detection
+    
+    Commit
+      10e68b02c861 ("Makefile: support compressed debug info")
+    added support for compressed debug sections.
+    
+    Support is detected by checking
+    - does the compiler support -gz=zlib
+    - does the assembler support --compressed-debug-sections=zlib
+    - does the linker support --compressed-debug-sections=zlib
+    
+    However, the gcc driver's support for this option is somewhat
+    convoluted. The driver's builtin specs are set based on the version of
+    binutils that it was configured with. It reports an error if the
+    configure-time linker/assembler (i.e., not necessarily the actual
+    assembler that will be run) do not support the option, but only if the
+    assembler (or linker) is actually invoked when -gz=zlib is passed.
+    
+    The cc-option check in scripts/Kconfig.include does not invoke the
+    assembler, so the gcc driver reports success even if it does not support
+    the option being passed to the assembler.
+    
+    Because the as-option check passes the option directly to the assembler
+    via -Wa,--compressed-debug-sections=zlib, the gcc driver does not see
+    this option and will never report an error.
+    
+    Combined with an installed version of binutils that is more recent than
+    the one the compiler was built with, it is possible for all three tests
+    to succeed, yet an actual compilation with -gz=zlib to fail.
+    
+    Moreover, it is unnecessary to explicitly pass
+    --compressed-debug-sections=zlib to the assembler via -Wa, since the
+    driver will do that automatically when it supports -gz=zlib.
+    
+    Convert the as-option to just -gz=zlib, simplifying it as well as
+    performing a better test of the gcc driver's capabilities.
+    
+    Reported-by: kernel test robot 
+    Signed-off-by: Arvind Sankar 
+    Reviewed-by: Nick Desaulniers 
+    Signed-off-by: Masahiro Yamada 
+
+diff --git a/Makefile b/Makefile
+index ae5d8220f431..29abe44ada91 100644
+--- a/Makefile
++++ b/Makefile
+@@ -828,7 +828,7 @@ endif
+ 
+ ifdef CONFIG_DEBUG_INFO_COMPRESSED
+ DEBUG_CFLAGS	+= -gz=zlib
+-KBUILD_AFLAGS	+= -Wa,--compress-debug-sections=zlib
++KBUILD_AFLAGS	+= -gz=zlib
+ KBUILD_LDFLAGS	+= --compress-debug-sections=zlib
+ endif
+ 
+diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
+index d74ac0fd6b2d..96999d4d2dda 100644
+--- a/lib/Kconfig.debug
++++ b/lib/Kconfig.debug
+@@ -229,7 +229,7 @@ config DEBUG_INFO_COMPRESSED
+ 	bool "Compressed debugging information"
+ 	depends on DEBUG_INFO
+ 	depends on $(cc-option,-gz=zlib)
+-	depends on $(as-option,-Wa$(comma)--compress-debug-sections=zlib)
++	depends on $(as-option,-gz=zlib)
+ 	depends on $(ld-option,--compress-debug-sections=zlib)
+ 	help
+ 	  Compress the debug information using zlib.  Requires GCC 5.0+ or Clang

commit e9524fb97ab5b41b85e1d3408f8e513433798f3c
+Author: Arvind Sankar 
+Date:   Wed May 27 19:26:02 2020 -0400
+
+    efi/x86: Don't blow away existing initrd
+    
+    Commit
+    
+      987053a30016 ("efi/x86: Move command-line initrd loading to efi_main")
+    
+    moved the command-line initrd loading into efi_main(), with a check
+    to ensure that it was attempted only if the EFI stub was booted via
+    efi_pe_entry rather than the EFI handover entry.
+    
+    However, in the case where it was booted via handover entry, and thus an
+    initrd may have already been loaded by the bootloader, it then wrote 0
+    for the initrd address and size, removing any existing initrd.
+    
+    Fix this by checking if size is positive before setting the fields in
+    the bootparams structure.
+    
+    Fixes: 987053a30016 ("efi/x86: Move command-line initrd loading to efi_main")
+    Reported-by: Dan Williams 
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Borislav Petkov 
+    Reviewed-by: Ard Biesheuvel 
+    Tested-by: Dan Williams 
+    Link: https://lkml.kernel.org/r/20200527232602.21596-1-nivedita@alum.mit.edu
+
+diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
+index 99a0cfb0c7ad..5a48d996ed71 100644
+--- a/drivers/firmware/efi/libstub/x86-stub.c
++++ b/drivers/firmware/efi/libstub/x86-stub.c
+@@ -768,10 +768,12 @@ unsigned long efi_main(efi_handle_t handle,
+ 			efi_err("Failed to load initrd!\n");
+ 			goto fail;
+ 		}
+-		efi_set_u64_split(addr, &hdr->ramdisk_image,
+-				  &boot_params->ext_ramdisk_image);
+-		efi_set_u64_split(size, &hdr->ramdisk_size,
+-				  &boot_params->ext_ramdisk_size);
++		if (size > 0) {
++			efi_set_u64_split(addr, &hdr->ramdisk_image,
++					  &boot_params->ext_ramdisk_image);
++			efi_set_u64_split(size, &hdr->ramdisk_size,
++					  &boot_params->ext_ramdisk_size);
++		}
+ 	}
+ 
+ 	/*

commit 9241dfe7f2772fc73c82eb950afb1c795d2c012c
+Author: Arvind Sankar 
+Date:   Sat May 23 18:15:13 2020 -0400
+
+    efi/x86: Drop the special GDT for the EFI thunk
+    
+    Instead of using efi_gdt64 to switch back to 64-bit mode and then
+    switching to the real boot-time GDT, just switch to the boot-time GDT
+    directly. The two GDT's are identical other than efi_gdt64 not including
+    the 32-bit code segment.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200523221513.1642948-1-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/arch/x86/boot/compressed/efi_thunk_64.S b/arch/x86/boot/compressed/efi_thunk_64.S
+index 2b2049259619..c4bb0f9363f5 100644
+--- a/arch/x86/boot/compressed/efi_thunk_64.S
++++ b/arch/x86/boot/compressed/efi_thunk_64.S
+@@ -28,8 +28,6 @@ SYM_FUNC_START(__efi64_thunk)
+ 	push	%rbx
+ 
+ 	leaq	1f(%rip), %rbp
+-	leaq	efi_gdt64(%rip), %rbx
+-	movl	%ebx, 2(%rbx)		/* Fixup the gdt base address */
+ 
+ 	movl	%ds, %eax
+ 	push	%rax
+@@ -48,7 +46,8 @@ SYM_FUNC_START(__efi64_thunk)
+ 	movl	%r8d, 0xc(%rsp)
+ 	movl	%r9d, 0x10(%rsp)
+ 
+-	sgdt	0x14(%rsp)
++	leaq	0x14(%rsp), %rbx
++	sgdt	(%rbx)
+ 
+ 	/*
+ 	 * Switch to gdt with 32-bit segments. This is the firmware GDT
+@@ -68,8 +67,7 @@ SYM_FUNC_START(__efi64_thunk)
+ 	pushq	%rax
+ 	lretq
+ 
+-1:	lgdt	0x14(%rsp)
+-	addq	$32, %rsp
++1:	addq	$32, %rsp
+ 	movq	%rdi, %rax
+ 
+ 	pop	%rbx
+@@ -175,14 +173,3 @@ SYM_DATA_END(efi32_boot_cs)
+ SYM_DATA_START(efi32_boot_ds)
+ 	.word	0
+ SYM_DATA_END(efi32_boot_ds)
+-
+-SYM_DATA_START(efi_gdt64)
+-	.word	efi_gdt64_end - efi_gdt64
+-	.long	0			/* Filled out by user */
+-	.word	0
+-	.quad	0x0000000000000000	/* NULL descriptor */
+-	.quad	0x00af9a000000ffff	/* __KERNEL_CS */
+-	.quad	0x00cf92000000ffff	/* __KERNEL_DS */
+-	.quad	0x0080890000000000	/* TS descriptor */
+-	.quad   0x0000000000000000	/* TS continued */
+-SYM_DATA_END_LABEL(efi_gdt64, SYM_L_LOCAL, efi_gdt64_end)

commit 67d631b7c05eff955ccff4139327f0f92a5117e5
+Author: Arvind Sankar 
+Date:   Sat Feb 29 18:11:20 2020 -0500
+
+    x86/mm: Stop printing BRK addresses
+    
+    This currently leaks kernel physical addresses into userspace.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Borislav Petkov 
+    Acked-by: Kees Cook 
+    Acked-by: Dave Hansen 
+    Link: https://lkml.kernel.org/r/20200229231120.1147527-1-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
+index 1bba16c5742b..a573a3e63f02 100644
+--- a/arch/x86/mm/init.c
++++ b/arch/x86/mm/init.c
+@@ -121,8 +121,6 @@ __ref void *alloc_low_pages(unsigned int num)
+ 	} else {
+ 		pfn = pgt_buf_end;
+ 		pgt_buf_end += num;
+-		printk(KERN_DEBUG "BRK [%#010lx, %#010lx] PGTABLE\n",
+-			pfn << PAGE_SHIFT, (pgt_buf_end << PAGE_SHIFT) - 1);
+ 	}
+ 
+ 	for (i = 0; i < num; i++) {

commit 80b1bfe1cb2f20225fb2d8f11d44af4a9d765396
+Author: Arvind Sankar 
+Date:   Wed May 20 20:29:21 2020 -0400
+
+    efi/libstub: Don't parse overlong command lines
+    
+    Check if the command line passed in is larger than COMMAND_LINE_SIZE,
+    and truncate it to the last full argument if so.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200521002921.69650-1-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
+index 9fb107e9355b..dbfaf8dcdda2 100644
+--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
++++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
+@@ -9,10 +9,12 @@
+ 
+ #include 
+ 
++#include 
+ #include 
+ #include 
+ #include  /* For CONSOLE_LOGLEVEL_* */
+ #include 
++#include 
+ 
+ #include "efistub.h"
+ 
+@@ -217,22 +219,33 @@ char *efi_convert_cmdline(efi_loaded_image_t *image,
+ 	unsigned long cmdline_addr = 0;
+ 	int options_chars = efi_table_attr(image, load_options_size) / 2;
+ 	const u16 *options = efi_table_attr(image, load_options);
+-	int options_bytes = 0;  /* UTF-8 bytes */
++	int options_bytes = 0, safe_options_bytes = 0;  /* UTF-8 bytes */
++	bool in_quote = false;
+ 	efi_status_t status;
+ 
+ 	if (options) {
+ 		s2 = options;
+-		while (options_chars--) {
++		while (options_bytes < COMMAND_LINE_SIZE && options_chars--) {
+ 			u16 c = *s2++;
+ 
+-			if (c == L'\0' || c == L'\n')
+-				break;
++			if (c < 0x80) {
++				if (c == L'\0' || c == L'\n')
++					break;
++				if (c == L'"')
++					in_quote = !in_quote;
++				else if (!in_quote && isspace((char)c))
++					safe_options_bytes = options_bytes;
++
++				options_bytes++;
++				continue;
++			}
++
+ 			/*
+ 			 * Get the number of UTF-8 bytes corresponding to a
+ 			 * UTF-16 character.
+ 			 * The first part handles everything in the BMP.
+ 			 */
+-			options_bytes += 1 + (c >= 0x80) + (c >= 0x800);
++			options_bytes += 2 + (c >= 0x800);
+ 			/*
+ 			 * Add one more byte for valid surrogate pairs. Invalid
+ 			 * surrogates will be replaced with 0xfffd and take up
+@@ -253,6 +266,11 @@ char *efi_convert_cmdline(efi_loaded_image_t *image,
+ 				}
+ 			}
+ 		}
++		if (options_bytes >= COMMAND_LINE_SIZE) {
++			options_bytes = safe_options_bytes;
++			efi_err("Command line is too long: truncated to %d bytes\n",
++				options_bytes);
++		}
+ 	}
+ 
+ 	options_bytes++;	/* NUL termination */

commit 04b24409b42a9fcae2379a6ddcf9c827b9af7a45
+Author: Arvind Sankar 
+Date:   Mon May 18 15:07:16 2020 -0400
+
+    efi/libstub: Use snprintf with %ls to convert the command line
+    
+    Now we can use snprintf to do the UTF-16 to UTF-8 translation for the
+    command line.
+    
+    Drop the special "zero" trick to handle an empty command line. This was
+    unnecessary even before this since with options_chars == 0,
+    efi_utf16_to_utf8 would not have accessed options at all. snprintf won't
+    access it either with a precision of 0.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200518190716.751506-25-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
+index 4d544f395403..9fb107e9355b 100644
+--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
++++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
+@@ -205,46 +205,6 @@ efi_status_t efi_parse_options(char const *cmdline)
+ 	return EFI_SUCCESS;
+ }
+ 
+-/*
+- * Convert an UTF-16 string, not necessarily null terminated, to UTF-8.
+- */
+-static u8 *efi_utf16_to_utf8(u8 *dst, const u16 *src, int n)
+-{
+-	unsigned int c;
+-
+-	while (n--) {
+-		c = *src++;
+-		if (n && c >= 0xd800 && c <= 0xdbff &&
+-		    *src >= 0xdc00 && *src <= 0xdfff) {
+-			c = 0x10000 + ((c & 0x3ff) << 10) + (*src & 0x3ff);
+-			src++;
+-			n--;
+-		}
+-		if (c >= 0xd800 && c <= 0xdfff)
+-			c = 0xfffd; /* Unmatched surrogate */
+-		if (c < 0x80) {
+-			*dst++ = c;
+-			continue;
+-		}
+-		if (c < 0x800) {
+-			*dst++ = 0xc0 + (c >> 6);
+-			goto t1;
+-		}
+-		if (c < 0x10000) {
+-			*dst++ = 0xe0 + (c >> 12);
+-			goto t2;
+-		}
+-		*dst++ = 0xf0 + (c >> 18);
+-		*dst++ = 0x80 + ((c >> 12) & 0x3f);
+-	t2:
+-		*dst++ = 0x80 + ((c >> 6) & 0x3f);
+-	t1:
+-		*dst++ = 0x80 + (c & 0x3f);
+-	}
+-
+-	return dst;
+-}
+-
+ /*
+  * Convert the unicode UEFI command line to ASCII to pass to kernel.
+  * Size of memory allocated return in *cmd_line_len.
+@@ -254,18 +214,15 @@ char *efi_convert_cmdline(efi_loaded_image_t *image,
+ 			  int *cmd_line_len, unsigned long max_addr)
+ {
+ 	const u16 *s2;
+-	u8 *s1 = NULL;
+ 	unsigned long cmdline_addr = 0;
+-	int load_options_chars = efi_table_attr(image, load_options_size) / 2;
++	int options_chars = efi_table_attr(image, load_options_size) / 2;
+ 	const u16 *options = efi_table_attr(image, load_options);
+ 	int options_bytes = 0;  /* UTF-8 bytes */
+-	int options_chars = 0;  /* UTF-16 chars */
+ 	efi_status_t status;
+-	u16 zero = 0;
+ 
+ 	if (options) {
+ 		s2 = options;
+-		while (options_chars < load_options_chars) {
++		while (options_chars--) {
+ 			u16 c = *s2++;
+ 
+ 			if (c == L'\0' || c == L'\n')
+@@ -276,7 +233,6 @@ char *efi_convert_cmdline(efi_loaded_image_t *image,
+ 			 * The first part handles everything in the BMP.
+ 			 */
+ 			options_bytes += 1 + (c >= 0x80) + (c >= 0x800);
+-			options_chars++;
+ 			/*
+ 			 * Add one more byte for valid surrogate pairs. Invalid
+ 			 * surrogates will be replaced with 0xfffd and take up
+@@ -288,35 +244,25 @@ char *efi_convert_cmdline(efi_loaded_image_t *image,
+ 				 * we must ignore it since we can't access the
+ 				 * low surrogate.
+ 				 */
+-				if (options_chars == load_options_chars) {
++				if (!options_chars) {
+ 					options_bytes -= 3;
+-					options_chars--;
+-					break;
+ 				} else if ((*s2 & 0xfc00) == 0xdc00) {
+ 					options_bytes++;
+-					options_chars++;
++					options_chars--;
+ 					s2++;
+ 				}
+ 			}
+ 		}
+ 	}
+ 
+-	if (!options_chars) {
+-		/* No command line options, so return empty string*/
+-		options = &zero;
+-	}
+-
+ 	options_bytes++;	/* NUL termination */
+ 
+ 	status = efi_allocate_pages(options_bytes, &cmdline_addr, max_addr);
+ 	if (status != EFI_SUCCESS)
+ 		return NULL;
+ 
+-	s1 = (u8 *)cmdline_addr;
+-	s2 = (const u16 *)options;
+-
+-	s1 = efi_utf16_to_utf8(s1, s2, options_chars);
+-	*s1 = '\0';
++	snprintf((char *)cmdline_addr, options_bytes, "%.*ls",
++		 options_bytes - 1, options);
+ 
+ 	*cmd_line_len = options_bytes;
+ 	return (char *)cmdline_addr;

commit 15c316bcbc23b777eae4e21f129526190aa20af1
+Author: Arvind Sankar 
+Date:   Mon May 18 15:07:15 2020 -0400
+
+    efi/libstub: Get the exact UTF-8 length
+    
+    efi_convert_cmdline currently overestimates the length of the equivalent
+    UTF-8 encoding.
+    
+    snprintf can now be used to do the conversion to UTF-8, however, it does
+    not have a way to specify the size of the UTF-16 string, only the size
+    of the resulting UTF-8 string. So in order to use it, we need to
+    precalculate the exact UTF-8 size.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200518190716.751506-24-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
+index 0d0007355c1e..4d544f395403 100644
+--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
++++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
+@@ -205,15 +205,6 @@ efi_status_t efi_parse_options(char const *cmdline)
+ 	return EFI_SUCCESS;
+ }
+ 
+-/*
+- * Get the number of UTF-8 bytes corresponding to an UTF-16 character.
+- * This overestimates for surrogates, but that is okay.
+- */
+-static int efi_utf8_bytes(u16 c)
+-{
+-	return 1 + (c >= 0x80) + (c >= 0x800);
+-}
+-
+ /*
+  * Convert an UTF-16 string, not necessarily null terminated, to UTF-8.
+  */
+@@ -274,10 +265,39 @@ char *efi_convert_cmdline(efi_loaded_image_t *image,
+ 
+ 	if (options) {
+ 		s2 = options;
+-		while (*s2 && *s2 != '\n'
+-		       && options_chars < load_options_chars) {
+-			options_bytes += efi_utf8_bytes(*s2++);
++		while (options_chars < load_options_chars) {
++			u16 c = *s2++;
++
++			if (c == L'\0' || c == L'\n')
++				break;
++			/*
++			 * Get the number of UTF-8 bytes corresponding to a
++			 * UTF-16 character.
++			 * The first part handles everything in the BMP.
++			 */
++			options_bytes += 1 + (c >= 0x80) + (c >= 0x800);
+ 			options_chars++;
++			/*
++			 * Add one more byte for valid surrogate pairs. Invalid
++			 * surrogates will be replaced with 0xfffd and take up
++			 * only 3 bytes.
++			 */
++			if ((c & 0xfc00) == 0xd800) {
++				/*
++				 * If the very last word is a high surrogate,
++				 * we must ignore it since we can't access the
++				 * low surrogate.
++				 */
++				if (options_chars == load_options_chars) {
++					options_bytes -= 3;
++					options_chars--;
++					break;
++				} else if ((*s2 & 0xfc00) == 0xdc00) {
++					options_bytes++;
++					options_chars++;
++					s2++;
++				}
++			}
+ 		}
+ 	}
+ 

commit a713979e443d4036e76e13bb3d30e9fa248915aa
+Author: Arvind Sankar 
+Date:   Mon May 18 15:07:14 2020 -0400
+
+    efi/libstub: Use %ls for filename
+    
+    efi_printk can now handle the UTF-16 filename, so print it using efi_err
+    instead of a separate efi_char16_puts call.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200518190716.751506-23-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/file.c b/drivers/firmware/efi/libstub/file.c
+index 933536c5236a..2005e33b33d5 100644
+--- a/drivers/firmware/efi/libstub/file.c
++++ b/drivers/firmware/efi/libstub/file.c
+@@ -46,9 +46,7 @@ static efi_status_t efi_open_file(efi_file_protocol_t *volume,
+ 
+ 	status = volume->open(volume, &fh, fi->filename, EFI_FILE_MODE_READ, 0);
+ 	if (status != EFI_SUCCESS) {
+-		efi_err("Failed to open file: ");
+-		efi_char16_puts(fi->filename);
+-		efi_puts("\n");
++		efi_err("Failed to open file: %ls\n", fi->filename);
+ 		return status;
+ 	}
+ 

commit 4b75bd363de3f3429c62359be4e4aa4da7fa233b
+Author: Arvind Sankar 
+Date:   Mon May 18 15:07:13 2020 -0400
+
+    efi/libstub: Add UTF-8 decoding to efi_puts
+    
+    In order to be able to use the UTF-16 support added to vsprintf in the
+    previous commit, enhance efi_puts to decode UTF-8 into UTF-16. Invalid
+    UTF-8 encodings are passed through unchanged.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200518190716.751506-22-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
+index f338d149aaa5..0d0007355c1e 100644
+--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
++++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
+@@ -36,17 +36,74 @@ void efi_char16_puts(efi_char16_t *str)
+ 		       output_string, str);
+ }
+ 
++static
++u32 utf8_to_utf32(const u8 **s8)
++{
++	u32 c32;
++	u8 c0, cx;
++	size_t clen, i;
++
++	c0 = cx = *(*s8)++;
++	/*
++	 * The position of the most-significant 0 bit gives us the length of
++	 * a multi-octet encoding.
++	 */
++	for (clen = 0; cx & 0x80; ++clen)
++		cx <<= 1;
++	/*
++	 * If the 0 bit is in position 8, this is a valid single-octet
++	 * encoding. If the 0 bit is in position 7 or positions 1-3, the
++	 * encoding is invalid.
++	 * In either case, we just return the first octet.
++	 */
++	if (clen < 2 || clen > 4)
++		return c0;
++	/* Get the bits from the first octet. */
++	c32 = cx >> clen--;
++	for (i = 0; i < clen; ++i) {
++		/* Trailing octets must have 10 in most significant bits. */
++		cx = (*s8)[i] ^ 0x80;
++		if (cx & 0xc0)
++			return c0;
++		c32 = (c32 << 6) | cx;
++	}
++	/*
++	 * Check for validity:
++	 * - The character must be in the Unicode range.
++	 * - It must not be a surrogate.
++	 * - It must be encoded using the correct number of octets.
++	 */
++	if (c32 > 0x10ffff ||
++	    (c32 & 0xf800) == 0xd800 ||
++	    clen != (c32 >= 0x80) + (c32 >= 0x800) + (c32 >= 0x10000))
++		return c0;
++	*s8 += clen;
++	return c32;
++}
++
+ void efi_puts(const char *str)
+ {
+ 	efi_char16_t buf[128];
+ 	size_t pos = 0, lim = ARRAY_SIZE(buf);
++	const u8 *s8 = (const u8 *)str;
++	u32 c32;
+ 
+-	while (*str) {
+-		if (*str == '\n')
++	while (*s8) {
++		if (*s8 == '\n')
+ 			buf[pos++] = L'\r';
+-		/* Cast to unsigned char to avoid sign-extension */
+-		buf[pos++] = (unsigned char)(*str++);
+-		if (*str == '\0' || pos >= lim - 2) {
++		c32 = utf8_to_utf32(&s8);
++		if (c32 < 0x10000) {
++			/* Characters in plane 0 use a single word. */
++			buf[pos++] = c32;
++		} else {
++			/*
++			 * Characters in other planes encode into a surrogate
++			 * pair.
++			 */
++			buf[pos++] = (0xd800 - (0x10000 >> 10)) + (c32 >> 10);
++			buf[pos++] = 0xdc00 + (c32 & 0x3ff);
++		}
++		if (*s8 == '\0' || pos >= lim - 2) {
+ 			buf[pos] = L'\0';
+ 			efi_char16_puts(buf);
+ 			pos = 0;

commit d850a2ff918be0691f8d0544a2156c856c42da5b
+Author: Arvind Sankar 
+Date:   Mon May 18 15:07:12 2020 -0400
+
+    efi/printf: Add support for wchar_t (UTF-16)
+    
+    Support %lc and %ls to output UTF-16 strings (converted to UTF-8).
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200518190716.751506-21-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/vsprintf.c b/drivers/firmware/efi/libstub/vsprintf.c
+index a3265a81adca..e65ef49a54cd 100644
+--- a/drivers/firmware/efi/libstub/vsprintf.c
++++ b/drivers/firmware/efi/libstub/vsprintf.c
+@@ -147,6 +147,7 @@ char *number(char *end, unsigned long long num, int base, char locase)
+ #define LEFT	16		/* left justified */
+ #define SMALL	32		/* Must be 32 == 0x20 */
+ #define SPECIAL	64		/* 0x */
++#define WIDE	128		/* UTF-16 string */
+ 
+ static
+ int get_flags(const char **fmt)
+@@ -238,6 +239,58 @@ char get_sign(long long *num, int flags)
+ 	return 0;
+ }
+ 
++static
++size_t utf16s_utf8nlen(const u16 *s16, size_t maxlen)
++{
++	size_t len, clen;
++
++	for (len = 0; len < maxlen && *s16; len += clen) {
++		u16 c0 = *s16++;
++
++		/* First, get the length for a BMP character */
++		clen = 1 + (c0 >= 0x80) + (c0 >= 0x800);
++		if (len + clen > maxlen)
++			break;
++		/*
++		 * If this is a high surrogate, and we're already at maxlen, we
++		 * can't include the character if it's a valid surrogate pair.
++		 * Avoid accessing one extra word just to check if it's valid
++		 * or not.
++		 */
++		if ((c0 & 0xfc00) == 0xd800) {
++			if (len + clen == maxlen)
++				break;
++			if ((*s16 & 0xfc00) == 0xdc00) {
++				++s16;
++				++clen;
++			}
++		}
++	}
++
++	return len;
++}
++
++static
++u32 utf16_to_utf32(const u16 **s16)
++{
++	u16 c0, c1;
++
++	c0 = *(*s16)++;
++	/* not a surrogate */
++	if ((c0 & 0xf800) != 0xd800)
++		return c0;
++	/* invalid: low surrogate instead of high */
++	if (c0 & 0x0400)
++		return 0xfffd;
++	c1 = **s16;
++	/* invalid: missing low surrogate */
++	if ((c1 & 0xfc00) != 0xdc00)
++		return 0xfffd;
++	/* valid surrogate pair */
++	++(*s16);
++	return (0x10000 - (0xd800 << 10) - 0xdc00) + (c0 << 10) + c1;
++}
++
+ #define PUTC(c) \
+ do {				\
+ 	if (pos < size)		\
+@@ -325,18 +378,31 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
+ 		switch (*fmt) {
+ 		case 'c':
+ 			flags &= LEFT;
+-			tmp[0] = (unsigned char)va_arg(args, int);
+ 			s = tmp;
+-			precision = len = 1;
++			if (qualifier == 'l') {
++				((u16 *)tmp)[0] = (u16)va_arg(args, unsigned int);
++				((u16 *)tmp)[1] = L'\0';
++				precision = INT_MAX;
++				goto wstring;
++			} else {
++				tmp[0] = (unsigned char)va_arg(args, int);
++				precision = len = 1;
++			}
+ 			goto output;
+ 
+ 		case 's':
+ 			flags &= LEFT;
+ 			if (precision < 0)
+ 				precision = INT_MAX;
+-			s = va_arg(args, char *);
++			s = va_arg(args, void *);
+ 			if (!s)
+ 				s = precision < 6 ? "" : "(null)";
++			else if (qualifier == 'l') {
++		wstring:
++				flags |= WIDE;
++				precision = len = utf16s_utf8nlen((const u16 *)s, precision);
++				goto output;
++			}
+ 			precision = len = strnlen(s, precision);
+ 			goto output;
+ 
+@@ -436,8 +502,43 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
+ 		while (precision-- > len)
+ 			PUTC('0');
+ 		/* Actual output */
+-		while (len-- > 0)
+-			PUTC(*s++);
++		if (flags & WIDE) {
++			const u16 *ws = (const u16 *)s;
++
++			while (len-- > 0) {
++				u32 c32 = utf16_to_utf32(&ws);
++				u8 *s8;
++				size_t clen;
++
++				if (c32 < 0x80) {
++					PUTC(c32);
++					continue;
++				}
++
++				/* Number of trailing octets */
++				clen = 1 + (c32 >= 0x800) + (c32 >= 0x10000);
++
++				len -= clen;
++				s8 = (u8 *)&buf[pos];
++
++				/* Avoid writing partial character */
++				PUTC('\0');
++				pos += clen;
++				if (pos >= size)
++					continue;
++
++				/* Set high bits of leading octet */
++				*s8 = (0xf00 >> 1) >> clen;
++				/* Write trailing octets in reverse order */
++				for (s8 += clen; clen; --clen, c32 >>= 6)
++					*s8-- = 0x80 | (c32 & 0x3f);
++				/* Set low bits of leading octet */
++				*s8 |= c32;
++			}
++		} else {
++			while (len-- > 0)
++				PUTC(*s++);
++		}
+ 		/* Trailing padding with ' ' */
+ 		while (field_width-- > 0)
+ 			PUTC(' ');

commit 14c574f35cfbc9272fc67b41f074c847db139652
+Author: Arvind Sankar 
+Date:   Mon May 18 15:07:11 2020 -0400
+
+    efi/gop: Add an option to list out the available GOP modes
+    
+    Add video=efifb:list option to list the modes that are available.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200518190716.751506-20-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/Documentation/fb/efifb.rst b/Documentation/fb/efifb.rst
+index 519550517fd4..6badff64756f 100644
+--- a/Documentation/fb/efifb.rst
++++ b/Documentation/fb/efifb.rst
+@@ -63,4 +63,9 @@ auto
+         with the highest resolution, it will choose one with the highest color
+         depth.
+ 
++list
++        The EFI stub will list out all the display modes that are available. A
++        specific mode can then be chosen using one of the above options for the
++        next boot.
++
+ Edgar Hucek 
+diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
+index 1f5a00b4f201..f338d149aaa5 100644
+--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
++++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
+@@ -463,3 +463,38 @@ efi_status_t efi_load_initrd(efi_loaded_image_t *image,
+ 
+ 	return status;
+ }
++
++efi_status_t efi_wait_for_key(unsigned long usec, efi_input_key_t *key)
++{
++	efi_event_t events[2], timer;
++	unsigned long index;
++	efi_simple_text_input_protocol_t *con_in;
++	efi_status_t status;
++
++	con_in = efi_table_attr(efi_system_table, con_in);
++	if (!con_in)
++		return EFI_UNSUPPORTED;
++	efi_set_event_at(events, 0, efi_table_attr(con_in, wait_for_key));
++
++	status = efi_bs_call(create_event, EFI_EVT_TIMER, 0, NULL, NULL, &timer);
++	if (status != EFI_SUCCESS)
++		return status;
++
++	status = efi_bs_call(set_timer, timer, EfiTimerRelative,
++			     EFI_100NSEC_PER_USEC * usec);
++	if (status != EFI_SUCCESS)
++		return status;
++	efi_set_event_at(events, 1, timer);
++
++	status = efi_bs_call(wait_for_event, 2, events, &index);
++	if (status == EFI_SUCCESS) {
++		if (index == 0)
++			status = efi_call_proto(con_in, read_keystroke, key);
++		else
++			status = EFI_TIMEOUT;
++	}
++
++	efi_bs_call(close_event, timer);
++
++	return status;
++}
+diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
+index c7c03099367f..ad7e0406d0ba 100644
+--- a/drivers/firmware/efi/libstub/efistub.h
++++ b/drivers/firmware/efi/libstub/efistub.h
+@@ -323,6 +323,8 @@ union efi_simple_text_input_protocol {
+ 	} mixed_mode;
+ };
+ 
++efi_status_t efi_wait_for_key(unsigned long usec, efi_input_key_t *key);
++
+ union efi_simple_text_output_protocol {
+ 	struct {
+ 		void *reset;
+diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
+index 34c0cba2c8bf..ea5da307d542 100644
+--- a/drivers/firmware/efi/libstub/gop.c
++++ b/drivers/firmware/efi/libstub/gop.c
+@@ -19,7 +19,8 @@ enum efi_cmdline_option {
+ 	EFI_CMDLINE_NONE,
+ 	EFI_CMDLINE_MODE_NUM,
+ 	EFI_CMDLINE_RES,
+-	EFI_CMDLINE_AUTO
++	EFI_CMDLINE_AUTO,
++	EFI_CMDLINE_LIST
+ };
+ 
+ static struct {
+@@ -100,6 +101,19 @@ static bool parse_auto(char *option, char **next)
+ 	return true;
+ }
+ 
++static bool parse_list(char *option, char **next)
++{
++	if (!strstarts(option, "list"))
++		return false;
++	option += strlen("list");
++	if (*option && *option++ != ',')
++		return false;
++	cmdline.option = EFI_CMDLINE_LIST;
++
++	*next = option;
++	return true;
++}
++
+ void efi_parse_option_graphics(char *option)
+ {
+ 	while (*option) {
+@@ -109,6 +123,8 @@ void efi_parse_option_graphics(char *option)
+ 			continue;
+ 		if (parse_auto(option, &option))
+ 			continue;
++		if (parse_list(option, &option))
++			continue;
+ 
+ 		while (*option && *option++ != ',')
+ 			;
+@@ -290,6 +306,82 @@ static u32 choose_mode_auto(efi_graphics_output_protocol_t *gop)
+ 	return best_mode;
+ }
+ 
++static u32 choose_mode_list(efi_graphics_output_protocol_t *gop)
++{
++	efi_status_t status;
++
++	efi_graphics_output_protocol_mode_t *mode;
++	efi_graphics_output_mode_info_t *info;
++	unsigned long info_size;
++
++	u32 max_mode, cur_mode;
++	int pf;
++	efi_pixel_bitmask_t pi;
++	u32 m, w, h;
++	u8 d;
++	const char *dstr;
++	bool valid;
++	efi_input_key_t key;
++
++	mode = efi_table_attr(gop, mode);
++
++	cur_mode = efi_table_attr(mode, mode);
++	max_mode = efi_table_attr(mode, max_mode);
++
++	efi_printk("Available graphics modes are 0-%u\n", max_mode-1);
++	efi_puts("  * = current mode\n"
++		 "  - = unusable mode\n");
++	for (m = 0; m < max_mode; m++) {
++		status = efi_call_proto(gop, query_mode, m,
++					&info_size, &info);
++		if (status != EFI_SUCCESS)
++			continue;
++
++		pf = info->pixel_format;
++		pi = info->pixel_information;
++		w  = info->horizontal_resolution;
++		h  = info->vertical_resolution;
++
++		efi_bs_call(free_pool, info);
++
++		valid = !(pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX);
++		d = 0;
++		switch (pf) {
++		case PIXEL_RGB_RESERVED_8BIT_PER_COLOR:
++			dstr = "rgb";
++			break;
++		case PIXEL_BGR_RESERVED_8BIT_PER_COLOR:
++			dstr = "bgr";
++			break;
++		case PIXEL_BIT_MASK:
++			dstr = "";
++			d = pixel_bpp(pf, pi);
++			break;
++		case PIXEL_BLT_ONLY:
++			dstr = "blt";
++			break;
++		default:
++			dstr = "xxx";
++			break;
++		}
++
++		efi_printk("Mode %3u %c%c: Resolution %ux%u-%s%.0hhu\n",
++			   m,
++			   m == cur_mode ? '*' : ' ',
++			   !valid ? '-' : ' ',
++			   w, h, dstr, d);
++	}
++
++	efi_puts("\nPress any key to continue (or wait 10 seconds)\n");
++	status = efi_wait_for_key(10 * EFI_USEC_PER_SEC, &key);
++	if (status != EFI_SUCCESS && status != EFI_TIMEOUT) {
++		efi_err("Unable to read key, continuing in 10 seconds\n");
++		efi_bs_call(stall, 10 * EFI_USEC_PER_SEC);
++	}
++
++	return cur_mode;
++}
++
+ static void set_mode(efi_graphics_output_protocol_t *gop)
+ {
+ 	efi_graphics_output_protocol_mode_t *mode;
+@@ -305,6 +397,9 @@ static void set_mode(efi_graphics_output_protocol_t *gop)
+ 	case EFI_CMDLINE_AUTO:
+ 		new_mode = choose_mode_auto(gop);
+ 		break;
++	case EFI_CMDLINE_LIST:
++		new_mode = choose_mode_list(gop);
++		break;
+ 	default:
+ 		return;
+ 	}
+diff --git a/include/linux/efi.h b/include/linux/efi.h
+index 974648db0c68..609201bd4682 100644
+--- a/include/linux/efi.h
++++ b/include/linux/efi.h
+@@ -39,6 +39,7 @@
+ #define EFI_WRITE_PROTECTED	( 8 | (1UL << (BITS_PER_LONG-1)))
+ #define EFI_OUT_OF_RESOURCES	( 9 | (1UL << (BITS_PER_LONG-1)))
+ #define EFI_NOT_FOUND		(14 | (1UL << (BITS_PER_LONG-1)))
++#define EFI_TIMEOUT		(18 | (1UL << (BITS_PER_LONG-1)))
+ #define EFI_ABORTED		(21 | (1UL << (BITS_PER_LONG-1)))
+ #define EFI_SECURITY_VIOLATION	(26 | (1UL << (BITS_PER_LONG-1)))
+ 

commit 9b47c5275614a16fd64359fab73fe6c736bf57a0
+Author: Arvind Sankar 
+Date:   Mon May 18 15:07:10 2020 -0400
+
+    efi/libstub: Add definitions for console input and events
+    
+    Add the required typedefs etc for using con_in's simple text input
+    protocol, and for using the boottime event services.
+    
+    Also add the prototype for the "stall" boot service.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200518190716.751506-19-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
+index 6b9ab0d8b2a7..89dcc7aa7e2c 100644
+--- a/arch/x86/include/asm/efi.h
++++ b/arch/x86/include/asm/efi.h
+@@ -9,6 +9,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ extern unsigned long efi_fw_vendor, efi_config_table;
+ 
+@@ -293,6 +294,15 @@ static inline u32 efi64_convert_status(efi_status_t status)
+ #define __efi64_argmap_allocate_pool(type, size, buffer)		\
+ 	((type), (size), efi64_zero_upper(buffer))
+ 
++#define __efi64_argmap_create_event(type, tpl, f, c, event)		\
++	((type), (tpl), (f), (c), efi64_zero_upper(event))
++
++#define __efi64_argmap_set_timer(event, type, time)			\
++	((event), (type), lower_32_bits(time), upper_32_bits(time))
++
++#define __efi64_argmap_wait_for_event(num, event, index)		\
++	((num), (event), efi64_zero_upper(index))
++
+ #define __efi64_argmap_handle_protocol(handle, protocol, interface)	\
+ 	((handle), (protocol), efi64_zero_upper(interface))
+ 
+diff --git a/arch/x86/xen/efi.c b/arch/x86/xen/efi.c
+index 1abe455d926a..205a9bc981b0 100644
+--- a/arch/x86/xen/efi.c
++++ b/arch/x86/xen/efi.c
+@@ -29,7 +29,7 @@ static efi_system_table_t efi_systab_xen __initdata = {
+ 	.fw_vendor	= EFI_INVALID_TABLE_ADDR, /* Initialized later. */
+ 	.fw_revision	= 0,			  /* Initialized later. */
+ 	.con_in_handle	= EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */
+-	.con_in		= EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */
++	.con_in		= NULL,			  /* Not used under Xen. */
+ 	.con_out_handle	= EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */
+ 	.con_out	= NULL, 		  /* Not used under Xen. */
+ 	.stderr_handle	= EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */
+diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
+index 3a323a009836..c7c03099367f 100644
+--- a/drivers/firmware/efi/libstub/efistub.h
++++ b/drivers/firmware/efi/libstub/efistub.h
+@@ -111,6 +111,16 @@ void efi_set_u64_split(u64 data, u32 *lo, u32 *hi)
+ #define EFI_LOCATE_BY_REGISTER_NOTIFY		1
+ #define EFI_LOCATE_BY_PROTOCOL			2
+ 
++/*
++ * boottime->stall takes the time period in microseconds
++ */
++#define EFI_USEC_PER_SEC		1000000
++
++/*
++ * boottime->set_timer takes the time in 100ns units
++ */
++#define EFI_100NSEC_PER_USEC	((u64)10)
++
+ struct efi_boot_memmap {
+ 	efi_memory_desc_t	**map;
+ 	unsigned long		*map_size;
+@@ -122,6 +132,39 @@ struct efi_boot_memmap {
+ 
+ typedef struct efi_generic_dev_path efi_device_path_protocol_t;
+ 
++typedef void *efi_event_t;
++/* Note that notifications won't work in mixed mode */
++typedef void (__efiapi *efi_event_notify_t)(efi_event_t, void *);
++
++#define EFI_EVT_TIMER		0x80000000U
++#define EFI_EVT_RUNTIME		0x40000000U
++#define EFI_EVT_NOTIFY_WAIT	0x00000100U
++#define EFI_EVT_NOTIFY_SIGNAL	0x00000200U
++
++/*
++ * boottime->wait_for_event takes an array of events as input.
++ * Provide a helper to set it up correctly for mixed mode.
++ */
++static inline
++void efi_set_event_at(efi_event_t *events, size_t idx, efi_event_t event)
++{
++	if (efi_is_native())
++		events[idx] = event;
++	else
++		((u32 *)events)[idx] = (u32)(unsigned long)event;
++}
++
++#define EFI_TPL_APPLICATION	4
++#define EFI_TPL_CALLBACK	8
++#define EFI_TPL_NOTIFY		16
++#define EFI_TPL_HIGH_LEVEL	31
++
++typedef enum {
++	EfiTimerCancel,
++	EfiTimerPeriodic,
++	EfiTimerRelative
++} EFI_TIMER_DELAY;
++
+ /*
+  * EFI Boot Services table
+  */
+@@ -140,11 +183,16 @@ union efi_boot_services {
+ 		efi_status_t (__efiapi *allocate_pool)(int, unsigned long,
+ 						       void **);
+ 		efi_status_t (__efiapi *free_pool)(void *);
+-		void *create_event;
+-		void *set_timer;
+-		void *wait_for_event;
++		efi_status_t (__efiapi *create_event)(u32, unsigned long,
++						      efi_event_notify_t, void *,
++						      efi_event_t *);
++		efi_status_t (__efiapi *set_timer)(efi_event_t,
++						  EFI_TIMER_DELAY, u64);
++		efi_status_t (__efiapi *wait_for_event)(unsigned long,
++							efi_event_t *,
++							unsigned long *);
+ 		void *signal_event;
+-		void *close_event;
++		efi_status_t (__efiapi *close_event)(efi_event_t);
+ 		void *check_event;
+ 		void *install_protocol_interface;
+ 		void *reinstall_protocol_interface;
+@@ -171,7 +219,7 @@ union efi_boot_services {
+ 		efi_status_t (__efiapi *exit_boot_services)(efi_handle_t,
+ 							    unsigned long);
+ 		void *get_next_monotonic_count;
+-		void *stall;
++		efi_status_t (__efiapi *stall)(unsigned long);
+ 		void *set_watchdog_timer;
+ 		void *connect_controller;
+ 		efi_status_t (__efiapi *disconnect_controller)(efi_handle_t,
+@@ -256,6 +304,25 @@ union efi_uga_draw_protocol {
+ 	} mixed_mode;
+ };
+ 
++typedef struct {
++	u16 scan_code;
++	efi_char16_t unicode_char;
++} efi_input_key_t;
++
++union efi_simple_text_input_protocol {
++	struct {
++		void *reset;
++		efi_status_t (__efiapi *read_keystroke)(efi_simple_text_input_protocol_t *,
++							efi_input_key_t *);
++		efi_event_t wait_for_key;
++	};
++	struct {
++		u32 reset;
++		u32 read_keystroke;
++		u32 wait_for_key;
++	} mixed_mode;
++};
++
+ union efi_simple_text_output_protocol {
+ 	struct {
+ 		void *reset;
+diff --git a/include/linux/efi.h b/include/linux/efi.h
+index 9b7c7ec319ac..974648db0c68 100644
+--- a/include/linux/efi.h
++++ b/include/linux/efi.h
+@@ -426,6 +426,7 @@ typedef struct {
+ 	u32 tables;
+ } efi_system_table_32_t;
+ 
++typedef union efi_simple_text_input_protocol efi_simple_text_input_protocol_t;
+ typedef union efi_simple_text_output_protocol efi_simple_text_output_protocol_t;
+ 
+ typedef union {
+@@ -434,7 +435,7 @@ typedef union {
+ 		unsigned long fw_vendor;	/* physical addr of CHAR16 vendor string */
+ 		u32 fw_revision;
+ 		unsigned long con_in_handle;
+-		unsigned long con_in;
++		efi_simple_text_input_protocol_t *con_in;
+ 		unsigned long con_out_handle;
+ 		efi_simple_text_output_protocol_t *con_out;
+ 		unsigned long stderr_handle;

commit 23d5b73fbfd787c4c63841912b079eac000a7414
+Author: Arvind Sankar 
+Date:   Wed May 20 19:07:54 2020 +0200
+
+    efi/libstub: Implement printk-style logging
+    
+    Use the efi_printk function in efi_info/efi_err, and add efi_debug. This
+    allows formatted output at different log levels.
+    
+    Add the notion of a loglevel instead of just quiet/not-quiet, and
+    parse the efi=debug kernel parameter in addition to quiet.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200520170223.GA3333632@rani.riverdale.lan/
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
+index 5ecafc57619a..1f5a00b4f201 100644
+--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
++++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
+@@ -11,6 +11,7 @@
+ 
+ #include 
+ #include 
++#include  /* For CONSOLE_LOGLEVEL_* */
+ #include 
+ 
+ #include "efistub.h"
+@@ -18,7 +19,7 @@
+ bool efi_nochunk;
+ bool efi_nokaslr;
+ bool efi_noinitrd;
+-bool efi_quiet;
++int efi_loglevel = CONSOLE_LOGLEVEL_DEFAULT;
+ bool efi_novamap;
+ 
+ static bool efi_nosoftreserve;
+@@ -58,6 +59,28 @@ int efi_printk(const char *fmt, ...)
+ 	char printf_buf[256];
+ 	va_list args;
+ 	int printed;
++	int loglevel = printk_get_level(fmt);
++
++	switch (loglevel) {
++	case '0' ... '9':
++		loglevel -= '0';
++		break;
++	default:
++		/*
++		 * Use loglevel -1 for cases where we just want to print to
++		 * the screen.
++		 */
++		loglevel = -1;
++		break;
++	}
++
++	if (loglevel >= efi_loglevel)
++		return 0;
++
++	if (loglevel >= 0)
++		efi_puts("EFI stub: ");
++
++	fmt = printk_skip_level(fmt);
+ 
+ 	va_start(args, fmt);
+ 	printed = vsnprintf(printf_buf, sizeof(printf_buf), fmt, args);
+@@ -100,7 +123,7 @@ efi_status_t efi_parse_options(char const *cmdline)
+ 		if (!strcmp(param, "nokaslr")) {
+ 			efi_nokaslr = true;
+ 		} else if (!strcmp(param, "quiet")) {
+-			efi_quiet = true;
++			efi_loglevel = CONSOLE_LOGLEVEL_QUIET;
+ 		} else if (!strcmp(param, "noinitrd")) {
+ 			efi_noinitrd = true;
+ 		} else if (!strcmp(param, "efi") && val) {
+@@ -114,6 +137,8 @@ efi_status_t efi_parse_options(char const *cmdline)
+ 				efi_disable_pci_dma = true;
+ 			if (parse_option_str(val, "no_disable_early_pci_dma"))
+ 				efi_disable_pci_dma = false;
++			if (parse_option_str(val, "debug"))
++				efi_loglevel = CONSOLE_LOGLEVEL_DEBUG;
+ 		} else if (!strcmp(param, "video") &&
+ 			   val && strstarts(val, "efifb:")) {
+ 			efi_parse_option_graphics(val + strlen("efifb:"));
+diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
+index caa7dcc71c69..3a323a009836 100644
+--- a/drivers/firmware/efi/libstub/efistub.h
++++ b/drivers/firmware/efi/libstub/efistub.h
+@@ -6,6 +6,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ 
+@@ -34,7 +35,7 @@
+ extern bool efi_nochunk;
+ extern bool efi_nokaslr;
+ extern bool efi_noinitrd;
+-extern bool efi_quiet;
++extern int efi_loglevel;
+ extern bool efi_novamap;
+ 
+ extern const efi_system_table_t *efi_system_table;
+@@ -49,11 +50,12 @@ extern const efi_system_table_t *efi_system_table;
+ 
+ #endif
+ 
+-#define efi_info(msg)		do {			\
+-	if (!efi_quiet) efi_puts("EFI stub: "msg);	\
+-} while (0)
+-
+-#define efi_err(msg) efi_puts("EFI stub: ERROR: "msg)
++#define efi_info(fmt, ...) \
++	efi_printk(KERN_INFO fmt, ##__VA_ARGS__)
++#define efi_err(fmt, ...) \
++	efi_printk(KERN_ERR "ERROR: " fmt, ##__VA_ARGS__)
++#define efi_debug(fmt, ...) \
++	efi_printk(KERN_DEBUG "DEBUG: " fmt, ##__VA_ARGS__)
+ 
+ /* Helper macros for the usual case of using simple C variables: */
+ #ifndef fdt_setprop_inplace_var

commit 5214028dd89e49ba27007c3ee475279e584261f0
+Author: Arvind Sankar 
+Date:   Fri Feb 7 16:49:26 2020 -0500
+
+    x86/boot: Correct relocation destination on old linkers
+    
+    For the 32-bit kernel, as described in
+    
+      6d92bc9d483a ("x86/build: Build compressed x86 kernels as PIE"),
+    
+    pre-2.26 binutils generates R_386_32 relocations in PIE mode. Since the
+    startup code does not perform relocation, any reloc entry with R_386_32
+    will remain as 0 in the executing code.
+    
+    Commit
+    
+      974f221c84b0 ("x86/boot: Move compressed kernel to the end of the
+                     decompression buffer")
+    
+    added a new symbol _end but did not mark it hidden, which doesn't give
+    the correct offset on older linkers. This causes the compressed kernel
+    to be copied beyond the end of the decompression buffer, rather than
+    flush against it. This region of memory may be reserved or already
+    allocated for other purposes by the bootloader.
+    
+    Mark _end as hidden to fix. This changes the relocation from R_386_32 to
+    R_386_RELATIVE even on the pre-2.26 binutils.
+    
+    For 64-bit, this is not strictly necessary, as the 64-bit kernel is only
+    built as PIE if the linker supports -z noreloc-overflow, which implies
+    binutils-2.27+, but for consistency, mark _end as hidden here too.
+    
+    The below illustrates the before/after impact of the patch using
+    binutils-2.25 and gcc-4.6.4 (locally compiled from source) and QEMU.
+    
+      Disassembly before patch:
+        48:   8b 86 60 02 00 00       mov    0x260(%esi),%eax
+        4e:   2d 00 00 00 00          sub    $0x0,%eax
+                              4f: R_386_32    _end
+      Disassembly after patch:
+        48:   8b 86 60 02 00 00       mov    0x260(%esi),%eax
+        4e:   2d 00 f0 76 00          sub    $0x76f000,%eax
+                              4f: R_386_RELATIVE      *ABS*
+    
+    Dump from extract_kernel before patch:
+            early console in extract_kernel
+            input_data: 0x0207c098 <--- this is at output + init_size
+            input_len: 0x0074fef1
+            output: 0x01000000
+            output_len: 0x00fa63d0
+            kernel_total_size: 0x0107c000
+            needed_size: 0x0107c000
+    
+    Dump from extract_kernel after patch:
+            early console in extract_kernel
+            input_data: 0x0190d098 <--- this is at output + init_size - _end
+            input_len: 0x0074fef1
+            output: 0x01000000
+            output_len: 0x00fa63d0
+            kernel_total_size: 0x0107c000
+            needed_size: 0x0107c000
+    
+    Fixes: 974f221c84b0 ("x86/boot: Move compressed kernel to the end of the decompression buffer")
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Borislav Petkov 
+    Link: https://lkml.kernel.org/r/20200207214926.3564079-1-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
+index ab3307036ba4..03557f2174bf 100644
+--- a/arch/x86/boot/compressed/head_32.S
++++ b/arch/x86/boot/compressed/head_32.S
+@@ -49,16 +49,17 @@
+  * Position Independent Executable (PIE) so that linker won't optimize
+  * R_386_GOT32X relocation to its fixed symbol address.  Older
+  * linkers generate R_386_32 relocations against locally defined symbols,
+- * _bss, _ebss, _got and _egot, in PIE.  It isn't wrong, just less
++ * _bss, _ebss, _got, _egot and _end, in PIE.  It isn't wrong, just less
+  * optimal than R_386_RELATIVE.  But the x86 kernel fails to properly handle
+  * R_386_32 relocations when relocating the kernel.  To generate
+- * R_386_RELATIVE relocations, we mark _bss, _ebss, _got and _egot as
++ * R_386_RELATIVE relocations, we mark _bss, _ebss, _got, _egot and _end as
+  * hidden:
+  */
+ 	.hidden _bss
+ 	.hidden _ebss
+ 	.hidden _got
+ 	.hidden _egot
++	.hidden _end
+ 
+ 	__HEAD
+ SYM_FUNC_START(startup_32)
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index 6b11060c3a0f..e821a7d7d5c4 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -42,6 +42,7 @@
+ 	.hidden _ebss
+ 	.hidden _got
+ 	.hidden _egot
++	.hidden _end
+ 
+ 	__HEAD
+ 	.code32

commit 8fb331e10b63888e944a8a0dcf79b17e93b475ba
+Author: Arvind Sankar 
+Date:   Mon May 18 15:07:08 2020 -0400
+
+    efi/printf: Turn vsprintf into vsnprintf
+    
+    Implement vsnprintf instead of vsprintf to avoid the possibility of a
+    buffer overflow.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200518190716.751506-17-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
+index 56b3b84fd3bd..5ecafc57619a 100644
+--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
++++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
+@@ -60,10 +60,14 @@ int efi_printk(const char *fmt, ...)
+ 	int printed;
+ 
+ 	va_start(args, fmt);
+-	printed = vsprintf(printf_buf, fmt, args);
++	printed = vsnprintf(printf_buf, sizeof(printf_buf), fmt, args);
+ 	va_end(args);
+ 
+ 	efi_puts(printf_buf);
++	if (printed >= sizeof(printf_buf)) {
++		efi_puts("[Message truncated]\n");
++		return -1;
++	}
+ 
+ 	return printed;
+ }
+diff --git a/drivers/firmware/efi/libstub/vsprintf.c b/drivers/firmware/efi/libstub/vsprintf.c
+index cca6b802b028..a3265a81adca 100644
+--- a/drivers/firmware/efi/libstub/vsprintf.c
++++ b/drivers/firmware/efi/libstub/vsprintf.c
+@@ -17,6 +17,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ static
+ int skip_atoi(const char **s)
+@@ -237,16 +238,22 @@ char get_sign(long long *num, int flags)
+ 	return 0;
+ }
+ 
+-int vsprintf(char *buf, const char *fmt, va_list ap)
++#define PUTC(c) \
++do {				\
++	if (pos < size)		\
++		buf[pos] = (c);	\
++	++pos;			\
++} while (0);
++
++int vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
+ {
+ 	/* The maximum space required is to print a 64-bit number in octal */
+ 	char tmp[(sizeof(unsigned long long) * 8 + 2) / 3];
+ 	char *tmp_end = &tmp[ARRAY_SIZE(tmp)];
+ 	long long num;
+ 	int base;
+-	char *str;
+ 	const char *s;
+-	int len;
++	size_t len, pos;
+ 	char sign;
+ 
+ 	int flags;		/* flags to number() */
+@@ -274,9 +281,9 @@ int vsprintf(char *buf, const char *fmt, va_list ap)
+ 	 */
+ 	va_copy(args, ap);
+ 
+-	for (str = buf; *fmt; ++fmt) {
++	for (pos = 0; *fmt; ++fmt) {
+ 		if (*fmt != '%' || *++fmt == '%') {
+-			*str++ = *fmt;
++			PUTC(*fmt);
+ 			continue;
+ 		}
+ 
+@@ -416,40 +423,41 @@ int vsprintf(char *buf, const char *fmt, va_list ap)
+ 		/* Leading padding with ' ' */
+ 		if (!(flags & LEFT))
+ 			while (field_width-- > 0)
+-				*str++ = ' ';
++				PUTC(' ');
+ 		/* sign */
+ 		if (sign)
+-			*str++ = sign;
++			PUTC(sign);
+ 		/* 0x/0X for hexadecimal */
+ 		if (flags & SPECIAL) {
+-			*str++ = '0';
+-			*str++ = 'X' | (flags & SMALL);
++			PUTC('0');
++			PUTC( 'X' | (flags & SMALL));
+ 		}
+ 		/* Zero padding and excess precision */
+ 		while (precision-- > len)
+-			*str++ = '0';
++			PUTC('0');
+ 		/* Actual output */
+ 		while (len-- > 0)
+-			*str++ = *s++;
++			PUTC(*s++);
+ 		/* Trailing padding with ' ' */
+ 		while (field_width-- > 0)
+-			*str++ = ' ';
++			PUTC(' ');
+ 	}
+ fail:
+-	*str = '\0';
+-
+ 	va_end(args);
+ 
+-	return str - buf;
++	if (size)
++		buf[min(pos, size-1)] = '\0';
++
++	return pos;
+ }
+ 
+-int sprintf(char *buf, const char *fmt, ...)
++int snprintf(char *buf, size_t size, const char *fmt, ...)
+ {
+ 	va_list args;
+ 	int i;
+ 
+ 	va_start(args, fmt);
+-	i = vsprintf(buf, fmt, args);
++	i = vsnprintf(buf, size, fmt, args);
+ 	va_end(args);
+ 	return i;
+ }

commit f97ca2c816748e3b7dee58775632f9e9269071e6
+Author: Arvind Sankar 
+Date:   Mon May 18 15:07:07 2020 -0400
+
+    efi/printf: Abort on invalid format
+    
+    If we get an invalid conversion specifier, bail out instead of trying to
+    fix it up. The format string likely has a typo or assumed we support
+    something that we don't, in either case the remaining arguments won't
+    match up with the remaining format string.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200518190716.751506-16-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/vsprintf.c b/drivers/firmware/efi/libstub/vsprintf.c
+index c09d97051c7e..cca6b802b028 100644
+--- a/drivers/firmware/efi/libstub/vsprintf.c
++++ b/drivers/firmware/efi/libstub/vsprintf.c
+@@ -359,12 +359,13 @@ int vsprintf(char *buf, const char *fmt, va_list ap)
+ 			break;
+ 
+ 		default:
+-			*str++ = '%';
+-			if (*fmt)
+-				*str++ = *fmt;
+-			else
+-				--fmt;
+-			continue;
++			/*
++			 * Bail out if the conversion specifier is invalid.
++			 * There's probably a typo in the format string and the
++			 * remaining specifiers are unlikely to match up with
++			 * the arguments.
++			 */
++			goto fail;
+ 		}
+ 		if (*fmt == 'p') {
+ 			num = (unsigned long)va_arg(args, void *);
+@@ -434,6 +435,7 @@ int vsprintf(char *buf, const char *fmt, va_list ap)
+ 		while (field_width-- > 0)
+ 			*str++ = ' ';
+ 	}
++fail:
+ 	*str = '\0';
+ 
+ 	va_end(args);

commit 6c4bcd8a46a98856c06ca3ba8a80f03a61e23960
+Author: Arvind Sankar 
+Date:   Mon May 18 15:07:06 2020 -0400
+
+    efi/printf: Refactor code to consolidate padding and output
+    
+    Consolidate the actual output of the formatted text into one place.
+    
+    Fix a couple of edge cases:
+    1. If 0 is printed with a precision of 0, the printf specification says
+       that nothing should be output, with one exception (2b).
+    2. The specification for octal alternate format (%#o) adds the leading
+       zero not as a prefix as the 0x for hexadecimal is, but by increasing
+       the precision if necessary to add the zero. This means that
+       a. %#.2o turns 8 into "010", but 1 into "01" rather than "001".
+       b. %#.o prints 0 as "0" rather than "", unlike the situation for
+          decimal, hexadecimal and regular octal format, which all output an
+          empty string.
+    
+    Reduce the space allocated for printing a number to the maximum actually
+    required (22 bytes for a 64-bit number in octal), instead of the 66
+    bytes previously allocated.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200518190716.751506-15-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/vsprintf.c b/drivers/firmware/efi/libstub/vsprintf.c
+index d427a7b1ef64..c09d97051c7e 100644
+--- a/drivers/firmware/efi/libstub/vsprintf.c
++++ b/drivers/firmware/efi/libstub/vsprintf.c
+@@ -14,10 +14,12 @@
+ 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ 
+-static int skip_atoi(const char **s)
++static
++int skip_atoi(const char **s)
+ {
+ 	int i = 0;
+ 
+@@ -32,16 +34,16 @@ static int skip_atoi(const char **s)
+  * r/10 == (r * 0xccd) >> 15 is exact for all r < 16389.
+  */
+ static
+-void put_dec_full4(char *buf, unsigned int r)
++void put_dec_full4(char *end, unsigned int r)
+ {
+ 	int i;
+ 
+ 	for (i = 0; i < 3; i++) {
+ 		unsigned int q = (r * 0xccd) >> 15;
+-		*buf++ = '0' + (r - q * 10);
++		*--end = '0' + (r - q * 10);
+ 		r = q;
+ 	}
+-	*buf++ = '0' + r;
++	*--end = '0' + r;
+ }
+ 
+ /* put_dec is copied from lib/vsprintf.c with small modifications */
+@@ -54,11 +56,11 @@ void put_dec_full4(char *buf, unsigned int r)
+  * (second call in the put_dec code, assuming n is all-ones).
+  */
+ static
+-unsigned int put_dec_helper4(char *buf, unsigned int x)
++unsigned int put_dec_helper4(char *end, unsigned int x)
+ {
+ 	unsigned int q = (x * 0x346DC5D7ULL) >> 43;
+ 
+-	put_dec_full4(buf, x - q * 10000);
++	put_dec_full4(end, x - q * 10000);
+ 	return q;
+ }
+ 
+@@ -68,10 +70,10 @@ unsigned int put_dec_helper4(char *buf, unsigned int x)
+  * Performs no 64-bit division and hence should be fast on 32-bit machines.
+  */
+ static
+-int put_dec(char *buf, unsigned long long n)
++char *put_dec(char *end, unsigned long long n)
+ {
+ 	unsigned int d3, d2, d1, q, h;
+-	char *p = buf;
++	char *p = end;
+ 
+ 	d1  = ((unsigned int)n >> 16); /* implicit "& 0xffff" */
+ 	h   = (n >> 32);
+@@ -82,28 +84,59 @@ int put_dec(char *buf, unsigned long long n)
+ 	     = 281_4749_7671_0656 d3 + 42_9496_7296 d2 + 6_5536 d1 + d0 */
+ 	q = 656 * d3 + 7296 * d2 + 5536 * d1 + ((unsigned int)n & 0xffff);
+ 	q = put_dec_helper4(p, q);
+-	p += 4;
++	p -= 4;
+ 
+ 	q += 7671 * d3 + 9496 * d2 + 6 * d1;
+ 	q = put_dec_helper4(p, q);
+-	p += 4;
++	p -= 4;
+ 
+ 	q += 4749 * d3 + 42 * d2;
+ 	q = put_dec_helper4(p, q);
+-	p += 4;
++	p -= 4;
+ 
+ 	q += 281 * d3;
+ 	q = put_dec_helper4(p, q);
+-	p += 4;
++	p -= 4;
+ 
+ 	put_dec_full4(p, q);
+-	p += 4;
++	p -= 4;
+ 
+ 	/* strip off the extra 0's we printed */
+-	while (p > buf && p[-1] == '0')
+-		--p;
++	while (p < end && *p == '0')
++		++p;
+ 
+-	return p - buf;
++	return p;
++}
++
++static
++char *number(char *end, unsigned long long num, int base, char locase)
++{
++	/*
++	 * locase = 0 or 0x20. ORing digits or letters with 'locase'
++	 * produces same digits or (maybe lowercased) letters
++	 */
++
++	/* we are called with base 8, 10 or 16, only, thus don't need "G..."  */
++	static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
++
++	switch (base) {
++	case 10:
++		if (num != 0)
++			end = put_dec(end, num);
++		break;
++	case 8:
++		for (; num != 0; num >>= 3)
++			*--end = '0' + (num & 07);
++		break;
++	case 16:
++		for (; num != 0; num >>= 4)
++			*--end = digits[num & 0xf] | locase;
++		break;
++	default:
++		unreachable();
++	};
++
++	return end;
+ }
+ 
+ #define ZEROPAD	1		/* pad with zero */
+@@ -114,95 +147,6 @@ int put_dec(char *buf, unsigned long long n)
+ #define SMALL	32		/* Must be 32 == 0x20 */
+ #define SPECIAL	64		/* 0x */
+ 
+-static char *number(char *str, long long num, int base, int size, int precision,
+-		    int type)
+-{
+-	/* we are called with base 8, 10 or 16, only, thus don't need "G..."  */
+-	static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
+-
+-	char tmp[66];
+-	char c, sign, locase;
+-	int i;
+-
+-	/* locase = 0 or 0x20. ORing digits or letters with 'locase'
+-	 * produces same digits or (maybe lowercased) letters */
+-	locase = (type & SMALL);
+-	if (type & LEFT)
+-		type &= ~ZEROPAD;
+-	c = (type & ZEROPAD) ? '0' : ' ';
+-	sign = 0;
+-	if (type & SIGN) {
+-		if (num < 0) {
+-			sign = '-';
+-			num = -num;
+-			size--;
+-		} else if (type & PLUS) {
+-			sign = '+';
+-			size--;
+-		} else if (type & SPACE) {
+-			sign = ' ';
+-			size--;
+-		}
+-	}
+-	if (type & SPECIAL) {
+-		if (base == 16)
+-			size -= 2;
+-		else if (base == 8)
+-			size--;
+-	}
+-	i = 0;
+-	if (num == 0)
+-		tmp[i++] = '0';
+-	else {
+-		switch (base) {
+-		case 10:
+-			i += put_dec(&tmp[i], num);
+-			break;
+-		case 8:
+-			while (num != 0) {
+-				tmp[i++] = '0' + (num & 07);
+-				num = (unsigned long long)num >> 3;
+-			}
+-			break;
+-		case 16:
+-			while (num != 0) {
+-				tmp[i++] = digits[num & 0xf] | locase;
+-				num = (unsigned long long)num >> 4;
+-			}
+-			break;
+-		default:
+-			unreachable();
+-		}
+-	}
+-
+-	if (i > precision)
+-		precision = i;
+-	size -= precision;
+-	if (!(type & (ZEROPAD + LEFT)))
+-		while (size-- > 0)
+-			*str++ = ' ';
+-	if (sign)
+-		*str++ = sign;
+-	if (type & SPECIAL) {
+-		if (base == 8) {
+-			*str++ = '0';
+-		} else if (base == 16) {
+-			*str++ = '0';
+-			*str++ = ('X' | locase);
+-		}
+-	}
+-	if (!(type & LEFT))
+-		while (size-- > 0)
+-			*str++ = c;
+-	while (i < precision--)
+-		*str++ = '0';
+-	while (i-- > 0)
+-		*str++ = tmp[i];
+-	while (size-- > 0)
+-		*str++ = ' ';
+-	return str;
+-}
+-
+ static
+ int get_flags(const char **fmt)
+ {
+@@ -277,13 +221,33 @@ unsigned long long get_number(int sign, int qualifier, va_list *ap)
+ 	}
+ }
+ 
++static
++char get_sign(long long *num, int flags)
++{
++	if (!(flags & SIGN))
++		return 0;
++	if (*num < 0) {
++		*num = -(*num);
++		return '-';
++	}
++	if (flags & PLUS)
++		return '+';
++	if (flags & SPACE)
++		return ' ';
++	return 0;
++}
++
+ int vsprintf(char *buf, const char *fmt, va_list ap)
+ {
+-	int len;
+-	unsigned long long num;
+-	int i, base;
++	/* The maximum space required is to print a 64-bit number in octal */
++	char tmp[(sizeof(unsigned long long) * 8 + 2) / 3];
++	char *tmp_end = &tmp[ARRAY_SIZE(tmp)];
++	long long num;
++	int base;
+ 	char *str;
+ 	const char *s;
++	int len;
++	char sign;
+ 
+ 	int flags;		/* flags to number() */
+ 
+@@ -326,6 +290,9 @@ int vsprintf(char *buf, const char *fmt, va_list ap)
+ 			flags |= LEFT;
+ 		}
+ 
++		if (flags & LEFT)
++			flags &= ~ZEROPAD;
++
+ 		/* get the precision */
+ 		precision = -1;
+ 		if (*fmt == '.') {
+@@ -346,32 +313,25 @@ int vsprintf(char *buf, const char *fmt, va_list ap)
+ 			}
+ 		}
+ 
++		sign = 0;
++
+ 		switch (*fmt) {
+ 		case 'c':
+-			if (!(flags & LEFT))
+-				while (--field_width > 0)
+-					*str++ = ' ';
+-			*str++ = (unsigned char)va_arg(args, int);
+-			while (--field_width > 0)
+-				*str++ = ' ';
+-			continue;
++			flags &= LEFT;
++			tmp[0] = (unsigned char)va_arg(args, int);
++			s = tmp;
++			precision = len = 1;
++			goto output;
+ 
+ 		case 's':
++			flags &= LEFT;
+ 			if (precision < 0)
+ 				precision = INT_MAX;
+ 			s = va_arg(args, char *);
+ 			if (!s)
+ 				s = precision < 6 ? "" : "(null)";
+-			len = strnlen(s, precision);
+-
+-			if (!(flags & LEFT))
+-				while (len < field_width--)
+-					*str++ = ' ';
+-			for (i = 0; i < len; ++i)
+-				*str++ = *s++;
+-			while (len < field_width--)
+-				*str++ = ' ';
+-			continue;
++			precision = len = strnlen(s, precision);
++			goto output;
+ 
+ 			/* integer number formats - set up the flags and "break" */
+ 		case 'o':
+@@ -394,6 +354,7 @@ int vsprintf(char *buf, const char *fmt, va_list ap)
+ 			flags |= SIGN;
+ 			fallthrough;
+ 		case 'u':
++			flags &= ~SPECIAL;
+ 			base = 10;
+ 			break;
+ 
+@@ -410,7 +371,68 @@ int vsprintf(char *buf, const char *fmt, va_list ap)
+ 		} else {
+ 			num = get_number(flags & SIGN, qualifier, &args);
+ 		}
+-		str = number(str, num, base, field_width, precision, flags);
++
++		sign = get_sign(&num, flags);
++		if (sign)
++			--field_width;
++
++		s = number(tmp_end, num, base, flags & SMALL);
++		len = tmp_end - s;
++		/* default precision is 1 */
++		if (precision < 0)
++			precision = 1;
++		/* precision is minimum number of digits to print */
++		if (precision < len)
++			precision = len;
++		if (flags & SPECIAL) {
++			/*
++			 * For octal, a leading 0 is printed only if necessary,
++			 * i.e. if it's not already there because of the
++			 * precision.
++			 */
++			if (base == 8 && precision == len)
++				++precision;
++			/*
++			 * For hexadecimal, the leading 0x is skipped if the
++			 * output is empty, i.e. both the number and the
++			 * precision are 0.
++			 */
++			if (base == 16 && precision > 0)
++				field_width -= 2;
++			else
++				flags &= ~SPECIAL;
++		}
++		/*
++		 * For zero padding, increase the precision to fill the field
++		 * width.
++		 */
++		if ((flags & ZEROPAD) && field_width > precision)
++			precision = field_width;
++
++output:
++		/* Calculate the padding necessary */
++		field_width -= precision;
++		/* Leading padding with ' ' */
++		if (!(flags & LEFT))
++			while (field_width-- > 0)
++				*str++ = ' ';
++		/* sign */
++		if (sign)
++			*str++ = sign;
++		/* 0x/0X for hexadecimal */
++		if (flags & SPECIAL) {
++			*str++ = '0';
++			*str++ = 'X' | (flags & SMALL);
++		}
++		/* Zero padding and excess precision */
++		while (precision-- > len)
++			*str++ = '0';
++		/* Actual output */
++		while (len-- > 0)
++			*str++ = *s++;
++		/* Trailing padding with ' ' */
++		while (field_width-- > 0)
++			*str++ = ' ';
+ 	}
+ 	*str = '\0';
+ 

commit fb031937a86874e6d663542bdbd83e310c13610e
+Author: Arvind Sankar 
+Date:   Mon May 18 15:07:05 2020 -0400
+
+    efi/printf: Handle null string input
+    
+    Print "(null)" for 's' if the input is a NULL pointer.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200518190716.751506-14-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/vsprintf.c b/drivers/firmware/efi/libstub/vsprintf.c
+index 27685c726c64..d427a7b1ef64 100644
+--- a/drivers/firmware/efi/libstub/vsprintf.c
++++ b/drivers/firmware/efi/libstub/vsprintf.c
+@@ -14,6 +14,7 @@
+ 
+ #include 
+ #include 
++#include 
+ #include 
+ 
+ static int skip_atoi(const char **s)
+@@ -356,7 +357,11 @@ int vsprintf(char *buf, const char *fmt, va_list ap)
+ 			continue;
+ 
+ 		case 's':
++			if (precision < 0)
++				precision = INT_MAX;
+ 			s = va_arg(args, char *);
++			if (!s)
++				s = precision < 6 ? "" : "(null)";
+ 			len = strnlen(s, precision);
+ 
+ 			if (!(flags & LEFT))

commit dec6119952eab7257624de5bd116a9e301ead5b7
+Author: Arvind Sankar 
+Date:   Mon May 18 15:07:04 2020 -0400
+
+    efi/printf: Factor out integer argument retrieval
+    
+    Factor out the code to get the correct type of numeric argument into a
+    helper function.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200518190716.751506-13-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/vsprintf.c b/drivers/firmware/efi/libstub/vsprintf.c
+index 0e6f2c1158fd..27685c726c64 100644
+--- a/drivers/firmware/efi/libstub/vsprintf.c
++++ b/drivers/firmware/efi/libstub/vsprintf.c
+@@ -244,6 +244,38 @@ int get_int(const char **fmt, va_list *ap)
+ 	return 0;
+ }
+ 
++static
++unsigned long long get_number(int sign, int qualifier, va_list *ap)
++{
++	if (sign) {
++		switch (qualifier) {
++		case 'L':
++			return va_arg(*ap, long long);
++		case 'l':
++			return va_arg(*ap, long);
++		case 'h':
++			return (short)va_arg(*ap, int);
++		case 'H':
++			return (signed char)va_arg(*ap, int);
++		default:
++			return va_arg(*ap, int);
++		};
++	} else {
++		switch (qualifier) {
++		case 'L':
++			return va_arg(*ap, unsigned long long);
++		case 'l':
++			return va_arg(*ap, unsigned long);
++		case 'h':
++			return (unsigned short)va_arg(*ap, int);
++		case 'H':
++			return (unsigned char)va_arg(*ap, int);
++		default:
++			return va_arg(*ap, unsigned int);
++		}
++	}
++}
++
+ int vsprintf(char *buf, const char *fmt, va_list ap)
+ {
+ 	int len;
+@@ -370,40 +402,8 @@ int vsprintf(char *buf, const char *fmt, va_list ap)
+ 		}
+ 		if (*fmt == 'p') {
+ 			num = (unsigned long)va_arg(args, void *);
+-		} else if (flags & SIGN) {
+-			switch (qualifier) {
+-			case 'L':
+-				num = va_arg(args, long long);
+-				break;
+-			case 'l':
+-				num = va_arg(args, long);
+-				break;
+-			case 'h':
+-				num = (short)va_arg(args, int);
+-				break;
+-			case 'H':
+-				num = (signed char)va_arg(args, int);
+-				break;
+-			default:
+-				num = va_arg(args, int);
+-			}
+ 		} else {
+-			switch (qualifier) {
+-			case 'L':
+-				num = va_arg(args, unsigned long long);
+-				break;
+-			case 'l':
+-				num = va_arg(args, unsigned long);
+-				break;
+-			case 'h':
+-				num = (unsigned short)va_arg(args, int);
+-				break;
+-			case 'H':
+-				num = (unsigned char)va_arg(args, int);
+-				break;
+-			default:
+-				num = va_arg(args, unsigned int);
+-			}
++			num = get_number(flags & SIGN, qualifier, &args);
+ 		}
+ 		str = number(str, num, base, field_width, precision, flags);
+ 	}

commit 3fbcf75bb41a0ff02189f6e873ba4c5d7c54c6a9
+Author: Arvind Sankar 
+Date:   Mon May 18 15:07:03 2020 -0400
+
+    efi/printf: Factor out width/precision parsing
+    
+    Factor out the width/precision parsing into a helper function.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200518190716.751506-12-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/vsprintf.c b/drivers/firmware/efi/libstub/vsprintf.c
+index b7316ab9f8b4..0e6f2c1158fd 100644
+--- a/drivers/firmware/efi/libstub/vsprintf.c
++++ b/drivers/firmware/efi/libstub/vsprintf.c
+@@ -231,7 +231,20 @@ int get_flags(const char **fmt)
+ 	} while (1);
+ }
+ 
+-int vsprintf(char *buf, const char *fmt, va_list args)
++static
++int get_int(const char **fmt, va_list *ap)
++{
++	if (isdigit(**fmt))
++		return skip_atoi(fmt);
++	if (**fmt == '*') {
++		++(*fmt);
++		/* it's the next argument */
++		return va_arg(*ap, int);
++	}
++	return 0;
++}
++
++int vsprintf(char *buf, const char *fmt, va_list ap)
+ {
+ 	int len;
+ 	unsigned long long num;
+@@ -246,6 +259,24 @@ int vsprintf(char *buf, const char *fmt, va_list args)
+ 				   number of chars for from string */
+ 	int qualifier;		/* 'h', 'hh', 'l' or 'll' for integer fields */
+ 
++	va_list args;
++
++	/*
++	 * We want to pass our input va_list to helper functions by reference,
++	 * but there's an annoying edge case. If va_list was originally passed
++	 * to us by value, we could just pass &ap down to the helpers. This is
++	 * the case on, for example, X86_32.
++	 * However, on X86_64 (and possibly others), va_list is actually a
++	 * size-1 array containing a structure. Our function parameter ap has
++	 * decayed from T[1] to T*, and &ap has type T** rather than T(*)[1],
++	 * which is what will be expected by a function taking a va_list *
++	 * parameter.
++	 * One standard way to solve this mess is by creating a copy in a local
++	 * variable of type va_list and then passing a pointer to that local
++	 * copy instead, which is what we do here.
++	 */
++	va_copy(args, ap);
++
+ 	for (str = buf; *fmt; ++fmt) {
+ 		if (*fmt != '%' || *++fmt == '%') {
+ 			*str++ = *fmt;
+@@ -256,32 +287,17 @@ int vsprintf(char *buf, const char *fmt, va_list args)
+ 		flags = get_flags(&fmt);
+ 
+ 		/* get field width */
+-		field_width = -1;
+-		if (isdigit(*fmt)) {
+-			field_width = skip_atoi(&fmt);
+-		} else if (*fmt == '*') {
+-			++fmt;
+-			/* it's the next argument */
+-			field_width = va_arg(args, int);
+-			if (field_width < 0) {
+-				field_width = -field_width;
+-				flags |= LEFT;
+-			}
++		field_width = get_int(&fmt, &args);
++		if (field_width < 0) {
++			field_width = -field_width;
++			flags |= LEFT;
+ 		}
+ 
+ 		/* get the precision */
+ 		precision = -1;
+ 		if (*fmt == '.') {
+ 			++fmt;
+-			if (isdigit(*fmt)) {
+-				precision = skip_atoi(&fmt);
+-			} else if (*fmt == '*') {
+-				++fmt;
+-				/* it's the next argument */
+-				precision = va_arg(args, int);
+-			} else {
+-				precision = 0;
+-			}
++			precision = get_int(&fmt, &args);
+ 			if (precision >= 0)
+ 				flags &= ~ZEROPAD;
+ 		}
+@@ -392,6 +408,9 @@ int vsprintf(char *buf, const char *fmt, va_list args)
+ 		str = number(str, num, base, field_width, precision, flags);
+ 	}
+ 	*str = '\0';
++
++	va_end(args);
++
+ 	return str - buf;
+ }
+ 

commit 7c30fd79168aeb83d11260246d93f8a293052007
+Author: Arvind Sankar 
+Date:   Mon May 18 15:07:02 2020 -0400
+
+    efi/printf: Merge 'p' with the integer formats
+    
+    Treat 'p' as a hexadecimal integer with precision equal to the number of
+    digits in void *.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200518190716.751506-11-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/vsprintf.c b/drivers/firmware/efi/libstub/vsprintf.c
+index 00123d5f402f..b7316ab9f8b4 100644
+--- a/drivers/firmware/efi/libstub/vsprintf.c
++++ b/drivers/firmware/efi/libstub/vsprintf.c
+@@ -297,9 +297,6 @@ int vsprintf(char *buf, const char *fmt, va_list args)
+ 			}
+ 		}
+ 
+-		/* default base */
+-		base = 10;
+-
+ 		switch (*fmt) {
+ 		case 'c':
+ 			if (!(flags & LEFT))
+@@ -323,21 +320,15 @@ int vsprintf(char *buf, const char *fmt, va_list args)
+ 				*str++ = ' ';
+ 			continue;
+ 
+-		case 'p':
+-			if (field_width == -1) {
+-				field_width = 2 * sizeof(void *);
+-				flags |= ZEROPAD;
+-			}
+-			str = number(str,
+-				     (unsigned long)va_arg(args, void *), 16,
+-				     field_width, precision, flags);
+-			continue;
+-
+ 			/* integer number formats - set up the flags and "break" */
+ 		case 'o':
+ 			base = 8;
+ 			break;
+ 
++		case 'p':
++			if (precision < 0)
++				precision = 2 * sizeof(void *);
++			fallthrough;
+ 		case 'x':
+ 			flags |= SMALL;
+ 			fallthrough;
+@@ -350,6 +341,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
+ 			flags |= SIGN;
+ 			fallthrough;
+ 		case 'u':
++			base = 10;
+ 			break;
+ 
+ 		default:
+@@ -360,7 +352,9 @@ int vsprintf(char *buf, const char *fmt, va_list args)
+ 				--fmt;
+ 			continue;
+ 		}
+-		if (flags & SIGN) {
++		if (*fmt == 'p') {
++			num = (unsigned long)va_arg(args, void *);
++		} else if (flags & SIGN) {
+ 			switch (qualifier) {
+ 			case 'L':
+ 				num = va_arg(args, long long);

commit 77e48db04a02ebd00229281c26575979b0b465e0
+Author: Arvind Sankar 
+Date:   Mon May 18 15:07:01 2020 -0400
+
+    efi/printf: Fix minor bug in precision handling
+    
+    A negative precision should be ignored completely, and the presence of a
+    valid precision should turn off the 0 flag.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200518190716.751506-10-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/vsprintf.c b/drivers/firmware/efi/libstub/vsprintf.c
+index fb9eb83f1728..00123d5f402f 100644
+--- a/drivers/firmware/efi/libstub/vsprintf.c
++++ b/drivers/firmware/efi/libstub/vsprintf.c
+@@ -279,9 +279,11 @@ int vsprintf(char *buf, const char *fmt, va_list args)
+ 				++fmt;
+ 				/* it's the next argument */
+ 				precision = va_arg(args, int);
+-			}
+-			if (precision < 0)
++			} else {
+ 				precision = 0;
++			}
++			if (precision >= 0)
++				flags &= ~ZEROPAD;
+ 		}
+ 
+ 		/* get the conversion qualifier */

commit 3b8350959cba0df4070741618e50c367319793bb
+Author: Arvind Sankar 
+Date:   Mon May 18 15:07:00 2020 -0400
+
+    efi/printf: Factor out flags parsing and handle '%' earlier
+    
+    Move flags parsing code out into a helper function.
+    
+    The '%%' case can be handled up front: it is not allowed to have flags,
+    width etc.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200518190716.751506-9-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/vsprintf.c b/drivers/firmware/efi/libstub/vsprintf.c
+index 8fd15e87d18c..fb9eb83f1728 100644
+--- a/drivers/firmware/efi/libstub/vsprintf.c
++++ b/drivers/firmware/efi/libstub/vsprintf.c
+@@ -202,6 +202,35 @@ static char *number(char *str, long long num, int base, int size, int precision,
+ 	return str;
+ }
+ 
++static
++int get_flags(const char **fmt)
++{
++	int flags = 0;
++
++	do {
++		switch (**fmt) {
++		case '-':
++			flags |= LEFT;
++			break;
++		case '+':
++			flags |= PLUS;
++			break;
++		case ' ':
++			flags |= SPACE;
++			break;
++		case '#':
++			flags |= SPECIAL;
++			break;
++		case '0':
++			flags |= ZEROPAD;
++			break;
++		default:
++			return flags;
++		}
++		++(*fmt);
++	} while (1);
++}
++
+ int vsprintf(char *buf, const char *fmt, va_list args)
+ {
+ 	int len;
+@@ -218,32 +247,13 @@ int vsprintf(char *buf, const char *fmt, va_list args)
+ 	int qualifier;		/* 'h', 'hh', 'l' or 'll' for integer fields */
+ 
+ 	for (str = buf; *fmt; ++fmt) {
+-		if (*fmt != '%') {
++		if (*fmt != '%' || *++fmt == '%') {
+ 			*str++ = *fmt;
+ 			continue;
+ 		}
+ 
+ 		/* process flags */
+-		flags = 0;
+-	      repeat:
+-		++fmt;		/* this also skips first '%' */
+-		switch (*fmt) {
+-		case '-':
+-			flags |= LEFT;
+-			goto repeat;
+-		case '+':
+-			flags |= PLUS;
+-			goto repeat;
+-		case ' ':
+-			flags |= SPACE;
+-			goto repeat;
+-		case '#':
+-			flags |= SPECIAL;
+-			goto repeat;
+-		case '0':
+-			flags |= ZEROPAD;
+-			goto repeat;
+-		}
++		flags = get_flags(&fmt);
+ 
+ 		/* get field width */
+ 		field_width = -1;
+@@ -321,10 +331,6 @@ int vsprintf(char *buf, const char *fmt, va_list args)
+ 				     field_width, precision, flags);
+ 			continue;
+ 
+-		case '%':
+-			*str++ = '%';
+-			continue;
+-
+ 			/* integer number formats - set up the flags and "break" */
+ 		case 'o':
+ 			base = 8;

commit ce5e3f909fc0ed67e58367b9c56a54c20a51080b
+Author: Arvind Sankar 
+Date:   Mon May 18 15:06:59 2020 -0400
+
+    efi/printf: Add 64-bit and 8-bit integer support
+    
+    Support 'll' qualifier for long long by copying the decimal printing
+    code from lib/vsprintf.c. For simplicity, the 32-bit code is used on
+    64-bit architectures as well.
+    
+    Support 'hh' qualifier for signed/unsigned char type integers.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200518190716.751506-8-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/vsprintf.c b/drivers/firmware/efi/libstub/vsprintf.c
+index 52cf22d0b6e5..8fd15e87d18c 100644
+--- a/drivers/firmware/efi/libstub/vsprintf.c
++++ b/drivers/firmware/efi/libstub/vsprintf.c
+@@ -7,10 +7,7 @@
+  * ----------------------------------------------------------------------- */
+ 
+ /*
+- * Oh, it's a waste of space, but oh-so-yummy for debugging.  This
+- * version of printf() does not include 64-bit support.  "Live with
+- * it."
+- *
++ * Oh, it's a waste of space, but oh-so-yummy for debugging.
+  */
+ 
+ #include 
+@@ -28,6 +25,86 @@ static int skip_atoi(const char **s)
+ 	return i;
+ }
+ 
++/*
++ * put_dec_full4 handles numbers in the range 0 <= r < 10000.
++ * The multiplier 0xccd is round(2^15/10), and the approximation
++ * r/10 == (r * 0xccd) >> 15 is exact for all r < 16389.
++ */
++static
++void put_dec_full4(char *buf, unsigned int r)
++{
++	int i;
++
++	for (i = 0; i < 3; i++) {
++		unsigned int q = (r * 0xccd) >> 15;
++		*buf++ = '0' + (r - q * 10);
++		r = q;
++	}
++	*buf++ = '0' + r;
++}
++
++/* put_dec is copied from lib/vsprintf.c with small modifications */
++
++/*
++ * Call put_dec_full4 on x % 10000, return x / 10000.
++ * The approximation x/10000 == (x * 0x346DC5D7) >> 43
++ * holds for all x < 1,128,869,999.  The largest value this
++ * helper will ever be asked to convert is 1,125,520,955.
++ * (second call in the put_dec code, assuming n is all-ones).
++ */
++static
++unsigned int put_dec_helper4(char *buf, unsigned int x)
++{
++	unsigned int q = (x * 0x346DC5D7ULL) >> 43;
++
++	put_dec_full4(buf, x - q * 10000);
++	return q;
++}
++
++/* Based on code by Douglas W. Jones found at
++ * 
++ * (with permission from the author).
++ * Performs no 64-bit division and hence should be fast on 32-bit machines.
++ */
++static
++int put_dec(char *buf, unsigned long long n)
++{
++	unsigned int d3, d2, d1, q, h;
++	char *p = buf;
++
++	d1  = ((unsigned int)n >> 16); /* implicit "& 0xffff" */
++	h   = (n >> 32);
++	d2  = (h      ) & 0xffff;
++	d3  = (h >> 16); /* implicit "& 0xffff" */
++
++	/* n = 2^48 d3 + 2^32 d2 + 2^16 d1 + d0
++	     = 281_4749_7671_0656 d3 + 42_9496_7296 d2 + 6_5536 d1 + d0 */
++	q = 656 * d3 + 7296 * d2 + 5536 * d1 + ((unsigned int)n & 0xffff);
++	q = put_dec_helper4(p, q);
++	p += 4;
++
++	q += 7671 * d3 + 9496 * d2 + 6 * d1;
++	q = put_dec_helper4(p, q);
++	p += 4;
++
++	q += 4749 * d3 + 42 * d2;
++	q = put_dec_helper4(p, q);
++	p += 4;
++
++	q += 281 * d3;
++	q = put_dec_helper4(p, q);
++	p += 4;
++
++	put_dec_full4(p, q);
++	p += 4;
++
++	/* strip off the extra 0's we printed */
++	while (p > buf && p[-1] == '0')
++		--p;
++
++	return p - buf;
++}
++
+ #define ZEROPAD	1		/* pad with zero */
+ #define SIGN	2		/* unsigned/signed long */
+ #define PLUS	4		/* show plus */
+@@ -36,13 +113,7 @@ static int skip_atoi(const char **s)
+ #define SMALL	32		/* Must be 32 == 0x20 */
+ #define SPECIAL	64		/* 0x */
+ 
+-#define __do_div(n, base) ({ \
+-int __res; \
+-__res = ((unsigned long) n) % (unsigned) base; \
+-n = ((unsigned long) n) / (unsigned) base; \
+-__res; })
+-
+-static char *number(char *str, long num, int base, int size, int precision,
++static char *number(char *str, long long num, int base, int size, int precision,
+ 		    int type)
+ {
+ 	/* we are called with base 8, 10 or 16, only, thus don't need "G..."  */
+@@ -57,8 +128,6 @@ static char *number(char *str, long num, int base, int size, int precision,
+ 	locase = (type & SMALL);
+ 	if (type & LEFT)
+ 		type &= ~ZEROPAD;
+-	if (base < 2 || base > 16)
+-		return NULL;
+ 	c = (type & ZEROPAD) ? '0' : ' ';
+ 	sign = 0;
+ 	if (type & SIGN) {
+@@ -83,9 +152,28 @@ static char *number(char *str, long num, int base, int size, int precision,
+ 	i = 0;
+ 	if (num == 0)
+ 		tmp[i++] = '0';
+-	else
+-		while (num != 0)
+-			tmp[i++] = (digits[__do_div(num, base)] | locase);
++	else {
++		switch (base) {
++		case 10:
++			i += put_dec(&tmp[i], num);
++			break;
++		case 8:
++			while (num != 0) {
++				tmp[i++] = '0' + (num & 07);
++				num = (unsigned long long)num >> 3;
++			}
++			break;
++		case 16:
++			while (num != 0) {
++				tmp[i++] = digits[num & 0xf] | locase;
++				num = (unsigned long long)num >> 4;
++			}
++			break;
++		default:
++			unreachable();
++		}
++	}
++
+ 	if (i > precision)
+ 		precision = i;
+ 	size -= precision;
+@@ -117,7 +205,7 @@ static char *number(char *str, long num, int base, int size, int precision,
+ int vsprintf(char *buf, const char *fmt, va_list args)
+ {
+ 	int len;
+-	unsigned long num;
++	unsigned long long num;
+ 	int i, base;
+ 	char *str;
+ 	const char *s;
+@@ -127,7 +215,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
+ 	int field_width;	/* width of output field */
+ 	int precision;		/* min. # of digits for integers; max
+ 				   number of chars for from string */
+-	int qualifier;		/* 'h' or 'l' for integer fields */
++	int qualifier;		/* 'h', 'hh', 'l' or 'll' for integer fields */
+ 
+ 	for (str = buf; *fmt; ++fmt) {
+ 		if (*fmt != '%') {
+@@ -191,6 +279,10 @@ int vsprintf(char *buf, const char *fmt, va_list args)
+ 		if (*fmt == 'h' || *fmt == 'l') {
+ 			qualifier = *fmt;
+ 			++fmt;
++			if (qualifier == *fmt) {
++				qualifier -= 'a'-'A';
++				++fmt;
++			}
+ 		}
+ 
+ 		/* default base */
+@@ -260,16 +352,40 @@ int vsprintf(char *buf, const char *fmt, va_list args)
+ 				--fmt;
+ 			continue;
+ 		}
+-		if (qualifier == 'l') {
+-			num = va_arg(args, unsigned long);
+-		} else if (qualifier == 'h') {
+-			num = (unsigned short)va_arg(args, int);
+-			if (flags & SIGN)
+-				num = (short)num;
+-		} else if (flags & SIGN) {
+-			num = va_arg(args, int);
++		if (flags & SIGN) {
++			switch (qualifier) {
++			case 'L':
++				num = va_arg(args, long long);
++				break;
++			case 'l':
++				num = va_arg(args, long);
++				break;
++			case 'h':
++				num = (short)va_arg(args, int);
++				break;
++			case 'H':
++				num = (signed char)va_arg(args, int);
++				break;
++			default:
++				num = va_arg(args, int);
++			}
+ 		} else {
+-			num = va_arg(args, unsigned int);
++			switch (qualifier) {
++			case 'L':
++				num = va_arg(args, unsigned long long);
++				break;
++			case 'l':
++				num = va_arg(args, unsigned long);
++				break;
++			case 'h':
++				num = (unsigned short)va_arg(args, int);
++				break;
++			case 'H':
++				num = (unsigned char)va_arg(args, int);
++				break;
++			default:
++				num = va_arg(args, unsigned int);
++			}
+ 		}
+ 		str = number(str, num, base, field_width, precision, flags);
+ 	}

commit 29a2806653360f1ba0f7608ef64d65d441a575f7
+Author: Arvind Sankar 
+Date:   Mon May 18 15:06:58 2020 -0400
+
+    efi/printf: Drop %n format and L qualifier
+    
+    %n is unused and deprecated.
+    
+    The L qualifer is parsed but not actually implemented.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200518190716.751506-7-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/vsprintf.c b/drivers/firmware/efi/libstub/vsprintf.c
+index bb62d3726c65..52cf22d0b6e5 100644
+--- a/drivers/firmware/efi/libstub/vsprintf.c
++++ b/drivers/firmware/efi/libstub/vsprintf.c
+@@ -127,7 +127,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
+ 	int field_width;	/* width of output field */
+ 	int precision;		/* min. # of digits for integers; max
+ 				   number of chars for from string */
+-	int qualifier;		/* 'h', 'l', or 'L' for integer fields */
++	int qualifier;		/* 'h' or 'l' for integer fields */
+ 
+ 	for (str = buf; *fmt; ++fmt) {
+ 		if (*fmt != '%') {
+@@ -188,7 +188,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
+ 
+ 		/* get the conversion qualifier */
+ 		qualifier = -1;
+-		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
++		if (*fmt == 'h' || *fmt == 'l') {
+ 			qualifier = *fmt;
+ 			++fmt;
+ 		}
+@@ -229,16 +229,6 @@ int vsprintf(char *buf, const char *fmt, va_list args)
+ 				     field_width, precision, flags);
+ 			continue;
+ 
+-		case 'n':
+-			if (qualifier == 'l') {
+-				long *ip = va_arg(args, long *);
+-				*ip = (str - buf);
+-			} else {
+-				int *ip = va_arg(args, int *);
+-				*ip = (str - buf);
+-			}
+-			continue;
+-
+ 		case '%':
+ 			*str++ = '%';
+ 			continue;

commit bbf8e8b0fe0401e1952c77088692fd273a9635a1
+Author: Arvind Sankar 
+Date:   Mon May 18 15:06:57 2020 -0400
+
+    efi/libstub: Optimize for size instead of speed
+    
+    Reclaim the bloat from the addition of printf by optimizing the stub for
+    size. With gcc 9, the text size of the stub is:
+    
+    ARCH    before  +printf    -Os
+    arm      35197    37889  34638
+    arm64    34883    38159  34479
+    i386     18571    21657  17025
+    x86_64   25677    29328  22144
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200518190716.751506-6-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
+index fb34c9d14a3c..034d71663b1e 100644
+--- a/drivers/firmware/efi/libstub/Makefile
++++ b/drivers/firmware/efi/libstub/Makefile
+@@ -7,7 +7,7 @@
+ #
+ cflags-$(CONFIG_X86_32)		:= -march=i386
+ cflags-$(CONFIG_X86_64)		:= -mcmodel=small
+-cflags-$(CONFIG_X86)		+= -m$(BITS) -D__KERNEL__ -O2 \
++cflags-$(CONFIG_X86)		+= -m$(BITS) -D__KERNEL__ \
+ 				   -fPIC -fno-strict-aliasing -mno-red-zone \
+ 				   -mno-mmx -mno-sse -fshort-wchar \
+ 				   -Wno-pointer-sign \
+@@ -25,7 +25,7 @@ cflags-$(CONFIG_ARM)		:= $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \
+ 
+ cflags-$(CONFIG_EFI_GENERIC_STUB) += -I$(srctree)/scripts/dtc/libfdt
+ 
+-KBUILD_CFLAGS			:= $(cflags-y) -DDISABLE_BRANCH_PROFILING \
++KBUILD_CFLAGS			:= $(cflags-y) -Os -DDISABLE_BRANCH_PROFILING \
+ 				   -include $(srctree)/drivers/firmware/efi/libstub/hidden.h \
+ 				   -D__NO_FORTIFY \
+ 				   $(call cc-option,-ffreestanding) \

commit 2c7d1e30e5884dc6f6727ecd9417491c9f321b59
+Author: Arvind Sankar 
+Date:   Mon May 18 15:06:56 2020 -0400
+
+    efi/libstub: Add a basic printf implementation
+    
+    Copy vsprintf from arch/x86/boot/printf.c to get a simple printf
+    implementation.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200518190716.751506-5-nivedita@alum.mit.edu
+    [ardb: add some missing braces in if...else clauses]
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
+index e5a49dc8e9bc..fb34c9d14a3c 100644
+--- a/drivers/firmware/efi/libstub/Makefile
++++ b/drivers/firmware/efi/libstub/Makefile
+@@ -44,7 +44,7 @@ KCOV_INSTRUMENT			:= n
+ lib-y				:= efi-stub-helper.o gop.o secureboot.o tpm.o \
+ 				   file.o mem.o random.o randomalloc.o pci.o \
+ 				   skip_spaces.o lib-cmdline.o lib-ctype.o \
+-				   alignedmem.o relocate.o
++				   alignedmem.o relocate.o vsprintf.o
+ 
+ # include the stub's generic dependencies from lib/ when building for ARM/arm64
+ efi-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c
+diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
+index 3cf506ab9ead..56b3b84fd3bd 100644
+--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
++++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
+@@ -7,6 +7,8 @@
+  * Copyright 2011 Intel Corporation; author Matt Fleming
+  */
+ 
++#include 
++
+ #include 
+ #include 
+ #include 
+@@ -51,6 +53,21 @@ void efi_puts(const char *str)
+ 	}
+ }
+ 
++int efi_printk(const char *fmt, ...)
++{
++	char printf_buf[256];
++	va_list args;
++	int printed;
++
++	va_start(args, fmt);
++	printed = vsprintf(printf_buf, fmt, args);
++	va_end(args);
++
++	efi_puts(printf_buf);
++
++	return printed;
++}
++
+ /*
+  * Parse the ASCII string 'cmdline' for EFI options, denoted by the efi=
+  * option, e.g. efi=nochunk.
+diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
+index 4f57611a65f2..caa7dcc71c69 100644
+--- a/drivers/firmware/efi/libstub/efistub.h
++++ b/drivers/firmware/efi/libstub/efistub.h
+@@ -3,6 +3,7 @@
+ #ifndef _DRIVERS_FIRMWARE_EFI_EFISTUB_H
+ #define _DRIVERS_FIRMWARE_EFI_EFISTUB_H
+ 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -632,6 +633,8 @@ void *get_efi_config_table(efi_guid_t guid);
+ void efi_char16_puts(efi_char16_t *);
+ void efi_puts(const char *str);
+ 
++__printf(1, 2) int efi_printk(char const *fmt, ...);
++
+ void efi_free(unsigned long size, unsigned long addr);
+ 
+ char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len,
+diff --git a/drivers/firmware/efi/libstub/vsprintf.c b/drivers/firmware/efi/libstub/vsprintf.c
+new file mode 100644
+index 000000000000..bb62d3726c65
+--- /dev/null
++++ b/drivers/firmware/efi/libstub/vsprintf.c
+@@ -0,0 +1,299 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/* -*- linux-c -*- ------------------------------------------------------- *
++ *
++ *   Copyright (C) 1991, 1992 Linus Torvalds
++ *   Copyright 2007 rPath, Inc. - All Rights Reserved
++ *
++ * ----------------------------------------------------------------------- */
++
++/*
++ * Oh, it's a waste of space, but oh-so-yummy for debugging.  This
++ * version of printf() does not include 64-bit support.  "Live with
++ * it."
++ *
++ */
++
++#include 
++
++#include 
++#include 
++#include 
++
++static int skip_atoi(const char **s)
++{
++	int i = 0;
++
++	while (isdigit(**s))
++		i = i * 10 + *((*s)++) - '0';
++	return i;
++}
++
++#define ZEROPAD	1		/* pad with zero */
++#define SIGN	2		/* unsigned/signed long */
++#define PLUS	4		/* show plus */
++#define SPACE	8		/* space if plus */
++#define LEFT	16		/* left justified */
++#define SMALL	32		/* Must be 32 == 0x20 */
++#define SPECIAL	64		/* 0x */
++
++#define __do_div(n, base) ({ \
++int __res; \
++__res = ((unsigned long) n) % (unsigned) base; \
++n = ((unsigned long) n) / (unsigned) base; \
++__res; })
++
++static char *number(char *str, long num, int base, int size, int precision,
++		    int type)
++{
++	/* we are called with base 8, 10 or 16, only, thus don't need "G..."  */
++	static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
++
++	char tmp[66];
++	char c, sign, locase;
++	int i;
++
++	/* locase = 0 or 0x20. ORing digits or letters with 'locase'
++	 * produces same digits or (maybe lowercased) letters */
++	locase = (type & SMALL);
++	if (type & LEFT)
++		type &= ~ZEROPAD;
++	if (base < 2 || base > 16)
++		return NULL;
++	c = (type & ZEROPAD) ? '0' : ' ';
++	sign = 0;
++	if (type & SIGN) {
++		if (num < 0) {
++			sign = '-';
++			num = -num;
++			size--;
++		} else if (type & PLUS) {
++			sign = '+';
++			size--;
++		} else if (type & SPACE) {
++			sign = ' ';
++			size--;
++		}
++	}
++	if (type & SPECIAL) {
++		if (base == 16)
++			size -= 2;
++		else if (base == 8)
++			size--;
++	}
++	i = 0;
++	if (num == 0)
++		tmp[i++] = '0';
++	else
++		while (num != 0)
++			tmp[i++] = (digits[__do_div(num, base)] | locase);
++	if (i > precision)
++		precision = i;
++	size -= precision;
++	if (!(type & (ZEROPAD + LEFT)))
++		while (size-- > 0)
++			*str++ = ' ';
++	if (sign)
++		*str++ = sign;
++	if (type & SPECIAL) {
++		if (base == 8) {
++			*str++ = '0';
++		} else if (base == 16) {
++			*str++ = '0';
++			*str++ = ('X' | locase);
++		}
++	}
++	if (!(type & LEFT))
++		while (size-- > 0)
++			*str++ = c;
++	while (i < precision--)
++		*str++ = '0';
++	while (i-- > 0)
++		*str++ = tmp[i];
++	while (size-- > 0)
++		*str++ = ' ';
++	return str;
++}
++
++int vsprintf(char *buf, const char *fmt, va_list args)
++{
++	int len;
++	unsigned long num;
++	int i, base;
++	char *str;
++	const char *s;
++
++	int flags;		/* flags to number() */
++
++	int field_width;	/* width of output field */
++	int precision;		/* min. # of digits for integers; max
++				   number of chars for from string */
++	int qualifier;		/* 'h', 'l', or 'L' for integer fields */
++
++	for (str = buf; *fmt; ++fmt) {
++		if (*fmt != '%') {
++			*str++ = *fmt;
++			continue;
++		}
++
++		/* process flags */
++		flags = 0;
++	      repeat:
++		++fmt;		/* this also skips first '%' */
++		switch (*fmt) {
++		case '-':
++			flags |= LEFT;
++			goto repeat;
++		case '+':
++			flags |= PLUS;
++			goto repeat;
++		case ' ':
++			flags |= SPACE;
++			goto repeat;
++		case '#':
++			flags |= SPECIAL;
++			goto repeat;
++		case '0':
++			flags |= ZEROPAD;
++			goto repeat;
++		}
++
++		/* get field width */
++		field_width = -1;
++		if (isdigit(*fmt)) {
++			field_width = skip_atoi(&fmt);
++		} else if (*fmt == '*') {
++			++fmt;
++			/* it's the next argument */
++			field_width = va_arg(args, int);
++			if (field_width < 0) {
++				field_width = -field_width;
++				flags |= LEFT;
++			}
++		}
++
++		/* get the precision */
++		precision = -1;
++		if (*fmt == '.') {
++			++fmt;
++			if (isdigit(*fmt)) {
++				precision = skip_atoi(&fmt);
++			} else if (*fmt == '*') {
++				++fmt;
++				/* it's the next argument */
++				precision = va_arg(args, int);
++			}
++			if (precision < 0)
++				precision = 0;
++		}
++
++		/* get the conversion qualifier */
++		qualifier = -1;
++		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
++			qualifier = *fmt;
++			++fmt;
++		}
++
++		/* default base */
++		base = 10;
++
++		switch (*fmt) {
++		case 'c':
++			if (!(flags & LEFT))
++				while (--field_width > 0)
++					*str++ = ' ';
++			*str++ = (unsigned char)va_arg(args, int);
++			while (--field_width > 0)
++				*str++ = ' ';
++			continue;
++
++		case 's':
++			s = va_arg(args, char *);
++			len = strnlen(s, precision);
++
++			if (!(flags & LEFT))
++				while (len < field_width--)
++					*str++ = ' ';
++			for (i = 0; i < len; ++i)
++				*str++ = *s++;
++			while (len < field_width--)
++				*str++ = ' ';
++			continue;
++
++		case 'p':
++			if (field_width == -1) {
++				field_width = 2 * sizeof(void *);
++				flags |= ZEROPAD;
++			}
++			str = number(str,
++				     (unsigned long)va_arg(args, void *), 16,
++				     field_width, precision, flags);
++			continue;
++
++		case 'n':
++			if (qualifier == 'l') {
++				long *ip = va_arg(args, long *);
++				*ip = (str - buf);
++			} else {
++				int *ip = va_arg(args, int *);
++				*ip = (str - buf);
++			}
++			continue;
++
++		case '%':
++			*str++ = '%';
++			continue;
++
++			/* integer number formats - set up the flags and "break" */
++		case 'o':
++			base = 8;
++			break;
++
++		case 'x':
++			flags |= SMALL;
++			fallthrough;
++		case 'X':
++			base = 16;
++			break;
++
++		case 'd':
++		case 'i':
++			flags |= SIGN;
++			fallthrough;
++		case 'u':
++			break;
++
++		default:
++			*str++ = '%';
++			if (*fmt)
++				*str++ = *fmt;
++			else
++				--fmt;
++			continue;
++		}
++		if (qualifier == 'l') {
++			num = va_arg(args, unsigned long);
++		} else if (qualifier == 'h') {
++			num = (unsigned short)va_arg(args, int);
++			if (flags & SIGN)
++				num = (short)num;
++		} else if (flags & SIGN) {
++			num = va_arg(args, int);
++		} else {
++			num = va_arg(args, unsigned int);
++		}
++		str = number(str, num, base, field_width, precision, flags);
++	}
++	*str = '\0';
++	return str - buf;
++}
++
++int sprintf(char *buf, const char *fmt, ...)
++{
++	va_list args;
++	int i;
++
++	va_start(args, fmt);
++	i = vsprintf(buf, fmt, args);
++	va_end(args);
++	return i;
++}

commit fd0528a24958b7e8d55669cf50749776308d4c5a
+Author: Arvind Sankar 
+Date:   Mon May 18 15:06:55 2020 -0400
+
+    efi/libstub: Buffer output of efi_puts
+    
+    Use a buffer to convert the string to UTF-16. This will reduce the
+    number of firmware calls required to print the string from one per
+    character to one per string in most cases.
+    
+    Cast the input char to unsigned char before converting to efi_char16_t
+    to avoid sign-extension in case there are any non-ASCII characters in
+    the input.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200518190716.751506-4-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
+index c6d7ef35e9f7..3cf506ab9ead 100644
+--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
++++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
+@@ -8,6 +8,7 @@
+  */
+ 
+ #include 
++#include 
+ #include 
+ 
+ #include "efistub.h"
+@@ -34,13 +35,19 @@ void efi_char16_puts(efi_char16_t *str)
+ 
+ void efi_puts(const char *str)
+ {
+-	while (*str) {
+-		efi_char16_t ch[] = { *str++, L'\0' };
++	efi_char16_t buf[128];
++	size_t pos = 0, lim = ARRAY_SIZE(buf);
+ 
+-		if (ch[0] == L'\n')
+-			efi_char16_puts(L"\r\n");
+-		else
+-			efi_char16_puts(ch);
++	while (*str) {
++		if (*str == '\n')
++			buf[pos++] = L'\r';
++		/* Cast to unsigned char to avoid sign-extension */
++		buf[pos++] = (unsigned char)(*str++);
++		if (*str == '\0' || pos >= lim - 2) {
++			buf[pos] = L'\0';
++			efi_char16_puts(buf);
++			pos = 0;
++		}
+ 	}
+ }
+ 

commit cb8c90a08c7f2f761919190093fca0611c1cece4
+Author: Arvind Sankar 
+Date:   Mon May 18 15:06:54 2020 -0400
+
+    efi/libstub: Rename efi_[char16_]printk to efi_[char16_]puts
+    
+    These functions do not support formatting, unlike printk. Rename them to
+    puts to make that clear.
+    
+    Move the implementations of these two functions next to each other.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200518190716.751506-3-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
+index 2927f3d30344..c6d7ef35e9f7 100644
+--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
++++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
+@@ -26,15 +26,21 @@ bool __pure __efi_soft_reserve_enabled(void)
+ 	return !efi_nosoftreserve;
+ }
+ 
+-void efi_printk(const char *str)
++void efi_char16_puts(efi_char16_t *str)
++{
++	efi_call_proto(efi_table_attr(efi_system_table, con_out),
++		       output_string, str);
++}
++
++void efi_puts(const char *str)
+ {
+ 	while (*str) {
+ 		efi_char16_t ch[] = { *str++, L'\0' };
+ 
+ 		if (ch[0] == L'\n')
+-			efi_char16_printk(L"\r\n");
++			efi_char16_puts(L"\r\n");
+ 		else
+-			efi_char16_printk(ch);
++			efi_char16_puts(ch);
+ 	}
+ }
+ 
+@@ -279,12 +285,6 @@ void *get_efi_config_table(efi_guid_t guid)
+ 	return NULL;
+ }
+ 
+-void efi_char16_printk(efi_char16_t *str)
+-{
+-	efi_call_proto(efi_table_attr(efi_system_table, con_out),
+-		       output_string, str);
+-}
+-
+ /*
+  * The LINUX_EFI_INITRD_MEDIA_GUID vendor media device path below provides a way
+  * for the firmware or bootloader to expose the initrd data directly to the stub
+diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
+index 998924916b03..4f57611a65f2 100644
+--- a/drivers/firmware/efi/libstub/efistub.h
++++ b/drivers/firmware/efi/libstub/efistub.h
+@@ -49,10 +49,10 @@ extern const efi_system_table_t *efi_system_table;
+ #endif
+ 
+ #define efi_info(msg)		do {			\
+-	if (!efi_quiet) efi_printk("EFI stub: "msg);	\
++	if (!efi_quiet) efi_puts("EFI stub: "msg);	\
+ } while (0)
+ 
+-#define efi_err(msg) efi_printk("EFI stub: ERROR: "msg)
++#define efi_err(msg) efi_puts("EFI stub: ERROR: "msg)
+ 
+ /* Helper macros for the usual case of using simple C variables: */
+ #ifndef fdt_setprop_inplace_var
+@@ -605,8 +605,6 @@ efi_status_t efi_exit_boot_services(void *handle,
+ 				    void *priv,
+ 				    efi_exit_boot_map_processing priv_func);
+ 
+-void efi_char16_printk(efi_char16_t *);
+-
+ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
+ 					    unsigned long *new_fdt_addr,
+ 					    unsigned long max_addr,
+@@ -630,7 +628,9 @@ efi_status_t check_platform_features(void);
+ 
+ void *get_efi_config_table(efi_guid_t guid);
+ 
+-void efi_printk(const char *str);
++/* NOTE: These functions do not print a trailing newline after the string */
++void efi_char16_puts(efi_char16_t *);
++void efi_puts(const char *str);
+ 
+ void efi_free(unsigned long size, unsigned long addr);
+ 
+diff --git a/drivers/firmware/efi/libstub/file.c b/drivers/firmware/efi/libstub/file.c
+index cc177152d0df..933536c5236a 100644
+--- a/drivers/firmware/efi/libstub/file.c
++++ b/drivers/firmware/efi/libstub/file.c
+@@ -47,8 +47,8 @@ static efi_status_t efi_open_file(efi_file_protocol_t *volume,
+ 	status = volume->open(volume, &fh, fi->filename, EFI_FILE_MODE_READ, 0);
+ 	if (status != EFI_SUCCESS) {
+ 		efi_err("Failed to open file: ");
+-		efi_char16_printk(fi->filename);
+-		efi_printk("\n");
++		efi_char16_puts(fi->filename);
++		efi_puts("\n");
+ 		return status;
+ 	}
+ 

commit 0b76735380224497e1c78a1bed606cbda83e3427
+Author: Arvind Sankar 
+Date:   Mon May 18 15:06:53 2020 -0400
+
+    efi/libstub: Include dependencies of efistub.h
+    
+    Add #include directives for include files that efistub.h depends on,
+    instead of relying on them having been included by the C source files
+    prior to efistub.h.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200518190716.751506-2-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
+index 15d0b6f3f6c6..998924916b03 100644
+--- a/drivers/firmware/efi/libstub/efistub.h
++++ b/drivers/firmware/efi/libstub/efistub.h
+@@ -3,6 +3,11 @@
+ #ifndef _DRIVERS_FIRMWARE_EFI_EFISTUB_H
+ #define _DRIVERS_FIRMWARE_EFI_EFISTUB_H
+ 
++#include 
++#include 
++#include 
++#include 
++
+ /* error code which can't be mistaken for valid address */
+ #define EFI_ERROR	(~0UL)
+ 

commit e78d334a5470ead861590ec83158f3b17bd6c807
+Author: Arvind Sankar 
+Date:   Mon May 11 18:58:49 2020 -0400
+
+    x86/boot: Mark global variables as static
+    
+    Mike Lothian reports that after commit
+      964124a97b97 ("efi/x86: Remove extra headroom for setup block")
+    gcc 10.1.0 fails with
+    
+      HOSTCC  arch/x86/boot/tools/build
+      /usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../x86_64-pc-linux-gnu/bin/ld:
+      error: linker defined: multiple definition of '_end'
+      /usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../x86_64-pc-linux-gnu/bin/ld:
+      /tmp/ccEkW0jM.o: previous definition here
+      collect2: error: ld returned 1 exit status
+      make[1]: *** [scripts/Makefile.host:103: arch/x86/boot/tools/build] Error 1
+      make: *** [arch/x86/Makefile:303: bzImage] Error 2
+    
+    The issue is with the _end variable that was added, to hold the end of
+    the compressed kernel from zoffsets.h (ZO__end). The name clashes with
+    the linker-defined _end symbol that indicates the end of the build
+    program itself.
+    
+    Even when there is no compile-time error, this causes build to use
+    memory past the end of its .bss section.
+    
+    To solve this, mark _end as static, and for symmetry, mark the rest of
+    the variables that keep track of symbols from the compressed kernel as
+    static as well.
+    
+    Fixes: 964124a97b97 ("efi/x86: Remove extra headroom for setup block")
+    Reported-by: Mike Lothian 
+    Tested-by: Mike Lothian 
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200511225849.1311869-1-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c
+index 8f8c8e386cea..c8b8c1a8d1fc 100644
+--- a/arch/x86/boot/tools/build.c
++++ b/arch/x86/boot/tools/build.c
+@@ -59,14 +59,14 @@ u8 buf[SETUP_SECT_MAX*512];
+ #define PECOFF_COMPAT_RESERVE 0x0
+ #endif
+ 
+-unsigned long efi32_stub_entry;
+-unsigned long efi64_stub_entry;
+-unsigned long efi_pe_entry;
+-unsigned long efi32_pe_entry;
+-unsigned long kernel_info;
+-unsigned long startup_64;
+-unsigned long _ehead;
+-unsigned long _end;
++static unsigned long efi32_stub_entry;
++static unsigned long efi64_stub_entry;
++static unsigned long efi_pe_entry;
++static unsigned long efi32_pe_entry;
++static unsigned long kernel_info;
++static unsigned long startup_64;
++static unsigned long _ehead;
++static unsigned long _end;
+ 
+ /*----------------------------------------------------------------------*/
+ 

commit de8c55208c3865d0532466097b0244fbea1d9089
+Author: Arvind Sankar 
+Date:   Mon May 4 11:02:48 2020 -0400
+
+    efi/libstub: Fix mixed mode boot issue after macro refactor
+    
+    Commit
+    
+      22090f84bc3f ("efi/libstub: unify EFI call wrappers for non-x86")
+    
+    refactored the macros that are used to provide wrappers for mixed-mode
+    calls on x86, allowing us to boot a 64-bit kernel on 32-bit firmware.
+    
+    Unfortunately, this broke mixed mode boot due to the fact that
+    efi_is_native() is not a macro on x86.
+    
+    All of these macros should go together, so rather than testing each one
+    to see if it is defined, condition the generic macro definitions on a
+    new ARCH_HAS_EFISTUB_WRAPPERS, and remove the wrapper definitions on x86
+    as well if CONFIG_EFI_MIXED is not enabled.
+    
+    Fixes: 22090f84bc3f ("efi/libstub: unify EFI call wrappers for non-x86")
+    Reported-by: Guenter Roeck 
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200504150248.62482-1-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
+index cd0c3fbf6156..6b9ab0d8b2a7 100644
+--- a/arch/x86/include/asm/efi.h
++++ b/arch/x86/include/asm/efi.h
+@@ -225,13 +225,15 @@ efi_status_t efi_set_virtual_address_map(unsigned long memory_map_size,
+ 
+ /* arch specific definitions used by the stub code */
+ 
+-extern const bool efi_is64;
++#ifdef CONFIG_EFI_MIXED
++
++#define ARCH_HAS_EFISTUB_WRAPPERS
+ 
+ static inline bool efi_is_64bit(void)
+ {
+-	if (IS_ENABLED(CONFIG_EFI_MIXED))
+-		return efi_is64;
+-	return IS_ENABLED(CONFIG_X86_64);
++	extern const bool efi_is64;
++
++	return efi_is64;
+ }
+ 
+ static inline bool efi_is_native(void)
+@@ -356,6 +358,15 @@ static inline u32 efi64_convert_status(efi_status_t status)
+ 						   runtime),		\
+ 				    func, __VA_ARGS__))
+ 
++#else /* CONFIG_EFI_MIXED */
++
++static inline bool efi_is_64bit(void)
++{
++	return IS_ENABLED(CONFIG_X86_64);
++}
++
++#endif /* CONFIG_EFI_MIXED */
++
+ extern bool efi_reboot_required(void);
+ extern bool efi_is_table_address(unsigned long phys_addr);
+ 
+diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
+index 874233cf8820..4f10a09563f3 100644
+--- a/drivers/firmware/efi/libstub/efistub.h
++++ b/drivers/firmware/efi/libstub/efistub.h
+@@ -33,20 +33,14 @@ extern bool efi_novamap;
+ 
+ extern const efi_system_table_t *efi_system_table;
+ 
+-#ifndef efi_bs_call
++#ifndef ARCH_HAS_EFISTUB_WRAPPERS
++
++#define efi_is_native()		(true)
+ #define efi_bs_call(func, ...)	efi_system_table->boottime->func(__VA_ARGS__)
+-#endif
+-#ifndef efi_rt_call
+ #define efi_rt_call(func, ...)	efi_system_table->runtime->func(__VA_ARGS__)
+-#endif
+-#ifndef efi_is_native
+-#define efi_is_native()		(true)
+-#endif
+-#ifndef efi_table_attr
+ #define efi_table_attr(inst, attr)	(inst->attr)
+-#endif
+-#ifndef efi_call_proto
+ #define efi_call_proto(inst, func, ...) inst->func(inst, ##__VA_ARGS__)
++
+ #endif
+ 
+ #define efi_info(msg)		do {			\

commit 055042bedd4e0af8186266b189b81e73e708b82b
+Author: Arvind Sankar 
+Date:   Thu Apr 30 14:28:43 2020 -0400
+
+    efi/libstub: Check return value of efi_parse_options
+    
+    efi_parse_options can fail if it is unable to allocate space for a copy
+    of the command line. Check the return value to make sure it succeeded.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200430182843.2510180-12-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/efi-stub.c b/drivers/firmware/efi/libstub/efi-stub.c
+index 63541c2440ef..c2484bf75c5d 100644
+--- a/drivers/firmware/efi/libstub/efi-stub.c
++++ b/drivers/firmware/efi/libstub/efi-stub.c
+@@ -207,11 +207,21 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg)
+ 
+ 	if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
+ 	    IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
+-	    cmdline_size == 0)
+-		efi_parse_options(CONFIG_CMDLINE);
++	    cmdline_size == 0) {
++		status = efi_parse_options(CONFIG_CMDLINE);
++		if (status != EFI_SUCCESS) {
++			efi_err("Failed to parse options\n");
++			goto fail_free_cmdline;
++		}
++	}
+ 
+-	if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0)
+-		efi_parse_options(cmdline_ptr);
++	if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0) {
++		status = efi_parse_options(cmdline_ptr);
++		if (status != EFI_SUCCESS) {
++			efi_err("Failed to parse options\n");
++			goto fail_free_cmdline;
++		}
++	}
+ 
+ 	efi_info("Booting Linux Kernel...\n");
+ 
+@@ -223,7 +233,7 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg)
+ 				     dram_base, image);
+ 	if (status != EFI_SUCCESS) {
+ 		efi_err("Failed to relocate kernel\n");
+-		goto fail_free_cmdline;
++		goto fail_free_screeninfo;
+ 	}
+ 
+ 	efi_retrieve_tpm2_eventlog();
+@@ -326,8 +336,9 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg)
+ fail_free_image:
+ 	efi_free(image_size, image_addr);
+ 	efi_free(reserve_size, reserve_addr);
+-fail_free_cmdline:
++fail_free_screeninfo:
+ 	free_screen_info(si);
++fail_free_cmdline:
+ 	efi_free(cmdline_size, (unsigned long)cmdline_ptr);
+ fail:
+ 	return status;
+diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
+index c84c5678e3e1..37154bb93c59 100644
+--- a/drivers/firmware/efi/libstub/x86-stub.c
++++ b/drivers/firmware/efi/libstub/x86-stub.c
+@@ -739,12 +739,20 @@ unsigned long efi_main(efi_handle_t handle,
+ 	}
+ 
+ #ifdef CONFIG_CMDLINE_BOOL
+-	efi_parse_options(CONFIG_CMDLINE);
++	status = efi_parse_options(CONFIG_CMDLINE);
++	if (status != EFI_SUCCESS) {
++		efi_err("Failed to parse options\n");
++		goto fail;
++	}
+ #endif
+ 	if (!IS_ENABLED(CONFIG_CMDLINE_OVERRIDE)) {
+ 		unsigned long cmdline_paddr = ((u64)hdr->cmd_line_ptr |
+ 					       ((u64)boot_params->ext_cmd_line_ptr << 32));
+-		efi_parse_options((char *)cmdline_paddr);
++		status = efi_parse_options((char *)cmdline_paddr);
++		if (status != EFI_SUCCESS) {
++			efi_err("Failed to parse options\n");
++			goto fail;
++		}
+ 	}
+ 
+ 	/*

commit 7dde67f2a23ac11962b17128d9a71698430ced95
+Author: Arvind Sankar 
+Date:   Thu Apr 30 14:28:42 2020 -0400
+
+    efi/x86: Support builtin command line
+    
+    Add support for the x86 CMDLINE_BOOL and CMDLINE_OVERRIDE configuration
+    options.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200430182843.2510180-11-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
+index f1a134596b53..c84c5678e3e1 100644
+--- a/drivers/firmware/efi/libstub/x86-stub.c
++++ b/drivers/firmware/efi/libstub/x86-stub.c
+@@ -680,7 +680,6 @@ unsigned long efi_main(efi_handle_t handle,
+ 	unsigned long buffer_start, buffer_end;
+ 	struct setup_header *hdr = &boot_params->hdr;
+ 	efi_status_t status;
+-	unsigned long cmdline_paddr;
+ 
+ 	efi_system_table = sys_table_arg;
+ 
+@@ -739,9 +738,14 @@ unsigned long efi_main(efi_handle_t handle,
+ 		image_offset = 0;
+ 	}
+ 
+-	cmdline_paddr = ((u64)hdr->cmd_line_ptr |
+-			 ((u64)boot_params->ext_cmd_line_ptr << 32));
+-	efi_parse_options((char *)cmdline_paddr);
++#ifdef CONFIG_CMDLINE_BOOL
++	efi_parse_options(CONFIG_CMDLINE);
++#endif
++	if (!IS_ENABLED(CONFIG_CMDLINE_OVERRIDE)) {
++		unsigned long cmdline_paddr = ((u64)hdr->cmd_line_ptr |
++					       ((u64)boot_params->ext_cmd_line_ptr << 32));
++		efi_parse_options((char *)cmdline_paddr);
++	}
+ 
+ 	/*
+ 	 * At this point, an initrd may already have been loaded by the

commit f61900fd0ebf6c6b91719d63272a54f4d11051df
+Author: Arvind Sankar 
+Date:   Thu Apr 30 14:28:41 2020 -0400
+
+    efi/libstub: Unify initrd loading across architectures
+    
+    Factor out the initrd loading into a common function that can be called
+    both from the generic efi-stub.c and the x86-specific x86-stub.c.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200430182843.2510180-10-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
+index 1c92ac231f94..7aac89e928ec 100644
+--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
++++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
+@@ -331,6 +331,7 @@ static const struct {
+  *		%EFI_OUT_OF_RESOURCES if memory allocation failed
+  *		%EFI_LOAD_ERROR in all other cases
+  */
++static
+ efi_status_t efi_load_initrd_dev_path(unsigned long *load_addr,
+ 				      unsigned long *load_size,
+ 				      unsigned long max)
+@@ -343,9 +344,6 @@ efi_status_t efi_load_initrd_dev_path(unsigned long *load_addr,
+ 	efi_handle_t handle;
+ 	efi_status_t status;
+ 
+-	if (!load_addr || !load_size)
+-		return EFI_INVALID_PARAMETER;
+-
+ 	dp = (efi_device_path_protocol_t *)&initrd_dev_path;
+ 	status = efi_bs_call(locate_device_path, &lf2_proto_guid, &dp, &handle);
+ 	if (status != EFI_SUCCESS)
+@@ -375,3 +373,45 @@ efi_status_t efi_load_initrd_dev_path(unsigned long *load_addr,
+ 	*load_size = initrd_size;
+ 	return EFI_SUCCESS;
+ }
++
++static
++efi_status_t efi_load_initrd_cmdline(efi_loaded_image_t *image,
++				     unsigned long *load_addr,
++				     unsigned long *load_size,
++				     unsigned long soft_limit,
++				     unsigned long hard_limit)
++{
++	if (!IS_ENABLED(CONFIG_EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER) ||
++	    (IS_ENABLED(CONFIG_X86) && (!efi_is_native() || image == NULL))) {
++		*load_addr = *load_size = 0;
++		return EFI_SUCCESS;
++	}
++
++	return handle_cmdline_files(image, L"initrd=", sizeof(L"initrd=") - 2,
++				    soft_limit, hard_limit,
++				    load_addr, load_size);
++}
++
++efi_status_t efi_load_initrd(efi_loaded_image_t *image,
++			     unsigned long *load_addr,
++			     unsigned long *load_size,
++			     unsigned long soft_limit,
++			     unsigned long hard_limit)
++{
++	efi_status_t status;
++
++	if (!load_addr || !load_size)
++		return EFI_INVALID_PARAMETER;
++
++	status = efi_load_initrd_dev_path(load_addr, load_size, hard_limit);
++	if (status == EFI_SUCCESS) {
++		efi_info("Loaded initrd from LINUX_EFI_INITRD_MEDIA_GUID device path\n");
++	} else if (status == EFI_NOT_FOUND) {
++		status = efi_load_initrd_cmdline(image, load_addr, load_size,
++						 soft_limit, hard_limit);
++		if (status == EFI_SUCCESS && *load_size > 0)
++			efi_info("Loaded initrd from command line option\n");
++	}
++
++	return status;
++}
+diff --git a/drivers/firmware/efi/libstub/efi-stub.c b/drivers/firmware/efi/libstub/efi-stub.c
+index cb02e8bb6b44..63541c2440ef 100644
+--- a/drivers/firmware/efi/libstub/efi-stub.c
++++ b/drivers/firmware/efi/libstub/efi-stub.c
+@@ -265,16 +265,8 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg)
+ 
+ 	if (!efi_noinitrd) {
+ 		max_addr = efi_get_max_initrd_addr(dram_base, image_addr);
+-		status = efi_load_initrd_dev_path(&initrd_addr, &initrd_size,
+-						  max_addr);
+-		if (status == EFI_SUCCESS) {
+-			efi_info("Loaded initrd from LINUX_EFI_INITRD_MEDIA_GUID device path\n");
+-		} else if (status == EFI_NOT_FOUND) {
+-			status = efi_load_initrd(image, &initrd_addr, &initrd_size,
+-						 ULONG_MAX, max_addr);
+-			if (status == EFI_SUCCESS && initrd_size > 0)
+-				efi_info("Loaded initrd from command line option\n");
+-		}
++		status = efi_load_initrd(image, &initrd_addr, &initrd_size,
++					 ULONG_MAX, max_addr);
+ 		if (status != EFI_SUCCESS)
+ 			efi_err("Failed to load initrd!\n");
+ 	}
+diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
+index 8c905a1be1b4..874233cf8820 100644
+--- a/drivers/firmware/efi/libstub/efistub.h
++++ b/drivers/firmware/efi/libstub/efistub.h
+@@ -677,21 +677,10 @@ static inline efi_status_t efi_load_dtb(efi_loaded_image_t *image,
+ 				    ULONG_MAX, ULONG_MAX, load_addr, load_size);
+ }
+ 
+-static inline efi_status_t efi_load_initrd(efi_loaded_image_t *image,
+-					   unsigned long *load_addr,
+-					   unsigned long *load_size,
+-					   unsigned long soft_limit,
+-					   unsigned long hard_limit)
+-{
+-	if (!IS_ENABLED(CONFIG_EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER))
+-		return EFI_SUCCESS;
+-
+-	return handle_cmdline_files(image, L"initrd=", sizeof(L"initrd=") - 2,
+-				    soft_limit, hard_limit, load_addr, load_size);
+-}
+-
+-efi_status_t efi_load_initrd_dev_path(unsigned long *load_addr,
+-				      unsigned long *load_size,
+-				      unsigned long max);
++efi_status_t efi_load_initrd(efi_loaded_image_t *image,
++			     unsigned long *load_addr,
++			     unsigned long *load_size,
++			     unsigned long soft_limit,
++			     unsigned long hard_limit);
+ 
+ #endif
+diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
+index defeb6035109..f1a134596b53 100644
+--- a/drivers/firmware/efi/libstub/x86-stub.c
++++ b/drivers/firmware/efi/libstub/x86-stub.c
+@@ -755,17 +755,8 @@ unsigned long efi_main(efi_handle_t handle,
+ 	if (!efi_noinitrd) {
+ 		unsigned long addr, size;
+ 
+-		status = efi_load_initrd_dev_path(&addr, &size, ULONG_MAX);
+-		if (status == EFI_NOT_FOUND) {
+-			if (efi_is_native() && image != NULL) {
+-				status = efi_load_initrd(image, &addr, &size,
+-							 hdr->initrd_addr_max,
+-							 ULONG_MAX);
+-			} else {
+-				addr = size = 0;
+-				status = EFI_SUCCESS;
+-			}
+-		}
++		status = efi_load_initrd(image, &addr, &size,
++					 hdr->initrd_addr_max, ULONG_MAX);
+ 
+ 		if (status != EFI_SUCCESS) {
+ 			efi_err("Failed to load initrd!\n");

commit 987053a30016a7d9ab3e4ad973e7c51aeb1f1ef6
+Author: Arvind Sankar 
+Date:   Thu Apr 30 14:28:40 2020 -0400
+
+    efi/x86: Move command-line initrd loading to efi_main
+    
+    Consolidate the initrd loading in efi_main.
+    
+    The command line options now need to be parsed only once.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200430182843.2510180-9-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
+index 3800eb22232e..defeb6035109 100644
+--- a/drivers/firmware/efi/libstub/x86-stub.c
++++ b/drivers/firmware/efi/libstub/x86-stub.c
+@@ -22,6 +22,7 @@
+ 
+ const efi_system_table_t *efi_system_table;
+ extern u32 image_offset;
++static efi_loaded_image_t *image = NULL;
+ 
+ static efi_status_t
+ preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
+@@ -355,7 +356,6 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
+ {
+ 	struct boot_params *boot_params;
+ 	struct setup_header *hdr;
+-	efi_loaded_image_t *image;
+ 	void *image_base;
+ 	efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID;
+ 	int options_size = 0;
+@@ -414,30 +414,9 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
+ 	hdr->ramdisk_image = 0;
+ 	hdr->ramdisk_size = 0;
+ 
+-	if (efi_is_native()) {
+-		status = efi_parse_options(cmdline_ptr);
+-		if (status != EFI_SUCCESS)
+-			goto fail2;
+-
+-		if (!efi_noinitrd) {
+-			status = efi_load_initrd(image, &ramdisk_addr,
+-						 &ramdisk_size,
+-						 hdr->initrd_addr_max,
+-						 ULONG_MAX);
+-			if (status != EFI_SUCCESS)
+-				goto fail2;
+-			efi_set_u64_split(ramdisk_addr, &hdr->ramdisk_image,
+-					  &boot_params->ext_ramdisk_image);
+-			efi_set_u64_split(ramdisk_size, &hdr->ramdisk_size,
+-					  &boot_params->ext_ramdisk_size);
+-		}
+-	}
+-
+ 	efi_stub_entry(handle, sys_table_arg, boot_params);
+ 	/* not reached */
+ 
+-fail2:
+-	efi_free(options_size, (unsigned long)cmdline_ptr);
+ fail:
+ 	efi_free(sizeof(struct boot_params), (unsigned long)boot_params);
+ 
+@@ -760,35 +739,42 @@ unsigned long efi_main(efi_handle_t handle,
+ 		image_offset = 0;
+ 	}
+ 
+-	/*
+-	 * efi_pe_entry() may have been called before efi_main(), in which
+-	 * case this is the second time we parse the cmdline. This is ok,
+-	 * parsing the cmdline multiple times does not have side-effects.
+-	 */
+ 	cmdline_paddr = ((u64)hdr->cmd_line_ptr |
+ 			 ((u64)boot_params->ext_cmd_line_ptr << 32));
+ 	efi_parse_options((char *)cmdline_paddr);
+ 
+ 	/*
+-	 * At this point, an initrd may already have been loaded, either by
+-	 * the bootloader and passed via bootparams, or loaded from a initrd=
+-	 * command line option by efi_pe_entry() above. In either case, we
+-	 * permit an initrd loaded from the LINUX_EFI_INITRD_MEDIA_GUID device
+-	 * path to supersede it.
++	 * At this point, an initrd may already have been loaded by the
++	 * bootloader and passed via bootparams. We permit an initrd loaded
++	 * from the LINUX_EFI_INITRD_MEDIA_GUID device path to supersede it.
++	 *
++	 * If the device path is not present, any command-line initrd=
++	 * arguments will be processed only if image is not NULL, which will be
++	 * the case only if we were loaded via the PE entry point.
+ 	 */
+ 	if (!efi_noinitrd) {
+ 		unsigned long addr, size;
+ 
+ 		status = efi_load_initrd_dev_path(&addr, &size, ULONG_MAX);
+-		if (status == EFI_SUCCESS) {
+-			efi_set_u64_split(addr, &hdr->ramdisk_image,
+-					  &boot_params->ext_ramdisk_image);
+-			efi_set_u64_split(size, &hdr->ramdisk_size,
+-					  &boot_params->ext_ramdisk_size);
+-		} else if (status != EFI_NOT_FOUND) {
+-			efi_err("efi_load_initrd_dev_path() failed!\n");
++		if (status == EFI_NOT_FOUND) {
++			if (efi_is_native() && image != NULL) {
++				status = efi_load_initrd(image, &addr, &size,
++							 hdr->initrd_addr_max,
++							 ULONG_MAX);
++			} else {
++				addr = size = 0;
++				status = EFI_SUCCESS;
++			}
++		}
++
++		if (status != EFI_SUCCESS) {
++			efi_err("Failed to load initrd!\n");
+ 			goto fail;
+ 		}
++		efi_set_u64_split(addr, &hdr->ramdisk_image,
++				  &boot_params->ext_ramdisk_image);
++		efi_set_u64_split(size, &hdr->ramdisk_size,
++				  &boot_params->ext_ramdisk_size);
+ 	}
+ 
+ 	/*

commit 3839ab85d0fabd8b51c7548c4c1bc35bdba8adca
+Author: Arvind Sankar 
+Date:   Thu Apr 30 14:28:39 2020 -0400
+
+    efi/libstub: Upgrade ignored dtb= argument message to error
+    
+    Use efi_err if we ignore a command-line dtb= argument, so that it shows
+    up even on a quiet boot.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200430182843.2510180-8-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/efi-stub.c b/drivers/firmware/efi/libstub/efi-stub.c
+index 72ffd2670f99..cb02e8bb6b44 100644
+--- a/drivers/firmware/efi/libstub/efi-stub.c
++++ b/drivers/firmware/efi/libstub/efi-stub.c
+@@ -241,7 +241,7 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg)
+ 	if (!IS_ENABLED(CONFIG_EFI_ARMSTUB_DTB_LOADER) ||
+ 	     secure_boot != efi_secureboot_mode_disabled) {
+ 		if (strstr(cmdline_ptr, "dtb="))
+-			efi_info("Ignoring DTB from command line.\n");
++			efi_err("Ignoring DTB from command line.\n");
+ 	} else {
+ 		status = efi_load_dtb(image, &fdt_addr, &fdt_size);
+ 

commit dad5b324212ef261e9b399b7456a4c3df0a8c300
+Author: Arvind Sankar 
+Date:   Thu Apr 30 14:28:38 2020 -0400
+
+    efi/tpm: Use efi_err for error messages
+    
+    Use efi_err instead of bare efi_printk for error messages.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200430182843.2510180-7-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/tpm.c b/drivers/firmware/efi/libstub/tpm.c
+index 1d59e103a2e3..09adcf51b75b 100644
+--- a/drivers/firmware/efi/libstub/tpm.c
++++ b/drivers/firmware/efi/libstub/tpm.c
+@@ -119,7 +119,7 @@ void efi_retrieve_tpm2_eventlog(void)
+ 			     sizeof(*log_tbl) + log_size, (void **)&log_tbl);
+ 
+ 	if (status != EFI_SUCCESS) {
+-		efi_printk("Unable to allocate memory for event log\n");
++		efi_err("Unable to allocate memory for event log\n");
+ 		return;
+ 	}
+ 

commit 61eac6d92d351fc446c7a0ba3b55a9b8d9977e30
+Author: Arvind Sankar 
+Date:   Thu Apr 30 14:28:37 2020 -0400
+
+    efi/gop: Use efi_err for error messages
+    
+    Use efi_err instead of bare efi_printk for error messages.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200430182843.2510180-6-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
+index 64cee0febae0..34c0cba2c8bf 100644
+--- a/drivers/firmware/efi/libstub/gop.c
++++ b/drivers/firmware/efi/libstub/gop.c
+@@ -134,14 +134,14 @@ static u32 choose_mode_modenum(efi_graphics_output_protocol_t *gop)
+ 
+ 	max_mode = efi_table_attr(mode, max_mode);
+ 	if (cmdline.mode >= max_mode) {
+-		efi_printk("Requested mode is invalid\n");
++		efi_err("Requested mode is invalid\n");
+ 		return cur_mode;
+ 	}
+ 
+ 	status = efi_call_proto(gop, query_mode, cmdline.mode,
+ 				&info_size, &info);
+ 	if (status != EFI_SUCCESS) {
+-		efi_printk("Couldn't get mode information\n");
++		efi_err("Couldn't get mode information\n");
+ 		return cur_mode;
+ 	}
+ 
+@@ -150,7 +150,7 @@ static u32 choose_mode_modenum(efi_graphics_output_protocol_t *gop)
+ 	efi_bs_call(free_pool, info);
+ 
+ 	if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX) {
+-		efi_printk("Invalid PixelFormat\n");
++		efi_err("Invalid PixelFormat\n");
+ 		return cur_mode;
+ 	}
+ 
+@@ -222,7 +222,7 @@ static u32 choose_mode_res(efi_graphics_output_protocol_t *gop)
+ 			return m;
+ 	}
+ 
+-	efi_printk("Couldn't find requested mode\n");
++	efi_err("Couldn't find requested mode\n");
+ 
+ 	return cur_mode;
+ }
+@@ -316,7 +316,7 @@ static void set_mode(efi_graphics_output_protocol_t *gop)
+ 		return;
+ 
+ 	if (efi_call_proto(gop, set_mode, new_mode) != EFI_SUCCESS)
+-		efi_printk("Failed to set requested mode\n");
++		efi_err("Failed to set requested mode\n");
+ }
+ 
+ static void find_bits(u32 mask, u8 *pos, u8 *size)

commit 36bdd0a78d56831f5d8df740012b6cdc71c0c73d
+Author: Arvind Sankar 
+Date:   Thu Apr 30 14:28:36 2020 -0400
+
+    efi/x86: Use efi_err for error messages
+    
+    Use efi_err instead of bare efi_printk for error messages.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200430182843.2510180-5-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
+index f91d4aab0156..3800eb22232e 100644
+--- a/drivers/firmware/efi/libstub/x86-stub.c
++++ b/drivers/firmware/efi/libstub/x86-stub.c
+@@ -49,7 +49,7 @@ preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
+ 	status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size,
+ 			     (void **)&rom);
+ 	if (status != EFI_SUCCESS) {
+-		efi_printk("Failed to allocate memory for 'rom'\n");
++		efi_err("Failed to allocate memory for 'rom'\n");
+ 		return status;
+ 	}
+ 
+@@ -65,7 +65,7 @@ preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
+ 				PCI_VENDOR_ID, 1, &rom->vendor);
+ 
+ 	if (status != EFI_SUCCESS) {
+-		efi_printk("Failed to read rom->vendor\n");
++		efi_err("Failed to read rom->vendor\n");
+ 		goto free_struct;
+ 	}
+ 
+@@ -73,7 +73,7 @@ preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
+ 				PCI_DEVICE_ID, 1, &rom->devid);
+ 
+ 	if (status != EFI_SUCCESS) {
+-		efi_printk("Failed to read rom->devid\n");
++		efi_err("Failed to read rom->devid\n");
+ 		goto free_struct;
+ 	}
+ 
+@@ -118,7 +118,7 @@ static void setup_efi_pci(struct boot_params *params)
+ 				     (void **)&pci_handle);
+ 
+ 		if (status != EFI_SUCCESS) {
+-			efi_printk("Failed to allocate memory for 'pci_handle'\n");
++			efi_err("Failed to allocate memory for 'pci_handle'\n");
+ 			return;
+ 		}
+ 
+@@ -172,7 +172,7 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params)
+ 		return;
+ 
+ 	if (efi_table_attr(p, version) != 0x10000) {
+-		efi_printk("Unsupported properties proto version\n");
++		efi_err("Unsupported properties proto version\n");
+ 		return;
+ 	}
+ 
+@@ -185,7 +185,7 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params)
+ 				     size + sizeof(struct setup_data),
+ 				     (void **)&new);
+ 		if (status != EFI_SUCCESS) {
+-			efi_printk("Failed to allocate memory for 'properties'\n");
++			efi_err("Failed to allocate memory for 'properties'\n");
+ 			return;
+ 		}
+ 
+@@ -372,7 +372,7 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
+ 
+ 	status = efi_bs_call(handle_protocol, handle, &proto, (void **)&image);
+ 	if (status != EFI_SUCCESS) {
+-		efi_printk("Failed to get handle for LOADED_IMAGE_PROTOCOL\n");
++		efi_err("Failed to get handle for LOADED_IMAGE_PROTOCOL\n");
+ 		efi_exit(handle, status);
+ 	}
+ 
+@@ -382,7 +382,7 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
+ 	status = efi_allocate_pages(sizeof(struct boot_params),
+ 				    (unsigned long *)&boot_params, ULONG_MAX);
+ 	if (status != EFI_SUCCESS) {
+-		efi_printk("Failed to allocate lowmem for boot params\n");
++		efi_err("Failed to allocate lowmem for boot params\n");
+ 		efi_exit(handle, status);
+ 	}
+ 
+@@ -749,7 +749,7 @@ unsigned long efi_main(efi_handle_t handle,
+ 					     hdr->kernel_alignment,
+ 					     LOAD_PHYSICAL_ADDR);
+ 		if (status != EFI_SUCCESS) {
+-			efi_printk("efi_relocate_kernel() failed!\n");
++			efi_err("efi_relocate_kernel() failed!\n");
+ 			goto fail;
+ 		}
+ 		/*
+@@ -786,7 +786,7 @@ unsigned long efi_main(efi_handle_t handle,
+ 			efi_set_u64_split(size, &hdr->ramdisk_size,
+ 					  &boot_params->ext_ramdisk_size);
+ 		} else if (status != EFI_NOT_FOUND) {
+-			efi_printk("efi_load_initrd_dev_path() failed!\n");
++			efi_err("efi_load_initrd_dev_path() failed!\n");
+ 			goto fail;
+ 		}
+ 	}
+@@ -813,13 +813,13 @@ unsigned long efi_main(efi_handle_t handle,
+ 
+ 	status = exit_boot(boot_params, handle);
+ 	if (status != EFI_SUCCESS) {
+-		efi_printk("exit_boot() failed!\n");
++		efi_err("exit_boot() failed!\n");
+ 		goto fail;
+ 	}
+ 
+ 	return bzimage_addr;
+ fail:
+-	efi_printk("efi_main() failed!\n");
++	efi_err("efi_main() failed!\n");
+ 
+ 	efi_exit(handle, status);
+ }

commit 793473c28a4b17ade3c2bb69782fb0b55acb6e0b
+Author: Arvind Sankar 
+Date:   Thu Apr 30 14:28:35 2020 -0400
+
+    efi/libstub: Move pr_efi/pr_efi_err into efi namespace
+    
+    Rename pr_efi to efi_info and pr_efi_err to efi_err to make it more
+    obvious that they are part of the EFI stub and not generic printk infra.
+    
+    Suggested-by: Joe Perches 
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200430182843.2510180-4-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/arm32-stub.c b/drivers/firmware/efi/libstub/arm32-stub.c
+index 7826553af2ba..b038afe2ee7a 100644
+--- a/drivers/firmware/efi/libstub/arm32-stub.c
++++ b/drivers/firmware/efi/libstub/arm32-stub.c
+@@ -18,7 +18,7 @@ efi_status_t check_platform_features(void)
+ 	/* LPAE kernels need compatible hardware */
+ 	block = cpuid_feature_extract(CPUID_EXT_MMFR0, 0);
+ 	if (block < 5) {
+-		pr_efi_err("This LPAE kernel is not supported by your CPU\n");
++		efi_err("This LPAE kernel is not supported by your CPU\n");
+ 		return EFI_UNSUPPORTED;
+ 	}
+ 	return EFI_SUCCESS;
+@@ -120,7 +120,7 @@ static efi_status_t reserve_kernel_base(unsigned long dram_base,
+ 	 */
+ 	status = efi_get_memory_map(&map);
+ 	if (status != EFI_SUCCESS) {
+-		pr_efi_err("reserve_kernel_base(): Unable to retrieve memory map.\n");
++		efi_err("reserve_kernel_base(): Unable to retrieve memory map.\n");
+ 		return status;
+ 	}
+ 
+@@ -162,7 +162,7 @@ static efi_status_t reserve_kernel_base(unsigned long dram_base,
+ 					     (end - start) / EFI_PAGE_SIZE,
+ 					     &start);
+ 			if (status != EFI_SUCCESS) {
+-				pr_efi_err("reserve_kernel_base(): alloc failed.\n");
++				efi_err("reserve_kernel_base(): alloc failed.\n");
+ 				goto out;
+ 			}
+ 			break;
+@@ -219,7 +219,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
+ 
+ 	status = reserve_kernel_base(kernel_base, reserve_addr, reserve_size);
+ 	if (status != EFI_SUCCESS) {
+-		pr_efi_err("Unable to allocate memory for uncompressed kernel.\n");
++		efi_err("Unable to allocate memory for uncompressed kernel.\n");
+ 		return status;
+ 	}
+ 
+@@ -232,7 +232,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
+ 	status = efi_relocate_kernel(image_addr, *image_size, *image_size,
+ 				     kernel_base + MAX_UNCOMP_KERNEL_SIZE, 0, 0);
+ 	if (status != EFI_SUCCESS) {
+-		pr_efi_err("Failed to relocate kernel.\n");
++		efi_err("Failed to relocate kernel.\n");
+ 		efi_free(*reserve_size, *reserve_addr);
+ 		*reserve_size = 0;
+ 		return status;
+@@ -244,7 +244,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
+ 	 * address at which the zImage is loaded.
+ 	 */
+ 	if (*image_addr + *image_size > dram_base + ZIMAGE_OFFSET_LIMIT) {
+-		pr_efi_err("Failed to relocate kernel, no low memory available.\n");
++		efi_err("Failed to relocate kernel, no low memory available.\n");
+ 		efi_free(*reserve_size, *reserve_addr);
+ 		*reserve_size = 0;
+ 		efi_free(*image_size, *image_addr);
+diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c
+index ba4db35015a3..7f6a57dec513 100644
+--- a/drivers/firmware/efi/libstub/arm64-stub.c
++++ b/drivers/firmware/efi/libstub/arm64-stub.c
+@@ -26,9 +26,9 @@ efi_status_t check_platform_features(void)
+ 	tg = (read_cpuid(ID_AA64MMFR0_EL1) >> ID_AA64MMFR0_TGRAN_SHIFT) & 0xf;
+ 	if (tg != ID_AA64MMFR0_TGRAN_SUPPORTED) {
+ 		if (IS_ENABLED(CONFIG_ARM64_64K_PAGES))
+-			pr_efi_err("This 64 KB granular kernel is not supported by your CPU\n");
++			efi_err("This 64 KB granular kernel is not supported by your CPU\n");
+ 		else
+-			pr_efi_err("This 16 KB granular kernel is not supported by your CPU\n");
++			efi_err("This 16 KB granular kernel is not supported by your CPU\n");
+ 		return EFI_UNSUPPORTED;
+ 	}
+ 	return EFI_SUCCESS;
+@@ -59,18 +59,18 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
+ 			status = efi_get_random_bytes(sizeof(phys_seed),
+ 						      (u8 *)&phys_seed);
+ 			if (status == EFI_NOT_FOUND) {
+-				pr_efi("EFI_RNG_PROTOCOL unavailable, no randomness supplied\n");
++				efi_info("EFI_RNG_PROTOCOL unavailable, no randomness supplied\n");
+ 			} else if (status != EFI_SUCCESS) {
+-				pr_efi_err("efi_get_random_bytes() failed\n");
++				efi_err("efi_get_random_bytes() failed\n");
+ 				return status;
+ 			}
+ 		} else {
+-			pr_efi("KASLR disabled on kernel command line\n");
++			efi_info("KASLR disabled on kernel command line\n");
+ 		}
+ 	}
+ 
+ 	if (image->image_base != _text)
+-		pr_efi_err("FIRMWARE BUG: efi_loaded_image_t::image_base has bogus value\n");
++		efi_err("FIRMWARE BUG: efi_loaded_image_t::image_base has bogus value\n");
+ 
+ 	kernel_size = _edata - _text;
+ 	kernel_memsize = kernel_size + (_end - _edata);
+@@ -102,7 +102,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
+ 						    ULONG_MAX, min_kimg_align);
+ 
+ 		if (status != EFI_SUCCESS) {
+-			pr_efi_err("Failed to relocate kernel\n");
++			efi_err("Failed to relocate kernel\n");
+ 			*reserve_size = 0;
+ 			return status;
+ 		}
+diff --git a/drivers/firmware/efi/libstub/efi-stub.c b/drivers/firmware/efi/libstub/efi-stub.c
+index ee225b323687..72ffd2670f99 100644
+--- a/drivers/firmware/efi/libstub/efi-stub.c
++++ b/drivers/firmware/efi/libstub/efi-stub.c
+@@ -69,7 +69,7 @@ static void install_memreserve_table(void)
+ 	status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, sizeof(*rsv),
+ 			     (void **)&rsv);
+ 	if (status != EFI_SUCCESS) {
+-		pr_efi_err("Failed to allocate memreserve entry!\n");
++		efi_err("Failed to allocate memreserve entry!\n");
+ 		return;
+ 	}
+ 
+@@ -80,7 +80,7 @@ static void install_memreserve_table(void)
+ 	status = efi_bs_call(install_configuration_table,
+ 			     &memreserve_table_guid, rsv);
+ 	if (status != EFI_SUCCESS)
+-		pr_efi_err("Failed to install memreserve config table!\n");
++		efi_err("Failed to install memreserve config table!\n");
+ }
+ 
+ static unsigned long get_dram_base(void)
+@@ -182,13 +182,13 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg)
+ 	status = efi_system_table->boottime->handle_protocol(handle,
+ 					&loaded_image_proto, (void *)&image);
+ 	if (status != EFI_SUCCESS) {
+-		pr_efi_err("Failed to get loaded image protocol\n");
++		efi_err("Failed to get loaded image protocol\n");
+ 		goto fail;
+ 	}
+ 
+ 	dram_base = get_dram_base();
+ 	if (dram_base == EFI_ERROR) {
+-		pr_efi_err("Failed to find DRAM base\n");
++		efi_err("Failed to find DRAM base\n");
+ 		status = EFI_LOAD_ERROR;
+ 		goto fail;
+ 	}
+@@ -200,7 +200,7 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg)
+ 	 */
+ 	cmdline_ptr = efi_convert_cmdline(image, &cmdline_size, ULONG_MAX);
+ 	if (!cmdline_ptr) {
+-		pr_efi_err("getting command line via LOADED_IMAGE_PROTOCOL\n");
++		efi_err("getting command line via LOADED_IMAGE_PROTOCOL\n");
+ 		status = EFI_OUT_OF_RESOURCES;
+ 		goto fail;
+ 	}
+@@ -213,7 +213,7 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg)
+ 	if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0)
+ 		efi_parse_options(cmdline_ptr);
+ 
+-	pr_efi("Booting Linux Kernel...\n");
++	efi_info("Booting Linux Kernel...\n");
+ 
+ 	si = setup_graphics();
+ 
+@@ -222,7 +222,7 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg)
+ 				     &reserve_size,
+ 				     dram_base, image);
+ 	if (status != EFI_SUCCESS) {
+-		pr_efi_err("Failed to relocate kernel\n");
++		efi_err("Failed to relocate kernel\n");
+ 		goto fail_free_cmdline;
+ 	}
+ 
+@@ -241,42 +241,42 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg)
+ 	if (!IS_ENABLED(CONFIG_EFI_ARMSTUB_DTB_LOADER) ||
+ 	     secure_boot != efi_secureboot_mode_disabled) {
+ 		if (strstr(cmdline_ptr, "dtb="))
+-			pr_efi("Ignoring DTB from command line.\n");
++			efi_info("Ignoring DTB from command line.\n");
+ 	} else {
+ 		status = efi_load_dtb(image, &fdt_addr, &fdt_size);
+ 
+ 		if (status != EFI_SUCCESS) {
+-			pr_efi_err("Failed to load device tree!\n");
++			efi_err("Failed to load device tree!\n");
+ 			goto fail_free_image;
+ 		}
+ 	}
+ 
+ 	if (fdt_addr) {
+-		pr_efi("Using DTB from command line\n");
++		efi_info("Using DTB from command line\n");
+ 	} else {
+ 		/* Look for a device tree configuration table entry. */
+ 		fdt_addr = (uintptr_t)get_fdt(&fdt_size);
+ 		if (fdt_addr)
+-			pr_efi("Using DTB from configuration table\n");
++			efi_info("Using DTB from configuration table\n");
+ 	}
+ 
+ 	if (!fdt_addr)
+-		pr_efi("Generating empty DTB\n");
++		efi_info("Generating empty DTB\n");
+ 
+ 	if (!efi_noinitrd) {
+ 		max_addr = efi_get_max_initrd_addr(dram_base, image_addr);
+ 		status = efi_load_initrd_dev_path(&initrd_addr, &initrd_size,
+ 						  max_addr);
+ 		if (status == EFI_SUCCESS) {
+-			pr_efi("Loaded initrd from LINUX_EFI_INITRD_MEDIA_GUID device path\n");
++			efi_info("Loaded initrd from LINUX_EFI_INITRD_MEDIA_GUID device path\n");
+ 		} else if (status == EFI_NOT_FOUND) {
+ 			status = efi_load_initrd(image, &initrd_addr, &initrd_size,
+ 						 ULONG_MAX, max_addr);
+ 			if (status == EFI_SUCCESS && initrd_size > 0)
+-				pr_efi("Loaded initrd from command line option\n");
++				efi_info("Loaded initrd from command line option\n");
+ 		}
+ 		if (status != EFI_SUCCESS)
+-			pr_efi_err("Failed to load initrd!\n");
++			efi_err("Failed to load initrd!\n");
+ 	}
+ 
+ 	efi_random_get_seed();
+@@ -326,7 +326,7 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg)
+ 	/* not reached */
+ 
+ fail_free_initrd:
+-	pr_efi_err("Failed to update FDT and exit boot services\n");
++	efi_err("Failed to update FDT and exit boot services\n");
+ 
+ 	efi_free(initrd_size, initrd_addr);
+ 	efi_free(fdt_size, fdt_addr);
+diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
+index e8aa70ba08d5..8c905a1be1b4 100644
+--- a/drivers/firmware/efi/libstub/efistub.h
++++ b/drivers/firmware/efi/libstub/efistub.h
+@@ -49,11 +49,11 @@ extern const efi_system_table_t *efi_system_table;
+ #define efi_call_proto(inst, func, ...) inst->func(inst, ##__VA_ARGS__)
+ #endif
+ 
+-#define pr_efi(msg)		do {			\
++#define efi_info(msg)		do {			\
+ 	if (!efi_quiet) efi_printk("EFI stub: "msg);	\
+ } while (0)
+ 
+-#define pr_efi_err(msg) efi_printk("EFI stub: ERROR: "msg)
++#define efi_err(msg) efi_printk("EFI stub: ERROR: "msg)
+ 
+ /* Helper macros for the usual case of using simple C variables: */
+ #ifndef fdt_setprop_inplace_var
+diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c
+index 3074a5e27c65..11ecf3c4640e 100644
+--- a/drivers/firmware/efi/libstub/fdt.c
++++ b/drivers/firmware/efi/libstub/fdt.c
+@@ -39,7 +39,7 @@ static efi_status_t update_fdt(void *orig_fdt, unsigned long orig_fdt_size,
+ 	/* Do some checks on provided FDT, if it exists: */
+ 	if (orig_fdt) {
+ 		if (fdt_check_header(orig_fdt)) {
+-			pr_efi_err("Device Tree header not valid!\n");
++			efi_err("Device Tree header not valid!\n");
+ 			return EFI_LOAD_ERROR;
+ 		}
+ 		/*
+@@ -47,7 +47,7 @@ static efi_status_t update_fdt(void *orig_fdt, unsigned long orig_fdt_size,
+ 		 * configuration table:
+ 		 */
+ 		if (orig_fdt_size && fdt_totalsize(orig_fdt) > orig_fdt_size) {
+-			pr_efi_err("Truncated device tree! foo!\n");
++			efi_err("Truncated device tree! foo!\n");
+ 			return EFI_LOAD_ERROR;
+ 		}
+ 	}
+@@ -270,16 +270,16 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
+ 	 */
+ 	status = efi_get_memory_map(&map);
+ 	if (status != EFI_SUCCESS) {
+-		pr_efi_err("Unable to retrieve UEFI memory map.\n");
++		efi_err("Unable to retrieve UEFI memory map.\n");
+ 		return status;
+ 	}
+ 
+-	pr_efi("Exiting boot services and installing virtual address map...\n");
++	efi_info("Exiting boot services and installing virtual address map...\n");
+ 
+ 	map.map = &memory_map;
+ 	status = efi_allocate_pages(MAX_FDT_SIZE, new_fdt_addr, max_addr);
+ 	if (status != EFI_SUCCESS) {
+-		pr_efi_err("Unable to allocate memory for new device tree.\n");
++		efi_err("Unable to allocate memory for new device tree.\n");
+ 		goto fail;
+ 	}
+ 
+@@ -296,7 +296,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
+ 			    initrd_addr, initrd_size);
+ 
+ 	if (status != EFI_SUCCESS) {
+-		pr_efi_err("Unable to construct new device tree.\n");
++		efi_err("Unable to construct new device tree.\n");
+ 		goto fail_free_new_fdt;
+ 	}
+ 
+@@ -342,7 +342,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
+ 		return EFI_SUCCESS;
+ 	}
+ 
+-	pr_efi_err("Exit boot services failed.\n");
++	efi_err("Exit boot services failed.\n");
+ 
+ fail_free_new_fdt:
+ 	efi_free(MAX_FDT_SIZE, *new_fdt_addr);
+@@ -363,7 +363,7 @@ void *get_fdt(unsigned long *fdt_size)
+ 		return NULL;
+ 
+ 	if (fdt_check_header(fdt) != 0) {
+-		pr_efi_err("Invalid header detected on UEFI supplied FDT, ignoring ...\n");
++		efi_err("Invalid header detected on UEFI supplied FDT, ignoring ...\n");
+ 		return NULL;
+ 	}
+ 	*fdt_size = fdt_totalsize(fdt);
+diff --git a/drivers/firmware/efi/libstub/file.c b/drivers/firmware/efi/libstub/file.c
+index 50aaf15f9ad5..cc177152d0df 100644
+--- a/drivers/firmware/efi/libstub/file.c
++++ b/drivers/firmware/efi/libstub/file.c
+@@ -46,7 +46,7 @@ static efi_status_t efi_open_file(efi_file_protocol_t *volume,
+ 
+ 	status = volume->open(volume, &fh, fi->filename, EFI_FILE_MODE_READ, 0);
+ 	if (status != EFI_SUCCESS) {
+-		pr_efi_err("Failed to open file: ");
++		efi_err("Failed to open file: ");
+ 		efi_char16_printk(fi->filename);
+ 		efi_printk("\n");
+ 		return status;
+@@ -55,7 +55,7 @@ static efi_status_t efi_open_file(efi_file_protocol_t *volume,
+ 	info_sz = sizeof(struct finfo);
+ 	status = fh->get_info(fh, &info_guid, &info_sz, fi);
+ 	if (status != EFI_SUCCESS) {
+-		pr_efi_err("Failed to get file info\n");
++		efi_err("Failed to get file info\n");
+ 		fh->close(fh);
+ 		return status;
+ 	}
+@@ -75,13 +75,13 @@ static efi_status_t efi_open_volume(efi_loaded_image_t *image,
+ 	status = efi_bs_call(handle_protocol, image->device_handle, &fs_proto,
+ 			     (void **)&io);
+ 	if (status != EFI_SUCCESS) {
+-		pr_efi_err("Failed to handle fs_proto\n");
++		efi_err("Failed to handle fs_proto\n");
+ 		return status;
+ 	}
+ 
+ 	status = io->open_volume(io, fh);
+ 	if (status != EFI_SUCCESS)
+-		pr_efi_err("Failed to open volume\n");
++		efi_err("Failed to open volume\n");
+ 
+ 	return status;
+ }
+@@ -191,7 +191,7 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
+ 							    &alloc_addr,
+ 							    hard_limit);
+ 			if (status != EFI_SUCCESS) {
+-				pr_efi_err("Failed to allocate memory for files\n");
++				efi_err("Failed to allocate memory for files\n");
+ 				goto err_close_file;
+ 			}
+ 
+@@ -215,7 +215,7 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
+ 
+ 			status = file->read(file, &chunksize, addr);
+ 			if (status != EFI_SUCCESS) {
+-				pr_efi_err("Failed to read file\n");
++				efi_err("Failed to read file\n");
+ 				goto err_close_file;
+ 			}
+ 			addr += chunksize;
+diff --git a/drivers/firmware/efi/libstub/pci.c b/drivers/firmware/efi/libstub/pci.c
+index b025e59b94df..60af51bed573 100644
+--- a/drivers/firmware/efi/libstub/pci.c
++++ b/drivers/firmware/efi/libstub/pci.c
+@@ -28,21 +28,21 @@ void efi_pci_disable_bridge_busmaster(void)
+ 
+ 	if (status != EFI_BUFFER_TOO_SMALL) {
+ 		if (status != EFI_SUCCESS && status != EFI_NOT_FOUND)
+-			pr_efi_err("Failed to locate PCI I/O handles'\n");
++			efi_err("Failed to locate PCI I/O handles'\n");
+ 		return;
+ 	}
+ 
+ 	status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, pci_handle_size,
+ 			     (void **)&pci_handle);
+ 	if (status != EFI_SUCCESS) {
+-		pr_efi_err("Failed to allocate memory for 'pci_handle'\n");
++		efi_err("Failed to allocate memory for 'pci_handle'\n");
+ 		return;
+ 	}
+ 
+ 	status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL, &pci_proto,
+ 			     NULL, &pci_handle_size, pci_handle);
+ 	if (status != EFI_SUCCESS) {
+-		pr_efi_err("Failed to locate PCI I/O handles'\n");
++		efi_err("Failed to locate PCI I/O handles'\n");
+ 		goto free_handle;
+ 	}
+ 
+@@ -106,7 +106,7 @@ void efi_pci_disable_bridge_busmaster(void)
+ 		status = efi_call_proto(pci, pci.write, EfiPciIoWidthUint16,
+ 					PCI_COMMAND, 1, &command);
+ 		if (status != EFI_SUCCESS)
+-			pr_efi_err("Failed to disable PCI busmastering\n");
++			efi_err("Failed to disable PCI busmastering\n");
+ 	}
+ 
+ free_handle:
+diff --git a/drivers/firmware/efi/libstub/relocate.c b/drivers/firmware/efi/libstub/relocate.c
+index 1507d3c82884..93c04d6aaed1 100644
+--- a/drivers/firmware/efi/libstub/relocate.c
++++ b/drivers/firmware/efi/libstub/relocate.c
+@@ -157,7 +157,7 @@ efi_status_t efi_relocate_kernel(unsigned long *image_addr,
+ 					     min_addr);
+ 	}
+ 	if (status != EFI_SUCCESS) {
+-		pr_efi_err("Failed to allocate usable memory for kernel.\n");
++		efi_err("Failed to allocate usable memory for kernel.\n");
+ 		return status;
+ 	}
+ 
+diff --git a/drivers/firmware/efi/libstub/secureboot.c b/drivers/firmware/efi/libstub/secureboot.c
+index a765378ad18c..5efc524b14be 100644
+--- a/drivers/firmware/efi/libstub/secureboot.c
++++ b/drivers/firmware/efi/libstub/secureboot.c
+@@ -67,10 +67,10 @@ enum efi_secureboot_mode efi_get_secureboot(void)
+ 		return efi_secureboot_mode_disabled;
+ 
+ secure_boot_enabled:
+-	pr_efi("UEFI Secure Boot is enabled.\n");
++	efi_info("UEFI Secure Boot is enabled.\n");
+ 	return efi_secureboot_mode_enabled;
+ 
+ out_efi_err:
+-	pr_efi_err("Could not determine UEFI Secure Boot status.\n");
++	efi_err("Could not determine UEFI Secure Boot status.\n");
+ 	return efi_secureboot_mode_unknown;
+ }

commit eed4e0193ee7b00213791f7732bce0fc0c54f3b3
+Author: Arvind Sankar 
+Date:   Thu Apr 30 14:28:34 2020 -0400
+
+    efi/libstub: Add a helper function to split 64-bit values
+    
+    In several places 64-bit values need to be split up into two 32-bit
+    fields, in order to be backward-compatible with the old 32-bit ABIs.
+    
+    Instead of open-coding this, add a helper function to set a 64-bit value
+    as two 32-bit fields.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200430182843.2510180-3-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
+index 5ff63230a1f1..e8aa70ba08d5 100644
+--- a/drivers/firmware/efi/libstub/efistub.h
++++ b/drivers/firmware/efi/libstub/efistub.h
+@@ -87,6 +87,13 @@ extern const efi_system_table_t *efi_system_table;
+ 		((handle = efi_get_handle_at((array), i)) || true);	\
+ 	     i++)
+ 
++static inline
++void efi_set_u64_split(u64 data, u32 *lo, u32 *hi)
++{
++	*lo = lower_32_bits(data);
++	*hi = upper_32_bits(data);
++}
++
+ /*
+  * Allocation types for calls to boottime->allocate_pages.
+  */
+diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
+index 216327d0b034..64cee0febae0 100644
+--- a/drivers/firmware/efi/libstub/gop.c
++++ b/drivers/firmware/efi/libstub/gop.c
+@@ -422,7 +422,6 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
+ 	efi_graphics_output_protocol_t *gop;
+ 	efi_graphics_output_protocol_mode_t *mode;
+ 	efi_graphics_output_mode_info_t *info;
+-	efi_physical_addr_t fb_base;
+ 
+ 	gop = find_gop(proto, size, handles);
+ 
+@@ -442,9 +441,8 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
+ 	si->lfb_width  = info->horizontal_resolution;
+ 	si->lfb_height = info->vertical_resolution;
+ 
+-	fb_base		 = efi_table_attr(mode, frame_buffer_base);
+-	si->lfb_base	 = lower_32_bits(fb_base);
+-	si->ext_lfb_base = upper_32_bits(fb_base);
++	efi_set_u64_split(efi_table_attr(mode, frame_buffer_base),
++			  &si->lfb_base, &si->ext_lfb_base);
+ 	if (si->ext_lfb_base)
+ 		si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE;
+ 
+diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
+index d4bafd7f6f9f..f91d4aab0156 100644
+--- a/drivers/firmware/efi/libstub/x86-stub.c
++++ b/drivers/firmware/efi/libstub/x86-stub.c
+@@ -408,9 +408,8 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
+ 	if (!cmdline_ptr)
+ 		goto fail;
+ 
+-	hdr->cmd_line_ptr = (unsigned long)cmdline_ptr;
+-	/* Fill in upper bits of command line address, NOP on 32 bit  */
+-	boot_params->ext_cmd_line_ptr = (u64)(unsigned long)cmdline_ptr >> 32;
++	efi_set_u64_split((unsigned long)cmdline_ptr,
++			  &hdr->cmd_line_ptr, &boot_params->ext_cmd_line_ptr);
+ 
+ 	hdr->ramdisk_image = 0;
+ 	hdr->ramdisk_size = 0;
+@@ -427,10 +426,10 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
+ 						 ULONG_MAX);
+ 			if (status != EFI_SUCCESS)
+ 				goto fail2;
+-			hdr->ramdisk_image = ramdisk_addr & 0xffffffff;
+-			hdr->ramdisk_size  = ramdisk_size & 0xffffffff;
+-			boot_params->ext_ramdisk_image = (u64)ramdisk_addr >> 32;
+-			boot_params->ext_ramdisk_size  = (u64)ramdisk_size >> 32;
++			efi_set_u64_split(ramdisk_addr, &hdr->ramdisk_image,
++					  &boot_params->ext_ramdisk_image);
++			efi_set_u64_split(ramdisk_size, &hdr->ramdisk_size,
++					  &boot_params->ext_ramdisk_size);
+ 		}
+ 	}
+ 
+@@ -639,17 +638,14 @@ static efi_status_t exit_boot_func(struct efi_boot_memmap *map,
+ 				   : EFI32_LOADER_SIGNATURE;
+ 	memcpy(&p->efi->efi_loader_signature, signature, sizeof(__u32));
+ 
+-	p->efi->efi_systab		= (unsigned long)efi_system_table;
++	efi_set_u64_split((unsigned long)efi_system_table,
++			  &p->efi->efi_systab, &p->efi->efi_systab_hi);
+ 	p->efi->efi_memdesc_size	= *map->desc_size;
+ 	p->efi->efi_memdesc_version	= *map->desc_ver;
+-	p->efi->efi_memmap		= (unsigned long)*map->map;
++	efi_set_u64_split((unsigned long)*map->map,
++			  &p->efi->efi_memmap, &p->efi->efi_memmap_hi);
+ 	p->efi->efi_memmap_size		= *map->map_size;
+ 
+-#ifdef CONFIG_X86_64
+-	p->efi->efi_systab_hi		= (unsigned long)efi_system_table >> 32;
+-	p->efi->efi_memmap_hi		= (unsigned long)*map->map >> 32;
+-#endif
+-
+ 	return EFI_SUCCESS;
+ }
+ 
+@@ -785,10 +781,10 @@ unsigned long efi_main(efi_handle_t handle,
+ 
+ 		status = efi_load_initrd_dev_path(&addr, &size, ULONG_MAX);
+ 		if (status == EFI_SUCCESS) {
+-			hdr->ramdisk_image		= (u32)addr;
+-			hdr->ramdisk_size 		= (u32)size;
+-			boot_params->ext_ramdisk_image	= (u64)addr >> 32;
+-			boot_params->ext_ramdisk_size 	= (u64)size >> 32;
++			efi_set_u64_split(addr, &hdr->ramdisk_image,
++					  &boot_params->ext_ramdisk_image);
++			efi_set_u64_split(size, &hdr->ramdisk_size,
++					  &boot_params->ext_ramdisk_size);
+ 		} else if (status != EFI_NOT_FOUND) {
+ 			efi_printk("efi_load_initrd_dev_path() failed!\n");
+ 			goto fail;

commit 019512f1fd373632577ecd3e8d721e48b71fb36a
+Author: Arvind Sankar 
+Date:   Thu Apr 30 14:28:33 2020 -0400
+
+    efi/x86: Use correct size for boot_params
+    
+    struct boot_params is only 4096 bytes, not 16384. Fix this by using
+    sizeof(struct boot_params) instead of hardcoding the incorrect value.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200430182843.2510180-2-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
+index 597793fe8d22..d4bafd7f6f9f 100644
+--- a/drivers/firmware/efi/libstub/x86-stub.c
++++ b/drivers/firmware/efi/libstub/x86-stub.c
+@@ -379,13 +379,14 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
+ 	image_base = efi_table_attr(image, image_base);
+ 	image_offset = (void *)startup_32 - image_base;
+ 
+-	status = efi_allocate_pages(0x4000, (unsigned long *)&boot_params, ULONG_MAX);
++	status = efi_allocate_pages(sizeof(struct boot_params),
++				    (unsigned long *)&boot_params, ULONG_MAX);
+ 	if (status != EFI_SUCCESS) {
+ 		efi_printk("Failed to allocate lowmem for boot params\n");
+ 		efi_exit(handle, status);
+ 	}
+ 
+-	memset(boot_params, 0x0, 0x4000);
++	memset(boot_params, 0x0, sizeof(struct boot_params));
+ 
+ 	hdr = &boot_params->hdr;
+ 
+@@ -439,7 +440,7 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
+ fail2:
+ 	efi_free(options_size, (unsigned long)cmdline_ptr);
+ fail:
+-	efi_free(0x4000, (unsigned long)boot_params);
++	efi_free(sizeof(struct boot_params), (unsigned long)boot_params);
+ 
+ 	efi_exit(handle, status);
+ }

commit 544393707f3ca4f185ea1e41cc3206d1526c99cf
+Author: Arvind Sankar 
+Date:   Thu Apr 16 11:12:27 2020 -0400
+
+    efi: Kill __efistub_global
+    
+    Now that both arm and x86 are using the linker script to place the EFI
+    stub's global variables in the correct section, remove __efistub_global.
+    
+    Signed-off-by: Arvind Sankar 
+    Reviewed-by: Ard Biesheuvel 
+    Link: https://lore.kernel.org/r/20200416151227.3360778-4-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
+index c6092b6038cf..14e56a64f208 100644
+--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
++++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
+@@ -12,14 +12,13 @@
+ 
+ #include "efistub.h"
+ 
+-static bool __efistub_global efi_nochunk;
+-static bool __efistub_global efi_nokaslr;
+-static bool __efistub_global efi_noinitrd;
+-static bool __efistub_global efi_quiet;
+-static bool __efistub_global efi_novamap;
+-static bool __efistub_global efi_nosoftreserve;
+-static bool __efistub_global efi_disable_pci_dma =
+-					IS_ENABLED(CONFIG_EFI_DISABLE_PCI_DMA);
++static bool efi_nochunk;
++static bool efi_nokaslr;
++static bool efi_noinitrd;
++static bool efi_quiet;
++static bool efi_novamap;
++static bool efi_nosoftreserve;
++static bool efi_disable_pci_dma = IS_ENABLED(CONFIG_EFI_DISABLE_PCI_DMA);
+ 
+ bool __pure nochunk(void)
+ {
+diff --git a/drivers/firmware/efi/libstub/efi-stub.c b/drivers/firmware/efi/libstub/efi-stub.c
+index 8a26cc11ca4a..8455c590c7b9 100644
+--- a/drivers/firmware/efi/libstub/efi-stub.c
++++ b/drivers/firmware/efi/libstub/efi-stub.c
+@@ -36,9 +36,9 @@
+ #endif
+ 
+ static u64 virtmap_base = EFI_RT_VIRTUAL_BASE;
+-static bool __efistub_global flat_va_mapping;
++static bool flat_va_mapping;
+ 
+-static efi_system_table_t *__efistub_global sys_table;
++static efi_system_table_t *sys_table;
+ 
+ __pure efi_system_table_t *efi_system_table(void)
+ {
+diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
+index 5244eacc5d4b..9a87fff1d4ba 100644
+--- a/drivers/firmware/efi/libstub/efistub.h
++++ b/drivers/firmware/efi/libstub/efistub.h
+@@ -25,8 +25,6 @@
+ #define EFI_ALLOC_ALIGN		EFI_PAGE_SIZE
+ #endif
+ 
+-#define __efistub_global
+-
+ extern bool __pure nochunk(void);
+ extern bool __pure nokaslr(void);
+ extern bool __pure noinitrd(void);
+diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
+index fa05a0b0adfd..216327d0b034 100644
+--- a/drivers/firmware/efi/libstub/gop.c
++++ b/drivers/firmware/efi/libstub/gop.c
+@@ -32,7 +32,7 @@ static struct {
+ 			u8 depth;
+ 		} res;
+ 	};
+-} cmdline __efistub_global = { .option = EFI_CMDLINE_NONE };
++} cmdline = { .option = EFI_CMDLINE_NONE };
+ 
+ static bool parse_modenum(char *option, char **next)
+ {
+diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
+index 05ccb229fb45..1c3807d0c321 100644
+--- a/drivers/firmware/efi/libstub/x86-stub.c
++++ b/drivers/firmware/efi/libstub/x86-stub.c
+@@ -20,7 +20,7 @@
+ /* Maximum physical address for 64-bit kernel with 4-level paging */
+ #define MAXMEM_X86_64_4LEVEL (1ull << 46)
+ 
+-static efi_system_table_t *sys_table __efistub_global;
++static efi_system_table_t *sys_table;
+ extern const bool efi_is64;
+ extern u32 image_offset;
+ 

commit 26a92425f9a301fdeb5482e7891915ce43cc0556
+Author: Arvind Sankar 
+Date:   Thu Apr 16 11:12:26 2020 -0400
+
+    efi/x86: Remove __efistub_global and add relocation check
+    
+    Instead of using __efistub_global to force variables into the .data
+    section, leave them in the .bss but pull the EFI stub's .bss section
+    into .data in the linker script for the compressed kernel.
+    
+    Add relocation checking for x86 as well to catch non-PC-relative
+    relocations that require runtime processing, since the EFI stub does not
+    do any runtime relocation processing.
+    
+    This will catch, for example, data relocations created by static
+    initializers of pointers.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200416151227.3360778-3-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/arch/x86/boot/compressed/vmlinux.lds.S b/arch/x86/boot/compressed/vmlinux.lds.S
+index 508cfa6828c5..0dc5c2b9614b 100644
+--- a/arch/x86/boot/compressed/vmlinux.lds.S
++++ b/arch/x86/boot/compressed/vmlinux.lds.S
+@@ -52,6 +52,7 @@ SECTIONS
+ 		_data = . ;
+ 		*(.data)
+ 		*(.data.*)
++		*(.bss.efistub)
+ 		_edata = . ;
+ 	}
+ 	. = ALIGN(L1_CACHE_BYTES);
+diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
+index aa3ab9a4105e..8d246b51bd49 100644
+--- a/drivers/firmware/efi/libstub/Makefile
++++ b/drivers/firmware/efi/libstub/Makefile
+@@ -60,6 +60,25 @@ lib-$(CONFIG_X86)		+= x86-stub.o
+ CFLAGS_arm32-stub.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
+ CFLAGS_arm64-stub.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
+ 
++#
++# For x86, bootloaders like systemd-boot or grub-efi do not zero-initialize the
++# .bss section, so the .bss section of the EFI stub needs to be included in the
++# .data section of the compressed kernel to ensure initialization. Rename the
++# .bss section here so it's easy to pick out in the linker script.
++#
++STUBCOPY_FLAGS-$(CONFIG_X86)	+= --rename-section .bss=.bss.efistub,load,alloc
++STUBCOPY_RELOC-$(CONFIG_X86_32)	:= R_386_32
++STUBCOPY_RELOC-$(CONFIG_X86_64)	:= R_X86_64_64
++
++#
++# ARM discards the .data section because it disallows r/w data in the
++# decompressor. So move our .data to .data.efistub and .bss to .bss.efistub,
++# which are preserved explicitly by the decompressor linker script.
++#
++STUBCOPY_FLAGS-$(CONFIG_ARM)	+= --rename-section .data=.data.efistub	\
++				   --rename-section .bss=.bss.efistub,load,alloc
++STUBCOPY_RELOC-$(CONFIG_ARM)	:= R_ARM_ABS
++
+ #
+ # arm64 puts the stub in the kernel proper, which will unnecessarily retain all
+ # code indefinitely unless it is annotated as __init/__initdata/__initconst etc.
+@@ -74,8 +93,8 @@ CFLAGS_arm64-stub.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
+ # a verification pass to see if any absolute relocations exist in any of the
+ # object files.
+ #
+-extra-$(CONFIG_EFI_GENERIC_STUB) := $(lib-y)
+-lib-$(CONFIG_EFI_GENERIC_STUB)	:= $(patsubst %.o,%.stub.o,$(lib-y))
++extra-y				:= $(lib-y)
++lib-y				:= $(patsubst %.o,%.stub.o,$(lib-y))
+ 
+ STUBCOPY_FLAGS-$(CONFIG_ARM64)	+= --prefix-alloc-sections=.init \
+ 				   --prefix-symbols=__efistub_
+@@ -98,12 +117,3 @@ quiet_cmd_stubcopy = STUBCPY $@
+ 		/bin/false;						\
+ 	fi;								\
+ 	$(OBJCOPY) $(STUBCOPY_FLAGS-y) $< $@
+-
+-#
+-# ARM discards the .data section because it disallows r/w data in the
+-# decompressor. So move our .data to .data.efistub and .bss to .bss.efistub,
+-# which are preserved explicitly by the decompressor linker script.
+-#
+-STUBCOPY_FLAGS-$(CONFIG_ARM)	+= --rename-section .data=.data.efistub	\
+-				   --rename-section .bss=.bss.efistub,load,alloc
+-STUBCOPY_RELOC-$(CONFIG_ARM)	:= R_ARM_ABS
+diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
+index 96e25b17c88e..5244eacc5d4b 100644
+--- a/drivers/firmware/efi/libstub/efistub.h
++++ b/drivers/firmware/efi/libstub/efistub.h
+@@ -25,11 +25,7 @@
+ #define EFI_ALLOC_ALIGN		EFI_PAGE_SIZE
+ #endif
+ 
+-#if defined(CONFIG_X86)
+-#define __efistub_global	__section(.data)
+-#else
+ #define __efistub_global
+-#endif
+ 
+ extern bool __pure nochunk(void);
+ extern bool __pure nokaslr(void);

commit 420b6d00ca94ce5b6578b1bc12e767ac7a0251ac
+Author: Arvind Sankar 
+Date:   Thu Apr 16 11:12:25 2020 -0400
+
+    efi/arm: Remove __efistub_global annotation
+    
+    Instead of using __efistub_global to force variables into the .data
+    section, leave them in the .bss but pull the EFI stub's .bss section
+    into .data in the linker script for the compressed kernel.
+    
+    Signed-off-by: Arvind Sankar 
+    Reviewed-by: Ard Biesheuvel 
+    Link: https://lore.kernel.org/r/20200416151227.3360778-2-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/arch/arm/boot/compressed/vmlinux.lds.S b/arch/arm/boot/compressed/vmlinux.lds.S
+index b247f399de71..b6793c7932a9 100644
+--- a/arch/arm/boot/compressed/vmlinux.lds.S
++++ b/arch/arm/boot/compressed/vmlinux.lds.S
+@@ -78,7 +78,7 @@ SECTIONS
+      * The EFI stub always executes from RAM, and runs strictly before the
+      * decompressor, so we can make an exception for its r/w data, and keep it
+      */
+-    *(.data.efistub)
++    *(.data.efistub .bss.efistub)
+     __pecoff_data_end = .;
+ 
+     /*
+diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
+index 9a712a6e2f87..aa3ab9a4105e 100644
+--- a/drivers/firmware/efi/libstub/Makefile
++++ b/drivers/firmware/efi/libstub/Makefile
+@@ -101,8 +101,9 @@ quiet_cmd_stubcopy = STUBCPY $@
+ 
+ #
+ # ARM discards the .data section because it disallows r/w data in the
+-# decompressor. So move our .data to .data.efistub, which is preserved
+-# explicitly by the decompressor linker script.
++# decompressor. So move our .data to .data.efistub and .bss to .bss.efistub,
++# which are preserved explicitly by the decompressor linker script.
+ #
+-STUBCOPY_FLAGS-$(CONFIG_ARM)	+= --rename-section .data=.data.efistub
++STUBCOPY_FLAGS-$(CONFIG_ARM)	+= --rename-section .data=.data.efistub	\
++				   --rename-section .bss=.bss.efistub,load,alloc
+ STUBCOPY_RELOC-$(CONFIG_ARM)	:= R_ARM_ABS
+diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
+index 2a0698d9dc78..96e25b17c88e 100644
+--- a/drivers/firmware/efi/libstub/efistub.h
++++ b/drivers/firmware/efi/libstub/efistub.h
+@@ -25,7 +25,7 @@
+ #define EFI_ALLOC_ALIGN		EFI_PAGE_SIZE
+ #endif
+ 
+-#if defined(CONFIG_ARM) || defined(CONFIG_X86)
++#if defined(CONFIG_X86)
+ #define __efistub_global	__section(.data)
+ #else
+ #define __efistub_global

commit 45d97a749e9fec6d5324b19561ce5fbfa937d60b
+Author: Arvind Sankar 
+Date:   Sat Mar 28 12:06:01 2020 -0400
+
+    efi/gop: Allow automatically choosing the best mode
+    
+    Add the ability to automatically pick the highest resolution video mode
+    (defined as the product of vertical and horizontal resolution) by using
+    a command-line argument of the form
+            video=efifb:auto
+    
+    If there are multiple modes with the highest resolution, pick one with
+    the highest color depth.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200328160601.378299-2-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/Documentation/fb/efifb.rst b/Documentation/fb/efifb.rst
+index eca38466487a..519550517fd4 100644
+--- a/Documentation/fb/efifb.rst
++++ b/Documentation/fb/efifb.rst
+@@ -57,4 +57,10 @@ mode=n
+         "rgb" or "bgr" to match specifically those pixel formats, or a number
+         for a mode with matching bits per pixel.
+ 
++auto
++        The EFI stub will choose the mode with the highest resolution (product
++        of horizontal and vertical resolution). If there are multiple modes
++        with the highest resolution, it will choose one with the highest color
++        depth.
++
+ Edgar Hucek 
+diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
+index 848cb605a9c4..fa05a0b0adfd 100644
+--- a/drivers/firmware/efi/libstub/gop.c
++++ b/drivers/firmware/efi/libstub/gop.c
+@@ -18,7 +18,8 @@
+ enum efi_cmdline_option {
+ 	EFI_CMDLINE_NONE,
+ 	EFI_CMDLINE_MODE_NUM,
+-	EFI_CMDLINE_RES
++	EFI_CMDLINE_RES,
++	EFI_CMDLINE_AUTO
+ };
+ 
+ static struct {
+@@ -86,6 +87,19 @@ static bool parse_res(char *option, char **next)
+ 	return true;
+ }
+ 
++static bool parse_auto(char *option, char **next)
++{
++	if (!strstarts(option, "auto"))
++		return false;
++	option += strlen("auto");
++	if (*option && *option++ != ',')
++		return false;
++	cmdline.option = EFI_CMDLINE_AUTO;
++
++	*next = option;
++	return true;
++}
++
+ void efi_parse_option_graphics(char *option)
+ {
+ 	while (*option) {
+@@ -93,6 +107,8 @@ void efi_parse_option_graphics(char *option)
+ 			continue;
+ 		if (parse_res(option, &option))
+ 			continue;
++		if (parse_auto(option, &option))
++			continue;
+ 
+ 		while (*option && *option++ != ',')
+ 			;
+@@ -211,6 +227,69 @@ static u32 choose_mode_res(efi_graphics_output_protocol_t *gop)
+ 	return cur_mode;
+ }
+ 
++static u32 choose_mode_auto(efi_graphics_output_protocol_t *gop)
++{
++	efi_status_t status;
++
++	efi_graphics_output_protocol_mode_t *mode;
++	efi_graphics_output_mode_info_t *info;
++	unsigned long info_size;
++
++	u32 max_mode, cur_mode, best_mode, area;
++	u8 depth;
++	int pf;
++	efi_pixel_bitmask_t pi;
++	u32 m, w, h, a;
++	u8 d;
++
++	mode = efi_table_attr(gop, mode);
++
++	cur_mode = efi_table_attr(mode, mode);
++	max_mode = efi_table_attr(mode, max_mode);
++
++	info = efi_table_attr(mode, info);
++
++	pf = info->pixel_format;
++	pi = info->pixel_information;
++	w  = info->horizontal_resolution;
++	h  = info->vertical_resolution;
++
++	best_mode = cur_mode;
++	area = w * h;
++	depth = pixel_bpp(pf, pi);
++
++	for (m = 0; m < max_mode; m++) {
++		if (m == cur_mode)
++			continue;
++
++		status = efi_call_proto(gop, query_mode, m,
++					&info_size, &info);
++		if (status != EFI_SUCCESS)
++			continue;
++
++		pf = info->pixel_format;
++		pi = info->pixel_information;
++		w  = info->horizontal_resolution;
++		h  = info->vertical_resolution;
++
++		efi_bs_call(free_pool, info);
++
++		if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX)
++			continue;
++		a = w * h;
++		if (a < area)
++			continue;
++		d = pixel_bpp(pf, pi);
++		if (a > area || d > depth) {
++			best_mode = m;
++			area = a;
++			depth = d;
++		}
++	}
++
++	return best_mode;
++}
++
+ static void set_mode(efi_graphics_output_protocol_t *gop)
+ {
+ 	efi_graphics_output_protocol_mode_t *mode;
+@@ -223,6 +302,9 @@ static void set_mode(efi_graphics_output_protocol_t *gop)
+ 	case EFI_CMDLINE_RES:
+ 		new_mode = choose_mode_res(gop);
+ 		break;
++	case EFI_CMDLINE_AUTO:
++		new_mode = choose_mode_auto(gop);
++		break;
+ 	default:
+ 		return;
+ 	}

commit 9a1663bc4d9856f6810786fec597dab5440a9d8d
+Author: Arvind Sankar 
+Date:   Thu Mar 19 22:00:27 2020 -0400
+
+    efi/gop: Allow specifying depth as well as resolution
+    
+    Extend the video mode argument to handle an optional color depth
+    specification of the form
+            video=efifb:x[-(rgb|bgr|)]
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200320020028.1936003-14-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/Documentation/fb/efifb.rst b/Documentation/fb/efifb.rst
+index 635275071307..eca38466487a 100644
+--- a/Documentation/fb/efifb.rst
++++ b/Documentation/fb/efifb.rst
+@@ -50,9 +50,11 @@ mode=n
+         The EFI stub will set the mode of the display to mode number n if
+         possible.
+ 
+-x
++x[-(rgb|bgr|)]
+         The EFI stub will search for a display mode that matches the specified
+-        horizontal and vertical resolution, and set the mode of the display to
+-        it if one is found.
++        horizontal and vertical resolution, and optionally bit depth, and set
++        the mode of the display to it if one is found. The bit depth can either
++        "rgb" or "bgr" to match specifically those pixel formats, or a number
++        for a mode with matching bits per pixel.
+ 
+ Edgar Hucek 
+diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
+index cc84e6a82f54..848cb605a9c4 100644
+--- a/drivers/firmware/efi/libstub/gop.c
++++ b/drivers/firmware/efi/libstub/gop.c
+@@ -27,6 +27,8 @@ static struct {
+ 		u32 mode;
+ 		struct {
+ 			u32 width, height;
++			int format;
++			u8 depth;
+ 		} res;
+ 	};
+ } cmdline __efistub_global = { .option = EFI_CMDLINE_NONE };
+@@ -50,7 +52,8 @@ static bool parse_modenum(char *option, char **next)
+ 
+ static bool parse_res(char *option, char **next)
+ {
+-	u32 w, h;
++	u32 w, h, d = 0;
++	int pf = -1;
+ 
+ 	if (!isdigit(*option))
+ 		return false;
+@@ -58,11 +61,26 @@ static bool parse_res(char *option, char **next)
+ 	if (*option++ != 'x' || !isdigit(*option))
+ 		return false;
+ 	h = simple_strtoull(option, &option, 10);
++	if (*option == '-') {
++		option++;
++		if (strstarts(option, "rgb")) {
++			option += strlen("rgb");
++			pf = PIXEL_RGB_RESERVED_8BIT_PER_COLOR;
++		} else if (strstarts(option, "bgr")) {
++			option += strlen("bgr");
++			pf = PIXEL_BGR_RESERVED_8BIT_PER_COLOR;
++		} else if (isdigit(*option))
++			d = simple_strtoull(option, &option, 10);
++		else
++			return false;
++	}
+ 	if (*option && *option++ != ',')
+ 		return false;
+ 	cmdline.option     = EFI_CMDLINE_RES;
+ 	cmdline.res.width  = w;
+ 	cmdline.res.height = h;
++	cmdline.res.format = pf;
++	cmdline.res.depth  = d;
+ 
+ 	*next = option;
+ 	return true;
+@@ -123,6 +141,18 @@ static u32 choose_mode_modenum(efi_graphics_output_protocol_t *gop)
+ 	return cmdline.mode;
+ }
+ 
++static u8 pixel_bpp(int pixel_format, efi_pixel_bitmask_t pixel_info)
++{
++	if (pixel_format == PIXEL_BIT_MASK) {
++		u32 mask = pixel_info.red_mask | pixel_info.green_mask |
++			   pixel_info.blue_mask | pixel_info.reserved_mask;
++		if (!mask)
++			return 0;
++		return __fls(mask) - __ffs(mask) + 1;
++	} else
++		return 32;
++}
++
+ static u32 choose_mode_res(efi_graphics_output_protocol_t *gop)
+ {
+ 	efi_status_t status;
+@@ -133,16 +163,21 @@ static u32 choose_mode_res(efi_graphics_output_protocol_t *gop)
+ 
+ 	u32 max_mode, cur_mode;
+ 	int pf;
++	efi_pixel_bitmask_t pi;
+ 	u32 m, w, h;
+ 
+ 	mode = efi_table_attr(gop, mode);
+ 
+ 	cur_mode = efi_table_attr(mode, mode);
+ 	info = efi_table_attr(mode, info);
+-	w = info->horizontal_resolution;
+-	h = info->vertical_resolution;
++	pf = info->pixel_format;
++	pi = info->pixel_information;
++	w  = info->horizontal_resolution;
++	h  = info->vertical_resolution;
+ 
+-	if (w == cmdline.res.width && h == cmdline.res.height)
++	if (w == cmdline.res.width && h == cmdline.res.height &&
++	    (cmdline.res.format < 0 || cmdline.res.format == pf) &&
++	    (!cmdline.res.depth || cmdline.res.depth == pixel_bpp(pf, pi)))
+ 		return cur_mode;
+ 
+ 	max_mode = efi_table_attr(mode, max_mode);
+@@ -157,6 +192,7 @@ static u32 choose_mode_res(efi_graphics_output_protocol_t *gop)
+ 			continue;
+ 
+ 		pf = info->pixel_format;
++		pi = info->pixel_information;
+ 		w  = info->horizontal_resolution;
+ 		h  = info->vertical_resolution;
+ 
+@@ -164,7 +200,9 @@ static u32 choose_mode_res(efi_graphics_output_protocol_t *gop)
+ 
+ 		if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX)
+ 			continue;
+-		if (w == cmdline.res.width && h == cmdline.res.height)
++		if (w == cmdline.res.width && h == cmdline.res.height &&
++		    (cmdline.res.format < 0 || cmdline.res.format == pf) &&
++		    (!cmdline.res.depth || cmdline.res.depth == pixel_bpp(pf, pi)))
+ 			return m;
+ 	}
+ 

commit d9ff0323d074c6c06467118c7a43d5748f147369
+Author: Arvind Sankar 
+Date:   Thu Mar 19 22:00:26 2020 -0400
+
+    efi/gop: Allow specifying mode by x
+    
+    Add the ability to choose a video mode using a command-line argument of
+    the form
+            video=efifb:x
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200320020028.1936003-13-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/Documentation/fb/efifb.rst b/Documentation/fb/efifb.rst
+index 367fbda2f4da..635275071307 100644
+--- a/Documentation/fb/efifb.rst
++++ b/Documentation/fb/efifb.rst
+@@ -50,4 +50,9 @@ mode=n
+         The EFI stub will set the mode of the display to mode number n if
+         possible.
+ 
++x
++        The EFI stub will search for a display mode that matches the specified
++        horizontal and vertical resolution, and set the mode of the display to
++        it if one is found.
++
+ Edgar Hucek 
+diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
+index a32b784b4577..cc84e6a82f54 100644
+--- a/drivers/firmware/efi/libstub/gop.c
++++ b/drivers/firmware/efi/libstub/gop.c
+@@ -6,6 +6,7 @@
+  * ----------------------------------------------------------------------- */
+ 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -17,11 +18,17 @@
+ enum efi_cmdline_option {
+ 	EFI_CMDLINE_NONE,
+ 	EFI_CMDLINE_MODE_NUM,
++	EFI_CMDLINE_RES
+ };
+ 
+ static struct {
+ 	enum efi_cmdline_option option;
+-	u32 mode;
++	union {
++		u32 mode;
++		struct {
++			u32 width, height;
++		} res;
++	};
+ } cmdline __efistub_global = { .option = EFI_CMDLINE_NONE };
+ 
+ static bool parse_modenum(char *option, char **next)
+@@ -41,11 +48,33 @@ static bool parse_modenum(char *option, char **next)
+ 	return true;
+ }
+ 
++static bool parse_res(char *option, char **next)
++{
++	u32 w, h;
++
++	if (!isdigit(*option))
++		return false;
++	w = simple_strtoull(option, &option, 10);
++	if (*option++ != 'x' || !isdigit(*option))
++		return false;
++	h = simple_strtoull(option, &option, 10);
++	if (*option && *option++ != ',')
++		return false;
++	cmdline.option     = EFI_CMDLINE_RES;
++	cmdline.res.width  = w;
++	cmdline.res.height = h;
++
++	*next = option;
++	return true;
++}
++
+ void efi_parse_option_graphics(char *option)
+ {
+ 	while (*option) {
+ 		if (parse_modenum(option, &option))
+ 			continue;
++		if (parse_res(option, &option))
++			continue;
+ 
+ 		while (*option && *option++ != ',')
+ 			;
+@@ -94,6 +123,56 @@ static u32 choose_mode_modenum(efi_graphics_output_protocol_t *gop)
+ 	return cmdline.mode;
+ }
+ 
++static u32 choose_mode_res(efi_graphics_output_protocol_t *gop)
++{
++	efi_status_t status;
++
++	efi_graphics_output_protocol_mode_t *mode;
++	efi_graphics_output_mode_info_t *info;
++	unsigned long info_size;
++
++	u32 max_mode, cur_mode;
++	int pf;
++	u32 m, w, h;
++
++	mode = efi_table_attr(gop, mode);
++
++	cur_mode = efi_table_attr(mode, mode);
++	info = efi_table_attr(mode, info);
++	w = info->horizontal_resolution;
++	h = info->vertical_resolution;
++
++	if (w == cmdline.res.width && h == cmdline.res.height)
++		return cur_mode;
++
++	max_mode = efi_table_attr(mode, max_mode);
++
++	for (m = 0; m < max_mode; m++) {
++		if (m == cur_mode)
++			continue;
++
++		status = efi_call_proto(gop, query_mode, m,
++					&info_size, &info);
++		if (status != EFI_SUCCESS)
++			continue;
++
++		pf = info->pixel_format;
++		w  = info->horizontal_resolution;
++		h  = info->vertical_resolution;
++
++		efi_bs_call(free_pool, info);
++
++		if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX)
++			continue;
++		if (w == cmdline.res.width && h == cmdline.res.height)
++			return m;
++	}
++
++	efi_printk("Couldn't find requested mode\n");
++
++	return cur_mode;
++}
++
+ static void set_mode(efi_graphics_output_protocol_t *gop)
+ {
+ 	efi_graphics_output_protocol_mode_t *mode;
+@@ -103,6 +182,9 @@ static void set_mode(efi_graphics_output_protocol_t *gop)
+ 	case EFI_CMDLINE_MODE_NUM:
+ 		new_mode = choose_mode_modenum(gop);
+ 		break;
++	case EFI_CMDLINE_RES:
++		new_mode = choose_mode_res(gop);
++		break;
+ 	default:
+ 		return;
+ 	}

commit fffb68047e563fb74f782c726e9bdf1fa117d93d
+Author: Arvind Sankar 
+Date:   Thu Mar 19 22:00:25 2020 -0400
+
+    efi/gop: Allow specifying mode number on command line
+    
+    Add the ability to choose a video mode for the selected gop by using a
+    command-line argument of the form
+            video=efifb:mode=
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200320020028.1936003-12-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/Documentation/fb/efifb.rst b/Documentation/fb/efifb.rst
+index 04840331a00e..367fbda2f4da 100644
+--- a/Documentation/fb/efifb.rst
++++ b/Documentation/fb/efifb.rst
+@@ -2,8 +2,10 @@
+ What is efifb?
+ ==============
+ 
+-This is a generic EFI platform driver for Intel based Apple computers.
+-efifb is only for EFI booted Intel Macs.
++This is a generic EFI platform driver for systems with UEFI firmware. The
++system must be booted via the EFI stub for this to be usable. efifb supports
++both firmware with Graphics Output Protocol (GOP) displays as well as older
++systems with only Universal Graphics Adapter (UGA) displays.
+ 
+ Supported Hardware
+ ==================
+@@ -12,11 +14,14 @@ Supported Hardware
+ - Macbook
+ - Macbook Pro 15"/17"
+ - MacMini
++- ARM/ARM64/X86 systems with UEFI firmware
+ 
+ How to use it?
+ ==============
+ 
+-efifb does not have any kind of autodetection of your machine.
++For UGA displays, efifb does not have any kind of autodetection of your
++machine.
++
+ You have to add the following kernel parameters in your elilo.conf::
+ 
+ 	Macbook :
+@@ -28,6 +33,9 @@ You have to add the following kernel parameters in your elilo.conf::
+ 	Macbook Pro 17", iMac 20" :
+ 		video=efifb:i20
+ 
++For GOP displays, efifb can autodetect the display's resolution and framebuffer
++address, so these should work out of the box without any special parameters.
++
+ Accepted options:
+ 
+ ======= ===========================================================
+@@ -36,4 +44,10 @@ nowc	Don't map the framebuffer write combined. This can be used
+ 	when large amounts of console data are written.
+ ======= ===========================================================
+ 
++Options for GOP displays:
++
++mode=n
++        The EFI stub will set the mode of the display to mode number n if
++        possible.
++
+ Edgar Hucek 
+diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
+index 9f34c7242939..c6092b6038cf 100644
+--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
++++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
+@@ -105,6 +105,9 @@ efi_status_t efi_parse_options(char const *cmdline)
+ 				efi_disable_pci_dma = true;
+ 			if (parse_option_str(val, "no_disable_early_pci_dma"))
+ 				efi_disable_pci_dma = false;
++		} else if (!strcmp(param, "video") &&
++			   val && strstarts(val, "efifb:")) {
++			efi_parse_option_graphics(val + strlen("efifb:"));
+ 		}
+ 	}
+ 	efi_bs_call(free_pool, buf);
+diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
+index 321244ed20a4..9af65be3b278 100644
+--- a/drivers/firmware/efi/libstub/efistub.h
++++ b/drivers/firmware/efi/libstub/efistub.h
+@@ -666,6 +666,8 @@ efi_status_t efi_relocate_kernel(unsigned long *image_addr,
+ 
+ efi_status_t efi_parse_options(char const *cmdline);
+ 
++void efi_parse_option_graphics(char *option);
++
+ efi_status_t efi_setup_gop(struct screen_info *si, efi_guid_t *proto,
+ 			   unsigned long size);
+ 
+diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
+index 2d91699e3061..a32b784b4577 100644
+--- a/drivers/firmware/efi/libstub/gop.c
++++ b/drivers/firmware/efi/libstub/gop.c
+@@ -8,11 +8,115 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ 
+ #include "efistub.h"
+ 
++enum efi_cmdline_option {
++	EFI_CMDLINE_NONE,
++	EFI_CMDLINE_MODE_NUM,
++};
++
++static struct {
++	enum efi_cmdline_option option;
++	u32 mode;
++} cmdline __efistub_global = { .option = EFI_CMDLINE_NONE };
++
++static bool parse_modenum(char *option, char **next)
++{
++	u32 m;
++
++	if (!strstarts(option, "mode="))
++		return false;
++	option += strlen("mode=");
++	m = simple_strtoull(option, &option, 0);
++	if (*option && *option++ != ',')
++		return false;
++	cmdline.option = EFI_CMDLINE_MODE_NUM;
++	cmdline.mode   = m;
++
++	*next = option;
++	return true;
++}
++
++void efi_parse_option_graphics(char *option)
++{
++	while (*option) {
++		if (parse_modenum(option, &option))
++			continue;
++
++		while (*option && *option++ != ',')
++			;
++	}
++}
++
++static u32 choose_mode_modenum(efi_graphics_output_protocol_t *gop)
++{
++	efi_status_t status;
++
++	efi_graphics_output_protocol_mode_t *mode;
++	efi_graphics_output_mode_info_t *info;
++	unsigned long info_size;
++
++	u32 max_mode, cur_mode;
++	int pf;
++
++	mode = efi_table_attr(gop, mode);
++
++	cur_mode = efi_table_attr(mode, mode);
++	if (cmdline.mode == cur_mode)
++		return cur_mode;
++
++	max_mode = efi_table_attr(mode, max_mode);
++	if (cmdline.mode >= max_mode) {
++		efi_printk("Requested mode is invalid\n");
++		return cur_mode;
++	}
++
++	status = efi_call_proto(gop, query_mode, cmdline.mode,
++				&info_size, &info);
++	if (status != EFI_SUCCESS) {
++		efi_printk("Couldn't get mode information\n");
++		return cur_mode;
++	}
++
++	pf = info->pixel_format;
++
++	efi_bs_call(free_pool, info);
++
++	if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX) {
++		efi_printk("Invalid PixelFormat\n");
++		return cur_mode;
++	}
++
++	return cmdline.mode;
++}
++
++static void set_mode(efi_graphics_output_protocol_t *gop)
++{
++	efi_graphics_output_protocol_mode_t *mode;
++	u32 cur_mode, new_mode;
++
++	switch (cmdline.option) {
++	case EFI_CMDLINE_MODE_NUM:
++		new_mode = choose_mode_modenum(gop);
++		break;
++	default:
++		return;
++	}
++
++	mode = efi_table_attr(gop, mode);
++	cur_mode = efi_table_attr(mode, mode);
++
++	if (new_mode == cur_mode)
++		return;
++
++	if (efi_call_proto(gop, set_mode, new_mode) != EFI_SUCCESS)
++		efi_printk("Failed to set requested mode\n");
++}
++
+ static void find_bits(u32 mask, u8 *pos, u8 *size)
+ {
+ 	if (!mask) {
+@@ -124,6 +228,9 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
+ 	if (!gop)
+ 		return EFI_NOT_FOUND;
+ 
++	/* Change mode if requested */
++	set_mode(gop);
++
+ 	/* EFI framebuffer */
+ 	mode = efi_table_attr(gop, mode);
+ 	info = efi_table_attr(mode, info);

commit b4b89a02724245c4f4eda9dbfb7895ddf122ca7f
+Author: Arvind Sankar 
+Date:   Thu Mar 19 22:00:24 2020 -0400
+
+    efi/gop: Add prototypes for query_mode and set_mode
+    
+    Add prototypes and argmap for the Graphics Output Protocol's QueryMode
+    and SetMode functions.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200320020028.1936003-11-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
+index 8391c115c0ec..f59cba117dcb 100644
+--- a/arch/x86/include/asm/efi.h
++++ b/arch/x86/include/asm/efi.h
+@@ -307,6 +307,10 @@ static inline u32 efi64_convert_status(efi_status_t status)
+ #define __efi64_argmap_load_file(protocol, path, policy, bufsize, buf)	\
+ 	((protocol), (path), (policy), efi64_zero_upper(bufsize), (buf))
+ 
++/* Graphics Output Protocol */
++#define __efi64_argmap_query_mode(gop, mode, size, info)		\
++	((gop), (mode), efi64_zero_upper(size), efi64_zero_upper(info))
++
+ /*
+  * The macros below handle the plumbing for the argument mapping. To add a
+  * mapping for a specific EFI method, simply define a macro
+diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
+index d9ad8582dbea..321244ed20a4 100644
+--- a/drivers/firmware/efi/libstub/efistub.h
++++ b/drivers/firmware/efi/libstub/efistub.h
+@@ -314,8 +314,10 @@ typedef union efi_graphics_output_protocol efi_graphics_output_protocol_t;
+ 
+ union efi_graphics_output_protocol {
+ 	struct {
+-		void *query_mode;
+-		void *set_mode;
++		efi_status_t (__efiapi *query_mode)(efi_graphics_output_protocol_t *,
++						    u32, unsigned long *,
++						    efi_graphics_output_mode_info_t **);
++		efi_status_t (__efiapi *set_mode)  (efi_graphics_output_protocol_t *, u32);
+ 		void *blt;
+ 		efi_graphics_output_protocol_mode_t *mode;
+ 	};

commit d49fd4bbf9bb0dbee3a3eed301ffeeb75636053b
+Author: Arvind Sankar 
+Date:   Thu Mar 19 22:00:23 2020 -0400
+
+    efi/gop: Remove unreachable code from setup_pixel_info
+    
+    pixel_format must be one of
+            PIXEL_RGB_RESERVED_8BIT_PER_COLOR
+            PIXEL_BGR_RESERVED_8BIT_PER_COLOR
+            PIXEL_BIT_MASK
+    since we skip PIXEL_BLT_ONLY when finding a gop.
+    
+    Remove the redundant code and add another check in find_gop to skip any
+    pixel formats that we don't know about, in case a later version of the
+    UEFI spec adds one.
+    
+    Reformat the code a little.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200320020028.1936003-10-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
+index 8bf424f35759..2d91699e3061 100644
+--- a/drivers/firmware/efi/libstub/gop.c
++++ b/drivers/firmware/efi/libstub/gop.c
+@@ -29,49 +29,34 @@ static void
+ setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line,
+ 		 efi_pixel_bitmask_t pixel_info, int pixel_format)
+ {
+-	if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) {
+-		si->lfb_depth = 32;
+-		si->lfb_linelength = pixels_per_scan_line * 4;
+-		si->red_size = 8;
+-		si->red_pos = 0;
+-		si->green_size = 8;
+-		si->green_pos = 8;
+-		si->blue_size = 8;
+-		si->blue_pos = 16;
+-		si->rsvd_size = 8;
+-		si->rsvd_pos = 24;
+-	} else if (pixel_format == PIXEL_BGR_RESERVED_8BIT_PER_COLOR) {
+-		si->lfb_depth = 32;
+-		si->lfb_linelength = pixels_per_scan_line * 4;
+-		si->red_size = 8;
+-		si->red_pos = 16;
+-		si->green_size = 8;
+-		si->green_pos = 8;
+-		si->blue_size = 8;
+-		si->blue_pos = 0;
+-		si->rsvd_size = 8;
+-		si->rsvd_pos = 24;
+-	} else if (pixel_format == PIXEL_BIT_MASK) {
+-		find_bits(pixel_info.red_mask, &si->red_pos, &si->red_size);
+-		find_bits(pixel_info.green_mask, &si->green_pos,
+-			  &si->green_size);
+-		find_bits(pixel_info.blue_mask, &si->blue_pos, &si->blue_size);
+-		find_bits(pixel_info.reserved_mask, &si->rsvd_pos,
+-			  &si->rsvd_size);
++	if (pixel_format == PIXEL_BIT_MASK) {
++		find_bits(pixel_info.red_mask,
++			  &si->red_pos, &si->red_size);
++		find_bits(pixel_info.green_mask,
++			  &si->green_pos, &si->green_size);
++		find_bits(pixel_info.blue_mask,
++			  &si->blue_pos, &si->blue_size);
++		find_bits(pixel_info.reserved_mask,
++			  &si->rsvd_pos, &si->rsvd_size);
+ 		si->lfb_depth = si->red_size + si->green_size +
+ 			si->blue_size + si->rsvd_size;
+ 		si->lfb_linelength = (pixels_per_scan_line * si->lfb_depth) / 8;
+ 	} else {
+-		si->lfb_depth = 4;
+-		si->lfb_linelength = si->lfb_width / 2;
+-		si->red_size = 0;
+-		si->red_pos = 0;
+-		si->green_size = 0;
+-		si->green_pos = 0;
+-		si->blue_size = 0;
+-		si->blue_pos = 0;
+-		si->rsvd_size = 0;
+-		si->rsvd_pos = 0;
++		if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) {
++			si->red_pos   = 0;
++			si->blue_pos  = 16;
++		} else /* PIXEL_BGR_RESERVED_8BIT_PER_COLOR */ {
++			si->blue_pos  = 0;
++			si->red_pos   = 16;
++		}
++
++		si->green_pos = 8;
++		si->rsvd_pos  = 24;
++		si->red_size = si->green_size =
++			si->blue_size = si->rsvd_size = 8;
++
++		si->lfb_depth = 32;
++		si->lfb_linelength = pixels_per_scan_line * 4;
+ 	}
+ }
+ 
+@@ -100,7 +85,8 @@ find_gop(efi_guid_t *proto, unsigned long size, void **handles)
+ 
+ 		mode = efi_table_attr(gop, mode);
+ 		info = efi_table_attr(mode, info);
+-		if (info->pixel_format == PIXEL_BLT_ONLY)
++		if (info->pixel_format == PIXEL_BLT_ONLY ||
++		    info->pixel_format >= PIXEL_FORMAT_MAX)
+ 			continue;
+ 
+ 		/*

commit 9867fc9de6a6a7a54edb2c43540c6db226e84a14
+Author: Arvind Sankar 
+Date:   Thu Mar 19 22:00:22 2020 -0400
+
+    efi/gop: Use helper macros for find_bits
+    
+    Use the __ffs/__fls macros to calculate the position and size of the
+    mask.
+    
+    Correct type of mask to u32 instead of unsigned long.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200320020028.1936003-9-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
+index 7b0baf9a912f..8bf424f35759 100644
+--- a/drivers/firmware/efi/libstub/gop.c
++++ b/drivers/firmware/efi/libstub/gop.c
+@@ -5,6 +5,7 @@
+  *
+  * ----------------------------------------------------------------------- */
+ 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -12,27 +13,16 @@
+ 
+ #include "efistub.h"
+ 
+-static void find_bits(unsigned long mask, u8 *pos, u8 *size)
++static void find_bits(u32 mask, u8 *pos, u8 *size)
+ {
+-	u8 first, len;
+-
+-	first = 0;
+-	len = 0;
+-
+-	if (mask) {
+-		while (!(mask & 0x1)) {
+-			mask = mask >> 1;
+-			first++;
+-		}
+-
+-		while (mask & 0x1) {
+-			mask = mask >> 1;
+-			len++;
+-		}
++	if (!mask) {
++		*pos = *size = 0;
++		return;
+ 	}
+ 
+-	*pos = first;
+-	*size = len;
++	/* UEFI spec guarantees that the set bits are contiguous */
++	*pos  = __ffs(mask);
++	*size = __fls(mask) - *pos + 1;
+ }
+ 
+ static void

commit f1d1853bdbcfb2d00ae0b850baf26d87e6d363d8
+Author: Arvind Sankar 
+Date:   Thu Mar 19 22:00:21 2020 -0400
+
+    efi/gop: Use helper macros for populating lfb_base
+    
+    Use the lower/upper_32_bits macros from kernel.h to initialize
+    si->lfb_base and si->ext_lfb_base.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200320020028.1936003-8-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
+index 0d195060a370..7b0baf9a912f 100644
+--- a/drivers/firmware/efi/libstub/gop.c
++++ b/drivers/firmware/efi/libstub/gop.c
+@@ -158,8 +158,8 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
+ 	si->lfb_height = info->vertical_resolution;
+ 
+ 	fb_base		 = efi_table_attr(mode, frame_buffer_base);
+-	si->lfb_base	 = fb_base;
+-	si->ext_lfb_base = (u64)(unsigned long)fb_base >> 32;
++	si->lfb_base	 = lower_32_bits(fb_base);
++	si->ext_lfb_base = upper_32_bits(fb_base);
+ 	if (si->ext_lfb_base)
+ 		si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE;
+ 

commit e484c594ba0e34686ad8780287961d09a3b4169b
+Author: Arvind Sankar 
+Date:   Thu Mar 19 22:00:20 2020 -0400
+
+    efi/gop: Move variable declarations into loop block
+    
+    Declare the variables inside the block where they're used.
+    
+    Get rid of a couple of redundant initializers.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200320020028.1936003-7-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
+index a7d3efe36c78..0d195060a370 100644
+--- a/drivers/firmware/efi/libstub/gop.c
++++ b/drivers/firmware/efi/libstub/gop.c
+@@ -88,16 +88,19 @@ setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line,
+ static efi_graphics_output_protocol_t *
+ find_gop(efi_guid_t *proto, unsigned long size, void **handles)
+ {
+-	efi_graphics_output_protocol_t *gop, *first_gop;
+-	efi_graphics_output_protocol_mode_t *mode;
+-	efi_graphics_output_mode_info_t *info = NULL;
+-	efi_status_t status;
++	efi_graphics_output_protocol_t *first_gop;
+ 	efi_handle_t h;
+ 	int i;
+ 
+ 	first_gop = NULL;
+ 
+ 	for_each_efi_handle(h, handles, size, i) {
++		efi_status_t status;
++
++		efi_graphics_output_protocol_t *gop;
++		efi_graphics_output_protocol_mode_t *mode;
++		efi_graphics_output_mode_info_t *info;
++
+ 		efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
+ 		void *dummy = NULL;
+ 
+@@ -136,7 +139,7 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
+ {
+ 	efi_graphics_output_protocol_t *gop;
+ 	efi_graphics_output_protocol_mode_t *mode;
+-	efi_graphics_output_mode_info_t *info = NULL;
++	efi_graphics_output_mode_info_t *info;
+ 	efi_physical_addr_t fb_base;
+ 
+ 	gop = find_gop(proto, size, handles);

commit 8e0a22e2b0531870e61110d12b1d37d6b5d24eed
+Author: Arvind Sankar 
+Date:   Thu Mar 19 22:00:19 2020 -0400
+
+    efi/gop: Slightly re-arrange logic of find_gop
+    
+    Small cleanup to get rid of conout_found.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200320020028.1936003-6-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
+index 92abcf558845..a7d3efe36c78 100644
+--- a/drivers/firmware/efi/libstub/gop.c
++++ b/drivers/firmware/efi/libstub/gop.c
+@@ -99,7 +99,6 @@ find_gop(efi_guid_t *proto, unsigned long size, void **handles)
+ 
+ 	for_each_efi_handle(h, handles, size, i) {
+ 		efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
+-		bool conout_found = false;
+ 		void *dummy = NULL;
+ 
+ 		status = efi_bs_call(handle_protocol, h, proto, (void **)&gop);
+@@ -111,25 +110,22 @@ find_gop(efi_guid_t *proto, unsigned long size, void **handles)
+ 		if (info->pixel_format == PIXEL_BLT_ONLY)
+ 			continue;
+ 
++		/*
++		 * Systems that use the UEFI Console Splitter may
++		 * provide multiple GOP devices, not all of which are
++		 * backed by real hardware. The workaround is to search
++		 * for a GOP implementing the ConOut protocol, and if
++		 * one isn't found, to just fall back to the first GOP.
++		 *
++		 * Once we've found a GOP supporting ConOut,
++		 * don't bother looking any further.
++		 */
+ 		status = efi_bs_call(handle_protocol, h, &conout_proto, &dummy);
+ 		if (status == EFI_SUCCESS)
+-			conout_found = true;
+-
+-		if (!first_gop || conout_found) {
+-			/*
+-			 * Systems that use the UEFI Console Splitter may
+-			 * provide multiple GOP devices, not all of which are
+-			 * backed by real hardware. The workaround is to search
+-			 * for a GOP implementing the ConOut protocol, and if
+-			 * one isn't found, to just fall back to the first GOP.
+-			 *
+-			 * Once we've found a GOP supporting ConOut,
+-			 * don't bother looking any further.
+-			 */
++			return gop;
++
++		if (!first_gop)
+ 			first_gop = gop;
+-			if (conout_found)
+-				break;
+-		}
+ 	}
+ 
+ 	return first_gop;

commit ecf53091f34af7172322ed40cfb5acf487329561
+Author: Arvind Sankar 
+Date:   Thu Mar 19 22:00:18 2020 -0400
+
+    efi/gop: Factor out locating the gop into a function
+    
+    Move the loop to find a gop into its own function.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200320020028.1936003-5-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
+index d692b8c65813..92abcf558845 100644
+--- a/drivers/firmware/efi/libstub/gop.c
++++ b/drivers/firmware/efi/libstub/gop.c
+@@ -85,19 +85,17 @@ setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line,
+ 	}
+ }
+ 
+-static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
+-			      unsigned long size, void **handles)
++static efi_graphics_output_protocol_t *
++find_gop(efi_guid_t *proto, unsigned long size, void **handles)
+ {
+ 	efi_graphics_output_protocol_t *gop, *first_gop;
+ 	efi_graphics_output_protocol_mode_t *mode;
+ 	efi_graphics_output_mode_info_t *info = NULL;
+-	efi_physical_addr_t fb_base;
+ 	efi_status_t status;
+ 	efi_handle_t h;
+ 	int i;
+ 
+ 	first_gop = NULL;
+-	gop = NULL;
+ 
+ 	for_each_efi_handle(h, handles, size, i) {
+ 		efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
+@@ -134,12 +132,25 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
+ 		}
+ 	}
+ 
++	return first_gop;
++}
++
++static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
++			      unsigned long size, void **handles)
++{
++	efi_graphics_output_protocol_t *gop;
++	efi_graphics_output_protocol_mode_t *mode;
++	efi_graphics_output_mode_info_t *info = NULL;
++	efi_physical_addr_t fb_base;
++
++	gop = find_gop(proto, size, handles);
++
+ 	/* Did we find any GOPs? */
+-	if (!first_gop)
++	if (!gop)
+ 		return EFI_NOT_FOUND;
+ 
+ 	/* EFI framebuffer */
+-	mode = efi_table_attr(first_gop, mode);
++	mode = efi_table_attr(gop, mode);
+ 	info = efi_table_attr(mode, info);
+ 
+ 	si->orig_video_isVGA = VIDEO_TYPE_EFI;

commit 6327e6d0e4a52688be621190381eea6a146bb777
+Author: Arvind Sankar 
+Date:   Thu Mar 19 22:00:17 2020 -0400
+
+    efi/gop: Get mode information outside the loop
+    
+    Move extraction of the mode information parameters outside the loop to
+    find the gop, and eliminate some redundant variables.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200320020028.1936003-4-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
+index 201b66970b2b..d692b8c65813 100644
+--- a/drivers/firmware/efi/libstub/gop.c
++++ b/drivers/firmware/efi/libstub/gop.c
+@@ -89,12 +89,9 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
+ 			      unsigned long size, void **handles)
+ {
+ 	efi_graphics_output_protocol_t *gop, *first_gop;
+-	u16 width, height;
+-	u32 pixels_per_scan_line;
+-	u32 ext_lfb_base;
++	efi_graphics_output_protocol_mode_t *mode;
++	efi_graphics_output_mode_info_t *info = NULL;
+ 	efi_physical_addr_t fb_base;
+-	efi_pixel_bitmask_t pixel_info;
+-	int pixel_format;
+ 	efi_status_t status;
+ 	efi_handle_t h;
+ 	int i;
+@@ -103,8 +100,6 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
+ 	gop = NULL;
+ 
+ 	for_each_efi_handle(h, handles, size, i) {
+-		efi_graphics_output_protocol_mode_t *mode;
+-		efi_graphics_output_mode_info_t *info = NULL;
+ 		efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
+ 		bool conout_found = false;
+ 		void *dummy = NULL;
+@@ -129,15 +124,7 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
+ 			 * backed by real hardware. The workaround is to search
+ 			 * for a GOP implementing the ConOut protocol, and if
+ 			 * one isn't found, to just fall back to the first GOP.
+-			 */
+-			width = info->horizontal_resolution;
+-			height = info->vertical_resolution;
+-			pixel_format = info->pixel_format;
+-			pixel_info = info->pixel_information;
+-			pixels_per_scan_line = info->pixels_per_scan_line;
+-			fb_base = efi_table_attr(mode, frame_buffer_base);
+-
+-			/*
++			 *
+ 			 * Once we've found a GOP supporting ConOut,
+ 			 * don't bother looking any further.
+ 			 */
+@@ -152,21 +139,24 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
+ 		return EFI_NOT_FOUND;
+ 
+ 	/* EFI framebuffer */
++	mode = efi_table_attr(first_gop, mode);
++	info = efi_table_attr(mode, info);
++
+ 	si->orig_video_isVGA = VIDEO_TYPE_EFI;
+ 
+-	si->lfb_width = width;
+-	si->lfb_height = height;
+-	si->lfb_base = fb_base;
++	si->lfb_width  = info->horizontal_resolution;
++	si->lfb_height = info->vertical_resolution;
+ 
+-	ext_lfb_base = (u64)(unsigned long)fb_base >> 32;
+-	if (ext_lfb_base) {
++	fb_base		 = efi_table_attr(mode, frame_buffer_base);
++	si->lfb_base	 = fb_base;
++	si->ext_lfb_base = (u64)(unsigned long)fb_base >> 32;
++	if (si->ext_lfb_base)
+ 		si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE;
+-		si->ext_lfb_base = ext_lfb_base;
+-	}
+ 
+ 	si->pages = 1;
+ 
+-	setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format);
++	setup_pixel_info(si, info->pixels_per_scan_line,
++			     info->pixel_information, info->pixel_format);
+ 
+ 	si->lfb_size = si->lfb_linelength * si->lfb_height;
+ 

commit 8cd207973c37175bf44727e28aa9c74fcf18de5e
+Author: Arvind Sankar 
+Date:   Thu Mar 19 22:00:16 2020 -0400
+
+    efi/gop: Move check for framebuffer before con_out
+    
+    If the gop doesn't have a framebuffer, there's no point in checking for
+    con_out support.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200320020028.1936003-3-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
+index f40d535dccb8..201b66970b2b 100644
+--- a/drivers/firmware/efi/libstub/gop.c
++++ b/drivers/firmware/efi/libstub/gop.c
+@@ -113,15 +113,16 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
+ 		if (status != EFI_SUCCESS)
+ 			continue;
+ 
++		mode = efi_table_attr(gop, mode);
++		info = efi_table_attr(mode, info);
++		if (info->pixel_format == PIXEL_BLT_ONLY)
++			continue;
++
+ 		status = efi_bs_call(handle_protocol, h, &conout_proto, &dummy);
+ 		if (status == EFI_SUCCESS)
+ 			conout_found = true;
+ 
+-		mode = efi_table_attr(gop, mode);
+-		info = efi_table_attr(mode, info);
+-
+-		if ((!first_gop || conout_found) &&
+-		    info->pixel_format != PIXEL_BLT_ONLY) {
++		if (!first_gop || conout_found) {
+ 			/*
+ 			 * Systems that use the UEFI Console Splitter may
+ 			 * provide multiple GOP devices, not all of which are

commit bd45870409a363eeb67e409645244ce38c7c2df3
+Author: Arvind Sankar 
+Date:   Thu Mar 19 22:00:15 2020 -0400
+
+    efi/gop: Remove redundant current_fb_base
+    
+    current_fb_base isn't used for anything except assigning to fb_base if
+    we locate a suitable gop.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200320020028.1936003-2-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
+index 55e6b3f286fe..f40d535dccb8 100644
+--- a/drivers/firmware/efi/libstub/gop.c
++++ b/drivers/firmware/efi/libstub/gop.c
+@@ -108,7 +108,6 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
+ 		efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
+ 		bool conout_found = false;
+ 		void *dummy = NULL;
+-		efi_physical_addr_t current_fb_base;
+ 
+ 		status = efi_bs_call(handle_protocol, h, proto, (void **)&gop);
+ 		if (status != EFI_SUCCESS)
+@@ -120,7 +119,6 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
+ 
+ 		mode = efi_table_attr(gop, mode);
+ 		info = efi_table_attr(mode, info);
+-		current_fb_base = efi_table_attr(mode, frame_buffer_base);
+ 
+ 		if ((!first_gop || conout_found) &&
+ 		    info->pixel_format != PIXEL_BLT_ONLY) {
+@@ -136,7 +134,7 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
+ 			pixel_format = info->pixel_format;
+ 			pixel_info = info->pixel_information;
+ 			pixels_per_scan_line = info->pixels_per_scan_line;
+-			fb_base = current_fb_base;
++			fb_base = efi_table_attr(mode, frame_buffer_base);
+ 
+ 			/*
+ 			 * Once we've found a GOP supporting ConOut,

commit 21cb9b414301c76f77f70d990a784ad6360e5a20
+Author: Arvind Sankar 
+Date:   Thu Apr 9 15:04:29 2020 +0200
+
+    efi/x86: Always relocate the kernel for EFI handover entry
+    
+    Commit
+    
+      d5cdf4cfeac9 ("efi/x86: Don't relocate the kernel unless necessary")
+    
+    tries to avoid relocating the kernel in the EFI stub as far as possible.
+    
+    However, when systemd-boot is used to boot a unified kernel image [1],
+    the image is constructed by embedding the bzImage as a .linux section in
+    a PE executable that contains a small stub loader from systemd that will
+    call the EFI stub handover entry, together with additional sections and
+    potentially an initrd. When this image is constructed, by for example
+    dracut, the initrd is placed after the bzImage without ensuring that at
+    least init_size bytes are available for the bzImage. If the kernel is
+    not relocated by the EFI stub, this could result in the compressed
+    kernel's startup code in head_{32,64}.S overwriting the initrd.
+    
+    To prevent this, unconditionally relocate the kernel if the EFI stub was
+    entered via the handover entry point.
+    
+    [1] https://systemd.io/BOOT_LOADER_SPECIFICATION/#type-2-efi-unified-kernel-images
+    
+    Fixes: d5cdf4cfeac9 ("efi/x86: Don't relocate the kernel unless necessary")
+    Reported-by: Sergey Shatunov 
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200406180614.429454-2-nivedita@alum.mit.edu
+    Link: https://lore.kernel.org/r/20200409130434.6736-5-ardb@kernel.org
+
+diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
+index 867a57e28980..05ccb229fb45 100644
+--- a/drivers/firmware/efi/libstub/x86-stub.c
++++ b/drivers/firmware/efi/libstub/x86-stub.c
+@@ -740,8 +740,15 @@ unsigned long efi_main(efi_handle_t handle,
+ 	 * now use KERNEL_IMAGE_SIZE, which will be 512MiB, the same as what
+ 	 * KASLR uses.
+ 	 *
+-	 * Also relocate it if image_offset is zero, i.e. we weren't loaded by
+-	 * LoadImage, but we are not aligned correctly.
++	 * Also relocate it if image_offset is zero, i.e. the kernel wasn't
++	 * loaded by LoadImage, but rather by a bootloader that called the
++	 * handover entry. The reason we must always relocate in this case is
++	 * to handle the case of systemd-boot booting a unified kernel image,
++	 * which is a PE executable that contains the bzImage and an initrd as
++	 * COFF sections. The initrd section is placed after the bzImage
++	 * without ensuring that there are at least init_size bytes available
++	 * for the bzImage, and thus the compressed kernel's startup code may
++	 * overwrite the initrd unless it is moved out of the way.
+ 	 */
+ 
+ 	buffer_start = ALIGN(bzimage_addr - image_offset,
+@@ -751,8 +758,7 @@ unsigned long efi_main(efi_handle_t handle,
+ 	if ((buffer_start < LOAD_PHYSICAL_ADDR)				     ||
+ 	    (IS_ENABLED(CONFIG_X86_32) && buffer_end > KERNEL_IMAGE_SIZE)    ||
+ 	    (IS_ENABLED(CONFIG_X86_64) && buffer_end > MAXMEM_X86_64_4LEVEL) ||
+-	    (image_offset == 0 && !IS_ALIGNED(bzimage_addr,
+-					      hdr->kernel_alignment))) {
++	    (image_offset == 0)) {
+ 		status = efi_relocate_kernel(&bzimage_addr,
+ 					     hdr->init_size, hdr->init_size,
+ 					     hdr->pref_address,

commit 105cb9544b161819b7be23a8a8419353a3218807
+Author: Arvind Sankar 
+Date:   Thu Apr 9 15:04:28 2020 +0200
+
+    efi/x86: Move efi stub globals from .bss to .data
+    
+    Commit
+    
+      3ee372ccce4d ("x86/boot/compressed/64: Remove .bss/.pgtable from bzImage")
+    
+    removed the .bss section from the bzImage.
+    
+    However, while a PE loader is required to zero-initialize the .bss
+    section before calling the PE entry point, the EFI handover protocol
+    does not currently document any requirement that .bss be initialized by
+    the bootloader prior to calling the handover entry.
+    
+    When systemd-boot is used to boot a unified kernel image [1], the image
+    is constructed by embedding the bzImage as a .linux section in a PE
+    executable that contains a small stub loader from systemd together with
+    additional sections and potentially an initrd. As the .bss section
+    within the bzImage is no longer explicitly present as part of the file,
+    it is not initialized before calling the EFI handover entry.
+    Furthermore, as the size of the embedded .linux section is only the size
+    of the bzImage file itself, the .bss section's memory may not even have
+    been allocated.
+    
+    In particular, this can result in efi_disable_pci_dma being true even
+    when it was not specified via the command line or configuration option,
+    which in turn causes crashes while booting on some systems.
+    
+    To avoid issues, place all EFI stub global variables into the .data
+    section instead of .bss. As of this writing, only boolean flags for a
+    few command line arguments and the sys_table pointer were in .bss and
+    will now move into the .data section.
+    
+    [1] https://systemd.io/BOOT_LOADER_SPECIFICATION/#type-2-efi-unified-kernel-images
+    
+    Fixes: 3ee372ccce4d ("x86/boot/compressed/64: Remove .bss/.pgtable from bzImage")
+    Reported-by: Sergey Shatunov 
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200406180614.429454-1-nivedita@alum.mit.edu
+    Link: https://lore.kernel.org/r/20200409130434.6736-4-ardb@kernel.org
+
+diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
+index cc90a748bcf0..67d26949fd26 100644
+--- a/drivers/firmware/efi/libstub/efistub.h
++++ b/drivers/firmware/efi/libstub/efistub.h
+@@ -25,7 +25,7 @@
+ #define EFI_ALLOC_ALIGN		EFI_PAGE_SIZE
+ #endif
+ 
+-#ifdef CONFIG_ARM
++#if defined(CONFIG_ARM) || defined(CONFIG_X86)
+ #define __efistub_global	__section(.data)
+ #else
+ #define __efistub_global
+diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
+index e02ea51273ff..867a57e28980 100644
+--- a/drivers/firmware/efi/libstub/x86-stub.c
++++ b/drivers/firmware/efi/libstub/x86-stub.c
+@@ -20,7 +20,7 @@
+ /* Maximum physical address for 64-bit kernel with 4-level paging */
+ #define MAXMEM_X86_64_4LEVEL (1ull << 46)
+ 
+-static efi_system_table_t *sys_table;
++static efi_system_table_t *sys_table __efistub_global;
+ extern const bool efi_is64;
+ extern u32 image_offset;
+ 

commit c479017faa3a9f6c60ea18ffe44e20b33487e10e
+Author: Ilia Mirkin 
+Date:   Wed Mar 11 23:51:54 2020 -0400
+
+    drm/msm: avoid double-attaching hdmi/edp bridges
+    
+    Each of hdmi and edp are already attached in msm_*_bridge_init. A second
+    attachment returns -EBUSY, failing the driver load.
+    
+    Tested with HDMI on IFC6410 (APQ8064 / MDP4), but eDP case should be
+    analogous.
+    
+    Fixes: 3ef2f119bd3ed (drm/msm: Use drm_attach_bridge() to attach a bridge to an encoder)
+    Cc: Boris Brezillon 
+    Signed-off-by: Ilia Mirkin 
+    Reviewed-by: Rob Clark 
+    Reviewed-by: Boris Brezillon 
+    Tested-by: Bjorn Andersson  (hdmi part)
+    Reviewed-by: Bjorn Andersson 
+    Signed-off-by: Rob Clark 
+
+diff --git a/drivers/gpu/drm/msm/edp/edp.c b/drivers/gpu/drm/msm/edp/edp.c
+index ad4e963ccd9b..106a67473af5 100644
+--- a/drivers/gpu/drm/msm/edp/edp.c
++++ b/drivers/gpu/drm/msm/edp/edp.c
+@@ -178,10 +178,6 @@ int msm_edp_modeset_init(struct msm_edp *edp, struct drm_device *dev,
+ 		goto fail;
+ 	}
+ 
+-	ret = drm_bridge_attach(encoder, edp->bridge, NULL);
+-	if (ret)
+-		goto fail;
+-
+ 	priv->bridges[priv->num_bridges++]       = edp->bridge;
+ 	priv->connectors[priv->num_connectors++] = edp->connector;
+ 
+diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
+index 1a9b6289637d..737453b6e596 100644
+--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
++++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
+@@ -327,10 +327,6 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
+ 		goto fail;
+ 	}
+ 
+-	ret = drm_bridge_attach(encoder, hdmi->bridge, NULL);
+-	if (ret)
+-		goto fail;
+-
+ 	priv->bridges[priv->num_bridges++]       = hdmi->bridge;
+ 	priv->connectors[priv->num_connectors++] = hdmi->connector;
+ 

commit 1babf557bf6e6ab92d5ebea642b9f636c77a4912
+Author: Arvind Sankar 
+Date:   Thu Mar 5 10:05:03 2020 -0500
+
+    microblaze: Stop printing the virtual memory layout
+    
+    For security, don't display the kernel's virtual memory layout.
+    
+    Kees Cook points out:
+    "These have been entirely removed on other architectures, so let's
+    just do the same for ia32 and remove it unconditionally."
+    
+    071929dbdd86 ("arm64: Stop printing the virtual memory layout")
+    1c31d4e96b8c ("ARM: 8820/1: mm: Stop printing the virtual memory layout")
+    31833332f798 ("m68k/mm: Stop printing the virtual memory layout")
+    fd8d0ca25631 ("parisc: Hide virtual kernel memory layout")
+    adb1fe9ae2ee ("mm/page_alloc: Remove kernel address exposure in free_reserved_area()")
+    
+    Signed-off-by: Arvind Sankar 
+    Acked-by: Tycho Andersen 
+    Signed-off-by: Michal Simek 
+
+diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c
+index 9899ff2ef9b6..1ffbfa96b9b8 100644
+--- a/arch/microblaze/mm/init.c
++++ b/arch/microblaze/mm/init.c
+@@ -201,18 +201,6 @@ void __init mem_init(void)
+ #endif
+ 
+ 	mem_init_print_info(NULL);
+-#ifdef CONFIG_MMU
+-	pr_info("Kernel virtual memory layout:\n");
+-	pr_info("  * 0x%08lx..0x%08lx  : fixmap\n", FIXADDR_START, FIXADDR_TOP);
+-#ifdef CONFIG_HIGHMEM
+-	pr_info("  * 0x%08lx..0x%08lx  : highmem PTEs\n",
+-		PKMAP_BASE, PKMAP_ADDR(LAST_PKMAP));
+-#endif /* CONFIG_HIGHMEM */
+-	pr_info("  * 0x%08lx..0x%08lx  : early ioremap\n",
+-		ioremap_bot, ioremap_base);
+-	pr_info("  * 0x%08lx..0x%08lx  : vmalloc & ioremap\n",
+-		(unsigned long)VMALLOC_START, VMALLOC_END);
+-#endif
+ 	mem_init_done = 1;
+ }
+ 

commit 0347d8c28cbbfd92527bad05931a458dbd62dc79
+Author: Arvind Sankar 
+Date:   Sun Mar 8 09:08:58 2020 +0100
+
+    efi/x86: Fix cast of image argument
+    
+    handle_protocol() expects void **, not void *.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200305143642.820865-1-nivedita@alum.mit.edu
+    Link: https://lore.kernel.org/r/20200308080859.21568-28-ardb@kernel.org
+
+diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
+index 383f59d44fbe..8d3a707789de 100644
+--- a/drivers/firmware/efi/libstub/x86-stub.c
++++ b/drivers/firmware/efi/libstub/x86-stub.c
+@@ -383,7 +383,7 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
+ 	if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
+ 		efi_exit(handle, EFI_INVALID_PARAMETER);
+ 
+-	status = efi_bs_call(handle_protocol, handle, &proto, (void *)&image);
++	status = efi_bs_call(handle_protocol, handle, &proto, (void **)&image);
+ 	if (status != EFI_SUCCESS) {
+ 		efi_printk("Failed to get handle for LOADED_IMAGE_PROTOCOL\n");
+ 		efi_exit(handle, status);

commit d5cdf4cfeac914617ca22866bd4685fd7f876dec
+Author: Arvind Sankar 
+Date:   Sun Mar 8 09:08:50 2020 +0100
+
+    efi/x86: Don't relocate the kernel unless necessary
+    
+    Add alignment slack to the PE image size, so that we can realign the
+    decompression buffer within the space allocated for the image.
+    
+    Only relocate the kernel if it has been loaded at an unsuitable address:
+    
+     - Below LOAD_PHYSICAL_ADDR, or
+     - Above 64T for 64-bit and 512MiB for 32-bit
+    
+    For 32-bit, the upper limit is conservative, but the exact limit can be
+    difficult to calculate.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200303221205.4048668-6-nivedita@alum.mit.edu
+    Link: https://lore.kernel.org/r/20200308080859.21568-20-ardb@kernel.org
+
+diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c
+index 8cac5b6103db..8f8c8e386cea 100644
+--- a/arch/x86/boot/tools/build.c
++++ b/arch/x86/boot/tools/build.c
+@@ -238,21 +238,17 @@ static void update_pecoff_text(unsigned int text_start, unsigned int file_sz,
+ 
+ 	pe_header = get_unaligned_le32(&buf[0x3c]);
+ 
+-#ifdef CONFIG_EFI_MIXED
+ 	/*
+-	 * In mixed mode, we will execute startup_32() at whichever offset in
+-	 * memory it happened to land when the PE/COFF loader loaded the image,
+-	 * which may be misaligned with respect to the kernel_alignment field
+-	 * in the setup header.
++	 * The PE/COFF loader may load the image at an address which is
++	 * misaligned with respect to the kernel_alignment field in the setup
++	 * header.
+ 	 *
+-	 * In order for startup_32 to safely execute in place at this offset,
+-	 * we need to ensure that the CONFIG_PHYSICAL_ALIGN aligned allocation
+-	 * it creates for the page tables does not extend beyond the declared
+-	 * size of the image in the PE/COFF header. So add the required slack.
++	 * In order to avoid relocating the kernel to correct the misalignment,
++	 * add slack to allow the buffer to be aligned within the declared size
++	 * of the image.
+ 	 */
+ 	bss_sz	+= CONFIG_PHYSICAL_ALIGN;
+ 	init_sz	+= CONFIG_PHYSICAL_ALIGN;
+-#endif
+ 
+ 	/*
+ 	 * Size of code: Subtract the size of the first sector (512 bytes)
+diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
+index 3e1bc8a370be..4615d29dd665 100644
+--- a/drivers/firmware/efi/libstub/x86-stub.c
++++ b/drivers/firmware/efi/libstub/x86-stub.c
+@@ -17,6 +17,9 @@
+ 
+ #include "efistub.h"
+ 
++/* Maximum physical address for 64-bit kernel with 4-level paging */
++#define MAXMEM_X86_64_4LEVEL (1ull << 46)
++
+ static efi_system_table_t *sys_table;
+ extern const bool efi_is64;
+ extern u32 image_offset;
+@@ -718,6 +721,7 @@ unsigned long efi_main(efi_handle_t handle,
+ 			     struct boot_params *boot_params)
+ {
+ 	unsigned long bzimage_addr = (unsigned long)startup_32;
++	unsigned long buffer_start, buffer_end;
+ 	struct setup_header *hdr = &boot_params->hdr;
+ 	efi_status_t status;
+ 	unsigned long cmdline_paddr;
+@@ -729,10 +733,33 @@ unsigned long efi_main(efi_handle_t handle,
+ 		efi_exit(handle, EFI_INVALID_PARAMETER);
+ 
+ 	/*
+-	 * If the kernel isn't already loaded at the preferred load
+-	 * address, relocate it.
++	 * If the kernel isn't already loaded at a suitable address,
++	 * relocate it.
++	 *
++	 * It must be loaded above LOAD_PHYSICAL_ADDR.
++	 *
++	 * The maximum address for 64-bit is 1 << 46 for 4-level paging. This
++	 * is defined as the macro MAXMEM, but unfortunately that is not a
++	 * compile-time constant if 5-level paging is configured, so we instead
++	 * define our own macro for use here.
++	 *
++	 * For 32-bit, the maximum address is complicated to figure out, for
++	 * now use KERNEL_IMAGE_SIZE, which will be 512MiB, the same as what
++	 * KASLR uses.
++	 *
++	 * Also relocate it if image_offset is zero, i.e. we weren't loaded by
++	 * LoadImage, but we are not aligned correctly.
+ 	 */
+-	if (bzimage_addr - image_offset != hdr->pref_address) {
++
++	buffer_start = ALIGN(bzimage_addr - image_offset,
++			     hdr->kernel_alignment);
++	buffer_end = buffer_start + hdr->init_size;
++
++	if ((buffer_start < LOAD_PHYSICAL_ADDR)				     ||
++	    (IS_ENABLED(CONFIG_X86_32) && buffer_end > KERNEL_IMAGE_SIZE)    ||
++	    (IS_ENABLED(CONFIG_X86_64) && buffer_end > MAXMEM_X86_64_4LEVEL) ||
++	    (image_offset == 0 && !IS_ALIGNED(bzimage_addr,
++					      hdr->kernel_alignment))) {
+ 		status = efi_relocate_kernel(&bzimage_addr,
+ 					     hdr->init_size, hdr->init_size,
+ 					     hdr->pref_address,

commit 964124a97b973555c475423fca0fceafdde01a17
+Author: Arvind Sankar 
+Date:   Sun Mar 8 09:08:49 2020 +0100
+
+    efi/x86: Remove extra headroom for setup block
+    
+    The following commit:
+    
+      223e3ee56f77 ("efi/x86: add headroom to decompressor BSS to account for setup block")
+    
+    added headroom to the PE image to account for the setup block, which
+    wasn't used for the decompression buffer.
+    
+    Now that the decompression buffer is located at the start of the image,
+    and includes the setup block, this is no longer required.
+    
+    Add a check to make sure that the head section of the compressed kernel
+    won't overwrite itself while relocating. This is only for
+    future-proofing as with current limits on the setup and the actual size
+    of the head section, this can never happen.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200303221205.4048668-5-nivedita@alum.mit.edu
+    Link: https://lore.kernel.org/r/20200308080859.21568-19-ardb@kernel.org
+
+diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c
+index 90d403dfec80..8cac5b6103db 100644
+--- a/arch/x86/boot/tools/build.c
++++ b/arch/x86/boot/tools/build.c
+@@ -65,6 +65,8 @@ unsigned long efi_pe_entry;
+ unsigned long efi32_pe_entry;
+ unsigned long kernel_info;
+ unsigned long startup_64;
++unsigned long _ehead;
++unsigned long _end;
+ 
+ /*----------------------------------------------------------------------*/
+ 
+@@ -232,7 +234,7 @@ static void update_pecoff_text(unsigned int text_start, unsigned int file_sz,
+ {
+ 	unsigned int pe_header;
+ 	unsigned int text_sz = file_sz - text_start;
+-	unsigned int bss_sz = init_sz + text_start - file_sz;
++	unsigned int bss_sz = init_sz - file_sz;
+ 
+ 	pe_header = get_unaligned_le32(&buf[0x3c]);
+ 
+@@ -259,7 +261,7 @@ static void update_pecoff_text(unsigned int text_start, unsigned int file_sz,
+ 	put_unaligned_le32(file_sz - 512 + bss_sz, &buf[pe_header + 0x1c]);
+ 
+ 	/* Size of image */
+-	put_unaligned_le32(init_sz + text_start, &buf[pe_header + 0x50]);
++	put_unaligned_le32(init_sz, &buf[pe_header + 0x50]);
+ 
+ 	/*
+ 	 * Address of entry point for PE/COFF executable
+@@ -360,6 +362,8 @@ static void parse_zoffset(char *fname)
+ 		PARSE_ZOFS(p, efi32_pe_entry);
+ 		PARSE_ZOFS(p, kernel_info);
+ 		PARSE_ZOFS(p, startup_64);
++		PARSE_ZOFS(p, _ehead);
++		PARSE_ZOFS(p, _end);
+ 
+ 		p = strchr(p, '\n');
+ 		while (p && (*p == '\r' || *p == '\n'))
+@@ -444,6 +448,26 @@ int main(int argc, char ** argv)
+ 	put_unaligned_le32(sys_size, &buf[0x1f4]);
+ 
+ 	init_sz = get_unaligned_le32(&buf[0x260]);
++#ifdef CONFIG_EFI_STUB
++	/*
++	 * The decompression buffer will start at ImageBase. When relocating
++	 * the compressed kernel to its end, we must ensure that the head
++	 * section does not get overwritten.  The head section occupies
++	 * [i, i + _ehead), and the destination is [init_sz - _end, init_sz).
++	 *
++	 * At present these should never overlap, because 'i' is at most 32k
++	 * because of SETUP_SECT_MAX, '_ehead' is less than 1k, and the
++	 * calculation of INIT_SIZE in boot/header.S ensures that
++	 * 'init_sz - _end' is at least 64k.
++	 *
++	 * For future-proofing, increase init_sz if necessary.
++	 */
++
++	if (init_sz - _end < i + _ehead) {
++		init_sz = (i + _ehead + _end + 4095) & ~4095;
++		put_unaligned_le32(init_sz, &buf[0x260]);
++	}
++#endif
+ 	update_pecoff_text(setup_sectors * 512, i + (sys_size * 16), init_sz);
+ 
+ 	efi_stub_entry_update();

commit 26725192c46e1e543ed86a06823fa591cd6faf58
+Author: Arvind Sankar 
+Date:   Sun Mar 8 09:08:48 2020 +0100
+
+    efi/x86: Add kernel preferred address to PE header
+    
+    Store the kernel's link address as ImageBase in the PE header. Note that
+    the PE specification requires the ImageBase to be 64k aligned. The
+    preferred address should almost always satisfy that, except for 32-bit
+    kernel if the configuration has been customized.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200303221205.4048668-4-nivedita@alum.mit.edu
+    Link: https://lore.kernel.org/r/20200308080859.21568-18-ardb@kernel.org
+
+diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
+index 4ee25e28996f..735ad7f21ab0 100644
+--- a/arch/x86/boot/header.S
++++ b/arch/x86/boot/header.S
+@@ -138,10 +138,12 @@ optional_header:
+ #endif
+ 
+ extra_header_fields:
++	# PE specification requires ImageBase to be 64k aligned
++	.set	image_base, (LOAD_PHYSICAL_ADDR + 0xffff) & ~0xffff
+ #ifdef CONFIG_X86_32
+-	.long	0				# ImageBase
++	.long	image_base			# ImageBase
+ #else
+-	.quad	0				# ImageBase
++	.quad	image_base			# ImageBase
+ #endif
+ 	.long	0x20				# SectionAlignment
+ 	.long	0x20				# FileAlignment

commit 1887c9b653f99577c0f8ec413b0921a32b6129e2
+Author: Arvind Sankar 
+Date:   Sun Mar 8 09:08:47 2020 +0100
+
+    efi/x86: Decompress at start of PE image load address
+    
+    When booted via PE loader, define image_offset to hold the offset of
+    startup_32() from the start of the PE image, and use it as the start of
+    the decompression buffer.
+    
+    [ mingo: Fixed the grammar in the comments. ]
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200303221205.4048668-3-nivedita@alum.mit.edu
+    Link: https://lore.kernel.org/r/20200308080859.21568-17-ardb@kernel.org
+
+diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
+index 894182500606..ab3307036ba4 100644
+--- a/arch/x86/boot/compressed/head_32.S
++++ b/arch/x86/boot/compressed/head_32.S
+@@ -100,6 +100,19 @@ SYM_FUNC_START(startup_32)
+ 
+ #ifdef CONFIG_RELOCATABLE
+ 	movl	%edx, %ebx
++
++#ifdef CONFIG_EFI_STUB
++/*
++ * If we were loaded via the EFI LoadImage service, startup_32() will be at an
++ * offset to the start of the space allocated for the image. efi_pe_entry() will
++ * set up image_offset to tell us where the image actually starts, so that we
++ * can use the full available buffer.
++ *	image_offset = startup_32 - image_base
++ * Otherwise image_offset will be zero and has no effect on the calculations.
++ */
++	subl    image_offset(%edx), %ebx
++#endif
++
+ 	movl	BP_kernel_alignment(%esi), %eax
+ 	decl	%eax
+ 	addl    %eax, %ebx
+@@ -226,6 +239,10 @@ SYM_DATA_START_LOCAL(gdt)
+ 	.quad	0x00cf92000000ffff	/* __KERNEL_DS */
+ SYM_DATA_END_LABEL(gdt, SYM_L_LOCAL, gdt_end)
+ 
++#ifdef CONFIG_EFI_STUB
++SYM_DATA(image_offset, .long 0)
++#endif
++
+ /*
+  * Stack and heap for uncompression
+  */
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index 5d8338a693ce..d4657d38e884 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -99,6 +99,19 @@ SYM_FUNC_START(startup_32)
+ 
+ #ifdef CONFIG_RELOCATABLE
+ 	movl	%ebp, %ebx
++
++#ifdef CONFIG_EFI_STUB
++/*
++ * If we were loaded via the EFI LoadImage service, startup_32 will be at an
++ * offset to the start of the space allocated for the image. efi_pe_entry will
++ * set up image_offset to tell us where the image actually starts, so that we
++ * can use the full available buffer.
++ *	image_offset = startup_32 - image_base
++ * Otherwise image_offset will be zero and has no effect on the calculations.
++ */
++	subl    image_offset(%ebp), %ebx
++#endif
++
+ 	movl	BP_kernel_alignment(%esi), %eax
+ 	decl	%eax
+ 	addl	%eax, %ebx
+@@ -111,9 +124,8 @@ SYM_FUNC_START(startup_32)
+ 1:
+ 
+ 	/* Target address to relocate to for decompression */
+-	movl	BP_init_size(%esi), %eax
+-	subl	$_end, %eax
+-	addl	%eax, %ebx
++	addl	BP_init_size(%esi), %ebx
++	subl	$_end, %ebx
+ 
+ /*
+  * Prepare for entering 64 bit mode
+@@ -299,6 +311,20 @@ SYM_CODE_START(startup_64)
+ 	/* Start with the delta to where the kernel will run at. */
+ #ifdef CONFIG_RELOCATABLE
+ 	leaq	startup_32(%rip) /* - $startup_32 */, %rbp
++
++#ifdef CONFIG_EFI_STUB
++/*
++ * If we were loaded via the EFI LoadImage service, startup_32 will be at an
++ * offset to the start of the space allocated for the image. efi_pe_entry will
++ * set up image_offset to tell us where the image actually starts, so that we
++ * can use the full available buffer.
++ *	image_offset = startup_32 - image_base
++ * Otherwise image_offset will be zero and has no effect on the calculations.
++ */
++	movl    image_offset(%rip), %eax
++	subq	%rax, %rbp
++#endif
++
+ 	movl	BP_kernel_alignment(%rsi), %eax
+ 	decl	%eax
+ 	addq	%rax, %rbp
+@@ -647,6 +673,10 @@ SYM_DATA_START_LOCAL(gdt)
+ 	.quad   0x0000000000000000	/* TS continued */
+ SYM_DATA_END_LABEL(gdt, SYM_L_LOCAL, gdt_end)
+ 
++#ifdef CONFIG_EFI_STUB
++SYM_DATA(image_offset, .long 0)
++#endif
++
+ #ifdef CONFIG_EFI_MIXED
+ SYM_DATA_LOCAL(efi32_boot_args, .long 0, 0, 0)
+ SYM_DATA(efi_is64, .byte 1)
+@@ -712,6 +742,12 @@ SYM_FUNC_START(efi32_pe_entry)
+ 	movl	-4(%ebp), %esi			// loaded_image
+ 	movl	LI32_image_base(%esi), %esi	// loaded_image->image_base
+ 	movl	%ebx, %ebp			// startup_32 for efi32_pe_stub_entry
++	/*
++	 * We need to set the image_offset variable here since startup_32() will
++	 * use it before we get to the 64-bit efi_pe_entry() in C code.
++	 */
++	subl	%esi, %ebx
++	movl	%ebx, image_offset(%ebp)	// save image_offset
+ 	jmp	efi32_pe_stub_entry
+ 
+ 2:	popl	%edi				// restore callee-save registers
+diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
+index 69a942f0640b..3e1bc8a370be 100644
+--- a/drivers/firmware/efi/libstub/x86-stub.c
++++ b/drivers/firmware/efi/libstub/x86-stub.c
+@@ -19,6 +19,7 @@
+ 
+ static efi_system_table_t *sys_table;
+ extern const bool efi_is64;
++extern u32 image_offset;
+ 
+ __pure efi_system_table_t *efi_system_table(void)
+ {
+@@ -365,6 +366,7 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
+ 	struct boot_params *boot_params;
+ 	struct setup_header *hdr;
+ 	efi_loaded_image_t *image;
++	void *image_base;
+ 	efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID;
+ 	int options_size = 0;
+ 	efi_status_t status;
+@@ -385,7 +387,10 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
+ 		efi_exit(handle, status);
+ 	}
+ 
+-	hdr = &((struct boot_params *)efi_table_attr(image, image_base))->hdr;
++	image_base = efi_table_attr(image, image_base);
++	image_offset = (void *)startup_32 - image_base;
++
++	hdr = &((struct boot_params *)image_base)->hdr;
+ 	above4g = hdr->xloadflags & XLF_CAN_BE_LOADED_ABOVE_4G;
+ 
+ 	status = efi_allocate_pages(0x4000, (unsigned long *)&boot_params,
+@@ -400,7 +405,7 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
+ 	hdr = &boot_params->hdr;
+ 
+ 	/* Copy the second sector to boot_params */
+-	memcpy(&hdr->jump, efi_table_attr(image, image_base) + 512, 512);
++	memcpy(&hdr->jump, image_base + 512, 512);
+ 
+ 	/*
+ 	 * Fill out some of the header fields ourselves because the
+@@ -727,7 +732,7 @@ unsigned long efi_main(efi_handle_t handle,
+ 	 * If the kernel isn't already loaded at the preferred load
+ 	 * address, relocate it.
+ 	 */
+-	if (bzimage_addr != hdr->pref_address) {
++	if (bzimage_addr - image_offset != hdr->pref_address) {
+ 		status = efi_relocate_kernel(&bzimage_addr,
+ 					     hdr->init_size, hdr->init_size,
+ 					     hdr->pref_address,
+@@ -737,6 +742,12 @@ unsigned long efi_main(efi_handle_t handle,
+ 			efi_printk("efi_relocate_kernel() failed!\n");
+ 			goto fail;
+ 		}
++		/*
++		 * Now that we've copied the kernel elsewhere, we no longer
++		 * have a set up block before startup_32(), so reset image_offset
++		 * to zero in case it was set earlier.
++		 */
++		image_offset = 0;
+ 	}
+ 
+ 	/*

commit 8ef44be393113dca5cece65bc142ebb8ef013af0
+Author: Arvind Sankar 
+Date:   Sun Mar 8 09:08:46 2020 +0100
+
+    x86/boot/compressed/32: Save the output address instead of recalculating it
+    
+    In preparation for being able to decompress into a buffer starting at a
+    different address than startup_32, save the calculated output address
+    instead of recalculating it later.
+    
+    We now keep track of three addresses:
+    
+            %edx: startup_32 as we were loaded by bootloader
+            %ebx: new location of compressed kernel
+            %ebp: start of decompression buffer
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200303221205.4048668-2-nivedita@alum.mit.edu
+    Link: https://lore.kernel.org/r/20200308080859.21568-16-ardb@kernel.org
+
+diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
+index 46bbe7ab4adf..894182500606 100644
+--- a/arch/x86/boot/compressed/head_32.S
++++ b/arch/x86/boot/compressed/head_32.S
+@@ -75,11 +75,11 @@ SYM_FUNC_START(startup_32)
+  */
+ 	leal	(BP_scratch+4)(%esi), %esp
+ 	call	1f
+-1:	popl	%ebp
+-	subl	$1b, %ebp
++1:	popl	%edx
++	subl	$1b, %edx
+ 
+ 	/* Load new GDT */
+-	leal	gdt(%ebp), %eax
++	leal	gdt(%edx), %eax
+ 	movl	%eax, 2(%eax)
+ 	lgdt	(%eax)
+ 
+@@ -92,13 +92,14 @@ SYM_FUNC_START(startup_32)
+ 	movl	%eax, %ss
+ 
+ /*
+- * %ebp contains the address we are loaded at by the boot loader and %ebx
++ * %edx contains the address we are loaded at by the boot loader and %ebx
+  * contains the address where we should move the kernel image temporarily
+- * for safe in-place decompression.
++ * for safe in-place decompression. %ebp contains the address that the kernel
++ * will be decompressed to.
+  */
+ 
+ #ifdef CONFIG_RELOCATABLE
+-	movl	%ebp, %ebx
++	movl	%edx, %ebx
+ 	movl	BP_kernel_alignment(%esi), %eax
+ 	decl	%eax
+ 	addl    %eax, %ebx
+@@ -110,10 +111,10 @@ SYM_FUNC_START(startup_32)
+ 	movl	$LOAD_PHYSICAL_ADDR, %ebx
+ 1:
+ 
++	movl	%ebx, %ebp	// Save the output address for later
+ 	/* Target address to relocate to for decompression */
+-	movl    BP_init_size(%esi), %eax
+-	subl    $_end, %eax
+-	addl    %eax, %ebx
++	addl    BP_init_size(%esi), %ebx
++	subl    $_end, %ebx
+ 
+ 	/* Set up the stack */
+ 	leal	boot_stack_end(%ebx), %esp
+@@ -127,7 +128,7 @@ SYM_FUNC_START(startup_32)
+  * where decompression in place becomes safe.
+  */
+ 	pushl	%esi
+-	leal	(_bss-4)(%ebp), %esi
++	leal	(_bss-4)(%edx), %esi
+ 	leal	(_bss-4)(%ebx), %edi
+ 	movl	$(_bss - startup_32), %ecx
+ 	shrl	$2, %ecx
+@@ -196,9 +197,7 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
+ 				/* push arguments for extract_kernel: */
+ 	pushl	$z_output_len	/* decompressed length, end of relocs */
+ 
+-	leal	_end(%ebx), %eax
+-	subl    BP_init_size(%esi), %eax
+-	pushl	%eax		/* output address */
++	pushl	%ebp		/* output address */
+ 
+ 	pushl	$z_input_len	/* input_len */
+ 	leal	input_data(%ebx), %eax

commit 81a34892c2c7c809f9c4e22c5ac936ae673fb9a2
+Author: Arvind Sankar 
+Date:   Sun Mar 8 09:08:44 2020 +0100
+
+    x86/boot: Use unsigned comparison for addresses
+    
+    The load address is compared with LOAD_PHYSICAL_ADDR using a signed
+    comparison currently (using jge instruction).
+    
+    When loading a 64-bit kernel using the new efi32_pe_entry() point added by:
+    
+      97aa276579b2 ("efi/x86: Add true mixed mode entry point into .compat section")
+    
+    using Qemu with -m 3072, the firmware actually loads us above 2Gb,
+    resulting in a very early crash.
+    
+    Use the JAE instruction to perform a unsigned comparison instead, as physical
+    addresses should be considered unsigned.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200301230436.2246909-6-nivedita@alum.mit.edu
+    Link: https://lore.kernel.org/r/20200308080859.21568-14-ardb@kernel.org
+
+diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
+index e013bdc1237b..46bbe7ab4adf 100644
+--- a/arch/x86/boot/compressed/head_32.S
++++ b/arch/x86/boot/compressed/head_32.S
+@@ -105,7 +105,7 @@ SYM_FUNC_START(startup_32)
+ 	notl	%eax
+ 	andl    %eax, %ebx
+ 	cmpl	$LOAD_PHYSICAL_ADDR, %ebx
+-	jge	1f
++	jae	1f
+ #endif
+ 	movl	$LOAD_PHYSICAL_ADDR, %ebx
+ 1:
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index 6a4ff919008c..5d8338a693ce 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -105,7 +105,7 @@ SYM_FUNC_START(startup_32)
+ 	notl	%eax
+ 	andl	%eax, %ebx
+ 	cmpl	$LOAD_PHYSICAL_ADDR, %ebx
+-	jge	1f
++	jae	1f
+ #endif
+ 	movl	$LOAD_PHYSICAL_ADDR, %ebx
+ 1:
+@@ -305,7 +305,7 @@ SYM_CODE_START(startup_64)
+ 	notq	%rax
+ 	andq	%rax, %rbp
+ 	cmpq	$LOAD_PHYSICAL_ADDR, %rbp
+-	jge	1f
++	jae	1f
+ #endif
+ 	movq	$LOAD_PHYSICAL_ADDR, %rbp
+ 1:

commit 8acf63efa1712fa5495425a4224378bb3e1231e0
+Author: Arvind Sankar 
+Date:   Sun Mar 8 09:08:43 2020 +0100
+
+    efi/x86: Avoid using code32_start
+    
+    code32_start is meant for 16-bit real-mode bootloaders to inform the
+    kernel where the 32-bit protected mode code starts. Nothing in the
+    protected mode kernel except the EFI stub uses it.
+    
+    efi_main() currently returns boot_params, with code32_start set inside it
+    to tell efi_stub_entry() where startup_32 is located. Since it was invoked
+    by efi_stub_entry() in the first place, boot_params is already known.
+    Return the address of startup_32 instead.
+    
+    This will allow a 64-bit kernel to live above 4Gb, for example, and it's
+    cleaner as well.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200301230436.2246909-5-nivedita@alum.mit.edu
+    Link: https://lore.kernel.org/r/20200308080859.21568-13-ardb@kernel.org
+
+diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
+index 2f8138b71ea9..e013bdc1237b 100644
+--- a/arch/x86/boot/compressed/head_32.S
++++ b/arch/x86/boot/compressed/head_32.S
+@@ -156,9 +156,8 @@ SYM_FUNC_END(startup_32)
+ SYM_FUNC_START(efi32_stub_entry)
+ SYM_FUNC_START_ALIAS(efi_stub_entry)
+ 	add	$0x4, %esp
++	movl	8(%esp), %esi	/* save boot_params pointer */
+ 	call	efi_main
+-	movl	%eax, %esi
+-	movl	BP_code32_start(%esi), %eax
+ 	leal	startup_32(%eax), %eax
+ 	jmp	*%eax
+ SYM_FUNC_END(efi32_stub_entry)
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index fabbd4c2e9f2..6a4ff919008c 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -472,9 +472,9 @@ SYM_CODE_END(startup_64)
+ SYM_FUNC_START(efi64_stub_entry)
+ SYM_FUNC_START_ALIAS(efi_stub_entry)
+ 	and	$~0xf, %rsp			/* realign the stack */
++	movq	%rdx, %rbx			/* save boot_params pointer */
+ 	call	efi_main
+-	movq	%rax,%rsi
+-	movl	BP_code32_start(%esi), %eax
++	movq	%rbx,%rsi
+ 	leaq	startup_64(%rax), %rax
+ 	jmp	*%rax
+ SYM_FUNC_END(efi64_stub_entry)
+diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
+index 5c7ee3df4d0b..3ca07ad552ae 100644
+--- a/arch/x86/kernel/asm-offsets.c
++++ b/arch/x86/kernel/asm-offsets.c
+@@ -88,7 +88,6 @@ static void __used common(void)
+ 	OFFSET(BP_kernel_alignment, boot_params, hdr.kernel_alignment);
+ 	OFFSET(BP_init_size, boot_params, hdr.init_size);
+ 	OFFSET(BP_pref_address, boot_params, hdr.pref_address);
+-	OFFSET(BP_code32_start, boot_params, hdr.code32_start);
+ 
+ 	BLANK();
+ 	DEFINE(PTREGS_SIZE, sizeof(struct pt_regs));
+diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
+index 9db98839d7b4..7f3e97c2aad3 100644
+--- a/drivers/firmware/efi/libstub/x86-stub.c
++++ b/drivers/firmware/efi/libstub/x86-stub.c
+@@ -703,10 +703,11 @@ static efi_status_t exit_boot(struct boot_params *boot_params, void *handle)
+ }
+ 
+ /*
+- * On success we return a pointer to a boot_params structure, and NULL
+- * on failure.
++ * On success, we return the address of startup_32, which has potentially been
++ * relocated by efi_relocate_kernel.
++ * On failure, we exit to the firmware via efi_exit instead of returning.
+  */
+-struct boot_params *efi_main(efi_handle_t handle,
++unsigned long efi_main(efi_handle_t handle,
+ 			     efi_system_table_t *sys_table_arg,
+ 			     struct boot_params *boot_params)
+ {
+@@ -736,7 +737,6 @@ struct boot_params *efi_main(efi_handle_t handle,
+ 			goto fail;
+ 		}
+ 	}
+-	hdr->code32_start = (u32)bzimage_addr;
+ 
+ 	/*
+ 	 * efi_pe_entry() may have been called before efi_main(), in which
+@@ -799,7 +799,7 @@ struct boot_params *efi_main(efi_handle_t handle,
+ 		goto fail;
+ 	}
+ 
+-	return boot_params;
++	return bzimage_addr;
+ fail:
+ 	efi_printk("efi_main() failed!\n");
+ 

commit 3fab43318f0565ffb45925bea5903bc400ce2864
+Author: Arvind Sankar 
+Date:   Sun Mar 8 09:08:42 2020 +0100
+
+    efi/x86: Make efi32_pe_entry() more readable
+    
+    Set up a proper frame pointer in efi32_pe_entry() so that it's easier to
+    calculate offsets for arguments.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200301230436.2246909-4-nivedita@alum.mit.edu
+    Link: https://lore.kernel.org/r/20200308080859.21568-12-ardb@kernel.org
+
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index 920daf62dac2..fabbd4c2e9f2 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -658,42 +658,65 @@ SYM_DATA(efi_is64, .byte 1)
+ 	.text
+ 	.code32
+ SYM_FUNC_START(efi32_pe_entry)
++/*
++ * efi_status_t efi32_pe_entry(efi_handle_t image_handle,
++ *			       efi_system_table_32_t *sys_table)
++ */
++
+ 	pushl	%ebp
++	movl	%esp, %ebp
++	pushl	%eax				// dummy push to allocate loaded_image
+ 
+-	pushl	%ebx
++	pushl	%ebx				// save callee-save registers
+ 	pushl	%edi
++
+ 	call	verify_cpu			// check for long mode support
+-	popl	%edi
+-	popl	%ebx
+ 	testl	%eax, %eax
+ 	movl	$0x80000003, %eax		// EFI_UNSUPPORTED
+-	jnz	3f
++	jnz	2f
+ 
+ 	call	1f
+-1:	pop	%ebp
+-	subl	$1b, %ebp
++1:	pop	%ebx
++	subl	$1b, %ebx
+ 
+ 	/* Get the loaded image protocol pointer from the image handle */
+-	subl	$12, %esp			// space for the loaded image pointer
+-	pushl	%esp				// pass its address
+-	leal	loaded_image_proto(%ebp), %eax
++	leal	-4(%ebp), %eax
++	pushl	%eax				// &loaded_image
++	leal	loaded_image_proto(%ebx), %eax
+ 	pushl	%eax				// pass the GUID address
+-	pushl	28(%esp)			// pass the image handle
++	pushl	8(%ebp)				// pass the image handle
+ 
+-	movl	36(%esp), %eax			// sys_table
++	/*
++	 * Note the alignment of the stack frame.
++	 *   sys_table
++	 *   handle             <-- 16-byte aligned on entry by ABI
++	 *   return address
++	 *   frame pointer
++	 *   loaded_image       <-- local variable
++	 *   saved %ebx		<-- 16-byte aligned here
++	 *   saved %edi
++	 *   &loaded_image
++	 *   &loaded_image_proto
++	 *   handle             <-- 16-byte aligned for call to handle_protocol
++	 */
++
++	movl	12(%ebp), %eax			// sys_table
+ 	movl	ST32_boottime(%eax), %eax	// sys_table->boottime
+ 	call	*BS32_handle_protocol(%eax)	// sys_table->boottime->handle_protocol
+-	cmp	$0, %eax
++	addl	$12, %esp			// restore argument space
++	testl	%eax, %eax
+ 	jnz	2f
+ 
+-	movl	32(%esp), %ecx			// image_handle
+-	movl	36(%esp), %edx			// sys_table
+-	movl	12(%esp), %esi			// loaded_image
++	movl	8(%ebp), %ecx			// image_handle
++	movl	12(%ebp), %edx			// sys_table
++	movl	-4(%ebp), %esi			// loaded_image
+ 	movl	LI32_image_base(%esi), %esi	// loaded_image->image_base
++	movl	%ebx, %ebp			// startup_32 for efi32_pe_stub_entry
+ 	jmp	efi32_pe_stub_entry
+ 
+-2:	addl	$24, %esp
+-3:	popl	%ebp
++2:	popl	%edi				// restore callee-save registers
++	popl	%ebx
++	leave
+ 	ret
+ SYM_FUNC_END(efi32_pe_entry)
+ 

commit 71ff44ac6cfaa1d8d3dff6c73636f4fb97b2be10
+Author: Arvind Sankar 
+Date:   Sun Mar 8 09:08:41 2020 +0100
+
+    efi/x86: Respect 32-bit ABI in efi32_pe_entry()
+    
+    verify_cpu() clobbers BX and DI. In case we have to return error, we need
+    to preserve them to respect the 32-bit calling convention.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200301230436.2246909-3-nivedita@alum.mit.edu
+    Link: https://lore.kernel.org/r/20200308080859.21568-11-ardb@kernel.org
+
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index 8105e8348607..920daf62dac2 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -660,7 +660,11 @@ SYM_DATA(efi_is64, .byte 1)
+ SYM_FUNC_START(efi32_pe_entry)
+ 	pushl	%ebp
+ 
++	pushl	%ebx
++	pushl	%edi
+ 	call	verify_cpu			// check for long mode support
++	popl	%edi
++	popl	%ebx
+ 	testl	%eax, %eax
+ 	movl	$0x80000003, %eax		// EFI_UNSUPPORTED
+ 	jnz	3f

commit 3cdcd6899eaf454b2539c624fff5daf63c175a7a
+Author: Arvind Sankar 
+Date:   Sun Mar 8 09:08:40 2020 +0100
+
+    efi/x86: Annotate the LOADED_IMAGE_PROTOCOL_GUID with SYM_DATA
+    
+    Use SYM_DATA*() macros to annotate this constant, and explicitly align it
+    to 4-byte boundary. Use lower-case for hexadecimal data.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+    Signed-off-by: Ingo Molnar 
+    Link: https://lore.kernel.org/r/20200301230436.2246909-2-nivedita@alum.mit.edu
+    Link: https://lore.kernel.org/r/20200308080859.21568-10-ardb@kernel.org
+
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index fcf8feaa57ea..8105e8348607 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -672,7 +672,7 @@ SYM_FUNC_START(efi32_pe_entry)
+ 	/* Get the loaded image protocol pointer from the image handle */
+ 	subl	$12, %esp			// space for the loaded image pointer
+ 	pushl	%esp				// pass its address
+-	leal	4f(%ebp), %eax
++	leal	loaded_image_proto(%ebp), %eax
+ 	pushl	%eax				// pass the GUID address
+ 	pushl	28(%esp)			// pass the image handle
+ 
+@@ -695,9 +695,12 @@ SYM_FUNC_END(efi32_pe_entry)
+ 
+ 	.section ".rodata"
+ 	/* EFI loaded image protocol GUID */
+-4:	.long	0x5B1B31A1
++	.balign 4
++SYM_DATA_START_LOCAL(loaded_image_proto)
++	.long	0x5b1b31a1
+ 	.word	0x9562, 0x11d2
+-	.byte	0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B
++	.byte	0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b
++SYM_DATA_END(loaded_image_proto)
+ #endif
+ 
+ /*

commit 681ff0181bbfb183e32bc6beb6ec076304470479
+Author: Arvind Sankar 
+Date:   Thu Mar 5 10:01:52 2020 -0500
+
+    x86/mm/init/32: Stop printing the virtual memory layout
+    
+    For security reasons, don't display the kernel's virtual memory layout.
+    
+    Kees Cook points out:
+    "These have been entirely removed on other architectures, so let's
+    just do the same for ia32 and remove it unconditionally."
+    
+    071929dbdd86 ("arm64: Stop printing the virtual memory layout")
+    1c31d4e96b8c ("ARM: 8820/1: mm: Stop printing the virtual memory layout")
+    31833332f798 ("m68k/mm: Stop printing the virtual memory layout")
+    fd8d0ca25631 ("parisc: Hide virtual kernel memory layout")
+    adb1fe9ae2ee ("mm/page_alloc: Remove kernel address exposure in free_reserved_area()")
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Thomas Gleixner 
+    Acked-by: Tycho Andersen 
+    Acked-by: Kees Cook 
+    Link: https://lkml.kernel.org/r/20200305150152.831697-1-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
+index 23df4885bbed..8ae0272c1c51 100644
+--- a/arch/x86/mm/init_32.c
++++ b/arch/x86/mm/init_32.c
+@@ -788,44 +788,6 @@ void __init mem_init(void)
+ 	x86_init.hyper.init_after_bootmem();
+ 
+ 	mem_init_print_info(NULL);
+-	printk(KERN_INFO "virtual kernel memory layout:\n"
+-		"    fixmap  : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+-		"  cpu_entry : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+-#ifdef CONFIG_HIGHMEM
+-		"    pkmap   : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+-#endif
+-		"    vmalloc : 0x%08lx - 0x%08lx   (%4ld MB)\n"
+-		"    lowmem  : 0x%08lx - 0x%08lx   (%4ld MB)\n"
+-		"      .init : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+-		"      .data : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+-		"      .text : 0x%08lx - 0x%08lx   (%4ld kB)\n",
+-		FIXADDR_START, FIXADDR_TOP,
+-		(FIXADDR_TOP - FIXADDR_START) >> 10,
+-
+-		CPU_ENTRY_AREA_BASE,
+-		CPU_ENTRY_AREA_BASE + CPU_ENTRY_AREA_MAP_SIZE,
+-		CPU_ENTRY_AREA_MAP_SIZE >> 10,
+-
+-#ifdef CONFIG_HIGHMEM
+-		PKMAP_BASE, PKMAP_BASE+LAST_PKMAP*PAGE_SIZE,
+-		(LAST_PKMAP*PAGE_SIZE) >> 10,
+-#endif
+-
+-		VMALLOC_START, VMALLOC_END,
+-		(VMALLOC_END - VMALLOC_START) >> 20,
+-
+-		(unsigned long)__va(0), (unsigned long)high_memory,
+-		((unsigned long)high_memory - (unsigned long)__va(0)) >> 20,
+-
+-		(unsigned long)&__init_begin, (unsigned long)&__init_end,
+-		((unsigned long)&__init_end -
+-		 (unsigned long)&__init_begin) >> 10,
+-
+-		(unsigned long)&_etext, (unsigned long)&_edata,
+-		((unsigned long)&_edata - (unsigned long)&_etext) >> 10,
+-
+-		(unsigned long)&_text, (unsigned long)&_etext,
+-		((unsigned long)&_etext - (unsigned long)&_text) >> 10);
+ 
+ 	/*
+ 	 * Check boundaries twice: Some fundamental inconsistencies can

commit c98a76eabbb6e7755f3d4a4c33f8fe869dda6383
+Author: Arvind Sankar 
+Date:   Wed Feb 26 18:00:31 2020 -0500
+
+    x86/boot/compressed: Fix reloading of GDTR post-relocation
+    
+    The following commit:
+    
+      ef5a7b5eb13e ("efi/x86: Remove GDT setup from efi_main")
+    
+    introduced GDT setup into the 32-bit kernel's startup_32, and reloads
+    the GDTR after relocating the kernel for paranoia's sake.
+    
+    A followup commit:
+    
+       32d009137a56 ("x86/boot: Reload GDTR after copying to the end of the buffer")
+    
+    introduced a similar GDTR reload in the 64-bit kernel as well.
+    
+    The GDTR is adjusted by (init_size-_end), however this may not be the
+    correct offset to apply if the kernel was loaded at a misaligned address
+    or below LOAD_PHYSICAL_ADDR, as in that case the decompression buffer
+    has an additional offset from the original load address.
+    
+    This should never happen for a conformant bootloader, but we're being
+    paranoid anyway, so just store the new GDT address in there instead of
+    adding any offsets, which is simpler as well.
+    
+    Fixes: ef5a7b5eb13e ("efi/x86: Remove GDT setup from efi_main")
+    Fixes: 32d009137a56 ("x86/boot: Reload GDTR after copying to the end of the buffer")
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ingo Molnar 
+    Cc: Ingo Molnar 
+    Cc: Ard Biesheuvel 
+    Cc: linux-efi@vger.kernel.org
+    Cc: Thomas Gleixner 
+    Cc: x86@kernel.org
+    Link: https://lore.kernel.org/r/20200226230031.3011645-2-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
+index 356060c5332c..2f8138b71ea9 100644
+--- a/arch/x86/boot/compressed/head_32.S
++++ b/arch/x86/boot/compressed/head_32.S
+@@ -139,12 +139,11 @@ SYM_FUNC_START(startup_32)
+ 	/*
+ 	 * The GDT may get overwritten either during the copy we just did or
+ 	 * during extract_kernel below. To avoid any issues, repoint the GDTR
+-	 * to the new copy of the GDT. EAX still contains the previously
+-	 * calculated relocation offset of init_size - _end.
++	 * to the new copy of the GDT.
+ 	 */
+-	leal	gdt(%ebx), %edx
+-	addl	%eax, 2(%edx)
+-	lgdt	(%edx)
++	leal	gdt(%ebx), %eax
++	movl	%eax, 2(%eax)
++	lgdt	(%eax)
+ 
+ /*
+  * Jump to the relocated address.
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index f7bacc4c1494..fcf8feaa57ea 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -456,8 +456,8 @@ trampoline_return:
+ 	 * to the new copy of the GDT.
+ 	 */
+ 	leaq	gdt64(%rbx), %rax
+-	subq	%rbp, 2(%rax)
+-	addq	%rbx, 2(%rax)
++	leaq	gdt(%rbx), %rdx
++	movq	%rdx, 2(%rax)
+ 	lgdt	(%rax)
+ 
+ /*

commit 6f8f0dc980028e98ae339876a8403edae4d20e39
+Author: Arvind Sankar 
+Date:   Mon Feb 24 18:21:29 2020 -0500
+
+    x86/vmlinux: Drop unneeded linker script discard of .eh_frame
+    
+    Now that .eh_frame sections for the files in setup.elf and realmode.elf
+    are not generated anymore, the linker scripts don't need the special
+    output section name /DISCARD/ any more.
+    
+    Remove the one in the main kernel linker script as well, since there are
+    no .eh_frame sections already, and fix up a comment referencing .eh_frame.
+    
+    Update the comment in asm/dwarf2.h referring to .eh_frame so it continues
+    to make sense, as well as being more specific.
+    
+     [ bp: Touch up commit message. ]
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Borislav Petkov 
+    Reviewed-by: Nathan Chancellor 
+    Reviewed-by: Nick Desaulniers 
+    Reviewed-by: Kees Cook 
+    Tested-by: Nathan Chancellor 
+    Link: https://lkml.kernel.org/r/20200224232129.597160-3-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/vmlinux.lds.S b/arch/x86/boot/compressed/vmlinux.lds.S
+index 469dcf800a2c..508cfa6828c5 100644
+--- a/arch/x86/boot/compressed/vmlinux.lds.S
++++ b/arch/x86/boot/compressed/vmlinux.lds.S
+@@ -73,9 +73,4 @@ SECTIONS
+ #endif
+ 	. = ALIGN(PAGE_SIZE);	/* keep ZO size page aligned */
+ 	_end = .;
+-
+-	/* Discard .eh_frame to save some space */
+-	/DISCARD/ : {
+-		*(.eh_frame)
+-	}
+ }
+diff --git a/arch/x86/boot/setup.ld b/arch/x86/boot/setup.ld
+index 3da1c37c6dd5..24c95522f231 100644
+--- a/arch/x86/boot/setup.ld
++++ b/arch/x86/boot/setup.ld
+@@ -52,7 +52,6 @@ SECTIONS
+ 	_end = .;
+ 
+ 	/DISCARD/	: {
+-		*(.eh_frame)
+ 		*(.note*)
+ 	}
+ 
+diff --git a/arch/x86/include/asm/dwarf2.h b/arch/x86/include/asm/dwarf2.h
+index ae391f609840..f71a0cce9373 100644
+--- a/arch/x86/include/asm/dwarf2.h
++++ b/arch/x86/include/asm/dwarf2.h
+@@ -42,8 +42,8 @@
+ 	 * Emit CFI data in .debug_frame sections, not .eh_frame sections.
+ 	 * The latter we currently just discard since we don't do DWARF
+ 	 * unwinding at runtime.  So only the offline DWARF information is
+-	 * useful to anyone.  Note we should not use this directive if
+-	 * vmlinux.lds.S gets changed so it doesn't discard .eh_frame.
++	 * useful to anyone.  Note we should not use this directive if we
++	 * ever decide to enable DWARF unwinding at runtime.
+ 	 */
+ 	.cfi_sections .debug_frame
+ #else
+diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
+index e3296aa028fe..5cab3a29adcb 100644
+--- a/arch/x86/kernel/vmlinux.lds.S
++++ b/arch/x86/kernel/vmlinux.lds.S
+@@ -313,8 +313,8 @@ SECTIONS
+ 
+ 	. = ALIGN(8);
+ 	/*
+-	 * .exit.text is discard at runtime, not link time, to deal with
+-	 *  references from .altinstructions and .eh_frame
++	 * .exit.text is discarded at runtime, not link time, to deal with
++	 *  references from .altinstructions
+ 	 */
+ 	.exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) {
+ 		EXIT_TEXT
+@@ -412,9 +412,6 @@ SECTIONS
+ 	DWARF_DEBUG
+ 
+ 	DISCARDS
+-	/DISCARD/ : {
+-		*(.eh_frame)
+-	}
+ }
+ 
+ 
+diff --git a/arch/x86/realmode/rm/realmode.lds.S b/arch/x86/realmode/rm/realmode.lds.S
+index 64d135d1ee63..63aa51875ba0 100644
+--- a/arch/x86/realmode/rm/realmode.lds.S
++++ b/arch/x86/realmode/rm/realmode.lds.S
+@@ -71,7 +71,6 @@ SECTIONS
+ 	/DISCARD/ : {
+ 		*(.note*)
+ 		*(.debug*)
+-		*(.eh_frame*)
+ 	}
+ 
+ #include "pasyms.h"

commit 003602ad5516e59940de42e44c8d8033387bb363
+Author: Arvind Sankar 
+Date:   Mon Feb 24 18:21:28 2020 -0500
+
+    x86/*/Makefile: Use -fno-asynchronous-unwind-tables to suppress .eh_frame sections
+    
+    While discussing a patch to discard .eh_frame from the compressed
+    vmlinux using the linker script, Fangrui Song pointed out [1] that these
+    sections shouldn't exist in the first place because arch/x86/Makefile
+    uses -fno-asynchronous-unwind-tables.
+    
+    It turns out this is because the Makefiles used to build the compressed
+    kernel redefine KBUILD_CFLAGS, dropping this flag.
+    
+    Add the flag to the Makefile for the compressed kernel, as well as the
+    EFI stub Makefile to fix this.
+    
+    Also add the flag to boot/Makefile and realmode/rm/Makefile so that the
+    kernel's boot code (boot/setup.elf) and realmode trampoline
+    (realmode/rm/realmode.elf) won't be compiled with .eh_frame sections,
+    since their linker scripts also just discard them.
+    
+      [1] https://lore.kernel.org/lkml/20200222185806.ywnqhfqmy67akfsa@google.com/
+    
+    Suggested-by: Fangrui Song 
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Borislav Petkov 
+    Reviewed-by: Nathan Chancellor 
+    Reviewed-by: Nick Desaulniers 
+    Reviewed-by: Kees Cook 
+    Tested-by: Nathan Chancellor 
+    Link: https://lkml.kernel.org/r/20200224232129.597160-2-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
+index 012b82fc8617..24f011e0adf1 100644
+--- a/arch/x86/boot/Makefile
++++ b/arch/x86/boot/Makefile
+@@ -68,6 +68,7 @@ clean-files += cpustr.h
+ KBUILD_CFLAGS	:= $(REALMODE_CFLAGS) -D_SETUP
+ KBUILD_AFLAGS	:= $(KBUILD_CFLAGS) -D__ASSEMBLY__
+ KBUILD_CFLAGS	+= $(call cc-option,-fmacro-prefix-map=$(srctree)/=)
++KBUILD_CFLAGS	+= -fno-asynchronous-unwind-tables
+ GCOV_PROFILE := n
+ UBSAN_SANITIZE := n
+ 
+diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
+index 26050ae0b27e..c33111341325 100644
+--- a/arch/x86/boot/compressed/Makefile
++++ b/arch/x86/boot/compressed/Makefile
+@@ -39,6 +39,7 @@ KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member)
+ KBUILD_CFLAGS += $(call cc-disable-warning, gnu)
+ KBUILD_CFLAGS += -Wno-pointer-sign
+ KBUILD_CFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=)
++KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
+ 
+ KBUILD_AFLAGS  := $(KBUILD_CFLAGS) -D__ASSEMBLY__
+ GCOV_PROFILE := n
+diff --git a/arch/x86/realmode/rm/Makefile b/arch/x86/realmode/rm/Makefile
+index 99b6332ba540..b11ec5d8f8ac 100644
+--- a/arch/x86/realmode/rm/Makefile
++++ b/arch/x86/realmode/rm/Makefile
+@@ -71,5 +71,6 @@ $(obj)/realmode.relocs: $(obj)/realmode.elf FORCE
+ KBUILD_CFLAGS	:= $(REALMODE_CFLAGS) -D_SETUP -D_WAKEUP \
+ 		   -I$(srctree)/arch/x86/boot
+ KBUILD_AFLAGS	:= $(KBUILD_CFLAGS) -D__ASSEMBLY__
++KBUILD_CFLAGS	+= -fno-asynchronous-unwind-tables
+ GCOV_PROFILE := n
+ UBSAN_SANITIZE := n
+diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
+index 98a81576213d..a1140c4ee478 100644
+--- a/drivers/firmware/efi/libstub/Makefile
++++ b/drivers/firmware/efi/libstub/Makefile
+@@ -12,7 +12,8 @@ cflags-$(CONFIG_X86)		+= -m$(BITS) -D__KERNEL__ -O2 \
+ 				   -mno-mmx -mno-sse -fshort-wchar \
+ 				   -Wno-pointer-sign \
+ 				   $(call cc-disable-warning, address-of-packed-member) \
+-				   $(call cc-disable-warning, gnu)
++				   $(call cc-disable-warning, gnu) \
++				   -fno-asynchronous-unwind-tables
+ 
+ # arm64 uses the full KBUILD_CFLAGS so it's necessary to explicitly
+ # disable the stackleak plugin

commit 0eea39a234dc52063d14541fabcb2c64516a2328
+Author: Arvind Sankar 
+Date:   Thu Jan 9 10:02:18 2020 -0500
+
+    x86/boot/compressed: Remove .eh_frame section from bzImage
+    
+    Discarding unnecessary sections with "*(*)" (see thread at Link: below)
+    works fine with the bfd linker but fails with lld:
+    
+      $ make -j$(nproc) -s CC=clang LD=ld.lld O=out.x86_64 distclean defconfig bzImage
+      ld.lld: error: discarding .shstrtab section is not allowed
+    
+    lld tries to also discard essential sections like .shstrtab, .symtab and
+    .strtab, which results in the link failing since .shstrtab is required
+    by the ELF specification: the e_shstrndx field in the ELF header is the
+    index of .shstrtab, and each section in the section table is required to
+    have an sh_name that points into the .shstrtab.
+    
+    .symtab and .strtab are also necessary to generate the zoffset.h file
+    for the bzImage header.
+    
+    Since the only sizeable section that can be discarded is .eh_frame,
+    restrict the discard to only .eh_frame to be safe.
+    
+     [ bp: Flesh out commit message and replace offending commit with this one. ]
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Borislav Petkov 
+    Tested-by: Nathan Chancellor 
+    Link: https://lkml.kernel.org/r/20200109150218.16544-2-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/vmlinux.lds.S b/arch/x86/boot/compressed/vmlinux.lds.S
+index 508cfa6828c5..469dcf800a2c 100644
+--- a/arch/x86/boot/compressed/vmlinux.lds.S
++++ b/arch/x86/boot/compressed/vmlinux.lds.S
+@@ -73,4 +73,9 @@ SECTIONS
+ #endif
+ 	. = ALIGN(PAGE_SIZE);	/* keep ZO size page aligned */
+ 	_end = .;
++
++	/* Discard .eh_frame to save some space */
++	/DISCARD/ : {
++		*(.eh_frame)
++	}
+ }

commit f32ea1cd124c9a8b847e33123d156cb55699fa51
+Author: Arvind Sankar 
+Date:   Thu Jan 30 17:20:04 2020 -0500
+
+    efi/x86: Mark setup_graphics static
+    
+    This function is only called from efi_main in the same source file.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200130222004.1932152-1-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
+index c92fe0b75cec..32423e83ba8f 100644
+--- a/arch/x86/boot/compressed/eboot.c
++++ b/arch/x86/boot/compressed/eboot.c
+@@ -315,7 +315,7 @@ setup_uga(struct screen_info *si, efi_guid_t *uga_proto, unsigned long size)
+ 	return status;
+ }
+ 
+-void setup_graphics(struct boot_params *boot_params)
++static void setup_graphics(struct boot_params *boot_params)
+ {
+ 	efi_guid_t graphics_proto = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
+ 	struct screen_info *si;

commit 8a3abe30de9fffec8b44adeb78f93ecb0f09b0c5
+Author: Arvind Sankar 
+Date:   Sun Feb 2 12:13:53 2020 -0500
+
+    x86/boot: Micro-optimize GDT loading instructions
+    
+    Rearrange the instructions a bit to use a 32-bit displacement once
+    instead of 2/3 times. This saves 8 bytes of machine code.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200202171353.3736319-8-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index c36e6156b6a3..a4f5561c1c0e 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -69,8 +69,9 @@ SYM_FUNC_START(startup_32)
+ 	subl	$1b, %ebp
+ 
+ 	/* Load new GDT with the 64bit segments using 32bit descriptor */
+-	addl	%ebp, gdt+2(%ebp)
+-	lgdt	gdt(%ebp)
++	leal	gdt(%ebp), %eax
++	movl	%eax, 2(%eax)
++	lgdt	(%eax)
+ 
+ 	/* Load segment registers with our descriptors */
+ 	movl	$__BOOT_DS, %eax
+@@ -355,9 +356,9 @@ SYM_CODE_START(startup_64)
+ 	 */
+ 
+ 	/* Make sure we have GDT with 32-bit code segment */
+-	leaq	gdt(%rip), %rax
+-	movq	%rax, gdt64+2(%rip)
+-	lgdt	gdt64(%rip)
++	leaq	gdt64(%rip), %rax
++	addq	%rax, 2(%rax)
++	lgdt	(%rax)
+ 
+ 	/*
+ 	 * paging_prepare() sets up the trampoline and checks if we need to
+@@ -625,12 +626,12 @@ SYM_FUNC_END(.Lno_longmode)
+ 	.data
+ SYM_DATA_START_LOCAL(gdt64)
+ 	.word	gdt_end - gdt - 1
+-	.quad   0
++	.quad   gdt - gdt64
+ SYM_DATA_END(gdt64)
+ 	.balign	8
+ SYM_DATA_START_LOCAL(gdt)
+ 	.word	gdt_end - gdt - 1
+-	.long	gdt
++	.long	0
+ 	.word	0
+ 	.quad	0x00cf9a000000ffff	/* __KERNEL32_CS */
+ 	.quad	0x00af9a000000ffff	/* __KERNEL_CS */

commit b75e2b076d00751579c73cfbbc8a7eac7d2a0468
+Author: Arvind Sankar 
+Date:   Sun Feb 2 12:13:52 2020 -0500
+
+    x86/boot: GDT limit value should be size - 1
+    
+    The limit value for the GDTR should be such that adding it to the base
+    address gives the address of the last byte of the GDT, i.e. it should be
+    one less than the size, not the size.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200202171353.3736319-7-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index 69cc6c68741e..c36e6156b6a3 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -624,12 +624,12 @@ SYM_FUNC_END(.Lno_longmode)
+ 
+ 	.data
+ SYM_DATA_START_LOCAL(gdt64)
+-	.word	gdt_end - gdt
++	.word	gdt_end - gdt - 1
+ 	.quad   0
+ SYM_DATA_END(gdt64)
+ 	.balign	8
+ SYM_DATA_START_LOCAL(gdt)
+-	.word	gdt_end - gdt
++	.word	gdt_end - gdt - 1
+ 	.long	gdt
+ 	.word	0
+ 	.quad	0x00cf9a000000ffff	/* __KERNEL32_CS */

commit ef5a7b5eb13ed88ba9690ab27def3a085332cc8c
+Author: Arvind Sankar 
+Date:   Sun Feb 2 12:13:51 2020 -0500
+
+    efi/x86: Remove GDT setup from efi_main
+    
+    The 64-bit kernel will already load a GDT in startup_64, which is the
+    next function to execute after return from efi_main.
+    
+    Add GDT setup code to the 32-bit kernel's startup_32 as well. Doing it
+    in the head code has the advantage that we can avoid potentially
+    corrupting the GDT during copy/decompression. This also removes
+    dependence on having a specific GDT layout setup by the bootloader.
+    
+    Both startup_32 and startup_64 now clear interrupts on entry, so we can
+    remove that from efi_main as well.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200202171353.3736319-6-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
+index 287393d725f0..c92fe0b75cec 100644
+--- a/arch/x86/boot/compressed/eboot.c
++++ b/arch/x86/boot/compressed/eboot.c
+@@ -712,10 +712,8 @@ struct boot_params *efi_main(efi_handle_t handle,
+ 			     efi_system_table_t *sys_table_arg,
+ 			     struct boot_params *boot_params)
+ {
+-	struct desc_ptr *gdt = NULL;
+ 	struct setup_header *hdr = &boot_params->hdr;
+ 	efi_status_t status;
+-	struct desc_struct *desc;
+ 	unsigned long cmdline_paddr;
+ 
+ 	sys_table = sys_table_arg;
+@@ -753,20 +751,6 @@ struct boot_params *efi_main(efi_handle_t handle,
+ 
+ 	setup_quirks(boot_params);
+ 
+-	status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, sizeof(*gdt),
+-			     (void **)&gdt);
+-	if (status != EFI_SUCCESS) {
+-		efi_printk("Failed to allocate memory for 'gdt' structure\n");
+-		goto fail;
+-	}
+-
+-	gdt->size = 0x800;
+-	status = efi_low_alloc(gdt->size, 8, (unsigned long *)&gdt->address);
+-	if (status != EFI_SUCCESS) {
+-		efi_printk("Failed to allocate memory for 'gdt'\n");
+-		goto fail;
+-	}
+-
+ 	/*
+ 	 * If the kernel isn't already loaded at the preferred load
+ 	 * address, relocate it.
+@@ -793,93 +777,6 @@ struct boot_params *efi_main(efi_handle_t handle,
+ 		goto fail;
+ 	}
+ 
+-	memset((char *)gdt->address, 0x0, gdt->size);
+-	desc = (struct desc_struct *)gdt->address;
+-
+-	/* The first GDT is a dummy. */
+-	desc++;
+-
+-	if (IS_ENABLED(CONFIG_X86_64)) {
+-		/* __KERNEL32_CS */
+-		desc->limit0	= 0xffff;
+-		desc->base0	= 0x0000;
+-		desc->base1	= 0x0000;
+-		desc->type	= SEG_TYPE_CODE | SEG_TYPE_EXEC_READ;
+-		desc->s		= DESC_TYPE_CODE_DATA;
+-		desc->dpl	= 0;
+-		desc->p		= 1;
+-		desc->limit1	= 0xf;
+-		desc->avl	= 0;
+-		desc->l		= 0;
+-		desc->d		= SEG_OP_SIZE_32BIT;
+-		desc->g		= SEG_GRANULARITY_4KB;
+-		desc->base2	= 0x00;
+-
+-		desc++;
+-	} else {
+-		/* Second entry is unused on 32-bit */
+-		desc++;
+-	}
+-
+-	/* __KERNEL_CS */
+-	desc->limit0	= 0xffff;
+-	desc->base0	= 0x0000;
+-	desc->base1	= 0x0000;
+-	desc->type	= SEG_TYPE_CODE | SEG_TYPE_EXEC_READ;
+-	desc->s		= DESC_TYPE_CODE_DATA;
+-	desc->dpl	= 0;
+-	desc->p		= 1;
+-	desc->limit1	= 0xf;
+-	desc->avl	= 0;
+-
+-	if (IS_ENABLED(CONFIG_X86_64)) {
+-		desc->l = 1;
+-		desc->d = 0;
+-	} else {
+-		desc->l = 0;
+-		desc->d = SEG_OP_SIZE_32BIT;
+-	}
+-	desc->g		= SEG_GRANULARITY_4KB;
+-	desc->base2	= 0x00;
+-	desc++;
+-
+-	/* __KERNEL_DS */
+-	desc->limit0	= 0xffff;
+-	desc->base0	= 0x0000;
+-	desc->base1	= 0x0000;
+-	desc->type	= SEG_TYPE_DATA | SEG_TYPE_READ_WRITE;
+-	desc->s		= DESC_TYPE_CODE_DATA;
+-	desc->dpl	= 0;
+-	desc->p		= 1;
+-	desc->limit1	= 0xf;
+-	desc->avl	= 0;
+-	desc->l		= 0;
+-	desc->d		= SEG_OP_SIZE_32BIT;
+-	desc->g		= SEG_GRANULARITY_4KB;
+-	desc->base2	= 0x00;
+-	desc++;
+-
+-	if (IS_ENABLED(CONFIG_X86_64)) {
+-		/* Task segment value */
+-		desc->limit0	= 0x0000;
+-		desc->base0	= 0x0000;
+-		desc->base1	= 0x0000;
+-		desc->type	= SEG_TYPE_TSS;
+-		desc->s		= 0;
+-		desc->dpl	= 0;
+-		desc->p		= 1;
+-		desc->limit1	= 0x0;
+-		desc->avl	= 0;
+-		desc->l		= 0;
+-		desc->d		= 0;
+-		desc->g		= SEG_GRANULARITY_4KB;
+-		desc->base2	= 0x00;
+-		desc++;
+-	}
+-
+-	asm volatile("cli");
+-	asm volatile ("lgdt %0" : : "m" (*gdt));
+-
+ 	return boot_params;
+ fail:
+ 	efi_printk("efi_main() failed!\n");
+diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
+index cb2cb91fce45..356060c5332c 100644
+--- a/arch/x86/boot/compressed/head_32.S
++++ b/arch/x86/boot/compressed/head_32.S
+@@ -64,12 +64,6 @@
+ SYM_FUNC_START(startup_32)
+ 	cld
+ 	cli
+-	movl	$__BOOT_DS, %eax
+-	movl	%eax, %ds
+-	movl	%eax, %es
+-	movl	%eax, %fs
+-	movl	%eax, %gs
+-	movl	%eax, %ss
+ 
+ /*
+  * Calculate the delta between where we were compiled to run
+@@ -84,6 +78,19 @@ SYM_FUNC_START(startup_32)
+ 1:	popl	%ebp
+ 	subl	$1b, %ebp
+ 
++	/* Load new GDT */
++	leal	gdt(%ebp), %eax
++	movl	%eax, 2(%eax)
++	lgdt	(%eax)
++
++	/* Load segment registers with our descriptors */
++	movl	$__BOOT_DS, %eax
++	movl	%eax, %ds
++	movl	%eax, %es
++	movl	%eax, %fs
++	movl	%eax, %gs
++	movl	%eax, %ss
++
+ /*
+  * %ebp contains the address we are loaded at by the boot loader and %ebx
+  * contains the address where we should move the kernel image temporarily
+@@ -129,6 +136,16 @@ SYM_FUNC_START(startup_32)
+ 	cld
+ 	popl	%esi
+ 
++	/*
++	 * The GDT may get overwritten either during the copy we just did or
++	 * during extract_kernel below. To avoid any issues, repoint the GDTR
++	 * to the new copy of the GDT. EAX still contains the previously
++	 * calculated relocation offset of init_size - _end.
++	 */
++	leal	gdt(%ebx), %edx
++	addl	%eax, 2(%edx)
++	lgdt	(%edx)
++
+ /*
+  * Jump to the relocated address.
+  */
+@@ -201,6 +218,17 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
+ 	jmp	*%eax
+ SYM_FUNC_END(.Lrelocated)
+ 
++	.data
++	.balign	8
++SYM_DATA_START_LOCAL(gdt)
++	.word	gdt_end - gdt - 1
++	.long	0
++	.word	0
++	.quad	0x0000000000000000	/* Reserved */
++	.quad	0x00cf9a000000ffff	/* __KERNEL_CS */
++	.quad	0x00cf92000000ffff	/* __KERNEL_DS */
++SYM_DATA_END_LABEL(gdt, SYM_L_LOCAL, gdt_end)
++
+ /*
+  * Stack and heap for uncompression
+  */

commit cae0e431a02cd63fecaf677ae166f184644125a7
+Author: Arvind Sankar 
+Date:   Sun Feb 2 12:13:50 2020 -0500
+
+    x86/boot: Clear direction and interrupt flags in startup_64
+    
+    startup_32 already clears these flags on entry, do it in startup_64 as
+    well for consistency.
+    
+    The direction flag in particular is not specified to be cleared in the
+    boot protocol documentation, and we currently call into C code
+    (paging_prepare) without explicitly clearing it.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200202171353.3736319-5-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index 27eb2a6786db..69cc6c68741e 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -264,6 +264,9 @@ SYM_CODE_START(startup_64)
+ 	 * and command line.
+ 	 */
+ 
++	cld
++	cli
++
+ 	/* Setup data segments. */
+ 	xorl	%eax, %eax
+ 	movl	%eax, %ds

commit 32d009137a5646947d450da6fa641a1f4dc1e42c
+Author: Arvind Sankar 
+Date:   Sun Feb 2 12:13:49 2020 -0500
+
+    x86/boot: Reload GDTR after copying to the end of the buffer
+    
+    The GDT may get overwritten during the copy or during extract_kernel,
+    which will cause problems if any segment register is touched before the
+    GDTR is reloaded by the decompressed kernel. For safety update the GDTR
+    to point to the GDT within the copied kernel.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200202171353.3736319-4-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index c56b30bd9c7b..27eb2a6786db 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -439,6 +439,16 @@ trampoline_return:
+ 	cld
+ 	popq	%rsi
+ 
++	/*
++	 * The GDT may get overwritten either during the copy we just did or
++	 * during extract_kernel below. To avoid any issues, repoint the GDTR
++	 * to the new copy of the GDT.
++	 */
++	leaq	gdt64(%rbx), %rax
++	subq	%rbp, 2(%rax)
++	addq	%rbx, 2(%rax)
++	lgdt	(%rax)
++
+ /*
+  * Jump to the relocated address.
+  */

commit 90ff226281e1083988a42cfc51f89d91734cc55e
+Author: Arvind Sankar 
+Date:   Sun Feb 2 12:13:48 2020 -0500
+
+    efi/x86: Don't depend on firmware GDT layout
+    
+    When booting in mixed mode, the firmware's GDT is still installed at
+    handover entry in efi32_stub_entry. We save the GDTR for later use in
+    __efi64_thunk but we are assuming that descriptor 2 (__KERNEL_CS) is a
+    valid 32-bit code segment descriptor and that descriptor 3
+    (__KERNEL_DS/__BOOT_DS) is a valid data segment descriptor.
+    
+    This happens to be true for OVMF (it actually uses descriptor 1 for data
+    segments, but descriptor 3 is also setup as data), but we shouldn't
+    depend on this being the case.
+    
+    Fix this by saving the code and data selectors in addition to the GDTR
+    in efi32_stub_entry, and restoring them in __efi64_thunk before calling
+    the firmware. The UEFI specification guarantees that selectors will be
+    flat, so using the DS selector for all the segment registers should be
+    enough.
+    
+    We also need to install our own GDT before initializing segment
+    registers in startup_32, so move the GDT load up to the beginning of the
+    function.
+    
+    [ardb: mention mixed mode in the commit log]
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200202171353.3736319-3-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/arch/x86/boot/compressed/efi_thunk_64.S b/arch/x86/boot/compressed/efi_thunk_64.S
+index 8fb7f6799c52..2b2049259619 100644
+--- a/arch/x86/boot/compressed/efi_thunk_64.S
++++ b/arch/x86/boot/compressed/efi_thunk_64.S
+@@ -54,11 +54,16 @@ SYM_FUNC_START(__efi64_thunk)
+ 	 * Switch to gdt with 32-bit segments. This is the firmware GDT
+ 	 * that was installed when the kernel started executing. This
+ 	 * pointer was saved at the EFI stub entry point in head_64.S.
++	 *
++	 * Pass the saved DS selector to the 32-bit code, and use far return to
++	 * restore the saved CS selector.
+ 	 */
+ 	leaq	efi32_boot_gdt(%rip), %rax
+ 	lgdt	(%rax)
+ 
+-	pushq	$__KERNEL_CS
++	movzwl	efi32_boot_ds(%rip), %edx
++	movzwq	efi32_boot_cs(%rip), %rax
++	pushq	%rax
+ 	leaq	efi_enter32(%rip), %rax
+ 	pushq	%rax
+ 	lretq
+@@ -73,6 +78,10 @@ SYM_FUNC_START(__efi64_thunk)
+ 	movl	%ebx, %es
+ 	pop	%rbx
+ 	movl	%ebx, %ds
++	/* Clear out 32-bit selector from FS and GS */
++	xorl	%ebx, %ebx
++	movl	%ebx, %fs
++	movl	%ebx, %gs
+ 
+ 	/*
+ 	 * Convert 32-bit status code into 64-bit.
+@@ -92,10 +101,12 @@ SYM_FUNC_END(__efi64_thunk)
+  * The stack should represent the 32-bit calling convention.
+  */
+ SYM_FUNC_START_LOCAL(efi_enter32)
+-	movl	$__KERNEL_DS, %eax
+-	movl	%eax, %ds
+-	movl	%eax, %es
+-	movl	%eax, %ss
++	/* Load firmware selector into data and stack segment registers */
++	movl	%edx, %ds
++	movl	%edx, %es
++	movl	%edx, %fs
++	movl	%edx, %gs
++	movl	%edx, %ss
+ 
+ 	/* Reload pgtables */
+ 	movl	%cr3, %eax
+@@ -157,6 +168,14 @@ SYM_DATA_START(efi32_boot_gdt)
+ 	.quad	0
+ SYM_DATA_END(efi32_boot_gdt)
+ 
++SYM_DATA_START(efi32_boot_cs)
++	.word	0
++SYM_DATA_END(efi32_boot_cs)
++
++SYM_DATA_START(efi32_boot_ds)
++	.word	0
++SYM_DATA_END(efi32_boot_ds)
++
+ SYM_DATA_START(efi_gdt64)
+ 	.word	efi_gdt64_end - efi_gdt64
+ 	.long	0			/* Filled out by user */
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index bd44d89540d3..c56b30bd9c7b 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -54,10 +54,6 @@ SYM_FUNC_START(startup_32)
+ 	 */
+ 	cld
+ 	cli
+-	movl	$(__BOOT_DS), %eax
+-	movl	%eax, %ds
+-	movl	%eax, %es
+-	movl	%eax, %ss
+ 
+ /*
+  * Calculate the delta between where we were compiled to run
+@@ -72,10 +68,20 @@ SYM_FUNC_START(startup_32)
+ 1:	popl	%ebp
+ 	subl	$1b, %ebp
+ 
++	/* Load new GDT with the 64bit segments using 32bit descriptor */
++	addl	%ebp, gdt+2(%ebp)
++	lgdt	gdt(%ebp)
++
++	/* Load segment registers with our descriptors */
++	movl	$__BOOT_DS, %eax
++	movl	%eax, %ds
++	movl	%eax, %es
++	movl	%eax, %fs
++	movl	%eax, %gs
++	movl	%eax, %ss
++
+ /* setup a stack and make sure cpu supports long mode. */
+-	movl	$boot_stack_end, %eax
+-	addl	%ebp, %eax
+-	movl	%eax, %esp
++	leal	boot_stack_end(%ebp), %esp
+ 
+ 	call	verify_cpu
+ 	testl	%eax, %eax
+@@ -112,10 +118,6 @@ SYM_FUNC_START(startup_32)
+  * Prepare for entering 64 bit mode
+  */
+ 
+-	/* Load new GDT with the 64bit segments using 32bit descriptor */
+-	addl	%ebp, gdt+2(%ebp)
+-	lgdt	gdt(%ebp)
+-
+ 	/* Enable PAE mode */
+ 	movl	%cr4, %eax
+ 	orl	$X86_CR4_PAE, %eax
+@@ -232,9 +234,13 @@ SYM_FUNC_START(efi32_stub_entry)
+ 
+ 	movl	%ecx, efi32_boot_args(%ebp)
+ 	movl	%edx, efi32_boot_args+4(%ebp)
+-	sgdtl	efi32_boot_gdt(%ebp)
+ 	movb	$0, efi_is64(%ebp)
+ 
++	/* Save firmware GDTR and code/data selectors */
++	sgdtl	efi32_boot_gdt(%ebp)
++	movw	%cs, efi32_boot_cs(%ebp)
++	movw	%ds, efi32_boot_ds(%ebp)
++
+ 	/* Disable paging */
+ 	movl	%cr0, %eax
+ 	btrl	$X86_CR0_PG_BIT, %eax

commit 67a6af7ad1d161dbc9c139e868d5549e632923f7
+Author: Arvind Sankar 
+Date:   Sun Feb 2 12:13:47 2020 -0500
+
+    x86/boot: Remove KEEP_SEGMENTS support
+    
+    Commit a24e785111a3 ("i386: paravirt boot sequence") added this flag for
+    use by paravirtualized environments such as Xen. However, Xen never made
+    use of this flag [1], and it was only ever used by lguest [2].
+    
+    Commit ecda85e70277 ("x86/lguest: Remove lguest support") removed
+    lguest, so KEEP_SEGMENTS has lost its last user.
+    
+    [1] https://lore.kernel.org/lkml/4D4B097C.5050405@goop.org
+    [2] https://www.mail-archive.com/lguest@lists.ozlabs.org/msg00469.html
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20200202171353.3736319-2-nivedita@alum.mit.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/Documentation/x86/boot.rst b/Documentation/x86/boot.rst
+index c9c201596c3e..fa7ddc0428c8 100644
+--- a/Documentation/x86/boot.rst
++++ b/Documentation/x86/boot.rst
+@@ -490,15 +490,11 @@ Protocol:	2.00+
+ 		kernel) to not write early messages that require
+ 		accessing the display hardware directly.
+ 
+-  Bit 6 (write): KEEP_SEGMENTS
++  Bit 6 (obsolete): KEEP_SEGMENTS
+ 
+ 	Protocol: 2.07+
+ 
+-	- If 0, reload the segment registers in the 32bit entry point.
+-	- If 1, do not reload the segment registers in the 32bit entry point.
+-
+-		Assume that %cs %ds %ss %es are all set to flat segments with
+-		a base of 0 (or the equivalent for their environment).
++        - This flag is obsolete.
+ 
+   Bit 7 (write): CAN_USE_HEAP
+ 
+diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
+index 73f17d0544dd..cb2cb91fce45 100644
+--- a/arch/x86/boot/compressed/head_32.S
++++ b/arch/x86/boot/compressed/head_32.S
+@@ -63,13 +63,6 @@
+ 	__HEAD
+ SYM_FUNC_START(startup_32)
+ 	cld
+-	/*
+-	 * Test KEEP_SEGMENTS flag to see if the bootloader is asking
+-	 * us to not reload segments
+-	 */
+-	testb	$KEEP_SEGMENTS, BP_loadflags(%esi)
+-	jnz	1f
+-
+ 	cli
+ 	movl	$__BOOT_DS, %eax
+ 	movl	%eax, %ds
+@@ -77,7 +70,6 @@ SYM_FUNC_START(startup_32)
+ 	movl	%eax, %fs
+ 	movl	%eax, %gs
+ 	movl	%eax, %ss
+-1:
+ 
+ /*
+  * Calculate the delta between where we were compiled to run
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index 1f1f6c8139b3..bd44d89540d3 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -53,19 +53,11 @@ SYM_FUNC_START(startup_32)
+ 	 * all need to be under the 4G limit.
+ 	 */
+ 	cld
+-	/*
+-	 * Test KEEP_SEGMENTS flag to see if the bootloader is asking
+-	 * us to not reload segments
+-	 */
+-	testb $KEEP_SEGMENTS, BP_loadflags(%esi)
+-	jnz 1f
+-
+ 	cli
+ 	movl	$(__BOOT_DS), %eax
+ 	movl	%eax, %ds
+ 	movl	%eax, %es
+ 	movl	%eax, %ss
+-1:
+ 
+ /*
+  * Calculate the delta between where we were compiled to run
+diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
+index 3923ab4630d7..f66a6b90f954 100644
+--- a/arch/x86/kernel/head_32.S
++++ b/arch/x86/kernel/head_32.S
+@@ -67,11 +67,6 @@ __HEAD
+ SYM_CODE_START(startup_32)
+ 	movl pa(initial_stack),%ecx
+ 	
+-	/* test KEEP_SEGMENTS flag to see if the bootloader is asking
+-		us to not reload segments */
+-	testb $KEEP_SEGMENTS, BP_loadflags(%esi)
+-	jnz 2f
+-
+ /*
+  * Set segments to known values.
+  */
+@@ -82,7 +77,6 @@ SYM_CODE_START(startup_32)
+ 	movl %eax,%fs
+ 	movl %eax,%gs
+ 	movl %eax,%ss
+-2:
+ 	leal -__PAGE_OFFSET(%ecx),%esp
+ 
+ /*

commit 3ee372ccce4d4e7c610748d0583979d3ed3a0cf4
+Author: Arvind Sankar 
+Date:   Thu Jan 9 10:02:17 2020 -0500
+
+    x86/boot/compressed/64: Remove .bss/.pgtable from bzImage
+    
+    Commit
+    
+      5b11f1cee579 ("x86, boot: straighten out ranges to copy/zero in
+      compressed/head*.S")
+    
+    introduced a separate .pgtable section, splitting it out from the rest
+    of .bss. This section was added without the writeable flag, marking it
+    as read-only. This results in the linker putting the .rela.dyn section
+    (containing bogus dynamic relocations from head_64.o) after the .bss and
+    .pgtable sections.
+    
+    When objcopy is used to convert compressed/vmlinux into a binary for
+    the bzImage:
+    
+    $ objcopy  -O binary -R .note -R .comment -S arch/x86/boot/compressed/vmlinux \
+                    arch/x86/boot/vmlinux.bin
+    
+    the .bss and .pgtable sections get materialized as ~176KiB of zero
+    bytes in the binary in order to place .rela.dyn at the correct location.
+    
+    Fix this by marking .pgtable as writeable. This moves the .rela.dyn
+    section up in the ELF image layout so that .bss and .pgtable are the
+    last allocated sections and so don't appear in bzImage.
+    
+     [ bp: Massage commit message. ]
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Borislav Petkov 
+    Acked-by: Kees Cook 
+    Link: https://lkml.kernel.org/r/20200109150218.16544-1-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index 68f31c48d6c2..c8ee6eff13ef 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -645,7 +645,7 @@ SYM_DATA_END_LABEL(boot_stack, SYM_L_LOCAL, boot_stack_end)
+ /*
+  * Space for page tables (not in .bss so not zeroed)
+  */
+-	.section ".pgtable","a",@nobits
++	.section ".pgtable","aw",@nobits
+ 	.balign 4096
+ SYM_DATA_LOCAL(pgtable,		.fill BOOT_PGT_SIZE, 1, 0)
+ 

commit a86255fe5258714e1f7c1bdfe95f08e4d098d450
+Author: Arvind Sankar 
+Date:   Tue Feb 11 12:33:33 2020 -0500
+
+    x86/boot/compressed/64: Use 32-bit (zero-extended) MOV for z_output_len
+    
+    z_output_len is the size of the decompressed payload (i.e. vmlinux +
+    vmlinux.relocs) and is generated as an unsigned 32-bit quantity by
+    mkpiggy.c.
+    
+    The current
+    
+      movq $z_output_len, %r9
+    
+    instruction generates a sign-extended move to %r9. Using
+    
+      movl $z_output_len, %r9d
+    
+    will instead zero-extend into %r9, which is appropriate for an unsigned
+    32-bit quantity. This is also what is already done for z_input_len, the
+    size of the compressed payload.
+    
+    [ bp:
+    
+      Also, z_output_len cannot be a 64-bit quantity because it participates
+      in:
+    
+      init_size:              .long INIT_SIZE         # kernel initialization size
+    
+      through INIT_SIZE which is a 32-bit quantity determined by the .long
+      directive (vs .quad for 64-bit). Furthermore, if it really must be a
+      64-bit quantity, then the insn must be MOVABS which can accommodate a
+      64-bit immediate and which the toolchain does not generate automatically.
+    ]
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Borislav Petkov 
+    Link: https://lkml.kernel.org/r/20200211173333.1722739-1-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index d1220de1de52..68f31c48d6c2 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -482,7 +482,7 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
+ 	leaq	input_data(%rip), %rdx  /* input_data */
+ 	movl	$z_input_len, %ecx	/* input_len */
+ 	movq	%rbp, %r8		/* output target address */
+-	movq	$z_output_len, %r9	/* decompressed length, end of relocs */
++	movl	$z_output_len, %r9d	/* decompressed length, end of relocs */
+ 	call	extract_kernel		/* returns kernel location in %rax */
+ 	popq	%rsi
+ 

commit 48bfdb9deffdc6b683feb25e15f4f26aac503501
+Author: Arvind Sankar 
+Date:   Tue Jan 7 14:44:35 2020 -0500
+
+    x86/boot/compressed/64: Use LEA to initialize boot stack pointer
+    
+    It's shorter, and it's what is used in every other place, so make it
+    consistent.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Borislav Petkov 
+    Link: https://lkml.kernel.org/r/20200107194436.2166846-2-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index 1f1f6c8139b3..d1220de1de52 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -81,9 +81,7 @@ SYM_FUNC_START(startup_32)
+ 	subl	$1b, %ebp
+ 
+ /* setup a stack and make sure cpu supports long mode. */
+-	movl	$boot_stack_end, %eax
+-	addl	%ebp, %eax
+-	movl	%eax, %esp
++	leal	boot_stack_end(%ebp), %esp
+ 
+ 	call	verify_cpu
+ 	testl	%eax, %eax

commit 93f9d1a4ac5930654c17412e3911b46ece73755a
+Author: Arvind Sankar 
+Date:   Tue Feb 11 11:22:35 2020 -0500
+
+    ALSA: usb-audio: Apply sample rate quirk for Audioengine D1
+    
+    The Audioengine D1 (0x2912:0x30c8) does support reading the sample rate,
+    but it returns the rate in byte-reversed order.
+    
+    When setting sampling rate, the driver produces these warning messages:
+    [168840.944226] usb 3-2.2: current rate 4500480 is different from the runtime rate 44100
+    [168854.930414] usb 3-2.2: current rate 8436480 is different from the runtime rate 48000
+    [168905.185825] usb 3-2.1.2: current rate 30465 is different from the runtime rate 96000
+    
+    As can be seen from the hexadecimal conversion, the current rate read
+    back is byte-reversed from the rate that was set.
+    
+    44100 == 0x00ac44, 4500480 == 0x44ac00
+    48000 == 0x00bb80, 8436480 == 0x80bb00
+    96000 == 0x017700,   30465 == 0x007701
+    
+    Rather than implementing a new quirk to reverse the order, just skip
+    checking the rate to avoid spamming the log.
+    
+    Signed-off-by: Arvind Sankar 
+    Cc: 
+    Link: https://lore.kernel.org/r/20200211162235.1639889-1-nivedita@alum.mit.edu
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
+index 3a5242e383b2..7f558f4b4520 100644
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -1440,6 +1440,7 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip)
+ 	case USB_ID(0x1395, 0x740a): /* Sennheiser DECT */
+ 	case USB_ID(0x1901, 0x0191): /* GE B850V3 CP2114 audio interface */
+ 	case USB_ID(0x21b4, 0x0081): /* AudioQuest DragonFly */
++	case USB_ID(0x2912, 0x30c8): /* Audioengine D1 */
+ 		return true;
+ 	}
+ 

commit 283900e82847e10898650c66a249c10b213934fb
+Author: Arvind Sankar 
+Date:   Thu Jan 30 22:17:19 2020 -0800
+
+    init/main.c: fix quoted value handling in unknown_bootoption
+    
+    Patch series "init/main.c: minor cleanup/bugfix of envvar handling", v2.
+    
+    unknown_bootoption passes unrecognized command line arguments to init as
+    either environment variables or arguments.  Some of the logic in the
+    function is broken for quoted command line arguments.
+    
+    When an argument of the form param="value" is processed by parse_args
+    and passed to unknown_bootoption, the command line has
+    
+      param\0"value\0
+    
+    with val pointing to the beginning of value.  The helper function
+    repair_env_string is then used to restore the '=' character that was
+    removed by parse_args, and strip the quotes off fully.  This results in
+    
+      param=value\0\0
+    
+    and val ends up pointing to the 'a' instead of the 'v' in value.  This
+    bug was introduced when repair_env_string was refactored into a separate
+    function, and the decrement of val in repair_env_string became dead
+    code.
+    
+    This causes two problems in unknown_bootoption in the two places where
+    the val pointer is used as a substitute for the length of param:
+    
+    1. An argument of the form param=".value" is misinterpreted as a
+       potential module parameter, with the result that it will not be
+       placed in init's environment.
+    
+    2. An argument of the form param="value" is checked to see if param is
+       an existing environment variable that should be overwritten, but the
+       comparison is off-by-one and compares 'param=v' instead of 'param='
+       against the existing environment. So passing, for example,
+       TERM="vt100" on the command line results in init being passed both
+       TERM=linux and TERM=vt100 in its environment.
+    
+    Patch 1 adds logging for the arguments and environment passed to init
+    and is independent of the rest: it can be dropped if this is
+    unnecessarily verbose.
+    
+    Patch 2 removes repair_env_string from initcall parameter parsing in
+    do_initcall_level, as that uses a separate copy of the command line now
+    and the repairing is no longer necessary.
+    
+    Patch 3 fixes the bug in unknown_bootoption by recording the length of
+    param explicitly instead of implying it from val-param.
+    
+    This patch (of 3):
+    
+    Commit a99cd1125189 ("init: fix bug where environment vars can't be
+    passed via boot args") introduced two minor bugs in unknown_bootoption
+    by factoring out the quoted value handling into a separate function.
+    
+    When value is quoted, repair_env_string will move the value up 1 byte to
+    strip the quotes, so val in unknown_bootoption no longer points to the
+    actual location of the value.
+    
+    The result is that an argument of the form param=".value" is mistakenly
+    treated as a potential module parameter and is not placed in init's
+    environment, and an argument of the form param="value" can result in a
+    duplicate environment variable: eg TERM="vt100" on the command line will
+    result in both TERM=linux and TERM=vt100 being placed into init's
+    environment.
+    
+    Fix this by recording the length of the param before calling
+    repair_env_string instead of relying on val.
+    
+    Link: http://lkml.kernel.org/r/20191212180023.24339-4-nivedita@alum.mit.edu
+    Signed-off-by: Arvind Sankar 
+    Cc: Chris Metcalf 
+    Cc: Krzysztof Mazur 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/init/main.c b/init/main.c
+index 51fced4ca87a..75eded9aafb0 100644
+--- a/init/main.c
++++ b/init/main.c
+@@ -255,7 +255,6 @@ static void __init repair_env_string(char *param, char *val)
+ 		else if (val == param+strlen(param)+2) {
+ 			val[-2] = '=';
+ 			memmove(val-1, val, strlen(val)+1);
+-			val--;
+ 		} else
+ 			BUG();
+ 	}
+@@ -290,6 +289,8 @@ static int __init set_init_arg(char *param, char *val,
+ static int __init unknown_bootoption(char *param, char *val,
+ 				     const char *unused, void *arg)
+ {
++	size_t len = strlen(param);
++
+ 	repair_env_string(param, val);
+ 
+ 	/* Handle obsolete-style parameters */
+@@ -297,7 +298,7 @@ static int __init unknown_bootoption(char *param, char *val,
+ 		return 0;
+ 
+ 	/* Unused module parameter. */
+-	if (strchr(param, '.') && (!val || strchr(param, '.') < val))
++	if (strnchr(param, len, '.'))
+ 		return 0;
+ 
+ 	if (panic_later)
+@@ -311,7 +312,7 @@ static int __init unknown_bootoption(char *param, char *val,
+ 				panic_later = "env";
+ 				panic_param = param;
+ 			}
+-			if (!strncmp(param, envp_init[i], val - param))
++			if (!strncmp(param, envp_init[i], len+1))
+ 				break;
+ 		}
+ 		envp_init[i] = param;

commit 7e2762e1d9f4b9cb67ed6c3b7aff2020c367d4ac
+Author: Arvind Sankar 
+Date:   Thu Jan 30 22:17:16 2020 -0800
+
+    init/main.c: remove unnecessary repair_env_string in do_initcall_level
+    
+    Since commit 08746a65c296 ("init: fix in-place parameter modification
+    regression"), parse_args in do_initcall_level is called on a copy of
+    saved_command_line.  It is unnecessary to call repair_env_string during
+    this parsing, as this copy is not used for anything later.
+    
+    Remove the now unnecessary arguments from repair_env_string as well.
+    
+    Link: http://lkml.kernel.org/r/20191212180023.24339-3-nivedita@alum.mit.edu
+    Signed-off-by: Arvind Sankar 
+    Cc: Krzysztof Mazur 
+    Cc: Chris Metcalf 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/init/main.c b/init/main.c
+index 424d88fef08e..51fced4ca87a 100644
+--- a/init/main.c
++++ b/init/main.c
+@@ -246,8 +246,7 @@ static int __init loglevel(char *str)
+ early_param("loglevel", loglevel);
+ 
+ /* Change NUL term back to "=", to make "param" the whole string. */
+-static int __init repair_env_string(char *param, char *val,
+-				    const char *unused, void *arg)
++static void __init repair_env_string(char *param, char *val)
+ {
+ 	if (val) {
+ 		/* param=val or param="val"? */
+@@ -260,7 +259,6 @@ static int __init repair_env_string(char *param, char *val,
+ 		} else
+ 			BUG();
+ 	}
+-	return 0;
+ }
+ 
+ /* Anything after -- gets handed straight to init. */
+@@ -272,7 +270,7 @@ static int __init set_init_arg(char *param, char *val,
+ 	if (panic_later)
+ 		return 0;
+ 
+-	repair_env_string(param, val, unused, NULL);
++	repair_env_string(param, val);
+ 
+ 	for (i = 0; argv_init[i]; i++) {
+ 		if (i == MAX_INIT_ARGS) {
+@@ -292,7 +290,7 @@ static int __init set_init_arg(char *param, char *val,
+ static int __init unknown_bootoption(char *param, char *val,
+ 				     const char *unused, void *arg)
+ {
+-	repair_env_string(param, val, unused, NULL);
++	repair_env_string(param, val);
+ 
+ 	/* Handle obsolete-style parameters */
+ 	if (obsolete_checksetup(param))
+@@ -991,6 +989,12 @@ static const char *initcall_level_names[] __initdata = {
+ 	"late",
+ };
+ 
++static int __init ignore_unknown_bootoption(char *param, char *val,
++			       const char *unused, void *arg)
++{
++	return 0;
++}
++
+ static void __init do_initcall_level(int level)
+ {
+ 	initcall_entry_t *fn;
+@@ -1000,7 +1004,7 @@ static void __init do_initcall_level(int level)
+ 		   initcall_command_line, __start___param,
+ 		   __stop___param - __start___param,
+ 		   level, level,
+-		   NULL, &repair_env_string);
++		   NULL, ignore_unknown_bootoption);
+ 
+ 	trace_initcall_level(initcall_level_names[level]);
+ 	for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)

commit b88c50ac304a14f14e70c4ad22577b6b84632d5e
+Author: Arvind Sankar 
+Date:   Thu Jan 30 22:17:13 2020 -0800
+
+    init/main.c: log arguments and environment passed to init
+    
+    Extend logging in `run_init_process` to also show the arguments and
+    environment that we are passing to init.
+    
+    Link: http://lkml.kernel.org/r/20191212180023.24339-2-nivedita@alum.mit.edu
+    Signed-off-by: Arvind Sankar 
+    Cc: Chris Metcalf 
+    Cc: Krzysztof Mazur 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/init/main.c b/init/main.c
+index db13a76c036e..424d88fef08e 100644
+--- a/init/main.c
++++ b/init/main.c
+@@ -1043,8 +1043,16 @@ static void __init do_pre_smp_initcalls(void)
+ 
+ static int run_init_process(const char *init_filename)
+ {
++	const char *const *p;
++
+ 	argv_init[0] = init_filename;
+ 	pr_info("Run %s as init process\n", init_filename);
++	pr_debug("  with arguments:\n");
++	for (p = argv_init; *p; p++)
++		pr_debug("    %s\n", *p);
++	pr_debug("  with environment:\n");
++	for (p = envp_init; *p; p++)
++		pr_debug("    %s\n", *p);
+ 	return do_execve(getname_kernel(init_filename),
+ 		(const char __user *const __user *)argv_init,
+ 		(const char __user *const __user *)envp_init);

commit 183ef7adf4ed638ac0fb0c3c9a71fc00e8512b61
+Author: Arvind Sankar 
+Date:   Tue Jan 7 14:44:34 2020 -0500
+
+    x86/boot: Simplify calculation of output address
+    
+    Condense the calculation of decompressed kernel start a little.
+    
+    Committer notes:
+    
+    before:
+    
+    ebp = ebx - (init_size - _end)
+    
+    after:
+    
+    eax = (ebx + _end) - init_size
+    
+    where in both ebx contains the temporary address the kernel is moved to
+    for in-place decompression.
+    
+    The before and after difference in register state is %eax and %ebp
+    but that is immaterial because the compressed image is not built with
+    -mregparm, i.e., all arguments of the following extract_kernel() call
+    are passed on the stack.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Borislav Petkov 
+    Link: https://lkml.kernel.org/r/20200107194436.2166846-1-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
+index f2dfd6d083ef..1cc55c79d1d0 100644
+--- a/arch/x86/boot/compressed/head_32.S
++++ b/arch/x86/boot/compressed/head_32.S
+@@ -240,11 +240,9 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
+ 				/* push arguments for extract_kernel: */
+ 	pushl	$z_output_len	/* decompressed length, end of relocs */
+ 
+-	movl    BP_init_size(%esi), %eax
+-	subl    $_end, %eax
+-	movl    %ebx, %ebp
+-	subl    %eax, %ebp
+-	pushl	%ebp		/* output address */
++	leal	_end(%ebx), %eax
++	subl    BP_init_size(%esi), %eax
++	pushl	%eax		/* output address */
+ 
+ 	pushl	$z_input_len	/* input_len */
+ 	leal	input_data(%ebx), %eax

commit 9167bd96346473de5b61124f4589949fdf3026cf
+Author: Arvind Sankar 
+Date:   Wed Jan 15 11:07:50 2020 -0500
+
+    sparc/console: kill off obsolete declarations
+    
+    commit 09d3f3f0e02c ("sparc: Kill PROM console driver.") missed removing
+    the declarations of the deleted prom_con structure and prom_con_init
+    function from console.h. Kill them off now.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: David S. Miller 
+
+diff --git a/include/linux/console.h b/include/linux/console.h
+index d09951d5a94e..f33016b3a401 100644
+--- a/include/linux/console.h
++++ b/include/linux/console.h
+@@ -101,7 +101,6 @@ extern const struct consw *conswitchp;
+ extern const struct consw dummy_con;	/* dummy console buffer */
+ extern const struct consw vga_con;	/* VGA text console */
+ extern const struct consw newport_con;	/* SGI Newport console  */
+-extern const struct consw prom_con;	/* SPARC PROM console */
+ 
+ int con_is_bound(const struct consw *csw);
+ int do_unregister_con_driver(const struct consw *csw);
+@@ -201,7 +200,6 @@ extern void suspend_console(void);
+ extern void resume_console(void);
+ 
+ int mda_console_init(void);
+-void prom_con_init(void);
+ 
+ void vcs_make_sysfs(int index);
+ void vcs_remove_sysfs(int index);

commit dacc9092336be20b01642afe1a51720b31f60369
+Author: Arvind Sankar 
+Date:   Tue Jan 7 18:04:10 2020 -0500
+
+    x86/sysfb: Fix check for bad VRAM size
+    
+    When checking whether the reported lfb_size makes sense, the height
+    * stride result is page-aligned before seeing whether it exceeds the
+    reported size.
+    
+    This doesn't work if height * stride is not an exact number of pages.
+    For example, as reported in the kernel bugzilla below, an 800x600x32 EFI
+    framebuffer gets skipped because of this.
+    
+    Move the PAGE_ALIGN to after the check vs size.
+    
+    Reported-by: Christopher Head 
+    Tested-by: Christopher Head 
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Borislav Petkov 
+    Link: https://bugzilla.kernel.org/show_bug.cgi?id=206051
+    Link: https://lkml.kernel.org/r/20200107230410.2291947-1-nivedita@alum.mit.edu
+
+diff --git a/arch/x86/kernel/sysfb_simplefb.c b/arch/x86/kernel/sysfb_simplefb.c
+index 01f0e2263b86..298fc1edd9c9 100644
+--- a/arch/x86/kernel/sysfb_simplefb.c
++++ b/arch/x86/kernel/sysfb_simplefb.c
+@@ -90,11 +90,11 @@ __init int create_simplefb(const struct screen_info *si,
+ 	if (si->orig_video_isVGA == VIDEO_TYPE_VLFB)
+ 		size <<= 16;
+ 	length = mode->height * mode->stride;
+-	length = PAGE_ALIGN(length);
+ 	if (length > size) {
+ 		printk(KERN_WARNING "sysfb: VRAM smaller than advertised\n");
+ 		return -EINVAL;
+ 	}
++	length = PAGE_ALIGN(length);
+ 
+ 	/* setup IORESOURCE_MEM as framebuffer memory */
+ 	memset(&res, 0, sizeof(res));

commit 131992709dc4c6140cec3b352f820cb873f7dd50
+Author: Ilia Mirkin 
+Date:   Fri Sep 6 00:13:59 2019 -0400
+
+    drm/nouveau/kms/gf119-: allow both 256- and 1024-sized LUTs to be used
+    
+    The hardware supports either size. Also add checks to ensure that only
+    these two sizes may be used for supplying a LUT.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/base907c.c b/drivers/gpu/drm/nouveau/dispnv50/base907c.c
+index 5f2de77e0f32..224a34c340fe 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/base907c.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/base907c.c
+@@ -75,12 +75,16 @@ base907c_xlut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+ 	}
+ }
+ 
+-static void
+-base907c_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
++static bool
++base907c_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, int size)
+ {
+-	asyw->xlut.i.mode = 7;
++	if (size != 256 && size != 1024)
++		return false;
++
++	asyw->xlut.i.mode = size == 1024 ? 4 : 7;
+ 	asyw->xlut.i.enable = 2;
+ 	asyw->xlut.i.load = head907d_olut_load;
++	return true;
+ }
+ 
+ static inline u32
+@@ -160,6 +164,7 @@ base907c = {
+ 	.csc_set = base907c_csc_set,
+ 	.csc_clr = base907c_csc_clr,
+ 	.olut_core = true,
++	.ilut_size = 1024,
+ 	.xlut_set = base907c_xlut_set,
+ 	.xlut_clr = base907c_xlut_clr,
+ 	.image_set = base907c_image_set,
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c
+index c9692df2b76c..f64c87dfc1d0 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/head.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/head.c
+@@ -213,6 +213,7 @@ nv50_head_atomic_check_lut(struct nv50_head *head,
+ {
+ 	struct nv50_disp *disp = nv50_disp(head->base.base.dev);
+ 	struct drm_property_blob *olut = asyh->state.gamma_lut;
++	int size;
+ 
+ 	/* Determine whether core output LUT should be enabled. */
+ 	if (olut) {
+@@ -229,14 +230,23 @@ nv50_head_atomic_check_lut(struct nv50_head *head,
+ 		}
+ 	}
+ 
+-	if (!olut && !head->func->olut_identity) {
+-		asyh->olut.handle = 0;
+-		return 0;
++	if (!olut) {
++		if (!head->func->olut_identity) {
++			asyh->olut.handle = 0;
++			return 0;
++		}
++		size = 0;
++	} else {
++		size = drm_color_lut_size(olut);
+ 	}
+ 
++	if (!head->func->olut(head, asyh, size)) {
++		DRM_DEBUG_KMS("Invalid olut\n");
++		return -EINVAL;
++	}
+ 	asyh->olut.handle = disp->core->chan.vram.handle;
+ 	asyh->olut.buffer = !asyh->olut.buffer;
+-	head->func->olut(head, asyh);
++
+ 	return 0;
+ }
+ 
+@@ -510,11 +520,11 @@ nv50_head_create(struct drm_device *dev, int index)
+ 	drm_crtc_init_with_planes(dev, crtc, &base->plane, &curs->plane,
+ 				  &nv50_head_func, "head-%d", head->base.index);
+ 	drm_crtc_helper_add(crtc, &nv50_head_help);
++	/* Keep the legacy gamma size at 256 to avoid compatibility issues */
+ 	drm_mode_crtc_set_gamma_size(crtc, 256);
+-	if (disp->disp->object.oclass >= GF110_DISP)
+-		drm_crtc_enable_color_mgmt(crtc, 256, true, 256);
+-	else
+-		drm_crtc_enable_color_mgmt(crtc, 0, false, 256);
++	drm_crtc_enable_color_mgmt(crtc, base->func->ilut_size,
++				   disp->disp->object.oclass >= GF110_DISP,
++				   head->func->olut_size);
+ 
+ 	if (head->func->olut_set) {
+ 		ret = nv50_lut_init(disp, &drm->client.mmu, &head->olut);
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.h b/drivers/gpu/drm/nouveau/dispnv50/head.h
+index d1c002f534d4..5c2cda2f32a8 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/head.h
++++ b/drivers/gpu/drm/nouveau/dispnv50/head.h
+@@ -20,8 +20,9 @@ void nv50_head_flush_clr(struct nv50_head *, struct nv50_head_atom *, bool y);
+ struct nv50_head_func {
+ 	void (*view)(struct nv50_head *, struct nv50_head_atom *);
+ 	void (*mode)(struct nv50_head *, struct nv50_head_atom *);
+-	void (*olut)(struct nv50_head *, struct nv50_head_atom *);
++	bool (*olut)(struct nv50_head *, struct nv50_head_atom *, int);
+ 	bool olut_identity;
++	int  olut_size;
+ 	void (*olut_set)(struct nv50_head *, struct nv50_head_atom *);
+ 	void (*olut_clr)(struct nv50_head *);
+ 	void (*core_calc)(struct nv50_head *, struct nv50_head_atom *);
+@@ -43,7 +44,7 @@ struct nv50_head_func {
+ extern const struct nv50_head_func head507d;
+ void head507d_view(struct nv50_head *, struct nv50_head_atom *);
+ void head507d_mode(struct nv50_head *, struct nv50_head_atom *);
+-void head507d_olut(struct nv50_head *, struct nv50_head_atom *);
++bool head507d_olut(struct nv50_head *, struct nv50_head_atom *, int);
+ void head507d_core_calc(struct nv50_head *, struct nv50_head_atom *);
+ void head507d_core_clr(struct nv50_head *);
+ int head507d_curs_layout(struct nv50_head *, struct nv50_wndw_atom *,
+@@ -60,7 +61,7 @@ extern const struct nv50_head_func head827d;
+ extern const struct nv50_head_func head907d;
+ void head907d_view(struct nv50_head *, struct nv50_head_atom *);
+ void head907d_mode(struct nv50_head *, struct nv50_head_atom *);
+-void head907d_olut(struct nv50_head *, struct nv50_head_atom *);
++bool head907d_olut(struct nv50_head *, struct nv50_head_atom *, int);
+ void head907d_olut_set(struct nv50_head *, struct nv50_head_atom *);
+ void head907d_olut_clr(struct nv50_head *);
+ void head907d_core_set(struct nv50_head *, struct nv50_head_atom *);
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/head507d.c b/drivers/gpu/drm/nouveau/dispnv50/head507d.c
+index 7561be5ca707..66ccf36b56a2 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/head507d.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/head507d.c
+@@ -271,15 +271,19 @@ head507d_olut_load(struct drm_color_lut *in, int size, void __iomem *mem)
+ 	writew(readw(mem - 4), mem + 4);
+ }
+ 
+-void
+-head507d_olut(struct nv50_head *head, struct nv50_head_atom *asyh)
++bool
++head507d_olut(struct nv50_head *head, struct nv50_head_atom *asyh, int size)
+ {
++	if (size != 256)
++		return false;
++
+ 	if (asyh->base.cpp == 1)
+ 		asyh->olut.mode = 0;
+ 	else
+ 		asyh->olut.mode = 1;
+ 
+ 	asyh->olut.load = head507d_olut_load;
++	return true;
+ }
+ 
+ void
+@@ -328,6 +332,7 @@ head507d = {
+ 	.view = head507d_view,
+ 	.mode = head507d_mode,
+ 	.olut = head507d_olut,
++	.olut_size = 256,
+ 	.olut_set = head507d_olut_set,
+ 	.olut_clr = head507d_olut_clr,
+ 	.core_calc = head507d_core_calc,
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/head827d.c b/drivers/gpu/drm/nouveau/dispnv50/head827d.c
+index af5e7bd5978b..11877119eea4 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/head827d.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/head827d.c
+@@ -108,6 +108,7 @@ head827d = {
+ 	.view = head507d_view,
+ 	.mode = head507d_mode,
+ 	.olut = head507d_olut,
++	.olut_size = 256,
+ 	.olut_set = head827d_olut_set,
+ 	.olut_clr = head827d_olut_clr,
+ 	.core_calc = head507d_core_calc,
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/head907d.c b/drivers/gpu/drm/nouveau/dispnv50/head907d.c
+index c2d09dd97b1f..3002ec23d7a6 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/head907d.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/head907d.c
+@@ -230,11 +230,15 @@ head907d_olut_load(struct drm_color_lut *in, int size, void __iomem *mem)
+ 	writew(readw(mem - 4), mem + 4);
+ }
+ 
+-void
+-head907d_olut(struct nv50_head *head, struct nv50_head_atom *asyh)
++bool
++head907d_olut(struct nv50_head *head, struct nv50_head_atom *asyh, int size)
+ {
+-	asyh->olut.mode = 7;
++	if (size != 256 && size != 1024)
++		return false;
++
++	asyh->olut.mode = size == 1024 ? 4 : 7;
+ 	asyh->olut.load = head907d_olut_load;
++	return true;
+ }
+ 
+ void
+@@ -285,6 +289,7 @@ head907d = {
+ 	.view = head907d_view,
+ 	.mode = head907d_mode,
+ 	.olut = head907d_olut,
++	.olut_size = 1024,
+ 	.olut_set = head907d_olut_set,
+ 	.olut_clr = head907d_olut_clr,
+ 	.core_calc = head507d_core_calc,
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/head917d.c b/drivers/gpu/drm/nouveau/dispnv50/head917d.c
+index 303df8459ca8..76958cedd51f 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/head917d.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/head917d.c
+@@ -83,6 +83,7 @@ head917d = {
+ 	.view = head907d_view,
+ 	.mode = head907d_mode,
+ 	.olut = head907d_olut,
++	.olut_size = 1024,
+ 	.olut_set = head907d_olut_set,
+ 	.olut_clr = head907d_olut_clr,
+ 	.core_calc = head507d_core_calc,
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/headc37d.c b/drivers/gpu/drm/nouveau/dispnv50/headc37d.c
+index ef6a99d95a9c..00011ce109a6 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/headc37d.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/headc37d.c
+@@ -148,14 +148,18 @@ headc37d_olut_set(struct nv50_head *head, struct nv50_head_atom *asyh)
+ 	}
+ }
+ 
+-static void
+-headc37d_olut(struct nv50_head *head, struct nv50_head_atom *asyh)
++static bool
++headc37d_olut(struct nv50_head *head, struct nv50_head_atom *asyh, int size)
+ {
++	if (size != 256 && size != 1024)
++		return false;
++
+ 	asyh->olut.mode = 2;
+-	asyh->olut.size = 0;
++	asyh->olut.size = size == 1024 ? 2 : 0;
+ 	asyh->olut.range = 0;
+ 	asyh->olut.output_mode = 1;
+ 	asyh->olut.load = head907d_olut_load;
++	return true;
+ }
+ 
+ static void
+@@ -201,6 +205,7 @@ headc37d = {
+ 	.view = headc37d_view,
+ 	.mode = headc37d_mode,
+ 	.olut = headc37d_olut,
++	.olut_size = 1024,
+ 	.olut_set = headc37d_olut_set,
+ 	.olut_clr = headc37d_olut_clr,
+ 	.curs_layout = head917d_curs_layout,
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/headc57d.c b/drivers/gpu/drm/nouveau/dispnv50/headc57d.c
+index 32a7f9e85fb0..938d910a1b1e 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/headc57d.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/headc57d.c
+@@ -151,17 +151,20 @@ headc57d_olut_load(struct drm_color_lut *in, int size, void __iomem *mem)
+ 	writew(readw(mem - 4), mem + 4);
+ }
+ 
+-void
+-headc57d_olut(struct nv50_head *head, struct nv50_head_atom *asyh)
++bool
++headc57d_olut(struct nv50_head *head, struct nv50_head_atom *asyh, int size)
+ {
++	if (size != 0 && size != 256 && size != 1024)
++		return false;
++
+ 	asyh->olut.mode = 2; /* DIRECT10 */
+ 	asyh->olut.size = 4 /* VSS header. */ + 1024 + 1 /* Entries. */;
+ 	asyh->olut.output_mode = 1; /* INTERPOLATE_ENABLE. */
+-	if (asyh->state.gamma_lut &&
+-	    asyh->state.gamma_lut->length / sizeof(struct drm_color_lut) == 256)
++	if (size == 256)
+ 		asyh->olut.load = headc57d_olut_load_8;
+ 	else
+ 		asyh->olut.load = headc57d_olut_load;
++	return true;
+ }
+ 
+ static void
+@@ -194,6 +197,7 @@ headc57d = {
+ 	.mode = headc57d_mode,
+ 	.olut = headc57d_olut,
+ 	.olut_identity = true,
++	.olut_size = 1024,
+ 	.olut_set = headc57d_olut_set,
+ 	.olut_clr = headc57d_olut_clr,
+ 	.curs_layout = head917d_curs_layout,
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/lut.c b/drivers/gpu/drm/nouveau/dispnv50/lut.c
+index 994def4fd51a..4e95ca5604ab 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/lut.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/lut.c
+@@ -49,7 +49,7 @@ nv50_lut_load(struct nv50_lut *lut, int buffer, struct drm_property_blob *blob,
+ 			kvfree(in);
+ 		}
+ 	} else {
+-		load(in, blob->length / sizeof(*in), mem);
++		load(in, drm_color_lut_size(blob), mem);
+ 	}
+ 
+ 	return addr;
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
+index 5193b6257061..890315291b01 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
+@@ -318,7 +318,7 @@ nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw, bool modeset,
+ 	return wndw->func->acquire(wndw, asyw, asyh);
+ }
+ 
+-static void
++static int
+ nv50_wndw_atomic_check_lut(struct nv50_wndw *wndw,
+ 			   struct nv50_wndw_atom *armw,
+ 			   struct nv50_wndw_atom *asyw,
+@@ -340,7 +340,7 @@ nv50_wndw_atomic_check_lut(struct nv50_wndw *wndw,
+ 		 */
+ 		if (!(ilut = asyh->state.gamma_lut)) {
+ 			asyw->visible = false;
+-			return;
++			return 0;
+ 		}
+ 
+ 		if (wndw->func->ilut)
+@@ -359,7 +359,10 @@ nv50_wndw_atomic_check_lut(struct nv50_wndw *wndw,
+ 	/* Recalculate LUT state. */
+ 	memset(&asyw->xlut, 0x00, sizeof(asyw->xlut));
+ 	if ((asyw->ilut = wndw->func->ilut ? ilut : NULL)) {
+-		wndw->func->ilut(wndw, asyw);
++		if (!wndw->func->ilut(wndw, asyw, drm_color_lut_size(ilut))) {
++			DRM_DEBUG_KMS("Invalid ilut\n");
++			return -EINVAL;
++		}
+ 		asyw->xlut.handle = wndw->wndw.vram.handle;
+ 		asyw->xlut.i.buffer = !asyw->xlut.i.buffer;
+ 		asyw->set.xlut = true;
+@@ -384,6 +387,7 @@ nv50_wndw_atomic_check_lut(struct nv50_wndw *wndw,
+ 
+ 	/* Can't do an immediate flip while changing the LUT. */
+ 	asyh->state.async_flip = false;
++	return 0;
+ }
+ 
+ static int
+@@ -424,8 +428,11 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
+ 	    (!armw->visible ||
+ 	     asyh->state.color_mgmt_changed ||
+ 	     asyw->state.fb->format->format !=
+-	     armw->state.fb->format->format))
+-		nv50_wndw_atomic_check_lut(wndw, armw, asyw, asyh);
++	     armw->state.fb->format->format)) {
++		ret = nv50_wndw_atomic_check_lut(wndw, armw, asyw, asyh);
++		if (ret)
++			return ret;
++	}
+ 
+ 	/* Calculate new window state. */
+ 	if (asyw->visible) {
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.h b/drivers/gpu/drm/nouveau/dispnv50/wndw.h
+index c63bd3bdaf06..caf397475918 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/wndw.h
++++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.h
+@@ -64,12 +64,13 @@ struct nv50_wndw_func {
+ 	void (*ntfy_clr)(struct nv50_wndw *);
+ 	int (*ntfy_wait_begun)(struct nouveau_bo *, u32 offset,
+ 			       struct nvif_device *);
+-	void (*ilut)(struct nv50_wndw *, struct nv50_wndw_atom *);
++	bool (*ilut)(struct nv50_wndw *, struct nv50_wndw_atom *, int);
+ 	void (*csc)(struct nv50_wndw *, struct nv50_wndw_atom *,
+ 		    const struct drm_color_ctm *);
+ 	void (*csc_set)(struct nv50_wndw *, struct nv50_wndw_atom *);
+ 	void (*csc_clr)(struct nv50_wndw *);
+ 	bool ilut_identity;
++	int  ilut_size;
+ 	bool olut_core;
+ 	void (*xlut_set)(struct nv50_wndw *, struct nv50_wndw_atom *);
+ 	void (*xlut_clr)(struct nv50_wndw *);
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c b/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c
+index 0f9402162bde..b92dc3461bbd 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c
+@@ -71,14 +71,18 @@ wndwc37e_ilut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+ 	}
+ }
+ 
+-static void
+-wndwc37e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
++static bool
++wndwc37e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, int size)
+ {
++	if (size != 256 && size != 1024)
++		return false;
++
+ 	asyw->xlut.i.mode = 2;
+-	asyw->xlut.i.size = 0;
++	asyw->xlut.i.size = size == 1024 ? 2 : 0;
+ 	asyw->xlut.i.range = 0;
+ 	asyw->xlut.i.output_mode = 1;
+ 	asyw->xlut.i.load = head907d_olut_load;
++	return true;
+ }
+ 
+ void
+@@ -261,6 +265,7 @@ wndwc37e = {
+ 	.ntfy_reset = corec37d_ntfy_init,
+ 	.ntfy_wait_begun = base507c_ntfy_wait_begun,
+ 	.ilut = wndwc37e_ilut,
++	.ilut_size = 1024,
+ 	.xlut_set = wndwc37e_ilut_set,
+ 	.xlut_clr = wndwc37e_ilut_clr,
+ 	.csc = base907c_csc,
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c b/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c
+index a311c79e5295..35c9c52fab26 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c
+@@ -156,19 +156,21 @@ wndwc57e_ilut_load(struct drm_color_lut *in, int size, void __iomem *mem)
+ 	writew(readw(mem - 4), mem + 4);
+ }
+ 
+-static void
+-wndwc57e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
++static bool
++wndwc57e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, int size)
+ {
+-	u16 size = asyw->ilut->length / sizeof(struct drm_color_lut);
++	if (size = size ? size : 1024, size != 256 && size != 1024)
++		return false;
++
+ 	if (size == 256) {
+ 		asyw->xlut.i.mode = 1; /* DIRECT8. */
+ 	} else {
+ 		asyw->xlut.i.mode = 2; /* DIRECT10. */
+-		size = 1024;
+ 	}
+ 	asyw->xlut.i.size = 4 /* VSS header. */ + size + 1 /* Entries. */;
+ 	asyw->xlut.i.output_mode = 0; /* INTERPOLATE_DISABLE. */
+ 	asyw->xlut.i.load = wndwc57e_ilut_load;
++	return true;
+ }
+ 
+ static const struct nv50_wndw_func
+@@ -183,6 +185,7 @@ wndwc57e = {
+ 	.ntfy_wait_begun = base507c_ntfy_wait_begun,
+ 	.ilut = wndwc57e_ilut,
+ 	.ilut_identity = true,
++	.ilut_size = 1024,
+ 	.xlut_set = wndwc57e_ilut_set,
+ 	.xlut_clr = wndwc57e_ilut_clr,
+ 	.csc = base907c_csc,

commit fec6388946ee05508543f0e3e5d34f436384548f
+Author: Arvind Sankar 
+Date:   Wed Dec 18 16:45:06 2019 -0500
+
+    arch/xtensa/setup: Drop dummy_con initialization
+    
+    con_init in tty/vt.c will now set conswitchp to dummy_con if it's unset.
+    Drop it from arch setup code.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20191218214506.49252-25-nivedita@alum.mit.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
+index 0f93b67c7a5a..adead45debe8 100644
+--- a/arch/xtensa/kernel/setup.c
++++ b/arch/xtensa/kernel/setup.c
+@@ -405,8 +405,6 @@ void __init setup_arch(char **cmdline_p)
+ #ifdef CONFIG_VT
+ # if defined(CONFIG_VGA_CONSOLE)
+ 	conswitchp = &vga_con;
+-# elif defined(CONFIG_DUMMY_CONSOLE)
+-	conswitchp = &dummy_con;
+ # endif
+ #endif
+ }

commit 2f1e1d8ba44458bdc673ac01d04ba7300d9f9534
+Author: Arvind Sankar 
+Date:   Wed Dec 18 16:45:05 2019 -0500
+
+    arch/x86/setup: Drop dummy_con initialization
+    
+    con_init in tty/vt.c will now set conswitchp to dummy_con if it's unset.
+    Drop it from arch setup code.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20191218214506.49252-24-nivedita@alum.mit.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
+index cedfe2077a69..8ad29fa05d00 100644
+--- a/arch/x86/kernel/setup.c
++++ b/arch/x86/kernel/setup.c
+@@ -1295,8 +1295,6 @@ void __init setup_arch(char **cmdline_p)
+ #if defined(CONFIG_VGA_CONSOLE)
+ 	if (!efi_enabled(EFI_BOOT) || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY))
+ 		conswitchp = &vga_con;
+-#elif defined(CONFIG_DUMMY_CONSOLE)
+-	conswitchp = &dummy_con;
+ #endif
+ #endif
+ 	x86_init.oem.banner();

commit 5ef438c854d326b662b79d8f84f1beb977529c38
+Author: Arvind Sankar 
+Date:   Wed Dec 18 16:45:04 2019 -0500
+
+    arch/unicore32/setup: Drop dummy_con initialization
+    
+    con_init in tty/vt.c will now set conswitchp to dummy_con if it's unset.
+    Drop it from arch setup code.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20191218214506.49252-23-nivedita@alum.mit.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/unicore32/kernel/setup.c b/arch/unicore32/kernel/setup.c
+index 95ae3b54df68..0c4242a5ee1d 100644
+--- a/arch/unicore32/kernel/setup.c
++++ b/arch/unicore32/kernel/setup.c
+@@ -270,8 +270,6 @@ void __init setup_arch(char **cmdline_p)
+ #ifdef CONFIG_VT
+ #if defined(CONFIG_VGA_CONSOLE)
+ 	conswitchp = &vga_con;
+-#elif defined(CONFIG_DUMMY_CONSOLE)
+-	conswitchp = &dummy_con;
+ #endif
+ #endif
+ 	early_trap_init();

commit 2f01bfc1ecfba5381e788d59df10f05c542b494e
+Author: Arvind Sankar 
+Date:   Wed Dec 18 16:45:03 2019 -0500
+
+    arch/sparc/setup: Drop dummy_con initialization
+    
+    con_init in tty/vt.c will now set conswitchp to dummy_con if it's unset.
+    Drop it from arch setup code.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20191218214506.49252-22-nivedita@alum.mit.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c
+index afe1592a6d08..5d1bcfce05d8 100644
+--- a/arch/sparc/kernel/setup_32.c
++++ b/arch/sparc/kernel/setup_32.c
+@@ -332,10 +332,6 @@ void __init setup_arch(char **cmdline_p)
+ 		break;
+ 	}
+ 
+-#ifdef CONFIG_DUMMY_CONSOLE
+-	conswitchp = &dummy_con;
+-#endif
+-
+ 	idprom_init();
+ 	load_mmu();
+ 
+diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c
+index fd2182a5c32d..75e3992203b6 100644
+--- a/arch/sparc/kernel/setup_64.c
++++ b/arch/sparc/kernel/setup_64.c
+@@ -653,10 +653,6 @@ void __init setup_arch(char **cmdline_p)
+ 	else
+ 		pr_info("ARCH: SUN4U\n");
+ 
+-#ifdef CONFIG_DUMMY_CONSOLE
+-	conswitchp = &dummy_con;
+-#endif
+-
+ 	idprom_init();
+ 
+ 	if (!root_flags)

commit 40b19e316294e8fd466c0328be607a042e7ec95b
+Author: Arvind Sankar 
+Date:   Wed Dec 18 16:45:02 2019 -0500
+
+    arch/sh/setup: Drop dummy_con initialization
+    
+    con_init in tty/vt.c will now set conswitchp to dummy_con if it's unset.
+    Drop it from arch setup code.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20191218214506.49252-21-nivedita@alum.mit.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
+index d232cfa01877..67f5a3b44c2e 100644
+--- a/arch/sh/kernel/setup.c
++++ b/arch/sh/kernel/setup.c
+@@ -341,10 +341,6 @@ void __init setup_arch(char **cmdline_p)
+ 
+ 	paging_init();
+ 
+-#ifdef CONFIG_DUMMY_CONSOLE
+-	conswitchp = &dummy_con;
+-#endif
+-
+ 	/* Perform the machine specific initialisation */
+ 	if (likely(sh_mv.mv_setup))
+ 		sh_mv.mv_setup(cmdline_p);

commit c5ff734cf65e5bf667569076f143389c2b1fba24
+Author: Arvind Sankar 
+Date:   Wed Dec 18 16:45:01 2019 -0500
+
+    arch/s390/setup: Drop dummy_con initialization
+    
+    con_init in tty/vt.c will now set conswitchp to dummy_con if it's unset.
+    Drop it from arch setup code.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20191218214506.49252-20-nivedita@alum.mit.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
+index 9cbf490fd162..703cfbca2d25 100644
+--- a/arch/s390/kernel/setup.c
++++ b/arch/s390/kernel/setup.c
+@@ -241,8 +241,6 @@ static void __init conmode_default(void)
+ 		SET_CONSOLE_SCLP;
+ #endif
+ 	}
+-	if (IS_ENABLED(CONFIG_VT) && IS_ENABLED(CONFIG_DUMMY_CONSOLE))
+-		conswitchp = &dummy_con;
+ }
+ 
+ #ifdef CONFIG_CRASH_DUMP

commit 2680e04c187495e779abdfdd8ff8e1805fcc1d63
+Author: Arvind Sankar 
+Date:   Wed Dec 18 16:45:00 2019 -0500
+
+    arch/riscv/setup: Drop dummy_con initialization
+    
+    con_init in tty/vt.c will now set conswitchp to dummy_con if it's unset.
+    Drop it from arch setup code.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20191218214506.49252-19-nivedita@alum.mit.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
+index 365ff8420bfe..9babfcf3bb70 100644
+--- a/arch/riscv/kernel/setup.c
++++ b/arch/riscv/kernel/setup.c
+@@ -78,9 +78,5 @@ void __init setup_arch(char **cmdline_p)
+ 	setup_smp();
+ #endif
+ 
+-#ifdef CONFIG_DUMMY_CONSOLE
+-	conswitchp = &dummy_con;
+-#endif
+-
+ 	riscv_fill_hwcap();
+ }

commit 4c82266d158d755d75b0e9dd75baac6e9a8d622f
+Author: Arvind Sankar 
+Date:   Wed Dec 18 16:44:59 2019 -0500
+
+    arch/powerpc/setup: Drop dummy_con initialization
+    
+    con_init in tty/vt.c will now set conswitchp to dummy_con if it's unset.
+    Drop it from arch setup code.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20191218214506.49252-18-nivedita@alum.mit.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
+index 488f1eecc0de..7f8c890360fe 100644
+--- a/arch/powerpc/kernel/setup-common.c
++++ b/arch/powerpc/kernel/setup-common.c
+@@ -949,9 +949,6 @@ void __init setup_arch(char **cmdline_p)
+ 
+ 	early_memtest(min_low_pfn << PAGE_SHIFT, max_low_pfn << PAGE_SHIFT);
+ 
+-	if (IS_ENABLED(CONFIG_DUMMY_CONSOLE))
+-		conswitchp = &dummy_con;
+-
+ 	if (ppc_md.setup_arch)
+ 		ppc_md.setup_arch();
+ 
+diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
+index 9680d766f20e..855eedb8d7d7 100644
+--- a/arch/powerpc/platforms/cell/setup.c
++++ b/arch/powerpc/platforms/cell/setup.c
+@@ -240,9 +240,6 @@ static void __init cell_setup_arch(void)
+ 	init_pci_config_tokens();
+ 
+ 	cbe_pervasive_init();
+-#ifdef CONFIG_DUMMY_CONSOLE
+-	conswitchp = &dummy_con;
+-#endif
+ 
+ 	mmio_nvram_init();
+ }
+diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
+index 9cd6f3e1000b..47f73103ef74 100644
+--- a/arch/powerpc/platforms/maple/setup.c
++++ b/arch/powerpc/platforms/maple/setup.c
+@@ -183,9 +183,6 @@ static void __init maple_setup_arch(void)
+ 	/* Lookup PCI hosts */
+        	maple_pci_init();
+ 
+-#ifdef CONFIG_DUMMY_CONSOLE
+-	conswitchp = &dummy_con;
+-#endif
+ 	maple_use_rtas_reboot_and_halt_if_present();
+ 
+ 	printk(KERN_DEBUG "Using native/NAP idle loop\n");
+diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c
+index 05a52f10c2f0..b612474f8f8e 100644
+--- a/arch/powerpc/platforms/pasemi/setup.c
++++ b/arch/powerpc/platforms/pasemi/setup.c
+@@ -147,10 +147,6 @@ static void __init pas_setup_arch(void)
+ 	/* Lookup PCI hosts */
+ 	pas_pci_init();
+ 
+-#ifdef CONFIG_DUMMY_CONSOLE
+-	conswitchp = &dummy_con;
+-#endif
+-
+ 	/* Remap SDC register for doing reset */
+ 	/* XXXOJN This should maybe come out of the device tree */
+ 	reset_reg = ioremap(0xfc101100, 4);
+diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
+index 8108b9b9b9ea..b29368931c56 100644
+--- a/arch/powerpc/platforms/ps3/setup.c
++++ b/arch/powerpc/platforms/ps3/setup.c
+@@ -200,10 +200,6 @@ static void __init ps3_setup_arch(void)
+ 	smp_init_ps3();
+ #endif
+ 
+-#ifdef CONFIG_DUMMY_CONSOLE
+-	conswitchp = &dummy_con;
+-#endif
+-
+ 	prealloc_ps3fb_videomemory();
+ 	prealloc_ps3flash_bounce_buffer();
+ 

commit 82292aaede74f072a4eff76c49d9f16cb66a64a4
+Author: Arvind Sankar 
+Date:   Wed Dec 18 16:44:58 2019 -0500
+
+    arch/parisc/setup: Drop dummy_con initialization
+    
+    con_init in tty/vt.c will now set conswitchp to dummy_con if it's unset.
+    Drop it from arch setup code.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20191218214506.49252-17-nivedita@alum.mit.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c
+index 53a21ce927de..e320bae501d3 100644
+--- a/arch/parisc/kernel/setup.c
++++ b/arch/parisc/kernel/setup.c
+@@ -151,10 +151,6 @@ void __init setup_arch(char **cmdline_p)
+ 	dma_ops_init();
+ #endif
+ 
+-#if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE)
+-	conswitchp = &dummy_con;	/* we use do_take_over_console() later ! */
+-#endif
+-
+ 	clear_sched_clock_stable();
+ }
+ 

commit bd3b0677cb47e79c7db2f1439b20888e84ec317d
+Author: Arvind Sankar 
+Date:   Wed Dec 18 16:44:57 2019 -0500
+
+    arch/openrisc/setup: Drop dummy_con initialization
+    
+    con_init in tty/vt.c will now set conswitchp to dummy_con if it's unset.
+    Drop it from arch setup code.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20191218214506.49252-16-nivedita@alum.mit.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/openrisc/kernel/setup.c b/arch/openrisc/kernel/setup.c
+index d668f5be3a99..c0a774b51e45 100644
+--- a/arch/openrisc/kernel/setup.c
++++ b/arch/openrisc/kernel/setup.c
+@@ -308,11 +308,6 @@ void __init setup_arch(char **cmdline_p)
+ 	/* paging_init() sets up the MMU and marks all pages as reserved */
+ 	paging_init();
+ 
+-#if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE)
+-	if (!conswitchp)
+-		conswitchp = &dummy_con;
+-#endif
+-
+ 	*cmdline_p = boot_command_line;
+ 
+ 	printk(KERN_INFO "OpenRISC Linux -- http://openrisc.io\n");

commit 701250223c67bfdc0252961d6536f51bc28c2f81
+Author: Arvind Sankar 
+Date:   Wed Dec 18 16:44:56 2019 -0500
+
+    arch/nios2/setup: Drop dummy_con initialization
+    
+    con_init in tty/vt.c will now set conswitchp to dummy_con if it's unset.
+    Drop it from arch setup code.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20191218214506.49252-15-nivedita@alum.mit.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/nios2/kernel/setup.c b/arch/nios2/kernel/setup.c
+index 4cf35b09c0ec..3c6e3c813a0b 100644
+--- a/arch/nios2/kernel/setup.c
++++ b/arch/nios2/kernel/setup.c
+@@ -196,8 +196,4 @@ void __init setup_arch(char **cmdline_p)
+ 	 * get kmalloc into gear
+ 	 */
+ 	paging_init();
+-
+-#if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE)
+-	conswitchp = &dummy_con;
+-#endif
+ }

commit 4b15a5b2053aa01e6be7389c73a9807726c0a939
+Author: Arvind Sankar 
+Date:   Wed Dec 18 16:44:55 2019 -0500
+
+    arch/nds32/setup: Drop dummy_con initialization
+    
+    con_init in tty/vt.c will now set conswitchp to dummy_con if it's unset.
+    Drop it from arch setup code.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20191218214506.49252-14-nivedita@alum.mit.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/nds32/kernel/setup.c b/arch/nds32/kernel/setup.c
+index 31d29d92478e..a066efbe53c0 100644
+--- a/arch/nds32/kernel/setup.c
++++ b/arch/nds32/kernel/setup.c
+@@ -317,11 +317,6 @@ void __init setup_arch(char **cmdline_p)
+ 
+ 	unflatten_and_copy_device_tree();
+ 
+-	if(IS_ENABLED(CONFIG_VT)) {
+-		if(IS_ENABLED(CONFIG_DUMMY_CONSOLE))
+-			conswitchp = &dummy_con;
+-	}
+-
+ 	*cmdline_p = boot_command_line;
+ 	early_trap_init();
+ }

commit 3229af4f3ef4db439471d21df562532365005bd5
+Author: Arvind Sankar 
+Date:   Wed Dec 18 16:44:54 2019 -0500
+
+    arch/mips/setup: Drop dummy_con initialization
+    
+    con_init in tty/vt.c will now set conswitchp to dummy_con if it's unset.
+    Drop it from arch setup code.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20191218214506.49252-13-nivedita@alum.mit.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
+index c3d4212b5f1d..a28057946ed1 100644
+--- a/arch/mips/kernel/setup.c
++++ b/arch/mips/kernel/setup.c
+@@ -796,8 +796,6 @@ void __init setup_arch(char **cmdline_p)
+ #if defined(CONFIG_VT)
+ #if defined(CONFIG_VGA_CONSOLE)
+ 	conswitchp = &vga_con;
+-#elif defined(CONFIG_DUMMY_CONSOLE)
+-	conswitchp = &dummy_con;
+ #endif
+ #endif
+ 

commit 4946d6cc01d82f41ef8502007958db4eee24952c
+Author: Arvind Sankar 
+Date:   Wed Dec 18 16:44:53 2019 -0500
+
+    arch/microblaze/setup: Drop dummy_con initialization
+    
+    con_init in tty/vt.c will now set conswitchp to dummy_con if it's unset.
+    Drop it from arch setup code.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20191218214506.49252-12-nivedita@alum.mit.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c
+index 522a0c5d9c59..511c1ab7f57f 100644
+--- a/arch/microblaze/kernel/setup.c
++++ b/arch/microblaze/kernel/setup.c
+@@ -65,10 +65,6 @@ void __init setup_arch(char **cmdline_p)
+ 	microblaze_cache_init();
+ 
+ 	xilinx_pci_init();
+-
+-#if defined(CONFIG_DUMMY_CONSOLE)
+-	conswitchp = &dummy_con;
+-#endif
+ }
+ 
+ #ifdef CONFIG_MTD_UCLINUX

commit 143c2ce261250adf86a3c1f4f5acaf5ba35ea07d
+Author: Arvind Sankar 
+Date:   Wed Dec 18 16:44:52 2019 -0500
+
+    arch/m68k/setup: Drop dummy_con initialization
+    
+    con_init in tty/vt.c will now set conswitchp to dummy_con if it's unset.
+    Drop it from arch setup code.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20191218214506.49252-11-nivedita@alum.mit.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/m68k/kernel/setup_mm.c b/arch/m68k/kernel/setup_mm.c
+index 528484feff80..ab8aa7be260f 100644
+--- a/arch/m68k/kernel/setup_mm.c
++++ b/arch/m68k/kernel/setup_mm.c
+@@ -274,10 +274,6 @@ void __init setup_arch(char **cmdline_p)
+ 
+ 	parse_early_param();
+ 
+-#ifdef CONFIG_DUMMY_CONSOLE
+-	conswitchp = &dummy_con;
+-#endif
+-
+ 	switch (m68k_machtype) {
+ #ifdef CONFIG_AMIGA
+ 	case MACH_AMIGA:
+diff --git a/arch/m68k/kernel/setup_no.c b/arch/m68k/kernel/setup_no.c
+index 3c5def10d486..a63483de7a42 100644
+--- a/arch/m68k/kernel/setup_no.c
++++ b/arch/m68k/kernel/setup_no.c
+@@ -146,10 +146,6 @@ void __init setup_arch(char **cmdline_p)
+ 	memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+ 	boot_command_line[COMMAND_LINE_SIZE-1] = 0;
+ 
+-#if defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_DUMMY_CONSOLE)
+-	conswitchp = &dummy_con;
+-#endif
+-
+ 	/*
+ 	 * Give all the memory to the bootmap allocator, tell it to put the
+ 	 * boot mem_map at the start of memory.
+diff --git a/arch/m68k/sun3x/config.c b/arch/m68k/sun3x/config.c
+index 03ce7f9facfe..d806dee71a9c 100644
+--- a/arch/m68k/sun3x/config.c
++++ b/arch/m68k/sun3x/config.c
+@@ -70,7 +70,6 @@ void __init config_sun3x(void)
+ 		break;
+ 	default:
+ 		serial_console = 0;
+-		conswitchp = &dummy_con;
+ 		break;
+ 	}
+ #endif

commit 6b448f12a221d172dbe0a4793f8bed302079c874
+Author: Arvind Sankar 
+Date:   Wed Dec 18 16:44:51 2019 -0500
+
+    arch/ia64/setup: Drop dummy_con initialization
+    
+    con_init in tty/vt.c will now set conswitchp to dummy_con if it's unset.
+    Drop it from arch setup code.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20191218214506.49252-10-nivedita@alum.mit.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
+index c49fcef754de..4009383453f7 100644
+--- a/arch/ia64/kernel/setup.c
++++ b/arch/ia64/kernel/setup.c
+@@ -608,9 +608,6 @@ setup_arch (char **cmdline_p)
+ 
+ #ifdef CONFIG_VT
+ 	if (!conswitchp) {
+-# if defined(CONFIG_DUMMY_CONSOLE)
+-		conswitchp = &dummy_con;
+-# endif
+ # if defined(CONFIG_VGA_CONSOLE)
+ 		/*
+ 		 * Non-legacy systems may route legacy VGA MMIO range to system

commit fb3e7a622003f1e7c4440650c21f938bf9beb976
+Author: Arvind Sankar 
+Date:   Wed Dec 18 16:44:50 2019 -0500
+
+    arch/csky/setup: Drop dummy_con initialization
+    
+    con_init in tty/vt.c will now set conswitchp to dummy_con if it's unset.
+    Drop it from arch setup code.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20191218214506.49252-9-nivedita@alum.mit.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/csky/kernel/setup.c b/arch/csky/kernel/setup.c
+index 23ee604aafdb..52eaf31ba27f 100644
+--- a/arch/csky/kernel/setup.c
++++ b/arch/csky/kernel/setup.c
+@@ -136,10 +136,6 @@ void __init setup_arch(char **cmdline_p)
+ #ifdef CONFIG_HIGHMEM
+ 	kmap_init();
+ #endif
+-
+-#if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE)
+-	conswitchp = &dummy_con;
+-#endif
+ }
+ 
+ unsigned long va_pa_offset;

commit 46cbe2f39976197a11da2abf27883530f3d0ddc2
+Author: Arvind Sankar 
+Date:   Wed Dec 18 16:44:48 2019 -0500
+
+    arch/arm64/setup: Drop dummy_con initialization
+    
+    con_init in tty/vt.c will now set conswitchp to dummy_con if it's unset.
+    Drop it from arch setup code.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20191218214506.49252-7-nivedita@alum.mit.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
+index 56f664561754..2a86676b693a 100644
+--- a/arch/arm64/kernel/setup.c
++++ b/arch/arm64/kernel/setup.c
+@@ -353,9 +353,6 @@ void __init setup_arch(char **cmdline_p)
+ 	init_task.thread_info.ttbr0 = __pa_symbol(empty_zero_page);
+ #endif
+ 
+-#ifdef CONFIG_VT
+-	conswitchp = &dummy_con;
+-#endif
+ 	if (boot_args[1] || boot_args[2] || boot_args[3]) {
+ 		pr_err("WARNING: x1-x3 nonzero in violation of boot protocol:\n"
+ 			"\tx1: %016llx\n\tx2: %016llx\n\tx3: %016llx\n"

commit 3e70ac06913ba5a3c613affb7c8df9fd6b4b24f9
+Author: Arvind Sankar 
+Date:   Wed Dec 18 16:44:47 2019 -0500
+
+    arch/arm/setup: Drop dummy_con initialization
+    
+    con_init in tty/vt.c will now set conswitchp to dummy_con if it's unset.
+    Drop it from arch setup code.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20191218214506.49252-6-nivedita@alum.mit.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
+index d0a464e317ea..d8e18cdd96d3 100644
+--- a/arch/arm/kernel/setup.c
++++ b/arch/arm/kernel/setup.c
+@@ -1164,8 +1164,6 @@ void __init setup_arch(char **cmdline_p)
+ #ifdef CONFIG_VT
+ #if defined(CONFIG_VGA_CONSOLE)
+ 	conswitchp = &vga_con;
+-#elif defined(CONFIG_DUMMY_CONSOLE)
+-	conswitchp = &dummy_con;
+ #endif
+ #endif
+ 

commit 61f23e657cd6cb42ae8d25351cd995afa562afdc
+Author: Arvind Sankar 
+Date:   Wed Dec 18 16:44:46 2019 -0500
+
+    arch/arc/setup: Drop dummy_con initialization
+    
+    con_init in tty/vt.c will now set conswitchp to dummy_con if it's unset.
+    Drop it from arch setup code.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20191218214506.49252-5-nivedita@alum.mit.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
+index 7ee89dc61f6e..e1c647490f00 100644
+--- a/arch/arc/kernel/setup.c
++++ b/arch/arc/kernel/setup.c
+@@ -572,10 +572,6 @@ void __init setup_arch(char **cmdline_p)
+ 	 */
+ 	root_mountflags &= ~MS_RDONLY;
+ 
+-#if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE)
+-	conswitchp = &dummy_con;
+-#endif
+-
+ 	arc_unwind_init();
+ }
+ 

commit 9ef497dcbc2be18845a1b3151efdca72697eeaad
+Author: Arvind Sankar 
+Date:   Wed Dec 18 16:44:45 2019 -0500
+
+    arch/alpha/setup: Drop dummy_con initialization
+    
+    con_init in tty/vt.c will now set conswitchp to dummy_con if it's unset.
+    Drop it from arch setup code.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20191218214506.49252-4-nivedita@alum.mit.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
+index 5d4c76a77a9f..f19aa577354b 100644
+--- a/arch/alpha/kernel/setup.c
++++ b/arch/alpha/kernel/setup.c
+@@ -655,8 +655,6 @@ setup_arch(char **cmdline_p)
+ #ifdef CONFIG_VT
+ #if defined(CONFIG_VGA_CONSOLE)
+ 	conswitchp = &vga_con;
+-#elif defined(CONFIG_DUMMY_CONSOLE)
+-	conswitchp = &dummy_con;
+ #endif
+ #endif
+ 

commit 805ece2a58085c33c0c087be049b77e94c12080a
+Author: Arvind Sankar 
+Date:   Wed Dec 18 16:44:44 2019 -0500
+
+    vt: Initialize conswitchp to dummy_con if unset
+    
+    If the arch setup code hasn't initialized conswitchp yet, set it to
+    dummy_con in con_init. This will allow us to drop the dummy_con
+    initialization that's done in almost every architecture.
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20191218214506.49252-3-nivedita@alum.mit.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
+index 34aa39d1aed9..2456afaf1c61 100644
+--- a/drivers/tty/vt/vt.c
++++ b/drivers/tty/vt/vt.c
+@@ -3326,8 +3326,9 @@ static int __init con_init(void)
+ 
+ 	console_lock();
+ 
+-	if (conswitchp)
+-		display_desc = conswitchp->con_startup();
++	if (!conswitchp)
++		conswitchp = &dummy_con;
++	display_desc = conswitchp->con_startup();
+ 	if (!display_desc) {
+ 		fg_console = 0;
+ 		console_unlock();

commit e018bc28b031348ff763b89b48b3b96f1f0e466b
+Author: Arvind Sankar 
+Date:   Wed Dec 18 16:44:43 2019 -0500
+
+    console/dummycon: Remove bogus depends on from DUMMY_CONSOLE
+    
+    Since commit [1] consolidated console configuration in
+    drivers/video/console, DUMMY_CONSOLE has always been enabled, since the
+    dependency is always satisfied.
+    
+    There is no point in trying to allow it to be configured out, since
+    (a) it's tiny, and (b) if VT_CONSOLE is enabled, we must have a working
+    console driver by the time con_init(vt.c) runs, and only dummycon is
+    guaranteed to work (vgacon may be configured in, but that doesn't mean
+    we have a VGA device).
+    
+    So just remove the fake dependency.
+    
+    [1] https://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git/commit?id=31d2a7d36d6989c714b792ec00358ada24c039e7
+    
+    Signed-off-by: Arvind Sankar 
+    Link: https://lore.kernel.org/r/20191218214506.49252-2-nivedita@alum.mit.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
+index c10e17fb9a9a..70c10ea1c38b 100644
+--- a/drivers/video/console/Kconfig
++++ b/drivers/video/console/Kconfig
+@@ -93,7 +93,6 @@ config SGI_NEWPORT_CONSOLE
+ 
+ config DUMMY_CONSOLE
+ 	bool
+-	depends on VGA_CONSOLE!=y || SGI_NEWPORT_CONSOLE!=y 
+ 	default y
+ 
+ config DUMMY_CONSOLE_COLUMNS

commit ea7d87f98fa9675076fb5ad208d889b217e83889
+Author: Arvind Sankar 
+Date:   Fri Jan 3 12:39:49 2020 +0100
+
+    efi/x86: Allow translating 64-bit arguments for mixed mode calls
+    
+    Introduce the ability to define macros to perform argument translation
+    for the calls that need it, and define them for the boot services that
+    we currently use.
+    
+    When calling 32-bit firmware methods in mixed mode, all output
+    parameters that are 32-bit according to the firmware, but 64-bit in the
+    kernel (ie OUT UINTN * or OUT VOID **) must be initialized in the
+    kernel, or the upper 32 bits may contain garbage. Define macros that
+    zero out the upper 32 bits of the output before invoking the firmware
+    method.
+    
+    When a 32-bit EFI call takes 64-bit arguments, the mixed-mode call must
+    push the two 32-bit halves as separate arguments onto the stack. This
+    can be achieved by splitting the argument into its two halves when
+    calling the assembler thunk. Define a macro to do this for the
+    free_pages boot service.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+    Cc: Andy Lutomirski 
+    Cc: Ard Biesheuvel 
+    Cc: Matthew Garrett 
+    Cc: linux-efi@vger.kernel.org
+    Link: https://lkml.kernel.org/r/20200103113953.9571-17-ardb@kernel.org
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
+index 565ee4733579..4afd29eb5b34 100644
+--- a/arch/x86/boot/compressed/eboot.c
++++ b/arch/x86/boot/compressed/eboot.c
+@@ -891,19 +891,3 @@ struct boot_params *efi_main(efi_handle_t handle,
+ 	for (;;)
+ 		asm("hlt");
+ }
+-
+-#ifdef CONFIG_EFI_MIXED
+-void efi_free_native(unsigned long size, unsigned long addr);
+-
+-void efi_free(unsigned long size, unsigned long addr)
+-{
+-	if (!size)
+-		return;
+-
+-	if (efi_is_native())
+-		efi_free_native(size, addr);
+-	else
+-		efi64_thunk(efi_system_table()->boottime->mixed_mode.free_pages,
+-			    addr, 0, DIV_ROUND_UP(size, EFI_PAGE_SIZE));
+-}
+-#endif
+diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
+index cfc450085584..166f0386719e 100644
+--- a/arch/x86/include/asm/efi.h
++++ b/arch/x86/include/asm/efi.h
+@@ -243,22 +243,83 @@ static inline bool efi_is_native(void)
+ 		: (__typeof__(inst->attr))				\
+ 			efi_mixed_mode_cast(inst->mixed_mode.attr))
+ 
++/*
++ * The following macros allow translating arguments if necessary from native to
++ * mixed mode. The use case for this is to initialize the upper 32 bits of
++ * output parameters, and where the 32-bit method requires a 64-bit argument,
++ * which must be split up into two arguments to be thunked properly.
++ *
++ * As examples, the AllocatePool boot service returns the address of the
++ * allocation, but it will not set the high 32 bits of the address. To ensure
++ * that the full 64-bit address is initialized, we zero-init the address before
++ * calling the thunk.
++ *
++ * The FreePages boot service takes a 64-bit physical address even in 32-bit
++ * mode. For the thunk to work correctly, a native 64-bit call of
++ * 	free_pages(addr, size)
++ * must be translated to
++ * 	efi64_thunk(free_pages, addr & U32_MAX, addr >> 32, size)
++ * so that the two 32-bit halves of addr get pushed onto the stack separately.
++ */
++
++static inline void *efi64_zero_upper(void *p)
++{
++	((u32 *)p)[1] = 0;
++	return p;
++}
++
++#define __efi64_argmap_free_pages(addr, size)				\
++	((addr), 0, (size))
++
++#define __efi64_argmap_get_memory_map(mm_size, mm, key, size, ver)	\
++	((mm_size), (mm), efi64_zero_upper(key), efi64_zero_upper(size), (ver))
++
++#define __efi64_argmap_allocate_pool(type, size, buffer)		\
++	((type), (size), efi64_zero_upper(buffer))
++
++#define __efi64_argmap_handle_protocol(handle, protocol, interface)	\
++	((handle), (protocol), efi64_zero_upper(interface))
++
++#define __efi64_argmap_locate_protocol(protocol, reg, interface)	\
++	((protocol), (reg), efi64_zero_upper(interface))
++
++/*
++ * The macros below handle the plumbing for the argument mapping. To add a
++ * mapping for a specific EFI method, simply define a macro
++ * __efi64_argmap_, following the examples above.
++ */
++
++#define __efi64_thunk_map(inst, func, ...)				\
++	efi64_thunk(inst->mixed_mode.func,				\
++		__efi64_argmap(__efi64_argmap_ ## func(__VA_ARGS__),	\
++			       (__VA_ARGS__)))
++
++#define __efi64_argmap(mapped, args)					\
++	__PASTE(__efi64_argmap__, __efi_nargs(__efi_eat mapped))(mapped, args)
++#define __efi64_argmap__0(mapped, args) __efi_eval mapped
++#define __efi64_argmap__1(mapped, args) __efi_eval args
++
++#define __efi_eat(...)
++#define __efi_eval(...) __VA_ARGS__
++
++/* The three macros below handle dispatching via the thunk if needed */
++
+ #define efi_call_proto(inst, func, ...)					\
+ 	(efi_is_native()						\
+ 		? inst->func(inst, ##__VA_ARGS__)			\
+-		: efi64_thunk(inst->mixed_mode.func, inst, ##__VA_ARGS__))
++		: __efi64_thunk_map(inst, func, inst, ##__VA_ARGS__))
+ 
+ #define efi_bs_call(func, ...)						\
+ 	(efi_is_native()						\
+ 		? efi_system_table()->boottime->func(__VA_ARGS__)	\
+-		: efi64_thunk(efi_table_attr(efi_system_table(),	\
+-				boottime)->mixed_mode.func, __VA_ARGS__))
++		: __efi64_thunk_map(efi_table_attr(efi_system_table(),	\
++				boottime), func, __VA_ARGS__))
+ 
+ #define efi_rt_call(func, ...)						\
+ 	(efi_is_native()						\
+ 		? efi_system_table()->runtime->func(__VA_ARGS__)	\
+-		: efi64_thunk(efi_table_attr(efi_system_table(),	\
+-				runtime)->mixed_mode.func, __VA_ARGS__))
++		: __efi64_thunk_map(efi_table_attr(efi_system_table(),	\
++				runtime), func, __VA_ARGS__))
+ 
+ extern bool efi_reboot_required(void);
+ extern bool efi_is_table_address(unsigned long phys_addr);
+diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
+index f1b9c36934e9..fcc45ee94e02 100644
+--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
++++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
+@@ -344,9 +344,6 @@ efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,
+ }
+ 
+ void efi_free(unsigned long size, unsigned long addr)
+-	__weak __alias(efi_free_native);
+-
+-void efi_free_native(unsigned long size, unsigned long addr)
+ {
+ 	unsigned long nr_pages;
+ 
+@@ -354,7 +351,7 @@ void efi_free_native(unsigned long size, unsigned long addr)
+ 		return;
+ 
+ 	nr_pages = round_up(size, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE;
+-	efi_system_table()->boottime->free_pages(addr, nr_pages);
++	efi_bs_call(free_pages, addr, nr_pages);
+ }
+ 
+ static efi_status_t efi_file_size(void *__fh, efi_char16_t *filename_16,

commit 14b864f4b5c402fe1ca394042beeea6fdf54f8f5
+Author: Arvind Sankar 
+Date:   Fri Jan 3 12:39:48 2020 +0100
+
+    efi/x86: Check number of arguments to variadic functions
+    
+    On x86 we need to thunk through assembler stubs to call the EFI services
+    for mixed mode, and for runtime services in 64-bit mode. The assembler
+    stubs have limits on how many arguments it handles. Introduce a few
+    macros to check that we do not try to pass too many arguments to the
+    stubs.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+    Cc: Andy Lutomirski 
+    Cc: Ard Biesheuvel 
+    Cc: Matthew Garrett 
+    Cc: linux-efi@vger.kernel.org
+    Link: https://lkml.kernel.org/r/20200103113953.9571-16-ardb@kernel.org
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/x86/boot/compressed/efi_thunk_64.S b/arch/x86/boot/compressed/efi_thunk_64.S
+index 6d95eb6b8912..d040ff5458e5 100644
+--- a/arch/x86/boot/compressed/efi_thunk_64.S
++++ b/arch/x86/boot/compressed/efi_thunk_64.S
+@@ -23,7 +23,7 @@
+ 
+ 	.code64
+ 	.text
+-SYM_FUNC_START(efi64_thunk)
++SYM_FUNC_START(__efi64_thunk)
+ 	push	%rbp
+ 	push	%rbx
+ 
+@@ -95,7 +95,7 @@ SYM_FUNC_START(efi64_thunk)
+ 	pop	%rbx
+ 	pop	%rbp
+ 	ret
+-SYM_FUNC_END(efi64_thunk)
++SYM_FUNC_END(__efi64_thunk)
+ 
+ 	.code32
+ /*
+diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
+index e7e9c6e057f9..cfc450085584 100644
+--- a/arch/x86/include/asm/efi.h
++++ b/arch/x86/include/asm/efi.h
+@@ -8,6 +8,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ /*
+  * We map the EFI regions needed for runtime services non-contiguously,
+@@ -34,6 +35,45 @@
+ 
+ #define ARCH_EFI_IRQ_FLAGS_MASK	X86_EFLAGS_IF
+ 
++/*
++ * The EFI services are called through variadic functions in many cases. These
++ * functions are implemented in assembler and support only a fixed number of
++ * arguments. The macros below allows us to check at build time that we don't
++ * try to call them with too many arguments.
++ *
++ * __efi_nargs() will return the number of arguments if it is 7 or less, and
++ * cause a BUILD_BUG otherwise. The limitations of the C preprocessor make it
++ * impossible to calculate the exact number of arguments beyond some
++ * pre-defined limit. The maximum number of arguments currently supported by
++ * any of the thunks is 7, so this is good enough for now and can be extended
++ * in the obvious way if we ever need more.
++ */
++
++#define __efi_nargs(...) __efi_nargs_(__VA_ARGS__)
++#define __efi_nargs_(...) __efi_nargs__(0, ##__VA_ARGS__,	\
++	__efi_arg_sentinel(7), __efi_arg_sentinel(6),		\
++	__efi_arg_sentinel(5), __efi_arg_sentinel(4),		\
++	__efi_arg_sentinel(3), __efi_arg_sentinel(2),		\
++	__efi_arg_sentinel(1), __efi_arg_sentinel(0))
++#define __efi_nargs__(_0, _1, _2, _3, _4, _5, _6, _7, n, ...)	\
++	__take_second_arg(n,					\
++		({ BUILD_BUG_ON_MSG(1, "__efi_nargs limit exceeded"); 8; }))
++#define __efi_arg_sentinel(n) , n
++
++/*
++ * __efi_nargs_check(f, n, ...) will cause a BUILD_BUG if the ellipsis
++ * represents more than n arguments.
++ */
++
++#define __efi_nargs_check(f, n, ...)					\
++	__efi_nargs_check_(f, __efi_nargs(__VA_ARGS__), n)
++#define __efi_nargs_check_(f, p, n) __efi_nargs_check__(f, p, n)
++#define __efi_nargs_check__(f, p, n) ({					\
++	BUILD_BUG_ON_MSG(						\
++		(p) > (n),						\
++		#f " called with too many arguments (" #p ">" #n ")");	\
++})
++
+ #ifdef CONFIG_X86_32
+ #define arch_efi_call_virt_setup()					\
+ ({									\
+@@ -56,7 +96,12 @@
+ 
+ #define EFI_LOADER_SIGNATURE	"EL64"
+ 
+-extern asmlinkage u64 efi_call(void *fp, ...);
++extern asmlinkage u64 __efi_call(void *fp, ...);
++
++#define efi_call(...) ({						\
++	__efi_nargs_check(efi_call, 7, __VA_ARGS__);			\
++	__efi_call(__VA_ARGS__);					\
++})
+ 
+ /*
+  * struct efi_scratch - Scratch space used while switching to/from efi_mm
+@@ -139,7 +184,12 @@ struct efi_setup_data {
+ extern u64 efi_setup;
+ 
+ #ifdef CONFIG_EFI
+-extern efi_status_t efi64_thunk(u32, ...);
++extern efi_status_t __efi64_thunk(u32, ...);
++
++#define efi64_thunk(...) ({						\
++	__efi_nargs_check(efi64_thunk, 6, __VA_ARGS__);			\
++	__efi64_thunk(__VA_ARGS__);					\
++})
+ 
+ static inline bool efi_is_mixed(void)
+ {
+diff --git a/arch/x86/platform/efi/efi_stub_64.S b/arch/x86/platform/efi/efi_stub_64.S
+index e7e1020f4ccb..15da118f04f0 100644
+--- a/arch/x86/platform/efi/efi_stub_64.S
++++ b/arch/x86/platform/efi/efi_stub_64.S
+@@ -10,7 +10,7 @@
+ #include 
+ #include 
+ 
+-SYM_FUNC_START(efi_call)
++SYM_FUNC_START(__efi_call)
+ 	pushq %rbp
+ 	movq %rsp, %rbp
+ 	and $~0xf, %rsp
+@@ -24,4 +24,4 @@ SYM_FUNC_START(efi_call)
+ 	CALL_NOSPEC %rdi
+ 	leave
+ 	ret
+-SYM_FUNC_END(efi_call)
++SYM_FUNC_END(__efi_call)
+diff --git a/arch/x86/platform/efi/efi_thunk_64.S b/arch/x86/platform/efi/efi_thunk_64.S
+index 162b35729633..26f0da238c1c 100644
+--- a/arch/x86/platform/efi/efi_thunk_64.S
++++ b/arch/x86/platform/efi/efi_thunk_64.S
+@@ -25,7 +25,7 @@
+ 
+ 	.text
+ 	.code64
+-SYM_CODE_START(efi64_thunk)
++SYM_CODE_START(__efi64_thunk)
+ 	push	%rbp
+ 	push	%rbx
+ 
+@@ -69,4 +69,4 @@ SYM_CODE_START(efi64_thunk)
+ 2:	pushl	$__KERNEL_CS
+ 	pushl	%ebp
+ 	lret
+-SYM_CODE_END(efi64_thunk)
++SYM_CODE_END(__efi64_thunk)

commit 8de8788d21826457ac3bfd1629d0e280f67c7b5f
+Author: Arvind Sankar 
+Date:   Tue Dec 24 16:10:04 2019 +0100
+
+    efi/gop: Unify 32/64-bit functions
+    
+    Use efi_table_attr macro to deal with 32/64-bit firmware using the same
+    source code.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+    Cc: Borislav Petkov 
+    Cc: James Morse 
+    Cc: Matt Fleming 
+    Cc: Thomas Gleixner 
+    Cc: linux-efi@vger.kernel.org
+    Link: https://lkml.kernel.org/r/20191224151025.32482-5-ardb@kernel.org
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
+index a0c1ef64d445..94045ab7dd3d 100644
+--- a/drivers/firmware/efi/libstub/gop.c
++++ b/drivers/firmware/efi/libstub/gop.c
+@@ -83,108 +83,14 @@ setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line,
+ 	}
+ }
+ 
+-static efi_status_t
+-setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
+-            efi_guid_t *proto, unsigned long size, void **gop_handle)
+-{
+-	efi_graphics_output_protocol_32_t *gop32, *first_gop;
+-	unsigned long nr_gops;
+-	u16 width, height;
+-	u32 pixels_per_scan_line;
+-	u32 ext_lfb_base;
+-	efi_physical_addr_t fb_base;
+-	efi_pixel_bitmask_t pixel_info;
+-	int pixel_format;
+-	efi_status_t status;
+-	u32 *handles = (u32 *)(unsigned long)gop_handle;
+-	int i;
+-
+-	first_gop = NULL;
+-	gop32 = NULL;
+-
+-	nr_gops = size / sizeof(u32);
+-	for (i = 0; i < nr_gops; i++) {
+-		efi_graphics_output_protocol_mode_32_t *mode;
+-		efi_graphics_output_mode_info_t *info = NULL;
+-		efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
+-		bool conout_found = false;
+-		void *dummy = NULL;
+-		efi_handle_t h = (efi_handle_t)(unsigned long)handles[i];
+-		efi_physical_addr_t current_fb_base;
+-
+-		status = efi_call_early(handle_protocol, h,
+-					proto, (void **)&gop32);
+-		if (status != EFI_SUCCESS)
+-			continue;
+-
+-		status = efi_call_early(handle_protocol, h,
+-					&conout_proto, &dummy);
+-		if (status == EFI_SUCCESS)
+-			conout_found = true;
+-
+-		mode = (void *)(unsigned long)gop32->mode;
+-		info = (void *)(unsigned long)mode->info;
+-		current_fb_base = mode->frame_buffer_base;
+-
+-		if ((!first_gop || conout_found) &&
+-		    info->pixel_format != PIXEL_BLT_ONLY) {
+-			/*
+-			 * Systems that use the UEFI Console Splitter may
+-			 * provide multiple GOP devices, not all of which are
+-			 * backed by real hardware. The workaround is to search
+-			 * for a GOP implementing the ConOut protocol, and if
+-			 * one isn't found, to just fall back to the first GOP.
+-			 */
+-			width = info->horizontal_resolution;
+-			height = info->vertical_resolution;
+-			pixel_format = info->pixel_format;
+-			pixel_info = info->pixel_information;
+-			pixels_per_scan_line = info->pixels_per_scan_line;
+-			fb_base = current_fb_base;
+-
+-			/*
+-			 * Once we've found a GOP supporting ConOut,
+-			 * don't bother looking any further.
+-			 */
+-			first_gop = gop32;
+-			if (conout_found)
+-				break;
+-		}
+-	}
+-
+-	/* Did we find any GOPs? */
+-	if (!first_gop)
+-		return EFI_NOT_FOUND;
+-
+-	/* EFI framebuffer */
+-	si->orig_video_isVGA = VIDEO_TYPE_EFI;
+-
+-	si->lfb_width = width;
+-	si->lfb_height = height;
+-	si->lfb_base = fb_base;
+-
+-	ext_lfb_base = (u64)(unsigned long)fb_base >> 32;
+-	if (ext_lfb_base) {
+-		si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE;
+-		si->ext_lfb_base = ext_lfb_base;
+-	}
+-
+-	si->pages = 1;
+-
+-	setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format);
+-
+-	si->lfb_size = si->lfb_linelength * si->lfb_height;
+-
+-	si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS;
+-
+-	return EFI_SUCCESS;
+-}
++#define efi_gop_attr(table, attr, instance) \
++	(efi_table_attr(efi_graphics_output_protocol##table, attr, instance))
+ 
+ static efi_status_t
+-setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
+-	    efi_guid_t *proto, unsigned long size, void **gop_handle)
++setup_gop(efi_system_table_t *sys_table_arg, struct screen_info *si,
++	  efi_guid_t *proto, unsigned long size, void **handles)
+ {
+-	efi_graphics_output_protocol_64_t *gop64, *first_gop;
++	efi_graphics_output_protocol_t *gop, *first_gop;
+ 	unsigned long nr_gops;
+ 	u16 width, height;
+ 	u32 pixels_per_scan_line;
+@@ -193,24 +99,26 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
+ 	efi_pixel_bitmask_t pixel_info;
+ 	int pixel_format;
+ 	efi_status_t status;
+-	u64 *handles = (u64 *)(unsigned long)gop_handle;
+ 	int i;
++	bool is64 = efi_is_64bit();
+ 
+ 	first_gop = NULL;
+-	gop64 = NULL;
++	gop = NULL;
+ 
+-	nr_gops = size / sizeof(u64);
++	nr_gops = size / (is64 ? sizeof(u64) : sizeof(u32));
+ 	for (i = 0; i < nr_gops; i++) {
+-		efi_graphics_output_protocol_mode_64_t *mode;
++		efi_graphics_output_protocol_mode_t *mode;
+ 		efi_graphics_output_mode_info_t *info = NULL;
+ 		efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
+ 		bool conout_found = false;
+ 		void *dummy = NULL;
+-		efi_handle_t h = (efi_handle_t)(unsigned long)handles[i];
++		efi_handle_t h = (efi_handle_t)(unsigned long)
++				 (is64 ? ((u64 *)handles)[i]
++				       : ((u32 *)handles)[i]);
+ 		efi_physical_addr_t current_fb_base;
+ 
+ 		status = efi_call_early(handle_protocol, h,
+-					proto, (void **)&gop64);
++					proto, (void **)&gop);
+ 		if (status != EFI_SUCCESS)
+ 			continue;
+ 
+@@ -219,9 +127,9 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
+ 		if (status == EFI_SUCCESS)
+ 			conout_found = true;
+ 
+-		mode = (void *)(unsigned long)gop64->mode;
+-		info = (void *)(unsigned long)mode->info;
+-		current_fb_base = mode->frame_buffer_base;
++		mode = (void *)(unsigned long)efi_gop_attr(, mode, gop);
++		info = (void *)(unsigned long)efi_gop_attr(_mode, info, mode);
++		current_fb_base = efi_gop_attr(_mode, frame_buffer_base, mode);
+ 
+ 		if ((!first_gop || conout_found) &&
+ 		    info->pixel_format != PIXEL_BLT_ONLY) {
+@@ -243,7 +151,7 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
+ 			 * Once we've found a GOP supporting ConOut,
+ 			 * don't bother looking any further.
+ 			 */
+-			first_gop = gop64;
++			first_gop = gop;
+ 			if (conout_found)
+ 				break;
+ 		}
+@@ -298,13 +206,7 @@ efi_status_t efi_setup_gop(efi_system_table_t *sys_table_arg,
+ 	if (status != EFI_SUCCESS)
+ 		goto free_handle;
+ 
+-	if (efi_is_64bit()) {
+-		status = setup_gop64(sys_table_arg, si, proto, size,
+-				     gop_handle);
+-	} else {
+-		status = setup_gop32(sys_table_arg, si, proto, size,
+-				     gop_handle);
+-	}
++	status = setup_gop(sys_table_arg, si, proto, size, gop_handle);
+ 
+ free_handle:
+ 	efi_call_early(free_pool, gop_handle);

commit 44c84b4ada73b8ff156181fcf6e320459b8daefd
+Author: Arvind Sankar 
+Date:   Tue Dec 24 16:10:03 2019 +0100
+
+    efi/gop: Convert GOP structures to typedef and clean up some types
+    
+    Use typedef for the GOP structures, in anticipation of unifying
+    32/64-bit code. Also use more appropriate types in the non-bitness
+    specific structures for the framebuffer address and pointers.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+    Cc: Borislav Petkov 
+    Cc: James Morse 
+    Cc: Matt Fleming 
+    Cc: Thomas Gleixner 
+    Cc: linux-efi@vger.kernel.org
+    Link: https://lkml.kernel.org/r/20191224151025.32482-4-ardb@kernel.org
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
+index b7bf1e993b8b..a0c1ef64d445 100644
+--- a/drivers/firmware/efi/libstub/gop.c
++++ b/drivers/firmware/efi/libstub/gop.c
+@@ -35,7 +35,7 @@ static void find_bits(unsigned long mask, u8 *pos, u8 *size)
+ 
+ static void
+ setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line,
+-		 struct efi_pixel_bitmask pixel_info, int pixel_format)
++		 efi_pixel_bitmask_t pixel_info, int pixel_format)
+ {
+ 	if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) {
+ 		si->lfb_depth = 32;
+@@ -87,13 +87,13 @@ static efi_status_t
+ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
+             efi_guid_t *proto, unsigned long size, void **gop_handle)
+ {
+-	struct efi_graphics_output_protocol_32 *gop32, *first_gop;
++	efi_graphics_output_protocol_32_t *gop32, *first_gop;
+ 	unsigned long nr_gops;
+ 	u16 width, height;
+ 	u32 pixels_per_scan_line;
+ 	u32 ext_lfb_base;
+-	u64 fb_base;
+-	struct efi_pixel_bitmask pixel_info;
++	efi_physical_addr_t fb_base;
++	efi_pixel_bitmask_t pixel_info;
+ 	int pixel_format;
+ 	efi_status_t status;
+ 	u32 *handles = (u32 *)(unsigned long)gop_handle;
+@@ -104,13 +104,13 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
+ 
+ 	nr_gops = size / sizeof(u32);
+ 	for (i = 0; i < nr_gops; i++) {
+-		struct efi_graphics_output_protocol_mode_32 *mode;
+-		struct efi_graphics_output_mode_info *info = NULL;
++		efi_graphics_output_protocol_mode_32_t *mode;
++		efi_graphics_output_mode_info_t *info = NULL;
+ 		efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
+ 		bool conout_found = false;
+ 		void *dummy = NULL;
+ 		efi_handle_t h = (efi_handle_t)(unsigned long)handles[i];
+-		u64 current_fb_base;
++		efi_physical_addr_t current_fb_base;
+ 
+ 		status = efi_call_early(handle_protocol, h,
+ 					proto, (void **)&gop32);
+@@ -184,13 +184,13 @@ static efi_status_t
+ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
+ 	    efi_guid_t *proto, unsigned long size, void **gop_handle)
+ {
+-	struct efi_graphics_output_protocol_64 *gop64, *first_gop;
++	efi_graphics_output_protocol_64_t *gop64, *first_gop;
+ 	unsigned long nr_gops;
+ 	u16 width, height;
+ 	u32 pixels_per_scan_line;
+ 	u32 ext_lfb_base;
+-	u64 fb_base;
+-	struct efi_pixel_bitmask pixel_info;
++	efi_physical_addr_t fb_base;
++	efi_pixel_bitmask_t pixel_info;
+ 	int pixel_format;
+ 	efi_status_t status;
+ 	u64 *handles = (u64 *)(unsigned long)gop_handle;
+@@ -201,13 +201,13 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
+ 
+ 	nr_gops = size / sizeof(u64);
+ 	for (i = 0; i < nr_gops; i++) {
+-		struct efi_graphics_output_protocol_mode_64 *mode;
+-		struct efi_graphics_output_mode_info *info = NULL;
++		efi_graphics_output_protocol_mode_64_t *mode;
++		efi_graphics_output_mode_info_t *info = NULL;
+ 		efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
+ 		bool conout_found = false;
+ 		void *dummy = NULL;
+ 		efi_handle_t h = (efi_handle_t)(unsigned long)handles[i];
+-		u64 current_fb_base;
++		efi_physical_addr_t current_fb_base;
+ 
+ 		status = efi_call_early(handle_protocol, h,
+ 					proto, (void **)&gop64);
+diff --git a/include/linux/efi.h b/include/linux/efi.h
+index 9ea81cfe1576..561db9deedae 100644
+--- a/include/linux/efi.h
++++ b/include/linux/efi.h
+@@ -1415,69 +1415,69 @@ struct efi_simple_text_output_protocol {
+ #define PIXEL_BLT_ONLY					3
+ #define PIXEL_FORMAT_MAX				4
+ 
+-struct efi_pixel_bitmask {
++typedef struct {
+ 	u32 red_mask;
+ 	u32 green_mask;
+ 	u32 blue_mask;
+ 	u32 reserved_mask;
+-};
++} efi_pixel_bitmask_t;
+ 
+-struct efi_graphics_output_mode_info {
++typedef struct {
+ 	u32 version;
+ 	u32 horizontal_resolution;
+ 	u32 vertical_resolution;
+ 	int pixel_format;
+-	struct efi_pixel_bitmask pixel_information;
++	efi_pixel_bitmask_t pixel_information;
+ 	u32 pixels_per_scan_line;
+-};
++} efi_graphics_output_mode_info_t;
+ 
+-struct efi_graphics_output_protocol_mode_32 {
++typedef struct {
+ 	u32 max_mode;
+ 	u32 mode;
+ 	u32 info;
+ 	u32 size_of_info;
+ 	u64 frame_buffer_base;
+ 	u32 frame_buffer_size;
+-};
++} efi_graphics_output_protocol_mode_32_t;
+ 
+-struct efi_graphics_output_protocol_mode_64 {
++typedef struct {
+ 	u32 max_mode;
+ 	u32 mode;
+ 	u64 info;
+ 	u64 size_of_info;
+ 	u64 frame_buffer_base;
+ 	u64 frame_buffer_size;
+-};
++} efi_graphics_output_protocol_mode_64_t;
+ 
+-struct efi_graphics_output_protocol_mode {
++typedef struct {
+ 	u32 max_mode;
+ 	u32 mode;
+-	unsigned long info;
++	efi_graphics_output_mode_info_t *info;
+ 	unsigned long size_of_info;
+-	u64 frame_buffer_base;
++	efi_physical_addr_t frame_buffer_base;
+ 	unsigned long frame_buffer_size;
+-};
++} efi_graphics_output_protocol_mode_t;
+ 
+-struct efi_graphics_output_protocol_32 {
++typedef struct {
+ 	u32 query_mode;
+ 	u32 set_mode;
+ 	u32 blt;
+ 	u32 mode;
+-};
++} efi_graphics_output_protocol_32_t;
+ 
+-struct efi_graphics_output_protocol_64 {
++typedef struct {
+ 	u64 query_mode;
+ 	u64 set_mode;
+ 	u64 blt;
+ 	u64 mode;
+-};
++} efi_graphics_output_protocol_64_t;
+ 
+-struct efi_graphics_output_protocol {
+-	unsigned long query_mode;
+-	unsigned long set_mode;
+-	unsigned long blt;
+-	struct efi_graphics_output_protocol_mode *mode;
+-};
++typedef struct {
++	void *query_mode;
++	void *set_mode;
++	void *blt;
++	efi_graphics_output_protocol_mode_t *mode;
++} efi_graphics_output_protocol_t;
+ 
+ extern struct list_head efivar_sysfs_list;
+ 

commit 6c895c2fca8a8d4e740b5498b48f81111569502a
+Author: Arvind Sankar 
+Date:   Tue Dec 24 16:10:02 2019 +0100
+
+    efi/gop: Remove unused typedef
+    
+    We have stopped using gop->query_mode(), so remove the unused typedef
+    for the function prototype.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+    Cc: Borislav Petkov 
+    Cc: James Morse 
+    Cc: Matt Fleming 
+    Cc: Thomas Gleixner 
+    Cc: linux-efi@vger.kernel.org
+    Link: https://lkml.kernel.org/r/20191224151025.32482-3-ardb@kernel.org
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/include/linux/efi.h b/include/linux/efi.h
+index 83a62f5c3fd7..9ea81cfe1576 100644
+--- a/include/linux/efi.h
++++ b/include/linux/efi.h
+@@ -1479,10 +1479,6 @@ struct efi_graphics_output_protocol {
+ 	struct efi_graphics_output_protocol_mode *mode;
+ };
+ 
+-typedef efi_status_t (*efi_graphics_output_protocol_query_mode)(
+-	struct efi_graphics_output_protocol *, u32, unsigned long *,
+-	struct efi_graphics_output_mode_info **);
+-
+ extern struct list_head efivar_sysfs_list;
+ 
+ static inline void

commit 8d62af1778125bd674cc66e8432305cc6aac5d89
+Author: Arvind Sankar 
+Date:   Tue Dec 24 16:10:01 2019 +0100
+
+    efi/gop: Remove bogus packed attribute from GOP structures
+    
+    EFI structures are not packed, they follow natural alignment.
+    
+    The packed attribute doesn't have any effect on the structure layout due
+    to the types and order of the members, and we only ever get these
+    structures as output from the EFI firmware so alignment issues have not
+    come up.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+    Cc: Borislav Petkov 
+    Cc: James Morse 
+    Cc: Matt Fleming 
+    Cc: Thomas Gleixner 
+    Cc: linux-efi@vger.kernel.org
+    Link: https://lkml.kernel.org/r/20191224151025.32482-2-ardb@kernel.org
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/include/linux/efi.h b/include/linux/efi.h
+index aa54586db7a5..83a62f5c3fd7 100644
+--- a/include/linux/efi.h
++++ b/include/linux/efi.h
+@@ -1429,7 +1429,7 @@ struct efi_graphics_output_mode_info {
+ 	int pixel_format;
+ 	struct efi_pixel_bitmask pixel_information;
+ 	u32 pixels_per_scan_line;
+-} __packed;
++};
+ 
+ struct efi_graphics_output_protocol_mode_32 {
+ 	u32 max_mode;
+@@ -1438,7 +1438,7 @@ struct efi_graphics_output_protocol_mode_32 {
+ 	u32 size_of_info;
+ 	u64 frame_buffer_base;
+ 	u32 frame_buffer_size;
+-} __packed;
++};
+ 
+ struct efi_graphics_output_protocol_mode_64 {
+ 	u32 max_mode;
+@@ -1447,7 +1447,7 @@ struct efi_graphics_output_protocol_mode_64 {
+ 	u64 size_of_info;
+ 	u64 frame_buffer_base;
+ 	u64 frame_buffer_size;
+-} __packed;
++};
+ 
+ struct efi_graphics_output_protocol_mode {
+ 	u32 max_mode;
+@@ -1456,7 +1456,7 @@ struct efi_graphics_output_protocol_mode {
+ 	unsigned long size_of_info;
+ 	u64 frame_buffer_base;
+ 	unsigned long frame_buffer_size;
+-} __packed;
++};
+ 
+ struct efi_graphics_output_protocol_32 {
+ 	u32 query_mode;

commit d92b54570d24d017d2630e314b525ed792f5aa6c
+Author: Arvind Sankar 
+Date:   Tue Dec 24 14:29:07 2019 +0100
+
+    efi/earlycon: Fix write-combine mapping on x86
+    
+    On x86, until PAT is initialized, WC translates into UC-. Since we
+    calculate and store pgprot_writecombine(PAGE_KERNEL) when earlycon is
+    initialized, this means we actually use UC- mappings instead of WC
+    mappings, which makes scrolling very slow.
+    
+    Instead store a boolean flag to indicate whether we want to use
+    writeback or write-combine mappings, and recalculate the actual pgprot_t
+    we need on every mapping. Once PAT is initialized, we will start using
+    write-combine mappings, which speeds up the scrolling considerably.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+    Cc: Hans de Goede 
+    Cc: Linus Torvalds 
+    Cc: Peter Zijlstra 
+    Cc: Thomas Gleixner 
+    Cc: linux-efi@vger.kernel.org
+    Fixes: 69c1f396f25b ("efi/x86: Convert x86 EFI earlyprintk into generic earlycon implementation")
+    Link: https://lkml.kernel.org/r/20191224132909.102540-2-ardb@kernel.org
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/drivers/firmware/efi/earlycon.c b/drivers/firmware/efi/earlycon.c
+index d4077db6dc97..5d4f84781aa0 100644
+--- a/drivers/firmware/efi/earlycon.c
++++ b/drivers/firmware/efi/earlycon.c
+@@ -17,7 +17,7 @@ static const struct console *earlycon_console __initdata;
+ static const struct font_desc *font;
+ static u32 efi_x, efi_y;
+ static u64 fb_base;
+-static pgprot_t fb_prot;
++static bool fb_wb;
+ static void *efi_fb;
+ 
+ /*
+@@ -33,10 +33,8 @@ static int __init efi_earlycon_remap_fb(void)
+ 	if (!earlycon_console || !(earlycon_console->flags & CON_ENABLED))
+ 		return 0;
+ 
+-	if (pgprot_val(fb_prot) == pgprot_val(PAGE_KERNEL))
+-		efi_fb = memremap(fb_base, screen_info.lfb_size, MEMREMAP_WB);
+-	else
+-		efi_fb = memremap(fb_base, screen_info.lfb_size, MEMREMAP_WC);
++	efi_fb = memremap(fb_base, screen_info.lfb_size,
++			  fb_wb ? MEMREMAP_WB : MEMREMAP_WC);
+ 
+ 	return efi_fb ? 0 : -ENOMEM;
+ }
+@@ -53,9 +51,12 @@ late_initcall(efi_earlycon_unmap_fb);
+ 
+ static __ref void *efi_earlycon_map(unsigned long start, unsigned long len)
+ {
++	pgprot_t fb_prot;
++
+ 	if (efi_fb)
+ 		return efi_fb + start;
+ 
++	fb_prot = fb_wb ? PAGE_KERNEL : pgprot_writecombine(PAGE_KERNEL);
+ 	return early_memremap_prot(fb_base + start, len, pgprot_val(fb_prot));
+ }
+ 
+@@ -215,10 +216,7 @@ static int __init efi_earlycon_setup(struct earlycon_device *device,
+ 	if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
+ 		fb_base |= (u64)screen_info.ext_lfb_base << 32;
+ 
+-	if (opt && !strcmp(opt, "ram"))
+-		fb_prot = PAGE_KERNEL;
+-	else
+-		fb_prot = pgprot_writecombine(PAGE_KERNEL);
++	fb_wb = opt && !strcmp(opt, "ram");
+ 
+ 	si = &screen_info;
+ 	xres = si->lfb_width;

commit 9fa76ca7b8bdcdf51fc8c7b7b7a7bfc4eccceb58
+Author: Arvind Sankar 
+Date:   Fri Dec 6 16:55:41 2019 +0000
+
+    efi: Fix efi_loaded_image_t::unload type
+    
+    The ::unload field is a function pointer, so it should be u32 for 32-bit,
+    u64 for 64-bit. Add a prototype for it in the native efi_loaded_image_t
+    type. Also change type of parent_handle and device_handle from void * to
+    efi_handle_t for documentation purposes.
+    
+    The unload method is not used, so no functional change.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+    Cc: Andy Shevchenko 
+    Cc: Bhupesh Sharma 
+    Cc: Linus Torvalds 
+    Cc: Masayoshi Mizuma 
+    Cc: Peter Zijlstra 
+    Cc: Thomas Gleixner 
+    Cc: linux-efi@vger.kernel.org
+    Link: https://lkml.kernel.org/r/20191206165542.31469-6-ardb@kernel.org
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/include/linux/efi.h b/include/linux/efi.h
+index 99dfea595c8c..aa54586db7a5 100644
+--- a/include/linux/efi.h
++++ b/include/linux/efi.h
+@@ -824,7 +824,7 @@ typedef struct {
+ 	__aligned_u64 image_size;
+ 	unsigned int image_code_type;
+ 	unsigned int image_data_type;
+-	unsigned long unload;
++	u32 unload;
+ } efi_loaded_image_32_t;
+ 
+ typedef struct {
+@@ -840,14 +840,14 @@ typedef struct {
+ 	__aligned_u64 image_size;
+ 	unsigned int image_code_type;
+ 	unsigned int image_data_type;
+-	unsigned long unload;
++	u64 unload;
+ } efi_loaded_image_64_t;
+ 
+ typedef struct {
+ 	u32 revision;
+-	void *parent_handle;
++	efi_handle_t parent_handle;
+ 	efi_system_table_t *system_table;
+-	void *device_handle;
++	efi_handle_t device_handle;
+ 	void *file_path;
+ 	void *reserved;
+ 	u32 load_options_size;
+@@ -856,7 +856,7 @@ typedef struct {
+ 	__aligned_u64 image_size;
+ 	unsigned int image_code_type;
+ 	unsigned int image_data_type;
+-	unsigned long unload;
++	efi_status_t (*unload)(efi_handle_t image_handle);
+ } efi_loaded_image_t;
+ 
+ 

commit ff397be685e410a59c34b21ce0c55d4daa466bb7
+Author: Arvind Sankar 
+Date:   Fri Dec 6 16:55:40 2019 +0000
+
+    efi/gop: Fix memory leak in __gop_query32/64()
+    
+    efi_graphics_output_protocol::query_mode() returns info in
+    callee-allocated memory which must be freed by the caller, which
+    we aren't doing.
+    
+    We don't actually need to call query_mode() in order to obtain the
+    info for the current graphics mode, which is already there in
+    gop->mode->info, so just access it directly in the setup_gop32/64()
+    functions.
+    
+    Also nothing uses the size of the info structure, so don't update the
+    passed-in size (which is the size of the gop_handle table in bytes)
+    unnecessarily.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+    Cc: Andy Shevchenko 
+    Cc: Bhupesh Sharma 
+    Cc: Masayoshi Mizuma 
+    Cc: linux-efi@vger.kernel.org
+    Link: https://lkml.kernel.org/r/20191206165542.31469-5-ardb@kernel.org
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
+index 69b2b019a1d0..b7bf1e993b8b 100644
+--- a/drivers/firmware/efi/libstub/gop.c
++++ b/drivers/firmware/efi/libstub/gop.c
+@@ -83,30 +83,6 @@ setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line,
+ 	}
+ }
+ 
+-static efi_status_t
+-__gop_query32(efi_system_table_t *sys_table_arg,
+-	      struct efi_graphics_output_protocol_32 *gop32,
+-	      struct efi_graphics_output_mode_info **info,
+-	      unsigned long *size, u64 *fb_base)
+-{
+-	struct efi_graphics_output_protocol_mode_32 *mode;
+-	efi_graphics_output_protocol_query_mode query_mode;
+-	efi_status_t status;
+-	unsigned long m;
+-
+-	m = gop32->mode;
+-	mode = (struct efi_graphics_output_protocol_mode_32 *)m;
+-	query_mode = (void *)(unsigned long)gop32->query_mode;
+-
+-	status = __efi_call_early(query_mode, (void *)gop32, mode->mode, size,
+-				  info);
+-	if (status != EFI_SUCCESS)
+-		return status;
+-
+-	*fb_base = mode->frame_buffer_base;
+-	return status;
+-}
+-
+ static efi_status_t
+ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
+             efi_guid_t *proto, unsigned long size, void **gop_handle)
+@@ -128,6 +104,7 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
+ 
+ 	nr_gops = size / sizeof(u32);
+ 	for (i = 0; i < nr_gops; i++) {
++		struct efi_graphics_output_protocol_mode_32 *mode;
+ 		struct efi_graphics_output_mode_info *info = NULL;
+ 		efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
+ 		bool conout_found = false;
+@@ -145,9 +122,11 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
+ 		if (status == EFI_SUCCESS)
+ 			conout_found = true;
+ 
+-		status = __gop_query32(sys_table_arg, gop32, &info, &size,
+-				       ¤t_fb_base);
+-		if (status == EFI_SUCCESS && (!first_gop || conout_found) &&
++		mode = (void *)(unsigned long)gop32->mode;
++		info = (void *)(unsigned long)mode->info;
++		current_fb_base = mode->frame_buffer_base;
++
++		if ((!first_gop || conout_found) &&
+ 		    info->pixel_format != PIXEL_BLT_ONLY) {
+ 			/*
+ 			 * Systems that use the UEFI Console Splitter may
+@@ -201,30 +180,6 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
+ 	return EFI_SUCCESS;
+ }
+ 
+-static efi_status_t
+-__gop_query64(efi_system_table_t *sys_table_arg,
+-	      struct efi_graphics_output_protocol_64 *gop64,
+-	      struct efi_graphics_output_mode_info **info,
+-	      unsigned long *size, u64 *fb_base)
+-{
+-	struct efi_graphics_output_protocol_mode_64 *mode;
+-	efi_graphics_output_protocol_query_mode query_mode;
+-	efi_status_t status;
+-	unsigned long m;
+-
+-	m = gop64->mode;
+-	mode = (struct efi_graphics_output_protocol_mode_64 *)m;
+-	query_mode = (void *)(unsigned long)gop64->query_mode;
+-
+-	status = __efi_call_early(query_mode, (void *)gop64, mode->mode, size,
+-				  info);
+-	if (status != EFI_SUCCESS)
+-		return status;
+-
+-	*fb_base = mode->frame_buffer_base;
+-	return status;
+-}
+-
+ static efi_status_t
+ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
+ 	    efi_guid_t *proto, unsigned long size, void **gop_handle)
+@@ -246,6 +201,7 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
+ 
+ 	nr_gops = size / sizeof(u64);
+ 	for (i = 0; i < nr_gops; i++) {
++		struct efi_graphics_output_protocol_mode_64 *mode;
+ 		struct efi_graphics_output_mode_info *info = NULL;
+ 		efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
+ 		bool conout_found = false;
+@@ -263,9 +219,11 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
+ 		if (status == EFI_SUCCESS)
+ 			conout_found = true;
+ 
+-		status = __gop_query64(sys_table_arg, gop64, &info, &size,
+-				       ¤t_fb_base);
+-		if (status == EFI_SUCCESS && (!first_gop || conout_found) &&
++		mode = (void *)(unsigned long)gop64->mode;
++		info = (void *)(unsigned long)mode->info;
++		current_fb_base = mode->frame_buffer_base;
++
++		if ((!first_gop || conout_found) &&
+ 		    info->pixel_format != PIXEL_BLT_ONLY) {
+ 			/*
+ 			 * Systems that use the UEFI Console Splitter may

commit dbd89c303b4420f6cdb689fd398349fc83b059dd
+Author: Arvind Sankar 
+Date:   Fri Dec 6 16:55:39 2019 +0000
+
+    efi/gop: Return EFI_SUCCESS if a usable GOP was found
+    
+    If we've found a usable instance of the Graphics Output Protocol
+    (GOP) with a framebuffer, it is possible that one of the later EFI
+    calls fails while checking if any support console output. In this
+    case status may be an EFI error code even though we found a usable
+    GOP.
+    
+    Fix this by explicitly return EFI_SUCCESS if a usable GOP has been
+    located.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+    Cc: Andy Shevchenko 
+    Cc: Bhupesh Sharma 
+    Cc: Masayoshi Mizuma 
+    Cc: linux-efi@vger.kernel.org
+    Link: https://lkml.kernel.org/r/20191206165542.31469-4-ardb@kernel.org
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
+index 08f3c1a2fb48..69b2b019a1d0 100644
+--- a/drivers/firmware/efi/libstub/gop.c
++++ b/drivers/firmware/efi/libstub/gop.c
+@@ -198,7 +198,7 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
+ 
+ 	si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS;
+ 
+-	return status;
++	return EFI_SUCCESS;
+ }
+ 
+ static efi_status_t
+@@ -316,7 +316,7 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
+ 
+ 	si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS;
+ 
+-	return status;
++	return EFI_SUCCESS;
+ }
+ 
+ /*

commit 6fc3cec30dfeee7d3c5db8154016aff9d65503c5
+Author: Arvind Sankar 
+Date:   Fri Dec 6 16:55:38 2019 +0000
+
+    efi/gop: Return EFI_NOT_FOUND if there are no usable GOPs
+    
+    If we don't find a usable instance of the Graphics Output Protocol
+    (GOP) because none of them have a framebuffer (i.e. they were all
+    PIXEL_BLT_ONLY), but all the EFI calls succeeded, we will return
+    EFI_SUCCESS even though we didn't find a usable GOP.
+    
+    Fix this by explicitly returning EFI_NOT_FOUND if no usable GOPs are
+    found, allowing the caller to probe for UGA instead.
+    
+    Signed-off-by: Arvind Sankar 
+    Signed-off-by: Ard Biesheuvel 
+    Cc: Andy Shevchenko 
+    Cc: Bhupesh Sharma 
+    Cc: Masayoshi Mizuma 
+    Cc: linux-efi@vger.kernel.org
+    Link: https://lkml.kernel.org/r/20191206165542.31469-3-ardb@kernel.org
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
+index 0101ca4c13b1..08f3c1a2fb48 100644
+--- a/drivers/firmware/efi/libstub/gop.c
++++ b/drivers/firmware/efi/libstub/gop.c
+@@ -119,7 +119,7 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
+ 	u64 fb_base;
+ 	struct efi_pixel_bitmask pixel_info;
+ 	int pixel_format;
+-	efi_status_t status = EFI_NOT_FOUND;
++	efi_status_t status;
+ 	u32 *handles = (u32 *)(unsigned long)gop_handle;
+ 	int i;
+ 
+@@ -175,7 +175,7 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
+ 
+ 	/* Did we find any GOPs? */
+ 	if (!first_gop)
+-		goto out;
++		return EFI_NOT_FOUND;
+ 
+ 	/* EFI framebuffer */
+ 	si->orig_video_isVGA = VIDEO_TYPE_EFI;
+@@ -197,7 +197,7 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
+ 	si->lfb_size = si->lfb_linelength * si->lfb_height;
+ 
+ 	si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS;
+-out:
++
+ 	return status;
+ }
+ 
+@@ -237,7 +237,7 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
+ 	u64 fb_base;
+ 	struct efi_pixel_bitmask pixel_info;
+ 	int pixel_format;
+-	efi_status_t status = EFI_NOT_FOUND;
++	efi_status_t status;
+ 	u64 *handles = (u64 *)(unsigned long)gop_handle;
+ 	int i;
+ 
+@@ -293,7 +293,7 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
+ 
+ 	/* Did we find any GOPs? */
+ 	if (!first_gop)
+-		goto out;
++		return EFI_NOT_FOUND;
+ 
+ 	/* EFI framebuffer */
+ 	si->orig_video_isVGA = VIDEO_TYPE_EFI;
+@@ -315,7 +315,7 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
+ 	si->lfb_size = si->lfb_linelength * si->lfb_height;
+ 
+ 	si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS;
+-out:
++
+ 	return status;
+ }
+ 

commit 9c24eaf81cc44d4bb38081c99eafd72ed85cf7f3
+Author: Arvind Sankar 
+Date:   Tue Oct 8 10:33:57 2019 -0400
+
+    iommu/vt-d: Return the correct dma mask when we are bypassing the IOMMU
+    
+    We must return a mask covering the full physical RAM when bypassing the
+    IOMMU mapping. Also, in iommu_need_mapping, we need to check using
+    dma_direct_get_required_mask to ensure that the device's dma_mask can
+    cover physical RAM before deciding to bypass IOMMU mapping.
+    
+    Based on an earlier patch from Christoph Hellwig.
+    
+    Fixes: 249baa547901 ("dma-mapping: provide a better default ->get_required_mask")
+    Signed-off-by: Arvind Sankar 
+    Reviewed-by: Lu Baolu 
+    Acked-by: Joerg Roedel 
+    Signed-off-by: Christoph Hellwig 
+
+diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
+index 3f974919d3bd..79e35b3180ac 100644
+--- a/drivers/iommu/intel-iommu.c
++++ b/drivers/iommu/intel-iommu.c
+@@ -3471,7 +3471,7 @@ static bool iommu_need_mapping(struct device *dev)
+ 		if (dev->coherent_dma_mask && dev->coherent_dma_mask < dma_mask)
+ 			dma_mask = dev->coherent_dma_mask;
+ 
+-		if (dma_mask >= dma_get_required_mask(dev))
++		if (dma_mask >= dma_direct_get_required_mask(dev))
+ 			return false;
+ 
+ 		/*
+@@ -3775,6 +3775,13 @@ static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nele
+ 	return nelems;
+ }
+ 
++static u64 intel_get_required_mask(struct device *dev)
++{
++	if (!iommu_need_mapping(dev))
++		return dma_direct_get_required_mask(dev);
++	return DMA_BIT_MASK(32);
++}
++
+ static const struct dma_map_ops intel_dma_ops = {
+ 	.alloc = intel_alloc_coherent,
+ 	.free = intel_free_coherent,
+@@ -3787,6 +3794,7 @@ static const struct dma_map_ops intel_dma_ops = {
+ 	.dma_supported = dma_direct_supported,
+ 	.mmap = dma_common_mmap,
+ 	.get_sgtable = dma_common_get_sgtable,
++	.get_required_mask = intel_get_required_mask,
+ };
+ 
+ static void

commit bec500777089b3c96c53681fc0aa6fee59711d4a
+Author: Arvind Sankar 
+Date:   Mon Oct 7 18:00:02 2019 -0400
+
+    lib/string: Make memzero_explicit() inline instead of external
+    
+    With the use of the barrier implied by barrier_data(), there is no need
+    for memzero_explicit() to be extern. Making it inline saves the overhead
+    of a function call, and allows the code to be reused in arch/*/purgatory
+    without having to duplicate the implementation.
+    
+    Tested-by: Hans de Goede 
+    Signed-off-by: Arvind Sankar 
+    Reviewed-by: Hans de Goede 
+    Cc: Ard Biesheuvel 
+    Cc: Borislav Petkov 
+    Cc: H . Peter Anvin 
+    Cc: Herbert Xu 
+    Cc: Linus Torvalds 
+    Cc: Peter Zijlstra 
+    Cc: Stephan Mueller 
+    Cc: Thomas Gleixner 
+    Cc: linux-crypto@vger.kernel.org
+    Cc: linux-s390@vger.kernel.org
+    Fixes: 906a4bb97f5d ("crypto: sha256 - Use get/put_unaligned_be32 to get input, memzero_explicit")
+    Link: https://lkml.kernel.org/r/20191007220000.GA408752@rani.riverdale.lan
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/include/linux/string.h b/include/linux/string.h
+index b2f9df7f0761..b6ccdc2c7f02 100644
+--- a/include/linux/string.h
++++ b/include/linux/string.h
+@@ -227,7 +227,26 @@ static inline bool strstarts(const char *str, const char *prefix)
+ }
+ 
+ size_t memweight(const void *ptr, size_t bytes);
+-void memzero_explicit(void *s, size_t count);
++
++/**
++ * memzero_explicit - Fill a region of memory (e.g. sensitive
++ *		      keying data) with 0s.
++ * @s: Pointer to the start of the area.
++ * @count: The size of the area.
++ *
++ * Note: usually using memset() is just fine (!), but in cases
++ * where clearing out _local_ data at the end of a scope is
++ * necessary, memzero_explicit() should be used instead in
++ * order to prevent the compiler from optimising away zeroing.
++ *
++ * memzero_explicit() doesn't need an arch-specific version as
++ * it just invokes the one of memset() implicitly.
++ */
++static inline void memzero_explicit(void *s, size_t count)
++{
++	memset(s, 0, count);
++	barrier_data(s);
++}
+ 
+ /**
+  * kbasename - return the last part of a pathname.
+diff --git a/lib/string.c b/lib/string.c
+index cd7a10c19210..08ec58cc673b 100644
+--- a/lib/string.c
++++ b/lib/string.c
+@@ -748,27 +748,6 @@ void *memset(void *s, int c, size_t count)
+ EXPORT_SYMBOL(memset);
+ #endif
+ 
+-/**
+- * memzero_explicit - Fill a region of memory (e.g. sensitive
+- *		      keying data) with 0s.
+- * @s: Pointer to the start of the area.
+- * @count: The size of the area.
+- *
+- * Note: usually using memset() is just fine (!), but in cases
+- * where clearing out _local_ data at the end of a scope is
+- * necessary, memzero_explicit() should be used instead in
+- * order to prevent the compiler from optimising away zeroing.
+- *
+- * memzero_explicit() doesn't need an arch-specific version as
+- * it just invokes the one of memset() implicitly.
+- */
+-void memzero_explicit(void *s, size_t count)
+-{
+-	memset(s, 0, count);
+-	barrier_data(s);
+-}
+-EXPORT_SYMBOL(memzero_explicit);
+-
+ #ifndef __HAVE_ARCH_MEMSET16
+ /**
+  * memset16() - Fill a memory area with a uint16_t

commit ca14c996afe7228ff9b480cf225211cc17212688
+Author: Arvind Sankar 
+Date:   Mon Sep 23 13:17:54 2019 -0400
+
+    x86/purgatory: Disable the stackleak GCC plugin for the purgatory
+    
+    Since commit:
+    
+      b059f801a937 ("x86/purgatory: Use CFLAGS_REMOVE rather than reset KBUILD_CFLAGS")
+    
+    kexec breaks if GCC_PLUGIN_STACKLEAK=y is enabled, as the purgatory
+    contains undefined references to stackleak_track_stack.
+    
+    Attempting to load a kexec kernel results in this failure:
+    
+      kexec: Undefined symbol: stackleak_track_stack
+      kexec-bzImage64: Loading purgatory failed
+    
+    Fix this by disabling the stackleak plugin for the purgatory.
+    
+    Signed-off-by: Arvind Sankar 
+    Reviewed-by: Nick Desaulniers 
+    Cc: Borislav Petkov 
+    Cc: H. Peter Anvin 
+    Cc: Linus Torvalds 
+    Cc: Peter Zijlstra 
+    Cc: Thomas Gleixner 
+    Fixes: b059f801a937 ("x86/purgatory: Use CFLAGS_REMOVE rather than reset KBUILD_CFLAGS")
+    Link: https://lkml.kernel.org/r/20190923171753.GA2252517@rani.riverdale.lan
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile
+index 10fb42da0007..b81b5172cf99 100644
+--- a/arch/x86/purgatory/Makefile
++++ b/arch/x86/purgatory/Makefile
+@@ -23,6 +23,7 @@ KCOV_INSTRUMENT := n
+ 
+ PURGATORY_CFLAGS_REMOVE := -mcmodel=kernel
+ PURGATORY_CFLAGS := -mcmodel=large -ffreestanding -fno-zero-initialized-in-bss
++PURGATORY_CFLAGS += $(DISABLE_STACKLEAK_PLUGIN)
+ 
+ # Default KBUILD_CFLAGS can have -pg option set when FTRACE is enabled. That
+ # in turn leaves some undefined symbols like __fentry__ in purgatory and not

commit af364a447b4ac34c719751fdec5dbdd74d888c3b
+Author: Ilia Mirkin 
+Date:   Mon Jun 10 22:32:45 2019 -0400
+
+    drm/nouveau/kms/nv50-: enable modern color management properties
+    
+    For GF119:GV100, we can enable DEGAMMA/CTM/GAMMA. For earlier GPUs, as
+    there is no CTM, having both degamma and gamma is a bit pointless. Later
+    GPUs currently lack an implementation.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c
+index 929d93b1677e..46e7f4c51f10 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/head.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/head.c
+@@ -512,6 +512,11 @@ nv50_head_create(struct drm_device *dev, int index)
+ 				  &nv50_head_func, "head-%d", head->base.index);
+ 	drm_crtc_helper_add(crtc, &nv50_head_help);
+ 	drm_mode_crtc_set_gamma_size(crtc, 256);
++	if (disp->disp->object.oclass >= GF110_DISP &&
++	    disp->disp->object.oclass < GV100_DISP)
++		drm_crtc_enable_color_mgmt(crtc, 256, true, 256);
++	else
++		drm_crtc_enable_color_mgmt(crtc, 0, false, 256);
+ 
+ 	if (head->func->olut_set) {
+ 		ret = nv50_lut_init(disp, &drm->client.mmu, &head->olut);

commit 88b703527ba70659365d989f29579f1292ebf9c3
+Author: Ilia Mirkin 
+Date:   Tue Jun 11 22:40:36 2019 -0400
+
+    drm/nouveau/kms/gf119-: add ctm property support
+    
+    This adds support on GF119:GV100 (exclusive) for CTM (aka CSC).
+    
+    Signed-off-by: Ilia Mirkin 
+
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/atom.h b/drivers/gpu/drm/nouveau/dispnv50/atom.h
+index b5fae5ab3fa8..75bda111da10 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/atom.h
++++ b/drivers/gpu/drm/nouveau/dispnv50/atom.h
+@@ -184,6 +184,11 @@ struct nv50_wndw_atom {
+ 		} i;
+ 	} xlut;
+ 
++	struct {
++		u32 matrix[12];
++		bool valid;
++	} csc;
++
+ 	struct {
+ 		u8  mode:2;
+ 		u8  interval:4;
+@@ -221,6 +226,7 @@ struct nv50_wndw_atom {
+ 			bool ntfy:1;
+ 			bool sema:1;
+ 			bool xlut:1;
++			bool csc:1;
+ 			bool image:1;
+ 			bool scale:1;
+ 			bool point:1;
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/base907c.c b/drivers/gpu/drm/nouveau/dispnv50/base907c.c
+index 049ce6da321c..fd0c1d84730b 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/base907c.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/base907c.c
+@@ -83,6 +83,68 @@ base907c_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+ 	asyw->xlut.i.load = head907d_olut_load;
+ }
+ 
++static inline u32
++csc_drm_to_base(u64 in)
++{
++	/* base takes a 19-bit 2's complement value in S3.16 format */
++	bool sign = in & BIT_ULL(63);
++	u32 integer = (in >> 32) & 0x7fffffff;
++	u32 fraction = in & 0xffffffff;
++
++	if (integer >= 4) {
++		return (1 << 18) - (sign ? 0 : 1);
++	} else {
++		u32 ret = (integer << 16) | (fraction >> 16);
++		if (sign)
++			ret = -ret;
++		return ret & GENMASK(18, 0);
++	}
++}
++
++static void
++base907c_csc(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
++	     const struct drm_color_ctm *ctm)
++{
++	int i, j;
++
++	for (j = 0; j < 3; j++) {
++		for (i = 0; i < 4; i++) {
++			u32 *val = &asyw->csc.matrix[j * 4 + i];
++			/* DRM does not support constant offset, while
++			 * HW CSC does. Skip it. */
++			if (i == 3) {
++				*val = 0;
++			} else {
++				*val = csc_drm_to_base(ctm->matrix[j * 3 + i]);
++			}
++		}
++	}
++}
++
++static void
++base907c_csc_clr(struct nv50_wndw *wndw)
++{
++	u32 *push;
++	if ((push = evo_wait(&wndw->wndw, 2))) {
++		evo_mthd(push, 0x0140, 1);
++		evo_data(push, 0x00000000);
++		evo_kick(push, &wndw->wndw);
++	}
++}
++
++static void
++base907c_csc_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
++{
++	u32 *push, i;
++	if ((push = evo_wait(&wndw->wndw, 13))) {
++		evo_mthd(push, 0x0140, 12);
++		evo_data(push, asyw->csc.matrix[0] | 0x80000000);
++		for (i = 1; i < 12; i++)
++			evo_data(push, asyw->csc.matrix[i]);
++		evo_kick(push, &wndw->wndw);
++	}
++}
++
+ const struct nv50_wndw_func
+ base907c = {
+ 	.acquire = base507c_acquire,
+@@ -94,6 +156,9 @@ base907c = {
+ 	.ntfy_clr = base507c_ntfy_clr,
+ 	.ntfy_wait_begun = base507c_ntfy_wait_begun,
+ 	.ilut = base907c_ilut,
++	.csc = base907c_csc,
++	.csc_set = base907c_csc_set,
++	.csc_clr = base907c_csc_clr,
+ 	.olut_core = true,
+ 	.xlut_set = base907c_xlut_set,
+ 	.xlut_clr = base907c_xlut_clr,
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
+index dd01ea21da97..c8d078629722 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
+@@ -120,6 +120,7 @@ nv50_wndw_flush_clr(struct nv50_wndw *wndw, u32 *interlock, bool flush,
+ 	if (clr.sema ) wndw->func-> sema_clr(wndw);
+ 	if (clr.ntfy ) wndw->func-> ntfy_clr(wndw);
+ 	if (clr.xlut ) wndw->func-> xlut_clr(wndw);
++	if (clr.csc  ) wndw->func->  csc_clr(wndw);
+ 	if (clr.image) wndw->func->image_clr(wndw);
+ 
+ 	interlock[wndw->interlock.type] |= wndw->interlock.data;
+@@ -147,6 +148,7 @@ nv50_wndw_flush_set(struct nv50_wndw *wndw, u32 *interlock,
+ 		wndw->func->xlut_set(wndw, asyw);
+ 	}
+ 
++	if (asyw->set.csc  ) wndw->func->csc_set  (wndw, asyw);
+ 	if (asyw->set.scale) wndw->func->scale_set(wndw, asyw);
+ 	if (asyw->set.point) {
+ 		if (asyw->set.point = false, asyw->set.mask)
+@@ -347,6 +349,16 @@ nv50_wndw_atomic_check_lut(struct nv50_wndw *wndw,
+ 	    (!armw->visible || (armw->xlut.handle && !asyw->xlut.handle)))
+ 		asyw->set.xlut = true;
+ 
++	if (wndw->func->csc && asyh->state.ctm) {
++		const struct drm_color_ctm *ctm = asyh->state.ctm->data;
++		wndw->func->csc(wndw, asyw, ctm);
++		asyw->csc.valid = true;
++		asyw->set.csc = true;
++	} else {
++		asyw->csc.valid = false;
++		asyw->clr.csc = armw->csc.valid;
++	}
++
+ 	/* Can't do an immediate flip while changing the LUT. */
+ 	asyh->state.pageflip_flags &= ~DRM_MODE_PAGE_FLIP_ASYNC;
+ }
+@@ -416,6 +428,7 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
+ 		asyw->clr.ntfy = armw->ntfy.handle != 0;
+ 		asyw->clr.sema = armw->sema.handle != 0;
+ 		asyw->clr.xlut = armw->xlut.handle != 0;
++		asyw->clr.csc  = armw->csc.valid;
+ 		if (wndw->func->image_clr)
+ 			asyw->clr.image = armw->image.handle[0] != 0;
+ 	}
+@@ -507,6 +520,7 @@ nv50_wndw_atomic_duplicate_state(struct drm_plane *plane)
+ 	asyw->ntfy = armw->ntfy;
+ 	asyw->ilut = NULL;
+ 	asyw->xlut = armw->xlut;
++	asyw->csc  = armw->csc;
+ 	asyw->image = armw->image;
+ 	asyw->point = armw->point;
+ 	asyw->clr.mask = 0;
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.h b/drivers/gpu/drm/nouveau/dispnv50/wndw.h
+index 03f3d8dc235a..1e781d80c990 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/wndw.h
++++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.h
+@@ -65,6 +65,10 @@ struct nv50_wndw_func {
+ 	int (*ntfy_wait_begun)(struct nouveau_bo *, u32 offset,
+ 			       struct nvif_device *);
+ 	void (*ilut)(struct nv50_wndw *, struct nv50_wndw_atom *);
++	void (*csc)(struct nv50_wndw *, struct nv50_wndw_atom *,
++		    const struct drm_color_ctm *);
++	void (*csc_set)(struct nv50_wndw *, struct nv50_wndw_atom *);
++	void (*csc_clr)(struct nv50_wndw *);
+ 	bool ilut_identity;
+ 	bool olut_core;
+ 	void (*xlut_set)(struct nv50_wndw *, struct nv50_wndw_atom *);

commit 7c844e9d95fb210b40398516d3d7525e8fa38a5f
+Author: Ilia Mirkin 
+Date:   Mon Jun 3 01:59:42 2019 -0400
+
+    drm/nouveau/kms/nv50-: remove overlay alpha formats
+    
+    The overlay logic can only do colorkey-based selection, not
+    alpha-blending.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c
+index 7354aaf79158..8ccd96113bad 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c
+@@ -161,9 +161,7 @@ ovly507e_format[] = {
+ 	DRM_FORMAT_YUYV,
+ 	DRM_FORMAT_UYVY,
+ 	DRM_FORMAT_XRGB8888,
+-	DRM_FORMAT_ARGB8888,
+ 	DRM_FORMAT_XRGB1555,
+-	DRM_FORMAT_ARGB1555,
+ 	0
+ };
+ 
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly827e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly827e.c
+index aaa9fe5a4fc8..2e68fc736fe1 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/ovly827e.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/ovly827e.c
+@@ -90,11 +90,8 @@ ovly827e_format[] = {
+ 	DRM_FORMAT_YUYV,
+ 	DRM_FORMAT_UYVY,
+ 	DRM_FORMAT_XRGB8888,
+-	DRM_FORMAT_ARGB8888,
+ 	DRM_FORMAT_XRGB1555,
+-	DRM_FORMAT_ARGB1555,
+ 	DRM_FORMAT_XBGR2101010,
+-	DRM_FORMAT_ABGR2101010,
+ 	0
+ };
+ 
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c
+index f947117d62b1..9efe5e9d5ce4 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c
+@@ -66,13 +66,9 @@ ovly907e_format[] = {
+ 	DRM_FORMAT_YUYV,
+ 	DRM_FORMAT_UYVY,
+ 	DRM_FORMAT_XRGB8888,
+-	DRM_FORMAT_ARGB8888,
+ 	DRM_FORMAT_XRGB1555,
+-	DRM_FORMAT_ARGB1555,
+ 	DRM_FORMAT_XBGR2101010,
+-	DRM_FORMAT_ABGR2101010,
+ 	DRM_FORMAT_XBGR16161616F,
+-	DRM_FORMAT_ABGR16161616F,
+ 	0
+ };
+ 
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly917e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly917e.c
+index fab567e258f9..e24d6fd23450 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/ovly917e.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/ovly917e.c
+@@ -26,15 +26,10 @@ ovly917e_format[] = {
+ 	DRM_FORMAT_YUYV,
+ 	DRM_FORMAT_UYVY,
+ 	DRM_FORMAT_XRGB8888,
+-	DRM_FORMAT_ARGB8888,
+ 	DRM_FORMAT_XRGB1555,
+-	DRM_FORMAT_ARGB1555,
+ 	DRM_FORMAT_XBGR2101010,
+-	DRM_FORMAT_ABGR2101010,
+ 	DRM_FORMAT_XRGB2101010,
+-	DRM_FORMAT_ARGB2101010,
+ 	DRM_FORMAT_XBGR16161616F,
+-	DRM_FORMAT_ABGR16161616F,
+ 	0
+ };
+ 

commit 38a72243235ecf2c1359ce66ebed29a7dfb680f7
+Author: Ilia Mirkin 
+Date:   Mon May 27 22:58:37 2019 -0400
+
+    drm/nouveau/kms/nv50-: add fp16 scanout support
+    
+    Older hardware seems to want 0..1024 values, while new hardware takes
+    0..1 values. We set the gain to 1024 for the earlier display classes.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/base507c.c b/drivers/gpu/drm/nouveau/dispnv50/base507c.c
+index 80e020611bcb..00a85f1e1a4a 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/base507c.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/base507c.c
+@@ -58,12 +58,21 @@ static void
+ base507c_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+ {
+ 	u32 *push;
+-	if ((push = evo_wait(&wndw->wndw, 10))) {
++	if ((push = evo_wait(&wndw->wndw, 13))) {
+ 		evo_mthd(push, 0x0084, 1);
+ 		evo_data(push, asyw->image.mode << 8 |
+ 			       asyw->image.interval << 4);
+ 		evo_mthd(push, 0x00c0, 1);
+ 		evo_data(push, asyw->image.handle[0]);
++		if (asyw->image.format == 0xca) {
++			evo_mthd(push, 0x0110, 2);
++			evo_data(push, 1);
++			evo_data(push, 0x6400);
++		} else {
++			evo_mthd(push, 0x0110, 2);
++			evo_data(push, 0);
++			evo_data(push, 0);
++		}
+ 		evo_mthd(push, 0x0800, 5);
+ 		evo_data(push, asyw->image.offset[0] >> 8);
+ 		evo_data(push, 0x00000000);
+@@ -181,9 +190,6 @@ base507c_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
+ 	const struct drm_framebuffer *fb = asyw->state.fb;
+ 	int ret;
+ 
+-	if (!fb->format->depth)
+-		return -EINVAL;
+-
+ 	ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state,
+ 						  DRM_PLANE_HELPER_NO_SCALING,
+ 						  DRM_PLANE_HELPER_NO_SCALING,
+@@ -202,6 +208,14 @@ base507c_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
+ 	asyh->base.y = asyw->state.src.y1 >> 16;
+ 	asyh->base.w = asyw->state.fb->width;
+ 	asyh->base.h = asyw->state.fb->height;
++
++	/* Some newer formats, esp FP16 ones, don't have a
++	 * "depth". There's nothing that really makes sense there
++	 * either, so just set it to the implicit bit count.
++	 */
++	if (!asyh->base.depth)
++		asyh->base.depth = asyh->base.cpp * 8;
++
+ 	return 0;
+ }
+ 
+@@ -217,6 +231,8 @@ base507c_format[] = {
+ 	DRM_FORMAT_ABGR2101010,
+ 	DRM_FORMAT_XBGR8888,
+ 	DRM_FORMAT_ABGR8888,
++	DRM_FORMAT_XBGR16161616F,
++	DRM_FORMAT_ABGR16161616F,
+ 	0
+ };
+ 
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/base827c.c b/drivers/gpu/drm/nouveau/dispnv50/base827c.c
+index 73646819a0d6..f4c05949dd62 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/base827c.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/base827c.c
+@@ -25,12 +25,21 @@ static void
+ base827c_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+ {
+ 	u32 *push;
+-	if ((push = evo_wait(&wndw->wndw, 10))) {
++	if ((push = evo_wait(&wndw->wndw, 13))) {
+ 		evo_mthd(push, 0x0084, 1);
+ 		evo_data(push, asyw->image.mode << 8 |
+ 			       asyw->image.interval << 4);
+ 		evo_mthd(push, 0x00c0, 1);
+ 		evo_data(push, asyw->image.handle[0]);
++		if (asyw->image.format == 0xca) {
++			evo_mthd(push, 0x0110, 2);
++			evo_data(push, 1);
++			evo_data(push, 0x6400);
++		} else {
++			evo_mthd(push, 0x0110, 2);
++			evo_data(push, 0);
++			evo_data(push, 0);
++		}
+ 		evo_mthd(push, 0x0800, 5);
+ 		evo_data(push, asyw->image.offset[0] >> 8);
+ 		evo_data(push, 0x00000000);
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/base917c.c b/drivers/gpu/drm/nouveau/dispnv50/base917c.c
+index 54d705bb81a5..a1baed4fe0e9 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/base917c.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/base917c.c
+@@ -36,6 +36,8 @@ base917c_format[] = {
+ 	DRM_FORMAT_ABGR8888,
+ 	DRM_FORMAT_XRGB2101010,
+ 	DRM_FORMAT_ARGB2101010,
++	DRM_FORMAT_XBGR16161616F,
++	DRM_FORMAT_ABGR16161616F,
+ 	0
+ };
+ 
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c
+index a3ce53046015..f947117d62b1 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c
+@@ -61,10 +61,25 @@ ovly907e = {
+ 	.update = ovly507e_update,
+ };
+ 
++static const u32
++ovly907e_format[] = {
++	DRM_FORMAT_YUYV,
++	DRM_FORMAT_UYVY,
++	DRM_FORMAT_XRGB8888,
++	DRM_FORMAT_ARGB8888,
++	DRM_FORMAT_XRGB1555,
++	DRM_FORMAT_ARGB1555,
++	DRM_FORMAT_XBGR2101010,
++	DRM_FORMAT_ABGR2101010,
++	DRM_FORMAT_XBGR16161616F,
++	DRM_FORMAT_ABGR16161616F,
++	0
++};
++
+ int
+ ovly907e_new(struct nouveau_drm *drm, int head, s32 oclass,
+ 	     struct nv50_wndw **pwndw)
+ {
+-	return ovly507e_new_(&ovly907e, ovly827e_format, drm, head, oclass,
++	return ovly507e_new_(&ovly907e, ovly907e_format, drm, head, oclass,
+ 			     0x00000004 << (head * 4), pwndw);
+ }
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly917e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly917e.c
+index 505fa7e78523..fab567e258f9 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/ovly917e.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/ovly917e.c
+@@ -33,6 +33,8 @@ ovly917e_format[] = {
+ 	DRM_FORMAT_ABGR2101010,
+ 	DRM_FORMAT_XRGB2101010,
+ 	DRM_FORMAT_ARGB2101010,
++	DRM_FORMAT_XBGR16161616F,
++	DRM_FORMAT_ABGR16161616F,
+ 	0
+ };
+ 
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
+index 0aaa7e0013f6..dd01ea21da97 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
+@@ -204,18 +204,20 @@ static int
+ nv50_wndw_atomic_check_acquire_rgb(struct nv50_wndw_atom *asyw)
+ {
+ 	switch (asyw->state.fb->format->format) {
+-	case DRM_FORMAT_C8         : asyw->image.format = 0x1e; break;
+-	case DRM_FORMAT_XRGB8888   :
+-	case DRM_FORMAT_ARGB8888   : asyw->image.format = 0xcf; break;
+-	case DRM_FORMAT_RGB565     : asyw->image.format = 0xe8; break;
+-	case DRM_FORMAT_XRGB1555   :
+-	case DRM_FORMAT_ARGB1555   : asyw->image.format = 0xe9; break;
+-	case DRM_FORMAT_XBGR2101010:
+-	case DRM_FORMAT_ABGR2101010: asyw->image.format = 0xd1; break;
+-	case DRM_FORMAT_XBGR8888   :
+-	case DRM_FORMAT_ABGR8888   : asyw->image.format = 0xd5; break;
+-	case DRM_FORMAT_XRGB2101010:
+-	case DRM_FORMAT_ARGB2101010: asyw->image.format = 0xdf; break;
++	case DRM_FORMAT_C8           : asyw->image.format = 0x1e; break;
++	case DRM_FORMAT_XRGB8888     :
++	case DRM_FORMAT_ARGB8888     : asyw->image.format = 0xcf; break;
++	case DRM_FORMAT_RGB565       : asyw->image.format = 0xe8; break;
++	case DRM_FORMAT_XRGB1555     :
++	case DRM_FORMAT_ARGB1555     : asyw->image.format = 0xe9; break;
++	case DRM_FORMAT_XBGR2101010  :
++	case DRM_FORMAT_ABGR2101010  : asyw->image.format = 0xd1; break;
++	case DRM_FORMAT_XBGR8888     :
++	case DRM_FORMAT_ABGR8888     : asyw->image.format = 0xd5; break;
++	case DRM_FORMAT_XRGB2101010  :
++	case DRM_FORMAT_ARGB2101010  : asyw->image.format = 0xdf; break;
++	case DRM_FORMAT_XBGR16161616F:
++	case DRM_FORMAT_ABGR16161616F: asyw->image.format = 0xca; break;
+ 	default:
+ 		return -EINVAL;
+ 	}
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c b/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c
+index e52a85c83f7a..826d1d760d3a 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c
+@@ -216,6 +216,8 @@ wndwc37e_format[] = {
+ 	DRM_FORMAT_ABGR8888,
+ 	DRM_FORMAT_XRGB2101010,
+ 	DRM_FORMAT_ARGB2101010,
++	DRM_FORMAT_XBGR16161616F,
++	DRM_FORMAT_ABGR16161616F,
+ 	0
+ };
+ 

commit b7019ac550eb3916f34d79db583e9b7ea2524afa
+Author: Ilia Mirkin 
+Date:   Wed Jun 19 20:13:43 2019 -0400
+
+    drm/nouveau: fix bogus GPL-2 license header
+    
+    The bulk SPDX addition made all these files into GPL-2.0 licensed files.
+    However the remainder of the project is MIT-licensed, these files
+    (primarily header files) were simply missing the boiler plate and got
+    caught up in the global update.
+    
+    Fixes: b24413180f5 (License cleanup: add SPDX GPL-2.0 license identifier to files with no license)
+    Signed-off-by: Ilia Mirkin 
+    Acked-by: Emil Velikov 
+    Acked-by: Karol Herbst 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/dispnv04/cursor.c b/drivers/gpu/drm/nouveau/dispnv04/cursor.c
+index ebf860bd59af..16e09f6b9113 100644
+--- a/drivers/gpu/drm/nouveau/dispnv04/cursor.c
++++ b/drivers/gpu/drm/nouveau/dispnv04/cursor.c
+@@ -1,4 +1,4 @@
+-// SPDX-License-Identifier: GPL-2.0
++// SPDX-License-Identifier: MIT
+ #include 
+ #include 
+ #include "nouveau_drv.h"
+diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.h b/drivers/gpu/drm/nouveau/dispnv04/disp.h
+index c6ed20a09f4a..6ccfc09bcf0f 100644
+--- a/drivers/gpu/drm/nouveau/dispnv04/disp.h
++++ b/drivers/gpu/drm/nouveau/dispnv04/disp.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NV04_DISPLAY_H__
+ #define __NV04_DISPLAY_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl0002.h b/drivers/gpu/drm/nouveau/include/nvif/cl0002.h
+index 1a8b45b4631f..65d432a5bd6c 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/cl0002.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/cl0002.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_CL0002_H__
+ #define __NVIF_CL0002_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl0046.h b/drivers/gpu/drm/nouveau/include/nvif/cl0046.h
+index c0d5eba4f8fc..d490d401870a 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/cl0046.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/cl0046.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_CL0046_H__
+ #define __NVIF_CL0046_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl006b.h b/drivers/gpu/drm/nouveau/include/nvif/cl006b.h
+index d0e8f35d9e92..c960c449e430 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/cl006b.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/cl006b.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_CL006B_H__
+ #define __NVIF_CL006B_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl0080.h b/drivers/gpu/drm/nouveau/include/nvif/cl0080.h
+index 4cbed0329367..cd9a2e687bb6 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/cl0080.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/cl0080.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_CL0080_H__
+ #define __NVIF_CL0080_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl506e.h b/drivers/gpu/drm/nouveau/include/nvif/cl506e.h
+index 989690fe3cd8..9df289c7a84f 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/cl506e.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/cl506e.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_CL506E_H__
+ #define __NVIF_CL506E_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl506f.h b/drivers/gpu/drm/nouveau/include/nvif/cl506f.h
+index 5137b6879abd..327c96a994bb 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/cl506f.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/cl506f.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_CL506F_H__
+ #define __NVIF_CL506F_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
+index bced81987269..38bf4f38e869 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_CL5070_H__
+ #define __NVIF_CL5070_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl507a.h b/drivers/gpu/drm/nouveau/include/nvif/cl507a.h
+index 36e537218596..3b2a9809b8ce 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/cl507a.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/cl507a.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_CL507A_H__
+ #define __NVIF_CL507A_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl507b.h b/drivers/gpu/drm/nouveau/include/nvif/cl507b.h
+index 3e643b752bfc..0f3d05581ea5 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/cl507b.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/cl507b.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_CL507B_H__
+ #define __NVIF_CL507B_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl507c.h b/drivers/gpu/drm/nouveau/include/nvif/cl507c.h
+index fd9e336d0a24..7da8813f4f5c 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/cl507c.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/cl507c.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_CL507C_H__
+ #define __NVIF_CL507C_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl507d.h b/drivers/gpu/drm/nouveau/include/nvif/cl507d.h
+index e994c6894e3e..4a56e42d8bc9 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/cl507d.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/cl507d.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_CL507D_H__
+ #define __NVIF_CL507D_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl507e.h b/drivers/gpu/drm/nouveau/include/nvif/cl507e.h
+index 8082d2fde248..633936cb6313 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/cl507e.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/cl507e.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_CL507E_H__
+ #define __NVIF_CL507E_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl826e.h b/drivers/gpu/drm/nouveau/include/nvif/cl826e.h
+index 1a875090b251..1b6496d31580 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/cl826e.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/cl826e.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_CL826E_H__
+ #define __NVIF_CL826E_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl826f.h b/drivers/gpu/drm/nouveau/include/nvif/cl826f.h
+index e4e50cfe88f1..148602264a76 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/cl826f.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/cl826f.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_CL826F_H__
+ #define __NVIF_CL826F_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl906f.h b/drivers/gpu/drm/nouveau/include/nvif/cl906f.h
+index ab0fa8adb756..3823d6891b55 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/cl906f.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/cl906f.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_CL906F_H__
+ #define __NVIF_CL906F_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl9097.h b/drivers/gpu/drm/nouveau/include/nvif/cl9097.h
+index e4c8de6d00b7..599d858afa36 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/cl9097.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/cl9097.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_CL9097_H__
+ #define __NVIF_CL9097_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/cla06f.h b/drivers/gpu/drm/nouveau/include/nvif/cla06f.h
+index 81401eb970ea..cfa18f1fbf83 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/cla06f.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/cla06f.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_CLA06F_H__
+ #define __NVIF_CLA06F_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/class.h b/drivers/gpu/drm/nouveau/include/nvif/class.h
+index 7d556a1c92fa..f704ae600e94 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/class.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/class.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_CLASS_H__
+ #define __NVIF_CLASS_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/clc36f.h b/drivers/gpu/drm/nouveau/include/nvif/clc36f.h
+index 6b14d7e3f6bb..f66885891238 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/clc36f.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/clc36f.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_CLC36F_H__
+ #define __NVIF_CLC36F_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/clc37b.h b/drivers/gpu/drm/nouveau/include/nvif/clc37b.h
+index 89b18189d43b..970a5ac4cb95 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/clc37b.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/clc37b.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_CLC37B_H__
+ #define __NVIF_CLC37B_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/clc37e.h b/drivers/gpu/drm/nouveau/include/nvif/clc37e.h
+index 899db9e915ef..7ea23695e7e1 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/clc37e.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/clc37e.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_CLC37E_H__
+ #define __NVIF_CLC37E_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/client.h b/drivers/gpu/drm/nouveau/include/nvif/client.h
+index f5df8b30c599..e63c6c965b54 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/client.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/client.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_CLIENT_H__
+ #define __NVIF_CLIENT_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/device.h b/drivers/gpu/drm/nouveau/include/nvif/device.h
+index ef839bd1d37e..25d969dcf67d 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/device.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/device.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_DEVICE_H__
+ #define __NVIF_DEVICE_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/driver.h b/drivers/gpu/drm/nouveau/include/nvif/driver.h
+index 93bccd45a042..8e85b936eaa0 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/driver.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/driver.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_DRIVER_H__
+ #define __NVIF_DRIVER_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/event.h b/drivers/gpu/drm/nouveau/include/nvif/event.h
+index ec5c924f576a..a6b1ee4f10ca 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/event.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/event.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_EVENT_H__
+ #define __NVIF_EVENT_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0000.h b/drivers/gpu/drm/nouveau/include/nvif/if0000.h
+index 30ecd31db5df..f7b8f8f48760 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/if0000.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/if0000.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_IF0000_H__
+ #define __NVIF_IF0000_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0001.h b/drivers/gpu/drm/nouveau/include/nvif/if0001.h
+index ca9215262215..4ced50e98ced 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/if0001.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/if0001.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_IF0001_H__
+ #define __NVIF_IF0001_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0002.h b/drivers/gpu/drm/nouveau/include/nvif/if0002.h
+index d9235c011196..df2915d6a61e 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/if0002.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/if0002.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_IF0002_H__
+ #define __NVIF_IF0002_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0003.h b/drivers/gpu/drm/nouveau/include/nvif/if0003.h
+index ae30b8261b88..78467da07c37 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/if0003.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/if0003.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_IF0003_H__
+ #define __NVIF_IF0003_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0004.h b/drivers/gpu/drm/nouveau/include/nvif/if0004.h
+index b35547c8ea36..d324c73c27fb 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/if0004.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/if0004.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_IF0004_H__
+ #define __NVIF_IF0004_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0005.h b/drivers/gpu/drm/nouveau/include/nvif/if0005.h
+index 8ed0ae101715..fb9305b3b32c 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/if0005.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/if0005.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_IF0005_H__
+ #define __NVIF_IF0005_H__
+ #define NV10_NVSW_NTFY_UEVENT                                              0x00
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/ioctl.h b/drivers/gpu/drm/nouveau/include/nvif/ioctl.h
+index b93d586a2304..886c63fe753f 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/ioctl.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/ioctl.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_IOCTL_H__
+ #define __NVIF_IOCTL_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/notify.h b/drivers/gpu/drm/nouveau/include/nvif/notify.h
+index 4ed169230657..6863732eb286 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/notify.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/notify.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_NOTIFY_H__
+ #define __NVIF_NOTIFY_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/object.h b/drivers/gpu/drm/nouveau/include/nvif/object.h
+index 8407651f6ac6..604fabc0e689 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/object.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/object.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_OBJECT_H__
+ #define __NVIF_OBJECT_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/os.h b/drivers/gpu/drm/nouveau/include/nvif/os.h
+index fd09b2842972..429d0106c123 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/os.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/os.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NOUVEAU_OS_H__
+ #define __NOUVEAU_OS_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/unpack.h b/drivers/gpu/drm/nouveau/include/nvif/unpack.h
+index 7f0d9f6cc1e7..0584b938e8f9 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/unpack.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/unpack.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVIF_UNPACK_H__
+ #define __NVIF_UNPACK_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/client.h b/drivers/gpu/drm/nouveau/include/nvkm/core/client.h
+index 757fac823a10..5d7017fe5039 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/core/client.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/core/client.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_CLIENT_H__
+ #define __NVKM_CLIENT_H__
+ #define nvkm_client(p) container_of((p), struct nvkm_client, object)
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/debug.h b/drivers/gpu/drm/nouveau/include/nvkm/core/debug.h
+index 966d1822dd80..b4a9c7d991ca 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/core/debug.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/core/debug.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_DEBUG_H__
+ #define __NVKM_DEBUG_H__
+ #define NV_DBG_FATAL    0
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h
+index 642492344196..6d55cd0476aa 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_DEVICE_H__
+ #define __NVKM_DEVICE_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h b/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h
+index 8a2be5b635e2..c6b401a6ea23 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_ENGINE_H__
+ #define __NVKM_ENGINE_H__
+ #define nvkm_engine(p) container_of((p), struct nvkm_engine, subdev)
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/enum.h b/drivers/gpu/drm/nouveau/include/nvkm/core/enum.h
+index 38acbde2de4f..ce98efd4b209 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/core/enum.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/core/enum.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_ENUM_H__
+ #define __NVKM_ENUM_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/event.h b/drivers/gpu/drm/nouveau/include/nvkm/core/event.h
+index d3c45e90a1c1..a7a413f07a78 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/core/event.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/core/event.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_EVENT_H__
+ #define __NVKM_EVENT_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h b/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h
+index 54da9c6bc8d5..383370c32428 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_FIRMWARE_H__
+ #define __NVKM_FIRMWARE_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/gpuobj.h b/drivers/gpu/drm/nouveau/include/nvkm/core/gpuobj.h
+index 10eeaeebc242..0f515ec28fa9 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/core/gpuobj.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/core/gpuobj.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_GPUOBJ_H__
+ #define __NVKM_GPUOBJ_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/ioctl.h b/drivers/gpu/drm/nouveau/include/nvkm/core/ioctl.h
+index e2d39192fa26..71ed147ad077 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/core/ioctl.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/core/ioctl.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_IOCTL_H__
+ #define __NVKM_IOCTL_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h b/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h
+index f34c80310861..b23bf6109f2d 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_MEMORY_H__
+ #define __NVKM_MEMORY_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/mm.h b/drivers/gpu/drm/nouveau/include/nvkm/core/mm.h
+index b0726c39429e..4ecfbde88537 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/core/mm.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/core/mm.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_MM_H__
+ #define __NVKM_MM_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/notify.h b/drivers/gpu/drm/nouveau/include/nvkm/core/notify.h
+index 4eb82bc563f3..3d358a66db3a 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/core/notify.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/core/notify.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_NOTIFY_H__
+ #define __NVKM_NOTIFY_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/object.h b/drivers/gpu/drm/nouveau/include/nvkm/core/object.h
+index 270f893cc154..7efcd5d2f2ff 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/core/object.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/core/object.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_OBJECT_H__
+ #define __NVKM_OBJECT_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/oproxy.h b/drivers/gpu/drm/nouveau/include/nvkm/core/oproxy.h
+index d950d5ee188b..0e70a9afba33 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/core/oproxy.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/core/oproxy.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_OPROXY_H__
+ #define __NVKM_OPROXY_H__
+ #define nvkm_oproxy(p) container_of((p), struct nvkm_oproxy, base)
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/option.h b/drivers/gpu/drm/nouveau/include/nvkm/core/option.h
+index a34a79bacbd0..6882eb7c7e26 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/core/option.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/core/option.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_OPTION_H__
+ #define __NVKM_OPTION_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/os.h b/drivers/gpu/drm/nouveau/include/nvkm/core/os.h
+index 445602d1e8d3..029a416197db 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/core/os.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/core/os.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_OS_H__
+ #define __NVKM_OS_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h b/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h
+index 4c7f647d2dc9..b4b5df3e1610 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_DEVICE_PCI_H__
+ #define __NVKM_DEVICE_PCI_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/ramht.h b/drivers/gpu/drm/nouveau/include/nvkm/core/ramht.h
+index d5d789663aca..bc2d1dcccb4e 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/core/ramht.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/core/ramht.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_RAMHT_H__
+ #define __NVKM_RAMHT_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h b/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h
+index 85a0777c2ce4..1218f28c14ba 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_SUBDEV_H__
+ #define __NVKM_SUBDEV_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h b/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h
+index 5c102d0206a7..924009dd2bb0 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_DEVICE_TEGRA_H__
+ #define __NVKM_DEVICE_TEGRA_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/bsp.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/bsp.h
+index 40613983fccb..f938f024db81 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/bsp.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/bsp.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_BSP_H__
+ #define __NVKM_BSP_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h
+index 5f3650692e4d..86f420f4630b 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_CE_H__
+ #define __NVKM_CE_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/cipher.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/cipher.h
+index 72b9da2de7c2..66c5c5e27520 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/cipher.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/cipher.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_CIPHER_H__
+ #define __NVKM_CIPHER_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
+index 3026b22d44fb..5a96c942d912 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_DISP_H__
+ #define __NVKM_DISP_H__
+ #define nvkm_disp(p) container_of((p), struct nvkm_disp, engine)
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/dma.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/dma.h
+index f0c1b2c8c78c..2e12cdb6bb93 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/dma.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/dma.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_DMA_H__
+ #define __NVKM_DMA_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h
+index 6427747b6f77..23b582d696c6 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_FALCON_H__
+ #define __NVKM_FALCON_H__
+ #define nvkm_falcon(p) container_of((p), struct nvkm_falcon, engine)
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h
+index b7fc04dd1628..b335f3a1e66d 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_FIFO_H__
+ #define __NVKM_FIFO_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h
+index 1e924c7f7ba7..2cde36f3c064 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_GR_H__
+ #define __NVKM_GR_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/mpeg.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/mpeg.h
+index 4ef3d4c5e358..8585a31f5943 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/mpeg.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/mpeg.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_MPEG_H__
+ #define __NVKM_MPEG_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/msenc.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/msenc.h
+index 985fc9490643..08fbe7b3cb4b 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/msenc.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/msenc.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_MSENC_H__
+ #define __NVKM_MSENC_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/mspdec.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/mspdec.h
+index e03f33472486..83bb2fcb2cbf 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/mspdec.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/mspdec.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_MSPDEC_H__
+ #define __NVKM_MSPDEC_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/msppp.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/msppp.h
+index 760bf17ea63d..69e09fd96e0c 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/msppp.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/msppp.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_MSPPP_H__
+ #define __NVKM_MSPPP_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/msvld.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/msvld.h
+index 281866d2501d..9e11cefc9649 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/msvld.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/msvld.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_MSVLD_H__
+ #define __NVKM_MSVLD_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h
+index b72a4844c5f7..7c7d7f0abfcc 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_NVDEC_H__
+ #define __NVKM_NVDEC_H__
+ #define nvkm_nvdec(p) container_of((p), struct nvkm_nvdec, engine)
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/nvenc.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/nvenc.h
+index cdd68a8bab8b..21624046d0a1 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/nvenc.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/nvenc.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_NVENC_H__
+ #define __NVKM_NVENC_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/pm.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/pm.h
+index 6cce8502f9df..4d754e7650d9 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/pm.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/pm.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_PM_H__
+ #define __NVKM_PM_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec.h
+index b206b918c43e..f14e98a8a0ca 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_SEC_H__
+ #define __NVKM_SEC_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h
+index c93ad332461a..33078f86c779 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_SEC2_H__
+ #define __NVKM_SEC2_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/sw.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/sw.h
+index 83a17c4e11e7..2e91769e3ee2 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/sw.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/sw.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_SW_H__
+ #define __NVKM_SW_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/vic.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/vic.h
+index 9b7d4877cf41..35555c559eab 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/vic.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/vic.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_VIC_H__
+ #define __NVKM_VIC_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/vp.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/vp.h
+index 53bf8aed48fb..8984415b2a3d 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/vp.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/vp.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_VP_H__
+ #define __NVKM_VP_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/xtensa.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/xtensa.h
+index 13c00ce6d556..fbf27b2293a9 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/xtensa.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/xtensa.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_XTENSA_H__
+ #define __NVKM_XTENSA_H__
+ #define nvkm_xtensa(p) container_of((p), struct nvkm_xtensa, engine)
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bar.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bar.h
+index da14486317ca..14b09f7e46a5 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bar.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bar.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_BAR_H__
+ #define __NVKM_BAR_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios.h
+index 979e9a144e7b..f2860f8e0c2e 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_BIOS_H__
+ #define __NVKM_BIOS_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/M0203.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/M0203.h
+index 425ccc47e3b7..9227ed640132 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/M0203.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/M0203.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_M0203_H__
+ #define __NVBIOS_M0203_H__
+ struct nvbios_M0203T {
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/M0205.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/M0205.h
+index b4e14e45a0e8..7ec1dabc5fe4 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/M0205.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/M0205.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_M0205_H__
+ #define __NVBIOS_M0205_H__
+ struct nvbios_M0205T {
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/M0209.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/M0209.h
+index c09376894d12..49a7bb0f3c50 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/M0209.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/M0209.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_M0209_H__
+ #define __NVBIOS_M0209_H__
+ u32 nvbios_M0209Te(struct nvkm_bios *,
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/P0260.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/P0260.h
+index 901d94ef11b8..caad7256d9e5 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/P0260.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/P0260.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_P0260_H__
+ #define __NVBIOS_P0260_H__
+ u32 nvbios_P0260Te(struct nvkm_bios *,
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/bit.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/bit.h
+index d068586f3263..ebfe45fce965 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/bit.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/bit.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_BIT_H__
+ #define __NVBIOS_BIT_H__
+ struct bit_entry {
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/bmp.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/bmp.h
+index 9a3f9483ee75..263408a535ae 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/bmp.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/bmp.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_BMP_H__
+ #define __NVBIOS_BMP_H__
+ static inline u16
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/boost.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/boost.h
+index a1c48c6b223b..489fd3554a17 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/boost.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/boost.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_BOOST_H__
+ #define __NVBIOS_BOOST_H__
+ u32 nvbios_boostTe(struct nvkm_bios *, u8 *, u8 *, u8 *, u8 *, u8 *, u8 *);
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/conn.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/conn.h
+index 8463b421d345..f5f59261ea81 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/conn.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/conn.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_CONN_H__
+ #define __NVBIOS_CONN_H__
+ enum dcb_connector_type {
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/cstep.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/cstep.h
+index 49343d276e11..6a287a016580 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/cstep.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/cstep.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_CSTEP_H__
+ #define __NVBIOS_CSTEP_H__
+ u32 nvbios_cstepTe(struct nvkm_bios *,
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/dcb.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/dcb.h
+index 63ddc6ed897a..a27a0f3fe7aa 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/dcb.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/dcb.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_DCB_H__
+ #define __NVBIOS_DCB_H__
+ enum dcb_output_type {
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/disp.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/disp.h
+index 423d92de0aae..ef44205a91f6 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/disp.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/disp.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_DISP_H__
+ #define __NVBIOS_DISP_H__
+ u16 nvbios_disp_table(struct nvkm_bios *,
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/dp.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/dp.h
+index 512e25a41803..1df5e1618455 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/dp.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/dp.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_DP_H__
+ #define __NVBIOS_DP_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/extdev.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/extdev.h
+index f93e4f951f2f..f29f2d8da142 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/extdev.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/extdev.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_EXTDEV_H__
+ #define __NVBIOS_EXTDEV_H__
+ enum nvbios_extdev_type {
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/fan.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/fan.h
+index 09c1d3b9d009..8b3fb1f5d3ab 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/fan.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/fan.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_FAN_H__
+ #define __NVBIOS_FAN_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h
+index b71a3555c64e..7c4f00366e71 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_GPIO_H__
+ #define __NVBIOS_GPIO_H__
+ enum dcb_gpio_func_name {
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/i2c.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/i2c.h
+index ae1f7483dd28..e84a0eb6df26 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/i2c.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/i2c.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_I2C_H__
+ #define __NVBIOS_I2C_H__
+ enum dcb_i2c_type {
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/iccsense.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/iccsense.h
+index e220a1ac1387..4c108fd2c805 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/iccsense.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/iccsense.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_ICCSENSE_H__
+ #define __NVBIOS_ICCSENSE_H__
+ struct pwr_rail_resistor_t {
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/image.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/image.h
+index 893288b060de..e13dc059a9ee 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/image.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/image.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_IMAGE_H__
+ #define __NVBIOS_IMAGE_H__
+ struct nvbios_image {
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/init.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/init.h
+index 744b1868e789..10df0215475e 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/init.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/init.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_INIT_H__
+ #define __NVBIOS_INIT_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/mxm.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/mxm.h
+index 327bf9c4b703..7204c6f4f247 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/mxm.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/mxm.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_MXM_H__
+ #define __NVBIOS_MXM_H__
+ u16 mxm_table(struct nvkm_bios *, u8 *ver, u8 *hdr);
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/npde.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/npde.h
+index ee5419b7b45b..f10f176a3323 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/npde.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/npde.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_NPDE_H__
+ #define __NVBIOS_NPDE_H__
+ struct nvbios_npdeT {
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/pcir.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/pcir.h
+index 1dffe8d6cc81..bb7bf67d1d19 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/pcir.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/pcir.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_PCIR_H__
+ #define __NVBIOS_PCIR_H__
+ struct nvbios_pcirT {
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/perf.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/perf.h
+index 0ee84ea6d737..1b67c0958721 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/perf.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/perf.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_PERF_H__
+ #define __NVBIOS_PERF_H__
+ u32 nvbios_perf_table(struct nvkm_bios *, u8 *ver, u8 *hdr,
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/pll.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/pll.h
+index ab964e085f02..b2c2d0959f6f 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/pll.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/pll.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_PLL_H__
+ #define __NVBIOS_PLL_H__
+ /*XXX: kill me */
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/pmu.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/pmu.h
+index fb41ecab8f8c..7177d39371cf 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/pmu.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/pmu.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_PMU_H__
+ #define __NVBIOS_PMU_H__
+ struct nvbios_pmuT {
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/power_budget.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/power_budget.h
+index ff12d810dce3..95306be163cc 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/power_budget.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/power_budget.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_POWER_BUDGET_H__
+ #define __NVBIOS_POWER_BUDGET_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h
+index 2b87a38adb7a..153edf898b5d 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_RAMCFG_H__
+ #define __NVBIOS_RAMCFG_H__
+ struct nvbios_ramcfg {
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h
+index 471eef434b51..7f054042f9d7 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_RAMMAP_H__
+ #define __NVBIOS_RAMMAP_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/therm.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/therm.h
+index 46a3b15e10ec..0fb8a3480871 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/therm.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/therm.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_THERM_H__
+ #define __NVBIOS_THERM_H__
+ struct nvbios_therm_threshold {
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/timing.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/timing.h
+index 40ceabf37827..c1f77773aace 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/timing.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/timing.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_TIMING_H__
+ #define __NVBIOS_TIMING_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vmap.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vmap.h
+index 67419bad584c..13103b9b5b96 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vmap.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vmap.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_VMAP_H__
+ #define __NVBIOS_VMAP_H__
+ struct nvbios_vmap {
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h
+index 6b36d5ecb8f9..0c9be1b2ebbf 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_VOLT_H__
+ #define __NVBIOS_VOLT_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vpstate.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vpstate.h
+index 36f3028d58ef..df94e26f873a 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vpstate.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vpstate.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_VPSTATE_H__
+ #define __NVBIOS_VPSTATE_H__
+ struct nvbios_vpstate_header {
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/xpio.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/xpio.h
+index d1bb5d044585..11b4c4d27e5f 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/xpio.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/xpio.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVBIOS_XPIO_H__
+ #define __NVBIOS_XPIO_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bus.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bus.h
+index 7695f7f77a06..ae9ad6c034fb 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bus.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bus.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_BUS_H__
+ #define __NVKM_BUS_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h
+index 15db75ef0189..bf937e7dfd77 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_CLK_H__
+ #define __NVKM_CLK_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/devinit.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/devinit.h
+index 8ba982c2fdfb..1a39e52e09e3 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/devinit.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/devinit.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_DEVINIT_H__
+ #define __NVKM_DEVINIT_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h
+index 27298f8b7ead..239ad222b95a 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_FB_H__
+ #define __NVKM_FB_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fuse.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fuse.h
+index 092193b7f98e..00111c34311e 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fuse.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fuse.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_FUSE_H__
+ #define __NVKM_FUSE_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gpio.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gpio.h
+index ee54899076e3..eaacf8d80527 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gpio.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gpio.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_GPIO_H__
+ #define __NVKM_GPIO_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h
+index 7957eafa5f0e..81b977319640 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_I2C_H__
+ #define __NVKM_I2C_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ibus.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ibus.h
+index 919653c1d101..db791411eaa8 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ibus.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ibus.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_IBUS_H__
+ #define __NVKM_IBUS_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/iccsense.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/iccsense.h
+index be9475cd94fd..f483dcd7cd1c 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/iccsense.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/iccsense.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_ICCSENSE_H__
+ #define __NVKM_ICCSENSE_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h
+index 36ed520ed2d0..c74ab7c31d05 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_INSTMEM_H__
+ #define __NVKM_INSTMEM_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h
+index 9db5f8293198..644d527c3b96 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_LTC_H__
+ #define __NVKM_LTC_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h
+index e38f4958dea2..6641fe4c252c 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_MC_H__
+ #define __NVKM_MC_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h
+index 28ade86f74c5..54cdcb017518 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_MMU_H__
+ #define __NVKM_MMU_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/mxm.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/mxm.h
+index 0fd6d6f8eada..78df1e9def05 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/mxm.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/mxm.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_MXM_H__
+ #define __NVKM_MXM_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h
+index 23803cc859fd..4803a4fad4a2 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_PCI_H__
+ #define __NVKM_PCI_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h
+index 4bc9384046c6..24fbcccd93eb 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_PMU_H__
+ #define __NVKM_PMU_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h
+index 9398d9f09339..62c34f98c930 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_THERM_H__
+ #define __NVKM_THERM_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h
+index 3693ebf371b6..a8c21c6c800b 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_TIMER_H__
+ #define __NVKM_TIMER_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/top.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/top.h
+index 2904e67d79d2..7be0e7e7bd77 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/top.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/top.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_TOP_H__
+ #define __NVKM_TOP_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/vga.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/vga.h
+index 312933ad7c2b..15ee5c321574 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/vga.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/vga.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NOUVEAU_VGA_H__
+ #define __NOUVEAU_VGA_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h
+index 6a765682fbfa..45053a280930 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_VOLT_H__
+ #define __NVKM_VOLT_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.h b/drivers/gpu/drm/nouveau/nouveau_abi16.h
+index 36fde1ff3ad5..195546719bfe 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_abi16.h
++++ b/drivers/gpu/drm/nouveau/nouveau_abi16.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NOUVEAU_ABI16_H__
+ #define __NOUVEAU_ABI16_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c
+index ffb195850314..fe3a10255c36 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_acpi.c
++++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c
+@@ -1,4 +1,4 @@
+-// SPDX-License-Identifier: GPL-2.0
++// SPDX-License-Identifier: MIT
+ #include 
+ #include 
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.h b/drivers/gpu/drm/nouveau/nouveau_acpi.h
+index b86294fc99e8..1e6e8a8c0455 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_acpi.h
++++ b/drivers/gpu/drm/nouveau/nouveau_acpi.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NOUVEAU_ACPI_H__
+ #define __NOUVEAU_ACPI_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.h b/drivers/gpu/drm/nouveau/nouveau_bo.h
+index 846f4bdec0de..383ac36d5869 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_bo.h
++++ b/drivers/gpu/drm/nouveau/nouveau_bo.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NOUVEAU_BO_H__
+ #define __NOUVEAU_BO_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.h b/drivers/gpu/drm/nouveau/nouveau_chan.h
+index 93814d1d31e4..9307357e1361 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_chan.h
++++ b/drivers/gpu/drm/nouveau/nouveau_chan.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NOUVEAU_CHAN_H__
+ #define __NOUVEAU_CHAN_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.h b/drivers/gpu/drm/nouveau/nouveau_debugfs.h
+index 1d01a82d4b6f..9420a6aca138 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_debugfs.h
++++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NOUVEAU_DEBUGFS_H__
+ #define __NOUVEAU_DEBUGFS_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h
+index 311e175f0513..9185f01e2d9b 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_display.h
++++ b/drivers/gpu/drm/nouveau/nouveau_display.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NOUVEAU_DISPLAY_H__
+ #define __NOUVEAU_DISPLAY_H__
+ #include "nouveau_drv.h"
+diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
+index 35ff0ca01a3b..aae035816383 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
++++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NOUVEAU_DRV_H__
+ #define __NOUVEAU_DRV_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h
+index ad27caeca0fd..c9e24baaaa4f 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_fence.h
++++ b/drivers/gpu/drm/nouveau/nouveau_fence.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NOUVEAU_FENCE_H__
+ #define __NOUVEAU_FENCE_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.h b/drivers/gpu/drm/nouveau/nouveau_gem.h
+index fe39998f65cc..03371204a47c 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_gem.h
++++ b/drivers/gpu/drm/nouveau/nouveau_gem.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NOUVEAU_GEM_H__
+ #define __NOUVEAU_GEM_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/nouveau_ioctl.h b/drivers/gpu/drm/nouveau/nouveau_ioctl.h
+index 380ede26806c..d17505530e3e 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_ioctl.h
++++ b/drivers/gpu/drm/nouveau/nouveau_ioctl.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NOUVEAU_IOCTL_H__
+ #define __NOUVEAU_IOCTL_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h b/drivers/gpu/drm/nouveau/nouveau_reg.h
+index b5b5fe40779d..cff7389f6ed3 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_reg.h
++++ b/drivers/gpu/drm/nouveau/nouveau_reg.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ 
+ #define NV04_PFB_BOOT_0						0x00100000
+ #	define NV04_PFB_BOOT_0_RAM_AMOUNT			0x00000003
+diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
+index 8ebdc74cc0ad..feaac908efed 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c
++++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
+@@ -1,4 +1,4 @@
+-// SPDX-License-Identifier: GPL-2.0
++// SPDX-License-Identifier: MIT
+ #include 
+ #include 
+ 
+diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.h b/drivers/gpu/drm/nouveau/nouveau_ttm.h
+index 89929ad8c7cd..085280754b3e 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_ttm.h
++++ b/drivers/gpu/drm/nouveau/nouveau_ttm.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NOUVEAU_TTM_H__
+ #define __NOUVEAU_TTM_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/nouveau_usif.h b/drivers/gpu/drm/nouveau/nouveau_usif.h
+index c68f1c65af3b..dc90d4a9d0d9 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_usif.h
++++ b/drivers/gpu/drm/nouveau/nouveau_usif.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NOUVEAU_USIF_H__
+ #define __NOUVEAU_USIF_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c
+index 8f1ce4833230..8f4b12a8092c 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_vga.c
++++ b/drivers/gpu/drm/nouveau/nouveau_vga.c
+@@ -1,4 +1,4 @@
+-// SPDX-License-Identifier: GPL-2.0
++// SPDX-License-Identifier: MIT
+ #include 
+ #include 
+ 
+diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.h b/drivers/gpu/drm/nouveau/nouveau_vga.h
+index 6a3000c88142..951a83f984dd 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_vga.h
++++ b/drivers/gpu/drm/nouveau/nouveau_vga.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NOUVEAU_VGA_H__
+ #define __NOUVEAU_VGA_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/nv10_fence.h b/drivers/gpu/drm/nouveau/nv10_fence.h
+index 7616c66803f8..300cf3fdbb46 100644
+--- a/drivers/gpu/drm/nouveau/nv10_fence.h
++++ b/drivers/gpu/drm/nouveau/nv10_fence.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NV10_FENCE_H_
+ #define __NV10_FENCE_H_
+ 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gf100.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gf100.fuc3.h
+index da130f5058e5..96d934f81600 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gf100.fuc3.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gf100.fuc3.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ static uint32_t gf100_ce_data[] = {
+ /* 0x0000: ctx_object */
+ 	0x00000000,
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gt215.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gt215.fuc3.h
+index 0b92eb32598d..d3fbd4ab5e31 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gt215.fuc3.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gt215.fuc3.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ static uint32_t gt215_ce_data[] = {
+ /* 0x0000: ctx_object */
+ 	0x00000000,
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h
+index 0e3d08f11b0b..b0c8342db15f 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_CE_PRIV_H__
+ #define __NVKM_CE_PRIV_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/acpi.h b/drivers/gpu/drm/nouveau/nvkm/engine/device/acpi.h
+index 6a62021e9861..1d3c5cf7c3b4 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/acpi.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/acpi.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_DEVICE_ACPI_H__
+ #define __NVKM_DEVICE_ACPI_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.h b/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.h
+index ebcc5c52fbd1..9f6d7f23af8d 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_DEVICE_CTRL_H__
+ #define __NVKM_DEVICE_CTRL_H__
+ #define nvkm_control(p) container_of((p), struct nvkm_control, object)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h
+index 2a53e37dfa7a..d8be2f77ac66 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_DEVICE_PRIV_H__
+ #define __NVKM_DEVICE_PRIV_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h
+index adc9d76d09cc..e55054b7329f 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NV50_DISP_CHAN_H__
+ #define __NV50_DISP_CHAN_H__
+ #define nv50_disp_chan(p) container_of((p), struct nv50_disp_chan, object)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h
+index 090e869ae612..dcbe60a4b911 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_DISP_CONN_H__
+ #define __NVKM_DISP_CONN_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h
+index 495f665a0ee6..428b3f488f03 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_DISP_DP_H__
+ #define __NVKM_DISP_DP_H__
+ #define nvkm_dp(p) container_of((p), struct nvkm_dp, outp)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmi.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmi.c
+index 10f2aa9f29a4..7147dc6d9018 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmi.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmi.c
+@@ -1,4 +1,4 @@
+-// SPDX-License-Identifier: GPL-2.0
++// SPDX-License-Identifier: MIT
+ #include "hdmi.h"
+ 
+ void pack_hdmi_infoframe(struct packed_hdmi_infoframe *packed_frame,
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmi.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmi.h
+index 45094c6e1425..fb1c3e3c5d4c 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmi.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmi.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_DISP_HDMI_H__
+ #define __NVKM_DISP_HDMI_H__
+ #include "ior.h"
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h
+index 7d55faf52fcb..7dde6237441d 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_DISP_HEAD_H__
+ #define __NVKM_DISP_HEAD_H__
+ #include "priv.h"
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
+index 1681ddccd298..009d3a8b7a50 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_DISP_IOR_H__
+ #define __NVKM_DISP_IOR_H__
+ #include "priv.h"
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h
+index e5d00f478bb1..a677161c7f3a 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NV50_DISP_H__
+ #define __NV50_DISP_H__
+ #define nv50_disp(p) container_of((p), struct nv50_disp, base)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
+index 6c8aa5cfed9d..721b068b87ef 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_DISP_OUTP_H__
+ #define __NVKM_DISP_OUTP_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h
+index ef66c5f38ad5..f815a5342880 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_DISP_PRIV_H__
+ #define __NVKM_DISP_PRIV_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h
+index aee9822a7a87..a1f942793f98 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NV50_DISP_ROOT_H__
+ #define __NV50_DISP_ROOT_H__
+ #define nv50_disp_root(p) container_of((p), struct nv50_disp_root, object)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/dma/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/dma/priv.h
+index 4307cbecd5c5..0c9d9640a59d 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/dma/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/dma/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_DMA_PRIV_H__
+ #define __NVKM_DMA_PRIV_H__
+ #define nvkm_dma(p) container_of((p), struct nvkm_dma, engine)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/dma/user.h b/drivers/gpu/drm/nouveau/nvkm/engine/dma/user.h
+index 9fe01fd75474..9c72ee214be7 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/dma/user.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/dma/user.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_DMA_USER_H__
+ #define __NVKM_DMA_USER_H__
+ #define nvkm_dmaobj(p) container_of((p), struct nvkm_dmaobj, object)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h
+index 2c7c5afc1ea5..177e10562600 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_FIFO_CHAN_H__
+ #define __NVKM_FIFO_CHAN_H__
+ #define nvkm_fifo_chan(p) container_of((p), struct nvkm_fifo_chan, object)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h
+index b653664e081b..7c125a15f963 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __GF100_FIFO_CHAN_H__
+ #define __GF100_FIFO_CHAN_H__
+ #define gf100_fifo_chan(p) container_of((p), struct gf100_fifo_chan, base)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h
+index f8557cdfbd81..22698661aa85 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __GK104_FIFO_CHAN_H__
+ #define __GK104_FIFO_CHAN_H__
+ #define gk104_fifo_chan(p) container_of((p), struct gk104_fifo_chan, base)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h
+index 15b06bdf5067..60ca79465aff 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NV04_FIFO_CHAN_H__
+ #define __NV04_FIFO_CHAN_H__
+ #define nv04_fifo_chan(p) container_of((p), struct nv04_fifo_chan, base)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h
+index 2e3c4005b874..5735ff72a9d1 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NV50_FIFO_CHAN_H__
+ #define __NV50_FIFO_CHAN_H__
+ #define nv50_fifo_chan(p) container_of((p), struct nv50_fifo_chan, base)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h
+index 68f97ba03df6..b8642490eb2f 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __GF100_FIFO_H__
+ #define __GF100_FIFO_H__
+ #define gf100_fifo(p) container_of((p), struct gf100_fifo, base)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h
+index d4e565658f46..c33f4593cbc6 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __GK104_FIFO_H__
+ #define __GK104_FIFO_H__
+ #define gk104_fifo(p) container_of((p), struct gk104_fifo, base)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h
+index 1d70542553cc..e5ecceee77ae 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NV04_FIFO_H__
+ #define __NV04_FIFO_H__
+ #define nv04_fifo(p) container_of((p), struct nv04_fifo, base)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h
+index a3994e8db462..87d30b6bd2ea 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NV50_FIFO_H__
+ #define __NV50_FIFO_H__
+ #define nv50_fifo(p) container_of((p), struct nv50_fifo, base)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h
+index d5acbba293f4..c66f5370b21f 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_FIFO_PRIV_H__
+ #define __NVKM_FIFO_PRIV_H__
+ #define nvkm_fifo(p) container_of((p), struct nvkm_fifo, engine)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/regsnv04.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/regsnv04.h
+index 49892a5e7201..4445a12b9a26 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/regsnv04.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/regsnv04.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NV04_FIFO_REGS_H__
+ #define __NV04_FIFO_REGS_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h
+index 33e932bd73b1..478b4723d0f9 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_GRCTX_NVC0_H__
+ #define __NVKM_GRCTX_NVC0_H__
+ #include "gf100.h"
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxnv40.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxnv40.h
+index 4d67d90261b8..7917567ade3a 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxnv40.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxnv40.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_GRCTX_H__
+ #define __NVKM_GRCTX_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf100.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf100.fuc3.h
+index 0323acb739c8..54e14b4d31b3 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf100.fuc3.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf100.fuc3.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ static uint32_t gf100_grgpc_data[] = {
+ /* 0x0000: gpc_mmio_list_head */
+ 	0x00000064,
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h
+index 1bb265917915..67524e615d81 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ static uint32_t gf117_grgpc_data[] = {
+ /* 0x0000: gpc_mmio_list_head */
+ 	0x0000006c,
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h
+index cf8343a693ba..60c8b7e89913 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ static uint32_t gk104_grgpc_data[] = {
+ /* 0x0000: gpc_mmio_list_head */
+ 	0x0000006c,
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h
+index f4bfa109ed27..c99d1566554c 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ static uint32_t gk110_grgpc_data[] = {
+ /* 0x0000: gpc_mmio_list_head */
+ 	0x0000006c,
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h
+index 59a3e1b2927f..753aa66729bf 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ static uint32_t gk208_grgpc_data[] = {
+ /* 0x0000: gpc_mmio_list_head */
+ 	0x0000006c,
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h
+index 8daa0516704a..db8b294cee39 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ static uint32_t gm107_grgpc_data[] = {
+ /* 0x0000: gpc_mmio_list_head */
+ 	0x0000006c,
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf100.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf100.fuc3.h
+index cbf2351f8da8..56162f6a6a94 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf100.fuc3.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf100.fuc3.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ static uint32_t gf100_grhub_data[] = {
+ /* 0x0000: hub_mmio_list_head */
+ 	0x00000300,
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf117.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf117.fuc3.h
+index 70830036ffee..9b9f0d93f915 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf117.fuc3.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf117.fuc3.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ static uint32_t gf117_grhub_data[] = {
+ /* 0x0000: hub_mmio_list_head */
+ 	0x00000300,
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk104.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk104.fuc3.h
+index 7f2fd84d0c3a..fa11857b9d31 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk104.fuc3.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk104.fuc3.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ static uint32_t gk104_grhub_data[] = {
+ /* 0x0000: hub_mmio_list_head */
+ 	0x00000300,
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk110.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk110.fuc3.h
+index 560063789de8..1d741b30a04a 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk110.fuc3.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk110.fuc3.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ static uint32_t gk110_grhub_data[] = {
+ /* 0x0000: hub_mmio_list_head */
+ 	0x00000300,
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk208.fuc5.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk208.fuc5.h
+index 71e85784b615..c24f35ad56a6 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk208.fuc5.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk208.fuc5.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ static uint32_t gk208_grhub_data[] = {
+ /* 0x0000: hub_mmio_list_head */
+ 	0x00000300,
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgm107.fuc5.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgm107.fuc5.h
+index d85eac6d1c61..649a442b4390 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgm107.fuc5.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgm107.fuc5.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ static uint32_t gm107_grhub_data[] = {
+ /* 0x0000: hub_mmio_list_head */
+ 	0x00000300,
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/os.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/os.h
+index f87693809c9f..6ac155b9663b 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/os.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/os.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_GRAPH_OS_H__
+ #define __NVKM_GRAPH_OS_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.h
+index d5a376c4dd0b..4327baea02af 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NV10_GR_H__
+ #define __NV10_GR_H__
+ #include "priv.h"
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c
+index 111c8bb4497b..d837630a3625 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c
+@@ -1,4 +1,4 @@
+-// SPDX-License-Identifier: GPL-2.0
++// SPDX-License-Identifier: MIT
+ #include "nv20.h"
+ #include "regs.h"
+ 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.h
+index 979dc5f7b32e..e57407a8a7c3 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NV20_GR_H__
+ #define __NV20_GR_H__
+ #define nv20_gr(p) container_of((p), struct nv20_gr, base)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv25.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv25.c
+index e59a28a26d65..32d29d3faee0 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv25.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv25.c
+@@ -1,4 +1,4 @@
+-// SPDX-License-Identifier: GPL-2.0
++// SPDX-License-Identifier: MIT
+ #include "nv20.h"
+ #include "regs.h"
+ 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv2a.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv2a.c
+index e113b2d4c811..f941062c66f0 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv2a.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv2a.c
+@@ -1,4 +1,4 @@
+-// SPDX-License-Identifier: GPL-2.0
++// SPDX-License-Identifier: MIT
+ #include "nv20.h"
+ #include "regs.h"
+ 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c
+index 4aac2c224874..785ec956df0f 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c
+@@ -1,4 +1,4 @@
+-// SPDX-License-Identifier: GPL-2.0
++// SPDX-License-Identifier: MIT
+ #include "nv20.h"
+ #include "regs.h"
+ 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c
+index 301556503e93..bd610d75c677 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c
+@@ -1,4 +1,4 @@
+-// SPDX-License-Identifier: GPL-2.0
++// SPDX-License-Identifier: MIT
+ #include "nv20.h"
+ #include "regs.h"
+ 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c
+index 5d6926611a5b..89db7f523037 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c
+@@ -1,4 +1,4 @@
+-// SPDX-License-Identifier: GPL-2.0
++// SPDX-License-Identifier: MIT
+ #include "nv20.h"
+ #include "regs.h"
+ 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.h
+index 731400937edd..e6128791b2d2 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NV40_GR_H__
+ #define __NV40_GR_H__
+ #define nv40_gr(p) container_of((p), struct nv40_gr, base)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.h
+index 5b9d99bee207..465f4da0ddfc 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NV50_GR_H__
+ #define __NV50_GR_H__
+ #define nv50_gr(p) container_of((p), struct nv50_gr, base)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h
+index d4d5601c51e7..3b30f24032cc 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_GR_PRIV_H__
+ #define __NVKM_GR_PRIV_H__
+ #define nvkm_gr(p) container_of((p), struct nvkm_gr, engine)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/regs.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/regs.h
+index dc4f936675ac..fd1b7d35c62b 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/regs.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/regs.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_GR_REGS_H__
+ #define __NVKM_GR_REGS_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h
+index b31fad8bdaad..b3e131538858 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NV31_MPEG_H__
+ #define __NV31_MPEG_H__
+ #define nv31_mpeg(p) container_of((p), struct nv31_mpeg, engine)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/priv.h
+index 26f9d14151e2..667a2d05dd89 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_MPEG_PRIV_H__
+ #define __NVKM_MPEG_PRIV_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/priv.h
+index db305072a82f..86445a2600d0 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_MSPDEC_PRIV_H__
+ #define __NVKM_MSPDEC_PRIV_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/msppp/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/msppp/priv.h
+index 7708e52c9043..f20b10915db2 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/msppp/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/msppp/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_MSPPP_PRIV_H__
+ #define __NVKM_MSPPP_PRIV_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/msvld/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/msvld/priv.h
+index 66c36049abca..5cd1e83badbb 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/msvld/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/msvld/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_MSVLD_PRIV_H__
+ #define __NVKM_MSVLD_PRIV_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/priv.h
+index 6c300739f621..57bfa3aa1835 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_NVDEC_PRIV_H__
+ #define __NVKM_NVDEC_PRIV_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.h
+index c74fd4557d41..461bb219b1c0 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_PM_NVC0_H__
+ #define __NVKM_PM_NVC0_H__
+ #include "priv.h"
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.h b/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.h
+index 3f37b713936c..8ed19320fda1 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_PM_NV40_H__
+ #define __NVKM_PM_NV40_H__
+ #define nv40_pm(p) container_of((p), struct nv40_pm, base)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h
+index 9fad3611a843..cd6f8f79b235 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_PM_PRIV_H__
+ #define __NVKM_PM_PRIV_H__
+ #define nvkm_pm(p) container_of((p), struct nvkm_pm, engine)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec/fuc/g98.fuc0s.h b/drivers/gpu/drm/nouveau/nvkm/engine/sec/fuc/g98.fuc0s.h
+index 6278a0c5fe83..fe90f2e05853 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/sec/fuc/g98.fuc0s.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec/fuc/g98.fuc0s.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ static uint32_t g98_sec_data[] = {
+ /* 0x0000: ctx_dma */
+ /* 0x0000: ctx_dma_query */
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h
+index ab0165e2d1a3..b331b00517e6 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_SEC2_PRIV_H__
+ #define __NVKM_SEC2_PRIV_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h
+index d42862fc43fd..32de53427aa4 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_SW_CHAN_H__
+ #define __NVKM_SW_CHAN_H__
+ #define nvkm_sw_chan(p) container_of((p), struct nvkm_sw_chan, object)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h
+index 459afd30a484..6d364d7b406a 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_SW_NV50_H__
+ #define __NVKM_SW_NV50_H__
+ #define nv50_sw_chan(p) container_of((p), struct nv50_sw_chan, base)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.h b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.h
+index d7034950ba87..d2f846499b92 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_NVSW_H__
+ #define __NVKM_NVSW_H__
+ #define nvkm_nvsw(p) container_of((p), struct nvkm_nvsw, object)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/sw/priv.h
+index 4aca1791abc3..6d18fc6180f2 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_SW_PRIV_H__
+ #define __NVKM_SW_PRIV_H__
+ #define nvkm_sw(p) container_of((p), struct nvkm_sw, engine)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/priv.h b/drivers/gpu/drm/nouveau/nvkm/falcon/priv.h
+index d515ad994199..900fe1d37b4d 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/falcon/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/falcon/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_FALCON_PRIV_H__
+ #define __NVKM_FALCON_PRIV_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.h b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.h
+index 4f2b66e8d795..4ae4c7145712 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __GF100_BAR_H__
+ #define __GF100_BAR_H__
+ #define gf100_bar(p) container_of((p), struct gf100_bar, base)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.h b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.h
+index 2fe833f6d9f7..e4193deb2e51 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NV50_BAR_H__
+ #define __NV50_BAR_H__
+ #define nv50_bar(p) container_of((p), struct nv50_bar, base)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/priv.h
+index 01ba5b26666e..869ad184f923 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_BAR_PRIV_H__
+ #define __NVKM_BAR_PRIV_H__
+ #define nvkm_bar(p) container_of((p), struct nvkm_bar, subdev)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h
+index 33435ca16311..fac1bff1311b 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_BIOS_PRIV_H__
+ #define __NVKM_BIOS_PRIV_H__
+ #define nvkm_bios(p) container_of((p), struct nvkm_bios, subdev)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h b/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h
+index 17ac1812a928..217a0a4a3bc5 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_BUS_HWSQ_H__
+ #define __NVKM_BUS_HWSQ_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bus/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/bus/priv.h
+index ef01e569352d..76f7ba1c6494 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bus/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bus/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_BUS_PRIV_H__
+ #define __NVKM_BUS_PRIV_H__
+ #define nvkm_bus(p) container_of((p), struct nvkm_bus, subdev)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.h b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.h
+index 1ea886a4301f..34754efbfb1e 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_CLK_NVA3_H__
+ #define __NVKM_CLK_NVA3_H__
+ #include "priv.h"
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.h b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.h
+index f134d979d884..7c7713238ec4 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NV50_CLK_H__
+ #define __NV50_CLK_H__
+ #define nv50_clk(p) container_of((p), struct nv50_clk, base)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/pll.h b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/pll.h
+index 9a39f1fd2976..631907564e71 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/pll.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/pll.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_PLL_H__
+ #define __NVKM_PLL_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/priv.h
+index b656177923fb..81dfb37480ae 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_CLK_PRIV_H__
+ #define __NVKM_CLK_PRIV_H__
+ #define nvkm_clk(p) container_of((p), struct nvkm_clk, subdev)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/seq.h b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/seq.h
+index d0715fe84328..e4b362d3449b 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/seq.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/seq.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_CLK_SEQ_H__
+ #define __NVKM_CLK_SEQ_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv04.h b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv04.h
+index b18e49847eee..15b029ddf6df 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv04.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv04.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NV04_DEVINIT_H__
+ #define __NV04_DEVINIT_H__
+ #define nv04_devinit(p) container_of((p), struct nv04_devinit, base)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.h b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.h
+index 72d130bb7f7c..e8d37a6145a2 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NV50_DEVINIT_H__
+ #define __NV50_DEVINIT_H__
+ #define nv50_devinit(p) container_of((p), struct nv50_devinit, base)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/priv.h
+index 5b3097a586dd..94723352137a 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_DEVINIT_PRIV_H__
+ #define __NVKM_DEVINIT_PRIV_H__
+ #define nvkm_devinit(p) container_of((p), struct nvkm_devinit, subdev)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h
+index ab261310753a..2ed7cdaab37c 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_RAM_NVC0_H__
+ #define __NVKM_RAM_NVC0_H__
+ #define gf100_fb(p) container_of((p), struct gf100_fb, base)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h
+index dacc696387b6..5e2b0c9539ed 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_FB_NV50_H__
+ #define __NVKM_FB_NV50_H__
+ #define nv50_fb(p) container_of((p), struct nv50_fb, base)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h
+index 1e4ad61c19e1..c4e9f55af283 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_FB_PRIV_H__
+ #define __NVKM_FB_PRIV_H__
+ #define nvkm_fb(p) container_of((p), struct nvkm_fb, subdev)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h
+index 330132e95b6f..d723a9b4e3c4 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_FB_RAM_PRIV_H__
+ #define __NVKM_FB_RAM_PRIV_H__
+ #include "priv.h"
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramfuc.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramfuc.h
+index a65fa5586af8..247c0f8a723b 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramfuc.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramfuc.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_FBRAM_FUC_H__
+ #define __NVKM_FBRAM_FUC_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.h
+index 11f6bb2936b9..a87de0871dfc 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NV40_FB_RAM_H__
+ #define __NV40_FB_RAM_H__
+ #define nv40_ram(p) container_of((p), struct nv40_ram, base)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramseq.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramseq.h
+index d8f5053e8e2a..aba5b73781d3 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramseq.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramseq.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_FBRAM_SEQ_H__
+ #define __NVKM_FBRAM_SEQ_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/regsnv04.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/regsnv04.h
+index ad26fcbe9e06..8098cd77dfdd 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/regsnv04.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/regsnv04.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_FB_REGS_04_H__
+ #define __NVKM_FB_REGS_04_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/priv.h
+index 3a5595a9e457..2edc612408dd 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_FUSE_PRIV_H__
+ #define __NVKM_FUSE_PRIV_H__
+ #define nvkm_fuse(p) container_of((p), struct nvkm_fuse, subdev)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/priv.h
+index 9759f13447bf..59e39affe2a0 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_GPIO_PRIV_H__
+ #define __NVKM_GPIO_PRIV_H__
+ #define nvkm_gpio(p) container_of((p), struct nvkm_gpio, subdev)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h
+index 08f6b2ee64ab..30b48896965e 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_I2C_AUX_H__
+ #define __NVKM_I2C_AUX_H__
+ #include "pad.h"
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.h b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.h
+index 465464bba58b..4c236ab34929 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_I2C_BUS_H__
+ #define __NVKM_I2C_BUS_H__
+ #include "pad.h"
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/pad.h b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/pad.h
+index 33f0c809e583..461016814f4f 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/pad.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/pad.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_I2C_PAD_H__
+ #define __NVKM_I2C_PAD_H__
+ #include 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/priv.h
+index f476a69b6cb7..bd86bc298ebe 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_I2C_PRIV_H__
+ #define __NVKM_I2C_PRIV_H__
+ #define nvkm_i2c(p) container_of((p), struct nvkm_i2c, subdev)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/priv.h
+index 504a6d37ec50..302d69e384d8 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_IBUS_PRIV_H__
+ #define __NVKM_IBUS_PRIV_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/priv.h
+index bd599b8252ca..cc09c6c504af 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_ICCSENSE_PRIV_H__
+ #define __NVKM_ICCSENSE_PRIV_H__
+ #define nvkm_iccsense(p) container_of((p), struct nvkm_iccsense, subdev)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h
+index b9e4751b9921..f5da8fcbdde3 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_INSTMEM_PRIV_H__
+ #define __NVKM_INSTMEM_PRIV_H__
+ #define nvkm_instmem(p) container_of((p), struct nvkm_instmem, subdev)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h
+index 9dcde43c0f3c..2fcf18e46ce3 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_LTC_PRIV_H__
+ #define __NVKM_LTC_PRIV_H__
+ #define nvkm_ltc(p) container_of((p), struct nvkm_ltc, subdev)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h
+index eb91a4cf452b..4aab753a6040 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_MC_PRIV_H__
+ #define __NVKM_MC_PRIV_H__
+ #define nvkm_mc(p) container_of((p), struct nvkm_mc, subdev)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h
+index 2ad1102a4e31..07f2fcd18f3d 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_MMU_PRIV_H__
+ #define __NVKM_MMU_PRIV_H__
+ #define nvkm_mmu(p) container_of((p), struct nvkm_mmu, subdev)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.h
+index 011a67fe4a8b..d9676b282ac0 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVMXM_MXMS_H__
+ #define __NVMXM_MXMS_H__
+ #include "priv.h"
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/priv.h
+index 6767c2279e7c..fc8f69e6fc64 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_MXM_PRIV_H__
+ #define __NVKM_MXM_PRIV_H__
+ #define nvkm_mxm(p) container_of((p), struct nvkm_mxm, subdev)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.h
+index edb7f00f0de5..ad4d3621d02b 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #include "priv.h"
+ #if defined(CONFIG_AGP) || (defined(CONFIG_AGP_MODULE) && defined(MODULE))
+ #ifndef __NVKM_PCI_AGP_H__
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/priv.h
+index c17f6063c9ea..7009aad86b6e 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_PCI_PRIV_H__
+ #define __NVKM_PCI_PRIV_H__
+ #define nvkm_pci(p) container_of((p), struct nvkm_pci, subdev)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf100.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf100.fuc3.h
+index 1dbe593e5960..4cf888f2bd03 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf100.fuc3.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf100.fuc3.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ static uint32_t gf100_pmu_data[] = {
+ /* 0x0000: proc_kern */
+ 	0x52544e49,
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4.h
+index e1e981966c2d..e80eff18e5d4 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ static uint32_t gf119_pmu_data[] = {
+ /* 0x0000: proc_kern */
+ 	0x52544e49,
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gk208.fuc5.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gk208.fuc5.h
+index e0222cb832fb..275ec71bc0c0 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gk208.fuc5.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gk208.fuc5.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ static uint32_t gk208_pmu_data[] = {
+ /* 0x0000: proc_kern */
+ 	0x52544e49,
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gt215.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gt215.fuc3.h
+index defddf5957ee..4b071e9bec7d 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gt215.fuc3.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gt215.fuc3.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ static uint32_t gt215_pmu_data[] = {
+ /* 0x0000: proc_kern */
+ 	0x52544e49,
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/os.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/os.h
+index 30d9480b9be5..0d5abf27ee52 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/os.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/os.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_PWR_OS_H__
+ #define __NVKM_PWR_OS_H__
+ 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/memx.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/memx.c
+index 7b052879af72..22eaebefced3 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/memx.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/memx.c
+@@ -1,4 +1,4 @@
+-// SPDX-License-Identifier: GPL-2.0
++// SPDX-License-Identifier: MIT
+ #ifndef __NVKM_PMU_MEMX_H__
+ #define __NVKM_PMU_MEMX_H__
+ #include "priv.h"
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h
+index e9c6f9725afe..26d73f9cd6d3 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_PMU_PRIV_H__
+ #define __NVKM_PMU_PRIV_H__
+ #define nvkm_pmu(p) container_of((p), struct nvkm_pmu, subdev)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/priv.h
+index 3b8878486faa..89e97294b182 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_TIMER_PRIV_H__
+ #define __NVKM_TIMER_PRIV_H__
+ #define nvkm_timer(p) container_of((p), struct nvkm_timer, subdev)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/regsnv04.h b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/regsnv04.h
+index 23d07f5f44d9..34a740bc6e4a 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/regsnv04.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/regsnv04.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #define NV04_PTIMER_INTR_0      0x009100
+ #define NV04_PTIMER_INTR_EN_0   0x009140
+ #define NV04_PTIMER_NUMERATOR   0x009200
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/top/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/top/priv.h
+index 4f49b0acaa0e..a16baa2941cf 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/top/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/top/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_TOP_PRIV_H__
+ #define __NVKM_TOP_PRIV_H__
+ #define nvkm_top(p) container_of((p), struct nvkm_top, subdev)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h
+index 1a8ad560321b..75f13a34671f 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: MIT */
+ #ifndef __NVKM_VOLT_PRIV_H__
+ #define __NVKM_VOLT_PRIV_H__
+ #define nvkm_volt(p) container_of((p), struct nvkm_volt, subdev)

commit 533f4752407543f488a9118d817b8c504352b6fb
+Author: Ilia Mirkin 
+Date:   Sat May 25 18:41:49 2019 -0400
+
+    drm/nouveau/disp/nv50-: fix center/aspect-corrected scaling
+    
+    Previously center scaling would get scaling applied to it (when it was
+    only supposed to center the image), and aspect-corrected scaling did not
+    always correctly pick whether to reduce width or height for a particular
+    combination of inputs/outputs.
+    
+    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=110660
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c
+index 48a6485ec4e0..929d93b1677e 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/head.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/head.c
+@@ -169,14 +169,34 @@ nv50_head_atomic_check_view(struct nv50_head_atom *armh,
+ 	 */
+ 	switch (mode) {
+ 	case DRM_MODE_SCALE_CENTER:
+-		asyh->view.oW = min((u16)umode->hdisplay, asyh->view.oW);
+-		asyh->view.oH = min((u16)umode_vdisplay, asyh->view.oH);
+-		/* fall-through */
++		/* NOTE: This will cause scaling when the input is
++		 * larger than the output.
++		 */
++		asyh->view.oW = min(asyh->view.iW, asyh->view.oW);
++		asyh->view.oH = min(asyh->view.iH, asyh->view.oH);
++		break;
+ 	case DRM_MODE_SCALE_ASPECT:
+-		if (asyh->view.oH < asyh->view.oW) {
++		/* Determine whether the scaling should be on width or on
++		 * height. This is done by comparing the aspect ratios of the
++		 * sizes. If the output AR is larger than input AR, that means
++		 * we want to change the width (letterboxed on the
++		 * left/right), otherwise on the height (letterboxed on the
++		 * top/bottom).
++		 *
++		 * E.g. 4:3 (1.333) AR image displayed on a 16:10 (1.6) AR
++		 * screen will have letterboxes on the left/right. However a
++		 * 16:9 (1.777) AR image on that same screen will have
++		 * letterboxes on the top/bottom.
++		 *
++		 * inputAR = iW / iH; outputAR = oW / oH
++		 * outputAR > inputAR is equivalent to oW * iH > iW * oH
++		 */
++		if (asyh->view.oW * asyh->view.iH > asyh->view.iW * asyh->view.oH) {
++			/* Recompute output width, i.e. left/right letterbox */
+ 			u32 r = (asyh->view.iW << 19) / asyh->view.iH;
+ 			asyh->view.oW = ((asyh->view.oH * r) + (r / 2)) >> 19;
+ 		} else {
++			/* Recompute output height, i.e. top/bottom letterbox */
+ 			u32 r = (asyh->view.iH << 19) / asyh->view.iW;
+ 			asyh->view.oH = ((asyh->view.oW * r) + (r / 2)) >> 19;
+ 		}

commit f8d6211ac77f0d1f7aebc64e961dc28771ba0052
+Author: Ilia Mirkin 
+Date:   Sat May 25 18:41:48 2019 -0400
+
+    drm/nouveau/disp/nv50-: force scaler for any non-default LVDS/eDP modes
+    
+    Higher layers tend to add a lot of modes not actually in the EDID, such
+    as the standard DMT modes. Changing this would be extremely intrusive to
+    everyone, so just force the scaler more often. There are no practical
+    cases we're aware of where a LVDS/eDP panel has multiple resolutions
+    exposed, and i915 already does it this way.
+    
+    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=110660
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
+index 7ba373f493b2..8497768f1b41 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
+@@ -322,8 +322,13 @@ nv50_outp_atomic_check_view(struct drm_encoder *encoder,
+ 		switch (connector->connector_type) {
+ 		case DRM_MODE_CONNECTOR_LVDS:
+ 		case DRM_MODE_CONNECTOR_eDP:
+-			/* Force use of scaler for non-EDID modes. */
+-			if (adjusted_mode->type & DRM_MODE_TYPE_DRIVER)
++			/* Don't force scaler for EDID modes with
++			 * same size as the native one (e.g. different
++			 * refresh rate)
++			 */
++			if (adjusted_mode->hdisplay == native_mode->hdisplay &&
++			    adjusted_mode->vdisplay == native_mode->vdisplay &&
++			    adjusted_mode->type & DRM_MODE_TYPE_DRIVER)
+ 				break;
+ 			mode = native_mode;
+ 			asyc->scaler.full = true;

commit fc782242749fa4235592854fafe1a1297583c1fb
+Author: Ilia Mirkin 
+Date:   Sun Jan 13 17:50:10 2019 -0500
+
+    drm/nouveau/volt/gf117: fix speedo readout register
+    
+    GF117 appears to use the same register as GK104 (but still with the
+    general Fermi readout mechanism).
+    
+    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=108980
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h
+index 8a0f85f5fc1a..6a765682fbfa 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h
+@@ -38,6 +38,7 @@ int nvkm_volt_set_id(struct nvkm_volt *, u8 id, u8 min_id, u8 temp,
+ 
+ int nv40_volt_new(struct nvkm_device *, int, struct nvkm_volt **);
+ int gf100_volt_new(struct nvkm_device *, int, struct nvkm_volt **);
++int gf117_volt_new(struct nvkm_device *, int, struct nvkm_volt **);
+ int gk104_volt_new(struct nvkm_device *, int, struct nvkm_volt **);
+ int gk20a_volt_new(struct nvkm_device *, int, struct nvkm_volt **);
+ int gm20b_volt_new(struct nvkm_device *, int, struct nvkm_volt **);
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
+index d9edb5785813..d75fa7678483 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
+@@ -1613,7 +1613,7 @@ nvd7_chipset = {
+ 	.pci = gf106_pci_new,
+ 	.therm = gf119_therm_new,
+ 	.timer = nv41_timer_new,
+-	.volt = gf100_volt_new,
++	.volt = gf117_volt_new,
+ 	.ce[0] = gf100_ce_new,
+ 	.disp = gf119_disp_new,
+ 	.dma = gf119_dma_new,
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild
+index bcd179ba11d0..146adcdd316a 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild
+@@ -2,6 +2,7 @@ nvkm-y += nvkm/subdev/volt/base.o
+ nvkm-y += nvkm/subdev/volt/gpio.o
+ nvkm-y += nvkm/subdev/volt/nv40.o
+ nvkm-y += nvkm/subdev/volt/gf100.o
++nvkm-y += nvkm/subdev/volt/gf117.o
+ nvkm-y += nvkm/subdev/volt/gk104.o
+ nvkm-y += nvkm/subdev/volt/gk20a.o
+ nvkm-y += nvkm/subdev/volt/gm20b.o
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gf117.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gf117.c
+new file mode 100644
+index 000000000000..547a58f0aeac
+--- /dev/null
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gf117.c
+@@ -0,0 +1,60 @@
++/*
++ * Copyright 2019 Ilia Mirkin
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * Authors: Ilia Mirkin
++ */
++#include "priv.h"
++
++#include 
++
++static int
++gf117_volt_speedo_read(struct nvkm_volt *volt)
++{
++	struct nvkm_device *device = volt->subdev.device;
++	struct nvkm_fuse *fuse = device->fuse;
++
++	if (!fuse)
++		return -EINVAL;
++
++	return nvkm_fuse_read(fuse, 0x3a8);
++}
++
++static const struct nvkm_volt_func
++gf117_volt = {
++	.oneinit = gf100_volt_oneinit,
++	.vid_get = nvkm_voltgpio_get,
++	.vid_set = nvkm_voltgpio_set,
++	.speedo_read = gf117_volt_speedo_read,
++};
++
++int
++gf117_volt_new(struct nvkm_device *device, int index, struct nvkm_volt **pvolt)
++{
++	struct nvkm_volt *volt;
++	int ret;
++
++	ret = nvkm_volt_new_(&gf117_volt, device, index, &volt);
++	*pvolt = volt;
++	if (ret)
++		return ret;
++
++	return nvkm_voltgpio_init(volt);
++}

commit a5176a4cb85bb6213daadf691097cf411da35df2
+Author: Ilia Mirkin 
+Date:   Thu Dec 13 22:44:08 2018 -0500
+
+    drm/nouveau/falcon: avoid touching registers if engine is off
+    
+    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=108980
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c b/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c
+index 816ccaedfc73..8675613e142b 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c
+@@ -22,6 +22,7 @@
+ #include 
+ 
+ #include 
++#include 
+ #include 
+ #include 
+ 
+@@ -107,8 +108,10 @@ nvkm_falcon_fini(struct nvkm_engine *engine, bool suspend)
+ 		}
+ 	}
+ 
+-	nvkm_mask(device, base + 0x048, 0x00000003, 0x00000000);
+-	nvkm_wr32(device, base + 0x014, 0xffffffff);
++	if (nvkm_mc_enabled(device, engine->subdev.index)) {
++		nvkm_mask(device, base + 0x048, 0x00000003, 0x00000000);
++		nvkm_wr32(device, base + 0x014, 0xffffffff);
++	}
+ 	return 0;
+ }
+ 

commit 9340d77f5327ea673a7f95f58139123d7a278243
+Author: Ilia Mirkin 
+Date:   Mon Sep 3 20:57:37 2018 -0400
+
+    drm/nouveau/disp: take sink support into account for exposing 594mhz
+    
+    Scrambling is required for supporting any mode over 340MHz. If it's not
+    supported, reject any modes that would require it.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
+index a22f4fd03a06..fd80661dff92 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
++++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
+@@ -969,18 +969,33 @@ nouveau_connector_get_modes(struct drm_connector *connector)
+ }
+ 
+ static unsigned
+-get_tmds_link_bandwidth(struct drm_connector *connector, bool hdmi)
++get_tmds_link_bandwidth(struct drm_connector *connector)
+ {
+ 	struct nouveau_connector *nv_connector = nouveau_connector(connector);
++	struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
+ 	struct nouveau_drm *drm = nouveau_drm(connector->dev);
+ 	struct dcb_output *dcb = nv_connector->detected_encoder->dcb;
++	struct drm_display_info *info = NULL;
++	const unsigned duallink_scale =
++		nouveau_duallink && nv_encoder->dcb->duallink_possible ? 2 : 1;
++
++	if (drm_detect_hdmi_monitor(nv_connector->edid))
++		info = &nv_connector->base.display_info;
+ 
+-	if (hdmi) {
++	if (info) {
+ 		if (nouveau_hdmimhz > 0)
+ 			return nouveau_hdmimhz * 1000;
+ 		/* Note: these limits are conservative, some Fermi's
+ 		 * can do 297 MHz. Unclear how this can be determined.
+ 		 */
++		if (drm->client.device.info.chipset >= 0x120) {
++			const int max_tmds_clock =
++				info->hdmi.scdc.scrambling.supported ?
++				594000 : 340000;
++			return info->max_tmds_clock ?
++				min(info->max_tmds_clock, max_tmds_clock) :
++				max_tmds_clock;
++		}
+ 		if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_KEPLER)
+ 			return 297000;
+ 		if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_FERMI)
+@@ -988,13 +1003,13 @@ get_tmds_link_bandwidth(struct drm_connector *connector, bool hdmi)
+ 	}
+ 	if (dcb->location != DCB_LOC_ON_CHIP ||
+ 	    drm->client.device.info.chipset >= 0x46)
+-		return 165000;
++		return 165000 * duallink_scale;
+ 	else if (drm->client.device.info.chipset >= 0x40)
+-		return 155000;
++		return 155000 * duallink_scale;
+ 	else if (drm->client.device.info.chipset >= 0x18)
+-		return 135000;
++		return 135000 * duallink_scale;
+ 	else
+-		return 112000;
++		return 112000 * duallink_scale;
+ }
+ 
+ static enum drm_mode_status
+@@ -1006,7 +1021,6 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
+ 	struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
+ 	unsigned min_clock = 25000, max_clock = min_clock;
+ 	unsigned clock = mode->clock;
+-	bool hdmi;
+ 
+ 	switch (nv_encoder->dcb->type) {
+ 	case DCB_OUTPUT_LVDS:
+@@ -1019,11 +1033,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
+ 		max_clock = 400000;
+ 		break;
+ 	case DCB_OUTPUT_TMDS:
+-		hdmi = drm_detect_hdmi_monitor(nv_connector->edid);
+-		max_clock = get_tmds_link_bandwidth(connector, hdmi);
+-		if (!hdmi && nouveau_duallink &&
+-		    nv_encoder->dcb->duallink_possible)
+-			max_clock *= 2;
++		max_clock = get_tmds_link_bandwidth(connector);
+ 		break;
+ 	case DCB_OUTPUT_ANALOG:
+ 		max_clock = nv_encoder->dcb->crtconf.maxfreq;

commit 7a406f8a62ff0a3647f96f0cfdb518a99a01bf3f
+Author: Ilia Mirkin 
+Date:   Mon Sep 3 20:57:36 2018 -0400
+
+    drm/nouveau/disp: add support for setting scdc parameters for high modes
+    
+    When SCDC is supported, make sure that we configure the GPU and monitor
+    to the same parameters.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
+index 1dbd1dcdcf15..5f163a025e89 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
+@@ -36,6 +36,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ 
+ #include 
+@@ -531,6 +532,7 @@ nv50_hdmi_disable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc)
+ static void
+ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
+ {
++	struct nouveau_drm *drm = nouveau_drm(encoder->dev);
+ 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+ 	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
+ 	struct nv50_disp *disp = nv50_disp(encoder->dev);
+@@ -548,9 +550,12 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
+ 		.pwr.rekey = 56, /* binary driver, and tegra, constant */
+ 	};
+ 	struct nouveau_connector *nv_connector;
++	struct drm_hdmi_info *hdmi;
+ 	u32 max_ac_packet;
+ 	union hdmi_infoframe avi_frame;
+ 	union hdmi_infoframe vendor_frame;
++	bool scdc_supported, high_tmds_clock_ratio = false, scrambling = false;
++	u8 config;
+ 	int ret;
+ 	int size;
+ 
+@@ -558,8 +563,11 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
+ 	if (!drm_detect_hdmi_monitor(nv_connector->edid))
+ 		return;
+ 
++	hdmi = &nv_connector->base.display_info.hdmi;
++	scdc_supported = hdmi->scdc.supported;
++
+ 	ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame.avi, mode,
+-						       false);
++						       scdc_supported);
+ 	if (!ret) {
+ 		/* We have an AVI InfoFrame, populate it to the display */
+ 		args.pwr.avi_infoframe_length
+@@ -582,12 +590,42 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
+ 	max_ac_packet -= 18; /* constant from tegra */
+ 	args.pwr.max_ac_packet = max_ac_packet / 32;
+ 
++	if (hdmi->scdc.scrambling.supported) {
++		high_tmds_clock_ratio = mode->clock > 340000;
++		scrambling = high_tmds_clock_ratio ||
++			hdmi->scdc.scrambling.low_rates;
++	}
++
++	args.pwr.scdc =
++		NV50_DISP_SOR_HDMI_PWR_V0_SCDC_SCRAMBLE * scrambling |
++		NV50_DISP_SOR_HDMI_PWR_V0_SCDC_DIV_BY_4 * high_tmds_clock_ratio;
++
+ 	size = sizeof(args.base)
+ 		+ sizeof(args.pwr)
+ 		+ args.pwr.avi_infoframe_length
+ 		+ args.pwr.vendor_infoframe_length;
+ 	nvif_mthd(&disp->disp->object, 0, &args, size);
++
+ 	nv50_audio_enable(encoder, mode);
++
++	/* If SCDC is supported by the downstream monitor, update
++	 * divider / scrambling settings to what we programmed above.
++	 */
++	if (!hdmi->scdc.scrambling.supported)
++		return;
++
++	ret = drm_scdc_readb(nv_encoder->i2c, SCDC_TMDS_CONFIG, &config);
++	if (ret < 0) {
++		NV_ERROR(drm, "Failure to read SCDC_TMDS_CONFIG: %d\n", ret);
++		return;
++	}
++	config &= ~(SCDC_TMDS_BIT_CLOCK_RATIO_BY_40 | SCDC_SCRAMBLING_ENABLE);
++	config |= SCDC_TMDS_BIT_CLOCK_RATIO_BY_40 * high_tmds_clock_ratio;
++	config |= SCDC_SCRAMBLING_ENABLE * scrambling;
++	ret = drm_scdc_writeb(nv_encoder->i2c, SCDC_TMDS_CONFIG, config);
++	if (ret < 0)
++		NV_ERROR(drm, "Failure to write SCDC_TMDS_CONFIG = 0x%02x: %d\n",
++			 config, ret);
+ }
+ 
+ /******************************************************************************

commit a971558c298755d2c07bc5508c65d689471763c8
+Author: Ilia Mirkin 
+Date:   Mon Sep 3 20:57:35 2018 -0400
+
+    drm/nouveau/disp: keep track of high-speed state, program into clock
+    
+    The register programmed by the clock method needs to contain a different
+    setting for the link speed as well as special divider settings.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c
+index ad5f658c3f6d..9b16a08eb4d9 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c
+@@ -31,4 +31,6 @@ gm200_hdmi_scdc(struct nvkm_ior *ior, int head, u8 scdc)
+ 	const u32 ctrl = scdc & 0x3;
+ 
+ 	nvkm_mask(device, 0x61c5bc + hoff, 0x00000003, ctrl);
++
++	ior->tmds.high_speed = !!(scdc & 0x2);
+ }
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
+index c5d34424f45f..0f0c86c32ec3 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
+@@ -41,6 +41,11 @@ struct nvkm_ior {
+ 		u8 nr;
+ 		u8 bw;
+ 	} dp;
++
++	/* Armed TMDS state. */
++	struct {
++		bool high_speed;
++	} tmds;
+ };
+ 
+ struct nvkm_ior_func {
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
+index e6e6dfbb1283..456a5a143522 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
+@@ -120,13 +120,16 @@ void
+ gf119_sor_clock(struct nvkm_ior *sor)
+ {
+ 	struct nvkm_device *device = sor->disp->engine.subdev.device;
+-	const int  div = sor->asy.link == 3;
+ 	const u32 soff = nv50_ior_base(sor);
++	u32 div1 = sor->asy.link == 3;
++	u32 div2 = sor->asy.link == 3;
+ 	if (sor->asy.proto == TMDS) {
+-		/* NFI why, but this sets DP_LINK_BW_2_7 when using TMDS. */
+-		nvkm_mask(device, 0x612300 + soff, 0x007c0000, 0x0a << 18);
++		const u32 speed = sor->tmds.high_speed ? 0x14 : 0x0a;
++		nvkm_mask(device, 0x612300 + soff, 0x007c0000, speed << 18);
++		if (sor->tmds.high_speed)
++			div2 = 1;
+ 	}
+-	nvkm_mask(device, 0x612300 + soff, 0x00000707, (div << 8) | div);
++	nvkm_mask(device, 0x612300 + soff, 0x00000707, (div2 << 8) | div1);
+ }
+ 
+ void

commit 4834e05049c9c807c38d0727ab422898fdfe2996
+Author: Ilia Mirkin 
+Date:   Mon Sep 3 20:57:34 2018 -0400
+
+    drm/nouveau/disp/gm200-: add scdc parameter setter
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
+index 3d485dbf310a..8089ac9a12e2 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
+@@ -50,6 +50,7 @@ nvkm-y += nvkm/engine/disp/hdmig84.o
+ nvkm-y += nvkm/engine/disp/hdmigt215.o
+ nvkm-y += nvkm/engine/disp/hdmigf119.o
+ nvkm-y += nvkm/engine/disp/hdmigk104.o
++nvkm-y += nvkm/engine/disp/hdmigm200.o
+ nvkm-y += nvkm/engine/disp/hdmigv100.o
+ 
+ nvkm-y += nvkm/engine/disp/conn.o
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c
+new file mode 100644
+index 000000000000..ad5f658c3f6d
+--- /dev/null
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c
+@@ -0,0 +1,34 @@
++/*
++ * Copyright 2018 Ilia Mirkin
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * Authors: Ilia Mirkin
++ */
++#include "hdmi.h"
++
++void
++gm200_hdmi_scdc(struct nvkm_ior *ior, int head, u8 scdc)
++{
++	struct nvkm_device *device = ior->disp->engine.subdev.device;
++	const u32 hoff = head * 0x800;
++	const u32 ctrl = scdc & 0x3;
++
++	nvkm_mask(device, 0x61c5bc + hoff, 0x00000003, ctrl);
++}
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
+index aa7aa2f21cf6..c5d34424f45f 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
+@@ -145,6 +145,8 @@ void gf119_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8);
+ void gk104_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8);
+ void gv100_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8);
+ 
++void gm200_hdmi_scdc(struct nvkm_ior *, int, u8);
++
+ void gt215_hda_hpd(struct nvkm_ior *, int, bool);
+ void gt215_hda_eld(struct nvkm_ior *, u8 *, u8);
+ 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c
+index d892bdf04034..384f82652bec 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c
+@@ -99,6 +99,7 @@ gm200_sor = {
+ 	.clock = gf119_sor_clock,
+ 	.hdmi = {
+ 		.ctrl = gk104_hdmi_ctrl,
++		.scdc = gm200_hdmi_scdc,
+ 	},
+ 	.dp = {
+ 		.lanes = { 0, 1, 2, 3 },
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c
+index 040db8a338de..8ba881a729ee 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c
+@@ -88,6 +88,7 @@ gv100_sor = {
+ 	.clock = gf119_sor_clock,
+ 	.hdmi = {
+ 		.ctrl = gv100_hdmi_ctrl,
++		.scdc = gm200_hdmi_scdc,
+ 	},
+ 	.dp = {
+ 		.lanes = { 0, 1, 2, 3 },

commit 4126b99e744b7a29746e201e2be6644d2edf3c56
+Author: Ilia Mirkin 
+Date:   Mon Sep 3 20:57:33 2018 -0400
+
+    drm/nouveau/disp: add a way to configure scrambling/tmds for hdmi 2.0
+    
+    High pixel clocks are required to use a 40 TMDS divider instead of 10,
+    and even low ones may optionally use scrambling depending on device
+    support.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
+index 7cdf53615d7b..bced81987269 100644
+--- a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
++++ b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
+@@ -69,7 +69,10 @@ struct nv50_disp_sor_hdmi_pwr_v0 {
+ 	__u8  rekey;
+ 	__u8  avi_infoframe_length;
+ 	__u8  vendor_infoframe_length;
+-	__u8  pad06[2];
++#define NV50_DISP_SOR_HDMI_PWR_V0_SCDC_SCRAMBLE (1 << 0)
++#define NV50_DISP_SOR_HDMI_PWR_V0_SCDC_DIV_BY_4 (1 << 1)
++	__u8  scdc;
++	__u8  pad07[1];
+ };
+ 
+ struct nv50_disp_sor_lvds_script_v0 {
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
+index 19911211a12a..aa7aa2f21cf6 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
+@@ -61,6 +61,7 @@ struct nvkm_ior_func {
+ 		void (*ctrl)(struct nvkm_ior *, int head, bool enable,
+ 			     u8 max_ac_packet, u8 rekey, u8 *avi, u8 avi_size,
+ 			     u8 *vendor, u8 vendor_size);
++		void (*scdc)(struct nvkm_ior *, int head, u8 scdc);
+ 	} hdmi;
+ 
+ 	struct {
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
+index 3aa5a2879239..5f758948d6e1 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
+@@ -176,9 +176,10 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
+ 		nvif_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
+ 		if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
+ 			nvif_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
+-					   "max_ac_packet %d rekey %d\n",
++					   "max_ac_packet %d rekey %d scdc %d\n",
+ 				   args->v0.version, args->v0.state,
+-				   args->v0.max_ac_packet, args->v0.rekey);
++				   args->v0.max_ac_packet, args->v0.rekey,
++				   args->v0.scdc);
+ 			if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f)
+ 				return -EINVAL;
+ 			if ((args->v0.avi_infoframe_length
+@@ -202,6 +203,11 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
+ 					   args->v0.max_ac_packet,
+ 					   args->v0.rekey, avi, avi_size,
+ 					   vendor, vendor_size);
++
++		if (outp->ior->func->hdmi.scdc)
++			outp->ior->func->hdmi.scdc(
++					outp->ior, hidx, args->v0.scdc);
++
+ 		return 0;
+ 	}
+ 		break;

commit dc76803e57cc86589c4efcb5362918f9b0c0436f
+Author: Rian Hunter 
+Date:   Sun Aug 19 16:08:53 2018 -0700
+
+    x86/process: Re-export start_thread()
+    
+    The consolidation of the start_thread() functions removed the export
+    unintentionally. This breaks binfmt handlers built as a module.
+    
+    Add it back.
+    
+    Fixes: e634d8fc792c ("x86-64: merge the standard and compat start_thread() functions")
+    Signed-off-by: Rian Hunter 
+    Signed-off-by: Thomas Gleixner 
+    Cc: "H. Peter Anvin" 
+    Cc: Andy Lutomirski 
+    Cc: Borislav Petkov 
+    Cc: Vitaly Kuznetsov 
+    Cc: Joerg Roedel 
+    Cc: Dmitry Safonov 
+    Cc: Josh Poimboeuf 
+    Cc: stable@vger.kernel.org
+    Link: https://lkml.kernel.org/r/20180819230854.7275-1-rian@alum.mit.edu
+
+diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
+index 476e3ddf8890..a451bc374b9b 100644
+--- a/arch/x86/kernel/process_64.c
++++ b/arch/x86/kernel/process_64.c
+@@ -384,6 +384,7 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
+ 	start_thread_common(regs, new_ip, new_sp,
+ 			    __USER_CS, __USER_DS, 0);
+ }
++EXPORT_SYMBOL_GPL(start_thread);
+ 
+ #ifdef CONFIG_COMPAT
+ void compat_start_thread(struct pt_regs *regs, u32 new_ip, u32 new_sp)

commit 7a22c737faef99d6f75d7049c1a2f6f0fdefb1ec
+Author: Ilia Mirkin 
+Date:   Sun Apr 22 17:47:12 2018 -0400
+
+    drm/nouveau: fix temp/pwm visibility, skip hwmon when no sensors exist
+    
+    A NV34 GPU was seeing temp and pwm entries in hwmon, which would error
+    out when read. These should not have been visible, but also the whole
+    hwmon object should just not have been registered in the first place.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_hwmon.c b/drivers/gpu/drm/nouveau/nouveau_hwmon.c
+index 7c965648df80..44178b4c3599 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_hwmon.c
++++ b/drivers/gpu/drm/nouveau/nouveau_hwmon.c
+@@ -327,7 +327,7 @@ nouveau_temp_is_visible(const void *data, u32 attr, int channel)
+ 	struct nouveau_drm *drm = nouveau_drm((struct drm_device *)data);
+ 	struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
+ 
+-	if (therm && therm->attr_get && nvkm_therm_temp_get(therm) < 0)
++	if (!therm || !therm->attr_get || nvkm_therm_temp_get(therm) < 0)
+ 		return 0;
+ 
+ 	switch (attr) {
+@@ -351,8 +351,8 @@ nouveau_pwm_is_visible(const void *data, u32 attr, int channel)
+ 	struct nouveau_drm *drm = nouveau_drm((struct drm_device *)data);
+ 	struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
+ 
+-	if (therm && therm->attr_get && therm->fan_get &&
+-				therm->fan_get(therm) < 0)
++	if (!therm || !therm->attr_get || !therm->fan_get ||
++	    therm->fan_get(therm) < 0)
+ 		return 0;
+ 
+ 	switch (attr) {
+@@ -707,13 +707,20 @@ nouveau_hwmon_init(struct drm_device *dev)
+ {
+ #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
+ 	struct nouveau_drm *drm = nouveau_drm(dev);
++	struct nvkm_iccsense *iccsense = nvxx_iccsense(&drm->client.device);
+ 	struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
++	struct nvkm_volt *volt = nvxx_volt(&drm->client.device);
+ 	const struct attribute_group *special_groups[N_ATTR_GROUPS];
+ 	struct nouveau_hwmon *hwmon;
+ 	struct device *hwmon_dev;
+ 	int ret = 0;
+ 	int i = 0;
+ 
++	if (!iccsense && !therm && !volt) {
++		NV_DEBUG(drm, "Skipping hwmon registration\n");
++		return 0;
++	}
++
+ 	hwmon = drm->hwmon = kzalloc(sizeof(*hwmon), GFP_KERNEL);
+ 	if (!hwmon)
+ 		return -ENOMEM;
+@@ -749,6 +756,9 @@ nouveau_hwmon_fini(struct drm_device *dev)
+ #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
+ 	struct nouveau_hwmon *hwmon = nouveau_hwmon(dev);
+ 
++	if (!hwmon)
++		return;
++
+ 	if (hwmon->hwmon)
+ 		hwmon_device_unregister(hwmon->hwmon);
+ 

commit c20bb155c2c5acb775f68be5d84fe679687c3c1e
+Author: Ilia Mirkin 
+Date:   Sat Feb 3 14:11:23 2018 -0500
+
+    drm/nouveau: prefer XBGR2101010 for addfb ioctl
+    
+    Nouveau only exposes support for XBGR2101010. Prior to the atomic
+    conversion, drm would pass in the wrong format in the framebuffer, but
+    it was always ignored -- both userspace (xf86-video-nouveau) and the
+    kernel driver agreed on the layout, so the fact that the format was
+    wrong didn't matter.
+    
+    With the atomic conversion, nouveau all of a sudden started caring about
+    the exact format, and so the previously-working code in
+    xf86-video-nouveau no longer functioned since the (internally-assigned)
+    format from the addfb ioctl was wrong.
+    
+    This change adds infrastructure to allow a drm driver to specify that it
+    prefers the XBGR format variant for the addfb ioctl, and makes nouveau's
+    nv50 display driver set it. (Prior gens had no support for 30bpp at all.)
+    
+    Signed-off-by: Ilia Mirkin 
+    Cc: stable@vger.kernel.org # v4.10+
+    Acked-by: Ben Skeggs 
+    Signed-off-by: Daniel Vetter 
+    Link: https://patchwork.freedesktop.org/patch/msgid/20180203191123.31507-1-imirkin@alum.mit.edu
+
+diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c
+index 5a13ff29f4f0..c0530a1af5e3 100644
+--- a/drivers/gpu/drm/drm_framebuffer.c
++++ b/drivers/gpu/drm/drm_framebuffer.c
+@@ -121,6 +121,10 @@ int drm_mode_addfb(struct drm_device *dev,
+ 	r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
+ 	r.handles[0] = or->handle;
+ 
++	if (r.pixel_format == DRM_FORMAT_XRGB2101010 &&
++	    dev->driver->driver_features & DRIVER_PREFER_XBGR_30BPP)
++		r.pixel_format = DRM_FORMAT_XBGR2101010;
++
+ 	ret = drm_mode_addfb2(dev, &r, file_priv);
+ 	if (ret)
+ 		return ret;
+diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
+index dd8d4352ed99..caddce88d2d8 100644
+--- a/drivers/gpu/drm/nouveau/nv50_display.c
++++ b/drivers/gpu/drm/nouveau/nv50_display.c
+@@ -4477,6 +4477,7 @@ nv50_display_create(struct drm_device *dev)
+ 	nouveau_display(dev)->fini = nv50_display_fini;
+ 	disp->disp = &nouveau_display(dev)->disp;
+ 	dev->mode_config.funcs = &nv50_disp_func;
++	dev->driver->driver_features |= DRIVER_PREFER_XBGR_30BPP;
+ 	if (nouveau_atomic)
+ 		dev->driver->driver_features |= DRIVER_ATOMIC;
+ 
+diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h
+index d32b688eb346..d23dcdd1bd95 100644
+--- a/include/drm/drm_drv.h
++++ b/include/drm/drm_drv.h
+@@ -56,6 +56,7 @@ struct drm_printer;
+ #define DRIVER_ATOMIC			0x10000
+ #define DRIVER_KMS_LEGACY_CONTEXT	0x20000
+ #define DRIVER_SYNCOBJ                  0x40000
++#define DRIVER_PREFER_XBGR_30BPP        0x80000
+ 
+ /**
+  * struct drm_driver - DRM driver structure

commit e75182f68b7b3a073e33b89ee4c1688160755930
+Author: Ilia Mirkin 
+Date:   Sat Dec 30 23:35:28 2017 -0500
+
+    drm/nouveau/kms/nv50: use "low res" lut for indexed mode
+    
+    This is what was done prior to the big refactor in kernel 3.8, and what
+    was done by xf86-video-nv. Experimentally, it seems like there's some
+    sort of issue with the high-res lut to be used there. Tested on G92.
+    
+    This ends up mattering because fbcon/fbdev chooses the C8 fb format for
+    low-vram systems, which can occur with some IGP-based configurations
+    with little "stolen" vram.
+    
+    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=80675
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
+index 2293b8ff56c6..f4daf8c55de1 100644
+--- a/drivers/gpu/drm/nouveau/nv50_display.c
++++ b/drivers/gpu/drm/nouveau/nv50_display.c
+@@ -1805,12 +1805,14 @@ nv50_head_lut_set(struct nv50_head *head, struct nv50_head_atom *asyh)
+ 	if ((push = evo_wait(core, 7))) {
+ 		if (core->base.user.oclass < G82_DISP_CORE_CHANNEL_DMA) {
+ 			evo_mthd(push, 0x0840 + (head->base.index * 0x400), 2);
+-			evo_data(push, 0xc0000000);
++			evo_data(push, asyh->base.depth == 8 ?
++				 0x80000000 : 0xc0000000);
+ 			evo_data(push, asyh->lut.offset >> 8);
+ 		} else
+ 		if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
+ 			evo_mthd(push, 0x0840 + (head->base.index * 0x400), 2);
+-			evo_data(push, 0xc0000000);
++			evo_data(push, asyh->base.depth == 8 ?
++				 0x80000000 : 0xc0000000);
+ 			evo_data(push, asyh->lut.offset >> 8);
+ 			evo_mthd(push, 0x085c + (head->base.index * 0x400), 1);
+ 			evo_data(push, asyh->lut.handle);

commit 3a0bc8cb9b102229ad26ae3788cef8c6c5273be1
+Author: Ilia Mirkin 
+Date:   Wed Nov 1 03:56:19 2017 +1000
+
+    drm/nouveau/kms: add 8.1Gbps DP link rate
+    
+    This was already done in dcb.c inside nvkm, but the other parser did not
+    get the update.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
+index dd6fba55ad5d..c4ef3a0a737e 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
++++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
+@@ -1478,9 +1478,13 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
+ 		case 1:
+ 			entry->dpconf.link_bw = 270000;
+ 			break;
+-		default:
++		case 2:
+ 			entry->dpconf.link_bw = 540000;
+ 			break;
++		case 3:
++		default:
++			entry->dpconf.link_bw = 810000;
++			break;
+ 		}
+ 		switch ((conf & 0x0f000000) >> 24) {
+ 		case 0xf:

commit 194d68dd051c2dd5ac2b522ae16100e774e8d869
+Author: Ilia Mirkin 
+Date:   Sun Oct 1 13:52:43 2017 -0400
+
+    drm/nouveau/bsp/g92: disable by default
+    
+    G92's seem to require some additional bit of initialization before the
+    BSP engine can work. It feels like clocks are not set up for the
+    underlying VLD engine, which means that all commands submitted to the
+    xtensa chip end up hanging. VP seems to work fine though.
+    
+    This still allows people to force-enable the bsp engine if they want to
+    play around with it, but makes it harder for the card to hang by
+    default.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+    Cc: stable@vger.kernel.org
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/bsp/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/bsp/g84.c
+index 8e2e24a74774..44e116f7880d 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/bsp/g84.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/bsp/g84.c
+@@ -39,5 +39,5 @@ int
+ g84_bsp_new(struct nvkm_device *device, int index, struct nvkm_engine **pengine)
+ {
+ 	return nvkm_xtensa_new_(&g84_bsp, device, index,
+-				true, 0x103000, pengine);
++				device->chipset != 0x92, 0x103000, pengine);
+ }

commit bc60c90f472b6e762ea96ef384072145adc8d4af
+Author: Ilia Mirkin 
+Date:   Thu Aug 10 12:13:40 2017 -0400
+
+    drm/nouveau/pci/msi: disable MSI on big-endian platforms by default
+    
+    It appears that MSI does not work on either G5 PPC nor on a E5500-based
+    platform, where other hardware is reported to work fine with MSI.
+    
+    Both tests were conducted with NV4x hardware, so perhaps other (or even
+    this) hardware can be made to work. It's still possible to force-enable
+    with config=NvMSI=1 on load.
+    
+    Signed-off-by: Ilia Mirkin 
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c
+index eb9b278198b2..a4cb82495cee 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c
+@@ -192,6 +192,10 @@ nvkm_pci_new_(const struct nvkm_pci_func *func, struct nvkm_device *device,
+ 		}
+ 	}
+ 
++#ifdef __BIG_ENDIAN
++	pci->msi = false;
++#endif
++
+ 	pci->msi = nvkm_boolopt(device->cfgopt, "NvMSI", pci->msi);
+ 	if (pci->msi && func->msi_rearm) {
+ 		pci->msi = pci_enable_msi(pci->pdev) == 0;

commit 856718054a1b6f38e085021bbd5b0e74817a8fa6
+Author: Ilia Mirkin 
+Date:   Sat Aug 5 22:25:05 2017 -0400
+
+    drm/nouveau/kms/nv04-nv4x: fix exposed format list
+    
+    drm_crtc_init exposes the XRGB8888 and ARGB8888 formats. In actuality,
+    ARGB8888's 32-bit depth messes up some formulas that weren't meant for
+    it, and the alpha is fairly meaningless for the primary plane.
+    
+    The modesetting logic appears to be fully prepared for RGB565 as well as
+    XRGB1555 however, as tested with modetest.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
+index 8f689f1f6122..6aa6ee16dcbd 100644
+--- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c
++++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
+@@ -1096,6 +1096,38 @@ static const struct drm_crtc_helper_funcs nv04_crtc_helper_funcs = {
+ 	.disable = nv_crtc_disable,
+ };
+ 
++static const uint32_t modeset_formats[] = {
++        DRM_FORMAT_XRGB8888,
++        DRM_FORMAT_RGB565,
++        DRM_FORMAT_XRGB1555,
++};
++
++static struct drm_plane *
++create_primary_plane(struct drm_device *dev)
++{
++        struct drm_plane *primary;
++        int ret;
++
++        primary = kzalloc(sizeof(*primary), GFP_KERNEL);
++        if (primary == NULL) {
++                DRM_DEBUG_KMS("Failed to allocate primary plane\n");
++                return NULL;
++        }
++
++        /* possible_crtc's will be filled in later by crtc_init */
++        ret = drm_universal_plane_init(dev, primary, 0,
++                                       &drm_primary_helper_funcs,
++                                       modeset_formats,
++                                       ARRAY_SIZE(modeset_formats), NULL,
++                                       DRM_PLANE_TYPE_PRIMARY, NULL);
++        if (ret) {
++                kfree(primary);
++                primary = NULL;
++        }
++
++        return primary;
++}
++
+ int
+ nv04_crtc_create(struct drm_device *dev, int crtc_num)
+ {
+@@ -1114,7 +1146,9 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num)
+ 	nv_crtc->save = nv_crtc_save;
+ 	nv_crtc->restore = nv_crtc_restore;
+ 
+-	drm_crtc_init(dev, &nv_crtc->base, &nv04_crtc_funcs);
++	drm_crtc_init_with_planes(dev, &nv_crtc->base,
++                                  create_primary_plane(dev), NULL,
++                                  &nv04_crtc_funcs, NULL);
+ 	drm_crtc_helper_add(&nv_crtc->base, &nv04_crtc_helper_funcs);
+ 	drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256);
+ 

commit 7fa620d577502670741925198b1ee5c55d3a65cf
+Author: Ilia Mirkin 
+Date:   Sat Aug 5 22:25:04 2017 -0400
+
+    drm/nouveau/kms/nv10-nv40: add NV21 support to overlay
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+index 5bd63c2f14a6..c8c2333f24ee 100644
+--- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c
++++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+@@ -63,6 +63,7 @@ static uint32_t formats[] = {
+ 	DRM_FORMAT_YUYV,
+ 	DRM_FORMAT_UYVY,
+ 	DRM_FORMAT_NV12,
++	DRM_FORMAT_NV21,
+ };
+ 
+ /* Sine can be approximated with
+@@ -159,16 +160,18 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+ 	nvif_wr32(dev, NV_PVIDEO_POINT_OUT(flip), crtc_y << 16 | crtc_x);
+ 	nvif_wr32(dev, NV_PVIDEO_SIZE_OUT(flip), crtc_h << 16 | crtc_w);
+ 
+-	if (fb->format->format != DRM_FORMAT_UYVY)
++	if (fb->format->format == DRM_FORMAT_YUYV ||
++	    fb->format->format == DRM_FORMAT_NV12)
+ 		format |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8;
+-	if (fb->format->format == DRM_FORMAT_NV12)
++	if (fb->format->format == DRM_FORMAT_NV12 ||
++	    fb->format->format == DRM_FORMAT_NV21)
+ 		format |= NV_PVIDEO_FORMAT_PLANAR;
+ 	if (nv_plane->iturbt_709)
+ 		format |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
+ 	if (nv_plane->colorkey & (1 << 24))
+ 		format |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY;
+ 
+-	if (fb->format->format == DRM_FORMAT_NV12) {
++	if (format & NV_PVIDEO_FORMAT_PLANAR) {
+ 		nvif_wr32(dev, NV_PVIDEO_UVPLANE_BASE(flip), 0);
+ 		nvif_wr32(dev, NV_PVIDEO_UVPLANE_OFFSET_BUFF(flip),
+ 			nv_fb->nvbo->bo.offset + fb->offsets[1]);

commit 9a6edc3ac968aca9ce51d16917705a857285286b
+Author: Ilia Mirkin 
+Date:   Sat Aug 5 22:25:03 2017 -0400
+
+    drm/nouveau/kms/nv04-nv40: improve overlay error detection, fix pitch setting
+    
+    We were previously setting the pitch based on a perfectly packed buffer.
+    This does not necessarily happen. Either modetest started generating
+    such buffers recently, or earlier testing only happened with well-picked
+    overlay sizes.
+    
+    While we're at it, beef up and refactor the error state detection.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+index e54944d23268..5bd63c2f14a6 100644
+--- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c
++++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+@@ -89,6 +89,26 @@ cos_mul(int degrees, int factor)
+ 	return sin_mul((degrees + 90) % 360, factor);
+ }
+ 
++static int
++verify_scaling(const struct drm_framebuffer *fb, uint8_t shift,
++               uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h,
++               uint32_t crtc_w, uint32_t crtc_h)
++{
++	if (crtc_w < (src_w >> shift) || crtc_h < (src_h >> shift)) {
++		DRM_DEBUG_KMS("Unsuitable framebuffer scaling: %dx%d -> %dx%d\n",
++			      src_w, src_h, crtc_w, crtc_h);
++		return -ERANGE;
++	}
++
++	if (src_x != 0 || src_y != 0) {
++		DRM_DEBUG_KMS("Unsuitable framebuffer offset: %d,%d\n",
++                              src_x, src_y);
++		return -ERANGE;
++	}
++
++	return 0;
++}
++
+ static int
+ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+ 		  struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+@@ -107,7 +127,9 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+ 	bool flip = nv_plane->flip;
+ 	int soff = NV_PCRTC0_SIZE * nv_crtc->index;
+ 	int soff2 = NV_PCRTC0_SIZE * !nv_crtc->index;
+-	int format, ret;
++	unsigned shift = drm->client.device.info.chipset >= 0x30 ? 1 : 3;
++	unsigned format = 0;
++	int ret;
+ 
+ 	/* Source parameters given in 16.16 fixed point, ignore fractional. */
+ 	src_x >>= 16;
+@@ -115,18 +137,9 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+ 	src_w >>= 16;
+ 	src_h >>= 16;
+ 
+-	format = ALIGN(src_w * 4, 0x100);
+-
+-	if (format > 0xffff)
+-		return -ERANGE;
+-
+-	if (drm->client.device.info.chipset >= 0x30) {
+-		if (crtc_w < (src_w >> 1) || crtc_h < (src_h >> 1))
+-			return -ERANGE;
+-	} else {
+-		if (crtc_w < (src_w >> 3) || crtc_h < (src_h >> 3))
+-			return -ERANGE;
+-	}
++	ret = verify_scaling(fb, shift, 0, 0, src_w, src_h, crtc_w, crtc_h);
++	if (ret)
++		return ret;
+ 
+ 	ret = nouveau_bo_pin(nv_fb->nvbo, TTM_PL_FLAG_VRAM, false);
+ 	if (ret)
+@@ -160,7 +173,7 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+ 		nvif_wr32(dev, NV_PVIDEO_UVPLANE_OFFSET_BUFF(flip),
+ 			nv_fb->nvbo->bo.offset + fb->offsets[1]);
+ 	}
+-	nvif_wr32(dev, NV_PVIDEO_FORMAT(flip), format);
++	nvif_wr32(dev, NV_PVIDEO_FORMAT(flip), format | fb->pitches[0]);
+ 	nvif_wr32(dev, NV_PVIDEO_STOP, 0);
+ 	/* TODO: wait for vblank? */
+ 	nvif_wr32(dev, NV_PVIDEO_BUFFER, flip ? 0x10 : 0x1);
+@@ -357,7 +370,7 @@ nv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+ 	struct nouveau_bo *cur = nv_plane->cur;
+ 	uint32_t overlay = 1;
+ 	int brightness = (nv_plane->brightness - 512) * 62 / 512;
+-	int pitch, ret, i;
++	int ret, i;
+ 
+ 	/* Source parameters given in 16.16 fixed point, ignore fractional. */
+ 	src_x >>= 16;
+@@ -365,17 +378,9 @@ nv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+ 	src_w >>= 16;
+ 	src_h >>= 16;
+ 
+-	pitch = ALIGN(src_w * 4, 0x100);
+-
+-	if (pitch > 0xffff)
+-		return -ERANGE;
+-
+-	/* TODO: Compute an offset? Not sure how to do this for YUYV. */
+-	if (src_x != 0 || src_y != 0)
+-		return -ERANGE;
+-
+-	if (crtc_w < src_w || crtc_h < src_h)
+-		return -ERANGE;
++	ret = verify_scaling(fb, 0, src_x, src_y, src_w, src_h, crtc_w, crtc_h);
++	if (ret)
++		return ret;
+ 
+ 	ret = nouveau_bo_pin(nv_fb->nvbo, TTM_PL_FLAG_VRAM, false);
+ 	if (ret)
+@@ -389,8 +394,9 @@ nv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+ 
+ 	for (i = 0; i < 2; i++) {
+ 		nvif_wr32(dev, NV_PVIDEO_BUFF0_START_ADDRESS + 4 * i,
+-			nv_fb->nvbo->bo.offset);
+-		nvif_wr32(dev, NV_PVIDEO_BUFF0_PITCH_LENGTH + 4 * i, pitch);
++			  nv_fb->nvbo->bo.offset);
++		nvif_wr32(dev, NV_PVIDEO_BUFF0_PITCH_LENGTH + 4 * i,
++			  fb->pitches[0]);
+ 		nvif_wr32(dev, NV_PVIDEO_BUFF0_OFFSET + 4 * i, 0);
+ 	}
+ 	nvif_wr32(dev, NV_PVIDEO_WINDOW_START, crtc_y << 16 | crtc_x);

commit 3ce72bcf33c200e78b87699d20f8e5a564e29a98
+Author: Ilia Mirkin 
+Date:   Sat Aug 5 22:25:02 2017 -0400
+
+    drm/nouveau/kms/nv04-nv40: prevent undisplayable framebuffers from creation
+    
+    Pre-nv50 YUV overlays have stringent requirements for working with the
+    internal machinery. Instead of rejecting these at update_plane time, we
+    should instead prevent the framebuffers from being created in the first
+    place.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
+index d66640047913..2e7785f49e6d 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_display.c
++++ b/drivers/gpu/drm/nouveau/nouveau_display.c
+@@ -231,9 +231,30 @@ nouveau_framebuffer_new(struct drm_device *dev,
+ 			struct nouveau_bo *nvbo,
+ 			struct nouveau_framebuffer **pfb)
+ {
++	struct nouveau_drm *drm = nouveau_drm(dev);
+ 	struct nouveau_framebuffer *fb;
+ 	int ret;
+ 
++        /* YUV overlays have special requirements pre-NV50 */
++	if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA &&
++
++	    (mode_cmd->pixel_format == DRM_FORMAT_YUYV ||
++	     mode_cmd->pixel_format == DRM_FORMAT_UYVY ||
++	     mode_cmd->pixel_format == DRM_FORMAT_NV12 ||
++	     mode_cmd->pixel_format == DRM_FORMAT_NV21) &&
++	    (mode_cmd->pitches[0] & 0x3f || /* align 64 */
++	     mode_cmd->pitches[0] >= 0x10000 || /* at most 64k pitch */
++	     (mode_cmd->pitches[1] && /* pitches for planes must match */
++	      mode_cmd->pitches[0] != mode_cmd->pitches[1]))) {
++		struct drm_format_name_buf format_name;
++		DRM_DEBUG_KMS("Unsuitable framebuffer: format: %s; pitches: 0x%x\n 0x%x\n",
++			      drm_get_format_name(mode_cmd->pixel_format,
++						  &format_name),
++			      mode_cmd->pitches[0],
++			      mode_cmd->pitches[1]);
++		return -EINVAL;
++	}
++
+ 	if (!(fb = *pfb = kzalloc(sizeof(*fb), GFP_KERNEL)))
+ 		return -ENOMEM;
+ 

commit d257f9bf06129613de539ea71ecea60848b662cd
+Author: Ilia Mirkin 
+Date:   Sat Aug 5 22:19:53 2017 -0400
+
+    drm/nouveau/mpeg: print more debug info when rejecting dma objects
+    
+    Signed-off-by: Ilia Mirkin 
+    Reviewed-by: Tobias Klausmann 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c
+index 8a8895246d26..7fea7d45202f 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c
+@@ -124,6 +124,8 @@ nv31_mpeg_tile(struct nvkm_engine *engine, int i, struct nvkm_fb_tile *tile)
+ static bool
+ nv31_mpeg_mthd_dma(struct nvkm_device *device, u32 mthd, u32 data)
+ {
++	struct nv31_mpeg *mpeg = nv31_mpeg(device->mpeg);
++	struct nvkm_subdev *subdev = &mpeg->engine.subdev;
+ 	u32 inst = data << 4;
+ 	u32 dma0 = nvkm_rd32(device, 0x700000 + inst);
+ 	u32 dma1 = nvkm_rd32(device, 0x700004 + inst);
+@@ -132,8 +134,11 @@ nv31_mpeg_mthd_dma(struct nvkm_device *device, u32 mthd, u32 data)
+ 	u32 size = dma1 + 1;
+ 
+ 	/* only allow linear DMA objects */
+-	if (!(dma0 & 0x00002000))
++	if (!(dma0 & 0x00002000)) {
++		nvkm_error(subdev, "inst %08x dma0 %08x dma1 %08x dma2 %08x\n",
++			   inst, dma0, dma1, dma2);
+ 		return false;
++	}
+ 
+ 	if (mthd == 0x0190) {
+ 		/* DMA_CMD */
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv40.c
+index 16de5bd94b14..b5ec7c504dc6 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv40.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv40.c
+@@ -31,6 +31,8 @@ bool
+ nv40_mpeg_mthd_dma(struct nvkm_device *device, u32 mthd, u32 data)
+ {
+ 	struct nvkm_instmem *imem = device->imem;
++	struct nv31_mpeg *mpeg = nv31_mpeg(device->mpeg);
++	struct nvkm_subdev *subdev = &mpeg->engine.subdev;
+ 	u32 inst = data << 4;
+ 	u32 dma0 = nvkm_instmem_rd32(imem, inst + 0);
+ 	u32 dma1 = nvkm_instmem_rd32(imem, inst + 4);
+@@ -39,8 +41,11 @@ nv40_mpeg_mthd_dma(struct nvkm_device *device, u32 mthd, u32 data)
+ 	u32 size = dma1 + 1;
+ 
+ 	/* only allow linear DMA objects */
+-	if (!(dma0 & 0x00002000))
++	if (!(dma0 & 0x00002000)) {
++		nvkm_error(subdev, "inst %08x dma0 %08x dma1 %08x dma2 %08x\n",
++			   inst, dma0, dma1, dma2);
+ 		return false;
++	}
+ 
+ 	if (mthd == 0x0190) {
+ 		/* DMA_CMD */

commit 2659b4ce284be569b06ea2c13e5d30517f8095ed
+Author: Ilia Mirkin 
+Date:   Mon Jul 3 14:46:21 2017 -0400
+
+    initial support (display-only) for GP108
+    
+    Forked from GP107 implementation. Secboot/gr left out as we don't have
+    signed blobs from NVIDIA in linux-firmware.
+    
+    (Ben): Was unable to mmiotrace the binary driver for unknown reasons,
+           so not able to 100% confirm that no other changes from GP107
+           are needed.  Quick testing shows it seems to work well enough
+           for display.  Due to NVIDIA dragging their heels on getting
+           signed firmware to us, this is the best we can do for now.
+    
+    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101601
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
+index 39fdafed7b4e..e096a5d9c292 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
+@@ -2323,6 +2323,35 @@ nv137_chipset = {
+ 	.sw = gf100_sw_new,
+ };
+ 
++static const struct nvkm_device_chip
++nv138_chipset = {
++	.name = "GP108",
++	.bar = gf100_bar_new,
++	.bios = nvkm_bios_new,
++	.bus = gf100_bus_new,
++	.devinit = gm200_devinit_new,
++	.fb = gp102_fb_new,
++	.fuse = gm107_fuse_new,
++	.gpio = gk104_gpio_new,
++	.i2c = gm200_i2c_new,
++	.ibus = gm200_ibus_new,
++	.imem = nv50_instmem_new,
++	.ltc = gp100_ltc_new,
++	.mc = gp100_mc_new,
++	.mmu = gf100_mmu_new,
++	.pci = gp100_pci_new,
++	.pmu = gp102_pmu_new,
++	.timer = gk20a_timer_new,
++	.top = gk104_top_new,
++	.ce[0] = gp102_ce_new,
++	.ce[1] = gp102_ce_new,
++	.ce[2] = gp102_ce_new,
++	.ce[3] = gp102_ce_new,
++	.disp = gp102_disp_new,
++	.dma = gf119_dma_new,
++	.fifo = gp100_fifo_new,
++};
++
+ static const struct nvkm_device_chip
+ nv13b_chipset = {
+ 	.name = "GP10B",
+@@ -2785,6 +2814,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
+ 		case 0x134: device->chip = &nv134_chipset; break;
+ 		case 0x136: device->chip = &nv136_chipset; break;
+ 		case 0x137: device->chip = &nv137_chipset; break;
++		case 0x138: device->chip = &nv138_chipset; break;
+ 		case 0x13b: device->chip = &nv13b_chipset; break;
+ 		default:
+ 			nvdev_error(device, "unknown chipset (%08x)\n", boot0);

commit eba5e56db65b7a44d57a98f5f382b2a2b9991321
+Author: Ilia Mirkin 
+Date:   Mon Jul 3 13:06:26 2017 -0400
+
+    drm/nouveau/disp/gf119-: avoid creating non-existent heads
+    
+    We assume that each board has 4 heads for GF119+. However this is not
+    necessarily true - in the case of a GP108 board, the register indicated
+    that there were only 2.
+    
+    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101601
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
+index f7b4326a4641..1449a2c8a1e9 100644
+--- a/drivers/gpu/drm/nouveau/nv50_display.c
++++ b/drivers/gpu/drm/nouveau/nv50_display.c
+@@ -4451,11 +4451,13 @@ nv50_display_create(struct drm_device *dev)
+ 
+ 	/* create crtc objects to represent the hw heads */
+ 	if (disp->disp->oclass >= GF110_DISP)
+-		crtcs = nvif_rd32(&device->object, 0x022448);
++		crtcs = nvif_rd32(&device->object, 0x612004) & 0xf;
+ 	else
+-		crtcs = 2;
++		crtcs = 0x3;
+ 
+-	for (i = 0; i < crtcs; i++) {
++	for (i = 0; i < fls(crtcs); i++) {
++		if (!(crtcs & (1 << i)))
++			continue;
+ 		ret = nv50_head_create(dev, i);
+ 		if (ret)
+ 			goto out;
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c
+index b33552757647..9fd7ae331308 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c
+@@ -92,5 +92,8 @@ gf119_head = {
+ int
+ gf119_head_new(struct nvkm_disp *disp, int id)
+ {
++	struct nvkm_device *device = disp->engine.subdev.device;
++	if (!(nvkm_rd32(device, 0x612004) & (0x00000001 << id)))
++		return 0;
+ 	return nvkm_head_new_(&gf119_head, disp, id);
+ }

commit a90e049cacd965dade4dae7263b4d3fd550e78b6
+Author: Ilia Mirkin 
+Date:   Wed Jun 28 08:24:45 2017 -0400
+
+    drm/nouveau/disp/nv50-: bump max chans to 21
+    
+    GP102's cursors go from chan 17..20. Increase the array size to hold
+    their data properly.
+    
+    Fixes: e50fcff15f ("drm/nouveau/disp/gp102: fix cursor/overlay immediate channel indices")
+    Cc: stable@vger.kernel.org # v4.10+
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h
+index 19c635663399..6ea19466f436 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h
+@@ -22,7 +22,7 @@ struct nv50_disp {
+ 		u8 type[3];
+ 	} pior;
+ 
+-	struct nv50_disp_chan *chan[17];
++	struct nv50_disp_chan *chan[21];
+ };
+ 
+ void nv50_disp_super_1(struct nv50_disp *);

commit eef4988ab4c1a99e88e535502a67763a78d51515
+Author: Ilia Mirkin 
+Date:   Mon Apr 3 22:46:14 2017 -0400
+
+    drm/nouveau/fifo/nv40: no ctxsw for pre-nv44 mpeg engine
+    
+    Signed-off-by: Ilia Mirkin 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c
+index 0ec179fc40a1..5f722c6e8a2f 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c
+@@ -44,6 +44,8 @@ nv40_fifo_dma_engine(struct nvkm_engine *engine, u32 *reg, u32 *ctx)
+ 		*ctx = 0x38;
+ 		return true;
+ 	case NVKM_ENGINE_MPEG:
++		if (engine->subdev.device->chipset < 0x44)
++			return false;
+ 		*reg = 0x00330c;
+ 		*ctx = 0x54;
+ 		return true;

commit ac799acaa4d8db4f7dcd968b15c9596c80a4677f
+Author: Ilia Mirkin 
+Date:   Sat Mar 18 16:23:10 2017 -0400
+
+    drm/nouveau/mmu/nv4a: use nv04 mmu rather than the nv44 one
+    
+    The NV4A (aka NV44A) is an oddity in the family. It only comes in AGP
+    and PCI varieties, rather than a core PCIE chip with a bridge for
+    AGP/PCI as necessary. As a result, it appears that the MMU is also
+    non-functional. For AGP cards, the vast majority of the NV4A lineup,
+    this worked out since we force AGP cards to use the nv04 mmu. However
+    for PCI variants, this did not work.
+    
+    Switching to the NV04 MMU makes it work like a charm. Thanks to mwk for
+    the suggestion. This should be a no-op for NV4A AGP boards, as they were
+    using it already.
+    
+    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=70388
+    Signed-off-by: Ilia Mirkin 
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
+index 1076949b802a..ffd7d09ed3ac 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
+@@ -714,7 +714,7 @@ nv4a_chipset = {
+ 	.i2c = nv04_i2c_new,
+ 	.imem = nv40_instmem_new,
+ 	.mc = nv44_mc_new,
+-	.mmu = nv44_mmu_new,
++	.mmu = nv04_mmu_new,
+ 	.pci = nv40_pci_new,
+ 	.therm = nv40_therm_new,
+ 	.timer = nv41_timer_new,

commit ad01a91a820cd9f0d880c407bf556b67298dcc93
+Author: Ilia Mirkin 
+Date:   Sat Mar 18 21:53:05 2017 -0400
+
+    drm/nouveau/mpeg: mthd returns true on success now
+    
+    Signed-off-by: Ilia Mirkin 
+    Fixes: 590801c1a3 ("drm/nouveau/mpeg: remove dependence on namedb/engctx lookup")
+    Cc: stable@vger.kernel.org # v4.3+
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c
+index 003ac915eaad..8a8895246d26 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c
+@@ -198,7 +198,7 @@ nv31_mpeg_intr(struct nvkm_engine *engine)
+ 		}
+ 
+ 		if (type == 0x00000010) {
+-			if (!nv31_mpeg_mthd(mpeg, mthd, data))
++			if (nv31_mpeg_mthd(mpeg, mthd, data))
+ 				show &= ~0x01000000;
+ 		}
+ 	}
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c
+index e536f37e24b0..c3cf02ed468e 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c
+@@ -172,7 +172,7 @@ nv44_mpeg_intr(struct nvkm_engine *engine)
+ 		}
+ 
+ 		if (type == 0x00000010) {
+-			if (!nv44_mpeg_mthd(subdev->device, mthd, data))
++			if (nv44_mpeg_mthd(subdev->device, mthd, data))
+ 				show &= ~0x01000000;
+ 		}
+ 	}

commit f94773b9f5ecd1df7c88c2e921924dd41d2020cc
+Author: Ilia Mirkin 
+Date:   Sat Mar 18 16:23:10 2017 -0400
+
+    drm/nouveau/mmu/nv4a: use nv04 mmu rather than the nv44 one
+    
+    The NV4A (aka NV44A) is an oddity in the family. It only comes in AGP
+    and PCI varieties, rather than a core PCIE chip with a bridge for
+    AGP/PCI as necessary. As a result, it appears that the MMU is also
+    non-functional. For AGP cards, the vast majority of the NV4A lineup,
+    this worked out since we force AGP cards to use the nv04 mmu. However
+    for PCI variants, this did not work.
+    
+    Switching to the NV04 MMU makes it work like a charm. Thanks to mwk for
+    the suggestion. This should be a no-op for NV4A AGP boards, as they were
+    using it already.
+    
+    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=70388
+    Signed-off-by: Ilia Mirkin 
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
+index 273562dd6bbd..0fc41db34522 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
+@@ -714,7 +714,7 @@ nv4a_chipset = {
+ 	.i2c = nv04_i2c_new,
+ 	.imem = nv40_instmem_new,
+ 	.mc = nv44_mc_new,
+-	.mmu = nv44_mmu_new,
++	.mmu = nv04_mmu_new,
+ 	.pci = nv40_pci_new,
+ 	.therm = nv40_therm_new,
+ 	.timer = nv41_timer_new,

commit 83bce9c2baa51e439480a713119a73d3c8b61083
+Author: Ilia Mirkin 
+Date:   Sat Mar 18 21:53:05 2017 -0400
+
+    drm/nouveau/mpeg: mthd returns true on success now
+    
+    Signed-off-by: Ilia Mirkin 
+    Fixes: 590801c1a3 ("drm/nouveau/mpeg: remove dependence on namedb/engctx lookup")
+    Cc: stable@vger.kernel.org # v4.3+
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c
+index 003ac915eaad..8a8895246d26 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c
+@@ -198,7 +198,7 @@ nv31_mpeg_intr(struct nvkm_engine *engine)
+ 		}
+ 
+ 		if (type == 0x00000010) {
+-			if (!nv31_mpeg_mthd(mpeg, mthd, data))
++			if (nv31_mpeg_mthd(mpeg, mthd, data))
+ 				show &= ~0x01000000;
+ 		}
+ 	}
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c
+index e536f37e24b0..c3cf02ed468e 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c
+@@ -172,7 +172,7 @@ nv44_mpeg_intr(struct nvkm_engine *engine)
+ 		}
+ 
+ 		if (type == 0x00000010) {
+-			if (!nv44_mpeg_mthd(subdev->device, mthd, data))
++			if (nv44_mpeg_mthd(subdev->device, mthd, data))
+ 				show &= ~0x01000000;
+ 		}
+ 	}

commit 0879683280508ea3d474dcaf91b4658985824513
+Author: Ilia Mirkin 
+Date:   Thu Jan 5 01:13:15 2017 -0500
+
+    drm/nouveau: fix bug id typo in comment
+    
+    The issue was recorded in fd.o bug 27501, not 25701.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/rammcp77.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/rammcp77.c
+index 0a0e44b75577..017a91de74a0 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/rammcp77.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/rammcp77.c
+@@ -39,7 +39,7 @@ mcp77_ram_init(struct nvkm_ram *base)
+ 	u32 flush  = ((ram->base.size - (ram->poller_base + 0x40)) >> 5) - 1;
+ 
+ 	/* Enable NISO poller for various clients and set their associated
+-	 * read address, only for MCP77/78 and MCP79/7A. (fd#25701)
++	 * read address, only for MCP77/78 and MCP79/7A. (fd#27501)
+ 	 */
+ 	nvkm_wr32(device, 0x100c18, dniso);
+ 	nvkm_mask(device, 0x100c14, 0x00000000, 0x00000001);

commit 24bf7ae359b8cca165bb30742d2b1c03a1eb23af
+Author: Ilia Mirkin 
+Date:   Thu Jan 19 22:56:30 2017 -0500
+
+    drm/nouveau/nv1a,nv1f/disp: fix memory clock rate retrieval
+    
+    Based on the xf86-video-nv code, NFORCE (NV1A) and NFORCE2 (NV1F) have a
+    different way of retrieving clocks. See the
+    nv_hw.c:nForceUpdateArbitrationSettings function in the original code
+    for how these clocks were accessed.
+    
+    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=54587
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/dispnv04/hw.c b/drivers/gpu/drm/nouveau/dispnv04/hw.c
+index 74856a8b8f35..e64f52464ecf 100644
+--- a/drivers/gpu/drm/nouveau/dispnv04/hw.c
++++ b/drivers/gpu/drm/nouveau/dispnv04/hw.c
+@@ -222,6 +222,7 @@ nouveau_hw_get_clock(struct drm_device *dev, enum nvbios_pll_type plltype)
+ 		uint32_t mpllP;
+ 
+ 		pci_read_config_dword(pci_get_bus_and_slot(0, 3), 0x6c, &mpllP);
++		mpllP = (mpllP >> 8) & 0xf;
+ 		if (!mpllP)
+ 			mpllP = 4;
+ 
+@@ -232,7 +233,7 @@ nouveau_hw_get_clock(struct drm_device *dev, enum nvbios_pll_type plltype)
+ 		uint32_t clock;
+ 
+ 		pci_read_config_dword(pci_get_bus_and_slot(0, 5), 0x4c, &clock);
+-		return clock;
++		return clock / 1000;
+ 	}
+ 
+ 	ret = nouveau_hw_get_pllvals(dev, plltype, &pllvals);

commit 1cc88ab9542441b3371104872eefc4924408aaa3
+Author: Ilia Mirkin 
+Date:   Sat Aug 27 21:32:34 2016 -0400
+
+    drm/nouveau/gr/nv3x: add 0x0597 kelvin 3d class support
+    
+    Tested on a NV34. There are reports of this also working on the other
+    nv3x chips. Largely useful for testing software written for NV2x without
+    having the actual hardware available.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c
+index f1e15a4d4f64..b4e3c50badc7 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c
+@@ -187,6 +187,7 @@ nv30_gr = {
+ 		{ -1, -1, 0x038a, &nv04_gr_object }, /* ifc (nv30) */
+ 		{ -1, -1, 0x039e, &nv04_gr_object }, /* swzsurf (nv30) */
+ 		{ -1, -1, 0x0397, &nv04_gr_object }, /* rankine */
++		{ -1, -1, 0x0597, &nv04_gr_object }, /* kelvin */
+ 		{}
+ 	}
+ };
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c
+index 300f5ed5de0b..e7ed04b935cd 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c
+@@ -123,6 +123,7 @@ nv34_gr = {
+ 		{ -1, -1, 0x0389, &nv04_gr_object }, /* sifm (nv30) */
+ 		{ -1, -1, 0x038a, &nv04_gr_object }, /* ifc (nv30) */
+ 		{ -1, -1, 0x039e, &nv04_gr_object }, /* swzsurf (nv30) */
++		{ -1, -1, 0x0597, &nv04_gr_object }, /* kelvin */
+ 		{ -1, -1, 0x0697, &nv04_gr_object }, /* rankine */
+ 		{}
+ 	}
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c
+index 740df0f52c38..5e8abacbacc6 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c
+@@ -124,6 +124,7 @@ nv35_gr = {
+ 		{ -1, -1, 0x038a, &nv04_gr_object }, /* ifc (nv30) */
+ 		{ -1, -1, 0x039e, &nv04_gr_object }, /* swzsurf (nv30) */
+ 		{ -1, -1, 0x0497, &nv04_gr_object }, /* rankine */
++		{ -1, -1, 0x0597, &nv04_gr_object }, /* kelvin */
+ 		{}
+ 	}
+ };

commit 9936aeeaebce816ba428eedf4da4b1a8e92e77f9
+Author: Ilia Mirkin 
+Date:   Wed Jul 27 01:00:31 2016 -0400
+
+    drm/nouveau/nouveau: bios pointers may be unaligned, use proper accessors
+    
+    This can show up on SPARC or other architectures that don't handle
+    unaligned accesses. The kernel normally fixes these up, but it shouldn't
+    have to.
+    
+    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=96836
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h
+index 0067586eb015..18eb061ccafb 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_bios.h
++++ b/drivers/gpu/drm/nouveau/nouveau_bios.h
+@@ -31,10 +31,8 @@
+ 
+ #define DCB_LOC_ON_CHIP 0
+ 
+-#define ROM16(x) le16_to_cpu(*(u16 *)&(x))
+-#define ROM32(x) le32_to_cpu(*(u32 *)&(x))
+-#define ROM48(x) ({ u8 *p = &(x); (u64)ROM16(p[4]) << 32 | ROM32(p[0]); })
+-#define ROM64(x) le64_to_cpu(*(u64 *)&(x))
++#define ROM16(x) get_unaligned_le16(&(x))
++#define ROM32(x) get_unaligned_le32(&(x))
+ #define ROMPTR(d,x) ({            \
+ 	struct nouveau_drm *drm = nouveau_drm((d)); \
+ 	ROM16(x) ? &drm->vbios.data[ROM16(x)] : NULL; \
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.c
+index 45a2f8e784f9..9abfa5e2fe9f 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.c
+@@ -23,8 +23,8 @@
+  */
+ #include "mxms.h"
+ 
+-#define ROM16(x) le16_to_cpu(*(u16 *)&(x))
+-#define ROM32(x) le32_to_cpu(*(u32 *)&(x))
++#define ROM16(x) get_unaligned_le16(&(x))
++#define ROM32(x) get_unaligned_le32(&(x))
+ 
+ static u8 *
+ mxms_data(struct nvkm_mxm *mxm)

commit 666ca3d8f19082f40745d75f3cc7cc0200ee87e3
+Author: Ilia Mirkin 
+Date:   Fri Sep 9 22:34:02 2016 -0400
+
+    drm/nouveau/fifo/nv04: avoid ramht race against cookie insertion
+    
+    Signed-off-by: Ilia Mirkin 
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c
+index edec30fd3ecd..0a7b6ed5ed28 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c
+@@ -37,7 +37,10 @@ nv04_fifo_dma_object_dtor(struct nvkm_fifo_chan *base, int cookie)
+ {
+ 	struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
+ 	struct nvkm_instmem *imem = chan->fifo->base.engine.subdev.device->imem;
++
++	mutex_lock(&chan->fifo->base.engine.subdev.mutex);
+ 	nvkm_ramht_remove(imem->ramht, cookie);
++	mutex_unlock(&chan->fifo->base.engine.subdev.mutex);
+ }
+ 
+ static int

commit d0e62ef6ed257715a88d0e5d7cd850a1695429e2
+Author: Ilia Mirkin 
+Date:   Wed Jul 27 19:16:39 2016 -0400
+
+    drm/nouveau/gr/nv3x: fix instobj write offsets in gr setup
+    
+    This should fix some unaligned access warnings. This is also likely to
+    fix non-descript issues on nv30/nv34 as a result of incorrect channel
+    setup.
+    
+    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=96836
+    Signed-off-by: Ilia Mirkin 
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c
+index 69de8c6259fe..f1e15a4d4f64 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c
+@@ -76,8 +76,8 @@ nv30_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
+ 		nvkm_wo32(chan->inst, i, 0x00040004);
+ 	for (i = 0x1f18; i <= 0x3088 ; i += 16) {
+ 		nvkm_wo32(chan->inst, i + 0, 0x10700ff9);
+-		nvkm_wo32(chan->inst, i + 1, 0x0436086c);
+-		nvkm_wo32(chan->inst, i + 2, 0x000c001b);
++		nvkm_wo32(chan->inst, i + 4, 0x0436086c);
++		nvkm_wo32(chan->inst, i + 8, 0x000c001b);
+ 	}
+ 	for (i = 0x30b8; i < 0x30c8; i += 4)
+ 		nvkm_wo32(chan->inst, i, 0x0000ffff);
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c
+index 2207dac23981..300f5ed5de0b 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c
+@@ -75,8 +75,8 @@ nv34_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
+ 		nvkm_wo32(chan->inst, i, 0x00040004);
+ 	for (i = 0x15ac; i <= 0x271c ; i += 16) {
+ 		nvkm_wo32(chan->inst, i + 0, 0x10700ff9);
+-		nvkm_wo32(chan->inst, i + 1, 0x0436086c);
+-		nvkm_wo32(chan->inst, i + 2, 0x000c001b);
++		nvkm_wo32(chan->inst, i + 4, 0x0436086c);
++		nvkm_wo32(chan->inst, i + 8, 0x000c001b);
+ 	}
+ 	for (i = 0x274c; i < 0x275c; i += 4)
+ 		nvkm_wo32(chan->inst, i, 0x0000ffff);

commit 78a121d82da8aff3aca2a6a1c40f5061081760f0
+Author: Ilia Mirkin 
+Date:   Sun Mar 6 16:06:06 2016 -0500
+
+    drm/nouveau/core: use vzalloc for allocating ramht
+    
+    Most calls to nvkm_ramht_new use 0x8000 as the size. This results in a
+    fairly sizeable chunk of memory to be allocated, which may not be
+    available with kzalloc. Since this is done fairly rarely (once per
+    channel), use vzalloc instead.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/core/ramht.c b/drivers/gpu/drm/nouveau/nvkm/core/ramht.c
+index 3216e157a8a0..89da47234016 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/core/ramht.c
++++ b/drivers/gpu/drm/nouveau/nvkm/core/ramht.c
+@@ -131,7 +131,7 @@ nvkm_ramht_del(struct nvkm_ramht **pramht)
+ 	struct nvkm_ramht *ramht = *pramht;
+ 	if (ramht) {
+ 		nvkm_gpuobj_del(&ramht->gpuobj);
+-		kfree(*pramht);
++		vfree(*pramht);
+ 		*pramht = NULL;
+ 	}
+ }
+@@ -143,8 +143,8 @@ nvkm_ramht_new(struct nvkm_device *device, u32 size, u32 align,
+ 	struct nvkm_ramht *ramht;
+ 	int ret, i;
+ 
+-	if (!(ramht = *pramht = kzalloc(sizeof(*ramht) + (size >> 3) *
+-					sizeof(*ramht->data), GFP_KERNEL)))
++	if (!(ramht = *pramht = vzalloc(sizeof(*ramht) +
++					(size >> 3) * sizeof(*ramht->data))))
+ 		return -ENOMEM;
+ 
+ 	ramht->device = device;

commit caf2be8a345f9edd00f54a77629ff7509b1d6c4b
+Author: Ilia Mirkin 
+Date:   Sat Jan 2 17:54:51 2016 -0500
+
+    drm/nouveau/gr/gf100: provide a bit more info for various errors
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
+index 414521b438f7..1f81069edc58 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
+@@ -856,7 +856,41 @@ gf100_gr_units(struct nvkm_gr *base)
+ 	return cfg;
+ }
+ 
++static const struct nvkm_bitfield gf100_dispatch_error[] = {
++	{ 0x00000001, "INJECTED_BUNDLE_ERROR" },
++	{ 0x00000002, "CLASS_SUBCH_MISMATCH" },
++	{ 0x00000004, "SUBCHSW_DURING_NOTIFY" },
++	{}
++};
++
++static const struct nvkm_bitfield gf100_m2mf_error[] = {
++	{ 0x00000001, "PUSH_TOO_MUCH_DATA" },
++	{ 0x00000002, "PUSH_NOT_ENOUGH_DATA" },
++	{}
++};
++
++static const struct nvkm_bitfield gf100_unk6_error[] = {
++	{ 0x00000001, "TEMP_TOO_SMALL" },
++	{}
++};
++
++static const struct nvkm_bitfield gf100_ccache_error[] = {
++	{ 0x00000001, "INTR" },
++	{ 0x00000002, "LDCONST_OOB" },
++	{}
++};
++
++static const struct nvkm_bitfield gf100_macro_error[] = {
++	{ 0x00000001, "TOO_FEW_PARAMS" },
++	{ 0x00000002, "TOO_MANY_PARAMS" },
++	{ 0x00000004, "ILLEGAL_OPCODE" },
++	{ 0x00000008, "DOUBLE_BRANCH" },
++	{ 0x00000010, "WATCHDOG" },
++	{}
++};
++
+ static const struct nvkm_bitfield gk104_sked_error[] = {
++	{ 0x00000040, "CTA_RESUME" },
+ 	{ 0x00000080, "CONSTANT_BUFFER_SIZE" },
+ 	{ 0x00000200, "LOCAL_MEMORY_SIZE_POS" },
+ 	{ 0x00000400, "LOCAL_MEMORY_SIZE_NEG" },
+@@ -866,6 +900,8 @@ static const struct nvkm_bitfield gk104_sked_error[] = {
+ 	{ 0x00040000, "TOTAL_THREADS" },
+ 	{ 0x00100000, "PROGRAM_OFFSET" },
+ 	{ 0x00200000, "SHARED_MEMORY_SIZE" },
++	{ 0x00800000, "CTA_THREAD_DIMENSION_ZERO" },
++	{ 0x01000000, "MEMORY_WINDOW_OVERLAP" },
+ 	{ 0x02000000, "SHARED_CONFIG_TOO_SMALL" },
+ 	{ 0x04000000, "TOTAL_REGISTER_COUNT" },
+ 	{}
+@@ -1035,12 +1071,16 @@ gf100_gr_trap_intr(struct gf100_gr *gr)
+ {
+ 	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
+ 	struct nvkm_device *device = subdev->device;
++	char error[128];
+ 	u32 trap = nvkm_rd32(device, 0x400108);
+ 	int rop, gpc;
+ 
+ 	if (trap & 0x00000001) {
+ 		u32 stat = nvkm_rd32(device, 0x404000);
+-		nvkm_error(subdev, "DISPATCH %08x\n", stat);
++
++		nvkm_snprintbf(error, sizeof(error), gf100_dispatch_error,
++			       stat & 0x3fffffff);
++		nvkm_error(subdev, "DISPATCH %08x [%s]\n", stat, error);
+ 		nvkm_wr32(device, 0x404000, 0xc0000000);
+ 		nvkm_wr32(device, 0x400108, 0x00000001);
+ 		trap &= ~0x00000001;
+@@ -1048,7 +1088,11 @@ gf100_gr_trap_intr(struct gf100_gr *gr)
+ 
+ 	if (trap & 0x00000002) {
+ 		u32 stat = nvkm_rd32(device, 0x404600);
+-		nvkm_error(subdev, "M2MF %08x\n", stat);
++
++		nvkm_snprintbf(error, sizeof(error), gf100_m2mf_error,
++			       stat & 0x3fffffff);
++		nvkm_error(subdev, "M2MF %08x [%s]\n", stat, error);
++
+ 		nvkm_wr32(device, 0x404600, 0xc0000000);
+ 		nvkm_wr32(device, 0x400108, 0x00000002);
+ 		trap &= ~0x00000002;
+@@ -1056,7 +1100,10 @@ gf100_gr_trap_intr(struct gf100_gr *gr)
+ 
+ 	if (trap & 0x00000008) {
+ 		u32 stat = nvkm_rd32(device, 0x408030);
+-		nvkm_error(subdev, "CCACHE %08x\n", stat);
++
++		nvkm_snprintbf(error, sizeof(error), gf100_m2mf_error,
++			       stat & 0x3fffffff);
++		nvkm_error(subdev, "CCACHE %08x [%s]\n", stat, error);
+ 		nvkm_wr32(device, 0x408030, 0xc0000000);
+ 		nvkm_wr32(device, 0x400108, 0x00000008);
+ 		trap &= ~0x00000008;
+@@ -1064,7 +1111,8 @@ gf100_gr_trap_intr(struct gf100_gr *gr)
+ 
+ 	if (trap & 0x00000010) {
+ 		u32 stat = nvkm_rd32(device, 0x405840);
+-		nvkm_error(subdev, "SHADER %08x\n", stat);
++		nvkm_error(subdev, "SHADER %08x, sph: 0x%06x, stage: 0x%02x\n",
++			   stat, stat & 0xffffff, (stat >> 24) & 0x3f);
+ 		nvkm_wr32(device, 0x405840, 0xc0000000);
+ 		nvkm_wr32(device, 0x400108, 0x00000010);
+ 		trap &= ~0x00000010;
+@@ -1072,7 +1120,11 @@ gf100_gr_trap_intr(struct gf100_gr *gr)
+ 
+ 	if (trap & 0x00000040) {
+ 		u32 stat = nvkm_rd32(device, 0x40601c);
+-		nvkm_error(subdev, "UNK6 %08x\n", stat);
++
++		nvkm_snprintbf(error, sizeof(error), gf100_unk6_error,
++			       stat & 0x3fffffff);
++		nvkm_error(subdev, "UNK6 %08x [%s]\n", stat, error);
++
+ 		nvkm_wr32(device, 0x40601c, 0xc0000000);
+ 		nvkm_wr32(device, 0x400108, 0x00000040);
+ 		trap &= ~0x00000040;
+@@ -1080,7 +1132,16 @@ gf100_gr_trap_intr(struct gf100_gr *gr)
+ 
+ 	if (trap & 0x00000080) {
+ 		u32 stat = nvkm_rd32(device, 0x404490);
+-		nvkm_error(subdev, "MACRO %08x\n", stat);
++		u32 pc = nvkm_rd32(device, 0x404494);
++		u32 op = nvkm_rd32(device, 0x40449c);
++
++		nvkm_snprintbf(error, sizeof(error), gf100_macro_error,
++			       stat & 0x1fffffff);
++		nvkm_error(subdev, "MACRO %08x [%s], pc: 0x%03x%s, op: 0x%08x\n",
++			   stat, error, pc & 0x7ff,
++			   (pc & 0x10000000) ? "" : " (invalid)",
++			   op);
++
+ 		nvkm_wr32(device, 0x404490, 0xc0000000);
+ 		nvkm_wr32(device, 0x400108, 0x00000080);
+ 		trap &= ~0x00000080;
+@@ -1088,10 +1149,9 @@ gf100_gr_trap_intr(struct gf100_gr *gr)
+ 
+ 	if (trap & 0x00000100) {
+ 		u32 stat = nvkm_rd32(device, 0x407020) & 0x3fffffff;
+-		char sked[128];
+ 
+-		nvkm_snprintbf(sked, sizeof(sked), gk104_sked_error, stat);
+-		nvkm_error(subdev, "SKED: %08x [%s]\n", stat, sked);
++		nvkm_snprintbf(error, sizeof(error), gk104_sked_error, stat);
++		nvkm_error(subdev, "SKED: %08x [%s]\n", stat, error);
+ 
+ 		if (stat)
+ 			nvkm_wr32(device, 0x407020, 0x40000000);

commit cfb4f929f7f8716af4de085da1d3881384644b81
+Author: Ilia Mirkin 
+Date:   Thu Nov 5 02:33:40 2015 -0500
+
+    drm/nouveau/nvkm: add/remove 0's to make 7 (or 9)-nibble constants use 8 nibbles
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c
+index ddaa16a71c84..ad0a6cfe7580 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c
+@@ -55,7 +55,7 @@ gk20a_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info)
+ 
+ 	gk104_grctx_generate_rop_active_fbps(gr);
+ 
+-	nvkm_mask(device, 0x5044b0, 0x8000000, 0x8000000);
++	nvkm_mask(device, 0x5044b0, 0x08000000, 0x08000000);
+ 
+ 	gf100_gr_wait_idle(gr);
+ 
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c
+index 9df45030ff9f..1fa3ade468ae 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c
+@@ -216,11 +216,11 @@ r1373f4_fini(struct gk104_ramfuc *fuc)
+ 	ram_wr32(fuc, 0x1373ec, tmp | (v1 << 16));
+ 	ram_mask(fuc, 0x1373f0, (~ram->mode & 3), 0x00000000);
+ 	if (ram->mode == 2) {
+-		ram_mask(fuc, 0x1373f4, 0x00000003, 0x000000002);
+-		ram_mask(fuc, 0x1373f4, 0x00001100, 0x000000000);
++		ram_mask(fuc, 0x1373f4, 0x00000003, 0x00000002);
++		ram_mask(fuc, 0x1373f4, 0x00001100, 0x00000000);
+ 	} else {
+-		ram_mask(fuc, 0x1373f4, 0x00000003, 0x000000001);
+-		ram_mask(fuc, 0x1373f4, 0x00010000, 0x000000000);
++		ram_mask(fuc, 0x1373f4, 0x00000003, 0x00000001);
++		ram_mask(fuc, 0x1373f4, 0x00010000, 0x00000000);
+ 	}
+ 	ram_mask(fuc, 0x10f800, 0x00000030, (v0 ^ v1) << 4);
+ }
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/nv40.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/nv40.c
+index 6326fdc5a48d..2c92ffb5f9d0 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/nv40.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/nv40.c
+@@ -107,7 +107,7 @@ nv40_fan_pwm_ctrl(struct nvkm_therm *therm, int line, bool enable)
+ {
+ 	struct nvkm_subdev *subdev = &therm->subdev;
+ 	struct nvkm_device *device = subdev->device;
+-	u32 mask = enable ? 0x80000000 : 0x0000000;
++	u32 mask = enable ? 0x80000000 : 0x00000000;
+ 	if      (line == 2) nvkm_mask(device, 0x0010f0, 0x80000000, mask);
+ 	else if (line == 9) nvkm_mask(device, 0x0015f4, 0x80000000, mask);
+ 	else {

commit 700c18ca08bf79360c117e39490c74c681189b65
+Author: Ilia Mirkin 
+Date:   Tue Nov 3 21:14:26 2015 -0500
+
+    drm/nouveau/kms: no need to check for empty edid before drm_detect_hdmi_monitor
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
+index ee97eae3c973..74247e1cb58d 100644
+--- a/drivers/gpu/drm/nouveau/nv50_display.c
++++ b/drivers/gpu/drm/nouveau/nv50_display.c
+@@ -774,7 +774,6 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update)
+ 	 */
+ 	if (nv_connector && ( nv_connector->underscan == UNDERSCAN_ON ||
+ 			     (nv_connector->underscan == UNDERSCAN_AUTO &&
+-			      nv_connector->edid &&
+ 			      drm_detect_hdmi_monitor(nv_connector->edid)))) {
+ 		u32 bX = nv_connector->underscan_hborder;
+ 		u32 bY = nv_connector->underscan_vborder;

commit 1a0c96c075bb4517d4ce4fb6750ee0a3cf38714c
+Author: Ilia Mirkin 
+Date:   Tue Nov 3 21:00:11 2015 -0500
+
+    drm/nouveau/kms: allow 225/297MHz pixel clocks for HDMI on Fermi/Kepler
+    
+    Some Fermi's apparently alow allow 297MHz clocks, so create a parameter
+    which allows end-users to set it themselves until we have a reliable way
+    to determine the board's maximum pixel clocks.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
+index 5dd1d0111cac..8d00d006fcde 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
++++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
+@@ -56,6 +56,10 @@ MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (default: enabled)");
+ int nouveau_duallink = 1;
+ module_param_named(duallink, nouveau_duallink, int, 0400);
+ 
++MODULE_PARM_DESC(hdmimhz, "Force a maximum HDMI pixel clock (in MHz)");
++int nouveau_hdmimhz = 0;
++module_param_named(hdmimhz, nouveau_hdmimhz, int, 0400);
++
+ struct nouveau_encoder *
+ find_encoder(struct drm_connector *connector, int type)
+ {
+@@ -809,12 +813,23 @@ nouveau_connector_get_modes(struct drm_connector *connector)
+ }
+ 
+ static unsigned
+-get_tmds_link_bandwidth(struct drm_connector *connector)
++get_tmds_link_bandwidth(struct drm_connector *connector, bool hdmi)
+ {
+ 	struct nouveau_connector *nv_connector = nouveau_connector(connector);
+ 	struct nouveau_drm *drm = nouveau_drm(connector->dev);
+ 	struct dcb_output *dcb = nv_connector->detected_encoder->dcb;
+ 
++	if (hdmi) {
++		if (nouveau_hdmimhz > 0)
++			return nouveau_hdmimhz * 1000;
++		/* Note: these limits are conservative, some Fermi's
++		 * can do 297 MHz. Unclear how this can be determined.
++		 */
++		if (drm->device.info.family >= NV_DEVICE_INFO_V0_KEPLER)
++			return 297000;
++		if (drm->device.info.family >= NV_DEVICE_INFO_V0_FERMI)
++			return 225000;
++	}
+ 	if (dcb->location != DCB_LOC_ON_CHIP ||
+ 	    drm->device.info.chipset >= 0x46)
+ 		return 165000;
+@@ -835,6 +850,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
+ 	struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
+ 	unsigned min_clock = 25000, max_clock = min_clock;
+ 	unsigned clock = mode->clock;
++	bool hdmi;
+ 
+ 	switch (nv_encoder->dcb->type) {
+ 	case DCB_OUTPUT_LVDS:
+@@ -847,8 +863,10 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
+ 		max_clock = 400000;
+ 		break;
+ 	case DCB_OUTPUT_TMDS:
+-		max_clock = get_tmds_link_bandwidth(connector);
+-		if (nouveau_duallink && nv_encoder->dcb->duallink_possible)
++		hdmi = drm_detect_hdmi_monitor(nv_connector->edid);
++		max_clock = get_tmds_link_bandwidth(connector, hdmi);
++		if (!hdmi && nouveau_duallink &&
++		    nv_encoder->dcb->duallink_possible)
+ 			max_clock *= 2;
+ 		break;
+ 	case DCB_OUTPUT_ANALOG:

commit b41c48571d504f293a9a6a6cfd6c8e5dcb4ccf83
+Author: Ilia Mirkin 
+Date:   Sat Oct 31 15:06:11 2015 -0400
+
+    drm/nouveau/pci: enable c800 magic for Medion Erazer X7827
+    
+    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=91557
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
+index c5fc9093ca63..e3c783d0e2ab 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
+@@ -684,6 +684,7 @@ nvkm_device_pci_10de_1189[] = {
+ static const struct nvkm_device_pci_vendor
+ nvkm_device_pci_10de_1199[] = {
+ 	{ 0x1458, 0xd001, "GeForce GTX 760" },
++	{ 0x1462, 0x1106, "GeForce GTX 780M", { .War00C800_0 = true } }, /* Medion Erazer X7827 */
+ 	{}
+ };
+ 

commit a2736b07df1f17c24c8890eb7b2dac529d9725d3
+Author: Ilia Mirkin 
+Date:   Tue Oct 27 17:39:49 2015 -0400
+
+    drm/nouveau/pci: enable c800 magic for Lenovo Y510P
+    
+    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=70354#c75
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
+index e8eb14e438f4..c5fc9093ca63 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
+@@ -258,6 +258,12 @@ nvkm_device_pci_10de_0df4[] = {
+ 	{}
+ };
+ 
++static const struct nvkm_device_pci_vendor
++nvkm_device_pci_10de_0fcd[] = {
++	{ 0x17aa, 0x3801, NULL, { .War00C800_0 = true } }, /* Lenovo Y510P */
++	{}
++};
++
+ static const struct nvkm_device_pci_vendor
+ nvkm_device_pci_10de_0fd2[] = {
+ 	{ 0x1028, 0x0595, "GeForce GT 640M LE" },
+@@ -1349,7 +1355,7 @@ nvkm_device_pci_10de[] = {
+ 	{ 0x0fc6, "GeForce GTX 650" },
+ 	{ 0x0fc8, "GeForce GT 740" },
+ 	{ 0x0fc9, "GeForce GT 730" },
+-	{ 0x0fcd, "GeForce GT 755M" },
++	{ 0x0fcd, "GeForce GT 755M", nvkm_device_pci_10de_0fcd },
+ 	{ 0x0fce, "GeForce GT 640M LE" },
+ 	{ 0x0fd1, "GeForce GT 650M" },
+ 	{ 0x0fd2, "GeForce GT 640M", nvkm_device_pci_10de_0fd2 },

commit 2e69a5cd25a131cf283d3b655c01fb6db15dd60c
+Author: Ilia Mirkin 
+Date:   Wed Oct 7 18:39:33 2015 -0400
+
+    drm/nouveau/gr: add FERMI_COMPUTE_B class to GF110+
+    
+    GF110+ supports both the A and B compute classes, make sure to accept
+    both.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c
+index d13187409d68..d081ee41fc14 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c
+@@ -98,6 +98,7 @@ gf110_gr = {
+ 		{ -1, -1, FERMI_B, &gf100_fermi },
+ 		{ -1, -1, FERMI_C, &gf100_fermi },
+ 		{ -1, -1, FERMI_COMPUTE_A },
++		{ -1, -1, FERMI_COMPUTE_B },
+ 		{}
+ 	}
+ };
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c
+index 28483d8bf3d2..d8e8af4d3b30 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c
+@@ -135,6 +135,7 @@ gf117_gr = {
+ 		{ -1, -1, FERMI_B, &gf100_fermi },
+ 		{ -1, -1, FERMI_C, &gf100_fermi },
+ 		{ -1, -1, FERMI_COMPUTE_A },
++		{ -1, -1, FERMI_COMPUTE_B },
+ 		{}
+ 	}
+ };
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c
+index 9811a72e0313..01faf9a73774 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c
+@@ -189,6 +189,7 @@ gf119_gr = {
+ 		{ -1, -1, FERMI_B, &gf100_fermi },
+ 		{ -1, -1, FERMI_C, &gf100_fermi },
+ 		{ -1, -1, FERMI_COMPUTE_A },
++		{ -1, -1, FERMI_COMPUTE_B },
+ 		{}
+ 	}
+ };

commit 3988f645f053a6889d00324dac3e57bd62cb8900
+Author: Ilia Mirkin 
+Date:   Wed Oct 7 18:39:32 2015 -0400
+
+    drm/nouveau/gr: document mp error 0x10
+    
+    NVIDIA provided the documentation for mp error 0x10, INVALID_ADDR_SPACE,
+    which apparently happens when trying to use an atomic operation on
+    local or shared memory (instead of global memory).
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
+index f1358a564e3e..dda7a7d224c9 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
+@@ -882,6 +882,7 @@ static const struct nvkm_enum gf100_mp_warp_error[] = {
+ 	{ 0x0d, "GPR_OUT_OF_BOUNDS" },
+ 	{ 0x0e, "MEM_OUT_OF_BOUNDS" },
+ 	{ 0x0f, "UNALIGNED_MEM_ACCESS" },
++	{ 0x10, "INVALID_ADDR_SPACE" },
+ 	{ 0x11, "INVALID_PARAM" },
+ 	{}
+ };

commit 04b8a4bd8e01e25b9fa9fa7b1c957a7346ae83c1
+Author: Ilia Mirkin 
+Date:   Tue Oct 20 01:15:39 2015 -0400
+
+    drm/nouveau/gem: return only valid domain when there's only one
+    
+    On nv50+, we restrict the valid domains to just the one where the buffer
+    was originally created. However after the buffer is evicted to system
+    memory, we might move it back to a different domain that was not
+    originally valid. When sharing the buffer and retrieving its GEM_INFO
+    data, we still want the domain that will be valid for this buffer in a
+    pushbuf, not the one where it currently happens to be.
+    
+    This resolves fdo#92504 and several others. These are due to suspend
+    evicting all buffers, making it more likely that they temporarily end up
+    in the wrong place.
+    
+    Cc: stable@vger.kernel.org
+    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=92504
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
+index 2c9981512d27..41be584147b9 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
++++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
+@@ -227,11 +227,12 @@ nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem,
+ 	struct nouveau_bo *nvbo = nouveau_gem_object(gem);
+ 	struct nvkm_vma *vma;
+ 
+-	if (nvbo->bo.mem.mem_type == TTM_PL_TT)
++	if (is_power_of_2(nvbo->valid_domains))
++		rep->domain = nvbo->valid_domains;
++	else if (nvbo->bo.mem.mem_type == TTM_PL_TT)
+ 		rep->domain = NOUVEAU_GEM_DOMAIN_GART;
+ 	else
+ 		rep->domain = NOUVEAU_GEM_DOMAIN_VRAM;
+-
+ 	rep->offset = nvbo->bo.offset;
+ 	if (cli->vm) {
+ 		vma = nouveau_bo_vma_find(nvbo, cli->vm);

commit 2a6c521bb41ce862e43db46f52e7681d33e8d771
+Author: Ilia Mirkin 
+Date:   Tue Oct 20 01:15:39 2015 -0400
+
+    drm/nouveau/gem: return only valid domain when there's only one
+    
+    On nv50+, we restrict the valid domains to just the one where the buffer
+    was originally created. However after the buffer is evicted to system
+    memory, we might move it back to a different domain that was not
+    originally valid. When sharing the buffer and retrieving its GEM_INFO
+    data, we still want the domain that will be valid for this buffer in a
+    pushbuf, not the one where it currently happens to be.
+    
+    This resolves fdo#92504 and several others. These are due to suspend
+    evicting all buffers, making it more likely that they temporarily end up
+    in the wrong place.
+    
+    Cc: stable@vger.kernel.org
+    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=92504
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
+index 2c9981512d27..41be584147b9 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
++++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
+@@ -227,11 +227,12 @@ nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem,
+ 	struct nouveau_bo *nvbo = nouveau_gem_object(gem);
+ 	struct nvkm_vma *vma;
+ 
+-	if (nvbo->bo.mem.mem_type == TTM_PL_TT)
++	if (is_power_of_2(nvbo->valid_domains))
++		rep->domain = nvbo->valid_domains;
++	else if (nvbo->bo.mem.mem_type == TTM_PL_TT)
+ 		rep->domain = NOUVEAU_GEM_DOMAIN_GART;
+ 	else
+ 		rep->domain = NOUVEAU_GEM_DOMAIN_VRAM;
+-
+ 	rep->offset = nvbo->bo.offset;
+ 	if (cli->vm) {
+ 		vma = nouveau_bo_vma_find(nvbo, cli->vm);

commit 25d295882a1adfcdaaad85369289677b87c7c8f0
+Author: Ilia Mirkin 
+Date:   Thu Oct 1 23:41:21 2015 -0400
+
+    drm/nouveau/bios: fix OF loading
+    
+    Currently OF bios load fails for a few reasons:
+     - checksum failure
+     - bios size too small
+     - no PCIR header
+     - bios length not a multiple of 4
+    
+    In this change, we resolve all of the above by ignoring any checksum
+    failures (since OF VBIOS tends not to have a checksum), and faking the
+    PCIR data when loading from OF.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h
+index e0ec2a6b7b79..212800ecdce9 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h
+@@ -8,7 +8,10 @@ struct nvbios_source {
+ 	void *(*init)(struct nvkm_bios *, const char *);
+ 	void  (*fini)(void *);
+ 	u32   (*read)(void *, u32 offset, u32 length, struct nvkm_bios *);
++	u32   (*size)(void *);
+ 	bool rw;
++	bool ignore_checksum;
++	bool no_pcir;
+ };
+ 
+ int nvbios_extend(struct nvkm_bios *, u32 length);
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
+index 792f017525f6..b2557e87afdd 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
+@@ -45,7 +45,7 @@ shadow_fetch(struct nvkm_bios *bios, struct shadow *mthd, u32 upto)
+ 		u32 read = mthd->func->read(data, start, limit - start, bios);
+ 		bios->size = start + read;
+ 	}
+-	return bios->size >= limit;
++	return bios->size >= upto;
+ }
+ 
+ static int
+@@ -55,14 +55,22 @@ shadow_image(struct nvkm_bios *bios, int idx, u32 offset, struct shadow *mthd)
+ 	struct nvbios_image image;
+ 	int score = 1;
+ 
+-	if (!shadow_fetch(bios, mthd, offset + 0x1000)) {
+-		nvkm_debug(subdev, "%08x: header fetch failed\n", offset);
+-		return 0;
+-	}
++	if (mthd->func->no_pcir) {
++		image.base = 0;
++		image.type = 0;
++		image.size = mthd->func->size(mthd->data);
++		image.last = 1;
++	} else {
++		if (!shadow_fetch(bios, mthd, offset + 0x1000)) {
++			nvkm_debug(subdev, "%08x: header fetch failed\n",
++				   offset);
++			return 0;
++		}
+ 
+-	if (!nvbios_image(bios, idx, &image)) {
+-		nvkm_debug(subdev, "image %d invalid\n", idx);
+-		return 0;
++		if (!nvbios_image(bios, idx, &image)) {
++			nvkm_debug(subdev, "image %d invalid\n", idx);
++			return 0;
++		}
+ 	}
+ 	nvkm_debug(subdev, "%08x: type %02x, %d bytes\n",
+ 		   image.base, image.type, image.size);
+@@ -74,7 +82,8 @@ shadow_image(struct nvkm_bios *bios, int idx, u32 offset, struct shadow *mthd)
+ 
+ 	switch (image.type) {
+ 	case 0x00:
+-		if (nvbios_checksum(&bios->data[image.base], image.size)) {
++		if (!mthd->func->ignore_checksum &&
++		    nvbios_checksum(&bios->data[image.base], image.size)) {
+ 			nvkm_debug(subdev, "%08x: checksum failed\n",
+ 				   image.base);
+ 			if (mthd->func->rw)
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c
+index bd60d7dd09f5..4bf486b57101 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c
+@@ -21,6 +21,7 @@
+  *
+  */
+ #include "priv.h"
++
+ #include 
+ 
+ #if defined(__powerpc__)
+@@ -33,17 +34,26 @@ static u32
+ of_read(void *data, u32 offset, u32 length, struct nvkm_bios *bios)
+ {
+ 	struct priv *priv = data;
+-	if (offset + length <= priv->size) {
++	if (offset < priv->size) {
++		length = min_t(u32, length, priv->size - offset);
+ 		memcpy_fromio(bios->data + offset, priv->data + offset, length);
+ 		return length;
+ 	}
+ 	return 0;
+ }
+ 
++static u32
++of_size(void *data)
++{
++	struct priv *priv = data;
++	return priv->size;
++}
++
+ static void *
+ of_init(struct nvkm_bios *bios, const char *name)
+ {
+-	struct pci_dev *pdev = bios->subdev.device->func->pci(bios->subdev.device)->pdev;
++	struct nvkm_device *device = bios->subdev.device;
++	struct pci_dev *pdev = device->func->pci(device)->pdev;
+ 	struct device_node *dn;
+ 	struct priv *priv;
+ 	if (!(dn = pci_device_to_OF_node(pdev)))
+@@ -62,7 +72,10 @@ nvbios_of = {
+ 	.init = of_init,
+ 	.fini = (void(*)(void *))kfree,
+ 	.read = of_read,
++	.size = of_size,
+ 	.rw = false,
++	.ignore_checksum = true,
++	.no_pcir = true,
+ };
+ #else
+ const struct nvbios_source

commit 5102ec3e99e271b3934a1e00bb52a2545eb7dbc5
+Author: Ilia Mirkin 
+Date:   Thu Sep 17 22:31:20 2015 -0400
+
+    drm/nouveau/display: allow up to 16k width/height for fermi+
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
+index cc6c228e11c8..e905c00acf1a 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_display.c
++++ b/drivers/gpu/drm/nouveau/nouveau_display.c
+@@ -469,9 +469,13 @@ nouveau_display_create(struct drm_device *dev)
+ 	if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
+ 		dev->mode_config.max_width = 4096;
+ 		dev->mode_config.max_height = 4096;
+-	} else {
++	} else
++	if (drm->device.info.family < NV_DEVICE_INFO_V0_FERMI) {
+ 		dev->mode_config.max_width = 8192;
+ 		dev->mode_config.max_height = 8192;
++	} else {
++		dev->mode_config.max_width = 16384;
++		dev->mode_config.max_height = 16384;
+ 	}
+ 
+ 	dev->mode_config.preferred_depth = 24;

commit 15ee005893c5ac8aabb66c2ad0033ef31dbdcfa3
+Author: Ilia Mirkin 
+Date:   Mon Aug 31 22:50:28 2015 -0400
+
+    drm/nouveau/gr/nv04: fix big endian setting on gr context
+    
+    Broken since "gr: convert user classes to new-style nvkm_object"
+    
+    Tested on a PPC64 G5 + NV34
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c
+index 426ba0025a8d..85c5b7fea5f5 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c
+@@ -1048,11 +1048,11 @@ nv04_gr_object_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent,
+ 	if (ret == 0) {
+ 		nvkm_kmap(*pgpuobj);
+ 		nvkm_wo32(*pgpuobj, 0x00, object->oclass);
+-		nvkm_wo32(*pgpuobj, 0x04, 0x00000000);
+-		nvkm_wo32(*pgpuobj, 0x08, 0x00000000);
+ #ifdef __BIG_ENDIAN
+-		nvkm_mo32(*pgpuobj, 0x08, 0x00080000, 0x00080000);
++		nvkm_mo32(*pgpuobj, 0x00, 0x00080000, 0x00080000);
+ #endif
++		nvkm_wo32(*pgpuobj, 0x04, 0x00000000);
++		nvkm_wo32(*pgpuobj, 0x08, 0x00000000);
+ 		nvkm_wo32(*pgpuobj, 0x0c, 0x00000000);
+ 		nvkm_done(*pgpuobj);
+ 	}

commit 895fb8e6f77589b9c50ff1f231b5025935d1d59f
+Author: Ilia Mirkin 
+Date:   Mon Aug 17 19:37:34 2015 -0400
+
+    drm/nouveau/fb/sddr3: add WR/CWL values seen on a GK208
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c
+index 77c53f9559cd..b4edc97dc8c5 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c
+@@ -53,7 +53,7 @@ static const struct ramxlat
+ ramddr3_wr[] = {
+ 	{ 5, 1 }, { 6, 2 }, { 7, 3 }, { 8, 4 }, { 10, 5 }, { 12, 6 },
+ 	/* the below are mentioned in some, but not all, ddr3 docs */
+-	{ 14, 7 }, { 16, 0 },
++	{ 14, 7 }, { 15, 7 }, { 16, 0 },
+ 	{ -1 }
+ };
+ 
+@@ -61,7 +61,7 @@ static const struct ramxlat
+ ramddr3_cwl[] = {
+ 	{ 5, 0 }, { 6, 1 }, { 7, 2 }, { 8, 3 },
+ 	/* the below are mentioned in some, but not all, ddr3 docs */
+-	{ 9, 4 },
++	{ 9, 4 }, { 10, 5 },
+ 	{ -1 }
+ };
+ 

commit bacbad17fbc636125bf472240860a58a54ad62db
+Author: Ilia Mirkin 
+Date:   Fri Jun 19 02:51:23 2015 -0400
+
+    drm/nouveau/bios: add opcodes 0x73 and 0x77
+    
+    No known VBIOSes use these, but they are present in the actual VBIOS
+    table parsing logic. No harm in adding these too.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
+index f4611e3f0971..8e5f6ce76232 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
+@@ -1741,6 +1741,24 @@ init_resume(struct nvbios_init *init)
+ 	init_exec_set(init, true);
+ }
+ 
++/**
++ * INIT_STRAP_CONDITION - opcode 0x73
++ *
++ */
++static void
++init_strap_condition(struct nvbios_init *init)
++{
++	struct nvkm_bios *bios = init->bios;
++	u32 mask = nv_ro32(bios, init->offset + 1);
++	u32 value = nv_ro32(bios, init->offset + 5);
++
++	trace("STRAP_CONDITION\t(R[0x101000] & 0x%08x) == 0x%08x\n", mask, value);
++	init->offset += 9;
++
++	if ((init_rd32(init, 0x101000) & mask) != value)
++		init_exec_set(init, false);
++}
++
+ /**
+  * INIT_TIME - opcode 0x74
+  *
+@@ -1796,6 +1814,23 @@ init_io_condition(struct nvbios_init *init)
+ 		init_exec_set(init, false);
+ }
+ 
++/**
++ * INIT_ZM_REG16 - opcode 0x77
++ *
++ */
++static void
++init_zm_reg16(struct nvbios_init *init)
++{
++	struct nvkm_bios *bios = init->bios;
++	u32 addr = nv_ro32(bios, init->offset + 1);
++	u16 data = nv_ro16(bios, init->offset + 5);
++
++	trace("ZM_REG\tR[0x%06x] = 0x%04x\n", addr, data);
++	init->offset += 7;
++
++	init_wr32(init, addr, data);
++}
++
+ /**
+  * INIT_INDEX_IO - opcode 0x78
+  *
+@@ -2202,9 +2237,11 @@ static struct nvbios_init_opcode {
+ 	[0x6f] = { init_macro },
+ 	[0x71] = { init_done },
+ 	[0x72] = { init_resume },
++	[0x73] = { init_strap_condition },
+ 	[0x74] = { init_time },
+ 	[0x75] = { init_condition },
+ 	[0x76] = { init_io_condition },
++	[0x77] = { init_zm_reg16 },
+ 	[0x78] = { init_index_io },
+ 	[0x79] = { init_pll },
+ 	[0x7a] = { init_zm_reg },

commit b7eea2d7e67cd4b65f42c00624277dae780f7009
+Author: Ilia Mirkin 
+Date:   Mon Jun 29 20:49:48 2015 -0400
+
+    drm/nouveau/fbcon/g80: reduce PUSH_SPACE alloc, fire ring on accel init
+    
+    Only 58 words get written to the ring, not 59. Also, normalize the accel
+    init wrt nvc0 and nv04 fbcon impls by firing the ring at accel init time
+    rather than waiting until "later".
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c
+index 394c89abcc97..901130b06072 100644
+--- a/drivers/gpu/drm/nouveau/nv50_fbcon.c
++++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c
+@@ -188,7 +188,7 @@ nv50_fbcon_accel_init(struct fb_info *info)
+ 	if (ret)
+ 		return ret;
+ 
+-	ret = RING_SPACE(chan, 59);
++	ret = RING_SPACE(chan, 58);
+ 	if (ret) {
+ 		nouveau_fbcon_gpu_lockup(info);
+ 		return ret;
+@@ -252,6 +252,7 @@ nv50_fbcon_accel_init(struct fb_info *info)
+ 	OUT_RING(chan, info->var.yres_virtual);
+ 	OUT_RING(chan, upper_32_bits(fb->vma.offset));
+ 	OUT_RING(chan, lower_32_bits(fb->vma.offset));
++	FIRE_RING(chan);
+ 
+ 	return 0;
+ }

commit 4fd26cb1e4049c7a630d86d52864a5722c7453ac
+Author: Ilia Mirkin 
+Date:   Mon Jun 29 20:43:46 2015 -0400
+
+    drm/nouveau/fbcon/gf100-: reduce RING_SPACE allocation
+    
+    We only emit 58 words to the ring, not 60.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvc0_fbcon.c b/drivers/gpu/drm/nouveau/nvc0_fbcon.c
+index 61246677e8dc..fcd2e5f27bb9 100644
+--- a/drivers/gpu/drm/nouveau/nvc0_fbcon.c
++++ b/drivers/gpu/drm/nouveau/nvc0_fbcon.c
+@@ -188,7 +188,7 @@ nvc0_fbcon_accel_init(struct fb_info *info)
+ 		return -EINVAL;
+ 	}
+ 
+-	ret = RING_SPACE(chan, 60);
++	ret = RING_SPACE(chan, 58);
+ 	if (ret) {
+ 		WARN_ON(1);
+ 		nouveau_fbcon_gpu_lockup(info);

commit d108142c0840ce389cd9898aa76943b3fb430b83
+Author: Ilia Mirkin 
+Date:   Mon Jun 29 04:07:20 2015 -0400
+
+    drm/nouveau/fbcon/nv11-: correctly account for ring space usage
+    
+    The RING_SPACE macro accounts how much space is used up so it's
+    important to ask it for the right amount. Incorrect accounting of this
+    can cause page faults down the line as writes are attempted outside of
+    the ring.
+    
+    Signed-off-by: Ilia Mirkin 
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c
+index 4ef602c5469d..495c57644ced 100644
+--- a/drivers/gpu/drm/nouveau/nv04_fbcon.c
++++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c
+@@ -203,7 +203,7 @@ nv04_fbcon_accel_init(struct fb_info *info)
+ 	if (ret)
+ 		return ret;
+ 
+-	if (RING_SPACE(chan, 49)) {
++	if (RING_SPACE(chan, 49 + (device->info.chipset >= 0x11 ? 4 : 0))) {
+ 		nouveau_fbcon_gpu_lockup(info);
+ 		return 0;
+ 	}

commit d31b11d85814ff669cfeb93c0f85b9d659a85ef8
+Author: Ilia Mirkin 
+Date:   Fri Jun 19 01:19:40 2015 -0400
+
+    drm/nouveau/bios: add proper support for opcode 0x59
+    
+    More analysis shows that this is identical to 0x79 except that it loads
+    the frequency indirectly from elsewhere in the VBIOS.
+    
+    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=91025
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
+index 1f590f839f76..f4611e3f0971 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
+@@ -577,9 +577,6 @@ init_reserved(struct nvbios_init *init)
+ 	u8 length, i;
+ 
+ 	switch (opcode) {
+-	case 0x59:
+-		length = 7;
+-		break;
+ 	case 0xaa:
+ 		length = 4;
+ 		break;
+@@ -1287,6 +1284,25 @@ init_zm_reg_sequence(struct nvbios_init *init)
+ 	}
+ }
+ 
++/**
++ * INIT_PLL_INDIRECT - opcode 0x59
++ *
++ */
++static void
++init_pll_indirect(struct nvbios_init *init)
++{
++	struct nvkm_bios *bios = init->bios;
++	u32  reg = nv_ro32(bios, init->offset + 1);
++	u16 addr = nv_ro16(bios, init->offset + 5);
++	u32 freq = (u32)nv_ro16(bios, addr) * 1000;
++
++	trace("PLL_INDIRECT\tR[0x%06x] =PLL= VBIOS[%04x] = %dkHz\n",
++	      reg, addr, freq);
++	init->offset += 7;
++
++	init_prog_pll(init, reg, freq);
++}
++
+ /**
+  * INIT_ZM_REG_INDIRECT - opcode 0x5a
+  *
+@@ -2167,7 +2183,7 @@ static struct nvbios_init_opcode {
+ 	[0x56] = { init_condition_time },
+ 	[0x57] = { init_ltime },
+ 	[0x58] = { init_zm_reg_sequence },
+-	[0x59] = { init_reserved },
++	[0x59] = { init_pll_indirect },
+ 	[0x5a] = { init_zm_reg_indirect },
+ 	[0x5b] = { init_sub_direct },
+ 	[0x5c] = { init_jump },

commit 360ccb8436ce83b9c25f969cee7b1b607899063b
+Author: Ilia Mirkin 
+Date:   Thu Jun 18 23:59:06 2015 -0400
+
+    drm/nouveau/bios: add 0x59 and 0x5a opcodes
+    
+    Opcode 0x5a is a register write for data looked up from another part of
+    the VBIOS image. 0x59 is a more complex opcode, but we may as well
+    recognize it. These occur on a single known instance of Riva TNT2
+    hardware.
+    
+    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=91025
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
+index f67cdae1e90a..1f590f839f76 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
+@@ -577,6 +577,9 @@ init_reserved(struct nvbios_init *init)
+ 	u8 length, i;
+ 
+ 	switch (opcode) {
++	case 0x59:
++		length = 7;
++		break;
+ 	case 0xaa:
+ 		length = 4;
+ 		break;
+@@ -1284,6 +1287,25 @@ init_zm_reg_sequence(struct nvbios_init *init)
+ 	}
+ }
+ 
++/**
++ * INIT_ZM_REG_INDIRECT - opcode 0x5a
++ *
++ */
++static void
++init_zm_reg_indirect(struct nvbios_init *init)
++{
++	struct nvkm_bios *bios = init->bios;
++	u32  reg = nv_ro32(bios, init->offset + 1);
++	u16 addr = nv_ro16(bios, init->offset + 5);
++	u32 data = nv_ro32(bios, addr);
++
++	trace("ZM_REG_INDIRECT\tR[0x%06x] = VBIOS[0x%04x] = 0x%08x\n",
++	      reg, addr, data);
++	init->offset += 7;
++
++	init_wr32(init, addr, data);
++}
++
+ /**
+  * INIT_SUB_DIRECT - opcode 0x5b
+  *
+@@ -2145,6 +2167,8 @@ static struct nvbios_init_opcode {
+ 	[0x56] = { init_condition_time },
+ 	[0x57] = { init_ltime },
+ 	[0x58] = { init_zm_reg_sequence },
++	[0x59] = { init_reserved },
++	[0x5a] = { init_zm_reg_indirect },
+ 	[0x5b] = { init_sub_direct },
+ 	[0x5c] = { init_jump },
+ 	[0x5e] = { init_i2c_if },

commit 4761703bd04bbdf56396d264903cc5a1fdcb3c01
+Author: Ilia Mirkin 
+Date:   Tue Dec 16 13:55:38 2014 -0500
+
+    drm/nv4c/mc: disable msi
+    
+    Several users have, over time, reported issues with MSI on these IGPs.
+    They're old, rarely available, and MSI doesn't provide such huge
+    advantages on them. Just disable.
+    
+    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=87361
+    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=74492
+    Fixes: fa8c9ac72fe ("drm/nv4c/mc: nv4x igp's have a different msi rearm register")
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c
+index a75c35ccf25c..165401c4045c 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c
+@@ -24,13 +24,6 @@
+ 
+ #include "nv04.h"
+ 
+-static void
+-nv4c_mc_msi_rearm(struct nouveau_mc *pmc)
+-{
+-	struct nv04_mc_priv *priv = (void *)pmc;
+-	nv_wr08(priv, 0x088050, 0xff);
+-}
+-
+ struct nouveau_oclass *
+ nv4c_mc_oclass = &(struct nouveau_mc_oclass) {
+ 	.base.handle = NV_SUBDEV(MC, 0x4c),
+@@ -41,5 +34,4 @@ nv4c_mc_oclass = &(struct nouveau_mc_oclass) {
+ 		.fini = _nouveau_mc_fini,
+ 	},
+ 	.intr = nv04_mc_intr,
+-	.msi_rearm = nv4c_mc_msi_rearm,
+ }.base;

commit 226d63a1addea8cbe8fc671978e62dc84927b046
+Author: Ilia Mirkin 
+Date:   Sun Nov 30 12:56:18 2014 -0500
+
+    drm/nouveau/gf116: remove copy1 engine
+    
+    Indications are that no GF116's actually have a copy engine there, but
+    actually have the decompression engine. This engine can be made to do
+    copies, but that should be done separately.
+    
+    Unclear why this didn't turn up on all GF116's, but perhaps the
+    non-mobile ones came with enough VRAM to not trigger ttm migrations in
+    test scenarios.
+    
+    Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=85465
+    Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=59168
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
+index cd05677ad4b7..72a40f95d048 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
++++ b/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
+@@ -218,7 +218,6 @@ nvc0_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_ENGINE_BSP    ] = &nvc0_bsp_oclass;
+ 		device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;
+ 		device->oclass[NVDEV_ENGINE_COPY0  ] = &nvc0_copy0_oclass;
+-		device->oclass[NVDEV_ENGINE_COPY1  ] = &nvc0_copy1_oclass;
+ 		device->oclass[NVDEV_ENGINE_DISP   ] =  nva3_disp_oclass;
+ 		device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
+ 		break;

commit 255b329ca7f0e9b5fa6da3a68bb713684fe10305
+Author: Ilia Mirkin 
+Date:   Sat Jun 7 15:39:45 2014 -0400
+
+    drm/gk208/gr: add missing registers to grctx init
+    
+    This fixes hangs on GK208 which happen instantaneously on trying to use a
+    geometry shader.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+    Cc: stable@vger.kernel.org # v3.14+
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c
+index 48351b4d6d6b..8de4a4291548 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c
++++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c
+@@ -545,10 +545,12 @@ nv108_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
+ 	mmio_list(0x408010, 0x80000000,  0, 0);
+ 	mmio_list(0x419004, 0x00000000,  8, 1);
+ 	mmio_list(0x419008, 0x00000000,  0, 0);
++	mmio_list(0x4064cc, 0x80000000,  0, 0);
+ 	mmio_list(0x408004, 0x00000000,  8, 0);
+ 	mmio_list(0x408008, 0x80000030,  0, 0);
+ 	mmio_list(0x418808, 0x00000000,  8, 0);
+ 	mmio_list(0x41880c, 0x80000030,  0, 0);
++	mmio_list(0x4064c8, 0x00c20200,  0, 0);
+ 	mmio_list(0x418810, 0x80000000, 12, 2);
+ 	mmio_list(0x419848, 0x10000000, 12, 2);
+ 

commit ed05ba72c841d330cef111282d76a5c7881940f5
+Author: Ilia Mirkin 
+Date:   Sun May 18 01:04:16 2014 -0400
+
+    drm/nouveau/clk: allow end-user reclocking for nv40, nvaa, and nve0 clock types
+    
+    Use with caution.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/clock.h b/drivers/gpu/drm/nouveau/core/include/subdev/clock.h
+index 8f4ced75444a..c01e29c9f89a 100644
+--- a/drivers/gpu/drm/nouveau/core/include/subdev/clock.h
++++ b/drivers/gpu/drm/nouveau/core/include/subdev/clock.h
+@@ -77,6 +77,8 @@ struct nouveau_clock {
+ 	int tstate; /* thermal adjustment (max-) */
+ 	int dstate; /* display adjustment (min+) */
+ 
++	bool allow_reclock;
++
+ 	int  (*read)(struct nouveau_clock *, enum nv_clk_src);
+ 	int  (*calc)(struct nouveau_clock *, struct nouveau_cstate *);
+ 	int  (*prog)(struct nouveau_clock *);
+@@ -106,8 +108,8 @@ struct nouveau_clocks {
+ 	int mdiv;
+ };
+ 
+-#define nouveau_clock_create(p,e,o,i,d)                                        \
+-	nouveau_clock_create_((p), (e), (o), (i), sizeof(**d), (void **)d)
++#define nouveau_clock_create(p,e,o,i,r,d)                                      \
++	nouveau_clock_create_((p), (e), (o), (i), (r), sizeof(**d), (void **)d)
+ #define nouveau_clock_destroy(p) ({                                            \
+ 	struct nouveau_clock *clk = (p);                                       \
+ 	_nouveau_clock_dtor(nv_object(clk));                                   \
+@@ -121,7 +123,7 @@ struct nouveau_clocks {
+ 
+ int  nouveau_clock_create_(struct nouveau_object *, struct nouveau_object *,
+ 			   struct nouveau_oclass *,
+-			   struct nouveau_clocks *, int, void **);
++			   struct nouveau_clocks *, bool, int, void **);
+ void _nouveau_clock_dtor(struct nouveau_object *);
+ int _nouveau_clock_init(struct nouveau_object *);
+ #define _nouveau_clock_fini _nouveau_subdev_fini
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/base.c b/drivers/gpu/drm/nouveau/core/subdev/clock/base.c
+index dd62baead39c..22351f594d2a 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/clock/base.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/clock/base.c
+@@ -346,8 +346,8 @@ nouveau_clock_ustate_update(struct nouveau_clock *clk, int req)
+ 	struct nouveau_pstate *pstate;
+ 	int i = 0;
+ 
+-	/* YKW repellant */
+-	return -ENOSYS;
++	if (!clk->allow_reclock)
++		return -ENOSYS;
+ 
+ 	if (req != -1 && req != -2) {
+ 		list_for_each_entry(pstate, &clk->states, head) {
+@@ -456,6 +456,7 @@ nouveau_clock_create_(struct nouveau_object *parent,
+ 		      struct nouveau_object *engine,
+ 		      struct nouveau_oclass *oclass,
+ 		      struct nouveau_clocks *clocks,
++		      bool allow_reclock,
+ 		      int length, void **object)
+ {
+ 	struct nouveau_device *device = nv_device(parent);
+@@ -478,6 +479,8 @@ nouveau_clock_create_(struct nouveau_object *parent,
+ 		ret = nouveau_pstate_new(clk, idx++);
+ 	} while (ret == 0);
+ 
++	clk->allow_reclock = allow_reclock;
++
+ 	mode = nouveau_stropt(device->cfgopt, "NvClkMode", &arglen);
+ 	if (mode) {
+ 		if (!strncasecmpz(mode, "disabled", arglen)) {
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c
+index b74db6cfc4e2..eb2d4425a49e 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c
+@@ -82,7 +82,8 @@ nv04_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	struct nv04_clock_priv *priv;
+ 	int ret;
+ 
+-	ret = nouveau_clock_create(parent, engine, oclass, nv04_domain, &priv);
++	ret = nouveau_clock_create(parent, engine, oclass, nv04_domain, false,
++				   &priv);
+ 	*pobject = nv_object(priv);
+ 	if (ret)
+ 		return ret;
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c
+index db7346f79080..8a9e16839791 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c
+@@ -213,7 +213,8 @@ nv40_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	struct nv40_clock_priv *priv;
+ 	int ret;
+ 
+-	ret = nouveau_clock_create(parent, engine, oclass, nv40_domain, &priv);
++	ret = nouveau_clock_create(parent, engine, oclass, nv40_domain, true,
++				   &priv);
+ 	*pobject = nv_object(priv);
+ 	if (ret)
+ 		return ret;
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c
+index 250a6d96016b..8c132772ba9e 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c
+@@ -507,7 +507,7 @@ nv50_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	int ret;
+ 
+ 	ret = nouveau_clock_create(parent, engine, oclass, pclass->domains,
+-				  &priv);
++				   false, &priv);
+ 	*pobject = nv_object(priv);
+ 	if (ret)
+ 		return ret;
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
+index 4f5a1373f002..9fb58354a80b 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
+@@ -302,7 +302,8 @@ nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	struct nva3_clock_priv *priv;
+ 	int ret;
+ 
+-	ret = nouveau_clock_create(parent, engine, oclass, nva3_domain, &priv);
++	ret = nouveau_clock_create(parent, engine, oclass, nva3_domain, false,
++				   &priv);
+ 	*pobject = nv_object(priv);
+ 	if (ret)
+ 		return ret;
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c
+index 7a723b4f564d..6a65fc9e9663 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c
+@@ -421,7 +421,8 @@ nvaa_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	struct nvaa_clock_priv *priv;
+ 	int ret;
+ 
+-	ret = nouveau_clock_create(parent, engine, oclass, nvaa_domains, &priv);
++	ret = nouveau_clock_create(parent, engine, oclass, nvaa_domains, true,
++				   &priv);
+ 	*pobject = nv_object(priv);
+ 	if (ret)
+ 		return ret;
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c
+index c3105720ed24..dbf8517f54da 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c
+@@ -437,7 +437,8 @@ nvc0_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	struct nvc0_clock_priv *priv;
+ 	int ret;
+ 
+-	ret = nouveau_clock_create(parent, engine, oclass, nvc0_domain, &priv);
++	ret = nouveau_clock_create(parent, engine, oclass, nvc0_domain, false,
++				   &priv);
+ 	*pobject = nv_object(priv);
+ 	if (ret)
+ 		return ret;
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c
+index d3c37c96f0e7..4ac1aa30ea11 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c
+@@ -473,7 +473,8 @@ nve0_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	struct nve0_clock_priv *priv;
+ 	int ret;
+ 
+-	ret = nouveau_clock_create(parent, engine, oclass, nve0_domain, &priv);
++	ret = nouveau_clock_create(parent, engine, oclass, nve0_domain, true,
++				   &priv);
+ 	*pobject = nv_object(priv);
+ 	if (ret)
+ 		return ret;

commit d2ed15b2314fc4954b5d4bc36d3230f7e73865a2
+Author: Ilia Mirkin 
+Date:   Sun May 18 01:04:15 2014 -0400
+
+    drm/nouveau/fb: default NvMemExec to on, turning it off is used for debugging only
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c
+index ef91b6e893af..e5d12c24cc43 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c
+@@ -211,7 +211,7 @@ nv50_ram_prog(struct nouveau_fb *pfb)
+ 	struct nv50_ram *ram = (void *)pfb->ram;
+ 	struct nv50_ramseq *hwsq = &ram->hwsq;
+ 
+-	ram_exec(hwsq, nouveau_boolopt(device->cfgopt, "NvMemExec", false));
++	ram_exec(hwsq, nouveau_boolopt(device->cfgopt, "NvMemExec", true));
+ 	return 0;
+ }
+ 
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c
+index 6eb97f16fbda..8076fb195dd5 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c
+@@ -309,7 +309,7 @@ nva3_ram_prog(struct nouveau_fb *pfb)
+ 	struct nouveau_device *device = nv_device(pfb);
+ 	struct nva3_ram *ram = (void *)pfb->ram;
+ 	struct nva3_ramfuc *fuc = &ram->fuc;
+-	ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", false));
++	ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", true));
+ 	return 0;
+ }
+ 
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
+index 8edc92224c84..5a6a5027f749 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
+@@ -408,7 +408,7 @@ nvc0_ram_prog(struct nouveau_fb *pfb)
+ 	struct nouveau_device *device = nv_device(pfb);
+ 	struct nvc0_ram *ram = (void *)pfb->ram;
+ 	struct nvc0_ramfuc *fuc = &ram->fuc;
+-	ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", false));
++	ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", true));
+ 	return 0;
+ }
+ 
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c
+index 16752192cf87..84c7efbc4f38 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c
+@@ -1111,7 +1111,7 @@ nve0_ram_prog(struct nouveau_fb *pfb)
+ 	struct nouveau_device *device = nv_device(pfb);
+ 	struct nve0_ram *ram = (void *)pfb->ram;
+ 	struct nve0_ramfuc *fuc = &ram->fuc;
+-	ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", false));
++	ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", true));
+ 	return (ram->base.next == &ram->base.xition);
+ }
+ 

commit a3d0b1218d351c6e6f3cea36abe22236a08cb246
+Author: Ilia Mirkin 
+Date:   Wed Mar 26 19:37:21 2014 -0400
+
+    drm/nouveau/acpi: allow non-optimus setups to load vbios from acpi
+    
+    There appear to be a crop of new hardware where the vbios is not
+    available from PROM/PRAMIN, but there is a valid _ROM method in ACPI.
+    The data read from PCIROM almost invariably contains invalid
+    instructions (still has the x86 opcodes), which makes this a low-risk
+    way to try to obtain a valid vbios image.
+    
+    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=76475
+    Signed-off-by: Ilia Mirkin 
+    Cc:  # v2.6.35+
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c
+index 83face3f608f..279206997e5c 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_acpi.c
++++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c
+@@ -389,9 +389,6 @@ bool nouveau_acpi_rom_supported(struct pci_dev *pdev)
+ 	acpi_status status;
+ 	acpi_handle dhandle, rom_handle;
+ 
+-	if (!nouveau_dsm_priv.dsm_detected && !nouveau_dsm_priv.optimus_detected)
+-		return false;
+-
+ 	dhandle = ACPI_HANDLE(&pdev->dev);
+ 	if (!dhandle)
+ 		return false;

commit 0d82674b811084110bd80dd260d477a5a0b85d79
+Author: Ilia Mirkin 
+Date:   Thu Dec 5 21:13:25 2013 -0500
+
+    hexagon: correct type on pgd copy
+    
+    swapper_pg_dir is an array of pgd_t, not pgd_t*. This has no actual
+    effect since sizeof(pgd_t) == sizeof(pgd_t*), but unconfuses tools that
+    check types.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Richard Kuo 
+
+diff --git a/arch/hexagon/include/asm/pgalloc.h b/arch/hexagon/include/asm/pgalloc.h
+index 4c9d382d7798..77da3b0ae3c2 100644
+--- a/arch/hexagon/include/asm/pgalloc.h
++++ b/arch/hexagon/include/asm/pgalloc.h
+@@ -45,7 +45,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+ 	 * map with a copy of the kernel's persistent map.
+ 	 */
+ 
+-	memcpy(pgd, swapper_pg_dir, PTRS_PER_PGD*sizeof(pgd_t *));
++	memcpy(pgd, swapper_pg_dir, PTRS_PER_PGD*sizeof(pgd_t));
+ 	mm->context.generation = kmap_generation;
+ 
+ 	/* Physical version is what is passed to virtual machine on switch */

commit cbc53c167921a5c86ab8fcbf41c101da741dab7d
+Author: Ilia Mirkin 
+Date:   Wed Mar 19 10:45:55 2014 -0400
+
+    drm/nouveau/disp/dp: allow 540MHz data rate
+    
+    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=76319
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/dport.c b/drivers/gpu/drm/nouveau/core/engine/disp/dport.c
+index 2aedb4e47d03..3ca2d25b7f5e 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/disp/dport.c
++++ b/drivers/gpu/drm/nouveau/core/engine/disp/dport.c
+@@ -273,7 +273,7 @@ nouveau_dp_train(struct nouveau_disp *disp, const struct nouveau_dp_func *func,
+ 		.outp = outp,
+ 		.head = head,
+ 	}, *dp = &_dp;
+-	const u32 bw_list[] = { 270000, 162000, 0 };
++	const u32 bw_list[] = { 540000, 270000, 162000, 0 };
+ 	const u32 *link_bw = bw_list;
+ 	u8  hdr, cnt, len;
+ 	u32 data;

commit 8db3a740b08a90888e02fd39c831e366a83abc43
+Author: Ilia Mirkin 
+Date:   Sun Feb 16 03:53:55 2014 -0500
+
+    drm/nouveau/bios: fix INDEX_ADDRESS_LATCHED trace printout
+    
+    Having a \n in the middle of a format string means that the next line
+    doesn't get the prefixes unlike every other line printed by the trace.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
+index de201baeb053..126651b344d4 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
+@@ -845,9 +845,8 @@ init_idx_addr_latched(struct nvbios_init *init)
+ 	u32 data = nv_ro32(bios, init->offset + 13);
+ 	u8 count = nv_ro08(bios, init->offset + 17);
+ 
+-	trace("INDEX_ADDRESS_LATCHED\t"
+-	      "R[0x%06x] : R[0x%06x]\n\tCTRL &= 0x%08x |= 0x%08x\n",
+-	      creg, dreg, mask, data);
++	trace("INDEX_ADDRESS_LATCHED\tR[0x%06x] : R[0x%06x]\n", creg, dreg);
++	trace("\tCTRL &= 0x%08x |= 0x%08x\n", mask, data);
+ 	init->offset += 18;
+ 
+ 	while (count--) {

commit 46a7b62596691d7eabb0b24ad28af7097eb66793
+Author: Ilia Mirkin 
+Date:   Fri Feb 14 14:28:36 2014 -0500
+
+    drm/nv50/gr: decode texture trap status code
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
+index ef3832002cc1..2c7809e1a09b 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
++++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
+@@ -330,6 +330,15 @@ static const struct nouveau_bitfield nv50_mpc_traps[] = {
+ 	{}
+ };
+ 
++static const struct nouveau_bitfield nv50_tex_traps[] = {
++	{ 0x00000001, "" }, /* any bit set? */
++	{ 0x00000002, "FAULT" },
++	{ 0x00000004, "STORAGE_TYPE_MISMATCH" },
++	{ 0x00000008, "LINEAR_MISMATCH" },
++	{ 0x00000020, "WRONG_MEMTYPE" },
++	{}
++};
++
+ static const struct nouveau_bitfield nv50_graph_trap_m2mf[] = {
+ 	{ 0x00000001, "NOTIFY" },
+ 	{ 0x00000002, "IN" },
+@@ -532,6 +541,13 @@ nv50_priv_tp_trap(struct nv50_graph_priv *priv, int type, u32 ustatus_old,
+ 				for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4)
+ 					nv_error(priv, "\t0x%08x: 0x%08x\n", r,
+ 						nv_rd32(priv, r));
++				if (ustatus) {
++					nv_error(priv, "%s - TP%d:", name, i);
++					nouveau_bitfield_print(nv50_tex_traps,
++							       ustatus);
++					pr_cont("\n");
++					ustatus = 0;
++				}
+ 			}
+ 			break;
+ 		case 7: /* MP error */

commit c33e05a1369262ce7930e536af1e049646275198
+Author: Ilia Mirkin 
+Date:   Thu Feb 13 21:35:14 2014 -0500
+
+    drm/nouveau: use nv_debug for NV_DEBUG, make DRM a separate subflag
+    
+    It's really confusing for NV_DEBUG's printing to be controlled via
+    drm.debug while everything else is controlled via nouveau.debug. These
+    messages can be turned on with nouveau.debug=DRM=debug.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
+index 0f67e194df5f..eeadcac8e8f4 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
++++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
+@@ -33,6 +33,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ #include 
+@@ -335,6 +336,7 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
+ 
+ 	dev->dev_private = drm;
+ 	drm->dev = dev;
++	nouveau_client(drm)->debug = nouveau_dbgopt(nouveau_debug, "DRM");
+ 
+ 	INIT_LIST_HEAD(&drm->clients);
+ 	spin_lock_init(&drm->tile.lock);
+diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h
+index 23ca7a517246..7efbafaf7c1d 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_drm.h
++++ b/drivers/gpu/drm/nouveau/nouveau_drm.h
+@@ -161,10 +161,7 @@ int nouveau_pmops_resume(struct device *);
+ #define NV_ERROR(cli, fmt, args...) nv_error((cli), fmt, ##args)
+ #define NV_WARN(cli, fmt, args...) nv_warn((cli), fmt, ##args)
+ #define NV_INFO(cli, fmt, args...) nv_info((cli), fmt, ##args)
+-#define NV_DEBUG(cli, fmt, args...) do {                                       \
+-	if (drm_debug & DRM_UT_DRIVER)                                         \
+-		nv_info((cli), fmt, ##args);                                   \
+-} while (0)
++#define NV_DEBUG(cli, fmt, args...) nv_debug((cli), fmt, ##args)
+ 
+ extern int nouveau_modeset;
+ 

commit 46941b0fb6e398e0966f1694f6463dc417af95a6
+Author: Ilia Mirkin 
+Date:   Thu Feb 13 03:39:50 2014 -0500
+
+    drm/nouveau: make hdmi device finding failure prints debug level
+    
+    The hdmi device is required for runtime pm. However it is not available
+    on many esp older devices, which were all seeing these error messages.
+    Take this opportunity to also convert to nv_debug instead of the DRM_*
+    messages, like the rest of nouveau does.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
+index a9f4a8b6e95c..0f67e194df5f 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
++++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
+@@ -300,22 +300,21 @@ static int nouveau_drm_probe(struct pci_dev *pdev,
+ #define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403
+ 
+ static void
+-nouveau_get_hdmi_dev(struct drm_device *dev)
++nouveau_get_hdmi_dev(struct nouveau_drm *drm)
+ {
+-	struct nouveau_drm *drm = dev->dev_private;
+-	struct pci_dev *pdev = dev->pdev;
++	struct pci_dev *pdev = drm->dev->pdev;
+ 
+ 	/* subfunction one is a hdmi audio device? */
+ 	drm->hdmi_device = pci_get_bus_and_slot((unsigned int)pdev->bus->number,
+ 						PCI_DEVFN(PCI_SLOT(pdev->devfn), 1));
+ 
+ 	if (!drm->hdmi_device) {
+-		DRM_INFO("hdmi device  not found %d %d %d\n", pdev->bus->number, PCI_SLOT(pdev->devfn), 1);
++		NV_DEBUG(drm, "hdmi device not found %d %d %d\n", pdev->bus->number, PCI_SLOT(pdev->devfn), 1);
+ 		return;
+ 	}
+ 
+ 	if ((drm->hdmi_device->class >> 8) != PCI_CLASS_MULTIMEDIA_HD_AUDIO) {
+-		DRM_INFO("possible hdmi device  not audio %d\n", drm->hdmi_device->class);
++		NV_DEBUG(drm, "possible hdmi device not audio %d\n", drm->hdmi_device->class);
+ 		pci_dev_put(drm->hdmi_device);
+ 		drm->hdmi_device = NULL;
+ 		return;
+@@ -340,7 +339,7 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
+ 	INIT_LIST_HEAD(&drm->clients);
+ 	spin_lock_init(&drm->tile.lock);
+ 
+-	nouveau_get_hdmi_dev(dev);
++	nouveau_get_hdmi_dev(drm);
+ 
+ 	/* make sure AGP controller is in a consistent state before we
+ 	 * (possibly) execute vbios init tables (see nouveau_agp.h)

commit ef98c1f7b37116ae45d892a23f46cffdda31773c
+Author: Ilia Mirkin 
+Date:   Sun Feb 9 15:51:25 2014 -0500
+
+    drm/nouveau/abi16: fix handles past the 32nd one
+    
+    abi16->handles is a u64, so make sure to use 1ULL << val when modifying.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c
+index b70111711be3..66abf4d6e575 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_abi16.c
++++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c
+@@ -139,7 +139,7 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16,
+ 
+ 	/* destroy channel object, all children will be killed too */
+ 	if (chan->chan) {
+-		abi16->handles &= ~(1 << (chan->chan->handle & 0xffff));
++		abi16->handles &= ~(1ULL << (chan->chan->handle & 0xffff));
+ 		nouveau_channel_del(&chan->chan);
+ 	}
+ 
+@@ -280,7 +280,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
+ 
+ 	INIT_LIST_HEAD(&chan->notifiers);
+ 	list_add(&chan->head, &abi16->channels);
+-	abi16->handles |= (1 << init->channel);
++	abi16->handles |= (1ULL << init->channel);
+ 
+ 	/* create channel object and initialise dma and fence management */
+ 	ret = nouveau_channel_new(drm, cli, NVDRM_DEVICE, NVDRM_CHAN |

commit 73970c47beb42f3e1ab0b86c537b1c79539f05f4
+Author: Ilia Mirkin 
+Date:   Sun Feb 9 15:51:24 2014 -0500
+
+    drm/nouveau: replace ffsll with __ffs64
+    
+    The ffsll function is a lot slower than the __ffs64 built-in which
+    compiles to a single instruction on 64-bit. It's also nice to avoid
+    custom versions of standard functions. Note that __ffs == ffs - 1.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/core/parent.c b/drivers/gpu/drm/nouveau/core/core/parent.c
+index 313380ce632d..dee5d1235e9b 100644
+--- a/drivers/gpu/drm/nouveau/core/core/parent.c
++++ b/drivers/gpu/drm/nouveau/core/core/parent.c
+@@ -49,7 +49,7 @@ nouveau_parent_sclass(struct nouveau_object *parent, u16 handle,
+ 
+ 	mask = nv_parent(parent)->engine;
+ 	while (mask) {
+-		int i = ffsll(mask) - 1;
++		int i = __ffs64(mask);
+ 
+ 		if (nv_iclass(parent, NV_CLIENT_CLASS))
+ 			engine = nv_engine(nv_client(parent)->device);
+diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c
+index 900fae01793e..b70111711be3 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_abi16.c
++++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c
+@@ -270,8 +270,8 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
+ 		return nouveau_abi16_put(abi16, -EINVAL);
+ 
+ 	/* allocate "abi16 channel" data and make up a handle for it */
+-	init->channel = ffsll(~abi16->handles);
+-	if (!init->channel--)
++	init->channel = __ffs64(~abi16->handles);
++	if (~abi16->handles == 0)
+ 		return nouveau_abi16_put(abi16, -ENOSPC);
+ 
+ 	chan = kzalloc(sizeof(*chan), GFP_KERNEL);

commit 4ac1b1a29f5d73aad47dfecc3e66577e8b79ad5a
+Author: Ilia Mirkin 
+Date:   Tue Feb 4 20:38:17 2014 -0500
+
+    drm/nv50/graph: update status enum names
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
+index 7a367c402978..ef3832002cc1 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
++++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
+@@ -197,34 +197,35 @@ static const struct nouveau_bitfield nv50_pgraph_status[] = {
+ 	{ 0x00000080, "UNK7" },
+ 	{ 0x00000100, "CTXPROG" },
+ 	{ 0x00000200, "VFETCH" },
+-	{ 0x00000400, "CCACHE_UNK4" },
+-	{ 0x00000800, "STRMOUT_GSCHED_UNK5" },
+-	{ 0x00001000, "UNK14XX" },
+-	{ 0x00002000, "UNK24XX_CSCHED" },
+-	{ 0x00004000, "UNK1CXX" },
++	{ 0x00000400, "CCACHE_PREGEOM" },
++	{ 0x00000800, "STRMOUT_VATTR_POSTGEOM" },
++	{ 0x00001000, "VCLIP" },
++	{ 0x00002000, "RATTR_APLANE" },
++	{ 0x00004000, "TRAST" },
+ 	{ 0x00008000, "CLIPID" },
+ 	{ 0x00010000, "ZCULL" },
+ 	{ 0x00020000, "ENG2D" },
+-	{ 0x00040000, "UNK34XX" },
+-	{ 0x00080000, "TPRAST" },
+-	{ 0x00100000, "TPROP" },
+-	{ 0x00200000, "TEX" },
+-	{ 0x00400000, "TPVP" },
+-	{ 0x00800000, "MP" },
++	{ 0x00040000, "RMASK" },
++	{ 0x00080000, "TPC_RAST" },
++	{ 0x00100000, "TPC_PROP" },
++	{ 0x00200000, "TPC_TEX" },
++	{ 0x00400000, "TPC_GEOM" },
++	{ 0x00800000, "TPC_MP" },
+ 	{ 0x01000000, "ROP" },
+ 	{}
+ };
+ 
+ static const char *const nv50_pgraph_vstatus_0[] = {
+-	"VFETCH", "CCACHE", "UNK4", "UNK5", "GSCHED", "STRMOUT", "UNK14XX", NULL
++	"VFETCH", "CCACHE", "PREGEOM", "POSTGEOM", "VATTR", "STRMOUT", "VCLIP",
++	NULL
+ };
+ 
+ static const char *const nv50_pgraph_vstatus_1[] = {
+-	"TPRAST", "TPROP", "TEXTURE", "TPVP", "MP", NULL
++	"TPC_RAST", "TPC_PROP", "TPC_TEX", "TPC_GEOM", "TPC_MP", NULL
+ };
+ 
+ static const char *const nv50_pgraph_vstatus_2[] = {
+-	"UNK24XX", "CSCHED", "UNK1CXX", "CLIPID", "ZCULL", "ENG2D", "UNK34XX",
++	"RATTR", "APLANE", "TRAST", "CLIPID", "ZCULL", "ENG2D", "RMASK",
+ 	"ROP", NULL
+ };
+ 

commit 6843bc3c568128e8771ba35cfefe95b7ec1c93a8
+Author: Ilia Mirkin 
+Date:   Wed Mar 5 07:55:10 2014 +0100
+
+    netfilter: ipset: move registration message to init from net_init
+    
+    Commit 1785e8f473 ("netfiler: ipset: Add net namespace for ipset") moved
+    the initialization print into net_init, which can get called a lot due
+    to namespaces. Move it back into init, reduce to pr_info.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Jozsef Kadlecsik 
+
+diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
+index c6c97b8b31ac..636cb8df5354 100644
+--- a/net/netfilter/ipset/ip_set_core.c
++++ b/net/netfilter/ipset/ip_set_core.c
+@@ -1945,7 +1945,6 @@ ip_set_net_init(struct net *net)
+ 		return -ENOMEM;
+ 	inst->is_deleted = 0;
+ 	rcu_assign_pointer(inst->ip_set_list, list);
+-	pr_notice("ip_set: protocol %u\n", IPSET_PROTOCOL);
+ 	return 0;
+ }
+ 
+@@ -1996,6 +1995,7 @@ ip_set_init(void)
+ 		nfnetlink_subsys_unregister(&ip_set_netlink_subsys);
+ 		return ret;
+ 	}
++	pr_info("ip_set: protocol %u\n", IPSET_PROTOCOL);
+ 	return 0;
+ }
+ 

commit 34d595081812da62b5357579267c4ab5eae64ac1
+Author: Ilia Mirkin 
+Date:   Sat Feb 15 23:27:01 2014 -0500
+
+    drm/nouveau: fix TTM_PL_TT memtype on pre-nv50
+    
+    Commit a55409066 ("drm/nv50-: map TTM_PL_SYSTEM through a BAR for CPU
+    access") made it possible to work with tiled memory. However
+    mem->mm_node is not a nouveau_mem for AGP-using pre-NV50 cards, but a
+    drm_mm_node, as created by the ttm_bo_manager_func. As such, extend the
+    untiled check to explicitly include all pre-nv50 cards.
+    
+    Reported-by: Ronald 
+    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=74613
+    Signed-off-by: Ilia Mirkin 
+    Tested-by: Ronald Uitermark 
+    Acked-by: Maarten Lankhorst 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
+index 488686d490c0..4aed1714b9ab 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
++++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
+@@ -1249,7 +1249,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
+ 			mem->bus.is_iomem = !dev->agp->cant_use_aperture;
+ 		}
+ #endif
+-		if (!node->memtype)
++		if (nv_device(drm->device)->card_type < NV_50 || !node->memtype)
+ 			/* untiled */
+ 			break;
+ 		/* fallthrough, tiled memory */

commit a7f1c1e65b68e1e1ab70898528d5977ed68a0a7d
+Author: Ilia Mirkin 
+Date:   Thu Feb 13 21:57:15 2014 -0500
+
+    drm/nv50/disp: use correct register to determine DP display bpp
+    
+    Commit 0a0afd282f ("drm/nv50-/disp: move DP link training to core and
+    train from supervisor") added code that uses the wrong register for
+    computing the display bpp, used for bandwidth calculation. Adjust to use
+    the same register as used by exec_clkcmp and nv50_disp_intr_unk20_2_dp.
+    
+    Reported-by: Torsten Wagner 
+    Reported-by: Michael Gulick 
+    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=67628
+    Cc: stable@vger.kernel.org # 3.9+
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
+index 940eaa5d8b9a..9ad722e4e087 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
++++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
+@@ -1142,7 +1142,7 @@ nv50_disp_intr_unk20_2(struct nv50_disp_priv *priv, int head)
+ 	if (conf != ~0) {
+ 		if (outp.location == 0 && outp.type == DCB_OUTPUT_DP) {
+ 			u32 soff = (ffs(outp.or) - 1) * 0x08;
+-			u32 ctrl = nv_rd32(priv, 0x610798 + soff);
++			u32 ctrl = nv_rd32(priv, 0x610794 + soff);
+ 			u32 datarate;
+ 
+ 			switch ((ctrl & 0x000f0000) >> 16) {

commit a8c13aacdc20268ced05c9bb065c5d219840205e
+Author: Ilia Mirkin 
+Date:   Sat Feb 8 22:35:13 2014 -0500
+
+    drm/nv50/gr: add missing nv_error parameter priv
+    
+    Commit ea7dce901 ("drm/nv50/gr: print mpc trap name when it's not an mp
+    trap") added an nv_error call that was missing the priv parameter. This
+    causes GPFs if the error is ever hit.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
+index 30ed19c52e05..7a367c402978 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
++++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
+@@ -539,7 +539,7 @@ nv50_priv_tp_trap(struct nv50_graph_priv *priv, int type, u32 ustatus_old,
+ 				ustatus &= ~0x04030000;
+ 			}
+ 			if (ustatus && display) {
+-				nv_error("%s - TP%d:", name, i);
++				nv_error(priv, "%s - TP%d:", name, i);
+ 				nouveau_bitfield_print(nv50_mpc_traps, ustatus);
+ 				pr_cont("\n");
+ 				ustatus = 0;

commit 5ac607ec4006d61c425c7846f29de8a9d8ce4f9f
+Author: Ilia Mirkin 
+Date:   Wed Feb 5 14:33:04 2014 -0500
+
+    drm/nv4c/bios: disallow retrieving from prom on nv4x igp's
+    
+    Suggested-by: Marcin Kościelnicki 
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c
+index aa0fbbec7f08..ef0c9c4a8cc3 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c
+@@ -130,6 +130,10 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios)
+ 	u16 pcir;
+ 	int i;
+ 
++	/* there is no prom on nv4x IGP's */
++	if (device->card_type == NV_40 && device->chipset >= 0x4c)
++		return;
++
+ 	/* enable access to rom */
+ 	if (device->card_type >= NV_50)
+ 		pcireg = 0x088050;

commit b71313e14bbc0b8fc25eeff53828ab8e2aee4f25
+Author: Ilia Mirkin 
+Date:   Wed Feb 5 14:33:03 2014 -0500
+
+    drm/nv4c/vga: decode register is in a different place on nv4x igp's
+    
+    Suggested-by: Marcin Kościelnicki 
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c
+index 81638d7f2eff..471347edc27e 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_vga.c
++++ b/drivers/gpu/drm/nouveau/nouveau_vga.c
+@@ -14,7 +14,9 @@ nouveau_vga_set_decode(void *priv, bool state)
+ {
+ 	struct nouveau_device *device = nouveau_dev(priv);
+ 
+-	if (device->chipset >= 0x40)
++	if (device->card_type == NV_40 && device->chipset >= 0x4c)
++		nv_wr32(device, 0x088060, state);
++	else if (device->chipset >= 0x40)
+ 		nv_wr32(device, 0x088054, state);
+ 	else
+ 		nv_wr32(device, 0x001854, state);

commit fa8c9ac72fe0bcdf5bc7cc84e85cc2a1af53f9fd
+Author: Ilia Mirkin 
+Date:   Wed Feb 5 14:33:02 2014 -0500
+
+    drm/nv4c/mc: nv4x igp's have a different msi rearm register
+    
+    See https://bugs.freedesktop.org/show_bug.cgi?id=74492
+    
+    Reported-by: Ronald 
+    Suggested-by: Marcin Kościelnicki 
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile
+index e88145ba1bf5..d310c195bdfe 100644
+--- a/drivers/gpu/drm/nouveau/Makefile
++++ b/drivers/gpu/drm/nouveau/Makefile
+@@ -141,6 +141,7 @@ nouveau-y += core/subdev/mc/base.o
+ nouveau-y += core/subdev/mc/nv04.o
+ nouveau-y += core/subdev/mc/nv40.o
+ nouveau-y += core/subdev/mc/nv44.o
++nouveau-y += core/subdev/mc/nv4c.o
+ nouveau-y += core/subdev/mc/nv50.o
+ nouveau-y += core/subdev/mc/nv94.o
+ nouveau-y += core/subdev/mc/nv98.o
+diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv40.c b/drivers/gpu/drm/nouveau/core/engine/device/nv40.c
+index 1b653dd74a70..08b88591ed60 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/device/nv40.c
++++ b/drivers/gpu/drm/nouveau/core/engine/device/nv40.c
+@@ -311,7 +311,7 @@ nv40_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
+ 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
+ 		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
+-		device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
++		device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
+ 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
+ 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
+ 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
+@@ -334,7 +334,7 @@ nv40_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
+ 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
+ 		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
+-		device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
++		device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
+ 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
+ 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
+ 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv4e_fb_oclass;
+@@ -357,7 +357,7 @@ nv40_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
+ 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
+ 		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
+-		device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
++		device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
+ 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
+ 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
+ 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
+@@ -380,7 +380,7 @@ nv40_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
+ 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
+ 		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
+-		device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
++		device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
+ 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
+ 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
+ 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
+@@ -403,7 +403,7 @@ nv40_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
+ 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
+ 		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
+-		device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
++		device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
+ 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
+ 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
+ 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
+diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h
+index adc88b73d911..3c6738edd127 100644
+--- a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h
++++ b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h
+@@ -47,6 +47,7 @@ struct nouveau_mc_oclass {
+ extern struct nouveau_oclass *nv04_mc_oclass;
+ extern struct nouveau_oclass *nv40_mc_oclass;
+ extern struct nouveau_oclass *nv44_mc_oclass;
++extern struct nouveau_oclass *nv4c_mc_oclass;
+ extern struct nouveau_oclass *nv50_mc_oclass;
+ extern struct nouveau_oclass *nv94_mc_oclass;
+ extern struct nouveau_oclass *nv98_mc_oclass;
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h
+index b0d5c31606c1..81a408e7d034 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h
++++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h
+@@ -14,6 +14,7 @@ int  nv04_mc_ctor(struct nouveau_object *, struct nouveau_object *,
+ extern const struct nouveau_mc_intr nv04_mc_intr[];
+ int  nv04_mc_init(struct nouveau_object *);
+ void nv40_mc_msi_rearm(struct nouveau_mc *);
++int  nv44_mc_init(struct nouveau_object *object);
+ int  nv50_mc_init(struct nouveau_object *);
+ extern const struct nouveau_mc_intr nv50_mc_intr[];
+ extern const struct nouveau_mc_intr nvc0_mc_intr[];
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c
+index 3bfee5c6c4f2..cc4d0d2d886e 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c
+@@ -24,7 +24,7 @@
+ 
+ #include "nv04.h"
+ 
+-static int
++int
+ nv44_mc_init(struct nouveau_object *object)
+ {
+ 	struct nv04_mc_priv *priv = (void *)object;
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c
+new file mode 100644
+index 000000000000..a75c35ccf25c
+--- /dev/null
++++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c
+@@ -0,0 +1,45 @@
++/*
++ * Copyright 2014 Ilia Mirkin
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * Authors: Ilia Mirkin
++ */
++
++#include "nv04.h"
++
++static void
++nv4c_mc_msi_rearm(struct nouveau_mc *pmc)
++{
++	struct nv04_mc_priv *priv = (void *)pmc;
++	nv_wr08(priv, 0x088050, 0xff);
++}
++
++struct nouveau_oclass *
++nv4c_mc_oclass = &(struct nouveau_mc_oclass) {
++	.base.handle = NV_SUBDEV(MC, 0x4c),
++	.base.ofuncs = &(struct nouveau_ofuncs) {
++		.ctor = nv04_mc_ctor,
++		.dtor = _nouveau_mc_dtor,
++		.init = nv44_mc_init,
++		.fini = _nouveau_mc_fini,
++	},
++	.intr = nv04_mc_intr,
++	.msi_rearm = nv4c_mc_msi_rearm,
++}.base;

commit 7d3428cd4b2ad51af86fdbdf8284ca38fa95e601
+Author: Ilia Mirkin 
+Date:   Wed Jan 29 19:53:00 2014 -0500
+
+    drm/nouveau: set irq_enabled manually
+    
+    Since commit 0fa9061ae8c ("drm/nouveau/mc: handle irq-related setup
+    ourselves"), drm_device->irq_enabled remained unset. This is needed in
+    order to properly wait for a vblank event in the generic drm code.
+    
+    See https://bugs.freedesktop.org/show_bug.cgi?id=74195
+    
+    Reported-by: Jan Janecek 
+    Signed-off-by: Ilia Mirkin 
+    Cc: stable@vger.kernel.org # 3.10+
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
+index 78c8e7146d56..89c484d8ac26 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
++++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
+@@ -376,6 +376,8 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
+ 	if (ret)
+ 		goto fail_device;
+ 
++	dev->irq_enabled = true;
++
+ 	/* workaround an odd issue on nvc1 by disabling the device's
+ 	 * nosnoop capability.  hopefully won't cause issues until a
+ 	 * better fix is found - assuming there is one...
+@@ -475,6 +477,7 @@ nouveau_drm_remove(struct pci_dev *pdev)
+ 	struct nouveau_drm *drm = nouveau_drm(dev);
+ 	struct nouveau_object *device;
+ 
++	dev->irq_enabled = false;
+ 	device = drm->client.base.device;
+ 	drm_put_dev(dev);
+ 

commit f3980dc50c5117a952baee7135aae50d48304af3
+Author: Ilia Mirkin 
+Date:   Thu Jan 23 02:45:02 2014 -0500
+
+    drm/nouveau: resume display if any later suspend bits fail
+    
+    If either idling channels or suspending the fence were to fail, the
+    display would never be resumed. Also if a client fails, resume the fence
+    (not functionally important, but it would potentially leak memory).
+    
+    See https://bugs.freedesktop.org/show_bug.cgi?id=70213
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
+index eecc6ca377c8..78c8e7146d56 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
++++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
+@@ -503,19 +503,21 @@ nouveau_do_suspend(struct drm_device *dev)
+ 	if (drm->cechan) {
+ 		ret = nouveau_channel_idle(drm->cechan);
+ 		if (ret)
+-			return ret;
++			goto fail_display;
+ 	}
+ 
+ 	if (drm->channel) {
+ 		ret = nouveau_channel_idle(drm->channel);
+ 		if (ret)
+-			return ret;
++			goto fail_display;
+ 	}
+ 
+ 	NV_INFO(drm, "suspending client object trees...\n");
+ 	if (drm->fence && nouveau_fence(drm)->suspend) {
+-		if (!nouveau_fence(drm)->suspend(drm))
+-			return -ENOMEM;
++		if (!nouveau_fence(drm)->suspend(drm)) {
++			ret = -ENOMEM;
++			goto fail_display;
++		}
+ 	}
+ 
+ 	list_for_each_entry(cli, &drm->clients, head) {
+@@ -537,6 +539,10 @@ nouveau_do_suspend(struct drm_device *dev)
+ 		nouveau_client_init(&cli->base);
+ 	}
+ 
++	if (drm->fence && nouveau_fence(drm)->resume)
++		nouveau_fence(drm)->resume(drm);
++
++fail_display:
+ 	if (dev->mode_config.num_crtc) {
+ 		NV_INFO(drm, "resuming display...\n");
+ 		nouveau_display_resume(dev);

commit ea7dce90105ff2eb81958498d6d9f30a0753bbe8
+Author: Ilia Mirkin 
+Date:   Fri Jan 17 00:13:05 2014 -0500
+
+    drm/nv50/gr: print mpc trap name when it's not an mp trap
+    
+    Signed-off-by: Ilia Mirkin 
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
+index 0f8d18ae6802..30ed19c52e05 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
++++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
+@@ -315,6 +315,20 @@ static const struct nouveau_bitfield nv50_mp_exec_errors[] = {
+ 	{}
+ };
+ 
++static const struct nouveau_bitfield nv50_mpc_traps[] = {
++	{ 0x0000001, "LOCAL_LIMIT_READ" },
++	{ 0x0000010, "LOCAL_LIMIT_WRITE" },
++	{ 0x0000040, "STACK_LIMIT" },
++	{ 0x0000100, "GLOBAL_LIMIT_READ" },
++	{ 0x0001000, "GLOBAL_LIMIT_WRITE" },
++	{ 0x0010000, "MP0" },
++	{ 0x0020000, "MP1" },
++	{ 0x0040000, "GLOBAL_LIMIT_RED" },
++	{ 0x0400000, "GLOBAL_LIMIT_ATOM" },
++	{ 0x4000000, "MP2" },
++	{}
++};
++
+ static const struct nouveau_bitfield nv50_graph_trap_m2mf[] = {
+ 	{ 0x00000001, "NOTIFY" },
+ 	{ 0x00000002, "IN" },
+@@ -524,6 +538,12 @@ nv50_priv_tp_trap(struct nv50_graph_priv *priv, int type, u32 ustatus_old,
+ 				nv50_priv_mp_trap(priv, i, display);
+ 				ustatus &= ~0x04030000;
+ 			}
++			if (ustatus && display) {
++				nv_error("%s - TP%d:", name, i);
++				nouveau_bitfield_print(nv50_mpc_traps, ustatus);
++				pr_cont("\n");
++				ustatus = 0;
++			}
+ 			break;
+ 		case 8: /* PROP error */
+ 			if (display)

commit f750ecc95068b2b492819ca15182fc4c632b4cca
+Author: Ilia Mirkin 
+Date:   Fri Jan 17 06:19:46 2014 -0500
+
+    drm/nv50/gr: update list of mp errors, make it a bitfield
+    
+    Signed-off-by: Ilia Mirkin 
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
+index a489ac2f3382..0f8d18ae6802 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
++++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
+@@ -304,12 +304,14 @@ nv84_graph_tlb_flush(struct nouveau_engine *engine)
+ 	return timeout ? -EBUSY : 0;
+ }
+ 
+-static const struct nouveau_enum nv50_mp_exec_error_names[] = {
+-	{ 3, "STACK_UNDERFLOW", NULL },
+-	{ 4, "QUADON_ACTIVE", NULL },
+-	{ 8, "TIMEOUT", NULL },
+-	{ 0x10, "INVALID_OPCODE", NULL },
+-	{ 0x40, "BREAKPOINT", NULL },
++static const struct nouveau_bitfield nv50_mp_exec_errors[] = {
++	{ 0x01, "STACK_UNDERFLOW" },
++	{ 0x02, "STACK_MISMATCH" },
++	{ 0x04, "QUADON_ACTIVE" },
++	{ 0x08, "TIMEOUT" },
++	{ 0x10, "INVALID_OPCODE" },
++	{ 0x20, "PM_OVERFLOW" },
++	{ 0x40, "BREAKPOINT" },
+ 	{}
+ };
+ 
+@@ -474,8 +476,8 @@ nv50_priv_mp_trap(struct nv50_graph_priv *priv, int tpid, int display)
+ 			oplow = nv_rd32(priv, addr + 0x70);
+ 			ophigh = nv_rd32(priv, addr + 0x74);
+ 			nv_error(priv, "TRAP_MP_EXEC - "
+-					"TP %d MP %d: ", tpid, i);
+-			nouveau_enum_print(nv50_mp_exec_error_names, status);
++					"TP %d MP %d:", tpid, i);
++			nouveau_bitfield_print(nv50_mp_exec_errors, status);
+ 			pr_cont(" at %06x warp %d, opcode %08x %08x\n",
+ 					pc&0xffffff, pc >> 24,
+ 					oplow, ophigh);

commit e2dd003dfa81de3247d7edae5d1a49427cf5a2c4
+Author: Ilia Mirkin 
+Date:   Thu Jan 16 02:47:11 2014 -0500
+
+    drm/nv50/gr: add more trap names to print on error
+    
+    Also avoids printing the errors bitfield if that information has already
+    been shown.
+    
+    Signed-off-by: Ilia Mirkin 
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
+index 03de5175dd9f..a489ac2f3382 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
++++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
+@@ -396,6 +396,60 @@ static const struct nouveau_bitfield nv50_graph_intr_name[] = {
+ 	{}
+ };
+ 
++static const struct nouveau_bitfield nv50_graph_trap_prop[] = {
++	{ 0x00000004, "SURF_WIDTH_OVERRUN" },
++	{ 0x00000008, "SURF_HEIGHT_OVERRUN" },
++	{ 0x00000010, "DST2D_FAULT" },
++	{ 0x00000020, "ZETA_FAULT" },
++	{ 0x00000040, "RT_FAULT" },
++	{ 0x00000080, "CUDA_FAULT" },
++	{ 0x00000100, "DST2D_STORAGE_TYPE_MISMATCH" },
++	{ 0x00000200, "ZETA_STORAGE_TYPE_MISMATCH" },
++	{ 0x00000400, "RT_STORAGE_TYPE_MISMATCH" },
++	{ 0x00000800, "DST2D_LINEAR_MISMATCH" },
++	{ 0x00001000, "RT_LINEAR_MISMATCH" },
++	{}
++};
++
++static void
++nv50_priv_prop_trap(struct nv50_graph_priv *priv,
++		    u32 ustatus_addr, u32 ustatus, u32 tp)
++{
++	u32 e0c = nv_rd32(priv, ustatus_addr + 0x04);
++	u32 e10 = nv_rd32(priv, ustatus_addr + 0x08);
++	u32 e14 = nv_rd32(priv, ustatus_addr + 0x0c);
++	u32 e18 = nv_rd32(priv, ustatus_addr + 0x10);
++	u32 e1c = nv_rd32(priv, ustatus_addr + 0x14);
++	u32 e20 = nv_rd32(priv, ustatus_addr + 0x18);
++	u32 e24 = nv_rd32(priv, ustatus_addr + 0x1c);
++
++	/* CUDA memory: l[], g[] or stack. */
++	if (ustatus & 0x00000080) {
++		if (e18 & 0x80000000) {
++			/* g[] read fault? */
++			nv_error(priv, "TRAP_PROP - TP %d - CUDA_FAULT - Global read fault at address %02x%08x\n",
++					 tp, e14, e10 | ((e18 >> 24) & 0x1f));
++			e18 &= ~0x1f000000;
++		} else if (e18 & 0xc) {
++			/* g[] write fault? */
++			nv_error(priv, "TRAP_PROP - TP %d - CUDA_FAULT - Global write fault at address %02x%08x\n",
++				 tp, e14, e10 | ((e18 >> 7) & 0x1f));
++			e18 &= ~0x00000f80;
++		} else {
++			nv_error(priv, "TRAP_PROP - TP %d - Unknown CUDA fault at address %02x%08x\n",
++				 tp, e14, e10);
++		}
++		ustatus &= ~0x00000080;
++	}
++	if (ustatus) {
++		nv_error(priv, "TRAP_PROP - TP %d -", tp);
++		nouveau_bitfield_print(nv50_graph_trap_prop, ustatus);
++		pr_cont(" - Address %02x%08x\n", e14, e10);
++	}
++	nv_error(priv, "TRAP_PROP - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
++		 tp, e0c, e18, e1c, e20, e24);
++}
++
+ static void
+ nv50_priv_mp_trap(struct nv50_graph_priv *priv, int tpid, int display)
+ {
+@@ -469,58 +523,11 @@ nv50_priv_tp_trap(struct nv50_graph_priv *priv, int type, u32 ustatus_old,
+ 				ustatus &= ~0x04030000;
+ 			}
+ 			break;
+-		case 8: /* TPDMA error */
+-			{
+-			u32 e0c = nv_rd32(priv, ustatus_addr + 4);
+-			u32 e10 = nv_rd32(priv, ustatus_addr + 8);
+-			u32 e14 = nv_rd32(priv, ustatus_addr + 0xc);
+-			u32 e18 = nv_rd32(priv, ustatus_addr + 0x10);
+-			u32 e1c = nv_rd32(priv, ustatus_addr + 0x14);
+-			u32 e20 = nv_rd32(priv, ustatus_addr + 0x18);
+-			u32 e24 = nv_rd32(priv, ustatus_addr + 0x1c);
+-			/* 2d engine destination */
+-			if (ustatus & 0x00000010) {
+-				if (display) {
+-					nv_error(priv, "TRAP_TPDMA_2D - TP %d - Unknown fault at address %02x%08x\n",
+-							i, e14, e10);
+-					nv_error(priv, "TRAP_TPDMA_2D - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
+-							i, e0c, e18, e1c, e20, e24);
+-				}
+-				ustatus &= ~0x00000010;
+-			}
+-			/* Render target */
+-			if (ustatus & 0x00000040) {
+-				if (display) {
+-					nv_error(priv, "TRAP_TPDMA_RT - TP %d - Unknown fault at address %02x%08x\n",
+-							i, e14, e10);
+-					nv_error(priv, "TRAP_TPDMA_RT - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
+-							i, e0c, e18, e1c, e20, e24);
+-				}
+-				ustatus &= ~0x00000040;
+-			}
+-			/* CUDA memory: l[], g[] or stack. */
+-			if (ustatus & 0x00000080) {
+-				if (display) {
+-					if (e18 & 0x80000000) {
+-						/* g[] read fault? */
+-						nv_error(priv, "TRAP_TPDMA - TP %d - Global read fault at address %02x%08x\n",
+-								i, e14, e10 | ((e18 >> 24) & 0x1f));
+-						e18 &= ~0x1f000000;
+-					} else if (e18 & 0xc) {
+-						/* g[] write fault? */
+-						nv_error(priv, "TRAP_TPDMA - TP %d - Global write fault at address %02x%08x\n",
+-								i, e14, e10 | ((e18 >> 7) & 0x1f));
+-						e18 &= ~0x00000f80;
+-					} else {
+-						nv_error(priv, "TRAP_TPDMA - TP %d - Unknown CUDA fault at address %02x%08x\n",
+-								i, e14, e10);
+-					}
+-					nv_error(priv, "TRAP_TPDMA - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
+-							i, e0c, e18, e1c, e20, e24);
+-				}
+-				ustatus &= ~0x00000080;
+-			}
+-			}
++		case 8: /* PROP error */
++			if (display)
++				nv50_priv_prop_trap(
++						priv, ustatus_addr, ustatus, i);
++			ustatus = 0;
+ 			break;
+ 		}
+ 		if (ustatus) {
+@@ -727,11 +734,11 @@ nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display,
+ 		status &= ~0x080;
+ 	}
+ 
+-	/* TPDMA:  Handles TP-initiated uncached memory accesses:
++	/* PROP:  Handles TP-initiated uncached memory accesses:
+ 	 * l[], g[], stack, 2d surfaces, render targets. */
+ 	if (status & 0x100) {
+ 		nv50_priv_tp_trap(priv, 8, 0x408e08, 0x408708, display,
+-				    "TRAP_TPDMA");
++				    "TRAP_PROP");
+ 		nv_wr32(priv, 0x400108, 0x100);
+ 		status &= ~0x100;
+ 	}
+@@ -760,7 +767,7 @@ nv50_graph_intr(struct nouveau_subdev *subdev)
+ 	u32 mthd = (addr & 0x00001ffc);
+ 	u32 data = nv_rd32(priv, 0x400708);
+ 	u32 class = nv_rd32(priv, 0x400814);
+-	u32 show = stat;
++	u32 show = stat, show_bitfield = stat;
+ 	int chid;
+ 
+ 	engctx = nouveau_engctx_get(engine, inst);
+@@ -778,21 +785,26 @@ nv50_graph_intr(struct nouveau_subdev *subdev)
+ 		nv_error(priv, "DATA_ERROR ");
+ 		nouveau_enum_print(nv50_data_error_names, ecode);
+ 		pr_cont("\n");
++		show_bitfield &= ~0x00100000;
+ 	}
+ 
+ 	if (stat & 0x00200000) {
+ 		if (!nv50_graph_trap_handler(priv, show, chid, (u64)inst << 12,
+ 				engctx))
+ 			show &= ~0x00200000;
++		show_bitfield &= ~0x00200000;
+ 	}
+ 
+ 	nv_wr32(priv, 0x400100, stat);
+ 	nv_wr32(priv, 0x400500, 0x00010001);
+ 
+ 	if (show) {
+-		nv_error(priv, "%s", "");
+-		nouveau_bitfield_print(nv50_graph_intr_name, show);
+-		pr_cont("\n");
++		show &= show_bitfield;
++		if (show) {
++			nv_error(priv, "%s", "");
++			nouveau_bitfield_print(nv50_graph_intr_name, show);
++			pr_cont("\n");
++		}
+ 		nv_error(priv,
+ 			 "ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
+ 			 chid, (u64)inst << 12, nouveau_client_name(engctx),

commit f87cd8b695d372087685976460fac1ec6ba2fca9
+Author: Ilia Mirkin 
+Date:   Sun Jan 19 04:18:15 2014 -0500
+
+    drm/nouveau/devinit: lock/unlock crtc regs for all devices, not just pre-nv50
+    
+    Also make nv_lockvgac work for nv50+ devices. This should fix
+    IO_CONDITION and related VBIOS opcodes that read/write the crtc regs.
+    
+    See https://bugs.freedesktop.org/show_bug.cgi?id=60680
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/vga.c b/drivers/gpu/drm/nouveau/core/engine/disp/vga.c
+index 5a1c68474597..8836c3cb99c3 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/disp/vga.c
++++ b/drivers/gpu/drm/nouveau/core/engine/disp/vga.c
+@@ -138,10 +138,15 @@ nv_wrvgai(void *obj, int head, u16 port, u8 index, u8 value)
+ bool
+ nv_lockvgac(void *obj, bool lock)
+ {
++	struct nouveau_device *dev = nv_device(obj);
++
+ 	bool locked = !nv_rdvgac(obj, 0, 0x1f);
+ 	u8 data = lock ? 0x99 : 0x57;
+-	nv_wrvgac(obj, 0, 0x1f, data);
+-	if (nv_device(obj)->chipset == 0x11) {
++	if (dev->card_type < NV_50)
++		nv_wrvgac(obj, 0, 0x1f, data);
++	else
++		nv_wrvgac(obj, 0, 0x3f, data);
++	if (dev->chipset == 0x11) {
+ 		if (!(nv_rd32(obj, 0x001084) & 0x10000000))
+ 			nv_wrvgac(obj, 1, 0x1f, data);
+ 	}
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c
+index 6b23d9a0b953..8fa34e8152c2 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c
+@@ -26,6 +26,7 @@
+ 
+ #include 
+ #include 
++#include 
+ 
+ #include "priv.h"
+ 
+@@ -38,6 +39,9 @@ _nouveau_devinit_fini(struct nouveau_object *object, bool suspend)
+ 	if (suspend)
+ 		devinit->post = true;
+ 
++	/* unlock the extended vga crtc regs */
++	nv_lockvgac(devinit, false);
++
+ 	return nouveau_subdev_fini(&devinit->base, suspend);
+ }
+ 
+@@ -61,6 +65,17 @@ _nouveau_devinit_init(struct nouveau_object *object)
+ 	return 0;
+ }
+ 
++void
++_nouveau_devinit_dtor(struct nouveau_object *object)
++{
++	struct nouveau_devinit *devinit = (void *)object;
++
++	/* lock crtc regs */
++	nv_lockvgac(devinit, true);
++
++	nouveau_subdev_destroy(&devinit->base);
++}
++
+ int
+ nouveau_devinit_create_(struct nouveau_object *parent,
+ 			struct nouveau_object *engine,
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c
+index 24025e4e882a..7037eae46e44 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c
+@@ -388,17 +388,21 @@ int
+ nv04_devinit_fini(struct nouveau_object *object, bool suspend)
+ {
+ 	struct nv04_devinit_priv *priv = (void *)object;
++	int ret;
+ 
+ 	/* make i2c busses accessible */
+ 	nv_mask(priv, 0x000200, 0x00000001, 0x00000001);
+ 
+-	/* unlock extended vga crtc regs, and unslave crtcs */
+-	nv_lockvgac(priv, false);
++	ret = nouveau_devinit_fini(&priv->base, suspend);
++	if (ret)
++		return ret;
++
++	/* unslave crtcs */
+ 	if (priv->owner < 0)
+ 		priv->owner = nv_rdvgaowner(priv);
+ 	nv_wrvgaowner(priv, 0);
+ 
+-	return nouveau_devinit_fini(&priv->base, suspend);
++	return 0;
+ }
+ 
+ int
+@@ -426,9 +430,8 @@ nv04_devinit_dtor(struct nouveau_object *object)
+ {
+ 	struct nv04_devinit_priv *priv = (void *)object;
+ 
+-	/* restore vga owner saved at first init, and lock crtc regs  */
++	/* restore vga owner saved at first init */
+ 	nv_wrvgaowner(priv, priv->owner);
+-	nv_lockvgac(priv, true);
+ 
+ 	nouveau_devinit_destroy(&priv->base);
+ }
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h
+index c4179b6d6eca..822a2fbf44a5 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h
++++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h
+@@ -15,8 +15,10 @@ struct nouveau_devinit_impl {
+ 
+ #define nouveau_devinit_create(p,e,o,d)                                        \
+ 	nouveau_devinit_create_((p), (e), (o), sizeof(**d), (void **)d)
+-#define nouveau_devinit_destroy(p)                                             \
+-	nouveau_subdev_destroy(&(p)->base)
++#define nouveau_devinit_destroy(p) ({                                          \
++	struct nouveau_devinit *d = (p);                                       \
++	_nouveau_devinit_dtor(nv_object(d));                                   \
++})
+ #define nouveau_devinit_init(p) ({                                             \
+ 	struct nouveau_devinit *d = (p);                                       \
+ 	_nouveau_devinit_init(nv_object(d));                                   \
+@@ -28,7 +30,7 @@ struct nouveau_devinit_impl {
+ 
+ int nouveau_devinit_create_(struct nouveau_object *, struct nouveau_object *,
+ 			    struct nouveau_oclass *, int, void **);
+-#define _nouveau_devinit_dtor _nouveau_subdev_dtor
++void _nouveau_devinit_dtor(struct nouveau_object *);
+ int _nouveau_devinit_init(struct nouveau_object *);
+ int _nouveau_devinit_fini(struct nouveau_object *, bool suspend);
+ 

commit 4019aaa2b314a5be9886ae1db64ff8c6d3c060ed
+Author: Ilia Mirkin 
+Date:   Tue Jan 14 16:29:06 2014 +1000
+
+    drm/nv50-/devinit: prevent use of engines marked as disabled by hw/vbios
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile
+index d1dd49b344ec..e88145ba1bf5 100644
+--- a/drivers/gpu/drm/nouveau/Makefile
++++ b/drivers/gpu/drm/nouveau/Makefile
+@@ -72,7 +72,10 @@ nouveau-y += core/subdev/devinit/nv10.o
+ nouveau-y += core/subdev/devinit/nv1a.o
+ nouveau-y += core/subdev/devinit/nv20.o
+ nouveau-y += core/subdev/devinit/nv50.o
++nouveau-y += core/subdev/devinit/nv84.o
++nouveau-y += core/subdev/devinit/nv98.o
+ nouveau-y += core/subdev/devinit/nva3.o
++nouveau-y += core/subdev/devinit/nvaf.o
+ nouveau-y += core/subdev/devinit/nvc0.o
+ nouveau-y += core/subdev/fb/base.o
+ nouveau-y += core/subdev/fb/nv04.o
+diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c
+index 993df09ad643..ac3291f781f6 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c
++++ b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c
+@@ -105,9 +105,6 @@ nvc0_copy0_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	struct nvc0_copy_priv *priv;
+ 	int ret;
+ 
+-	if (nv_rd32(parent, 0x022500) & 0x00000100)
+-		return -ENODEV;
+-
+ 	ret = nouveau_falcon_create(parent, engine, oclass, 0x104000, true,
+ 				    "PCE0", "copy0", &priv);
+ 	*pobject = nv_object(priv);
+@@ -133,9 +130,6 @@ nvc0_copy1_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	struct nvc0_copy_priv *priv;
+ 	int ret;
+ 
+-	if (nv_rd32(parent, 0x022500) & 0x00000200)
+-		return -ENODEV;
+-
+ 	ret = nouveau_falcon_create(parent, engine, oclass, 0x105000, true,
+ 				    "PCE1", "copy1", &priv);
+ 	*pobject = nv_object(priv);
+diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c b/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c
+index 30f1ef1edcc5..748a61eb3c6f 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c
++++ b/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c
+@@ -88,9 +88,6 @@ nve0_copy0_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	struct nve0_copy_priv *priv;
+ 	int ret;
+ 
+-	if (nv_rd32(parent, 0x022500) & 0x00000100)
+-		return -ENODEV;
+-
+ 	ret = nouveau_engine_create(parent, engine, oclass, true,
+ 				    "PCE0", "copy0", &priv);
+ 	*pobject = nv_object(priv);
+@@ -112,9 +109,6 @@ nve0_copy1_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	struct nve0_copy_priv *priv;
+ 	int ret;
+ 
+-	if (nv_rd32(parent, 0x022500) & 0x00000200)
+-		return -ENODEV;
+-
+ 	ret = nouveau_engine_create(parent, engine, oclass, true,
+ 				    "PCE1", "copy1", &priv);
+ 	*pobject = nv_object(priv);
+diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv50.c b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c
+index 5ae94475a3f1..81d5c26643d5 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/device/nv50.c
++++ b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c
+@@ -90,7 +90,7 @@ nv50_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
+ 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
+ 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
+-		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv50_devinit_oclass;
++		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
+ 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv50_mc_oclass;
+ 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv50_bus_oclass;
+ 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
+@@ -118,7 +118,7 @@ nv50_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
+ 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
+ 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
+-		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv50_devinit_oclass;
++		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
+ 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv50_mc_oclass;
+ 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv50_bus_oclass;
+ 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
+@@ -146,7 +146,7 @@ nv50_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
+ 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
+ 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
+-		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv50_devinit_oclass;
++		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
+ 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv50_mc_oclass;
+ 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv50_bus_oclass;
+ 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
+@@ -174,7 +174,7 @@ nv50_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
+ 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
+ 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
+-		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv50_devinit_oclass;
++		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
+ 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv94_mc_oclass;
+ 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
+ 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
+@@ -202,7 +202,7 @@ nv50_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
+ 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
+ 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
+-		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv50_devinit_oclass;
++		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
+ 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv94_mc_oclass;
+ 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
+ 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
+@@ -230,7 +230,7 @@ nv50_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
+ 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
+ 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
+-		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv50_devinit_oclass;
++		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv98_devinit_oclass;
+ 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
+ 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
+ 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
+@@ -258,7 +258,7 @@ nv50_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
+ 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
+ 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
+-		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv50_devinit_oclass;
++		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
+ 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
+ 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
+ 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
+@@ -286,7 +286,7 @@ nv50_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nvaa_clock_oclass;
+ 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
+ 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
+-		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv50_devinit_oclass;
++		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv98_devinit_oclass;
+ 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
+ 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
+ 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
+@@ -314,7 +314,7 @@ nv50_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nvaa_clock_oclass;
+ 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
+ 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
+-		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv50_devinit_oclass;
++		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv98_devinit_oclass;
+ 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
+ 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
+ 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
+@@ -430,7 +430,7 @@ nv50_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nva3_clock_oclass;
+ 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
+ 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
+-		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nva3_devinit_oclass;
++		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvaf_devinit_oclass;
+ 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
+ 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
+ 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
+diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
+index 378a015091d2..d52c0f50a1a9 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
++++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
+@@ -967,9 +967,6 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	int heads = nv_rd32(parent, 0x022448);
+ 	int ret;
+ 
+-	if (nv_rd32(parent, 0x022500) & 0x00000001)
+-		return -ENODEV;
+-
+ 	ret = nouveau_disp_create(parent, engine, oclass, heads,
+ 				  "PDISP", "display", &priv);
+ 	*pobject = nv_object(priv);
+diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
+index fb1fe6ae5e74..20725b363d58 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
++++ b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
+@@ -54,9 +54,6 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	int heads = nv_rd32(parent, 0x022448);
+ 	int ret;
+ 
+-	if (nv_rd32(parent, 0x022500) & 0x00000001)
+-		return -ENODEV;
+-
+ 	ret = nouveau_disp_create(parent, engine, oclass, heads,
+ 				  "PDISP", "display", &priv);
+ 	*pobject = nv_object(priv);
+diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
+index 42aa6b97dbea..a488c36e40f9 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
++++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
+@@ -54,9 +54,6 @@ nvf0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	int heads = nv_rd32(parent, 0x022448);
+ 	int ret;
+ 
+-	if (nv_rd32(parent, 0x022500) & 0x00000001)
+-		return -ENODEV;
+-
+ 	ret = nouveau_disp_create(parent, engine, oclass, heads,
+ 				  "PDISP", "display", &priv);
+ 	*pobject = nv_object(priv);
+diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/devinit.h b/drivers/gpu/drm/nouveau/core/include/subdev/devinit.h
+index e59384d04870..ed1ac68c38b3 100644
+--- a/drivers/gpu/drm/nouveau/core/include/subdev/devinit.h
++++ b/drivers/gpu/drm/nouveau/core/include/subdev/devinit.h
+@@ -23,7 +23,10 @@ extern struct nouveau_oclass *nv10_devinit_oclass;
+ extern struct nouveau_oclass *nv1a_devinit_oclass;
+ extern struct nouveau_oclass *nv20_devinit_oclass;
+ extern struct nouveau_oclass *nv50_devinit_oclass;
++extern struct nouveau_oclass *nv84_devinit_oclass;
++extern struct nouveau_oclass *nv98_devinit_oclass;
+ extern struct nouveau_oclass *nva3_devinit_oclass;
++extern struct nouveau_oclass *nvaf_devinit_oclass;
+ extern struct nouveau_oclass *nvc0_devinit_oclass;
+ 
+ #endif
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c
+index 6013c42503d1..6b23d9a0b953 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c
+@@ -44,12 +44,21 @@ _nouveau_devinit_fini(struct nouveau_object *object, bool suspend)
+ int
+ _nouveau_devinit_init(struct nouveau_object *object)
+ {
++	struct nouveau_devinit_impl *impl = (void *)object->oclass;
+ 	struct nouveau_devinit *devinit = (void *)object;
+-	int ret = nouveau_subdev_init(&devinit->base);
++	int ret;
++
++	ret = nouveau_subdev_init(&devinit->base);
++	if (ret)
++		return ret;
++
++	ret = nvbios_init(&devinit->base, devinit->post);
+ 	if (ret)
+ 		return ret;
+ 
+-	return nvbios_init(&devinit->base, devinit->post);
++	if (impl->disable)
++		nv_device(devinit)->disable_mask |= impl->disable(devinit);
++	return 0;
+ }
+ 
+ int
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c
+index f81509eb6c3e..b46c62a1d5d8 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c
+@@ -30,7 +30,7 @@
+ 
+ #include "nv50.h"
+ 
+-static int
++int
+ nv50_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
+ {
+ 	struct nv50_devinit_priv *priv = (void *)devinit;
+@@ -74,6 +74,19 @@ nv50_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
+ 	return 0;
+ }
+ 
++static u64
++nv50_devinit_disable(struct nouveau_devinit *devinit)
++{
++	struct nv50_devinit_priv *priv = (void *)devinit;
++	u32 r001540 = nv_rd32(priv, 0x001540);
++	u64 disable = 0ULL;
++
++	if (!(r001540 & 0x40000000))
++		disable |= (1ULL << NVDEV_ENGINE_MPEG);
++
++	return disable;
++}
++
+ int
+ nv50_devinit_init(struct nouveau_object *object)
+ {
+@@ -146,4 +159,5 @@ nv50_devinit_oclass = &(struct nouveau_devinit_impl) {
+ 		.fini = _nouveau_devinit_fini,
+ 	},
+ 	.pll_set = nv50_devinit_pll_set,
++	.disable = nv50_devinit_disable,
+ }.base;
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h
+index f87e483b0977..141c27e9f182 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h
++++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h
+@@ -11,5 +11,8 @@ int  nv50_devinit_ctor(struct nouveau_object *, struct nouveau_object *,
+ 		       struct nouveau_oclass *, void *, u32,
+ 		       struct nouveau_object **);
+ int  nv50_devinit_init(struct nouveau_object *);
++int  nv50_devinit_pll_set(struct nouveau_devinit *, u32, u32);
++
++int  nva3_devinit_pll_set(struct nouveau_devinit *, u32, u32);
+ 
+ #endif
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv84.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv84.c
+new file mode 100644
+index 000000000000..787422505d87
+--- /dev/null
++++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv84.c
+@@ -0,0 +1,63 @@
++/*
++ * Copyright 2013 Red Hat Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * Authors: Ben Skeggs
++ */
++
++#include "nv50.h"
++
++static u64
++nv84_devinit_disable(struct nouveau_devinit *devinit)
++{
++	struct nv50_devinit_priv *priv = (void *)devinit;
++	u32 r001540 = nv_rd32(priv, 0x001540);
++	u32 r00154c = nv_rd32(priv, 0x00154c);
++	u64 disable = 0ULL;
++
++	if (!(r001540 & 0x40000000)) {
++		disable |= (1ULL << NVDEV_ENGINE_MPEG);
++		disable |= (1ULL << NVDEV_ENGINE_VP);
++		disable |= (1ULL << NVDEV_ENGINE_BSP);
++		disable |= (1ULL << NVDEV_ENGINE_CRYPT);
++	}
++
++	if (!(r00154c & 0x00000004))
++		disable |= (1ULL << NVDEV_ENGINE_DISP);
++	if (!(r00154c & 0x00000020))
++		disable |= (1ULL << NVDEV_ENGINE_BSP);
++	if (!(r00154c & 0x00000040))
++		disable |= (1ULL << NVDEV_ENGINE_CRYPT);
++
++	return disable;
++}
++
++struct nouveau_oclass *
++nv84_devinit_oclass = &(struct nouveau_devinit_impl) {
++	.base.handle = NV_SUBDEV(DEVINIT, 0x84),
++	.base.ofuncs = &(struct nouveau_ofuncs) {
++		.ctor = nv50_devinit_ctor,
++		.dtor = _nouveau_devinit_dtor,
++		.init = nv50_devinit_init,
++		.fini = _nouveau_devinit_fini,
++	},
++	.pll_set = nv50_devinit_pll_set,
++	.disable = nv84_devinit_disable,
++}.base;
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv98.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv98.c
+new file mode 100644
+index 000000000000..2b0e963fc6f0
+--- /dev/null
++++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv98.c
+@@ -0,0 +1,62 @@
++/*
++ * Copyright 2013 Red Hat Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * Authors: Ben Skeggs
++ */
++
++#include "nv50.h"
++
++static u64
++nv98_devinit_disable(struct nouveau_devinit *devinit)
++{
++	struct nv50_devinit_priv *priv = (void *)devinit;
++	u32 r001540 = nv_rd32(priv, 0x001540);
++	u32 r00154c = nv_rd32(priv, 0x00154c);
++	u64 disable = 0ULL;
++
++	if (!(r001540 & 0x40000000)) {
++		disable |= (1ULL << NVDEV_ENGINE_VP);
++		disable |= (1ULL << NVDEV_ENGINE_BSP);
++		disable |= (1ULL << NVDEV_ENGINE_PPP);
++	}
++
++	if (!(r00154c & 0x00000004))
++		disable |= (1ULL << NVDEV_ENGINE_DISP);
++	if (!(r00154c & 0x00000020))
++		disable |= (1ULL << NVDEV_ENGINE_BSP);
++	if (!(r00154c & 0x00000040))
++		disable |= (1ULL << NVDEV_ENGINE_CRYPT);
++
++	return disable;
++}
++
++struct nouveau_oclass *
++nv98_devinit_oclass = &(struct nouveau_devinit_impl) {
++	.base.handle = NV_SUBDEV(DEVINIT, 0x98),
++	.base.ofuncs = &(struct nouveau_ofuncs) {
++		.ctor = nv50_devinit_ctor,
++		.dtor = _nouveau_devinit_dtor,
++		.init = nv50_devinit_init,
++		.fini = _nouveau_devinit_fini,
++	},
++	.pll_set = nv50_devinit_pll_set,
++	.disable = nv98_devinit_disable,
++}.base;
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c
+index 67f55940b00e..6dedf1dad7f7 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c
+@@ -24,7 +24,7 @@
+ 
+ #include "nv50.h"
+ 
+-static int
++int
+ nva3_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
+ {
+ 	struct nv50_devinit_priv *priv = (void *)devinit;
+@@ -58,6 +58,29 @@ nva3_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
+ 	return ret;
+ }
+ 
++static u64
++nva3_devinit_disable(struct nouveau_devinit *devinit)
++{
++	struct nv50_devinit_priv *priv = (void *)devinit;
++	u32 r001540 = nv_rd32(priv, 0x001540);
++	u32 r00154c = nv_rd32(priv, 0x00154c);
++	u64 disable = 0ULL;
++
++	if (!(r001540 & 0x40000000)) {
++		disable |= (1ULL << NVDEV_ENGINE_VP);
++		disable |= (1ULL << NVDEV_ENGINE_PPP);
++	}
++
++	if (!(r00154c & 0x00000004))
++		disable |= (1ULL << NVDEV_ENGINE_DISP);
++	if (!(r00154c & 0x00000020))
++		disable |= (1ULL << NVDEV_ENGINE_BSP);
++	if (!(r00154c & 0x00000200))
++		disable |= (1ULL << NVDEV_ENGINE_COPY0);
++
++	return disable;
++}
++
+ struct nouveau_oclass *
+ nva3_devinit_oclass = &(struct nouveau_devinit_impl) {
+ 	.base.handle = NV_SUBDEV(DEVINIT, 0xa3),
+@@ -68,4 +91,5 @@ nva3_devinit_oclass = &(struct nouveau_devinit_impl) {
+ 		.fini = _nouveau_devinit_fini,
+ 	},
+ 	.pll_set = nva3_devinit_pll_set,
++	.disable = nva3_devinit_disable,
+ }.base;
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nvaf.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nvaf.c
+new file mode 100644
+index 000000000000..4fc68d27eff3
+--- /dev/null
++++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nvaf.c
+@@ -0,0 +1,63 @@
++/*
++ * Copyright 2013 Red Hat Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * Authors: Ben Skeggs
++ */
++
++#include "nv50.h"
++
++static u64
++nvaf_devinit_disable(struct nouveau_devinit *devinit)
++{
++	struct nv50_devinit_priv *priv = (void *)devinit;
++	u32 r001540 = nv_rd32(priv, 0x001540);
++	u32 r00154c = nv_rd32(priv, 0x00154c);
++	u64 disable = 0;
++
++	if (!(r001540 & 0x40000000)) {
++		disable |= (1ULL << NVDEV_ENGINE_VP);
++		disable |= (1ULL << NVDEV_ENGINE_PPP);
++	}
++
++	if (!(r00154c & 0x00000004))
++		disable |= (1ULL << NVDEV_ENGINE_DISP);
++	if (!(r00154c & 0x00000020))
++		disable |= (1ULL << NVDEV_ENGINE_BSP);
++	if (!(r00154c & 0x00000040))
++		disable |= (1ULL << NVDEV_ENGINE_VIC);
++	if (!(r00154c & 0x00000200))
++		disable |= (1ULL << NVDEV_ENGINE_COPY0);
++
++	return disable;
++}
++
++struct nouveau_oclass *
++nvaf_devinit_oclass = &(struct nouveau_devinit_impl) {
++	.base.handle = NV_SUBDEV(DEVINIT, 0xaf),
++	.base.ofuncs = &(struct nouveau_ofuncs) {
++		.ctor = nv50_devinit_ctor,
++		.dtor = _nouveau_devinit_dtor,
++		.init = nv50_devinit_init,
++		.fini = _nouveau_devinit_fini,
++	},
++	.pll_set = nva3_devinit_pll_set,
++	.disable = nvaf_devinit_disable,
++}.base;
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c
+index ced0e8241b34..fa7e63766b1b 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c
+@@ -59,6 +59,33 @@ nvc0_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
+ 	return ret;
+ }
+ 
++static u64
++nvc0_devinit_disable(struct nouveau_devinit *devinit)
++{
++	struct nv50_devinit_priv *priv = (void *)devinit;
++	u32 r022500 = nv_rd32(priv, 0x022500);
++	u64 disable = 0ULL;
++
++	if (r022500 & 0x00000001)
++		disable |= (1ULL << NVDEV_ENGINE_DISP);
++
++	if (r022500 & 0x00000002) {
++		disable |= (1ULL << NVDEV_ENGINE_VP);
++		disable |= (1ULL << NVDEV_ENGINE_PPP);
++	}
++
++	if (r022500 & 0x00000004)
++		disable |= (1ULL << NVDEV_ENGINE_BSP);
++	if (r022500 & 0x00000008)
++		disable |= (1ULL << NVDEV_ENGINE_VENC);
++	if (r022500 & 0x00000100)
++		disable |= (1ULL << NVDEV_ENGINE_COPY0);
++	if (r022500 & 0x00000200)
++		disable |= (1ULL << NVDEV_ENGINE_COPY1);
++
++	return disable;
++}
++
+ static int
+ nvc0_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 		  struct nouveau_oclass *oclass, void *data, u32 size,
+@@ -87,4 +114,5 @@ nvc0_devinit_oclass = &(struct nouveau_devinit_impl) {
+ 		.fini = _nouveau_devinit_fini,
+ 	},
+ 	.pll_set = nvc0_devinit_pll_set,
++	.disable = nvc0_devinit_disable,
+ }.base;
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h
+index ae8de97ecf16..c4179b6d6eca 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h
++++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h
+@@ -10,6 +10,7 @@ struct nouveau_devinit_impl {
+ 	struct nouveau_oclass base;
+ 	void (*meminit)(struct nouveau_devinit *);
+ 	int  (*pll_set)(struct nouveau_devinit *, u32 type, u32 freq);
++	u64  (*disable)(struct nouveau_devinit *);
+ };
+ 
+ #define nouveau_devinit_create(p,e,o,d)                                        \

commit f0d13e3a851ef29691076d89ff7ee69f004037a7
+Author: Ilia Mirkin 
+Date:   Thu Jan 9 21:19:11 2014 -0500
+
+    drm/nouveau/device: provide a way for devinit to mark engines as disabled
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/core/engine.c b/drivers/gpu/drm/nouveau/core/core/engine.c
+index c8bed4a26833..1f6954ae9dd3 100644
+--- a/drivers/gpu/drm/nouveau/core/core/engine.c
++++ b/drivers/gpu/drm/nouveau/core/core/engine.c
+@@ -42,11 +42,24 @@ nouveau_engine_create_(struct nouveau_object *parent,
+ 	if (ret)
+ 		return ret;
+ 
+-	if ( parent &&
+-	    !nouveau_boolopt(nv_device(parent)->cfgopt, iname, enable)) {
+-		if (!enable)
+-			nv_warn(engine, "disabled, %s=1 to enable\n", iname);
+-		return -ENODEV;
++	if (parent) {
++		struct nouveau_device *device = nv_device(parent);
++		int engidx = nv_engidx(nv_object(engine));
++
++		if (device->disable_mask & (1ULL << engidx)) {
++			if (!nouveau_boolopt(device->cfgopt, iname, false)) {
++				nv_debug(engine, "engine disabled by hw/fw\n");
++				return -ENODEV;
++			}
++
++			nv_warn(engine, "ignoring hw/fw engine disable\n");
++		}
++
++		if (!nouveau_boolopt(device->cfgopt, iname, enable)) {
++			if (!enable)
++				nv_warn(engine, "disabled, %s=1 to enable\n", iname);
++			return -ENODEV;
++		}
+ 	}
+ 
+ 	INIT_LIST_HEAD(&engine->contexts);
+diff --git a/drivers/gpu/drm/nouveau/core/include/core/device.h b/drivers/gpu/drm/nouveau/core/include/core/device.h
+index 24809c10b4b3..7b8ea221b00d 100644
+--- a/drivers/gpu/drm/nouveau/core/include/core/device.h
++++ b/drivers/gpu/drm/nouveau/core/include/core/device.h
+@@ -71,6 +71,7 @@ struct nouveau_device {
+ 	const char *dbgopt;
+ 	const char *name;
+ 	const char *cname;
++	u64 disable_mask;
+ 
+ 	enum {
+ 		NV_04    = 0x04,

commit 90d6db1635d5e225623af2e2e859feb607345287
+Author: Ilia Mirkin 
+Date:   Sat Dec 7 11:42:19 2013 -0500
+
+    drm/nouveau/falcon: use vmalloc to create firwmare copies
+    
+    Some firmware images may be large (64K), so using kmalloc memory is
+    inappropriate for them. Use vmalloc instead, to avoid high-order
+    allocation failures.
+    
+    Signed-off-by: Ilia Mirkin 
+    Cc: stable@vger.kernel.org
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/falcon.c b/drivers/gpu/drm/nouveau/core/engine/falcon.c
+index e03fc8e4dc1d..5e077e4ed7f6 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/falcon.c
++++ b/drivers/gpu/drm/nouveau/core/engine/falcon.c
+@@ -56,6 +56,16 @@ _nouveau_falcon_wr32(struct nouveau_object *object, u64 addr, u32 data)
+ 	nv_wr32(falcon, falcon->addr + addr, data);
+ }
+ 
++static void *
++vmemdup(const void *src, size_t len)
++{
++	void *p = vmalloc(len);
++
++	if (p)
++		memcpy(p, src, len);
++	return p;
++}
++
+ int
+ _nouveau_falcon_init(struct nouveau_object *object)
+ {
+@@ -111,7 +121,7 @@ _nouveau_falcon_init(struct nouveau_object *object)
+ 
+ 		ret = request_firmware(&fw, name, &device->pdev->dev);
+ 		if (ret == 0) {
+-			falcon->code.data = kmemdup(fw->data, fw->size, GFP_KERNEL);
++			falcon->code.data = vmemdup(fw->data, fw->size);
+ 			falcon->code.size = fw->size;
+ 			falcon->data.data = NULL;
+ 			falcon->data.size = 0;
+@@ -134,7 +144,7 @@ _nouveau_falcon_init(struct nouveau_object *object)
+ 			return ret;
+ 		}
+ 
+-		falcon->data.data = kmemdup(fw->data, fw->size, GFP_KERNEL);
++		falcon->data.data = vmemdup(fw->data, fw->size);
+ 		falcon->data.size = fw->size;
+ 		release_firmware(fw);
+ 		if (!falcon->data.data)
+@@ -149,7 +159,7 @@ _nouveau_falcon_init(struct nouveau_object *object)
+ 			return ret;
+ 		}
+ 
+-		falcon->code.data = kmemdup(fw->data, fw->size, GFP_KERNEL);
++		falcon->code.data = vmemdup(fw->data, fw->size);
+ 		falcon->code.size = fw->size;
+ 		release_firmware(fw);
+ 		if (!falcon->code.data)
+@@ -235,8 +245,8 @@ _nouveau_falcon_fini(struct nouveau_object *object, bool suspend)
+ 	if (!suspend) {
+ 		nouveau_gpuobj_ref(NULL, &falcon->core);
+ 		if (falcon->external) {
+-			kfree(falcon->data.data);
+-			kfree(falcon->code.data);
++			vfree(falcon->data.data);
++			vfree(falcon->code.data);
+ 			falcon->code.data = NULL;
+ 		}
+ 	}

commit ab9b18a6a13c438505d3419bd59dcd8e1856cedd
+Author: Ilia Mirkin 
+Date:   Fri Nov 15 11:26:45 2013 -0500
+
+    drm/nv04/plane: add support for nv04/nv05 video overlay
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+index ba40c7be3787..ab03f7719d2d 100644
+--- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c
++++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+@@ -55,6 +55,8 @@ struct nouveau_plane {
+ 	int hue;
+ 	int saturation;
+ 	int iturbt_709;
++
++	void (*set_params)(struct nouveau_plane *);
+ };
+ 
+ static uint32_t formats[] = {
+@@ -183,9 +185,9 @@ nv10_disable_plane(struct drm_plane *plane)
+ }
+ 
+ static void
+-nv10_destroy_plane(struct drm_plane *plane)
++nv_destroy_plane(struct drm_plane *plane)
+ {
+-	nv10_disable_plane(plane);
++	plane->funcs->disable_plane(plane);
+ 	drm_plane_cleanup(plane);
+ 	kfree(plane);
+ }
+@@ -218,9 +220,9 @@ nv10_set_params(struct nouveau_plane *plane)
+ }
+ 
+ static int
+-nv10_set_property(struct drm_plane *plane,
+-		  struct drm_property *property,
+-		  uint64_t value)
++nv_set_property(struct drm_plane *plane,
++		struct drm_property *property,
++		uint64_t value)
+ {
+ 	struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane;
+ 
+@@ -239,15 +241,16 @@ nv10_set_property(struct drm_plane *plane,
+ 	else
+ 		return -EINVAL;
+ 
+-	nv10_set_params(nv_plane);
++	if (nv_plane->set_params)
++		nv_plane->set_params(nv_plane);
+ 	return 0;
+ }
+ 
+ static const struct drm_plane_funcs nv10_plane_funcs = {
+ 	.update_plane = nv10_update_plane,
+ 	.disable_plane = nv10_disable_plane,
+-	.set_property = nv10_set_property,
+-	.destroy = nv10_destroy_plane,
++	.set_property = nv_set_property,
++	.destroy = nv_destroy_plane,
+ };
+ 
+ static void
+@@ -322,8 +325,159 @@ nv10_overlay_init(struct drm_device *device)
+ 	drm_object_attach_property(&plane->base.base,
+ 				   plane->props.iturbt_709, plane->iturbt_709);
+ 
++	plane->set_params = nv10_set_params;
+ 	nv10_set_params(plane);
+-	nv_wr32(dev, NV_PVIDEO_STOP, 1);
++	nv10_disable_plane(&plane->base);
++	return;
++cleanup:
++	drm_plane_cleanup(&plane->base);
++err:
++	kfree(plane);
++	nv_error(dev, "Failed to create plane\n");
++}
++
++static int
++nv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
++		  struct drm_framebuffer *fb, int crtc_x, int crtc_y,
++		  unsigned int crtc_w, unsigned int crtc_h,
++		  uint32_t src_x, uint32_t src_y,
++		  uint32_t src_w, uint32_t src_h)
++{
++	struct nouveau_device *dev = nouveau_dev(plane->dev);
++	struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane;
++	struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb);
++	struct nouveau_bo *cur = nv_plane->cur;
++	uint32_t overlay = 1;
++	int brightness = (nv_plane->brightness - 512) * 62 / 512;
++	int pitch, ret, i;
++
++	/* Source parameters given in 16.16 fixed point, ignore fractional. */
++	src_x >>= 16;
++	src_y >>= 16;
++	src_w >>= 16;
++	src_h >>= 16;
++
++	pitch = ALIGN(src_w * 4, 0x100);
++
++	if (pitch > 0xffff)
++		return -ERANGE;
++
++	/* TODO: Compute an offset? Not sure how to do this for YUYV. */
++	if (src_x != 0 || src_y != 0)
++		return -ERANGE;
++
++	if (crtc_w < src_w || crtc_h < src_h)
++		return -ERANGE;
++
++	ret = nouveau_bo_pin(nv_fb->nvbo, TTM_PL_FLAG_VRAM);
++	if (ret)
++		return ret;
++
++	nv_plane->cur = nv_fb->nvbo;
++
++	nv_wr32(dev, NV_PVIDEO_OE_STATE, 0);
++	nv_wr32(dev, NV_PVIDEO_SU_STATE, 0);
++	nv_wr32(dev, NV_PVIDEO_RM_STATE, 0);
++
++	for (i = 0; i < 2; i++) {
++		nv_wr32(dev, NV_PVIDEO_BUFF0_START_ADDRESS + 4 * i,
++			nv_fb->nvbo->bo.offset);
++		nv_wr32(dev, NV_PVIDEO_BUFF0_PITCH_LENGTH + 4 * i, pitch);
++		nv_wr32(dev, NV_PVIDEO_BUFF0_OFFSET + 4 * i, 0);
++	}
++	nv_wr32(dev, NV_PVIDEO_WINDOW_START, crtc_y << 16 | crtc_x);
++	nv_wr32(dev, NV_PVIDEO_WINDOW_SIZE, crtc_h << 16 | crtc_w);
++	nv_wr32(dev, NV_PVIDEO_STEP_SIZE,
++		(uint32_t)(((src_h - 1) << 11) / (crtc_h - 1)) << 16 | (uint32_t)(((src_w - 1) << 11) / (crtc_w - 1)));
++
++	/* It should be possible to convert hue/contrast to this */
++	nv_wr32(dev, NV_PVIDEO_RED_CSC_OFFSET, 0x69 - brightness);
++	nv_wr32(dev, NV_PVIDEO_GREEN_CSC_OFFSET, 0x3e + brightness);
++	nv_wr32(dev, NV_PVIDEO_BLUE_CSC_OFFSET, 0x89 - brightness);
++	nv_wr32(dev, NV_PVIDEO_CSC_ADJUST, 0);
++
++	nv_wr32(dev, NV_PVIDEO_CONTROL_Y, 0x001); /* (BLUR_ON, LINE_HALF) */
++	nv_wr32(dev, NV_PVIDEO_CONTROL_X, 0x111); /* (WEIGHT_HEAVY, SHARPENING_ON, SMOOTHING_ON) */
++
++	nv_wr32(dev, NV_PVIDEO_FIFO_BURST_LENGTH, 0x03);
++	nv_wr32(dev, NV_PVIDEO_FIFO_THRES_SIZE, 0x38);
++
++	nv_wr32(dev, NV_PVIDEO_KEY, nv_plane->colorkey);
++
++	if (nv_plane->colorkey & (1 << 24))
++		overlay |= 0x10;
++	if (fb->pixel_format == DRM_FORMAT_YUYV)
++		overlay |= 0x100;
++
++	nv_wr32(dev, NV_PVIDEO_OVERLAY, overlay);
++
++	nv_wr32(dev, NV_PVIDEO_SU_STATE, nv_rd32(dev, NV_PVIDEO_SU_STATE) ^ (1 << 16));
++
++	if (cur)
++		nouveau_bo_unpin(cur);
++
++	return 0;
++}
++
++static int
++nv04_disable_plane(struct drm_plane *plane)
++{
++	struct nouveau_device *dev = nouveau_dev(plane->dev);
++	struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane;
++
++	nv_mask(dev, NV_PVIDEO_OVERLAY, 1, 0);
++	nv_wr32(dev, NV_PVIDEO_OE_STATE, 0);
++	nv_wr32(dev, NV_PVIDEO_SU_STATE, 0);
++	nv_wr32(dev, NV_PVIDEO_RM_STATE, 0);
++	if (nv_plane->cur) {
++		nouveau_bo_unpin(nv_plane->cur);
++		nv_plane->cur = NULL;
++	}
++
++	return 0;
++}
++
++static const struct drm_plane_funcs nv04_plane_funcs = {
++	.update_plane = nv04_update_plane,
++	.disable_plane = nv04_disable_plane,
++	.set_property = nv_set_property,
++	.destroy = nv_destroy_plane,
++};
++
++static void
++nv04_overlay_init(struct drm_device *device)
++{
++	struct nouveau_device *dev = nouveau_dev(device);
++	struct nouveau_plane *plane = kzalloc(sizeof(struct nouveau_plane), GFP_KERNEL);
++	int ret;
++
++	if (!plane)
++		return;
++
++	ret = drm_plane_init(device, &plane->base, 1 /* single crtc */,
++			     &nv04_plane_funcs,
++			     formats, 2, false);
++	if (ret)
++		goto err;
++
++	/* Set up the plane properties */
++	plane->props.colorkey = drm_property_create_range(
++			device, 0, "colorkey", 0, 0x01ffffff);
++	plane->props.brightness = drm_property_create_range(
++			device, 0, "brightness", 0, 1024);
++	if (!plane->props.colorkey ||
++	    !plane->props.brightness)
++		goto cleanup;
++
++	plane->colorkey = 0;
++	drm_object_attach_property(&plane->base.base,
++				   plane->props.colorkey, plane->colorkey);
++
++	plane->brightness = 512;
++	drm_object_attach_property(&plane->base.base,
++				   plane->props.brightness, plane->brightness);
++
++	nv04_disable_plane(&plane->base);
+ 	return;
+ cleanup:
+ 	drm_plane_cleanup(&plane->base);
+@@ -336,6 +490,8 @@ void
+ nouveau_overlay_init(struct drm_device *device)
+ {
+ 	struct nouveau_device *dev = nouveau_dev(device);
+-	if (dev->chipset >= 0x10 && dev->chipset <= 0x40)
++	if (dev->chipset < 0x10)
++		nv04_overlay_init(device);
++	else if (dev->chipset <= 0x40)
+ 		nv10_overlay_init(device);
+ }

commit 7ffb078172d6906c4712914321c551d4f595875f
+Author: Ilia Mirkin 
+Date:   Fri Nov 15 11:26:44 2013 -0500
+
+    drm/nv10/plane: add YUYV support
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+index 32e7064b819b..ba40c7be3787 100644
+--- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c
++++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+@@ -58,6 +58,7 @@ struct nouveau_plane {
+ };
+ 
+ static uint32_t formats[] = {
++	DRM_FORMAT_YUYV,
+ 	DRM_FORMAT_UYVY,
+ 	DRM_FORMAT_NV12,
+ };
+@@ -140,10 +141,10 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+ 	nv_wr32(dev, NV_PVIDEO_POINT_OUT(flip), crtc_y << 16 | crtc_x);
+ 	nv_wr32(dev, NV_PVIDEO_SIZE_OUT(flip), crtc_h << 16 | crtc_w);
+ 
+-	if (fb->pixel_format == DRM_FORMAT_NV12) {
++	if (fb->pixel_format != DRM_FORMAT_UYVY)
+ 		format |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8;
++	if (fb->pixel_format == DRM_FORMAT_NV12)
+ 		format |= NV_PVIDEO_FORMAT_PLANAR;
+-	}
+ 	if (nv_plane->iturbt_709)
+ 		format |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
+ 	if (nv_plane->colorkey & (1 << 24))
+@@ -266,7 +267,7 @@ nv10_overlay_init(struct drm_device *device)
+ 	case 0x15:
+ 	case 0x1a:
+ 	case 0x20:
+-		num_formats = 1;
++		num_formats = 2;
+ 		break;
+ 	}
+ 

commit 710d86f8bc4515a906799b85135e6f6962703e01
+Author: Ilia Mirkin 
+Date:   Fri Dec 6 18:56:53 2013 -0500
+
+    MIPS: BCM47XX: Fix some very confused types and data corruption
+    
+    Fix nvram_read_alpha2 copying too many bytes over the ssb_sprom
+    structure. Also fix the arguments of the read_macaddr, although the code
+    was technically not wrong before due to an extra dereference.
+    
+    Signed-off-by: Ilia Mirkin 
+    Acked-by: Hauke Mehrtens 
+    Signed-off-by: John Crispin 
+    Patchwork: http://patchwork.linux-mips.org/patch/6211/
+
+diff --git a/arch/mips/bcm47xx/sprom.c b/arch/mips/bcm47xx/sprom.c
+index ad03c931b905..a8b5408dd349 100644
+--- a/arch/mips/bcm47xx/sprom.c
++++ b/arch/mips/bcm47xx/sprom.c
+@@ -135,7 +135,7 @@ static void nvram_read_leddc(const char *prefix, const char *name,
+ }
+ 
+ static void nvram_read_macaddr(const char *prefix, const char *name,
+-			       u8 (*val)[6], bool fallback)
++			       u8 val[6], bool fallback)
+ {
+ 	char buf[100];
+ 	int err;
+@@ -144,11 +144,11 @@ static void nvram_read_macaddr(const char *prefix, const char *name,
+ 	if (err < 0)
+ 		return;
+ 
+-	bcm47xx_nvram_parse_macaddr(buf, *val);
++	bcm47xx_nvram_parse_macaddr(buf, val);
+ }
+ 
+ static void nvram_read_alpha2(const char *prefix, const char *name,
+-			     char (*val)[2], bool fallback)
++			     char val[2], bool fallback)
+ {
+ 	char buf[10];
+ 	int err;
+@@ -162,7 +162,7 @@ static void nvram_read_alpha2(const char *prefix, const char *name,
+ 		pr_warn("alpha2 is too long %s\n", buf);
+ 		return;
+ 	}
+-	memcpy(val, buf, sizeof(val));
++	memcpy(val, buf, 2);
+ }
+ 
+ static void bcm47xx_fill_sprom_r1234589(struct ssb_sprom *sprom,
+@@ -180,7 +180,7 @@ static void bcm47xx_fill_sprom_r1234589(struct ssb_sprom *sprom,
+ 		      fallback);
+ 	nvram_read_s8(prefix, NULL, "ag1", &sprom->antenna_gain.a1, 0,
+ 		      fallback);
+-	nvram_read_alpha2(prefix, "ccode", &sprom->alpha2, fallback);
++	nvram_read_alpha2(prefix, "ccode", sprom->alpha2, fallback);
+ }
+ 
+ static void bcm47xx_fill_sprom_r12389(struct ssb_sprom *sprom,
+@@ -633,20 +633,20 @@ static void bcm47xx_fill_sprom_path_r45(struct ssb_sprom *sprom,
+ static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom,
+ 					const char *prefix, bool fallback)
+ {
+-	nvram_read_macaddr(prefix, "et0macaddr", &sprom->et0mac, fallback);
++	nvram_read_macaddr(prefix, "et0macaddr", sprom->et0mac, fallback);
+ 	nvram_read_u8(prefix, NULL, "et0mdcport", &sprom->et0mdcport, 0,
+ 		      fallback);
+ 	nvram_read_u8(prefix, NULL, "et0phyaddr", &sprom->et0phyaddr, 0,
+ 		      fallback);
+ 
+-	nvram_read_macaddr(prefix, "et1macaddr", &sprom->et1mac, fallback);
++	nvram_read_macaddr(prefix, "et1macaddr", sprom->et1mac, fallback);
+ 	nvram_read_u8(prefix, NULL, "et1mdcport", &sprom->et1mdcport, 0,
+ 		      fallback);
+ 	nvram_read_u8(prefix, NULL, "et1phyaddr", &sprom->et1phyaddr, 0,
+ 		      fallback);
+ 
+-	nvram_read_macaddr(prefix, "macaddr", &sprom->il0mac, fallback);
+-	nvram_read_macaddr(prefix, "il0macaddr", &sprom->il0mac, fallback);
++	nvram_read_macaddr(prefix, "macaddr", sprom->il0mac, fallback);
++	nvram_read_macaddr(prefix, "il0macaddr", sprom->il0mac, fallback);
+ }
+ 
+ static void bcm47xx_fill_board_data(struct ssb_sprom *sprom, const char *prefix,

commit 72de182362e013b2c2cc92092d97fff58e429d5d
+Author: Ilia Mirkin 
+Date:   Sun Jan 19 10:30:32 2014 -0500
+
+    drm/nouveau/mxm: fix null deref on load
+    
+    Since commit 61b365a505d6 ("drm/nouveau: populate master subdev pointer
+    only when fully constructed"), the nouveau_mxm(bios) call will return
+    NULL, since it's still being called from the constructor.  Instead, pass
+    the mxm pointer via the unused data field.
+    
+    See https://bugs.freedesktop.org/show_bug.cgi?id=73791
+    
+    Reported-by: Andreas Reis 
+    Tested-by: Andreas Reis 
+    Signed-off-by: Ilia Mirkin 
+    Cc: Ben Skeggs 
+    Cc: Dave Airlie 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c
+index af129c2e8113..64f8b4702bf7 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c
+@@ -100,7 +100,7 @@ mxm_match_dcb(struct nouveau_mxm *mxm, u8 *data, void *info)
+ static int
+ mxm_dcb_sanitise_entry(struct nouveau_bios *bios, void *data, int idx, u16 pdcb)
+ {
+-	struct nouveau_mxm *mxm = nouveau_mxm(bios);
++	struct nouveau_mxm *mxm = data;
+ 	struct context ctx = { .outp = (u32 *)(bios->data + pdcb) };
+ 	u8 type, i2cidx, link, ver, len;
+ 	u8 *conn;
+@@ -199,7 +199,7 @@ mxm_dcb_sanitise(struct nouveau_mxm *mxm)
+ 		return;
+ 	}
+ 
+-	dcb_outp_foreach(bios, NULL, mxm_dcb_sanitise_entry);
++	dcb_outp_foreach(bios, mxm, mxm_dcb_sanitise_entry);
+ 	mxms_foreach(mxm, 0x01, mxm_show_unmatched, NULL);
+ }
+ 

commit 5d2f4767c4eacab351b8450b0de4d3261fe1a957
+Author: Ilia Mirkin 
+Date:   Tue Jan 7 12:33:59 2014 -0500
+
+    drm/nouveau/bios: fix offset calculation for BMPv1 bioses
+    
+    The only BIOS on record that needs the 14 offset has a bios major
+    version 2 but BMP version 1.01. Another bunch of BIOSes that need the 18
+    offset have BMP version 2.01 or 5.01 or higher. So instead of looking at the
+    bios major version, look at the BMP version. BIOSes with BMP version 0
+    do not contain a detectable script, so always return 0 for them.
+    
+    See https://bugs.freedesktop.org/show_bug.cgi?id=68835
+    
+    Reported-by: Mauro Molinari 
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
+index 9f5b81e99731..df1b1b423093 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
+@@ -365,13 +365,13 @@ static u16
+ init_script(struct nouveau_bios *bios, int index)
+ {
+ 	struct nvbios_init init = { .bios = bios };
+-	u16 data;
++	u16 bmp_ver = bmp_version(bios), data;
+ 
+-	if (bmp_version(bios) && bmp_version(bios) < 0x0510) {
+-		if (index > 1)
++	if (bmp_ver && bmp_ver < 0x0510) {
++		if (index > 1 || bmp_ver < 0x0100)
+ 			return 0x0000;
+ 
+-		data = bios->bmp_offset + (bios->version.major < 2 ? 14 : 18);
++		data = bios->bmp_offset + (bmp_ver < 0x0200 ? 14 : 18);
+ 		return nv_ro16(bios, data + (index * 2));
+ 	}
+ 

commit 6d60792ec059d9f2139828f9f017679abb81aa73
+Author: Ilia Mirkin 
+Date:   Sun Jan 5 20:07:02 2014 -0500
+
+    drm/nouveau/bios: make jump conditional
+    
+    This fixes a hang in VBIOS scripts of the form "condition; jump".
+    The jump used to always be executed, while now it will only be
+    executed if the condition is true.
+    
+    See https://bugs.freedesktop.org/show_bug.cgi?id=72943
+    
+    Reported-by: Darcy Brás da Silva 
+    Signed-off-by: Ilia Mirkin 
+    Cc: stable@vger.kernel.org
+
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
+index 420908cb82b6..9f5b81e99731 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
+@@ -1294,7 +1294,11 @@ init_jump(struct nvbios_init *init)
+ 	u16 offset = nv_ro16(bios, init->offset + 1);
+ 
+ 	trace("JUMP\t0x%04x\n", offset);
+-	init->offset = offset;
++
++	if (init_exec(init))
++		init->offset = offset;
++	else
++		init->offset += 3;
+ }
+ 
+ /**

commit b25b4427e9dfba073cf9bc86603956ed395eb6e3
+Author: Ilia Mirkin 
+Date:   Wed Dec 11 22:19:01 2013 -0500
+
+    drm/nouveau: only runtime suspend by default in optimus configuration
+    
+    The intent was to only enable it by default for optimus, e.g. see the
+    runtime_idle callback. The suspend callback may be called directly, e.g.
+    as a result of nouveau_crtc_set_config.
+    
+    Reported-by: Stefan Lippers-Hollmann 
+    Signed-off-by: Ilia Mirkin 
+    Tested-by: Stefan Lippers-Hollmann 
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Dave Airlie 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
+index 7a3759f1c41a..98a22e6e27a1 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
++++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
+@@ -858,6 +858,12 @@ static int nouveau_pmops_runtime_suspend(struct device *dev)
+ 	if (nouveau_runtime_pm == 0)
+ 		return -EINVAL;
+ 
++	/* are we optimus enabled? */
++	if (nouveau_runtime_pm == -1 && !nouveau_is_optimus() && !nouveau_is_v1_dsm()) {
++		DRM_DEBUG_DRIVER("failing to power off - not optimus\n");
++		return -EINVAL;
++	}
++
+ 	nv_debug_level(SILENT);
+ 	drm_kms_helper_poll_disable(drm_dev);
+ 	vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF);

commit 0f58411d4fd704d8958879fb08751eae3573271b
+Author: Ilia Mirkin 
+Date:   Thu Dec 5 09:42:49 2013 -0500
+
+    drm: don't double-free on driver load error
+    
+    All instances of drm_dev_register are followed by drm_dev_free on
+    failure. Don't free dev->control/render/primary on failure, as they will
+    be freed by drm_dev_free since commit 8f6599da8e (drm: delay minor
+    destruction to drm_dev_free()). Instead unplug them.
+    
+    Signed-off-by: Ilia Mirkin 
+    Reported-and-tested-by: Bruno Prémont 
+    Reviewed-by: David Herrmann 
+    Signed-off-by: Dave Airlie 
+
+diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
+index f53d5246979c..66dd3a001cf1 100644
+--- a/drivers/gpu/drm/drm_stub.c
++++ b/drivers/gpu/drm/drm_stub.c
+@@ -566,11 +566,11 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
+ 	if (dev->driver->unload)
+ 		dev->driver->unload(dev);
+ err_primary_node:
+-	drm_put_minor(dev->primary);
++	drm_unplug_minor(dev->primary);
+ err_render_node:
+-	drm_put_minor(dev->render);
++	drm_unplug_minor(dev->render);
+ err_control_node:
+-	drm_put_minor(dev->control);
++	drm_unplug_minor(dev->control);
+ err_agp:
+ 	if (dev->driver->bus->agp_destroy)
+ 		dev->driver->bus->agp_destroy(dev);

commit 1b429835be7ce514b36b551e785d425fd56cd1f2
+Author: Ilia Mirkin 
+Date:   Fri Dec 6 19:43:37 2013 -0500
+
+    powerpc/44x: Fix ocm_block allocation
+    
+    Allocate enough memory for the ocm_block structure, not just a pointer
+    to it.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Benjamin Herrenschmidt 
+
+diff --git a/arch/powerpc/sysdev/ppc4xx_ocm.c b/arch/powerpc/sysdev/ppc4xx_ocm.c
+index b7c43453236d..85d9e37f5ccb 100644
+--- a/arch/powerpc/sysdev/ppc4xx_ocm.c
++++ b/arch/powerpc/sysdev/ppc4xx_ocm.c
+@@ -339,7 +339,7 @@ void *ppc4xx_ocm_alloc(phys_addr_t *phys, int size, int align,
+ 		if (IS_ERR_VALUE(offset))
+ 			continue;
+ 
+-		ocm_blk = kzalloc(sizeof(struct ocm_block *), GFP_KERNEL);
++		ocm_blk = kzalloc(sizeof(struct ocm_block), GFP_KERNEL);
+ 		if (!ocm_blk) {
+ 			printk(KERN_ERR "PPC4XX OCM: could not allocate ocm block");
+ 			rh_free(ocm_reg->rh, offset);

commit efffa9841cf42ae8350d421070cea962b063df8c
+Author: Ilia Mirkin 
+Date:   Fri Nov 15 11:26:43 2013 -0500
+
+    drm/nv10/plane: some chipsets don't support NV12
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+index c14afb794147..32e7064b819b 100644
+--- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c
++++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+@@ -58,8 +58,8 @@ struct nouveau_plane {
+ };
+ 
+ static uint32_t formats[] = {
+-	DRM_FORMAT_NV12,
+ 	DRM_FORMAT_UYVY,
++	DRM_FORMAT_NV12,
+ };
+ 
+ /* Sine can be approximated with
+@@ -254,14 +254,25 @@ nv10_overlay_init(struct drm_device *device)
+ {
+ 	struct nouveau_device *dev = nouveau_dev(device);
+ 	struct nouveau_plane *plane = kzalloc(sizeof(struct nouveau_plane), GFP_KERNEL);
++	int num_formats = ARRAY_SIZE(formats);
+ 	int ret;
+ 
+ 	if (!plane)
+ 		return;
+ 
++	switch (dev->chipset) {
++	case 0x10:
++	case 0x11:
++	case 0x15:
++	case 0x1a:
++	case 0x20:
++		num_formats = 1;
++		break;
++	}
++
+ 	ret = drm_plane_init(device, &plane->base, 3 /* both crtc's */,
+ 			     &nv10_plane_funcs,
+-			     formats, ARRAY_SIZE(formats), false);
++			     formats, num_formats, false);
+ 	if (ret)
+ 		goto err;
+ 

commit 050828e9563d03cbaab950c16ae4aebaa02ff0de
+Author: Ilia Mirkin 
+Date:   Fri Nov 15 11:26:42 2013 -0500
+
+    drm/nv10/plane: add downscaling restrictions
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+index 514a3055903c..c14afb794147 100644
+--- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c
++++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+@@ -112,7 +112,15 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+ 	format = ALIGN(src_w * 4, 0x100);
+ 
+ 	if (format > 0xffff)
+-		return -EINVAL;
++		return -ERANGE;
++
++	if (dev->chipset >= 0x30) {
++		if (crtc_w < (src_w >> 1) || crtc_h < (src_h >> 1))
++			return -ERANGE;
++	} else {
++		if (crtc_w < (src_w >> 3) || crtc_h < (src_h >> 3))
++			return -ERANGE;
++	}
+ 
+ 	ret = nouveau_bo_pin(nv_fb->nvbo, TTM_PL_FLAG_VRAM);
+ 	if (ret)

commit 92e5b0a2b121c29eac31e6d8106ceefa31de46a9
+Author: Ilia Mirkin 
+Date:   Fri Nov 15 11:26:41 2013 -0500
+
+    drm/nv10/plane: fix format computation
+    
+    Otherwise none of the format checks pass, since the width was still in
+    16.16 encoding.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+index 3618ac6b6316..514a3055903c 100644
+--- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c
++++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+@@ -99,10 +99,17 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+ 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+ 	struct nouveau_bo *cur = nv_plane->cur;
+ 	bool flip = nv_plane->flip;
+-	int format = ALIGN(src_w * 4, 0x100);
+ 	int soff = NV_PCRTC0_SIZE * nv_crtc->index;
+ 	int soff2 = NV_PCRTC0_SIZE * !nv_crtc->index;
+-	int ret;
++	int format, ret;
++
++	/* Source parameters given in 16.16 fixed point, ignore fractional. */
++	src_x >>= 16;
++	src_y >>= 16;
++	src_w >>= 16;
++	src_h >>= 16;
++
++	format = ALIGN(src_w * 4, 0x100);
+ 
+ 	if (format > 0xffff)
+ 		return -EINVAL;
+@@ -113,12 +120,6 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+ 
+ 	nv_plane->cur = nv_fb->nvbo;
+ 
+-	/* Source parameters given in 16.16 fixed point, ignore fractional. */
+-	src_x = src_x >> 16;
+-	src_y = src_y >> 16;
+-	src_w = src_w >> 16;
+-	src_h = src_h >> 16;
+-
+ 	nv_mask(dev, NV_PCRTC_ENGINE_CTRL + soff, NV_CRTC_FSEL_OVERLAY, NV_CRTC_FSEL_OVERLAY);
+ 	nv_mask(dev, NV_PCRTC_ENGINE_CTRL + soff2, NV_CRTC_FSEL_OVERLAY, 0);
+ 

commit eec99016e38b740662509f097effb90abc7a1376
+Author: Ilia Mirkin 
+Date:   Wed Nov 27 12:38:42 2013 -0500
+
+    drm/nouveau/hwmon: fix compilation without CONFIG_HWMON
+    
+    Reported-by: Jim Davis 
+    Tested-by: Jim Davis 
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Dave Airlie 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_hwmon.c b/drivers/gpu/drm/nouveau/nouveau_hwmon.c
+index 38a4db5bfe21..4aff04fa483c 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_hwmon.c
++++ b/drivers/gpu/drm/nouveau/nouveau_hwmon.c
+@@ -630,7 +630,6 @@ nouveau_hwmon_init(struct drm_device *dev)
+ 	hwmon->hwmon = NULL;
+ 	return ret;
+ #else
+-	hwmon->hwmon = NULL;
+ 	return 0;
+ #endif
+ }

commit fd34381b0e2827228cbda45aa2cca4127ff073b2
+Author: Ilia Mirkin 
+Date:   Sun Oct 27 11:54:09 2013 -0400
+
+    drm/nouveau/agp: add a quirk list to limit agp modes
+    
+    Certain combinations of hardware can't actually support the maximum
+    detected speed. Add a quirk list that lists pairs of hostbridge/chip pci
+    ids and the mode that they should work with.
+    
+    See https://bugs.freedesktop.org/show_bug.cgi?id=20341
+    
+    Reported-by: Jason Detring 
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_agp.c b/drivers/gpu/drm/nouveau/nouveau_agp.c
+index 6e7a55f93a85..2953c4e91e1a 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_agp.c
++++ b/drivers/gpu/drm/nouveau/nouveau_agp.c
+@@ -11,10 +11,28 @@ MODULE_PARM_DESC(agpmode, "AGP mode (0 to disable AGP)");
+ static int nouveau_agpmode = -1;
+ module_param_named(agpmode, nouveau_agpmode, int, 0400);
+ 
++struct nouveau_agpmode_quirk {
++	u16 hostbridge_vendor;
++	u16 hostbridge_device;
++	u16 chip_vendor;
++	u16 chip_device;
++	int mode;
++};
++
++static struct nouveau_agpmode_quirk nouveau_agpmode_quirk_list[] = {
++	/* VIA Apollo PRO133x / GeForce FX 5600 Ultra, max agpmode 2, fdo #20341 */
++	{ PCI_VENDOR_ID_VIA, 0x0691, PCI_VENDOR_ID_NVIDIA, 0x0311, 2 },
++
++	{},
++};
++
+ static unsigned long
+-get_agp_mode(struct nouveau_drm *drm, unsigned long mode)
++get_agp_mode(struct nouveau_drm *drm, const struct drm_agp_info *info)
+ {
+ 	struct nouveau_device *device = nv_device(drm->device);
++	struct nouveau_agpmode_quirk *quirk = nouveau_agpmode_quirk_list;
++	int agpmode = nouveau_agpmode;
++	unsigned long mode = info->mode;
+ 
+ 	/*
+ 	 * FW seems to be broken on nv18, it makes the card lock up
+@@ -23,12 +41,28 @@ get_agp_mode(struct nouveau_drm *drm, unsigned long mode)
+ 	if (device->chipset == 0x18)
+ 		mode &= ~PCI_AGP_COMMAND_FW;
+ 
++	/*
++	 * Go through the quirks list and adjust the agpmode accordingly.
++	 */
++	while (agpmode == -1 && quirk->hostbridge_vendor) {
++		if (info->id_vendor == quirk->hostbridge_vendor &&
++		    info->id_device == quirk->hostbridge_device &&
++		    device->pdev->vendor == quirk->chip_vendor &&
++		    device->pdev->device == quirk->chip_device) {
++			agpmode = quirk->mode;
++			nv_info(device, "Forcing agp mode to %dX. Use agpmode to override.\n",
++				agpmode);
++			break;
++		}
++		++quirk;
++	}
++
+ 	/*
+ 	 * AGP mode set in the command line.
+ 	 */
+-	if (nouveau_agpmode > 0) {
++	if (agpmode > 0) {
+ 		bool agpv3 = mode & 0x8;
+-		int rate = agpv3 ? nouveau_agpmode / 4 : nouveau_agpmode;
++		int rate = agpv3 ? agpmode / 4 : agpmode;
+ 
+ 		mode = (mode & ~0x7) | (rate & 0x7);
+ 	}
+@@ -90,7 +124,7 @@ nouveau_agp_reset(struct nouveau_drm *drm)
+ 		if (ret)
+ 			return;
+ 
+-		mode.mode  = get_agp_mode(drm, info.mode);
++		mode.mode  = get_agp_mode(drm, &info);
+ 		mode.mode &= ~PCI_AGP_COMMAND_FW;
+ 
+ 		ret = drm_agp_enable(dev, mode);
+@@ -139,7 +173,7 @@ nouveau_agp_init(struct nouveau_drm *drm)
+ 	}
+ 
+ 	/* see agp.h for the AGPSTAT_* modes available */
+-	mode.mode = get_agp_mode(drm, info.mode);
++	mode.mode = get_agp_mode(drm, &info);
+ 
+ 	ret = drm_agp_enable(dev, mode);
+ 	if (ret) {

commit be0dd4ddefebb35915979e280047eb6f5ecc3235
+Author: Ilia Mirkin 
+Date:   Sat Sep 7 21:04:12 2013 -0400
+
+    drm/nv31/mpeg: split the nv31 and nv40 dma setting implementations
+    
+    NV31 has different config bits than NV40+ do. Also fix the DMA_IMAGE
+    VRAM-only setting to check the right bits.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
+index 9330fc42bd89..77b630867010 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
++++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
+@@ -80,18 +80,18 @@ nv31_mpeg_mthd_dma(struct nouveau_object *object, u32 mthd, void *arg, u32 len)
+ 
+ 	if (mthd == 0x0190) {
+ 		/* DMA_CMD */
+-		nv_mask(priv, 0x00b300, 0x00030000, (dma0 & 0x00030000));
++		nv_mask(priv, 0x00b300, 0x00010000, (dma0 & 0x00030000) ? 0x00010000 : 0);
+ 		nv_wr32(priv, 0x00b334, base);
+ 		nv_wr32(priv, 0x00b324, size);
+ 	} else
+ 	if (mthd == 0x01a0) {
+ 		/* DMA_DATA */
+-		nv_mask(priv, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2);
++		nv_mask(priv, 0x00b300, 0x00020000, (dma0 & 0x00030000) ? 0x00020000 : 0);
+ 		nv_wr32(priv, 0x00b360, base);
+ 		nv_wr32(priv, 0x00b364, size);
+ 	} else {
+ 		/* DMA_IMAGE, VRAM only */
+-		if (dma0 & 0x000c0000)
++		if (dma0 & 0x00030000)
+ 			return -EINVAL;
+ 
+ 		nv_wr32(priv, 0x00b370, base);
+@@ -101,7 +101,7 @@ nv31_mpeg_mthd_dma(struct nouveau_object *object, u32 mthd, void *arg, u32 len)
+ 	return 0;
+ }
+ 
+-static struct nouveau_ofuncs
++struct nouveau_ofuncs
+ nv31_mpeg_ofuncs = {
+ 	.ctor = nv31_mpeg_object_ctor,
+ 	.dtor = _nouveau_gpuobj_dtor,
+diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c
+index 26f3262c0b2a..d4e7ec0ba68c 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c
++++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c
+@@ -33,6 +33,63 @@
+ #include 
+ #include 
+ 
++/*******************************************************************************
++ * MPEG object classes
++ ******************************************************************************/
++
++static int
++nv40_mpeg_mthd_dma(struct nouveau_object *object, u32 mthd, void *arg, u32 len)
++{
++	struct nouveau_instmem *imem = nouveau_instmem(object);
++	struct nv31_mpeg_priv *priv = (void *)object->engine;
++	u32 inst = *(u32 *)arg << 4;
++	u32 dma0 = nv_ro32(imem, inst + 0);
++	u32 dma1 = nv_ro32(imem, inst + 4);
++	u32 dma2 = nv_ro32(imem, inst + 8);
++	u32 base = (dma2 & 0xfffff000) | (dma0 >> 20);
++	u32 size = dma1 + 1;
++
++	/* only allow linear DMA objects */
++	if (!(dma0 & 0x00002000))
++		return -EINVAL;
++
++	if (mthd == 0x0190) {
++		/* DMA_CMD */
++		nv_mask(priv, 0x00b300, 0x00030000, (dma0 & 0x00030000));
++		nv_wr32(priv, 0x00b334, base);
++		nv_wr32(priv, 0x00b324, size);
++	} else
++	if (mthd == 0x01a0) {
++		/* DMA_DATA */
++		nv_mask(priv, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2);
++		nv_wr32(priv, 0x00b360, base);
++		nv_wr32(priv, 0x00b364, size);
++	} else {
++		/* DMA_IMAGE, VRAM only */
++		if (dma0 & 0x00030000)
++			return -EINVAL;
++
++		nv_wr32(priv, 0x00b370, base);
++		nv_wr32(priv, 0x00b374, size);
++	}
++
++	return 0;
++}
++
++static struct nouveau_omthds
++nv40_mpeg_omthds[] = {
++	{ 0x0190, 0x0190, nv40_mpeg_mthd_dma },
++	{ 0x01a0, 0x01a0, nv40_mpeg_mthd_dma },
++	{ 0x01b0, 0x01b0, nv40_mpeg_mthd_dma },
++	{}
++};
++
++struct nouveau_oclass
++nv40_mpeg_sclass[] = {
++	{ 0x3174, &nv31_mpeg_ofuncs, nv40_mpeg_omthds },
++	{}
++};
++
+ /*******************************************************************************
+  * PMPEG engine/subdev functions
+  ******************************************************************************/
+@@ -68,7 +125,7 @@ nv40_mpeg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	nv_subdev(priv)->unit = 0x00000002;
+ 	nv_subdev(priv)->intr = nv40_mpeg_intr;
+ 	nv_engine(priv)->cclass = &nv31_mpeg_cclass;
+-	nv_engine(priv)->sclass = nv31_mpeg_sclass;
++	nv_engine(priv)->sclass = nv40_mpeg_sclass;
+ 	nv_engine(priv)->tile_prog = nv31_mpeg_tile_prog;
+ 	return 0;
+ }
+diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv44.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv44.c
+index 012b95d5d4c3..3d8c2133e0e8 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv44.c
++++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv44.c
+@@ -177,7 +177,7 @@ nv44_mpeg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	nv_subdev(priv)->unit = 0x00000002;
+ 	nv_subdev(priv)->intr = nv44_mpeg_me_intr;
+ 	nv_engine(priv)->cclass = &nv44_mpeg_cclass;
+-	nv_engine(priv)->sclass = nv31_mpeg_sclass;
++	nv_engine(priv)->sclass = nv40_mpeg_sclass;
+ 	nv_engine(priv)->tile_prog = nv31_mpeg_tile_prog;
+ 	return 0;
+ }
+diff --git a/drivers/gpu/drm/nouveau/core/include/engine/mpeg.h b/drivers/gpu/drm/nouveau/core/include/engine/mpeg.h
+index 8b7560e2ec19..9b0d938199f6 100644
+--- a/drivers/gpu/drm/nouveau/core/include/engine/mpeg.h
++++ b/drivers/gpu/drm/nouveau/core/include/engine/mpeg.h
+@@ -45,8 +45,10 @@ extern struct nouveau_oclass nv40_mpeg_oclass;
+ extern struct nouveau_oclass nv44_mpeg_oclass;
+ extern struct nouveau_oclass nv50_mpeg_oclass;
+ extern struct nouveau_oclass nv84_mpeg_oclass;
++extern struct nouveau_ofuncs nv31_mpeg_ofuncs;
+ extern struct nouveau_oclass nv31_mpeg_cclass;
+ extern struct nouveau_oclass nv31_mpeg_sclass[];
++extern struct nouveau_oclass nv40_mpeg_sclass[];
+ void nv31_mpeg_intr(struct nouveau_subdev *);
+ void nv31_mpeg_tile_prog(struct nouveau_engine *, int);
+ int  nv31_mpeg_init(struct nouveau_object *);

commit e6585cab68a71a6025f7b6ace2681ebb866a030e
+Author: Ilia Mirkin 
+Date:   Sat Sep 7 21:04:11 2013 -0400
+
+    drm/nv31/mpeg: store chan singleton in engine, use it for dispatch
+    
+    This makes nv31+ able to actually perform the nv_call, since previously
+    the inst was not available.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
+index 2f80b2232232..9330fc42bd89 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
++++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
+@@ -147,6 +147,8 @@ nv31_mpeg_context_ctor(struct nouveau_object *parent,
+ 	if (ret)
+ 		return ret;
+ 
++	priv->chan = chan;
++
+ 	return 0;
+ }
+ 
+@@ -155,8 +157,11 @@ nv31_mpeg_context_dtor(struct nouveau_object *object)
+ {
+ 	struct nv31_mpeg_priv *priv = (void *)object->engine;
+ 	struct nv31_mpeg_chan *chan = (void *)object;
+-	atomic_dec(&priv->refcount);
++
++	WARN_ON(priv->chan != chan);
++	priv->chan = NULL;
+ 	nouveau_object_destroy(&chan->base);
++	atomic_dec(&priv->refcount);
+ }
+ 
+ struct nouveau_oclass
+@@ -189,20 +194,19 @@ void
+ nv31_mpeg_intr(struct nouveau_subdev *subdev)
+ {
+ 	struct nouveau_fifo *pfifo = nouveau_fifo(subdev);
+-	struct nouveau_engine *engine = nv_engine(subdev);
+-	struct nouveau_object *engctx;
+ 	struct nouveau_handle *handle;
+ 	struct nv31_mpeg_priv *priv = (void *)subdev;
+-	u32 inst = nv_rd32(priv, 0x00b318) & 0x000fffff;
++	struct nouveau_object *engctx = &priv->chan->base;
+ 	u32 stat = nv_rd32(priv, 0x00b100);
+ 	u32 type = nv_rd32(priv, 0x00b230);
+ 	u32 mthd = nv_rd32(priv, 0x00b234);
+ 	u32 data = nv_rd32(priv, 0x00b238);
+ 	u32 show = stat;
+-	int chid;
++	int chid = pfifo->chid(pfifo, engctx);
+ 
+-	engctx = nouveau_engctx_get(engine, inst);
+-	chid   = pfifo->chid(pfifo, engctx);
++	if (engctx)
++		if (nouveau_object_inc(engctx))
++			engctx = NULL;
+ 
+ 	if (stat & 0x01000000) {
+ 		/* happens on initial binding of the object */
+@@ -211,7 +215,7 @@ nv31_mpeg_intr(struct nouveau_subdev *subdev)
+ 			show &= ~0x01000000;
+ 		}
+ 
+-		if (type == 0x00000010) {
++		if (type == 0x00000010 && engctx) {
+ 			handle = nouveau_handle_get_class(engctx, 0x3174);
+ 			if (handle && !nv_call(handle->object, mthd, data))
+ 				show &= ~0x01000000;
+@@ -224,12 +228,13 @@ nv31_mpeg_intr(struct nouveau_subdev *subdev)
+ 
+ 	if (show) {
+ 		nv_error(priv,
+-			 "ch %d [0x%08x %s] 0x%08x 0x%08x 0x%08x 0x%08x\n",
+-			 chid, inst << 4, nouveau_client_name(engctx), stat,
++			 "ch %d [%s] 0x%08x 0x%08x 0x%08x 0x%08x\n",
++			 chid, nouveau_client_name(engctx), stat,
+ 			 type, mthd, data);
+ 	}
+ 
+-	nouveau_engctx_put(engctx);
++	if (engctx)
++		WARN_ON(nouveau_object_dec(engctx, false));
+ }
+ 
+ static int
+diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.h b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.h
+index a488c13bffd6..62d04e475315 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.h
++++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.h
+@@ -3,13 +3,14 @@
+ 
+ #include 
+ 
++struct nv31_mpeg_chan {
++	struct nouveau_object base;
++};
++
+ struct nv31_mpeg_priv {
+ 	struct nouveau_mpeg base;
+ 	atomic_t refcount;
+-};
+-
+-struct nv31_mpeg_chan {
+-	struct nouveau_object base;
++	struct nv31_mpeg_chan *chan;
+ };
+ 
+ #endif

commit 912de74c811fa5ba523bf1e525ce8ce45ecfeed4
+Author: Ilia Mirkin 
+Date:   Sat Sep 7 21:04:10 2013 -0400
+
+    drm/nv40/mpeg: use the nv31-provided classes
+    
+    Since nv40 only covers pre-nv44 now, it can use the nv31-provided
+    functions.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
+index 5c54aa10cc0a..2f80b2232232 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
++++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
+@@ -34,15 +34,7 @@
+ 
+ #include 
+ #include 
+-
+-struct nv31_mpeg_priv {
+-	struct nouveau_mpeg base;
+-	atomic_t refcount;
+-};
+-
+-struct nv31_mpeg_chan {
+-	struct nouveau_object base;
+-};
++#include 
+ 
+ /*******************************************************************************
+  * MPEG object classes
+@@ -167,7 +159,7 @@ nv31_mpeg_context_dtor(struct nouveau_object *object)
+ 	nouveau_object_destroy(&chan->base);
+ }
+ 
+-static struct nouveau_oclass
++struct nouveau_oclass
+ nv31_mpeg_cclass = {
+ 	.handle = NV_ENGCTX(MPEG, 0x31),
+ 	.ofuncs = &(struct nouveau_ofuncs) {
+diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.h b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.h
+new file mode 100644
+index 000000000000..a488c13bffd6
+--- /dev/null
++++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.h
+@@ -0,0 +1,15 @@
++#ifndef __NV31_MPEG_H__
++#define __NV31_MPEG_H__
++
++#include 
++
++struct nv31_mpeg_priv {
++	struct nouveau_mpeg base;
++	atomic_t refcount;
++};
++
++struct nv31_mpeg_chan {
++	struct nouveau_object base;
++};
++
++#endif
+diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c
+index dd6196072e9c..26f3262c0b2a 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c
++++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c
+@@ -31,67 +31,7 @@
+ #include 
+ 
+ #include 
+-#include 
+-
+-struct nv40_mpeg_priv {
+-	struct nouveau_mpeg base;
+-};
+-
+-struct nv40_mpeg_chan {
+-	struct nouveau_mpeg_chan base;
+-};
+-
+-/*******************************************************************************
+- * PMPEG context
+- ******************************************************************************/
+-
+-static int
+-nv40_mpeg_context_ctor(struct nouveau_object *parent,
+-		       struct nouveau_object *engine,
+-		       struct nouveau_oclass *oclass, void *data, u32 size,
+-		       struct nouveau_object **pobject)
+-{
+-	struct nv40_mpeg_chan *chan;
+-	int ret;
+-
+-	ret = nouveau_mpeg_context_create(parent, engine, oclass, NULL,
+-					  264 * 4, 16,
+-					  NVOBJ_FLAG_ZERO_ALLOC, &chan);
+-	*pobject = nv_object(chan);
+-	if (ret)
+-		return ret;
+-
+-	nv_wo32(&chan->base.base, 0x78, 0x02001ec1);
+-	return 0;
+-}
+-
+-static int
+-nv40_mpeg_context_fini(struct nouveau_object *object, bool suspend)
+-{
+-
+-	struct nv40_mpeg_priv *priv = (void *)object->engine;
+-	struct nv40_mpeg_chan *chan = (void *)object;
+-	u32 inst = 0x80000000 | nv_gpuobj(chan)->addr >> 4;
+-
+-	nv_mask(priv, 0x00b32c, 0x00000001, 0x00000000);
+-	if (nv_rd32(priv, 0x00b318) == inst)
+-		nv_mask(priv, 0x00b318, 0x80000000, 0x00000000);
+-	nv_mask(priv, 0x00b32c, 0x00000001, 0x00000001);
+-	return 0;
+-}
+-
+-static struct nouveau_oclass
+-nv40_mpeg_cclass = {
+-	.handle = NV_ENGCTX(MPEG, 0x40),
+-	.ofuncs = &(struct nouveau_ofuncs) {
+-		.ctor = nv40_mpeg_context_ctor,
+-		.dtor = _nouveau_mpeg_context_dtor,
+-		.init = _nouveau_mpeg_context_init,
+-		.fini = nv40_mpeg_context_fini,
+-		.rd32 = _nouveau_mpeg_context_rd32,
+-		.wr32 = _nouveau_mpeg_context_wr32,
+-	},
+-};
++#include 
+ 
+ /*******************************************************************************
+  * PMPEG engine/subdev functions
+@@ -100,7 +40,7 @@ nv40_mpeg_cclass = {
+ static void
+ nv40_mpeg_intr(struct nouveau_subdev *subdev)
+ {
+-	struct nv40_mpeg_priv *priv = (void *)subdev;
++	struct nv31_mpeg_priv *priv = (void *)subdev;
+ 	u32 stat;
+ 
+ 	if ((stat = nv_rd32(priv, 0x00b100)))
+@@ -117,7 +57,7 @@ nv40_mpeg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	       struct nouveau_oclass *oclass, void *data, u32 size,
+ 	       struct nouveau_object **pobject)
+ {
+-	struct nv40_mpeg_priv *priv;
++	struct nv31_mpeg_priv *priv;
+ 	int ret;
+ 
+ 	ret = nouveau_mpeg_create(parent, engine, oclass, &priv);
+@@ -127,7 +67,7 @@ nv40_mpeg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 
+ 	nv_subdev(priv)->unit = 0x00000002;
+ 	nv_subdev(priv)->intr = nv40_mpeg_intr;
+-	nv_engine(priv)->cclass = &nv40_mpeg_cclass;
++	nv_engine(priv)->cclass = &nv31_mpeg_cclass;
+ 	nv_engine(priv)->sclass = nv31_mpeg_sclass;
+ 	nv_engine(priv)->tile_prog = nv31_mpeg_tile_prog;
+ 	return 0;
+diff --git a/drivers/gpu/drm/nouveau/core/include/engine/mpeg.h b/drivers/gpu/drm/nouveau/core/include/engine/mpeg.h
+index 6f4263dfa578..8b7560e2ec19 100644
+--- a/drivers/gpu/drm/nouveau/core/include/engine/mpeg.h
++++ b/drivers/gpu/drm/nouveau/core/include/engine/mpeg.h
+@@ -45,7 +45,7 @@ extern struct nouveau_oclass nv40_mpeg_oclass;
+ extern struct nouveau_oclass nv44_mpeg_oclass;
+ extern struct nouveau_oclass nv50_mpeg_oclass;
+ extern struct nouveau_oclass nv84_mpeg_oclass;
+-
++extern struct nouveau_oclass nv31_mpeg_cclass;
+ extern struct nouveau_oclass nv31_mpeg_sclass[];
+ void nv31_mpeg_intr(struct nouveau_subdev *);
+ void nv31_mpeg_tile_prog(struct nouveau_engine *, int);

commit 5fa7543041cbc2d3139e8d2178df61a33ac3f9ac
+Author: Ilia Mirkin 
+Date:   Sat Sep 7 21:04:09 2013 -0400
+
+    drm/nv44/mpeg: create a copy of the nv31/nv40 impls
+    
+    The nv31/nv40 impls are actually fairly nv44-specific, since they assume
+    the presence of the instance register/context switching. Create a copy
+    before nv31/nv40 get fixed.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile
+index d939a1da3203..56b35b2dc691 100644
+--- a/drivers/gpu/drm/nouveau/Makefile
++++ b/drivers/gpu/drm/nouveau/Makefile
+@@ -227,6 +227,7 @@ nouveau-y += core/engine/graph/nve4.o
+ nouveau-y += core/engine/graph/nvf0.o
+ nouveau-y += core/engine/mpeg/nv31.o
+ nouveau-y += core/engine/mpeg/nv40.o
++nouveau-y += core/engine/mpeg/nv44.o
+ nouveau-y += core/engine/mpeg/nv50.o
+ nouveau-y += core/engine/mpeg/nv84.o
+ nouveau-y += core/engine/ppp/nv98.o
+diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv40.c b/drivers/gpu/drm/nouveau/core/engine/device/nv40.c
+index 0f3225142168..c0d79435bdff 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/device/nv40.c
++++ b/drivers/gpu/drm/nouveau/core/engine/device/nv40.c
+@@ -150,7 +150,7 @@ nv40_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
+ 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
+ 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
+-		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass;
++		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
+ 		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+ 		break;
+ 	case 0x47:
+@@ -171,7 +171,7 @@ nv40_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
+ 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
+ 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
+-		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass;
++		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
+ 		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+ 		break;
+ 	case 0x49:
+@@ -192,7 +192,7 @@ nv40_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
+ 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
+ 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
+-		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass;
++		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
+ 		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+ 		break;
+ 	case 0x4b:
+@@ -213,7 +213,7 @@ nv40_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
+ 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
+ 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
+-		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass;
++		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
+ 		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+ 		break;
+ 	case 0x44:
+@@ -234,7 +234,7 @@ nv40_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
+ 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
+ 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
+-		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass;
++		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
+ 		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+ 		break;
+ 	case 0x46:
+@@ -255,7 +255,7 @@ nv40_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
+ 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
+ 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
+-		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass;
++		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
+ 		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+ 		break;
+ 	case 0x4a:
+@@ -276,7 +276,7 @@ nv40_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
+ 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
+ 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
+-		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass;
++		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
+ 		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+ 		break;
+ 	case 0x4c:
+@@ -297,7 +297,7 @@ nv40_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
+ 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
+ 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
+-		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass;
++		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
+ 		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+ 		break;
+ 	case 0x4e:
+@@ -318,7 +318,7 @@ nv40_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
+ 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
+ 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
+-		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass;
++		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
+ 		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+ 		break;
+ 	case 0x63:
+@@ -339,7 +339,7 @@ nv40_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
+ 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
+ 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
+-		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass;
++		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
+ 		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+ 		break;
+ 	case 0x67:
+@@ -360,7 +360,7 @@ nv40_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
+ 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
+ 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
+-		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass;
++		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
+ 		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+ 		break;
+ 	case 0x68:
+@@ -381,7 +381,7 @@ nv40_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
+ 		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;
+ 		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;
+-		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass;
++		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass;
+ 		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass;
+ 		break;
+ 	default:
+diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv44.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv44.c
+new file mode 100644
+index 000000000000..012b95d5d4c3
+--- /dev/null
++++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv44.c
+@@ -0,0 +1,194 @@
++/*
++ * Copyright 2012 Red Hat Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * Authors: Ben Skeggs
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++#include 
++#include 
++
++#include 
++#include 
++
++struct nv44_mpeg_priv {
++	struct nouveau_mpeg base;
++};
++
++struct nv44_mpeg_chan {
++	struct nouveau_mpeg_chan base;
++};
++
++/*******************************************************************************
++ * PMPEG context
++ ******************************************************************************/
++
++static int
++nv44_mpeg_context_ctor(struct nouveau_object *parent,
++		       struct nouveau_object *engine,
++		       struct nouveau_oclass *oclass, void *data, u32 size,
++		       struct nouveau_object **pobject)
++{
++	struct nv44_mpeg_chan *chan;
++	int ret;
++
++	ret = nouveau_mpeg_context_create(parent, engine, oclass, NULL,
++					  264 * 4, 16,
++					  NVOBJ_FLAG_ZERO_ALLOC, &chan);
++	*pobject = nv_object(chan);
++	if (ret)
++		return ret;
++
++	nv_wo32(&chan->base.base, 0x78, 0x02001ec1);
++	return 0;
++}
++
++static int
++nv44_mpeg_context_fini(struct nouveau_object *object, bool suspend)
++{
++
++	struct nv44_mpeg_priv *priv = (void *)object->engine;
++	struct nv44_mpeg_chan *chan = (void *)object;
++	u32 inst = 0x80000000 | nv_gpuobj(chan)->addr >> 4;
++
++	nv_mask(priv, 0x00b32c, 0x00000001, 0x00000000);
++	if (nv_rd32(priv, 0x00b318) == inst)
++		nv_mask(priv, 0x00b318, 0x80000000, 0x00000000);
++	nv_mask(priv, 0x00b32c, 0x00000001, 0x00000001);
++	return 0;
++}
++
++static struct nouveau_oclass
++nv44_mpeg_cclass = {
++	.handle = NV_ENGCTX(MPEG, 0x44),
++	.ofuncs = &(struct nouveau_ofuncs) {
++		.ctor = nv44_mpeg_context_ctor,
++		.dtor = _nouveau_mpeg_context_dtor,
++		.init = _nouveau_mpeg_context_init,
++		.fini = nv44_mpeg_context_fini,
++		.rd32 = _nouveau_mpeg_context_rd32,
++		.wr32 = _nouveau_mpeg_context_wr32,
++	},
++};
++
++/*******************************************************************************
++ * PMPEG engine/subdev functions
++ ******************************************************************************/
++
++static void
++nv44_mpeg_intr(struct nouveau_subdev *subdev)
++{
++	struct nouveau_fifo *pfifo = nouveau_fifo(subdev);
++	struct nouveau_engine *engine = nv_engine(subdev);
++	struct nouveau_object *engctx;
++	struct nouveau_handle *handle;
++	struct nv44_mpeg_priv *priv = (void *)subdev;
++	u32 inst = nv_rd32(priv, 0x00b318) & 0x000fffff;
++	u32 stat = nv_rd32(priv, 0x00b100);
++	u32 type = nv_rd32(priv, 0x00b230);
++	u32 mthd = nv_rd32(priv, 0x00b234);
++	u32 data = nv_rd32(priv, 0x00b238);
++	u32 show = stat;
++	int chid;
++
++	engctx = nouveau_engctx_get(engine, inst);
++	chid   = pfifo->chid(pfifo, engctx);
++
++	if (stat & 0x01000000) {
++		/* happens on initial binding of the object */
++		if (type == 0x00000020 && mthd == 0x0000) {
++			nv_mask(priv, 0x00b308, 0x00000000, 0x00000000);
++			show &= ~0x01000000;
++		}
++
++		if (type == 0x00000010) {
++			handle = nouveau_handle_get_class(engctx, 0x3174);
++			if (handle && !nv_call(handle->object, mthd, data))
++				show &= ~0x01000000;
++			nouveau_handle_put(handle);
++		}
++	}
++
++	nv_wr32(priv, 0x00b100, stat);
++	nv_wr32(priv, 0x00b230, 0x00000001);
++
++	if (show) {
++		nv_error(priv,
++			 "ch %d [0x%08x %s] 0x%08x 0x%08x 0x%08x 0x%08x\n",
++			 chid, inst << 4, nouveau_client_name(engctx), stat,
++			 type, mthd, data);
++	}
++
++	nouveau_engctx_put(engctx);
++}
++
++static void
++nv44_mpeg_me_intr(struct nouveau_subdev *subdev)
++{
++	struct nv44_mpeg_priv *priv = (void *)subdev;
++	u32 stat;
++
++	if ((stat = nv_rd32(priv, 0x00b100)))
++		nv44_mpeg_intr(subdev);
++
++	if ((stat = nv_rd32(priv, 0x00b800))) {
++		nv_error(priv, "PMSRCH 0x%08x\n", stat);
++		nv_wr32(priv, 0x00b800, stat);
++	}
++}
++
++static int
++nv44_mpeg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
++	       struct nouveau_oclass *oclass, void *data, u32 size,
++	       struct nouveau_object **pobject)
++{
++	struct nv44_mpeg_priv *priv;
++	int ret;
++
++	ret = nouveau_mpeg_create(parent, engine, oclass, &priv);
++	*pobject = nv_object(priv);
++	if (ret)
++		return ret;
++
++	nv_subdev(priv)->unit = 0x00000002;
++	nv_subdev(priv)->intr = nv44_mpeg_me_intr;
++	nv_engine(priv)->cclass = &nv44_mpeg_cclass;
++	nv_engine(priv)->sclass = nv31_mpeg_sclass;
++	nv_engine(priv)->tile_prog = nv31_mpeg_tile_prog;
++	return 0;
++}
++
++struct nouveau_oclass
++nv44_mpeg_oclass = {
++	.handle = NV_ENGINE(MPEG, 0x44),
++	.ofuncs = &(struct nouveau_ofuncs) {
++		.ctor = nv44_mpeg_ctor,
++		.dtor = _nouveau_mpeg_dtor,
++		.init = nv31_mpeg_init,
++		.fini = _nouveau_mpeg_fini,
++	},
++};
+diff --git a/drivers/gpu/drm/nouveau/core/include/engine/mpeg.h b/drivers/gpu/drm/nouveau/core/include/engine/mpeg.h
+index 1d1a89a06ee4..6f4263dfa578 100644
+--- a/drivers/gpu/drm/nouveau/core/include/engine/mpeg.h
++++ b/drivers/gpu/drm/nouveau/core/include/engine/mpeg.h
+@@ -42,6 +42,7 @@ struct nouveau_mpeg {
+ 
+ extern struct nouveau_oclass nv31_mpeg_oclass;
+ extern struct nouveau_oclass nv40_mpeg_oclass;
++extern struct nouveau_oclass nv44_mpeg_oclass;
+ extern struct nouveau_oclass nv50_mpeg_oclass;
+ extern struct nouveau_oclass nv84_mpeg_oclass;
+ 

commit be4ba550461fbb90a75390b3f001a8fa27e4c70e
+Author: Ilia Mirkin 
+Date:   Sat Sep 7 21:04:08 2013 -0400
+
+    drm/nv31/mpeg: no need to set compat mode differently for nv44 gr
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
+index c19004301309..5c54aa10cc0a 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
++++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
+@@ -34,7 +34,6 @@
+ 
+ #include 
+ #include 
+-#include 
+ 
+ struct nv31_mpeg_priv {
+ 	struct nouveau_mpeg base;
+@@ -284,10 +283,7 @@ nv31_mpeg_init(struct nouveau_object *object)
+ 	/* PMPEG init */
+ 	nv_wr32(priv, 0x00b32c, 0x00000000);
+ 	nv_wr32(priv, 0x00b314, 0x00000100);
+-	if (nv_device(priv)->chipset >= 0x40 && nv44_graph_class(priv))
+-		nv_wr32(priv, 0x00b220, 0x00000044);
+-	else
+-		nv_wr32(priv, 0x00b220, 0x00000031);
++	nv_wr32(priv, 0x00b220, 0x00000031);
+ 	nv_wr32(priv, 0x00b300, 0x02001ec1);
+ 	nv_mask(priv, 0x00b32c, 0x00000001, 0x00000001);
+ 

commit 515de6b27f96fb7ff58f34bda6e1be44a6f9e46d
+Author: Ilia Mirkin 
+Date:   Sat Sep 7 20:33:43 2013 -0400
+
+    drm/nv10/kms: add plane support for nv10-nv40
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
+index 05e903f08a36..a0bc8a89b699 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
++++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
+@@ -59,6 +59,7 @@ nv04_disp_intr(struct nouveau_subdev *subdev)
+ 	struct nv04_disp_priv *priv = (void *)subdev;
+ 	u32 crtc0 = nv_rd32(priv, 0x600100);
+ 	u32 crtc1 = nv_rd32(priv, 0x602100);
++	u32 pvideo;
+ 
+ 	if (crtc0 & 0x00000001) {
+ 		nouveau_event_trigger(priv->base.vblank, 0);
+@@ -69,6 +70,14 @@ nv04_disp_intr(struct nouveau_subdev *subdev)
+ 		nouveau_event_trigger(priv->base.vblank, 1);
+ 		nv_wr32(priv, 0x602100, 0x00000001);
+ 	}
++
++	if (nv_device(priv)->chipset >= 0x10 &&
++	    nv_device(priv)->chipset <= 0x40) {
++		pvideo = nv_rd32(priv, 0x8100);
++		if (pvideo & ~0x11)
++			nv_info(priv, "PVIDEO intr: %08x\n", pvideo);
++		nv_wr32(priv, 0x8100, pvideo);
++	}
+ }
+ 
+ static int
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c
+index 64aa4edb0d9d..062c0489fd5e 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c
+@@ -33,6 +33,7 @@ nv04_mc_intr[] = {
+ 	{ 0x00000001, NVDEV_ENGINE_MPEG },	/* NV17- MPEG/ME */
+ 	{ 0x00000100, NVDEV_ENGINE_FIFO },
+ 	{ 0x00001000, NVDEV_ENGINE_GR },
++	{ 0x00010000, NVDEV_ENGINE_DISP },
+ 	{ 0x00020000, NVDEV_ENGINE_VP },	/* NV40- */
+ 	{ 0x00100000, NVDEV_SUBDEV_TIMER },
+ 	{ 0x01000000, NVDEV_ENGINE_DISP },	/* NV04- PCRTC0 */
+diff --git a/drivers/gpu/drm/nouveau/dispnv04/Makefile b/drivers/gpu/drm/nouveau/dispnv04/Makefile
+index ea3f5b8a0f95..424a489d0f03 100644
+--- a/drivers/gpu/drm/nouveau/dispnv04/Makefile
++++ b/drivers/gpu/drm/nouveau/dispnv04/Makefile
+@@ -5,6 +5,7 @@ nouveau-y += dispnv04/dac.o
+ nouveau-y += dispnv04/dfp.o
+ nouveau-y += dispnv04/disp.o
+ nouveau-y += dispnv04/hw.o
++nouveau-y += dispnv04/overlay.o
+ nouveau-y += dispnv04/tvmodesnv17.o
+ nouveau-y += dispnv04/tvnv04.o
+ nouveau-y += dispnv04/tvnv17.o
+diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c
+index 4908d3fd0486..b13ff0fc42de 100644
+--- a/drivers/gpu/drm/nouveau/dispnv04/disp.c
++++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c
+@@ -140,6 +140,8 @@ nv04_display_create(struct drm_device *dev)
+ 		func->save(encoder);
+ 	}
+ 
++	nouveau_overlay_init(dev);
++
+ 	return 0;
+ }
+ 
+diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.h b/drivers/gpu/drm/nouveau/dispnv04/disp.h
+index 2cf65e0b517e..56a28db04000 100644
+--- a/drivers/gpu/drm/nouveau/dispnv04/disp.h
++++ b/drivers/gpu/drm/nouveau/dispnv04/disp.h
+@@ -123,6 +123,9 @@ int nv04_tv_create(struct drm_connector *, struct dcb_output *);
+ /* nv17_tv.c */
+ int nv17_tv_create(struct drm_connector *, struct dcb_output *);
+ 
++/* overlay.c */
++void nouveau_overlay_init(struct drm_device *dev);
++
+ static inline bool
+ nv_two_heads(struct drm_device *dev)
+ {
+diff --git a/drivers/gpu/drm/nouveau/dispnv04/hw.c b/drivers/gpu/drm/nouveau/dispnv04/hw.c
+index 3d51ae9070f8..aca76af115b3 100644
+--- a/drivers/gpu/drm/nouveau/dispnv04/hw.c
++++ b/drivers/gpu/drm/nouveau/dispnv04/hw.c
+@@ -27,6 +27,7 @@
+ #include "hw.h"
+ 
+ #include 
++#include 
+ #include 
+ #include 
+ 
+@@ -664,6 +665,7 @@ nv_load_state_ext(struct drm_device *dev, int head,
+ 	struct nouveau_drm *drm = nouveau_drm(dev);
+ 	struct nouveau_device *device = nv_device(drm->device);
+ 	struct nouveau_timer *ptimer = nouveau_timer(device);
++	struct nouveau_fb *pfb = nouveau_fb(device);
+ 	struct nv04_crtc_reg *regp = &state->crtc_reg[head];
+ 	uint32_t reg900;
+ 	int i;
+@@ -680,10 +682,10 @@ nv_load_state_ext(struct drm_device *dev, int head,
+ 		nv_wr32(device, NV_PVIDEO_INTR_EN, 0);
+ 		nv_wr32(device, NV_PVIDEO_OFFSET_BUFF(0), 0);
+ 		nv_wr32(device, NV_PVIDEO_OFFSET_BUFF(1), 0);
+-		nv_wr32(device, NV_PVIDEO_LIMIT(0), 0); //drm->fb_available_size - 1);
+-		nv_wr32(device, NV_PVIDEO_LIMIT(1), 0); //drm->fb_available_size - 1);
+-		nv_wr32(device, NV_PVIDEO_UVPLANE_LIMIT(0), 0); //drm->fb_available_size - 1);
+-		nv_wr32(device, NV_PVIDEO_UVPLANE_LIMIT(1), 0); //drm->fb_available_size - 1);
++		nv_wr32(device, NV_PVIDEO_LIMIT(0), pfb->ram->size - 1);
++		nv_wr32(device, NV_PVIDEO_LIMIT(1), pfb->ram->size - 1);
++		nv_wr32(device, NV_PVIDEO_UVPLANE_LIMIT(0), pfb->ram->size - 1);
++		nv_wr32(device, NV_PVIDEO_UVPLANE_LIMIT(1), pfb->ram->size - 1);
+ 		nv_wr32(device, NV_PBUS_POWERCTRL_2, 0);
+ 
+ 		NVWriteCRTC(dev, head, NV_PCRTC_CURSOR_CONFIG, regp->cursor_cfg);
+diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+new file mode 100644
+index 000000000000..3618ac6b6316
+--- /dev/null
++++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+@@ -0,0 +1,320 @@
++/*
++ * Copyright 2013 Ilia Mirkin
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
++ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ *
++ * Implementation based on the pre-KMS implementation in xf86-video-nouveau,
++ * written by Arthur Huillet.
++ */
++
++#include 
++#include 
++#include 
++
++#include "nouveau_drm.h"
++
++#include "nouveau_bo.h"
++#include "nouveau_connector.h"
++#include "nouveau_display.h"
++#include "nvreg.h"
++
++
++struct nouveau_plane {
++	struct drm_plane base;
++	bool flip;
++	struct nouveau_bo *cur;
++
++	struct {
++		struct drm_property *colorkey;
++		struct drm_property *contrast;
++		struct drm_property *brightness;
++		struct drm_property *hue;
++		struct drm_property *saturation;
++		struct drm_property *iturbt_709;
++	} props;
++
++	int colorkey;
++	int contrast;
++	int brightness;
++	int hue;
++	int saturation;
++	int iturbt_709;
++};
++
++static uint32_t formats[] = {
++	DRM_FORMAT_NV12,
++	DRM_FORMAT_UYVY,
++};
++
++/* Sine can be approximated with
++ * http://en.wikipedia.org/wiki/Bhaskara_I's_sine_approximation_formula
++ * sin(x degrees) ~= 4 x (180 - x) / (40500 - x (180 - x) )
++ * Note that this only works for the range [0, 180].
++ * Also note that sin(x) == -sin(x - 180)
++ */
++static inline int
++sin_mul(int degrees, int factor)
++{
++	if (degrees > 180) {
++		degrees -= 180;
++		factor *= -1;
++	}
++	return factor * 4 * degrees * (180 - degrees) /
++		(40500 - degrees * (180 - degrees));
++}
++
++/* cos(x) = sin(x + 90) */
++static inline int
++cos_mul(int degrees, int factor)
++{
++	return sin_mul((degrees + 90) % 360, factor);
++}
++
++static int
++nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
++		  struct drm_framebuffer *fb, int crtc_x, int crtc_y,
++		  unsigned int crtc_w, unsigned int crtc_h,
++		  uint32_t src_x, uint32_t src_y,
++		  uint32_t src_w, uint32_t src_h)
++{
++	struct nouveau_device *dev = nouveau_dev(plane->dev);
++	struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane;
++	struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb);
++	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
++	struct nouveau_bo *cur = nv_plane->cur;
++	bool flip = nv_plane->flip;
++	int format = ALIGN(src_w * 4, 0x100);
++	int soff = NV_PCRTC0_SIZE * nv_crtc->index;
++	int soff2 = NV_PCRTC0_SIZE * !nv_crtc->index;
++	int ret;
++
++	if (format > 0xffff)
++		return -EINVAL;
++
++	ret = nouveau_bo_pin(nv_fb->nvbo, TTM_PL_FLAG_VRAM);
++	if (ret)
++		return ret;
++
++	nv_plane->cur = nv_fb->nvbo;
++
++	/* Source parameters given in 16.16 fixed point, ignore fractional. */
++	src_x = src_x >> 16;
++	src_y = src_y >> 16;
++	src_w = src_w >> 16;
++	src_h = src_h >> 16;
++
++	nv_mask(dev, NV_PCRTC_ENGINE_CTRL + soff, NV_CRTC_FSEL_OVERLAY, NV_CRTC_FSEL_OVERLAY);
++	nv_mask(dev, NV_PCRTC_ENGINE_CTRL + soff2, NV_CRTC_FSEL_OVERLAY, 0);
++
++	nv_wr32(dev, NV_PVIDEO_BASE(flip), 0);
++	nv_wr32(dev, NV_PVIDEO_OFFSET_BUFF(flip), nv_fb->nvbo->bo.offset);
++	nv_wr32(dev, NV_PVIDEO_SIZE_IN(flip), src_h << 16 | src_w);
++	nv_wr32(dev, NV_PVIDEO_POINT_IN(flip), src_y << 16 | src_x);
++	nv_wr32(dev, NV_PVIDEO_DS_DX(flip), (src_w << 20) / crtc_w);
++	nv_wr32(dev, NV_PVIDEO_DT_DY(flip), (src_h << 20) / crtc_h);
++	nv_wr32(dev, NV_PVIDEO_POINT_OUT(flip), crtc_y << 16 | crtc_x);
++	nv_wr32(dev, NV_PVIDEO_SIZE_OUT(flip), crtc_h << 16 | crtc_w);
++
++	if (fb->pixel_format == DRM_FORMAT_NV12) {
++		format |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8;
++		format |= NV_PVIDEO_FORMAT_PLANAR;
++	}
++	if (nv_plane->iturbt_709)
++		format |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
++	if (nv_plane->colorkey & (1 << 24))
++		format |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY;
++
++	if (fb->pixel_format == DRM_FORMAT_NV12) {
++		nv_wr32(dev, NV_PVIDEO_UVPLANE_BASE(flip), 0);
++		nv_wr32(dev, NV_PVIDEO_UVPLANE_OFFSET_BUFF(flip),
++			nv_fb->nvbo->bo.offset + fb->offsets[1]);
++	}
++	nv_wr32(dev, NV_PVIDEO_FORMAT(flip), format);
++	nv_wr32(dev, NV_PVIDEO_STOP, 0);
++	/* TODO: wait for vblank? */
++	nv_wr32(dev, NV_PVIDEO_BUFFER, flip ? 0x10 : 0x1);
++	nv_plane->flip = !flip;
++
++	if (cur)
++		nouveau_bo_unpin(cur);
++
++	return 0;
++}
++
++static int
++nv10_disable_plane(struct drm_plane *plane)
++{
++	struct nouveau_device *dev = nouveau_dev(plane->dev);
++	struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane;
++
++	nv_wr32(dev, NV_PVIDEO_STOP, 1);
++	if (nv_plane->cur) {
++		nouveau_bo_unpin(nv_plane->cur);
++		nv_plane->cur = NULL;
++	}
++
++	return 0;
++}
++
++static void
++nv10_destroy_plane(struct drm_plane *plane)
++{
++	nv10_disable_plane(plane);
++	drm_plane_cleanup(plane);
++	kfree(plane);
++}
++
++static void
++nv10_set_params(struct nouveau_plane *plane)
++{
++	struct nouveau_device *dev = nouveau_dev(plane->base.dev);
++	u32 luma = (plane->brightness - 512) << 16 | plane->contrast;
++	u32 chroma = ((sin_mul(plane->hue, plane->saturation) & 0xffff) << 16) |
++		(cos_mul(plane->hue, plane->saturation) & 0xffff);
++	u32 format = 0;
++
++	nv_wr32(dev, NV_PVIDEO_LUMINANCE(0), luma);
++	nv_wr32(dev, NV_PVIDEO_LUMINANCE(1), luma);
++	nv_wr32(dev, NV_PVIDEO_CHROMINANCE(0), chroma);
++	nv_wr32(dev, NV_PVIDEO_CHROMINANCE(1), chroma);
++	nv_wr32(dev, NV_PVIDEO_COLOR_KEY, plane->colorkey & 0xffffff);
++
++	if (plane->cur) {
++		if (plane->iturbt_709)
++			format |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
++		if (plane->colorkey & (1 << 24))
++			format |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY;
++		nv_mask(dev, NV_PVIDEO_FORMAT(plane->flip),
++			NV_PVIDEO_FORMAT_MATRIX_ITURBT709 |
++			NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY,
++			format);
++	}
++}
++
++static int
++nv10_set_property(struct drm_plane *plane,
++		  struct drm_property *property,
++		  uint64_t value)
++{
++	struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane;
++
++	if (property == nv_plane->props.colorkey)
++		nv_plane->colorkey = value;
++	else if (property == nv_plane->props.contrast)
++		nv_plane->contrast = value;
++	else if (property == nv_plane->props.brightness)
++		nv_plane->brightness = value;
++	else if (property == nv_plane->props.hue)
++		nv_plane->hue = value;
++	else if (property == nv_plane->props.saturation)
++		nv_plane->saturation = value;
++	else if (property == nv_plane->props.iturbt_709)
++		nv_plane->iturbt_709 = value;
++	else
++		return -EINVAL;
++
++	nv10_set_params(nv_plane);
++	return 0;
++}
++
++static const struct drm_plane_funcs nv10_plane_funcs = {
++	.update_plane = nv10_update_plane,
++	.disable_plane = nv10_disable_plane,
++	.set_property = nv10_set_property,
++	.destroy = nv10_destroy_plane,
++};
++
++static void
++nv10_overlay_init(struct drm_device *device)
++{
++	struct nouveau_device *dev = nouveau_dev(device);
++	struct nouveau_plane *plane = kzalloc(sizeof(struct nouveau_plane), GFP_KERNEL);
++	int ret;
++
++	if (!plane)
++		return;
++
++	ret = drm_plane_init(device, &plane->base, 3 /* both crtc's */,
++			     &nv10_plane_funcs,
++			     formats, ARRAY_SIZE(formats), false);
++	if (ret)
++		goto err;
++
++	/* Set up the plane properties */
++	plane->props.colorkey = drm_property_create_range(
++			device, 0, "colorkey", 0, 0x01ffffff);
++	plane->props.contrast = drm_property_create_range(
++			device, 0, "contrast", 0, 8192 - 1);
++	plane->props.brightness = drm_property_create_range(
++			device, 0, "brightness", 0, 1024);
++	plane->props.hue = drm_property_create_range(
++			device, 0, "hue", 0, 359);
++	plane->props.saturation = drm_property_create_range(
++			device, 0, "saturation", 0, 8192 - 1);
++	plane->props.iturbt_709 = drm_property_create_range(
++			device, 0, "iturbt_709", 0, 1);
++	if (!plane->props.colorkey ||
++	    !plane->props.contrast ||
++	    !plane->props.brightness ||
++	    !plane->props.hue ||
++	    !plane->props.saturation ||
++	    !plane->props.iturbt_709)
++		goto cleanup;
++
++	plane->colorkey = 0;
++	drm_object_attach_property(&plane->base.base,
++				   plane->props.colorkey, plane->colorkey);
++
++	plane->contrast = 0x1000;
++	drm_object_attach_property(&plane->base.base,
++				   plane->props.contrast, plane->contrast);
++
++	plane->brightness = 512;
++	drm_object_attach_property(&plane->base.base,
++				   plane->props.brightness, plane->brightness);
++
++	plane->hue = 0;
++	drm_object_attach_property(&plane->base.base,
++				   plane->props.hue, plane->hue);
++
++	plane->saturation = 0x1000;
++	drm_object_attach_property(&plane->base.base,
++				   plane->props.saturation, plane->saturation);
++
++	plane->iturbt_709 = 0;
++	drm_object_attach_property(&plane->base.base,
++				   plane->props.iturbt_709, plane->iturbt_709);
++
++	nv10_set_params(plane);
++	nv_wr32(dev, NV_PVIDEO_STOP, 1);
++	return;
++cleanup:
++	drm_plane_cleanup(&plane->base);
++err:
++	kfree(plane);
++	nv_error(dev, "Failed to create plane\n");
++}
++
++void
++nouveau_overlay_init(struct drm_device *device)
++{
++	struct nouveau_device *dev = nouveau_dev(device);
++	if (dev->chipset >= 0x10 && dev->chipset <= 0x40)
++		nv10_overlay_init(device);
++}

commit 8aa816b0bbcefa8517d7e10586d7dbb0ead3c4c1
+Author: Ilia Mirkin 
+Date:   Thu Sep 5 04:45:03 2013 -0400
+
+    drm/nv10: fix chipset checks, mostly for the benefit of nv1a
+    
+    NV1A is numerically higher than NV17 but generationally lower. Use the
+    new card type to help disambiguate.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/device/base.c b/drivers/gpu/drm/nouveau/core/engine/device/base.c
+index f8b4fbf55889..de1e9eca0151 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/device/base.c
++++ b/drivers/gpu/drm/nouveau/core/engine/device/base.c
+@@ -219,7 +219,7 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
+ 		nv_info(device, "Family : NV%02X\n", device->card_type);
+ 
+ 		/* determine frequency of timing crystal */
+-		if ( device->chipset < 0x17 ||
++		if ( device->card_type <= NV_10 || device->chipset < 0x17 ||
+ 		    (device->chipset >= 0x20 && device->chipset < 0x25))
+ 			strap &= 0x00000040;
+ 		else
+diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c
+index 23c143aaa556..4532f7e5618c 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c
++++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c
+@@ -945,7 +945,8 @@ nv10_graph_load_context(struct nv10_graph_chan *chan, int chid)
+ 	for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++)
+ 		nv_wr32(priv, nv10_graph_ctx_regs[i], chan->nv10[i]);
+ 
+-	if (nv_device(priv)->chipset >= 0x17) {
++	if (nv_device(priv)->card_type >= NV_11 &&
++	    nv_device(priv)->chipset >= 0x17) {
+ 		for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++)
+ 			nv_wr32(priv, nv17_graph_ctx_regs[i], chan->nv17[i]);
+ 	}
+@@ -970,7 +971,8 @@ nv10_graph_unload_context(struct nv10_graph_chan *chan)
+ 	for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++)
+ 		chan->nv10[i] = nv_rd32(priv, nv10_graph_ctx_regs[i]);
+ 
+-	if (nv_device(priv)->chipset >= 0x17) {
++	if (nv_device(priv)->card_type >= NV_11 &&
++	    nv_device(priv)->chipset >= 0x17) {
+ 		for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++)
+ 			chan->nv17[i] = nv_rd32(priv, nv17_graph_ctx_regs[i]);
+ 	}
+@@ -1052,7 +1054,8 @@ nv10_graph_context_ctor(struct nouveau_object *parent,
+ 	NV_WRITE_CTX(0x00400e14, 0x00001000);
+ 	NV_WRITE_CTX(0x00400e30, 0x00080008);
+ 	NV_WRITE_CTX(0x00400e34, 0x00080008);
+-	if (nv_device(priv)->chipset >= 0x17) {
++	if (nv_device(priv)->card_type >= NV_11 &&
++	    nv_device(priv)->chipset >= 0x17) {
+ 		/* is it really needed ??? */
+ 		NV17_WRITE_CTX(NV10_PGRAPH_DEBUG_4,
+ 					nv_rd32(priv, NV10_PGRAPH_DEBUG_4));
+@@ -1231,7 +1234,7 @@ nv10_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 		nv_engine(priv)->sclass = nv10_graph_sclass;
+ 	else
+ 	if (nv_device(priv)->chipset <  0x17 ||
+-	    nv_device(priv)->chipset == 0x1a)
++	    nv_device(priv)->card_type < NV_11)
+ 		nv_engine(priv)->sclass = nv15_graph_sclass;
+ 	else
+ 		nv_engine(priv)->sclass = nv17_graph_sclass;
+@@ -1270,7 +1273,8 @@ nv10_graph_init(struct nouveau_object *object)
+ 	nv_wr32(priv, NV04_PGRAPH_DEBUG_2, 0x25f92ad9);
+ 	nv_wr32(priv, NV04_PGRAPH_DEBUG_3, 0x55DE0830 | (1 << 29) | (1 << 31));
+ 
+-	if (nv_device(priv)->chipset >= 0x17) {
++	if (nv_device(priv)->card_type >= NV_11 &&
++	    nv_device(priv)->chipset >= 0x17) {
+ 		nv_wr32(priv, NV10_PGRAPH_DEBUG_4, 0x1f000000);
+ 		nv_wr32(priv, 0x400a10, 0x03ff3fb6);
+ 		nv_wr32(priv, 0x400838, 0x002f8684);
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c
+index b22357d9b821..27c8235f1a85 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c
+@@ -168,7 +168,8 @@ setPLL_single(struct nouveau_devinit *devinit, u32 reg,
+ 		/* downclock -- write new NM first */
+ 		nv_wr32(devinit, reg, (oldpll & 0xffff0000) | pv->NM1);
+ 
+-	if (chip_version < 0x17 && chip_version != 0x11)
++	if ((chip_version < 0x17 || chip_version == 0x1a) &&
++	    chip_version != 0x11)
+ 		/* wait a bit on older chips */
+ 		msleep(64);
+ 	nv_rd32(devinit, reg);
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c
+index 463b08fa0968..8d274dba1ef1 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c
+@@ -38,12 +38,18 @@ static void
+ nv10_devinit_meminit(struct nouveau_devinit *devinit)
+ {
+ 	struct nv10_devinit_priv *priv = (void *)devinit;
+-	const int mem_width[] = { 0x10, 0x00, 0x20 };
+-	const int mem_width_count = nv_device(priv)->chipset >= 0x17 ? 3 : 2;
++	static const int mem_width[] = { 0x10, 0x00, 0x20 };
++	int mem_width_count;
+ 	uint32_t patt = 0xdeadbeef;
+ 	struct io_mapping *fb;
+ 	int i, j, k;
+ 
++	if (nv_device(priv)->card_type >= NV_11 &&
++	    nv_device(priv)->chipset >= 0x17)
++		mem_width_count = 3;
++	else
++		mem_width_count = 2;
++
+ 	/* Map the framebuffer aperture */
+ 	fb = fbmem_init(nv_device(priv)->pdev);
+ 	if (!fb) {
+diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
+index 69bf82d126ea..c0a79c715827 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
++++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
+@@ -142,7 +142,8 @@ nouveau_accel_init(struct nouveau_drm *drm)
+ 
+ 	/* initialise synchronisation routines */
+ 	if      (device->card_type < NV_10) ret = nv04_fence_create(drm);
+-	else if (device->chipset   <  0x17) ret = nv10_fence_create(drm);
++	else if (device->card_type < NV_11 ||
++		 device->chipset   <  0x17) ret = nv10_fence_create(drm);
+ 	else if (device->card_type < NV_50) ret = nv17_fence_create(drm);
+ 	else if (device->chipset   <  0x84) ret = nv50_fence_create(drm);
+ 	else if (device->card_type < NV_C0) ret = nv84_fence_create(drm);

commit 4a0ff75418851116d034fa4d91bef114f01a329d
+Author: Ilia Mirkin 
+Date:   Thu Sep 5 04:45:02 2013 -0400
+
+    drm/nv10: introduce a new NV_11 card type
+    
+    NV11/17/1F/18 come after NV10/15/16/1A. In order to facilitate using
+    numerical comparisons, split up the two sets into different card types.
+    
+    This change should be a no-op except that the relevant cards will see
+    NV11 printed instead of NV10 for the family.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/device/base.c b/drivers/gpu/drm/nouveau/core/engine/device/base.c
+index 1407d80b910c..f8b4fbf55889 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/device/base.c
++++ b/drivers/gpu/drm/nouveau/core/engine/device/base.c
+@@ -161,7 +161,13 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
+ 		if ((boot0 & 0x0f000000) > 0) {
+ 			device->chipset = (boot0 & 0xff00000) >> 20;
+ 			switch (device->chipset & 0xf0) {
+-			case 0x10: device->card_type = NV_10; break;
++			case 0x10: {
++				if (0x461 & (1 << (device->chipset & 0xf)))
++					device->card_type = NV_10;
++				else
++					device->card_type = NV_11;
++				break;
++			}
+ 			case 0x20: device->card_type = NV_20; break;
+ 			case 0x30: device->card_type = NV_30; break;
+ 			case 0x40:
+@@ -188,7 +194,8 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
+ 
+ 		switch (device->card_type) {
+ 		case NV_04: ret = nv04_identify(device); break;
+-		case NV_10: ret = nv10_identify(device); break;
++		case NV_10:
++		case NV_11: ret = nv10_identify(device); break;
+ 		case NV_20: ret = nv20_identify(device); break;
+ 		case NV_30: ret = nv30_identify(device); break;
+ 		case NV_40: ret = nv40_identify(device); break;
+diff --git a/drivers/gpu/drm/nouveau/core/include/core/device.h b/drivers/gpu/drm/nouveau/core/include/core/device.h
+index 0a1698faeff3..40c6dcf6ff63 100644
+--- a/drivers/gpu/drm/nouveau/core/include/core/device.h
++++ b/drivers/gpu/drm/nouveau/core/include/core/device.h
+@@ -72,6 +72,7 @@ struct nouveau_device {
+ 	enum {
+ 		NV_04    = 0x04,
+ 		NV_10    = 0x10,
++		NV_11    = 0x11,
+ 		NV_20    = 0x20,
+ 		NV_30    = 0x30,
+ 		NV_40    = 0x40,
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c b/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c
+index f835501203e5..1f76de597d4b 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c
+@@ -114,6 +114,7 @@ pll_map(struct nouveau_bios *bios)
+ 	switch (nv_device(bios)->card_type) {
+ 	case NV_04:
+ 	case NV_10:
++	case NV_11:
+ 	case NV_20:
+ 	case NV_30:
+ 		return nv04_pll_mapping;
+diff --git a/drivers/gpu/drm/nouveau/dispnv04/hw.c b/drivers/gpu/drm/nouveau/dispnv04/hw.c
+index f8dee834527f..3d51ae9070f8 100644
+--- a/drivers/gpu/drm/nouveau/dispnv04/hw.c
++++ b/drivers/gpu/drm/nouveau/dispnv04/hw.c
+@@ -740,7 +740,7 @@ nv_load_state_ext(struct drm_device *dev, int head,
+ 	}
+ 	/* NV11 and NV20 stop at 0x52. */
+ 	if (nv_gf4_disp_arch(dev)) {
+-		if (nv_device(drm->device)->card_type == NV_10) {
++		if (nv_device(drm->device)->card_type < NV_20) {
+ 			/* Not waiting for vertical retrace before modifying
+ 			   CRE_53/CRE_54 causes lockups. */
+ 			nouveau_timer_wait_eq(ptimer, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x8);
+diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c
+index 72055a35f845..3621e7f23477 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_abi16.c
++++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c
+@@ -87,6 +87,7 @@ nouveau_abi16_swclass(struct nouveau_drm *drm)
+ 	case NV_04:
+ 		return 0x006e;
+ 	case NV_10:
++	case NV_11:
+ 	case NV_20:
+ 	case NV_30:
+ 	case NV_40:
+diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
+index c28a5a9ff053..949ab0cbc4ab 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
++++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
+@@ -269,7 +269,8 @@ set_placement_range(struct nouveau_bo *nvbo, uint32_t type)
+ 	struct nouveau_fb *pfb = nouveau_fb(drm->device);
+ 	u32 vram_pages = pfb->ram->size >> PAGE_SHIFT;
+ 
+-	if (nv_device(drm->device)->card_type == NV_10 &&
++	if ((nv_device(drm->device)->card_type == NV_10 ||
++	     nv_device(drm->device)->card_type == NV_11) &&
+ 	    nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM) &&
+ 	    nvbo->bo.mem.num_pages < vram_pages / 4) {
+ 		/*
+diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
+index 1aa682494a18..1674882d60d5 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
++++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
+@@ -215,9 +215,10 @@ nouveau_connector_set_encoder(struct drm_connector *connector,
+ 	} else {
+ 		connector->doublescan_allowed = true;
+ 		if (nv_device(drm->device)->card_type == NV_20 ||
+-		   (nv_device(drm->device)->card_type == NV_10 &&
+-		    (dev->pdev->device & 0x0ff0) != 0x0100 &&
+-		    (dev->pdev->device & 0x0ff0) != 0x0150))
++		    ((nv_device(drm->device)->card_type == NV_10 ||
++		      nv_device(drm->device)->card_type == NV_11) &&
++		     (dev->pdev->device & 0x0ff0) != 0x0100 &&
++		     (dev->pdev->device & 0x0ff0) != 0x0150))
+ 			/* HW is broken */
+ 			connector->interlace_allowed = false;
+ 		else

commit 73f4b1f8938174dcf1645563e541022837a6a7f4
+Author: Ilia Mirkin 
+Date:   Thu Sep 5 04:45:01 2013 -0400
+
+    drm/nouveau: fix backlight mask on ppc powerbook
+    
+    This code was originally moved to using nv_mask by d31e078d84. This
+    should not have any actual effect since the mask isn't applied to the
+    value.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/dispnv04/dfp.c b/drivers/gpu/drm/nouveau/dispnv04/dfp.c
+index 59d1c040b84f..bb6c3c3f981d 100644
+--- a/drivers/gpu/drm/nouveau/dispnv04/dfp.c
++++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c
+@@ -493,7 +493,7 @@ static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode)
+ 	if (dev->pdev->device == 0x0174 || dev->pdev->device == 0x0179 ||
+ 	    dev->pdev->device == 0x0189 || dev->pdev->device == 0x0329) {
+ 		if (mode == DRM_MODE_DPMS_ON) {
+-			nv_mask(device, NV_PBUS_DEBUG_DUALHEAD_CTL, 0, 1 << 31);
++			nv_mask(device, NV_PBUS_DEBUG_DUALHEAD_CTL, 1 << 31, 1 << 31);
+ 			nv_mask(device, NV_PCRTC_GPIO_EXT, 3, 1);
+ 		} else {
+ 			nv_mask(device, NV_PBUS_DEBUG_DUALHEAD_CTL, 1 << 31, 0);

commit 4449933a3703704e8dc74ea774372857240c142d
+Author: Ilia Mirkin 
+Date:   Thu Sep 5 04:45:00 2013 -0400
+
+    drm/nouveau: remove prototype for non-existent nouveau_connector_bpp
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
+index 27c2be68810e..264a778f473b 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
++++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
+@@ -107,7 +107,4 @@ nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc)
+ struct drm_connector *
+ nouveau_connector_create(struct drm_device *, int index);
+ 
+-int
+-nouveau_connector_bpp(struct drm_connector *);
+-
+ #endif /* __NOUVEAU_CONNECTOR_H__ */

commit c865534f1e5b5b4ef03f4a55cf4730f4b70dd75b
+Author: Ilia Mirkin 
+Date:   Fri Aug 23 13:03:14 2013 -0400
+
+    drm/nouveau/i2c: pass the function pointers in at creation time
+    
+    i2c_bit_add_bus can call the pre_xfer function, which expects the func
+    pointer to be set. Pass in func to the port creation logic so that it is
+    set before i2c_bit_add_bus.
+    
+    See https://bugs.freedesktop.org/show_bug.cgi?id=68456
+    
+    Reported-by: Hans-Peter Deifel 
+    Tested-by: Hans-Peter Deifel 
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h
+index 888384c0bed8..7e4e2775f249 100644
+--- a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h
++++ b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h
+@@ -39,8 +39,8 @@ struct nouveau_i2c_func {
+ 	int  (*drv_ctl)(struct nouveau_i2c_port *, int lane, int sw, int pe);
+ };
+ 
+-#define nouveau_i2c_port_create(p,e,o,i,a,d)                                   \
+-	nouveau_i2c_port_create_((p), (e), (o), (i), (a),                      \
++#define nouveau_i2c_port_create(p,e,o,i,a,f,d)                                 \
++	nouveau_i2c_port_create_((p), (e), (o), (i), (a), (f),                 \
+ 				 sizeof(**d), (void **)d)
+ #define nouveau_i2c_port_destroy(p) ({                                         \
+ 	struct nouveau_i2c_port *port = (p);                                   \
+@@ -53,7 +53,9 @@ struct nouveau_i2c_func {
+ 
+ int nouveau_i2c_port_create_(struct nouveau_object *, struct nouveau_object *,
+ 			     struct nouveau_oclass *, u8,
+-			     const struct i2c_algorithm *, int, void **);
++			     const struct i2c_algorithm *,
++			     const struct nouveau_i2c_func *,
++			     int, void **);
+ void _nouveau_i2c_port_dtor(struct nouveau_object *);
+ #define _nouveau_i2c_port_init nouveau_object_init
+ #define _nouveau_i2c_port_fini nouveau_object_fini
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/anx9805.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/anx9805.c
+index dec94e9d776a..4b195ac4da66 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/i2c/anx9805.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/anx9805.c
+@@ -118,7 +118,8 @@ anx9805_aux_chan_ctor(struct nouveau_object *parent,
+ 	int ret;
+ 
+ 	ret = nouveau_i2c_port_create(parent, engine, oclass, index,
+-				     &nouveau_i2c_aux_algo, &chan);
++				      &nouveau_i2c_aux_algo, &anx9805_aux_func,
++				      &chan);
+ 	*pobject = nv_object(chan);
+ 	if (ret)
+ 		return ret;
+@@ -140,8 +141,6 @@ anx9805_aux_chan_ctor(struct nouveau_object *parent,
+ 		struct i2c_algo_bit_data *algo = mast->adapter.algo_data;
+ 		algo->udelay = max(algo->udelay, 40);
+ 	}
+-
+-	chan->base.func = &anx9805_aux_func;
+ 	return 0;
+ }
+ 
+@@ -234,7 +233,8 @@ anx9805_ddc_port_ctor(struct nouveau_object *parent,
+ 	int ret;
+ 
+ 	ret = nouveau_i2c_port_create(parent, engine, oclass, index,
+-				     &anx9805_i2c_algo, &port);
++				      &anx9805_i2c_algo, &anx9805_i2c_func,
++				      &port);
+ 	*pobject = nv_object(port);
+ 	if (ret)
+ 		return ret;
+@@ -256,8 +256,6 @@ anx9805_ddc_port_ctor(struct nouveau_object *parent,
+ 		struct i2c_algo_bit_data *algo = mast->adapter.algo_data;
+ 		algo->udelay = max(algo->udelay, 40);
+ 	}
+-
+-	port->base.func = &anx9805_i2c_func;
+ 	return 0;
+ }
+ 
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
+index 8ae2625415e1..2895c19bb152 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
+@@ -95,6 +95,7 @@ nouveau_i2c_port_create_(struct nouveau_object *parent,
+ 			 struct nouveau_object *engine,
+ 			 struct nouveau_oclass *oclass, u8 index,
+ 			 const struct i2c_algorithm *algo,
++			 const struct nouveau_i2c_func *func,
+ 			 int size, void **pobject)
+ {
+ 	struct nouveau_device *device = nv_device(parent);
+@@ -112,6 +113,7 @@ nouveau_i2c_port_create_(struct nouveau_object *parent,
+ 	port->adapter.owner = THIS_MODULE;
+ 	port->adapter.dev.parent = &device->pdev->dev;
+ 	port->index = index;
++	port->func = func;
+ 	i2c_set_adapdata(&port->adapter, i2c);
+ 
+ 	if ( algo == &nouveau_i2c_bit_algo &&
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c
+index 2ad18840fe63..860d5d2365da 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c
+@@ -91,12 +91,12 @@ nv04_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	int ret;
+ 
+ 	ret = nouveau_i2c_port_create(parent, engine, oclass, index,
+-				     &nouveau_i2c_bit_algo, &port);
++				      &nouveau_i2c_bit_algo, &nv04_i2c_func,
++				      &port);
+ 	*pobject = nv_object(port);
+ 	if (ret)
+ 		return ret;
+ 
+-	port->base.func = &nv04_i2c_func;
+ 	port->drive = info->drive;
+ 	port->sense = info->sense;
+ 	return 0;
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c
+index f501ae25dbb3..0c2655a03bb4 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c
+@@ -84,12 +84,12 @@ nv4e_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	int ret;
+ 
+ 	ret = nouveau_i2c_port_create(parent, engine, oclass, index,
+-				     &nouveau_i2c_bit_algo, &port);
++				      &nouveau_i2c_bit_algo, &nv4e_i2c_func,
++				      &port);
+ 	*pobject = nv_object(port);
+ 	if (ret)
+ 		return ret;
+ 
+-	port->base.func = &nv4e_i2c_func;
+ 	port->addr = 0x600800 + info->drive;
+ 	return 0;
+ }
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c
+index 378dfa324e5f..a8d67a287704 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c
+@@ -85,7 +85,8 @@ nv50_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	int ret;
+ 
+ 	ret = nouveau_i2c_port_create(parent, engine, oclass, index,
+-				     &nouveau_i2c_bit_algo, &port);
++				      &nouveau_i2c_bit_algo, &nv50_i2c_func,
++				      &port);
+ 	*pobject = nv_object(port);
+ 	if (ret)
+ 		return ret;
+@@ -93,7 +94,6 @@ nv50_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	if (info->drive >= nv50_i2c_addr_nr)
+ 		return -EINVAL;
+ 
+-	port->base.func = &nv50_i2c_func;
+ 	port->state = 0x00000007;
+ 	port->addr = nv50_i2c_addr[info->drive];
+ 	return 0;
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c
+index 61b771670bfe..df6d3e4b68be 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c
+@@ -186,7 +186,8 @@ nv94_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	int ret;
+ 
+ 	ret = nouveau_i2c_port_create(parent, engine, oclass, index,
+-				     &nouveau_i2c_bit_algo, &port);
++				      &nouveau_i2c_bit_algo, &nv94_i2c_func,
++				      &port);
+ 	*pobject = nv_object(port);
+ 	if (ret)
+ 		return ret;
+@@ -194,7 +195,6 @@ nv94_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	if (info->drive >= nv50_i2c_addr_nr)
+ 		return -EINVAL;
+ 
+-	port->base.func = &nv94_i2c_func;
+ 	port->state = 7;
+ 	port->addr = nv50_i2c_addr[info->drive];
+ 	if (info->share != DCB_I2C_UNUSED) {
+@@ -221,12 +221,12 @@ nv94_aux_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	int ret;
+ 
+ 	ret = nouveau_i2c_port_create(parent, engine, oclass, index,
+-				     &nouveau_i2c_aux_algo, &port);
++				      &nouveau_i2c_aux_algo, &nv94_aux_func,
++				      &port);
+ 	*pobject = nv_object(port);
+ 	if (ret)
+ 		return ret;
+ 
+-	port->base.func = &nv94_aux_func;
+ 	port->addr = info->drive;
+ 	if (info->share != DCB_I2C_UNUSED) {
+ 		port->ctrl = 0x00e500 + (info->drive * 0x50);
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c
+index f761b8a610f1..29967d30f97c 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c
+@@ -60,12 +60,12 @@ nvd0_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	int ret;
+ 
+ 	ret = nouveau_i2c_port_create(parent, engine, oclass, index,
+-				     &nouveau_i2c_bit_algo, &port);
++				      &nouveau_i2c_bit_algo, &nvd0_i2c_func,
++				      &port);
+ 	*pobject = nv_object(port);
+ 	if (ret)
+ 		return ret;
+ 
+-	port->base.func = &nvd0_i2c_func;
+ 	port->state = 0x00000007;
+ 	port->addr = 0x00d014 + (info->drive * 0x20);
+ 	if (info->share != DCB_I2C_UNUSED) {

commit c98b81946827fe04c36bfa6bb376ffa739b0c2d0
+Author: Ilia Mirkin 
+Date:   Mon Jul 29 19:05:16 2013 -0400
+
+    drm/nouveau: remove duplicate copy of nv44_graph_class
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h
+index 7da35a4e7970..ad8209377529 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h
++++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h
+@@ -1,6 +1,9 @@
+ #ifndef __NV40_GRAPH_H__
+ #define __NV40_GRAPH_H__
+ 
++#include 
++#include 
++
+ /* returns 1 if device is one of the nv4x using the 0x4497 object class,
+  * helpful to determine a number of other hardware features
+  */
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c
+index 716bf41bc3c1..b10a143787a7 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c
+@@ -22,15 +22,9 @@
+  * Authors: Ben Skeggs
+  */
+ 
+-#include "nv04.h"
++#include 
+ 
+-static inline int
+-nv44_graph_class(struct nv04_instmem_priv *priv)
+-{
+-	if ((nv_device(priv)->chipset & 0xf0) == 0x60)
+-		return 1;
+-	return !(0x0baf & (1 << (nv_device(priv)->chipset & 0x0f)));
+-}
++#include "nv04.h"
+ 
+ static int
+ nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,

commit ef7d64e5c27bc2587b4a20c9ae04413ce679bd8c
+Author: Ilia Mirkin 
+Date:   Sun Jul 28 22:30:06 2013 -0400
+
+    drm/nouveau/vdec: implement support for VP3 engines
+    
+    For NV98+, BSP/VP/PPP are all FUC-based engines. Hook them all up in the
+    same way as NVC0, but with a couple of different values. Also make sure
+    that the PPP engine is handled in the fifo/mc/vm.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/bsp/nv98.c b/drivers/gpu/drm/nouveau/core/engine/bsp/nv98.c
+index 8bf92b0e6d82..6b089e022fd2 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/bsp/nv98.c
++++ b/drivers/gpu/drm/nouveau/core/engine/bsp/nv98.c
+@@ -19,16 +19,14 @@
+  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  * OTHER DEALINGS IN THE SOFTWARE.
+  *
+- * Authors: Ben Skeggs
++ * Authors: Ben Skeggs, Maarten Lankhorst, Ilia Mirkin
+  */
+ 
+-#include 
+-#include 
+-
++#include 
+ #include 
+ 
+ struct nv98_bsp_priv {
+-	struct nouveau_engine base;
++	struct nouveau_falcon base;
+ };
+ 
+ /*******************************************************************************
+@@ -37,30 +35,48 @@ struct nv98_bsp_priv {
+ 
+ static struct nouveau_oclass
+ nv98_bsp_sclass[] = {
++	{ 0x88b1, &nouveau_object_ofuncs },
++	{ 0x85b1, &nouveau_object_ofuncs },
++	{ 0x86b1, &nouveau_object_ofuncs },
+ 	{},
+ };
+ 
+ /*******************************************************************************
+- * BSP context
++ * PBSP context
+  ******************************************************************************/
+ 
+ static struct nouveau_oclass
+ nv98_bsp_cclass = {
+ 	.handle = NV_ENGCTX(BSP, 0x98),
+ 	.ofuncs = &(struct nouveau_ofuncs) {
+-		.ctor = _nouveau_engctx_ctor,
+-		.dtor = _nouveau_engctx_dtor,
+-		.init = _nouveau_engctx_init,
+-		.fini = _nouveau_engctx_fini,
+-		.rd32 = _nouveau_engctx_rd32,
+-		.wr32 = _nouveau_engctx_wr32,
++		.ctor = _nouveau_falcon_context_ctor,
++		.dtor = _nouveau_falcon_context_dtor,
++		.init = _nouveau_falcon_context_init,
++		.fini = _nouveau_falcon_context_fini,
++		.rd32 = _nouveau_falcon_context_rd32,
++		.wr32 = _nouveau_falcon_context_wr32,
+ 	},
+ };
+ 
+ /*******************************************************************************
+- * BSP engine/subdev functions
++ * PBSP engine/subdev functions
+  ******************************************************************************/
+ 
++static int
++nv98_bsp_init(struct nouveau_object *object)
++{
++	struct nv98_bsp_priv *priv = (void *)object;
++	int ret;
++
++	ret = nouveau_falcon_init(&priv->base);
++	if (ret)
++		return ret;
++
++	nv_wr32(priv, 0x084010, 0x0000ffd2);
++	nv_wr32(priv, 0x08401c, 0x0000fff2);
++	return 0;
++}
++
+ static int
+ nv98_bsp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	      struct nouveau_oclass *oclass, void *data, u32 size,
+@@ -69,7 +85,7 @@ nv98_bsp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	struct nv98_bsp_priv *priv;
+ 	int ret;
+ 
+-	ret = nouveau_engine_create(parent, engine, oclass, true,
++	ret = nouveau_falcon_create(parent, engine, oclass, 0x084000, true,
+ 				    "PBSP", "bsp", &priv);
+ 	*pobject = nv_object(priv);
+ 	if (ret)
+@@ -86,8 +102,10 @@ nv98_bsp_oclass = {
+ 	.handle = NV_ENGINE(BSP, 0x98),
+ 	.ofuncs = &(struct nouveau_ofuncs) {
+ 		.ctor = nv98_bsp_ctor,
+-		.dtor = _nouveau_engine_dtor,
+-		.init = _nouveau_engine_init,
+-		.fini = _nouveau_engine_fini,
++		.dtor = _nouveau_falcon_dtor,
++		.init = nv98_bsp_init,
++		.fini = _nouveau_falcon_fini,
++		.rd32 = _nouveau_falcon_rd32,
++		.wr32 = _nouveau_falcon_wr32,
+ 	},
+ };
+diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
+index 433b2d8b73b2..91a87cd7195a 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
++++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
+@@ -56,6 +56,7 @@ nv84_fifo_context_attach(struct nouveau_object *parent,
+ 	case NVDEV_ENGINE_SW   : return 0;
+ 	case NVDEV_ENGINE_GR   : addr = 0x0020; break;
+ 	case NVDEV_ENGINE_VP   : addr = 0x0040; break;
++	case NVDEV_ENGINE_PPP  :
+ 	case NVDEV_ENGINE_MPEG : addr = 0x0060; break;
+ 	case NVDEV_ENGINE_BSP  : addr = 0x0080; break;
+ 	case NVDEV_ENGINE_CRYPT: addr = 0x00a0; break;
+@@ -91,6 +92,7 @@ nv84_fifo_context_detach(struct nouveau_object *parent, bool suspend,
+ 	case NVDEV_ENGINE_SW   : return 0;
+ 	case NVDEV_ENGINE_GR   : engn = 0; addr = 0x0020; break;
+ 	case NVDEV_ENGINE_VP   : engn = 3; addr = 0x0040; break;
++	case NVDEV_ENGINE_PPP  :
+ 	case NVDEV_ENGINE_MPEG : engn = 1; addr = 0x0060; break;
+ 	case NVDEV_ENGINE_BSP  : engn = 5; addr = 0x0080; break;
+ 	case NVDEV_ENGINE_CRYPT: engn = 4; addr = 0x00a0; break;
+diff --git a/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c b/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c
+index 5a5b2a773ed7..13bf31c40aa1 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c
++++ b/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c
+@@ -19,21 +19,14 @@
+  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  * OTHER DEALINGS IN THE SOFTWARE.
+  *
+- * Authors: Ben Skeggs
++ * Authors: Ben Skeggs, Maarten Lankhorst, Ilia Mirkin
+  */
+ 
+-#include 
+-#include 
+-#include 
+-
++#include 
+ #include 
+ 
+ struct nv98_ppp_priv {
+-	struct nouveau_engine base;
+-};
+-
+-struct nv98_ppp_chan {
+-	struct nouveau_engctx base;
++	struct nouveau_falcon base;
+ };
+ 
+ /*******************************************************************************
+@@ -42,6 +35,8 @@ struct nv98_ppp_chan {
+ 
+ static struct nouveau_oclass
+ nv98_ppp_sclass[] = {
++	{ 0x88b3, &nouveau_object_ofuncs },
++	{ 0x85b3, &nouveau_object_ofuncs },
+ 	{},
+ };
+ 
+@@ -53,12 +48,12 @@ static struct nouveau_oclass
+ nv98_ppp_cclass = {
+ 	.handle = NV_ENGCTX(PPP, 0x98),
+ 	.ofuncs = &(struct nouveau_ofuncs) {
+-		.ctor = _nouveau_engctx_ctor,
+-		.dtor = _nouveau_engctx_dtor,
+-		.init = _nouveau_engctx_init,
+-		.fini = _nouveau_engctx_fini,
+-		.rd32 = _nouveau_engctx_rd32,
+-		.wr32 = _nouveau_engctx_wr32,
++		.ctor = _nouveau_falcon_context_ctor,
++		.dtor = _nouveau_falcon_context_dtor,
++		.init = _nouveau_falcon_context_init,
++		.fini = _nouveau_falcon_context_fini,
++		.rd32 = _nouveau_falcon_context_rd32,
++		.wr32 = _nouveau_falcon_context_wr32,
+ 	},
+ };
+ 
+@@ -66,6 +61,21 @@ nv98_ppp_cclass = {
+  * PPPP engine/subdev functions
+  ******************************************************************************/
+ 
++static int
++nv98_ppp_init(struct nouveau_object *object)
++{
++	struct nv98_ppp_priv *priv = (void *)object;
++	int ret;
++
++	ret = nouveau_falcon_init(&priv->base);
++	if (ret)
++		return ret;
++
++	nv_wr32(priv, 0x086010, 0x0000ffd2);
++	nv_wr32(priv, 0x08601c, 0x0000fff2);
++	return 0;
++}
++
+ static int
+ nv98_ppp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	      struct nouveau_oclass *oclass, void *data, u32 size,
+@@ -74,7 +84,7 @@ nv98_ppp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	struct nv98_ppp_priv *priv;
+ 	int ret;
+ 
+-	ret = nouveau_engine_create(parent, engine, oclass, true,
++	ret = nouveau_falcon_create(parent, engine, oclass, 0x086000, true,
+ 				    "PPPP", "ppp", &priv);
+ 	*pobject = nv_object(priv);
+ 	if (ret)
+@@ -91,8 +101,10 @@ nv98_ppp_oclass = {
+ 	.handle = NV_ENGINE(PPP, 0x98),
+ 	.ofuncs = &(struct nouveau_ofuncs) {
+ 		.ctor = nv98_ppp_ctor,
+-		.dtor = _nouveau_engine_dtor,
+-		.init = _nouveau_engine_init,
+-		.fini = _nouveau_engine_fini,
++		.dtor = _nouveau_falcon_dtor,
++		.init = nv98_ppp_init,
++		.fini = _nouveau_falcon_fini,
++		.rd32 = _nouveau_falcon_rd32,
++		.wr32 = _nouveau_falcon_wr32,
+ 	},
+ };
+diff --git a/drivers/gpu/drm/nouveau/core/engine/vp/nv98.c b/drivers/gpu/drm/nouveau/core/engine/vp/nv98.c
+index 8a8236bc84de..fc9ae0ff1ef5 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/vp/nv98.c
++++ b/drivers/gpu/drm/nouveau/core/engine/vp/nv98.c
+@@ -19,16 +19,14 @@
+  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  * OTHER DEALINGS IN THE SOFTWARE.
+  *
+- * Authors: Ben Skeggs
++ * Authors: Ben Skeggs, Maarten Lankhorst, Ilia Mirkin
+  */
+ 
+-#include 
+-#include 
+-
++#include 
+ #include 
+ 
+ struct nv98_vp_priv {
+-	struct nouveau_engine base;
++	struct nouveau_falcon base;
+ };
+ 
+ /*******************************************************************************
+@@ -37,6 +35,8 @@ struct nv98_vp_priv {
+ 
+ static struct nouveau_oclass
+ nv98_vp_sclass[] = {
++	{ 0x88b2, &nouveau_object_ofuncs },
++	{ 0x85b2, &nouveau_object_ofuncs },
+ 	{},
+ };
+ 
+@@ -48,12 +48,12 @@ static struct nouveau_oclass
+ nv98_vp_cclass = {
+ 	.handle = NV_ENGCTX(VP, 0x98),
+ 	.ofuncs = &(struct nouveau_ofuncs) {
+-		.ctor = _nouveau_engctx_ctor,
+-		.dtor = _nouveau_engctx_dtor,
+-		.init = _nouveau_engctx_init,
+-		.fini = _nouveau_engctx_fini,
+-		.rd32 = _nouveau_engctx_rd32,
+-		.wr32 = _nouveau_engctx_wr32,
++		.ctor = _nouveau_falcon_context_ctor,
++		.dtor = _nouveau_falcon_context_dtor,
++		.init = _nouveau_falcon_context_init,
++		.fini = _nouveau_falcon_context_fini,
++		.rd32 = _nouveau_falcon_context_rd32,
++		.wr32 = _nouveau_falcon_context_wr32,
+ 	},
+ };
+ 
+@@ -61,6 +61,21 @@ nv98_vp_cclass = {
+  * PVP engine/subdev functions
+  ******************************************************************************/
+ 
++static int
++nv98_vp_init(struct nouveau_object *object)
++{
++	struct nv98_vp_priv *priv = (void *)object;
++	int ret;
++
++	ret = nouveau_falcon_init(&priv->base);
++	if (ret)
++		return ret;
++
++	nv_wr32(priv, 0x085010, 0x0000ffd2);
++	nv_wr32(priv, 0x08501c, 0x0000fff2);
++	return 0;
++}
++
+ static int
+ nv98_vp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	     struct nouveau_oclass *oclass, void *data, u32 size,
+@@ -69,7 +84,7 @@ nv98_vp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	struct nv98_vp_priv *priv;
+ 	int ret;
+ 
+-	ret = nouveau_engine_create(parent, engine, oclass, true,
++	ret = nouveau_falcon_create(parent, engine, oclass, 0x085000, true,
+ 				    "PVP", "vp", &priv);
+ 	*pobject = nv_object(priv);
+ 	if (ret)
+@@ -86,8 +101,10 @@ nv98_vp_oclass = {
+ 	.handle = NV_ENGINE(VP, 0x98),
+ 	.ofuncs = &(struct nouveau_ofuncs) {
+ 		.ctor = nv98_vp_ctor,
+-		.dtor = _nouveau_engine_dtor,
+-		.init = _nouveau_engine_init,
+-		.fini = _nouveau_engine_fini,
++		.dtor = _nouveau_falcon_dtor,
++		.init = nv98_vp_init,
++		.fini = _nouveau_falcon_fini,
++		.rd32 = _nouveau_falcon_rd32,
++		.wr32 = _nouveau_falcon_wr32,
+ 	},
+ };
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c
+index 0d57b4d3e001..06710419a59b 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c
+@@ -35,6 +35,7 @@ nv98_mc_intr[] = {
+ 	{ 0x00001000, NVDEV_ENGINE_GR },
+ 	{ 0x00004000, NVDEV_ENGINE_CRYPT },	/* NV84:NVA3 */
+ 	{ 0x00008000, NVDEV_ENGINE_BSP },
++	{ 0x00020000, NVDEV_ENGINE_VP },
+ 	{ 0x00080000, NVDEV_SUBDEV_THERM },	/* NVA3:NVC0 */
+ 	{ 0x00100000, NVDEV_SUBDEV_TIMER },
+ 	{ 0x00200000, NVDEV_SUBDEV_GPIO },
+@@ -42,7 +43,7 @@ nv98_mc_intr[] = {
+ 	{ 0x04000000, NVDEV_ENGINE_DISP },
+ 	{ 0x10000000, NVDEV_SUBDEV_BUS },
+ 	{ 0x80000000, NVDEV_ENGINE_SW },
+-	{ 0x0040d101, NVDEV_SUBDEV_FB },
++	{ 0x0042d101, NVDEV_SUBDEV_FB },
+ 	{},
+ };
+ 
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c
+index 07dd1fe2d6fb..a4aa81a2173b 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c
+@@ -174,6 +174,7 @@ nv50_vm_flush(struct nouveau_vm *vm)
+ 		case NVDEV_ENGINE_GR   : vme = 0x00; break;
+ 		case NVDEV_ENGINE_VP   : vme = 0x01; break;
+ 		case NVDEV_SUBDEV_BAR  : vme = 0x06; break;
++		case NVDEV_ENGINE_PPP  :
+ 		case NVDEV_ENGINE_MPEG : vme = 0x08; break;
+ 		case NVDEV_ENGINE_BSP  : vme = 0x09; break;
+ 		case NVDEV_ENGINE_CRYPT: vme = 0x0a; break;

commit 57be046e5af098ab2ff972269799ef495a7f8a2b
+Author: Ilia Mirkin 
+Date:   Sat Jul 27 00:27:00 2013 -0400
+
+    drm/nouveau/core: get rid of math.h, replace log2i with order_base_2
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/core/ramht.c b/drivers/gpu/drm/nouveau/core/core/ramht.c
+index 86a64045dd60..f3b9bddc3875 100644
+--- a/drivers/gpu/drm/nouveau/core/core/ramht.c
++++ b/drivers/gpu/drm/nouveau/core/core/ramht.c
+@@ -22,7 +22,6 @@
+ 
+ #include 
+ #include 
+-#include 
+ 
+ #include 
+ 
+@@ -104,6 +103,6 @@ nouveau_ramht_new(struct nouveau_object *parent, struct nouveau_object *pargpu,
+ 	if (ret)
+ 		return ret;
+ 
+-	ramht->bits = log2i(nv_gpuobj(ramht)->size >> 3);
++	ramht->bits = order_base_2(nv_gpuobj(ramht)->size >> 3);
+ 	return 0;
+ }
+diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c
+index e9b8217d0075..7e5dff51d3c5 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c
++++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c
+@@ -26,7 +26,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ 
+ #include 
+ #include 
+@@ -278,7 +277,7 @@ nv50_fifo_chan_ctor_ind(struct nouveau_object *parent,
+ 		return ret;
+ 
+ 	ioffset = args->ioffset;
+-	ilength = log2i(args->ilength / 8);
++	ilength = order_base_2(args->ilength / 8);
+ 
+ 	nv_wo32(base->ramfc, 0x3c, 0x403f6078);
+ 	nv_wo32(base->ramfc, 0x44, 0x01003fff);
+diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
+index 7f53196cff52..433b2d8b73b2 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
++++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
+@@ -28,7 +28,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ 
+ #include 
+ #include 
+@@ -258,7 +257,7 @@ nv84_fifo_chan_ctor_ind(struct nouveau_object *parent,
+ 	nv_parent(chan)->object_detach = nv50_fifo_object_detach;
+ 
+ 	ioffset = args->ioffset;
+-	ilength = log2i(args->ilength / 8);
++	ilength = order_base_2(args->ilength / 8);
+ 
+ 	nv_wo32(base->ramfc, 0x3c, 0x403f6078);
+ 	nv_wo32(base->ramfc, 0x44, 0x01003fff);
+diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
+index 46dfa68c47bb..ce92f289e751 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
++++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
+@@ -29,7 +29,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ #include 
+ 
+ #include 
+@@ -200,7 +199,7 @@ nvc0_fifo_chan_ctor(struct nouveau_object *parent,
+ 
+ 	usermem = chan->base.chid * 0x1000;
+ 	ioffset = args->ioffset;
+-	ilength = log2i(args->ilength / 8);
++	ilength = order_base_2(args->ilength / 8);
+ 
+ 	for (i = 0; i < 0x1000; i += 4)
+ 		nv_wo32(priv->user.mem, usermem + i, 0x00000000);
+diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
+index 09644fa9602c..8e8121abe31b 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
++++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
+@@ -29,7 +29,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ #include 
+ 
+ #include 
+@@ -240,7 +239,7 @@ nve0_fifo_chan_ctor(struct nouveau_object *parent,
+ 
+ 	usermem = chan->base.chid * 0x200;
+ 	ioffset = args->ioffset;
+-	ilength = log2i(args->ilength / 8);
++	ilength = order_base_2(args->ilength / 8);
+ 
+ 	for (i = 0; i < 0x200; i += 4)
+ 		nv_wo32(priv->user.mem, usermem + i, 0x00000000);
+diff --git a/drivers/gpu/drm/nouveau/core/include/core/math.h b/drivers/gpu/drm/nouveau/core/include/core/math.h
+deleted file mode 100644
+index f808131c5cd8..000000000000
+--- a/drivers/gpu/drm/nouveau/core/include/core/math.h
++++ /dev/null
+@@ -1,16 +0,0 @@
+-#ifndef __NOUVEAU_MATH_H__
+-#define __NOUVEAU_MATH_H__
+-
+-static inline int
+-log2i(u64 base)
+-{
+-	u64 temp = base >> 1;
+-	int log2;
+-
+-	for (log2 = 0; temp; log2++, temp >>= 1) {
+-	}
+-
+-	return (base & (base - 1)) ? log2 + 1: log2;
+-}
+-
+-#endif
+diff --git a/drivers/gpu/drm/nouveau/core/os.h b/drivers/gpu/drm/nouveau/core/os.h
+index 3bd9be2ab37f..d48683a82585 100644
+--- a/drivers/gpu/drm/nouveau/core/os.h
++++ b/drivers/gpu/drm/nouveau/core/os.h
+@@ -13,11 +13,12 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ 

commit 6284bf41b97fb36ed96b664a3c23b6dc3661f5f9
+Author: Ilia Mirkin 
+Date:   Fri Aug 9 17:25:54 2013 -0400
+
+    drm/nouveau/fb: fix null derefs in nv49 and nv4e init
+    
+    Commit dceef5d87 (drm/nouveau/fb: initialise vram controller as pfb
+    sub-object) moved some code around and introduced these null derefs.
+    pfb->ram is set to the new ram object outside of this ctor.
+    
+    Reported-by: Ronald Uitermark 
+    Tested-by: Ronald Uitermark 
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv49.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv49.c
+index 19e3a9a63a02..ab7ef0ac9e34 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv49.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv49.c
+@@ -40,15 +40,15 @@ nv49_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,
+ 		return ret;
+ 
+ 	switch (pfb914 & 0x00000003) {
+-	case 0x00000000: pfb->ram->type = NV_MEM_TYPE_DDR1; break;
+-	case 0x00000001: pfb->ram->type = NV_MEM_TYPE_DDR2; break;
+-	case 0x00000002: pfb->ram->type = NV_MEM_TYPE_GDDR3; break;
++	case 0x00000000: ram->type = NV_MEM_TYPE_DDR1; break;
++	case 0x00000001: ram->type = NV_MEM_TYPE_DDR2; break;
++	case 0x00000002: ram->type = NV_MEM_TYPE_GDDR3; break;
+ 	case 0x00000003: break;
+ 	}
+ 
+-	pfb->ram->size  =  nv_rd32(pfb, 0x10020c) & 0xff000000;
+-	pfb->ram->parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1;
+-	pfb->ram->tags  =  nv_rd32(pfb, 0x100320);
++	ram->size  =  nv_rd32(pfb, 0x10020c) & 0xff000000;
++	ram->parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1;
++	ram->tags  =  nv_rd32(pfb, 0x100320);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv4e.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv4e.c
+index 7192aa6e5577..63a6aab86028 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv4e.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv4e.c
+@@ -38,8 +38,8 @@ nv4e_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	if (ret)
+ 		return ret;
+ 
+-	pfb->ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000;
+-	pfb->ram->type = NV_MEM_TYPE_STOLEN;
++	ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000;
++	ram->type = NV_MEM_TYPE_STOLEN;
+ 	return 0;
+ }
+ 

commit b21e3afe2357c0f49348a5fb61247012bf8262ec
+Author: Ilia Mirkin 
+Date:   Wed Aug 7 22:34:48 2013 -0400
+
+    drm: use ida to allocate connector ids
+    
+    This makes it so that reloading a module does not cause all the
+    connector ids to change, which are user-visible and sometimes used
+    for configuration.
+    
+    Signed-off-by: Ilia Mirkin 
+    Reviewed-by: Ville Syrjälä 
+    Signed-off-by: Dave Airlie 
+
+diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
+index fc83bb9eb514..a6917645fb4a 100644
+--- a/drivers/gpu/drm/drm_crtc.c
++++ b/drivers/gpu/drm/drm_crtc.c
+@@ -186,29 +186,29 @@ static const struct drm_prop_enum_list drm_dirty_info_enum_list[] = {
+ struct drm_conn_prop_enum_list {
+ 	int type;
+ 	const char *name;
+-	int count;
++	struct ida ida;
+ };
+ 
+ /*
+  * Connector and encoder types.
+  */
+ static struct drm_conn_prop_enum_list drm_connector_enum_list[] =
+-{	{ DRM_MODE_CONNECTOR_Unknown, "Unknown", 0 },
+-	{ DRM_MODE_CONNECTOR_VGA, "VGA", 0 },
+-	{ DRM_MODE_CONNECTOR_DVII, "DVI-I", 0 },
+-	{ DRM_MODE_CONNECTOR_DVID, "DVI-D", 0 },
+-	{ DRM_MODE_CONNECTOR_DVIA, "DVI-A", 0 },
+-	{ DRM_MODE_CONNECTOR_Composite, "Composite", 0 },
+-	{ DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO", 0 },
+-	{ DRM_MODE_CONNECTOR_LVDS, "LVDS", 0 },
+-	{ DRM_MODE_CONNECTOR_Component, "Component", 0 },
+-	{ DRM_MODE_CONNECTOR_9PinDIN, "DIN", 0 },
+-	{ DRM_MODE_CONNECTOR_DisplayPort, "DP", 0 },
+-	{ DRM_MODE_CONNECTOR_HDMIA, "HDMI-A", 0 },
+-	{ DRM_MODE_CONNECTOR_HDMIB, "HDMI-B", 0 },
+-	{ DRM_MODE_CONNECTOR_TV, "TV", 0 },
+-	{ DRM_MODE_CONNECTOR_eDP, "eDP", 0 },
+-	{ DRM_MODE_CONNECTOR_VIRTUAL, "Virtual", 0},
++{	{ DRM_MODE_CONNECTOR_Unknown, "Unknown" },
++	{ DRM_MODE_CONNECTOR_VGA, "VGA" },
++	{ DRM_MODE_CONNECTOR_DVII, "DVI-I" },
++	{ DRM_MODE_CONNECTOR_DVID, "DVI-D" },
++	{ DRM_MODE_CONNECTOR_DVIA, "DVI-A" },
++	{ DRM_MODE_CONNECTOR_Composite, "Composite" },
++	{ DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO" },
++	{ DRM_MODE_CONNECTOR_LVDS, "LVDS" },
++	{ DRM_MODE_CONNECTOR_Component, "Component" },
++	{ DRM_MODE_CONNECTOR_9PinDIN, "DIN" },
++	{ DRM_MODE_CONNECTOR_DisplayPort, "DP" },
++	{ DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" },
++	{ DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" },
++	{ DRM_MODE_CONNECTOR_TV, "TV" },
++	{ DRM_MODE_CONNECTOR_eDP, "eDP" },
++	{ DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" },
+ };
+ 
+ static const struct drm_prop_enum_list drm_encoder_enum_list[] =
+@@ -220,6 +220,22 @@ static const struct drm_prop_enum_list drm_encoder_enum_list[] =
+ 	{ DRM_MODE_ENCODER_VIRTUAL, "Virtual" },
+ };
+ 
++void drm_connector_ida_init(void)
++{
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(drm_connector_enum_list); i++)
++		ida_init(&drm_connector_enum_list[i].ida);
++}
++
++void drm_connector_ida_destroy(void)
++{
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(drm_connector_enum_list); i++)
++		ida_destroy(&drm_connector_enum_list[i].ida);
++}
++
+ const char *drm_get_encoder_name(const struct drm_encoder *encoder)
+ {
+ 	static char buf[32];
+@@ -711,6 +727,8 @@ int drm_connector_init(struct drm_device *dev,
+ 		       int connector_type)
+ {
+ 	int ret;
++	struct ida *connector_ida =
++		&drm_connector_enum_list[connector_type].ida;
+ 
+ 	drm_modeset_lock_all(dev);
+ 
+@@ -723,7 +741,12 @@ int drm_connector_init(struct drm_device *dev,
+ 	connector->funcs = funcs;
+ 	connector->connector_type = connector_type;
+ 	connector->connector_type_id =
+-		++drm_connector_enum_list[connector_type].count; /* TODO */
++		ida_simple_get(connector_ida, 1, 0, GFP_KERNEL);
++	if (connector->connector_type_id < 0) {
++		ret = connector->connector_type_id;
++		drm_mode_object_put(dev, &connector->base);
++		goto out;
++	}
+ 	INIT_LIST_HEAD(&connector->probed_modes);
+ 	INIT_LIST_HEAD(&connector->modes);
+ 	connector->edid_blob_ptr = NULL;
+@@ -764,6 +787,9 @@ void drm_connector_cleanup(struct drm_connector *connector)
+ 	list_for_each_entry_safe(mode, t, &connector->modes, head)
+ 		drm_mode_remove(connector, mode);
+ 
++	ida_remove(&drm_connector_enum_list[connector->connector_type].ida,
++		   connector->connector_type_id);
++
+ 	drm_mode_object_put(dev, &connector->base);
+ 	list_del(&connector->head);
+ 	dev->mode_config.num_connector--;
+diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
+index 5b949a736712..d97976cc51cd 100644
+--- a/drivers/gpu/drm/drm_drv.c
++++ b/drivers/gpu/drm/drm_drv.c
+@@ -226,6 +226,7 @@ static int __init drm_core_init(void)
+ 	int ret = -ENOMEM;
+ 
+ 	drm_global_init();
++	drm_connector_ida_init();
+ 	idr_init(&drm_minors_idr);
+ 
+ 	if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
+@@ -273,6 +274,7 @@ static void __exit drm_core_exit(void)
+ 
+ 	unregister_chrdev(DRM_MAJOR, "drm");
+ 
++	drm_connector_ida_destroy();
+ 	idr_destroy(&drm_minors_idr);
+ }
+ 
+diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
+index 32e0820357e6..45f133228553 100644
+--- a/include/drm/drm_crtc.h
++++ b/include/drm/drm_crtc.h
+@@ -869,6 +869,8 @@ extern int drm_crtc_init(struct drm_device *dev,
+ 			 const struct drm_crtc_funcs *funcs);
+ extern void drm_crtc_cleanup(struct drm_crtc *crtc);
+ 
++extern void drm_connector_ida_init(void);
++extern void drm_connector_ida_destroy(void);
+ extern int drm_connector_init(struct drm_device *dev,
+ 			      struct drm_connector *connector,
+ 			      const struct drm_connector_funcs *funcs,

commit dc409df9447a4e3884d150e2b0dbd89242403fa6
+Author: Ilia Mirkin 
+Date:   Mon Jul 29 19:05:18 2013 -0400
+
+    drm/nv31/mpeg: don't recognize nv3x cards as having nv44 graph class
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
+index 9f7c7d53e61e..c19004301309 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
++++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
+@@ -284,7 +284,10 @@ nv31_mpeg_init(struct nouveau_object *object)
+ 	/* PMPEG init */
+ 	nv_wr32(priv, 0x00b32c, 0x00000000);
+ 	nv_wr32(priv, 0x00b314, 0x00000100);
+-	nv_wr32(priv, 0x00b220, nv44_graph_class(priv) ? 0x00000044 : 0x00000031);
++	if (nv_device(priv)->chipset >= 0x40 && nv44_graph_class(priv))
++		nv_wr32(priv, 0x00b220, 0x00000044);
++	else
++		nv_wr32(priv, 0x00b220, 0x00000031);
+ 	nv_wr32(priv, 0x00b300, 0x02001ec1);
+ 	nv_mask(priv, 0x00b32c, 0x00000001, 0x00000001);
+ 

commit 3d8b2b489e490ae63b7eddb3dcdfcee9bc32d473
+Author: Ilia Mirkin 
+Date:   Mon Jul 29 19:05:17 2013 -0400
+
+    drm/nv40/mpeg: write magic value to channel object to make it work
+    
+    Looks like the rewrite in commit ebb945a94b ("drm/nouveau: port all
+    engines to new engine module format") missed that one little detail.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c
+index f7c581ad1991..dd6196072e9c 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c
++++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c
+@@ -61,6 +61,7 @@ nv40_mpeg_context_ctor(struct nouveau_object *parent,
+ 	if (ret)
+ 		return ret;
+ 
++	nv_wo32(&chan->base.base, 0x78, 0x02001ec1);
+ 	return 0;
+ }
+ 

commit 02d69294a174d7cb6a76080b6d16971ca08728d4
+Author: Ilia Mirkin 
+Date:   Sun Jul 28 22:30:57 2013 -0400
+
+    drm/nva3-/disp: fix hda eld writing, needs to be padded
+    
+    Commits 0a9e2b959 (drm/nvd0/disp: move HDA codec setup to core) and
+    a4feaf4ea (drm/nva3/disp: move hda codec handling to core) moved code
+    around but neglected to fill data up to 0x60 as before. This caused
+    /proc/asound/cardN/eld#3.0 to show eld_valid as 0. With this patch, that
+    file is again populated with the correct data.
+    
+    See https://bugs.freedesktop.org/show_bug.cgi?id=67051
+    
+    Reported-and-tested-by: Alex 
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c
+index 373dbcc523b2..a19e7d79b847 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c
++++ b/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c
+@@ -36,6 +36,8 @@ nva3_hda_eld(struct nv50_disp_priv *priv, int or, u8 *data, u32 size)
+ 	if (data && data[0]) {
+ 		for (i = 0; i < size; i++)
+ 			nv_wr32(priv, 0x61c440 + soff, (i << 8) | data[i]);
++		for (; i < 0x60; i++)
++			nv_wr32(priv, 0x61c440 + soff, (i << 8));
+ 		nv_mask(priv, 0x61c448 + soff, 0x80000003, 0x80000003);
+ 	} else
+ 	if (data) {
+diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c
+index dc57e24fc1df..717639386ced 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c
++++ b/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c
+@@ -41,6 +41,8 @@ nvd0_hda_eld(struct nv50_disp_priv *priv, int or, u8 *data, u32 size)
+ 	if (data && data[0]) {
+ 		for (i = 0; i < size; i++)
+ 			nv_wr32(priv, 0x10ec00 + soff, (i << 8) | data[i]);
++		for (; i < 0x60; i++)
++			nv_wr32(priv, 0x10ec00 + soff, (i << 8));
+ 		nv_mask(priv, 0x10ec10 + soff, 0x80000003, 0x80000003);
+ 	} else
+ 	if (data) {

commit 18f35fa6584fb28c674014674de20ed82bb84618
+Author: Ilia Mirkin 
+Date:   Sat Jul 27 00:27:01 2013 -0400
+
+    drm/nv31/mpeg: fix mpeg engine initialization
+    
+    object->engine is null, which leads to a null deref down the line
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
+index 49ecbb859b25..9f7c7d53e61e 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
++++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
+@@ -265,8 +265,8 @@ nv31_mpeg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ int
+ nv31_mpeg_init(struct nouveau_object *object)
+ {
+-	struct nouveau_engine *engine = nv_engine(object->engine);
+-	struct nv31_mpeg_priv *priv = (void *)engine;
++	struct nouveau_engine *engine = nv_engine(object);
++	struct nv31_mpeg_priv *priv = (void *)object;
+ 	struct nouveau_fb *pfb = nouveau_fb(object);
+ 	int ret, i;
+ 

commit 921837634de046acd32a7e02157349be4e97885a
+Author: Ilia Mirkin 
+Date:   Sat Jul 27 00:26:59 2013 -0400
+
+    drm/nv50/mc: include vp in the fb error reporting mask
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c
+index 0cb322a5e72c..f25fc5fc7dd1 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c
+@@ -41,7 +41,7 @@ nv50_mc_intr[] = {
+ 	{ 0x04000000, NVDEV_ENGINE_DISP },
+ 	{ 0x10000000, NVDEV_SUBDEV_BUS },
+ 	{ 0x80000000, NVDEV_ENGINE_SW },
+-	{ 0x0000d101, NVDEV_SUBDEV_FB },
++	{ 0x0002d101, NVDEV_SUBDEV_FB },
+ 	{},
+ };
+ 

commit bfcd92a0ae2996a34b1fd020b3e0951946ae6903
+Author: Ilia Mirkin 
+Date:   Fri Jul 19 06:27:45 2013 -0400
+
+    drm/nouveau/core: xtensa firmware size needs to be 0x40000 no matter what
+    
+    The current logic is wrong since we send fw->size >> 8 to the
+    card. Rounding the size up by 0x100 and 0x1000 didn't seem to help,
+    the card still hung, so go back to what the blob does -- 0x40000.
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/xtensa.c b/drivers/gpu/drm/nouveau/core/engine/xtensa.c
+index 0639bc59d0a5..5f6ede7c4892 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/xtensa.c
++++ b/drivers/gpu/drm/nouveau/core/engine/xtensa.c
+@@ -118,7 +118,13 @@ _nouveau_xtensa_init(struct nouveau_object *object)
+ 			return ret;
+ 		}
+ 
+-		ret = nouveau_gpuobj_new(object, NULL, fw->size, 0x1000, 0,
++		if (fw->size > 0x40000) {
++			nv_warn(xtensa, "firmware %s too large\n", name);
++			release_firmware(fw);
++			return -EINVAL;
++		}
++
++		ret = nouveau_gpuobj_new(object, NULL, 0x40000, 0x1000, 0,
+ 					 &xtensa->gpu_fw);
+ 		if (ret) {
+ 			release_firmware(fw);

commit bf03d1b293cc556df53545e318110505014d805e
+Author: Ilia Mirkin 
+Date:   Wed Jul 3 03:06:02 2013 -0400
+
+    drm/nva3/disp: Fix HDMI audio regression
+    
+    This is the nva3 counterpart to commit beba44b17 (drm/nv84/disp: Fix
+    HDMI audio regression). The regression happened as a result of
+    refactoring in commit 8e9e3d2de (drm/nv84/disp: move hdmi control into
+    core).
+    
+    Reported-and-tested-by: Max Baldwin 
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+    Cc: stable@vger.kernel.org
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c
+index f065fc248adf..db8c6fd46278 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c
++++ b/drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c
+@@ -55,6 +55,10 @@ nva3_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
+ 	nv_wr32(priv, 0x61c510 + soff, 0x00000000);
+ 	nv_mask(priv, 0x61c500 + soff, 0x00000001, 0x00000001);
+ 
++	nv_mask(priv, 0x61c5d0 + soff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */
++	nv_mask(priv, 0x61c568 + soff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */
++	nv_mask(priv, 0x61c578 + soff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */
++
+ 	/* ??? */
+ 	nv_mask(priv, 0x61733c, 0x00100000, 0x00100000); /* RESETF */
+ 	nv_mask(priv, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */

commit 05f9a5bc58381f58095d8789e1c2d4e18758c2bc
+Author: Ilia Mirkin 
+Date:   Thu Jun 27 14:14:01 2013 +1000
+
+    drm/nouveau/bsp/nv84: initial vp2 engine implementation
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c
+index 1d9f614cb97d..1e8e75c0684a 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c
++++ b/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c
+@@ -19,24 +19,19 @@
+  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  * OTHER DEALINGS IN THE SOFTWARE.
+  *
+- * Authors: Ben Skeggs
++ * Authors: Ben Skeggs, Ilia Mirkin
+  */
+ 
+-#include 
+-#include 
+-
++#include 
+ #include 
+ 
+-struct nv84_bsp_priv {
+-	struct nouveau_engine base;
+-};
+-
+ /*******************************************************************************
+  * BSP object classes
+  ******************************************************************************/
+ 
+ static struct nouveau_oclass
+ nv84_bsp_sclass[] = {
++	{ 0x74b0, &nouveau_object_ofuncs },
+ 	{},
+ };
+ 
+@@ -48,7 +43,7 @@ static struct nouveau_oclass
+ nv84_bsp_cclass = {
+ 	.handle = NV_ENGCTX(BSP, 0x84),
+ 	.ofuncs = &(struct nouveau_ofuncs) {
+-		.ctor = _nouveau_engctx_ctor,
++		.ctor = _nouveau_xtensa_engctx_ctor,
+ 		.dtor = _nouveau_engctx_dtor,
+ 		.init = _nouveau_engctx_init,
+ 		.fini = _nouveau_engctx_fini,
+@@ -66,10 +61,10 @@ nv84_bsp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	      struct nouveau_oclass *oclass, void *data, u32 size,
+ 	      struct nouveau_object **pobject)
+ {
+-	struct nv84_bsp_priv *priv;
++	struct nouveau_xtensa *priv;
+ 	int ret;
+ 
+-	ret = nouveau_engine_create(parent, engine, oclass, true,
++	ret = nouveau_xtensa_create(parent, engine, oclass, 0x103000, true,
+ 				    "PBSP", "bsp", &priv);
+ 	*pobject = nv_object(priv);
+ 	if (ret)
+@@ -78,6 +73,8 @@ nv84_bsp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	nv_subdev(priv)->unit = 0x04008000;
+ 	nv_engine(priv)->cclass = &nv84_bsp_cclass;
+ 	nv_engine(priv)->sclass = nv84_bsp_sclass;
++	priv->fifo_val = 0x1111;
++	priv->unkd28 = 0x90044;
+ 	return 0;
+ }
+ 
+@@ -86,8 +83,10 @@ nv84_bsp_oclass = {
+ 	.handle = NV_ENGINE(BSP, 0x84),
+ 	.ofuncs = &(struct nouveau_ofuncs) {
+ 		.ctor = nv84_bsp_ctor,
+-		.dtor = _nouveau_engine_dtor,
+-		.init = _nouveau_engine_init,
+-		.fini = _nouveau_engine_fini,
++		.dtor = _nouveau_xtensa_dtor,
++		.init = _nouveau_xtensa_init,
++		.fini = _nouveau_xtensa_fini,
++		.rd32 = _nouveau_xtensa_rd32,
++		.wr32 = _nouveau_xtensa_wr32,
+ 	},
+ };
+diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
+index 65519dc75ba7..7f53196cff52 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
++++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
+@@ -58,6 +58,7 @@ nv84_fifo_context_attach(struct nouveau_object *parent,
+ 	case NVDEV_ENGINE_GR   : addr = 0x0020; break;
+ 	case NVDEV_ENGINE_VP   : addr = 0x0040; break;
+ 	case NVDEV_ENGINE_MPEG : addr = 0x0060; break;
++	case NVDEV_ENGINE_BSP  : addr = 0x0080; break;
+ 	case NVDEV_ENGINE_CRYPT: addr = 0x00a0; break;
+ 	case NVDEV_ENGINE_COPY0: addr = 0x00c0; break;
+ 	default:
+@@ -92,6 +93,7 @@ nv84_fifo_context_detach(struct nouveau_object *parent, bool suspend,
+ 	case NVDEV_ENGINE_GR   : engn = 0; addr = 0x0020; break;
+ 	case NVDEV_ENGINE_VP   : engn = 3; addr = 0x0040; break;
+ 	case NVDEV_ENGINE_MPEG : engn = 1; addr = 0x0060; break;
++	case NVDEV_ENGINE_BSP  : engn = 5; addr = 0x0080; break;
+ 	case NVDEV_ENGINE_CRYPT: engn = 4; addr = 0x00a0; break;
+ 	case NVDEV_ENGINE_COPY0: engn = 2; addr = 0x00c0; break;
+ 	default:
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c
+index fcae49f678b5..07dd1fe2d6fb 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c
+@@ -175,6 +175,7 @@ nv50_vm_flush(struct nouveau_vm *vm)
+ 		case NVDEV_ENGINE_VP   : vme = 0x01; break;
+ 		case NVDEV_SUBDEV_BAR  : vme = 0x06; break;
+ 		case NVDEV_ENGINE_MPEG : vme = 0x08; break;
++		case NVDEV_ENGINE_BSP  : vme = 0x09; break;
+ 		case NVDEV_ENGINE_CRYPT: vme = 0x0a; break;
+ 		case NVDEV_ENGINE_COPY0: vme = 0x0d; break;
+ 		default:

commit a0376b1481fdb9c9e8064ea0c5af8bd80da3f8f3
+Author: Ilia Mirkin 
+Date:   Thu Jun 27 14:12:46 2013 +1000
+
+    drm/nouveau/vp/nv84: initial vp2 engine implementation
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
+index 35b94bd18808..65519dc75ba7 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
++++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
+@@ -56,6 +56,7 @@ nv84_fifo_context_attach(struct nouveau_object *parent,
+ 	switch (nv_engidx(object->engine)) {
+ 	case NVDEV_ENGINE_SW   : return 0;
+ 	case NVDEV_ENGINE_GR   : addr = 0x0020; break;
++	case NVDEV_ENGINE_VP   : addr = 0x0040; break;
+ 	case NVDEV_ENGINE_MPEG : addr = 0x0060; break;
+ 	case NVDEV_ENGINE_CRYPT: addr = 0x00a0; break;
+ 	case NVDEV_ENGINE_COPY0: addr = 0x00c0; break;
+@@ -89,6 +90,7 @@ nv84_fifo_context_detach(struct nouveau_object *parent, bool suspend,
+ 	switch (nv_engidx(object->engine)) {
+ 	case NVDEV_ENGINE_SW   : return 0;
+ 	case NVDEV_ENGINE_GR   : engn = 0; addr = 0x0020; break;
++	case NVDEV_ENGINE_VP   : engn = 3; addr = 0x0040; break;
+ 	case NVDEV_ENGINE_MPEG : engn = 1; addr = 0x0060; break;
+ 	case NVDEV_ENGINE_CRYPT: engn = 4; addr = 0x00a0; break;
+ 	case NVDEV_ENGINE_COPY0: engn = 2; addr = 0x00c0; break;
+diff --git a/drivers/gpu/drm/nouveau/core/engine/vp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/vp/nv84.c
+index 261cd96e6951..fd6272b8cdb2 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/vp/nv84.c
++++ b/drivers/gpu/drm/nouveau/core/engine/vp/nv84.c
+@@ -19,24 +19,19 @@
+  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  * OTHER DEALINGS IN THE SOFTWARE.
+  *
+- * Authors: Ben Skeggs
++ * Authors: Ben Skeggs, Ilia Mirkin
+  */
+ 
+-#include 
+-#include 
+-
++#include 
+ #include 
+ 
+-struct nv84_vp_priv {
+-	struct nouveau_engine base;
+-};
+-
+ /*******************************************************************************
+  * VP object classes
+  ******************************************************************************/
+ 
+ static struct nouveau_oclass
+ nv84_vp_sclass[] = {
++	{ 0x7476, &nouveau_object_ofuncs },
+ 	{},
+ };
+ 
+@@ -48,7 +43,7 @@ static struct nouveau_oclass
+ nv84_vp_cclass = {
+ 	.handle = NV_ENGCTX(VP, 0x84),
+ 	.ofuncs = &(struct nouveau_ofuncs) {
+-		.ctor = _nouveau_engctx_ctor,
++		.ctor = _nouveau_xtensa_engctx_ctor,
+ 		.dtor = _nouveau_engctx_dtor,
+ 		.init = _nouveau_engctx_init,
+ 		.fini = _nouveau_engctx_fini,
+@@ -66,10 +61,10 @@ nv84_vp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	     struct nouveau_oclass *oclass, void *data, u32 size,
+ 	     struct nouveau_object **pobject)
+ {
+-	struct nv84_vp_priv *priv;
++	struct nouveau_xtensa *priv;
+ 	int ret;
+ 
+-	ret = nouveau_engine_create(parent, engine, oclass, true,
++	ret = nouveau_xtensa_create(parent, engine, oclass, 0xf000, true,
+ 				    "PVP", "vp", &priv);
+ 	*pobject = nv_object(priv);
+ 	if (ret)
+@@ -78,6 +73,8 @@ nv84_vp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ 	nv_subdev(priv)->unit = 0x01020000;
+ 	nv_engine(priv)->cclass = &nv84_vp_cclass;
+ 	nv_engine(priv)->sclass = nv84_vp_sclass;
++	priv->fifo_val = 0x111;
++	priv->unkd28 = 0x9c544;
+ 	return 0;
+ }
+ 
+@@ -86,8 +83,10 @@ nv84_vp_oclass = {
+ 	.handle = NV_ENGINE(VP, 0x84),
+ 	.ofuncs = &(struct nouveau_ofuncs) {
+ 		.ctor = nv84_vp_ctor,
+-		.dtor = _nouveau_engine_dtor,
+-		.init = _nouveau_engine_init,
+-		.fini = _nouveau_engine_fini,
++		.dtor = _nouveau_xtensa_dtor,
++		.init = _nouveau_xtensa_init,
++		.fini = _nouveau_xtensa_fini,
++		.rd32 = _nouveau_xtensa_rd32,
++		.wr32 = _nouveau_xtensa_wr32,
+ 	},
+ };
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c
+index d796924f9930..0cb322a5e72c 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c
+@@ -35,6 +35,7 @@ nv50_mc_intr[] = {
+ 	{ 0x00001000, NVDEV_ENGINE_GR },
+ 	{ 0x00004000, NVDEV_ENGINE_CRYPT },	/* NV84- */
+ 	{ 0x00008000, NVDEV_ENGINE_BSP },	/* NV84- */
++	{ 0x00020000, NVDEV_ENGINE_VP },	/* NV84- */
+ 	{ 0x00100000, NVDEV_SUBDEV_TIMER },
+ 	{ 0x00200000, NVDEV_SUBDEV_GPIO },
+ 	{ 0x04000000, NVDEV_ENGINE_DISP },
+diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c
+index 486c813b9ea9..fcae49f678b5 100644
+--- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c
+@@ -172,6 +172,7 @@ nv50_vm_flush(struct nouveau_vm *vm)
+ 
+ 		switch (i) {
+ 		case NVDEV_ENGINE_GR   : vme = 0x00; break;
++		case NVDEV_ENGINE_VP   : vme = 0x01; break;
+ 		case NVDEV_SUBDEV_BAR  : vme = 0x06; break;
+ 		case NVDEV_ENGINE_MPEG : vme = 0x08; break;
+ 		case NVDEV_ENGINE_CRYPT: vme = 0x0a; break;

commit 44b1e3bd6adc050fac1daccee5bbff019daadc8e
+Author: Ilia Mirkin 
+Date:   Thu Jun 27 14:08:22 2013 +1000
+
+    drm/nouveau/core: xtensa engine base class implementation
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile
+index 78f9aa24f1fd..b59cfd79bd79 100644
+--- a/drivers/gpu/drm/nouveau/Makefile
++++ b/drivers/gpu/drm/nouveau/Makefile
+@@ -142,6 +142,7 @@ nouveau-y += core/subdev/vm/nv50.o
+ nouveau-y += core/subdev/vm/nvc0.o
+ 
+ nouveau-y += core/engine/falcon.o
++nouveau-y += core/engine/xtensa.o
+ nouveau-y += core/engine/dmaobj/base.o
+ nouveau-y += core/engine/dmaobj/nv04.o
+ nouveau-y += core/engine/dmaobj/nv50.o
+diff --git a/drivers/gpu/drm/nouveau/core/engine/xtensa.c b/drivers/gpu/drm/nouveau/core/engine/xtensa.c
+new file mode 100644
+index 000000000000..0639bc59d0a5
+--- /dev/null
++++ b/drivers/gpu/drm/nouveau/core/engine/xtensa.c
+@@ -0,0 +1,170 @@
++/*
++ * Copyright 2013 Ilia Mirkin
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ */
++
++#include 
++
++u32
++_nouveau_xtensa_rd32(struct nouveau_object *object, u64 addr)
++{
++	struct nouveau_xtensa *xtensa = (void *)object;
++	return nv_rd32(xtensa, xtensa->addr + addr);
++}
++
++void
++_nouveau_xtensa_wr32(struct nouveau_object *object, u64 addr, u32 data)
++{
++	struct nouveau_xtensa *xtensa = (void *)object;
++	nv_wr32(xtensa, xtensa->addr + addr, data);
++}
++
++int
++_nouveau_xtensa_engctx_ctor(struct nouveau_object *parent,
++			    struct nouveau_object *engine,
++			    struct nouveau_oclass *oclass, void *data, u32 size,
++			    struct nouveau_object **pobject)
++{
++	struct nouveau_engctx *engctx;
++	int ret;
++
++	ret = nouveau_engctx_create(parent, engine, oclass, NULL,
++				    0x10000, 0x1000,
++				    NVOBJ_FLAG_ZERO_ALLOC, &engctx);
++	*pobject = nv_object(engctx);
++	return ret;
++}
++
++void
++_nouveau_xtensa_intr(struct nouveau_subdev *subdev)
++{
++	struct nouveau_xtensa *xtensa = (void *)subdev;
++	u32 unk104 = nv_ro32(xtensa, 0xd04);
++	u32 intr = nv_ro32(xtensa, 0xc20);
++	u32 chan = nv_ro32(xtensa, 0xc28);
++	u32 unk10c = nv_ro32(xtensa, 0xd0c);
++
++	if (intr & 0x10)
++		nv_warn(xtensa, "Watchdog interrupt, engine hung.\n");
++	nv_wo32(xtensa, 0xc20, intr);
++	intr = nv_ro32(xtensa, 0xc20);
++	if (unk104 == 0x10001 && unk10c == 0x200 && chan && !intr) {
++		nv_debug(xtensa, "Enabling FIFO_CTRL\n");
++		nv_mask(xtensa, xtensa->addr + 0xd94, 0, xtensa->fifo_val);
++	}
++}
++
++int
++nouveau_xtensa_create_(struct nouveau_object *parent,
++		       struct nouveau_object *engine,
++		       struct nouveau_oclass *oclass, u32 addr, bool enable,
++		       const char *iname, const char *fname,
++		       int length, void **pobject)
++{
++	struct nouveau_xtensa *xtensa;
++	int ret;
++
++	ret = nouveau_engine_create_(parent, engine, oclass, enable, iname,
++				     fname, length, pobject);
++	xtensa = *pobject;
++	if (ret)
++		return ret;
++
++	nv_subdev(xtensa)->intr = _nouveau_xtensa_intr;
++
++	xtensa->addr = addr;
++
++	return 0;
++}
++
++int
++_nouveau_xtensa_init(struct nouveau_object *object)
++{
++	struct nouveau_device *device = nv_device(object);
++	struct nouveau_xtensa *xtensa = (void *)object;
++	const struct firmware *fw;
++	char name[32];
++	int i, ret;
++	u32 tmp;
++
++	ret = nouveau_engine_init(&xtensa->base);
++	if (ret)
++		return ret;
++
++	if (!xtensa->gpu_fw) {
++		snprintf(name, sizeof(name), "nouveau/nv84_xuc%03x",
++			 xtensa->addr >> 12);
++
++		ret = request_firmware(&fw, name, &device->pdev->dev);
++		if (ret) {
++			nv_warn(xtensa, "unable to load firmware %s\n", name);
++			return ret;
++		}
++
++		ret = nouveau_gpuobj_new(object, NULL, fw->size, 0x1000, 0,
++					 &xtensa->gpu_fw);
++		if (ret) {
++			release_firmware(fw);
++			return ret;
++		}
++
++		nv_debug(xtensa, "Loading firmware to address: 0x%llx\n",
++			 xtensa->gpu_fw->addr);
++
++		for (i = 0; i < fw->size / 4; i++)
++			nv_wo32(xtensa->gpu_fw, i * 4, *((u32 *)fw->data + i));
++		release_firmware(fw);
++	}
++
++	nv_wo32(xtensa, 0xd10, 0x1fffffff); /* ?? */
++	nv_wo32(xtensa, 0xd08, 0x0fffffff); /* ?? */
++
++	nv_wo32(xtensa, 0xd28, xtensa->unkd28); /* ?? */
++	nv_wo32(xtensa, 0xc20, 0x3f); /* INTR */
++	nv_wo32(xtensa, 0xd84, 0x3f); /* INTR_EN */
++
++	nv_wo32(xtensa, 0xcc0, xtensa->gpu_fw->addr >> 8); /* XT_REGION_BASE */
++	nv_wo32(xtensa, 0xcc4, 0x1c); /* XT_REGION_SETUP */
++	nv_wo32(xtensa, 0xcc8, xtensa->gpu_fw->size >> 8); /* XT_REGION_LIMIT */
++
++	tmp = nv_rd32(xtensa, 0x0);
++	nv_wo32(xtensa, 0xde0, tmp); /* SCRATCH_H2X */
++
++	nv_wo32(xtensa, 0xce8, 0xf); /* XT_REGION_SETUP */
++
++	nv_wo32(xtensa, 0xc20, 0x3f); /* INTR */
++	nv_wo32(xtensa, 0xd84, 0x3f); /* INTR_EN */
++
++	return 0;
++}
++
++int
++_nouveau_xtensa_fini(struct nouveau_object *object, bool suspend)
++{
++	struct nouveau_xtensa *xtensa = (void *)object;
++
++	nv_wo32(xtensa, 0xd84, 0); /* INTR_EN */
++	nv_wo32(xtensa, 0xd94, 0); /* FIFO_CTRL */
++
++	if (!suspend)
++		nouveau_gpuobj_ref(NULL, &xtensa->gpu_fw);
++
++	return nouveau_engine_fini(&xtensa->base, suspend);
++}
+diff --git a/drivers/gpu/drm/nouveau/core/include/engine/xtensa.h b/drivers/gpu/drm/nouveau/core/include/engine/xtensa.h
+new file mode 100644
+index 000000000000..306100f31f02
+--- /dev/null
++++ b/drivers/gpu/drm/nouveau/core/include/engine/xtensa.h
+@@ -0,0 +1,38 @@
++#ifndef __NOUVEAU_XTENSA_H__
++#define __NOUVEAU_XTENSA_H__
++
++#include 
++#include 
++#include 
++
++struct nouveau_xtensa {
++	struct nouveau_engine base;
++
++	u32 addr;
++	struct nouveau_gpuobj *gpu_fw;
++	u32 fifo_val;
++	u32 unkd28;
++};
++
++#define nouveau_xtensa_create(p,e,c,b,d,i,f,r)				\
++	nouveau_xtensa_create_((p), (e), (c), (b), (d), (i), (f),	\
++			       sizeof(**r),(void **)r)
++
++int _nouveau_xtensa_engctx_ctor(struct nouveau_object *,
++				struct nouveau_object *,
++				struct nouveau_oclass *, void *, u32,
++				struct nouveau_object **);
++
++void _nouveau_xtensa_intr(struct nouveau_subdev *);
++int nouveau_xtensa_create_(struct nouveau_object *,
++			   struct nouveau_object *,
++			   struct nouveau_oclass *, u32, bool,
++			   const char *, const char *,
++			   int, void **);
++#define _nouveau_xtensa_dtor _nouveau_engine_dtor
++int _nouveau_xtensa_init(struct nouveau_object *);
++int _nouveau_xtensa_fini(struct nouveau_object *, bool);
++u32  _nouveau_xtensa_rd32(struct nouveau_object *, u64);
++void _nouveau_xtensa_wr32(struct nouveau_object *, u64, u32);
++
++#endif

commit 0d4a1450c95801c21ba4db109303fbad62378b91
+Author: Ilia Mirkin 
+Date:   Thu Jun 27 14:04:20 2013 +1000
+
+    drm/nouveau/vdec: fork vp3 implementations from vp2
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile
+index 5a2695f2759a..78f9aa24f1fd 100644
+--- a/drivers/gpu/drm/nouveau/Makefile
++++ b/drivers/gpu/drm/nouveau/Makefile
+@@ -148,6 +148,7 @@ nouveau-y += core/engine/dmaobj/nv50.o
+ nouveau-y += core/engine/dmaobj/nvc0.o
+ nouveau-y += core/engine/dmaobj/nvd0.o
+ nouveau-y += core/engine/bsp/nv84.o
++nouveau-y += core/engine/bsp/nv98.o
+ nouveau-y += core/engine/bsp/nvc0.o
+ nouveau-y += core/engine/bsp/nve0.o
+ nouveau-y += core/engine/copy/nva3.o
+@@ -222,6 +223,7 @@ nouveau-y += core/engine/software/nv10.o
+ nouveau-y += core/engine/software/nv50.o
+ nouveau-y += core/engine/software/nvc0.o
+ nouveau-y += core/engine/vp/nv84.o
++nouveau-y += core/engine/vp/nv98.o
+ nouveau-y += core/engine/vp/nvc0.o
+ nouveau-y += core/engine/vp/nve0.o
+ 
+diff --git a/drivers/gpu/drm/nouveau/core/engine/bsp/nv98.c b/drivers/gpu/drm/nouveau/core/engine/bsp/nv98.c
+new file mode 100644
+index 000000000000..8bf92b0e6d82
+--- /dev/null
++++ b/drivers/gpu/drm/nouveau/core/engine/bsp/nv98.c
+@@ -0,0 +1,93 @@
++/*
++ * Copyright 2012 Red Hat Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * Authors: Ben Skeggs
++ */
++
++#include 
++#include 
++
++#include 
++
++struct nv98_bsp_priv {
++	struct nouveau_engine base;
++};
++
++/*******************************************************************************
++ * BSP object classes
++ ******************************************************************************/
++
++static struct nouveau_oclass
++nv98_bsp_sclass[] = {
++	{},
++};
++
++/*******************************************************************************
++ * BSP context
++ ******************************************************************************/
++
++static struct nouveau_oclass
++nv98_bsp_cclass = {
++	.handle = NV_ENGCTX(BSP, 0x98),
++	.ofuncs = &(struct nouveau_ofuncs) {
++		.ctor = _nouveau_engctx_ctor,
++		.dtor = _nouveau_engctx_dtor,
++		.init = _nouveau_engctx_init,
++		.fini = _nouveau_engctx_fini,
++		.rd32 = _nouveau_engctx_rd32,
++		.wr32 = _nouveau_engctx_wr32,
++	},
++};
++
++/*******************************************************************************
++ * BSP engine/subdev functions
++ ******************************************************************************/
++
++static int
++nv98_bsp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
++	      struct nouveau_oclass *oclass, void *data, u32 size,
++	      struct nouveau_object **pobject)
++{
++	struct nv98_bsp_priv *priv;
++	int ret;
++
++	ret = nouveau_engine_create(parent, engine, oclass, true,
++				    "PBSP", "bsp", &priv);
++	*pobject = nv_object(priv);
++	if (ret)
++		return ret;
++
++	nv_subdev(priv)->unit = 0x04008000;
++	nv_engine(priv)->cclass = &nv98_bsp_cclass;
++	nv_engine(priv)->sclass = nv98_bsp_sclass;
++	return 0;
++}
++
++struct nouveau_oclass
++nv98_bsp_oclass = {
++	.handle = NV_ENGINE(BSP, 0x98),
++	.ofuncs = &(struct nouveau_ofuncs) {
++		.ctor = nv98_bsp_ctor,
++		.dtor = _nouveau_engine_dtor,
++		.init = _nouveau_engine_init,
++		.fini = _nouveau_engine_fini,
++	},
++};
+diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv50.c b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c
+index 5c1db3e1f0f2..ffc18b80c5d9 100644
+--- a/drivers/gpu/drm/nouveau/core/engine/device/nv50.c
++++ b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c
+@@ -227,9 +227,9 @@ nv50_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv84_fifo_oclass;
+ 		device->oclass[NVDEV_ENGINE_SW     ] = &nv50_software_oclass;
+ 		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;
+-		device->oclass[NVDEV_ENGINE_VP     ] = &nv84_vp_oclass;
++		device->oclass[NVDEV_ENGINE_VP     ] = &nv98_vp_oclass;
+ 		device->oclass[NVDEV_ENGINE_CRYPT  ] = &nv98_crypt_oclass;
+-		device->oclass[NVDEV_ENGINE_BSP    ] = &nv84_bsp_oclass;
++		device->oclass[NVDEV_ENGINE_BSP    ] = &nv98_bsp_oclass;
+ 		device->oclass[NVDEV_ENGINE_PPP    ] = &nv98_ppp_oclass;
+ 		device->oclass[NVDEV_ENGINE_DISP   ] = &nv94_disp_oclass;
+ 		break;
+@@ -279,9 +279,9 @@ nv50_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv84_fifo_oclass;
+ 		device->oclass[NVDEV_ENGINE_SW     ] = &nv50_software_oclass;
+ 		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;
+-		device->oclass[NVDEV_ENGINE_VP     ] = &nv84_vp_oclass;
++		device->oclass[NVDEV_ENGINE_VP     ] = &nv98_vp_oclass;
+ 		device->oclass[NVDEV_ENGINE_CRYPT  ] = &nv98_crypt_oclass;
+-		device->oclass[NVDEV_ENGINE_BSP    ] = &nv84_bsp_oclass;
++		device->oclass[NVDEV_ENGINE_BSP    ] = &nv98_bsp_oclass;
+ 		device->oclass[NVDEV_ENGINE_PPP    ] = &nv98_ppp_oclass;
+ 		device->oclass[NVDEV_ENGINE_DISP   ] = &nv94_disp_oclass;
+ 		break;
+@@ -305,9 +305,9 @@ nv50_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv84_fifo_oclass;
+ 		device->oclass[NVDEV_ENGINE_SW     ] = &nv50_software_oclass;
+ 		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;
+-		device->oclass[NVDEV_ENGINE_VP     ] = &nv84_vp_oclass;
++		device->oclass[NVDEV_ENGINE_VP     ] = &nv98_vp_oclass;
+ 		device->oclass[NVDEV_ENGINE_CRYPT  ] = &nv98_crypt_oclass;
+-		device->oclass[NVDEV_ENGINE_BSP    ] = &nv84_bsp_oclass;
++		device->oclass[NVDEV_ENGINE_BSP    ] = &nv98_bsp_oclass;
+ 		device->oclass[NVDEV_ENGINE_PPP    ] = &nv98_ppp_oclass;
+ 		device->oclass[NVDEV_ENGINE_DISP   ] = &nv94_disp_oclass;
+ 		break;
+@@ -332,8 +332,8 @@ nv50_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_ENGINE_SW     ] = &nv50_software_oclass;
+ 		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;
+ 		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv84_mpeg_oclass;
+-		device->oclass[NVDEV_ENGINE_VP     ] = &nv84_vp_oclass;
+-		device->oclass[NVDEV_ENGINE_BSP    ] = &nv84_bsp_oclass;
++		device->oclass[NVDEV_ENGINE_VP     ] = &nv98_vp_oclass;
++		device->oclass[NVDEV_ENGINE_BSP    ] = &nv98_bsp_oclass;
+ 		device->oclass[NVDEV_ENGINE_PPP    ] = &nv98_ppp_oclass;
+ 		device->oclass[NVDEV_ENGINE_COPY0  ] = &nva3_copy_oclass;
+ 		device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass;
+@@ -358,8 +358,8 @@ nv50_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv84_fifo_oclass;
+ 		device->oclass[NVDEV_ENGINE_SW     ] = &nv50_software_oclass;
+ 		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;
+-		device->oclass[NVDEV_ENGINE_VP     ] = &nv84_vp_oclass;
+-		device->oclass[NVDEV_ENGINE_BSP    ] = &nv84_bsp_oclass;
++		device->oclass[NVDEV_ENGINE_VP     ] = &nv98_vp_oclass;
++		device->oclass[NVDEV_ENGINE_BSP    ] = &nv98_bsp_oclass;
+ 		device->oclass[NVDEV_ENGINE_PPP    ] = &nv98_ppp_oclass;
+ 		device->oclass[NVDEV_ENGINE_COPY0  ] = &nva3_copy_oclass;
+ 		device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass;
+@@ -384,8 +384,8 @@ nv50_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv84_fifo_oclass;
+ 		device->oclass[NVDEV_ENGINE_SW     ] = &nv50_software_oclass;
+ 		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;
+-		device->oclass[NVDEV_ENGINE_VP     ] = &nv84_vp_oclass;
+-		device->oclass[NVDEV_ENGINE_BSP    ] = &nv84_bsp_oclass;
++		device->oclass[NVDEV_ENGINE_VP     ] = &nv98_vp_oclass;
++		device->oclass[NVDEV_ENGINE_BSP    ] = &nv98_bsp_oclass;
+ 		device->oclass[NVDEV_ENGINE_PPP    ] = &nv98_ppp_oclass;
+ 		device->oclass[NVDEV_ENGINE_COPY0  ] = &nva3_copy_oclass;
+ 		device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass;
+@@ -410,8 +410,8 @@ nv50_identify(struct nouveau_device *device)
+ 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv84_fifo_oclass;
+ 		device->oclass[NVDEV_ENGINE_SW     ] = &nv50_software_oclass;
+ 		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;
+-		device->oclass[NVDEV_ENGINE_VP     ] = &nv84_vp_oclass;
+-		device->oclass[NVDEV_ENGINE_BSP    ] = &nv84_bsp_oclass;
++		device->oclass[NVDEV_ENGINE_VP     ] = &nv98_vp_oclass;
++		device->oclass[NVDEV_ENGINE_BSP    ] = &nv98_bsp_oclass;
+ 		device->oclass[NVDEV_ENGINE_PPP    ] = &nv98_ppp_oclass;
+ 		device->oclass[NVDEV_ENGINE_COPY0  ] = &nva3_copy_oclass;
+ 		device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass;
+diff --git a/drivers/gpu/drm/nouveau/core/engine/vp/nv98.c b/drivers/gpu/drm/nouveau/core/engine/vp/nv98.c
+new file mode 100644
+index 000000000000..8a8236bc84de
+--- /dev/null
++++ b/drivers/gpu/drm/nouveau/core/engine/vp/nv98.c
+@@ -0,0 +1,93 @@
++/*
++ * Copyright 2012 Red Hat Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * Authors: Ben Skeggs
++ */
++
++#include 
++#include 
++
++#include 
++
++struct nv98_vp_priv {
++	struct nouveau_engine base;
++};
++
++/*******************************************************************************
++ * VP object classes
++ ******************************************************************************/
++
++static struct nouveau_oclass
++nv98_vp_sclass[] = {
++	{},
++};
++
++/*******************************************************************************
++ * PVP context
++ ******************************************************************************/
++
++static struct nouveau_oclass
++nv98_vp_cclass = {
++	.handle = NV_ENGCTX(VP, 0x98),
++	.ofuncs = &(struct nouveau_ofuncs) {
++		.ctor = _nouveau_engctx_ctor,
++		.dtor = _nouveau_engctx_dtor,
++		.init = _nouveau_engctx_init,
++		.fini = _nouveau_engctx_fini,
++		.rd32 = _nouveau_engctx_rd32,
++		.wr32 = _nouveau_engctx_wr32,
++	},
++};
++
++/*******************************************************************************
++ * PVP engine/subdev functions
++ ******************************************************************************/
++
++static int
++nv98_vp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
++	     struct nouveau_oclass *oclass, void *data, u32 size,
++	     struct nouveau_object **pobject)
++{
++	struct nv98_vp_priv *priv;
++	int ret;
++
++	ret = nouveau_engine_create(parent, engine, oclass, true,
++				    "PVP", "vp", &priv);
++	*pobject = nv_object(priv);
++	if (ret)
++		return ret;
++
++	nv_subdev(priv)->unit = 0x01020000;
++	nv_engine(priv)->cclass = &nv98_vp_cclass;
++	nv_engine(priv)->sclass = nv98_vp_sclass;
++	return 0;
++}
++
++struct nouveau_oclass
++nv98_vp_oclass = {
++	.handle = NV_ENGINE(VP, 0x98),
++	.ofuncs = &(struct nouveau_ofuncs) {
++		.ctor = nv98_vp_ctor,
++		.dtor = _nouveau_engine_dtor,
++		.init = _nouveau_engine_init,
++		.fini = _nouveau_engine_fini,
++	},
++};
+diff --git a/drivers/gpu/drm/nouveau/core/include/engine/bsp.h b/drivers/gpu/drm/nouveau/core/include/engine/bsp.h
+index 13ccdf54dfad..67662e2c4547 100644
+--- a/drivers/gpu/drm/nouveau/core/include/engine/bsp.h
++++ b/drivers/gpu/drm/nouveau/core/include/engine/bsp.h
+@@ -2,6 +2,7 @@
+ #define __NOUVEAU_BSP_H__
+ 
+ extern struct nouveau_oclass nv84_bsp_oclass;
++extern struct nouveau_oclass nv98_bsp_oclass;
+ extern struct nouveau_oclass nvc0_bsp_oclass;
+ extern struct nouveau_oclass nve0_bsp_oclass;
+ 
+diff --git a/drivers/gpu/drm/nouveau/core/include/engine/vp.h b/drivers/gpu/drm/nouveau/core/include/engine/vp.h
+index d7b287b115bf..39baebec7fbb 100644
+--- a/drivers/gpu/drm/nouveau/core/include/engine/vp.h
++++ b/drivers/gpu/drm/nouveau/core/include/engine/vp.h
+@@ -2,6 +2,7 @@
+ #define __NOUVEAU_VP_H__
+ 
+ extern struct nouveau_oclass nv84_vp_oclass;
++extern struct nouveau_oclass nv98_vp_oclass;
+ extern struct nouveau_oclass nvc0_vp_oclass;
+ extern struct nouveau_oclass nve0_vp_oclass;
+ 

commit a08aa355af18c53f17f499c1cc6e2af66a77ba9b
+Author: Ilia Mirkin 
+Date:   Tue May 24 17:13:30 2011 -0700
+
+    lru_cache: use correct type in sizeof for allocation
+    
+    This has no actual effect, since sizeof(struct hlist_head) ==
+    sizeof(struct hlist_head *), but it's still the wrong type to use.
+    
+    The semantic match that finds this problem:
+    // 
+    @@
+    type T;
+    identifier x;
+    @@
+    T *x;
+    ...
+    * x = kzalloc(... * sizeof(T*) * ..., ...);
+    // 
+    
+    [akpm@linux-foundation.org: use kcalloc()]
+    Signed-off-by: Ilia Mirkin 
+    Acked-by: Lars Ellenberg 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/lib/lru_cache.c b/lib/lru_cache.c
+index 270de9d31b8c..a07e7268d7ed 100644
+--- a/lib/lru_cache.c
++++ b/lib/lru_cache.c
+@@ -84,7 +84,7 @@ struct lru_cache *lc_create(const char *name, struct kmem_cache *cache,
+ 	if (e_count > LC_MAX_ACTIVE)
+ 		return NULL;
+ 
+-	slot = kzalloc(e_count * sizeof(struct hlist_head*), GFP_KERNEL);
++	slot = kcalloc(e_count, sizeof(struct hlist_head), GFP_KERNEL);
+ 	if (!slot)
+ 		goto out_fail;
+ 	element = kzalloc(e_count * sizeof(struct lc_element *), GFP_KERNEL);

commit 6e9d592f02f657361168c94e22d9602cad71a09c
+Author: Ilia Mirkin 
+Date:   Thu Mar 17 14:08:57 2011 -0400
+
+    rtlwifi: Fix memset argument order
+    
+    These were found using the following semantic match:
+    // 
+    @@expression E1; type T;@@
+    * memset(E1, ... * sizeof(T) * ..., ...);
+    // 
+    
+    Also take this opportunity to remove the unnecessary void* casts.
+    
+    Signed-off-by: Ilia Mirkin 
+    Tested-by: Larry Finger 
+    Acked-by: Larry Finger 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/rtlwifi/efuse.c
+index 4f92cba6810a..f74a8701c67d 100644
+--- a/drivers/net/wireless/rtlwifi/efuse.c
++++ b/drivers/net/wireless/rtlwifi/efuse.c
+@@ -410,8 +410,8 @@ bool efuse_shadow_update(struct ieee80211_hw *hw)
+ 
+ 	if (!efuse_shadow_update_chk(hw)) {
+ 		efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]);
+-		memcpy((void *)&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0],
+-		       (void *)&rtlefuse->efuse_map[EFUSE_INIT_MAP][0],
++		memcpy(&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0],
++		       &rtlefuse->efuse_map[EFUSE_INIT_MAP][0],
+ 		       rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]);
+ 
+ 		RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD,
+@@ -446,9 +446,9 @@ bool efuse_shadow_update(struct ieee80211_hw *hw)
+ 
+ 		if (word_en != 0x0F) {
+ 			u8 tmpdata[8];
+-			memcpy((void *)tmpdata,
+-			       (void *)(&rtlefuse->
+-					efuse_map[EFUSE_MODIFY_MAP][base]), 8);
++			memcpy(tmpdata,
++			       &rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base],
++			       8);
+ 			RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_LOUD,
+ 				      ("U-efuse\n"), tmpdata, 8);
+ 
+@@ -465,8 +465,8 @@ bool efuse_shadow_update(struct ieee80211_hw *hw)
+ 	efuse_power_switch(hw, true, false);
+ 	efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]);
+ 
+-	memcpy((void *)&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0],
+-	       (void *)&rtlefuse->efuse_map[EFUSE_INIT_MAP][0],
++	memcpy(&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0],
++	       &rtlefuse->efuse_map[EFUSE_INIT_MAP][0],
+ 	       rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]);
+ 
+ 	RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, ("<---\n"));
+@@ -479,13 +479,12 @@ void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw)
+ 	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ 
+ 	if (rtlefuse->autoload_failflag == true) {
+-		memset((void *)(&rtlefuse->efuse_map[EFUSE_INIT_MAP][0]), 128,
+-		       0xFF);
++		memset(&rtlefuse->efuse_map[EFUSE_INIT_MAP][0], 0xFF, 128);
+ 	} else
+ 		efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]);
+ 
+-	memcpy((void *)&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0],
+-	       (void *)&rtlefuse->efuse_map[EFUSE_INIT_MAP][0],
++	memcpy(&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0],
++	       &rtlefuse->efuse_map[EFUSE_INIT_MAP][0],
+ 	       rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]);
+ 
+ }
+@@ -694,8 +693,8 @@ static int efuse_pg_packet_read(struct ieee80211_hw *hw, u8 offset, u8 *data)
+ 	if (offset > 15)
+ 		return false;
+ 
+-	memset((void *)data, PGPKT_DATA_SIZE * sizeof(u8), 0xff);
+-	memset((void *)tmpdata, PGPKT_DATA_SIZE * sizeof(u8), 0xff);
++	memset(data, 0xff, PGPKT_DATA_SIZE * sizeof(u8));
++	memset(tmpdata, 0xff, PGPKT_DATA_SIZE * sizeof(u8));
+ 
+ 	while (bcontinual && (efuse_addr < EFUSE_MAX_SIZE)) {
+ 		if (readstate & PG_STATE_HEADER) {
+@@ -862,7 +861,7 @@ static void efuse_write_data_case2(struct ieee80211_hw *hw, u16 *efuse_addr,
+ 
+ 		tmp_word_cnts = efuse_calculate_word_cnts(tmp_pkt.word_en);
+ 
+-		memset((void *)originaldata, 8 * sizeof(u8), 0xff);
++		memset(originaldata, 0xff, 8 * sizeof(u8));
+ 
+ 		if (efuse_pg_packet_read(hw, tmp_pkt.offset, originaldata)) {
+ 			badworden = efuse_word_enable_data_write(hw,
+@@ -917,7 +916,7 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw,
+ 	target_pkt.offset = offset;
+ 	target_pkt.word_en = word_en;
+ 
+-	memset((void *)target_pkt.data, 8 * sizeof(u8), 0xFF);
++	memset(target_pkt.data, 0xFF, 8 * sizeof(u8));
+ 
+ 	efuse_word_enable_data_read(word_en, data, target_pkt.data);
+ 	target_word_cnts = efuse_calculate_word_cnts(target_pkt.word_en);
+@@ -1022,7 +1021,7 @@ static u8 efuse_word_enable_data_write(struct ieee80211_hw *hw,
+ 	u8 badworden = 0x0F;
+ 	u8 tmpdata[8];
+ 
+-	memset((void *)tmpdata, PGPKT_DATA_SIZE, 0xff);
++	memset(tmpdata, 0xff, PGPKT_DATA_SIZE);
+ 	RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD,
+ 		 ("word_en = %x efuse_addr=%x\n", word_en, efuse_addr));
+ 

commit dd9b15dc03075993f63a8a69667a3a8989aedfa1
+Author: Ilia Mirkin 
+Date:   Sun Mar 13 00:29:00 2011 -0500
+
+    staging: hv: Remove NULL check before kfree
+    
+    This patch was generated by the following semantic patch:
+    // 
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); }
+    + kfree(E);
+    
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); E = NULL; }
+    + kfree(E);
+    + E = NULL;
+    // 
+    
+    Signed-off-by: Ilia Mirkin 
+    Cc: K. Y. Srinivasan 
+    Cc: Haiyang Zhang 
+    Cc: Mike Sterling 
+    Cc: Abhishek Kane 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/channel_mgmt.c b/drivers/staging/hv/channel_mgmt.c
+index 33688094e1fd..bc0393a41d29 100644
+--- a/drivers/staging/hv/channel_mgmt.c
++++ b/drivers/staging/hv/channel_mgmt.c
+@@ -829,8 +829,7 @@ int vmbus_request_offers(void)
+ 
+ 
+ cleanup:
+-	if (msginfo)
+-		kfree(msginfo);
++	kfree(msginfo);
+ 
+ 	return ret;
+ }
+diff --git a/drivers/staging/hv/connection.c b/drivers/staging/hv/connection.c
+index fd589e381e31..44b203b95a22 100644
+--- a/drivers/staging/hv/connection.c
++++ b/drivers/staging/hv/connection.c
+@@ -186,9 +186,7 @@ int vmbus_connect(void)
+ 		vmbus_connection.monitor_pages = NULL;
+ 	}
+ 
+-	if (msginfo) {
+-		kfree(msginfo);
+-	}
++	kfree(msginfo);
+ 
+ 	return ret;
+ }
+diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c
+index 8f94f433961f..6fa462109ce9 100644
+--- a/drivers/staging/hv/hv_mouse.c
++++ b/drivers/staging/hv/hv_mouse.c
+@@ -402,15 +402,11 @@ static void MousevscOnReceiveDeviceInfo(struct mousevsc_dev *InputDevice, struct
+ 	return;
+ 
+ Cleanup:
+-	if (InputDevice->HidDesc) {
+-		kfree(InputDevice->HidDesc);
+-		InputDevice->HidDesc = NULL;
+-	}
++	kfree(InputDevice->HidDesc);
++	InputDevice->HidDesc = NULL;
+ 
+-	if (InputDevice->ReportDesc) {
+-		kfree(InputDevice->ReportDesc);
+-		InputDevice->ReportDesc = NULL;
+-	}
++	kfree(InputDevice->ReportDesc);
++	InputDevice->ReportDesc = NULL;
+ 
+ 	InputDevice->DeviceInfoStatus = -1;
+ 	InputDevice->device_wait_condition = 1;

commit a6f9c48fdd566e09d437e104c5b5963133db1be4
+Author: Ilia Mirkin 
+Date:   Sun Mar 13 00:29:17 2011 -0500
+
+    staging: wlan-ng: Remove NULL check before kfree
+    
+    This patch was generated by the following semantic patch:
+    // 
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); }
+    + kfree(E);
+    
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); E = NULL; }
+    + kfree(E);
+    + E = NULL;
+    // 
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c
+index a6efc033fe10..7843dfdaa3cf 100644
+--- a/drivers/staging/wlan-ng/hfa384x_usb.c
++++ b/drivers/staging/wlan-ng/hfa384x_usb.c
+@@ -612,10 +612,8 @@ void hfa384x_destroy(hfa384x_t *hw)
+ 		hfa384x_drvr_stop(hw);
+ 	hw->state = HFA384x_STATE_PREINIT;
+ 
+-	if (hw->scanresults) {
+-		kfree(hw->scanresults);
+-		hw->scanresults = NULL;
+-	}
++	kfree(hw->scanresults);
++	hw->scanresults = NULL;
+ 
+ 	/* Now to clean out the auth queue */
+ 	while ((skb = skb_dequeue(&hw->authq)))
+diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c
+index fd5ddb29436c..729d03d28d75 100644
+--- a/drivers/staging/wlan-ng/prism2fw.c
++++ b/drivers/staging/wlan-ng/prism2fw.c
+@@ -443,8 +443,7 @@ void free_chunks(struct imgchunk *fchunk, unsigned int *nfchunks)
+ {
+ 	int i;
+ 	for (i = 0; i < *nfchunks; i++) {
+-		if (fchunk[i].data != NULL)
+-			kfree(fchunk[i].data);
++		kfree(fchunk[i].data);
+ 	}
+ 	*nfchunks = 0;
+ 	memset(fchunk, 0, sizeof(*fchunk));

commit 4d527a7adbc47bdc357ddab513861e6a7636755e
+Author: Ilia Mirkin 
+Date:   Sun Mar 13 00:29:16 2011 -0500
+
+    staging: winbond: Remove NULL check before kfree
+    
+    This patch was generated by the following semantic patch:
+    // 
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); }
+    + kfree(E);
+    
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); E = NULL; }
+    + kfree(E);
+    + E = NULL;
+    // 
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/winbond/wb35reg.c b/drivers/staging/winbond/wb35reg.c
+index 42ae61014522..da595f16f634 100644
+--- a/drivers/staging/winbond/wb35reg.c
++++ b/drivers/staging/winbond/wb35reg.c
+@@ -66,8 +66,7 @@ unsigned char Wb35Reg_BurstWrite(struct hw_data *pHwData, u16 RegisterNo, u32 *p
+ 	} else {
+ 		if (urb)
+ 			usb_free_urb(urb);
+-		if (reg_queue)
+-			kfree(reg_queue);
++		kfree(reg_queue);
+ 		return false;
+ 	}
+    return false;

commit 1d5c536efeb9c109e330209867ae1242d42cdb7b
+Author: Ilia Mirkin 
+Date:   Sun Mar 13 00:29:15 2011 -0500
+
+    staging: vt6656: Remove NULL check before kfree
+    
+    This patch was generated by the following semantic patch:
+    // 
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); }
+    + kfree(E);
+    
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); E = NULL; }
+    + kfree(E);
+    + E = NULL;
+    // 
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/vt6656/firmware.c b/drivers/staging/vt6656/firmware.c
+index 162541255a02..8c8126a3540b 100644
+--- a/drivers/staging/vt6656/firmware.c
++++ b/drivers/staging/vt6656/firmware.c
+@@ -109,8 +109,7 @@ FIRMWAREbDownload(
+ 	result = TRUE;
+ 
+ out:
+-	if (pBuffer)
+-		kfree(pBuffer);
++	kfree(pBuffer);
+ 
+ 	spin_lock_irq(&pDevice->lock);
+ 	return result;
+diff --git a/drivers/staging/vt6656/hostap.c b/drivers/staging/vt6656/hostap.c
+index f70e922a615b..51b5adf36577 100644
+--- a/drivers/staging/vt6656/hostap.c
++++ b/drivers/staging/vt6656/hostap.c
+@@ -858,8 +858,7 @@ int vt6656_hostap_ioctl(PSDevice pDevice, struct iw_point *p)
+ 	}
+ 
+  out:
+-	if (param != NULL)
+-		kfree(param);
++	kfree(param);
+ 
+ 	return ret;
+ }
+diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c
+index 37d639602c8b..af14ab01ed7b 100644
+--- a/drivers/staging/vt6656/main_usb.c
++++ b/drivers/staging/vt6656/main_usb.c
+@@ -837,8 +837,7 @@ static void device_free_tx_bufs(PSDevice pDevice)
+             usb_kill_urb(pTxContext->pUrb);
+             usb_free_urb(pTxContext->pUrb);
+         }
+-        if (pTxContext)
+-            kfree(pTxContext);
++        kfree(pTxContext);
+     }
+     return;
+ }
+@@ -861,8 +860,7 @@ static void device_free_rx_bufs(PSDevice pDevice)
+         if (pRCB->skb)
+             dev_kfree_skb(pRCB->skb);
+     }
+-    if (pDevice->pRCBMem)
+-        kfree(pDevice->pRCBMem);
++    kfree(pDevice->pRCBMem);
+ 
+     return;
+ }
+@@ -878,8 +876,7 @@ static void usb_device_reset(PSDevice pDevice)
+ 
+ static void device_free_int_bufs(PSDevice pDevice)
+ {
+-    if (pDevice->intBuf.pDataBuf != NULL)
+-        kfree(pDevice->intBuf.pDataBuf);
++    kfree(pDevice->intBuf.pDataBuf);
+     return;
+ }
+ 
+@@ -1480,8 +1477,7 @@ static unsigned char *Config_FileOperation(PSDevice pDevice)
+   */
+ 
+ if(result!=0) {
+-    if(buffer)
+-  	 kfree(buffer);
++    kfree(buffer);
+     buffer=NULL;
+ }
+   return buffer;
+diff --git a/drivers/staging/vt6656/wpactl.c b/drivers/staging/vt6656/wpactl.c
+index 7fd300f2e7c3..8752736181bb 100644
+--- a/drivers/staging/vt6656/wpactl.c
++++ b/drivers/staging/vt6656/wpactl.c
+@@ -999,8 +999,7 @@ int wpa_ioctl(PSDevice pDevice, struct iw_point *p)
+ 	}
+ 
+ out:
+-	if (param != NULL)
+-		kfree(param);
++	kfree(param);
+ 
+ 	return ret;
+ }

commit 6403bb7dc1f6d77a93850935d9277a0d74783cf0
+Author: Ilia Mirkin 
+Date:   Sun Mar 13 00:29:14 2011 -0500
+
+    staging: vt6655: Remove NULL check before kfree
+    
+    This patch was generated by the following semantic patch:
+    // 
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); }
+    + kfree(E);
+    
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); E = NULL; }
+    + kfree(E);
+    + E = NULL;
+    // 
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c
+index 638e3916774d..efaf19bc07b7 100644
+--- a/drivers/staging/vt6655/device_main.c
++++ b/drivers/staging/vt6655/device_main.c
+@@ -3064,8 +3064,7 @@ else {
+ }
+ 
+ error1:
+-  if(buffer)
+-  	 kfree(buffer);
++  kfree(buffer);
+ 
+   if(filp_close(filp,NULL))
+        printk("Config_FileOperation:close file fail\n");
+diff --git a/drivers/staging/vt6655/hostap.c b/drivers/staging/vt6655/hostap.c
+index 5b83f942cdab..773502702203 100644
+--- a/drivers/staging/vt6655/hostap.c
++++ b/drivers/staging/vt6655/hostap.c
+@@ -860,8 +860,7 @@ int vt6655_hostap_ioctl(PSDevice pDevice, struct iw_point *p)
+ 	}
+ 
+  out:
+-	if (param != NULL)
+-		kfree(param);
++	kfree(param);
+ 
+ 	return ret;
+ }
+diff --git a/drivers/staging/vt6655/wpactl.c b/drivers/staging/vt6655/wpactl.c
+index 4bdb8362de82..fbae16de27a7 100644
+--- a/drivers/staging/vt6655/wpactl.c
++++ b/drivers/staging/vt6655/wpactl.c
+@@ -987,8 +987,7 @@ int wpa_ioctl(PSDevice pDevice, struct iw_point *p)
+ 	}
+ 
+ out:
+-	if (param != NULL)
+-		kfree(param);
++	kfree(param);
+ 
+ 	return ret;
+ }

commit 794a8946ba2339af09dd1f39c8462c3611bebf77
+Author: Ilia Mirkin 
+Date:   Sun Mar 13 00:29:13 2011 -0500
+
+    staging: vme: Remove NULL check before kfree
+    
+    This patch was generated by the following semantic patch:
+    // 
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); }
+    + kfree(E);
+    
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); E = NULL; }
+    + kfree(E);
+    + E = NULL;
+    // 
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.c b/drivers/staging/vme/bridges/vme_ca91cx42.c
+index 5d734d9ed27d..d4a48c4e59c2 100644
+--- a/drivers/staging/vme/bridges/vme_ca91cx42.c
++++ b/drivers/staging/vme/bridges/vme_ca91cx42.c
+@@ -516,8 +516,7 @@ static int ca91cx42_alloc_resource(struct vme_master_resource *image,
+ 	if (existing_size != 0) {
+ 		iounmap(image->kern_base);
+ 		image->kern_base = NULL;
+-		if (image->bus_resource.name != NULL)
+-			kfree(image->bus_resource.name);
++		kfree(image->bus_resource.name);
+ 		release_resource(&image->bus_resource);
+ 		memset(&image->bus_resource, 0, sizeof(struct resource));
+ 	}
+diff --git a/drivers/staging/vme/bridges/vme_tsi148.c b/drivers/staging/vme/bridges/vme_tsi148.c
+index 2df19eacbca5..b00a53e793e7 100644
+--- a/drivers/staging/vme/bridges/vme_tsi148.c
++++ b/drivers/staging/vme/bridges/vme_tsi148.c
+@@ -821,8 +821,7 @@ static int tsi148_alloc_resource(struct vme_master_resource *image,
+ 	if (existing_size != 0) {
+ 		iounmap(image->kern_base);
+ 		image->kern_base = NULL;
+-		if (image->bus_resource.name != NULL)
+-			kfree(image->bus_resource.name);
++		kfree(image->bus_resource.name);
+ 		release_resource(&image->bus_resource);
+ 		memset(&image->bus_resource, 0, sizeof(struct resource));
+ 	}

commit 06dde506203147e8d245a505d491c40254561f17
+Author: Ilia Mirkin 
+Date:   Sun Mar 13 00:29:12 2011 -0500
+
+    staging: usbip: Remove NULL check before kfree
+    
+    This patch was generated by the following semantic patch:
+    // 
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); }
+    + kfree(E);
+    
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); E = NULL; }
+    + kfree(E);
+    + E = NULL;
+    // 
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/usbip/stub_main.c b/drivers/staging/usbip/stub_main.c
+index f3a40968aae2..076a7e531098 100644
+--- a/drivers/staging/usbip/stub_main.c
++++ b/drivers/staging/usbip/stub_main.c
+@@ -264,11 +264,9 @@ void stub_device_cleanup_urbs(struct stub_device *sdev)
+ 
+ 		kmem_cache_free(stub_priv_cache, priv);
+ 
+-		if (urb->transfer_buffer != NULL)
+-			kfree(urb->transfer_buffer);
++		kfree(urb->transfer_buffer);
+ 
+-		if (urb->setup_packet != NULL)
+-			kfree(urb->setup_packet);
++		kfree(urb->setup_packet);
+ 
+ 		usb_free_urb(urb);
+ 	}

commit 9f7ff701ad7b7bdcab949aa0527fe7efb3882afa
+Author: Ilia Mirkin 
+Date:   Sun Mar 13 00:29:11 2011 -0500
+
+    staging: tidspbridge: Remove NULL check before kfree
+    
+    This patch was generated by the following semantic patch:
+    // 
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); }
+    + kfree(E);
+    
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); E = NULL; }
+    + kfree(E);
+    + E = NULL;
+    // 
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/tidspbridge/core/chnl_sm.c b/drivers/staging/tidspbridge/core/chnl_sm.c
+index 3c05d7cb9c94..8381130e1460 100644
+--- a/drivers/staging/tidspbridge/core/chnl_sm.c
++++ b/drivers/staging/tidspbridge/core/chnl_sm.c
+@@ -828,8 +828,7 @@ int bridge_chnl_open(struct chnl_object **chnl,
+ 	free_chirp_list(&pchnl->io_requests);
+ 	free_chirp_list(&pchnl->free_packets_list);
+ 
+-	if (sync_event)
+-		kfree(sync_event);
++	kfree(sync_event);
+ 
+ 	if (pchnl->ntfy_obj) {
+ 		ntfy_delete(pchnl->ntfy_obj);
+diff --git a/drivers/staging/tidspbridge/pmgr/dbll.c b/drivers/staging/tidspbridge/pmgr/dbll.c
+index 2e20f78e2c31..31da62b14bc9 100644
+--- a/drivers/staging/tidspbridge/pmgr/dbll.c
++++ b/drivers/staging/tidspbridge/pmgr/dbll.c
+@@ -272,8 +272,7 @@ void dbll_delete(struct dbll_tar_obj *target)
+ 	DBC_REQUIRE(refs > 0);
+ 	DBC_REQUIRE(zl_target);
+ 
+-	if (zl_target != NULL)
+-		kfree(zl_target);
++	kfree(zl_target);
+ 
+ }
+ 

commit 39dd3e5d7b09b5a5010ed1aef512f2d58b65cb99
+Author: Ilia Mirkin 
+Date:   Sun Mar 13 00:29:10 2011 -0500
+
+    staging: speakup: Remove NULL check before kfree
+    
+    This patch was generated by the following semantic patch:
+    // 
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); }
+    + kfree(E);
+    
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); E = NULL; }
+    + kfree(E);
+    + E = NULL;
+    // 
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c
+index cd981a13c12d..42fcf7e9cb64 100644
+--- a/drivers/staging/speakup/main.c
++++ b/drivers/staging/speakup/main.c
+@@ -1305,10 +1305,8 @@ void speakup_deallocate(struct vc_data *vc)
+ 	int vc_num;
+ 
+ 	vc_num = vc->vc_num;
+-	if (speakup_console[vc_num] != NULL) {
+-		kfree(speakup_console[vc_num]);
+-		speakup_console[vc_num] = NULL;
+-	}
++	kfree(speakup_console[vc_num]);
++	speakup_console[vc_num] = NULL;
+ }
+ 
+ static u_char is_cursor;

commit ef055f10000c5013d269cac9fc92c200bf314e40
+Author: Ilia Mirkin 
+Date:   Sun Mar 13 00:29:09 2011 -0500
+
+    staging: serqt_usb2: Remove NULL check before kfree
+    
+    This patch was generated by the following semantic patch:
+    // 
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); }
+    + kfree(E);
+    
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); E = NULL; }
+    + kfree(E);
+    + E = NULL;
+    // 
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c
+index 27841ef6a568..2be2d889d443 100644
+--- a/drivers/staging/serqt_usb2/serqt_usb2.c
++++ b/drivers/staging/serqt_usb2/serqt_usb2.c
+@@ -1098,8 +1098,7 @@ static void qt_close(struct usb_serial_port *port)
+ 
+ 	if (qt_port->write_urb) {
+ 		/* if this urb had a transfer buffer already (old tx) free it */
+-		if (qt_port->write_urb->transfer_buffer != NULL)
+-			kfree(qt_port->write_urb->transfer_buffer);
++		kfree(qt_port->write_urb->transfer_buffer);
+ 		usb_free_urb(qt_port->write_urb);
+ 	}
+ 

commit b7977fa250c1732d1fc1b5832f257655fd7471a4
+Author: Ilia Mirkin 
+Date:   Sun Mar 13 00:29:08 2011 -0500
+
+    staging: rtl8712: Remove NULL check before kfree
+    
+    This patch was generated by the following semantic patch:
+    // 
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); }
+    + kfree(E);
+    
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); E = NULL; }
+    + kfree(E);
+    + E = NULL;
+    // 
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
+index 8ebfdd620ba4..bd315c77610a 100644
+--- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
++++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
+@@ -1873,8 +1873,7 @@ static int r871x_mp_ioctl_hdl(struct net_device *dev,
+ 		goto _r871x_mp_ioctl_hdl_exit;
+ 	}
+ _r871x_mp_ioctl_hdl_exit:
+-	if (pparmbuf != NULL)
+-		kfree(pparmbuf);
++	kfree(pparmbuf);
+ 	return ret;
+ }
+ 

commit e72714fb20b2bac88e6bc06401a124243791ca08
+Author: Ilia Mirkin 
+Date:   Sun Mar 13 00:29:07 2011 -0500
+
+    staging: rtl8192u: Remove NULL check before kfree
+    
+    This patch was generated by the following semantic patch:
+    // 
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); }
+    + kfree(E);
+    
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); E = NULL; }
+    + kfree(E);
+    + E = NULL;
+    // 
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8192u/ieee80211/cipher.c b/drivers/staging/rtl8192u/ieee80211/cipher.c
+index 0b9e8a4ae7b5..69dcc3176ebc 100644
+--- a/drivers/staging/rtl8192u/ieee80211/cipher.c
++++ b/drivers/staging/rtl8192u/ieee80211/cipher.c
+@@ -294,6 +294,5 @@ int crypto_init_cipher_ops(struct crypto_tfm *tfm)
+ 
+ void crypto_exit_cipher_ops(struct crypto_tfm *tfm)
+ {
+-	if (tfm->crt_cipher.cit_iv)
+-		kfree(tfm->crt_cipher.cit_iv);
++	kfree(tfm->crt_cipher.cit_iv);
+ }
+diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
+index 7455264aa543..fe978f359f91 100644
+--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
++++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
+@@ -198,11 +198,8 @@ void free_ieee80211(struct net_device *dev)
+ 	int i;
+ 	//struct list_head *p, *q;
+ //	del_timer_sync(&ieee->SwBwTimer);
+-	if (ieee->pHTInfo != NULL)
+-	{
+-		kfree(ieee->pHTInfo);
+-		ieee->pHTInfo = NULL;
+-	}
++	kfree(ieee->pHTInfo);
++	ieee->pHTInfo = NULL;
+ 	RemoveAllTS(ieee);
+ 	ieee80211_softmac_free(ieee);
+ 	del_timer_sync(&ieee->crypt_deinit_timer);
+diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
+index 1ea8da3655ec..498b520efcf4 100644
+--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
++++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
+@@ -1384,11 +1384,8 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
+ 	return 1;
+ 
+  rx_dropped:
+-	if (rxb != NULL)
+-	{
+-		kfree(rxb);
+-		rxb = NULL;
+-	}
++	kfree(rxb);
++	rxb = NULL;
+ 	stats->rx_dropped++;
+ 
+ 	/* Returning 0 indicates to caller that we have not handled the SKB--
+diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
+index 20f8c347cae4..4992d630f984 100644
+--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
++++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
+@@ -2755,11 +2755,8 @@ void ieee80211_softmac_init(struct ieee80211_device *ieee)
+ void ieee80211_softmac_free(struct ieee80211_device *ieee)
+ {
+ 	down(&ieee->wx_sem);
+-	if(NULL != ieee->pDot11dInfo)
+-	{
+-		kfree(ieee->pDot11dInfo);
+-		ieee->pDot11dInfo = NULL;
+-	}
++	kfree(ieee->pDot11dInfo);
++	ieee->pDot11dInfo = NULL;
+ 	del_timer_sync(&ieee->associate_timer);
+ 
+ 	cancel_delayed_work(&ieee->associate_retry_wq);
+diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c
+index d6f55c290dbe..f0ba7f467493 100644
+--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c
++++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c
+@@ -855,7 +855,6 @@ int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
+ 		ieee->wpa_ie_len = len;
+ 	}
+ 	else{
+-		if (ieee->wpa_ie)
+ 		kfree(ieee->wpa_ie);
+ 		ieee->wpa_ie = NULL;
+ 		ieee->wpa_ie_len = 0;
+diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
+index ae4f2b9d9e8f..da612e6d994e 100644
+--- a/drivers/staging/rtl8192u/r8192U_core.c
++++ b/drivers/staging/rtl8192u/r8192U_core.c
+@@ -2242,12 +2242,8 @@ short rtl8192_usb_initendpoints(struct net_device *dev)
+ 
+ 
+ destroy:
+-	if (priv->pp_rxskb) {
+-		kfree(priv->pp_rxskb);
+-	}
+-	if (priv->rx_urb) {
+-		kfree(priv->rx_urb);
+-	}
++	kfree(priv->pp_rxskb);
++	kfree(priv->rx_urb);
+ 
+ 	priv->pp_rxskb = NULL;
+ 	priv->rx_urb = NULL;
+@@ -2276,10 +2272,8 @@ void rtl8192_usb_deleteendpoints(struct net_device *dev)
+ 		kfree(priv->rx_urb);
+ 		priv->rx_urb = NULL;
+ 	}
+-	if(priv->oldaddr){
+-		kfree(priv->oldaddr);
+-		priv->oldaddr = NULL;
+-	}
++	kfree(priv->oldaddr);
++	priv->oldaddr = NULL;
+ 	if (priv->pp_rxskb) {
+ 		kfree(priv->pp_rxskb);
+ 		priv->pp_rxskb = 0;
+@@ -2304,14 +2298,10 @@ void rtl8192_usb_deleteendpoints(struct net_device *dev)
+ 
+ 	}
+ #else
+-	if(priv->rx_urb){
+-		kfree(priv->rx_urb);
+-		priv->rx_urb = NULL;
+-	}
+-	if(priv->oldaddr){
+-		kfree(priv->oldaddr);
+-		priv->oldaddr = NULL;
+-	}
++	kfree(priv->rx_urb);
++	priv->rx_urb = NULL;
++	kfree(priv->oldaddr);
++	priv->oldaddr = NULL;
+ 	if (priv->pp_rxskb) {
+ 		kfree(priv->pp_rxskb);
+ 		priv->pp_rxskb = 0;
+@@ -5828,10 +5818,8 @@ static int __devinit rtl8192_usb_probe(struct usb_interface *intf,
+ 
+ fail2:
+ 	rtl8192_down(dev);
+-	if (priv->pFirmware) {
+-		kfree(priv->pFirmware);
+-		priv->pFirmware = NULL;
+-	}
++	kfree(priv->pFirmware);
++	priv->pFirmware = NULL;
+ 	rtl8192_usb_deleteendpoints(dev);
+ 	destroy_workqueue(priv->priv_wq);
+ 	mdelay(10);
+@@ -5869,11 +5857,8 @@ static void __devexit rtl8192_usb_disconnect(struct usb_interface *intf)
+ 		rtl8192_proc_remove_one(dev);
+ 
+ 			rtl8192_down(dev);
+-		if (priv->pFirmware)
+-		{
+-			kfree(priv->pFirmware);
+-			priv->pFirmware = NULL;
+-		}
++		kfree(priv->pFirmware);
++		priv->pFirmware = NULL;
+ 	//	priv->rf_close(dev);
+ //		rtl8192_SetRFPowerState(dev, eRfOff);
+ 		rtl8192_usb_deleteendpoints(dev);

commit 7e901dcd73d73230ad0e66e35fb6f1da244e41f7
+Author: Ilia Mirkin 
+Date:   Sun Mar 13 00:29:06 2011 -0500
+
+    staging: rtl8192e: Remove NULL check before kfree
+    
+    This patch was generated by the following semantic patch:
+    // 
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); }
+    + kfree(E);
+    
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); E = NULL; }
+    + kfree(E);
+    + E = NULL;
+    // 
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c
+index 67bcd41e66b1..663b0b8e1095 100644
+--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c
++++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c
+@@ -195,11 +195,8 @@ void free_ieee80211(struct net_device *dev)
+ {
+ 	struct ieee80211_device *ieee = netdev_priv(dev);
+ 	int i;
+-	if (ieee->pHTInfo != NULL)
+-	{
+-		kfree(ieee->pHTInfo);
+-		ieee->pHTInfo = NULL;
+-	}
++	kfree(ieee->pHTInfo);
++	ieee->pHTInfo = NULL;
+ 	RemoveAllTS(ieee);
+ 	ieee80211_softmac_free(ieee);
+ 	del_timer_sync(&ieee->crypt_deinit_timer);
+diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
+index e2eac7cadf4f..57acb3f21adf 100644
+--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
++++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
+@@ -1411,11 +1411,8 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
+ 	return 1;
+ 
+  rx_dropped:
+-	if (rxb != NULL)
+-	{
+-		kfree(rxb);
+-		rxb = NULL;
+-	}
++	kfree(rxb);
++	rxb = NULL;
+ 	stats->rx_dropped++;
+ 
+ 	/* Returning 0 indicates to caller that we have not handled the SKB--
+diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
+index fc96676bb9ce..8d73a7313766 100644
+--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
++++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
+@@ -2818,11 +2818,8 @@ void ieee80211_softmac_free(struct ieee80211_device *ieee)
+ {
+ 	down(&ieee->wx_sem);
+ #ifdef ENABLE_DOT11D
+-	if(NULL != ieee->pDot11dInfo)
+-	{
+-		kfree(ieee->pDot11dInfo);
+-		ieee->pDot11dInfo = NULL;
+-	}
++	kfree(ieee->pDot11dInfo);
++	ieee->pDot11dInfo = NULL;
+ #endif
+ 	del_timer_sync(&ieee->associate_timer);
+ 
+diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c
+index cac340e5238a..bb0ff26bd843 100644
+--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c
++++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c
+@@ -862,7 +862,6 @@ int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
+ 		ieee->wpa_ie_len = len;
+ 	}
+ 	else{
+-		if (ieee->wpa_ie)
+ 		kfree(ieee->wpa_ie);
+ 		ieee->wpa_ie = NULL;
+ 		ieee->wpa_ie_len = 0;

commit 76be349c0045073bbed4f669f87e36b1d8fda256
+Author: Ilia Mirkin 
+Date:   Sun Mar 13 00:29:05 2011 -0500
+
+    staging: rtl8187se: Remove NULL check before kfree
+    
+    This patch was generated by the following semantic patch:
+    // 
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); }
+    + kfree(E);
+    
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); E = NULL; }
+    + kfree(E);
+    + E = NULL;
+    // 
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
+index 74a3b4c211ad..771e0196842e 100644
+--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
++++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
+@@ -2605,8 +2605,7 @@ void ieee80211_softmac_free(struct ieee80211_device *ieee)
+ 	cancel_delayed_work(&ieee->GPIOChangeRFWorkItem);
+ 
+ 	destroy_workqueue(ieee->wq);
+-	if(NULL != ieee->pDot11dInfo)
+-		kfree(ieee->pDot11dInfo);
++	kfree(ieee->pDot11dInfo);
+ 	up(&ieee->wx_sem);
+ }
+ 
+diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
+index 07d8dbcdca28..ca414a915a4e 100644
+--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
++++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
+@@ -735,7 +735,6 @@ int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
+ 		ieee->wpa_ie_len = len;
+ 	}
+ 	else{
+-		if (ieee->wpa_ie)
+ 		kfree(ieee->wpa_ie);
+ 		ieee->wpa_ie = NULL;
+ 		ieee->wpa_ie_len = 0;

commit aea9d72f97218d45e993836bcb6c6e6fd49e0b90
+Author: Ilia Mirkin 
+Date:   Sun Mar 13 00:29:04 2011 -0500
+
+    staging: rt2860: Remove NULL check before kfree
+    
+    This patch was generated by the following semantic patch:
+    // 
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); }
+    + kfree(E);
+    
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); E = NULL; }
+    + kfree(E);
+    + E = NULL;
+    // 
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rt2860/common/spectrum.c b/drivers/staging/rt2860/common/spectrum.c
+index 1dfb802aab9a..c0d2f428069c 100644
+--- a/drivers/staging/rt2860/common/spectrum.c
++++ b/drivers/staging/rt2860/common/spectrum.c
+@@ -416,8 +416,7 @@ void MeasureReqTabExit(struct rt_rtmp_adapter *pAd)
+ {
+ 	NdisFreeSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
+ 
+-	if (pAd->CommonCfg.pMeasureReqTab)
+-		kfree(pAd->CommonCfg.pMeasureReqTab);
++	kfree(pAd->CommonCfg.pMeasureReqTab);
+ 	pAd->CommonCfg.pMeasureReqTab = NULL;
+ 
+ 	return;
+@@ -614,8 +613,7 @@ void TpcReqTabExit(struct rt_rtmp_adapter *pAd)
+ {
+ 	NdisFreeSpinLock(&pAd->CommonCfg.TpcReqTabLock);
+ 
+-	if (pAd->CommonCfg.pTpcReqTab)
+-		kfree(pAd->CommonCfg.pTpcReqTab);
++	kfree(pAd->CommonCfg.pTpcReqTab);
+ 	pAd->CommonCfg.pTpcReqTab = NULL;
+ 
+ 	return;
+diff --git a/drivers/staging/rt2860/rt_linux.c b/drivers/staging/rt2860/rt_linux.c
+index b3f836de332b..e5b042712430 100644
+--- a/drivers/staging/rt2860/rt_linux.c
++++ b/drivers/staging/rt2860/rt_linux.c
+@@ -241,8 +241,7 @@ void RTMPFreeAdapter(struct rt_rtmp_adapter *pAd)
+ 
+ 	os_cookie = (struct os_cookie *)pAd->OS_Cookie;
+ 
+-	if (pAd->BeaconBuf)
+-		kfree(pAd->BeaconBuf);
++	kfree(pAd->BeaconBuf);
+ 
+ 	NdisFreeSpinLock(&pAd->MgmtRingLock);
+ 
+@@ -264,8 +263,7 @@ void RTMPFreeAdapter(struct rt_rtmp_adapter *pAd)
+ 	release_firmware(pAd->firmware);
+ 
+ 	vfree(pAd);		/* pci_free_consistent(os_cookie->pci_dev,sizeof(struct rt_rtmp_adapter),pAd,os_cookie->pAd_pa); */
+-	if (os_cookie)
+-		kfree(os_cookie);
++	kfree(os_cookie);
+ }
+ 
+ BOOLEAN OS_Need_Clone_Packet(void)

commit 14910178fcdcca53230afd4155a6c48e230b2919
+Author: Ilia Mirkin 
+Date:   Sun Mar 13 00:29:03 2011 -0500
+
+    staging: pohmelfs: Remove NULL check before kfree
+    
+    This patch was generated by the following semantic patch:
+    // 
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); }
+    + kfree(E);
+    
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); E = NULL; }
+    + kfree(E);
+    + E = NULL;
+    // 
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/pohmelfs/config.c b/drivers/staging/pohmelfs/config.c
+index ed913306e5d6..a9a3e25a7efa 100644
+--- a/drivers/staging/pohmelfs/config.c
++++ b/drivers/staging/pohmelfs/config.c
+@@ -601,11 +601,9 @@ void pohmelfs_config_exit(void)
+ 
+ 		list_del(&g->group_entry);
+ 
+-		if (g->hash_string)
+-			kfree(g->hash_string);
++		kfree(g->hash_string);
+ 
+-		if (g->cipher_string)
+-			kfree(g->cipher_string);
++		kfree(g->cipher_string);
+ 
+ 		kfree(g);
+ 	}

commit 43c04d42c3c5a23e2aff330d4d361c733118df80
+Author: Ilia Mirkin 
+Date:   Sun Mar 13 00:29:02 2011 -0500
+
+    staging: line6: Remove NULL check before kfree
+    
+    This patch was generated by the following semantic patch:
+    // 
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); }
+    + kfree(E);
+    
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); E = NULL; }
+    + kfree(E);
+    + E = NULL;
+    // 
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/line6/pcm.c b/drivers/staging/line6/pcm.c
+index b9c55f9eb501..9d4c8a606eea 100644
+--- a/drivers/staging/line6/pcm.c
++++ b/drivers/staging/line6/pcm.c
+@@ -189,8 +189,7 @@ int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels)
+ 		line6pcm->buffer_out = NULL;
+ 	}
+ #if LINE6_BACKUP_MONITOR_SIGNAL
+-	if (line6pcm->prev_fbuf != NULL)
+-		kfree(line6pcm->prev_fbuf);
++	kfree(line6pcm->prev_fbuf);
+ #endif
+ 
+ 	return 0;

commit 306be9e1c167dcd7d6635bd434ee8e63ab22a5d6
+Author: Ilia Mirkin 
+Date:   Sun Mar 13 00:29:01 2011 -0500
+
+    staging: keucr: Remove NULL check before kfree
+    
+    This patch was generated by the following semantic patch:
+    // 
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); }
+    + kfree(E);
+    
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); E = NULL; }
+    + kfree(E);
+    + E = NULL;
+    // 
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/keucr/ms.c b/drivers/staging/keucr/ms.c
+index 48496e4da42b..a7137217cf86 100644
+--- a/drivers/staging/keucr/ms.c
++++ b/drivers/staging/keucr/ms.c
+@@ -244,8 +244,8 @@ int MS_CardInit(struct us_data *us)
+ 	result = MS_STATUS_SUCCESS;
+ 
+ exit:
+-	if (PageBuffer1)		kfree(PageBuffer1);
+-    	if (PageBuffer0)		kfree(PageBuffer0);
++	kfree(PageBuffer1);
++    	kfree(PageBuffer0);
+ 
+ 	printk("MS_CardInit end\n");
+ 	return result;
+@@ -280,7 +280,7 @@ int MS_LibCheckDisableBlock(struct us_data *us, WORD PhyBlock)
+ 	} while(1);
+ 
+ exit:
+-	if (PageBuf)	kfree(PageBuf);
++	kfree(PageBuf);
+ 	return result;
+ }
+ 
+@@ -324,17 +324,11 @@ void MS_LibFreeWriteBuf(struct us_data *us)
+ //----- MS_LibFreeLogicalMap() ---------------------------------------
+ int MS_LibFreeLogicalMap(struct us_data *us)
+ {
+-	if (us->MS_Lib.Phy2LogMap)
+-	{
+-		kfree(us->MS_Lib.Phy2LogMap);
+-		us->MS_Lib.Phy2LogMap = NULL;
+-	}
++	kfree(us->MS_Lib.Phy2LogMap);
++	us->MS_Lib.Phy2LogMap = NULL;
+ 
+-	if (us->MS_Lib.Log2PhyMap)
+-	{
+-		kfree(us->MS_Lib.Log2PhyMap);
+-		us->MS_Lib.Log2PhyMap = NULL;
+-	}
++	kfree(us->MS_Lib.Log2PhyMap);
++	us->MS_Lib.Log2PhyMap = NULL;
+ 
+     return 0;
+ }
+@@ -470,7 +464,7 @@ int MS_LibProcessBootBlock(struct us_data *us, WORD PhyBlock, BYTE *PageData)
+ 
+ exit:
+ 	if (result)		MS_LibFreeLogicalMap(us);
+-	if (PageBuffer)	kfree(PageBuffer);
++	kfree(PageBuffer);
+ 
+ 	result = 0;
+ 	return result;

commit 56d17639703b4683e3e9be36dff7c6d811f4cbf5
+Author: Ilia Mirkin 
+Date:   Sun Mar 13 00:28:59 2011 -0500
+
+    staging: go7007: Remove NULL check before kfree
+    
+    This patch was generated by the following semantic patch:
+    // 
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); }
+    + kfree(E);
+    
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); E = NULL; }
+    + kfree(E);
+    + E = NULL;
+    // 
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/go7007/go7007-usb.c b/drivers/staging/go7007/go7007-usb.c
+index bea9f4d5bc3c..3db3b0a91cc1 100644
+--- a/drivers/staging/go7007/go7007-usb.c
++++ b/drivers/staging/go7007/go7007-usb.c
+@@ -1247,15 +1247,13 @@ static void go7007_usb_disconnect(struct usb_interface *intf)
+ 		vurb = usb->video_urbs[i];
+ 		if (vurb) {
+ 			usb_kill_urb(vurb);
+-			if (vurb->transfer_buffer)
+-				kfree(vurb->transfer_buffer);
++			kfree(vurb->transfer_buffer);
+ 			usb_free_urb(vurb);
+ 		}
+ 		aurb = usb->audio_urbs[i];
+ 		if (aurb) {
+ 			usb_kill_urb(aurb);
+-			if (aurb->transfer_buffer)
+-				kfree(aurb->transfer_buffer);
++			kfree(aurb->transfer_buffer);
+ 			usb_free_urb(aurb);
+ 		}
+ 	}

commit b00917802bda6eba09125e8b4d273339188f9bad
+Author: Ilia Mirkin 
+Date:   Sun Mar 13 00:28:58 2011 -0500
+
+    staging: cx25821: Remove NULL check before kfree
+    
+    This patch was generated by the following semantic patch:
+    // 
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); }
+    + kfree(E);
+    
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); E = NULL; }
+    + kfree(E);
+    + E = NULL;
+    // 
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/cx25821/cx25821-audio-upstream.c b/drivers/staging/cx25821/cx25821-audio-upstream.c
+index 7992a3ba526f..0f9ca777bd4d 100644
+--- a/drivers/staging/cx25821/cx25821-audio-upstream.c
++++ b/drivers/staging/cx25821/cx25821-audio-upstream.c
+@@ -244,13 +244,10 @@ void cx25821_stop_upstream_audio(struct cx25821_dev *dev)
+ 	dev->_audioframe_count = 0;
+ 	dev->_audiofile_status = END_OF_FILE;
+ 
+-	if (dev->_irq_audio_queues) {
+-		kfree(dev->_irq_audio_queues);
+-		dev->_irq_audio_queues = NULL;
+-	}
++	kfree(dev->_irq_audio_queues);
++	dev->_irq_audio_queues = NULL;
+ 
+-	if (dev->_audiofilename != NULL)
+-		kfree(dev->_audiofilename);
++	kfree(dev->_audiofilename);
+ }
+ 
+ void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev)
+diff --git a/drivers/staging/cx25821/cx25821-video-upstream-ch2.c b/drivers/staging/cx25821/cx25821-video-upstream-ch2.c
+index e2efacdfb874..655357da3d6a 100644
+--- a/drivers/staging/cx25821/cx25821-video-upstream-ch2.c
++++ b/drivers/staging/cx25821/cx25821-video-upstream-ch2.c
+@@ -234,13 +234,10 @@ void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev)
+ 	dev->_frame_count_ch2 = 0;
+ 	dev->_file_status_ch2 = END_OF_FILE;
+ 
+-	if (dev->_irq_queues_ch2) {
+-		kfree(dev->_irq_queues_ch2);
+-		dev->_irq_queues_ch2 = NULL;
+-	}
++	kfree(dev->_irq_queues_ch2);
++	dev->_irq_queues_ch2 = NULL;
+ 
+-	if (dev->_filename_ch2 != NULL)
+-		kfree(dev->_filename_ch2);
++	kfree(dev->_filename_ch2);
+ 
+ 	tmp = cx_read(VID_CH_MODE_SEL);
+ 	cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
+diff --git a/drivers/staging/cx25821/cx25821-video-upstream.c b/drivers/staging/cx25821/cx25821-video-upstream.c
+index 31b4e3c74c8d..eb0172bf39d1 100644
+--- a/drivers/staging/cx25821/cx25821-video-upstream.c
++++ b/drivers/staging/cx25821/cx25821-video-upstream.c
+@@ -279,13 +279,10 @@ void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev)
+ 	dev->_frame_count = 0;
+ 	dev->_file_status = END_OF_FILE;
+ 
+-	if (dev->_irq_queues) {
+-		kfree(dev->_irq_queues);
+-		dev->_irq_queues = NULL;
+-	}
++	kfree(dev->_irq_queues);
++	dev->_irq_queues = NULL;
+ 
+-	if (dev->_filename != NULL)
+-		kfree(dev->_filename);
++	kfree(dev->_filename);
+ 
+ 	tmp = cx_read(VID_CH_MODE_SEL);
+ 	cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);

commit e4e1f289be88a75dc8b63d50ade1f9a2e6168021
+Author: Ilia Mirkin 
+Date:   Sun Mar 13 00:28:57 2011 -0500
+
+    staging: comedi: Remove NULL check before kfree
+    
+    This patch was generated by the following semantic patch:
+    // 
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); }
+    + kfree(E);
+    
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); E = NULL; }
+    + kfree(E);
+    + E = NULL;
+    // 
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c
+index 95049a8d3b38..6c26ac887eee 100644
+--- a/drivers/staging/comedi/drivers/8255.c
++++ b/drivers/staging/comedi/drivers/8255.c
+@@ -383,14 +383,7 @@ EXPORT_SYMBOL(subdev_8255_init_irq);
+ 
+ void subdev_8255_cleanup(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+-	if (s->private) {
+-		/* this test does nothing, so comment it out
+-		 * if (subdevpriv->have_irq) {
+-		 * }
+-		 */
+-
+-		kfree(s->private);
+-	}
++	kfree(s->private);
+ }
+ EXPORT_SYMBOL(subdev_8255_cleanup);
+ 
+diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
+index 0af1b4659088..e7905bac92da 100644
+--- a/drivers/staging/comedi/drivers/das16.c
++++ b/drivers/staging/comedi/drivers/das16.c
+@@ -1695,10 +1695,8 @@ static int das16_detach(struct comedi_device *dev)
+ 		}
+ 		if (devpriv->dma_chan)
+ 			free_dma(devpriv->dma_chan);
+-		if (devpriv->user_ai_range_table)
+-			kfree(devpriv->user_ai_range_table);
+-		if (devpriv->user_ao_range_table)
+-			kfree(devpriv->user_ao_range_table);
++		kfree(devpriv->user_ai_range_table);
++		kfree(devpriv->user_ao_range_table);
+ 	}
+ 
+ 	if (dev->irq)
+diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
+index e46d62b75fc0..4d0053ea2465 100644
+--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
++++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
+@@ -479,8 +479,7 @@ static int a2150_detach(struct comedi_device *dev)
+ 	if (devpriv) {
+ 		if (devpriv->dma)
+ 			free_dma(devpriv->dma);
+-		if (devpriv->dma_buffer)
+-			kfree(devpriv->dma_buffer);
++		kfree(devpriv->dma_buffer);
+ 	}
+ 
+ 	return 0;
+diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
+index 0728c3c0cb0e..241fe525abf0 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc.c
++++ b/drivers/staging/comedi/drivers/ni_labpc.c
+@@ -797,8 +797,7 @@ int labpc_common_detach(struct comedi_device *dev)
+ 		subdev_8255_cleanup(dev, dev->subdevices + 2);
+ 
+ 	/* only free stuff if it has been allocated by _attach */
+-	if (devpriv->dma_buffer)
+-		kfree(devpriv->dma_buffer);
++	kfree(devpriv->dma_buffer);
+ 	if (devpriv->dma_chan)
+ 		free_dma(devpriv->dma_chan);
+ 	if (dev->irq)
+diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
+index c9be9e05f028..ebfce33f0b4f 100644
+--- a/drivers/staging/comedi/drivers/serial2002.c
++++ b/drivers/staging/comedi/drivers/serial2002.c
+@@ -907,12 +907,8 @@ static int serial2002_detach(struct comedi_device *dev)
+ 	printk("comedi%d: serial2002: remove\n", dev->minor);
+ 	for (i = 0; i < 5; i++) {
+ 		s = &dev->subdevices[i];
+-		if (s->maxdata_list) {
+-			kfree(s->maxdata_list);
+-		}
+-		if (s->range_table_list) {
+-			kfree(s->range_table_list);
+-		}
++		kfree(s->maxdata_list);
++		kfree(s->range_table_list);
+ 	}
+ 	return 0;
+ }
+diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
+index 696ee045e25f..be93c30e4b15 100644
+--- a/drivers/staging/comedi/drivers/usbdux.c
++++ b/drivers/staging/comedi/drivers/usbdux.c
+@@ -2265,12 +2265,8 @@ static void tidy_up(struct usbduxsub *usbduxsub_tmp)
+ 			usbduxsub_unlink_OutURBs(usbduxsub_tmp);
+ 		}
+ 		for (i = 0; i < usbduxsub_tmp->numOfOutBuffers; i++) {
+-			if (usbduxsub_tmp->urbOut[i]->transfer_buffer) {
+-				kfree(usbduxsub_tmp->
+-				      urbOut[i]->transfer_buffer);
+-				usbduxsub_tmp->urbOut[i]->transfer_buffer =
+-				    NULL;
+-			}
++			kfree(usbduxsub_tmp->urbOut[i]->transfer_buffer);
++			usbduxsub_tmp->urbOut[i]->transfer_buffer = NULL;
+ 			if (usbduxsub_tmp->urbOut[i]) {
+ 				usb_kill_urb(usbduxsub_tmp->urbOut[i]);
+ 				usb_free_urb(usbduxsub_tmp->urbOut[i]);

commit 46d994b1f5b481c7f0a77edece270cf253db84c9
+Author: Ilia Mirkin 
+Date:   Sun Mar 13 00:28:56 2011 -0500
+
+    staging: brcm80211: Remove NULL check before kfree
+    
+    This patch was generated by the following semantic patch:
+    // 
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); }
+    + kfree(E);
+    
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); E = NULL; }
+    + kfree(E);
+    + E = NULL;
+    // 
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c b/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c
+index 8398fa4c0340..39a4d001fbd0 100644
+--- a/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c
++++ b/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c
+@@ -415,8 +415,7 @@ int dhd_prot_attach(dhd_pub_t *dhd)
+ 	return 0;
+ 
+ fail:
+-	if (cdc != NULL)
+-		kfree(cdc);
++	kfree(cdc);
+ 	return BCME_NOMEM;
+ }
+ 
+diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_common.c b/drivers/staging/brcm80211/brcmfmac/dhd_common.c
+index 64d88c20354e..aa171f6181e9 100644
+--- a/drivers/staging/brcm80211/brcmfmac/dhd_common.c
++++ b/drivers/staging/brcm80211/brcmfmac/dhd_common.c
+@@ -996,8 +996,7 @@ dhd_pktfilter_offload_enable(dhd_pub_t *dhd, char *arg, int enable,
+ 			   __func__, arg, rc));
+ 
+ fail:
+-	if (arg_org)
+-		kfree(arg_org);
++	kfree(arg_org);
+ }
+ 
+ void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg)
+@@ -1132,11 +1131,9 @@ void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg)
+ 			   __func__, arg));
+ 
+ fail:
+-	if (arg_org)
+-		kfree(arg_org);
++	kfree(arg_org);
+ 
+-	if (buf)
+-		kfree(buf);
++	kfree(buf);
+ }
+ 
+ void dhd_arp_offload_set(dhd_pub_t *dhd, int arp_mode)
+diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_linux.c b/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
+index d473f64bc0df..02c6d446934c 100644
+--- a/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
++++ b/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
+@@ -1777,8 +1777,7 @@ static int dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
+ 			bcmerror = -EFAULT;
+ 	}
+ 
+-	if (buf)
+-		kfree(buf);
++	kfree(buf);
+ 
+ 	if (bcmerror > 0)
+ 		bcmerror = 0;
+diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c b/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c
+index dd2e36749d0a..a6da7268d87a 100644
+--- a/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c
++++ b/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c
+@@ -1930,10 +1930,8 @@ static int dhdsdio_checkdied(dhd_bus_t *bus, u8 *data, uint size)
+ #endif				/* DHD_DEBUG */
+ 
+ done:
+-	if (mbuffer)
+-		kfree(mbuffer);
+-	if (str)
+-		kfree(str);
++	kfree(mbuffer);
++	kfree(str);
+ 
+ 	return bcmerror;
+ }
+@@ -1962,8 +1960,7 @@ static int dhdsdio_mem_dump(dhd_bus_t *bus)
+ 		ret = dhdsdio_membytes(bus, false, start, databuf, read_size);
+ 		if (ret) {
+ 			DHD_ERROR(("%s: Error membytes %d\n", __func__, ret));
+-			if (buf)
+-				kfree(buf);
++			kfree(buf);
+ 			return -1;
+ 		}
+ 		printk(".");
+@@ -2081,8 +2078,7 @@ int dhdsdio_downloadvars(dhd_bus_t *bus, void *arg, int len)
+ 	}
+ 
+ 	/* Free the old ones and replace with passed variables */
+-	if (bus->vars)
+-		kfree(bus->vars);
++	kfree(bus->vars);
+ 
+ 	bus->vars = kmalloc(len, GFP_ATOMIC);
+ 	bus->varsz = bus->vars ? len : 0;
+@@ -5541,10 +5537,8 @@ static void dhdsdio_release_malloc(dhd_bus_t *bus)
+ 		bus->rxlen = 0;
+ 	}
+ 
+-	if (bus->databuf) {
+-		kfree(bus->databuf);
+-		bus->databuf = NULL;
+-	}
++	kfree(bus->databuf);
++	bus->databuf = NULL;
+ }
+ 
+ static void dhdsdio_release_dongle(dhd_bus_t *bus)
+@@ -5732,8 +5726,7 @@ static int dhdsdio_download_code_file(struct dhd_bus *bus, char *fw_path)
+ 	}
+ 
+ err:
+-	if (memblock)
+-		kfree(memblock);
++	kfree(memblock);
+ 
+ 	if (image)
+ 		dhd_os_close_image(image);
+@@ -5872,8 +5865,7 @@ static int dhdsdio_download_nvram(struct dhd_bus *bus)
+ 	}
+ 
+ err:
+-	if (memblock)
+-		kfree(memblock);
++	kfree(memblock);
+ 
+ 	if (image)
+ 		dhd_os_close_image(image);
+diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_cmn.c b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_cmn.c
+index fc810e342df8..8f75af2ffc58 100644
+--- a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_cmn.c
++++ b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_cmn.c
+@@ -759,8 +759,7 @@ wlc_phy_t *wlc_phy_attach(shared_phy_t *sh, void *regs, int bandtype, char *vars
+ 	return &pi->pubpi_ro;
+ 
+  err:
+-	if (pi)
+-		kfree(pi);
++	kfree(pi);
+ 	return NULL;
+ }
+ 
+diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_n.c b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_n.c
+index a38587309ccc..7947c6028b6e 100644
+--- a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_n.c
++++ b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_n.c
+@@ -22383,8 +22383,7 @@ wlc_phy_gen_load_samples_nphy(phy_info_t *pi, u32 f_kHz, u16 max_val,
+ 
+ 	wlc_phy_loadsampletable_nphy(pi, tone_buf, num_samps);
+ 
+-	if (tone_buf != NULL)
+-		kfree(tone_buf);
++	kfree(tone_buf);
+ 
+ 	return num_samps;
+ }
+@@ -22431,8 +22430,7 @@ wlc_phy_loadsampletable_nphy(phy_info_t *pi, cs32 *tone_buf,
+ 	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SAMPLEPLAY, num_samps, 0, 32,
+ 				 data_buf);
+ 
+-	if (data_buf != NULL)
+-		kfree(data_buf);
++	kfree(data_buf);
+ 
+ 	if (pi->phyhang_avoid)
+ 		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+diff --git a/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c b/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c
+index a523b231cffe..66708d8df7f6 100644
+--- a/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c
++++ b/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c
+@@ -1379,8 +1379,7 @@ static void wl_free(struct wl_info *wl)
+ 	for (t = wl->timers; t; t = next) {
+ 		next = t->next;
+ #ifdef BCMDBG
+-		if (t->name)
+-			kfree(t->name);
++		kfree(t->name);
+ #endif
+ 		kfree(t);
+ 	}
+@@ -1716,8 +1715,7 @@ void wl_free_timer(struct wl_info *wl, struct wl_timer *t)
+ 	if (wl->timers == t) {
+ 		wl->timers = wl->timers->next;
+ #ifdef BCMDBG
+-		if (t->name)
+-			kfree(t->name);
++		kfree(t->name);
+ #endif
+ 		kfree(t);
+ 		return;
+@@ -1729,8 +1727,7 @@ void wl_free_timer(struct wl_info *wl, struct wl_timer *t)
+ 		if (tmp->next == t) {
+ 			tmp->next = t->next;
+ #ifdef BCMDBG
+-			if (t->name)
+-				kfree(t->name);
++			kfree(t->name);
+ #endif
+ 			kfree(t);
+ 			return;
+diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_main.c b/drivers/staging/brcm80211/brcmsmac/wlc_main.c
+index 97b320da433a..0870dc913cda 100644
+--- a/drivers/staging/brcm80211/brcmsmac/wlc_main.c
++++ b/drivers/staging/brcm80211/brcmsmac/wlc_main.c
+@@ -2160,10 +2160,8 @@ uint wlc_detach(struct wlc_info *wlc)
+ 
+ 
+ #ifdef BCMDBG
+-	if (wlc->country_ie_override) {
+-		kfree(wlc->country_ie_override);
+-		wlc->country_ie_override = NULL;
+-	}
++	kfree(wlc->country_ie_override);
++	wlc->country_ie_override = NULL;
+ #endif				/* BCMDBG */
+ 
+ 	{
+diff --git a/drivers/staging/brcm80211/util/bcmotp.c b/drivers/staging/brcm80211/util/bcmotp.c
+index b080345397f0..ba71c108b366 100644
+--- a/drivers/staging/brcm80211/util/bcmotp.c
++++ b/drivers/staging/brcm80211/util/bcmotp.c
+@@ -830,8 +830,7 @@ static int hndotp_nvread(void *oh, char *data, uint *len)
+ 	*len = offset;
+ 
+  out:
+-	if (rawotp)
+-		kfree(rawotp);
++	kfree(rawotp);
+ 	si_setcoreidx(oi->sih, idx);
+ 
+ 	return rc;
+diff --git a/drivers/staging/brcm80211/util/bcmsrom.c b/drivers/staging/brcm80211/util/bcmsrom.c
+index 7373603b6646..eca35b94e96c 100644
+--- a/drivers/staging/brcm80211/util/bcmsrom.c
++++ b/drivers/staging/brcm80211/util/bcmsrom.c
+@@ -1527,8 +1527,7 @@ static int otp_read_pci(si_t *sih, u16 *buf, uint bufsz)
+ 
+ 	memcpy(buf, otp, bufsz);
+ 
+-	if (otp)
+-		kfree(otp);
++	kfree(otp);
+ 
+ 	/* Check CRC */
+ 	if (buf[0] == 0xffff) {
+diff --git a/drivers/staging/brcm80211/util/hnddma.c b/drivers/staging/brcm80211/util/hnddma.c
+index 122f7d3fd704..8a81eb997f99 100644
+--- a/drivers/staging/brcm80211/util/hnddma.c
++++ b/drivers/staging/brcm80211/util/hnddma.c
+@@ -559,21 +559,17 @@ static void _dma_detach(dma_info_t *di)
+ 				    (di->rxdpaorig));
+ 
+ 	/* free packet pointer vectors */
+-	if (di->txp)
+-		kfree((void *)di->txp);
+-	if (di->rxp)
+-		kfree((void *)di->rxp);
++	kfree(di->txp);
++	kfree(di->rxp);
+ 
+ 	/* free tx packet DMA handles */
+-	if (di->txp_dmah)
+-		kfree(di->txp_dmah);
++	kfree(di->txp_dmah);
+ 
+ 	/* free rx packet DMA handles */
+-	if (di->rxp_dmah)
+-		kfree(di->rxp_dmah);
++	kfree(di->rxp_dmah);
+ 
+ 	/* free our private info structure */
+-	kfree((void *)di);
++	kfree(di);
+ 
+ }
+ 

commit 23c32986870b4abb5b426d3399a4cbd43948e37c
+Author: Ilia Mirkin 
+Date:   Sun Mar 13 00:28:55 2011 -0500
+
+    staging: bcm: Remove NULL check before kfree
+    
+    This patch was generated by the following semantic patch:
+    // 
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); }
+    + kfree(E);
+    
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); E = NULL; }
+    + kfree(E);
+    + E = NULL;
+    // 
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/bcm/CmHost.c b/drivers/staging/bcm/CmHost.c
+index 017b4717b25b..9be184f143e5 100644
+--- a/drivers/staging/bcm/CmHost.c
++++ b/drivers/staging/bcm/CmHost.c
+@@ -974,11 +974,7 @@ static VOID CopyToAdapter( register PMINI_ADAPTER Adapter,		/**u8RequesttransmissionPolicy &
+ 				MASK_DISABLE_HEADER_SUPPRESSION);
+ 
+-	if(Adapter->PackInfo[uiSearchRuleIndex].pstSFIndication)
+-	{
+-		kfree(Adapter->PackInfo[uiSearchRuleIndex].pstSFIndication);
+-		Adapter->PackInfo[uiSearchRuleIndex].pstSFIndication = NULL;
+-	}
++	kfree(Adapter->PackInfo[uiSearchRuleIndex].pstSFIndication);
+ 	Adapter->PackInfo[uiSearchRuleIndex].pstSFIndication = pstAddIndication;
+ 
+ 	//Re Sort the SF list in PackInfo according to Traffic Priority
+@@ -1971,10 +1967,7 @@ INT AllocAdapterDsxBuffer(PMINI_ADAPTER Adapter)
+ 
+ INT FreeAdapterDsxBuffer(PMINI_ADAPTER Adapter)
+ {
+-	if(Adapter->caDsxReqResp)
+-	{
+-		kfree(Adapter->caDsxReqResp);
+-	}
++	kfree(Adapter->caDsxReqResp);
+ 	return 0;
+ 
+ }

commit 4dd53810912089380223c8fbddd83dcb642b6166
+Author: Ilia Mirkin 
+Date:   Sun Mar 13 00:28:54 2011 -0500
+
+    staging: ath6kl: Remove NULL check before kfree
+    
+    This patch was generated by the following semantic patch:
+    // 
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); }
+    + kfree(E);
+    
+    @@ expression E; @@
+    - if (E != NULL) { kfree(E); E = NULL; }
+    + kfree(E);
+    + E = NULL;
+    // 
+    
+    Signed-off-by: Ilia Mirkin 
+    Acked-by: Luis R. Rodriguez 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c b/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c
+index b9f8c7206da6..8a1cedb9eea9 100644
+--- a/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c
++++ b/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c
+@@ -1214,9 +1214,7 @@ delHifDevice(HIF_DEVICE * device)
+ {
+     AR_DEBUG_ASSERT(device!= NULL);
+     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: delHifDevice; 0x%p\n", device));
+-    if (device->dma_buffer != NULL) {
+-        kfree(device->dma_buffer);
+-    }
++    kfree(device->dma_buffer);
+     kfree(device);
+ }
+ 
+diff --git a/drivers/staging/ath6kl/os/linux/ar6000_android.c b/drivers/staging/ath6kl/os/linux/ar6000_android.c
+index f7d1069072b9..002cdc76c830 100644
+--- a/drivers/staging/ath6kl/os/linux/ar6000_android.c
++++ b/drivers/staging/ath6kl/os/linux/ar6000_android.c
+@@ -120,9 +120,7 @@ int logger_write(const enum logidx index,
+     }
+     set_fs(oldfs);
+ out_free_message:
+-    if (msg) {
+-        kfree(msg);
+-    }
++    kfree(msg);
+     return ret;
+ }
+ #endif
+diff --git a/drivers/staging/ath6kl/os/linux/ar6k_pal.c b/drivers/staging/ath6kl/os/linux/ar6k_pal.c
+index fee7cb945e24..8dd51ee0f72f 100644
+--- a/drivers/staging/ath6kl/os/linux/ar6k_pal.c
++++ b/drivers/staging/ath6kl/os/linux/ar6k_pal.c
+@@ -260,10 +260,8 @@ static void bt_cleanup_hci_pal(ar6k_hci_pal_info_t *pHciPalInfo)
+ 		}          
+ 	}
+ 
+-	if (pHciPalInfo->hdev != NULL) {
+-		kfree(pHciPalInfo->hdev);
+-		pHciPalInfo->hdev = NULL;
+-	}
++	kfree(pHciPalInfo->hdev);
++	pHciPalInfo->hdev = NULL;
+ }
+ 
+ /*********************************************************
+diff --git a/drivers/staging/ath6kl/os/linux/hci_bridge.c b/drivers/staging/ath6kl/os/linux/hci_bridge.c
+index a02827bab8d9..327aab6f0109 100644
+--- a/drivers/staging/ath6kl/os/linux/hci_bridge.c
++++ b/drivers/staging/ath6kl/os/linux/hci_bridge.c
+@@ -929,10 +929,8 @@ static void bt_cleanup_hci(struct ar6k_hci_bridge_info *pHcidevInfo)
+         }          
+     }   
+     
+-    if (pHcidevInfo->pBtStackHCIDev != NULL) {
+-        kfree(pHcidevInfo->pBtStackHCIDev);
+-        pHcidevInfo->pBtStackHCIDev = NULL;
+-    }  
++    kfree(pHcidevInfo->pBtStackHCIDev);
++    pHcidevInfo->pBtStackHCIDev = NULL;  
+ }
+ 
+ static int bt_register_hci(struct ar6k_hci_bridge_info *pHcidevInfo)

commit f7fdaca910e6bc13659ecdffc28c97938b752e01
+Author: Ilia Mirkin 
+Date:   Sun Feb 20 17:10:51 2011 -0500
+
+    arm: imx: Zero entire imxdma structure
+    
+    The semantic match that finds the problem:
+    // 
+    @@
+    type T;
+    identifier x;
+    @@
+    
+    T *x;
+    ...
+    * memset(x, ..., ... * sizeof(x) * ...);
+    // 
+    
+    Signed-off-by: Ilia Mirkin 
+    Signed-off-by: Sascha Hauer 
+
+diff --git a/arch/arm/mach-imx/dma-v1.c b/arch/arm/mach-imx/dma-v1.c
+index e9f1769b49f5..236f1495efad 100644
+--- a/arch/arm/mach-imx/dma-v1.c
++++ b/arch/arm/mach-imx/dma-v1.c
+@@ -699,7 +699,7 @@ int imx_dma_request(int channel, const char *name)
+ 		local_irq_restore(flags);
+ 		return -EBUSY;
+ 	}
+-	memset(imxdma, 0, sizeof(imxdma));
++	memset(imxdma, 0, sizeof(*imxdma));
+ 	imxdma->name = name;
+ 	local_irq_restore(flags); /* request_irq() can block */
+ 

commit e9ca75b53576ddf82ea2d803f87c59dffac7bc42
+Author: Gerald Britton 
+Date:   Mon May 14 13:53:01 2007 -0400
+
+    cciss: Fix pci_driver.shutdown while device is still active
+    
+    Fix an Oops in the cciss driver caused by system shutdown while a filesystem
+    on a cciss device is still active.  The cciss_remove_one function only
+    properly removes the device if the device has been cleanly released by its
+    users, which is not the case when the pci_driver.shutdown method is called.
+    
+    This patch adds a new cciss_shutdown function to better match the pattern
+    used by various SCSI drivers: deactivate device interrupts and flush caches.
+    It also alters the cciss_remove_one function to match and readds the
+    __devexit annotation that was removed when cciss_remove_one was serving as
+    the pci_driver.shutdown method.
+    
+    Signed-off-by: Gerald Britton 
+    Acked-by: Mike Miller 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
+index 370dfe1c422e..5acc6c44aead 100644
+--- a/drivers/block/cciss.c
++++ b/drivers/block/cciss.c
+@@ -3469,13 +3469,39 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
+ 	return -1;
+ }
+ 
+-static void cciss_remove_one(struct pci_dev *pdev)
++static void cciss_shutdown(struct pci_dev *pdev)
+ {
+ 	ctlr_info_t *tmp_ptr;
+-	int i, j;
++	int i;
+ 	char flush_buf[4];
+ 	int return_code;
+ 
++	tmp_ptr = pci_get_drvdata(pdev);
++	if (tmp_ptr == NULL)
++		return;
++	i = tmp_ptr->ctlr;
++	if (hba[i] == NULL)
++		return;
++
++	/* Turn board interrupts off  and send the flush cache command */
++	/* sendcmd will turn off interrupt, and send the flush...
++	 * To write all data in the battery backed cache to disks */
++	memset(flush_buf, 0, 4);
++	return_code = sendcmd(CCISS_CACHE_FLUSH, i, flush_buf, 4, 0, 0, 0, NULL,
++			      TYPE_CMD);
++	if (return_code == IO_OK) {
++		printk(KERN_INFO "Completed flushing cache on controller %d\n", i);
++	} else {
++		printk(KERN_WARNING "Error flushing cache on controller %d\n", i);
++	}
++	free_irq(hba[i]->intr[2], hba[i]);
++}
++
++static void __devexit cciss_remove_one(struct pci_dev *pdev)
++{
++	ctlr_info_t *tmp_ptr;
++	int i, j;
++
+ 	if (pci_get_drvdata(pdev) == NULL) {
+ 		printk(KERN_ERR "cciss: Unable to remove device \n");
+ 		return;
+@@ -3506,18 +3532,7 @@ static void cciss_remove_one(struct pci_dev *pdev)
+ 
+ 	cciss_unregister_scsi(i);	/* unhook from SCSI subsystem */
+ 
+-	/* Turn board interrupts off  and send the flush cache command */
+-	/* sendcmd will turn off interrupt, and send the flush...
+-	 * To write all data in the battery backed cache to disks */
+-	memset(flush_buf, 0, 4);
+-	return_code = sendcmd(CCISS_CACHE_FLUSH, i, flush_buf, 4, 0, 0, 0, NULL,
+-			      TYPE_CMD);
+-	if (return_code == IO_OK) {
+-		printk(KERN_INFO "Completed flushing cache on controller %d\n", i);
+-	} else {
+-		printk(KERN_WARNING "Error flushing cache on controller %d\n", i);
+-	}
+-	free_irq(hba[i]->intr[2], hba[i]);
++	cciss_shutdown(pdev);
+ 
+ #ifdef CONFIG_PCI_MSI
+ 	if (hba[i]->msix_vector)
+@@ -3550,7 +3565,7 @@ static struct pci_driver cciss_pci_driver = {
+ 	.probe = cciss_init_one,
+ 	.remove = __devexit_p(cciss_remove_one),
+ 	.id_table = cciss_pci_device_id,	/* id_table */
+-	.shutdown = cciss_remove_one,
++	.shutdown = cciss_shutdown,
+ };
+ 
+ /*

commit 303794400992b907b7cac0d91788603636c7e0fe
+Author: Gerald Britton 
+Date:   Tue Feb 14 10:19:04 2006 -0500
+
+    [PATCH] x86: fix oprofile kernel callgraph regression
+    
+    Fix x86 oprofile regression introduced by:
+      commit c34d1b4d165c67b966bca4aba026443d7ff161eb
+      [PATCH] mm: kill check_user_page_readable
+    
+    That commit reorganized tests for the userspace stack walking moving all
+    those tests into dump_backtrace(), however, dump_backtrace() was used for
+    both userspace and kernel stalk walking.  The result is typically no
+    recorded callgraph information for kernel samples.
+    
+    Revive the original function as dump_kernel_backtrace() and rename the
+    other to dump_user_backtrace() to avoid future confusion.
+    
+    Signed-off-by: Gerald Britton 
+    Apology-from: Hugh Dickins 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/i386/oprofile/backtrace.c b/arch/i386/oprofile/backtrace.c
+index acc18138fb22..c049ce414f01 100644
+--- a/arch/i386/oprofile/backtrace.c
++++ b/arch/i386/oprofile/backtrace.c
+@@ -20,7 +20,20 @@ struct frame_head {
+ } __attribute__((packed));
+ 
+ static struct frame_head *
+-dump_backtrace(struct frame_head * head)
++dump_kernel_backtrace(struct frame_head * head)
++{
++	oprofile_add_trace(head->ret);
++
++	/* frame pointers should strictly progress back up the stack
++	 * (towards higher addresses) */
++	if (head >= head->ebp)
++		return NULL;
++
++	return head->ebp;
++}
++
++static struct frame_head *
++dump_user_backtrace(struct frame_head * head)
+ {
+ 	struct frame_head bufhead[2];
+ 
+@@ -105,10 +118,10 @@ x86_backtrace(struct pt_regs * const regs, unsigned int depth)
+ 
+ 	if (!user_mode_vm(regs)) {
+ 		while (depth-- && valid_kernel_stack(head, regs))
+-			head = dump_backtrace(head);
++			head = dump_kernel_backtrace(head);
+ 		return;
+ 	}
+ 
+ 	while (depth-- && head)
+-		head = dump_backtrace(head);
++		head = dump_user_backtrace(head);
+ }

commit 70a0dec45174c976c64b4c8c1d0898581f759948
+Author: Tom Goff 
+Date:   Thu Jun 23 16:11:57 2016 -0400
+
+    ipmr/ip6mr: Initialize the last assert time of mfc entries.
+    
+    This fixes wrong-interface signaling on 32-bit platforms for entries
+    created when jiffies > 2^31 + MFC_ASSERT_THRESH.
+    
+    Signed-off-by: Tom Goff 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
+index 21a38e296fe2..5ad48ec77710 100644
+--- a/net/ipv4/ipmr.c
++++ b/net/ipv4/ipmr.c
+@@ -891,8 +891,10 @@ static struct mfc_cache *ipmr_cache_alloc(void)
+ {
+ 	struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
+ 
+-	if (c)
++	if (c) {
++		c->mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1;
+ 		c->mfc_un.res.minvif = MAXVIFS;
++	}
+ 	return c;
+ }
+ 
+diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
+index f2e2013f8346..487ef3bc7bbc 100644
+--- a/net/ipv6/ip6mr.c
++++ b/net/ipv6/ip6mr.c
+@@ -1074,6 +1074,7 @@ static struct mfc6_cache *ip6mr_cache_alloc(void)
+ 	struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
+ 	if (!c)
+ 		return NULL;
++	c->mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1;
+ 	c->mfc_un.res.minvif = MAXMIFS;
+ 	return c;
+ }

commit 92944c4520edd35a060cfbdaa7431d4e3c3ebd56
+Author: David Ward 
+Date:   Wed Sep 16 12:28:01 2015 -0400
+
+    USB: qcserial: update comment for Sierra Wireless MC7304/MC7354
+    
+    This comment is ambiguous since there are other MC73xx devices with
+    different USB IDs. This USB ID is found in the MC7304 and MC7354.
+    
+    Cc: Bjørn Mork 
+    Signed-off-by: David Ward 
+    Signed-off-by: Johan Hovold 
+
+diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
+index 8ad342dddca3..f224820f7652 100644
+--- a/drivers/usb/serial/qcserial.c
++++ b/drivers/usb/serial/qcserial.c
+@@ -143,7 +143,7 @@ static const struct usb_device_id id_table[] = {
+ 	{DEVICE_SWI(0x0f3d, 0x68a2)},	/* Sierra Wireless MC7700 */
+ 	{DEVICE_SWI(0x114f, 0x68a2)},	/* Sierra Wireless MC7750 */
+ 	{DEVICE_SWI(0x1199, 0x68a2)},	/* Sierra Wireless MC7710 */
+-	{DEVICE_SWI(0x1199, 0x68c0)},	/* Sierra Wireless MC73xx */
++	{DEVICE_SWI(0x1199, 0x68c0)},	/* Sierra Wireless MC7304/MC7354 */
+ 	{DEVICE_SWI(0x1199, 0x901c)},	/* Sierra Wireless EM7700 */
+ 	{DEVICE_SWI(0x1199, 0x901f)},	/* Sierra Wireless EM7355 */
+ 	{DEVICE_SWI(0x1199, 0x9040)},	/* Sierra Wireless Modem */

commit fbbf9fd2f1b8b4490ff777df2af5543608dde6f1
+Author: David Ward 
+Date:   Wed Sep 16 12:28:00 2015 -0400
+
+    Revert "USB: qcserial/option: make AT URCs work for Sierra Wireless MC73xx"
+    
+    This reverts commit d80c0d14183516f184a5ac88e11008ee4c7d2a2e
+    (excluding the change to MAX_BL_NUM, which has since been removed).
+    
+    The qcserial driver now enables the SET_CONTROL_LINE_STATE request
+    so that AT URCs will work. Move these devices back to the qcserial
+    driver, which is used for other devices in this series that follow
+    the same layout.
+    
+    Cc: Bjørn Mork 
+    Signed-off-by: David Ward 
+    Signed-off-by: Johan Hovold 
+
+diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
+index af4f3def3673..685fef71d3d1 100644
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -233,8 +233,6 @@ static void option_instat_callback(struct urb *urb);
+ 
+ #define QUALCOMM_VENDOR_ID			0x05C6
+ 
+-#define SIERRA_VENDOR_ID			0x1199
+-
+ #define CMOTECH_VENDOR_ID			0x16d8
+ #define CMOTECH_PRODUCT_6001			0x6001
+ #define CMOTECH_PRODUCT_CMU_300			0x6002
+@@ -610,11 +608,6 @@ static const struct option_blacklist_info telit_le920_blacklist = {
+ 	.reserved = BIT(1) | BIT(5),
+ };
+ 
+-static const struct option_blacklist_info sierra_mc73xx_blacklist = {
+-	.sendsetup = BIT(0) | BIT(2),
+-	.reserved = BIT(8) | BIT(10) | BIT(11),
+-};
+-
+ static const struct usb_device_id option_ids[] = {
+ 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
+ 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
+@@ -1112,8 +1105,6 @@ static const struct usb_device_id option_ids[] = {
+ 	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
+ 	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */
+ 	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */
+-	{ USB_DEVICE_INTERFACE_CLASS(SIERRA_VENDOR_ID, 0x68c0, 0xff),
+-	  .driver_info = (kernel_ulong_t)&sierra_mc73xx_blacklist }, /* MC73xx */
+ 	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
+ 	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
+ 	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003),
+diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
+index 9bb42cff143a..8ad342dddca3 100644
+--- a/drivers/usb/serial/qcserial.c
++++ b/drivers/usb/serial/qcserial.c
+@@ -143,6 +143,7 @@ static const struct usb_device_id id_table[] = {
+ 	{DEVICE_SWI(0x0f3d, 0x68a2)},	/* Sierra Wireless MC7700 */
+ 	{DEVICE_SWI(0x114f, 0x68a2)},	/* Sierra Wireless MC7750 */
+ 	{DEVICE_SWI(0x1199, 0x68a2)},	/* Sierra Wireless MC7710 */
++	{DEVICE_SWI(0x1199, 0x68c0)},	/* Sierra Wireless MC73xx */
+ 	{DEVICE_SWI(0x1199, 0x901c)},	/* Sierra Wireless EM7700 */
+ 	{DEVICE_SWI(0x1199, 0x901f)},	/* Sierra Wireless EM7355 */
+ 	{DEVICE_SWI(0x1199, 0x9040)},	/* Sierra Wireless Modem */

commit 3d07984b4fe76000f5210630c19ab34aa9d3c5a4
+Author: David Ward 
+Date:   Wed Sep 16 12:27:59 2015 -0400
+
+    Revert "USB: qcserial/option: make AT URCs work for Sierra Wireless MC7305/MC7355"
+    
+    This reverts commit 653cdc13a340ad1cef29f1bab0d05d0771fa1d57.
+    
+    The qcserial driver now enables the SET_CONTROL_LINE_STATE request
+    so that AT URCs will work. Move these devices back to the qcserial
+    driver, which is used for other devices in this series that follow
+    the same layout.
+    
+    Cc: Bjørn Mork 
+    Signed-off-by: David Ward 
+    Signed-off-by: Johan Hovold 
+
+diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
+index edfaec19e1ae..af4f3def3673 100644
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -1114,8 +1114,6 @@ static const struct usb_device_id option_ids[] = {
+ 	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */
+ 	{ USB_DEVICE_INTERFACE_CLASS(SIERRA_VENDOR_ID, 0x68c0, 0xff),
+ 	  .driver_info = (kernel_ulong_t)&sierra_mc73xx_blacklist }, /* MC73xx */
+-	{ USB_DEVICE_INTERFACE_CLASS(SIERRA_VENDOR_ID, 0x9041, 0xff),
+-	  .driver_info = (kernel_ulong_t)&sierra_mc73xx_blacklist }, /* MC7305/MC7355 */
+ 	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
+ 	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
+ 	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003),
+diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
+index c2d0e5cfd2c3..9bb42cff143a 100644
+--- a/drivers/usb/serial/qcserial.c
++++ b/drivers/usb/serial/qcserial.c
+@@ -146,6 +146,7 @@ static const struct usb_device_id id_table[] = {
+ 	{DEVICE_SWI(0x1199, 0x901c)},	/* Sierra Wireless EM7700 */
+ 	{DEVICE_SWI(0x1199, 0x901f)},	/* Sierra Wireless EM7355 */
+ 	{DEVICE_SWI(0x1199, 0x9040)},	/* Sierra Wireless Modem */
++	{DEVICE_SWI(0x1199, 0x9041)},	/* Sierra Wireless MC7305/MC7355 */
+ 	{DEVICE_SWI(0x1199, 0x9051)},	/* Netgear AirCard 340U */
+ 	{DEVICE_SWI(0x1199, 0x9053)},	/* Sierra Wireless Modem */
+ 	{DEVICE_SWI(0x1199, 0x9054)},	/* Sierra Wireless Modem */

commit efd3e9151fea1b1140d39dc58ec7099a07f0bdff
+Author: David Ward 
+Date:   Wed Sep 16 12:27:58 2015 -0400
+
+    USB: qcserial: make AT URCs work for Sierra Wireless devices
+    
+    Three Sierra Wireless modems have been found to require the CDC ACM
+    SET_CONTROL_LINE_STATE request on the AT port in order to receive
+    unsolicited response codes, most recently the Dell Wireless 5808e
+    (which is a re-branded Sierra Wireless EM7355). On the other hand,
+    the Sierra Wireless MC7710 does not seem to need this request, but
+    it was found to work either way.
+    
+    Use this request on the AT port of devices with the Sierra Wireless
+    layout in the qcserial driver. The other modems that were moved to
+    the option driver to work around this can now be moved back.
+    
+    Cc: Bjørn Mork 
+    Signed-off-by: David Ward 
+    Signed-off-by: Johan Hovold 
+
+diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
+index ebcec8cda858..c2d0e5cfd2c3 100644
+--- a/drivers/usb/serial/qcserial.c
++++ b/drivers/usb/serial/qcserial.c
+@@ -175,6 +175,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
+ 	__u8 nintf;
+ 	__u8 ifnum;
+ 	int altsetting = -1;
++	bool sendsetup = false;
+ 
+ 	nintf = serial->dev->actconfig->desc.bNumInterfaces;
+ 	dev_dbg(dev, "Num Interfaces = %d\n", nintf);
+@@ -286,6 +287,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
+ 			break;
+ 		case 3:
+ 			dev_dbg(dev, "Modem port found\n");
++			sendsetup = true;
+ 			break;
+ 		default:
+ 			/* don't claim any unsupported interface */
+@@ -337,17 +339,25 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
+ 		}
+ 	}
+ 
++	if (!retval)
++		usb_set_serial_data(serial, (void *)(unsigned long)sendsetup);
++
+ 	return retval;
+ }
+ 
+ static int qc_attach(struct usb_serial *serial)
+ {
+ 	struct usb_wwan_intf_private *data;
++	bool sendsetup;
+ 
+ 	data = kzalloc(sizeof(*data), GFP_KERNEL);
+ 	if (!data)
+ 		return -ENOMEM;
+ 
++	sendsetup = !!(unsigned long)(usb_get_serial_data(serial));
++	if (sendsetup)
++		data->use_send_setup = 1;
++
+ 	spin_lock_init(&data->susp_lock);
+ 
+ 	usb_set_serial_data(serial, data);
+@@ -374,6 +384,7 @@ static struct usb_serial_driver qcdevice = {
+ 	.probe               = qcprobe,
+ 	.open		     = usb_wwan_open,
+ 	.close		     = usb_wwan_close,
++	.dtr_rts	     = usb_wwan_dtr_rts,
+ 	.write		     = usb_wwan_write,
+ 	.write_room	     = usb_wwan_write_room,
+ 	.chars_in_buffer     = usb_wwan_chars_in_buffer,

commit 669e729f9fb4e05ff02dfa01cbb8606549c6cb7c
+Author: David Ward 
+Date:   Wed Sep 16 12:27:57 2015 -0400
+
+    USB: usb_wwan/option: generalize option_send_setup for other drivers
+    
+    Only the option driver implements the send_setup callback; it uses the
+    SET_CONTROL_LINE_STATE request in CDC ACM to generate DTR/RTS signals
+    on the port. This is not driver-specific though and is needed by other
+    drivers, so move the function to the usb_wwan driver (with formatting
+    tweaks), and replace the callback pointer with a flag that enables the
+    request.
+    
+    Suggested-by: Bjørn Mork 
+    Suggested-by: Johan Hovold 
+    Signed-off-by: David Ward 
+    Signed-off-by: Johan Hovold 
+
+diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
+index 4d16c9744f54..edfaec19e1ae 100644
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -48,7 +48,6 @@ static int  option_probe(struct usb_serial *serial,
+ 			const struct usb_device_id *id);
+ static int option_attach(struct usb_serial *serial);
+ static void option_release(struct usb_serial *serial);
+-static int option_send_setup(struct usb_serial_port *port);
+ static void option_instat_callback(struct urb *urb);
+ 
+ /* Vendor and product IDs */
+@@ -1890,7 +1889,7 @@ static int option_attach(struct usb_serial *serial)
+ 
+ 	if (!blacklist || !test_bit(iface_desc->bInterfaceNumber,
+ 						&blacklist->sendsetup)) {
+-		data->send_setup = option_send_setup;
++		data->use_send_setup = 1;
+ 	}
+ 	spin_lock_init(&data->susp_lock);
+ 
+@@ -1961,39 +1960,6 @@ static void option_instat_callback(struct urb *urb)
+ 	}
+ }
+ 
+-/** send RTS/DTR state to the port.
+- *
+- * This is exactly the same as SET_CONTROL_LINE_STATE from the PSTN
+- * CDC.
+-*/
+-static int option_send_setup(struct usb_serial_port *port)
+-{
+-	struct usb_serial *serial = port->serial;
+-	struct usb_wwan_port_private *portdata;
+-	int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
+-	int val = 0;
+-	int res;
+-
+-	portdata = usb_get_serial_port_data(port);
+-
+-	if (portdata->dtr_state)
+-		val |= 0x01;
+-	if (portdata->rts_state)
+-		val |= 0x02;
+-
+-	res = usb_autopm_get_interface(serial->interface);
+-	if (res)
+-		return res;
+-
+-	res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+-				0x22, 0x21, val, ifNum, NULL,
+-				0, USB_CTRL_SET_TIMEOUT);
+-
+-	usb_autopm_put_interface(serial->interface);
+-
+-	return res;
+-}
+-
+ MODULE_AUTHOR(DRIVER_AUTHOR);
+ MODULE_DESCRIPTION(DRIVER_DESC);
+ MODULE_LICENSE("GPL");
+diff --git a/drivers/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h
+index f22dff58b587..44b25c08c68a 100644
+--- a/drivers/usb/serial/usb-wwan.h
++++ b/drivers/usb/serial/usb-wwan.h
+@@ -34,9 +34,9 @@ extern int usb_wwan_resume(struct usb_serial *serial);
+ struct usb_wwan_intf_private {
+ 	spinlock_t susp_lock;
+ 	unsigned int suspended:1;
++	unsigned int use_send_setup:1;
+ 	int in_flight;
+ 	unsigned int open_ports;
+-	int (*send_setup) (struct usb_serial_port *port);
+ 	void *private;
+ };
+ 
+diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
+index 825305cb71d9..be9cb61b4d19 100644
+--- a/drivers/usb/serial/usb_wwan.c
++++ b/drivers/usb/serial/usb_wwan.c
+@@ -36,6 +36,40 @@
+ #include 
+ #include "usb-wwan.h"
+ 
++/*
++ * Generate DTR/RTS signals on the port using the SET_CONTROL_LINE_STATE request
++ * in CDC ACM.
++ */
++static int usb_wwan_send_setup(struct usb_serial_port *port)
++{
++	struct usb_serial *serial = port->serial;
++	struct usb_wwan_port_private *portdata;
++	int val = 0;
++	int ifnum;
++	int res;
++
++	portdata = usb_get_serial_port_data(port);
++
++	if (portdata->dtr_state)
++		val |= 0x01;
++	if (portdata->rts_state)
++		val |= 0x02;
++
++	ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
++
++	res = usb_autopm_get_interface(serial->interface);
++	if (res)
++		return res;
++
++	res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
++				0x22, 0x21, val, ifnum, NULL, 0,
++				USB_CTRL_SET_TIMEOUT);
++
++	usb_autopm_put_interface(port->serial->interface);
++
++	return res;
++}
++
+ void usb_wwan_dtr_rts(struct usb_serial_port *port, int on)
+ {
+ 	struct usb_wwan_port_private *portdata;
+@@ -43,7 +77,7 @@ void usb_wwan_dtr_rts(struct usb_serial_port *port, int on)
+ 
+ 	intfdata = usb_get_serial_data(port->serial);
+ 
+-	if (!intfdata->send_setup)
++	if (!intfdata->use_send_setup)
+ 		return;
+ 
+ 	portdata = usb_get_serial_port_data(port);
+@@ -51,7 +85,7 @@ void usb_wwan_dtr_rts(struct usb_serial_port *port, int on)
+ 	portdata->rts_state = on;
+ 	portdata->dtr_state = on;
+ 
+-	intfdata->send_setup(port);
++	usb_wwan_send_setup(port);
+ }
+ EXPORT_SYMBOL(usb_wwan_dtr_rts);
+ 
+@@ -84,7 +118,7 @@ int usb_wwan_tiocmset(struct tty_struct *tty,
+ 	portdata = usb_get_serial_port_data(port);
+ 	intfdata = usb_get_serial_data(port->serial);
+ 
+-	if (!intfdata->send_setup)
++	if (!intfdata->use_send_setup)
+ 		return -EINVAL;
+ 
+ 	/* FIXME: what locks portdata fields ? */
+@@ -97,7 +131,7 @@ int usb_wwan_tiocmset(struct tty_struct *tty,
+ 		portdata->rts_state = 0;
+ 	if (clear & TIOCM_DTR)
+ 		portdata->dtr_state = 0;
+-	return intfdata->send_setup(port);
++	return usb_wwan_send_setup(port);
+ }
+ EXPORT_SYMBOL(usb_wwan_tiocmset);
+ 

commit bd8869e86b8a1e5e5b29fad766b2676bb74e5395
+Author: David Ward 
+Date:   Wed Sep 16 12:27:56 2015 -0400
+
+    USB: option: revert introduction of struct option_private
+    
+    This is a partial, context modified revert of commit e463c6dda8f5
+    ("USB: option: handle send_setup blacklisting at probe"), which
+    introduced an unnecessary struct option_private for storing the
+    interface number used in option_send_setup. Removing this struct
+    will allow option_send_setup to be generalized for other drivers.
+    
+    Suggested-by: Bjørn Mork 
+    Signed-off-by: David Ward 
+    Signed-off-by: Johan Hovold 
+
+diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
+index 6956c4f62216..4d16c9744f54 100644
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -1835,10 +1835,6 @@ static struct usb_serial_driver * const serial_drivers[] = {
+ 	&option_1port_device, NULL
+ };
+ 
+-struct option_private {
+-	u8 bInterfaceNumber;
+-};
+-
+ module_usb_serial_driver(serial_drivers, option_ids);
+ 
+ static int option_probe(struct usb_serial *serial,
+@@ -1882,26 +1878,16 @@ static int option_attach(struct usb_serial *serial)
+ 	struct usb_interface_descriptor *iface_desc;
+ 	const struct option_blacklist_info *blacklist;
+ 	struct usb_wwan_intf_private *data;
+-	struct option_private *priv;
+ 
+ 	data = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL);
+ 	if (!data)
+ 		return -ENOMEM;
+ 
+-	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+-	if (!priv) {
+-		kfree(data);
+-		return -ENOMEM;
+-	}
+-
+ 	/* Retrieve blacklist info stored at probe. */
+ 	blacklist = usb_get_serial_data(serial);
+ 
+ 	iface_desc = &serial->interface->cur_altsetting->desc;
+ 
+-	priv->bInterfaceNumber = iface_desc->bInterfaceNumber;
+-	data->private = priv;
+-
+ 	if (!blacklist || !test_bit(iface_desc->bInterfaceNumber,
+ 						&blacklist->sendsetup)) {
+ 		data->send_setup = option_send_setup;
+@@ -1916,9 +1902,7 @@ static int option_attach(struct usb_serial *serial)
+ static void option_release(struct usb_serial *serial)
+ {
+ 	struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial);
+-	struct option_private *priv = intfdata->private;
+ 
+-	kfree(priv);
+ 	kfree(intfdata);
+ }
+ 
+@@ -1985,9 +1969,8 @@ static void option_instat_callback(struct urb *urb)
+ static int option_send_setup(struct usb_serial_port *port)
+ {
+ 	struct usb_serial *serial = port->serial;
+-	struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial);
+-	struct option_private *priv = intfdata->private;
+ 	struct usb_wwan_port_private *portdata;
++	int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
+ 	int val = 0;
+ 	int res;
+ 
+@@ -2003,7 +1986,7 @@ static int option_send_setup(struct usb_serial_port *port)
+ 		return res;
+ 
+ 	res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+-				0x22, 0x21, val, priv->bInterfaceNumber, NULL,
++				0x22, 0x21, val, ifNum, NULL,
+ 				0, USB_CTRL_SET_TIMEOUT);
+ 
+ 	usb_autopm_put_interface(serial->interface);

commit e704059272aae2aaa5e5ce7a76e4c27c492e947e
+Author: David Ward 
+Date:   Mon Aug 31 14:15:14 2015 -0400
+
+    net: qmi_wwan: Sierra Wireless MC73xx -> Sierra Wireless MC7304/MC7354
+    
+    Other Sierra Wireless MC73xx devices exist, with different USB IDs.
+    
+    Cc: Bjørn Mork 
+    Signed-off-by: David Ward 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
+index 6392ae3c4ab8..355842b85ee9 100644
+--- a/drivers/net/usb/qmi_wwan.c
++++ b/drivers/net/usb/qmi_wwan.c
+@@ -752,8 +752,8 @@ static const struct usb_device_id products[] = {
+ 	{QMI_FIXED_INTF(0x114f, 0x68a2, 8)},    /* Sierra Wireless MC7750 */
+ 	{QMI_FIXED_INTF(0x1199, 0x68a2, 8)},	/* Sierra Wireless MC7710 in QMI mode */
+ 	{QMI_FIXED_INTF(0x1199, 0x68a2, 19)},	/* Sierra Wireless MC7710 in QMI mode */
+-	{QMI_FIXED_INTF(0x1199, 0x68c0, 8)},	/* Sierra Wireless MC73xx */
+-	{QMI_FIXED_INTF(0x1199, 0x68c0, 10)},	/* Sierra Wireless MC73xx */
++	{QMI_FIXED_INTF(0x1199, 0x68c0, 8)},	/* Sierra Wireless MC7304/MC7354 */
++	{QMI_FIXED_INTF(0x1199, 0x68c0, 10)},	/* Sierra Wireless MC7304/MC7354 */
+ 	{QMI_FIXED_INTF(0x1199, 0x901c, 8)},    /* Sierra Wireless EM7700 */
+ 	{QMI_FIXED_INTF(0x1199, 0x901f, 8)},    /* Sierra Wireless EM7355 */
+ 	{QMI_FIXED_INTF(0x1199, 0x9041, 8)},	/* Sierra Wireless MC7305/MC7355 */

commit 44840dec6127e4d7c5074f75d2dd96bc4ab85fe3
+Author: David Ward 
+Date:   Tue Aug 18 10:36:23 2015 +0200
+
+    USB: qcserial: add HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module
+    
+    This is an HP-branded Sierra Wireless EM7355:
+    https://bugzilla.redhat.com/show_bug.cgi?id=1223646#c2
+    
+    Signed-off-by: David Ward 
+    Cc: stable 
+    Signed-off-by: Johan Hovold 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
+index d156545728c2..ebcec8cda858 100644
+--- a/drivers/usb/serial/qcserial.c
++++ b/drivers/usb/serial/qcserial.c
+@@ -139,6 +139,7 @@ static const struct usb_device_id id_table[] = {
+ 	{USB_DEVICE(0x0AF0, 0x8120)},	/* Option GTM681W */
+ 
+ 	/* non-Gobi Sierra Wireless devices */
++	{DEVICE_SWI(0x03f0, 0x4e1d)},	/* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */
+ 	{DEVICE_SWI(0x0f3d, 0x68a2)},	/* Sierra Wireless MC7700 */
+ 	{DEVICE_SWI(0x114f, 0x68a2)},	/* Sierra Wireless MC7750 */
+ 	{DEVICE_SWI(0x1199, 0x68a2)},	/* Sierra Wireless MC7710 */

commit a8079092c1bbf9aec3756b35256c7816b8845af7
+Author: David Ward 
+Date:   Sat Aug 15 20:12:30 2015 -0400
+
+    net: qmi_wwan: add HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module
+    
+    This is an HP-branded Sierra Wireless EM7355:
+    https://bugzilla.redhat.com/show_bug.cgi?id=1223646#c2
+    
+    Signed-off-by: David Ward 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
+index 9d43460ce3c7..64a60afbe50c 100644
+--- a/drivers/net/usb/qmi_wwan.c
++++ b/drivers/net/usb/qmi_wwan.c
+@@ -785,6 +785,7 @@ static const struct usb_device_id products[] = {
+ 	{QMI_FIXED_INTF(0x413c, 0x81a4, 8)},	/* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */
+ 	{QMI_FIXED_INTF(0x413c, 0x81a8, 8)},	/* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card */
+ 	{QMI_FIXED_INTF(0x413c, 0x81a9, 8)},	/* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */
++	{QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)},	/* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */
+ 	{QMI_FIXED_INTF(0x03f0, 0x581d, 4)},	/* HP lt4112 LTE/HSPA+ Gobi 4G Module (Huawei me906e) */
+ 
+ 	/* 4. Gobi 1000 devices */

commit 865b804244f228e80fb62abe464296399253cce8
+Author: David Ward 
+Date:   Sun Jul 26 12:18:58 2015 -0400
+
+    net/ipv4: suppress NETDEV_UP notification on address lifetime update
+    
+    This notification causes the FIB to be updated, which is not needed
+    because the address already exists, and more importantly it may undo
+    intentional changes that were made to the FIB after the address was
+    originally added. (As a point of comparison, when an address becomes
+    deprecated because its preferred lifetime expired, a notification on
+    this chain is not generated.)
+    
+    The motivation for this commit is fixing an incompatibility between
+    DHCP clients which set and update the address lifetime according to
+    the lease, and a commercial VPN client which replaces kernel routes
+    in a way that outbound traffic is sent only through the tunnel (and
+    disconnects if any further route changes are detected via netlink).
+    
+    Signed-off-by: David Ward 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
+index e813196c91c7..2d9cb1748f81 100644
+--- a/net/ipv4/devinet.c
++++ b/net/ipv4/devinet.c
+@@ -882,7 +882,6 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 		queue_delayed_work(system_power_efficient_wq,
+ 				&check_lifetime_work, 0);
+ 		rtmsg_ifa(RTM_NEWADDR, ifa, nlh, NETLINK_CB(skb).portid);
+-		blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa);
+ 	}
+ 	return 0;
+ }

commit a3eb95f891d6130b1fc03dd07a8b54cf0a5c8ab8
+Author: David Ward 
+Date:   Sat May 9 22:01:46 2015 -0400
+
+    net_sched: gred: add TCA_GRED_LIMIT attribute
+    
+    In a GRED qdisc, if the default "virtual queue" (VQ) does not have drop
+    parameters configured, then packets for the default VQ are not subjected
+    to RED and are only dropped if the queue is larger than the net_device's
+    tx_queue_len. This behavior is useful for WRED mode, since these packets
+    will still influence the calculated average queue length and (therefore)
+    the drop probability for all of the other VQs. However, for some drivers
+    tx_queue_len is zero. In other cases the user may wish to make the limit
+    the same for all VQs (including the default VQ with no drop parameters).
+    
+    This change adds a TCA_GRED_LIMIT attribute to set the GRED queue limit,
+    in bytes, during qdisc setup. (This limit is in bytes to be consistent
+    with the drop parameters.) The default limit is the same as for a bfifo
+    queue (tx_queue_len * psched_mtu). If the drop parameters of any VQ are
+    configured with a smaller limit than the GRED queue limit, that VQ will
+    still observe the smaller limit instead.
+    
+    Signed-off-by: David Ward 
+    Signed-off-by: David S. Miller 
+
+diff --git a/include/uapi/linux/pkt_sched.h b/include/uapi/linux/pkt_sched.h
+index 69d88b309cc7..8d2530daca9f 100644
+--- a/include/uapi/linux/pkt_sched.h
++++ b/include/uapi/linux/pkt_sched.h
+@@ -268,7 +268,8 @@ enum {
+        TCA_GRED_STAB,
+        TCA_GRED_DPS,
+        TCA_GRED_MAX_P,
+-	   __TCA_GRED_MAX,
++       TCA_GRED_LIMIT,
++       __TCA_GRED_MAX,
+ };
+ 
+ #define TCA_GRED_MAX (__TCA_GRED_MAX - 1)
+diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
+index a4ca4517cdc8..826e2994152b 100644
+--- a/net/sched/sch_gred.c
++++ b/net/sched/sch_gred.c
+@@ -165,7 +165,8 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+ 			 * if no default DP has been configured. This
+ 			 * allows for DP flows to be left untouched.
+ 			 */
+-			if (skb_queue_len(&sch->q) < qdisc_dev(sch)->tx_queue_len)
++			if (likely(sch->qstats.backlog + qdisc_pkt_len(skb) <=
++					sch->limit))
+ 				return qdisc_enqueue_tail(skb, sch);
+ 			else
+ 				goto drop;
+@@ -397,7 +398,10 @@ static inline int gred_change_vq(struct Qdisc *sch, int dp,
+ 
+ 	q->DP = dp;
+ 	q->prio = prio;
+-	q->limit = ctl->limit;
++	if (ctl->limit > sch->limit)
++		q->limit = sch->limit;
++	else
++		q->limit = ctl->limit;
+ 
+ 	if (q->backlog == 0)
+ 		red_end_of_idle_period(&q->vars);
+@@ -414,6 +418,7 @@ static const struct nla_policy gred_policy[TCA_GRED_MAX + 1] = {
+ 	[TCA_GRED_STAB]		= { .len = 256 },
+ 	[TCA_GRED_DPS]		= { .len = sizeof(struct tc_gred_sopt) },
+ 	[TCA_GRED_MAX_P]	= { .type = NLA_U32 },
++	[TCA_GRED_LIMIT]	= { .type = NLA_U32 },
+ };
+ 
+ static int gred_change(struct Qdisc *sch, struct nlattr *opt)
+@@ -433,11 +438,15 @@ static int gred_change(struct Qdisc *sch, struct nlattr *opt)
+ 	if (err < 0)
+ 		return err;
+ 
+-	if (tb[TCA_GRED_PARMS] == NULL && tb[TCA_GRED_STAB] == NULL)
++	if (tb[TCA_GRED_PARMS] == NULL && tb[TCA_GRED_STAB] == NULL) {
++		if (tb[TCA_GRED_LIMIT] != NULL)
++			sch->limit = nla_get_u32(tb[TCA_GRED_LIMIT]);
+ 		return gred_change_table_def(sch, opt);
++	}
+ 
+ 	if (tb[TCA_GRED_PARMS] == NULL ||
+-	    tb[TCA_GRED_STAB] == NULL)
++	    tb[TCA_GRED_STAB] == NULL ||
++	    tb[TCA_GRED_LIMIT] != NULL)
+ 		return -EINVAL;
+ 
+ 	max_P = tb[TCA_GRED_MAX_P] ? nla_get_u32(tb[TCA_GRED_MAX_P]) : 0;
+@@ -501,6 +510,14 @@ static int gred_init(struct Qdisc *sch, struct nlattr *opt)
+ 	if (tb[TCA_GRED_PARMS] || tb[TCA_GRED_STAB])
+ 		return -EINVAL;
+ 
++	if (tb[TCA_GRED_LIMIT])
++		sch->limit = nla_get_u32(tb[TCA_GRED_LIMIT]);
++	else {
++		u32 qlen = qdisc_dev(sch)->tx_queue_len ? : 1;
++
++		sch->limit = qlen * psched_mtu(qdisc_dev(sch));
++	}
++
+ 	return gred_change_table_def(sch, tb[TCA_GRED_DPS]);
+ }
+ 
+@@ -531,6 +548,9 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)
+ 	if (nla_put(skb, TCA_GRED_MAX_P, sizeof(max_p), max_p))
+ 		goto nla_put_failure;
+ 
++	if (nla_put_u32(skb, TCA_GRED_LIMIT, sch->limit))
++		goto nla_put_failure;
++
+ 	parms = nla_nest_start(skb, TCA_GRED_PARMS);
+ 	if (parms == NULL)
+ 		goto nla_put_failure;

commit 145a42b3a964c6647464f05bd58aa33787de7f75
+Author: David Ward 
+Date:   Sat May 9 22:01:47 2015 -0400
+
+    net_sched: gred: use correct backlog value in WRED mode
+    
+    In WRED mode, the backlog for a single virtual queue (VQ) should not be
+    used to determine queue behavior; instead the backlog is summed across
+    all VQs. This sum is currently used when calculating the average queue
+    lengths. It also needs to be used when determining if the queue's hard
+    limit has been reached, or when reporting each VQ's backlog via netlink.
+    q->backlog will only be used if the queue switches out of WRED mode.
+    
+    Signed-off-by: David Ward 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
+index a4ca4517cdc8..634529e0ce6b 100644
+--- a/net/sched/sch_gred.c
++++ b/net/sched/sch_gred.c
+@@ -229,7 +229,7 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+ 		break;
+ 	}
+ 
+-	if (q->backlog + qdisc_pkt_len(skb) <= q->limit) {
++	if (gred_backlog(t, q, sch) + qdisc_pkt_len(skb) <= q->limit) {
+ 		q->backlog += qdisc_pkt_len(skb);
+ 		return qdisc_enqueue_tail(skb, sch);
+ 	}
+@@ -553,7 +553,7 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)
+ 
+ 		opt.limit	= q->limit;
+ 		opt.DP		= q->DP;
+-		opt.backlog	= q->backlog;
++		opt.backlog	= gred_backlog(table, q, sch);
+ 		opt.prio	= q->prio;
+ 		opt.qth_min	= q->parms.qth_min >> q->parms.Wlog;
+ 		opt.qth_max	= q->parms.qth_max >> q->parms.Wlog;

commit fb745e9a037895321781d066aa24757ceabf9df9
+Author: David Ward 
+Date:   Thu Apr 11 13:47:15 2013 +0000
+
+    net/802/mrp: fix possible race condition when calling mrp_pdu_queue()
+    
+    (Adapted from a very similar change to net/802/garp.c by Cong Wang.)
+    
+    mrp_pdu_queue() should ways be called with the applicant spin lock.
+    mrp_uninit_applicant() only holds the rtnl lock which is not enough;
+    a race is possible because mrp_rcv() is called in BH context:
+    
+            mrp_rcv()
+              |->mrp_pdu_parse_msg()
+                |->mrp_pdu_parse_vecattr()
+                  |->mrp_pdu_parse_vecattr_event()
+                    |-> mrp_attr_event()
+                      |-> mrp_pdu_append_vecattr_event()
+                        |-> mrp_pdu_queue()
+    
+    Cc: Cong Wang 
+    Cc: Eric Dumazet 
+    Signed-off-by: David Ward 
+    Acked-by: Cong Wang 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/802/mrp.c b/net/802/mrp.c
+index a4cc3229952a..e085bcc754f6 100644
+--- a/net/802/mrp.c
++++ b/net/802/mrp.c
+@@ -870,8 +870,12 @@ void mrp_uninit_applicant(struct net_device *dev, struct mrp_application *appl)
+ 	 * all pending messages before the applicant is gone.
+ 	 */
+ 	del_timer_sync(&app->join_timer);
++
++	spin_lock(&app->lock);
+ 	mrp_mad_event(app, MRP_EVENT_TX);
+ 	mrp_pdu_queue(app);
++	spin_unlock(&app->lock);
++
+ 	mrp_queue_xmit(app);
+ 
+ 	dev_mc_del(dev, appl->group_address);

commit 4660c7f498c07c43173142ea95145e9dac5a6d14
+Author: David Ward 
+Date:   Mon Mar 11 10:43:39 2013 +0000
+
+    net/ipv4: Ensure that location of timestamp option is stored
+    
+    This is needed in order to detect if the timestamp option appears
+    more than once in a packet, to remove the option if the packet is
+    fragmented, etc. My previous change neglected to store the option
+    location when the router addresses were prespecified and Pointer >
+    Length. But now the option location is also stored when Flag is an
+    unrecognized value, to ensure these option handling behaviors are
+    still performed.
+    
+    Signed-off-by: David Ward 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
+index 310a3647c83d..ec7264514a82 100644
+--- a/net/ipv4/ip_options.c
++++ b/net/ipv4/ip_options.c
+@@ -370,7 +370,6 @@ int ip_options_compile(struct net *net,
+ 				}
+ 				switch (optptr[3]&0xF) {
+ 				      case IPOPT_TS_TSONLY:
+-					opt->ts = optptr - iph;
+ 					if (skb)
+ 						timeptr = &optptr[optptr[2]-1];
+ 					opt->ts_needtime = 1;
+@@ -381,7 +380,6 @@ int ip_options_compile(struct net *net,
+ 						pp_ptr = optptr + 2;
+ 						goto error;
+ 					}
+-					opt->ts = optptr - iph;
+ 					if (rt)  {
+ 						spec_dst_fill(&spec_dst, skb);
+ 						memcpy(&optptr[optptr[2]-1], &spec_dst, 4);
+@@ -396,7 +394,6 @@ int ip_options_compile(struct net *net,
+ 						pp_ptr = optptr + 2;
+ 						goto error;
+ 					}
+-					opt->ts = optptr - iph;
+ 					{
+ 						__be32 addr;
+ 						memcpy(&addr, &optptr[optptr[2]-1], 4);
+@@ -429,12 +426,12 @@ int ip_options_compile(struct net *net,
+ 					pp_ptr = optptr + 3;
+ 					goto error;
+ 				}
+-				opt->ts = optptr - iph;
+ 				if (skb) {
+ 					optptr[3] = (optptr[3]&0xF)|((overflow+1)<<4);
+ 					opt->is_changed = 1;
+ 				}
+ 			}
++			opt->ts = optptr - iph;
+ 			break;
+ 		      case IPOPT_RA:
+ 			if (optlen < 4) {

commit fef4c86e59a76f2ec1a77d5732f40752700bd5dd
+Author: David Oostdyk 
+Date:   Fri Mar 8 08:28:15 2013 +0000
+
+    rrunner.c: fix possible memory leak in rr_init_one()
+    
+    In the event that register_netdev() failed, the rrpriv->evt_ring
+    allocation would have not been freed.
+    
+    Signed-off-by: David Oostdyk 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/hippi/rrunner.c b/drivers/net/hippi/rrunner.c
+index e5b19b056909..3c4d6274bb9b 100644
+--- a/drivers/net/hippi/rrunner.c
++++ b/drivers/net/hippi/rrunner.c
+@@ -202,6 +202,9 @@ static int rr_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	return 0;
+ 
+  out:
++	if (rrpriv->evt_ring)
++		pci_free_consistent(pdev, EVT_RING_SIZE, rrpriv->evt_ring,
++				    rrpriv->evt_ring_dma);
+ 	if (rrpriv->rx_ring)
+ 		pci_free_consistent(pdev, RX_TOTAL_SIZE, rrpriv->rx_ring,
+ 				    rrpriv->rx_ring_dma);

commit fa2b04f4502d74659e4e4b1294c6d88e08ece032
+Author: David Ward 
+Date:   Tue Mar 5 17:06:32 2013 +0000
+
+    net/ipv4: Timestamp option cannot overflow with prespecified addresses
+    
+    When a router forwards a packet that contains the IPv4 timestamp option,
+    if there is no space left in the option for the router to add its own
+    timestamp, then the router increments the Overflow value in the option.
+    
+    However, if the addresses of the routers are prespecified in the option,
+    then the overflow condition cannot happen: the option is structured so
+    that each prespecified router has a place to write its timestamp. Other
+    routers do not add a timestamp, so there will never be a lack of space.
+    
+    This fix ensures that the Overflow value in the IPv4 timestamp option is
+    not incremented when the addresses of the routers are prespecified, even
+    if the Pointer value is greater than the Length value.
+    
+    Signed-off-by: David Ward 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
+index f6289bf6f332..310a3647c83d 100644
+--- a/net/ipv4/ip_options.c
++++ b/net/ipv4/ip_options.c
+@@ -423,7 +423,7 @@ int ip_options_compile(struct net *net,
+ 					put_unaligned_be32(midtime, timeptr);
+ 					opt->is_changed = 1;
+ 				}
+-			} else {
++			} else if ((optptr[3]&0xF) != IPOPT_TS_PRESPEC) {
+ 				unsigned int overflow = optptr[3]>>4;
+ 				if (overflow == 15) {
+ 					pp_ptr = optptr + 3;

commit 86fbe9bb599fcaf7e92e38dbfdad0414a2d68f7d
+Author: David Ward 
+Date:   Fri Feb 8 17:17:07 2013 +0000
+
+    net/8021q: Implement Multiple VLAN Registration Protocol (MVRP)
+    
+    Initial implementation of the Multiple VLAN Registration Protocol
+    (MVRP) from IEEE 802.1Q-2011, based on the existing implementation
+    of the GARP VLAN Registration Protocol (GVRP).
+    
+    Signed-off-by: David Ward 
+    Acked-by: Patrick McHardy 
+    Signed-off-by: David S. Miller 
+
+diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h
+index 67fb87ca1094..798032d01112 100644
+--- a/include/uapi/linux/if_ether.h
++++ b/include/uapi/linux/if_ether.h
+@@ -83,6 +83,7 @@
+ #define ETH_P_802_EX1	0x88B5		/* 802.1 Local Experimental 1.  */
+ #define ETH_P_TIPC	0x88CA		/* TIPC 			*/
+ #define ETH_P_8021AH	0x88E7          /* 802.1ah Backbone Service Tag */
++#define ETH_P_MVRP	0x88F5          /* 802.1Q MVRP                  */
+ #define ETH_P_1588	0x88F7		/* IEEE 1588 Timesync */
+ #define ETH_P_FCOE	0x8906		/* Fibre Channel over Ethernet  */
+ #define ETH_P_TDLS	0x890D          /* TDLS */
+diff --git a/include/uapi/linux/if_vlan.h b/include/uapi/linux/if_vlan.h
+index 0744f8e65d15..7e5e6b397332 100644
+--- a/include/uapi/linux/if_vlan.h
++++ b/include/uapi/linux/if_vlan.h
+@@ -34,6 +34,7 @@ enum vlan_flags {
+ 	VLAN_FLAG_REORDER_HDR	= 0x1,
+ 	VLAN_FLAG_GVRP		= 0x2,
+ 	VLAN_FLAG_LOOSE_BINDING	= 0x4,
++	VLAN_FLAG_MVRP		= 0x8,
+ };
+ 
+ enum vlan_name_types {
+diff --git a/net/8021q/Kconfig b/net/8021q/Kconfig
+index fa073a54963e..8f7517df41a5 100644
+--- a/net/8021q/Kconfig
++++ b/net/8021q/Kconfig
+@@ -27,3 +27,14 @@ config VLAN_8021Q_GVRP
+ 	  automatic propagation of registered VLANs to switches.
+ 
+ 	  If unsure, say N.
++
++config VLAN_8021Q_MVRP
++	bool "MVRP (Multiple VLAN Registration Protocol) support"
++	depends on VLAN_8021Q
++	select MRP
++	help
++	  Select this to enable MVRP end-system support. MVRP is used for
++	  automatic propagation of registered VLANs to switches; it
++	  supersedes GVRP and is not backwards-compatible.
++
++	  If unsure, say N.
+diff --git a/net/8021q/Makefile b/net/8021q/Makefile
+index 9f4f174ead1c..7bc8db08d7ef 100644
+--- a/net/8021q/Makefile
++++ b/net/8021q/Makefile
+@@ -6,5 +6,6 @@ obj-$(CONFIG_VLAN_8021Q)		+= 8021q.o
+ 
+ 8021q-y					:= vlan.o vlan_dev.o vlan_netlink.o
+ 8021q-$(CONFIG_VLAN_8021Q_GVRP)		+= vlan_gvrp.o
++8021q-$(CONFIG_VLAN_8021Q_MVRP)		+= vlan_mvrp.o
+ 8021q-$(CONFIG_PROC_FS)			+= vlanproc.o
+ 
+diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
+index addc578d5443..a18714469bf7 100644
+--- a/net/8021q/vlan.c
++++ b/net/8021q/vlan.c
+@@ -95,6 +95,8 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
+ 
+ 	grp->nr_vlan_devs--;
+ 
++	if (vlan->flags & VLAN_FLAG_MVRP)
++		vlan_mvrp_request_leave(dev);
+ 	if (vlan->flags & VLAN_FLAG_GVRP)
+ 		vlan_gvrp_request_leave(dev);
+ 
+@@ -107,8 +109,10 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
+ 
+ 	netdev_upper_dev_unlink(real_dev, dev);
+ 
+-	if (grp->nr_vlan_devs == 0)
++	if (grp->nr_vlan_devs == 0) {
++		vlan_mvrp_uninit_applicant(real_dev);
+ 		vlan_gvrp_uninit_applicant(real_dev);
++	}
+ 
+ 	/* Get rid of the vlan's reference to real_dev */
+ 	dev_put(real_dev);
+@@ -151,15 +155,18 @@ int register_vlan_dev(struct net_device *dev)
+ 		err = vlan_gvrp_init_applicant(real_dev);
+ 		if (err < 0)
+ 			goto out_vid_del;
++		err = vlan_mvrp_init_applicant(real_dev);
++		if (err < 0)
++			goto out_uninit_gvrp;
+ 	}
+ 
+ 	err = vlan_group_prealloc_vid(grp, vlan_id);
+ 	if (err < 0)
+-		goto out_uninit_applicant;
++		goto out_uninit_mvrp;
+ 
+ 	err = netdev_upper_dev_link(real_dev, dev);
+ 	if (err)
+-		goto out_uninit_applicant;
++		goto out_uninit_mvrp;
+ 
+ 	err = register_netdevice(dev);
+ 	if (err < 0)
+@@ -181,7 +188,10 @@ int register_vlan_dev(struct net_device *dev)
+ 
+ out_upper_dev_unlink:
+ 	netdev_upper_dev_unlink(real_dev, dev);
+-out_uninit_applicant:
++out_uninit_mvrp:
++	if (grp->nr_vlan_devs == 0)
++		vlan_mvrp_uninit_applicant(real_dev);
++out_uninit_gvrp:
+ 	if (grp->nr_vlan_devs == 0)
+ 		vlan_gvrp_uninit_applicant(real_dev);
+ out_vid_del:
+@@ -655,13 +665,19 @@ static int __init vlan_proto_init(void)
+ 	if (err < 0)
+ 		goto err3;
+ 
+-	err = vlan_netlink_init();
++	err = vlan_mvrp_init();
+ 	if (err < 0)
+ 		goto err4;
+ 
++	err = vlan_netlink_init();
++	if (err < 0)
++		goto err5;
++
+ 	vlan_ioctl_set(vlan_ioctl_handler);
+ 	return 0;
+ 
++err5:
++	vlan_mvrp_uninit();
+ err4:
+ 	vlan_gvrp_uninit();
+ err3:
+@@ -682,6 +698,7 @@ static void __exit vlan_cleanup_module(void)
+ 	unregister_pernet_subsys(&vlan_net_ops);
+ 	rcu_barrier(); /* Wait for completion of call_rcu()'s */
+ 
++	vlan_mvrp_uninit();
+ 	vlan_gvrp_uninit();
+ }
+ 
+diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
+index a4886d94c40c..670f1e8cfc0f 100644
+--- a/net/8021q/vlan.h
++++ b/net/8021q/vlan.h
+@@ -171,6 +171,22 @@ static inline int vlan_gvrp_init(void) { return 0; }
+ static inline void vlan_gvrp_uninit(void) {}
+ #endif
+ 
++#ifdef CONFIG_VLAN_8021Q_MVRP
++extern int vlan_mvrp_request_join(const struct net_device *dev);
++extern void vlan_mvrp_request_leave(const struct net_device *dev);
++extern int vlan_mvrp_init_applicant(struct net_device *dev);
++extern void vlan_mvrp_uninit_applicant(struct net_device *dev);
++extern int vlan_mvrp_init(void);
++extern void vlan_mvrp_uninit(void);
++#else
++static inline int vlan_mvrp_request_join(const struct net_device *dev) { return 0; }
++static inline void vlan_mvrp_request_leave(const struct net_device *dev) {}
++static inline int vlan_mvrp_init_applicant(struct net_device *dev) { return 0; }
++static inline void vlan_mvrp_uninit_applicant(struct net_device *dev) {}
++static inline int vlan_mvrp_init(void) { return 0; }
++static inline void vlan_mvrp_uninit(void) {}
++#endif
++
+ extern const char vlan_fullname[];
+ extern const char vlan_version[];
+ extern int vlan_netlink_init(void);
+diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
+index 09f9108d4688..34df5b3c9b75 100644
+--- a/net/8021q/vlan_dev.c
++++ b/net/8021q/vlan_dev.c
+@@ -261,7 +261,7 @@ int vlan_dev_change_flags(const struct net_device *dev, u32 flags, u32 mask)
+ 	u32 old_flags = vlan->flags;
+ 
+ 	if (mask & ~(VLAN_FLAG_REORDER_HDR | VLAN_FLAG_GVRP |
+-		     VLAN_FLAG_LOOSE_BINDING))
++		     VLAN_FLAG_LOOSE_BINDING | VLAN_FLAG_MVRP))
+ 		return -EINVAL;
+ 
+ 	vlan->flags = (old_flags & ~mask) | (flags & mask);
+@@ -272,6 +272,13 @@ int vlan_dev_change_flags(const struct net_device *dev, u32 flags, u32 mask)
+ 		else
+ 			vlan_gvrp_request_leave(dev);
+ 	}
++
++	if (netif_running(dev) && (vlan->flags ^ old_flags) & VLAN_FLAG_MVRP) {
++		if (vlan->flags & VLAN_FLAG_MVRP)
++			vlan_mvrp_request_join(dev);
++		else
++			vlan_mvrp_request_leave(dev);
++	}
+ 	return 0;
+ }
+ 
+@@ -312,6 +319,9 @@ static int vlan_dev_open(struct net_device *dev)
+ 	if (vlan->flags & VLAN_FLAG_GVRP)
+ 		vlan_gvrp_request_join(dev);
+ 
++	if (vlan->flags & VLAN_FLAG_MVRP)
++		vlan_mvrp_request_join(dev);
++
+ 	if (netif_carrier_ok(real_dev))
+ 		netif_carrier_on(dev);
+ 	return 0;
+diff --git a/net/8021q/vlan_mvrp.c b/net/8021q/vlan_mvrp.c
+new file mode 100644
+index 000000000000..d9ec1d5964aa
+--- /dev/null
++++ b/net/8021q/vlan_mvrp.c
+@@ -0,0 +1,72 @@
++/*
++ *	IEEE 802.1Q Multiple VLAN Registration Protocol (MVRP)
++ *
++ *	Copyright (c) 2012 Massachusetts Institute of Technology
++ *
++ *	Adapted from code in net/8021q/vlan_gvrp.c
++ *	Copyright (c) 2008 Patrick McHardy 
++ *
++ *	This program is free software; you can redistribute it and/or
++ *	modify it under the terms of the GNU General Public License
++ *	version 2 as published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++#include 
++#include "vlan.h"
++
++#define MRP_MVRP_ADDRESS	{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x21 }
++
++enum mvrp_attributes {
++	MVRP_ATTR_INVALID,
++	MVRP_ATTR_VID,
++	__MVRP_ATTR_MAX
++};
++#define MVRP_ATTR_MAX	(__MVRP_ATTR_MAX - 1)
++
++static struct mrp_application vlan_mrp_app __read_mostly = {
++	.type		= MRP_APPLICATION_MVRP,
++	.maxattr	= MVRP_ATTR_MAX,
++	.pkttype.type	= htons(ETH_P_MVRP),
++	.group_address	= MRP_MVRP_ADDRESS,
++	.version	= 0,
++};
++
++int vlan_mvrp_request_join(const struct net_device *dev)
++{
++	const struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
++	__be16 vlan_id = htons(vlan->vlan_id);
++
++	return mrp_request_join(vlan->real_dev, &vlan_mrp_app,
++				&vlan_id, sizeof(vlan_id), MVRP_ATTR_VID);
++}
++
++void vlan_mvrp_request_leave(const struct net_device *dev)
++{
++	const struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
++	__be16 vlan_id = htons(vlan->vlan_id);
++
++	mrp_request_leave(vlan->real_dev, &vlan_mrp_app,
++			  &vlan_id, sizeof(vlan_id), MVRP_ATTR_VID);
++}
++
++int vlan_mvrp_init_applicant(struct net_device *dev)
++{
++	return mrp_init_applicant(dev, &vlan_mrp_app);
++}
++
++void vlan_mvrp_uninit_applicant(struct net_device *dev)
++{
++	mrp_uninit_applicant(dev, &vlan_mrp_app);
++}
++
++int __init vlan_mvrp_init(void)
++{
++	return mrp_register_application(&vlan_mrp_app);
++}
++
++void vlan_mvrp_uninit(void)
++{
++	mrp_unregister_application(&vlan_mrp_app);
++}
+diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c
+index 708c80ea1874..1789658b7cd7 100644
+--- a/net/8021q/vlan_netlink.c
++++ b/net/8021q/vlan_netlink.c
+@@ -62,7 +62,7 @@ static int vlan_validate(struct nlattr *tb[], struct nlattr *data[])
+ 		flags = nla_data(data[IFLA_VLAN_FLAGS]);
+ 		if ((flags->flags & flags->mask) &
+ 		    ~(VLAN_FLAG_REORDER_HDR | VLAN_FLAG_GVRP |
+-		      VLAN_FLAG_LOOSE_BINDING))
++		      VLAN_FLAG_LOOSE_BINDING | VLAN_FLAG_MVRP))
+ 			return -EINVAL;
+ 	}
+ 

commit febf018d22347b5df94066bca05d0c11a84e839d
+Author: David Ward 
+Date:   Fri Feb 8 17:17:06 2013 +0000
+
+    net/802: Implement Multiple Registration Protocol (MRP)
+    
+    Initial implementation of the Multiple Registration Protocol (MRP)
+    from IEEE 802.1Q-2011, based on the existing implementation of the
+    Generic Attribute Registration Protocol (GARP).
+    
+    Signed-off-by: David Ward 
+    Acked-by: Patrick McHardy 
+    Signed-off-by: David S. Miller 
+
+diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
+index ab2774eb49e8..25bd46f52877 100644
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -1290,6 +1290,8 @@ struct net_device {
+ 	};
+ 	/* GARP */
+ 	struct garp_port __rcu	*garp_port;
++	/* MRP */
++	struct mrp_port __rcu	*mrp_port;
+ 
+ 	/* class/net/name entry */
+ 	struct device		dev;
+diff --git a/include/net/mrp.h b/include/net/mrp.h
+new file mode 100644
+index 000000000000..4fbf02aa2ec1
+--- /dev/null
++++ b/include/net/mrp.h
+@@ -0,0 +1,143 @@
++#ifndef _NET_MRP_H
++#define _NET_MRP_H
++
++#define MRP_END_MARK		0x0
++
++struct mrp_pdu_hdr {
++	u8	version;
++};
++
++struct mrp_msg_hdr {
++	u8	attrtype;
++	u8	attrlen;
++};
++
++struct mrp_vecattr_hdr {
++	__be16	lenflags;
++	unsigned char	firstattrvalue[];
++#define MRP_VECATTR_HDR_LEN_MASK cpu_to_be16(0x1FFF)
++#define MRP_VECATTR_HDR_FLAG_LA cpu_to_be16(0x2000)
++};
++
++enum mrp_vecattr_event {
++	MRP_VECATTR_EVENT_NEW,
++	MRP_VECATTR_EVENT_JOIN_IN,
++	MRP_VECATTR_EVENT_IN,
++	MRP_VECATTR_EVENT_JOIN_MT,
++	MRP_VECATTR_EVENT_MT,
++	MRP_VECATTR_EVENT_LV,
++	__MRP_VECATTR_EVENT_MAX
++};
++
++struct mrp_skb_cb {
++	struct mrp_msg_hdr	*mh;
++	struct mrp_vecattr_hdr	*vah;
++	unsigned char		attrvalue[];
++};
++
++static inline struct mrp_skb_cb *mrp_cb(struct sk_buff *skb)
++{
++	BUILD_BUG_ON(sizeof(struct mrp_skb_cb) >
++		     FIELD_SIZEOF(struct sk_buff, cb));
++	return (struct mrp_skb_cb *)skb->cb;
++}
++
++enum mrp_applicant_state {
++	MRP_APPLICANT_INVALID,
++	MRP_APPLICANT_VO,
++	MRP_APPLICANT_VP,
++	MRP_APPLICANT_VN,
++	MRP_APPLICANT_AN,
++	MRP_APPLICANT_AA,
++	MRP_APPLICANT_QA,
++	MRP_APPLICANT_LA,
++	MRP_APPLICANT_AO,
++	MRP_APPLICANT_QO,
++	MRP_APPLICANT_AP,
++	MRP_APPLICANT_QP,
++	__MRP_APPLICANT_MAX
++};
++#define MRP_APPLICANT_MAX	(__MRP_APPLICANT_MAX - 1)
++
++enum mrp_event {
++	MRP_EVENT_NEW,
++	MRP_EVENT_JOIN,
++	MRP_EVENT_LV,
++	MRP_EVENT_TX,
++	MRP_EVENT_R_NEW,
++	MRP_EVENT_R_JOIN_IN,
++	MRP_EVENT_R_IN,
++	MRP_EVENT_R_JOIN_MT,
++	MRP_EVENT_R_MT,
++	MRP_EVENT_R_LV,
++	MRP_EVENT_R_LA,
++	MRP_EVENT_REDECLARE,
++	MRP_EVENT_PERIODIC,
++	__MRP_EVENT_MAX
++};
++#define MRP_EVENT_MAX		(__MRP_EVENT_MAX - 1)
++
++enum mrp_tx_action {
++	MRP_TX_ACTION_NONE,
++	MRP_TX_ACTION_S_NEW,
++	MRP_TX_ACTION_S_JOIN_IN,
++	MRP_TX_ACTION_S_JOIN_IN_OPTIONAL,
++	MRP_TX_ACTION_S_IN_OPTIONAL,
++	MRP_TX_ACTION_S_LV,
++};
++
++struct mrp_attr {
++	struct rb_node			node;
++	enum mrp_applicant_state	state;
++	u8				type;
++	u8				len;
++	unsigned char			value[];
++};
++
++enum mrp_applications {
++	MRP_APPLICATION_MVRP,
++	__MRP_APPLICATION_MAX
++};
++#define MRP_APPLICATION_MAX	(__MRP_APPLICATION_MAX - 1)
++
++struct mrp_application {
++	enum mrp_applications	type;
++	unsigned int		maxattr;
++	struct packet_type	pkttype;
++	unsigned char		group_address[ETH_ALEN];
++	u8			version;
++};
++
++struct mrp_applicant {
++	struct mrp_application	*app;
++	struct net_device	*dev;
++	struct timer_list	join_timer;
++
++	spinlock_t		lock;
++	struct sk_buff_head	queue;
++	struct sk_buff		*pdu;
++	struct rb_root		mad;
++	struct rcu_head		rcu;
++};
++
++struct mrp_port {
++	struct mrp_applicant __rcu	*applicants[MRP_APPLICATION_MAX + 1];
++	struct rcu_head			rcu;
++};
++
++extern int	mrp_register_application(struct mrp_application *app);
++extern void	mrp_unregister_application(struct mrp_application *app);
++
++extern int	mrp_init_applicant(struct net_device *dev,
++				    struct mrp_application *app);
++extern void	mrp_uninit_applicant(struct net_device *dev,
++				      struct mrp_application *app);
++
++extern int	mrp_request_join(const struct net_device *dev,
++				  const struct mrp_application *app,
++				  const void *value, u8 len, u8 type);
++extern void	mrp_request_leave(const struct net_device *dev,
++				   const struct mrp_application *app,
++				   const void *value, u8 len, u8 type);
++
++#endif /* _NET_MRP_H */
+diff --git a/net/802/Kconfig b/net/802/Kconfig
+index be33d27c8e69..80d4bf78905d 100644
+--- a/net/802/Kconfig
++++ b/net/802/Kconfig
+@@ -5,3 +5,6 @@ config STP
+ config GARP
+ 	tristate
+ 	select STP
++
++config MRP
++	tristate
+diff --git a/net/802/Makefile b/net/802/Makefile
+index a30d6e385aed..37e654d6615e 100644
+--- a/net/802/Makefile
++++ b/net/802/Makefile
+@@ -11,3 +11,4 @@ obj-$(CONFIG_IPX)	+= p8022.o psnap.o p8023.o
+ obj-$(CONFIG_ATALK)	+= p8022.o psnap.o
+ obj-$(CONFIG_STP)	+= stp.o
+ obj-$(CONFIG_GARP)	+= garp.o
++obj-$(CONFIG_MRP)	+= mrp.o
+diff --git a/net/802/mrp.c b/net/802/mrp.c
+new file mode 100644
+index 000000000000..47a9e14c8ba7
+--- /dev/null
++++ b/net/802/mrp.c
+@@ -0,0 +1,895 @@
++/*
++ *	IEEE 802.1Q Multiple Registration Protocol (MRP)
++ *
++ *	Copyright (c) 2012 Massachusetts Institute of Technology
++ *
++ *	Adapted from code in net/802/garp.c
++ *	Copyright (c) 2008 Patrick McHardy 
++ *
++ *	This program is free software; you can redistribute it and/or
++ *	modify it under the terms of the GNU General Public License
++ *	version 2 as published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++static unsigned int mrp_join_time __read_mostly = 200;
++module_param(mrp_join_time, uint, 0644);
++MODULE_PARM_DESC(mrp_join_time, "Join time in ms (default 200ms)");
++MODULE_LICENSE("GPL");
++
++static const u8
++mrp_applicant_state_table[MRP_APPLICANT_MAX + 1][MRP_EVENT_MAX + 1] = {
++	[MRP_APPLICANT_VO] = {
++		[MRP_EVENT_NEW]		= MRP_APPLICANT_VN,
++		[MRP_EVENT_JOIN]	= MRP_APPLICANT_VP,
++		[MRP_EVENT_LV]		= MRP_APPLICANT_VO,
++		[MRP_EVENT_TX]		= MRP_APPLICANT_VO,
++		[MRP_EVENT_R_NEW]	= MRP_APPLICANT_VO,
++		[MRP_EVENT_R_JOIN_IN]	= MRP_APPLICANT_AO,
++		[MRP_EVENT_R_IN]	= MRP_APPLICANT_VO,
++		[MRP_EVENT_R_JOIN_MT]	= MRP_APPLICANT_VO,
++		[MRP_EVENT_R_MT]	= MRP_APPLICANT_VO,
++		[MRP_EVENT_R_LV]	= MRP_APPLICANT_VO,
++		[MRP_EVENT_R_LA]	= MRP_APPLICANT_VO,
++		[MRP_EVENT_REDECLARE]	= MRP_APPLICANT_VO,
++		[MRP_EVENT_PERIODIC]	= MRP_APPLICANT_VO,
++	},
++	[MRP_APPLICANT_VP] = {
++		[MRP_EVENT_NEW]		= MRP_APPLICANT_VN,
++		[MRP_EVENT_JOIN]	= MRP_APPLICANT_VP,
++		[MRP_EVENT_LV]		= MRP_APPLICANT_VO,
++		[MRP_EVENT_TX]		= MRP_APPLICANT_AA,
++		[MRP_EVENT_R_NEW]	= MRP_APPLICANT_VP,
++		[MRP_EVENT_R_JOIN_IN]	= MRP_APPLICANT_AP,
++		[MRP_EVENT_R_IN]	= MRP_APPLICANT_VP,
++		[MRP_EVENT_R_JOIN_MT]	= MRP_APPLICANT_VP,
++		[MRP_EVENT_R_MT]	= MRP_APPLICANT_VP,
++		[MRP_EVENT_R_LV]	= MRP_APPLICANT_VP,
++		[MRP_EVENT_R_LA]	= MRP_APPLICANT_VP,
++		[MRP_EVENT_REDECLARE]	= MRP_APPLICANT_VP,
++		[MRP_EVENT_PERIODIC]	= MRP_APPLICANT_VP,
++	},
++	[MRP_APPLICANT_VN] = {
++		[MRP_EVENT_NEW]		= MRP_APPLICANT_VN,
++		[MRP_EVENT_JOIN]	= MRP_APPLICANT_VN,
++		[MRP_EVENT_LV]		= MRP_APPLICANT_LA,
++		[MRP_EVENT_TX]		= MRP_APPLICANT_AN,
++		[MRP_EVENT_R_NEW]	= MRP_APPLICANT_VN,
++		[MRP_EVENT_R_JOIN_IN]	= MRP_APPLICANT_VN,
++		[MRP_EVENT_R_IN]	= MRP_APPLICANT_VN,
++		[MRP_EVENT_R_JOIN_MT]	= MRP_APPLICANT_VN,
++		[MRP_EVENT_R_MT]	= MRP_APPLICANT_VN,
++		[MRP_EVENT_R_LV]	= MRP_APPLICANT_VN,
++		[MRP_EVENT_R_LA]	= MRP_APPLICANT_VN,
++		[MRP_EVENT_REDECLARE]	= MRP_APPLICANT_VN,
++		[MRP_EVENT_PERIODIC]	= MRP_APPLICANT_VN,
++	},
++	[MRP_APPLICANT_AN] = {
++		[MRP_EVENT_NEW]		= MRP_APPLICANT_AN,
++		[MRP_EVENT_JOIN]	= MRP_APPLICANT_AN,
++		[MRP_EVENT_LV]		= MRP_APPLICANT_LA,
++		[MRP_EVENT_TX]		= MRP_APPLICANT_QA,
++		[MRP_EVENT_R_NEW]	= MRP_APPLICANT_AN,
++		[MRP_EVENT_R_JOIN_IN]	= MRP_APPLICANT_AN,
++		[MRP_EVENT_R_IN]	= MRP_APPLICANT_AN,
++		[MRP_EVENT_R_JOIN_MT]	= MRP_APPLICANT_AN,
++		[MRP_EVENT_R_MT]	= MRP_APPLICANT_AN,
++		[MRP_EVENT_R_LV]	= MRP_APPLICANT_VN,
++		[MRP_EVENT_R_LA]	= MRP_APPLICANT_VN,
++		[MRP_EVENT_REDECLARE]	= MRP_APPLICANT_VN,
++		[MRP_EVENT_PERIODIC]	= MRP_APPLICANT_AN,
++	},
++	[MRP_APPLICANT_AA] = {
++		[MRP_EVENT_NEW]		= MRP_APPLICANT_VN,
++		[MRP_EVENT_JOIN]	= MRP_APPLICANT_AA,
++		[MRP_EVENT_LV]		= MRP_APPLICANT_LA,
++		[MRP_EVENT_TX]		= MRP_APPLICANT_QA,
++		[MRP_EVENT_R_NEW]	= MRP_APPLICANT_AA,
++		[MRP_EVENT_R_JOIN_IN]	= MRP_APPLICANT_QA,
++		[MRP_EVENT_R_IN]	= MRP_APPLICANT_AA,
++		[MRP_EVENT_R_JOIN_MT]	= MRP_APPLICANT_AA,
++		[MRP_EVENT_R_MT]	= MRP_APPLICANT_AA,
++		[MRP_EVENT_R_LV]	= MRP_APPLICANT_VP,
++		[MRP_EVENT_R_LA]	= MRP_APPLICANT_VP,
++		[MRP_EVENT_REDECLARE]	= MRP_APPLICANT_VP,
++		[MRP_EVENT_PERIODIC]	= MRP_APPLICANT_AA,
++	},
++	[MRP_APPLICANT_QA] = {
++		[MRP_EVENT_NEW]		= MRP_APPLICANT_VN,
++		[MRP_EVENT_JOIN]	= MRP_APPLICANT_QA,
++		[MRP_EVENT_LV]		= MRP_APPLICANT_LA,
++		[MRP_EVENT_TX]		= MRP_APPLICANT_QA,
++		[MRP_EVENT_R_NEW]	= MRP_APPLICANT_QA,
++		[MRP_EVENT_R_JOIN_IN]	= MRP_APPLICANT_QA,
++		[MRP_EVENT_R_IN]	= MRP_APPLICANT_QA,
++		[MRP_EVENT_R_JOIN_MT]	= MRP_APPLICANT_AA,
++		[MRP_EVENT_R_MT]	= MRP_APPLICANT_AA,
++		[MRP_EVENT_R_LV]	= MRP_APPLICANT_VP,
++		[MRP_EVENT_R_LA]	= MRP_APPLICANT_VP,
++		[MRP_EVENT_REDECLARE]	= MRP_APPLICANT_VP,
++		[MRP_EVENT_PERIODIC]	= MRP_APPLICANT_AA,
++	},
++	[MRP_APPLICANT_LA] = {
++		[MRP_EVENT_NEW]		= MRP_APPLICANT_VN,
++		[MRP_EVENT_JOIN]	= MRP_APPLICANT_AA,
++		[MRP_EVENT_LV]		= MRP_APPLICANT_LA,
++		[MRP_EVENT_TX]		= MRP_APPLICANT_VO,
++		[MRP_EVENT_R_NEW]	= MRP_APPLICANT_LA,
++		[MRP_EVENT_R_JOIN_IN]	= MRP_APPLICANT_LA,
++		[MRP_EVENT_R_IN]	= MRP_APPLICANT_LA,
++		[MRP_EVENT_R_JOIN_MT]	= MRP_APPLICANT_LA,
++		[MRP_EVENT_R_MT]	= MRP_APPLICANT_LA,
++		[MRP_EVENT_R_LV]	= MRP_APPLICANT_LA,
++		[MRP_EVENT_R_LA]	= MRP_APPLICANT_LA,
++		[MRP_EVENT_REDECLARE]	= MRP_APPLICANT_LA,
++		[MRP_EVENT_PERIODIC]	= MRP_APPLICANT_LA,
++	},
++	[MRP_APPLICANT_AO] = {
++		[MRP_EVENT_NEW]		= MRP_APPLICANT_VN,
++		[MRP_EVENT_JOIN]	= MRP_APPLICANT_AP,
++		[MRP_EVENT_LV]		= MRP_APPLICANT_AO,
++		[MRP_EVENT_TX]		= MRP_APPLICANT_AO,
++		[MRP_EVENT_R_NEW]	= MRP_APPLICANT_AO,
++		[MRP_EVENT_R_JOIN_IN]	= MRP_APPLICANT_QO,
++		[MRP_EVENT_R_IN]	= MRP_APPLICANT_AO,
++		[MRP_EVENT_R_JOIN_MT]	= MRP_APPLICANT_AO,
++		[MRP_EVENT_R_MT]	= MRP_APPLICANT_AO,
++		[MRP_EVENT_R_LV]	= MRP_APPLICANT_VO,
++		[MRP_EVENT_R_LA]	= MRP_APPLICANT_VO,
++		[MRP_EVENT_REDECLARE]	= MRP_APPLICANT_VO,
++		[MRP_EVENT_PERIODIC]	= MRP_APPLICANT_AO,
++	},
++	[MRP_APPLICANT_QO] = {
++		[MRP_EVENT_NEW]		= MRP_APPLICANT_VN,
++		[MRP_EVENT_JOIN]	= MRP_APPLICANT_QP,
++		[MRP_EVENT_LV]		= MRP_APPLICANT_QO,
++		[MRP_EVENT_TX]		= MRP_APPLICANT_QO,
++		[MRP_EVENT_R_NEW]	= MRP_APPLICANT_QO,
++		[MRP_EVENT_R_JOIN_IN]	= MRP_APPLICANT_QO,
++		[MRP_EVENT_R_IN]	= MRP_APPLICANT_QO,
++		[MRP_EVENT_R_JOIN_MT]	= MRP_APPLICANT_AO,
++		[MRP_EVENT_R_MT]	= MRP_APPLICANT_AO,
++		[MRP_EVENT_R_LV]	= MRP_APPLICANT_VO,
++		[MRP_EVENT_R_LA]	= MRP_APPLICANT_VO,
++		[MRP_EVENT_REDECLARE]	= MRP_APPLICANT_VO,
++		[MRP_EVENT_PERIODIC]	= MRP_APPLICANT_QO,
++	},
++	[MRP_APPLICANT_AP] = {
++		[MRP_EVENT_NEW]		= MRP_APPLICANT_VN,
++		[MRP_EVENT_JOIN]	= MRP_APPLICANT_AP,
++		[MRP_EVENT_LV]		= MRP_APPLICANT_AO,
++		[MRP_EVENT_TX]		= MRP_APPLICANT_QA,
++		[MRP_EVENT_R_NEW]	= MRP_APPLICANT_AP,
++		[MRP_EVENT_R_JOIN_IN]	= MRP_APPLICANT_QP,
++		[MRP_EVENT_R_IN]	= MRP_APPLICANT_AP,
++		[MRP_EVENT_R_JOIN_MT]	= MRP_APPLICANT_AP,
++		[MRP_EVENT_R_MT]	= MRP_APPLICANT_AP,
++		[MRP_EVENT_R_LV]	= MRP_APPLICANT_VP,
++		[MRP_EVENT_R_LA]	= MRP_APPLICANT_VP,
++		[MRP_EVENT_REDECLARE]	= MRP_APPLICANT_VP,
++		[MRP_EVENT_PERIODIC]	= MRP_APPLICANT_AP,
++	},
++	[MRP_APPLICANT_QP] = {
++		[MRP_EVENT_NEW]		= MRP_APPLICANT_VN,
++		[MRP_EVENT_JOIN]	= MRP_APPLICANT_QP,
++		[MRP_EVENT_LV]		= MRP_APPLICANT_QO,
++		[MRP_EVENT_TX]		= MRP_APPLICANT_QP,
++		[MRP_EVENT_R_NEW]	= MRP_APPLICANT_QP,
++		[MRP_EVENT_R_JOIN_IN]	= MRP_APPLICANT_QP,
++		[MRP_EVENT_R_IN]	= MRP_APPLICANT_QP,
++		[MRP_EVENT_R_JOIN_MT]	= MRP_APPLICANT_AP,
++		[MRP_EVENT_R_MT]	= MRP_APPLICANT_AP,
++		[MRP_EVENT_R_LV]	= MRP_APPLICANT_VP,
++		[MRP_EVENT_R_LA]	= MRP_APPLICANT_VP,
++		[MRP_EVENT_REDECLARE]	= MRP_APPLICANT_VP,
++		[MRP_EVENT_PERIODIC]	= MRP_APPLICANT_AP,
++	},
++};
++
++static const u8
++mrp_tx_action_table[MRP_APPLICANT_MAX + 1] = {
++	[MRP_APPLICANT_VO] = MRP_TX_ACTION_S_IN_OPTIONAL,
++	[MRP_APPLICANT_VP] = MRP_TX_ACTION_S_JOIN_IN,
++	[MRP_APPLICANT_VN] = MRP_TX_ACTION_S_NEW,
++	[MRP_APPLICANT_AN] = MRP_TX_ACTION_S_NEW,
++	[MRP_APPLICANT_AA] = MRP_TX_ACTION_S_JOIN_IN,
++	[MRP_APPLICANT_QA] = MRP_TX_ACTION_S_JOIN_IN_OPTIONAL,
++	[MRP_APPLICANT_LA] = MRP_TX_ACTION_S_LV,
++	[MRP_APPLICANT_AO] = MRP_TX_ACTION_S_IN_OPTIONAL,
++	[MRP_APPLICANT_QO] = MRP_TX_ACTION_S_IN_OPTIONAL,
++	[MRP_APPLICANT_AP] = MRP_TX_ACTION_S_JOIN_IN,
++	[MRP_APPLICANT_QP] = MRP_TX_ACTION_S_IN_OPTIONAL,
++};
++
++static void mrp_attrvalue_inc(void *value, u8 len)
++{
++	u8 *v = (u8 *)value;
++
++	/* Add 1 to the last byte. If it becomes zero,
++	 * go to the previous byte and repeat.
++	 */
++	while (len > 0 && !++v[--len])
++		;
++}
++
++static int mrp_attr_cmp(const struct mrp_attr *attr,
++			 const void *value, u8 len, u8 type)
++{
++	if (attr->type != type)
++		return attr->type - type;
++	if (attr->len != len)
++		return attr->len - len;
++	return memcmp(attr->value, value, len);
++}
++
++static struct mrp_attr *mrp_attr_lookup(const struct mrp_applicant *app,
++					const void *value, u8 len, u8 type)
++{
++	struct rb_node *parent = app->mad.rb_node;
++	struct mrp_attr *attr;
++	int d;
++
++	while (parent) {
++		attr = rb_entry(parent, struct mrp_attr, node);
++		d = mrp_attr_cmp(attr, value, len, type);
++		if (d > 0)
++			parent = parent->rb_left;
++		else if (d < 0)
++			parent = parent->rb_right;
++		else
++			return attr;
++	}
++	return NULL;
++}
++
++static struct mrp_attr *mrp_attr_create(struct mrp_applicant *app,
++					const void *value, u8 len, u8 type)
++{
++	struct rb_node *parent = NULL, **p = &app->mad.rb_node;
++	struct mrp_attr *attr;
++	int d;
++
++	while (*p) {
++		parent = *p;
++		attr = rb_entry(parent, struct mrp_attr, node);
++		d = mrp_attr_cmp(attr, value, len, type);
++		if (d > 0)
++			p = &parent->rb_left;
++		else if (d < 0)
++			p = &parent->rb_right;
++		else {
++			/* The attribute already exists; re-use it. */
++			return attr;
++		}
++	}
++	attr = kmalloc(sizeof(*attr) + len, GFP_ATOMIC);
++	if (!attr)
++		return attr;
++	attr->state = MRP_APPLICANT_VO;
++	attr->type  = type;
++	attr->len   = len;
++	memcpy(attr->value, value, len);
++
++	rb_link_node(&attr->node, parent, p);
++	rb_insert_color(&attr->node, &app->mad);
++	return attr;
++}
++
++static void mrp_attr_destroy(struct mrp_applicant *app, struct mrp_attr *attr)
++{
++	rb_erase(&attr->node, &app->mad);
++	kfree(attr);
++}
++
++static int mrp_pdu_init(struct mrp_applicant *app)
++{
++	struct sk_buff *skb;
++	struct mrp_pdu_hdr *ph;
++
++	skb = alloc_skb(app->dev->mtu + LL_RESERVED_SPACE(app->dev),
++			GFP_ATOMIC);
++	if (!skb)
++		return -ENOMEM;
++
++	skb->dev = app->dev;
++	skb->protocol = app->app->pkttype.type;
++	skb_reserve(skb, LL_RESERVED_SPACE(app->dev));
++	skb_reset_network_header(skb);
++	skb_reset_transport_header(skb);
++
++	ph = (struct mrp_pdu_hdr *)__skb_put(skb, sizeof(*ph));
++	ph->version = app->app->version;
++
++	app->pdu = skb;
++	return 0;
++}
++
++static int mrp_pdu_append_end_mark(struct mrp_applicant *app)
++{
++	__be16 *endmark;
++
++	if (skb_tailroom(app->pdu) < sizeof(*endmark))
++		return -1;
++	endmark = (__be16 *)__skb_put(app->pdu, sizeof(*endmark));
++	put_unaligned(MRP_END_MARK, endmark);
++	return 0;
++}
++
++static void mrp_pdu_queue(struct mrp_applicant *app)
++{
++	if (!app->pdu)
++		return;
++
++	if (mrp_cb(app->pdu)->mh)
++		mrp_pdu_append_end_mark(app);
++	mrp_pdu_append_end_mark(app);
++
++	dev_hard_header(app->pdu, app->dev, ntohs(app->app->pkttype.type),
++			app->app->group_address, app->dev->dev_addr,
++			app->pdu->len);
++
++	skb_queue_tail(&app->queue, app->pdu);
++	app->pdu = NULL;
++}
++
++static void mrp_queue_xmit(struct mrp_applicant *app)
++{
++	struct sk_buff *skb;
++
++	while ((skb = skb_dequeue(&app->queue)))
++		dev_queue_xmit(skb);
++}
++
++static int mrp_pdu_append_msg_hdr(struct mrp_applicant *app,
++				  u8 attrtype, u8 attrlen)
++{
++	struct mrp_msg_hdr *mh;
++
++	if (mrp_cb(app->pdu)->mh) {
++		if (mrp_pdu_append_end_mark(app) < 0)
++			return -1;
++		mrp_cb(app->pdu)->mh = NULL;
++		mrp_cb(app->pdu)->vah = NULL;
++	}
++
++	if (skb_tailroom(app->pdu) < sizeof(*mh))
++		return -1;
++	mh = (struct mrp_msg_hdr *)__skb_put(app->pdu, sizeof(*mh));
++	mh->attrtype = attrtype;
++	mh->attrlen = attrlen;
++	mrp_cb(app->pdu)->mh = mh;
++	return 0;
++}
++
++static int mrp_pdu_append_vecattr_hdr(struct mrp_applicant *app,
++				      const void *firstattrvalue, u8 attrlen)
++{
++	struct mrp_vecattr_hdr *vah;
++
++	if (skb_tailroom(app->pdu) < sizeof(*vah) + attrlen)
++		return -1;
++	vah = (struct mrp_vecattr_hdr *)__skb_put(app->pdu,
++						  sizeof(*vah) + attrlen);
++	put_unaligned(0, &vah->lenflags);
++	memcpy(vah->firstattrvalue, firstattrvalue, attrlen);
++	mrp_cb(app->pdu)->vah = vah;
++	memcpy(mrp_cb(app->pdu)->attrvalue, firstattrvalue, attrlen);
++	return 0;
++}
++
++static int mrp_pdu_append_vecattr_event(struct mrp_applicant *app,
++					const struct mrp_attr *attr,
++					enum mrp_vecattr_event vaevent)
++{
++	u16 len, pos;
++	u8 *vaevents;
++	int err;
++again:
++	if (!app->pdu) {
++		err = mrp_pdu_init(app);
++		if (err < 0)
++			return err;
++	}
++
++	/* If there is no Message header in the PDU, or the Message header is
++	 * for a different attribute type, add an EndMark (if necessary) and a
++	 * new Message header to the PDU.
++	 */
++	if (!mrp_cb(app->pdu)->mh ||
++	    mrp_cb(app->pdu)->mh->attrtype != attr->type ||
++	    mrp_cb(app->pdu)->mh->attrlen != attr->len) {
++		if (mrp_pdu_append_msg_hdr(app, attr->type, attr->len) < 0)
++			goto queue;
++	}
++
++	/* If there is no VectorAttribute header for this Message in the PDU,
++	 * or this attribute's value does not sequentially follow the previous
++	 * attribute's value, add a new VectorAttribute header to the PDU.
++	 */
++	if (!mrp_cb(app->pdu)->vah ||
++	    memcmp(mrp_cb(app->pdu)->attrvalue, attr->value, attr->len)) {
++		if (mrp_pdu_append_vecattr_hdr(app, attr->value, attr->len) < 0)
++			goto queue;
++	}
++
++	len = be16_to_cpu(get_unaligned(&mrp_cb(app->pdu)->vah->lenflags));
++	pos = len % 3;
++
++	/* Events are packed into Vectors in the PDU, three to a byte. Add a
++	 * byte to the end of the Vector if necessary.
++	 */
++	if (!pos) {
++		if (skb_tailroom(app->pdu) < sizeof(u8))
++			goto queue;
++		vaevents = (u8 *)__skb_put(app->pdu, sizeof(u8));
++	} else {
++		vaevents = (u8 *)(skb_tail_pointer(app->pdu) - sizeof(u8));
++	}
++
++	switch (pos) {
++	case 0:
++		*vaevents = vaevent * (__MRP_VECATTR_EVENT_MAX *
++				       __MRP_VECATTR_EVENT_MAX);
++		break;
++	case 1:
++		*vaevents += vaevent * __MRP_VECATTR_EVENT_MAX;
++		break;
++	case 2:
++		*vaevents += vaevent;
++		break;
++	default:
++		WARN_ON(1);
++	}
++
++	/* Increment the length of the VectorAttribute in the PDU, as well as
++	 * the value of the next attribute that would continue its Vector.
++	 */
++	put_unaligned(cpu_to_be16(++len), &mrp_cb(app->pdu)->vah->lenflags);
++	mrp_attrvalue_inc(mrp_cb(app->pdu)->attrvalue, attr->len);
++
++	return 0;
++
++queue:
++	mrp_pdu_queue(app);
++	goto again;
++}
++
++static void mrp_attr_event(struct mrp_applicant *app,
++			   struct mrp_attr *attr, enum mrp_event event)
++{
++	enum mrp_applicant_state state;
++
++	state = mrp_applicant_state_table[attr->state][event];
++	if (state == MRP_APPLICANT_INVALID) {
++		WARN_ON(1);
++		return;
++	}
++
++	if (event == MRP_EVENT_TX) {
++		/* When appending the attribute fails, don't update its state
++		 * in order to retry at the next TX event.
++		 */
++
++		switch (mrp_tx_action_table[attr->state]) {
++		case MRP_TX_ACTION_NONE:
++		case MRP_TX_ACTION_S_JOIN_IN_OPTIONAL:
++		case MRP_TX_ACTION_S_IN_OPTIONAL:
++			break;
++		case MRP_TX_ACTION_S_NEW:
++			if (mrp_pdu_append_vecattr_event(
++				    app, attr, MRP_VECATTR_EVENT_NEW) < 0)
++				return;
++			break;
++		case MRP_TX_ACTION_S_JOIN_IN:
++			if (mrp_pdu_append_vecattr_event(
++				    app, attr, MRP_VECATTR_EVENT_JOIN_IN) < 0)
++				return;
++			break;
++		case MRP_TX_ACTION_S_LV:
++			if (mrp_pdu_append_vecattr_event(
++				    app, attr, MRP_VECATTR_EVENT_LV) < 0)
++				return;
++			/* As a pure applicant, sending a leave message
++			 * implies that the attribute was unregistered and
++			 * can be destroyed.
++			 */
++			mrp_attr_destroy(app, attr);
++			return;
++		default:
++			WARN_ON(1);
++		}
++	}
++
++	attr->state = state;
++}
++
++int mrp_request_join(const struct net_device *dev,
++		     const struct mrp_application *appl,
++		     const void *value, u8 len, u8 type)
++{
++	struct mrp_port *port = rtnl_dereference(dev->mrp_port);
++	struct mrp_applicant *app = rtnl_dereference(
++		port->applicants[appl->type]);
++	struct mrp_attr *attr;
++
++	if (sizeof(struct mrp_skb_cb) + len >
++	    FIELD_SIZEOF(struct sk_buff, cb))
++		return -ENOMEM;
++
++	spin_lock_bh(&app->lock);
++	attr = mrp_attr_create(app, value, len, type);
++	if (!attr) {
++		spin_unlock_bh(&app->lock);
++		return -ENOMEM;
++	}
++	mrp_attr_event(app, attr, MRP_EVENT_JOIN);
++	spin_unlock_bh(&app->lock);
++	return 0;
++}
++EXPORT_SYMBOL_GPL(mrp_request_join);
++
++void mrp_request_leave(const struct net_device *dev,
++		       const struct mrp_application *appl,
++		       const void *value, u8 len, u8 type)
++{
++	struct mrp_port *port = rtnl_dereference(dev->mrp_port);
++	struct mrp_applicant *app = rtnl_dereference(
++		port->applicants[appl->type]);
++	struct mrp_attr *attr;
++
++	if (sizeof(struct mrp_skb_cb) + len >
++	    FIELD_SIZEOF(struct sk_buff, cb))
++		return;
++
++	spin_lock_bh(&app->lock);
++	attr = mrp_attr_lookup(app, value, len, type);
++	if (!attr) {
++		spin_unlock_bh(&app->lock);
++		return;
++	}
++	mrp_attr_event(app, attr, MRP_EVENT_LV);
++	spin_unlock_bh(&app->lock);
++}
++EXPORT_SYMBOL_GPL(mrp_request_leave);
++
++static void mrp_mad_event(struct mrp_applicant *app, enum mrp_event event)
++{
++	struct rb_node *node, *next;
++	struct mrp_attr *attr;
++
++	for (node = rb_first(&app->mad);
++	     next = node ? rb_next(node) : NULL, node != NULL;
++	     node = next) {
++		attr = rb_entry(node, struct mrp_attr, node);
++		mrp_attr_event(app, attr, event);
++	}
++}
++
++static void mrp_join_timer_arm(struct mrp_applicant *app)
++{
++	unsigned long delay;
++
++	delay = (u64)msecs_to_jiffies(mrp_join_time) * net_random() >> 32;
++	mod_timer(&app->join_timer, jiffies + delay);
++}
++
++static void mrp_join_timer(unsigned long data)
++{
++	struct mrp_applicant *app = (struct mrp_applicant *)data;
++
++	spin_lock(&app->lock);
++	mrp_mad_event(app, MRP_EVENT_TX);
++	mrp_pdu_queue(app);
++	spin_unlock(&app->lock);
++
++	mrp_queue_xmit(app);
++	mrp_join_timer_arm(app);
++}
++
++static int mrp_pdu_parse_end_mark(struct sk_buff *skb, int *offset)
++{
++	__be16 endmark;
++
++	if (skb_copy_bits(skb, *offset, &endmark, sizeof(endmark)) < 0)
++		return -1;
++	if (endmark == MRP_END_MARK) {
++		*offset += sizeof(endmark);
++		return -1;
++	}
++	return 0;
++}
++
++static void mrp_pdu_parse_vecattr_event(struct mrp_applicant *app,
++					struct sk_buff *skb,
++					enum mrp_vecattr_event vaevent)
++{
++	struct mrp_attr *attr;
++	enum mrp_event event;
++
++	attr = mrp_attr_lookup(app, mrp_cb(skb)->attrvalue,
++			       mrp_cb(skb)->mh->attrlen,
++			       mrp_cb(skb)->mh->attrtype);
++	if (attr == NULL)
++		return;
++
++	switch (vaevent) {
++	case MRP_VECATTR_EVENT_NEW:
++		event = MRP_EVENT_R_NEW;
++		break;
++	case MRP_VECATTR_EVENT_JOIN_IN:
++		event = MRP_EVENT_R_JOIN_IN;
++		break;
++	case MRP_VECATTR_EVENT_IN:
++		event = MRP_EVENT_R_IN;
++		break;
++	case MRP_VECATTR_EVENT_JOIN_MT:
++		event = MRP_EVENT_R_JOIN_MT;
++		break;
++	case MRP_VECATTR_EVENT_MT:
++		event = MRP_EVENT_R_MT;
++		break;
++	case MRP_VECATTR_EVENT_LV:
++		event = MRP_EVENT_R_LV;
++		break;
++	default:
++		return;
++	}
++
++	mrp_attr_event(app, attr, event);
++}
++
++static int mrp_pdu_parse_vecattr(struct mrp_applicant *app,
++				 struct sk_buff *skb, int *offset)
++{
++	struct mrp_vecattr_hdr _vah;
++	u16 valen;
++	u8 vaevents, vaevent;
++
++	mrp_cb(skb)->vah = skb_header_pointer(skb, *offset, sizeof(_vah),
++					      &_vah);
++	if (!mrp_cb(skb)->vah)
++		return -1;
++	*offset += sizeof(_vah);
++
++	if (get_unaligned(&mrp_cb(skb)->vah->lenflags) &
++	    MRP_VECATTR_HDR_FLAG_LA)
++		mrp_mad_event(app, MRP_EVENT_R_LA);
++	valen = be16_to_cpu(get_unaligned(&mrp_cb(skb)->vah->lenflags) &
++			    MRP_VECATTR_HDR_LEN_MASK);
++
++	/* The VectorAttribute structure in a PDU carries event information
++	 * about one or more attributes having consecutive values. Only the
++	 * value for the first attribute is contained in the structure. So
++	 * we make a copy of that value, and then increment it each time we
++	 * advance to the next event in its Vector.
++	 */
++	if (sizeof(struct mrp_skb_cb) + mrp_cb(skb)->mh->attrlen >
++	    FIELD_SIZEOF(struct sk_buff, cb))
++		return -1;
++	if (skb_copy_bits(skb, *offset, mrp_cb(skb)->attrvalue,
++			  mrp_cb(skb)->mh->attrlen) < 0)
++		return -1;
++	*offset += mrp_cb(skb)->mh->attrlen;
++
++	/* In a VectorAttribute, the Vector contains events which are packed
++	 * three to a byte. We process one byte of the Vector at a time.
++	 */
++	while (valen > 0) {
++		if (skb_copy_bits(skb, *offset, &vaevents,
++				  sizeof(vaevents)) < 0)
++			return -1;
++		*offset += sizeof(vaevents);
++
++		/* Extract and process the first event. */
++		vaevent = vaevents / (__MRP_VECATTR_EVENT_MAX *
++				      __MRP_VECATTR_EVENT_MAX);
++		if (vaevent >= __MRP_VECATTR_EVENT_MAX) {
++			/* The byte is malformed; stop processing. */
++			return -1;
++		}
++		mrp_pdu_parse_vecattr_event(app, skb, vaevent);
++
++		/* If present, extract and process the second event. */
++		if (!--valen)
++			break;
++		mrp_attrvalue_inc(mrp_cb(skb)->attrvalue,
++				  mrp_cb(skb)->mh->attrlen);
++		vaevents %= (__MRP_VECATTR_EVENT_MAX *
++			     __MRP_VECATTR_EVENT_MAX);
++		vaevent = vaevents / __MRP_VECATTR_EVENT_MAX;
++		mrp_pdu_parse_vecattr_event(app, skb, vaevent);
++
++		/* If present, extract and process the third event. */
++		if (!--valen)
++			break;
++		mrp_attrvalue_inc(mrp_cb(skb)->attrvalue,
++				  mrp_cb(skb)->mh->attrlen);
++		vaevents %= __MRP_VECATTR_EVENT_MAX;
++		vaevent = vaevents;
++		mrp_pdu_parse_vecattr_event(app, skb, vaevent);
++	}
++	return 0;
++}
++
++static int mrp_pdu_parse_msg(struct mrp_applicant *app, struct sk_buff *skb,
++			     int *offset)
++{
++	struct mrp_msg_hdr _mh;
++
++	mrp_cb(skb)->mh = skb_header_pointer(skb, *offset, sizeof(_mh), &_mh);
++	if (!mrp_cb(skb)->mh)
++		return -1;
++	*offset += sizeof(_mh);
++
++	if (mrp_cb(skb)->mh->attrtype == 0 ||
++	    mrp_cb(skb)->mh->attrtype > app->app->maxattr ||
++	    mrp_cb(skb)->mh->attrlen == 0)
++		return -1;
++
++	while (skb->len > *offset) {
++		if (mrp_pdu_parse_end_mark(skb, offset) < 0)
++			break;
++		if (mrp_pdu_parse_vecattr(app, skb, offset) < 0)
++			return -1;
++	}
++	return 0;
++}
++
++int mrp_rcv(struct sk_buff *skb, struct net_device *dev,
++	    struct packet_type *pt, struct net_device *orig_dev)
++{
++	struct mrp_application *appl = container_of(pt, struct mrp_application,
++						    pkttype);
++	struct mrp_port *port;
++	struct mrp_applicant *app;
++	struct mrp_pdu_hdr _ph;
++	const struct mrp_pdu_hdr *ph;
++	int offset = skb_network_offset(skb);
++
++	/* If the interface is in promiscuous mode, drop the packet if
++	 * it was unicast to another host.
++	 */
++	if (unlikely(skb->pkt_type == PACKET_OTHERHOST))
++		goto out;
++	skb = skb_share_check(skb, GFP_ATOMIC);
++	if (unlikely(!skb))
++		goto out;
++	port = rcu_dereference(dev->mrp_port);
++	if (unlikely(!port))
++		goto out;
++	app = rcu_dereference(port->applicants[appl->type]);
++	if (unlikely(!app))
++		goto out;
++
++	ph = skb_header_pointer(skb, offset, sizeof(_ph), &_ph);
++	if (!ph)
++		goto out;
++	offset += sizeof(_ph);
++
++	if (ph->version != app->app->version)
++		goto out;
++
++	spin_lock(&app->lock);
++	while (skb->len > offset) {
++		if (mrp_pdu_parse_end_mark(skb, &offset) < 0)
++			break;
++		if (mrp_pdu_parse_msg(app, skb, &offset) < 0)
++			break;
++	}
++	spin_unlock(&app->lock);
++out:
++	kfree_skb(skb);
++	return 0;
++}
++
++static int mrp_init_port(struct net_device *dev)
++{
++	struct mrp_port *port;
++
++	port = kzalloc(sizeof(*port), GFP_KERNEL);
++	if (!port)
++		return -ENOMEM;
++	rcu_assign_pointer(dev->mrp_port, port);
++	return 0;
++}
++
++static void mrp_release_port(struct net_device *dev)
++{
++	struct mrp_port *port = rtnl_dereference(dev->mrp_port);
++	unsigned int i;
++
++	for (i = 0; i <= MRP_APPLICATION_MAX; i++) {
++		if (rtnl_dereference(port->applicants[i]))
++			return;
++	}
++	RCU_INIT_POINTER(dev->mrp_port, NULL);
++	kfree_rcu(port, rcu);
++}
++
++int mrp_init_applicant(struct net_device *dev, struct mrp_application *appl)
++{
++	struct mrp_applicant *app;
++	int err;
++
++	ASSERT_RTNL();
++
++	if (!rtnl_dereference(dev->mrp_port)) {
++		err = mrp_init_port(dev);
++		if (err < 0)
++			goto err1;
++	}
++
++	err = -ENOMEM;
++	app = kzalloc(sizeof(*app), GFP_KERNEL);
++	if (!app)
++		goto err2;
++
++	err = dev_mc_add(dev, appl->group_address);
++	if (err < 0)
++		goto err3;
++
++	app->dev = dev;
++	app->app = appl;
++	app->mad = RB_ROOT;
++	spin_lock_init(&app->lock);
++	skb_queue_head_init(&app->queue);
++	rcu_assign_pointer(dev->mrp_port->applicants[appl->type], app);
++	setup_timer(&app->join_timer, mrp_join_timer, (unsigned long)app);
++	mrp_join_timer_arm(app);
++	return 0;
++
++err3:
++	kfree(app);
++err2:
++	mrp_release_port(dev);
++err1:
++	return err;
++}
++EXPORT_SYMBOL_GPL(mrp_init_applicant);
++
++void mrp_uninit_applicant(struct net_device *dev, struct mrp_application *appl)
++{
++	struct mrp_port *port = rtnl_dereference(dev->mrp_port);
++	struct mrp_applicant *app = rtnl_dereference(
++		port->applicants[appl->type]);
++
++	ASSERT_RTNL();
++
++	RCU_INIT_POINTER(port->applicants[appl->type], NULL);
++
++	/* Delete timer and generate a final TX event to flush out
++	 * all pending messages before the applicant is gone.
++	 */
++	del_timer_sync(&app->join_timer);
++	mrp_mad_event(app, MRP_EVENT_TX);
++	mrp_pdu_queue(app);
++	mrp_queue_xmit(app);
++
++	dev_mc_del(dev, appl->group_address);
++	kfree_rcu(app, rcu);
++	mrp_release_port(dev);
++}
++EXPORT_SYMBOL_GPL(mrp_uninit_applicant);
++
++int mrp_register_application(struct mrp_application *appl)
++{
++	appl->pkttype.func = mrp_rcv;
++	dev_add_pack(&appl->pkttype);
++	return 0;
++}
++EXPORT_SYMBOL_GPL(mrp_register_application);
++
++void mrp_unregister_application(struct mrp_application *appl)
++{
++	dev_remove_pack(&appl->pkttype);
++}
++EXPORT_SYMBOL_GPL(mrp_unregister_application);

commit 040468a0a7b3f9c7966126d98151bc64f1423657
+Author: David Ward 
+Date:   Sun Jan 27 13:04:58 2013 +0000
+
+    ip_gre: When TOS is inherited, use configured TOS value for non-IP packets
+    
+    A GRE tunnel can be configured so that outgoing tunnel packets inherit
+    the value of the TOS field from the inner IP header. In doing so, when
+    a non-IP packet is transmitted through the tunnel, the TOS field will
+    always be set to 0.
+    
+    Instead, the user should be able to configure a different TOS value as
+    the fallback to use for non-IP packets. This is helpful when the non-IP
+    packets are all control packets and should be handled by routers outside
+    the tunnel as having Internet Control precedence. One example of this is
+    the NHRP packets that control a DMVPN-compatible mGRE tunnel; they are
+    encapsulated directly by GRE and do not contain an inner IP header.
+    
+    Under the existing behavior, the IFLA_GRE_TOS parameter must be set to
+    '1' for the TOS value to be inherited. Now, only the least significant
+    bit of this parameter must be set to '1', and when a non-IP packet is
+    sent through the tunnel, the upper 6 bits of this same parameter will be
+    copied into the TOS field. (The ECN bits get masked off as before.)
+    
+    This behavior is backwards-compatible with existing configurations and
+    iproute2 versions.
+    
+    Signed-off-by: David Ward 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
+index af6be70821c4..801e02355ec4 100644
+--- a/net/ipv4/ip_gre.c
++++ b/net/ipv4/ip_gre.c
+@@ -820,8 +820,8 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
+ 
+ 	ttl = tiph->ttl;
+ 	tos = tiph->tos;
+-	if (tos == 1) {
+-		tos = 0;
++	if (tos & 0x1) {
++		tos &= ~0x1;
+ 		if (skb->protocol == htons(ETH_P_IP))
+ 			tos = old_iph->tos;
+ 		else if (skb->protocol == htons(ETH_P_IPV6))

commit ba1bf474eae07a128fae6252bf7d68eaef0eacf8
+Author: David Ward 
+Date:   Thu Sep 13 05:22:35 2012 +0000
+
+    net_sched: gred: actually perform idling in WRED mode
+    
+    gred_dequeue() and gred_drop() do not seem to get called when the
+    queue is empty, meaning that we never start idling while in WRED
+    mode. And since qidlestart is not stored by gred_store_wred_set(),
+    we would never stop idling while in WRED mode if we ever started.
+    This messes up the average queue size calculation that influences
+    packet marking/dropping behavior.
+    
+    Now, we start WRED mode idling as we are removing the last packet
+    from the queue. Also we now actually stop WRED mode idling when we
+    are enqueuing a packet.
+    
+    Cc: Bruce Osler 
+    Signed-off-by: David Ward 
+    Acked-by: Jamal Hadi Salim 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
+index b2570b59d85e..d42234c0f13b 100644
+--- a/net/sched/sch_gred.c
++++ b/net/sched/sch_gred.c
+@@ -136,6 +136,7 @@ static inline void gred_store_wred_set(struct gred_sched *table,
+ 				       struct gred_sched_data *q)
+ {
+ 	table->wred_set.qavg = q->vars.qavg;
++	table->wred_set.qidlestart = q->vars.qidlestart;
+ }
+ 
+ static inline int gred_use_ecn(struct gred_sched *t)
+@@ -259,16 +260,18 @@ static struct sk_buff *gred_dequeue(struct Qdisc *sch)
+ 		} else {
+ 			q->backlog -= qdisc_pkt_len(skb);
+ 
+-			if (!q->backlog && !gred_wred_mode(t))
+-				red_start_of_idle_period(&q->vars);
++			if (gred_wred_mode(t)) {
++				if (!sch->qstats.backlog)
++					red_start_of_idle_period(&t->wred_set);
++			} else {
++				if (!q->backlog)
++					red_start_of_idle_period(&q->vars);
++			}
+ 		}
+ 
+ 		return skb;
+ 	}
+ 
+-	if (gred_wred_mode(t) && !red_is_idling(&t->wred_set))
+-		red_start_of_idle_period(&t->wred_set);
+-
+ 	return NULL;
+ }
+ 
+@@ -290,19 +293,20 @@ static unsigned int gred_drop(struct Qdisc *sch)
+ 			q->backlog -= len;
+ 			q->stats.other++;
+ 
+-			if (!q->backlog && !gred_wred_mode(t))
+-				red_start_of_idle_period(&q->vars);
++			if (gred_wred_mode(t)) {
++				if (!sch->qstats.backlog)
++					red_start_of_idle_period(&t->wred_set);
++			} else {
++				if (!q->backlog)
++					red_start_of_idle_period(&q->vars);
++			}
+ 		}
+ 
+ 		qdisc_drop(skb, sch);
+ 		return len;
+ 	}
+ 
+-	if (gred_wred_mode(t) && !red_is_idling(&t->wred_set))
+-		red_start_of_idle_period(&t->wred_set);
+-
+ 	return 0;
+-
+ }
+ 
+ static void gred_reset(struct Qdisc *sch)

commit 1fe37b106b039d9358fd1211c39b1fa199e547a8
+Author: David Ward 
+Date:   Thu Sep 13 05:22:34 2012 +0000
+
+    net_sched: gred: fix qave reporting via netlink
+    
+    q->vars.qavg is a Wlog scaled value, but q->backlog is not. In order
+    to pass q->vars.qavg as the backlog value, we need to un-scale it.
+    Additionally, the qave value returned via netlink should not be Wlog
+    scaled, so we need to un-scale the result of red_calc_qavg().
+    
+    This caused artificially high values for "Average Queue" to be shown
+    by 'tc -s -d qdisc', but did not affect the actual operation of GRED.
+    
+    Signed-off-by: David Ward 
+    Acked-by: Jamal Hadi Salim 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
+index e19d4ebfea1c..b2570b59d85e 100644
+--- a/net/sched/sch_gred.c
++++ b/net/sched/sch_gred.c
+@@ -534,6 +534,7 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)
+ 	for (i = 0; i < MAX_DPs; i++) {
+ 		struct gred_sched_data *q = table->tab[i];
+ 		struct tc_gred_qopt opt;
++		unsigned long qavg;
+ 
+ 		memset(&opt, 0, sizeof(opt));
+ 
+@@ -565,7 +566,9 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)
+ 		if (gred_wred_mode(table))
+ 			gred_load_wred_set(table, q);
+ 
+-		opt.qave = red_calc_qavg(&q->parms, &q->vars, q->vars.qavg);
++		qavg = red_calc_qavg(&q->parms, &q->vars,
++				     q->vars.qavg >> q->parms.Wlog);
++		opt.qave = qavg >> q->parms.Wlog;
+ 
+ append_opt:
+ 		if (nla_append(skb, sizeof(opt), &opt) < 0)

commit c22e464022f935b0cbd8724b1d99d800d49518a9
+Author: David Ward 
+Date:   Thu Sep 13 05:22:33 2012 +0000
+
+    net_sched: gred: eliminate redundant DP prio comparisons
+    
+    Each pair of DPs only needs to be compared once when searching for
+    a non-unique prio value.
+    
+    Signed-off-by: David Ward 
+    Acked-by: Jamal Hadi Salim 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
+index fca73cdf44d9..e19d4ebfea1c 100644
+--- a/net/sched/sch_gred.c
++++ b/net/sched/sch_gred.c
+@@ -102,9 +102,8 @@ static inline int gred_wred_mode_check(struct Qdisc *sch)
+ 		if (q == NULL)
+ 			continue;
+ 
+-		for (n = 0; n < table->DPs; n++)
+-			if (table->tab[n] && table->tab[n] != q &&
+-			    table->tab[n]->prio == q->prio)
++		for (n = i + 1; n < table->DPs; n++)
++			if (table->tab[n] && table->tab[n]->prio == q->prio)
+ 				return 1;
+ 	}
+ 

commit e29fe837bfa3ca0a9f4ef1d4a90e6e0a74b6b8a0
+Author: David Ward 
+Date:   Thu Sep 13 05:22:32 2012 +0000
+
+    net_sched: gred: correct comment about qavg calculation in RIO mode
+    
+    Signed-off-by: David Ward 
+    Acked-by: Jamal Hadi Salim 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
+index e901583e4ea5..fca73cdf44d9 100644
+--- a/net/sched/sch_gred.c
++++ b/net/sched/sch_gred.c
+@@ -176,7 +176,7 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+ 		skb->tc_index = (skb->tc_index & ~GRED_VQ_MASK) | dp;
+ 	}
+ 
+-	/* sum up all the qaves of prios <= to ours to get the new qave */
++	/* sum up all the qaves of prios < ours to get the new qave */
+ 	if (!gred_wred_mode(t) && gred_rio_mode(t)) {
+ 		int i;
+ 

commit 4362aaf6054b9760652c7047cdf6fa852acb6cf7
+Author: David Ward 
+Date:   Mon Apr 16 03:17:22 2012 +0000
+
+    net_sched: red: Make minor corrections to comments
+    
+    Signed-off-by: David Ward 
+    Signed-off-by: David S. Miller 
+
+diff --git a/include/net/red.h b/include/net/red.h
+index 77d4c3745cb5..ef46058d35bf 100644
+--- a/include/net/red.h
++++ b/include/net/red.h
+@@ -245,7 +245,7 @@ static inline unsigned long red_calc_qavg_from_idle_time(const struct red_parms
+ 	 *
+ 	 * dummy packets as a burst after idle time, i.e.
+ 	 *
+-	 * 	p->qavg *= (1-W)^m
++	 * 	v->qavg *= (1-W)^m
+ 	 *
+ 	 * This is an apparently overcomplicated solution (f.e. we have to
+ 	 * precompute a table to make this calculation in reasonable time)
+@@ -279,7 +279,7 @@ static inline unsigned long red_calc_qavg_no_idle_time(const struct red_parms *p
+ 						       unsigned int backlog)
+ {
+ 	/*
+-	 * NOTE: p->qavg is fixed point number with point at Wlog.
++	 * NOTE: v->qavg is fixed point number with point at Wlog.
+ 	 * The formula below is equvalent to floating point
+ 	 * version:
+ 	 *
+@@ -390,7 +390,7 @@ static inline void red_adaptative_algo(struct red_parms *p, struct red_vars *v)
+ 	if (red_is_idling(v))
+ 		qavg = red_calc_qavg_from_idle_time(p, v);
+ 
+-	/* p->qavg is fixed point number with point at Wlog */
++	/* v->qavg is fixed point number with point at Wlog */
+ 	qavg >>= p->Wlog;
+ 
+ 	if (qavg > p->target_max && p->max_P <= MAX_P_MAX)

commit 244b65dbfede788f2fa3fe2463c44d0809e97c6b
+Author: David Ward 
+Date:   Sun Apr 15 12:31:45 2012 +0000
+
+    net_sched: gred: Fix oops in gred_dump() in WRED mode
+    
+    A parameter set exists for WRED mode, called wred_set, to hold the same
+    values for qavg and qidlestart across all VQs. The WRED mode values had
+    been previously held in the VQ for the default DP. After these values
+    were moved to wred_set, the VQ for the default DP was no longer created
+    automatically (so that it could be omitted on purpose, to have packets
+    in the default DP enqueued directly to the device without using RED).
+    
+    However, gred_dump() was overlooked during that change; in WRED mode it
+    still reads qavg/qidlestart from the VQ for the default DP, which might
+    not even exist. As a result, this command sequence will cause an oops:
+    
+    tc qdisc add dev $DEV handle $HANDLE parent $PARENT gred setup \
+        DPs 3 default 2 grio
+    tc qdisc change dev $DEV handle $HANDLE gred DP 0 prio 8 $RED_OPTIONS
+    tc qdisc change dev $DEV handle $HANDLE gred DP 1 prio 8 $RED_OPTIONS
+    
+    This fixes gred_dump() in WRED mode to use the values held in wred_set.
+    
+    Signed-off-by: David Ward 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
+index 0b15236be7b6..8179494c269a 100644
+--- a/net/sched/sch_gred.c
++++ b/net/sched/sch_gred.c
+@@ -565,11 +565,8 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)
+ 		opt.packets	= q->packetsin;
+ 		opt.bytesin	= q->bytesin;
+ 
+-		if (gred_wred_mode(table)) {
+-			q->vars.qidlestart =
+-				table->tab[table->def]->vars.qidlestart;
+-			q->vars.qavg = table->tab[table->def]->vars.qavg;
+-		}
++		if (gred_wred_mode(table))
++			gred_load_wred_set(table, q);
+ 
+ 		opt.qave = red_calc_qavg(&q->parms, &q->vars, q->vars.qavg);
+ 

commit 6f66cdc3e5d3d5ccbb7ee9265b8211cdc24aa401
+Author: David Ward 
+Date:   Mon Apr 9 04:13:53 2012 +0000
+
+    net/garp: fix GID rbtree ordering
+    
+    The comparison operators were backwards in both garp_attr_lookup and
+    garp_attr_create, so the entire GID rbtree was in reverse order.
+    (There was no practical side effect to this though, except that PDUs
+    were sent with attributes listed in reverse order, which is still
+    valid by the protocol. This change is only for clarity.)
+    
+    Signed-off-by: David Ward 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/802/garp.c b/net/802/garp.c
+index a5c224830439..8456f5d98b85 100644
+--- a/net/802/garp.c
++++ b/net/802/garp.c
+@@ -157,9 +157,9 @@ static struct garp_attr *garp_attr_lookup(const struct garp_applicant *app,
+ 	while (parent) {
+ 		attr = rb_entry(parent, struct garp_attr, node);
+ 		d = garp_attr_cmp(attr, data, len, type);
+-		if (d < 0)
++		if (d > 0)
+ 			parent = parent->rb_left;
+-		else if (d > 0)
++		else if (d < 0)
+ 			parent = parent->rb_right;
+ 		else
+ 			return attr;
+@@ -178,9 +178,9 @@ static struct garp_attr *garp_attr_create(struct garp_applicant *app,
+ 		parent = *p;
+ 		attr = rb_entry(parent, struct garp_attr, node);
+ 		d = garp_attr_cmp(attr, data, len, type);
+-		if (d < 0)
++		if (d > 0)
+ 			p = &parent->rb_left;
+-		else if (d > 0)
++		else if (d < 0)
+ 			p = &parent->rb_right;
+ 		else {
+ 			/* The attribute already exists; re-use it. */

commit 67378563df2e168d32a4054616f244a91aec462d
+Author: David Ward 
+Date:   Tue Mar 27 09:01:52 2012 +0000
+
+    net/garp: avoid infinite loop if attribute already exists
+    
+    An infinite loop occurred if garp_attr_create was called with the values
+    of an existing attribute. This might happen if a previous leave request
+    for the attribute has not yet been followed by a PDU transmission (or,
+    if the application previously issued a join request for the attribute
+    and is now issuing another one, without having issued a leave request).
+    
+    If garp_attr_create finds an existing attribute having the same values,
+    return the address to it. Its state will then get updated (i.e., if it
+    was in a leaving state, it will move into a non-leaving state and not
+    get deleted during the next PDU transmission).
+    
+    To accomplish this fix, collapse garp_attr_insert into garp_attr_create
+    (which is its only caller).
+    
+    Thanks to Jorge Boncompte [DTI2]  for contributing to
+    this fix.
+    
+    Signed-off-by: David Ward 
+    Acked-by: Jorge Boncompte [DTI2] 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/802/garp.c b/net/802/garp.c
+index 8e21b6db3981..a5c224830439 100644
+--- a/net/802/garp.c
++++ b/net/802/garp.c
+@@ -167,7 +167,8 @@ static struct garp_attr *garp_attr_lookup(const struct garp_applicant *app,
+ 	return NULL;
+ }
+ 
+-static void garp_attr_insert(struct garp_applicant *app, struct garp_attr *new)
++static struct garp_attr *garp_attr_create(struct garp_applicant *app,
++					  const void *data, u8 len, u8 type)
+ {
+ 	struct rb_node *parent = NULL, **p = &app->gid.rb_node;
+ 	struct garp_attr *attr;
+@@ -176,21 +177,16 @@ static void garp_attr_insert(struct garp_applicant *app, struct garp_attr *new)
+ 	while (*p) {
+ 		parent = *p;
+ 		attr = rb_entry(parent, struct garp_attr, node);
+-		d = garp_attr_cmp(attr, new->data, new->dlen, new->type);
++		d = garp_attr_cmp(attr, data, len, type);
+ 		if (d < 0)
+ 			p = &parent->rb_left;
+ 		else if (d > 0)
+ 			p = &parent->rb_right;
++		else {
++			/* The attribute already exists; re-use it. */
++			return attr;
++		}
+ 	}
+-	rb_link_node(&new->node, parent, p);
+-	rb_insert_color(&new->node, &app->gid);
+-}
+-
+-static struct garp_attr *garp_attr_create(struct garp_applicant *app,
+-					  const void *data, u8 len, u8 type)
+-{
+-	struct garp_attr *attr;
+-
+ 	attr = kmalloc(sizeof(*attr) + len, GFP_ATOMIC);
+ 	if (!attr)
+ 		return attr;
+@@ -198,7 +194,9 @@ static struct garp_attr *garp_attr_create(struct garp_applicant *app,
+ 	attr->type  = type;
+ 	attr->dlen  = len;
+ 	memcpy(attr->data, data, len);
+-	garp_attr_insert(app, attr);
++
++	rb_link_node(&attr->node, parent, p);
++	rb_insert_color(&attr->node, &app->gid);
+ 	return attr;
+ }
+ 

commit cb2d0f3e968bff7c6d262aca3e3ab8d4184e69b2
+Author: David Ward 
+Date:   Sun Sep 18 12:53:20 2011 +0000
+
+    macvlan/macvtap: Fix unicast between macvtap interfaces in bridge mode
+    
+    Packets should always be forwarded to the lowerdev using dev_forward_skb.
+    vlan->forward is for packets being forwarded directly to another macvlan/
+    macvtap device (used for multicast in bridge mode).
+    
+    Reported-and-tested-by: Shlomo Pongratz 
+    Signed-off-by: David Ward 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
+index 05172c39a0ce..376e3e94bae0 100644
+--- a/drivers/net/macvlan.c
++++ b/drivers/net/macvlan.c
+@@ -239,7 +239,7 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
+ 		dest = macvlan_hash_lookup(port, eth->h_dest);
+ 		if (dest && dest->mode == MACVLAN_MODE_BRIDGE) {
+ 			/* send to lowerdev first for its network taps */
+-			vlan->forward(vlan->lowerdev, skb);
++			dev_forward_skb(vlan->lowerdev, skb);
+ 
+ 			return NET_XMIT_SUCCESS;
+ 		}

commit aa1c366e4febc7f5c2b84958a2dd7cd70e28f9d0
+Author: dpward 
+Date:   Mon Sep 5 16:47:24 2011 +0000
+
+    net: Handle different key sizes between address families in flow cache
+    
+    With the conversion of struct flowi to a union of AF-specific structs, some
+    operations on the flow cache need to account for the exact size of the key.
+    
+    Signed-off-by: David Ward 
+    Signed-off-by: David S. Miller 
+
+diff --git a/include/net/flow.h b/include/net/flow.h
+index 2ec377d9ab9f..a09447749e2d 100644
+--- a/include/net/flow.h
++++ b/include/net/flow.h
+@@ -7,6 +7,7 @@
+ #ifndef _NET_FLOW_H
+ #define _NET_FLOW_H
+ 
++#include 
+ #include 
+ #include 
+ 
+@@ -161,6 +162,24 @@ static inline struct flowi *flowidn_to_flowi(struct flowidn *fldn)
+ 	return container_of(fldn, struct flowi, u.dn);
+ }
+ 
++typedef unsigned long flow_compare_t;
++
++static inline size_t flow_key_size(u16 family)
++{
++	switch (family) {
++	case AF_INET:
++		BUILD_BUG_ON(sizeof(struct flowi4) % sizeof(flow_compare_t));
++		return sizeof(struct flowi4) / sizeof(flow_compare_t);
++	case AF_INET6:
++		BUILD_BUG_ON(sizeof(struct flowi6) % sizeof(flow_compare_t));
++		return sizeof(struct flowi6) / sizeof(flow_compare_t);
++	case AF_DECnet:
++		BUILD_BUG_ON(sizeof(struct flowidn) % sizeof(flow_compare_t));
++		return sizeof(struct flowidn) / sizeof(flow_compare_t);
++	}
++	return 0;
++}
++
+ #define FLOW_DIR_IN	0
+ #define FLOW_DIR_OUT	1
+ #define FLOW_DIR_FWD	2
+diff --git a/net/core/flow.c b/net/core/flow.c
+index 47b6d26c2afb..555a456efb07 100644
+--- a/net/core/flow.c
++++ b/net/core/flow.c
+@@ -173,29 +173,26 @@ static void flow_new_hash_rnd(struct flow_cache *fc,
+ 
+ static u32 flow_hash_code(struct flow_cache *fc,
+ 			  struct flow_cache_percpu *fcp,
+-			  const struct flowi *key)
++			  const struct flowi *key,
++			  size_t keysize)
+ {
+ 	const u32 *k = (const u32 *) key;
++	const u32 length = keysize * sizeof(flow_compare_t) / sizeof(u32);
+ 
+-	return jhash2(k, (sizeof(*key) / sizeof(u32)), fcp->hash_rnd)
++	return jhash2(k, length, fcp->hash_rnd)
+ 		& (flow_cache_hash_size(fc) - 1);
+ }
+ 
+-typedef unsigned long flow_compare_t;
+-
+ /* I hear what you're saying, use memcmp.  But memcmp cannot make
+- * important assumptions that we can here, such as alignment and
+- * constant size.
++ * important assumptions that we can here, such as alignment.
+  */
+-static int flow_key_compare(const struct flowi *key1, const struct flowi *key2)
++static int flow_key_compare(const struct flowi *key1, const struct flowi *key2,
++			    size_t keysize)
+ {
+ 	const flow_compare_t *k1, *k1_lim, *k2;
+-	const int n_elem = sizeof(struct flowi) / sizeof(flow_compare_t);
+-
+-	BUILD_BUG_ON(sizeof(struct flowi) % sizeof(flow_compare_t));
+ 
+ 	k1 = (const flow_compare_t *) key1;
+-	k1_lim = k1 + n_elem;
++	k1_lim = k1 + keysize;
+ 
+ 	k2 = (const flow_compare_t *) key2;
+ 
+@@ -216,6 +213,7 @@ flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir,
+ 	struct flow_cache_entry *fle, *tfle;
+ 	struct hlist_node *entry;
+ 	struct flow_cache_object *flo;
++	size_t keysize;
+ 	unsigned int hash;
+ 
+ 	local_bh_disable();
+@@ -223,6 +221,11 @@ flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir,
+ 
+ 	fle = NULL;
+ 	flo = NULL;
++
++	keysize = flow_key_size(family);
++	if (!keysize)
++		goto nocache;
++
+ 	/* Packet really early in init?  Making flow_cache_init a
+ 	 * pre-smp initcall would solve this.  --RR */
+ 	if (!fcp->hash_table)
+@@ -231,12 +234,12 @@ flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir,
+ 	if (fcp->hash_rnd_recalc)
+ 		flow_new_hash_rnd(fc, fcp);
+ 
+-	hash = flow_hash_code(fc, fcp, key);
++	hash = flow_hash_code(fc, fcp, key, keysize);
+ 	hlist_for_each_entry(tfle, entry, &fcp->hash_table[hash], u.hlist) {
+ 		if (tfle->net == net &&
+ 		    tfle->family == family &&
+ 		    tfle->dir == dir &&
+-		    flow_key_compare(key, &tfle->key) == 0) {
++		    flow_key_compare(key, &tfle->key, keysize) == 0) {
+ 			fle = tfle;
+ 			break;
+ 		}
+@@ -251,7 +254,7 @@ flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir,
+ 			fle->net = net;
+ 			fle->family = family;
+ 			fle->dir = dir;
+-			memcpy(&fle->key, key, sizeof(*key));
++			memcpy(&fle->key, key, keysize * sizeof(flow_compare_t));
+ 			fle->object = NULL;
+ 			hlist_add_head(&fle->u.hlist, &fcp->hash_table[hash]);
+ 			fcp->hash_count++;

commit 728871bc05afc8ff310b17dba3e57a2472792b13
+Author: David Ward 
+Date:   Mon Sep 5 16:47:23 2011 +0000
+
+    net: Align AF-specific flowi structs to long
+    
+    AF-specific flowi structs are now passed to flow_key_compare, which must
+    also be aligned to a long.
+    
+    Signed-off-by: David Ward 
+    Signed-off-by: David S. Miller 
+
+diff --git a/include/net/flow.h b/include/net/flow.h
+index 78113daadd63..2ec377d9ab9f 100644
+--- a/include/net/flow.h
++++ b/include/net/flow.h
+@@ -68,7 +68,7 @@ struct flowi4 {
+ #define fl4_ipsec_spi		uli.spi
+ #define fl4_mh_type		uli.mht.type
+ #define fl4_gre_key		uli.gre_key
+-};
++} __attribute__((__aligned__(BITS_PER_LONG/8)));
+ 
+ static inline void flowi4_init_output(struct flowi4 *fl4, int oif,
+ 				      __u32 mark, __u8 tos, __u8 scope,
+@@ -112,7 +112,7 @@ struct flowi6 {
+ #define fl6_ipsec_spi		uli.spi
+ #define fl6_mh_type		uli.mht.type
+ #define fl6_gre_key		uli.gre_key
+-};
++} __attribute__((__aligned__(BITS_PER_LONG/8)));
+ 
+ struct flowidn {
+ 	struct flowi_common	__fl_common;
+@@ -127,7 +127,7 @@ struct flowidn {
+ 	union flowi_uli		uli;
+ #define fld_sport		uli.ports.sport
+ #define fld_dport		uli.ports.dport
+-};
++} __attribute__((__aligned__(BITS_PER_LONG/8)));
+ 
+ struct flowi {
+ 	union {

commit 0542b69e2c57fc9668ce6a03155bea6e1f557901
+Author: dpward 
+Date:   Wed Aug 31 06:05:27 2011 +0000
+
+    net: Make flow cache namespace-aware
+    
+    flow_cache_lookup will return a cached object (or null pointer) that the
+    resolver (i.e. xfrm_policy_lookup) previously found for another namespace
+    using the same key/family/dir.  Instead, make the namespace part of what
+    identifies entries in the cache.
+    
+    As before, flow_entry_valid will return 0 for entries where the namespace
+    has been deleted, and they will be removed from the cache the next time
+    flow_cache_gc_task is run.
+    
+    Reported-by: Andrew Dickinson 
+    Signed-off-by: David Ward 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/core/flow.c b/net/core/flow.c
+index bf32c33cad3b..47b6d26c2afb 100644
+--- a/net/core/flow.c
++++ b/net/core/flow.c
+@@ -30,6 +30,7 @@ struct flow_cache_entry {
+ 		struct hlist_node	hlist;
+ 		struct list_head	gc_list;
+ 	} u;
++	struct net			*net;
+ 	u16				family;
+ 	u8				dir;
+ 	u32				genid;
+@@ -232,7 +233,8 @@ flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir,
+ 
+ 	hash = flow_hash_code(fc, fcp, key);
+ 	hlist_for_each_entry(tfle, entry, &fcp->hash_table[hash], u.hlist) {
+-		if (tfle->family == family &&
++		if (tfle->net == net &&
++		    tfle->family == family &&
+ 		    tfle->dir == dir &&
+ 		    flow_key_compare(key, &tfle->key) == 0) {
+ 			fle = tfle;
+@@ -246,6 +248,7 @@ flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir,
+ 
+ 		fle = kmem_cache_alloc(flow_cachep, GFP_ATOMIC);
+ 		if (fle) {
++			fle->net = net;
+ 			fle->family = family;
+ 			fle->dir = dir;
+ 			memcpy(&fle->key, key, sizeof(*key));

commit a37dd3332319260cce81ac91ce25fcc3a31de997
+Author: David Ward 
+Date:   Thu May 19 02:53:20 2011 +0000
+
+    macvlan: Forward unicast frames in bridge mode to lowerdev
+    
+    Unicast frames between macvlan interfaces in bridge mode are not otherwise
+    sent to network taps on the lowerdev (as all other macvlan frames are), so
+    forward the frames to the receive queue of the lowerdev first.
+    
+    Signed-off-by: David Ward 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
+index d72a70615c0f..d6aeaa5f25ea 100644
+--- a/drivers/net/macvlan.c
++++ b/drivers/net/macvlan.c
+@@ -238,10 +238,8 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
+ 
+ 		dest = macvlan_hash_lookup(port, eth->h_dest);
+ 		if (dest && dest->mode == MACVLAN_MODE_BRIDGE) {
+-			unsigned int length = skb->len + ETH_HLEN;
+-			int ret = dest->forward(dest->dev, skb);
+-			macvlan_count_rx(dest, length,
+-					 ret == NET_RX_SUCCESS, 0);
++			/* send to lowerdev first for its network taps */
++			vlan->forward(vlan->lowerdev, skb);
+ 
+ 			return NET_XMIT_SUCCESS;
+ 		}

commit 31ce8c71a3bdab12debb5899b1f6dac13e54c71d
+Author: David Ward 
+Date:   Sat Aug 29 00:04:09 2009 -0700
+
+    ipv6: Update Neighbor Cache when IPv6 RA is received on a router
+    
+    When processing a received IPv6 Router Advertisement, the kernel
+    creates or updates an IPv6 Neighbor Cache entry for the sender --
+    but presently this does not occur if IPv6 forwarding is enabled
+    (net.ipv6.conf.*.forwarding = 1), or if IPv6 Router Advertisements
+    are not accepted (net.ipv6.conf.*.accept_ra = 0), because in these
+    cases processing of the Router Advertisement has already halted.
+    
+    This patch allows the Neighbor Cache to be updated in these cases,
+    while still avoiding any modification to routes or link parameters.
+    
+    This continues to satisfy RFC 4861, since any entry created in the
+    Neighbor Cache as the result of a received Router Advertisement is
+    still placed in the STALE state.
+    
+    Signed-off-by: David Ward 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
+index 1ba42bd65577..44b4c87e5cce 100644
+--- a/net/ipv6/ndisc.c
++++ b/net/ipv6/ndisc.c
+@@ -1151,10 +1151,6 @@ static void ndisc_router_discovery(struct sk_buff *skb)
+ 			   skb->dev->name);
+ 		return;
+ 	}
+-	if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) {
+-		in6_dev_put(in6_dev);
+-		return;
+-	}
+ 
+ 	if (!ndisc_parse_options(opt, optlen, &ndopts)) {
+ 		in6_dev_put(in6_dev);
+@@ -1163,6 +1159,10 @@ static void ndisc_router_discovery(struct sk_buff *skb)
+ 		return;
+ 	}
+ 
++	/* skip route and link configuration on routers */
++	if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra)
++		goto skip_linkparms;
++
+ #ifdef CONFIG_IPV6_NDISC_NODETYPE
+ 	/* skip link-specific parameters from interior routers */
+ 	if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT)
+@@ -1283,9 +1283,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
+ 		}
+ 	}
+ 
+-#ifdef CONFIG_IPV6_NDISC_NODETYPE
+ skip_linkparms:
+-#endif
+ 
+ 	/*
+ 	 *	Process options.
+@@ -1312,6 +1310,10 @@ static void ndisc_router_discovery(struct sk_buff *skb)
+ 			     NEIGH_UPDATE_F_ISROUTER);
+ 	}
+ 
++	/* skip route and link configuration on routers */
++	if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra)
++		goto out;
++
+ #ifdef CONFIG_IPV6_ROUTE_INFO
+ 	if (in6_dev->cnf.accept_ra_rtr_pref && ndopts.nd_opts_ri) {
+ 		struct nd_opt_hdr *p;

\ No newline at end of file diff --git a/detail/10.html b/detail/10.html new file mode 100644 index 0000000..2ff8c79 --- /dev/null +++ b/detail/10.html @@ -0,0 +1,28693 @@ +

Patches contributed by Peking University


commit 44d0fb387b53e56c8a050bac5c7d460e21eb226f
+Author: Ruihan Li 
+Date:   Mon May 15 21:09:58 2023 +0800
+
+    mm: page_table_check: Ensure user pages are not slab pages
+    
+    The current uses of PageAnon in page table check functions can lead to
+    type confusion bugs between struct page and slab [1], if slab pages are
+    accidentally mapped into the user space. This is because slab reuses the
+    bits in struct page to store its internal states, which renders PageAnon
+    ineffective on slab pages.
+    
+    Since slab pages are not expected to be mapped into the user space, this
+    patch adds BUG_ON(PageSlab(page)) checks to make sure that slab pages
+    are not inadvertently mapped. Otherwise, there must be some bugs in the
+    kernel.
+    
+    Reported-by: syzbot+fcf1a817ceb50935ce99@syzkaller.appspotmail.com
+    Closes: https://lore.kernel.org/lkml/000000000000258e5e05fae79fc1@google.com/ [1]
+    Fixes: df4e817b7108 ("mm: page table check")
+    Cc:  # 5.17
+    Signed-off-by: Ruihan Li 
+    Acked-by: Pasha Tatashin 
+    Link: https://lore.kernel.org/r/20230515130958.32471-5-lrh2000@pku.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
+index 1c68d67b832f..92a2063a0a23 100644
+--- a/include/linux/page-flags.h
++++ b/include/linux/page-flags.h
+@@ -617,6 +617,12 @@ PAGEFLAG_FALSE(VmemmapSelfHosted, vmemmap_self_hosted)
+  * Please note that, confusingly, "page_mapping" refers to the inode
+  * address_space which maps the page from disk; whereas "page_mapped"
+  * refers to user virtual address space into which the page is mapped.
++ *
++ * For slab pages, since slab reuses the bits in struct page to store its
++ * internal states, the page->mapping does not exist as such, nor do these
++ * flags below.  So in order to avoid testing non-existent bits, please
++ * make sure that PageSlab(page) actually evaluates to false before calling
++ * the following functions (e.g., PageAnon).  See mm/slab.h.
+  */
+ #define PAGE_MAPPING_ANON	0x1
+ #define PAGE_MAPPING_MOVABLE	0x2
+diff --git a/mm/page_table_check.c b/mm/page_table_check.c
+index 25d8610c0042..f2baf97d5f38 100644
+--- a/mm/page_table_check.c
++++ b/mm/page_table_check.c
+@@ -71,6 +71,8 @@ static void page_table_check_clear(struct mm_struct *mm, unsigned long addr,
+ 
+ 	page = pfn_to_page(pfn);
+ 	page_ext = page_ext_get(page);
++
++	BUG_ON(PageSlab(page));
+ 	anon = PageAnon(page);
+ 
+ 	for (i = 0; i < pgcnt; i++) {
+@@ -107,6 +109,8 @@ static void page_table_check_set(struct mm_struct *mm, unsigned long addr,
+ 
+ 	page = pfn_to_page(pfn);
+ 	page_ext = page_ext_get(page);
++
++	BUG_ON(PageSlab(page));
+ 	anon = PageAnon(page);
+ 
+ 	for (i = 0; i < pgcnt; i++) {
+@@ -133,6 +137,8 @@ void __page_table_check_zero(struct page *page, unsigned int order)
+ 	struct page_ext *page_ext;
+ 	unsigned long i;
+ 
++	BUG_ON(PageSlab(page));
++
+ 	page_ext = page_ext_get(page);
+ 	BUG_ON(!page_ext);
+ 	for (i = 0; i < (1ul << order); i++) {

commit 81a31a860bb61d54eb688af2568d9332ed9b8942
+Author: Ruihan Li 
+Date:   Mon May 15 21:09:57 2023 +0800
+
+    mm: page_table_check: Make it dependent on EXCLUSIVE_SYSTEM_RAM
+    
+    Without EXCLUSIVE_SYSTEM_RAM, users are allowed to map arbitrary
+    physical memory regions into the userspace via /dev/mem. At the same
+    time, pages may change their properties (e.g., from anonymous pages to
+    named pages) while they are still being mapped in the userspace, leading
+    to "corruption" detected by the page table check.
+    
+    To avoid these false positives, this patch makes PAGE_TABLE_CHECK
+    depends on EXCLUSIVE_SYSTEM_RAM. This dependency is understandable
+    because PAGE_TABLE_CHECK is a hardening technique but /dev/mem without
+    STRICT_DEVMEM (i.e., !EXCLUSIVE_SYSTEM_RAM) is itself a security
+    problem.
+    
+    Even with EXCLUSIVE_SYSTEM_RAM, I/O pages may be still allowed to be
+    mapped via /dev/mem. However, these pages are always considered as named
+    pages, so they won't break the logic used in the page table check.
+    
+    Cc:  # 5.17
+    Signed-off-by: Ruihan Li 
+    Acked-by: David Hildenbrand 
+    Acked-by: Pasha Tatashin 
+    Link: https://lore.kernel.org/r/20230515130958.32471-4-lrh2000@pku.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/mm/page_table_check.rst b/Documentation/mm/page_table_check.rst
+index cfd8f4117cf3..c12838ce6b8d 100644
+--- a/Documentation/mm/page_table_check.rst
++++ b/Documentation/mm/page_table_check.rst
+@@ -52,3 +52,22 @@ Build kernel with:
+ 
+ Optionally, build kernel with PAGE_TABLE_CHECK_ENFORCED in order to have page
+ table support without extra kernel parameter.
++
++Implementation notes
++====================
++
++We specifically decided not to use VMA information in order to avoid relying on
++MM states (except for limited "struct page" info). The page table check is a
++separate from Linux-MM state machine that verifies that the user accessible
++pages are not falsely shared.
++
++PAGE_TABLE_CHECK depends on EXCLUSIVE_SYSTEM_RAM. The reason is that without
++EXCLUSIVE_SYSTEM_RAM, users are allowed to map arbitrary physical memory
++regions into the userspace via /dev/mem. At the same time, pages may change
++their properties (e.g., from anonymous pages to named pages) while they are
++still being mapped in the userspace, leading to "corruption" detected by the
++page table check.
++
++Even with EXCLUSIVE_SYSTEM_RAM, I/O pages may be still allowed to be mapped via
++/dev/mem. However, these pages are always considered as named pages, so they
++won't break the logic used in the page table check.
+diff --git a/mm/Kconfig.debug b/mm/Kconfig.debug
+index a925415b4d10..018a5bd2f576 100644
+--- a/mm/Kconfig.debug
++++ b/mm/Kconfig.debug
+@@ -98,6 +98,7 @@ config PAGE_OWNER
+ config PAGE_TABLE_CHECK
+ 	bool "Check for invalid mappings in user page tables"
+ 	depends on ARCH_SUPPORTS_PAGE_TABLE_CHECK
++	depends on EXCLUSIVE_SYSTEM_RAM
+ 	select PAGE_EXTENSION
+ 	help
+ 	  Check that anonymous page is not being mapped twice with read write

commit d0b861653f8c16839c3035875b556afc4472f941
+Author: Ruihan Li 
+Date:   Mon May 15 21:09:56 2023 +0800
+
+    usb: usbfs: Use consistent mmap functions
+    
+    When hcd->localmem_pool is non-null, localmem_pool is used to allocate
+    DMA memory. In this case, the dma address will be properly returned (in
+    dma_handle), and dma_mmap_coherent should be used to map this memory
+    into the user space. However, the current implementation uses
+    pfn_remap_range, which is supposed to map normal pages.
+    
+    Instead of repeating the logic in the memory allocation function, this
+    patch introduces a more robust solution. Here, the type of allocated
+    memory is checked by testing whether dma_handle is properly set. If
+    dma_handle is properly returned, it means some DMA pages are allocated
+    and dma_mmap_coherent should be used to map them. Otherwise, normal
+    pages are allocated and pfn_remap_range should be called. This ensures
+    that the correct mmap functions are used consistently, independently
+    with logic details that determine which type of memory gets allocated.
+    
+    Fixes: a0e710a7def4 ("USB: usbfs: fix mmap dma mismatch")
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Ruihan Li 
+    Link: https://lore.kernel.org/r/20230515130958.32471-3-lrh2000@pku.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 3936ca7f7d2f..fcf68818e999 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -235,7 +235,7 @@ static int usbdev_mmap(struct file *file, struct vm_area_struct *vma)
+ 	size_t size = vma->vm_end - vma->vm_start;
+ 	void *mem;
+ 	unsigned long flags;
+-	dma_addr_t dma_handle;
++	dma_addr_t dma_handle = DMA_MAPPING_ERROR;
+ 	int ret;
+ 
+ 	ret = usbfs_increase_memory_usage(size + sizeof(struct usb_memory));
+@@ -265,7 +265,14 @@ static int usbdev_mmap(struct file *file, struct vm_area_struct *vma)
+ 	usbm->vma_use_count = 1;
+ 	INIT_LIST_HEAD(&usbm->memlist);
+ 
+-	if (hcd->localmem_pool || !hcd_uses_dma(hcd)) {
++	/*
++	 * In DMA-unavailable cases, hcd_buffer_alloc_pages allocates
++	 * normal pages and assigns DMA_MAPPING_ERROR to dma_handle. Check
++	 * whether we are in such cases, and then use remap_pfn_range (or
++	 * dma_mmap_coherent) to map normal (or DMA) pages into the user
++	 * space, respectively.
++	 */
++	if (dma_handle == DMA_MAPPING_ERROR) {
+ 		if (remap_pfn_range(vma, vma->vm_start,
+ 				    virt_to_phys(usbm->mem) >> PAGE_SHIFT,
+ 				    size, vma->vm_page_prot) < 0) {

commit 0143d148d1e882fb1538dc9974c94d63961719b9
+Author: Ruihan Li 
+Date:   Mon May 15 21:09:55 2023 +0800
+
+    usb: usbfs: Enforce page requirements for mmap
+    
+    The current implementation of usbdev_mmap uses usb_alloc_coherent to
+    allocate memory pages that will later be mapped into the user space.
+    Meanwhile, usb_alloc_coherent employs three different methods to
+    allocate memory, as outlined below:
+     * If hcd->localmem_pool is non-null, it uses gen_pool_dma_alloc to
+       allocate memory;
+     * If DMA is not available, it uses kmalloc to allocate memory;
+     * Otherwise, it uses dma_alloc_coherent.
+    
+    However, it should be noted that gen_pool_dma_alloc does not guarantee
+    that the resulting memory will be page-aligned. Furthermore, trying to
+    map slab pages (i.e., memory allocated by kmalloc) into the user space
+    is not resonable and can lead to problems, such as a type confusion bug
+    when PAGE_TABLE_CHECK=y [1].
+    
+    To address these issues, this patch introduces hcd_alloc_coherent_pages,
+    which addresses the above two problems. Specifically,
+    hcd_alloc_coherent_pages uses gen_pool_dma_alloc_align instead of
+    gen_pool_dma_alloc to ensure that the memory is page-aligned. To replace
+    kmalloc, hcd_alloc_coherent_pages directly allocates pages by calling
+    __get_free_pages.
+    
+    Reported-by: syzbot+fcf1a817ceb50935ce99@syzkaller.appspotmail.comm
+    Closes: https://lore.kernel.org/lkml/000000000000258e5e05fae79fc1@google.com/ [1]
+    Fixes: f7d34b445abc ("USB: Add support for usbfs zerocopy.")
+    Fixes: ff2437befd8f ("usb: host: Fix excessive alignment restriction for local memory allocations")
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Ruihan Li 
+    Acked-by: Alan Stern 
+    Link: https://lore.kernel.org/r/20230515130958.32471-2-lrh2000@pku.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
+index fbb087b728dc..268ccbec88f9 100644
+--- a/drivers/usb/core/buffer.c
++++ b/drivers/usb/core/buffer.c
+@@ -172,3 +172,44 @@ void hcd_buffer_free(
+ 	}
+ 	dma_free_coherent(hcd->self.sysdev, size, addr, dma);
+ }
++
++void *hcd_buffer_alloc_pages(struct usb_hcd *hcd,
++		size_t size, gfp_t mem_flags, dma_addr_t *dma)
++{
++	if (size == 0)
++		return NULL;
++
++	if (hcd->localmem_pool)
++		return gen_pool_dma_alloc_align(hcd->localmem_pool,
++				size, dma, PAGE_SIZE);
++
++	/* some USB hosts just use PIO */
++	if (!hcd_uses_dma(hcd)) {
++		*dma = DMA_MAPPING_ERROR;
++		return (void *)__get_free_pages(mem_flags,
++				get_order(size));
++	}
++
++	return dma_alloc_coherent(hcd->self.sysdev,
++			size, dma, mem_flags);
++}
++
++void hcd_buffer_free_pages(struct usb_hcd *hcd,
++		size_t size, void *addr, dma_addr_t dma)
++{
++	if (!addr)
++		return;
++
++	if (hcd->localmem_pool) {
++		gen_pool_free(hcd->localmem_pool,
++				(unsigned long)addr, size);
++		return;
++	}
++
++	if (!hcd_uses_dma(hcd)) {
++		free_pages((unsigned long)addr, get_order(size));
++		return;
++	}
++
++	dma_free_coherent(hcd->self.sysdev, size, addr, dma);
++}
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index e501a03d6c70..3936ca7f7d2f 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -186,6 +186,7 @@ static int connected(struct usb_dev_state *ps)
+ static void dec_usb_memory_use_count(struct usb_memory *usbm, int *count)
+ {
+ 	struct usb_dev_state *ps = usbm->ps;
++	struct usb_hcd *hcd = bus_to_hcd(ps->dev->bus);
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&ps->lock, flags);
+@@ -194,8 +195,8 @@ static void dec_usb_memory_use_count(struct usb_memory *usbm, int *count)
+ 		list_del(&usbm->memlist);
+ 		spin_unlock_irqrestore(&ps->lock, flags);
+ 
+-		usb_free_coherent(ps->dev, usbm->size, usbm->mem,
+-				usbm->dma_handle);
++		hcd_buffer_free_pages(hcd, usbm->size,
++				usbm->mem, usbm->dma_handle);
+ 		usbfs_decrease_memory_usage(
+ 			usbm->size + sizeof(struct usb_memory));
+ 		kfree(usbm);
+@@ -247,8 +248,8 @@ static int usbdev_mmap(struct file *file, struct vm_area_struct *vma)
+ 		goto error_decrease_mem;
+ 	}
+ 
+-	mem = usb_alloc_coherent(ps->dev, size, GFP_USER | __GFP_NOWARN,
+-			&dma_handle);
++	mem = hcd_buffer_alloc_pages(hcd,
++			size, GFP_USER | __GFP_NOWARN, &dma_handle);
+ 	if (!mem) {
+ 		ret = -ENOMEM;
+ 		goto error_free_usbm;
+diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
+index 094c77eaf455..0c7eff91adf4 100644
+--- a/include/linux/usb/hcd.h
++++ b/include/linux/usb/hcd.h
+@@ -501,6 +501,11 @@ void *hcd_buffer_alloc(struct usb_bus *bus, size_t size,
+ void hcd_buffer_free(struct usb_bus *bus, size_t size,
+ 	void *addr, dma_addr_t dma);
+ 
++void *hcd_buffer_alloc_pages(struct usb_hcd *hcd,
++		size_t size, gfp_t mem_flags, dma_addr_t *dma);
++void hcd_buffer_free_pages(struct usb_hcd *hcd,
++		size_t size, void *addr, dma_addr_t dma);
++
+ /* generic bus glue, needed for host controllers that don't use PCI */
+ extern irqreturn_t usb_hcd_irq(int irq, void *__hcd);
+ 

commit a2904d2825536aa896a149a9174d11b0958e7095
+Author: Ruihan Li 
+Date:   Wed May 3 21:39:37 2023 +0800
+
+    Bluetooth: Unlink CISes when LE disconnects in hci_conn_del
+    
+    Currently, hci_conn_del calls hci_conn_unlink for BR/EDR, (e)SCO, and
+    CIS connections, i.e., everything except LE connections. However, if
+    (e)SCO connections are unlinked when BR/EDR disconnects, CIS connections
+    should also be unlinked when LE disconnects.
+    
+    In terms of disconnection behavior, CIS and (e)SCO connections are not
+    too different. One peculiarity of CIS is that when CIS connections are
+    disconnected, the CIS handle isn't deleted, as per [BLUETOOTH CORE
+    SPECIFICATION Version 5.4 | Vol 4, Part E] 7.1.6 Disconnect command:
+    
+            All SCO, eSCO, and CIS connections on a physical link should be
+            disconnected before the ACL connection on the same physical
+            connection is disconnected. If it does not, they will be
+            implicitly disconnected as part of the ACL disconnection.
+            ...
+            Note: As specified in Section 7.7.5, on the Central, the handle
+            for a CIS remains valid even after disconnection and, therefore,
+            the Host can recreate a disconnected CIS at a later point in
+            time using the same connection handle.
+    
+    Since hci_conn_link invokes both hci_conn_get and hci_conn_hold,
+    hci_conn_unlink should perform both hci_conn_put and hci_conn_drop as
+    well. However, currently it performs only hci_conn_put.
+    
+    This patch makes hci_conn_unlink call hci_conn_drop as well, which
+    simplifies the logic in hci_conn_del a bit and may benefit future users
+    of hci_conn_unlink. But it is noted that this change additionally
+    implies that hci_conn_unlink can queue disc_work on conn itself, with
+    the following call stack:
+    
+            hci_conn_unlink(conn)  [conn->parent == NULL]
+                    -> hci_conn_unlink(child)  [child->parent == conn]
+                            -> hci_conn_drop(child->parent)
+                                    -> queue_delayed_work(&conn->disc_work)
+    
+    Queued disc_work after hci_conn_del can be spurious, so during the
+    process of hci_conn_del, it is necessary to make the call to
+    cancel_delayed_work(&conn->disc_work) after invoking hci_conn_unlink.
+    
+    Signed-off-by: Ruihan Li 
+    Co-developed-by: Luiz Augusto von Dentz 
+    Signed-off-by: Luiz Augusto von Dentz 
+
+diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
+index ce588359b290..f75ef12f18f7 100644
+--- a/net/bluetooth/hci_conn.c
++++ b/net/bluetooth/hci_conn.c
+@@ -1100,7 +1100,9 @@ static void hci_conn_unlink(struct hci_conn *conn)
+ 			 * yet at this point. Delete it now, otherwise it is
+ 			 * possible for it to be stuck and can't be deleted.
+ 			 */
+-			if (child->handle == HCI_CONN_HANDLE_UNSET)
++			if ((child->type == SCO_LINK ||
++			     child->type == ESCO_LINK) &&
++			    child->handle == HCI_CONN_HANDLE_UNSET)
+ 				hci_conn_del(child);
+ 		}
+ 
+@@ -1113,6 +1115,7 @@ static void hci_conn_unlink(struct hci_conn *conn)
+ 	list_del_rcu(&conn->link->list);
+ 	synchronize_rcu();
+ 
++	hci_conn_drop(conn->parent);
+ 	hci_conn_put(conn->parent);
+ 	conn->parent = NULL;
+ 
+@@ -1126,12 +1129,13 @@ void hci_conn_del(struct hci_conn *conn)
+ 
+ 	BT_DBG("%s hcon %p handle %d", hdev->name, conn, conn->handle);
+ 
++	hci_conn_unlink(conn);
++
+ 	cancel_delayed_work_sync(&conn->disc_work);
+ 	cancel_delayed_work_sync(&conn->auto_accept_work);
+ 	cancel_delayed_work_sync(&conn->idle_work);
+ 
+ 	if (conn->type == ACL_LINK) {
+-		hci_conn_unlink(conn);
+ 		/* Unacked frames */
+ 		hdev->acl_cnt += conn->sent;
+ 	} else if (conn->type == LE_LINK) {
+@@ -1142,13 +1146,6 @@ void hci_conn_del(struct hci_conn *conn)
+ 		else
+ 			hdev->acl_cnt += conn->sent;
+ 	} else {
+-		struct hci_conn *acl = conn->parent;
+-
+-		if (acl) {
+-			hci_conn_unlink(conn);
+-			hci_conn_drop(acl);
+-		}
+-
+ 		/* Unacked ISO frames */
+ 		if (conn->type == ISO_LINK) {
+ 			if (hdev->iso_pkts)
+@@ -2485,12 +2482,6 @@ void hci_conn_hash_flush(struct hci_dev *hdev)
+ 						list)) != NULL) {
+ 		conn->state = BT_CLOSED;
+ 		hci_disconn_cfm(conn, HCI_ERROR_LOCAL_HOST_TERM);
+-
+-		/* Unlink before deleting otherwise it is possible that
+-		 * hci_conn_del removes the link which may cause the list to
+-		 * contain items already freed.
+-		 */
+-		hci_conn_unlink(conn);
+ 		hci_conn_del(conn);
+ 	}
+ }

commit a2ac591cb4d83e1f2d4b4adb3c14b2c79764650a
+Author: Ruihan Li 
+Date:   Wed May 3 21:39:36 2023 +0800
+
+    Bluetooth: Fix UAF in hci_conn_hash_flush again
+    
+    Commit 06149746e720 ("Bluetooth: hci_conn: Add support for linking
+    multiple hcon") reintroduced a previously fixed bug [1] ("KASAN:
+    slab-use-after-free Read in hci_conn_hash_flush"). This bug was
+    originally fixed by commit 5dc7d23e167e ("Bluetooth: hci_conn: Fix
+    possible UAF").
+    
+    The hci_conn_unlink function was added to avoid invalidating the link
+    traversal caused by successive hci_conn_del operations releasing extra
+    connections. However, currently hci_conn_unlink itself also releases
+    extra connections, resulted in the reintroduced bug.
+    
+    This patch follows a more robust solution for cleaning up all
+    connections, by repeatedly removing the first connection until there are
+    none left. This approach does not rely on the inner workings of
+    hci_conn_del and ensures proper cleanup of all connections.
+    
+    Meanwhile, we need to make sure that hci_conn_del never fails. Indeed it
+    doesn't, as it now always returns zero. To make this a bit clearer, this
+    patch also changes its return type to void.
+    
+    Reported-by: syzbot+8bb72f86fc823817bc5d@syzkaller.appspotmail.com
+    Closes: https://lore.kernel.org/linux-bluetooth/000000000000aa920505f60d25ad@google.com/
+    Fixes: 06149746e720 ("Bluetooth: hci_conn: Add support for linking multiple hcon")
+    Signed-off-by: Ruihan Li 
+    Co-developed-by: Luiz Augusto von Dentz 
+    Signed-off-by: Luiz Augusto von Dentz 
+
+diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
+index a6c8aee2f256..8baf34639939 100644
+--- a/include/net/bluetooth/hci_core.h
++++ b/include/net/bluetooth/hci_core.h
+@@ -1327,7 +1327,7 @@ int hci_le_create_cis(struct hci_conn *conn);
+ 
+ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
+ 			      u8 role);
+-int hci_conn_del(struct hci_conn *conn);
++void hci_conn_del(struct hci_conn *conn);
+ void hci_conn_hash_flush(struct hci_dev *hdev);
+ void hci_conn_check_pending(struct hci_dev *hdev);
+ 
+diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
+index 44d0643fc681..ce588359b290 100644
+--- a/net/bluetooth/hci_conn.c
++++ b/net/bluetooth/hci_conn.c
+@@ -1088,6 +1088,14 @@ static void hci_conn_unlink(struct hci_conn *conn)
+ 
+ 			hci_conn_unlink(child);
+ 
++			/* If hdev is down it means
++			 * hci_dev_close_sync/hci_conn_hash_flush is in progress
++			 * and links don't need to be cleanup as all connections
++			 * would be cleanup.
++			 */
++			if (!test_bit(HCI_UP, &hdev->flags))
++				continue;
++
+ 			/* Due to race, SCO connection might be not established
+ 			 * yet at this point. Delete it now, otherwise it is
+ 			 * possible for it to be stuck and can't be deleted.
+@@ -1112,7 +1120,7 @@ static void hci_conn_unlink(struct hci_conn *conn)
+ 	conn->link = NULL;
+ }
+ 
+-int hci_conn_del(struct hci_conn *conn)
++void hci_conn_del(struct hci_conn *conn)
+ {
+ 	struct hci_dev *hdev = conn->hdev;
+ 
+@@ -1163,8 +1171,6 @@ int hci_conn_del(struct hci_conn *conn)
+ 	 * rest of hci_conn_del.
+ 	 */
+ 	hci_conn_cleanup(conn);
+-
+-	return 0;
+ }
+ 
+ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src, uint8_t src_type)
+@@ -2465,22 +2471,27 @@ void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active)
+ /* Drop all connection on the device */
+ void hci_conn_hash_flush(struct hci_dev *hdev)
+ {
+-	struct hci_conn_hash *h = &hdev->conn_hash;
+-	struct hci_conn *c, *n;
++	struct list_head *head = &hdev->conn_hash.list;
++	struct hci_conn *conn;
+ 
+ 	BT_DBG("hdev %s", hdev->name);
+ 
+-	list_for_each_entry_safe(c, n, &h->list, list) {
+-		c->state = BT_CLOSED;
+-
+-		hci_disconn_cfm(c, HCI_ERROR_LOCAL_HOST_TERM);
++	/* We should not traverse the list here, because hci_conn_del
++	 * can remove extra links, which may cause the list traversal
++	 * to hit items that have already been released.
++	 */
++	while ((conn = list_first_entry_or_null(head,
++						struct hci_conn,
++						list)) != NULL) {
++		conn->state = BT_CLOSED;
++		hci_disconn_cfm(conn, HCI_ERROR_LOCAL_HOST_TERM);
+ 
+ 		/* Unlink before deleting otherwise it is possible that
+ 		 * hci_conn_del removes the link which may cause the list to
+ 		 * contain items already freed.
+ 		 */
+-		hci_conn_unlink(c);
+-		hci_conn_del(c);
++		hci_conn_unlink(conn);
++		hci_conn_del(conn);
+ 	}
+ }
+ 

commit 2910431ab0e500dfc5df12299bb15eef0f30b43e
+Author: Ruihan Li 
+Date:   Wed May 3 21:39:35 2023 +0800
+
+    Bluetooth: Refcnt drop must be placed last in hci_conn_unlink
+    
+    If hci_conn_put(conn->parent) reduces conn->parent's reference count to
+    zero, it can immediately deallocate conn->parent. At the same time,
+    conn->link->list has its head in conn->parent, causing use-after-free
+    problems in the latter list_del_rcu(&conn->link->list).
+    
+    This problem can be easily solved by reordering the two operations,
+    i.e., first performing the list removal with list_del_rcu and then
+    decreasing the refcnt with hci_conn_put.
+    
+    Reported-by: Luiz Augusto von Dentz 
+    Closes: https://lore.kernel.org/linux-bluetooth/CABBYNZ+1kce8_RJrLNOXd_8=Mdpb=2bx4Nto-hFORk=qiOkoCg@mail.gmail.com/
+    Fixes: 06149746e720 ("Bluetooth: hci_conn: Add support for linking multiple hcon")
+    Signed-off-by: Ruihan Li 
+    Signed-off-by: Luiz Augusto von Dentz 
+
+diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
+index 70e1655a9df6..44d0643fc681 100644
+--- a/net/bluetooth/hci_conn.c
++++ b/net/bluetooth/hci_conn.c
+@@ -1102,12 +1102,12 @@ static void hci_conn_unlink(struct hci_conn *conn)
+ 	if (!conn->link)
+ 		return;
+ 
+-	hci_conn_put(conn->parent);
+-	conn->parent = NULL;
+-
+ 	list_del_rcu(&conn->link->list);
+ 	synchronize_rcu();
+ 
++	hci_conn_put(conn->parent);
++	conn->parent = NULL;
++
+ 	kfree(conn->link);
+ 	conn->link = NULL;
+ }

commit ca1fd42e7dbfcb34890ffbf1f2f4b356776dab6f
+Author: Ruihan Li 
+Date:   Wed May 3 21:39:34 2023 +0800
+
+    Bluetooth: Fix potential double free caused by hci_conn_unlink
+    
+    The hci_conn_unlink function is being called by hci_conn_del, which
+    means it should not call hci_conn_del with the input parameter conn
+    again. If it does, conn may have already been released when
+    hci_conn_unlink returns, leading to potential UAF and double-free
+    issues.
+    
+    This patch resolves the problem by modifying hci_conn_unlink to release
+    only conn's child links when necessary, but never release conn itself.
+    
+    Reported-by: syzbot+690b90b14f14f43f4688@syzkaller.appspotmail.com
+    Closes: https://lore.kernel.org/linux-bluetooth/000000000000484a8205faafe216@google.com/
+    Fixes: 06149746e720 ("Bluetooth: hci_conn: Add support for linking multiple hcon")
+    Signed-off-by: Ruihan Li 
+    Signed-off-by: Luiz Augusto von Dentz 
+    Reported-by: syzbot+690b90b14f14f43f4688@syzkaller.appspotmail.com
+    Reported-by: Luiz Augusto von Dentz 
+    Reported-by: syzbot+8bb72f86fc823817bc5d@syzkaller.appspotmail.com
+
+diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
+index 640b951bf40a..70e1655a9df6 100644
+--- a/net/bluetooth/hci_conn.c
++++ b/net/bluetooth/hci_conn.c
+@@ -1083,8 +1083,18 @@ static void hci_conn_unlink(struct hci_conn *conn)
+ 	if (!conn->parent) {
+ 		struct hci_link *link, *t;
+ 
+-		list_for_each_entry_safe(link, t, &conn->link_list, list)
+-			hci_conn_unlink(link->conn);
++		list_for_each_entry_safe(link, t, &conn->link_list, list) {
++			struct hci_conn *child = link->conn;
++
++			hci_conn_unlink(child);
++
++			/* Due to race, SCO connection might be not established
++			 * yet at this point. Delete it now, otherwise it is
++			 * possible for it to be stuck and can't be deleted.
++			 */
++			if (child->handle == HCI_CONN_HANDLE_UNSET)
++				hci_conn_del(child);
++		}
+ 
+ 		return;
+ 	}
+@@ -1100,13 +1110,6 @@ static void hci_conn_unlink(struct hci_conn *conn)
+ 
+ 	kfree(conn->link);
+ 	conn->link = NULL;
+-
+-	/* Due to race, SCO connection might be not established
+-	 * yet at this point. Delete it now, otherwise it is
+-	 * possible for it to be stuck and can't be deleted.
+-	 */
+-	if (conn->handle == HCI_CONN_HANDLE_UNSET)
+-		hci_conn_del(conn);
+ }
+ 
+ int hci_conn_del(struct hci_conn *conn)

commit 1a261a6e10e80cd7c69c3f5bdf47cd41f928fd08
+Author: Ruihan Li 
+Date:   Tue Apr 25 00:21:10 2023 +0800
+
+    scripts: Remove ICC-related dead code
+    
+    Intel compiler support has already been completely removed in commit
+    95207db8166a ("Remove Intel compiler support").  However, it appears
+    that there is still some ICC-related code in scripts/cc-version.sh.
+    There is no harm in leaving the code as it is, but removing the dead
+    code makes the codebase a bit cleaner.
+    
+    Hopefully all ICC-related stuff in the build scripts will be removed
+    after this commit, given the grep output as below:
+    
+            (linux/scripts) $ grep -i -w -R 'icc'
+            cc-version.sh:ICC)
+            cc-version.sh:  min_version=$($min_tool_version icc)
+            dtc/include-prefixes/arm64/qcom/sm6350.dtsi:#include 
+    
+    Fixes: 95207db8166a ("Remove Intel compiler support")
+    Signed-off-by: Ruihan Li 
+    Reviewed-by: Nick Desaulniers 
+    Reviewed-by: Nathan Chancellor 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/scripts/cc-version.sh b/scripts/cc-version.sh
+index 0573c92e841d..a7e28b6a514e 100755
+--- a/scripts/cc-version.sh
++++ b/scripts/cc-version.sh
+@@ -45,10 +45,6 @@ Clang)
+ 	version=$2.$3.$4
+ 	min_version=$($min_tool_version llvm)
+ 	;;
+-ICC)
+-	version=$(($2 / 100)).$(($2 % 100)).$3
+-	min_version=$($min_tool_version icc)
+-	;;
+ *)
+ 	echo "$orig_args: unknown C compiler" >&2
+ 	exit 1

commit 25c150ac103a4ebeed0319994c742a90634ddf18
+Author: Ruihan Li 
+Date:   Sun Apr 16 16:14:04 2023 +0800
+
+    bluetooth: Perform careful capability checks in hci_sock_ioctl()
+    
+    Previously, capability was checked using capable(), which verified that the
+    caller of the ioctl system call had the required capability. In addition,
+    the result of the check would be stored in the HCI_SOCK_TRUSTED flag,
+    making it persistent for the socket.
+    
+    However, malicious programs can abuse this approach by deliberately sharing
+    an HCI socket with a privileged task. The HCI socket will be marked as
+    trusted when the privileged task occasionally makes an ioctl call.
+    
+    This problem can be solved by using sk_capable() to check capability, which
+    ensures that not only the current task but also the socket opener has the
+    specified capability, thus reducing the risk of privilege escalation
+    through the previously identified vulnerability.
+    
+    Cc: stable@vger.kernel.org
+    Fixes: f81f5b2db869 ("Bluetooth: Send control open and close messages for HCI raw sockets")
+    Signed-off-by: Ruihan Li 
+    Signed-off-by: Luiz Augusto von Dentz 
+
+diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
+index 8d8950101cee..1d249d839819 100644
+--- a/net/bluetooth/hci_sock.c
++++ b/net/bluetooth/hci_sock.c
+@@ -1031,7 +1031,14 @@ static int hci_sock_ioctl(struct socket *sock, unsigned int cmd,
+ 	if (hci_sock_gen_cookie(sk)) {
+ 		struct sk_buff *skb;
+ 
+-		if (capable(CAP_NET_ADMIN))
++		/* Perform careful checks before setting the HCI_SOCK_TRUSTED
++		 * flag. Make sure that not only the current task but also
++		 * the socket opener has the required capability, since
++		 * privileged programs can be tricked into making ioctl calls
++		 * on HCI sockets, and the socket should not be marked as
++		 * trusted simply because the ioctl caller is privileged.
++		 */
++		if (sk_capable(sk, CAP_NET_ADMIN))
+ 			hci_sock_set_flag(sk, HCI_SOCK_TRUSTED);
+ 
+ 		/* Send event to monitor */

commit 000c2fa2c144c499c881a101819cf1936a1f7cf2
+Author: Ruihan Li 
+Date:   Sun Apr 16 16:02:51 2023 +0800
+
+    bluetooth: Add cmd validity checks at the start of hci_sock_ioctl()
+    
+    Previously, channel open messages were always sent to monitors on the first
+    ioctl() call for unbound HCI sockets, even if the command and arguments
+    were completely invalid. This can leave an exploitable hole with the abuse
+    of invalid ioctl calls.
+    
+    This commit hardens the ioctl processing logic by first checking if the
+    command is valid, and immediately returning with an ENOIOCTLCMD error code
+    if it is not. This ensures that ioctl calls with invalid commands are free
+    of side effects, and increases the difficulty of further exploitation by
+    forcing exploitation to find a way to pass a valid command first.
+    
+    Signed-off-by: Ruihan Li 
+    Co-developed-by: Marcel Holtmann 
+    Signed-off-by: Marcel Holtmann 
+    Signed-off-by: Luiz Augusto von Dentz 
+
+diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
+index 06581223238c..8d8950101cee 100644
+--- a/net/bluetooth/hci_sock.c
++++ b/net/bluetooth/hci_sock.c
+@@ -987,6 +987,34 @@ static int hci_sock_ioctl(struct socket *sock, unsigned int cmd,
+ 
+ 	BT_DBG("cmd %x arg %lx", cmd, arg);
+ 
++	/* Make sure the cmd is valid before doing anything */
++	switch (cmd) {
++	case HCIGETDEVLIST:
++	case HCIGETDEVINFO:
++	case HCIGETCONNLIST:
++	case HCIDEVUP:
++	case HCIDEVDOWN:
++	case HCIDEVRESET:
++	case HCIDEVRESTAT:
++	case HCISETSCAN:
++	case HCISETAUTH:
++	case HCISETENCRYPT:
++	case HCISETPTYPE:
++	case HCISETLINKPOL:
++	case HCISETLINKMODE:
++	case HCISETACLMTU:
++	case HCISETSCOMTU:
++	case HCIINQUIRY:
++	case HCISETRAW:
++	case HCIGETCONNINFO:
++	case HCIGETAUTHINFO:
++	case HCIBLOCKADDR:
++	case HCIUNBLOCKADDR:
++		break;
++	default:
++		return -ENOIOCTLCMD;
++	}
++
+ 	lock_sock(sk);
+ 
+ 	if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) {

commit eb4c0788964730d12e8dd520bd8f5217ca48321c
+Author: Yongzhi Liu 
+Date:   Thu May 19 05:09:48 2022 -0700
+
+    hv_netvsc: Fix potential dereference of NULL pointer
+    
+    The return value of netvsc_devinfo_get()
+    needs to be checked to avoid use of NULL
+    pointer in case of an allocation failure.
+    
+    Fixes: 0efeea5fb153 ("hv_netvsc: Add the support of hibernation")
+    Signed-off-by: Yongzhi Liu 
+    Reviewed-by: Haiyang Zhang 
+    Link: https://lore.kernel.org/r/1652962188-129281-1-git-send-email-lyz_cs@pku.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
+index fde1c492ca02..b1dece6b9698 100644
+--- a/drivers/net/hyperv/netvsc_drv.c
++++ b/drivers/net/hyperv/netvsc_drv.c
+@@ -2671,7 +2671,10 @@ static int netvsc_suspend(struct hv_device *dev)
+ 
+ 	/* Save the current config info */
+ 	ndev_ctx->saved_netvsc_dev_info = netvsc_devinfo_get(nvdev);
+-
++	if (!ndev_ctx->saved_netvsc_dev_info) {
++		ret = -ENOMEM;
++		goto out;
++	}
+ 	ret = netvsc_detach(net, nvdev);
+ out:
+ 	rtnl_unlock();

commit 087f9c3f2309ed183f7e4b85ae57121d8663224d
+Author: Yongzhi Liu 
+Date:   Fri Mar 11 09:06:01 2022 -0800
+
+    RDMA/mlx5: Fix memory leak in error flow for subscribe event routine
+    
+    In case the second xa_insert() fails, the obj_event is not released.  Fix
+    the error unwind flow to free that memory to avoid a memory leak.
+    
+    Fixes: 759738537142 ("IB/mlx5: Enable subscription for device events over DEVX")
+    Link: https://lore.kernel.org/r/1647018361-18266-1-git-send-email-lyz_cs@pku.edu.cn
+    Signed-off-by: Yongzhi Liu 
+    Signed-off-by: Jason Gunthorpe 
+
+diff --git a/drivers/infiniband/hw/mlx5/devx.c b/drivers/infiniband/hw/mlx5/devx.c
+index 08b7f6bc56c3..15c0884d1f49 100644
+--- a/drivers/infiniband/hw/mlx5/devx.c
++++ b/drivers/infiniband/hw/mlx5/devx.c
+@@ -1886,8 +1886,10 @@ subscribe_event_xa_alloc(struct mlx5_devx_event_table *devx_event_table,
+ 				key_level2,
+ 				obj_event,
+ 				GFP_KERNEL);
+-		if (err)
++		if (err) {
++			kfree(obj_event);
+ 			return err;
++		}
+ 		INIT_LIST_HEAD(&obj_event->obj_sub_list);
+ 	}
+ 

commit 455896c53d5b803733ddd84e1bf8a430644439b6
+Author: Yongzhi Liu 
+Date:   Sat Jan 15 21:34:56 2022 -0800
+
+    dmaengine: shdma: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_() increments the runtime PM usage counter even
+    when it returns an error code, thus a matching decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Yongzhi Liu 
+    Link: https://lore.kernel.org/r/1642311296-87020-1-git-send-email-lyz_cs@pku.edu.cn
+    Signed-off-by: Vinod Koul 
+
+diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c
+index 158e5e7defae..b26ed690f03c 100644
+--- a/drivers/dma/sh/shdma-base.c
++++ b/drivers/dma/sh/shdma-base.c
+@@ -115,8 +115,10 @@ static dma_cookie_t shdma_tx_submit(struct dma_async_tx_descriptor *tx)
+ 		ret = pm_runtime_get(schan->dev);
+ 
+ 		spin_unlock_irq(&schan->chan_lock);
+-		if (ret < 0)
++		if (ret < 0) {
+ 			dev_err(schan->dev, "%s(): GET = %d\n", __func__, ret);
++			pm_runtime_put(schan->dev);
++		}
+ 
+ 		pm_runtime_barrier(schan->dev);
+ 

commit e57c1a3bd5e8e0c7181f65ae55581f0236a8f284
+Author: Yongzhi Liu 
+Date:   Fri Jan 28 05:41:02 2022 -0800
+
+    drm/v3d: fix missing unlock
+    
+    [why]
+    Unlock is needed on the error handling path to prevent dead lock.
+    v3d_submit_cl_ioctl and v3d_submit_csd_ioctl is missing unlock.
+    
+    [how]
+    Fix this by changing goto target on the error handling path. So
+    changing the goto to target an error handling path
+    that includes drm_gem_unlock reservations.
+    
+    Signed-off-by: Yongzhi Liu 
+    Reviewed-by: Melissa Wen 
+    Signed-off-by: Melissa Wen 
+    Link: https://patchwork.freedesktop.org/patch/msgid/1643377262-109975-1-git-send-email-lyz_cs@pku.edu.cn
+
+diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c
+index c7ed2e1cbab6..92bc0faee84f 100644
+--- a/drivers/gpu/drm/v3d/v3d_gem.c
++++ b/drivers/gpu/drm/v3d/v3d_gem.c
+@@ -798,7 +798,7 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
+ 
+ 		if (!render->base.perfmon) {
+ 			ret = -ENOENT;
+-			goto fail;
++			goto fail_perfmon;
+ 		}
+ 	}
+ 
+@@ -847,6 +847,7 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
+ 
+ fail_unreserve:
+ 	mutex_unlock(&v3d->sched_lock);
++fail_perfmon:
+ 	drm_gem_unlock_reservations(last_job->bo,
+ 				    last_job->bo_count, &acquire_ctx);
+ fail:
+@@ -1027,7 +1028,7 @@ v3d_submit_csd_ioctl(struct drm_device *dev, void *data,
+ 						     args->perfmon_id);
+ 		if (!job->base.perfmon) {
+ 			ret = -ENOENT;
+-			goto fail;
++			goto fail_perfmon;
+ 		}
+ 	}
+ 
+@@ -1056,6 +1057,7 @@ v3d_submit_csd_ioctl(struct drm_device *dev, void *data,
+ 
+ fail_unreserve:
+ 	mutex_unlock(&v3d->sched_lock);
++fail_perfmon:
+ 	drm_gem_unlock_reservations(clean_job->bo, clean_job->bo_count,
+ 				    &acquire_ctx);
+ fail:

commit 46f47807738441e354873546dde0b000106c068a
+Author: Yongzhi Liu 
+Date:   Sun Jan 23 23:20:35 2022 -0800
+
+    drm/bridge: Add missing pm_runtime_put_sync
+    
+    pm_runtime_get_sync() will increase the rumtime PM counter
+    even when it returns an error. Thus a pairing decrement is needed
+    to prevent refcount leak. Fix this by replacing this API with
+    pm_runtime_resume_and_get(), which will not change the runtime
+    PM counter on error. Besides, a matching decrement is needed
+    on the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Yongzhi Liu 
+    Reviewed-by: Laurent Pinchart 
+    Signed-off-by: Robert Foss 
+    Link: https://patchwork.freedesktop.org/patch/msgid/1643008835-73961-1-git-send-email-lyz_cs@pku.edu.cn
+
+diff --git a/drivers/gpu/drm/bridge/nwl-dsi.c b/drivers/gpu/drm/bridge/nwl-dsi.c
+index 9282e61dfbf0..30aacd939dc3 100644
+--- a/drivers/gpu/drm/bridge/nwl-dsi.c
++++ b/drivers/gpu/drm/bridge/nwl-dsi.c
+@@ -862,18 +862,19 @@ nwl_dsi_bridge_mode_set(struct drm_bridge *bridge,
+ 	memcpy(&dsi->mode, adjusted_mode, sizeof(dsi->mode));
+ 	drm_mode_debug_printmodeline(adjusted_mode);
+ 
+-	pm_runtime_get_sync(dev);
++	if (pm_runtime_resume_and_get(dev) < 0)
++		return;
+ 
+ 	if (clk_prepare_enable(dsi->lcdif_clk) < 0)
+-		return;
++		goto runtime_put;
+ 	if (clk_prepare_enable(dsi->core_clk) < 0)
+-		return;
++		goto runtime_put;
+ 
+ 	/* Step 1 from DSI reset-out instructions */
+ 	ret = reset_control_deassert(dsi->rst_pclk);
+ 	if (ret < 0) {
+ 		DRM_DEV_ERROR(dev, "Failed to deassert PCLK: %d\n", ret);
+-		return;
++		goto runtime_put;
+ 	}
+ 
+ 	/* Step 2 from DSI reset-out instructions */
+@@ -883,13 +884,18 @@ nwl_dsi_bridge_mode_set(struct drm_bridge *bridge,
+ 	ret = reset_control_deassert(dsi->rst_esc);
+ 	if (ret < 0) {
+ 		DRM_DEV_ERROR(dev, "Failed to deassert ESC: %d\n", ret);
+-		return;
++		goto runtime_put;
+ 	}
+ 	ret = reset_control_deassert(dsi->rst_byte);
+ 	if (ret < 0) {
+ 		DRM_DEV_ERROR(dev, "Failed to deassert BYTE: %d\n", ret);
+-		return;
++		goto runtime_put;
+ 	}
++
++	return;
++
++runtime_put:
++	pm_runtime_put_sync(dev);
+ }
+ 
+ static void

commit 5d5c6dba2b43e28845d7d7ed32a36802329a5f52
+Author: Yongzhi Liu 
+Date:   Fri Jan 21 11:26:13 2022 +0000
+
+    drm/amd/display: Fix memory leak
+    
+    [why]
+    Resource release is needed on the error handling path
+    to prevent memory leak.
+    
+    [how]
+    Fix this by adding kfree on the error handling path.
+    
+    Reviewed-by: Harry Wentland 
+    Signed-off-by: Yongzhi Liu 
+    Signed-off-by: Alex Deucher 
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+index 26719efa5396..12d437d9a0e4 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+@@ -227,8 +227,10 @@ static ssize_t dp_link_settings_read(struct file *f, char __user *buf,
+ 			break;
+ 
+ 		r = put_user(*(rd_buf + result), buf);
+-		if (r)
++		if (r) {
++			kfree(rd_buf);
+ 			return r; /* r = -EFAULT */
++		}
+ 
+ 		buf += 1;
+ 		size -= 1;
+@@ -389,8 +391,10 @@ static ssize_t dp_phy_settings_read(struct file *f, char __user *buf,
+ 			break;
+ 
+ 		r = put_user((*(rd_buf + result)), buf);
+-		if (r)
++		if (r) {
++			kfree(rd_buf);
+ 			return r; /* r = -EFAULT */
++		}
+ 
+ 		buf += 1;
+ 		size -= 1;
+@@ -1359,8 +1363,10 @@ static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf,
+ 				break;
+ 	}
+ 
+-	if (!pipe_ctx)
++	if (!pipe_ctx) {
++		kfree(rd_buf);
+ 		return -ENXIO;
++	}
+ 
+ 	dsc = pipe_ctx->stream_res.dsc;
+ 	if (dsc)
+@@ -1376,8 +1382,10 @@ static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf,
+ 			break;
+ 
+ 		r = put_user(*(rd_buf + result), buf);
+-		if (r)
++		if (r) {
++			kfree(rd_buf);
+ 			return r; /* r = -EFAULT */
++		}
+ 
+ 		buf += 1;
+ 		size -= 1;
+@@ -1546,8 +1554,10 @@ static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf,
+ 				break;
+ 	}
+ 
+-	if (!pipe_ctx)
++	if (!pipe_ctx) {
++		kfree(rd_buf);
+ 		return -ENXIO;
++	}
+ 
+ 	dsc = pipe_ctx->stream_res.dsc;
+ 	if (dsc)
+@@ -1563,8 +1573,10 @@ static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf,
+ 			break;
+ 
+ 		r = put_user(*(rd_buf + result), buf);
+-		if (r)
++		if (r) {
++			kfree(rd_buf);
+ 			return r; /* r = -EFAULT */
++		}
+ 
+ 		buf += 1;
+ 		size -= 1;
+@@ -1731,8 +1743,10 @@ static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf,
+ 				break;
+ 	}
+ 
+-	if (!pipe_ctx)
++	if (!pipe_ctx) {
++		kfree(rd_buf);
+ 		return -ENXIO;
++	}
+ 
+ 	dsc = pipe_ctx->stream_res.dsc;
+ 	if (dsc)
+@@ -1748,8 +1762,10 @@ static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf,
+ 			break;
+ 
+ 		r = put_user(*(rd_buf + result), buf);
+-		if (r)
++		if (r) {
++			kfree(rd_buf);
+ 			return r; /* r = -EFAULT */
++		}
+ 
+ 		buf += 1;
+ 		size -= 1;
+@@ -1912,8 +1928,10 @@ static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf,
+ 				break;
+ 	}
+ 
+-	if (!pipe_ctx)
++	if (!pipe_ctx) {
++		kfree(rd_buf);
+ 		return -ENXIO;
++	}
+ 
+ 	dsc = pipe_ctx->stream_res.dsc;
+ 	if (dsc)
+@@ -1929,8 +1947,10 @@ static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf,
+ 			break;
+ 
+ 		r = put_user(*(rd_buf + result), buf);
+-		if (r)
++		if (r) {
++			kfree(rd_buf);
+ 			return r; /* r = -EFAULT */
++		}
+ 
+ 		buf += 1;
+ 		size -= 1;
+@@ -2088,8 +2108,10 @@ static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf,
+ 				break;
+ 	}
+ 
+-	if (!pipe_ctx)
++	if (!pipe_ctx) {
++		kfree(rd_buf);
+ 		return -ENXIO;
++	}
+ 
+ 	dsc = pipe_ctx->stream_res.dsc;
+ 	if (dsc)
+@@ -2105,8 +2127,10 @@ static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf,
+ 			break;
+ 
+ 		r = put_user(*(rd_buf + result), buf);
+-		if (r)
++		if (r) {
++			kfree(rd_buf);
+ 			return r; /* r = -EFAULT */
++		}
+ 
+ 		buf += 1;
+ 		size -= 1;
+@@ -2145,8 +2169,10 @@ static ssize_t dp_dsc_pic_height_read(struct file *f, char __user *buf,
+ 				break;
+ 	}
+ 
+-	if (!pipe_ctx)
++	if (!pipe_ctx) {
++		kfree(rd_buf);
+ 		return -ENXIO;
++	}
+ 
+ 	dsc = pipe_ctx->stream_res.dsc;
+ 	if (dsc)
+@@ -2162,8 +2188,10 @@ static ssize_t dp_dsc_pic_height_read(struct file *f, char __user *buf,
+ 			break;
+ 
+ 		r = put_user(*(rd_buf + result), buf);
+-		if (r)
++		if (r) {
++			kfree(rd_buf);
+ 			return r; /* r = -EFAULT */
++		}
+ 
+ 		buf += 1;
+ 		size -= 1;
+@@ -2217,8 +2245,10 @@ static ssize_t dp_dsc_chunk_size_read(struct file *f, char __user *buf,
+ 				break;
+ 	}
+ 
+-	if (!pipe_ctx)
++	if (!pipe_ctx) {
++		kfree(rd_buf);
+ 		return -ENXIO;
++	}
+ 
+ 	dsc = pipe_ctx->stream_res.dsc;
+ 	if (dsc)
+@@ -2234,8 +2264,10 @@ static ssize_t dp_dsc_chunk_size_read(struct file *f, char __user *buf,
+ 			break;
+ 
+ 		r = put_user(*(rd_buf + result), buf);
+-		if (r)
++		if (r) {
++			kfree(rd_buf);
+ 			return r; /* r = -EFAULT */
++		}
+ 
+ 		buf += 1;
+ 		size -= 1;
+@@ -2289,8 +2321,10 @@ static ssize_t dp_dsc_slice_bpg_offset_read(struct file *f, char __user *buf,
+ 				break;
+ 	}
+ 
+-	if (!pipe_ctx)
++	if (!pipe_ctx) {
++		kfree(rd_buf);
+ 		return -ENXIO;
++	}
+ 
+ 	dsc = pipe_ctx->stream_res.dsc;
+ 	if (dsc)
+@@ -2306,8 +2340,10 @@ static ssize_t dp_dsc_slice_bpg_offset_read(struct file *f, char __user *buf,
+ 			break;
+ 
+ 		r = put_user(*(rd_buf + result), buf);
+-		if (r)
++		if (r) {
++			kfree(rd_buf);
+ 			return r; /* r = -EFAULT */
++		}
+ 
+ 		buf += 1;
+ 		size -= 1;
+@@ -3459,8 +3495,10 @@ static ssize_t dcc_en_bits_read(
+ 	dc->hwss.get_dcc_en_bits(dc, dcc_en_bits);
+ 
+ 	rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);
+-	if (!rd_buf)
++	if (!rd_buf) {
++		kfree(dcc_en_bits);
+ 		return -ENOMEM;
++	}
+ 
+ 	for (i = 0; i < num_pipes; i++)
+ 		offset += snprintf(rd_buf + offset, rd_buf_size - offset,
+@@ -3473,8 +3511,10 @@ static ssize_t dcc_en_bits_read(
+ 		if (*pos >= rd_buf_size)
+ 			break;
+ 		r = put_user(*(rd_buf + result), buf);
+-		if (r)
++		if (r) {
++			kfree(rd_buf);
+ 			return r; /* r = -EFAULT */
++		}
+ 		buf += 1;
+ 		size -= 1;
+ 		*pos += 1;

commit 4bd8dd0d61f961e6c13cc118d4ebbdba57f8561f
+Author: Yongzhi Liu 
+Date:   Tue Jan 18 15:11:51 2022 -0500
+
+    drm/amdgpu: Add missing pm_runtime_put_autosuspend
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code, thus a matching decrement is needed
+    on the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Yongzhi Liu 
+    Reviewed-by: Lijo Lazar 
+    Signed-off-by: Alex Deucher 
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
+index 9aea1cc5b27e..4b950de9bf66 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
+@@ -1120,8 +1120,10 @@ static ssize_t amdgpu_debugfs_gfxoff_read(struct file *f, char __user *buf,
+ 		return -EINVAL;
+ 
+ 	r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
+-	if (r < 0)
++	if (r < 0) {
++		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
+ 		return r;
++	}
+ 
+ 	while (size) {
+ 		uint32_t value;

commit 5cf069f910c5c87055fb970a8103f0ad38ba7143
+Author: Liu Junqi 
+Date:   Thu Nov 25 12:47:29 2021 +0800
+
+    staging: unisys: visornic: removed a blank line at the end of function
+    
+    Removed a blank line at the end of function to clear checkpatch warning
+    and make it more like typical coding style.
+    
+    Signed-off-by: Liu Junqi 
+    Link: https://lore.kernel.org/r/20211125044729.594727-3-liujunqi@pku.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c
+index aec0db28126d..643432458105 100644
+--- a/drivers/staging/unisys/visornic/visornic_main.c
++++ b/drivers/staging/unisys/visornic/visornic_main.c
+@@ -1764,7 +1764,6 @@ static void visornic_channel_interrupt(struct visor_device *dev)
+ 		napi_schedule(&devdata->napi);
+ 
+ 	atomic_set(&devdata->interrupt_rcvd, 0);
+-
+ }
+ 
+ /* visornic_probe - probe function for visornic devices

commit 4e4437d09cbeb1babbf7986414ff9f23679c76a6
+Author: Liu Junqi 
+Date:   Thu Nov 25 12:47:28 2021 +0800
+
+    staging: unisys: visornic: reindent to avoid '(' at the end of line
+    
+    A change to make the code more like typical coding style.
+    
+    Signed-off-by: Liu Junqi 
+    Link: https://lore.kernel.org/r/20211125044729.594727-2-liujunqi@pku.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c
+index 18be80648825..aec0db28126d 100644
+--- a/drivers/staging/unisys/visornic/visornic_main.c
++++ b/drivers/staging/unisys/visornic/visornic_main.c
+@@ -1759,9 +1759,8 @@ static void visornic_channel_interrupt(struct visor_device *dev)
+ 	if (!devdata)
+ 		return;
+ 
+-	if (!visorchannel_signalempty(
+-				   devdata->dev->visorchannel,
+-				   IOCHAN_FROM_IOPART))
++	if (!visorchannel_signalempty(devdata->dev->visorchannel,
++				      IOCHAN_FROM_IOPART))
+ 		napi_schedule(&devdata->napi);
+ 
+ 	atomic_set(&devdata->interrupt_rcvd, 0);

commit a70fc7d0d1beb4c6d3ce1eb1a18624fa59538f40
+Author: Liu Junqi 
+Date:   Thu Nov 25 12:47:27 2021 +0800
+
+    staging: unisys: visornic: fixed a typo cant -> can't
+    
+    Fixed a typo: cant -> can't in visornic_main.c.
+    
+    Signed-off-by: Liu Junqi 
+    Link: https://lore.kernel.org/r/20211125044729.594727-1-liujunqi@pku.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c
+index 62cd9b783732..18be80648825 100644
+--- a/drivers/staging/unisys/visornic/visornic_main.c
++++ b/drivers/staging/unisys/visornic/visornic_main.c
+@@ -1590,7 +1590,7 @@ static void send_rcv_posts_if_needed(struct visornic_devdata *devdata)
+ 	netdev = devdata->netdev;
+ 	rcv_bufs_allocated = 0;
+ 	/* this code is trying to prevent getting stuck here forever,
+-	 * but still retry it if you cant allocate them all this time.
++	 * but still retry it if you can't allocate them all this time.
+ 	 */
+ 	cur_num_rcv_bufs_to_alloc = devdata->num_rcv_bufs_could_not_alloc;
+ 	while (cur_num_rcv_bufs_to_alloc > 0) {

commit 515f49702423f3a9b1bb6b6d89057bb47f799062
+Author: Liu Junqi 
+Date:   Thu Nov 18 11:37:38 2021 +0800
+
+    staging: unisys: visorhba: use tab to indent instead of whitespace
+    
+    changed the whitespace to tab to comply with kernel coding style.
+    
+    Signed-off-by: Liu Junqi 
+    Link: https://lore.kernel.org/r/20211118033737.576775-1-liujunqi@pku.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/unisys/visorhba/visorhba_main.c b/drivers/staging/unisys/visorhba/visorhba_main.c
+index 694644112447..8eee131e834d 100644
+--- a/drivers/staging/unisys/visorhba/visorhba_main.c
++++ b/drivers/staging/unisys/visorhba/visorhba_main.c
+@@ -266,7 +266,7 @@ static int forward_taskmgmt_command(enum task_mgmt_types tasktype,
+ 					 ¬ifyevent, ¬ifyresult);
+ 	if (ret) {
+ 		dev_dbg(&scsidev->sdev_gendev,
+-		        "visorhba: setup_scsitaskmgmt_handles returned %d\n", ret);
++			"visorhba: setup_scsitaskmgmt_handles returned %d\n", ret);
+ 		return FAILED;
+ 	}
+ 

commit d4ffd5df9d18031b6a53f934388726775b4452d3
+Author: Jiashuo Liang 
+Date:   Fri Jul 30 11:01:52 2021 +0800
+
+    x86/fault: Fix wrong signal when vsyscall fails with pkey
+    
+    The function __bad_area_nosemaphore() calls kernelmode_fixup_or_oops()
+    with the parameter @signal being actually @pkey, which will send a
+    signal numbered with the argument in @pkey.
+    
+    This bug can be triggered when the kernel fails to access user-given
+    memory pages that are protected by a pkey, so it can go down the
+    do_user_addr_fault() path and pass the !user_mode() check in
+    __bad_area_nosemaphore().
+    
+    Most cases will simply run the kernel fixup code to make an -EFAULT. But
+    when another condition current->thread.sig_on_uaccess_err is met, which
+    is only used to emulate vsyscall, the kernel will generate the wrong
+    signal.
+    
+    Add a new parameter @pkey to kernelmode_fixup_or_oops() to fix this.
+    
+     [ bp: Massage commit message, fix build error as reported by the 0day
+       bot: https://lkml.kernel.org/r/202109202245.APvuT8BX-lkp@intel.com ]
+    
+    Fixes: 5042d40a264c ("x86/fault: Bypass no_context() for implicit kernel faults from usermode")
+    Reported-by: kernel test robot 
+    Signed-off-by: Jiashuo Liang 
+    Signed-off-by: Borislav Petkov 
+    Acked-by: Dave Hansen 
+    Link: https://lkml.kernel.org/r/20210730030152.249106-1-liangjs@pku.edu.cn
+
+diff --git a/arch/x86/include/asm/pkeys.h b/arch/x86/include/asm/pkeys.h
+index 5c7bcaa79623..1d5f14aff5f6 100644
+--- a/arch/x86/include/asm/pkeys.h
++++ b/arch/x86/include/asm/pkeys.h
+@@ -2,8 +2,6 @@
+ #ifndef _ASM_X86_PKEYS_H
+ #define _ASM_X86_PKEYS_H
+ 
+-#define ARCH_DEFAULT_PKEY	0
+-
+ /*
+  * If more than 16 keys are ever supported, a thorough audit
+  * will be necessary to ensure that the types that store key
+diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
+index b2eefdefc108..84a2c8c4af73 100644
+--- a/arch/x86/mm/fault.c
++++ b/arch/x86/mm/fault.c
+@@ -710,7 +710,8 @@ page_fault_oops(struct pt_regs *regs, unsigned long error_code,
+ 
+ static noinline void
+ kernelmode_fixup_or_oops(struct pt_regs *regs, unsigned long error_code,
+-			 unsigned long address, int signal, int si_code)
++			 unsigned long address, int signal, int si_code,
++			 u32 pkey)
+ {
+ 	WARN_ON_ONCE(user_mode(regs));
+ 
+@@ -735,8 +736,12 @@ kernelmode_fixup_or_oops(struct pt_regs *regs, unsigned long error_code,
+ 
+ 			set_signal_archinfo(address, error_code);
+ 
+-			/* XXX: hwpoison faults will set the wrong code. */
+-			force_sig_fault(signal, si_code, (void __user *)address);
++			if (si_code == SEGV_PKUERR) {
++				force_sig_pkuerr((void __user *)address, pkey);
++			} else {
++				/* XXX: hwpoison faults will set the wrong code. */
++				force_sig_fault(signal, si_code, (void __user *)address);
++			}
+ 		}
+ 
+ 		/*
+@@ -798,7 +803,8 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
+ 	struct task_struct *tsk = current;
+ 
+ 	if (!user_mode(regs)) {
+-		kernelmode_fixup_or_oops(regs, error_code, address, pkey, si_code);
++		kernelmode_fixup_or_oops(regs, error_code, address,
++					 SIGSEGV, si_code, pkey);
+ 		return;
+ 	}
+ 
+@@ -930,7 +936,8 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address,
+ {
+ 	/* Kernel mode? Handle exceptions or die: */
+ 	if (!user_mode(regs)) {
+-		kernelmode_fixup_or_oops(regs, error_code, address, SIGBUS, BUS_ADRERR);
++		kernelmode_fixup_or_oops(regs, error_code, address,
++					 SIGBUS, BUS_ADRERR, ARCH_DEFAULT_PKEY);
+ 		return;
+ 	}
+ 
+@@ -1396,7 +1403,8 @@ void do_user_addr_fault(struct pt_regs *regs,
+ 		 */
+ 		if (!user_mode(regs))
+ 			kernelmode_fixup_or_oops(regs, error_code, address,
+-						 SIGBUS, BUS_ADRERR);
++						 SIGBUS, BUS_ADRERR,
++						 ARCH_DEFAULT_PKEY);
+ 		return;
+ 	}
+ 
+@@ -1416,7 +1424,8 @@ void do_user_addr_fault(struct pt_regs *regs,
+ 		return;
+ 
+ 	if (fatal_signal_pending(current) && !user_mode(regs)) {
+-		kernelmode_fixup_or_oops(regs, error_code, address, 0, 0);
++		kernelmode_fixup_or_oops(regs, error_code, address,
++					 0, 0, ARCH_DEFAULT_PKEY);
+ 		return;
+ 	}
+ 
+@@ -1424,7 +1433,8 @@ void do_user_addr_fault(struct pt_regs *regs,
+ 		/* Kernel mode? Handle exceptions or die: */
+ 		if (!user_mode(regs)) {
+ 			kernelmode_fixup_or_oops(regs, error_code, address,
+-						 SIGSEGV, SEGV_MAPERR);
++						 SIGSEGV, SEGV_MAPERR,
++						 ARCH_DEFAULT_PKEY);
+ 			return;
+ 		}
+ 
+diff --git a/include/linux/pkeys.h b/include/linux/pkeys.h
+index 6beb26b7151d..86be8bf27b41 100644
+--- a/include/linux/pkeys.h
++++ b/include/linux/pkeys.h
+@@ -4,6 +4,8 @@
+ 
+ #include 
+ 
++#define ARCH_DEFAULT_PKEY	0
++
+ #ifdef CONFIG_ARCH_HAS_PKEYS
+ #include 
+ #else /* ! CONFIG_ARCH_HAS_PKEYS */

commit 5405b42c2f08efe67b531799ba2fdb35bac93e70
+Author: Jiashuo Liang 
+Date:   Tue Jun 1 16:52:03 2021 +0800
+
+    x86/fault: Don't send SIGSEGV twice on SEGV_PKUERR
+    
+    __bad_area_nosemaphore() calls both force_sig_pkuerr() and
+    force_sig_fault() when handling SEGV_PKUERR. This does not cause
+    problems because the second signal is filtered by the legacy_queue()
+    check in __send_signal() because in both cases, the signal is SIGSEGV,
+    the second one seeing that the first one is already pending.
+    
+    This causes the kernel to do unnecessary work so send the signal only
+    once for SEGV_PKUERR.
+    
+     [ bp: Massage commit message. ]
+    
+    Fixes: 9db812dbb29d ("signal/x86: Call force_sig_pkuerr from __bad_area_nosemaphore")
+    Suggested-by: "Eric W. Biederman" 
+    Signed-off-by: Jiashuo Liang 
+    Signed-off-by: Borislav Petkov 
+    Acked-by: "Eric W. Biederman" 
+    Link: https://lkml.kernel.org/r/20210601085203.40214-1-liangjs@pku.edu.cn
+
+diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
+index 1c548ad00752..6bda7f67d737 100644
+--- a/arch/x86/mm/fault.c
++++ b/arch/x86/mm/fault.c
+@@ -836,8 +836,8 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
+ 
+ 	if (si_code == SEGV_PKUERR)
+ 		force_sig_pkuerr((void __user *)address, pkey);
+-
+-	force_sig_fault(SIGSEGV, si_code, (void __user *)address);
++	else
++		force_sig_fault(SIGSEGV, si_code, (void __user *)address);
+ 
+ 	local_irq_disable();
+ }

commit dd3b8c329aa270027fba61a02a12600972dc3983
+Author: Guan Xuetao 
+Date:   Wed Mar 21 21:10:56 2018 +0800
+
+    MAINTAINERS: UNICORE32: Change email account
+    
+    Change email account for unicore32 arch and pkunity soc drivers
+    Since old email server mprc.pku.edu.cn was blocked in recent years
+    
+    Signed-off-by: Guan Xuetao 
+    Cc: Arnd Bergmann 
+    Signed-off-by: Arnd Bergmann 
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 48486a505a4e..f86f3b253a10 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -10930,7 +10930,7 @@ F:	include/linux/pktcdvd.h
+ F:	include/uapi/linux/pktcdvd.h
+ 
+ PKUNITY SOC DRIVERS
+-M:	Guan Xuetao 
++M:	Guan Xuetao 
+ W:	http://mprc.pku.edu.cn/~guanxuetao/linux
+ S:	Maintained
+ T:	git git://github.com/gxt/linux.git
+@@ -14154,7 +14154,7 @@ F:	include/linux/uwb.h
+ F:	include/linux/uwb/
+ 
+ UNICORE32 ARCHITECTURE:
+-M:	Guan Xuetao 
++M:	Guan Xuetao 
+ W:	http://mprc.pku.edu.cn/~guanxuetao/linux
+ S:	Maintained
+ T:	git git://github.com/gxt/linux.git

commit 2b1193d5287004edfbf89407149a3159656f47f1
+Author: John Hunter 
+Date:   Tue Apr 14 17:07:22 2015 +0800
+
+    drm: fix trivial typo mistake
+    
+    Signed-off-by: John Hunter 
+    Signed-off-by: Daniel Vetter 
+
+diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
+index 97c33b40005f..b009d707f562 100644
+--- a/include/drm/drm_crtc.h
++++ b/include/drm/drm_crtc.h
+@@ -975,7 +975,7 @@ struct drm_mode_set {
+  * struct drm_mode_config_funcs - basic driver provided mode setting functions
+  * @fb_create: create a new framebuffer object
+  * @output_poll_changed: function to handle output configuration changes
+- * @atomic_check: check whether a give atomic state update is possible
++ * @atomic_check: check whether a given atomic state update is possible
+  * @atomic_commit: commit an atomic state update previously verified with
+  * 	atomic_check()
+  *

commit 16d78bc2e4d69df962a750ac37ce69dd8eda401b
+Author: John Hunter 
+Date:   Tue Apr 7 19:38:50 2015 +0800
+
+    drm: Fix some typos
+    
+    Signed-off-by: John Hunter 
+    Signed-off-by: Daniel Vetter 
+
+diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
+index 57efdbeff008..0537f327b145 100644
+--- a/drivers/gpu/drm/drm_atomic.c
++++ b/drivers/gpu/drm/drm_atomic.c
+@@ -780,7 +780,7 @@ drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
+ EXPORT_SYMBOL(drm_atomic_set_crtc_for_plane);
+ 
+ /**
+- * drm_atomic_set_fb_for_plane - set crtc for plane
++ * drm_atomic_set_fb_for_plane - set framebuffer for plane
+  * @plane_state: atomic state object for the plane
+  * @fb: fb to use for the plane
+  *
+@@ -933,7 +933,7 @@ EXPORT_SYMBOL(drm_atomic_connectors_for_crtc);
+  *
+  * This function should be used by legacy entry points which don't understand
+  * -EDEADLK semantics. For simplicity this one will grab all modeset locks after
+- *  the slowpath completed.
++ * the slowpath completed.
+  */
+ void drm_atomic_legacy_backoff(struct drm_atomic_state *state)
+ {

commit 0388df05088def7ce5f3dd1b2293f05739be2a23
+Author: John Hunter 
+Date:   Tue Mar 17 15:30:28 2015 +0800
+
+    drm: change connector to tmp_connector
+    
+    This wasn't too harmful since we already look at connector,
+    which has the same effect as the loop for any non-cloned configs.
+    Only when we have a cloned configuration is it important to look
+    at other connectors. Furthermore existing userspace always changes
+    dpms on all of them anyway.
+    
+    Signed-off-by: JohnHunter 
+    Signed-off-by: Daniel Vetter 
+
+diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
+index 52e7e18c102a..d9ed9a54fd1e 100644
+--- a/drivers/gpu/drm/drm_atomic_helper.c
++++ b/drivers/gpu/drm/drm_atomic_helper.c
+@@ -2001,10 +2001,10 @@ void drm_atomic_helper_connector_dpms(struct drm_connector *connector,
+ 	WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));
+ 
+ 	list_for_each_entry(tmp_connector, &config->connector_list, head) {
+-		if (connector->state->crtc != crtc)
++		if (tmp_connector->state->crtc != crtc)
+ 			continue;
+ 
+-		if (connector->dpms == DRM_MODE_DPMS_ON) {
++		if (tmp_connector->dpms == DRM_MODE_DPMS_ON) {
+ 			active = true;
+ 			break;
+ 		}

commit f98bd3eff592fa708bb260cf3c6403e443cd40b7
+Author: John Hunter 
+Date:   Tue Mar 17 15:30:26 2015 +0800
+
+    drm: Fix some typo mistake of the annotations
+    
+    There are some mistakes that the function name in the annotaions
+    is not matching the real function name.
+    And some duplication word in annotations
+    
+    Signed-off-by: John Hunter 
+    Signed-off-by: Daniel Vetter 
+
+diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
+index 5bcb4baeb9cb..52e7e18c102a 100644
+--- a/drivers/gpu/drm/drm_atomic_helper.c
++++ b/drivers/gpu/drm/drm_atomic_helper.c
+@@ -346,7 +346,7 @@ needs_modeset(struct drm_crtc_state *state)
+ }
+ 
+ /**
+- * drm_atomic_helper_check - validate state object for modeset changes
++ * drm_atomic_helper_check_modeset - validate state object for modeset changes
+  * @dev: DRM device
+  * @state: the driver state object
+  *
+@@ -461,7 +461,7 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
+ EXPORT_SYMBOL(drm_atomic_helper_check_modeset);
+ 
+ /**
+- * drm_atomic_helper_check - validate state object for modeset changes
++ * drm_atomic_helper_check_planes - validate state object for planes changes
+  * @dev: DRM device
+  * @state: the driver state object
+  *
+@@ -605,7 +605,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
+ 
+ 		/*
+ 		 * Each encoder has at most one connector (since we always steal
+-		 * it away), so we won't call call disable hooks twice.
++		 * it away), so we won't call disable hooks twice.
+ 		 */
+ 		if (encoder->bridge)
+ 			encoder->bridge->funcs->disable(encoder->bridge);
+@@ -757,7 +757,7 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
+ 
+ 		/*
+ 		 * Each encoder has at most one connector (since we always steal
+-		 * it away), so we won't call call mode_set hooks twice.
++		 * it away), so we won't call mode_set hooks twice.
+ 		 */
+ 		if (funcs->mode_set)
+ 			funcs->mode_set(encoder, mode, adjusted_mode);
+@@ -858,7 +858,7 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
+ 
+ 		/*
+ 		 * Each encoder has at most one connector (since we always steal
+-		 * it away), so we won't call call enable hooks twice.
++		 * it away), so we won't call enable hooks twice.
+ 		 */
+ 		if (encoder->bridge)
+ 			encoder->bridge->funcs->pre_enable(encoder->bridge);
+@@ -1025,7 +1025,7 @@ int drm_atomic_helper_commit(struct drm_device *dev,
+ 
+ 	/*
+ 	 * Everything below can be run asynchronously without the need to grab
+-	 * any modeset locks at all under one conditions: It must be guaranteed
++	 * any modeset locks at all under one condition: It must be guaranteed
+ 	 * that the asynchronous work has either been cancelled (if the driver
+ 	 * supports it, which at least requires that the framebuffers get
+ 	 * cleaned up with drm_atomic_helper_cleanup_planes()) or completed

commit ceebf4d5016bd1182b214eafd46ebd24d6cdf668
+Author: Guan Xuetao 
+Date:   Tue May 27 07:53:10 2014 +0800
+
+    UniCore32: Change git tree location information in MAINTAINERS
+    
+    UniCore32 git repo has moved to github.
+    Branch 'unicore32' is used for prepared patches, and automatically merged to linux-next.
+    Branch 'unicore32-working' is used for development.
+    
+    Signed-off-by: Guan Xuetao 
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index e36d18d8f0eb..ddf53ff84053 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -6960,7 +6960,7 @@ PKUNITY SOC DRIVERS
+ M:	Guan Xuetao 
+ W:	http://mprc.pku.edu.cn/~guanxuetao/linux
+ S:	Maintained
+-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/epip/linux-2.6-unicore32.git
++T:	git git://github.com/gxt/linux.git
+ F:	drivers/input/serio/i8042-unicore32io.h
+ F:	drivers/i2c/busses/i2c-puv3.c
+ F:	drivers/video/fb-puv3.c
+@@ -9277,7 +9277,7 @@ UNICORE32 ARCHITECTURE:
+ M:	Guan Xuetao 
+ W:	http://mprc.pku.edu.cn/~guanxuetao/linux
+ S:	Maintained
+-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/epip/linux-2.6-unicore32.git
++T:	git git://github.com/gxt/linux.git
+ F:	arch/unicore32/
+ 
+ UNIFDEF

commit ddd2d384b019d1733335c0fca7eccae3c29d2a14
+Author: Guan Xuetao 
+Date:   Mon Oct 15 14:41:36 2012 +0800
+
+    unicore32: Use Kbuild infrastructure for kvm_para.h
+    
+    All the headers but kvm_para.h use the Kbuild infrastructure to
+    get to the asm-generic headers.
+    
+    Cc: linux-kbuild@vger.kernel.org
+    Signed-off-by: Steven Rostedt 
+    Signed-off-by: Guan Xuetao 
+
+diff --git a/arch/unicore32/include/uapi/asm/Kbuild b/arch/unicore32/include/uapi/asm/Kbuild
+index a44b1c453d13..0514d7ad6855 100644
+--- a/arch/unicore32/include/uapi/asm/Kbuild
++++ b/arch/unicore32/include/uapi/asm/Kbuild
+@@ -6,3 +6,5 @@ header-y += kvm_para.h
+ header-y += ptrace.h
+ header-y += sigcontext.h
+ header-y += unistd.h
++
++generic-y += kvm_para.h
+diff --git a/arch/unicore32/include/uapi/asm/kvm_para.h b/arch/unicore32/include/uapi/asm/kvm_para.h
+deleted file mode 100644
+index 14fab8f0b957..000000000000
+--- a/arch/unicore32/include/uapi/asm/kvm_para.h
++++ /dev/null
+@@ -1 +0,0 @@
+-#include 

commit 10e1e99e55378a65529c48753703c069aebce7af
+Author: Guan Xuetao 
+Date:   Thu Jun 14 11:38:25 2012 +0800
+
+    UniCore32-bugfix: Remove definitions in asm/bug.h to solve difference between native and cross compiler
+    
+    For kernel/bound.c being compiled by native compiler, it will generate following errors in gcc 4.4.3:
+      CC      kernel/bounds.s
+    In file included from include/linux/bug.h:4,
+                     from include/linux/page-flags.h:9,
+                     from kernel/bounds.c:9:
+    arch/unicore32/include/asm/bug.h:22: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'void'
+    arch/unicore32/include/asm/bug.h:23: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'void'
+    
+    So, we moved definitions in asm/bug.h to arch/unicore32/kernel/setup.h to solve the problem.
+    
+    Signed-off-by: Guan Xuetao 
+
+diff --git a/arch/unicore32/include/asm/bug.h b/arch/unicore32/include/asm/bug.h
+index b1ff8cadb086..93a56f3e2344 100644
+--- a/arch/unicore32/include/asm/bug.h
++++ b/arch/unicore32/include/asm/bug.h
+@@ -19,9 +19,4 @@ extern void die(const char *msg, struct pt_regs *regs, int err);
+ extern void uc32_notify_die(const char *str, struct pt_regs *regs,
+ 		struct siginfo *info, unsigned long err, unsigned long trap);
+ 
+-extern asmlinkage void __backtrace(void);
+-extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
+-
+-extern void __show_regs(struct pt_regs *);
+-
+ #endif /* __UNICORE_BUG_H__ */
+diff --git a/arch/unicore32/kernel/setup.h b/arch/unicore32/kernel/setup.h
+index f23955028a18..30f749da8f73 100644
+--- a/arch/unicore32/kernel/setup.h
++++ b/arch/unicore32/kernel/setup.h
+@@ -30,4 +30,10 @@ extern char __vectors_start[], __vectors_end[];
+ extern void kernel_thread_helper(void);
+ 
+ extern void __init early_signal_init(void);
++
++extern asmlinkage void __backtrace(void);
++extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
++
++extern void __show_regs(struct pt_regs *);
++
+ #endif

commit 195d4577d1d7ab1f0398b3190547c116b56f435f
+Author: Guan Xuetao 
+Date:   Thu Jun 14 15:39:48 2012 +0800
+
+    UniCore32-bugfix: fix mismatch return value of __xchg_bad_pointer
+    
+    When disintegrate system.h, I left an error in asm/cmpxchg.h, which
+    will result in following error:
+    
+    arch/unicore32/include/asm/cmpxchg.h: In function '__xchg':
+    arch/unicore32/include/asm/cmpxchg.h:38: error: void value not ignored as it ought to be
+    
+    Signed-off-by: Guan Xuetao 
+
+diff --git a/arch/unicore32/include/asm/cmpxchg.h b/arch/unicore32/include/asm/cmpxchg.h
+index df4d5acfd19f..8e797ad4fa24 100644
+--- a/arch/unicore32/include/asm/cmpxchg.h
++++ b/arch/unicore32/include/asm/cmpxchg.h
+@@ -35,7 +35,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
+ 			: "memory", "cc");
+ 		break;
+ 	default:
+-		ret = __xchg_bad_pointer();
++		__xchg_bad_pointer();
+ 	}
+ 
+ 	return ret;

commit 446d141e1c84d34c70592b53443b06533703c324
+Author: Guan Xuetao 
+Date:   Thu Apr 12 09:18:46 2012 +0800
+
+    UniCore32 bugfix: add missed CONFIG_ZONE_DMA
+    
+    Because our PCI-bus handler confines dma zone into 128M, we should add
+    CONFIG_ZONE_DMA for all boards. Otherwise, all memory bigger than 128M
+    will be pushed into ZONE_MOVABLE.
+    
+    Cc: Arnd Bergmann 
+    Signed-off-by: Liu Guoli 
+    Signed-off-by: Guan Xuetao 
+
+diff --git a/arch/unicore32/Kconfig b/arch/unicore32/Kconfig
+index e5c5473e69ce..5b95ba4e0c70 100644
+--- a/arch/unicore32/Kconfig
++++ b/arch/unicore32/Kconfig
+@@ -64,6 +64,9 @@ config GENERIC_CALIBRATE_DELAY
+ config ARCH_MAY_HAVE_PC_FDC
+ 	bool
+ 
++config ZONE_DMA
++	def_bool y
++
+ config NEED_DMA_MAP_STATE
+        def_bool y
+ 

commit 8978bfd2288adaa24d39fa15f57eb9e24ffeca12
+Author: Guan Xuetao 
+Date:   Wed Mar 28 18:30:03 2012 +0100
+
+    Disintegrate asm/system.h for Unicore32 [based on ver #3, changed by gxt]
+    
+    Disintegrate asm/system.h for Unicore32. (Compilation successful)
+    The implementation details are not changed, but only splitted.
+    BTW, some codestyles are adjusted.
+    
+    Signed-off-by: David Howells 
+    Signed-off-by: Guan Xuetao 
+
+diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
+index ca113d6999c5..34b789b71115 100644
+--- a/arch/unicore32/include/asm/Kbuild
++++ b/arch/unicore32/include/asm/Kbuild
+@@ -3,7 +3,6 @@ include include/asm-generic/Kbuild.asm
+ generic-y += atomic.h
+ generic-y += auxvec.h
+ generic-y += bitsperlong.h
+-generic-y += bug.h
+ generic-y += bugs.h
+ generic-y += cputime.h
+ generic-y += current.h
+diff --git a/arch/unicore32/include/asm/barrier.h b/arch/unicore32/include/asm/barrier.h
+new file mode 100644
+index 000000000000..a6620e5336b6
+--- /dev/null
++++ b/arch/unicore32/include/asm/barrier.h
+@@ -0,0 +1,28 @@
++/*
++ * Memory barrier implementations for PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2012 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_BARRIER_H__
++#define __UNICORE_BARRIER_H__
++
++#define isb() __asm__ __volatile__ ("" : : : "memory")
++#define dsb() __asm__ __volatile__ ("" : : : "memory")
++#define dmb() __asm__ __volatile__ ("" : : : "memory")
++
++#define mb()				barrier()
++#define rmb()				barrier()
++#define wmb()				barrier()
++#define smp_mb()			barrier()
++#define smp_rmb()			barrier()
++#define smp_wmb()			barrier()
++#define read_barrier_depends()		do { } while (0)
++#define smp_read_barrier_depends()	do { } while (0)
++
++#define set_mb(var, value)		do { var = value; smp_mb(); } while (0)
++
++#endif /* __UNICORE_BARRIER_H__ */
+diff --git a/arch/unicore32/include/asm/bug.h b/arch/unicore32/include/asm/bug.h
+new file mode 100644
+index 000000000000..b1ff8cadb086
+--- /dev/null
++++ b/arch/unicore32/include/asm/bug.h
+@@ -0,0 +1,27 @@
++/*
++ * Bug handling for PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2012 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_BUG_H__
++#define __UNICORE_BUG_H__
++
++#include 
++
++struct pt_regs;
++struct siginfo;
++
++extern void die(const char *msg, struct pt_regs *regs, int err);
++extern void uc32_notify_die(const char *str, struct pt_regs *regs,
++		struct siginfo *info, unsigned long err, unsigned long trap);
++
++extern asmlinkage void __backtrace(void);
++extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
++
++extern void __show_regs(struct pt_regs *);
++
++#endif /* __UNICORE_BUG_H__ */
+diff --git a/arch/unicore32/include/asm/cmpxchg.h b/arch/unicore32/include/asm/cmpxchg.h
+new file mode 100644
+index 000000000000..df4d5acfd19f
+--- /dev/null
++++ b/arch/unicore32/include/asm/cmpxchg.h
+@@ -0,0 +1,61 @@
++/*
++ * Atomics xchg/cmpxchg for PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2012 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_CMPXCHG_H__
++#define __UNICORE_CMPXCHG_H__
++
++/*
++ * Generate a link failure on undefined symbol if the pointer points to a value
++ * of unsupported size.
++ */
++extern void __xchg_bad_pointer(void);
++
++static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
++		int size)
++{
++	unsigned long ret;
++
++	switch (size) {
++	case 1:
++		asm volatile("swapb	%0, %1, [%2]"
++			: "=&r" (ret)
++			: "r" (x), "r" (ptr)
++			: "memory", "cc");
++		break;
++	case 4:
++		asm volatile("swapw	%0, %1, [%2]"
++			: "=&r" (ret)
++			: "r" (x), "r" (ptr)
++			: "memory", "cc");
++		break;
++	default:
++		ret = __xchg_bad_pointer();
++	}
++
++	return ret;
++}
++
++#define xchg(ptr, x) \
++	((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
++
++#include 
++
++/*
++ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
++ * them available.
++ */
++#define cmpxchg_local(ptr, o, n)					\
++		((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr),	\
++		(unsigned long)(o), (unsigned long)(n), sizeof(*(ptr))))
++#define cmpxchg64_local(ptr, o, n)					\
++		__cmpxchg64_local_generic((ptr), (o), (n))
++
++#include 
++
++#endif /* __UNICORE_CMPXCHG_H__ */
+diff --git a/arch/unicore32/include/asm/exec.h b/arch/unicore32/include/asm/exec.h
+new file mode 100644
+index 000000000000..06d1f0f57888
+--- /dev/null
++++ b/arch/unicore32/include/asm/exec.h
+@@ -0,0 +1,15 @@
++/*
++ * Process execution bits for PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2012 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_EXEC_H__
++#define __UNICORE_EXEC_H__
++
++#define arch_align_stack(x)		(x)
++
++#endif /* __UNICORE_EXEC_H__ */
+diff --git a/arch/unicore32/include/asm/hwdef-copro.h b/arch/unicore32/include/asm/hwdef-copro.h
+new file mode 100644
+index 000000000000..a3292f039a68
+--- /dev/null
++++ b/arch/unicore32/include/asm/hwdef-copro.h
+@@ -0,0 +1,48 @@
++/*
++ * Co-processor register definitions for PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2012 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_HWDEF_COPRO_H__
++#define __UNICORE_HWDEF_COPRO_H__
++
++/*
++ * Control Register bits (CP#0 CR1)
++ */
++#define CR_M	(1 << 0)	/* MMU enable				*/
++#define CR_A	(1 << 1)	/* Alignment abort enable		*/
++#define CR_D	(1 << 2)	/* Dcache enable			*/
++#define CR_I	(1 << 3)	/* Icache enable			*/
++#define CR_B	(1 << 4)	/* Dcache write mechanism: write back	*/
++#define CR_T	(1 << 5)	/* Burst enable				*/
++#define CR_V	(1 << 13)	/* Vectors relocated to 0xffff0000	*/
++
++#ifndef __ASSEMBLY__
++
++#define vectors_high()		(cr_alignment & CR_V)
++
++extern unsigned long cr_no_alignment;	/* defined in entry.S */
++extern unsigned long cr_alignment;	/* defined in entry.S */
++
++static inline unsigned int get_cr(void)
++{
++	unsigned int val;
++	asm("movc %0, p0.c1, #0" : "=r" (val) : : "cc");
++	return val;
++}
++
++static inline void set_cr(unsigned int val)
++{
++	asm volatile("movc p0.c1, %0, #0" : : "r" (val) : "cc");
++	isb();
++}
++
++extern void adjust_cr(unsigned long mask, unsigned long set);
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* __UNICORE_HWDEF_COPRO_H__ */
+diff --git a/arch/unicore32/include/asm/io.h b/arch/unicore32/include/asm/io.h
+index adddf6d64077..39decb6e6f57 100644
+--- a/arch/unicore32/include/asm/io.h
++++ b/arch/unicore32/include/asm/io.h
+@@ -16,7 +16,6 @@
+ 
+ #include 
+ #include 
+-#include 
+ 
+ #define PCI_IOBASE	PKUNITY_PCILIO_BASE
+ #include 
+diff --git a/arch/unicore32/include/asm/switch_to.h b/arch/unicore32/include/asm/switch_to.h
+new file mode 100644
+index 000000000000..39572d2bd692
+--- /dev/null
++++ b/arch/unicore32/include/asm/switch_to.h
+@@ -0,0 +1,30 @@
++/*
++ * Task switching for PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2012 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_SWITCH_TO_H__
++#define __UNICORE_SWITCH_TO_H__
++
++struct task_struct;
++struct thread_info;
++
++/*
++ * switch_to(prev, next) should switch from task `prev' to `next'
++ * `prev' will never be the same as `next'.  schedule() itself
++ * contains the memory barrier to tell GCC not to cache `current'.
++ */
++extern struct task_struct *__switch_to(struct task_struct *,
++		struct thread_info *, struct thread_info *);
++
++#define switch_to(prev, next, last)					\
++	do {								\
++		last = __switch_to(prev, task_thread_info(prev),	\
++					task_thread_info(next));	\
++	} while (0)
++
++#endif /* __UNICORE_SWITCH_TO_H__ */
+diff --git a/arch/unicore32/include/asm/system.h b/arch/unicore32/include/asm/system.h
+index 246b71c17fda..a7f40578587c 100644
+--- a/arch/unicore32/include/asm/system.h
++++ b/arch/unicore32/include/asm/system.h
+@@ -1,161 +1,5 @@
+-/*
+- * linux/arch/unicore32/include/asm/system.h
+- *
+- * Code specific to PKUnity SoC and UniCore ISA
+- *
+- * Copyright (C) 2001-2010 GUAN Xue-tao
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-#ifndef __UNICORE_SYSTEM_H__
+-#define __UNICORE_SYSTEM_H__
+-
+-#ifdef __KERNEL__
+-
+-/*
+- * CR1 bits (CP#0 CR1)
+- */
+-#define CR_M	(1 << 0)	/* MMU enable				*/
+-#define CR_A	(1 << 1)	/* Alignment abort enable		*/
+-#define CR_D	(1 << 2)	/* Dcache enable			*/
+-#define CR_I	(1 << 3)	/* Icache enable			*/
+-#define CR_B	(1 << 4)	/* Dcache write mechanism: write back	*/
+-#define CR_T	(1 << 5)	/* Burst enable				*/
+-#define CR_V	(1 << 13)	/* Vectors relocated to 0xffff0000	*/
+-
+-#ifndef __ASSEMBLY__
+-
+-#include 
+-#include 
+-
+-struct thread_info;
+-struct task_struct;
+-
+-struct pt_regs;
+-
+-void die(const char *msg, struct pt_regs *regs, int err);
+-
+-struct siginfo;
+-void uc32_notify_die(const char *str, struct pt_regs *regs,
+-		struct siginfo *info, unsigned long err, unsigned long trap);
+-
+-void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
+-				       struct pt_regs *),
+-		     int sig, int code, const char *name);
+-
+-#define xchg(ptr, x) \
+-	((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
+-
+-extern asmlinkage void __backtrace(void);
+-extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
+-
+-struct mm_struct;
+-extern void show_pte(struct mm_struct *mm, unsigned long addr);
+-extern void __show_regs(struct pt_regs *);
+-
+-extern int cpu_architecture(void);
+-extern void cpu_init(void);
+-
+-#define vectors_high()	(cr_alignment & CR_V)
+-
+-#define isb() __asm__ __volatile__ ("" : : : "memory")
+-#define dsb() __asm__ __volatile__ ("" : : : "memory")
+-#define dmb() __asm__ __volatile__ ("" : : : "memory")
+-
+-#define mb()		barrier()
+-#define rmb()		barrier()
+-#define wmb()		barrier()
+-#define smp_mb()	barrier()
+-#define smp_rmb()	barrier()
+-#define smp_wmb()	barrier()
+-#define read_barrier_depends()		do { } while (0)
+-#define smp_read_barrier_depends()	do { } while (0)
+-
+-#define set_mb(var, value)	do { var = value; smp_mb(); } while (0)
+-#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
+-
+-extern unsigned long cr_no_alignment;	/* defined in entry-unicore.S */
+-extern unsigned long cr_alignment;	/* defined in entry-unicore.S */
+-
+-static inline unsigned int get_cr(void)
+-{
+-	unsigned int val;
+-	asm("movc %0, p0.c1, #0" : "=r" (val) : : "cc");
+-	return val;
+-}
+-
+-static inline void set_cr(unsigned int val)
+-{
+-	asm volatile("movc p0.c1, %0, #0	@set CR"
+-	  : : "r" (val) : "cc");
+-	isb();
+-}
+-
+-extern void adjust_cr(unsigned long mask, unsigned long set);
+-
+-/*
+- * switch_to(prev, next) should switch from task `prev' to `next'
+- * `prev' will never be the same as `next'.  schedule() itself
+- * contains the memory barrier to tell GCC not to cache `current'.
+- */
+-extern struct task_struct *__switch_to(struct task_struct *,
+-		struct thread_info *, struct thread_info *);
+-extern void panic(const char *fmt, ...);
+-
+-#define switch_to(prev, next, last)					\
+-do {									\
+-	last = __switch_to(prev,					\
+-		task_thread_info(prev), task_thread_info(next));	\
+-} while (0)
+-
+-static inline unsigned long
+-__xchg(unsigned long x, volatile void *ptr, int size)
+-{
+-	unsigned long ret;
+-
+-	switch (size) {
+-	case 1:
+-		asm volatile("@	__xchg1\n"
+-		"	swapb	%0, %1, [%2]"
+-			: "=&r" (ret)
+-			: "r" (x), "r" (ptr)
+-			: "memory", "cc");
+-		break;
+-	case 4:
+-		asm volatile("@	__xchg4\n"
+-		"	swapw	%0, %1, [%2]"
+-			: "=&r" (ret)
+-			: "r" (x), "r" (ptr)
+-			: "memory", "cc");
+-		break;
+-	default:
+-		panic("xchg: bad data size: ptr 0x%p, size %d\n",
+-			ptr, size);
+-	}
+-
+-	return ret;
+-}
+-
+-#include 
+-
+-/*
+- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+- * them available.
+- */
+-#define cmpxchg_local(ptr, o, n)					\
+-		((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr),	\
+-		(unsigned long)(o), (unsigned long)(n), sizeof(*(ptr))))
+-#define cmpxchg64_local(ptr, o, n)					\
+-		__cmpxchg64_local_generic((ptr), (o), (n))
+-
+-#include 
+-
+-#endif /* __ASSEMBLY__ */
+-
+-#define arch_align_stack(x) (x)
+-
+-#endif /* __KERNEL__ */
+-
+-#endif
++/* FILE TO BE DELETED. DO NOT ADD STUFF HERE! */
++#include 
++#include 
++#include 
++#include 
+diff --git a/arch/unicore32/include/asm/uaccess.h b/arch/unicore32/include/asm/uaccess.h
+index 2acda503a6d9..897e11ad8124 100644
+--- a/arch/unicore32/include/asm/uaccess.h
++++ b/arch/unicore32/include/asm/uaccess.h
+@@ -16,7 +16,6 @@
+ #include 
+ 
+ #include 
+-#include 
+ 
+ #define __copy_from_user	__copy_from_user
+ #define __copy_to_user		__copy_to_user
+diff --git a/arch/unicore32/kernel/dma.c b/arch/unicore32/kernel/dma.c
+index ae441bc3122c..ed2d4d78d9c4 100644
+--- a/arch/unicore32/kernel/dma.c
++++ b/arch/unicore32/kernel/dma.c
+@@ -18,7 +18,6 @@
+ #include 
+ #include 
+ 
+-#include 
+ #include 
+ #include 
+ #include 
+diff --git a/arch/unicore32/kernel/head.S b/arch/unicore32/kernel/head.S
+index 8caf322e110d..e8f0b98c02ee 100644
+--- a/arch/unicore32/kernel/head.S
++++ b/arch/unicore32/kernel/head.S
+@@ -17,7 +17,7 @@
+ #include 
+ #include 
+ #include 
+-#include 
++#include 
+ #include 
+ 
+ #if (PHYS_OFFSET & 0x003fffff)
+diff --git a/arch/unicore32/kernel/hibernate.c b/arch/unicore32/kernel/hibernate.c
+index 7d0f0b7983a0..d75ef8b6cb56 100644
+--- a/arch/unicore32/kernel/hibernate.c
++++ b/arch/unicore32/kernel/hibernate.c
+@@ -15,7 +15,6 @@
+ #include 
+ #include 
+ 
+-#include 
+ #include 
+ #include 
+ #include 
+diff --git a/arch/unicore32/kernel/irq.c b/arch/unicore32/kernel/irq.c
+index d4efa7d679ff..0be5ccd7ccd2 100644
+--- a/arch/unicore32/kernel/irq.c
++++ b/arch/unicore32/kernel/irq.c
+@@ -26,7 +26,6 @@
+ #include 
+ #include 
+ 
+-#include 
+ #include 
+ 
+ #include "setup.h"
+diff --git a/arch/unicore32/kernel/ksyms.c b/arch/unicore32/kernel/ksyms.c
+index d98bd812cae1..d285d71cbe35 100644
+--- a/arch/unicore32/kernel/ksyms.c
++++ b/arch/unicore32/kernel/ksyms.c
+@@ -20,7 +20,6 @@
+ #include 
+ 
+ #include 
+-#include 
+ 
+ #include "ksyms.h"
+ 
+diff --git a/arch/unicore32/kernel/process.c b/arch/unicore32/kernel/process.c
+index 52edc2b62873..1b3f152bb9c5 100644
+--- a/arch/unicore32/kernel/process.c
++++ b/arch/unicore32/kernel/process.c
+@@ -34,7 +34,6 @@
+ 
+ #include 
+ #include 
+-#include 
+ #include 
+ 
+ #include "setup.h"
+diff --git a/arch/unicore32/kernel/setup.h b/arch/unicore32/kernel/setup.h
+index dcd1306eb5c6..f23955028a18 100644
+--- a/arch/unicore32/kernel/setup.h
++++ b/arch/unicore32/kernel/setup.h
+@@ -12,8 +12,11 @@
+ #ifndef __UNICORE_KERNEL_SETUP_H__
+ #define __UNICORE_KERNEL_SETUP_H__
+ 
++#include 
++
+ extern void paging_init(void);
+ extern void puv3_core_init(void);
++extern void cpu_init(void);
+ 
+ extern void puv3_ps2_init(void);
+ extern void pci_puv3_preinit(void);
+diff --git a/arch/unicore32/kernel/traps.c b/arch/unicore32/kernel/traps.c
+index b9a26465e728..2054f0d4db13 100644
+--- a/arch/unicore32/kernel/traps.c
++++ b/arch/unicore32/kernel/traps.c
+@@ -26,7 +26,6 @@
+ #include 
+ 
+ #include 
+-#include 
+ #include 
+ 
+ #include "setup.h"
+diff --git a/arch/unicore32/mm/alignment.c b/arch/unicore32/mm/alignment.c
+index 28f576d733ee..de7dc5fdd58b 100644
+--- a/arch/unicore32/mm/alignment.c
++++ b/arch/unicore32/mm/alignment.c
+@@ -24,6 +24,8 @@
+ #include 
+ #include 
+ 
++#include "mm.h"
++
+ #define CODING_BITS(i)	(i & 0xe0000120)
+ 
+ #define LDST_P_BIT(i)	(i & (1 << 28))	/* Preindex             */
+diff --git a/arch/unicore32/mm/fault.c b/arch/unicore32/mm/fault.c
+index 283aa4b50b7a..2eeb9c04cab0 100644
+--- a/arch/unicore32/mm/fault.c
++++ b/arch/unicore32/mm/fault.c
+@@ -20,7 +20,6 @@
+ #include 
+ #include 
+ 
+-#include 
+ #include 
+ #include 
+ 
+diff --git a/arch/unicore32/mm/flush.c b/arch/unicore32/mm/flush.c
+index 93478cc8b26d..6d4c096ffa2a 100644
+--- a/arch/unicore32/mm/flush.c
++++ b/arch/unicore32/mm/flush.c
+@@ -14,7 +14,6 @@
+ #include 
+ 
+ #include 
+-#include 
+ #include 
+ 
+ void flush_cache_mm(struct mm_struct *mm)
+diff --git a/arch/unicore32/mm/mm.h b/arch/unicore32/mm/mm.h
+index 3296bca0f1f7..05c7f532eee2 100644
+--- a/arch/unicore32/mm/mm.h
++++ b/arch/unicore32/mm/mm.h
+@@ -9,6 +9,8 @@
+  * it under the terms of the GNU General Public License version 2 as
+  * published by the Free Software Foundation.
+  */
++#include 
++
+ /* the upper-most page table pointer */
+ extern pmd_t *top_pmd;
+ extern int sysctl_overcommit_memory;
+@@ -34,6 +36,9 @@ struct mem_type {
+ const struct mem_type *get_mem_type(unsigned int type);
+ 
+ extern void __flush_dcache_page(struct address_space *, struct page *);
++extern void hook_fault_code(int nr, int (*fn)
++		(unsigned long, unsigned int, struct pt_regs *),
++		int sig, int code, const char *name);
+ 
+ void __init bootmem_init(void);
+ void uc32_mm_memblock_reserve(void);

commit b3a0aa3ae1c0889ffe8abb2e326d5c74c7c9c097
+Author: Guan Xuetao 
+Date:   Wed Dec 28 09:24:29 2011 +0800
+
+    rtc-puv3: solve section mismatch in rtc-puv3.c
+    
+    The patch renames puv3_rtcdrv to puv3_rtc_driver, so that modpost will know
+    that this is simply a list of pointers to driver functions, in which case
+    the section mismatch is OK. (Thanks Michal Marek)
+    
+    Cc: Axel Lin 
+    Cc: Michal Marek 
+    Cc: Arnd Bergmann 
+    Cc: Alessandro Zummo 
+    Cc: rtc-linux@googlegroups.com
+    Signed-off-by: Guan Xuetao 
+    
+    --
+    Section mismatch warning information:
+    
+    WARNING: drivers/rtc/built-in.o(.data+0x90): Section mismatch in
+    reference from the variable puv3_rtcdrv to the
+    function .devinit.text:puv3_rtc_probe()
+    The variable puv3_rtcdrv references
+    the function __devinit puv3_rtc_probe()
+    If the reference is valid then annotate the
+    variable with __init* or __refdata (see linux/init.h) or name the
+    variable:
+    *driver, *_template, *_timer, *_sht, *_ops, *_probe, *_probe_one,
+    *_console
+    
+    WARNING: drivers/rtc/built-in.o(.data+0x94): Section mismatch in
+    reference from the variable puv3_rtcdrv to the
+    function .devexit.text:puv3_rtc_remove()
+    The variable puv3_rtcdrv references
+    the function __devexit puv3_rtc_remove()
+    If the reference is valid then annotate the
+    variable with __exit* (see linux/init.h) or name the variable:
+    *driver, *_template, *_timer, *_sht, *_ops, *_probe, *_probe_one,
+    *_console
+    
+    WARNING: drivers/built-in.o(.data+0x6c04): Section mismatch in reference
+    from the variable puv3_rtcdrv to the
+    function .devinit.text:puv3_rtc_probe()
+    The variable puv3_rtcdrv references
+    the function __devinit puv3_rtc_probe()
+    If the reference is valid then annotate the
+    variable with __init* or __refdata (see linux/init.h) or name the
+    variable:
+    *driver, *_template, *_timer, *_sht, *_ops, *_probe, *_probe_one,
+    *_console
+    
+    WARNING: drivers/built-in.o(.data+0x6c08): Section mismatch in reference
+    from the variable puv3_rtcdrv to the
+    function .devexit.text:puv3_rtc_remove()
+    The variable puv3_rtcdrv references
+    the function __devexit puv3_rtc_remove()
+    If the reference is valid then annotate the
+    variable with __exit* (see linux/init.h) or name the variable:
+    *driver, *_template, *_timer, *_sht, *_ops, *_probe, *_probe_one,
+    *_console
+    
+    WARNING: vmlinux.o(.data+0x1126c): Section mismatch in reference from
+    the variable puv3_rtcdrv to the function .devinit.text:puv3_rtc_probe()
+    The variable puv3_rtcdrv references
+    the function __devinit puv3_rtc_probe()
+    If the reference is valid then annotate the
+    variable with __init* or __refdata (see linux/init.h) or name the
+    variable:
+    *driver, *_template, *_timer, *_sht, *_ops, *_probe, *_probe_one,
+    *_console
+    
+    WARNING: vmlinux.o(.data+0x11270): Section mismatch in reference from
+    the variable puv3_rtcdrv to the function .devexit.text:puv3_rtc_remove()
+    The variable puv3_rtcdrv references
+    the function __devexit puv3_rtc_remove()
+    If the reference is valid then annotate the
+    variable with __exit* (see linux/init.h) or name the variable:
+    *driver, *_template, *_timer, *_sht, *_ops, *_probe, *_probe_one,
+    *_console
+
+diff --git a/drivers/rtc/rtc-puv3.c b/drivers/rtc/rtc-puv3.c
+index 6490a02b1703..ab0acaeb2371 100644
+--- a/drivers/rtc/rtc-puv3.c
++++ b/drivers/rtc/rtc-puv3.c
+@@ -326,7 +326,7 @@ static int puv3_rtc_resume(struct platform_device *pdev)
+ #define puv3_rtc_resume  NULL
+ #endif
+ 
+-static struct platform_driver puv3_rtcdrv = {
++static struct platform_driver puv3_rtc_driver = {
+ 	.probe		= puv3_rtc_probe,
+ 	.remove		= __devexit_p(puv3_rtc_remove),
+ 	.suspend	= puv3_rtc_suspend,
+@@ -337,7 +337,7 @@ static struct platform_driver puv3_rtcdrv = {
+ 	}
+ };
+ 
+-module_platform_driver(puv3_rtcdrv);
++module_platform_driver(puv3_rtc_driver);
+ 
+ MODULE_DESCRIPTION("RTC Driver for the PKUnity v3 chip");
+ MODULE_AUTHOR("Hu Dongliang");

commit 60e2b00ea200e1527668bfb766ecbdf578ad7de8
+Author: Guan Xuetao 
+Date:   Mon Dec 26 17:03:50 2011 +0800
+
+    rtc-puv3: using module_platform_driver()
+    
+    This patch converts the driver to use the module_platform_driver()
+    macro which makes the code smaller and a bit simpler.
+    
+    Signed-off-by: Axel Lin 
+    Signed-off-by: Guan Xuetao 
+
+diff --git a/drivers/rtc/rtc-puv3.c b/drivers/rtc/rtc-puv3.c
+index 540ead3cb3c7..6490a02b1703 100644
+--- a/drivers/rtc/rtc-puv3.c
++++ b/drivers/rtc/rtc-puv3.c
+@@ -337,21 +337,7 @@ static struct platform_driver puv3_rtcdrv = {
+ 	}
+ };
+ 
+-static char __initdata banner[] = "PKUnity-v3 RTC, (c) 2009 PKUnity Co.\n";
+-
+-static int __init puv3_rtc_init(void)
+-{
+-	printk(banner);
+-	return platform_driver_register(&puv3_rtcdrv);
+-}
+-
+-static void __exit puv3_rtc_exit(void)
+-{
+-	platform_driver_unregister(&puv3_rtcdrv);
+-}
+-
+-module_init(puv3_rtc_init);
+-module_exit(puv3_rtc_exit);
++module_platform_driver(puv3_rtcdrv);
+ 
+ MODULE_DESCRIPTION("RTC Driver for the PKUnity v3 chip");
+ MODULE_AUTHOR("Hu Dongliang");

commit 858af58f67d4aba8afb02438e74292b9273cdb10
+Author: Guan Xuetao 
+Date:   Mon Dec 26 16:59:34 2011 +0800
+
+    i2c-puv3: using module_platform_driver()
+    
+    This patch converts the driver to use the module_platform_driver()
+    macro which makes the code smaller and a bit simpler.
+    
+    Signed-off-by: Axel Lin 
+    Signed-off-by: Guan Xuetao 
+
+diff --git a/drivers/i2c/busses/i2c-puv3.c b/drivers/i2c/busses/i2c-puv3.c
+index fac673940849..93709fbe30eb 100644
+--- a/drivers/i2c/busses/i2c-puv3.c
++++ b/drivers/i2c/busses/i2c-puv3.c
+@@ -276,8 +276,6 @@ static int puv3_i2c_resume(struct platform_device *dev)
+ #define puv3_i2c_resume NULL
+ #endif
+ 
+-MODULE_ALIAS("platform:puv3_i2c");
+-
+ static struct platform_driver puv3_i2c_driver = {
+ 	.probe		= puv3_i2c_probe,
+ 	.remove		= __devexit_p(puv3_i2c_remove),
+@@ -289,18 +287,8 @@ static struct platform_driver puv3_i2c_driver = {
+ 	}
+ };
+ 
+-static int __init puv3_i2c_init(void)
+-{
+-	return platform_driver_register(&puv3_i2c_driver);
+-}
+-
+-static void __exit puv3_i2c_exit(void)
+-{
+-	platform_driver_unregister(&puv3_i2c_driver);
+-}
+-
+-module_init(puv3_i2c_init);
+-module_exit(puv3_i2c_exit);
++module_platform_driver(puv3_i2c_driver);
+ 
+ MODULE_DESCRIPTION("PKUnity v3 I2C driver");
+ MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:puv3_i2c");

commit a9196b0bd3284fa3388998c9208a708a8f2e4c83
+Author: Guan Xuetao 
+Date:   Fri Dec 23 09:15:39 2011 +0800
+
+    rtc-puv3: irq: remove IRQF_DISABLED
+    
+    This flag is deprecated, so is removed now.
+    
+    Signed-off-by: Yong Zhang 
+    Signed-off-by: Guan Xuetao 
+
+diff --git a/drivers/rtc/rtc-puv3.c b/drivers/rtc/rtc-puv3.c
+index e4b6880aabd0..540ead3cb3c7 100644
+--- a/drivers/rtc/rtc-puv3.c
++++ b/drivers/rtc/rtc-puv3.c
+@@ -164,7 +164,7 @@ static int puv3_rtc_open(struct device *dev)
+ 	int ret;
+ 
+ 	ret = request_irq(puv3_rtc_alarmno, puv3_rtc_alarmirq,
+-			  IRQF_DISABLED,  "pkunity-rtc alarm", rtc_dev);
++			0, "pkunity-rtc alarm", rtc_dev);
+ 
+ 	if (ret) {
+ 		dev_err(dev, "IRQ%d error %d\n", puv3_rtc_alarmno, ret);
+@@ -172,7 +172,7 @@ static int puv3_rtc_open(struct device *dev)
+ 	}
+ 
+ 	ret = request_irq(puv3_rtc_tickno, puv3_rtc_tickirq,
+-			  IRQF_DISABLED,  "pkunity-rtc tick", rtc_dev);
++			0, "pkunity-rtc tick", rtc_dev);
+ 
+ 	if (ret) {
+ 		dev_err(dev, "IRQ%d error %d\n", puv3_rtc_tickno, ret);

commit a50e4213e71adc7dde0d514aabd8af7275fee39f
+Author: Guan Xuetao 
+Date:   Thu Aug 18 15:38:05 2011 +0800
+
+    unicore32: add ioremap_nocache definition
+    
+    Bugfix for following error messages:
+    lib/iomap.c: In function 'pci_iomap':
+    lib/iomap.c:274: error: implicit declaration of function 'ioremap_nocache'
+    lib/iomap.c:274: warning: return makes pointer from integer without a cast
+    
+    Also see commit 
+      it will hide the ioremap_nocache function for systems with an MMU
+    
+    Signed-off-by: Guan Xuetao 
+    Cc: Arnd Bergmann 
+    Cc: Jonas Bonn 
+
+diff --git a/arch/unicore32/include/asm/io.h b/arch/unicore32/include/asm/io.h
+index a75ad0b117cc..adddf6d64077 100644
+--- a/arch/unicore32/include/asm/io.h
++++ b/arch/unicore32/include/asm/io.h
+@@ -37,6 +37,7 @@ extern void __uc32_iounmap(volatile void __iomem *addr);
+  */
+ #define ioremap(cookie, size)		__uc32_ioremap(cookie, size)
+ #define ioremap_cached(cookie, size)	__uc32_ioremap_cached(cookie, size)
++#define ioremap_nocache(cookie, size)	__uc32_ioremap(cookie, size)
+ #define iounmap(cookie)			__uc32_iounmap(cookie)
+ 
+ #define HAVE_ARCH_PIO_SIZE

commit 62439a2954b9027c9ec481e1d39cd5d63f7c1b17
+Author: Guan Xuetao 
+Date:   Thu Aug 18 15:43:10 2011 +0800
+
+    unicore32: delete specified xlate_dev_mem_ptr
+    
+    For the commit  has changed
+    xlate_dev_mem_ptr definition in asm-generic/io.h for the systems with
+    an MMU, so delete it from unicore32 specified io.h.
+    
+    Signed-off-by: Guan Xuetao 
+    Cc: Arnd Bergmann 
+    Cc: Jonas Bonn 
+
+diff --git a/arch/unicore32/include/asm/io.h b/arch/unicore32/include/asm/io.h
+index 1a5c5a5eb39c..a75ad0b117cc 100644
+--- a/arch/unicore32/include/asm/io.h
++++ b/arch/unicore32/include/asm/io.h
+@@ -39,13 +39,6 @@ extern void __uc32_iounmap(volatile void __iomem *addr);
+ #define ioremap_cached(cookie, size)	__uc32_ioremap_cached(cookie, size)
+ #define iounmap(cookie)			__uc32_iounmap(cookie)
+ 
+-/*
+- * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+- * access
+- */
+-#undef xlate_dev_mem_ptr
+-#define xlate_dev_mem_ptr(p)	__va(p)
+-
+ #define HAVE_ARCH_PIO_SIZE
+ #define PIO_OFFSET		(unsigned int)(PCI_IOBASE)
+ #define PIO_MASK		(unsigned int)(IO_SPACE_LIMIT)

commit eb52d5801302a3515506891c13338fbaa7222f36
+Author: Yu Yue 
+Date:   Fri Aug 26 18:03:42 2011 +0800
+
+    of: add include asm/setup.h in drivers/of/fdt.c
+    
+    In the file drivers/of/fdt.c, it uses the COMMAND_LINE_SIZE which is stated
+    in asm/setup.h, so asm/setup.h should be included in drivers/of/fdt.c.
+    
+    Signed-off-by: Yu Yue 
+    Signed-off-by: Guan Xuetao 
+    
+    Cc: Grant Likerly 
+    Cc: devicetree-discuss@lists.ozlabs.org
+    Cc: Arnd Bergmann 
+
+diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
+index 91a375fb6ae6..ea2bd1be2640 100644
+--- a/drivers/of/fdt.c
++++ b/drivers/of/fdt.c
+@@ -23,6 +23,7 @@
+ #include 
+ #endif /* CONFIG_PPC */
+ 
++#include 
+ #include 
+ 
+ char *of_fdt_get_string(struct boot_param_header *blob, u32 offset)

commit e13b91c1c47e7be178d2d7914452040ee82c0bd2
+Author: Guan Xuetao 
+Date:   Mon Jun 13 11:44:49 2011 +0800
+
+    unicore32: fix build error for find bitops
+    
+    Remove the __uc32_ prefix in find bitops functions.
+    Move find_* macros behind asm-generic/bitops.h inclusion.
+    see commit <19de85ef574c3a2182e3ccad9581805052f14946>
+      bitops: add #ifndef for each of find bitops
+    also see commit <63e424c84429903c92a0f1e9654c31ccaf6694d0>
+      arch: remove CONFIG_GENERIC_FIND_{NEXT_BIT,BIT_LE,LAST_BIT}
+    
+    Signed-off-by: Guan Xuetao 
+    Cc: Akinobu Mita 
+    Acked-by: Akinobu Mita 
+    Cc: Arnd Bergmann 
+
+diff --git a/arch/unicore32/include/asm/bitops.h b/arch/unicore32/include/asm/bitops.h
+index 1628a6328994..401f597bc38c 100644
+--- a/arch/unicore32/include/asm/bitops.h
++++ b/arch/unicore32/include/asm/bitops.h
+@@ -13,12 +13,6 @@
+ #ifndef __UNICORE_BITOPS_H__
+ #define __UNICORE_BITOPS_H__
+ 
+-#define find_next_bit		__uc32_find_next_bit
+-#define find_next_zero_bit	__uc32_find_next_zero_bit
+-
+-#define find_first_bit		__uc32_find_first_bit
+-#define find_first_zero_bit	__uc32_find_first_zero_bit
+-
+ #define _ASM_GENERIC_BITOPS_FLS_H_
+ #define _ASM_GENERIC_BITOPS___FLS_H_
+ #define _ASM_GENERIC_BITOPS_FFS_H_
+@@ -44,4 +38,10 @@ static inline int fls(int x)
+ 
+ #include 
+ 
++/* following definitions: to avoid using codes in lib/find_*.c */
++#define find_next_bit		find_next_bit
++#define find_next_zero_bit	find_next_zero_bit
++#define find_first_bit		find_first_bit
++#define find_first_zero_bit	find_first_zero_bit
++
+ #endif /* __UNICORE_BITOPS_H__ */
+diff --git a/arch/unicore32/kernel/ksyms.c b/arch/unicore32/kernel/ksyms.c
+index a8970809428a..d98bd812cae1 100644
+--- a/arch/unicore32/kernel/ksyms.c
++++ b/arch/unicore32/kernel/ksyms.c
+@@ -24,8 +24,8 @@
+ 
+ #include "ksyms.h"
+ 
+-EXPORT_SYMBOL(__uc32_find_next_zero_bit);
+-EXPORT_SYMBOL(__uc32_find_next_bit);
++EXPORT_SYMBOL(find_next_zero_bit);
++EXPORT_SYMBOL(find_next_bit);
+ 
+ EXPORT_SYMBOL(__backtrace);
+ 
+diff --git a/arch/unicore32/lib/findbit.S b/arch/unicore32/lib/findbit.S
+index c360ce905d8b..c77746247d36 100644
+--- a/arch/unicore32/lib/findbit.S
++++ b/arch/unicore32/lib/findbit.S
+@@ -17,7 +17,7 @@
+  * Purpose  : Find a 'zero' bit
+  * Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit);
+  */
+-__uc32_find_first_zero_bit:
++ENTRY(find_first_zero_bit)
+ 		cxor.a	r1, #0
+ 		beq	3f
+ 		mov	r2, #0
+@@ -29,13 +29,14 @@ __uc32_find_first_zero_bit:
+ 		bub	1b
+ 3:		mov	r0, r1			@ no free bits
+ 		mov	pc, lr
++ENDPROC(find_first_zero_bit)
+ 
+ /*
+  * Purpose  : Find next 'zero' bit
+  * Prototype: int find_next_zero_bit
+  *		(void *addr, unsigned int maxbit, int offset)
+  */
+-ENTRY(__uc32_find_next_zero_bit)
++ENTRY(find_next_zero_bit)
+ 		cxor.a	r1, #0
+ 		beq	3b
+ 		and.a	ip, r2, #7
+@@ -47,14 +48,14 @@ ENTRY(__uc32_find_next_zero_bit)
+ 		or	r2, r2, #7		@ if zero, then no bits here
+ 		add	r2, r2, #1		@ align bit pointer
+ 		b	2b			@ loop for next bit
+-ENDPROC(__uc32_find_next_zero_bit)
++ENDPROC(find_next_zero_bit)
+ 
+ /*
+  * Purpose  : Find a 'one' bit
+  * Prototype: int find_first_bit
+  *		(const unsigned long *addr, unsigned int maxbit);
+  */
+-__uc32_find_first_bit:
++ENTRY(find_first_bit)
+ 		cxor.a	r1, #0
+ 		beq	3f
+ 		mov	r2, #0
+@@ -66,13 +67,14 @@ __uc32_find_first_bit:
+ 		bub	1b
+ 3:		mov	r0, r1			@ no free bits
+ 		mov	pc, lr
++ENDPROC(find_first_bit)
+ 
+ /*
+  * Purpose  : Find next 'one' bit
+  * Prototype: int find_next_zero_bit
+  *		(void *addr, unsigned int maxbit, int offset)
+  */
+-ENTRY(__uc32_find_next_bit)
++ENTRY(find_next_bit)
+ 		cxor.a	r1, #0
+ 		beq	3b
+ 		and.a	ip, r2, #7
+@@ -83,7 +85,7 @@ ENTRY(__uc32_find_next_bit)
+ 		or	r2, r2, #7		@ if zero, then no bits here
+ 		add	r2, r2, #1		@ align bit pointer
+ 		b	2b			@ loop for next bit
+-ENDPROC(__uc32_find_next_bit)
++ENDPROC(find_next_bit)
+ 
+ /*
+  * One or more bits in the LSB of r3 are assumed to be set.

commit 62b62c5c29468412cadd39dfb1113d3f0a323cfe
+Author: Guan Xuetao 
+Date:   Thu May 26 18:17:43 2011 +0800
+
+    unicore32: using generic-y format for one line asm-generic files
+    
+    The patch adds one-line asm-generic files in arch/unicore32/include/asm/Kbuild
+    Also, remove the old implementation in arch/unicore32/Makefile
+    see commit from Sam Ravnborg 
+      kbuild: asm-generic support
+    
+    Signed-off-by: Guan Xuetao 
+    Acked-by: Arnd Bergmann 
+
+diff --git a/arch/unicore32/Makefile b/arch/unicore32/Makefile
+index 6555abbaeb87..6af4bc415f2b 100644
+--- a/arch/unicore32/Makefile
++++ b/arch/unicore32/Makefile
+@@ -40,39 +40,6 @@ core-y			+= arch/unicore32/mm/
+ 
+ libs-y			+= arch/unicore32/lib/
+ 
+-ASM_GENERATED_DIR	:= $(srctree)/arch/unicore32/include/generated
+-LINUXINCLUDE		+= -I$(ASM_GENERATED_DIR)
+-
+-ASM_GENERIC_HEADERS	:= atomic.h auxvec.h
+-ASM_GENERIC_HEADERS	+= bitsperlong.h bug.h bugs.h
+-ASM_GENERIC_HEADERS	+= cputime.h current.h
+-ASM_GENERIC_HEADERS	+= device.h div64.h
+-ASM_GENERIC_HEADERS	+= emergency-restart.h errno.h
+-ASM_GENERIC_HEADERS	+= fb.h fcntl.h ftrace.h futex.h
+-ASM_GENERIC_HEADERS	+= hardirq.h hw_irq.h
+-ASM_GENERIC_HEADERS	+= ioctl.h ioctls.h ipcbuf.h irq_regs.h
+-ASM_GENERIC_HEADERS	+= kdebug.h kmap_types.h
+-ASM_GENERIC_HEADERS	+= local.h
+-ASM_GENERIC_HEADERS	+= mman.h module.h msgbuf.h
+-ASM_GENERIC_HEADERS	+= param.h parport.h percpu.h poll.h posix_types.h
+-ASM_GENERIC_HEADERS	+= resource.h
+-ASM_GENERIC_HEADERS	+= scatterlist.h sections.h segment.h sembuf.h serial.h
+-ASM_GENERIC_HEADERS	+= setup.h shmbuf.h shmparam.h
+-ASM_GENERIC_HEADERS	+= siginfo.h signal.h sizes.h
+-ASM_GENERIC_HEADERS	+= socket.h sockios.h stat.h statfs.h swab.h syscalls.h
+-ASM_GENERIC_HEADERS	+= termbits.h termios.h topology.h types.h
+-ASM_GENERIC_HEADERS	+= ucontext.h unaligned.h user.h
+-ASM_GENERIC_HEADERS	+= vga.h
+-ASM_GENERIC_HEADERS	+= xor.h
+-
+-archprepare:
+-ifneq ($(ASM_GENERATED_DIR), $(wildcard $(ASM_GENERATED_DIR)))
+-	$(Q)mkdir -p $(ASM_GENERATED_DIR)/asm
+-	$(Q)$(foreach a, $(ASM_GENERIC_HEADERS),	\
+-		echo '#include '	\
+-			> $(ASM_GENERATED_DIR)/asm/$a; )
+-endif
+-
+ boot			:= arch/unicore32/boot
+ 
+ # Default defconfig and target when executing plain make
+@@ -84,8 +51,6 @@ all:	$(KBUILD_IMAGE)
+ zImage Image uImage: vmlinux
+ 	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+ 
+-MRPROPER_DIRS		+= $(ASM_GENERATED_DIR)
+-
+ archclean:
+ 	$(Q)$(MAKE) $(clean)=$(boot)
+ 
+diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
+index b200fdaca44d..ca113d6999c5 100644
+--- a/arch/unicore32/include/asm/Kbuild
++++ b/arch/unicore32/include/asm/Kbuild
+@@ -1,2 +1,61 @@
+ include include/asm-generic/Kbuild.asm
+ 
++generic-y += atomic.h
++generic-y += auxvec.h
++generic-y += bitsperlong.h
++generic-y += bug.h
++generic-y += bugs.h
++generic-y += cputime.h
++generic-y += current.h
++generic-y += device.h
++generic-y += div64.h
++generic-y += emergency-restart.h
++generic-y += errno.h
++generic-y += fb.h
++generic-y += fcntl.h
++generic-y += ftrace.h
++generic-y += futex.h
++generic-y += hardirq.h
++generic-y += hw_irq.h
++generic-y += ioctl.h
++generic-y += ioctls.h
++generic-y += ipcbuf.h
++generic-y += irq_regs.h
++generic-y += kdebug.h
++generic-y += kmap_types.h
++generic-y += local.h
++generic-y += mman.h
++generic-y += module.h
++generic-y += msgbuf.h
++generic-y += param.h
++generic-y += parport.h
++generic-y += percpu.h
++generic-y += poll.h
++generic-y += posix_types.h
++generic-y += resource.h
++generic-y += scatterlist.h
++generic-y += sections.h
++generic-y += segment.h
++generic-y += sembuf.h
++generic-y += serial.h
++generic-y += setup.h
++generic-y += shmbuf.h
++generic-y += shmparam.h
++generic-y += siginfo.h
++generic-y += signal.h
++generic-y += sizes.h
++generic-y += socket.h
++generic-y += sockios.h
++generic-y += stat.h
++generic-y += statfs.h
++generic-y += swab.h
++generic-y += syscalls.h
++generic-y += termbits.h
++generic-y += termios.h
++generic-y += topology.h
++generic-y += types.h
++generic-y += ucontext.h
++generic-y += unaligned.h
++generic-y += user.h
++generic-y += vga.h
++generic-y += xor.h

commit 42733b3c4861799b3c30c1e416099324bb577960
+Author: Guan Xuetao 
+Date:   Thu May 26 17:19:20 2011 +0800
+
+    unicore32: change PERCPU to PERCPU_SECTION
+    
+    The patch changes PERCPU to PERCPU_SECTION
+    see commit from Tejun Heo <0415b00d175e0d8945e6785aad21b5f157976ce0>
+      percpu: Always align percpu output section to PAGE_SIZE
+    
+    Signed-off-by: Guan Xuetao 
+    Acked-by: Tejun Heo 
+
+diff --git a/arch/unicore32/kernel/vmlinux.lds.S b/arch/unicore32/kernel/vmlinux.lds.S
+index 9bf7f7af52c5..77e407e49a63 100644
+--- a/arch/unicore32/kernel/vmlinux.lds.S
++++ b/arch/unicore32/kernel/vmlinux.lds.S
+@@ -30,7 +30,7 @@ SECTIONS
+ 	HEAD_TEXT_SECTION
+ 	INIT_TEXT_SECTION(PAGE_SIZE)
+ 	INIT_DATA_SECTION(16)
+-	PERCPU(L1_CACHE_BYTES, PAGE_SIZE)
++	PERCPU_SECTION(L1_CACHE_BYTES)
+ 	__init_end = .;
+ 
+ 	_stext = .;

commit 978b42e6f6f48560b18661a5e187aec7329a094b
+Author: Guan Xuetao 
+Date:   Mon May 16 15:28:19 2011 +0800
+
+    unicore32: add KBUILD_DEFCONFIG with unicore32_defconfig (old debug_defconfig)
+    
+    Rename debug_defconfig to unicore32_defconfig, which is a minimal config for
+    PKUnity-v3 (130nm) SoC board.
+    Also, add KBUILD_DEFCONFIG to use 'make defconfig'.
+    
+    Signed-off-by: Guan Xuetao 
+    Acked-by: Arnd Bergmann 
+
+diff --git a/arch/unicore32/Makefile b/arch/unicore32/Makefile
+index 76a8beec7d03..6555abbaeb87 100644
+--- a/arch/unicore32/Makefile
++++ b/arch/unicore32/Makefile
+@@ -75,7 +75,8 @@ endif
+ 
+ boot			:= arch/unicore32/boot
+ 
+-# Default target when executing plain make
++# Default defconfig and target when executing plain make
++KBUILD_DEFCONFIG	:= $(ARCH)_defconfig
+ KBUILD_IMAGE		:= zImage
+ 
+ all:	$(KBUILD_IMAGE)
+diff --git a/arch/unicore32/configs/debug_defconfig b/arch/unicore32/configs/unicore32_defconfig
+similarity index 99%
+rename from arch/unicore32/configs/debug_defconfig
+rename to arch/unicore32/configs/unicore32_defconfig
+index 9b9c2519a38f..c9dd3198b6f7 100644
+--- a/arch/unicore32/configs/debug_defconfig
++++ b/arch/unicore32/configs/unicore32_defconfig
+@@ -1,6 +1,6 @@
+ ### General setup
+ CONFIG_EXPERIMENTAL=y
+-CONFIG_LOCALVERSION="-debug"
++CONFIG_LOCALVERSION="-unicore32"
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ CONFIG_POSIX_MQUEUE=y

commit f4728fd21f6d81bb2100da7eb9c675f1a74ad30d
+Author: Guan Xuetao 
+Date:   Wed Apr 20 19:06:53 2011 +0800
+
+    unicore32: change zImage physical address, though it's PIC codes
+    
+    U-boot will load the kernel image to 48M physical memory address.
+    The patch changes it to the correct address, though it's PIC codes.
+    
+    Signed-off-by: Guan Xuetao 
+    Acked-by: Arnd Bergmann 
+
+diff --git a/arch/unicore32/boot/compressed/Makefile b/arch/unicore32/boot/compressed/Makefile
+index 95373428cb3d..b0954a2d23cf 100644
+--- a/arch/unicore32/boot/compressed/Makefile
++++ b/arch/unicore32/boot/compressed/Makefile
+@@ -59,7 +59,7 @@ $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/head.o $(obj)/piggy.o \
+ # We now have a PIC decompressor implementation.  Decompressors running
+ # from RAM should not define ZTEXTADDR.  Decompressors running directly
+ # from ROM or Flash must define ZTEXTADDR (preferably via the config)
+-ZTEXTADDR	:= 0
++ZTEXTADDR	:= 0x03000000
+ ZBSSADDR	:= ALIGN(4)
+ 
+ SEDFLAGS_lds	= s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/

commit 2809e80b8a73d556b2302e273966fb15db16c51e
+Author: Guan Xuetao 
+Date:   Thu May 26 16:43:27 2011 +0800
+
+    unicore32: move rtc-puv3.c to drivers/rtc directory
+    
+    The patch moves rtc driver for PKUnity-v3 SoC from arch/unicore32/kernel/
+    to drivers/rtc/, with renaming it to rtc-puv3.c.
+    Also, Kconfig, Makefile, and MAINTAINERS are modified correspondingly.
+    
+    Signed-off-by: Guan Xuetao 
+    Acked-by: Arnd Bergmann 
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index b5ea4d033730..bbe49d8c22af 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -4945,6 +4945,7 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/epip/linux-2.6-unicore32.gi
+ F:	drivers/input/serio/i8042-unicore32io.h
+ F:	drivers/i2c/busses/i2c-puv3.c
+ F:	drivers/video/fb-puv3.c
++F:	drivers/rtc/rtc-puv3.c
+ 
+ PMC SIERRA MaxRAID DRIVER
+ M:	Anil Ravindranath 
+diff --git a/arch/unicore32/Kconfig b/arch/unicore32/Kconfig
+index d3a303246c9f..e57dcce9bfda 100644
+--- a/arch/unicore32/Kconfig
++++ b/arch/unicore32/Kconfig
+@@ -231,10 +231,6 @@ config PUV3_PWM
+ 	help
+ 	  Enable support for NB0916 PWM controllers
+ 
+-config PUV3_RTC
+-	tristate "PKUnity v3 RTC Support"
+-	depends on !ARCH_FPGA
+-
+ if PUV3_NB0916
+ 
+ menu "PKUnity NetBook-0916 Features"
+diff --git a/arch/unicore32/configs/debug_defconfig b/arch/unicore32/configs/debug_defconfig
+index b5fbde9f1cb2..9b9c2519a38f 100644
+--- a/arch/unicore32/configs/debug_defconfig
++++ b/arch/unicore32/configs/debug_defconfig
+@@ -64,7 +64,6 @@ CONFIG_I2C_BATTERY_BQ27200=n
+ CONFIG_I2C_EEPROM_AT24=n
+ CONFIG_LCD_BACKLIGHT=n
+ 
+-CONFIG_PUV3_RTC=y
+ CONFIG_PUV3_UMAL=y
+ CONFIG_PUV3_MUSB=n
+ CONFIG_PUV3_AC97=n
+@@ -167,8 +166,9 @@ CONFIG_LEDS_TRIGGER_IDE_DISK=y
+ CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+ 
+ #	Real Time Clock
+-CONFIG_RTC_LIB=m
+-CONFIG_RTC_CLASS=m
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_DRV_PUV3=y
+ 
+ ### File systems
+ CONFIG_EXT2_FS=m
+diff --git a/arch/unicore32/kernel/Makefile b/arch/unicore32/kernel/Makefile
+index ec23a2fb2f50..aeb0f181568e 100644
+--- a/arch/unicore32/kernel/Makefile
++++ b/arch/unicore32/kernel/Makefile
+@@ -16,7 +16,6 @@ obj-$(CONFIG_UNICORE_FPU_F64)	+= fpu-ucf64.o
+ obj-$(CONFIG_ARCH_PUV3)		+= clock.o irq.o time.o
+ 
+ obj-$(CONFIG_PUV3_GPIO)		+= gpio.o
+-obj-$(CONFIG_PUV3_RTC)		+= rtc.o
+ obj-$(CONFIG_PUV3_PWM)		+= pwm.o
+ obj-$(CONFIG_PUV3_PM)		+= pm.o sleep.o
+ obj-$(CONFIG_HIBERNATION)	+= hibernate.o hibernate_asm.o
+diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
+index f822e13dc04b..ce2aabf5c550 100644
+--- a/drivers/rtc/Kconfig
++++ b/drivers/rtc/Kconfig
+@@ -1051,4 +1051,13 @@ config RTC_DRV_TILE
+ 	  Enable support for the Linux driver side of the Tilera
+ 	  hypervisor's real-time clock interface.
+ 
++config RTC_DRV_PUV3
++	tristate "PKUnity v3 RTC support"
++	depends on ARCH_PUV3
++	help
++	  This enables support for the RTC in the PKUnity-v3 SoCs.
++
++	  This drive can also be built as a module. If so, the module
++	  will be called rtc-puv3.
++
+ endif # RTC_CLASS
+diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
+index 213d725f16d4..0ffefe877bfa 100644
+--- a/drivers/rtc/Makefile
++++ b/drivers/rtc/Makefile
+@@ -78,6 +78,7 @@ obj-$(CONFIG_RTC_DRV_PCF50633)	+= rtc-pcf50633.o
+ obj-$(CONFIG_RTC_DRV_PL030)	+= rtc-pl030.o
+ obj-$(CONFIG_RTC_DRV_PL031)	+= rtc-pl031.o
+ obj-$(CONFIG_RTC_DRV_PS3)	+= rtc-ps3.o
++obj-$(CONFIG_RTC_DRV_PUV3)	+= rtc-puv3.o
+ obj-$(CONFIG_RTC_DRV_PXA)	+= rtc-pxa.o
+ obj-$(CONFIG_RTC_DRV_R9701)	+= rtc-r9701.o
+ obj-$(CONFIG_RTC_DRV_RP5C01)	+= rtc-rp5c01.o
+diff --git a/arch/unicore32/kernel/rtc.c b/drivers/rtc/rtc-puv3.c
+similarity index 98%
+rename from arch/unicore32/kernel/rtc.c
+rename to drivers/rtc/rtc-puv3.c
+index 8cad70b3302c..46f14b82f3ab 100644
+--- a/arch/unicore32/kernel/rtc.c
++++ b/drivers/rtc/rtc-puv3.c
+@@ -1,7 +1,5 @@
+ /*
+- * linux/arch/unicore32/kernel/rtc.c
+- *
+- * Code specific to PKUnity SoC and UniCore ISA
++ * RTC driver code specific to PKUnity SoC and UniCore ISA
+  *
+  *	Maintained by GUAN Xue-tao 
+  *	Copyright (C) 2001-2010 Guan Xuetao
+@@ -36,7 +34,6 @@ static int puv3_rtc_tickno  = IRQ_RTC;
+ static DEFINE_SPINLOCK(puv3_rtc_pie_lock);
+ 
+ /* IRQ Handlers */
+-
+ static irqreturn_t puv3_rtc_alarmirq(int irq, void *id)
+ {
+ 	struct rtc_device *rdev = id;
+@@ -89,7 +86,6 @@ static int puv3_rtc_setpie(struct device *dev, int enabled)
+ }
+ 
+ /* Time read/write */
+-
+ static int puv3_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
+ {
+ 	rtc_time_to_tm(readl(RTC_RCNR), rtc_tm);
+@@ -196,7 +192,6 @@ static void puv3_rtc_release(struct device *dev)
+ 	struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
+ 
+ 	/* do not clear AIE here, it may be needed for wake */
+-
+ 	puv3_rtc_setpie(dev, 0);
+ 	free_irq(puv3_rtc_alarmno, rtc_dev);
+ 	free_irq(puv3_rtc_tickno, rtc_dev);
+@@ -218,7 +213,6 @@ static void puv3_rtc_enable(struct platform_device *pdev, int en)
+ 		writel(readl(RTC_RTSR) & ~RTC_RTSR_HZE, RTC_RTSR);
+ 	} else {
+ 		/* re-enable the device, and check it is ok */
+-
+ 		if ((readl(RTC_RTSR) & RTC_RTSR_HZE) == 0) {
+ 			dev_info(&pdev->dev, "rtc disabled, re-enabling\n");
+ 			writel(readl(RTC_RTSR) | RTC_RTSR_HZE, RTC_RTSR);
+@@ -251,7 +245,6 @@ static int puv3_rtc_probe(struct platform_device *pdev)
+ 	pr_debug("%s: probe=%p\n", __func__, pdev);
+ 
+ 	/* find the IRQs */
+-
+ 	puv3_rtc_tickno = platform_get_irq(pdev, 1);
+ 	if (puv3_rtc_tickno < 0) {
+ 		dev_err(&pdev->dev, "no irq for rtc tick\n");
+@@ -268,7 +261,6 @@ static int puv3_rtc_probe(struct platform_device *pdev)
+ 		 puv3_rtc_tickno, puv3_rtc_alarmno);
+ 
+ 	/* get the memory region */
+-
+ 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ 	if (res == NULL) {
+ 		dev_err(&pdev->dev, "failed to get memory region resource\n");
+@@ -288,7 +280,6 @@ static int puv3_rtc_probe(struct platform_device *pdev)
+ 	puv3_rtc_enable(pdev, 1);
+ 
+ 	/* register RTC and exit */
+-
+ 	rtc = rtc_device_register("pkunity", &pdev->dev, &puv3_rtcops,
+ 				  THIS_MODULE);
+ 
+@@ -315,8 +306,6 @@ static int puv3_rtc_probe(struct platform_device *pdev)
+ 
+ #ifdef CONFIG_PM
+ 
+-/* RTC Power management control */
+-
+ static int ticnt_save;
+ 
+ static int puv3_rtc_suspend(struct platform_device *pdev, pm_message_t state)
+@@ -368,4 +357,3 @@ module_exit(puv3_rtc_exit);
+ MODULE_DESCRIPTION("RTC Driver for the PKUnity v3 chip");
+ MODULE_AUTHOR("Hu Dongliang");
+ MODULE_LICENSE("GPL v2");
+-

commit 6b794743b2c5e21825d35b5d5dd57d6fcc388198
+Author: Guan Xuetao 
+Date:   Fri Apr 1 16:38:59 2011 +0800
+
+    unicore32 framebuffer fix: get videomemory by __get_free_pages() and make it floatable
+    
+    1. get videomemory by __get_free_pages() in fb-puv3.c
+    2. remove resource reservation for old fixed UNIGFX_MMAP & UVC_MMAP space
+    3. remove unused macros: PKUNTIY_UNIGFX_MMAP_BASE, PKUNITY_UNIGFX_MMAP_SIZE,
+            PKUNITY_UVC_MMAP_BASE, PKUNITY_UVC_MMAP_SIZE and KUSER_UNIGFX_BASE
+    4. remove unused header linux/vmalloc.h in fb-puv3.h
+    
+    Signed-off-by: Guan Xuetao 
+    Acked-by: Arnd Bergmann 
+
+diff --git a/arch/unicore32/include/mach/PKUnity.h b/arch/unicore32/include/mach/PKUnity.h
+index a18bdc3810e6..8040d575dddb 100644
+--- a/arch/unicore32/include/mach/PKUnity.h
++++ b/arch/unicore32/include/mach/PKUnity.h
+@@ -23,16 +23,6 @@
+ #define PKUNITY_SDRAM_BASE		0x00000000 /* 0x00000000 - 0x7FFFFFFF 2GB */
+ #define PKUNITY_MMIO_BASE		0x80000000 /* 0x80000000 - 0xFFFFFFFF 2GB */
+ 
+-/*
+- * PKUNITY Memory Map Addresses: 0x0D000000 - 0x0EFFFFFF (32MB)
+- *	0x0D000000 - 0x0DFFFFFF 16MB: for UVC
+- *	0x0E000000 - 0x0EFFFFFF 16MB: for UNIGFX
+- */
+-#define PKUNITY_UVC_MMAP_BASE		0x0D000000
+-#define PKUNITY_UVC_MMAP_SIZE		0x01000000 /* 16MB */
+-#define PKUNITY_UNIGFX_MMAP_BASE        0x0E000000
+-#define PKUNITY_UNIGFX_MMAP_SIZE        0x01000000 /* 16MB */
+-
+ /*
+  * PKUNITY System Bus Addresses (PCI): 0x80000000 - 0xBFFFFFFF (1GB)
+  * 0x80000000 - 0x8000000B 12B    PCI Configuration regs
+diff --git a/arch/unicore32/include/mach/memory.h b/arch/unicore32/include/mach/memory.h
+index 0bf21c944710..4be72c21d491 100644
+--- a/arch/unicore32/include/mach/memory.h
++++ b/arch/unicore32/include/mach/memory.h
+@@ -50,7 +50,6 @@ void puv3_pci_adjust_zones(unsigned long *size, unsigned long *holes);
+ 
+ /* kuser area */
+ #define KUSER_VECPAGE_BASE	(KUSER_BASE + UL(0x3fff0000))
+-#define KUSER_UNIGFX_BASE	(PAGE_OFFSET + PKUNITY_UNIGFX_MMAP_BASE)
+ /* kuser_vecpage (0xbfff0000) is ro, and vectors page (0xffff0000) is rw */
+ #define kuser_vecpage_to_vectors(x)	((x) - (KUSER_VECPAGE_BASE)	\
+ 					+ (VECTORS_BASE))
+diff --git a/arch/unicore32/kernel/puv3-core.c b/arch/unicore32/kernel/puv3-core.c
+index 8b1b6beb858e..1a505a787765 100644
+--- a/arch/unicore32/kernel/puv3-core.c
++++ b/arch/unicore32/kernel/puv3-core.c
+@@ -99,11 +99,6 @@ static struct resource puv3_unigfx_resources[] = {
+ 		.end	= io_v2p(PKUNITY_UNIGFX_BASE) + 0xfff,
+ 		.flags	= IORESOURCE_MEM,
+ 	},
+-	[1] = {
+-		.start	= PKUNITY_UNIGFX_MMAP_BASE,
+-		.end	= PKUNITY_UNIGFX_MMAP_BASE + PKUNITY_UNIGFX_MMAP_SIZE,
+-		.flags	= IORESOURCE_MEM,
+-	},
+ };
+ 
+ static struct resource puv3_rtc_resources[] = {
+diff --git a/arch/unicore32/kernel/setup.c b/arch/unicore32/kernel/setup.c
+index 1e175a82844d..471b6bca8da4 100644
+--- a/arch/unicore32/kernel/setup.c
++++ b/arch/unicore32/kernel/setup.c
+@@ -63,12 +63,6 @@ static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
+  * Standard memory resources
+  */
+ static struct resource mem_res[] = {
+-	{
+-		.name = "Video RAM",
+-		.start = 0,
+-		.end = 0,
+-		.flags = IORESOURCE_MEM
+-	},
+ 	{
+ 		.name = "Kernel text",
+ 		.start = 0,
+@@ -83,9 +77,8 @@ static struct resource mem_res[] = {
+ 	}
+ };
+ 
+-#define video_ram   mem_res[0]
+-#define kernel_code mem_res[1]
+-#define kernel_data mem_res[2]
++#define kernel_code mem_res[0]
++#define kernel_data mem_res[1]
+ 
+ /*
+  * These functions re-use the assembly code in head.S, which
+@@ -224,10 +217,6 @@ request_standard_resources(struct meminfo *mi)
+ 		    kernel_data.end <= res->end)
+ 			request_resource(res, &kernel_data);
+ 	}
+-
+-	video_ram.start = PKUNITY_UNIGFX_MMAP_BASE;
+-	video_ram.end   = PKUNITY_UNIGFX_MMAP_BASE + PKUNITY_UNIGFX_MMAP_SIZE;
+-	request_resource(&iomem_resource, &video_ram);
+ }
+ 
+ static void (*init_machine)(void) __initdata;
+diff --git a/arch/unicore32/mm/mmu.c b/arch/unicore32/mm/mmu.c
+index 7bf3d588631f..db2d334941b4 100644
+--- a/arch/unicore32/mm/mmu.c
++++ b/arch/unicore32/mm/mmu.c
+@@ -338,15 +338,6 @@ void __init uc32_mm_memblock_reserve(void)
+ 	 * and can only be in node 0.
+ 	 */
+ 	memblock_reserve(__pa(swapper_pg_dir), PTRS_PER_PGD * sizeof(pgd_t));
+-
+-#ifdef CONFIG_PUV3_UNIGFX
+-	/*
+-	 * These should likewise go elsewhere.  They pre-reserve the
+-	 * screen/video memory region at the 48M~64M of main system memory.
+-	 */
+-	memblock_reserve(PKUNITY_UNIGFX_MMAP_BASE, PKUNITY_UNIGFX_MMAP_SIZE);
+-	memblock_reserve(PKUNITY_UVC_MMAP_BASE, PKUNITY_UVC_MMAP_SIZE);
+-#endif
+ }
+ 
+ /*
+@@ -370,17 +361,6 @@ static void __init devicemaps_init(void)
+ 	for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE)
+ 		pmd_clear(pmd_off_k(addr));
+ 
+-	/*
+-	 * Create a mapping for UniGFX VRAM
+-	 */
+-#ifdef CONFIG_PUV3_UNIGFX
+-	map.pfn = __phys_to_pfn(PKUNITY_UNIGFX_MMAP_BASE);
+-	map.virtual = KUSER_UNIGFX_BASE;
+-	map.length = PKUNITY_UNIGFX_MMAP_SIZE;
+-	map.type = MT_KUSER;
+-	create_mapping(&map);
+-#endif
+-
+ 	/*
+ 	 * Create a mapping for the machine vectors at the high-vectors
+ 	 * location (0xffff0000).  If we aren't using high-vectors, also
+diff --git a/drivers/video/fb-puv3.c b/drivers/video/fb-puv3.c
+index dbd2dc4745d1..27f2c57e06e9 100644
+--- a/drivers/video/fb-puv3.c
++++ b/drivers/video/fb-puv3.c
+@@ -13,7 +13,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ #include 
+ #include 
+ #include 
+@@ -531,7 +530,7 @@ static int unifb_set_par(struct fb_info *info)
+ 		return -EINVAL;
+ 	}
+ 
+-	writel(PKUNITY_UNIGFX_MMAP_BASE, UDE_FSA);
++	writel(info->fix.smem_start, UDE_FSA);
+ 	writel(info->var.yres, UDE_LS);
+ 	writel(get_line_length(info->var.xres,
+ 			info->var.bits_per_pixel) >> 3, UDE_PS);
+@@ -680,13 +679,27 @@ static int unifb_probe(struct platform_device *dev)
+ 	struct fb_info *info;
+ 	u32 unifb_regs[UNIFB_REGS_NUM];
+ 	int retval = -ENOMEM;
+-	struct resource *iomem, *mapmem;
++	struct resource *iomem;
++	void *videomemory;
++
++	videomemory = (void *)__get_free_pages(GFP_KERNEL | __GFP_COMP,
++				get_order(UNIFB_MEMSIZE));
++	if (!videomemory)
++		goto err;
++
++	memset(videomemory, 0, UNIFB_MEMSIZE);
++
++	unifb_fix.smem_start = virt_to_phys(videomemory);
++	unifb_fix.smem_len = UNIFB_MEMSIZE;
++
++	iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
++	unifb_fix.mmio_start = iomem->start;
+ 
+ 	info = framebuffer_alloc(sizeof(u32)*256, &dev->dev);
+ 	if (!info)
+ 		goto err;
+ 
+-	info->screen_base = (char __iomem *)KUSER_UNIGFX_BASE;
++	info->screen_base = (char __iomem *)videomemory;
+ 	info->fbops = &unifb_ops;
+ 
+ 	retval = fb_find_mode(&info->var, info, NULL,
+@@ -695,13 +708,6 @@ static int unifb_probe(struct platform_device *dev)
+ 	if (!retval || (retval == 4))
+ 		info->var = unifb_default;
+ 
+-	iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
+-	unifb_fix.mmio_start = iomem->start;
+-
+-	mapmem = platform_get_resource(dev, IORESOURCE_MEM, 1);
+-	unifb_fix.smem_start = mapmem->start;
+-	unifb_fix.smem_len = UNIFB_MEMSIZE;
+-
+ 	info->fix = unifb_fix;
+ 	info->pseudo_palette = info->par;
+ 	info->par = NULL;

commit 858e4f4ba14441c2d43eed55dcd660c09bae38df
+Author: Guan Xuetao 
+Date:   Tue Mar 29 20:38:51 2011 +0800
+
+    unicore32 rtc driver fix: cleanup irq_set_freq and irq_set_state
+    
+    Signed-off-by: Guan Xuetao 
+
+diff --git a/arch/unicore32/kernel/rtc.c b/arch/unicore32/kernel/rtc.c
+index c5f068295b51..8cad70b3302c 100644
+--- a/arch/unicore32/kernel/rtc.c
++++ b/arch/unicore32/kernel/rtc.c
+@@ -88,11 +88,6 @@ static int puv3_rtc_setpie(struct device *dev, int enabled)
+ 	return 0;
+ }
+ 
+-static int puv3_rtc_setfreq(struct device *dev, int freq)
+-{
+-	return 0;
+-}
+-
+ /* Time read/write */
+ 
+ static int puv3_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
+@@ -214,8 +209,6 @@ static const struct rtc_class_ops puv3_rtcops = {
+ 	.set_time	= puv3_rtc_settime,
+ 	.read_alarm	= puv3_rtc_getalarm,
+ 	.set_alarm	= puv3_rtc_setalarm,
+-	.irq_set_freq	= puv3_rtc_setfreq,
+-	.irq_set_state	= puv3_rtc_setpie,
+ 	.proc	        = puv3_rtc_proc,
+ };
+ 
+@@ -294,8 +287,6 @@ static int puv3_rtc_probe(struct platform_device *pdev)
+ 
+ 	puv3_rtc_enable(pdev, 1);
+ 
+-	puv3_rtc_setfreq(&pdev->dev, 1);
+-
+ 	/* register RTC and exit */
+ 
+ 	rtc = rtc_device_register("pkunity", &pdev->dev, &puv3_rtcops,

commit 0bfdc8e121fd61adbc03848af3ca15fcbef2d1d8
+Author: Guan Xuetao 
+Date:   Tue Mar 29 22:17:42 2011 +0800
+
+    unicore32 fix: remove arch-specific futex support
+    
+    The futex functions in unicore32 are not used and verified,
+    so just replaced by asm-generic version.
+    
+    Signed-off-by: Guan Xuetao 
+    Acked-by: Arnd Bergmann 
+
+diff --git a/arch/unicore32/Makefile b/arch/unicore32/Makefile
+index e08d6d370a8a..76a8beec7d03 100644
+--- a/arch/unicore32/Makefile
++++ b/arch/unicore32/Makefile
+@@ -48,7 +48,7 @@ ASM_GENERIC_HEADERS	+= bitsperlong.h bug.h bugs.h
+ ASM_GENERIC_HEADERS	+= cputime.h current.h
+ ASM_GENERIC_HEADERS	+= device.h div64.h
+ ASM_GENERIC_HEADERS	+= emergency-restart.h errno.h
+-ASM_GENERIC_HEADERS	+= fb.h fcntl.h ftrace.h
++ASM_GENERIC_HEADERS	+= fb.h fcntl.h ftrace.h futex.h
+ ASM_GENERIC_HEADERS	+= hardirq.h hw_irq.h
+ ASM_GENERIC_HEADERS	+= ioctl.h ioctls.h ipcbuf.h irq_regs.h
+ ASM_GENERIC_HEADERS	+= kdebug.h kmap_types.h
+diff --git a/arch/unicore32/include/asm/futex.h b/arch/unicore32/include/asm/futex.h
+deleted file mode 100644
+index 07dea6170558..000000000000
+--- a/arch/unicore32/include/asm/futex.h
++++ /dev/null
+@@ -1,143 +0,0 @@
+-/*
+- * linux/arch/unicore32/include/asm/futex.h
+- *
+- * Code specific to PKUnity SoC and UniCore ISA
+- *
+- * Copyright (C) 2001-2010 GUAN Xue-tao
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#ifndef __UNICORE_FUTEX_H__
+-#define __UNICORE_FUTEX_H__
+-
+-#ifdef __KERNEL__
+-
+-#include 
+-#include 
+-#include 
+-#include 
+-
+-#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)	\
+-	__asm__ __volatile__(					\
+-	"1:	ldw.u	%1, [%2]\n"				\
+-	"	" insn "\n"					\
+-	"2:	stw.u	%0, [%2]\n"				\
+-	"	mov	%0, #0\n"				\
+-	"3:\n"							\
+-	"	.pushsection __ex_table,\"a\"\n"		\
+-	"	.align	3\n"					\
+-	"	.long	1b, 4f, 2b, 4f\n"			\
+-	"	.popsection\n"					\
+-	"	.pushsection .fixup,\"ax\"\n"			\
+-	"4:	mov	%0, %4\n"				\
+-	"	b	3b\n"					\
+-	"	.popsection"					\
+-	: "=&r" (ret), "=&r" (oldval)				\
+-	: "r" (uaddr), "r" (oparg), "Ir" (-EFAULT)		\
+-	: "cc", "memory")
+-
+-static inline int
+-futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+-{
+-	int op = (encoded_op >> 28) & 7;
+-	int cmp = (encoded_op >> 24) & 15;
+-	int oparg = (encoded_op << 8) >> 20;
+-	int cmparg = (encoded_op << 20) >> 20;
+-	int oldval = 0, ret;
+-
+-	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+-		oparg = 1 << oparg;
+-
+-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+-		return -EFAULT;
+-
+-	pagefault_disable();	/* implies preempt_disable() */
+-
+-	switch (op) {
+-	case FUTEX_OP_SET:
+-		__futex_atomic_op("mov	%0, %3", ret, oldval, uaddr, oparg);
+-		break;
+-	case FUTEX_OP_ADD:
+-		__futex_atomic_op("add	%0, %1, %3", ret, oldval, uaddr, oparg);
+-		break;
+-	case FUTEX_OP_OR:
+-		__futex_atomic_op("or	%0, %1, %3", ret, oldval, uaddr, oparg);
+-		break;
+-	case FUTEX_OP_ANDN:
+-		__futex_atomic_op("and	%0, %1, %3",
+-				ret, oldval, uaddr, ~oparg);
+-		break;
+-	case FUTEX_OP_XOR:
+-		__futex_atomic_op("xor	%0, %1, %3", ret, oldval, uaddr, oparg);
+-		break;
+-	default:
+-		ret = -ENOSYS;
+-	}
+-
+-	pagefault_enable();	/* subsumes preempt_enable() */
+-
+-	if (!ret) {
+-		switch (cmp) {
+-		case FUTEX_OP_CMP_EQ:
+-			ret = (oldval == cmparg);
+-			break;
+-		case FUTEX_OP_CMP_NE:
+-			ret = (oldval != cmparg);
+-			break;
+-		case FUTEX_OP_CMP_LT:
+-			ret = (oldval <  cmparg);
+-			break;
+-		case FUTEX_OP_CMP_GE:
+-			ret = (oldval >= cmparg);
+-			break;
+-		case FUTEX_OP_CMP_LE:
+-			ret = (oldval <= cmparg);
+-			break;
+-		case FUTEX_OP_CMP_GT:
+-			ret = (oldval >  cmparg);
+-			break;
+-		default:
+-			ret = -ENOSYS;
+-		}
+-	}
+-	return ret;
+-}
+-
+-static inline int
+-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+-{
+-	int val;
+-
+-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+-		return -EFAULT;
+-
+-	pagefault_disable();	/* implies preempt_disable() */
+-
+-	__asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
+-	"1:	ldw.u	%0, [%3]\n"
+-	"	cmpxor.a	%0, %1\n"
+-	"	bne	3f\n"
+-	"2:	stw.u	%2, [%3]\n"
+-	"3:\n"
+-	"	.pushsection __ex_table,\"a\"\n"
+-	"	.align	3\n"
+-	"	.long	1b, 4f, 2b, 4f\n"
+-	"	.popsection\n"
+-	"	.pushsection .fixup,\"ax\"\n"
+-	"4:	mov	%0, %4\n"
+-	"	b	3b\n"
+-	"	.popsection"
+-	: "=&r" (val)
+-	: "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT)
+-	: "cc", "memory");
+-
+-	pagefault_enable();	/* subsumes preempt_enable() */
+-
+-	return val;
+-}
+-
+-#endif /* __KERNEL__ */
+-#endif /* __UNICORE_FUTEX_H__ */

commit df93878c9623146de8050308d65bcfeea4fb0aca
+Author: Guan Xuetao 
+Date:   Tue Mar 29 21:30:04 2011 +0800
+
+    unicore32 ldscript fix: add cacheline parameter to PERCPU() macro
+    
+    Also, adjust cacheline parameter of RW_DATA_SECTION and EXCEPTION_TABLE
+    
+    Signed-off-by: Guan Xuetao 
+    Acked-by: Arnd Bergmann 
+
+diff --git a/arch/unicore32/kernel/vmlinux.lds.S b/arch/unicore32/kernel/vmlinux.lds.S
+index 0b4eb89729e7..9bf7f7af52c5 100644
+--- a/arch/unicore32/kernel/vmlinux.lds.S
++++ b/arch/unicore32/kernel/vmlinux.lds.S
+@@ -14,6 +14,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ OUTPUT_ARCH(unicore32)
+ ENTRY(stext)
+@@ -29,7 +30,7 @@ SECTIONS
+ 	HEAD_TEXT_SECTION
+ 	INIT_TEXT_SECTION(PAGE_SIZE)
+ 	INIT_DATA_SECTION(16)
+-	PERCPU(PAGE_SIZE)
++	PERCPU(L1_CACHE_BYTES, PAGE_SIZE)
+ 	__init_end = .;
+ 
+ 	_stext = .;
+@@ -45,10 +46,10 @@ SECTIONS
+ 
+ 	_sdata = .;
+ 	RO_DATA_SECTION(PAGE_SIZE)
+-	RW_DATA_SECTION(32, PAGE_SIZE, THREAD_SIZE)
++	RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
+ 	_edata = .;
+ 
+-	EXCEPTION_TABLE(32)
++	EXCEPTION_TABLE(L1_CACHE_BYTES)
+ 	NOTES
+ 
+ 	BSS_SECTION(0, 0, 0)

commit 289d6b0e287e0acd85f3e6b7ea6c2cb5c234909a
+Author: GuanXuetao 
+Date:   Fri Mar 4 20:00:11 2011 +0800
+
+    unicore32: rewrite arch-specific tlb.h to use asm-generic version
+    
+    Signed-off-by: Guan Xuetao 
+
+diff --git a/arch/unicore32/include/asm/tlb.h b/arch/unicore32/include/asm/tlb.h
+index 02ee40e47a0d..9cca15cdae94 100644
+--- a/arch/unicore32/include/asm/tlb.h
++++ b/arch/unicore32/include/asm/tlb.h
+@@ -12,87 +12,17 @@
+ #ifndef __UNICORE_TLB_H__
+ #define __UNICORE_TLB_H__
+ 
+-#include 
+-#include 
+-#include 
+-
+-/*
+- * TLB handling.  This allows us to remove pages from the page
+- * tables, and efficiently handle the TLB issues.
+- */
+-struct mmu_gather {
+-	struct mm_struct	*mm;
+-	unsigned int		fullmm;
+-	unsigned long		range_start;
+-	unsigned long		range_end;
+-};
+-
+-DECLARE_PER_CPU(struct mmu_gather, mmu_gathers);
+-
+-static inline struct mmu_gather *
+-tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush)
+-{
+-	struct mmu_gather *tlb = &get_cpu_var(mmu_gathers);
+-
+-	tlb->mm = mm;
+-	tlb->fullmm = full_mm_flush;
+-
+-	return tlb;
+-}
+-
+-static inline void
+-tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
+-{
+-	if (tlb->fullmm)
+-		flush_tlb_mm(tlb->mm);
+-
+-	/* keep the page table cache within bounds */
+-	check_pgt_cache();
+-
+-	put_cpu_var(mmu_gathers);
+-}
+-
+-/*
+- * Memorize the range for the TLB flush.
+- */
+-static inline void
+-tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, unsigned long addr)
+-{
+-	if (!tlb->fullmm) {
+-		if (addr < tlb->range_start)
+-			tlb->range_start = addr;
+-		if (addr + PAGE_SIZE > tlb->range_end)
+-			tlb->range_end = addr + PAGE_SIZE;
+-	}
+-}
+-
+-/*
+- * In the case of tlb vma handling, we can optimise these away in the
+- * case where we're doing a full MM flush.  When we're doing a munmap,
+- * the vmas are adjusted to only cover the region to be torn down.
+- */
+-static inline void
+-tlb_start_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
+-{
+-	if (!tlb->fullmm) {
+-		flush_cache_range(vma, vma->vm_start, vma->vm_end);
+-		tlb->range_start = TASK_SIZE;
+-		tlb->range_end = 0;
+-	}
+-}
+-
+-static inline void
+-tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
+-{
+-	if (!tlb->fullmm && tlb->range_end > 0)
+-		flush_tlb_range(vma, tlb->range_start, tlb->range_end);
+-}
+-
+-#define tlb_remove_page(tlb, page)	free_page_and_swap_cache(page)
+-#define pte_free_tlb(tlb, ptep, addr)	pte_free((tlb)->mm, ptep)
+-#define pmd_free_tlb(tlb, pmdp, addr)	pmd_free((tlb)->mm, pmdp)
+-#define pud_free_tlb(tlb, x, addr)      do { } while (0)
+-
+-#define tlb_migrate_finish(mm)		do { } while (0)
++#define tlb_start_vma(tlb, vma)				do { } while (0)
++#define tlb_end_vma(tlb, vma)				do { } while (0)
++#define __tlb_remove_tlb_entry(tlb, ptep, address)	do { } while (0)
++#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
++
++#define __pte_free_tlb(tlb, pte, addr)				\
++	do {							\
++		pgtable_page_dtor(pte);				\
++		tlb_remove_page((tlb), (pte));			\
++	} while (0)
++
++#include 
+ 
+ #endif

commit 1cf46c42d7688a2e09de87fc9201b0e9a0961866
+Author: GuanXuetao 
+Date:   Fri Mar 4 18:07:48 2011 +0800
+
+    unicore32: modify io_p2v and io_v2p macros, and adjust PKUNITY_mmio_BASEs
+    
+    1. remove __REG macro
+    2. add (void __iomem *) to io_p2v macro
+    3. add (phys_addr_t) to io_v2p macro
+    4. add PKUNITY_AHB_BASE and PKUNITY_APB_BASE definitions
+    5. modify all PKUNITY_mmio_BASEs from physical addr to virtual addr
+    6. adjust prefix macro for all usage of PKUNITY_mmio_BASEs
+      -- by advice with Arnd Bergmann
+    
+    Signed-off-by: Guan Xuetao 
+    Reviewed-by: Arnd Bergmann 
+
+diff --git a/arch/unicore32/include/asm/io.h b/arch/unicore32/include/asm/io.h
+index 2483fcbadbe4..4bd87f3d13d4 100644
+--- a/arch/unicore32/include/asm/io.h
++++ b/arch/unicore32/include/asm/io.h
+@@ -18,7 +18,7 @@
+ #include 
+ #include 
+ 
+-#define PCI_IOBASE	io_p2v(PKUNITY_PCILIO_BASE)
++#define PCI_IOBASE	PKUNITY_PCILIO_BASE
+ #include 
+ 
+ /*
+diff --git a/arch/unicore32/include/mach/PKUnity.h b/arch/unicore32/include/mach/PKUnity.h
+index 940e9ed0941c..a18bdc3810e6 100644
+--- a/arch/unicore32/include/mach/PKUnity.h
++++ b/arch/unicore32/include/mach/PKUnity.h
+@@ -22,83 +22,87 @@
+  */
+ #define PKUNITY_SDRAM_BASE		0x00000000 /* 0x00000000 - 0x7FFFFFFF 2GB */
+ #define PKUNITY_MMIO_BASE		0x80000000 /* 0x80000000 - 0xFFFFFFFF 2GB */
+-#define PKUNITY_PCI_BASE		0x80000000 /* 0x80000000 - 0xBFFFFFFF 1GB */
+-#include "regs-pci.h"
+-#define PKUNITY_BOOT_ROM2_BASE		0xF4000000 /* 0xF4000000 - 0xF7FFFFFF 64MB */
+-#define PKUNITY_BOOT_SRAM2_BASE		0xF8000000 /* 0xF8000000 - 0xFBFFFFFF 64MB */
+-#define PKUNITY_BOOT_FLASH_BASE		0xFC000000 /* 0xFC000000 - 0xFFFFFFFF 64MB */
+ 
+ /*
+  * PKUNITY Memory Map Addresses: 0x0D000000 - 0x0EFFFFFF (32MB)
++ *	0x0D000000 - 0x0DFFFFFF 16MB: for UVC
++ *	0x0E000000 - 0x0EFFFFFF 16MB: for UNIGFX
+  */
+-#define PKUNITY_UVC_MMAP_BASE		0x0D000000 /* 0x0D000000 - 0x0DFFFFFF 16MB */
++#define PKUNITY_UVC_MMAP_BASE		0x0D000000
+ #define PKUNITY_UVC_MMAP_SIZE		0x01000000 /* 16MB */
+-#define PKUNITY_UNIGFX_MMAP_BASE        0x0E000000 /* 0x0E000000 - 0x0EFFFFFF 16MB */
++#define PKUNITY_UNIGFX_MMAP_BASE        0x0E000000
+ #define PKUNITY_UNIGFX_MMAP_SIZE        0x01000000 /* 16MB */
+ 
+ /*
+  * PKUNITY System Bus Addresses (PCI): 0x80000000 - 0xBFFFFFFF (1GB)
++ * 0x80000000 - 0x8000000B 12B    PCI Configuration regs
++ * 0x80010000 - 0x80010250 592B   PCI Bridge Base
++ * 0x80030000 - 0x8003FFFF 64KB   PCI Legacy IO
++ * 0x90000000 - 0x97FFFFFF 128MB  PCI AHB-PCI MEM-mapping
++ * 0x98000000 - 0x9FFFFFFF 128MB  PCI PCI-AHB MEM-mapping
+  */
+-/* PCI Configuration regs */
+-#define PKUNITY_PCICFG_BASE             0x80000000 /* 0x80000000 - 0x8000000B 12B */
+-/* PCI Bridge Base */
+-#define PKUNITY_PCIBRI_BASE             0x80010000 /* 0x80010000 - 0x80010250 592B */
+-/* PCI Legacy IO */
+-#define PKUNITY_PCILIO_BASE             0x80030000 /* 0x80030000 - 0x8003FFFF 64KB */
+-/* PCI AHB-PCI MEM-mapping */
+-#define PKUNITY_PCIMEM_BASE             0x90000000 /* 0x90000000 - 0x97FFFFFF 128MB */
+-/* PCI PCI-AHB MEM-mapping */
+-#define PKUNITY_PCIAHB_BASE             0x98000000 /* 0x98000000 - 0x9FFFFFFF 128MB */
++#define PKUNITY_PCI_BASE		io_p2v(0x80000000) /* 0x80000000 - 0xBFFFFFFF 1GB */
++#include "regs-pci.h"
++
++#define PKUNITY_PCICFG_BASE		(PKUNITY_PCI_BASE + 0x0)
++#define PKUNITY_PCIBRI_BASE		(PKUNITY_PCI_BASE + 0x00010000)
++#define PKUNITY_PCILIO_BASE		(PKUNITY_PCI_BASE + 0x00030000)
++#define PKUNITY_PCIMEM_BASE		(PKUNITY_PCI_BASE + 0x10000000)
++#define PKUNITY_PCIAHB_BASE		(PKUNITY_PCI_BASE + 0x18000000)
+ 
+ /*
+  * PKUNITY System Bus Addresses (AHB): 0xC0000000 - 0xEDFFFFFF (640MB)
+  */
++#define PKUNITY_AHB_BASE		io_p2v(0xC0000000)
++
+ /* AHB-0 is DDR2 SDRAM */
+ /* AHB-1 is PCI Space */
+-#define PKUNITY_ARBITER_BASE		0xC0000000 /* AHB-2 */
+-#define PKUNITY_DDR2CTRL_BASE		0xC0100000 /* AHB-3 */
+-#define PKUNITY_DMAC_BASE		0xC0200000 /* AHB-4 */
++#define PKUNITY_ARBITER_BASE		(PKUNITY_AHB_BASE + 0x000000) /* AHB-2 */
++#define PKUNITY_DDR2CTRL_BASE		(PKUNITY_AHB_BASE + 0x100000) /* AHB-3 */
++#define PKUNITY_DMAC_BASE		(PKUNITY_AHB_BASE + 0x200000) /* AHB-4 */
+ #include "regs-dmac.h"
+-#define PKUNITY_UMAL_BASE		0xC0300000 /* AHB-5 */
++#define PKUNITY_UMAL_BASE		(PKUNITY_AHB_BASE + 0x300000) /* AHB-5 */
+ #include "regs-umal.h"
+-#define PKUNITY_USB_BASE		0xC0400000 /* AHB-6 */
+-#define PKUNITY_SATA_BASE		0xC0500000 /* AHB-7 */
+-#define PKUNITY_SMC_BASE		0xC0600000 /* AHB-8 */
++#define PKUNITY_USB_BASE		(PKUNITY_AHB_BASE + 0x400000) /* AHB-6 */
++#define PKUNITY_SATA_BASE		(PKUNITY_AHB_BASE + 0x500000) /* AHB-7 */
++#define PKUNITY_SMC_BASE		(PKUNITY_AHB_BASE + 0x600000) /* AHB-8 */
+ /* AHB-9 is for APB bridge */
+-#define PKUNITY_MME_BASE		0xC0700000 /* AHB-10 */
+-#define PKUNITY_UNIGFX_BASE		0xC0800000 /* AHB-11 */
++#define PKUNITY_MME_BASE		(PKUNITY_AHB_BASE + 0x700000) /* AHB-10 */
++#define PKUNITY_UNIGFX_BASE		(PKUNITY_AHB_BASE + 0x800000) /* AHB-11 */
+ #include "regs-unigfx.h"
+-#define PKUNITY_NAND_BASE		0xC0900000 /* AHB-12 */
++#define PKUNITY_NAND_BASE		(PKUNITY_AHB_BASE + 0x900000) /* AHB-12 */
+ #include "regs-nand.h"
+-#define PKUNITY_H264D_BASE		0xC0A00000 /* AHB-13 */
+-#define PKUNITY_H264E_BASE		0xC0B00000 /* AHB-14 */
++#define PKUNITY_H264D_BASE		(PKUNITY_AHB_BASE + 0xA00000) /* AHB-13 */
++#define PKUNITY_H264E_BASE		(PKUNITY_AHB_BASE + 0xB00000) /* AHB-14 */
+ 
+ /*
+  * PKUNITY Peripheral Bus Addresses (APB): 0xEE000000 - 0xEFFFFFFF (128MB)
+  */
+-#define PKUNITY_UART0_BASE		0xEE000000 /* APB-0 */
+-#define PKUNITY_UART1_BASE		0xEE100000 /* APB-1 */
++#define PKUNITY_APB_BASE		io_p2v(0xEE000000)
++
++#define PKUNITY_UART0_BASE		(PKUNITY_APB_BASE + 0x000000) /* APB-0 */
++#define PKUNITY_UART1_BASE		(PKUNITY_APB_BASE + 0x100000) /* APB-1 */
+ #include "regs-uart.h"
+-#define PKUNITY_I2C_BASE		0xEE200000 /* APB-2 */
++#define PKUNITY_I2C_BASE		(PKUNITY_APB_BASE + 0x200000) /* APB-2 */
+ #include "regs-i2c.h"
+-#define PKUNITY_SPI_BASE		0xEE300000 /* APB-3 */
++#define PKUNITY_SPI_BASE		(PKUNITY_APB_BASE + 0x300000) /* APB-3 */
+ #include "regs-spi.h"
+-#define PKUNITY_AC97_BASE		0xEE400000 /* APB-4 */
++#define PKUNITY_AC97_BASE		(PKUNITY_APB_BASE + 0x400000) /* APB-4 */
+ #include "regs-ac97.h"
+-#define PKUNITY_GPIO_BASE		0xEE500000 /* APB-5 */
++#define PKUNITY_GPIO_BASE		(PKUNITY_APB_BASE + 0x500000) /* APB-5 */
+ #include "regs-gpio.h"
+-#define PKUNITY_INTC_BASE		0xEE600000 /* APB-6 */
++#define PKUNITY_INTC_BASE		(PKUNITY_APB_BASE + 0x600000) /* APB-6 */
+ #include "regs-intc.h"
+-#define PKUNITY_RTC_BASE		0xEE700000 /* APB-7 */
++#define PKUNITY_RTC_BASE		(PKUNITY_APB_BASE + 0x700000) /* APB-7 */
+ #include "regs-rtc.h"
+-#define PKUNITY_OST_BASE		0xEE800000 /* APB-8 */
++#define PKUNITY_OST_BASE		(PKUNITY_APB_BASE + 0x800000) /* APB-8 */
+ #include "regs-ost.h"
+-#define PKUNITY_RESETC_BASE		0xEE900000 /* APB-9 */
++#define PKUNITY_RESETC_BASE		(PKUNITY_APB_BASE + 0x900000) /* APB-9 */
+ #include "regs-resetc.h"
+-#define PKUNITY_PM_BASE			0xEEA00000 /* APB-10 */
++#define PKUNITY_PM_BASE			(PKUNITY_APB_BASE + 0xA00000) /* APB-10 */
+ #include "regs-pm.h"
+-#define PKUNITY_PS2_BASE		0xEEB00000 /* APB-11 */
++#define PKUNITY_PS2_BASE		(PKUNITY_APB_BASE + 0xB00000) /* APB-11 */
+ #include "regs-ps2.h"
+-#define PKUNITY_SDC_BASE		0xEEC00000 /* APB-12 */
++#define PKUNITY_SDC_BASE		(PKUNITY_APB_BASE + 0xC00000) /* APB-12 */
+ #include "regs-sdc.h"
+ 
+diff --git a/arch/unicore32/include/mach/hardware.h b/arch/unicore32/include/mach/hardware.h
+index b71405ab6de6..930bea6e129a 100644
+--- a/arch/unicore32/include/mach/hardware.h
++++ b/arch/unicore32/include/mach/hardware.h
+@@ -17,17 +17,16 @@
+ 
+ #include "PKUnity.h"
+ 
++#ifndef __ASSEMBLY__
++#define io_p2v(x)	(void __iomem *)((x) - PKUNITY_MMIO_BASE)
++#define io_v2p(x)	(phys_addr_t)((x) + PKUNITY_MMIO_BASE)
++#else
+ #define io_p2v(x)	((x) - PKUNITY_MMIO_BASE)
+ #define io_v2p(x)	((x) + PKUNITY_MMIO_BASE)
+-
+-#ifndef __ASSEMBLY__
+-
+-# define __REG(x)	(void __iomem *)io_p2v(x)
+-
+ #endif
+ 
+ #define PCIBIOS_MIN_IO			0x4000 /* should lower than 64KB */
+-#define PCIBIOS_MIN_MEM			PKUNITY_PCIMEM_BASE
++#define PCIBIOS_MIN_MEM			io_v2p(PKUNITY_PCIMEM_BASE)
+ 
+ /*
+  * We override the standard dma-mask routines for bouncing.
+diff --git a/arch/unicore32/include/mach/memory.h b/arch/unicore32/include/mach/memory.h
+index b774eff3ea65..0bf21c944710 100644
+--- a/arch/unicore32/include/mach/memory.h
++++ b/arch/unicore32/include/mach/memory.h
+@@ -45,8 +45,8 @@ void puv3_pci_adjust_zones(unsigned long *size, unsigned long *holes);
+ #define is_pcibus_device(dev)	(dev &&			\
+ 				(strncmp(dev->bus->name, "pci", 3) == 0))
+ 
+-#define __virt_to_pcibus(x)     (__virt_to_phys(x) + PKUNITY_PCIAHB_BASE)
+-#define __pcibus_to_virt(x)     __phys_to_virt((x) - PKUNITY_PCIAHB_BASE)
++#define __virt_to_pcibus(x)     (__virt_to_phys((x) + PKUNITY_PCIAHB_BASE))
++#define __pcibus_to_virt(x)     (__phys_to_virt(x) - PKUNITY_PCIAHB_BASE)
+ 
+ /* kuser area */
+ #define KUSER_VECPAGE_BASE	(KUSER_BASE + UL(0x3fff0000))
+diff --git a/arch/unicore32/include/mach/regs-ac97.h b/arch/unicore32/include/mach/regs-ac97.h
+index ce299bf4adae..b7563e9d6503 100644
+--- a/arch/unicore32/include/mach/regs-ac97.h
++++ b/arch/unicore32/include/mach/regs-ac97.h
+@@ -2,16 +2,16 @@
+  * PKUnity AC97 Registers
+  */
+ 
+-#define PKUNITY_AC97_CONR		__REG(PKUNITY_AC97_BASE + 0x0000)
+-#define PKUNITY_AC97_OCR		__REG(PKUNITY_AC97_BASE + 0x0004)
+-#define PKUNITY_AC97_ICR		__REG(PKUNITY_AC97_BASE + 0x0008)
+-#define PKUNITY_AC97_CRAC		__REG(PKUNITY_AC97_BASE + 0x000C)
+-#define PKUNITY_AC97_INTR		__REG(PKUNITY_AC97_BASE + 0x0010)
+-#define PKUNITY_AC97_INTRSTAT		__REG(PKUNITY_AC97_BASE + 0x0014)
+-#define PKUNITY_AC97_INTRCLEAR		__REG(PKUNITY_AC97_BASE + 0x0018)
+-#define PKUNITY_AC97_ENABLE		__REG(PKUNITY_AC97_BASE + 0x001C)
+-#define PKUNITY_AC97_OUT_FIFO		__REG(PKUNITY_AC97_BASE + 0x0020)
+-#define PKUNITY_AC97_IN_FIFO		__REG(PKUNITY_AC97_BASE + 0x0030)
++#define PKUNITY_AC97_CONR		(PKUNITY_AC97_BASE + 0x0000)
++#define PKUNITY_AC97_OCR		(PKUNITY_AC97_BASE + 0x0004)
++#define PKUNITY_AC97_ICR		(PKUNITY_AC97_BASE + 0x0008)
++#define PKUNITY_AC97_CRAC		(PKUNITY_AC97_BASE + 0x000C)
++#define PKUNITY_AC97_INTR		(PKUNITY_AC97_BASE + 0x0010)
++#define PKUNITY_AC97_INTRSTAT		(PKUNITY_AC97_BASE + 0x0014)
++#define PKUNITY_AC97_INTRCLEAR		(PKUNITY_AC97_BASE + 0x0018)
++#define PKUNITY_AC97_ENABLE		(PKUNITY_AC97_BASE + 0x001C)
++#define PKUNITY_AC97_OUT_FIFO		(PKUNITY_AC97_BASE + 0x0020)
++#define PKUNITY_AC97_IN_FIFO		(PKUNITY_AC97_BASE + 0x0030)
+ 
+ #define AC97_CODEC_REG(v)               FIELD((v), 7, 16)
+ #define AC97_CODEC_VAL(v)               FIELD((v), 16, 0)
+diff --git a/arch/unicore32/include/mach/regs-dmac.h b/arch/unicore32/include/mach/regs-dmac.h
+index 09fce9d0d640..66de9e7d1c8f 100644
+--- a/arch/unicore32/include/mach/regs-dmac.h
++++ b/arch/unicore32/include/mach/regs-dmac.h
+@@ -5,27 +5,27 @@
+ /*
+  * Interrupt Status Reg DMAC_ISR.
+  */
+-#define DMAC_ISR		__REG(PKUNITY_DMAC_BASE + 0x0020)
++#define DMAC_ISR		(PKUNITY_DMAC_BASE + 0x0020)
+ /*
+  * Interrupt Transfer Complete Status Reg DMAC_ITCSR.
+  */
+-#define DMAC_ITCSR		__REG(PKUNITY_DMAC_BASE + 0x0050)
++#define DMAC_ITCSR		(PKUNITY_DMAC_BASE + 0x0050)
+ /*
+  * Interrupt Transfer Complete Clear Reg DMAC_ITCCR.
+  */
+-#define DMAC_ITCCR		__REG(PKUNITY_DMAC_BASE + 0x0060)
++#define DMAC_ITCCR		(PKUNITY_DMAC_BASE + 0x0060)
+ /*
+  * Interrupt Error Status Reg DMAC_IESR.
+  */
+-#define DMAC_IESR		__REG(PKUNITY_DMAC_BASE + 0x0080)
++#define DMAC_IESR		(PKUNITY_DMAC_BASE + 0x0080)
+ /*
+  * Interrupt Error Clear Reg DMAC_IECR.
+  */
+-#define DMAC_IECR		__REG(PKUNITY_DMAC_BASE + 0x0090)
++#define DMAC_IECR		(PKUNITY_DMAC_BASE + 0x0090)
+ /*
+  * Enable Channels Reg DMAC_ENCH.
+  */
+-#define DMAC_ENCH		__REG(PKUNITY_DMAC_BASE + 0x00B0)
++#define DMAC_ENCH		(PKUNITY_DMAC_BASE + 0x00B0)
+ 
+ /*
+  * DMA control reg. Space [byte]
+@@ -35,19 +35,19 @@
+ /*
+  * Source Addr DMAC_SRCADDR(ch).
+  */
+-#define DMAC_SRCADDR(ch)	__REG(PKUNITY_DMAC_BASE + (ch)*DMASp + 0x00)
++#define DMAC_SRCADDR(ch)	(PKUNITY_DMAC_BASE + (ch)*DMASp + 0x00)
+ /*
+  * Destination Addr DMAC_DESTADDR(ch).
+  */
+-#define DMAC_DESTADDR(ch)	__REG(PKUNITY_DMAC_BASE + (ch)*DMASp + 0x04)
++#define DMAC_DESTADDR(ch)	(PKUNITY_DMAC_BASE + (ch)*DMASp + 0x04)
+ /*
+  * Control Reg DMAC_CONTROL(ch).
+  */
+-#define DMAC_CONTROL(ch)	__REG(PKUNITY_DMAC_BASE + (ch)*DMASp + 0x0C)
++#define DMAC_CONTROL(ch)	(PKUNITY_DMAC_BASE + (ch)*DMASp + 0x0C)
+ /*
+  * Configuration Reg DMAC_CONFIG(ch).
+  */
+-#define DMAC_CONFIG(ch)		__REG(PKUNITY_DMAC_BASE + (ch)*DMASp + 0x10)
++#define DMAC_CONFIG(ch)		(PKUNITY_DMAC_BASE + (ch)*DMASp + 0x10)
+ 
+ #define DMAC_IR_MASK            FMASK(6, 0)
+ /*
+diff --git a/arch/unicore32/include/mach/regs-gpio.h b/arch/unicore32/include/mach/regs-gpio.h
+index 5dd99d4c209e..0273b861ef96 100644
+--- a/arch/unicore32/include/mach/regs-gpio.h
++++ b/arch/unicore32/include/mach/regs-gpio.h
+@@ -5,35 +5,35 @@
+ /*
+  * Voltage Status Reg GPIO_GPLR.
+  */
+-#define GPIO_GPLR	__REG(PKUNITY_GPIO_BASE + 0x0000)
++#define GPIO_GPLR	(PKUNITY_GPIO_BASE + 0x0000)
+ /*
+  * Pin Direction Reg GPIO_GPDR.
+  */
+-#define GPIO_GPDR	__REG(PKUNITY_GPIO_BASE + 0x0004)
++#define GPIO_GPDR	(PKUNITY_GPIO_BASE + 0x0004)
+ /*
+  * Output Pin Set Reg GPIO_GPSR.
+  */
+-#define GPIO_GPSR	__REG(PKUNITY_GPIO_BASE + 0x0008)
++#define GPIO_GPSR	(PKUNITY_GPIO_BASE + 0x0008)
+ /*
+  * Output Pin Clear Reg GPIO_GPCR.
+  */
+-#define GPIO_GPCR	__REG(PKUNITY_GPIO_BASE + 0x000C)
++#define GPIO_GPCR	(PKUNITY_GPIO_BASE + 0x000C)
+ /*
+  * Raise Edge Detect Reg GPIO_GRER.
+  */
+-#define GPIO_GRER	__REG(PKUNITY_GPIO_BASE + 0x0010)
++#define GPIO_GRER	(PKUNITY_GPIO_BASE + 0x0010)
+ /*
+  * Fall Edge Detect Reg GPIO_GFER.
+  */
+-#define GPIO_GFER	__REG(PKUNITY_GPIO_BASE + 0x0014)
++#define GPIO_GFER	(PKUNITY_GPIO_BASE + 0x0014)
+ /*
+  * Edge Status Reg GPIO_GEDR.
+  */
+-#define GPIO_GEDR	__REG(PKUNITY_GPIO_BASE + 0x0018)
++#define GPIO_GEDR	(PKUNITY_GPIO_BASE + 0x0018)
+ /*
+  * Sepcial Voltage Detect Reg GPIO_GPIR.
+  */
+-#define GPIO_GPIR	__REG(PKUNITY_GPIO_BASE + 0x0020)
++#define GPIO_GPIR	(PKUNITY_GPIO_BASE + 0x0020)
+ 
+ #define GPIO_MIN	(0)
+ #define GPIO_MAX	(27)
+diff --git a/arch/unicore32/include/mach/regs-i2c.h b/arch/unicore32/include/mach/regs-i2c.h
+index 70b704f8dda8..463d108f8bfb 100644
+--- a/arch/unicore32/include/mach/regs-i2c.h
++++ b/arch/unicore32/include/mach/regs-i2c.h
+@@ -5,35 +5,35 @@
+ /*
+  * Control Reg I2C_CON.
+  */
+-#define I2C_CON		__REG(PKUNITY_I2C_BASE + 0x0000)
++#define I2C_CON		(PKUNITY_I2C_BASE + 0x0000)
+ /*
+  * Target Address Reg I2C_TAR.
+  */
+-#define I2C_TAR		__REG(PKUNITY_I2C_BASE + 0x0004)
++#define I2C_TAR		(PKUNITY_I2C_BASE + 0x0004)
+ /*
+  * Data buffer and command Reg I2C_DATACMD.
+  */
+-#define I2C_DATACMD	__REG(PKUNITY_I2C_BASE + 0x0010)
++#define I2C_DATACMD	(PKUNITY_I2C_BASE + 0x0010)
+ /*
+  * Enable Reg I2C_ENABLE.
+  */
+-#define I2C_ENABLE	__REG(PKUNITY_I2C_BASE + 0x006C)
++#define I2C_ENABLE	(PKUNITY_I2C_BASE + 0x006C)
+ /*
+  * Status Reg I2C_STATUS.
+  */
+-#define I2C_STATUS	__REG(PKUNITY_I2C_BASE + 0x0070)
++#define I2C_STATUS	(PKUNITY_I2C_BASE + 0x0070)
+ /*
+  * Tx FIFO Length Reg I2C_TXFLR.
+  */
+-#define I2C_TXFLR	__REG(PKUNITY_I2C_BASE + 0x0074)
++#define I2C_TXFLR	(PKUNITY_I2C_BASE + 0x0074)
+ /*
+  * Rx FIFO Length Reg I2C_RXFLR.
+  */
+-#define I2C_RXFLR	__REG(PKUNITY_I2C_BASE + 0x0078)
++#define I2C_RXFLR	(PKUNITY_I2C_BASE + 0x0078)
+ /*
+  * Enable Status Reg I2C_ENSTATUS.
+  */
+-#define I2C_ENSTATUS	__REG(PKUNITY_I2C_BASE + 0x009C)
++#define I2C_ENSTATUS	(PKUNITY_I2C_BASE + 0x009C)
+ 
+ #define I2C_CON_MASTER          FIELD(1, 1, 0)
+ #define I2C_CON_SPEED_STD       FIELD(1, 2, 1)
+diff --git a/arch/unicore32/include/mach/regs-intc.h b/arch/unicore32/include/mach/regs-intc.h
+index 409ae4776145..25648f89cbd3 100644
+--- a/arch/unicore32/include/mach/regs-intc.h
++++ b/arch/unicore32/include/mach/regs-intc.h
+@@ -4,25 +4,25 @@
+ /*
+  * INTC Level Reg INTC_ICLR.
+  */
+-#define INTC_ICLR	__REG(PKUNITY_INTC_BASE + 0x0000)
++#define INTC_ICLR	(PKUNITY_INTC_BASE + 0x0000)
+ /*
+  * INTC Mask Reg INTC_ICMR.
+  */
+-#define INTC_ICMR	__REG(PKUNITY_INTC_BASE + 0x0004)
++#define INTC_ICMR	(PKUNITY_INTC_BASE + 0x0004)
+ /*
+  * INTC Pending Reg INTC_ICPR.
+  */
+-#define INTC_ICPR	__REG(PKUNITY_INTC_BASE + 0x0008)
++#define INTC_ICPR	(PKUNITY_INTC_BASE + 0x0008)
+ /*
+  * INTC IRQ Pending Reg INTC_ICIP.
+  */
+-#define INTC_ICIP	__REG(PKUNITY_INTC_BASE + 0x000C)
++#define INTC_ICIP	(PKUNITY_INTC_BASE + 0x000C)
+ /*
+  * INTC REAL Pending Reg INTC_ICFP.
+  */
+-#define INTC_ICFP	__REG(PKUNITY_INTC_BASE + 0x0010)
++#define INTC_ICFP	(PKUNITY_INTC_BASE + 0x0010)
+ /*
+  * INTC Control Reg INTC_ICCR.
+  */
+-#define INTC_ICCR	__REG(PKUNITY_INTC_BASE + 0x0014)
++#define INTC_ICCR	(PKUNITY_INTC_BASE + 0x0014)
+ 
+diff --git a/arch/unicore32/include/mach/regs-nand.h b/arch/unicore32/include/mach/regs-nand.h
+index 0c33fe8c3090..a7c5563bb550 100644
+--- a/arch/unicore32/include/mach/regs-nand.h
++++ b/arch/unicore32/include/mach/regs-nand.h
+@@ -4,67 +4,67 @@
+ /*
+  * ID Reg. 0 NAND_IDR0
+  */
+-#define NAND_IDR0	__REG(PKUNITY_NAND_BASE + 0x0000)
++#define NAND_IDR0	(PKUNITY_NAND_BASE + 0x0000)
+ /*
+  * ID Reg. 1 NAND_IDR1
+  */
+-#define NAND_IDR1	__REG(PKUNITY_NAND_BASE + 0x0004)
++#define NAND_IDR1	(PKUNITY_NAND_BASE + 0x0004)
+ /*
+  * ID Reg. 2 NAND_IDR2
+  */
+-#define NAND_IDR2	__REG(PKUNITY_NAND_BASE + 0x0008)
++#define NAND_IDR2	(PKUNITY_NAND_BASE + 0x0008)
+ /*
+  * ID Reg. 3 NAND_IDR3
+  */
+-#define NAND_IDR3	__REG(PKUNITY_NAND_BASE + 0x000C)
++#define NAND_IDR3	(PKUNITY_NAND_BASE + 0x000C)
+ /*
+  * Page Address Reg 0 NAND_PAR0
+  */
+-#define NAND_PAR0	__REG(PKUNITY_NAND_BASE + 0x0010)
++#define NAND_PAR0	(PKUNITY_NAND_BASE + 0x0010)
+ /*
+  * Page Address Reg 1 NAND_PAR1
+  */
+-#define NAND_PAR1	__REG(PKUNITY_NAND_BASE + 0x0014)
++#define NAND_PAR1	(PKUNITY_NAND_BASE + 0x0014)
+ /*
+  * Page Address Reg 2 NAND_PAR2
+  */
+-#define NAND_PAR2	__REG(PKUNITY_NAND_BASE + 0x0018)
++#define NAND_PAR2	(PKUNITY_NAND_BASE + 0x0018)
+ /*
+  * ECC Enable Reg NAND_ECCEN
+  */
+-#define NAND_ECCEN	__REG(PKUNITY_NAND_BASE + 0x001C)
++#define NAND_ECCEN	(PKUNITY_NAND_BASE + 0x001C)
+ /*
+  * Buffer Reg NAND_BUF
+  */
+-#define NAND_BUF	__REG(PKUNITY_NAND_BASE + 0x0020)
++#define NAND_BUF	(PKUNITY_NAND_BASE + 0x0020)
+ /*
+  * ECC Status Reg NAND_ECCSR
+  */
+-#define NAND_ECCSR	__REG(PKUNITY_NAND_BASE + 0x0024)
++#define NAND_ECCSR	(PKUNITY_NAND_BASE + 0x0024)
+ /*
+  * Command Reg NAND_CMD
+  */
+-#define NAND_CMD	__REG(PKUNITY_NAND_BASE + 0x0028)
++#define NAND_CMD	(PKUNITY_NAND_BASE + 0x0028)
+ /*
+  * DMA Configure Reg NAND_DMACR
+  */
+-#define NAND_DMACR	__REG(PKUNITY_NAND_BASE + 0x002C)
++#define NAND_DMACR	(PKUNITY_NAND_BASE + 0x002C)
+ /*
+  * Interrupt Reg NAND_IR
+  */
+-#define NAND_IR		__REG(PKUNITY_NAND_BASE + 0x0030)
++#define NAND_IR		(PKUNITY_NAND_BASE + 0x0030)
+ /*
+  * Interrupt Mask Reg NAND_IMR
+  */
+-#define NAND_IMR	__REG(PKUNITY_NAND_BASE + 0x0034)
++#define NAND_IMR	(PKUNITY_NAND_BASE + 0x0034)
+ /*
+  * Chip Enable Reg NAND_CHIPEN
+  */
+-#define NAND_CHIPEN	__REG(PKUNITY_NAND_BASE + 0x0038)
++#define NAND_CHIPEN	(PKUNITY_NAND_BASE + 0x0038)
+ /*
+  * Address Reg NAND_ADDR
+  */
+-#define NAND_ADDR	__REG(PKUNITY_NAND_BASE + 0x003C)
++#define NAND_ADDR	(PKUNITY_NAND_BASE + 0x003C)
+ 
+ /*
+  * Command bits NAND_CMD_CMD_MASK
+diff --git a/arch/unicore32/include/mach/regs-ost.h b/arch/unicore32/include/mach/regs-ost.h
+index 33049a827518..7b91fe698eed 100644
+--- a/arch/unicore32/include/mach/regs-ost.h
++++ b/arch/unicore32/include/mach/regs-ost.h
+@@ -4,47 +4,47 @@
+ /*
+  * Match Reg 0 OST_OSMR0
+  */
+-#define OST_OSMR0	__REG(PKUNITY_OST_BASE + 0x0000)
++#define OST_OSMR0	(PKUNITY_OST_BASE + 0x0000)
+ /*
+  * Match Reg 1 OST_OSMR1
+  */
+-#define OST_OSMR1	__REG(PKUNITY_OST_BASE + 0x0004)
++#define OST_OSMR1	(PKUNITY_OST_BASE + 0x0004)
+ /*
+  * Match Reg 2 OST_OSMR2
+  */
+-#define OST_OSMR2	__REG(PKUNITY_OST_BASE + 0x0008)
++#define OST_OSMR2	(PKUNITY_OST_BASE + 0x0008)
+ /*
+  * Match Reg 3 OST_OSMR3
+  */
+-#define OST_OSMR3	__REG(PKUNITY_OST_BASE + 0x000C)
++#define OST_OSMR3	(PKUNITY_OST_BASE + 0x000C)
+ /*
+  * Counter Reg OST_OSCR
+  */
+-#define OST_OSCR	__REG(PKUNITY_OST_BASE + 0x0010)
++#define OST_OSCR	(PKUNITY_OST_BASE + 0x0010)
+ /*
+  * Status Reg OST_OSSR
+  */
+-#define OST_OSSR	__REG(PKUNITY_OST_BASE + 0x0014)
++#define OST_OSSR	(PKUNITY_OST_BASE + 0x0014)
+ /*
+  * Watchdog Enable Reg OST_OWER
+  */
+-#define OST_OWER	__REG(PKUNITY_OST_BASE + 0x0018)
++#define OST_OWER	(PKUNITY_OST_BASE + 0x0018)
+ /*
+  * Interrupt Enable Reg OST_OIER
+  */
+-#define OST_OIER	__REG(PKUNITY_OST_BASE + 0x001C)
++#define OST_OIER	(PKUNITY_OST_BASE + 0x001C)
+ /*
+  * PWM Pulse Width Control Reg OST_PWMPWCR
+  */
+-#define OST_PWMPWCR	__REG(PKUNITY_OST_BASE + 0x0080)
++#define OST_PWMPWCR	(PKUNITY_OST_BASE + 0x0080)
+ /*
+  * PWM Duty Cycle Control Reg OST_PWMDCCR
+  */
+-#define OST_PWMDCCR	__REG(PKUNITY_OST_BASE + 0x0084)
++#define OST_PWMDCCR	(PKUNITY_OST_BASE + 0x0084)
+ /*
+  * PWM Period Control Reg OST_PWMPCR
+  */
+-#define OST_PWMPCR	__REG(PKUNITY_OST_BASE + 0x0088)
++#define OST_PWMPCR	(PKUNITY_OST_BASE + 0x0088)
+ 
+ /*
+  * Match detected 0 OST_OSSR_M0
+diff --git a/arch/unicore32/include/mach/regs-pci.h b/arch/unicore32/include/mach/regs-pci.h
+index e8e1f1a52fd0..6a9341686bf8 100644
+--- a/arch/unicore32/include/mach/regs-pci.h
++++ b/arch/unicore32/include/mach/regs-pci.h
+@@ -8,79 +8,79 @@
+ /*
+  * PCICFG Bridge Base Reg.
+  */
+-#define PCICFG_BRIBASE          __REG(PKUNITY_PCICFG_BASE + 0x0000)
++#define PCICFG_BRIBASE          (PKUNITY_PCICFG_BASE + 0x0000)
+ /*
+  * PCICFG Address Reg.
+  */
+-#define PCICFG_ADDR             __REG(PKUNITY_PCICFG_BASE + 0x0004)
++#define PCICFG_ADDR             (PKUNITY_PCICFG_BASE + 0x0004)
+ /*
+  * PCICFG Address Reg.
+  */
+-#define PCICFG_DATA             __REG(PKUNITY_PCICFG_BASE + 0x0008)
++#define PCICFG_DATA             (PKUNITY_PCICFG_BASE + 0x0008)
+ 
+ /*
+  * PCI Bridge configuration space
+  */
+-#define PCIBRI_ID		__REG(PKUNITY_PCIBRI_BASE + 0x0000)
+-#define PCIBRI_CMD		__REG(PKUNITY_PCIBRI_BASE + 0x0004)
+-#define PCIBRI_CLASS		__REG(PKUNITY_PCIBRI_BASE + 0x0008)
+-#define PCIBRI_LTR		__REG(PKUNITY_PCIBRI_BASE + 0x000C)
+-#define PCIBRI_BAR0		__REG(PKUNITY_PCIBRI_BASE + 0x0010)
+-#define PCIBRI_BAR1		__REG(PKUNITY_PCIBRI_BASE + 0x0014)
+-#define PCIBRI_BAR2		__REG(PKUNITY_PCIBRI_BASE + 0x0018)
+-#define PCIBRI_BAR3		__REG(PKUNITY_PCIBRI_BASE + 0x001C)
+-#define PCIBRI_BAR4		__REG(PKUNITY_PCIBRI_BASE + 0x0020)
+-#define PCIBRI_BAR5		__REG(PKUNITY_PCIBRI_BASE + 0x0024)
++#define PCIBRI_ID		(PKUNITY_PCIBRI_BASE + 0x0000)
++#define PCIBRI_CMD		(PKUNITY_PCIBRI_BASE + 0x0004)
++#define PCIBRI_CLASS		(PKUNITY_PCIBRI_BASE + 0x0008)
++#define PCIBRI_LTR		(PKUNITY_PCIBRI_BASE + 0x000C)
++#define PCIBRI_BAR0		(PKUNITY_PCIBRI_BASE + 0x0010)
++#define PCIBRI_BAR1		(PKUNITY_PCIBRI_BASE + 0x0014)
++#define PCIBRI_BAR2		(PKUNITY_PCIBRI_BASE + 0x0018)
++#define PCIBRI_BAR3		(PKUNITY_PCIBRI_BASE + 0x001C)
++#define PCIBRI_BAR4		(PKUNITY_PCIBRI_BASE + 0x0020)
++#define PCIBRI_BAR5		(PKUNITY_PCIBRI_BASE + 0x0024)
+ 
+-#define PCIBRI_PCICTL0		__REG(PKUNITY_PCIBRI_BASE + 0x0100)
+-#define PCIBRI_PCIBAR0		__REG(PKUNITY_PCIBRI_BASE + 0x0104)
+-#define PCIBRI_PCIAMR0		__REG(PKUNITY_PCIBRI_BASE + 0x0108)
+-#define PCIBRI_PCITAR0		__REG(PKUNITY_PCIBRI_BASE + 0x010C)
+-#define PCIBRI_PCICTL1		__REG(PKUNITY_PCIBRI_BASE + 0x0110)
+-#define PCIBRI_PCIBAR1		__REG(PKUNITY_PCIBRI_BASE + 0x0114)
+-#define PCIBRI_PCIAMR1		__REG(PKUNITY_PCIBRI_BASE + 0x0118)
+-#define PCIBRI_PCITAR1		__REG(PKUNITY_PCIBRI_BASE + 0x011C)
+-#define PCIBRI_PCICTL2		__REG(PKUNITY_PCIBRI_BASE + 0x0120)
+-#define PCIBRI_PCIBAR2		__REG(PKUNITY_PCIBRI_BASE + 0x0124)
+-#define PCIBRI_PCIAMR2		__REG(PKUNITY_PCIBRI_BASE + 0x0128)
+-#define PCIBRI_PCITAR2		__REG(PKUNITY_PCIBRI_BASE + 0x012C)
+-#define PCIBRI_PCICTL3		__REG(PKUNITY_PCIBRI_BASE + 0x0130)
+-#define PCIBRI_PCIBAR3		__REG(PKUNITY_PCIBRI_BASE + 0x0134)
+-#define PCIBRI_PCIAMR3		__REG(PKUNITY_PCIBRI_BASE + 0x0138)
+-#define PCIBRI_PCITAR3		__REG(PKUNITY_PCIBRI_BASE + 0x013C)
+-#define PCIBRI_PCICTL4		__REG(PKUNITY_PCIBRI_BASE + 0x0140)
+-#define PCIBRI_PCIBAR4		__REG(PKUNITY_PCIBRI_BASE + 0x0144)
+-#define PCIBRI_PCIAMR4		__REG(PKUNITY_PCIBRI_BASE + 0x0148)
+-#define PCIBRI_PCITAR4		__REG(PKUNITY_PCIBRI_BASE + 0x014C)
+-#define PCIBRI_PCICTL5		__REG(PKUNITY_PCIBRI_BASE + 0x0150)
+-#define PCIBRI_PCIBAR5		__REG(PKUNITY_PCIBRI_BASE + 0x0154)
+-#define PCIBRI_PCIAMR5		__REG(PKUNITY_PCIBRI_BASE + 0x0158)
+-#define PCIBRI_PCITAR5		__REG(PKUNITY_PCIBRI_BASE + 0x015C)
++#define PCIBRI_PCICTL0		(PKUNITY_PCIBRI_BASE + 0x0100)
++#define PCIBRI_PCIBAR0		(PKUNITY_PCIBRI_BASE + 0x0104)
++#define PCIBRI_PCIAMR0		(PKUNITY_PCIBRI_BASE + 0x0108)
++#define PCIBRI_PCITAR0		(PKUNITY_PCIBRI_BASE + 0x010C)
++#define PCIBRI_PCICTL1		(PKUNITY_PCIBRI_BASE + 0x0110)
++#define PCIBRI_PCIBAR1		(PKUNITY_PCIBRI_BASE + 0x0114)
++#define PCIBRI_PCIAMR1		(PKUNITY_PCIBRI_BASE + 0x0118)
++#define PCIBRI_PCITAR1		(PKUNITY_PCIBRI_BASE + 0x011C)
++#define PCIBRI_PCICTL2		(PKUNITY_PCIBRI_BASE + 0x0120)
++#define PCIBRI_PCIBAR2		(PKUNITY_PCIBRI_BASE + 0x0124)
++#define PCIBRI_PCIAMR2		(PKUNITY_PCIBRI_BASE + 0x0128)
++#define PCIBRI_PCITAR2		(PKUNITY_PCIBRI_BASE + 0x012C)
++#define PCIBRI_PCICTL3		(PKUNITY_PCIBRI_BASE + 0x0130)
++#define PCIBRI_PCIBAR3		(PKUNITY_PCIBRI_BASE + 0x0134)
++#define PCIBRI_PCIAMR3		(PKUNITY_PCIBRI_BASE + 0x0138)
++#define PCIBRI_PCITAR3		(PKUNITY_PCIBRI_BASE + 0x013C)
++#define PCIBRI_PCICTL4		(PKUNITY_PCIBRI_BASE + 0x0140)
++#define PCIBRI_PCIBAR4		(PKUNITY_PCIBRI_BASE + 0x0144)
++#define PCIBRI_PCIAMR4		(PKUNITY_PCIBRI_BASE + 0x0148)
++#define PCIBRI_PCITAR4		(PKUNITY_PCIBRI_BASE + 0x014C)
++#define PCIBRI_PCICTL5		(PKUNITY_PCIBRI_BASE + 0x0150)
++#define PCIBRI_PCIBAR5		(PKUNITY_PCIBRI_BASE + 0x0154)
++#define PCIBRI_PCIAMR5		(PKUNITY_PCIBRI_BASE + 0x0158)
++#define PCIBRI_PCITAR5		(PKUNITY_PCIBRI_BASE + 0x015C)
+ 
+-#define PCIBRI_AHBCTL0		__REG(PKUNITY_PCIBRI_BASE + 0x0180)
+-#define PCIBRI_AHBBAR0		__REG(PKUNITY_PCIBRI_BASE + 0x0184)
+-#define PCIBRI_AHBAMR0		__REG(PKUNITY_PCIBRI_BASE + 0x0188)
+-#define PCIBRI_AHBTAR0		__REG(PKUNITY_PCIBRI_BASE + 0x018C)
+-#define PCIBRI_AHBCTL1		__REG(PKUNITY_PCIBRI_BASE + 0x0190)
+-#define PCIBRI_AHBBAR1		__REG(PKUNITY_PCIBRI_BASE + 0x0194)
+-#define PCIBRI_AHBAMR1		__REG(PKUNITY_PCIBRI_BASE + 0x0198)
+-#define PCIBRI_AHBTAR1		__REG(PKUNITY_PCIBRI_BASE + 0x019C)
+-#define PCIBRI_AHBCTL2		__REG(PKUNITY_PCIBRI_BASE + 0x01A0)
+-#define PCIBRI_AHBBAR2		__REG(PKUNITY_PCIBRI_BASE + 0x01A4)
+-#define PCIBRI_AHBAMR2		__REG(PKUNITY_PCIBRI_BASE + 0x01A8)
+-#define PCIBRI_AHBTAR2		__REG(PKUNITY_PCIBRI_BASE + 0x01AC)
+-#define PCIBRI_AHBCTL3		__REG(PKUNITY_PCIBRI_BASE + 0x01B0)
+-#define PCIBRI_AHBBAR3		__REG(PKUNITY_PCIBRI_BASE + 0x01B4)
+-#define PCIBRI_AHBAMR3		__REG(PKUNITY_PCIBRI_BASE + 0x01B8)
+-#define PCIBRI_AHBTAR3		__REG(PKUNITY_PCIBRI_BASE + 0x01BC)
+-#define PCIBRI_AHBCTL4		__REG(PKUNITY_PCIBRI_BASE + 0x01C0)
+-#define PCIBRI_AHBBAR4		__REG(PKUNITY_PCIBRI_BASE + 0x01C4)
+-#define PCIBRI_AHBAMR4		__REG(PKUNITY_PCIBRI_BASE + 0x01C8)
+-#define PCIBRI_AHBTAR4		__REG(PKUNITY_PCIBRI_BASE + 0x01CC)
+-#define PCIBRI_AHBCTL5		__REG(PKUNITY_PCIBRI_BASE + 0x01D0)
+-#define PCIBRI_AHBBAR5		__REG(PKUNITY_PCIBRI_BASE + 0x01D4)
+-#define PCIBRI_AHBAMR5		__REG(PKUNITY_PCIBRI_BASE + 0x01D8)
+-#define PCIBRI_AHBTAR5		__REG(PKUNITY_PCIBRI_BASE + 0x01DC)
++#define PCIBRI_AHBCTL0		(PKUNITY_PCIBRI_BASE + 0x0180)
++#define PCIBRI_AHBBAR0		(PKUNITY_PCIBRI_BASE + 0x0184)
++#define PCIBRI_AHBAMR0		(PKUNITY_PCIBRI_BASE + 0x0188)
++#define PCIBRI_AHBTAR0		(PKUNITY_PCIBRI_BASE + 0x018C)
++#define PCIBRI_AHBCTL1		(PKUNITY_PCIBRI_BASE + 0x0190)
++#define PCIBRI_AHBBAR1		(PKUNITY_PCIBRI_BASE + 0x0194)
++#define PCIBRI_AHBAMR1		(PKUNITY_PCIBRI_BASE + 0x0198)
++#define PCIBRI_AHBTAR1		(PKUNITY_PCIBRI_BASE + 0x019C)
++#define PCIBRI_AHBCTL2		(PKUNITY_PCIBRI_BASE + 0x01A0)
++#define PCIBRI_AHBBAR2		(PKUNITY_PCIBRI_BASE + 0x01A4)
++#define PCIBRI_AHBAMR2		(PKUNITY_PCIBRI_BASE + 0x01A8)
++#define PCIBRI_AHBTAR2		(PKUNITY_PCIBRI_BASE + 0x01AC)
++#define PCIBRI_AHBCTL3		(PKUNITY_PCIBRI_BASE + 0x01B0)
++#define PCIBRI_AHBBAR3		(PKUNITY_PCIBRI_BASE + 0x01B4)
++#define PCIBRI_AHBAMR3		(PKUNITY_PCIBRI_BASE + 0x01B8)
++#define PCIBRI_AHBTAR3		(PKUNITY_PCIBRI_BASE + 0x01BC)
++#define PCIBRI_AHBCTL4		(PKUNITY_PCIBRI_BASE + 0x01C0)
++#define PCIBRI_AHBBAR4		(PKUNITY_PCIBRI_BASE + 0x01C4)
++#define PCIBRI_AHBAMR4		(PKUNITY_PCIBRI_BASE + 0x01C8)
++#define PCIBRI_AHBTAR4		(PKUNITY_PCIBRI_BASE + 0x01CC)
++#define PCIBRI_AHBCTL5		(PKUNITY_PCIBRI_BASE + 0x01D0)
++#define PCIBRI_AHBBAR5		(PKUNITY_PCIBRI_BASE + 0x01D4)
++#define PCIBRI_AHBAMR5		(PKUNITY_PCIBRI_BASE + 0x01D8)
++#define PCIBRI_AHBTAR5		(PKUNITY_PCIBRI_BASE + 0x01DC)
+ 
+ #define PCIBRI_CTLx_AT          FIELD(1, 1, 2)
+ #define PCIBRI_CTLx_PREF        FIELD(1, 1, 1)
+diff --git a/arch/unicore32/include/mach/regs-pm.h b/arch/unicore32/include/mach/regs-pm.h
+index ed2d2fc6ad0c..854844aa8f4b 100644
+--- a/arch/unicore32/include/mach/regs-pm.h
++++ b/arch/unicore32/include/mach/regs-pm.h
+@@ -4,75 +4,75 @@
+ /*
+  * PM Control Reg PM_PMCR
+  */
+-#define PM_PMCR                 __REG(PKUNITY_PM_BASE + 0x0000)
++#define PM_PMCR                 (PKUNITY_PM_BASE + 0x0000)
+ /*
+  * PM General Conf. Reg PM_PGCR
+  */
+-#define PM_PGCR                 __REG(PKUNITY_PM_BASE + 0x0004)
++#define PM_PGCR                 (PKUNITY_PM_BASE + 0x0004)
+ /*
+  * PM PLL Conf. Reg PM_PPCR
+  */
+-#define PM_PPCR                 __REG(PKUNITY_PM_BASE + 0x0008)
++#define PM_PPCR                 (PKUNITY_PM_BASE + 0x0008)
+ /*
+  * PM Wakeup Enable Reg PM_PWER
+  */
+-#define PM_PWER                 __REG(PKUNITY_PM_BASE + 0x000C)
++#define PM_PWER                 (PKUNITY_PM_BASE + 0x000C)
+ /*
+  * PM GPIO Sleep Status Reg PM_PGSR
+  */
+-#define PM_PGSR                 __REG(PKUNITY_PM_BASE + 0x0010)
++#define PM_PGSR                 (PKUNITY_PM_BASE + 0x0010)
+ /*
+  * PM Clock Gate Reg PM_PCGR
+  */
+-#define PM_PCGR                 __REG(PKUNITY_PM_BASE + 0x0014)
++#define PM_PCGR                 (PKUNITY_PM_BASE + 0x0014)
+ /*
+  * PM SYS PLL Conf. Reg PM_PLLSYSCFG
+  */
+-#define PM_PLLSYSCFG            __REG(PKUNITY_PM_BASE + 0x0018)
++#define PM_PLLSYSCFG            (PKUNITY_PM_BASE + 0x0018)
+ /*
+  * PM DDR PLL Conf. Reg PM_PLLDDRCFG
+  */
+-#define PM_PLLDDRCFG            __REG(PKUNITY_PM_BASE + 0x001C)
++#define PM_PLLDDRCFG            (PKUNITY_PM_BASE + 0x001C)
+ /*
+  * PM VGA PLL Conf. Reg PM_PLLVGACFG
+  */
+-#define PM_PLLVGACFG            __REG(PKUNITY_PM_BASE + 0x0020)
++#define PM_PLLVGACFG            (PKUNITY_PM_BASE + 0x0020)
+ /*
+  * PM Div Conf. Reg PM_DIVCFG
+  */
+-#define PM_DIVCFG               __REG(PKUNITY_PM_BASE + 0x0024)
++#define PM_DIVCFG               (PKUNITY_PM_BASE + 0x0024)
+ /*
+  * PM SYS PLL Status Reg PM_PLLSYSSTATUS
+  */
+-#define PM_PLLSYSSTATUS         __REG(PKUNITY_PM_BASE + 0x0028)
++#define PM_PLLSYSSTATUS         (PKUNITY_PM_BASE + 0x0028)
+ /*
+  * PM DDR PLL Status Reg PM_PLLDDRSTATUS
+  */
+-#define PM_PLLDDRSTATUS         __REG(PKUNITY_PM_BASE + 0x002C)
++#define PM_PLLDDRSTATUS         (PKUNITY_PM_BASE + 0x002C)
+ /*
+  * PM VGA PLL Status Reg PM_PLLVGASTATUS
+  */
+-#define PM_PLLVGASTATUS         __REG(PKUNITY_PM_BASE + 0x0030)
++#define PM_PLLVGASTATUS         (PKUNITY_PM_BASE + 0x0030)
+ /*
+  * PM Div Status Reg PM_DIVSTATUS
+  */
+-#define PM_DIVSTATUS            __REG(PKUNITY_PM_BASE + 0x0034)
++#define PM_DIVSTATUS            (PKUNITY_PM_BASE + 0x0034)
+ /*
+  * PM Software Reset Reg PM_SWRESET
+  */
+-#define PM_SWRESET              __REG(PKUNITY_PM_BASE + 0x0038)
++#define PM_SWRESET              (PKUNITY_PM_BASE + 0x0038)
+ /*
+  * PM DDR2 PAD Start Reg PM_DDR2START
+  */
+-#define PM_DDR2START            __REG(PKUNITY_PM_BASE + 0x003C)
++#define PM_DDR2START            (PKUNITY_PM_BASE + 0x003C)
+ /*
+  * PM DDR2 PAD Status Reg PM_DDR2CAL0
+  */
+-#define PM_DDR2CAL0             __REG(PKUNITY_PM_BASE + 0x0040)
++#define PM_DDR2CAL0             (PKUNITY_PM_BASE + 0x0040)
+ /*
+  * PM PLL DFC Done Reg PM_PLLDFCDONE
+  */
+-#define PM_PLLDFCDONE           __REG(PKUNITY_PM_BASE + 0x0044)
++#define PM_PLLDFCDONE           (PKUNITY_PM_BASE + 0x0044)
+ 
+ #define PM_PMCR_SFB             FIELD(1, 1, 0)
+ #define PM_PMCR_IFB             FIELD(1, 1, 1)
+diff --git a/arch/unicore32/include/mach/regs-ps2.h b/arch/unicore32/include/mach/regs-ps2.h
+index 7da2071838ab..17d4e6dc0069 100644
+--- a/arch/unicore32/include/mach/regs-ps2.h
++++ b/arch/unicore32/include/mach/regs-ps2.h
+@@ -4,17 +4,17 @@
+ /*
+  * the same as I8042_DATA_REG PS2_DATA
+  */
+-#define PS2_DATA	__REG(PKUNITY_PS2_BASE + 0x0060)
++#define PS2_DATA	(PKUNITY_PS2_BASE + 0x0060)
+ /*
+  * the same as I8042_COMMAND_REG PS2_COMMAND
+  */
+-#define PS2_COMMAND	__REG(PKUNITY_PS2_BASE + 0x0064)
++#define PS2_COMMAND	(PKUNITY_PS2_BASE + 0x0064)
+ /*
+  * the same as I8042_STATUS_REG PS2_STATUS
+  */
+-#define PS2_STATUS	__REG(PKUNITY_PS2_BASE + 0x0064)
++#define PS2_STATUS	(PKUNITY_PS2_BASE + 0x0064)
+ /*
+  * counter reg PS2_CNT
+  */
+-#define PS2_CNT		__REG(PKUNITY_PS2_BASE + 0x0068)
++#define PS2_CNT		(PKUNITY_PS2_BASE + 0x0068)
+ 
+diff --git a/arch/unicore32/include/mach/regs-resetc.h b/arch/unicore32/include/mach/regs-resetc.h
+index 17639898fd84..39900cf4c936 100644
+--- a/arch/unicore32/include/mach/regs-resetc.h
++++ b/arch/unicore32/include/mach/regs-resetc.h
+@@ -4,11 +4,11 @@
+ /*
+  * Software Reset Register
+  */
+-#define RESETC_SWRR	__REG(PKUNITY_RESETC_BASE + 0x0000)
++#define RESETC_SWRR	(PKUNITY_RESETC_BASE + 0x0000)
+ /*
+  * Reset Status Register
+  */
+-#define RESETC_RSSR	__REG(PKUNITY_RESETC_BASE + 0x0004)
++#define RESETC_RSSR	(PKUNITY_RESETC_BASE + 0x0004)
+ 
+ /*
+  * Software Reset Bit
+diff --git a/arch/unicore32/include/mach/regs-rtc.h b/arch/unicore32/include/mach/regs-rtc.h
+index 155e38757186..e94ca193271d 100644
+--- a/arch/unicore32/include/mach/regs-rtc.h
++++ b/arch/unicore32/include/mach/regs-rtc.h
+@@ -4,19 +4,19 @@
+ /*
+  * RTC Alarm Reg RTC_RTAR
+  */
+-#define RTC_RTAR	__REG(PKUNITY_RTC_BASE + 0x0000)
++#define RTC_RTAR	(PKUNITY_RTC_BASE + 0x0000)
+ /*
+  * RTC Count Reg RTC_RCNR
+  */
+-#define RTC_RCNR	__REG(PKUNITY_RTC_BASE + 0x0004)
++#define RTC_RCNR	(PKUNITY_RTC_BASE + 0x0004)
+ /*
+  * RTC Trim Reg RTC_RTTR
+  */
+-#define RTC_RTTR	__REG(PKUNITY_RTC_BASE + 0x0008)
++#define RTC_RTTR	(PKUNITY_RTC_BASE + 0x0008)
+ /*
+  * RTC Status Reg RTC_RTSR
+  */
+-#define RTC_RTSR	__REG(PKUNITY_RTC_BASE + 0x0010)
++#define RTC_RTSR	(PKUNITY_RTC_BASE + 0x0010)
+ 
+ /*
+  * ALarm detected RTC_RTSR_AL
+diff --git a/arch/unicore32/include/mach/regs-sdc.h b/arch/unicore32/include/mach/regs-sdc.h
+index 3457b88c453c..1303ecf660ba 100644
+--- a/arch/unicore32/include/mach/regs-sdc.h
++++ b/arch/unicore32/include/mach/regs-sdc.h
+@@ -4,67 +4,67 @@
+ /*
+  * Clock Control Reg SDC_CCR
+  */
+-#define SDC_CCR		__REG(PKUNITY_SDC_BASE + 0x0000)
++#define SDC_CCR		(PKUNITY_SDC_BASE + 0x0000)
+ /*
+  * Software Reset Reg SDC_SRR
+  */
+-#define SDC_SRR		__REG(PKUNITY_SDC_BASE + 0x0004)
++#define SDC_SRR		(PKUNITY_SDC_BASE + 0x0004)
+ /*
+  * Argument Reg SDC_ARGUMENT
+  */
+-#define SDC_ARGUMENT	__REG(PKUNITY_SDC_BASE + 0x0008)
++#define SDC_ARGUMENT	(PKUNITY_SDC_BASE + 0x0008)
+ /*
+  * Command Reg SDC_COMMAND
+  */
+-#define SDC_COMMAND	__REG(PKUNITY_SDC_BASE + 0x000C)
++#define SDC_COMMAND	(PKUNITY_SDC_BASE + 0x000C)
+ /*
+  * Block Size Reg SDC_BLOCKSIZE
+  */
+-#define SDC_BLOCKSIZE	__REG(PKUNITY_SDC_BASE + 0x0010)
++#define SDC_BLOCKSIZE	(PKUNITY_SDC_BASE + 0x0010)
+ /*
+  * Block Cound Reg SDC_BLOCKCOUNT
+  */
+-#define SDC_BLOCKCOUNT	__REG(PKUNITY_SDC_BASE + 0x0014)
++#define SDC_BLOCKCOUNT	(PKUNITY_SDC_BASE + 0x0014)
+ /*
+  * Transfer Mode Reg SDC_TMR
+  */
+-#define SDC_TMR		__REG(PKUNITY_SDC_BASE + 0x0018)
++#define SDC_TMR		(PKUNITY_SDC_BASE + 0x0018)
+ /*
+  * Response Reg. 0 SDC_RES0
+  */
+-#define SDC_RES0	__REG(PKUNITY_SDC_BASE + 0x001C)
++#define SDC_RES0	(PKUNITY_SDC_BASE + 0x001C)
+ /*
+  * Response Reg. 1 SDC_RES1
+  */
+-#define SDC_RES1	__REG(PKUNITY_SDC_BASE + 0x0020)
++#define SDC_RES1	(PKUNITY_SDC_BASE + 0x0020)
+ /*
+  * Response Reg. 2 SDC_RES2
+  */
+-#define SDC_RES2	__REG(PKUNITY_SDC_BASE + 0x0024)
++#define SDC_RES2	(PKUNITY_SDC_BASE + 0x0024)
+ /*
+  * Response Reg. 3 SDC_RES3
+  */
+-#define SDC_RES3	__REG(PKUNITY_SDC_BASE + 0x0028)
++#define SDC_RES3	(PKUNITY_SDC_BASE + 0x0028)
+ /*
+  * Read Timeout Control Reg SDC_RTCR
+  */
+-#define SDC_RTCR	__REG(PKUNITY_SDC_BASE + 0x002C)
++#define SDC_RTCR	(PKUNITY_SDC_BASE + 0x002C)
+ /*
+  * Interrupt Status Reg SDC_ISR
+  */
+-#define SDC_ISR		__REG(PKUNITY_SDC_BASE + 0x0030)
++#define SDC_ISR		(PKUNITY_SDC_BASE + 0x0030)
+ /*
+  * Interrupt Status Mask Reg SDC_ISMR
+  */
+-#define SDC_ISMR	__REG(PKUNITY_SDC_BASE + 0x0034)
++#define SDC_ISMR	(PKUNITY_SDC_BASE + 0x0034)
+ /*
+  * RX FIFO SDC_RXFIFO
+  */
+-#define SDC_RXFIFO	__REG(PKUNITY_SDC_BASE + 0x0038)
++#define SDC_RXFIFO	(PKUNITY_SDC_BASE + 0x0038)
+ /*
+  * TX FIFO SDC_TXFIFO
+  */
+-#define SDC_TXFIFO	__REG(PKUNITY_SDC_BASE + 0x003C)
++#define SDC_TXFIFO	(PKUNITY_SDC_BASE + 0x003C)
+ 
+ /*
+  * SD Clock Enable SDC_CCR_CLKEN
+diff --git a/arch/unicore32/include/mach/regs-spi.h b/arch/unicore32/include/mach/regs-spi.h
+index cadc713c55b9..de16895e2dc0 100644
+--- a/arch/unicore32/include/mach/regs-spi.h
++++ b/arch/unicore32/include/mach/regs-spi.h
+@@ -4,27 +4,27 @@
+ /*
+  * Control reg. 0 SPI_CR0
+  */
+-#define SPI_CR0		__REG(PKUNITY_SPI_BASE + 0x0000)
++#define SPI_CR0		(PKUNITY_SPI_BASE + 0x0000)
+ /*
+  * Control reg. 1 SPI_CR1
+  */
+-#define SPI_CR1		__REG(PKUNITY_SPI_BASE + 0x0004)
++#define SPI_CR1		(PKUNITY_SPI_BASE + 0x0004)
+ /*
+  * Enable reg SPI_SSIENR
+  */
+-#define SPI_SSIENR	__REG(PKUNITY_SPI_BASE + 0x0008)
++#define SPI_SSIENR	(PKUNITY_SPI_BASE + 0x0008)
+ /*
+  * Status reg SPI_SR
+  */
+-#define SPI_SR		__REG(PKUNITY_SPI_BASE + 0x0028)
++#define SPI_SR		(PKUNITY_SPI_BASE + 0x0028)
+ /*
+  * Interrupt Mask reg SPI_IMR
+  */
+-#define SPI_IMR		__REG(PKUNITY_SPI_BASE + 0x002C)
++#define SPI_IMR		(PKUNITY_SPI_BASE + 0x002C)
+ /*
+  * Interrupt Status reg SPI_ISR
+  */
+-#define SPI_ISR		__REG(PKUNITY_SPI_BASE + 0x0030)
++#define SPI_ISR		(PKUNITY_SPI_BASE + 0x0030)
+ 
+ /*
+  * Enable SPI Controller SPI_SSIENR_EN
+diff --git a/arch/unicore32/include/mach/regs-umal.h b/arch/unicore32/include/mach/regs-umal.h
+index 2e718d1e86cc..885bb62fee71 100644
+--- a/arch/unicore32/include/mach/regs-umal.h
++++ b/arch/unicore32/include/mach/regs-umal.h
+@@ -10,86 +10,86 @@
+ /*
+  * TX/RX reset and control UMAL_CFG1
+  */
+-#define UMAL_CFG1		__REG(PKUNITY_UMAL_BASE + 0x0000)
++#define UMAL_CFG1		(PKUNITY_UMAL_BASE + 0x0000)
+ /*
+  * MAC interface mode control UMAL_CFG2
+  */
+-#define UMAL_CFG2		__REG(PKUNITY_UMAL_BASE + 0x0004)
++#define UMAL_CFG2		(PKUNITY_UMAL_BASE + 0x0004)
+ /*
+  * Inter Packet/Frame Gap UMAL_IPGIFG
+  */
+-#define UMAL_IPGIFG		__REG(PKUNITY_UMAL_BASE + 0x0008)
++#define UMAL_IPGIFG		(PKUNITY_UMAL_BASE + 0x0008)
+ /*
+  * Collision retry or backoff UMAL_HALFDUPLEX
+  */
+-#define UMAL_HALFDUPLEX		__REG(PKUNITY_UMAL_BASE + 0x000c)
++#define UMAL_HALFDUPLEX		(PKUNITY_UMAL_BASE + 0x000c)
+ /*
+  * Maximum Frame Length UMAL_MAXFRAME
+  */
+-#define UMAL_MAXFRAME		__REG(PKUNITY_UMAL_BASE + 0x0010)
++#define UMAL_MAXFRAME		(PKUNITY_UMAL_BASE + 0x0010)
+ /*
+  * Test Regsiter UMAL_TESTREG
+  */
+-#define UMAL_TESTREG		__REG(PKUNITY_UMAL_BASE + 0x001c)
++#define UMAL_TESTREG		(PKUNITY_UMAL_BASE + 0x001c)
+ /*
+  * MII Management Configure UMAL_MIICFG
+  */
+-#define UMAL_MIICFG		__REG(PKUNITY_UMAL_BASE + 0x0020)
++#define UMAL_MIICFG		(PKUNITY_UMAL_BASE + 0x0020)
+ /*
+  * MII Management Command UMAL_MIICMD
+  */
+-#define UMAL_MIICMD		__REG(PKUNITY_UMAL_BASE + 0x0024)
++#define UMAL_MIICMD		(PKUNITY_UMAL_BASE + 0x0024)
+ /*
+  * MII Management Address UMAL_MIIADDR
+  */
+-#define UMAL_MIIADDR		__REG(PKUNITY_UMAL_BASE + 0x0028)
++#define UMAL_MIIADDR		(PKUNITY_UMAL_BASE + 0x0028)
+ /*
+  * MII Management Control UMAL_MIICTRL
+  */
+-#define UMAL_MIICTRL		__REG(PKUNITY_UMAL_BASE + 0x002c)
++#define UMAL_MIICTRL		(PKUNITY_UMAL_BASE + 0x002c)
+ /*
+  * MII Management Status UMAL_MIISTATUS
+  */
+-#define UMAL_MIISTATUS		__REG(PKUNITY_UMAL_BASE + 0x0030)
++#define UMAL_MIISTATUS		(PKUNITY_UMAL_BASE + 0x0030)
+ /*
+  * MII Managment Indicator UMAL_MIIIDCT
+  */
+-#define UMAL_MIIIDCT		__REG(PKUNITY_UMAL_BASE + 0x0034)
++#define UMAL_MIIIDCT		(PKUNITY_UMAL_BASE + 0x0034)
+ /*
+  * Interface Control UMAL_IFCTRL
+  */
+-#define UMAL_IFCTRL		__REG(PKUNITY_UMAL_BASE + 0x0038)
++#define UMAL_IFCTRL		(PKUNITY_UMAL_BASE + 0x0038)
+ /*
+  * Interface Status UMAL_IFSTATUS
+  */
+-#define UMAL_IFSTATUS		__REG(PKUNITY_UMAL_BASE + 0x003c)
++#define UMAL_IFSTATUS		(PKUNITY_UMAL_BASE + 0x003c)
+ /*
+  * MAC address (high 4 bytes) UMAL_STADDR1
+  */
+-#define UMAL_STADDR1		__REG(PKUNITY_UMAL_BASE + 0x0040)
++#define UMAL_STADDR1		(PKUNITY_UMAL_BASE + 0x0040)
+ /*
+  * MAC address (low 2 bytes) UMAL_STADDR2
+  */
+-#define UMAL_STADDR2		__REG(PKUNITY_UMAL_BASE + 0x0044)
++#define UMAL_STADDR2		(PKUNITY_UMAL_BASE + 0x0044)
+ 
+ /* FIFO MODULE OF UMAL */
+ /* UMAL's FIFO module provides data queuing for increased system level
+  * throughput
+  */
+-#define UMAL_FIFOCFG0		__REG(PKUNITY_UMAL_BASE + 0x0048)
+-#define UMAL_FIFOCFG1		__REG(PKUNITY_UMAL_BASE + 0x004c)
+-#define UMAL_FIFOCFG2		__REG(PKUNITY_UMAL_BASE + 0x0050)
+-#define UMAL_FIFOCFG3		__REG(PKUNITY_UMAL_BASE + 0x0054)
+-#define UMAL_FIFOCFG4		__REG(PKUNITY_UMAL_BASE + 0x0058)
+-#define UMAL_FIFOCFG5		__REG(PKUNITY_UMAL_BASE + 0x005c)
+-#define UMAL_FIFORAM0		__REG(PKUNITY_UMAL_BASE + 0x0060)
+-#define UMAL_FIFORAM1		__REG(PKUNITY_UMAL_BASE + 0x0064)
+-#define UMAL_FIFORAM2		__REG(PKUNITY_UMAL_BASE + 0x0068)
+-#define UMAL_FIFORAM3		__REG(PKUNITY_UMAL_BASE + 0x006c)
+-#define UMAL_FIFORAM4		__REG(PKUNITY_UMAL_BASE + 0x0070)
+-#define UMAL_FIFORAM5		__REG(PKUNITY_UMAL_BASE + 0x0074)
+-#define UMAL_FIFORAM6		__REG(PKUNITY_UMAL_BASE + 0x0078)
+-#define UMAL_FIFORAM7		__REG(PKUNITY_UMAL_BASE + 0x007c)
++#define UMAL_FIFOCFG0		(PKUNITY_UMAL_BASE + 0x0048)
++#define UMAL_FIFOCFG1		(PKUNITY_UMAL_BASE + 0x004c)
++#define UMAL_FIFOCFG2		(PKUNITY_UMAL_BASE + 0x0050)
++#define UMAL_FIFOCFG3		(PKUNITY_UMAL_BASE + 0x0054)
++#define UMAL_FIFOCFG4		(PKUNITY_UMAL_BASE + 0x0058)
++#define UMAL_FIFOCFG5		(PKUNITY_UMAL_BASE + 0x005c)
++#define UMAL_FIFORAM0		(PKUNITY_UMAL_BASE + 0x0060)
++#define UMAL_FIFORAM1		(PKUNITY_UMAL_BASE + 0x0064)
++#define UMAL_FIFORAM2		(PKUNITY_UMAL_BASE + 0x0068)
++#define UMAL_FIFORAM3		(PKUNITY_UMAL_BASE + 0x006c)
++#define UMAL_FIFORAM4		(PKUNITY_UMAL_BASE + 0x0070)
++#define UMAL_FIFORAM5		(PKUNITY_UMAL_BASE + 0x0074)
++#define UMAL_FIFORAM6		(PKUNITY_UMAL_BASE + 0x0078)
++#define UMAL_FIFORAM7		(PKUNITY_UMAL_BASE + 0x007c)
+ 
+ /* MAHBE MODUEL OF UMAL */
+ /* UMAL's MAHBE module interfaces to the host system through 32-bit AHB Master
+@@ -99,35 +99,35 @@
+ /*
+  * Transmit Control UMAL_DMATxCtrl
+  */
+-#define UMAL_DMATxCtrl		__REG(PKUNITY_UMAL_BASE + 0x0180)
++#define UMAL_DMATxCtrl		(PKUNITY_UMAL_BASE + 0x0180)
+ /*
+  * Pointer to TX Descripter UMAL_DMATxDescriptor
+  */
+-#define UMAL_DMATxDescriptor	__REG(PKUNITY_UMAL_BASE + 0x0184)
++#define UMAL_DMATxDescriptor	(PKUNITY_UMAL_BASE + 0x0184)
+ /*
+  * Status of Tx Packet Transfers UMAL_DMATxStatus
+  */
+-#define UMAL_DMATxStatus	__REG(PKUNITY_UMAL_BASE + 0x0188)
++#define UMAL_DMATxStatus	(PKUNITY_UMAL_BASE + 0x0188)
+ /*
+  * Receive Control UMAL_DMARxCtrl
+  */
+-#define UMAL_DMARxCtrl		__REG(PKUNITY_UMAL_BASE + 0x018c)
++#define UMAL_DMARxCtrl		(PKUNITY_UMAL_BASE + 0x018c)
+ /*
+  * Pointer to Rx Descriptor UMAL_DMARxDescriptor
+  */
+-#define UMAL_DMARxDescriptor	__REG(PKUNITY_UMAL_BASE + 0x0190)
++#define UMAL_DMARxDescriptor	(PKUNITY_UMAL_BASE + 0x0190)
+ /*
+  * Status of Rx Packet Transfers UMAL_DMARxStatus
+  */
+-#define UMAL_DMARxStatus	__REG(PKUNITY_UMAL_BASE + 0x0194)
++#define UMAL_DMARxStatus	(PKUNITY_UMAL_BASE + 0x0194)
+ /*
+  * Interrupt Mask UMAL_DMAIntrMask
+  */
+-#define UMAL_DMAIntrMask	__REG(PKUNITY_UMAL_BASE + 0x0198)
++#define UMAL_DMAIntrMask	(PKUNITY_UMAL_BASE + 0x0198)
+ /*
+  * Interrupts, read only UMAL_DMAInterrupt
+  */
+-#define UMAL_DMAInterrupt	__REG(PKUNITY_UMAL_BASE + 0x019c)
++#define UMAL_DMAInterrupt	(PKUNITY_UMAL_BASE + 0x019c)
+ 
+ /*
+  * Commands for UMAL_CFG1 register
+diff --git a/arch/unicore32/include/mach/regs-unigfx.h b/arch/unicore32/include/mach/regs-unigfx.h
+index 58bbd540a393..faf8b287fccf 100644
+--- a/arch/unicore32/include/mach/regs-unigfx.h
++++ b/arch/unicore32/include/mach/regs-unigfx.h
+@@ -11,67 +11,67 @@
+ /*
+  * control reg UDE_CFG
+  */
+-#define UDE_CFG       __REG(UDE_BASE + 0x0000)
++#define UDE_CFG       (UDE_BASE + 0x0000)
+ /*
+  * framebuffer start address reg UDE_FSA
+  */
+-#define UDE_FSA       __REG(UDE_BASE + 0x0004)
++#define UDE_FSA       (UDE_BASE + 0x0004)
+ /*
+  * line size reg UDE_LS
+  */
+-#define UDE_LS        __REG(UDE_BASE + 0x0008)
++#define UDE_LS        (UDE_BASE + 0x0008)
+ /*
+  * pitch size reg UDE_PS
+  */
+-#define UDE_PS        __REG(UDE_BASE + 0x000C)
++#define UDE_PS        (UDE_BASE + 0x000C)
+ /*
+  * horizontal active time reg UDE_HAT
+  */
+-#define UDE_HAT       __REG(UDE_BASE + 0x0010)
++#define UDE_HAT       (UDE_BASE + 0x0010)
+ /*
+  * horizontal blank time reg UDE_HBT
+  */
+-#define UDE_HBT       __REG(UDE_BASE + 0x0014)
++#define UDE_HBT       (UDE_BASE + 0x0014)
+ /*
+  * horizontal sync time reg UDE_HST
+  */
+-#define UDE_HST       __REG(UDE_BASE + 0x0018)
++#define UDE_HST       (UDE_BASE + 0x0018)
+ /*
+  * vertival active time reg UDE_VAT
+  */
+-#define UDE_VAT       __REG(UDE_BASE + 0x001C)
++#define UDE_VAT       (UDE_BASE + 0x001C)
+ /*
+  * vertival blank time reg UDE_VBT
+  */
+-#define UDE_VBT       __REG(UDE_BASE + 0x0020)
++#define UDE_VBT       (UDE_BASE + 0x0020)
+ /*
+  * vertival sync time reg UDE_VST
+  */
+-#define UDE_VST       __REG(UDE_BASE + 0x0024)
++#define UDE_VST       (UDE_BASE + 0x0024)
+ /*
+  * cursor position UDE_CXY
+  */
+-#define UDE_CXY       __REG(UDE_BASE + 0x0028)
++#define UDE_CXY       (UDE_BASE + 0x0028)
+ /*
+  * cursor front color UDE_CC0
+  */
+-#define UDE_CC0       __REG(UDE_BASE + 0x002C)
++#define UDE_CC0       (UDE_BASE + 0x002C)
+ /*
+  * cursor background color UDE_CC1
+  */
+-#define UDE_CC1       __REG(UDE_BASE + 0x0030)
++#define UDE_CC1       (UDE_BASE + 0x0030)
+ /*
+  * video position UDE_VXY
+  */
+-#define UDE_VXY       __REG(UDE_BASE + 0x0034)
++#define UDE_VXY       (UDE_BASE + 0x0034)
+ /*
+  * video start address reg UDE_VSA
+  */
+-#define UDE_VSA       __REG(UDE_BASE + 0x0040)
++#define UDE_VSA       (UDE_BASE + 0x0040)
+ /*
+  * video size reg UDE_VS
+  */
+-#define UDE_VS        __REG(UDE_BASE + 0x004C)
++#define UDE_VS        (UDE_BASE + 0x004C)
+ 
+ /*
+  * command reg for UNIGFX GE
+@@ -79,102 +79,102 @@
+ /*
+  * src xy reg UGE_SRCXY
+  */
+-#define UGE_SRCXY     __REG(UGE_BASE + 0x0000)
++#define UGE_SRCXY     (UGE_BASE + 0x0000)
+ /*
+  * dst xy reg UGE_DSTXY
+  */
+-#define UGE_DSTXY     __REG(UGE_BASE + 0x0004)
++#define UGE_DSTXY     (UGE_BASE + 0x0004)
+ /*
+  * pitch reg UGE_PITCH
+  */
+-#define UGE_PITCH     __REG(UGE_BASE + 0x0008)
++#define UGE_PITCH     (UGE_BASE + 0x0008)
+ /*
+  * src start reg UGE_SRCSTART
+  */
+-#define UGE_SRCSTART  __REG(UGE_BASE + 0x000C)
++#define UGE_SRCSTART  (UGE_BASE + 0x000C)
+ /*
+  * dst start reg UGE_DSTSTART
+  */
+-#define UGE_DSTSTART  __REG(UGE_BASE + 0x0010)
++#define UGE_DSTSTART  (UGE_BASE + 0x0010)
+ /*
+  * width height reg UGE_WIDHEIGHT
+  */
+-#define UGE_WIDHEIGHT __REG(UGE_BASE + 0x0014)
++#define UGE_WIDHEIGHT (UGE_BASE + 0x0014)
+ /*
+  * rop alpah reg UGE_ROPALPHA
+  */
+-#define UGE_ROPALPHA  __REG(UGE_BASE + 0x0018)
++#define UGE_ROPALPHA  (UGE_BASE + 0x0018)
+ /*
+  * front color UGE_FCOLOR
+  */
+-#define UGE_FCOLOR    __REG(UGE_BASE + 0x001C)
++#define UGE_FCOLOR    (UGE_BASE + 0x001C)
+ /*
+  * background color UGE_BCOLOR
+  */
+-#define UGE_BCOLOR    __REG(UGE_BASE + 0x0020)
++#define UGE_BCOLOR    (UGE_BASE + 0x0020)
+ /*
+  * src color key for high value UGE_SCH
+  */
+-#define UGE_SCH       __REG(UGE_BASE + 0x0024)
++#define UGE_SCH       (UGE_BASE + 0x0024)
+ /*
+  * dst color key for high value UGE_DCH
+  */
+-#define UGE_DCH       __REG(UGE_BASE + 0x0028)
++#define UGE_DCH       (UGE_BASE + 0x0028)
+ /*
+  * src color key for low value UGE_SCL
+  */
+-#define UGE_SCL       __REG(UGE_BASE + 0x002C)
++#define UGE_SCL       (UGE_BASE + 0x002C)
+ /*
+  * dst color key for low value UGE_DCL
+  */
+-#define UGE_DCL       __REG(UGE_BASE + 0x0030)
++#define UGE_DCL       (UGE_BASE + 0x0030)
+ /*
+  * clip 0 reg UGE_CLIP0
+  */
+-#define UGE_CLIP0     __REG(UGE_BASE + 0x0034)
++#define UGE_CLIP0     (UGE_BASE + 0x0034)
+ /*
+  * clip 1 reg UGE_CLIP1
+  */
+-#define UGE_CLIP1     __REG(UGE_BASE + 0x0038)
++#define UGE_CLIP1     (UGE_BASE + 0x0038)
+ /*
+  * command reg UGE_COMMAND
+  */
+-#define UGE_COMMAND   __REG(UGE_BASE + 0x003C)
++#define UGE_COMMAND   (UGE_BASE + 0x003C)
+ /*
+  * pattern 0 UGE_P0
+  */
+-#define UGE_P0        __REG(UGE_BASE + 0x0040)
+-#define UGE_P1        __REG(UGE_BASE + 0x0044)
+-#define UGE_P2        __REG(UGE_BASE + 0x0048)
+-#define UGE_P3        __REG(UGE_BASE + 0x004C)
+-#define UGE_P4        __REG(UGE_BASE + 0x0050)
+-#define UGE_P5        __REG(UGE_BASE + 0x0054)
+-#define UGE_P6        __REG(UGE_BASE + 0x0058)
+-#define UGE_P7        __REG(UGE_BASE + 0x005C)
+-#define UGE_P8        __REG(UGE_BASE + 0x0060)
+-#define UGE_P9        __REG(UGE_BASE + 0x0064)
+-#define UGE_P10       __REG(UGE_BASE + 0x0068)
+-#define UGE_P11       __REG(UGE_BASE + 0x006C)
+-#define UGE_P12       __REG(UGE_BASE + 0x0070)
+-#define UGE_P13       __REG(UGE_BASE + 0x0074)
+-#define UGE_P14       __REG(UGE_BASE + 0x0078)
+-#define UGE_P15       __REG(UGE_BASE + 0x007C)
+-#define UGE_P16       __REG(UGE_BASE + 0x0080)
+-#define UGE_P17       __REG(UGE_BASE + 0x0084)
+-#define UGE_P18       __REG(UGE_BASE + 0x0088)
+-#define UGE_P19       __REG(UGE_BASE + 0x008C)
+-#define UGE_P20       __REG(UGE_BASE + 0x0090)
+-#define UGE_P21       __REG(UGE_BASE + 0x0094)
+-#define UGE_P22       __REG(UGE_BASE + 0x0098)
+-#define UGE_P23       __REG(UGE_BASE + 0x009C)
+-#define UGE_P24       __REG(UGE_BASE + 0x00A0)
+-#define UGE_P25       __REG(UGE_BASE + 0x00A4)
+-#define UGE_P26       __REG(UGE_BASE + 0x00A8)
+-#define UGE_P27       __REG(UGE_BASE + 0x00AC)
+-#define UGE_P28       __REG(UGE_BASE + 0x00B0)
+-#define UGE_P29       __REG(UGE_BASE + 0x00B4)
+-#define UGE_P30       __REG(UGE_BASE + 0x00B8)
+-#define UGE_P31       __REG(UGE_BASE + 0x00BC)
++#define UGE_P0        (UGE_BASE + 0x0040)
++#define UGE_P1        (UGE_BASE + 0x0044)
++#define UGE_P2        (UGE_BASE + 0x0048)
++#define UGE_P3        (UGE_BASE + 0x004C)
++#define UGE_P4        (UGE_BASE + 0x0050)
++#define UGE_P5        (UGE_BASE + 0x0054)
++#define UGE_P6        (UGE_BASE + 0x0058)
++#define UGE_P7        (UGE_BASE + 0x005C)
++#define UGE_P8        (UGE_BASE + 0x0060)
++#define UGE_P9        (UGE_BASE + 0x0064)
++#define UGE_P10       (UGE_BASE + 0x0068)
++#define UGE_P11       (UGE_BASE + 0x006C)
++#define UGE_P12       (UGE_BASE + 0x0070)
++#define UGE_P13       (UGE_BASE + 0x0074)
++#define UGE_P14       (UGE_BASE + 0x0078)
++#define UGE_P15       (UGE_BASE + 0x007C)
++#define UGE_P16       (UGE_BASE + 0x0080)
++#define UGE_P17       (UGE_BASE + 0x0084)
++#define UGE_P18       (UGE_BASE + 0x0088)
++#define UGE_P19       (UGE_BASE + 0x008C)
++#define UGE_P20       (UGE_BASE + 0x0090)
++#define UGE_P21       (UGE_BASE + 0x0094)
++#define UGE_P22       (UGE_BASE + 0x0098)
++#define UGE_P23       (UGE_BASE + 0x009C)
++#define UGE_P24       (UGE_BASE + 0x00A0)
++#define UGE_P25       (UGE_BASE + 0x00A4)
++#define UGE_P26       (UGE_BASE + 0x00A8)
++#define UGE_P27       (UGE_BASE + 0x00AC)
++#define UGE_P28       (UGE_BASE + 0x00B0)
++#define UGE_P29       (UGE_BASE + 0x00B4)
++#define UGE_P30       (UGE_BASE + 0x00B8)
++#define UGE_P31       (UGE_BASE + 0x00BC)
+ 
+ #define UDE_CFG_DST_MASK	FMASK(2, 8)
+ #define UDE_CFG_DST8            FIELD(0x0, 2, 8)
+diff --git a/arch/unicore32/kernel/entry.S b/arch/unicore32/kernel/entry.S
+index 83698b7c8f5b..00a259f9819e 100644
+--- a/arch/unicore32/kernel/entry.S
++++ b/arch/unicore32/kernel/entry.S
+@@ -91,7 +91,7 @@
+ 	.endm
+ 
+ 	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+-	ldw	\base, =(io_p2v(PKUNITY_INTC_BASE))
++	ldw	\base, =(PKUNITY_INTC_BASE)
+ 	ldw	\irqstat, [\base+], #0xC	@ INTC_ICIP
+ 	ldw	\tmp,	  [\base+], #0x4	@ INTC_ICMR
+ 	and.a	\irqstat, \irqstat, \tmp
+diff --git a/arch/unicore32/kernel/irq.c b/arch/unicore32/kernel/irq.c
+index e1dbfcb61873..b23624cf3062 100644
+--- a/arch/unicore32/kernel/irq.c
++++ b/arch/unicore32/kernel/irq.c
+@@ -226,8 +226,8 @@ static struct irq_chip puv3_normal_chip = {
+ 
+ static struct resource irq_resource = {
+ 	.name	= "irqs",
+-	.start	= PKUNITY_INTC_BASE,
+-	.end	= PKUNITY_INTC_BASE + 0xFFFFF,
++	.start	= io_v2p(PKUNITY_INTC_BASE),
++	.end	= io_v2p(PKUNITY_INTC_BASE) + 0xFFFFF,
+ };
+ 
+ static struct puv3_irq_state {
+diff --git a/arch/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c
+index 65c265ee8e94..100eab842e66 100644
+--- a/arch/unicore32/kernel/pci.c
++++ b/arch/unicore32/kernel/pci.c
+@@ -75,27 +75,27 @@ void pci_puv3_preinit(void)
+ {
+ 	printk(KERN_DEBUG "PCI: PKUnity PCI Controller Initializing ...\n");
+ 	/* config PCI bridge base */
+-	writel(PKUNITY_PCIBRI_BASE, PCICFG_BRIBASE);
++	writel(io_v2p(PKUNITY_PCIBRI_BASE), PCICFG_BRIBASE);
+ 
+ 	writel(0, PCIBRI_AHBCTL0);
+-	writel(PKUNITY_PCIBRI_BASE | PCIBRI_BARx_MEM, PCIBRI_AHBBAR0);
++	writel(io_v2p(PKUNITY_PCIBRI_BASE) | PCIBRI_BARx_MEM, PCIBRI_AHBBAR0);
+ 	writel(0xFFFF0000, PCIBRI_AHBAMR0);
+ 	writel(0, PCIBRI_AHBTAR0);
+ 
+ 	writel(PCIBRI_CTLx_AT, PCIBRI_AHBCTL1);
+-	writel(PKUNITY_PCILIO_BASE | PCIBRI_BARx_IO, PCIBRI_AHBBAR1);
++	writel(io_v2p(PKUNITY_PCILIO_BASE) | PCIBRI_BARx_IO, PCIBRI_AHBBAR1);
+ 	writel(0xFFFF0000, PCIBRI_AHBAMR1);
+ 	writel(0x00000000, PCIBRI_AHBTAR1);
+ 
+ 	writel(PCIBRI_CTLx_PREF, PCIBRI_AHBCTL2);
+-	writel(PKUNITY_PCIMEM_BASE | PCIBRI_BARx_MEM, PCIBRI_AHBBAR2);
++	writel(io_v2p(PKUNITY_PCIMEM_BASE) | PCIBRI_BARx_MEM, PCIBRI_AHBBAR2);
+ 	writel(0xF8000000, PCIBRI_AHBAMR2);
+ 	writel(0, PCIBRI_AHBTAR2);
+ 
+-	writel(PKUNITY_PCIAHB_BASE | PCIBRI_BARx_MEM, PCIBRI_BAR1);
++	writel(io_v2p(PKUNITY_PCIAHB_BASE) | PCIBRI_BARx_MEM, PCIBRI_BAR1);
+ 
+ 	writel(PCIBRI_CTLx_AT | PCIBRI_CTLx_PREF, PCIBRI_PCICTL0);
+-	writel(PKUNITY_PCIAHB_BASE | PCIBRI_BARx_MEM, PCIBRI_PCIBAR0);
++	writel(io_v2p(PKUNITY_PCIAHB_BASE) | PCIBRI_BARx_MEM, PCIBRI_PCIBAR0);
+ 	writel(0xF8000000, PCIBRI_PCIAMR0);
+ 	writel(PKUNITY_SDRAM_BASE, PCIBRI_PCITAR0);
+ 
+diff --git a/arch/unicore32/kernel/puv3-core.c b/arch/unicore32/kernel/puv3-core.c
+index 7d10e7b07c20..8b1b6beb858e 100644
+--- a/arch/unicore32/kernel/puv3-core.c
++++ b/arch/unicore32/kernel/puv3-core.c
+@@ -50,8 +50,8 @@ unsigned long long sched_clock(void)
+ static struct resource puv3_usb_resources[] = {
+ 	/* order is significant! */
+ 	{
+-		.start		= PKUNITY_USB_BASE,
+-		.end		= PKUNITY_USB_BASE + 0x3ff,
++		.start		= io_v2p(PKUNITY_USB_BASE),
++		.end		= io_v2p(PKUNITY_USB_BASE) + 0x3ff,
+ 		.flags		= IORESOURCE_MEM,
+ 	}, {
+ 		.start		= IRQ_USB,
+@@ -82,8 +82,8 @@ static struct musb_hdrc_platform_data puv3_usb_plat = {
+ 
+ static struct resource puv3_mmc_resources[] = {
+ 	[0] = {
+-		.start	= PKUNITY_SDC_BASE,
+-		.end	= PKUNITY_SDC_BASE + 0xfff,
++		.start	= io_v2p(PKUNITY_SDC_BASE),
++		.end	= io_v2p(PKUNITY_SDC_BASE) + 0xfff,
+ 		.flags	= IORESOURCE_MEM,
+ 	},
+ 	[1] = {
+@@ -95,8 +95,8 @@ static struct resource puv3_mmc_resources[] = {
+ 
+ static struct resource puv3_unigfx_resources[] = {
+ 	[0] = {
+-		.start	= PKUNITY_UNIGFX_BASE,
+-		.end	= PKUNITY_UNIGFX_BASE + 0xfff,
++		.start	= io_v2p(PKUNITY_UNIGFX_BASE),
++		.end	= io_v2p(PKUNITY_UNIGFX_BASE) + 0xfff,
+ 		.flags	= IORESOURCE_MEM,
+ 	},
+ 	[1] = {
+@@ -108,8 +108,8 @@ static struct resource puv3_unigfx_resources[] = {
+ 
+ static struct resource puv3_rtc_resources[] = {
+ 	[0] = {
+-		.start = PKUNITY_RTC_BASE,
+-		.end   = PKUNITY_RTC_BASE + 0xff,
++		.start = io_v2p(PKUNITY_RTC_BASE),
++		.end   = io_v2p(PKUNITY_RTC_BASE) + 0xff,
+ 		.flags = IORESOURCE_MEM,
+ 	},
+ 	[1] = {
+@@ -126,16 +126,16 @@ static struct resource puv3_rtc_resources[] = {
+ 
+ static struct resource puv3_pwm_resources[] = {
+ 	[0] = {
+-		.start	= PKUNITY_OST_BASE + 0x80,
+-		.end	= PKUNITY_OST_BASE + 0xff,
++		.start	= io_v2p(PKUNITY_OST_BASE) + 0x80,
++		.end	= io_v2p(PKUNITY_OST_BASE) + 0xff,
+ 		.flags	= IORESOURCE_MEM,
+ 	},
+ };
+ 
+ static struct resource puv3_uart0_resources[] = {
+ 	[0] = {
+-		.start = PKUNITY_UART0_BASE,
+-		.end   = PKUNITY_UART0_BASE + 0xff,
++		.start = io_v2p(PKUNITY_UART0_BASE),
++		.end   = io_v2p(PKUNITY_UART0_BASE) + 0xff,
+ 		.flags = IORESOURCE_MEM,
+ 	},
+ 	[1] = {
+@@ -147,8 +147,8 @@ static struct resource puv3_uart0_resources[] = {
+ 
+ static struct resource puv3_uart1_resources[] = {
+ 	[0] = {
+-		.start = PKUNITY_UART1_BASE,
+-		.end   = PKUNITY_UART1_BASE + 0xff,
++		.start = io_v2p(PKUNITY_UART1_BASE),
++		.end   = io_v2p(PKUNITY_UART1_BASE) + 0xff,
+ 		.flags = IORESOURCE_MEM,
+ 	},
+ 	[1] = {
+@@ -160,8 +160,8 @@ static struct resource puv3_uart1_resources[] = {
+ 
+ static struct resource puv3_umal_resources[] = {
+ 	[0] = {
+-		.start = PKUNITY_UMAL_BASE,
+-		.end   = PKUNITY_UMAL_BASE + 0x1fff,
++		.start = io_v2p(PKUNITY_UMAL_BASE),
++		.end   = io_v2p(PKUNITY_UMAL_BASE) + 0x1fff,
+ 		.flags = IORESOURCE_MEM,
+ 	},
+ 	[1] = {
+diff --git a/arch/unicore32/kernel/puv3-nb0916.c b/arch/unicore32/kernel/puv3-nb0916.c
+index a78e60420653..e731c561ed4e 100644
+--- a/arch/unicore32/kernel/puv3-nb0916.c
++++ b/arch/unicore32/kernel/puv3-nb0916.c
+@@ -39,8 +39,8 @@ static struct resource physmap_flash_resource = {
+ 
+ static struct resource puv3_i2c_resources[] = {
+ 	[0] = {
+-		.start = PKUNITY_I2C_BASE,
+-		.end   = PKUNITY_I2C_BASE + 0xff,
++		.start = io_v2p(PKUNITY_I2C_BASE),
++		.end   = io_v2p(PKUNITY_I2C_BASE) + 0xff,
+ 		.flags = IORESOURCE_MEM,
+ 	},
+ 	[1] = {
+diff --git a/arch/unicore32/kernel/sleep.S b/arch/unicore32/kernel/sleep.S
+index f7c3fc87f7fe..607a104aec59 100644
+--- a/arch/unicore32/kernel/sleep.S
++++ b/arch/unicore32/kernel/sleep.S
+@@ -76,10 +76,10 @@ ENTRY(puv3_cpu_suspend)
+ 
+ 
+ 	@ DDR2 BaseAddr
+-	ldw	r0, =io_p2v(PKUNITY_DDR2CTRL_BASE)
++	ldw	r0, =(PKUNITY_DDR2CTRL_BASE)
+ 
+ 	@ PM BaseAddr
+-	ldw	r1, =io_p2v(PKUNITY_PM_BASE)
++	ldw	r1, =(PKUNITY_PM_BASE)
+ 
+ 	@ set PLL_SYS_CFG reg, 275
+ 	movl	r6, #0x00002401

commit 4fde87cb13a29c06e0b4c2cba86445492098fbc2
+Author: GuanXuetao 
+Date:   Sun Feb 27 12:46:06 2011 +0800
+
+    unicore32: replace unicore32-specific iomap functions with generic lib implementation
+    
+    1. define and enable CONFIG_GENERIC_IOMAP
+    2. define unicore32-specific PCI_IOBASE for asm-generic/io.h
+    3. define HAVE_ARCH_PIO_SIZE and unicore32-specific PIO_* macros
+    4. remove all unicore32-specific iomap functions
+    
+    Signed-off-by: Guan Xuetao 
+    Reviewed-and-Acked-by: Arnd Bergmann 
+
+diff --git a/arch/unicore32/Kconfig b/arch/unicore32/Kconfig
+index 7f65018e64ac..4a36db45fb3d 100644
+--- a/arch/unicore32/Kconfig
++++ b/arch/unicore32/Kconfig
+@@ -30,6 +30,9 @@ config GENERIC_CLOCKEVENTS
+ config GENERIC_CSUM
+ 	def_bool y
+ 
++config GENERIC_IOMAP
++	def_bool y
++
+ config NO_IOPORT
+ 	bool
+ 
+diff --git a/arch/unicore32/include/asm/io.h b/arch/unicore32/include/asm/io.h
+index d73457c1800a..2483fcbadbe4 100644
+--- a/arch/unicore32/include/asm/io.h
++++ b/arch/unicore32/include/asm/io.h
+@@ -18,6 +18,7 @@
+ #include 
+ #include 
+ 
++#define PCI_IOBASE	io_p2v(PKUNITY_PCILIO_BASE)
+ #include 
+ 
+ /*
+@@ -38,9 +39,6 @@ extern void __uc32_iounmap(volatile void __iomem *addr);
+ #define ioremap_cached(cookie, size)	__uc32_ioremap_cached(cookie, size)
+ #define iounmap(cookie)			__uc32_iounmap(cookie)
+ 
+-extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
+-extern void ioport_unmap(void __iomem *addr);
+-
+ /*
+  * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+  * access
+@@ -48,5 +46,10 @@ extern void ioport_unmap(void __iomem *addr);
+ #undef xlate_dev_mem_ptr
+ #define xlate_dev_mem_ptr(p)	__va(p)
+ 
++#define HAVE_ARCH_PIO_SIZE
++#define PIO_OFFSET		(unsigned int)(PCI_IOBASE)
++#define PIO_MASK		(unsigned int)(IO_SPACE_LIMIT)
++#define PIO_RESERVED		(PIO_OFFSET + PIO_MASK + 1)
++
+ #endif	/* __KERNEL__ */
+ #endif	/* __UNICORE_IO_H__ */
+diff --git a/arch/unicore32/mm/Makefile b/arch/unicore32/mm/Makefile
+index f3ff41039f51..46c166699319 100644
+--- a/arch/unicore32/mm/Makefile
++++ b/arch/unicore32/mm/Makefile
+@@ -3,7 +3,7 @@
+ #
+ 
+ obj-y				:= extable.o fault.o init.o pgd.o mmu.o
+-obj-y				+= iomap.o flush.o ioremap.o
++obj-y				+= flush.o ioremap.o
+ 
+ obj-$(CONFIG_SWIOTLB)		+= dma-swiotlb.o
+ 
+diff --git a/arch/unicore32/mm/iomap.c b/arch/unicore32/mm/iomap.c
+deleted file mode 100644
+index a7e1a3d2e069..000000000000
+--- a/arch/unicore32/mm/iomap.c
++++ /dev/null
+@@ -1,56 +0,0 @@
+-/*
+- * linux/arch/unicore32/mm/iomap.c
+- *
+- * Code specific to PKUnity SoC and UniCore ISA
+- *
+- * Copyright (C) 2001-2010 GUAN Xue-tao
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- *
+- * Map IO port and PCI memory spaces so that {read,write}[bwl] can
+- * be used to access this memory.
+- */
+-#include 
+-#include 
+-#include 
+-#include 
+-
+-#ifdef __io
+-void __iomem *ioport_map(unsigned long port, unsigned int nr)
+-{
+-	/* we map PC lagcy 64K IO port to PCI IO space 0x80030000 */
+-	return (void __iomem *) (unsigned long)
+-			io_p2v((port & 0xffff) + PKUNITY_PCILIO_BASE);
+-}
+-EXPORT_SYMBOL(ioport_map);
+-
+-void ioport_unmap(void __iomem *addr)
+-{
+-}
+-EXPORT_SYMBOL(ioport_unmap);
+-#endif
+-
+-#ifdef CONFIG_PCI
+-void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+-{
+-	resource_size_t start = pci_resource_start(dev, bar);
+-	resource_size_t len   = pci_resource_len(dev, bar);
+-	unsigned long flags = pci_resource_flags(dev, bar);
+-
+-	if (!len || !start)
+-		return NULL;
+-	if (maxlen && len > maxlen)
+-		len = maxlen;
+-	if (flags & IORESOURCE_IO)
+-		return ioport_map(start, len);
+-	if (flags & IORESOURCE_MEM) {
+-		if (flags & IORESOURCE_CACHEABLE)
+-			return ioremap(start, len);
+-		return ioremap_nocache(start, len);
+-	}
+-	return NULL;
+-}
+-EXPORT_SYMBOL(pci_iomap);
+-#endif

commit ce443ab5fd536941da1d529ba3963324f941fc29
+Author: GuanXuetao 
+Date:   Sat Feb 26 21:39:10 2011 +0800
+
+    unicore32 machine related: add frame buffer driver for pkunity-v3 soc
+    
+    change from original version -- by advice of Paul Mundt
+    1. remove videomemorysize definitions
+    2. remove unifb_enable and unifb_setup
+    3. use dev_warn instead of printk in fb driver
+    4. remove judgement for FB_ACCEL_PUV3_UNIGFX
+    5. adjust clk_get and clk_set_rate calls
+    6. add resources definitions
+    7. remove unifb_option
+    8. adjust register for platform_device
+    9. adjust unifb_ops position and unifb_regs assignment position
+    
+    Signed-off-by: Guan Xuetao 
+    Acked-by: Arnd Bergmann 
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index fa842ba63a1b..98f942eb7286 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -4902,6 +4902,7 @@ S:	Maintained
+ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/epip/linux-2.6-unicore32.git
+ F:	drivers/input/serio/i8042-unicore32io.h
+ F:	drivers/i2c/busses/i2c-puv3.c
++F:	drivers/video/fb-puv3.c
+ 
+ PMC SIERRA MaxRAID DRIVER
+ M:	Anil Ravindranath 
+diff --git a/arch/unicore32/configs/debug_defconfig b/arch/unicore32/configs/debug_defconfig
+index bf42abdd9683..b5fbde9f1cb2 100644
+--- a/arch/unicore32/configs/debug_defconfig
++++ b/arch/unicore32/configs/debug_defconfig
+@@ -66,7 +66,6 @@ CONFIG_LCD_BACKLIGHT=n
+ 
+ CONFIG_PUV3_RTC=y
+ CONFIG_PUV3_UMAL=y
+-CONFIG_PUV3_UNIGFX=y
+ CONFIG_PUV3_MUSB=n
+ CONFIG_PUV3_AC97=n
+ CONFIG_PUV3_NAND=n
+@@ -130,6 +129,8 @@ CONFIG_VIDEO_DEV=n
+ CONFIG_USB_VIDEO_CLASS=n
+ 
+ #	Graphics support
++CONFIG_FB=y
++CONFIG_FB_PUV3_UNIGFX=y
+ #	Console display driver support
+ CONFIG_VGA_CONSOLE=n
+ CONFIG_FRAMEBUFFER_CONSOLE=y
+diff --git a/arch/unicore32/include/mach/memory.h b/arch/unicore32/include/mach/memory.h
+index 541949dfa5b4..b774eff3ea65 100644
+--- a/arch/unicore32/include/mach/memory.h
++++ b/arch/unicore32/include/mach/memory.h
+@@ -50,7 +50,7 @@ void puv3_pci_adjust_zones(unsigned long *size, unsigned long *holes);
+ 
+ /* kuser area */
+ #define KUSER_VECPAGE_BASE	(KUSER_BASE + UL(0x3fff0000))
+-#define KUSER_UNIGFX_BASE	(KUSER_BASE + PKUNITY_UNIGFX_MMAP_BASE)
++#define KUSER_UNIGFX_BASE	(PAGE_OFFSET + PKUNITY_UNIGFX_MMAP_BASE)
+ /* kuser_vecpage (0xbfff0000) is ro, and vectors page (0xffff0000) is rw */
+ #define kuser_vecpage_to_vectors(x)	((x) - (KUSER_VECPAGE_BASE)	\
+ 					+ (VECTORS_BASE))
+diff --git a/arch/unicore32/kernel/puv3-core.c b/arch/unicore32/kernel/puv3-core.c
+index 6edf928a106c..7d10e7b07c20 100644
+--- a/arch/unicore32/kernel/puv3-core.c
++++ b/arch/unicore32/kernel/puv3-core.c
+@@ -93,6 +93,19 @@ static struct resource puv3_mmc_resources[] = {
+ 	},
+ };
+ 
++static struct resource puv3_unigfx_resources[] = {
++	[0] = {
++		.start	= PKUNITY_UNIGFX_BASE,
++		.end	= PKUNITY_UNIGFX_BASE + 0xfff,
++		.flags	= IORESOURCE_MEM,
++	},
++	[1] = {
++		.start	= PKUNITY_UNIGFX_MMAP_BASE,
++		.end	= PKUNITY_UNIGFX_MMAP_BASE + PKUNITY_UNIGFX_MMAP_SIZE,
++		.flags	= IORESOURCE_MEM,
++	},
++};
++
+ static struct resource puv3_rtc_resources[] = {
+ 	[0] = {
+ 		.start = PKUNITY_RTC_BASE,
+@@ -256,6 +269,8 @@ void __init puv3_core_init(void)
+ 			puv3_umal_resources, ARRAY_SIZE(puv3_umal_resources));
+ 	platform_device_register_simple("PKUnity-v3-MMC", -1,
+ 			puv3_mmc_resources, ARRAY_SIZE(puv3_mmc_resources));
++	platform_device_register_simple("PKUnity-v3-UNIGFX", -1,
++			puv3_unigfx_resources, ARRAY_SIZE(puv3_unigfx_resources));
+ 	platform_device_register_simple("PKUnity-v3-PWM", -1,
+ 			puv3_pwm_resources, ARRAY_SIZE(puv3_pwm_resources));
+ 	platform_device_register_simple("PKUnity-v3-UART", 0,
+diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
+index 6bafb51bb437..ec55a87899ab 100644
+--- a/drivers/video/Kconfig
++++ b/drivers/video/Kconfig
+@@ -2365,6 +2365,17 @@ config FB_JZ4740
+ 	help
+ 	  Framebuffer support for the JZ4740 SoC.
+ 
++config FB_PUV3_UNIGFX
++	tristate "PKUnity v3 Unigfx framebuffer support"
++	depends on FB && UNICORE32 && ARCH_PUV3
++	select FB_SYS_FILLRECT
++	select FB_SYS_COPYAREA
++	select FB_SYS_IMAGEBLIT
++	select FB_SYS_FOPS
++	help
++	  Choose this option if you want to use the Unigfx device as a
++	  framebuffer device. Without the support of PCI & AGP.
++
+ source "drivers/video/omap/Kconfig"
+ source "drivers/video/omap2/Kconfig"
+ 
+diff --git a/drivers/video/Makefile b/drivers/video/Makefile
+index 8c8fabdff9d0..b0eb3da24670 100644
+--- a/drivers/video/Makefile
++++ b/drivers/video/Makefile
+@@ -139,6 +139,7 @@ obj-$(CONFIG_FB_MB862XX)	  += mb862xx/
+ obj-$(CONFIG_FB_MSM)              += msm/
+ obj-$(CONFIG_FB_NUC900)           += nuc900fb.o
+ obj-$(CONFIG_FB_JZ4740)		  += jz4740_fb.o
++obj-$(CONFIG_FB_PUV3_UNIGFX)      += fb-puv3.o
+ 
+ # Platform or fallback drivers go here
+ obj-$(CONFIG_FB_UVESA)            += uvesafb.o
+diff --git a/drivers/video/fb-puv3.c b/drivers/video/fb-puv3.c
+new file mode 100644
+index 000000000000..dbd2dc4745d1
+--- /dev/null
++++ b/drivers/video/fb-puv3.c
+@@ -0,0 +1,846 @@
++/*
++ * Frame Buffer Driver for PKUnity-v3 Unigfx
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ *	Maintained by GUAN Xue-tao 
++ *	Copyright (C) 2001-2010 Guan Xuetao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++#include 
++
++/* Platform_data reserved for unifb registers. */
++#define UNIFB_REGS_NUM		10
++/* RAM reserved for the frame buffer. */
++#define UNIFB_MEMSIZE		(SZ_4M)		/* 4 MB for 1024*768*32b */
++
++/*
++ * cause UNIGFX don not have EDID
++ * all the modes are organized as follow
++ */
++static const struct fb_videomode unifb_modes[] = {
++	/* 0 640x480-60 VESA */
++	{ "640x480@60",  60,  640, 480,  25175000,  48, 16, 34, 10,  96, 1,
++	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
++	/* 1 640x480-75 VESA */
++	{ "640x480@75",  75,  640, 480,  31500000, 120, 16, 18,  1,  64, 1,
++	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
++	/* 2 800x600-60 VESA */
++	{ "800x600@60",  60,  800, 600,  40000000,  88, 40, 26,  1, 128, 1,
++	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
++	/* 3 800x600-75 VESA */
++	{ "800x600@75",  75,  800, 600,  49500000, 160, 16, 23,  1,  80, 1,
++	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
++	/* 4 1024x768-60 VESA */
++	{ "1024x768@60", 60, 1024, 768,  65000000, 160, 24, 34,  3, 136, 1,
++	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
++	/* 5 1024x768-75 VESA */
++	{ "1024x768@75", 75, 1024, 768,  78750000, 176, 16, 30,  1,  96, 1,
++	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
++	/* 6 1280x960-60 VESA */
++	{ "1280x960@60", 60, 1280, 960, 108000000, 312, 96, 38,  1, 112, 1,
++	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
++	/* 7 1440x900-60 VESA */
++	{ "1440x900@60", 60, 1440, 900, 106500000, 232, 80, 30,  3, 152, 1,
++	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
++	/* 8 FIXME 9 1024x600-60 VESA UNTESTED */
++	{ "1024x600@60", 60, 1024, 600,  50650000, 160, 24, 26,  1, 136, 1,
++	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
++	/* 9 FIXME 10 1024x600-75 VESA UNTESTED */
++	{ "1024x600@75", 75, 1024, 600,  61500000, 176, 16, 23,  1,  96, 1,
++	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
++	/* 10 FIXME 11 1366x768-60 VESA UNTESTED */
++	{ "1366x768@60", 60, 1366, 768,  85500000, 256, 58, 18,  1,  112, 3,
++	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
++};
++
++static struct fb_var_screeninfo unifb_default = {
++	.xres =		640,
++	.yres =		480,
++	.xres_virtual =	640,
++	.yres_virtual =	480,
++	.bits_per_pixel = 16,
++	.red =		{ 11, 5, 0 },
++	.green =	{ 5,  6, 0 },
++	.blue =		{ 0,  5, 0 },
++	.activate =	FB_ACTIVATE_NOW,
++	.height =	-1,
++	.width =	-1,
++	.pixclock =	25175000,
++	.left_margin =	48,
++	.right_margin =	16,
++	.upper_margin =	33,
++	.lower_margin =	10,
++	.hsync_len =	96,
++	.vsync_len =	2,
++	.vmode =	FB_VMODE_NONINTERLACED,
++};
++
++static struct fb_fix_screeninfo unifb_fix = {
++	.id =		"UNIGFX FB",
++	.type =		FB_TYPE_PACKED_PIXELS,
++	.visual =	FB_VISUAL_TRUECOLOR,
++	.xpanstep =	1,
++	.ypanstep =	1,
++	.ywrapstep =	1,
++	.accel =	FB_ACCEL_NONE,
++};
++
++static void unifb_sync(struct fb_info *info)
++{
++	/* TODO: may, this can be replaced by interrupt */
++	int cnt;
++
++	for (cnt = 0; cnt < 0x10000000; cnt++) {
++		if (readl(UGE_COMMAND) & 0x1000000)
++			return;
++	}
++
++	if (cnt > 0x8000000)
++		dev_warn(info->device, "Warning: UniGFX GE time out ...\n");
++}
++
++static void unifb_prim_fillrect(struct fb_info *info,
++				const struct fb_fillrect *region)
++{
++	int awidth = region->width;
++	int aheight = region->height;
++	int m_iBpp = info->var.bits_per_pixel;
++	int screen_width = info->var.xres;
++	int src_sel = 1;	/* from fg_color */
++	int pat_sel = 1;
++	int src_x0 = 0;
++	int dst_x0 = region->dx;
++	int src_y0 = 0;
++	int dst_y0 = region->dy;
++	int rop_alpha_sel = 0;
++	int rop_alpha_code = 0xCC;
++	int x_dir = 1;
++	int y_dir = 1;
++	int alpha_r = 0;
++	int alpha_sel = 0;
++	int dst_pitch = screen_width * (m_iBpp / 8);
++	int dst_offset = dst_y0 * dst_pitch + dst_x0 * (m_iBpp / 8);
++	int src_pitch = screen_width * (m_iBpp / 8);
++	int src_offset = src_y0 * src_pitch + src_x0 * (m_iBpp / 8);
++	unsigned int command = 0;
++	int clip_region = 0;
++	int clip_en = 0;
++	int tp_en = 0;
++	int fg_color = 0;
++	int bottom = info->var.yres - 1;
++	int right = info->var.xres - 1;
++	int top = 0;
++
++	bottom = (bottom << 16) | right;
++	command = (rop_alpha_sel << 26) | (pat_sel << 18) | (src_sel << 16)
++		| (x_dir << 20) | (y_dir << 21) | (command << 24)
++		| (clip_region << 23) | (clip_en << 22) | (tp_en << 27);
++	src_pitch = (dst_pitch << 16) | src_pitch;
++	awidth = awidth | (aheight << 16);
++	alpha_r = ((rop_alpha_code & 0xff) << 8) | (alpha_r & 0xff)
++		| (alpha_sel << 16);
++	src_x0 = (src_x0 & 0x1fff) | ((src_y0 & 0x1fff) << 16);
++	dst_x0 = (dst_x0 & 0x1fff) | ((dst_y0 & 0x1fff) << 16);
++	fg_color = region->color;
++
++	unifb_sync(info);
++
++	writel(((u32 *)(info->pseudo_palette))[fg_color], UGE_FCOLOR);
++	writel(0, UGE_BCOLOR);
++	writel(src_pitch, UGE_PITCH);
++	writel(src_offset, UGE_SRCSTART);
++	writel(dst_offset, UGE_DSTSTART);
++	writel(awidth, UGE_WIDHEIGHT);
++	writel(top, UGE_CLIP0);
++	writel(bottom, UGE_CLIP1);
++	writel(alpha_r, UGE_ROPALPHA);
++	writel(src_x0, UGE_SRCXY);
++	writel(dst_x0, UGE_DSTXY);
++	writel(command, UGE_COMMAND);
++}
++
++static void unifb_fillrect(struct fb_info *info,
++		const struct fb_fillrect *region)
++{
++	struct fb_fillrect modded;
++	int vxres, vyres;
++
++	if (info->flags & FBINFO_HWACCEL_DISABLED) {
++		sys_fillrect(info, region);
++		return;
++	}
++
++	vxres = info->var.xres_virtual;
++	vyres = info->var.yres_virtual;
++
++	memcpy(&modded, region, sizeof(struct fb_fillrect));
++
++	if (!modded.width || !modded.height ||
++	    modded.dx >= vxres || modded.dy >= vyres)
++		return;
++
++	if (modded.dx + modded.width > vxres)
++		modded.width = vxres - modded.dx;
++	if (modded.dy + modded.height > vyres)
++		modded.height = vyres - modded.dy;
++
++	unifb_prim_fillrect(info, &modded);
++}
++
++static void unifb_prim_copyarea(struct fb_info *info,
++				const struct fb_copyarea *area)
++{
++	int awidth = area->width;
++	int aheight = area->height;
++	int m_iBpp = info->var.bits_per_pixel;
++	int screen_width = info->var.xres;
++	int src_sel = 2;	/* from mem */
++	int pat_sel = 0;
++	int src_x0 = area->sx;
++	int dst_x0 = area->dx;
++	int src_y0 = area->sy;
++	int dst_y0 = area->dy;
++
++	int rop_alpha_sel = 0;
++	int rop_alpha_code = 0xCC;
++	int x_dir = 1;
++	int y_dir = 1;
++
++	int alpha_r = 0;
++	int alpha_sel = 0;
++	int dst_pitch = screen_width * (m_iBpp / 8);
++	int dst_offset = dst_y0 * dst_pitch + dst_x0 * (m_iBpp / 8);
++	int src_pitch = screen_width * (m_iBpp / 8);
++	int src_offset = src_y0 * src_pitch + src_x0 * (m_iBpp / 8);
++	unsigned int command = 0;
++	int clip_region = 0;
++	int clip_en = 1;
++	int tp_en = 0;
++	int top = 0;
++	int bottom = info->var.yres;
++	int right = info->var.xres;
++	int fg_color = 0;
++	int bg_color = 0;
++
++	if (src_x0 < 0)
++		src_x0 = 0;
++	if (src_y0 < 0)
++		src_y0 = 0;
++
++	if (src_y0 - dst_y0 > 0) {
++		y_dir = 1;
++	} else {
++		y_dir = 0;
++		src_offset = (src_y0 + aheight) * src_pitch +
++				src_x0 * (m_iBpp / 8);
++		dst_offset = (dst_y0 + aheight) * dst_pitch +
++				dst_x0 * (m_iBpp / 8);
++		src_y0 += aheight;
++		dst_y0 += aheight;
++	}
++
++	command = (rop_alpha_sel << 26) | (pat_sel << 18) | (src_sel << 16) |
++		(x_dir << 20) | (y_dir << 21) | (command << 24) |
++		(clip_region << 23) | (clip_en << 22) | (tp_en << 27);
++	src_pitch = (dst_pitch << 16) | src_pitch;
++	awidth = awidth | (aheight << 16);
++	alpha_r = ((rop_alpha_code & 0xff) << 8) | (alpha_r & 0xff) |
++		(alpha_sel << 16);
++	src_x0 = (src_x0 & 0x1fff) | ((src_y0 & 0x1fff) << 16);
++	dst_x0 = (dst_x0 & 0x1fff) | ((dst_y0 & 0x1fff) << 16);
++	bottom = (bottom << 16) | right;
++
++	unifb_sync(info);
++
++	writel(src_pitch, UGE_PITCH);
++	writel(src_offset, UGE_SRCSTART);
++	writel(dst_offset, UGE_DSTSTART);
++	writel(awidth, UGE_WIDHEIGHT);
++	writel(top, UGE_CLIP0);
++	writel(bottom, UGE_CLIP1);
++	writel(bg_color, UGE_BCOLOR);
++	writel(fg_color, UGE_FCOLOR);
++	writel(alpha_r, UGE_ROPALPHA);
++	writel(src_x0, UGE_SRCXY);
++	writel(dst_x0, UGE_DSTXY);
++	writel(command, UGE_COMMAND);
++}
++
++static void unifb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
++{
++	struct fb_copyarea modded;
++	u32 vxres, vyres;
++	modded.sx = area->sx;
++	modded.sy = area->sy;
++	modded.dx = area->dx;
++	modded.dy = area->dy;
++	modded.width = area->width;
++	modded.height = area->height;
++
++	if (info->flags & FBINFO_HWACCEL_DISABLED) {
++		sys_copyarea(info, area);
++		return;
++	}
++
++	vxres = info->var.xres_virtual;
++	vyres = info->var.yres_virtual;
++
++	if (!modded.width || !modded.height ||
++	    modded.sx >= vxres || modded.sy >= vyres ||
++	    modded.dx >= vxres || modded.dy >= vyres)
++		return;
++
++	if (modded.sx + modded.width > vxres)
++		modded.width = vxres - modded.sx;
++	if (modded.dx + modded.width > vxres)
++		modded.width = vxres - modded.dx;
++	if (modded.sy + modded.height > vyres)
++		modded.height = vyres - modded.sy;
++	if (modded.dy + modded.height > vyres)
++		modded.height = vyres - modded.dy;
++
++	unifb_prim_copyarea(info, &modded);
++}
++
++static void unifb_imageblit(struct fb_info *info, const struct fb_image *image)
++{
++	sys_imageblit(info, image);
++}
++
++static u_long get_line_length(int xres_virtual, int bpp)
++{
++	u_long length;
++
++	length = xres_virtual * bpp;
++	length = (length + 31) & ~31;
++	length >>= 3;
++	return length;
++}
++
++/*
++ *  Setting the video mode has been split into two parts.
++ *  First part, xxxfb_check_var, must not write anything
++ *  to hardware, it should only verify and adjust var.
++ *  This means it doesn't alter par but it does use hardware
++ *  data from it to check this var.
++ */
++static int unifb_check_var(struct fb_var_screeninfo *var,
++			 struct fb_info *info)
++{
++	u_long line_length;
++
++	/*
++	 *  FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
++	 *  as FB_VMODE_SMOOTH_XPAN is only used internally
++	 */
++
++	if (var->vmode & FB_VMODE_CONUPDATE) {
++		var->vmode |= FB_VMODE_YWRAP;
++		var->xoffset = info->var.xoffset;
++		var->yoffset = info->var.yoffset;
++	}
++
++	/*
++	 *  Some very basic checks
++	 */
++	if (!var->xres)
++		var->xres = 1;
++	if (!var->yres)
++		var->yres = 1;
++	if (var->xres > var->xres_virtual)
++		var->xres_virtual = var->xres;
++	if (var->yres > var->yres_virtual)
++		var->yres_virtual = var->yres;
++	if (var->bits_per_pixel <= 1)
++		var->bits_per_pixel = 1;
++	else if (var->bits_per_pixel <= 8)
++		var->bits_per_pixel = 8;
++	else if (var->bits_per_pixel <= 16)
++		var->bits_per_pixel = 16;
++	else if (var->bits_per_pixel <= 24)
++		var->bits_per_pixel = 24;
++	else if (var->bits_per_pixel <= 32)
++		var->bits_per_pixel = 32;
++	else
++		return -EINVAL;
++
++	if (var->xres_virtual < var->xoffset + var->xres)
++		var->xres_virtual = var->xoffset + var->xres;
++	if (var->yres_virtual < var->yoffset + var->yres)
++		var->yres_virtual = var->yoffset + var->yres;
++
++	/*
++	 *  Memory limit
++	 */
++	line_length =
++	    get_line_length(var->xres_virtual, var->bits_per_pixel);
++	if (line_length * var->yres_virtual > UNIFB_MEMSIZE)
++		return -ENOMEM;
++
++	/*
++	 * Now that we checked it we alter var. The reason being is that the
++	 * video mode passed in might not work but slight changes to it might
++	 * make it work. This way we let the user know what is acceptable.
++	 */
++	switch (var->bits_per_pixel) {
++	case 1:
++	case 8:
++		var->red.offset = 0;
++		var->red.length = 8;
++		var->green.offset = 0;
++		var->green.length = 8;
++		var->blue.offset = 0;
++		var->blue.length = 8;
++		var->transp.offset = 0;
++		var->transp.length = 0;
++		break;
++	case 16:		/* RGBA 5551 */
++		if (var->transp.length) {
++			var->red.offset = 0;
++			var->red.length = 5;
++			var->green.offset = 5;
++			var->green.length = 5;
++			var->blue.offset = 10;
++			var->blue.length = 5;
++			var->transp.offset = 15;
++			var->transp.length = 1;
++		} else {	/* RGB 565 */
++			var->red.offset = 11;
++			var->red.length = 5;
++			var->green.offset = 5;
++			var->green.length = 6;
++			var->blue.offset = 0;
++			var->blue.length = 5;
++			var->transp.offset = 0;
++			var->transp.length = 0;
++		}
++		break;
++	case 24:		/* RGB 888 */
++		var->red.offset = 0;
++		var->red.length = 8;
++		var->green.offset = 8;
++		var->green.length = 8;
++		var->blue.offset = 16;
++		var->blue.length = 8;
++		var->transp.offset = 0;
++		var->transp.length = 0;
++		break;
++	case 32:		/* RGBA 8888 */
++		var->red.offset = 16;
++		var->red.length = 8;
++		var->green.offset = 8;
++		var->green.length = 8;
++		var->blue.offset = 0;
++		var->blue.length = 8;
++		var->transp.offset = 24;
++		var->transp.length = 8;
++		break;
++	}
++	var->red.msb_right = 0;
++	var->green.msb_right = 0;
++	var->blue.msb_right = 0;
++	var->transp.msb_right = 0;
++
++	return 0;
++}
++
++/*
++ * This routine actually sets the video mode. It's in here where we
++ * the hardware state info->par and fix which can be affected by the
++ * change in par. For this driver it doesn't do much.
++ */
++static int unifb_set_par(struct fb_info *info)
++{
++	int hTotal, vTotal, hSyncStart, hSyncEnd, vSyncStart, vSyncEnd;
++	int format;
++
++#ifdef CONFIG_PUV3_PM
++	struct clk *clk_vga;
++	u32 pixclk = 0;
++	int i;
++
++	for (i = 0; i <= 10; i++) {
++		if    (info->var.xres         == unifb_modes[i].xres
++		    && info->var.yres         == unifb_modes[i].yres
++		    && info->var.upper_margin == unifb_modes[i].upper_margin
++		    && info->var.lower_margin == unifb_modes[i].lower_margin
++		    && info->var.left_margin  == unifb_modes[i].left_margin
++		    && info->var.right_margin == unifb_modes[i].right_margin
++		    && info->var.hsync_len    == unifb_modes[i].hsync_len
++		    && info->var.vsync_len    == unifb_modes[i].vsync_len) {
++			pixclk = unifb_modes[i].pixclock;
++			break;
++		}
++	}
++
++	/* set clock rate */
++	clk_vga = clk_get(info->device, "VGA_CLK");
++	if (clk_vga == ERR_PTR(-ENOENT))
++		return -ENOENT;
++
++	if (pixclk != 0) {
++		if (clk_set_rate(clk_vga, pixclk)) { /* set clock failed */
++			info->fix = unifb_fix;
++			info->var = unifb_default;
++			if (clk_set_rate(clk_vga, unifb_default.pixclock))
++				return -EINVAL;
++		}
++	}
++#endif
++
++	info->fix.line_length = get_line_length(info->var.xres_virtual,
++						info->var.bits_per_pixel);
++
++	hSyncStart = info->var.xres + info->var.right_margin;
++	hSyncEnd = hSyncStart + info->var.hsync_len;
++	hTotal = hSyncEnd + info->var.left_margin;
++
++	vSyncStart = info->var.yres + info->var.lower_margin;
++	vSyncEnd = vSyncStart + info->var.vsync_len;
++	vTotal = vSyncEnd + info->var.upper_margin;
++
++	switch (info->var.bits_per_pixel) {
++	case 8:
++		format = UDE_CFG_DST8;
++		break;
++	case 16:
++		format = UDE_CFG_DST16;
++		break;
++	case 24:
++		format = UDE_CFG_DST24;
++		break;
++	case 32:
++		format = UDE_CFG_DST32;
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	writel(PKUNITY_UNIGFX_MMAP_BASE, UDE_FSA);
++	writel(info->var.yres, UDE_LS);
++	writel(get_line_length(info->var.xres,
++			info->var.bits_per_pixel) >> 3, UDE_PS);
++			/* >> 3 for hardware required. */
++	writel((hTotal << 16) | (info->var.xres), UDE_HAT);
++	writel(((hTotal - 1) << 16) | (info->var.xres - 1), UDE_HBT);
++	writel(((hSyncEnd - 1) << 16) | (hSyncStart - 1), UDE_HST);
++	writel((vTotal << 16) | (info->var.yres), UDE_VAT);
++	writel(((vTotal - 1) << 16) | (info->var.yres - 1), UDE_VBT);
++	writel(((vSyncEnd - 1) << 16) | (vSyncStart - 1), UDE_VST);
++	writel(UDE_CFG_GDEN_ENABLE | UDE_CFG_TIMEUP_ENABLE
++			| format | 0xC0000001, UDE_CFG);
++
++	return 0;
++}
++
++/*
++ *  Set a single color register. The values supplied are already
++ *  rounded down to the hardware's capabilities (according to the
++ *  entries in the var structure). Return != 0 for invalid regno.
++ */
++static int unifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
++			 u_int transp, struct fb_info *info)
++{
++	if (regno >= 256)	/* no. of hw registers */
++		return 1;
++
++	/* grayscale works only partially under directcolor */
++	if (info->var.grayscale) {
++		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
++		red = green = blue =
++		    (red * 77 + green * 151 + blue * 28) >> 8;
++	}
++
++#define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
++	switch (info->fix.visual) {
++	case FB_VISUAL_TRUECOLOR:
++	case FB_VISUAL_PSEUDOCOLOR:
++		red = CNVT_TOHW(red, info->var.red.length);
++		green = CNVT_TOHW(green, info->var.green.length);
++		blue = CNVT_TOHW(blue, info->var.blue.length);
++		transp = CNVT_TOHW(transp, info->var.transp.length);
++		break;
++	case FB_VISUAL_DIRECTCOLOR:
++		red = CNVT_TOHW(red, 8);	/* expect 8 bit DAC */
++		green = CNVT_TOHW(green, 8);
++		blue = CNVT_TOHW(blue, 8);
++		/* hey, there is bug in transp handling... */
++		transp = CNVT_TOHW(transp, 8);
++		break;
++	}
++#undef CNVT_TOHW
++	/* Truecolor has hardware independent palette */
++	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
++		u32 v;
++
++		if (regno >= 16)
++			return 1;
++
++		v = (red << info->var.red.offset) |
++		    (green << info->var.green.offset) |
++		    (blue << info->var.blue.offset) |
++		    (transp << info->var.transp.offset);
++		switch (info->var.bits_per_pixel) {
++		case 8:
++			break;
++		case 16:
++		case 24:
++		case 32:
++			((u32 *) (info->pseudo_palette))[regno] = v;
++			break;
++		default:
++			return 1;
++		}
++		return 0;
++	}
++	return 0;
++}
++
++/*
++ *  Pan or Wrap the Display
++ *
++ *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
++ */
++static int unifb_pan_display(struct fb_var_screeninfo *var,
++			   struct fb_info *info)
++{
++	if (var->vmode & FB_VMODE_YWRAP) {
++		if (var->yoffset < 0
++		    || var->yoffset >= info->var.yres_virtual
++		    || var->xoffset)
++			return -EINVAL;
++	} else {
++		if (var->xoffset + var->xres > info->var.xres_virtual ||
++		    var->yoffset + var->yres > info->var.yres_virtual)
++			return -EINVAL;
++	}
++	info->var.xoffset = var->xoffset;
++	info->var.yoffset = var->yoffset;
++	if (var->vmode & FB_VMODE_YWRAP)
++		info->var.vmode |= FB_VMODE_YWRAP;
++	else
++		info->var.vmode &= ~FB_VMODE_YWRAP;
++	return 0;
++}
++
++int unifb_mmap(struct fb_info *info,
++		    struct vm_area_struct *vma)
++{
++	unsigned long size = vma->vm_end - vma->vm_start;
++	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
++	unsigned long pos = info->fix.smem_start + offset;
++
++	if (offset + size > info->fix.smem_len)
++		return -EINVAL;
++
++	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
++
++	if (io_remap_pfn_range(vma, vma->vm_start, pos >> PAGE_SHIFT, size,
++				vma->vm_page_prot))
++		return -EAGAIN;
++
++	vma->vm_flags |= VM_RESERVED;	/* avoid to swap out this VMA */
++	return 0;
++
++}
++
++static struct fb_ops unifb_ops = {
++	.fb_read        = fb_sys_read,
++	.fb_write       = fb_sys_write,
++	.fb_check_var	= unifb_check_var,
++	.fb_set_par	= unifb_set_par,
++	.fb_setcolreg	= unifb_setcolreg,
++	.fb_pan_display	= unifb_pan_display,
++	.fb_fillrect	= unifb_fillrect,
++	.fb_copyarea	= unifb_copyarea,
++	.fb_imageblit   = unifb_imageblit,
++	.fb_mmap	= unifb_mmap,
++};
++
++/*
++ *  Initialisation
++ */
++static int unifb_probe(struct platform_device *dev)
++{
++	struct fb_info *info;
++	u32 unifb_regs[UNIFB_REGS_NUM];
++	int retval = -ENOMEM;
++	struct resource *iomem, *mapmem;
++
++	info = framebuffer_alloc(sizeof(u32)*256, &dev->dev);
++	if (!info)
++		goto err;
++
++	info->screen_base = (char __iomem *)KUSER_UNIGFX_BASE;
++	info->fbops = &unifb_ops;
++
++	retval = fb_find_mode(&info->var, info, NULL,
++			      unifb_modes, 10, &unifb_modes[0], 16);
++
++	if (!retval || (retval == 4))
++		info->var = unifb_default;
++
++	iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
++	unifb_fix.mmio_start = iomem->start;
++
++	mapmem = platform_get_resource(dev, IORESOURCE_MEM, 1);
++	unifb_fix.smem_start = mapmem->start;
++	unifb_fix.smem_len = UNIFB_MEMSIZE;
++
++	info->fix = unifb_fix;
++	info->pseudo_palette = info->par;
++	info->par = NULL;
++	info->flags = FBINFO_FLAG_DEFAULT;
++#ifdef FB_ACCEL_PUV3_UNIGFX
++	info->fix.accel = FB_ACCEL_PUV3_UNIGFX;
++#endif
++
++	retval = fb_alloc_cmap(&info->cmap, 256, 0);
++	if (retval < 0)
++		goto err1;
++
++	retval = register_framebuffer(info);
++	if (retval < 0)
++		goto err2;
++	platform_set_drvdata(dev, info);
++	platform_device_add_data(dev, unifb_regs, sizeof(u32) * UNIFB_REGS_NUM);
++
++	printk(KERN_INFO
++	       "fb%d: Virtual frame buffer device, using %dM of video memory\n",
++	       info->node, UNIFB_MEMSIZE >> 20);
++	return 0;
++err2:
++	fb_dealloc_cmap(&info->cmap);
++err1:
++	framebuffer_release(info);
++err:
++	return retval;
++}
++
++static int unifb_remove(struct platform_device *dev)
++{
++	struct fb_info *info = platform_get_drvdata(dev);
++
++	if (info) {
++		unregister_framebuffer(info);
++		fb_dealloc_cmap(&info->cmap);
++		framebuffer_release(info);
++	}
++	return 0;
++}
++
++#ifdef CONFIG_PM
++static int unifb_resume(struct platform_device *dev)
++{
++	int rc = 0;
++	u32 *unifb_regs = dev->dev.platform_data;
++
++	if (dev->dev.power.power_state.event == PM_EVENT_ON)
++		return 0;
++
++	console_lock();
++
++	if (dev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
++		writel(unifb_regs[0], UDE_FSA);
++		writel(unifb_regs[1], UDE_LS);
++		writel(unifb_regs[2], UDE_PS);
++		writel(unifb_regs[3], UDE_HAT);
++		writel(unifb_regs[4], UDE_HBT);
++		writel(unifb_regs[5], UDE_HST);
++		writel(unifb_regs[6], UDE_VAT);
++		writel(unifb_regs[7], UDE_VBT);
++		writel(unifb_regs[8], UDE_VST);
++		writel(unifb_regs[9], UDE_CFG);
++	}
++	dev->dev.power.power_state = PMSG_ON;
++
++	console_unlock();
++
++	return rc;
++}
++
++static int unifb_suspend(struct platform_device *dev, pm_message_t mesg)
++{
++	u32 *unifb_regs = dev->dev.platform_data;
++
++	unifb_regs[0] = readl(UDE_FSA);
++	unifb_regs[1] = readl(UDE_LS);
++	unifb_regs[2] = readl(UDE_PS);
++	unifb_regs[3] = readl(UDE_HAT);
++	unifb_regs[4] = readl(UDE_HBT);
++	unifb_regs[5] = readl(UDE_HST);
++	unifb_regs[6] = readl(UDE_VAT);
++	unifb_regs[7] = readl(UDE_VBT);
++	unifb_regs[8] = readl(UDE_VST);
++	unifb_regs[9] = readl(UDE_CFG);
++
++	if (mesg.event == dev->dev.power.power_state.event)
++		return 0;
++
++	switch (mesg.event) {
++	case PM_EVENT_FREEZE:		/* about to take snapshot */
++	case PM_EVENT_PRETHAW:		/* before restoring snapshot */
++		goto done;
++	}
++
++	console_lock();
++
++	/* do nothing... */
++
++	console_unlock();
++
++done:
++	dev->dev.power.power_state = mesg;
++
++	return 0;
++}
++#else
++#define	unifb_resume	NULL
++#define unifb_suspend	NULL
++#endif
++
++static struct platform_driver unifb_driver = {
++	.probe	 = unifb_probe,
++	.remove  = unifb_remove,
++	.resume  = unifb_resume,
++	.suspend = unifb_suspend,
++	.driver  = {
++		.name	= "PKUnity-v3-UNIGFX",
++	},
++};
++
++static int __init unifb_init(void)
++{
++#ifndef MODULE
++	if (fb_get_options("unifb", NULL))
++		return -ENODEV;
++#endif
++
++	return platform_driver_register(&unifb_driver);
++}
++
++module_init(unifb_init);
++
++static void __exit unifb_exit(void)
++{
++	platform_driver_unregister(&unifb_driver);
++}
++
++module_exit(unifb_exit);
++
++MODULE_LICENSE("GPL v2");
+diff --git a/include/linux/fb.h b/include/linux/fb.h
+index 68ba85a00c06..b2a36391d2a1 100644
+--- a/include/linux/fb.h
++++ b/include/linux/fb.h
+@@ -152,6 +152,8 @@
+ #define FB_ACCEL_PROSAVAGE_DDR  0x8d	/* S3 ProSavage DDR             */
+ #define FB_ACCEL_PROSAVAGE_DDRK 0x8e	/* S3 ProSavage DDR-K           */
+ 
++#define FB_ACCEL_PUV3_UNIGFX	0xa0	/* PKUnity-v3 Unigfx		*/
++
+ struct fb_fix_screeninfo {
+ 	char id[16];			/* identification string eg "TT Builtin" */
+ 	unsigned long smem_start;	/* Start of frame buffer mem */

commit d10e4a660d11212a41ac5d2c116a655e25e2d38a
+Author: GuanXuetao 
+Date:   Sat Feb 26 21:29:29 2011 +0800
+
+    unicore32 machine related files: add i2c bus drivers for pkunity-v3 soc
+    
+    change from original version -- by advice of Jean Delvare
+    1. remove global variable i2c_reg, replaced by local variables
+    2. replace ENXIO with ENODEV when no platform resources
+    3. add adapter->nr assignment before i2c_add_numbered_adapter() call
+    4. add judgement for i2c_del_adapter() return value
+    5. release adapter when driver removed
+    6. add __devexit for puv3_i2c_remove() function
+    7. modify several names to more appropriated ones
+    
+    Signed-off-by: Guan Xuetao 
+    Acked-by: Arnd Bergmann 
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index e8b15bfec6d6..fa842ba63a1b 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -4901,6 +4901,7 @@ W:	http://mprc.pku.edu.cn/~guanxuetao/linux
+ S:	Maintained
+ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/epip/linux-2.6-unicore32.git
+ F:	drivers/input/serio/i8042-unicore32io.h
++F:	drivers/i2c/busses/i2c-puv3.c
+ 
+ PMC SIERRA MaxRAID DRIVER
+ M:	Anil Ravindranath 
+diff --git a/arch/unicore32/configs/debug_defconfig b/arch/unicore32/configs/debug_defconfig
+index 3647f68147da..bf42abdd9683 100644
+--- a/arch/unicore32/configs/debug_defconfig
++++ b/arch/unicore32/configs/debug_defconfig
+@@ -114,6 +114,10 @@ CONFIG_INPUT_EVDEV=m
+ #	Keyboards
+ CONFIG_KEYBOARD_GPIO=m
+ 
++#	I2C support
++CONFIG_I2C=y
++CONFIG_I2C_PUV3=y
++
+ #	Hardware Monitoring support
+ #CONFIG_SENSORS_LM75=m
+ #	Generic Thermal sysfs driver
+diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
+index 113505a6434e..cbfcf6fb4a61 100644
+--- a/drivers/i2c/busses/Kconfig
++++ b/drivers/i2c/busses/Kconfig
+@@ -523,6 +523,17 @@ config I2C_PNX
+ 	  This driver can also be built as a module.  If so, the module
+ 	  will be called i2c-pnx.
+ 
++config I2C_PUV3
++	tristate "PKUnity v3 I2C bus support"
++	depends on UNICORE32 && ARCH_PUV3
++	select I2C_ALGOBIT
++	help
++	  This driver supports the I2C IP inside the PKUnity-v3 SoC.
++	  This I2C bus controller is under AMBA/AXI bus.
++
++	  This driver can also be built as a module.  If so, the module
++	  will be called i2c-puv3.
++
+ config I2C_PXA
+ 	tristate "Intel PXA2XX I2C adapter"
+ 	depends on ARCH_PXA || ARCH_MMP
+diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
+index 9d2d0ec7fb23..a83966acc5ab 100644
+--- a/drivers/i2c/busses/Makefile
++++ b/drivers/i2c/busses/Makefile
+@@ -51,6 +51,7 @@ obj-$(CONFIG_I2C_PASEMI)	+= i2c-pasemi.o
+ obj-$(CONFIG_I2C_PCA_PLATFORM)	+= i2c-pca-platform.o
+ obj-$(CONFIG_I2C_PMCMSP)	+= i2c-pmcmsp.o
+ obj-$(CONFIG_I2C_PNX)		+= i2c-pnx.o
++obj-$(CONFIG_I2C_PUV3)		+= i2c-puv3.o
+ obj-$(CONFIG_I2C_PXA)		+= i2c-pxa.o
+ obj-$(CONFIG_I2C_S3C2410)	+= i2c-s3c2410.o
+ obj-$(CONFIG_I2C_S6000)		+= i2c-s6000.o
+diff --git a/drivers/i2c/busses/i2c-puv3.c b/drivers/i2c/busses/i2c-puv3.c
+new file mode 100644
+index 000000000000..fac673940849
+--- /dev/null
++++ b/drivers/i2c/busses/i2c-puv3.c
+@@ -0,0 +1,306 @@
++/*
++ * I2C driver for PKUnity-v3 SoC
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ *	Maintained by GUAN Xue-tao 
++ *	Copyright (C) 2001-2010 Guan Xuetao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++/*
++ * Poll the i2c status register until the specified bit is set.
++ * Returns 0 if timed out (100 msec).
++ */
++static short poll_status(unsigned long bit)
++{
++	int loop_cntr = 1000;
++
++	if (bit & I2C_STATUS_TFNF) {
++		do {
++			udelay(10);
++		} while (!(readl(I2C_STATUS) & bit) && (--loop_cntr > 0));
++	} else {
++		/* RXRDY handler */
++		do {
++			if (readl(I2C_TAR) == I2C_TAR_EEPROM)
++				msleep(20);
++			else
++				udelay(10);
++		} while (!(readl(I2C_RXFLR) & 0xf) && (--loop_cntr > 0));
++	}
++
++	return (loop_cntr > 0);
++}
++
++static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length)
++{
++	int i2c_reg = *buf;
++
++	/* Read data */
++	while (length--) {
++		if (!poll_status(I2C_STATUS_TFNF)) {
++			dev_dbg(&adap->dev, "Tx FIFO Not Full timeout\n");
++			return -ETIMEDOUT;
++		}
++
++		/* send addr */
++		writel(i2c_reg | I2C_DATACMD_WRITE, I2C_DATACMD);
++
++		/* get ready to next write */
++		i2c_reg++;
++
++		/* send read CMD */
++		writel(I2C_DATACMD_READ, I2C_DATACMD);
++
++		/* wait until the Rx FIFO have available */
++		if (!poll_status(I2C_STATUS_RFNE)) {
++			dev_dbg(&adap->dev, "RXRDY timeout\n");
++			return -ETIMEDOUT;
++		}
++
++		/* read the data to buf */
++		*buf = (readl(I2C_DATACMD) & I2C_DATACMD_DAT_MASK);
++		buf++;
++	}
++
++	return 0;
++}
++
++static int xfer_write(struct i2c_adapter *adap, unsigned char *buf, int length)
++{
++	int i2c_reg = *buf;
++
++	/* Do nothing but storing the reg_num to a static variable */
++	if (i2c_reg == -1) {
++		printk(KERN_WARNING "Error i2c reg\n");
++		return -ETIMEDOUT;
++	}
++
++	if (length == 1)
++		return 0;
++
++	buf++;
++	length--;
++	while (length--) {
++		/* send addr */
++		writel(i2c_reg | I2C_DATACMD_WRITE, I2C_DATACMD);
++
++		/* send write CMD */
++		writel(*buf | I2C_DATACMD_WRITE, I2C_DATACMD);
++
++		/* wait until the Rx FIFO have available */
++		msleep(20);
++
++		/* read the data to buf */
++		i2c_reg++;
++		buf++;
++	}
++
++	return 0;
++}
++
++/*
++ * Generic i2c master transfer entrypoint.
++ *
++ */
++static int puv3_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *pmsg,
++		int num)
++{
++	int i, ret;
++	unsigned char swap;
++
++	/* Disable i2c */
++	writel(I2C_ENABLE_DISABLE, I2C_ENABLE);
++
++	/* Set the work mode and speed*/
++	writel(I2C_CON_MASTER | I2C_CON_SPEED_STD | I2C_CON_SLAVEDISABLE, I2C_CON);
++
++	writel(pmsg->addr, I2C_TAR);
++
++	/* Enable i2c */
++	writel(I2C_ENABLE_ENABLE, I2C_ENABLE);
++
++	dev_dbg(&adap->dev, "puv3_i2c_xfer: processing %d messages:\n", num);
++
++	for (i = 0; i < num; i++) {
++		dev_dbg(&adap->dev, " #%d: %sing %d byte%s %s 0x%02x\n", i,
++			pmsg->flags & I2C_M_RD ? "read" : "writ",
++			pmsg->len, pmsg->len > 1 ? "s" : "",
++			pmsg->flags & I2C_M_RD ? "from" : "to",	pmsg->addr);
++
++		if (pmsg->len && pmsg->buf) {	/* sanity check */
++			if (pmsg->flags & I2C_M_RD)
++				ret = xfer_read(adap, pmsg->buf, pmsg->len);
++			else
++				ret = xfer_write(adap, pmsg->buf, pmsg->len);
++
++			if (ret)
++				return ret;
++
++		}
++		dev_dbg(&adap->dev, "transfer complete\n");
++		pmsg++;		/* next message */
++	}
++
++	/* XXX: fixup be16_to_cpu in bq27x00_battery.c */
++	if (pmsg->addr == I2C_TAR_PWIC) {
++		swap = pmsg->buf[0];
++		pmsg->buf[0] = pmsg->buf[1];
++		pmsg->buf[1] = swap;
++	}
++
++	return i;
++}
++
++/*
++ * Return list of supported functionality.
++ */
++static u32 puv3_i2c_func(struct i2c_adapter *adapter)
++{
++	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
++}
++
++static struct i2c_algorithm puv3_i2c_algorithm = {
++	.master_xfer	= puv3_i2c_xfer,
++	.functionality	= puv3_i2c_func,
++};
++
++/*
++ * Main initialization routine.
++ */
++static int __devinit puv3_i2c_probe(struct platform_device *pdev)
++{
++	struct i2c_adapter *adapter;
++	struct resource *mem;
++	int rc;
++
++	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	if (!mem)
++		return -ENODEV;
++
++	if (!request_mem_region(mem->start, resource_size(mem), "puv3_i2c"))
++		return -EBUSY;
++
++	adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
++	if (adapter == NULL) {
++		dev_err(&pdev->dev, "can't allocate inteface!\n");
++		rc = -ENOMEM;
++		goto fail_nomem;
++	}
++	snprintf(adapter->name, sizeof(adapter->name), "PUV3-I2C at 0x%08x",
++			mem->start);
++	adapter->algo = &puv3_i2c_algorithm;
++	adapter->class = I2C_CLASS_HWMON;
++	adapter->dev.parent = &pdev->dev;
++
++	platform_set_drvdata(pdev, adapter);
++
++	adapter->nr = pdev->id;
++	rc = i2c_add_numbered_adapter(adapter);
++	if (rc) {
++		dev_err(&pdev->dev, "Adapter '%s' registration failed\n",
++				adapter->name);
++		goto fail_add_adapter;
++	}
++
++	dev_info(&pdev->dev, "PKUnity v3 i2c bus adapter.\n");
++	return 0;
++
++fail_add_adapter:
++	platform_set_drvdata(pdev, NULL);
++	kfree(adapter);
++fail_nomem:
++	release_mem_region(mem->start, resource_size(mem));
++
++	return rc;
++}
++
++static int __devexit puv3_i2c_remove(struct platform_device *pdev)
++{
++	struct i2c_adapter *adapter = platform_get_drvdata(pdev);
++	struct resource *mem;
++	int rc;
++
++	rc = i2c_del_adapter(adapter);
++	if (rc) {
++		dev_err(&pdev->dev, "Adapter '%s' delete fail\n",
++				adapter->name);
++		return rc;
++	}
++
++	put_device(&pdev->dev);
++	platform_set_drvdata(pdev, NULL);
++
++	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	release_mem_region(mem->start, resource_size(mem));
++
++	return rc;
++}
++
++#ifdef CONFIG_PM
++static int puv3_i2c_suspend(struct platform_device *dev, pm_message_t state)
++{
++	int poll_count;
++	/* Disable the IIC */
++	writel(I2C_ENABLE_DISABLE, I2C_ENABLE);
++	for (poll_count = 0; poll_count < 50; poll_count++) {
++		if (readl(I2C_ENSTATUS) & I2C_ENSTATUS_ENABLE)
++			udelay(25);
++	}
++
++	return 0;
++}
++
++static int puv3_i2c_resume(struct platform_device *dev)
++{
++	return 0 ;
++}
++#else
++#define puv3_i2c_suspend NULL
++#define puv3_i2c_resume NULL
++#endif
++
++MODULE_ALIAS("platform:puv3_i2c");
++
++static struct platform_driver puv3_i2c_driver = {
++	.probe		= puv3_i2c_probe,
++	.remove		= __devexit_p(puv3_i2c_remove),
++	.suspend	= puv3_i2c_suspend,
++	.resume		= puv3_i2c_resume,
++	.driver		= {
++		.name	= "PKUnity-v3-I2C",
++		.owner	= THIS_MODULE,
++	}
++};
++
++static int __init puv3_i2c_init(void)
++{
++	return platform_driver_register(&puv3_i2c_driver);
++}
++
++static void __exit puv3_i2c_exit(void)
++{
++	platform_driver_unregister(&puv3_i2c_driver);
++}
++
++module_init(puv3_i2c_init);
++module_exit(puv3_i2c_exit);
++
++MODULE_DESCRIPTION("PKUnity v3 I2C driver");
++MODULE_LICENSE("GPL v2");

commit e5abf78b57199a417eb01ff922a5ea6ff9e10b61
+Author: GuanXuetao 
+Date:   Sat Feb 26 21:21:18 2011 +0800
+
+    unicore32 io: redefine __REG(x) and re-use readl/writel funcs
+    
+      -- by advice of Arnd Bergmann
+    
+    Signed-off-by: Guan Xuetao 
+    Reviewed-by: Arnd Bergmann 
+
+diff --git a/arch/unicore32/include/asm/gpio.h b/arch/unicore32/include/asm/gpio.h
+index 3aaa41e9e413..2716f14e3ff6 100644
+--- a/arch/unicore32/include/asm/gpio.h
++++ b/arch/unicore32/include/asm/gpio.h
+@@ -13,6 +13,7 @@
+ #ifndef __UNICORE_GPIO_H__
+ #define __UNICORE_GPIO_H__
+ 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -66,7 +67,7 @@
+ static inline int gpio_get_value(unsigned gpio)
+ {
+ 	if (__builtin_constant_p(gpio) && (gpio <= GPIO_MAX))
+-		return GPIO_GPLR & GPIO_GPIO(gpio);
++		return readl(GPIO_GPLR) & GPIO_GPIO(gpio);
+ 	else
+ 		return __gpio_get_value(gpio);
+ }
+@@ -75,9 +76,9 @@ static inline void gpio_set_value(unsigned gpio, int value)
+ {
+ 	if (__builtin_constant_p(gpio) && (gpio <= GPIO_MAX))
+ 		if (value)
+-			GPIO_GPSR = GPIO_GPIO(gpio);
++			writel(GPIO_GPIO(gpio), GPIO_GPSR);
+ 		else
+-			GPIO_GPCR = GPIO_GPIO(gpio);
++			writel(GPIO_GPIO(gpio), GPIO_GPCR);
+ 	else
+ 		__gpio_set_value(gpio, value);
+ }
+@@ -86,7 +87,7 @@ static inline void gpio_set_value(unsigned gpio, int value)
+ 
+ static inline unsigned gpio_to_irq(unsigned gpio)
+ {
+-	if ((gpio < IRQ_GPIOHIGH) && (FIELD(1, 1, gpio) & GPIO_GPIR))
++	if ((gpio < IRQ_GPIOHIGH) && (FIELD(1, 1, gpio) & readl(GPIO_GPIR)))
+ 		return IRQ_GPIOLOW0 + gpio;
+ 	else
+ 		return IRQ_GPIO0 + gpio;
+diff --git a/arch/unicore32/include/mach/dma.h b/arch/unicore32/include/mach/dma.h
+index 3e3224a10525..d655c1b6e083 100644
+--- a/arch/unicore32/include/mach/dma.h
++++ b/arch/unicore32/include/mach/dma.h
+@@ -35,7 +35,14 @@ extern int puv3_request_dma(char *name,
+ 
+ extern void puv3_free_dma(int dma_ch);
+ 
+-#define puv3_stop_dma(ch)		(DMAC_CONFIG(ch) &= ~DMAC_CONFIG_EN)
+-#define puv3_resume_dma(ch)             (DMAC_CONFIG(ch) |= DMAC_CONFIG_EN)
++static inline void puv3_stop_dma(int ch)
++{
++	writel(readl(DMAC_CONFIG(ch)) & ~DMAC_CONFIG_EN, DMAC_CONFIG(ch));
++}
++
++static inline void puv3_resume_dma(int ch)
++{
++	writel(readl(DMAC_CONFIG(ch)) | DMAC_CONFIG_EN, DMAC_CONFIG(ch));
++}
+ 
+ #endif /* __MACH_PUV3_DMA_H__ */
+diff --git a/arch/unicore32/include/mach/hardware.h b/arch/unicore32/include/mach/hardware.h
+index c7d3dd6b4eff..b71405ab6de6 100644
+--- a/arch/unicore32/include/mach/hardware.h
++++ b/arch/unicore32/include/mach/hardware.h
+@@ -22,13 +22,7 @@
+ 
+ #ifndef __ASSEMBLY__
+ 
+-# define __REG(x)	(*((volatile unsigned long *)io_p2v(x)))
+-# define __PREG(x)	(io_v2p((unsigned long)&(x)))
+-
+-#else
+-
+-# define __REG(x)	io_p2v(x)
+-# define __PREG(x)	io_v2p(x)
++# define __REG(x)	(void __iomem *)io_p2v(x)
+ 
+ #endif
+ 
+diff --git a/arch/unicore32/kernel/clock.c b/arch/unicore32/kernel/clock.c
+index 80323db581fd..18d4563e6fa5 100644
+--- a/arch/unicore32/kernel/clock.c
++++ b/arch/unicore32/kernel/clock.c
+@@ -20,6 +20,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ 
+@@ -152,28 +153,29 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
+ 		if (ret)
+ 			return ret;
+ 
+-		if (PM_PLLVGACFG == pll_vgacfg)
++		if (readl(PM_PLLVGACFG) == pll_vgacfg)
+ 			return 0;
+ 
+ 		/* set pll vga cfg reg. */
+-		PM_PLLVGACFG = pll_vgacfg;
++		writel(pll_vgacfg, PM_PLLVGACFG);
+ 
+-		PM_PMCR = PM_PMCR_CFBVGA;
+-		while ((PM_PLLDFCDONE & PM_PLLDFCDONE_VGADFC)
++		writel(PM_PMCR_CFBVGA, PM_PMCR);
++		while ((readl(PM_PLLDFCDONE) & PM_PLLDFCDONE_VGADFC)
+ 				!= PM_PLLDFCDONE_VGADFC)
+ 			udelay(100); /* about 1ms */
+ 
+ 		/* set div cfg reg. */
+-		PM_PCGR |= PM_PCGR_VGACLK;
++		writel(readl(PM_PCGR) | PM_PCGR_VGACLK, PM_PCGR);
+ 
+-		PM_DIVCFG = (PM_DIVCFG & ~PM_DIVCFG_VGACLK_MASK)
+-				| PM_DIVCFG_VGACLK(pll_vgadiv);
++		writel((readl(PM_DIVCFG) & ~PM_DIVCFG_VGACLK_MASK)
++				| PM_DIVCFG_VGACLK(pll_vgadiv), PM_DIVCFG);
+ 
+-		PM_SWRESET |= PM_SWRESET_VGADIV;
+-		while ((PM_SWRESET & PM_SWRESET_VGADIV) == PM_SWRESET_VGADIV)
++		writel(readl(PM_SWRESET) | PM_SWRESET_VGADIV, PM_SWRESET);
++		while ((readl(PM_SWRESET) & PM_SWRESET_VGADIV)
++				== PM_SWRESET_VGADIV)
+ 			udelay(100); /* 65536 bclk32, about 320us */
+ 
+-		PM_PCGR &= ~PM_PCGR_VGACLK;
++		writel(readl(PM_PCGR) & ~PM_PCGR_VGACLK, PM_PCGR);
+ 	}
+ #ifdef CONFIG_CPU_FREQ
+ 	if (clk == &clk_mclk_clk) {
+@@ -323,15 +325,15 @@ struct {
+ static int __init clk_init(void)
+ {
+ #ifdef CONFIG_PUV3_PM
+-	u32 pllrate, divstatus = PM_DIVSTATUS;
+-	u32 pcgr_val = PM_PCGR;
++	u32 pllrate, divstatus = readl(PM_DIVSTATUS);
++	u32 pcgr_val = readl(PM_PCGR);
+ 	int i;
+ 
+ 	pcgr_val |= PM_PCGR_BCLKMME | PM_PCGR_BCLKH264E | PM_PCGR_BCLKH264D
+ 			| PM_PCGR_HECLK | PM_PCGR_HDCLK;
+-	PM_PCGR = pcgr_val;
++	writel(pcgr_val, PM_PCGR);
+ 
+-	pllrate = PM_PLLSYSSTATUS;
++	pllrate = readl(PM_PLLSYSSTATUS);
+ 
+ 	/* lookup pmclk_table */
+ 	clk_mclk_clk.rate = 0;
+@@ -346,7 +348,7 @@ static int __init clk_init(void)
+ 		clk_bclk32_clk.rate = clk_mclk_clk.rate /
+ 			(((divstatus & 0x0000f000) >> 12) + 1);
+ 
+-	pllrate = PM_PLLDDRSTATUS;
++	pllrate = readl(PM_PLLDDRSTATUS);
+ 
+ 	/* lookup pddr_table */
+ 	clk_ddr_clk.rate = 0;
+@@ -357,7 +359,7 @@ static int __init clk_init(void)
+ 		}
+ 	}
+ 
+-	pllrate = PM_PLLVGASTATUS;
++	pllrate = readl(PM_PLLVGASTATUS);
+ 
+ 	/* lookup pvga_table */
+ 	clk_vga_clk.rate = 0;
+diff --git a/arch/unicore32/kernel/dma.c b/arch/unicore32/kernel/dma.c
+index b8dcc2514e9a..ae441bc3122c 100644
+--- a/arch/unicore32/kernel/dma.c
++++ b/arch/unicore32/kernel/dma.c
+@@ -16,6 +16,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ #include 
+@@ -94,15 +95,16 @@ EXPORT_SYMBOL(puv3_free_dma);
+ 
+ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
+ {
+-	int i, dint = DMAC_ITCSR;
++	int i, dint;
+ 
++	dint = readl(DMAC_ITCSR);
+ 	for (i = 0; i < MAX_DMA_CHANNELS; i++) {
+ 		if (dint & DMAC_CHANNEL(i)) {
+ 			struct dma_channel *channel = &dma_channels[i];
+ 
+ 			/* Clear TC interrupt of channel i */
+-			DMAC_ITCCR = DMAC_CHANNEL(i);
+-			DMAC_ITCCR = 0;
++			writel(DMAC_CHANNEL(i), DMAC_ITCCR);
++			writel(0, DMAC_ITCCR);
+ 
+ 			if (channel->name && channel->irq_handler) {
+ 				channel->irq_handler(i, channel->data);
+@@ -121,15 +123,16 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
+ 
+ static irqreturn_t dma_err_handler(int irq, void *dev_id)
+ {
+-	int i, dint = DMAC_IESR;
++	int i, dint;
+ 
++	dint = readl(DMAC_IESR);
+ 	for (i = 0; i < MAX_DMA_CHANNELS; i++) {
+ 		if (dint & DMAC_CHANNEL(i)) {
+ 			struct dma_channel *channel = &dma_channels[i];
+ 
+ 			/* Clear Err interrupt of channel i */
+-			DMAC_IECR = DMAC_CHANNEL(i);
+-			DMAC_IECR = 0;
++			writel(DMAC_CHANNEL(i), DMAC_IECR);
++			writel(0, DMAC_IECR);
+ 
+ 			if (channel->name && channel->err_handler) {
+ 				channel->err_handler(i, channel->data);
+diff --git a/arch/unicore32/kernel/gpio.c b/arch/unicore32/kernel/gpio.c
+index 4cb28308bb5f..cb12ec39552c 100644
+--- a/arch/unicore32/kernel/gpio.c
++++ b/arch/unicore32/kernel/gpio.c
+@@ -52,15 +52,15 @@ device_initcall(puv3_gpio_leds_init);
+ 
+ static int puv3_gpio_get(struct gpio_chip *chip, unsigned offset)
+ {
+-	return GPIO_GPLR & GPIO_GPIO(offset);
++	return readl(GPIO_GPLR) & GPIO_GPIO(offset);
+ }
+ 
+ static void puv3_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+ {
+ 	if (value)
+-		GPIO_GPSR = GPIO_GPIO(offset);
++		writel(GPIO_GPIO(offset), GPIO_GPSR);
+ 	else
+-		GPIO_GPCR = GPIO_GPIO(offset);
++		writel(GPIO_GPIO(offset), GPIO_GPCR);
+ }
+ 
+ static int puv3_direction_input(struct gpio_chip *chip, unsigned offset)
+@@ -68,7 +68,7 @@ static int puv3_direction_input(struct gpio_chip *chip, unsigned offset)
+ 	unsigned long flags;
+ 
+ 	local_irq_save(flags);
+-	GPIO_GPDR &= ~GPIO_GPIO(offset);
++	writel(readl(GPIO_GPDR) & ~GPIO_GPIO(offset), GPIO_GPDR);
+ 	local_irq_restore(flags);
+ 	return 0;
+ }
+@@ -80,7 +80,7 @@ static int puv3_direction_output(struct gpio_chip *chip, unsigned offset,
+ 
+ 	local_irq_save(flags);
+ 	puv3_gpio_set(chip, offset, value);
+-	GPIO_GPDR |= GPIO_GPIO(offset);
++	writel(readl(GPIO_GPDR) | GPIO_GPIO(offset), GPIO_GPDR);
+ 	local_irq_restore(flags);
+ 	return 0;
+ }
+@@ -97,7 +97,7 @@ static struct gpio_chip puv3_gpio_chip = {
+ 
+ void __init puv3_init_gpio(void)
+ {
+-	GPIO_GPDR = GPIO_DIR;
++	writel(GPIO_DIR, GPIO_GPDR);
+ #if	defined(CONFIG_PUV3_NB0916) || defined(CONFIG_PUV3_SMW0919)	\
+ 	|| defined(CONFIG_PUV3_DB0913)
+ 	gpio_set_value(GPO_WIFI_EN, 1);
+diff --git a/arch/unicore32/kernel/irq.c b/arch/unicore32/kernel/irq.c
+index 38e30897dea3..e1dbfcb61873 100644
+--- a/arch/unicore32/kernel/irq.c
++++ b/arch/unicore32/kernel/irq.c
+@@ -66,8 +66,8 @@ static int puv3_gpio_type(struct irq_data *d, unsigned int type)
+ 	else
+ 		GPIO_IRQ_falling_edge &= ~mask;
+ 
+-	GPIO_GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
+-	GPIO_GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
++	writel(GPIO_IRQ_rising_edge & GPIO_IRQ_mask, GPIO_GRER);
++	writel(GPIO_IRQ_falling_edge & GPIO_IRQ_mask, GPIO_GFER);
+ 
+ 	return 0;
+ }
+@@ -77,25 +77,25 @@ static int puv3_gpio_type(struct irq_data *d, unsigned int type)
+  */
+ static void puv3_low_gpio_ack(struct irq_data *d)
+ {
+-	GPIO_GEDR = (1 << d->irq);
++	writel((1 << d->irq), GPIO_GEDR);
+ }
+ 
+ static void puv3_low_gpio_mask(struct irq_data *d)
+ {
+-	INTC_ICMR &= ~(1 << d->irq);
++	writel(readl(INTC_ICMR) & ~(1 << d->irq), INTC_ICMR);
+ }
+ 
+ static void puv3_low_gpio_unmask(struct irq_data *d)
+ {
+-	INTC_ICMR |= 1 << d->irq;
++	writel(readl(INTC_ICMR) | (1 << d->irq), INTC_ICMR);
+ }
+ 
+ static int puv3_low_gpio_wake(struct irq_data *d, unsigned int on)
+ {
+ 	if (on)
+-		PM_PWER |= 1 << d->irq;
++		writel(readl(PM_PWER) | (1 << d->irq), PM_PWER);
+ 	else
+-		PM_PWER &= ~(1 << d->irq);
++		writel(readl(PM_PWER) & ~(1 << d->irq), PM_PWER);
+ 	return 0;
+ }
+ 
+@@ -118,13 +118,13 @@ puv3_gpio_handler(unsigned int irq, struct irq_desc *desc)
+ {
+ 	unsigned int mask;
+ 
+-	mask = GPIO_GEDR;
++	mask = readl(GPIO_GEDR);
+ 	do {
+ 		/*
+ 		 * clear down all currently active IRQ sources.
+ 		 * We will be processing them all.
+ 		 */
+-		GPIO_GEDR = mask;
++		writel(mask, GPIO_GEDR);
+ 
+ 		irq = IRQ_GPIO0;
+ 		do {
+@@ -133,7 +133,7 @@ puv3_gpio_handler(unsigned int irq, struct irq_desc *desc)
+ 			mask >>= 1;
+ 			irq++;
+ 		} while (mask);
+-		mask = GPIO_GEDR;
++		mask = readl(GPIO_GEDR);
+ 	} while (mask);
+ }
+ 
+@@ -146,7 +146,7 @@ static void puv3_high_gpio_ack(struct irq_data *d)
+ {
+ 	unsigned int mask = GPIO_MASK(d->irq);
+ 
+-	GPIO_GEDR = mask;
++	writel(mask, GPIO_GEDR);
+ }
+ 
+ static void puv3_high_gpio_mask(struct irq_data *d)
+@@ -155,8 +155,8 @@ static void puv3_high_gpio_mask(struct irq_data *d)
+ 
+ 	GPIO_IRQ_mask &= ~mask;
+ 
+-	GPIO_GRER &= ~mask;
+-	GPIO_GFER &= ~mask;
++	writel(readl(GPIO_GRER) & ~mask, GPIO_GRER);
++	writel(readl(GPIO_GFER) & ~mask, GPIO_GFER);
+ }
+ 
+ static void puv3_high_gpio_unmask(struct irq_data *d)
+@@ -165,16 +165,16 @@ static void puv3_high_gpio_unmask(struct irq_data *d)
+ 
+ 	GPIO_IRQ_mask |= mask;
+ 
+-	GPIO_GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
+-	GPIO_GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
++	writel(GPIO_IRQ_rising_edge & GPIO_IRQ_mask, GPIO_GRER);
++	writel(GPIO_IRQ_falling_edge & GPIO_IRQ_mask, GPIO_GFER);
+ }
+ 
+ static int puv3_high_gpio_wake(struct irq_data *d, unsigned int on)
+ {
+ 	if (on)
+-		PM_PWER |= PM_PWER_GPIOHIGH;
++		writel(readl(PM_PWER) | PM_PWER_GPIOHIGH, PM_PWER);
+ 	else
+-		PM_PWER &= ~PM_PWER_GPIOHIGH;
++		writel(readl(PM_PWER) & ~PM_PWER_GPIOHIGH, PM_PWER);
+ 	return 0;
+ }
+ 
+@@ -193,12 +193,12 @@ static struct irq_chip puv3_high_gpio_chip = {
+  */
+ static void puv3_mask_irq(struct irq_data *d)
+ {
+-	INTC_ICMR &= ~(1 << d->irq);
++	writel(readl(INTC_ICMR) & ~(1 << d->irq), INTC_ICMR);
+ }
+ 
+ static void puv3_unmask_irq(struct irq_data *d)
+ {
+-	INTC_ICMR |= (1 << d->irq);
++	writel(readl(INTC_ICMR) | (1 << d->irq), INTC_ICMR);
+ }
+ 
+ /*
+@@ -208,9 +208,9 @@ static int puv3_set_wake(struct irq_data *d, unsigned int on)
+ {
+ 	if (d->irq == IRQ_RTCAlarm) {
+ 		if (on)
+-			PM_PWER |= PM_PWER_RTC;
++			writel(readl(PM_PWER) | PM_PWER_RTC, PM_PWER);
+ 		else
+-			PM_PWER &= ~PM_PWER_RTC;
++			writel(readl(PM_PWER) & ~PM_PWER_RTC, PM_PWER);
+ 		return 0;
+ 	}
+ 	return -EINVAL;
+@@ -242,25 +242,25 @@ static int puv3_irq_suspend(struct sys_device *dev, pm_message_t state)
+ 	struct puv3_irq_state *st = &puv3_irq_state;
+ 
+ 	st->saved = 1;
+-	st->icmr = INTC_ICMR;
+-	st->iclr = INTC_ICLR;
+-	st->iccr = INTC_ICCR;
++	st->icmr = readl(INTC_ICMR);
++	st->iclr = readl(INTC_ICLR);
++	st->iccr = readl(INTC_ICCR);
+ 
+ 	/*
+ 	 * Disable all GPIO-based interrupts.
+ 	 */
+-	INTC_ICMR &= ~(0x1ff);
++	writel(readl(INTC_ICMR) & ~(0x1ff), INTC_ICMR);
+ 
+ 	/*
+ 	 * Set the appropriate edges for wakeup.
+ 	 */
+-	GPIO_GRER = PM_PWER & GPIO_IRQ_rising_edge;
+-	GPIO_GFER = PM_PWER & GPIO_IRQ_falling_edge;
++	writel(readl(PM_PWER) & GPIO_IRQ_rising_edge, GPIO_GRER);
++	writel(readl(PM_PWER) & GPIO_IRQ_falling_edge, GPIO_GFER);
+ 
+ 	/*
+ 	 * Clear any pending GPIO interrupts.
+ 	 */
+-	GPIO_GEDR = GPIO_GEDR;
++	writel(readl(GPIO_GEDR), GPIO_GEDR);
+ 
+ 	return 0;
+ }
+@@ -270,13 +270,13 @@ static int puv3_irq_resume(struct sys_device *dev)
+ 	struct puv3_irq_state *st = &puv3_irq_state;
+ 
+ 	if (st->saved) {
+-		INTC_ICCR = st->iccr;
+-		INTC_ICLR = st->iclr;
++		writel(st->iccr, INTC_ICCR);
++		writel(st->iclr, INTC_ICLR);
+ 
+-		GPIO_GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
+-		GPIO_GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
++		writel(GPIO_IRQ_rising_edge & GPIO_IRQ_mask, GPIO_GRER);
++		writel(GPIO_IRQ_falling_edge & GPIO_IRQ_mask, GPIO_GFER);
+ 
+-		INTC_ICMR = st->icmr;
++		writel(st->icmr, INTC_ICMR);
+ 	}
+ 	return 0;
+ }
+@@ -307,18 +307,18 @@ void __init init_IRQ(void)
+ 	request_resource(&iomem_resource, &irq_resource);
+ 
+ 	/* disable all IRQs */
+-	INTC_ICMR = 0;
++	writel(0, INTC_ICMR);
+ 
+ 	/* all IRQs are IRQ, not REAL */
+-	INTC_ICLR = 0;
++	writel(0, INTC_ICLR);
+ 
+ 	/* clear all GPIO edge detects */
+-	GPIO_GPIR = FMASK(8, 0) & ~FIELD(1, 1, GPI_SOFF_REQ);
+-	GPIO_GFER = 0;
+-	GPIO_GRER = 0;
+-	GPIO_GEDR = 0x0FFFFFFF;
++	writel(FMASK(8, 0) & ~FIELD(1, 1, GPI_SOFF_REQ), GPIO_GPIR);
++	writel(0, GPIO_GFER);
++	writel(0, GPIO_GRER);
++	writel(0x0FFFFFFF, GPIO_GEDR);
+ 
+-	INTC_ICCR = 1;
++	writel(1, INTC_ICCR);
+ 
+ 	for (irq = 0; irq < IRQ_GPIOHIGH; irq++) {
+ 		set_irq_chip(irq, &puv3_low_gpio_chip);
+diff --git a/arch/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c
+index d4e55e2d2d29..65c265ee8e94 100644
+--- a/arch/unicore32/kernel/pci.c
++++ b/arch/unicore32/kernel/pci.c
+@@ -30,16 +30,16 @@ static int
+ puv3_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+ 			int size, u32 *value)
+ {
+-	PCICFG_ADDR = CONFIG_CMD(bus, devfn, where);
++	writel(CONFIG_CMD(bus, devfn, where), PCICFG_ADDR);
+ 	switch (size) {
+ 	case 1:
+-		*value = (PCICFG_DATA >> ((where & 3) * 8)) & 0xFF;
++		*value = (readl(PCICFG_DATA) >> ((where & 3) * 8)) & 0xFF;
+ 		break;
+ 	case 2:
+-		*value = (PCICFG_DATA >> ((where & 2) * 8)) & 0xFFFF;
++		*value = (readl(PCICFG_DATA) >> ((where & 2) * 8)) & 0xFFFF;
+ 		break;
+ 	case 4:
+-		*value = PCICFG_DATA;
++		*value = readl(PCICFG_DATA);
+ 		break;
+ 	}
+ 	return PCIBIOS_SUCCESSFUL;
+@@ -49,18 +49,18 @@ static int
+ puv3_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+ 			int size, u32 value)
+ {
+-	PCICFG_ADDR = CONFIG_CMD(bus, devfn, where);
++	writel(CONFIG_CMD(bus, devfn, where), PCICFG_ADDR);
+ 	switch (size) {
+ 	case 1:
+-		PCICFG_DATA = (PCICFG_DATA & ~FMASK(8, (where&3)*8))
+-			| FIELD(value, 8, (where&3)*8);
++		writel((readl(PCICFG_DATA) & ~FMASK(8, (where&3)*8))
++			| FIELD(value, 8, (where&3)*8), PCICFG_DATA);
+ 		break;
+ 	case 2:
+-		PCICFG_DATA = (PCICFG_DATA & ~FMASK(16, (where&2)*8))
+-			| FIELD(value, 16, (where&2)*8);
++		writel((readl(PCICFG_DATA) & ~FMASK(16, (where&2)*8))
++			| FIELD(value, 16, (where&2)*8), PCICFG_DATA);
+ 		break;
+ 	case 4:
+-		PCICFG_DATA = value;
++		writel(value, PCICFG_DATA);
+ 		break;
+ 	}
+ 	return PCIBIOS_SUCCESSFUL;
+@@ -75,31 +75,31 @@ void pci_puv3_preinit(void)
+ {
+ 	printk(KERN_DEBUG "PCI: PKUnity PCI Controller Initializing ...\n");
+ 	/* config PCI bridge base */
+-	PCICFG_BRIBASE = PKUNITY_PCIBRI_BASE;
++	writel(PKUNITY_PCIBRI_BASE, PCICFG_BRIBASE);
+ 
+-	PCIBRI_AHBCTL0 = 0;
+-	PCIBRI_AHBBAR0 = PKUNITY_PCIBRI_BASE | PCIBRI_BARx_MEM;
+-	PCIBRI_AHBAMR0 = 0xFFFF0000;
+-	PCIBRI_AHBTAR0 = 0;
++	writel(0, PCIBRI_AHBCTL0);
++	writel(PKUNITY_PCIBRI_BASE | PCIBRI_BARx_MEM, PCIBRI_AHBBAR0);
++	writel(0xFFFF0000, PCIBRI_AHBAMR0);
++	writel(0, PCIBRI_AHBTAR0);
+ 
+-	PCIBRI_AHBCTL1 = PCIBRI_CTLx_AT;
+-	PCIBRI_AHBBAR1 = PKUNITY_PCILIO_BASE | PCIBRI_BARx_IO;
+-	PCIBRI_AHBAMR1 = 0xFFFF0000;
+-	PCIBRI_AHBTAR1 = 0x00000000;
++	writel(PCIBRI_CTLx_AT, PCIBRI_AHBCTL1);
++	writel(PKUNITY_PCILIO_BASE | PCIBRI_BARx_IO, PCIBRI_AHBBAR1);
++	writel(0xFFFF0000, PCIBRI_AHBAMR1);
++	writel(0x00000000, PCIBRI_AHBTAR1);
+ 
+-	PCIBRI_AHBCTL2 = PCIBRI_CTLx_PREF;
+-	PCIBRI_AHBBAR2 = PKUNITY_PCIMEM_BASE | PCIBRI_BARx_MEM;
+-	PCIBRI_AHBAMR2 = 0xF8000000;
+-	PCIBRI_AHBTAR2 = 0;
++	writel(PCIBRI_CTLx_PREF, PCIBRI_AHBCTL2);
++	writel(PKUNITY_PCIMEM_BASE | PCIBRI_BARx_MEM, PCIBRI_AHBBAR2);
++	writel(0xF8000000, PCIBRI_AHBAMR2);
++	writel(0, PCIBRI_AHBTAR2);
+ 
+-	PCIBRI_BAR1 = PKUNITY_PCIAHB_BASE | PCIBRI_BARx_MEM;
++	writel(PKUNITY_PCIAHB_BASE | PCIBRI_BARx_MEM, PCIBRI_BAR1);
+ 
+-	PCIBRI_PCICTL0 = PCIBRI_CTLx_AT | PCIBRI_CTLx_PREF;
+-	PCIBRI_PCIBAR0 = PKUNITY_PCIAHB_BASE | PCIBRI_BARx_MEM;
+-	PCIBRI_PCIAMR0 = 0xF8000000;
+-	PCIBRI_PCITAR0 = PKUNITY_SDRAM_BASE;
++	writel(PCIBRI_CTLx_AT | PCIBRI_CTLx_PREF, PCIBRI_PCICTL0);
++	writel(PKUNITY_PCIAHB_BASE | PCIBRI_BARx_MEM, PCIBRI_PCIBAR0);
++	writel(0xF8000000, PCIBRI_PCIAMR0);
++	writel(PKUNITY_SDRAM_BASE, PCIBRI_PCITAR0);
+ 
+-	PCIBRI_CMD = PCIBRI_CMD | PCIBRI_CMD_IO | PCIBRI_CMD_MEM;
++	writel(readl(PCIBRI_CMD) | PCIBRI_CMD_IO | PCIBRI_CMD_MEM, PCIBRI_CMD);
+ }
+ 
+ static int __init pci_puv3_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+diff --git a/arch/unicore32/kernel/process.c b/arch/unicore32/kernel/process.c
+index 8d4a273ae086..ba401df971ed 100644
+--- a/arch/unicore32/kernel/process.c
++++ b/arch/unicore32/kernel/process.c
+@@ -125,9 +125,9 @@ void machine_restart(char *cmd)
+ 		/* Jump into ROM at address 0xffff0000 */
+ 		cpu_reset(VECTORS_BASE);
+ 	} else {
+-		PM_PLLSYSCFG = 0x00002001; /* cpu clk = 250M */
+-		PM_PLLDDRCFG = 0x00100800; /* ddr clk =  44M */
+-		PM_PLLVGACFG = 0x00002001; /* vga clk = 250M */
++		writel(0x00002001, PM_PLLSYSCFG); /* cpu clk = 250M */
++		writel(0x00100800, PM_PLLDDRCFG); /* ddr clk =  44M */
++		writel(0x00002001, PM_PLLVGACFG); /* vga clk = 250M */
+ 
+ 		/* Use on-chip reset capability */
+ 		/* following instructions must be in one icache line */
+@@ -141,10 +141,10 @@ void machine_restart(char *cmd)
+ 			"	nop; nop; nop\n\t"
+ 			/* prefetch 3 instructions at most */
+ 			:
+-			: "r" ((unsigned long)&PM_PMCR),
++			: "r" (PM_PMCR),
+ 			  "r" (PM_PMCR_CFBSYS | PM_PMCR_CFBDDR
+ 				| PM_PMCR_CFBVGA),
+-			  "r" ((unsigned long)&RESETC_SWRR),
++			  "r" (RESETC_SWRR),
+ 			  "r" (RESETC_SWRR_SRB)
+ 			: "r0", "memory");
+ 	}
+diff --git a/arch/unicore32/kernel/puv3-core.c b/arch/unicore32/kernel/puv3-core.c
+index 26cc52b51e7b..6edf928a106c 100644
+--- a/arch/unicore32/kernel/puv3-core.c
++++ b/arch/unicore32/kernel/puv3-core.c
+@@ -36,7 +36,7 @@
+  */
+ unsigned long long sched_clock(void)
+ {
+-	unsigned long long v = cnt32_to_63(OST_OSCR);
++	unsigned long long v = cnt32_to_63(readl(OST_OSCR));
+ 
+ 	/* original conservative method, but overflow frequently
+ 	 * v *= NSEC_PER_SEC >> 12;
+@@ -187,15 +187,15 @@ static void puv3_cpu_pm_restore(unsigned long *sleep_save)
+ static int puv3_cpu_pm_prepare(void)
+ {
+ 	/* set resume return address */
+-	PM_DIVCFG = virt_to_phys(puv3_cpu_resume);
++	writel(virt_to_phys(puv3_cpu_resume), PM_DIVCFG);
+ 	return 0;
+ }
+ 
+ static void puv3_cpu_pm_enter(suspend_state_t state)
+ {
+ 	/* Clear reset status */
+-	RESETC_RSSR = RESETC_RSSR_HWR | RESETC_RSSR_WDR
+-			| RESETC_RSSR_SMR | RESETC_RSSR_SWR;
++	writel(RESETC_RSSR_HWR | RESETC_RSSR_WDR
++			| RESETC_RSSR_SMR | RESETC_RSSR_SWR, RESETC_RSSR);
+ 
+ 	switch (state) {
+ /*	case PM_SUSPEND_ON:
+@@ -242,7 +242,7 @@ void puv3_ps2_init(void)
+ 	struct clk *bclk32;
+ 
+ 	bclk32 = clk_get(NULL, "BUS32_CLK");
+-	PS2_CNT = clk_get_rate(bclk32) / 200000; /* should > 5us */
++	writel(clk_get_rate(bclk32) / 200000, PS2_CNT); /* should > 5us */
+ }
+ 
+ void __init puv3_core_init(void)
+diff --git a/arch/unicore32/kernel/rtc.c b/arch/unicore32/kernel/rtc.c
+index 5e4db4158589..c5f068295b51 100644
+--- a/arch/unicore32/kernel/rtc.c
++++ b/arch/unicore32/kernel/rtc.c
+@@ -41,7 +41,7 @@ static irqreturn_t puv3_rtc_alarmirq(int irq, void *id)
+ {
+ 	struct rtc_device *rdev = id;
+ 
+-	RTC_RTSR |= RTC_RTSR_AL;
++	writel(readl(RTC_RTSR) | RTC_RTSR_AL, RTC_RTSR);
+ 	rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF);
+ 	return IRQ_HANDLED;
+ }
+@@ -50,7 +50,7 @@ static irqreturn_t puv3_rtc_tickirq(int irq, void *id)
+ {
+ 	struct rtc_device *rdev = id;
+ 
+-	RTC_RTSR |= RTC_RTSR_HZ;
++	writel(readl(RTC_RTSR) | RTC_RTSR_HZ, RTC_RTSR);
+ 	rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF);
+ 	return IRQ_HANDLED;
+ }
+@@ -62,12 +62,12 @@ static void puv3_rtc_setaie(int to)
+ 
+ 	pr_debug("%s: aie=%d\n", __func__, to);
+ 
+-	tmp = RTC_RTSR & ~RTC_RTSR_ALE;
++	tmp = readl(RTC_RTSR) & ~RTC_RTSR_ALE;
+ 
+ 	if (to)
+ 		tmp |= RTC_RTSR_ALE;
+ 
+-	RTC_RTSR = tmp;
++	writel(tmp, RTC_RTSR);
+ }
+ 
+ static int puv3_rtc_setpie(struct device *dev, int enabled)
+@@ -77,12 +77,12 @@ static int puv3_rtc_setpie(struct device *dev, int enabled)
+ 	pr_debug("%s: pie=%d\n", __func__, enabled);
+ 
+ 	spin_lock_irq(&puv3_rtc_pie_lock);
+-	tmp = RTC_RTSR & ~RTC_RTSR_HZE;
++	tmp = readl(RTC_RTSR) & ~RTC_RTSR_HZE;
+ 
+ 	if (enabled)
+ 		tmp |= RTC_RTSR_HZE;
+ 
+-	RTC_RTSR = tmp;
++	writel(tmp, RTC_RTSR);
+ 	spin_unlock_irq(&puv3_rtc_pie_lock);
+ 
+ 	return 0;
+@@ -97,7 +97,7 @@ static int puv3_rtc_setfreq(struct device *dev, int freq)
+ 
+ static int puv3_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
+ {
+-	rtc_time_to_tm(RTC_RCNR, rtc_tm);
++	rtc_time_to_tm(readl(RTC_RCNR), rtc_tm);
+ 
+ 	pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n",
+ 		 rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
+@@ -115,7 +115,7 @@ static int puv3_rtc_settime(struct device *dev, struct rtc_time *tm)
+ 		 tm->tm_hour, tm->tm_min, tm->tm_sec);
+ 
+ 	rtc_tm_to_time(tm, &rtc_count);
+-	RTC_RCNR = rtc_count;
++	writel(rtc_count, RTC_RCNR);
+ 
+ 	return 0;
+ }
+@@ -124,9 +124,9 @@ static int puv3_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
+ {
+ 	struct rtc_time *alm_tm = &alrm->time;
+ 
+-	rtc_time_to_tm(RTC_RTAR, alm_tm);
++	rtc_time_to_tm(readl(RTC_RTAR), alm_tm);
+ 
+-	alrm->enabled = RTC_RTSR & RTC_RTSR_ALE;
++	alrm->enabled = readl(RTC_RTSR) & RTC_RTSR_ALE;
+ 
+ 	pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n",
+ 		 alrm->enabled,
+@@ -147,7 +147,7 @@ static int puv3_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+ 		 tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec);
+ 
+ 	rtc_tm_to_time(tm, &rtcalarm_count);
+-	RTC_RTAR = rtcalarm_count;
++	writel(rtcalarm_count, RTC_RTAR);
+ 
+ 	puv3_rtc_setaie(alrm->enabled);
+ 
+@@ -162,7 +162,7 @@ static int puv3_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+ static int puv3_rtc_proc(struct device *dev, struct seq_file *seq)
+ {
+ 	seq_printf(seq, "periodic_IRQ\t: %s\n",
+-		     (RTC_RTSR & RTC_RTSR_HZE) ? "yes" : "no");
++		     (readl(RTC_RTSR) & RTC_RTSR_HZE) ? "yes" : "no");
+ 	return 0;
+ }
+ 
+@@ -222,13 +222,13 @@ static const struct rtc_class_ops puv3_rtcops = {
+ static void puv3_rtc_enable(struct platform_device *pdev, int en)
+ {
+ 	if (!en) {
+-		RTC_RTSR &= ~RTC_RTSR_HZE;
++		writel(readl(RTC_RTSR) & ~RTC_RTSR_HZE, RTC_RTSR);
+ 	} else {
+ 		/* re-enable the device, and check it is ok */
+ 
+-		if ((RTC_RTSR & RTC_RTSR_HZE) == 0) {
++		if ((readl(RTC_RTSR) & RTC_RTSR_HZE) == 0) {
+ 			dev_info(&pdev->dev, "rtc disabled, re-enabling\n");
+-			RTC_RTSR |= RTC_RTSR_HZE;
++			writel(readl(RTC_RTSR) | RTC_RTSR_HZE, RTC_RTSR);
+ 		}
+ 	}
+ }
+@@ -331,7 +331,7 @@ static int ticnt_save;
+ static int puv3_rtc_suspend(struct platform_device *pdev, pm_message_t state)
+ {
+ 	/* save RTAR for anyone using periodic interrupts */
+-	ticnt_save = RTC_RTAR;
++	ticnt_save = readl(RTC_RTAR);
+ 	puv3_rtc_enable(pdev, 0);
+ 	return 0;
+ }
+@@ -339,7 +339,7 @@ static int puv3_rtc_suspend(struct platform_device *pdev, pm_message_t state)
+ static int puv3_rtc_resume(struct platform_device *pdev)
+ {
+ 	puv3_rtc_enable(pdev, 1);
+-	RTC_RTAR = ticnt_save;
++	writel(ticnt_save, RTC_RTAR);
+ 	return 0;
+ }
+ #else
+diff --git a/arch/unicore32/kernel/time.c b/arch/unicore32/kernel/time.c
+index 8bb4b815bce9..080710c09241 100644
+--- a/arch/unicore32/kernel/time.c
++++ b/arch/unicore32/kernel/time.c
+@@ -26,8 +26,8 @@ static irqreturn_t puv3_ost0_interrupt(int irq, void *dev_id)
+ 	struct clock_event_device *c = dev_id;
+ 
+ 	/* Disarm the compare/match, signal the event. */
+-	OST_OIER &= ~OST_OIER_E0;
+-	OST_OSSR &= ~OST_OSSR_M0;
++	writel(readl(OST_OIER) & ~OST_OIER_E0, OST_OIER);
++	writel(readl(OST_OSSR) & ~OST_OSSR_M0, OST_OSSR);
+ 	c->event_handler(c);
+ 
+ 	return IRQ_HANDLED;
+@@ -38,10 +38,10 @@ puv3_osmr0_set_next_event(unsigned long delta, struct clock_event_device *c)
+ {
+ 	unsigned long next, oscr;
+ 
+-	OST_OIER |= OST_OIER_E0;
+-	next = OST_OSCR + delta;
+-	OST_OSMR0 = next;
+-	oscr = OST_OSCR;
++	writel(readl(OST_OIER) | OST_OIER_E0, OST_OIER);
++	next = readl(OST_OSCR) + delta;
++	writel(next, OST_OSMR0);
++	oscr = readl(OST_OSCR);
+ 
+ 	return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0;
+ }
+@@ -53,8 +53,8 @@ puv3_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *c)
+ 	case CLOCK_EVT_MODE_ONESHOT:
+ 	case CLOCK_EVT_MODE_UNUSED:
+ 	case CLOCK_EVT_MODE_SHUTDOWN:
+-		OST_OIER &= ~OST_OIER_E0;
+-		OST_OSSR &= ~OST_OSSR_M0;
++		writel(readl(OST_OIER) & ~OST_OIER_E0, OST_OIER);
++		writel(readl(OST_OSSR) & ~OST_OSSR_M0, OST_OSSR);
+ 		break;
+ 
+ 	case CLOCK_EVT_MODE_RESUME:
+@@ -73,7 +73,7 @@ static struct clock_event_device ckevt_puv3_osmr0 = {
+ 
+ static cycle_t puv3_read_oscr(struct clocksource *cs)
+ {
+-	return OST_OSCR;
++	return readl(OST_OSCR);
+ }
+ 
+ static struct clocksource cksrc_puv3_oscr = {
+@@ -93,8 +93,8 @@ static struct irqaction puv3_timer_irq = {
+ 
+ void __init time_init(void)
+ {
+-	OST_OIER = 0;		/* disable any timer interrupts */
+-	OST_OSSR = 0;		/* clear status on all timers */
++	writel(0, OST_OIER);		/* disable any timer interrupts */
++	writel(0, OST_OSSR);		/* clear status on all timers */
+ 
+ 	clockevents_calc_mult_shift(&ckevt_puv3_osmr0, CLOCK_TICK_RATE, 5);
+ 
+@@ -115,26 +115,26 @@ unsigned long osmr[4], oier;
+ 
+ void puv3_timer_suspend(void)
+ {
+-	osmr[0] = OST_OSMR0;
+-	osmr[1] = OST_OSMR1;
+-	osmr[2] = OST_OSMR2;
+-	osmr[3] = OST_OSMR3;
+-	oier = OST_OIER;
++	osmr[0] = readl(OST_OSMR0);
++	osmr[1] = readl(OST_OSMR1);
++	osmr[2] = readl(OST_OSMR2);
++	osmr[3] = readl(OST_OSMR3);
++	oier = readl(OST_OIER);
+ }
+ 
+ void puv3_timer_resume(void)
+ {
+-	OST_OSSR = 0;
+-	OST_OSMR0 = osmr[0];
+-	OST_OSMR1 = osmr[1];
+-	OST_OSMR2 = osmr[2];
+-	OST_OSMR3 = osmr[3];
+-	OST_OIER = oier;
++	writel(0, OST_OSSR);
++	writel(osmr[0], OST_OSMR0);
++	writel(osmr[1], OST_OSMR1);
++	writel(osmr[2], OST_OSMR2);
++	writel(osmr[3], OST_OSMR3);
++	writel(oier, OST_OIER);
+ 
+ 	/*
+ 	 * OSMR0 is the system timer: make sure OSCR is sufficiently behind
+ 	 */
+-	OST_OSCR = OST_OSMR0 - LATCH;
++	writel(readl(OST_OSMR0) - LATCH, OST_OSCR);
+ }
+ #else
+ void puv3_timer_suspend(void) { };
+diff --git a/drivers/input/serio/i8042-unicore32io.h b/drivers/input/serio/i8042-unicore32io.h
+index 620b040b81b0..73f5cc124a36 100644
+--- a/drivers/input/serio/i8042-unicore32io.h
++++ b/drivers/input/serio/i8042-unicore32io.h
+@@ -29,11 +29,11 @@
+ /*
+  * Register numbers.
+  */
+-#define I8042_COMMAND_REG	((volatile void __iomem *)&PS2_COMMAND)
+-#define I8042_STATUS_REG	((volatile void __iomem *)&PS2_STATUS)
+-#define I8042_DATA_REG		((volatile void __iomem *)&PS2_DATA)
++#define I8042_COMMAND_REG	PS2_COMMAND
++#define I8042_STATUS_REG	PS2_STATUS
++#define I8042_DATA_REG		PS2_DATA
+ 
+-#define I8042_REGION_START	(resource_size_t)(&PS2_DATA)
++#define I8042_REGION_START	(resource_size_t)(PS2_DATA)
+ #define I8042_REGION_SIZE	(resource_size_t)(16)
+ 
+ static inline int i8042_read_data(void)

commit 4517366d870b89d6fb8c0c90deb6c73d975908af
+Author: GuanXuetao 
+Date:   Fri Feb 25 17:58:00 2011 +0800
+
+    unicore32 i8042 upgrade and bugfix: adjust resource request region type
+    
+    Signed-off-by: Guan Xuetao 
+
+diff --git a/drivers/input/serio/i8042-unicore32io.h b/drivers/input/serio/i8042-unicore32io.h
+index 2cdd8726446f..620b040b81b0 100644
+--- a/drivers/input/serio/i8042-unicore32io.h
++++ b/drivers/input/serio/i8042-unicore32io.h
+@@ -58,7 +58,7 @@ static inline void i8042_write_command(int val)
+ 
+ static inline int i8042_platform_init(void)
+ {
+-	if (!request_region(I8042_REGION_START, I8042_REGION_SIZE, "i8042"))
++	if (!request_mem_region(I8042_REGION_START, I8042_REGION_SIZE, "i8042"))
+ 		return -EBUSY;
+ 
+ 	i8042_reset = 1;
+@@ -67,7 +67,7 @@ static inline int i8042_platform_init(void)
+ 
+ static inline void i8042_platform_exit(void)
+ {
+-	release_region(I8042_REGION_START, I8042_REGION_SIZE);
++	release_mem_region(I8042_REGION_START, I8042_REGION_SIZE);
+ }
+ 
+ #endif /* _I8042_UNICORE32_H */

commit 4ef2ec63cc5117d099960c49910533e467942e27
+Author: GuanXuetao 
+Date:   Tue Feb 22 17:34:47 2011 +0800
+
+    unicore32 upgrade to v2.6.38-rc5: add one more paramter for pte_alloc_map call
+    
+    Signed-off-by: Guan Xuetao 
+
+diff --git a/arch/unicore32/mm/pgd.c b/arch/unicore32/mm/pgd.c
+index 632cef7cd378..08b8d4295e70 100644
+--- a/arch/unicore32/mm/pgd.c
++++ b/arch/unicore32/mm/pgd.c
+@@ -54,7 +54,7 @@ pgd_t *get_pgd_slow(struct mm_struct *mm)
+ 		if (!new_pmd)
+ 			goto no_pmd;
+ 
+-		new_pte = pte_alloc_map(mm, new_pmd, 0);
++		new_pte = pte_alloc_map(mm, NULL, new_pmd, 0);
+ 		if (!new_pte)
+ 			goto no_pte;
+ 

commit 3838b82c0a6806daf820acacf02cd9aefe9df7b8
+Author: GuanXuetao 
+Date:   Fri Feb 18 18:38:33 2011 +0800
+
+    unicore32 i8042: adjust io funcs of i8042-unicore32io.h
+    
+    replace inb/outb with readb/writeb in i8042-unicore32io.h
+    and correct typecasting of register and region macros
+      -- by advice with Arnd Bergmann
+    
+    Signed-off-by: Guan Xuetao 
+
+diff --git a/drivers/input/serio/i8042-unicore32io.h b/drivers/input/serio/i8042-unicore32io.h
+index 6a7e8b3ce61a..2cdd8726446f 100644
+--- a/drivers/input/serio/i8042-unicore32io.h
++++ b/drivers/input/serio/i8042-unicore32io.h
+@@ -29,33 +29,36 @@
+ /*
+  * Register numbers.
+  */
+-#define I8042_COMMAND_REG	((unsigned long)&PS2_COMMAND)
+-#define I8042_STATUS_REG	((unsigned long)&PS2_STATUS)
+-#define I8042_DATA_REG		((unsigned long)&PS2_DATA)
++#define I8042_COMMAND_REG	((volatile void __iomem *)&PS2_COMMAND)
++#define I8042_STATUS_REG	((volatile void __iomem *)&PS2_STATUS)
++#define I8042_DATA_REG		((volatile void __iomem *)&PS2_DATA)
++
++#define I8042_REGION_START	(resource_size_t)(&PS2_DATA)
++#define I8042_REGION_SIZE	(resource_size_t)(16)
+ 
+ static inline int i8042_read_data(void)
+ {
+-	return inb(I8042_DATA_REG);
++	return readb(I8042_DATA_REG);
+ }
+ 
+ static inline int i8042_read_status(void)
+ {
+-	return inb(I8042_STATUS_REG);
++	return readb(I8042_STATUS_REG);
+ }
+ 
+ static inline void i8042_write_data(int val)
+ {
+-	outb(val, I8042_DATA_REG);
++	writeb(val, I8042_DATA_REG);
+ }
+ 
+ static inline void i8042_write_command(int val)
+ {
+-	outb(val, I8042_COMMAND_REG);
++	writeb(val, I8042_COMMAND_REG);
+ }
+ 
+ static inline int i8042_platform_init(void)
+ {
+-	if (!request_region(I8042_DATA_REG, 16, "i8042"))
++	if (!request_region(I8042_REGION_START, I8042_REGION_SIZE, "i8042"))
+ 		return -EBUSY;
+ 
+ 	i8042_reset = 1;
+@@ -64,7 +67,7 @@ static inline int i8042_platform_init(void)
+ 
+ static inline void i8042_platform_exit(void)
+ {
+-	release_region(I8042_DATA_REG, 16);
++	release_region(I8042_REGION_START, I8042_REGION_SIZE);
+ }
+ 
+ #endif /* _I8042_UNICORE32_H */

commit bd42aa75b4231b5fd3742de4c4b84ad590a7d654
+Author: GuanXuetao 
+Date:   Sat Feb 26 20:49:47 2011 +0800
+
+    unicore32: rename PKUNITY_IOSPACE_BASE to PKUNITY_MMIO_BASE
+    
+    for the term IOSPACE normally refers to the PCI PIO space
+      -- by advice with Arnd Bergmann
+    
+    Signed-off-by: Guan Xuetao 
+
+diff --git a/arch/unicore32/include/mach/PKUnity.h b/arch/unicore32/include/mach/PKUnity.h
+index fa11eba0afd6..940e9ed0941c 100644
+--- a/arch/unicore32/include/mach/PKUnity.h
++++ b/arch/unicore32/include/mach/PKUnity.h
+@@ -21,7 +21,7 @@
+  * Memory Definitions
+  */
+ #define PKUNITY_SDRAM_BASE		0x00000000 /* 0x00000000 - 0x7FFFFFFF 2GB */
+-#define PKUNITY_IOSPACE_BASE            0x80000000 /* 0x80000000 - 0xFFFFFFFF 2GB */
++#define PKUNITY_MMIO_BASE		0x80000000 /* 0x80000000 - 0xFFFFFFFF 2GB */
+ #define PKUNITY_PCI_BASE		0x80000000 /* 0x80000000 - 0xBFFFFFFF 1GB */
+ #include "regs-pci.h"
+ #define PKUNITY_BOOT_ROM2_BASE		0xF4000000 /* 0xF4000000 - 0xF7FFFFFF 64MB */
+diff --git a/arch/unicore32/include/mach/hardware.h b/arch/unicore32/include/mach/hardware.h
+index 3fb7236f8d69..c7d3dd6b4eff 100644
+--- a/arch/unicore32/include/mach/hardware.h
++++ b/arch/unicore32/include/mach/hardware.h
+@@ -17,8 +17,8 @@
+ 
+ #include "PKUnity.h"
+ 
+-#define io_p2v(x)	((x) - PKUNITY_IOSPACE_BASE)
+-#define io_v2p(x)	((x) + PKUNITY_IOSPACE_BASE)
++#define io_p2v(x)	((x) - PKUNITY_MMIO_BASE)
++#define io_v2p(x)	((x) + PKUNITY_MMIO_BASE)
+ 
+ #ifndef __ASSEMBLY__
+ 

commit 36a8b8c399480b5388ddd198ead78c9dd0e50df0
+Author: GuanXuetao 
+Date:   Thu Feb 17 19:15:36 2011 +0800
+
+    unicore32: modify function names and parameters for irq_chips
+    
+      -- by advice with Thomas Gleixner
+    
+    Signed-off-by: Guan Xuetao 
+
+diff --git a/arch/unicore32/Kconfig b/arch/unicore32/Kconfig
+index 90835c959476..7f65018e64ac 100644
+--- a/arch/unicore32/Kconfig
++++ b/arch/unicore32/Kconfig
+@@ -10,6 +10,7 @@ config UNICORE32
+ 	select HAVE_KERNEL_LZMA
+ 	select GENERIC_FIND_FIRST_BIT
+ 	select GENERIC_IRQ_PROBE
++	select GENERIC_HARDIRQS_NO_DEPRECATED
+ 	select ARCH_WANT_FRAME_POINTERS
+ 	help
+ 	  UniCore-32 is 32-bit Instruction Set Architecture,
+diff --git a/arch/unicore32/kernel/irq.c b/arch/unicore32/kernel/irq.c
+index 7c211f597833..38e30897dea3 100644
+--- a/arch/unicore32/kernel/irq.c
++++ b/arch/unicore32/kernel/irq.c
+@@ -42,14 +42,14 @@ static int GPIO_IRQ_mask = 0;
+ 
+ #define GPIO_MASK(irq)		(1 << (irq - IRQ_GPIO0))
+ 
+-static int puv3_gpio_type(unsigned int irq, unsigned int type)
++static int puv3_gpio_type(struct irq_data *d, unsigned int type)
+ {
+ 	unsigned int mask;
+ 
+-	if (irq < IRQ_GPIOHIGH)
+-		mask = 1 << irq;
++	if (d->irq < IRQ_GPIOHIGH)
++		mask = 1 << d->irq;
+ 	else
+-		mask = GPIO_MASK(irq);
++		mask = GPIO_MASK(d->irq);
+ 
+ 	if (type == IRQ_TYPE_PROBE) {
+ 		if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask)
+@@ -75,37 +75,37 @@ static int puv3_gpio_type(unsigned int irq, unsigned int type)
+ /*
+  * GPIO IRQs must be acknowledged.  This is for IRQs from 0 to 7.
+  */
+-static void puv3_low_gpio_ack(unsigned int irq)
++static void puv3_low_gpio_ack(struct irq_data *d)
+ {
+-	GPIO_GEDR = (1 << irq);
++	GPIO_GEDR = (1 << d->irq);
+ }
+ 
+-static void puv3_low_gpio_mask(unsigned int irq)
++static void puv3_low_gpio_mask(struct irq_data *d)
+ {
+-	INTC_ICMR &= ~(1 << irq);
++	INTC_ICMR &= ~(1 << d->irq);
+ }
+ 
+-static void puv3_low_gpio_unmask(unsigned int irq)
++static void puv3_low_gpio_unmask(struct irq_data *d)
+ {
+-	INTC_ICMR |= 1 << irq;
++	INTC_ICMR |= 1 << d->irq;
+ }
+ 
+-static int puv3_low_gpio_wake(unsigned int irq, unsigned int on)
++static int puv3_low_gpio_wake(struct irq_data *d, unsigned int on)
+ {
+ 	if (on)
+-		PM_PWER |= 1 << irq;
++		PM_PWER |= 1 << d->irq;
+ 	else
+-		PM_PWER &= ~(1 << irq);
++		PM_PWER &= ~(1 << d->irq);
+ 	return 0;
+ }
+ 
+ static struct irq_chip puv3_low_gpio_chip = {
+ 	.name		= "GPIO-low",
+-	.ack		= puv3_low_gpio_ack,
+-	.mask		= puv3_low_gpio_mask,
+-	.unmask		= puv3_low_gpio_unmask,
+-	.set_type	= puv3_gpio_type,
+-	.set_wake	= puv3_low_gpio_wake,
++	.irq_ack	= puv3_low_gpio_ack,
++	.irq_mask	= puv3_low_gpio_mask,
++	.irq_unmask	= puv3_low_gpio_unmask,
++	.irq_set_type	= puv3_gpio_type,
++	.irq_set_wake	= puv3_low_gpio_wake,
+ };
+ 
+ /*
+@@ -142,16 +142,16 @@ puv3_gpio_handler(unsigned int irq, struct irq_desc *desc)
+  * In addition, the IRQs are all collected up into one bit in the
+  * interrupt controller registers.
+  */
+-static void puv3_high_gpio_ack(unsigned int irq)
++static void puv3_high_gpio_ack(struct irq_data *d)
+ {
+-	unsigned int mask = GPIO_MASK(irq);
++	unsigned int mask = GPIO_MASK(d->irq);
+ 
+ 	GPIO_GEDR = mask;
+ }
+ 
+-static void puv3_high_gpio_mask(unsigned int irq)
++static void puv3_high_gpio_mask(struct irq_data *d)
+ {
+-	unsigned int mask = GPIO_MASK(irq);
++	unsigned int mask = GPIO_MASK(d->irq);
+ 
+ 	GPIO_IRQ_mask &= ~mask;
+ 
+@@ -159,9 +159,9 @@ static void puv3_high_gpio_mask(unsigned int irq)
+ 	GPIO_GFER &= ~mask;
+ }
+ 
+-static void puv3_high_gpio_unmask(unsigned int irq)
++static void puv3_high_gpio_unmask(struct irq_data *d)
+ {
+-	unsigned int mask = GPIO_MASK(irq);
++	unsigned int mask = GPIO_MASK(d->irq);
+ 
+ 	GPIO_IRQ_mask |= mask;
+ 
+@@ -169,7 +169,7 @@ static void puv3_high_gpio_unmask(unsigned int irq)
+ 	GPIO_GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
+ }
+ 
+-static int puv3_high_gpio_wake(unsigned int irq, unsigned int on)
++static int puv3_high_gpio_wake(struct irq_data *d, unsigned int on)
+ {
+ 	if (on)
+ 		PM_PWER |= PM_PWER_GPIOHIGH;
+@@ -180,33 +180,33 @@ static int puv3_high_gpio_wake(unsigned int irq, unsigned int on)
+ 
+ static struct irq_chip puv3_high_gpio_chip = {
+ 	.name		= "GPIO-high",
+-	.ack		= puv3_high_gpio_ack,
+-	.mask		= puv3_high_gpio_mask,
+-	.unmask		= puv3_high_gpio_unmask,
+-	.set_type	= puv3_gpio_type,
+-	.set_wake	= puv3_high_gpio_wake,
++	.irq_ack	= puv3_high_gpio_ack,
++	.irq_mask	= puv3_high_gpio_mask,
++	.irq_unmask	= puv3_high_gpio_unmask,
++	.irq_set_type	= puv3_gpio_type,
++	.irq_set_wake	= puv3_high_gpio_wake,
+ };
+ 
+ /*
+  * We don't need to ACK IRQs on the PKUnity unless they're GPIOs
+  * this is for internal IRQs i.e. from 8 to 31.
+  */
+-static void puv3_mask_irq(unsigned int irq)
++static void puv3_mask_irq(struct irq_data *d)
+ {
+-	INTC_ICMR &= ~(1 << irq);
++	INTC_ICMR &= ~(1 << d->irq);
+ }
+ 
+-static void puv3_unmask_irq(unsigned int irq)
++static void puv3_unmask_irq(struct irq_data *d)
+ {
+-	INTC_ICMR |= (1 << irq);
++	INTC_ICMR |= (1 << d->irq);
+ }
+ 
+ /*
+  * Apart form GPIOs, only the RTC alarm can be a wakeup event.
+  */
+-static int puv3_set_wake(unsigned int irq, unsigned int on)
++static int puv3_set_wake(struct irq_data *d, unsigned int on)
+ {
+-	if (irq == IRQ_RTCAlarm) {
++	if (d->irq == IRQ_RTCAlarm) {
+ 		if (on)
+ 			PM_PWER |= PM_PWER_RTC;
+ 		else
+@@ -218,10 +218,10 @@ static int puv3_set_wake(unsigned int irq, unsigned int on)
+ 
+ static struct irq_chip puv3_normal_chip = {
+ 	.name		= "PKUnity-v3",
+-	.ack		= puv3_mask_irq,
+-	.mask		= puv3_mask_irq,
+-	.unmask		= puv3_unmask_irq,
+-	.set_wake	= puv3_set_wake,
++	.irq_ack	= puv3_mask_irq,
++	.irq_mask	= puv3_mask_irq,
++	.irq_unmask	= puv3_unmask_irq,
++	.irq_set_wake	= puv3_set_wake,
+ };
+ 
+ static struct resource irq_resource = {
+@@ -383,7 +383,7 @@ int show_interrupts(struct seq_file *p, void *v)
+ 		seq_printf(p, "%3d: ", i);
+ 		for_each_present_cpu(cpu)
+ 			seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
+-		seq_printf(p, " %10s", desc->chip->name ? : "-");
++		seq_printf(p, " %10s", desc->irq_data.chip->name ? : "-");
+ 		seq_printf(p, "  %s", action->name);
+ 		for (action = action->next; action; action = action->next)
+ 			seq_printf(p, ", %s", action->name);

commit 3ab457cadd15bb388b200813222af1d5fb71c9d6
+Author: GuanXuetao 
+Date:   Thu Feb 17 19:06:59 2011 +0800
+
+    unicore32: remove unused lines in arch/unicore32/include/asm/irq.h
+    
+    Signed-off-by: Guan Xuetao 
+
+diff --git a/arch/unicore32/include/asm/irq.h b/arch/unicore32/include/asm/irq.h
+index ade8bb87111d..baea93e2a6e6 100644
+--- a/arch/unicore32/include/asm/irq.h
++++ b/arch/unicore32/include/asm/irq.h
+@@ -95,9 +95,7 @@
+ #define IRQ_SD_CD               IRQ_GPIO6 /* falling or rising trigger */
+ 
+ #ifndef __ASSEMBLY__
+-struct irqaction;
+ struct pt_regs;
+-extern void migrate_irqs(void);
+ 
+ extern void asm_do_IRQ(unsigned int, struct pt_regs *);
+ 

commit a913a8234bb812d21bb0f75c2458f9eb941ddf91
+Author: GuanXuetao 
+Date:   Thu Feb 17 17:50:43 2011 +0800
+
+    unicore32 time.c: change calculate method for clock_event_device
+    
+    apply clockevents_calc_mult_shift() to get rid of
+    shift assignment and mult calculation for osmr0
+      -- by advice with Thomas Gleixner
+    
+    Signed-off-by: Guan Xuetao 
+
+diff --git a/arch/unicore32/kernel/time.c b/arch/unicore32/kernel/time.c
+index 8090d763a606..8bb4b815bce9 100644
+--- a/arch/unicore32/kernel/time.c
++++ b/arch/unicore32/kernel/time.c
+@@ -66,11 +66,6 @@ puv3_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *c)
+ static struct clock_event_device ckevt_puv3_osmr0 = {
+ 	.name		= "osmr0",
+ 	.features	= CLOCK_EVT_FEAT_ONESHOT,
+-#ifdef CONFIG_ARCH_FPGA
+-	.shift		= 18, /* correct shift val: 16, but warn_on_slowpath */
+-#else
+-	.shift          = 30,
+-#endif
+ 	.rating		= 200,
+ 	.set_next_event	= puv3_osmr0_set_next_event,
+ 	.set_mode	= puv3_osmr0_set_mode,
+@@ -101,8 +96,8 @@ void __init time_init(void)
+ 	OST_OIER = 0;		/* disable any timer interrupts */
+ 	OST_OSSR = 0;		/* clear status on all timers */
+ 
+-	ckevt_puv3_osmr0.mult =
+-		div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt_puv3_osmr0.shift);
++	clockevents_calc_mult_shift(&ckevt_puv3_osmr0, CLOCK_TICK_RATE, 5);
++
+ 	ckevt_puv3_osmr0.max_delta_ns =
+ 		clockevent_delta2ns(0x7fffffff, &ckevt_puv3_osmr0);
+ 	ckevt_puv3_osmr0.min_delta_ns =

commit b31d82737d068bf7ff8ed4592914c8fd7fdb51f0
+Author: GuanXuetao 
+Date:   Sun Jan 16 00:35:49 2011 +0800
+
+    unicore32: ADD MAINTAINER for unicore32 architecture
+    
+    Add MAINTAINER list for unicore32 architecture and pkunity soc drivers.
+    
+    Signed-off-by: Guan Xuetao 
+    Acked-by: Arnd Bergmann 
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index f1bc3dc6b369..e8b15bfec6d6 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -4895,6 +4895,13 @@ S:	Maintained
+ F:	drivers/block/pktcdvd.c
+ F:	include/linux/pktcdvd.h
+ 
++PKUNITY SOC DRIVERS
++M:	Guan Xuetao 
++W:	http://mprc.pku.edu.cn/~guanxuetao/linux
++S:	Maintained
++T:	git git://git.kernel.org/pub/scm/linux/kernel/git/epip/linux-2.6-unicore32.git
++F:	drivers/input/serio/i8042-unicore32io.h
++
+ PMC SIERRA MaxRAID DRIVER
+ M:	Anil Ravindranath 
+ L:	linux-scsi@vger.kernel.org
+@@ -6259,6 +6266,13 @@ F:	drivers/uwb/
+ F:	include/linux/uwb.h
+ F:	include/linux/uwb/
+ 
++UNICORE32 ARCHITECTURE:
++M:	Guan Xuetao 
++W:	http://mprc.pku.edu.cn/~guanxuetao/linux
++S:	Maintained
++T:	git git://git.kernel.org/pub/scm/linux/kernel/git/epip/linux-2.6-unicore32.git
++F:	arch/unicore32/
++
+ UNIFDEF
+ M:	Tony Finch 
+ W:	http://dotat.at/prog/unifdef

commit 425ad52b86d9710719b3aa811d6cab56b3852981
+Author: GuanXuetao 
+Date:   Sat Jan 15 18:28:19 2011 +0800
+
+    unicore32 machine related files: ps2 driver
+    
+    This patch implements arch-specific ps2 driver.
+    
+    By reviewed with Dmitry Torokhov:
+         1. move i8042-ucio.h to drivers/input/serio/i8042-unicore32io.h
+         2. move puv3_ps2_init() to arch/unicore32/kernel/puv3-core.c
+         3. remove unused comments.
+    
+    Signed-off-by: Guan Xuetao 
+    Acked-by: Dmitry Torokhov 
+
+diff --git a/drivers/input/serio/i8042-unicore32io.h b/drivers/input/serio/i8042-unicore32io.h
+new file mode 100644
+index 000000000000..6a7e8b3ce61a
+--- /dev/null
++++ b/drivers/input/serio/i8042-unicore32io.h
+@@ -0,0 +1,70 @@
++/*
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ *	Maintained by GUAN Xue-tao 
++ *	Copyright (C) 2001-2011 Guan Xuetao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef _I8042_UNICORE32_H
++#define _I8042_UNICORE32_H
++
++#include 
++
++/*
++ * Names.
++ */
++#define I8042_KBD_PHYS_DESC "isa0060/serio0"
++#define I8042_AUX_PHYS_DESC "isa0060/serio1"
++#define I8042_MUX_PHYS_DESC "isa0060/serio%d"
++
++/*
++ * IRQs.
++ */
++#define I8042_KBD_IRQ           IRQ_PS2_KBD
++#define I8042_AUX_IRQ           IRQ_PS2_AUX
++
++/*
++ * Register numbers.
++ */
++#define I8042_COMMAND_REG	((unsigned long)&PS2_COMMAND)
++#define I8042_STATUS_REG	((unsigned long)&PS2_STATUS)
++#define I8042_DATA_REG		((unsigned long)&PS2_DATA)
++
++static inline int i8042_read_data(void)
++{
++	return inb(I8042_DATA_REG);
++}
++
++static inline int i8042_read_status(void)
++{
++	return inb(I8042_STATUS_REG);
++}
++
++static inline void i8042_write_data(int val)
++{
++	outb(val, I8042_DATA_REG);
++}
++
++static inline void i8042_write_command(int val)
++{
++	outb(val, I8042_COMMAND_REG);
++}
++
++static inline int i8042_platform_init(void)
++{
++	if (!request_region(I8042_DATA_REG, 16, "i8042"))
++		return -EBUSY;
++
++	i8042_reset = 1;
++	return 0;
++}
++
++static inline void i8042_platform_exit(void)
++{
++	release_region(I8042_DATA_REG, 16);
++}
++
++#endif /* _I8042_UNICORE32_H */
+diff --git a/drivers/input/serio/i8042.h b/drivers/input/serio/i8042.h
+index ac1d759d0f55..3452708fbe3b 100644
+--- a/drivers/input/serio/i8042.h
++++ b/drivers/input/serio/i8042.h
+@@ -26,6 +26,8 @@
+ #include "i8042-sparcio.h"
+ #elif defined(CONFIG_X86) || defined(CONFIG_IA64)
+ #include "i8042-x86ia64io.h"
++#elif defined(CONFIG_UNICORE32)
++#include "i8042-unicore32io.h"
+ #else
+ #include "i8042-io.h"
+ #endif

commit 700598cef866011b878f389c30414d31fa5bb87b
+Author: GuanXuetao 
+Date:   Sat Jan 15 18:25:14 2011 +0800
+
+    unicore32 machine related files: pci bus handling
+    
+    This patch implements arch-specific pci bus driver.
+    
+    Signed-off-by: Guan Xuetao 
+
+diff --git a/arch/unicore32/include/asm/pci.h b/arch/unicore32/include/asm/pci.h
+new file mode 100644
+index 000000000000..c5b28b459535
+--- /dev/null
++++ b/arch/unicore32/include/asm/pci.h
+@@ -0,0 +1,46 @@
++/*
++ * linux/arch/unicore32/include/asm/pci.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_PCI_H__
++#define __UNICORE_PCI_H__
++
++#ifdef __KERNEL__
++#include 
++#include 
++#include  /* for PCIBIOS_MIN_* */
++
++static inline void pcibios_set_master(struct pci_dev *dev)
++{
++	/* No special bus mastering setup handling */
++}
++
++static inline void pcibios_penalize_isa_irq(int irq, int active)
++{
++	/* We don't do dynamic PCI IRQ allocation */
++}
++
++#ifdef CONFIG_PCI
++static inline void pci_dma_burst_advice(struct pci_dev *pdev,
++					enum pci_dma_burst_strategy *strat,
++					unsigned long *strategy_parameter)
++{
++	*strat = PCI_DMA_BURST_INFINITY;
++	*strategy_parameter = ~0UL;
++}
++#endif
++
++#define HAVE_PCI_MMAP
++extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
++	enum pci_mmap_state mmap_state, int write_combine);
++
++#endif /* __KERNEL__ */
++
++#endif
+diff --git a/arch/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c
+new file mode 100644
+index 000000000000..d4e55e2d2d29
+--- /dev/null
++++ b/arch/unicore32/kernel/pci.c
+@@ -0,0 +1,404 @@
++/*
++ * linux/arch/unicore32/kernel/pci.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ *  PCI bios-type initialisation for PCI machines
++ *
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++static int debug_pci;
++static int use_firmware;
++
++#define CONFIG_CMD(bus, devfn, where)	\
++	(0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
++
++static int
++puv3_read_config(struct pci_bus *bus, unsigned int devfn, int where,
++			int size, u32 *value)
++{
++	PCICFG_ADDR = CONFIG_CMD(bus, devfn, where);
++	switch (size) {
++	case 1:
++		*value = (PCICFG_DATA >> ((where & 3) * 8)) & 0xFF;
++		break;
++	case 2:
++		*value = (PCICFG_DATA >> ((where & 2) * 8)) & 0xFFFF;
++		break;
++	case 4:
++		*value = PCICFG_DATA;
++		break;
++	}
++	return PCIBIOS_SUCCESSFUL;
++}
++
++static int
++puv3_write_config(struct pci_bus *bus, unsigned int devfn, int where,
++			int size, u32 value)
++{
++	PCICFG_ADDR = CONFIG_CMD(bus, devfn, where);
++	switch (size) {
++	case 1:
++		PCICFG_DATA = (PCICFG_DATA & ~FMASK(8, (where&3)*8))
++			| FIELD(value, 8, (where&3)*8);
++		break;
++	case 2:
++		PCICFG_DATA = (PCICFG_DATA & ~FMASK(16, (where&2)*8))
++			| FIELD(value, 16, (where&2)*8);
++		break;
++	case 4:
++		PCICFG_DATA = value;
++		break;
++	}
++	return PCIBIOS_SUCCESSFUL;
++}
++
++struct pci_ops pci_puv3_ops = {
++	.read  = puv3_read_config,
++	.write = puv3_write_config,
++};
++
++void pci_puv3_preinit(void)
++{
++	printk(KERN_DEBUG "PCI: PKUnity PCI Controller Initializing ...\n");
++	/* config PCI bridge base */
++	PCICFG_BRIBASE = PKUNITY_PCIBRI_BASE;
++
++	PCIBRI_AHBCTL0 = 0;
++	PCIBRI_AHBBAR0 = PKUNITY_PCIBRI_BASE | PCIBRI_BARx_MEM;
++	PCIBRI_AHBAMR0 = 0xFFFF0000;
++	PCIBRI_AHBTAR0 = 0;
++
++	PCIBRI_AHBCTL1 = PCIBRI_CTLx_AT;
++	PCIBRI_AHBBAR1 = PKUNITY_PCILIO_BASE | PCIBRI_BARx_IO;
++	PCIBRI_AHBAMR1 = 0xFFFF0000;
++	PCIBRI_AHBTAR1 = 0x00000000;
++
++	PCIBRI_AHBCTL2 = PCIBRI_CTLx_PREF;
++	PCIBRI_AHBBAR2 = PKUNITY_PCIMEM_BASE | PCIBRI_BARx_MEM;
++	PCIBRI_AHBAMR2 = 0xF8000000;
++	PCIBRI_AHBTAR2 = 0;
++
++	PCIBRI_BAR1 = PKUNITY_PCIAHB_BASE | PCIBRI_BARx_MEM;
++
++	PCIBRI_PCICTL0 = PCIBRI_CTLx_AT | PCIBRI_CTLx_PREF;
++	PCIBRI_PCIBAR0 = PKUNITY_PCIAHB_BASE | PCIBRI_BARx_MEM;
++	PCIBRI_PCIAMR0 = 0xF8000000;
++	PCIBRI_PCITAR0 = PKUNITY_SDRAM_BASE;
++
++	PCIBRI_CMD = PCIBRI_CMD | PCIBRI_CMD_IO | PCIBRI_CMD_MEM;
++}
++
++static int __init pci_puv3_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++	if (dev->bus->number == 0) {
++#ifdef CONFIG_ARCH_FPGA /* 4 pci slots */
++		if      (dev->devfn == 0x00)
++			return IRQ_PCIINTA;
++		else if (dev->devfn == 0x08)
++			return IRQ_PCIINTB;
++		else if (dev->devfn == 0x10)
++			return IRQ_PCIINTC;
++		else if (dev->devfn == 0x18)
++			return IRQ_PCIINTD;
++#endif
++#ifdef CONFIG_PUV3_DB0913 /* 3 pci slots */
++		if      (dev->devfn == 0x30)
++			return IRQ_PCIINTB;
++		else if (dev->devfn == 0x60)
++			return IRQ_PCIINTC;
++		else if (dev->devfn == 0x58)
++			return IRQ_PCIINTD;
++#endif
++#if	defined(CONFIG_PUV3_NB0916) || defined(CONFIG_PUV3_SMW0919)
++		/* only support 2 pci devices */
++		if      (dev->devfn == 0x00)
++			return IRQ_PCIINTC; /* sata */
++#endif
++	}
++	return -1;
++}
++
++/*
++ * Only first 128MB of memory can be accessed via PCI.
++ * We use GFP_DMA to allocate safe buffers to do map/unmap.
++ * This is really ugly and we need a better way of specifying
++ * DMA-capable regions of memory.
++ */
++void __init puv3_pci_adjust_zones(unsigned long *zone_size,
++	unsigned long *zhole_size)
++{
++	unsigned int sz = SZ_128M >> PAGE_SHIFT;
++
++	/*
++	 * Only adjust if > 128M on current system
++	 */
++	if (zone_size[0] <= sz)
++		return;
++
++	zone_size[1] = zone_size[0] - sz;
++	zone_size[0] = sz;
++	zhole_size[1] = zhole_size[0];
++	zhole_size[0] = 0;
++}
++
++void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
++{
++	if (debug_pci)
++		printk(KERN_DEBUG "PCI: Assigning IRQ %02d to %s\n",
++				irq, pci_name(dev));
++	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
++}
++
++/*
++ * If the bus contains any of these devices, then we must not turn on
++ * parity checking of any kind.
++ */
++static inline int pdev_bad_for_parity(struct pci_dev *dev)
++{
++	return 0;
++}
++
++/*
++ * pcibios_fixup_bus - Called after each bus is probed,
++ * but before its children are examined.
++ */
++void __devinit pcibios_fixup_bus(struct pci_bus *bus)
++{
++	struct pci_dev *dev;
++	u16 features = PCI_COMMAND_SERR
++		| PCI_COMMAND_PARITY
++		| PCI_COMMAND_FAST_BACK;
++
++	bus->resource[0] = &ioport_resource;
++	bus->resource[1] = &iomem_resource;
++
++	/*
++	 * Walk the devices on this bus, working out what we can
++	 * and can't support.
++	 */
++	list_for_each_entry(dev, &bus->devices, bus_list) {
++		u16 status;
++
++		pci_read_config_word(dev, PCI_STATUS, &status);
++
++		/*
++		 * If any device on this bus does not support fast back
++		 * to back transfers, then the bus as a whole is not able
++		 * to support them.  Having fast back to back transfers
++		 * on saves us one PCI cycle per transaction.
++		 */
++		if (!(status & PCI_STATUS_FAST_BACK))
++			features &= ~PCI_COMMAND_FAST_BACK;
++
++		if (pdev_bad_for_parity(dev))
++			features &= ~(PCI_COMMAND_SERR
++					| PCI_COMMAND_PARITY);
++
++		switch (dev->class >> 8) {
++		case PCI_CLASS_BRIDGE_PCI:
++			pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &status);
++			status |= PCI_BRIDGE_CTL_PARITY
++				| PCI_BRIDGE_CTL_MASTER_ABORT;
++			status &= ~(PCI_BRIDGE_CTL_BUS_RESET
++				| PCI_BRIDGE_CTL_FAST_BACK);
++			pci_write_config_word(dev, PCI_BRIDGE_CONTROL, status);
++			break;
++
++		case PCI_CLASS_BRIDGE_CARDBUS:
++			pci_read_config_word(dev, PCI_CB_BRIDGE_CONTROL,
++					&status);
++			status |= PCI_CB_BRIDGE_CTL_PARITY
++				| PCI_CB_BRIDGE_CTL_MASTER_ABORT;
++			pci_write_config_word(dev, PCI_CB_BRIDGE_CONTROL,
++					status);
++			break;
++		}
++	}
++
++	/*
++	 * Now walk the devices again, this time setting them up.
++	 */
++	list_for_each_entry(dev, &bus->devices, bus_list) {
++		u16 cmd;
++
++		pci_read_config_word(dev, PCI_COMMAND, &cmd);
++		cmd |= features;
++		pci_write_config_word(dev, PCI_COMMAND, cmd);
++
++		pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
++				      L1_CACHE_BYTES >> 2);
++	}
++
++	/*
++	 * Propagate the flags to the PCI bridge.
++	 */
++	if (bus->self && bus->self->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
++		if (features & PCI_COMMAND_FAST_BACK)
++			bus->bridge_ctl |= PCI_BRIDGE_CTL_FAST_BACK;
++		if (features & PCI_COMMAND_PARITY)
++			bus->bridge_ctl |= PCI_BRIDGE_CTL_PARITY;
++	}
++
++	/*
++	 * Report what we did for this bus
++	 */
++	printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n",
++		bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis");
++}
++#ifdef CONFIG_HOTPLUG
++EXPORT_SYMBOL(pcibios_fixup_bus);
++#endif
++
++static int __init pci_common_init(void)
++{
++	struct pci_bus *puv3_bus;
++
++	pci_puv3_preinit();
++
++	puv3_bus = pci_scan_bus(0, &pci_puv3_ops, NULL);
++
++	if (!puv3_bus)
++		panic("PCI: unable to scan bus!");
++
++	pci_fixup_irqs(pci_common_swizzle, pci_puv3_map_irq);
++
++	if (!use_firmware) {
++		/*
++		 * Size the bridge windows.
++		 */
++		pci_bus_size_bridges(puv3_bus);
++
++		/*
++		 * Assign resources.
++		 */
++		pci_bus_assign_resources(puv3_bus);
++	}
++
++	/*
++	 * Tell drivers about devices found.
++	 */
++	pci_bus_add_devices(puv3_bus);
++
++	return 0;
++}
++subsys_initcall(pci_common_init);
++
++char * __devinit pcibios_setup(char *str)
++{
++	if (!strcmp(str, "debug")) {
++		debug_pci = 1;
++		return NULL;
++	} else if (!strcmp(str, "firmware")) {
++		use_firmware = 1;
++		return NULL;
++	}
++	return str;
++}
++
++/*
++ * From arch/i386/kernel/pci-i386.c:
++ *
++ * We need to avoid collisions with `mirrored' VGA ports
++ * and other strange ISA hardware, so we always want the
++ * addresses to be allocated in the 0x000-0x0ff region
++ * modulo 0x400.
++ *
++ * Why? Because some silly external IO cards only decode
++ * the low 10 bits of the IO address. The 0x00-0xff region
++ * is reserved for motherboard devices that decode all 16
++ * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
++ * but we want to try to avoid allocating at 0x2900-0x2bff
++ * which might be mirrored at 0x0100-0x03ff..
++ */
++resource_size_t pcibios_align_resource(void *data, const struct resource *res,
++				resource_size_t size, resource_size_t align)
++{
++	resource_size_t start = res->start;
++
++	if (res->flags & IORESOURCE_IO && start & 0x300)
++		start = (start + 0x3ff) & ~0x3ff;
++
++	start = (start + align - 1) & ~(align - 1);
++
++	return start;
++}
++
++/**
++ * pcibios_enable_device - Enable I/O and memory.
++ * @dev: PCI device to be enabled
++ */
++int pcibios_enable_device(struct pci_dev *dev, int mask)
++{
++	u16 cmd, old_cmd;
++	int idx;
++	struct resource *r;
++
++	pci_read_config_word(dev, PCI_COMMAND, &cmd);
++	old_cmd = cmd;
++	for (idx = 0; idx < 6; idx++) {
++		/* Only set up the requested stuff */
++		if (!(mask & (1 << idx)))
++			continue;
++
++		r = dev->resource + idx;
++		if (!r->start && r->end) {
++			printk(KERN_ERR "PCI: Device %s not available because"
++			       " of resource collisions\n", pci_name(dev));
++			return -EINVAL;
++		}
++		if (r->flags & IORESOURCE_IO)
++			cmd |= PCI_COMMAND_IO;
++		if (r->flags & IORESOURCE_MEM)
++			cmd |= PCI_COMMAND_MEMORY;
++	}
++
++	/*
++	 * Bridges (eg, cardbus bridges) need to be fully enabled
++	 */
++	if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
++		cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
++
++	if (cmd != old_cmd) {
++		printk("PCI: enabling device %s (%04x -> %04x)\n",
++		       pci_name(dev), old_cmd, cmd);
++		pci_write_config_word(dev, PCI_COMMAND, cmd);
++	}
++	return 0;
++}
++
++int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
++			enum pci_mmap_state mmap_state, int write_combine)
++{
++	unsigned long phys;
++
++	if (mmap_state == pci_mmap_io)
++		return -EINVAL;
++
++	phys = vma->vm_pgoff;
++
++	/*
++	 * Mark this as IO
++	 */
++	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
++
++	if (remap_pfn_range(vma, vma->vm_start, phys,
++			     vma->vm_end - vma->vm_start,
++			     vma->vm_page_prot))
++		return -EAGAIN;
++
++	return 0;
++}
+diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
+index 98e6fdf34d30..77cf813ba264 100644
+--- a/drivers/pci/Makefile
++++ b/drivers/pci/Makefile
+@@ -42,6 +42,7 @@ obj-$(CONFIG_PCI_IOV) += iov.o
+ obj-$(CONFIG_X86) += setup-bus.o
+ obj-$(CONFIG_ALPHA) += setup-bus.o setup-irq.o
+ obj-$(CONFIG_ARM) += setup-bus.o setup-irq.o
++obj-$(CONFIG_UNICORE32) += setup-bus.o setup-irq.o
+ obj-$(CONFIG_PARISC) += setup-bus.o
+ obj-$(CONFIG_SUPERH) += setup-bus.o setup-irq.o
+ obj-$(CONFIG_PPC) += setup-bus.o

commit b08b4f8e63e60a64f81e194269be14afee396f33
+Author: GuanXuetao 
+Date:   Sat Feb 26 20:08:36 2011 +0800
+
+    unicore32 machine related files: hardware registers
+    
+    This patch adds all hardware registers definitions.
+    
+    Signed-off-by: Guan Xuetao 
+
+diff --git a/arch/unicore32/include/mach/PKUnity.h b/arch/unicore32/include/mach/PKUnity.h
+new file mode 100644
+index 000000000000..fa11eba0afd6
+--- /dev/null
++++ b/arch/unicore32/include/mach/PKUnity.h
+@@ -0,0 +1,104 @@
++/*
++ * linux/arch/unicore32/include/mach/PKUnity.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++/* Be sure that virtual mapping is defined right */
++#ifndef __MACH_PUV3_HARDWARE_H__
++#error You must include hardware.h not PKUnity.h
++#endif
++
++#include "bitfield.h"
++
++/*
++ * Memory Definitions
++ */
++#define PKUNITY_SDRAM_BASE		0x00000000 /* 0x00000000 - 0x7FFFFFFF 2GB */
++#define PKUNITY_IOSPACE_BASE            0x80000000 /* 0x80000000 - 0xFFFFFFFF 2GB */
++#define PKUNITY_PCI_BASE		0x80000000 /* 0x80000000 - 0xBFFFFFFF 1GB */
++#include "regs-pci.h"
++#define PKUNITY_BOOT_ROM2_BASE		0xF4000000 /* 0xF4000000 - 0xF7FFFFFF 64MB */
++#define PKUNITY_BOOT_SRAM2_BASE		0xF8000000 /* 0xF8000000 - 0xFBFFFFFF 64MB */
++#define PKUNITY_BOOT_FLASH_BASE		0xFC000000 /* 0xFC000000 - 0xFFFFFFFF 64MB */
++
++/*
++ * PKUNITY Memory Map Addresses: 0x0D000000 - 0x0EFFFFFF (32MB)
++ */
++#define PKUNITY_UVC_MMAP_BASE		0x0D000000 /* 0x0D000000 - 0x0DFFFFFF 16MB */
++#define PKUNITY_UVC_MMAP_SIZE		0x01000000 /* 16MB */
++#define PKUNITY_UNIGFX_MMAP_BASE        0x0E000000 /* 0x0E000000 - 0x0EFFFFFF 16MB */
++#define PKUNITY_UNIGFX_MMAP_SIZE        0x01000000 /* 16MB */
++
++/*
++ * PKUNITY System Bus Addresses (PCI): 0x80000000 - 0xBFFFFFFF (1GB)
++ */
++/* PCI Configuration regs */
++#define PKUNITY_PCICFG_BASE             0x80000000 /* 0x80000000 - 0x8000000B 12B */
++/* PCI Bridge Base */
++#define PKUNITY_PCIBRI_BASE             0x80010000 /* 0x80010000 - 0x80010250 592B */
++/* PCI Legacy IO */
++#define PKUNITY_PCILIO_BASE             0x80030000 /* 0x80030000 - 0x8003FFFF 64KB */
++/* PCI AHB-PCI MEM-mapping */
++#define PKUNITY_PCIMEM_BASE             0x90000000 /* 0x90000000 - 0x97FFFFFF 128MB */
++/* PCI PCI-AHB MEM-mapping */
++#define PKUNITY_PCIAHB_BASE             0x98000000 /* 0x98000000 - 0x9FFFFFFF 128MB */
++
++/*
++ * PKUNITY System Bus Addresses (AHB): 0xC0000000 - 0xEDFFFFFF (640MB)
++ */
++/* AHB-0 is DDR2 SDRAM */
++/* AHB-1 is PCI Space */
++#define PKUNITY_ARBITER_BASE		0xC0000000 /* AHB-2 */
++#define PKUNITY_DDR2CTRL_BASE		0xC0100000 /* AHB-3 */
++#define PKUNITY_DMAC_BASE		0xC0200000 /* AHB-4 */
++#include "regs-dmac.h"
++#define PKUNITY_UMAL_BASE		0xC0300000 /* AHB-5 */
++#include "regs-umal.h"
++#define PKUNITY_USB_BASE		0xC0400000 /* AHB-6 */
++#define PKUNITY_SATA_BASE		0xC0500000 /* AHB-7 */
++#define PKUNITY_SMC_BASE		0xC0600000 /* AHB-8 */
++/* AHB-9 is for APB bridge */
++#define PKUNITY_MME_BASE		0xC0700000 /* AHB-10 */
++#define PKUNITY_UNIGFX_BASE		0xC0800000 /* AHB-11 */
++#include "regs-unigfx.h"
++#define PKUNITY_NAND_BASE		0xC0900000 /* AHB-12 */
++#include "regs-nand.h"
++#define PKUNITY_H264D_BASE		0xC0A00000 /* AHB-13 */
++#define PKUNITY_H264E_BASE		0xC0B00000 /* AHB-14 */
++
++/*
++ * PKUNITY Peripheral Bus Addresses (APB): 0xEE000000 - 0xEFFFFFFF (128MB)
++ */
++#define PKUNITY_UART0_BASE		0xEE000000 /* APB-0 */
++#define PKUNITY_UART1_BASE		0xEE100000 /* APB-1 */
++#include "regs-uart.h"
++#define PKUNITY_I2C_BASE		0xEE200000 /* APB-2 */
++#include "regs-i2c.h"
++#define PKUNITY_SPI_BASE		0xEE300000 /* APB-3 */
++#include "regs-spi.h"
++#define PKUNITY_AC97_BASE		0xEE400000 /* APB-4 */
++#include "regs-ac97.h"
++#define PKUNITY_GPIO_BASE		0xEE500000 /* APB-5 */
++#include "regs-gpio.h"
++#define PKUNITY_INTC_BASE		0xEE600000 /* APB-6 */
++#include "regs-intc.h"
++#define PKUNITY_RTC_BASE		0xEE700000 /* APB-7 */
++#include "regs-rtc.h"
++#define PKUNITY_OST_BASE		0xEE800000 /* APB-8 */
++#include "regs-ost.h"
++#define PKUNITY_RESETC_BASE		0xEE900000 /* APB-9 */
++#include "regs-resetc.h"
++#define PKUNITY_PM_BASE			0xEEA00000 /* APB-10 */
++#include "regs-pm.h"
++#define PKUNITY_PS2_BASE		0xEEB00000 /* APB-11 */
++#include "regs-ps2.h"
++#define PKUNITY_SDC_BASE		0xEEC00000 /* APB-12 */
++#include "regs-sdc.h"
++
+diff --git a/arch/unicore32/include/mach/bitfield.h b/arch/unicore32/include/mach/bitfield.h
+new file mode 100644
+index 000000000000..128a70281efc
+--- /dev/null
++++ b/arch/unicore32/include/mach/bitfield.h
+@@ -0,0 +1,24 @@
++/*
++ * linux/arch/unicore32/include/mach/bitfield.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __MACH_PUV3_BITFIELD_H__
++#define __MACH_PUV3_BITFIELD_H__
++
++#ifndef __ASSEMBLY__
++#define UData(Data)	((unsigned long) (Data))
++#else
++#define UData(Data)	(Data)
++#endif
++
++#define FIELD(val, vmask, vshift)	(((val) & ((UData(1) << (vmask)) - 1)) << (vshift))
++#define FMASK(vmask, vshift)		(((UData(1) << (vmask)) - 1) << (vshift))
++
++#endif /* __MACH_PUV3_BITFIELD_H__ */
+diff --git a/arch/unicore32/include/mach/hardware.h b/arch/unicore32/include/mach/hardware.h
+new file mode 100644
+index 000000000000..3fb7236f8d69
+--- /dev/null
++++ b/arch/unicore32/include/mach/hardware.h
+@@ -0,0 +1,45 @@
++/*
++ * linux/arch/unicore32/include/mach/hardware.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This file contains the hardware definitions for PKUnity architecture
++ */
++
++#ifndef __MACH_PUV3_HARDWARE_H__
++#define __MACH_PUV3_HARDWARE_H__
++
++#include "PKUnity.h"
++
++#define io_p2v(x)	((x) - PKUNITY_IOSPACE_BASE)
++#define io_v2p(x)	((x) + PKUNITY_IOSPACE_BASE)
++
++#ifndef __ASSEMBLY__
++
++# define __REG(x)	(*((volatile unsigned long *)io_p2v(x)))
++# define __PREG(x)	(io_v2p((unsigned long)&(x)))
++
++#else
++
++# define __REG(x)	io_p2v(x)
++# define __PREG(x)	io_v2p(x)
++
++#endif
++
++#define PCIBIOS_MIN_IO			0x4000 /* should lower than 64KB */
++#define PCIBIOS_MIN_MEM			PKUNITY_PCIMEM_BASE
++
++/*
++ * We override the standard dma-mask routines for bouncing.
++ */
++#define	HAVE_ARCH_PCI_SET_DMA_MASK
++
++#define pcibios_assign_all_busses()	1
++
++#endif  /* __MACH_PUV3_HARDWARE_H__ */
+diff --git a/arch/unicore32/include/mach/regs-ac97.h b/arch/unicore32/include/mach/regs-ac97.h
+new file mode 100644
+index 000000000000..ce299bf4adae
+--- /dev/null
++++ b/arch/unicore32/include/mach/regs-ac97.h
+@@ -0,0 +1,32 @@
++/*
++ * PKUnity AC97 Registers
++ */
++
++#define PKUNITY_AC97_CONR		__REG(PKUNITY_AC97_BASE + 0x0000)
++#define PKUNITY_AC97_OCR		__REG(PKUNITY_AC97_BASE + 0x0004)
++#define PKUNITY_AC97_ICR		__REG(PKUNITY_AC97_BASE + 0x0008)
++#define PKUNITY_AC97_CRAC		__REG(PKUNITY_AC97_BASE + 0x000C)
++#define PKUNITY_AC97_INTR		__REG(PKUNITY_AC97_BASE + 0x0010)
++#define PKUNITY_AC97_INTRSTAT		__REG(PKUNITY_AC97_BASE + 0x0014)
++#define PKUNITY_AC97_INTRCLEAR		__REG(PKUNITY_AC97_BASE + 0x0018)
++#define PKUNITY_AC97_ENABLE		__REG(PKUNITY_AC97_BASE + 0x001C)
++#define PKUNITY_AC97_OUT_FIFO		__REG(PKUNITY_AC97_BASE + 0x0020)
++#define PKUNITY_AC97_IN_FIFO		__REG(PKUNITY_AC97_BASE + 0x0030)
++
++#define AC97_CODEC_REG(v)               FIELD((v), 7, 16)
++#define AC97_CODEC_VAL(v)               FIELD((v), 16, 0)
++#define AC97_CODEC_WRITECOMPLETE        FIELD(1, 1, 2)
++
++/*
++ * VAR PLAY SAMPLE RATE
++ */
++#define AC97_CMD_VPSAMPLE		(FIELD(3, 2, 16) | FIELD(3, 2, 0))
++
++/*
++ * FIX CAPTURE SAMPLE RATE
++ */
++#define AC97_CMD_FCSAMPLE		FIELD(7, 3, 0)
++
++#define AC97_CMD_RESET			FIELD(1, 1, 0)
++#define AC97_CMD_ENABLE			FIELD(1, 1, 0)
++#define AC97_CMD_DISABLE		FIELD(0, 1, 0)
+diff --git a/arch/unicore32/include/mach/regs-dmac.h b/arch/unicore32/include/mach/regs-dmac.h
+new file mode 100644
+index 000000000000..09fce9d0d640
+--- /dev/null
++++ b/arch/unicore32/include/mach/regs-dmac.h
+@@ -0,0 +1,81 @@
++/*
++ * PKUnity Direct Memory Access Controller (DMAC)
++ */
++
++/*
++ * Interrupt Status Reg DMAC_ISR.
++ */
++#define DMAC_ISR		__REG(PKUNITY_DMAC_BASE + 0x0020)
++/*
++ * Interrupt Transfer Complete Status Reg DMAC_ITCSR.
++ */
++#define DMAC_ITCSR		__REG(PKUNITY_DMAC_BASE + 0x0050)
++/*
++ * Interrupt Transfer Complete Clear Reg DMAC_ITCCR.
++ */
++#define DMAC_ITCCR		__REG(PKUNITY_DMAC_BASE + 0x0060)
++/*
++ * Interrupt Error Status Reg DMAC_IESR.
++ */
++#define DMAC_IESR		__REG(PKUNITY_DMAC_BASE + 0x0080)
++/*
++ * Interrupt Error Clear Reg DMAC_IECR.
++ */
++#define DMAC_IECR		__REG(PKUNITY_DMAC_BASE + 0x0090)
++/*
++ * Enable Channels Reg DMAC_ENCH.
++ */
++#define DMAC_ENCH		__REG(PKUNITY_DMAC_BASE + 0x00B0)
++
++/*
++ * DMA control reg. Space [byte]
++ */
++#define DMASp                   0x00000100
++
++/*
++ * Source Addr DMAC_SRCADDR(ch).
++ */
++#define DMAC_SRCADDR(ch)	__REG(PKUNITY_DMAC_BASE + (ch)*DMASp + 0x00)
++/*
++ * Destination Addr DMAC_DESTADDR(ch).
++ */
++#define DMAC_DESTADDR(ch)	__REG(PKUNITY_DMAC_BASE + (ch)*DMASp + 0x04)
++/*
++ * Control Reg DMAC_CONTROL(ch).
++ */
++#define DMAC_CONTROL(ch)	__REG(PKUNITY_DMAC_BASE + (ch)*DMASp + 0x0C)
++/*
++ * Configuration Reg DMAC_CONFIG(ch).
++ */
++#define DMAC_CONFIG(ch)		__REG(PKUNITY_DMAC_BASE + (ch)*DMASp + 0x10)
++
++#define DMAC_IR_MASK            FMASK(6, 0)
++/*
++ * select channel (ch)
++ */
++#define DMAC_CHANNEL(ch)	FIELD(1, 1, (ch))
++
++#define DMAC_CONTROL_SIZE_BYTE(v)       (FIELD((v), 12, 14) | \
++					FIELD(0, 3, 9) | FIELD(0, 3, 6))
++#define DMAC_CONTROL_SIZE_HWORD(v)      (FIELD((v) >> 1, 12, 14) | \
++					FIELD(1, 3, 9) | FIELD(1, 3, 6))
++#define DMAC_CONTROL_SIZE_WORD(v)       (FIELD((v) >> 2, 12, 14) | \
++					FIELD(2, 3, 9) | FIELD(2, 3, 6))
++#define DMAC_CONTROL_DI                 FIELD(1, 1, 13)
++#define DMAC_CONTROL_SI                 FIELD(1, 1, 12)
++#define DMAC_CONTROL_BURST_1BYTE        (FIELD(0, 3, 3) | FIELD(0, 3, 0))
++#define DMAC_CONTROL_BURST_4BYTE        (FIELD(3, 3, 3) | FIELD(3, 3, 0))
++#define DMAC_CONTROL_BURST_8BYTE        (FIELD(5, 3, 3) | FIELD(5, 3, 0))
++#define DMAC_CONTROL_BURST_16BYTE       (FIELD(7, 3, 3) | FIELD(7, 3, 0))
++
++#define	DMAC_CONFIG_UART0_WR    (FIELD(2, 4, 11) | FIELD(1, 2, 1))
++#define	DMAC_CONFIG_UART0_RD    (FIELD(2, 4, 7)  | FIELD(2, 2, 1))
++#define	DMAC_CONFIG_UART1_WR    (FIELD(3, 4, 11) | FIELD(1, 2, 1))
++#define	DMAC_CONFIG_UART1RD     (FIELD(3, 4, 7)  | FIELD(2, 2, 1))
++#define	DMAC_CONFIG_AC97WR      (FIELD(4, 4, 11) | FIELD(1, 2, 1))
++#define	DMAC_CONFIG_AC97RD      (FIELD(4, 4, 7)  | FIELD(2, 2, 1))
++#define	DMAC_CONFIG_MMCWR       (FIELD(7, 4, 11) | FIELD(1, 2, 1))
++#define	DMAC_CONFIG_MMCRD       (FIELD(7, 4, 7)  | FIELD(2, 2, 1))
++#define DMAC_CONFIG_MASKITC     FIELD(1, 1, 4)
++#define DMAC_CONFIG_MASKIE      FIELD(1, 1, 3)
++#define DMAC_CONFIG_EN          FIELD(1, 1, 0)
+diff --git a/arch/unicore32/include/mach/regs-gpio.h b/arch/unicore32/include/mach/regs-gpio.h
+new file mode 100644
+index 000000000000..5dd99d4c209e
+--- /dev/null
++++ b/arch/unicore32/include/mach/regs-gpio.h
+@@ -0,0 +1,70 @@
++/*
++ * PKUnity General-Purpose Input/Output (GPIO) Registers
++ */
++
++/*
++ * Voltage Status Reg GPIO_GPLR.
++ */
++#define GPIO_GPLR	__REG(PKUNITY_GPIO_BASE + 0x0000)
++/*
++ * Pin Direction Reg GPIO_GPDR.
++ */
++#define GPIO_GPDR	__REG(PKUNITY_GPIO_BASE + 0x0004)
++/*
++ * Output Pin Set Reg GPIO_GPSR.
++ */
++#define GPIO_GPSR	__REG(PKUNITY_GPIO_BASE + 0x0008)
++/*
++ * Output Pin Clear Reg GPIO_GPCR.
++ */
++#define GPIO_GPCR	__REG(PKUNITY_GPIO_BASE + 0x000C)
++/*
++ * Raise Edge Detect Reg GPIO_GRER.
++ */
++#define GPIO_GRER	__REG(PKUNITY_GPIO_BASE + 0x0010)
++/*
++ * Fall Edge Detect Reg GPIO_GFER.
++ */
++#define GPIO_GFER	__REG(PKUNITY_GPIO_BASE + 0x0014)
++/*
++ * Edge Status Reg GPIO_GEDR.
++ */
++#define GPIO_GEDR	__REG(PKUNITY_GPIO_BASE + 0x0018)
++/*
++ * Sepcial Voltage Detect Reg GPIO_GPIR.
++ */
++#define GPIO_GPIR	__REG(PKUNITY_GPIO_BASE + 0x0020)
++
++#define GPIO_MIN	(0)
++#define GPIO_MAX	(27)
++
++#define GPIO_GPIO(Nb)	(0x00000001 << (Nb))	/* GPIO [0..27] */
++#define GPIO_GPIO0	GPIO_GPIO(0)	/* GPIO  [0] */
++#define GPIO_GPIO1	GPIO_GPIO(1)	/* GPIO  [1] */
++#define GPIO_GPIO2	GPIO_GPIO(2)	/* GPIO  [2] */
++#define GPIO_GPIO3	GPIO_GPIO(3)	/* GPIO  [3] */
++#define GPIO_GPIO4	GPIO_GPIO(4)	/* GPIO  [4] */
++#define GPIO_GPIO5	GPIO_GPIO(5)	/* GPIO  [5] */
++#define GPIO_GPIO6	GPIO_GPIO(6)	/* GPIO  [6] */
++#define GPIO_GPIO7	GPIO_GPIO(7)	/* GPIO  [7] */
++#define GPIO_GPIO8	GPIO_GPIO(8)	/* GPIO  [8] */
++#define GPIO_GPIO9	GPIO_GPIO(9)	/* GPIO  [9] */
++#define GPIO_GPIO10	GPIO_GPIO(10)	/* GPIO [10] */
++#define GPIO_GPIO11	GPIO_GPIO(11)	/* GPIO [11] */
++#define GPIO_GPIO12	GPIO_GPIO(12)	/* GPIO [12] */
++#define GPIO_GPIO13	GPIO_GPIO(13)	/* GPIO [13] */
++#define GPIO_GPIO14	GPIO_GPIO(14)	/* GPIO [14] */
++#define GPIO_GPIO15	GPIO_GPIO(15)	/* GPIO [15] */
++#define GPIO_GPIO16	GPIO_GPIO(16)	/* GPIO [16] */
++#define GPIO_GPIO17	GPIO_GPIO(17)	/* GPIO [17] */
++#define GPIO_GPIO18	GPIO_GPIO(18)	/* GPIO [18] */
++#define GPIO_GPIO19	GPIO_GPIO(19)	/* GPIO [19] */
++#define GPIO_GPIO20	GPIO_GPIO(20)	/* GPIO [20] */
++#define GPIO_GPIO21	GPIO_GPIO(21)	/* GPIO [21] */
++#define GPIO_GPIO22	GPIO_GPIO(22)	/* GPIO [22] */
++#define GPIO_GPIO23	GPIO_GPIO(23)	/* GPIO [23] */
++#define GPIO_GPIO24	GPIO_GPIO(24)	/* GPIO [24] */
++#define GPIO_GPIO25	GPIO_GPIO(25)	/* GPIO [25] */
++#define GPIO_GPIO26	GPIO_GPIO(26)	/* GPIO [26] */
++#define GPIO_GPIO27	GPIO_GPIO(27)	/* GPIO [27] */
++
+diff --git a/arch/unicore32/include/mach/regs-i2c.h b/arch/unicore32/include/mach/regs-i2c.h
+new file mode 100644
+index 000000000000..70b704f8dda8
+--- /dev/null
++++ b/arch/unicore32/include/mach/regs-i2c.h
+@@ -0,0 +1,63 @@
++/*
++ * PKUnity Inter-integrated Circuit (I2C) Registers
++ */
++
++/*
++ * Control Reg I2C_CON.
++ */
++#define I2C_CON		__REG(PKUNITY_I2C_BASE + 0x0000)
++/*
++ * Target Address Reg I2C_TAR.
++ */
++#define I2C_TAR		__REG(PKUNITY_I2C_BASE + 0x0004)
++/*
++ * Data buffer and command Reg I2C_DATACMD.
++ */
++#define I2C_DATACMD	__REG(PKUNITY_I2C_BASE + 0x0010)
++/*
++ * Enable Reg I2C_ENABLE.
++ */
++#define I2C_ENABLE	__REG(PKUNITY_I2C_BASE + 0x006C)
++/*
++ * Status Reg I2C_STATUS.
++ */
++#define I2C_STATUS	__REG(PKUNITY_I2C_BASE + 0x0070)
++/*
++ * Tx FIFO Length Reg I2C_TXFLR.
++ */
++#define I2C_TXFLR	__REG(PKUNITY_I2C_BASE + 0x0074)
++/*
++ * Rx FIFO Length Reg I2C_RXFLR.
++ */
++#define I2C_RXFLR	__REG(PKUNITY_I2C_BASE + 0x0078)
++/*
++ * Enable Status Reg I2C_ENSTATUS.
++ */
++#define I2C_ENSTATUS	__REG(PKUNITY_I2C_BASE + 0x009C)
++
++#define I2C_CON_MASTER          FIELD(1, 1, 0)
++#define I2C_CON_SPEED_STD       FIELD(1, 2, 1)
++#define I2C_CON_SPEED_FAST      FIELD(2, 2, 1)
++#define I2C_CON_RESTART         FIELD(1, 1, 5)
++#define I2C_CON_SLAVEDISABLE    FIELD(1, 1, 6)
++
++#define I2C_DATACMD_READ        FIELD(1, 1, 8)
++#define I2C_DATACMD_WRITE       FIELD(0, 1, 8)
++#define I2C_DATACMD_DAT_MASK    FMASK(8, 0)
++#define I2C_DATACMD_DAT(v)      FIELD((v), 8, 0)
++
++#define I2C_ENABLE_ENABLE       FIELD(1, 1, 0)
++#define I2C_ENABLE_DISABLE      FIELD(0, 1, 0)
++
++#define I2C_STATUS_RFF          FIELD(1, 1, 4)
++#define I2C_STATUS_RFNE         FIELD(1, 1, 3)
++#define I2C_STATUS_TFE          FIELD(1, 1, 2)
++#define I2C_STATUS_TFNF         FIELD(1, 1, 1)
++#define I2C_STATUS_ACTIVITY     FIELD(1, 1, 0)
++
++#define I2C_ENSTATUS_ENABLE	FIELD(1, 1, 0)
++
++#define I2C_TAR_THERMAL	0x4f
++#define I2C_TAR_SPD	0x50
++#define I2C_TAR_PWIC    0x55
++#define I2C_TAR_EEPROM	0x57
+diff --git a/arch/unicore32/include/mach/regs-intc.h b/arch/unicore32/include/mach/regs-intc.h
+new file mode 100644
+index 000000000000..409ae4776145
+--- /dev/null
++++ b/arch/unicore32/include/mach/regs-intc.h
+@@ -0,0 +1,28 @@
++/*
++ * PKUNITY Interrupt Controller (INTC) Registers
++ */
++/*
++ * INTC Level Reg INTC_ICLR.
++ */
++#define INTC_ICLR	__REG(PKUNITY_INTC_BASE + 0x0000)
++/*
++ * INTC Mask Reg INTC_ICMR.
++ */
++#define INTC_ICMR	__REG(PKUNITY_INTC_BASE + 0x0004)
++/*
++ * INTC Pending Reg INTC_ICPR.
++ */
++#define INTC_ICPR	__REG(PKUNITY_INTC_BASE + 0x0008)
++/*
++ * INTC IRQ Pending Reg INTC_ICIP.
++ */
++#define INTC_ICIP	__REG(PKUNITY_INTC_BASE + 0x000C)
++/*
++ * INTC REAL Pending Reg INTC_ICFP.
++ */
++#define INTC_ICFP	__REG(PKUNITY_INTC_BASE + 0x0010)
++/*
++ * INTC Control Reg INTC_ICCR.
++ */
++#define INTC_ICCR	__REG(PKUNITY_INTC_BASE + 0x0014)
++
+diff --git a/arch/unicore32/include/mach/regs-nand.h b/arch/unicore32/include/mach/regs-nand.h
+new file mode 100644
+index 000000000000..0c33fe8c3090
+--- /dev/null
++++ b/arch/unicore32/include/mach/regs-nand.h
+@@ -0,0 +1,79 @@
++/*
++ * PKUnity NAND Controller Registers
++ */
++/*
++ * ID Reg. 0 NAND_IDR0
++ */
++#define NAND_IDR0	__REG(PKUNITY_NAND_BASE + 0x0000)
++/*
++ * ID Reg. 1 NAND_IDR1
++ */
++#define NAND_IDR1	__REG(PKUNITY_NAND_BASE + 0x0004)
++/*
++ * ID Reg. 2 NAND_IDR2
++ */
++#define NAND_IDR2	__REG(PKUNITY_NAND_BASE + 0x0008)
++/*
++ * ID Reg. 3 NAND_IDR3
++ */
++#define NAND_IDR3	__REG(PKUNITY_NAND_BASE + 0x000C)
++/*
++ * Page Address Reg 0 NAND_PAR0
++ */
++#define NAND_PAR0	__REG(PKUNITY_NAND_BASE + 0x0010)
++/*
++ * Page Address Reg 1 NAND_PAR1
++ */
++#define NAND_PAR1	__REG(PKUNITY_NAND_BASE + 0x0014)
++/*
++ * Page Address Reg 2 NAND_PAR2
++ */
++#define NAND_PAR2	__REG(PKUNITY_NAND_BASE + 0x0018)
++/*
++ * ECC Enable Reg NAND_ECCEN
++ */
++#define NAND_ECCEN	__REG(PKUNITY_NAND_BASE + 0x001C)
++/*
++ * Buffer Reg NAND_BUF
++ */
++#define NAND_BUF	__REG(PKUNITY_NAND_BASE + 0x0020)
++/*
++ * ECC Status Reg NAND_ECCSR
++ */
++#define NAND_ECCSR	__REG(PKUNITY_NAND_BASE + 0x0024)
++/*
++ * Command Reg NAND_CMD
++ */
++#define NAND_CMD	__REG(PKUNITY_NAND_BASE + 0x0028)
++/*
++ * DMA Configure Reg NAND_DMACR
++ */
++#define NAND_DMACR	__REG(PKUNITY_NAND_BASE + 0x002C)
++/*
++ * Interrupt Reg NAND_IR
++ */
++#define NAND_IR		__REG(PKUNITY_NAND_BASE + 0x0030)
++/*
++ * Interrupt Mask Reg NAND_IMR
++ */
++#define NAND_IMR	__REG(PKUNITY_NAND_BASE + 0x0034)
++/*
++ * Chip Enable Reg NAND_CHIPEN
++ */
++#define NAND_CHIPEN	__REG(PKUNITY_NAND_BASE + 0x0038)
++/*
++ * Address Reg NAND_ADDR
++ */
++#define NAND_ADDR	__REG(PKUNITY_NAND_BASE + 0x003C)
++
++/*
++ * Command bits NAND_CMD_CMD_MASK
++ */
++#define NAND_CMD_CMD_MASK		FMASK(4, 4)
++#define NAND_CMD_CMD_READPAGE		FIELD(0x0, 4, 4)
++#define NAND_CMD_CMD_ERASEBLOCK		FIELD(0x6, 4, 4)
++#define NAND_CMD_CMD_READSTATUS		FIELD(0x7, 4, 4)
++#define NAND_CMD_CMD_WRITEPAGE		FIELD(0x8, 4, 4)
++#define NAND_CMD_CMD_READID		FIELD(0x9, 4, 4)
++#define NAND_CMD_CMD_RESET		FIELD(0xf, 4, 4)
++
+diff --git a/arch/unicore32/include/mach/regs-ost.h b/arch/unicore32/include/mach/regs-ost.h
+new file mode 100644
+index 000000000000..33049a827518
+--- /dev/null
++++ b/arch/unicore32/include/mach/regs-ost.h
+@@ -0,0 +1,92 @@
++/*
++ * PKUnity Operating System Timer (OST) Registers
++ */
++/*
++ * Match Reg 0 OST_OSMR0
++ */
++#define OST_OSMR0	__REG(PKUNITY_OST_BASE + 0x0000)
++/*
++ * Match Reg 1 OST_OSMR1
++ */
++#define OST_OSMR1	__REG(PKUNITY_OST_BASE + 0x0004)
++/*
++ * Match Reg 2 OST_OSMR2
++ */
++#define OST_OSMR2	__REG(PKUNITY_OST_BASE + 0x0008)
++/*
++ * Match Reg 3 OST_OSMR3
++ */
++#define OST_OSMR3	__REG(PKUNITY_OST_BASE + 0x000C)
++/*
++ * Counter Reg OST_OSCR
++ */
++#define OST_OSCR	__REG(PKUNITY_OST_BASE + 0x0010)
++/*
++ * Status Reg OST_OSSR
++ */
++#define OST_OSSR	__REG(PKUNITY_OST_BASE + 0x0014)
++/*
++ * Watchdog Enable Reg OST_OWER
++ */
++#define OST_OWER	__REG(PKUNITY_OST_BASE + 0x0018)
++/*
++ * Interrupt Enable Reg OST_OIER
++ */
++#define OST_OIER	__REG(PKUNITY_OST_BASE + 0x001C)
++/*
++ * PWM Pulse Width Control Reg OST_PWMPWCR
++ */
++#define OST_PWMPWCR	__REG(PKUNITY_OST_BASE + 0x0080)
++/*
++ * PWM Duty Cycle Control Reg OST_PWMDCCR
++ */
++#define OST_PWMDCCR	__REG(PKUNITY_OST_BASE + 0x0084)
++/*
++ * PWM Period Control Reg OST_PWMPCR
++ */
++#define OST_PWMPCR	__REG(PKUNITY_OST_BASE + 0x0088)
++
++/*
++ * Match detected 0 OST_OSSR_M0
++ */
++#define OST_OSSR_M0		FIELD(1, 1, 0)
++/*
++ * Match detected 1 OST_OSSR_M1
++ */
++#define OST_OSSR_M1		FIELD(1, 1, 1)
++/*
++ * Match detected 2 OST_OSSR_M2
++ */
++#define OST_OSSR_M2		FIELD(1, 1, 2)
++/*
++ * Match detected 3 OST_OSSR_M3
++ */
++#define OST_OSSR_M3		FIELD(1, 1, 3)
++
++/*
++ * Interrupt enable 0 OST_OIER_E0
++ */
++#define OST_OIER_E0		FIELD(1, 1, 0)
++/*
++ * Interrupt enable 1 OST_OIER_E1
++ */
++#define OST_OIER_E1		FIELD(1, 1, 1)
++/*
++ * Interrupt enable 2 OST_OIER_E2
++ */
++#define OST_OIER_E2		FIELD(1, 1, 2)
++/*
++ * Interrupt enable 3 OST_OIER_E3
++ */
++#define OST_OIER_E3		FIELD(1, 1, 3)
++
++/*
++ * Watchdog Match Enable OST_OWER_WME
++ */
++#define OST_OWER_WME		FIELD(1, 1, 0)
++
++/*
++ * PWM Full Duty Cycle OST_PWMDCCR_FDCYCLE
++ */
++#define OST_PWMDCCR_FDCYCLE	FIELD(1, 1, 10)
++
+diff --git a/arch/unicore32/include/mach/regs-pci.h b/arch/unicore32/include/mach/regs-pci.h
+new file mode 100644
+index 000000000000..e8e1f1a52fd0
+--- /dev/null
++++ b/arch/unicore32/include/mach/regs-pci.h
+@@ -0,0 +1,94 @@
++/*
++ * PKUnity AHB-PCI Bridge Registers
++ */
++
++/*
++ * AHB/PCI fixed physical address for pci addess configuration
++ */
++/*
++ * PCICFG Bridge Base Reg.
++ */
++#define PCICFG_BRIBASE          __REG(PKUNITY_PCICFG_BASE + 0x0000)
++/*
++ * PCICFG Address Reg.
++ */
++#define PCICFG_ADDR             __REG(PKUNITY_PCICFG_BASE + 0x0004)
++/*
++ * PCICFG Address Reg.
++ */
++#define PCICFG_DATA             __REG(PKUNITY_PCICFG_BASE + 0x0008)
++
++/*
++ * PCI Bridge configuration space
++ */
++#define PCIBRI_ID		__REG(PKUNITY_PCIBRI_BASE + 0x0000)
++#define PCIBRI_CMD		__REG(PKUNITY_PCIBRI_BASE + 0x0004)
++#define PCIBRI_CLASS		__REG(PKUNITY_PCIBRI_BASE + 0x0008)
++#define PCIBRI_LTR		__REG(PKUNITY_PCIBRI_BASE + 0x000C)
++#define PCIBRI_BAR0		__REG(PKUNITY_PCIBRI_BASE + 0x0010)
++#define PCIBRI_BAR1		__REG(PKUNITY_PCIBRI_BASE + 0x0014)
++#define PCIBRI_BAR2		__REG(PKUNITY_PCIBRI_BASE + 0x0018)
++#define PCIBRI_BAR3		__REG(PKUNITY_PCIBRI_BASE + 0x001C)
++#define PCIBRI_BAR4		__REG(PKUNITY_PCIBRI_BASE + 0x0020)
++#define PCIBRI_BAR5		__REG(PKUNITY_PCIBRI_BASE + 0x0024)
++
++#define PCIBRI_PCICTL0		__REG(PKUNITY_PCIBRI_BASE + 0x0100)
++#define PCIBRI_PCIBAR0		__REG(PKUNITY_PCIBRI_BASE + 0x0104)
++#define PCIBRI_PCIAMR0		__REG(PKUNITY_PCIBRI_BASE + 0x0108)
++#define PCIBRI_PCITAR0		__REG(PKUNITY_PCIBRI_BASE + 0x010C)
++#define PCIBRI_PCICTL1		__REG(PKUNITY_PCIBRI_BASE + 0x0110)
++#define PCIBRI_PCIBAR1		__REG(PKUNITY_PCIBRI_BASE + 0x0114)
++#define PCIBRI_PCIAMR1		__REG(PKUNITY_PCIBRI_BASE + 0x0118)
++#define PCIBRI_PCITAR1		__REG(PKUNITY_PCIBRI_BASE + 0x011C)
++#define PCIBRI_PCICTL2		__REG(PKUNITY_PCIBRI_BASE + 0x0120)
++#define PCIBRI_PCIBAR2		__REG(PKUNITY_PCIBRI_BASE + 0x0124)
++#define PCIBRI_PCIAMR2		__REG(PKUNITY_PCIBRI_BASE + 0x0128)
++#define PCIBRI_PCITAR2		__REG(PKUNITY_PCIBRI_BASE + 0x012C)
++#define PCIBRI_PCICTL3		__REG(PKUNITY_PCIBRI_BASE + 0x0130)
++#define PCIBRI_PCIBAR3		__REG(PKUNITY_PCIBRI_BASE + 0x0134)
++#define PCIBRI_PCIAMR3		__REG(PKUNITY_PCIBRI_BASE + 0x0138)
++#define PCIBRI_PCITAR3		__REG(PKUNITY_PCIBRI_BASE + 0x013C)
++#define PCIBRI_PCICTL4		__REG(PKUNITY_PCIBRI_BASE + 0x0140)
++#define PCIBRI_PCIBAR4		__REG(PKUNITY_PCIBRI_BASE + 0x0144)
++#define PCIBRI_PCIAMR4		__REG(PKUNITY_PCIBRI_BASE + 0x0148)
++#define PCIBRI_PCITAR4		__REG(PKUNITY_PCIBRI_BASE + 0x014C)
++#define PCIBRI_PCICTL5		__REG(PKUNITY_PCIBRI_BASE + 0x0150)
++#define PCIBRI_PCIBAR5		__REG(PKUNITY_PCIBRI_BASE + 0x0154)
++#define PCIBRI_PCIAMR5		__REG(PKUNITY_PCIBRI_BASE + 0x0158)
++#define PCIBRI_PCITAR5		__REG(PKUNITY_PCIBRI_BASE + 0x015C)
++
++#define PCIBRI_AHBCTL0		__REG(PKUNITY_PCIBRI_BASE + 0x0180)
++#define PCIBRI_AHBBAR0		__REG(PKUNITY_PCIBRI_BASE + 0x0184)
++#define PCIBRI_AHBAMR0		__REG(PKUNITY_PCIBRI_BASE + 0x0188)
++#define PCIBRI_AHBTAR0		__REG(PKUNITY_PCIBRI_BASE + 0x018C)
++#define PCIBRI_AHBCTL1		__REG(PKUNITY_PCIBRI_BASE + 0x0190)
++#define PCIBRI_AHBBAR1		__REG(PKUNITY_PCIBRI_BASE + 0x0194)
++#define PCIBRI_AHBAMR1		__REG(PKUNITY_PCIBRI_BASE + 0x0198)
++#define PCIBRI_AHBTAR1		__REG(PKUNITY_PCIBRI_BASE + 0x019C)
++#define PCIBRI_AHBCTL2		__REG(PKUNITY_PCIBRI_BASE + 0x01A0)
++#define PCIBRI_AHBBAR2		__REG(PKUNITY_PCIBRI_BASE + 0x01A4)
++#define PCIBRI_AHBAMR2		__REG(PKUNITY_PCIBRI_BASE + 0x01A8)
++#define PCIBRI_AHBTAR2		__REG(PKUNITY_PCIBRI_BASE + 0x01AC)
++#define PCIBRI_AHBCTL3		__REG(PKUNITY_PCIBRI_BASE + 0x01B0)
++#define PCIBRI_AHBBAR3		__REG(PKUNITY_PCIBRI_BASE + 0x01B4)
++#define PCIBRI_AHBAMR3		__REG(PKUNITY_PCIBRI_BASE + 0x01B8)
++#define PCIBRI_AHBTAR3		__REG(PKUNITY_PCIBRI_BASE + 0x01BC)
++#define PCIBRI_AHBCTL4		__REG(PKUNITY_PCIBRI_BASE + 0x01C0)
++#define PCIBRI_AHBBAR4		__REG(PKUNITY_PCIBRI_BASE + 0x01C4)
++#define PCIBRI_AHBAMR4		__REG(PKUNITY_PCIBRI_BASE + 0x01C8)
++#define PCIBRI_AHBTAR4		__REG(PKUNITY_PCIBRI_BASE + 0x01CC)
++#define PCIBRI_AHBCTL5		__REG(PKUNITY_PCIBRI_BASE + 0x01D0)
++#define PCIBRI_AHBBAR5		__REG(PKUNITY_PCIBRI_BASE + 0x01D4)
++#define PCIBRI_AHBAMR5		__REG(PKUNITY_PCIBRI_BASE + 0x01D8)
++#define PCIBRI_AHBTAR5		__REG(PKUNITY_PCIBRI_BASE + 0x01DC)
++
++#define PCIBRI_CTLx_AT          FIELD(1, 1, 2)
++#define PCIBRI_CTLx_PREF        FIELD(1, 1, 1)
++#define PCIBRI_CTLx_MRL         FIELD(1, 1, 0)
++
++#define PCIBRI_BARx_ADDR        FIELD(0xFFFFFFFC, 30, 2)
++#define PCIBRI_BARx_IO          FIELD(1, 1, 0)
++#define PCIBRI_BARx_MEM         FIELD(0, 1, 0)
++
++#define PCIBRI_CMD_IO           FIELD(1, 1, 0)
++#define PCIBRI_CMD_MEM          FIELD(1, 1, 1)
+diff --git a/arch/unicore32/include/mach/regs-pm.h b/arch/unicore32/include/mach/regs-pm.h
+new file mode 100644
+index 000000000000..ed2d2fc6ad0c
+--- /dev/null
++++ b/arch/unicore32/include/mach/regs-pm.h
+@@ -0,0 +1,126 @@
++/*
++ * PKUNITY Power Manager (PM) Registers
++ */
++/*
++ * PM Control Reg PM_PMCR
++ */
++#define PM_PMCR                 __REG(PKUNITY_PM_BASE + 0x0000)
++/*
++ * PM General Conf. Reg PM_PGCR
++ */
++#define PM_PGCR                 __REG(PKUNITY_PM_BASE + 0x0004)
++/*
++ * PM PLL Conf. Reg PM_PPCR
++ */
++#define PM_PPCR                 __REG(PKUNITY_PM_BASE + 0x0008)
++/*
++ * PM Wakeup Enable Reg PM_PWER
++ */
++#define PM_PWER                 __REG(PKUNITY_PM_BASE + 0x000C)
++/*
++ * PM GPIO Sleep Status Reg PM_PGSR
++ */
++#define PM_PGSR                 __REG(PKUNITY_PM_BASE + 0x0010)
++/*
++ * PM Clock Gate Reg PM_PCGR
++ */
++#define PM_PCGR                 __REG(PKUNITY_PM_BASE + 0x0014)
++/*
++ * PM SYS PLL Conf. Reg PM_PLLSYSCFG
++ */
++#define PM_PLLSYSCFG            __REG(PKUNITY_PM_BASE + 0x0018)
++/*
++ * PM DDR PLL Conf. Reg PM_PLLDDRCFG
++ */
++#define PM_PLLDDRCFG            __REG(PKUNITY_PM_BASE + 0x001C)
++/*
++ * PM VGA PLL Conf. Reg PM_PLLVGACFG
++ */
++#define PM_PLLVGACFG            __REG(PKUNITY_PM_BASE + 0x0020)
++/*
++ * PM Div Conf. Reg PM_DIVCFG
++ */
++#define PM_DIVCFG               __REG(PKUNITY_PM_BASE + 0x0024)
++/*
++ * PM SYS PLL Status Reg PM_PLLSYSSTATUS
++ */
++#define PM_PLLSYSSTATUS         __REG(PKUNITY_PM_BASE + 0x0028)
++/*
++ * PM DDR PLL Status Reg PM_PLLDDRSTATUS
++ */
++#define PM_PLLDDRSTATUS         __REG(PKUNITY_PM_BASE + 0x002C)
++/*
++ * PM VGA PLL Status Reg PM_PLLVGASTATUS
++ */
++#define PM_PLLVGASTATUS         __REG(PKUNITY_PM_BASE + 0x0030)
++/*
++ * PM Div Status Reg PM_DIVSTATUS
++ */
++#define PM_DIVSTATUS            __REG(PKUNITY_PM_BASE + 0x0034)
++/*
++ * PM Software Reset Reg PM_SWRESET
++ */
++#define PM_SWRESET              __REG(PKUNITY_PM_BASE + 0x0038)
++/*
++ * PM DDR2 PAD Start Reg PM_DDR2START
++ */
++#define PM_DDR2START            __REG(PKUNITY_PM_BASE + 0x003C)
++/*
++ * PM DDR2 PAD Status Reg PM_DDR2CAL0
++ */
++#define PM_DDR2CAL0             __REG(PKUNITY_PM_BASE + 0x0040)
++/*
++ * PM PLL DFC Done Reg PM_PLLDFCDONE
++ */
++#define PM_PLLDFCDONE           __REG(PKUNITY_PM_BASE + 0x0044)
++
++#define PM_PMCR_SFB             FIELD(1, 1, 0)
++#define PM_PMCR_IFB             FIELD(1, 1, 1)
++#define PM_PMCR_CFBSYS          FIELD(1, 1, 2)
++#define PM_PMCR_CFBDDR          FIELD(1, 1, 3)
++#define PM_PMCR_CFBVGA          FIELD(1, 1, 4)
++#define PM_PMCR_CFBDIVBCLK      FIELD(1, 1, 5)
++
++/*
++ * GPIO 8~27 wake-up enable PM_PWER_GPIOHIGH
++ */
++#define PM_PWER_GPIOHIGH        FIELD(1, 1, 8)
++/*
++ * RTC alarm wake-up enable PM_PWER_RTC
++ */
++#define PM_PWER_RTC             FIELD(1, 1, 31)
++
++#define PM_PCGR_BCLK64DDR	FIELD(1, 1, 0)
++#define PM_PCGR_BCLK64VGA	FIELD(1, 1, 1)
++#define PM_PCGR_BCLKDDR		FIELD(1, 1, 2)
++#define PM_PCGR_BCLKPCI		FIELD(1, 1, 4)
++#define PM_PCGR_BCLKDMAC	FIELD(1, 1, 5)
++#define PM_PCGR_BCLKUMAL	FIELD(1, 1, 6)
++#define PM_PCGR_BCLKUSB		FIELD(1, 1, 7)
++#define PM_PCGR_BCLKMME		FIELD(1, 1, 10)
++#define PM_PCGR_BCLKNAND	FIELD(1, 1, 11)
++#define PM_PCGR_BCLKH264E	FIELD(1, 1, 12)
++#define PM_PCGR_BCLKVGA		FIELD(1, 1, 13)
++#define PM_PCGR_BCLKH264D	FIELD(1, 1, 14)
++#define PM_PCGR_VECLK		FIELD(1, 1, 15)
++#define PM_PCGR_HECLK		FIELD(1, 1, 16)
++#define PM_PCGR_HDCLK		FIELD(1, 1, 17)
++#define PM_PCGR_NANDCLK		FIELD(1, 1, 18)
++#define PM_PCGR_GECLK		FIELD(1, 1, 19)
++#define PM_PCGR_VGACLK          FIELD(1, 1, 20)
++#define PM_PCGR_PCICLK		FIELD(1, 1, 21)
++#define PM_PCGR_SATACLK		FIELD(1, 1, 25)
++
++/*
++ * [23:20]PM_DIVCFG_VGACLK(v)
++ */
++#define PM_DIVCFG_VGACLK_MASK   FMASK(4, 20)
++#define PM_DIVCFG_VGACLK(v)	FIELD((v), 4, 20)
++
++#define PM_SWRESET_USB          FIELD(1, 1, 6)
++#define PM_SWRESET_VGADIV       FIELD(1, 1, 26)
++#define PM_SWRESET_GEDIV        FIELD(1, 1, 27)
++
++#define PM_PLLDFCDONE_SYSDFC    FIELD(1, 1, 0)
++#define PM_PLLDFCDONE_DDRDFC    FIELD(1, 1, 1)
++#define PM_PLLDFCDONE_VGADFC    FIELD(1, 1, 2)
+diff --git a/arch/unicore32/include/mach/regs-ps2.h b/arch/unicore32/include/mach/regs-ps2.h
+new file mode 100644
+index 000000000000..7da2071838ab
+--- /dev/null
++++ b/arch/unicore32/include/mach/regs-ps2.h
+@@ -0,0 +1,20 @@
++/*
++ * PKUnity PS2 Controller Registers
++ */
++/*
++ * the same as I8042_DATA_REG PS2_DATA
++ */
++#define PS2_DATA	__REG(PKUNITY_PS2_BASE + 0x0060)
++/*
++ * the same as I8042_COMMAND_REG PS2_COMMAND
++ */
++#define PS2_COMMAND	__REG(PKUNITY_PS2_BASE + 0x0064)
++/*
++ * the same as I8042_STATUS_REG PS2_STATUS
++ */
++#define PS2_STATUS	__REG(PKUNITY_PS2_BASE + 0x0064)
++/*
++ * counter reg PS2_CNT
++ */
++#define PS2_CNT		__REG(PKUNITY_PS2_BASE + 0x0068)
++
+diff --git a/arch/unicore32/include/mach/regs-resetc.h b/arch/unicore32/include/mach/regs-resetc.h
+new file mode 100644
+index 000000000000..17639898fd84
+--- /dev/null
++++ b/arch/unicore32/include/mach/regs-resetc.h
+@@ -0,0 +1,34 @@
++/*
++ * PKUnity Reset Controller (RC) Registers
++ */
++/*
++ * Software Reset Register
++ */
++#define RESETC_SWRR	__REG(PKUNITY_RESETC_BASE + 0x0000)
++/*
++ * Reset Status Register
++ */
++#define RESETC_RSSR	__REG(PKUNITY_RESETC_BASE + 0x0004)
++
++/*
++ * Software Reset Bit
++ */
++#define RESETC_SWRR_SRB		FIELD(1, 1, 0)
++
++/*
++ * Hardware Reset
++ */
++#define RESETC_RSSR_HWR		FIELD(1, 1, 0)
++/*
++ * Software Reset
++ */
++#define RESETC_RSSR_SWR		FIELD(1, 1, 1)
++/*
++ * Watchdog Reset
++ */
++#define RESETC_RSSR_WDR		FIELD(1, 1, 2)
++/*
++ * Sleep Mode Reset
++ */
++#define RESETC_RSSR_SMR		FIELD(1, 1, 3)
++
+diff --git a/arch/unicore32/include/mach/regs-rtc.h b/arch/unicore32/include/mach/regs-rtc.h
+new file mode 100644
+index 000000000000..155e38757186
+--- /dev/null
++++ b/arch/unicore32/include/mach/regs-rtc.h
+@@ -0,0 +1,37 @@
++/*
++ * PKUnity Real-Time Clock (RTC) control registers
++ */
++/*
++ * RTC Alarm Reg RTC_RTAR
++ */
++#define RTC_RTAR	__REG(PKUNITY_RTC_BASE + 0x0000)
++/*
++ * RTC Count Reg RTC_RCNR
++ */
++#define RTC_RCNR	__REG(PKUNITY_RTC_BASE + 0x0004)
++/*
++ * RTC Trim Reg RTC_RTTR
++ */
++#define RTC_RTTR	__REG(PKUNITY_RTC_BASE + 0x0008)
++/*
++ * RTC Status Reg RTC_RTSR
++ */
++#define RTC_RTSR	__REG(PKUNITY_RTC_BASE + 0x0010)
++
++/*
++ * ALarm detected RTC_RTSR_AL
++ */
++#define RTC_RTSR_AL		FIELD(1, 1, 0)
++/*
++ * 1 Hz clock detected RTC_RTSR_HZ
++ */
++#define RTC_RTSR_HZ		FIELD(1, 1, 1)
++/*
++ * ALarm interrupt Enable RTC_RTSR_ALE
++ */
++#define RTC_RTSR_ALE		FIELD(1, 1, 2)
++/*
++ * 1 Hz clock interrupt Enable RTC_RTSR_HZE
++ */
++#define RTC_RTSR_HZE		FIELD(1, 1, 3)
++
+diff --git a/arch/unicore32/include/mach/regs-sdc.h b/arch/unicore32/include/mach/regs-sdc.h
+new file mode 100644
+index 000000000000..3457b88c453c
+--- /dev/null
++++ b/arch/unicore32/include/mach/regs-sdc.h
+@@ -0,0 +1,156 @@
++/*
++ * PKUnity Multi-Media Card and Security Digital Card (MMC/SD) Registers
++ */
++/*
++ * Clock Control Reg SDC_CCR
++ */
++#define SDC_CCR		__REG(PKUNITY_SDC_BASE + 0x0000)
++/*
++ * Software Reset Reg SDC_SRR
++ */
++#define SDC_SRR		__REG(PKUNITY_SDC_BASE + 0x0004)
++/*
++ * Argument Reg SDC_ARGUMENT
++ */
++#define SDC_ARGUMENT	__REG(PKUNITY_SDC_BASE + 0x0008)
++/*
++ * Command Reg SDC_COMMAND
++ */
++#define SDC_COMMAND	__REG(PKUNITY_SDC_BASE + 0x000C)
++/*
++ * Block Size Reg SDC_BLOCKSIZE
++ */
++#define SDC_BLOCKSIZE	__REG(PKUNITY_SDC_BASE + 0x0010)
++/*
++ * Block Cound Reg SDC_BLOCKCOUNT
++ */
++#define SDC_BLOCKCOUNT	__REG(PKUNITY_SDC_BASE + 0x0014)
++/*
++ * Transfer Mode Reg SDC_TMR
++ */
++#define SDC_TMR		__REG(PKUNITY_SDC_BASE + 0x0018)
++/*
++ * Response Reg. 0 SDC_RES0
++ */
++#define SDC_RES0	__REG(PKUNITY_SDC_BASE + 0x001C)
++/*
++ * Response Reg. 1 SDC_RES1
++ */
++#define SDC_RES1	__REG(PKUNITY_SDC_BASE + 0x0020)
++/*
++ * Response Reg. 2 SDC_RES2
++ */
++#define SDC_RES2	__REG(PKUNITY_SDC_BASE + 0x0024)
++/*
++ * Response Reg. 3 SDC_RES3
++ */
++#define SDC_RES3	__REG(PKUNITY_SDC_BASE + 0x0028)
++/*
++ * Read Timeout Control Reg SDC_RTCR
++ */
++#define SDC_RTCR	__REG(PKUNITY_SDC_BASE + 0x002C)
++/*
++ * Interrupt Status Reg SDC_ISR
++ */
++#define SDC_ISR		__REG(PKUNITY_SDC_BASE + 0x0030)
++/*
++ * Interrupt Status Mask Reg SDC_ISMR
++ */
++#define SDC_ISMR	__REG(PKUNITY_SDC_BASE + 0x0034)
++/*
++ * RX FIFO SDC_RXFIFO
++ */
++#define SDC_RXFIFO	__REG(PKUNITY_SDC_BASE + 0x0038)
++/*
++ * TX FIFO SDC_TXFIFO
++ */
++#define SDC_TXFIFO	__REG(PKUNITY_SDC_BASE + 0x003C)
++
++/*
++ * SD Clock Enable SDC_CCR_CLKEN
++ */
++#define SDC_CCR_CLKEN			FIELD(1, 1, 2)
++/*
++ * [15:8] SDC_CCR_PDIV(v)
++ */
++#define SDC_CCR_PDIV(v)			FIELD((v), 8, 8)
++
++/*
++ * Software reset enable SDC_SRR_ENABLE
++ */
++#define SDC_SRR_ENABLE			FIELD(0, 1, 0)
++/*
++ * Software reset disable SDC_SRR_DISABLE
++ */
++#define SDC_SRR_DISABLE			FIELD(1, 1, 0)
++
++/*
++ * Response type SDC_COMMAND_RESTYPE_MASK
++ */
++#define SDC_COMMAND_RESTYPE_MASK	FMASK(2, 0)
++/*
++ * No response SDC_COMMAND_RESTYPE_NONE
++ */
++#define SDC_COMMAND_RESTYPE_NONE	FIELD(0, 2, 0)
++/*
++ * 136-bit long response SDC_COMMAND_RESTYPE_LONG
++ */
++#define SDC_COMMAND_RESTYPE_LONG	FIELD(1, 2, 0)
++/*
++ * 48-bit short response SDC_COMMAND_RESTYPE_SHORT
++ */
++#define SDC_COMMAND_RESTYPE_SHORT	FIELD(2, 2, 0)
++/*
++ * 48-bit short and test if busy response SDC_COMMAND_RESTYPE_SHORTBUSY
++ */
++#define SDC_COMMAND_RESTYPE_SHORTBUSY	FIELD(3, 2, 0)
++/*
++ * data ready SDC_COMMAND_DATAREADY
++ */
++#define SDC_COMMAND_DATAREADY		FIELD(1, 1, 2)
++#define SDC_COMMAND_CMDEN		FIELD(1, 1, 3)
++/*
++ * [10:5] SDC_COMMAND_CMDINDEX(v)
++ */
++#define SDC_COMMAND_CMDINDEX(v)		FIELD((v), 6, 5)
++
++/*
++ * [10:0] SDC_BLOCKSIZE_BSMASK(v)
++ */
++#define SDC_BLOCKSIZE_BSMASK(v)		FIELD((v), 11, 0)
++/*
++ * [11:0] SDC_BLOCKCOUNT_BCMASK(v)
++ */
++#define SDC_BLOCKCOUNT_BCMASK(v)	FIELD((v), 12, 0)
++
++/*
++ * Data Width 1bit SDC_TMR_WTH_1BIT
++ */
++#define SDC_TMR_WTH_1BIT		FIELD(0, 1, 0)
++/*
++ * Data Width 4bit SDC_TMR_WTH_4BIT
++ */
++#define SDC_TMR_WTH_4BIT		FIELD(1, 1, 0)
++/*
++ * Read SDC_TMR_DIR_READ
++ */
++#define SDC_TMR_DIR_READ		FIELD(0, 1, 1)
++/*
++ * Write SDC_TMR_DIR_WRITE
++ */
++#define SDC_TMR_DIR_WRITE		FIELD(1, 1, 1)
++
++#define SDC_IR_MASK			FMASK(13, 0)
++#define SDC_IR_RESTIMEOUT		FIELD(1, 1, 0)
++#define SDC_IR_WRITECRC			FIELD(1, 1, 1)
++#define SDC_IR_READCRC			FIELD(1, 1, 2)
++#define SDC_IR_TXFIFOREAD		FIELD(1, 1, 3)
++#define SDC_IR_RXFIFOWRITE		FIELD(1, 1, 4)
++#define SDC_IR_READTIMEOUT		FIELD(1, 1, 5)
++#define SDC_IR_DATACOMPLETE		FIELD(1, 1, 6)
++#define SDC_IR_CMDCOMPLETE		FIELD(1, 1, 7)
++#define SDC_IR_RXFIFOFULL		FIELD(1, 1, 8)
++#define SDC_IR_RXFIFOEMPTY		FIELD(1, 1, 9)
++#define SDC_IR_TXFIFOFULL		FIELD(1, 1, 10)
++#define SDC_IR_TXFIFOEMPTY		FIELD(1, 1, 11)
++#define SDC_IR_ENDCMDWITHRES		FIELD(1, 1, 12)
+diff --git a/arch/unicore32/include/mach/regs-spi.h b/arch/unicore32/include/mach/regs-spi.h
+new file mode 100644
+index 000000000000..cadc713c55b9
+--- /dev/null
++++ b/arch/unicore32/include/mach/regs-spi.h
+@@ -0,0 +1,98 @@
++/*
++ * PKUnity Serial Peripheral Interface (SPI) Registers
++ */
++/*
++ * Control reg. 0 SPI_CR0
++ */
++#define SPI_CR0		__REG(PKUNITY_SPI_BASE + 0x0000)
++/*
++ * Control reg. 1 SPI_CR1
++ */
++#define SPI_CR1		__REG(PKUNITY_SPI_BASE + 0x0004)
++/*
++ * Enable reg SPI_SSIENR
++ */
++#define SPI_SSIENR	__REG(PKUNITY_SPI_BASE + 0x0008)
++/*
++ * Status reg SPI_SR
++ */
++#define SPI_SR		__REG(PKUNITY_SPI_BASE + 0x0028)
++/*
++ * Interrupt Mask reg SPI_IMR
++ */
++#define SPI_IMR		__REG(PKUNITY_SPI_BASE + 0x002C)
++/*
++ * Interrupt Status reg SPI_ISR
++ */
++#define SPI_ISR		__REG(PKUNITY_SPI_BASE + 0x0030)
++
++/*
++ * Enable SPI Controller SPI_SSIENR_EN
++ */
++#define SPI_SSIENR_EN		FIELD(1, 1, 0)
++
++/*
++ * SPI Busy SPI_SR_BUSY
++ */
++#define SPI_SR_BUSY		FIELD(1, 1, 0)
++/*
++ * Transmit FIFO Not Full SPI_SR_TFNF
++ */
++#define SPI_SR_TFNF		FIELD(1, 1, 1)
++/*
++ * Transmit FIFO Empty SPI_SR_TFE
++ */
++#define SPI_SR_TFE		FIELD(1, 1, 2)
++/*
++ * Receive FIFO Not Empty SPI_SR_RFNE
++ */
++#define SPI_SR_RFNE		FIELD(1, 1, 3)
++/*
++ * Receive FIFO Full SPI_SR_RFF
++ */
++#define SPI_SR_RFF		FIELD(1, 1, 4)
++
++/*
++ * Trans. FIFO Empty Interrupt Status SPI_ISR_TXEIS
++ */
++#define SPI_ISR_TXEIS		FIELD(1, 1, 0)
++/*
++ * Trans. FIFO Overflow Interrupt Status SPI_ISR_TXOIS
++ */
++#define SPI_ISR_TXOIS		FIELD(1, 1, 1)
++/*
++ * Receiv. FIFO Underflow Interrupt Status SPI_ISR_RXUIS
++ */
++#define SPI_ISR_RXUIS		FIELD(1, 1, 2)
++/*
++ * Receiv. FIFO Overflow Interrupt Status SPI_ISR_RXOIS
++ */
++#define SPI_ISR_RXOIS		FIELD(1, 1, 3)
++/*
++ * Receiv. FIFO Full Interrupt Status SPI_ISR_RXFIS
++ */
++#define SPI_ISR_RXFIS		FIELD(1, 1, 4)
++#define SPI_ISR_MSTIS		FIELD(1, 1, 5)
++
++/*
++ * Trans. FIFO Empty Interrupt Mask SPI_IMR_TXEIM
++ */
++#define SPI_IMR_TXEIM		FIELD(1, 1, 0)
++/*
++ * Trans. FIFO Overflow Interrupt Mask SPI_IMR_TXOIM
++ */
++#define SPI_IMR_TXOIM		FIELD(1, 1, 1)
++/*
++ * Receiv. FIFO Underflow Interrupt Mask SPI_IMR_RXUIM
++ */
++#define SPI_IMR_RXUIM		FIELD(1, 1, 2)
++/*
++ * Receiv. FIFO Overflow Interrupt Mask SPI_IMR_RXOIM
++ */
++#define SPI_IMR_RXOIM		FIELD(1, 1, 3)
++/*
++ * Receiv. FIFO Full Interrupt Mask SPI_IMR_RXFIM
++ */
++#define SPI_IMR_RXFIM		FIELD(1, 1, 4)
++#define SPI_IMR_MSTIM		FIELD(1, 1, 5)
++
+diff --git a/arch/unicore32/include/mach/regs-uart.h b/arch/unicore32/include/mach/regs-uart.h
+new file mode 100644
+index 000000000000..9fa6b1938b77
+--- /dev/null
++++ b/arch/unicore32/include/mach/regs-uart.h
+@@ -0,0 +1,3 @@
++/*
++ * PKUnity Universal Asynchronous Receiver/Transmitter (UART) Registers
++ */
+diff --git a/arch/unicore32/include/mach/regs-umal.h b/arch/unicore32/include/mach/regs-umal.h
+new file mode 100644
+index 000000000000..2e718d1e86cc
+--- /dev/null
++++ b/arch/unicore32/include/mach/regs-umal.h
+@@ -0,0 +1,229 @@
++/*
++ * PKUnity Ultra Media Access Layer (UMAL) Ethernet MAC Registers
++ */
++
++/* MAC module of UMAL */
++/* UMAL's MAC module includes G/MII interface, several additional PHY
++ * interfaces, and MAC control sub-layer, which provides support for control
++ * frames (e.g. PAUSE frames).
++ */
++/*
++ * TX/RX reset and control UMAL_CFG1
++ */
++#define UMAL_CFG1		__REG(PKUNITY_UMAL_BASE + 0x0000)
++/*
++ * MAC interface mode control UMAL_CFG2
++ */
++#define UMAL_CFG2		__REG(PKUNITY_UMAL_BASE + 0x0004)
++/*
++ * Inter Packet/Frame Gap UMAL_IPGIFG
++ */
++#define UMAL_IPGIFG		__REG(PKUNITY_UMAL_BASE + 0x0008)
++/*
++ * Collision retry or backoff UMAL_HALFDUPLEX
++ */
++#define UMAL_HALFDUPLEX		__REG(PKUNITY_UMAL_BASE + 0x000c)
++/*
++ * Maximum Frame Length UMAL_MAXFRAME
++ */
++#define UMAL_MAXFRAME		__REG(PKUNITY_UMAL_BASE + 0x0010)
++/*
++ * Test Regsiter UMAL_TESTREG
++ */
++#define UMAL_TESTREG		__REG(PKUNITY_UMAL_BASE + 0x001c)
++/*
++ * MII Management Configure UMAL_MIICFG
++ */
++#define UMAL_MIICFG		__REG(PKUNITY_UMAL_BASE + 0x0020)
++/*
++ * MII Management Command UMAL_MIICMD
++ */
++#define UMAL_MIICMD		__REG(PKUNITY_UMAL_BASE + 0x0024)
++/*
++ * MII Management Address UMAL_MIIADDR
++ */
++#define UMAL_MIIADDR		__REG(PKUNITY_UMAL_BASE + 0x0028)
++/*
++ * MII Management Control UMAL_MIICTRL
++ */
++#define UMAL_MIICTRL		__REG(PKUNITY_UMAL_BASE + 0x002c)
++/*
++ * MII Management Status UMAL_MIISTATUS
++ */
++#define UMAL_MIISTATUS		__REG(PKUNITY_UMAL_BASE + 0x0030)
++/*
++ * MII Managment Indicator UMAL_MIIIDCT
++ */
++#define UMAL_MIIIDCT		__REG(PKUNITY_UMAL_BASE + 0x0034)
++/*
++ * Interface Control UMAL_IFCTRL
++ */
++#define UMAL_IFCTRL		__REG(PKUNITY_UMAL_BASE + 0x0038)
++/*
++ * Interface Status UMAL_IFSTATUS
++ */
++#define UMAL_IFSTATUS		__REG(PKUNITY_UMAL_BASE + 0x003c)
++/*
++ * MAC address (high 4 bytes) UMAL_STADDR1
++ */
++#define UMAL_STADDR1		__REG(PKUNITY_UMAL_BASE + 0x0040)
++/*
++ * MAC address (low 2 bytes) UMAL_STADDR2
++ */
++#define UMAL_STADDR2		__REG(PKUNITY_UMAL_BASE + 0x0044)
++
++/* FIFO MODULE OF UMAL */
++/* UMAL's FIFO module provides data queuing for increased system level
++ * throughput
++ */
++#define UMAL_FIFOCFG0		__REG(PKUNITY_UMAL_BASE + 0x0048)
++#define UMAL_FIFOCFG1		__REG(PKUNITY_UMAL_BASE + 0x004c)
++#define UMAL_FIFOCFG2		__REG(PKUNITY_UMAL_BASE + 0x0050)
++#define UMAL_FIFOCFG3		__REG(PKUNITY_UMAL_BASE + 0x0054)
++#define UMAL_FIFOCFG4		__REG(PKUNITY_UMAL_BASE + 0x0058)
++#define UMAL_FIFOCFG5		__REG(PKUNITY_UMAL_BASE + 0x005c)
++#define UMAL_FIFORAM0		__REG(PKUNITY_UMAL_BASE + 0x0060)
++#define UMAL_FIFORAM1		__REG(PKUNITY_UMAL_BASE + 0x0064)
++#define UMAL_FIFORAM2		__REG(PKUNITY_UMAL_BASE + 0x0068)
++#define UMAL_FIFORAM3		__REG(PKUNITY_UMAL_BASE + 0x006c)
++#define UMAL_FIFORAM4		__REG(PKUNITY_UMAL_BASE + 0x0070)
++#define UMAL_FIFORAM5		__REG(PKUNITY_UMAL_BASE + 0x0074)
++#define UMAL_FIFORAM6		__REG(PKUNITY_UMAL_BASE + 0x0078)
++#define UMAL_FIFORAM7		__REG(PKUNITY_UMAL_BASE + 0x007c)
++
++/* MAHBE MODUEL OF UMAL */
++/* UMAL's MAHBE module interfaces to the host system through 32-bit AHB Master
++ * and Slave ports.Registers within the M-AHBE provide Control and Status
++ * information concerning these transfers.
++ */
++/*
++ * Transmit Control UMAL_DMATxCtrl
++ */
++#define UMAL_DMATxCtrl		__REG(PKUNITY_UMAL_BASE + 0x0180)
++/*
++ * Pointer to TX Descripter UMAL_DMATxDescriptor
++ */
++#define UMAL_DMATxDescriptor	__REG(PKUNITY_UMAL_BASE + 0x0184)
++/*
++ * Status of Tx Packet Transfers UMAL_DMATxStatus
++ */
++#define UMAL_DMATxStatus	__REG(PKUNITY_UMAL_BASE + 0x0188)
++/*
++ * Receive Control UMAL_DMARxCtrl
++ */
++#define UMAL_DMARxCtrl		__REG(PKUNITY_UMAL_BASE + 0x018c)
++/*
++ * Pointer to Rx Descriptor UMAL_DMARxDescriptor
++ */
++#define UMAL_DMARxDescriptor	__REG(PKUNITY_UMAL_BASE + 0x0190)
++/*
++ * Status of Rx Packet Transfers UMAL_DMARxStatus
++ */
++#define UMAL_DMARxStatus	__REG(PKUNITY_UMAL_BASE + 0x0194)
++/*
++ * Interrupt Mask UMAL_DMAIntrMask
++ */
++#define UMAL_DMAIntrMask	__REG(PKUNITY_UMAL_BASE + 0x0198)
++/*
++ * Interrupts, read only UMAL_DMAInterrupt
++ */
++#define UMAL_DMAInterrupt	__REG(PKUNITY_UMAL_BASE + 0x019c)
++
++/*
++ * Commands for UMAL_CFG1 register
++ */
++#define UMAL_CFG1_TXENABLE	FIELD(1, 1, 0)
++#define UMAL_CFG1_RXENABLE	FIELD(1, 1, 2)
++#define UMAL_CFG1_TXFLOWCTL	FIELD(1, 1, 4)
++#define UMAL_CFG1_RXFLOWCTL	FIELD(1, 1, 5)
++#define UMAL_CFG1_CONFLPBK	FIELD(1, 1, 8)
++#define UMAL_CFG1_RESET		FIELD(1, 1, 31)
++#define UMAL_CFG1_CONFFLCTL	(MAC_TX_FLOW_CTL | MAC_RX_FLOW_CTL)
++
++/*
++ * Commands for UMAL_CFG2 register
++ */
++#define UMAL_CFG2_FULLDUPLEX	FIELD(1, 1, 0)
++#define UMAL_CFG2_CRCENABLE	FIELD(1, 1, 1)
++#define UMAL_CFG2_PADCRC	FIELD(1, 1, 2)
++#define UMAL_CFG2_LENGTHCHECK	FIELD(1, 1, 4)
++#define UMAL_CFG2_MODEMASK	FMASK(2, 8)
++#define UMAL_CFG2_NIBBLEMODE	FIELD(1, 2, 8)
++#define UMAL_CFG2_BYTEMODE	FIELD(2, 2, 8)
++#define UMAL_CFG2_PREAMBLENMASK	FMASK(4, 12)
++#define UMAL_CFG2_DEFPREAMBLEN	FIELD(7, 4, 12)
++#define UMAL_CFG2_FD100		(UMAL_CFG2_DEFPREAMBLEN | UMAL_CFG2_NIBBLEMODE \
++				| UMAL_CFG2_LENGTHCHECK | UMAL_CFG2_PADCRC \
++				| UMAL_CFG2_CRCENABLE | UMAL_CFG2_FULLDUPLEX)
++#define UMAL_CFG2_FD1000	(UMAL_CFG2_DEFPREAMBLEN | UMAL_CFG2_BYTEMODE \
++				| UMAL_CFG2_LENGTHCHECK | UMAL_CFG2_PADCRC \
++				| UMAL_CFG2_CRCENABLE | UMAL_CFG2_FULLDUPLEX)
++#define UMAL_CFG2_HD100		(UMAL_CFG2_DEFPREAMBLEN | UMAL_CFG2_NIBBLEMODE \
++				| UMAL_CFG2_LENGTHCHECK | UMAL_CFG2_PADCRC \
++				| UMAL_CFG2_CRCENABLE)
++
++/*
++ * Command for UMAL_IFCTRL register
++ */
++#define UMAL_IFCTRL_RESET	FIELD(1, 1, 31)
++
++/*
++ * Command for UMAL_MIICFG register
++ */
++#define UMAL_MIICFG_RESET	FIELD(1, 1, 31)
++
++/*
++ * Command for UMAL_MIICMD register
++ */
++#define UMAL_MIICMD_READ	FIELD(1, 1, 0)
++
++/*
++ * Command for UMAL_MIIIDCT register
++ */
++#define UMAL_MIIIDCT_BUSY	FIELD(1, 1, 0)
++#define UMAL_MIIIDCT_NOTVALID	FIELD(1, 1, 2)
++
++/*
++ * Commands for DMATxCtrl regesters
++ */
++#define UMAL_DMA_Enable		FIELD(1, 1, 0)
++
++/*
++ * Commands for DMARxCtrl regesters
++ */
++#define UMAL_DMAIntrMask_ENABLEHALFWORD	FIELD(1, 1, 16)
++
++/*
++ * Command for DMARxStatus
++ */
++#define CLR_RX_BUS_ERR		FIELD(1, 1, 3)
++#define CLR_RX_OVERFLOW		FIELD(1, 1, 2)
++#define CLR_RX_PKT		FIELD(1, 1, 0)
++
++/*
++ * Command for DMATxStatus
++ */
++#define CLR_TX_BUS_ERR		FIELD(1, 1, 3)
++#define CLR_TX_UNDERRUN		FIELD(1, 1, 1)
++#define CLR_TX_PKT		FIELD(1, 1, 0)
++
++/*
++ * Commands for DMAIntrMask and DMAInterrupt register
++ */
++#define INT_RX_MASK		FIELD(0xd, 4, 4)
++#define INT_TX_MASK		FIELD(0xb, 4, 0)
++
++#define INT_RX_BUS_ERR		FIELD(1, 1, 7)
++#define INT_RX_OVERFLOW		FIELD(1, 1, 6)
++#define INT_RX_PKT		FIELD(1, 1, 4)
++#define INT_TX_BUS_ERR		FIELD(1, 1, 3)
++#define INT_TX_UNDERRUN		FIELD(1, 1, 1)
++#define INT_TX_PKT		FIELD(1, 1, 0)
++
++/*
++ * MARCOS of UMAL's descriptors
++ */
++#define UMAL_DESC_PACKETSIZE_EMPTY	FIELD(1, 1, 31)
++#define UMAL_DESC_PACKETSIZE_NONEMPTY	FIELD(0, 1, 31)
++#define UMAL_DESC_PACKETSIZE_SIZEMASK	FMASK(12, 0)
++
+diff --git a/arch/unicore32/include/mach/regs-unigfx.h b/arch/unicore32/include/mach/regs-unigfx.h
+new file mode 100644
+index 000000000000..58bbd540a393
+--- /dev/null
++++ b/arch/unicore32/include/mach/regs-unigfx.h
+@@ -0,0 +1,200 @@
++/*
++ * PKUnity UNIGFX Registers
++ */
++
++#define UDE_BASE      (PKUNITY_UNIGFX_BASE + 0x1400)
++#define UGE_BASE      (PKUNITY_UNIGFX_BASE + 0x0000)
++
++/*
++ * command reg for UNIGFX DE
++ */
++/*
++ * control reg UDE_CFG
++ */
++#define UDE_CFG       __REG(UDE_BASE + 0x0000)
++/*
++ * framebuffer start address reg UDE_FSA
++ */
++#define UDE_FSA       __REG(UDE_BASE + 0x0004)
++/*
++ * line size reg UDE_LS
++ */
++#define UDE_LS        __REG(UDE_BASE + 0x0008)
++/*
++ * pitch size reg UDE_PS
++ */
++#define UDE_PS        __REG(UDE_BASE + 0x000C)
++/*
++ * horizontal active time reg UDE_HAT
++ */
++#define UDE_HAT       __REG(UDE_BASE + 0x0010)
++/*
++ * horizontal blank time reg UDE_HBT
++ */
++#define UDE_HBT       __REG(UDE_BASE + 0x0014)
++/*
++ * horizontal sync time reg UDE_HST
++ */
++#define UDE_HST       __REG(UDE_BASE + 0x0018)
++/*
++ * vertival active time reg UDE_VAT
++ */
++#define UDE_VAT       __REG(UDE_BASE + 0x001C)
++/*
++ * vertival blank time reg UDE_VBT
++ */
++#define UDE_VBT       __REG(UDE_BASE + 0x0020)
++/*
++ * vertival sync time reg UDE_VST
++ */
++#define UDE_VST       __REG(UDE_BASE + 0x0024)
++/*
++ * cursor position UDE_CXY
++ */
++#define UDE_CXY       __REG(UDE_BASE + 0x0028)
++/*
++ * cursor front color UDE_CC0
++ */
++#define UDE_CC0       __REG(UDE_BASE + 0x002C)
++/*
++ * cursor background color UDE_CC1
++ */
++#define UDE_CC1       __REG(UDE_BASE + 0x0030)
++/*
++ * video position UDE_VXY
++ */
++#define UDE_VXY       __REG(UDE_BASE + 0x0034)
++/*
++ * video start address reg UDE_VSA
++ */
++#define UDE_VSA       __REG(UDE_BASE + 0x0040)
++/*
++ * video size reg UDE_VS
++ */
++#define UDE_VS        __REG(UDE_BASE + 0x004C)
++
++/*
++ * command reg for UNIGFX GE
++ */
++/*
++ * src xy reg UGE_SRCXY
++ */
++#define UGE_SRCXY     __REG(UGE_BASE + 0x0000)
++/*
++ * dst xy reg UGE_DSTXY
++ */
++#define UGE_DSTXY     __REG(UGE_BASE + 0x0004)
++/*
++ * pitch reg UGE_PITCH
++ */
++#define UGE_PITCH     __REG(UGE_BASE + 0x0008)
++/*
++ * src start reg UGE_SRCSTART
++ */
++#define UGE_SRCSTART  __REG(UGE_BASE + 0x000C)
++/*
++ * dst start reg UGE_DSTSTART
++ */
++#define UGE_DSTSTART  __REG(UGE_BASE + 0x0010)
++/*
++ * width height reg UGE_WIDHEIGHT
++ */
++#define UGE_WIDHEIGHT __REG(UGE_BASE + 0x0014)
++/*
++ * rop alpah reg UGE_ROPALPHA
++ */
++#define UGE_ROPALPHA  __REG(UGE_BASE + 0x0018)
++/*
++ * front color UGE_FCOLOR
++ */
++#define UGE_FCOLOR    __REG(UGE_BASE + 0x001C)
++/*
++ * background color UGE_BCOLOR
++ */
++#define UGE_BCOLOR    __REG(UGE_BASE + 0x0020)
++/*
++ * src color key for high value UGE_SCH
++ */
++#define UGE_SCH       __REG(UGE_BASE + 0x0024)
++/*
++ * dst color key for high value UGE_DCH
++ */
++#define UGE_DCH       __REG(UGE_BASE + 0x0028)
++/*
++ * src color key for low value UGE_SCL
++ */
++#define UGE_SCL       __REG(UGE_BASE + 0x002C)
++/*
++ * dst color key for low value UGE_DCL
++ */
++#define UGE_DCL       __REG(UGE_BASE + 0x0030)
++/*
++ * clip 0 reg UGE_CLIP0
++ */
++#define UGE_CLIP0     __REG(UGE_BASE + 0x0034)
++/*
++ * clip 1 reg UGE_CLIP1
++ */
++#define UGE_CLIP1     __REG(UGE_BASE + 0x0038)
++/*
++ * command reg UGE_COMMAND
++ */
++#define UGE_COMMAND   __REG(UGE_BASE + 0x003C)
++/*
++ * pattern 0 UGE_P0
++ */
++#define UGE_P0        __REG(UGE_BASE + 0x0040)
++#define UGE_P1        __REG(UGE_BASE + 0x0044)
++#define UGE_P2        __REG(UGE_BASE + 0x0048)
++#define UGE_P3        __REG(UGE_BASE + 0x004C)
++#define UGE_P4        __REG(UGE_BASE + 0x0050)
++#define UGE_P5        __REG(UGE_BASE + 0x0054)
++#define UGE_P6        __REG(UGE_BASE + 0x0058)
++#define UGE_P7        __REG(UGE_BASE + 0x005C)
++#define UGE_P8        __REG(UGE_BASE + 0x0060)
++#define UGE_P9        __REG(UGE_BASE + 0x0064)
++#define UGE_P10       __REG(UGE_BASE + 0x0068)
++#define UGE_P11       __REG(UGE_BASE + 0x006C)
++#define UGE_P12       __REG(UGE_BASE + 0x0070)
++#define UGE_P13       __REG(UGE_BASE + 0x0074)
++#define UGE_P14       __REG(UGE_BASE + 0x0078)
++#define UGE_P15       __REG(UGE_BASE + 0x007C)
++#define UGE_P16       __REG(UGE_BASE + 0x0080)
++#define UGE_P17       __REG(UGE_BASE + 0x0084)
++#define UGE_P18       __REG(UGE_BASE + 0x0088)
++#define UGE_P19       __REG(UGE_BASE + 0x008C)
++#define UGE_P20       __REG(UGE_BASE + 0x0090)
++#define UGE_P21       __REG(UGE_BASE + 0x0094)
++#define UGE_P22       __REG(UGE_BASE + 0x0098)
++#define UGE_P23       __REG(UGE_BASE + 0x009C)
++#define UGE_P24       __REG(UGE_BASE + 0x00A0)
++#define UGE_P25       __REG(UGE_BASE + 0x00A4)
++#define UGE_P26       __REG(UGE_BASE + 0x00A8)
++#define UGE_P27       __REG(UGE_BASE + 0x00AC)
++#define UGE_P28       __REG(UGE_BASE + 0x00B0)
++#define UGE_P29       __REG(UGE_BASE + 0x00B4)
++#define UGE_P30       __REG(UGE_BASE + 0x00B8)
++#define UGE_P31       __REG(UGE_BASE + 0x00BC)
++
++#define UDE_CFG_DST_MASK	FMASK(2, 8)
++#define UDE_CFG_DST8            FIELD(0x0, 2, 8)
++#define UDE_CFG_DST16           FIELD(0x1, 2, 8)
++#define UDE_CFG_DST24           FIELD(0x2, 2, 8)
++#define UDE_CFG_DST32           FIELD(0x3, 2, 8)
++
++/*
++ * GDEN enable UDE_CFG_GDEN_ENABLE
++ */
++#define UDE_CFG_GDEN_ENABLE     FIELD(1, 1, 3)
++/*
++ * VDEN enable UDE_CFG_VDEN_ENABLE
++ */
++#define UDE_CFG_VDEN_ENABLE     FIELD(1, 1, 4)
++/*
++ * CDEN enable UDE_CFG_CDEN_ENABLE
++ */
++#define UDE_CFG_CDEN_ENABLE     FIELD(1, 1, 5)
++/*
++ * TIMEUP enable UDE_CFG_TIMEUP_ENABLE
++ */
++#define UDE_CFG_TIMEUP_ENABLE   FIELD(1, 1, 6)

commit fa7499ef77db8d535e3c609c8064e9ee50c0693c
+Author: GuanXuetao 
+Date:   Sat Feb 26 19:51:18 2011 +0800
+
+    unicore32 machine related files: core files
+    
+    This patch adds machine related core files, also including build infrastructure.
+    
+    Signed-off-by: Guan Xuetao 
+    Reviewed-by: Arnd Bergmann 
+
+diff --git a/arch/unicore32/Kconfig b/arch/unicore32/Kconfig
+index cc6a83215881..90835c959476 100644
+--- a/arch/unicore32/Kconfig
++++ b/arch/unicore32/Kconfig
+@@ -231,6 +231,31 @@ config PUV3_RTC
+ 	tristate "PKUnity v3 RTC Support"
+ 	depends on !ARCH_FPGA
+ 
++if PUV3_NB0916
++
++menu "PKUnity NetBook-0916 Features"
++
++config I2C_BATTERY_BQ27200
++	tristate "I2C Battery BQ27200 Support"
++	select PUV3_I2C
++	select POWER_SUPPLY
++	select BATTERY_BQ27x00
++
++config I2C_EEPROM_AT24
++	tristate "I2C EEPROMs AT24 support"
++	select PUV3_I2C
++	select MISC_DEVICES
++	select EEPROM_AT24
++
++config LCD_BACKLIGHT
++	tristate "LCD Backlight support"
++	select BACKLIGHT_LCD_SUPPORT
++	select BACKLIGHT_PWM
++
++endmenu
++
++endif
++
+ endif
+ 
+ source "drivers/Kconfig"
+diff --git a/arch/unicore32/kernel/puv3-core.c b/arch/unicore32/kernel/puv3-core.c
+new file mode 100644
+index 000000000000..26cc52b51e7b
+--- /dev/null
++++ b/arch/unicore32/kernel/puv3-core.c
+@@ -0,0 +1,270 @@
++/*
++ *  linux/arch/unicore32/kernel/puv3-core.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ *	Maintained by GUAN Xue-tao 
++ *	Copyright (C) 2001-2010 Guan Xuetao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++#include 
++#include 
++
++/*
++ * This is the PKUnity sched_clock implementation.  This has
++ * a resolution of 271ns, and a maximum value of 32025597s (370 days).
++ *
++ * The return value is guaranteed to be monotonic in that range as
++ * long as there is always less than 582 seconds between successive
++ * calls to this function.
++ *
++ *  ( * 1E9 / CLOCK_TICK_RATE ) -> about 2235/32
++ */
++unsigned long long sched_clock(void)
++{
++	unsigned long long v = cnt32_to_63(OST_OSCR);
++
++	/* original conservative method, but overflow frequently
++	 * v *= NSEC_PER_SEC >> 12;
++	 * do_div(v, CLOCK_TICK_RATE >> 12);
++	 */
++	v = ((v & 0x7fffffffffffffffULL) * 2235) >> 5;
++
++	return v;
++}
++
++static struct resource puv3_usb_resources[] = {
++	/* order is significant! */
++	{
++		.start		= PKUNITY_USB_BASE,
++		.end		= PKUNITY_USB_BASE + 0x3ff,
++		.flags		= IORESOURCE_MEM,
++	}, {
++		.start		= IRQ_USB,
++		.flags		= IORESOURCE_IRQ,
++	}, {
++		.start		= IRQ_USB,
++		.flags		= IORESOURCE_IRQ,
++	},
++};
++
++static struct musb_hdrc_config	puv3_usb_config[] = {
++	{
++		.num_eps = 16,
++		.multipoint = 1,
++#ifdef CONFIG_USB_INVENTRA_DMA
++		.dma = 1,
++		.dma_channels = 8,
++#endif
++	},
++};
++
++static struct musb_hdrc_platform_data puv3_usb_plat = {
++	.mode		= MUSB_HOST,
++	.min_power	= 100,
++	.clock		= 0,
++	.config		= puv3_usb_config,
++};
++
++static struct resource puv3_mmc_resources[] = {
++	[0] = {
++		.start	= PKUNITY_SDC_BASE,
++		.end	= PKUNITY_SDC_BASE + 0xfff,
++		.flags	= IORESOURCE_MEM,
++	},
++	[1] = {
++		.start	= IRQ_SDC,
++		.end	= IRQ_SDC,
++		.flags	= IORESOURCE_IRQ,
++	},
++};
++
++static struct resource puv3_rtc_resources[] = {
++	[0] = {
++		.start = PKUNITY_RTC_BASE,
++		.end   = PKUNITY_RTC_BASE + 0xff,
++		.flags = IORESOURCE_MEM,
++	},
++	[1] = {
++		.start = IRQ_RTCAlarm,
++		.end   = IRQ_RTCAlarm,
++		.flags = IORESOURCE_IRQ,
++	},
++	[2] = {
++		.start = IRQ_RTC,
++		.end   = IRQ_RTC,
++		.flags = IORESOURCE_IRQ
++	}
++};
++
++static struct resource puv3_pwm_resources[] = {
++	[0] = {
++		.start	= PKUNITY_OST_BASE + 0x80,
++		.end	= PKUNITY_OST_BASE + 0xff,
++		.flags	= IORESOURCE_MEM,
++	},
++};
++
++static struct resource puv3_uart0_resources[] = {
++	[0] = {
++		.start = PKUNITY_UART0_BASE,
++		.end   = PKUNITY_UART0_BASE + 0xff,
++		.flags = IORESOURCE_MEM,
++	},
++	[1] = {
++		.start = IRQ_UART0,
++		.end   = IRQ_UART0,
++		.flags = IORESOURCE_IRQ
++	}
++};
++
++static struct resource puv3_uart1_resources[] = {
++	[0] = {
++		.start = PKUNITY_UART1_BASE,
++		.end   = PKUNITY_UART1_BASE + 0xff,
++		.flags = IORESOURCE_MEM,
++	},
++	[1] = {
++		.start = IRQ_UART1,
++		.end   = IRQ_UART1,
++		.flags = IORESOURCE_IRQ
++	}
++};
++
++static struct resource puv3_umal_resources[] = {
++	[0] = {
++		.start = PKUNITY_UMAL_BASE,
++		.end   = PKUNITY_UMAL_BASE + 0x1fff,
++		.flags = IORESOURCE_MEM,
++	},
++	[1] = {
++		.start = IRQ_UMAL,
++		.end   = IRQ_UMAL,
++		.flags = IORESOURCE_IRQ
++	}
++};
++
++#ifdef CONFIG_PUV3_PM
++
++#define SAVE(x)		sleep_save[SLEEP_SAVE_##x] = x
++#define RESTORE(x)	x = sleep_save[SLEEP_SAVE_##x]
++
++/*
++ * List of global PXA peripheral registers to preserve.
++ * More ones like CP and general purpose register values are preserved
++ * with the stack pointer in sleep.S.
++ */
++enum {
++	SLEEP_SAVE_PM_PLLDDRCFG,
++	SLEEP_SAVE_COUNT
++};
++
++
++static void puv3_cpu_pm_save(unsigned long *sleep_save)
++{
++/*	SAVE(PM_PLLDDRCFG); */
++}
++
++static void puv3_cpu_pm_restore(unsigned long *sleep_save)
++{
++/*	RESTORE(PM_PLLDDRCFG); */
++}
++
++static int puv3_cpu_pm_prepare(void)
++{
++	/* set resume return address */
++	PM_DIVCFG = virt_to_phys(puv3_cpu_resume);
++	return 0;
++}
++
++static void puv3_cpu_pm_enter(suspend_state_t state)
++{
++	/* Clear reset status */
++	RESETC_RSSR = RESETC_RSSR_HWR | RESETC_RSSR_WDR
++			| RESETC_RSSR_SMR | RESETC_RSSR_SWR;
++
++	switch (state) {
++/*	case PM_SUSPEND_ON:
++		puv3_cpu_idle();
++		break; */
++	case PM_SUSPEND_MEM:
++		puv3_cpu_pm_prepare();
++		puv3_cpu_suspend(PM_PMCR_SFB);
++		break;
++	}
++}
++
++static int puv3_cpu_pm_valid(suspend_state_t state)
++{
++	return state == PM_SUSPEND_MEM;
++}
++
++static void puv3_cpu_pm_finish(void)
++{
++	/* ensure not to come back here if it wasn't intended */
++	/* PSPR = 0; */
++}
++
++static struct puv3_cpu_pm_fns puv3_cpu_pm_fnss = {
++	.save_count	= SLEEP_SAVE_COUNT,
++	.valid		= puv3_cpu_pm_valid,
++	.save		= puv3_cpu_pm_save,
++	.restore	= puv3_cpu_pm_restore,
++	.enter		= puv3_cpu_pm_enter,
++	.prepare	= puv3_cpu_pm_prepare,
++	.finish		= puv3_cpu_pm_finish,
++};
++
++static void __init puv3_init_pm(void)
++{
++	puv3_cpu_pm_fns = &puv3_cpu_pm_fnss;
++}
++#else
++static inline void puv3_init_pm(void) {}
++#endif
++
++void puv3_ps2_init(void)
++{
++	struct clk *bclk32;
++
++	bclk32 = clk_get(NULL, "BUS32_CLK");
++	PS2_CNT = clk_get_rate(bclk32) / 200000; /* should > 5us */
++}
++
++void __init puv3_core_init(void)
++{
++	puv3_init_pm();
++	puv3_ps2_init();
++
++	platform_device_register_simple("PKUnity-v3-RTC", -1,
++			puv3_rtc_resources, ARRAY_SIZE(puv3_rtc_resources));
++	platform_device_register_simple("PKUnity-v3-UMAL", -1,
++			puv3_umal_resources, ARRAY_SIZE(puv3_umal_resources));
++	platform_device_register_simple("PKUnity-v3-MMC", -1,
++			puv3_mmc_resources, ARRAY_SIZE(puv3_mmc_resources));
++	platform_device_register_simple("PKUnity-v3-PWM", -1,
++			puv3_pwm_resources, ARRAY_SIZE(puv3_pwm_resources));
++	platform_device_register_simple("PKUnity-v3-UART", 0,
++			puv3_uart0_resources, ARRAY_SIZE(puv3_uart0_resources));
++	platform_device_register_simple("PKUnity-v3-UART", 1,
++			puv3_uart1_resources, ARRAY_SIZE(puv3_uart1_resources));
++	platform_device_register_simple("PKUnity-v3-AC97", -1, NULL, 0);
++	platform_device_register_resndata(&platform_bus, "musb_hdrc", -1,
++			puv3_usb_resources, ARRAY_SIZE(puv3_usb_resources),
++			&puv3_usb_plat, sizeof(puv3_usb_plat));
++}
++
+diff --git a/arch/unicore32/kernel/puv3-nb0916.c b/arch/unicore32/kernel/puv3-nb0916.c
+new file mode 100644
+index 000000000000..a78e60420653
+--- /dev/null
++++ b/arch/unicore32/kernel/puv3-nb0916.c
+@@ -0,0 +1,145 @@
++/*
++ * linux/arch/unicore32/kernel/puv3-nb0916.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ *	Maintained by GUAN Xue-tao 
++ *	Copyright (C) 2001-2010 Guan Xuetao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++
++static struct physmap_flash_data physmap_flash_data = {
++	.width		= 1,
++};
++
++static struct resource physmap_flash_resource = {
++	.start		= 0xFFF80000,
++	.end		= 0xFFFFFFFF,
++	.flags		= IORESOURCE_MEM,
++};
++
++static struct resource puv3_i2c_resources[] = {
++	[0] = {
++		.start = PKUNITY_I2C_BASE,
++		.end   = PKUNITY_I2C_BASE + 0xff,
++		.flags = IORESOURCE_MEM,
++	},
++	[1] = {
++		.start = IRQ_I2C,
++		.end   = IRQ_I2C,
++		.flags = IORESOURCE_IRQ,
++	}
++};
++
++static struct platform_pwm_backlight_data nb0916_backlight_data = {
++	.pwm_id		= 0,
++	.max_brightness	= 100,
++	.dft_brightness	= 100,
++	.pwm_period_ns	= 70 * 1024,
++};
++
++static struct gpio_keys_button nb0916_gpio_keys[] = {
++	{
++		.type	= EV_KEY,
++		.code	= KEY_POWER,
++		.gpio	= GPI_SOFF_REQ,
++		.desc	= "Power Button",
++		.wakeup = 1,
++		.active_low = 1,
++	},
++	{
++		.type	= EV_KEY,
++		.code	= BTN_TOUCH,
++		.gpio	= GPI_BTN_TOUCH,
++		.desc	= "Touchpad Button",
++		.wakeup = 1,
++		.active_low = 1,
++	},
++};
++
++static struct gpio_keys_platform_data nb0916_gpio_button_data = {
++	.buttons	= nb0916_gpio_keys,
++	.nbuttons	= ARRAY_SIZE(nb0916_gpio_keys),
++};
++
++static irqreturn_t nb0916_lcdcaseoff_handler(int irq, void *dev_id)
++{
++	if (gpio_get_value(GPI_LCD_CASE_OFF))
++		gpio_set_value(GPO_LCD_EN, 1);
++	else
++		gpio_set_value(GPO_LCD_EN, 0);
++
++	return IRQ_HANDLED;
++}
++
++static irqreturn_t nb0916_overheat_handler(int irq, void *dev_id)
++{
++	machine_halt();
++	/* SYSTEM HALT, NO RETURN */
++	return IRQ_HANDLED;
++}
++
++static struct i2c_board_info __initdata puv3_i2c_devices[] = {
++	{	I2C_BOARD_INFO("lm75",		I2C_TAR_THERMAL),	},
++	{	I2C_BOARD_INFO("bq27200",	I2C_TAR_PWIC),		},
++	{	I2C_BOARD_INFO("24c02",		I2C_TAR_EEPROM),	},
++};
++
++int __init mach_nb0916_init(void)
++{
++	i2c_register_board_info(0, puv3_i2c_devices,
++			ARRAY_SIZE(puv3_i2c_devices));
++
++	platform_device_register_simple("PKUnity-v3-I2C", -1,
++			puv3_i2c_resources, ARRAY_SIZE(puv3_i2c_resources));
++
++	platform_device_register_data(&platform_bus, "pwm-backlight", -1,
++			&nb0916_backlight_data, sizeof(nb0916_backlight_data));
++
++	platform_device_register_data(&platform_bus, "gpio-keys", -1,
++			&nb0916_gpio_button_data, sizeof(nb0916_gpio_button_data));
++
++	platform_device_register_resndata(&platform_bus, "physmap-flash", -1,
++			&physmap_flash_resource, 1,
++			&physmap_flash_data, sizeof(physmap_flash_data));
++
++	if (request_irq(gpio_to_irq(GPI_LCD_CASE_OFF),
++		&nb0916_lcdcaseoff_handler,
++		IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
++		"NB0916 lcd case off", NULL) < 0) {
++
++		printk(KERN_DEBUG "LCD-Case-OFF IRQ %d not available\n",
++			gpio_to_irq(GPI_LCD_CASE_OFF));
++	}
++
++	if (request_irq(gpio_to_irq(GPI_OTP_INT), &nb0916_overheat_handler,
++		IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
++		"NB0916 overheating protection", NULL) < 0) {
++
++		printk(KERN_DEBUG "Overheating Protection IRQ %d not available\n",
++			gpio_to_irq(GPI_OTP_INT));
++	}
++
++	return 0;
++}
++
++subsys_initcall_sync(mach_nb0916_init);

commit 70fac51feaf2ca50c84e102e2a2699eb19ef24bd
+Author: GuanXuetao 
+Date:   Sat Jan 15 18:23:31 2011 +0800
+
+    unicore32 additional architecture files: boot process
+    
+    This patch implements booting process, including uncompression process.
+    
+    Signed-off-by: Guan Xuetao 
+    Reviewed-by: Arnd Bergmann 
+
+diff --git a/arch/unicore32/boot/Makefile b/arch/unicore32/boot/Makefile
+new file mode 100644
+index 000000000000..79e5f88845d9
+--- /dev/null
++++ b/arch/unicore32/boot/Makefile
+@@ -0,0 +1,47 @@
++#
++# arch/unicore32/boot/Makefile
++#
++# This file is included by the global makefile so that you can add your own
++# architecture-specific flags and dependencies.
++#
++# This file is subject to the terms and conditions of the GNU General Public
++# License.  See the file "COPYING" in the main directory of this archive
++# for more details.
++#
++# Copyright (C) 2001~2010 GUAN Xue-tao
++#
++
++MKIMAGE := $(srctree)/scripts/mkuboot.sh
++
++targets := Image zImage uImage
++
++$(obj)/Image: vmlinux FORCE
++	$(call if_changed,objcopy)
++	@echo '  Kernel: $@ is ready'
++
++$(obj)/compressed/vmlinux: $(obj)/Image FORCE
++	$(Q)$(MAKE) $(build)=$(obj)/compressed $@
++
++$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
++	$(call if_changed,objcopy)
++	@echo '  Kernel: $@ is ready'
++
++quiet_cmd_uimage = UIMAGE  $@
++      cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A unicore -O linux -T kernel \
++		   -C none -a $(LOADADDR) -e $(STARTADDR) \
++		   -n 'Linux-$(KERNELRELEASE)' -d $< $@
++
++$(obj)/uImage: LOADADDR=0x0
++
++$(obj)/uImage: STARTADDR=$(LOADADDR)
++
++$(obj)/uImage: $(obj)/zImage FORCE
++	$(call if_changed,uimage)
++	@echo '  Image $@ is ready'
++
++PHONY += initrd FORCE
++initrd:
++	@test "$(INITRD)" != "" || \
++	(echo You must specify INITRD; exit -1)
++
++subdir- := compressed
+diff --git a/arch/unicore32/boot/compressed/Makefile b/arch/unicore32/boot/compressed/Makefile
+new file mode 100644
+index 000000000000..95373428cb3d
+--- /dev/null
++++ b/arch/unicore32/boot/compressed/Makefile
+@@ -0,0 +1,68 @@
++#
++# linux/arch/unicore32/boot/compressed/Makefile
++#
++# create a compressed vmlinuz image from the original vmlinux
++#
++# This file is subject to the terms and conditions of the GNU General Public
++# License.  See the file "COPYING" in the main directory of this archive
++# for more details.
++#
++# Copyright (C) 2001~2010 GUAN Xue-tao
++#
++
++EXTRA_CFLAGS	:= -fpic -fno-builtin
++EXTRA_AFLAGS	:= -Wa,-march=all
++
++OBJS		:= misc.o
++
++# font.c and font.o
++CFLAGS_font.o	:= -Dstatic=
++$(obj)/font.c: $(srctree)/drivers/video/console/font_8x8.c
++	$(call cmd,shipped)
++
++# piggy.S and piggy.o
++suffix_$(CONFIG_KERNEL_GZIP)	:= gzip
++suffix_$(CONFIG_KERNEL_BZIP2)	:= bz2
++suffix_$(CONFIG_KERNEL_LZO)	:= lzo
++suffix_$(CONFIG_KERNEL_LZMA)	:= lzma
++
++$(obj)/piggy.$(suffix_y): $(obj)/../Image FORCE
++	$(call if_changed,$(suffix_y))
++
++SEDFLAGS_piggy	= s/DECOMP_SUFFIX/$(suffix_y)/
++$(obj)/piggy.S: $(obj)/piggy.S.in
++	@sed "$(SEDFLAGS_piggy)" < $< > $@
++
++$(obj)/piggy.o:  $(obj)/piggy.$(suffix_y) $(obj)/piggy.S FORCE
++
++targets		:= vmlinux vmlinux.lds font.o font.c head.o misc.o \
++			piggy.$(suffix_y) piggy.o piggy.S \
++
++# Make sure files are removed during clean
++extra-y		+= piggy.gzip piggy.bz2 piggy.lzo piggy.lzma
++
++# ?
++LDFLAGS_vmlinux += -p
++# Report unresolved symbol references
++LDFLAGS_vmlinux += --no-undefined
++# Delete all temporary local symbols
++LDFLAGS_vmlinux += -X
++# Next argument is a linker script
++LDFLAGS_vmlinux += -T
++
++# For uidivmod
++$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/head.o $(obj)/piggy.o \
++		$(obj)/misc.o FORCE
++	$(call if_changed,ld)
++	@:
++
++# We now have a PIC decompressor implementation.  Decompressors running
++# from RAM should not define ZTEXTADDR.  Decompressors running directly
++# from ROM or Flash must define ZTEXTADDR (preferably via the config)
++ZTEXTADDR	:= 0
++ZBSSADDR	:= ALIGN(4)
++
++SEDFLAGS_lds	= s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
++$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/unicore32/boot/Makefile $(KCONFIG_CONFIG)
++	@sed "$(SEDFLAGS_lds)" < $< > $@
++
+diff --git a/arch/unicore32/boot/compressed/head.S b/arch/unicore32/boot/compressed/head.S
+new file mode 100644
+index 000000000000..fbd1e374c685
+--- /dev/null
++++ b/arch/unicore32/boot/compressed/head.S
+@@ -0,0 +1,204 @@
++/*
++ * linux/arch/unicore32/boot/compressed/head.S
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++
++#define csub	cmpsub
++#define cand	cmpand
++#define nop8	nop; nop; nop; nop; nop; nop; nop; nop
++
++		.section ".start", #alloc, #execinstr
++		.text
++start:
++		.type	start,#function
++
++		/* Initialize ASR, PRIV mode and INTR off */
++		mov	r0, #0xD3
++		mov.a	asr, r0
++
++		adr	r0, LC0
++		ldm	(r1, r2, r3, r5, r6, r7, r8), [r0]+
++		ldw	sp, [r0+], #28
++		sub.a	r0, r0, r1		@ calculate the delta offset
++
++		/*
++		 * if delta is zero, we are running at the address
++		 * we were linked at.
++		 */
++		beq	not_relocated
++
++		/*
++		 * We're running at a different address.  We need to fix
++		 * up various pointers:
++		 *   r5 - zImage base address (_start)
++		 *   r7 - GOT start
++		 *   r8 - GOT end
++		 */
++		add	r5, r5, r0
++		add	r7, r7, r0
++		add	r8, r8, r0
++
++		/*
++		 * we need to fix up pointers into the BSS region.
++		 *   r2 - BSS start
++		 *   r3 - BSS end
++		 *   sp - stack pointer
++		 */
++		add	r2, r2, r0
++		add	r3, r3, r0
++		add	sp, sp, r0
++
++		/*
++		 * Relocate all entries in the GOT table.
++		 * This fixes up the C references.
++		 *   r7 - GOT start
++		 *   r8 - GOT end
++		 */
++1001:		ldw	r1, [r7+], #0
++		add	r1, r1, r0
++		stw.w	r1, [r7]+, #4
++		csub.a	r7, r8
++		bub	1001b
++
++not_relocated:
++		/*
++		 * Clear BSS region.
++		 *   r2 - BSS start
++		 *   r3 - BSS end
++		 */
++		mov	r0, #0
++1002:		stw.w	r0, [r2]+, #4
++		csub.a	r2, r3
++		bub	1002b
++
++		/*
++		 * Turn on the cache.
++		 */
++                mov     r0, #0
++                movc    p0.c5, r0, #28		@ cache invalidate all
++                nop8
++                movc    p0.c6, r0, #6		@ tlb invalidate all
++                nop8
++
++                mov     r0, #0x1c		@ en icache and wb dcache
++                movc    p0.c1, r0, #0
++                nop8
++
++		/*
++		 * Set up some pointers, for starting decompressing.
++		 */
++
++		mov	r1, sp			@ malloc space above stack
++		add	r2, sp, #0x10000	@ 64k max
++
++		/*
++		 * Check to see if we will overwrite ourselves.
++		 *   r4 = final kernel address
++		 *   r5 = start of this image
++		 *   r6 = size of decompressed image
++		 *   r2 = end of malloc space (and therefore this image)
++		 * We basically want:
++		 *   r4 >= r2 -> OK
++		 *   r4 + image length <= r5 -> OK
++		 */
++		ldw	r4, =KERNEL_IMAGE_START
++		csub.a	r4, r2
++		bea	wont_overwrite
++		add	r0, r4, r6
++		csub.a	r0, r5
++		beb	wont_overwrite
++
++		/*
++		 * If overwrite, just print error message
++		 */
++		b	__error_overwrite
++
++		/*
++		 * We're not in danger of overwriting ourselves.
++		 * Do this the simple way.
++		 */
++wont_overwrite:
++		/*
++		 * decompress_kernel:
++		 *   r0: output_start
++		 *   r1: free_mem_ptr_p
++		 *   r2: free_mem_ptr_end_p
++		 */
++		mov	r0, r4
++		b.l	decompress_kernel	@ C functions
++
++		/*
++		 * Clean and flush the cache to maintain consistency.
++		 */
++		mov	r0, #0
++                movc    p0.c5, r0, #14		@ flush dcache
++		nop8
++                movc    p0.c5, r0, #20		@ icache invalidate all
++                nop8
++
++		/*
++		 * Turn off the Cache and MMU.
++		 */
++		mov	r0, #0			@ disable i/d cache and MMU
++		movc	p0.c1, r0, #0
++                nop8
++
++		mov	r0, #0			@ must be zero
++		ldw	r4, =KERNEL_IMAGE_START
++		mov	pc, r4			@ call kernel
++
++
++		.align	2
++		.type	LC0, #object
++LC0:		.word	LC0			@ r1
++		.word	__bss_start		@ r2
++		.word	_end			@ r3
++		.word	_start			@ r5
++		.word	_image_size		@ r6
++		.word	_got_start		@ r7
++		.word	_got_end		@ r8
++		.word	decompress_stack_end	@ sp
++		.size	LC0, . - LC0
++
++print_string:
++#ifdef CONFIG_DEBUG_OCD
++2001:		ldb.w	r1, [r0]+, #1
++		csub.a	r1, #0
++		bne	2002f
++		mov	pc, lr
++2002:
++		movc	r2, p1.c0, #0
++		cand.a	r2, #2
++		bne	2002b
++		movc	p1.c1, r1, #1
++		csub.a	r1, #'\n'
++		cmoveq	r1, #'\r'
++		beq	2002b
++		b	2001b
++#else
++		mov	pc, lr
++#endif
++
++__error_overwrite:
++		adr	r0, str_error
++		b.l	print_string
++2001:		nop8
++		b	2001b
++str_error:	.asciz	"\nError: Kernel address OVERWRITE\n"
++		.align
++
++		.ltorg
++
++		.align	4
++		.section ".stack", "aw", %nobits
++decompress_stack:	.space	4096
++decompress_stack_end:
+diff --git a/arch/unicore32/boot/compressed/misc.c b/arch/unicore32/boot/compressed/misc.c
+new file mode 100644
+index 000000000000..176d5bda3559
+--- /dev/null
++++ b/arch/unicore32/boot/compressed/misc.c
+@@ -0,0 +1,126 @@
++/*
++ * linux/arch/unicore32/boot/compressed/misc.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include 
++#include 
++
++/*
++ * gzip delarations
++ */
++unsigned char *output_data;
++unsigned long output_ptr;
++
++unsigned int free_mem_ptr;
++unsigned int free_mem_end_ptr;
++
++#define STATIC static
++#define STATIC_RW_DATA	/* non-static please */
++
++/*
++ * arch-dependent implementations
++ */
++#ifndef ARCH_HAVE_DECOMP_ERROR
++#define arch_decomp_error(x)
++#endif
++
++#ifndef ARCH_HAVE_DECOMP_SETUP
++#define arch_decomp_setup()
++#endif
++
++#ifndef ARCH_HAVE_DECOMP_PUTS
++#define arch_decomp_puts(p)
++#endif
++
++void *memcpy(void *dest, const void *src, size_t n)
++{
++	int i = 0;
++	unsigned char *d = (unsigned char *)dest, *s = (unsigned char *)src;
++
++	for (i = n >> 3; i > 0; i--) {
++		*d++ = *s++;
++		*d++ = *s++;
++		*d++ = *s++;
++		*d++ = *s++;
++		*d++ = *s++;
++		*d++ = *s++;
++		*d++ = *s++;
++		*d++ = *s++;
++	}
++
++	if (n & 1 << 2) {
++		*d++ = *s++;
++		*d++ = *s++;
++		*d++ = *s++;
++		*d++ = *s++;
++	}
++
++	if (n & 1 << 1) {
++		*d++ = *s++;
++		*d++ = *s++;
++	}
++
++	if (n & 1)
++		*d++ = *s++;
++
++	return dest;
++}
++
++void error(char *x)
++{
++	arch_decomp_puts("\n\n");
++	arch_decomp_puts(x);
++	arch_decomp_puts("\n\n -- System halted");
++
++	arch_decomp_error(x);
++
++	for (;;)
++		; /* Halt */
++}
++
++/* Heap size should be adjusted for different decompress method */
++#ifdef CONFIG_KERNEL_GZIP
++#include "../../../../lib/decompress_inflate.c"
++#endif
++
++#ifdef CONFIG_KERNEL_BZIP2
++#include "../../../../lib/decompress_bunzip2.c"
++#endif
++
++#ifdef CONFIG_KERNEL_LZO
++#include "../../../../lib/decompress_unlzo.c"
++#endif
++
++#ifdef CONFIG_KERNEL_LZMA
++#include "../../../../lib/decompress_unlzma.c"
++#endif
++
++unsigned long decompress_kernel(unsigned long output_start,
++		unsigned long free_mem_ptr_p,
++		unsigned long free_mem_ptr_end_p)
++{
++	unsigned char *tmp;
++
++	output_data		= (unsigned char *)output_start;
++	free_mem_ptr		= free_mem_ptr_p;
++	free_mem_end_ptr	= free_mem_ptr_end_p;
++
++	arch_decomp_setup();
++
++	tmp = (unsigned char *) (((unsigned long)input_data_end) - 4);
++	output_ptr = get_unaligned_le32(tmp);
++
++	arch_decomp_puts("Uncompressing Linux...");
++	decompress(input_data, input_data_end - input_data, NULL, NULL,
++			output_data, NULL, error);
++	arch_decomp_puts(" done, booting the kernel.\n");
++	return output_ptr;
++}
+diff --git a/arch/unicore32/boot/compressed/piggy.S.in b/arch/unicore32/boot/compressed/piggy.S.in
+new file mode 100644
+index 000000000000..b79704d58026
+--- /dev/null
++++ b/arch/unicore32/boot/compressed/piggy.S.in
+@@ -0,0 +1,6 @@
++	.section .piggydata,#alloc
++	.globl	input_data
++input_data:
++	.incbin	"arch/unicore32/boot/compressed/piggy.DECOMP_SUFFIX"
++	.globl	input_data_end
++input_data_end:
+diff --git a/arch/unicore32/boot/compressed/vmlinux.lds.in b/arch/unicore32/boot/compressed/vmlinux.lds.in
+new file mode 100644
+index 000000000000..d5a3ce296239
+--- /dev/null
++++ b/arch/unicore32/boot/compressed/vmlinux.lds.in
+@@ -0,0 +1,61 @@
++/*
++ * linux/arch/unicore/boot/compressed/vmlinux.lds.in
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++OUTPUT_ARCH(unicore32)
++ENTRY(_start)
++SECTIONS
++{
++  /DISCARD/ : {
++    /*
++     * Discard any r/w data - this produces a link error if we have any,
++     * which is required for PIC decompression.  Local data generates
++     * GOTOFF relocations, which prevents it being relocated independently
++     * of the text/got segments.
++     */
++    *(.data)
++  }
++
++  . = TEXT_START;
++  _text = .;
++
++  .text : {
++    _start = .;
++    *(.start)
++    *(.text)
++    *(.text.*)
++    *(.fixup)
++    *(.gnu.warning)
++    *(.rodata)
++    *(.rodata.*)
++    *(.piggydata)
++    . = ALIGN(4);
++  }
++
++  _etext = .;
++
++  /* Assume size of decompressed image is 4x the compressed image */
++  _image_size = (_etext - _text) * 4;
++
++  _got_start = .;
++  .got			: { *(.got) }
++  _got_end = .;
++  .got.plt		: { *(.got.plt) }
++  _edata = .;
++
++  . = BSS_START;
++  __bss_start = .;
++  .bss			: { *(.bss) }
++  _end = .;
++
++  .stack		: { *(.stack) }
++  .comment 0		: { *(.comment) }
++}
++
+diff --git a/arch/unicore32/include/mach/uncompress.h b/arch/unicore32/include/mach/uncompress.h
+new file mode 100644
+index 000000000000..142d3e7958a9
+--- /dev/null
++++ b/arch/unicore32/include/mach/uncompress.h
+@@ -0,0 +1,34 @@
++/*
++ * linux/arch/unicore32/include/mach/uncompress.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __MACH_PUV3_UNCOMPRESS_H__
++#define __MACH_PUV3_UNCOMPRESS_H__
++
++#include "hardware.h"
++#include "ocd.h"
++
++extern char input_data[];
++extern char input_data_end[];
++
++static void arch_decomp_puts(const char *ptr)
++{
++	char c;
++
++	while ((c = *ptr++) != '\0') {
++		if (c == '\n')
++			putc('\r');
++		putc(c);
++	}
++}
++#define ARCH_HAVE_DECOMP_PUTS
++
++#endif /* __MACH_PUV3_UNCOMPRESS_H__ */

commit 96cf5185a95e0b304596fe19edcf8dfcd5c10699
+Author: GuanXuetao 
+Date:   Sat Jan 15 18:23:09 2011 +0800
+
+    unicore32 additional architecture files: low-level lib: misc
+    
+    This patch implements the rest low-level libraries.
+    
+    Signed-off-by: Guan Xuetao 
+    Acked-by: Arnd Bergmann 
+
+diff --git a/arch/unicore32/include/asm/assembler.h b/arch/unicore32/include/asm/assembler.h
+new file mode 100644
+index 000000000000..8e87ed7faeba
+--- /dev/null
++++ b/arch/unicore32/include/asm/assembler.h
+@@ -0,0 +1,131 @@
++/*
++ * linux/arch/unicore32/include/asm/assembler.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ *  Do not include any C declarations in this file - it is included by
++ *  assembler source.
++ */
++#ifndef __ASSEMBLY__
++#error "Only include this from assembly code"
++#endif
++
++#include 
++
++/*
++ * Little Endian independent macros for shifting bytes within registers.
++ */
++#define pull            >>
++#define push            <<
++#define get_byte_0      << #0
++#define get_byte_1	>> #8
++#define get_byte_2	>> #16
++#define get_byte_3	>> #24
++#define put_byte_0      << #0
++#define put_byte_1	<< #8
++#define put_byte_2	<< #16
++#define put_byte_3	<< #24
++
++#define cadd		cmpadd
++#define cand		cmpand
++#define csub		cmpsub
++#define cxor		cmpxor
++
++/*
++ * Enable and disable interrupts
++ */
++	.macro disable_irq, temp
++	mov	\temp, asr
++	andn     \temp, \temp, #0xFF
++	or	\temp, \temp, #PSR_I_BIT | PRIV_MODE
++	mov.a	asr, \temp
++	.endm
++
++	.macro enable_irq, temp
++	mov	\temp, asr
++	andn     \temp, \temp, #0xFF
++	or	\temp, \temp, #PRIV_MODE
++	mov.a	asr, \temp
++	.endm
++
++#define USER(x...)				\
++9999:	x;					\
++	.pushsection __ex_table, "a";		\
++	.align	3;				\
++	.long	9999b, 9001f;			\
++	.popsection
++
++	.macro	notcond, cond, nexti = .+8
++	.ifc	\cond, eq
++		bne	\nexti
++	.else;	.ifc	\cond, ne
++		beq	\nexti
++	.else;	.ifc	\cond, ea
++		bub	\nexti
++	.else;	.ifc	\cond, ub
++		bea	\nexti
++	.else;	.ifc	\cond, fs
++		bns	\nexti
++	.else;	.ifc	\cond, ns
++		bfs	\nexti
++	.else;	.ifc	\cond, fv
++		bnv	\nexti
++	.else;	.ifc	\cond, nv
++		bfv	\nexti
++	.else;	.ifc	\cond, ua
++		beb	\nexti
++	.else;	.ifc	\cond, eb
++		bua	\nexti
++	.else;	.ifc	\cond, eg
++		bsl	\nexti
++	.else;	.ifc	\cond, sl
++		beg	\nexti
++	.else;	.ifc	\cond, sg
++		bel	\nexti
++	.else;	.ifc	\cond, el
++		bsg	\nexti
++	.else;	.ifnc	\cond, al
++		.error  "Unknown cond in notcond macro argument"
++	.endif;	.endif;	.endif;	.endif;	.endif;	.endif;	.endif
++	.endif;	.endif;	.endif;	.endif;	.endif;	.endif;	.endif
++	.endif
++	.endm
++
++	.macro	usracc, instr, reg, ptr, inc, cond, rept, abort
++	.rept	\rept
++	notcond	\cond, .+8
++9999 :
++	.if	\inc == 1
++	\instr\()b.u \reg, [\ptr], #\inc
++	.elseif	\inc == 4
++	\instr\()w.u \reg, [\ptr], #\inc
++	.else
++	.error	"Unsupported inc macro argument"
++	.endif
++
++	.pushsection __ex_table, "a"
++	.align	3
++	.long	9999b, \abort
++	.popsection
++	.endr
++	.endm
++
++	.macro	strusr, reg, ptr, inc, cond = al, rept = 1, abort = 9001f
++	usracc	st, \reg, \ptr, \inc, \cond, \rept, \abort
++	.endm
++
++	.macro	ldrusr, reg, ptr, inc, cond = al, rept = 1, abort = 9001f
++	usracc	ld, \reg, \ptr, \inc, \cond, \rept, \abort
++	.endm
++
++	.macro	nop8
++	.rept	8
++		nop
++	.endr
++	.endm
+diff --git a/arch/unicore32/include/asm/bitops.h b/arch/unicore32/include/asm/bitops.h
+new file mode 100644
+index 000000000000..1628a6328994
+--- /dev/null
++++ b/arch/unicore32/include/asm/bitops.h
+@@ -0,0 +1,47 @@
++/*
++ * linux/arch/unicore32/include/asm/bitops.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __UNICORE_BITOPS_H__
++#define __UNICORE_BITOPS_H__
++
++#define find_next_bit		__uc32_find_next_bit
++#define find_next_zero_bit	__uc32_find_next_zero_bit
++
++#define find_first_bit		__uc32_find_first_bit
++#define find_first_zero_bit	__uc32_find_first_zero_bit
++
++#define _ASM_GENERIC_BITOPS_FLS_H_
++#define _ASM_GENERIC_BITOPS___FLS_H_
++#define _ASM_GENERIC_BITOPS_FFS_H_
++#define _ASM_GENERIC_BITOPS___FFS_H_
++/*
++ * On UNICORE, those functions can be implemented around
++ * the cntlz instruction for much better code efficiency.
++ */
++
++static inline int fls(int x)
++{
++	int ret;
++
++	asm("cntlz\t%0, %1" : "=r" (ret) : "r" (x) : "cc");
++	ret = 32 - ret;
++
++	return ret;
++}
++
++#define __fls(x) (fls(x) - 1)
++#define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); })
++#define __ffs(x) (ffs(x) - 1)
++
++#include 
++
++#endif /* __UNICORE_BITOPS_H__ */
+diff --git a/arch/unicore32/include/asm/checksum.h b/arch/unicore32/include/asm/checksum.h
+new file mode 100644
+index 000000000000..f55c3f937c3e
+--- /dev/null
++++ b/arch/unicore32/include/asm/checksum.h
+@@ -0,0 +1,41 @@
++/*
++ * linux/arch/unicore32/include/asm/checksum.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * IP checksum routines
++ */
++#ifndef __UNICORE_CHECKSUM_H__
++#define __UNICORE_CHECKSUM_H__
++
++/*
++ * computes the checksum of the TCP/UDP pseudo-header
++ * returns a 16-bit checksum, already complemented
++ */
++
++static inline __wsum
++csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
++		   unsigned short proto, __wsum sum)
++{
++	__asm__(
++	"add.a	%0, %1, %2\n"
++	"addc.a	%0, %0, %3\n"
++	"addc.a	%0, %0, %4 << #8\n"
++	"addc.a	%0, %0, %5\n"
++	"addc	%0, %0, #0\n"
++	: "=&r"(sum)
++	: "r" (sum), "r" (daddr), "r" (saddr), "r" (len), "Ir" (htons(proto))
++	: "cc");
++	return sum;
++}
++#define csum_tcpudp_nofold	csum_tcpudp_nofold
++
++#include 
++
++#endif
+diff --git a/arch/unicore32/include/asm/delay.h b/arch/unicore32/include/asm/delay.h
+new file mode 100644
+index 000000000000..164ae61cd6f7
+--- /dev/null
++++ b/arch/unicore32/include/asm/delay.h
+@@ -0,0 +1,52 @@
++/*
++ * linux/arch/unicore32/include/asm/delay.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * Delay routines, using a pre-computed "loops_per_second" value.
++ */
++#ifndef __UNICORE_DELAY_H__
++#define __UNICORE_DELAY_H__
++
++#include 	/* HZ */
++
++extern void __delay(int loops);
++
++/*
++ * This function intentionally does not exist; if you see references to
++ * it, it means that you're calling udelay() with an out of range value.
++ *
++ * With currently imposed limits, this means that we support a max delay
++ * of 2000us. Further limits: HZ<=1000 and bogomips<=3355
++ */
++extern void __bad_udelay(void);
++
++/*
++ * division by multiplication: you don't have to worry about
++ * loss of precision.
++ *
++ * Use only for very small delays ( < 1 msec).  Should probably use a
++ * lookup table, really, as the multiplications take much too long with
++ * short delays.  This is a "reasonable" implementation, though (and the
++ * first constant multiplications gets optimized away if the delay is
++ * a constant)
++ */
++extern void __udelay(unsigned long usecs);
++extern void __const_udelay(unsigned long);
++
++#define MAX_UDELAY_MS 2
++
++#define udelay(n)							\
++	(__builtin_constant_p(n) ?					\
++	  ((n) > (MAX_UDELAY_MS * 1000) ? __bad_udelay() :		\
++			__const_udelay((n) * ((2199023U*HZ)>>11))) :	\
++	  __udelay(n))
++
++#endif /* __UNICORE_DELAY_H__ */
++
+diff --git a/arch/unicore32/include/asm/futex.h b/arch/unicore32/include/asm/futex.h
+new file mode 100644
+index 000000000000..07dea6170558
+--- /dev/null
++++ b/arch/unicore32/include/asm/futex.h
+@@ -0,0 +1,143 @@
++/*
++ * linux/arch/unicore32/include/asm/futex.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __UNICORE_FUTEX_H__
++#define __UNICORE_FUTEX_H__
++
++#ifdef __KERNEL__
++
++#include 
++#include 
++#include 
++#include 
++
++#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)	\
++	__asm__ __volatile__(					\
++	"1:	ldw.u	%1, [%2]\n"				\
++	"	" insn "\n"					\
++	"2:	stw.u	%0, [%2]\n"				\
++	"	mov	%0, #0\n"				\
++	"3:\n"							\
++	"	.pushsection __ex_table,\"a\"\n"		\
++	"	.align	3\n"					\
++	"	.long	1b, 4f, 2b, 4f\n"			\
++	"	.popsection\n"					\
++	"	.pushsection .fixup,\"ax\"\n"			\
++	"4:	mov	%0, %4\n"				\
++	"	b	3b\n"					\
++	"	.popsection"					\
++	: "=&r" (ret), "=&r" (oldval)				\
++	: "r" (uaddr), "r" (oparg), "Ir" (-EFAULT)		\
++	: "cc", "memory")
++
++static inline int
++futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
++{
++	int op = (encoded_op >> 28) & 7;
++	int cmp = (encoded_op >> 24) & 15;
++	int oparg = (encoded_op << 8) >> 20;
++	int cmparg = (encoded_op << 20) >> 20;
++	int oldval = 0, ret;
++
++	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
++		oparg = 1 << oparg;
++
++	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
++		return -EFAULT;
++
++	pagefault_disable();	/* implies preempt_disable() */
++
++	switch (op) {
++	case FUTEX_OP_SET:
++		__futex_atomic_op("mov	%0, %3", ret, oldval, uaddr, oparg);
++		break;
++	case FUTEX_OP_ADD:
++		__futex_atomic_op("add	%0, %1, %3", ret, oldval, uaddr, oparg);
++		break;
++	case FUTEX_OP_OR:
++		__futex_atomic_op("or	%0, %1, %3", ret, oldval, uaddr, oparg);
++		break;
++	case FUTEX_OP_ANDN:
++		__futex_atomic_op("and	%0, %1, %3",
++				ret, oldval, uaddr, ~oparg);
++		break;
++	case FUTEX_OP_XOR:
++		__futex_atomic_op("xor	%0, %1, %3", ret, oldval, uaddr, oparg);
++		break;
++	default:
++		ret = -ENOSYS;
++	}
++
++	pagefault_enable();	/* subsumes preempt_enable() */
++
++	if (!ret) {
++		switch (cmp) {
++		case FUTEX_OP_CMP_EQ:
++			ret = (oldval == cmparg);
++			break;
++		case FUTEX_OP_CMP_NE:
++			ret = (oldval != cmparg);
++			break;
++		case FUTEX_OP_CMP_LT:
++			ret = (oldval <  cmparg);
++			break;
++		case FUTEX_OP_CMP_GE:
++			ret = (oldval >= cmparg);
++			break;
++		case FUTEX_OP_CMP_LE:
++			ret = (oldval <= cmparg);
++			break;
++		case FUTEX_OP_CMP_GT:
++			ret = (oldval >  cmparg);
++			break;
++		default:
++			ret = -ENOSYS;
++		}
++	}
++	return ret;
++}
++
++static inline int
++futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
++{
++	int val;
++
++	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
++		return -EFAULT;
++
++	pagefault_disable();	/* implies preempt_disable() */
++
++	__asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
++	"1:	ldw.u	%0, [%3]\n"
++	"	cmpxor.a	%0, %1\n"
++	"	bne	3f\n"
++	"2:	stw.u	%2, [%3]\n"
++	"3:\n"
++	"	.pushsection __ex_table,\"a\"\n"
++	"	.align	3\n"
++	"	.long	1b, 4f, 2b, 4f\n"
++	"	.popsection\n"
++	"	.pushsection .fixup,\"ax\"\n"
++	"4:	mov	%0, %4\n"
++	"	b	3b\n"
++	"	.popsection"
++	: "=&r" (val)
++	: "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT)
++	: "cc", "memory");
++
++	pagefault_enable();	/* subsumes preempt_enable() */
++
++	return val;
++}
++
++#endif /* __KERNEL__ */
++#endif /* __UNICORE_FUTEX_H__ */
+diff --git a/arch/unicore32/include/asm/io.h b/arch/unicore32/include/asm/io.h
+new file mode 100644
+index 000000000000..d73457c1800a
+--- /dev/null
++++ b/arch/unicore32/include/asm/io.h
+@@ -0,0 +1,52 @@
++/*
++ * linux/arch/unicore32/include/asm/io.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_IO_H__
++#define __UNICORE_IO_H__
++
++#ifdef __KERNEL__
++
++#include 
++#include 
++#include 
++
++#include 
++
++/*
++ * __uc32_ioremap and __uc32_ioremap_cached takes CPU physical address.
++ */
++extern void __iomem *__uc32_ioremap(unsigned long, size_t);
++extern void __iomem *__uc32_ioremap_cached(unsigned long, size_t);
++extern void __uc32_iounmap(volatile void __iomem *addr);
++
++/*
++ * ioremap and friends.
++ *
++ * ioremap takes a PCI memory address, as specified in
++ * Documentation/IO-mapping.txt.
++ *
++ */
++#define ioremap(cookie, size)		__uc32_ioremap(cookie, size)
++#define ioremap_cached(cookie, size)	__uc32_ioremap_cached(cookie, size)
++#define iounmap(cookie)			__uc32_iounmap(cookie)
++
++extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
++extern void ioport_unmap(void __iomem *addr);
++
++/*
++ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
++ * access
++ */
++#undef xlate_dev_mem_ptr
++#define xlate_dev_mem_ptr(p)	__va(p)
++
++#endif	/* __KERNEL__ */
++#endif	/* __UNICORE_IO_H__ */
+diff --git a/arch/unicore32/include/asm/mutex.h b/arch/unicore32/include/asm/mutex.h
+new file mode 100644
+index 000000000000..fab7d0e8adf6
+--- /dev/null
++++ b/arch/unicore32/include/asm/mutex.h
+@@ -0,0 +1,20 @@
++/*
++ * linux/arch/unicore32/include/asm/mutex.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * UniCore optimized mutex locking primitives
++ *
++ * Please look into asm-generic/mutex-xchg.h for a formal definition.
++ */
++#ifndef __UNICORE_MUTEX_H__
++#define __UNICORE_MUTEX_H__
++
++# include 
++#endif
+diff --git a/arch/unicore32/lib/Makefile b/arch/unicore32/lib/Makefile
+new file mode 100644
+index 000000000000..87229a558b36
+--- /dev/null
++++ b/arch/unicore32/lib/Makefile
+@@ -0,0 +1,27 @@
++#
++# linux/arch/unicore32/lib/Makefile
++#
++# Copyright (C) 2001-2010 GUAN Xue-tao
++#
++
++lib-y	:= backtrace.o delay.o findbit.o
++lib-y	+= strncpy_from_user.o strnlen_user.o
++lib-y	+= clear_user.o copy_page.o
++lib-y	+= copy_from_user.o copy_to_user.o
++
++GNU_LIBC_A		:= $(shell $(CC) $(KBUILD_CFLAGS) -print-file-name=libc.a)
++GNU_LIBC_A_OBJS		:= memchr.o memcpy.o memmove.o memset.o
++GNU_LIBC_A_OBJS		+= strchr.o strrchr.o
++GNU_LIBC_A_OBJS		+= rawmemchr.o			# needed by strrchr.o
++
++GNU_LIBGCC_A		:= $(shell $(CC) $(KBUILD_CFLAGS) -print-file-name=libgcc.a)
++GNU_LIBGCC_A_OBJS	:= _ashldi3.o _ashrdi3.o _lshrdi3.o
++GNU_LIBGCC_A_OBJS	+= _divsi3.o _modsi3.o _ucmpdi2.o _umodsi3.o _udivsi3.o
++
++lib-y	+= $(GNU_LIBC_A_OBJS) $(GNU_LIBGCC_A_OBJS)
++
++$(addprefix $(obj)/, $(GNU_LIBC_A_OBJS)):
++	$(Q)$(AR) p $(GNU_LIBC_A) $(notdir $@) > $@
++
++$(addprefix $(obj)/, $(GNU_LIBGCC_A_OBJS)):
++	$(Q)$(AR) p $(GNU_LIBGCC_A) $(notdir $@) > $@
+diff --git a/arch/unicore32/lib/delay.S b/arch/unicore32/lib/delay.S
+new file mode 100644
+index 000000000000..24664c009e78
+--- /dev/null
++++ b/arch/unicore32/lib/delay.S
+@@ -0,0 +1,51 @@
++/*
++ * linux/arch/unicore32/lib/delay.S
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++		.text
++
++.LC0:		.word	loops_per_jiffy
++.LC1:		.word	(2199023*HZ)>>11
++
++/*
++ * r0  <= 2000
++ * lpj <= 0x01ffffff (max. 3355 bogomips)
++ * HZ  <= 1000
++ */
++
++ENTRY(__udelay)
++		ldw	r2, .LC1
++		mul	r0, r2, r0
++ENTRY(__const_udelay)				@ 0 <= r0 <= 0x7fffff06
++		ldw	r2, .LC0
++		ldw	r2, [r2]		@ max = 0x01ffffff
++		mov	r0, r0 >> #14		@ max = 0x0001ffff
++		mov	r2, r2 >> #10		@ max = 0x00007fff
++		mul	r0, r2, r0		@ max = 2^32-1
++		mov.a	r0, r0 >> #6
++		cmoveq	pc, lr
++
++/*
++ * loops = r0 * HZ * loops_per_jiffy / 1000000
++ *
++ * Oh, if only we had a cycle counter...
++ */
++
++@ Delay routine
++ENTRY(__delay)
++		sub.a	r0, r0, #2
++		bua	__delay
++		mov	pc, lr
++ENDPROC(__udelay)
++ENDPROC(__const_udelay)
++ENDPROC(__delay)
+diff --git a/arch/unicore32/lib/findbit.S b/arch/unicore32/lib/findbit.S
+new file mode 100644
+index 000000000000..c360ce905d8b
+--- /dev/null
++++ b/arch/unicore32/lib/findbit.S
+@@ -0,0 +1,98 @@
++/*
++ * linux/arch/unicore32/lib/findbit.S
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++                .text
++
++/*
++ * Purpose  : Find a 'zero' bit
++ * Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit);
++ */
++__uc32_find_first_zero_bit:
++		cxor.a	r1, #0
++		beq	3f
++		mov	r2, #0
++1:		ldb	r3, [r0+], r2 >> #3
++		xor.a	r3, r3, #0xff		@ invert bits
++		bne	.L_found		@ any now set - found zero bit
++		add	r2, r2, #8		@ next bit pointer
++2:		csub.a	r2, r1			@ any more?
++		bub	1b
++3:		mov	r0, r1			@ no free bits
++		mov	pc, lr
++
++/*
++ * Purpose  : Find next 'zero' bit
++ * Prototype: int find_next_zero_bit
++ *		(void *addr, unsigned int maxbit, int offset)
++ */
++ENTRY(__uc32_find_next_zero_bit)
++		cxor.a	r1, #0
++		beq	3b
++		and.a	ip, r2, #7
++		beq	1b			@ If new byte, goto old routine
++		ldb	r3, [r0+], r2 >> #3
++		xor	r3, r3, #0xff		@ now looking for a 1 bit
++		mov.a	r3, r3 >> ip		@ shift off unused bits
++		bne	.L_found
++		or	r2, r2, #7		@ if zero, then no bits here
++		add	r2, r2, #1		@ align bit pointer
++		b	2b			@ loop for next bit
++ENDPROC(__uc32_find_next_zero_bit)
++
++/*
++ * Purpose  : Find a 'one' bit
++ * Prototype: int find_first_bit
++ *		(const unsigned long *addr, unsigned int maxbit);
++ */
++__uc32_find_first_bit:
++		cxor.a	r1, #0
++		beq	3f
++		mov	r2, #0
++1:		ldb	r3, [r0+], r2 >> #3
++		mov.a	r3, r3
++		bne	.L_found		@ any now set - found zero bit
++		add	r2, r2, #8		@ next bit pointer
++2:		csub.a	r2, r1			@ any more?
++		bub	1b
++3:		mov	r0, r1			@ no free bits
++		mov	pc, lr
++
++/*
++ * Purpose  : Find next 'one' bit
++ * Prototype: int find_next_zero_bit
++ *		(void *addr, unsigned int maxbit, int offset)
++ */
++ENTRY(__uc32_find_next_bit)
++		cxor.a	r1, #0
++		beq	3b
++		and.a	ip, r2, #7
++		beq	1b			@ If new byte, goto old routine
++		ldb	r3, [r0+], r2 >> #3
++		mov.a	r3, r3 >> ip		@ shift off unused bits
++		bne	.L_found
++		or	r2, r2, #7		@ if zero, then no bits here
++		add	r2, r2, #1		@ align bit pointer
++		b	2b			@ loop for next bit
++ENDPROC(__uc32_find_next_bit)
++
++/*
++ * One or more bits in the LSB of r3 are assumed to be set.
++ */
++.L_found:
++		rsub	r1, r3, #0
++		and	r3, r3, r1
++		cntlz	r3, r3
++		rsub	r3, r3, #31
++		add	r0, r2, r3
++		mov	pc, lr
++

commit 77c93b2f2388b974253af4149aa025b4751f92ad
+Author: GuanXuetao 
+Date:   Sat Feb 26 18:49:26 2011 +0800
+
+    unicore32 additional architecture files: low-level lib: uaccess
+    
+    This patch implements low-level uaccess libraries.
+    
+    Signed-off-by: Guan Xuetao 
+    Acked-by: Arnd Bergmann 
+
+diff --git a/arch/unicore32/include/asm/uaccess.h b/arch/unicore32/include/asm/uaccess.h
+new file mode 100644
+index 000000000000..2acda503a6d9
+--- /dev/null
++++ b/arch/unicore32/include/asm/uaccess.h
+@@ -0,0 +1,47 @@
++/*
++ * linux/arch/unicore32/include/asm/uaccess.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_UACCESS_H__
++#define __UNICORE_UACCESS_H__
++
++#include 
++#include 
++
++#include 
++#include 
++
++#define __copy_from_user	__copy_from_user
++#define __copy_to_user		__copy_to_user
++#define __strncpy_from_user	__strncpy_from_user
++#define __strnlen_user		__strnlen_user
++#define __clear_user		__clear_user
++
++#define __kernel_ok		(segment_eq(get_fs(), KERNEL_DS))
++#define __user_ok(addr, size)	(((size) <= TASK_SIZE)			\
++				&& ((addr) <= TASK_SIZE - (size)))
++#define __access_ok(addr, size)	(__kernel_ok || __user_ok((addr), (size)))
++
++extern unsigned long __must_check
++__copy_from_user(void *to, const void __user *from, unsigned long n);
++extern unsigned long __must_check
++__copy_to_user(void __user *to, const void *from, unsigned long n);
++extern unsigned long __must_check
++__clear_user(void __user *addr, unsigned long n);
++extern unsigned long __must_check
++__strncpy_from_user(char *to, const char __user *from, unsigned long count);
++extern unsigned long
++__strnlen_user(const char __user *s, long n);
++
++#include 
++
++extern int fixup_exception(struct pt_regs *regs);
++
++#endif /* __UNICORE_UACCESS_H__ */
+diff --git a/arch/unicore32/lib/clear_user.S b/arch/unicore32/lib/clear_user.S
+new file mode 100644
+index 000000000000..20047f7224fd
+--- /dev/null
++++ b/arch/unicore32/lib/clear_user.S
+@@ -0,0 +1,57 @@
++/*
++ * linux/arch/unicore32/lib/clear_user.S
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++
++		.text
++
++/* Prototype: int __clear_user(void *addr, size_t sz)
++ * Purpose  : clear some user memory
++ * Params   : addr - user memory address to clear
++ *          : sz   - number of bytes to clear
++ * Returns  : number of bytes NOT cleared
++ */
++WEAK(__clear_user)
++		stm.w	(lr), [sp-]
++		stm.w	(r1), [sp-]
++		mov	r2, #0
++		csub.a	r1, #4
++		bsl	2f
++		and.a	ip, r0, #3
++		beq	1f
++		csub.a	ip, #2
++		strusr	r2, r0, 1
++		strusr	r2, r0, 1, el
++		strusr	r2, r0, 1, sl
++		rsub	ip, ip, #4
++		sub	r1, r1, ip		@  7  6  5  4  3  2  1
++1:		sub.a	r1, r1, #8		@ -1 -2 -3 -4 -5 -6 -7
++		strusr	r2, r0, 4, ns, rept=2
++		bns	1b
++		add.a	r1, r1, #4		@  3  2  1  0 -1 -2 -3
++		strusr	r2, r0, 4, ns
++2:		cand.a	r1, #2			@ 1x 1x 0x 0x 1x 1x 0x
++		strusr	r2, r0, 1, ne, rept=2
++		cand.a	r1, #1			@ x1 x0 x1 x0 x1 x0 x1
++		beq	3f
++USER(		stb.u	r2, [r0])
++3:		mov	r0, #0
++		ldm.w	(r1), [sp]+
++		ldm.w	(pc), [sp]+
++ENDPROC(__clear_user)
++
++		.pushsection .fixup,"ax"
++		.align	0
++9001:		ldm.w	(r0), [sp]+
++		ldm.w	(pc), [sp]+
++		.popsection
++
+diff --git a/arch/unicore32/lib/copy_from_user.S b/arch/unicore32/lib/copy_from_user.S
+new file mode 100644
+index 000000000000..ab0767ea5dbd
+--- /dev/null
++++ b/arch/unicore32/lib/copy_from_user.S
+@@ -0,0 +1,108 @@
++/*
++ * linux/arch/unicore32/lib/copy_from_user.S
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include 
++#include 
++
++/*
++ * Prototype:
++ *
++ *	size_t __copy_from_user(void *to, const void *from, size_t n)
++ *
++ * Purpose:
++ *
++ *	copy a block to kernel memory from user memory
++ *
++ * Params:
++ *
++ *	to = kernel memory
++ *	from = user memory
++ *	n = number of bytes to copy
++ *
++ * Return value:
++ *
++ *	Number of bytes NOT copied.
++ */
++
++	.macro ldr1w ptr reg abort
++	ldrusr	\reg, \ptr, 4, abort=\abort
++	.endm
++
++	.macro ldr4w ptr reg1 reg2 reg3 reg4 abort
++100:	ldm.w	(\reg1, \reg2, \reg3, \reg4), [\ptr]+
++	.pushsection __ex_table, "a"
++	.align	3
++	.long 100b, \abort
++	.popsection
++	.endm
++
++	.macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
++100:	ldm.w (\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8), [\ptr]+
++	.pushsection __ex_table, "a"
++	.align	3
++	.long 100b, \abort
++	.popsection
++	.endm
++
++	.macro ldr1b ptr reg cond=al abort
++	ldrusr	\reg, \ptr, 1, \cond, abort=\abort
++	.endm
++
++	.macro str1w ptr reg abort
++	stw.w \reg, [\ptr]+, #4
++	.endm
++
++	.macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
++	stm.w (\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8), [\ptr]+
++	.endm
++
++	.macro str1b ptr reg cond=al abort
++	.ifnc	\cond, al
++	b\cond	201f
++	b	202f
++	.endif
++201:	stb.w \reg, [\ptr]+, #1
++202:
++	.endm
++
++	.macro enter
++	mov	r3, #0
++	stm.w	(r0, r2, r3), [sp-]
++	.endm
++
++	.macro exit
++	add	sp, sp, #8
++	ldm.w	(r0), [sp]+
++	mov	pc, lr
++	.endm
++
++	.text
++
++ENTRY(__copy_from_user)
++
++#include "copy_template.S"
++
++ENDPROC(__copy_from_user)
++
++	.pushsection .fixup,"ax"
++	.align 0
++	copy_abort_preamble
++	ldm.w	(r1, r2), [sp]+
++	sub	r3, r0, r1
++	rsub	r2, r3, r2
++	stw	r2, [sp]
++	mov	r1, #0
++	b.l	memset
++	ldw.w	r0, [sp]+, #4
++	copy_abort_end
++	.popsection
++
+diff --git a/arch/unicore32/lib/copy_page.S b/arch/unicore32/lib/copy_page.S
+new file mode 100644
+index 000000000000..3a448d755ade
+--- /dev/null
++++ b/arch/unicore32/lib/copy_page.S
+@@ -0,0 +1,39 @@
++/*
++ * linux/arch/unicore32/lib/copy_page.S
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ *  ASM optimised string functions
++ */
++#include 
++#include 
++#include 
++#include 
++
++#define COPY_COUNT (PAGE_SZ/256)
++
++		.text
++		.align	5
++/*
++ * UniCore optimised copy_page routine
++ */
++ENTRY(copy_page)
++		stm.w	(r17 - r19, lr), [sp-]
++		mov	r17, r0
++		mov	r18, r1
++		mov	r19, #COPY_COUNT
++1:
++	.rept	4
++		ldm.w	(r0 - r15), [r18]+
++		stm.w	(r0 - r15), [r17]+
++	.endr
++		sub.a	r19, r19, #1
++		bne	1b
++		ldm.w	(r17 - r19, pc), [sp]+
++ENDPROC(copy_page)
+diff --git a/arch/unicore32/lib/copy_template.S b/arch/unicore32/lib/copy_template.S
+new file mode 100644
+index 000000000000..524287fc0120
+--- /dev/null
++++ b/arch/unicore32/lib/copy_template.S
+@@ -0,0 +1,214 @@
++/*
++ * linux/arch/unicore32/lib/copy_template.S
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++/*
++ * Theory of operation
++ * -------------------
++ *
++ * This file provides the core code for a forward memory copy used in
++ * the implementation of memcopy(), copy_to_user() and copy_from_user().
++ *
++ * The including file must define the following accessor macros
++ * according to the need of the given function:
++ *
++ * ldr1w ptr reg abort
++ *
++ *	This loads one word from 'ptr', stores it in 'reg' and increments
++ *	'ptr' to the next word. The 'abort' argument is used for fixup tables.
++ *
++ * ldr4w ptr reg1 reg2 reg3 reg4 abort
++ * ldr8w ptr, reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
++ *
++ *	This loads four or eight words starting from 'ptr', stores them
++ *	in provided registers and increments 'ptr' past those words.
++ *	The'abort' argument is used for fixup tables.
++ *
++ * ldr1b ptr reg cond abort
++ *
++ *	Similar to ldr1w, but it loads a byte and increments 'ptr' one byte.
++ *	It also must apply the condition code if provided, otherwise the
++ *	"al" condition is assumed by default.
++ *
++ * str1w ptr reg abort
++ * str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
++ * str1b ptr reg cond abort
++ *
++ *	Same as their ldr* counterparts, but data is stored to 'ptr' location
++ *	rather than being loaded.
++ *
++ * enter
++ *
++ *	Preserve the provided registers on the stack plus any additional
++ *	data as needed by the implementation including this code. Called
++ *	upon code entry.
++ *
++ * exit
++ *
++ *	Restore registers with the values previously saved with the
++ *	'preserv' macro. Called upon code termination.
++ */
++
++
++		enter
++
++		sub.a	r2, r2, #4
++		bsl	8f
++		and.a	ip, r0, #3
++		bne	9f
++		and.a	ip, r1, #3
++		bne	10f
++
++1:		sub.a	r2, r2, #(28)
++		stm.w	(r5 - r8), [sp-]
++		bsl	5f
++
++3:
++4:		ldr8w	r1, r3, r4, r5, r6, r7, r8, r10, r11, abort=20f
++		sub.a	r2, r2, #32
++		str8w	r0, r3, r4, r5, r6, r7, r8, r10, r11, abort=20f
++		beg	3b
++
++5:		and.a	ip, r2, #28
++		rsub	ip, ip, #32
++		beq	7f
++		add	pc, pc, ip		@ C is always clear here
++		nop
++
++		ldr1w	r1, r3, abort=20f
++		ldr1w	r1, r4, abort=20f
++		ldr1w	r1, r5, abort=20f
++		ldr1w	r1, r6, abort=20f
++		ldr1w	r1, r7, abort=20f
++		ldr1w	r1, r8, abort=20f
++		ldr1w	r1, r11, abort=20f
++
++		add	pc, pc, ip
++		nop
++
++		str1w	r0, r3, abort=20f
++		str1w	r0, r4, abort=20f
++		str1w	r0, r5, abort=20f
++		str1w	r0, r6, abort=20f
++		str1w	r0, r7, abort=20f
++		str1w	r0, r8, abort=20f
++		str1w	r0, r11, abort=20f
++
++7:		ldm.w	(r5 - r8), [sp]+
++
++8:		mov.a	r2, r2 << #31
++		ldr1b	r1, r3, ne, abort=21f
++		ldr1b	r1, r4, ea, abort=21f
++		ldr1b	r1, r10, ea, abort=21f
++		str1b	r0, r3, ne, abort=21f
++		str1b	r0, r4, ea, abort=21f
++		str1b	r0, r10, ea, abort=21f
++
++		exit
++
++9:		rsub	ip, ip, #4
++		csub.a	ip, #2
++		ldr1b	r1, r3, sg, abort=21f
++		ldr1b	r1, r4, eg, abort=21f
++		ldr1b	r1, r11, abort=21f
++		str1b	r0, r3, sg, abort=21f
++		str1b	r0, r4, eg, abort=21f
++		sub.a	r2, r2, ip
++		str1b	r0, r11, abort=21f
++		bsl	8b
++		and.a	ip, r1, #3
++		beq	1b
++
++10:		andn	r1, r1, #3
++		csub.a	ip, #2
++		ldr1w	r1, r11, abort=21f
++		beq	17f
++		bsg	18f
++
++
++		.macro	forward_copy_shift a b
++
++		sub.a	r2, r2, #28
++		bsl	14f
++
++11:		stm.w	(r5 - r9), [sp-]
++
++12:
++		ldr4w	r1, r4, r5, r6, r7, abort=19f
++		mov	r3, r11 pull #\a
++		sub.a	r2, r2, #32
++		ldr4w	r1, r8, r9, r10, r11, abort=19f
++		or	r3, r3, r4 push #\b
++		mov	r4, r4 pull #\a
++		or	r4, r4, r5 push #\b
++		mov	r5, r5 pull #\a
++		or	r5, r5, r6 push #\b
++		mov	r6, r6 pull #\a
++		or	r6, r6, r7 push #\b
++		mov	r7, r7 pull #\a
++		or	r7, r7, r8 push #\b
++		mov	r8, r8 pull #\a
++		or	r8, r8, r9 push #\b
++		mov	r9, r9 pull #\a
++		or	r9, r9, r10 push #\b
++		mov	r10, r10 pull #\a
++		or	r10, r10, r11 push #\b
++		str8w	r0, r3, r4, r5, r6, r7, r8, r9, r10, , abort=19f
++		beg	12b
++
++		ldm.w	(r5 - r9), [sp]+
++
++14:		and.a	ip, r2, #28
++		beq	16f
++
++15:		mov	r3, r11 pull #\a
++		ldr1w	r1, r11, abort=21f
++		sub.a	ip, ip, #4
++		or	r3, r3, r11 push #\b
++		str1w	r0, r3, abort=21f
++		bsg	15b
++
++16:		sub	r1, r1, #(\b / 8)
++		b	8b
++
++		.endm
++
++
++		forward_copy_shift	a=8	b=24
++
++17:		forward_copy_shift	a=16	b=16
++
++18:		forward_copy_shift	a=24	b=8
++
++
++/*
++ * Abort preamble and completion macros.
++ * If a fixup handler is required then those macros must surround it.
++ * It is assumed that the fixup code will handle the private part of
++ * the exit macro.
++ */
++
++	.macro	copy_abort_preamble
++19:	ldm.w	(r5 - r9), [sp]+
++	b	21f
++299:	.word	0			@ store lr
++					@ to avoid function call in fixup
++20:	ldm.w	(r5 - r8), [sp]+
++21:
++	adr	r1, 299b
++	stw	lr, [r1]
++	.endm
++
++	.macro	copy_abort_end
++	adr	lr, 299b
++	ldw	pc, [lr]
++	.endm
++
+diff --git a/arch/unicore32/lib/copy_to_user.S b/arch/unicore32/lib/copy_to_user.S
+new file mode 100644
+index 000000000000..6e22151c840d
+--- /dev/null
++++ b/arch/unicore32/lib/copy_to_user.S
+@@ -0,0 +1,96 @@
++/*
++ * linux/arch/unicore32/lib/copy_to_user.S
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include 
++#include 
++
++/*
++ * Prototype:
++ *
++ *	size_t __copy_to_user(void *to, const void *from, size_t n)
++ *
++ * Purpose:
++ *
++ *	copy a block to user memory from kernel memory
++ *
++ * Params:
++ *
++ *	to = user memory
++ *	from = kernel memory
++ *	n = number of bytes to copy
++ *
++ * Return value:
++ *
++ *	Number of bytes NOT copied.
++ */
++
++	.macro ldr1w ptr reg abort
++	ldw.w \reg, [\ptr]+, #4
++	.endm
++
++	.macro ldr4w ptr reg1 reg2 reg3 reg4 abort
++	ldm.w	(\reg1, \reg2, \reg3, \reg4), [\ptr]+
++	.endm
++
++	.macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
++	ldm.w (\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8), [\ptr]+
++	.endm
++
++	.macro ldr1b ptr reg cond=al abort
++	notcond	\cond, .+8
++	ldb.w \reg, [\ptr]+, #1
++	.endm
++
++	.macro str1w ptr reg abort
++	strusr	\reg, \ptr, 4, abort=\abort
++	.endm
++
++	.macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
++100:	stm.w (\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8), [\ptr]+
++
++	.pushsection __ex_table, "a"
++	.long 100b, \abort
++	.popsection
++	.endm
++
++	.macro str1b ptr reg cond=al abort
++	strusr	\reg, \ptr, 1, \cond, abort=\abort
++	.endm
++
++	.macro enter
++	mov	r3, #0
++	stm.w	(r0, r2, r3), [sp-]
++	.endm
++
++	.macro exit
++	add	sp, sp, #8
++	ldm.w	(r0), [sp]+
++	mov	pc, lr
++	.endm
++
++	.text
++
++WEAK(__copy_to_user)
++
++#include "copy_template.S"
++
++ENDPROC(__copy_to_user)
++
++	.pushsection .fixup,"ax"
++	.align 0
++	copy_abort_preamble
++	ldm.w	(r1, r2, r3), [sp]+
++	sub	r0, r0, r1
++	rsub	r0, r0, r2
++	copy_abort_end
++	.popsection
++
+diff --git a/arch/unicore32/lib/strncpy_from_user.S b/arch/unicore32/lib/strncpy_from_user.S
+new file mode 100644
+index 000000000000..ff6c304d5c7e
+--- /dev/null
++++ b/arch/unicore32/lib/strncpy_from_user.S
+@@ -0,0 +1,45 @@
++/*
++ * linux/arch/unicore32/lib/strncpy_from_user.S
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++
++	.text
++	.align	5
++
++/*
++ * Copy a string from user space to kernel space.
++ *  r0 = dst, r1 = src, r2 = byte length
++ * returns the number of characters copied (strlen of copied string),
++ *  -EFAULT on exception, or "len" if we fill the whole buffer
++ */
++ENTRY(__strncpy_from_user)
++	mov	ip, r1
++1:	sub.a	r2, r2, #1
++	ldrusr	r3, r1, 1, ns
++	bfs	2f
++	stb.w	r3, [r0]+, #1
++	cxor.a	r3, #0
++	bne	1b
++	sub	r1, r1, #1	@ take NUL character out of count
++2:	sub	r0, r1, ip
++	mov	pc, lr
++ENDPROC(__strncpy_from_user)
++
++	.pushsection .fixup,"ax"
++	.align	0
++9001:	mov	r3, #0
++	stb	r3, [r0+], #0	@ null terminate
++	mov	r0, #-EFAULT
++	mov	pc, lr
++	.popsection
++
+diff --git a/arch/unicore32/lib/strnlen_user.S b/arch/unicore32/lib/strnlen_user.S
+new file mode 100644
+index 000000000000..75863030f21d
+--- /dev/null
++++ b/arch/unicore32/lib/strnlen_user.S
+@@ -0,0 +1,42 @@
++/*
++ * linux/arch/unicore32/lib/strnlen_user.S
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++
++	.text
++	.align	5
++
++/* Prototype: unsigned long __strnlen_user(const char *str, long n)
++ * Purpose  : get length of a string in user memory
++ * Params   : str - address of string in user memory
++ * Returns  : length of string *including terminator*
++ *	      or zero on exception, or n + 1 if too long
++ */
++ENTRY(__strnlen_user)
++	mov	r2, r0
++1:
++	ldrusr	r3, r0, 1
++	cxor.a	r3, #0
++	beq	2f
++	sub.a	r1, r1, #1
++	bne	1b
++	add	r0, r0, #1
++2:	sub	r0, r0, r2
++	mov	pc, lr
++ENDPROC(__strnlen_user)
++
++	.pushsection .fixup,"ax"
++	.align	0
++9001:	mov	r0, #0
++	mov	pc, lr
++	.popsection

commit 28bab059a23aac6bb129b307410e5b63e132a290
+Author: GuanXuetao 
+Date:   Sat Jan 15 18:22:19 2011 +0800
+
+    unicore32 additional architecture files: low-level lib: ocd debug
+    
+    This patch implements low-level debug libraries with On-Chip-Debugger hardware support.
+    
+    Signed-off-by: Guan Xuetao 
+    Acked-by: Arnd Bergmann 
+
+diff --git a/arch/unicore32/include/mach/ocd.h b/arch/unicore32/include/mach/ocd.h
+new file mode 100644
+index 000000000000..189fd71bfa34
+--- /dev/null
++++ b/arch/unicore32/include/mach/ocd.h
+@@ -0,0 +1,36 @@
++/*
++ * linux/arch/unicore32/include/mach/ocd.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __MACH_PUV3_OCD_H__
++#define __MACH_PUV3_OCD_H__
++
++#if defined(CONFIG_DEBUG_OCD)
++static inline void ocd_putc(unsigned int c)
++{
++	int status, i = 0x2000000;
++
++	do {
++		if (--i < 0)
++			return;
++
++		asm volatile ("movc %0, p1.c0, #0" : "=r" (status));
++	} while (status & 2);
++
++	asm("movc p1.c1, %0, #1" : : "r" (c));
++}
++
++#define putc(ch)	ocd_putc(ch)
++#else
++#define putc(ch)
++#endif
++
++#endif
+diff --git a/arch/unicore32/kernel/debug-macro.S b/arch/unicore32/kernel/debug-macro.S
+new file mode 100644
+index 000000000000..2711d6d87d8e
+--- /dev/null
++++ b/arch/unicore32/kernel/debug-macro.S
+@@ -0,0 +1,89 @@
++/*
++ * linux/arch/unicore32/kernel/debug-macro.S
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * Debugging macro include header
++ */
++#include 
++#include 
++
++		.macro	put_word_ocd, rd, rx=r16
++1001:		movc		\rx, p1.c0, #0
++		cand.a	\rx, #2
++		bne	1001b
++		movc		p1.c1, \rd, #1
++		.endm
++
++#ifdef CONFIG_DEBUG_OCD
++		/* debug using UniCore On-Chip-Debugger */
++		.macro	addruart, rx
++		.endm
++
++		.macro	senduart, rd, rx
++		put_word_ocd	\rd, \rx
++		.endm
++
++		.macro	busyuart, rd, rx
++		.endm
++
++		.macro	waituart, rd, rx
++		.endm
++#else
++#define UART_CLK_DEFAULT        3686400 * 20
++	/* Uartclk = MCLK/ 2, The MCLK on my board is 3686400 * 40  */
++#define BAUD_RATE_DEFAULT	115200
++	/* The baud rate of the serial port */
++
++#define UART_DIVISOR_DEFAULT	(UART_CLK_DEFAULT \
++				/ (16 * BAUD_RATE_DEFAULT) - 1)
++
++		.macro	addruart,rx
++		mrc	p0, #0, \rx, c1, c0
++		tst	\rx, #1			@ MMU enabled?
++		moveq	\rx, #0xee000000	@ physical base address
++		movne	\rx, #0x6e000000	@ virtual address
++
++		@ We probe for the active serial port here
++		@ However, now we assume UART0 is active:	epip4d
++		@ We assume r1 and r2 can be clobbered.
++
++		movl 	r2, #UART_DIVISOR_DEFAULT
++		mov 	r1, #0x80
++		str	r1, [\rx, #UART_LCR_OFFSET]
++		and	r1, r2, #0xff00
++		mov	r1, r1, lsr #8
++		str	r1, [\rx, #UART_DLH_OFFSET]
++		and	r1, r2, #0xff
++		str	r1, [\rx, #UART_DLL_OFFSET]
++		mov 	r1, #0x7
++		str	r1, [\rx, #UART_FCR_OFFSET]
++		mov 	r1, #0x3
++		str	r1, [\rx, #UART_LCR_OFFSET]
++		mov 	r1, #0x0
++		str	r1, [\rx, #UART_IER_OFFSET]
++		.endm
++
++		.macro	senduart,rd,rx
++		str	\rd, [\rx, #UART_THR_OFFSET]
++		.endm
++
++		.macro	waituart,rd,rx
++1001:		ldr	\rd, [\rx, #UART_LSR_OFFSET]
++		tst	\rd, #UART_LSR_THRE
++		beq	1001b
++		.endm
++
++		.macro	busyuart,rd,rx
++1001:		ldr	\rd, [\rx, #UART_LSR_OFFSET]
++		tst	\rd, #UART_LSR_TEMT
++		bne	1001b
++		.endm
++#endif
++
+diff --git a/arch/unicore32/kernel/debug.S b/arch/unicore32/kernel/debug.S
+new file mode 100644
+index 000000000000..029fd12f6ab0
+--- /dev/null
++++ b/arch/unicore32/kernel/debug.S
+@@ -0,0 +1,85 @@
++/*
++ * linux/arch/unicore32/kernel/debug.S
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ *  32-bit debugging code
++ */
++#include 
++#include 
++
++		.text
++
++/*
++ * Some debugging routines (useful if you've got MM problems and
++ * printk isn't working).  For DEBUGGING ONLY!!!  Do not leave
++ * references to these in a production kernel!
++ */
++#include "debug-macro.S"
++
++/*
++ * Useful debugging routines
++ */
++ENTRY(printhex8)
++		mov	r1, #8
++		b	printhex
++ENDPROC(printhex8)
++
++ENTRY(printhex4)
++		mov	r1, #4
++		b	printhex
++ENDPROC(printhex4)
++
++ENTRY(printhex2)
++		mov	r1, #2
++printhex:	adr	r2, hexbuf
++		add	r3, r2, r1
++		mov	r1, #0
++		stb	r1, [r3]
++1:		and	r1, r0, #15
++		mov	r0, r0 >> #4
++		csub.a	r1, #10
++		beg	2f
++		add	r1, r1, #'0' - 'a' + 10
++2:		add	r1, r1, #'a' - 10
++		stb.w	r1, [r3+], #-1
++		cxor.a	r3, r2
++		bne	1b
++		mov	r0, r2
++		b	printascii
++ENDPROC(printhex2)
++
++		.ltorg
++
++ENTRY(printascii)
++		addruart r3
++		b	2f
++1:		waituart r2, r3
++		senduart r1, r3
++		busyuart r2, r3
++		cxor.a	r1, #'\n'
++		cmoveq	r1, #'\r'
++		beq	1b
++2:		cxor.a	r0, #0
++		beq	3f
++		ldb.w	r1, [r0]+, #1
++		cxor.a	r1, #0
++		bne	1b
++3:		mov	pc, lr
++ENDPROC(printascii)
++
++ENTRY(printch)
++		addruart r3
++		mov	r1, r0
++		mov	r0, #0
++		b	1b
++ENDPROC(printch)
++
++hexbuf:		.space 16
++
+diff --git a/arch/unicore32/kernel/early_printk.c b/arch/unicore32/kernel/early_printk.c
+new file mode 100644
+index 000000000000..3922255f1fa8
+--- /dev/null
++++ b/arch/unicore32/kernel/early_printk.c
+@@ -0,0 +1,59 @@
++/*
++ * linux/arch/unicore32/kernel/early_printk.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++#include 
++
++/* On-Chip-Debugger functions */
++
++static void early_ocd_write(struct console *con, const char *s, unsigned n)
++{
++	while (*s && n-- > 0) {
++		if (*s == '\n')
++			ocd_putc((int)'\r');
++		ocd_putc((int)*s);
++		s++;
++	}
++}
++
++static struct console early_ocd_console = {
++	.name =		"earlyocd",
++	.write =	early_ocd_write,
++	.flags =	CON_PRINTBUFFER,
++	.index =	-1,
++};
++
++/* Direct interface for emergencies */
++static struct console *early_console = &early_ocd_console;
++
++static int __initdata keep_early;
++
++static int __init setup_early_printk(char *buf)
++{
++	if (!buf)
++		return 0;
++
++	if (strstr(buf, "keep"))
++		keep_early = 1;
++
++	if (!strncmp(buf, "ocd", 3))
++		early_console = &early_ocd_console;
++
++	if (keep_early)
++		early_console->flags &= ~CON_BOOT;
++	else
++		early_console->flags |= CON_BOOT;
++	register_console(early_console);
++	return 0;
++}
++early_param("earlyprintk", setup_early_printk);

commit 6dea1ba1c82013c108d235ec32c6d8bd9ff6b48d
+Author: GuanXuetao 
+Date:   Sat Jan 15 18:21:56 2011 +0800
+
+    unicore32 additional architecture files: ptrace handling
+    
+    This patch adds ptrace support.
+    
+    Changed from previous version:
+        1. disable arch_has_single_step and remove single-step instruction handler
+        2. add 'Ross Biro 1/23/92' contributor information
+        3. clean unused codes
+    
+    Signed-off-by: Guan Xuetao 
+    Acked-by: Arnd Bergmann 
+
+diff --git a/arch/unicore32/include/asm/ptrace.h b/arch/unicore32/include/asm/ptrace.h
+new file mode 100644
+index 000000000000..b9caf9b0997b
+--- /dev/null
++++ b/arch/unicore32/include/asm/ptrace.h
+@@ -0,0 +1,133 @@
++/*
++ * linux/arch/unicore32/include/asm/ptrace.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_PTRACE_H__
++#define __UNICORE_PTRACE_H__
++
++#define PTRACE_GET_THREAD_AREA	22
++
++/*
++ * PSR bits
++ */
++#define USER_MODE	0x00000010
++#define REAL_MODE	0x00000011
++#define INTR_MODE	0x00000012
++#define PRIV_MODE	0x00000013
++#define ABRT_MODE	0x00000017
++#define EXTN_MODE	0x0000001b
++#define SUSR_MODE	0x0000001f
++#define MODE_MASK	0x0000001f
++#define PSR_R_BIT	0x00000040
++#define PSR_I_BIT	0x00000080
++#define PSR_V_BIT	0x10000000
++#define PSR_C_BIT	0x20000000
++#define PSR_Z_BIT	0x40000000
++#define PSR_S_BIT	0x80000000
++
++/*
++ * Groups of PSR bits
++ */
++#define PSR_f		0xff000000	/* Flags		*/
++#define PSR_c		0x000000ff	/* Control		*/
++
++#ifndef __ASSEMBLY__
++
++/*
++ * This struct defines the way the registers are stored on the
++ * stack during a system call.  Note that sizeof(struct pt_regs)
++ * has to be a multiple of 8.
++ */
++struct pt_regs {
++	unsigned long uregs[34];
++};
++
++#define UCreg_asr		uregs[32]
++#define UCreg_pc		uregs[31]
++#define UCreg_lr		uregs[30]
++#define UCreg_sp		uregs[29]
++#define UCreg_ip		uregs[28]
++#define UCreg_fp		uregs[27]
++#define UCreg_26		uregs[26]
++#define UCreg_25		uregs[25]
++#define UCreg_24		uregs[24]
++#define UCreg_23		uregs[23]
++#define UCreg_22		uregs[22]
++#define UCreg_21		uregs[21]
++#define UCreg_20		uregs[20]
++#define UCreg_19		uregs[19]
++#define UCreg_18		uregs[18]
++#define UCreg_17		uregs[17]
++#define UCreg_16		uregs[16]
++#define UCreg_15		uregs[15]
++#define UCreg_14		uregs[14]
++#define UCreg_13		uregs[13]
++#define UCreg_12		uregs[12]
++#define UCreg_11		uregs[11]
++#define UCreg_10		uregs[10]
++#define UCreg_09		uregs[9]
++#define UCreg_08		uregs[8]
++#define UCreg_07		uregs[7]
++#define UCreg_06		uregs[6]
++#define UCreg_05		uregs[5]
++#define UCreg_04		uregs[4]
++#define UCreg_03		uregs[3]
++#define UCreg_02		uregs[2]
++#define UCreg_01		uregs[1]
++#define UCreg_00		uregs[0]
++#define UCreg_ORIG_00		uregs[33]
++
++#ifdef __KERNEL__
++
++#define user_mode(regs)	\
++	(processor_mode(regs) == USER_MODE)
++
++#define processor_mode(regs) \
++	((regs)->UCreg_asr & MODE_MASK)
++
++#define interrupts_enabled(regs) \
++	(!((regs)->UCreg_asr & PSR_I_BIT))
++
++#define fast_interrupts_enabled(regs) \
++	(!((regs)->UCreg_asr & PSR_R_BIT))
++
++/* Are the current registers suitable for user mode?
++ * (used to maintain security in signal handlers)
++ */
++static inline int valid_user_regs(struct pt_regs *regs)
++{
++	unsigned long mode = regs->UCreg_asr & MODE_MASK;
++
++	/*
++	 * Always clear the R (REAL) bits
++	 */
++	regs->UCreg_asr &= ~(PSR_R_BIT);
++
++	if ((regs->UCreg_asr & PSR_I_BIT) == 0) {
++		if (mode == USER_MODE)
++			return 1;
++	}
++
++	/*
++	 * Force ASR to something logical...
++	 */
++	regs->UCreg_asr &= PSR_f | USER_MODE;
++
++	return 0;
++}
++
++#define instruction_pointer(regs)	((regs)->UCreg_pc)
++
++#endif /* __KERNEL__ */
++
++#endif /* __ASSEMBLY__ */
++
++#endif
++
+diff --git a/arch/unicore32/kernel/ptrace.c b/arch/unicore32/kernel/ptrace.c
+new file mode 100644
+index 000000000000..9f07c08da050
+--- /dev/null
++++ b/arch/unicore32/kernel/ptrace.c
+@@ -0,0 +1,149 @@
++/*
++ * linux/arch/unicore32/kernel/ptrace.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * By Ross Biro 1/23/92
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++#include 
++
++/*
++ * this routine will get a word off of the processes privileged stack.
++ * the offset is how far from the base addr as stored in the THREAD.
++ * this routine assumes that all the privileged stacks are in our
++ * data space.
++ */
++static inline long get_user_reg(struct task_struct *task, int offset)
++{
++	return task_pt_regs(task)->uregs[offset];
++}
++
++/*
++ * this routine will put a word on the processes privileged stack.
++ * the offset is how far from the base addr as stored in the THREAD.
++ * this routine assumes that all the privileged stacks are in our
++ * data space.
++ */
++static inline int
++put_user_reg(struct task_struct *task, int offset, long data)
++{
++	struct pt_regs newregs, *regs = task_pt_regs(task);
++	int ret = -EINVAL;
++
++	newregs = *regs;
++	newregs.uregs[offset] = data;
++
++	if (valid_user_regs(&newregs)) {
++		regs->uregs[offset] = data;
++		ret = 0;
++	}
++
++	return ret;
++}
++
++/*
++ * Called by kernel/ptrace.c when detaching..
++ */
++void ptrace_disable(struct task_struct *child)
++{
++}
++
++/*
++ * We actually access the pt_regs stored on the kernel stack.
++ */
++static int ptrace_read_user(struct task_struct *tsk, unsigned long off,
++			    unsigned long __user *ret)
++{
++	unsigned long tmp;
++
++	tmp = 0;
++	if (off < sizeof(struct pt_regs))
++		tmp = get_user_reg(tsk, off >> 2);
++
++	return put_user(tmp, ret);
++}
++
++/*
++ * We actually access the pt_regs stored on the kernel stack.
++ */
++static int ptrace_write_user(struct task_struct *tsk, unsigned long off,
++			     unsigned long val)
++{
++	if (off >= sizeof(struct pt_regs))
++		return 0;
++
++	return put_user_reg(tsk, off >> 2, val);
++}
++
++long arch_ptrace(struct task_struct *child, long request,
++		 unsigned long addr, unsigned long data)
++{
++	int ret;
++	unsigned long __user *datap = (unsigned long __user *) data;
++
++	switch (request) {
++	case PTRACE_PEEKUSR:
++		ret = ptrace_read_user(child, addr, datap);
++		break;
++
++	case PTRACE_POKEUSR:
++		ret = ptrace_write_user(child, addr, data);
++		break;
++
++	case PTRACE_GET_THREAD_AREA:
++		ret = put_user(task_pt_regs(child)->UCreg_16,
++			       datap);
++		break;
++
++	default:
++		ret = ptrace_request(child, request, addr, data);
++		break;
++	}
++
++	return ret;
++}
++
++asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
++{
++	unsigned long ip;
++
++	if (!test_thread_flag(TIF_SYSCALL_TRACE))
++		return scno;
++	if (!(current->ptrace & PT_PTRACED))
++		return scno;
++
++	/*
++	 * Save IP.  IP is used to denote syscall entry/exit:
++	 *  IP = 0 -> entry, = 1 -> exit
++	 */
++	ip = regs->UCreg_ip;
++	regs->UCreg_ip = why;
++
++	current_thread_info()->syscall = scno;
++
++	/* the 0x80 provides a way for the tracing parent to distinguish
++	   between a syscall stop and SIGTRAP delivery */
++	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
++				 ? 0x80 : 0));
++	/*
++	 * this isn't the same as continuing with a signal, but it will do
++	 * for normal use.  strace only continues with a signal if the
++	 * stopping signal is not SIGTRAP.  -brl
++	 */
++	if (current->exit_code) {
++		send_sig(current->exit_code, current, 1);
++		current->exit_code = 0;
++	}
++	regs->UCreg_ip = ip;
++
++	return current_thread_info()->syscall;
++}

commit d9bc15794d122cb7bdc9a069d22f3d3166dd31d4
+Author: GuanXuetao 
+Date:   Sat Jan 15 18:21:31 2011 +0800
+
+    unicore32 additional architecture files: float point handling
+    
+    This patch implements support for float point unit, which using UniCore-F64 FPU hardware
+    in UniCore32 ISA.
+    
+    Signed-off-by: Guan Xuetao 
+    Acked-by: Arnd Bergmann 
+
+diff --git a/arch/unicore32/include/asm/fpstate.h b/arch/unicore32/include/asm/fpstate.h
+new file mode 100644
+index 000000000000..ba97fac6220d
+--- /dev/null
++++ b/arch/unicore32/include/asm/fpstate.h
+@@ -0,0 +1,26 @@
++/*
++ * linux/arch/unicore32/include/asm/fpstate.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __UNICORE_FPSTATE_H__
++#define __UNICORE_FPSTATE_H__
++
++#ifndef __ASSEMBLY__
++
++#define FP_REGS_NUMBER		33
++
++struct fp_state {
++	unsigned int regs[FP_REGS_NUMBER];
++} __attribute__((aligned(8)));
++
++#endif
++
++#endif
+diff --git a/arch/unicore32/include/asm/fpu-ucf64.h b/arch/unicore32/include/asm/fpu-ucf64.h
+new file mode 100644
+index 000000000000..16c1457882ee
+--- /dev/null
++++ b/arch/unicore32/include/asm/fpu-ucf64.h
+@@ -0,0 +1,53 @@
++/*
++ * linux/arch/unicore32/include/asm/fpu-ucf64.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ *	Maintained by GUAN Xue-tao 
++ *	Copyright (C) 2001-2010 Guan Xuetao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#define FPSCR			s31
++
++/* FPSCR bits */
++#define FPSCR_DEFAULT_NAN	(1<<25)
++
++#define FPSCR_CMPINSTR_BIT	(1<<31)
++
++#define FPSCR_CON		(1<<29)
++#define FPSCR_TRAP		(1<<27)
++
++/* RND mode */
++#define FPSCR_ROUND_NEAREST	(0<<0)
++#define FPSCR_ROUND_PLUSINF	(2<<0)
++#define FPSCR_ROUND_MINUSINF	(3<<0)
++#define FPSCR_ROUND_TOZERO	(1<<0)
++#define FPSCR_RMODE_BIT		(0)
++#define FPSCR_RMODE_MASK	(7 << FPSCR_RMODE_BIT)
++
++/* trap enable */
++#define FPSCR_IOE		(1<<16)
++#define FPSCR_OFE		(1<<14)
++#define FPSCR_UFE		(1<<13)
++#define FPSCR_IXE		(1<<12)
++#define FPSCR_HIE		(1<<11)
++#define FPSCR_NDE		(1<<10)	/* non denomal */
++
++/* flags */
++#define FPSCR_IDC		(1<<24)
++#define FPSCR_HIC		(1<<23)
++#define FPSCR_IXC		(1<<22)
++#define FPSCR_OFC		(1<<21)
++#define FPSCR_UFC		(1<<20)
++#define FPSCR_IOC		(1<<19)
++
++/* stick bits */
++#define FPSCR_IOS		(1<<9)
++#define FPSCR_OFS		(1<<7)
++#define FPSCR_UFS		(1<<6)
++#define FPSCR_IXS		(1<<5)
++#define FPSCR_HIS		(1<<4)
++#define FPSCR_NDS		(1<<3)	/*non denomal */
+diff --git a/arch/unicore32/kernel/fpu-ucf64.c b/arch/unicore32/kernel/fpu-ucf64.c
+new file mode 100644
+index 000000000000..282a60ac82ba
+--- /dev/null
++++ b/arch/unicore32/kernel/fpu-ucf64.c
+@@ -0,0 +1,126 @@
++/*
++ * linux/arch/unicore32/kernel/fpu-ucf64.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++
++/*
++ * A special flag to tell the normalisation code not to normalise.
++ */
++#define F64_NAN_FLAG	0x100
++
++/*
++ * A bit pattern used to indicate the initial (unset) value of the
++ * exception mask, in case nothing handles an instruction.  This
++ * doesn't include the NAN flag, which get masked out before
++ * we check for an error.
++ */
++#define F64_EXCEPTION_ERROR	((u32)-1 & ~F64_NAN_FLAG)
++
++/*
++ * Since we aren't building with -mfpu=f64, we need to code
++ * these instructions using their MRC/MCR equivalents.
++ */
++#define f64reg(_f64_) #_f64_
++
++#define cff(_f64_) ({			\
++	u32 __v;			\
++	asm("cff %0, " f64reg(_f64_) "@ fmrx	%0, " #_f64_	\
++	    : "=r" (__v) : : "cc");	\
++	__v;				\
++	})
++
++#define ctf(_f64_, _var_)		\
++	asm("ctf %0, " f64reg(_f64_) "@ fmxr	" #_f64_ ", %0"	\
++	   : : "r" (_var_) : "cc")
++
++/*
++ * Raise a SIGFPE for the current process.
++ * sicode describes the signal being raised.
++ */
++void ucf64_raise_sigfpe(unsigned int sicode, struct pt_regs *regs)
++{
++	siginfo_t info;
++
++	memset(&info, 0, sizeof(info));
++
++	info.si_signo = SIGFPE;
++	info.si_code = sicode;
++	info.si_addr = (void __user *)(instruction_pointer(regs) - 4);
++
++	/*
++	 * This is the same as NWFPE, because it's not clear what
++	 * this is used for
++	 */
++	current->thread.error_code = 0;
++	current->thread.trap_no = 6;
++
++	send_sig_info(SIGFPE, &info, current);
++}
++
++/*
++ * Handle exceptions of UniCore-F64.
++ */
++void ucf64_exchandler(u32 inst, u32 fpexc, struct pt_regs *regs)
++{
++	u32 tmp = fpexc;
++	u32 exc = F64_EXCEPTION_ERROR & fpexc;
++
++	pr_debug("UniCore-F64: instruction %08x fpscr %08x\n",
++			inst, fpexc);
++
++	if (exc & FPSCR_CMPINSTR_BIT) {
++		if (exc & FPSCR_CON)
++			tmp |= FPSCR_CON;
++		else
++			tmp &= ~(FPSCR_CON);
++		exc &= ~(FPSCR_CMPINSTR_BIT | FPSCR_CON);
++	} else {
++		pr_debug(KERN_ERR "UniCore-F64 Error: unhandled exceptions\n");
++		pr_debug(KERN_ERR "UniCore-F64 FPSCR 0x%08x INST 0x%08x\n",
++				cff(FPSCR), inst);
++
++		ucf64_raise_sigfpe(0, regs);
++		return;
++	}
++
++	/*
++	 * Update the FPSCR with the additional exception flags.
++	 * Comparison instructions always return at least one of
++	 * these flags set.
++	 */
++	tmp &= ~(FPSCR_TRAP | FPSCR_IOS | FPSCR_OFS | FPSCR_UFS |
++			FPSCR_IXS | FPSCR_HIS | FPSCR_IOC | FPSCR_OFC |
++			FPSCR_UFC | FPSCR_IXC | FPSCR_HIC);
++
++	tmp |= exc;
++	ctf(FPSCR, tmp);
++}
++
++/*
++ * F64 support code initialisation.
++ */
++static int __init ucf64_init(void)
++{
++	ctf(FPSCR, 0x0);     /* FPSCR_UFE | FPSCR_NDE perhaps better */
++
++	printk(KERN_INFO "Enable UniCore-F64 support.\n");
++
++	return 0;
++}
++
++late_initcall(ucf64_init);

commit 64909882862e9bb88aa6177e3f92056f5601b3e3
+Author: GuanXuetao 
+Date:   Sat Feb 26 20:23:59 2011 +0800
+
+    unicore32 additional architecture files: pm related files
+    
+    This patch adds pm related files, including hibernate and sleep supports.
+    
+    Signed-off-by: Guan Xuetao 
+    Acked-by: Arnd Bergmann 
+
+diff --git a/arch/unicore32/include/asm/suspend.h b/arch/unicore32/include/asm/suspend.h
+new file mode 100644
+index 000000000000..88a9c0f32b21
+--- /dev/null
++++ b/arch/unicore32/include/asm/suspend.h
+@@ -0,0 +1,30 @@
++/*
++ * linux/arch/unicore32/include/asm/suspend.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __UNICORE_SUSPEND_H__
++#define __UNICORE_SUSPEND_H__
++
++#ifndef __ASSEMBLY__
++static inline int arch_prepare_suspend(void) { return 0; }
++
++#include 
++
++struct swsusp_arch_regs {
++	struct cpu_context_save	cpu_context;	/* cpu context */
++#ifdef CONFIG_UNICORE_FPU_F64
++	struct fp_state		fpstate __attribute__((aligned(8)));
++#endif
++};
++#endif
++
++#endif /* __UNICORE_SUSPEND_H__ */
++
+diff --git a/arch/unicore32/include/mach/pm.h b/arch/unicore32/include/mach/pm.h
+new file mode 100644
+index 000000000000..4dcd34ae194c
+--- /dev/null
++++ b/arch/unicore32/include/mach/pm.h
+@@ -0,0 +1,43 @@
++/*
++ * linux/arch/unicore/include/mach/pm.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __PUV3_PM_H__
++#define __PUV3_PM_H__
++
++#include 
++
++struct puv3_cpu_pm_fns {
++	int	save_count;
++	void	(*save)(unsigned long *);
++	void	(*restore)(unsigned long *);
++	int	(*valid)(suspend_state_t state);
++	void	(*enter)(suspend_state_t state);
++	int	(*prepare)(void);
++	void	(*finish)(void);
++};
++
++extern struct puv3_cpu_pm_fns *puv3_cpu_pm_fns;
++
++/* sleep.S */
++extern void puv3_cpu_suspend(unsigned int);
++
++extern void puv3_cpu_resume(void);
++
++extern int puv3_pm_enter(suspend_state_t state);
++
++/* Defined in hibernate_asm.S */
++extern int restore_image(pgd_t *resume_pg_dir, struct pbe *restore_pblist);
++
++/* References to section boundaries */
++extern const void __nosave_begin, __nosave_end;
++
++extern struct pbe *restore_pblist;
++#endif
+diff --git a/arch/unicore32/kernel/clock.c b/arch/unicore32/kernel/clock.c
+new file mode 100644
+index 000000000000..80323db581fd
+--- /dev/null
++++ b/arch/unicore32/kernel/clock.c
+@@ -0,0 +1,388 @@
++/*
++ * linux/arch/unicore32/kernel/clock.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ *	Maintained by GUAN Xue-tao 
++ *	Copyright (C) 2001-2010 Guan Xuetao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++
++/*
++ * Very simple clock implementation
++ */
++struct clk {
++	struct list_head	node;
++	unsigned long		rate;
++	const char		*name;
++};
++
++static struct clk clk_ost_clk = {
++	.name		= "OST_CLK",
++	.rate		= CLOCK_TICK_RATE,
++};
++
++static struct clk clk_mclk_clk = {
++	.name		= "MAIN_CLK",
++};
++
++static struct clk clk_bclk32_clk = {
++	.name		= "BUS32_CLK",
++};
++
++static struct clk clk_ddr_clk = {
++	.name		= "DDR_CLK",
++};
++
++static struct clk clk_vga_clk = {
++	.name		= "VGA_CLK",
++};
++
++static LIST_HEAD(clocks);
++static DEFINE_MUTEX(clocks_mutex);
++
++struct clk *clk_get(struct device *dev, const char *id)
++{
++	struct clk *p, *clk = ERR_PTR(-ENOENT);
++
++	mutex_lock(&clocks_mutex);
++	list_for_each_entry(p, &clocks, node) {
++		if (strcmp(id, p->name) == 0) {
++			clk = p;
++			break;
++		}
++	}
++	mutex_unlock(&clocks_mutex);
++
++	return clk;
++}
++EXPORT_SYMBOL(clk_get);
++
++void clk_put(struct clk *clk)
++{
++}
++EXPORT_SYMBOL(clk_put);
++
++int clk_enable(struct clk *clk)
++{
++	return 0;
++}
++EXPORT_SYMBOL(clk_enable);
++
++void clk_disable(struct clk *clk)
++{
++}
++EXPORT_SYMBOL(clk_disable);
++
++unsigned long clk_get_rate(struct clk *clk)
++{
++	return clk->rate;
++}
++EXPORT_SYMBOL(clk_get_rate);
++
++struct {
++	unsigned long rate;
++	unsigned long cfg;
++	unsigned long div;
++} vga_clk_table[] = {
++	{.rate =  25175000, .cfg = 0x00002001, .div = 0x9},
++	{.rate =  31500000, .cfg = 0x00002001, .div = 0x7},
++	{.rate =  40000000, .cfg = 0x00003801, .div = 0x9},
++	{.rate =  49500000, .cfg = 0x00003801, .div = 0x7},
++	{.rate =  65000000, .cfg = 0x00002c01, .div = 0x4},
++	{.rate =  78750000, .cfg = 0x00002400, .div = 0x7},
++	{.rate = 108000000, .cfg = 0x00002c01, .div = 0x2},
++	{.rate = 106500000, .cfg = 0x00003c01, .div = 0x3},
++	{.rate =  50650000, .cfg = 0x00106400, .div = 0x9},
++	{.rate =  61500000, .cfg = 0x00106400, .div = 0xa},
++	{.rate =  85500000, .cfg = 0x00002800, .div = 0x6},
++};
++
++struct {
++	unsigned long mrate;
++	unsigned long prate;
++} mclk_clk_table[] = {
++	{.mrate = 500000000, .prate = 0x00109801},
++	{.mrate = 525000000, .prate = 0x00104C00},
++	{.mrate = 550000000, .prate = 0x00105000},
++	{.mrate = 575000000, .prate = 0x00105400},
++	{.mrate = 600000000, .prate = 0x00105800},
++	{.mrate = 625000000, .prate = 0x00105C00},
++	{.mrate = 650000000, .prate = 0x00106000},
++	{.mrate = 675000000, .prate = 0x00106400},
++	{.mrate = 700000000, .prate = 0x00106800},
++	{.mrate = 725000000, .prate = 0x00106C00},
++	{.mrate = 750000000, .prate = 0x00107000},
++	{.mrate = 775000000, .prate = 0x00107400},
++	{.mrate = 800000000, .prate = 0x00107800},
++};
++
++int clk_set_rate(struct clk *clk, unsigned long rate)
++{
++	if (clk == &clk_vga_clk) {
++		unsigned long pll_vgacfg, pll_vgadiv;
++		int ret, i;
++
++		/* lookup vga_clk_table */
++		ret = -EINVAL;
++		for (i = 0; i < ARRAY_SIZE(vga_clk_table); i++) {
++			if (rate == vga_clk_table[i].rate) {
++				pll_vgacfg = vga_clk_table[i].cfg;
++				pll_vgadiv = vga_clk_table[i].div;
++				ret = 0;
++				break;
++			}
++		}
++
++		if (ret)
++			return ret;
++
++		if (PM_PLLVGACFG == pll_vgacfg)
++			return 0;
++
++		/* set pll vga cfg reg. */
++		PM_PLLVGACFG = pll_vgacfg;
++
++		PM_PMCR = PM_PMCR_CFBVGA;
++		while ((PM_PLLDFCDONE & PM_PLLDFCDONE_VGADFC)
++				!= PM_PLLDFCDONE_VGADFC)
++			udelay(100); /* about 1ms */
++
++		/* set div cfg reg. */
++		PM_PCGR |= PM_PCGR_VGACLK;
++
++		PM_DIVCFG = (PM_DIVCFG & ~PM_DIVCFG_VGACLK_MASK)
++				| PM_DIVCFG_VGACLK(pll_vgadiv);
++
++		PM_SWRESET |= PM_SWRESET_VGADIV;
++		while ((PM_SWRESET & PM_SWRESET_VGADIV) == PM_SWRESET_VGADIV)
++			udelay(100); /* 65536 bclk32, about 320us */
++
++		PM_PCGR &= ~PM_PCGR_VGACLK;
++	}
++#ifdef CONFIG_CPU_FREQ
++	if (clk == &clk_mclk_clk) {
++		u32 pll_rate, divstatus = PM_DIVSTATUS;
++		int ret, i;
++
++		/* lookup mclk_clk_table */
++		ret = -EINVAL;
++		for (i = 0; i < ARRAY_SIZE(mclk_clk_table); i++) {
++			if (rate == mclk_clk_table[i].mrate) {
++				pll_rate = mclk_clk_table[i].prate;
++				clk_mclk_clk.rate = mclk_clk_table[i].mrate;
++				ret = 0;
++				break;
++			}
++		}
++
++		if (ret)
++			return ret;
++
++		if (clk_mclk_clk.rate)
++			clk_bclk32_clk.rate = clk_mclk_clk.rate
++				/ (((divstatus & 0x0000f000) >> 12) + 1);
++
++		/* set pll sys cfg reg. */
++		PM_PLLSYSCFG = pll_rate;
++
++		PM_PMCR = PM_PMCR_CFBSYS;
++		while ((PM_PLLDFCDONE & PM_PLLDFCDONE_SYSDFC)
++				!= PM_PLLDFCDONE_SYSDFC)
++			udelay(100);
++			/* about 1ms */
++	}
++#endif
++	return 0;
++}
++EXPORT_SYMBOL(clk_set_rate);
++
++int clk_register(struct clk *clk)
++{
++	mutex_lock(&clocks_mutex);
++	list_add(&clk->node, &clocks);
++	mutex_unlock(&clocks_mutex);
++	printk(KERN_DEFAULT "PKUnity PM: %s %lu.%02luM\n", clk->name,
++		(clk->rate)/1000000, (clk->rate)/10000 % 100);
++	return 0;
++}
++EXPORT_SYMBOL(clk_register);
++
++void clk_unregister(struct clk *clk)
++{
++	mutex_lock(&clocks_mutex);
++	list_del(&clk->node);
++	mutex_unlock(&clocks_mutex);
++}
++EXPORT_SYMBOL(clk_unregister);
++
++struct {
++	unsigned long prate;
++	unsigned long rate;
++} pllrate_table[] = {
++	{.prate = 0x00002001, .rate = 250000000},
++	{.prate = 0x00104801, .rate = 250000000},
++	{.prate = 0x00104C01, .rate = 262500000},
++	{.prate = 0x00002401, .rate = 275000000},
++	{.prate = 0x00105001, .rate = 275000000},
++	{.prate = 0x00105401, .rate = 287500000},
++	{.prate = 0x00002801, .rate = 300000000},
++	{.prate = 0x00105801, .rate = 300000000},
++	{.prate = 0x00105C01, .rate = 312500000},
++	{.prate = 0x00002C01, .rate = 325000000},
++	{.prate = 0x00106001, .rate = 325000000},
++	{.prate = 0x00106401, .rate = 337500000},
++	{.prate = 0x00003001, .rate = 350000000},
++	{.prate = 0x00106801, .rate = 350000000},
++	{.prate = 0x00106C01, .rate = 362500000},
++	{.prate = 0x00003401, .rate = 375000000},
++	{.prate = 0x00107001, .rate = 375000000},
++	{.prate = 0x00107401, .rate = 387500000},
++	{.prate = 0x00003801, .rate = 400000000},
++	{.prate = 0x00107801, .rate = 400000000},
++	{.prate = 0x00107C01, .rate = 412500000},
++	{.prate = 0x00003C01, .rate = 425000000},
++	{.prate = 0x00108001, .rate = 425000000},
++	{.prate = 0x00108401, .rate = 437500000},
++	{.prate = 0x00004001, .rate = 450000000},
++	{.prate = 0x00108801, .rate = 450000000},
++	{.prate = 0x00108C01, .rate = 462500000},
++	{.prate = 0x00004401, .rate = 475000000},
++	{.prate = 0x00109001, .rate = 475000000},
++	{.prate = 0x00109401, .rate = 487500000},
++	{.prate = 0x00004801, .rate = 500000000},
++	{.prate = 0x00109801, .rate = 500000000},
++	{.prate = 0x00104C00, .rate = 525000000},
++	{.prate = 0x00002400, .rate = 550000000},
++	{.prate = 0x00105000, .rate = 550000000},
++	{.prate = 0x00105400, .rate = 575000000},
++	{.prate = 0x00002800, .rate = 600000000},
++	{.prate = 0x00105800, .rate = 600000000},
++	{.prate = 0x00105C00, .rate = 625000000},
++	{.prate = 0x00002C00, .rate = 650000000},
++	{.prate = 0x00106000, .rate = 650000000},
++	{.prate = 0x00106400, .rate = 675000000},
++	{.prate = 0x00003000, .rate = 700000000},
++	{.prate = 0x00106800, .rate = 700000000},
++	{.prate = 0x00106C00, .rate = 725000000},
++	{.prate = 0x00003400, .rate = 750000000},
++	{.prate = 0x00107000, .rate = 750000000},
++	{.prate = 0x00107400, .rate = 775000000},
++	{.prate = 0x00003800, .rate = 800000000},
++	{.prate = 0x00107800, .rate = 800000000},
++	{.prate = 0x00107C00, .rate = 825000000},
++	{.prate = 0x00003C00, .rate = 850000000},
++	{.prate = 0x00108000, .rate = 850000000},
++	{.prate = 0x00108400, .rate = 875000000},
++	{.prate = 0x00004000, .rate = 900000000},
++	{.prate = 0x00108800, .rate = 900000000},
++	{.prate = 0x00108C00, .rate = 925000000},
++	{.prate = 0x00004400, .rate = 950000000},
++	{.prate = 0x00109000, .rate = 950000000},
++	{.prate = 0x00109400, .rate = 975000000},
++	{.prate = 0x00004800, .rate = 1000000000},
++	{.prate = 0x00109800, .rate = 1000000000},
++};
++
++struct {
++	unsigned long prate;
++	unsigned long drate;
++} pddr_table[] = {
++	{.prate = 0x00100800, .drate = 44236800},
++	{.prate = 0x00100C00, .drate = 66355200},
++	{.prate = 0x00101000, .drate = 88473600},
++	{.prate = 0x00101400, .drate = 110592000},
++	{.prate = 0x00101800, .drate = 132710400},
++	{.prate = 0x00101C01, .drate = 154828800},
++	{.prate = 0x00102001, .drate = 176947200},
++	{.prate = 0x00102401, .drate = 199065600},
++	{.prate = 0x00102801, .drate = 221184000},
++	{.prate = 0x00102C01, .drate = 243302400},
++	{.prate = 0x00103001, .drate = 265420800},
++	{.prate = 0x00103401, .drate = 287539200},
++	{.prate = 0x00103801, .drate = 309657600},
++	{.prate = 0x00103C01, .drate = 331776000},
++	{.prate = 0x00104001, .drate = 353894400},
++};
++
++static int __init clk_init(void)
++{
++#ifdef CONFIG_PUV3_PM
++	u32 pllrate, divstatus = PM_DIVSTATUS;
++	u32 pcgr_val = PM_PCGR;
++	int i;
++
++	pcgr_val |= PM_PCGR_BCLKMME | PM_PCGR_BCLKH264E | PM_PCGR_BCLKH264D
++			| PM_PCGR_HECLK | PM_PCGR_HDCLK;
++	PM_PCGR = pcgr_val;
++
++	pllrate = PM_PLLSYSSTATUS;
++
++	/* lookup pmclk_table */
++	clk_mclk_clk.rate = 0;
++	for (i = 0; i < ARRAY_SIZE(pllrate_table); i++) {
++		if (pllrate == pllrate_table[i].prate) {
++			clk_mclk_clk.rate = pllrate_table[i].rate;
++			break;
++		}
++	}
++
++	if (clk_mclk_clk.rate)
++		clk_bclk32_clk.rate = clk_mclk_clk.rate /
++			(((divstatus & 0x0000f000) >> 12) + 1);
++
++	pllrate = PM_PLLDDRSTATUS;
++
++	/* lookup pddr_table */
++	clk_ddr_clk.rate = 0;
++	for (i = 0; i < ARRAY_SIZE(pddr_table); i++) {
++		if (pllrate == pddr_table[i].prate) {
++			clk_ddr_clk.rate = pddr_table[i].drate;
++			break;
++		}
++	}
++
++	pllrate = PM_PLLVGASTATUS;
++
++	/* lookup pvga_table */
++	clk_vga_clk.rate = 0;
++	for (i = 0; i < ARRAY_SIZE(pllrate_table); i++) {
++		if (pllrate == pllrate_table[i].prate) {
++			clk_vga_clk.rate = pllrate_table[i].rate;
++			break;
++		}
++	}
++
++	if (clk_vga_clk.rate)
++		clk_vga_clk.rate = clk_vga_clk.rate /
++			(((divstatus & 0x00f00000) >> 20) + 1);
++
++	clk_register(&clk_vga_clk);
++#endif
++#ifdef CONFIG_ARCH_FPGA
++	clk_ddr_clk.rate = 33000000;
++	clk_mclk_clk.rate = 33000000;
++	clk_bclk32_clk.rate = 33000000;
++#endif
++	clk_register(&clk_ddr_clk);
++	clk_register(&clk_mclk_clk);
++	clk_register(&clk_bclk32_clk);
++	clk_register(&clk_ost_clk);
++	return 0;
++}
++core_initcall(clk_init);
+diff --git a/arch/unicore32/kernel/cpu-ucv2.c b/arch/unicore32/kernel/cpu-ucv2.c
+new file mode 100644
+index 000000000000..4a99f62584c7
+--- /dev/null
++++ b/arch/unicore32/kernel/cpu-ucv2.c
+@@ -0,0 +1,93 @@
++/*
++ * linux/arch/unicore32/kernel/cpu-ucv2.c: clock scaling for the UniCore-II
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ *	Maintained by GUAN Xue-tao 
++ *	Copyright (C) 2001-2010 Guan Xuetao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++
++static struct cpufreq_driver ucv2_driver;
++
++/* make sure that only the "userspace" governor is run
++ * -- anything else wouldn't make sense on this platform, anyway.
++ */
++int ucv2_verify_speed(struct cpufreq_policy *policy)
++{
++	if (policy->cpu)
++		return -EINVAL;
++
++	cpufreq_verify_within_limits(policy,
++			policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
++
++	return 0;
++}
++
++static unsigned int ucv2_getspeed(unsigned int cpu)
++{
++	struct clk *mclk = clk_get(NULL, "MAIN_CLK");
++
++	if (cpu)
++		return 0;
++	return clk_get_rate(mclk)/1000;
++}
++
++static int ucv2_target(struct cpufreq_policy *policy,
++			 unsigned int target_freq,
++			 unsigned int relation)
++{
++	unsigned int cur = ucv2_getspeed(0);
++	struct cpufreq_freqs freqs;
++	struct clk *mclk = clk_get(NULL, "MAIN_CLK");
++
++	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
++
++	if (!clk_set_rate(mclk, target_freq * 1000)) {
++		freqs.old = cur;
++		freqs.new = target_freq;
++		freqs.cpu = 0;
++	}
++
++	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
++
++	return 0;
++}
++
++static int __init ucv2_cpu_init(struct cpufreq_policy *policy)
++{
++	if (policy->cpu != 0)
++		return -EINVAL;
++	policy->cur = ucv2_getspeed(0);
++	policy->min = policy->cpuinfo.min_freq = 250000;
++	policy->max = policy->cpuinfo.max_freq = 1000000;
++	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
++	return 0;
++}
++
++static struct cpufreq_driver ucv2_driver = {
++	.flags		= CPUFREQ_STICKY,
++	.verify		= ucv2_verify_speed,
++	.target		= ucv2_target,
++	.get		= ucv2_getspeed,
++	.init		= ucv2_cpu_init,
++	.name		= "UniCore-II",
++};
++
++static int __init ucv2_cpufreq_init(void)
++{
++	return cpufreq_register_driver(&ucv2_driver);
++}
++
++arch_initcall(ucv2_cpufreq_init);
+diff --git a/arch/unicore32/kernel/hibernate.c b/arch/unicore32/kernel/hibernate.c
+new file mode 100644
+index 000000000000..7d0f0b7983a0
+--- /dev/null
++++ b/arch/unicore32/kernel/hibernate.c
+@@ -0,0 +1,160 @@
++/*
++ *  linux/arch/unicore32/kernel/hibernate.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ *	Maintained by GUAN Xue-tao 
++ *	Copyright (C) 2001-2010 Guan Xuetao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include 
++#include 
++#include 
++
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include "mach/pm.h"
++
++/* Pointer to the temporary resume page tables */
++pgd_t *resume_pg_dir;
++
++struct swsusp_arch_regs swsusp_arch_regs_cpu0;
++
++/*
++ * Create a middle page table on a resume-safe page and put a pointer to it in
++ * the given global directory entry.  This only returns the gd entry
++ * in non-PAE compilation mode, since the middle layer is folded.
++ */
++static pmd_t *resume_one_md_table_init(pgd_t *pgd)
++{
++	pud_t *pud;
++	pmd_t *pmd_table;
++
++	pud = pud_offset(pgd, 0);
++	pmd_table = pmd_offset(pud, 0);
++
++	return pmd_table;
++}
++
++/*
++ * Create a page table on a resume-safe page and place a pointer to it in
++ * a middle page directory entry.
++ */
++static pte_t *resume_one_page_table_init(pmd_t *pmd)
++{
++	if (pmd_none(*pmd)) {
++		pte_t *page_table = (pte_t *)get_safe_page(GFP_ATOMIC);
++		if (!page_table)
++			return NULL;
++
++		set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_KERNEL_TABLE));
++
++		BUG_ON(page_table != pte_offset_kernel(pmd, 0));
++
++		return page_table;
++	}
++
++	return pte_offset_kernel(pmd, 0);
++}
++
++/*
++ * This maps the physical memory to kernel virtual address space, a total
++ * of max_low_pfn pages, by creating page tables starting from address
++ * PAGE_OFFSET.  The page tables are allocated out of resume-safe pages.
++ */
++static int resume_physical_mapping_init(pgd_t *pgd_base)
++{
++	unsigned long pfn;
++	pgd_t *pgd;
++	pmd_t *pmd;
++	pte_t *pte;
++	int pgd_idx, pmd_idx;
++
++	pgd_idx = pgd_index(PAGE_OFFSET);
++	pgd = pgd_base + pgd_idx;
++	pfn = 0;
++
++	for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) {
++		pmd = resume_one_md_table_init(pgd);
++		if (!pmd)
++			return -ENOMEM;
++
++		if (pfn >= max_low_pfn)
++			continue;
++
++		for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD; pmd++, pmd_idx++) {
++			pte_t *max_pte;
++
++			if (pfn >= max_low_pfn)
++				break;
++
++			/* Map with normal page tables.
++			 * NOTE: We can mark everything as executable here
++			 */
++			pte = resume_one_page_table_init(pmd);
++			if (!pte)
++				return -ENOMEM;
++
++			max_pte = pte + PTRS_PER_PTE;
++			for (; pte < max_pte; pte++, pfn++) {
++				if (pfn >= max_low_pfn)
++					break;
++
++				set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));
++			}
++		}
++	}
++
++	return 0;
++}
++
++static inline void resume_init_first_level_page_table(pgd_t *pg_dir)
++{
++}
++
++int swsusp_arch_resume(void)
++{
++	int error;
++
++	resume_pg_dir = (pgd_t *)get_safe_page(GFP_ATOMIC);
++	if (!resume_pg_dir)
++		return -ENOMEM;
++
++	resume_init_first_level_page_table(resume_pg_dir);
++	error = resume_physical_mapping_init(resume_pg_dir);
++	if (error)
++		return error;
++
++	/* We have got enough memory and from now on we cannot recover */
++	restore_image(resume_pg_dir, restore_pblist);
++	return 0;
++}
++
++/*
++ *	pfn_is_nosave - check if given pfn is in the 'nosave' section
++ */
++
++int pfn_is_nosave(unsigned long pfn)
++{
++	unsigned long begin_pfn = __pa(&__nosave_begin) >> PAGE_SHIFT;
++	unsigned long end_pfn = PAGE_ALIGN(__pa(&__nosave_end)) >> PAGE_SHIFT;
++
++	return (pfn >= begin_pfn) && (pfn < end_pfn);
++}
++
++void save_processor_state(void)
++{
++}
++
++void restore_processor_state(void)
++{
++	local_flush_tlb_all();
++}
+diff --git a/arch/unicore32/kernel/hibernate_asm.S b/arch/unicore32/kernel/hibernate_asm.S
+new file mode 100644
+index 000000000000..cc3c65253c8c
+--- /dev/null
++++ b/arch/unicore32/kernel/hibernate_asm.S
+@@ -0,0 +1,117 @@
++/*
++ * linux/arch/unicore32/kernel/hibernate_asm.S
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ *	Maintained by GUAN Xue-tao 
++ *	Copyright (C) 2001-2010 Guan Xuetao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++@ restore_image(pgd_t *resume_pg_dir, struct pbe *restore_pblist)
++@ r0: resume_pg_dir
++@ r1: restore_pblist
++@ copy restore_pblist pages
++@ restore registers from swsusp_arch_regs_cpu0
++@
++ENTRY(restore_image)
++	sub	r0, r0, #PAGE_OFFSET
++	mov	r5, #0
++	movc	p0.c6, r5, #6	@invalidate ITLB & DTLB
++	movc	p0.c2, r0, #0
++	nop
++	nop
++	nop
++	nop
++	nop
++	nop
++	nop
++
++	.p2align 4,,7
++101:
++	csub.a	r1, #0
++	beq	109f
++
++	ldw	r6, [r1+], #PBE_ADDRESS
++	ldw	r7, [r1+], #PBE_ORIN_ADDRESS
++
++	movl	ip, #128
++102:	ldm.w	(r8 - r15), [r6]+
++	stm.w	(r8 - r15), [r7]+
++	sub.a	ip, ip, #1
++	bne	102b
++
++	ldw	r1, [r1+], #PBE_NEXT
++	b	101b
++
++	.p2align 4,,7
++109:
++	/* go back to the original page tables */
++	ldw	r0, =swapper_pg_dir
++	sub	r0, r0, #PAGE_OFFSET
++	mov	r5, #0
++	movc	p0.c6, r5, #6
++	movc	p0.c2, r0, #0
++	nop
++	nop
++	nop
++	nop
++	nop
++	nop
++	nop
++
++#ifdef	CONFIG_UNICORE_FPU_F64
++	ldw	ip, 1f
++	add	ip, ip, #SWSUSP_FPSTATE
++	lfm.w	(f0  - f7 ), [ip]+
++	lfm.w	(f8  - f15), [ip]+
++	lfm.w	(f16 - f23), [ip]+
++	lfm.w	(f24 - f31), [ip]+
++	ldw	r4, [ip]
++	ctf	r4, s31
++#endif
++	mov	r0, #0x0
++	ldw	ip, 1f
++	add	ip, ip, #SWSUSP_CPU
++	ldm.w	(r4 - r15), [ip]+
++	ldm	(r16 - r27, sp, pc), [ip]+	@ Load all regs saved previously
++
++	.align	2
++1:	.long	swsusp_arch_regs_cpu0
++
++
++@ swsusp_arch_suspend()
++@ - prepare pc for resume, return from function without swsusp_save on resume
++@ - save registers in swsusp_arch_regs_cpu0
++@ - call swsusp_save write suspend image
++
++ENTRY(swsusp_arch_suspend)
++	ldw	ip, 1f
++	add	ip, ip, #SWSUSP_CPU
++	stm.w	(r4 - r15), [ip]+
++	stm.w	(r16 - r27, sp, lr), [ip]+
++
++#ifdef	CONFIG_UNICORE_FPU_F64
++	ldw	ip, 1f
++	add	ip, ip, #SWSUSP_FPSTATE
++	sfm.w	(f0  - f7 ), [ip]+
++	sfm.w	(f8  - f15), [ip]+
++	sfm.w	(f16 - f23), [ip]+
++	sfm.w	(f24 - f31), [ip]+
++	cff	r4, s31
++	stw	r4, [ip]
++#endif
++	b	swsusp_save			@ no return
++
++1:	.long	swsusp_arch_regs_cpu0
+diff --git a/arch/unicore32/kernel/pm.c b/arch/unicore32/kernel/pm.c
+new file mode 100644
+index 000000000000..784bc2db3b28
+--- /dev/null
++++ b/arch/unicore32/kernel/pm.c
+@@ -0,0 +1,123 @@
++/*
++ * linux/arch/unicore32/kernel/pm.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ *	Maintained by GUAN Xue-tao 
++ *	Copyright (C) 2001-2010 Guan Xuetao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++#include 
++
++#include "setup.h"
++
++struct puv3_cpu_pm_fns *puv3_cpu_pm_fns;
++static unsigned long *sleep_save;
++
++int puv3_pm_enter(suspend_state_t state)
++{
++	unsigned long sleep_save_checksum = 0, checksum = 0;
++	int i;
++
++	/* skip registers saving for standby */
++	if (state != PM_SUSPEND_STANDBY) {
++		puv3_cpu_pm_fns->save(sleep_save);
++		/* before sleeping, calculate and save a checksum */
++		for (i = 0; i < puv3_cpu_pm_fns->save_count - 1; i++)
++			sleep_save_checksum += sleep_save[i];
++	}
++
++	/* *** go zzz *** */
++	puv3_cpu_pm_fns->enter(state);
++	cpu_init();
++#ifdef CONFIG_INPUT_KEYBOARD
++	puv3_ps2_init();
++#endif
++#ifdef CONFIG_PCI
++	pci_puv3_preinit();
++#endif
++	if (state != PM_SUSPEND_STANDBY) {
++		/* after sleeping, validate the checksum */
++		for (i = 0; i < puv3_cpu_pm_fns->save_count - 1; i++)
++			checksum += sleep_save[i];
++
++		/* if invalid, display message and wait for a hardware reset */
++		if (checksum != sleep_save_checksum) {
++			while (1)
++				puv3_cpu_pm_fns->enter(state);
++		}
++		puv3_cpu_pm_fns->restore(sleep_save);
++	}
++
++	pr_debug("*** made it back from resume\n");
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(puv3_pm_enter);
++
++unsigned long sleep_phys_sp(void *sp)
++{
++	return virt_to_phys(sp);
++}
++
++static int puv3_pm_valid(suspend_state_t state)
++{
++	if (puv3_cpu_pm_fns)
++		return puv3_cpu_pm_fns->valid(state);
++
++	return -EINVAL;
++}
++
++static int puv3_pm_prepare(void)
++{
++	int ret = 0;
++
++	if (puv3_cpu_pm_fns && puv3_cpu_pm_fns->prepare)
++		ret = puv3_cpu_pm_fns->prepare();
++
++	return ret;
++}
++
++static void puv3_pm_finish(void)
++{
++	if (puv3_cpu_pm_fns && puv3_cpu_pm_fns->finish)
++		puv3_cpu_pm_fns->finish();
++}
++
++static struct platform_suspend_ops puv3_pm_ops = {
++	.valid		= puv3_pm_valid,
++	.enter		= puv3_pm_enter,
++	.prepare	= puv3_pm_prepare,
++	.finish		= puv3_pm_finish,
++};
++
++static int __init puv3_pm_init(void)
++{
++	if (!puv3_cpu_pm_fns) {
++		printk(KERN_ERR "no valid puv3_cpu_pm_fns defined\n");
++		return -EINVAL;
++	}
++
++	sleep_save = kmalloc(puv3_cpu_pm_fns->save_count
++				* sizeof(unsigned long), GFP_KERNEL);
++	if (!sleep_save) {
++		printk(KERN_ERR "failed to alloc memory for pm save\n");
++		return -ENOMEM;
++	}
++
++	suspend_set_ops(&puv3_pm_ops);
++	return 0;
++}
++
++device_initcall(puv3_pm_init);
+diff --git a/arch/unicore32/kernel/sleep.S b/arch/unicore32/kernel/sleep.S
+new file mode 100644
+index 000000000000..f7c3fc87f7fe
+--- /dev/null
++++ b/arch/unicore32/kernel/sleep.S
+@@ -0,0 +1,202 @@
++/*
++ * linux/arch/unicore32/kernel/sleep.S
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ *	Maintained by GUAN Xue-tao 
++ *	Copyright (C) 2001-2010 Guan Xuetao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include 
++#include 
++#include 
++
++		.text
++
++pkunity_cpu_save_cp:
++
++	@ get coprocessor registers
++
++	movc	r3, p0.c7, #0			@ PID
++	movc	r4, p0.c2, #0			@ translation table base addr
++	movc	r5, p0.c1, #0			@ control reg
++
++
++	@ store them plus current virtual stack ptr on stack
++	mov	r6, sp
++	stm.w	(r3 - r6), [sp-]
++
++	mov	pc, lr
++
++pkunity_cpu_save_sp:
++	@ preserve phys address of stack
++	mov	r0, sp
++	stw.w	lr, [sp+], #-4
++	b.l	sleep_phys_sp
++	ldw	r1, =sleep_save_sp
++	stw	r0, [r1]
++	ldw.w	pc, [sp]+, #4
++
++/*
++ * puv3_cpu_suspend()
++ *
++ * Forces CPU into sleep state.
++ *
++ * r0 = value for PWRMODE M field for desired sleep state
++ */
++
++ENTRY(puv3_cpu_suspend)
++	stm.w	(r16 - r27, lr), [sp-]		@ save registers on stack
++	stm.w	(r4 - r15), [sp-]		@ save registers on stack
++
++#ifdef	CONFIG_UNICORE_FPU_F64
++	sfm.w	(f0  - f7 ), [sp-]
++	sfm.w	(f8  - f15), [sp-]
++	sfm.w	(f16 - f23), [sp-]
++	sfm.w	(f24 - f31), [sp-]
++	cff	r4, s31
++	stm.w	(r4), [sp-]
++#endif
++	b.l	pkunity_cpu_save_cp
++
++	b.l	pkunity_cpu_save_sp
++
++	@ clean data cache
++	mov	r1, #0
++	movc	p0.c5, r1, #14
++	nop
++	nop
++	nop
++	nop
++
++
++
++	@ DDR2 BaseAddr
++	ldw	r0, =io_p2v(PKUNITY_DDR2CTRL_BASE)
++
++	@ PM BaseAddr
++	ldw	r1, =io_p2v(PKUNITY_PM_BASE)
++
++	@ set PLL_SYS_CFG reg, 275
++	movl	r6, #0x00002401
++	stw	r6, [r1+], #0x18
++	@ set PLL_DDR_CFG reg, 66MHz
++	movl	r6, #0x00100c00
++	stw	r6, [r1+], #0x1c
++
++	@ set wake up source
++	movl	r8, #0x800001ff		@ epip4d
++	stw	r8, [r1+], #0xc
++
++	@ set PGSR
++	movl	r5, #0x40000
++	stw	r5, [r1+], #0x10
++
++	@ prepare DDR2 refresh settings
++	ldw	r5, [r0+], #0x24
++	or	r5, r5, #0x00000001
++
++	@ prepare PMCR for PLL changing
++	movl	r6, #0xc
++
++	@ prepare for closing PLL
++	movl	r7, #0x1
++
++	@ prepare sleep mode
++	mov	r8, #0x1
++
++@	movl	r0, 0x11111111
++@	put_word_ocd r0
++	b	pkunity_cpu_do_suspend
++
++	.ltorg
++	.align	5
++pkunity_cpu_do_suspend:
++	b	101f
++	@ put DDR2 into self-refresh
++100:	stw	r5, [r0+], #0x24
++	@ change PLL
++	stw	r6, [r1]
++	b	1f
++
++	.ltorg
++	.align	5
++101:	b	102f
++	@ wait for PLL changing complete
++1:	ldw	r6, [r1+], #0x44
++	csub.a	r6, #0x1
++	bne	1b
++	b	2f
++
++	.ltorg
++	.align	5
++102:	b	100b
++	@ close PLL
++2:	stw	r7, [r1+], #0x4
++	@ enter sleep mode
++	stw	r8, [r1]
++3:	b	3b
++
++
++
++
++/*
++ * puv3_cpu_resume()
++ *
++ * entry point from bootloader into kernel during resume
++ *
++ * Note: Yes, part of the following code is located into the .data section.
++ *       This is to allow sleep_save_sp to be accessed with a relative load
++ *       while we can't rely on any MMU translation.  We could have put
++ *       sleep_save_sp in the .text section as well, but some setups might
++ *       insist on it to be truly read-only.
++ */
++
++	.data
++	.align 5
++ENTRY(puv3_cpu_resume)
++@	movl	r0, 0x20202020
++@	put_word_ocd r0
++
++	ldw	r0, sleep_save_sp		@ stack phys addr
++	ldw	r2, =resume_after_mmu		@ its absolute virtual address
++	ldm	(r3 - r6), [r0]+		@ CP regs + virt stack ptr
++	mov	sp, r6				@ CP regs + virt stack ptr
++
++	mov	r1, #0
++	movc	p0.c6, r1, #6			@ invalidate I & D TLBs
++	movc	p0.c5, r1, #28			@ invalidate I & D caches, BTB
++
++	movc	p0.c7, r3, #0			@ PID
++	movc	p0.c2, r4, #0			@ translation table base addr
++	movc	p0.c1, r5, #0			@ control reg, turn on mmu
++	nop
++	jump	r2
++	nop
++	nop
++	nop
++	nop
++	nop
++
++sleep_save_sp:
++	.word	0				@ preserve stack phys ptr here
++
++	.text
++resume_after_mmu:
++@	movl	r0, 0x30303030
++@	put_word_ocd r0
++
++#ifdef	CONFIG_UNICORE_FPU_F64
++	lfm.w	(f0  - f7 ), [sp]+
++	lfm.w	(f8  - f15), [sp]+
++	lfm.w	(f16 - f23), [sp]+
++	lfm.w	(f24 - f31), [sp]+
++	ldm.w	(r4), [sp]+
++	ctf	r4, s31
++#endif
++	ldm.w	(r4 - r15), [sp]+		@ restore registers from stack
++	ldm.w	(r16 - r27, pc), [sp]+		@ return to caller

commit f864d2f8304e6be90b4c4e4ac615edc6fcefd4c1
+Author: GuanXuetao 
+Date:   Sat Jan 15 18:20:01 2011 +0800
+
+    unicore32 core architecture: signals handling
+    
+    This patch implements signals.
+    
+    Signed-off-by: Guan Xuetao 
+
+diff --git a/arch/unicore32/include/asm/sigcontext.h b/arch/unicore32/include/asm/sigcontext.h
+new file mode 100644
+index 000000000000..6a2d7671c052
+--- /dev/null
++++ b/arch/unicore32/include/asm/sigcontext.h
+@@ -0,0 +1,29 @@
++/*
++ * linux/arch/unicore32/include/asm/sigcontext.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_SIGCONTEXT_H__
++#define __UNICORE_SIGCONTEXT_H__
++
++#include 
++/*
++ * Signal context structure - contains all info to do with the state
++ * before the signal handler was invoked.  Note: only add new entries
++ * to the end of the structure.
++ */
++struct sigcontext {
++	unsigned long trap_no;
++	unsigned long error_code;
++	unsigned long oldmask;
++	unsigned long fault_address;
++	struct pt_regs regs;
++};
++
++#endif
+diff --git a/arch/unicore32/kernel/signal.c b/arch/unicore32/kernel/signal.c
+new file mode 100644
+index 000000000000..b163fca56789
+--- /dev/null
++++ b/arch/unicore32/kernel/signal.c
+@@ -0,0 +1,494 @@
++/*
++ * linux/arch/unicore32/kernel/signal.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++#include 
++
++#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
++
++/*
++ * For UniCore syscalls, we encode the syscall number into the instruction.
++ */
++#define SWI_SYS_SIGRETURN	(0xff000000) /* error number for new abi */
++#define SWI_SYS_RT_SIGRETURN	(0xff000000 | (__NR_rt_sigreturn))
++#define SWI_SYS_RESTART		(0xff000000 | (__NR_restart_syscall))
++
++#define KERN_SIGRETURN_CODE	(KUSER_VECPAGE_BASE + 0x00000500)
++#define KERN_RESTART_CODE	(KERN_SIGRETURN_CODE + sizeof(sigreturn_codes))
++
++const unsigned long sigreturn_codes[3] = {
++	SWI_SYS_SIGRETURN, SWI_SYS_RT_SIGRETURN,
++};
++
++const unsigned long syscall_restart_code[2] = {
++	SWI_SYS_RESTART,	/* swi	__NR_restart_syscall */
++	0x69efc004,		/* ldr	pc, [sp], #4 */
++};
++
++/*
++ * Do a signal return; undo the signal stack.  These are aligned to 64-bit.
++ */
++struct sigframe {
++	struct ucontext uc;
++	unsigned long retcode[2];
++};
++
++struct rt_sigframe {
++	struct siginfo info;
++	struct sigframe sig;
++};
++
++static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
++{
++	sigset_t set;
++	int err;
++
++	err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
++	if (err == 0) {
++		sigdelsetmask(&set, ~_BLOCKABLE);
++		spin_lock_irq(¤t->sighand->siglock);
++		current->blocked = set;
++		recalc_sigpending();
++		spin_unlock_irq(¤t->sighand->siglock);
++	}
++
++	err |= __get_user(regs->UCreg_00, &sf->uc.uc_mcontext.regs.UCreg_00);
++	err |= __get_user(regs->UCreg_01, &sf->uc.uc_mcontext.regs.UCreg_01);
++	err |= __get_user(regs->UCreg_02, &sf->uc.uc_mcontext.regs.UCreg_02);
++	err |= __get_user(regs->UCreg_03, &sf->uc.uc_mcontext.regs.UCreg_03);
++	err |= __get_user(regs->UCreg_04, &sf->uc.uc_mcontext.regs.UCreg_04);
++	err |= __get_user(regs->UCreg_05, &sf->uc.uc_mcontext.regs.UCreg_05);
++	err |= __get_user(regs->UCreg_06, &sf->uc.uc_mcontext.regs.UCreg_06);
++	err |= __get_user(regs->UCreg_07, &sf->uc.uc_mcontext.regs.UCreg_07);
++	err |= __get_user(regs->UCreg_08, &sf->uc.uc_mcontext.regs.UCreg_08);
++	err |= __get_user(regs->UCreg_09, &sf->uc.uc_mcontext.regs.UCreg_09);
++	err |= __get_user(regs->UCreg_10, &sf->uc.uc_mcontext.regs.UCreg_10);
++	err |= __get_user(regs->UCreg_11, &sf->uc.uc_mcontext.regs.UCreg_11);
++	err |= __get_user(regs->UCreg_12, &sf->uc.uc_mcontext.regs.UCreg_12);
++	err |= __get_user(regs->UCreg_13, &sf->uc.uc_mcontext.regs.UCreg_13);
++	err |= __get_user(regs->UCreg_14, &sf->uc.uc_mcontext.regs.UCreg_14);
++	err |= __get_user(regs->UCreg_15, &sf->uc.uc_mcontext.regs.UCreg_15);
++	err |= __get_user(regs->UCreg_16, &sf->uc.uc_mcontext.regs.UCreg_16);
++	err |= __get_user(regs->UCreg_17, &sf->uc.uc_mcontext.regs.UCreg_17);
++	err |= __get_user(regs->UCreg_18, &sf->uc.uc_mcontext.regs.UCreg_18);
++	err |= __get_user(regs->UCreg_19, &sf->uc.uc_mcontext.regs.UCreg_19);
++	err |= __get_user(regs->UCreg_20, &sf->uc.uc_mcontext.regs.UCreg_20);
++	err |= __get_user(regs->UCreg_21, &sf->uc.uc_mcontext.regs.UCreg_21);
++	err |= __get_user(regs->UCreg_22, &sf->uc.uc_mcontext.regs.UCreg_22);
++	err |= __get_user(regs->UCreg_23, &sf->uc.uc_mcontext.regs.UCreg_23);
++	err |= __get_user(regs->UCreg_24, &sf->uc.uc_mcontext.regs.UCreg_24);
++	err |= __get_user(regs->UCreg_25, &sf->uc.uc_mcontext.regs.UCreg_25);
++	err |= __get_user(regs->UCreg_26, &sf->uc.uc_mcontext.regs.UCreg_26);
++	err |= __get_user(regs->UCreg_fp, &sf->uc.uc_mcontext.regs.UCreg_fp);
++	err |= __get_user(regs->UCreg_ip, &sf->uc.uc_mcontext.regs.UCreg_ip);
++	err |= __get_user(regs->UCreg_sp, &sf->uc.uc_mcontext.regs.UCreg_sp);
++	err |= __get_user(regs->UCreg_lr, &sf->uc.uc_mcontext.regs.UCreg_lr);
++	err |= __get_user(regs->UCreg_pc, &sf->uc.uc_mcontext.regs.UCreg_pc);
++	err |= __get_user(regs->UCreg_asr, &sf->uc.uc_mcontext.regs.UCreg_asr);
++
++	err |= !valid_user_regs(regs);
++
++	return err;
++}
++
++asmlinkage int __sys_rt_sigreturn(struct pt_regs *regs)
++{
++	struct rt_sigframe __user *frame;
++
++	/* Always make any pending restarted system calls return -EINTR */
++	current_thread_info()->restart_block.fn = do_no_restart_syscall;
++
++	/*
++	 * Since we stacked the signal on a 64-bit boundary,
++	 * then 'sp' should be word aligned here.  If it's
++	 * not, then the user is trying to mess with us.
++	 */
++	if (regs->UCreg_sp & 7)
++		goto badframe;
++
++	frame = (struct rt_sigframe __user *)regs->UCreg_sp;
++
++	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
++		goto badframe;
++
++	if (restore_sigframe(regs, &frame->sig))
++		goto badframe;
++
++	if (do_sigaltstack(&frame->sig.uc.uc_stack, NULL, regs->UCreg_sp)
++			== -EFAULT)
++		goto badframe;
++
++	return regs->UCreg_00;
++
++badframe:
++	force_sig(SIGSEGV, current);
++	return 0;
++}
++
++static int setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs,
++		sigset_t *set)
++{
++	int err = 0;
++
++	err |= __put_user(regs->UCreg_00, &sf->uc.uc_mcontext.regs.UCreg_00);
++	err |= __put_user(regs->UCreg_01, &sf->uc.uc_mcontext.regs.UCreg_01);
++	err |= __put_user(regs->UCreg_02, &sf->uc.uc_mcontext.regs.UCreg_02);
++	err |= __put_user(regs->UCreg_03, &sf->uc.uc_mcontext.regs.UCreg_03);
++	err |= __put_user(regs->UCreg_04, &sf->uc.uc_mcontext.regs.UCreg_04);
++	err |= __put_user(regs->UCreg_05, &sf->uc.uc_mcontext.regs.UCreg_05);
++	err |= __put_user(regs->UCreg_06, &sf->uc.uc_mcontext.regs.UCreg_06);
++	err |= __put_user(regs->UCreg_07, &sf->uc.uc_mcontext.regs.UCreg_07);
++	err |= __put_user(regs->UCreg_08, &sf->uc.uc_mcontext.regs.UCreg_08);
++	err |= __put_user(regs->UCreg_09, &sf->uc.uc_mcontext.regs.UCreg_09);
++	err |= __put_user(regs->UCreg_10, &sf->uc.uc_mcontext.regs.UCreg_10);
++	err |= __put_user(regs->UCreg_11, &sf->uc.uc_mcontext.regs.UCreg_11);
++	err |= __put_user(regs->UCreg_12, &sf->uc.uc_mcontext.regs.UCreg_12);
++	err |= __put_user(regs->UCreg_13, &sf->uc.uc_mcontext.regs.UCreg_13);
++	err |= __put_user(regs->UCreg_14, &sf->uc.uc_mcontext.regs.UCreg_14);
++	err |= __put_user(regs->UCreg_15, &sf->uc.uc_mcontext.regs.UCreg_15);
++	err |= __put_user(regs->UCreg_16, &sf->uc.uc_mcontext.regs.UCreg_16);
++	err |= __put_user(regs->UCreg_17, &sf->uc.uc_mcontext.regs.UCreg_17);
++	err |= __put_user(regs->UCreg_18, &sf->uc.uc_mcontext.regs.UCreg_18);
++	err |= __put_user(regs->UCreg_19, &sf->uc.uc_mcontext.regs.UCreg_19);
++	err |= __put_user(regs->UCreg_20, &sf->uc.uc_mcontext.regs.UCreg_20);
++	err |= __put_user(regs->UCreg_21, &sf->uc.uc_mcontext.regs.UCreg_21);
++	err |= __put_user(regs->UCreg_22, &sf->uc.uc_mcontext.regs.UCreg_22);
++	err |= __put_user(regs->UCreg_23, &sf->uc.uc_mcontext.regs.UCreg_23);
++	err |= __put_user(regs->UCreg_24, &sf->uc.uc_mcontext.regs.UCreg_24);
++	err |= __put_user(regs->UCreg_25, &sf->uc.uc_mcontext.regs.UCreg_25);
++	err |= __put_user(regs->UCreg_26, &sf->uc.uc_mcontext.regs.UCreg_26);
++	err |= __put_user(regs->UCreg_fp, &sf->uc.uc_mcontext.regs.UCreg_fp);
++	err |= __put_user(regs->UCreg_ip, &sf->uc.uc_mcontext.regs.UCreg_ip);
++	err |= __put_user(regs->UCreg_sp, &sf->uc.uc_mcontext.regs.UCreg_sp);
++	err |= __put_user(regs->UCreg_lr, &sf->uc.uc_mcontext.regs.UCreg_lr);
++	err |= __put_user(regs->UCreg_pc, &sf->uc.uc_mcontext.regs.UCreg_pc);
++	err |= __put_user(regs->UCreg_asr, &sf->uc.uc_mcontext.regs.UCreg_asr);
++
++	err |= __put_user(current->thread.trap_no,
++			&sf->uc.uc_mcontext.trap_no);
++	err |= __put_user(current->thread.error_code,
++			&sf->uc.uc_mcontext.error_code);
++	err |= __put_user(current->thread.address,
++			&sf->uc.uc_mcontext.fault_address);
++	err |= __put_user(set->sig[0], &sf->uc.uc_mcontext.oldmask);
++
++	err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set));
++
++	return err;
++}
++
++static inline void __user *get_sigframe(struct k_sigaction *ka,
++		struct pt_regs *regs, int framesize)
++{
++	unsigned long sp = regs->UCreg_sp;
++	void __user *frame;
++
++	/*
++	 * This is the X/Open sanctioned signal stack switching.
++	 */
++	if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
++		sp = current->sas_ss_sp + current->sas_ss_size;
++
++	/*
++	 * ATPCS B01 mandates 8-byte alignment
++	 */
++	frame = (void __user *)((sp - framesize) & ~7);
++
++	/*
++	 * Check that we can actually write to the signal frame.
++	 */
++	if (!access_ok(VERIFY_WRITE, frame, framesize))
++		frame = NULL;
++
++	return frame;
++}
++
++static int setup_return(struct pt_regs *regs, struct k_sigaction *ka,
++	     unsigned long __user *rc, void __user *frame, int usig)
++{
++	unsigned long handler = (unsigned long)ka->sa.sa_handler;
++	unsigned long retcode;
++	unsigned long asr = regs->UCreg_asr & ~PSR_f;
++
++	unsigned int idx = 0;
++
++	if (ka->sa.sa_flags & SA_SIGINFO)
++		idx += 1;
++
++	if (__put_user(sigreturn_codes[idx],   rc) ||
++	    __put_user(sigreturn_codes[idx+1], rc+1))
++		return 1;
++
++	retcode = KERN_SIGRETURN_CODE + (idx << 2);
++
++	regs->UCreg_00 = usig;
++	regs->UCreg_sp = (unsigned long)frame;
++	regs->UCreg_lr = retcode;
++	regs->UCreg_pc = handler;
++	regs->UCreg_asr = asr;
++
++	return 0;
++}
++
++static int setup_frame(int usig, struct k_sigaction *ka,
++		sigset_t *set, struct pt_regs *regs)
++{
++	struct sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame));
++	int err = 0;
++
++	if (!frame)
++		return 1;
++
++	/*
++	 * Set uc.uc_flags to a value which sc.trap_no would never have.
++	 */
++	err |= __put_user(0x5ac3c35a, &frame->uc.uc_flags);
++
++	err |= setup_sigframe(frame, regs, set);
++	if (err == 0)
++		err |= setup_return(regs, ka, frame->retcode, frame, usig);
++
++	return err;
++}
++
++static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
++	       sigset_t *set, struct pt_regs *regs)
++{
++	struct rt_sigframe __user *frame =
++			get_sigframe(ka, regs, sizeof(*frame));
++	stack_t stack;
++	int err = 0;
++
++	if (!frame)
++		return 1;
++
++	err |= copy_siginfo_to_user(&frame->info, info);
++
++	err |= __put_user(0, &frame->sig.uc.uc_flags);
++	err |= __put_user(NULL, &frame->sig.uc.uc_link);
++
++	memset(&stack, 0, sizeof(stack));
++	stack.ss_sp = (void __user *)current->sas_ss_sp;
++	stack.ss_flags = sas_ss_flags(regs->UCreg_sp);
++	stack.ss_size = current->sas_ss_size;
++	err |= __copy_to_user(&frame->sig.uc.uc_stack, &stack, sizeof(stack));
++
++	err |= setup_sigframe(&frame->sig, regs, set);
++	if (err == 0)
++		err |= setup_return(regs, ka, frame->sig.retcode, frame, usig);
++
++	if (err == 0) {
++		/*
++		 * For realtime signals we must also set the second and third
++		 * arguments for the signal handler.
++		 */
++		regs->UCreg_01 = (unsigned long)&frame->info;
++		regs->UCreg_02 = (unsigned long)&frame->sig.uc;
++	}
++
++	return err;
++}
++
++static inline void setup_syscall_restart(struct pt_regs *regs)
++{
++	regs->UCreg_00 = regs->UCreg_ORIG_00;
++	regs->UCreg_pc -= 4;
++}
++
++/*
++ * OK, we're invoking a handler
++ */
++static int handle_signal(unsigned long sig, struct k_sigaction *ka,
++	      siginfo_t *info, sigset_t *oldset,
++	      struct pt_regs *regs, int syscall)
++{
++	struct thread_info *thread = current_thread_info();
++	struct task_struct *tsk = current;
++	int usig = sig;
++	int ret;
++
++	/*
++	 * If we were from a system call, check for system call restarting...
++	 */
++	if (syscall) {
++		switch (regs->UCreg_00) {
++		case -ERESTART_RESTARTBLOCK:
++		case -ERESTARTNOHAND:
++			regs->UCreg_00 = -EINTR;
++			break;
++		case -ERESTARTSYS:
++			if (!(ka->sa.sa_flags & SA_RESTART)) {
++				regs->UCreg_00 = -EINTR;
++				break;
++			}
++			/* fallthrough */
++		case -ERESTARTNOINTR:
++			setup_syscall_restart(regs);
++		}
++	}
++
++	/*
++	 * translate the signal
++	 */
++	if (usig < 32 && thread->exec_domain
++			&& thread->exec_domain->signal_invmap)
++		usig = thread->exec_domain->signal_invmap[usig];
++
++	/*
++	 * Set up the stack frame
++	 */
++	if (ka->sa.sa_flags & SA_SIGINFO)
++		ret = setup_rt_frame(usig, ka, info, oldset, regs);
++	else
++		ret = setup_frame(usig, ka, oldset, regs);
++
++	/*
++	 * Check that the resulting registers are actually sane.
++	 */
++	ret |= !valid_user_regs(regs);
++
++	if (ret != 0) {
++		force_sigsegv(sig, tsk);
++		return ret;
++	}
++
++	/*
++	 * Block the signal if we were successful.
++	 */
++	spin_lock_irq(&tsk->sighand->siglock);
++	sigorsets(&tsk->blocked, &tsk->blocked,
++		  &ka->sa.sa_mask);
++	if (!(ka->sa.sa_flags & SA_NODEFER))
++		sigaddset(&tsk->blocked, sig);
++	recalc_sigpending();
++	spin_unlock_irq(&tsk->sighand->siglock);
++
++	return 0;
++}
++
++/*
++ * Note that 'init' is a special process: it doesn't get signals it doesn't
++ * want to handle. Thus you cannot kill init even with a SIGKILL even by
++ * mistake.
++ *
++ * Note that we go through the signals twice: once to check the signals that
++ * the kernel can handle, and then we build all the user-level signal handling
++ * stack-frames in one go after that.
++ */
++static void do_signal(struct pt_regs *regs, int syscall)
++{
++	struct k_sigaction ka;
++	siginfo_t info;
++	int signr;
++
++	/*
++	 * We want the common case to go fast, which
++	 * is why we may in certain cases get here from
++	 * kernel mode. Just return without doing anything
++	 * if so.
++	 */
++	if (!user_mode(regs))
++		return;
++
++	if (try_to_freeze())
++		goto no_signal;
++
++	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
++	if (signr > 0) {
++		sigset_t *oldset;
++
++		if (test_thread_flag(TIF_RESTORE_SIGMASK))
++			oldset = ¤t->saved_sigmask;
++		else
++			oldset = ¤t->blocked;
++		if (handle_signal(signr, &ka, &info, oldset, regs, syscall)
++				== 0) {
++			/*
++			 * A signal was successfully delivered; the saved
++			 * sigmask will have been stored in the signal frame,
++			 * and will be restored by sigreturn, so we can simply
++			 * clear the TIF_RESTORE_SIGMASK flag.
++			 */
++			if (test_thread_flag(TIF_RESTORE_SIGMASK))
++				clear_thread_flag(TIF_RESTORE_SIGMASK);
++		}
++		return;
++	}
++
++ no_signal:
++	/*
++	 * No signal to deliver to the process - restart the syscall.
++	 */
++	if (syscall) {
++		if (regs->UCreg_00 == -ERESTART_RESTARTBLOCK) {
++				u32 __user *usp;
++
++				regs->UCreg_sp -= 4;
++				usp = (u32 __user *)regs->UCreg_sp;
++
++				if (put_user(regs->UCreg_pc, usp) == 0) {
++					regs->UCreg_pc = KERN_RESTART_CODE;
++				} else {
++					regs->UCreg_sp += 4;
++					force_sigsegv(0, current);
++				}
++		}
++		if (regs->UCreg_00 == -ERESTARTNOHAND ||
++		    regs->UCreg_00 == -ERESTARTSYS ||
++		    regs->UCreg_00 == -ERESTARTNOINTR) {
++			setup_syscall_restart(regs);
++		}
++
++		/* If there's no signal to deliver, we just put the saved
++		 * sigmask back.
++		 */
++		if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
++			clear_thread_flag(TIF_RESTORE_SIGMASK);
++			sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
++		}
++	}
++}
++
++asmlinkage void do_notify_resume(struct pt_regs *regs,
++		unsigned int thread_flags, int syscall)
++{
++	if (thread_flags & _TIF_SIGPENDING)
++		do_signal(regs, syscall);
++
++	if (thread_flags & _TIF_NOTIFY_RESUME) {
++		clear_thread_flag(TIF_NOTIFY_RESUME);
++		tracehook_notify_resume(regs);
++		if (current->replacement_session_keyring)
++			key_replace_session_keyring();
++	}
++}
++
++/*
++ * Copy signal return handlers into the vector page, and
++ * set sigreturn to be a pointer to these.
++ */
++void __init early_signal_init(void)
++{
++	memcpy((void *)kuser_vecpage_to_vectors(KERN_SIGRETURN_CODE),
++			sigreturn_codes, sizeof(sigreturn_codes));
++	memcpy((void *)kuser_vecpage_to_vectors(KERN_RESTART_CODE),
++			syscall_restart_code, sizeof(syscall_restart_code));
++	/* Need not to flush icache, since early_trap_init will do it last. */
++}

commit 752bcb4d02ccfd5e7a8d810424154169b4cca8ae
+Author: GuanXuetao 
+Date:   Sat Jan 15 18:19:35 2011 +0800
+
+    unicore32 core architecture: interrupts ang gpio handling
+    
+    This patch implements interrupts and gpio handling.
+    UniCore32 has 9 gpio interrupt sources.
+    And gpio device operations are also here.
+    
+    Signed-off-by: Guan Xuetao 
+
+diff --git a/arch/unicore32/include/asm/gpio.h b/arch/unicore32/include/asm/gpio.h
+new file mode 100644
+index 000000000000..3aaa41e9e413
+--- /dev/null
++++ b/arch/unicore32/include/asm/gpio.h
+@@ -0,0 +1,103 @@
++/*
++ * linux/arch/unicore32/include/asm/gpio.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __UNICORE_GPIO_H__
++#define __UNICORE_GPIO_H__
++
++#include 
++#include 
++#include 
++
++#define GPI_OTP_INT             0
++#define GPI_PCI_INTA            1
++#define GPI_PCI_INTB            2
++#define GPI_PCI_INTC            3
++#define GPI_PCI_INTD            4
++#define GPI_BAT_DET             5
++#define GPI_SD_CD               6
++#define GPI_SOFF_REQ            7
++#define GPI_SD_WP               8
++#define GPI_LCD_CASE_OFF        9
++#define GPO_WIFI_EN             10
++#define GPO_HDD_LED             11
++#define GPO_VGA_EN              12
++#define GPO_LCD_EN              13
++#define GPO_LED_DATA            14
++#define GPO_LED_CLK             15
++#define GPO_CAM_PWR_EN          16
++#define GPO_LCD_VCC_EN          17
++#define GPO_SOFT_OFF            18
++#define GPO_BT_EN               19
++#define GPO_FAN_ON              20
++#define GPO_SPKR                21
++#define GPO_SET_V1              23
++#define GPO_SET_V2              24
++#define GPO_CPU_HEALTH          25
++#define GPO_LAN_SEL             26
++
++#ifdef CONFIG_PUV3_NB0916
++#define GPI_BTN_TOUCH		14
++#define GPIO_IN			0x000043ff /* 1 for input */
++#define GPIO_OUT		0x0fffbc00 /* 1 for output */
++#endif	/* CONFIG_PUV3_NB0916 */
++
++#ifdef CONFIG_PUV3_SMW0919
++#define GPIO_IN			0x000003ff /* 1 for input */
++#define GPIO_OUT		0x0ffffc00 /* 1 for output */
++#endif  /* CONFIG_PUV3_SMW0919 */
++
++#ifdef CONFIG_PUV3_DB0913
++#define GPIO_IN			0x000001df /* 1 for input */
++#define GPIO_OUT		0x03fee800 /* 1 for output */
++#endif  /* CONFIG_PUV3_DB0913 */
++
++#define GPIO_DIR                (~((GPIO_IN) | 0xf0000000))
++				/* 0 input, 1 output */
++
++static inline int gpio_get_value(unsigned gpio)
++{
++	if (__builtin_constant_p(gpio) && (gpio <= GPIO_MAX))
++		return GPIO_GPLR & GPIO_GPIO(gpio);
++	else
++		return __gpio_get_value(gpio);
++}
++
++static inline void gpio_set_value(unsigned gpio, int value)
++{
++	if (__builtin_constant_p(gpio) && (gpio <= GPIO_MAX))
++		if (value)
++			GPIO_GPSR = GPIO_GPIO(gpio);
++		else
++			GPIO_GPCR = GPIO_GPIO(gpio);
++	else
++		__gpio_set_value(gpio, value);
++}
++
++#define gpio_cansleep	__gpio_cansleep
++
++static inline unsigned gpio_to_irq(unsigned gpio)
++{
++	if ((gpio < IRQ_GPIOHIGH) && (FIELD(1, 1, gpio) & GPIO_GPIR))
++		return IRQ_GPIOLOW0 + gpio;
++	else
++		return IRQ_GPIO0 + gpio;
++}
++
++static inline unsigned irq_to_gpio(unsigned irq)
++{
++	if (irq < IRQ_GPIOHIGH)
++		return irq - IRQ_GPIOLOW0;
++	else
++		return irq - IRQ_GPIO0;
++}
++
++#endif /* __UNICORE_GPIO_H__ */
+diff --git a/arch/unicore32/include/asm/irq.h b/arch/unicore32/include/asm/irq.h
+new file mode 100644
+index 000000000000..ade8bb87111d
+--- /dev/null
++++ b/arch/unicore32/include/asm/irq.h
+@@ -0,0 +1,107 @@
++/*
++ * linux/arch/unicore32/include/asm/irq.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_IRQ_H__
++#define __UNICORE_IRQ_H__
++
++#include 
++
++#define	IRQ_GPIOLOW0		0x00
++#define	IRQ_GPIOLOW1		0x01
++#define	IRQ_GPIOLOW2		0x02
++#define	IRQ_GPIOLOW3		0x03
++#define	IRQ_GPIOLOW4		0x04
++#define	IRQ_GPIOLOW5		0x05
++#define	IRQ_GPIOLOW6		0x06
++#define	IRQ_GPIOLOW7		0x07
++#define IRQ_GPIOHIGH		0x08
++#define IRQ_USB			0x09
++#define IRQ_SDC			0x0a
++#define IRQ_AC97		0x0b
++#define IRQ_SATA		0x0c
++#define IRQ_MME			0x0d
++#define IRQ_PCI_BRIDGE		0x0e
++#define	IRQ_DDR			0x0f
++#define	IRQ_SPI			0x10
++#define	IRQ_UNIGFX		0x11
++#define	IRQ_I2C			0x11
++#define	IRQ_UART1		0x12
++#define	IRQ_UART0		0x13
++#define IRQ_UMAL		0x14
++#define IRQ_NAND		0x15
++#define IRQ_PS2_KBD		0x16
++#define IRQ_PS2_AUX		0x17
++#define IRQ_DMA			0x18
++#define IRQ_DMAERR		0x19
++#define	IRQ_TIMER0		0x1a
++#define	IRQ_TIMER1		0x1b
++#define	IRQ_TIMER2		0x1c
++#define	IRQ_TIMER3		0x1d
++#define	IRQ_RTC			0x1e
++#define	IRQ_RTCAlarm		0x1f
++
++#define	IRQ_GPIO0		0x20
++#define	IRQ_GPIO1		0x21
++#define	IRQ_GPIO2		0x22
++#define	IRQ_GPIO3		0x23
++#define	IRQ_GPIO4		0x24
++#define	IRQ_GPIO5		0x25
++#define	IRQ_GPIO6		0x26
++#define	IRQ_GPIO7		0x27
++#define IRQ_GPIO8		0x28
++#define IRQ_GPIO9		0x29
++#define IRQ_GPIO10		0x2a
++#define IRQ_GPIO11		0x2b
++#define IRQ_GPIO12		0x2c
++#define IRQ_GPIO13		0x2d
++#define IRQ_GPIO14		0x2e
++#define IRQ_GPIO15		0x2f
++#define IRQ_GPIO16		0x30
++#define IRQ_GPIO17		0x31
++#define IRQ_GPIO18		0x32
++#define IRQ_GPIO19		0x33
++#define IRQ_GPIO20		0x34
++#define IRQ_GPIO21		0x35
++#define IRQ_GPIO22		0x36
++#define IRQ_GPIO23		0x37
++#define IRQ_GPIO24		0x38
++#define IRQ_GPIO25		0x39
++#define IRQ_GPIO26		0x3a
++#define IRQ_GPIO27		0x3b
++
++#ifdef CONFIG_ARCH_FPGA
++#define IRQ_PCIINTA             IRQ_GPIOLOW2
++#define IRQ_PCIINTB             IRQ_GPIOLOW1
++#define IRQ_PCIINTC             IRQ_GPIOLOW0
++#define IRQ_PCIINTD             IRQ_GPIOLOW6
++#endif
++
++#if defined(CONFIG_PUV3_DB0913) || defined(CONFIG_PUV3_NB0916)	\
++	|| defined(CONFIG_PUV3_SMW0919)
++#define IRQ_PCIINTA             IRQ_GPIOLOW1
++#define IRQ_PCIINTB             IRQ_GPIOLOW2
++#define IRQ_PCIINTC             IRQ_GPIOLOW3
++#define IRQ_PCIINTD             IRQ_GPIOLOW4
++#endif
++
++#define IRQ_SD_CD               IRQ_GPIO6 /* falling or rising trigger */
++
++#ifndef __ASSEMBLY__
++struct irqaction;
++struct pt_regs;
++extern void migrate_irqs(void);
++
++extern void asm_do_IRQ(unsigned int, struct pt_regs *);
++
++#endif
++
++#endif
++
+diff --git a/arch/unicore32/include/asm/irqflags.h b/arch/unicore32/include/asm/irqflags.h
+new file mode 100644
+index 000000000000..6d8a28dfdbae
+--- /dev/null
++++ b/arch/unicore32/include/asm/irqflags.h
+@@ -0,0 +1,53 @@
++/*
++ * linux/arch/unicore32/include/asm/irqflags.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_IRQFLAGS_H__
++#define __UNICORE_IRQFLAGS_H__
++
++#ifdef __KERNEL__
++
++#include 
++
++#define ARCH_IRQ_DISABLED	(PRIV_MODE | PSR_I_BIT)
++#define ARCH_IRQ_ENABLED	(PRIV_MODE)
++
++/*
++ * Save the current interrupt enable state.
++ */
++static inline unsigned long arch_local_save_flags(void)
++{
++	unsigned long temp;
++
++	asm volatile("mov %0, asr" : "=r" (temp) : : "memory", "cc");
++
++	return temp & PSR_c;
++}
++
++/*
++ * restore saved IRQ state
++ */
++static inline void arch_local_irq_restore(unsigned long flags)
++{
++	unsigned long temp;
++
++	asm volatile(
++		"mov	%0, asr\n"
++		"mov.a	asr, %1\n"
++		"mov.f	asr, %0"
++		: "=&r" (temp)
++		: "r" (flags)
++		: "memory", "cc");
++}
++
++#include 
++
++#endif
++#endif
+diff --git a/arch/unicore32/kernel/gpio.c b/arch/unicore32/kernel/gpio.c
+new file mode 100644
+index 000000000000..4cb28308bb5f
+--- /dev/null
++++ b/arch/unicore32/kernel/gpio.c
+@@ -0,0 +1,122 @@
++/*
++ * linux/arch/unicore32/kernel/gpio.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ *	Maintained by GUAN Xue-tao 
++ *	Copyright (C) 2001-2010 Guan Xuetao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++/* in FPGA, no GPIO support */
++
++#include 
++#include 
++#include 
++#include 
++
++#ifdef CONFIG_LEDS
++#include 
++#include 
++
++static const struct gpio_led puv3_gpio_leds[] = {
++	{ .name = "cpuhealth", .gpio = GPO_CPU_HEALTH, .active_low = 0,
++		.default_trigger = "heartbeat",	},
++	{ .name = "hdd_led", .gpio = GPO_HDD_LED, .active_low = 1,
++		.default_trigger = "ide-disk", },
++};
++
++static const struct gpio_led_platform_data puv3_gpio_led_data = {
++	.num_leds =	ARRAY_SIZE(puv3_gpio_leds),
++	.leds =		(void *) puv3_gpio_leds,
++};
++
++static struct platform_device puv3_gpio_gpio_leds = {
++	.name =		"leds-gpio",
++	.id =		-1,
++	.dev = {
++		.platform_data = (void *) &puv3_gpio_led_data,
++	}
++};
++
++static int __init puv3_gpio_leds_init(void)
++{
++	platform_device_register(&puv3_gpio_gpio_leds);
++	return 0;
++}
++
++device_initcall(puv3_gpio_leds_init);
++#endif
++
++static int puv3_gpio_get(struct gpio_chip *chip, unsigned offset)
++{
++	return GPIO_GPLR & GPIO_GPIO(offset);
++}
++
++static void puv3_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
++{
++	if (value)
++		GPIO_GPSR = GPIO_GPIO(offset);
++	else
++		GPIO_GPCR = GPIO_GPIO(offset);
++}
++
++static int puv3_direction_input(struct gpio_chip *chip, unsigned offset)
++{
++	unsigned long flags;
++
++	local_irq_save(flags);
++	GPIO_GPDR &= ~GPIO_GPIO(offset);
++	local_irq_restore(flags);
++	return 0;
++}
++
++static int puv3_direction_output(struct gpio_chip *chip, unsigned offset,
++		int value)
++{
++	unsigned long flags;
++
++	local_irq_save(flags);
++	puv3_gpio_set(chip, offset, value);
++	GPIO_GPDR |= GPIO_GPIO(offset);
++	local_irq_restore(flags);
++	return 0;
++}
++
++static struct gpio_chip puv3_gpio_chip = {
++	.label			= "gpio",
++	.direction_input	= puv3_direction_input,
++	.direction_output	= puv3_direction_output,
++	.set			= puv3_gpio_set,
++	.get			= puv3_gpio_get,
++	.base			= 0,
++	.ngpio			= GPIO_MAX + 1,
++};
++
++void __init puv3_init_gpio(void)
++{
++	GPIO_GPDR = GPIO_DIR;
++#if	defined(CONFIG_PUV3_NB0916) || defined(CONFIG_PUV3_SMW0919)	\
++	|| defined(CONFIG_PUV3_DB0913)
++	gpio_set_value(GPO_WIFI_EN, 1);
++	gpio_set_value(GPO_HDD_LED, 1);
++	gpio_set_value(GPO_VGA_EN, 1);
++	gpio_set_value(GPO_LCD_EN, 1);
++	gpio_set_value(GPO_CAM_PWR_EN, 0);
++	gpio_set_value(GPO_LCD_VCC_EN, 1);
++	gpio_set_value(GPO_SOFT_OFF, 1);
++	gpio_set_value(GPO_BT_EN, 1);
++	gpio_set_value(GPO_FAN_ON, 0);
++	gpio_set_value(GPO_SPKR, 0);
++	gpio_set_value(GPO_CPU_HEALTH, 1);
++	gpio_set_value(GPO_LAN_SEL, 1);
++/*
++ * DO NOT modify the GPO_SET_V1 and GPO_SET_V2 in kernel
++ *	gpio_set_value(GPO_SET_V1, 1);
++ *	gpio_set_value(GPO_SET_V2, 1);
++ */
++#endif
++	gpiochip_add(&puv3_gpio_chip);
++}
+diff --git a/arch/unicore32/kernel/irq.c b/arch/unicore32/kernel/irq.c
+new file mode 100644
+index 000000000000..7c211f597833
+--- /dev/null
++++ b/arch/unicore32/kernel/irq.c
+@@ -0,0 +1,426 @@
++/*
++ * linux/arch/unicore32/kernel/irq.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++#include 
++
++#include "setup.h"
++
++/*
++ * PKUnity GPIO edge detection for IRQs:
++ * IRQs are generated on Falling-Edge, Rising-Edge, or both.
++ * Use this instead of directly setting GRER/GFER.
++ */
++static int GPIO_IRQ_rising_edge;
++static int GPIO_IRQ_falling_edge;
++static int GPIO_IRQ_mask = 0;
++
++#define GPIO_MASK(irq)		(1 << (irq - IRQ_GPIO0))
++
++static int puv3_gpio_type(unsigned int irq, unsigned int type)
++{
++	unsigned int mask;
++
++	if (irq < IRQ_GPIOHIGH)
++		mask = 1 << irq;
++	else
++		mask = GPIO_MASK(irq);
++
++	if (type == IRQ_TYPE_PROBE) {
++		if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask)
++			return 0;
++		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
++	}
++
++	if (type & IRQ_TYPE_EDGE_RISING)
++		GPIO_IRQ_rising_edge |= mask;
++	else
++		GPIO_IRQ_rising_edge &= ~mask;
++	if (type & IRQ_TYPE_EDGE_FALLING)
++		GPIO_IRQ_falling_edge |= mask;
++	else
++		GPIO_IRQ_falling_edge &= ~mask;
++
++	GPIO_GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
++	GPIO_GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
++
++	return 0;
++}
++
++/*
++ * GPIO IRQs must be acknowledged.  This is for IRQs from 0 to 7.
++ */
++static void puv3_low_gpio_ack(unsigned int irq)
++{
++	GPIO_GEDR = (1 << irq);
++}
++
++static void puv3_low_gpio_mask(unsigned int irq)
++{
++	INTC_ICMR &= ~(1 << irq);
++}
++
++static void puv3_low_gpio_unmask(unsigned int irq)
++{
++	INTC_ICMR |= 1 << irq;
++}
++
++static int puv3_low_gpio_wake(unsigned int irq, unsigned int on)
++{
++	if (on)
++		PM_PWER |= 1 << irq;
++	else
++		PM_PWER &= ~(1 << irq);
++	return 0;
++}
++
++static struct irq_chip puv3_low_gpio_chip = {
++	.name		= "GPIO-low",
++	.ack		= puv3_low_gpio_ack,
++	.mask		= puv3_low_gpio_mask,
++	.unmask		= puv3_low_gpio_unmask,
++	.set_type	= puv3_gpio_type,
++	.set_wake	= puv3_low_gpio_wake,
++};
++
++/*
++ * IRQ8 (GPIO0 through 27) handler.  We enter here with the
++ * irq_controller_lock held, and IRQs disabled.  Decode the IRQ
++ * and call the handler.
++ */
++static void
++puv3_gpio_handler(unsigned int irq, struct irq_desc *desc)
++{
++	unsigned int mask;
++
++	mask = GPIO_GEDR;
++	do {
++		/*
++		 * clear down all currently active IRQ sources.
++		 * We will be processing them all.
++		 */
++		GPIO_GEDR = mask;
++
++		irq = IRQ_GPIO0;
++		do {
++			if (mask & 1)
++				generic_handle_irq(irq);
++			mask >>= 1;
++			irq++;
++		} while (mask);
++		mask = GPIO_GEDR;
++	} while (mask);
++}
++
++/*
++ * GPIO0-27 edge IRQs need to be handled specially.
++ * In addition, the IRQs are all collected up into one bit in the
++ * interrupt controller registers.
++ */
++static void puv3_high_gpio_ack(unsigned int irq)
++{
++	unsigned int mask = GPIO_MASK(irq);
++
++	GPIO_GEDR = mask;
++}
++
++static void puv3_high_gpio_mask(unsigned int irq)
++{
++	unsigned int mask = GPIO_MASK(irq);
++
++	GPIO_IRQ_mask &= ~mask;
++
++	GPIO_GRER &= ~mask;
++	GPIO_GFER &= ~mask;
++}
++
++static void puv3_high_gpio_unmask(unsigned int irq)
++{
++	unsigned int mask = GPIO_MASK(irq);
++
++	GPIO_IRQ_mask |= mask;
++
++	GPIO_GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
++	GPIO_GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
++}
++
++static int puv3_high_gpio_wake(unsigned int irq, unsigned int on)
++{
++	if (on)
++		PM_PWER |= PM_PWER_GPIOHIGH;
++	else
++		PM_PWER &= ~PM_PWER_GPIOHIGH;
++	return 0;
++}
++
++static struct irq_chip puv3_high_gpio_chip = {
++	.name		= "GPIO-high",
++	.ack		= puv3_high_gpio_ack,
++	.mask		= puv3_high_gpio_mask,
++	.unmask		= puv3_high_gpio_unmask,
++	.set_type	= puv3_gpio_type,
++	.set_wake	= puv3_high_gpio_wake,
++};
++
++/*
++ * We don't need to ACK IRQs on the PKUnity unless they're GPIOs
++ * this is for internal IRQs i.e. from 8 to 31.
++ */
++static void puv3_mask_irq(unsigned int irq)
++{
++	INTC_ICMR &= ~(1 << irq);
++}
++
++static void puv3_unmask_irq(unsigned int irq)
++{
++	INTC_ICMR |= (1 << irq);
++}
++
++/*
++ * Apart form GPIOs, only the RTC alarm can be a wakeup event.
++ */
++static int puv3_set_wake(unsigned int irq, unsigned int on)
++{
++	if (irq == IRQ_RTCAlarm) {
++		if (on)
++			PM_PWER |= PM_PWER_RTC;
++		else
++			PM_PWER &= ~PM_PWER_RTC;
++		return 0;
++	}
++	return -EINVAL;
++}
++
++static struct irq_chip puv3_normal_chip = {
++	.name		= "PKUnity-v3",
++	.ack		= puv3_mask_irq,
++	.mask		= puv3_mask_irq,
++	.unmask		= puv3_unmask_irq,
++	.set_wake	= puv3_set_wake,
++};
++
++static struct resource irq_resource = {
++	.name	= "irqs",
++	.start	= PKUNITY_INTC_BASE,
++	.end	= PKUNITY_INTC_BASE + 0xFFFFF,
++};
++
++static struct puv3_irq_state {
++	unsigned int	saved;
++	unsigned int	icmr;
++	unsigned int	iclr;
++	unsigned int	iccr;
++} puv3_irq_state;
++
++static int puv3_irq_suspend(struct sys_device *dev, pm_message_t state)
++{
++	struct puv3_irq_state *st = &puv3_irq_state;
++
++	st->saved = 1;
++	st->icmr = INTC_ICMR;
++	st->iclr = INTC_ICLR;
++	st->iccr = INTC_ICCR;
++
++	/*
++	 * Disable all GPIO-based interrupts.
++	 */
++	INTC_ICMR &= ~(0x1ff);
++
++	/*
++	 * Set the appropriate edges for wakeup.
++	 */
++	GPIO_GRER = PM_PWER & GPIO_IRQ_rising_edge;
++	GPIO_GFER = PM_PWER & GPIO_IRQ_falling_edge;
++
++	/*
++	 * Clear any pending GPIO interrupts.
++	 */
++	GPIO_GEDR = GPIO_GEDR;
++
++	return 0;
++}
++
++static int puv3_irq_resume(struct sys_device *dev)
++{
++	struct puv3_irq_state *st = &puv3_irq_state;
++
++	if (st->saved) {
++		INTC_ICCR = st->iccr;
++		INTC_ICLR = st->iclr;
++
++		GPIO_GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
++		GPIO_GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
++
++		INTC_ICMR = st->icmr;
++	}
++	return 0;
++}
++
++static struct sysdev_class puv3_irq_sysclass = {
++	.name		= "pkunity-irq",
++	.suspend	= puv3_irq_suspend,
++	.resume		= puv3_irq_resume,
++};
++
++static struct sys_device puv3_irq_device = {
++	.id		= 0,
++	.cls		= &puv3_irq_sysclass,
++};
++
++static int __init puv3_irq_init_devicefs(void)
++{
++	sysdev_class_register(&puv3_irq_sysclass);
++	return sysdev_register(&puv3_irq_device);
++}
++
++device_initcall(puv3_irq_init_devicefs);
++
++void __init init_IRQ(void)
++{
++	unsigned int irq;
++
++	request_resource(&iomem_resource, &irq_resource);
++
++	/* disable all IRQs */
++	INTC_ICMR = 0;
++
++	/* all IRQs are IRQ, not REAL */
++	INTC_ICLR = 0;
++
++	/* clear all GPIO edge detects */
++	GPIO_GPIR = FMASK(8, 0) & ~FIELD(1, 1, GPI_SOFF_REQ);
++	GPIO_GFER = 0;
++	GPIO_GRER = 0;
++	GPIO_GEDR = 0x0FFFFFFF;
++
++	INTC_ICCR = 1;
++
++	for (irq = 0; irq < IRQ_GPIOHIGH; irq++) {
++		set_irq_chip(irq, &puv3_low_gpio_chip);
++		set_irq_handler(irq, handle_edge_irq);
++		irq_modify_status(irq,
++			IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN,
++			0);
++	}
++
++	for (irq = IRQ_GPIOHIGH + 1; irq < IRQ_GPIO0; irq++) {
++		set_irq_chip(irq, &puv3_normal_chip);
++		set_irq_handler(irq, handle_level_irq);
++		irq_modify_status(irq,
++			IRQ_NOREQUEST | IRQ_NOAUTOEN,
++			IRQ_NOPROBE);
++	}
++
++	for (irq = IRQ_GPIO0; irq <= IRQ_GPIO27; irq++) {
++		set_irq_chip(irq, &puv3_high_gpio_chip);
++		set_irq_handler(irq, handle_edge_irq);
++		irq_modify_status(irq,
++			IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN,
++			0);
++	}
++
++	/*
++	 * Install handler for GPIO 0-27 edge detect interrupts
++	 */
++	set_irq_chip(IRQ_GPIOHIGH, &puv3_normal_chip);
++	set_irq_chained_handler(IRQ_GPIOHIGH, puv3_gpio_handler);
++
++#ifdef CONFIG_PUV3_GPIO
++	puv3_init_gpio();
++#endif
++}
++
++int show_interrupts(struct seq_file *p, void *v)
++{
++	int i = *(loff_t *) v, cpu;
++	struct irq_desc *desc;
++	struct irqaction *action;
++	unsigned long flags;
++
++	if (i == 0) {
++		char cpuname[12];
++
++		seq_printf(p, "    ");
++		for_each_present_cpu(cpu) {
++			sprintf(cpuname, "CPU%d", cpu);
++			seq_printf(p, " %10s", cpuname);
++		}
++		seq_putc(p, '\n');
++	}
++
++	if (i < nr_irqs) {
++		desc = irq_to_desc(i);
++		raw_spin_lock_irqsave(&desc->lock, flags);
++		action = desc->action;
++		if (!action)
++			goto unlock;
++
++		seq_printf(p, "%3d: ", i);
++		for_each_present_cpu(cpu)
++			seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
++		seq_printf(p, " %10s", desc->chip->name ? : "-");
++		seq_printf(p, "  %s", action->name);
++		for (action = action->next; action; action = action->next)
++			seq_printf(p, ", %s", action->name);
++
++		seq_putc(p, '\n');
++unlock:
++		raw_spin_unlock_irqrestore(&desc->lock, flags);
++	} else if (i == nr_irqs) {
++		seq_printf(p, "Error in interrupt!\n");
++	}
++	return 0;
++}
++
++/*
++ * do_IRQ handles all hardware IRQ's.  Decoded IRQs should not
++ * come via this function.  Instead, they should provide their
++ * own 'handler'
++ */
++asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
++{
++	struct pt_regs *old_regs = set_irq_regs(regs);
++
++	irq_enter();
++
++	/*
++	 * Some hardware gives randomly wrong interrupts.  Rather
++	 * than crashing, do something sensible.
++	 */
++	if (unlikely(irq >= nr_irqs)) {
++		if (printk_ratelimit())
++			printk(KERN_WARNING "Bad IRQ%u\n", irq);
++		ack_bad_irq(irq);
++	} else {
++		generic_handle_irq(irq);
++	}
++
++	irq_exit();
++	set_irq_regs(old_regs);
++}
++

commit 02b2ee16cc31df2b23d6f6c68a597d947f6c10e8
+Author: GuanXuetao 
+Date:   Sat Jan 15 18:19:03 2011 +0800
+
+    unicore32 core architecture: timer and time handling
+    
+    This patch implements timer and time.
+    RTC and PWM device drivers are also here.
+    
+    Signed-off-by: Guan Xuetao 
+
+diff --git a/arch/unicore32/include/asm/timex.h b/arch/unicore32/include/asm/timex.h
+new file mode 100644
+index 000000000000..faf16ba46544
+--- /dev/null
++++ b/arch/unicore32/include/asm/timex.h
+@@ -0,0 +1,34 @@
++/*
++ * linux/arch/unicore32/include/asm/timex.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __UNICORE_TIMEX_H__
++#define __UNICORE_TIMEX_H__
++
++#ifdef	CONFIG_ARCH_FPGA
++
++/* in FPGA, APB clock is 33M, and OST clock is 32K, */
++/* so, 1M is selected for timer interrupt correctly */
++#define	CLOCK_TICK_RATE		(32*1024)
++
++#endif
++
++#if defined(CONFIG_PUV3_DB0913)		\
++	|| defined(CONFIG_PUV3_NB0916)	\
++	|| defined(CONFIG_PUV3_SMW0919)
++
++#define  CLOCK_TICK_RATE         (14318000)
++
++#endif
++
++#include 
++
++#endif
+diff --git a/arch/unicore32/kernel/pwm.c b/arch/unicore32/kernel/pwm.c
+new file mode 100644
+index 000000000000..4615d51e3ba6
+--- /dev/null
++++ b/arch/unicore32/kernel/pwm.c
+@@ -0,0 +1,263 @@
++/*
++ * linux/arch/unicore32/kernel/pwm.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ *	Maintained by GUAN Xue-tao 
++ *	Copyright (C) 2001-2010 Guan Xuetao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++#include 
++
++struct pwm_device {
++	struct list_head	node;
++	struct platform_device *pdev;
++
++	const char	*label;
++	struct clk	*clk;
++	int		clk_enabled;
++
++	unsigned int	use_count;
++	unsigned int	pwm_id;
++};
++
++/*
++ * period_ns = 10^9 * (PRESCALE + 1) * (PV + 1) / PWM_CLK_RATE
++ * duty_ns   = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE
++ */
++int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
++{
++	unsigned long long c;
++	unsigned long period_cycles, prescale, pv, dc;
++
++	if (pwm == NULL || period_ns == 0 || duty_ns > period_ns)
++		return -EINVAL;
++
++	c = clk_get_rate(pwm->clk);
++	c = c * period_ns;
++	do_div(c, 1000000000);
++	period_cycles = c;
++
++	if (period_cycles < 1)
++		period_cycles = 1;
++	prescale = (period_cycles - 1) / 1024;
++	pv = period_cycles / (prescale + 1) - 1;
++
++	if (prescale > 63)
++		return -EINVAL;
++
++	if (duty_ns == period_ns)
++		dc = OST_PWMDCCR_FDCYCLE;
++	else
++		dc = (pv + 1) * duty_ns / period_ns;
++
++	/* NOTE: the clock to PWM has to be enabled first
++	 * before writing to the registers
++	 */
++	clk_enable(pwm->clk);
++	OST_PWMPWCR = prescale;
++	OST_PWMDCCR = pv - dc;
++	OST_PWMPCR  = pv;
++	clk_disable(pwm->clk);
++
++	return 0;
++}
++EXPORT_SYMBOL(pwm_config);
++
++int pwm_enable(struct pwm_device *pwm)
++{
++	int rc = 0;
++
++	if (!pwm->clk_enabled) {
++		rc = clk_enable(pwm->clk);
++		if (!rc)
++			pwm->clk_enabled = 1;
++	}
++	return rc;
++}
++EXPORT_SYMBOL(pwm_enable);
++
++void pwm_disable(struct pwm_device *pwm)
++{
++	if (pwm->clk_enabled) {
++		clk_disable(pwm->clk);
++		pwm->clk_enabled = 0;
++	}
++}
++EXPORT_SYMBOL(pwm_disable);
++
++static DEFINE_MUTEX(pwm_lock);
++static LIST_HEAD(pwm_list);
++
++struct pwm_device *pwm_request(int pwm_id, const char *label)
++{
++	struct pwm_device *pwm;
++	int found = 0;
++
++	mutex_lock(&pwm_lock);
++
++	list_for_each_entry(pwm, &pwm_list, node) {
++		if (pwm->pwm_id == pwm_id) {
++			found = 1;
++			break;
++		}
++	}
++
++	if (found) {
++		if (pwm->use_count == 0) {
++			pwm->use_count++;
++			pwm->label = label;
++		} else
++			pwm = ERR_PTR(-EBUSY);
++	} else
++		pwm = ERR_PTR(-ENOENT);
++
++	mutex_unlock(&pwm_lock);
++	return pwm;
++}
++EXPORT_SYMBOL(pwm_request);
++
++void pwm_free(struct pwm_device *pwm)
++{
++	mutex_lock(&pwm_lock);
++
++	if (pwm->use_count) {
++		pwm->use_count--;
++		pwm->label = NULL;
++	} else
++		pr_warning("PWM device already freed\n");
++
++	mutex_unlock(&pwm_lock);
++}
++EXPORT_SYMBOL(pwm_free);
++
++static inline void __add_pwm(struct pwm_device *pwm)
++{
++	mutex_lock(&pwm_lock);
++	list_add_tail(&pwm->node, &pwm_list);
++	mutex_unlock(&pwm_lock);
++}
++
++static struct pwm_device *pwm_probe(struct platform_device *pdev,
++		unsigned int pwm_id, struct pwm_device *parent_pwm)
++{
++	struct pwm_device *pwm;
++	struct resource *r;
++	int ret = 0;
++
++	pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL);
++	if (pwm == NULL) {
++		dev_err(&pdev->dev, "failed to allocate memory\n");
++		return ERR_PTR(-ENOMEM);
++	}
++
++	pwm->clk = clk_get(NULL, "OST_CLK");
++	if (IS_ERR(pwm->clk)) {
++		ret = PTR_ERR(pwm->clk);
++		goto err_free;
++	}
++	pwm->clk_enabled = 0;
++
++	pwm->use_count = 0;
++	pwm->pwm_id = pwm_id;
++	pwm->pdev = pdev;
++
++	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	if (r == NULL) {
++		dev_err(&pdev->dev, "no memory resource defined\n");
++		ret = -ENODEV;
++		goto err_free_clk;
++	}
++
++	r = request_mem_region(r->start, resource_size(r), pdev->name);
++	if (r == NULL) {
++		dev_err(&pdev->dev, "failed to request memory resource\n");
++		ret = -EBUSY;
++		goto err_free_clk;
++	}
++
++	__add_pwm(pwm);
++	platform_set_drvdata(pdev, pwm);
++	return pwm;
++
++err_free_clk:
++	clk_put(pwm->clk);
++err_free:
++	kfree(pwm);
++	return ERR_PTR(ret);
++}
++
++static int __devinit puv3_pwm_probe(struct platform_device *pdev)
++{
++	struct pwm_device *pwm = pwm_probe(pdev, pdev->id, NULL);
++
++	if (IS_ERR(pwm))
++		return PTR_ERR(pwm);
++
++	return 0;
++}
++
++static int __devexit pwm_remove(struct platform_device *pdev)
++{
++	struct pwm_device *pwm;
++	struct resource *r;
++
++	pwm = platform_get_drvdata(pdev);
++	if (pwm == NULL)
++		return -ENODEV;
++
++	mutex_lock(&pwm_lock);
++	list_del(&pwm->node);
++	mutex_unlock(&pwm_lock);
++
++	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	release_mem_region(r->start, resource_size(r));
++
++	clk_put(pwm->clk);
++	kfree(pwm);
++	return 0;
++}
++
++static struct platform_driver puv3_pwm_driver = {
++	.driver		= {
++		.name	= "PKUnity-v3-PWM",
++	},
++	.probe		= puv3_pwm_probe,
++	.remove		= __devexit_p(pwm_remove),
++};
++
++static int __init pwm_init(void)
++{
++	int ret = 0;
++
++	ret = platform_driver_register(&puv3_pwm_driver);
++	if (ret) {
++		printk(KERN_ERR "failed to register puv3_pwm_driver\n");
++		return ret;
++	}
++
++	return ret;
++}
++arch_initcall(pwm_init);
++
++static void __exit pwm_exit(void)
++{
++	platform_driver_unregister(&puv3_pwm_driver);
++}
++module_exit(pwm_exit);
++
++MODULE_LICENSE("GPL v2");
+diff --git a/arch/unicore32/kernel/rtc.c b/arch/unicore32/kernel/rtc.c
+new file mode 100644
+index 000000000000..5e4db4158589
+--- /dev/null
++++ b/arch/unicore32/kernel/rtc.c
+@@ -0,0 +1,380 @@
++/*
++ * linux/arch/unicore32/kernel/rtc.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ *	Maintained by GUAN Xue-tao 
++ *	Copyright (C) 2001-2010 Guan Xuetao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++#include 
++
++static struct resource *puv3_rtc_mem;
++
++static int puv3_rtc_alarmno = IRQ_RTCAlarm;
++static int puv3_rtc_tickno  = IRQ_RTC;
++
++static DEFINE_SPINLOCK(puv3_rtc_pie_lock);
++
++/* IRQ Handlers */
++
++static irqreturn_t puv3_rtc_alarmirq(int irq, void *id)
++{
++	struct rtc_device *rdev = id;
++
++	RTC_RTSR |= RTC_RTSR_AL;
++	rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF);
++	return IRQ_HANDLED;
++}
++
++static irqreturn_t puv3_rtc_tickirq(int irq, void *id)
++{
++	struct rtc_device *rdev = id;
++
++	RTC_RTSR |= RTC_RTSR_HZ;
++	rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF);
++	return IRQ_HANDLED;
++}
++
++/* Update control registers */
++static void puv3_rtc_setaie(int to)
++{
++	unsigned int tmp;
++
++	pr_debug("%s: aie=%d\n", __func__, to);
++
++	tmp = RTC_RTSR & ~RTC_RTSR_ALE;
++
++	if (to)
++		tmp |= RTC_RTSR_ALE;
++
++	RTC_RTSR = tmp;
++}
++
++static int puv3_rtc_setpie(struct device *dev, int enabled)
++{
++	unsigned int tmp;
++
++	pr_debug("%s: pie=%d\n", __func__, enabled);
++
++	spin_lock_irq(&puv3_rtc_pie_lock);
++	tmp = RTC_RTSR & ~RTC_RTSR_HZE;
++
++	if (enabled)
++		tmp |= RTC_RTSR_HZE;
++
++	RTC_RTSR = tmp;
++	spin_unlock_irq(&puv3_rtc_pie_lock);
++
++	return 0;
++}
++
++static int puv3_rtc_setfreq(struct device *dev, int freq)
++{
++	return 0;
++}
++
++/* Time read/write */
++
++static int puv3_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
++{
++	rtc_time_to_tm(RTC_RCNR, rtc_tm);
++
++	pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n",
++		 rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
++		 rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
++
++	return 0;
++}
++
++static int puv3_rtc_settime(struct device *dev, struct rtc_time *tm)
++{
++	unsigned long rtc_count = 0;
++
++	pr_debug("set time %02d.%02d.%02d %02d/%02d/%02d\n",
++		 tm->tm_year, tm->tm_mon, tm->tm_mday,
++		 tm->tm_hour, tm->tm_min, tm->tm_sec);
++
++	rtc_tm_to_time(tm, &rtc_count);
++	RTC_RCNR = rtc_count;
++
++	return 0;
++}
++
++static int puv3_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
++{
++	struct rtc_time *alm_tm = &alrm->time;
++
++	rtc_time_to_tm(RTC_RTAR, alm_tm);
++
++	alrm->enabled = RTC_RTSR & RTC_RTSR_ALE;
++
++	pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n",
++		 alrm->enabled,
++		 alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday,
++		 alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec);
++
++	return 0;
++}
++
++static int puv3_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
++{
++	struct rtc_time *tm = &alrm->time;
++	unsigned long rtcalarm_count = 0;
++
++	pr_debug("puv3_rtc_setalarm: %d, %02x/%02x/%02x %02x.%02x.%02x\n",
++		 alrm->enabled,
++		 tm->tm_mday & 0xff, tm->tm_mon & 0xff, tm->tm_year & 0xff,
++		 tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec);
++
++	rtc_tm_to_time(tm, &rtcalarm_count);
++	RTC_RTAR = rtcalarm_count;
++
++	puv3_rtc_setaie(alrm->enabled);
++
++	if (alrm->enabled)
++		enable_irq_wake(puv3_rtc_alarmno);
++	else
++		disable_irq_wake(puv3_rtc_alarmno);
++
++	return 0;
++}
++
++static int puv3_rtc_proc(struct device *dev, struct seq_file *seq)
++{
++	seq_printf(seq, "periodic_IRQ\t: %s\n",
++		     (RTC_RTSR & RTC_RTSR_HZE) ? "yes" : "no");
++	return 0;
++}
++
++static int puv3_rtc_open(struct device *dev)
++{
++	struct platform_device *pdev = to_platform_device(dev);
++	struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
++	int ret;
++
++	ret = request_irq(puv3_rtc_alarmno, puv3_rtc_alarmirq,
++			  IRQF_DISABLED,  "pkunity-rtc alarm", rtc_dev);
++
++	if (ret) {
++		dev_err(dev, "IRQ%d error %d\n", puv3_rtc_alarmno, ret);
++		return ret;
++	}
++
++	ret = request_irq(puv3_rtc_tickno, puv3_rtc_tickirq,
++			  IRQF_DISABLED,  "pkunity-rtc tick", rtc_dev);
++
++	if (ret) {
++		dev_err(dev, "IRQ%d error %d\n", puv3_rtc_tickno, ret);
++		goto tick_err;
++	}
++
++	return ret;
++
++ tick_err:
++	free_irq(puv3_rtc_alarmno, rtc_dev);
++	return ret;
++}
++
++static void puv3_rtc_release(struct device *dev)
++{
++	struct platform_device *pdev = to_platform_device(dev);
++	struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
++
++	/* do not clear AIE here, it may be needed for wake */
++
++	puv3_rtc_setpie(dev, 0);
++	free_irq(puv3_rtc_alarmno, rtc_dev);
++	free_irq(puv3_rtc_tickno, rtc_dev);
++}
++
++static const struct rtc_class_ops puv3_rtcops = {
++	.open		= puv3_rtc_open,
++	.release	= puv3_rtc_release,
++	.read_time	= puv3_rtc_gettime,
++	.set_time	= puv3_rtc_settime,
++	.read_alarm	= puv3_rtc_getalarm,
++	.set_alarm	= puv3_rtc_setalarm,
++	.irq_set_freq	= puv3_rtc_setfreq,
++	.irq_set_state	= puv3_rtc_setpie,
++	.proc	        = puv3_rtc_proc,
++};
++
++static void puv3_rtc_enable(struct platform_device *pdev, int en)
++{
++	if (!en) {
++		RTC_RTSR &= ~RTC_RTSR_HZE;
++	} else {
++		/* re-enable the device, and check it is ok */
++
++		if ((RTC_RTSR & RTC_RTSR_HZE) == 0) {
++			dev_info(&pdev->dev, "rtc disabled, re-enabling\n");
++			RTC_RTSR |= RTC_RTSR_HZE;
++		}
++	}
++}
++
++static int puv3_rtc_remove(struct platform_device *dev)
++{
++	struct rtc_device *rtc = platform_get_drvdata(dev);
++
++	platform_set_drvdata(dev, NULL);
++	rtc_device_unregister(rtc);
++
++	puv3_rtc_setpie(&dev->dev, 0);
++	puv3_rtc_setaie(0);
++
++	release_resource(puv3_rtc_mem);
++	kfree(puv3_rtc_mem);
++
++	return 0;
++}
++
++static int puv3_rtc_probe(struct platform_device *pdev)
++{
++	struct rtc_device *rtc;
++	struct resource *res;
++	int ret;
++
++	pr_debug("%s: probe=%p\n", __func__, pdev);
++
++	/* find the IRQs */
++
++	puv3_rtc_tickno = platform_get_irq(pdev, 1);
++	if (puv3_rtc_tickno < 0) {
++		dev_err(&pdev->dev, "no irq for rtc tick\n");
++		return -ENOENT;
++	}
++
++	puv3_rtc_alarmno = platform_get_irq(pdev, 0);
++	if (puv3_rtc_alarmno < 0) {
++		dev_err(&pdev->dev, "no irq for alarm\n");
++		return -ENOENT;
++	}
++
++	pr_debug("PKUnity_rtc: tick irq %d, alarm irq %d\n",
++		 puv3_rtc_tickno, puv3_rtc_alarmno);
++
++	/* get the memory region */
++
++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	if (res == NULL) {
++		dev_err(&pdev->dev, "failed to get memory region resource\n");
++		return -ENOENT;
++	}
++
++	puv3_rtc_mem = request_mem_region(res->start,
++					 res->end-res->start+1,
++					 pdev->name);
++
++	if (puv3_rtc_mem == NULL) {
++		dev_err(&pdev->dev, "failed to reserve memory region\n");
++		ret = -ENOENT;
++		goto err_nores;
++	}
++
++	puv3_rtc_enable(pdev, 1);
++
++	puv3_rtc_setfreq(&pdev->dev, 1);
++
++	/* register RTC and exit */
++
++	rtc = rtc_device_register("pkunity", &pdev->dev, &puv3_rtcops,
++				  THIS_MODULE);
++
++	if (IS_ERR(rtc)) {
++		dev_err(&pdev->dev, "cannot attach rtc\n");
++		ret = PTR_ERR(rtc);
++		goto err_nortc;
++	}
++
++	/* platform setup code should have handled this; sigh */
++	if (!device_can_wakeup(&pdev->dev))
++		device_init_wakeup(&pdev->dev, 1);
++
++	platform_set_drvdata(pdev, rtc);
++	return 0;
++
++ err_nortc:
++	puv3_rtc_enable(pdev, 0);
++	release_resource(puv3_rtc_mem);
++
++ err_nores:
++	return ret;
++}
++
++#ifdef CONFIG_PM
++
++/* RTC Power management control */
++
++static int ticnt_save;
++
++static int puv3_rtc_suspend(struct platform_device *pdev, pm_message_t state)
++{
++	/* save RTAR for anyone using periodic interrupts */
++	ticnt_save = RTC_RTAR;
++	puv3_rtc_enable(pdev, 0);
++	return 0;
++}
++
++static int puv3_rtc_resume(struct platform_device *pdev)
++{
++	puv3_rtc_enable(pdev, 1);
++	RTC_RTAR = ticnt_save;
++	return 0;
++}
++#else
++#define puv3_rtc_suspend NULL
++#define puv3_rtc_resume  NULL
++#endif
++
++static struct platform_driver puv3_rtcdrv = {
++	.probe		= puv3_rtc_probe,
++	.remove		= __devexit_p(puv3_rtc_remove),
++	.suspend	= puv3_rtc_suspend,
++	.resume		= puv3_rtc_resume,
++	.driver		= {
++		.name	= "PKUnity-v3-RTC",
++		.owner	= THIS_MODULE,
++	}
++};
++
++static char __initdata banner[] = "PKUnity-v3 RTC, (c) 2009 PKUnity Co.\n";
++
++static int __init puv3_rtc_init(void)
++{
++	printk(banner);
++	return platform_driver_register(&puv3_rtcdrv);
++}
++
++static void __exit puv3_rtc_exit(void)
++{
++	platform_driver_unregister(&puv3_rtcdrv);
++}
++
++module_init(puv3_rtc_init);
++module_exit(puv3_rtc_exit);
++
++MODULE_DESCRIPTION("RTC Driver for the PKUnity v3 chip");
++MODULE_AUTHOR("Hu Dongliang");
++MODULE_LICENSE("GPL v2");
++
+diff --git a/arch/unicore32/kernel/time.c b/arch/unicore32/kernel/time.c
+new file mode 100644
+index 000000000000..8090d763a606
+--- /dev/null
++++ b/arch/unicore32/kernel/time.c
+@@ -0,0 +1,148 @@
++/*
++ * linux/arch/unicore32/kernel/time.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ *	Maintained by GUAN Xue-tao 
++ *	Copyright (C) 2001-2010 Guan Xuetao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++
++#define MIN_OSCR_DELTA 2
++
++static irqreturn_t puv3_ost0_interrupt(int irq, void *dev_id)
++{
++	struct clock_event_device *c = dev_id;
++
++	/* Disarm the compare/match, signal the event. */
++	OST_OIER &= ~OST_OIER_E0;
++	OST_OSSR &= ~OST_OSSR_M0;
++	c->event_handler(c);
++
++	return IRQ_HANDLED;
++}
++
++static int
++puv3_osmr0_set_next_event(unsigned long delta, struct clock_event_device *c)
++{
++	unsigned long next, oscr;
++
++	OST_OIER |= OST_OIER_E0;
++	next = OST_OSCR + delta;
++	OST_OSMR0 = next;
++	oscr = OST_OSCR;
++
++	return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0;
++}
++
++static void
++puv3_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *c)
++{
++	switch (mode) {
++	case CLOCK_EVT_MODE_ONESHOT:
++	case CLOCK_EVT_MODE_UNUSED:
++	case CLOCK_EVT_MODE_SHUTDOWN:
++		OST_OIER &= ~OST_OIER_E0;
++		OST_OSSR &= ~OST_OSSR_M0;
++		break;
++
++	case CLOCK_EVT_MODE_RESUME:
++	case CLOCK_EVT_MODE_PERIODIC:
++		break;
++	}
++}
++
++static struct clock_event_device ckevt_puv3_osmr0 = {
++	.name		= "osmr0",
++	.features	= CLOCK_EVT_FEAT_ONESHOT,
++#ifdef CONFIG_ARCH_FPGA
++	.shift		= 18, /* correct shift val: 16, but warn_on_slowpath */
++#else
++	.shift          = 30,
++#endif
++	.rating		= 200,
++	.set_next_event	= puv3_osmr0_set_next_event,
++	.set_mode	= puv3_osmr0_set_mode,
++};
++
++static cycle_t puv3_read_oscr(struct clocksource *cs)
++{
++	return OST_OSCR;
++}
++
++static struct clocksource cksrc_puv3_oscr = {
++	.name		= "oscr",
++	.rating		= 200,
++	.read		= puv3_read_oscr,
++	.mask		= CLOCKSOURCE_MASK(32),
++	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
++};
++
++static struct irqaction puv3_timer_irq = {
++	.name		= "ost0",
++	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
++	.handler	= puv3_ost0_interrupt,
++	.dev_id		= &ckevt_puv3_osmr0,
++};
++
++void __init time_init(void)
++{
++	OST_OIER = 0;		/* disable any timer interrupts */
++	OST_OSSR = 0;		/* clear status on all timers */
++
++	ckevt_puv3_osmr0.mult =
++		div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt_puv3_osmr0.shift);
++	ckevt_puv3_osmr0.max_delta_ns =
++		clockevent_delta2ns(0x7fffffff, &ckevt_puv3_osmr0);
++	ckevt_puv3_osmr0.min_delta_ns =
++		clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_puv3_osmr0) + 1;
++	ckevt_puv3_osmr0.cpumask = cpumask_of(0);
++
++	setup_irq(IRQ_TIMER0, &puv3_timer_irq);
++
++	clocksource_register_hz(&cksrc_puv3_oscr, CLOCK_TICK_RATE);
++	clockevents_register_device(&ckevt_puv3_osmr0);
++}
++
++#ifdef CONFIG_PM
++unsigned long osmr[4], oier;
++
++void puv3_timer_suspend(void)
++{
++	osmr[0] = OST_OSMR0;
++	osmr[1] = OST_OSMR1;
++	osmr[2] = OST_OSMR2;
++	osmr[3] = OST_OSMR3;
++	oier = OST_OIER;
++}
++
++void puv3_timer_resume(void)
++{
++	OST_OSSR = 0;
++	OST_OSMR0 = osmr[0];
++	OST_OSMR1 = osmr[1];
++	OST_OSMR2 = osmr[2];
++	OST_OSMR3 = osmr[3];
++	OST_OIER = oier;
++
++	/*
++	 * OSMR0 is the system timer: make sure OSCR is sufficiently behind
++	 */
++	OST_OSCR = OST_OSMR0 - LATCH;
++}
++#else
++void puv3_timer_suspend(void) { };
++void puv3_timer_resume(void) { };
++#endif
++

commit 10c9c10c31514564b09c153432a42ffaea3ce831
+Author: GuanXuetao 
+Date:   Sat Jan 15 18:18:29 2011 +0800
+
+    unicore32 core architecture: mm related: consistent device DMA handling
+    
+    This patch implements consistent device DMA handling of memory management.
+    DMA device operations are also here.
+    
+    Signed-off-by: Guan Xuetao 
+    Reviewed-by: Arnd Bergmann 
+
+diff --git a/arch/unicore32/include/asm/cacheflush.h b/arch/unicore32/include/asm/cacheflush.h
+new file mode 100644
+index 000000000000..c0301e6c8b81
+--- /dev/null
++++ b/arch/unicore32/include/asm/cacheflush.h
+@@ -0,0 +1,211 @@
++/*
++ * linux/arch/unicore32/include/asm/cacheflush.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_CACHEFLUSH_H__
++#define __UNICORE_CACHEFLUSH_H__
++
++#include 
++
++#include 
++
++#define CACHE_COLOUR(vaddr)	((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
++
++/*
++ * This flag is used to indicate that the page pointed to by a pte is clean
++ * and does not require cleaning before returning it to the user.
++ */
++#define PG_dcache_clean PG_arch_1
++
++/*
++ *	MM Cache Management
++ *	===================
++ *
++ *	The arch/unicore32/mm/cache.S files implement these methods.
++ *
++ *	Start addresses are inclusive and end addresses are exclusive;
++ *	start addresses should be rounded down, end addresses up.
++ *
++ *	See Documentation/cachetlb.txt for more information.
++ *	Please note that the implementation of these, and the required
++ *	effects are cache-type (VIVT/VIPT/PIPT) specific.
++ *
++ *	flush_icache_all()
++ *
++ *		Unconditionally clean and invalidate the entire icache.
++ *		Currently only needed for cache-v6.S and cache-v7.S, see
++ *		__flush_icache_all for the generic implementation.
++ *
++ *	flush_kern_all()
++ *
++ *		Unconditionally clean and invalidate the entire cache.
++ *
++ *	flush_user_all()
++ *
++ *		Clean and invalidate all user space cache entries
++ *		before a change of page tables.
++ *
++ *	flush_user_range(start, end, flags)
++ *
++ *		Clean and invalidate a range of cache entries in the
++ *		specified address space before a change of page tables.
++ *		- start - user start address (inclusive, page aligned)
++ *		- end   - user end address   (exclusive, page aligned)
++ *		- flags - vma->vm_flags field
++ *
++ *	coherent_kern_range(start, end)
++ *
++ *		Ensure coherency between the Icache and the Dcache in the
++ *		region described by start, end.  If you have non-snooping
++ *		Harvard caches, you need to implement this function.
++ *		- start  - virtual start address
++ *		- end    - virtual end address
++ *
++ *	coherent_user_range(start, end)
++ *
++ *		Ensure coherency between the Icache and the Dcache in the
++ *		region described by start, end.  If you have non-snooping
++ *		Harvard caches, you need to implement this function.
++ *		- start  - virtual start address
++ *		- end    - virtual end address
++ *
++ *	flush_kern_dcache_area(kaddr, size)
++ *
++ *		Ensure that the data held in page is written back.
++ *		- kaddr  - page address
++ *		- size   - region size
++ *
++ *	DMA Cache Coherency
++ *	===================
++ *
++ *	dma_flush_range(start, end)
++ *
++ *		Clean and invalidate the specified virtual address range.
++ *		- start  - virtual start address
++ *		- end    - virtual end address
++ */
++
++extern void __cpuc_flush_icache_all(void);
++extern void __cpuc_flush_kern_all(void);
++extern void __cpuc_flush_user_all(void);
++extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int);
++extern void __cpuc_coherent_kern_range(unsigned long, unsigned long);
++extern void __cpuc_coherent_user_range(unsigned long, unsigned long);
++extern void __cpuc_flush_dcache_area(void *, size_t);
++extern void __cpuc_flush_kern_dcache_area(void *addr, size_t size);
++
++/*
++ * These are private to the dma-mapping API.  Do not use directly.
++ * Their sole purpose is to ensure that data held in the cache
++ * is visible to DMA, or data written by DMA to system memory is
++ * visible to the CPU.
++ */
++extern void __cpuc_dma_clean_range(unsigned long, unsigned long);
++extern void __cpuc_dma_flush_range(unsigned long, unsigned long);
++
++/*
++ * Copy user data from/to a page which is mapped into a different
++ * processes address space.  Really, we want to allow our "user
++ * space" model to handle this.
++ */
++extern void copy_to_user_page(struct vm_area_struct *, struct page *,
++	unsigned long, void *, const void *, unsigned long);
++#define copy_from_user_page(vma, page, vaddr, dst, src, len)	\
++	do {							\
++		memcpy(dst, src, len);				\
++	} while (0)
++
++/*
++ * Convert calls to our calling convention.
++ */
++/* Invalidate I-cache */
++static inline void __flush_icache_all(void)
++{
++	asm("movc	p0.c5, %0, #20;\n"
++	    "nop; nop; nop; nop; nop; nop; nop; nop\n"
++	    :
++	    : "r" (0));
++}
++
++#define flush_cache_all()		__cpuc_flush_kern_all()
++
++extern void flush_cache_mm(struct mm_struct *mm);
++extern void flush_cache_range(struct vm_area_struct *vma,
++		unsigned long start, unsigned long end);
++extern void flush_cache_page(struct vm_area_struct *vma,
++		unsigned long user_addr, unsigned long pfn);
++
++#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
++
++/*
++ * flush_cache_user_range is used when we want to ensure that the
++ * Harvard caches are synchronised for the user space address range.
++ * This is used for the UniCore private sys_cacheflush system call.
++ */
++#define flush_cache_user_range(vma, start, end) \
++	__cpuc_coherent_user_range((start) & PAGE_MASK, PAGE_ALIGN(end))
++
++/*
++ * Perform necessary cache operations to ensure that data previously
++ * stored within this range of addresses can be executed by the CPU.
++ */
++#define flush_icache_range(s, e)	__cpuc_coherent_kern_range(s, e)
++
++/*
++ * Perform necessary cache operations to ensure that the TLB will
++ * see data written in the specified area.
++ */
++#define clean_dcache_area(start, size)	cpu_dcache_clean_area(start, size)
++
++/*
++ * flush_dcache_page is used when the kernel has written to the page
++ * cache page at virtual address page->virtual.
++ *
++ * If this page isn't mapped (ie, page_mapping == NULL), or it might
++ * have userspace mappings, then we _must_ always clean + invalidate
++ * the dcache entries associated with the kernel mapping.
++ *
++ * Otherwise we can defer the operation, and clean the cache when we are
++ * about to change to user space.  This is the same method as used on SPARC64.
++ * See update_mmu_cache for the user space part.
++ */
++#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
++extern void flush_dcache_page(struct page *);
++
++#define flush_dcache_mmap_lock(mapping)			\
++	spin_lock_irq(&(mapping)->tree_lock)
++#define flush_dcache_mmap_unlock(mapping)		\
++	spin_unlock_irq(&(mapping)->tree_lock)
++
++#define flush_icache_user_range(vma, page, addr, len)	\
++	flush_dcache_page(page)
++
++/*
++ * We don't appear to need to do anything here.  In fact, if we did, we'd
++ * duplicate cache flushing elsewhere performed by flush_dcache_page().
++ */
++#define flush_icache_page(vma, page)	do { } while (0)
++
++/*
++ * flush_cache_vmap() is used when creating mappings (eg, via vmap,
++ * vmalloc, ioremap etc) in kernel space for pages.  On non-VIPT
++ * caches, since the direct-mappings of these pages may contain cached
++ * data, we need to do a full cache flush to ensure that writebacks
++ * don't corrupt data placed into these pages via the new mappings.
++ */
++static inline void flush_cache_vmap(unsigned long start, unsigned long end)
++{
++}
++
++static inline void flush_cache_vunmap(unsigned long start, unsigned long end)
++{
++}
++
++#endif
+diff --git a/arch/unicore32/include/asm/dma-mapping.h b/arch/unicore32/include/asm/dma-mapping.h
+new file mode 100644
+index 000000000000..9258e592f414
+--- /dev/null
++++ b/arch/unicore32/include/asm/dma-mapping.h
+@@ -0,0 +1,124 @@
++/*
++ * linux/arch/unicore32/include/asm/dma-mapping.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_DMA_MAPPING_H__
++#define __UNICORE_DMA_MAPPING_H__
++
++#ifdef __KERNEL__
++
++#include 
++#include 
++#include 
++
++#include 
++
++#include 
++#include 
++
++extern struct dma_map_ops swiotlb_dma_map_ops;
++
++static inline struct dma_map_ops *get_dma_ops(struct device *dev)
++{
++	return &swiotlb_dma_map_ops;
++}
++
++static inline int dma_supported(struct device *dev, u64 mask)
++{
++	struct dma_map_ops *dma_ops = get_dma_ops(dev);
++
++	if (unlikely(dma_ops == NULL))
++		return 0;
++
++	return dma_ops->dma_supported(dev, mask);
++}
++
++static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
++{
++	struct dma_map_ops *dma_ops = get_dma_ops(dev);
++
++	if (dma_ops->mapping_error)
++		return dma_ops->mapping_error(dev, dma_addr);
++
++	return 0;
++}
++
++#include 
++
++static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
++{
++	if (dev && dev->dma_mask)
++		return addr + size - 1 <= *dev->dma_mask;
++
++	return 1;
++}
++
++static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
++{
++	return paddr;
++}
++
++static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
++{
++	return daddr;
++}
++
++static inline void dma_mark_clean(void *addr, size_t size) {}
++
++static inline int dma_set_mask(struct device *dev, u64 dma_mask)
++{
++	if (!dev->dma_mask || !dma_supported(dev, dma_mask))
++		return -EIO;
++
++	*dev->dma_mask = dma_mask;
++
++	return 0;
++}
++
++static inline void *dma_alloc_coherent(struct device *dev, size_t size,
++				       dma_addr_t *dma_handle, gfp_t flag)
++{
++	struct dma_map_ops *dma_ops = get_dma_ops(dev);
++
++	return dma_ops->alloc_coherent(dev, size, dma_handle, flag);
++}
++
++static inline void dma_free_coherent(struct device *dev, size_t size,
++				     void *cpu_addr, dma_addr_t dma_handle)
++{
++	struct dma_map_ops *dma_ops = get_dma_ops(dev);
++
++	dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
++}
++
++#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
++#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
++
++static inline void dma_cache_sync(struct device *dev, void *vaddr,
++		size_t size, enum dma_data_direction direction)
++{
++	unsigned long start = (unsigned long)vaddr;
++	unsigned long end   = start + size;
++
++	switch (direction) {
++	case DMA_NONE:
++		BUG();
++	case DMA_FROM_DEVICE:
++	case DMA_BIDIRECTIONAL:	/* writeback and invalidate */
++		__cpuc_dma_flush_range(start, end);
++		break;
++	case DMA_TO_DEVICE:		/* writeback only */
++		__cpuc_dma_clean_range(start, end);
++		break;
++	}
++}
++
++#endif /* __KERNEL__ */
++#endif
+diff --git a/arch/unicore32/include/asm/dma.h b/arch/unicore32/include/asm/dma.h
+new file mode 100644
+index 000000000000..38dfff9df32f
+--- /dev/null
++++ b/arch/unicore32/include/asm/dma.h
+@@ -0,0 +1,23 @@
++/*
++ * linux/arch/unicore32/include/asm/dma.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __UNICORE_DMA_H__
++#define __UNICORE_DMA_H__
++
++#include 
++#include 
++
++#ifdef CONFIG_PCI
++extern int isa_dma_bridge_buggy;
++#endif
++
++#endif /* __UNICORE_DMA_H__ */
+diff --git a/arch/unicore32/include/asm/tlbflush.h b/arch/unicore32/include/asm/tlbflush.h
+new file mode 100644
+index 000000000000..e446ac8bb9e5
+--- /dev/null
++++ b/arch/unicore32/include/asm/tlbflush.h
+@@ -0,0 +1,195 @@
++/*
++ * linux/arch/unicore32/include/asm/tlbflush.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_TLBFLUSH_H__
++#define __UNICORE_TLBFLUSH_H__
++
++#ifndef __ASSEMBLY__
++
++#include 
++
++extern void __cpu_flush_user_tlb_range(unsigned long, unsigned long,
++					struct vm_area_struct *);
++extern void __cpu_flush_kern_tlb_range(unsigned long, unsigned long);
++
++/*
++ *	TLB Management
++ *	==============
++ *
++ *	The arch/unicore/mm/tlb-*.S files implement these methods.
++ *
++ *	The TLB specific code is expected to perform whatever tests it
++ *	needs to determine if it should invalidate the TLB for each
++ *	call.  Start addresses are inclusive and end addresses are
++ *	exclusive; it is safe to round these addresses down.
++ *
++ *	flush_tlb_all()
++ *
++ *		Invalidate the entire TLB.
++ *
++ *	flush_tlb_mm(mm)
++ *
++ *		Invalidate all TLB entries in a particular address
++ *		space.
++ *		- mm	- mm_struct describing address space
++ *
++ *	flush_tlb_range(mm,start,end)
++ *
++ *		Invalidate a range of TLB entries in the specified
++ *		address space.
++ *		- mm	- mm_struct describing address space
++ *		- start - start address (may not be aligned)
++ *		- end	- end address (exclusive, may not be aligned)
++ *
++ *	flush_tlb_page(vaddr,vma)
++ *
++ *		Invalidate the specified page in the specified address range.
++ *		- vaddr - virtual address (may not be aligned)
++ *		- vma	- vma_struct describing address range
++ *
++ *	flush_kern_tlb_page(kaddr)
++ *
++ *		Invalidate the TLB entry for the specified page.  The address
++ *		will be in the kernels virtual memory space.  Current uses
++ *		only require the D-TLB to be invalidated.
++ *		- kaddr - Kernel virtual memory address
++ */
++
++static inline void local_flush_tlb_all(void)
++{
++	const int zero = 0;
++
++	/* TLB invalidate all */
++	asm("movc p0.c6, %0, #6; nop; nop; nop; nop; nop; nop; nop; nop"
++		: : "r" (zero) : "cc");
++}
++
++static inline void local_flush_tlb_mm(struct mm_struct *mm)
++{
++	const int zero = 0;
++
++	if (cpumask_test_cpu(get_cpu(), mm_cpumask(mm))) {
++		/* TLB invalidate all */
++		asm("movc p0.c6, %0, #6; nop; nop; nop; nop; nop; nop; nop; nop"
++			: : "r" (zero) : "cc");
++	}
++	put_cpu();
++}
++
++static inline void
++local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
++{
++	if (cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm))) {
++#ifndef CONFIG_CPU_TLB_SINGLE_ENTRY_DISABLE
++		/* iTLB invalidate page */
++		asm("movc p0.c6, %0, #5; nop; nop; nop; nop; nop; nop; nop; nop"
++			: : "r" (uaddr & PAGE_MASK) : "cc");
++		/* dTLB invalidate page */
++		asm("movc p0.c6, %0, #3; nop; nop; nop; nop; nop; nop; nop; nop"
++			: : "r" (uaddr & PAGE_MASK) : "cc");
++#else
++		/* TLB invalidate all */
++		asm("movc p0.c6, %0, #6; nop; nop; nop; nop; nop; nop; nop; nop"
++			: : "r" (uaddr & PAGE_MASK) : "cc");
++#endif
++	}
++}
++
++static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
++{
++#ifndef CONFIG_CPU_TLB_SINGLE_ENTRY_DISABLE
++	/* iTLB invalidate page */
++	asm("movc p0.c6, %0, #5; nop; nop; nop; nop; nop; nop; nop; nop"
++		: : "r" (kaddr & PAGE_MASK) : "cc");
++	/* dTLB invalidate page */
++	asm("movc p0.c6, %0, #3; nop; nop; nop; nop; nop; nop; nop; nop"
++		: : "r" (kaddr & PAGE_MASK) : "cc");
++#else
++	/* TLB invalidate all */
++	asm("movc p0.c6, %0, #6; nop; nop; nop; nop; nop; nop; nop; nop"
++		: : "r" (kaddr & PAGE_MASK) : "cc");
++#endif
++}
++
++/*
++ *	flush_pmd_entry
++ *
++ *	Flush a PMD entry (word aligned, or double-word aligned) to
++ *	RAM if the TLB for the CPU we are running on requires this.
++ *	This is typically used when we are creating PMD entries.
++ *
++ *	clean_pmd_entry
++ *
++ *	Clean (but don't drain the write buffer) if the CPU requires
++ *	these operations.  This is typically used when we are removing
++ *	PMD entries.
++ */
++static inline void flush_pmd_entry(pmd_t *pmd)
++{
++#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
++	/* flush dcache line, see dcacheline_flush in proc-macros.S */
++	asm("mov	r1, %0 << #20\n"
++		"ldw	r2, =_stext\n"
++		"add	r2, r2, r1 >> #20\n"
++		"ldw	r1, [r2+], #0x0000\n"
++		"ldw	r1, [r2+], #0x1000\n"
++		"ldw	r1, [r2+], #0x2000\n"
++		"ldw	r1, [r2+], #0x3000\n"
++		: : "r" (pmd) : "r1", "r2");
++#else
++	/* flush dcache all */
++	asm("movc p0.c5, %0, #14; nop; nop; nop; nop; nop; nop; nop; nop"
++		: : "r" (pmd) : "cc");
++#endif
++}
++
++static inline void clean_pmd_entry(pmd_t *pmd)
++{
++#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
++	/* clean dcache line */
++	asm("movc p0.c5, %0, #11; nop; nop; nop; nop; nop; nop; nop; nop"
++		: : "r" (__pa(pmd) & ~(L1_CACHE_BYTES - 1)) : "cc");
++#else
++	/* clean dcache all */
++	asm("movc p0.c5, %0, #10; nop; nop; nop; nop; nop; nop; nop; nop"
++		: : "r" (pmd) : "cc");
++#endif
++}
++
++/*
++ * Convert calls to our calling convention.
++ */
++#define local_flush_tlb_range(vma, start, end)	\
++	__cpu_flush_user_tlb_range(start, end, vma)
++#define local_flush_tlb_kernel_range(s, e)	\
++	__cpu_flush_kern_tlb_range(s, e)
++
++#define flush_tlb_all		local_flush_tlb_all
++#define flush_tlb_mm		local_flush_tlb_mm
++#define flush_tlb_page		local_flush_tlb_page
++#define flush_tlb_kernel_page	local_flush_tlb_kernel_page
++#define flush_tlb_range		local_flush_tlb_range
++#define flush_tlb_kernel_range	local_flush_tlb_kernel_range
++
++/*
++ * if PG_dcache_clean is not set for the page, we need to ensure that any
++ * cache entries for the kernels virtual memory range are written
++ * back to the page.
++ */
++extern void update_mmu_cache(struct vm_area_struct *vma,
++		unsigned long addr, pte_t *ptep);
++
++extern void do_bad_area(unsigned long addr, unsigned int fsr,
++		struct pt_regs *regs);
++
++#endif
++
++#endif
+diff --git a/arch/unicore32/include/mach/dma.h b/arch/unicore32/include/mach/dma.h
+new file mode 100644
+index 000000000000..3e3224a10525
+--- /dev/null
++++ b/arch/unicore32/include/mach/dma.h
+@@ -0,0 +1,41 @@
++/*
++ * linux/arch/unicore32/include/mach/dma.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __MACH_PUV3_DMA_H__
++#define __MACH_PUV3_DMA_H__
++
++/*
++ * The PKUnity has six internal DMA channels.
++ */
++#define MAX_DMA_CHANNELS	6
++
++typedef enum {
++	DMA_PRIO_HIGH = 0,
++	DMA_PRIO_MEDIUM = 1,
++	DMA_PRIO_LOW = 2
++} puv3_dma_prio;
++
++/*
++ * DMA registration
++ */
++
++extern int puv3_request_dma(char *name,
++			 puv3_dma_prio prio,
++			 void (*irq_handler)(int, void *),
++			 void (*err_handler)(int, void *),
++			 void *data);
++
++extern void puv3_free_dma(int dma_ch);
++
++#define puv3_stop_dma(ch)		(DMAC_CONFIG(ch) &= ~DMAC_CONFIG_EN)
++#define puv3_resume_dma(ch)             (DMAC_CONFIG(ch) |= DMAC_CONFIG_EN)
++
++#endif /* __MACH_PUV3_DMA_H__ */
+diff --git a/arch/unicore32/kernel/dma.c b/arch/unicore32/kernel/dma.c
+new file mode 100644
+index 000000000000..b8dcc2514e9a
+--- /dev/null
++++ b/arch/unicore32/kernel/dma.c
+@@ -0,0 +1,180 @@
++/*
++ * linux/arch/unicore32/kernel/dma.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ *	Maintained by GUAN Xue-tao 
++ *	Copyright (C) 2001-2010 Guan Xuetao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++#include 
++#include 
++#include 
++
++struct dma_channel {
++	char *name;
++	puv3_dma_prio prio;
++	void (*irq_handler)(int, void *);
++	void (*err_handler)(int, void *);
++	void *data;
++};
++
++static struct dma_channel dma_channels[MAX_DMA_CHANNELS];
++
++int puv3_request_dma(char *name, puv3_dma_prio prio,
++			 void (*irq_handler)(int, void *),
++			 void (*err_handler)(int, void *),
++			 void *data)
++{
++	unsigned long flags;
++	int i, found = 0;
++
++	/* basic sanity checks */
++	if (!name)
++		return -EINVAL;
++
++	local_irq_save(flags);
++
++	do {
++		/* try grabbing a DMA channel with the requested priority */
++		for (i = 0; i < MAX_DMA_CHANNELS; i++) {
++			if ((dma_channels[i].prio == prio) &&
++			    !dma_channels[i].name) {
++				found = 1;
++				break;
++			}
++		}
++		/* if requested prio group is full, try a hier priority */
++	} while (!found && prio--);
++
++	if (found) {
++		dma_channels[i].name = name;
++		dma_channels[i].irq_handler = irq_handler;
++		dma_channels[i].err_handler = err_handler;
++		dma_channels[i].data = data;
++	} else {
++		printk(KERN_WARNING "No more available DMA channels for %s\n",
++				name);
++		i = -ENODEV;
++	}
++
++	local_irq_restore(flags);
++	return i;
++}
++EXPORT_SYMBOL(puv3_request_dma);
++
++void puv3_free_dma(int dma_ch)
++{
++	unsigned long flags;
++
++	if (!dma_channels[dma_ch].name) {
++		printk(KERN_CRIT
++			"%s: trying to free channel %d which is already freed\n",
++			__func__, dma_ch);
++		return;
++	}
++
++	local_irq_save(flags);
++	dma_channels[dma_ch].name = NULL;
++	dma_channels[dma_ch].err_handler = NULL;
++	local_irq_restore(flags);
++}
++EXPORT_SYMBOL(puv3_free_dma);
++
++static irqreturn_t dma_irq_handler(int irq, void *dev_id)
++{
++	int i, dint = DMAC_ITCSR;
++
++	for (i = 0; i < MAX_DMA_CHANNELS; i++) {
++		if (dint & DMAC_CHANNEL(i)) {
++			struct dma_channel *channel = &dma_channels[i];
++
++			/* Clear TC interrupt of channel i */
++			DMAC_ITCCR = DMAC_CHANNEL(i);
++			DMAC_ITCCR = 0;
++
++			if (channel->name && channel->irq_handler) {
++				channel->irq_handler(i, channel->data);
++			} else {
++				/*
++				 * IRQ for an unregistered DMA channel:
++				 * let's clear the interrupts and disable it.
++				 */
++				printk(KERN_WARNING "spurious IRQ for"
++						" DMA channel %d\n", i);
++			}
++		}
++	}
++	return IRQ_HANDLED;
++}
++
++static irqreturn_t dma_err_handler(int irq, void *dev_id)
++{
++	int i, dint = DMAC_IESR;
++
++	for (i = 0; i < MAX_DMA_CHANNELS; i++) {
++		if (dint & DMAC_CHANNEL(i)) {
++			struct dma_channel *channel = &dma_channels[i];
++
++			/* Clear Err interrupt of channel i */
++			DMAC_IECR = DMAC_CHANNEL(i);
++			DMAC_IECR = 0;
++
++			if (channel->name && channel->err_handler) {
++				channel->err_handler(i, channel->data);
++			} else {
++				/*
++				 * IRQ for an unregistered DMA channel:
++				 * let's clear the interrupts and disable it.
++				 */
++				printk(KERN_WARNING "spurious IRQ for"
++						" DMA channel %d\n", i);
++			}
++		}
++	}
++	return IRQ_HANDLED;
++}
++
++int __init puv3_init_dma(void)
++{
++	int i, ret;
++
++	/* dma channel priorities on v8 processors:
++	 * ch 0 - 1  <--> (0) DMA_PRIO_HIGH
++	 * ch 2 - 3  <--> (1) DMA_PRIO_MEDIUM
++	 * ch 4 - 5  <--> (2) DMA_PRIO_LOW
++	 */
++	for (i = 0; i < MAX_DMA_CHANNELS; i++) {
++		puv3_stop_dma(i);
++		dma_channels[i].name = NULL;
++		dma_channels[i].prio = min((i & 0x7) >> 1, DMA_PRIO_LOW);
++	}
++
++	ret = request_irq(IRQ_DMA, dma_irq_handler, 0, "DMA", NULL);
++	if (ret) {
++		printk(KERN_CRIT "Can't register IRQ for DMA\n");
++		return ret;
++	}
++
++	ret = request_irq(IRQ_DMAERR, dma_err_handler, 0, "DMAERR", NULL);
++	if (ret) {
++		printk(KERN_CRIT "Can't register IRQ for DMAERR\n");
++		free_irq(IRQ_DMA, "DMA");
++		return ret;
++	}
++
++	return 0;
++}
++
++postcore_initcall(puv3_init_dma);
+diff --git a/arch/unicore32/mm/cache-ucv2.S b/arch/unicore32/mm/cache-ucv2.S
+new file mode 100644
+index 000000000000..ecaa1727f906
+--- /dev/null
++++ b/arch/unicore32/mm/cache-ucv2.S
+@@ -0,0 +1,212 @@
++/*
++ * linux/arch/unicore32/mm/cache-ucv2.S
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ *  This is the "shell" of the UniCore-v2 processor support.
++ */
++#include 
++#include 
++#include 
++#include 
++
++#include "proc-macros.S"
++
++/*
++ *	__cpuc_flush_icache_all()
++ *	__cpuc_flush_kern_all()
++ *	__cpuc_flush_user_all()
++ *
++ *	Flush the entire cache.
++ */
++ENTRY(__cpuc_flush_icache_all)
++	/*FALLTHROUGH*/
++ENTRY(__cpuc_flush_kern_all)
++	/*FALLTHROUGH*/
++ENTRY(__cpuc_flush_user_all)
++	mov	r0, #0
++	movc	p0.c5, r0, #14			@ Dcache flush all
++	nop8
++
++	mov	r0, #0
++	movc	p0.c5, r0, #20			@ Icache invalidate all
++	nop8
++
++	mov	pc, lr
++
++/*
++ *	__cpuc_flush_user_range(start, end, flags)
++ *
++ *	Flush a range of TLB entries in the specified address space.
++ *
++ *	- start - start address (may not be aligned)
++ *	- end   - end address (exclusive, may not be aligned)
++ *	- flags	- vm_area_struct flags describing address space
++ */
++ENTRY(__cpuc_flush_user_range)
++	cxor.a	r2, #0
++	beq	__cpuc_dma_flush_range
++
++#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
++	andn	r0, r0, #CACHE_LINESIZE - 1	@ Safety check
++	sub	r1, r1, r0
++	csub.a	r1, #MAX_AREA_SIZE
++	bsg	2f
++
++	andn	r1, r1, #CACHE_LINESIZE - 1
++	add	r1, r1, #CACHE_LINESIZE
++
++101:	dcacheline_flush	r0, r11, r12
++
++	add	r0, r0, #CACHE_LINESIZE
++	sub.a	r1, r1, #CACHE_LINESIZE
++	bns	101b
++	b	3f
++#endif
++2:	mov	ip, #0
++	movc	p0.c5, ip, #14			@ Dcache flush all
++	nop8
++
++3:	mov	ip, #0
++	movc	p0.c5, ip, #20			@ Icache invalidate all
++	nop8
++
++	mov	pc, lr
++
++/*
++ *	__cpuc_coherent_kern_range(start,end)
++ *	__cpuc_coherent_user_range(start,end)
++ *
++ *	Ensure that the I and D caches are coherent within specified
++ *	region.  This is typically used when code has been written to
++ *	a memory region, and will be executed.
++ *
++ *	- start   - virtual start address of region
++ *	- end     - virtual end address of region
++ */
++ENTRY(__cpuc_coherent_kern_range)
++	/* FALLTHROUGH */
++ENTRY(__cpuc_coherent_user_range)
++#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
++	andn	r0, r0, #CACHE_LINESIZE - 1	@ Safety check
++	sub	r1, r1, r0
++	csub.a	r1, #MAX_AREA_SIZE
++	bsg	2f
++
++	andn	r1, r1, #CACHE_LINESIZE - 1
++	add	r1, r1, #CACHE_LINESIZE
++
++	@ r0 va2pa r10
++	mov	r9, #PAGE_SZ
++	sub	r9, r9, #1			@ PAGE_MASK
++101:	va2pa	r0, r10, r11, r12, r13, 2f	@ r10 is PA
++	b	103f
++102:	cand.a	r0, r9
++	beq	101b
++
++103:	movc	p0.c5, r10, #11			@ Dcache clean line of R10
++	nop8
++
++	add	r0, r0, #CACHE_LINESIZE
++	add	r10, r10, #CACHE_LINESIZE
++	sub.a	r1, r1, #CACHE_LINESIZE
++	bns	102b
++	b	3f
++#endif
++2:	mov	ip, #0
++	movc	p0.c5, ip, #10			@ Dcache clean all
++	nop8
++
++3:	mov	ip, #0
++	movc	p0.c5, ip, #20			@ Icache invalidate all
++	nop8
++
++	mov	pc, lr
++
++/*
++ *	__cpuc_flush_kern_dcache_area(void *addr, size_t size)
++ *
++ *	- addr	- kernel address
++ *	- size	- region size
++ */
++ENTRY(__cpuc_flush_kern_dcache_area)
++	mov	ip, #0
++	movc	p0.c5, ip, #14			@ Dcache flush all
++	nop8
++	mov	pc, lr
++
++/*
++ *	__cpuc_dma_clean_range(start,end)
++ *	- start   - virtual start address of region
++ *	- end     - virtual end address of region
++ */
++ENTRY(__cpuc_dma_clean_range)
++#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
++	andn	r0, r0, #CACHE_LINESIZE - 1
++	sub	r1, r1, r0
++	andn	r1, r1, #CACHE_LINESIZE - 1
++	add	r1, r1, #CACHE_LINESIZE
++
++	csub.a	r1, #MAX_AREA_SIZE
++	bsg	2f
++
++	@ r0 va2pa r10
++	mov	r9, #PAGE_SZ
++	sub	r9, r9, #1			@ PAGE_MASK
++101:	va2pa	r0, r10, r11, r12, r13, 2f	@ r10 is PA
++	b	1f
++102:	cand.a	r0, r9
++	beq	101b
++
++1:	movc	p0.c5, r10, #11			@ Dcache clean line of R10
++	nop8
++	add	r0, r0, #CACHE_LINESIZE
++	add	r10, r10, #CACHE_LINESIZE
++	sub.a	r1, r1, #CACHE_LINESIZE
++	bns	102b
++	mov	pc, lr
++#endif
++2:	mov	ip, #0
++	movc	p0.c5, ip, #10			@ Dcache clean all
++	nop8
++
++	mov	pc, lr
++
++/*
++ *	__cpuc_dma_inv_range(start,end)
++ *	__cpuc_dma_flush_range(start,end)
++ *	- start   - virtual start address of region
++ *	- end     - virtual end address of region
++ */
++__cpuc_dma_inv_range:
++	/* FALLTHROUGH */
++ENTRY(__cpuc_dma_flush_range)
++#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
++	andn	r0, r0, #CACHE_LINESIZE - 1
++	sub	r1, r1, r0
++	andn	r1, r1, #CACHE_LINESIZE - 1
++	add	r1, r1, #CACHE_LINESIZE
++
++	csub.a	r1, #MAX_AREA_SIZE
++	bsg	2f
++
++	@ r0 va2pa r10
++101:	dcacheline_flush	r0, r11, r12
++
++	add	r0, r0, #CACHE_LINESIZE
++	sub.a	r1, r1, #CACHE_LINESIZE
++	bns	101b
++	mov	pc, lr
++#endif
++2:	mov	ip, #0
++	movc	p0.c5, ip, #14			@ Dcache flush all
++	nop8
++
++	mov	pc, lr
++
+diff --git a/arch/unicore32/mm/dma-swiotlb.c b/arch/unicore32/mm/dma-swiotlb.c
+new file mode 100644
+index 000000000000..bfa9fbb2bbb1
+--- /dev/null
++++ b/arch/unicore32/mm/dma-swiotlb.c
+@@ -0,0 +1,34 @@
++/*
++ * Contains routines needed to support swiotlb for UniCore32.
++ *
++ * Copyright (C) 2010 Guan Xuetao
++ *
++ * This program is free software; you can redistribute  it and/or modify it
++ * under  the terms of  the GNU General  Public License as published by the
++ * Free Software Foundation;  either version 2 of the  License, or (at your
++ * option) any later version.
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++
++struct dma_map_ops swiotlb_dma_map_ops = {
++	.alloc_coherent = swiotlb_alloc_coherent,
++	.free_coherent = swiotlb_free_coherent,
++	.map_sg = swiotlb_map_sg_attrs,
++	.unmap_sg = swiotlb_unmap_sg_attrs,
++	.dma_supported = swiotlb_dma_supported,
++	.map_page = swiotlb_map_page,
++	.unmap_page = swiotlb_unmap_page,
++	.sync_single_for_cpu = swiotlb_sync_single_for_cpu,
++	.sync_single_for_device = swiotlb_sync_single_for_device,
++	.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
++	.sync_sg_for_device = swiotlb_sync_sg_for_device,
++	.mapping_error = swiotlb_dma_mapping_error,
++};
++EXPORT_SYMBOL(swiotlb_dma_map_ops);
+diff --git a/arch/unicore32/mm/flush.c b/arch/unicore32/mm/flush.c
+new file mode 100644
+index 000000000000..93478cc8b26d
+--- /dev/null
++++ b/arch/unicore32/mm/flush.c
+@@ -0,0 +1,98 @@
++/*
++ * linux/arch/unicore32/mm/flush.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++
++#include 
++#include 
++#include 
++
++void flush_cache_mm(struct mm_struct *mm)
++{
++}
++
++void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
++		unsigned long end)
++{
++	if (vma->vm_flags & VM_EXEC)
++		__flush_icache_all();
++}
++
++void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr,
++		unsigned long pfn)
++{
++}
++
++static void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
++			 unsigned long uaddr, void *kaddr, unsigned long len)
++{
++	/* VIPT non-aliasing D-cache */
++	if (vma->vm_flags & VM_EXEC) {
++		unsigned long addr = (unsigned long)kaddr;
++
++		__cpuc_coherent_kern_range(addr, addr + len);
++	}
++}
++
++/*
++ * Copy user data from/to a page which is mapped into a different
++ * processes address space.  Really, we want to allow our "user
++ * space" model to handle this.
++ *
++ * Note that this code needs to run on the current CPU.
++ */
++void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
++		       unsigned long uaddr, void *dst, const void *src,
++		       unsigned long len)
++{
++	memcpy(dst, src, len);
++	flush_ptrace_access(vma, page, uaddr, dst, len);
++}
++
++void __flush_dcache_page(struct address_space *mapping, struct page *page)
++{
++	/*
++	 * Writeback any data associated with the kernel mapping of this
++	 * page.  This ensures that data in the physical page is mutually
++	 * coherent with the kernels mapping.
++	 */
++	__cpuc_flush_kern_dcache_area(page_address(page), PAGE_SIZE);
++}
++
++/*
++ * Ensure cache coherency between kernel mapping and userspace mapping
++ * of this page.
++ */
++void flush_dcache_page(struct page *page)
++{
++	struct address_space *mapping;
++
++	/*
++	 * The zero page is never written to, so never has any dirty
++	 * cache lines, and therefore never needs to be flushed.
++	 */
++	if (page == ZERO_PAGE(0))
++		return;
++
++	mapping = page_mapping(page);
++
++	if (mapping && !mapping_mapped(mapping))
++		clear_bit(PG_dcache_clean, &page->flags);
++	else {
++		__flush_dcache_page(mapping, page);
++		if (mapping)
++			__flush_icache_all();
++		set_bit(PG_dcache_clean, &page->flags);
++	}
++}
++EXPORT_SYMBOL(flush_dcache_page);
+diff --git a/arch/unicore32/mm/tlb-ucv2.S b/arch/unicore32/mm/tlb-ucv2.S
+new file mode 100644
+index 000000000000..061d455f9a15
+--- /dev/null
++++ b/arch/unicore32/mm/tlb-ucv2.S
+@@ -0,0 +1,89 @@
++/*
++ * linux/arch/unicore32/mm/tlb-ucv2.S
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++#include "proc-macros.S"
++
++/*
++ *	__cpu_flush_user_tlb_range(start, end, vma)
++ *
++ *	Invalidate a range of TLB entries in the specified address space.
++ *
++ *	- start - start address (may not be aligned)
++ *	- end   - end address (exclusive, may not be aligned)
++ *	- vma   - vma_struct describing address range
++ */
++ENTRY(__cpu_flush_user_tlb_range)
++#ifndef	CONFIG_CPU_TLB_SINGLE_ENTRY_DISABLE
++	mov	r0, r0 >> #PAGE_SHIFT		@ align address
++	mov	r0, r0 << #PAGE_SHIFT
++	vma_vm_flags r2, r2			@ get vma->vm_flags
++1:
++	movc	p0.c6, r0, #3
++	nop8
++
++	cand.a	r2, #VM_EXEC			@ Executable area ?
++	beq	2f
++
++	movc	p0.c6, r0, #5
++	nop8
++2:
++	add	r0, r0, #PAGE_SZ
++	csub.a	r0, r1
++	beb	1b
++#else
++	movc	p0.c6, r0, #2
++	nop8
++
++	cand.a	r2, #VM_EXEC			@ Executable area ?
++	beq	2f
++
++	movc	p0.c6, r0, #4
++	nop8
++2:
++#endif
++	mov	pc, lr
++
++/*
++ *	__cpu_flush_kern_tlb_range(start,end)
++ *
++ *	Invalidate a range of kernel TLB entries
++ *
++ *	- start - start address (may not be aligned)
++ *	- end   - end address (exclusive, may not be aligned)
++ */
++ENTRY(__cpu_flush_kern_tlb_range)
++#ifndef	CONFIG_CPU_TLB_SINGLE_ENTRY_DISABLE
++	mov	r0, r0 >> #PAGE_SHIFT		@ align address
++	mov	r0, r0 << #PAGE_SHIFT
++1:
++	movc	p0.c6, r0, #3
++	nop8
++
++	movc	p0.c6, r0, #5
++	nop8
++
++	add	r0, r0, #PAGE_SZ
++	csub.a	r0, r1
++	beb	1b
++#else
++	movc	p0.c6, r0, #2
++	nop8
++
++	movc	p0.c6, r0, #4
++	nop8
++#endif
++	mov	pc, lr
++

commit 56372b0b2f533c9a25bd40a0577405f6ddb7cff2
+Author: GuanXuetao 
+Date:   Sat Jan 15 18:17:56 2011 +0800
+
+    unicore32 core architecture: mm related: fault handling
+    
+    This patch implements fault handling of memory management.
+    
+    Signed-off-by: Guan Xuetao 
+    Reviewed-by: Arnd Bergmann 
+
+diff --git a/arch/unicore32/include/asm/mmu.h b/arch/unicore32/include/asm/mmu.h
+new file mode 100644
+index 000000000000..66fa341dc2c6
+--- /dev/null
++++ b/arch/unicore32/include/asm/mmu.h
+@@ -0,0 +1,17 @@
++/*
++ * linux/arch/unicore32/include/asm/mmu.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_MMU_H__
++#define __UNICORE_MMU_H__
++
++typedef	unsigned long mm_context_t;
++
++#endif
+diff --git a/arch/unicore32/include/asm/mmu_context.h b/arch/unicore32/include/asm/mmu_context.h
+new file mode 100644
+index 000000000000..fb5e4c658f7a
+--- /dev/null
++++ b/arch/unicore32/include/asm/mmu_context.h
+@@ -0,0 +1,87 @@
++/*
++ * linux/arch/unicore32/include/asm/mmu_context.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_MMU_CONTEXT_H__
++#define __UNICORE_MMU_CONTEXT_H__
++
++#include 
++#include 
++#include 
++
++#include 
++#include 
++
++#define init_new_context(tsk, mm)	0
++
++#define destroy_context(mm)		do { } while (0)
++
++/*
++ * This is called when "tsk" is about to enter lazy TLB mode.
++ *
++ * mm:  describes the currently active mm context
++ * tsk: task which is entering lazy tlb
++ * cpu: cpu number which is entering lazy tlb
++ *
++ * tsk->mm will be NULL
++ */
++static inline void
++enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
++{
++}
++
++/*
++ * This is the actual mm switch as far as the scheduler
++ * is concerned.  No registers are touched.  We avoid
++ * calling the CPU specific function when the mm hasn't
++ * actually changed.
++ */
++static inline void
++switch_mm(struct mm_struct *prev, struct mm_struct *next,
++	  struct task_struct *tsk)
++{
++	unsigned int cpu = smp_processor_id();
++
++	if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)) || prev != next)
++		cpu_switch_mm(next->pgd, next);
++}
++
++#define deactivate_mm(tsk, mm)	do { } while (0)
++#define activate_mm(prev, next)	switch_mm(prev, next, NULL)
++
++/*
++ * We are inserting a "fake" vma for the user-accessible vector page so
++ * gdb and friends can get to it through ptrace and /proc//mem.
++ * But we also want to remove it before the generic code gets to see it
++ * during process exit or the unmapping of it would  cause total havoc.
++ * (the macro is used as remove_vma() is static to mm/mmap.c)
++ */
++#define arch_exit_mmap(mm) \
++do { \
++	struct vm_area_struct *high_vma = find_vma(mm, 0xffff0000); \
++	if (high_vma) { \
++		BUG_ON(high_vma->vm_next);  /* it should be last */ \
++		if (high_vma->vm_prev) \
++			high_vma->vm_prev->vm_next = NULL; \
++		else \
++			mm->mmap = NULL; \
++		rb_erase(&high_vma->vm_rb, &mm->mm_rb); \
++		mm->mmap_cache = NULL; \
++		mm->map_count--; \
++		remove_vma(high_vma); \
++	} \
++} while (0)
++
++static inline void arch_dup_mmap(struct mm_struct *oldmm,
++				 struct mm_struct *mm)
++{
++}
++
++#endif
+diff --git a/arch/unicore32/include/asm/pgalloc.h b/arch/unicore32/include/asm/pgalloc.h
+new file mode 100644
+index 000000000000..0213e373a895
+--- /dev/null
++++ b/arch/unicore32/include/asm/pgalloc.h
+@@ -0,0 +1,110 @@
++/*
++ * linux/arch/unicore32/include/asm/pgalloc.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_PGALLOC_H__
++#define __UNICORE_PGALLOC_H__
++
++#include 
++#include 
++#include 
++#include 
++
++#define check_pgt_cache()		do { } while (0)
++
++#define _PAGE_USER_TABLE	(PMD_TYPE_TABLE | PMD_PRESENT)
++#define _PAGE_KERNEL_TABLE	(PMD_TYPE_TABLE | PMD_PRESENT)
++
++extern pgd_t *get_pgd_slow(struct mm_struct *mm);
++extern void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd);
++
++#define pgd_alloc(mm)			get_pgd_slow(mm)
++#define pgd_free(mm, pgd)		free_pgd_slow(mm, pgd)
++
++#define PGALLOC_GFP	(GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO)
++
++/*
++ * Allocate one PTE table.
++ */
++static inline pte_t *
++pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr)
++{
++	pte_t *pte;
++
++	pte = (pte_t *)__get_free_page(PGALLOC_GFP);
++	if (pte)
++		clean_dcache_area(pte, PTRS_PER_PTE * sizeof(pte_t));
++
++	return pte;
++}
++
++static inline pgtable_t
++pte_alloc_one(struct mm_struct *mm, unsigned long addr)
++{
++	struct page *pte;
++
++	pte = alloc_pages(PGALLOC_GFP, 0);
++	if (pte) {
++		if (!PageHighMem(pte)) {
++			void *page = page_address(pte);
++			clean_dcache_area(page, PTRS_PER_PTE * sizeof(pte_t));
++		}
++		pgtable_page_ctor(pte);
++	}
++
++	return pte;
++}
++
++/*
++ * Free one PTE table.
++ */
++static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
++{
++	if (pte)
++		free_page((unsigned long)pte);
++}
++
++static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
++{
++	pgtable_page_dtor(pte);
++	__free_page(pte);
++}
++
++static inline void __pmd_populate(pmd_t *pmdp, unsigned long pmdval)
++{
++	set_pmd(pmdp, __pmd(pmdval));
++	flush_pmd_entry(pmdp);
++}
++
++/*
++ * Populate the pmdp entry with a pointer to the pte.  This pmd is part
++ * of the mm address space.
++ */
++static inline void
++pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep)
++{
++	unsigned long pte_ptr = (unsigned long)ptep;
++
++	/*
++	 * The pmd must be loaded with the physical
++	 * address of the PTE table
++	 */
++	__pmd_populate(pmdp, __pa(pte_ptr) | _PAGE_KERNEL_TABLE);
++}
++
++static inline void
++pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep)
++{
++	__pmd_populate(pmdp,
++			page_to_pfn(ptep) << PAGE_SHIFT | _PAGE_USER_TABLE);
++}
++#define pmd_pgtable(pmd) pmd_page(pmd)
++
++#endif
+diff --git a/arch/unicore32/include/asm/pgtable-hwdef.h b/arch/unicore32/include/asm/pgtable-hwdef.h
+new file mode 100644
+index 000000000000..7314e859cca0
+--- /dev/null
++++ b/arch/unicore32/include/asm/pgtable-hwdef.h
+@@ -0,0 +1,55 @@
++/*
++ * linux/arch/unicore32/include/asm/pgtable-hwdef.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_PGTABLE_HWDEF_H__
++#define __UNICORE_PGTABLE_HWDEF_H__
++
++/*
++ * Hardware page table definitions.
++ *
++ * + Level 1 descriptor (PMD)
++ *   - common
++ */
++#define PMD_TYPE_MASK		(3 << 0)
++#define PMD_TYPE_TABLE		(0 << 0)
++/*#define PMD_TYPE_LARGE	(1 << 0) */
++#define PMD_TYPE_INVALID	(2 << 0)
++#define PMD_TYPE_SECT		(3 << 0)
++
++#define PMD_PRESENT		(1 << 2)
++#define PMD_YOUNG		(1 << 3)
++
++/*#define PMD_SECT_DIRTY	(1 << 4) */
++#define PMD_SECT_CACHEABLE	(1 << 5)
++#define PMD_SECT_EXEC		(1 << 6)
++#define PMD_SECT_WRITE		(1 << 7)
++#define PMD_SECT_READ		(1 << 8)
++
++/*
++ * + Level 2 descriptor (PTE)
++ *   - common
++ */
++#define PTE_TYPE_MASK		(3 << 0)
++#define PTE_TYPE_SMALL		(0 << 0)
++#define PTE_TYPE_MIDDLE		(1 << 0)
++#define PTE_TYPE_LARGE		(2 << 0)
++#define PTE_TYPE_INVALID	(3 << 0)
++
++#define PTE_PRESENT		(1 << 2)
++#define PTE_FILE		(1 << 3)	/* only when !PRESENT */
++#define PTE_YOUNG		(1 << 3)
++#define PTE_DIRTY		(1 << 4)
++#define PTE_CACHEABLE		(1 << 5)
++#define PTE_EXEC		(1 << 6)
++#define PTE_WRITE		(1 << 7)
++#define PTE_READ		(1 << 8)
++
++#endif
+diff --git a/arch/unicore32/include/asm/pgtable.h b/arch/unicore32/include/asm/pgtable.h
+new file mode 100644
+index 000000000000..68b2f297ac97
+--- /dev/null
++++ b/arch/unicore32/include/asm/pgtable.h
+@@ -0,0 +1,317 @@
++/*
++ * linux/arch/unicore32/include/asm/pgtable.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_PGTABLE_H__
++#define __UNICORE_PGTABLE_H__
++
++#include 
++#include 
++
++#include 
++#include 
++
++/*
++ * Just any arbitrary offset to the start of the vmalloc VM area: the
++ * current 8MB value just means that there will be a 8MB "hole" after the
++ * physical memory until the kernel virtual memory starts.  That means that
++ * any out-of-bounds memory accesses will hopefully be caught.
++ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
++ * area for the same reason. ;)
++ *
++ * Note that platforms may override VMALLOC_START, but they must provide
++ * VMALLOC_END.  VMALLOC_END defines the (exclusive) limit of this space,
++ * which may not overlap IO space.
++ */
++#ifndef VMALLOC_START
++#define VMALLOC_OFFSET		SZ_8M
++#define VMALLOC_START		(((unsigned long)high_memory + VMALLOC_OFFSET) \
++					& ~(VMALLOC_OFFSET-1))
++#define VMALLOC_END		(0xff000000UL)
++#endif
++
++#define PTRS_PER_PTE		1024
++#define PTRS_PER_PGD		1024
++
++/*
++ * PGDIR_SHIFT determines what a third-level page table entry can map
++ */
++#define PGDIR_SHIFT		22
++
++#ifndef __ASSEMBLY__
++extern void __pte_error(const char *file, int line, unsigned long val);
++extern void __pgd_error(const char *file, int line, unsigned long val);
++
++#define pte_ERROR(pte)		__pte_error(__FILE__, __LINE__, pte_val(pte))
++#define pgd_ERROR(pgd)		__pgd_error(__FILE__, __LINE__, pgd_val(pgd))
++#endif /* !__ASSEMBLY__ */
++
++#define PGDIR_SIZE		(1UL << PGDIR_SHIFT)
++#define PGDIR_MASK		(~(PGDIR_SIZE-1))
++
++/*
++ * This is the lowest virtual address we can permit any user space
++ * mapping to be mapped at.  This is particularly important for
++ * non-high vector CPUs.
++ */
++#define FIRST_USER_ADDRESS	PAGE_SIZE
++
++#define FIRST_USER_PGD_NR	1
++#define USER_PTRS_PER_PGD	((TASK_SIZE/PGDIR_SIZE) - FIRST_USER_PGD_NR)
++
++/*
++ * section address mask and size definitions.
++ */
++#define SECTION_SHIFT		22
++#define SECTION_SIZE		(1UL << SECTION_SHIFT)
++#define SECTION_MASK		(~(SECTION_SIZE-1))
++
++#ifndef __ASSEMBLY__
++
++/*
++ * The pgprot_* and protection_map entries will be fixed up in runtime
++ * to include the cachable bits based on memory policy, as well as any
++ * architecture dependent bits.
++ */
++#define _PTE_DEFAULT		(PTE_PRESENT | PTE_YOUNG | PTE_CACHEABLE)
++
++extern pgprot_t pgprot_user;
++extern pgprot_t pgprot_kernel;
++
++#define PAGE_NONE		pgprot_user
++#define PAGE_SHARED		__pgprot(pgprot_val(pgprot_user | PTE_READ \
++								| PTE_WRITE)
++#define PAGE_SHARED_EXEC	__pgprot(pgprot_val(pgprot_user | PTE_READ \
++								| PTE_WRITE \
++								| PTE_EXEC)
++#define PAGE_COPY		__pgprot(pgprot_val(pgprot_user | PTE_READ)
++#define PAGE_COPY_EXEC		__pgprot(pgprot_val(pgprot_user | PTE_READ \
++								| PTE_EXEC)
++#define PAGE_READONLY		__pgprot(pgprot_val(pgprot_user | PTE_READ)
++#define PAGE_READONLY_EXEC	__pgprot(pgprot_val(pgprot_user | PTE_READ \
++								| PTE_EXEC)
++#define PAGE_KERNEL		pgprot_kernel
++#define PAGE_KERNEL_EXEC	__pgprot(pgprot_val(pgprot_kernel | PTE_EXEC))
++
++#define __PAGE_NONE		__pgprot(_PTE_DEFAULT)
++#define __PAGE_SHARED		__pgprot(_PTE_DEFAULT | PTE_READ \
++							| PTE_WRITE)
++#define __PAGE_SHARED_EXEC	__pgprot(_PTE_DEFAULT | PTE_READ \
++							| PTE_WRITE \
++							| PTE_EXEC)
++#define __PAGE_COPY		__pgprot(_PTE_DEFAULT | PTE_READ)
++#define __PAGE_COPY_EXEC	__pgprot(_PTE_DEFAULT | PTE_READ \
++							| PTE_EXEC)
++#define __PAGE_READONLY		__pgprot(_PTE_DEFAULT | PTE_READ)
++#define __PAGE_READONLY_EXEC	__pgprot(_PTE_DEFAULT | PTE_READ \
++							| PTE_EXEC)
++
++#endif /* __ASSEMBLY__ */
++
++/*
++ * The table below defines the page protection levels that we insert into our
++ * Linux page table version.  These get translated into the best that the
++ * architecture can perform.  Note that on UniCore hardware:
++ *  1) We cannot do execute protection
++ *  2) If we could do execute protection, then read is implied
++ *  3) write implies read permissions
++ */
++#define __P000  __PAGE_NONE
++#define __P001  __PAGE_READONLY
++#define __P010  __PAGE_COPY
++#define __P011  __PAGE_COPY
++#define __P100  __PAGE_READONLY_EXEC
++#define __P101  __PAGE_READONLY_EXEC
++#define __P110  __PAGE_COPY_EXEC
++#define __P111  __PAGE_COPY_EXEC
++
++#define __S000  __PAGE_NONE
++#define __S001  __PAGE_READONLY
++#define __S010  __PAGE_SHARED
++#define __S011  __PAGE_SHARED
++#define __S100  __PAGE_READONLY_EXEC
++#define __S101  __PAGE_READONLY_EXEC
++#define __S110  __PAGE_SHARED_EXEC
++#define __S111  __PAGE_SHARED_EXEC
++
++#ifndef __ASSEMBLY__
++/*
++ * ZERO_PAGE is a global shared page that is always zero: used
++ * for zero-mapped memory areas etc..
++ */
++extern struct page *empty_zero_page;
++#define ZERO_PAGE(vaddr)		(empty_zero_page)
++
++#define pte_pfn(pte)			(pte_val(pte) >> PAGE_SHIFT)
++#define pfn_pte(pfn, prot)		(__pte(((pfn) << PAGE_SHIFT) \
++						| pgprot_val(prot)))
++
++#define pte_none(pte)			(!pte_val(pte))
++#define pte_clear(mm, addr, ptep)	set_pte(ptep, __pte(0))
++#define pte_page(pte)			(pfn_to_page(pte_pfn(pte)))
++#define pte_offset_kernel(dir, addr)	(pmd_page_vaddr(*(dir)) \
++						+ __pte_index(addr))
++
++#define pte_offset_map(dir, addr)	(pmd_page_vaddr(*(dir)) \
++						+ __pte_index(addr))
++#define pte_unmap(pte)			do { } while (0)
++
++#define set_pte(ptep, pte)	cpu_set_pte(ptep, pte)
++
++#define set_pte_at(mm, addr, ptep, pteval)	\
++	do {					\
++		set_pte(ptep, pteval);          \
++	} while (0)
++
++/*
++ * The following only work if pte_present() is true.
++ * Undefined behaviour if not..
++ */
++#define pte_present(pte)	(pte_val(pte) & PTE_PRESENT)
++#define pte_write(pte)		(pte_val(pte) & PTE_WRITE)
++#define pte_dirty(pte)		(pte_val(pte) & PTE_DIRTY)
++#define pte_young(pte)		(pte_val(pte) & PTE_YOUNG)
++#define pte_exec(pte)		(pte_val(pte) & PTE_EXEC)
++#define pte_special(pte)	(0)
++
++#define PTE_BIT_FUNC(fn, op) \
++static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
++
++PTE_BIT_FUNC(wrprotect, &= ~PTE_WRITE);
++PTE_BIT_FUNC(mkwrite,   |= PTE_WRITE);
++PTE_BIT_FUNC(mkclean,   &= ~PTE_DIRTY);
++PTE_BIT_FUNC(mkdirty,   |= PTE_DIRTY);
++PTE_BIT_FUNC(mkold,     &= ~PTE_YOUNG);
++PTE_BIT_FUNC(mkyoung,   |= PTE_YOUNG);
++
++static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
++
++/*
++ * Mark the prot value as uncacheable.
++ */
++#define pgprot_noncached(prot)		\
++	__pgprot(pgprot_val(prot) & ~PTE_CACHEABLE)
++#define pgprot_writecombine(prot)	\
++	__pgprot(pgprot_val(prot) & ~PTE_CACHEABLE)
++#define pgprot_dmacoherent(prot)	\
++	__pgprot(pgprot_val(prot) & ~PTE_CACHEABLE)
++
++#define pmd_none(pmd)		(!pmd_val(pmd))
++#define pmd_present(pmd)	(pmd_val(pmd) & PMD_PRESENT)
++#define pmd_bad(pmd)		(((pmd_val(pmd) &		\
++				(PMD_PRESENT | PMD_TYPE_MASK))	\
++				!= (PMD_PRESENT | PMD_TYPE_TABLE)))
++
++#define set_pmd(pmdpd, pmdval)		\
++	do {				\
++		*(pmdpd) = pmdval;	\
++	} while (0)
++
++#define pmd_clear(pmdp)			\
++	do {				\
++		set_pmd(pmdp, __pmd(0));\
++		clean_pmd_entry(pmdp);	\
++	} while (0)
++
++#define pmd_page_vaddr(pmd) ((pte_t *)__va(pmd_val(pmd) & PAGE_MASK))
++#define pmd_page(pmd)		pfn_to_page(__phys_to_pfn(pmd_val(pmd)))
++
++/*
++ * Conversion functions: convert a page and protection to a page entry,
++ * and a page entry and page directory to the page they refer to.
++ */
++#define mk_pte(page, prot)	pfn_pte(page_to_pfn(page), prot)
++
++/* to find an entry in a page-table-directory */
++#define pgd_index(addr)		((addr) >> PGDIR_SHIFT)
++
++#define pgd_offset(mm, addr)	((mm)->pgd+pgd_index(addr))
++
++/* to find an entry in a kernel page-table-directory */
++#define pgd_offset_k(addr)	pgd_offset(&init_mm, addr)
++
++/* Find an entry in the third-level page table.. */
++#define __pte_index(addr)	(((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
++
++static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
++{
++	const unsigned long mask = PTE_EXEC | PTE_WRITE | PTE_READ;
++	pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
++	return pte;
++}
++
++extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
++
++/*
++ * Encode and decode a swap entry.  Swap entries are stored in the Linux
++ * page tables as follows:
++ *
++ *   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
++ *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
++ *   <--------------- offset --------------> <--- type --> 0 0 0 0 0
++ *
++ * This gives us up to 127 swap files and 32GB per swap file.  Note that
++ * the offset field is always non-zero.
++ */
++#define __SWP_TYPE_SHIFT	5
++#define __SWP_TYPE_BITS		7
++#define __SWP_TYPE_MASK		((1 << __SWP_TYPE_BITS) - 1)
++#define __SWP_OFFSET_SHIFT	(__SWP_TYPE_BITS + __SWP_TYPE_SHIFT)
++
++#define __swp_type(x)		(((x).val >> __SWP_TYPE_SHIFT)		\
++				& __SWP_TYPE_MASK)
++#define __swp_offset(x)		((x).val >> __SWP_OFFSET_SHIFT)
++#define __swp_entry(type, offset) ((swp_entry_t) {			\
++				((type) << __SWP_TYPE_SHIFT) |		\
++				((offset) << __SWP_OFFSET_SHIFT) })
++
++#define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
++#define __swp_entry_to_pte(swp)	((pte_t) { (swp).val })
++
++/*
++ * It is an error for the kernel to have more swap files than we can
++ * encode in the PTEs.  This ensures that we know when MAX_SWAPFILES
++ * is increased beyond what we presently support.
++ */
++#define MAX_SWAPFILES_CHECK()	\
++	BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > __SWP_TYPE_BITS)
++
++/*
++ * Encode and decode a file entry.  File entries are stored in the Linux
++ * page tables as follows:
++ *
++ *   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
++ *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
++ *   <----------------------- offset ----------------------> 1 0 0 0
++ */
++#define pte_file(pte)		(pte_val(pte) & PTE_FILE)
++#define pte_to_pgoff(x)		(pte_val(x) >> 4)
++#define pgoff_to_pte(x)		__pte(((x) << 4) | PTE_FILE)
++
++#define PTE_FILE_MAX_BITS	28
++
++/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
++/* FIXME: this is not correct */
++#define kern_addr_valid(addr)	(1)
++
++#include 
++
++/*
++ * remap a physical page `pfn' of size `size' with page protection `prot'
++ * into virtual address `from'
++ */
++#define io_remap_pfn_range(vma, from, pfn, size, prot)	\
++		remap_pfn_range(vma, from, pfn, size, prot)
++
++#define pgtable_cache_init() do { } while (0)
++
++#endif /* !__ASSEMBLY__ */
++
++#endif /* __UNICORE_PGTABLE_H__ */
+diff --git a/arch/unicore32/mm/alignment.c b/arch/unicore32/mm/alignment.c
+new file mode 100644
+index 000000000000..28f576d733ee
+--- /dev/null
++++ b/arch/unicore32/mm/alignment.c
+@@ -0,0 +1,523 @@
++/*
++ * linux/arch/unicore32/mm/alignment.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++/*
++ * TODO:
++ *  FPU ldm/stm not handling
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++#include 
++
++#define CODING_BITS(i)	(i & 0xe0000120)
++
++#define LDST_P_BIT(i)	(i & (1 << 28))	/* Preindex             */
++#define LDST_U_BIT(i)	(i & (1 << 27))	/* Add offset           */
++#define LDST_W_BIT(i)	(i & (1 << 25))	/* Writeback            */
++#define LDST_L_BIT(i)	(i & (1 << 24))	/* Load                 */
++
++#define LDST_P_EQ_U(i)	((((i) ^ ((i) >> 1)) & (1 << 27)) == 0)
++
++#define LDSTH_I_BIT(i)	(i & (1 << 26))	/* half-word immed      */
++#define LDM_S_BIT(i)	(i & (1 << 26))	/* write ASR from BSR */
++#define LDM_H_BIT(i)	(i & (1 << 6))	/* select r0-r15 or r16-r31 */
++
++#define RN_BITS(i)	((i >> 19) & 31)	/* Rn                   */
++#define RD_BITS(i)	((i >> 14) & 31)	/* Rd                   */
++#define RM_BITS(i)	(i & 31)	/* Rm                   */
++
++#define REGMASK_BITS(i)	(((i & 0x7fe00) >> 3) | (i & 0x3f))
++#define OFFSET_BITS(i)	(i & 0x03fff)
++
++#define SHIFT_BITS(i)	((i >> 9) & 0x1f)
++#define SHIFT_TYPE(i)	(i & 0xc0)
++#define SHIFT_LSL	0x00
++#define SHIFT_LSR	0x40
++#define SHIFT_ASR	0x80
++#define SHIFT_RORRRX	0xc0
++
++union offset_union {
++	unsigned long un;
++	signed long sn;
++};
++
++#define TYPE_ERROR	0
++#define TYPE_FAULT	1
++#define TYPE_LDST	2
++#define TYPE_DONE	3
++#define TYPE_SWAP  4
++#define TYPE_COLS  5		/* Coprocessor load/store */
++
++#define get8_unaligned_check(val, addr, err)		\
++	__asm__(					\
++	"1:	ldb.u	%1, [%2], #1\n"			\
++	"2:\n"						\
++	"	.pushsection .fixup,\"ax\"\n"		\
++	"	.align	2\n"				\
++	"3:	mov	%0, #1\n"			\
++	"	b	2b\n"				\
++	"	.popsection\n"				\
++	"	.pushsection __ex_table,\"a\"\n"		\
++	"	.align	3\n"				\
++	"	.long	1b, 3b\n"			\
++	"	.popsection\n"				\
++	: "=r" (err), "=&r" (val), "=r" (addr)		\
++	: "0" (err), "2" (addr))
++
++#define get8t_unaligned_check(val, addr, err)		\
++	__asm__(					\
++	"1:	ldb.u	%1, [%2], #1\n"			\
++	"2:\n"						\
++	"	.pushsection .fixup,\"ax\"\n"		\
++	"	.align	2\n"				\
++	"3:	mov	%0, #1\n"			\
++	"	b	2b\n"				\
++	"	.popsection\n"				\
++	"	.pushsection __ex_table,\"a\"\n"		\
++	"	.align	3\n"				\
++	"	.long	1b, 3b\n"			\
++	"	.popsection\n"				\
++	: "=r" (err), "=&r" (val), "=r" (addr)		\
++	: "0" (err), "2" (addr))
++
++#define get16_unaligned_check(val, addr)			\
++	do {							\
++		unsigned int err = 0, v, a = addr;		\
++		get8_unaligned_check(val, a, err);		\
++		get8_unaligned_check(v, a, err);		\
++		val |= v << 8;					\
++		if (err)					\
++			goto fault;				\
++	} while (0)
++
++#define put16_unaligned_check(val, addr)			\
++	do {							\
++		unsigned int err = 0, v = val, a = addr;	\
++		__asm__(					\
++		"1:	stb.u	%1, [%2], #1\n"			\
++		"	mov	%1, %1 >> #8\n"			\
++		"2:	stb.u	%1, [%2]\n"			\
++		"3:\n"						\
++		"	.pushsection .fixup,\"ax\"\n"		\
++		"	.align	2\n"				\
++		"4:	mov	%0, #1\n"			\
++		"	b	3b\n"				\
++		"	.popsection\n"				\
++		"	.pushsection __ex_table,\"a\"\n"		\
++		"	.align	3\n"				\
++		"	.long	1b, 4b\n"			\
++		"	.long	2b, 4b\n"			\
++		"	.popsection\n"				\
++		: "=r" (err), "=&r" (v), "=&r" (a)		\
++		: "0" (err), "1" (v), "2" (a));			\
++		if (err)					\
++			goto fault;				\
++	} while (0)
++
++#define __put32_unaligned_check(ins, val, addr)			\
++	do {							\
++		unsigned int err = 0, v = val, a = addr;	\
++		__asm__(					\
++		"1:	"ins"	%1, [%2], #1\n"			\
++		"	mov	%1, %1 >> #8\n"			\
++		"2:	"ins"	%1, [%2], #1\n"			\
++		"	mov	%1, %1 >> #8\n"			\
++		"3:	"ins"	%1, [%2], #1\n"			\
++		"	mov	%1, %1 >> #8\n"			\
++		"4:	"ins"	%1, [%2]\n"			\
++		"5:\n"						\
++		"	.pushsection .fixup,\"ax\"\n"		\
++		"	.align	2\n"				\
++		"6:	mov	%0, #1\n"			\
++		"	b	5b\n"				\
++		"	.popsection\n"				\
++		"	.pushsection __ex_table,\"a\"\n"		\
++		"	.align	3\n"				\
++		"	.long	1b, 6b\n"			\
++		"	.long	2b, 6b\n"			\
++		"	.long	3b, 6b\n"			\
++		"	.long	4b, 6b\n"			\
++		"	.popsection\n"				\
++		: "=r" (err), "=&r" (v), "=&r" (a)		\
++		: "0" (err), "1" (v), "2" (a));			\
++		if (err)					\
++			goto fault;				\
++	} while (0)
++
++#define get32_unaligned_check(val, addr)			\
++	do {							\
++		unsigned int err = 0, v, a = addr;		\
++		get8_unaligned_check(val, a, err);		\
++		get8_unaligned_check(v, a, err);		\
++		val |= v << 8;					\
++		get8_unaligned_check(v, a, err);		\
++		val |= v << 16;					\
++		get8_unaligned_check(v, a, err);		\
++		val |= v << 24;					\
++		if (err)					\
++			goto fault;				\
++	} while (0)
++
++#define put32_unaligned_check(val, addr)			\
++	__put32_unaligned_check("stb.u", val, addr)
++
++#define get32t_unaligned_check(val, addr)			\
++	do {							\
++		unsigned int err = 0, v, a = addr;		\
++		get8t_unaligned_check(val, a, err);		\
++		get8t_unaligned_check(v, a, err);		\
++		val |= v << 8;					\
++		get8t_unaligned_check(v, a, err);		\
++		val |= v << 16;					\
++		get8t_unaligned_check(v, a, err);		\
++		val |= v << 24;					\
++		if (err)					\
++			goto fault;				\
++	} while (0)
++
++#define put32t_unaligned_check(val, addr)			\
++	__put32_unaligned_check("stb.u", val, addr)
++
++static void
++do_alignment_finish_ldst(unsigned long addr, unsigned long instr,
++			 struct pt_regs *regs, union offset_union offset)
++{
++	if (!LDST_U_BIT(instr))
++		offset.un = -offset.un;
++
++	if (!LDST_P_BIT(instr))
++		addr += offset.un;
++
++	if (!LDST_P_BIT(instr) || LDST_W_BIT(instr))
++		regs->uregs[RN_BITS(instr)] = addr;
++}
++
++static int
++do_alignment_ldrhstrh(unsigned long addr, unsigned long instr,
++		      struct pt_regs *regs)
++{
++	unsigned int rd = RD_BITS(instr);
++
++	/* old value 0x40002120, can't judge swap instr correctly */
++	if ((instr & 0x4b003fe0) == 0x40000120)
++		goto swp;
++
++	if (LDST_L_BIT(instr)) {
++		unsigned long val;
++		get16_unaligned_check(val, addr);
++
++		/* signed half-word? */
++		if (instr & 0x80)
++			val = (signed long)((signed short)val);
++
++		regs->uregs[rd] = val;
++	} else
++		put16_unaligned_check(regs->uregs[rd], addr);
++
++	return TYPE_LDST;
++
++swp:
++	/* only handle swap word
++	 * for swap byte should not active this alignment exception */
++	get32_unaligned_check(regs->uregs[RD_BITS(instr)], addr);
++	put32_unaligned_check(regs->uregs[RM_BITS(instr)], addr);
++	return TYPE_SWAP;
++
++fault:
++	return TYPE_FAULT;
++}
++
++static int
++do_alignment_ldrstr(unsigned long addr, unsigned long instr,
++		    struct pt_regs *regs)
++{
++	unsigned int rd = RD_BITS(instr);
++
++	if (!LDST_P_BIT(instr) && LDST_W_BIT(instr))
++		goto trans;
++
++	if (LDST_L_BIT(instr))
++		get32_unaligned_check(regs->uregs[rd], addr);
++	else
++		put32_unaligned_check(regs->uregs[rd], addr);
++	return TYPE_LDST;
++
++trans:
++	if (LDST_L_BIT(instr))
++		get32t_unaligned_check(regs->uregs[rd], addr);
++	else
++		put32t_unaligned_check(regs->uregs[rd], addr);
++	return TYPE_LDST;
++
++fault:
++	return TYPE_FAULT;
++}
++
++/*
++ * LDM/STM alignment handler.
++ *
++ * There are 4 variants of this instruction:
++ *
++ * B = rn pointer before instruction, A = rn pointer after instruction
++ *              ------ increasing address ----->
++ *	        |    | r0 | r1 | ... | rx |    |
++ * PU = 01             B                    A
++ * PU = 11        B                    A
++ * PU = 00        A                    B
++ * PU = 10             A                    B
++ */
++static int
++do_alignment_ldmstm(unsigned long addr, unsigned long instr,
++		    struct pt_regs *regs)
++{
++	unsigned int rd, rn, pc_correction, reg_correction, nr_regs, regbits;
++	unsigned long eaddr, newaddr;
++
++	if (LDM_S_BIT(instr))
++		goto bad;
++
++	pc_correction = 4;	/* processor implementation defined */
++
++	/* count the number of registers in the mask to be transferred */
++	nr_regs = hweight16(REGMASK_BITS(instr)) * 4;
++
++	rn = RN_BITS(instr);
++	newaddr = eaddr = regs->uregs[rn];
++
++	if (!LDST_U_BIT(instr))
++		nr_regs = -nr_regs;
++	newaddr += nr_regs;
++	if (!LDST_U_BIT(instr))
++		eaddr = newaddr;
++
++	if (LDST_P_EQ_U(instr))	/* U = P */
++		eaddr += 4;
++
++	/*
++	 * This is a "hint" - we already have eaddr worked out by the
++	 * processor for us.
++	 */
++	if (addr != eaddr) {
++		printk(KERN_ERR "LDMSTM: PC = %08lx, instr = %08lx, "
++		       "addr = %08lx, eaddr = %08lx\n",
++		       instruction_pointer(regs), instr, addr, eaddr);
++		show_regs(regs);
++	}
++
++	if (LDM_H_BIT(instr))
++		reg_correction = 0x10;
++	else
++		reg_correction = 0x00;
++
++	for (regbits = REGMASK_BITS(instr), rd = 0; regbits;
++	     regbits >>= 1, rd += 1)
++		if (regbits & 1) {
++			if (LDST_L_BIT(instr))
++				get32_unaligned_check(regs->
++					uregs[rd + reg_correction], eaddr);
++			else
++				put32_unaligned_check(regs->
++					uregs[rd + reg_correction], eaddr);
++			eaddr += 4;
++		}
++
++	if (LDST_W_BIT(instr))
++		regs->uregs[rn] = newaddr;
++	return TYPE_DONE;
++
++fault:
++	regs->UCreg_pc -= pc_correction;
++	return TYPE_FAULT;
++
++bad:
++	printk(KERN_ERR "Alignment trap: not handling ldm with s-bit set\n");
++	return TYPE_ERROR;
++}
++
++static int
++do_alignment(unsigned long addr, unsigned int error_code, struct pt_regs *regs)
++{
++	union offset_union offset;
++	unsigned long instr, instrptr;
++	int (*handler) (unsigned long addr, unsigned long instr,
++			struct pt_regs *regs);
++	unsigned int type;
++
++	instrptr = instruction_pointer(regs);
++	if (instrptr >= PAGE_OFFSET)
++		instr = *(unsigned long *)instrptr;
++	else {
++		__asm__ __volatile__(
++				"ldw.u	%0, [%1]\n"
++				: "=&r"(instr)
++				: "r"(instrptr));
++	}
++
++	regs->UCreg_pc += 4;
++
++	switch (CODING_BITS(instr)) {
++	case 0x40000120:	/* ldrh or strh */
++		if (LDSTH_I_BIT(instr))
++			offset.un = (instr & 0x3e00) >> 4 | (instr & 31);
++		else
++			offset.un = regs->uregs[RM_BITS(instr)];
++		handler = do_alignment_ldrhstrh;
++		break;
++
++	case 0x60000000:	/* ldr or str immediate */
++	case 0x60000100:	/* ldr or str immediate */
++	case 0x60000020:	/* ldr or str immediate */
++	case 0x60000120:	/* ldr or str immediate */
++		offset.un = OFFSET_BITS(instr);
++		handler = do_alignment_ldrstr;
++		break;
++
++	case 0x40000000:	/* ldr or str register */
++		offset.un = regs->uregs[RM_BITS(instr)];
++		{
++			unsigned int shiftval = SHIFT_BITS(instr);
++
++			switch (SHIFT_TYPE(instr)) {
++			case SHIFT_LSL:
++				offset.un <<= shiftval;
++				break;
++
++			case SHIFT_LSR:
++				offset.un >>= shiftval;
++				break;
++
++			case SHIFT_ASR:
++				offset.sn >>= shiftval;
++				break;
++
++			case SHIFT_RORRRX:
++				if (shiftval == 0) {
++					offset.un >>= 1;
++					if (regs->UCreg_asr & PSR_C_BIT)
++						offset.un |= 1 << 31;
++				} else
++					offset.un = offset.un >> shiftval |
++					    offset.un << (32 - shiftval);
++				break;
++			}
++		}
++		handler = do_alignment_ldrstr;
++		break;
++
++	case 0x80000000:	/* ldm or stm */
++	case 0x80000020:	/* ldm or stm */
++		handler = do_alignment_ldmstm;
++		break;
++
++	default:
++		goto bad;
++	}
++
++	type = handler(addr, instr, regs);
++
++	if (type == TYPE_ERROR || type == TYPE_FAULT)
++		goto bad_or_fault;
++
++	if (type == TYPE_LDST)
++		do_alignment_finish_ldst(addr, instr, regs, offset);
++
++	return 0;
++
++bad_or_fault:
++	if (type == TYPE_ERROR)
++		goto bad;
++	regs->UCreg_pc -= 4;
++	/*
++	 * We got a fault - fix it up, or die.
++	 */
++	do_bad_area(addr, error_code, regs);
++	return 0;
++
++bad:
++	/*
++	 * Oops, we didn't handle the instruction.
++	 * However, we must handle fpu instr firstly.
++	 */
++#ifdef CONFIG_UNICORE_FPU_F64
++	/* handle co.load/store */
++#define CODING_COLS                0xc0000000
++#define COLS_OFFSET_BITS(i)	(i & 0x1FF)
++#define COLS_L_BITS(i)		(i & (1<<24))
++#define COLS_FN_BITS(i)		((i>>14) & 31)
++	if ((instr & 0xe0000000) == CODING_COLS) {
++		unsigned int fn = COLS_FN_BITS(instr);
++		unsigned long val = 0;
++		if (COLS_L_BITS(instr)) {
++			get32t_unaligned_check(val, addr);
++			switch (fn) {
++#define ASM_MTF(n)	case n:						\
++			__asm__ __volatile__("MTF %0, F" __stringify(n)	\
++				: : "r"(val));				\
++			break;
++			ASM_MTF(0); ASM_MTF(1); ASM_MTF(2); ASM_MTF(3);
++			ASM_MTF(4); ASM_MTF(5); ASM_MTF(6); ASM_MTF(7);
++			ASM_MTF(8); ASM_MTF(9); ASM_MTF(10); ASM_MTF(11);
++			ASM_MTF(12); ASM_MTF(13); ASM_MTF(14); ASM_MTF(15);
++			ASM_MTF(16); ASM_MTF(17); ASM_MTF(18); ASM_MTF(19);
++			ASM_MTF(20); ASM_MTF(21); ASM_MTF(22); ASM_MTF(23);
++			ASM_MTF(24); ASM_MTF(25); ASM_MTF(26); ASM_MTF(27);
++			ASM_MTF(28); ASM_MTF(29); ASM_MTF(30); ASM_MTF(31);
++#undef ASM_MTF
++			}
++		} else {
++			switch (fn) {
++#define ASM_MFF(n)	case n:						\
++			__asm__ __volatile__("MFF %0, F" __stringify(n)	\
++				: : "r"(val));				\
++			break;
++			ASM_MFF(0); ASM_MFF(1); ASM_MFF(2); ASM_MFF(3);
++			ASM_MFF(4); ASM_MFF(5); ASM_MFF(6); ASM_MFF(7);
++			ASM_MFF(8); ASM_MFF(9); ASM_MFF(10); ASM_MFF(11);
++			ASM_MFF(12); ASM_MFF(13); ASM_MFF(14); ASM_MFF(15);
++			ASM_MFF(16); ASM_MFF(17); ASM_MFF(18); ASM_MFF(19);
++			ASM_MFF(20); ASM_MFF(21); ASM_MFF(22); ASM_MFF(23);
++			ASM_MFF(24); ASM_MFF(25); ASM_MFF(26); ASM_MFF(27);
++			ASM_MFF(28); ASM_MFF(29); ASM_MFF(30); ASM_MFF(31);
++#undef ASM_MFF
++			}
++			put32t_unaligned_check(val, addr);
++		}
++		return TYPE_COLS;
++	}
++fault:
++	return TYPE_FAULT;
++#endif
++	printk(KERN_ERR "Alignment trap: not handling instruction "
++	       "%08lx at [<%08lx>]\n", instr, instrptr);
++	return 1;
++}
++
++/*
++ * This needs to be done after sysctl_init, otherwise sys/ will be
++ * overwritten.  Actually, this shouldn't be in sys/ at all since
++ * it isn't a sysctl, and it doesn't contain sysctl information.
++ */
++static int __init alignment_init(void)
++{
++	hook_fault_code(1, do_alignment, SIGBUS, BUS_ADRALN,
++			"alignment exception");
++
++	return 0;
++}
++
++fs_initcall(alignment_init);
+diff --git a/arch/unicore32/mm/extable.c b/arch/unicore32/mm/extable.c
+new file mode 100644
+index 000000000000..6564180eb285
+--- /dev/null
++++ b/arch/unicore32/mm/extable.c
+@@ -0,0 +1,24 @@
++/*
++ * linux/arch/unicore32/mm/extable.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++
++int fixup_exception(struct pt_regs *regs)
++{
++	const struct exception_table_entry *fixup;
++
++	fixup = search_exception_tables(instruction_pointer(regs));
++	if (fixup)
++		regs->UCreg_pc = fixup->fixup;
++
++	return fixup != NULL;
++}
+diff --git a/arch/unicore32/mm/fault.c b/arch/unicore32/mm/fault.c
+new file mode 100644
+index 000000000000..283aa4b50b7a
+--- /dev/null
++++ b/arch/unicore32/mm/fault.c
+@@ -0,0 +1,479 @@
++/*
++ * linux/arch/unicore32/mm/fault.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++#include 
++#include 
++
++/*
++ * Fault status register encodings.  We steal bit 31 for our own purposes.
++ */
++#define FSR_LNX_PF		(1 << 31)
++
++static inline int fsr_fs(unsigned int fsr)
++{
++	/* xyabcde will be abcde+xy */
++	return (fsr & 31) + ((fsr & (3 << 5)) >> 5);
++}
++
++/*
++ * This is useful to dump out the page tables associated with
++ * 'addr' in mm 'mm'.
++ */
++void show_pte(struct mm_struct *mm, unsigned long addr)
++{
++	pgd_t *pgd;
++
++	if (!mm)
++		mm = &init_mm;
++
++	printk(KERN_ALERT "pgd = %p\n", mm->pgd);
++	pgd = pgd_offset(mm, addr);
++	printk(KERN_ALERT "[%08lx] *pgd=%08lx", addr, pgd_val(*pgd));
++
++	do {
++		pmd_t *pmd;
++		pte_t *pte;
++
++		if (pgd_none(*pgd))
++			break;
++
++		if (pgd_bad(*pgd)) {
++			printk("(bad)");
++			break;
++		}
++
++		pmd = pmd_offset((pud_t *) pgd, addr);
++		if (PTRS_PER_PMD != 1)
++			printk(", *pmd=%08lx", pmd_val(*pmd));
++
++		if (pmd_none(*pmd))
++			break;
++
++		if (pmd_bad(*pmd)) {
++			printk("(bad)");
++			break;
++		}
++
++		/* We must not map this if we have highmem enabled */
++		if (PageHighMem(pfn_to_page(pmd_val(*pmd) >> PAGE_SHIFT)))
++			break;
++
++		pte = pte_offset_map(pmd, addr);
++		printk(", *pte=%08lx", pte_val(*pte));
++		pte_unmap(pte);
++	} while (0);
++
++	printk("\n");
++}
++
++/*
++ * Oops.  The kernel tried to access some page that wasn't present.
++ */
++static void __do_kernel_fault(struct mm_struct *mm, unsigned long addr,
++		unsigned int fsr, struct pt_regs *regs)
++{
++	/*
++	 * Are we prepared to handle this kernel fault?
++	 */
++	if (fixup_exception(regs))
++		return;
++
++	/*
++	 * No handler, we'll have to terminate things with extreme prejudice.
++	 */
++	bust_spinlocks(1);
++	printk(KERN_ALERT
++	       "Unable to handle kernel %s at virtual address %08lx\n",
++	       (addr < PAGE_SIZE) ? "NULL pointer dereference" :
++	       "paging request", addr);
++
++	show_pte(mm, addr);
++	die("Oops", regs, fsr);
++	bust_spinlocks(0);
++	do_exit(SIGKILL);
++}
++
++/*
++ * Something tried to access memory that isn't in our memory map..
++ * User mode accesses just cause a SIGSEGV
++ */
++static void __do_user_fault(struct task_struct *tsk, unsigned long addr,
++		unsigned int fsr, unsigned int sig, int code,
++		struct pt_regs *regs)
++{
++	struct siginfo si;
++
++	tsk->thread.address = addr;
++	tsk->thread.error_code = fsr;
++	tsk->thread.trap_no = 14;
++	si.si_signo = sig;
++	si.si_errno = 0;
++	si.si_code = code;
++	si.si_addr = (void __user *)addr;
++	force_sig_info(sig, &si, tsk);
++}
++
++void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
++{
++	struct task_struct *tsk = current;
++	struct mm_struct *mm = tsk->active_mm;
++
++	/*
++	 * If we are in kernel mode at this point, we
++	 * have no context to handle this fault with.
++	 */
++	if (user_mode(regs))
++		__do_user_fault(tsk, addr, fsr, SIGSEGV, SEGV_MAPERR, regs);
++	else
++		__do_kernel_fault(mm, addr, fsr, regs);
++}
++
++#define VM_FAULT_BADMAP		0x010000
++#define VM_FAULT_BADACCESS	0x020000
++
++/*
++ * Check that the permissions on the VMA allow for the fault which occurred.
++ * If we encountered a write fault, we must have write permission, otherwise
++ * we allow any permission.
++ */
++static inline bool access_error(unsigned int fsr, struct vm_area_struct *vma)
++{
++	unsigned int mask = VM_READ | VM_WRITE | VM_EXEC;
++
++	if (!(fsr ^ 0x12))	/* write? */
++		mask = VM_WRITE;
++	if (fsr & FSR_LNX_PF)
++		mask = VM_EXEC;
++
++	return vma->vm_flags & mask ? false : true;
++}
++
++static int __do_pf(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
++		struct task_struct *tsk)
++{
++	struct vm_area_struct *vma;
++	int fault;
++
++	vma = find_vma(mm, addr);
++	fault = VM_FAULT_BADMAP;
++	if (unlikely(!vma))
++		goto out;
++	if (unlikely(vma->vm_start > addr))
++		goto check_stack;
++
++	/*
++	 * Ok, we have a good vm_area for this
++	 * memory access, so we can handle it.
++	 */
++good_area:
++	if (access_error(fsr, vma)) {
++		fault = VM_FAULT_BADACCESS;
++		goto out;
++	}
++
++	/*
++	 * If for any reason at all we couldn't handle the fault, make
++	 * sure we exit gracefully rather than endlessly redo the fault.
++	 */
++	fault = handle_mm_fault(mm, vma, addr & PAGE_MASK,
++			    (!(fsr ^ 0x12)) ? FAULT_FLAG_WRITE : 0);
++	if (unlikely(fault & VM_FAULT_ERROR))
++		return fault;
++	if (fault & VM_FAULT_MAJOR)
++		tsk->maj_flt++;
++	else
++		tsk->min_flt++;
++	return fault;
++
++check_stack:
++	if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(vma, addr))
++		goto good_area;
++out:
++	return fault;
++}
++
++static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
++{
++	struct task_struct *tsk;
++	struct mm_struct *mm;
++	int fault, sig, code;
++
++	tsk = current;
++	mm = tsk->mm;
++
++	/*
++	 * If we're in an interrupt or have no user
++	 * context, we must not take the fault..
++	 */
++	if (in_atomic() || !mm)
++		goto no_context;
++
++	/*
++	 * As per x86, we may deadlock here.  However, since the kernel only
++	 * validly references user space from well defined areas of the code,
++	 * we can bug out early if this is from code which shouldn't.
++	 */
++	if (!down_read_trylock(&mm->mmap_sem)) {
++		if (!user_mode(regs)
++		    && !search_exception_tables(regs->UCreg_pc))
++			goto no_context;
++		down_read(&mm->mmap_sem);
++	} else {
++		/*
++		 * The above down_read_trylock() might have succeeded in
++		 * which case, we'll have missed the might_sleep() from
++		 * down_read()
++		 */
++		might_sleep();
++#ifdef CONFIG_DEBUG_VM
++		if (!user_mode(regs) &&
++		    !search_exception_tables(regs->UCreg_pc))
++			goto no_context;
++#endif
++	}
++
++	fault = __do_pf(mm, addr, fsr, tsk);
++	up_read(&mm->mmap_sem);
++
++	/*
++	 * Handle the "normal" case first - VM_FAULT_MAJOR / VM_FAULT_MINOR
++	 */
++	if (likely(!(fault &
++	       (VM_FAULT_ERROR | VM_FAULT_BADMAP | VM_FAULT_BADACCESS))))
++		return 0;
++
++	if (fault & VM_FAULT_OOM) {
++		/*
++		 * We ran out of memory, call the OOM killer, and return to
++		 * userspace (which will retry the fault, or kill us if we
++		 * got oom-killed)
++		 */
++		pagefault_out_of_memory();
++		return 0;
++	}
++
++	/*
++	 * If we are in kernel mode at this point, we
++	 * have no context to handle this fault with.
++	 */
++	if (!user_mode(regs))
++		goto no_context;
++
++	if (fault & VM_FAULT_SIGBUS) {
++		/*
++		 * We had some memory, but were unable to
++		 * successfully fix up this page fault.
++		 */
++		sig = SIGBUS;
++		code = BUS_ADRERR;
++	} else {
++		/*
++		 * Something tried to access memory that
++		 * isn't in our memory map..
++		 */
++		sig = SIGSEGV;
++		code = fault == VM_FAULT_BADACCESS ? SEGV_ACCERR : SEGV_MAPERR;
++	}
++
++	__do_user_fault(tsk, addr, fsr, sig, code, regs);
++	return 0;
++
++no_context:
++	__do_kernel_fault(mm, addr, fsr, regs);
++	return 0;
++}
++
++/*
++ * First Level Translation Fault Handler
++ *
++ * We enter here because the first level page table doesn't contain
++ * a valid entry for the address.
++ *
++ * If the address is in kernel space (>= TASK_SIZE), then we are
++ * probably faulting in the vmalloc() area.
++ *
++ * If the init_task's first level page tables contains the relevant
++ * entry, we copy the it to this task.  If not, we send the process
++ * a signal, fixup the exception, or oops the kernel.
++ *
++ * NOTE! We MUST NOT take any locks for this case. We may be in an
++ * interrupt or a critical region, and should only copy the information
++ * from the master page table, nothing more.
++ */
++static int do_ifault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
++{
++	unsigned int index;
++	pgd_t *pgd, *pgd_k;
++	pmd_t *pmd, *pmd_k;
++
++	if (addr < TASK_SIZE)
++		return do_pf(addr, fsr, regs);
++
++	if (user_mode(regs))
++		goto bad_area;
++
++	index = pgd_index(addr);
++
++	pgd = cpu_get_pgd() + index;
++	pgd_k = init_mm.pgd + index;
++
++	if (pgd_none(*pgd_k))
++		goto bad_area;
++
++	pmd_k = pmd_offset((pud_t *) pgd_k, addr);
++	pmd = pmd_offset((pud_t *) pgd, addr);
++
++	if (pmd_none(*pmd_k))
++		goto bad_area;
++
++	set_pmd(pmd, *pmd_k);
++	flush_pmd_entry(pmd);
++	return 0;
++
++bad_area:
++	do_bad_area(addr, fsr, regs);
++	return 0;
++}
++
++/*
++ * This abort handler always returns "fault".
++ */
++static int do_bad(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
++{
++	return 1;
++}
++
++static int do_good(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
++{
++	unsigned int res1, res2;
++
++	printk("dabt exception but no error!\n");
++
++	__asm__ __volatile__(
++			"mff %0,f0\n"
++			"mff %1,f1\n"
++			: "=r"(res1), "=r"(res2)
++			:
++			: "memory");
++
++	printk(KERN_EMERG "r0 :%08x  r1 :%08x\n", res1, res2);
++	panic("shut up\n");
++	return 0;
++}
++
++static struct fsr_info {
++	int (*fn) (unsigned long addr, unsigned int fsr, struct pt_regs *regs);
++	int sig;
++	int code;
++	const char *name;
++} fsr_info[] = {
++	/*
++	 * The following are the standard Unicore-I and UniCore-II aborts.
++	 */
++	{ do_good,	SIGBUS,  0,		"no error"		},
++	{ do_bad,	SIGBUS,  BUS_ADRALN,	"alignment exception"	},
++	{ do_bad,	SIGBUS,  BUS_OBJERR,	"external exception"	},
++	{ do_bad,	SIGBUS,  0,		"burst operation"	},
++	{ do_bad,	SIGBUS,  0,		"unknown 00100"		},
++	{ do_ifault,	SIGSEGV, SEGV_MAPERR,	"2nd level pt non-exist"},
++	{ do_bad,	SIGBUS,  0,		"2nd lvl large pt non-exist" },
++	{ do_bad,	SIGBUS,  0,		"invalid pte"		},
++	{ do_pf,	SIGSEGV, SEGV_MAPERR,	"page miss"		},
++	{ do_bad,	SIGBUS,  0,		"middle page miss"	},
++	{ do_bad,	SIGBUS,	 0,		"large page miss"	},
++	{ do_pf,	SIGSEGV, SEGV_MAPERR,	"super page (section) miss" },
++	{ do_bad,	SIGBUS,  0,		"unknown 01100"		},
++	{ do_bad,	SIGBUS,  0,		"unknown 01101"		},
++	{ do_bad,	SIGBUS,  0,		"unknown 01110"		},
++	{ do_bad,	SIGBUS,  0,		"unknown 01111"		},
++	{ do_bad,	SIGBUS,  0,		"addr: up 3G or IO"	},
++	{ do_pf,	SIGSEGV, SEGV_ACCERR,	"read unreadable addr"	},
++	{ do_pf,	SIGSEGV, SEGV_ACCERR,	"write unwriteable addr"},
++	{ do_pf,	SIGSEGV, SEGV_ACCERR,	"exec unexecutable addr"},
++	{ do_bad,	SIGBUS,  0,		"unknown 10100"		},
++	{ do_bad,	SIGBUS,  0,		"unknown 10101"		},
++	{ do_bad,	SIGBUS,  0,		"unknown 10110"		},
++	{ do_bad,	SIGBUS,  0,		"unknown 10111"		},
++	{ do_bad,	SIGBUS,  0,		"unknown 11000"		},
++	{ do_bad,	SIGBUS,  0,		"unknown 11001"		},
++	{ do_bad,	SIGBUS,  0,		"unknown 11010"		},
++	{ do_bad,	SIGBUS,  0,		"unknown 11011"		},
++	{ do_bad,	SIGBUS,  0,		"unknown 11100"		},
++	{ do_bad,	SIGBUS,  0,		"unknown 11101"		},
++	{ do_bad,	SIGBUS,  0,		"unknown 11110"		},
++	{ do_bad,	SIGBUS,  0,		"unknown 11111"		}
++};
++
++void __init hook_fault_code(int nr,
++		int (*fn) (unsigned long, unsigned int, struct pt_regs *),
++		int sig, int code, const char *name)
++{
++	if (nr < 0 || nr >= ARRAY_SIZE(fsr_info))
++		BUG();
++
++	fsr_info[nr].fn   = fn;
++	fsr_info[nr].sig  = sig;
++	fsr_info[nr].code = code;
++	fsr_info[nr].name = name;
++}
++
++/*
++ * Dispatch a data abort to the relevant handler.
++ */
++asmlinkage void do_DataAbort(unsigned long addr, unsigned int fsr,
++			struct pt_regs *regs)
++{
++	const struct fsr_info *inf = fsr_info + fsr_fs(fsr);
++	struct siginfo info;
++
++	if (!inf->fn(addr, fsr & ~FSR_LNX_PF, regs))
++		return;
++
++	printk(KERN_ALERT "Unhandled fault: %s (0x%03x) at 0x%08lx\n",
++	       inf->name, fsr, addr);
++
++	info.si_signo = inf->sig;
++	info.si_errno = 0;
++	info.si_code = inf->code;
++	info.si_addr = (void __user *)addr;
++	uc32_notify_die("", regs, &info, fsr, 0);
++}
++
++asmlinkage void do_PrefetchAbort(unsigned long addr,
++			unsigned int ifsr, struct pt_regs *regs)
++{
++	const struct fsr_info *inf = fsr_info + fsr_fs(ifsr);
++	struct siginfo info;
++
++	if (!inf->fn(addr, ifsr | FSR_LNX_PF, regs))
++		return;
++
++	printk(KERN_ALERT "Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n",
++	       inf->name, ifsr, addr);
++
++	info.si_signo = inf->sig;
++	info.si_errno = 0;
++	info.si_code = inf->code;
++	info.si_addr = (void __user *)addr;
++	uc32_notify_die("", regs, &info, ifsr, 0);
++}
+diff --git a/arch/unicore32/mm/mmu.c b/arch/unicore32/mm/mmu.c
+new file mode 100644
+index 000000000000..7bf3d588631f
+--- /dev/null
++++ b/arch/unicore32/mm/mmu.c
+@@ -0,0 +1,533 @@
++/*
++ * linux/arch/unicore32/mm/mmu.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++
++#include "mm.h"
++
++DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
++
++/*
++ * empty_zero_page is a special page that is used for
++ * zero-initialized data and COW.
++ */
++struct page *empty_zero_page;
++EXPORT_SYMBOL(empty_zero_page);
++
++/*
++ * The pmd table for the upper-most set of pages.
++ */
++pmd_t *top_pmd;
++
++pgprot_t pgprot_user;
++EXPORT_SYMBOL(pgprot_user);
++
++pgprot_t pgprot_kernel;
++EXPORT_SYMBOL(pgprot_kernel);
++
++static int __init noalign_setup(char *__unused)
++{
++	cr_alignment &= ~CR_A;
++	cr_no_alignment &= ~CR_A;
++	set_cr(cr_alignment);
++	return 1;
++}
++__setup("noalign", noalign_setup);
++
++void adjust_cr(unsigned long mask, unsigned long set)
++{
++	unsigned long flags;
++
++	mask &= ~CR_A;
++
++	set &= mask;
++
++	local_irq_save(flags);
++
++	cr_no_alignment = (cr_no_alignment & ~mask) | set;
++	cr_alignment = (cr_alignment & ~mask) | set;
++
++	set_cr((get_cr() & ~mask) | set);
++
++	local_irq_restore(flags);
++}
++
++struct map_desc {
++	unsigned long virtual;
++	unsigned long pfn;
++	unsigned long length;
++	unsigned int type;
++};
++
++#define PROT_PTE_DEVICE		(PTE_PRESENT | PTE_YOUNG |	\
++				PTE_DIRTY | PTE_READ | PTE_WRITE)
++#define PROT_SECT_DEVICE	(PMD_TYPE_SECT | PMD_PRESENT |	\
++				PMD_SECT_READ | PMD_SECT_WRITE)
++
++static struct mem_type mem_types[] = {
++	[MT_DEVICE] = {		  /* Strongly ordered */
++		.prot_pte	= PROT_PTE_DEVICE,
++		.prot_l1	= PMD_TYPE_TABLE | PMD_PRESENT,
++		.prot_sect	= PROT_SECT_DEVICE,
++	},
++	/*
++	 * MT_KUSER: pte for vecpage -- cacheable,
++	 *       and sect for unigfx mmap -- noncacheable
++	 */
++	[MT_KUSER] = {
++		.prot_pte  = PTE_PRESENT | PTE_YOUNG | PTE_DIRTY |
++				PTE_CACHEABLE | PTE_READ | PTE_EXEC,
++		.prot_l1   = PMD_TYPE_TABLE | PMD_PRESENT,
++		.prot_sect = PROT_SECT_DEVICE,
++	},
++	[MT_HIGH_VECTORS] = {
++		.prot_pte  = PTE_PRESENT | PTE_YOUNG | PTE_DIRTY |
++				PTE_CACHEABLE | PTE_READ | PTE_WRITE |
++				PTE_EXEC,
++		.prot_l1   = PMD_TYPE_TABLE | PMD_PRESENT,
++	},
++	[MT_MEMORY] = {
++		.prot_pte  = PTE_PRESENT | PTE_YOUNG | PTE_DIRTY |
++				PTE_WRITE | PTE_EXEC,
++		.prot_l1   = PMD_TYPE_TABLE | PMD_PRESENT,
++		.prot_sect = PMD_TYPE_SECT | PMD_PRESENT | PMD_SECT_CACHEABLE |
++				PMD_SECT_READ | PMD_SECT_WRITE | PMD_SECT_EXEC,
++	},
++	[MT_ROM] = {
++		.prot_sect = PMD_TYPE_SECT | PMD_PRESENT | PMD_SECT_CACHEABLE |
++				PMD_SECT_READ,
++	},
++};
++
++const struct mem_type *get_mem_type(unsigned int type)
++{
++	return type < ARRAY_SIZE(mem_types) ? &mem_types[type] : NULL;
++}
++EXPORT_SYMBOL(get_mem_type);
++
++/*
++ * Adjust the PMD section entries according to the CPU in use.
++ */
++static void __init build_mem_type_table(void)
++{
++	pgprot_user   = __pgprot(PTE_PRESENT | PTE_YOUNG | PTE_CACHEABLE);
++	pgprot_kernel = __pgprot(PTE_PRESENT | PTE_YOUNG |
++				 PTE_DIRTY | PTE_READ | PTE_WRITE |
++				 PTE_EXEC | PTE_CACHEABLE);
++}
++
++#define vectors_base()	(vectors_high() ? 0xffff0000 : 0)
++
++static void __init *early_alloc(unsigned long sz)
++{
++	void *ptr = __va(memblock_alloc(sz, sz));
++	memset(ptr, 0, sz);
++	return ptr;
++}
++
++static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr,
++		unsigned long prot)
++{
++	if (pmd_none(*pmd)) {
++		pte_t *pte = early_alloc(PTRS_PER_PTE * sizeof(pte_t));
++		__pmd_populate(pmd, __pa(pte) | prot);
++	}
++	BUG_ON(pmd_bad(*pmd));
++	return pte_offset_kernel(pmd, addr);
++}
++
++static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
++				  unsigned long end, unsigned long pfn,
++				  const struct mem_type *type)
++{
++	pte_t *pte = early_pte_alloc(pmd, addr, type->prot_l1);
++	do {
++		set_pte(pte, pfn_pte(pfn, __pgprot(type->prot_pte)));
++		pfn++;
++	} while (pte++, addr += PAGE_SIZE, addr != end);
++}
++
++static void __init alloc_init_section(pgd_t *pgd, unsigned long addr,
++				      unsigned long end, unsigned long phys,
++				      const struct mem_type *type)
++{
++	pmd_t *pmd = pmd_offset((pud_t *)pgd, addr);
++
++	/*
++	 * Try a section mapping - end, addr and phys must all be aligned
++	 * to a section boundary.
++	 */
++	if (((addr | end | phys) & ~SECTION_MASK) == 0) {
++		pmd_t *p = pmd;
++
++		do {
++			set_pmd(pmd, __pmd(phys | type->prot_sect));
++			phys += SECTION_SIZE;
++		} while (pmd++, addr += SECTION_SIZE, addr != end);
++
++		flush_pmd_entry(p);
++	} else {
++		/*
++		 * No need to loop; pte's aren't interested in the
++		 * individual L1 entries.
++		 */
++		alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);
++	}
++}
++
++/*
++ * Create the page directory entries and any necessary
++ * page tables for the mapping specified by `md'.  We
++ * are able to cope here with varying sizes and address
++ * offsets, and we take full advantage of sections.
++ */
++static void __init create_mapping(struct map_desc *md)
++{
++	unsigned long phys, addr, length, end;
++	const struct mem_type *type;
++	pgd_t *pgd;
++
++	if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) {
++		printk(KERN_WARNING "BUG: not creating mapping for "
++		       "0x%08llx at 0x%08lx in user region\n",
++		       __pfn_to_phys((u64)md->pfn), md->virtual);
++		return;
++	}
++
++	if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
++	    md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) {
++		printk(KERN_WARNING "BUG: mapping for 0x%08llx at 0x%08lx "
++		       "overlaps vmalloc space\n",
++		       __pfn_to_phys((u64)md->pfn), md->virtual);
++	}
++
++	type = &mem_types[md->type];
++
++	addr = md->virtual & PAGE_MASK;
++	phys = (unsigned long)__pfn_to_phys(md->pfn);
++	length = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK));
++
++	if (type->prot_l1 == 0 && ((addr | phys | length) & ~SECTION_MASK)) {
++		printk(KERN_WARNING "BUG: map for 0x%08lx at 0x%08lx can not "
++		       "be mapped using pages, ignoring.\n",
++		       __pfn_to_phys(md->pfn), addr);
++		return;
++	}
++
++	pgd = pgd_offset_k(addr);
++	end = addr + length;
++	do {
++		unsigned long next = pgd_addr_end(addr, end);
++
++		alloc_init_section(pgd, addr, next, phys, type);
++
++		phys += next - addr;
++		addr = next;
++	} while (pgd++, addr != end);
++}
++
++static void * __initdata vmalloc_min = (void *)(VMALLOC_END - SZ_128M);
++
++/*
++ * vmalloc=size forces the vmalloc area to be exactly 'size'
++ * bytes. This can be used to increase (or decrease) the vmalloc
++ * area - the default is 128m.
++ */
++static int __init early_vmalloc(char *arg)
++{
++	unsigned long vmalloc_reserve = memparse(arg, NULL);
++
++	if (vmalloc_reserve < SZ_16M) {
++		vmalloc_reserve = SZ_16M;
++		printk(KERN_WARNING
++			"vmalloc area too small, limiting to %luMB\n",
++			vmalloc_reserve >> 20);
++	}
++
++	if (vmalloc_reserve > VMALLOC_END - (PAGE_OFFSET + SZ_32M)) {
++		vmalloc_reserve = VMALLOC_END - (PAGE_OFFSET + SZ_32M);
++		printk(KERN_WARNING
++			"vmalloc area is too big, limiting to %luMB\n",
++			vmalloc_reserve >> 20);
++	}
++
++	vmalloc_min = (void *)(VMALLOC_END - vmalloc_reserve);
++	return 0;
++}
++early_param("vmalloc", early_vmalloc);
++
++static phys_addr_t lowmem_limit __initdata = SZ_1G;
++
++static void __init sanity_check_meminfo(void)
++{
++	int i, j;
++
++	lowmem_limit = __pa(vmalloc_min - 1) + 1;
++	memblock_set_current_limit(lowmem_limit);
++
++	for (i = 0, j = 0; i < meminfo.nr_banks; i++) {
++		struct membank *bank = &meminfo.bank[j];
++		*bank = meminfo.bank[i];
++		j++;
++	}
++	meminfo.nr_banks = j;
++}
++
++static inline void prepare_page_table(void)
++{
++	unsigned long addr;
++	phys_addr_t end;
++
++	/*
++	 * Clear out all the mappings below the kernel image.
++	 */
++	for (addr = 0; addr < MODULES_VADDR; addr += PGDIR_SIZE)
++		pmd_clear(pmd_off_k(addr));
++
++	for ( ; addr < PAGE_OFFSET; addr += PGDIR_SIZE)
++		pmd_clear(pmd_off_k(addr));
++
++	/*
++	 * Find the end of the first block of lowmem.
++	 */
++	end = memblock.memory.regions[0].base + memblock.memory.regions[0].size;
++	if (end >= lowmem_limit)
++		end = lowmem_limit;
++
++	/*
++	 * Clear out all the kernel space mappings, except for the first
++	 * memory bank, up to the end of the vmalloc region.
++	 */
++	for (addr = __phys_to_virt(end);
++	     addr < VMALLOC_END; addr += PGDIR_SIZE)
++		pmd_clear(pmd_off_k(addr));
++}
++
++/*
++ * Reserve the special regions of memory
++ */
++void __init uc32_mm_memblock_reserve(void)
++{
++	/*
++	 * Reserve the page tables.  These are already in use,
++	 * and can only be in node 0.
++	 */
++	memblock_reserve(__pa(swapper_pg_dir), PTRS_PER_PGD * sizeof(pgd_t));
++
++#ifdef CONFIG_PUV3_UNIGFX
++	/*
++	 * These should likewise go elsewhere.  They pre-reserve the
++	 * screen/video memory region at the 48M~64M of main system memory.
++	 */
++	memblock_reserve(PKUNITY_UNIGFX_MMAP_BASE, PKUNITY_UNIGFX_MMAP_SIZE);
++	memblock_reserve(PKUNITY_UVC_MMAP_BASE, PKUNITY_UVC_MMAP_SIZE);
++#endif
++}
++
++/*
++ * Set up device the mappings.  Since we clear out the page tables for all
++ * mappings above VMALLOC_END, we will remove any debug device mappings.
++ * This means you have to be careful how you debug this function, or any
++ * called function.  This means you can't use any function or debugging
++ * method which may touch any device, otherwise the kernel _will_ crash.
++ */
++static void __init devicemaps_init(void)
++{
++	struct map_desc map;
++	unsigned long addr;
++	void *vectors;
++
++	/*
++	 * Allocate the vector page early.
++	 */
++	vectors = early_alloc(PAGE_SIZE);
++
++	for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE)
++		pmd_clear(pmd_off_k(addr));
++
++	/*
++	 * Create a mapping for UniGFX VRAM
++	 */
++#ifdef CONFIG_PUV3_UNIGFX
++	map.pfn = __phys_to_pfn(PKUNITY_UNIGFX_MMAP_BASE);
++	map.virtual = KUSER_UNIGFX_BASE;
++	map.length = PKUNITY_UNIGFX_MMAP_SIZE;
++	map.type = MT_KUSER;
++	create_mapping(&map);
++#endif
++
++	/*
++	 * Create a mapping for the machine vectors at the high-vectors
++	 * location (0xffff0000).  If we aren't using high-vectors, also
++	 * create a mapping at the low-vectors virtual address.
++	 */
++	map.pfn = __phys_to_pfn(virt_to_phys(vectors));
++	map.virtual = VECTORS_BASE;
++	map.length = PAGE_SIZE;
++	map.type = MT_HIGH_VECTORS;
++	create_mapping(&map);
++
++	/*
++	 * Create a mapping for the kuser page at the special
++	 * location (0xbfff0000) to the same vectors location.
++	 */
++	map.pfn = __phys_to_pfn(virt_to_phys(vectors));
++	map.virtual = KUSER_VECPAGE_BASE;
++	map.length = PAGE_SIZE;
++	map.type = MT_KUSER;
++	create_mapping(&map);
++
++	/*
++	 * Finally flush the caches and tlb to ensure that we're in a
++	 * consistent state wrt the writebuffer.  This also ensures that
++	 * any write-allocated cache lines in the vector page are written
++	 * back.  After this point, we can start to touch devices again.
++	 */
++	local_flush_tlb_all();
++	flush_cache_all();
++}
++
++static void __init map_lowmem(void)
++{
++	struct memblock_region *reg;
++
++	/* Map all the lowmem memory banks. */
++	for_each_memblock(memory, reg) {
++		phys_addr_t start = reg->base;
++		phys_addr_t end = start + reg->size;
++		struct map_desc map;
++
++		if (end > lowmem_limit)
++			end = lowmem_limit;
++		if (start >= end)
++			break;
++
++		map.pfn = __phys_to_pfn(start);
++		map.virtual = __phys_to_virt(start);
++		map.length = end - start;
++		map.type = MT_MEMORY;
++
++		create_mapping(&map);
++	}
++}
++
++/*
++ * paging_init() sets up the page tables, initialises the zone memory
++ * maps, and sets up the zero page, bad page and bad page tables.
++ */
++void __init paging_init(void)
++{
++	void *zero_page;
++
++	build_mem_type_table();
++	sanity_check_meminfo();
++	prepare_page_table();
++	map_lowmem();
++	devicemaps_init();
++
++	top_pmd = pmd_off_k(0xffff0000);
++
++	/* allocate the zero page. */
++	zero_page = early_alloc(PAGE_SIZE);
++
++	bootmem_init();
++
++	empty_zero_page = virt_to_page(zero_page);
++	__flush_dcache_page(NULL, empty_zero_page);
++}
++
++/*
++ * In order to soft-boot, we need to insert a 1:1 mapping in place of
++ * the user-mode pages.  This will then ensure that we have predictable
++ * results when turning the mmu off
++ */
++void setup_mm_for_reboot(char mode)
++{
++	unsigned long base_pmdval;
++	pgd_t *pgd;
++	int i;
++
++	/*
++	 * We need to access to user-mode page tables here. For kernel threads
++	 * we don't have any user-mode mappings so we use the context that we
++	 * "borrowed".
++	 */
++	pgd = current->active_mm->pgd;
++
++	base_pmdval = PMD_SECT_WRITE | PMD_SECT_READ | PMD_TYPE_SECT;
++
++	for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++, pgd++) {
++		unsigned long pmdval = (i << PGDIR_SHIFT) | base_pmdval;
++		pmd_t *pmd;
++
++		pmd = pmd_off(pgd, i << PGDIR_SHIFT);
++		set_pmd(pmd, __pmd(pmdval));
++		flush_pmd_entry(pmd);
++	}
++
++	local_flush_tlb_all();
++}
++
++/*
++ * Take care of architecture specific things when placing a new PTE into
++ * a page table, or changing an existing PTE.  Basically, there are two
++ * things that we need to take care of:
++ *
++ *  1. If PG_dcache_clean is not set for the page, we need to ensure
++ *     that any cache entries for the kernels virtual memory
++ *     range are written back to the page.
++ *  2. If we have multiple shared mappings of the same space in
++ *     an object, we need to deal with the cache aliasing issues.
++ *
++ * Note that the pte lock will be held.
++ */
++void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr,
++	pte_t *ptep)
++{
++	unsigned long pfn = pte_pfn(*ptep);
++	struct address_space *mapping;
++	struct page *page;
++
++	if (!pfn_valid(pfn))
++		return;
++
++	/*
++	 * The zero page is never written to, so never has any dirty
++	 * cache lines, and therefore never needs to be flushed.
++	 */
++	page = pfn_to_page(pfn);
++	if (page == ZERO_PAGE(0))
++		return;
++
++	mapping = page_mapping(page);
++	if (!test_and_set_bit(PG_dcache_clean, &page->flags))
++		__flush_dcache_page(mapping, page);
++	if (mapping)
++		if (vma->vm_flags & VM_EXEC)
++			__flush_icache_all();
++}
+diff --git a/arch/unicore32/mm/pgd.c b/arch/unicore32/mm/pgd.c
+new file mode 100644
+index 000000000000..632cef7cd378
+--- /dev/null
++++ b/arch/unicore32/mm/pgd.c
+@@ -0,0 +1,102 @@
++/*
++ * linux/arch/unicore32/mm/pgd.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++
++#include 
++#include 
++#include 
++
++#include "mm.h"
++
++#define FIRST_KERNEL_PGD_NR	(FIRST_USER_PGD_NR + USER_PTRS_PER_PGD)
++
++/*
++ * need to get a 4k page for level 1
++ */
++pgd_t *get_pgd_slow(struct mm_struct *mm)
++{
++	pgd_t *new_pgd, *init_pgd;
++	pmd_t *new_pmd, *init_pmd;
++	pte_t *new_pte, *init_pte;
++
++	new_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL, 0);
++	if (!new_pgd)
++		goto no_pgd;
++
++	memset(new_pgd, 0, FIRST_KERNEL_PGD_NR * sizeof(pgd_t));
++
++	/*
++	 * Copy over the kernel and IO PGD entries
++	 */
++	init_pgd = pgd_offset_k(0);
++	memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR,
++		       (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t));
++
++	clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t));
++
++	if (!vectors_high()) {
++		/*
++		 * On UniCore, first page must always be allocated since it
++		 * contains the machine vectors.
++		 */
++		new_pmd = pmd_alloc(mm, (pud_t *)new_pgd, 0);
++		if (!new_pmd)
++			goto no_pmd;
++
++		new_pte = pte_alloc_map(mm, new_pmd, 0);
++		if (!new_pte)
++			goto no_pte;
++
++		init_pmd = pmd_offset((pud_t *)init_pgd, 0);
++		init_pte = pte_offset_map(init_pmd, 0);
++		set_pte(new_pte, *init_pte);
++		pte_unmap(init_pte);
++		pte_unmap(new_pte);
++	}
++
++	return new_pgd;
++
++no_pte:
++	pmd_free(mm, new_pmd);
++no_pmd:
++	free_pages((unsigned long)new_pgd, 0);
++no_pgd:
++	return NULL;
++}
++
++void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd)
++{
++	pmd_t *pmd;
++	pgtable_t pte;
++
++	if (!pgd)
++		return;
++
++	/* pgd is always present and good */
++	pmd = pmd_off(pgd, 0);
++	if (pmd_none(*pmd))
++		goto free;
++	if (pmd_bad(*pmd)) {
++		pmd_ERROR(*pmd);
++		pmd_clear(pmd);
++		goto free;
++	}
++
++	pte = pmd_pgtable(*pmd);
++	pmd_clear(pmd);
++	pte_free(mm, pte);
++	pmd_free(mm, pmd);
++free:
++	free_pages((unsigned long) pgd, 0);
++}

commit b50f1704e9c441c58cf6dc05e72953ca30e1d4d2
+Author: GuanXuetao 
+Date:   Sat Jan 15 18:16:59 2011 +0800
+
+    unicore32 core architecture: mm related: generic codes
+    
+    This patch includes generic codes for memory management.
+    
+    Signed-off-by: Guan Xuetao 
+    Reviewed-by: Arnd Bergmann 
+
+diff --git a/arch/unicore32/include/asm/cache.h b/arch/unicore32/include/asm/cache.h
+new file mode 100644
+index 000000000000..ad8f795d86ca
+--- /dev/null
++++ b/arch/unicore32/include/asm/cache.h
+@@ -0,0 +1,27 @@
++/*
++ * linux/arch/unicore32/include/asm/cache.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_CACHE_H__
++#define __UNICORE_CACHE_H__
++
++#define L1_CACHE_SHIFT		(5)
++#define L1_CACHE_BYTES		(1 << L1_CACHE_SHIFT)
++
++/*
++ * Memory returned by kmalloc() may be used for DMA, so we must make
++ * sure that all such allocations are cache aligned. Otherwise,
++ * unrelated code may cause parts of the buffer to be read into the
++ * cache before the transfer is done, causing old data to be seen by
++ * the CPU.
++ */
++#define ARCH_DMA_MINALIGN	L1_CACHE_BYTES
++
++#endif
+diff --git a/arch/unicore32/include/asm/memblock.h b/arch/unicore32/include/asm/memblock.h
+new file mode 100644
+index 000000000000..a8a5d8d0a26e
+--- /dev/null
++++ b/arch/unicore32/include/asm/memblock.h
+@@ -0,0 +1,46 @@
++/*
++ * linux/arch/unicore32/include/asm/memblock.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __UNICORE_MEMBLOCK_H__
++#define __UNICORE_MEMBLOCK_H__
++
++/*
++ * Memory map description
++ */
++# define NR_BANKS 8
++
++struct membank {
++	unsigned long start;
++	unsigned long size;
++	unsigned int highmem;
++};
++
++struct meminfo {
++	int nr_banks;
++	struct membank bank[NR_BANKS];
++};
++
++extern struct meminfo meminfo;
++
++#define for_each_bank(iter, mi)				\
++	for (iter = 0; iter < (mi)->nr_banks; iter++)
++
++#define bank_pfn_start(bank)	__phys_to_pfn((bank)->start)
++#define bank_pfn_end(bank)	__phys_to_pfn((bank)->start + (bank)->size)
++#define bank_pfn_size(bank)	((bank)->size >> PAGE_SHIFT)
++#define bank_phys_start(bank)	((bank)->start)
++#define bank_phys_end(bank)	((bank)->start + (bank)->size)
++#define bank_phys_size(bank)	((bank)->size)
++
++extern void uc32_memblock_init(struct meminfo *);
++
++#endif
+diff --git a/arch/unicore32/include/asm/memory.h b/arch/unicore32/include/asm/memory.h
+new file mode 100644
+index 000000000000..5eddb997defe
+--- /dev/null
++++ b/arch/unicore32/include/asm/memory.h
+@@ -0,0 +1,123 @@
++/*
++ * linux/arch/unicore32/include/asm/memory.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ *  Note: this file should not be included by non-asm/.h files
++ */
++#ifndef __UNICORE_MEMORY_H__
++#define __UNICORE_MEMORY_H__
++
++#include 
++#include 
++#include 
++#include 
++
++/*
++ * Allow for constants defined here to be used from assembly code
++ * by prepending the UL suffix only with actual C code compilation.
++ */
++#define UL(x) _AC(x, UL)
++
++/*
++ * PAGE_OFFSET - the virtual address of the start of the kernel image
++ * TASK_SIZE - the maximum size of a user space task.
++ * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area
++ */
++#define PAGE_OFFSET		UL(0xC0000000)
++#define TASK_SIZE		(PAGE_OFFSET - UL(0x41000000))
++#define TASK_UNMAPPED_BASE	(PAGE_OFFSET / 3)
++
++/*
++ * The module space lives between the addresses given by TASK_SIZE
++ * and PAGE_OFFSET - it must be within 32MB of the kernel text.
++ */
++#define MODULES_VADDR		(PAGE_OFFSET - 16*1024*1024)
++#if TASK_SIZE > MODULES_VADDR
++#error Top of user space clashes with start of module space
++#endif
++
++#define MODULES_END		(PAGE_OFFSET)
++
++/*
++ * Allow 16MB-aligned ioremap pages
++ */
++#define IOREMAP_MAX_ORDER	24
++
++/*
++ * Physical vs virtual RAM address space conversion.  These are
++ * private definitions which should NOT be used outside memory.h
++ * files.  Use virt_to_phys/phys_to_virt/__pa/__va instead.
++ */
++#ifndef __virt_to_phys
++#define __virt_to_phys(x)	((x) - PAGE_OFFSET + PHYS_OFFSET)
++#define __phys_to_virt(x)	((x) - PHYS_OFFSET + PAGE_OFFSET)
++#endif
++
++/*
++ * Convert a physical address to a Page Frame Number and back
++ */
++#define	__phys_to_pfn(paddr)	((paddr) >> PAGE_SHIFT)
++#define	__pfn_to_phys(pfn)	((pfn) << PAGE_SHIFT)
++
++/*
++ * Convert a page to/from a physical address
++ */
++#define page_to_phys(page)	(__pfn_to_phys(page_to_pfn(page)))
++#define phys_to_page(phys)	(pfn_to_page(__phys_to_pfn(phys)))
++
++#ifndef __ASSEMBLY__
++
++#ifndef arch_adjust_zones
++#define arch_adjust_zones(size, holes) do { } while (0)
++#endif
++
++/*
++ * PFNs are used to describe any physical page; this means
++ * PFN 0 == physical address 0.
++ *
++ * This is the PFN of the first RAM page in the kernel
++ * direct-mapped view.  We assume this is the first page
++ * of RAM in the mem_map as well.
++ */
++#define PHYS_PFN_OFFSET	(PHYS_OFFSET >> PAGE_SHIFT)
++
++/*
++ * Drivers should NOT use these either.
++ */
++#define __pa(x)			__virt_to_phys((unsigned long)(x))
++#define __va(x)			((void *)__phys_to_virt((unsigned long)(x)))
++#define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
++
++/*
++ * Conversion between a struct page and a physical address.
++ *
++ * Note: when converting an unknown physical address to a
++ * struct page, the resulting pointer must be validated
++ * using VALID_PAGE().  It must return an invalid struct page
++ * for any physical address not corresponding to a system
++ * RAM address.
++ *
++ *  page_to_pfn(page)	convert a struct page * to a PFN number
++ *  pfn_to_page(pfn)	convert a _valid_ PFN number to struct page *
++ *
++ *  virt_to_page(k)	convert a _valid_ virtual address to struct page *
++ *  virt_addr_valid(k)	indicates whether a virtual address is valid
++ */
++#define ARCH_PFN_OFFSET		PHYS_PFN_OFFSET
++
++#define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
++#define virt_addr_valid(kaddr)	((unsigned long)(kaddr) >= PAGE_OFFSET && \
++		(unsigned long)(kaddr) < (unsigned long)high_memory)
++
++#endif
++
++#include 
++
++#endif
+diff --git a/arch/unicore32/include/asm/page.h b/arch/unicore32/include/asm/page.h
+new file mode 100644
+index 000000000000..594b3226250e
+--- /dev/null
++++ b/arch/unicore32/include/asm/page.h
+@@ -0,0 +1,80 @@
++/*
++ * linux/arch/unicore32/include/asm/page.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_PAGE_H__
++#define __UNICORE_PAGE_H__
++
++/* PAGE_SHIFT determines the page size */
++#define PAGE_SHIFT		12
++#define PAGE_SIZE		(_AC(1, UL) << PAGE_SHIFT)
++#define PAGE_MASK		(~(PAGE_SIZE-1))
++
++#ifndef __ASSEMBLY__
++
++struct page;
++struct vm_area_struct;
++
++#define clear_page(page)	memset((void *)(page), 0, PAGE_SIZE)
++extern void copy_page(void *to, const void *from);
++
++#define clear_user_page(page, vaddr, pg)	clear_page(page)
++#define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
++
++#undef STRICT_MM_TYPECHECKS
++
++#ifdef STRICT_MM_TYPECHECKS
++/*
++ * These are used to make use of C type-checking..
++ */
++typedef struct { unsigned long pte; } pte_t;
++typedef struct { unsigned long pgd; } pgd_t;
++typedef struct { unsigned long pgprot; } pgprot_t;
++
++#define pte_val(x)      ((x).pte)
++#define pgd_val(x)	((x).pgd)
++#define pgprot_val(x)   ((x).pgprot)
++
++#define __pte(x)        ((pte_t) { (x) })
++#define __pgd(x)	((pgd_t) { (x) })
++#define __pgprot(x)     ((pgprot_t) { (x) })
++
++#else
++/*
++ * .. while these make it easier on the compiler
++ */
++typedef unsigned long pte_t;
++typedef unsigned long pgd_t;
++typedef unsigned long pgprot_t;
++
++#define pte_val(x)      (x)
++#define pgd_val(x)      (x)
++#define pgprot_val(x)   (x)
++
++#define __pte(x)        (x)
++#define __pgd(x)	(x)
++#define __pgprot(x)     (x)
++
++#endif /* STRICT_MM_TYPECHECKS */
++
++typedef struct page *pgtable_t;
++
++extern int pfn_valid(unsigned long);
++
++#include 
++
++#endif /* !__ASSEMBLY__ */
++
++#define VM_DATA_DEFAULT_FLAGS \
++	(VM_READ | VM_WRITE | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
++
++#include 
++
++#endif
+diff --git a/arch/unicore32/include/asm/tlb.h b/arch/unicore32/include/asm/tlb.h
+new file mode 100644
+index 000000000000..02ee40e47a0d
+--- /dev/null
++++ b/arch/unicore32/include/asm/tlb.h
+@@ -0,0 +1,98 @@
++/*
++ * linux/arch/unicore32/include/asm/tlb.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_TLB_H__
++#define __UNICORE_TLB_H__
++
++#include 
++#include 
++#include 
++
++/*
++ * TLB handling.  This allows us to remove pages from the page
++ * tables, and efficiently handle the TLB issues.
++ */
++struct mmu_gather {
++	struct mm_struct	*mm;
++	unsigned int		fullmm;
++	unsigned long		range_start;
++	unsigned long		range_end;
++};
++
++DECLARE_PER_CPU(struct mmu_gather, mmu_gathers);
++
++static inline struct mmu_gather *
++tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush)
++{
++	struct mmu_gather *tlb = &get_cpu_var(mmu_gathers);
++
++	tlb->mm = mm;
++	tlb->fullmm = full_mm_flush;
++
++	return tlb;
++}
++
++static inline void
++tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
++{
++	if (tlb->fullmm)
++		flush_tlb_mm(tlb->mm);
++
++	/* keep the page table cache within bounds */
++	check_pgt_cache();
++
++	put_cpu_var(mmu_gathers);
++}
++
++/*
++ * Memorize the range for the TLB flush.
++ */
++static inline void
++tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, unsigned long addr)
++{
++	if (!tlb->fullmm) {
++		if (addr < tlb->range_start)
++			tlb->range_start = addr;
++		if (addr + PAGE_SIZE > tlb->range_end)
++			tlb->range_end = addr + PAGE_SIZE;
++	}
++}
++
++/*
++ * In the case of tlb vma handling, we can optimise these away in the
++ * case where we're doing a full MM flush.  When we're doing a munmap,
++ * the vmas are adjusted to only cover the region to be torn down.
++ */
++static inline void
++tlb_start_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
++{
++	if (!tlb->fullmm) {
++		flush_cache_range(vma, vma->vm_start, vma->vm_end);
++		tlb->range_start = TASK_SIZE;
++		tlb->range_end = 0;
++	}
++}
++
++static inline void
++tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
++{
++	if (!tlb->fullmm && tlb->range_end > 0)
++		flush_tlb_range(vma, tlb->range_start, tlb->range_end);
++}
++
++#define tlb_remove_page(tlb, page)	free_page_and_swap_cache(page)
++#define pte_free_tlb(tlb, ptep, addr)	pte_free((tlb)->mm, ptep)
++#define pmd_free_tlb(tlb, pmdp, addr)	pmd_free((tlb)->mm, pmdp)
++#define pud_free_tlb(tlb, x, addr)      do { } while (0)
++
++#define tlb_migrate_finish(mm)		do { } while (0)
++
++#endif
+diff --git a/arch/unicore32/include/mach/map.h b/arch/unicore32/include/mach/map.h
+new file mode 100644
+index 000000000000..55c936573741
+--- /dev/null
++++ b/arch/unicore32/include/mach/map.h
+@@ -0,0 +1,20 @@
++/*
++ * linux/arch/unicore32/include/mach/map.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ *  Page table mapping constructs and function prototypes
++ */
++#define MT_DEVICE		0
++#define MT_DEVICE_CACHED	2
++#define MT_KUSER		7
++#define MT_HIGH_VECTORS		8
++#define MT_MEMORY		9
++#define MT_ROM			10
++
+diff --git a/arch/unicore32/include/mach/memory.h b/arch/unicore32/include/mach/memory.h
+new file mode 100644
+index 000000000000..541949dfa5b4
+--- /dev/null
++++ b/arch/unicore32/include/mach/memory.h
+@@ -0,0 +1,58 @@
++/*
++ * linux/arch/unicore32/include/mach/memory.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __MACH_PUV3_MEMORY_H__
++#define __MACH_PUV3_MEMORY_H__
++
++#include 
++
++/* Physical DRAM offset. */
++#define PHYS_OFFSET	UL(0x00000000)
++/* The base address of exception vectors. */
++#define VECTORS_BASE	UL(0xffff0000)
++/* The base address of kuser area. */
++#define KUSER_BASE	UL(0x80000000)
++
++#ifdef __ASSEMBLY__
++/* The byte offset of the kernel image in RAM from the start of RAM. */
++#define KERNEL_IMAGE_START	0x00408000
++#endif
++
++#if !defined(__ASSEMBLY__) && defined(CONFIG_PCI)
++
++void puv3_pci_adjust_zones(unsigned long *size, unsigned long *holes);
++
++#define arch_adjust_zones(size, holes) \
++	puv3_pci_adjust_zones(size, holes)
++
++#endif
++
++/*
++ * PCI controller in PKUnity-3 masks highest 5-bit for upstream channel,
++ * so we must limit the DMA allocation within 128M physical memory for
++ * supporting PCI devices.
++ */
++#define PCI_DMA_THRESHOLD	(PHYS_OFFSET + SZ_128M - 1)
++
++#define is_pcibus_device(dev)	(dev &&			\
++				(strncmp(dev->bus->name, "pci", 3) == 0))
++
++#define __virt_to_pcibus(x)     (__virt_to_phys(x) + PKUNITY_PCIAHB_BASE)
++#define __pcibus_to_virt(x)     __phys_to_virt((x) - PKUNITY_PCIAHB_BASE)
++
++/* kuser area */
++#define KUSER_VECPAGE_BASE	(KUSER_BASE + UL(0x3fff0000))
++#define KUSER_UNIGFX_BASE	(KUSER_BASE + PKUNITY_UNIGFX_MMAP_BASE)
++/* kuser_vecpage (0xbfff0000) is ro, and vectors page (0xffff0000) is rw */
++#define kuser_vecpage_to_vectors(x)	((x) - (KUSER_VECPAGE_BASE)	\
++					+ (VECTORS_BASE))
++
++#endif
+diff --git a/arch/unicore32/mm/Kconfig b/arch/unicore32/mm/Kconfig
+new file mode 100644
+index 000000000000..5f77fb3c63be
+--- /dev/null
++++ b/arch/unicore32/mm/Kconfig
+@@ -0,0 +1,50 @@
++comment "Processor Type"
++
++# Select CPU types depending on the architecture selected.  This selects
++# which CPUs we support in the kernel image, and the compiler instruction
++# optimiser behaviour.
++
++config CPU_UCV2
++	def_bool y
++
++comment "Processor Features"
++
++config CPU_ICACHE_DISABLE
++	bool "Disable I-Cache (I-bit)"
++	help
++	  Say Y here to disable the processor instruction cache. Unless
++	  you have a reason not to or are unsure, say N.
++
++config CPU_DCACHE_DISABLE
++	bool "Disable D-Cache (D-bit)"
++	help
++	  Say Y here to disable the processor data cache. Unless
++	  you have a reason not to or are unsure, say N.
++
++config CPU_DCACHE_WRITETHROUGH
++	bool "Force write through D-cache"
++	help
++	  Say Y here to use the data cache in writethrough mode. Unless you
++	  specifically require this or are unsure, say N.
++
++config CPU_DCACHE_LINE_DISABLE
++	bool "Disable D-cache line ops"
++	default y
++	help
++	  Say Y here to disable the data cache line operations.
++
++config CPU_TLB_SINGLE_ENTRY_DISABLE
++	bool "Disable TLB single entry ops"
++	default y
++	help
++	  Say Y here to disable the TLB single entry operations.
++
++config SWIOTLB
++	def_bool y
++
++config IOMMU_HELPER
++	def_bool SWIOTLB
++
++config NEED_SG_DMA_LENGTH
++	def_bool SWIOTLB
++
+diff --git a/arch/unicore32/mm/Makefile b/arch/unicore32/mm/Makefile
+new file mode 100644
+index 000000000000..f3ff41039f51
+--- /dev/null
++++ b/arch/unicore32/mm/Makefile
+@@ -0,0 +1,15 @@
++#
++# Makefile for the linux unicore-specific parts of the memory manager.
++#
++
++obj-y				:= extable.o fault.o init.o pgd.o mmu.o
++obj-y				+= iomap.o flush.o ioremap.o
++
++obj-$(CONFIG_SWIOTLB)		+= dma-swiotlb.o
++
++obj-$(CONFIG_MODULES)		+= proc-syms.o
++
++obj-$(CONFIG_ALIGNMENT_TRAP)	+= alignment.o
++
++obj-$(CONFIG_CPU_UCV2)		+= cache-ucv2.o tlb-ucv2.o proc-ucv2.o
++
+diff --git a/arch/unicore32/mm/init.c b/arch/unicore32/mm/init.c
+new file mode 100644
+index 000000000000..3dbe3709b69d
+--- /dev/null
++++ b/arch/unicore32/mm/init.c
+@@ -0,0 +1,517 @@
++/*
++ *  linux/arch/unicore32/mm/init.c
++ *
++ *  Copyright (C) 2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include "mm.h"
++
++static unsigned long phys_initrd_start __initdata = 0x01000000;
++static unsigned long phys_initrd_size __initdata = SZ_8M;
++
++static int __init early_initrd(char *p)
++{
++	unsigned long start, size;
++	char *endp;
++
++	start = memparse(p, &endp);
++	if (*endp == ',') {
++		size = memparse(endp + 1, NULL);
++
++		phys_initrd_start = start;
++		phys_initrd_size = size;
++	}
++	return 0;
++}
++early_param("initrd", early_initrd);
++
++/*
++ * This keeps memory configuration data used by a couple memory
++ * initialization functions, as well as show_mem() for the skipping
++ * of holes in the memory map.  It is populated by uc32_add_memory().
++ */
++struct meminfo meminfo;
++
++void show_mem(void)
++{
++	int free = 0, total = 0, reserved = 0;
++	int shared = 0, cached = 0, slab = 0, i;
++	struct meminfo *mi = &meminfo;
++
++	printk(KERN_DEFAULT "Mem-info:\n");
++	show_free_areas();
++
++	for_each_bank(i, mi) {
++		struct membank *bank = &mi->bank[i];
++		unsigned int pfn1, pfn2;
++		struct page *page, *end;
++
++		pfn1 = bank_pfn_start(bank);
++		pfn2 = bank_pfn_end(bank);
++
++		page = pfn_to_page(pfn1);
++		end  = pfn_to_page(pfn2 - 1) + 1;
++
++		do {
++			total++;
++			if (PageReserved(page))
++				reserved++;
++			else if (PageSwapCache(page))
++				cached++;
++			else if (PageSlab(page))
++				slab++;
++			else if (!page_count(page))
++				free++;
++			else
++				shared += page_count(page) - 1;
++			page++;
++		} while (page < end);
++	}
++
++	printk(KERN_DEFAULT "%d pages of RAM\n", total);
++	printk(KERN_DEFAULT "%d free pages\n", free);
++	printk(KERN_DEFAULT "%d reserved pages\n", reserved);
++	printk(KERN_DEFAULT "%d slab pages\n", slab);
++	printk(KERN_DEFAULT "%d pages shared\n", shared);
++	printk(KERN_DEFAULT "%d pages swap cached\n", cached);
++}
++
++static void __init find_limits(unsigned long *min, unsigned long *max_low,
++	unsigned long *max_high)
++{
++	struct meminfo *mi = &meminfo;
++	int i;
++
++	*min = -1UL;
++	*max_low = *max_high = 0;
++
++	for_each_bank(i, mi) {
++		struct membank *bank = &mi->bank[i];
++		unsigned long start, end;
++
++		start = bank_pfn_start(bank);
++		end = bank_pfn_end(bank);
++
++		if (*min > start)
++			*min = start;
++		if (*max_high < end)
++			*max_high = end;
++		if (bank->highmem)
++			continue;
++		if (*max_low < end)
++			*max_low = end;
++	}
++}
++
++static void __init uc32_bootmem_init(unsigned long start_pfn,
++	unsigned long end_pfn)
++{
++	struct memblock_region *reg;
++	unsigned int boot_pages;
++	phys_addr_t bitmap;
++	pg_data_t *pgdat;
++
++	/*
++	 * Allocate the bootmem bitmap page.  This must be in a region
++	 * of memory which has already been mapped.
++	 */
++	boot_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
++	bitmap = memblock_alloc_base(boot_pages << PAGE_SHIFT, L1_CACHE_BYTES,
++				__pfn_to_phys(end_pfn));
++
++	/*
++	 * Initialise the bootmem allocator, handing the
++	 * memory banks over to bootmem.
++	 */
++	node_set_online(0);
++	pgdat = NODE_DATA(0);
++	init_bootmem_node(pgdat, __phys_to_pfn(bitmap), start_pfn, end_pfn);
++
++	/* Free the lowmem regions from memblock into bootmem. */
++	for_each_memblock(memory, reg) {
++		unsigned long start = memblock_region_memory_base_pfn(reg);
++		unsigned long end = memblock_region_memory_end_pfn(reg);
++
++		if (end >= end_pfn)
++			end = end_pfn;
++		if (start >= end)
++			break;
++
++		free_bootmem(__pfn_to_phys(start), (end - start) << PAGE_SHIFT);
++	}
++
++	/* Reserve the lowmem memblock reserved regions in bootmem. */
++	for_each_memblock(reserved, reg) {
++		unsigned long start = memblock_region_reserved_base_pfn(reg);
++		unsigned long end = memblock_region_reserved_end_pfn(reg);
++
++		if (end >= end_pfn)
++			end = end_pfn;
++		if (start >= end)
++			break;
++
++		reserve_bootmem(__pfn_to_phys(start),
++			(end - start) << PAGE_SHIFT, BOOTMEM_DEFAULT);
++	}
++}
++
++static void __init uc32_bootmem_free(unsigned long min, unsigned long max_low,
++	unsigned long max_high)
++{
++	unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
++	struct memblock_region *reg;
++
++	/*
++	 * initialise the zones.
++	 */
++	memset(zone_size, 0, sizeof(zone_size));
++
++	/*
++	 * The memory size has already been determined.  If we need
++	 * to do anything fancy with the allocation of this memory
++	 * to the zones, now is the time to do it.
++	 */
++	zone_size[0] = max_low - min;
++
++	/*
++	 * Calculate the size of the holes.
++	 *  holes = node_size - sum(bank_sizes)
++	 */
++	memcpy(zhole_size, zone_size, sizeof(zhole_size));
++	for_each_memblock(memory, reg) {
++		unsigned long start = memblock_region_memory_base_pfn(reg);
++		unsigned long end = memblock_region_memory_end_pfn(reg);
++
++		if (start < max_low) {
++			unsigned long low_end = min(end, max_low);
++			zhole_size[0] -= low_end - start;
++		}
++	}
++
++	/*
++	 * Adjust the sizes according to any special requirements for
++	 * this machine type.
++	 */
++	arch_adjust_zones(zone_size, zhole_size);
++
++	free_area_init_node(0, zone_size, min, zhole_size);
++}
++
++int pfn_valid(unsigned long pfn)
++{
++	return memblock_is_memory(pfn << PAGE_SHIFT);
++}
++EXPORT_SYMBOL(pfn_valid);
++
++static void uc32_memory_present(void)
++{
++}
++
++static int __init meminfo_cmp(const void *_a, const void *_b)
++{
++	const struct membank *a = _a, *b = _b;
++	long cmp = bank_pfn_start(a) - bank_pfn_start(b);
++	return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
++}
++
++void __init uc32_memblock_init(struct meminfo *mi)
++{
++	int i;
++
++	sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]),
++		meminfo_cmp, NULL);
++
++	memblock_init();
++	for (i = 0; i < mi->nr_banks; i++)
++		memblock_add(mi->bank[i].start, mi->bank[i].size);
++
++	/* Register the kernel text, kernel data and initrd with memblock. */
++	memblock_reserve(__pa(_text), _end - _text);
++
++#ifdef CONFIG_BLK_DEV_INITRD
++	if (phys_initrd_size) {
++		memblock_reserve(phys_initrd_start, phys_initrd_size);
++
++		/* Now convert initrd to virtual addresses */
++		initrd_start = __phys_to_virt(phys_initrd_start);
++		initrd_end = initrd_start + phys_initrd_size;
++	}
++#endif
++
++	uc32_mm_memblock_reserve();
++
++	memblock_analyze();
++	memblock_dump_all();
++}
++
++void __init bootmem_init(void)
++{
++	unsigned long min, max_low, max_high;
++
++	max_low = max_high = 0;
++
++	find_limits(&min, &max_low, &max_high);
++
++	uc32_bootmem_init(min, max_low);
++
++#ifdef CONFIG_SWIOTLB
++	swiotlb_init(1);
++#endif
++	/*
++	 * Sparsemem tries to allocate bootmem in memory_present(),
++	 * so must be done after the fixed reservations
++	 */
++	uc32_memory_present();
++
++	/*
++	 * sparse_init() needs the bootmem allocator up and running.
++	 */
++	sparse_init();
++
++	/*
++	 * Now free the memory - free_area_init_node needs
++	 * the sparse mem_map arrays initialized by sparse_init()
++	 * for memmap_init_zone(), otherwise all PFNs are invalid.
++	 */
++	uc32_bootmem_free(min, max_low, max_high);
++
++	high_memory = __va((max_low << PAGE_SHIFT) - 1) + 1;
++
++	/*
++	 * This doesn't seem to be used by the Linux memory manager any
++	 * more, but is used by ll_rw_block.  If we can get rid of it, we
++	 * also get rid of some of the stuff above as well.
++	 *
++	 * Note: max_low_pfn and max_pfn reflect the number of _pages_ in
++	 * the system, not the maximum PFN.
++	 */
++	max_low_pfn = max_low - PHYS_PFN_OFFSET;
++	max_pfn = max_high - PHYS_PFN_OFFSET;
++}
++
++static inline int free_area(unsigned long pfn, unsigned long end, char *s)
++{
++	unsigned int pages = 0, size = (end - pfn) << (PAGE_SHIFT - 10);
++
++	for (; pfn < end; pfn++) {
++		struct page *page = pfn_to_page(pfn);
++		ClearPageReserved(page);
++		init_page_count(page);
++		__free_page(page);
++		pages++;
++	}
++
++	if (size && s)
++		printk(KERN_INFO "Freeing %s memory: %dK\n", s, size);
++
++	return pages;
++}
++
++static inline void
++free_memmap(unsigned long start_pfn, unsigned long end_pfn)
++{
++	struct page *start_pg, *end_pg;
++	unsigned long pg, pgend;
++
++	/*
++	 * Convert start_pfn/end_pfn to a struct page pointer.
++	 */
++	start_pg = pfn_to_page(start_pfn - 1) + 1;
++	end_pg = pfn_to_page(end_pfn);
++
++	/*
++	 * Convert to physical addresses, and
++	 * round start upwards and end downwards.
++	 */
++	pg = PAGE_ALIGN(__pa(start_pg));
++	pgend = __pa(end_pg) & PAGE_MASK;
++
++	/*
++	 * If there are free pages between these,
++	 * free the section of the memmap array.
++	 */
++	if (pg < pgend)
++		free_bootmem(pg, pgend - pg);
++}
++
++/*
++ * The mem_map array can get very big.  Free the unused area of the memory map.
++ */
++static void __init free_unused_memmap(struct meminfo *mi)
++{
++	unsigned long bank_start, prev_bank_end = 0;
++	unsigned int i;
++
++	/*
++	 * This relies on each bank being in address order.
++	 * The banks are sorted previously in bootmem_init().
++	 */
++	for_each_bank(i, mi) {
++		struct membank *bank = &mi->bank[i];
++
++		bank_start = bank_pfn_start(bank);
++
++		/*
++		 * If we had a previous bank, and there is a space
++		 * between the current bank and the previous, free it.
++		 */
++		if (prev_bank_end && prev_bank_end < bank_start)
++			free_memmap(prev_bank_end, bank_start);
++
++		/*
++		 * Align up here since the VM subsystem insists that the
++		 * memmap entries are valid from the bank end aligned to
++		 * MAX_ORDER_NR_PAGES.
++		 */
++		prev_bank_end = ALIGN(bank_pfn_end(bank), MAX_ORDER_NR_PAGES);
++	}
++}
++
++/*
++ * mem_init() marks the free areas in the mem_map and tells us how much
++ * memory is free.  This is done after various parts of the system have
++ * claimed their memory after the kernel image.
++ */
++void __init mem_init(void)
++{
++	unsigned long reserved_pages, free_pages;
++	struct memblock_region *reg;
++	int i;
++
++	max_mapnr   = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map;
++
++	/* this will put all unused low memory onto the freelists */
++	free_unused_memmap(&meminfo);
++
++	totalram_pages += free_all_bootmem();
++
++	reserved_pages = free_pages = 0;
++
++	for_each_bank(i, &meminfo) {
++		struct membank *bank = &meminfo.bank[i];
++		unsigned int pfn1, pfn2;
++		struct page *page, *end;
++
++		pfn1 = bank_pfn_start(bank);
++		pfn2 = bank_pfn_end(bank);
++
++		page = pfn_to_page(pfn1);
++		end  = pfn_to_page(pfn2 - 1) + 1;
++
++		do {
++			if (PageReserved(page))
++				reserved_pages++;
++			else if (!page_count(page))
++				free_pages++;
++			page++;
++		} while (page < end);
++	}
++
++	/*
++	 * Since our memory may not be contiguous, calculate the
++	 * real number of pages we have in this system
++	 */
++	printk(KERN_INFO "Memory:");
++	num_physpages = 0;
++	for_each_memblock(memory, reg) {
++		unsigned long pages = memblock_region_memory_end_pfn(reg) -
++			memblock_region_memory_base_pfn(reg);
++		num_physpages += pages;
++		printk(" %ldMB", pages >> (20 - PAGE_SHIFT));
++	}
++	printk(" = %luMB total\n", num_physpages >> (20 - PAGE_SHIFT));
++
++	printk(KERN_NOTICE "Memory: %luk/%luk available, %luk reserved, %luK highmem\n",
++		nr_free_pages() << (PAGE_SHIFT-10),
++		free_pages << (PAGE_SHIFT-10),
++		reserved_pages << (PAGE_SHIFT-10),
++		totalhigh_pages << (PAGE_SHIFT-10));
++
++	printk(KERN_NOTICE "Virtual kernel memory layout:\n"
++		"    vector  : 0x%08lx - 0x%08lx   (%4ld kB)\n"
++		"    vmalloc : 0x%08lx - 0x%08lx   (%4ld MB)\n"
++		"    lowmem  : 0x%08lx - 0x%08lx   (%4ld MB)\n"
++		"    modules : 0x%08lx - 0x%08lx   (%4ld MB)\n"
++		"      .init : 0x%p" " - 0x%p" "   (%4d kB)\n"
++		"      .text : 0x%p" " - 0x%p" "   (%4d kB)\n"
++		"      .data : 0x%p" " - 0x%p" "   (%4d kB)\n",
++
++		VECTORS_BASE, VECTORS_BASE + PAGE_SIZE,
++		DIV_ROUND_UP(PAGE_SIZE, SZ_1K),
++		VMALLOC_START, VMALLOC_END,
++		DIV_ROUND_UP((VMALLOC_END - VMALLOC_START), SZ_1M),
++		PAGE_OFFSET, (unsigned long)high_memory,
++		DIV_ROUND_UP(((unsigned long)high_memory - PAGE_OFFSET), SZ_1M),
++		MODULES_VADDR, MODULES_END,
++		DIV_ROUND_UP((MODULES_END - MODULES_VADDR), SZ_1M),
++
++		__init_begin, __init_end,
++		DIV_ROUND_UP((__init_end - __init_begin), SZ_1K),
++		_stext, _etext,
++		DIV_ROUND_UP((_etext - _stext), SZ_1K),
++		_sdata, _edata,
++		DIV_ROUND_UP((_edata - _sdata), SZ_1K));
++
++	BUILD_BUG_ON(TASK_SIZE				> MODULES_VADDR);
++	BUG_ON(TASK_SIZE				> MODULES_VADDR);
++
++	if (PAGE_SIZE >= 16384 && num_physpages <= 128) {
++		/*
++		 * On a machine this small we won't get
++		 * anywhere without overcommit, so turn
++		 * it on by default.
++		 */
++		sysctl_overcommit_memory = OVERCOMMIT_ALWAYS;
++	}
++}
++
++void free_initmem(void)
++{
++	totalram_pages += free_area(__phys_to_pfn(__pa(__init_begin)),
++				    __phys_to_pfn(__pa(__init_end)),
++				    "init");
++}
++
++#ifdef CONFIG_BLK_DEV_INITRD
++
++static int keep_initrd;
++
++void free_initrd_mem(unsigned long start, unsigned long end)
++{
++	if (!keep_initrd)
++		totalram_pages += free_area(__phys_to_pfn(__pa(start)),
++					    __phys_to_pfn(__pa(end)),
++					    "initrd");
++}
++
++static int __init keepinitrd_setup(char *__unused)
++{
++	keep_initrd = 1;
++	return 1;
++}
++
++__setup("keepinitrd", keepinitrd_setup);
++#endif
+diff --git a/arch/unicore32/mm/iomap.c b/arch/unicore32/mm/iomap.c
+new file mode 100644
+index 000000000000..a7e1a3d2e069
+--- /dev/null
++++ b/arch/unicore32/mm/iomap.c
+@@ -0,0 +1,56 @@
++/*
++ * linux/arch/unicore32/mm/iomap.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * Map IO port and PCI memory spaces so that {read,write}[bwl] can
++ * be used to access this memory.
++ */
++#include 
++#include 
++#include 
++#include 
++
++#ifdef __io
++void __iomem *ioport_map(unsigned long port, unsigned int nr)
++{
++	/* we map PC lagcy 64K IO port to PCI IO space 0x80030000 */
++	return (void __iomem *) (unsigned long)
++			io_p2v((port & 0xffff) + PKUNITY_PCILIO_BASE);
++}
++EXPORT_SYMBOL(ioport_map);
++
++void ioport_unmap(void __iomem *addr)
++{
++}
++EXPORT_SYMBOL(ioport_unmap);
++#endif
++
++#ifdef CONFIG_PCI
++void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
++{
++	resource_size_t start = pci_resource_start(dev, bar);
++	resource_size_t len   = pci_resource_len(dev, bar);
++	unsigned long flags = pci_resource_flags(dev, bar);
++
++	if (!len || !start)
++		return NULL;
++	if (maxlen && len > maxlen)
++		len = maxlen;
++	if (flags & IORESOURCE_IO)
++		return ioport_map(start, len);
++	if (flags & IORESOURCE_MEM) {
++		if (flags & IORESOURCE_CACHEABLE)
++			return ioremap(start, len);
++		return ioremap_nocache(start, len);
++	}
++	return NULL;
++}
++EXPORT_SYMBOL(pci_iomap);
++#endif
+diff --git a/arch/unicore32/mm/ioremap.c b/arch/unicore32/mm/ioremap.c
+new file mode 100644
+index 000000000000..b7a605597b08
+--- /dev/null
++++ b/arch/unicore32/mm/ioremap.c
+@@ -0,0 +1,261 @@
++/*
++ * linux/arch/unicore32/mm/ioremap.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ *
++ * Re-map IO memory to kernel address space so that we can access it.
++ *
++ * This allows a driver to remap an arbitrary region of bus memory into
++ * virtual space.  One should *only* use readl, writel, memcpy_toio and
++ * so on with such remapped areas.
++ *
++ * Because UniCore only has a 32-bit address space we can't address the
++ * whole of the (physical) PCI space at once.  PCI huge-mode addressing
++ * allows us to circumvent this restriction by splitting PCI space into
++ * two 2GB chunks and mapping only one at a time into processor memory.
++ * We use MMU protection domains to trap any attempt to access the bank
++ * that is not currently mapped.  (This isn't fully implemented yet.)
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++#include "mm.h"
++
++/*
++ * Used by ioremap() and iounmap() code to mark (super)section-mapped
++ * I/O regions in vm_struct->flags field.
++ */
++#define VM_UNICORE_SECTION_MAPPING	0x80000000
++
++int ioremap_page(unsigned long virt, unsigned long phys,
++		 const struct mem_type *mtype)
++{
++	return ioremap_page_range(virt, virt + PAGE_SIZE, phys,
++				  __pgprot(mtype->prot_pte));
++}
++EXPORT_SYMBOL(ioremap_page);
++
++/*
++ * Section support is unsafe on SMP - If you iounmap and ioremap a region,
++ * the other CPUs will not see this change until their next context switch.
++ * Meanwhile, (eg) if an interrupt comes in on one of those other CPUs
++ * which requires the new ioremap'd region to be referenced, the CPU will
++ * reference the _old_ region.
++ *
++ * Note that get_vm_area_caller() allocates a guard 4K page, so we need to
++ * mask the size back to 4MB aligned or we will overflow in the loop below.
++ */
++static void unmap_area_sections(unsigned long virt, unsigned long size)
++{
++	unsigned long addr = virt, end = virt + (size & ~(SZ_4M - 1));
++	pgd_t *pgd;
++
++	flush_cache_vunmap(addr, end);
++	pgd = pgd_offset_k(addr);
++	do {
++		pmd_t pmd, *pmdp = pmd_offset((pud_t *)pgd, addr);
++
++		pmd = *pmdp;
++		if (!pmd_none(pmd)) {
++			/*
++			 * Clear the PMD from the page table, and
++			 * increment the kvm sequence so others
++			 * notice this change.
++			 *
++			 * Note: this is still racy on SMP machines.
++			 */
++			pmd_clear(pmdp);
++
++			/*
++			 * Free the page table, if there was one.
++			 */
++			if ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_TABLE)
++				pte_free_kernel(&init_mm, pmd_page_vaddr(pmd));
++		}
++
++		addr += PGDIR_SIZE;
++		pgd++;
++	} while (addr < end);
++
++	flush_tlb_kernel_range(virt, end);
++}
++
++static int
++remap_area_sections(unsigned long virt, unsigned long pfn,
++		    size_t size, const struct mem_type *type)
++{
++	unsigned long addr = virt, end = virt + size;
++	pgd_t *pgd;
++
++	/*
++	 * Remove and free any PTE-based mapping, and
++	 * sync the current kernel mapping.
++	 */
++	unmap_area_sections(virt, size);
++
++	pgd = pgd_offset_k(addr);
++	do {
++		pmd_t *pmd = pmd_offset((pud_t *)pgd, addr);
++
++		set_pmd(pmd, __pmd(__pfn_to_phys(pfn) | type->prot_sect));
++		pfn += SZ_4M >> PAGE_SHIFT;
++		flush_pmd_entry(pmd);
++
++		addr += PGDIR_SIZE;
++		pgd++;
++	} while (addr < end);
++
++	return 0;
++}
++
++void __iomem *__uc32_ioremap_pfn_caller(unsigned long pfn,
++	unsigned long offset, size_t size, unsigned int mtype, void *caller)
++{
++	const struct mem_type *type;
++	int err;
++	unsigned long addr;
++	struct vm_struct *area;
++
++	/*
++	 * High mappings must be section aligned
++	 */
++	if (pfn >= 0x100000 && (__pfn_to_phys(pfn) & ~SECTION_MASK))
++		return NULL;
++
++	/*
++	 * Don't allow RAM to be mapped
++	 */
++	if (pfn_valid(pfn)) {
++		printk(KERN_WARNING "BUG: Your driver calls ioremap() on\n"
++			"system memory.  This leads to architecturally\n"
++			"unpredictable behaviour, and ioremap() will fail in\n"
++			"the next kernel release. Please fix your driver.\n");
++		WARN_ON(1);
++	}
++
++	type = get_mem_type(mtype);
++	if (!type)
++		return NULL;
++
++	/*
++	 * Page align the mapping size, taking account of any offset.
++	 */
++	size = PAGE_ALIGN(offset + size);
++
++	area = get_vm_area_caller(size, VM_IOREMAP, caller);
++	if (!area)
++		return NULL;
++	addr = (unsigned long)area->addr;
++
++	if (!((__pfn_to_phys(pfn) | size | addr) & ~PMD_MASK)) {
++		area->flags |= VM_UNICORE_SECTION_MAPPING;
++		err = remap_area_sections(addr, pfn, size, type);
++	} else
++		err = ioremap_page_range(addr, addr + size, __pfn_to_phys(pfn),
++					 __pgprot(type->prot_pte));
++
++	if (err) {
++		vunmap((void *)addr);
++		return NULL;
++	}
++
++	flush_cache_vmap(addr, addr + size);
++	return (void __iomem *) (offset + addr);
++}
++
++void __iomem *__uc32_ioremap_caller(unsigned long phys_addr, size_t size,
++	unsigned int mtype, void *caller)
++{
++	unsigned long last_addr;
++	unsigned long offset = phys_addr & ~PAGE_MASK;
++	unsigned long pfn = __phys_to_pfn(phys_addr);
++
++	/*
++	 * Don't allow wraparound or zero size
++	 */
++	last_addr = phys_addr + size - 1;
++	if (!size || last_addr < phys_addr)
++		return NULL;
++
++	return __uc32_ioremap_pfn_caller(pfn, offset, size, mtype, caller);
++}
++
++/*
++ * Remap an arbitrary physical address space into the kernel virtual
++ * address space. Needed when the kernel wants to access high addresses
++ * directly.
++ *
++ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
++ * have to convert them into an offset in a page-aligned mapping, but the
++ * caller shouldn't need to know that small detail.
++ */
++void __iomem *
++__uc32_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
++		  unsigned int mtype)
++{
++	return __uc32_ioremap_pfn_caller(pfn, offset, size, mtype,
++			__builtin_return_address(0));
++}
++EXPORT_SYMBOL(__uc32_ioremap_pfn);
++
++void __iomem *
++__uc32_ioremap(unsigned long phys_addr, size_t size)
++{
++	return __uc32_ioremap_caller(phys_addr, size, MT_DEVICE,
++			__builtin_return_address(0));
++}
++EXPORT_SYMBOL(__uc32_ioremap);
++
++void __iomem *
++__uc32_ioremap_cached(unsigned long phys_addr, size_t size)
++{
++	return __uc32_ioremap_caller(phys_addr, size, MT_DEVICE_CACHED,
++			__builtin_return_address(0));
++}
++EXPORT_SYMBOL(__uc32_ioremap_cached);
++
++void __uc32_iounmap(volatile void __iomem *io_addr)
++{
++	void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr);
++	struct vm_struct **p, *tmp;
++
++	/*
++	 * If this is a section based mapping we need to handle it
++	 * specially as the VM subsystem does not know how to handle
++	 * such a beast. We need the lock here b/c we need to clear
++	 * all the mappings before the area can be reclaimed
++	 * by someone else.
++	 */
++	write_lock(&vmlist_lock);
++	for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) {
++		if ((tmp->flags & VM_IOREMAP) && (tmp->addr == addr)) {
++			if (tmp->flags & VM_UNICORE_SECTION_MAPPING) {
++				unmap_area_sections((unsigned long)tmp->addr,
++						    tmp->size);
++			}
++			break;
++		}
++	}
++	write_unlock(&vmlist_lock);
++
++	vunmap(addr);
++}
++EXPORT_SYMBOL(__uc32_iounmap);
+diff --git a/arch/unicore32/mm/mm.h b/arch/unicore32/mm/mm.h
+new file mode 100644
+index 000000000000..3296bca0f1f7
+--- /dev/null
++++ b/arch/unicore32/mm/mm.h
+@@ -0,0 +1,39 @@
++/*
++ * linux/arch/unicore32/mm/mm.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++/* the upper-most page table pointer */
++extern pmd_t *top_pmd;
++extern int sysctl_overcommit_memory;
++
++#define TOP_PTE(x)	pte_offset_kernel(top_pmd, x)
++
++static inline pmd_t *pmd_off(pgd_t *pgd, unsigned long virt)
++{
++	return pmd_offset((pud_t *)pgd, virt);
++}
++
++static inline pmd_t *pmd_off_k(unsigned long virt)
++{
++	return pmd_off(pgd_offset_k(virt), virt);
++}
++
++struct mem_type {
++	unsigned int prot_pte;
++	unsigned int prot_l1;
++	unsigned int prot_sect;
++};
++
++const struct mem_type *get_mem_type(unsigned int type);
++
++extern void __flush_dcache_page(struct address_space *, struct page *);
++
++void __init bootmem_init(void);
++void uc32_mm_memblock_reserve(void);

commit f73670e8a55c11d47c28dca35dc4bc7dfbd4e6eb
+Author: GuanXuetao 
+Date:   Sat Jan 15 18:16:21 2011 +0800
+
+    unicore32 core architecture: process/thread related codes
+    
+    This patch implements process/thread related codes. Backtrace and stacktrace are here.
+    
+    Signed-off-by: Guan Xuetao 
+    Reviewed-by: Arnd Bergmann 
+
+diff --git a/arch/unicore32/include/asm/stacktrace.h b/arch/unicore32/include/asm/stacktrace.h
+new file mode 100644
+index 000000000000..76edc65a5871
+--- /dev/null
++++ b/arch/unicore32/include/asm/stacktrace.h
+@@ -0,0 +1,31 @@
++/*
++ * linux/arch/unicore32/include/asm/stacktrace.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __UNICORE_STACKTRACE_H__
++#define __UNICORE_STACKTRACE_H__
++
++struct stackframe {
++	unsigned long fp;
++	unsigned long sp;
++	unsigned long lr;
++	unsigned long pc;
++};
++
++#ifdef CONFIG_FRAME_POINTER
++extern int unwind_frame(struct stackframe *frame);
++#else
++#define unwind_frame(f) (-EINVAL)
++#endif
++extern void walk_stackframe(struct stackframe *frame,
++			    int (*fn)(struct stackframe *, void *), void *data);
++
++#endif	/* __UNICORE_STACKTRACE_H__ */
+diff --git a/arch/unicore32/include/asm/thread_info.h b/arch/unicore32/include/asm/thread_info.h
+new file mode 100644
+index 000000000000..c270e9e04861
+--- /dev/null
++++ b/arch/unicore32/include/asm/thread_info.h
+@@ -0,0 +1,154 @@
++/*
++ * linux/arch/unicore32/include/asm/thread_info.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_THREAD_INFO_H__
++#define __UNICORE_THREAD_INFO_H__
++
++#ifdef __KERNEL__
++
++#include 
++#include 
++
++#define THREAD_SIZE_ORDER	1
++#define THREAD_SIZE		8192
++#define THREAD_START_SP		(THREAD_SIZE - 8)
++
++#ifndef __ASSEMBLY__
++
++struct task_struct;
++struct exec_domain;
++
++#include 
++
++typedef struct {
++	unsigned long seg;
++} mm_segment_t;
++
++struct cpu_context_save {
++	__u32	r4;
++	__u32	r5;
++	__u32	r6;
++	__u32	r7;
++	__u32	r8;
++	__u32	r9;
++	__u32	r10;
++	__u32	r11;
++	__u32	r12;
++	__u32	r13;
++	__u32	r14;
++	__u32	r15;
++	__u32	r16;
++	__u32	r17;
++	__u32	r18;
++	__u32	r19;
++	__u32	r20;
++	__u32	r21;
++	__u32	r22;
++	__u32	r23;
++	__u32	r24;
++	__u32	r25;
++	__u32	r26;
++	__u32	fp;
++	__u32	sp;
++	__u32	pc;
++};
++
++/*
++ * low level task data that entry.S needs immediate access to.
++ * __switch_to() assumes cpu_context follows immediately after cpu_domain.
++ */
++struct thread_info {
++	unsigned long		flags;		/* low level flags */
++	int			preempt_count;	/* 0 => preemptable */
++						/* <0 => bug */
++	mm_segment_t		addr_limit;	/* address limit */
++	struct task_struct	*task;		/* main task structure */
++	struct exec_domain	*exec_domain;	/* execution domain */
++	__u32			cpu;		/* cpu */
++	struct cpu_context_save	cpu_context;	/* cpu context */
++	__u32			syscall;	/* syscall number */
++	__u8			used_cp[16];	/* thread used copro */
++#ifdef CONFIG_UNICORE_FPU_F64
++	struct fp_state		fpstate __attribute__((aligned(8)));
++#endif
++	struct restart_block	restart_block;
++};
++
++#define INIT_THREAD_INFO(tsk)						\
++{									\
++	.task		= &tsk,						\
++	.exec_domain	= &default_exec_domain,				\
++	.flags		= 0,						\
++	.preempt_count	= INIT_PREEMPT_COUNT,				\
++	.addr_limit	= KERNEL_DS,					\
++	.restart_block	= {						\
++		.fn	= do_no_restart_syscall,			\
++	},								\
++}
++
++#define init_thread_info	(init_thread_union.thread_info)
++#define init_stack		(init_thread_union.stack)
++
++/*
++ * how to get the thread information struct from C
++ */
++static inline struct thread_info *current_thread_info(void) __attribute_const__;
++
++static inline struct thread_info *current_thread_info(void)
++{
++	register unsigned long sp asm ("sp");
++	return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));
++}
++
++#define thread_saved_pc(tsk)	\
++	((unsigned long)(task_thread_info(tsk)->cpu_context.pc))
++#define thread_saved_sp(tsk)	\
++	((unsigned long)(task_thread_info(tsk)->cpu_context.sp))
++#define thread_saved_fp(tsk)	\
++	((unsigned long)(task_thread_info(tsk)->cpu_context.fp))
++
++#endif
++
++/*
++ * We use bit 30 of the preempt_count to indicate that kernel
++ * preemption is occurring.  See .
++ */
++#define PREEMPT_ACTIVE	0x40000000
++
++/*
++ * thread information flags:
++ *  TIF_SYSCALL_TRACE	- syscall trace active
++ *  TIF_SIGPENDING	- signal pending
++ *  TIF_NEED_RESCHED	- rescheduling necessary
++ *  TIF_NOTIFY_RESUME	- callback before returning to user
++ */
++#define TIF_SIGPENDING		0
++#define TIF_NEED_RESCHED	1
++#define TIF_NOTIFY_RESUME	2	/* callback before returning to user */
++#define TIF_SYSCALL_TRACE	8
++#define TIF_MEMDIE		18
++#define TIF_FREEZE		19
++#define TIF_RESTORE_SIGMASK	20
++
++#define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
++#define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
++#define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
++#define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
++#define _TIF_FREEZE		(1 << TIF_FREEZE)
++#define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
++
++/*
++ * Change these and you break ASM code in entry-common.S
++ */
++#define _TIF_WORK_MASK		0x000000ff
++
++#endif /* __KERNEL__ */
++#endif /* __UNICORE_THREAD_INFO_H__ */
+diff --git a/arch/unicore32/kernel/init_task.c b/arch/unicore32/kernel/init_task.c
+new file mode 100644
+index 000000000000..a35a1e50e4f4
+--- /dev/null
++++ b/arch/unicore32/kernel/init_task.c
+@@ -0,0 +1,44 @@
++/*
++ * linux/arch/unicore32/kernel/init_task.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++
++static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
++static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
++/*
++ * Initial thread structure.
++ *
++ * We need to make sure that this is 8192-byte aligned due to the
++ * way process stacks are handled. This is done by making sure
++ * the linker maps this in the .text segment right after head.S,
++ * and making head.S ensure the proper alignment.
++ *
++ * The things we do for performance..
++ */
++union thread_union init_thread_union __init_task_data = {
++	INIT_THREAD_INFO(init_task) };
++
++/*
++ * Initial task structure.
++ *
++ * All other task structs will be allocated on slabs in fork.c
++ */
++struct task_struct init_task = INIT_TASK(init_task);
++EXPORT_SYMBOL(init_task);
+diff --git a/arch/unicore32/kernel/process.c b/arch/unicore32/kernel/process.c
+new file mode 100644
+index 000000000000..8d4a273ae086
+--- /dev/null
++++ b/arch/unicore32/kernel/process.c
+@@ -0,0 +1,389 @@
++/*
++ * linux/arch/unicore32/kernel/process.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++#include 
++#include 
++#include 
++
++#include "setup.h"
++
++static const char * const processor_modes[] = {
++	"UK00", "UK01", "UK02", "UK03", "UK04", "UK05", "UK06", "UK07",
++	"UK08", "UK09", "UK0A", "UK0B", "UK0C", "UK0D", "UK0E", "UK0F",
++	"USER", "REAL", "INTR", "PRIV", "UK14", "UK15", "UK16", "ABRT",
++	"UK18", "UK19", "UK1A", "EXTN", "UK1C", "UK1D", "UK1E", "SUSR"
++};
++
++/*
++ * The idle thread, has rather strange semantics for calling pm_idle,
++ * but this is what x86 does and we need to do the same, so that
++ * things like cpuidle get called in the same way.
++ */
++void cpu_idle(void)
++{
++	/* endless idle loop with no priority at all */
++	while (1) {
++		tick_nohz_stop_sched_tick(1);
++		while (!need_resched()) {
++			local_irq_disable();
++			stop_critical_timings();
++			cpu_do_idle();
++			local_irq_enable();
++			start_critical_timings();
++		}
++		tick_nohz_restart_sched_tick();
++		preempt_enable_no_resched();
++		schedule();
++		preempt_disable();
++	}
++}
++
++static char reboot_mode = 'h';
++
++int __init reboot_setup(char *str)
++{
++	reboot_mode = str[0];
++	return 1;
++}
++
++__setup("reboot=", reboot_setup);
++
++void machine_halt(void)
++{
++	gpio_set_value(GPO_SOFT_OFF, 0);
++}
++
++/*
++ * Function pointers to optional machine specific functions
++ */
++void (*pm_power_off)(void) = NULL;
++
++void machine_power_off(void)
++{
++	if (pm_power_off)
++		pm_power_off();
++	machine_halt();
++}
++
++void machine_restart(char *cmd)
++{
++	/* Disable interrupts first */
++	local_irq_disable();
++
++	/*
++	 * Tell the mm system that we are going to reboot -
++	 * we may need it to insert some 1:1 mappings so that
++	 * soft boot works.
++	 */
++	setup_mm_for_reboot(reboot_mode);
++
++	/* Clean and invalidate caches */
++	flush_cache_all();
++
++	/* Turn off caching */
++	cpu_proc_fin();
++
++	/* Push out any further dirty data, and ensure cache is empty */
++	flush_cache_all();
++
++	/*
++	 * Now handle reboot code.
++	 */
++	if (reboot_mode == 's') {
++		/* Jump into ROM at address 0xffff0000 */
++		cpu_reset(VECTORS_BASE);
++	} else {
++		PM_PLLSYSCFG = 0x00002001; /* cpu clk = 250M */
++		PM_PLLDDRCFG = 0x00100800; /* ddr clk =  44M */
++		PM_PLLVGACFG = 0x00002001; /* vga clk = 250M */
++
++		/* Use on-chip reset capability */
++		/* following instructions must be in one icache line */
++		__asm__ __volatile__(
++			"	.align 5\n\t"
++			"	stw	%1, [%0]\n\t"
++			"201:	ldw	r0, [%0]\n\t"
++			"	cmpsub.a	r0, #0\n\t"
++			"	bne	201b\n\t"
++			"	stw	%3, [%2]\n\t"
++			"	nop; nop; nop\n\t"
++			/* prefetch 3 instructions at most */
++			:
++			: "r" ((unsigned long)&PM_PMCR),
++			  "r" (PM_PMCR_CFBSYS | PM_PMCR_CFBDDR
++				| PM_PMCR_CFBVGA),
++			  "r" ((unsigned long)&RESETC_SWRR),
++			  "r" (RESETC_SWRR_SRB)
++			: "r0", "memory");
++	}
++
++	/*
++	 * Whoops - the architecture was unable to reboot.
++	 * Tell the user!
++	 */
++	mdelay(1000);
++	printk(KERN_EMERG "Reboot failed -- System halted\n");
++	do { } while (1);
++}
++
++void __show_regs(struct pt_regs *regs)
++{
++	unsigned long flags;
++	char buf[64];
++
++	printk(KERN_DEFAULT "CPU: %d    %s  (%s %.*s)\n",
++		raw_smp_processor_id(), print_tainted(),
++		init_utsname()->release,
++		(int)strcspn(init_utsname()->version, " "),
++		init_utsname()->version);
++	print_symbol("PC is at %s\n", instruction_pointer(regs));
++	print_symbol("LR is at %s\n", regs->UCreg_lr);
++	printk(KERN_DEFAULT "pc : [<%08lx>]    lr : [<%08lx>]    psr: %08lx\n"
++	       "sp : %08lx  ip : %08lx  fp : %08lx\n",
++		regs->UCreg_pc, regs->UCreg_lr, regs->UCreg_asr,
++		regs->UCreg_sp, regs->UCreg_ip, regs->UCreg_fp);
++	printk(KERN_DEFAULT "r26: %08lx  r25: %08lx  r24: %08lx\n",
++		regs->UCreg_26, regs->UCreg_25,
++		regs->UCreg_24);
++	printk(KERN_DEFAULT "r23: %08lx  r22: %08lx  r21: %08lx  r20: %08lx\n",
++		regs->UCreg_23, regs->UCreg_22,
++		regs->UCreg_21, regs->UCreg_20);
++	printk(KERN_DEFAULT "r19: %08lx  r18: %08lx  r17: %08lx  r16: %08lx\n",
++		regs->UCreg_19, regs->UCreg_18,
++		regs->UCreg_17, regs->UCreg_16);
++	printk(KERN_DEFAULT "r15: %08lx  r14: %08lx  r13: %08lx  r12: %08lx\n",
++		regs->UCreg_15, regs->UCreg_14,
++		regs->UCreg_13, regs->UCreg_12);
++	printk(KERN_DEFAULT "r11: %08lx  r10: %08lx  r9 : %08lx  r8 : %08lx\n",
++		regs->UCreg_11, regs->UCreg_10,
++		regs->UCreg_09, regs->UCreg_08);
++	printk(KERN_DEFAULT "r7 : %08lx  r6 : %08lx  r5 : %08lx  r4 : %08lx\n",
++		regs->UCreg_07, regs->UCreg_06,
++		regs->UCreg_05, regs->UCreg_04);
++	printk(KERN_DEFAULT "r3 : %08lx  r2 : %08lx  r1 : %08lx  r0 : %08lx\n",
++		regs->UCreg_03, regs->UCreg_02,
++		regs->UCreg_01, regs->UCreg_00);
++
++	flags = regs->UCreg_asr;
++	buf[0] = flags & PSR_S_BIT ? 'S' : 's';
++	buf[1] = flags & PSR_Z_BIT ? 'Z' : 'z';
++	buf[2] = flags & PSR_C_BIT ? 'C' : 'c';
++	buf[3] = flags & PSR_V_BIT ? 'V' : 'v';
++	buf[4] = '\0';
++
++	printk(KERN_DEFAULT "Flags: %s  INTR o%s  REAL o%s  Mode %s  Segment %s\n",
++		buf, interrupts_enabled(regs) ? "n" : "ff",
++		fast_interrupts_enabled(regs) ? "n" : "ff",
++		processor_modes[processor_mode(regs)],
++		segment_eq(get_fs(), get_ds()) ? "kernel" : "user");
++	{
++		unsigned int ctrl;
++
++		buf[0] = '\0';
++		{
++			unsigned int transbase;
++			asm("movc %0, p0.c2, #0\n"
++			    : "=r" (transbase));
++			snprintf(buf, sizeof(buf), "  Table: %08x", transbase);
++		}
++		asm("movc %0, p0.c1, #0\n" : "=r" (ctrl));
++
++		printk(KERN_DEFAULT "Control: %08x%s\n", ctrl, buf);
++	}
++}
++
++void show_regs(struct pt_regs *regs)
++{
++	printk(KERN_DEFAULT "\n");
++	printk(KERN_DEFAULT "Pid: %d, comm: %20s\n",
++			task_pid_nr(current), current->comm);
++	__show_regs(regs);
++	__backtrace();
++}
++
++/*
++ * Free current thread data structures etc..
++ */
++void exit_thread(void)
++{
++}
++
++void flush_thread(void)
++{
++	struct thread_info *thread = current_thread_info();
++	struct task_struct *tsk = current;
++
++	memset(thread->used_cp, 0, sizeof(thread->used_cp));
++	memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
++#ifdef CONFIG_UNICORE_FPU_F64
++	memset(&thread->fpstate, 0, sizeof(struct fp_state));
++#endif
++}
++
++void release_thread(struct task_struct *dead_task)
++{
++}
++
++asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
++
++int
++copy_thread(unsigned long clone_flags, unsigned long stack_start,
++	    unsigned long stk_sz, struct task_struct *p, struct pt_regs *regs)
++{
++	struct thread_info *thread = task_thread_info(p);
++	struct pt_regs *childregs = task_pt_regs(p);
++
++	*childregs = *regs;
++	childregs->UCreg_00 = 0;
++	childregs->UCreg_sp = stack_start;
++
++	memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save));
++	thread->cpu_context.sp = (unsigned long)childregs;
++	thread->cpu_context.pc = (unsigned long)ret_from_fork;
++
++	if (clone_flags & CLONE_SETTLS)
++		childregs->UCreg_16 = regs->UCreg_03;
++
++	return 0;
++}
++
++/*
++ * Fill in the task's elfregs structure for a core dump.
++ */
++int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs)
++{
++	elf_core_copy_regs(elfregs, task_pt_regs(t));
++	return 1;
++}
++
++/*
++ * fill in the fpe structure for a core dump...
++ */
++int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fp)
++{
++	struct thread_info *thread = current_thread_info();
++	int used_math = thread->used_cp[1] | thread->used_cp[2];
++
++#ifdef CONFIG_UNICORE_FPU_F64
++	if (used_math)
++		memcpy(fp, &thread->fpstate, sizeof(*fp));
++#endif
++	return used_math != 0;
++}
++EXPORT_SYMBOL(dump_fpu);
++
++/*
++ * Shuffle the argument into the correct register before calling the
++ * thread function.  r1 is the thread argument, r2 is the pointer to
++ * the thread function, and r3 points to the exit function.
++ */
++asm(".pushsection .text\n"
++"	.align\n"
++"	.type	kernel_thread_helper, #function\n"
++"kernel_thread_helper:\n"
++"	mov.a	asr, r7\n"
++"	mov	r0, r4\n"
++"	mov	lr, r6\n"
++"	mov	pc, r5\n"
++"	.size	kernel_thread_helper, . - kernel_thread_helper\n"
++"	.popsection");
++
++/*
++ * Create a kernel thread.
++ */
++pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
++{
++	struct pt_regs regs;
++
++	memset(®s, 0, sizeof(regs));
++
++	regs.UCreg_04 = (unsigned long)arg;
++	regs.UCreg_05 = (unsigned long)fn;
++	regs.UCreg_06 = (unsigned long)do_exit;
++	regs.UCreg_07 = PRIV_MODE;
++	regs.UCreg_pc = (unsigned long)kernel_thread_helper;
++	regs.UCreg_asr = regs.UCreg_07 | PSR_I_BIT;
++
++	return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);
++}
++EXPORT_SYMBOL(kernel_thread);
++
++unsigned long get_wchan(struct task_struct *p)
++{
++	struct stackframe frame;
++	int count = 0;
++	if (!p || p == current || p->state == TASK_RUNNING)
++		return 0;
++
++	frame.fp = thread_saved_fp(p);
++	frame.sp = thread_saved_sp(p);
++	frame.lr = 0;			/* recovered from the stack */
++	frame.pc = thread_saved_pc(p);
++	do {
++		int ret = unwind_frame(&frame);
++		if (ret < 0)
++			return 0;
++		if (!in_sched_functions(frame.pc))
++			return frame.pc;
++	} while ((count++) < 16);
++	return 0;
++}
++
++unsigned long arch_randomize_brk(struct mm_struct *mm)
++{
++	unsigned long range_end = mm->brk + 0x02000000;
++	return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
++}
++
++/*
++ * The vectors page is always readable from user space for the
++ * atomic helpers and the signal restart code.  Let's declare a mapping
++ * for it so it is visible through ptrace and /proc//mem.
++ */
++
++int vectors_user_mapping(void)
++{
++	struct mm_struct *mm = current->mm;
++	return install_special_mapping(mm, 0xffff0000, PAGE_SIZE,
++				       VM_READ | VM_EXEC |
++				       VM_MAYREAD | VM_MAYEXEC |
++				       VM_ALWAYSDUMP | VM_RESERVED,
++				       NULL);
++}
++
++const char *arch_vma_name(struct vm_area_struct *vma)
++{
++	return (vma->vm_start == 0xffff0000) ? "[vectors]" : NULL;
++}
+diff --git a/arch/unicore32/kernel/stacktrace.c b/arch/unicore32/kernel/stacktrace.c
+new file mode 100644
+index 000000000000..b34030bdabe3
+--- /dev/null
++++ b/arch/unicore32/kernel/stacktrace.c
+@@ -0,0 +1,131 @@
++/*
++ * linux/arch/unicore32/kernel/stacktrace.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++
++#include 
++
++#if defined(CONFIG_FRAME_POINTER)
++/*
++ * Unwind the current stack frame and store the new register values in the
++ * structure passed as argument. Unwinding is equivalent to a function return,
++ * hence the new PC value rather than LR should be used for backtrace.
++ *
++ * With framepointer enabled, a simple function prologue looks like this:
++ *	mov	ip, sp
++ *	stmdb	sp!, {fp, ip, lr, pc}
++ *	sub	fp, ip, #4
++ *
++ * A simple function epilogue looks like this:
++ *	ldm	sp, {fp, sp, pc}
++ *
++ * Note that with framepointer enabled, even the leaf functions have the same
++ * prologue and epilogue, therefore we can ignore the LR value in this case.
++ */
++int notrace unwind_frame(struct stackframe *frame)
++{
++	unsigned long high, low;
++	unsigned long fp = frame->fp;
++
++	/* only go to a higher address on the stack */
++	low = frame->sp;
++	high = ALIGN(low, THREAD_SIZE);
++
++	/* check current frame pointer is within bounds */
++	if (fp < (low + 12) || fp + 4 >= high)
++		return -EINVAL;
++
++	/* restore the registers from the stack frame */
++	frame->fp = *(unsigned long *)(fp - 12);
++	frame->sp = *(unsigned long *)(fp - 8);
++	frame->pc = *(unsigned long *)(fp - 4);
++
++	return 0;
++}
++#endif
++
++void notrace walk_stackframe(struct stackframe *frame,
++		     int (*fn)(struct stackframe *, void *), void *data)
++{
++	while (1) {
++		int ret;
++
++		if (fn(frame, data))
++			break;
++		ret = unwind_frame(frame);
++		if (ret < 0)
++			break;
++	}
++}
++EXPORT_SYMBOL(walk_stackframe);
++
++#ifdef CONFIG_STACKTRACE
++struct stack_trace_data {
++	struct stack_trace *trace;
++	unsigned int no_sched_functions;
++	unsigned int skip;
++};
++
++static int save_trace(struct stackframe *frame, void *d)
++{
++	struct stack_trace_data *data = d;
++	struct stack_trace *trace = data->trace;
++	unsigned long addr = frame->pc;
++
++	if (data->no_sched_functions && in_sched_functions(addr))
++		return 0;
++	if (data->skip) {
++		data->skip--;
++		return 0;
++	}
++
++	trace->entries[trace->nr_entries++] = addr;
++
++	return trace->nr_entries >= trace->max_entries;
++}
++
++void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
++{
++	struct stack_trace_data data;
++	struct stackframe frame;
++
++	data.trace = trace;
++	data.skip = trace->skip;
++
++	if (tsk != current) {
++		data.no_sched_functions = 1;
++		frame.fp = thread_saved_fp(tsk);
++		frame.sp = thread_saved_sp(tsk);
++		frame.lr = 0;		/* recovered from the stack */
++		frame.pc = thread_saved_pc(tsk);
++	} else {
++		register unsigned long current_sp asm("sp");
++
++		data.no_sched_functions = 0;
++		frame.fp = (unsigned long)__builtin_frame_address(0);
++		frame.sp = current_sp;
++		frame.lr = (unsigned long)__builtin_return_address(0);
++		frame.pc = (unsigned long)save_stack_trace_tsk;
++	}
++
++	walk_stackframe(&frame, save_trace, &data);
++	if (trace->nr_entries < trace->max_entries)
++		trace->entries[trace->nr_entries++] = ULONG_MAX;
++}
++
++void save_stack_trace(struct stack_trace *trace)
++{
++	save_stack_trace_tsk(current, trace);
++}
++EXPORT_SYMBOL_GPL(save_stack_trace);
++#endif
+diff --git a/arch/unicore32/lib/backtrace.S b/arch/unicore32/lib/backtrace.S
+new file mode 100644
+index 000000000000..ef01d77f2f65
+--- /dev/null
++++ b/arch/unicore32/lib/backtrace.S
+@@ -0,0 +1,163 @@
++/*
++ * linux/arch/unicore32/lib/backtrace.S
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++		.text
++
++@ fp is 0 or stack frame
++
++#define frame	v4
++#define sv_fp	v5
++#define sv_pc	v6
++#define offset	v8
++
++ENTRY(__backtrace)
++		mov	r0, fp
++
++ENTRY(c_backtrace)
++
++#if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
++		mov	pc, lr
++ENDPROC(__backtrace)
++ENDPROC(c_backtrace)
++#else
++		stm.w	(v4 - v8, lr), [sp-]	@ Save an extra register
++						@ so we have a location...
++		mov.a	frame, r0		@ if frame pointer is zero
++		beq	no_frame		@ we have no stack frames
++
++1:		stm.w	(pc), [sp-]		@ calculate offset of PC stored
++		ldw.w	r0, [sp]+, #4		@ by stmfd for this CPU
++		adr	r1, 1b
++		sub	offset, r0, r1
++
++/*
++ * Stack frame layout:
++ *             optionally saved caller registers (r4 - r10)
++ *             saved fp
++ *             saved sp
++ *             saved lr
++ *    frame => saved pc
++ *             optionally saved arguments (r0 - r3)
++ * saved sp => 
++ *
++ * Functions start with the following code sequence:
++ *                  mov   ip, sp
++ *                  stm.w (r0 - r3), [sp-] (optional)
++ * corrected pc =>  stm.w sp, (..., fp, ip, lr, pc)
++ */
++for_each_frame:
++
++1001:		ldw	sv_pc, [frame+], #0	@ get saved pc
++1002:		ldw	sv_fp, [frame+], #-12	@ get saved fp
++
++		sub	sv_pc, sv_pc, offset	@ Correct PC for prefetching
++
++1003:		ldw	r2, [sv_pc+], #-4	@ if stmfd sp, {args} exists,
++		ldw	r3, .Ldsi+4		@ adjust saved 'pc' back one
++		cxor.a	r3, r2 >> #14		@ instruction
++		beq	201f
++		sub	r0, sv_pc, #4		@ allow for mov
++		b	202f
++201:
++		sub	r0, sv_pc, #8		@ allow for mov + stmia
++202:
++		ldw	r1, [frame+], #-4	@ get saved lr
++		mov	r2, frame
++		b.l	dump_backtrace_entry
++
++		ldw	r1, [sv_pc+], #-4	@ if stmfd sp, {args} exists,
++		ldw	r3, .Ldsi+4
++		cxor.a	r3, r1 >> #14
++		bne	1004f
++		ldw	r0, [frame+], #-8	@ get sp
++		sub	r0, r0, #4		@ point at the last arg
++		b.l	.Ldumpstm		@ dump saved registers
++
++1004:		ldw	r1, [sv_pc+], #0	@ if stmfd {, fp, ip, lr, pc}
++		ldw	r3, .Ldsi		@ instruction exists,
++		cxor.a	r3, r1 >> #14
++		bne	201f
++		sub	r0, frame, #16
++		b.l	.Ldumpstm		@ dump saved registers
++201:
++		cxor.a	sv_fp, #0		@ zero saved fp means
++		beq	no_frame		@ no further frames
++
++		csub.a	sv_fp, frame		@ next frame must be
++		mov	frame, sv_fp		@ above the current frame
++		bua	for_each_frame
++
++1006:		adr	r0, .Lbad
++		mov	r1, frame
++		b.l	printk
++no_frame:	ldm.w	(v4 - v8, pc), [sp]+
++ENDPROC(__backtrace)
++ENDPROC(c_backtrace)
++
++		.pushsection __ex_table,"a"
++		.align	3
++		.long	1001b, 1006b
++		.long	1002b, 1006b
++		.long	1003b, 1006b
++		.long	1004b, 1006b
++		.popsection
++
++#define instr v4
++#define reg   v5
++#define stack v6
++
++.Ldumpstm:	stm.w	(instr, reg, stack, v7, lr), [sp-]
++		mov	stack, r0
++		mov	instr, r1
++		mov	reg, #14
++		mov	v7, #0
++1:		mov	r3, #1
++		csub.a	reg, #8
++		bne	201f
++		sub	reg, reg, #3
++201:
++		cand.a	instr, r3 << reg
++		beq	2f
++		add	v7, v7, #1
++		cxor.a	v7, #6
++		cmoveq	v7, #1
++		cmoveq	r1, #'\n'
++		cmovne	r1, #' '
++		ldw.w	r3, [stack]+, #-4
++		mov	r2, reg
++		csub.a	r2, #8
++		bsl	201f
++		sub	r2, r2, #3
++201:
++		cand.a	instr, #0x40		@ if H is 1, high 16 regs
++		beq	201f
++		add	r2, r2, #0x10		@ so r2 need add 16
++201:
++		adr	r0, .Lfp
++		b.l	printk
++2:		sub.a	reg, reg, #1
++		bns	1b
++		cxor.a	v7, #0
++		beq	201f
++		adr	r0, .Lcr
++		b.l	printk
++201:		ldm.w	(instr, reg, stack, v7, pc), [sp]+
++
++.Lfp:		.asciz	"%cr%d:%08x"
++.Lcr:		.asciz	"\n"
++.Lbad:		.asciz	"Backtrace aborted due to bad frame pointer <%p>\n"
++		.align
++.Ldsi:		.word	0x92eec000 >> 14	@ stm.w sp, (... fp, ip, lr, pc)
++		.word	0x92e10000 >> 14	@ stm.w sp, ()
++
++#endif

commit 141c943fd4b323bae2b47f67743dba96134afb1f
+Author: GuanXuetao 
+Date:   Sat Jan 15 18:15:45 2011 +0800
+
+    unicore32 core architecture: low level entry and setup codes
+    
+    This patch implements low level entry and setup codes.
+    
+    Signed-off-by: Guan Xuetao 
+    Reviewed-by: Arnd Bergmann 
+
+diff --git a/arch/unicore32/include/asm/traps.h b/arch/unicore32/include/asm/traps.h
+new file mode 100644
+index 000000000000..66e17a724bfe
+--- /dev/null
++++ b/arch/unicore32/include/asm/traps.h
+@@ -0,0 +1,21 @@
++/*
++ * linux/arch/unicore32/include/asm/traps.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_TRAP_H__
++#define __UNICORE_TRAP_H__
++
++extern void __init early_trap_init(void);
++extern void dump_backtrace_entry(unsigned long where,
++		unsigned long from, unsigned long frame);
++
++extern void do_DataAbort(unsigned long addr, unsigned int fsr,
++		 struct pt_regs *regs);
++#endif
+diff --git a/arch/unicore32/kernel/entry.S b/arch/unicore32/kernel/entry.S
+new file mode 100644
+index 000000000000..83698b7c8f5b
+--- /dev/null
++++ b/arch/unicore32/kernel/entry.S
+@@ -0,0 +1,824 @@
++/*
++ * linux/arch/unicore32/kernel/entry.S
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ *  Low-level vector interface routines
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include "debug-macro.S"
++
++@
++@ Most of the stack format comes from struct pt_regs, but with
++@ the addition of 8 bytes for storing syscall args 5 and 6.
++@
++#define S_OFF		8
++
++/*
++ * The SWI code relies on the fact that R0 is at the bottom of the stack
++ * (due to slow/fast restore user regs).
++ */
++#if S_R0 != 0
++#error "Please fix"
++#endif
++
++	.macro	zero_fp
++#ifdef CONFIG_FRAME_POINTER
++	mov	fp, #0
++#endif
++	.endm
++
++	.macro	alignment_trap, rtemp
++#ifdef CONFIG_ALIGNMENT_TRAP
++	ldw	\rtemp, .LCcralign
++	ldw	\rtemp, [\rtemp]
++	movc	p0.c1, \rtemp, #0
++#endif
++	.endm
++
++	.macro	load_user_sp_lr, rd, rtemp, offset = 0
++	mov	\rtemp, asr
++	xor	\rtemp, \rtemp, #(PRIV_MODE ^ SUSR_MODE)
++	mov.a	asr, \rtemp			@ switch to the SUSR mode
++
++	ldw	sp, [\rd+], #\offset		@ load sp_user
++	ldw	lr, [\rd+], #\offset + 4	@ load lr_user
++
++	xor	\rtemp, \rtemp, #(PRIV_MODE ^ SUSR_MODE)
++	mov.a	asr, \rtemp			@ switch back to the PRIV mode
++	.endm
++
++	.macro	priv_exit, rpsr
++	mov.a	bsr, \rpsr
++	ldm.w	(r0 - r15), [sp]+
++	ldm.b	(r16 - pc), [sp]+		@ load r0 - pc, asr
++	.endm
++
++	.macro	restore_user_regs, fast = 0, offset = 0
++	ldw	r1, [sp+], #\offset + S_PSR	@ get calling asr
++	ldw	lr, [sp+], #\offset + S_PC	@ get pc
++	mov.a	bsr, r1				@ save in bsr_priv
++	.if	\fast
++	add	sp, sp, #\offset + S_R1		@ r0 is syscall return value
++	ldm.w	(r1 - r15), [sp]+		@ get calling r1 - r15
++	ldur	(r16 - lr), [sp]+		@ get calling r16 - lr
++	.else
++	ldm.w	(r0 - r15), [sp]+		@ get calling r0 - r15
++	ldur	(r16 - lr), [sp]+		@ get calling r16 - lr
++	.endif
++	nop
++	add	sp, sp, #S_FRAME_SIZE - S_R16
++	mov.a	pc, lr				@ return
++						@ and move bsr_priv into asr
++	.endm
++
++	.macro	get_thread_info, rd
++	mov	\rd, sp >> #13
++	mov	\rd, \rd << #13
++	.endm
++
++	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
++	ldw	\base, =(io_p2v(PKUNITY_INTC_BASE))
++	ldw	\irqstat, [\base+], #0xC	@ INTC_ICIP
++	ldw	\tmp,	  [\base+], #0x4	@ INTC_ICMR
++	and.a	\irqstat, \irqstat, \tmp
++	beq	1001f
++	cntlz	\irqnr, \irqstat
++	rsub	\irqnr, \irqnr, #31
++1001:	/* EQ will be set if no irqs pending */
++	.endm
++
++#ifdef CONFIG_DEBUG_LL
++	.macro	printreg, reg, temp
++		adr	\temp, 901f
++		stm	(r0-r3), [\temp]+
++		stw	lr, [\temp+], #0x10
++		mov	r0, \reg
++		b.l	printhex8
++		mov	r0, #':'
++		b.l	printch
++		mov	r0, pc
++		b.l	printhex8
++		adr	r0, 902f
++		b.l	printascii
++		adr	\temp, 901f
++		ldm	(r0-r3), [\temp]+
++		ldw	lr, [\temp+], #0x10
++		b	903f
++901:	.word	0, 0, 0, 0, 0	@ r0-r3, lr
++902:	.asciz	": epip4d\n"
++	.align
++903:
++	.endm
++#endif
++
++/*
++ * These are the registers used in the syscall handler, and allow us to
++ * have in theory up to 7 arguments to a function - r0 to r6.
++ *
++ * Note that tbl == why is intentional.
++ *
++ * We must set at least "tsk" and "why" when calling ret_with_reschedule.
++ */
++scno	.req	r21		@ syscall number
++tbl	.req	r22		@ syscall table pointer
++why	.req	r22		@ Linux syscall (!= 0)
++tsk	.req	r23		@ current thread_info
++
++/*
++ * Interrupt handling.  Preserves r17, r18, r19
++ */
++	.macro	intr_handler
++1:	get_irqnr_and_base r0, r6, r5, lr
++	beq	2f
++	mov	r1, sp
++	@
++	@ routine called with r0 = irq number, r1 = struct pt_regs *
++	@
++	adr	lr, 1b
++	b	asm_do_IRQ
++2:
++	.endm
++
++/*
++ * PRIV mode handlers
++ */
++	.macro	priv_entry
++	sub	sp, sp, #(S_FRAME_SIZE - 4)
++	stm	(r1 - r15), [sp]+
++	add	r5, sp, #S_R15
++	stm	(r16 - r28), [r5]+
++
++	ldm	(r1 - r3), [r0]+
++	add	r5, sp, #S_SP - 4	@ here for interlock avoidance
++	mov	r4, #-1			@  ""  ""      ""       ""
++	add	r0, sp, #(S_FRAME_SIZE - 4)
++	stw.w	r1, [sp+], #-4		@ save the "real" r0 copied
++					@ from the exception stack
++
++	mov	r1, lr
++
++	@
++	@ We are now ready to fill in the remaining blanks on the stack:
++	@
++	@  r0 - sp_priv
++	@  r1 - lr_priv
++	@  r2 - lr_, already fixed up for correct return/restart
++	@  r3 - bsr_
++	@  r4 - orig_r0 (see pt_regs definition in ptrace.h)
++	@
++	stm	(r0 - r4), [r5]+
++	.endm
++
++/*
++ * User mode handlers
++ *
++ */
++	.macro	user_entry
++	sub	sp, sp, #S_FRAME_SIZE
++	stm	(r1 - r15), [sp+]
++	add	r4, sp, #S_R16
++	stm	(r16 - r28), [r4]+
++
++	ldm	(r1 - r3), [r0]+
++	add	r0, sp, #S_PC		@ here for interlock avoidance
++	mov	r4, #-1			@  ""  ""     ""        ""
++
++	stw	r1, [sp]		@ save the "real" r0 copied
++					@ from the exception stack
++
++	@
++	@ We are now ready to fill in the remaining blanks on the stack:
++	@
++	@  r2 - lr_, already fixed up for correct return/restart
++	@  r3 - bsr_
++	@  r4 - orig_r0 (see pt_regs definition in ptrace.h)
++	@
++	@ Also, separately save sp_user and lr_user
++	@
++	stm	(r2 - r4), [r0]+
++	stur	(sp, lr), [r0-]
++
++	@
++	@ Enable the alignment trap while in kernel mode
++	@
++	alignment_trap r0
++
++	@
++	@ Clear FP to mark the first stack frame
++	@
++	zero_fp
++	.endm
++
++	.text
++
++@
++@ __invalid - generic code for failed exception
++@			(re-entrant version of handlers)
++@
++__invalid:
++	sub	sp, sp, #S_FRAME_SIZE
++	stm	(r1 - r15), [sp+]
++	add	r1, sp, #S_R16
++	stm	(r16 - r28, sp, lr), [r1]+
++
++	zero_fp
++
++	ldm	(r4 - r6), [r0]+
++	add	r0, sp, #S_PC		@ here for interlock avoidance
++	mov	r7, #-1			@  ""   ""    ""        ""
++	stw	r4, [sp]		@ save preserved r0
++	stm	(r5 - r7), [r0]+	@ lr_,
++					@ asr_, "old_r0"
++
++	mov	r0, sp
++	mov	r1, asr
++	b	bad_mode
++ENDPROC(__invalid)
++
++	.align	5
++__dabt_priv:
++	priv_entry
++
++	@
++	@ get ready to re-enable interrupts if appropriate
++	@
++	mov	r17, asr
++	cand.a	r3, #PSR_I_BIT
++	bne	1f
++	andn	r17, r17, #PSR_I_BIT
++1:
++
++	@
++	@ Call the processor-specific abort handler:
++	@
++	@  r2 - aborted context pc
++	@  r3 - aborted context asr
++	@
++	@ The abort handler must return the aborted address in r0, and
++	@ the fault status register in r1.
++	@
++	movc	r1, p0.c3, #0		@ get FSR
++	movc	r0, p0.c4, #0		@ get FAR
++
++	@
++	@ set desired INTR state, then call main handler
++	@
++	mov.a	asr, r17
++	mov	r2, sp
++	b.l	do_DataAbort
++
++	@
++	@ INTRs off again before pulling preserved data off the stack
++	@
++	disable_irq r0
++
++	@
++	@ restore BSR and restart the instruction
++	@
++	ldw	r2, [sp+], #S_PSR
++	priv_exit r2				@ return from exception
++ENDPROC(__dabt_priv)
++
++	.align	5
++__intr_priv:
++	priv_entry
++
++	intr_handler
++
++	mov	r0, #0				@ epip4d
++	movc	p0.c5, r0, #14
++	nop; nop; nop; nop; nop; nop; nop; nop
++
++	ldw	r4, [sp+], #S_PSR		@ irqs are already disabled
++
++	priv_exit r4				@ return from exception
++ENDPROC(__intr_priv)
++
++	.ltorg
++
++	.align	5
++__extn_priv:
++	priv_entry
++
++	mov	r0, sp				@ struct pt_regs *regs
++	mov	r1, asr
++	b	bad_mode			@ not supported
++ENDPROC(__extn_priv)
++
++	.align	5
++__pabt_priv:
++	priv_entry
++
++	@
++	@ re-enable interrupts if appropriate
++	@
++	mov	r17, asr
++	cand.a	r3, #PSR_I_BIT
++	bne	1f
++	andn	r17, r17, #PSR_I_BIT
++1:
++
++	@
++	@ set args, then call main handler
++	@
++	@  r0 - address of faulting instruction
++	@  r1 - pointer to registers on stack
++	@
++	mov	r0, r2			@ pass address of aborted instruction
++	mov	r1, #5
++	mov.a	asr, r17
++	mov	r2, sp			@ regs
++	b.l	do_PrefetchAbort	@ call abort handler
++
++	@
++	@ INTRs off again before pulling preserved data off the stack
++	@
++	disable_irq r0
++
++	@
++	@ restore BSR and restart the instruction
++	@
++	ldw	r2, [sp+], #S_PSR
++	priv_exit r2			@ return from exception
++ENDPROC(__pabt_priv)
++
++	.align	5
++.LCcralign:
++	.word	cr_alignment
++
++	.align	5
++__dabt_user:
++	user_entry
++
++#ifdef CONFIG_UNICORE_FPU_F64
++	cff	ip, s31
++	cand.a	ip, #0x08000000		@ FPU execption traps?
++	beq	209f
++
++	ldw	ip, [sp+], #S_PC
++	add	ip, ip, #4
++	stw	ip, [sp+], #S_PC
++	@
++	@ fall through to the emulation code, which returns using r19 if
++	@ it has emulated the instruction, or the more conventional lr
++	@ if we are to treat this as a real extended instruction
++	@
++	@  r0 - instruction
++	@
++1:	ldw.u	r0, [r2]
++	adr	r19, ret_from_exception
++	adr	lr, 209f
++	@
++	@ fallthrough to call do_uc_f64
++	@
++/*
++ * Check whether the instruction is a co-processor instruction.
++ * If yes, we need to call the relevant co-processor handler.
++ *
++ * Note that we don't do a full check here for the co-processor
++ * instructions; all instructions with bit 27 set are well
++ * defined.  The only instructions that should fault are the
++ * co-processor instructions.
++ *
++ * Emulators may wish to make use of the following registers:
++ *  r0  = instruction opcode.
++ *  r2  = PC
++ *  r19 = normal "successful" return address
++ *  r20 = this threads thread_info structure.
++ *  lr  = unrecognised instruction return address
++ */
++	get_thread_info r20			@ get current thread
++	and	r8, r0, #0x00003c00		@ mask out CP number
++	mov	r7, #1
++	stb	r7, [r20+], #TI_USED_CP + 2	@ set appropriate used_cp[]
++
++	@ F64 hardware support entry point.
++	@  r0  = faulted instruction
++	@  r19 = return address
++	@  r20 = fp_state
++	enable_irq r4
++	add	r20, r20, #TI_FPSTATE	@ r20 = workspace
++	cff	r1, s31			@ get fpu FPSCR
++	andn    r2, r1, #0x08000000
++	ctf     r2, s31			@ clear 27 bit
++	mov	r2, sp			@ nothing stacked - regdump is at TOS
++	mov	lr, r19			@ setup for a return to the user code
++
++	@ Now call the C code to package up the bounce to the support code
++	@   r0 holds the trigger instruction
++	@   r1 holds the FPSCR value
++	@   r2 pointer to register dump
++	b	ucf64_exchandler
++209:
++#endif
++	@
++	@ Call the processor-specific abort handler:
++	@
++	@  r2 - aborted context pc
++	@  r3 - aborted context asr
++	@
++	@ The abort handler must return the aborted address in r0, and
++	@ the fault status register in r1.
++	@
++	movc	r1, p0.c3, #0		@ get FSR
++	movc	r0, p0.c4, #0		@ get FAR
++
++	@
++	@ INTRs on, then call the main handler
++	@
++	enable_irq r2
++	mov	r2, sp
++	adr	lr, ret_from_exception
++	b	do_DataAbort
++ENDPROC(__dabt_user)
++
++	.align	5
++__intr_user:
++	user_entry
++
++	get_thread_info tsk
++
++	intr_handler
++
++	mov	why, #0
++	b	ret_to_user
++ENDPROC(__intr_user)
++
++	.ltorg
++
++	.align	5
++__extn_user:
++	user_entry
++
++	mov	r0, sp
++	mov	r1, asr
++	b	bad_mode
++ENDPROC(__extn_user)
++
++	.align	5
++__pabt_user:
++	user_entry
++
++	mov	r0, r2			@ pass address of aborted instruction.
++	mov	r1, #5
++	enable_irq r1			@ Enable interrupts
++	mov	r2, sp			@ regs
++	b.l	do_PrefetchAbort	@ call abort handler
++	/* fall through */
++/*
++ * This is the return code to user mode for abort handlers
++ */
++ENTRY(ret_from_exception)
++	get_thread_info tsk
++	mov	why, #0
++	b	ret_to_user
++ENDPROC(__pabt_user)
++ENDPROC(ret_from_exception)
++
++/*
++ * Register switch for UniCore V2 processors
++ * r0 = previous task_struct, r1 = previous thread_info, r2 = next thread_info
++ * previous and next are guaranteed not to be the same.
++ */
++ENTRY(__switch_to)
++	add	ip, r1, #TI_CPU_SAVE
++	stm.w	(r4 - r15), [ip]+
++	stm.w	(r16 - r27, sp, lr), [ip]+
++
++#ifdef	CONFIG_UNICORE_FPU_F64
++	add	ip, r1, #TI_FPSTATE
++	sfm.w	(f0  - f7 ), [ip]+
++	sfm.w	(f8  - f15), [ip]+
++	sfm.w	(f16 - f23), [ip]+
++	sfm.w	(f24 - f31), [ip]+
++	cff	r4, s31
++	stw	r4, [ip]
++
++	add	ip, r2, #TI_FPSTATE
++	lfm.w	(f0  - f7 ), [ip]+
++	lfm.w	(f8  - f15), [ip]+
++	lfm.w	(f16 - f23), [ip]+
++	lfm.w	(f24 - f31), [ip]+
++	ldw	r4, [ip]
++	ctf	r4, s31
++#endif
++	add	ip, r2, #TI_CPU_SAVE
++	ldm.w	(r4 - r15), [ip]+
++	ldm	(r16 - r27, sp, pc), [ip]+	@ Load all regs saved previously
++ENDPROC(__switch_to)
++
++	.align	5
++/*
++ * This is the fast syscall return path.  We do as little as
++ * possible here, and this includes saving r0 back into the PRIV
++ * stack.
++ */
++ret_fast_syscall:
++	disable_irq r1				@ disable interrupts
++	ldw	r1, [tsk+], #TI_FLAGS
++	cand.a	r1, #_TIF_WORK_MASK
++	bne	fast_work_pending
++
++	@ fast_restore_user_regs
++	restore_user_regs fast = 1, offset = S_OFF
++
++/*
++ * Ok, we need to do extra processing, enter the slow path.
++ */
++fast_work_pending:
++	stw.w	r0, [sp+], #S_R0+S_OFF		@ returned r0
++work_pending:
++	cand.a	r1, #_TIF_NEED_RESCHED
++	bne	work_resched
++	cand.a	r1, #_TIF_SIGPENDING|_TIF_NOTIFY_RESUME
++	beq	no_work_pending
++	mov	r0, sp				@ 'regs'
++	mov	r2, why				@ 'syscall'
++	cand.a	r1, #_TIF_SIGPENDING		@ delivering a signal?
++	cmovne	why, #0				@ prevent further restarts
++	b.l	do_notify_resume
++	b	ret_slow_syscall		@ Check work again
++
++work_resched:
++	b.l	schedule
++/*
++ * "slow" syscall return path.  "why" tells us if this was a real syscall.
++ */
++ENTRY(ret_to_user)
++ret_slow_syscall:
++	disable_irq r1				@ disable interrupts
++	get_thread_info tsk			@ epip4d, one path error?!
++	ldw	r1, [tsk+], #TI_FLAGS
++	cand.a	r1, #_TIF_WORK_MASK
++	bne	work_pending
++no_work_pending:
++	@ slow_restore_user_regs
++	restore_user_regs fast = 0, offset = 0
++ENDPROC(ret_to_user)
++
++/*
++ * This is how we return from a fork.
++ */
++ENTRY(ret_from_fork)
++	b.l	schedule_tail
++	get_thread_info tsk
++	ldw	r1, [tsk+], #TI_FLAGS		@ check for syscall tracing
++	mov	why, #1
++	cand.a	r1, #_TIF_SYSCALL_TRACE		@ are we tracing syscalls?
++	beq	ret_slow_syscall
++	mov	r1, sp
++	mov	r0, #1				@ trace exit [IP = 1]
++	b.l	syscall_trace
++	b	ret_slow_syscall
++ENDPROC(ret_from_fork)
++
++/*=============================================================================
++ * SWI handler
++ *-----------------------------------------------------------------------------
++ */
++	.align	5
++ENTRY(vector_swi)
++	sub	sp, sp, #S_FRAME_SIZE
++	stm	(r0 - r15), [sp]+		@ Calling r0 - r15
++	add	r8, sp, #S_R16
++	stm	(r16 - r28), [r8]+		@ Calling r16 - r28
++	add	r8, sp, #S_PC
++	stur	(sp, lr), [r8-]			@ Calling sp, lr
++	mov	r8, bsr				@ called from non-REAL mode
++	stw	lr, [sp+], #S_PC		@ Save calling PC
++	stw	r8, [sp+], #S_PSR		@ Save ASR
++	stw	r0, [sp+], #S_OLD_R0		@ Save OLD_R0
++	zero_fp
++
++	/*
++	 * Get the system call number.
++	 */
++	sub	ip, lr, #4
++	ldw.u	scno, [ip]			@ get SWI instruction
++
++#ifdef CONFIG_ALIGNMENT_TRAP
++	ldw	ip, __cr_alignment
++	ldw	ip, [ip]
++	movc	p0.c1, ip, #0                   @ update control register
++#endif
++	enable_irq ip
++
++	get_thread_info tsk
++	ldw	tbl, =sys_call_table		@ load syscall table pointer
++
++	andn	scno, scno, #0xff000000		@ mask off SWI op-code
++	andn	scno, scno, #0x00ff0000		@ mask off SWI op-code
++
++	stm.w	(r4, r5), [sp-]			@ push fifth and sixth args
++	ldw	ip, [tsk+], #TI_FLAGS		@ check for syscall tracing
++	cand.a	ip, #_TIF_SYSCALL_TRACE		@ are we tracing syscalls?
++	bne	__sys_trace
++
++	csub.a	scno, #__NR_syscalls		@ check upper syscall limit
++	adr	lr, ret_fast_syscall		@ return address
++	bea	1f
++	ldw	pc, [tbl+], scno << #2		@ call sys_* routine
++1:
++	add	r1, sp, #S_OFF
++2:	mov	why, #0				@ no longer a real syscall
++	b	sys_ni_syscall			@ not private func
++
++	/*
++	 * This is the really slow path.  We're going to be doing
++	 * context switches, and waiting for our parent to respond.
++	 */
++__sys_trace:
++	mov	r2, scno
++	add	r1, sp, #S_OFF
++	mov	r0, #0				@ trace entry [IP = 0]
++	b.l	syscall_trace
++
++	adr	lr, __sys_trace_return		@ return address
++	mov	scno, r0			@ syscall number (possibly new)
++	add	r1, sp, #S_R0 + S_OFF		@ pointer to regs
++	csub.a	scno, #__NR_syscalls		@ check upper syscall limit
++	bea	2b
++	ldm	(r0 - r3), [r1]+		@ have to reload r0 - r3
++	ldw	pc, [tbl+], scno << #2		@ call sys_* routine
++
++__sys_trace_return:
++	stw.w	r0, [sp+], #S_R0 + S_OFF	@ save returned r0
++	mov	r2, scno
++	mov	r1, sp
++	mov	r0, #1				@ trace exit [IP = 1]
++	b.l	syscall_trace
++	b	ret_slow_syscall
++
++	.align	5
++#ifdef CONFIG_ALIGNMENT_TRAP
++	.type	__cr_alignment, #object
++__cr_alignment:
++	.word	cr_alignment
++#endif
++	.ltorg
++
++ENTRY(sys_execve)
++		add	r3, sp, #S_OFF
++		b	__sys_execve
++ENDPROC(sys_execve)
++
++ENTRY(sys_clone)
++		add	ip, sp, #S_OFF
++		stw	ip, [sp+], #4
++		b	__sys_clone
++ENDPROC(sys_clone)
++
++ENTRY(sys_rt_sigreturn)
++		add	r0, sp, #S_OFF
++		mov	why, #0		@ prevent syscall restart handling
++		b	__sys_rt_sigreturn
++ENDPROC(sys_rt_sigreturn)
++
++ENTRY(sys_sigaltstack)
++		ldw	r2, [sp+], #S_OFF + S_SP
++		b	do_sigaltstack
++ENDPROC(sys_sigaltstack)
++
++	__INIT
++
++/*
++ * Vector stubs.
++ *
++ * This code is copied to 0xffff0200 so we can use branches in the
++ * vectors, rather than ldr's.  Note that this code must not
++ * exceed 0x300 bytes.
++ *
++ * Common stub entry macro:
++ *   Enter in INTR mode, bsr = PRIV/USER ASR, lr = PRIV/USER PC
++ *
++ * SP points to a minimal amount of processor-private memory, the address
++ * of which is copied into r0 for the mode specific abort handler.
++ */
++	.macro	vector_stub, name, mode
++	.align	5
++
++vector_\name:
++	@
++	@ Save r0, lr_ (parent PC) and bsr_
++	@ (parent ASR)
++	@
++	stw	r0, [sp]
++	stw	lr, [sp+], #4		@ save r0, lr
++	mov	lr, bsr
++	stw	lr, [sp+], #8		@ save bsr
++
++	@
++	@ Prepare for PRIV mode.  INTRs remain disabled.
++	@
++	mov	r0, asr
++	xor	r0, r0, #(\mode ^ PRIV_MODE)
++	mov.a	bsr, r0
++
++	@
++	@ the branch table must immediately follow this code
++	@
++	and	lr, lr, #0x03
++	add	lr, lr, #1
++	mov	r0, sp
++	ldw	lr, [pc+], lr << #2
++	mov.a	pc, lr			@ branch to handler in PRIV mode
++ENDPROC(vector_\name)
++	.align	2
++	@ handler addresses follow this label
++	.endm
++
++	.globl	__stubs_start
++__stubs_start:
++/*
++ * Interrupt dispatcher
++ */
++	vector_stub	intr, INTR_MODE
++
++	.long	__intr_user			@  0  (USER)
++	.long	__invalid			@  1
++	.long	__invalid			@  2
++	.long	__intr_priv			@  3  (PRIV)
++
++/*
++ * Data abort dispatcher
++ * Enter in ABT mode, bsr = USER ASR, lr = USER PC
++ */
++	vector_stub	dabt, ABRT_MODE
++
++	.long	__dabt_user			@  0  (USER)
++	.long	__invalid			@  1
++	.long	__invalid			@  2  (INTR)
++	.long	__dabt_priv			@  3  (PRIV)
++
++/*
++ * Prefetch abort dispatcher
++ * Enter in ABT mode, bsr = USER ASR, lr = USER PC
++ */
++	vector_stub	pabt, ABRT_MODE
++
++	.long	__pabt_user			@  0 (USER)
++	.long	__invalid			@  1
++	.long	__invalid			@  2 (INTR)
++	.long	__pabt_priv			@  3 (PRIV)
++
++/*
++ * Undef instr entry dispatcher
++ * Enter in EXTN mode, bsr = PRIV/USER ASR, lr = PRIV/USER PC
++ */
++	vector_stub	extn, EXTN_MODE
++
++	.long	__extn_user			@  0 (USER)
++	.long	__invalid			@  1
++	.long	__invalid			@  2 (INTR)
++	.long	__extn_priv			@  3 (PRIV)
++
++/*
++ * We group all the following data together to optimise
++ * for CPUs with separate I & D caches.
++ */
++	.align	5
++
++.LCvswi:
++	.word	vector_swi
++
++	.globl	__stubs_end
++__stubs_end:
++
++	.equ	stubs_offset, __vectors_start + 0x200 - __stubs_start
++
++	.globl	__vectors_start
++__vectors_start:
++	jepriv	SYS_ERROR0
++	b	vector_extn + stubs_offset
++	ldw	pc, .LCvswi + stubs_offset
++	b	vector_pabt + stubs_offset
++	b	vector_dabt + stubs_offset
++	jepriv	SYS_ERROR0
++	b	vector_intr + stubs_offset
++	jepriv	SYS_ERROR0
++
++	.globl	__vectors_end
++__vectors_end:
++
++	.data
++
++	.globl	cr_alignment
++	.globl	cr_no_alignment
++cr_alignment:
++	.space	4
++cr_no_alignment:
++	.space	4
+diff --git a/arch/unicore32/kernel/head.S b/arch/unicore32/kernel/head.S
+new file mode 100644
+index 000000000000..92255f3ab6a7
+--- /dev/null
++++ b/arch/unicore32/kernel/head.S
+@@ -0,0 +1,252 @@
++/*
++ * linux/arch/unicore32/kernel/head.S
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#if (PHYS_OFFSET & 0x003fffff)
++#error "PHYS_OFFSET must be at an even 4MiB boundary!"
++#endif
++
++#define KERNEL_RAM_VADDR	(PAGE_OFFSET + KERNEL_IMAGE_START)
++#define KERNEL_RAM_PADDR	(PHYS_OFFSET + KERNEL_IMAGE_START)
++
++#define KERNEL_PGD_PADDR	(KERNEL_RAM_PADDR - 0x1000)
++#define KERNEL_PGD_VADDR	(KERNEL_RAM_VADDR - 0x1000)
++
++#define KERNEL_START		KERNEL_RAM_VADDR
++#define KERNEL_END		_end
++
++/*
++ * swapper_pg_dir is the virtual address of the initial page table.
++ * We place the page tables 4K below KERNEL_RAM_VADDR.  Therefore, we must
++ * make sure that KERNEL_RAM_VADDR is correctly set.  Currently, we expect
++ * the least significant 16 bits to be 0x8000, but we could probably
++ * relax this restriction to KERNEL_RAM_VADDR >= PAGE_OFFSET + 0x1000.
++ */
++#if (KERNEL_RAM_VADDR & 0xffff) != 0x8000
++#error KERNEL_RAM_VADDR must start at 0xXXXX8000
++#endif
++
++	.globl	swapper_pg_dir
++	.equ	swapper_pg_dir, KERNEL_RAM_VADDR - 0x1000
++
++/*
++ * Kernel startup entry point.
++ * ---------------------------
++ *
++ * This is normally called from the decompressor code.  The requirements
++ * are: MMU = off, D-cache = off, I-cache = dont care
++ *
++ * This code is mostly position independent, so if you link the kernel at
++ * 0xc0008000, you call this at __pa(0xc0008000).
++ */
++	__HEAD
++ENTRY(stext)
++	@ set asr
++	mov	r0, #PRIV_MODE			@ ensure priv mode
++	or	r0, #PSR_R_BIT | PSR_I_BIT	@ disable irqs
++	mov.a	asr, r0
++
++	@ process identify
++	movc	r0, p0.c0, #0			@ cpuid
++	movl	r1, 0xff00ffff			@ mask
++	movl	r2, 0x4d000863			@ value
++	and	r0, r1, r0
++	cxor.a	r0, r2
++	bne	__error_p			@ invalid processor id
++
++	/*
++	 * Clear the 4K level 1 swapper page table
++	 */
++	movl	r0, #KERNEL_PGD_PADDR		@ page table address
++	mov	r1, #0
++	add	r2, r0, #0x1000
++101:	stw.w	r1, [r0]+, #4
++	stw.w	r1, [r0]+, #4
++	stw.w	r1, [r0]+, #4
++	stw.w	r1, [r0]+, #4
++	cxor.a	r0, r2
++	bne	101b
++
++	movl	r4, #KERNEL_PGD_PADDR		@ page table address
++	mov	r7, #PMD_TYPE_SECT | PMD_PRESENT	@ page size: section
++	or	r7, r7, #PMD_SECT_CACHEABLE		@ cacheable
++	or	r7, r7, #PMD_SECT_READ | PMD_SECT_WRITE | PMD_SECT_EXEC
++
++	/*
++	 * Create identity mapping for first 4MB of kernel to
++	 * cater for the MMU enable.  This identity mapping
++	 * will be removed by paging_init().  We use our current program
++	 * counter to determine corresponding section base address.
++	 */
++	mov	r6, pc
++	mov	r6, r6 >> #22			@ start of kernel section
++	or	r1, r7, r6 << #22		@ flags + kernel base
++	stw	r1, [r4+], r6 << #2		@ identity mapping
++
++	/*
++	 * Now setup the pagetables for our kernel direct
++	 * mapped region.
++	 */
++	add	r0, r4,  #(KERNEL_START & 0xff000000) >> 20
++	stw.w	r1, [r0+], #(KERNEL_START & 0x00c00000) >> 20
++	movl	r6, #(KERNEL_END - 1)
++	add	r0, r0, #4
++	add	r6, r4, r6 >> #20
++102:	csub.a	r0, r6
++	add	r1, r1, #1 << 22
++	bua	103f
++	stw.w	r1, [r0]+, #4
++	b	102b
++103:
++	/*
++	 * Then map first 4MB of ram in case it contains our boot params.
++	 */
++	add	r0, r4, #PAGE_OFFSET >> 20
++	or	r6, r7, #(PHYS_OFFSET & 0xffc00000)
++	stw	r6, [r0]
++
++	ldw	r15, __switch_data		@ address to jump to after
++
++	/*
++	 * Initialise TLB, Caches, and MMU state ready to switch the MMU
++	 * on.
++	 */
++	mov	r0, #0
++	movc	p0.c5, r0, #28			@ cache invalidate all
++	nop8
++	movc	p0.c6, r0, #6			@ TLB invalidate all
++	nop8
++
++	/*
++	 * ..V. .... ..TB IDAM
++	 * ..1. .... ..01 1111
++	 */
++	movl	r0, #0x201f			@ control register setting
++
++	/*
++	 * Setup common bits before finally enabling the MMU.  Essentially
++	 * this is just loading the page table pointer and domain access
++	 * registers.
++	 */
++	#ifndef CONFIG_ALIGNMENT_TRAP
++		andn	r0, r0, #CR_A
++	#endif
++	#ifdef CONFIG_CPU_DCACHE_DISABLE
++		andn	r0, r0, #CR_D
++	#endif
++	#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
++		andn	r0, r0, #CR_B
++	#endif
++	#ifdef CONFIG_CPU_ICACHE_DISABLE
++		andn	r0, r0, #CR_I
++	#endif
++
++	movc	p0.c2, r4, #0			@ set pgd
++	b	__turn_mmu_on
++ENDPROC(stext)
++
++/*
++ * Enable the MMU.  This completely changes the stucture of the visible
++ * memory space.  You will not be able to trace execution through this.
++ *
++ *  r0  = cp#0 control register
++ *  r15 = *virtual* address to jump to upon completion
++ */
++	.align	5
++__turn_mmu_on:
++	mov	r0, r0
++	movc	p0.c1, r0, #0			@ write control reg
++	nop					@ fetch inst by phys addr
++	mov	pc, r15
++	nop8					@ fetch inst by phys addr
++ENDPROC(__turn_mmu_on)
++
++/*
++ * Setup the initial page tables.  We only setup the barest
++ * amount which are required to get the kernel running, which
++ * generally means mapping in the kernel code.
++ *
++ * r9  = cpuid
++ * r10 = procinfo
++ *
++ * Returns:
++ *  r0, r3, r6, r7 corrupted
++ *  r4 = physical page table address
++ */
++	.ltorg
++
++	.align	2
++	.type	__switch_data, %object
++__switch_data:
++	.long	__mmap_switched
++	.long	__bss_start			@ r6
++	.long	_end				@ r7
++	.long	cr_alignment			@ r8
++	.long	init_thread_union + THREAD_START_SP @ sp
++
++/*
++ * The following fragment of code is executed with the MMU on in MMU mode,
++ * and uses absolute addresses; this is not position independent.
++ *
++ *  r0  = cp#0 control register
++ */
++__mmap_switched:
++	adr	r3, __switch_data + 4
++
++	ldm.w	(r6, r7, r8), [r3]+
++	ldw	sp, [r3]
++
++	mov	fp, #0				@ Clear BSS (and zero fp)
++203:	csub.a	r6, r7
++	bea	204f
++	stw.w	fp, [r6]+,#4
++	b	203b
++204:
++	andn	r1, r0, #CR_A			@ Clear 'A' bit
++	stm	(r0, r1), [r8]+			@ Save control register values
++	b	start_kernel
++ENDPROC(__mmap_switched)
++
++/*
++ * Exception handling.  Something went wrong and we can't proceed.  We
++ * ought to tell the user, but since we don't have any guarantee that
++ * we're even running on the right architecture, we do virtually nothing.
++ *
++ * If CONFIG_DEBUG_LL is set we try to print out something about the error
++ * and hope for the best (useful if bootloader fails to pass a proper
++ * machine ID for example).
++ */
++__error_p:
++#ifdef CONFIG_DEBUG_LL
++	adr	r0, str_p1
++	b.l	printascii
++	mov	r0, r9
++	b.l	printhex8
++	adr	r0, str_p2
++	b.l	printascii
++901:	nop8
++	b	901b
++str_p1:	.asciz	"\nError: unrecognized processor variant (0x"
++str_p2:	.asciz	").\n"
++	.align
++#endif
++ENDPROC(__error_p)
++
+diff --git a/arch/unicore32/kernel/setup.c b/arch/unicore32/kernel/setup.c
+new file mode 100644
+index 000000000000..1e175a82844d
+--- /dev/null
++++ b/arch/unicore32/kernel/setup.c
+@@ -0,0 +1,360 @@
++/*
++ * linux/arch/unicore32/kernel/setup.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include "setup.h"
++
++#ifndef MEM_SIZE
++#define MEM_SIZE	(16*1024*1024)
++#endif
++
++struct stack {
++	u32 irq[3];
++	u32 abt[3];
++	u32 und[3];
++} ____cacheline_aligned;
++
++static struct stack stacks[NR_CPUS];
++
++char elf_platform[ELF_PLATFORM_SIZE];
++EXPORT_SYMBOL(elf_platform);
++
++static char __initdata cmd_line[COMMAND_LINE_SIZE];
++
++static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
++
++/*
++ * Standard memory resources
++ */
++static struct resource mem_res[] = {
++	{
++		.name = "Video RAM",
++		.start = 0,
++		.end = 0,
++		.flags = IORESOURCE_MEM
++	},
++	{
++		.name = "Kernel text",
++		.start = 0,
++		.end = 0,
++		.flags = IORESOURCE_MEM
++	},
++	{
++		.name = "Kernel data",
++		.start = 0,
++		.end = 0,
++		.flags = IORESOURCE_MEM
++	}
++};
++
++#define video_ram   mem_res[0]
++#define kernel_code mem_res[1]
++#define kernel_data mem_res[2]
++
++/*
++ * These functions re-use the assembly code in head.S, which
++ * already provide the required functionality.
++ */
++static void __init setup_processor(void)
++{
++	printk(KERN_DEFAULT "CPU: UniCore-II [%08x] revision %d, cr=%08lx\n",
++	       uc32_cpuid, (int)(uc32_cpuid >> 16) & 15, cr_alignment);
++
++	sprintf(init_utsname()->machine, "puv3");
++	sprintf(elf_platform, "ucv2");
++}
++
++/*
++ * cpu_init - initialise one CPU.
++ *
++ * cpu_init sets up the per-CPU stacks.
++ */
++void cpu_init(void)
++{
++	unsigned int cpu = smp_processor_id();
++	struct stack *stk = &stacks[cpu];
++
++	/*
++	 * setup stacks for re-entrant exception handlers
++	 */
++	__asm__ (
++	"mov.a	asr, %1\n\t"
++	"add	sp, %0, %2\n\t"
++	"mov.a	asr, %3\n\t"
++	"add	sp, %0, %4\n\t"
++	"mov.a	asr, %5\n\t"
++	"add	sp, %0, %6\n\t"
++	"mov.a	asr, %7"
++	    :
++	    : "r" (stk),
++	      "r" (PSR_R_BIT | PSR_I_BIT | INTR_MODE),
++	      "I" (offsetof(struct stack, irq[0])),
++	      "r" (PSR_R_BIT | PSR_I_BIT | ABRT_MODE),
++	      "I" (offsetof(struct stack, abt[0])),
++	      "r" (PSR_R_BIT | PSR_I_BIT | EXTN_MODE),
++	      "I" (offsetof(struct stack, und[0])),
++	      "r" (PSR_R_BIT | PSR_I_BIT | PRIV_MODE)
++	: "r30", "cc");
++}
++
++static int __init uc32_add_memory(unsigned long start, unsigned long size)
++{
++	struct membank *bank = &meminfo.bank[meminfo.nr_banks];
++
++	if (meminfo.nr_banks >= NR_BANKS) {
++		printk(KERN_CRIT "NR_BANKS too low, "
++			"ignoring memory at %#lx\n", start);
++		return -EINVAL;
++	}
++
++	/*
++	 * Ensure that start/size are aligned to a page boundary.
++	 * Size is appropriately rounded down, start is rounded up.
++	 */
++	size -= start & ~PAGE_MASK;
++
++	bank->start = PAGE_ALIGN(start);
++	bank->size  = size & PAGE_MASK;
++
++	/*
++	 * Check whether this memory region has non-zero size or
++	 * invalid node number.
++	 */
++	if (bank->size == 0)
++		return -EINVAL;
++
++	meminfo.nr_banks++;
++	return 0;
++}
++
++/*
++ * Pick out the memory size.  We look for mem=size@start,
++ * where start and size are "size[KkMm]"
++ */
++static int __init early_mem(char *p)
++{
++	static int usermem __initdata = 1;
++	unsigned long size, start;
++	char *endp;
++
++	/*
++	 * If the user specifies memory size, we
++	 * blow away any automatically generated
++	 * size.
++	 */
++	if (usermem) {
++		usermem = 0;
++		meminfo.nr_banks = 0;
++	}
++
++	start = PHYS_OFFSET;
++	size  = memparse(p, &endp);
++	if (*endp == '@')
++		start = memparse(endp + 1, NULL);
++
++	uc32_add_memory(start, size);
++
++	return 0;
++}
++early_param("mem", early_mem);
++
++static void __init
++request_standard_resources(struct meminfo *mi)
++{
++	struct resource *res;
++	int i;
++
++	kernel_code.start   = virt_to_phys(_stext);
++	kernel_code.end     = virt_to_phys(_etext - 1);
++	kernel_data.start   = virt_to_phys(_sdata);
++	kernel_data.end     = virt_to_phys(_end - 1);
++
++	for (i = 0; i < mi->nr_banks; i++) {
++		if (mi->bank[i].size == 0)
++			continue;
++
++		res = alloc_bootmem_low(sizeof(*res));
++		res->name  = "System RAM";
++		res->start = mi->bank[i].start;
++		res->end   = mi->bank[i].start + mi->bank[i].size - 1;
++		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
++
++		request_resource(&iomem_resource, res);
++
++		if (kernel_code.start >= res->start &&
++		    kernel_code.end <= res->end)
++			request_resource(res, &kernel_code);
++		if (kernel_data.start >= res->start &&
++		    kernel_data.end <= res->end)
++			request_resource(res, &kernel_data);
++	}
++
++	video_ram.start = PKUNITY_UNIGFX_MMAP_BASE;
++	video_ram.end   = PKUNITY_UNIGFX_MMAP_BASE + PKUNITY_UNIGFX_MMAP_SIZE;
++	request_resource(&iomem_resource, &video_ram);
++}
++
++static void (*init_machine)(void) __initdata;
++
++static int __init customize_machine(void)
++{
++	/* customizes platform devices, or adds new ones */
++	if (init_machine)
++		init_machine();
++	return 0;
++}
++arch_initcall(customize_machine);
++
++void __init setup_arch(char **cmdline_p)
++{
++	char *from = default_command_line;
++
++	setup_processor();
++
++	init_mm.start_code = (unsigned long) _stext;
++	init_mm.end_code   = (unsigned long) _etext;
++	init_mm.end_data   = (unsigned long) _edata;
++	init_mm.brk	   = (unsigned long) _end;
++
++	/* parse_early_param needs a boot_command_line */
++	strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
++
++	/* populate cmd_line too for later use, preserving boot_command_line */
++	strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
++	*cmdline_p = cmd_line;
++
++	parse_early_param();
++
++	uc32_memblock_init(&meminfo);
++
++	paging_init();
++	request_standard_resources(&meminfo);
++
++	cpu_init();
++
++	/*
++	 * Set up various architecture-specific pointers
++	 */
++	init_machine = puv3_core_init;
++
++#ifdef CONFIG_VT
++#if defined(CONFIG_VGA_CONSOLE)
++	conswitchp = &vga_con;
++#elif defined(CONFIG_DUMMY_CONSOLE)
++	conswitchp = &dummy_con;
++#endif
++#endif
++	early_trap_init();
++}
++
++static struct cpu cpuinfo_unicore;
++
++static int __init topology_init(void)
++{
++	int i;
++
++	for_each_possible_cpu(i)
++		register_cpu(&cpuinfo_unicore, i);
++
++	return 0;
++}
++subsys_initcall(topology_init);
++
++#ifdef CONFIG_HAVE_PROC_CPU
++static int __init proc_cpu_init(void)
++{
++	struct proc_dir_entry *res;
++
++	res = proc_mkdir("cpu", NULL);
++	if (!res)
++		return -ENOMEM;
++	return 0;
++}
++fs_initcall(proc_cpu_init);
++#endif
++
++static int c_show(struct seq_file *m, void *v)
++{
++	seq_printf(m, "Processor\t: UniCore-II rev %d (%s)\n",
++		   (int)(uc32_cpuid >> 16) & 15, elf_platform);
++
++	seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
++		   loops_per_jiffy / (500000/HZ),
++		   (loops_per_jiffy / (5000/HZ)) % 100);
++
++	/* dump out the processor features */
++	seq_puts(m, "Features\t: CMOV UC-F64");
++
++	seq_printf(m, "\nCPU implementer\t: 0x%02x\n", uc32_cpuid >> 24);
++	seq_printf(m, "CPU architecture: 2\n");
++	seq_printf(m, "CPU revision\t: %d\n", (uc32_cpuid >> 16) & 15);
++
++	seq_printf(m, "Cache type\t: write-back\n"
++			"Cache clean\t: cp0 c5 ops\n"
++			"Cache lockdown\t: not support\n"
++			"Cache format\t: Harvard\n");
++
++	seq_puts(m, "\n");
++
++	seq_printf(m, "Hardware\t: PKUnity v3\n");
++
++	return 0;
++}
++
++static void *c_start(struct seq_file *m, loff_t *pos)
++{
++	return *pos < 1 ? (void *)1 : NULL;
++}
++
++static void *c_next(struct seq_file *m, void *v, loff_t *pos)
++{
++	++*pos;
++	return NULL;
++}
++
++static void c_stop(struct seq_file *m, void *v)
++{
++}
++
++const struct seq_operations cpuinfo_op = {
++	.start	= c_start,
++	.next	= c_next,
++	.stop	= c_stop,
++	.show	= c_show
++};
+diff --git a/arch/unicore32/kernel/setup.h b/arch/unicore32/kernel/setup.h
+new file mode 100644
+index 000000000000..dcd1306eb5c6
+--- /dev/null
++++ b/arch/unicore32/kernel/setup.h
+@@ -0,0 +1,30 @@
++/*
++ * linux/arch/unicore32/kernel/setup.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_KERNEL_SETUP_H__
++#define __UNICORE_KERNEL_SETUP_H__
++
++extern void paging_init(void);
++extern void puv3_core_init(void);
++
++extern void puv3_ps2_init(void);
++extern void pci_puv3_preinit(void);
++extern void __init puv3_init_gpio(void);
++
++extern void setup_mm_for_reboot(char mode);
++
++extern char __stubs_start[], __stubs_end[];
++extern char __vectors_start[], __vectors_end[];
++
++extern void kernel_thread_helper(void);
++
++extern void __init early_signal_init(void);
++#endif
+diff --git a/arch/unicore32/kernel/traps.c b/arch/unicore32/kernel/traps.c
+new file mode 100644
+index 000000000000..25abbb101729
+--- /dev/null
++++ b/arch/unicore32/kernel/traps.c
+@@ -0,0 +1,333 @@
++/*
++ * linux/arch/unicore32/kernel/traps.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ *  'traps.c' handles hardware exceptions after we have saved some state.
++ *  Mostly a debugging aid, but will probably kill the offending process.
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++#include 
++#include 
++
++#include "setup.h"
++
++static void dump_mem(const char *, const char *, unsigned long, unsigned long);
++
++void dump_backtrace_entry(unsigned long where,
++		unsigned long from, unsigned long frame)
++{
++#ifdef CONFIG_KALLSYMS
++	printk(KERN_DEFAULT "[<%08lx>] (%pS) from [<%08lx>] (%pS)\n",
++			where, (void *)where, from, (void *)from);
++#else
++	printk(KERN_DEFAULT "Function entered at [<%08lx>] from [<%08lx>]\n",
++			where, from);
++#endif
++}
++
++/*
++ * Stack pointers should always be within the kernels view of
++ * physical memory.  If it is not there, then we can't dump
++ * out any information relating to the stack.
++ */
++static int verify_stack(unsigned long sp)
++{
++	if (sp < PAGE_OFFSET ||
++	    (sp > (unsigned long)high_memory && high_memory != NULL))
++		return -EFAULT;
++
++	return 0;
++}
++
++/*
++ * Dump out the contents of some memory nicely...
++ */
++static void dump_mem(const char *lvl, const char *str, unsigned long bottom,
++		     unsigned long top)
++{
++	unsigned long first;
++	mm_segment_t fs;
++	int i;
++
++	/*
++	 * We need to switch to kernel mode so that we can use __get_user
++	 * to safely read from kernel space.  Note that we now dump the
++	 * code first, just in case the backtrace kills us.
++	 */
++	fs = get_fs();
++	set_fs(KERNEL_DS);
++
++	printk(KERN_DEFAULT "%s%s(0x%08lx to 0x%08lx)\n",
++			lvl, str, bottom, top);
++
++	for (first = bottom & ~31; first < top; first += 32) {
++		unsigned long p;
++		char str[sizeof(" 12345678") * 8 + 1];
++
++		memset(str, ' ', sizeof(str));
++		str[sizeof(str) - 1] = '\0';
++
++		for (p = first, i = 0; i < 8 && p < top; i++, p += 4) {
++			if (p >= bottom && p < top) {
++				unsigned long val;
++				if (__get_user(val, (unsigned long *)p) == 0)
++					sprintf(str + i * 9, " %08lx", val);
++				else
++					sprintf(str + i * 9, " ????????");
++			}
++		}
++		printk(KERN_DEFAULT "%s%04lx:%s\n", lvl, first & 0xffff, str);
++	}
++
++	set_fs(fs);
++}
++
++static void dump_instr(const char *lvl, struct pt_regs *regs)
++{
++	unsigned long addr = instruction_pointer(regs);
++	const int width = 8;
++	mm_segment_t fs;
++	char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str;
++	int i;
++
++	/*
++	 * We need to switch to kernel mode so that we can use __get_user
++	 * to safely read from kernel space.  Note that we now dump the
++	 * code first, just in case the backtrace kills us.
++	 */
++	fs = get_fs();
++	set_fs(KERNEL_DS);
++
++	for (i = -4; i < 1; i++) {
++		unsigned int val, bad;
++
++		bad = __get_user(val, &((u32 *)addr)[i]);
++
++		if (!bad)
++			p += sprintf(p, i == 0 ? "(%0*x) " : "%0*x ",
++					width, val);
++		else {
++			p += sprintf(p, "bad PC value");
++			break;
++		}
++	}
++	printk(KERN_DEFAULT "%sCode: %s\n", lvl, str);
++
++	set_fs(fs);
++}
++
++static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
++{
++	unsigned int fp, mode;
++	int ok = 1;
++
++	printk(KERN_DEFAULT "Backtrace: ");
++
++	if (!tsk)
++		tsk = current;
++
++	if (regs) {
++		fp = regs->UCreg_fp;
++		mode = processor_mode(regs);
++	} else if (tsk != current) {
++		fp = thread_saved_fp(tsk);
++		mode = 0x10;
++	} else {
++		asm("mov %0, fp" : "=r" (fp) : : "cc");
++		mode = 0x10;
++	}
++
++	if (!fp) {
++		printk("no frame pointer");
++		ok = 0;
++	} else if (verify_stack(fp)) {
++		printk("invalid frame pointer 0x%08x", fp);
++		ok = 0;
++	} else if (fp < (unsigned long)end_of_stack(tsk))
++		printk("frame pointer underflow");
++	printk("\n");
++
++	if (ok)
++		c_backtrace(fp, mode);
++}
++
++void dump_stack(void)
++{
++	dump_backtrace(NULL, NULL);
++}
++EXPORT_SYMBOL(dump_stack);
++
++void show_stack(struct task_struct *tsk, unsigned long *sp)
++{
++	dump_backtrace(NULL, tsk);
++	barrier();
++}
++
++static int __die(const char *str, int err, struct thread_info *thread,
++		struct pt_regs *regs)
++{
++	struct task_struct *tsk = thread->task;
++	static int die_counter;
++	int ret;
++
++	printk(KERN_EMERG "Internal error: %s: %x [#%d]\n",
++	       str, err, ++die_counter);
++	sysfs_printk_last_file();
++
++	/* trap and error numbers are mostly meaningless on UniCore */
++	ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, \
++			SIGSEGV);
++	if (ret == NOTIFY_STOP)
++		return ret;
++
++	print_modules();
++	__show_regs(regs);
++	printk(KERN_EMERG "Process %.*s (pid: %d, stack limit = 0x%p)\n",
++		TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), thread + 1);
++
++	if (!user_mode(regs) || in_interrupt()) {
++		dump_mem(KERN_EMERG, "Stack: ", regs->UCreg_sp,
++			 THREAD_SIZE + (unsigned long)task_stack_page(tsk));
++		dump_backtrace(regs, tsk);
++		dump_instr(KERN_EMERG, regs);
++	}
++
++	return ret;
++}
++
++DEFINE_SPINLOCK(die_lock);
++
++/*
++ * This function is protected against re-entrancy.
++ */
++void die(const char *str, struct pt_regs *regs, int err)
++{
++	struct thread_info *thread = current_thread_info();
++	int ret;
++
++	oops_enter();
++
++	spin_lock_irq(&die_lock);
++	console_verbose();
++	bust_spinlocks(1);
++	ret = __die(str, err, thread, regs);
++
++	bust_spinlocks(0);
++	add_taint(TAINT_DIE);
++	spin_unlock_irq(&die_lock);
++	oops_exit();
++
++	if (in_interrupt())
++		panic("Fatal exception in interrupt");
++	if (panic_on_oops)
++		panic("Fatal exception");
++	if (ret != NOTIFY_STOP)
++		do_exit(SIGSEGV);
++}
++
++void uc32_notify_die(const char *str, struct pt_regs *regs,
++		struct siginfo *info, unsigned long err, unsigned long trap)
++{
++	if (user_mode(regs)) {
++		current->thread.error_code = err;
++		current->thread.trap_no = trap;
++
++		force_sig_info(info->si_signo, info, current);
++	} else
++		die(str, regs, err);
++}
++
++/*
++ * bad_mode handles the impossible case in the vectors.  If you see one of
++ * these, then it's extremely serious, and could mean you have buggy hardware.
++ * It never returns, and never tries to sync.  We hope that we can at least
++ * dump out some state information...
++ */
++asmlinkage void bad_mode(struct pt_regs *regs, unsigned int reason)
++{
++	console_verbose();
++
++	printk(KERN_CRIT "Bad mode detected with reason 0x%x\n", reason);
++
++	die("Oops - bad mode", regs, 0);
++	local_irq_disable();
++	panic("bad mode");
++}
++
++void __pte_error(const char *file, int line, unsigned long val)
++{
++	printk(KERN_DEFAULT "%s:%d: bad pte %08lx.\n", file, line, val);
++}
++
++void __pmd_error(const char *file, int line, unsigned long val)
++{
++	printk(KERN_DEFAULT "%s:%d: bad pmd %08lx.\n", file, line, val);
++}
++
++void __pgd_error(const char *file, int line, unsigned long val)
++{
++	printk(KERN_DEFAULT "%s:%d: bad pgd %08lx.\n", file, line, val);
++}
++
++asmlinkage void __div0(void)
++{
++	printk(KERN_DEFAULT "Division by zero in kernel.\n");
++	dump_stack();
++}
++EXPORT_SYMBOL(__div0);
++
++void abort(void)
++{
++	BUG();
++
++	/* if that doesn't kill us, halt */
++	panic("Oops failed to kill thread");
++}
++EXPORT_SYMBOL(abort);
++
++void __init trap_init(void)
++{
++	return;
++}
++
++void __init early_trap_init(void)
++{
++	unsigned long vectors = VECTORS_BASE;
++
++	/*
++	 * Copy the vectors, stubs (in entry-unicore.S)
++	 * into the vector page, mapped at 0xffff0000, and ensure these
++	 * are visible to the instruction stream.
++	 */
++	memcpy((void *)vectors,
++			__vectors_start,
++			__vectors_end - __vectors_start);
++	memcpy((void *)vectors + 0x200,
++			__stubs_start,
++			__stubs_end - __stubs_start);
++
++	early_signal_init();
++
++	flush_icache_range(vectors, vectors + PAGE_SIZE);
++}

commit 79725df5786d2fa48f582b116ea1d74193cc96ca
+Author: GuanXuetao 
+Date:   Sat Jan 15 18:15:01 2011 +0800
+
+    unicore32 core architecture: processor and system headers
+    
+    This patch includes processor and system headers. System call interface is here.
+    We used the syscall interface the same as asm-generic version.
+    
+    Signed-off-by: Guan Xuetao 
+    Reviewed-by: Arnd Bergmann 
+
+diff --git a/arch/unicore32/include/asm/byteorder.h b/arch/unicore32/include/asm/byteorder.h
+new file mode 100644
+index 000000000000..ebe1b3fef3e3
+--- /dev/null
++++ b/arch/unicore32/include/asm/byteorder.h
+@@ -0,0 +1,24 @@
++/*
++ * linux/arch/unicore32/include/asm/byteorder.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * UniCore ONLY support Little Endian mode, the data bus is connected such
++ * that byte accesses appear as:
++ *  0 = d0...d7, 1 = d8...d15, 2 = d16...d23, 3 = d24...d31
++ * and word accesses (data or instruction) appear as:
++ *  d0...d31
++ */
++#ifndef __UNICORE_BYTEORDER_H__
++#define __UNICORE_BYTEORDER_H__
++
++#include 
++
++#endif
++
+diff --git a/arch/unicore32/include/asm/cpu-single.h b/arch/unicore32/include/asm/cpu-single.h
+new file mode 100644
+index 000000000000..0f55d1823439
+--- /dev/null
++++ b/arch/unicore32/include/asm/cpu-single.h
+@@ -0,0 +1,45 @@
++/*
++ * linux/arch/unicore32/include/asm/cpu-single.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_CPU_SINGLE_H__
++#define __UNICORE_CPU_SINGLE_H__
++
++#include 
++#include 
++
++#ifdef __KERNEL__
++#ifndef __ASSEMBLY__
++
++#define cpu_switch_mm(pgd, mm) cpu_do_switch_mm(virt_to_phys(pgd), mm)
++
++#define cpu_get_pgd()					\
++	({						\
++		unsigned long pg;			\
++		__asm__("movc	%0, p0.c2, #0"		\
++			 : "=r" (pg) : : "cc");		\
++		pg &= ~0x0fff;				\
++		(pgd_t *)phys_to_virt(pg);		\
++	})
++
++struct mm_struct;
++
++/* declare all the functions as extern */
++extern void cpu_proc_fin(void);
++extern int cpu_do_idle(void);
++extern void cpu_dcache_clean_area(void *, int);
++extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm);
++extern void cpu_set_pte(pte_t *ptep, pte_t pte);
++extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
++
++#endif /* __ASSEMBLY__ */
++#endif /* __KERNEL__ */
++
++#endif /* __UNICORE_CPU_SINGLE_H__ */
+diff --git a/arch/unicore32/include/asm/cputype.h b/arch/unicore32/include/asm/cputype.h
+new file mode 100644
+index 000000000000..ec1a30f98077
+--- /dev/null
++++ b/arch/unicore32/include/asm/cputype.h
+@@ -0,0 +1,33 @@
++/*
++ * linux/arch/unicore32/include/asm/cputype.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_CPUTYPE_H__
++#define __UNICORE_CPUTYPE_H__
++
++#include 
++
++#define CPUID_CPUID	0
++#define CPUID_CACHETYPE	1
++
++#define read_cpuid(reg)							\
++	({								\
++		unsigned int __val;					\
++		asm("movc	%0, p0.c0, #" __stringify(reg)		\
++		    : "=r" (__val)					\
++		    :							\
++		    : "cc");						\
++		__val;							\
++	})
++
++#define uc32_cpuid		read_cpuid(CPUID_CPUID)
++#define uc32_cachetype		read_cpuid(CPUID_CACHETYPE)
++
++#endif
+diff --git a/arch/unicore32/include/asm/hwcap.h b/arch/unicore32/include/asm/hwcap.h
+new file mode 100644
+index 000000000000..97bd40fdd4ac
+--- /dev/null
++++ b/arch/unicore32/include/asm/hwcap.h
+@@ -0,0 +1,32 @@
++/*
++ * linux/arch/unicore32/include/asm/hwcap.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_HWCAP_H__
++#define __UNICORE_HWCAP_H__
++
++/*
++ * HWCAP flags
++ */
++#define HWCAP_MSP		1
++#define HWCAP_UNICORE16		2
++#define HWCAP_CMOV		4
++#define HWCAP_UNICORE_F64       8
++#define HWCAP_TLS		0x80
++
++#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
++/*
++ * This yields a mask that user programs can use to figure out what
++ * instruction set this cpu supports.
++ */
++#define ELF_HWCAP		(HWCAP_CMOV | HWCAP_UNICORE_F64)
++#endif
++
++#endif
+diff --git a/arch/unicore32/include/asm/processor.h b/arch/unicore32/include/asm/processor.h
+new file mode 100644
+index 000000000000..e11cb0786578
+--- /dev/null
++++ b/arch/unicore32/include/asm/processor.h
+@@ -0,0 +1,92 @@
++/*
++ * linux/arch/unicore32/include/asm/processor.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __UNICORE_PROCESSOR_H__
++#define __UNICORE_PROCESSOR_H__
++
++/*
++ * Default implementation of macro that returns current
++ * instruction pointer ("program counter").
++ */
++#define current_text_addr() ({ __label__ _l; _l: &&_l; })
++
++#ifdef __KERNEL__
++
++#include 
++#include 
++
++#ifdef __KERNEL__
++#define STACK_TOP	TASK_SIZE
++#define STACK_TOP_MAX	TASK_SIZE
++#endif
++
++struct debug_entry {
++	u32			address;
++	u32			insn;
++};
++
++struct debug_info {
++	int			nsaved;
++	struct debug_entry	bp[2];
++};
++
++struct thread_struct {
++							/* fault info	  */
++	unsigned long		address;
++	unsigned long		trap_no;
++	unsigned long		error_code;
++							/* debugging	  */
++	struct debug_info	debug;
++};
++
++#define INIT_THREAD  {	}
++
++#define start_thread(regs, pc, sp)					\
++({									\
++	unsigned long *stack = (unsigned long *)sp;			\
++	set_fs(USER_DS);						\
++	memset(regs->uregs, 0, sizeof(regs->uregs));			\
++	regs->UCreg_asr = USER_MODE;					\
++	regs->UCreg_pc = pc & ~1;	/* pc */                        \
++	regs->UCreg_sp = sp;		/* sp */                        \
++	regs->UCreg_02 = stack[2];	/* r2 (envp) */                 \
++	regs->UCreg_01 = stack[1];	/* r1 (argv) */                 \
++	regs->UCreg_00 = stack[0];	/* r0 (argc) */                 \
++})
++
++/* Forward declaration, a strange C thing */
++struct task_struct;
++
++/* Free all resources held by a thread. */
++extern void release_thread(struct task_struct *);
++
++/* Prepare to copy thread state - unlazy all lazy status */
++#define prepare_to_copy(tsk)	do { } while (0)
++
++unsigned long get_wchan(struct task_struct *p);
++
++#define cpu_relax()			barrier()
++
++/*
++ * Create a new kernel thread
++ */
++extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
++
++#define task_pt_regs(p) \
++	((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)
++
++#define KSTK_EIP(tsk)	(task_pt_regs(tsk)->UCreg_pc)
++#define KSTK_ESP(tsk)	(task_pt_regs(tsk)->UCreg_sp)
++
++#endif
++
++#endif /* __UNICORE_PROCESSOR_H__ */
+diff --git a/arch/unicore32/include/asm/system.h b/arch/unicore32/include/asm/system.h
+new file mode 100644
+index 000000000000..246b71c17fda
+--- /dev/null
++++ b/arch/unicore32/include/asm/system.h
+@@ -0,0 +1,161 @@
++/*
++ * linux/arch/unicore32/include/asm/system.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_SYSTEM_H__
++#define __UNICORE_SYSTEM_H__
++
++#ifdef __KERNEL__
++
++/*
++ * CR1 bits (CP#0 CR1)
++ */
++#define CR_M	(1 << 0)	/* MMU enable				*/
++#define CR_A	(1 << 1)	/* Alignment abort enable		*/
++#define CR_D	(1 << 2)	/* Dcache enable			*/
++#define CR_I	(1 << 3)	/* Icache enable			*/
++#define CR_B	(1 << 4)	/* Dcache write mechanism: write back	*/
++#define CR_T	(1 << 5)	/* Burst enable				*/
++#define CR_V	(1 << 13)	/* Vectors relocated to 0xffff0000	*/
++
++#ifndef __ASSEMBLY__
++
++#include 
++#include 
++
++struct thread_info;
++struct task_struct;
++
++struct pt_regs;
++
++void die(const char *msg, struct pt_regs *regs, int err);
++
++struct siginfo;
++void uc32_notify_die(const char *str, struct pt_regs *regs,
++		struct siginfo *info, unsigned long err, unsigned long trap);
++
++void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
++				       struct pt_regs *),
++		     int sig, int code, const char *name);
++
++#define xchg(ptr, x) \
++	((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
++
++extern asmlinkage void __backtrace(void);
++extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
++
++struct mm_struct;
++extern void show_pte(struct mm_struct *mm, unsigned long addr);
++extern void __show_regs(struct pt_regs *);
++
++extern int cpu_architecture(void);
++extern void cpu_init(void);
++
++#define vectors_high()	(cr_alignment & CR_V)
++
++#define isb() __asm__ __volatile__ ("" : : : "memory")
++#define dsb() __asm__ __volatile__ ("" : : : "memory")
++#define dmb() __asm__ __volatile__ ("" : : : "memory")
++
++#define mb()		barrier()
++#define rmb()		barrier()
++#define wmb()		barrier()
++#define smp_mb()	barrier()
++#define smp_rmb()	barrier()
++#define smp_wmb()	barrier()
++#define read_barrier_depends()		do { } while (0)
++#define smp_read_barrier_depends()	do { } while (0)
++
++#define set_mb(var, value)	do { var = value; smp_mb(); } while (0)
++#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
++
++extern unsigned long cr_no_alignment;	/* defined in entry-unicore.S */
++extern unsigned long cr_alignment;	/* defined in entry-unicore.S */
++
++static inline unsigned int get_cr(void)
++{
++	unsigned int val;
++	asm("movc %0, p0.c1, #0" : "=r" (val) : : "cc");
++	return val;
++}
++
++static inline void set_cr(unsigned int val)
++{
++	asm volatile("movc p0.c1, %0, #0	@set CR"
++	  : : "r" (val) : "cc");
++	isb();
++}
++
++extern void adjust_cr(unsigned long mask, unsigned long set);
++
++/*
++ * switch_to(prev, next) should switch from task `prev' to `next'
++ * `prev' will never be the same as `next'.  schedule() itself
++ * contains the memory barrier to tell GCC not to cache `current'.
++ */
++extern struct task_struct *__switch_to(struct task_struct *,
++		struct thread_info *, struct thread_info *);
++extern void panic(const char *fmt, ...);
++
++#define switch_to(prev, next, last)					\
++do {									\
++	last = __switch_to(prev,					\
++		task_thread_info(prev), task_thread_info(next));	\
++} while (0)
++
++static inline unsigned long
++__xchg(unsigned long x, volatile void *ptr, int size)
++{
++	unsigned long ret;
++
++	switch (size) {
++	case 1:
++		asm volatile("@	__xchg1\n"
++		"	swapb	%0, %1, [%2]"
++			: "=&r" (ret)
++			: "r" (x), "r" (ptr)
++			: "memory", "cc");
++		break;
++	case 4:
++		asm volatile("@	__xchg4\n"
++		"	swapw	%0, %1, [%2]"
++			: "=&r" (ret)
++			: "r" (x), "r" (ptr)
++			: "memory", "cc");
++		break;
++	default:
++		panic("xchg: bad data size: ptr 0x%p, size %d\n",
++			ptr, size);
++	}
++
++	return ret;
++}
++
++#include 
++
++/*
++ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
++ * them available.
++ */
++#define cmpxchg_local(ptr, o, n)					\
++		((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr),	\
++		(unsigned long)(o), (unsigned long)(n), sizeof(*(ptr))))
++#define cmpxchg64_local(ptr, o, n)					\
++		__cmpxchg64_local_generic((ptr), (o), (n))
++
++#include 
++
++#endif /* __ASSEMBLY__ */
++
++#define arch_align_stack(x) (x)
++
++#endif /* __KERNEL__ */
++
++#endif
+diff --git a/arch/unicore32/include/asm/unistd.h b/arch/unicore32/include/asm/unistd.h
+new file mode 100644
+index 000000000000..9b2428019961
+--- /dev/null
++++ b/arch/unicore32/include/asm/unistd.h
+@@ -0,0 +1,18 @@
++/*
++ * linux/arch/unicore32/include/asm/unistd.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#if !defined(__UNICORE_UNISTD_H__) || defined(__SYSCALL)
++#define __UNICORE_UNISTD_H__
++
++/* Use the standard ABI for syscalls. */
++#include 
++
++#endif /* __UNICORE_UNISTD_H__ */
+diff --git a/arch/unicore32/kernel/sys.c b/arch/unicore32/kernel/sys.c
+new file mode 100644
+index 000000000000..3afe60a39ac9
+--- /dev/null
++++ b/arch/unicore32/kernel/sys.c
+@@ -0,0 +1,126 @@
++/*
++ * linux/arch/unicore32/kernel/sys.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++#include 
++
++/* Clone a task - this clones the calling program thread.
++ * This is called indirectly via a small wrapper
++ */
++asmlinkage long __sys_clone(unsigned long clone_flags, unsigned long newsp,
++			 void __user *parent_tid, void __user *child_tid,
++			 struct pt_regs *regs)
++{
++	if (!newsp)
++		newsp = regs->UCreg_sp;
++
++	return do_fork(clone_flags, newsp, regs, 0,
++			parent_tid, child_tid);
++}
++
++/* sys_execve() executes a new program.
++ * This is called indirectly via a small wrapper
++ */
++asmlinkage long __sys_execve(const char __user *filename,
++			  const char __user *const __user *argv,
++			  const char __user *const __user *envp,
++			  struct pt_regs *regs)
++{
++	int error;
++	char *fn;
++
++	fn = getname(filename);
++	error = PTR_ERR(fn);
++	if (IS_ERR(fn))
++		goto out;
++	error = do_execve(fn, argv, envp, regs);
++	putname(fn);
++out:
++	return error;
++}
++
++int kernel_execve(const char *filename,
++		  const char *const argv[],
++		  const char *const envp[])
++{
++	struct pt_regs regs;
++	int ret;
++
++	memset(®s, 0, sizeof(struct pt_regs));
++	ret = do_execve(filename,
++			(const char __user *const __user *)argv,
++			(const char __user *const __user *)envp, ®s);
++	if (ret < 0)
++		goto out;
++
++	/*
++	 * Save argc to the register structure for userspace.
++	 */
++	regs.UCreg_00 = ret;
++
++	/*
++	 * We were successful.  We won't be returning to our caller, but
++	 * instead to user space by manipulating the kernel stack.
++	 */
++	asm("add	r0, %0, %1\n\t"
++		"mov	r1, %2\n\t"
++		"mov	r2, %3\n\t"
++		"mov	r22, #0\n\t"	/* not a syscall */
++		"mov	r23, %0\n\t"	/* thread structure */
++		"b.l	memmove\n\t"	/* copy regs to top of stack */
++		"mov	sp, r0\n\t"	/* reposition stack pointer */
++		"b	ret_to_user"
++		:
++		: "r" (current_thread_info()),
++		  "Ir" (THREAD_START_SP - sizeof(regs)),
++		  "r" (®s),
++		  "Ir" (sizeof(regs))
++		: "r0", "r1", "r2", "r3", "ip", "lr", "memory");
++
++ out:
++	return ret;
++}
++EXPORT_SYMBOL(kernel_execve);
++
++/* Note: used by the compat code even in 64-bit Linux. */
++SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
++		unsigned long, prot, unsigned long, flags,
++		unsigned long, fd, unsigned long, off_4k)
++{
++	return sys_mmap_pgoff(addr, len, prot, flags, fd,
++			      off_4k);
++}
++
++/* Provide the actual syscall number to call mapping. */
++#undef __SYSCALL
++#define __SYSCALL(nr, call)	[nr] = (call),
++
++/* Note that we don't include  but  */
++void *sys_call_table[__NR_syscalls] = {
++	[0 ... __NR_syscalls-1] = sys_ni_syscall,
++#include 
++};
+diff --git a/arch/unicore32/mm/proc-macros.S b/arch/unicore32/mm/proc-macros.S
+new file mode 100644
+index 000000000000..51560d68c894
+--- /dev/null
++++ b/arch/unicore32/mm/proc-macros.S
+@@ -0,0 +1,145 @@
++/*
++ * linux/arch/unicore32/mm/proc-macros.S
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * We need constants.h for:
++ *  VMA_VM_MM
++ *  VMA_VM_FLAGS
++ *  VM_EXEC
++ */
++#include 
++#include 
++#include 
++
++/*
++ * the cache line sizes of the I and D cache are the same
++ */
++#define CACHE_LINESIZE	32
++
++/*
++ * This is the maximum size of an area which will be invalidated
++ * using the single invalidate entry instructions.  Anything larger
++ * than this, and we go for the whole cache.
++ *
++ * This value should be chosen such that we choose the cheapest
++ * alternative.
++ */
++#ifdef CONFIG_CPU_UCV2
++#define MAX_AREA_SIZE	0x800		/* 64 cache line */
++#endif
++
++/*
++ * vma_vm_mm - get mm pointer from vma pointer (vma->vm_mm)
++ */
++	.macro	vma_vm_mm, rd, rn
++	ldw	\rd, [\rn+], #VMA_VM_MM
++	.endm
++
++/*
++ * vma_vm_flags - get vma->vm_flags
++ */
++	.macro	vma_vm_flags, rd, rn
++	ldw	\rd, [\rn+], #VMA_VM_FLAGS
++	.endm
++
++	.macro	tsk_mm, rd, rn
++	ldw	\rd, [\rn+], #TI_TASK
++	ldw	\rd, [\rd+], #TSK_ACTIVE_MM
++	.endm
++
++/*
++ * act_mm - get current->active_mm
++ */
++	.macro	act_mm, rd
++	andn	\rd, sp, #8128
++	andn	\rd, \rd, #63
++	ldw	\rd, [\rd+], #TI_TASK
++	ldw	\rd, [\rd+], #TSK_ACTIVE_MM
++	.endm
++
++/*
++ * mmid - get context id from mm pointer (mm->context.id)
++ */
++	.macro	mmid, rd, rn
++	ldw	\rd, [\rn+], #MM_CONTEXT_ID
++	.endm
++
++/*
++ * mask_asid - mask the ASID from the context ID
++ */
++	.macro	asid, rd, rn
++	and	\rd, \rn, #255
++	.endm
++
++	.macro	crval, clear, mmuset, ucset
++	.word	\clear
++	.word	\mmuset
++	.endm
++
++#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
++/*
++ * va2pa va, pa, tbl, msk, off, err
++ *	This macro is used to translate virtual address to its physical address.
++ *
++ *	va: virtual address
++ *	pa: physical address, result is stored in this register
++ *	tbl, msk, off:	temp registers, will be destroyed
++ *	err: jump to error label if the physical address not exist
++ * NOTE: all regs must be different
++ */
++	.macro	va2pa, va, pa, tbl, msk, off, err=990f
++	movc	\pa, p0.c2, #0
++	mov	\off, \va >> #22		@ off <- index of 1st page table
++	adr	\tbl, 910f			@ tbl <- table of 1st page table
++900:						@ ---- handle 1, 2 page table
++	add	\pa, \pa, #PAGE_OFFSET		@ pa <- virt addr of page table
++	ldw	\pa, [\pa+], \off << #2		@ pa <- the content of pt
++	cand.a	\pa, #4				@ test exist bit
++	beq	\err				@ if not exist
++	and	\off, \pa, #3			@ off <- the last 2 bits
++	add	\tbl, \tbl, \off << #3		@ cmove table pointer
++	ldw	\msk, [\tbl+], #0		@ get the mask
++	ldw	pc, [\tbl+], #4
++930:						@ ---- handle 2nd page table
++	and	\pa, \pa, \msk			@ pa <- phys addr of 2nd pt
++	mov	\off, \va << #10
++	cntlo	\tbl, \msk			@ use tbl as temp reg
++	mov	\off, \off >> \tbl
++	mov	\off, \off >> #2		@ off <- index of 2nd pt
++	adr	\tbl, 920f			@ tbl <- table of 2nd pt
++	b	900b
++910:						@ 1st level page table
++	.word	0xfffff000, 930b		@ second level page table
++	.word	0xfffffc00, 930b		@ second level large page table
++	.word	0x00000000, \err		@ invalid
++	.word	0xffc00000, 980f		@ super page
++
++920:						@ 2nd level page table
++	.word	0xfffff000, 980f		@ page
++	.word	0xffffc000, 980f		@ middle page
++	.word	0xffff0000, 980f		@ large page
++	.word	0x00000000, \err		@ invalid
++980:
++	andn	\tbl, \va, \msk
++	and	\pa, \pa, \msk
++	or	\pa, \pa, \tbl
++990:
++	.endm
++#endif
++
++	.macro dcacheline_flush, addr, t1, t2
++	mov	\t1, \addr << #20
++	ldw	\t2, =_stext			@ _stext must ALIGN(4096)
++	add	\t2, \t2, \t1 >> #20
++	ldw	\t1, [\t2+], #0x0000
++	ldw	\t1, [\t2+], #0x1000
++	ldw	\t1, [\t2+], #0x2000
++	ldw	\t1, [\t2+], #0x3000
++	.endm
+diff --git a/arch/unicore32/mm/proc-ucv2.S b/arch/unicore32/mm/proc-ucv2.S
+new file mode 100644
+index 000000000000..9d296092e362
+--- /dev/null
++++ b/arch/unicore32/mm/proc-ucv2.S
+@@ -0,0 +1,134 @@
++/*
++ * linux/arch/unicore32/mm/proc-ucv2.S
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include "proc-macros.S"
++
++ENTRY(cpu_proc_fin)
++	stm.w	(lr), [sp-]
++	mov	ip, #PSR_R_BIT | PSR_I_BIT | PRIV_MODE
++	mov.a	asr, ip
++	b.l	__cpuc_flush_kern_all
++	ldm.w	(pc), [sp]+
++
++/*
++ *	cpu_reset(loc)
++ *
++ *	Perform a soft reset of the system.  Put the CPU into the
++ *	same state as it would be if it had been reset, and branch
++ *	to what would be the reset vector.
++ *
++ *	- loc   - location to jump to for soft reset
++ */
++	.align	5
++ENTRY(cpu_reset)
++	mov	ip, #0
++	movc	p0.c5, ip, #28			@ Cache invalidate all
++	nop8
++
++	movc	p0.c6, ip, #6			@ TLB invalidate all
++	nop8
++
++	movc	ip, p0.c1, #0			@ ctrl register
++	or	ip, ip, #0x2000			@ vector base address
++	andn	ip, ip, #0x000f			@ ............idam
++	movc	p0.c1, ip, #0			@ disable caches and mmu
++	nop
++	mov	pc, r0				@ jump to loc
++	nop8
++
++/*
++ *	cpu_do_idle()
++ *
++ *	Idle the processor (eg, wait for interrupt).
++ *
++ *	IRQs are already disabled.
++ */
++ENTRY(cpu_do_idle)
++	mov	r0, #0				@ PCI address
++	.rept	8
++	ldw	r1, [r0]
++	.endr
++	mov	pc, lr
++
++ENTRY(cpu_dcache_clean_area)
++#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
++	csub.a	r1, #MAX_AREA_SIZE
++	bsg	101f
++	mov	r9, #PAGE_SZ
++	sub	r9, r9, #1			@ PAGE_MASK
++1:	va2pa	r0, r10, r11, r12, r13		@ r10 is PA
++	b	3f
++2:	cand.a	r0, r9
++	beq	1b
++3:	movc	p0.c5, r10, #11			@ clean D entry
++	nop8
++	add	r0, r0, #CACHE_LINESIZE
++	add	r10, r10, #CACHE_LINESIZE
++	sub.a	r1, r1, #CACHE_LINESIZE
++	bua	2b
++	mov	pc, lr
++#endif
++101:	mov	ip, #0
++	movc	p0.c5, ip, #10			@ Dcache clean all
++	nop8
++
++	mov	pc, lr
++
++/*
++ *	cpu_do_switch_mm(pgd_phys)
++ *
++ *	Set the translation table base pointer to be pgd_phys
++ *
++ *	- pgd_phys - physical address of new pgd
++ *
++ *	It is assumed that:
++ *	- we are not using split page tables
++ */
++	.align	5
++ENTRY(cpu_do_switch_mm)
++	movc	p0.c2, r0, #0			@ update page table ptr
++	nop8
++
++	movc	p0.c6, ip, #6			@ TLB invalidate all
++	nop8
++
++	mov	pc, lr
++
++/*
++ *	cpu_set_pte(ptep, pte)
++ *
++ *	Set a level 2 translation table entry.
++ *
++ *	- ptep  - pointer to level 2 translation table entry
++ *	- pte   - PTE value to store
++ */
++	.align	5
++ENTRY(cpu_set_pte)
++	stw	r1, [r0]
++#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
++	sub	r2, r0, #PAGE_OFFSET
++	movc	p0.c5, r2, #11				@ Dcache clean line
++	nop8
++#else
++	mov	ip, #0
++	movc	p0.c5, ip, #10				@ Dcache clean all
++	nop8
++	@dcacheline_flush	r0, r2, ip
++#endif
++	mov	pc, lr
++

commit 87c1a3fb7c07322dfd63a63dd6d42339ad52ddee
+Author: GuanXuetao 
+Date:   Sat Jan 15 18:13:50 2011 +0800
+
+    unicore32 core architecture: generic elf and ksyms stuff
+    
+    This patch includes some generic stuff including elf and ksyms.
+    Because all one-line asm-generic headers are auto-generated by ASM_GENERIC_HEADERS
+    in arch/unicore32/Makefile, so the rest seems very little.
+    ELF handling functions and module handling functions are also here.
+    
+    Signed-off-by: Guan Xuetao 
+    Reviewed-by: Arnd Bergmann 
+
+diff --git a/arch/unicore32/include/asm/elf.h b/arch/unicore32/include/asm/elf.h
+new file mode 100644
+index 000000000000..829042d07722
+--- /dev/null
++++ b/arch/unicore32/include/asm/elf.h
+@@ -0,0 +1,94 @@
++/*
++ * linux/arch/unicore32/include/asm/elf.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __UNICORE_ELF_H__
++#define __UNICORE_ELF_H__
++
++#include 
++
++/*
++ * ELF register definitions..
++ */
++#include 
++
++typedef unsigned long elf_greg_t;
++typedef unsigned long elf_freg_t[3];
++
++#define ELF_NGREG (sizeof(struct pt_regs) / sizeof(elf_greg_t))
++typedef elf_greg_t elf_gregset_t[ELF_NGREG];
++
++typedef struct fp_state elf_fpregset_t;
++
++#define EM_UNICORE		110
++
++#define R_UNICORE_NONE		0
++#define R_UNICORE_PC24		1
++#define R_UNICORE_ABS32		2
++#define R_UNICORE_CALL		28
++#define R_UNICORE_JUMP24	29
++
++/*
++ * These are used to set parameters in the core dumps.
++ */
++#define ELF_CLASS	ELFCLASS32
++#define ELF_DATA	ELFDATA2LSB
++#define ELF_ARCH	EM_UNICORE
++
++/*
++ * This yields a string that ld.so will use to load implementation
++ * specific libraries for optimization.  This is more specific in
++ * intent than poking at uname or /proc/cpuinfo.
++ *
++ */
++#define ELF_PLATFORM_SIZE 8
++#define ELF_PLATFORM	(elf_platform)
++
++extern char elf_platform[];
++
++struct elf32_hdr;
++
++/*
++ * This is used to ensure we don't load something for the wrong architecture.
++ */
++extern int elf_check_arch(const struct elf32_hdr *);
++#define elf_check_arch elf_check_arch
++
++struct task_struct;
++int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs);
++#define ELF_CORE_COPY_TASK_REGS dump_task_regs
++
++#define ELF_EXEC_PAGESIZE	4096
++
++/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
++   use of this is to invoke "./ld.so someprog" to test out a new version of
++   the loader.  We need to make sure that it is out of the way of the program
++   that it will "exec", and that there is sufficient room for the brk.  */
++
++#define ELF_ET_DYN_BASE	(2 * TASK_SIZE / 3)
++
++/* When the program starts, a1 contains a pointer to a function to be
++   registered with atexit, as per the SVR4 ABI.  A value of 0 means we
++   have no such handler.  */
++#define ELF_PLAT_INIT(_r, load_addr)	{(_r)->UCreg_00 = 0; }
++
++extern void elf_set_personality(const struct elf32_hdr *);
++#define SET_PERSONALITY(ex)	elf_set_personality(&(ex))
++
++struct mm_struct;
++extern unsigned long arch_randomize_brk(struct mm_struct *mm);
++#define arch_randomize_brk arch_randomize_brk
++
++extern int vectors_user_mapping(void);
++#define arch_setup_additional_pages(bprm, uses_interp) vectors_user_mapping()
++#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
++
++#endif
+diff --git a/arch/unicore32/include/asm/string.h b/arch/unicore32/include/asm/string.h
+new file mode 100644
+index 000000000000..55264c84369a
+--- /dev/null
++++ b/arch/unicore32/include/asm/string.h
+@@ -0,0 +1,38 @@
++/*
++ * linux/arch/unicore32/include/asm/string.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_STRING_H__
++#define __UNICORE_STRING_H__
++
++/*
++ * We don't do inline string functions, since the
++ * optimised inline asm versions are not small.
++ */
++
++#define __HAVE_ARCH_STRRCHR
++extern char *strrchr(const char *s, int c);
++
++#define __HAVE_ARCH_STRCHR
++extern char *strchr(const char *s, int c);
++
++#define __HAVE_ARCH_MEMCPY
++extern void *memcpy(void *, const void *, __kernel_size_t);
++
++#define __HAVE_ARCH_MEMMOVE
++extern void *memmove(void *, const void *, __kernel_size_t);
++
++#define __HAVE_ARCH_MEMCHR
++extern void *memchr(const void *, int, __kernel_size_t);
++
++#define __HAVE_ARCH_MEMSET
++extern void *memset(void *, int, __kernel_size_t);
++
++#endif
+diff --git a/arch/unicore32/kernel/asm-offsets.c b/arch/unicore32/kernel/asm-offsets.c
+new file mode 100644
+index 000000000000..ffcbe7536ca7
+--- /dev/null
++++ b/arch/unicore32/kernel/asm-offsets.c
+@@ -0,0 +1,112 @@
++/*
++ * linux/arch/unicore32/kernel/asm-offsets.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * Generate definitions needed by assembly language modules.
++ * This code generates raw asm output which is post-processed to extract
++ * and format the required data.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++/*
++ * GCC 3.0, 3.1: general bad code generation.
++ * GCC 3.2.0: incorrect function argument offset calculation.
++ * GCC 3.2.x: miscompiles NEW_AUX_ENT in fs/binfmt_elf.c
++ *	(http://gcc.gnu.org/PR8896) and incorrect structure
++ *		initialisation in fs/jffs2/erase.c
++ */
++#if (__GNUC__ < 4)
++#error Your compiler should upgrade to uc4
++#error	Known good compilers: 4.2.2
++#endif
++
++int main(void)
++{
++	DEFINE(TSK_ACTIVE_MM,	offsetof(struct task_struct, active_mm));
++	BLANK();
++	DEFINE(TI_FLAGS,	offsetof(struct thread_info, flags));
++	DEFINE(TI_PREEMPT,	offsetof(struct thread_info, preempt_count));
++	DEFINE(TI_ADDR_LIMIT,	offsetof(struct thread_info, addr_limit));
++	DEFINE(TI_TASK,		offsetof(struct thread_info, task));
++	DEFINE(TI_EXEC_DOMAIN,	offsetof(struct thread_info, exec_domain));
++	DEFINE(TI_CPU,		offsetof(struct thread_info, cpu));
++	DEFINE(TI_CPU_SAVE,	offsetof(struct thread_info, cpu_context));
++	DEFINE(TI_USED_CP,	offsetof(struct thread_info, used_cp));
++#ifdef CONFIG_UNICORE_FPU_F64
++	DEFINE(TI_FPSTATE,	offsetof(struct thread_info, fpstate));
++#endif
++	BLANK();
++	DEFINE(S_R0,		offsetof(struct pt_regs, UCreg_00));
++	DEFINE(S_R1,		offsetof(struct pt_regs, UCreg_01));
++	DEFINE(S_R2,		offsetof(struct pt_regs, UCreg_02));
++	DEFINE(S_R3,		offsetof(struct pt_regs, UCreg_03));
++	DEFINE(S_R4,		offsetof(struct pt_regs, UCreg_04));
++	DEFINE(S_R5,		offsetof(struct pt_regs, UCreg_05));
++	DEFINE(S_R6,		offsetof(struct pt_regs, UCreg_06));
++	DEFINE(S_R7,		offsetof(struct pt_regs, UCreg_07));
++	DEFINE(S_R8,		offsetof(struct pt_regs, UCreg_08));
++	DEFINE(S_R9,		offsetof(struct pt_regs, UCreg_09));
++	DEFINE(S_R10,		offsetof(struct pt_regs, UCreg_10));
++	DEFINE(S_R11,		offsetof(struct pt_regs, UCreg_11));
++	DEFINE(S_R12,		offsetof(struct pt_regs, UCreg_12));
++	DEFINE(S_R13,		offsetof(struct pt_regs, UCreg_13));
++	DEFINE(S_R14,		offsetof(struct pt_regs, UCreg_14));
++	DEFINE(S_R15,		offsetof(struct pt_regs, UCreg_15));
++	DEFINE(S_R16,		offsetof(struct pt_regs, UCreg_16));
++	DEFINE(S_R17,		offsetof(struct pt_regs, UCreg_17));
++	DEFINE(S_R18,		offsetof(struct pt_regs, UCreg_18));
++	DEFINE(S_R19,		offsetof(struct pt_regs, UCreg_19));
++	DEFINE(S_R20,		offsetof(struct pt_regs, UCreg_20));
++	DEFINE(S_R21,		offsetof(struct pt_regs, UCreg_21));
++	DEFINE(S_R22,		offsetof(struct pt_regs, UCreg_22));
++	DEFINE(S_R23,		offsetof(struct pt_regs, UCreg_23));
++	DEFINE(S_R24,		offsetof(struct pt_regs, UCreg_24));
++	DEFINE(S_R25,		offsetof(struct pt_regs, UCreg_25));
++	DEFINE(S_R26,		offsetof(struct pt_regs, UCreg_26));
++	DEFINE(S_FP,		offsetof(struct pt_regs, UCreg_fp));
++	DEFINE(S_IP,		offsetof(struct pt_regs, UCreg_ip));
++	DEFINE(S_SP,		offsetof(struct pt_regs, UCreg_sp));
++	DEFINE(S_LR,		offsetof(struct pt_regs, UCreg_lr));
++	DEFINE(S_PC,		offsetof(struct pt_regs, UCreg_pc));
++	DEFINE(S_PSR,		offsetof(struct pt_regs, UCreg_asr));
++	DEFINE(S_OLD_R0,	offsetof(struct pt_regs, UCreg_ORIG_00));
++	DEFINE(S_FRAME_SIZE,	sizeof(struct pt_regs));
++	BLANK();
++	DEFINE(VMA_VM_MM,	offsetof(struct vm_area_struct, vm_mm));
++	DEFINE(VMA_VM_FLAGS,	offsetof(struct vm_area_struct, vm_flags));
++	BLANK();
++	DEFINE(VM_EXEC,		VM_EXEC);
++	BLANK();
++	DEFINE(PAGE_SZ,		PAGE_SIZE);
++	BLANK();
++	DEFINE(SYS_ERROR0,	0x9f0000);
++	BLANK();
++	DEFINE(PBE_ADDRESS,		offsetof(struct pbe, address));
++	DEFINE(PBE_ORIN_ADDRESS,	offsetof(struct pbe, orig_address));
++	DEFINE(PBE_NEXT,		offsetof(struct pbe, next));
++	DEFINE(SWSUSP_CPU,		offsetof(struct swsusp_arch_regs, \
++							cpu_context));
++#ifdef	CONFIG_UNICORE_FPU_F64
++	DEFINE(SWSUSP_FPSTATE,		offsetof(struct swsusp_arch_regs, \
++							fpstate));
++#endif
++	BLANK();
++	DEFINE(DMA_BIDIRECTIONAL,	DMA_BIDIRECTIONAL);
++	DEFINE(DMA_TO_DEVICE,		DMA_TO_DEVICE);
++	DEFINE(DMA_FROM_DEVICE,		DMA_FROM_DEVICE);
++	return 0;
++}
+diff --git a/arch/unicore32/kernel/elf.c b/arch/unicore32/kernel/elf.c
+new file mode 100644
+index 000000000000..0a176734fefa
+--- /dev/null
++++ b/arch/unicore32/kernel/elf.c
+@@ -0,0 +1,38 @@
++/*
++ * linux/arch/unicore32/kernel/elf.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++
++int elf_check_arch(const struct elf32_hdr *x)
++{
++	/* Make sure it's an UniCore executable */
++	if (x->e_machine != EM_UNICORE)
++		return 0;
++
++	/* Make sure the entry address is reasonable */
++	if (x->e_entry & 3)
++		return 0;
++
++	return 1;
++}
++EXPORT_SYMBOL(elf_check_arch);
++
++void elf_set_personality(const struct elf32_hdr *x)
++{
++	unsigned int personality = PER_LINUX;
++
++	set_personality(personality);
++}
++EXPORT_SYMBOL(elf_set_personality);
+diff --git a/arch/unicore32/kernel/ksyms.c b/arch/unicore32/kernel/ksyms.c
+new file mode 100644
+index 000000000000..a8970809428a
+--- /dev/null
++++ b/arch/unicore32/kernel/ksyms.c
+@@ -0,0 +1,99 @@
++/*
++ * linux/arch/unicore32/kernel/ksyms.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++#include 
++
++#include "ksyms.h"
++
++EXPORT_SYMBOL(__uc32_find_next_zero_bit);
++EXPORT_SYMBOL(__uc32_find_next_bit);
++
++EXPORT_SYMBOL(__backtrace);
++
++	/* platform dependent support */
++EXPORT_SYMBOL(__udelay);
++EXPORT_SYMBOL(__const_udelay);
++
++	/* networking */
++EXPORT_SYMBOL(csum_partial);
++EXPORT_SYMBOL(csum_partial_copy_from_user);
++EXPORT_SYMBOL(csum_partial_copy_nocheck);
++EXPORT_SYMBOL(__csum_ipv6_magic);
++
++	/* io */
++#ifndef __raw_readsb
++EXPORT_SYMBOL(__raw_readsb);
++#endif
++#ifndef __raw_readsw
++EXPORT_SYMBOL(__raw_readsw);
++#endif
++#ifndef __raw_readsl
++EXPORT_SYMBOL(__raw_readsl);
++#endif
++#ifndef __raw_writesb
++EXPORT_SYMBOL(__raw_writesb);
++#endif
++#ifndef __raw_writesw
++EXPORT_SYMBOL(__raw_writesw);
++#endif
++#ifndef __raw_writesl
++EXPORT_SYMBOL(__raw_writesl);
++#endif
++
++	/* string / mem functions */
++EXPORT_SYMBOL(strchr);
++EXPORT_SYMBOL(strrchr);
++EXPORT_SYMBOL(memset);
++EXPORT_SYMBOL(memcpy);
++EXPORT_SYMBOL(memmove);
++EXPORT_SYMBOL(memchr);
++
++	/* user mem (segment) */
++EXPORT_SYMBOL(__strnlen_user);
++EXPORT_SYMBOL(__strncpy_from_user);
++
++EXPORT_SYMBOL(copy_page);
++
++EXPORT_SYMBOL(__copy_from_user);
++EXPORT_SYMBOL(__copy_to_user);
++EXPORT_SYMBOL(__clear_user);
++
++EXPORT_SYMBOL(__get_user_1);
++EXPORT_SYMBOL(__get_user_2);
++EXPORT_SYMBOL(__get_user_4);
++
++EXPORT_SYMBOL(__put_user_1);
++EXPORT_SYMBOL(__put_user_2);
++EXPORT_SYMBOL(__put_user_4);
++EXPORT_SYMBOL(__put_user_8);
++
++EXPORT_SYMBOL(__ashldi3);
++EXPORT_SYMBOL(__ashrdi3);
++EXPORT_SYMBOL(__divsi3);
++EXPORT_SYMBOL(__lshrdi3);
++EXPORT_SYMBOL(__modsi3);
++EXPORT_SYMBOL(__muldi3);
++EXPORT_SYMBOL(__ucmpdi2);
++EXPORT_SYMBOL(__udivsi3);
++EXPORT_SYMBOL(__umodsi3);
++EXPORT_SYMBOL(__bswapsi2);
++
+diff --git a/arch/unicore32/kernel/ksyms.h b/arch/unicore32/kernel/ksyms.h
+new file mode 100644
+index 000000000000..185cdc712d03
+--- /dev/null
++++ b/arch/unicore32/kernel/ksyms.h
+@@ -0,0 +1,15 @@
++/*
++ * libgcc functions - functions that are used internally by the
++ * compiler...  (prototypes are not correct though, but that
++ * doesn't really matter since they're not versioned).
++ */
++extern void __ashldi3(void);
++extern void __ashrdi3(void);
++extern void __divsi3(void);
++extern void __lshrdi3(void);
++extern void __modsi3(void);
++extern void __muldi3(void);
++extern void __ucmpdi2(void);
++extern void __udivsi3(void);
++extern void __umodsi3(void);
++extern void __bswapsi2(void);
+diff --git a/arch/unicore32/kernel/module.c b/arch/unicore32/kernel/module.c
+new file mode 100644
+index 000000000000..3e5a38d71a1e
+--- /dev/null
++++ b/arch/unicore32/kernel/module.c
+@@ -0,0 +1,152 @@
++/*
++ * linux/arch/unicore32/kernel/module.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++#include 
++
++void *module_alloc(unsigned long size)
++{
++	struct vm_struct *area;
++
++	size = PAGE_ALIGN(size);
++	if (!size)
++		return NULL;
++
++	area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END);
++	if (!area)
++		return NULL;
++
++	return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL_EXEC);
++}
++
++void module_free(struct module *module, void *region)
++{
++	vfree(region);
++}
++
++int module_frob_arch_sections(Elf_Ehdr *hdr,
++			      Elf_Shdr *sechdrs,
++			      char *secstrings,
++			      struct module *mod)
++{
++	return 0;
++}
++
++int
++apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
++	       unsigned int relindex, struct module *module)
++{
++	Elf32_Shdr *symsec = sechdrs + symindex;
++	Elf32_Shdr *relsec = sechdrs + relindex;
++	Elf32_Shdr *dstsec = sechdrs + relsec->sh_info;
++	Elf32_Rel *rel = (void *)relsec->sh_addr;
++	unsigned int i;
++
++	for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rel); i++, rel++) {
++		unsigned long loc;
++		Elf32_Sym *sym;
++		s32 offset;
++
++		offset = ELF32_R_SYM(rel->r_info);
++		if (offset < 0 || offset >
++				(symsec->sh_size / sizeof(Elf32_Sym))) {
++			printk(KERN_ERR "%s: bad relocation, "
++					"section %d reloc %d\n",
++					module->name, relindex, i);
++			return -ENOEXEC;
++		}
++
++		sym = ((Elf32_Sym *)symsec->sh_addr) + offset;
++
++		if (rel->r_offset < 0 || rel->r_offset >
++				dstsec->sh_size - sizeof(u32)) {
++			printk(KERN_ERR "%s: out of bounds relocation, "
++				"section %d reloc %d offset %d size %d\n",
++				module->name, relindex, i, rel->r_offset,
++				dstsec->sh_size);
++			return -ENOEXEC;
++		}
++
++		loc = dstsec->sh_addr + rel->r_offset;
++
++		switch (ELF32_R_TYPE(rel->r_info)) {
++		case R_UNICORE_NONE:
++			/* ignore */
++			break;
++
++		case R_UNICORE_ABS32:
++			*(u32 *)loc += sym->st_value;
++			break;
++
++		case R_UNICORE_PC24:
++		case R_UNICORE_CALL:
++		case R_UNICORE_JUMP24:
++			offset = (*(u32 *)loc & 0x00ffffff) << 2;
++			if (offset & 0x02000000)
++				offset -= 0x04000000;
++
++			offset += sym->st_value - loc;
++			if (offset & 3 ||
++			    offset <= (s32)0xfe000000 ||
++			    offset >= (s32)0x02000000) {
++				printk(KERN_ERR
++				       "%s: relocation out of range, section "
++				       "%d reloc %d sym '%s'\n", module->name,
++				       relindex, i, strtab + sym->st_name);
++				return -ENOEXEC;
++			}
++
++			offset >>= 2;
++
++			*(u32 *)loc &= 0xff000000;
++			*(u32 *)loc |= offset & 0x00ffffff;
++			break;
++
++		default:
++			printk(KERN_ERR "%s: unknown relocation: %u\n",
++			       module->name, ELF32_R_TYPE(rel->r_info));
++			return -ENOEXEC;
++		}
++	}
++	return 0;
++}
++
++int
++apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
++		   unsigned int symindex, unsigned int relsec,
++		   struct module *module)
++{
++	printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n",
++	       module->name);
++	return -ENOEXEC;
++}
++
++int
++module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
++		struct module *module)
++{
++	return 0;
++}
++
++void
++module_arch_cleanup(struct module *mod)
++{
++}
+diff --git a/arch/unicore32/mm/proc-syms.c b/arch/unicore32/mm/proc-syms.c
+new file mode 100644
+index 000000000000..f30071e3665d
+--- /dev/null
++++ b/arch/unicore32/mm/proc-syms.c
+@@ -0,0 +1,23 @@
++/*
++ * linux/arch/unicore32/mm/proc-syms.c
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include 
++#include 
++
++#include 
++#include 
++#include 
++
++EXPORT_SYMBOL(cpu_dcache_clean_area);
++EXPORT_SYMBOL(cpu_set_pte);
++
++EXPORT_SYMBOL(__cpuc_dma_flush_range);
++EXPORT_SYMBOL(__cpuc_dma_clean_range);

commit 790edb61c0d87d1f1daafcaaa8f7c66b7b82bdad
+Author: GuanXuetao 
+Date:   Sat Feb 26 18:24:56 2011 +0800
+
+    unicore32 core architecture: build infrastructure
+    
+    This patch implements build infrastructure.
+    
+    Signed-off-by: Guan Xuetao 
+    Reviewed-by: Arnd Bergmann 
+
+diff --git a/arch/unicore32/.gitignore b/arch/unicore32/.gitignore
+new file mode 100644
+index 000000000000..947e99c2a957
+--- /dev/null
++++ b/arch/unicore32/.gitignore
+@@ -0,0 +1,21 @@
++#
++# Generated include files
++#
++include/generated
++#
++# Generated ld script file
++#
++kernel/vmlinux.lds
++#
++# Generated images in boot
++#
++boot/Image
++boot/zImage
++boot/uImage
++#
++# Generated files in boot/compressed
++#
++boot/compressed/piggy.S
++boot/compressed/piggy.gzip
++boot/compressed/vmlinux
++boot/compressed/vmlinux.lds
+diff --git a/arch/unicore32/Kconfig b/arch/unicore32/Kconfig
+new file mode 100644
+index 000000000000..cc6a83215881
+--- /dev/null
++++ b/arch/unicore32/Kconfig
+@@ -0,0 +1,246 @@
++config UNICORE32
++	def_bool y
++	select HAVE_MEMBLOCK
++	select HAVE_GENERIC_DMA_COHERENT
++	select HAVE_GENERIC_HARDIRQS
++	select HAVE_DMA_ATTRS
++	select HAVE_KERNEL_GZIP
++	select HAVE_KERNEL_BZIP2
++	select HAVE_KERNEL_LZO
++	select HAVE_KERNEL_LZMA
++	select GENERIC_FIND_FIRST_BIT
++	select GENERIC_IRQ_PROBE
++	select ARCH_WANT_FRAME_POINTERS
++	help
++	  UniCore-32 is 32-bit Instruction Set Architecture,
++	  including a series of low-power-consumption RISC chip
++	  designs licensed by PKUnity Ltd.
++	  Please see web page at .
++
++config HAVE_PWM
++	bool
++
++config GENERIC_GPIO
++	def_bool y
++
++config GENERIC_CLOCKEVENTS
++	bool
++
++config GENERIC_CSUM
++	def_bool y
++
++config NO_IOPORT
++	bool
++
++config STACKTRACE_SUPPORT
++	def_bool y
++
++config HAVE_LATENCYTOP_SUPPORT
++	def_bool y
++
++config LOCKDEP_SUPPORT
++	def_bool y
++
++config RWSEM_GENERIC_SPINLOCK
++	def_bool y
++
++config RWSEM_XCHGADD_ALGORITHM
++	bool
++
++config ARCH_HAS_ILOG2_U32
++	bool
++
++config ARCH_HAS_ILOG2_U64
++	bool
++
++config ARCH_HAS_CPUFREQ
++	bool
++
++config GENERIC_HWEIGHT
++	def_bool y
++
++config GENERIC_CALIBRATE_DELAY
++	def_bool y
++
++config ARCH_MAY_HAVE_PC_FDC
++	bool
++
++config NEED_DMA_MAP_STATE
++       def_bool y
++
++source "init/Kconfig"
++
++source "kernel/Kconfig.freezer"
++
++menu "System Type"
++
++config MMU
++	def_bool y
++
++config ARCH_FPGA
++	bool
++
++config ARCH_PUV3
++	def_bool y
++	select CPU_UCV2
++	select GENERIC_CLOCKEVENTS
++	select HAVE_CLK
++	select ARCH_REQUIRE_GPIOLIB
++	select ARCH_HAS_CPUFREQ
++
++# CONFIGs for ARCH_PUV3
++
++if ARCH_PUV3
++
++choice
++	prompt "Board Selection"
++	default PUV3_DB0913
++
++config PUV3_FPGA_DLX200
++	select ARCH_FPGA
++	bool "FPGA board"
++
++config PUV3_DB0913
++	bool "DEBUG board (0913)"
++
++config PUV3_NB0916
++	bool "NetBook board (0916)"
++	select HAVE_PWM
++
++config PUV3_SMW0919
++	bool "Security Mini-Workstation board (0919)"
++
++endchoice
++
++config PUV3_PM
++	def_bool y if !ARCH_FPGA
++
++endif
++
++source "arch/unicore32/mm/Kconfig"
++
++comment "Floating poing support"
++
++config UNICORE_FPU_F64
++	def_bool y if !ARCH_FPGA
++
++endmenu
++
++menu "Bus support"
++
++config PCI
++	bool "PCI Support"
++	help
++	  Find out whether you have a PCI motherboard. PCI is the name of a
++	  bus system, i.e. the way the CPU talks to the other stuff inside
++	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
++	  VESA. If you have PCI, say Y, otherwise N.
++
++source "drivers/pci/Kconfig"
++
++source "drivers/pcmcia/Kconfig"
++
++endmenu
++
++menu "Kernel Features"
++
++source "kernel/time/Kconfig"
++
++source "kernel/Kconfig.preempt"
++
++source "kernel/Kconfig.hz"
++
++source "mm/Kconfig"
++
++config LEDS
++	def_bool y
++	depends on GENERIC_GPIO
++
++config ALIGNMENT_TRAP
++	def_bool y
++	help
++	  Unicore processors can not fetch/store information which is not
++	  naturally aligned on the bus, i.e., a 4 byte fetch must start at an
++	  address divisible by 4. On 32-bit Unicore processors, these non-aligned
++	  fetch/store instructions will be emulated in software if you say
++	  here, which has a severe performance impact. This is necessary for
++	  correct operation of some network protocols. With an IP-only
++	  configuration it is safe to say N, otherwise say Y.
++
++endmenu
++
++menu "Boot options"
++
++config CMDLINE
++	string "Default kernel command string"
++	default ""
++
++config CMDLINE_FORCE
++	bool "Always use the default kernel command string"
++	depends on CMDLINE != ""
++	help
++	  Always use the default kernel command string, even if the boot
++	  loader passes other arguments to the kernel.
++	  This is useful if you cannot or don't want to change the
++	  command-line options your boot loader passes to the kernel.
++
++	  If unsure, say N.
++
++endmenu
++
++menu "Userspace binary formats"
++
++source "fs/Kconfig.binfmt"
++
++endmenu
++
++menu "Power management options"
++
++source "kernel/power/Kconfig"
++
++if ARCH_HAS_CPUFREQ
++source "drivers/cpufreq/Kconfig"
++endif
++
++config ARCH_SUSPEND_POSSIBLE
++	def_bool y if !ARCH_FPGA
++
++config ARCH_HIBERNATION_POSSIBLE
++	def_bool y if !ARCH_FPGA
++
++endmenu
++
++source "net/Kconfig"
++
++if ARCH_PUV3
++
++config PUV3_GPIO
++	bool
++	depends on !ARCH_FPGA
++	select GENERIC_GPIO
++	select GPIO_SYSFS if EXPERIMENTAL
++	default y
++
++config PUV3_PWM
++	tristate
++	default BACKLIGHT_PWM
++	help
++	  Enable support for NB0916 PWM controllers
++
++config PUV3_RTC
++	tristate "PKUnity v3 RTC Support"
++	depends on !ARCH_FPGA
++
++endif
++
++source "drivers/Kconfig"
++
++source "fs/Kconfig"
++
++source "arch/unicore32/Kconfig.debug"
++
++source "security/Kconfig"
++
++source "crypto/Kconfig"
++
++source "lib/Kconfig"
+diff --git a/arch/unicore32/Kconfig.debug b/arch/unicore32/Kconfig.debug
+new file mode 100644
+index 000000000000..3140151ede45
+--- /dev/null
++++ b/arch/unicore32/Kconfig.debug
+@@ -0,0 +1,68 @@
++menu "Kernel hacking"
++
++source "lib/Kconfig.debug"
++
++config STRICT_DEVMEM
++	bool "Filter access to /dev/mem"
++	depends on MMU
++	---help---
++	  If this option is disabled, you allow userspace (root) access to all
++	  of memory, including kernel and userspace memory. Accidental
++	  access to this is obviously disastrous, but specific access can
++	  be used by people debugging the kernel.
++
++	  If this option is switched on, the /dev/mem file only allows
++	  userspace access to memory mapped peripherals.
++
++          If in doubt, say Y.
++
++config EARLY_PRINTK
++	def_bool DEBUG_OCD
++	help
++	  Write kernel log output directly into the ocd or to a serial port.
++
++	  This is useful for kernel debugging when your machine crashes very
++	  early before the console code is initialized. For normal operation
++	  it is not recommended because it looks ugly and doesn't cooperate
++	  with klogd/syslogd or the X server. You should normally N here,
++	  unless you want to debug such a crash.
++
++config DEBUG_STACK_USAGE
++	bool "Enable stack utilization instrumentation"
++	depends on DEBUG_KERNEL
++	help
++	  Enables the display of the minimum amount of free stack which each
++	  task has ever had available in the sysrq-T output.
++
++# These options are only for real kernel hackers who want to get their hands dirty.
++config DEBUG_LL
++	bool "Kernel low-level debugging functions"
++	depends on DEBUG_KERNEL
++	help
++	  Say Y here to include definitions of printascii, printch, printhex
++	  in the kernel.  This is helpful if you are debugging code that
++	  executes before the console is initialized.
++
++config DEBUG_OCD
++	bool "Kernel low-level debugging via On-Chip-Debugger"
++	depends on DEBUG_LL
++	default y
++	help
++	  Say Y here if you want the debug print routines to direct their
++	  output to the UniCore On-Chip-Debugger channel using CP #1.
++
++config DEBUG_OCD_BREAKPOINT
++	bool "Breakpoint support via On-Chip-Debugger"
++	depends on DEBUG_OCD
++
++config DEBUG_UART
++	int "Kernel low-level debugging messages via serial port"
++	depends on DEBUG_LL
++	range 0 1
++	default "0"
++	help
++	  Choice for UART for kernel low-level using PKUnity UARTS,
++	  should be between zero and one. The port must have been
++	  initialised by the boot-loader before use.
++
++endmenu
+diff --git a/arch/unicore32/Makefile b/arch/unicore32/Makefile
+new file mode 100644
+index 000000000000..e08d6d370a8a
+--- /dev/null
++++ b/arch/unicore32/Makefile
+@@ -0,0 +1,95 @@
++#
++# arch/unicore32/Makefile
++#
++# This file is included by the global makefile so that you can add your own
++# architecture-specific flags and dependencies.
++#
++# This file is subject to the terms and conditions of the GNU General Public
++# License.  See the file "COPYING" in the main directory of this archive
++# for more details.
++#
++# Copyright (C) 2002~2010 by Guan Xue-tao
++#
++ifneq ($(SUBARCH),$(ARCH))
++	ifeq ($(CROSS_COMPILE),)
++		CROSS_COMPILE := $(call cc-cross-prefix, unicore32-linux-)
++	endif
++endif
++
++LDFLAGS_vmlinux		:= -p --no-undefined -X
++
++OBJCOPYFLAGS		:= -O binary -R .note -R .note.gnu.build-id -R .comment -S
++
++# Never generate .eh_frame
++KBUILD_CFLAGS		+= $(call cc-option,-fno-dwarf2-cfi-asm)
++
++# Never use hard float in kernel
++KBUILD_CFLAGS		+= -msoft-float
++
++ifeq ($(CONFIG_FRAME_POINTER),y)
++KBUILD_CFLAGS		+= -mno-sched-prolog
++endif
++
++CHECKFLAGS		+= -D__unicore32__
++
++head-y			:= arch/unicore32/kernel/head.o
++head-y			+= arch/unicore32/kernel/init_task.o
++
++core-y			+= arch/unicore32/kernel/
++core-y			+= arch/unicore32/mm/
++
++libs-y			+= arch/unicore32/lib/
++
++ASM_GENERATED_DIR	:= $(srctree)/arch/unicore32/include/generated
++LINUXINCLUDE		+= -I$(ASM_GENERATED_DIR)
++
++ASM_GENERIC_HEADERS	:= atomic.h auxvec.h
++ASM_GENERIC_HEADERS	+= bitsperlong.h bug.h bugs.h
++ASM_GENERIC_HEADERS	+= cputime.h current.h
++ASM_GENERIC_HEADERS	+= device.h div64.h
++ASM_GENERIC_HEADERS	+= emergency-restart.h errno.h
++ASM_GENERIC_HEADERS	+= fb.h fcntl.h ftrace.h
++ASM_GENERIC_HEADERS	+= hardirq.h hw_irq.h
++ASM_GENERIC_HEADERS	+= ioctl.h ioctls.h ipcbuf.h irq_regs.h
++ASM_GENERIC_HEADERS	+= kdebug.h kmap_types.h
++ASM_GENERIC_HEADERS	+= local.h
++ASM_GENERIC_HEADERS	+= mman.h module.h msgbuf.h
++ASM_GENERIC_HEADERS	+= param.h parport.h percpu.h poll.h posix_types.h
++ASM_GENERIC_HEADERS	+= resource.h
++ASM_GENERIC_HEADERS	+= scatterlist.h sections.h segment.h sembuf.h serial.h
++ASM_GENERIC_HEADERS	+= setup.h shmbuf.h shmparam.h
++ASM_GENERIC_HEADERS	+= siginfo.h signal.h sizes.h
++ASM_GENERIC_HEADERS	+= socket.h sockios.h stat.h statfs.h swab.h syscalls.h
++ASM_GENERIC_HEADERS	+= termbits.h termios.h topology.h types.h
++ASM_GENERIC_HEADERS	+= ucontext.h unaligned.h user.h
++ASM_GENERIC_HEADERS	+= vga.h
++ASM_GENERIC_HEADERS	+= xor.h
++
++archprepare:
++ifneq ($(ASM_GENERATED_DIR), $(wildcard $(ASM_GENERATED_DIR)))
++	$(Q)mkdir -p $(ASM_GENERATED_DIR)/asm
++	$(Q)$(foreach a, $(ASM_GENERIC_HEADERS),	\
++		echo '#include '	\
++			> $(ASM_GENERATED_DIR)/asm/$a; )
++endif
++
++boot			:= arch/unicore32/boot
++
++# Default target when executing plain make
++KBUILD_IMAGE		:= zImage
++
++all:	$(KBUILD_IMAGE)
++
++zImage Image uImage: vmlinux
++	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
++
++MRPROPER_DIRS		+= $(ASM_GENERATED_DIR)
++
++archclean:
++	$(Q)$(MAKE) $(clean)=$(boot)
++
++define archhelp
++  echo  '* zImage        - Compressed kernel image (arch/$(ARCH)/boot/zImage)'
++  echo  '  Image         - Uncompressed kernel image (arch/$(ARCH)/boot/Image)'
++  echo  '  uImage        - U-Boot wrapped zImage'
++endef
+diff --git a/arch/unicore32/configs/debug_defconfig b/arch/unicore32/configs/debug_defconfig
+new file mode 100644
+index 000000000000..3647f68147da
+--- /dev/null
++++ b/arch/unicore32/configs/debug_defconfig
+@@ -0,0 +1,210 @@
++### General setup
++CONFIG_EXPERIMENTAL=y
++CONFIG_LOCALVERSION="-debug"
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_POSIX_MQUEUE=y
++CONFIG_HOTPLUG=y
++#	Initial RAM filesystem and RAM disk (initramfs/initrd) support
++#CONFIG_BLK_DEV_INITRD=y
++#CONFIG_INITRAMFS_SOURCE="arch/unicore/ramfs/ramfs_config"
++
++### Enable loadable module support
++CONFIG_MODULES=n
++CONFIG_MODULE_UNLOAD=y
++
++### System Type
++CONFIG_ARCH_PUV3=y
++#	Board Selection
++CONFIG_PUV3_NB0916=y
++#	Processor Features
++CONFIG_CPU_DCACHE_LINE_DISABLE=y
++CONFIG_CPU_TLB_SINGLE_ENTRY_DISABLE=n
++
++### Bus support
++CONFIG_PCI=y
++CONFIG_PCI_LEGACY=n
++
++### Boot options
++#	for debug, adding: earlyprintk=ocd,keep initcall_debug
++#	others support: test_suspend=mem root=/dev/sda
++#	hibernate support: resume=/dev/sda3
++CONFIG_CMDLINE="earlyprintk=ocd,keep ignore_loglevel"
++# TODO: mem=512M video=unifb:1024x600-16@75
++# for nfs: root=/dev/nfs rw nfsroot=192.168.10.88:/home/udb/nfs/,rsize=1024,wsize=1024
++#	ip=192.168.10.83:192.168.10.88:192.168.10.1:255.255.255.0::eth0:off
++CONFIG_CMDLINE_FORCE=y
++
++### Power management options
++CONFIG_PM=y
++CONFIG_HIBERNATION=y
++CONFIG_PM_STD_PARTITION="/dev/sda3"
++CONFIG_CPU_FREQ=n
++CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
++
++### Networking support
++CONFIG_NET=y
++#	Networking options
++CONFIG_PACKET=m
++CONFIG_UNIX=m
++#	TCP/IP networking
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++CONFIG_IP_PNP=y
++CONFIG_IPV6=n
++#	Wireless
++CONFIG_WIRELESS=y
++CONFIG_WIRELESS_EXT=y
++CONFIG_MAC80211=m
++
++### PKUnity SoC Features
++CONFIG_USB_WLAN_HED_AQ3=n
++CONFIG_USB_CMMB_INNOFIDEI=n
++CONFIG_I2C_BATTERY_BQ27200=n
++CONFIG_I2C_EEPROM_AT24=n
++CONFIG_LCD_BACKLIGHT=n
++
++CONFIG_PUV3_RTC=y
++CONFIG_PUV3_UMAL=y
++CONFIG_PUV3_UNIGFX=y
++CONFIG_PUV3_MUSB=n
++CONFIG_PUV3_AC97=n
++CONFIG_PUV3_NAND=n
++CONFIG_PUV3_MMC=n
++CONFIG_PUV3_UART=n
++
++### Device Drivers
++#	Memory Technology Device (MTD) support
++CONFIG_MTD=m
++CONFIG_MTD_UBI=m
++CONFIG_MTD_PARTITIONS=y
++CONFIG_MTD_CHAR=m
++CONFIG_MTD_BLKDEVS=m
++#	RAM/ROM/Flash chip drivers
++CONFIG_MTD_CFI=m
++CONFIG_MTD_JEDECPROBE=m
++CONFIG_MTD_CFI_AMDSTD=m
++#	Mapping drivers for chip access
++CONFIG_MTD_PHYSMAP=m
++
++#	Block devices
++CONFIG_BLK_DEV_LOOP=m
++
++#	SCSI device support
++CONFIG_SCSI=y
++CONFIG_BLK_DEV_SD=y
++CONFIG_BLK_DEV_SR=m
++CONFIG_CHR_DEV_SG=m
++
++#	Serial ATA (prod) and Parallel ATA (experimental) drivers
++CONFIG_ATA=y
++CONFIG_SATA_VIA=y
++
++#	Network device support
++CONFIG_NETDEVICES=y
++CONFIG_NET_ETHERNET=y
++CONFIG_NETDEV_1000=y
++#	Wireless LAN
++CONFIG_WLAN_80211=n
++CONFIG_RT2X00=n
++CONFIG_RT73USB=n
++
++#	Input device support
++CONFIG_INPUT_EVDEV=m
++#	Keyboards
++CONFIG_KEYBOARD_GPIO=m
++
++#	Hardware Monitoring support
++#CONFIG_SENSORS_LM75=m
++#	Generic Thermal sysfs driver
++#CONFIG_THERMAL=m
++#CONFIG_THERMAL_HWMON=y
++
++#	Multimedia support
++CONFIG_MEDIA_SUPPORT=n
++CONFIG_VIDEO_DEV=n
++CONFIG_USB_VIDEO_CLASS=n
++
++#	Graphics support
++#	Console display driver support
++CONFIG_VGA_CONSOLE=n
++CONFIG_FRAMEBUFFER_CONSOLE=y
++CONFIG_FONTS=y
++CONFIG_FONT_8x8=y
++CONFIG_FONT_8x16=y
++#	Bootup logo
++CONFIG_LOGO=n
++
++#	Sound card support
++CONFIG_SOUND=m
++#	Advanced Linux Sound Architecture
++CONFIG_SND=m
++CONFIG_SND_MIXER_OSS=m
++CONFIG_SND_PCM_OSS=m
++
++#	USB support
++CONFIG_USB_ARCH_HAS_HCD=n
++CONFIG_USB=n
++CONFIG_USB_DEVICEFS=n
++CONFIG_USB_PRINTER=n
++CONFIG_USB_STORAGE=n
++#	Inventra Highspeed Dual Role Controller
++CONFIG_USB_MUSB_HDRC=n
++
++#	LED Support
++CONFIG_NEW_LEDS=y
++CONFIG_LEDS_CLASS=y
++CONFIG_LEDS_GPIO=y
++#	LED Triggers
++CONFIG_LEDS_TRIGGERS=y
++CONFIG_LEDS_TRIGGER_TIMER=y
++CONFIG_LEDS_TRIGGER_IDE_DISK=y
++CONFIG_LEDS_TRIGGER_HEARTBEAT=y
++
++#	Real Time Clock
++CONFIG_RTC_LIB=m
++CONFIG_RTC_CLASS=m
++
++### File systems
++CONFIG_EXT2_FS=m
++CONFIG_EXT3_FS=y
++CONFIG_EXT4_FS=y
++CONFIG_FUSE_FS=m
++#	CD-ROM/DVD Filesystems
++CONFIG_ISO9660_FS=m
++CONFIG_JOLIET=y
++CONFIG_UDF_FS=m
++#	DOS/FAT/NT Filesystems
++CONFIG_VFAT_FS=m
++#	Pseudo filesystems
++CONFIG_PROC_FS=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++#	Miscellaneous filesystems
++CONFIG_MISC_FILESYSTEMS=y
++CONFIG_JFFS2_FS=m
++CONFIG_UBIFS_FS=m
++#	Network File Systems
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++CONFIG_ROOT_NFS=y
++#	Partition Types
++CONFIG_PARTITION_ADVANCED=y
++CONFIG_MSDOS_PARTITION=y
++#	Native language support
++CONFIG_NLS=y
++CONFIG_NLS_CODEPAGE_437=m
++CONFIG_NLS_CODEPAGE_936=m
++CONFIG_NLS_ISO8859_1=m
++CONFIG_NLS_UTF8=m
++
++### Kernel hacking
++CONFIG_FRAME_WARN=8096
++CONFIG_MAGIC_SYSRQ=y
++CONFIG_DEBUG_KERNEL=y
++CONFIG_PROVE_LOCKING=n
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_FRAME_POINTER=y
++CONFIG_DEBUG_LL=y
++
+diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
+new file mode 100644
+index 000000000000..b200fdaca44d
+--- /dev/null
++++ b/arch/unicore32/include/asm/Kbuild
+@@ -0,0 +1,2 @@
++include include/asm-generic/Kbuild.asm
++
+diff --git a/arch/unicore32/include/asm/linkage.h b/arch/unicore32/include/asm/linkage.h
+new file mode 100644
+index 000000000000..d1618bd35b67
+--- /dev/null
++++ b/arch/unicore32/include/asm/linkage.h
+@@ -0,0 +1,22 @@
++/*
++ * linux/arch/unicore32/include/asm/linkage.h
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __UNICORE_LINKAGE_H__
++#define __UNICORE_LINKAGE_H__
++
++#define __ALIGN .align 0
++#define __ALIGN_STR ".align 0"
++
++#define ENDPROC(name) \
++	.type name, %function; \
++	END(name)
++
++#endif
+diff --git a/arch/unicore32/kernel/Makefile b/arch/unicore32/kernel/Makefile
+new file mode 100644
+index 000000000000..ec23a2fb2f50
+--- /dev/null
++++ b/arch/unicore32/kernel/Makefile
+@@ -0,0 +1,33 @@
++#
++# Makefile for the linux kernel.
++#
++
++# Object file lists.
++obj-y				:= dma.o elf.o entry.o process.o ptrace.o
++obj-y				+= setup.o signal.o sys.o stacktrace.o traps.o
++
++obj-$(CONFIG_MODULES)		+= ksyms.o module.o
++obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
++
++obj-$(CONFIG_CPU_FREQ)		+= cpu-ucv2.o
++obj-$(CONFIG_UNICORE_FPU_F64)	+= fpu-ucf64.o
++
++# obj-y for architecture PKUnity v3
++obj-$(CONFIG_ARCH_PUV3)		+= clock.o irq.o time.o
++
++obj-$(CONFIG_PUV3_GPIO)		+= gpio.o
++obj-$(CONFIG_PUV3_RTC)		+= rtc.o
++obj-$(CONFIG_PUV3_PWM)		+= pwm.o
++obj-$(CONFIG_PUV3_PM)		+= pm.o sleep.o
++obj-$(CONFIG_HIBERNATION)	+= hibernate.o hibernate_asm.o
++
++obj-$(CONFIG_PCI)		+= pci.o
++
++# obj-y for specific machines
++obj-$(CONFIG_ARCH_PUV3)		+= puv3-core.o
++obj-$(CONFIG_PUV3_NB0916)	+= puv3-nb0916.o
++
++head-y				:= head.o
++obj-$(CONFIG_DEBUG_LL)		+= debug.o
++
++extra-y				:= $(head-y) init_task.o vmlinux.lds
+diff --git a/arch/unicore32/kernel/vmlinux.lds.S b/arch/unicore32/kernel/vmlinux.lds.S
+new file mode 100644
+index 000000000000..0b4eb89729e7
+--- /dev/null
++++ b/arch/unicore32/kernel/vmlinux.lds.S
+@@ -0,0 +1,61 @@
++/*
++ * linux/arch/unicore32/kernel/vmlinux.lds.S
++ *
++ * Code specific to PKUnity SoC and UniCore ISA
++ *
++ * Copyright (C) 2001-2010 GUAN Xue-tao
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include 
++#include 
++#include 
++#include 
++
++OUTPUT_ARCH(unicore32)
++ENTRY(stext)
++
++jiffies = jiffies_64;
++
++SECTIONS
++{
++	. = PAGE_OFFSET + KERNEL_IMAGE_START;
++
++	_text = .;
++	__init_begin = .;
++	HEAD_TEXT_SECTION
++	INIT_TEXT_SECTION(PAGE_SIZE)
++	INIT_DATA_SECTION(16)
++	PERCPU(PAGE_SIZE)
++	__init_end = .;
++
++	_stext = .;
++	.text : {		/* Real text segment */
++		TEXT_TEXT
++		SCHED_TEXT
++		LOCK_TEXT
++
++		*(.fixup)
++		*(.gnu.warning)
++	}
++	_etext = .;
++
++	_sdata = .;
++	RO_DATA_SECTION(PAGE_SIZE)
++	RW_DATA_SECTION(32, PAGE_SIZE, THREAD_SIZE)
++	_edata = .;
++
++	EXCEPTION_TABLE(32)
++	NOTES
++
++	BSS_SECTION(0, 0, 0)
++	_end = .;
++
++	STABS_DEBUG
++	DWARF_DEBUG
++
++	DISCARDS		/* Exit code and data */
++}

commit 7f509a9ef7af0d6ac852d49eb87ed2b9857821cc
+Author: GuanXuetao 
+Date:   Sat Jan 15 18:08:09 2011 +0800
+
+    asm-generic headers: add arch-specific __strnlen_user calling in uaccess.h
+    
+    This patch changes the implementation of strnlen_user in include/asm-generic/uaccess.h.
+    Originally, it calls strlen() function directly, which may not correctly handle the access of
+    user space in most mmu-enabled architectures.
+    New __strnlen_user is added for using as an architecture specific function.
+    
+    Signed-off-by: Guan Xuetao 
+    Reviewed-by: Arnd Bergmann 
+
+diff --git a/include/asm-generic/uaccess.h b/include/asm-generic/uaccess.h
+index b218b8513d04..ac68c999b6c2 100644
+--- a/include/asm-generic/uaccess.h
++++ b/include/asm-generic/uaccess.h
+@@ -288,14 +288,16 @@ strncpy_from_user(char *dst, const char __user *src, long count)
+  *
+  * Return 0 on exception, a value greater than N if too long
+  */
+-#ifndef strnlen_user
++#ifndef __strnlen_user
++#define __strnlen_user strnlen
++#endif
++
+ static inline long strnlen_user(const char __user *src, long n)
+ {
+ 	if (!access_ok(VERIFY_READ, src, 1))
+ 		return 0;
+-	return strlen((void * __force)src) + 1;
++	return __strnlen_user(src, n);
+ }
+-#endif
+ 
+ static inline long strlen_user(const char __user *src)
+ {

commit 38f5bf84bd588a82890f5ab32cba3317555a73e1
+Author: GuanXuetao 
+Date:   Sat Jan 15 18:07:08 2011 +0800
+
+    asm-generic headers: add ftrace.h
+    
+    This patch adds ftrace.h into asm-generic headers.
+    The file content could be empty in most architectures.
+    
+    Signed-off-by: Guan Xuetao 
+    Acked-by: Arnd Bergmann 
+
+diff --git a/include/asm-generic/ftrace.h b/include/asm-generic/ftrace.h
+new file mode 100644
+index 000000000000..51abba9ea7ad
+--- /dev/null
++++ b/include/asm-generic/ftrace.h
+@@ -0,0 +1,16 @@
++/*
++ * linux/include/asm-generic/ftrace.h
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __ASM_GENERIC_FTRACE_H__
++#define __ASM_GENERIC_FTRACE_H__
++
++/*
++ * Not all architectures need their own ftrace.h, the most
++ * common definitions are already in linux/ftrace.h.
++ */
++
++#endif /* __ASM_GENERIC_FTRACE_H__ */

commit d232b128e28f54cd8811dd4f6d8b72ffb12cc0a1
+Author: GuanXuetao 
+Date:   Sat Jan 15 18:06:44 2011 +0800
+
+    asm-generic headers: add sizes.h
+    
+    This patch adds sizes.h into asm-generic headers.
+    Only 32-bit version supported.
+    
+    Signed-off-by: Guan Xuetao 
+    Acked-by: Arnd Bergmann 
+
+diff --git a/include/asm-generic/sizes.h b/include/asm-generic/sizes.h
+new file mode 100644
+index 000000000000..ea5d4ef81061
+--- /dev/null
++++ b/include/asm-generic/sizes.h
+@@ -0,0 +1,47 @@
++/*
++ * linux/include/asm-generic/sizes.h
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __ASM_GENERIC_SIZES_H__
++#define __ASM_GENERIC_SIZES_H__
++
++#define SZ_1				0x00000001
++#define SZ_2				0x00000002
++#define SZ_4				0x00000004
++#define SZ_8				0x00000008
++#define SZ_16				0x00000010
++#define SZ_32				0x00000020
++#define SZ_64				0x00000040
++#define SZ_128				0x00000080
++#define SZ_256				0x00000100
++#define SZ_512				0x00000200
++
++#define SZ_1K				0x00000400
++#define SZ_2K				0x00000800
++#define SZ_4K				0x00001000
++#define SZ_8K				0x00002000
++#define SZ_16K				0x00004000
++#define SZ_32K				0x00008000
++#define SZ_64K				0x00010000
++#define SZ_128K				0x00020000
++#define SZ_256K				0x00040000
++#define SZ_512K				0x00080000
++
++#define SZ_1M				0x00100000
++#define SZ_2M				0x00200000
++#define SZ_4M				0x00400000
++#define SZ_8M				0x00800000
++#define SZ_16M				0x01000000
++#define SZ_32M				0x02000000
++#define SZ_64M				0x04000000
++#define SZ_128M				0x08000000
++#define SZ_256M				0x10000000
++#define SZ_512M				0x20000000
++
++#define SZ_1G				0x40000000
++#define SZ_2G				0x80000000
++
++#endif /* __ASM_GENERIC_SIZES_H__ */

commit 7dc59bdde7063323b6a70c2f0fadb399ede8038d
+Author: GuanXuetao 
+Date:   Tue Feb 22 19:06:43 2011 +0800
+
+    asm-generic: fix inX/outX functions for architectures that have PCI
+    
+    The definitions for the PC-style PIO functions in asm-generic/io.h were
+    meant as dummies so you could compile code on architectures without
+    ISA and PCI buses. However, unicore32 actually wants to use them
+    with a real PCI bus, so they need to be defined to actually address
+    the register window holding the I/O ports.
+    
+    Signed-off-by: Arnd Bergmann 
+
+diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
+index 4644c9a7f724..e0ffa3ddb02a 100644
+--- a/include/asm-generic/io.h
++++ b/include/asm-generic/io.h
+@@ -94,6 +94,10 @@ static inline void __raw_writeq(u64 b, volatile void __iomem *addr)
+ #define writeq(b,addr) __raw_writeq(__cpu_to_le64(b),addr)
+ #endif
+ 
++#ifndef PCI_IOBASE
++#define PCI_IOBASE ((void __iomem *) 0)
++#endif
++
+ /*****************************************************************************/
+ /*
+  * traditional input/output functions
+@@ -101,32 +105,32 @@ static inline void __raw_writeq(u64 b, volatile void __iomem *addr)
+ 
+ static inline u8 inb(unsigned long addr)
+ {
+-	return readb((volatile void __iomem *) addr);
++	return readb(addr + PCI_IOBASE);
+ }
+ 
+ static inline u16 inw(unsigned long addr)
+ {
+-	return readw((volatile void __iomem *) addr);
++	return readw(addr + PCI_IOBASE);
+ }
+ 
+ static inline u32 inl(unsigned long addr)
+ {
+-	return readl((volatile void __iomem *) addr);
++	return readl(addr + PCI_IOBASE);
+ }
+ 
+ static inline void outb(u8 b, unsigned long addr)
+ {
+-	writeb(b, (volatile void __iomem *) addr);
++	writeb(b, addr + PCI_IOBASE);
+ }
+ 
+ static inline void outw(u16 b, unsigned long addr)
+ {
+-	writew(b, (volatile void __iomem *) addr);
++	writew(b, addr + PCI_IOBASE);
+ }
+ 
+ static inline void outl(u32 b, unsigned long addr)
+ {
+-	writel(b, (volatile void __iomem *) addr);
++	writel(b, addr + PCI_IOBASE);
+ }
+ 
+ #define inb_p(addr)	inb(addr)
+@@ -213,32 +217,32 @@ static inline void outsl(unsigned long addr, const void *buffer, int count)
+ 
+ static inline void readsl(const void __iomem *addr, void *buf, int len)
+ {
+-	insl((unsigned long)addr, buf, len);
++	insl(addr - PCI_IOBASE, buf, len);
+ }
+ 
+ static inline void readsw(const void __iomem *addr, void *buf, int len)
+ {
+-	insw((unsigned long)addr, buf, len);
++	insw(addr - PCI_IOBASE, buf, len);
+ }
+ 
+ static inline void readsb(const void __iomem *addr, void *buf, int len)
+ {
+-	insb((unsigned long)addr, buf, len);
++	insb(addr - PCI_IOBASE, buf, len);
+ }
+ 
+ static inline void writesl(const void __iomem *addr, const void *buf, int len)
+ {
+-	outsl((unsigned long)addr, buf, len);
++	outsl(addr - PCI_IOBASE, buf, len);
+ }
+ 
+ static inline void writesw(const void __iomem *addr, const void *buf, int len)
+ {
+-	outsw((unsigned long)addr, buf, len);
++	outsw(addr - PCI_IOBASE, buf, len);
+ }
+ 
+ static inline void writesb(const void __iomem *addr, const void *buf, int len)
+ {
+-	outsb((unsigned long)addr, buf, len);
++	outsb(addr - PCI_IOBASE, buf, len);
+ }
+ 
+ #ifndef CONFIG_GENERIC_IOMAP
+@@ -269,8 +273,9 @@ static inline void writesb(const void __iomem *addr, const void *buf, int len)
+ 	outsl((unsigned long) (p), (src), (count))
+ #endif /* CONFIG_GENERIC_IOMAP */
+ 
+-
+-#define IO_SPACE_LIMIT 0xffffffff
++#ifndef IO_SPACE_LIMIT
++#define IO_SPACE_LIMIT 0xffff
++#endif
+ 
+ #ifdef __KERNEL__
+ 

commit 188c517a050ec5b123e72cab76ea213721e5bd9d
+Author: Lin Ming 
+Date:   Tue Sep 25 15:17:07 2012 +0000
+
+    ipv6: return errno pointers consistently for fib6_add_1()
+    
+    fib6_add_1() should consistently return errno pointers,
+    rather than a mixture of NULL and errno pointers.
+    
+    Signed-off-by: Lin Ming 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
+index 286acfc21250..24995a93ef8c 100644
+--- a/net/ipv6/ip6_fib.c
++++ b/net/ipv6/ip6_fib.c
+@@ -514,7 +514,7 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr,
+ 	ln = node_alloc();
+ 
+ 	if (!ln)
+-		return NULL;
++		return ERR_PTR(-ENOMEM);
+ 	ln->fn_bit = plen;
+ 
+ 	ln->parent = pn;
+@@ -561,7 +561,7 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr,
+ 				node_free(in);
+ 			if (ln)
+ 				node_free(ln);
+-			return NULL;
++			return ERR_PTR(-ENOMEM);
+ 		}
+ 
+ 		/*
+@@ -611,7 +611,7 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr,
+ 		ln = node_alloc();
+ 
+ 		if (!ln)
+-			return NULL;
++			return ERR_PTR(-ENOMEM);
+ 
+ 		ln->fn_bit = plen;
+ 
+@@ -777,11 +777,8 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
+ 
+ 	if (IS_ERR(fn)) {
+ 		err = PTR_ERR(fn);
+-		fn = NULL;
+-	}
+-
+-	if (!fn)
+ 		goto out;
++	}
+ 
+ 	pn = fn;
+ 
+@@ -820,15 +817,12 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
+ 					allow_create, replace_required);
+ 
+ 			if (IS_ERR(sn)) {
+-				err = PTR_ERR(sn);
+-				sn = NULL;
+-			}
+-			if (!sn) {
+ 				/* If it is failed, discard just allocated
+ 				   root, and then (in st_failure) stale node
+ 				   in main tree.
+ 				 */
+ 				node_free(sfn);
++				err = PTR_ERR(sn);
+ 				goto st_failure;
+ 			}
+ 
+@@ -843,10 +837,8 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
+ 
+ 			if (IS_ERR(sn)) {
+ 				err = PTR_ERR(sn);
+-				sn = NULL;
+-			}
+-			if (!sn)
+ 				goto st_failure;
++			}
+ 		}
+ 
+ 		if (!fn->leaf) {

commit 61648d91fc278fd1d500da8061d17e6920cd3500
+Author: Lin Ming 
+Date:   Sun Jul 29 02:00:03 2012 +0000
+
+    ipv4: clean up put_child
+    
+    The first parameter struct trie *t is not used anymore.
+    Remove it.
+    
+    Signed-off-by: Lin Ming 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
+index 2a6fdc2708c6..f0cdb30921c0 100644
+--- a/net/ipv4/fib_trie.c
++++ b/net/ipv4/fib_trie.c
+@@ -159,7 +159,6 @@ struct trie {
+ #endif
+ };
+ 
+-static void put_child(struct trie *t, struct tnode *tn, int i, struct rt_trie_node *n);
+ static void tnode_put_child_reorg(struct tnode *tn, int i, struct rt_trie_node *n,
+ 				  int wasfull);
+ static struct rt_trie_node *resize(struct trie *t, struct tnode *tn);
+@@ -490,7 +489,7 @@ static inline int tnode_full(const struct tnode *tn, const struct rt_trie_node *
+ 	return ((struct tnode *) n)->pos == tn->pos + tn->bits;
+ }
+ 
+-static inline void put_child(struct trie *t, struct tnode *tn, int i,
++static inline void put_child(struct tnode *tn, int i,
+ 			     struct rt_trie_node *n)
+ {
+ 	tnode_put_child_reorg(tn, i, n, -1);
+@@ -754,8 +753,8 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn)
+ 				goto nomem;
+ 			}
+ 
+-			put_child(t, tn, 2*i, (struct rt_trie_node *) left);
+-			put_child(t, tn, 2*i+1, (struct rt_trie_node *) right);
++			put_child(tn, 2*i, (struct rt_trie_node *) left);
++			put_child(tn, 2*i+1, (struct rt_trie_node *) right);
+ 		}
+ 	}
+ 
+@@ -776,9 +775,9 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn)
+ 			if (tkey_extract_bits(node->key,
+ 					      oldtnode->pos + oldtnode->bits,
+ 					      1) == 0)
+-				put_child(t, tn, 2*i, node);
++				put_child(tn, 2*i, node);
+ 			else
+-				put_child(t, tn, 2*i+1, node);
++				put_child(tn, 2*i+1, node);
+ 			continue;
+ 		}
+ 
+@@ -786,8 +785,8 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn)
+ 		inode = (struct tnode *) node;
+ 
+ 		if (inode->bits == 1) {
+-			put_child(t, tn, 2*i, rtnl_dereference(inode->child[0]));
+-			put_child(t, tn, 2*i+1, rtnl_dereference(inode->child[1]));
++			put_child(tn, 2*i, rtnl_dereference(inode->child[0]));
++			put_child(tn, 2*i+1, rtnl_dereference(inode->child[1]));
+ 
+ 			tnode_free_safe(inode);
+ 			continue;
+@@ -817,22 +816,22 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn)
+ 		 */
+ 
+ 		left = (struct tnode *) tnode_get_child(tn, 2*i);
+-		put_child(t, tn, 2*i, NULL);
++		put_child(tn, 2*i, NULL);
+ 
+ 		BUG_ON(!left);
+ 
+ 		right = (struct tnode *) tnode_get_child(tn, 2*i+1);
+-		put_child(t, tn, 2*i+1, NULL);
++		put_child(tn, 2*i+1, NULL);
+ 
+ 		BUG_ON(!right);
+ 
+ 		size = tnode_child_length(left);
+ 		for (j = 0; j < size; j++) {
+-			put_child(t, left, j, rtnl_dereference(inode->child[j]));
+-			put_child(t, right, j, rtnl_dereference(inode->child[j + size]));
++			put_child(left, j, rtnl_dereference(inode->child[j]));
++			put_child(right, j, rtnl_dereference(inode->child[j + size]));
+ 		}
+-		put_child(t, tn, 2*i, resize(t, left));
+-		put_child(t, tn, 2*i+1, resize(t, right));
++		put_child(tn, 2*i, resize(t, left));
++		put_child(tn, 2*i+1, resize(t, right));
+ 
+ 		tnode_free_safe(inode);
+ 	}
+@@ -877,7 +876,7 @@ static struct tnode *halve(struct trie *t, struct tnode *tn)
+ 			if (!newn)
+ 				goto nomem;
+ 
+-			put_child(t, tn, i/2, (struct rt_trie_node *)newn);
++			put_child(tn, i/2, (struct rt_trie_node *)newn);
+ 		}
+ 
+ 	}
+@@ -892,21 +891,21 @@ static struct tnode *halve(struct trie *t, struct tnode *tn)
+ 		if (left == NULL) {
+ 			if (right == NULL)    /* Both are empty */
+ 				continue;
+-			put_child(t, tn, i/2, right);
++			put_child(tn, i/2, right);
+ 			continue;
+ 		}
+ 
+ 		if (right == NULL) {
+-			put_child(t, tn, i/2, left);
++			put_child(tn, i/2, left);
+ 			continue;
+ 		}
+ 
+ 		/* Two nonempty children */
+ 		newBinNode = (struct tnode *) tnode_get_child(tn, i/2);
+-		put_child(t, tn, i/2, NULL);
+-		put_child(t, newBinNode, 0, left);
+-		put_child(t, newBinNode, 1, right);
+-		put_child(t, tn, i/2, resize(t, newBinNode));
++		put_child(tn, i/2, NULL);
++		put_child(newBinNode, 0, left);
++		put_child(newBinNode, 1, right);
++		put_child(tn, i/2, resize(t, newBinNode));
+ 	}
+ 	tnode_free_safe(oldtnode);
+ 	return tn;
+@@ -1125,7 +1124,7 @@ static struct list_head *fib_insert_node(struct trie *t, u32 key, int plen)
+ 		node_set_parent((struct rt_trie_node *)l, tp);
+ 
+ 		cindex = tkey_extract_bits(key, tp->pos, tp->bits);
+-		put_child(t, tp, cindex, (struct rt_trie_node *)l);
++		put_child(tp, cindex, (struct rt_trie_node *)l);
+ 	} else {
+ 		/* Case 3: n is a LEAF or a TNODE and the key doesn't match. */
+ 		/*
+@@ -1155,12 +1154,12 @@ static struct list_head *fib_insert_node(struct trie *t, u32 key, int plen)
+ 		node_set_parent((struct rt_trie_node *)tn, tp);
+ 
+ 		missbit = tkey_extract_bits(key, newpos, 1);
+-		put_child(t, tn, missbit, (struct rt_trie_node *)l);
+-		put_child(t, tn, 1-missbit, n);
++		put_child(tn, missbit, (struct rt_trie_node *)l);
++		put_child(tn, 1-missbit, n);
+ 
+ 		if (tp) {
+ 			cindex = tkey_extract_bits(key, tp->pos, tp->bits);
+-			put_child(t, tp, cindex, (struct rt_trie_node *)tn);
++			put_child(tp, cindex, (struct rt_trie_node *)tn);
+ 		} else {
+ 			rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn);
+ 			tp = tn;
+@@ -1619,7 +1618,7 @@ static void trie_leaf_remove(struct trie *t, struct leaf *l)
+ 
+ 	if (tp) {
+ 		t_key cindex = tkey_extract_bits(l->key, tp->pos, tp->bits);
+-		put_child(t, tp, cindex, NULL);
++		put_child(tp, cindex, NULL);
+ 		trie_rebalance(t, tp);
+ 	} else
+ 		RCU_INIT_POINTER(t->trie, NULL);

commit 4ea4bf7ebcbacee2f4736d261efb0693e87a34c9
+Author: Lin Ming 
+Date:   Sun Jul 29 01:19:55 2012 +0000
+
+    ipv4: fix debug info in tnode_new
+    
+    It should print size of struct rt_trie_node * allocated instead of size
+    of struct rt_trie_node.
+    
+    Signed-off-by: Lin Ming 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
+index 18cbc15b20d5..2a6fdc2708c6 100644
+--- a/net/ipv4/fib_trie.c
++++ b/net/ipv4/fib_trie.c
+@@ -473,7 +473,7 @@ static struct tnode *tnode_new(t_key key, int pos, int bits)
+ 	}
+ 
+ 	pr_debug("AT %p s=%zu %zu\n", tn, sizeof(struct tnode),
+-		 sizeof(struct rt_trie_node) << bits);
++		 sizeof(struct rt_trie_node *) << bits);
+ 	return tn;
+ }
+ 

commit 8fe5cb873b7ef7f4fa49477455e8f2e3d555230e
+Author: Lin Ming 
+Date:   Mon Jul 23 04:11:21 2012 +0000
+
+    ipv4: Remove redundant assignment
+    
+    It is redundant to set no_addr and accept_local to 0 and then set them
+    with other values just after that.
+    
+    Signed-off-by: Lin Ming 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
+index f277cf0e6321..8732cc7920ed 100644
+--- a/net/ipv4/fib_frontend.c
++++ b/net/ipv4/fib_frontend.c
+@@ -258,7 +258,6 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
+ 	fl4.flowi4_tos = tos;
+ 	fl4.flowi4_scope = RT_SCOPE_UNIVERSE;
+ 
+-	no_addr = accept_local = 0;
+ 	no_addr = idev->ifa_list == NULL;
+ 
+ 	accept_local = IN_DEV_ACCEPT_LOCAL(idev);

commit 9e33ce453f8ac8452649802bee1f410319408f4b
+Author: Lin Ming 
+Date:   Sat Jul 7 18:26:10 2012 +0800
+
+    ipvs: fix oops on NAT reply in br_nf context
+    
+    IPVS should not reset skb->nf_bridge in FORWARD hook
+    by calling nf_reset for NAT replies. It triggers oops in
+    br_nf_forward_finish.
+    
+    [  579.781508] BUG: unable to handle kernel NULL pointer dereference at 0000000000000004
+    [  579.781669] IP: [] br_nf_forward_finish+0x58/0x112
+    [  579.781792] PGD 218f9067 PUD 0
+    [  579.781865] Oops: 0000 [#1] SMP
+    [  579.781945] CPU 0
+    [  579.781983] Modules linked in:
+    [  579.782047]
+    [  579.782080]
+    [  579.782114] Pid: 4644, comm: qemu Tainted: G        W    3.5.0-rc5-00006-g95e69f9 #282 Hewlett-Packard  /30E8
+    [  579.782300] RIP: 0010:[]  [] br_nf_forward_finish+0x58/0x112
+    [  579.782455] RSP: 0018:ffff88007b003a98  EFLAGS: 00010287
+    [  579.782541] RAX: 0000000000000008 RBX: ffff8800762ead00 RCX: 000000000001670a
+    [  579.782653] RDX: 0000000000000000 RSI: 000000000000000a RDI: ffff8800762ead00
+    [  579.782845] RBP: ffff88007b003ac8 R08: 0000000000016630 R09: ffff88007b003a90
+    [  579.782957] R10: ffff88007b0038e8 R11: ffff88002da37540 R12: ffff88002da01a02
+    [  579.783066] R13: ffff88002da01a80 R14: ffff88002d83c000 R15: ffff88002d82a000
+    [  579.783177] FS:  0000000000000000(0000) GS:ffff88007b000000(0063) knlGS:00000000f62d1b70
+    [  579.783306] CS:  0010 DS: 002b ES: 002b CR0: 000000008005003b
+    [  579.783395] CR2: 0000000000000004 CR3: 00000000218fe000 CR4: 00000000000027f0
+    [  579.783505] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+    [  579.783684] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
+    [  579.783795] Process qemu (pid: 4644, threadinfo ffff880021b20000, task ffff880021aba760)
+    [  579.783919] Stack:
+    [  579.783959]  ffff88007693cedc ffff8800762ead00 ffff88002da01a02 ffff8800762ead00
+    [  579.784110]  ffff88002da01a02 ffff88002da01a80 ffff88007b003b18 ffffffff817b26c7
+    [  579.784260]  ffff880080000000 ffffffff81ef59f0 ffff8800762ead00 ffffffff81ef58b0
+    [  579.784477] Call Trace:
+    [  579.784523]  
+    [  579.784562]
+    [  579.784603]  [] br_nf_forward_ip+0x275/0x2c8
+    [  579.784707]  [] nf_iterate+0x47/0x7d
+    [  579.784797]  [] ? br_dev_queue_push_xmit+0xae/0xae
+    [  579.784906]  [] nf_hook_slow+0x6d/0x102
+    [  579.784995]  [] ? br_dev_queue_push_xmit+0xae/0xae
+    [  579.785175]  [] ? _raw_write_unlock_bh+0x19/0x1b
+    [  579.785179]  [] __br_forward+0x97/0xa2
+    [  579.785179]  [] br_handle_frame_finish+0x1a6/0x257
+    [  579.785179]  [] br_nf_pre_routing_finish+0x26d/0x2cb
+    [  579.785179]  [] br_nf_pre_routing+0x55d/0x5c1
+    [  579.785179]  [] nf_iterate+0x47/0x7d
+    [  579.785179]  [] ? br_handle_local_finish+0x44/0x44
+    [  579.785179]  [] nf_hook_slow+0x6d/0x102
+    [  579.785179]  [] ? br_handle_local_finish+0x44/0x44
+    [  579.785179]  [] ? sky2_poll+0xb35/0xb54
+    [  579.785179]  [] br_handle_frame+0x213/0x229
+    [  579.785179]  [] ? br_handle_frame_finish+0x257/0x257
+    [  579.785179]  [] __netif_receive_skb+0x2b4/0x3f1
+    [  579.785179]  [] process_backlog+0x99/0x1e2
+    [  579.785179]  [] net_rx_action+0xdf/0x242
+    [  579.785179]  [] __do_softirq+0xc1/0x1e0
+    [  579.785179]  [] ? trace_hardirqs_off_thunk+0x3a/0x6c
+    [  579.785179]  [] call_softirq+0x1c/0x30
+    
+    The steps to reproduce as follow,
+    
+    1. On Host1, setup brige br0(192.168.1.106)
+    2. Boot a kvm guest(192.168.1.105) on Host1 and start httpd
+    3. Start IPVS service on Host1
+       ipvsadm -A -t 192.168.1.106:80 -s rr
+       ipvsadm -a -t 192.168.1.106:80 -r 192.168.1.105:80 -m
+    4. Run apache benchmark on Host2(192.168.1.101)
+       ab -n 1000 http://192.168.1.106/
+    
+    ip_vs_reply4
+      ip_vs_out
+        handle_response
+          ip_vs_notrack
+            nf_reset()
+            {
+              skb->nf_bridge = NULL;
+            }
+    
+    Actually, IPVS wants in this case just to replace nfct
+    with untracked version. So replace the nf_reset(skb) call
+    in ip_vs_notrack() with a nf_conntrack_put(skb->nfct) call.
+    
+    Signed-off-by: Lin Ming 
+    Signed-off-by: Julian Anastasov 
+    Signed-off-by: Simon Horman 
+    Signed-off-by: Pablo Neira Ayuso 
+
+diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
+index d6146b4811c2..95374d1696a1 100644
+--- a/include/net/ip_vs.h
++++ b/include/net/ip_vs.h
+@@ -1425,7 +1425,7 @@ static inline void ip_vs_notrack(struct sk_buff *skb)
+ 	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
+ 
+ 	if (!ct || !nf_ct_is_untracked(ct)) {
+-		nf_reset(skb);
++		nf_conntrack_put(skb->nfct);
+ 		skb->nfct = &nf_ct_untracked_get()->ct_general;
+ 		skb->nfctinfo = IP_CT_NEW;
+ 		nf_conntrack_get(skb->nfct);

commit 1ff2b0c303698e486f1e0886b4d9876200ef8ca5
+Author: Lin Ming 
+Date:   Sat Apr 21 00:11:05 2012 +0800
+
+    xen: implement IRQ_WORK_VECTOR handler
+    
+    Signed-off-by: Lin Ming 
+    Signed-off-by: Konrad Rzeszutek Wilk 
+
+diff --git a/arch/x86/include/asm/xen/events.h b/arch/x86/include/asm/xen/events.h
+index 1df35417c412..cc146d51449e 100644
+--- a/arch/x86/include/asm/xen/events.h
++++ b/arch/x86/include/asm/xen/events.h
+@@ -6,6 +6,7 @@ enum ipi_vector {
+ 	XEN_CALL_FUNCTION_VECTOR,
+ 	XEN_CALL_FUNCTION_SINGLE_VECTOR,
+ 	XEN_SPIN_UNLOCK_VECTOR,
++	XEN_IRQ_WORK_VECTOR,
+ 
+ 	XEN_NR_IPIS,
+ };
+diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
+index 2dc6628c1520..3ec3f8eb19fc 100644
+--- a/arch/x86/xen/smp.c
++++ b/arch/x86/xen/smp.c
+@@ -16,6 +16,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ #include 
+@@ -41,10 +42,12 @@ cpumask_var_t xen_cpu_initialized_map;
+ static DEFINE_PER_CPU(int, xen_resched_irq);
+ static DEFINE_PER_CPU(int, xen_callfunc_irq);
+ static DEFINE_PER_CPU(int, xen_callfuncsingle_irq);
++static DEFINE_PER_CPU(int, xen_irq_work);
+ static DEFINE_PER_CPU(int, xen_debug_irq) = -1;
+ 
+ static irqreturn_t xen_call_function_interrupt(int irq, void *dev_id);
+ static irqreturn_t xen_call_function_single_interrupt(int irq, void *dev_id);
++static irqreturn_t xen_irq_work_interrupt(int irq, void *dev_id);
+ 
+ /*
+  * Reschedule call back.
+@@ -143,6 +146,17 @@ static int xen_smp_intr_init(unsigned int cpu)
+ 		goto fail;
+ 	per_cpu(xen_callfuncsingle_irq, cpu) = rc;
+ 
++	callfunc_name = kasprintf(GFP_KERNEL, "irqwork%d", cpu);
++	rc = bind_ipi_to_irqhandler(XEN_IRQ_WORK_VECTOR,
++				    cpu,
++				    xen_irq_work_interrupt,
++				    IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING,
++				    callfunc_name,
++				    NULL);
++	if (rc < 0)
++		goto fail;
++	per_cpu(xen_irq_work, cpu) = rc;
++
+ 	return 0;
+ 
+  fail:
+@@ -155,6 +169,8 @@ static int xen_smp_intr_init(unsigned int cpu)
+ 	if (per_cpu(xen_callfuncsingle_irq, cpu) >= 0)
+ 		unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu),
+ 				       NULL);
++	if (per_cpu(xen_irq_work, cpu) >= 0)
++		unbind_from_irqhandler(per_cpu(xen_irq_work, cpu), NULL);
+ 
+ 	return rc;
+ }
+@@ -509,6 +525,9 @@ static inline int xen_map_vector(int vector)
+ 	case CALL_FUNCTION_SINGLE_VECTOR:
+ 		xen_vector = XEN_CALL_FUNCTION_SINGLE_VECTOR;
+ 		break;
++	case IRQ_WORK_VECTOR:
++		xen_vector = XEN_IRQ_WORK_VECTOR;
++		break;
+ 	default:
+ 		xen_vector = -1;
+ 		printk(KERN_ERR "xen: vector 0x%x is not implemented\n",
+@@ -588,6 +607,16 @@ static irqreturn_t xen_call_function_single_interrupt(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
++static irqreturn_t xen_irq_work_interrupt(int irq, void *dev_id)
++{
++	irq_enter();
++	irq_work_run();
++	inc_irq_stat(apic_irq_work_irqs);
++	irq_exit();
++
++	return IRQ_HANDLED;
++}
++
+ static const struct smp_ops xen_smp_ops __initconst = {
+ 	.smp_prepare_boot_cpu = xen_smp_prepare_boot_cpu,
+ 	.smp_prepare_cpus = xen_smp_prepare_cpus,
+@@ -634,6 +663,7 @@ static void xen_hvm_cpu_die(unsigned int cpu)
+ 	unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu), NULL);
+ 	unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu), NULL);
+ 	unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu), NULL);
++	unbind_from_irqhandler(per_cpu(xen_irq_work, cpu), NULL);
+ 	native_cpu_die(cpu);
+ }
+ 

commit ab6ec39a191243b9968bb9ac7f26cc7ec30c618b
+Author: Lin Ming 
+Date:   Tue May 1 00:16:27 2012 +0800
+
+    xen/apic: implement io apic read with hypercall
+    
+    Implements xen_io_apic_read with hypercall, so it returns proper
+    IO-APIC information instead of fabricated one.
+    
+    Fallback to return an emulated IO_APIC values if hypercall fails.
+    
+    [v2: fallback to return an emulated IO_APIC values if hypercall fails]
+    Signed-off-by: Lin Ming 
+    Signed-off-by: Konrad Rzeszutek Wilk 
+
+diff --git a/arch/x86/xen/apic.c b/arch/x86/xen/apic.c
+index 73ade38caa32..1913bf2d2a9c 100644
+--- a/arch/x86/xen/apic.c
++++ b/arch/x86/xen/apic.c
+@@ -1,8 +1,21 @@
+ #include 
+ #include 
++#include 
++#include 
++#include 
+ 
+ unsigned int xen_io_apic_read(unsigned apic, unsigned reg)
+ {
++	struct physdev_apic apic_op;
++	int ret;
++
++	apic_op.apic_physbase = mpc_ioapic_addr(apic);
++	apic_op.reg = reg;
++	ret = HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic_op);
++	if (!ret)
++		return apic_op.value;
++
++	/* fallback to return an emulated IO_APIC values */
+ 	if (reg == 0x1)
+ 		return 0x00170020;
+ 	else if (reg == 0x0)

\ No newline at end of file diff --git a/detail/11.html b/detail/11.html new file mode 100644 index 0000000..90496e1 --- /dev/null +++ b/detail/11.html @@ -0,0 +1,5814 @@ +

Patches contributed by Unknown (fsl.cs.sunysb.edu)


commit f45827e84186af152492c6d0dcf4105b4a605f9b
+Author: Erez Zadok 
+Date:   Fri Oct 24 00:14:38 2014 +0200
+
+    overlayfs: implement show_options
+    
+    This is useful because of the stacking nature of overlayfs.  Users like to
+    find out (via /proc/mounts) which lower/upper directory were used at mount
+    time.
+    
+    AV: even failing ovl_parse_opt() could've done some kstrdup()
+    AV: failure of ovl_alloc_entry() should end up with ENOMEM, not EINVAL
+    
+    Signed-off-by: Erez Zadok 
+    Signed-off-by: Miklos Szeredi 
+
+diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
+index aaf562b9f937..7dcc24e84417 100644
+--- a/fs/overlayfs/super.c
++++ b/fs/overlayfs/super.c
+@@ -17,6 +17,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include "overlayfs.h"
+ 
+ MODULE_AUTHOR("Miklos Szeredi ");
+@@ -25,12 +26,20 @@ MODULE_LICENSE("GPL");
+ 
+ #define OVERLAYFS_SUPER_MAGIC 0x794c764f
+ 
++struct ovl_config {
++	char *lowerdir;
++	char *upperdir;
++	char *workdir;
++};
++
+ /* private information held for overlayfs's superblock */
+ struct ovl_fs {
+ 	struct vfsmount *upper_mnt;
+ 	struct vfsmount *lower_mnt;
+ 	struct dentry *workdir;
+ 	long lower_namelen;
++	/* pathnames of lower and upper dirs, for show_options */
++	struct ovl_config config;
+ };
+ 
+ struct ovl_dir_cache;
+@@ -384,6 +393,9 @@ static void ovl_put_super(struct super_block *sb)
+ 	mntput(ufs->upper_mnt);
+ 	mntput(ufs->lower_mnt);
+ 
++	kfree(ufs->config.lowerdir);
++	kfree(ufs->config.upperdir);
++	kfree(ufs->config.workdir);
+ 	kfree(ufs);
+ }
+ 
+@@ -413,15 +425,27 @@ static int ovl_statfs(struct dentry *dentry, struct kstatfs *buf)
+ 	return err;
+ }
+ 
++/**
++ * ovl_show_options
++ *
++ * Prints the mount options for a given superblock.
++ * Returns zero; does not fail.
++ */
++static int ovl_show_options(struct seq_file *m, struct dentry *dentry)
++{
++	struct super_block *sb = dentry->d_sb;
++	struct ovl_fs *ufs = sb->s_fs_info;
++
++	seq_printf(m, ",lowerdir=%s", ufs->config.lowerdir);
++	seq_printf(m, ",upperdir=%s", ufs->config.upperdir);
++	seq_printf(m, ",workdir=%s", ufs->config.workdir);
++	return 0;
++}
++
+ static const struct super_operations ovl_super_operations = {
+ 	.put_super	= ovl_put_super,
+ 	.statfs		= ovl_statfs,
+-};
+-
+-struct ovl_config {
+-	char *lowerdir;
+-	char *upperdir;
+-	char *workdir;
++	.show_options	= ovl_show_options,
+ };
+ 
+ enum {
+@@ -442,10 +466,6 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
+ {
+ 	char *p;
+ 
+-	config->upperdir = NULL;
+-	config->lowerdir = NULL;
+-	config->workdir = NULL;
+-
+ 	while ((p = strsep(&opt, ",")) != NULL) {
+ 		int token;
+ 		substring_t args[MAX_OPT_ARGS];
+@@ -586,39 +606,40 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
+ 	struct dentry *root_dentry;
+ 	struct ovl_entry *oe;
+ 	struct ovl_fs *ufs;
+-	struct ovl_config config;
+ 	struct kstatfs statfs;
+ 	int err;
+ 
+-	err = ovl_parse_opt((char *) data, &config);
+-	if (err)
++	err = -ENOMEM;
++	ufs = kzalloc(sizeof(struct ovl_fs), GFP_KERNEL);
++	if (!ufs)
+ 		goto out;
+ 
++	err = ovl_parse_opt((char *) data, &ufs->config);
++	if (err)
++		goto out_free_config;
++
+ 	/* FIXME: workdir is not needed for a R/O mount */
+ 	err = -EINVAL;
+-	if (!config.upperdir || !config.lowerdir || !config.workdir) {
++	if (!ufs->config.upperdir || !ufs->config.lowerdir ||
++	    !ufs->config.workdir) {
+ 		pr_err("overlayfs: missing upperdir or lowerdir or workdir\n");
+ 		goto out_free_config;
+ 	}
+ 
+ 	err = -ENOMEM;
+-	ufs = kmalloc(sizeof(struct ovl_fs), GFP_KERNEL);
+-	if (!ufs)
+-		goto out_free_config;
+-
+ 	oe = ovl_alloc_entry();
+ 	if (oe == NULL)
+-		goto out_free_ufs;
++		goto out_free_config;
+ 
+-	err = ovl_mount_dir(config.upperdir, &upperpath);
++	err = ovl_mount_dir(ufs->config.upperdir, &upperpath);
+ 	if (err)
+ 		goto out_free_oe;
+ 
+-	err = ovl_mount_dir(config.lowerdir, &lowerpath);
++	err = ovl_mount_dir(ufs->config.lowerdir, &lowerpath);
+ 	if (err)
+ 		goto out_put_upperpath;
+ 
+-	err = ovl_mount_dir(config.workdir, &workpath);
++	err = ovl_mount_dir(ufs->config.workdir, &workpath);
+ 	if (err)
+ 		goto out_put_lowerpath;
+ 
+@@ -674,7 +695,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
+ 	err = PTR_ERR(ufs->workdir);
+ 	if (IS_ERR(ufs->workdir)) {
+ 		pr_err("overlayfs: failed to create directory %s/%s\n",
+-		       config.workdir, OVL_WORKDIR_NAME);
++		       ufs->config.workdir, OVL_WORKDIR_NAME);
+ 		goto out_put_lower_mnt;
+ 	}
+ 
+@@ -729,12 +750,11 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
+ 	path_put(&upperpath);
+ out_free_oe:
+ 	kfree(oe);
+-out_free_ufs:
+-	kfree(ufs);
+ out_free_config:
+-	kfree(config.lowerdir);
+-	kfree(config.upperdir);
+-	kfree(config.workdir);
++	kfree(ufs->config.lowerdir);
++	kfree(ufs->config.upperdir);
++	kfree(ufs->config.workdir);
++	kfree(ufs);
+ out:
+ 	return err;
+ }

commit 1a4022f88d40e1255920b017556092ab926d7f66
+Author: Erez Zadok 
+Date:   Sat May 21 01:19:59 2011 -0400
+
+    VFS: move BUG_ON test for symlink nd->depth after current->link_count test
+    
+    This solves a serious VFS-level bug in nested_symlink (which was
+    rewritten from do_follow_link), and follows the order of depth tests
+    that existed before.
+    
+    The bug triggers a BUG_ON in fs/namei.c:1381, when running racer with
+    symlink and rename ops.
+    
+    Signed-off-by: Erez Zadok 
+    Acked-by: Miklos Szeredi 
+    Cc: stable@kernel.org
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/namei.c b/fs/namei.c
+index e3c4f112ebf7..6ff858c049c0 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -1378,12 +1378,12 @@ static inline int nested_symlink(struct path *path, struct nameidata *nd)
+ {
+ 	int res;
+ 
+-	BUG_ON(nd->depth >= MAX_NESTED_LINKS);
+ 	if (unlikely(current->link_count >= MAX_NESTED_LINKS)) {
+ 		path_put_conditional(path, nd);
+ 		path_put(&nd->path);
+ 		return -ELOOP;
+ 	}
++	BUG_ON(nd->depth >= MAX_NESTED_LINKS);
+ 
+ 	nd->depth++;
+ 	current->link_count++;

commit b3d7ae5f47a58a9f7b152deeaf7daa1fc558a8f1
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:48 2006 -0800
+
+    [PATCH] struct path: convert zorro
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/zorro/proc.c b/drivers/zorro/proc.c
+index 7aa2d3de6d37..60b05bc15642 100644
+--- a/drivers/zorro/proc.c
++++ b/drivers/zorro/proc.c
+@@ -47,7 +47,7 @@ proc_bus_zorro_lseek(struct file *file, loff_t off, int whence)
+ static ssize_t
+ proc_bus_zorro_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+ {
+-	struct inode *ino = file->f_dentry->d_inode;
++	struct inode *ino = file->f_path.dentry->d_inode;
+ 	struct proc_dir_entry *dp = PDE(ino);
+ 	struct zorro_dev *z = dp->data;
+ 	struct ConfigDev cd;

commit ad9a824e004067a3d888567a991603f1ac36efb2
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:48 2006 -0800
+
+    [PATCH] struct path: convert video
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c
+index ab34b96acc31..30a8369757e7 100644
+--- a/drivers/video/arcfb.c
++++ b/drivers/video/arcfb.c
+@@ -454,7 +454,7 @@ static ssize_t arcfb_write(struct file *file, const char __user *buf, size_t cou
+ 	unsigned int xres;
+ 
+ 	p = *ppos;
+-	inode = file->f_dentry->d_inode;
++	inode = file->f_path.dentry->d_inode;
+ 	fbidx = iminor(inode);
+ 	info = registered_fb[fbidx];
+ 
+diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c
+index 737257d278f0..29e07c109887 100644
+--- a/drivers/video/epson1355fb.c
++++ b/drivers/video/epson1355fb.c
+@@ -405,7 +405,7 @@ static inline unsigned long copy_to_user16(void *to, const void *from,
+ static ssize_t
+ epson1355fb_read(struct file *file, char *buf, size_t count, loff_t * ppos)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	int fbidx = iminor(inode);
+ 	struct fb_info *info = registered_fb[fbidx];
+ 	unsigned long p = *ppos;
+@@ -437,7 +437,7 @@ static ssize_t
+ epson1355fb_write(struct file *file, const char *buf,
+ 		  size_t count, loff_t * ppos)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	int fbidx = iminor(inode);
+ 	struct fb_info *info = registered_fb[fbidx];
+ 	unsigned long p = *ppos;
+diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
+index e973a87fbb01..00a216879785 100644
+--- a/drivers/video/fbmem.c
++++ b/drivers/video/fbmem.c
+@@ -572,7 +572,7 @@ static ssize_t
+ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+ {
+ 	unsigned long p = *ppos;
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	int fbidx = iminor(inode);
+ 	struct fb_info *info = registered_fb[fbidx];
+ 	u32 *buffer, *dst;
+@@ -647,7 +647,7 @@ static ssize_t
+ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+ {
+ 	unsigned long p = *ppos;
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	int fbidx = iminor(inode);
+ 	struct fb_info *info = registered_fb[fbidx];
+ 	u32 *buffer, *src;
+@@ -1081,7 +1081,7 @@ static int fb_get_fscreeninfo(struct inode *inode, struct file *file,
+ static long
+ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	int fbidx = iminor(inode);
+ 	struct fb_info *info = registered_fb[fbidx];
+ 	struct fb_ops *fb = info->fbops;
+@@ -1121,7 +1121,7 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ static int 
+ fb_mmap(struct file *file, struct vm_area_struct * vma)
+ {
+-	int fbidx = iminor(file->f_dentry->d_inode);
++	int fbidx = iminor(file->f_path.dentry->d_inode);
+ 	struct fb_info *info = registered_fb[fbidx];
+ 	struct fb_ops *fb = info->fbops;
+ 	unsigned long off;

commit 723731b2eef6599cf09af1fbfe0b12857b439e2d
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:47 2006 -0800
+
+    [PATCH] struct path: convert v4l
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/media/video/compat_ioctl32.c b/drivers/media/video/compat_ioctl32.c
+index d82a488f12a6..f065ad12cc61 100644
+--- a/drivers/media/video/compat_ioctl32.c
++++ b/drivers/media/video/compat_ioctl32.c
+@@ -118,7 +118,7 @@ static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ 		ret = file->f_op->unlocked_ioctl(file, cmd, arg);
+ 	else if (file->f_op->ioctl) {
+ 		lock_kernel();
+-		ret = file->f_op->ioctl(file->f_dentry->d_inode, file, cmd, arg);
++		ret = file->f_op->ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
+ 		unlock_kernel();
+ 	}
+ 
+diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
+index d424a4129d69..41ec0c4b35a2 100644
+--- a/drivers/media/video/videodev.c
++++ b/drivers/media/video/videodev.c
+@@ -105,7 +105,7 @@ static DEFINE_MUTEX(videodev_lock);
+ 
+ struct video_device* video_devdata(struct file *file)
+ {
+-	return video_device[iminor(file->f_dentry->d_inode)];
++	return video_device[iminor(file->f_path.dentry->d_inode)];
+ }
+ 
+ /*
+diff --git a/drivers/media/video/zoran_procfs.c b/drivers/media/video/zoran_procfs.c
+index c7f6f6488360..c374c76b3753 100644
+--- a/drivers/media/video/zoran_procfs.c
++++ b/drivers/media/video/zoran_procfs.c
+@@ -144,7 +144,7 @@ static int zoran_open(struct inode *inode, struct file *file)
+ static ssize_t zoran_write(struct file *file, const char __user *buffer,
+ 			size_t count, loff_t *ppos)
+ {
+-	struct zoran *zr = PDE(file->f_dentry->d_inode)->data;
++	struct zoran *zr = PDE(file->f_path.dentry->d_inode)->data;
+ 	char *string, *sp;
+ 	char *line, *ldelim, *varname, *svar, *tdelim;
+ 
+@@ -165,7 +165,7 @@ static ssize_t zoran_write(struct file *file, const char __user *buffer,
+ 	}
+ 	string[count] = 0;
+ 	dprintk(4, KERN_INFO "%s: write_proc: name=%s count=%zu zr=%p\n",
+-		ZR_DEVNAME(zr), file->f_dentry->d_name.name, count, zr);
++		ZR_DEVNAME(zr), file->f_path.dentry->d_name.name, count, zr);
+ 	ldelim = " \t\n";
+ 	tdelim = "=";
+ 	line = strpbrk(sp, ldelim);

commit 33cb89940082c54f348062db2f8bab6cf8fed816
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:46 2006 -0800
+
+    [PATCH] struct path: convert usb
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
+index b5d6a79af0be..11dad22da41c 100644
+--- a/drivers/usb/core/inode.c
++++ b/drivers/usb/core/inode.c
+@@ -379,7 +379,7 @@ static loff_t default_file_lseek (struct file *file, loff_t offset, int orig)
+ {
+ 	loff_t retval = -EINVAL;
+ 
+-	mutex_lock(&file->f_dentry->d_inode->i_mutex);
++	mutex_lock(&file->f_path.dentry->d_inode->i_mutex);
+ 	switch(orig) {
+ 	case 0:
+ 		if (offset > 0) {
+@@ -396,7 +396,7 @@ static loff_t default_file_lseek (struct file *file, loff_t offset, int orig)
+ 	default:
+ 		break;
+ 	}
+-	mutex_unlock(&file->f_dentry->d_inode->i_mutex);
++	mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
+ 	return retval;
+ }
+ 
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index c98316ce8384..a265e262a2ee 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -1909,10 +1909,10 @@ static int fsync_sub(struct lun *curlun)
+ 	if (!filp->f_op->fsync)
+ 		return -EINVAL;
+ 
+-	inode = filp->f_dentry->d_inode;
++	inode = filp->f_path.dentry->d_inode;
+ 	mutex_lock(&inode->i_mutex);
+ 	rc = filemap_fdatawrite(inode->i_mapping);
+-	err = filp->f_op->fsync(filp, filp->f_dentry, 1);
++	err = filp->f_op->fsync(filp, filp->f_path.dentry, 1);
+ 	if (!rc)
+ 		rc = err;
+ 	err = filemap_fdatawait(inode->i_mapping);
+@@ -1950,7 +1950,7 @@ static int do_synchronize_cache(struct fsg_dev *fsg)
+ static void invalidate_sub(struct lun *curlun)
+ {
+ 	struct file	*filp = curlun->filp;
+-	struct inode	*inode = filp->f_dentry->d_inode;
++	struct inode	*inode = filp->f_path.dentry->d_inode;
+ 	unsigned long	rc;
+ 
+ 	rc = invalidate_inode_pages(inode->i_mapping);
+@@ -3526,8 +3526,8 @@ static int open_backing_file(struct lun *curlun, const char *filename)
+ 	if (!(filp->f_mode & FMODE_WRITE))
+ 		ro = 1;
+ 
+-	if (filp->f_dentry)
+-		inode = filp->f_dentry->d_inode;
++	if (filp->f_path.dentry)
++		inode = filp->f_path.dentry->d_inode;
+ 	if (inode && S_ISBLK(inode->i_mode)) {
+ 		if (bdev_read_only(inode->i_bdev))
+ 			ro = 1;
+@@ -3606,7 +3606,7 @@ static ssize_t show_file(struct device *dev, struct device_attribute *attr, char
+ 
+ 	down_read(&fsg->filesem);
+ 	if (backing_file_is_open(curlun)) {	// Get the complete pathname
+-		p = d_path(curlun->filp->f_dentry, curlun->filp->f_vfsmnt,
++		p = d_path(curlun->filp->f_path.dentry, curlun->filp->f_path.mnt,
+ 				buf, PAGE_SIZE - 1);
+ 		if (IS_ERR(p))
+ 			rc = PTR_ERR(p);
+@@ -4030,8 +4030,8 @@ static int __init fsg_bind(struct usb_gadget *gadget)
+ 		if (backing_file_is_open(curlun)) {
+ 			p = NULL;
+ 			if (pathbuf) {
+-				p = d_path(curlun->filp->f_dentry,
+-					curlun->filp->f_vfsmnt,
++				p = d_path(curlun->filp->f_path.dentry,
++					curlun->filp->f_path.mnt,
+ 					pathbuf, PATH_MAX);
+ 				if (IS_ERR(p))
+ 					p = NULL;
+diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
+index b99ca9c79821..0398908b15d4 100644
+--- a/drivers/usb/misc/sisusbvga/sisusb.c
++++ b/drivers/usb/misc/sisusbvga/sisusb.c
+@@ -3168,7 +3168,7 @@ sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+ 		case SISUSB_GET_CONFIG:
+ 		case SISUSB_COMMAND:
+ 			lock_kernel();
+-			retval = sisusb_ioctl(f->f_dentry->d_inode, f, cmd, arg);
++			retval = sisusb_ioctl(f->f_path.dentry->d_inode, f, cmd, arg);
+ 			unlock_kernel();
+ 			return retval;
+ 

commit 592ccbf9fba665031765d9bb0f6c1ede1fa62f96
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:45 2006 -0800
+
+    [PATCH] struct path: convert unix
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/net/unix/garbage.c b/net/unix/garbage.c
+index 746c2f4a5fa6..f14ad6635fcc 100644
+--- a/net/unix/garbage.c
++++ b/net/unix/garbage.c
+@@ -96,7 +96,7 @@ atomic_t unix_tot_inflight = ATOMIC_INIT(0);
+ static struct sock *unix_get_socket(struct file *filp)
+ {
+ 	struct sock *u_sock = NULL;
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 
+ 	/*
+ 	 *	Socket ?

commit 763454d6108ad1c6d4e1013321aef8bf5efb3a4f
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:45 2006 -0800
+
+    [PATCH] struct path: convert ufs
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c
+index 7f0a0aa63584..433b6f68403a 100644
+--- a/fs/ufs/dir.c
++++ b/fs/ufs/dir.c
+@@ -426,7 +426,7 @@ static int
+ ufs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ {
+ 	loff_t pos = filp->f_pos;
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct super_block *sb = inode->i_sb;
+ 	unsigned int offset = pos & ~PAGE_CACHE_MASK;
+ 	unsigned long n = pos >> PAGE_CACHE_SHIFT;

commit 5096e933a943c23bd9314b0ac7e14d07073cb2e5
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:44 2006 -0800
+
+    [PATCH] struct path: convert udf
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/udf/dir.c b/fs/udf/dir.c
+index 8c28efa3b8ff..2391c9150c49 100644
+--- a/fs/udf/dir.c
++++ b/fs/udf/dir.c
+@@ -77,7 +77,7 @@ const struct file_operations udf_dir_operations = {
+ 
+ int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ {
+-	struct inode *dir = filp->f_dentry->d_inode;
++	struct inode *dir = filp->f_path.dentry->d_inode;
+ 	int result;
+ 
+ 	lock_kernel();
+@@ -225,7 +225,7 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
+ 
+ 		if ( cfi.fileCharacteristics & FID_FILE_CHAR_PARENT )
+ 		{
+-			iblock = parent_ino(filp->f_dentry);
++			iblock = parent_ino(filp->f_path.dentry);
+ 			flen = 2;
+ 			memcpy(fname, "..", flen);
+ 			dt_type = DT_DIR;
+diff --git a/fs/udf/file.c b/fs/udf/file.c
+index 7aedd552cba1..d81f2db7b0e3 100644
+--- a/fs/udf/file.c
++++ b/fs/udf/file.c
+@@ -108,7 +108,7 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
+ {
+ 	ssize_t retval;
+ 	struct file *file = iocb->ki_filp;
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	int err, pos;
+ 	size_t count = iocb->ki_left;
+ 

commit 5495ca657d854ac57733ce5a52eee52255b3f4d8
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:43 2006 -0800
+
+    [PATCH] struct path: convert sysv
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c
+index f2bef962d309..ebf7007fa161 100644
+--- a/fs/sysv/dir.c
++++ b/fs/sysv/dir.c
+@@ -70,7 +70,7 @@ static struct page * dir_get_page(struct inode *dir, unsigned long n)
+ static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir)
+ {
+ 	unsigned long pos = filp->f_pos;
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct super_block *sb = inode->i_sb;
+ 	unsigned offset = pos & ~PAGE_CACHE_MASK;
+ 	unsigned long n = pos >> PAGE_CACHE_SHIFT;

commit 303b46bb77a4b1679fd39d7ab5597630743e0ff5
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:42 2006 -0800
+
+    [PATCH] struct path: convert sunrpc
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index a02ecc1f230d..e1a104abb782 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -501,7 +501,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
+ 	if (!buf)
+ 		goto out;
+ 
+-	clnt = RPC_I(filp->f_dentry->d_inode)->private;
++	clnt = RPC_I(filp->f_path.dentry->d_inode)->private;
+ 	err = -EFAULT;
+ 	if (copy_from_user(buf, src, mlen))
+ 		goto err;
+diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
+index d96fd466a9a4..80aff0474572 100644
+--- a/net/sunrpc/cache.c
++++ b/net/sunrpc/cache.c
+@@ -670,7 +670,7 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
+ {
+ 	struct cache_reader *rp = filp->private_data;
+ 	struct cache_request *rq;
+-	struct cache_detail *cd = PDE(filp->f_dentry->d_inode)->data;
++	struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data;
+ 	int err;
+ 
+ 	if (count == 0)
+@@ -747,7 +747,7 @@ cache_write(struct file *filp, const char __user *buf, size_t count,
+ 	    loff_t *ppos)
+ {
+ 	int err;
+-	struct cache_detail *cd = PDE(filp->f_dentry->d_inode)->data;
++	struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data;
+ 
+ 	if (count == 0)
+ 		return 0;
+@@ -778,7 +778,7 @@ cache_poll(struct file *filp, poll_table *wait)
+ 	unsigned int mask;
+ 	struct cache_reader *rp = filp->private_data;
+ 	struct cache_queue *cq;
+-	struct cache_detail *cd = PDE(filp->f_dentry->d_inode)->data;
++	struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data;
+ 
+ 	poll_wait(filp, &queue_wait, wait);
+ 
+@@ -1254,7 +1254,7 @@ static struct file_operations content_file_operations = {
+ static ssize_t read_flush(struct file *file, char __user *buf,
+ 			    size_t count, loff_t *ppos)
+ {
+-	struct cache_detail *cd = PDE(file->f_dentry->d_inode)->data;
++	struct cache_detail *cd = PDE(file->f_path.dentry->d_inode)->data;
+ 	char tbuf[20];
+ 	unsigned long p = *ppos;
+ 	int len;
+@@ -1275,7 +1275,7 @@ static ssize_t read_flush(struct file *file, char __user *buf,
+ static ssize_t write_flush(struct file * file, const char __user * buf,
+ 			     size_t count, loff_t *ppos)
+ {
+-	struct cache_detail *cd = PDE(file->f_dentry->d_inode)->data;
++	struct cache_detail *cd = PDE(file->f_path.dentry->d_inode)->data;
+ 	char tbuf[20];
+ 	char *ep;
+ 	long flushtime;
+diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
+index 19703aa9659e..89273d35e0cc 100644
+--- a/net/sunrpc/rpc_pipe.c
++++ b/net/sunrpc/rpc_pipe.c
+@@ -214,7 +214,7 @@ rpc_pipe_release(struct inode *inode, struct file *filp)
+ static ssize_t
+ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset)
+ {
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct rpc_inode *rpci = RPC_I(inode);
+ 	struct rpc_pipe_msg *msg;
+ 	int res = 0;
+@@ -257,7 +257,7 @@ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset)
+ static ssize_t
+ rpc_pipe_write(struct file *filp, const char __user *buf, size_t len, loff_t *offset)
+ {
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct rpc_inode *rpci = RPC_I(inode);
+ 	int res;
+ 
+@@ -275,7 +275,7 @@ rpc_pipe_poll(struct file *filp, struct poll_table_struct *wait)
+ 	struct rpc_inode *rpci;
+ 	unsigned int mask = 0;
+ 
+-	rpci = RPC_I(filp->f_dentry->d_inode);
++	rpci = RPC_I(filp->f_path.dentry->d_inode);
+ 	poll_wait(filp, &rpci->waitq, wait);
+ 
+ 	mask = POLLOUT | POLLWRNORM;
+@@ -290,7 +290,7 @@ static int
+ rpc_pipe_ioctl(struct inode *ino, struct file *filp,
+ 		unsigned int cmd, unsigned long arg)
+ {
+-	struct rpc_inode *rpci = RPC_I(filp->f_dentry->d_inode);
++	struct rpc_inode *rpci = RPC_I(filp->f_path.dentry->d_inode);
+ 	int len;
+ 
+ 	switch (cmd) {

commit 1250ca4c8f48de482ec7c476cb024fe93ad1fbb3
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:41 2006 -0800
+
+    [PATCH] struct path: convert sparc64
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c
+index d7caa60a0074..f205fc7cbcd0 100644
+--- a/arch/sparc64/kernel/binfmt_aout32.c
++++ b/arch/sparc64/kernel/binfmt_aout32.c
+@@ -209,7 +209,7 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+ 	if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
+ 	     N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||
+ 	    N_TRSIZE(ex) || N_DRSIZE(ex) ||
+-	    bprm->file->f_dentry->d_inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
++	    bprm->file->f_path.dentry->d_inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
+ 		return -ENOEXEC;
+ 	}
+ 
+@@ -349,7 +349,7 @@ static int load_aout32_library(struct file *file)
+ 	int retval;
+ 	struct exec ex;
+ 
+-	inode = file->f_dentry->d_inode;
++	inode = file->f_path.dentry->d_inode;
+ 
+ 	retval = -ENOEXEC;
+ 	error = kernel_read(file, 0, (char *) &ex, sizeof(ex));
+diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
+index 7da72d3b322a..4446f66590fa 100644
+--- a/arch/sparc64/kernel/sys_sunos32.c
++++ b/arch/sparc64/kernel/sys_sunos32.c
+@@ -83,7 +83,7 @@ asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 of
+  		file = fget(fd);
+ 		if (!file)
+ 			goto out;
+-		inode = file->f_dentry->d_inode;
++		inode = file->f_path.dentry->d_inode;
+ 		if (imajor(inode) == MEM_MAJOR && iminor(inode) == 5) {
+ 			flags |= MAP_ANONYMOUS;
+ 			fput(file);
+@@ -615,7 +615,7 @@ sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr)
+ 	if (!file)
+ 		return 0;
+ 
+-	inode = file->f_dentry->d_inode;
++	inode = file->f_path.dentry->d_inode;
+ 
+ 	socket = SOCKET_I(inode);
+ 	local.sin_family = AF_INET;
+diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c
+index 12a940cc791f..61be597bf430 100644
+--- a/arch/sparc64/solaris/fs.c
++++ b/arch/sparc64/solaris/fs.c
+@@ -449,7 +449,7 @@ asmlinkage int solaris_fstatvfs(unsigned int fd, u32 buf)
+ 	error = -EBADF;
+ 	file = fget(fd);
+ 	if (file) {
+-		error = report_statvfs(file->f_vfsmnt, file->f_dentry->d_inode, buf);
++		error = report_statvfs(file->f_path.mnt, file->f_path.dentry->d_inode, buf);
+ 		fput(file);
+ 	}
+ 
+@@ -481,7 +481,7 @@ asmlinkage int solaris_fstatvfs64(unsigned int fd, u32 buf)
+ 	file = fget(fd);
+ 	if (file) {
+ 		lock_kernel();
+-		error = report_statvfs64(file->f_vfsmnt, file->f_dentry->d_inode, buf);
++		error = report_statvfs64(file->f_path.mnt, file->f_path.dentry->d_inode, buf);
+ 		unlock_kernel();
+ 		fput(file);
+ 	}
+diff --git a/arch/sparc64/solaris/ioctl.c b/arch/sparc64/solaris/ioctl.c
+index be0a054e3ed6..330743c5b3d8 100644
+--- a/arch/sparc64/solaris/ioctl.c
++++ b/arch/sparc64/solaris/ioctl.c
+@@ -299,8 +299,8 @@ static inline int solaris_sockmod(unsigned int fd, unsigned int cmd, u32 arg)
+ 	rcu_read_lock();
+ 	fdt = files_fdtable(current->files);
+ 	if (! fdt->fd[fd] ||
+-	    ! fdt->fd[fd]->f_dentry ||
+-	    ! (ino = fdt->fd[fd]->f_dentry->d_inode) ||
++	    ! fdt->fd[fd]->f_path.dentry ||
++	    ! (ino = fdt->fd[fd]->f_path.dentry->d_inode) ||
+ 	    ! S_ISSOCK(ino->i_mode)) {
+ 		rcu_read_unlock();
+ 		return TBADF;
+@@ -480,7 +480,7 @@ static inline int solaris_S(struct file *filp, unsigned int fd, unsigned int cmd
+         struct sol_socket_struct *sock;
+         struct module_info *mi;
+ 
+-        ino = filp->f_dentry->d_inode;
++        ino = filp->f_path.dentry->d_inode;
+         if (!S_ISSOCK(ino->i_mode))
+ 		return -EBADF;
+         sock = filp->private_data;
+diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c
+index e84241d5f7f4..bca16e8c95c3 100644
+--- a/arch/sparc64/solaris/misc.c
++++ b/arch/sparc64/solaris/misc.c
+@@ -77,7 +77,7 @@ static u32 do_solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u64 o
+ 		if (!file)
+ 			goto out;
+ 		else {
+-			struct inode * inode = file->f_dentry->d_inode;
++			struct inode * inode = file->f_path.dentry->d_inode;
+ 			if(imajor(inode) == MEM_MAJOR &&
+ 			   iminor(inode) == 5) {
+ 				flags |= MAP_ANONYMOUS;
+diff --git a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c
+index 7c90e41fd3be..89a4757f192f 100644
+--- a/arch/sparc64/solaris/socksys.c
++++ b/arch/sparc64/solaris/socksys.c
+@@ -96,13 +96,13 @@ static int socksys_open(struct inode * inode, struct file * filp)
+ 	 * No shit.  WTF is it supposed to do, anyway?
+ 	 *
+ 	 * Try instead:
+-	 * d_delete(filp->f_dentry), then d_instantiate with sock inode
++	 * d_delete(filp->f_path.dentry), then d_instantiate with sock inode
+ 	 */
+-	dentry = filp->f_dentry;
+-	filp->f_dentry = dget(fcheck(fd)->f_dentry);
+-	filp->f_dentry->d_inode->i_rdev = inode->i_rdev;
+-	filp->f_dentry->d_inode->i_flock = inode->i_flock;
+-	SOCKET_I(filp->f_dentry->d_inode)->file = filp;
++	dentry = filp->f_path.dentry;
++	filp->f_path.dentry = dget(fcheck(fd)->f_path.dentry);
++	filp->f_path.dentry->d_inode->i_rdev = inode->i_rdev;
++	filp->f_path.dentry->d_inode->i_flock = inode->i_flock;
++	SOCKET_I(filp->f_path.dentry->d_inode)->file = filp;
+ 	filp->f_op = &socksys_file_ops;
+         sock = (struct sol_socket_struct*) 
+         	mykmalloc(sizeof(struct sol_socket_struct), GFP_KERNEL);
+@@ -148,7 +148,7 @@ static unsigned int socksys_poll(struct file * filp, poll_table * wait)
+ 	struct inode *ino;
+ 	unsigned int mask = 0;
+ 
+-	ino=filp->f_dentry->d_inode;
++	ino=filp->f_path.dentry->d_inode;
+ 	if (ino && S_ISSOCK(ino->i_mode)) {
+ 		struct sol_socket_struct *sock;
+ 		sock = (struct sol_socket_struct*)filp->private_data;
+diff --git a/arch/sparc64/solaris/timod.c b/arch/sparc64/solaris/timod.c
+index b84e5456b025..a9d32ceabf26 100644
+--- a/arch/sparc64/solaris/timod.c
++++ b/arch/sparc64/solaris/timod.c
+@@ -147,7 +147,7 @@ static void timod_wake_socket(unsigned int fd)
+ 
+ 	SOLD("wakeing socket");
+ 	fdt = files_fdtable(current->files);
+-	sock = SOCKET_I(fdt->fd[fd]->f_dentry->d_inode);
++	sock = SOCKET_I(fdt->fd[fd]->f_path.dentry->d_inode);
+ 	wake_up_interruptible(&sock->wait);
+ 	read_lock(&sock->sk->sk_callback_lock);
+ 	if (sock->fasync_list && !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
+@@ -361,7 +361,7 @@ int timod_putmsg(unsigned int fd, char __user *ctl_buf, int ctl_len,
+ 
+ 	fdt = files_fdtable(current->files);
+ 	filp = fdt->fd[fd];
+-	ino = filp->f_dentry->d_inode;
++	ino = filp->f_path.dentry->d_inode;
+ 	sock = (struct sol_socket_struct *)filp->private_data;
+ 	SOLD("entry");
+ 	if (get_user(ret, (int __user *)A(ctl_buf)))
+@@ -644,7 +644,7 @@ int timod_getmsg(unsigned int fd, char __user *ctl_buf, int ctl_maxlen, s32 __us
+ 	SOLDD(("%u %p %d %p %p %d %p %d\n", fd, ctl_buf, ctl_maxlen, ctl_len, data_buf, data_maxlen, data_len, *flags_p));
+ 	fdt = files_fdtable(current->files);
+ 	filp = fdt->fd[fd];
+-	ino = filp->f_dentry->d_inode;
++	ino = filp->f_path.dentry->d_inode;
+ 	sock = (struct sol_socket_struct *)filp->private_data;
+ 	SOLDD(("%p %p\n", sock->pfirst, sock->pfirst ? sock->pfirst->next : NULL));
+ 	if ( ctl_maxlen > 0 && !sock->pfirst && SOCKET_I(ino)->type == SOCK_STREAM
+@@ -865,7 +865,7 @@ asmlinkage int solaris_getmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
+ 	filp = fdt->fd[fd];
+ 	if(!filp) goto out;
+ 
+-	ino = filp->f_dentry->d_inode;
++	ino = filp->f_path.dentry->d_inode;
+ 	if (!ino || !S_ISSOCK(ino->i_mode))
+ 		goto out;
+ 
+@@ -933,7 +933,7 @@ asmlinkage int solaris_putmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
+ 	filp = fdt->fd[fd];
+ 	if(!filp) goto out;
+ 
+-	ino = filp->f_dentry->d_inode;
++	ino = filp->f_path.dentry->d_inode;
+ 	if (!ino) goto out;
+ 
+ 	if (!S_ISSOCK(ino->i_mode) &&

commit 45e079810a27d4a072347d90d405948f95cee812
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:41 2006 -0800
+
+    [PATCH] struct path: convert sparc
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c
+index 6f3ac548ee66..0bf8c165fc92 100644
+--- a/arch/sparc/kernel/sys_sunos.c
++++ b/arch/sparc/kernel/sys_sunos.c
+@@ -94,8 +94,8 @@ asmlinkage unsigned long sunos_mmap(unsigned long addr, unsigned long len,
+ 	 * SunOS is so stupid some times... hmph!
+ 	 */
+ 	if (file) {
+-		if (imajor(file->f_dentry->d_inode) == MEM_MAJOR &&
+-		    iminor(file->f_dentry->d_inode) == 5) {
++		if (imajor(file->f_path.dentry->d_inode) == MEM_MAJOR &&
++		    iminor(file->f_path.dentry->d_inode) == 5) {
+ 			flags |= MAP_ANONYMOUS;
+ 			fput(file);
+ 			file = NULL;
+@@ -655,7 +655,7 @@ sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr)
+ 	if (!file)
+ 		goto out;
+ 
+-	inode = file->f_dentry->d_inode;
++	inode = file->f_path.dentry->d_inode;
+ 
+ 	socket = SOCKET_I(inode);
+ 	local.sin_family = AF_INET;

commit 7bc563239e4c276afebd11d2e6e67ddc0cc65f0d
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:40 2006 -0800
+
+    [PATCH] struct path: convert sound
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/sound/core/info.c b/sound/core/info.c
+index 0b4aab3225e5..54591e2eb6ee 100644
+--- a/sound/core/info.c
++++ b/sound/core/info.c
+@@ -488,7 +488,7 @@ static long snd_info_entry_ioctl(struct file *file, unsigned int cmd,
+ 
+ static int snd_info_entry_mmap(struct file *file, struct vm_area_struct *vma)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	struct snd_info_private_data *data;
+ 	struct snd_info_entry *entry;
+ 
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 6ea67b16c676..b52e89393fa3 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -1604,7 +1604,7 @@ static struct file *snd_pcm_file_fd(int fd)
+ 	file = fget(fd);
+ 	if (!file)
+ 		return NULL;
+-	inode = file->f_dentry->d_inode;
++	inode = file->f_path.dentry->d_inode;
+ 	if (!S_ISCHR(inode->i_mode) ||
+ 	    imajor(inode) != snd_major) {
+ 		fput(file);
+diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c
+index 87bd3100aef3..80b836e80d99 100644
+--- a/sound/oss/dmasound/dmasound_core.c
++++ b/sound/oss/dmasound/dmasound_core.c
+@@ -1051,7 +1051,7 @@ static int sq_release(struct inode *inode, struct file *file)
+ 
+ 	if (file->f_mode & FMODE_WRITE) {
+ 		if (write_sq.busy)
+-			rc = sq_fsync(file, file->f_dentry);
++			rc = sq_fsync(file, file->f_path.dentry);
+ 
+ 		sq_reset_output() ; /* make sure dma is stopped and all is quiet */
+ 		write_sq_release_buffers();
+@@ -1217,7 +1217,7 @@ static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd,
+ 		if ((file->f_mode & FMODE_READ) && dmasound.mach.record)
+ 			sq_reset_input() ;
+ 		if (file->f_mode & FMODE_WRITE) {
+-			result = sq_fsync(file, file->f_dentry);
++			result = sq_fsync(file, file->f_path.dentry);
+ 			sq_reset_output() ;
+ 		}
+ 		/* if we are the shared resource owner then release them */
+diff --git a/sound/oss/msnd_pinnacle.c b/sound/oss/msnd_pinnacle.c
+index d5146790f5e3..24110d63b136 100644
+--- a/sound/oss/msnd_pinnacle.c
++++ b/sound/oss/msnd_pinnacle.c
+@@ -1007,7 +1007,7 @@ static int dsp_write(const char __user *buf, size_t len)
+ 
+ static ssize_t dev_read(struct file *file, char __user *buf, size_t count, loff_t *off)
+ {
+-	int minor = iminor(file->f_dentry->d_inode);
++	int minor = iminor(file->f_path.dentry->d_inode);
+ 	if (minor == dev.dsp_minor)
+ 		return dsp_read(buf, count);
+ 	else
+@@ -1016,7 +1016,7 @@ static ssize_t dev_read(struct file *file, char __user *buf, size_t count, loff_
+ 
+ static ssize_t dev_write(struct file *file, const char __user *buf, size_t count, loff_t *off)
+ {
+-	int minor = iminor(file->f_dentry->d_inode);
++	int minor = iminor(file->f_path.dentry->d_inode);
+ 	if (minor == dev.dsp_minor)
+ 		return dsp_write(buf, count);
+ 	else
+diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c
+index 8fb8e7f99556..a89108cb74ea 100644
+--- a/sound/oss/soundcard.c
++++ b/sound/oss/soundcard.c
+@@ -141,7 +141,7 @@ static int get_mixer_levels(void __user * arg)
+ 
+ static ssize_t sound_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+ {
+-	int dev = iminor(file->f_dentry->d_inode);
++	int dev = iminor(file->f_path.dentry->d_inode);
+ 	int ret = -EINVAL;
+ 
+ 	/*
+@@ -174,7 +174,7 @@ static ssize_t sound_read(struct file *file, char __user *buf, size_t count, lof
+ 
+ static ssize_t sound_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+ {
+-	int dev = iminor(file->f_dentry->d_inode);
++	int dev = iminor(file->f_path.dentry->d_inode);
+ 	int ret = -EINVAL;
+ 	
+ 	lock_kernel();
+@@ -393,7 +393,7 @@ static int sound_ioctl(struct inode *inode, struct file *file,
+ 
+ static unsigned int sound_poll(struct file *file, poll_table * wait)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	int dev = iminor(inode);
+ 
+ 	DEB(printk("sound_poll(dev=%d)\n", dev));
+@@ -418,7 +418,7 @@ static int sound_mmap(struct file *file, struct vm_area_struct *vma)
+ 	int dev_class;
+ 	unsigned long size;
+ 	struct dma_buffparms *dmap = NULL;
+-	int dev = iminor(file->f_dentry->d_inode);
++	int dev = iminor(file->f_path.dentry->d_inode);
+ 
+ 	dev_class = dev & 0x0f;
+ 	dev >>= 4;
+diff --git a/sound/sound_firmware.c b/sound/sound_firmware.c
+index 3a181d4c0dc6..3304344713ae 100644
+--- a/sound/sound_firmware.c
++++ b/sound/sound_firmware.c
+@@ -19,7 +19,7 @@ static int do_mod_firmware_load(const char *fn, char **fp)
+ 		printk(KERN_INFO "Unable to load '%s'.\n", fn);
+ 		return 0;
+ 	}
+-	l = filp->f_dentry->d_inode->i_size;
++	l = filp->f_path.dentry->d_inode->i_size;
+ 	if (l <= 0 || l > 131072)
+ 	{
+ 		printk(KERN_INFO "Invalid firmware '%s'\n", fn);

commit 17b75e69493f655a09908045eddbb48718aef5de
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:39 2006 -0800
+
+    [PATCH] struct path: convert smbfs
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/smbfs/cache.c b/fs/smbfs/cache.c
+index 74b86d9725a6..8182f0542a21 100644
+--- a/fs/smbfs/cache.c
++++ b/fs/smbfs/cache.c
+@@ -125,7 +125,7 @@ smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
+ 	       struct smb_cache_control *ctrl, struct qstr *qname,
+ 	       struct smb_fattr *entry)
+ {
+-	struct dentry *newdent, *dentry = filp->f_dentry;
++	struct dentry *newdent, *dentry = filp->f_path.dentry;
+ 	struct inode *newino, *inode = dentry->d_inode;
+ 	struct smb_cache_control ctl = *ctrl;
+ 	int valid = 0;
+diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c
+index 70d9c5a37f5a..b1e58d1ac9ca 100644
+--- a/fs/smbfs/dir.c
++++ b/fs/smbfs/dir.c
+@@ -78,7 +78,7 @@ struct inode_operations smb_dir_inode_operations_unix =
+ static int 
+ smb_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ {
+-	struct dentry *dentry = filp->f_dentry;
++	struct dentry *dentry = filp->f_path.dentry;
+ 	struct inode *dir = dentry->d_inode;
+ 	struct smb_sb_info *server = server_from_dentry(dentry);
+ 	union  smb_dir_cache *cache = NULL;
+@@ -238,12 +238,12 @@ smb_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ static int
+ smb_dir_open(struct inode *dir, struct file *file)
+ {
+-	struct dentry *dentry = file->f_dentry;
++	struct dentry *dentry = file->f_path.dentry;
+ 	struct smb_sb_info *server;
+ 	int error = 0;
+ 
+ 	VERBOSE("(%s/%s)\n", dentry->d_parent->d_name.name,
+-		file->f_dentry->d_name.name);
++		file->f_path.dentry->d_name.name);
+ 
+ 	/*
+ 	 * Directory timestamps in the core protocol aren't updated
+diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
+index 50784d13c87b..e50533a79517 100644
+--- a/fs/smbfs/file.c
++++ b/fs/smbfs/file.c
+@@ -102,7 +102,7 @@ static int
+ smb_readpage(struct file *file, struct page *page)
+ {
+ 	int		error;
+-	struct dentry  *dentry = file->f_dentry;
++	struct dentry  *dentry = file->f_path.dentry;
+ 
+ 	page_cache_get(page);
+ 	error = smb_readpage_sync(dentry, page);
+@@ -205,7 +205,7 @@ static int
+ smb_updatepage(struct file *file, struct page *page, unsigned long offset,
+ 	       unsigned int count)
+ {
+-	struct dentry *dentry = file->f_dentry;
++	struct dentry *dentry = file->f_path.dentry;
+ 
+ 	DEBUG1("(%s/%s %d@%lld)\n", DENTRY_PATH(dentry), count,
+ 		((unsigned long long)page->index << PAGE_CACHE_SHIFT) + offset);
+@@ -218,7 +218,7 @@ smb_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
+ 			unsigned long nr_segs, loff_t pos)
+ {
+ 	struct file * file = iocb->ki_filp;
+-	struct dentry * dentry = file->f_dentry;
++	struct dentry * dentry = file->f_path.dentry;
+ 	ssize_t	status;
+ 
+ 	VERBOSE("file %s/%s, count=%lu@%lu\n", DENTRY_PATH(dentry),
+@@ -243,7 +243,7 @@ smb_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
+ static int
+ smb_file_mmap(struct file * file, struct vm_area_struct * vma)
+ {
+-	struct dentry * dentry = file->f_dentry;
++	struct dentry * dentry = file->f_path.dentry;
+ 	int	status;
+ 
+ 	VERBOSE("file %s/%s, address %lu - %lu\n",
+@@ -264,7 +264,7 @@ static ssize_t
+ smb_file_sendfile(struct file *file, loff_t *ppos,
+ 		  size_t count, read_actor_t actor, void *target)
+ {
+-	struct dentry *dentry = file->f_dentry;
++	struct dentry *dentry = file->f_path.dentry;
+ 	ssize_t status;
+ 
+ 	VERBOSE("file %s/%s, pos=%Ld, count=%d\n",
+@@ -323,7 +323,7 @@ smb_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
+ 			       unsigned long nr_segs, loff_t pos)
+ {
+ 	struct file * file = iocb->ki_filp;
+-	struct dentry * dentry = file->f_dentry;
++	struct dentry * dentry = file->f_path.dentry;
+ 	ssize_t	result;
+ 
+ 	VERBOSE("file %s/%s, count=%lu@%lu\n",
+@@ -355,7 +355,7 @@ static int
+ smb_file_open(struct inode *inode, struct file * file)
+ {
+ 	int result;
+-	struct dentry *dentry = file->f_dentry;
++	struct dentry *dentry = file->f_path.dentry;
+ 	int smb_mode = (file->f_mode & O_ACCMODE) - 1;
+ 
+ 	lock_kernel();
+diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c
+index 40e174db9872..a5ced9e0c6c4 100644
+--- a/fs/smbfs/proc.c
++++ b/fs/smbfs/proc.c
+@@ -873,7 +873,7 @@ smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt)
+ 	filp = fget(opt->fd);
+ 	if (!filp)
+ 		goto out;
+-	if (!smb_valid_socket(filp->f_dentry->d_inode))
++	if (!smb_valid_socket(filp->f_path.dentry->d_inode))
+ 		goto out_putf;
+ 
+ 	server->sock_file = filp;
+@@ -898,7 +898,7 @@ smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt)
+ 	/*
+ 	 * Store the server in sock user_data (Only used by sunrpc)
+ 	 */
+-	sk = SOCKET_I(filp->f_dentry->d_inode)->sk;
++	sk = SOCKET_I(filp->f_path.dentry->d_inode)->sk;
+ 	sk->sk_user_data = server;
+ 
+ 	/* chain into the data_ready callback */
+@@ -1939,7 +1939,7 @@ static int
+ smb_proc_readdir_short(struct file *filp, void *dirent, filldir_t filldir,
+ 		       struct smb_cache_control *ctl)
+ {
+-	struct dentry *dir = filp->f_dentry;
++	struct dentry *dir = filp->f_path.dentry;
+ 	struct smb_sb_info *server = server_from_dentry(dir);
+ 	struct qstr qname;
+ 	struct smb_fattr fattr;
+@@ -2291,7 +2291,7 @@ static int
+ smb_proc_readdir_long(struct file *filp, void *dirent, filldir_t filldir,
+ 		      struct smb_cache_control *ctl)
+ {
+-	struct dentry *dir = filp->f_dentry;
++	struct dentry *dir = filp->f_path.dentry;
+ 	struct smb_sb_info *server = server_from_dentry(dir);
+ 	struct qstr qname;
+ 	struct smb_fattr fattr;
+@@ -2859,7 +2859,7 @@ static int
+ smb_proc_readdir_null(struct file *filp, void *dirent, filldir_t filldir,
+ 		      struct smb_cache_control *ctl)
+ {
+-	struct smb_sb_info *server = server_from_dentry(filp->f_dentry);
++	struct smb_sb_info *server = server_from_dentry(filp->f_path.dentry);
+ 
+ 	if (smb_proc_ops_wait(server) < 0)
+ 		return -EIO;
+diff --git a/fs/smbfs/sock.c b/fs/smbfs/sock.c
+index 6815b1b12b68..92ea6b2367d7 100644
+--- a/fs/smbfs/sock.c
++++ b/fs/smbfs/sock.c
+@@ -82,10 +82,10 @@ server_sock(struct smb_sb_info *server)
+ 	if (server && (file = server->sock_file))
+ 	{
+ #ifdef SMBFS_PARANOIA
+-		if (!smb_valid_socket(file->f_dentry->d_inode))
++		if (!smb_valid_socket(file->f_path.dentry->d_inode))
+ 			PARANOIA("bad socket!\n");
+ #endif
+-		return SOCKET_I(file->f_dentry->d_inode);
++		return SOCKET_I(file->f_path.dentry->d_inode);
+ 	}
+ 	return NULL;
+ }

commit c943c4b49c75f3cae89e5d993ce1ae859395caa2
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:38 2006 -0800
+
+    [PATCH] struct path: convert sh
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/sh/oprofile/op_model_sh7750.c b/arch/sh/oprofile/op_model_sh7750.c
+index c265185b22a7..60402eec4b4d 100644
+--- a/arch/sh/oprofile/op_model_sh7750.c
++++ b/arch/sh/oprofile/op_model_sh7750.c
+@@ -142,7 +142,7 @@ static u64 sh7750_read_counter(int counter)
+  */
+ static inline int to_counter(struct file *file)
+ {
+-	const unsigned char *name = file->f_dentry->d_parent->d_name.name;
++	const unsigned char *name = file->f_path.dentry->d_parent->d_name.name;
+ 
+ 	return (int)simple_strtol(name, NULL, 10);
+ }

commit 3d5ff529ea222461a5fa3c4df05cbdc5eb56864d
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:38 2006 -0800
+
+    [PATCH] struct path: convert selinux
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
+index f5df8c70a9b5..3753416eb9b9 100644
+--- a/security/selinux/hooks.c
++++ b/security/selinux/hooks.c
+@@ -1120,8 +1120,8 @@ static int file_has_perm(struct task_struct *tsk,
+ {
+ 	struct task_security_struct *tsec = tsk->security;
+ 	struct file_security_struct *fsec = file->f_security;
+-	struct vfsmount *mnt = file->f_vfsmnt;
+-	struct dentry *dentry = file->f_dentry;
++	struct vfsmount *mnt = file->f_path.mnt;
++	struct dentry *dentry = file->f_path.dentry;
+ 	struct inode *inode = dentry->d_inode;
+ 	struct avc_audit_data ad;
+ 	int rc;
+@@ -1581,7 +1581,7 @@ static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
+ static int selinux_bprm_set_security(struct linux_binprm *bprm)
+ {
+ 	struct task_security_struct *tsec;
+-	struct inode *inode = bprm->file->f_dentry->d_inode;
++	struct inode *inode = bprm->file->f_path.dentry->d_inode;
+ 	struct inode_security_struct *isec;
+ 	struct bprm_security_struct *bsec;
+ 	u32 newsid;
+@@ -1621,10 +1621,10 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm)
+ 	}
+ 
+ 	AVC_AUDIT_DATA_INIT(&ad, FS);
+-	ad.u.fs.mnt = bprm->file->f_vfsmnt;
+-	ad.u.fs.dentry = bprm->file->f_dentry;
++	ad.u.fs.mnt = bprm->file->f_path.mnt;
++	ad.u.fs.dentry = bprm->file->f_path.dentry;
+ 
+-	if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID)
++	if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
+ 		newsid = tsec->sid;
+ 
+         if (tsec->sid == newsid) {
+@@ -1708,7 +1708,7 @@ static inline void flush_unauthorized_files(struct files_struct * files)
+ 			   than using file_has_perm, as this particular open
+ 			   file may belong to another process and we are only
+ 			   interested in the inode-based check here. */
+-			struct inode *inode = file->f_dentry->d_inode;
++			struct inode *inode = file->f_path.dentry->d_inode;
+ 			if (inode_has_perm(current, inode,
+ 					   FILE__READ | FILE__WRITE, NULL)) {
+ 				drop_tty = 1;
+@@ -2420,7 +2420,7 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t
+ static int selinux_file_permission(struct file *file, int mask)
+ {
+ 	int rc;
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 
+ 	if (!mask) {
+ 		/* No permission to check.  Existence test. */
+@@ -2597,7 +2597,7 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
+ 
+ 	switch (cmd) {
+ 	        case F_SETFL:
+-			if (!file->f_dentry || !file->f_dentry->d_inode) {
++			if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
+ 				err = -EINVAL;
+ 				break;
+ 			}
+@@ -2623,7 +2623,7 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
+ 		case F_SETLK64:
+ 	        case F_SETLKW64:
+ #endif
+-			if (!file->f_dentry || !file->f_dentry->d_inode) {
++			if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
+ 				err = -EINVAL;
+ 				break;
+ 			}
+diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
+index cd244419c980..c8bf6e172f6e 100644
+--- a/security/selinux/selinuxfs.c
++++ b/security/selinux/selinuxfs.c
+@@ -448,7 +448,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
+ 
+ static ssize_t selinux_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
+ {
+-	ino_t ino =  file->f_dentry->d_inode->i_ino;
++	ino_t ino =  file->f_path.dentry->d_inode->i_ino;
+ 	char *data;
+ 	ssize_t rv;
+ 
+@@ -805,7 +805,7 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,
+ 		goto out;
+ 	}
+ 
+-	inode = filep->f_dentry->d_inode;
++	inode = filep->f_path.dentry->d_inode;
+ 	cur_enforcing = security_get_bool_value(inode->i_ino - BOOL_INO_OFFSET);
+ 	if (cur_enforcing < 0) {
+ 		ret = cur_enforcing;
+@@ -864,7 +864,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
+ 	if (new_value)
+ 		new_value = 1;
+ 
+-	inode = filep->f_dentry->d_inode;
++	inode = filep->f_path.dentry->d_inode;
+ 	bool_pending_values[inode->i_ino - BOOL_INO_OFFSET] = new_value;
+ 	length = count;
+ 
+@@ -965,7 +965,7 @@ static void sel_remove_bools(struct dentry *de)
+ 	file_list_lock();
+ 	list_for_each(p, &sb->s_files) {
+ 		struct file * filp = list_entry(p, struct file, f_u.fu_list);
+-		struct dentry * dentry = filp->f_dentry;
++		struct dentry * dentry = filp->f_path.dentry;
+ 
+ 		if (dentry->d_parent != de) {
+ 			continue;

commit 7ac6207b2a6a5b828bc333f2530a3bd48197af3e
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:37 2006 -0800
+
+    [PATCH] struct path: convert scsi
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+index f6a452846fab..978bfc1e0c6a 100644
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -863,7 +863,7 @@ static void sd_rescan(struct device *dev)
+  */
+ static long sd_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ {
+-	struct block_device *bdev = file->f_dentry->d_inode->i_bdev;
++	struct block_device *bdev = file->f_path.dentry->d_inode->i_bdev;
+ 	struct gendisk *disk = bdev->bd_disk;
+ 	struct scsi_device *sdev = scsi_disk(disk)->device;
+ 
+diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
+index 587274dd7059..e016e0906e1a 100644
+--- a/drivers/scsi/st.c
++++ b/drivers/scsi/st.c
+@@ -922,7 +922,7 @@ static int check_tape(struct scsi_tape *STp, struct file *filp)
+ 	struct st_modedef *STm;
+ 	struct st_partstat *STps;
+ 	char *name = tape_name(STp);
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	int mode = TAPE_MODE(inode);
+ 
+ 	STp->ready = ST_READY;

commit 7fa95f726aba6033d7baffcfda484c31b8cfe153
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:36 2006 -0800
+
+    [PATCH] struct path: convert sbus
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c
+index 385f4f768311..ac7d1258efee 100644
+--- a/drivers/sbus/char/bpp.c
++++ b/drivers/sbus/char/bpp.c
+@@ -621,7 +621,7 @@ static long read_ecp(unsigned minor, char __user *c, unsigned long cnt)
+ static ssize_t bpp_read(struct file *f, char __user *c, size_t cnt, loff_t * ppos)
+ {
+       long rc;
+-      unsigned minor = iminor(f->f_dentry->d_inode);
++      unsigned minor = iminor(f->f_path.dentry->d_inode);
+       if (minor >= BPP_NO) return -ENODEV;
+       if (!instances[minor].present) return -ENODEV;
+ 
+@@ -774,7 +774,7 @@ static long write_ecp(unsigned minor, const char __user *c, unsigned long cnt)
+ static ssize_t bpp_write(struct file *f, const char __user *c, size_t cnt, loff_t * ppos)
+ {
+       long errno = 0;
+-      unsigned minor = iminor(f->f_dentry->d_inode);
++      unsigned minor = iminor(f->f_path.dentry->d_inode);
+       if (minor >= BPP_NO) return -ENODEV;
+       if (!instances[minor].present) return -ENODEV;
+ 
+diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c
+index f5803ecb1999..ad1c7db96cb4 100644
+--- a/drivers/sbus/char/cpwatchdog.c
++++ b/drivers/sbus/char/cpwatchdog.c
+@@ -404,7 +404,7 @@ static long wd_compat_ioctl(struct file *file, unsigned int cmd,
+ 	case WIOCSTOP:
+ 	case WIOCGSTAT:
+ 		lock_kernel();
+-		rval = wd_ioctl(file->f_dentry->d_inode, file, cmd, arg);
++		rval = wd_ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
+ 		unlock_kernel();
+ 		break;
+ 	/* everything else is handled by the generic compat layer */
+diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
+index d92bc8827a9e..a4909e0c7f83 100644
+--- a/drivers/sbus/char/display7seg.c
++++ b/drivers/sbus/char/display7seg.c
+@@ -121,7 +121,7 @@ static long d7s_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ 	__u8 ireg = 0;
+ 	int error = 0;
+ 
+-	if (D7S_MINOR != iminor(file->f_dentry->d_inode))
++	if (D7S_MINOR != iminor(file->f_path.dentry->d_inode))
+ 		return -ENODEV;
+ 
+ 	lock_kernel();
+diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c
+index 81ba2d71cee2..4e2a0e2dcc2e 100644
+--- a/drivers/sbus/char/openprom.c
++++ b/drivers/sbus/char/openprom.c
+@@ -676,7 +676,7 @@ static long openprom_compat_ioctl(struct file *file, unsigned int cmd,
+ 	case OPROMSETCUR:
+ 	case OPROMPCI2NODE:
+ 	case OPROMPATH2NODE:
+-		rval = openprom_ioctl(file->f_dentry->d_inode, file, cmd, arg);
++		rval = openprom_ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
+ 		break;
+ 	}
+ 
+diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c
+index 55b2b31bd7ab..2722af5d3404 100644
+--- a/drivers/sbus/char/vfc_dev.c
++++ b/drivers/sbus/char/vfc_dev.c
+@@ -610,7 +610,7 @@ static int vfc_mmap(struct file *file, struct vm_area_struct *vma)
+ 	unsigned int map_size, ret, map_offset;
+ 	struct vfc_dev *dev;
+ 	
+-	dev = vfc_get_dev_ptr(iminor(file->f_dentry->d_inode));
++	dev = vfc_get_dev_ptr(iminor(file->f_path.dentry->d_inode));
+ 	if(dev == NULL)
+ 		return -ENODEV;
+ 

commit d20343e7406a114a561030e683fafc4fdbc9c6bd
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:35 2006 -0800
+
+    [PATCH] struct path: convert s390
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
+index cd702ae45d6d..b6716c4b9934 100644
+--- a/arch/s390/hypfs/inode.c
++++ b/arch/s390/hypfs/inode.c
+@@ -109,7 +109,7 @@ static void hypfs_drop_inode(struct inode *inode)
+ 
+ static int hypfs_open(struct inode *inode, struct file *filp)
+ {
+-	char *data = filp->f_dentry->d_inode->i_private;
++	char *data = filp->f_path.dentry->d_inode->i_private;
+ 	struct hypfs_sb_info *fs_info;
+ 
+ 	if (filp->f_mode & FMODE_WRITE) {
+@@ -174,7 +174,7 @@ static ssize_t hypfs_aio_write(struct kiocb *iocb, const struct iovec *iov,
+ 	struct hypfs_sb_info *fs_info;
+ 	size_t count = iov_length(iov, nr_segs);
+ 
+-	sb = iocb->ki_filp->f_dentry->d_inode->i_sb;
++	sb = iocb->ki_filp->f_path.dentry->d_inode->i_sb;
+ 	fs_info = sb->s_fs_info;
+ 	/*
+ 	 * Currently we only allow one update per second for two reasons:
+diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
+index 43f3d0c7e132..ef5266fbce62 100644
+--- a/arch/s390/kernel/debug.c
++++ b/arch/s390/kernel/debug.c
+@@ -603,13 +603,13 @@ debug_open(struct inode *inode, struct file *file)
+ 	debug_info_t *debug_info, *debug_info_snapshot;
+ 
+ 	down(&debug_lock);
+-	debug_info = file->f_dentry->d_inode->i_private;
++	debug_info = file->f_path.dentry->d_inode->i_private;
+ 	/* find debug view */
+ 	for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
+ 		if (!debug_info->views[i])
+ 			continue;
+ 		else if (debug_info->debugfs_entries[i] ==
+-			 file->f_dentry) {
++			 file->f_path.dentry) {
+ 			goto found;	/* found view ! */
+ 		}
+ 	}

commit 49522c97ac1c19188ff63598cdd0c980ba7f1239
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:34 2006 -0800
+
+    [PATCH] struct path: convert s390-drivers
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
+index 8fed3603e9ea..758cfb542865 100644
+--- a/drivers/s390/block/dasd_ioctl.c
++++ b/drivers/s390/block/dasd_ioctl.c
+@@ -430,7 +430,7 @@ dasd_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 	int rval;
+ 
+ 	lock_kernel();
+-	rval = dasd_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
++	rval = dasd_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
+ 	unlock_kernel();
+ 
+ 	return (rval == -EINVAL) ? -ENOIOCTLCMD : rval;
+diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
+index ef205ddd31a4..0893d306ae80 100644
+--- a/drivers/s390/char/fs3270.c
++++ b/drivers/s390/char/fs3270.c
+@@ -419,9 +419,9 @@ fs3270_open(struct inode *inode, struct file *filp)
+ 	struct idal_buffer *ib;
+ 	int minor, rc;
+ 
+-	if (imajor(filp->f_dentry->d_inode) != IBM_FS3270_MAJOR)
++	if (imajor(filp->f_path.dentry->d_inode) != IBM_FS3270_MAJOR)
+ 		return -ENODEV;
+-	minor = iminor(filp->f_dentry->d_inode);
++	minor = iminor(filp->f_path.dentry->d_inode);
+ 	/* Check for minor 0 multiplexer. */
+ 	if (minor == 0) {
+ 		struct tty_struct *tty;
+diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
+index 97f75237bed6..31198c8f2718 100644
+--- a/drivers/s390/char/tape_char.c
++++ b/drivers/s390/char/tape_char.c
+@@ -298,13 +298,13 @@ tapechar_open (struct inode *inode, struct file *filp)
+ 	int minor, rc;
+ 
+ 	DBF_EVENT(6, "TCHAR:open: %i:%i\n",
+-		imajor(filp->f_dentry->d_inode),
+-		iminor(filp->f_dentry->d_inode));
++		imajor(filp->f_path.dentry->d_inode),
++		iminor(filp->f_path.dentry->d_inode));
+ 
+-	if (imajor(filp->f_dentry->d_inode) != tapechar_major)
++	if (imajor(filp->f_path.dentry->d_inode) != tapechar_major)
+ 		return -ENODEV;
+ 
+-	minor = iminor(filp->f_dentry->d_inode);
++	minor = iminor(filp->f_path.dentry->d_inode);
+ 	device = tape_get_device(minor / TAPE_MINORS_PER_DEV);
+ 	if (IS_ERR(device)) {
+ 		DBF_EVENT(3, "TCHAR:open: tape_get_device() failed\n");

commit 3027795e7b873da643e851d62d17f6bcc43d6e4a
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:34 2006 -0800
+
+    [PATCH] struct path: convert romfs
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c
+index c5af088d4a4c..d3e243a6f609 100644
+--- a/fs/romfs/inode.c
++++ b/fs/romfs/inode.c
+@@ -276,7 +276,7 @@ static unsigned char romfs_dtype_table[] = {
+ static int
+ romfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ {
+-	struct inode *i = filp->f_dentry->d_inode;
++	struct inode *i = filp->f_path.dentry->d_inode;
+ 	struct romfs_inode ri;
+ 	unsigned long offset, maxoff;
+ 	int j, ino, nextfh;

commit 1fc5adbd1916793c19d25347f484806c124d9be7
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:33 2006 -0800
+
+    [PATCH] struct path: convert reiserfs
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c
+index 657050ad7430..96a2f8889da3 100644
+--- a/fs/reiserfs/dir.c
++++ b/fs/reiserfs/dir.c
+@@ -45,7 +45,7 @@ static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry,
+ //
+ static int reiserfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ {
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct cpu_key pos_key;	/* key of current position in the directory (key of directory entry) */
+ 	INITIALIZE_PATH(path_to_entry);
+ 	struct buffer_head *bh;
+@@ -135,7 +135,7 @@ static int reiserfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ 				/* Ignore the .reiserfs_priv entry */
+ 				if (reiserfs_xattrs(inode->i_sb) &&
+ 				    !old_format_only(inode->i_sb) &&
+-				    filp->f_dentry == inode->i_sb->s_root &&
++				    filp->f_path.dentry == inode->i_sb->s_root &&
+ 				    REISERFS_SB(inode->i_sb)->priv_root &&
+ 				    REISERFS_SB(inode->i_sb)->priv_root->d_inode
+ 				    && deh_objectid(deh) ==
+diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
+index 373d862c3f87..99b6f329ba23 100644
+--- a/fs/reiserfs/file.c
++++ b/fs/reiserfs/file.c
+@@ -1288,7 +1288,7 @@ static ssize_t reiserfs_file_write(struct file *file,	/* the file we are going t
+ 	loff_t pos;		// Current position in the file.
+ 	ssize_t res;		// return value of various functions that we call.
+ 	int err = 0;
+-	struct inode *inode = file->f_dentry->d_inode;	// Inode of the file that we are writing to.
++	struct inode *inode = file->f_path.dentry->d_inode;	// Inode of the file that we are writing to.
+ 	/* To simplify coding at this time, we store
+ 	   locked pages in array for now */
+ 	struct page *prepared_pages[REISERFS_WRITE_PAGES_AT_A_TIME];
+@@ -1335,7 +1335,7 @@ static ssize_t reiserfs_file_write(struct file *file,	/* the file we are going t
+ 	if (count == 0)
+ 		goto out;
+ 
+-	res = remove_suid(file->f_dentry);
++	res = remove_suid(file->f_path.dentry);
+ 	if (res)
+ 		goto out;
+ 
+diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
+index 9c57578cb831..b484d2913c0d 100644
+--- a/fs/reiserfs/ioctl.c
++++ b/fs/reiserfs/ioctl.c
+@@ -99,7 +99,7 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+ long reiserfs_compat_ioctl(struct file *file, unsigned int cmd,
+ 				unsigned long arg)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	int ret;
+ 
+ 	/* These are just misnamed, they actually get/put from/to user an int */
+diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c
+index c533ec1bcaec..ecc9943202fc 100644
+--- a/fs/reiserfs/procfs.c
++++ b/fs/reiserfs/procfs.c
+@@ -295,7 +295,7 @@ static int show_oidmap(struct seq_file *m, struct super_block *sb)
+ 	}
+ #if defined( REISERFS_USE_OIDMAPF )
+ 	if (sb_info->oidmap.use_file && (sb_info->oidmap.mapf != NULL)) {
+-		loff_t size = sb_info->oidmap.mapf->f_dentry->d_inode->i_size;
++		loff_t size = sb_info->oidmap.mapf->f_path.dentry->d_inode->i_size;
+ 		total_used += size / sizeof(reiserfs_oidinterval_d_t);
+ 	}
+ #endif
+diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
+index 1e4d68590178..f01389fd162e 100644
+--- a/fs/reiserfs/xattr.c
++++ b/fs/reiserfs/xattr.c
+@@ -274,7 +274,7 @@ static struct file *open_xa_file(const struct inode *inode, const char *name,
+  */
+ static int __xattr_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ {
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct cpu_key pos_key;	/* key of current position in the directory (key of directory entry) */
+ 	INITIALIZE_PATH(path_to_entry);
+ 	struct buffer_head *bh;
+@@ -420,7 +420,7 @@ static int __xattr_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ static
+ int xattr_readdir(struct file *file, filldir_t filler, void *buf)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	int res = -ENOTDIR;
+ 	if (!file->f_op || !file->f_op->readdir)
+ 		goto out;
+@@ -508,7 +508,7 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer,
+ 		goto out;
+ 	}
+ 
+-	xinode = fp->f_dentry->d_inode;
++	xinode = fp->f_path.dentry->d_inode;
+ 	REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
+ 
+ 	/* we need to copy it off.. */
+@@ -527,7 +527,7 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer,
+ 	newattrs.ia_size = buffer_size;
+ 	newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
+ 	mutex_lock(&xinode->i_mutex);
+-	err = notify_change(fp->f_dentry, &newattrs);
++	err = notify_change(fp->f_path.dentry, &newattrs);
+ 	if (err)
+ 		goto out_filp;
+ 
+@@ -626,7 +626,7 @@ reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer,
+ 		goto out;
+ 	}
+ 
+-	xinode = fp->f_dentry->d_inode;
++	xinode = fp->f_path.dentry->d_inode;
+ 	isize = xinode->i_size;
+ 	REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
+ 

commit a57c4d65f70cb43c8503bc213c8be638011c22e7
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:32 2006 -0800
+
+    [PATCH] struct path: convert ramfs
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
+index bfe5dbf1002e..61cbe1ef06b9 100644
+--- a/fs/ramfs/file-nommu.c
++++ b/fs/ramfs/file-nommu.c
+@@ -232,7 +232,7 @@ unsigned long ramfs_nommu_get_unmapped_area(struct file *file,
+ 					    unsigned long pgoff, unsigned long flags)
+ {
+ 	unsigned long maxpages, lpages, nr, loop, ret;
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	struct page **pages = NULL, **ptr, *page;
+ 	loff_t isize;
+ 

commit 24e23c24e7a4754e50439dfc33bdbd05b09c4cc5
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:32 2006 -0800
+
+    [PATCH] struct path: convert qnx4
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c
+index 0d7103fa0df5..c94db1db7a71 100644
+--- a/fs/qnx4/dir.c
++++ b/fs/qnx4/dir.c
+@@ -22,7 +22,7 @@
+ 
+ static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ {
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	unsigned int offset;
+ 	struct buffer_head *bh;
+ 	struct qnx4_inode_entry *de;

commit c2c8bbadbf6532e48025c9065231244f0c477c29
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:31 2006 -0800
+
+    [PATCH] struct path: convert ppc
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/ppc/8xx_io/cs4218_tdm.c b/arch/ppc/8xx_io/cs4218_tdm.c
+index 959d31c26cbb..c71ef3c2e7bf 100644
+--- a/arch/ppc/8xx_io/cs4218_tdm.c
++++ b/arch/ppc/8xx_io/cs4218_tdm.c
+@@ -2165,7 +2165,7 @@ static int sq_release(struct inode *inode, struct file *file)
+ 	int rc = 0;
+ 
+ 	if (sq.busy)
+-		rc = sq_fsync(file, file->f_dentry);
++		rc = sq_fsync(file, file->f_path.dentry);
+ 	sound.soft = sound.dsp;
+ 	sound.hard = sound.dsp;
+ 	sound_silence();
+@@ -2218,25 +2218,25 @@ static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd,
+ 		return 0;
+ 	case SNDCTL_DSP_POST:
+ 	case SNDCTL_DSP_SYNC:
+-		return sq_fsync(file, file->f_dentry);
++		return sq_fsync(file, file->f_path.dentry);
+ 
+ 		/* ++TeSche: before changing any of these it's
+ 		 * probably wise to wait until sound playing has
+ 		 * settled down. */
+ 	case SNDCTL_DSP_SPEED:
+-		sq_fsync(file, file->f_dentry);
++		sq_fsync(file, file->f_path.dentry);
+ 		IOCTL_IN(arg, data);
+ 		return IOCTL_OUT(arg, sound_set_speed(data));
+ 	case SNDCTL_DSP_STEREO:
+-		sq_fsync(file, file->f_dentry);
++		sq_fsync(file, file->f_path.dentry);
+ 		IOCTL_IN(arg, data);
+ 		return IOCTL_OUT(arg, sound_set_stereo(data));
+ 	case SOUND_PCM_WRITE_CHANNELS:
+-		sq_fsync(file, file->f_dentry);
++		sq_fsync(file, file->f_path.dentry);
+ 		IOCTL_IN(arg, data);
+ 		return IOCTL_OUT(arg, sound_set_stereo(data-1)+1);
+ 	case SNDCTL_DSP_SETFMT:
+-		sq_fsync(file, file->f_dentry);
++		sq_fsync(file, file->f_path.dentry);
+ 		IOCTL_IN(arg, data);
+ 		return IOCTL_OUT(arg, sound_set_format(data));
+ 	case SNDCTL_DSP_GETFMTS:

commit b4d1ab58c016f4dffef4ff1eb392fa84e3c35024
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:30 2006 -0800
+
+    [PATCH] struct path: convert powerpc
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c
+index f598cb519539..dd7001cacf75 100644
+--- a/arch/powerpc/kernel/proc_ppc64.c
++++ b/arch/powerpc/kernel/proc_ppc64.c
+@@ -83,7 +83,7 @@ __initcall(proc_ppc64_init);
+ static loff_t page_map_seek( struct file *file, loff_t off, int whence)
+ {
+ 	loff_t new;
+-	struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
++	struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
+ 
+ 	switch(whence) {
+ 	case 0:
+@@ -106,13 +106,13 @@ static loff_t page_map_seek( struct file *file, loff_t off, int whence)
+ static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes,
+ 			      loff_t *ppos)
+ {
+-	struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
++	struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
+ 	return simple_read_from_buffer(buf, nbytes, ppos, dp->data, dp->size);
+ }
+ 
+ static int page_map_mmap( struct file *file, struct vm_area_struct *vma )
+ {
+-	struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
++	struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
+ 
+ 	if ((vma->vm_end - vma->vm_start) > dp->size)
+ 		return -EINVAL;
+diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
+index 7d0f13fecc0e..0c4fcd34bfe5 100644
+--- a/arch/powerpc/kernel/rtas_flash.c
++++ b/arch/powerpc/kernel/rtas_flash.c
+@@ -193,7 +193,7 @@ static void free_flash_list(struct flash_block_list *f)
+ 
+ static int rtas_flash_release(struct inode *inode, struct file *file)
+ {
+-	struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
++	struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
+ 	struct rtas_update_flash_t *uf;
+ 	
+ 	uf = (struct rtas_update_flash_t *) dp->data;
+@@ -255,7 +255,7 @@ static void get_flash_status_msg(int status, char *buf)
+ static ssize_t rtas_flash_read(struct file *file, char __user *buf,
+ 			       size_t count, loff_t *ppos)
+ {
+-	struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
++	struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
+ 	struct rtas_update_flash_t *uf;
+ 	char msg[RTAS_MSG_MAXLEN];
+ 	int msglen;
+@@ -299,7 +299,7 @@ void rtas_block_ctor(void *ptr, struct kmem_cache *cache, unsigned long flags)
+ static ssize_t rtas_flash_write(struct file *file, const char __user *buffer,
+ 				size_t count, loff_t *off)
+ {
+-	struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
++	struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
+ 	struct rtas_update_flash_t *uf;
+ 	char *p;
+ 	int next_free;
+@@ -391,7 +391,7 @@ static void manage_flash(struct rtas_manage_flash_t *args_buf)
+ static ssize_t manage_flash_read(struct file *file, char __user *buf,
+ 			       size_t count, loff_t *ppos)
+ {
+-	struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
++	struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
+ 	struct rtas_manage_flash_t *args_buf;
+ 	char msg[RTAS_MSG_MAXLEN];
+ 	int msglen;
+@@ -421,7 +421,7 @@ static ssize_t manage_flash_read(struct file *file, char __user *buf,
+ static ssize_t manage_flash_write(struct file *file, const char __user *buf,
+ 				size_t count, loff_t *off)
+ {
+-	struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
++	struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
+ 	struct rtas_manage_flash_t *args_buf;
+ 	const char reject_str[] = "0";
+ 	const char commit_str[] = "1";
+@@ -492,7 +492,7 @@ static int get_validate_flash_msg(struct rtas_validate_flash_t *args_buf,
+ static ssize_t validate_flash_read(struct file *file, char __user *buf,
+ 			       size_t count, loff_t *ppos)
+ {
+-	struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
++	struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
+ 	struct rtas_validate_flash_t *args_buf;
+ 	char msg[RTAS_MSG_MAXLEN];
+ 	int msglen;
+@@ -520,7 +520,7 @@ static ssize_t validate_flash_read(struct file *file, char __user *buf,
+ static ssize_t validate_flash_write(struct file *file, const char __user *buf,
+ 				    size_t count, loff_t *off)
+ {
+-	struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
++	struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
+ 	struct rtas_validate_flash_t *args_buf;
+ 	int rc;
+ 
+@@ -569,7 +569,7 @@ static ssize_t validate_flash_write(struct file *file, const char __user *buf,
+ 
+ static int validate_flash_release(struct inode *inode, struct file *file)
+ {
+-	struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
++	struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
+ 	struct rtas_validate_flash_t *args_buf;
+ 
+ 	args_buf = (struct rtas_validate_flash_t *) dp->data;
+diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
+index e3af9112c026..738b9244382f 100644
+--- a/arch/powerpc/platforms/cell/spufs/inode.c
++++ b/arch/powerpc/platforms/cell/spufs/inode.c
+@@ -205,7 +205,7 @@ static int spufs_dir_close(struct inode *inode, struct file *file)
+ 	struct dentry *dir;
+ 	int ret;
+ 
+-	dir = file->f_dentry;
++	dir = file->f_path.dentry;
+ 	parent = dir->d_parent->d_inode;
+ 	ctx = SPUFS_I(dir->d_inode)->i_ctx;
+ 
+@@ -363,7 +363,7 @@ static int spufs_gang_close(struct inode *inode, struct file *file)
+ 	struct dentry *dir;
+ 	int ret;
+ 
+-	dir = file->f_dentry;
++	dir = file->f_path.dentry;
+ 	parent = dir->d_parent->d_inode;
+ 
+ 	ret = spufs_rmgang(parent, dir);
+diff --git a/arch/powerpc/platforms/cell/spufs/syscalls.c b/arch/powerpc/platforms/cell/spufs/syscalls.c
+index a6d1ae4dc2a3..8e37bdf4dfda 100644
+--- a/arch/powerpc/platforms/cell/spufs/syscalls.c
++++ b/arch/powerpc/platforms/cell/spufs/syscalls.c
+@@ -46,7 +46,7 @@ static long do_spu_run(struct file *filp,
+ 	if (filp->f_op != &spufs_context_fops)
+ 		goto out;
+ 
+-	i = SPUFS_I(filp->f_dentry->d_inode);
++	i = SPUFS_I(filp->f_path.dentry->d_inode);
+ 	ret = spufs_run_spu(filp, i->i_ctx, &npc, &status);
+ 
+ 	if (put_user(npc, unpc))
+diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c
+index b5737d68d6c4..cff15ae24f6b 100644
+--- a/arch/powerpc/platforms/iseries/mf.c
++++ b/arch/powerpc/platforms/iseries/mf.c
+@@ -1178,7 +1178,7 @@ static ssize_t proc_mf_change_vmlinux(struct file *file,
+ 				      const char __user *buf,
+ 				      size_t count, loff_t *ppos)
+ {
+-	struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
++	struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
+ 	ssize_t rc;
+ 	dma_addr_t dma_addr;
+ 	char *page;
+diff --git a/arch/powerpc/platforms/pseries/hvCall_inst.c b/arch/powerpc/platforms/pseries/hvCall_inst.c
+index 446e17d162a5..80181c4c49eb 100644
+--- a/arch/powerpc/platforms/pseries/hvCall_inst.c
++++ b/arch/powerpc/platforms/pseries/hvCall_inst.c
+@@ -85,7 +85,7 @@ static int hcall_inst_seq_open(struct inode *inode, struct file *file)
+ 
+ 	rc = seq_open(file, &hcall_inst_seq_ops);
+ 	seq = file->private_data;
+-	seq->private = file->f_dentry->d_inode->i_private;
++	seq->private = file->f_path.dentry->d_inode->i_private;
+ 
+ 	return rc;
+ }
+diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c
+index 77a5bb1d9c30..45368a57d7dd 100644
+--- a/arch/powerpc/platforms/pseries/scanlog.c
++++ b/arch/powerpc/platforms/pseries/scanlog.c
+@@ -47,7 +47,7 @@ static struct proc_dir_entry *proc_ppc64_scan_log_dump;	/* The proc file */
+ static ssize_t scanlog_read(struct file *file, char __user *buf,
+ 			    size_t count, loff_t *ppos)
+ {
+-        struct inode * inode = file->f_dentry->d_inode;
++        struct inode * inode = file->f_path.dentry->d_inode;
+ 	struct proc_dir_entry *dp;
+ 	unsigned int *data;
+ 	int status;

commit 40fad04b224db982cce5f6226ebe3ceb6529b781
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:29 2006 -0800
+
+    [PATCH] struct path: convert pcmcia
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c
+index d077870c6731..327372b7a54e 100644
+--- a/drivers/pcmcia/pcmcia_ioctl.c
++++ b/drivers/pcmcia/pcmcia_ioctl.c
+@@ -486,7 +486,7 @@ static ssize_t ds_read(struct file *file, char __user *buf,
+     user_info_t *user;
+     int ret;
+ 
+-    ds_dbg(2, "ds_read(socket %d)\n", iminor(file->f_dentry->d_inode));
++    ds_dbg(2, "ds_read(socket %d)\n", iminor(file->f_path.dentry->d_inode));
+ 
+     if (count < 4)
+ 	return -EINVAL;
+@@ -511,7 +511,7 @@ static ssize_t ds_read(struct file *file, char __user *buf,
+ static ssize_t ds_write(struct file *file, const char __user *buf,
+ 			size_t count, loff_t *ppos)
+ {
+-    ds_dbg(2, "ds_write(socket %d)\n", iminor(file->f_dentry->d_inode));
++    ds_dbg(2, "ds_write(socket %d)\n", iminor(file->f_path.dentry->d_inode));
+ 
+     if (count != 4)
+ 	return -EINVAL;
+@@ -529,7 +529,7 @@ static u_int ds_poll(struct file *file, poll_table *wait)
+     struct pcmcia_socket *s;
+     user_info_t *user;
+ 
+-    ds_dbg(2, "ds_poll(socket %d)\n", iminor(file->f_dentry->d_inode));
++    ds_dbg(2, "ds_poll(socket %d)\n", iminor(file->f_path.dentry->d_inode));
+ 
+     user = file->private_data;
+     if (CHECK_USER(user))

commit 46cc65a767f458aec4d342b814a661a15dc31be1
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:28 2006 -0800
+
+    [PATCH] struct path: convert pci
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
+index 99cf33379769..4a6760a3b31f 100644
+--- a/drivers/pci/proc.c
++++ b/drivers/pci/proc.c
+@@ -23,7 +23,7 @@ static loff_t
+ proc_bus_pci_lseek(struct file *file, loff_t off, int whence)
+ {
+ 	loff_t new = -1;
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 
+ 	mutex_lock(&inode->i_mutex);
+ 	switch (whence) {
+@@ -48,7 +48,7 @@ proc_bus_pci_lseek(struct file *file, loff_t off, int whence)
+ static ssize_t
+ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+ {
+-	const struct inode *ino = file->f_dentry->d_inode;
++	const struct inode *ino = file->f_path.dentry->d_inode;
+ 	const struct proc_dir_entry *dp = PDE(ino);
+ 	struct pci_dev *dev = dp->data;
+ 	unsigned int pos = *ppos;
+@@ -130,7 +130,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
+ static ssize_t
+ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, loff_t *ppos)
+ {
+-	const struct inode *ino = file->f_dentry->d_inode;
++	const struct inode *ino = file->f_path.dentry->d_inode;
+ 	const struct proc_dir_entry *dp = PDE(ino);
+ 	struct pci_dev *dev = dp->data;
+ 	int pos = *ppos;
+@@ -245,7 +245,7 @@ static int proc_bus_pci_ioctl(struct inode *inode, struct file *file, unsigned i
+ #ifdef HAVE_PCI_MMAP
+ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	const struct proc_dir_entry *dp = PDE(inode);
+ 	struct pci_dev *dev = dp->data;
+ 	struct pci_filp_private *fpriv = file->private_data;

commit 0c5a5566892de5b240c89b9f72eb1c2e861206a0
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:28 2006 -0800
+
+    [PATCH] struct path: convert parisc
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c
+index 2e2dc4f2c853..d88309209f56 100644
+--- a/arch/parisc/hpux/sys_hpux.c
++++ b/arch/parisc/hpux/sys_hpux.c
+@@ -237,7 +237,7 @@ asmlinkage long hpux_fstatfs(unsigned int fd, struct hpux_statfs __user * buf)
+ 	file = fget(fd);
+ 	if (!file)
+ 		goto out;
+-	error = vfs_statfs_hpux(file->f_dentry, &tmp);
++	error = vfs_statfs_hpux(file->f_path.dentry, &tmp);
+ 	if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
+ 		error = -EFAULT;
+ 	fput(file);

commit 1fb1430b14db30b8f113ddb4db389d316386f20b
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:27 2006 -0800
+
+    [PATCH] struct path: convert oprofile
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
+index 43e521e99126..78c2e6e4b42e 100644
+--- a/drivers/oprofile/buffer_sync.c
++++ b/drivers/oprofile/buffer_sync.c
+@@ -220,8 +220,8 @@ static unsigned long get_exec_dcookie(struct mm_struct * mm)
+ 			continue;
+ 		if (!(vma->vm_flags & VM_EXECUTABLE))
+ 			continue;
+-		cookie = fast_get_dcookie(vma->vm_file->f_dentry,
+-			vma->vm_file->f_vfsmnt);
++		cookie = fast_get_dcookie(vma->vm_file->f_path.dentry,
++			vma->vm_file->f_path.mnt);
+ 		break;
+ 	}
+ 
+@@ -246,8 +246,8 @@ static unsigned long lookup_dcookie(struct mm_struct * mm, unsigned long addr, o
+ 			continue;
+ 
+ 		if (vma->vm_file) {
+-			cookie = fast_get_dcookie(vma->vm_file->f_dentry,
+-				vma->vm_file->f_vfsmnt);
++			cookie = fast_get_dcookie(vma->vm_file->f_path.dentry,
++				vma->vm_file->f_path.mnt);
+ 			*offset = (vma->vm_pgoff << PAGE_SHIFT) + addr -
+ 				vma->vm_start;
+ 		} else {

commit 80a067801d8cc9384f17991b90811f87ceab8225
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:26 2006 -0800
+
+    [PATCH] struct path: convert openpromfs
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
+index 26f44e0074ec..99c0bc37ba09 100644
+--- a/fs/openpromfs/inode.c
++++ b/fs/openpromfs/inode.c
+@@ -262,7 +262,7 @@ static struct dentry *openpromfs_lookup(struct inode *dir, struct dentry *dentry
+ 
+ static int openpromfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
+ {
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct op_inode_info *oi = OP_I(inode);
+ 	struct device_node *dp = oi->u.node;
+ 	struct device_node *child;

commit d28c91740ae2cd1d963f9e4e3889789894cb6d52
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:25 2006 -0800
+
+    [PATCH] struct path: convert ocfs2
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
+index 2f7268e81520..ef6cd30108a9 100644
+--- a/fs/ocfs2/aops.c
++++ b/fs/ocfs2/aops.c
+@@ -595,7 +595,7 @@ static void ocfs2_dio_end_io(struct kiocb *iocb,
+ 			     ssize_t bytes,
+ 			     void *private)
+ {
+-	struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
++	struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode;
+ 
+ 	/* this io's submitter should not have unlocked this before we could */
+ 	BUG_ON(!ocfs2_iocb_is_rw_locked(iocb));
+@@ -611,7 +611,7 @@ static ssize_t ocfs2_direct_IO(int rw,
+ 			       unsigned long nr_segs)
+ {
+ 	struct file *file = iocb->ki_filp;
+-	struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
++	struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host;
+ 	int ret;
+ 
+ 	mlog_entry_void();
+diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
+index baad2aa27c14..66821e178167 100644
+--- a/fs/ocfs2/dir.c
++++ b/fs/ocfs2/dir.c
+@@ -79,7 +79,7 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir)
+ 	struct buffer_head * bh, * tmp;
+ 	struct ocfs2_dir_entry * de;
+ 	int err;
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct super_block * sb = inode->i_sb;
+ 	unsigned int ra_sectors = 16;
+ 	int lock_level = 0;
+diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c
+index 941acf14e61f..b7f0ba97a1a2 100644
+--- a/fs/ocfs2/dlm/dlmfs.c
++++ b/fs/ocfs2/dlm/dlmfs.c
+@@ -176,7 +176,7 @@ static ssize_t dlmfs_file_read(struct file *filp,
+ 	int bytes_left;
+ 	ssize_t readlen;
+ 	char *lvb_buf;
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 
+ 	mlog(0, "inode %lu, count = %zu, *ppos = %llu\n",
+ 		inode->i_ino, count, *ppos);
+@@ -220,7 +220,7 @@ static ssize_t dlmfs_file_write(struct file *filp,
+ 	int bytes_left;
+ 	ssize_t writelen;
+ 	char *lvb_buf;
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 
+ 	mlog(0, "inode %lu, count = %zu, *ppos = %llu\n",
+ 		inode->i_ino, count, *ppos);
+diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
+index 8786b3c490aa..e9a82ad95c1e 100644
+--- a/fs/ocfs2/file.c
++++ b/fs/ocfs2/file.c
+@@ -68,7 +68,7 @@ static int ocfs2_file_open(struct inode *inode, struct file *file)
+ 	struct ocfs2_inode_info *oi = OCFS2_I(inode);
+ 
+ 	mlog_entry("(0x%p, 0x%p, '%.*s')\n", inode, file,
+-		   file->f_dentry->d_name.len, file->f_dentry->d_name.name);
++		   file->f_path.dentry->d_name.len, file->f_path.dentry->d_name.name);
+ 
+ 	spin_lock(&oi->ip_lock);
+ 
+@@ -98,8 +98,8 @@ static int ocfs2_file_release(struct inode *inode, struct file *file)
+ 	struct ocfs2_inode_info *oi = OCFS2_I(inode);
+ 
+ 	mlog_entry("(0x%p, 0x%p, '%.*s')\n", inode, file,
+-		       file->f_dentry->d_name.len,
+-		       file->f_dentry->d_name.name);
++		       file->f_path.dentry->d_name.len,
++		       file->f_path.dentry->d_name.name);
+ 
+ 	spin_lock(&oi->ip_lock);
+ 	if (!--oi->ip_open_count)
+@@ -1131,13 +1131,13 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
+ {
+ 	int ret, rw_level, have_alloc_sem = 0;
+ 	struct file *filp = iocb->ki_filp;
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	int appending = filp->f_flags & O_APPEND ? 1 : 0;
+ 
+ 	mlog_entry("(0x%p, %u, '%.*s')\n", filp,
+ 		   (unsigned int)nr_segs,
+-		   filp->f_dentry->d_name.len,
+-		   filp->f_dentry->d_name.name);
++		   filp->f_path.dentry->d_name.len,
++		   filp->f_path.dentry->d_name.name);
+ 
+ 	/* happy write of zero bytes */
+ 	if (iocb->ki_left == 0)
+@@ -1159,7 +1159,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
+ 		goto out;
+ 	}
+ 
+-	ret = ocfs2_prepare_inode_for_write(filp->f_dentry, &iocb->ki_pos,
++	ret = ocfs2_prepare_inode_for_write(filp->f_path.dentry, &iocb->ki_pos,
+ 					    iocb->ki_left, appending);
+ 	if (ret < 0) {
+ 		mlog_errno(ret);
+@@ -1207,12 +1207,12 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe,
+ 				       unsigned int flags)
+ {
+ 	int ret;
+-	struct inode *inode = out->f_dentry->d_inode;
++	struct inode *inode = out->f_path.dentry->d_inode;
+ 
+ 	mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", out, pipe,
+ 		   (unsigned int)len,
+-		   out->f_dentry->d_name.len,
+-		   out->f_dentry->d_name.name);
++		   out->f_path.dentry->d_name.len,
++		   out->f_path.dentry->d_name.name);
+ 
+ 	inode_double_lock(inode, pipe->inode);
+ 
+@@ -1222,7 +1222,7 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe,
+ 		goto out;
+ 	}
+ 
+-	ret = ocfs2_prepare_inode_for_write(out->f_dentry, ppos, len, 0);
++	ret = ocfs2_prepare_inode_for_write(out->f_path.dentry, ppos, len, 0);
+ 	if (ret < 0) {
+ 		mlog_errno(ret);
+ 		goto out_unlock;
+@@ -1247,12 +1247,12 @@ static ssize_t ocfs2_file_splice_read(struct file *in,
+ 				      unsigned int flags)
+ {
+ 	int ret = 0;
+-	struct inode *inode = in->f_dentry->d_inode;
++	struct inode *inode = in->f_path.dentry->d_inode;
+ 
+ 	mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", in, pipe,
+ 		   (unsigned int)len,
+-		   in->f_dentry->d_name.len,
+-		   in->f_dentry->d_name.name);
++		   in->f_path.dentry->d_name.len,
++		   in->f_path.dentry->d_name.name);
+ 
+ 	/*
+ 	 * See the comment in ocfs2_file_aio_read()
+@@ -1278,12 +1278,12 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
+ {
+ 	int ret = 0, rw_level = -1, have_alloc_sem = 0, lock_level = 0;
+ 	struct file *filp = iocb->ki_filp;
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 
+ 	mlog_entry("(0x%p, %u, '%.*s')\n", filp,
+ 		   (unsigned int)nr_segs,
+-		   filp->f_dentry->d_name.len,
+-		   filp->f_dentry->d_name.name);
++		   filp->f_path.dentry->d_name.len,
++		   filp->f_path.dentry->d_name.name);
+ 
+ 	if (!inode) {
+ 		ret = -EINVAL;

commit 6db5fc5d536560e31978c6911b1f5662e42083ac
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:25 2006 -0800
+
+    [PATCH] struct path: convert netlink
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
+index 3baafb10f8f3..276131fe56dd 100644
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -699,7 +699,7 @@ static struct sock *netlink_getsockbypid(struct sock *ssk, u32 pid)
+ 
+ struct sock *netlink_getsockbyfilp(struct file *filp)
+ {
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct sock *sock;
+ 
+ 	if (!S_ISSOCK(inode->i_mode))

commit 6df81ab22700aadbbefaf0aa00bb9a18f9f54028
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:24 2006 -0800
+
+    [PATCH] struct path: convert netfilter
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
+index 098365062234..fef56ae61abe 100644
+--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
++++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
+@@ -683,7 +683,7 @@ static ssize_t clusterip_proc_write(struct file *file, const char __user *input,
+ {
+ #define PROC_WRITELEN	10
+ 	char buffer[PROC_WRITELEN+1];
+-	struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
++	struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+ 	struct clusterip_config *c = pde->data;
+ 	unsigned long nodenum;
+ 
+diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
+index 126db44e71a8..4db0e73c56f1 100644
+--- a/net/ipv4/netfilter/ipt_recent.c
++++ b/net/ipv4/netfilter/ipt_recent.c
+@@ -401,7 +401,7 @@ static int recent_seq_open(struct inode *inode, struct file *file)
+ static ssize_t recent_proc_write(struct file *file, const char __user *input,
+ 				 size_t size, loff_t *loff)
+ {
+-	struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
++	struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+ 	struct recent_table *t = pde->data;
+ 	struct recent_entry *e;
+ 	char buf[sizeof("+255.255.255.255")], *c = buf;

commit 3126a42c4d40c2b963f880cd5c1e00f0b4fb0dc9
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:23 2006 -0800
+
+    [PATCH] struct path: convert net
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/net/socket.c b/net/socket.c
+index 29ea1de43ecb..4e396312f8d5 100644
+--- a/net/socket.c
++++ b/net/socket.c
+@@ -362,20 +362,20 @@ static int sock_attach_fd(struct socket *sock, struct file *file)
+ 	this.name = name;
+ 	this.hash = 0;
+ 
+-	file->f_dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this);
+-	if (unlikely(!file->f_dentry))
++	file->f_path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this);
++	if (unlikely(!file->f_path.dentry))
+ 		return -ENOMEM;
+ 
+-	file->f_dentry->d_op = &sockfs_dentry_operations;
++	file->f_path.dentry->d_op = &sockfs_dentry_operations;
+ 	/*
+ 	 * We dont want to push this dentry into global dentry hash table.
+ 	 * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED
+ 	 * This permits a working /proc/$pid/fd/XXX on sockets
+ 	 */
+-	file->f_dentry->d_flags &= ~DCACHE_UNHASHED;
+-	d_instantiate(file->f_dentry, SOCK_INODE(sock));
+-	file->f_vfsmnt = mntget(sock_mnt);
+-	file->f_mapping = file->f_dentry->d_inode->i_mapping;
++	file->f_path.dentry->d_flags &= ~DCACHE_UNHASHED;
++	d_instantiate(file->f_path.dentry, SOCK_INODE(sock));
++	file->f_path.mnt = mntget(sock_mnt);
++	file->f_mapping = file->f_path.dentry->d_inode->i_mapping;
+ 
+ 	sock->file = file;
+ 	file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops;
+@@ -413,7 +413,7 @@ static struct socket *sock_from_file(struct file *file, int *err)
+ 	if (file->f_op == &socket_file_ops)
+ 		return file->private_data;	/* set in sock_map_fd */
+ 
+-	inode = file->f_dentry->d_inode;
++	inode = file->f_path.dentry->d_inode;
+ 	if (!S_ISSOCK(inode->i_mode)) {
+ 		*err = -ENOTSOCK;
+ 		return NULL;

commit 92e5baef8578a03335059a3dec933955c361edc1
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:22 2006 -0800
+
+    [PATCH] struct path: convert ncpfs
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
+index 458b3b785194..73747772c3bb 100644
+--- a/fs/ncpfs/dir.c
++++ b/fs/ncpfs/dir.c
+@@ -402,7 +402,7 @@ static time_t ncp_obtain_mtime(struct dentry *dentry)
+ 
+ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ {
+-	struct dentry *dentry = filp->f_dentry;
++	struct dentry *dentry = filp->f_path.dentry;
+ 	struct inode *inode = dentry->d_inode;
+ 	struct page *page = NULL;
+ 	struct ncp_server *server = NCP_SERVER(inode);
+@@ -554,7 +554,7 @@ static int
+ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
+ 		struct ncp_cache_control *ctrl, struct ncp_entry_info *entry)
+ {
+-	struct dentry *newdent, *dentry = filp->f_dentry;
++	struct dentry *newdent, *dentry = filp->f_path.dentry;
+ 	struct inode *newino, *inode = dentry->d_inode;
+ 	struct ncp_cache_control ctl = *ctrl;
+ 	struct qstr qname;
+@@ -649,7 +649,7 @@ static void
+ ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir,
+ 			struct ncp_cache_control *ctl)
+ {
+-	struct dentry *dentry = filp->f_dentry;
++	struct dentry *dentry = filp->f_path.dentry;
+ 	struct inode *inode = dentry->d_inode;
+ 	struct ncp_server *server = NCP_SERVER(inode);
+ 	struct ncp_volume_info info;
+@@ -685,7 +685,7 @@ static void
+ ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
+ 						struct ncp_cache_control *ctl)
+ {
+-	struct dentry *dentry = filp->f_dentry;
++	struct dentry *dentry = filp->f_path.dentry;
+ 	struct inode *dir = dentry->d_inode;
+ 	struct ncp_server *server = NCP_SERVER(dir);
+ 	struct nw_search_sequence seq;
+diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c
+index df37524b85db..b91fea03b1c3 100644
+--- a/fs/ncpfs/file.c
++++ b/fs/ncpfs/file.c
+@@ -101,7 +101,7 @@ int ncp_make_open(struct inode *inode, int right)
+ static ssize_t
+ ncp_file_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+ {
+-	struct dentry *dentry = file->f_dentry;
++	struct dentry *dentry = file->f_path.dentry;
+ 	struct inode *inode = dentry->d_inode;
+ 	size_t already_read = 0;
+ 	off_t pos;
+@@ -182,7 +182,7 @@ ncp_file_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+ static ssize_t
+ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+ {
+-	struct dentry *dentry = file->f_dentry;
++	struct dentry *dentry = file->f_path.dentry;
+ 	struct inode *inode = dentry->d_inode;
+ 	size_t already_written = 0;
+ 	off_t pos;
+diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
+index fae53243bb92..47462ac94474 100644
+--- a/fs/ncpfs/inode.c
++++ b/fs/ncpfs/inode.c
+@@ -471,7 +471,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
+ 	if (!ncp_filp)
+ 		goto out;
+ 	error = -ENOTSOCK;
+-	sock_inode = ncp_filp->f_dentry->d_inode;
++	sock_inode = ncp_filp->f_path.dentry->d_inode;
+ 	if (!S_ISSOCK(sock_inode->i_mode))
+ 		goto out_fput;
+ 	sock = SOCKET_I(sock_inode);
+@@ -504,7 +504,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
+ 		if (!server->info_filp)
+ 			goto out_fput;
+ 		error = -ENOTSOCK;
+-		sock_inode = server->info_filp->f_dentry->d_inode;
++		sock_inode = server->info_filp->f_path.dentry->d_inode;
+ 		if (!S_ISSOCK(sock_inode->i_mode))
+ 			goto out_fput2;
+ 		info_sock = SOCKET_I(sock_inode);
+diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
+index 589d1eac55c1..8843a83d4ef0 100644
+--- a/fs/ncpfs/ioctl.c
++++ b/fs/ncpfs/ioctl.c
+@@ -35,7 +35,7 @@ static int
+ ncp_get_fs_info(struct ncp_server * server, struct file *file,
+ 		struct ncp_fs_info __user *arg)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	struct ncp_fs_info info;
+ 
+ 	if ((file_permission(file, MAY_WRITE) != 0)
+@@ -65,7 +65,7 @@ static int
+ ncp_get_fs_info_v2(struct ncp_server * server, struct file *file,
+ 		   struct ncp_fs_info_v2 __user * arg)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	struct ncp_fs_info_v2 info2;
+ 
+ 	if ((file_permission(file, MAY_WRITE) != 0)
+@@ -136,7 +136,7 @@ static int
+ ncp_get_compat_fs_info_v2(struct ncp_server * server, struct file *file,
+ 		   struct compat_ncp_fs_info_v2 __user * arg)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	struct compat_ncp_fs_info_v2 info2;
+ 
+ 	if ((file_permission(file, MAY_WRITE) != 0)
+@@ -824,7 +824,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
+ #ifdef CONFIG_COMPAT
+ long ncp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	int ret;
+ 
+ 	lock_kernel();
+diff --git a/fs/ncpfs/mmap.c b/fs/ncpfs/mmap.c
+index e7d5a3097fe6..70a69115500f 100644
+--- a/fs/ncpfs/mmap.c
++++ b/fs/ncpfs/mmap.c
+@@ -29,7 +29,7 @@ static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area,
+ 				     unsigned long address, int *type)
+ {
+ 	struct file *file = area->vm_file;
+-	struct dentry *dentry = file->f_dentry;
++	struct dentry *dentry = file->f_path.dentry;
+ 	struct inode *inode = dentry->d_inode;
+ 	struct page* page;
+ 	char *pg_addr;
+@@ -106,7 +106,7 @@ static struct vm_operations_struct ncp_file_mmap =
+ /* This is used for a general mmap of a ncp file */
+ int ncp_mmap(struct file *file, struct vm_area_struct *vma)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	
+ 	DPRINTK("ncp_mmap: called\n");
+ 

commit 17506041de973bdc718b9a255d822e571b12b421
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:22 2006 -0800
+
+    [PATCH] struct path: convert nbd
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
+index 7bf2cfbd6285..090796bef78f 100644
+--- a/drivers/block/nbd.c
++++ b/drivers/block/nbd.c
+@@ -537,7 +537,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
+ 		error = -EINVAL;
+ 		file = fget(arg);
+ 		if (file) {
+-			inode = file->f_dentry->d_inode;
++			inode = file->f_path.dentry->d_inode;
+ 			if (S_ISSOCK(inode->i_mode)) {
+ 				lo->file = file;
+ 				lo->sock = SOCKET_I(inode);

commit e9536ae7205d255bc94616b72910fc6e16c861fe
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:21 2006 -0800
+
+    [PATCH] struct path: convert mm
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/mm/mempolicy.c b/mm/mempolicy.c
+index b917d6fdc1bb..da9463946556 100644
+--- a/mm/mempolicy.c
++++ b/mm/mempolicy.c
+@@ -1857,7 +1857,7 @@ int show_numa_map(struct seq_file *m, void *v)
+ 
+ 	if (file) {
+ 		seq_printf(m, " file=");
+-		seq_path(m, file->f_vfsmnt, file->f_dentry, "\n\t= ");
++		seq_path(m, file->f_path.mnt, file->f_path.dentry, "\n\t= ");
+ 	} else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) {
+ 		seq_printf(m, " heap");
+ 	} else if (vma->vm_start <= mm->start_stack &&
+diff --git a/mm/nommu.c b/mm/nommu.c
+index af874569d0f1..23fb033e596d 100644
+--- a/mm/nommu.c
++++ b/mm/nommu.c
+@@ -523,7 +523,7 @@ static int validate_mmap_request(struct file *file,
+ 		 */
+ 		mapping = file->f_mapping;
+ 		if (!mapping)
+-			mapping = file->f_dentry->d_inode->i_mapping;
++			mapping = file->f_path.dentry->d_inode->i_mapping;
+ 
+ 		capabilities = 0;
+ 		if (mapping && mapping->backing_dev_info)
+@@ -532,7 +532,7 @@ static int validate_mmap_request(struct file *file,
+ 		if (!capabilities) {
+ 			/* no explicit capabilities set, so assume some
+ 			 * defaults */
+-			switch (file->f_dentry->d_inode->i_mode & S_IFMT) {
++			switch (file->f_path.dentry->d_inode->i_mode & S_IFMT) {
+ 			case S_IFREG:
+ 			case S_IFBLK:
+ 				capabilities = BDI_CAP_MAP_COPY;
+@@ -563,11 +563,11 @@ static int validate_mmap_request(struct file *file,
+ 			    !(file->f_mode & FMODE_WRITE))
+ 				return -EACCES;
+ 
+-			if (IS_APPEND(file->f_dentry->d_inode) &&
++			if (IS_APPEND(file->f_path.dentry->d_inode) &&
+ 			    (file->f_mode & FMODE_WRITE))
+ 				return -EACCES;
+ 
+-			if (locks_verify_locked(file->f_dentry->d_inode))
++			if (locks_verify_locked(file->f_path.dentry->d_inode))
+ 				return -EAGAIN;
+ 
+ 			if (!(capabilities & BDI_CAP_MAP_DIRECT))
+@@ -598,7 +598,7 @@ static int validate_mmap_request(struct file *file,
+ 
+ 		/* handle executable mappings and implied executable
+ 		 * mappings */
+-		if (file->f_vfsmnt->mnt_flags & MNT_NOEXEC) {
++		if (file->f_path.mnt->mnt_flags & MNT_NOEXEC) {
+ 			if (prot & PROT_EXEC)
+ 				return -EPERM;
+ 		}
+@@ -833,7 +833,7 @@ unsigned long do_mmap_pgoff(struct file *file,
+ 				continue;
+ 
+ 			/* search for overlapping mappings on the same file */
+-			if (vma->vm_file->f_dentry->d_inode != file->f_dentry->d_inode)
++			if (vma->vm_file->f_path.dentry->d_inode != file->f_path.dentry->d_inode)
+ 				continue;
+ 
+ 			if (vma->vm_pgoff >= pgoff + pglen)
+diff --git a/mm/readahead.c b/mm/readahead.c
+index a386f2b6b335..c0df5ed05f62 100644
+--- a/mm/readahead.c
++++ b/mm/readahead.c
+@@ -450,7 +450,7 @@ static int make_ahead_window(struct address_space *mapping, struct file *filp,
+  *
+  * Note that @filp is purely used for passing on to the ->readpage[s]()
+  * handler: it may refer to a different file from @mapping (so we may not use
+- * @filp->f_mapping or @filp->f_dentry->d_inode here).
++ * @filp->f_mapping or @filp->f_path.dentry->d_inode here).
+  * Also, @ra may not be equal to &@filp->f_ra.
+  *
+  */
+diff --git a/mm/tiny-shmem.c b/mm/tiny-shmem.c
+index 5f2cbf0f153c..c7f6e1914bc4 100644
+--- a/mm/tiny-shmem.c
++++ b/mm/tiny-shmem.c
+@@ -79,8 +79,8 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
+ 	d_instantiate(dentry, inode);
+ 	inode->i_nlink = 0;	/* It is unlinked */
+ 
+-	file->f_vfsmnt = mntget(shm_mnt);
+-	file->f_dentry = dentry;
++	file->f_path.mnt = mntget(shm_mnt);
++	file->f_path.dentry = dentry;
+ 	file->f_mapping = inode->i_mapping;
+ 	file->f_op = &ramfs_file_operations;
+ 	file->f_mode = FMODE_WRITE | FMODE_READ;

commit 1b04fe9a8ef10774174897b15d753b9de85fe9e9
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:20 2006 -0800
+
+    [PATCH] struct path: convert mips
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
+index 8c8c8324f775..5a99e3e0c96d 100644
+--- a/arch/mips/kernel/rtlx.c
++++ b/arch/mips/kernel/rtlx.c
+@@ -415,7 +415,7 @@ static unsigned int file_poll(struct file *file, poll_table * wait)
+ 	int minor;
+ 	unsigned int mask = 0;
+ 
+-	minor = iminor(file->f_dentry->d_inode);
++	minor = iminor(file->f_path.dentry->d_inode);
+ 
+ 	poll_wait(file, &channel_wqs[minor].rt_queue, wait);
+ 	poll_wait(file, &channel_wqs[minor].lx_queue, wait);
+@@ -437,7 +437,7 @@ static unsigned int file_poll(struct file *file, poll_table * wait)
+ static ssize_t file_read(struct file *file, char __user * buffer, size_t count,
+ 			 loff_t * ppos)
+ {
+-	int minor = iminor(file->f_dentry->d_inode);
++	int minor = iminor(file->f_path.dentry->d_inode);
+ 
+ 	/* data available? */
+ 	if (!rtlx_read_poll(minor, (file->f_flags & O_NONBLOCK) ? 0 : 1)) {
+@@ -454,7 +454,7 @@ static ssize_t file_write(struct file *file, const char __user * buffer,
+ 	struct rtlx_channel *rt;
+ 	DECLARE_WAITQUEUE(wait, current);
+ 
+-	minor = iminor(file->f_dentry->d_inode);
++	minor = iminor(file->f_path.dentry->d_inode);
+ 	rt = &rtlx->channel[minor];
+ 
+ 	/* any space left... */
+diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
+index 93c74fefff76..6c2406a93f2b 100644
+--- a/arch/mips/kernel/sysirix.c
++++ b/arch/mips/kernel/sysirix.c
+@@ -732,7 +732,7 @@ asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs __user *buf)
+ 		goto out;
+ 	}
+ 
+-	error = vfs_statfs(file->f_dentry, &kbuf);
++	error = vfs_statfs(file->f_path.dentry, &kbuf);
+ 	if (error)
+ 		goto out_f;
+ 
+@@ -1041,7 +1041,7 @@ asmlinkage unsigned long irix_mmap32(unsigned long addr, size_t len, int prot,
+ 			unsigned long old_pos;
+ 			long max_size = offset + len;
+ 
+-			if (max_size > file->f_dentry->d_inode->i_size) {
++			if (max_size > file->f_path.dentry->d_inode->i_size) {
+ 				old_pos = sys_lseek (fd, max_size - 1, 0);
+ 				sys_write (fd, (void __user *) "", 1);
+ 				sys_lseek (fd, old_pos, 0);
+@@ -1406,7 +1406,7 @@ asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs __user *buf)
+ 		error = -EBADF;
+ 		goto out;
+ 	}
+-	error = vfs_statfs(file->f_dentry, &kbuf);
++	error = vfs_statfs(file->f_path.dentry, &kbuf);
+ 	if (error)
+ 		goto out_f;
+ 
+@@ -1526,7 +1526,7 @@ asmlinkage int irix_mmap64(struct pt_regs *regs)
+ 			unsigned long old_pos;
+ 			long max_size = off2 + len;
+ 
+-			if (max_size > file->f_dentry->d_inode->i_size) {
++			if (max_size > file->f_path.dentry->d_inode->i_size) {
+ 				old_pos = sys_lseek (fd, max_size - 1, 0);
+ 				sys_write (fd, (void __user *) "", 1);
+ 				sys_lseek (fd, old_pos, 0);
+@@ -1658,7 +1658,7 @@ asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs __user *buf)
+ 		error = -EBADF;
+ 		goto out;
+ 	}
+-	error = vfs_statfs(file->f_dentry, &kbuf);
++	error = vfs_statfs(file->f_path.dentry, &kbuf);
+ 	if (error)
+ 		goto out_f;
+ 
+diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
+index 51ddd2166898..666bef484dcb 100644
+--- a/arch/mips/kernel/vpe.c
++++ b/arch/mips/kernel/vpe.c
+@@ -1179,7 +1179,7 @@ static ssize_t vpe_write(struct file *file, const char __user * buffer,
+ 	size_t ret = count;
+ 	struct vpe *v;
+ 
+-	minor = iminor(file->f_dentry->d_inode);
++	minor = iminor(file->f_path.dentry->d_inode);
+ 	if ((v = get_vpe(minor)) == NULL)
+ 		return -ENODEV;
+ 
+diff --git a/arch/mips/lasat/sysctl.c b/arch/mips/lasat/sysctl.c
+index 6dd7ae1b7c25..da35d4555491 100644
+--- a/arch/mips/lasat/sysctl.c
++++ b/arch/mips/lasat/sysctl.c
+@@ -286,11 +286,11 @@ int proc_lasat_eeprom_value(ctl_table *table, int write, struct file *filp,
+ 		mutex_unlock(&lasat_info_mutex);
+ 		return r;
+ 	}
+-	if (filp && filp->f_dentry)
++	if (filp && filp->f_path.dentry)
+ 	{
+-		if (!strcmp(filp->f_dentry->d_name.name, "prid"))
++		if (!strcmp(filp->f_path.dentry->d_name.name, "prid"))
+ 			lasat_board_info.li_eeprom_info.prid = lasat_board_info.li_prid;
+-		if (!strcmp(filp->f_dentry->d_name.name, "debugaccess"))
++		if (!strcmp(filp->f_path.dentry->d_name.name, "debugaccess"))
+ 			lasat_board_info.li_eeprom_info.debugaccess = lasat_board_info.li_debugaccess;
+ 	}
+ 	lasat_write_eeprom_info();

commit dcf258ae682c2dbbe1a34624f2b3f56353d3874d
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:19 2006 -0800
+
+    [PATCH] struct path: convert minix
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/minix/dir.c b/fs/minix/dir.c
+index 2b0a389d1987..ab782c4086f5 100644
+--- a/fs/minix/dir.c
++++ b/fs/minix/dir.c
+@@ -82,7 +82,7 @@ static inline void *minix_next_entry(void *de, struct minix_sb_info *sbi)
+ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir)
+ {
+ 	unsigned long pos = filp->f_pos;
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct super_block *sb = inode->i_sb;
+ 	unsigned offset = pos & ~PAGE_CACHE_MASK;
+ 	unsigned long n = pos >> PAGE_CACHE_SHIFT;

commit c649bb9c55e78dcff0e1383c13d91e0bfc2abb4a
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:19 2006 -0800
+
+    [PATCH] struct path: convert md
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
+index d6f614738bbd..5432d07c074d 100644
+--- a/drivers/md/bitmap.c
++++ b/drivers/md/bitmap.c
+@@ -212,8 +212,8 @@ char *file_path(struct file *file, char *buf, int count)
+ 	if (!buf)
+ 		return NULL;
+ 
+-	d = file->f_dentry;
+-	v = file->f_vfsmnt;
++	d = file->f_path.dentry;
++	v = file->f_path.mnt;
+ 
+ 	buf = d_path(d, v, buf, count);
+ 
+@@ -349,7 +349,7 @@ static struct page *read_page(struct file *file, unsigned long index,
+ 			      unsigned long count)
+ {
+ 	struct page *page = NULL;
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	struct buffer_head *bh;
+ 	sector_t block;
+ 
+@@ -662,7 +662,7 @@ static void bitmap_file_put(struct bitmap *bitmap)
+ 	bitmap_file_unmap(bitmap);
+ 
+ 	if (file) {
+-		struct inode *inode = file->f_dentry->d_inode;
++		struct inode *inode = file->f_path.dentry->d_inode;
+ 		invalidate_inode_pages(inode->i_mapping);
+ 		fput(file);
+ 	}
+diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
+index 00234909b3db..4a1cee48e652 100644
+--- a/drivers/md/dm-linear.c
++++ b/drivers/md/dm-linear.c
+@@ -108,7 +108,7 @@ static int linear_ioctl(struct dm_target *ti, struct inode *inode,
+ 	struct dentry fake_dentry = {};
+ 
+ 	fake_file.f_mode = lc->dev->mode;
+-	fake_file.f_dentry = &fake_dentry;
++	fake_file.f_path.dentry = &fake_dentry;
+ 	fake_dentry.d_inode = bdev->bd_inode;
+ 
+ 	return blkdev_driver_ioctl(bdev->bd_inode, &fake_file, bdev->bd_disk, cmd, arg);
+diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
+index e9dfe2c98059..dda4109292bc 100644
+--- a/drivers/md/dm-mpath.c
++++ b/drivers/md/dm-mpath.c
+@@ -1272,7 +1272,7 @@ static int multipath_ioctl(struct dm_target *ti, struct inode *inode,
+ 	struct dentry fake_dentry = {};
+ 	int r = 0;
+ 
+-	fake_file.f_dentry = &fake_dentry;
++	fake_file.f_path.dentry = &fake_dentry;
+ 
+ 	spin_lock_irqsave(&m->lock, flags);
+ 
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 3ce7a5d81d81..53bd46dba0cb 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -4846,8 +4846,8 @@ static int md_seq_show(struct seq_file *seq, void *v)
+ 				chunk_kb ? "KB" : "B");
+ 			if (bitmap->file) {
+ 				seq_printf(seq, ", file: ");
+-				seq_path(seq, bitmap->file->f_vfsmnt,
+-					 bitmap->file->f_dentry," \t\n");
++				seq_path(seq, bitmap->file->f_path.mnt,
++					 bitmap->file->f_path.dentry," \t\n");
+ 			}
+ 
+ 			seq_printf(seq, "\n");

commit 225a719f79fbc4d0cd9d9ebc5b2e3ac0e95845aa
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:18 2006 -0800
+
+    [PATCH] struct path: convert lockd
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
+index b85a0ad2cfb6..92681c9e9b20 100644
+--- a/fs/lockd/clntlock.c
++++ b/fs/lockd/clntlock.c
+@@ -126,7 +126,7 @@ __be32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock
+ 			continue;
+ 		if (!nlm_cmp_addr(&block->b_host->h_addr, addr))
+ 			continue;
+-		if (nfs_compare_fh(NFS_FH(fl_blocked->fl_file->f_dentry->d_inode) ,fh) != 0)
++		if (nfs_compare_fh(NFS_FH(fl_blocked->fl_file->f_path.dentry->d_inode) ,fh) != 0)
+ 			continue;
+ 		/* Alright, we found a lock. Set the return status
+ 		 * and wake up the caller
+diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
+index 497c3cd59d52..80a1a6dccc8f 100644
+--- a/fs/lockd/clntproc.c
++++ b/fs/lockd/clntproc.c
+@@ -129,7 +129,7 @@ static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
+ 
+ 	nlmclnt_next_cookie(&argp->cookie);
+ 	argp->state   = nsm_local_state;
+-	memcpy(&lock->fh, NFS_FH(fl->fl_file->f_dentry->d_inode), sizeof(struct nfs_fh));
++	memcpy(&lock->fh, NFS_FH(fl->fl_file->f_path.dentry->d_inode), sizeof(struct nfs_fh));
+ 	lock->caller  = utsname()->nodename;
+ 	lock->oh.data = req->a_owner;
+ 	lock->oh.len  = snprintf(req->a_owner, sizeof(req->a_owner), "%u@%s",
+diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
+index 7e219b938552..5c054b20fd5e 100644
+--- a/fs/lockd/svclock.c
++++ b/fs/lockd/svclock.c
+@@ -343,8 +343,8 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
+ 	__be32			ret;
+ 
+ 	dprintk("lockd: nlmsvc_lock(%s/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n",
+-				file->f_file->f_dentry->d_inode->i_sb->s_id,
+-				file->f_file->f_dentry->d_inode->i_ino,
++				file->f_file->f_path.dentry->d_inode->i_sb->s_id,
++				file->f_file->f_path.dentry->d_inode->i_ino,
+ 				lock->fl.fl_type, lock->fl.fl_pid,
+ 				(long long)lock->fl.fl_start,
+ 				(long long)lock->fl.fl_end,
+@@ -420,8 +420,8 @@ nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock,
+ 				       struct nlm_lock *conflock)
+ {
+ 	dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n",
+-				file->f_file->f_dentry->d_inode->i_sb->s_id,
+-				file->f_file->f_dentry->d_inode->i_ino,
++				file->f_file->f_path.dentry->d_inode->i_sb->s_id,
++				file->f_file->f_path.dentry->d_inode->i_ino,
+ 				lock->fl.fl_type,
+ 				(long long)lock->fl.fl_start,
+ 				(long long)lock->fl.fl_end);
+@@ -454,8 +454,8 @@ nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock)
+ 	int	error;
+ 
+ 	dprintk("lockd: nlmsvc_unlock(%s/%ld, pi=%d, %Ld-%Ld)\n",
+-				file->f_file->f_dentry->d_inode->i_sb->s_id,
+-				file->f_file->f_dentry->d_inode->i_ino,
++				file->f_file->f_path.dentry->d_inode->i_sb->s_id,
++				file->f_file->f_path.dentry->d_inode->i_ino,
+ 				lock->fl.fl_pid,
+ 				(long long)lock->fl.fl_start,
+ 				(long long)lock->fl.fl_end);
+@@ -483,8 +483,8 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
+ 	int status = 0;
+ 
+ 	dprintk("lockd: nlmsvc_cancel(%s/%ld, pi=%d, %Ld-%Ld)\n",
+-				file->f_file->f_dentry->d_inode->i_sb->s_id,
+-				file->f_file->f_dentry->d_inode->i_ino,
++				file->f_file->f_path.dentry->d_inode->i_sb->s_id,
++				file->f_file->f_path.dentry->d_inode->i_ino,
+ 				lock->fl.fl_pid,
+ 				(long long)lock->fl.fl_start,
+ 				(long long)lock->fl.fl_end);
+diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
+index e83024e16042..c0df00c74ce3 100644
+--- a/fs/lockd/svcsubs.c
++++ b/fs/lockd/svcsubs.c
+@@ -43,7 +43,7 @@ static inline void nlm_debug_print_fh(char *msg, struct nfs_fh *f)
+ 
+ static inline void nlm_debug_print_file(char *msg, struct nlm_file *file)
+ {
+-	struct inode *inode = file->f_file->f_dentry->d_inode;
++	struct inode *inode = file->f_file->f_path.dentry->d_inode;
+ 
+ 	dprintk("lockd: %s %s/%ld\n",
+ 		msg, inode->i_sb->s_id, inode->i_ino);
+diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
+index 8c39654549d8..0c962b82a9de 100644
+--- a/include/linux/lockd/lockd.h
++++ b/include/linux/lockd/lockd.h
+@@ -206,7 +206,7 @@ void		  nlmsvc_invalidate_all(void);
+ static __inline__ struct inode *
+ nlmsvc_file_inode(struct nlm_file *file)
+ {
+-	return file->f_file->f_dentry->d_inode;
++	return file->f_file->f_path.dentry->d_inode;
+ }
+ 
+ /*

commit a7a005fd12b84392becca311f2a20d5bf2a1b7af
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:17 2006 -0800
+
+    [PATCH] struct path: convert kernel
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/kernel/auditsc.c b/kernel/auditsc.c
+index b6cb802fbcd1..298897559ca4 100644
+--- a/kernel/auditsc.c
++++ b/kernel/auditsc.c
+@@ -781,8 +781,8 @@ static void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk
+ 			if ((vma->vm_flags & VM_EXECUTABLE) &&
+ 			    vma->vm_file) {
+ 				audit_log_d_path(ab, "exe=",
+-						 vma->vm_file->f_dentry,
+-						 vma->vm_file->f_vfsmnt);
++						 vma->vm_file->f_path.dentry,
++						 vma->vm_file->f_path.mnt);
+ 				break;
+ 			}
+ 			vma = vma->vm_next;
+diff --git a/kernel/cpuset.c b/kernel/cpuset.c
+index 0a6b4d89f9a0..2c3b4431472b 100644
+--- a/kernel/cpuset.c
++++ b/kernel/cpuset.c
+@@ -413,8 +413,8 @@ static struct file_system_type cpuset_fs_type = {
+  *
+  *
+  * When reading/writing to a file:
+- *	- the cpuset to use in file->f_dentry->d_parent->d_fsdata
+- *	- the 'cftype' of the file is file->f_dentry->d_fsdata
++ *	- the cpuset to use in file->f_path.dentry->d_parent->d_fsdata
++ *	- the 'cftype' of the file is file->f_path.dentry->d_fsdata
+  */
+ 
+ struct cftype {
+@@ -1284,8 +1284,8 @@ static ssize_t cpuset_common_file_write(struct file *file,
+ 					const char __user *userbuf,
+ 					size_t nbytes, loff_t *unused_ppos)
+ {
+-	struct cpuset *cs = __d_cs(file->f_dentry->d_parent);
+-	struct cftype *cft = __d_cft(file->f_dentry);
++	struct cpuset *cs = __d_cs(file->f_path.dentry->d_parent);
++	struct cftype *cft = __d_cft(file->f_path.dentry);
+ 	cpuset_filetype_t type = cft->private;
+ 	char *buffer;
+ 	char *pathbuf = NULL;
+@@ -1367,7 +1367,7 @@ static ssize_t cpuset_file_write(struct file *file, const char __user *buf,
+ 						size_t nbytes, loff_t *ppos)
+ {
+ 	ssize_t retval = 0;
+-	struct cftype *cft = __d_cft(file->f_dentry);
++	struct cftype *cft = __d_cft(file->f_path.dentry);
+ 	if (!cft)
+ 		return -ENODEV;
+ 
+@@ -1417,8 +1417,8 @@ static int cpuset_sprintf_memlist(char *page, struct cpuset *cs)
+ static ssize_t cpuset_common_file_read(struct file *file, char __user *buf,
+ 				size_t nbytes, loff_t *ppos)
+ {
+-	struct cftype *cft = __d_cft(file->f_dentry);
+-	struct cpuset *cs = __d_cs(file->f_dentry->d_parent);
++	struct cftype *cft = __d_cft(file->f_path.dentry);
++	struct cpuset *cs = __d_cs(file->f_path.dentry->d_parent);
+ 	cpuset_filetype_t type = cft->private;
+ 	char *page;
+ 	ssize_t retval = 0;
+@@ -1476,7 +1476,7 @@ static ssize_t cpuset_file_read(struct file *file, char __user *buf, size_t nbyt
+ 								loff_t *ppos)
+ {
+ 	ssize_t retval = 0;
+-	struct cftype *cft = __d_cft(file->f_dentry);
++	struct cftype *cft = __d_cft(file->f_path.dentry);
+ 	if (!cft)
+ 		return -ENODEV;
+ 
+@@ -1498,7 +1498,7 @@ static int cpuset_file_open(struct inode *inode, struct file *file)
+ 	if (err)
+ 		return err;
+ 
+-	cft = __d_cft(file->f_dentry);
++	cft = __d_cft(file->f_path.dentry);
+ 	if (!cft)
+ 		return -ENODEV;
+ 	if (cft->open)
+@@ -1511,7 +1511,7 @@ static int cpuset_file_open(struct inode *inode, struct file *file)
+ 
+ static int cpuset_file_release(struct inode *inode, struct file *file)
+ {
+-	struct cftype *cft = __d_cft(file->f_dentry);
++	struct cftype *cft = __d_cft(file->f_path.dentry);
+ 	if (cft->release)
+ 		return cft->release(inode, file);
+ 	return 0;
+@@ -1700,7 +1700,7 @@ static int pid_array_to_buf(char *buf, int sz, pid_t *a, int npids)
+  */
+ static int cpuset_tasks_open(struct inode *unused, struct file *file)
+ {
+-	struct cpuset *cs = __d_cs(file->f_dentry->d_parent);
++	struct cpuset *cs = __d_cs(file->f_path.dentry->d_parent);
+ 	struct ctr_struct *ctr;
+ 	pid_t *pidarray;
+ 	int npids;

commit ff273773bfd4f2131bad1318e56519fcceac2339
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:16 2006 -0800
+
+    [PATCH] struct path: convert jfs
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
+index ecb2216d881c..47bc0b5d1324 100644
+--- a/fs/jfs/jfs_dtree.c
++++ b/fs/jfs/jfs_dtree.c
+@@ -3009,7 +3009,7 @@ static inline struct jfs_dirent *next_jfs_dirent(struct jfs_dirent *dirent)
+  */
+ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ {
+-	struct inode *ip = filp->f_dentry->d_inode;
++	struct inode *ip = filp->f_path.dentry->d_inode;
+ 	struct nls_table *codepage = JFS_SBI(ip->i_sb)->nls_tab;
+ 	int rc = 0;
+ 	loff_t dtpos;	/* legacy OS/2 style position */

commit ec2e203c8297d576c74a101cebd657bc1f180dd1
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:16 2006 -0800
+
+    [PATCH] struct path: convert jffs2
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
+index 9def6adf4a5d..da6034d50718 100644
+--- a/fs/jffs2/dir.c
++++ b/fs/jffs2/dir.c
+@@ -123,11 +123,11 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ {
+ 	struct jffs2_inode_info *f;
+ 	struct jffs2_sb_info *c;
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct jffs2_full_dirent *fd;
+ 	unsigned long offset, curofs;
+ 
+-	D1(printk(KERN_DEBUG "jffs2_readdir() for dir_i #%lu\n", filp->f_dentry->d_inode->i_ino));
++	D1(printk(KERN_DEBUG "jffs2_readdir() for dir_i #%lu\n", filp->f_path.dentry->d_inode->i_ino));
+ 
+ 	f = JFFS2_INODE_INFO(inode);
+ 	c = JFFS2_SB_INFO(inode->i_sb);
+@@ -141,7 +141,7 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ 		offset++;
+ 	}
+ 	if (offset == 1) {
+-		unsigned long pino = parent_ino(filp->f_dentry);
++		unsigned long pino = parent_ino(filp->f_path.dentry);
+ 		D1(printk(KERN_DEBUG "Dirent 1: \"..\", ino #%lu\n", pino));
+ 		if (filldir(dirent, "..", 2, 1, pino, DT_DIR) < 0)
+ 			goto out;

commit 4d832d460e13dd9c2cc93739ac0fd75bd8645e93
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:15 2006 -0800
+
+    [PATCH] struct path: convert jffs
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
+index 9f15bce92022..7b40c69f44eb 100644
+--- a/fs/jffs/inode-v23.c
++++ b/fs/jffs/inode-v23.c
+@@ -566,7 +566,7 @@ static int
+ jffs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ {
+ 	struct jffs_file *f;
+-	struct dentry *dentry = filp->f_dentry;
++	struct dentry *dentry = filp->f_path.dentry;
+ 	struct inode *inode = dentry->d_inode;
+ 	struct jffs_control *c = (struct jffs_control *)inode->i_sb->s_fs_info;
+ 	int j;
+@@ -1372,7 +1372,7 @@ jffs_file_write(struct file *filp, const char *buf, size_t count,
+ 	struct jffs_control *c;
+ 	struct jffs_file *f;
+ 	struct jffs_node *node;
+-	struct dentry *dentry = filp->f_dentry;
++	struct dentry *dentry = filp->f_path.dentry;
+ 	struct inode *inode = dentry->d_inode;
+ 	int recoverable = 0;
+ 	size_t written = 0;
+@@ -1380,7 +1380,7 @@ jffs_file_write(struct file *filp, const char *buf, size_t count,
+ 	loff_t pos = *ppos;
+ 	int err;
+ 
+-	inode = filp->f_dentry->d_inode;
++	inode = filp->f_path.dentry->d_inode;
+ 
+ 	D2(printk("***jffs_file_write(): inode: 0x%p (ino: %lu), "
+ 		  "filp: 0x%p, buf: 0x%p, count: %d\n",

commit d1f229744ece0b7aa7ce89ecd1fb598b90305d5b
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:14 2006 -0800
+
+    [PATCH] struct path: convert ixj
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
+index 1b601b6cf2a2..df4cc1fb5f68 100644
+--- a/drivers/telephony/ixj.c
++++ b/drivers/telephony/ixj.c
+@@ -2747,7 +2747,7 @@ static void alaw2ulaw(unsigned char *buff, unsigned long len)
+ static ssize_t ixj_read(struct file * file_p, char __user *buf, size_t length, loff_t * ppos)
+ {
+ 	unsigned long i = *ppos;
+-	IXJ * j = get_ixj(NUM(file_p->f_dentry->d_inode));
++	IXJ * j = get_ixj(NUM(file_p->f_path.dentry->d_inode));
+ 
+ 	DECLARE_WAITQUEUE(wait, current);
+ 
+@@ -2804,7 +2804,7 @@ static ssize_t ixj_enhanced_read(struct file * file_p, char __user *buf, size_t
+ {
+ 	int pre_retval;
+ 	ssize_t read_retval = 0;
+-	IXJ *j = get_ixj(NUM(file_p->f_dentry->d_inode));
++	IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode));
+ 
+ 	pre_retval = ixj_PreRead(j, 0L);
+ 	switch (pre_retval) {
+@@ -2883,7 +2883,7 @@ static ssize_t ixj_enhanced_write(struct file * file_p, const char __user *buf,
+ 	int pre_retval;
+ 	ssize_t write_retval = 0;
+ 
+-	IXJ *j = get_ixj(NUM(file_p->f_dentry->d_inode));
++	IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode));
+ 
+ 	pre_retval = ixj_PreWrite(j, 0L);
+ 	switch (pre_retval) {
+@@ -4582,7 +4582,7 @@ static unsigned int ixj_poll(struct file *file_p, poll_table * wait)
+ {
+ 	unsigned int mask = 0;
+ 
+-	IXJ *j = get_ixj(NUM(file_p->f_dentry->d_inode));
++	IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode));
+ 
+ 	poll_wait(file_p, &(j->poll_q), wait);
+ 	if (j->read_buffer_ready > 0)
+@@ -6657,7 +6657,7 @@ static int ixj_ioctl(struct inode *inode, struct file *file_p, unsigned int cmd,
+ 
+ static int ixj_fasync(int fd, struct file *file_p, int mode)
+ {
+-	IXJ *j = get_ixj(NUM(file_p->f_dentry->d_inode));
++	IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode));
+ 
+ 	return fasync_helper(fd, file_p, mode, &j->async_queue);
+ }

commit 4482dfad69d783d1df03ed3952838451a249985e
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:13 2006 -0800
+
+    [PATCH] struct path: convert isdn
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
+index 11844bbfe933..787a630a8e56 100644
+--- a/drivers/isdn/capi/capi.c
++++ b/drivers/isdn/capi/capi.c
+@@ -1010,7 +1010,7 @@ static int capinc_tty_open(struct tty_struct * tty, struct file * file)
+ {
+ 	struct capiminor *mp;
+ 
+-	if ((mp = capiminor_find(iminor(file->f_dentry->d_inode))) == 0)
++	if ((mp = capiminor_find(iminor(file->f_path.dentry->d_inode))) == 0)
+ 		return -ENXIO;
+ 	if (mp->nccip == 0)
+ 		return -ENXIO;
+diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c
+index fcd49920b220..4d238eff1773 100644
+--- a/drivers/isdn/hysdn/hysdn_proclog.c
++++ b/drivers/isdn/hysdn/hysdn_proclog.c
+@@ -204,7 +204,7 @@ hysdn_log_read(struct file *file, char __user *buf, size_t count, loff_t * off)
+ {
+ 	struct log_data *inf;
+ 	int len;
+-	struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
++	struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+ 	struct procdata *pd = NULL;
+ 	hysdn_card *card;
+ 
+@@ -354,7 +354,7 @@ static unsigned int
+ hysdn_log_poll(struct file *file, poll_table * wait)
+ {
+ 	unsigned int mask = 0;
+-	struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
++	struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+ 	hysdn_card *card;
+ 	struct procdata *pd = NULL;
+ 
+diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
+index 69aee2602aa6..a610a05aa217 100644
+--- a/drivers/isdn/i4l/isdn_common.c
++++ b/drivers/isdn/i4l/isdn_common.c
+@@ -1059,7 +1059,7 @@ isdn_info_update(void)
+ static ssize_t
+ isdn_read(struct file *file, char __user *buf, size_t count, loff_t * off)
+ {
+-	uint minor = iminor(file->f_dentry->d_inode);
++	uint minor = iminor(file->f_path.dentry->d_inode);
+ 	int len = 0;
+ 	int drvidx;
+ 	int chidx;
+@@ -1166,7 +1166,7 @@ isdn_read(struct file *file, char __user *buf, size_t count, loff_t * off)
+ static ssize_t
+ isdn_write(struct file *file, const char __user *buf, size_t count, loff_t * off)
+ {
+-	uint minor = iminor(file->f_dentry->d_inode);
++	uint minor = iminor(file->f_path.dentry->d_inode);
+ 	int drvidx;
+ 	int chidx;
+ 	int retval;
+@@ -1228,7 +1228,7 @@ static unsigned int
+ isdn_poll(struct file *file, poll_table * wait)
+ {
+ 	unsigned int mask = 0;
+-	unsigned int minor = iminor(file->f_dentry->d_inode);
++	unsigned int minor = iminor(file->f_path.dentry->d_inode);
+ 	int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
+ 
+ 	lock_kernel();
+diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
+index 119412d6bd15..175199088bf4 100644
+--- a/drivers/isdn/i4l/isdn_ppp.c
++++ b/drivers/isdn/i4l/isdn_ppp.c
+@@ -667,7 +667,7 @@ isdn_ppp_poll(struct file *file, poll_table * wait)
+ 
+ 	if (is->debug & 0x2)
+ 		printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n",
+-				iminor(file->f_dentry->d_inode));
++				iminor(file->f_path.dentry->d_inode));
+ 
+ 	/* just registers wait_queue hook. This doesn't really wait. */
+ 	poll_wait(file, &is->wq, wait);

commit b23463b9b94a00baf4cc3cf835c366cffff715c2
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:13 2006 -0800
+
+    [PATCH] struct path: convert isapnp
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/pnp/isapnp/proc.c b/drivers/pnp/isapnp/proc.c
+index 958c11bedd0d..d21f3c1e72fc 100644
+--- a/drivers/pnp/isapnp/proc.c
++++ b/drivers/pnp/isapnp/proc.c
+@@ -56,7 +56,7 @@ static loff_t isapnp_proc_bus_lseek(struct file *file, loff_t off, int whence)
+ 
+ static ssize_t isapnp_proc_bus_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+ {
+-	struct inode *ino = file->f_dentry->d_inode;
++	struct inode *ino = file->f_path.dentry->d_inode;
+ 	struct proc_dir_entry *dp = PDE(ino);
+ 	struct pnp_dev *dev = dp->data;
+ 	int pos = *ppos;

commit 780884144248cbb6945b191c9867741bb8c0ad35
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:12 2006 -0800
+
+    [PATCH] struct path: convert ipmi
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
+index 375d3378eecd..e257835a9a73 100644
+--- a/drivers/char/ipmi/ipmi_devintf.c
++++ b/drivers/char/ipmi/ipmi_devintf.c
+@@ -798,7 +798,7 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
+ 		if (copy_to_user(precv64, &recv64, sizeof(recv64)))
+ 			return -EFAULT;
+ 
+-		rc = ipmi_ioctl(filep->f_dentry->d_inode, filep,
++		rc = ipmi_ioctl(filep->f_path.dentry->d_inode, filep,
+ 				((cmd == COMPAT_IPMICTL_RECEIVE_MSG)
+ 				 ? IPMICTL_RECEIVE_MSG
+ 				 : IPMICTL_RECEIVE_MSG_TRUNC),
+@@ -815,7 +815,7 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
+ 		return rc;
+ 	}
+ 	default:
+-		return ipmi_ioctl(filep->f_dentry->d_inode, filep, cmd, arg);
++		return ipmi_ioctl(filep->f_path.dentry->d_inode, filep, cmd, arg);
+ 	}
+ }
+ #endif

commit 6d63079adde80bb549528371e6407f88e9d27bc3
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:11 2006 -0800
+
+    [PATCH] struct path: convert ipc
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/ipc/mqueue.c b/ipc/mqueue.c
+index 3acc1661e517..02717f71d8d0 100644
+--- a/ipc/mqueue.c
++++ b/ipc/mqueue.c
+@@ -322,7 +322,7 @@ static int mqueue_unlink(struct inode *dir, struct dentry *dentry)
+ static ssize_t mqueue_read_file(struct file *filp, char __user *u_data,
+ 				size_t count, loff_t * off)
+ {
+-	struct mqueue_inode_info *info = MQUEUE_I(filp->f_dentry->d_inode);
++	struct mqueue_inode_info *info = MQUEUE_I(filp->f_path.dentry->d_inode);
+ 	char buffer[FILENT_SIZE];
+ 	size_t slen;
+ 	loff_t o;
+@@ -354,13 +354,13 @@ static ssize_t mqueue_read_file(struct file *filp, char __user *u_data,
+ 		return -EFAULT;
+ 
+ 	*off = o + count;
+-	filp->f_dentry->d_inode->i_atime = filp->f_dentry->d_inode->i_ctime = CURRENT_TIME;
++	filp->f_path.dentry->d_inode->i_atime = filp->f_path.dentry->d_inode->i_ctime = CURRENT_TIME;
+ 	return count;
+ }
+ 
+ static int mqueue_flush_file(struct file *filp, fl_owner_t id)
+ {
+-	struct mqueue_inode_info *info = MQUEUE_I(filp->f_dentry->d_inode);
++	struct mqueue_inode_info *info = MQUEUE_I(filp->f_path.dentry->d_inode);
+ 
+ 	spin_lock(&info->lock);
+ 	if (task_tgid(current) == info->notify_owner)
+@@ -372,7 +372,7 @@ static int mqueue_flush_file(struct file *filp, fl_owner_t id)
+ 
+ static unsigned int mqueue_poll_file(struct file *filp, struct poll_table_struct *poll_tab)
+ {
+-	struct mqueue_inode_info *info = MQUEUE_I(filp->f_dentry->d_inode);
++	struct mqueue_inode_info *info = MQUEUE_I(filp->f_path.dentry->d_inode);
+ 	int retval = 0;
+ 
+ 	poll_wait(filp, &info->wait_q, poll_tab);
+@@ -836,7 +836,7 @@ asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
+ 	if (unlikely(!filp))
+ 		goto out;
+ 
+-	inode = filp->f_dentry->d_inode;
++	inode = filp->f_path.dentry->d_inode;
+ 	if (unlikely(filp->f_op != &mqueue_file_operations))
+ 		goto out_fput;
+ 	info = MQUEUE_I(inode);
+@@ -919,7 +919,7 @@ asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
+ 	if (unlikely(!filp))
+ 		goto out;
+ 
+-	inode = filp->f_dentry->d_inode;
++	inode = filp->f_path.dentry->d_inode;
+ 	if (unlikely(filp->f_op != &mqueue_file_operations))
+ 		goto out_fput;
+ 	info = MQUEUE_I(inode);
+@@ -1056,7 +1056,7 @@ asmlinkage long sys_mq_notify(mqd_t mqdes,
+ 	if (!filp)
+ 		goto out;
+ 
+-	inode = filp->f_dentry->d_inode;
++	inode = filp->f_path.dentry->d_inode;
+ 	if (unlikely(filp->f_op != &mqueue_file_operations))
+ 		goto out_fput;
+ 	info = MQUEUE_I(inode);
+@@ -1126,7 +1126,7 @@ asmlinkage long sys_mq_getsetattr(mqd_t mqdes,
+ 	if (!filp)
+ 		goto out;
+ 
+-	inode = filp->f_dentry->d_inode;
++	inode = filp->f_path.dentry->d_inode;
+ 	if (unlikely(filp->f_op != &mqueue_file_operations))
+ 		goto out_fput;
+ 	info = MQUEUE_I(inode);
+diff --git a/ipc/shm.c b/ipc/shm.c
+index d1198dd07a1a..6d16bb6de7d2 100644
+--- a/ipc/shm.c
++++ b/ipc/shm.c
+@@ -168,7 +168,7 @@ static inline void shm_inc(struct ipc_namespace *ns, int id)
+ static void shm_open(struct vm_area_struct *shmd)
+ {
+ 	shm_inc(shm_file_ns(shmd->vm_file),
+-			shmd->vm_file->f_dentry->d_inode->i_ino);
++			shmd->vm_file->f_path.dentry->d_inode->i_ino);
+ }
+ 
+ /*
+@@ -187,7 +187,7 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
+ 	if (!is_file_hugepages(shp->shm_file))
+ 		shmem_lock(shp->shm_file, 0, shp->mlock_user);
+ 	else
+-		user_shm_unlock(shp->shm_file->f_dentry->d_inode->i_size,
++		user_shm_unlock(shp->shm_file->f_path.dentry->d_inode->i_size,
+ 						shp->mlock_user);
+ 	fput (shp->shm_file);
+ 	security_shm_free(shp);
+@@ -203,7 +203,7 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
+ static void shm_close (struct vm_area_struct *shmd)
+ {
+ 	struct file * file = shmd->vm_file;
+-	int id = file->f_dentry->d_inode->i_ino;
++	int id = file->f_path.dentry->d_inode->i_ino;
+ 	struct shmid_kernel *shp;
+ 	struct ipc_namespace *ns;
+ 
+@@ -233,7 +233,7 @@ static int shm_mmap(struct file * file, struct vm_area_struct * vma)
+ 		vma->vm_ops = &shm_vm_ops;
+ 		if (!(vma->vm_flags & VM_WRITE))
+ 			vma->vm_flags &= ~VM_MAYWRITE;
+-		shm_inc(shm_file_ns(file), file->f_dentry->d_inode->i_ino);
++		shm_inc(shm_file_ns(file), file->f_path.dentry->d_inode->i_ino);
+ 	}
+ 
+ 	return ret;
+@@ -330,7 +330,7 @@ static int newseg (struct ipc_namespace *ns, key_t key, int shmflg, size_t size)
+ 	shp->shm_nattch = 0;
+ 	shp->id = shm_buildid(ns, id, shp->shm_perm.seq);
+ 	shp->shm_file = file;
+-	file->f_dentry->d_inode->i_ino = shp->id;
++	file->f_path.dentry->d_inode->i_ino = shp->id;
+ 
+ 	shm_file_ns(file) = get_ipc_ns(ns);
+ 
+@@ -495,7 +495,7 @@ static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss,
+ 		if(!shp)
+ 			continue;
+ 
+-		inode = shp->shm_file->f_dentry->d_inode;
++		inode = shp->shm_file->f_path.dentry->d_inode;
+ 
+ 		if (is_file_hugepages(shp->shm_file)) {
+ 			struct address_space *mapping = inode->i_mapping;
+@@ -843,7 +843,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
+ 	}
+ 		
+ 	file = shp->shm_file;
+-	size = i_size_read(file->f_dentry->d_inode);
++	size = i_size_read(file->f_path.dentry->d_inode);
+ 	shp->shm_nattch++;
+ 	shm_unlock(shp);
+ 
+@@ -948,7 +948,7 @@ asmlinkage long sys_shmdt(char __user *shmaddr)
+ 			(vma->vm_start - addr)/PAGE_SIZE == vma->vm_pgoff) {
+ 
+ 
+-			size = vma->vm_file->f_dentry->d_inode->i_size;
++			size = vma->vm_file->f_path.dentry->d_inode->i_size;
+ 			do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start);
+ 			/*
+ 			 * We discovered the size of the shm segment, so

commit 1cfd6e648b5ea21b0d48bf6f18b129e4576557d5
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:10 2006 -0800
+
+    [PATCH] struct path: convert infiniband
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
+index 4e16314e8e6d..a617ca7b6923 100644
+--- a/drivers/infiniband/core/uverbs_main.c
++++ b/drivers/infiniband/core/uverbs_main.c
+@@ -534,9 +534,9 @@ struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
+ 	 * module reference.
+ 	 */
+ 	filp->f_op 	   = fops_get(&uverbs_event_fops);
+-	filp->f_vfsmnt 	   = mntget(uverbs_event_mnt);
+-	filp->f_dentry 	   = dget(uverbs_event_mnt->mnt_root);
+-	filp->f_mapping    = filp->f_dentry->d_inode->i_mapping;
++	filp->f_path.mnt 	   = mntget(uverbs_event_mnt);
++	filp->f_path.dentry 	   = dget(uverbs_event_mnt->mnt_root);
++	filp->f_mapping    = filp->f_path.dentry->d_inode->i_mapping;
+ 	filp->f_flags      = O_RDONLY;
+ 	filp->f_mode       = FMODE_READ;
+ 	filp->private_data = ev_file;
+diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
+index a9ddc6911f66..340f27e3ebff 100644
+--- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
++++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
+@@ -1745,9 +1745,9 @@ static int ipath_assign_port(struct file *fp,
+ 		goto done;
+ 	}
+ 
+-	i_minor = iminor(fp->f_dentry->d_inode) - IPATH_USER_MINOR_BASE;
++	i_minor = iminor(fp->f_path.dentry->d_inode) - IPATH_USER_MINOR_BASE;
+ 	ipath_cdbg(VERBOSE, "open on dev %lx (minor %d)\n",
+-		   (long)fp->f_dentry->d_inode->i_rdev, i_minor);
++		   (long)fp->f_path.dentry->d_inode->i_rdev, i_minor);
+ 
+ 	if (i_minor)
+ 		ret = find_free_port(i_minor - 1, fp, uinfo);
+diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
+index d9ff283f725e..79a60f020a21 100644
+--- a/drivers/infiniband/hw/ipath/ipath_fs.c
++++ b/drivers/infiniband/hw/ipath/ipath_fs.c
+@@ -118,7 +118,7 @@ static ssize_t atomic_counters_read(struct file *file, char __user *buf,
+ 	u16 i;
+ 	struct ipath_devdata *dd;
+ 
+-	dd = file->f_dentry->d_inode->i_private;
++	dd = file->f_path.dentry->d_inode->i_private;
+ 
+ 	for (i = 0; i < NUM_COUNTERS; i++)
+ 		counters[i] = ipath_snap_cntr(dd, i);
+@@ -138,7 +138,7 @@ static ssize_t atomic_node_info_read(struct file *file, char __user *buf,
+ 	struct ipath_devdata *dd;
+ 	u64 guid;
+ 
+-	dd = file->f_dentry->d_inode->i_private;
++	dd = file->f_path.dentry->d_inode->i_private;
+ 
+ 	guid = be64_to_cpu(dd->ipath_guid);
+ 
+@@ -177,7 +177,7 @@ static ssize_t atomic_port_info_read(struct file *file, char __user *buf,
+ 	u32 tmp, tmp2;
+ 	struct ipath_devdata *dd;
+ 
+-	dd = file->f_dentry->d_inode->i_private;
++	dd = file->f_path.dentry->d_inode->i_private;
+ 
+ 	/* so we only initialize non-zero fields. */
+ 	memset(portinfo, 0, sizeof portinfo);
+@@ -324,7 +324,7 @@ static ssize_t flash_read(struct file *file, char __user *buf,
+ 		goto bail;
+ 	}
+ 
+-	dd = file->f_dentry->d_inode->i_private;
++	dd = file->f_path.dentry->d_inode->i_private;
+ 	if (ipath_eeprom_read(dd, pos, tmp, count)) {
+ 		ipath_dev_err(dd, "failed to read from flash\n");
+ 		ret = -ENXIO;
+@@ -377,7 +377,7 @@ static ssize_t flash_write(struct file *file, const char __user *buf,
+ 		goto bail_tmp;
+ 	}
+ 
+-	dd = file->f_dentry->d_inode->i_private;
++	dd = file->f_path.dentry->d_inode->i_private;
+ 	if (ipath_eeprom_write(dd, pos, tmp, count)) {
+ 		ret = -ENXIO;
+ 		ipath_dev_err(dd, "failed to write to flash\n");

commit 4db61081fac72623eb638f918819046361ff1508
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:10 2006 -0800
+
+    [PATCH] struct path: convert ieee1394
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
+index af4a78a8ef3b..536ba3f580fd 100644
+--- a/drivers/ieee1394/ieee1394_core.h
++++ b/drivers/ieee1394/ieee1394_core.h
+@@ -217,7 +217,7 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
+ /* return the index (within a minor number block) of a file */
+ static inline unsigned char ieee1394_file_to_instance(struct file *file)
+ {
+-	return file->f_dentry->d_inode->i_cindex;
++	return file->f_path.dentry->d_inode->i_cindex;
+ }
+ 
+ extern int hpsb_disable_irm;

commit b66ffad90429a2ed84c6e8954d205539f6cc86a9
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:09 2006 -0800
+
+    [PATCH] struct path: convert ia64
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
+index a4a6e1463af8..957681c39ad9 100644
+--- a/arch/ia64/ia32/sys_ia32.c
++++ b/arch/ia64/ia32/sys_ia32.c
+@@ -235,7 +235,7 @@ mmap_subpage (struct file *file, unsigned long start, unsigned long end, int pro
+ 
+ 	if (!(flags & MAP_ANONYMOUS)) {
+ 		/* read the file contents */
+-		inode = file->f_dentry->d_inode;
++		inode = file->f_path.dentry->d_inode;
+ 		if (!inode->i_fop || !file->f_op->read
+ 		    || ((*file->f_op->read)(file, (char __user *) start, end - start, &off) < 0))
+ 		{
+@@ -837,7 +837,7 @@ emulate_mmap (struct file *file, unsigned long start, unsigned long len, int pro
+ 
+ 	if (!is_congruent) {
+ 		/* read the file contents */
+-		inode = file->f_dentry->d_inode;
++		inode = file->f_path.dentry->d_inode;
+ 		if (!inode->i_fop || !file->f_op->read
+ 		    || ((*file->f_op->read)(file, (char __user *) pstart, pend - pstart, &poff)
+ 			< 0))
+diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
+index dbb28164b19b..aa94f60fa8e7 100644
+--- a/arch/ia64/kernel/perfmon.c
++++ b/arch/ia64/kernel/perfmon.c
+@@ -2188,13 +2188,13 @@ pfm_alloc_fd(struct file **cfile)
+ 	/*
+ 	 * allocate a new dcache entry
+ 	 */
+-	file->f_dentry = d_alloc(pfmfs_mnt->mnt_sb->s_root, &this);
+-	if (!file->f_dentry) goto out;
++	file->f_path.dentry = d_alloc(pfmfs_mnt->mnt_sb->s_root, &this);
++	if (!file->f_path.dentry) goto out;
+ 
+-	file->f_dentry->d_op = &pfmfs_dentry_operations;
++	file->f_path.dentry->d_op = &pfmfs_dentry_operations;
+ 
+-	d_add(file->f_dentry, inode);
+-	file->f_vfsmnt = mntget(pfmfs_mnt);
++	d_add(file->f_path.dentry, inode);
++	file->f_path.mnt = mntget(pfmfs_mnt);
+ 	file->f_mapping = inode->i_mapping;
+ 
+ 	file->f_op    = &pfm_file_ops;
+diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
+index fd607ca51a8d..e375a2f0f2c3 100644
+--- a/arch/ia64/kernel/salinfo.c
++++ b/arch/ia64/kernel/salinfo.c
+@@ -302,7 +302,7 @@ salinfo_event_open(struct inode *inode, struct file *file)
+ static ssize_t
+ salinfo_event_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	struct proc_dir_entry *entry = PDE(inode);
+ 	struct salinfo_data *data = entry->data;
+ 	char cmd[32];
+@@ -464,7 +464,7 @@ salinfo_log_new_read(int cpu, struct salinfo_data *data)
+ static ssize_t
+ salinfo_log_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	struct proc_dir_entry *entry = PDE(inode);
+ 	struct salinfo_data *data = entry->data;
+ 	u8 *buf;
+@@ -525,7 +525,7 @@ salinfo_log_clear(struct salinfo_data *data, int cpu)
+ static ssize_t
+ salinfo_log_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	struct proc_dir_entry *entry = PDE(inode);
+ 	struct salinfo_data *data = entry->data;
+ 	char cmd[32];

commit cba0a128434f1fae6f90ba9f1fedf18be7abcf48
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:08 2006 -0800
+
+    [PATCH] struct path: convert i2c-drivers
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
+index 94a4e9a3013c..2e22a2ffa606 100644
+--- a/drivers/i2c/i2c-dev.c
++++ b/drivers/i2c/i2c-dev.c
+@@ -119,7 +119,7 @@ static ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count,
+ 		return -ENOMEM;
+ 
+ 	pr_debug("i2c-dev: i2c-%d reading %zd bytes.\n",
+-		iminor(file->f_dentry->d_inode), count);
++		iminor(file->f_path.dentry->d_inode), count);
+ 
+ 	ret = i2c_master_recv(client,tmp,count);
+ 	if (ret >= 0)
+@@ -147,7 +147,7 @@ static ssize_t i2cdev_write (struct file *file, const char __user *buf, size_t c
+ 	}
+ 
+ 	pr_debug("i2c-dev: i2c-%d writing %zd bytes.\n",
+-		iminor(file->f_dentry->d_inode), count);
++		iminor(file->f_path.dentry->d_inode), count);
+ 
+ 	ret = i2c_master_send(client,tmp,count);
+ 	kfree(tmp);

commit b39424e274a17c9c3233c9911dd328b10370de8f
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:07 2006 -0800
+
+    [PATCH] struct path: convert hugetlbfs
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
+index 0706f5aac6a2..ed2c22340ad7 100644
+--- a/fs/hugetlbfs/inode.c
++++ b/fs/hugetlbfs/inode.c
+@@ -58,7 +58,7 @@ static void huge_pagevec_release(struct pagevec *pvec)
+ 
+ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	loff_t len, vma_len;
+ 	int ret;
+ 
+@@ -774,8 +774,8 @@ struct file *hugetlb_zero_setup(size_t size)
+ 	d_instantiate(dentry, inode);
+ 	inode->i_size = size;
+ 	inode->i_nlink = 0;
+-	file->f_vfsmnt = mntget(hugetlbfs_vfsmount);
+-	file->f_dentry = dentry;
++	file->f_path.mnt = mntget(hugetlbfs_vfsmount);
++	file->f_path.dentry = dentry;
+ 	file->f_mapping = inode->i_mapping;
+ 	file->f_op = &hugetlbfs_file_operations;
+ 	file->f_mode = FMODE_WRITE | FMODE_READ;

commit 471b17e7ed0cb29338458eaa09103902891d802a
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:07 2006 -0800
+
+    [PATCH] struct path: convert hppfs
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c
+index 642675fc394a..afd340a45da4 100644
+--- a/fs/hppfs/hppfs_kern.c
++++ b/fs/hppfs/hppfs_kern.c
+@@ -221,7 +221,7 @@ static ssize_t read_proc(struct file *file, char __user *buf, ssize_t count,
+ 	ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
+ 	ssize_t n;
+ 
+-	read = file->f_dentry->d_inode->i_fop->read;
++	read = file->f_path.dentry->d_inode->i_fop->read;
+ 
+ 	if(!is_user)
+ 		set_fs(KERNEL_DS);
+@@ -320,7 +320,7 @@ static ssize_t hppfs_write(struct file *file, const char __user *buf, size_t len
+ 	ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
+ 	int err;
+ 
+-	write = proc_file->f_dentry->d_inode->i_fop->write;
++	write = proc_file->f_path.dentry->d_inode->i_fop->write;
+ 
+ 	proc_file->f_pos = file->f_pos;
+ 	err = (*write)(proc_file, buf, len, &proc_file->f_pos);
+@@ -464,7 +464,7 @@ static int hppfs_open(struct inode *inode, struct file *file)
+ 	if(data == NULL)
+ 		goto out;
+ 
+-	host_file = dentry_name(file->f_dentry, strlen("/rw"));
++	host_file = dentry_name(file->f_path.dentry, strlen("/rw"));
+ 	if(host_file == NULL)
+ 		goto out_free2;
+ 
+@@ -547,7 +547,7 @@ static loff_t hppfs_llseek(struct file *file, loff_t off, int where)
+ 	loff_t (*llseek)(struct file *, loff_t, int);
+ 	loff_t ret;
+ 
+-	llseek = proc_file->f_dentry->d_inode->i_fop->llseek;
++	llseek = proc_file->f_path.dentry->d_inode->i_fop->llseek;
+ 	if(llseek != NULL){
+ 		ret = (*llseek)(proc_file, off, where);
+ 		if(ret < 0)
+@@ -591,10 +591,10 @@ static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir)
+ 	struct hppfs_dirent dirent = ((struct hppfs_dirent)
+ 		                      { .vfs_dirent  	= ent,
+ 					.filldir 	= filldir,
+-					.dentry  	= file->f_dentry } );
++					.dentry  	= file->f_path.dentry } );
+ 	int err;
+ 
+-	readdir = proc_file->f_dentry->d_inode->i_fop->readdir;
++	readdir = proc_file->f_path.dentry->d_inode->i_fop->readdir;
+ 
+ 	proc_file->f_pos = file->f_pos;
+ 	err = (*readdir)(proc_file, &dirent, hppfs_filldir);

commit 575800b3ccd51246f6bac3a07e253f72a61d74b9
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:06 2006 -0800
+
+    [PATCH] struct path: convert hpfs
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c
+index 594f9c428fc2..6916c41d7017 100644
+--- a/fs/hpfs/dir.c
++++ b/fs/hpfs/dir.c
+@@ -24,7 +24,7 @@ static loff_t hpfs_dir_lseek(struct file *filp, loff_t off, int whence)
+ 	loff_t new_off = off + (whence == 1 ? filp->f_pos : 0);
+ 	loff_t pos;
+ 	struct quad_buffer_head qbh;
+-	struct inode *i = filp->f_dentry->d_inode;
++	struct inode *i = filp->f_path.dentry->d_inode;
+ 	struct hpfs_inode_info *hpfs_inode = hpfs_i(i);
+ 	struct super_block *s = i->i_sb;
+ 
+@@ -52,7 +52,7 @@ static loff_t hpfs_dir_lseek(struct file *filp, loff_t off, int whence)
+ 
+ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ {
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct hpfs_inode_info *hpfs_inode = hpfs_i(inode);
+ 	struct quad_buffer_head qbh;
+ 	struct hpfs_dirent *de;
+diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
+index 8b94d24855f0..fb4c8915010a 100644
+--- a/fs/hpfs/file.c
++++ b/fs/hpfs/file.c
+@@ -115,7 +115,7 @@ static ssize_t hpfs_file_write(struct file *file, const char __user *buf,
+ 
+ 	retval = do_sync_write(file, buf, count, ppos);
+ 	if (retval > 0)
+-		hpfs_i(file->f_dentry->d_inode)->i_dirty = 1;
++		hpfs_i(file->f_path.dentry->d_inode)->i_dirty = 1;
+ 	return retval;
+ }
+ 

commit 680b0da9b10d97ddf3c325bf03ae8425ebf4fdec
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:05 2006 -0800
+
+    [PATCH] struct path: convert hostfs
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
+index b6bd33ca3731..1e6fc3799876 100644
+--- a/fs/hostfs/hostfs_kern.c
++++ b/fs/hostfs/hostfs_kern.c
+@@ -35,7 +35,7 @@ static inline struct hostfs_inode_info *HOSTFS_I(struct inode *inode)
+ 	return(list_entry(inode, struct hostfs_inode_info, vfs_inode));
+ }
+ 
+-#define FILE_HOSTFS_I(file) HOSTFS_I((file)->f_dentry->d_inode)
++#define FILE_HOSTFS_I(file) HOSTFS_I((file)->f_path.dentry->d_inode)
+ 
+ int hostfs_d_delete(struct dentry *dentry)
+ {
+@@ -325,7 +325,7 @@ int hostfs_readdir(struct file *file, void *ent, filldir_t filldir)
+ 	unsigned long long next, ino;
+ 	int error, len;
+ 
+-	name = dentry_name(file->f_dentry, 0);
++	name = dentry_name(file->f_path.dentry, 0);
+ 	if(name == NULL) return(-ENOMEM);
+ 	dir = open_dir(name, &error);
+ 	kfree(name);
+@@ -366,7 +366,7 @@ int hostfs_file_open(struct inode *ino, struct file *file)
+ 	if(w)
+ 		r = 1;
+ 
+-	name = dentry_name(file->f_dentry, 0);
++	name = dentry_name(file->f_path.dentry, 0);
+ 	if(name == NULL)
+ 		return(-ENOMEM);
+ 

commit f44ea03102a021b9c36cc82c7b6312cd23f23b3d
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:04 2006 -0800
+
+    [PATCH] struct path: convert hfsplus
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
+index 7e309751645f..e886ac8460d3 100644
+--- a/fs/hfsplus/dir.c
++++ b/fs/hfsplus/dir.c
+@@ -111,7 +111,7 @@ static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry,
+ 
+ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ {
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct super_block *sb = inode->i_sb;
+ 	int len, err;
+ 	char strbuf[HFSPLUS_MAX_STRLEN + 1];
+diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
+index 9e3675249633..75e8c4d8aac3 100644
+--- a/fs/hfsplus/inode.c
++++ b/fs/hfsplus/inode.c
+@@ -97,7 +97,7 @@ static ssize_t hfsplus_direct_IO(int rw, struct kiocb *iocb,
+ 		const struct iovec *iov, loff_t offset, unsigned long nr_segs)
+ {
+ 	struct file *file = iocb->ki_filp;
+-	struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
++	struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host;
+ 
+ 	return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
+ 				  offset, nr_segs, hfsplus_get_block, NULL);

commit c528896004793065b5ffd710e1cd844603ad8518
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:04 2006 -0800
+
+    [PATCH] struct path: convert hfs
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
+index 37d681b4f216..e2e0358da335 100644
+--- a/fs/hfs/dir.c
++++ b/fs/hfs/dir.c
+@@ -53,7 +53,7 @@ static struct dentry *hfs_lookup(struct inode *dir, struct dentry *dentry,
+  */
+ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ {
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct super_block *sb = inode->i_sb;
+ 	int len, err;
+ 	char strbuf[HFS_MAX_NAMELEN];
+diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
+index 02f5573e0349..5cb7f8fee8d6 100644
+--- a/fs/hfs/inode.c
++++ b/fs/hfs/inode.c
+@@ -102,7 +102,7 @@ static ssize_t hfs_direct_IO(int rw, struct kiocb *iocb,
+ 		const struct iovec *iov, loff_t offset, unsigned long nr_segs)
+ {
+ 	struct file *file = iocb->ki_filp;
+-	struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
++	struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host;
+ 
+ 	return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
+ 				  offset, nr_segs, hfs_get_block, NULL);

commit 81454098f7c54118d290cd503bda2a41e3ac43fb
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:03 2006 -0800
+
+    [PATCH] struct path: convert gfs2
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
+index b3f1e0349ae0..faa07e4b97d0 100644
+--- a/fs/gfs2/ops_file.c
++++ b/fs/gfs2/ops_file.c
+@@ -247,7 +247,7 @@ static const u32 gfs2_to_fsflags[32] = {
+ 
+ static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
+ {
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct gfs2_inode *ip = GFS2_I(inode);
+ 	struct gfs2_holder gh;
+ 	int error;
+@@ -305,7 +305,7 @@ void gfs2_set_inode_flags(struct inode *inode)
+  */
+ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
+ {
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct gfs2_inode *ip = GFS2_I(inode);
+ 	struct gfs2_sbd *sdp = GFS2_SB(inode);
+ 	struct buffer_head *bh;
+@@ -588,7 +588,7 @@ static int do_flock(struct file *file, int cmd, struct file_lock *fl)
+ {
+ 	struct gfs2_file *fp = file->private_data;
+ 	struct gfs2_holder *fl_gh = &fp->f_fl_gh;
+-	struct gfs2_inode *ip = GFS2_I(file->f_dentry->d_inode);
++	struct gfs2_inode *ip = GFS2_I(file->f_path.dentry->d_inode);
+ 	struct gfs2_glock *gl;
+ 	unsigned int state;
+ 	int flags;

commit 7706a9d6183da7701a9bca7155bccfcd182c670a
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:02 2006 -0800
+
+    [PATCH] struct path: convert fuse
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/fuse/control.c b/fs/fuse/control.c
+index 16b39c053d47..8c58bd453993 100644
+--- a/fs/fuse/control.c
++++ b/fs/fuse/control.c
+@@ -23,7 +23,7 @@ static struct fuse_conn *fuse_ctl_file_conn_get(struct file *file)
+ {
+ 	struct fuse_conn *fc;
+ 	mutex_lock(&fuse_mutex);
+-	fc = file->f_dentry->d_inode->i_private;
++	fc = file->f_path.dentry->d_inode->i_private;
+ 	if (fc)
+ 		fc = fuse_conn_get(fc);
+ 	mutex_unlock(&fuse_mutex);
+diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
+index 1cabdb229adb..40080477ceb4 100644
+--- a/fs/fuse/dir.c
++++ b/fs/fuse/dir.c
+@@ -856,7 +856,7 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
+ 	int err;
+ 	size_t nbytes;
+ 	struct page *page;
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	struct fuse_conn *fc = get_fuse_conn(inode);
+ 	struct fuse_req *req;
+ 
+diff --git a/fs/fuse/file.c b/fs/fuse/file.c
+index 128f79c40803..1387749201b3 100644
+--- a/fs/fuse/file.c
++++ b/fs/fuse/file.c
+@@ -141,8 +141,8 @@ int fuse_release_common(struct inode *inode, struct file *file, int isdir)
+ 					isdir ? FUSE_RELEASEDIR : FUSE_RELEASE);
+ 
+ 		/* Hold vfsmount and dentry until release is finished */
+-		req->vfsmount = mntget(file->f_vfsmnt);
+-		req->dentry = dget(file->f_dentry);
++		req->vfsmount = mntget(file->f_path.mnt);
++		req->dentry = dget(file->f_path.dentry);
+ 		request_send_background(fc, req);
+ 	}
+ 
+@@ -184,7 +184,7 @@ static u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id)
+ 
+ static int fuse_flush(struct file *file, fl_owner_t id)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	struct fuse_conn *fc = get_fuse_conn(inode);
+ 	struct fuse_file *ff = file->private_data;
+ 	struct fuse_req *req;
+@@ -533,7 +533,7 @@ static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf,
+ static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
+ 			      size_t count, loff_t *ppos, int write)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	struct fuse_conn *fc = get_fuse_conn(inode);
+ 	size_t nmax = write ? fc->max_write : fc->max_read;
+ 	loff_t pos = *ppos;
+@@ -607,7 +607,7 @@ static ssize_t fuse_direct_read(struct file *file, char __user *buf,
+ static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
+ 				 size_t count, loff_t *ppos)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	ssize_t res;
+ 	/* Don't allow parallel writes to the same file */
+ 	mutex_lock(&inode->i_mutex);
+@@ -662,7 +662,7 @@ static int convert_fuse_file_lock(const struct fuse_file_lock *ffl,
+ static void fuse_lk_fill(struct fuse_req *req, struct file *file,
+ 			 const struct file_lock *fl, int opcode, pid_t pid)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	struct fuse_conn *fc = get_fuse_conn(inode);
+ 	struct fuse_file *ff = file->private_data;
+ 	struct fuse_lk_in *arg = &req->misc.lk_in;
+@@ -682,7 +682,7 @@ static void fuse_lk_fill(struct fuse_req *req, struct file *file,
+ 
+ static int fuse_getlk(struct file *file, struct file_lock *fl)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	struct fuse_conn *fc = get_fuse_conn(inode);
+ 	struct fuse_req *req;
+ 	struct fuse_lk_out outarg;
+@@ -707,7 +707,7 @@ static int fuse_getlk(struct file *file, struct file_lock *fl)
+ 
+ static int fuse_setlk(struct file *file, struct file_lock *fl)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	struct fuse_conn *fc = get_fuse_conn(inode);
+ 	struct fuse_req *req;
+ 	int opcode = (fl->fl_flags & FL_SLEEP) ? FUSE_SETLKW : FUSE_SETLK;
+@@ -734,7 +734,7 @@ static int fuse_setlk(struct file *file, struct file_lock *fl)
+ 
+ static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	struct fuse_conn *fc = get_fuse_conn(inode);
+ 	int err;
+ 

commit 1f70ceccb8e9159118c1ac65a245b16406d9e721
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:01 2006 -0800
+
+    [PATCH] struct path: convert frv
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/frv/mm/elf-fdpic.c b/arch/frv/mm/elf-fdpic.c
+index f5a653033fe0..9477ccce070e 100644
+--- a/arch/frv/mm/elf-fdpic.c
++++ b/arch/frv/mm/elf-fdpic.c
+@@ -110,14 +110,14 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
+ 
+ #if 0
+ 	printk("[area] l=%lx (ENOMEM) f='%s'\n",
+-	       len, filp ? filp->f_dentry->d_name.name : "");
++	       len, filp ? filp->f_path.dentry->d_name.name : "");
+ #endif
+ 	return -ENOMEM;
+ 
+  success:
+ #if 0
+ 	printk("[area] l=%lx ad=%lx f='%s'\n",
+-	       len, addr, filp ? filp->f_dentry->d_name.name : "");
++	       len, addr, filp ? filp->f_path.dentry->d_name.name : "");
+ #endif
+ 	return addr;
+ } /* end arch_get_unmapped_area() */

commit 6a90cd248deca1ceaf417c9a04bf3be6026e7a64
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:01 2006 -0800
+
+    [PATCH] struct path: convert freevxfs
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
+index 43886fa00a2a..3995d7fbedab 100644
+--- a/fs/freevxfs/vxfs_lookup.c
++++ b/fs/freevxfs/vxfs_lookup.c
+@@ -240,7 +240,7 @@ vxfs_lookup(struct inode *dip, struct dentry *dp, struct nameidata *nd)
+ static int
+ vxfs_readdir(struct file *fp, void *retp, filldir_t filler)
+ {
+-	struct inode		*ip = fp->f_dentry->d_inode;
++	struct inode		*ip = fp->f_path.dentry->d_inode;
+ 	struct super_block	*sbp = ip->i_sb;
+ 	u_long			bsize = sbp->s_blocksize;
+ 	u_long			page, npages, block, pblocks, nblocks, offset;

commit 0191f2055cd16a2252219c621329b52d8b67194e
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:37:00 2006 -0800
+
+    [PATCH] struct path: convert efs
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/efs/dir.c b/fs/efs/dir.c
+index 17f5b2d3c16a..b46c488eefc8 100644
+--- a/fs/efs/dir.c
++++ b/fs/efs/dir.c
+@@ -20,7 +20,7 @@ struct inode_operations efs_dir_inode_operations = {
+ };
+ 
+ static int efs_readdir(struct file *filp, void *dirent, filldir_t filldir) {
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct buffer_head *bh;
+ 
+ 	struct efs_dir		*dirblock;

commit cc5ef55fd0d81f70b0afc86817aa1d305fd6aeaa
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:36:59 2006 -0800
+
+    [PATCH] struct path: convert drm
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/char/drm/drm_ioc32.c b/drivers/char/drm/drm_ioc32.c
+index d4f874520082..fafeb34f89d5 100644
+--- a/drivers/char/drm/drm_ioc32.c
++++ b/drivers/char/drm/drm_ioc32.c
+@@ -102,7 +102,7 @@ static int compat_drm_version(struct file *file, unsigned int cmd,
+ 			  &version->desc))
+ 		return -EFAULT;
+ 
+-	err = drm_ioctl(file->f_dentry->d_inode, file,
++	err = drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			DRM_IOCTL_VERSION, (unsigned long)version);
+ 	if (err)
+ 		return err;
+@@ -143,7 +143,7 @@ static int compat_drm_getunique(struct file *file, unsigned int cmd,
+ 			  &u->unique))
+ 		return -EFAULT;
+ 
+-	err = drm_ioctl(file->f_dentry->d_inode, file,
++	err = drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			DRM_IOCTL_GET_UNIQUE, (unsigned long)u);
+ 	if (err)
+ 		return err;
+@@ -172,7 +172,7 @@ static int compat_drm_setunique(struct file *file, unsigned int cmd,
+ 			  &u->unique))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_SET_UNIQUE, (unsigned long)u);
+ }
+ 
+@@ -203,7 +203,7 @@ static int compat_drm_getmap(struct file *file, unsigned int cmd,
+ 	if (__put_user(idx, &map->offset))
+ 		return -EFAULT;
+ 
+-	err = drm_ioctl(file->f_dentry->d_inode, file,
++	err = drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			DRM_IOCTL_GET_MAP, (unsigned long)map);
+ 	if (err)
+ 		return err;
+@@ -244,7 +244,7 @@ static int compat_drm_addmap(struct file *file, unsigned int cmd,
+ 	    || __put_user(m32.flags, &map->flags))
+ 		return -EFAULT;
+ 
+-	err = drm_ioctl(file->f_dentry->d_inode, file,
++	err = drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			DRM_IOCTL_ADD_MAP, (unsigned long)map);
+ 	if (err)
+ 		return err;
+@@ -282,7 +282,7 @@ static int compat_drm_rmmap(struct file *file, unsigned int cmd,
+ 	if (__put_user((void *)(unsigned long)handle, &map->handle))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_RM_MAP, (unsigned long)map);
+ }
+ 
+@@ -312,7 +312,7 @@ static int compat_drm_getclient(struct file *file, unsigned int cmd,
+ 	if (__put_user(idx, &client->idx))
+ 		return -EFAULT;
+ 
+-	err = drm_ioctl(file->f_dentry->d_inode, file,
++	err = drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			DRM_IOCTL_GET_CLIENT, (unsigned long)client);
+ 	if (err)
+ 		return err;
+@@ -349,7 +349,7 @@ static int compat_drm_getstats(struct file *file, unsigned int cmd,
+ 	if (!access_ok(VERIFY_WRITE, stats, sizeof(*stats)))
+ 		return -EFAULT;
+ 
+-	err = drm_ioctl(file->f_dentry->d_inode, file,
++	err = drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			DRM_IOCTL_GET_STATS, (unsigned long)stats);
+ 	if (err)
+ 		return err;
+@@ -393,7 +393,7 @@ static int compat_drm_addbufs(struct file *file, unsigned int cmd,
+ 	    || __put_user(agp_start, &buf->agp_start))
+ 		return -EFAULT;
+ 
+-	err = drm_ioctl(file->f_dentry->d_inode, file,
++	err = drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			DRM_IOCTL_ADD_BUFS, (unsigned long)buf);
+ 	if (err)
+ 		return err;
+@@ -425,7 +425,7 @@ static int compat_drm_markbufs(struct file *file, unsigned int cmd,
+ 	    || __put_user(b32.high_mark, &buf->high_mark))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_MARK_BUFS, (unsigned long)buf);
+ }
+ 
+@@ -467,7 +467,7 @@ static int compat_drm_infobufs(struct file *file, unsigned int cmd,
+ 	    || __put_user(list, &request->list))
+ 		return -EFAULT;
+ 
+-	err = drm_ioctl(file->f_dentry->d_inode, file,
++	err = drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			DRM_IOCTL_INFO_BUFS, (unsigned long)request);
+ 	if (err)
+ 		return err;
+@@ -529,7 +529,7 @@ static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
+ 	    || __put_user(list, &request->list))
+ 		return -EFAULT;
+ 
+-	err = drm_ioctl(file->f_dentry->d_inode, file,
++	err = drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			DRM_IOCTL_MAP_BUFS, (unsigned long)request);
+ 	if (err)
+ 		return err;
+@@ -576,7 +576,7 @@ static int compat_drm_freebufs(struct file *file, unsigned int cmd,
+ 			  &request->list))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_FREE_BUFS, (unsigned long)request);
+ }
+ 
+@@ -603,7 +603,7 @@ static int compat_drm_setsareactx(struct file *file, unsigned int cmd,
+ 			  &request->handle))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_SET_SAREA_CTX, (unsigned long)request);
+ }
+ 
+@@ -626,7 +626,7 @@ static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
+ 	if (__put_user(ctx_id, &request->ctx_id))
+ 		return -EFAULT;
+ 
+-	err = drm_ioctl(file->f_dentry->d_inode, file,
++	err = drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			DRM_IOCTL_GET_SAREA_CTX, (unsigned long)request);
+ 	if (err)
+ 		return err;
+@@ -662,7 +662,7 @@ static int compat_drm_resctx(struct file *file, unsigned int cmd,
+ 			  &res->contexts))
+ 		return -EFAULT;
+ 
+-	err = drm_ioctl(file->f_dentry->d_inode, file,
++	err = drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			DRM_IOCTL_RES_CTX, (unsigned long)res);
+ 	if (err)
+ 		return err;
+@@ -716,7 +716,7 @@ static int compat_drm_dma(struct file *file, unsigned int cmd,
+ 			  &d->request_sizes))
+ 		return -EFAULT;
+ 
+-	err = drm_ioctl(file->f_dentry->d_inode, file,
++	err = drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			DRM_IOCTL_DMA, (unsigned long)d);
+ 	if (err)
+ 		return err;
+@@ -749,7 +749,7 @@ static int compat_drm_agp_enable(struct file *file, unsigned int cmd,
+ 	if (put_user(m32.mode, &mode->mode))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_AGP_ENABLE, (unsigned long)mode);
+ }
+ 
+@@ -779,7 +779,7 @@ static int compat_drm_agp_info(struct file *file, unsigned int cmd,
+ 	if (!access_ok(VERIFY_WRITE, info, sizeof(*info)))
+ 		return -EFAULT;
+ 
+-	err = drm_ioctl(file->f_dentry->d_inode, file,
++	err = drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			DRM_IOCTL_AGP_INFO, (unsigned long)info);
+ 	if (err)
+ 		return err;
+@@ -825,7 +825,7 @@ static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
+ 	    || __put_user(req32.type, &request->type))
+ 		return -EFAULT;
+ 
+-	err = drm_ioctl(file->f_dentry->d_inode, file,
++	err = drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			DRM_IOCTL_AGP_ALLOC, (unsigned long)request);
+ 	if (err)
+ 		return err;
+@@ -833,7 +833,7 @@ static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
+ 	if (__get_user(req32.handle, &request->handle)
+ 	    || __get_user(req32.physical, &request->physical)
+ 	    || copy_to_user(argp, &req32, sizeof(req32))) {
+-		drm_ioctl(file->f_dentry->d_inode, file,
++		drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			  DRM_IOCTL_AGP_FREE, (unsigned long)request);
+ 		return -EFAULT;
+ 	}
+@@ -854,7 +854,7 @@ static int compat_drm_agp_free(struct file *file, unsigned int cmd,
+ 	    || __put_user(handle, &request->handle))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_AGP_FREE, (unsigned long)request);
+ }
+ 
+@@ -879,7 +879,7 @@ static int compat_drm_agp_bind(struct file *file, unsigned int cmd,
+ 	    || __put_user(req32.offset, &request->offset))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_AGP_BIND, (unsigned long)request);
+ }
+ 
+@@ -896,7 +896,7 @@ static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
+ 	    || __put_user(handle, &request->handle))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_AGP_UNBIND, (unsigned long)request);
+ }
+ #endif				/* __OS_HAS_AGP */
+@@ -921,7 +921,7 @@ static int compat_drm_sg_alloc(struct file *file, unsigned int cmd,
+ 	    || __put_user(x, &request->size))
+ 		return -EFAULT;
+ 
+-	err = drm_ioctl(file->f_dentry->d_inode, file,
++	err = drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			DRM_IOCTL_SG_ALLOC, (unsigned long)request);
+ 	if (err)
+ 		return err;
+@@ -948,7 +948,7 @@ static int compat_drm_sg_free(struct file *file, unsigned int cmd,
+ 	    || __put_user(x << PAGE_SHIFT, &request->handle))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_SG_FREE, (unsigned long)request);
+ }
+ 
+@@ -988,7 +988,7 @@ static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
+ 	    || __put_user(req32.request.signal, &request->request.signal))
+ 		return -EFAULT;
+ 
+-	err = drm_ioctl(file->f_dentry->d_inode, file,
++	err = drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			DRM_IOCTL_WAIT_VBLANK, (unsigned long)request);
+ 	if (err)
+ 		return err;
+@@ -1060,7 +1060,7 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 	if (fn != NULL)
+ 		ret = (*fn) (filp, cmd, arg);
+ 	else
+-		ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
++		ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
+ 	unlock_kernel();
+ 
+ 	return ret;
+diff --git a/drivers/char/drm/i915_ioc32.c b/drivers/char/drm/i915_ioc32.c
+index 296248cdc767..1fe68a251b75 100644
+--- a/drivers/char/drm/i915_ioc32.c
++++ b/drivers/char/drm/i915_ioc32.c
+@@ -66,7 +66,7 @@ static int compat_i915_batchbuffer(struct file *file, unsigned int cmd,
+ 			  &batchbuffer->cliprects))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_I915_BATCHBUFFER,
+ 			 (unsigned long)batchbuffer);
+ }
+@@ -102,7 +102,7 @@ static int compat_i915_cmdbuffer(struct file *file, unsigned int cmd,
+ 			  &cmdbuffer->cliprects))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_I915_CMDBUFFER, (unsigned long)cmdbuffer);
+ }
+ 
+@@ -125,7 +125,7 @@ static int compat_i915_irq_emit(struct file *file, unsigned int cmd,
+ 			  &request->irq_seq))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_I915_IRQ_EMIT, (unsigned long)request);
+ }
+ typedef struct drm_i915_getparam32 {
+@@ -149,7 +149,7 @@ static int compat_i915_getparam(struct file *file, unsigned int cmd,
+ 			  &request->value))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_I915_GETPARAM, (unsigned long)request);
+ }
+ 
+@@ -178,7 +178,7 @@ static int compat_i915_alloc(struct file *file, unsigned int cmd,
+ 			  &request->region_offset))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_I915_ALLOC, (unsigned long)request);
+ }
+ 
+@@ -215,7 +215,7 @@ long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 	if (fn != NULL)
+ 		ret = (*fn) (filp, cmd, arg);
+ 	else
+-		ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
++		ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
+ 	unlock_kernel();
+ 
+ 	return ret;
+diff --git a/drivers/char/drm/mga_ioc32.c b/drivers/char/drm/mga_ioc32.c
+index 54a18eb2fc04..30d00478ddee 100644
+--- a/drivers/char/drm/mga_ioc32.c
++++ b/drivers/char/drm/mga_ioc32.c
+@@ -100,7 +100,7 @@ static int compat_mga_init(struct file *file, unsigned int cmd,
+ 	if (err)
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_MGA_INIT, (unsigned long)init);
+ }
+ 
+@@ -125,7 +125,7 @@ static int compat_mga_getparam(struct file *file, unsigned int cmd,
+ 			  &getparam->value))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam);
+ }
+ 
+@@ -166,7 +166,7 @@ static int compat_mga_dma_bootstrap(struct file *file, unsigned int cmd,
+ 	    || __put_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size))
+ 		return -EFAULT;
+ 
+-	err = drm_ioctl(file->f_dentry->d_inode, file,
++	err = drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			DRM_IOCTL_MGA_DMA_BOOTSTRAP,
+ 			(unsigned long)dma_bootstrap);
+ 	if (err)
+@@ -224,7 +224,7 @@ long mga_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 	if (fn != NULL)
+ 		ret = (*fn) (filp, cmd, arg);
+ 	else
+-		ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
++		ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
+ 	unlock_kernel();
+ 
+ 	return ret;
+diff --git a/drivers/char/drm/r128_ioc32.c b/drivers/char/drm/r128_ioc32.c
+index 9dd6d4116e47..d3cb676eee84 100644
+--- a/drivers/char/drm/r128_ioc32.c
++++ b/drivers/char/drm/r128_ioc32.c
+@@ -95,7 +95,7 @@ static int compat_r128_init(struct file *file, unsigned int cmd,
+ 			  &init->agp_textures_offset))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_R128_INIT, (unsigned long)init);
+ }
+ 
+@@ -129,7 +129,7 @@ static int compat_r128_depth(struct file *file, unsigned int cmd,
+ 			  &depth->mask))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_R128_DEPTH, (unsigned long)depth);
+ 
+ }
+@@ -153,7 +153,7 @@ static int compat_r128_stipple(struct file *file, unsigned int cmd,
+ 			  &stipple->mask))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_R128_STIPPLE, (unsigned long)stipple);
+ }
+ 
+@@ -178,7 +178,7 @@ static int compat_r128_getparam(struct file *file, unsigned int cmd,
+ 			  &getparam->value))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_R128_GETPARAM, (unsigned long)getparam);
+ }
+ 
+@@ -214,7 +214,7 @@ long r128_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 	if (fn != NULL)
+ 		ret = (*fn) (filp, cmd, arg);
+ 	else
+-		ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
++		ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
+ 	unlock_kernel();
+ 
+ 	return ret;
+diff --git a/drivers/char/drm/radeon_ioc32.c b/drivers/char/drm/radeon_ioc32.c
+index 0ccfd3618ff1..1f1f9cc055a4 100644
+--- a/drivers/char/drm/radeon_ioc32.c
++++ b/drivers/char/drm/radeon_ioc32.c
+@@ -92,7 +92,7 @@ static int compat_radeon_cp_init(struct file *file, unsigned int cmd,
+ 			  &init->gart_textures_offset))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_RADEON_CP_INIT, (unsigned long)init);
+ }
+ 
+@@ -125,7 +125,7 @@ static int compat_radeon_cp_clear(struct file *file, unsigned int cmd,
+ 			  &clr->depth_boxes))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_RADEON_CLEAR, (unsigned long)clr);
+ }
+ 
+@@ -149,7 +149,7 @@ static int compat_radeon_cp_stipple(struct file *file, unsigned int cmd,
+ 			  &request->mask))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_RADEON_STIPPLE, (unsigned long)request);
+ }
+ 
+@@ -204,7 +204,7 @@ static int compat_radeon_cp_texture(struct file *file, unsigned int cmd,
+ 			  &image->data))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_RADEON_TEXTURE, (unsigned long)request);
+ }
+ 
+@@ -238,7 +238,7 @@ static int compat_radeon_cp_vertex2(struct file *file, unsigned int cmd,
+ 			  &request->prim))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_RADEON_VERTEX2, (unsigned long)request);
+ }
+ 
+@@ -268,7 +268,7 @@ static int compat_radeon_cp_cmdbuf(struct file *file, unsigned int cmd,
+ 			  &request->boxes))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_RADEON_CMDBUF, (unsigned long)request);
+ }
+ 
+@@ -293,7 +293,7 @@ static int compat_radeon_cp_getparam(struct file *file, unsigned int cmd,
+ 			  &request->value))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_RADEON_GETPARAM, (unsigned long)request);
+ }
+ 
+@@ -322,7 +322,7 @@ static int compat_radeon_mem_alloc(struct file *file, unsigned int cmd,
+ 			  &request->region_offset))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_RADEON_ALLOC, (unsigned long)request);
+ }
+ 
+@@ -345,7 +345,7 @@ static int compat_radeon_irq_emit(struct file *file, unsigned int cmd,
+ 			  &request->irq_seq))
+ 		return -EFAULT;
+ 
+-	return drm_ioctl(file->f_dentry->d_inode, file,
++	return drm_ioctl(file->f_path.dentry->d_inode, file,
+ 			 DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long)request);
+ }
+ 
+@@ -386,7 +386,7 @@ long radeon_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 	if (fn != NULL)
+ 		ret = (*fn) (filp, cmd, arg);
+ 	else
+-		ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
++		ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
+ 	unlock_kernel();
+ 
+ 	return ret;

commit d817be9ca8766b521f6195f57281284c5ab0ff4c
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:36:58 2006 -0800
+
+    [PATCH] struct path: convert cris
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/cris/arch-v32/drivers/sync_serial.c b/arch/cris/arch-v32/drivers/sync_serial.c
+index e067806b2208..424eb0eb1cd5 100644
+--- a/arch/cris/arch-v32/drivers/sync_serial.c
++++ b/arch/cris/arch-v32/drivers/sync_serial.c
+@@ -504,7 +504,7 @@ static int sync_serial_release(struct inode *inode, struct file *file)
+ 
+ static unsigned int sync_serial_poll(struct file *file, poll_table *wait)
+ {
+-	int dev = iminor(file->f_dentry->d_inode);
++	int dev = iminor(file->f_path.dentry->d_inode);
+ 	unsigned int mask = 0;
+ 	sync_port* port;
+ 	DEBUGPOLL( static unsigned int prev_mask = 0; );
+@@ -531,7 +531,7 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file,
+ 		  unsigned int cmd, unsigned long arg)
+ {
+ 	int return_val = 0;
+-	int dev = iminor(file->f_dentry->d_inode);
++	int dev = iminor(file->f_path.dentry->d_inode);
+ 	sync_port* port;
+ 	reg_sser_rw_tr_cfg tr_cfg;
+ 	reg_sser_rw_rec_cfg rec_cfg;
+@@ -789,7 +789,7 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file,
+ static ssize_t sync_serial_write(struct file * file, const char * buf,
+                                  size_t count, loff_t *ppos)
+ {
+-	int dev = iminor(file->f_dentry->d_inode);
++	int dev = iminor(file->f_path.dentry->d_inode);
+ 	DECLARE_WAITQUEUE(wait, current);
+ 	sync_port *port;
+ 	unsigned long c, c1;
+@@ -919,7 +919,7 @@ static ssize_t sync_serial_write(struct file * file, const char * buf,
+ static ssize_t sync_serial_read(struct file * file, char * buf,
+ 				size_t count, loff_t *ppos)
+ {
+-	int dev = iminor(file->f_dentry->d_inode);
++	int dev = iminor(file->f_path.dentry->d_inode);
+ 	int avail;
+ 	sync_port *port;
+ 	unsigned char* start;

commit 352d8af748a1bee0935987b811c9fc4693803d99
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:36:58 2006 -0800
+
+    [PATCH] struct path: convert cramfs
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
+index 0509cedd415c..6db03fb089dc 100644
+--- a/fs/cramfs/inode.c
++++ b/fs/cramfs/inode.c
+@@ -338,7 +338,7 @@ static int cramfs_statfs(struct dentry *dentry, struct kstatfs *buf)
+  */
+ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ {
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct super_block *sb = inode->i_sb;
+ 	char *buf;
+ 	unsigned int offset;

commit f04538c38134edf5f424dc24fda6ef46da736734
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:36:57 2006 -0800
+
+    [PATCH] struct path: convert cosa
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
+index e1bf8b93f958..6c7dfb50143f 100644
+--- a/drivers/net/wan/cosa.c
++++ b/drivers/net/wan/cosa.c
+@@ -974,12 +974,12 @@ static int cosa_open(struct inode *inode, struct file *file)
+ 	unsigned long flags;
+ 	int n;
+ 
+-	if ((n=iminor(file->f_dentry->d_inode)>>CARD_MINOR_BITS)
++	if ((n=iminor(file->f_path.dentry->d_inode)>>CARD_MINOR_BITS)
+ 		>= nr_cards)
+ 		return -ENODEV;
+ 	cosa = cosa_cards+n;
+ 
+-	if ((n=iminor(file->f_dentry->d_inode)
++	if ((n=iminor(file->f_path.dentry->d_inode)
+ 		& ((1<= cosa->nchannels)
+ 		return -ENODEV;
+ 	chan = cosa->chan + n;

commit d4176d326d76ddea457a5e42ac8c2e3aed3430b1
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:36:56 2006 -0800
+
+    [PATCH] struct path: convert coda
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/dir.c b/fs/coda/dir.c
+index 0102b28a15fb..0c6f7f3b3dd7 100644
+--- a/fs/coda/dir.c
++++ b/fs/coda/dir.c
+@@ -441,7 +441,7 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
+ /* file operations for directories */
+ int coda_readdir(struct file *coda_file, void *dirent, filldir_t filldir)
+ {
+-	struct dentry *coda_dentry = coda_file->f_dentry;
++	struct dentry *coda_dentry = coda_file->f_path.dentry;
+ 	struct coda_file_info *cfi;
+ 	struct file *host_file;
+ 	struct inode *host_inode;
+@@ -453,7 +453,7 @@ int coda_readdir(struct file *coda_file, void *dirent, filldir_t filldir)
+ 
+ 	coda_vfs_stat.readdir++;
+ 
+-	host_inode = host_file->f_dentry->d_inode;
++	host_inode = host_file->f_path.dentry->d_inode;
+ 	mutex_lock(&host_inode->i_mutex);
+ 	host_file->f_pos = coda_file->f_pos;
+ 
+@@ -544,14 +544,14 @@ static int coda_venus_readdir(struct file *filp, filldir_t filldir,
+ 		/* catch truncated reads */
+ 		if (ret < vdir_size || ret < vdir_size + vdir->d_namlen) {
+ 			printk("coda_venus_readdir: short read: %ld\n",
+-			       filp->f_dentry->d_inode->i_ino);
++			       filp->f_path.dentry->d_inode->i_ino);
+ 			ret = -EBADF;
+ 			break;
+ 		}
+ 		/* validate whether the directory file actually makes sense */
+ 		if (vdir->d_reclen < vdir_size + vdir->d_namlen) {
+ 			printk("coda_venus_readdir: Invalid dir: %ld\n",
+-			       filp->f_dentry->d_inode->i_ino);
++			       filp->f_path.dentry->d_inode->i_ino);
+ 			ret = -EBADF;
+ 			break;
+ 		}
+diff --git a/fs/coda/file.c b/fs/coda/file.c
+index dbfbcfa5b3c0..5ef2b609ec7d 100644
+--- a/fs/coda/file.c
++++ b/fs/coda/file.c
+@@ -66,7 +66,7 @@ coda_file_sendfile(struct file *coda_file, loff_t *ppos, size_t count,
+ static ssize_t
+ coda_file_write(struct file *coda_file, const char __user *buf, size_t count, loff_t *ppos)
+ {
+-	struct inode *host_inode, *coda_inode = coda_file->f_dentry->d_inode;
++	struct inode *host_inode, *coda_inode = coda_file->f_path.dentry->d_inode;
+ 	struct coda_file_info *cfi;
+ 	struct file *host_file;
+ 	ssize_t ret;
+@@ -78,7 +78,7 @@ coda_file_write(struct file *coda_file, const char __user *buf, size_t count, lo
+ 	if (!host_file->f_op || !host_file->f_op->write)
+ 		return -EINVAL;
+ 
+-	host_inode = host_file->f_dentry->d_inode;
++	host_inode = host_file->f_path.dentry->d_inode;
+ 	mutex_lock(&coda_inode->i_mutex);
+ 
+ 	ret = host_file->f_op->write(host_file, buf, count, ppos);
+@@ -106,8 +106,8 @@ coda_file_mmap(struct file *coda_file, struct vm_area_struct *vma)
+ 	if (!host_file->f_op || !host_file->f_op->mmap)
+ 		return -ENODEV;
+ 
+-	coda_inode = coda_file->f_dentry->d_inode;
+-	host_inode = host_file->f_dentry->d_inode;
++	coda_inode = coda_file->f_path.dentry->d_inode;
++	host_inode = host_file->f_path.dentry->d_inode;
+ 	coda_file->f_mapping = host_file->f_mapping;
+ 	if (coda_inode->i_mapping == &coda_inode->i_data)
+ 		coda_inode->i_mapping = host_inode->i_mapping;
+@@ -190,7 +190,7 @@ int coda_flush(struct file *coda_file, fl_owner_t id)
+ 	cfi = CODA_FTOC(coda_file);
+ 	BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
+ 
+-	coda_inode = coda_file->f_dentry->d_inode;
++	coda_inode = coda_file->f_path.dentry->d_inode;
+ 
+ 	err = venus_store(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags,
+ 			  coda_file->f_uid);
+@@ -233,7 +233,7 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
+ 		err = venus_close(coda_inode->i_sb, coda_i2f(coda_inode),
+ 				  coda_flags, coda_file->f_uid);
+ 
+-	host_inode = cfi->cfi_container->f_dentry->d_inode;
++	host_inode = cfi->cfi_container->f_path.dentry->d_inode;
+ 	cii = ITOC(coda_inode);
+ 
+ 	/* did we mmap this file? */
+@@ -270,7 +270,7 @@ int coda_fsync(struct file *coda_file, struct dentry *coda_dentry, int datasync)
+ 	coda_vfs_stat.fsync++;
+ 
+ 	if (host_file->f_op && host_file->f_op->fsync) {
+-		host_dentry = host_file->f_dentry;
++		host_dentry = host_file->f_path.dentry;
+ 		host_inode = host_dentry->d_inode;
+ 		mutex_lock(&host_inode->i_mutex);
+ 		err = host_file->f_op->fsync(host_file, host_dentry, datasync);
+diff --git a/fs/coda/inode.c b/fs/coda/inode.c
+index b64659fa82d0..01395defed85 100644
+--- a/fs/coda/inode.c
++++ b/fs/coda/inode.c
+@@ -119,7 +119,7 @@ static int get_device_index(struct coda_mount_data *data)
+ 	file = fget(data->fd);
+ 	inode = NULL;
+ 	if(file)
+-		inode = file->f_dentry->d_inode;
++		inode = file->f_path.dentry->d_inode;
+ 	
+ 	if(!inode || !S_ISCHR(inode->i_mode) ||
+ 	   imajor(inode) != CODA_PSDEV_MAJOR) {

commit a7113a966241b700aecc7b8cb326cecb62e3c4b2
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:36:55 2006 -0800
+
+    [PATCH] struct path: convert char-drivers
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/char/cs5535_gpio.c b/drivers/char/cs5535_gpio.c
+index 8ce3f34cfc22..c02d9e99e050 100644
+--- a/drivers/char/cs5535_gpio.c
++++ b/drivers/char/cs5535_gpio.c
+@@ -82,7 +82,7 @@ static inline u32 cs5535_lowhigh_base(int reg)
+ static ssize_t cs5535_gpio_write(struct file *file, const char __user *data,
+ 				 size_t len, loff_t *ppos)
+ {
+-	u32	m = iminor(file->f_dentry->d_inode);
++	u32	m = iminor(file->f_path.dentry->d_inode);
+ 	int	i, j;
+ 	u32	base = gpio_base + cs5535_lowhigh_base(m);
+ 	u32	m0, m1;
+@@ -117,7 +117,7 @@ static ssize_t cs5535_gpio_write(struct file *file, const char __user *data,
+ static ssize_t cs5535_gpio_read(struct file *file, char __user *buf,
+ 				size_t len, loff_t *ppos)
+ {
+-	u32	m = iminor(file->f_dentry->d_inode);
++	u32	m = iminor(file->f_path.dentry->d_inode);
+ 	u32	base = gpio_base + cs5535_lowhigh_base(m);
+ 	int	rd_bit = 1 << (m & 0x0f);
+ 	int	i;
+diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
+index 9b1bf60ffbe7..06f2dbf17710 100644
+--- a/drivers/char/dsp56k.c
++++ b/drivers/char/dsp56k.c
+@@ -201,7 +201,7 @@ static int dsp56k_upload(u_char __user *bin, int len)
+ static ssize_t dsp56k_read(struct file *file, char __user *buf, size_t count,
+ 			   loff_t *ppos)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	int dev = iminor(inode) & 0x0f;
+ 
+ 	switch(dev)
+@@ -264,7 +264,7 @@ static ssize_t dsp56k_read(struct file *file, char __user *buf, size_t count,
+ static ssize_t dsp56k_write(struct file *file, const char __user *buf, size_t count,
+ 			    loff_t *ppos)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	int dev = iminor(inode) & 0x0f;
+ 
+ 	switch(dev)
+@@ -420,7 +420,7 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file,
+ #if 0
+ static unsigned int dsp56k_poll(struct file *file, poll_table *wait)
+ {
+-	int dev = iminor(file->f_dentry->d_inode) & 0x0f;
++	int dev = iminor(file->f_path.dentry->d_inode) & 0x0f;
+ 
+ 	switch(dev)
+ 	{
+diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c
+index 5e82c3bad2e3..d4005e94fe5f 100644
+--- a/drivers/char/dtlk.c
++++ b/drivers/char/dtlk.c
+@@ -122,7 +122,7 @@ static void dtlk_timer_tick(unsigned long data);
+ static ssize_t dtlk_read(struct file *file, char __user *buf,
+ 			 size_t count, loff_t * ppos)
+ {
+-	unsigned int minor = iminor(file->f_dentry->d_inode);
++	unsigned int minor = iminor(file->f_path.dentry->d_inode);
+ 	char ch;
+ 	int i = 0, retries;
+ 
+@@ -174,7 +174,7 @@ static ssize_t dtlk_write(struct file *file, const char __user *buf,
+ 	}
+ #endif
+ 
+-	if (iminor(file->f_dentry->d_inode) != DTLK_MINOR)
++	if (iminor(file->f_path.dentry->d_inode) != DTLK_MINOR)
+ 		return -EINVAL;
+ 
+ 	while (1) {
+diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
+index cda2459c1d60..6810b7bbcbb7 100644
+--- a/drivers/char/ip2/ip2main.c
++++ b/drivers/char/ip2/ip2main.c
+@@ -2700,7 +2700,7 @@ static
+ ssize_t
+ ip2_ipl_read(struct file *pFile, char __user *pData, size_t count, loff_t *off )
+ {
+-	unsigned int minor = iminor(pFile->f_dentry->d_inode);
++	unsigned int minor = iminor(pFile->f_path.dentry->d_inode);
+ 	int rc = 0;
+ 
+ #ifdef IP2DEBUG_IPL
+diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
+index 8f591945ebd9..b6f0d036a760 100644
+--- a/drivers/char/istallion.c
++++ b/drivers/char/istallion.c
+@@ -4194,7 +4194,7 @@ static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, lof
+ 	void *p;
+ 	loff_t off = *offp;
+ 
+-	brdnr = iminor(fp->f_dentry->d_inode);
++	brdnr = iminor(fp->f_path.dentry->d_inode);
+ 	if (brdnr >= stli_nrbrds)
+ 		return -ENODEV;
+ 	brdp = stli_brds[brdnr];
+@@ -4258,7 +4258,7 @@ static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t cou
+ 	void *p;
+ 	loff_t off = *offp;
+ 
+-	brdnr = iminor(fp->f_dentry->d_inode);
++	brdnr = iminor(fp->f_path.dentry->d_inode);
+ 
+ 	if (brdnr >= stli_nrbrds)
+ 		return -ENODEV;
+diff --git a/drivers/char/lp.c b/drivers/char/lp.c
+index 1ecea7d448f1..b70b5388b5a8 100644
+--- a/drivers/char/lp.c
++++ b/drivers/char/lp.c
+@@ -296,7 +296,7 @@ static int lp_wait_ready(int minor, int nonblock)
+ static ssize_t lp_write(struct file * file, const char __user * buf,
+ 		        size_t count, loff_t *ppos)
+ {
+-	unsigned int minor = iminor(file->f_dentry->d_inode);
++	unsigned int minor = iminor(file->f_path.dentry->d_inode);
+ 	struct parport *port = lp_table[minor].dev->port;
+ 	char *kbuf = lp_table[minor].lp_buffer;
+ 	ssize_t retv = 0;
+@@ -415,7 +415,7 @@ static ssize_t lp_read(struct file * file, char __user * buf,
+ 		       size_t count, loff_t *ppos)
+ {
+ 	DEFINE_WAIT(wait);
+-	unsigned int minor=iminor(file->f_dentry->d_inode);
++	unsigned int minor=iminor(file->f_path.dentry->d_inode);
+ 	struct parport *port = lp_table[minor].dev->port;
+ 	ssize_t retval = 0;
+ 	char *kbuf = lp_table[minor].lp_buffer;
+diff --git a/drivers/char/mem.c b/drivers/char/mem.c
+index e67eef4867ba..089020e0ee5a 100644
+--- a/drivers/char/mem.c
++++ b/drivers/char/mem.c
+@@ -774,7 +774,7 @@ static loff_t memory_lseek(struct file * file, loff_t offset, int orig)
+ {
+ 	loff_t ret;
+ 
+-	mutex_lock(&file->f_dentry->d_inode->i_mutex);
++	mutex_lock(&file->f_path.dentry->d_inode->i_mutex);
+ 	switch (orig) {
+ 		case 0:
+ 			file->f_pos = offset;
+@@ -789,7 +789,7 @@ static loff_t memory_lseek(struct file * file, loff_t offset, int orig)
+ 		default:
+ 			ret = -EINVAL;
+ 	}
+-	mutex_unlock(&file->f_dentry->d_inode->i_mutex);
++	mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
+ 	return ret;
+ }
+ 
+diff --git a/drivers/char/nsc_gpio.c b/drivers/char/nsc_gpio.c
+index 4d47d79bcea7..808d44e9a32a 100644
+--- a/drivers/char/nsc_gpio.c
++++ b/drivers/char/nsc_gpio.c
+@@ -41,7 +41,7 @@ void nsc_gpio_dump(struct nsc_gpio_ops *amp, unsigned index)
+ ssize_t nsc_gpio_write(struct file *file, const char __user *data,
+ 		       size_t len, loff_t *ppos)
+ {
+-	unsigned m = iminor(file->f_dentry->d_inode);
++	unsigned m = iminor(file->f_path.dentry->d_inode);
+ 	struct nsc_gpio_ops *amp = file->private_data;
+ 	struct device *dev = amp->dev;
+ 	size_t i;
+@@ -104,7 +104,7 @@ ssize_t nsc_gpio_write(struct file *file, const char __user *data,
+ ssize_t nsc_gpio_read(struct file *file, char __user * buf,
+ 		      size_t len, loff_t * ppos)
+ {
+-	unsigned m = iminor(file->f_dentry->d_inode);
++	unsigned m = iminor(file->f_path.dentry->d_inode);
+ 	int value;
+ 	struct nsc_gpio_ops *amp = file->private_data;
+ 
+diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
+index c1e3dd837fc8..4abd1eff61d6 100644
+--- a/drivers/char/ppdev.c
++++ b/drivers/char/ppdev.c
+@@ -106,7 +106,7 @@ static inline void pp_enable_irq (struct pp_struct *pp)
+ static ssize_t pp_read (struct file * file, char __user * buf, size_t count,
+ 			loff_t * ppos)
+ {
+-	unsigned int minor = iminor(file->f_dentry->d_inode);
++	unsigned int minor = iminor(file->f_path.dentry->d_inode);
+ 	struct pp_struct *pp = file->private_data;
+ 	char * kbuffer;
+ 	ssize_t bytes_read = 0;
+@@ -189,7 +189,7 @@ static ssize_t pp_read (struct file * file, char __user * buf, size_t count,
+ static ssize_t pp_write (struct file * file, const char __user * buf,
+ 			 size_t count, loff_t * ppos)
+ {
+-	unsigned int minor = iminor(file->f_dentry->d_inode);
++	unsigned int minor = iminor(file->f_path.dentry->d_inode);
+ 	struct pp_struct *pp = file->private_data;
+ 	char * kbuffer;
+ 	ssize_t bytes_written = 0;
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 4c6782a1ecdb..092a01cc02da 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -1048,7 +1048,7 @@ random_write(struct file * file, const char __user * buffer,
+ 	if (p == buffer) {
+ 		return (ssize_t)ret;
+ 	} else {
+-		struct inode *inode = file->f_dentry->d_inode;
++		struct inode *inode = file->f_path.dentry->d_inode;
+ 	        inode->i_mtime = current_fs_time(inode->i_sb);
+ 		mark_inode_dirty(inode);
+ 		return (ssize_t)(p - buffer);
+diff --git a/drivers/char/raw.c b/drivers/char/raw.c
+index 3b32313f6eb4..645e20a06ece 100644
+--- a/drivers/char/raw.c
++++ b/drivers/char/raw.c
+@@ -75,7 +75,7 @@ static int raw_open(struct inode *inode, struct file *filp)
+ 	filp->f_flags |= O_DIRECT;
+ 	filp->f_mapping = bdev->bd_inode->i_mapping;
+ 	if (++raw_devices[minor].inuse == 1)
+-		filp->f_dentry->d_inode->i_mapping =
++		filp->f_path.dentry->d_inode->i_mapping =
+ 			bdev->bd_inode->i_mapping;
+ 	filp->private_data = bdev;
+ 	mutex_unlock(&raw_mutex);
+diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
+index fc87070f1866..17d54e1331b2 100644
+--- a/drivers/char/sonypi.c
++++ b/drivers/char/sonypi.c
+@@ -979,7 +979,7 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf,
+ 	}
+ 
+ 	if (ret > 0) {
+-		struct inode *inode = file->f_dentry->d_inode;
++		struct inode *inode = file->f_path.dentry->d_inode;
+ 		inode->i_atime = current_fs_time(inode->i_sb);
+ 	}
+ 
+diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c
+index bb1bad4c18f9..4c431cb7cf1b 100644
+--- a/drivers/char/tb0219.c
++++ b/drivers/char/tb0219.c
+@@ -164,7 +164,7 @@ static ssize_t tanbac_tb0219_read(struct file *file, char __user *buf, size_t le
+ 	unsigned int minor;
+ 	char value;
+ 
+-	minor = iminor(file->f_dentry->d_inode);
++	minor = iminor(file->f_path.dentry->d_inode);
+ 	switch (minor) {
+ 	case 0:
+ 		value = get_led();
+@@ -200,7 +200,7 @@ static ssize_t tanbac_tb0219_write(struct file *file, const char __user *data,
+ 	int retval = 0;
+ 	char c;
+ 
+-	minor = iminor(file->f_dentry->d_inode);
++	minor = iminor(file->f_path.dentry->d_inode);
+ 	switch (minor) {
+ 	case 0:
+ 		type = TYPE_LED;
+diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c
+index 9df0ca1be0e3..47fb20f69695 100644
+--- a/drivers/char/tipar.c
++++ b/drivers/char/tipar.c
+@@ -285,7 +285,7 @@ static ssize_t
+ tipar_write (struct file *file, const char __user *buf, size_t count,
+ 		loff_t * ppos)
+ {
+-	unsigned int minor = iminor(file->f_dentry->d_inode) - TIPAR_MINOR;
++	unsigned int minor = iminor(file->f_path.dentry->d_inode) - TIPAR_MINOR;
+ 	ssize_t n;
+ 
+ 	parport_claim_or_block(table[minor].dev);
+@@ -313,7 +313,7 @@ static ssize_t
+ tipar_read(struct file *file, char __user *buf, size_t count, loff_t * ppos)
+ {
+ 	int b = 0;
+-	unsigned int minor = iminor(file->f_dentry->d_inode) - TIPAR_MINOR;
++	unsigned int minor = iminor(file->f_path.dentry->d_inode) - TIPAR_MINOR;
+ 	ssize_t retval = 0;
+ 	ssize_t n = 0;
+ 
+diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
+index 0c856a6f3677..8a2d26e98ac4 100644
+--- a/drivers/char/tty_io.c
++++ b/drivers/char/tty_io.c
+@@ -1629,7 +1629,7 @@ static ssize_t tty_read(struct file * file, char __user * buf, size_t count,
+ 	struct tty_ldisc *ld;
+ 
+ 	tty = (struct tty_struct *)file->private_data;
+-	inode = file->f_dentry->d_inode;
++	inode = file->f_path.dentry->d_inode;
+ 	if (tty_paranoia_check(tty, inode, "tty_read"))
+ 		return -EIO;
+ 	if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags)))
+@@ -1732,7 +1732,7 @@ static inline ssize_t do_tty_write(
+ 		cond_resched();
+ 	}
+ 	if (written) {
+-		struct inode *inode = file->f_dentry->d_inode;
++		struct inode *inode = file->f_path.dentry->d_inode;
+ 		inode->i_mtime = current_fs_time(inode->i_sb);
+ 		ret = written;
+ 	}
+@@ -1763,7 +1763,7 @@ static ssize_t tty_write(struct file * file, const char __user * buf, size_t cou
+ 			 loff_t *ppos)
+ {
+ 	struct tty_struct * tty;
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	ssize_t ret;
+ 	struct tty_ldisc *ld;
+ 	
+@@ -2170,7 +2170,7 @@ static void release_dev(struct file * filp)
+ 	unsigned long flags;
+ 	
+ 	tty = (struct tty_struct *)filp->private_data;
+-	if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "release_dev"))
++	if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "release_dev"))
+ 		return;
+ 
+ 	check_tty_count(tty, "release_dev");
+@@ -2680,7 +2680,7 @@ static unsigned int tty_poll(struct file * filp, poll_table * wait)
+ 	int ret = 0;
+ 
+ 	tty = (struct tty_struct *)filp->private_data;
+-	if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "tty_poll"))
++	if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_poll"))
+ 		return 0;
+ 		
+ 	ld = tty_ldisc_ref_wait(tty);
+@@ -2696,7 +2696,7 @@ static int tty_fasync(int fd, struct file * filp, int on)
+ 	int retval;
+ 
+ 	tty = (struct tty_struct *)filp->private_data;
+-	if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "tty_fasync"))
++	if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync"))
+ 		return 0;
+ 	
+ 	retval = fasync_helper(fd, filp, on, &tty->fasync);
+diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
+index f442b574b44a..26776517f04c 100644
+--- a/drivers/char/vc_screen.c
++++ b/drivers/char/vc_screen.c
+@@ -72,7 +72,7 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig)
+ 	int size;
+ 
+ 	down(&con_buf_sem);
+-	size = vcs_size(file->f_dentry->d_inode);
++	size = vcs_size(file->f_path.dentry->d_inode);
+ 	switch (orig) {
+ 		default:
+ 			up(&con_buf_sem);
+@@ -98,7 +98,7 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig)
+ static ssize_t
+ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	unsigned int currcons = iminor(inode);
+ 	struct vc_data *vc;
+ 	long pos;
+@@ -271,7 +271,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+ static ssize_t
+ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	unsigned int currcons = iminor(inode);
+ 	struct vc_data *vc;
+ 	long pos;
+diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
+index 73c78bf75d7f..94d79cb8ce8d 100644
+--- a/drivers/char/viotape.c
++++ b/drivers/char/viotape.c
+@@ -442,7 +442,7 @@ static ssize_t viotap_write(struct file *file, const char *buf,
+ 	if (op == NULL)
+ 		return -ENOMEM;
+ 
+-	get_dev_info(file->f_dentry->d_inode, &devi);
++	get_dev_info(file->f_path.dentry->d_inode, &devi);
+ 
+ 	/*
+ 	 * We need to make sure we can send a request.  We use
+@@ -532,7 +532,7 @@ static ssize_t viotap_read(struct file *file, char *buf, size_t count,
+ 	if (op == NULL)
+ 		return -ENOMEM;
+ 
+-	get_dev_info(file->f_dentry->d_inode, &devi);
++	get_dev_info(file->f_path.dentry->d_inode, &devi);
+ 
+ 	/*
+ 	 * We need to make sure we can send a request.  We use
+@@ -612,7 +612,7 @@ static int viotap_ioctl(struct inode *inode, struct file *file,
+ 	if (op == NULL)
+ 		return -ENOMEM;
+ 
+-	get_dev_info(file->f_dentry->d_inode, &devi);
++	get_dev_info(file->f_path.dentry->d_inode, &devi);
+ 
+ 	down(&reqSem);
+ 
+@@ -777,7 +777,7 @@ static int viotap_open(struct inode *inode, struct file *file)
+ 	if (op == NULL)
+ 		return -ENOMEM;
+ 
+-	get_dev_info(file->f_dentry->d_inode, &devi);
++	get_dev_info(file->f_path.dentry->d_inode, &devi);
+ 
+ 	/* Note: We currently only support one mode! */
+ 	if ((devi.devno >= viotape_numdev) || (devi.mode)) {
+@@ -822,7 +822,7 @@ static int viotap_release(struct inode *inode, struct file *file)
+ 		return -ENOMEM;
+ 	init_completion(&op->com);
+ 
+-	get_dev_info(file->f_dentry->d_inode, &devi);
++	get_dev_info(file->f_path.dentry->d_inode, &devi);
+ 
+ 	if (devi.devno >= viotape_numdev) {
+ 		ret = -ENODEV;
+diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c
+index 8e7949305171..a744dad9cf45 100644
+--- a/drivers/char/vr41xx_giu.c
++++ b/drivers/char/vr41xx_giu.c
+@@ -506,7 +506,7 @@ static ssize_t gpio_read(struct file *file, char __user *buf, size_t len,
+ 	unsigned int pin;
+ 	char value = '0';
+ 
+-	pin = iminor(file->f_dentry->d_inode);
++	pin = iminor(file->f_path.dentry->d_inode);
+ 	if (pin >= giu_nr_pins)
+ 		return -EBADF;
+ 
+@@ -530,7 +530,7 @@ static ssize_t gpio_write(struct file *file, const char __user *data,
+ 	char c;
+ 	int retval = 0;
+ 
+-	pin = iminor(file->f_dentry->d_inode);
++	pin = iminor(file->f_path.dentry->d_inode);
+ 	if (pin >= giu_nr_pins)
+ 		return -EBADF;
+ 

commit 6c648be6f4183775679c1f2cc4d094128f104fb2
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:36:55 2006 -0800
+
+    [PATCH] struct path: convert block_drivers
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c
+index 8e41c87b026e..e04be94d195c 100644
+--- a/drivers/block/acsi_slm.c
++++ b/drivers/block/acsi_slm.c
+@@ -363,7 +363,7 @@ static ssize_t slm_read( struct file *file, char *buf, size_t count,
+ 						 loff_t *ppos )
+ 
+ {
+-	struct inode *node = file->f_dentry->d_inode;
++	struct inode *node = file->f_path.dentry->d_inode;
+ 	unsigned long page;
+ 	int length;
+ 	int end;
+@@ -618,7 +618,7 @@ static ssize_t slm_write( struct file *file, const char *buf, size_t count,
+ 						  loff_t *ppos )
+ 
+ {
+-	struct inode *node = file->f_dentry->d_inode;
++	struct inode *node = file->f_path.dentry->d_inode;
+ 	int		device = iminor(node);
+ 	int		n, filled, w, h;
+ 
+diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
+index 892e092afe9a..ee159edb6b88 100644
+--- a/drivers/block/cciss.c
++++ b/drivers/block/cciss.c
+@@ -535,7 +535,7 @@ static int do_ioctl(struct file *f, unsigned cmd, unsigned long arg)
+ {
+ 	int ret;
+ 	lock_kernel();
+-	ret = cciss_ioctl(f->f_dentry->d_inode, f, cmd, arg);
++	ret = cciss_ioctl(f->f_path.dentry->d_inode, f, cmd, arg);
+ 	unlock_kernel();
+ 	return ret;
+ }
+diff --git a/drivers/block/loop.c b/drivers/block/loop.c
+index beab6d2643cb..6b5b64207407 100644
+--- a/drivers/block/loop.c
++++ b/drivers/block/loop.c
+@@ -1000,7 +1000,7 @@ loop_get_status(struct loop_device *lo, struct loop_info64 *info)
+ 
+ 	if (lo->lo_state != Lo_bound)
+ 		return -ENXIO;
+-	error = vfs_getattr(file->f_vfsmnt, file->f_dentry, &stat);
++	error = vfs_getattr(file->f_path.mnt, file->f_path.dentry, &stat);
+ 	if (error)
+ 		return error;
+ 	memset(info, 0, sizeof(*info));
+@@ -1287,7 +1287,7 @@ loop_get_status_compat(struct loop_device *lo,
+ 
+ static long lo_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
+ 	int err;
+ 

commit c5a20b6c26efb58c2ba2ebebcc65748f5b92f662
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:36:54 2006 -0800
+
+    [PATCH] struct path: convert block
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/block/ioctl.c b/block/ioctl.c
+index 9fddb99c3efb..f6962b64660e 100644
+--- a/block/ioctl.c
++++ b/block/ioctl.c
+@@ -290,7 +290,7 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
+    ENOIOCTLCMD for unknown ioctls. */
+ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
+ {
+-	struct block_device *bdev = file->f_dentry->d_inode->i_bdev;
++	struct block_device *bdev = file->f_path.dentry->d_inode->i_bdev;
+ 	struct gendisk *disk = bdev->bd_disk;
+ 	int ret = -ENOIOCTLCMD;
+ 	if (disk->fops->compat_ioctl) {

commit 61a8424ab8f611d199bfc8ca329ec0ea77a4d4ea
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:36:53 2006 -0800
+
+    [PATCH] struct path: convert bfs
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
+index a650f1d0b85e..2a746e688df5 100644
+--- a/fs/bfs/dir.c
++++ b/fs/bfs/dir.c
+@@ -27,7 +27,7 @@ static struct buffer_head * bfs_find_entry(struct inode * dir,
+ 
+ static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir)
+ {
+-	struct inode * dir = f->f_dentry->d_inode;
++	struct inode * dir = f->f_path.dentry->d_inode;
+ 	struct buffer_head * bh;
+ 	struct bfs_dirent * de;
+ 	unsigned int offset;

commit 28f375fd6ff266d8e321648b36456f696cfae220
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:36:52 2006 -0800
+
+    [PATCH] struct path: convert befs
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
+index bce402eee554..481e59b9d91c 100644
+--- a/fs/befs/linuxvfs.c
++++ b/fs/befs/linuxvfs.c
+@@ -212,7 +212,7 @@ befs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+ static int
+ befs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ {
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct super_block *sb = inode->i_sb;
+ 	befs_data_stream *ds = &BEFS_I(inode)->i_data.ds;
+ 	befs_off_t value;
+@@ -222,7 +222,7 @@ befs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ 	char keybuf[BEFS_NAME_LEN + 1];
+ 	char *nlsname;
+ 	int nlsnamelen;
+-	const char *dirname = filp->f_dentry->d_name.name;
++	const char *dirname = filp->f_path.dentry->d_name.name;
+ 
+ 	befs_debug(sb, "---> befs_readdir() "
+ 		   "name %s, inode %ld, filp->f_pos %Ld",

commit 76a0f17429f5dd82186eec2ee2f37f5a5237d1a8
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:36:52 2006 -0800
+
+    [PATCH] struct path: convert atm
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/net/atm/proc.c b/net/atm/proc.c
+index 91fe5f53ff11..739866bfe9e9 100644
+--- a/net/atm/proc.c
++++ b/net/atm/proc.c
+@@ -393,7 +393,7 @@ static ssize_t proc_dev_atm_read(struct file *file, char __user *buf,
+ 	if (count == 0) return 0;
+ 	page = get_zeroed_page(GFP_KERNEL);
+ 	if (!page) return -ENOMEM;
+-	dev = PDE(file->f_dentry->d_inode)->data;
++	dev = PDE(file->f_path.dentry->d_inode)->data;
+ 	if (!dev->ops->proc_read)
+ 		length = -EINVAL;
+ 	else {

commit 8ac0352bb20c5a8c051218c689d263b4591d50e1
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:36:51 2006 -0800
+
+    [PATCH] struct path: convert alpha
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
+index ad6173651995..fb804043b320 100644
+--- a/arch/alpha/kernel/osf_sys.c
++++ b/arch/alpha/kernel/osf_sys.c
+@@ -277,7 +277,7 @@ osf_fstatfs(unsigned long fd, struct osf_statfs __user *buffer, unsigned long bu
+ 	retval = -EBADF;
+ 	file = fget(fd);
+ 	if (file) {
+-		retval = do_osf_statfs(file->f_dentry, buffer, bufsiz);
++		retval = do_osf_statfs(file->f_path.dentry, buffer, bufsiz);
+ 		fput(file);
+ 	}
+ 	return retval;

commit 1d56a96956158d0fb1902c56ffa0e38caa39bddb
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:36:50 2006 -0800
+
+    [PATCH] struct path: convert afs
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/afs/dir.c b/fs/afs/dir.c
+index a6ec75c56fcf..4acd04134055 100644
+--- a/fs/afs/dir.c
++++ b/fs/afs/dir.c
+@@ -392,10 +392,10 @@ static int afs_dir_readdir(struct file *file, void *cookie, filldir_t filldir)
+ 	unsigned fpos;
+ 	int ret;
+ 
+-	_enter("{%Ld,{%lu}}", file->f_pos, file->f_dentry->d_inode->i_ino);
++	_enter("{%Ld,{%lu}}", file->f_pos, file->f_path.dentry->d_inode->i_ino);
+ 
+ 	fpos = file->f_pos;
+-	ret = afs_dir_iterate(file->f_dentry->d_inode, &fpos, cookie, filldir);
++	ret = afs_dir_iterate(file->f_path.dentry->d_inode, &fpos, cookie, filldir);
+ 	file->f_pos = fpos;
+ 
+ 	_leave(" = %d", ret);
+diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
+index 99785a79d043..f33b1a81a761 100644
+--- a/fs/afs/mntpt.c
++++ b/fs/afs/mntpt.c
+@@ -136,11 +136,11 @@ static int afs_mntpt_open(struct inode *inode, struct file *file)
+ {
+ 	kenter("%p,%p{%p{%s},%s}",
+ 	       inode, file,
+-	       file->f_dentry->d_parent,
+-	       file->f_dentry->d_parent ?
+-	       file->f_dentry->d_parent->d_name.name :
++	       file->f_path.dentry->d_parent,
++	       file->f_path.dentry->d_parent ?
++	       file->f_path.dentry->d_parent->d_name.name :
+ 	       (const unsigned char *) "",
+-	       file->f_dentry->d_name.name);
++	       file->f_path.dentry->d_name.name);
+ 
+ 	return -EREMOTE;
+ } /* end afs_mntpt_open() */

commit 514653e25962c37b11fe648e4ef1c1130f697bcb
+Author: Josef Sipek 
+Date:   Fri Dec 8 02:36:50 2006 -0800
+
+    [PATCH] struct path: convert adfs
+    
+    Signed-off-by: Josef Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c
+index d3c7905b2ddc..2b8903893d3f 100644
+--- a/fs/adfs/dir.c
++++ b/fs/adfs/dir.c
+@@ -28,7 +28,7 @@ static DEFINE_RWLOCK(adfs_dir_lock);
+ static int
+ adfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ {
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct super_block *sb = inode->i_sb;
+ 	struct adfs_dir_ops *ops = ADFS_SB(sb)->s_dir;
+ 	struct object_info obj;

\ No newline at end of file diff --git a/detail/110.html b/detail/110.html new file mode 100644 index 0000000..36577ab --- /dev/null +++ b/detail/110.html @@ -0,0 +1,39 @@ +

Patches contributed by University of Massachusetts at Lowell


commit 581141cb4b10ebd865dcb7b80f5e712e2def5408
+Author: Albert D. Cahalan 
+Date:   Tue Feb 14 13:53:20 2006 -0800
+
+    [PATCH] x86: document sysenter path
+    
+    This path isn't obvious.  It looks as if the kernel will be taking three
+    args from the user stack, but it only takes one from there.
+    
+    Signed-off-by: Albert Cahalan 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/i386/kernel/vsyscall-sysenter.S b/arch/i386/kernel/vsyscall-sysenter.S
+index 4daefb2ec1b2..76b728159403 100644
+--- a/arch/i386/kernel/vsyscall-sysenter.S
++++ b/arch/i386/kernel/vsyscall-sysenter.S
+@@ -7,6 +7,21 @@
+  *    for details.
+  */
+ 
++/*
++ * The caller puts arg2 in %ecx, which gets pushed. The kernel will use
++ * %ecx itself for arg2. The pushing is because the sysexit instruction
++ * (found in entry.S) requires that we clobber %ecx with the desired %esp.
++ * User code might expect that %ecx is unclobbered though, as it would be
++ * for returning via the iret instruction, so we must push and pop.
++ *
++ * The caller puts arg3 in %edx, which the sysexit instruction requires
++ * for %eip. Thus, exactly as for arg2, we must push and pop.
++ *
++ * Arg6 is different. The caller puts arg6 in %ebp. Since the sysenter
++ * instruction clobbers %esp, the user's %esp won't even survive entry
++ * into the kernel. We store %esp in %ebp. Code in entry.S must fetch
++ * arg6 from the stack.
++ */
+ 	.text
+ 	.globl __kernel_vsyscall
+ 	.type __kernel_vsyscall,@function

\ No newline at end of file diff --git a/detail/12.html b/detail/12.html new file mode 100644 index 0000000..19c5c7e --- /dev/null +++ b/detail/12.html @@ -0,0 +1,6139 @@ +

Patches contributed by University of Science and Technology of China


commit aadb22ba2f656581b2f733deb3a467c48cc618f6
+Author: Lv Yunlong 
+Date:   Wed Apr 6 21:04:43 2022 +0200
+
+    drbd: Fix five use after free bugs in get_initial_state
+    
+    In get_initial_state, it calls notify_initial_state_done(skb,..) if
+    cb->args[5]==1. If genlmsg_put() failed in notify_initial_state_done(),
+    the skb will be freed by nlmsg_free(skb).
+    Then get_initial_state will goto out and the freed skb will be used by
+    return value skb->len, which is a uaf bug.
+    
+    What's worse, the same problem goes even further: skb can also be
+    freed in the notify_*_state_change -> notify_*_state calls below.
+    Thus 4 additional uaf bugs happened.
+    
+    My patch lets the problem callee functions: notify_initial_state_done
+    and notify_*_state_change return an error code if errors happen.
+    So that the error codes could be propagated and the uaf bugs can be avoid.
+    
+    v2 reports a compilation warning. This v3 fixed this warning and built
+    successfully in my local environment with no additional warnings.
+    v2: https://lore.kernel.org/patchwork/patch/1435218/
+    
+    Fixes: a29728463b254 ("drbd: Backport the "events2" command")
+    Signed-off-by: Lv Yunlong 
+    Reviewed-by: Christoph Böhmwalder 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
+index 4b55e864a0a3..4d3efaa20b7b 100644
+--- a/drivers/block/drbd/drbd_int.h
++++ b/drivers/block/drbd/drbd_int.h
+@@ -1638,22 +1638,22 @@ struct sib_info {
+ };
+ void drbd_bcast_event(struct drbd_device *device, const struct sib_info *sib);
+ 
+-extern void notify_resource_state(struct sk_buff *,
++extern int notify_resource_state(struct sk_buff *,
+ 				  unsigned int,
+ 				  struct drbd_resource *,
+ 				  struct resource_info *,
+ 				  enum drbd_notification_type);
+-extern void notify_device_state(struct sk_buff *,
++extern int notify_device_state(struct sk_buff *,
+ 				unsigned int,
+ 				struct drbd_device *,
+ 				struct device_info *,
+ 				enum drbd_notification_type);
+-extern void notify_connection_state(struct sk_buff *,
++extern int notify_connection_state(struct sk_buff *,
+ 				    unsigned int,
+ 				    struct drbd_connection *,
+ 				    struct connection_info *,
+ 				    enum drbd_notification_type);
+-extern void notify_peer_device_state(struct sk_buff *,
++extern int notify_peer_device_state(struct sk_buff *,
+ 				     unsigned int,
+ 				     struct drbd_peer_device *,
+ 				     struct peer_device_info *,
+diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
+index 02030c9c4d3b..b7216c186ba4 100644
+--- a/drivers/block/drbd/drbd_nl.c
++++ b/drivers/block/drbd/drbd_nl.c
+@@ -4549,7 +4549,7 @@ static int nla_put_notification_header(struct sk_buff *msg,
+ 	return drbd_notification_header_to_skb(msg, &nh, true);
+ }
+ 
+-void notify_resource_state(struct sk_buff *skb,
++int notify_resource_state(struct sk_buff *skb,
+ 			   unsigned int seq,
+ 			   struct drbd_resource *resource,
+ 			   struct resource_info *resource_info,
+@@ -4591,16 +4591,17 @@ void notify_resource_state(struct sk_buff *skb,
+ 		if (err && err != -ESRCH)
+ 			goto failed;
+ 	}
+-	return;
++	return 0;
+ 
+ nla_put_failure:
+ 	nlmsg_free(skb);
+ failed:
+ 	drbd_err(resource, "Error %d while broadcasting event. Event seq:%u\n",
+ 			err, seq);
++	return err;
+ }
+ 
+-void notify_device_state(struct sk_buff *skb,
++int notify_device_state(struct sk_buff *skb,
+ 			 unsigned int seq,
+ 			 struct drbd_device *device,
+ 			 struct device_info *device_info,
+@@ -4640,16 +4641,17 @@ void notify_device_state(struct sk_buff *skb,
+ 		if (err && err != -ESRCH)
+ 			goto failed;
+ 	}
+-	return;
++	return 0;
+ 
+ nla_put_failure:
+ 	nlmsg_free(skb);
+ failed:
+ 	drbd_err(device, "Error %d while broadcasting event. Event seq:%u\n",
+ 		 err, seq);
++	return err;
+ }
+ 
+-void notify_connection_state(struct sk_buff *skb,
++int notify_connection_state(struct sk_buff *skb,
+ 			     unsigned int seq,
+ 			     struct drbd_connection *connection,
+ 			     struct connection_info *connection_info,
+@@ -4689,16 +4691,17 @@ void notify_connection_state(struct sk_buff *skb,
+ 		if (err && err != -ESRCH)
+ 			goto failed;
+ 	}
+-	return;
++	return 0;
+ 
+ nla_put_failure:
+ 	nlmsg_free(skb);
+ failed:
+ 	drbd_err(connection, "Error %d while broadcasting event. Event seq:%u\n",
+ 		 err, seq);
++	return err;
+ }
+ 
+-void notify_peer_device_state(struct sk_buff *skb,
++int notify_peer_device_state(struct sk_buff *skb,
+ 			      unsigned int seq,
+ 			      struct drbd_peer_device *peer_device,
+ 			      struct peer_device_info *peer_device_info,
+@@ -4739,13 +4742,14 @@ void notify_peer_device_state(struct sk_buff *skb,
+ 		if (err && err != -ESRCH)
+ 			goto failed;
+ 	}
+-	return;
++	return 0;
+ 
+ nla_put_failure:
+ 	nlmsg_free(skb);
+ failed:
+ 	drbd_err(peer_device, "Error %d while broadcasting event. Event seq:%u\n",
+ 		 err, seq);
++	return err;
+ }
+ 
+ void notify_helper(enum drbd_notification_type type,
+@@ -4796,7 +4800,7 @@ void notify_helper(enum drbd_notification_type type,
+ 		 err, seq);
+ }
+ 
+-static void notify_initial_state_done(struct sk_buff *skb, unsigned int seq)
++static int notify_initial_state_done(struct sk_buff *skb, unsigned int seq)
+ {
+ 	struct drbd_genlmsghdr *dh;
+ 	int err;
+@@ -4810,11 +4814,12 @@ static void notify_initial_state_done(struct sk_buff *skb, unsigned int seq)
+ 	if (nla_put_notification_header(skb, NOTIFY_EXISTS))
+ 		goto nla_put_failure;
+ 	genlmsg_end(skb, dh);
+-	return;
++	return 0;
+ 
+ nla_put_failure:
+ 	nlmsg_free(skb);
+ 	pr_err("Error %d sending event. Event seq:%u\n", err, seq);
++	return err;
+ }
+ 
+ static void free_state_changes(struct list_head *list)
+@@ -4841,6 +4846,7 @@ static int get_initial_state(struct sk_buff *skb, struct netlink_callback *cb)
+ 	unsigned int seq = cb->args[2];
+ 	unsigned int n;
+ 	enum drbd_notification_type flags = 0;
++	int err = 0;
+ 
+ 	/* There is no need for taking notification_mutex here: it doesn't
+ 	   matter if the initial state events mix with later state chage
+@@ -4849,32 +4855,32 @@ static int get_initial_state(struct sk_buff *skb, struct netlink_callback *cb)
+ 
+ 	cb->args[5]--;
+ 	if (cb->args[5] == 1) {
+-		notify_initial_state_done(skb, seq);
++		err = notify_initial_state_done(skb, seq);
+ 		goto out;
+ 	}
+ 	n = cb->args[4]++;
+ 	if (cb->args[4] < cb->args[3])
+ 		flags |= NOTIFY_CONTINUES;
+ 	if (n < 1) {
+-		notify_resource_state_change(skb, seq, state_change->resource,
++		err = notify_resource_state_change(skb, seq, state_change->resource,
+ 					     NOTIFY_EXISTS | flags);
+ 		goto next;
+ 	}
+ 	n--;
+ 	if (n < state_change->n_connections) {
+-		notify_connection_state_change(skb, seq, &state_change->connections[n],
++		err = notify_connection_state_change(skb, seq, &state_change->connections[n],
+ 					       NOTIFY_EXISTS | flags);
+ 		goto next;
+ 	}
+ 	n -= state_change->n_connections;
+ 	if (n < state_change->n_devices) {
+-		notify_device_state_change(skb, seq, &state_change->devices[n],
++		err = notify_device_state_change(skb, seq, &state_change->devices[n],
+ 					   NOTIFY_EXISTS | flags);
+ 		goto next;
+ 	}
+ 	n -= state_change->n_devices;
+ 	if (n < state_change->n_devices * state_change->n_connections) {
+-		notify_peer_device_state_change(skb, seq, &state_change->peer_devices[n],
++		err = notify_peer_device_state_change(skb, seq, &state_change->peer_devices[n],
+ 						NOTIFY_EXISTS | flags);
+ 		goto next;
+ 	}
+@@ -4889,7 +4895,10 @@ static int get_initial_state(struct sk_buff *skb, struct netlink_callback *cb)
+ 		cb->args[4] = 0;
+ 	}
+ out:
+-	return skb->len;
++	if (err)
++		return err;
++	else
++		return skb->len;
+ }
+ 
+ int drbd_adm_get_initial_state(struct sk_buff *skb, struct netlink_callback *cb)
+diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c
+index b8a27818ab3f..4ee11aef6672 100644
+--- a/drivers/block/drbd/drbd_state.c
++++ b/drivers/block/drbd/drbd_state.c
+@@ -1537,7 +1537,7 @@ int drbd_bitmap_io_from_worker(struct drbd_device *device,
+ 	return rv;
+ }
+ 
+-void notify_resource_state_change(struct sk_buff *skb,
++int notify_resource_state_change(struct sk_buff *skb,
+ 				  unsigned int seq,
+ 				  struct drbd_resource_state_change *resource_state_change,
+ 				  enum drbd_notification_type type)
+@@ -1550,10 +1550,10 @@ void notify_resource_state_change(struct sk_buff *skb,
+ 		.res_susp_fen = resource_state_change->susp_fen[NEW],
+ 	};
+ 
+-	notify_resource_state(skb, seq, resource, &resource_info, type);
++	return notify_resource_state(skb, seq, resource, &resource_info, type);
+ }
+ 
+-void notify_connection_state_change(struct sk_buff *skb,
++int notify_connection_state_change(struct sk_buff *skb,
+ 				    unsigned int seq,
+ 				    struct drbd_connection_state_change *connection_state_change,
+ 				    enum drbd_notification_type type)
+@@ -1564,10 +1564,10 @@ void notify_connection_state_change(struct sk_buff *skb,
+ 		.conn_role = connection_state_change->peer_role[NEW],
+ 	};
+ 
+-	notify_connection_state(skb, seq, connection, &connection_info, type);
++	return notify_connection_state(skb, seq, connection, &connection_info, type);
+ }
+ 
+-void notify_device_state_change(struct sk_buff *skb,
++int notify_device_state_change(struct sk_buff *skb,
+ 				unsigned int seq,
+ 				struct drbd_device_state_change *device_state_change,
+ 				enum drbd_notification_type type)
+@@ -1577,10 +1577,10 @@ void notify_device_state_change(struct sk_buff *skb,
+ 		.dev_disk_state = device_state_change->disk_state[NEW],
+ 	};
+ 
+-	notify_device_state(skb, seq, device, &device_info, type);
++	return notify_device_state(skb, seq, device, &device_info, type);
+ }
+ 
+-void notify_peer_device_state_change(struct sk_buff *skb,
++int notify_peer_device_state_change(struct sk_buff *skb,
+ 				     unsigned int seq,
+ 				     struct drbd_peer_device_state_change *p,
+ 				     enum drbd_notification_type type)
+@@ -1594,7 +1594,7 @@ void notify_peer_device_state_change(struct sk_buff *skb,
+ 		.peer_resync_susp_dependency = p->resync_susp_dependency[NEW],
+ 	};
+ 
+-	notify_peer_device_state(skb, seq, peer_device, &peer_device_info, type);
++	return notify_peer_device_state(skb, seq, peer_device, &peer_device_info, type);
+ }
+ 
+ static void broadcast_state_change(struct drbd_state_change *state_change)
+@@ -1602,7 +1602,7 @@ static void broadcast_state_change(struct drbd_state_change *state_change)
+ 	struct drbd_resource_state_change *resource_state_change = &state_change->resource[0];
+ 	bool resource_state_has_changed;
+ 	unsigned int n_device, n_connection, n_peer_device, n_peer_devices;
+-	void (*last_func)(struct sk_buff *, unsigned int, void *,
++	int (*last_func)(struct sk_buff *, unsigned int, void *,
+ 			  enum drbd_notification_type) = NULL;
+ 	void *last_arg = NULL;
+ 
+diff --git a/drivers/block/drbd/drbd_state_change.h b/drivers/block/drbd/drbd_state_change.h
+index ba80f612d6ab..d5b0479bc9a6 100644
+--- a/drivers/block/drbd/drbd_state_change.h
++++ b/drivers/block/drbd/drbd_state_change.h
+@@ -44,19 +44,19 @@ extern struct drbd_state_change *remember_old_state(struct drbd_resource *, gfp_
+ extern void copy_old_to_new_state_change(struct drbd_state_change *);
+ extern void forget_state_change(struct drbd_state_change *);
+ 
+-extern void notify_resource_state_change(struct sk_buff *,
++extern int notify_resource_state_change(struct sk_buff *,
+ 					 unsigned int,
+ 					 struct drbd_resource_state_change *,
+ 					 enum drbd_notification_type type);
+-extern void notify_connection_state_change(struct sk_buff *,
++extern int notify_connection_state_change(struct sk_buff *,
+ 					   unsigned int,
+ 					   struct drbd_connection_state_change *,
+ 					   enum drbd_notification_type type);
+-extern void notify_device_state_change(struct sk_buff *,
++extern int notify_device_state_change(struct sk_buff *,
+ 				       unsigned int,
+ 				       struct drbd_device_state_change *,
+ 				       enum drbd_notification_type type);
+-extern void notify_peer_device_state_change(struct sk_buff *,
++extern int notify_peer_device_state_change(struct sk_buff *,
+ 					    unsigned int,
+ 					    struct drbd_peer_device_state_change *,
+ 					    enum drbd_notification_type type);

commit f27456693b960ce4022d40b943808b3362ce80f9
+Author: zhuxinran 
+Date:   Thu Dec 16 14:14:39 2021 +0800
+
+    9p/trans_virtio: Fix typo in the comment for p9_virtio_create()
+    
+    couldlook ==> could look
+    
+    Link: https://lkml.kernel.org/r/20211216061439.4186-1-zhuran@mail.ustc.edu.cn
+    Signed-off-by: zhuxinran 
+    Signed-off-by: Dominique Martinet 
+
+diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
+index bd5a89c4960d..f7dc561ca516 100644
+--- a/net/9p/trans_virtio.c
++++ b/net/9p/trans_virtio.c
+@@ -648,7 +648,7 @@ static int p9_virtio_probe(struct virtio_device *vdev)
+  * @args: args passed from sys_mount() for per-transport options (unused)
+  *
+  * This sets up a transport channel for 9p communication.  Right now
+- * we only match the first available channel, but eventually we couldlook up
++ * we only match the first available channel, but eventually we could look up
+  * alternate channels by matching devname versus a virtio_config entry.
+  * We use a simple reference count mechanism to ensure that only a single
+  * mount has a channel open at a time.

commit f973795a8d19cbf3d03807704eb7c6ff65788d5a
+Author: Lv Yunlong 
+Date:   Fri Apr 2 22:47:55 2021 -0700
+
+    wireless: iwlwifi: Fix a double free in iwl_txq_dyn_alloc_dma
+    
+    In iwl_txq_dyn_alloc_dma, txq->tfds is freed at first time by:
+    iwl_txq_alloc()->goto err_free_tfds->dma_free_coherent(). But
+    it forgot to set txq->tfds to NULL.
+    
+    Then the txq->tfds is freed again in iwl_txq_dyn_alloc_dma by:
+    goto error->iwl_txq_gen2_free_memory()->dma_free_coherent().
+    
+    My patch sets txq->tfds to NULL after the first free to avoid the
+    double free.
+    
+    Fixes: 0cd1ad2d7fd41 ("iwlwifi: move all bus-independent TX functions to common code")
+    Signed-off-by: Lv Yunlong 
+    Link: https://lore.kernel.org/r/20210403054755.4781-1-lyl2019@mail.ustc.edu.cn
+    Signed-off-by: Luca Coelho 
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/queue/tx.c b/drivers/net/wireless/intel/iwlwifi/queue/tx.c
+index 451b06069350..0f3526b0c5b0 100644
+--- a/drivers/net/wireless/intel/iwlwifi/queue/tx.c
++++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.c
+@@ -1072,6 +1072,7 @@ int iwl_txq_alloc(struct iwl_trans *trans, struct iwl_txq *txq, int slots_num,
+ 	return 0;
+ err_free_tfds:
+ 	dma_free_coherent(trans->dev, tfd_sz, txq->tfds, txq->dma_addr);
++	txq->tfds = NULL;
+ error:
+ 	if (txq->entries && cmd_queue)
+ 		for (i = 0; i < slots_num; i++)

commit 7dd0c9e547b6924e18712b6b51aa3cba1896ee2c
+Author: Lv Yunlong 
+Date:   Sun May 9 10:24:02 2021 +0200
+
+    media: v4l2-core: Avoid the dangling pointer in v4l2_fh_release
+    
+    A use after free bug caused by the dangling pointer
+    filp->privitate_data in v4l2_fh_release.
+    See https://lore.kernel.org/patchwork/patch/1419058/.
+    
+    My patch sets the dangling pointer to NULL to provide
+    robust.
+    
+    Signed-off-by: Lv Yunlong 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/v4l2-core/v4l2-fh.c b/drivers/media/v4l2-core/v4l2-fh.c
+index 684574f58e82..90eec79ee995 100644
+--- a/drivers/media/v4l2-core/v4l2-fh.c
++++ b/drivers/media/v4l2-core/v4l2-fh.c
+@@ -96,6 +96,7 @@ int v4l2_fh_release(struct file *filp)
+ 		v4l2_fh_del(fh);
+ 		v4l2_fh_exit(fh);
+ 		kfree(fh);
++		filp->private_data = NULL;
+ 	}
+ 	return 0;
+ }

commit 01fe904c9afd26e79c1f73aa0ca2e3d785e5e319
+Author: Lv Yunlong 
+Date:   Sun May 9 10:12:31 2021 +0200
+
+    media: exynos4-is: Fix a use after free in isp_video_release
+    
+    In isp_video_release, file->private_data is freed via
+    _vb2_fop_release()->v4l2_fh_release(). But the freed
+    file->private_data is still used in v4l2_fh_is_singular_file()
+    ->v4l2_fh_is_singular(file->private_data), which is a use
+    after free bug.
+    
+    My patch uses a variable 'is_singular_file' to avoid the uaf.
+    v3: https://lore.kernel.org/patchwork/patch/1419058/
+    
+    Fixes: 34947b8aebe3f ("[media] exynos4-is: Add the FIMC-IS ISP capture DMA driver")
+    Signed-off-by: Lv Yunlong 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.c b/drivers/media/platform/exynos4-is/fimc-isp-video.c
+index 8d9dc597deaa..83688a7982f7 100644
+--- a/drivers/media/platform/exynos4-is/fimc-isp-video.c
++++ b/drivers/media/platform/exynos4-is/fimc-isp-video.c
+@@ -305,17 +305,20 @@ static int isp_video_release(struct file *file)
+ 	struct fimc_is_video *ivc = &isp->video_capture;
+ 	struct media_entity *entity = &ivc->ve.vdev.entity;
+ 	struct media_device *mdev = entity->graph_obj.mdev;
++	bool is_singular_file;
+ 
+ 	mutex_lock(&isp->video_lock);
+ 
+-	if (v4l2_fh_is_singular_file(file) && ivc->streaming) {
++	is_singular_file = v4l2_fh_is_singular_file(file);
++
++	if (is_singular_file && ivc->streaming) {
+ 		media_pipeline_stop(entity);
+ 		ivc->streaming = 0;
+ 	}
+ 
+ 	_vb2_fop_release(file, NULL);
+ 
+-	if (v4l2_fh_is_singular_file(file)) {
++	if (is_singular_file) {
+ 		fimc_pipeline_call(&ivc->ve, close);
+ 
+ 		mutex_lock(&mdev->graph_mutex);

commit 9272e5d0028d45a3b45b58c9255e6e0df53f7ad9
+Author: Lv Yunlong 
+Date:   Mon May 24 02:32:05 2021 -0700
+
+    ipack/carriers/tpci200: Fix a double free in tpci200_pci_probe
+    
+    In the out_err_bus_register error branch of tpci200_pci_probe,
+    tpci200->info->cfg_regs is freed by tpci200_uninstall()->
+    tpci200_unregister()->pci_iounmap(..,tpci200->info->cfg_regs)
+    in the first time.
+    
+    But later, iounmap() is called to free tpci200->info->cfg_regs
+    again.
+    
+    My patch sets tpci200->info->cfg_regs to NULL after tpci200_uninstall()
+    to avoid the double free.
+    
+    Fixes: cea2f7cdff2af ("Staging: ipack/bridges/tpci200: Use the TPCI200 in big endian mode")
+    Cc: stable 
+    Acked-by: Samuel Iglesias Gonsalvez 
+    Signed-off-by: Lv Yunlong 
+    Link: https://lore.kernel.org/r/20210524093205.8333-1-lyl2019@mail.ustc.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/ipack/carriers/tpci200.c b/drivers/ipack/carriers/tpci200.c
+index ec71063fff76..e1822e87ec3d 100644
+--- a/drivers/ipack/carriers/tpci200.c
++++ b/drivers/ipack/carriers/tpci200.c
+@@ -596,8 +596,11 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
+ 
+ out_err_bus_register:
+ 	tpci200_uninstall(tpci200);
++	/* tpci200->info->cfg_regs is unmapped in tpci200_uninstall */
++	tpci200->info->cfg_regs = NULL;
+ out_err_install:
+-	iounmap(tpci200->info->cfg_regs);
++	if (tpci200->info->cfg_regs)
++		iounmap(tpci200->info->cfg_regs);
+ out_err_ioremap:
+ 	pci_release_region(pdev, TPCI200_CFG_MEM_BAR);
+ out_err_pci_request:

commit 8f3e136ff378a2b22dbc0ca2a6e58022e6df36d2
+Author: Jisheng Zhang 
+Date:   Fri May 7 22:19:59 2021 +0800
+
+    riscv: mm: Remove setup_zero_page()
+    
+    The empty_zero_page sits at .bss..page_aligned section, so will be
+    cleared to zero during clearing bss, we don't need to clear it again.
+    
+    Signed-off-by: Jisheng Zhang 
+    Reviewed-by: Anup Patel 
+    Signed-off-by: Palmer Dabbelt 
+
+diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
+index 4faf8bd157ea..11b61bea0c4d 100644
+--- a/arch/riscv/mm/init.c
++++ b/arch/riscv/mm/init.c
+@@ -67,11 +67,6 @@ static void __init zone_sizes_init(void)
+ 	free_area_init(max_zone_pfns);
+ }
+ 
+-static void __init setup_zero_page(void)
+-{
+-	memset((void *)empty_zero_page, 0, PAGE_SIZE);
+-}
+-
+ #if defined(CONFIG_MMU) && defined(CONFIG_DEBUG_VM)
+ static inline void print_mlk(char *name, unsigned long b, unsigned long t)
+ {
+@@ -867,7 +862,6 @@ RESERVEDMEM_OF_DECLARE(elfcorehdr, "linux,elfcorehdr", elfcore_hdr_setup);
+ void __init paging_init(void)
+ {
+ 	setup_vm_final();
+-	setup_zero_page();
+ }
+ 
+ void __init misc_mem_init(void)

commit 7272b591c4cb9327c43443f67b8fbae7657dd9ae
+Author: Lv Yunlong 
+Date:   Mon Apr 26 10:06:20 2021 -0700
+
+    misc/libmasm/module: Fix two use after free in ibmasm_init_one
+    
+    In ibmasm_init_one, it calls ibmasm_init_remote_input_dev().
+    Inside ibmasm_init_remote_input_dev, mouse_dev and keybd_dev are
+    allocated by input_allocate_device(), and assigned to
+    sp->remote.mouse_dev and sp->remote.keybd_dev respectively.
+    
+    In the err_free_devices error branch of ibmasm_init_one,
+    mouse_dev and keybd_dev are freed by input_free_device(), and return
+    error. Then the execution runs into error_send_message error branch
+    of ibmasm_init_one, where ibmasm_free_remote_input_dev(sp) is called
+    to unregister the freed sp->remote.mouse_dev and sp->remote.keybd_dev.
+    
+    My patch add a "error_init_remote" label to handle the error of
+    ibmasm_init_remote_input_dev(), to avoid the uaf bugs.
+    
+    Signed-off-by: Lv Yunlong 
+    Link: https://lore.kernel.org/r/20210426170620.10546-1-lyl2019@mail.ustc.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c
+index 4edad6c445d3..dc8a06c06c63 100644
+--- a/drivers/misc/ibmasm/module.c
++++ b/drivers/misc/ibmasm/module.c
+@@ -111,7 +111,7 @@ static int ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	result = ibmasm_init_remote_input_dev(sp);
+ 	if (result) {
+ 		dev_err(sp->dev, "Failed to initialize remote queue\n");
+-		goto error_send_message;
++		goto error_init_remote;
+ 	}
+ 
+ 	result = ibmasm_send_driver_vpd(sp);
+@@ -131,8 +131,9 @@ static int ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	return 0;
+ 
+ error_send_message:
+-	disable_sp_interrupts(sp->base_address);
+ 	ibmasm_free_remote_input_dev(sp);
++error_init_remote:
++	disable_sp_interrupts(sp->base_address);
+ 	free_irq(sp->irq, (void *)sp);
+ error_request_irq:
+ 	iounmap(sp->base_address);

commit ea995218dddba171fecd05496c69617c5ef3c5b8
+Author: Lv Yunlong 
+Date:   Mon Apr 26 05:43:40 2021 -0700
+
+    drm/i915/gt: Fix a double free in gen8_preallocate_top_level_pdp
+    
+    Our code analyzer reported a double free bug.
+    
+    In gen8_preallocate_top_level_pdp, pde and pde->pt.base are allocated
+    via alloc_pd(vm) with one reference. If pin_pt_dma() failed, pde->pt.base
+    is freed by i915_gem_object_put() with a reference dropped. Then free_pd
+    calls free_px() defined in intel_ppgtt.c, which calls i915_gem_object_put()
+    to put pde->pt.base again.
+    
+    As pde->pt.base is protected by refcount, so the second put will not free
+    pde->pt.base actually. But, maybe it is better to remove the first put?
+    
+    Fixes: 82adf901138cc ("drm/i915/gt: Shrink i915_page_directory's slab bucket")
+    Signed-off-by: Lv Yunlong 
+    Reviewed-by: Matthew Auld 
+    Signed-off-by: Matthew Auld 
+    Link: https://patchwork.freedesktop.org/patch/msgid/20210426124340.4238-1-lyl2019@mail.ustc.edu.cn
+    (cherry picked from commit ac69496fe65cca0611d5917b7d232730ff605bc7)
+    Signed-off-by: Jani Nikula 
+
+diff --git a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c
+index 176c19633412..74bf6fc8461f 100644
+--- a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c
++++ b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c
+@@ -641,7 +641,6 @@ static int gen8_preallocate_top_level_pdp(struct i915_ppgtt *ppgtt)
+ 
+ 		err = pin_pt_dma(vm, pde->pt.base);
+ 		if (err) {
+-			i915_gem_object_put(pde->pt.base);
+ 			free_pd(vm, pde);
+ 			return err;
+ 		}

commit 115726c5d312b462c9d9931ea42becdfa838a076
+Author: Lv Yunlong 
+Date:   Mon Apr 26 06:43:46 2021 -0700
+
+    habanalabs/gaudi: Fix a potential use after free in gaudi_memset_device_memory
+    
+    Our code analyzer reported a uaf.
+    
+    In gaudi_memset_device_memory, cb is get via hl_cb_kernel_create()
+    with 2 refcount.
+    If hl_cs_allocate_job() failed, the execution runs into release_cb
+    branch. One ref of cb is dropped by hl_cb_put(cb) and could be freed
+    if other thread also drops one ref. Then cb is used by cb->id later,
+    which is a potential uaf.
+    
+    My patch add a variable 'id' to accept the value of cb->id before the
+    hl_cb_put(cb) is called, to avoid the potential uaf.
+    
+    Fixes: 423815bf02e25 ("habanalabs/gaudi: remove PCI access to SM block")
+    Signed-off-by: Lv Yunlong 
+    Reviewed-by: Oded Gabbay 
+    Signed-off-by: Oded Gabbay 
+
+diff --git a/drivers/misc/habanalabs/gaudi/gaudi.c b/drivers/misc/habanalabs/gaudi/gaudi.c
+index 81155f06c126..9e4a6bb3acd1 100644
+--- a/drivers/misc/habanalabs/gaudi/gaudi.c
++++ b/drivers/misc/habanalabs/gaudi/gaudi.c
+@@ -5579,6 +5579,7 @@ static int gaudi_memset_device_memory(struct hl_device *hdev, u64 addr,
+ 	struct hl_cs_job *job;
+ 	u32 cb_size, ctl, err_cause;
+ 	struct hl_cb *cb;
++	u64 id;
+ 	int rc;
+ 
+ 	cb = hl_cb_kernel_create(hdev, PAGE_SIZE, false);
+@@ -5645,8 +5646,9 @@ static int gaudi_memset_device_memory(struct hl_device *hdev, u64 addr,
+ 	}
+ 
+ release_cb:
++	id = cb->id;
+ 	hl_cb_put(cb);
+-	hl_cb_destroy(hdev, &hdev->kernel_cb_mgr, cb->id << PAGE_SHIFT);
++	hl_cb_destroy(hdev, &hdev->kernel_cb_mgr, id << PAGE_SHIFT);
+ 
+ 	return rc;
+ }

commit 643001b47adc844ae33510c4bb93c236667008a3
+Author: Lv Yunlong 
+Date:   Sun May 2 04:58:18 2021 -0700
+
+    ethernet:enic: Fix a use after free bug in enic_hard_start_xmit
+    
+    In enic_hard_start_xmit, it calls enic_queue_wq_skb(). Inside
+    enic_queue_wq_skb, if some error happens, the skb will be freed
+    by dev_kfree_skb(skb). But the freed skb is still used in
+    skb_tx_timestamp(skb).
+    
+    My patch makes enic_queue_wq_skb() return error and goto spin_unlock()
+    incase of error. The solution is provided by Govind.
+    See https://lkml.org/lkml/2021/4/30/961.
+    
+    Fixes: fb7516d42478e ("enic: add sw timestamp support")
+    Signed-off-by: Lv Yunlong 
+    Acked-by: Govindarajulu Varadarajan 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
+index f48957a17c3a..d0a8f7106958 100644
+--- a/drivers/net/ethernet/cisco/enic/enic_main.c
++++ b/drivers/net/ethernet/cisco/enic/enic_main.c
+@@ -768,7 +768,7 @@ static inline int enic_queue_wq_skb_encap(struct enic *enic, struct vnic_wq *wq,
+ 	return err;
+ }
+ 
+-static inline void enic_queue_wq_skb(struct enic *enic,
++static inline int enic_queue_wq_skb(struct enic *enic,
+ 	struct vnic_wq *wq, struct sk_buff *skb)
+ {
+ 	unsigned int mss = skb_shinfo(skb)->gso_size;
+@@ -814,6 +814,7 @@ static inline void enic_queue_wq_skb(struct enic *enic,
+ 		wq->to_use = buf->next;
+ 		dev_kfree_skb(skb);
+ 	}
++	return err;
+ }
+ 
+ /* netif_tx_lock held, process context with BHs disabled, or BH */
+@@ -857,7 +858,8 @@ static netdev_tx_t enic_hard_start_xmit(struct sk_buff *skb,
+ 		return NETDEV_TX_BUSY;
+ 	}
+ 
+-	enic_queue_wq_skb(enic, wq, skb);
++	if (enic_queue_wq_skb(enic, wq, skb))
++		goto error;
+ 
+ 	if (vnic_wq_desc_avail(wq) < MAX_SKB_FRAGS + ENIC_DESC_MAX_SPLITS)
+ 		netif_tx_stop_queue(txq);
+@@ -865,6 +867,7 @@ static netdev_tx_t enic_hard_start_xmit(struct sk_buff *skb,
+ 	if (!netdev_xmit_more() || netif_xmit_stopped(txq))
+ 		vnic_wq_doorbell(wq);
+ 
++error:
+ 	spin_unlock(&enic->wq_lock[txq_map]);
+ 
+ 	return NETDEV_TX_OK;

commit 75258586793efc521e5dd52a5bf6c7a4cf7002be
+Author: Lv Yunlong 
+Date:   Tue Apr 27 09:22:58 2021 -0700
+
+    net:nfc:digital: Fix a double free in digital_tg_recv_dep_req
+    
+    In digital_tg_recv_dep_req, it calls nfc_tm_data_received(..,resp).
+    If nfc_tm_data_received() failed, the callee will free the resp via
+    kfree_skb() and return error. But in the exit branch, the resp
+    will be freed again.
+    
+    My patch sets resp to NULL if nfc_tm_data_received() failed, to
+    avoid the double free.
+    
+    Fixes: 1c7a4c24fbfd9 ("NFC Digital: Add target NFC-DEP support")
+    Signed-off-by: Lv Yunlong 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/nfc/digital_dep.c b/net/nfc/digital_dep.c
+index 1150731126e2..3982fa084737 100644
+--- a/net/nfc/digital_dep.c
++++ b/net/nfc/digital_dep.c
+@@ -1273,6 +1273,8 @@ static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg,
+ 	}
+ 
+ 	rc = nfc_tm_data_received(ddev->nfc_dev, resp);
++	if (rc)
++		resp = NULL;
+ 
+ exit:
+ 	kfree_skb(ddev->chaining_skb);

commit 34b39efa5ae82fc0ad0acc27653c12a56328dbbe
+Author: Lv Yunlong 
+Date:   Mon Apr 26 07:06:14 2021 -0700
+
+    RDMA/bnxt_re: Fix a double free in bnxt_qplib_alloc_res
+    
+    In bnxt_qplib_alloc_res, it calls bnxt_qplib_alloc_dpi_tbl().  Inside
+    bnxt_qplib_alloc_dpi_tbl, dpit->dbr_bar_reg_iomem is freed via
+    pci_iounmap() in unmap_io error branch. After the callee returns err code,
+    bnxt_qplib_alloc_res calls
+    bnxt_qplib_free_res()->bnxt_qplib_free_dpi_tbl() in the fail branch. Then
+    dpit->dbr_bar_reg_iomem is freed in the second time by pci_iounmap().
+    
+    My patch set dpit->dbr_bar_reg_iomem to NULL after it is freed by
+    pci_iounmap() in the first time, to avoid the double free.
+    
+    Fixes: 1ac5a4047975 ("RDMA/bnxt_re: Add bnxt_re RoCE driver")
+    Link: https://lore.kernel.org/r/20210426140614.6722-1-lyl2019@mail.ustc.edu.cn
+    Signed-off-by: Lv Yunlong 
+    Reviewed-by: Leon Romanovsky 
+    Acked-by: Devesh Sharma 
+    Signed-off-by: Jason Gunthorpe 
+
+diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.c b/drivers/infiniband/hw/bnxt_re/qplib_res.c
+index fa7878336100..3ca47004b752 100644
+--- a/drivers/infiniband/hw/bnxt_re/qplib_res.c
++++ b/drivers/infiniband/hw/bnxt_re/qplib_res.c
+@@ -854,6 +854,7 @@ static int bnxt_qplib_alloc_dpi_tbl(struct bnxt_qplib_res     *res,
+ 
+ unmap_io:
+ 	pci_iounmap(res->pdev, dpit->dbr_bar_reg_iomem);
++	dpit->dbr_bar_reg_iomem = NULL;
+ 	return -ENOMEM;
+ }
+ 

commit 3093ee182f01689b89e9f8797b321603e5de4f63
+Author: Lv Yunlong 
+Date:   Sun Apr 25 18:16:47 2021 -0700
+
+    RDMA/siw: Fix a use after free in siw_alloc_mr
+    
+    Our code analyzer reported a UAF.
+    
+    In siw_alloc_mr(), it calls siw_mr_add_mem(mr,..). In the implementation of
+    siw_mr_add_mem(), mem is assigned to mr->mem and then mem is freed via
+    kfree(mem) if xa_alloc_cyclic() failed. Here, mr->mem still point to a
+    freed object. After, the execution continue up to the err_out branch of
+    siw_alloc_mr, and the freed mr->mem is used in siw_mr_drop_mem(mr).
+    
+    My patch moves "mr->mem = mem" behind the if (xa_alloc_cyclic(..)<0) {}
+    section, to avoid the uaf.
+    
+    Fixes: 2251334dcac9 ("rdma/siw: application buffer management")
+    Link: https://lore.kernel.org/r/20210426011647.3561-1-lyl2019@mail.ustc.edu.cn
+    Signed-off-by: Lv Yunlong 
+    Reviewed-by: Bernard Metzler 
+    Signed-off-by: Jason Gunthorpe 
+
+diff --git a/drivers/infiniband/sw/siw/siw_mem.c b/drivers/infiniband/sw/siw/siw_mem.c
+index 34a910cf0edb..61c17db70d65 100644
+--- a/drivers/infiniband/sw/siw/siw_mem.c
++++ b/drivers/infiniband/sw/siw/siw_mem.c
+@@ -106,8 +106,6 @@ int siw_mr_add_mem(struct siw_mr *mr, struct ib_pd *pd, void *mem_obj,
+ 	mem->perms = rights & IWARP_ACCESS_MASK;
+ 	kref_init(&mem->ref);
+ 
+-	mr->mem = mem;
+-
+ 	get_random_bytes(&next, 4);
+ 	next &= 0x00ffffff;
+ 
+@@ -116,6 +114,8 @@ int siw_mr_add_mem(struct siw_mr *mr, struct ib_pd *pd, void *mem_obj,
+ 		kfree(mem);
+ 		return -ENOMEM;
+ 	}
++
++	mr->mem = mem;
+ 	/* Set the STag index part */
+ 	mem->stag = id << 8;
+ 	mr->base_mr.lkey = mr->base_mr.rkey = mem->stag;

commit ac69496fe65cca0611d5917b7d232730ff605bc7
+Author: Lv Yunlong 
+Date:   Mon Apr 26 05:43:40 2021 -0700
+
+    drm/i915/gt: Fix a double free in gen8_preallocate_top_level_pdp
+    
+    Our code analyzer reported a double free bug.
+    
+    In gen8_preallocate_top_level_pdp, pde and pde->pt.base are allocated
+    via alloc_pd(vm) with one reference. If pin_pt_dma() failed, pde->pt.base
+    is freed by i915_gem_object_put() with a reference dropped. Then free_pd
+    calls free_px() defined in intel_ppgtt.c, which calls i915_gem_object_put()
+    to put pde->pt.base again.
+    
+    As pde->pt.base is protected by refcount, so the second put will not free
+    pde->pt.base actually. But, maybe it is better to remove the first put?
+    
+    Fixes: 82adf901138cc ("drm/i915/gt: Shrink i915_page_directory's slab bucket")
+    Signed-off-by: Lv Yunlong 
+    Reviewed-by: Matthew Auld 
+    Signed-off-by: Matthew Auld 
+    Link: https://patchwork.freedesktop.org/patch/msgid/20210426124340.4238-1-lyl2019@mail.ustc.edu.cn
+
+diff --git a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c
+index 176c19633412..74bf6fc8461f 100644
+--- a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c
++++ b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c
+@@ -641,7 +641,6 @@ static int gen8_preallocate_top_level_pdp(struct i915_ppgtt *ppgtt)
+ 
+ 		err = pin_pt_dma(vm, pde->pt.base);
+ 		if (err) {
+-			i915_gem_object_put(pde->pt.base);
+ 			free_pd(vm, pde);
+ 			return err;
+ 		}

commit 6d72e7c767acbbdd44ebc7d89c6690b405b32b57
+Author: Lv Yunlong 
+Date:   Mon Apr 26 09:06:25 2021 -0700
+
+    net:emac/emac-mac: Fix a use after free in emac_mac_tx_buf_send
+    
+    In emac_mac_tx_buf_send, it calls emac_tx_fill_tpd(..,skb,..).
+    If some error happens in emac_tx_fill_tpd(), the skb will be freed via
+    dev_kfree_skb(skb) in error branch of emac_tx_fill_tpd().
+    But the freed skb is still used via skb->len by netdev_sent_queue(,skb->len).
+    
+    As i observed that emac_tx_fill_tpd() haven't modified the value of skb->len,
+    thus my patch assigns skb->len to 'len' before the possible free and
+    use 'len' instead of skb->len later.
+    
+    Fixes: b9b17debc69d2 ("net: emac: emac gigabit ethernet controller driver")
+    Signed-off-by: Lv Yunlong 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/qualcomm/emac/emac-mac.c b/drivers/net/ethernet/qualcomm/emac/emac-mac.c
+index 117188e3c7de..87b8c032195d 100644
+--- a/drivers/net/ethernet/qualcomm/emac/emac-mac.c
++++ b/drivers/net/ethernet/qualcomm/emac/emac-mac.c
+@@ -1437,6 +1437,7 @@ netdev_tx_t emac_mac_tx_buf_send(struct emac_adapter *adpt,
+ {
+ 	struct emac_tpd tpd;
+ 	u32 prod_idx;
++	int len;
+ 
+ 	memset(&tpd, 0, sizeof(tpd));
+ 
+@@ -1456,9 +1457,10 @@ netdev_tx_t emac_mac_tx_buf_send(struct emac_adapter *adpt,
+ 	if (skb_network_offset(skb) != ETH_HLEN)
+ 		TPD_TYP_SET(&tpd, 1);
+ 
++	len = skb->len;
+ 	emac_tx_fill_tpd(adpt, tx_q, skb, &tpd);
+ 
+-	netdev_sent_queue(adpt->netdev, skb->len);
++	netdev_sent_queue(adpt->netdev, len);
+ 
+ 	/* Make sure the are enough free descriptors to hold one
+ 	 * maximum-sized SKB.  We need one desc for each fragment,

commit 4fb44dd2c1dda18606348acdfdb97e8759dde9df
+Author: Lv Yunlong 
+Date:   Mon Apr 26 07:55:41 2021 -0700
+
+    ALSA: sb: Fix two use after free in snd_sb_qsound_build
+    
+    In snd_sb_qsound_build, snd_ctl_add(..,p->qsound_switch...) and
+    snd_ctl_add(..,p->qsound_space..) are called. But the second
+    arguments of snd_ctl_add() could be freed via snd_ctl_add_replace()
+    ->snd_ctl_free_one(). After the error code is returned,
+    snd_sb_qsound_destroy(p) is called in __error branch.
+    
+    But in snd_sb_qsound_destroy(), the freed p->qsound_switch and
+    p->qsound_space are still used by snd_ctl_remove().
+    
+    My patch set p->qsound_switch and p->qsound_space to NULL if
+    snd_ctl_add() failed to avoid the uaf bugs. But these codes need
+    to further be improved with the code style.
+    
+    Signed-off-by: Lv Yunlong 
+    Cc: 
+    Link: https://lore.kernel.org/r/20210426145541.8070-1-lyl2019@mail.ustc.edu.cn
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c
+index 8635a2b6b36b..4789345a8fdd 100644
+--- a/sound/isa/sb/sb16_csp.c
++++ b/sound/isa/sb/sb16_csp.c
+@@ -1045,10 +1045,14 @@ static int snd_sb_qsound_build(struct snd_sb_csp * p)
+ 
+ 	spin_lock_init(&p->q_lock);
+ 
+-	if ((err = snd_ctl_add(card, p->qsound_switch = snd_ctl_new1(&snd_sb_qsound_switch, p))) < 0)
++	if ((err = snd_ctl_add(card, p->qsound_switch = snd_ctl_new1(&snd_sb_qsound_switch, p))) < 0) {
++		p->qsound_switch = NULL;
+ 		goto __error;
+-	if ((err = snd_ctl_add(card, p->qsound_space = snd_ctl_new1(&snd_sb_qsound_space, p))) < 0)
++	}
++	if ((err = snd_ctl_add(card, p->qsound_space = snd_ctl_new1(&snd_sb_qsound_space, p))) < 0) {
++		p->qsound_space = NULL;
+ 		goto __error;
++	}
+ 
+ 	return 0;
+ 

commit 72ce11ddfa4e9e1879103581a60b7e34547eaa0a
+Author: Lv Yunlong 
+Date:   Mon Apr 26 07:32:29 2021 -0700
+
+    drivers/block/null_blk/main: Fix a double free in null_init.
+    
+    In null_init, null_add_dev(dev) is called.
+    In null_add_dev, it calls null_free_zoned_dev(dev) to free dev->zones
+    via kvfree(dev->zones) in out_cleanup_zone branch and returns err.
+    Then null_init accept the err code and then calls null_free_dev(dev).
+    
+    But in null_free_dev(dev), dev->zones is freed again by
+    null_free_zoned_dev().
+    
+    My patch set dev->zones to NULL in null_free_zoned_dev() after
+    kvfree(dev->zones) is called, to avoid the double free.
+    
+    Fixes: 2984c8684f962 ("nullb: factor disk parameters")
+    Signed-off-by: Lv Yunlong 
+    Link: https://lore.kernel.org/r/20210426143229.7374-1-lyl2019@mail.ustc.edu.cn
+    Signed-off-by: Jens Axboe 
+
+diff --git a/drivers/block/null_blk/zoned.c b/drivers/block/null_blk/zoned.c
+index bfcab1c782b5..dae54dd1aeac 100644
+--- a/drivers/block/null_blk/zoned.c
++++ b/drivers/block/null_blk/zoned.c
+@@ -180,6 +180,7 @@ int null_register_zoned_dev(struct nullb *nullb)
+ void null_free_zoned_dev(struct nullb_device *dev)
+ {
+ 	kvfree(dev->zones);
++	dev->zones = NULL;
+ }
+ 
+ int null_report_zones(struct gendisk *disk, sector_t sector,

commit 1c98f574403dbcf2eb832d5535a10d967333ef2d
+Author: Lv Yunlong 
+Date:   Mon Apr 26 06:11:29 2021 -0700
+
+    ALSA: emu8000: Fix a use after free in snd_emu8000_create_mixer
+    
+    Our code analyzer reported a uaf.
+    
+    In snd_emu8000_create_mixer, the callee snd_ctl_add(..,emu->controls[i])
+    calls snd_ctl_add_replace(.., kcontrol,..). Inside snd_ctl_add_replace(),
+    if error happens, kcontrol will be freed by snd_ctl_free_one(kcontrol).
+    Then emu->controls[i] points to a freed memory, and the execution comes
+    to __error branch of snd_emu8000_create_mixer. The freed emu->controls[i]
+    is used in snd_ctl_remove(card, emu->controls[i]).
+    
+    My patch set emu->controls[i] to NULL if snd_ctl_add() failed to avoid
+    the uaf.
+    
+    Signed-off-by: Lv Yunlong 
+    Cc: 
+    Link: https://lore.kernel.org/r/20210426131129.4796-1-lyl2019@mail.ustc.edu.cn
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c
+index 0aa545ac6e60..1c90421a88dc 100644
+--- a/sound/isa/sb/emu8000.c
++++ b/sound/isa/sb/emu8000.c
+@@ -1029,8 +1029,10 @@ snd_emu8000_create_mixer(struct snd_card *card, struct snd_emu8000 *emu)
+ 
+ 	memset(emu->controls, 0, sizeof(emu->controls));
+ 	for (i = 0; i < EMU8000_NUM_CONTROLS; i++) {
+-		if ((err = snd_ctl_add(card, emu->controls[i] = snd_ctl_new1(mixer_defs[i], emu))) < 0)
++		if ((err = snd_ctl_add(card, emu->controls[i] = snd_ctl_new1(mixer_defs[i], emu))) < 0) {
++			emu->controls[i] = NULL;
+ 			goto __error;
++		}
+ 	}
+ 	return 0;
+ 

commit 8392df5d7e0b6a7d21440da1fc259f9938f4dec3
+Author: Lv Yunlong 
+Date:   Mon Mar 29 05:01:54 2021 -0700
+
+    ath10k: Fix a use after free in ath10k_htc_send_bundle
+    
+    In ath10k_htc_send_bundle, the bundle_skb could be freed by
+    dev_kfree_skb_any(bundle_skb). But the bundle_skb is used later
+    by bundle_skb->len.
+    
+    As skb_len = bundle_skb->len, my patch replaces bundle_skb->len to
+    skb_len after the bundle_skb was freed.
+    
+    Fixes: c8334512f3dd1 ("ath10k: add htt TX bundle for sdio")
+    Signed-off-by: Lv Yunlong 
+    Signed-off-by: Kalle Valo 
+    Link: https://lore.kernel.org/r/20210329120154.8963-1-lyl2019@mail.ustc.edu.cn
+
+diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
+index 0a37be6a7d33..fab398046a3f 100644
+--- a/drivers/net/wireless/ath/ath10k/htc.c
++++ b/drivers/net/wireless/ath/ath10k/htc.c
+@@ -669,7 +669,7 @@ static int ath10k_htc_send_bundle(struct ath10k_htc_ep *ep,
+ 
+ 	ath10k_dbg(ar, ATH10K_DBG_HTC,
+ 		   "bundle tx status %d eid %d req count %d count %d len %d\n",
+-		   ret, ep->eid, skb_queue_len(&ep->tx_req_head), cn, bundle_skb->len);
++		   ret, ep->eid, skb_queue_len(&ep->tx_req_head), cn, skb_len);
+ 	return ret;
+ }
+ 

commit a8e083ee8e2a6c94c29733835adae8bf5b832748
+Author: Lv Yunlong 
+Date:   Fri Apr 2 11:26:27 2021 -0700
+
+    mwl8k: Fix a double Free in mwl8k_probe_hw
+    
+    In mwl8k_probe_hw, hw->priv->txq is freed at the first time by
+    dma_free_coherent() in the call chain:
+    if(!priv->ap_fw)->mwl8k_init_txqs(hw)->mwl8k_txq_init(hw, i).
+    
+    Then in err_free_queues of mwl8k_probe_hw, hw->priv->txq is freed
+    at the second time by mwl8k_txq_deinit(hw, i)->dma_free_coherent().
+    
+    My patch set txq->txd to NULL after the first free to avoid the
+    double free.
+    
+    Fixes: a66098daacee2 ("mwl8k: Marvell TOPDOG wireless driver")
+    Signed-off-by: Lv Yunlong 
+    Signed-off-by: Kalle Valo 
+    Link: https://lore.kernel.org/r/20210402182627.4256-1-lyl2019@mail.ustc.edu.cn
+
+diff --git a/drivers/net/wireless/marvell/mwl8k.c b/drivers/net/wireless/marvell/mwl8k.c
+index c9f8c056aa51..84b32a5f01ee 100644
+--- a/drivers/net/wireless/marvell/mwl8k.c
++++ b/drivers/net/wireless/marvell/mwl8k.c
+@@ -1473,6 +1473,7 @@ static int mwl8k_txq_init(struct ieee80211_hw *hw, int index)
+ 	if (txq->skb == NULL) {
+ 		dma_free_coherent(&priv->pdev->dev, size, txq->txd,
+ 				  txq->txd_dma);
++		txq->txd = NULL;
+ 		return -ENOMEM;
+ 	}
+ 

commit ea45b6008f8095db0cc09ad6e03c7785c2986197
+Author: Lv Yunlong 
+Date:   Tue Mar 30 18:44:58 2021 -0700
+
+    dmaengine: Fix a double free in dma_async_device_register
+    
+    In the first list_for_each_entry() macro of dma_async_device_register,
+    it gets the chan from list and calls __dma_async_device_channel_register
+    (..,chan). We can see that chan->local is allocated by alloc_percpu() and
+    it is freed chan->local by free_percpu(chan->local) when
+    __dma_async_device_channel_register() failed.
+    
+    But after __dma_async_device_channel_register() failed, the caller will
+    goto err_out and freed the chan->local in the second time by free_percpu().
+    
+    The cause of this problem is forget to set chan->local to NULL when
+    chan->local was freed in __dma_async_device_channel_register(). My
+    patch sets chan->local to NULL when the callee failed to avoid double free.
+    
+    Fixes: d2fb0a0438384 ("dmaengine: break out channel registration")
+    Signed-off-by: Lv Yunlong 
+    Reviewed-by: Dave Jiang 
+    Link: https://lore.kernel.org/r/20210331014458.3944-1-lyl2019@mail.ustc.edu.cn
+    Signed-off-by: Vinod Koul 
+
+diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
+index fe6a460c4373..af3ee288bc11 100644
+--- a/drivers/dma/dmaengine.c
++++ b/drivers/dma/dmaengine.c
+@@ -1086,6 +1086,7 @@ static int __dma_async_device_channel_register(struct dma_device *device,
+ 	kfree(chan->dev);
+  err_free_local:
+ 	free_percpu(chan->local);
++	chan->local = NULL;
+ 	return rc;
+ }
+ 

commit f7cae626cabb3350b23722b78fe34dd7a615ca04
+Author: Lv Yunlong 
+Date:   Fri Apr 2 10:13:48 2021 -0700
+
+    crypto: qat - Fix a double free in adf_create_ring
+    
+    In adf_create_ring, if the callee adf_init_ring() failed, the callee will
+    free the ring->base_addr by dma_free_coherent() and return -EFAULT. Then
+    adf_create_ring will goto err and the ring->base_addr will be freed again
+    in adf_cleanup_ring().
+    
+    My patch sets ring->base_addr to NULL after the first freed to avoid the
+    double free.
+    
+    Fixes: a672a9dc872ec ("crypto: qat - Intel(R) QAT transport code")
+    Signed-off-by: Lv Yunlong 
+    Signed-off-by: Herbert Xu 
+
+diff --git a/drivers/crypto/qat/qat_common/adf_transport.c b/drivers/crypto/qat/qat_common/adf_transport.c
+index 888c1e047295..8ba28409fb74 100644
+--- a/drivers/crypto/qat/qat_common/adf_transport.c
++++ b/drivers/crypto/qat/qat_common/adf_transport.c
+@@ -172,6 +172,7 @@ static int adf_init_ring(struct adf_etr_ring_data *ring)
+ 		dev_err(&GET_DEV(accel_dev), "Ring address not aligned\n");
+ 		dma_free_coherent(&GET_DEV(accel_dev), ring_size_bytes,
+ 				  ring->base_addr, ring->dma_addr);
++		ring->base_addr = NULL;
+ 		return -EFAULT;
+ 	}
+ 

commit 076de75de1e53160e9b099f75872c1f9adf41a0b
+Author: Lv Yunlong 
+Date:   Fri Apr 2 23:09:05 2021 -0700
+
+    mtd: rawnand: gpmi: Fix a double free in gpmi_nand_init
+    
+    If the callee gpmi_alloc_dma_buffer() failed to alloc memory for
+    this->raw_buffer, gpmi_free_dma_buffer() will be called to free
+    this->auxiliary_virt. But this->auxiliary_virt is still a non-NULL
+    and valid ptr.
+    
+    Then gpmi_alloc_dma_buffer() returns err and gpmi_free_dma_buffer()
+    is called again to free this->auxiliary_virt in err_out. This causes
+    a double free.
+    
+    As gpmi_free_dma_buffer() has already called in gpmi_alloc_dma_buffer's
+    error path, so it should return err directly instead of releasing the dma
+    buffer again.
+    
+    Fixes: 4d02423e9afe6 ("mtd: nand: gpmi: Fix gpmi_nand_init() error path")
+    Signed-off-by: Lv Yunlong 
+    Signed-off-by: Miquel Raynal 
+    Link: https://lore.kernel.org/linux-mtd/20210403060905.5251-1-lyl2019@mail.ustc.edu.cn
+
+diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+index 3fa8c22d3f36..4d08e4ab5c1b 100644
+--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
++++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+@@ -2449,7 +2449,7 @@ static int gpmi_nand_init(struct gpmi_nand_data *this)
+ 	this->bch_geometry.auxiliary_size = 128;
+ 	ret = gpmi_alloc_dma_buffer(this);
+ 	if (ret)
+-		goto err_out;
++		return ret;
+ 
+ 	nand_controller_init(&this->base);
+ 	this->base.ops = &gpmi_nand_controller_ops;

commit b25b343db0526669947a427e9a31bac91d29bb06
+Author: Lv Yunlong 
+Date:   Fri Apr 2 10:40:19 2021 -0700
+
+    net: broadcom: bcm4908enet: Fix a double free in bcm4908_enet_dma_alloc
+    
+    In bcm4908_enet_dma_alloc, if callee bcm4908_dma_alloc_buf_descs() failed,
+    it will free the ring->cpu_addr by dma_free_coherent() and return error.
+    Then bcm4908_enet_dma_free() will be called, and free the same cpu_addr
+    by dma_free_coherent() again.
+    
+    My patch set ring->cpu_addr to NULL after it is freed in
+    bcm4908_dma_alloc_buf_descs() to avoid the double free.
+    
+    Fixes: 4feffeadbcb2e ("net: broadcom: bcm4908enet: add BCM4908 controller driver")
+    Signed-off-by: Lv Yunlong 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/broadcom/bcm4908_enet.c b/drivers/net/ethernet/broadcom/bcm4908_enet.c
+index 98cf82dea3e4..65981931a798 100644
+--- a/drivers/net/ethernet/broadcom/bcm4908_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm4908_enet.c
+@@ -172,6 +172,7 @@ static int bcm4908_dma_alloc_buf_descs(struct bcm4908_enet *enet,
+ 
+ err_free_buf_descs:
+ 	dma_free_coherent(dev, size, ring->cpu_addr, ring->dma_addr);
++	ring->cpu_addr = NULL;
+ 	return -ENOMEM;
+ }
+ 

commit bdc2ab5c61a5c07388f4820ff21e787b4dfd1ced
+Author: Lv Yunlong 
+Date:   Tue Mar 30 18:59:59 2021 -0700
+
+    net/rds: Fix a use after free in rds_message_map_pages
+    
+    In rds_message_map_pages, the rm is freed by rds_message_put(rm).
+    But rm is still used by rm->data.op_sg in return value.
+    
+    My patch assigns ERR_CAST(rm->data.op_sg) to err before the rm is
+    freed to avoid the uaf.
+    
+    Fixes: 7dba92037baf3 ("net/rds: Use ERR_PTR for rds_message_alloc_sgs()")
+    Signed-off-by: Lv Yunlong 
+    Reviewed-by: Håkon Bugge 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/rds/message.c b/net/rds/message.c
+index 071a261fdaab..799034e0f513 100644
+--- a/net/rds/message.c
++++ b/net/rds/message.c
+@@ -347,8 +347,9 @@ struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned in
+ 	rm->data.op_nents = DIV_ROUND_UP(total_len, PAGE_SIZE);
+ 	rm->data.op_sg = rds_message_alloc_sgs(rm, num_sgs);
+ 	if (IS_ERR(rm->data.op_sg)) {
++		void *err = ERR_CAST(rm->data.op_sg);
+ 		rds_message_put(rm);
+-		return ERR_CAST(rm->data.op_sg);
++		return err;
+ 	}
+ 
+ 	for (i = 0; i < rm->data.op_nents; ++i) {

commit 6e5a03bcba44e080a6bf300194a68ce9bb1e5184
+Author: Lv Yunlong 
+Date:   Mon Mar 29 04:50:02 2021 -0700
+
+    ethernet/netronome/nfp: Fix a use after free in nfp_bpf_ctrl_msg_rx
+    
+    In nfp_bpf_ctrl_msg_rx, if
+    nfp_ccm_get_type(skb) == NFP_CCM_TYPE_BPF_BPF_EVENT is true, the skb
+    will be freed. But the skb is still used by nfp_ccm_rx(&bpf->ccm, skb).
+    
+    My patch adds a return when the skb was freed.
+    
+    Fixes: bcf0cafab44fd ("nfp: split out common control message handling code")
+    Signed-off-by: Lv Yunlong 
+    Reviewed-by: Jakub Kicinski 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/netronome/nfp/bpf/cmsg.c b/drivers/net/ethernet/netronome/nfp/bpf/cmsg.c
+index 0e2db6ea79e9..2ec62c8d86e1 100644
+--- a/drivers/net/ethernet/netronome/nfp/bpf/cmsg.c
++++ b/drivers/net/ethernet/netronome/nfp/bpf/cmsg.c
+@@ -454,6 +454,7 @@ void nfp_bpf_ctrl_msg_rx(struct nfp_app *app, struct sk_buff *skb)
+ 			dev_consume_skb_any(skb);
+ 		else
+ 			dev_kfree_skb_any(skb);
++		return;
+ 	}
+ 
+ 	nfp_ccm_rx(&bpf->ccm, skb);

commit 6bf24dc0cc0cc43b29ba344b66d78590e687e046
+Author: Lv Yunlong 
+Date:   Sun Mar 28 00:30:29 2021 -0700
+
+    net:tipc: Fix a double free in tipc_sk_mcast_rcv
+    
+    In the if(skb_peek(arrvq) == skb) branch, it calls __skb_dequeue(arrvq) to get
+    the skb by skb = skb_peek(arrvq). Then __skb_dequeue() unlinks the skb from arrvq
+    and returns the skb which equals to skb_peek(arrvq). After __skb_dequeue(arrvq)
+    finished, the skb is freed by kfree_skb(__skb_dequeue(arrvq)) in the first time.
+    
+    Unfortunately, the same skb is freed in the second time by kfree_skb(skb) after
+    the branch completed.
+    
+    My patch removes kfree_skb() in the if(skb_peek(arrvq) == skb) branch, because
+    this skb will be freed by kfree_skb(skb) finally.
+    
+    Fixes: cb1b728096f54 ("tipc: eliminate race condition at multicast reception")
+    Signed-off-by: Lv Yunlong 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/tipc/socket.c b/net/tipc/socket.c
+index cebcc104dc70..022999e0202d 100644
+--- a/net/tipc/socket.c
++++ b/net/tipc/socket.c
+@@ -1265,7 +1265,7 @@ void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq,
+ 		spin_lock_bh(&inputq->lock);
+ 		if (skb_peek(arrvq) == skb) {
+ 			skb_queue_splice_tail_init(&tmpq, inputq);
+-			kfree_skb(__skb_dequeue(arrvq));
++			__skb_dequeue(arrvq);
+ 		}
+ 		spin_unlock_bh(&inputq->lock);
+ 		__skb_queue_purge(&tmpq);

commit 63415767a2446136372e777cde5bb351f21ec21d
+Author: Lv Yunlong 
+Date:   Mon Mar 29 05:36:48 2021 -0700
+
+    ethernet: myri10ge: Fix a use after free in myri10ge_sw_tso
+    
+    In myri10ge_sw_tso, the skb_list_walk_safe macro will set
+    (curr) = (segs) and (next) = (curr)->next. If status!=0 is true,
+    the memory pointed by curr and segs will be free by dev_kfree_skb_any(curr).
+    But later, the segs is used by segs = segs->next and causes a uaf.
+    
+    As (next) = (curr)->next, my patch replaces seg->next to next.
+    
+    Fixes: 536577f36ff7a ("net: myri10ge: use skb_list_walk_safe helper for gso segments")
+    Signed-off-by: Lv Yunlong 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+index 1634ca6d4a8f..c84c8bf2bc20 100644
+--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
++++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+@@ -2897,7 +2897,7 @@ static netdev_tx_t myri10ge_sw_tso(struct sk_buff *skb,
+ 			dev_kfree_skb_any(curr);
+ 			if (segs != NULL) {
+ 				curr = segs;
+-				segs = segs->next;
++				segs = next;
+ 				curr->next = NULL;
+ 				dev_kfree_skb_any(segs);
+ 			}

commit 1b479fb801602b22512f53c19b1f93a4fc5d5d9d
+Author: Lv Yunlong 
+Date:   Sun Mar 28 00:50:08 2021 -0700
+
+    drivers/net/wan/hdlc_fr: Fix a double free in pvc_xmit
+    
+    In pvc_xmit, if __skb_pad(skb, pad, false) failed, it will free
+    the skb in the first time and goto drop. But the same skb is freed
+    by kfree_skb(skb) in the second time in drop.
+    
+    Maintaining the original function unchanged, my patch adds a new
+    label out to avoid the double free if __skb_pad() failed.
+    
+    Fixes: f5083d0cee08a ("drivers/net/wan/hdlc_fr: Improvements to the code of pvc_xmit")
+    Signed-off-by: Lv Yunlong 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
+index 0720f5f92caa..4d9dc7d15908 100644
+--- a/drivers/net/wan/hdlc_fr.c
++++ b/drivers/net/wan/hdlc_fr.c
+@@ -415,7 +415,7 @@ static netdev_tx_t pvc_xmit(struct sk_buff *skb, struct net_device *dev)
+ 
+ 		if (pad > 0) { /* Pad the frame with zeros */
+ 			if (__skb_pad(skb, pad, false))
+-				goto drop;
++				goto out;
+ 			skb_put(skb, pad);
+ 		}
+ 	}
+@@ -448,8 +448,9 @@ static netdev_tx_t pvc_xmit(struct sk_buff *skb, struct net_device *dev)
+ 	return NETDEV_TX_OK;
+ 
+ drop:
+-	dev->stats.tx_dropped++;
+ 	kfree_skb(skb);
++out:
++	dev->stats.tx_dropped++;
+ 	return NETDEV_TX_OK;
+ }
+ 

commit adb76a520d068a54ee5ca82e756cf8e5a47363a4
+Author: Lv Yunlong 
+Date:   Mon Mar 22 09:13:25 2021 -0700
+
+    IB/isert: Fix a use after free in isert_connect_request
+    
+    The device is got by isert_device_get() with refcount is 1, and is
+    assigned to isert_conn by
+      isert_conn->device = device.
+    
+    When isert_create_qp() failed, device will be freed with
+    isert_device_put().
+    
+    Later, the device is used in isert_free_login_buf(isert_conn) by the
+    isert_conn->device->ib_device statement.
+    
+    Free the device in the correct order.
+    
+    Fixes: ae9ea9ed38c9 ("iser-target: Split some logic in isert_connect_request to routines")
+    Link: https://lore.kernel.org/r/20210322161325.7491-1-lyl2019@mail.ustc.edu.cn
+    Signed-off-by: Lv Yunlong 
+    Acked-by: Sagi Grimberg 
+    Reviewed-by: Leon Romanovsky 
+    Reviewed-by: Max Gurtovoy 
+    Signed-off-by: Jason Gunthorpe 
+
+diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
+index 7305ed8976c2..18266f07c58d 100644
+--- a/drivers/infiniband/ulp/isert/ib_isert.c
++++ b/drivers/infiniband/ulp/isert/ib_isert.c
+@@ -438,23 +438,23 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
+ 	isert_init_conn(isert_conn);
+ 	isert_conn->cm_id = cma_id;
+ 
+-	ret = isert_alloc_login_buf(isert_conn, cma_id->device);
+-	if (ret)
+-		goto out;
+-
+ 	device = isert_device_get(cma_id);
+ 	if (IS_ERR(device)) {
+ 		ret = PTR_ERR(device);
+-		goto out_rsp_dma_map;
++		goto out;
+ 	}
+ 	isert_conn->device = device;
+ 
++	ret = isert_alloc_login_buf(isert_conn, cma_id->device);
++	if (ret)
++		goto out_conn_dev;
++
+ 	isert_set_nego_params(isert_conn, &event->param.conn);
+ 
+ 	isert_conn->qp = isert_create_qp(isert_conn, cma_id);
+ 	if (IS_ERR(isert_conn->qp)) {
+ 		ret = PTR_ERR(isert_conn->qp);
+-		goto out_conn_dev;
++		goto out_rsp_dma_map;
+ 	}
+ 
+ 	ret = isert_login_post_recv(isert_conn);
+@@ -473,10 +473,10 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
+ 
+ out_destroy_qp:
+ 	isert_destroy_qp(isert_conn);
+-out_conn_dev:
+-	isert_device_put(device);
+ out_rsp_dma_map:
+ 	isert_free_login_buf(isert_conn);
++out_conn_dev:
++	isert_device_put(device);
+ out:
+ 	kfree(isert_conn);
+ 	rdma_reject(cma_id, NULL, 0, IB_CM_REJ_CONSUMER_DEFINED);

commit 52762efa2b256ed1c5274e5177cbd52ee11a2f6a
+Author: Lv Yunlong 
+Date:   Mon Mar 22 18:46:56 2021 -0700
+
+    gpu/xen: Fix a use after free in xen_drm_drv_init
+    
+    In function displback_changed, has the call chain
+    displback_connect(front_info)->xen_drm_drv_init(front_info).
+    We can see that drm_info is assigned to front_info->drm_info
+    and drm_info is freed in fail branch in xen_drm_drv_init().
+    
+    Later displback_disconnect(front_info) is called and it calls
+    xen_drm_drv_fini(front_info) cause a use after free by
+    drm_info = front_info->drm_info statement.
+    
+    My patch has done two things. First fixes the fail label which
+    drm_info = kzalloc() failed and still free the drm_info.
+    Second sets front_info->drm_info to NULL to avoid uaf.
+    
+    Signed-off-by: Lv Yunlong 
+    Reviewed-by: Oleksandr Andrushchenko 
+    Signed-off-by: Oleksandr Andrushchenko 
+    Link: https://patchwork.freedesktop.org/patch/msgid/20210323014656.10068-1-lyl2019@mail.ustc.edu.cn
+
+diff --git a/drivers/gpu/drm/xen/xen_drm_front.c b/drivers/gpu/drm/xen/xen_drm_front.c
+index 30d9adf31c84..9f14d99c763c 100644
+--- a/drivers/gpu/drm/xen/xen_drm_front.c
++++ b/drivers/gpu/drm/xen/xen_drm_front.c
+@@ -521,7 +521,7 @@ static int xen_drm_drv_init(struct xen_drm_front_info *front_info)
+ 	drm_dev = drm_dev_alloc(&xen_drm_driver, dev);
+ 	if (IS_ERR(drm_dev)) {
+ 		ret = PTR_ERR(drm_dev);
+-		goto fail;
++		goto fail_dev;
+ 	}
+ 
+ 	drm_info->drm_dev = drm_dev;
+@@ -551,8 +551,10 @@ static int xen_drm_drv_init(struct xen_drm_front_info *front_info)
+ 	drm_kms_helper_poll_fini(drm_dev);
+ 	drm_mode_config_cleanup(drm_dev);
+ 	drm_dev_put(drm_dev);
+-fail:
++fail_dev:
+ 	kfree(drm_info);
++	front_info->drm_info = NULL;
++fail:
+ 	return ret;
+ }
+ 

commit 37df9f3fedb6aeaff5564145e8162aab912c9284
+Author: Lv Yunlong 
+Date:   Wed Mar 24 03:37:24 2021 -0700
+
+    video: hyperv_fb: Fix a double free in hvfb_probe
+    
+    Function hvfb_probe() calls hvfb_getmem(), expecting upon return that
+    info->apertures is either NULL or points to memory that should be freed
+    by framebuffer_release().  But hvfb_getmem() is freeing the memory and
+    leaving the pointer non-NULL, resulting in a double free if an error
+    occurs or later if hvfb_remove() is called.
+    
+    Fix this by removing all kfree(info->apertures) calls in hvfb_getmem().
+    This will allow framebuffer_release() to free the memory, which follows
+    the pattern of other fbdev drivers.
+    
+    Fixes: 3a6fb6c4255c ("video: hyperv: hyperv_fb: Use physical memory for fb on HyperV Gen 1 VMs.")
+    Signed-off-by: Lv Yunlong 
+    Reviewed-by: Michael Kelley 
+    Link: https://lore.kernel.org/r/20210324103724.4189-1-lyl2019@mail.ustc.edu.cn
+    Signed-off-by: Wei Liu 
+
+diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c
+index c8b0ae676809..4dc9077dd2ac 100644
+--- a/drivers/video/fbdev/hyperv_fb.c
++++ b/drivers/video/fbdev/hyperv_fb.c
+@@ -1031,7 +1031,6 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info)
+ 			PCI_DEVICE_ID_HYPERV_VIDEO, NULL);
+ 		if (!pdev) {
+ 			pr_err("Unable to find PCI Hyper-V video\n");
+-			kfree(info->apertures);
+ 			return -ENODEV;
+ 		}
+ 
+@@ -1129,7 +1128,6 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info)
+ 	} else {
+ 		pci_dev_put(pdev);
+ 	}
+-	kfree(info->apertures);
+ 
+ 	return 0;
+ 
+@@ -1141,7 +1139,6 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info)
+ err1:
+ 	if (!gen2vm)
+ 		pci_dev_put(pdev);
+-	kfree(info->apertures);
+ 
+ 	return -ENOMEM;
+ }

commit 9ceee7d0841a8f7d7644021ba7d4cc1fbc7966e3
+Author: Lv Yunlong 
+Date:   Wed Mar 10 00:31:27 2021 -0800
+
+    firmware/efi: Fix a use after bug in efi_mem_reserve_persistent
+    
+    In the for loop in efi_mem_reserve_persistent(), prsv = rsv->next
+    use the unmapped rsv. Use the unmapped pages will cause segment
+    fault.
+    
+    Fixes: 18df7577adae6 ("efi/memreserve: deal with memreserve entries in unmapped memory")
+    Signed-off-by: Lv Yunlong 
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
+index df3f9bcab581..4b7ee3fa9224 100644
+--- a/drivers/firmware/efi/efi.c
++++ b/drivers/firmware/efi/efi.c
+@@ -927,7 +927,7 @@ int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
+ 	}
+ 
+ 	/* first try to find a slot in an existing linked list entry */
+-	for (prsv = efi_memreserve_root->next; prsv; prsv = rsv->next) {
++	for (prsv = efi_memreserve_root->next; prsv; ) {
+ 		rsv = memremap(prsv, sizeof(*rsv), MEMREMAP_WB);
+ 		index = atomic_fetch_add_unless(&rsv->count, 1, rsv->size);
+ 		if (index < rsv->size) {
+@@ -937,6 +937,7 @@ int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
+ 			memunmap(rsv);
+ 			return efi_mem_reserve_iomem(addr, size);
+ 		}
++		prsv = rsv->next;
+ 		memunmap(rsv);
+ 	}
+ 

commit c8c165dea4c8f5ad67b1240861e4f6c5395fa4ac
+Author: Lv Yunlong 
+Date:   Wed Mar 10 22:46:36 2021 -0800
+
+    scsi: st: Fix a use after free in st_open()
+    
+    In st_open(), if STp->in_use is true, STp will be freed by
+    scsi_tape_put(). However, STp is still used by DEBC_printk() after. It is
+    better to DEBC_printk() before scsi_tape_put().
+    
+    Link: https://lore.kernel.org/r/20210311064636.10522-1-lyl2019@mail.ustc.edu.cn
+    Acked-by: Kai Mäkisara 
+    Signed-off-by: Lv Yunlong 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
+index 841ad2fc369a..9ca536aae784 100644
+--- a/drivers/scsi/st.c
++++ b/drivers/scsi/st.c
+@@ -1269,8 +1269,8 @@ static int st_open(struct inode *inode, struct file *filp)
+ 	spin_lock(&st_use_lock);
+ 	if (STp->in_use) {
+ 		spin_unlock(&st_use_lock);
+-		scsi_tape_put(STp);
+ 		DEBC_printk(STp, "Device already in use.\n");
++		scsi_tape_put(STp);
+ 		return (-EBUSY);
+ 	}
+ 

commit 2bb817712e2f77486d6ee17e7efaf91997a685f8
+Author: Lv Yunlong 
+Date:   Wed Mar 10 22:30:05 2021 -0800
+
+    scsi: myrs: Fix a double free in myrs_cleanup()
+    
+    In myrs_cleanup(), cs->mmio_base will be freed twice by iounmap().
+    
+    Link: https://lore.kernel.org/r/20210311063005.9963-1-lyl2019@mail.ustc.edu.cn
+    Fixes: 77266186397c ("scsi: myrs: Add Mylex RAID controller (SCSI interface)")
+    Reviewed-by: Hannes Reinecke 
+    Signed-off-by: Lv Yunlong 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/scsi/myrs.c b/drivers/scsi/myrs.c
+index 4adf9ded296a..329fd025c718 100644
+--- a/drivers/scsi/myrs.c
++++ b/drivers/scsi/myrs.c
+@@ -2273,12 +2273,12 @@ static void myrs_cleanup(struct myrs_hba *cs)
+ 	if (cs->mmio_base) {
+ 		cs->disable_intr(cs);
+ 		iounmap(cs->mmio_base);
++		cs->mmio_base = NULL;
+ 	}
+ 	if (cs->irq)
+ 		free_irq(cs->irq, cs);
+ 	if (cs->io_addr)
+ 		release_region(cs->io_addr, 0x80);
+-	iounmap(cs->mmio_base);
+ 	pci_set_drvdata(pdev, NULL);
+ 	pci_disable_device(pdev);
+ 	scsi_host_put(cs->host);

commit db74623a3850db99cb9692fda9e836a56b74198d
+Author: Lv Yunlong 
+Date:   Wed Mar 10 20:01:40 2021 -0800
+
+    net/qlcnic: Fix a use after free in qlcnic_83xx_get_minidump_template
+    
+    In qlcnic_83xx_get_minidump_template, fw_dump->tmpl_hdr was freed by
+    vfree(). But unfortunately, it is used when extended is true.
+    
+    Fixes: 7061b2bdd620e ("qlogic: Deletion of unnecessary checks before two function calls")
+    Signed-off-by: Lv Yunlong 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
+index 7760a3394e93..7ecb3dfe30bd 100644
+--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
+@@ -1425,6 +1425,7 @@ void qlcnic_83xx_get_minidump_template(struct qlcnic_adapter *adapter)
+ 
+ 	if (fw_dump->tmpl_hdr == NULL || current_version > prev_version) {
+ 		vfree(fw_dump->tmpl_hdr);
++		fw_dump->tmpl_hdr = NULL;
+ 
+ 		if (qlcnic_83xx_md_check_extended_dump_capability(adapter))
+ 			extended = !qlcnic_83xx_extend_md_capab(adapter);
+@@ -1443,6 +1444,8 @@ void qlcnic_83xx_get_minidump_template(struct qlcnic_adapter *adapter)
+ 			struct qlcnic_83xx_dump_template_hdr *hdr;
+ 
+ 			hdr = fw_dump->tmpl_hdr;
++			if (!hdr)
++				return;
+ 			hdr->drv_cap_mask = 0x1f;
+ 			fw_dump->cap_mask = 0x1f;
+ 			dev_info(&pdev->dev,

commit abec6561fc4e0fbb19591a0b35676d8c783b5493
+Author: Lv Yunlong 
+Date:   Wed Mar 10 21:44:13 2021 -0800
+
+    nvme-rdma: Fix a use after free in nvmet_rdma_write_data_done
+    
+    In nvmet_rdma_write_data_done, rsp is recoverd by wc->wr_cqe and freed by
+    nvmet_rdma_release_rsp(). But after that, pr_info() used the freed
+    chunk's member object and could leak the freed chunk address with
+    wc->wr_cqe by computing the offset.
+    
+    Signed-off-by: Lv Yunlong 
+    Signed-off-by: Christoph Hellwig 
+
+diff --git a/drivers/nvme/target/rdma.c b/drivers/nvme/target/rdma.c
+index 06b6b742bb21..6c1f3ab7649c 100644
+--- a/drivers/nvme/target/rdma.c
++++ b/drivers/nvme/target/rdma.c
+@@ -802,9 +802,8 @@ static void nvmet_rdma_write_data_done(struct ib_cq *cq, struct ib_wc *wc)
+ 		nvmet_req_uninit(&rsp->req);
+ 		nvmet_rdma_release_rsp(rsp);
+ 		if (wc->status != IB_WC_WR_FLUSH_ERR) {
+-			pr_info("RDMA WRITE for CQE 0x%p failed with status %s (%d).\n",
+-				wc->wr_cqe, ib_wc_status_msg(wc->status),
+-				wc->status);
++			pr_info("RDMA WRITE for CQE failed with status %s (%d).\n",
++				ib_wc_status_msg(wc->status), wc->status);
+ 			nvmet_rdma_error_comp(queue);
+ 		}
+ 		return;

commit d1c2b5010d07e967d7cbcc232a86b2308d824ca3
+Author: He Chunhui 
+Date:   Tue Jul 26 06:16:52 2016 +0000
+
+    net: neigh: disallow transition to NUD_STALE if lladdr is unchanged in neigh_update()
+    
+    NUD_STALE is used when the caller(e.g. arp_process()) can't guarantee
+    neighbour reachability. If the entry was NUD_VALID and lladdr is unchanged,
+    the entry state should not be changed.
+    
+    Currently the code puts an extra "NUD_CONNECTED" condition. So if old state
+    was NUD_DELAY or NUD_PROBE (they are NUD_VALID but not NUD_CONNECTED), the
+    state can be changed to NUD_STALE.
+    
+    This may cause problem. Because NUD_STALE lladdr doesn't guarantee
+    reachability, when we send traffic, the state will be changed to
+    NUD_DELAY. In normal case, if we get no confirmation (by dst_confirm()),
+    we will change the state to NUD_PROBE and send probe traffic. But now the
+    state may be reset to NUD_STALE again(e.g. by broadcast ARP packets),
+    so the probe traffic will not be sent. This situation may happen again and
+    again, and packets will be sent to an non-reachable lladdr forever.
+    
+    The fix is to remove the "NUD_CONNECTED" condition. After that the
+    "NEIGH_UPDATE_F_WEAK_OVERRIDE" condition (used by IPv6) in that branch will
+    be redundant, so remove it.
+    
+    This change may increase probe traffic, but it's essential since NUD_STALE
+    lladdr is unreliable. To ensure correctness, we prefer to resolve lladdr,
+    when we can't get confirmation, even while remote packets try to set
+    NUD_STALE state.
+    
+    Signed-off-by: Chunhui He 
+    Signed-off-by: Julian Anastasov 
+    Reviewed-by: Hannes Frederic Sowa 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/core/neighbour.c b/net/core/neighbour.c
+index 5cdc62a8eb84..cf26e04c4046 100644
+--- a/net/core/neighbour.c
++++ b/net/core/neighbour.c
+@@ -1060,8 +1060,6 @@ static void neigh_update_hhs(struct neighbour *neigh)
+ 	NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
+ 				lladdr instead of overriding it
+ 				if it is different.
+-				It also allows to retain current state
+-				if lladdr is unchanged.
+ 	NEIGH_UPDATE_F_ADMIN	means that the change is administrative.
+ 
+ 	NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing
+@@ -1150,10 +1148,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
+ 			} else
+ 				goto out;
+ 		} else {
+-			if (lladdr == neigh->ha && new == NUD_STALE &&
+-			    ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) ||
+-			     (old & NUD_CONNECTED))
+-			    )
++			if (lladdr == neigh->ha && new == NUD_STALE)
+ 				new = old;
+ 		}
+ 	}

commit 35f1790e6c6a7e4cae57b616cf36444d27fa6b28
+Author: He Chunhui 
+Date:   Wed Feb 1 00:48:28 2012 +0800
+
+    x86, boot: Fix port argument to inl() function
+    
+    "u32 port" in inl() should be "u16 port".
+    
+    [ hpa: it's a bug, but it doesn't produce incorrect code, so no need
+      to put this into urgent or stable. ]
+    
+    Signed-off-by: He Chunhui 
+    Link: http://lkml.kernel.org/r/32892299.2931391328028508117.JavaMail.coremail@mailweb
+    Signed-off-by: H. Peter Anvin 
+
+diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
+index c7093bd9f2d3..18997e5a1053 100644
+--- a/arch/x86/boot/boot.h
++++ b/arch/x86/boot/boot.h
+@@ -67,7 +67,7 @@ static inline void outl(u32 v, u16 port)
+ {
+ 	asm volatile("outl %0,%1" : : "a" (v), "dN" (port));
+ }
+-static inline u32 inl(u32 port)
++static inline u32 inl(u16 port)
+ {
+ 	u32 v;
+ 	asm volatile("inl %1,%0" : "=a" (v) : "dN" (port));

commit f9543d0ab6392a9a5bff0034622688dc10d9d225
+Author: JiSheng Zhang 
+Date:   Sat Jul 19 15:35:41 2008 +0800
+
+    firewire: queue the right number of data
+    
+    There will be 4 padding bytes in struct fw_cdev_event_response on some platforms
+    The member:__u32 data will point to these padding bytes. While queue the
+    response and data in complete_transaction in fw-cdev.c, it will queue like this:
+    |response(excluding padding bytes)|4 padding bytes|4 padding bytes|data.
+    It queue 4 extra bytes. That is to say it use "&response + sizeof(response)"
+    while other place of kernel and userspace library use "&response + offsetof
+    (typeof(response), data)". So it will lost the last 4 bytes of data. This patch
+    can fix it while not changing the struct definition.
+    
+    Signed-off-by: JiSheng Zhang 
+    
+    This fixes responses to outbound block read requests on 64bit architectures.
+    Tested on i686, x86-64, and x86-64 with i686 userland, using firecontrol and
+    gscanbus.
+    
+    Signed-off-by: Stefan Richter 
+
+diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c
+index c639915fc3cb..bc81d6fcd2fd 100644
+--- a/drivers/firewire/fw-cdev.c
++++ b/drivers/firewire/fw-cdev.c
+@@ -382,9 +382,9 @@ complete_transaction(struct fw_card *card, int rcode,
+ 
+ 	response->response.type   = FW_CDEV_EVENT_RESPONSE;
+ 	response->response.rcode  = rcode;
+-	queue_event(client, &response->event,
+-		    &response->response, sizeof(response->response),
+-		    response->response.data, response->response.length);
++	queue_event(client, &response->event, &response->response,
++		    sizeof(response->response) + response->response.length,
++		    NULL, 0);
+ }
+ 
+ static int ioctl_send_request(struct client *client, void *buffer)

commit 8bc3be2751b4f74ab90a446da1912fd8204d53f7
+Author: Fengguang Wu 
+Date:   Mon Feb 4 22:29:36 2008 -0800
+
+    writeback: speed up writeback of big dirty files
+    
+    After making dirty a 100M file, the normal behavior is to start the
+    writeback for all data after 30s delays.  But sometimes the following
+    happens instead:
+    
+            - after 30s:    ~4M
+            - after 5s:     ~4M
+            - after 5s:     all remaining 92M
+    
+    Some analyze shows that the internal io dispatch queues goes like this:
+    
+                    s_io            s_more_io
+                    -------------------------
+            1)      100M,1K         0
+            2)      1K              96M
+            3)      0               96M
+    1) initial state with a 100M file and a 1K file
+    
+    2) 4M written, nr_to_write <= 0, so write more
+    
+    3) 1K written, nr_to_write > 0, no more writes(BUG)
+    
+    nr_to_write > 0 in (3) fools the upper layer to think that data have all
+    been written out.  The big dirty file is actually still sitting in
+    s_more_io.  We cannot simply splice s_more_io back to s_io as soon as s_io
+    becomes empty, and let the loop in generic_sync_sb_inodes() continue: this
+    may starve newly expired inodes in s_dirty.  It is also not an option to
+    draw inodes from both s_more_io and s_dirty, an let the loop go on: this
+    might lead to live locks, and might also starve other superblocks in sync
+    time(well kupdate may still starve some superblocks, that's another bug).
+    
+    We have to return when a full scan of s_io completes.  So nr_to_write > 0
+    does not necessarily mean that "all data are written".  This patch
+    introduces a flag writeback_control.more_io to indicate that more io should
+    be done.  With it the big dirty file no longer has to wait for the next
+    kupdate invokation 5s later.
+    
+    In sync_sb_inodes() we only set more_io on super_blocks we actually
+    visited.  This avoids the interaction between two pdflush deamons.
+    
+    Also in __sync_single_inode() we don't blindly keep requeuing the io if the
+    filesystem cannot progress.  Failing to do so may lead to 100% iowait.
+    
+    Tested-by: Mike Snitzer 
+    Signed-off-by: Fengguang Wu 
+    Cc: Michael Rubin 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
+index 3fe782d70a71..0b3064079fa5 100644
+--- a/fs/fs-writeback.c
++++ b/fs/fs-writeback.c
+@@ -284,7 +284,17 @@ __sync_single_inode(struct inode *inode, struct writeback_control *wbc)
+ 				 * soon as the queue becomes uncongested.
+ 				 */
+ 				inode->i_state |= I_DIRTY_PAGES;
+-				requeue_io(inode);
++				if (wbc->nr_to_write <= 0) {
++					/*
++					 * slice used up: queue for next turn
++					 */
++					requeue_io(inode);
++				} else {
++					/*
++					 * somehow blocked: retry later
++					 */
++					redirty_tail(inode);
++				}
+ 			} else {
+ 				/*
+ 				 * Otherwise fully redirty the inode so that
+@@ -468,8 +478,12 @@ sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
+ 		iput(inode);
+ 		cond_resched();
+ 		spin_lock(&inode_lock);
+-		if (wbc->nr_to_write <= 0)
++		if (wbc->nr_to_write <= 0) {
++			wbc->more_io = 1;
+ 			break;
++		}
++		if (!list_empty(&sb->s_more_io))
++			wbc->more_io = 1;
+ 	}
+ 	return;		/* Leave any unwritten inodes on s_io */
+ }
+diff --git a/include/linux/writeback.h b/include/linux/writeback.h
+index b2cd826a8c90..b7b3362f7717 100644
+--- a/include/linux/writeback.h
++++ b/include/linux/writeback.h
+@@ -62,6 +62,7 @@ struct writeback_control {
+ 	unsigned for_reclaim:1;		/* Invoked from the page allocator */
+ 	unsigned for_writepages:1;	/* This is a writepages() call */
+ 	unsigned range_cyclic:1;	/* range_start is cyclic */
++	unsigned more_io:1;		/* more io to be dispatched */
+ };
+ 
+ /*
+diff --git a/mm/page-writeback.c b/mm/page-writeback.c
+index a4ca162666c5..5e00f1772c20 100644
+--- a/mm/page-writeback.c
++++ b/mm/page-writeback.c
+@@ -567,6 +567,7 @@ static void background_writeout(unsigned long _min_pages)
+ 			global_page_state(NR_UNSTABLE_NFS) < background_thresh
+ 				&& min_pages <= 0)
+ 			break;
++		wbc.more_io = 0;
+ 		wbc.encountered_congestion = 0;
+ 		wbc.nr_to_write = MAX_WRITEBACK_PAGES;
+ 		wbc.pages_skipped = 0;
+@@ -574,8 +575,9 @@ static void background_writeout(unsigned long _min_pages)
+ 		min_pages -= MAX_WRITEBACK_PAGES - wbc.nr_to_write;
+ 		if (wbc.nr_to_write > 0 || wbc.pages_skipped > 0) {
+ 			/* Wrote less than expected */
+-			congestion_wait(WRITE, HZ/10);
+-			if (!wbc.encountered_congestion)
++			if (wbc.encountered_congestion || wbc.more_io)
++				congestion_wait(WRITE, HZ/10);
++			else
+ 				break;
+ 		}
+ 	}
+@@ -640,11 +642,12 @@ static void wb_kupdate(unsigned long arg)
+ 			global_page_state(NR_UNSTABLE_NFS) +
+ 			(inodes_stat.nr_inodes - inodes_stat.nr_unused);
+ 	while (nr_to_write > 0) {
++		wbc.more_io = 0;
+ 		wbc.encountered_congestion = 0;
+ 		wbc.nr_to_write = MAX_WRITEBACK_PAGES;
+ 		writeback_inodes(&wbc);
+ 		if (wbc.nr_to_write > 0) {
+-			if (wbc.encountered_congestion)
++			if (wbc.encountered_congestion || wbc.more_io)
+ 				congestion_wait(WRITE, HZ/10);
+ 			else
+ 				break;	/* All the old data is written */

commit ec4dd3eb35759f9fbeb5c1abb01403b2fde64cc9
+Author: Fengguang Wu 
+Date:   Mon Feb 4 22:28:56 2008 -0800
+
+    maps4: add proportional set size accounting in smaps
+    
+    The "proportional set size" (PSS) of a process is the count of pages it has
+    in memory, where each page is divided by the number of processes sharing
+    it.  So if a process has 1000 pages all to itself, and 1000 shared with one
+    other process, its PSS will be 1500.
+    
+                   - lwn.net: "ELC: How much memory are applications really using?"
+    
+    The PSS proposed by Matt Mackall is a very nice metic for measuring an
+    process's memory footprint.  So collect and export it via
+    /proc//smaps.
+    
+    Matt Mackall's pagemap/kpagemap and John Berthels's exmap can also do the
+    job.  They are comprehensive tools.  But for PSS, let's do it in the simple
+    way.
+    
+    Cc: John Berthels 
+    Cc: Bernardo Innocenti 
+    Cc: Padraig Brady 
+    Cc: Denys Vlasenko 
+    Cc: Balbir Singh 
+    Signed-off-by: Matt Mackall 
+    Signed-off-by: Fengguang Wu 
+    Cc: Hugh Dickins 
+    Cc: Dave Hansen 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
+index 8043a3eab52c..8952ce70315e 100644
+--- a/fs/proc/task_mmu.c
++++ b/fs/proc/task_mmu.c
+@@ -114,6 +114,25 @@ static void pad_len_spaces(struct seq_file *m, int len)
+ 	seq_printf(m, "%*c", len, ' ');
+ }
+ 
++/*
++ * Proportional Set Size(PSS): my share of RSS.
++ *
++ * PSS of a process is the count of pages it has in memory, where each
++ * page is divided by the number of processes sharing it.  So if a
++ * process has 1000 pages all to itself, and 1000 shared with one other
++ * process, its PSS will be 1500.
++ *
++ * To keep (accumulated) division errors low, we adopt a 64bit
++ * fixed-point pss counter to minimize division errors. So (pss >>
++ * PSS_SHIFT) would be the real byte count.
++ *
++ * A shift of 12 before division means (assuming 4K page size):
++ * 	- 1M 3-user-pages add up to 8KB errors;
++ * 	- supports mapcount up to 2^24, or 16M;
++ * 	- supports PSS up to 2^52 bytes, or 4PB.
++ */
++#define PSS_SHIFT 12
++
+ struct mem_size_stats
+ {
+ 	unsigned long resident;
+@@ -122,6 +141,7 @@ struct mem_size_stats
+ 	unsigned long private_clean;
+ 	unsigned long private_dirty;
+ 	unsigned long referenced;
++	u64 pss;
+ };
+ 
+ struct pmd_walker {
+@@ -195,6 +215,7 @@ static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats
+ 		seq_printf(m,
+ 			   "Size:           %8lu kB\n"
+ 			   "Rss:            %8lu kB\n"
++			   "Pss:            %8lu kB\n"
+ 			   "Shared_Clean:   %8lu kB\n"
+ 			   "Shared_Dirty:   %8lu kB\n"
+ 			   "Private_Clean:  %8lu kB\n"
+@@ -202,6 +223,7 @@ static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats
+ 			   "Referenced:     %8lu kB\n",
+ 			   (vma->vm_end - vma->vm_start) >> 10,
+ 			   mss->resident >> 10,
++			   (unsigned long)(mss->pss >> (10 + PSS_SHIFT)),
+ 			   mss->shared_clean  >> 10,
+ 			   mss->shared_dirty  >> 10,
+ 			   mss->private_clean >> 10,
+@@ -226,6 +248,7 @@ static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
+ 	pte_t *pte, ptent;
+ 	spinlock_t *ptl;
+ 	struct page *page;
++	int mapcount;
+ 
+ 	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
+ 	for (; addr != end; pte++, addr += PAGE_SIZE) {
+@@ -242,16 +265,19 @@ static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
+ 		/* Accumulate the size in pages that have been accessed. */
+ 		if (pte_young(ptent) || PageReferenced(page))
+ 			mss->referenced += PAGE_SIZE;
+-		if (page_mapcount(page) >= 2) {
++		mapcount = page_mapcount(page);
++		if (mapcount >= 2) {
+ 			if (pte_dirty(ptent))
+ 				mss->shared_dirty += PAGE_SIZE;
+ 			else
+ 				mss->shared_clean += PAGE_SIZE;
++			mss->pss += (PAGE_SIZE << PSS_SHIFT) / mapcount;
+ 		} else {
+ 			if (pte_dirty(ptent))
+ 				mss->private_dirty += PAGE_SIZE;
+ 			else
+ 				mss->private_clean += PAGE_SIZE;
++			mss->pss += (PAGE_SIZE << PSS_SHIFT);
+ 		}
+ 	}
+ 	pte_unmap_unlock(pte - 1, ptl);

commit 28bc44d7d1d967b8251214dd7a130d523b5ba5ee
+Author: Fengguang Wu 
+Date:   Sun Feb 3 18:04:10 2008 +0200
+
+    do_invalidatepage() comment typo fix
+    
+    Fix a typo in the comment for do_invalidatepage().
+    
+    Signed-off-by: Fengguang Wu 
+    Signed-off-by: Adrian Bunk 
+
+diff --git a/mm/truncate.c b/mm/truncate.c
+index cadc15653dde..c3123b08ff6d 100644
+--- a/mm/truncate.c
++++ b/mm/truncate.c
+@@ -21,7 +21,7 @@
+ 
+ 
+ /**
+- * do_invalidatepage - invalidate part of all of a page
++ * do_invalidatepage - invalidate part or all of a page
+  * @page: the page which is affected
+  * @offset: the index of the truncation point
+  *

commit 70d215c4a7dfbddc138a2dd726d8f80f3e6d2622
+Author: Fengguang Wu 
+Date:   Fri Dec 7 16:35:14 2007 +0800
+
+    HID: the `bit' in hidinput_mapping_quirks() is an out parameter
+    
+    Fix a panic, by changing
+            hidinput_mapping_quirks(,, unsigned long *bit,)
+    to
+            hidinput_mapping_quirks(,, unsigned long **bit,)
+    
+    The `bit' in this function is an out parameter.
+    
+    Signed-off-by: Fengguang Wu 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/hid-input-quirks.c b/drivers/hid/hid-input-quirks.c
+index fbe8b6de1a63..4bcdc9bb658e 100644
+--- a/drivers/hid/hid-input-quirks.c
++++ b/drivers/hid/hid-input-quirks.c
+@@ -16,16 +16,16 @@
+ #include 
+ #include 
+ 
+-#define map_abs(c)      do { usage->code = c; usage->type = EV_ABS; bit = input->absbit; *max = ABS_MAX; } while (0)
+-#define map_rel(c)      do { usage->code = c; usage->type = EV_REL; bit = input->relbit; *max = REL_MAX; } while (0)
+-#define map_key(c)      do { usage->code = c; usage->type = EV_KEY; bit = input->keybit; *max = KEY_MAX; } while (0)
+-#define map_led(c)      do { usage->code = c; usage->type = EV_LED; bit = input->ledbit; *max = LED_MAX; } while (0)
++#define map_abs(c)      do { usage->code = c; usage->type = EV_ABS; *bit = input->absbit; *max = ABS_MAX; } while (0)
++#define map_rel(c)      do { usage->code = c; usage->type = EV_REL; *bit = input->relbit; *max = REL_MAX; } while (0)
++#define map_key(c)      do { usage->code = c; usage->type = EV_KEY; *bit = input->keybit; *max = KEY_MAX; } while (0)
++#define map_led(c)      do { usage->code = c; usage->type = EV_LED; *bit = input->ledbit; *max = LED_MAX; } while (0)
+ 
+-#define map_abs_clear(c)        do { map_abs(c); clear_bit(c, bit); } while (0)
+-#define map_key_clear(c)        do { map_key(c); clear_bit(c, bit); } while (0)
++#define map_abs_clear(c)        do { map_abs(c); clear_bit(c, *bit); } while (0)
++#define map_key_clear(c)        do { map_key(c); clear_bit(c, *bit); } while (0)
+ 
+ static int quirk_belkin_wkbd(struct hid_usage *usage, struct input_dev *input,
+-			      unsigned long *bit, int *max)
++			      unsigned long **bit, int *max)
+ {
+ 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
+ 		return 0;
+@@ -41,7 +41,7 @@ static int quirk_belkin_wkbd(struct hid_usage *usage, struct input_dev *input,
+ }
+ 
+ static int quirk_cherry_cymotion(struct hid_usage *usage, struct input_dev *input,
+-			      unsigned long *bit, int *max)
++			      unsigned long **bit, int *max)
+ {
+ 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
+ 		return 0;
+@@ -57,7 +57,7 @@ static int quirk_cherry_cymotion(struct hid_usage *usage, struct input_dev *inpu
+ }
+ 
+ static int quirk_logitech_ultrax_remote(struct hid_usage *usage, struct input_dev *input,
+-			      unsigned long *bit, int *max)
++			      unsigned long **bit, int *max)
+ {
+ 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
+ 		return 0;
+@@ -90,7 +90,7 @@ static int quirk_logitech_ultrax_remote(struct hid_usage *usage, struct input_de
+ }
+ 
+ static int quirk_chicony_tactical_pad(struct hid_usage *usage, struct input_dev *input,
+-			      unsigned long *bit, int *max)
++			      unsigned long **bit, int *max)
+ {
+ 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
+ 		return 0;
+@@ -115,7 +115,7 @@ static int quirk_chicony_tactical_pad(struct hid_usage *usage, struct input_dev
+ }
+ 
+ static int quirk_microsoft_ergonomy_kb(struct hid_usage *usage, struct input_dev *input,
+-			      unsigned long *bit, int *max)
++			      unsigned long **bit, int *max)
+ {
+ 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
+ 		return 0;
+@@ -138,7 +138,7 @@ static int quirk_microsoft_ergonomy_kb(struct hid_usage *usage, struct input_dev
+ }
+ 
+ static int quirk_microsoft_presenter_8k(struct hid_usage *usage, struct input_dev *input,
+-			      unsigned long *bit, int *max)
++			      unsigned long **bit, int *max)
+ {
+ 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
+ 		return 0;
+@@ -156,7 +156,7 @@ static int quirk_microsoft_presenter_8k(struct hid_usage *usage, struct input_de
+ }
+ 
+ static int quirk_petalynx_remote(struct hid_usage *usage, struct input_dev *input,
+-			      unsigned long *bit, int *max)
++			      unsigned long **bit, int *max)
+ {
+ 	if (((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) &&
+ 			((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER))
+@@ -184,7 +184,7 @@ static int quirk_petalynx_remote(struct hid_usage *usage, struct input_dev *inpu
+ }
+ 
+ static int quirk_logitech_wireless(struct hid_usage *usage, struct input_dev *input,
+-			      unsigned long *bit, int *max)
++			      unsigned long **bit, int *max)
+ {
+ 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
+ 		return 0;
+@@ -236,7 +236,7 @@ static int quirk_logitech_wireless(struct hid_usage *usage, struct input_dev *in
+ }
+ 
+ static int quirk_cherry_genius_29e(struct hid_usage *usage, struct input_dev *input,
+-			      unsigned long *bit, int *max)
++			      unsigned long **bit, int *max)
+ {
+ 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
+ 		return 0;
+@@ -254,7 +254,7 @@ static int quirk_cherry_genius_29e(struct hid_usage *usage, struct input_dev *in
+ }
+ 
+ static int quirk_btc_8193(struct hid_usage *usage, struct input_dev *input,
+-			      unsigned long *bit, int *max)
++			      unsigned long **bit, int *max)
+ {
+ 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
+ 		return 0;
+@@ -307,7 +307,7 @@ static int quirk_btc_8193(struct hid_usage *usage, struct input_dev *input,
+ static const struct hid_input_blacklist {
+ 	__u16 idVendor;
+ 	__u16 idProduct;
+-	int (*quirk)(struct hid_usage *, struct input_dev *, unsigned long *, int *);
++	int (*quirk)(struct hid_usage *, struct input_dev *, unsigned long **, int *);
+ } hid_input_blacklist[] = {
+ 	{ VENDOR_ID_BELKIN, DEVICE_ID_BELKIN_WIRELESS_KEYBOARD, quirk_belkin_wkbd },
+ 
+@@ -335,7 +335,7 @@ static const struct hid_input_blacklist {
+ 
+ int hidinput_mapping_quirks(struct hid_usage *usage, 
+ 				   struct input_dev *input, 
+-				   unsigned long *bit, int *max)
++				   unsigned long **bit, int *max)
+ {
+ 	struct hid_device *device = input_get_drvdata(input);
+ 	int i = 0;
+diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
+index aeb018e31bfc..5325d98b4328 100644
+--- a/drivers/hid/hid-input.c
++++ b/drivers/hid/hid-input.c
+@@ -382,7 +382,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
+ 	}
+ 
+ 	/* handle input mappings for quirky devices */
+-	ret = hidinput_mapping_quirks(usage, input, bit, &max);
++	ret = hidinput_mapping_quirks(usage, input, &bit, &max);
+ 	if (ret)
+ 		goto mapped;
+ 
+diff --git a/include/linux/hid.h b/include/linux/hid.h
+index 24f04cd742de..6a70b788ee9c 100644
+--- a/include/linux/hid.h
++++ b/include/linux/hid.h
+@@ -526,7 +526,7 @@ extern void hidinput_disconnect(struct hid_device *);
+ int hid_set_field(struct hid_field *, unsigned, __s32);
+ int hid_input_report(struct hid_device *, int type, u8 *, int, int);
+ int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field);
+-int hidinput_mapping_quirks(struct hid_usage *, struct input_dev *, unsigned long *, int *);
++int hidinput_mapping_quirks(struct hid_usage *, struct input_dev *, unsigned long **, int *);
+ void hidinput_event_quirks(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
+ int hidinput_apple_event(struct hid_device *, struct input_dev *, struct hid_usage *, __s32);
+ void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt);

commit c06a018fa5362fa9ed0768bd747c0fab26bc8849
+Author: Fengguang Wu 
+Date:   Wed Nov 14 16:59:54 2007 -0800
+
+    reiserfs: don't drop PG_dirty when releasing sub-page-sized dirty file
+    
+    This is not a new problem in 2.6.23-git17.  2.6.22/2.6.23 is buggy in the
+    same way.
+    
+    Reiserfs could accumulate dirty sub-page-size files until umount time.
+    They cannot be synced to disk by pdflush routines or explicit `sync'
+    commands.  Only `umount' can do the trick.
+    
+    The direct cause is: the dirty page's PG_dirty is wrongly _cleared_.
+    Call trace:
+             [] cancel_dirty_page+0xd0/0xf0
+             [] :reiserfs:reiserfs_cut_from_item+0x660/0x710
+             [] :reiserfs:reiserfs_do_truncate+0x271/0x530
+             [] :reiserfs:reiserfs_truncate_file+0xfd/0x3b0
+             [] :reiserfs:reiserfs_file_release+0x1e0/0x340
+             [] __fput+0xcc/0x1b0
+             [] fput+0x16/0x20
+             [] filp_close+0x56/0x90
+             [] sys_close+0xad/0x110
+             [] system_call+0x7e/0x83
+    
+    Fix the bug by removing the cancel_dirty_page() call. Tests show that
+    it causes no bad behaviors on various write sizes.
+    
+    === for the patient ===
+    Here are more detailed demonstrations of the problem.
+    
+    1) the page has both PG_dirty(D)/PAGECACHE_TAG_DIRTY(d) after being written to;
+       and then only PAGECACHE_TAG_DIRTY(d) remains after the file is closed.
+    
+    ------------------------------ screen 0 ------------------------------
+    [T0] root /home/wfg# cat > /test/tiny
+    [T1] hi
+    [T2] root /home/wfg#
+    
+    ------------------------------ screen 1 ------------------------------
+    [T1] root /home/wfg# echo /test/tiny > /proc/filecache
+    [T1] root /home/wfg# cat /proc/filecache
+         # file /test/tiny
+         # flags R:referenced A:active M:mmap U:uptodate D:dirty W:writeback O:owner B:buffer d:dirty w:writeback
+         # idx   len     state   refcnt
+         0       1       ___UD__Bd_      2
+    [T2] root /home/wfg# cat /proc/filecache
+         # file /test/tiny
+         # flags R:referenced A:active M:mmap U:uptodate D:dirty W:writeback O:owner B:buffer d:dirty w:writeback
+         # idx   len     state   refcnt
+         0       1       ___U___Bd_      2
+    
+    2) note the non-zero 'cancelled_write_bytes' after /tmp/hi is copied.
+    
+    ------------------------------ screen 0 ------------------------------
+    [T0] root /home/wfg# echo hi > /tmp/hi
+    [T1] root /home/wfg# cp /tmp/hi /dev/stdin /test
+    [T2] hi
+    [T3] root /home/wfg#
+    
+    ------------------------------ screen 1 ------------------------------
+    [T1] root /proc/4397# cd /proc/`pidof cp`
+    [T1] root /proc/4713# cat io
+         rchar: 8396
+         wchar: 3
+         syscr: 20
+         syscw: 1
+         read_bytes: 0
+         write_bytes: 20480
+         cancelled_write_bytes: 4096
+    [T2] root /proc/4713# cat io
+         rchar: 8399
+         wchar: 6
+         syscr: 21
+         syscw: 2
+         read_bytes: 0
+         write_bytes: 24576
+         cancelled_write_bytes: 4096
+    
+    //Question: the 'write_bytes' is a bit more than expected ;-)
+    
+    Tested-by: Maxim Levitsky 
+    Cc: Peter Zijlstra 
+    Cc: Jeff Mahoney 
+    Signed-off-by: Fengguang Wu 
+    Reviewed-by: Chris Mason 
+    Cc: 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
+index ca41567d7890..d2db2417b2bd 100644
+--- a/fs/reiserfs/stree.c
++++ b/fs/reiserfs/stree.c
+@@ -1458,9 +1458,6 @@ static void unmap_buffers(struct page *page, loff_t pos)
+ 				}
+ 				bh = next;
+ 			} while (bh != head);
+-			if (PAGE_SIZE == bh->b_size) {
+-				cancel_dirty_page(page, PAGE_CACHE_SIZE);
+-			}
+ 		}
+ 	}
+ }

commit df7c487250b17aa0caeee7d85f120330f1d31355
+Author: Fengguang Wu 
+Date:   Sat Oct 20 02:26:04 2007 +0200
+
+    trivial copy_data_pages() tidy up
+    
+    Change the loop style of copy_data_pages() to remove a duplicate condition.
+    
+    Signed-off-by: Fengguang Wu 
+    Acked-by: Rafael J. Wysocki 
+    Signed-off-by: Adrian Bunk 
+
+diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
+index ccc95ac07bed..78039b477d2b 100644
+--- a/kernel/power/snapshot.c
++++ b/kernel/power/snapshot.c
+@@ -1005,11 +1005,12 @@ copy_data_pages(struct memory_bitmap *copy_bm, struct memory_bitmap *orig_bm)
+ 	}
+ 	memory_bm_position_reset(orig_bm);
+ 	memory_bm_position_reset(copy_bm);
+-	do {
++	for(;;) {
+ 		pfn = memory_bm_next_pfn(orig_bm);
+-		if (likely(pfn != BM_END_OF_MAP))
+-			copy_data_page(memory_bm_next_pfn(copy_bm), pfn);
+-	} while (pfn != BM_END_OF_MAP);
++		if (unlikely(pfn == BM_END_OF_MAP))
++			break;
++		copy_data_page(memory_bm_next_pfn(copy_bm), pfn);
++	}
+ }
+ 
+ /* Total number of image pages */

commit f68fd5f480248ca49e20e30a8e2387bc54694580
+Author: Fengguang Wu 
+Date:   Wed Oct 17 18:04:34 2007 +0200
+
+    x86: call free_init_pages() with irqs enabled in alternative_instructions()
+    
+    In alternative_instructions(), call free_init_pages() with irqs enabled.
+    
+    It fixes the warning message in smp_call_function*(), which should not be
+    called with irqs disabled.
+    
+    [    0.310000] CPU: L1 I Cache: 64K (64 bytes/line), D cache 64K (64 bytes/line)
+    [    0.310000] CPU: L2 Cache: 512K (64 bytes/line)
+    [    0.310000] CPU 0/0 -> Node 0
+    [    0.310000] SMP alternatives: switching to UP code
+    [    0.310000] Freeing SMP alternatives: 25k freed
+    [    0.310000] WARNING: at arch/x86_64/kernel/smp.c:397 smp_call_function_mask()
+    [    0.310000]
+    [    0.310000] Call Trace:
+    [    0.310000]  [] dump_trace+0x3ee/0x4a0
+    [    0.310000]  [] show_trace+0x43/0x70
+    [    0.310000]  [] dump_stack+0x15/0x20
+    [    0.310000]  [] smp_call_function_mask+0x94/0xa0
+    [    0.310000]  [] smp_call_function+0x32/0x40
+    [    0.310000]  [] on_each_cpu+0x1f/0x50
+    [    0.310000]  [] global_flush_tlb+0x8c/0x110
+    [    0.310000]  [] free_init_pages+0xe5/0xf0
+    [    0.310000]  [] alternative_instructions+0x7e/0x150
+    [    0.310000]  [] check_bugs+0x1a/0x20
+    [    0.310000]  [] start_kernel+0x2da/0x380
+    [    0.310000]  [] _sinittext+0x132/0x140
+    [    0.310000]
+    [    0.320000] ACPI: Core revision 20070126
+    [    0.560000] Using local APIC timer interrupts.
+    [    0.590000] Detected 62.496 MHz APIC timer.
+    [    0.590000] Brought up 1 CPUs
+    
+    [ tglx: arch/x86 adaptation ]
+    
+    Cc: Laurent Vivier 
+    Cc: Andi Kleen 
+    Signed-off-by: Fengguang Wu 
+    Signed-off-by: Andi Kleen 
+    Signed-off-by: Ingo Molnar 
+    Signed-off-by: Thomas Gleixner 
+
+diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
+index 11b03d3c6fda..dff1c9e1c2ee 100644
+--- a/arch/x86/kernel/alternative.c
++++ b/arch/x86/kernel/alternative.c
+@@ -415,9 +415,6 @@ void __init alternative_instructions(void)
+ 			alternatives_smp_unlock(__smp_locks, __smp_locks_end,
+ 						_text, _etext);
+ 		}
+-		free_init_pages("SMP alternatives",
+-				(unsigned long)__smp_locks,
+-				(unsigned long)__smp_locks_end);
+ 	} else {
+ 		alternatives_smp_module_add(NULL, "core kernel",
+ 					    __smp_locks, __smp_locks_end,
+@@ -428,6 +425,11 @@ void __init alternative_instructions(void)
+  	apply_paravirt(__parainstructions, __parainstructions_end);
+ 	local_irq_restore(flags);
+ 
++	if (smp_alt_once)
++		free_init_pages("SMP alternatives",
++				(unsigned long)__smp_locks,
++				(unsigned long)__smp_locks_end);
++
+ 	restart_nmi();
+ #ifdef CONFIG_X86_MCE
+ 	restart_mce();

commit 369f2389e7d03022abdd25e298bffb9613cd0e54
+Author: Fengguang Wu 
+Date:   Tue Oct 16 23:30:45 2007 -0700
+
+    writeback: remove unnecessary wait in throttle_vm_writeout()
+    
+    We don't want to introduce pointless delays in throttle_vm_writeout() when
+    the writeback limits are not yet exceeded, do we?
+    
+    Cc: Nick Piggin 
+    Cc: OGAWA Hirofumi 
+    Cc: Kumar Gala 
+    Cc: Pete Zaitcev 
+    Cc: Greg KH 
+    Reviewed-by: Rik van Riel 
+    Signed-off-by: Fengguang Wu 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/mm/page-writeback.c b/mm/page-writeback.c
+index d8c21e5a1bc9..7845462064f4 100644
+--- a/mm/page-writeback.c
++++ b/mm/page-writeback.c
+@@ -502,16 +502,6 @@ void throttle_vm_writeout(gfp_t gfp_mask)
+ 	long background_thresh;
+ 	long dirty_thresh;
+ 
+-	if ((gfp_mask & (__GFP_FS|__GFP_IO)) != (__GFP_FS|__GFP_IO)) {
+-		/*
+-		 * The caller might hold locks which can prevent IO completion
+-		 * or progress in the filesystem.  So we cannot just sit here
+-		 * waiting for IO to complete.
+-		 */
+-		congestion_wait(WRITE, HZ/10);
+-		return;
+-	}
+-
+         for ( ; ; ) {
+ 		get_dirty_limits(&background_thresh, &dirty_thresh, NULL, NULL);
+ 
+@@ -525,6 +515,14 @@ void throttle_vm_writeout(gfp_t gfp_mask)
+ 			global_page_state(NR_WRITEBACK) <= dirty_thresh)
+                         	break;
+                 congestion_wait(WRITE, HZ/10);
++
++		/*
++		 * The caller might hold locks which can prevent IO completion
++		 * or progress in the filesystem.  So we cannot just sit here
++		 * waiting for IO to complete.
++		 */
++		if ((gfp_mask & (__GFP_FS|__GFP_IO)) != (__GFP_FS|__GFP_IO))
++			break;
+         }
+ }
+ 

commit 2e6883bdf49abd0e7f0d9b6297fc3be7ebb2250b
+Author: Fengguang Wu 
+Date:   Tue Oct 16 23:30:43 2007 -0700
+
+    writeback: introduce writeback_control.more_io to indicate more io
+    
+    After making dirty a 100M file, the normal behavior is to start the writeback
+    for all data after 30s delays.  But sometimes the following happens instead:
+    
+            - after 30s:    ~4M
+            - after 5s:     ~4M
+            - after 5s:     all remaining 92M
+    
+    Some analyze shows that the internal io dispatch queues goes like this:
+    
+                    s_io            s_more_io
+                    -------------------------
+            1)      100M,1K         0
+            2)      1K              96M
+            3)      0               96M
+    
+    1) initial state with a 100M file and a 1K file
+    2) 4M written, nr_to_write <= 0, so write more
+    3) 1K written, nr_to_write > 0, no more writes(BUG)
+    
+    nr_to_write > 0 in (3) fools the upper layer to think that data have all been
+    written out.  The big dirty file is actually still sitting in s_more_io.  We
+    cannot simply splice s_more_io back to s_io as soon as s_io becomes empty, and
+    let the loop in generic_sync_sb_inodes() continue: this may starve newly
+    expired inodes in s_dirty.  It is also not an option to draw inodes from both
+    s_more_io and s_dirty, an let the loop go on: this might lead to live locks,
+    and might also starve other superblocks in sync time(well kupdate may still
+    starve some superblocks, that's another bug).
+    
+    We have to return when a full scan of s_io completes.  So nr_to_write > 0 does
+    not necessarily mean that "all data are written".  This patch introduces a
+    flag writeback_control.more_io to indicate this situation.  With it the big
+    dirty file no longer has to wait for the next kupdate invocation 5s later.
+    
+    Cc: David Chinner 
+    Cc: Ken Chen 
+    Signed-off-by: Fengguang Wu 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
+index 414df43706c7..71c158ac60a3 100644
+--- a/fs/fs-writeback.c
++++ b/fs/fs-writeback.c
+@@ -473,6 +473,8 @@ sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
+ 		if (wbc->nr_to_write <= 0)
+ 			break;
+ 	}
++	if (!list_empty(&sb->s_more_io))
++		wbc->more_io = 1;
+ 	return;		/* Leave any unwritten inodes on s_io */
+ }
+ 
+diff --git a/include/linux/writeback.h b/include/linux/writeback.h
+index 52be879793ed..1200868a5dee 100644
+--- a/include/linux/writeback.h
++++ b/include/linux/writeback.h
+@@ -62,6 +62,7 @@ struct writeback_control {
+ 	unsigned for_reclaim:1;		/* Invoked from the page allocator */
+ 	unsigned for_writepages:1;	/* This is a writepages() call */
+ 	unsigned range_cyclic:1;	/* range_start is cyclic */
++	unsigned more_io:1;		/* more io to be dispatched */
+ };
+ 
+ /*
+diff --git a/mm/page-writeback.c b/mm/page-writeback.c
+index 334852131588..bcdbbf6c4a85 100644
+--- a/mm/page-writeback.c
++++ b/mm/page-writeback.c
+@@ -553,6 +553,7 @@ static void background_writeout(unsigned long _min_pages)
+ 			global_page_state(NR_UNSTABLE_NFS) < background_thresh
+ 				&& min_pages <= 0)
+ 			break;
++		wbc.more_io = 0;
+ 		wbc.encountered_congestion = 0;
+ 		wbc.nr_to_write = MAX_WRITEBACK_PAGES;
+ 		wbc.pages_skipped = 0;
+@@ -560,8 +561,9 @@ static void background_writeout(unsigned long _min_pages)
+ 		min_pages -= MAX_WRITEBACK_PAGES - wbc.nr_to_write;
+ 		if (wbc.nr_to_write > 0 || wbc.pages_skipped > 0) {
+ 			/* Wrote less than expected */
+-			congestion_wait(WRITE, HZ/10);
+-			if (!wbc.encountered_congestion)
++			if (wbc.encountered_congestion || wbc.more_io)
++				congestion_wait(WRITE, HZ/10);
++			else
+ 				break;
+ 		}
+ 	}
+@@ -626,11 +628,12 @@ static void wb_kupdate(unsigned long arg)
+ 			global_page_state(NR_UNSTABLE_NFS) +
+ 			(inodes_stat.nr_inodes - inodes_stat.nr_unused);
+ 	while (nr_to_write > 0) {
++		wbc.more_io = 0;
+ 		wbc.encountered_congestion = 0;
+ 		wbc.nr_to_write = MAX_WRITEBACK_PAGES;
+ 		writeback_inodes(&wbc);
+ 		if (wbc.nr_to_write > 0) {
+-			if (wbc.encountered_congestion)
++			if (wbc.encountered_congestion || wbc.more_io)
+ 				congestion_wait(WRITE, HZ/10);
+ 			else
+ 				break;	/* All the old data is written */

commit 1f7decf6d9f06dac008b8d66935c0c3b18e564f9
+Author: Fengguang Wu 
+Date:   Tue Oct 16 23:30:42 2007 -0700
+
+    writeback: remove pages_skipped accounting in __block_write_full_page()
+    
+    Miklos Szeredi  and me identified a writeback bug:
+    
+    > The following strange behavior can be observed:
+    >
+    > 1. large file is written
+    > 2. after 30 seconds, nr_dirty goes down by 1024
+    > 3. then for some time (< 30 sec) nothing happens (disk idle)
+    > 4. then nr_dirty again goes down by 1024
+    > 5. repeat from 3. until whole file is written
+    >
+    > So basically a 4Mbyte chunk of the file is written every 30 seconds.
+    > I'm quite sure this is not the intended behavior.
+    
+    It can be produced by the following test scheme:
+    
+    # cat bin/test-writeback.sh
+    grep nr_dirty /proc/vmstat
+    echo 1 > /proc/sys/fs/inode_debug
+    dd if=/dev/zero of=/var/x bs=1K count=204800&
+    while true; do grep nr_dirty /proc/vmstat; sleep 1; done
+    
+    # bin/test-writeback.sh
+    nr_dirty 19207
+    nr_dirty 19207
+    nr_dirty 30924
+    204800+0 records in
+    204800+0 records out
+    209715200 bytes (210 MB) copied, 1.58363 seconds, 132 MB/s
+    nr_dirty 47150
+    nr_dirty 47141
+    nr_dirty 47142
+    nr_dirty 47142
+    nr_dirty 47142
+    nr_dirty 47142
+    nr_dirty 47205
+    nr_dirty 47214
+    nr_dirty 47214
+    nr_dirty 47214
+    nr_dirty 47214
+    nr_dirty 47214
+    nr_dirty 47215
+    nr_dirty 47216
+    nr_dirty 47216
+    nr_dirty 47216
+    nr_dirty 47154
+    nr_dirty 47143
+    nr_dirty 47143
+    nr_dirty 47143
+    nr_dirty 47143
+    nr_dirty 47143
+    nr_dirty 47142
+    nr_dirty 47142
+    nr_dirty 47142
+    nr_dirty 47142
+    nr_dirty 47134
+    nr_dirty 47134
+    nr_dirty 47135
+    nr_dirty 47135
+    nr_dirty 47135
+    nr_dirty 46097 <== -1038
+    nr_dirty 46098
+    nr_dirty 46098
+    nr_dirty 46098
+    [...]
+    nr_dirty 46091
+    nr_dirty 46092
+    nr_dirty 46092
+    nr_dirty 45069 <== -1023
+    nr_dirty 45056
+    nr_dirty 45056
+    nr_dirty 45056
+    [...]
+    nr_dirty 37822
+    nr_dirty 36799 <== -1023
+    [...]
+    nr_dirty 36781
+    nr_dirty 35758 <== -1023
+    [...]
+    nr_dirty 34708
+    nr_dirty 33672 <== -1024
+    [...]
+    nr_dirty 33692
+    nr_dirty 32669 <== -1023
+    
+    % ls -li /var/x
+    847824 -rw-r--r-- 1 root root 200M 2007-08-12 04:12 /var/x
+    
+    % dmesg|grep 847824  # generated by a debug printk
+    [  529.263184] redirtied inode 847824 line 548
+    [  564.250872] redirtied inode 847824 line 548
+    [  594.272797] redirtied inode 847824 line 548
+    [  629.231330] redirtied inode 847824 line 548
+    [  659.224674] redirtied inode 847824 line 548
+    [  689.219890] redirtied inode 847824 line 548
+    [  724.226655] redirtied inode 847824 line 548
+    [  759.198568] redirtied inode 847824 line 548
+    
+    # line 548 in fs/fs-writeback.c:
+    543                 if (wbc->pages_skipped != pages_skipped) {
+    544                         /*
+    545                          * writeback is not making progress due to locked
+    546                          * buffers.  Skip this inode for now.
+    547                          */
+    548                         redirty_tail(inode);
+    549                 }
+    
+    More debug efforts show that __block_write_full_page()
+    never has the chance to call submit_bh() for that big dirty file:
+    the buffer head is *clean*. So basicly no page io is issued by
+    __block_write_full_page(), hence pages_skipped goes up.
+    
+    Also the comment in generic_sync_sb_inodes():
+    
+    544                         /*
+    545                          * writeback is not making progress due to locked
+    546                          * buffers.  Skip this inode for now.
+    547                          */
+    
+    and the comment in __block_write_full_page():
+    
+    1713                 /*
+    1714                  * The page was marked dirty, but the buffers were
+    1715                  * clean.  Someone wrote them back by hand with
+    1716                  * ll_rw_block/submit_bh.  A rare case.
+    1717                  */
+    
+    do not quite agree with each other. The page writeback should be skipped for
+    'locked buffer', but here it is 'clean buffer'!
+    
+    This patch fixes this bug. Though I'm not sure why __block_write_full_page()
+    is called only to do nothing and who actually issued the writeback for us.
+    
+    This is the two possible new behaviors after the patch:
+    
+    1) pretty nice: wait 30s and write ALL:)
+    2) not so good:
+            - during the dd: ~16M
+            - after 30s:      ~4M
+            - after 5s:       ~4M
+            - after 5s:     ~176M
+    
+    The next patch will fix case (2).
+    
+    Cc: David Chinner 
+    Cc: Ken Chen 
+    Signed-off-by: Fengguang Wu 
+    Signed-off-by: David Chinner 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/buffer.c b/fs/buffer.c
+index 86e58b1dcd9c..76403b1764c5 100644
+--- a/fs/buffer.c
++++ b/fs/buffer.c
+@@ -1730,7 +1730,6 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
+ 		 * The page and buffer_heads can be released at any time from
+ 		 * here on.
+ 		 */
+-		wbc->pages_skipped++;	/* We didn't write this page */
+ 	}
+ 	return err;
+ 
+diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
+index 354d68a32d4a..52bd08c0a278 100644
+--- a/fs/xfs/linux-2.6/xfs_aops.c
++++ b/fs/xfs/linux-2.6/xfs_aops.c
+@@ -402,10 +402,9 @@ xfs_start_page_writeback(
+ 		clear_page_dirty_for_io(page);
+ 	set_page_writeback(page);
+ 	unlock_page(page);
+-	if (!buffers) {
++	/* If no buffers on the page are to be written, finish it here */
++	if (!buffers)
+ 		end_page_writeback(page);
+-		wbc->pages_skipped++;	/* We didn't write this page */
+-	}
+ }
+ 
+ static inline int bio_add_buffer(struct bio *bio, struct buffer_head *bh)

commit 08d8e9749e7f0435ba4683b620e8d30d59276b4c
+Author: Fengguang Wu 
+Date:   Tue Oct 16 23:30:39 2007 -0700
+
+    writeback: fix ntfs with sb_has_dirty_inodes()
+    
+    NTFS's if-condition on dirty inodes is not complete.  Fix it with
+    sb_has_dirty_inodes().
+    
+    Cc: Anton Altaparmakov 
+    Cc: Ken Chen 
+    Signed-off-by: Fengguang Wu 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
+index 1f22fb5217c0..414df43706c7 100644
+--- a/fs/fs-writeback.c
++++ b/fs/fs-writeback.c
+@@ -199,6 +199,14 @@ static void queue_io(struct super_block *sb,
+ 	move_expired_inodes(&sb->s_dirty, &sb->s_io, older_than_this);
+ }
+ 
++int sb_has_dirty_inodes(struct super_block *sb)
++{
++	return !list_empty(&sb->s_dirty) ||
++	       !list_empty(&sb->s_io) ||
++	       !list_empty(&sb->s_more_io);
++}
++EXPORT_SYMBOL(sb_has_dirty_inodes);
++
+ /*
+  * Write a single inode's dirty pages and inode data out to disk.
+  * If `wait' is set, wait on the writeout.
+@@ -497,7 +505,7 @@ writeback_inodes(struct writeback_control *wbc)
+ restart:
+ 	sb = sb_entry(super_blocks.prev);
+ 	for (; sb != sb_entry(&super_blocks); sb = sb_entry(sb->s_list.prev)) {
+-		if (!list_empty(&sb->s_dirty) || !list_empty(&sb->s_io)) {
++		if (sb_has_dirty_inodes(sb)) {
+ 			/* we're making our own get_super here */
+ 			sb->s_count++;
+ 			spin_unlock(&sb_lock);
+diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
+index ad2124573024..3e76f3b216bc 100644
+--- a/fs/ntfs/super.c
++++ b/fs/ntfs/super.c
+@@ -2381,14 +2381,14 @@ static void ntfs_put_super(struct super_block *sb)
+ 	 */
+ 	ntfs_commit_inode(vol->mft_ino);
+ 	write_inode_now(vol->mft_ino, 1);
+-	if (!list_empty(&sb->s_dirty)) {
++	if (sb_has_dirty_inodes(sb)) {
+ 		const char *s1, *s2;
+ 
+ 		mutex_lock(&vol->mft_ino->i_mutex);
+ 		truncate_inode_pages(vol->mft_ino->i_mapping, 0);
+ 		mutex_unlock(&vol->mft_ino->i_mutex);
+ 		write_inode_now(vol->mft_ino, 1);
+-		if (!list_empty(&sb->s_dirty)) {
++		if (sb_has_dirty_inodes(sb)) {
+ 			static const char *_s1 = "inodes";
+ 			static const char *_s2 = "";
+ 			s1 = _s1;
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 0b38a897c114..b70331f9f5b7 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -1729,6 +1729,7 @@ extern int bdev_read_only(struct block_device *);
+ extern int set_blocksize(struct block_device *, int);
+ extern int sb_set_blocksize(struct super_block *, int);
+ extern int sb_min_blocksize(struct super_block *, int);
++extern int sb_has_dirty_inodes(struct super_block *);
+ 
+ extern int generic_file_mmap(struct file *, struct vm_area_struct *);
+ extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *);

commit 2c1365791048e8aff42138ed5f6040b3c7824a69
+Author: Fengguang Wu 
+Date:   Tue Oct 16 23:30:39 2007 -0700
+
+    writeback: fix time ordering of the per superblock inode lists 8
+    
+    Streamline the management of dirty inode lists and fix time ordering bugs.
+    
+    The writeback logic used to move not-yet-expired dirty inodes from s_dirty to
+    s_io, *only to* move them back.  The move-inodes-back-and-forth thing is a
+    mess, which is eliminated by this patch.
+    
+    The new scheme is:
+    - s_dirty acts as a time ordered io delaying queue;
+    - s_io/s_more_io together acts as an io dispatching queue.
+    
+    On kupdate writeback, we pull some inodes from s_dirty to s_io at the start of
+    every full scan of s_io.  Otherwise  (i.e. for sync/throttle/background
+    writeback), we always pull from s_dirty on each run (a partial scan).
+    
+    Note that the line
+            list_splice_init(&sb->s_more_io, &sb->s_io);
+    is moved to queue_io() to leave s_io empty. Otherwise a big dirtied file will
+    sit in s_io for a long time, preventing new expired inodes to get in.
+    
+    Cc: Ken Chen 
+    Cc: Andrew Morton 
+    Signed-off-by: Fengguang Wu 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
+index c9d105ff7970..1f22fb5217c0 100644
+--- a/fs/fs-writeback.c
++++ b/fs/fs-writeback.c
+@@ -119,7 +119,7 @@ void __mark_inode_dirty(struct inode *inode, int flags)
+ 			goto out;
+ 
+ 		/*
+-		 * If the inode was already on s_dirty or s_io, don't
++		 * If the inode was already on s_dirty/s_io/s_more_io, don't
+ 		 * reposition it (that would break s_dirty time-ordering).
+ 		 */
+ 		if (!was_dirty) {
+@@ -172,6 +172,33 @@ static void requeue_io(struct inode *inode)
+ 	list_move(&inode->i_list, &inode->i_sb->s_more_io);
+ }
+ 
++/*
++ * Move expired dirty inodes from @delaying_queue to @dispatch_queue.
++ */
++static void move_expired_inodes(struct list_head *delaying_queue,
++			       struct list_head *dispatch_queue,
++				unsigned long *older_than_this)
++{
++	while (!list_empty(delaying_queue)) {
++		struct inode *inode = list_entry(delaying_queue->prev,
++						struct inode, i_list);
++		if (older_than_this &&
++			time_after(inode->dirtied_when, *older_than_this))
++			break;
++		list_move(&inode->i_list, dispatch_queue);
++	}
++}
++
++/*
++ * Queue all expired dirty inodes for io, eldest first.
++ */
++static void queue_io(struct super_block *sb,
++				unsigned long *older_than_this)
++{
++	list_splice_init(&sb->s_more_io, sb->s_io.prev);
++	move_expired_inodes(&sb->s_dirty, &sb->s_io, older_than_this);
++}
++
+ /*
+  * Write a single inode's dirty pages and inode data out to disk.
+  * If `wait' is set, wait on the writeout.
+@@ -222,7 +249,7 @@ __sync_single_inode(struct inode *inode, struct writeback_control *wbc)
+ 			/*
+ 			 * We didn't write back all the pages.  nfs_writepages()
+ 			 * sometimes bales out without doing anything. Redirty
+-			 * the inode.  It is moved from s_io onto s_dirty.
++			 * the inode; Move it from s_io onto s_more_io/s_dirty.
+ 			 */
+ 			/*
+ 			 * akpm: if the caller was the kupdate function we put
+@@ -235,10 +262,9 @@ __sync_single_inode(struct inode *inode, struct writeback_control *wbc)
+ 			 */
+ 			if (wbc->for_kupdate) {
+ 				/*
+-				 * For the kupdate function we leave the inode
+-				 * at the head of sb_dirty so it will get more
+-				 * writeout as soon as the queue becomes
+-				 * uncongested.
++				 * For the kupdate function we move the inode
++				 * to s_more_io so it will get more writeout as
++				 * soon as the queue becomes uncongested.
+ 				 */
+ 				inode->i_state |= I_DIRTY_PAGES;
+ 				requeue_io(inode);
+@@ -296,10 +322,10 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
+ 
+ 		/*
+ 		 * We're skipping this inode because it's locked, and we're not
+-		 * doing writeback-for-data-integrity.  Move it to the head of
+-		 * s_dirty so that writeback can proceed with the other inodes
+-		 * on s_io.  We'll have another go at writing back this inode
+-		 * when the s_dirty iodes get moved back onto s_io.
++		 * doing writeback-for-data-integrity.  Move it to s_more_io so
++		 * that writeback can proceed with the other inodes on s_io.
++		 * We'll have another go at writing back this inode when we
++		 * completed a full scan of s_io.
+ 		 */
+ 		requeue_io(inode);
+ 
+@@ -366,7 +392,7 @@ sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
+ 	const unsigned long start = jiffies;	/* livelock avoidance */
+ 
+ 	if (!wbc->for_kupdate || list_empty(&sb->s_io))
+-		list_splice_init(&sb->s_dirty, &sb->s_io);
++		queue_io(sb, wbc->older_than_this);
+ 
+ 	while (!list_empty(&sb->s_io)) {
+ 		struct inode *inode = list_entry(sb->s_io.prev,
+@@ -411,13 +437,6 @@ sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
+ 		if (time_after(inode->dirtied_when, start))
+ 			break;
+ 
+-		/* Was this inode dirtied too recently? */
+-		if (wbc->older_than_this && time_after(inode->dirtied_when,
+-						*wbc->older_than_this)) {
+-			list_splice_init(&sb->s_io, sb->s_dirty.prev);
+-			break;
+-		}
+-
+ 		/* Is another pdflush already flushing this queue? */
+ 		if (current_is_pdflush() && !writeback_acquire(bdi))
+ 			break;
+@@ -446,10 +465,6 @@ sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
+ 		if (wbc->nr_to_write <= 0)
+ 			break;
+ 	}
+-
+-	if (list_empty(&sb->s_io))
+-		list_splice_init(&sb->s_more_io, &sb->s_io);
+-
+ 	return;		/* Leave any unwritten inodes on s_io */
+ }
+ 
+@@ -459,7 +474,7 @@ sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
+  * Note:
+  * We don't need to grab a reference to superblock here. If it has non-empty
+  * ->s_dirty it's hadn't been killed yet and kill_super() won't proceed
+- * past sync_inodes_sb() until both the ->s_dirty and ->s_io lists are
++ * past sync_inodes_sb() until the ->s_dirty/s_io/s_more_io lists are all
+  * empty. Since __sync_single_inode() regains inode_lock before it finally moves
+  * inode from superblock lists we are OK.
+  *

commit 57f6b96c09c30e444e0d3fc3080feba037657a7b
+Author: Fengguang Wu 
+Date:   Tue Oct 16 01:24:37 2007 -0700
+
+    filemap: convert some unsigned long to pgoff_t
+    
+    Convert some 'unsigned long' to pgoff_t.
+    
+    Signed-off-by: Fengguang Wu 
+    Cc: Rusty Russell 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
+index 8a83537d6978..862fc07dc6c0 100644
+--- a/include/linux/pagemap.h
++++ b/include/linux/pagemap.h
+@@ -84,11 +84,11 @@ static inline struct page *page_cache_alloc_cold(struct address_space *x)
+ typedef int filler_t(void *, struct page *);
+ 
+ extern struct page * find_get_page(struct address_space *mapping,
+-				unsigned long index);
++				pgoff_t index);
+ extern struct page * find_lock_page(struct address_space *mapping,
+-				unsigned long index);
++				pgoff_t index);
+ extern struct page * find_or_create_page(struct address_space *mapping,
+-				unsigned long index, gfp_t gfp_mask);
++				pgoff_t index, gfp_t gfp_mask);
+ unsigned find_get_pages(struct address_space *mapping, pgoff_t start,
+ 			unsigned int nr_pages, struct page **pages);
+ unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t start,
+@@ -99,41 +99,42 @@ unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index,
+ /*
+  * Returns locked page at given index in given cache, creating it if needed.
+  */
+-static inline struct page *grab_cache_page(struct address_space *mapping, unsigned long index)
++static inline struct page *grab_cache_page(struct address_space *mapping,
++								pgoff_t index)
+ {
+ 	return find_or_create_page(mapping, index, mapping_gfp_mask(mapping));
+ }
+ 
+ extern struct page * grab_cache_page_nowait(struct address_space *mapping,
+-				unsigned long index);
++				pgoff_t index);
+ extern struct page * read_cache_page_async(struct address_space *mapping,
+-				unsigned long index, filler_t *filler,
++				pgoff_t index, filler_t *filler,
+ 				void *data);
+ extern struct page * read_cache_page(struct address_space *mapping,
+-				unsigned long index, filler_t *filler,
++				pgoff_t index, filler_t *filler,
+ 				void *data);
+ extern int read_cache_pages(struct address_space *mapping,
+ 		struct list_head *pages, filler_t *filler, void *data);
+ 
+ static inline struct page *read_mapping_page_async(
+ 						struct address_space *mapping,
+-					     unsigned long index, void *data)
++						     pgoff_t index, void *data)
+ {
+ 	filler_t *filler = (filler_t *)mapping->a_ops->readpage;
+ 	return read_cache_page_async(mapping, index, filler, data);
+ }
+ 
+ static inline struct page *read_mapping_page(struct address_space *mapping,
+-					     unsigned long index, void *data)
++					     pgoff_t index, void *data)
+ {
+ 	filler_t *filler = (filler_t *)mapping->a_ops->readpage;
+ 	return read_cache_page(mapping, index, filler, data);
+ }
+ 
+ int add_to_page_cache(struct page *page, struct address_space *mapping,
+-				unsigned long index, gfp_t gfp_mask);
++				pgoff_t index, gfp_t gfp_mask);
+ int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
+-				unsigned long index, gfp_t gfp_mask);
++				pgoff_t index, gfp_t gfp_mask);
+ extern void remove_from_page_cache(struct page *page);
+ extern void __remove_from_page_cache(struct page *page);
+ 
+diff --git a/mm/filemap.c b/mm/filemap.c
+index c1b94054cbbe..b436cbb3a834 100644
+--- a/mm/filemap.c
++++ b/mm/filemap.c
+@@ -593,7 +593,7 @@ void fastcall __lock_page_nosync(struct page *page)
+  * Is there a pagecache struct page at the given (mapping, offset) tuple?
+  * If yes, increment its refcount and return it; if no, return NULL.
+  */
+-struct page * find_get_page(struct address_space *mapping, unsigned long offset)
++struct page * find_get_page(struct address_space *mapping, pgoff_t offset)
+ {
+ 	struct page *page;
+ 
+@@ -617,7 +617,7 @@ EXPORT_SYMBOL(find_get_page);
+  * Returns zero if the page was not present. find_lock_page() may sleep.
+  */
+ struct page *find_lock_page(struct address_space *mapping,
+-				unsigned long offset)
++				pgoff_t offset)
+ {
+ 	struct page *page;
+ 
+@@ -663,7 +663,7 @@ EXPORT_SYMBOL(find_lock_page);
+  * memory exhaustion.
+  */
+ struct page *find_or_create_page(struct address_space *mapping,
+-		unsigned long index, gfp_t gfp_mask)
++		pgoff_t index, gfp_t gfp_mask)
+ {
+ 	struct page *page, *cached_page = NULL;
+ 	int err;
+@@ -797,7 +797,7 @@ EXPORT_SYMBOL(find_get_pages_tag);
+  * and deadlock against the caller's locked page.
+  */
+ struct page *
+-grab_cache_page_nowait(struct address_space *mapping, unsigned long index)
++grab_cache_page_nowait(struct address_space *mapping, pgoff_t index)
+ {
+ 	struct page *page = find_get_page(mapping, index);
+ 
+@@ -866,10 +866,10 @@ void do_generic_mapping_read(struct address_space *mapping,
+ 			     read_actor_t actor)
+ {
+ 	struct inode *inode = mapping->host;
+-	unsigned long index;
+-	unsigned long offset;
+-	unsigned long last_index;
+-	unsigned long prev_index;
++	pgoff_t index;
++	pgoff_t last_index;
++	pgoff_t prev_index;
++	unsigned long offset;      /* offset into pagecache page */
+ 	unsigned int prev_offset;
+ 	struct page *cached_page;
+ 	int error;
+@@ -883,7 +883,7 @@ void do_generic_mapping_read(struct address_space *mapping,
+ 
+ 	for (;;) {
+ 		struct page *page;
+-		unsigned long end_index;
++		pgoff_t end_index;
+ 		loff_t isize;
+ 		unsigned long nr, ret;
+ 
+@@ -1217,7 +1217,7 @@ EXPORT_SYMBOL(generic_file_aio_read);
+ 
+ static ssize_t
+ do_readahead(struct address_space *mapping, struct file *filp,
+-	     unsigned long index, unsigned long nr)
++	     pgoff_t index, unsigned long nr)
+ {
+ 	if (!mapping || !mapping->a_ops || !mapping->a_ops->readpage)
+ 		return -EINVAL;
+@@ -1237,8 +1237,8 @@ asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count)
+ 	if (file) {
+ 		if (file->f_mode & FMODE_READ) {
+ 			struct address_space *mapping = file->f_mapping;
+-			unsigned long start = offset >> PAGE_CACHE_SHIFT;
+-			unsigned long end = (offset + count - 1) >> PAGE_CACHE_SHIFT;
++			pgoff_t start = offset >> PAGE_CACHE_SHIFT;
++			pgoff_t end = (offset + count - 1) >> PAGE_CACHE_SHIFT;
+ 			unsigned long len = end - start + 1;
+ 			ret = do_readahead(mapping, file, start, len);
+ 		}
+@@ -1256,7 +1256,7 @@ asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count)
+  * This adds the requested page to the page cache if it isn't already there,
+  * and schedules an I/O to read in its contents from disk.
+  */
+-static int fastcall page_cache_read(struct file * file, unsigned long offset)
++static int fastcall page_cache_read(struct file * file, pgoff_t offset)
+ {
+ 	struct address_space *mapping = file->f_mapping;
+ 	struct page *page; 
+@@ -1497,7 +1497,7 @@ EXPORT_SYMBOL(generic_file_mmap);
+ EXPORT_SYMBOL(generic_file_readonly_mmap);
+ 
+ static struct page *__read_cache_page(struct address_space *mapping,
+-				unsigned long index,
++				pgoff_t index,
+ 				int (*filler)(void *,struct page*),
+ 				void *data)
+ {
+@@ -1538,7 +1538,7 @@ static struct page *__read_cache_page(struct address_space *mapping,
+  * after submitting it to the filler.
+  */
+ struct page *read_cache_page_async(struct address_space *mapping,
+-				unsigned long index,
++				pgoff_t index,
+ 				int (*filler)(void *,struct page*),
+ 				void *data)
+ {
+@@ -1586,7 +1586,7 @@ EXPORT_SYMBOL(read_cache_page_async);
+  * If the page does not get brought uptodate, return -EIO.
+  */
+ struct page *read_cache_page(struct address_space *mapping,
+-				unsigned long index,
++				pgoff_t index,
+ 				int (*filler)(void *,struct page*),
+ 				void *data)
+ {

commit b2c3843b1e25e2c67347c4671f33fbe6f5067e6b
+Author: Fengguang Wu 
+Date:   Tue Oct 16 01:24:37 2007 -0700
+
+    filemap: trivial code cleanups
+    
+    - remove unused local next_index in do_generic_mapping_read()
+    - remove a redudant page_cache_read() declaration
+    
+    Signed-off-by: Fengguang Wu 
+    Cc: Rusty Russell 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/mm/filemap.c b/mm/filemap.c
+index 3c97bdc74a85..c1b94054cbbe 100644
+--- a/mm/filemap.c
++++ b/mm/filemap.c
+@@ -869,7 +869,6 @@ void do_generic_mapping_read(struct address_space *mapping,
+ 	unsigned long index;
+ 	unsigned long offset;
+ 	unsigned long last_index;
+-	unsigned long next_index;
+ 	unsigned long prev_index;
+ 	unsigned int prev_offset;
+ 	struct page *cached_page;
+@@ -877,7 +876,6 @@ void do_generic_mapping_read(struct address_space *mapping,
+ 
+ 	cached_page = NULL;
+ 	index = *ppos >> PAGE_CACHE_SHIFT;
+-	next_index = index;
+ 	prev_index = ra->prev_pos >> PAGE_CACHE_SHIFT;
+ 	prev_offset = ra->prev_pos & (PAGE_CACHE_SIZE-1);
+ 	last_index = (*ppos + desc->count + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT;
+@@ -1250,7 +1248,6 @@ asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count)
+ }
+ 
+ #ifdef CONFIG_MMU
+-static int FASTCALL(page_cache_read(struct file * file, unsigned long offset));
+ /**
+  * page_cache_read - adds requested page to the page cache if not already there
+  * @file:	file to read

commit f2e189827a914b66e435e68b1c9e37775cb995ed
+Author: Fengguang Wu 
+Date:   Tue Oct 16 01:24:36 2007 -0700
+
+    readahead: remove the limit max_sectors_kb imposed on max_readahead_kb
+    
+    Remove the size limit max_sectors_kb imposed on max_readahead_kb.
+    
+    The size restriction is unreasonable.  Especially when max_sectors_kb cannot
+    grow larger than max_hw_sectors_kb, which can be rather small for some disk
+    drives.
+    
+    Cc: Jens Axboe 
+    Signed-off-by: Fengguang Wu 
+    Acked-by: Jens Axboe 
+    Cc: Rusty Russell 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
+index d875673e76cd..a83823fcd74f 100644
+--- a/block/ll_rw_blk.c
++++ b/block/ll_rw_blk.c
+@@ -3928,7 +3928,6 @@ queue_max_sectors_store(struct request_queue *q, const char *page, size_t count)
+ 			max_hw_sectors_kb = q->max_hw_sectors >> 1,
+ 			page_kb = 1 << (PAGE_CACHE_SHIFT - 10);
+ 	ssize_t ret = queue_var_store(&max_sectors_kb, page, count);
+-	int ra_kb;
+ 
+ 	if (max_sectors_kb > max_hw_sectors_kb || max_sectors_kb < page_kb)
+ 		return -EINVAL;
+@@ -3937,14 +3936,6 @@ queue_max_sectors_store(struct request_queue *q, const char *page, size_t count)
+ 	 * values synchronously:
+ 	 */
+ 	spin_lock_irq(q->queue_lock);
+-	/*
+-	 * Trim readahead window as well, if necessary:
+-	 */
+-	ra_kb = q->backing_dev_info.ra_pages << (PAGE_CACHE_SHIFT - 10);
+-	if (ra_kb > max_sectors_kb)
+-		q->backing_dev_info.ra_pages =
+-				max_sectors_kb >> (PAGE_CACHE_SHIFT - 10);
+-
+ 	q->max_sectors = max_sectors_kb << 1;
+ 	spin_unlock_irq(q->queue_lock);
+ 

commit 535443f51543df61111bbd234300ae549d220448
+Author: Fengguang Wu 
+Date:   Tue Oct 16 01:24:36 2007 -0700
+
+    readahead: remove several readahead macros
+    
+    Remove VM_MAX_CACHE_HIT, MAX_RA_PAGES and MIN_RA_PAGES.
+    
+    Signed-off-by: Fengguang Wu 
+    Cc: Rusty Russell 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/mm.h b/include/linux/mm.h
+index fbff8e481cc4..291c4cc06ea7 100644
+--- a/include/linux/mm.h
++++ b/include/linux/mm.h
+@@ -1106,8 +1106,6 @@ int write_one_page(struct page *page, int wait);
+ /* readahead.c */
+ #define VM_MAX_READAHEAD	128	/* kbytes */
+ #define VM_MIN_READAHEAD	16	/* kbytes (includes current page) */
+-#define VM_MAX_CACHE_HIT    	256	/* max pages in a row in cache before
+-					 * turning readahead off */
+ 
+ int do_page_cache_readahead(struct address_space *mapping, struct file *filp,
+ 			pgoff_t offset, unsigned long nr_to_read);
+diff --git a/mm/readahead.c b/mm/readahead.c
+index fd588ffc5086..fc52f9f1b80c 100644
+--- a/mm/readahead.c
++++ b/mm/readahead.c
+@@ -22,16 +22,8 @@ void default_unplug_io_fn(struct backing_dev_info *bdi, struct page *page)
+ }
+ EXPORT_SYMBOL(default_unplug_io_fn);
+ 
+-/*
+- * Convienent macros for min/max read-ahead pages.
+- * Note that MAX_RA_PAGES is rounded down, while MIN_RA_PAGES is rounded up.
+- * The latter is necessary for systems with large page size(i.e. 64k).
+- */
+-#define MAX_RA_PAGES	(VM_MAX_READAHEAD*1024 / PAGE_CACHE_SIZE)
+-#define MIN_RA_PAGES	DIV_ROUND_UP(VM_MIN_READAHEAD*1024, PAGE_CACHE_SIZE)
+-
+ struct backing_dev_info default_backing_dev_info = {
+-	.ra_pages	= MAX_RA_PAGES,
++	.ra_pages	= VM_MAX_READAHEAD * 1024 / PAGE_CACHE_SIZE,
+ 	.state		= 0,
+ 	.capabilities	= BDI_CAP_MAP_COPY,
+ 	.unplug_io_fn	= default_unplug_io_fn,

commit 7ff81078d8b9f3d05a27b7bd3786ffb1ef1b0d1f
+Author: Fengguang Wu 
+Date:   Tue Oct 16 01:24:35 2007 -0700
+
+    readahead: remove the local copy of ra in do_generic_mapping_read()
+    
+    The local copy of ra in do_generic_mapping_read() can now go away.
+    
+    It predates readanead(req_size).  In a time when the readahead code was called
+    on *every* single page.  Hence a local has to be made to reduce the chance of
+    the readahead state being overwritten by a concurrent reader.  More details
+    in: Linux: Random File I/O Regressions In 2.6
+    
+    
+    Cc: Nick Piggin 
+    Signed-off-by: Fengguang Wu 
+    Cc: Rusty Russell 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/mm/filemap.c b/mm/filemap.c
+index bbcca456d8a6..3c97bdc74a85 100644
+--- a/mm/filemap.c
++++ b/mm/filemap.c
+@@ -859,7 +859,7 @@ static void shrink_readahead_size_eio(struct file *filp,
+  * It may be NULL.
+  */
+ void do_generic_mapping_read(struct address_space *mapping,
+-			     struct file_ra_state *_ra,
++			     struct file_ra_state *ra,
+ 			     struct file *filp,
+ 			     loff_t *ppos,
+ 			     read_descriptor_t *desc,
+@@ -874,13 +874,12 @@ void do_generic_mapping_read(struct address_space *mapping,
+ 	unsigned int prev_offset;
+ 	struct page *cached_page;
+ 	int error;
+-	struct file_ra_state ra = *_ra;
+ 
+ 	cached_page = NULL;
+ 	index = *ppos >> PAGE_CACHE_SHIFT;
+ 	next_index = index;
+-	prev_index = ra.prev_pos >> PAGE_CACHE_SHIFT;
+-	prev_offset = ra.prev_pos & (PAGE_CACHE_SIZE-1);
++	prev_index = ra->prev_pos >> PAGE_CACHE_SHIFT;
++	prev_offset = ra->prev_pos & (PAGE_CACHE_SIZE-1);
+ 	last_index = (*ppos + desc->count + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT;
+ 	offset = *ppos & ~PAGE_CACHE_MASK;
+ 
+@@ -895,7 +894,7 @@ void do_generic_mapping_read(struct address_space *mapping,
+ 		page = find_get_page(mapping, index);
+ 		if (!page) {
+ 			page_cache_sync_readahead(mapping,
+-					&ra, filp,
++					ra, filp,
+ 					index, last_index - index);
+ 			page = find_get_page(mapping, index);
+ 			if (unlikely(page == NULL))
+@@ -903,7 +902,7 @@ void do_generic_mapping_read(struct address_space *mapping,
+ 		}
+ 		if (PageReadahead(page)) {
+ 			page_cache_async_readahead(mapping,
+-					&ra, filp, page,
++					ra, filp, page,
+ 					index, last_index - index);
+ 		}
+ 		if (!PageUptodate(page))
+@@ -1014,7 +1013,7 @@ void do_generic_mapping_read(struct address_space *mapping,
+ 				}
+ 				unlock_page(page);
+ 				error = -EIO;
+-				shrink_readahead_size_eio(filp, &ra);
++				shrink_readahead_size_eio(filp, ra);
+ 				goto readpage_error;
+ 			}
+ 			unlock_page(page);
+@@ -1054,10 +1053,9 @@ void do_generic_mapping_read(struct address_space *mapping,
+ 	}
+ 
+ out:
+-	*_ra = ra;
+-	_ra->prev_pos = prev_index;
+-	_ra->prev_pos <<= PAGE_CACHE_SHIFT;
+-	_ra->prev_pos |= prev_offset;
++	ra->prev_pos = prev_index;
++	ra->prev_pos <<= PAGE_CACHE_SHIFT;
++	ra->prev_pos |= prev_offset;
+ 
+ 	*ppos = ((loff_t)index << PAGE_CACHE_SHIFT) + offset;
+ 	if (cached_page)

commit 6b10c6c9fbfe754e8482efb8c8b84f8e40c0f2eb
+Author: Fengguang Wu 
+Date:   Tue Oct 16 01:24:34 2007 -0700
+
+    readahead: basic support of interleaved reads
+    
+    This is a simplified version of the pagecache context based readahead.  It
+    handles the case of multiple threads reading on the same fd and invalidating
+    each others' readahead state.  It does the trick by scanning the pagecache and
+    recovering the current read stream's readahead status.
+    
+    The algorithm works in a opportunistic way, in that it does not try to detect
+    interleaved reads _actively_, which requires a probe into the page cache
+    (which means a little more overhead for random reads).  It only tries to
+    handle a previously started sequential readahead whose state was overwritten
+    by another concurrent stream, and it can do this job pretty well.
+    
+    Negative and positive examples(or what you can expect from it):
+    
+    1) it cannot detect and serve perfect request-by-request interleaved reads
+       right:
+            time    stream 1  stream 2
+            0       1
+            1                 1001
+            2       2
+            3                 1002
+            4       3
+            5                 1003
+            6       4
+            7                 1004
+            8       5
+            9                 1005
+    
+    Here no single readahead will be carried out.
+    
+    2) However, if it's two concurrent reads by two threads, the chance of the
+       initial sequential readahead be started is huge. Once the first sequential
+       readahead is started for a stream, this patch will ensure that the readahead
+       window continues to rampup and won't be disturbed by other streams.
+    
+            time    stream 1  stream 2
+            0       1
+            1       2
+            2                 1001
+            3       3
+            4                 1002
+            5                 1003
+            6       4
+            7       5
+            8                 1004
+            9       6
+            10                1005
+            11      7
+            12                1006
+            13                1007
+    
+    Here stream 1 will start a readahead at page 2, and stream 2 will start its
+    first readahead at page 1003.  From then on the two streams will be served
+    right.
+    
+    Cc: Rusty Russell 
+    Signed-off-by: Fengguang Wu 
+    Cc: Rusty Russell 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/mm/readahead.c b/mm/readahead.c
+index 4a58befbde4a..fd588ffc5086 100644
+--- a/mm/readahead.c
++++ b/mm/readahead.c
+@@ -379,6 +379,29 @@ ondemand_readahead(struct address_space *mapping,
+ 						offset, req_size, 0);
+ 	}
+ 
++	/*
++	 * Hit a marked page without valid readahead state.
++	 * E.g. interleaved reads.
++	 * Query the pagecache for async_size, which normally equals to
++	 * readahead size. Ramp it up and use it as the new readahead size.
++	 */
++	if (hit_readahead_marker) {
++		pgoff_t start;
++
++		read_lock_irq(&mapping->tree_lock);
++		start = radix_tree_next_hole(&mapping->page_tree, offset, max+1);
++		read_unlock_irq(&mapping->tree_lock);
++
++		if (!start || start - offset > max)
++			return 0;
++
++		ra->start = start;
++		ra->size = start - offset;	/* old async_size */
++		ra->size = get_next_ra_size(ra, max);
++		ra->async_size = ra->size;
++		goto readit;
++	}
++
+ 	/*
+ 	 * It may be one of
+ 	 * 	- first read on start of file
+@@ -390,16 +413,6 @@ ondemand_readahead(struct address_space *mapping,
+ 	ra->size = get_init_ra_size(req_size, max);
+ 	ra->async_size = ra->size > req_size ? ra->size - req_size : ra->size;
+ 
+-	/*
+-	 * Hit on a marked page without valid readahead state.
+-	 * E.g. interleaved reads.
+-	 * Not knowing its readahead pos/size, bet on the minimal possible one.
+-	 */
+-	if (hit_readahead_marker) {
+-		ra->start++;
+-		ra->size = get_next_ra_size(ra, max);
+-	}
+-
+ readit:
+ 	return ra_submit(ra, mapping, filp);
+ }

commit 6df8ba4f8a4c4abca9ccad10441d0dddbdff301c
+Author: Fengguang Wu 
+Date:   Tue Oct 16 01:24:33 2007 -0700
+
+    radixtree: introduce radix_tree_next_hole()
+    
+    Introduce radix_tree_next_hole(root, index, max_scan) to scan radix tree for
+    the first hole.  It will be used in interleaved readahead.
+    
+    The implementation is dumb and obviously correct.  It can help debug(and
+    document) the possible smart one in future.
+    
+    Cc: Nick Piggin 
+    Signed-off-by: Fengguang Wu 
+    Cc: Rusty Russell 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h
+index f9e77d2ee320..430e4a8c1382 100644
+--- a/include/linux/radix-tree.h
++++ b/include/linux/radix-tree.h
+@@ -155,6 +155,8 @@ void *radix_tree_delete(struct radix_tree_root *, unsigned long);
+ unsigned int
+ radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
+ 			unsigned long first_index, unsigned int max_items);
++unsigned long radix_tree_next_hole(struct radix_tree_root *root,
++				unsigned long index, unsigned long max_scan);
+ int radix_tree_preload(gfp_t gfp_mask);
+ void radix_tree_init(void);
+ void *radix_tree_tag_set(struct radix_tree_root *root,
+diff --git a/lib/radix-tree.c b/lib/radix-tree.c
+index 514efb200be6..7af368a4401b 100644
+--- a/lib/radix-tree.c
++++ b/lib/radix-tree.c
+@@ -599,6 +599,42 @@ int radix_tree_tag_get(struct radix_tree_root *root,
+ EXPORT_SYMBOL(radix_tree_tag_get);
+ #endif
+ 
++/**
++ *	radix_tree_next_hole    -    find the next hole (not-present entry)
++ *	@root:		tree root
++ *	@index:		index key
++ *	@max_scan:	maximum range to search
++ *
++ *	Search the set [index, min(index+max_scan-1, MAX_INDEX)] for the lowest
++ *	indexed hole.
++ *
++ *	Returns: the index of the hole if found, otherwise returns an index
++ *	outside of the set specified (in which case 'return - index >= max_scan'
++ *	will be true).
++ *
++ *	radix_tree_next_hole may be called under rcu_read_lock. However, like
++ *	radix_tree_gang_lookup, this will not atomically search a snapshot of the
++ *	tree at a single point in time. For example, if a hole is created at index
++ *	5, then subsequently a hole is created at index 10, radix_tree_next_hole
++ *	covering both indexes may return 10 if called under rcu_read_lock.
++ */
++unsigned long radix_tree_next_hole(struct radix_tree_root *root,
++				unsigned long index, unsigned long max_scan)
++{
++	unsigned long i;
++
++	for (i = 0; i < max_scan; i++) {
++		if (!radix_tree_lookup(root, index))
++			break;
++		index++;
++		if (index == 0)
++			break;
++	}
++
++	return index;
++}
++EXPORT_SYMBOL(radix_tree_next_hole);
++
+ static unsigned int
+ __lookup(struct radix_tree_node *slot, void **results, unsigned long index,
+ 	unsigned int max_items, unsigned long *next_index)

commit f4e6b498d6e06742d72706ef50593a9c4dd72214
+Author: Fengguang Wu 
+Date:   Tue Oct 16 01:24:33 2007 -0700
+
+    readahead: combine file_ra_state.prev_index/prev_offset into prev_pos
+    
+    Combine the file_ra_state members
+                                    unsigned long prev_index
+                                    unsigned int prev_offset
+    into
+                                    loff_t prev_pos
+    
+    It is more consistent and better supports huge files.
+    
+    Thanks to Peter for the nice proposal!
+    
+    [akpm@linux-foundation.org: fix shift overflow]
+    Cc: Peter Zijlstra 
+    Signed-off-by: Fengguang Wu 
+    Cc: Rusty Russell 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c
+index c00723a99f44..c2c3491b18cf 100644
+--- a/fs/ext3/dir.c
++++ b/fs/ext3/dir.c
+@@ -143,7 +143,7 @@ static int ext3_readdir(struct file * filp,
+ 					sb->s_bdev->bd_inode->i_mapping,
+ 					&filp->f_ra, filp,
+ 					index, 1);
+-			filp->f_ra.prev_index = index;
++			filp->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT;
+ 			bh = ext3_bread(NULL, inode, blk, 0, &err);
+ 		}
+ 
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index 3ab01c04e00c..e11890acfa21 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -142,7 +142,7 @@ static int ext4_readdir(struct file * filp,
+ 					sb->s_bdev->bd_inode->i_mapping,
+ 					&filp->f_ra, filp,
+ 					index, 1);
+-			filp->f_ra.prev_index = index;
++			filp->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT;
+ 			bh = ext4_bread(NULL, inode, blk, 0, &err);
+ 		}
+ 
+diff --git a/fs/splice.c b/fs/splice.c
+index e95a36228863..2df6be43c667 100644
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -447,7 +447,7 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
+ 	 */
+ 	while (page_nr < nr_pages)
+ 		page_cache_release(pages[page_nr++]);
+-	in->f_ra.prev_index = index;
++	in->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT;
+ 
+ 	if (spd.nr_pages)
+ 		return splice_to_pipe(pipe, &spd);
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 8250811081ff..500ffc0e4ac7 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -704,8 +704,7 @@ struct file_ra_state {
+ 
+ 	unsigned int ra_pages;		/* Maximum readahead window */
+ 	int mmap_miss;			/* Cache miss stat for mmap accesses */
+-	unsigned long prev_index;	/* Cache last read() position */
+-	unsigned int prev_offset;	/* Offset where last read() ended in a page */
++	loff_t prev_pos;		/* Cache last read() position */
+ };
+ 
+ /*
+diff --git a/mm/filemap.c b/mm/filemap.c
+index 5dc18d76e703..bbcca456d8a6 100644
+--- a/mm/filemap.c
++++ b/mm/filemap.c
+@@ -879,8 +879,8 @@ void do_generic_mapping_read(struct address_space *mapping,
+ 	cached_page = NULL;
+ 	index = *ppos >> PAGE_CACHE_SHIFT;
+ 	next_index = index;
+-	prev_index = ra.prev_index;
+-	prev_offset = ra.prev_offset;
++	prev_index = ra.prev_pos >> PAGE_CACHE_SHIFT;
++	prev_offset = ra.prev_pos & (PAGE_CACHE_SIZE-1);
+ 	last_index = (*ppos + desc->count + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT;
+ 	offset = *ppos & ~PAGE_CACHE_MASK;
+ 
+@@ -966,7 +966,6 @@ void do_generic_mapping_read(struct address_space *mapping,
+ 		index += offset >> PAGE_CACHE_SHIFT;
+ 		offset &= ~PAGE_CACHE_MASK;
+ 		prev_offset = offset;
+-		ra.prev_offset = offset;
+ 
+ 		page_cache_release(page);
+ 		if (ret == nr && desc->count)
+@@ -1056,9 +1055,11 @@ void do_generic_mapping_read(struct address_space *mapping,
+ 
+ out:
+ 	*_ra = ra;
+-	_ra->prev_index = prev_index;
++	_ra->prev_pos = prev_index;
++	_ra->prev_pos <<= PAGE_CACHE_SHIFT;
++	_ra->prev_pos |= prev_offset;
+ 
+-	*ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
++	*ppos = ((loff_t)index << PAGE_CACHE_SHIFT) + offset;
+ 	if (cached_page)
+ 		page_cache_release(cached_page);
+ 	if (filp)
+@@ -1396,7 +1397,7 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+ 	 * Found the page and have a reference on it.
+ 	 */
+ 	mark_page_accessed(page);
+-	ra->prev_index = page->index;
++	ra->prev_pos = (loff_t)page->index << PAGE_CACHE_SHIFT;
+ 	vmf->page = page;
+ 	return ret | VM_FAULT_LOCKED;
+ 
+diff --git a/mm/readahead.c b/mm/readahead.c
+index d2504877b269..4a58befbde4a 100644
+--- a/mm/readahead.c
++++ b/mm/readahead.c
+@@ -46,7 +46,7 @@ void
+ file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping)
+ {
+ 	ra->ra_pages = mapping->backing_dev_info->ra_pages;
+-	ra->prev_index = -1;
++	ra->prev_pos = -1;
+ }
+ EXPORT_SYMBOL_GPL(file_ra_state_init);
+ 
+@@ -327,7 +327,7 @@ static unsigned long get_next_ra_size(struct file_ra_state *ra,
+  * indicator. The flag won't be set on already cached pages, to avoid the
+  * readahead-for-nothing fuss, saving pointless page cache lookups.
+  *
+- * prev_index tracks the last visited page in the _previous_ read request.
++ * prev_pos tracks the last visited byte in the _previous_ read request.
+  * It should be maintained by the caller, and will be used for detecting
+  * small random reads. Note that the readahead algorithm checks loosely
+  * for sequential patterns. Hence interleaved reads might be served as
+@@ -351,11 +351,9 @@ ondemand_readahead(struct address_space *mapping,
+ 		   bool hit_readahead_marker, pgoff_t offset,
+ 		   unsigned long req_size)
+ {
+-	int max;	/* max readahead pages */
+-	int sequential;
+-
+-	max = ra->ra_pages;
+-	sequential = (offset - ra->prev_index <= 1UL) || (req_size > max);
++	int	max = ra->ra_pages;	/* max readahead pages */
++	pgoff_t prev_offset;
++	int	sequential;
+ 
+ 	/*
+ 	 * It's the expected callback offset, assume sequential access.
+@@ -369,6 +367,9 @@ ondemand_readahead(struct address_space *mapping,
+ 		goto readit;
+ 	}
+ 
++	prev_offset = ra->prev_pos >> PAGE_CACHE_SHIFT;
++	sequential = offset - prev_offset <= 1UL || req_size > max;
++
+ 	/*
+ 	 * Standalone, small read.
+ 	 * Read as is, and do not pollute the readahead state.

commit 0bb7ba6b9c358c12084a3cbc6ac08c8d1e973937
+Author: Fengguang Wu 
+Date:   Tue Oct 16 01:24:32 2007 -0700
+
+    readahead: mmap read-around simplification
+    
+    Fold file_ra_state.mmap_hit into file_ra_state.mmap_miss and make it an int.
+    
+    Signed-off-by: Fengguang Wu 
+    Cc: Rusty Russell 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 7a998c49a086..8250811081ff 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -703,8 +703,7 @@ struct file_ra_state {
+ 					   there are only # of pages ahead */
+ 
+ 	unsigned int ra_pages;		/* Maximum readahead window */
+-	unsigned long mmap_hit;		/* Cache hit stat for mmap accesses */
+-	unsigned long mmap_miss;	/* Cache miss stat for mmap accesses */
++	int mmap_miss;			/* Cache miss stat for mmap accesses */
+ 	unsigned long prev_index;	/* Cache last read() position */
+ 	unsigned int prev_offset;	/* Offset where last read() ended in a page */
+ };
+diff --git a/mm/filemap.c b/mm/filemap.c
+index 15c8413ee929..5dc18d76e703 100644
+--- a/mm/filemap.c
++++ b/mm/filemap.c
+@@ -1349,7 +1349,7 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+ 		 * Do we miss much more than hit in this file? If so,
+ 		 * stop bothering with read-ahead. It will only hurt.
+ 		 */
+-		if (ra->mmap_miss > ra->mmap_hit + MMAP_LOTSAMISS)
++		if (ra->mmap_miss > MMAP_LOTSAMISS)
+ 			goto no_cached_page;
+ 
+ 		/*
+@@ -1375,7 +1375,7 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+ 	}
+ 
+ 	if (!did_readaround)
+-		ra->mmap_hit++;
++		ra->mmap_miss--;
+ 
+ 	/*
+ 	 * We have a locked page in the page cache, now we need to check

commit 937085aa35cc873d427d250a1e304d641af24628
+Author: Fengguang Wu 
+Date:   Tue Oct 16 01:24:31 2007 -0700
+
+    readahead: compacting file_ra_state
+    
+    Use 'unsigned int' instead of 'unsigned long' for readahead sizes.
+    
+    This helps reduce memory consumption on 64bit CPU when a lot of files are
+    opened.
+    
+    CC: Andi Kleen 
+    Signed-off-by: Fengguang Wu 
+    Cc: Rusty Russell 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 4a6a21077bae..7a998c49a086 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -697,12 +697,12 @@ struct fown_struct {
+  * Track a single file's readahead state
+  */
+ struct file_ra_state {
+-	pgoff_t start;                  /* where readahead started */
+-	unsigned long size;             /* # of readahead pages */
+-	unsigned long async_size;       /* do asynchronous readahead when
++	pgoff_t start;			/* where readahead started */
++	unsigned int size;		/* # of readahead pages */
++	unsigned int async_size;	/* do asynchronous readahead when
+ 					   there are only # of pages ahead */
+ 
+-	unsigned long ra_pages;		/* Maximum readahead window */
++	unsigned int ra_pages;		/* Maximum readahead window */
+ 	unsigned long mmap_hit;		/* Cache hit stat for mmap accesses */
+ 	unsigned long mmap_miss;	/* Cache miss stat for mmap accesses */
+ 	unsigned long prev_index;	/* Cache last read() position */
+diff --git a/mm/readahead.c b/mm/readahead.c
+index be20c9d699d3..d2504877b269 100644
+--- a/mm/readahead.c
++++ b/mm/readahead.c
+@@ -351,7 +351,7 @@ ondemand_readahead(struct address_space *mapping,
+ 		   bool hit_readahead_marker, pgoff_t offset,
+ 		   unsigned long req_size)
+ {
+-	unsigned long max;	/* max readahead pages */
++	int max;	/* max readahead pages */
+ 	int sequential;
+ 
+ 	max = ra->ra_pages;

commit f9acc8c7b35a100f3a9e0e6977f7807b0169f9a5
+Author: Fengguang Wu 
+Date:   Thu Jul 19 01:48:08 2007 -0700
+
+    readahead: sanify file_ra_state names
+    
+    Rename some file_ra_state variables and remove some accessors.
+    
+    It results in much simpler code.
+    Kudos to Rusty!
+    
+    Signed-off-by: Fengguang Wu 
+    Cc: Rusty Russell 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 29cb32d3a849..d33beadd9a43 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -695,16 +695,12 @@ struct fown_struct {
+ 
+ /*
+  * Track a single file's readahead state
+- *
+- *  ================#============|==================#==================|
+- *                  ^            ^                  ^                  ^
+- *  file_ra_state.la_index    .ra_index   .lookahead_index   .readahead_index
+  */
+ struct file_ra_state {
+-	pgoff_t la_index;               /* enqueue time */
+-	pgoff_t ra_index;               /* begin offset */
+-	pgoff_t lookahead_index;        /* time to do next readahead */
+-	pgoff_t readahead_index;        /* end offset */
++	pgoff_t start;                  /* where readahead started */
++	unsigned long size;             /* # of readahead pages */
++	unsigned long async_size;       /* do asynchronous readahead when
++					   there are only # of pages ahead */
+ 
+ 	unsigned long ra_pages;		/* Maximum readahead window */
+ 	unsigned long mmap_hit;		/* Cache hit stat for mmap accesses */
+@@ -713,60 +709,15 @@ struct file_ra_state {
+ 	unsigned int prev_offset;	/* Offset where last read() ended in a page */
+ };
+ 
+-/*
+- * Measuring read-ahead sizes.
+- *
+- *                  |----------- readahead size ------------>|
+- *  ===#============|==================#=====================|
+- *     |------- invoke interval ------>|-- lookahead size -->|
+- */
+-static inline unsigned long ra_readahead_size(struct file_ra_state *ra)
+-{
+-	return ra->readahead_index - ra->ra_index;
+-}
+-
+-static inline unsigned long ra_lookahead_size(struct file_ra_state *ra)
+-{
+-	return ra->readahead_index - ra->lookahead_index;
+-}
+-
+-static inline unsigned long ra_invoke_interval(struct file_ra_state *ra)
+-{
+-	return ra->lookahead_index - ra->la_index;
+-}
+-
+ /*
+  * Check if @index falls in the readahead windows.
+  */
+ static inline int ra_has_index(struct file_ra_state *ra, pgoff_t index)
+ {
+-	return (index >= ra->la_index &&
+-		index <  ra->readahead_index);
+-}
+-
+-/*
+- * Where is the old read-ahead and look-ahead?
+- */
+-static inline void ra_set_index(struct file_ra_state *ra,
+-				pgoff_t la_index, pgoff_t ra_index)
+-{
+-	ra->la_index = la_index;
+-	ra->ra_index = ra_index;
++	return (index >= ra->start &&
++		index <  ra->start + ra->size);
+ }
+ 
+-/*
+- * Where is the new read-ahead and look-ahead?
+- */
+-static inline void ra_set_size(struct file_ra_state *ra,
+-				unsigned long ra_size, unsigned long la_size)
+-{
+-	ra->readahead_index = ra->ra_index + ra_size;
+-	ra->lookahead_index = ra->ra_index + ra_size - la_size;
+-}
+-
+-unsigned long ra_submit(struct file_ra_state *ra,
+-		       struct address_space *mapping, struct file *filp);
+-
+ struct file {
+ 	/*
+ 	 * fu_list becomes invalid after file_free is called and queued via
+diff --git a/mm/readahead.c b/mm/readahead.c
+index 3d262bb738a9..39bf45d43320 100644
+--- a/mm/readahead.c
++++ b/mm/readahead.c
+@@ -253,21 +253,16 @@ unsigned long max_sane_readahead(unsigned long nr)
+ /*
+  * Submit IO for the read-ahead request in file_ra_state.
+  */
+-unsigned long ra_submit(struct file_ra_state *ra,
++static unsigned long ra_submit(struct file_ra_state *ra,
+ 		       struct address_space *mapping, struct file *filp)
+ {
+-	unsigned long ra_size;
+-	unsigned long la_size;
+ 	int actual;
+ 
+-	ra_size = ra_readahead_size(ra);
+-	la_size = ra_lookahead_size(ra);
+ 	actual = __do_page_cache_readahead(mapping, filp,
+-					ra->ra_index, ra_size, la_size);
++					ra->start, ra->size, ra->async_size);
+ 
+ 	return actual;
+ }
+-EXPORT_SYMBOL_GPL(ra_submit);
+ 
+ /*
+  * Set the initial window size, round to next power of 2 and square
+@@ -296,7 +291,7 @@ static unsigned long get_init_ra_size(unsigned long size, unsigned long max)
+ static unsigned long get_next_ra_size(struct file_ra_state *ra,
+ 						unsigned long max)
+ {
+-	unsigned long cur = ra->readahead_index - ra->ra_index;
++	unsigned long cur = ra->size;
+ 	unsigned long newsize;
+ 
+ 	if (cur < max / 16)
+@@ -313,28 +308,21 @@ static unsigned long get_next_ra_size(struct file_ra_state *ra,
+  * The fields in struct file_ra_state represent the most-recently-executed
+  * readahead attempt:
+  *
+- *                    |-------- last readahead window -------->|
+- *       |-- application walking here -->|
+- * ======#============|==================#=====================|
+- *       ^la_index    ^ra_index          ^lookahead_index      ^readahead_index
+- *
+- * [ra_index, readahead_index) represents the last readahead window.
+- *
+- * [la_index, lookahead_index] is where the application would be walking(in
+- * the common case of cache-cold sequential reads): the last window was
+- * established when the application was at la_index, and the next window will
+- * be bring in when the application reaches lookahead_index.
++ *                        |<----- async_size ---------|
++ *     |------------------- size -------------------->|
++ *     |==================#===========================|
++ *     ^start             ^page marked with PG_readahead
+  *
+  * To overlap application thinking time and disk I/O time, we do
+  * `readahead pipelining': Do not wait until the application consumed all
+  * readahead pages and stalled on the missing page at readahead_index;
+- * Instead, submit an asynchronous readahead I/O as early as the application
+- * reads on the page at lookahead_index. Normally lookahead_index will be
+- * equal to ra_index, for maximum pipelining.
++ * Instead, submit an asynchronous readahead I/O as soon as there are
++ * only async_size pages left in the readahead window. Normally async_size
++ * will be equal to size, for maximum pipelining.
+  *
+  * In interleaved sequential reads, concurrent streams on the same fd can
+  * be invalidating each other's readahead state. So we flag the new readahead
+- * page at lookahead_index with PG_readahead, and use it as readahead
++ * page at (start+size-async_size) with PG_readahead, and use it as readahead
+  * indicator. The flag won't be set on already cached pages, to avoid the
+  * readahead-for-nothing fuss, saving pointless page cache lookups.
+  *
+@@ -363,24 +351,21 @@ ondemand_readahead(struct address_space *mapping,
+ 		   unsigned long req_size)
+ {
+ 	unsigned long max;	/* max readahead pages */
+-	pgoff_t ra_index;	/* readahead index */
+-	unsigned long ra_size;	/* readahead size */
+-	unsigned long la_size;	/* lookahead size */
+ 	int sequential;
+ 
+ 	max = ra->ra_pages;
+ 	sequential = (offset - ra->prev_index <= 1UL) || (req_size > max);
+ 
+ 	/*
+-	 * Lookahead/readahead hit, assume sequential access.
++	 * It's the expected callback offset, assume sequential access.
+ 	 * Ramp up sizes, and push forward the readahead window.
+ 	 */
+-	if (offset && (offset == ra->lookahead_index ||
+-			offset == ra->readahead_index)) {
+-		ra_index = ra->readahead_index;
+-		ra_size = get_next_ra_size(ra, max);
+-		la_size = ra_size;
+-		goto fill_ra;
++	if (offset && (offset == (ra->start + ra->size - ra->async_size) ||
++			offset == (ra->start + ra->size))) {
++		ra->start += ra->size;
++		ra->size = get_next_ra_size(ra, max);
++		ra->async_size = ra->size;
++		goto readit;
+ 	}
+ 
+ 	/*
+@@ -399,24 +384,21 @@ ondemand_readahead(struct address_space *mapping,
+ 	 * 	- oversize random read
+ 	 * Start readahead for it.
+ 	 */
+-	ra_index = offset;
+-	ra_size = get_init_ra_size(req_size, max);
+-	la_size = ra_size > req_size ? ra_size - req_size : ra_size;
++	ra->start = offset;
++	ra->size = get_init_ra_size(req_size, max);
++	ra->async_size = ra->size > req_size ? ra->size - req_size : ra->size;
+ 
+ 	/*
+-	 * Hit on a lookahead page without valid readahead state.
++	 * Hit on a marked page without valid readahead state.
+ 	 * E.g. interleaved reads.
+ 	 * Not knowing its readahead pos/size, bet on the minimal possible one.
+ 	 */
+ 	if (hit_readahead_marker) {
+-		ra_index++;
+-		ra_size = min(4 * ra_size, max);
++		ra->start++;
++		ra->size = get_next_ra_size(ra, max);
+ 	}
+ 
+-fill_ra:
+-	ra_set_index(ra, offset, ra_index);
+-	ra_set_size(ra, ra_size, la_size);
+-
++readit:
+ 	return ra_submit(ra, mapping, filp);
+ }
+ 

commit fe3cba17c49471e99d3421e675fc8b3deaaf0b70
+Author: Fengguang Wu 
+Date:   Thu Jul 19 01:48:07 2007 -0700
+
+    mm: share PG_readahead and PG_reclaim
+    
+    Share the same page flag bit for PG_readahead and PG_reclaim.
+    
+    One is used only on file reads, another is only for emergency writes.  One
+    is used mostly for fresh/young pages, another is for old pages.
+    
+    Combinations of possible interactions are:
+    
+    a) clear PG_reclaim => implicit clear of PG_readahead
+            it will delay an asynchronous readahead into a synchronous one
+            it actually does _good_ for readahead:
+                    the pages will be reclaimed soon, it's readahead thrashing!
+                    in this case, synchronous readahead makes more sense.
+    
+    b) clear PG_readahead => implicit clear of PG_reclaim
+            one(and only one) page will not be reclaimed in time
+            it can be avoided by checking PageWriteback(page) in readahead first
+    
+    c) set PG_reclaim => implicit set of PG_readahead
+            will confuse readahead and make it restart the size rampup process
+            it's a trivial problem, and can mostly be avoided by checking
+            PageWriteback(page) first in readahead
+    
+    d) set PG_readahead => implicit set of PG_reclaim
+            PG_readahead will never be set on already cached pages.
+            PG_reclaim will always be cleared on dirtying a page.
+            so not a problem.
+    
+    In summary,
+            a)   we get better behavior
+            b,d) possible interactions can be avoided
+            c)   racy condition exists that might affect readahead, but the chance
+                 is _really_ low, and the hurt on readahead is trivial.
+    
+    Compound pages also use PG_reclaim, but for now they do not interact with
+    reclaim/readahead code.
+    
+    Signed-off-by: Fengguang Wu 
+    Cc: Rusty Russell 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
+index 709d92fd2877..a454176c3e30 100644
+--- a/include/linux/page-flags.h
++++ b/include/linux/page-flags.h
+@@ -83,7 +83,6 @@
+ #define PG_private		11	/* If pagecache, has fs-private data */
+ 
+ #define PG_writeback		12	/* Page is under writeback */
+-#define PG_readahead		13	/* Reminder to do async read-ahead */
+ #define PG_compound		14	/* Part of a compound page */
+ #define PG_swapcache		15	/* Swap page: swp_entry_t in private */
+ 
+@@ -91,6 +90,9 @@
+ #define PG_reclaim		17	/* To be reclaimed asap */
+ #define PG_buddy		19	/* Page is free, on buddy lists */
+ 
++/* PG_readahead is only used for file reads; PG_reclaim is only for writes */
++#define PG_readahead		PG_reclaim /* Reminder to do async read-ahead */
++
+ /* PG_owner_priv_1 users should have descriptive aliases */
+ #define PG_checked		PG_owner_priv_1 /* Used by some filesystems */
+ #define PG_pinned		PG_owner_priv_1	/* Xen pinned pagetable */
+diff --git a/mm/page-writeback.c b/mm/page-writeback.c
+index e62482718012..51b3eb6ab445 100644
+--- a/mm/page-writeback.c
++++ b/mm/page-writeback.c
+@@ -920,6 +920,7 @@ int clear_page_dirty_for_io(struct page *page)
+ 
+ 	BUG_ON(!PageLocked(page));
+ 
++	ClearPageReclaim(page);
+ 	if (mapping && mapping_cap_account_dirty(mapping)) {
+ 		/*
+ 		 * Yes, Virginia, this is indeed insane.
+diff --git a/mm/page_alloc.c b/mm/page_alloc.c
+index 2165be9462c0..43cb3b3e1679 100644
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -453,12 +453,6 @@ static inline int free_pages_check(struct page *page)
+ 			1 << PG_reserved |
+ 			1 << PG_buddy ))))
+ 		bad_page(page);
+-	/*
+-	 * PageReclaim == PageTail. It is only an error
+-	 * for PageReclaim to be set if PageCompound is clear.
+-	 */
+-	if (unlikely(!PageCompound(page) && PageReclaim(page)))
+-		bad_page(page);
+ 	if (PageDirty(page))
+ 		__ClearPageDirty(page);
+ 	/*
+@@ -602,7 +596,6 @@ static int prep_new_page(struct page *page, int order, gfp_t gfp_flags)
+ 			1 << PG_locked	|
+ 			1 << PG_active	|
+ 			1 << PG_dirty	|
+-			1 << PG_reclaim	|
+ 			1 << PG_slab    |
+ 			1 << PG_swapcache |
+ 			1 << PG_writeback |
+diff --git a/mm/readahead.c b/mm/readahead.c
+index 5b3c9b7d70fa..205a4a431516 100644
+--- a/mm/readahead.c
++++ b/mm/readahead.c
+@@ -448,6 +448,12 @@ page_cache_readahead_ondemand(struct address_space *mapping,
+ 		return 0;
+ 
+ 	if (page) {
++		/*
++		 * It can be PG_reclaim.
++		 */
++		if (PageWriteback(page))
++			return 0;
++
+ 		ClearPageReadahead(page);
+ 
+ 		/*

commit d8983910a4045fa21022cfccf76ed13eb40fd7f5
+Author: Fengguang Wu 
+Date:   Thu Jul 19 01:48:06 2007 -0700
+
+    readahead: pass real splice size
+    
+    Pass real splice size to page_cache_readahead_ondemand().
+    
+    The splice code works in chunks of 16 pages internally.  The readahead code
+    should be told of the overall splice size, instead of the internal chunk size.
+     Otherwize bad things may happen.  Imagine some 17-page random splice reads.
+    The code before this patch will result in two readahead calls: readahead(16);
+    readahead(1); That leads to one 16-page I/O and one 32-page I/O: one extra I/O
+    and 31 readahead miss pages.
+    
+    Signed-off-by: Fengguang Wu 
+    Cc: Jens Axboe 
+    Cc: Rusty Russell 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/splice.c b/fs/splice.c
+index 421b3b821152..6ddd0329f866 100644
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -265,7 +265,7 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
+ 			   unsigned int flags)
+ {
+ 	struct address_space *mapping = in->f_mapping;
+-	unsigned int loff, nr_pages;
++	unsigned int loff, nr_pages, req_pages;
+ 	struct page *pages[PIPE_BUFFERS];
+ 	struct partial_page partial[PIPE_BUFFERS];
+ 	struct page *page;
+@@ -281,10 +281,8 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
+ 
+ 	index = *ppos >> PAGE_CACHE_SHIFT;
+ 	loff = *ppos & ~PAGE_CACHE_MASK;
+-	nr_pages = (len + loff + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+-
+-	if (nr_pages > PIPE_BUFFERS)
+-		nr_pages = PIPE_BUFFERS;
++	req_pages = (len + loff + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
++	nr_pages = min(req_pages, (unsigned)PIPE_BUFFERS);
+ 
+ 	/*
+ 	 * Lookup the (hopefully) full range of pages we need.
+@@ -298,7 +296,7 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
+ 	 */
+ 	if (spd.nr_pages < nr_pages)
+ 		page_cache_readahead_ondemand(mapping, &in->f_ra, in,
+-				NULL, index, nr_pages - spd.nr_pages);
++				NULL, index, req_pages - spd.nr_pages);
+ 
+ 	error = 0;
+ 	while (spd.nr_pages < nr_pages) {
+@@ -355,7 +353,7 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
+ 
+ 		if (PageReadahead(page))
+ 			page_cache_readahead_ondemand(mapping, &in->f_ra, in,
+-					page, index, nr_pages - page_nr);
++					page, index, req_pages - page_nr);
+ 
+ 		/*
+ 		 * If the page isn't uptodate, we may need to start io on it

commit 431a4820bfcdf7ff530e745230bafb06c9bf2d6d
+Author: Fengguang Wu 
+Date:   Thu Jul 19 01:48:05 2007 -0700
+
+    readahead: move synchronous readahead call out of splice loop
+    
+    Move synchronous page_cache_readahead_ondemand() call out of splice loop.
+    
+    This avoids one pointless page allocation/insertion in case of non-zero
+    ra_pages, or many pointless readahead calls in case of zero ra_pages.
+    
+    Note that if a user sets ra_pages to less than PIPE_BUFFERS=16 pages, he will
+    not get expected readahead behavior anyway.  The splice code works in batches
+    of 16 pages, which can be taken as another form of synchronous readahead.
+    
+    Signed-off-by: Fengguang Wu 
+    Cc: Jens Axboe 
+    Cc: Rusty Russell 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/splice.c b/fs/splice.c
+index 722449f7d5d6..421b3b821152 100644
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -290,13 +290,17 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
+ 	 * Lookup the (hopefully) full range of pages we need.
+ 	 */
+ 	spd.nr_pages = find_get_pages_contig(mapping, index, nr_pages, pages);
++	index += spd.nr_pages;
+ 
+ 	/*
+ 	 * If find_get_pages_contig() returned fewer pages than we needed,
+-	 * allocate the rest and fill in the holes.
++	 * readahead/allocate the rest and fill in the holes.
+ 	 */
++	if (spd.nr_pages < nr_pages)
++		page_cache_readahead_ondemand(mapping, &in->f_ra, in,
++				NULL, index, nr_pages - spd.nr_pages);
++
+ 	error = 0;
+-	index += spd.nr_pages;
+ 	while (spd.nr_pages < nr_pages) {
+ 		/*
+ 		 * Page could be there, find_get_pages_contig() breaks on
+@@ -304,9 +308,6 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
+ 		 */
+ 		page = find_get_page(mapping, index);
+ 		if (!page) {
+-			page_cache_readahead_ondemand(mapping, &in->f_ra, in,
+-					NULL, index, nr_pages - spd.nr_pages);
+-
+ 			/*
+ 			 * page didn't exist, allocate one.
+ 			 */

commit c743d96b6d2ff55a94df7b5ac7c74987bb9c343b
+Author: Fengguang Wu 
+Date:   Thu Jul 19 01:48:04 2007 -0700
+
+    readahead: remove the old algorithm
+    
+    Remove the old readahead algorithm.
+    
+    Signed-off-by: Fengguang Wu 
+    Cc: Steven Pratt 
+    Cc: Ram Pai 
+    Cc: Rusty Russell 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 9a5f562abc77..29cb32d3a849 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -701,14 +701,6 @@ struct fown_struct {
+  *  file_ra_state.la_index    .ra_index   .lookahead_index   .readahead_index
+  */
+ struct file_ra_state {
+-	unsigned long start;		/* Current window */
+-	unsigned long size;
+-	unsigned long flags;		/* ra flags RA_FLAG_xxx*/
+-	unsigned long cache_hit;	/* cache hit count*/
+-	unsigned long prev_index;	/* Cache last read() position */
+-	unsigned long ahead_start;	/* Ahead window */
+-	unsigned long ahead_size;
+-
+ 	pgoff_t la_index;               /* enqueue time */
+ 	pgoff_t ra_index;               /* begin offset */
+ 	pgoff_t lookahead_index;        /* time to do next readahead */
+@@ -717,10 +709,9 @@ struct file_ra_state {
+ 	unsigned long ra_pages;		/* Maximum readahead window */
+ 	unsigned long mmap_hit;		/* Cache hit stat for mmap accesses */
+ 	unsigned long mmap_miss;	/* Cache miss stat for mmap accesses */
++	unsigned long prev_index;	/* Cache last read() position */
+ 	unsigned int prev_offset;	/* Offset where last read() ended in a page */
+ };
+-#define RA_FLAG_MISS 0x01	/* a cache miss occured against this file */
+-#define RA_FLAG_INCACHE 0x02	/* file is already in cache */
+ 
+ /*
+  * Measuring read-ahead sizes.
+diff --git a/include/linux/mm.h b/include/linux/mm.h
+index 619c0e80cf0c..3d0d7d285237 100644
+--- a/include/linux/mm.h
++++ b/include/linux/mm.h
+@@ -1144,13 +1144,6 @@ unsigned long page_cache_readahead_ondemand(struct address_space *mapping,
+ 			  struct page *page,
+ 			  pgoff_t offset,
+ 			  unsigned long size);
+-unsigned long page_cache_readahead(struct address_space *mapping,
+-			  struct file_ra_state *ra,
+-			  struct file *filp,
+-			  pgoff_t offset,
+-			  unsigned long size);
+-void handle_ra_miss(struct address_space *mapping, 
+-		    struct file_ra_state *ra, pgoff_t offset);
+ unsigned long max_sane_readahead(unsigned long nr);
+ 
+ /* Do stack extension */
+diff --git a/mm/readahead.c b/mm/readahead.c
+index c094e4f5a250..5b3c9b7d70fa 100644
+--- a/mm/readahead.c
++++ b/mm/readahead.c
+@@ -49,82 +49,6 @@ file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping)
+ }
+ EXPORT_SYMBOL_GPL(file_ra_state_init);
+ 
+-/*
+- * Return max readahead size for this inode in number-of-pages.
+- */
+-static inline unsigned long get_max_readahead(struct file_ra_state *ra)
+-{
+-	return ra->ra_pages;
+-}
+-
+-static inline unsigned long get_min_readahead(struct file_ra_state *ra)
+-{
+-	return MIN_RA_PAGES;
+-}
+-
+-static inline void reset_ahead_window(struct file_ra_state *ra)
+-{
+-	/*
+-	 * ... but preserve ahead_start + ahead_size value,
+-	 * see 'recheck:' label in page_cache_readahead().
+-	 * Note: We never use ->ahead_size as rvalue without
+-	 * checking ->ahead_start != 0 first.
+-	 */
+-	ra->ahead_size += ra->ahead_start;
+-	ra->ahead_start = 0;
+-}
+-
+-static inline void ra_off(struct file_ra_state *ra)
+-{
+-	ra->start = 0;
+-	ra->flags = 0;
+-	ra->size = 0;
+-	reset_ahead_window(ra);
+-	return;
+-}
+-
+-/*
+- * Set the initial window size, round to next power of 2 and square
+- * for small size, x 4 for medium, and x 2 for large
+- * for 128k (32 page) max ra
+- * 1-8 page = 32k initial, > 8 page = 128k initial
+- */
+-static unsigned long get_init_ra_size(unsigned long size, unsigned long max)
+-{
+-	unsigned long newsize = roundup_pow_of_two(size);
+-
+-	if (newsize <= max / 32)
+-		newsize = newsize * 4;
+-	else if (newsize <= max / 4)
+-		newsize = newsize * 2;
+-	else
+-		newsize = max;
+-	return newsize;
+-}
+-
+-/*
+- * Set the new window size, this is called only when I/O is to be submitted,
+- * not for each call to readahead.  If a cache miss occured, reduce next I/O
+- * size, else increase depending on how close to max we are.
+- */
+-static inline unsigned long get_next_ra_size(struct file_ra_state *ra)
+-{
+-	unsigned long max = get_max_readahead(ra);
+-	unsigned long min = get_min_readahead(ra);
+-	unsigned long cur = ra->size;
+-	unsigned long newsize;
+-
+-	if (ra->flags & RA_FLAG_MISS) {
+-		ra->flags &= ~RA_FLAG_MISS;
+-		newsize = max((cur - 2), min);
+-	} else if (cur < max / 16) {
+-		newsize = 4 * cur;
+-	} else {
+-		newsize = 2 * cur;
+-	}
+-	return min(newsize, max);
+-}
+-
+ #define list_to_page(head) (list_entry((head)->prev, struct page, lru))
+ 
+ /**
+@@ -200,66 +124,6 @@ static int read_pages(struct address_space *mapping, struct file *filp,
+ 	return ret;
+ }
+ 
+-/*
+- * Readahead design.
+- *
+- * The fields in struct file_ra_state represent the most-recently-executed
+- * readahead attempt:
+- *
+- * start:	Page index at which we started the readahead
+- * size:	Number of pages in that read
+- *              Together, these form the "current window".
+- *              Together, start and size represent the `readahead window'.
+- * prev_index:  The page which the readahead algorithm most-recently inspected.
+- *              It is mainly used to detect sequential file reading.
+- *              If page_cache_readahead sees that it is again being called for
+- *              a page which it just looked at, it can return immediately without
+- *              making any state changes.
+- * offset:      Offset in the prev_index where the last read ended - used for
+- *              detection of sequential file reading.
+- * ahead_start,
+- * ahead_size:  Together, these form the "ahead window".
+- * ra_pages:	The externally controlled max readahead for this fd.
+- *
+- * When readahead is in the off state (size == 0), readahead is disabled.
+- * In this state, prev_index is used to detect the resumption of sequential I/O.
+- *
+- * The readahead code manages two windows - the "current" and the "ahead"
+- * windows.  The intent is that while the application is walking the pages
+- * in the current window, I/O is underway on the ahead window.  When the
+- * current window is fully traversed, it is replaced by the ahead window
+- * and the ahead window is invalidated.  When this copying happens, the
+- * new current window's pages are probably still locked.  So
+- * we submit a new batch of I/O immediately, creating a new ahead window.
+- *
+- * So:
+- *
+- *   ----|----------------|----------------|-----
+- *       ^start           ^start+size
+- *                        ^ahead_start     ^ahead_start+ahead_size
+- *
+- *         ^ When this page is read, we submit I/O for the
+- *           ahead window.
+- *
+- * A `readahead hit' occurs when a read request is made against a page which is
+- * the next sequential page. Ahead window calculations are done only when it
+- * is time to submit a new IO.  The code ramps up the size agressively at first,
+- * but slow down as it approaches max_readhead.
+- *
+- * Any seek/ramdom IO will result in readahead being turned off.  It will resume
+- * at the first sequential access.
+- *
+- * There is a special-case: if the first page which the application tries to
+- * read happens to be the first page of the file, it is assumed that a linear
+- * read is about to happen and the window is immediately set to the initial size
+- * based on I/O request size and the max_readahead.
+- *
+- * This function is to be called for every read request, rather than when
+- * it is time to perform readahead.  It is called only once for the entire I/O
+- * regardless of size unless readahead is unable to start enough I/O to satisfy
+- * the request (I/O request > max_readahead).
+- */
+-
+ /*
+  * do_page_cache_readahead actually reads a chunk of disk.  It allocates all
+  * the pages first, then submits them all for I/O. This avoids the very bad
+@@ -295,7 +159,7 @@ __do_page_cache_readahead(struct address_space *mapping, struct file *filp,
+ 	read_lock_irq(&mapping->tree_lock);
+ 	for (page_idx = 0; page_idx < nr_to_read; page_idx++) {
+ 		pgoff_t page_offset = offset + page_idx;
+-		
++
+ 		if (page_offset > end_index)
+ 			break;
+ 
+@@ -360,28 +224,6 @@ int force_page_cache_readahead(struct address_space *mapping, struct file *filp,
+ 	return ret;
+ }
+ 
+-/*
+- * Check how effective readahead is being.  If the amount of started IO is
+- * less than expected then the file is partly or fully in pagecache and
+- * readahead isn't helping.
+- *
+- */
+-static inline int check_ra_success(struct file_ra_state *ra,
+-			unsigned long nr_to_read, unsigned long actual)
+-{
+-	if (actual == 0) {
+-		ra->cache_hit += nr_to_read;
+-		if (ra->cache_hit >= VM_MAX_CACHE_HIT) {
+-			ra_off(ra);
+-			ra->flags |= RA_FLAG_INCACHE;
+-			return 0;
+-		}
+-	} else {
+-		ra->cache_hit=0;
+-	}
+-	return 1;
+-}
+-
+ /*
+  * This version skips the IO if the queue is read-congested, and will tell the
+  * block layer to abandon the readahead if request allocation would block.
+@@ -398,191 +240,6 @@ int do_page_cache_readahead(struct address_space *mapping, struct file *filp,
+ 	return __do_page_cache_readahead(mapping, filp, offset, nr_to_read, 0);
+ }
+ 
+-/*
+- * Read 'nr_to_read' pages starting at page 'offset'. If the flag 'block'
+- * is set wait till the read completes.  Otherwise attempt to read without
+- * blocking.
+- * Returns 1 meaning 'success' if read is successful without switching off
+- * readahead mode. Otherwise return failure.
+- */
+-static int
+-blockable_page_cache_readahead(struct address_space *mapping, struct file *filp,
+-			pgoff_t offset, unsigned long nr_to_read,
+-			struct file_ra_state *ra, int block)
+-{
+-	int actual;
+-
+-	if (!block && bdi_read_congested(mapping->backing_dev_info))
+-		return 0;
+-
+-	actual = __do_page_cache_readahead(mapping, filp, offset, nr_to_read, 0);
+-
+-	return check_ra_success(ra, nr_to_read, actual);
+-}
+-
+-static int make_ahead_window(struct address_space *mapping, struct file *filp,
+-				struct file_ra_state *ra, int force)
+-{
+-	int block, ret;
+-
+-	ra->ahead_size = get_next_ra_size(ra);
+-	ra->ahead_start = ra->start + ra->size;
+-
+-	block = force || (ra->prev_index >= ra->ahead_start);
+-	ret = blockable_page_cache_readahead(mapping, filp,
+-			ra->ahead_start, ra->ahead_size, ra, block);
+-
+-	if (!ret && !force) {
+-		/* A read failure in blocking mode, implies pages are
+-		 * all cached. So we can safely assume we have taken
+-		 * care of all the pages requested in this call.
+-		 * A read failure in non-blocking mode, implies we are
+-		 * reading more pages than requested in this call.  So
+-		 * we safely assume we have taken care of all the pages
+-		 * requested in this call.
+-		 *
+-		 * Just reset the ahead window in case we failed due to
+-		 * congestion.  The ahead window will any way be closed
+-		 * in case we failed due to excessive page cache hits.
+-		 */
+-		reset_ahead_window(ra);
+-	}
+-
+-	return ret;
+-}
+-
+-/**
+- * page_cache_readahead - generic adaptive readahead
+- * @mapping: address_space which holds the pagecache and I/O vectors
+- * @ra: file_ra_state which holds the readahead state
+- * @filp: passed on to ->readpage() and ->readpages()
+- * @offset: start offset into @mapping, in PAGE_CACHE_SIZE units
+- * @req_size: hint: total size of the read which the caller is performing in
+- *            PAGE_CACHE_SIZE units
+- *
+- * page_cache_readahead() is the main function.  It performs the adaptive
+- * readahead window size management and submits the readahead I/O.
+- *
+- * Note that @filp is purely used for passing on to the ->readpage[s]()
+- * handler: it may refer to a different file from @mapping (so we may not use
+- * @filp->f_mapping or @filp->f_path.dentry->d_inode here).
+- * Also, @ra may not be equal to &@filp->f_ra.
+- *
+- */
+-unsigned long
+-page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra,
+-		     struct file *filp, pgoff_t offset, unsigned long req_size)
+-{
+-	unsigned long max, newsize;
+-	int sequential;
+-
+-	/*
+-	 * We avoid doing extra work and bogusly perturbing the readahead
+-	 * window expansion logic.
+-	 */
+-	if (offset == ra->prev_index && --req_size)
+-		++offset;
+-
+-	/* Note that prev_index == -1 if it is a first read */
+-	sequential = (offset == ra->prev_index + 1);
+-	ra->prev_index = offset;
+-	ra->prev_offset = 0;
+-
+-	max = get_max_readahead(ra);
+-	newsize = min(req_size, max);
+-
+-	/* No readahead or sub-page sized read or file already in cache */
+-	if (newsize == 0 || (ra->flags & RA_FLAG_INCACHE))
+-		goto out;
+-
+-	ra->prev_index += newsize - 1;
+-
+-	/*
+-	 * Special case - first read at start of file. We'll assume it's
+-	 * a whole-file read and grow the window fast.  Or detect first
+-	 * sequential access
+-	 */
+-	if (sequential && ra->size == 0) {
+-		ra->size = get_init_ra_size(newsize, max);
+-		ra->start = offset;
+-		if (!blockable_page_cache_readahead(mapping, filp, offset,
+-							 ra->size, ra, 1))
+-			goto out;
+-
+-		/*
+-		 * If the request size is larger than our max readahead, we
+-		 * at least want to be sure that we get 2 IOs in flight and
+-		 * we know that we will definitly need the new I/O.
+-		 * once we do this, subsequent calls should be able to overlap
+-		 * IOs,* thus preventing stalls. so issue the ahead window
+-		 * immediately.
+-		 */
+-		if (req_size >= max)
+-			make_ahead_window(mapping, filp, ra, 1);
+-
+-		goto out;
+-	}
+-
+-	/*
+-	 * Now handle the random case:
+-	 * partial page reads and first access were handled above,
+-	 * so this must be the next page otherwise it is random
+-	 */
+-	if (!sequential) {
+-		ra_off(ra);
+-		blockable_page_cache_readahead(mapping, filp, offset,
+-				 newsize, ra, 1);
+-		goto out;
+-	}
+-
+-	/*
+-	 * If we get here we are doing sequential IO and this was not the first
+-	 * occurence (ie we have an existing window)
+-	 */
+-	if (ra->ahead_start == 0) {	 /* no ahead window yet */
+-		if (!make_ahead_window(mapping, filp, ra, 0))
+-			goto recheck;
+-	}
+-
+-	/*
+-	 * Already have an ahead window, check if we crossed into it.
+-	 * If so, shift windows and issue a new ahead window.
+-	 * Only return the #pages that are in the current window, so that
+-	 * we get called back on the first page of the ahead window which
+-	 * will allow us to submit more IO.
+-	 */
+-	if (ra->prev_index >= ra->ahead_start) {
+-		ra->start = ra->ahead_start;
+-		ra->size = ra->ahead_size;
+-		make_ahead_window(mapping, filp, ra, 0);
+-recheck:
+-		/* prev_index shouldn't overrun the ahead window */
+-		ra->prev_index = min(ra->prev_index,
+-			ra->ahead_start + ra->ahead_size - 1);
+-	}
+-
+-out:
+-	return ra->prev_index + 1;
+-}
+-EXPORT_SYMBOL_GPL(page_cache_readahead);
+-
+-/*
+- * handle_ra_miss() is called when it is known that a page which should have
+- * been present in the pagecache (we just did some readahead there) was in fact
+- * not found.  This will happen if it was evicted by the VM (readahead
+- * thrashing)
+- *
+- * Turn on the cache miss flag in the RA struct, this will cause the RA code
+- * to reduce the RA size on the next read.
+- */
+-void handle_ra_miss(struct address_space *mapping,
+-		struct file_ra_state *ra, pgoff_t offset)
+-{
+-	ra->flags |= RA_FLAG_MISS;
+-	ra->flags &= ~RA_FLAG_INCACHE;
+-	ra->cache_hit = 0;
+-}
+-
+ /*
+  * Given a desired number of PAGE_CACHE_SIZE readahead pages, return a
+  * sensible upper limit.
+@@ -612,20 +269,40 @@ unsigned long ra_submit(struct file_ra_state *ra,
+ }
+ EXPORT_SYMBOL_GPL(ra_submit);
+ 
++/*
++ * Set the initial window size, round to next power of 2 and square
++ * for small size, x 4 for medium, and x 2 for large
++ * for 128k (32 page) max ra
++ * 1-8 page = 32k initial, > 8 page = 128k initial
++ */
++static unsigned long get_init_ra_size(unsigned long size, unsigned long max)
++{
++	unsigned long newsize = roundup_pow_of_two(size);
++
++	if (newsize <= max / 32)
++		newsize = newsize * 4;
++	else if (newsize <= max / 4)
++		newsize = newsize * 2;
++	else
++		newsize = max;
++
++	return newsize;
++}
++
+ /*
+  *  Get the previous window size, ramp it up, and
+  *  return it as the new window size.
+  */
+-static unsigned long get_next_ra_size2(struct file_ra_state *ra,
++static unsigned long get_next_ra_size(struct file_ra_state *ra,
+ 						unsigned long max)
+ {
+ 	unsigned long cur = ra->readahead_index - ra->ra_index;
+ 	unsigned long newsize;
+ 
+ 	if (cur < max / 16)
+-		newsize = cur * 4;
++		newsize = 4 * cur;
+ 	else
+-		newsize = cur * 2;
++		newsize = 2 * cur;
+ 
+ 	return min(newsize, max);
+ }
+@@ -701,7 +378,7 @@ ondemand_readahead(struct address_space *mapping,
+ 	if (offset && (offset == ra->lookahead_index ||
+ 			offset == ra->readahead_index)) {
+ 		ra_index = ra->readahead_index;
+-		ra_size = get_next_ra_size2(ra, max);
++		ra_size = get_next_ra_size(ra, max);
+ 		la_size = ra_size;
+ 		goto fill_ra;
+ 	}

commit dc7868fcb9a73990e6f30371c1be465c436a7a7f
+Author: Fengguang Wu 
+Date:   Thu Jul 19 01:48:04 2007 -0700
+
+    readahead: convert ext3/ext4 invocations
+    
+    Convert ext3/ext4 dir reads to use on-demand readahead.
+    
+    Readahead for dirs operates _not_ on file level, but on blockdev level.  This
+    makes a difference when the data blocks are not continuous.  And the read
+    routine is somehow opaque: there's no handy info about the status of current
+    page.  So a simplified call scheme is employed: to call into readahead
+    whenever the current page falls out of readahead windows.
+    
+    Signed-off-by: Fengguang Wu 
+    Cc: Steven Pratt 
+    Cc: Ram Pai 
+    Cc: Rusty Russell 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c
+index 852869840f24..3c6d384a2c66 100644
+--- a/fs/ext3/dir.c
++++ b/fs/ext3/dir.c
+@@ -136,12 +136,14 @@ static int ext3_readdir(struct file * filp,
+ 		err = ext3_get_blocks_handle(NULL, inode, blk, 1,
+ 						&map_bh, 0, 0);
+ 		if (err > 0) {
+-			page_cache_readahead(sb->s_bdev->bd_inode->i_mapping,
+-				&filp->f_ra,
+-				filp,
+-				map_bh.b_blocknr >>
+-					(PAGE_CACHE_SHIFT - inode->i_blkbits),
+-				1);
++			pgoff_t index = map_bh.b_blocknr >>
++					(PAGE_CACHE_SHIFT - inode->i_blkbits);
++			if (!ra_has_index(&filp->f_ra, index))
++				page_cache_readahead_ondemand(
++					sb->s_bdev->bd_inode->i_mapping,
++					&filp->f_ra, filp,
++					NULL, index, 1);
++			filp->f_ra.prev_index = index;
+ 			bh = ext3_bread(NULL, inode, blk, 0, &err);
+ 		}
+ 
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index e8ad06e28318..0a872a09fed8 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -135,12 +135,14 @@ static int ext4_readdir(struct file * filp,
+ 		map_bh.b_state = 0;
+ 		err = ext4_get_blocks_wrap(NULL, inode, blk, 1, &map_bh, 0, 0);
+ 		if (err > 0) {
+-			page_cache_readahead(sb->s_bdev->bd_inode->i_mapping,
+-				&filp->f_ra,
+-				filp,
+-				map_bh.b_blocknr >>
+-					(PAGE_CACHE_SHIFT - inode->i_blkbits),
+-				1);
++			pgoff_t index = map_bh.b_blocknr >>
++					(PAGE_CACHE_SHIFT - inode->i_blkbits);
++			if (!ra_has_index(&filp->f_ra, index))
++				page_cache_readahead_ondemand(
++					sb->s_bdev->bd_inode->i_mapping,
++					&filp->f_ra, filp,
++					NULL, index, 1);
++			filp->f_ra.prev_index = index;
+ 			bh = ext4_bread(NULL, inode, blk, 0, &err);
+ 		}
+ 

commit a08a166fe77d9f9ad88ed6d06b97e73453661f89
+Author: Fengguang Wu 
+Date:   Thu Jul 19 01:48:03 2007 -0700
+
+    readahead: convert splice invocations
+    
+    Convert splice reads to use on-demand readahead.
+    
+    Signed-off-by: Fengguang Wu 
+    Cc: Steven Pratt 
+    Cc: Ram Pai 
+    Cc: Jens Axboe 
+    Cc: Rusty Russell 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/splice.c b/fs/splice.c
+index 53fc2082a468..722449f7d5d6 100644
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -286,12 +286,6 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
+ 	if (nr_pages > PIPE_BUFFERS)
+ 		nr_pages = PIPE_BUFFERS;
+ 
+-	/*
+-	 * Don't try to 2nd guess the read-ahead logic, call into
+-	 * page_cache_readahead() like the page cache reads would do.
+-	 */
+-	page_cache_readahead(mapping, &in->f_ra, in, index, nr_pages);
+-
+ 	/*
+ 	 * Lookup the (hopefully) full range of pages we need.
+ 	 */
+@@ -310,11 +304,8 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
+ 		 */
+ 		page = find_get_page(mapping, index);
+ 		if (!page) {
+-			/*
+-			 * Make sure the read-ahead engine is notified
+-			 * about this failure.
+-			 */
+-			handle_ra_miss(mapping, &in->f_ra, index);
++			page_cache_readahead_ondemand(mapping, &in->f_ra, in,
++					NULL, index, nr_pages - spd.nr_pages);
+ 
+ 			/*
+ 			 * page didn't exist, allocate one.
+@@ -361,6 +352,10 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
+ 		this_len = min_t(unsigned long, len, PAGE_CACHE_SIZE - loff);
+ 		page = pages[page_nr];
+ 
++		if (PageReadahead(page))
++			page_cache_readahead_ondemand(mapping, &in->f_ra, in,
++					page, index, nr_pages - page_nr);
++
+ 		/*
+ 		 * If the page isn't uptodate, we may need to start io on it
+ 		 */
+@@ -453,6 +448,7 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
+ 	 */
+ 	while (page_nr < nr_pages)
+ 		page_cache_release(pages[page_nr++]);
++	in->f_ra.prev_index = index;
+ 
+ 	if (spd.nr_pages)
+ 		return splice_to_pipe(pipe, &spd);

commit 3ea89ee86a82e9fbde37018d9b9e92a552e5fd13
+Author: Fengguang Wu 
+Date:   Thu Jul 19 01:48:02 2007 -0700
+
+    readahead: convert filemap invocations
+    
+    Convert filemap reads to use on-demand readahead.
+    
+    The new call scheme is to
+    - call readahead on non-cached page
+    - call readahead on look-ahead page
+    - update prev_index when finished with the read request
+    
+    Signed-off-by: Fengguang Wu 
+    Cc: Steven Pratt 
+    Cc: Ram Pai 
+    Cc: Rusty Russell 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/mm/filemap.c b/mm/filemap.c
+index 4fd9e3f0f48a..5eb0a6b9d607 100644
+--- a/mm/filemap.c
++++ b/mm/filemap.c
+@@ -891,15 +891,20 @@ void do_generic_mapping_read(struct address_space *mapping,
+ 		unsigned long nr, ret;
+ 
+ 		cond_resched();
+-		if (index == next_index)
+-			next_index = page_cache_readahead(mapping, &ra, filp,
+-					index, last_index - index);
+-
+ find_page:
+ 		page = find_get_page(mapping, index);
+-		if (unlikely(page == NULL)) {
+-			handle_ra_miss(mapping, &ra, index);
+-			goto no_cached_page;
++		if (!page) {
++			page_cache_readahead_ondemand(mapping,
++					&ra, filp, page,
++					index, last_index - index);
++			page = find_get_page(mapping, index);
++			if (unlikely(page == NULL))
++				goto no_cached_page;
++		}
++		if (PageReadahead(page)) {
++			page_cache_readahead_ondemand(mapping,
++					&ra, filp, page,
++					index, last_index - index);
+ 		}
+ 		if (!PageUptodate(page))
+ 			goto page_not_up_to_date;
+@@ -1051,6 +1056,7 @@ void do_generic_mapping_read(struct address_space *mapping,
+ 
+ out:
+ 	*_ra = ra;
++	_ra->prev_index = prev_index;
+ 
+ 	*ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
+ 	if (cached_page)
+@@ -1332,27 +1338,31 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+ 	if (VM_RandomReadHint(vma))
+ 		goto no_cached_page;
+ 
+-	/*
+-	 * The readahead code wants to be told about each and every page
+-	 * so it can build and shrink its windows appropriately
+-	 *
+-	 * For sequential accesses, we use the generic readahead logic.
+-	 */
+-	if (VM_SequentialReadHint(vma))
+-		page_cache_readahead(mapping, ra, file, vmf->pgoff, 1);
+-
+ 	/*
+ 	 * Do we have something in the page cache already?
+ 	 */
+ retry_find:
+ 	page = find_lock_page(mapping, vmf->pgoff);
++	/*
++	 * For sequential accesses, we use the generic readahead logic.
++	 */
++	if (VM_SequentialReadHint(vma)) {
++		if (!page) {
++			page_cache_readahead_ondemand(mapping, ra, file, page,
++							   vmf->pgoff, 1);
++			page = find_lock_page(mapping, vmf->pgoff);
++			if (!page)
++				goto no_cached_page;
++		}
++		if (PageReadahead(page)) {
++			page_cache_readahead_ondemand(mapping, ra, file, page,
++							   vmf->pgoff, 1);
++		}
++	}
++
+ 	if (!page) {
+ 		unsigned long ra_pages;
+ 
+-		if (VM_SequentialReadHint(vma)) {
+-			handle_ra_miss(mapping, ra, vmf->pgoff);
+-			goto no_cached_page;
+-		}
+ 		ra->mmap_miss++;
+ 
+ 		/*
+@@ -1405,6 +1415,7 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+ 	 * Found the page and have a reference on it.
+ 	 */
+ 	mark_page_accessed(page);
++	ra->prev_index = page->index;
+ 	vmf->page = page;
+ 	return ret | VM_FAULT_LOCKED;
+ 

commit 122a21d11cbfda6d1e33cbc8ae9e4c4ee2f1886e
+Author: Fengguang Wu 
+Date:   Thu Jul 19 01:48:01 2007 -0700
+
+    readahead: on-demand readahead logic
+    
+    This is a minimal readahead algorithm that aims to replace the current one.
+    It is more flexible and reliable, while maintaining almost the same behavior
+    and performance.  Also it is full integrated with adaptive readahead.
+    
+    It is designed to be called on demand:
+            - on a missing page, to do synchronous readahead
+            - on a lookahead page, to do asynchronous readahead
+    
+    In this way it eliminated the awkward workarounds for cache hit/miss,
+    readahead thrashing, retried read, and unaligned read.  It also adopts the
+    data structure introduced by adaptive readahead, parameterizes readahead
+    pipelining with `lookahead_index', and reduces the current/ahead windows to
+    one single window.
+    
+    HEURISTICS
+    
+    The logic deals with four cases:
+    
+            - sequential-next
+                    found a consistent readahead window, so push it forward
+    
+            - random
+                    standalone small read, so read as is
+    
+            - sequential-first
+                    create a new readahead window for a sequential/oversize request
+    
+            - lookahead-clueless
+                    hit a lookahead page not associated with the readahead window,
+                    so create a new readahead window and ramp it up
+    
+    In each case, three parameters are determined:
+    
+            - readahead index: where the next readahead begins
+            - readahead size:  how much to readahead
+            - lookahead size:  when to do the next readahead (for pipelining)
+    
+    BEHAVIORS
+    
+    The old behaviors are maximally preserved for trivial sequential/random reads.
+    Notable changes are:
+    
+            - It no longer imposes strict sequential checks.
+              It might help some interleaved cases, and clustered random reads.
+              It does introduce risks of a random lookahead hit triggering an
+              unexpected readahead. But in general it is more likely to do good
+              than to do evil.
+    
+            - Interleaved reads are supported in a minimal way.
+              Their chances of being detected and proper handled are still low.
+    
+            - Readahead thrashings are better handled.
+              The current readahead leads to tiny average I/O sizes, because it
+              never turn back for the thrashed pages.  They have to be fault in
+              by do_generic_mapping_read() one by one.  Whereas the on-demand
+              readahead will redo readahead for them.
+    
+    OVERHEADS
+    
+    The new code reduced the overheads of
+    
+            - excessively calling the readahead routine on small sized reads
+              (the current readahead code insists on seeing all requests)
+    
+            - doing a lot of pointless page-cache lookups for small cached files
+              (the current readahead only turns itself off after 256 cache hits,
+              unfortunately most files are < 1MB, so never see that chance)
+    
+    That accounts for speedup of
+            - 0.3% on 1-page sequential reads on sparse file
+            - 1.2% on 1-page cache hot sequential reads
+            - 3.2% on 256-page cache hot sequential reads
+            - 1.3% on cache hot `tar /lib`
+    
+    However, it does introduce one extra page-cache lookup per cache miss, which
+    impacts random reads slightly. That's 1% overheads for 1-page random reads on
+    sparse file.
+    
+    PERFORMANCE
+    
+    The basic benchmark setup is
+            - 2.6.20 kernel with on-demand readahead
+            - 1MB max readahead size
+            - 2.9GHz Intel Core 2 CPU
+            - 2GB memory
+            - 160G/8M Hitachi SATA II 7200 RPM disk
+    
+    The benchmarks show that
+            - it maintains the same performance for trivial sequential/random reads
+            - sysbench/OLTP performance on MySQL gains up to 8%
+            - performance on readahead thrashing gains up to 3 times
+    
+    iozone throughput (KB/s): roughly the same
+    ==========================================
+    iozone -c -t1 -s 4096m -r 64k
+    
+                                   2.6.20          on-demand      gain
+    first run
+              "  Initial write "   61437.27        64521.53      +5.0%
+              "        Rewrite "   47893.02        48335.20      +0.9%
+              "           Read "   62111.84        62141.49      +0.0%
+              "        Re-read "   62242.66        62193.17      -0.1%
+              "   Reverse Read "   50031.46        49989.79      -0.1%
+              "    Stride read "    8657.61         8652.81      -0.1%
+              "    Random read "   13914.28        13898.23      -0.1%
+              " Mixed workload "   19069.27        19033.32      -0.2%
+              "   Random write "   14849.80        14104.38      -5.0%
+              "         Pwrite "   62955.30        65701.57      +4.4%
+              "          Pread "   62209.99        62256.26      +0.1%
+    
+    second run
+              "  Initial write "   60810.31        66258.69      +9.0%
+              "        Rewrite "   49373.89        57833.66     +17.1%
+              "           Read "   62059.39        62251.28      +0.3%
+              "        Re-read "   62264.32        62256.82      -0.0%
+              "   Reverse Read "   49970.96        50565.72      +1.2%
+              "    Stride read "    8654.81         8638.45      -0.2%
+              "    Random read "   13901.44        13949.91      +0.3%
+              " Mixed workload "   19041.32        19092.04      +0.3%
+              "   Random write "   14019.99        14161.72      +1.0%
+              "         Pwrite "   64121.67        68224.17      +6.4%
+              "          Pread "   62225.08        62274.28      +0.1%
+    
+    In summary, writes are unstable, reads are pretty close on average:
+    
+                              access pattern  2.6.20  on-demand   gain
+                                       Read  62085.61  62196.38  +0.2%
+                                    Re-read  62253.49  62224.99  -0.0%
+                               Reverse Read  50001.21  50277.75  +0.6%
+                                Stride read   8656.21   8645.63  -0.1%
+                                Random read  13907.86  13924.07  +0.1%
+                             Mixed workload  19055.29  19062.68  +0.0%
+                                      Pread  62217.53  62265.27  +0.1%
+    
+    aio-stress: roughly the same
+    ============================
+    aio-stress -l -s4096 -r128 -t1 -o1 knoppix511-dvd-cn.iso
+    aio-stress -l -s4096 -r128 -t1 -o3 knoppix511-dvd-cn.iso
+    
+                                            2.6.20      on-demand  delta
+                            sequential       92.57s      92.54s    -0.0%
+                            random          311.87s     312.15s    +0.1%
+    
+    sysbench fileio: roughly the same
+    =================================
+    sysbench --test=fileio --file-io-mode=async --file-test-mode=rndrw \
+             --file-total-size=4G --file-block-size=64K \
+             --num-threads=001 --max-requests=10000 --max-time=900 run
+    
+                                    threads    2.6.20   on-demand    delta
+                    first run
+                                          1   59.1974s    59.2262s  +0.0%
+                                          2   58.0575s    58.2269s  +0.3%
+                                          4   48.0545s    47.1164s  -2.0%
+                                          8   41.0684s    41.2229s  +0.4%
+                                         16   35.8817s    36.4448s  +1.6%
+                                         32   32.6614s    32.8240s  +0.5%
+                                         64   23.7601s    24.1481s  +1.6%
+                                        128   24.3719s    23.8225s  -2.3%
+                                        256   23.2366s    22.0488s  -5.1%
+    
+                    second run
+                                          1   59.6720s    59.5671s  -0.2%
+                                          8   41.5158s    41.9541s  +1.1%
+                                         64   25.0200s    23.9634s  -4.2%
+                                        256   22.5491s    20.9486s  -7.1%
+    
+    Note that the numbers are not very stable because of the writes.
+    The overall performance is close when we sum all seconds up:
+    
+                    sum all up               495.046s    491.514s   -0.7%
+    
+    sysbench oltp (trans/sec): up to 8% gain
+    ========================================
+    sysbench --test=oltp --oltp-table-size=10000000 --oltp-read-only \
+             --mysql-socket=/var/run/mysqld/mysqld.sock \
+             --mysql-user=root --mysql-password=readahead \
+             --num-threads=064 --max-requests=10000 --max-time=900 run
+    
+            10000-transactions run
+                                    threads    2.6.20   on-demand    gain
+                                          1     62.81       64.56   +2.8%
+                                          2     67.97       70.93   +4.4%
+                                          4     81.81       85.87   +5.0%
+                                          8     94.60       97.89   +3.5%
+                                         16     99.07      104.68   +5.7%
+                                         32     95.93      104.28   +8.7%
+                                         64     96.48      103.68   +7.5%
+            5000-transactions run
+                                          1     48.21       48.65   +0.9%
+                                          8     68.60       70.19   +2.3%
+                                         64     70.57       74.72   +5.9%
+            2000-transactions run
+                                          1     37.57       38.04   +1.3%
+                                          2     38.43       38.99   +1.5%
+                                          4     45.39       46.45   +2.3%
+                                          8     51.64       52.36   +1.4%
+                                         16     54.39       55.18   +1.5%
+                                         32     52.13       54.49   +4.5%
+                                         64     54.13       54.61   +0.9%
+    
+    That's interesting results. Some investigations show that
+            - MySQL is accessing the db file non-uniformly: some parts are
+              more hot than others
+            - It is mostly doing 4-page random reads, and sometimes doing two
+              reads in a row, the latter one triggers a 16-page readahead.
+            - The on-demand readahead leaves many lookahead pages (flagged
+              PG_readahead) there. Many of them will be hit, and trigger
+              more readahead pages. Which might save more seeks.
+            - Naturally, the readahead windows tend to lie in hot areas,
+              and the lookahead pages in hot areas is more likely to be hit.
+            - The more overall read density, the more possible gain.
+    
+    That also explains the adaptive readahead tricks for clustered random reads.
+    
+    readahead thrashing: 3 times better
+    ===================================
+    We boot kernel with "mem=128m single", and start a 100KB/s stream on every
+    second, until reaching 200 streams.
+    
+                                  max throughput     min avg I/O size
+                    2.6.20:            5MB/s               16KB
+                    on-demand:        15MB/s              140KB
+    
+    Signed-off-by: Fengguang Wu 
+    Cc: Steven Pratt 
+    Cc: Ram Pai 
+    Cc: Rusty Russell 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/mm.h b/include/linux/mm.h
+index f8e12b3b6110..619c0e80cf0c 100644
+--- a/include/linux/mm.h
++++ b/include/linux/mm.h
+@@ -1138,6 +1138,12 @@ int do_page_cache_readahead(struct address_space *mapping, struct file *filp,
+ 			pgoff_t offset, unsigned long nr_to_read);
+ int force_page_cache_readahead(struct address_space *mapping, struct file *filp,
+ 			pgoff_t offset, unsigned long nr_to_read);
++unsigned long page_cache_readahead_ondemand(struct address_space *mapping,
++			  struct file_ra_state *ra,
++			  struct file *filp,
++			  struct page *page,
++			  pgoff_t offset,
++			  unsigned long size);
+ unsigned long page_cache_readahead(struct address_space *mapping,
+ 			  struct file_ra_state *ra,
+ 			  struct file *filp,
+diff --git a/mm/readahead.c b/mm/readahead.c
+index 072ce8f8357d..c094e4f5a250 100644
+--- a/mm/readahead.c
++++ b/mm/readahead.c
+@@ -611,3 +611,177 @@ unsigned long ra_submit(struct file_ra_state *ra,
+ 	return actual;
+ }
+ EXPORT_SYMBOL_GPL(ra_submit);
++
++/*
++ *  Get the previous window size, ramp it up, and
++ *  return it as the new window size.
++ */
++static unsigned long get_next_ra_size2(struct file_ra_state *ra,
++						unsigned long max)
++{
++	unsigned long cur = ra->readahead_index - ra->ra_index;
++	unsigned long newsize;
++
++	if (cur < max / 16)
++		newsize = cur * 4;
++	else
++		newsize = cur * 2;
++
++	return min(newsize, max);
++}
++
++/*
++ * On-demand readahead design.
++ *
++ * The fields in struct file_ra_state represent the most-recently-executed
++ * readahead attempt:
++ *
++ *                    |-------- last readahead window -------->|
++ *       |-- application walking here -->|
++ * ======#============|==================#=====================|
++ *       ^la_index    ^ra_index          ^lookahead_index      ^readahead_index
++ *
++ * [ra_index, readahead_index) represents the last readahead window.
++ *
++ * [la_index, lookahead_index] is where the application would be walking(in
++ * the common case of cache-cold sequential reads): the last window was
++ * established when the application was at la_index, and the next window will
++ * be bring in when the application reaches lookahead_index.
++ *
++ * To overlap application thinking time and disk I/O time, we do
++ * `readahead pipelining': Do not wait until the application consumed all
++ * readahead pages and stalled on the missing page at readahead_index;
++ * Instead, submit an asynchronous readahead I/O as early as the application
++ * reads on the page at lookahead_index. Normally lookahead_index will be
++ * equal to ra_index, for maximum pipelining.
++ *
++ * In interleaved sequential reads, concurrent streams on the same fd can
++ * be invalidating each other's readahead state. So we flag the new readahead
++ * page at lookahead_index with PG_readahead, and use it as readahead
++ * indicator. The flag won't be set on already cached pages, to avoid the
++ * readahead-for-nothing fuss, saving pointless page cache lookups.
++ *
++ * prev_index tracks the last visited page in the _previous_ read request.
++ * It should be maintained by the caller, and will be used for detecting
++ * small random reads. Note that the readahead algorithm checks loosely
++ * for sequential patterns. Hence interleaved reads might be served as
++ * sequential ones.
++ *
++ * There is a special-case: if the first page which the application tries to
++ * read happens to be the first page of the file, it is assumed that a linear
++ * read is about to happen and the window is immediately set to the initial size
++ * based on I/O request size and the max_readahead.
++ *
++ * The code ramps up the readahead size aggressively at first, but slow down as
++ * it approaches max_readhead.
++ */
++
++/*
++ * A minimal readahead algorithm for trivial sequential/random reads.
++ */
++static unsigned long
++ondemand_readahead(struct address_space *mapping,
++		   struct file_ra_state *ra, struct file *filp,
++		   struct page *page, pgoff_t offset,
++		   unsigned long req_size)
++{
++	unsigned long max;	/* max readahead pages */
++	pgoff_t ra_index;	/* readahead index */
++	unsigned long ra_size;	/* readahead size */
++	unsigned long la_size;	/* lookahead size */
++	int sequential;
++
++	max = ra->ra_pages;
++	sequential = (offset - ra->prev_index <= 1UL) || (req_size > max);
++
++	/*
++	 * Lookahead/readahead hit, assume sequential access.
++	 * Ramp up sizes, and push forward the readahead window.
++	 */
++	if (offset && (offset == ra->lookahead_index ||
++			offset == ra->readahead_index)) {
++		ra_index = ra->readahead_index;
++		ra_size = get_next_ra_size2(ra, max);
++		la_size = ra_size;
++		goto fill_ra;
++	}
++
++	/*
++	 * Standalone, small read.
++	 * Read as is, and do not pollute the readahead state.
++	 */
++	if (!page && !sequential) {
++		return __do_page_cache_readahead(mapping, filp,
++						offset, req_size, 0);
++	}
++
++	/*
++	 * It may be one of
++	 * 	- first read on start of file
++	 * 	- sequential cache miss
++	 * 	- oversize random read
++	 * Start readahead for it.
++	 */
++	ra_index = offset;
++	ra_size = get_init_ra_size(req_size, max);
++	la_size = ra_size > req_size ? ra_size - req_size : ra_size;
++
++	/*
++	 * Hit on a lookahead page without valid readahead state.
++	 * E.g. interleaved reads.
++	 * Not knowing its readahead pos/size, bet on the minimal possible one.
++	 */
++	if (page) {
++		ra_index++;
++		ra_size = min(4 * ra_size, max);
++	}
++
++fill_ra:
++	ra_set_index(ra, offset, ra_index);
++	ra_set_size(ra, ra_size, la_size);
++
++	return ra_submit(ra, mapping, filp);
++}
++
++/**
++ * page_cache_readahead_ondemand - generic file readahead
++ * @mapping: address_space which holds the pagecache and I/O vectors
++ * @ra: file_ra_state which holds the readahead state
++ * @filp: passed on to ->readpage() and ->readpages()
++ * @page: the page at @offset, or NULL if non-present
++ * @offset: start offset into @mapping, in PAGE_CACHE_SIZE units
++ * @req_size: hint: total size of the read which the caller is performing in
++ *            PAGE_CACHE_SIZE units
++ *
++ * page_cache_readahead_ondemand() is the entry point of readahead logic.
++ * This function should be called when it is time to perform readahead:
++ * 1) @page == NULL
++ *    A cache miss happened, time for synchronous readahead.
++ * 2) @page != NULL && PageReadahead(@page)
++ *    A look-ahead hit occured, time for asynchronous readahead.
++ */
++unsigned long
++page_cache_readahead_ondemand(struct address_space *mapping,
++				struct file_ra_state *ra, struct file *filp,
++				struct page *page, pgoff_t offset,
++				unsigned long req_size)
++{
++	/* no read-ahead */
++	if (!ra->ra_pages)
++		return 0;
++
++	if (page) {
++		ClearPageReadahead(page);
++
++		/*
++		 * Defer asynchronous read-ahead on IO congestion.
++		 */
++		if (bdi_read_congested(mapping->backing_dev_info))
++			return 0;
++	}
++
++	/* do read-ahead */
++	return ondemand_readahead(mapping, ra, filp, page,
++					offset, req_size);
++}
++EXPORT_SYMBOL_GPL(page_cache_readahead_ondemand);

commit 5ce1110b92b31d079aa443e967f43a2294e01194
+Author: Fengguang Wu 
+Date:   Thu Jul 19 01:47:59 2007 -0700
+
+    readahead: data structure and routines
+    
+    Extend struct file_ra_state to support the on-demand readahead logic.  Also
+    define some helpers for it.
+    
+    Signed-off-by: Fengguang Wu 
+    Cc: Steven Pratt 
+    Cc: Ram Pai 
+    Cc: Rusty Russell 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 75dd16efc9b6..9a5f562abc77 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -695,6 +695,10 @@ struct fown_struct {
+ 
+ /*
+  * Track a single file's readahead state
++ *
++ *  ================#============|==================#==================|
++ *                  ^            ^                  ^                  ^
++ *  file_ra_state.la_index    .ra_index   .lookahead_index   .readahead_index
+  */
+ struct file_ra_state {
+ 	unsigned long start;		/* Current window */
+@@ -704,6 +708,12 @@ struct file_ra_state {
+ 	unsigned long prev_index;	/* Cache last read() position */
+ 	unsigned long ahead_start;	/* Ahead window */
+ 	unsigned long ahead_size;
++
++	pgoff_t la_index;               /* enqueue time */
++	pgoff_t ra_index;               /* begin offset */
++	pgoff_t lookahead_index;        /* time to do next readahead */
++	pgoff_t readahead_index;        /* end offset */
++
+ 	unsigned long ra_pages;		/* Maximum readahead window */
+ 	unsigned long mmap_hit;		/* Cache hit stat for mmap accesses */
+ 	unsigned long mmap_miss;	/* Cache miss stat for mmap accesses */
+@@ -712,6 +722,60 @@ struct file_ra_state {
+ #define RA_FLAG_MISS 0x01	/* a cache miss occured against this file */
+ #define RA_FLAG_INCACHE 0x02	/* file is already in cache */
+ 
++/*
++ * Measuring read-ahead sizes.
++ *
++ *                  |----------- readahead size ------------>|
++ *  ===#============|==================#=====================|
++ *     |------- invoke interval ------>|-- lookahead size -->|
++ */
++static inline unsigned long ra_readahead_size(struct file_ra_state *ra)
++{
++	return ra->readahead_index - ra->ra_index;
++}
++
++static inline unsigned long ra_lookahead_size(struct file_ra_state *ra)
++{
++	return ra->readahead_index - ra->lookahead_index;
++}
++
++static inline unsigned long ra_invoke_interval(struct file_ra_state *ra)
++{
++	return ra->lookahead_index - ra->la_index;
++}
++
++/*
++ * Check if @index falls in the readahead windows.
++ */
++static inline int ra_has_index(struct file_ra_state *ra, pgoff_t index)
++{
++	return (index >= ra->la_index &&
++		index <  ra->readahead_index);
++}
++
++/*
++ * Where is the old read-ahead and look-ahead?
++ */
++static inline void ra_set_index(struct file_ra_state *ra,
++				pgoff_t la_index, pgoff_t ra_index)
++{
++	ra->la_index = la_index;
++	ra->ra_index = ra_index;
++}
++
++/*
++ * Where is the new read-ahead and look-ahead?
++ */
++static inline void ra_set_size(struct file_ra_state *ra,
++				unsigned long ra_size, unsigned long la_size)
++{
++	ra->readahead_index = ra->ra_index + ra_size;
++	ra->lookahead_index = ra->ra_index + ra_size - la_size;
++}
++
++unsigned long ra_submit(struct file_ra_state *ra,
++		       struct address_space *mapping, struct file *filp);
++
+ struct file {
+ 	/*
+ 	 * fu_list becomes invalid after file_free is called and queued via
+diff --git a/mm/readahead.c b/mm/readahead.c
+index 7f9bf588c936..072ce8f8357d 100644
+--- a/mm/readahead.c
++++ b/mm/readahead.c
+@@ -592,3 +592,22 @@ unsigned long max_sane_readahead(unsigned long nr)
+ 	return min(nr, (node_page_state(numa_node_id(), NR_INACTIVE)
+ 		+ node_page_state(numa_node_id(), NR_FREE_PAGES)) / 2);
+ }
++
++/*
++ * Submit IO for the read-ahead request in file_ra_state.
++ */
++unsigned long ra_submit(struct file_ra_state *ra,
++		       struct address_space *mapping, struct file *filp)
++{
++	unsigned long ra_size;
++	unsigned long la_size;
++	int actual;
++
++	ra_size = ra_readahead_size(ra);
++	la_size = ra_lookahead_size(ra);
++	actual = __do_page_cache_readahead(mapping, filp,
++					ra->ra_index, ra_size, la_size);
++
++	return actual;
++}
++EXPORT_SYMBOL_GPL(ra_submit);

commit f615bfca468c9b80ed2d09be5fdbaf470a32c045
+Author: Fengguang Wu 
+Date:   Thu Jul 19 01:47:58 2007 -0700
+
+    readahead: MIN_RA_PAGES/MAX_RA_PAGES macros
+    
+    Define two convenient macros for read-ahead:
+            - MAX_RA_PAGES: rounded down counterpart of VM_MAX_READAHEAD
+            - MIN_RA_PAGES: rounded _up_ counterpart of VM_MIN_READAHEAD
+    
+    Note that the rounded up MIN_RA_PAGES will work flawlessly with _large_
+    page sizes like 64k.
+    
+    Signed-off-by: Fengguang Wu 
+    Cc: Steven Pratt 
+    Cc: Ram Pai 
+    Cc: Rusty Russell 
+    Cc: 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/mm/readahead.c b/mm/readahead.c
+index 88ea0f29aac8..7f9bf588c936 100644
+--- a/mm/readahead.c
++++ b/mm/readahead.c
+@@ -21,8 +21,16 @@ void default_unplug_io_fn(struct backing_dev_info *bdi, struct page *page)
+ }
+ EXPORT_SYMBOL(default_unplug_io_fn);
+ 
++/*
++ * Convienent macros for min/max read-ahead pages.
++ * Note that MAX_RA_PAGES is rounded down, while MIN_RA_PAGES is rounded up.
++ * The latter is necessary for systems with large page size(i.e. 64k).
++ */
++#define MAX_RA_PAGES	(VM_MAX_READAHEAD*1024 / PAGE_CACHE_SIZE)
++#define MIN_RA_PAGES	DIV_ROUND_UP(VM_MIN_READAHEAD*1024, PAGE_CACHE_SIZE)
++
+ struct backing_dev_info default_backing_dev_info = {
+-	.ra_pages	= (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE,
++	.ra_pages	= MAX_RA_PAGES,
+ 	.state		= 0,
+ 	.capabilities	= BDI_CAP_MAP_COPY,
+ 	.unplug_io_fn	= default_unplug_io_fn,
+@@ -51,7 +59,7 @@ static inline unsigned long get_max_readahead(struct file_ra_state *ra)
+ 
+ static inline unsigned long get_min_readahead(struct file_ra_state *ra)
+ {
+-	return (VM_MIN_READAHEAD * 1024) / PAGE_CACHE_SIZE;
++	return MIN_RA_PAGES;
+ }
+ 
+ static inline void reset_ahead_window(struct file_ra_state *ra)

commit 46fc3e7b4e7233a0ac981ac9084b55217318d04d
+Author: Fengguang Wu 
+Date:   Thu Jul 19 01:47:57 2007 -0700
+
+    readahead: add look-ahead support to __do_page_cache_readahead()
+    
+    Add look-ahead support to __do_page_cache_readahead().
+    
+    It works by
+            - mark the Nth backwards page with PG_readahead,
+            (which instructs the page's first reader to invoke readahead)
+            - and only do the marking for newly allocated pages.
+            (to prevent blindly doing readahead on already cached pages)
+    
+    Look-ahead is a technique to achieve I/O pipelining:
+    
+    While the application is working through a chunk of cached pages, the kernel
+    reads-ahead the next chunk of pages _before_ time of need.  It effectively
+    hides low level I/O latencies to high level applications.
+    
+    Signed-off-by: Fengguang Wu 
+    Cc: Steven Pratt 
+    Cc: Ram Pai 
+    Cc: Rusty Russell 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/mm/readahead.c b/mm/readahead.c
+index 9861e883fe57..88ea0f29aac8 100644
+--- a/mm/readahead.c
++++ b/mm/readahead.c
+@@ -265,7 +265,8 @@ static int read_pages(struct address_space *mapping, struct file *filp,
+  */
+ static int
+ __do_page_cache_readahead(struct address_space *mapping, struct file *filp,
+-			pgoff_t offset, unsigned long nr_to_read)
++			pgoff_t offset, unsigned long nr_to_read,
++			unsigned long lookahead_size)
+ {
+ 	struct inode *inode = mapping->host;
+ 	struct page *page;
+@@ -278,7 +279,7 @@ __do_page_cache_readahead(struct address_space *mapping, struct file *filp,
+ 	if (isize == 0)
+ 		goto out;
+ 
+- 	end_index = ((isize - 1) >> PAGE_CACHE_SHIFT);
++	end_index = ((isize - 1) >> PAGE_CACHE_SHIFT);
+ 
+ 	/*
+ 	 * Preallocate as many pages as we will need.
+@@ -301,6 +302,8 @@ __do_page_cache_readahead(struct address_space *mapping, struct file *filp,
+ 			break;
+ 		page->index = page_offset;
+ 		list_add(&page->lru, &page_pool);
++		if (page_idx == nr_to_read - lookahead_size)
++			SetPageReadahead(page);
+ 		ret++;
+ 	}
+ 	read_unlock_irq(&mapping->tree_lock);
+@@ -337,7 +340,7 @@ int force_page_cache_readahead(struct address_space *mapping, struct file *filp,
+ 		if (this_chunk > nr_to_read)
+ 			this_chunk = nr_to_read;
+ 		err = __do_page_cache_readahead(mapping, filp,
+-						offset, this_chunk);
++						offset, this_chunk, 0);
+ 		if (err < 0) {
+ 			ret = err;
+ 			break;
+@@ -384,7 +387,7 @@ int do_page_cache_readahead(struct address_space *mapping, struct file *filp,
+ 	if (bdi_read_congested(mapping->backing_dev_info))
+ 		return -1;
+ 
+-	return __do_page_cache_readahead(mapping, filp, offset, nr_to_read);
++	return __do_page_cache_readahead(mapping, filp, offset, nr_to_read, 0);
+ }
+ 
+ /*
+@@ -404,7 +407,7 @@ blockable_page_cache_readahead(struct address_space *mapping, struct file *filp,
+ 	if (!block && bdi_read_congested(mapping->backing_dev_info))
+ 		return 0;
+ 
+-	actual = __do_page_cache_readahead(mapping, filp, offset, nr_to_read);
++	actual = __do_page_cache_readahead(mapping, filp, offset, nr_to_read, 0);
+ 
+ 	return check_ra_success(ra, nr_to_read, actual);
+ }
+@@ -449,7 +452,7 @@ static int make_ahead_window(struct address_space *mapping, struct file *filp,
+  * @req_size: hint: total size of the read which the caller is performing in
+  *            PAGE_CACHE_SIZE units
+  *
+- * page_cache_readahead() is the main function.  If performs the adaptive
++ * page_cache_readahead() is the main function.  It performs the adaptive
+  * readahead window size management and submits the readahead I/O.
+  *
+  * Note that @filp is purely used for passing on to the ->readpage[s]()

commit d77c2d7cc5126639a47d73300b40d461f2811a0f
+Author: Fengguang Wu 
+Date:   Thu Jul 19 01:47:55 2007 -0700
+
+    readahead: introduce PG_readahead
+    
+    Introduce a new page flag: PG_readahead.
+    
+    It acts as a look-ahead mark, which tells the page reader: Hey, it's time to
+    invoke the read-ahead logic.  For the sake of I/O pipelining, don't wait until
+    it runs out of cached pages!
+    
+    Signed-off-by: Fengguang Wu 
+    Cc: Steven Pratt 
+    Cc: Ram Pai 
+    Cc: Rusty Russell 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
+index 731cd2ac3227..709d92fd2877 100644
+--- a/include/linux/page-flags.h
++++ b/include/linux/page-flags.h
+@@ -83,6 +83,7 @@
+ #define PG_private		11	/* If pagecache, has fs-private data */
+ 
+ #define PG_writeback		12	/* Page is under writeback */
++#define PG_readahead		13	/* Reminder to do async read-ahead */
+ #define PG_compound		14	/* Part of a compound page */
+ #define PG_swapcache		15	/* Swap page: swp_entry_t in private */
+ 
+@@ -226,6 +227,10 @@ static inline void SetPageUptodate(struct page *page)
+ #define SetPageMappedToDisk(page) set_bit(PG_mappedtodisk, &(page)->flags)
+ #define ClearPageMappedToDisk(page) clear_bit(PG_mappedtodisk, &(page)->flags)
+ 
++#define PageReadahead(page)	test_bit(PG_readahead, &(page)->flags)
++#define SetPageReadahead(page)	set_bit(PG_readahead, &(page)->flags)
++#define ClearPageReadahead(page) clear_bit(PG_readahead, &(page)->flags)
++
+ #define PageReclaim(page)	test_bit(PG_reclaim, &(page)->flags)
+ #define SetPageReclaim(page)	set_bit(PG_reclaim, &(page)->flags)
+ #define ClearPageReclaim(page)	clear_bit(PG_reclaim, &(page)->flags)
+diff --git a/mm/page_alloc.c b/mm/page_alloc.c
+index e2a10b957f23..2165be9462c0 100644
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -617,7 +617,7 @@ static int prep_new_page(struct page *page, int order, gfp_t gfp_flags)
+ 	if (PageReserved(page))
+ 		return 1;
+ 
+-	page->flags &= ~(1 << PG_uptodate | 1 << PG_error |
++	page->flags &= ~(1 << PG_uptodate | 1 << PG_error | 1 << PG_readahead |
+ 			1 << PG_referenced | 1 << PG_arch_1 |
+ 			1 << PG_owner_priv_1 | 1 << PG_mappedtodisk);
+ 	set_page_private(page, 0);

commit 76d42bd96984832c4ea8bc8cbd74e496ac31409e
+Author: Wu Fengguang 
+Date:   Sun Jun 25 05:48:43 2006 -0700
+
+    [PATCH] readahead: backoff on I/O error
+    
+    Backoff readahead size exponentially on I/O error.
+    
+    Michael Tokarev  described the problem as:
+    
+    [QUOTE]
+    Suppose there's a CD-rom with a scratch/etc, one sector is unreadable.
+    In order to "fix" it, one have to read it and write to another CD-rom,
+    or something.. or just ignore the error (if it's just a skip in a video
+    stream).  Let's assume the unreadable block is number U.
+    
+    But current behavior is just insane.  An application requests block
+    number N, which is before U. Kernel tries to read-ahead blocks N..U.
+    Cdrom drive tries to read it, re-read it.. for some time.  Finally,
+    when all the N..U-1 blocks are read, kernel returns block number N
+    (as requested) to an application, successefully.
+    
+    Now an app requests block number N+1, and kernel tries to read
+    blocks N+1..U+1.  Retrying again as in previous step.
+    
+    And so on, up to when an app requests block number U-1.  And when,
+    finally, it requests block U, it receives read error.
+    
+    So, kernel currentry tries to re-read the same failing block as
+    many times as the current readahead value (256 (times?) by default).
+    
+    This whole process already killed my cdrom drive (I posted about it
+    to LKML several months ago) - literally, the drive has fried, and
+    does not work anymore.  Ofcourse that problem was a bug in firmware
+    (or whatever) of the drive *too*, but.. main problem with that is
+    current readahead logic as described above.
+    [/QUOTE]
+    
+    Which was confirmed by Jens Axboe :
+    
+    [QUOTE]
+    For ide-cd, it tends do only end the first part of the request on a
+    medium error. So you may see a lot of repeats :/
+    [/QUOTE]
+    
+    With this patch, retries are expected to be reduced from, say, 256, to 5.
+    
+    [akpm@osdl.org: cleanups]
+    Signed-off-by: Wu Fengguang 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/mm/filemap.c b/mm/filemap.c
+index 1ed4be2a7654..9c7334bafda8 100644
+--- a/mm/filemap.c
++++ b/mm/filemap.c
+@@ -828,6 +828,32 @@ grab_cache_page_nowait(struct address_space *mapping, unsigned long index)
+ }
+ EXPORT_SYMBOL(grab_cache_page_nowait);
+ 
++/*
++ * CD/DVDs are error prone. When a medium error occurs, the driver may fail
++ * a _large_ part of the i/o request. Imagine the worst scenario:
++ *
++ *      ---R__________________________________________B__________
++ *         ^ reading here                             ^ bad block(assume 4k)
++ *
++ * read(R) => miss => readahead(R...B) => media error => frustrating retries
++ * => failing the whole request => read(R) => read(R+1) =>
++ * readahead(R+1...B+1) => bang => read(R+2) => read(R+3) =>
++ * readahead(R+3...B+2) => bang => read(R+3) => read(R+4) =>
++ * readahead(R+4...B+3) => bang => read(R+4) => read(R+5) => ......
++ *
++ * It is going insane. Fix it by quickly scaling down the readahead size.
++ */
++static void shrink_readahead_size_eio(struct file *filp,
++					struct file_ra_state *ra)
++{
++	if (!ra->ra_pages)
++		return;
++
++	ra->ra_pages /= 4;
++	printk(KERN_WARNING "Reducing readahead size to %luK\n",
++			ra->ra_pages << (PAGE_CACHE_SHIFT - 10));
++}
++
+ /**
+  * do_generic_mapping_read - generic file read routine
+  * @mapping:	address_space to be read
+@@ -985,6 +1011,7 @@ void do_generic_mapping_read(struct address_space *mapping,
+ 				}
+ 				unlock_page(page);
+ 				error = -EIO;
++				shrink_readahead_size_eio(filp, &ra);
+ 				goto readpage_error;
+ 			}
+ 			unlock_page(page);
+@@ -1522,6 +1549,7 @@ struct page *filemap_nopage(struct vm_area_struct *area,
+ 	 * Things didn't work out. Return zero to tell the
+ 	 * mm layer so, possibly freeing the page cache page first.
+ 	 */
++	shrink_readahead_size_eio(file, ra);
+ 	page_cache_release(page);
+ 	return NULL;
+ }

commit e5dcd90b53d601a04482db9800336a0ccf190880
+Author: Wu Fengguang 
+Date:   Sun Jun 25 05:48:14 2006 -0700
+
+    [PATCH] radixtree: normalize radix_tree_tag_get() return value
+    
+    In radix_tree_tag_get(), return normalized value of 0/1, as indicated
+    by its comment.
+    
+    Signed-off-by: Wu Fengguang 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/lib/radix-tree.c b/lib/radix-tree.c
+index b32efae7688e..637d55608de5 100644
+--- a/lib/radix-tree.c
++++ b/lib/radix-tree.c
+@@ -530,7 +530,7 @@ int radix_tree_tag_get(struct radix_tree_root *root,
+ 			int ret = tag_get(slot, tag, offset);
+ 
+ 			BUG_ON(ret && saw_unset_tag);
+-			return ret;
++			return !!ret;
+ 		}
+ 		slot = slot->slots[offset];
+ 		shift -= RADIX_TREE_MAP_SHIFT;

commit fb8d14e172a29ba5ac69a73b61196be86fdfc3e1
+Author: Wu Fengguang 
+Date:   Wed Mar 22 00:08:28 2006 -0800
+
+    [PATCH] mm: shrink_inactive_lis() nr_scan accounting fix
+    
+    In shrink_inactive_list(), nr_scan is not accounted when nr_taken is 0.
+    But 0 pages taken does not mean 0 pages scanned.
+    
+    Move the goto statement below the accounting code to fix it.
+    
+    Signed-off-by: Wu Fengguang 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/mm/vmscan.c b/mm/vmscan.c
+index 85e95f445022..486184d2b50c 100644
+--- a/mm/vmscan.c
++++ b/mm/vmscan.c
+@@ -1132,9 +1132,6 @@ static unsigned long shrink_inactive_list(unsigned long max_scan,
+ 		zone->pages_scanned += nr_scan;
+ 		spin_unlock_irq(&zone->lru_lock);
+ 
+-		if (nr_taken == 0)
+-			goto done;
+-
+ 		nr_scanned += nr_scan;
+ 		nr_freed = shrink_page_list(&page_list, sc);
+ 		nr_reclaimed += nr_freed;
+@@ -1146,6 +1143,9 @@ static unsigned long shrink_inactive_list(unsigned long max_scan,
+ 			__mod_page_state_zone(zone, pgscan_direct, nr_scan);
+ 		__mod_page_state_zone(zone, pgsteal, nr_freed);
+ 
++		if (nr_taken == 0)
++			goto done;
++
+ 		spin_lock(&zone->lru_lock);
+ 		/*
+ 		 * Put back any unfreeable pages.
+@@ -1166,8 +1166,9 @@ static unsigned long shrink_inactive_list(unsigned long max_scan,
+ 			}
+ 		}
+   	} while (nr_scanned < max_scan);
+-	spin_unlock_irq(&zone->lru_lock);
++	spin_unlock(&zone->lru_lock);
+ done:
++	local_irq_enable();
+ 	pagevec_release(&pvec);
+ 	return nr_reclaimed;
+ }

commit c9b02d970c385a253edb36c87643b0df706b50b4
+Author: Wu Fengguang 
+Date:   Wed Mar 22 00:08:23 2006 -0800
+
+    [PATCH] mm: isolate_lru_pages() scan count fix
+    
+    In isolate_lru_pages(), *scanned reports one more scan because the scan
+    counter is increased one more time on exit of the while-loop.
+    
+    Change the while-loop to for-loop to fix it.
+    
+    Signed-off-by: Nick Piggin 
+    Signed-off-by: Wu Fengguang 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/mm/vmscan.c b/mm/vmscan.c
+index c712b946e4ff..85e95f445022 100644
+--- a/mm/vmscan.c
++++ b/mm/vmscan.c
+@@ -1074,9 +1074,9 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
+ {
+ 	unsigned long nr_taken = 0;
+ 	struct page *page;
+-	unsigned long scan = 0;
++	unsigned long scan;
+ 
+-	while (scan++ < nr_to_scan && !list_empty(src)) {
++	for (scan = 0; scan < nr_to_scan && !list_empty(src); scan++) {
+ 		struct list_head *target;
+ 		page = lru_to_page(src);
+ 		prefetchw_prev_lru_page(page, src, flags);

\ No newline at end of file diff --git a/detail/13.html b/detail/13.html new file mode 100644 index 0000000..5287dd7 --- /dev/null +++ b/detail/13.html @@ -0,0 +1,11330 @@ +

Patches contributed by University of Washington


commit 19050da1d1057a7bc73fd9039f94b7f63a00e54e
+Author: Kenneth Lee 
+Date:   Tue Aug 9 00:20:50 2022 -0700
+
+    ARM: OMAP2+: hwmod: Use kzalloc for allocating only one element
+    
+    Use kzalloc(...) rather than kcalloc(1, ...) because the number of
+    elements we are specifying in this case is 1, so kzalloc would
+    accomplish the same thing and we can simplify.
+    
+    Signed-off-by: Kenneth Lee 
+    Message-Id: <20220809072050.1733996-1-klee33@uw.edu>
+    Signed-off-by: Tony Lindgren 
+
+diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
+index de3fd0bc862d..aac4c4ee2528 100644
+--- a/arch/arm/mach-omap2/omap_hwmod.c
++++ b/arch/arm/mach-omap2/omap_hwmod.c
+@@ -3454,7 +3454,7 @@ static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh,
+ 	}
+ 
+ 	if (list_empty(&oh->slave_ports)) {
+-		oi = kcalloc(1, sizeof(*oi), GFP_KERNEL);
++		oi = kzalloc(sizeof(*oi), GFP_KERNEL);
+ 		if (!oi)
+ 			goto out_free_class;
+ 

commit aa1d627207cace003163dee24d1c06fa4e910c6b
+Author: Kenneth Lee 
+Date:   Thu Aug 18 22:42:55 2022 -0700
+
+    ceph: Use kcalloc for allocating multiple elements
+    
+    Prefer using kcalloc(a, b) over kzalloc(a * b) as this improves
+    semantics since kcalloc is intended for allocating an array of memory.
+    
+    Signed-off-by: Kenneth Lee 
+    Reviewed-by: Xiubo Li 
+    Signed-off-by: Ilya Dryomov 
+
+diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
+index 0dc1251c3c6d..fb023f9fafcb 100644
+--- a/fs/ceph/caps.c
++++ b/fs/ceph/caps.c
+@@ -2286,7 +2286,7 @@ static int flush_mdlog_and_wait_inode_unsafe_requests(struct inode *inode)
+ 		struct ceph_mds_request *req;
+ 		int i;
+ 
+-		sessions = kzalloc(max_sessions * sizeof(s), GFP_KERNEL);
++		sessions = kcalloc(max_sessions, sizeof(s), GFP_KERNEL);
+ 		if (!sessions) {
+ 			err = -ENOMEM;
+ 			goto out;

commit 92f017c4aee6e2bb79593adeacccbea3afe62223
+Author: Kenneth Lee 
+Date:   Thu Aug 18 22:51:17 2022 -0700
+
+    fs/ntfs3: Use kmalloc_array for allocating multiple elements
+    
+    Prefer using kmalloc_array(a, b) over kmalloc(a * b) as this
+    improves semantics since kmalloc is intended for allocating an
+    array of memory.
+    
+    Signed-off-by: Kenneth Lee 
+    Signed-off-by: Konstantin Komarov 
+
+diff --git a/fs/ntfs3/bitmap.c b/fs/ntfs3/bitmap.c
+index 5d44ceac855b..1675c9a69788 100644
+--- a/fs/ntfs3/bitmap.c
++++ b/fs/ntfs3/bitmap.c
+@@ -1324,7 +1324,7 @@ int wnd_extend(struct wnd_bitmap *wnd, size_t new_bits)
+ 		new_last = wbits;
+ 
+ 	if (new_wnd != wnd->nwnd) {
+-		new_free = kmalloc(new_wnd * sizeof(u16), GFP_NOFS);
++		new_free = kmalloc_array(new_wnd, sizeof(u16), GFP_NOFS);
+ 		if (!new_free)
+ 			return -ENOMEM;
+ 

commit d3524bb5b9a0c567b853a0024526afe87dde01ed
+Author: Kenneth Lee 
+Date:   Fri Sep 16 13:20:52 2022 +0100
+
+    nvmem: brcm_nvram: Use kzalloc for allocating only one element
+    
+    Use kzalloc(...) rather than kcalloc(1, ...) because the number of
+    elements we are specifying in this case is 1, so kzalloc would
+    accomplish the same thing and we can simplify.
+    
+    Signed-off-by: Kenneth Lee 
+    Signed-off-by: Srinivas Kandagatla 
+    Link: https://lore.kernel.org/r/20220916122100.170016-6-srinivas.kandagatla@linaro.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/nvmem/brcm_nvram.c b/drivers/nvmem/brcm_nvram.c
+index 450b927691c3..4441daa20965 100644
+--- a/drivers/nvmem/brcm_nvram.c
++++ b/drivers/nvmem/brcm_nvram.c
+@@ -96,7 +96,7 @@ static int brcm_nvram_parse(struct brcm_nvram *priv)
+ 
+ 	len = le32_to_cpu(header.len);
+ 
+-	data = kcalloc(1, len, GFP_KERNEL);
++	data = kzalloc(len, GFP_KERNEL);
+ 	memcpy_fromio(data, priv->base, len);
+ 	data[len - 1] = '\0';
+ 

commit b2d4c646d5a15c1854e09898a374983167e53e0e
+Author: Kenneth Lee 
+Date:   Mon Aug 8 15:00:19 2022 -0700
+
+    mm/damon/dbgfs: use kmalloc for allocating only one element
+    
+    Use kmalloc(...) rather than kmalloc_array(1, ...) because the number of
+    elements we are specifying in this case is 1, kmalloc would accomplish the
+    same thing and we can simplify.
+    
+    Link: https://lkml.kernel.org/r/20220808220019.1680469-1-klee33@uw.edu
+    Signed-off-by: Kenneth Lee 
+    Reviewed-by: SeongJae Park 
+    Signed-off-by: Andrew Morton 
+
+diff --git a/mm/damon/dbgfs.c b/mm/damon/dbgfs.c
+index cfdf63132d5a..3b55a1b219b5 100644
+--- a/mm/damon/dbgfs.c
++++ b/mm/damon/dbgfs.c
+@@ -1044,7 +1044,7 @@ static int __init __damon_dbgfs_init(void)
+ 				fops[i]);
+ 	dbgfs_fill_ctx_dir(dbgfs_root, dbgfs_ctxs[0]);
+ 
+-	dbgfs_dirs = kmalloc_array(1, sizeof(dbgfs_root), GFP_KERNEL);
++	dbgfs_dirs = kmalloc(sizeof(dbgfs_root), GFP_KERNEL);
+ 	if (!dbgfs_dirs) {
+ 		debugfs_remove(dbgfs_root);
+ 		return -ENOMEM;

commit 00784da3e6b8c1f0e58d813272503d014de8f64b
+Author: Kenneth Lee 
+Date:   Sat Aug 6 22:16:56 2022 -0700
+
+    can: kvaser_usb: kvaser_usb_hydra: Use kzalloc for allocating only one element
+    
+    Use kzalloc(...) rather than kcalloc(1, ...) since because the number of
+    elements we are specifying in this case is 1, kzalloc would accomplish the
+    same thing and we can simplify. Also refactor how we calculate the sizeof()
+    as checkstyle for kzalloc() prefers using the variable we are assigning
+    to versus the type of that variable for calculating the size to allocate.
+    
+    Signed-off-by: Kenneth Lee 
+    Link: https://lore.kernel.org/all/20220807051656.1991446-1-klee33@uw.edu
+    Signed-off-by: Marc Kleine-Budde 
+
+diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
+index dd65c101bfb8..6871d474dabf 100644
+--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
+@@ -534,7 +534,7 @@ static int kvaser_usb_hydra_send_simple_cmd(struct kvaser_usb *dev,
+ 	struct kvaser_cmd *cmd;
+ 	int err;
+ 
+-	cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL);
++	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ 	if (!cmd)
+ 		return -ENOMEM;
+ 
+@@ -573,7 +573,7 @@ kvaser_usb_hydra_send_simple_cmd_async(struct kvaser_usb_net_priv *priv,
+ 	struct kvaser_usb *dev = priv->dev;
+ 	int err;
+ 
+-	cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_ATOMIC);
++	cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
+ 	if (!cmd)
+ 		return -ENOMEM;
+ 
+@@ -694,7 +694,7 @@ static int kvaser_usb_hydra_map_channel(struct kvaser_usb *dev, u16 transid,
+ 	struct kvaser_cmd *cmd;
+ 	int err;
+ 
+-	cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL);
++	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ 	if (!cmd)
+ 		return -ENOMEM;
+ 
+@@ -735,7 +735,7 @@ static int kvaser_usb_hydra_get_single_capability(struct kvaser_usb *dev,
+ 	int err;
+ 	int i;
+ 
+-	cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL);
++	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ 	if (!cmd)
+ 		return -ENOMEM;
+ 
+@@ -1394,7 +1394,7 @@ kvaser_usb_hydra_frame_to_cmd_ext(const struct kvaser_usb_net_priv *priv,
+ 	u32 kcan_id;
+ 	u32 kcan_header;
+ 
+-	cmd = kcalloc(1, sizeof(struct kvaser_cmd_ext), GFP_ATOMIC);
++	cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
+ 	if (!cmd)
+ 		return NULL;
+ 
+@@ -1468,7 +1468,7 @@ kvaser_usb_hydra_frame_to_cmd_std(const struct kvaser_usb_net_priv *priv,
+ 	u32 flags;
+ 	u32 id;
+ 
+-	cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_ATOMIC);
++	cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
+ 	if (!cmd)
+ 		return NULL;
+ 
+@@ -1533,7 +1533,7 @@ static int kvaser_usb_hydra_set_bittiming(struct net_device *netdev)
+ 	int sjw = bt->sjw;
+ 	int err;
+ 
+-	cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL);
++	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ 	if (!cmd)
+ 		return -ENOMEM;
+ 
+@@ -1567,7 +1567,7 @@ static int kvaser_usb_hydra_set_data_bittiming(struct net_device *netdev)
+ 	int sjw = dbt->sjw;
+ 	int err;
+ 
+-	cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL);
++	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ 	if (!cmd)
+ 		return -ENOMEM;
+ 
+@@ -1711,7 +1711,7 @@ static int kvaser_usb_hydra_get_software_details(struct kvaser_usb *dev)
+ 	u32 flags;
+ 	struct kvaser_usb_dev_card_data *card_data = &dev->card_data;
+ 
+-	cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL);
++	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ 	if (!cmd)
+ 		return -ENOMEM;
+ 
+@@ -1851,7 +1851,7 @@ static int kvaser_usb_hydra_set_opt_mode(const struct kvaser_usb_net_priv *priv)
+ 		return -EINVAL;
+ 	}
+ 
+-	cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL);
++	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ 	if (!cmd)
+ 		return -ENOMEM;
+ 

commit d2ff1d2067ac382f189eadc1a400b948fd398658
+Author: Conrad Meyer 
+Date:   Sat Mar 8 21:42:58 2014 -0500
+
+    Staging: comedi: do not initialize statics to 0 (apci1500)
+    
+    Minor style cleanup per checkpatch.pl.
+    
+    Signed-off-by: Conrad Meyer 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+index 4f5ce6af59dc..1f7adc5a97f2 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+@@ -141,16 +141,16 @@ enum {
+ 	APCI1500_RW_PORT_B_PATTERN_MASK
+ };
+ 
+-static int i_TimerCounter1Init = 0;
+-static int i_TimerCounter2Init = 0;
+-static int i_WatchdogCounter3Init = 0;
+-static int i_Event1Status = 0, i_Event2Status = 0;
+-static int i_TimerCounterWatchdogInterrupt = 0;
+-static int i_Logic = 0, i_CounterLogic = 0;
+-static int i_InterruptMask = 0;
+-static int i_InputChannel = 0;
+-static int i_TimerCounter1Enabled = 0, i_TimerCounter2Enabled = 0,
+-	   i_WatchdogCounter3Enabled = 0;
++static int i_TimerCounter1Init;
++static int i_TimerCounter2Init;
++static int i_WatchdogCounter3Init;
++static int i_Event1Status, i_Event2Status;
++static int i_TimerCounterWatchdogInterrupt;
++static int i_Logic, i_CounterLogic;
++static int i_InterruptMask;
++static int i_InputChannel;
++static int i_TimerCounter1Enabled, i_TimerCounter2Enabled,
++	   i_WatchdogCounter3Enabled;
+ 
+ /*
+   +----------------------------------------------------------------------------+
+@@ -977,7 +977,7 @@ static int i_APCI1500_WriteDigitalOutput(struct comedi_device *dev,
+ 					 unsigned int *data)
+ {
+ 	struct addi_private *devpriv = dev->private;
+-	static unsigned int ui_Temp = 0;
++	static unsigned int ui_Temp;
+ 	unsigned int ui_Temp1;
+ 	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	/*  get the channel */
+ 

commit c9847a6eeb8906d9026848dc442ae1bf7c5de7a9
+Author: Conrad Meyer 
+Date:   Sat Mar 8 21:42:49 2014 -0500
+
+    Staging: comedi: Kill comment art in hwdrv_apci1500.c
+    
+    Nudge the commenting in this mess a little further from 'bad.' Much of
+    it was incorrectly indented.
+    
+    Another sed cleanup:
+      $ sed -i -e '/\/\*\*\*\*\*\*\*\*\**\//,1d' addi-data/hwdrv_apci1500.c
+    
+    Signed-off-by: Conrad Meyer 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+index 0ccf784b81a4..4f5ce6af59dc 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+@@ -241,14 +241,10 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
+ 	int i_PatternTransitionCount = 0, i_RegValue;
+ 	int i;
+ 
+-      /*************************************************/
+ 	/* Selects the master interrupt control register */
+-      /*************************************************/
+ 	outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-      /**********************************************/
+ 	/* Disables  the main interrupt on the board */
+-      /**********************************************/
+ 	outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 
+ 	if (data[0] == 1) {
+@@ -327,17 +323,13 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
+ 	}			/* for (i_Count = i_MaxChannel; i_Count >0;i_Count --) */
+ 
+ 	if (data[0] == 1) {
+-		    /****************************/
+ 		/* Test the interrupt logic */
+-		    /****************************/
+ 
+ 		if (data[1] == APCI1500_AND ||
+ 			data[1] == APCI1500_OR ||
+ 			data[1] == APCI1500_OR_PRIORITY) {
+-		       /**************************************/
+ 			/* Tests if a transition was declared */
+ 			/* for a OR PRIORITY logic            */
+-		       /**************************************/
+ 
+ 			if (data[1] == APCI1500_OR_PRIORITY
+ 				&& i_PatternTransition != 0) {
+@@ -346,10 +338,8 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
+ 				return -EINVAL;
+ 			}	/*  if (data[1]== APCI1500_OR_PRIORITY && i_PatternTransition != 0) */
+ 
+-		       /*************************************/
+ 			/* Tests if more than one transition */
+ 			/* was declared for an AND logic     */
+-		       /*************************************/
+ 
+ 			if (data[1] == APCI1500_AND) {
+ 				for (i_Count = 0; i_Count < 8; i_Count++) {
+@@ -367,21 +357,15 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
+ 				}	/*  if (i_PatternTransitionCount > 1) */
+ 			}	/*  if (data[1]== APCI1500_AND) */
+ 
+-			    /*****************************************************************/
+ 			/* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+-			    /*****************************************************************/
+ 			outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+-			/******************/
+ 			/* Disable Port A */
+-			    /******************/
+ 			outb(0xF0,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+-			/**********************************************/
+ 			/* Selects the polarity register of port 1    */
+-			    /**********************************************/
+ 			outb(APCI1500_RW_PORT_A_PATTERN_POLARITY,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+@@ -389,20 +373,16 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-			/*********************************************/
+ 			/* Selects the pattern mask register of      */
+ 			/* port 1                                    */
+-			    /*********************************************/
+ 			outb(APCI1500_RW_PORT_A_PATTERN_MASK,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+ 			outb(i_PatternMask,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+-			/********************************************/
+ 			/* Selects the pattern transition register  */
+ 			/* of port 1                                */
+-			    /********************************************/
+ 			outb(APCI1500_RW_PORT_A_PATTERN_TRANSITION,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+@@ -410,10 +390,8 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-		      /******************************************/
+ 			/* Selects the mode specification mask    */
+ 			/* register of port 1                     */
+-			  /******************************************/
+ 			outb(APCI1500_RW_PORT_A_SPECIFICATION,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+@@ -421,17 +399,13 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
+ 				inb(devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-		      /******************************************/
+ 			/* Selects the mode specification mask    */
+ 			/* register of port 1                     */
+-			  /******************************************/
+ 			outb(APCI1500_RW_PORT_A_SPECIFICATION,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-		      /**********************/
+ 			/* Port A new mode    */
+-			  /**********************/
+ 
+ 			i_RegValue = (i_RegValue & 0xF9) | data[1] | 0x9;
+ 			outb(i_RegValue,
+@@ -440,16 +414,12 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
+ 
+ 			i_Event1Status = 1;
+ 
+-		      /*****************************************************************/
+ 			/* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+-			  /*****************************************************************/
+ 
+ 			outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+-		      /*****************/
+ 			/* Enable Port A */
+-			  /*****************/
+ 			outb(0xF4,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+@@ -462,32 +432,22 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
+ 		}		/*  else }// if(data[1]==APCI1500_AND||data[1]==APCI1500_OR||data[1]==APCI1500_OR_PRIORITY) */
+ 	}			/*    if (data[0]== 1) */
+ 
+-		 /************************************/
+ 	/* Test if event setting for port 2 */
+-		 /************************************/
+ 
+ 	if (data[0] == 2) {
+-		    /************************/
+ 		/* Test the event logic */
+-		    /************************/
+ 
+ 		if (data[1] == APCI1500_OR) {
+-		       /*****************************************************************/
+ 			/* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+-		       /*****************************************************************/
+ 			outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+-		       /******************/
+ 			/* Disable Port B */
+-		       /******************/
+ 			outb(0x74,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+-		       /****************************************/
+ 			/* Selects the mode specification mask  */
+ 			/* register of port B                   */
+-		       /****************************************/
+ 			outb(APCI1500_RW_PORT_B_SPECIFICATION,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+@@ -495,10 +455,8 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
+ 				inb(devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-		       /******************************************/
+ 			/* Selects the mode specification mask    */
+ 			/* register of port B                     */
+-		       /******************************************/
+ 			outb(APCI1500_RW_PORT_B_SPECIFICATION,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+@@ -507,37 +465,29 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-		       /**********************************/
+ 			/* Selects error channels 1 and 2 */
+-		       /**********************************/
+ 
+ 			i_PatternMask = (i_PatternMask | 0xC0);
+ 			i_PatternPolarity = (i_PatternPolarity | 0xC0);
+ 			i_PatternTransition = (i_PatternTransition | 0xC0);
+ 
+-		       /**********************************************/
+ 			/* Selects the polarity register of port 2    */
+-		       /**********************************************/
+ 			outb(APCI1500_RW_PORT_B_PATTERN_POLARITY,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+ 			outb(i_PatternPolarity,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+-		       /**********************************************/
+ 			/* Selects the pattern transition register    */
+ 			/* of port 2                                  */
+-		       /**********************************************/
+ 			outb(APCI1500_RW_PORT_B_PATTERN_TRANSITION,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+ 			outb(i_PatternTransition,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+-		       /**********************************************/
+ 			/* Selects the pattern Mask register    */
+ 			/* of port 2                                  */
+-		       /**********************************************/
+ 
+ 			outb(APCI1500_RW_PORT_B_PATTERN_MASK,
+ 				devpriv->iobase +
+@@ -546,20 +496,16 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-		       /******************************************/
+ 			/* Selects the mode specification mask    */
+ 			/* register of port 2                     */
+-		       /******************************************/
+ 			outb(APCI1500_RW_PORT_B_SPECIFICATION,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+ 			i_RegValue =
+ 				inb(devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+-		       /******************************************/
+ 			/* Selects the mode specification mask    */
+ 			/* register of port 2                     */
+-		       /******************************************/
+ 			outb(APCI1500_RW_PORT_B_SPECIFICATION,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+@@ -569,16 +515,12 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+ 
+ 			i_Event2Status = 1;
+-		       /*****************************************************************/
+ 			/* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+-		       /*****************************************************************/
+ 
+ 			outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+-		       /*****************/
+ 			/* Enable Port B */
+-		       /*****************/
+ 
+ 			outb(0xF4,
+ 				devpriv->iobase +
+@@ -627,48 +569,30 @@ static int i_APCI1500_StartStopInputEvent(struct comedi_device *dev,
+ 
+ 	switch (data[0]) {
+ 	case START:
+-	      /*************************/
+ 		/* Tests the port number */
+-	      /*************************/
+ 
+ 		if (data[1] == 1 || data[1] == 2) {
+-		  /***************************/
+ 			/* Test if port 1 selected */
+-		  /***************************/
+ 
+ 			if (data[1] == 1) {
+-		    /*****************************/
+ 				/* Test if event initialised */
+-		    /*****************************/
+ 				if (i_Event1Status == 1) {
+-		       /*****************************************************************/
+ 					/* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+-		       /*****************************************************************/
+ 					outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-		       /******************/
+ 					/* Disable Port A */
+-		       /******************/
+ 					outb(0xF0,
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+-		       /***************************************************/
+ 					/* Selects the command and status register of      */
+ 					/* port 1                                          */
+-		       /***************************************************/
+ 					outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-		       /*************************************/
+ 					/* Allows the pattern interrupt      */
+-		       /*************************************/
+ 					outb(0xC0,
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+-		       /*****************************************************************/
+ 					/* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+-		       /*****************************************************************/
+ 					outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-		       /*****************/
+ 					/* Enable Port A */
+-		       /*****************/
+ 					outb(0xF4,
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+@@ -681,11 +605,8 @@ static int i_APCI1500_StartStopInputEvent(struct comedi_device *dev,
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+ 
+ 					/* Selects the master interrupt control register */
+-		       /*************************************************/
+ 					outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-		       /**********************************************/
+ 					/* Authorizes the main interrupt on the board */
+-		       /**********************************************/
+ 					outb(0xD0,
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+@@ -700,44 +621,29 @@ static int i_APCI1500_StartStopInputEvent(struct comedi_device *dev,
+ 			if (data[1] == 2) {
+ 
+ 				if (i_Event2Status == 1) {
+-			    /*****************************************************************/
+ 					/* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+-			    /*****************************************************************/
+ 					outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-		       /******************/
+ 					/* Disable Port B */
+-		       /******************/
+ 					outb(0x74,
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+-		       /***************************************************/
+ 					/* Selects the command and status register of      */
+ 					/* port 2                                          */
+-		       /***************************************************/
+ 					outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-		       /*************************************/
+ 					/* Allows the pattern interrupt      */
+-		       /*************************************/
+ 					outb(0xC0,
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+-		       /*****************************************************************/
+ 					/* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+-		       /*****************************************************************/
+ 					outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-		       /*****************/
+ 					/* Enable Port B */
+-		       /*****************/
+ 					outb(0xF4,
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+ 
+ 					/* Selects the master interrupt control register */
+-		       /*************************************************/
+ 					outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-		       /**********************************************/
+ 					/* Authorizes the main interrupt on the board */
+-		       /**********************************************/
+ 					outb(0xD0,
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+@@ -759,48 +665,30 @@ static int i_APCI1500_StartStopInputEvent(struct comedi_device *dev,
+ 		break;
+ 
+ 	case STOP:
+-		  /*************************/
+ 		/* Tests the port number */
+-		  /*************************/
+ 
+ 		if (data[1] == 1 || data[1] == 2) {
+-		  /***************************/
+ 			/* Test if port 1 selected */
+-		  /***************************/
+ 
+ 			if (data[1] == 1) {
+-		    /*****************************/
+ 				/* Test if event initialised */
+-		    /*****************************/
+ 				if (i_Event1Status == 1) {
+-		       /*****************************************************************/
+ 					/* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+-		       /*****************************************************************/
+ 					outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-		       /******************/
+ 					/* Disable Port A */
+-		       /******************/
+ 					outb(0xF0,
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+-		       /***************************************************/
+ 					/* Selects the command and status register of      */
+ 					/* port 1                                          */
+-		       /***************************************************/
+ 					outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-		       /*************************************/
+ 					/* Inhibits the pattern interrupt      */
+-		       /*************************************/
+ 					outb(0xE0,
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+-		       /*****************************************************************/
+ 					/* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+-		       /*****************************************************************/
+ 					outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-		       /*****************/
+ 					/* Enable Port A */
+-		       /*****************/
+ 					outb(0xF4,
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+@@ -813,38 +701,24 @@ static int i_APCI1500_StartStopInputEvent(struct comedi_device *dev,
+ 				}	/* else if(i_Event1Status==1) */
+ 			}	/* if (data[1]==1) */
+ 			if (data[1] == 2) {
+-			 /*****************************/
+ 				/* Test if event initialised */
+-			 /*****************************/
+ 				if (i_Event2Status == 1) {
+-			  /*****************************************************************/
+ 					/* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+-			  /*****************************************************************/
+ 					outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-			  /******************/
+ 					/* Disable Port B */
+-			  /******************/
+ 					outb(0x74,
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+-			  /***************************************************/
+ 					/* Selects the command and status register of      */
+ 					/* port 2                                         */
+-			  /***************************************************/
+ 					outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-		       /*************************************/
+ 					/* Inhibits the pattern interrupt      */
+-		       /*************************************/
+ 					outb(0xE0,
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+-		       /*****************************************************************/
+ 					/* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+-		       /*****************************************************************/
+ 					outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-		       /*****************/
+ 					/* Enable Port B */
+-		       /*****************/
+ 					outb(0xF4,
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+@@ -900,9 +774,7 @@ static int i_APCI1500_Initialisation(struct comedi_device *dev,
+ 	struct addi_private *devpriv = dev->private;
+ 	int i_DummyRead = 0;
+ 
+-    /******************/
+ 	/* Software reset */
+-    /******************/
+ 	i_DummyRead = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	i_DummyRead = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+@@ -910,16 +782,12 @@ static int i_APCI1500_Initialisation(struct comedi_device *dev,
+ 	outb(1, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 
+- /*****************************************************/
+ 	/* Selects the master configuration control register */
+- /*****************************************************/
+ 	outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	outb(0xF4, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-	/*****************************************************/
+ 	/* Selects the mode specification register of port A */
+-	/*****************************************************/
+ 	outb(APCI1500_RW_PORT_A_SPECIFICATION,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	outb(0x10, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+@@ -951,9 +819,7 @@ static int i_APCI1500_Initialisation(struct comedi_device *dev,
+ 	/* Deletes the register */
+ 	outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-	 /*****************************************************/
+ 	/* Selects the mode specification register of port B */
+-	 /*****************************************************/
+ 	outb(APCI1500_RW_PORT_B_SPECIFICATION,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	outb(0x10, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+@@ -983,9 +849,7 @@ static int i_APCI1500_Initialisation(struct comedi_device *dev,
+ 	/* Deletes the register */
+ 	outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-	   /*****************************************************/
+ 	/* Selects the data path polarity register of port C */
+-	   /*****************************************************/
+ 	outb(APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	/* High level of port C means 1 */
+@@ -1000,9 +864,7 @@ static int i_APCI1500_Initialisation(struct comedi_device *dev,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	/* Deletes it */
+ 	outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-	   /******************************************************/
+ 	/* Selects the command and status register of timer 1 */
+-	   /******************************************************/
+ 	outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	/* Deletes IP and IUS */
+@@ -1012,9 +874,7 @@ static int i_APCI1500_Initialisation(struct comedi_device *dev,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	/* Deactivates the interrupt management of timer 1         */
+ 	outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-	   /******************************************************/
+ 	/* Selects the command and status register of timer 2 */
+-	   /******************************************************/
+ 	outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	/* Deletes IP and IUS */
+@@ -1024,9 +884,7 @@ static int i_APCI1500_Initialisation(struct comedi_device *dev,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	/* Deactivates Timer 2 interrupt management:               */
+ 	outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-	  /******************************************************/
+ 	/* Selects the command and status register of timer 3 */
+-	  /******************************************************/
+ 	outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	/* Deletes IP and IUS */
+@@ -1036,9 +894,7 @@ static int i_APCI1500_Initialisation(struct comedi_device *dev,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	/* Deactivates interrupt management of timer 3:            */
+ 	outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-	 /*************************************************/
+ 	/* Selects the master interrupt control register */
+-	 /*************************************************/
+ 	outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	/* Deletes all interrupts */
+@@ -1368,123 +1224,91 @@ static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
+ 		}		/*  switch(data[4]) */
+ 
+ 		i_TimerCounterMode = data[2] | data[4] | 7;
+-			 /*************************/
+ 		/* Test the reload value */
+-			 /*************************/
+ 
+ 		if ((data[3] >= 0) && (data[3] <= 65535)) {
+ 			if (data[7] == APCI1500_ENABLE
+ 				|| data[7] == APCI1500_DISABLE) {
+ 
+-				/************************************************/
+ 				/* Selects the mode register of timer/counter 1 */
+-				/************************************************/
+ 				outb(APCI1500_RW_CPT_TMR1_MODE_SPECIFICATION,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+-				/***********************/
+ 				/* Writes the new mode */
+-				/***********************/
+ 				outb(i_TimerCounterMode,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				/****************************************************/
+ 				/* Selects the constant register of timer/counter 1 */
+-				/****************************************************/
+ 
+ 				outb(APCI1500_RW_CPT_TMR1_TIME_CST_LOW,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				  /*************************/
+ 				/* Writes the low value  */
+-				  /*************************/
+ 
+ 				outb(data[3],
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				   /****************************************************/
+ 				/* Selects the constant register of timer/counter 1 */
+-				   /****************************************************/
+ 
+ 				outb(APCI1500_RW_CPT_TMR1_TIME_CST_HIGH,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				  /**************************/
+ 				/* Writes the high value  */
+-				  /**************************/
+ 
+ 				data[3] = data[3] >> 8;
+ 				outb(data[3],
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				     /*********************************************/
+ 				/* Selects the master configuration register */
+-				     /*********************************************/
+ 
+ 				outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				     /**********************/
+ 				/* Reads the register */
+-				     /**********************/
+ 
+ 				i_MasterConfiguration =
+ 					inb(devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				       /********************************************************/
+ 				/* Enables timer/counter 1 and triggers timer/counter 1 */
+-				       /********************************************************/
+ 
+ 				i_MasterConfiguration =
+ 					i_MasterConfiguration | 0x40;
+ 
+-				    /*********************************************/
+ 				/* Selects the master configuration register */
+-				    /*********************************************/
+ 				outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				      /********************************/
+ 				/* Writes the new configuration */
+-				      /********************************/
+ 				outb(i_MasterConfiguration,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+-					 /****************************************/
+ 				/* Selects the commands register of     */
+ 				/* timer/counter 1                      */
+-					 /****************************************/
+ 
+ 				outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				       /***************************/
+ 				/* Disable timer/counter 1 */
+-				       /***************************/
+ 
+ 				outb(0x0,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+-					  /****************************************/
+ 				/* Selects the commands register of     */
+ 				/* timer/counter 1                      */
+-					  /****************************************/
+ 				outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				      /***************************/
+ 				/* Trigger timer/counter 1 */
+-				      /***************************/
+ 				outb(0x2,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+@@ -1562,123 +1386,91 @@ static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
+ 
+ 		i_TimerCounterMode = data[2] | data[4] | data[5] | data[6] | 7;
+ 
+-			     /*************************/
+ 		/* Test the reload value */
+-			     /*************************/
+ 
+ 		if ((data[3] >= 0) && (data[3] <= 65535)) {
+ 			if (data[7] == APCI1500_ENABLE
+ 				|| data[7] == APCI1500_DISABLE) {
+ 
+-				/************************************************/
+ 				/* Selects the mode register of timer/counter 2 */
+-				/************************************************/
+ 				outb(APCI1500_RW_CPT_TMR2_MODE_SPECIFICATION,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+-				/***********************/
+ 				/* Writes the new mode */
+-				/***********************/
+ 				outb(i_TimerCounterMode,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				/****************************************************/
+ 				/* Selects the constant register of timer/counter 2 */
+-				/****************************************************/
+ 
+ 				outb(APCI1500_RW_CPT_TMR2_TIME_CST_LOW,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				  /*************************/
+ 				/* Writes the low value  */
+-				  /*************************/
+ 
+ 				outb(data[3],
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				   /****************************************************/
+ 				/* Selects the constant register of timer/counter 2 */
+-				   /****************************************************/
+ 
+ 				outb(APCI1500_RW_CPT_TMR2_TIME_CST_HIGH,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				  /**************************/
+ 				/* Writes the high value  */
+-				  /**************************/
+ 
+ 				data[3] = data[3] >> 8;
+ 				outb(data[3],
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				     /*********************************************/
+ 				/* Selects the master configuration register */
+-				     /*********************************************/
+ 
+ 				outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				     /**********************/
+ 				/* Reads the register */
+-				     /**********************/
+ 
+ 				i_MasterConfiguration =
+ 					inb(devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				       /********************************************************/
+ 				/* Enables timer/counter 2 and triggers timer/counter 2 */
+-				       /********************************************************/
+ 
+ 				i_MasterConfiguration =
+ 					i_MasterConfiguration | 0x20;
+ 
+-				    /*********************************************/
+ 				/* Selects the master configuration register */
+-				    /*********************************************/
+ 				outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				      /********************************/
+ 				/* Writes the new configuration */
+-				      /********************************/
+ 				outb(i_MasterConfiguration,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+-					 /****************************************/
+ 				/* Selects the commands register of     */
+ 				/* timer/counter 2                      */
+-					 /****************************************/
+ 
+ 				outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				       /***************************/
+ 				/* Disable timer/counter 2 */
+-				       /***************************/
+ 
+ 				outb(0x0,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+-					  /****************************************/
+ 				/* Selects the commands register of     */
+ 				/* timer/counter 2                      */
+-					  /****************************************/
+ 				outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				      /***************************/
+ 				/* Trigger timer/counter 1 */
+-				      /***************************/
+ 				outb(0x2,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+@@ -1740,142 +1532,104 @@ static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
+ 			return -EINVAL;
+ 		}		/*  switch(data[6]) */
+ 
+-		      /*****************************/
+ 		/* Test if used for watchdog */
+-			  /*****************************/
+ 
+ 		if (data[2] == APCI1500_WATCHDOG) {
+-			     /*****************************/
+ 			/* - Enables the output line */
+ 			/* - Enables retrigger       */
+ 			/* - Pulses output           */
+-			     /*****************************/
+ 			i_TimerCounterMode = data[2] | data[4] | 0x54;
+ 		}		/* if (data[2] == APCI1500_WATCHDOG) */
+ 		else {
+ 			i_TimerCounterMode = data[2] | data[4] | data[6] | 7;
+ 		}		/* elseif (data[2] == APCI1500_WATCHDOG) */
+-				 /*************************/
+ 		/* Test the reload value */
+-			     /*************************/
+ 
+ 		if ((data[3] >= 0) && (data[3] <= 65535)) {
+ 			if (data[7] == APCI1500_ENABLE
+ 				|| data[7] == APCI1500_DISABLE) {
+ 
+-				/************************************************/
+ 				/* Selects the mode register of watchdog/counter 3 */
+-				/************************************************/
+ 				outb(APCI1500_RW_CPT_TMR3_MODE_SPECIFICATION,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+-				/***********************/
+ 				/* Writes the new mode */
+-				/***********************/
+ 				outb(i_TimerCounterMode,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				/****************************************************/
+ 				/* Selects the constant register of watchdog/counter 3 */
+-				/****************************************************/
+ 
+ 				outb(APCI1500_RW_CPT_TMR3_TIME_CST_LOW,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				  /*************************/
+ 				/* Writes the low value  */
+-				  /*************************/
+ 
+ 				outb(data[3],
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				   /****************************************************/
+ 				/* Selects the constant register of watchdog/counter 3 */
+-				   /****************************************************/
+ 
+ 				outb(APCI1500_RW_CPT_TMR3_TIME_CST_HIGH,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				  /**************************/
+ 				/* Writes the high value  */
+-				  /**************************/
+ 
+ 				data[3] = data[3] >> 8;
+ 				outb(data[3],
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				     /*********************************************/
+ 				/* Selects the master configuration register */
+-				     /*********************************************/
+ 
+ 				outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				     /**********************/
+ 				/* Reads the register */
+-				     /**********************/
+ 
+ 				i_MasterConfiguration =
+ 					inb(devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				       /********************************************************/
+ 				/* Enables watchdog/counter 3 and triggers watchdog/counter 3 */
+-				       /********************************************************/
+ 
+ 				i_MasterConfiguration =
+ 					i_MasterConfiguration | 0x10;
+ 
+-				    /*********************************************/
+ 				/* Selects the master configuration register */
+-				    /*********************************************/
+ 				outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				      /********************************/
+ 				/* Writes the new configuration */
+-				      /********************************/
+ 				outb(i_MasterConfiguration,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				      /********************/
+ 				/* Test if COUNTER */
+-					  /********************/
+ 				if (data[2] == APCI1500_COUNTER) {
+ 
+-					    /*************************************/
+ 					/* Selects the command register of   */
+ 					/* watchdog/counter 3                */
+-						 /*************************************/
+ 					outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+-					      /*************************************************/
+ 					/* Disable the  watchdog/counter 3 and starts it */
+-						  /*************************************************/
+ 					outb(0x0,
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-					      /*************************************/
+ 					/* Selects the command register of   */
+ 					/* watchdog/counter 3                */
+-						  /*************************************/
+ 
+ 					outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+-					     /*************************************************/
+ 					/* Trigger the  watchdog/counter 3 and starts it */
+-						 /*************************************************/
+ 					outb(0x2,
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+@@ -1953,13 +1707,9 @@ static int i_apci1500_timer_watchdog(struct comedi_device *dev,
+ 				else {
+ 					i_CommandAndStatusValue = 0xE4;	/* disable the interrupt */
+ 				}	/* elseif(i_TimerCounterWatchdogInterrupt==1) */
+-					      /**************************/
+ 				/* Starts timer/counter 1 */
+-					      /**************************/
+ 				i_TimerCounter1Enabled = 1;
+-						/********************************************/
+ 				/* Selects the commands and status register */
+-						/********************************************/
+ 				outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+@@ -1976,13 +1726,9 @@ static int i_apci1500_timer_watchdog(struct comedi_device *dev,
+ 
+ 		case STOP:
+ 
+-					      /**************************/
+ 			/* Stop timer/counter 1 */
+-					      /**************************/
+ 
+-						/********************************************/
+ 			/* Selects the commands and status register */
+-						/********************************************/
+ 			outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+@@ -1995,23 +1741,17 @@ static int i_apci1500_timer_watchdog(struct comedi_device *dev,
+ 		case TRIGGER:
+ 			if (i_TimerCounter1Init == 1) {
+ 				if (i_TimerCounter1Enabled == 1) {
+-						 /************************/
+ 					/* Set Trigger and gate */
+-						 /************************/
+ 
+ 					i_CommandAndStatusValue = 0x6;
+ 				}	/* if( i_TimerCounter1Enabled==1) */
+ 				else {
+-						   /***************/
+ 					/* Set Trigger */
+-						   /***************/
+ 
+ 					i_CommandAndStatusValue = 0x2;
+ 				}	/* elseif(i_TimerCounter1Enabled==1) */
+ 
+-						/********************************************/
+ 				/* Selects the commands and status register */
+-						/********************************************/
+ 				outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+@@ -2043,13 +1783,9 @@ static int i_apci1500_timer_watchdog(struct comedi_device *dev,
+ 				else {
+ 					i_CommandAndStatusValue = 0xE4;	/* disable the interrupt */
+ 				}	/* elseif(i_TimerCounterWatchdogInterrupt==1) */
+-					      /**************************/
+ 				/* Starts timer/counter 2 */
+-					      /**************************/
+ 				i_TimerCounter2Enabled = 1;
+-						/********************************************/
+ 				/* Selects the commands and status register */
+-						/********************************************/
+ 				outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+@@ -2066,13 +1802,9 @@ static int i_apci1500_timer_watchdog(struct comedi_device *dev,
+ 
+ 		case STOP:
+ 
+-					      /**************************/
+ 			/* Stop timer/counter 2 */
+-					      /**************************/
+ 
+-						/********************************************/
+ 			/* Selects the commands and status register */
+-						/********************************************/
+ 			outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+@@ -2084,23 +1816,17 @@ static int i_apci1500_timer_watchdog(struct comedi_device *dev,
+ 		case TRIGGER:
+ 			if (i_TimerCounter2Init == 1) {
+ 				if (i_TimerCounter2Enabled == 1) {
+-						 /************************/
+ 					/* Set Trigger and gate */
+-						 /************************/
+ 
+ 					i_CommandAndStatusValue = 0x6;
+ 				}	/* if( i_TimerCounter2Enabled==1) */
+ 				else {
+-						   /***************/
+ 					/* Set Trigger */
+-						   /***************/
+ 
+ 					i_CommandAndStatusValue = 0x2;
+ 				}	/* elseif(i_TimerCounter2Enabled==1) */
+ 
+-						/********************************************/
+ 				/* Selects the commands and status register */
+-						/********************************************/
+ 				outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+@@ -2131,13 +1857,9 @@ static int i_apci1500_timer_watchdog(struct comedi_device *dev,
+ 				else {
+ 					i_CommandAndStatusValue = 0xE4;	/* disable the interrupt */
+ 				}	/* elseif(i_TimerCounterWatchdogInterrupt==1) */
+-					      /**************************/
+ 				/* Starts Watchdog/counter 3 */
+-					      /**************************/
+ 				i_WatchdogCounter3Enabled = 1;
+-						/********************************************/
+ 				/* Selects the commands and status register */
+-						/********************************************/
+ 				outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+@@ -2155,13 +1877,9 @@ static int i_apci1500_timer_watchdog(struct comedi_device *dev,
+ 
+ 		case STOP:
+ 
+-					      /**************************/
+ 			/* Stop Watchdog/counter 3 */
+-					      /**************************/
+ 
+-						/********************************************/
+ 			/* Selects the commands and status register */
+-						/********************************************/
+ 			outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+@@ -2176,23 +1894,17 @@ static int i_apci1500_timer_watchdog(struct comedi_device *dev,
+ 			case 0:	/* triggering counter 3 */
+ 				if (i_WatchdogCounter3Init == 1) {
+ 					if (i_WatchdogCounter3Enabled == 1) {
+-							       /************************/
+ 						/* Set Trigger and gate */
+-							       /************************/
+ 
+ 						i_CommandAndStatusValue = 0x6;
+ 					}	/* if( i_WatchdogCounter3Enabled==1) */
+ 					else {
+-							   /***************/
+ 						/* Set Trigger */
+-							   /***************/
+ 
+ 						i_CommandAndStatusValue = 0x2;
+ 					}	/* elseif(i_WatchdogCounter3Enabled==1) */
+ 
+-						/********************************************/
+ 					/* Selects the commands and status register */
+-						/********************************************/
+ 					outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+@@ -2210,9 +1922,7 @@ static int i_apci1500_timer_watchdog(struct comedi_device *dev,
+ 				/* triggering Watchdog 3 */
+ 				if (i_WatchdogCounter3Init == 1) {
+ 
+-						/********************************************/
+ 					/* Selects the commands and status register */
+-						/********************************************/
+ 					outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+@@ -2283,23 +1993,17 @@ static int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device *dev,
+ 		/* Read counter/timer1 */
+ 		if (i_TimerCounter1Init == 1) {
+ 			if (i_TimerCounter1Enabled == 1) {
+-		  /************************/
+ 				/* Set RCC and gate */
+-		  /************************/
+ 
+ 				i_CommandAndStatusValue = 0xC;
+ 			}	/* if( i_TimerCounter1Init==1) */
+ 			else {
+-		    /***************/
+ 				/* Set RCC */
+-		    /***************/
+ 
+ 				i_CommandAndStatusValue = 0x8;
+ 			}	/* elseif(i_TimerCounter1Init==1) */
+ 
+-		/********************************************/
+ 			/* Selects the commands and status register */
+-		/********************************************/
+ 			outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+@@ -2307,9 +2011,7 @@ static int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device *dev,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-		 /***************************************/
+ 			/* Selects the counter register (high) */
+-		 /***************************************/
+ 			outb(APCI1500_R_CPT_TMR1_VALUE_HIGH,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+@@ -2335,23 +2037,17 @@ static int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device *dev,
+ 		/* Read counter/timer2 */
+ 		if (i_TimerCounter2Init == 1) {
+ 			if (i_TimerCounter2Enabled == 1) {
+-		  /************************/
+ 				/* Set RCC and gate */
+-		  /************************/
+ 
+ 				i_CommandAndStatusValue = 0xC;
+ 			}	/* if( i_TimerCounter2Init==1) */
+ 			else {
+-		    /***************/
+ 				/* Set RCC */
+-		    /***************/
+ 
+ 				i_CommandAndStatusValue = 0x8;
+ 			}	/* elseif(i_TimerCounter2Init==1) */
+ 
+-		/********************************************/
+ 			/* Selects the commands and status register */
+-		/********************************************/
+ 			outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+@@ -2359,9 +2055,7 @@ static int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device *dev,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-		 /***************************************/
+ 			/* Selects the counter register (high) */
+-		 /***************************************/
+ 			outb(APCI1500_R_CPT_TMR2_VALUE_HIGH,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+@@ -2387,23 +2081,17 @@ static int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device *dev,
+ 		/* Read counter/watchdog2 */
+ 		if (i_WatchdogCounter3Init == 1) {
+ 			if (i_WatchdogCounter3Enabled == 1) {
+-		  /************************/
+ 				/* Set RCC and gate */
+-		  /************************/
+ 
+ 				i_CommandAndStatusValue = 0xC;
+ 			}	/* if( i_TimerCounter2Init==1) */
+ 			else {
+-		    /***************/
+ 				/* Set RCC */
+-		    /***************/
+ 
+ 				i_CommandAndStatusValue = 0x8;
+ 			}	/* elseif(i_WatchdogCounter3Init==1) */
+ 
+-		/********************************************/
+ 			/* Selects the commands and status register */
+-		/********************************************/
+ 			outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+@@ -2411,9 +2099,7 @@ static int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device *dev,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-		 /***************************************/
+ 			/* Selects the counter register (high) */
+-		 /***************************************/
+ 			outb(APCI1500_R_CPT_TMR3_VALUE_HIGH,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+@@ -2525,135 +2211,95 @@ static int i_APCI1500_ConfigureInterrupt(struct comedi_device *dev,
+ 		}		/* else if(data[0]==0) */
+ 	}			/* elseif(data[0]==1) */
+ 
+-	 /*****************************************************/
+ 	/* Selects the mode specification register of port B */
+-	 /*****************************************************/
+ 	outb(APCI1500_RW_PORT_B_SPECIFICATION,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	outb(APCI1500_RW_PORT_B_SPECIFICATION,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-      /*********************************************/
+ 	/* Writes the new configuration (APCI1500_OR) */
+-      /*********************************************/
+ 	i_RegValue = (i_RegValue & 0xF9) | APCI1500_OR;
+ 
+ 	outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-       /*****************************************************/
+ 	/* Selects the command and status register of port B */
+-       /*****************************************************/
+ 	outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-	/*****************************************/
+ 	/* Authorises the interrupt on the board */
+-	/*****************************************/
+ 	outb(0xC0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-	/***************************************************/
+ 	/* Selects the pattern polarity register of port B */
+-	/***************************************************/
+ 	outb(APCI1500_RW_PORT_B_PATTERN_POLARITY,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	outb(i_Constant, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-	/*****************************************************/
+ 	/* Selects the pattern transition register of port B */
+-	/*****************************************************/
+ 	outb(APCI1500_RW_PORT_B_PATTERN_TRANSITION,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	outb(i_Constant, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-	/***********************************************/
+ 	/* Selects the pattern mask register of port B */
+-	/***********************************************/
+ 	outb(APCI1500_RW_PORT_B_PATTERN_MASK,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	outb(i_Constant, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-	/*****************************************************/
+ 	/* Selects the command and status register of port A */
+-	/*****************************************************/
+ 	outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-	 /***********************************/
+ 	/* Deletes the interrupt of port A */
+-	 /***********************************/
+ 
+ 	i_RegValue = (i_RegValue & 0x0F) | 0x20;
+ 	outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-	/*****************************************************/
+ 	/* Selects the command and status register of port  B */
+-	/*****************************************************/
+ 	outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-	 /***********************************/
+ 	/* Deletes the interrupt of port B */
+-	 /***********************************/
+ 
+ 	i_RegValue = (i_RegValue & 0x0F) | 0x20;
+ 	outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-	/*****************************************************/
+ 	/* Selects the command and status register of timer 1 */
+-	/*****************************************************/
+ 	outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-	 /***********************************/
+ 	/* Deletes the interrupt of timer 1 */
+-	 /***********************************/
+ 
+ 	i_RegValue = (i_RegValue & 0x0F) | 0x20;
+ 	outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-	 /*****************************************************/
+ 	/* Selects the command and status register of timer 2 */
+-	/*****************************************************/
+ 	outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-	 /***********************************/
+ 	/* Deletes the interrupt of timer 2 */
+-	 /***********************************/
+ 
+ 	i_RegValue = (i_RegValue & 0x0F) | 0x20;
+ 	outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-	/*****************************************************/
+ 	/* Selects the command and status register of timer 3 */
+-	/*****************************************************/
+ 	outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-	 /***********************************/
+ 	/* Deletes the interrupt of timer 3 */
+-	 /***********************************/
+ 
+ 	i_RegValue = (i_RegValue & 0x0F) | 0x20;
+ 	outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-	 /*************************************************/
+ 	/* Selects the master interrupt control register */
+-	 /*************************************************/
+ 	outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-	/**********************************************/
+ 	/* Authorizes the main interrupt on the board */
+-	/**********************************************/
+ 	outb(0xD0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-      /***************************/
+ 	/* Enables the PCI interrupt */
+-      /*****************************/
+ 	outl(0x3000, devpriv->i_IobaseAmcc + 0x38);
+ 	ui_Status = inl(devpriv->i_IobaseAmcc + 0x10);
+ 	ui_Status = inl(devpriv->i_IobaseAmcc + 0x38);
+@@ -2688,44 +2334,28 @@ static void v_APCI1500_Interrupt(int irq, void *d)
+ 	int i_RegValue = 0;
+ 	i_InterruptMask = 0;
+ 
+- /***********************************/
+ 	/* Read the board interrupt status */
+- /***********************************/
+ 	ui_InterruptStatus = inl(devpriv->i_IobaseAmcc + 0x38);
+ 
+-  /***************************************/
+ 	/* Test if board generated a interrupt */
+-  /***************************************/
+ 	if ((ui_InterruptStatus & 0x800000) == 0x800000) {
+-      /************************/
+ 		/* Disable all Interrupt */
+-      /************************/
+-      /*************************************************/
+ 		/* Selects the master interrupt control register */
+-      /*************************************************/
+ 		/* outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); */
+-	/**********************************************/
+ 		/* Disables  the main interrupt on the board */
+-	/**********************************************/
+ 		/* outb(0x00,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); */
+ 
+-   /*****************************************************/
+ 		/* Selects the command and status register of port A */
+-   /*****************************************************/
+ 		outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
+ 			devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 		i_RegValue =
+ 			inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 		if ((i_RegValue & 0x60) == 0x60) {
+-	   /*****************************************************/
+ 			/* Selects the command and status register of port A */
+-	   /*****************************************************/
+ 			outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+-	    /***********************************/
+ 			/* Deletes the interrupt of port A */
+-	    /***********************************/
+ 			i_RegValue = (i_RegValue & 0x0F) | 0x20;
+ 			outb(i_RegValue,
+ 				devpriv->iobase +
+@@ -2739,9 +2369,7 @@ static void v_APCI1500_Interrupt(int irq, void *d)
+ 					inb(devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-	      /***************************************************/
+ 				/* Selects the interrupt vector register of port A */
+-	      /***************************************************/
+ 				outb(APCI1500_RW_PORT_A_INTERRUPT_CONTROL,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+@@ -2757,44 +2385,32 @@ static void v_APCI1500_Interrupt(int irq, void *d)
+ 			}	/* elseif(i_Logic==APCI1500_OR_PRIORITY) */
+ 		}		/*  if ((i_RegValue & 0x60) == 0x60) */
+ 
+-	   /*****************************************************/
+ 		/* Selects the command and status register of port B */
+-	   /*****************************************************/
+ 		outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+ 			devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 		i_RegValue =
+ 			inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 		if ((i_RegValue & 0x60) == 0x60) {
+-	     /*****************************************************/
+ 			/* Selects the command and status register of port B */
+-	     /*****************************************************/
+ 			outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+-	     /***********************************/
+ 			/* Deletes the interrupt of port B */
+-	     /***********************************/
+ 			i_RegValue = (i_RegValue & 0x0F) | 0x20;
+ 			outb(i_RegValue,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+-	     /****************/
+ 			/* Reads port B */
+-	     /****************/
+ 			i_RegValue =
+ 				inb((unsigned int) devpriv->iobase +
+ 				APCI1500_Z8536_PORT_B);
+ 
+ 			i_RegValue = i_RegValue & 0xC0;
+-	      /**************************************/
+ 			/* Tests if this is an external error */
+-	      /**************************************/
+ 
+ 			if (i_RegValue) {
+ 				/* Disable the interrupt */
+-		     /*****************************************************/
+ 				/* Selects the command and status register of port B */
+-		     /*****************************************************/
+ 				outl(0x0, devpriv->i_IobaseAmcc + 0x38);
+ 
+ 				if (i_RegValue & 0x80) {
+@@ -2812,46 +2428,34 @@ static void v_APCI1500_Interrupt(int irq, void *d)
+ 			}	/*  if (i_RegValue) */
+ 		}		/* if ((i_RegValue & 0x60) == 0x60) */
+ 
+-		/*****************************************************/
+ 		/* Selects the command and status register of timer 1 */
+-		/*****************************************************/
+ 		outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ 			devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 		i_RegValue =
+ 			inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 		if ((i_RegValue & 0x60) == 0x60) {
+-		   /*****************************************************/
+ 			/* Selects the command and status register of timer 1 */
+-		   /*****************************************************/
+ 			outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+-		   /***********************************/
+ 			/* Deletes the interrupt of timer 1 */
+-		   /***********************************/
+ 			i_RegValue = (i_RegValue & 0x0F) | 0x20;
+ 			outb(i_RegValue,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+ 			i_InterruptMask = i_InterruptMask | 4;
+ 		}		/*  if ((i_RegValue & 0x60) == 0x60) */
+-		/*****************************************************/
+ 		/* Selects the command and status register of timer 2 */
+-		/*****************************************************/
+ 		outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ 			devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 		i_RegValue =
+ 			inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 		if ((i_RegValue & 0x60) == 0x60) {
+-		   /*****************************************************/
+ 			/* Selects the command and status register of timer 2 */
+-		   /*****************************************************/
+ 			outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+-		   /***********************************/
+ 			/* Deletes the interrupt of timer 2 */
+-		   /***********************************/
+ 			i_RegValue = (i_RegValue & 0x0F) | 0x20;
+ 			outb(i_RegValue,
+ 				devpriv->iobase +
+@@ -2859,23 +2463,17 @@ static void v_APCI1500_Interrupt(int irq, void *d)
+ 			i_InterruptMask = i_InterruptMask | 8;
+ 		}		/*  if ((i_RegValue & 0x60) == 0x60) */
+ 
+-		/*****************************************************/
+ 		/* Selects the command and status register of timer 3 */
+-		/*****************************************************/
+ 		outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ 			devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 		i_RegValue =
+ 			inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 		if ((i_RegValue & 0x60) == 0x60) {
+-		   /*****************************************************/
+ 			/* Selects the command and status register of timer 3 */
+-		   /*****************************************************/
+ 			outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+-		   /***********************************/
+ 			/* Deletes the interrupt of timer 3 */
+-		   /***********************************/
+ 			i_RegValue = (i_RegValue & 0x0F) | 0x20;
+ 			outb(i_RegValue,
+ 				devpriv->iobase +
+@@ -2889,18 +2487,12 @@ static void v_APCI1500_Interrupt(int irq, void *d)
+ 		}		/*  if ((i_RegValue & 0x60) == 0x60) */
+ 
+ 		send_sig(SIGIO, devpriv->tsk_Current, 0);	/*  send signal to the sample */
+-	       /***********************/
+ 		/* Enable all Interrupts */
+-	       /***********************/
+ 
+-	       /*************************************************/
+ 		/* Selects the master interrupt control register */
+-	       /*************************************************/
+ 		outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,
+ 			devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-	       /**********************************************/
+ 		/* Authorizes the main interrupt on the board */
+-	       /**********************************************/
+ 		outb(0xD0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	}			/*   if ((ui_InterruptStatus & 0x800000) == 0x800000) */
+ 	else {
+@@ -2944,9 +2536,7 @@ static int i_APCI1500_Reset(struct comedi_device *dev)
+ 	i_TimerCounter2Enabled = 0;
+ 	i_WatchdogCounter3Enabled = 0;
+ 
+-    /******************/
+ 	/* Software reset */
+-    /******************/
+ 	i_DummyRead = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	i_DummyRead = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+@@ -2954,16 +2544,12 @@ static int i_APCI1500_Reset(struct comedi_device *dev)
+ 	outb(1, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 
+- /*****************************************************/
+ 	/* Selects the master configuration control register */
+- /*****************************************************/
+ 	outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	outb(0xF4, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-	/*****************************************************/
+ 	/* Selects the mode specification register of port A */
+-	/*****************************************************/
+ 	outb(APCI1500_RW_PORT_A_SPECIFICATION,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	outb(0x10, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+@@ -2995,9 +2581,7 @@ static int i_APCI1500_Reset(struct comedi_device *dev)
+ 	/* Deletes the register */
+ 	outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-	 /*****************************************************/
+ 	/* Selects the mode specification register of port B */
+-	 /*****************************************************/
+ 	outb(APCI1500_RW_PORT_B_SPECIFICATION,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	outb(0x10, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+@@ -3027,9 +2611,7 @@ static int i_APCI1500_Reset(struct comedi_device *dev)
+ 	/* Deletes the register */
+ 	outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-	   /*****************************************************/
+ 	/* Selects the data path polarity register of port C */
+-	   /*****************************************************/
+ 	outb(APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	/* High level of port C means 1 */
+@@ -3044,9 +2626,7 @@ static int i_APCI1500_Reset(struct comedi_device *dev)
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	/* Deletes it */
+ 	outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-	   /******************************************************/
+ 	/* Selects the command and status register of timer 1 */
+-	   /******************************************************/
+ 	outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	/* Deletes IP and IUS */
+@@ -3056,9 +2636,7 @@ static int i_APCI1500_Reset(struct comedi_device *dev)
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	/* Deactivates the interrupt management of timer 1         */
+ 	outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-	   /******************************************************/
+ 	/* Selects the command and status register of timer 2 */
+-	   /******************************************************/
+ 	outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	/* Deletes IP and IUS */
+@@ -3068,9 +2646,7 @@ static int i_APCI1500_Reset(struct comedi_device *dev)
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	/* Deactivates Timer 2 interrupt management:               */
+ 	outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-	  /******************************************************/
+ 	/* Selects the command and status register of timer 3 */
+-	  /******************************************************/
+ 	outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	/* Deletes IP and IUS */
+@@ -3080,71 +2656,43 @@ static int i_APCI1500_Reset(struct comedi_device *dev)
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	/* Deactivates interrupt management of timer 3:            */
+ 	outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-	 /*************************************************/
+ 	/* Selects the master interrupt control register */
+-	 /*************************************************/
+ 	outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	/* Deletes all interrupts */
+ 	outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	/* reset all the digital outputs */
+ 	outw(0x0, devpriv->i_IobaseAddon + APCI1500_DIGITAL_OP);
+-/*******************************/
+ /* Disable the board interrupt */
+-/*******************************/
+- /*************************************************/
+ 	/* Selects the master interrupt control register */
+- /*************************************************/
+ 	outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-/****************************/
+ /* Deactivates all interrupts */
+-/******************************/
+ 	outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+- /*****************************************************/
+ 	/* Selects the command and status register of port A */
+- /*****************************************************/
+ 	outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-/****************************/
+ /* Deactivates all interrupts */
+-/******************************/
+ 	outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-/*****************************************************/
+ 	/* Selects the command and status register of port B */
+- /*****************************************************/
+ 	outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-/****************************/
+ /* Deactivates all interrupts */
+-/******************************/
+ 	outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-/*****************************************************/
+ 	/* Selects the command and status register of timer 1 */
+- /*****************************************************/
+ 	outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-/****************************/
+ /* Deactivates all interrupts */
+-/******************************/
+ 	outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-/*****************************************************/
+ 	/* Selects the command and status register of timer 2 */
+- /*****************************************************/
+ 	outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-/****************************/
+ /* Deactivates all interrupts */
+-/******************************/
+ 	outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-/*****************************************************/
+ /* Selects the command and status register of timer 3*/
+-/*****************************************************/
+ 	outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-/****************************/
+ /* Deactivates all interrupts */
+-/******************************/
+ 	outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	return 0;
+ }

commit d0ba1e38e05212037b5107522f12537f8168c463
+Author: Conrad Meyer 
+Date:   Sat Mar 8 21:42:39 2014 -0500
+
+    Staging: comedi: Fix some raw printks with dev_warn()
+    
+    Brought to you with the help of sed and manual clean-up after.
+    
+      $ sed -i -e 's|printk("\\n|dev_warn(dev->hw_dev,\n\t"|' \
+        addi-data/hwdrv_apci1500.c
+    
+    Since all of these printk()s were for invalid API inputs and most of
+    them returned -EINVAL, I fixed the rest of them to return -EINVAL as
+    well.
+    
+    Signed-off-by: Conrad Meyer 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+index 2628ac44f109..0ccf784b81a4 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+@@ -259,7 +259,8 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
+ 			i_MaxChannel = 6;
+ 		}		/*  if(data[0]==2) */
+ 		else {
+-			printk("\nThe specified port event  does not exist\n");
++			dev_warn(dev->hw_dev,
++				"The specified port event does not exist\n");
+ 			return -EINVAL;
+ 		}		/* else if(data[0]==2) */
+ 	}			/* else  if (data[0] == 1) */
+@@ -274,7 +275,8 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
+ 		data[1] = APCI1500_OR_PRIORITY;
+ 		break;
+ 	default:
+-		printk("\nThe specified interrupt logic does not exist\n");
++		dev_warn(dev->hw_dev,
++			"The specified interrupt logic does not exist\n");
+ 		return -EINVAL;
+ 	}			/* switch(data[1]); */
+ 
+@@ -318,7 +320,8 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
+ 		case 5:
+ 			break;
+ 		default:
+-			printk("\nThe option indicated in the event mask does not exist\n");
++			dev_warn(dev->hw_dev,
++				"The option indicated in the event mask does not exist\n");
+ 			return -EINVAL;
+ 		}		/*  switch(i_EventMask) */
+ 	}			/* for (i_Count = i_MaxChannel; i_Count >0;i_Count --) */
+@@ -338,10 +341,8 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
+ 
+ 			if (data[1] == APCI1500_OR_PRIORITY
+ 				&& i_PatternTransition != 0) {
+-			      /********************************************/
+-				/* Transition error on an OR PRIORITY logic */
+-			      /********************************************/
+-				printk("\nTransition error on an OR PRIORITY logic\n");
++				dev_warn(dev->hw_dev,
++					"Transition error on an OR PRIORITY logic\n");
+ 				return -EINVAL;
+ 			}	/*  if (data[1]== APCI1500_OR_PRIORITY && i_PatternTransition != 0) */
+ 
+@@ -360,10 +361,8 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
+ 				}	/* for (i_Count = 0; i_Count < 8; i_Count++) */
+ 
+ 				if (i_PatternTransitionCount > 1) {
+-				  /****************************************/
+-					/* Transition error on an AND logic     */
+-				  /****************************************/
+-					printk("\n Transition error on an AND logic\n");
++					dev_warn(dev->hw_dev,
++						"Transition error on an AND logic\n");
+ 					return -EINVAL;
+ 				}	/*  if (i_PatternTransitionCount > 1) */
+ 			}	/*  if (data[1]== APCI1500_AND) */
+@@ -457,7 +456,8 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
+ 
+ 		}		/*  if(data[1]==APCI1500_AND||data[1]==APCI1500_OR||data[1]==APCI1500_OR_PRIORITY) */
+ 		else {
+-			printk("\nThe choice for interrupt logic does not exist\n");
++			dev_warn(dev->hw_dev,
++				"The choice for interrupt logic does not exist\n");
+ 			return -EINVAL;
+ 		}		/*  else }// if(data[1]==APCI1500_AND||data[1]==APCI1500_OR||data[1]==APCI1500_OR_PRIORITY) */
+ 	}			/*    if (data[0]== 1) */
+@@ -585,7 +585,8 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+ 		}		/*   if (data[1] == APCI1500_OR) */
+ 		else {
+-			printk("\nThe choice for interrupt logic does not exist\n");
++			dev_warn(dev->hw_dev,
++				"The choice for interrupt logic does not exist\n");
+ 			return -EINVAL;
+ 		}		/* elseif (data[1] == APCI1500_OR) */
+ 	}			/* if(data[0]==2) */
+@@ -691,7 +692,8 @@ static int i_APCI1500_StartStopInputEvent(struct comedi_device *dev,
+ 
+ 				}	/*  if(i_Event1Status==1) */
+ 				else {
+-					printk("\nEvent 1 not initialised\n");
++					dev_warn(dev->hw_dev,
++						"Event 1 not initialised\n");
+ 					return -EINVAL;
+ 				}	/* else if(i_Event1Status==1) */
+ 			}	/* if (data[1]==1) */
+@@ -742,13 +744,15 @@ static int i_APCI1500_StartStopInputEvent(struct comedi_device *dev,
+ 					i_Event2InterruptStatus = 1;
+ 				}	/*  if(i_Event2Status==1) */
+ 				else {
+-					printk("\nEvent 2 not initialised\n");
++					dev_warn(dev->hw_dev,
++						"Event 2 not initialised\n");
+ 					return -EINVAL;
+ 				}	/* else if(i_Event2Status==1) */
+ 			}	/*  if(data[1]==2) */
+ 		}		/*  if (data[1] == 1 || data[0] == 2) */
+ 		else {
+-			printk("\nThe port parameter is in error\n");
++			dev_warn(dev->hw_dev,
++				"The port parameter is in error\n");
+ 			return -EINVAL;
+ 		}		/* else if (data[1] == 1 || data[0] == 2) */
+ 
+@@ -803,7 +807,8 @@ static int i_APCI1500_StartStopInputEvent(struct comedi_device *dev,
+ 					i_Event1InterruptStatus = 0;
+ 				}	/*  if(i_Event1Status==1) */
+ 				else {
+-					printk("\nEvent 1 not initialised\n");
++					dev_warn(dev->hw_dev,
++						"Event 1 not initialised\n");
+ 					return -EINVAL;
+ 				}	/* else if(i_Event1Status==1) */
+ 			}	/* if (data[1]==1) */
+@@ -846,19 +851,22 @@ static int i_APCI1500_StartStopInputEvent(struct comedi_device *dev,
+ 					i_Event2InterruptStatus = 0;
+ 				}	/*  if(i_Event2Status==1) */
+ 				else {
+-					printk("\nEvent 2 not initialised\n");
++					dev_warn(dev->hw_dev,
++						"Event 2 not initialised\n");
+ 					return -EINVAL;
+ 				}	/* else if(i_Event2Status==1) */
+ 			}	/* if(data[1]==2) */
+ 
+ 		}		/*  if (data[1] == 1 || data[1] == 2) */
+ 		else {
+-			printk("\nThe port parameter is in error\n");
++			dev_warn(dev->hw_dev,
++				"The port parameter is in error\n");
+ 			return -EINVAL;
+ 		}		/* else if (data[1] == 1 || data[1] == 2) */
+ 		break;
+ 	default:
+-		printk("\nThe option of START/STOP logic does not exist\n");
++		dev_warn(dev->hw_dev,
++			"The option of START/STOP logic does not exist\n");
+ 		return -EINVAL;
+ 	}			/* switch(data[0]) */
+ 
+@@ -1164,7 +1172,9 @@ static int i_APCI1500_WriteDigitalOutput(struct comedi_device *dev,
+ 					APCI1500_DIGITAL_OP);
+ 			}	/*  if(data[1]==1) */
+ 			else {
+-				printk("\nSpecified channel not supported\n");
++				dev_warn(dev->hw_dev,
++					"Specified channel not supported\n");
++				return -EINVAL;
+ 			}	/* else if(data[1]==1) */
+ 		}		/* elseif(data[1]==0) */
+ 	}			/* if(data[3]==0) */
+@@ -1241,12 +1251,15 @@ static int i_APCI1500_WriteDigitalOutput(struct comedi_device *dev,
+ 						APCI1500_DIGITAL_OP);
+ 				}	/*  if(data[1]==1) */
+ 				else {
+-					printk("\nSpecified channel not supported\n");
++					dev_warn(dev->hw_dev,
++						"Specified channel not supported\n");
++					return -EINVAL;
+ 				}	/* else if(data[1]==1) */
+ 			}	/* elseif(data[1]==0) */
+ 		}		/* if(data[3]==1); */
+ 		else {
+-			printk("\nSpecified functionality does not exist\n");
++			dev_warn(dev->hw_dev,
++				"Specified functionality does not exist\n");
+ 			return -EINVAL;
+ 		}		/* if else data[3]==1) */
+ 	}			/* if else data[3]==0) */
+@@ -1318,7 +1331,8 @@ static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
+ 	}			/*  if(data[0]==0||data[0]==1||data[0]==2) */
+ 	else {
+ 		if (data[0] != 3) {
+-			printk("\nThe option for input clock selection does not exist\n");
++			dev_warn(dev->hw_dev,
++				"The option for input clock selection does not exist\n");
+ 			return -EINVAL;
+ 		}		/*  if(data[0]!=3) */
+ 	}			/* elseif(data[0]==0||data[0]==1||data[0]==2) */
+@@ -1334,7 +1348,8 @@ static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
+ 			data[2] = APCI1500_TIMER;
+ 			break;
+ 		default:
+-			printk("\nThis choice is not a timer nor a counter\n");
++			dev_warn(dev->hw_dev,
++				"This choice is not a timer nor a counter\n");
+ 			return -EINVAL;
+ 		}		/*  switch(data[2]) */
+ 
+@@ -1347,7 +1362,8 @@ static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
+ 			data[4] = APCI1500_SINGLE;
+ 			break;
+ 		default:
+-			printk("\nThis option for single/continuous mode does not exist\n");
++			dev_warn(dev->hw_dev,
++				"This option for single/continuous mode does not exist\n");
+ 			return -EINVAL;
+ 		}		/*  switch(data[4]) */
+ 
+@@ -1474,12 +1490,14 @@ static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 			}	/* if(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) */
+ 			else {
+-				printk("\nError in selection of interrupt enable or disable\n");
++				dev_warn(dev->hw_dev,
++					"Error in selection of interrupt enable or disable\n");
+ 				return -EINVAL;
+ 			}	/* elseif(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) */
+ 		}		/*  if ((data[3]>= 0) && (data[3] <= 65535)) */
+ 		else {
+-			printk("\nError in selection of reload value\n");
++			dev_warn(dev->hw_dev,
++				"Error in selection of reload value\n");
+ 			return -EINVAL;
+ 		}		/* else if ((data[3]>= 0) && (data[3] <= 65535)) */
+ 		i_TimerCounterWatchdogInterrupt = data[7];
+@@ -1495,7 +1513,8 @@ static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
+ 			data[2] = APCI1500_TIMER;
+ 			break;
+ 		default:
+-			printk("\nThis choice is not a timer nor a counter\n");
++			dev_warn(dev->hw_dev,
++				"This choice is not a timer nor a counter\n");
+ 			return -EINVAL;
+ 		}		/*  switch(data[2]) */
+ 
+@@ -1508,7 +1527,8 @@ static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
+ 			data[4] = APCI1500_SINGLE;
+ 			break;
+ 		default:
+-			printk("\nThis option for single/continuous mode does not exist\n");
++			dev_warn(dev->hw_dev,
++				"This option for single/continuous mode does not exist\n");
+ 			return -EINVAL;
+ 		}		/*  switch(data[4]) */
+ 
+@@ -1521,7 +1541,8 @@ static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
+ 			data[5] = APCI1500_HARDWARE_TRIGGER;
+ 			break;
+ 		default:
+-			printk("\nThis choice for software or hardware trigger does not exist\n");
++			dev_warn(dev->hw_dev,
++				"This choice for software or hardware trigger does not exist\n");
+ 			return -EINVAL;
+ 		}		/*  switch(data[5]) */
+ 
+@@ -1534,7 +1555,8 @@ static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
+ 			data[6] = APCI1500_HARDWARE_GATE;
+ 			break;
+ 		default:
+-			printk("\nThis choice for software or hardware gate does not exist\n");
++			dev_warn(dev->hw_dev,
++				"This choice for software or hardware gate does not exist\n");
+ 			return -EINVAL;
+ 		}		/*  switch(data[6]) */
+ 
+@@ -1662,12 +1684,14 @@ static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 			}	/* if(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) */
+ 			else {
+-				printk("\nError in selection of interrupt enable or disable\n");
++				dev_warn(dev->hw_dev,
++					"Error in selection of interrupt enable or disable\n");
+ 				return -EINVAL;
+ 			}	/* elseif(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) */
+ 		}		/*  if ((data[3]>= 0) && (data[3] <= 65535)) */
+ 		else {
+-			printk("\nError in selection of reload value\n");
++			dev_warn(dev->hw_dev,
++				"Error in selection of reload value\n");
+ 			return -EINVAL;
+ 		}		/* else if ((data[3]>= 0) && (data[3] <= 65535)) */
+ 		i_TimerCounterWatchdogInterrupt = data[7];
+@@ -1683,7 +1707,8 @@ static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
+ 			data[2] = APCI1500_WATCHDOG;
+ 			break;
+ 		default:
+-			printk("\nThis choice is not a watchdog nor a counter\n");
++			dev_warn(dev->hw_dev,
++				"This choice is not a watchdog nor a counter\n");
+ 			return -EINVAL;
+ 		}		/*  switch(data[2]) */
+ 
+@@ -1696,7 +1721,8 @@ static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
+ 			data[4] = APCI1500_SINGLE;
+ 			break;
+ 		default:
+-			printk("\nThis option for single/continuous mode does not exist\n");
++			dev_warn(dev->hw_dev,
++				"This option for single/continuous mode does not exist\n");
+ 			return -EINVAL;
+ 		}		/*  switch(data[4]) */
+ 
+@@ -1709,7 +1735,8 @@ static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
+ 			data[6] = APCI1500_HARDWARE_GATE;
+ 			break;
+ 		default:
+-			printk("\nThis choice for software or hardware gate does not exist\n");
++			dev_warn(dev->hw_dev,
++				"This choice for software or hardware gate does not exist\n");
+ 			return -EINVAL;
+ 		}		/*  switch(data[6]) */
+ 
+@@ -1857,12 +1884,14 @@ static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
+ 
+ 			}	/* if(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) */
+ 			else {
+-				printk("\nError in selection of interrupt enable or disable\n");
++				dev_warn(dev->hw_dev,
++					"Error in selection of interrupt enable or disable\n");
+ 				return -EINVAL;
+ 			}	/* elseif(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) */
+ 		}		/*  if ((data[3]>= 0) && (data[3] <= 65535)) */
+ 		else {
+-			printk("\nError in selection of reload value\n");
++			dev_warn(dev->hw_dev,
++				"Error in selection of reload value\n");
+ 			return -EINVAL;
+ 		}		/* else if ((data[3]>= 0) && (data[3] <= 65535)) */
+ 		i_TimerCounterWatchdogInterrupt = data[7];
+@@ -1870,7 +1899,9 @@ static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
+ 		break;
+ 
+ 	default:
+-		printk("\nThe specified counter\timer option does not exist\n");
++		dev_warn(dev->hw_dev,
++			"The specified counter/timer option does not exist\n");
++		return -EINVAL;
+ 	}			/* switch(data[1]) */
+ 	i_CounterLogic = data[2];
+ 	return insn->n;
+@@ -1937,7 +1968,8 @@ static int i_apci1500_timer_watchdog(struct comedi_device *dev,
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 			}	/* if( i_TimerCounter1Init==1) */
+ 			else {
+-				printk("\nCounter/Timer1 not configured\n");
++				dev_warn(dev->hw_dev,
++					"Counter/Timer1 not configured\n");
+ 				return -EINVAL;
+ 			}
+ 			break;
+@@ -1988,13 +2020,15 @@ static int i_apci1500_timer_watchdog(struct comedi_device *dev,
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 			}	/* if( i_TimerCounter1Init==1) */
+ 			else {
+-				printk("\nCounter/Timer1 not configured\n");
++				dev_warn(dev->hw_dev,
++					"Counter/Timer1 not configured\n");
+ 				return -EINVAL;
+ 			}
+ 			break;
+ 
+ 		default:
+-			printk("\nThe specified option for start/stop/trigger does not exist\n");
++			dev_warn(dev->hw_dev,
++				"The specified option for start/stop/trigger does not exist\n");
+ 			return -EINVAL;
+ 		}		/* switch(data[1]) */
+ 		break;
+@@ -2024,7 +2058,8 @@ static int i_apci1500_timer_watchdog(struct comedi_device *dev,
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 			}	/* if( i_TimerCounter2Init==1) */
+ 			else {
+-				printk("\nCounter/Timer2 not configured\n");
++				dev_warn(dev->hw_dev,
++					"Counter/Timer2 not configured\n");
+ 				return -EINVAL;
+ 			}
+ 			break;
+@@ -2074,12 +2109,14 @@ static int i_apci1500_timer_watchdog(struct comedi_device *dev,
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 			}	/* if( i_TimerCounter2Init==1) */
+ 			else {
+-				printk("\nCounter/Timer2 not configured\n");
++				dev_warn(dev->hw_dev,
++					"Counter/Timer2 not configured\n");
+ 				return -EINVAL;
+ 			}
+ 			break;
+ 		default:
+-			printk("\nThe specified option for start/stop/trigger does not exist\n");
++			dev_warn(dev->hw_dev,
++				"The specified option for start/stop/trigger does not exist\n");
+ 			return -EINVAL;
+ 		}		/* switch(data[1]) */
+ 		break;
+@@ -2110,7 +2147,8 @@ static int i_apci1500_timer_watchdog(struct comedi_device *dev,
+ 
+ 			}	/*  if( i_WatchdogCounter3init==1) */
+ 			else {
+-				printk("\nWatchdog/Counter3 not configured\n");
++				dev_warn(dev->hw_dev,
++					"Watchdog/Counter3 not configured\n");
+ 				return -EINVAL;
+ 			}
+ 			break;
+@@ -2163,7 +2201,8 @@ static int i_apci1500_timer_watchdog(struct comedi_device *dev,
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+ 				}	/* if( i_WatchdogCounter3Init==1) */
+ 				else {
+-					printk("\nCounter3 not configured\n");
++					dev_warn(dev->hw_dev,
++						"Counter3 not configured\n");
+ 					return -EINVAL;
+ 				}
+ 				break;
+@@ -2182,22 +2221,26 @@ static int i_apci1500_timer_watchdog(struct comedi_device *dev,
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+ 				}	/* if( i_WatchdogCounter3Init==1) */
+ 				else {
+-					printk("\nWatchdog 3 not configured\n");
++					dev_warn(dev->hw_dev,
++						"Watchdog 3 not configured\n");
+ 					return -EINVAL;
+ 				}
+ 				break;
+ 			default:
+-				printk("\nWrong choice of watchdog/counter3\n");
++				dev_warn(dev->hw_dev,
++					"Wrong choice of watchdog/counter3\n");
+ 				return -EINVAL;
+ 			}	/* switch(data[2]) */
+ 			break;
+ 		default:
+-			printk("\nThe specified option for start/stop/trigger does not exist\n");
++			dev_warn(dev->hw_dev,
++				"The specified option for start/stop/trigger does not exist\n");
+ 			return -EINVAL;
+ 		}		/* switch(data[1]) */
+ 		break;
+ 	default:
+-		printk("\nThe specified choice for counter/watchdog/timer does not exist\n");
++		dev_warn(dev->hw_dev,
++			"The specified choice for counter/watchdog/timer does not exist\n");
+ 		return -EINVAL;
+ 	}			/* switch(data[0]) */
+ 	return insn->n;
+@@ -2283,7 +2326,8 @@ static int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device *dev,
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+ 		}		/* if( i_TimerCounter1Init==1) */
+ 		else {
+-			printk("\nTimer/Counter1 not configured\n");
++			dev_warn(dev->hw_dev,
++				"Timer/Counter1 not configured\n");
+ 			return -EINVAL;
+ 		}		/* elseif( i_TimerCounter1Init==1) */
+ 		break;
+@@ -2334,7 +2378,8 @@ static int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device *dev,
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+ 		}		/* if( i_TimerCounter2Init==1) */
+ 		else {
+-			printk("\nTimer/Counter2 not configured\n");
++			dev_warn(dev->hw_dev,
++				"Timer/Counter2 not configured\n");
+ 			return -EINVAL;
+ 		}		/* elseif( i_TimerCounter2Init==1) */
+ 		break;
+@@ -2385,12 +2430,14 @@ static int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device *dev,
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+ 		}		/* if( i_WatchdogCounter3Init==1) */
+ 		else {
+-			printk("\nWatchdogCounter3 not configured\n");
++			dev_warn(dev->hw_dev,
++				"WatchdogCounter3 not configured\n");
+ 			return -EINVAL;
+ 		}		/* elseif( i_WatchdogCounter3Init==1) */
+ 		break;
+ 	default:
+-		printk("\nThe choice of timer/counter/watchdog does not exist\n");
++		dev_warn(dev->hw_dev,
++			"The choice of timer/counter/watchdog does not exist\n");
+ 		return -EINVAL;
+ 	}			/* switch(data[0]) */
+ 
+@@ -2472,7 +2519,8 @@ static int i_APCI1500_ConfigureInterrupt(struct comedi_device *dev,
+ 			i_Constant = 0x00;
+ 		}		/* if{data[0]==0) */
+ 		else {
+-			printk("\nThe parameter passed to driver is in error for enabling the voltage interrupt\n");
++			dev_warn(dev->hw_dev,
++				"The parameter passed to driver is in error for enabling the voltage interrupt\n");
+ 			return -EINVAL;
+ 		}		/* else if(data[0]==0) */
+ 	}			/* elseif(data[0]==1) */
+@@ -2730,7 +2778,6 @@ static void v_APCI1500_Interrupt(int irq, void *d)
+ 			outb(i_RegValue,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+-			printk("\n\n\n");
+ 	     /****************/
+ 			/* Reads port B */
+ 	     /****************/
+@@ -2857,7 +2904,8 @@ static void v_APCI1500_Interrupt(int irq, void *d)
+ 		outb(0xD0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	}			/*   if ((ui_InterruptStatus & 0x800000) == 0x800000) */
+ 	else {
+-		printk("\nInterrupt from unknown source\n");
++		dev_warn(dev->hw_dev,
++			"Interrupt from unknown source\n");
+ 
+ 	}			/* else if ((ui_InterruptStatus & 0x800000) == 0x800000) */
+ 	return;

commit f3c25d569045c8e0f274956291b51641241da174
+Author: Conrad Meyer 
+Date:   Sat Mar 8 15:47:24 2014 -0500
+
+    Staging: comedi: Fix 80-char line limit style issue in addi_apci_1500.c
+    
+    Rename some very long functions in addi-data/hwdrv_apci1500.c.
+    
+    Signed-off-by: Conrad Meyer 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+index 054910511e9e..2628ac44f109 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+@@ -1052,7 +1052,7 @@ static int apci1500_di_insn_bits(struct comedi_device *dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function   Name   : int i_APCI1500_ConfigDigitalOutputErrorInterrupt
++| Function   Name   : int i_apci1500_config_output
+ |                      (struct comedi_device *dev,struct comedi_subdevice *s struct comedi_insn
+ |                      *insn,unsigned int *data)                                  |
+ |				                                                     |
+@@ -1078,10 +1078,9 @@ static int apci1500_di_insn_bits(struct comedi_device *dev,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-static int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device *dev,
+-							struct comedi_subdevice *s,
+-							struct comedi_insn *insn,
+-							unsigned int *data)
++static int i_acpi1500_config_output(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn,
++	unsigned int *data)
+ {
+ 	struct addi_private *devpriv = dev->private;
+ 
+@@ -1879,7 +1878,7 @@ static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function   Name   : int i_APCI1500_StartStopTriggerTimerCounterWatchdog      |
++| Function   Name   : int i_apci1500_timer_watchdog
+ |				(struct comedi_device *dev,struct comedi_subdevice *s,
+ |                         struct comedi_insn *insn,unsigned int *data);                  |
+ +----------------------------------------------------------------------------+
+@@ -1905,10 +1904,9 @@ static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-static int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device *dev,
+-							   struct comedi_subdevice *s,
+-							   struct comedi_insn *insn,
+-							   unsigned int *data)
++static int i_apci1500_timer_watchdog(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn,
++	unsigned int *data)
+ {
+ 	struct addi_private *devpriv = dev->private;
+ 	int i_CommandAndStatusValue;
+diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c
+index 74f7ace8adbc..afa7d6e97a5b 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_1500.c
++++ b/drivers/staging/comedi/drivers/addi_apci_1500.c
+@@ -26,11 +26,11 @@ static const struct addi_board apci1500_boardtypes[] = {
+ 		.di_read		= i_APCI1500_Initialisation,
+ 		.di_write		= i_APCI1500_StartStopInputEvent,
+ 		.di_bits		= apci1500_di_insn_bits,
+-		.do_config		= i_APCI1500_ConfigDigitalOutputErrorInterrupt,
++		.do_config		= i_acpi1500_config_output,
+ 		.do_write		= i_APCI1500_WriteDigitalOutput,
+ 		.do_bits		= i_APCI1500_ConfigureInterrupt,
+ 		.timer_config		= i_APCI1500_ConfigCounterTimerWatchdog,
+-		.timer_write		= i_APCI1500_StartStopTriggerTimerCounterWatchdog,
++		.timer_write		= i_apci1500_timer_watchdog,
+ 		.timer_read		= i_APCI1500_ReadInterruptMask,
+ 		.timer_bits		= i_APCI1500_ReadCounterTimerWatchdog,
+ 	},

commit 18a4d8c97b841632920c16a6fa9216d1214f3db7
+Author: Luke Nelson 
+Date:   Mon Jul 20 19:52:40 2020 -0700
+
+    bpf, riscv: Use compressed instructions in the rv64 JIT
+    
+    This patch uses the RVC support and encodings from bpf_jit.h to optimize
+    the rv64 jit.
+    
+    The optimizations work by replacing emit(rv_X(...)) with a call to a
+    helper function emit_X, which will emit a compressed version of the
+    instruction when possible, and when RVC is enabled.
+    
+    The JIT continues to pass all tests in lib/test_bpf.c, and introduces
+    no new failures to test_verifier; both with and without RVC being enabled.
+    
+    Most changes are straightforward replacements of emit(rv_X(...), ctx)
+    with emit_X(..., ctx), with the following exceptions bearing mention;
+    
+    * Change emit_imm to sign-extend the value in "lower", since the
+    checks for RVC (and the instructions themselves) treat the value as
+    signed. Otherwise, small negative immediates will not be recognized as
+    encodable using an RVC instruction. For example, without this change,
+    emit_imm(rd, -1, ctx) would cause lower to become 4095, which is not a
+    6b int even though a "c.li rd, -1" instruction suffices.
+    
+    * For {BPF_MOV,BPF_ADD} BPF_X, drop using addiw,addw in the 32-bit
+    cases since the values are zero-extended into the upper 32 bits in
+    the following instructions anyways, and the addition commutes with
+    zero-extension. (BPF_SUB BPF_X must still use subw since subtraction
+    does not commute with zero-extension.)
+    
+    This patch avoids optimizing branches and jumps to use RVC instructions
+    since surrounding code often makes assumptions about the sizes of
+    emitted instructions. Optimizing these will require changing these
+    functions (e.g., emit_branch) to dynamically compute jump offsets.
+    
+    The following are examples of the JITed code for the verifier selftest
+    "direct packet read test#3 for CGROUP_SKB OK", without and with RVC
+    enabled, respectively. The former uses 178 bytes, and the latter uses 112,
+    for a ~37% reduction in code size for this example.
+    
+    Without RVC:
+    
+       0: 02000813    addi  a6,zero,32
+       4: fd010113    addi  sp,sp,-48
+       8: 02813423    sd    s0,40(sp)
+       c: 02913023    sd    s1,32(sp)
+      10: 01213c23    sd    s2,24(sp)
+      14: 01313823    sd    s3,16(sp)
+      18: 01413423    sd    s4,8(sp)
+      1c: 03010413    addi  s0,sp,48
+      20: 03056683    lwu   a3,48(a0)
+      24: 02069693    slli  a3,a3,0x20
+      28: 0206d693    srli  a3,a3,0x20
+      2c: 03456703    lwu   a4,52(a0)
+      30: 02071713    slli  a4,a4,0x20
+      34: 02075713    srli  a4,a4,0x20
+      38: 03856483    lwu   s1,56(a0)
+      3c: 02049493    slli  s1,s1,0x20
+      40: 0204d493    srli  s1,s1,0x20
+      44: 03c56903    lwu   s2,60(a0)
+      48: 02091913    slli  s2,s2,0x20
+      4c: 02095913    srli  s2,s2,0x20
+      50: 04056983    lwu   s3,64(a0)
+      54: 02099993    slli  s3,s3,0x20
+      58: 0209d993    srli  s3,s3,0x20
+      5c: 09056a03    lwu   s4,144(a0)
+      60: 020a1a13    slli  s4,s4,0x20
+      64: 020a5a13    srli  s4,s4,0x20
+      68: 00900313    addi  t1,zero,9
+      6c: 006a7463    bgeu  s4,t1,0x74
+      70: 00000a13    addi  s4,zero,0
+      74: 02d52823    sw    a3,48(a0)
+      78: 02e52a23    sw    a4,52(a0)
+      7c: 02952c23    sw    s1,56(a0)
+      80: 03252e23    sw    s2,60(a0)
+      84: 05352023    sw    s3,64(a0)
+      88: 00000793    addi  a5,zero,0
+      8c: 02813403    ld    s0,40(sp)
+      90: 02013483    ld    s1,32(sp)
+      94: 01813903    ld    s2,24(sp)
+      98: 01013983    ld    s3,16(sp)
+      9c: 00813a03    ld    s4,8(sp)
+      a0: 03010113    addi  sp,sp,48
+      a4: 00078513    addi  a0,a5,0
+      a8: 00008067    jalr  zero,0(ra)
+    
+    With RVC:
+    
+       0:   02000813    addi    a6,zero,32
+       4:   7179        c.addi16sp  sp,-48
+       6:   f422        c.sdsp  s0,40(sp)
+       8:   f026        c.sdsp  s1,32(sp)
+       a:   ec4a        c.sdsp  s2,24(sp)
+       c:   e84e        c.sdsp  s3,16(sp)
+       e:   e452        c.sdsp  s4,8(sp)
+      10:   1800        c.addi4spn  s0,sp,48
+      12:   03056683    lwu     a3,48(a0)
+      16:   1682        c.slli  a3,0x20
+      18:   9281        c.srli  a3,0x20
+      1a:   03456703    lwu     a4,52(a0)
+      1e:   1702        c.slli  a4,0x20
+      20:   9301        c.srli  a4,0x20
+      22:   03856483    lwu     s1,56(a0)
+      26:   1482        c.slli  s1,0x20
+      28:   9081        c.srli  s1,0x20
+      2a:   03c56903    lwu     s2,60(a0)
+      2e:   1902        c.slli  s2,0x20
+      30:   02095913    srli    s2,s2,0x20
+      34:   04056983    lwu     s3,64(a0)
+      38:   1982        c.slli  s3,0x20
+      3a:   0209d993    srli    s3,s3,0x20
+      3e:   09056a03    lwu     s4,144(a0)
+      42:   1a02        c.slli  s4,0x20
+      44:   020a5a13    srli    s4,s4,0x20
+      48:   4325        c.li    t1,9
+      4a:   006a7363    bgeu    s4,t1,0x50
+      4e:   4a01        c.li    s4,0
+      50:   d914        c.sw    a3,48(a0)
+      52:   d958        c.sw    a4,52(a0)
+      54:   dd04        c.sw    s1,56(a0)
+      56:   03252e23    sw      s2,60(a0)
+      5a:   05352023    sw      s3,64(a0)
+      5e:   4781        c.li    a5,0
+      60:   7422        c.ldsp  s0,40(sp)
+      62:   7482        c.ldsp  s1,32(sp)
+      64:   6962        c.ldsp  s2,24(sp)
+      66:   69c2        c.ldsp  s3,16(sp)
+      68:   6a22        c.ldsp  s4,8(sp)
+      6a:   6145        c.addi16sp  sp,48
+      6c:   853e        c.mv    a0,a5
+      6e:   8082        c.jr    ra
+    
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Alexei Starovoitov 
+    Cc: Björn Töpel 
+    Link: https://lore.kernel.org/bpf/20200721025241.8077-4-luke.r.nels@gmail.com
+
+diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
+index 55861269da2a..8a56b5293117 100644
+--- a/arch/riscv/net/bpf_jit_comp64.c
++++ b/arch/riscv/net/bpf_jit_comp64.c
+@@ -132,19 +132,23 @@ static void emit_imm(u8 rd, s64 val, struct rv_jit_context *ctx)
+ 	 *
+ 	 * This also means that we need to process LSB to MSB.
+ 	 */
+-	s64 upper = (val + (1 << 11)) >> 12, lower = val & 0xfff;
++	s64 upper = (val + (1 << 11)) >> 12;
++	/* Sign-extend lower 12 bits to 64 bits since immediates for li, addiw,
++	 * and addi are signed and RVC checks will perform signed comparisons.
++	 */
++	s64 lower = ((val & 0xfff) << 52) >> 52;
+ 	int shift;
+ 
+ 	if (is_32b_int(val)) {
+ 		if (upper)
+-			emit(rv_lui(rd, upper), ctx);
++			emit_lui(rd, upper, ctx);
+ 
+ 		if (!upper) {
+-			emit(rv_addi(rd, RV_REG_ZERO, lower), ctx);
++			emit_li(rd, lower, ctx);
+ 			return;
+ 		}
+ 
+-		emit(rv_addiw(rd, rd, lower), ctx);
++		emit_addiw(rd, rd, lower, ctx);
+ 		return;
+ 	}
+ 
+@@ -154,9 +158,9 @@ static void emit_imm(u8 rd, s64 val, struct rv_jit_context *ctx)
+ 
+ 	emit_imm(rd, upper, ctx);
+ 
+-	emit(rv_slli(rd, rd, shift), ctx);
++	emit_slli(rd, rd, shift, ctx);
+ 	if (lower)
+-		emit(rv_addi(rd, rd, lower), ctx);
++		emit_addi(rd, rd, lower, ctx);
+ }
+ 
+ static void __build_epilogue(bool is_tail_call, struct rv_jit_context *ctx)
+@@ -164,43 +168,43 @@ static void __build_epilogue(bool is_tail_call, struct rv_jit_context *ctx)
+ 	int stack_adjust = ctx->stack_size, store_offset = stack_adjust - 8;
+ 
+ 	if (seen_reg(RV_REG_RA, ctx)) {
+-		emit(rv_ld(RV_REG_RA, store_offset, RV_REG_SP), ctx);
++		emit_ld(RV_REG_RA, store_offset, RV_REG_SP, ctx);
+ 		store_offset -= 8;
+ 	}
+-	emit(rv_ld(RV_REG_FP, store_offset, RV_REG_SP), ctx);
++	emit_ld(RV_REG_FP, store_offset, RV_REG_SP, ctx);
+ 	store_offset -= 8;
+ 	if (seen_reg(RV_REG_S1, ctx)) {
+-		emit(rv_ld(RV_REG_S1, store_offset, RV_REG_SP), ctx);
++		emit_ld(RV_REG_S1, store_offset, RV_REG_SP, ctx);
+ 		store_offset -= 8;
+ 	}
+ 	if (seen_reg(RV_REG_S2, ctx)) {
+-		emit(rv_ld(RV_REG_S2, store_offset, RV_REG_SP), ctx);
++		emit_ld(RV_REG_S2, store_offset, RV_REG_SP, ctx);
+ 		store_offset -= 8;
+ 	}
+ 	if (seen_reg(RV_REG_S3, ctx)) {
+-		emit(rv_ld(RV_REG_S3, store_offset, RV_REG_SP), ctx);
++		emit_ld(RV_REG_S3, store_offset, RV_REG_SP, ctx);
+ 		store_offset -= 8;
+ 	}
+ 	if (seen_reg(RV_REG_S4, ctx)) {
+-		emit(rv_ld(RV_REG_S4, store_offset, RV_REG_SP), ctx);
++		emit_ld(RV_REG_S4, store_offset, RV_REG_SP, ctx);
+ 		store_offset -= 8;
+ 	}
+ 	if (seen_reg(RV_REG_S5, ctx)) {
+-		emit(rv_ld(RV_REG_S5, store_offset, RV_REG_SP), ctx);
++		emit_ld(RV_REG_S5, store_offset, RV_REG_SP, ctx);
+ 		store_offset -= 8;
+ 	}
+ 	if (seen_reg(RV_REG_S6, ctx)) {
+-		emit(rv_ld(RV_REG_S6, store_offset, RV_REG_SP), ctx);
++		emit_ld(RV_REG_S6, store_offset, RV_REG_SP, ctx);
+ 		store_offset -= 8;
+ 	}
+ 
+-	emit(rv_addi(RV_REG_SP, RV_REG_SP, stack_adjust), ctx);
++	emit_addi(RV_REG_SP, RV_REG_SP, stack_adjust, ctx);
+ 	/* Set return value. */
+ 	if (!is_tail_call)
+-		emit(rv_addi(RV_REG_A0, RV_REG_A5, 0), ctx);
+-	emit(rv_jalr(RV_REG_ZERO, is_tail_call ? RV_REG_T3 : RV_REG_RA,
+-		     is_tail_call ? 4 : 0), /* skip TCC init */
+-	     ctx);
++		emit_mv(RV_REG_A0, RV_REG_A5, ctx);
++	emit_jalr(RV_REG_ZERO, is_tail_call ? RV_REG_T3 : RV_REG_RA,
++		  is_tail_call ? 4 : 0, /* skip TCC init */
++		  ctx);
+ }
+ 
+ static void emit_bcc(u8 cond, u8 rd, u8 rs, int rvoff,
+@@ -280,8 +284,8 @@ static void emit_branch(u8 cond, u8 rd, u8 rs, int rvoff,
+ 
+ static void emit_zext_32(u8 reg, struct rv_jit_context *ctx)
+ {
+-	emit(rv_slli(reg, reg, 32), ctx);
+-	emit(rv_srli(reg, reg, 32), ctx);
++	emit_slli(reg, reg, 32, ctx);
++	emit_srli(reg, reg, 32, ctx);
+ }
+ 
+ static int emit_bpf_tail_call(int insn, struct rv_jit_context *ctx)
+@@ -310,7 +314,7 @@ static int emit_bpf_tail_call(int insn, struct rv_jit_context *ctx)
+ 	/* if (TCC-- < 0)
+ 	 *     goto out;
+ 	 */
+-	emit(rv_addi(RV_REG_T1, tcc, -1), ctx);
++	emit_addi(RV_REG_T1, tcc, -1, ctx);
+ 	off = ninsns_rvoff(tc_ninsn - (ctx->ninsns - start_insn));
+ 	emit_branch(BPF_JSLT, tcc, RV_REG_ZERO, off, ctx);
+ 
+@@ -318,12 +322,12 @@ static int emit_bpf_tail_call(int insn, struct rv_jit_context *ctx)
+ 	 * if (!prog)
+ 	 *     goto out;
+ 	 */
+-	emit(rv_slli(RV_REG_T2, RV_REG_A2, 3), ctx);
+-	emit(rv_add(RV_REG_T2, RV_REG_T2, RV_REG_A1), ctx);
++	emit_slli(RV_REG_T2, RV_REG_A2, 3, ctx);
++	emit_add(RV_REG_T2, RV_REG_T2, RV_REG_A1, ctx);
+ 	off = offsetof(struct bpf_array, ptrs);
+ 	if (is_12b_check(off, insn))
+ 		return -1;
+-	emit(rv_ld(RV_REG_T2, off, RV_REG_T2), ctx);
++	emit_ld(RV_REG_T2, off, RV_REG_T2, ctx);
+ 	off = ninsns_rvoff(tc_ninsn - (ctx->ninsns - start_insn));
+ 	emit_branch(BPF_JEQ, RV_REG_T2, RV_REG_ZERO, off, ctx);
+ 
+@@ -331,8 +335,8 @@ static int emit_bpf_tail_call(int insn, struct rv_jit_context *ctx)
+ 	off = offsetof(struct bpf_prog, bpf_func);
+ 	if (is_12b_check(off, insn))
+ 		return -1;
+-	emit(rv_ld(RV_REG_T3, off, RV_REG_T2), ctx);
+-	emit(rv_addi(RV_REG_TCC, RV_REG_T1, 0), ctx);
++	emit_ld(RV_REG_T3, off, RV_REG_T2, ctx);
++	emit_mv(RV_REG_TCC, RV_REG_T1, ctx);
+ 	__build_epilogue(true, ctx);
+ 	return 0;
+ }
+@@ -360,9 +364,9 @@ static void init_regs(u8 *rd, u8 *rs, const struct bpf_insn *insn,
+ 
+ static void emit_zext_32_rd_rs(u8 *rd, u8 *rs, struct rv_jit_context *ctx)
+ {
+-	emit(rv_addi(RV_REG_T2, *rd, 0), ctx);
++	emit_mv(RV_REG_T2, *rd, ctx);
+ 	emit_zext_32(RV_REG_T2, ctx);
+-	emit(rv_addi(RV_REG_T1, *rs, 0), ctx);
++	emit_mv(RV_REG_T1, *rs, ctx);
+ 	emit_zext_32(RV_REG_T1, ctx);
+ 	*rd = RV_REG_T2;
+ 	*rs = RV_REG_T1;
+@@ -370,15 +374,15 @@ static void emit_zext_32_rd_rs(u8 *rd, u8 *rs, struct rv_jit_context *ctx)
+ 
+ static void emit_sext_32_rd_rs(u8 *rd, u8 *rs, struct rv_jit_context *ctx)
+ {
+-	emit(rv_addiw(RV_REG_T2, *rd, 0), ctx);
+-	emit(rv_addiw(RV_REG_T1, *rs, 0), ctx);
++	emit_addiw(RV_REG_T2, *rd, 0, ctx);
++	emit_addiw(RV_REG_T1, *rs, 0, ctx);
+ 	*rd = RV_REG_T2;
+ 	*rs = RV_REG_T1;
+ }
+ 
+ static void emit_zext_32_rd_t1(u8 *rd, struct rv_jit_context *ctx)
+ {
+-	emit(rv_addi(RV_REG_T2, *rd, 0), ctx);
++	emit_mv(RV_REG_T2, *rd, ctx);
+ 	emit_zext_32(RV_REG_T2, ctx);
+ 	emit_zext_32(RV_REG_T1, ctx);
+ 	*rd = RV_REG_T2;
+@@ -386,7 +390,7 @@ static void emit_zext_32_rd_t1(u8 *rd, struct rv_jit_context *ctx)
+ 
+ static void emit_sext_32_rd(u8 *rd, struct rv_jit_context *ctx)
+ {
+-	emit(rv_addiw(RV_REG_T2, *rd, 0), ctx);
++	emit_addiw(RV_REG_T2, *rd, 0, ctx);
+ 	*rd = RV_REG_T2;
+ }
+ 
+@@ -432,7 +436,7 @@ static int emit_call(bool fixed, u64 addr, struct rv_jit_context *ctx)
+ 	if (ret)
+ 		return ret;
+ 	rd = bpf_to_rv_reg(BPF_REG_0, ctx);
+-	emit(rv_addi(rd, RV_REG_A0, 0), ctx);
++	emit_mv(rd, RV_REG_A0, ctx);
+ 	return 0;
+ }
+ 
+@@ -458,7 +462,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 			emit_zext_32(rd, ctx);
+ 			break;
+ 		}
+-		emit(is64 ? rv_addi(rd, rs, 0) : rv_addiw(rd, rs, 0), ctx);
++		emit_mv(rd, rs, ctx);
+ 		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+ 		break;
+@@ -466,31 +470,35 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 	/* dst = dst OP src */
+ 	case BPF_ALU | BPF_ADD | BPF_X:
+ 	case BPF_ALU64 | BPF_ADD | BPF_X:
+-		emit(is64 ? rv_add(rd, rd, rs) : rv_addw(rd, rd, rs), ctx);
++		emit_add(rd, rd, rs, ctx);
+ 		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+ 		break;
+ 	case BPF_ALU | BPF_SUB | BPF_X:
+ 	case BPF_ALU64 | BPF_SUB | BPF_X:
+-		emit(is64 ? rv_sub(rd, rd, rs) : rv_subw(rd, rd, rs), ctx);
++		if (is64)
++			emit_sub(rd, rd, rs, ctx);
++		else
++			emit_subw(rd, rd, rs, ctx);
++
+ 		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+ 		break;
+ 	case BPF_ALU | BPF_AND | BPF_X:
+ 	case BPF_ALU64 | BPF_AND | BPF_X:
+-		emit(rv_and(rd, rd, rs), ctx);
++		emit_and(rd, rd, rs, ctx);
+ 		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+ 		break;
+ 	case BPF_ALU | BPF_OR | BPF_X:
+ 	case BPF_ALU64 | BPF_OR | BPF_X:
+-		emit(rv_or(rd, rd, rs), ctx);
++		emit_or(rd, rd, rs, ctx);
+ 		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+ 		break;
+ 	case BPF_ALU | BPF_XOR | BPF_X:
+ 	case BPF_ALU64 | BPF_XOR | BPF_X:
+-		emit(rv_xor(rd, rd, rs), ctx);
++		emit_xor(rd, rd, rs, ctx);
+ 		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+ 		break;
+@@ -534,8 +542,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 	/* dst = -dst */
+ 	case BPF_ALU | BPF_NEG:
+ 	case BPF_ALU64 | BPF_NEG:
+-		emit(is64 ? rv_sub(rd, RV_REG_ZERO, rd) :
+-		     rv_subw(rd, RV_REG_ZERO, rd), ctx);
++		emit_sub(rd, RV_REG_ZERO, rd, ctx);
+ 		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+ 		break;
+@@ -544,8 +551,8 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 	case BPF_ALU | BPF_END | BPF_FROM_LE:
+ 		switch (imm) {
+ 		case 16:
+-			emit(rv_slli(rd, rd, 48), ctx);
+-			emit(rv_srli(rd, rd, 48), ctx);
++			emit_slli(rd, rd, 48, ctx);
++			emit_srli(rd, rd, 48, ctx);
+ 			break;
+ 		case 32:
+ 			if (!aux->verifier_zext)
+@@ -558,51 +565,51 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 		break;
+ 
+ 	case BPF_ALU | BPF_END | BPF_FROM_BE:
+-		emit(rv_addi(RV_REG_T2, RV_REG_ZERO, 0), ctx);
++		emit_li(RV_REG_T2, 0, ctx);
+ 
+-		emit(rv_andi(RV_REG_T1, rd, 0xff), ctx);
+-		emit(rv_add(RV_REG_T2, RV_REG_T2, RV_REG_T1), ctx);
+-		emit(rv_slli(RV_REG_T2, RV_REG_T2, 8), ctx);
+-		emit(rv_srli(rd, rd, 8), ctx);
++		emit_andi(RV_REG_T1, rd, 0xff, ctx);
++		emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
++		emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
++		emit_srli(rd, rd, 8, ctx);
+ 		if (imm == 16)
+ 			goto out_be;
+ 
+-		emit(rv_andi(RV_REG_T1, rd, 0xff), ctx);
+-		emit(rv_add(RV_REG_T2, RV_REG_T2, RV_REG_T1), ctx);
+-		emit(rv_slli(RV_REG_T2, RV_REG_T2, 8), ctx);
+-		emit(rv_srli(rd, rd, 8), ctx);
++		emit_andi(RV_REG_T1, rd, 0xff, ctx);
++		emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
++		emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
++		emit_srli(rd, rd, 8, ctx);
+ 
+-		emit(rv_andi(RV_REG_T1, rd, 0xff), ctx);
+-		emit(rv_add(RV_REG_T2, RV_REG_T2, RV_REG_T1), ctx);
+-		emit(rv_slli(RV_REG_T2, RV_REG_T2, 8), ctx);
+-		emit(rv_srli(rd, rd, 8), ctx);
++		emit_andi(RV_REG_T1, rd, 0xff, ctx);
++		emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
++		emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
++		emit_srli(rd, rd, 8, ctx);
+ 		if (imm == 32)
+ 			goto out_be;
+ 
+-		emit(rv_andi(RV_REG_T1, rd, 0xff), ctx);
+-		emit(rv_add(RV_REG_T2, RV_REG_T2, RV_REG_T1), ctx);
+-		emit(rv_slli(RV_REG_T2, RV_REG_T2, 8), ctx);
+-		emit(rv_srli(rd, rd, 8), ctx);
+-
+-		emit(rv_andi(RV_REG_T1, rd, 0xff), ctx);
+-		emit(rv_add(RV_REG_T2, RV_REG_T2, RV_REG_T1), ctx);
+-		emit(rv_slli(RV_REG_T2, RV_REG_T2, 8), ctx);
+-		emit(rv_srli(rd, rd, 8), ctx);
+-
+-		emit(rv_andi(RV_REG_T1, rd, 0xff), ctx);
+-		emit(rv_add(RV_REG_T2, RV_REG_T2, RV_REG_T1), ctx);
+-		emit(rv_slli(RV_REG_T2, RV_REG_T2, 8), ctx);
+-		emit(rv_srli(rd, rd, 8), ctx);
+-
+-		emit(rv_andi(RV_REG_T1, rd, 0xff), ctx);
+-		emit(rv_add(RV_REG_T2, RV_REG_T2, RV_REG_T1), ctx);
+-		emit(rv_slli(RV_REG_T2, RV_REG_T2, 8), ctx);
+-		emit(rv_srli(rd, rd, 8), ctx);
++		emit_andi(RV_REG_T1, rd, 0xff, ctx);
++		emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
++		emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
++		emit_srli(rd, rd, 8, ctx);
++
++		emit_andi(RV_REG_T1, rd, 0xff, ctx);
++		emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
++		emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
++		emit_srli(rd, rd, 8, ctx);
++
++		emit_andi(RV_REG_T1, rd, 0xff, ctx);
++		emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
++		emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
++		emit_srli(rd, rd, 8, ctx);
++
++		emit_andi(RV_REG_T1, rd, 0xff, ctx);
++		emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
++		emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
++		emit_srli(rd, rd, 8, ctx);
+ out_be:
+-		emit(rv_andi(RV_REG_T1, rd, 0xff), ctx);
+-		emit(rv_add(RV_REG_T2, RV_REG_T2, RV_REG_T1), ctx);
++		emit_andi(RV_REG_T1, rd, 0xff, ctx);
++		emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
+ 
+-		emit(rv_addi(rd, RV_REG_T2, 0), ctx);
++		emit_mv(rd, RV_REG_T2, ctx);
+ 		break;
+ 
+ 	/* dst = imm */
+@@ -617,12 +624,10 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 	case BPF_ALU | BPF_ADD | BPF_K:
+ 	case BPF_ALU64 | BPF_ADD | BPF_K:
+ 		if (is_12b_int(imm)) {
+-			emit(is64 ? rv_addi(rd, rd, imm) :
+-			     rv_addiw(rd, rd, imm), ctx);
++			emit_addi(rd, rd, imm, ctx);
+ 		} else {
+ 			emit_imm(RV_REG_T1, imm, ctx);
+-			emit(is64 ? rv_add(rd, rd, RV_REG_T1) :
+-			     rv_addw(rd, rd, RV_REG_T1), ctx);
++			emit_add(rd, rd, RV_REG_T1, ctx);
+ 		}
+ 		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+@@ -630,12 +635,10 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 	case BPF_ALU | BPF_SUB | BPF_K:
+ 	case BPF_ALU64 | BPF_SUB | BPF_K:
+ 		if (is_12b_int(-imm)) {
+-			emit(is64 ? rv_addi(rd, rd, -imm) :
+-			     rv_addiw(rd, rd, -imm), ctx);
++			emit_addi(rd, rd, -imm, ctx);
+ 		} else {
+ 			emit_imm(RV_REG_T1, imm, ctx);
+-			emit(is64 ? rv_sub(rd, rd, RV_REG_T1) :
+-			     rv_subw(rd, rd, RV_REG_T1), ctx);
++			emit_sub(rd, rd, RV_REG_T1, ctx);
+ 		}
+ 		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+@@ -643,10 +646,10 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 	case BPF_ALU | BPF_AND | BPF_K:
+ 	case BPF_ALU64 | BPF_AND | BPF_K:
+ 		if (is_12b_int(imm)) {
+-			emit(rv_andi(rd, rd, imm), ctx);
++			emit_andi(rd, rd, imm, ctx);
+ 		} else {
+ 			emit_imm(RV_REG_T1, imm, ctx);
+-			emit(rv_and(rd, rd, RV_REG_T1), ctx);
++			emit_and(rd, rd, RV_REG_T1, ctx);
+ 		}
+ 		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+@@ -657,7 +660,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 			emit(rv_ori(rd, rd, imm), ctx);
+ 		} else {
+ 			emit_imm(RV_REG_T1, imm, ctx);
+-			emit(rv_or(rd, rd, RV_REG_T1), ctx);
++			emit_or(rd, rd, RV_REG_T1, ctx);
+ 		}
+ 		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+@@ -668,7 +671,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 			emit(rv_xori(rd, rd, imm), ctx);
+ 		} else {
+ 			emit_imm(RV_REG_T1, imm, ctx);
+-			emit(rv_xor(rd, rd, RV_REG_T1), ctx);
++			emit_xor(rd, rd, RV_REG_T1, ctx);
+ 		}
+ 		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+@@ -699,19 +702,28 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 		break;
+ 	case BPF_ALU | BPF_LSH | BPF_K:
+ 	case BPF_ALU64 | BPF_LSH | BPF_K:
+-		emit(is64 ? rv_slli(rd, rd, imm) : rv_slliw(rd, rd, imm), ctx);
++		emit_slli(rd, rd, imm, ctx);
++
+ 		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+ 		break;
+ 	case BPF_ALU | BPF_RSH | BPF_K:
+ 	case BPF_ALU64 | BPF_RSH | BPF_K:
+-		emit(is64 ? rv_srli(rd, rd, imm) : rv_srliw(rd, rd, imm), ctx);
++		if (is64)
++			emit_srli(rd, rd, imm, ctx);
++		else
++			emit(rv_srliw(rd, rd, imm), ctx);
++
+ 		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+ 		break;
+ 	case BPF_ALU | BPF_ARSH | BPF_K:
+ 	case BPF_ALU64 | BPF_ARSH | BPF_K:
+-		emit(is64 ? rv_srai(rd, rd, imm) : rv_sraiw(rd, rd, imm), ctx);
++		if (is64)
++			emit_srai(rd, rd, imm, ctx);
++		else
++			emit(rv_sraiw(rd, rd, imm), ctx);
++
+ 		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+ 		break;
+@@ -763,7 +775,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 		if (BPF_OP(code) == BPF_JSET) {
+ 			/* Adjust for and */
+ 			rvoff -= 4;
+-			emit(rv_and(RV_REG_T1, rd, rs), ctx);
++			emit_and(RV_REG_T1, rd, rs, ctx);
+ 			emit_branch(BPF_JNE, RV_REG_T1, RV_REG_ZERO, rvoff,
+ 				    ctx);
+ 		} else {
+@@ -819,17 +831,17 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 		rvoff = rv_offset(i, off, ctx);
+ 		s = ctx->ninsns;
+ 		if (is_12b_int(imm)) {
+-			emit(rv_andi(RV_REG_T1, rd, imm), ctx);
++			emit_andi(RV_REG_T1, rd, imm, ctx);
+ 		} else {
+ 			emit_imm(RV_REG_T1, imm, ctx);
+-			emit(rv_and(RV_REG_T1, rd, RV_REG_T1), ctx);
++			emit_and(RV_REG_T1, rd, RV_REG_T1, ctx);
+ 		}
+ 		/* For jset32, we should clear the upper 32 bits of t1, but
+ 		 * sign-extension is sufficient here and saves one instruction,
+ 		 * as t1 is used only in comparison against zero.
+ 		 */
+ 		if (!is64 && imm < 0)
+-			emit(rv_addiw(RV_REG_T1, RV_REG_T1, 0), ctx);
++			emit_addiw(RV_REG_T1, RV_REG_T1, 0, ctx);
+ 		e = ctx->ninsns;
+ 		rvoff -= ninsns_rvoff(e - s);
+ 		emit_branch(BPF_JNE, RV_REG_T1, RV_REG_ZERO, rvoff, ctx);
+@@ -887,7 +899,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 		}
+ 
+ 		emit_imm(RV_REG_T1, off, ctx);
+-		emit(rv_add(RV_REG_T1, RV_REG_T1, rs), ctx);
++		emit_add(RV_REG_T1, RV_REG_T1, rs, ctx);
+ 		emit(rv_lbu(rd, 0, RV_REG_T1), ctx);
+ 		if (insn_is_zext(&insn[1]))
+ 			return 1;
+@@ -899,7 +911,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 		}
+ 
+ 		emit_imm(RV_REG_T1, off, ctx);
+-		emit(rv_add(RV_REG_T1, RV_REG_T1, rs), ctx);
++		emit_add(RV_REG_T1, RV_REG_T1, rs, ctx);
+ 		emit(rv_lhu(rd, 0, RV_REG_T1), ctx);
+ 		if (insn_is_zext(&insn[1]))
+ 			return 1;
+@@ -911,20 +923,20 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 		}
+ 
+ 		emit_imm(RV_REG_T1, off, ctx);
+-		emit(rv_add(RV_REG_T1, RV_REG_T1, rs), ctx);
++		emit_add(RV_REG_T1, RV_REG_T1, rs, ctx);
+ 		emit(rv_lwu(rd, 0, RV_REG_T1), ctx);
+ 		if (insn_is_zext(&insn[1]))
+ 			return 1;
+ 		break;
+ 	case BPF_LDX | BPF_MEM | BPF_DW:
+ 		if (is_12b_int(off)) {
+-			emit(rv_ld(rd, off, rs), ctx);
++			emit_ld(rd, off, rs, ctx);
+ 			break;
+ 		}
+ 
+ 		emit_imm(RV_REG_T1, off, ctx);
+-		emit(rv_add(RV_REG_T1, RV_REG_T1, rs), ctx);
+-		emit(rv_ld(rd, 0, RV_REG_T1), ctx);
++		emit_add(RV_REG_T1, RV_REG_T1, rs, ctx);
++		emit_ld(rd, 0, RV_REG_T1, ctx);
+ 		break;
+ 
+ 	/* ST: *(size *)(dst + off) = imm */
+@@ -936,7 +948,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 		}
+ 
+ 		emit_imm(RV_REG_T2, off, ctx);
+-		emit(rv_add(RV_REG_T2, RV_REG_T2, rd), ctx);
++		emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
+ 		emit(rv_sb(RV_REG_T2, 0, RV_REG_T1), ctx);
+ 		break;
+ 
+@@ -948,30 +960,30 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 		}
+ 
+ 		emit_imm(RV_REG_T2, off, ctx);
+-		emit(rv_add(RV_REG_T2, RV_REG_T2, rd), ctx);
++		emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
+ 		emit(rv_sh(RV_REG_T2, 0, RV_REG_T1), ctx);
+ 		break;
+ 	case BPF_ST | BPF_MEM | BPF_W:
+ 		emit_imm(RV_REG_T1, imm, ctx);
+ 		if (is_12b_int(off)) {
+-			emit(rv_sw(rd, off, RV_REG_T1), ctx);
++			emit_sw(rd, off, RV_REG_T1, ctx);
+ 			break;
+ 		}
+ 
+ 		emit_imm(RV_REG_T2, off, ctx);
+-		emit(rv_add(RV_REG_T2, RV_REG_T2, rd), ctx);
+-		emit(rv_sw(RV_REG_T2, 0, RV_REG_T1), ctx);
++		emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
++		emit_sw(RV_REG_T2, 0, RV_REG_T1, ctx);
+ 		break;
+ 	case BPF_ST | BPF_MEM | BPF_DW:
+ 		emit_imm(RV_REG_T1, imm, ctx);
+ 		if (is_12b_int(off)) {
+-			emit(rv_sd(rd, off, RV_REG_T1), ctx);
++			emit_sd(rd, off, RV_REG_T1, ctx);
+ 			break;
+ 		}
+ 
+ 		emit_imm(RV_REG_T2, off, ctx);
+-		emit(rv_add(RV_REG_T2, RV_REG_T2, rd), ctx);
+-		emit(rv_sd(RV_REG_T2, 0, RV_REG_T1), ctx);
++		emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
++		emit_sd(RV_REG_T2, 0, RV_REG_T1, ctx);
+ 		break;
+ 
+ 	/* STX: *(size *)(dst + off) = src */
+@@ -982,7 +994,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 		}
+ 
+ 		emit_imm(RV_REG_T1, off, ctx);
+-		emit(rv_add(RV_REG_T1, RV_REG_T1, rd), ctx);
++		emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
+ 		emit(rv_sb(RV_REG_T1, 0, rs), ctx);
+ 		break;
+ 	case BPF_STX | BPF_MEM | BPF_H:
+@@ -992,28 +1004,28 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 		}
+ 
+ 		emit_imm(RV_REG_T1, off, ctx);
+-		emit(rv_add(RV_REG_T1, RV_REG_T1, rd), ctx);
++		emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
+ 		emit(rv_sh(RV_REG_T1, 0, rs), ctx);
+ 		break;
+ 	case BPF_STX | BPF_MEM | BPF_W:
+ 		if (is_12b_int(off)) {
+-			emit(rv_sw(rd, off, rs), ctx);
++			emit_sw(rd, off, rs, ctx);
+ 			break;
+ 		}
+ 
+ 		emit_imm(RV_REG_T1, off, ctx);
+-		emit(rv_add(RV_REG_T1, RV_REG_T1, rd), ctx);
+-		emit(rv_sw(RV_REG_T1, 0, rs), ctx);
++		emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
++		emit_sw(RV_REG_T1, 0, rs, ctx);
+ 		break;
+ 	case BPF_STX | BPF_MEM | BPF_DW:
+ 		if (is_12b_int(off)) {
+-			emit(rv_sd(rd, off, rs), ctx);
++			emit_sd(rd, off, rs, ctx);
+ 			break;
+ 		}
+ 
+ 		emit_imm(RV_REG_T1, off, ctx);
+-		emit(rv_add(RV_REG_T1, RV_REG_T1, rd), ctx);
+-		emit(rv_sd(RV_REG_T1, 0, rs), ctx);
++		emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
++		emit_sd(RV_REG_T1, 0, rs, ctx);
+ 		break;
+ 	/* STX XADD: lock *(u32 *)(dst + off) += src */
+ 	case BPF_STX | BPF_XADD | BPF_W:
+@@ -1021,10 +1033,10 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 	case BPF_STX | BPF_XADD | BPF_DW:
+ 		if (off) {
+ 			if (is_12b_int(off)) {
+-				emit(rv_addi(RV_REG_T1, rd, off), ctx);
++				emit_addi(RV_REG_T1, rd, off, ctx);
+ 			} else {
+ 				emit_imm(RV_REG_T1, off, ctx);
+-				emit(rv_add(RV_REG_T1, RV_REG_T1, rd), ctx);
++				emit_add(RV_REG_T1, RV_REG_T1, rd, ctx);
+ 			}
+ 
+ 			rd = RV_REG_T1;
+@@ -1073,52 +1085,53 @@ void bpf_jit_build_prologue(struct rv_jit_context *ctx)
+ 
+ 	/* First instruction is always setting the tail-call-counter
+ 	 * (TCC) register. This instruction is skipped for tail calls.
++	 * Force using a 4-byte (non-compressed) instruction.
+ 	 */
+ 	emit(rv_addi(RV_REG_TCC, RV_REG_ZERO, MAX_TAIL_CALL_CNT), ctx);
+ 
+-	emit(rv_addi(RV_REG_SP, RV_REG_SP, -stack_adjust), ctx);
++	emit_addi(RV_REG_SP, RV_REG_SP, -stack_adjust, ctx);
+ 
+ 	if (seen_reg(RV_REG_RA, ctx)) {
+-		emit(rv_sd(RV_REG_SP, store_offset, RV_REG_RA), ctx);
++		emit_sd(RV_REG_SP, store_offset, RV_REG_RA, ctx);
+ 		store_offset -= 8;
+ 	}
+-	emit(rv_sd(RV_REG_SP, store_offset, RV_REG_FP), ctx);
++	emit_sd(RV_REG_SP, store_offset, RV_REG_FP, ctx);
+ 	store_offset -= 8;
+ 	if (seen_reg(RV_REG_S1, ctx)) {
+-		emit(rv_sd(RV_REG_SP, store_offset, RV_REG_S1), ctx);
++		emit_sd(RV_REG_SP, store_offset, RV_REG_S1, ctx);
+ 		store_offset -= 8;
+ 	}
+ 	if (seen_reg(RV_REG_S2, ctx)) {
+-		emit(rv_sd(RV_REG_SP, store_offset, RV_REG_S2), ctx);
++		emit_sd(RV_REG_SP, store_offset, RV_REG_S2, ctx);
+ 		store_offset -= 8;
+ 	}
+ 	if (seen_reg(RV_REG_S3, ctx)) {
+-		emit(rv_sd(RV_REG_SP, store_offset, RV_REG_S3), ctx);
++		emit_sd(RV_REG_SP, store_offset, RV_REG_S3, ctx);
+ 		store_offset -= 8;
+ 	}
+ 	if (seen_reg(RV_REG_S4, ctx)) {
+-		emit(rv_sd(RV_REG_SP, store_offset, RV_REG_S4), ctx);
++		emit_sd(RV_REG_SP, store_offset, RV_REG_S4, ctx);
+ 		store_offset -= 8;
+ 	}
+ 	if (seen_reg(RV_REG_S5, ctx)) {
+-		emit(rv_sd(RV_REG_SP, store_offset, RV_REG_S5), ctx);
++		emit_sd(RV_REG_SP, store_offset, RV_REG_S5, ctx);
+ 		store_offset -= 8;
+ 	}
+ 	if (seen_reg(RV_REG_S6, ctx)) {
+-		emit(rv_sd(RV_REG_SP, store_offset, RV_REG_S6), ctx);
++		emit_sd(RV_REG_SP, store_offset, RV_REG_S6, ctx);
+ 		store_offset -= 8;
+ 	}
+ 
+-	emit(rv_addi(RV_REG_FP, RV_REG_SP, stack_adjust), ctx);
++	emit_addi(RV_REG_FP, RV_REG_SP, stack_adjust, ctx);
+ 
+ 	if (bpf_stack_adjust)
+-		emit(rv_addi(RV_REG_S5, RV_REG_SP, bpf_stack_adjust), ctx);
++		emit_addi(RV_REG_S5, RV_REG_SP, bpf_stack_adjust, ctx);
+ 
+ 	/* Program contains calls and tail calls, so RV_REG_TCC need
+ 	 * to be saved across calls.
+ 	 */
+ 	if (seen_tail_call(ctx) && seen_call(ctx))
+-		emit(rv_addi(RV_REG_TCC_SAVED, RV_REG_TCC, 0), ctx);
++		emit_mv(RV_REG_TCC_SAVED, RV_REG_TCC, ctx);
+ 
+ 	ctx->stack_size = stack_adjust;
+ }

commit 804ec72c68c8477b8713a1e8f8eda120d3471031
+Author: Luke Nelson 
+Date:   Mon Jul 20 19:52:39 2020 -0700
+
+    bpf, riscv: Add encodings for compressed instructions
+    
+    This patch adds functions for encoding and emitting compressed riscv
+    (RVC) instructions to the BPF JIT.
+    
+    Some regular riscv instructions can be compressed into an RVC instruction
+    if the instruction fields meet some requirements. For example, "add rd,
+    rs1, rs2" can be compressed into "c.add rd, rs2" when rd == rs1.
+    
+    To make using RVC encodings simpler, this patch also adds helper
+    functions that selectively emit either a regular instruction or a
+    compressed instruction if possible.
+    
+    For example, emit_add will produce a "c.add" if possible and regular
+    "add" otherwise.
+    
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Alexei Starovoitov 
+    Link: https://lore.kernel.org/bpf/20200721025241.8077-3-luke.r.nels@gmail.com
+
+diff --git a/arch/riscv/net/bpf_jit.h b/arch/riscv/net/bpf_jit.h
+index e90d336a9e5f..75c1e9996867 100644
+--- a/arch/riscv/net/bpf_jit.h
++++ b/arch/riscv/net/bpf_jit.h
+@@ -53,6 +53,18 @@ enum {
+ 	RV_REG_T6 =	31,
+ };
+ 
++static inline bool is_creg(u8 reg)
++{
++	return (1 << reg) & (BIT(RV_REG_FP) |
++			     BIT(RV_REG_S1) |
++			     BIT(RV_REG_A0) |
++			     BIT(RV_REG_A1) |
++			     BIT(RV_REG_A2) |
++			     BIT(RV_REG_A3) |
++			     BIT(RV_REG_A4) |
++			     BIT(RV_REG_A5));
++}
++
+ struct rv_jit_context {
+ 	struct bpf_prog *prog;
+ 	u16 *insns;		/* RV insns */
+@@ -142,6 +154,36 @@ static inline int invert_bpf_cond(u8 cond)
+ 	return -1;
+ }
+ 
++static inline bool is_6b_int(long val)
++{
++	return -(1L << 5) <= val && val < (1L << 5);
++}
++
++static inline bool is_7b_uint(unsigned long val)
++{
++	return val < (1UL << 7);
++}
++
++static inline bool is_8b_uint(unsigned long val)
++{
++	return val < (1UL << 8);
++}
++
++static inline bool is_9b_uint(unsigned long val)
++{
++	return val < (1UL << 9);
++}
++
++static inline bool is_10b_int(long val)
++{
++	return -(1L << 9) <= val && val < (1L << 9);
++}
++
++static inline bool is_10b_uint(unsigned long val)
++{
++	return val < (1UL << 10);
++}
++
+ static inline bool is_12b_int(long val)
+ {
+ 	return -(1L << 11) <= val && val < (1L << 11);
+@@ -232,6 +274,59 @@ static inline u32 rv_amo_insn(u8 funct5, u8 aq, u8 rl, u8 rs2, u8 rs1,
+ 	return rv_r_insn(funct7, rs2, rs1, funct3, rd, opcode);
+ }
+ 
++/* RISC-V compressed instruction formats. */
++
++static inline u16 rv_cr_insn(u8 funct4, u8 rd, u8 rs2, u8 op)
++{
++	return (funct4 << 12) | (rd << 7) | (rs2 << 2) | op;
++}
++
++static inline u16 rv_ci_insn(u8 funct3, u32 imm6, u8 rd, u8 op)
++{
++	u32 imm;
++
++	imm = ((imm6 & 0x20) << 7) | ((imm6 & 0x1f) << 2);
++	return (funct3 << 13) | (rd << 7) | op | imm;
++}
++
++static inline u16 rv_css_insn(u8 funct3, u32 uimm, u8 rs2, u8 op)
++{
++	return (funct3 << 13) | (uimm << 7) | (rs2 << 2) | op;
++}
++
++static inline u16 rv_ciw_insn(u8 funct3, u32 uimm, u8 rd, u8 op)
++{
++	return (funct3 << 13) | (uimm << 5) | ((rd & 0x7) << 2) | op;
++}
++
++static inline u16 rv_cl_insn(u8 funct3, u32 imm_hi, u8 rs1, u32 imm_lo, u8 rd,
++			     u8 op)
++{
++	return (funct3 << 13) | (imm_hi << 10) | ((rs1 & 0x7) << 7) |
++		(imm_lo << 5) | ((rd & 0x7) << 2) | op;
++}
++
++static inline u16 rv_cs_insn(u8 funct3, u32 imm_hi, u8 rs1, u32 imm_lo, u8 rs2,
++			     u8 op)
++{
++	return (funct3 << 13) | (imm_hi << 10) | ((rs1 & 0x7) << 7) |
++		(imm_lo << 5) | ((rs2 & 0x7) << 2) | op;
++}
++
++static inline u16 rv_ca_insn(u8 funct6, u8 rd, u8 funct2, u8 rs2, u8 op)
++{
++	return (funct6 << 10) | ((rd & 0x7) << 7) | (funct2 << 5) |
++		((rs2 & 0x7) << 2) | op;
++}
++
++static inline u16 rv_cb_insn(u8 funct3, u32 imm6, u8 funct2, u8 rd, u8 op)
++{
++	u32 imm;
++
++	imm = ((imm6 & 0x20) << 7) | ((imm6 & 0x1f) << 2);
++	return (funct3 << 13) | (funct2 << 10) | ((rd & 0x7) << 7) | op | imm;
++}
++
+ /* Instructions shared by both RV32 and RV64. */
+ 
+ static inline u32 rv_addi(u8 rd, u8 rs1, u16 imm11_0)
+@@ -439,6 +534,135 @@ static inline u32 rv_amoadd_w(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
+ 	return rv_amo_insn(0, aq, rl, rs2, rs1, 2, rd, 0x2f);
+ }
+ 
++/* RVC instrutions. */
++
++static inline u16 rvc_addi4spn(u8 rd, u32 imm10)
++{
++	u32 imm;
++
++	imm = ((imm10 & 0x30) << 2) | ((imm10 & 0x3c0) >> 4) |
++		((imm10 & 0x4) >> 1) | ((imm10 & 0x8) >> 3);
++	return rv_ciw_insn(0x0, imm, rd, 0x0);
++}
++
++static inline u16 rvc_lw(u8 rd, u32 imm7, u8 rs1)
++{
++	u32 imm_hi, imm_lo;
++
++	imm_hi = (imm7 & 0x38) >> 3;
++	imm_lo = ((imm7 & 0x4) >> 1) | ((imm7 & 0x40) >> 6);
++	return rv_cl_insn(0x2, imm_hi, rs1, imm_lo, rd, 0x0);
++}
++
++static inline u16 rvc_sw(u8 rs1, u32 imm7, u8 rs2)
++{
++	u32 imm_hi, imm_lo;
++
++	imm_hi = (imm7 & 0x38) >> 3;
++	imm_lo = ((imm7 & 0x4) >> 1) | ((imm7 & 0x40) >> 6);
++	return rv_cs_insn(0x6, imm_hi, rs1, imm_lo, rs2, 0x0);
++}
++
++static inline u16 rvc_addi(u8 rd, u32 imm6)
++{
++	return rv_ci_insn(0, imm6, rd, 0x1);
++}
++
++static inline u16 rvc_li(u8 rd, u32 imm6)
++{
++	return rv_ci_insn(0x2, imm6, rd, 0x1);
++}
++
++static inline u16 rvc_addi16sp(u32 imm10)
++{
++	u32 imm;
++
++	imm = ((imm10 & 0x200) >> 4) | (imm10 & 0x10) | ((imm10 & 0x40) >> 3) |
++		((imm10 & 0x180) >> 6) | ((imm10 & 0x20) >> 5);
++	return rv_ci_insn(0x3, imm, RV_REG_SP, 0x1);
++}
++
++static inline u16 rvc_lui(u8 rd, u32 imm6)
++{
++	return rv_ci_insn(0x3, imm6, rd, 0x1);
++}
++
++static inline u16 rvc_srli(u8 rd, u32 imm6)
++{
++	return rv_cb_insn(0x4, imm6, 0, rd, 0x1);
++}
++
++static inline u16 rvc_srai(u8 rd, u32 imm6)
++{
++	return rv_cb_insn(0x4, imm6, 0x1, rd, 0x1);
++}
++
++static inline u16 rvc_andi(u8 rd, u32 imm6)
++{
++	return rv_cb_insn(0x4, imm6, 0x2, rd, 0x1);
++}
++
++static inline u16 rvc_sub(u8 rd, u8 rs)
++{
++	return rv_ca_insn(0x23, rd, 0, rs, 0x1);
++}
++
++static inline u16 rvc_xor(u8 rd, u8 rs)
++{
++	return rv_ca_insn(0x23, rd, 0x1, rs, 0x1);
++}
++
++static inline u16 rvc_or(u8 rd, u8 rs)
++{
++	return rv_ca_insn(0x23, rd, 0x2, rs, 0x1);
++}
++
++static inline u16 rvc_and(u8 rd, u8 rs)
++{
++	return rv_ca_insn(0x23, rd, 0x3, rs, 0x1);
++}
++
++static inline u16 rvc_slli(u8 rd, u32 imm6)
++{
++	return rv_ci_insn(0, imm6, rd, 0x2);
++}
++
++static inline u16 rvc_lwsp(u8 rd, u32 imm8)
++{
++	u32 imm;
++
++	imm = ((imm8 & 0xc0) >> 6) | (imm8 & 0x3c);
++	return rv_ci_insn(0x2, imm, rd, 0x2);
++}
++
++static inline u16 rvc_jr(u8 rs1)
++{
++	return rv_cr_insn(0x8, rs1, RV_REG_ZERO, 0x2);
++}
++
++static inline u16 rvc_mv(u8 rd, u8 rs)
++{
++	return rv_cr_insn(0x8, rd, rs, 0x2);
++}
++
++static inline u16 rvc_jalr(u8 rs1)
++{
++	return rv_cr_insn(0x9, rs1, RV_REG_ZERO, 0x2);
++}
++
++static inline u16 rvc_add(u8 rd, u8 rs)
++{
++	return rv_cr_insn(0x9, rd, rs, 0x2);
++}
++
++static inline u16 rvc_swsp(u32 imm8, u8 rs2)
++{
++	u32 imm;
++
++	imm = (imm8 & 0x3c) | ((imm8 & 0xc0) >> 6);
++	return rv_css_insn(0x6, imm, rs2, 0x2);
++}
++
+ /*
+  * RV64-only instructions.
+  *
+@@ -528,6 +752,234 @@ static inline u32 rv_amoadd_d(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
+ 	return rv_amo_insn(0, aq, rl, rs2, rs1, 3, rd, 0x2f);
+ }
+ 
++/* RV64-only RVC instructions. */
++
++static inline u16 rvc_ld(u8 rd, u32 imm8, u8 rs1)
++{
++	u32 imm_hi, imm_lo;
++
++	imm_hi = (imm8 & 0x38) >> 3;
++	imm_lo = (imm8 & 0xc0) >> 6;
++	return rv_cl_insn(0x3, imm_hi, rs1, imm_lo, rd, 0x0);
++}
++
++static inline u16 rvc_sd(u8 rs1, u32 imm8, u8 rs2)
++{
++	u32 imm_hi, imm_lo;
++
++	imm_hi = (imm8 & 0x38) >> 3;
++	imm_lo = (imm8 & 0xc0) >> 6;
++	return rv_cs_insn(0x7, imm_hi, rs1, imm_lo, rs2, 0x0);
++}
++
++static inline u16 rvc_subw(u8 rd, u8 rs)
++{
++	return rv_ca_insn(0x27, rd, 0, rs, 0x1);
++}
++
++static inline u16 rvc_addiw(u8 rd, u32 imm6)
++{
++	return rv_ci_insn(0x1, imm6, rd, 0x1);
++}
++
++static inline u16 rvc_ldsp(u8 rd, u32 imm9)
++{
++	u32 imm;
++
++	imm = ((imm9 & 0x1c0) >> 6) | (imm9 & 0x38);
++	return rv_ci_insn(0x3, imm, rd, 0x2);
++}
++
++static inline u16 rvc_sdsp(u32 imm9, u8 rs2)
++{
++	u32 imm;
++
++	imm = (imm9 & 0x38) | ((imm9 & 0x1c0) >> 6);
++	return rv_css_insn(0x7, imm, rs2, 0x2);
++}
++
++#endif /* __riscv_xlen == 64 */
++
++/* Helper functions that emit RVC instructions when possible. */
++
++static inline void emit_jalr(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx)
++{
++	if (rvc_enabled() && rd == RV_REG_RA && rs && !imm)
++		emitc(rvc_jalr(rs), ctx);
++	else if (rvc_enabled() && !rd && rs && !imm)
++		emitc(rvc_jr(rs), ctx);
++	else
++		emit(rv_jalr(rd, rs, imm), ctx);
++}
++
++static inline void emit_mv(u8 rd, u8 rs, struct rv_jit_context *ctx)
++{
++	if (rvc_enabled() && rd && rs)
++		emitc(rvc_mv(rd, rs), ctx);
++	else
++		emit(rv_addi(rd, rs, 0), ctx);
++}
++
++static inline void emit_add(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx)
++{
++	if (rvc_enabled() && rd && rd == rs1 && rs2)
++		emitc(rvc_add(rd, rs2), ctx);
++	else
++		emit(rv_add(rd, rs1, rs2), ctx);
++}
++
++static inline void emit_addi(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx)
++{
++	if (rvc_enabled() && rd == RV_REG_SP && rd == rs && is_10b_int(imm) && imm && !(imm & 0xf))
++		emitc(rvc_addi16sp(imm), ctx);
++	else if (rvc_enabled() && is_creg(rd) && rs == RV_REG_SP && is_10b_uint(imm) &&
++		 !(imm & 0x3) && imm)
++		emitc(rvc_addi4spn(rd, imm), ctx);
++	else if (rvc_enabled() && rd && rd == rs && imm && is_6b_int(imm))
++		emitc(rvc_addi(rd, imm), ctx);
++	else
++		emit(rv_addi(rd, rs, imm), ctx);
++}
++
++static inline void emit_li(u8 rd, s32 imm, struct rv_jit_context *ctx)
++{
++	if (rvc_enabled() && rd && is_6b_int(imm))
++		emitc(rvc_li(rd, imm), ctx);
++	else
++		emit(rv_addi(rd, RV_REG_ZERO, imm), ctx);
++}
++
++static inline void emit_lui(u8 rd, s32 imm, struct rv_jit_context *ctx)
++{
++	if (rvc_enabled() && rd && rd != RV_REG_SP && is_6b_int(imm) && imm)
++		emitc(rvc_lui(rd, imm), ctx);
++	else
++		emit(rv_lui(rd, imm), ctx);
++}
++
++static inline void emit_slli(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx)
++{
++	if (rvc_enabled() && rd && rd == rs && imm && (u32)imm < __riscv_xlen)
++		emitc(rvc_slli(rd, imm), ctx);
++	else
++		emit(rv_slli(rd, rs, imm), ctx);
++}
++
++static inline void emit_andi(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx)
++{
++	if (rvc_enabled() && is_creg(rd) && rd == rs && is_6b_int(imm))
++		emitc(rvc_andi(rd, imm), ctx);
++	else
++		emit(rv_andi(rd, rs, imm), ctx);
++}
++
++static inline void emit_srli(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx)
++{
++	if (rvc_enabled() && is_creg(rd) && rd == rs && imm && (u32)imm < __riscv_xlen)
++		emitc(rvc_srli(rd, imm), ctx);
++	else
++		emit(rv_srli(rd, rs, imm), ctx);
++}
++
++static inline void emit_srai(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx)
++{
++	if (rvc_enabled() && is_creg(rd) && rd == rs && imm && (u32)imm < __riscv_xlen)
++		emitc(rvc_srai(rd, imm), ctx);
++	else
++		emit(rv_srai(rd, rs, imm), ctx);
++}
++
++static inline void emit_sub(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx)
++{
++	if (rvc_enabled() && is_creg(rd) && rd == rs1 && is_creg(rs2))
++		emitc(rvc_sub(rd, rs2), ctx);
++	else
++		emit(rv_sub(rd, rs1, rs2), ctx);
++}
++
++static inline void emit_or(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx)
++{
++	if (rvc_enabled() && is_creg(rd) && rd == rs1 && is_creg(rs2))
++		emitc(rvc_or(rd, rs2), ctx);
++	else
++		emit(rv_or(rd, rs1, rs2), ctx);
++}
++
++static inline void emit_and(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx)
++{
++	if (rvc_enabled() && is_creg(rd) && rd == rs1 && is_creg(rs2))
++		emitc(rvc_and(rd, rs2), ctx);
++	else
++		emit(rv_and(rd, rs1, rs2), ctx);
++}
++
++static inline void emit_xor(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx)
++{
++	if (rvc_enabled() && is_creg(rd) && rd == rs1 && is_creg(rs2))
++		emitc(rvc_xor(rd, rs2), ctx);
++	else
++		emit(rv_xor(rd, rs1, rs2), ctx);
++}
++
++static inline void emit_lw(u8 rd, s32 off, u8 rs1, struct rv_jit_context *ctx)
++{
++	if (rvc_enabled() && rs1 == RV_REG_SP && rd && is_8b_uint(off) && !(off & 0x3))
++		emitc(rvc_lwsp(rd, off), ctx);
++	else if (rvc_enabled() && is_creg(rd) && is_creg(rs1) && is_7b_uint(off) && !(off & 0x3))
++		emitc(rvc_lw(rd, off, rs1), ctx);
++	else
++		emit(rv_lw(rd, off, rs1), ctx);
++}
++
++static inline void emit_sw(u8 rs1, s32 off, u8 rs2, struct rv_jit_context *ctx)
++{
++	if (rvc_enabled() && rs1 == RV_REG_SP && is_8b_uint(off) && !(off & 0x3))
++		emitc(rvc_swsp(off, rs2), ctx);
++	else if (rvc_enabled() && is_creg(rs1) && is_creg(rs2) && is_7b_uint(off) && !(off & 0x3))
++		emitc(rvc_sw(rs1, off, rs2), ctx);
++	else
++		emit(rv_sw(rs1, off, rs2), ctx);
++}
++
++/* RV64-only helper functions. */
++#if __riscv_xlen == 64
++
++static inline void emit_addiw(u8 rd, u8 rs, s32 imm, struct rv_jit_context *ctx)
++{
++	if (rvc_enabled() && rd && rd == rs && is_6b_int(imm))
++		emitc(rvc_addiw(rd, imm), ctx);
++	else
++		emit(rv_addiw(rd, rs, imm), ctx);
++}
++
++static inline void emit_ld(u8 rd, s32 off, u8 rs1, struct rv_jit_context *ctx)
++{
++	if (rvc_enabled() && rs1 == RV_REG_SP && rd && is_9b_uint(off) && !(off & 0x7))
++		emitc(rvc_ldsp(rd, off), ctx);
++	else if (rvc_enabled() && is_creg(rd) && is_creg(rs1) && is_8b_uint(off) && !(off & 0x7))
++		emitc(rvc_ld(rd, off, rs1), ctx);
++	else
++		emit(rv_ld(rd, off, rs1), ctx);
++}
++
++static inline void emit_sd(u8 rs1, s32 off, u8 rs2, struct rv_jit_context *ctx)
++{
++	if (rvc_enabled() && rs1 == RV_REG_SP && is_9b_uint(off) && !(off & 0x7))
++		emitc(rvc_sdsp(off, rs2), ctx);
++	else if (rvc_enabled() && is_creg(rs1) && is_creg(rs2) && is_8b_uint(off) && !(off & 0x7))
++		emitc(rvc_sd(rs1, off, rs2), ctx);
++	else
++		emit(rv_sd(rs1, off, rs2), ctx);
++}
++
++static inline void emit_subw(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx)
++{
++	if (rvc_enabled() && is_creg(rd) && rd == rs1 && is_creg(rs2))
++		emitc(rvc_subw(rd, rs2), ctx);
++	else
++		emit(rv_subw(rd, rs1, rs2), ctx);
++}
++
+ #endif /* __riscv_xlen == 64 */
+ 
+ void bpf_jit_build_prologue(struct rv_jit_context *ctx);

commit bfabff3cb0fef366086c64f24be8ab316a355b99
+Author: Luke Nelson 
+Date:   Mon Jul 20 19:52:38 2020 -0700
+
+    bpf, riscv: Modify JIT ctx to support compressed instructions
+    
+    This patch makes the necessary changes to struct rv_jit_context and to
+    bpf_int_jit_compile to support compressed riscv (RVC) instructions in
+    the BPF JIT.
+    
+    It changes the JIT image to be u16 instead of u32, since RVC instructions
+    are 2 bytes as opposed to 4.
+    
+    It also changes ctx->offset and ctx->ninsns to refer to 2-byte
+    instructions rather than 4-byte ones. The riscv PC is required to be
+    16-bit aligned with or without RVC, so this is sufficient to refer to
+    any valid riscv offset.
+    
+    The code for computing jump offsets in bytes is updated accordingly,
+    and factored into a new "ninsns_rvoff" function to simplify the code.
+    
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Alexei Starovoitov 
+    Link: https://lore.kernel.org/bpf/20200721025241.8077-2-luke.r.nels@gmail.com
+
+diff --git a/arch/riscv/net/bpf_jit.h b/arch/riscv/net/bpf_jit.h
+index 20e235d06f66..e90d336a9e5f 100644
+--- a/arch/riscv/net/bpf_jit.h
++++ b/arch/riscv/net/bpf_jit.h
+@@ -13,6 +13,11 @@
+ #include 
+ #include 
+ 
++static inline bool rvc_enabled(void)
++{
++	return IS_ENABLED(CONFIG_RISCV_ISA_C);
++}
++
+ enum {
+ 	RV_REG_ZERO =	0,	/* The constant value 0 */
+ 	RV_REG_RA =	1,	/* Return address */
+@@ -50,7 +55,7 @@ enum {
+ 
+ struct rv_jit_context {
+ 	struct bpf_prog *prog;
+-	u32 *insns;		/* RV insns */
++	u16 *insns;		/* RV insns */
+ 	int ninsns;
+ 	int epilogue_offset;
+ 	int *offset;		/* BPF to RV */
+@@ -58,6 +63,12 @@ struct rv_jit_context {
+ 	int stack_size;
+ };
+ 
++/* Convert from ninsns to bytes. */
++static inline int ninsns_rvoff(int ninsns)
++{
++	return ninsns << 1;
++}
++
+ struct rv_jit_data {
+ 	struct bpf_binary_header *header;
+ 	u8 *image;
+@@ -74,8 +85,22 @@ static inline void bpf_flush_icache(void *start, void *end)
+ 	flush_icache_range((unsigned long)start, (unsigned long)end);
+ }
+ 
++/* Emit a 4-byte riscv instruction. */
+ static inline void emit(const u32 insn, struct rv_jit_context *ctx)
+ {
++	if (ctx->insns) {
++		ctx->insns[ctx->ninsns] = insn;
++		ctx->insns[ctx->ninsns + 1] = (insn >> 16);
++	}
++
++	ctx->ninsns += 2;
++}
++
++/* Emit a 2-byte riscv compressed instruction. */
++static inline void emitc(const u16 insn, struct rv_jit_context *ctx)
++{
++	BUILD_BUG_ON(!rvc_enabled());
++
+ 	if (ctx->insns)
+ 		ctx->insns[ctx->ninsns] = insn;
+ 
+@@ -86,7 +111,7 @@ static inline int epilogue_offset(struct rv_jit_context *ctx)
+ {
+ 	int to = ctx->epilogue_offset, from = ctx->ninsns;
+ 
+-	return (to - from) << 2;
++	return ninsns_rvoff(to - from);
+ }
+ 
+ /* Return -1 or inverted cond. */
+@@ -149,7 +174,7 @@ static inline int rv_offset(int insn, int off, struct rv_jit_context *ctx)
+ 	off++; /* BPF branch is from PC+1, RV is from PC */
+ 	from = (insn > 0) ? ctx->offset[insn - 1] : 0;
+ 	to = (insn + off > 0) ? ctx->offset[insn + off - 1] : 0;
+-	return (to - from) << 2;
++	return ninsns_rvoff(to - from);
+ }
+ 
+ /* Instruction formats. */
+diff --git a/arch/riscv/net/bpf_jit_comp32.c b/arch/riscv/net/bpf_jit_comp32.c
+index b198eaa74456..bc5f2204693f 100644
+--- a/arch/riscv/net/bpf_jit_comp32.c
++++ b/arch/riscv/net/bpf_jit_comp32.c
+@@ -644,7 +644,7 @@ static int emit_branch_r64(const s8 *src1, const s8 *src2, s32 rvoff,
+ 
+ 	e = ctx->ninsns;
+ 	/* Adjust for extra insns. */
+-	rvoff -= (e - s) << 2;
++	rvoff -= ninsns_rvoff(e - s);
+ 	emit_jump_and_link(RV_REG_ZERO, rvoff, true, ctx);
+ 	return 0;
+ }
+@@ -713,7 +713,7 @@ static int emit_bcc(u8 op, u8 rd, u8 rs, int rvoff, struct rv_jit_context *ctx)
+ 	if (far) {
+ 		e = ctx->ninsns;
+ 		/* Adjust for extra insns. */
+-		rvoff -= (e - s) << 2;
++		rvoff -= ninsns_rvoff(e - s);
+ 		emit_jump_and_link(RV_REG_ZERO, rvoff, true, ctx);
+ 	}
+ 	return 0;
+@@ -731,7 +731,7 @@ static int emit_branch_r32(const s8 *src1, const s8 *src2, s32 rvoff,
+ 
+ 	e = ctx->ninsns;
+ 	/* Adjust for extra insns. */
+-	rvoff -= (e - s) << 2;
++	rvoff -= ninsns_rvoff(e - s);
+ 
+ 	if (emit_bcc(op, lo(rs1), lo(rs2), rvoff, ctx))
+ 		return -1;
+@@ -795,7 +795,7 @@ static int emit_bpf_tail_call(int insn, struct rv_jit_context *ctx)
+ 	 * if (index >= max_entries)
+ 	 *   goto out;
+ 	 */
+-	off = (tc_ninsn - (ctx->ninsns - start_insn)) << 2;
++	off = ninsns_rvoff(tc_ninsn - (ctx->ninsns - start_insn));
+ 	emit_bcc(BPF_JGE, lo(idx_reg), RV_REG_T1, off, ctx);
+ 
+ 	/*
+@@ -804,7 +804,7 @@ static int emit_bpf_tail_call(int insn, struct rv_jit_context *ctx)
+ 	 *   goto out;
+ 	 */
+ 	emit(rv_addi(RV_REG_T1, RV_REG_TCC, -1), ctx);
+-	off = (tc_ninsn - (ctx->ninsns - start_insn)) << 2;
++	off = ninsns_rvoff(tc_ninsn - (ctx->ninsns - start_insn));
+ 	emit_bcc(BPF_JSLT, RV_REG_TCC, RV_REG_ZERO, off, ctx);
+ 
+ 	/*
+@@ -818,7 +818,7 @@ static int emit_bpf_tail_call(int insn, struct rv_jit_context *ctx)
+ 	if (is_12b_check(off, insn))
+ 		return -1;
+ 	emit(rv_lw(RV_REG_T0, off, RV_REG_T0), ctx);
+-	off = (tc_ninsn - (ctx->ninsns - start_insn)) << 2;
++	off = ninsns_rvoff(tc_ninsn - (ctx->ninsns - start_insn));
+ 	emit_bcc(BPF_JEQ, RV_REG_T0, RV_REG_ZERO, off, ctx);
+ 
+ 	/*
+@@ -1214,7 +1214,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 			emit_imm32(tmp2, imm, ctx);
+ 			src = tmp2;
+ 			e = ctx->ninsns;
+-			rvoff -= (e - s) << 2;
++			rvoff -= ninsns_rvoff(e - s);
+ 		}
+ 
+ 		if (is64)
+diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
+index 6cfd164cbe88..55861269da2a 100644
+--- a/arch/riscv/net/bpf_jit_comp64.c
++++ b/arch/riscv/net/bpf_jit_comp64.c
+@@ -304,14 +304,14 @@ static int emit_bpf_tail_call(int insn, struct rv_jit_context *ctx)
+ 	if (is_12b_check(off, insn))
+ 		return -1;
+ 	emit(rv_lwu(RV_REG_T1, off, RV_REG_A1), ctx);
+-	off = (tc_ninsn - (ctx->ninsns - start_insn)) << 2;
++	off = ninsns_rvoff(tc_ninsn - (ctx->ninsns - start_insn));
+ 	emit_branch(BPF_JGE, RV_REG_A2, RV_REG_T1, off, ctx);
+ 
+ 	/* if (TCC-- < 0)
+ 	 *     goto out;
+ 	 */
+ 	emit(rv_addi(RV_REG_T1, tcc, -1), ctx);
+-	off = (tc_ninsn - (ctx->ninsns - start_insn)) << 2;
++	off = ninsns_rvoff(tc_ninsn - (ctx->ninsns - start_insn));
+ 	emit_branch(BPF_JSLT, tcc, RV_REG_ZERO, off, ctx);
+ 
+ 	/* prog = array->ptrs[index];
+@@ -324,7 +324,7 @@ static int emit_bpf_tail_call(int insn, struct rv_jit_context *ctx)
+ 	if (is_12b_check(off, insn))
+ 		return -1;
+ 	emit(rv_ld(RV_REG_T2, off, RV_REG_T2), ctx);
+-	off = (tc_ninsn - (ctx->ninsns - start_insn)) << 2;
++	off = ninsns_rvoff(tc_ninsn - (ctx->ninsns - start_insn));
+ 	emit_branch(BPF_JEQ, RV_REG_T2, RV_REG_ZERO, off, ctx);
+ 
+ 	/* goto *(prog->bpf_func + 4); */
+@@ -757,7 +757,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 			e = ctx->ninsns;
+ 
+ 			/* Adjust for extra insns */
+-			rvoff -= (e - s) << 2;
++			rvoff -= ninsns_rvoff(e - s);
+ 		}
+ 
+ 		if (BPF_OP(code) == BPF_JSET) {
+@@ -810,7 +810,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 		e = ctx->ninsns;
+ 
+ 		/* Adjust for extra insns */
+-		rvoff -= (e - s) << 2;
++		rvoff -= ninsns_rvoff(e - s);
+ 		emit_branch(BPF_OP(code), rd, rs, rvoff, ctx);
+ 		break;
+ 
+@@ -831,7 +831,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 		if (!is64 && imm < 0)
+ 			emit(rv_addiw(RV_REG_T1, RV_REG_T1, 0), ctx);
+ 		e = ctx->ninsns;
+-		rvoff -= (e - s) << 2;
++		rvoff -= ninsns_rvoff(e - s);
+ 		emit_branch(BPF_JNE, RV_REG_T1, RV_REG_ZERO, rvoff, ctx);
+ 		break;
+ 
+diff --git a/arch/riscv/net/bpf_jit_core.c b/arch/riscv/net/bpf_jit_core.c
+index 709b94ece3ed..3630d447352c 100644
+--- a/arch/riscv/net/bpf_jit_core.c
++++ b/arch/riscv/net/bpf_jit_core.c
+@@ -73,7 +73,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
+ 
+ 	if (ctx->offset) {
+ 		extra_pass = true;
+-		image_size = sizeof(u32) * ctx->ninsns;
++		image_size = sizeof(*ctx->insns) * ctx->ninsns;
+ 		goto skip_init_ctx;
+ 	}
+ 
+@@ -103,7 +103,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
+ 			if (jit_data->header)
+ 				break;
+ 
+-			image_size = sizeof(u32) * ctx->ninsns;
++			image_size = sizeof(*ctx->insns) * ctx->ninsns;
+ 			jit_data->header =
+ 				bpf_jit_binary_alloc(image_size,
+ 						     &jit_data->image,
+@@ -114,7 +114,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
+ 				goto out_offset;
+ 			}
+ 
+-			ctx->insns = (u32 *)jit_data->image;
++			ctx->insns = (u16 *)jit_data->image;
+ 			/*
+ 			 * Now, when the image is allocated, the image can
+ 			 * potentially shrink more (auipc/jalr -> jal).

commit fd868f14818901821699988fdac680ebd80cd360
+Author: Luke Nelson 
+Date:   Fri May 8 11:15:46 2020 -0700
+
+    bpf, arm64: Optimize ADD,SUB,JMP BPF_K using arm64 add/sub immediates
+    
+    The current code for BPF_{ADD,SUB} BPF_K loads the BPF immediate to a
+    temporary register before performing the addition/subtraction. Similarly,
+    BPF_JMP BPF_K cases load the immediate to a temporary register before
+    comparison.
+    
+    This patch introduces optimizations that use arm64 immediate add, sub,
+    cmn, or cmp instructions when the BPF immediate fits. If the immediate
+    does not fit, it falls back to using a temporary register.
+    
+    Example of generated code for BPF_ALU64_IMM(BPF_ADD, R0, 2):
+    
+    without optimization:
+    
+      24: mov x10, #0x2
+      28: add x7, x7, x10
+    
+    with optimization:
+    
+      24: add x7, x7, #0x2
+    
+    The code could use A64_{ADD,SUB}_I directly and check if it returns
+    AARCH64_BREAK_FAULT, similar to how logical immediates are handled.
+    However, aarch64_insn_gen_add_sub_imm from insn.c prints error messages
+    when the immediate does not fit, and it's simpler to check if the
+    immediate fits ahead of time.
+    
+    Co-developed-by: Xi Wang 
+    Signed-off-by: Xi Wang 
+    Signed-off-by: Luke Nelson 
+    Acked-by: Daniel Borkmann 
+    Link: https://lore.kernel.org/r/20200508181547.24783-4-luke.r.nels@gmail.com
+    Signed-off-by: Will Deacon 
+
+diff --git a/arch/arm64/net/bpf_jit.h b/arch/arm64/net/bpf_jit.h
+index f36a779949e6..923ae7ff68c8 100644
+--- a/arch/arm64/net/bpf_jit.h
++++ b/arch/arm64/net/bpf_jit.h
+@@ -100,6 +100,14 @@
+ /* Rd = Rn OP imm12 */
+ #define A64_ADD_I(sf, Rd, Rn, imm12) A64_ADDSUB_IMM(sf, Rd, Rn, imm12, ADD)
+ #define A64_SUB_I(sf, Rd, Rn, imm12) A64_ADDSUB_IMM(sf, Rd, Rn, imm12, SUB)
++#define A64_ADDS_I(sf, Rd, Rn, imm12) \
++	A64_ADDSUB_IMM(sf, Rd, Rn, imm12, ADD_SETFLAGS)
++#define A64_SUBS_I(sf, Rd, Rn, imm12) \
++	A64_ADDSUB_IMM(sf, Rd, Rn, imm12, SUB_SETFLAGS)
++/* Rn + imm12; set condition flags */
++#define A64_CMN_I(sf, Rn, imm12) A64_ADDS_I(sf, A64_ZR, Rn, imm12)
++/* Rn - imm12; set condition flags */
++#define A64_CMP_I(sf, Rn, imm12) A64_SUBS_I(sf, A64_ZR, Rn, imm12)
+ /* Rd = Rn */
+ #define A64_MOV(sf, Rd, Rn) A64_ADD_I(sf, Rd, Rn, 0)
+ 
+diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
+index 083e5d8a5e2c..561a2fea9cdd 100644
+--- a/arch/arm64/net/bpf_jit_comp.c
++++ b/arch/arm64/net/bpf_jit_comp.c
+@@ -167,6 +167,12 @@ static inline int epilogue_offset(const struct jit_ctx *ctx)
+ 	return to - from;
+ }
+ 
++static bool is_addsub_imm(u32 imm)
++{
++	/* Either imm12 or shifted imm12. */
++	return !(imm & ~0xfff) || !(imm & ~0xfff000);
++}
++
+ /* Stack must be multiples of 16B */
+ #define STACK_ALIGN(sz) (((sz) + 15) & ~15)
+ 
+@@ -479,13 +485,25 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
+ 	/* dst = dst OP imm */
+ 	case BPF_ALU | BPF_ADD | BPF_K:
+ 	case BPF_ALU64 | BPF_ADD | BPF_K:
+-		emit_a64_mov_i(is64, tmp, imm, ctx);
+-		emit(A64_ADD(is64, dst, dst, tmp), ctx);
++		if (is_addsub_imm(imm)) {
++			emit(A64_ADD_I(is64, dst, dst, imm), ctx);
++		} else if (is_addsub_imm(-imm)) {
++			emit(A64_SUB_I(is64, dst, dst, -imm), ctx);
++		} else {
++			emit_a64_mov_i(is64, tmp, imm, ctx);
++			emit(A64_ADD(is64, dst, dst, tmp), ctx);
++		}
+ 		break;
+ 	case BPF_ALU | BPF_SUB | BPF_K:
+ 	case BPF_ALU64 | BPF_SUB | BPF_K:
+-		emit_a64_mov_i(is64, tmp, imm, ctx);
+-		emit(A64_SUB(is64, dst, dst, tmp), ctx);
++		if (is_addsub_imm(imm)) {
++			emit(A64_SUB_I(is64, dst, dst, imm), ctx);
++		} else if (is_addsub_imm(-imm)) {
++			emit(A64_ADD_I(is64, dst, dst, -imm), ctx);
++		} else {
++			emit_a64_mov_i(is64, tmp, imm, ctx);
++			emit(A64_SUB(is64, dst, dst, tmp), ctx);
++		}
+ 		break;
+ 	case BPF_ALU | BPF_AND | BPF_K:
+ 	case BPF_ALU64 | BPF_AND | BPF_K:
+@@ -639,8 +657,14 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
+ 	case BPF_JMP32 | BPF_JSLT | BPF_K:
+ 	case BPF_JMP32 | BPF_JSGE | BPF_K:
+ 	case BPF_JMP32 | BPF_JSLE | BPF_K:
+-		emit_a64_mov_i(is64, tmp, imm, ctx);
+-		emit(A64_CMP(is64, dst, tmp), ctx);
++		if (is_addsub_imm(imm)) {
++			emit(A64_CMP_I(is64, dst, imm), ctx);
++		} else if (is_addsub_imm(-imm)) {
++			emit(A64_CMN_I(is64, dst, -imm), ctx);
++		} else {
++			emit_a64_mov_i(is64, tmp, imm, ctx);
++			emit(A64_CMP(is64, dst, tmp), ctx);
++		}
+ 		goto emit_cond_jmp;
+ 	case BPF_JMP | BPF_JSET | BPF_K:
+ 	case BPF_JMP32 | BPF_JSET | BPF_K:

commit fd49591cb49b72abd1b665222a635ccb17df7923
+Author: Luke Nelson 
+Date:   Fri May 8 11:15:45 2020 -0700
+
+    bpf, arm64: Optimize AND,OR,XOR,JSET BPF_K using arm64 logical immediates
+    
+    The current code for BPF_{AND,OR,XOR,JSET} BPF_K loads the immediate to
+    a temporary register before use.
+    
+    This patch changes the code to avoid using a temporary register
+    when the BPF immediate is encodable using an arm64 logical immediate
+    instruction. If the encoding fails (due to the immediate not being
+    encodable), it falls back to using a temporary register.
+    
+    Example of generated code for BPF_ALU32_IMM(BPF_AND, R0, 0x80000001):
+    
+    without optimization:
+    
+      24: mov  w10, #0x8000ffff
+      28: movk w10, #0x1
+      2c: and  w7, w7, w10
+    
+    with optimization:
+    
+      24: and  w7, w7, #0x80000001
+    
+    Since the encoding process is quite complex, the JIT reuses existing
+    functionality in arch/arm64/kernel/insn.c for encoding logical immediates
+    rather than duplicate it in the JIT.
+    
+    Co-developed-by: Xi Wang 
+    Signed-off-by: Xi Wang 
+    Signed-off-by: Luke Nelson 
+    Acked-by: Daniel Borkmann 
+    Link: https://lore.kernel.org/r/20200508181547.24783-3-luke.r.nels@gmail.com
+    Signed-off-by: Will Deacon 
+
+diff --git a/arch/arm64/net/bpf_jit.h b/arch/arm64/net/bpf_jit.h
+index eb73f9f72c46..f36a779949e6 100644
+--- a/arch/arm64/net/bpf_jit.h
++++ b/arch/arm64/net/bpf_jit.h
+@@ -189,4 +189,18 @@
+ /* Rn & Rm; set condition flags */
+ #define A64_TST(sf, Rn, Rm) A64_ANDS(sf, A64_ZR, Rn, Rm)
+ 
++/* Logical (immediate) */
++#define A64_LOGIC_IMM(sf, Rd, Rn, imm, type) ({ \
++	u64 imm64 = (sf) ? (u64)imm : (u64)(u32)imm; \
++	aarch64_insn_gen_logical_immediate(AARCH64_INSN_LOGIC_##type, \
++		A64_VARIANT(sf), Rn, Rd, imm64); \
++})
++/* Rd = Rn OP imm */
++#define A64_AND_I(sf, Rd, Rn, imm) A64_LOGIC_IMM(sf, Rd, Rn, imm, AND)
++#define A64_ORR_I(sf, Rd, Rn, imm) A64_LOGIC_IMM(sf, Rd, Rn, imm, ORR)
++#define A64_EOR_I(sf, Rd, Rn, imm) A64_LOGIC_IMM(sf, Rd, Rn, imm, EOR)
++#define A64_ANDS_I(sf, Rd, Rn, imm) A64_LOGIC_IMM(sf, Rd, Rn, imm, AND_SETFLAGS)
++/* Rn & imm; set condition flags */
++#define A64_TST_I(sf, Rn, imm) A64_ANDS_I(sf, A64_ZR, Rn, imm)
++
+ #endif /* _BPF_JIT_H */
+diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
+index cdc79de0c794..083e5d8a5e2c 100644
+--- a/arch/arm64/net/bpf_jit_comp.c
++++ b/arch/arm64/net/bpf_jit_comp.c
+@@ -356,6 +356,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
+ 	const bool isdw = BPF_SIZE(code) == BPF_DW;
+ 	u8 jmp_cond, reg;
+ 	s32 jmp_offset;
++	u32 a64_insn;
+ 
+ #define check_imm(bits, imm) do {				\
+ 	if ((((imm) > 0) && ((imm) >> (bits))) ||		\
+@@ -488,18 +489,33 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
+ 		break;
+ 	case BPF_ALU | BPF_AND | BPF_K:
+ 	case BPF_ALU64 | BPF_AND | BPF_K:
+-		emit_a64_mov_i(is64, tmp, imm, ctx);
+-		emit(A64_AND(is64, dst, dst, tmp), ctx);
++		a64_insn = A64_AND_I(is64, dst, dst, imm);
++		if (a64_insn != AARCH64_BREAK_FAULT) {
++			emit(a64_insn, ctx);
++		} else {
++			emit_a64_mov_i(is64, tmp, imm, ctx);
++			emit(A64_AND(is64, dst, dst, tmp), ctx);
++		}
+ 		break;
+ 	case BPF_ALU | BPF_OR | BPF_K:
+ 	case BPF_ALU64 | BPF_OR | BPF_K:
+-		emit_a64_mov_i(is64, tmp, imm, ctx);
+-		emit(A64_ORR(is64, dst, dst, tmp), ctx);
++		a64_insn = A64_ORR_I(is64, dst, dst, imm);
++		if (a64_insn != AARCH64_BREAK_FAULT) {
++			emit(a64_insn, ctx);
++		} else {
++			emit_a64_mov_i(is64, tmp, imm, ctx);
++			emit(A64_ORR(is64, dst, dst, tmp), ctx);
++		}
+ 		break;
+ 	case BPF_ALU | BPF_XOR | BPF_K:
+ 	case BPF_ALU64 | BPF_XOR | BPF_K:
+-		emit_a64_mov_i(is64, tmp, imm, ctx);
+-		emit(A64_EOR(is64, dst, dst, tmp), ctx);
++		a64_insn = A64_EOR_I(is64, dst, dst, imm);
++		if (a64_insn != AARCH64_BREAK_FAULT) {
++			emit(a64_insn, ctx);
++		} else {
++			emit_a64_mov_i(is64, tmp, imm, ctx);
++			emit(A64_EOR(is64, dst, dst, tmp), ctx);
++		}
+ 		break;
+ 	case BPF_ALU | BPF_MUL | BPF_K:
+ 	case BPF_ALU64 | BPF_MUL | BPF_K:
+@@ -628,8 +644,13 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
+ 		goto emit_cond_jmp;
+ 	case BPF_JMP | BPF_JSET | BPF_K:
+ 	case BPF_JMP32 | BPF_JSET | BPF_K:
+-		emit_a64_mov_i(is64, tmp, imm, ctx);
+-		emit(A64_TST(is64, dst, tmp), ctx);
++		a64_insn = A64_TST_I(is64, dst, imm);
++		if (a64_insn != AARCH64_BREAK_FAULT) {
++			emit(a64_insn, ctx);
++		} else {
++			emit_a64_mov_i(is64, tmp, imm, ctx);
++			emit(A64_TST(is64, dst, tmp), ctx);
++		}
+ 		goto emit_cond_jmp;
+ 	/* function call */
+ 	case BPF_JMP | BPF_CALL:

commit 579d1b3faa3735e781ff74aac0afd598515dbc63
+Author: Luke Nelson 
+Date:   Fri May 8 11:15:44 2020 -0700
+
+    arm64: insn: Fix two bugs in encoding 32-bit logical immediates
+    
+    This patch fixes two issues present in the current function for encoding
+    arm64 logical immediates when using the 32-bit variants of instructions.
+    
+    First, the code does not correctly reject an all-ones 32-bit immediate,
+    and returns an undefined instruction encoding.
+    
+    Second, the code incorrectly rejects some 32-bit immediates that are
+    actually encodable as logical immediates. The root cause is that the code
+    uses a default mask of 64-bit all-ones, even for 32-bit immediates.
+    This causes an issue later on when the default mask is used to fill the
+    top bits of the immediate with ones, shown here:
+    
+      /*
+       * Pattern: 0..01..10..01..1
+       *
+       * Fill the unused top bits with ones, and check if
+       * the result is a valid immediate (all ones with a
+       * contiguous ranges of zeroes).
+       */
+      imm |= ~mask;
+      if (!range_of_ones(~imm))
+              return AARCH64_BREAK_FAULT;
+    
+    To see the problem, consider an immediate of the form 0..01..10..01..1,
+    where the upper 32 bits are zero, such as 0x80000001. The code checks
+    if ~(imm | ~mask) contains a range of ones: the incorrect mask yields
+    1..10..01..10..0, which fails the check; the correct mask yields
+    0..01..10..0, which succeeds.
+    
+    The fix for both issues is to generate a correct mask based on the
+    instruction immediate size, and use the mask to check for all-ones,
+    all-zeroes, and values wider than the mask.
+    
+    Currently, arch/arm64/kvm/va_layout.c is the only user of this function,
+    which uses 64-bit immediates and therefore won't trigger these bugs.
+    
+    We tested the new code against llvm-mc with all 1,302 encodable 32-bit
+    logical immediates and all 5,334 encodable 64-bit logical immediates.
+    
+    Fixes: ef3935eeebff ("arm64: insn: Add encoder for bitwise operations using literals")
+    Suggested-by: Will Deacon 
+    Co-developed-by: Xi Wang 
+    Signed-off-by: Xi Wang 
+    Signed-off-by: Luke Nelson 
+    Reviewed-by: Marc Zyngier 
+    Link: https://lore.kernel.org/r/20200508181547.24783-2-luke.r.nels@gmail.com
+    Signed-off-by: Will Deacon 
+
+diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
+index 4a9e773a177f..cc2f3d901c91 100644
+--- a/arch/arm64/kernel/insn.c
++++ b/arch/arm64/kernel/insn.c
+@@ -1535,16 +1535,10 @@ static u32 aarch64_encode_immediate(u64 imm,
+ 				    u32 insn)
+ {
+ 	unsigned int immr, imms, n, ones, ror, esz, tmp;
+-	u64 mask = ~0UL;
+-
+-	/* Can't encode full zeroes or full ones */
+-	if (!imm || !~imm)
+-		return AARCH64_BREAK_FAULT;
++	u64 mask;
+ 
+ 	switch (variant) {
+ 	case AARCH64_INSN_VARIANT_32BIT:
+-		if (upper_32_bits(imm))
+-			return AARCH64_BREAK_FAULT;
+ 		esz = 32;
+ 		break;
+ 	case AARCH64_INSN_VARIANT_64BIT:
+@@ -1556,6 +1550,12 @@ static u32 aarch64_encode_immediate(u64 imm,
+ 		return AARCH64_BREAK_FAULT;
+ 	}
+ 
++	mask = GENMASK(esz - 1, 0);
++
++	/* Can't encode full zeroes, full ones, or value wider than the mask */
++	if (!imm || imm == mask || imm & ~mask)
++		return AARCH64_BREAK_FAULT;
++
+ 	/*
+ 	 * Inverse of Replicate(). Try to spot a repeating pattern
+ 	 * with a pow2 stride.

commit 073ca6a0369e09c586a103e665f2dd67f1c71444
+Author: Luke Nelson 
+Date:   Tue May 5 17:03:20 2020 -0700
+
+    bpf, riscv: Optimize BPF_JSET BPF_K using andi on RV64
+    
+    This patch optimizes BPF_JSET BPF_K by using a RISC-V andi instruction
+    when the BPF immediate fits in 12 bits, instead of first loading the
+    immediate to a temporary register.
+    
+    Examples of generated code with and without this optimization:
+    
+    BPF_JMP_IMM(BPF_JSET, R1, 2, 1) without optimization:
+    
+      20: li    t1,2
+      24: and   t1,a0,t1
+      28: bnez  t1,0x30
+    
+    BPF_JMP_IMM(BPF_JSET, R1, 2, 1) with optimization:
+    
+      20: andi  t1,a0,2
+      24: bnez  t1,0x2c
+    
+    BPF_JMP32_IMM(BPF_JSET, R1, 2, 1) without optimization:
+    
+      20: li    t1,2
+      24: mv    t2,a0
+      28: slli  t2,t2,0x20
+      2c: srli  t2,t2,0x20
+      30: slli  t1,t1,0x20
+      34: srli  t1,t1,0x20
+      38: and   t1,t2,t1
+      3c: bnez  t1,0x44
+    
+    BPF_JMP32_IMM(BPF_JSET, R1, 2, 1) with optimization:
+    
+      20: andi  t1,a0,2
+      24: bnez  t1,0x2c
+    
+    In these examples, because the upper 32 bits of the sign-extended
+    immediate are 0, BPF_JMP BPF_JSET and BPF_JMP32 BPF_JSET are equivalent
+    and therefore the JIT produces identical code for them.
+    
+    Co-developed-by: Xi Wang 
+    Signed-off-by: Xi Wang 
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Daniel Borkmann 
+    Reviewed-by: Björn Töpel 
+    Acked-by: Björn Töpel 
+    Link: https://lore.kernel.org/bpf/20200506000320.28965-5-luke.r.nels@gmail.com
+
+diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
+index b07cef952019..6cfd164cbe88 100644
+--- a/arch/riscv/net/bpf_jit_comp64.c
++++ b/arch/riscv/net/bpf_jit_comp64.c
+@@ -792,8 +792,6 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 	case BPF_JMP32 | BPF_JSGE | BPF_K:
+ 	case BPF_JMP | BPF_JSLE | BPF_K:
+ 	case BPF_JMP32 | BPF_JSLE | BPF_K:
+-	case BPF_JMP | BPF_JSET | BPF_K:
+-	case BPF_JMP32 | BPF_JSET | BPF_K:
+ 		rvoff = rv_offset(i, off, ctx);
+ 		s = ctx->ninsns;
+ 		if (imm) {
+@@ -813,15 +811,28 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 
+ 		/* Adjust for extra insns */
+ 		rvoff -= (e - s) << 2;
++		emit_branch(BPF_OP(code), rd, rs, rvoff, ctx);
++		break;
+ 
+-		if (BPF_OP(code) == BPF_JSET) {
+-			/* Adjust for and */
+-			rvoff -= 4;
+-			emit(rv_and(rs, rd, rs), ctx);
+-			emit_branch(BPF_JNE, rs, RV_REG_ZERO, rvoff, ctx);
++	case BPF_JMP | BPF_JSET | BPF_K:
++	case BPF_JMP32 | BPF_JSET | BPF_K:
++		rvoff = rv_offset(i, off, ctx);
++		s = ctx->ninsns;
++		if (is_12b_int(imm)) {
++			emit(rv_andi(RV_REG_T1, rd, imm), ctx);
+ 		} else {
+-			emit_branch(BPF_OP(code), rd, rs, rvoff, ctx);
++			emit_imm(RV_REG_T1, imm, ctx);
++			emit(rv_and(RV_REG_T1, rd, RV_REG_T1), ctx);
+ 		}
++		/* For jset32, we should clear the upper 32 bits of t1, but
++		 * sign-extension is sufficient here and saves one instruction,
++		 * as t1 is used only in comparison against zero.
++		 */
++		if (!is64 && imm < 0)
++			emit(rv_addiw(RV_REG_T1, RV_REG_T1, 0), ctx);
++		e = ctx->ninsns;
++		rvoff -= (e - s) << 2;
++		emit_branch(BPF_JNE, RV_REG_T1, RV_REG_ZERO, rvoff, ctx);
+ 		break;
+ 
+ 	/* function call */

commit ca349a6a104e58479defdc08ce56472a48f7cb81
+Author: Luke Nelson 
+Date:   Tue May 5 17:03:19 2020 -0700
+
+    bpf, riscv: Optimize BPF_JMP BPF_K when imm == 0 on RV64
+    
+    This patch adds an optimization to BPF_JMP (32- and 64-bit) BPF_K for
+    when the BPF immediate is zero.
+    
+    When the immediate is zero, the code can directly use the RISC-V zero
+    register instead of loading a zero immediate to a temporary register
+    first.
+    
+    Co-developed-by: Xi Wang 
+    Signed-off-by: Xi Wang 
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Daniel Borkmann 
+    Reviewed-by: Björn Töpel 
+    Acked-by: Björn Töpel 
+    Link: https://lore.kernel.org/bpf/20200506000320.28965-4-luke.r.nels@gmail.com
+
+diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
+index c3ce9a911b66..b07cef952019 100644
+--- a/arch/riscv/net/bpf_jit_comp64.c
++++ b/arch/riscv/net/bpf_jit_comp64.c
+@@ -796,7 +796,13 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 	case BPF_JMP32 | BPF_JSET | BPF_K:
+ 		rvoff = rv_offset(i, off, ctx);
+ 		s = ctx->ninsns;
+-		emit_imm(RV_REG_T1, imm, ctx);
++		if (imm) {
++			emit_imm(RV_REG_T1, imm, ctx);
++			rs = RV_REG_T1;
++		} else {
++			/* If imm is 0, simply use zero register. */
++			rs = RV_REG_ZERO;
++		}
+ 		if (!is64) {
+ 			if (is_signed_bpf_cond(BPF_OP(code)))
+ 				emit_sext_32_rd(&rd, ctx);
+@@ -811,11 +817,10 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 		if (BPF_OP(code) == BPF_JSET) {
+ 			/* Adjust for and */
+ 			rvoff -= 4;
+-			emit(rv_and(RV_REG_T1, rd, RV_REG_T1), ctx);
+-			emit_branch(BPF_JNE, RV_REG_T1, RV_REG_ZERO, rvoff,
+-				    ctx);
++			emit(rv_and(rs, rd, rs), ctx);
++			emit_branch(BPF_JNE, rs, RV_REG_ZERO, rvoff, ctx);
+ 		} else {
+-			emit_branch(BPF_OP(code), rd, RV_REG_T1, rvoff, ctx);
++			emit_branch(BPF_OP(code), rd, rs, rvoff, ctx);
+ 		}
+ 		break;
+ 

commit 21a099abb765c3754689e1f7ca4536fa560112d0
+Author: Luke Nelson 
+Date:   Tue May 5 17:03:18 2020 -0700
+
+    bpf, riscv: Optimize FROM_LE using verifier_zext on RV64
+    
+    This patch adds two optimizations for BPF_ALU BPF_END BPF_FROM_LE in
+    the RV64 BPF JIT.
+    
+    First, it enables the verifier zero-extension optimization to avoid zero
+    extension when imm == 32. Second, it avoids generating code for imm ==
+    64, since it is equivalent to a no-op.
+    
+    Co-developed-by: Xi Wang 
+    Signed-off-by: Xi Wang 
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Daniel Borkmann 
+    Reviewed-by: Björn Töpel 
+    Acked-by: Björn Töpel 
+    Link: https://lore.kernel.org/bpf/20200506000320.28965-3-luke.r.nels@gmail.com
+
+diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
+index e2636902a74e..c3ce9a911b66 100644
+--- a/arch/riscv/net/bpf_jit_comp64.c
++++ b/arch/riscv/net/bpf_jit_comp64.c
+@@ -542,13 +542,21 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 
+ 	/* dst = BSWAP##imm(dst) */
+ 	case BPF_ALU | BPF_END | BPF_FROM_LE:
+-	{
+-		int shift = 64 - imm;
+-
+-		emit(rv_slli(rd, rd, shift), ctx);
+-		emit(rv_srli(rd, rd, shift), ctx);
++		switch (imm) {
++		case 16:
++			emit(rv_slli(rd, rd, 48), ctx);
++			emit(rv_srli(rd, rd, 48), ctx);
++			break;
++		case 32:
++			if (!aux->verifier_zext)
++				emit_zext_32(rd, ctx);
++			break;
++		case 64:
++			/* Do nothing */
++			break;
++		}
+ 		break;
+-	}
++
+ 	case BPF_ALU | BPF_END | BPF_FROM_BE:
+ 		emit(rv_addi(RV_REG_T2, RV_REG_ZERO, 0), ctx);
+ 

commit 0224b2acea0f9e3908d33e27b2dcb4e04686e997
+Author: Luke Nelson 
+Date:   Tue May 5 17:03:17 2020 -0700
+
+    bpf, riscv: Enable missing verifier_zext optimizations on RV64
+    
+    Commit 66d0d5a854a6 ("riscv: bpf: eliminate zero extension code-gen")
+    added support for the verifier zero-extension optimization on RV64 and
+    commit 46dd3d7d287b ("bpf, riscv: Enable zext optimization for more
+    RV64G ALU ops") enabled it for more instruction cases.
+    
+    However, BPF_LSH BPF_X and BPF_{LSH,RSH,ARSH} BPF_K are still missing
+    the optimization.
+    
+    This patch enables the zero-extension optimization for these remaining
+    cases.
+    
+    Co-developed-by: Xi Wang 
+    Signed-off-by: Xi Wang 
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Daniel Borkmann 
+    Reviewed-by: Björn Töpel 
+    Acked-by: Björn Töpel 
+    Link: https://lore.kernel.org/bpf/20200506000320.28965-2-luke.r.nels@gmail.com
+
+diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
+index d208a9fd6c52..e2636902a74e 100644
+--- a/arch/riscv/net/bpf_jit_comp64.c
++++ b/arch/riscv/net/bpf_jit_comp64.c
+@@ -515,7 +515,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 	case BPF_ALU | BPF_LSH | BPF_X:
+ 	case BPF_ALU64 | BPF_LSH | BPF_X:
+ 		emit(is64 ? rv_sll(rd, rd, rs) : rv_sllw(rd, rd, rs), ctx);
+-		if (!is64)
++		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+ 		break;
+ 	case BPF_ALU | BPF_RSH | BPF_X:
+@@ -692,19 +692,19 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 	case BPF_ALU | BPF_LSH | BPF_K:
+ 	case BPF_ALU64 | BPF_LSH | BPF_K:
+ 		emit(is64 ? rv_slli(rd, rd, imm) : rv_slliw(rd, rd, imm), ctx);
+-		if (!is64)
++		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+ 		break;
+ 	case BPF_ALU | BPF_RSH | BPF_K:
+ 	case BPF_ALU64 | BPF_RSH | BPF_K:
+ 		emit(is64 ? rv_srli(rd, rd, imm) : rv_srliw(rd, rd, imm), ctx);
+-		if (!is64)
++		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+ 		break;
+ 	case BPF_ALU | BPF_ARSH | BPF_K:
+ 	case BPF_ALU64 | BPF_ARSH | BPF_K:
+ 		emit(is64 ? rv_srai(rd, rd, imm) : rv_sraiw(rd, rd, imm), ctx);
+-		if (!is64)
++		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+ 		break;
+ 

commit c648c9c7429e979ca081359f39b6902aed92d490
+Author: Luke Nelson 
+Date:   Thu Apr 30 19:02:10 2020 -0700
+
+    bpf, arm: Optimize ALU ARSH K using asr immediate instruction
+    
+    This patch adds an optimization that uses the asr immediate instruction
+    for BPF_ALU BPF_ARSH BPF_K, rather than loading the immediate to
+    a temporary register. This is similar to existing code for handling
+    BPF_ALU BPF_{LSH,RSH} BPF_K. This optimization saves two instructions
+    and is more consistent with LSH and RSH.
+    
+    Example of the code generated for BPF_ALU32_IMM(BPF_ARSH, BPF_REG_0, 5)
+    before the optimization:
+    
+      2c:  mov    r8, #5
+      30:  mov    r9, #0
+      34:  asr    r0, r0, r8
+    
+    and after optimization:
+    
+      2c:  asr    r0, r0, #5
+    
+    Tested on QEMU using lib/test_bpf and test_verifier.
+    
+    Co-developed-by: Xi Wang 
+    Signed-off-by: Xi Wang 
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Daniel Borkmann 
+    Link: https://lore.kernel.org/bpf/20200501020210.32294-3-luke.r.nels@gmail.com
+
+diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
+index 48b89211ee5c..0207b6ea6e8a 100644
+--- a/arch/arm/net/bpf_jit_32.c
++++ b/arch/arm/net/bpf_jit_32.c
+@@ -795,6 +795,9 @@ static inline void emit_a32_alu_i(const s8 dst, const u32 val,
+ 	case BPF_RSH:
+ 		emit(ARM_LSR_I(rd, rd, val), ctx);
+ 		break;
++	case BPF_ARSH:
++		emit(ARM_ASR_I(rd, rd, val), ctx);
++		break;
+ 	case BPF_NEG:
+ 		emit(ARM_RSB_I(rd, rd, val), ctx);
+ 		break;
+@@ -1408,7 +1411,6 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
+ 	case BPF_ALU | BPF_MUL | BPF_X:
+ 	case BPF_ALU | BPF_LSH | BPF_X:
+ 	case BPF_ALU | BPF_RSH | BPF_X:
+-	case BPF_ALU | BPF_ARSH | BPF_K:
+ 	case BPF_ALU | BPF_ARSH | BPF_X:
+ 	case BPF_ALU64 | BPF_ADD | BPF_K:
+ 	case BPF_ALU64 | BPF_ADD | BPF_X:
+@@ -1465,10 +1467,12 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
+ 	case BPF_ALU64 | BPF_MOD | BPF_K:
+ 	case BPF_ALU64 | BPF_MOD | BPF_X:
+ 		goto notyet;
+-	/* dst = dst >> imm */
+ 	/* dst = dst << imm */
+-	case BPF_ALU | BPF_RSH | BPF_K:
++	/* dst = dst >> imm */
++	/* dst = dst >> imm (signed) */
+ 	case BPF_ALU | BPF_LSH | BPF_K:
++	case BPF_ALU | BPF_RSH | BPF_K:
++	case BPF_ALU | BPF_ARSH | BPF_K:
+ 		if (unlikely(imm > 31))
+ 			return -EINVAL;
+ 		if (imm)
+diff --git a/arch/arm/net/bpf_jit_32.h b/arch/arm/net/bpf_jit_32.h
+index fb67cbc589e0..e0b593a1498d 100644
+--- a/arch/arm/net/bpf_jit_32.h
++++ b/arch/arm/net/bpf_jit_32.h
+@@ -94,6 +94,9 @@
+ #define ARM_INST_LSR_I		0x01a00020
+ #define ARM_INST_LSR_R		0x01a00030
+ 
++#define ARM_INST_ASR_I		0x01a00040
++#define ARM_INST_ASR_R		0x01a00050
++
+ #define ARM_INST_MOV_R		0x01a00000
+ #define ARM_INST_MOVS_R		0x01b00000
+ #define ARM_INST_MOV_I		0x03a00000

commit cf48db69bdfad2930b95fd51d64444e5a7b469ae
+Author: Luke Nelson 
+Date:   Thu Apr 30 19:02:09 2020 -0700
+
+    bpf, arm: Optimize ALU64 ARSH X using orrpl conditional instruction
+    
+    This patch optimizes the code generated by emit_a32_arsh_r64, which
+    handles the BPF_ALU64 BPF_ARSH BPF_X instruction.
+    
+    The original code uses a conditional B followed by an unconditional ORR.
+    The optimization saves one instruction by removing the B instruction
+    and using a conditional ORR (with an inverted condition).
+    
+    Example of the code generated for BPF_ALU64_REG(BPF_ARSH, BPF_REG_0,
+    BPF_REG_1), before optimization:
+    
+      34:  rsb    ip, r2, #32
+      38:  subs   r9, r2, #32
+      3c:  lsr    lr, r0, r2
+      40:  orr    lr, lr, r1, lsl ip
+      44:  bmi    0x4c
+      48:  orr    lr, lr, r1, asr r9
+      4c:  asr    ip, r1, r2
+      50:  mov    r0, lr
+      54:  mov    r1, ip
+    
+    and after optimization:
+    
+      34:  rsb    ip, r2, #32
+      38:  subs   r9, r2, #32
+      3c:  lsr    lr, r0, r2
+      40:  orr    lr, lr, r1, lsl ip
+      44:  orrpl  lr, lr, r1, asr r9
+      48:  asr    ip, r1, r2
+      4c:  mov    r0, lr
+      50:  mov    r1, ip
+    
+    Tested on QEMU using lib/test_bpf and test_verifier.
+    
+    Co-developed-by: Xi Wang 
+    Signed-off-by: Xi Wang 
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Daniel Borkmann 
+    Link: https://lore.kernel.org/bpf/20200501020210.32294-2-luke.r.nels@gmail.com
+
+diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
+index bf85d6db4931..48b89211ee5c 100644
+--- a/arch/arm/net/bpf_jit_32.c
++++ b/arch/arm/net/bpf_jit_32.c
+@@ -860,8 +860,8 @@ static inline void emit_a32_arsh_r64(const s8 dst[], const s8 src[],
+ 	emit(ARM_SUBS_I(tmp2[0], rt, 32), ctx);
+ 	emit(ARM_MOV_SR(ARM_LR, rd[1], SRTYPE_LSR, rt), ctx);
+ 	emit(ARM_ORR_SR(ARM_LR, ARM_LR, rd[0], SRTYPE_ASL, ARM_IP), ctx);
+-	_emit(ARM_COND_MI, ARM_B(0), ctx);
+-	emit(ARM_ORR_SR(ARM_LR, ARM_LR, rd[0], SRTYPE_ASR, tmp2[0]), ctx);
++	_emit(ARM_COND_PL,
++	      ARM_ORR_SR(ARM_LR, ARM_LR, rd[0], SRTYPE_ASR, tmp2[0]), ctx);
+ 	emit(ARM_MOV_SR(ARM_IP, rd[0], SRTYPE_ASR, rt), ctx);
+ 
+ 	arm_bpf_put_reg32(dst_lo, ARM_LR, ctx);

commit 91f658587a962378a410cc7dc90e122a4ccd7cf3
+Author: Luke Nelson 
+Date:   Wed Apr 29 17:51:27 2020 -0700
+
+    bpf, riscv: Fix stack layout of JITed code on RV32
+    
+    This patch fixes issues with stackframe unwinding and alignment in the
+    current stack layout for BPF programs on RV32.
+    
+    In the current layout, RV32 fp points to the JIT scratch registers, rather
+    than to the callee-saved registers. This breaks stackframe unwinding,
+    which expects fp to point just above the saved ra and fp registers.
+    
+    This patch fixes the issue by moving the callee-saved registers to be
+    stored on the top of the stack, pointed to by fp. This satisfies the
+    assumptions of stackframe unwinding.
+    
+    This patch also fixes an issue with the old layout that the stack was
+    not aligned to 16 bytes.
+    
+    Stacktrace from JITed code using the old stack layout:
+    
+      [   12.196249 ] [] walk_stackframe+0x0/0x96
+    
+    Stacktrace using the new stack layout:
+    
+      [   13.062888 ] [] walk_stackframe+0x0/0x96
+      [   13.063028 ] [] show_stack+0x28/0x32
+      [   13.063253 ] [] bpf_prog_82b916b2dfa00464+0x80/0x908
+      [   13.063417 ] [] bpf_test_run+0x124/0x39a
+      [   13.063553 ] [] bpf_prog_test_run_skb+0x234/0x448
+      [   13.063704 ] [] __do_sys_bpf+0x766/0x13b4
+      [   13.063840 ] [] sys_bpf+0xc/0x14
+      [   13.063961 ] [] ret_from_syscall+0x0/0x2
+    
+    The new code is also simpler to understand and includes an ASCII diagram
+    of the stack layout.
+    
+    Tested on riscv32 QEMU virt machine.
+    
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Daniel Borkmann 
+    Acked-by: Xi Wang 
+    Link: https://lore.kernel.org/bpf/20200430005127.2205-1-luke.r.nels@gmail.com
+
+diff --git a/arch/riscv/net/bpf_jit_comp32.c b/arch/riscv/net/bpf_jit_comp32.c
+index 11083d4d5f2d..b198eaa74456 100644
+--- a/arch/riscv/net/bpf_jit_comp32.c
++++ b/arch/riscv/net/bpf_jit_comp32.c
+@@ -13,8 +13,35 @@
+ #include 
+ #include "bpf_jit.h"
+ 
++/*
++ * Stack layout during BPF program execution:
++ *
++ *                     high
++ *     RV32 fp =>  +----------+
++ *                 | saved ra |
++ *                 | saved fp | RV32 callee-saved registers
++ *                 |   ...    |
++ *                 +----------+ <= (fp - 4 * NR_SAVED_REGISTERS)
++ *                 |  hi(R6)  |
++ *                 |  lo(R6)  |
++ *                 |  hi(R7)  | JIT scratch space for BPF registers
++ *                 |  lo(R7)  |
++ *                 |   ...    |
++ *  BPF_REG_FP =>  +----------+ <= (fp - 4 * NR_SAVED_REGISTERS
++ *                 |          |        - 4 * BPF_JIT_SCRATCH_REGS)
++ *                 |          |
++ *                 |   ...    | BPF program stack
++ *                 |          |
++ *     RV32 sp =>  +----------+
++ *                 |          |
++ *                 |   ...    | Function call stack
++ *                 |          |
++ *                 +----------+
++ *                     low
++ */
++
+ enum {
+-	/* Stack layout - these are offsets from (top of stack - 4). */
++	/* Stack layout - these are offsets from top of JIT scratch space. */
+ 	BPF_R6_HI,
+ 	BPF_R6_LO,
+ 	BPF_R7_HI,
+@@ -29,7 +56,11 @@ enum {
+ 	BPF_JIT_SCRATCH_REGS,
+ };
+ 
+-#define STACK_OFFSET(k) (-4 - ((k) * 4))
++/* Number of callee-saved registers stored to stack: ra, fp, s1--s7. */
++#define NR_SAVED_REGISTERS	9
++
++/* Offset from fp for BPF registers stored on stack. */
++#define STACK_OFFSET(k)	(-4 - (4 * NR_SAVED_REGISTERS) - (4 * (k)))
+ 
+ #define TMP_REG_1	(MAX_BPF_JIT_REG + 0)
+ #define TMP_REG_2	(MAX_BPF_JIT_REG + 1)
+@@ -111,11 +142,9 @@ static void emit_imm64(const s8 *rd, s32 imm_hi, s32 imm_lo,
+ 
+ static void __build_epilogue(bool is_tail_call, struct rv_jit_context *ctx)
+ {
+-	int stack_adjust = ctx->stack_size, store_offset = stack_adjust - 4;
++	int stack_adjust = ctx->stack_size;
+ 	const s8 *r0 = bpf2rv32[BPF_REG_0];
+ 
+-	store_offset -= 4 * BPF_JIT_SCRATCH_REGS;
+-
+ 	/* Set return value if not tail call. */
+ 	if (!is_tail_call) {
+ 		emit(rv_addi(RV_REG_A0, lo(r0), 0), ctx);
+@@ -123,15 +152,15 @@ static void __build_epilogue(bool is_tail_call, struct rv_jit_context *ctx)
+ 	}
+ 
+ 	/* Restore callee-saved registers. */
+-	emit(rv_lw(RV_REG_RA, store_offset - 0, RV_REG_SP), ctx);
+-	emit(rv_lw(RV_REG_FP, store_offset - 4, RV_REG_SP), ctx);
+-	emit(rv_lw(RV_REG_S1, store_offset - 8, RV_REG_SP), ctx);
+-	emit(rv_lw(RV_REG_S2, store_offset - 12, RV_REG_SP), ctx);
+-	emit(rv_lw(RV_REG_S3, store_offset - 16, RV_REG_SP), ctx);
+-	emit(rv_lw(RV_REG_S4, store_offset - 20, RV_REG_SP), ctx);
+-	emit(rv_lw(RV_REG_S5, store_offset - 24, RV_REG_SP), ctx);
+-	emit(rv_lw(RV_REG_S6, store_offset - 28, RV_REG_SP), ctx);
+-	emit(rv_lw(RV_REG_S7, store_offset - 32, RV_REG_SP), ctx);
++	emit(rv_lw(RV_REG_RA, stack_adjust - 4, RV_REG_SP), ctx);
++	emit(rv_lw(RV_REG_FP, stack_adjust - 8, RV_REG_SP), ctx);
++	emit(rv_lw(RV_REG_S1, stack_adjust - 12, RV_REG_SP), ctx);
++	emit(rv_lw(RV_REG_S2, stack_adjust - 16, RV_REG_SP), ctx);
++	emit(rv_lw(RV_REG_S3, stack_adjust - 20, RV_REG_SP), ctx);
++	emit(rv_lw(RV_REG_S4, stack_adjust - 24, RV_REG_SP), ctx);
++	emit(rv_lw(RV_REG_S5, stack_adjust - 28, RV_REG_SP), ctx);
++	emit(rv_lw(RV_REG_S6, stack_adjust - 32, RV_REG_SP), ctx);
++	emit(rv_lw(RV_REG_S7, stack_adjust - 36, RV_REG_SP), ctx);
+ 
+ 	emit(rv_addi(RV_REG_SP, RV_REG_SP, stack_adjust), ctx);
+ 
+@@ -1260,17 +1289,20 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 
+ void bpf_jit_build_prologue(struct rv_jit_context *ctx)
+ {
+-	/* Make space to save 9 registers: ra, fp, s1--s7. */
+-	int stack_adjust = 9 * sizeof(u32), store_offset, bpf_stack_adjust;
+ 	const s8 *fp = bpf2rv32[BPF_REG_FP];
+ 	const s8 *r1 = bpf2rv32[BPF_REG_1];
+-
+-	bpf_stack_adjust = round_up(ctx->prog->aux->stack_depth, 16);
++	int stack_adjust = 0;
++	int bpf_stack_adjust =
++		round_up(ctx->prog->aux->stack_depth, STACK_ALIGN);
++
++	/* Make space for callee-saved registers. */
++	stack_adjust += NR_SAVED_REGISTERS * sizeof(u32);
++	/* Make space for BPF registers on stack. */
++	stack_adjust += BPF_JIT_SCRATCH_REGS * sizeof(u32);
++	/* Make space for BPF stack. */
+ 	stack_adjust += bpf_stack_adjust;
+-
+-	store_offset = stack_adjust - 4;
+-
+-	stack_adjust += 4 * BPF_JIT_SCRATCH_REGS;
++	/* Round up for stack alignment. */
++	stack_adjust = round_up(stack_adjust, STACK_ALIGN);
+ 
+ 	/*
+ 	 * The first instruction sets the tail-call-counter (TCC) register.
+@@ -1281,24 +1313,24 @@ void bpf_jit_build_prologue(struct rv_jit_context *ctx)
+ 	emit(rv_addi(RV_REG_SP, RV_REG_SP, -stack_adjust), ctx);
+ 
+ 	/* Save callee-save registers. */
+-	emit(rv_sw(RV_REG_SP, store_offset - 0, RV_REG_RA), ctx);
+-	emit(rv_sw(RV_REG_SP, store_offset - 4, RV_REG_FP), ctx);
+-	emit(rv_sw(RV_REG_SP, store_offset - 8, RV_REG_S1), ctx);
+-	emit(rv_sw(RV_REG_SP, store_offset - 12, RV_REG_S2), ctx);
+-	emit(rv_sw(RV_REG_SP, store_offset - 16, RV_REG_S3), ctx);
+-	emit(rv_sw(RV_REG_SP, store_offset - 20, RV_REG_S4), ctx);
+-	emit(rv_sw(RV_REG_SP, store_offset - 24, RV_REG_S5), ctx);
+-	emit(rv_sw(RV_REG_SP, store_offset - 28, RV_REG_S6), ctx);
+-	emit(rv_sw(RV_REG_SP, store_offset - 32, RV_REG_S7), ctx);
++	emit(rv_sw(RV_REG_SP, stack_adjust - 4, RV_REG_RA), ctx);
++	emit(rv_sw(RV_REG_SP, stack_adjust - 8, RV_REG_FP), ctx);
++	emit(rv_sw(RV_REG_SP, stack_adjust - 12, RV_REG_S1), ctx);
++	emit(rv_sw(RV_REG_SP, stack_adjust - 16, RV_REG_S2), ctx);
++	emit(rv_sw(RV_REG_SP, stack_adjust - 20, RV_REG_S3), ctx);
++	emit(rv_sw(RV_REG_SP, stack_adjust - 24, RV_REG_S4), ctx);
++	emit(rv_sw(RV_REG_SP, stack_adjust - 28, RV_REG_S5), ctx);
++	emit(rv_sw(RV_REG_SP, stack_adjust - 32, RV_REG_S6), ctx);
++	emit(rv_sw(RV_REG_SP, stack_adjust - 36, RV_REG_S7), ctx);
+ 
+ 	/* Set fp: used as the base address for stacked BPF registers. */
+ 	emit(rv_addi(RV_REG_FP, RV_REG_SP, stack_adjust), ctx);
+ 
+-	/* Set up BPF stack pointer. */
++	/* Set up BPF frame pointer. */
+ 	emit(rv_addi(lo(fp), RV_REG_SP, bpf_stack_adjust), ctx);
+ 	emit(rv_addi(hi(fp), RV_REG_ZERO, 0), ctx);
+ 
+-	/* Set up context pointer. */
++	/* Set up BPF context pointer. */
+ 	emit(rv_addi(lo(r1), RV_REG_A0, 0), ctx);
+ 	emit(rv_addi(hi(r1), RV_REG_ZERO, 0), ctx);
+ 

commit 745abfaa9eafa597d31fdf24a3249e5206a98768
+Author: Luke Nelson 
+Date:   Mon Apr 20 17:28:04 2020 -0700
+
+    bpf, riscv: Fix tail call count off by one in RV32 BPF JIT
+    
+    This patch fixes an off by one error in the RV32 JIT handling for BPF
+    tail call. Currently, the code decrements TCC before checking if it
+    is less than zero. This limits the maximum number of tail calls to 32
+    instead of 33 as in other JITs. The fix is to instead check the old
+    value of TCC before decrementing.
+    
+    Fixes: 5f316b65e99f ("riscv, bpf: Add RV32G eBPF JIT")
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Alexei Starovoitov 
+    Acked-by: Xi Wang 
+    Link: https://lore.kernel.org/bpf/20200421002804.5118-1-luke.r.nels@gmail.com
+
+diff --git a/arch/riscv/net/bpf_jit_comp32.c b/arch/riscv/net/bpf_jit_comp32.c
+index 302934177760..11083d4d5f2d 100644
+--- a/arch/riscv/net/bpf_jit_comp32.c
++++ b/arch/riscv/net/bpf_jit_comp32.c
+@@ -770,12 +770,13 @@ static int emit_bpf_tail_call(int insn, struct rv_jit_context *ctx)
+ 	emit_bcc(BPF_JGE, lo(idx_reg), RV_REG_T1, off, ctx);
+ 
+ 	/*
+-	 * if ((temp_tcc = tcc - 1) < 0)
++	 * temp_tcc = tcc - 1;
++	 * if (tcc < 0)
+ 	 *   goto out;
+ 	 */
+ 	emit(rv_addi(RV_REG_T1, RV_REG_TCC, -1), ctx);
+ 	off = (tc_ninsn - (ctx->ninsns - start_insn)) << 2;
+-	emit_bcc(BPF_JSLT, RV_REG_T1, RV_REG_ZERO, off, ctx);
++	emit_bcc(BPF_JSLT, RV_REG_TCC, RV_REG_ZERO, off, ctx);
+ 
+ 	/*
+ 	 * prog = array->ptrs[index];

commit 50fe7ebb6475711c15b3397467e6424e20026d94
+Author: Luke Nelson 
+Date:   Wed Apr 22 10:36:30 2020 -0700
+
+    bpf, x86_32: Fix clobbering of dst for BPF_JSET
+    
+    The current JIT clobbers the destination register for BPF_JSET BPF_X
+    and BPF_K by using "and" and "or" instructions. This is fine when the
+    destination register is a temporary loaded from a register stored on
+    the stack but not otherwise.
+    
+    This patch fixes the problem (for both BPF_K and BPF_X) by always loading
+    the destination register into temporaries since BPF_JSET should not
+    modify the destination register.
+    
+    This bug may not be currently triggerable as BPF_REG_AX is the only
+    register not stored on the stack and the verifier uses it in a limited
+    way.
+    
+    Fixes: 03f5781be2c7b ("bpf, x86_32: add eBPF JIT compiler for ia32")
+    Signed-off-by: Xi Wang 
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Alexei Starovoitov 
+    Acked-by: Wang YanQing 
+    Link: https://lore.kernel.org/bpf/20200422173630.8351-2-luke.r.nels@gmail.com
+
+diff --git a/arch/x86/net/bpf_jit_comp32.c b/arch/x86/net/bpf_jit_comp32.c
+index cc9ad3892ea6..ba7d9ccfc662 100644
+--- a/arch/x86/net/bpf_jit_comp32.c
++++ b/arch/x86/net/bpf_jit_comp32.c
+@@ -2015,8 +2015,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
+ 		case BPF_JMP | BPF_JSET | BPF_X:
+ 		case BPF_JMP32 | BPF_JSET | BPF_X: {
+ 			bool is_jmp64 = BPF_CLASS(insn->code) == BPF_JMP;
+-			u8 dreg_lo = dstk ? IA32_EAX : dst_lo;
+-			u8 dreg_hi = dstk ? IA32_EDX : dst_hi;
++			u8 dreg_lo = IA32_EAX;
++			u8 dreg_hi = IA32_EDX;
+ 			u8 sreg_lo = sstk ? IA32_ECX : src_lo;
+ 			u8 sreg_hi = sstk ? IA32_EBX : src_hi;
+ 
+@@ -2028,6 +2028,13 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
+ 					      add_2reg(0x40, IA32_EBP,
+ 						       IA32_EDX),
+ 					      STACK_VAR(dst_hi));
++			} else {
++				/* mov dreg_lo,dst_lo */
++				EMIT2(0x89, add_2reg(0xC0, dreg_lo, dst_lo));
++				if (is_jmp64)
++					/* mov dreg_hi,dst_hi */
++					EMIT2(0x89,
++					      add_2reg(0xC0, dreg_hi, dst_hi));
+ 			}
+ 
+ 			if (sstk) {
+@@ -2052,8 +2059,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
+ 		case BPF_JMP | BPF_JSET | BPF_K:
+ 		case BPF_JMP32 | BPF_JSET | BPF_K: {
+ 			bool is_jmp64 = BPF_CLASS(insn->code) == BPF_JMP;
+-			u8 dreg_lo = dstk ? IA32_EAX : dst_lo;
+-			u8 dreg_hi = dstk ? IA32_EDX : dst_hi;
++			u8 dreg_lo = IA32_EAX;
++			u8 dreg_hi = IA32_EDX;
+ 			u8 sreg_lo = IA32_ECX;
+ 			u8 sreg_hi = IA32_EBX;
+ 			u32 hi;
+@@ -2066,6 +2073,13 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
+ 					      add_2reg(0x40, IA32_EBP,
+ 						       IA32_EDX),
+ 					      STACK_VAR(dst_hi));
++			} else {
++				/* mov dreg_lo,dst_lo */
++				EMIT2(0x89, add_2reg(0xC0, dreg_lo, dst_lo));
++				if (is_jmp64)
++					/* mov dreg_hi,dst_hi */
++					EMIT2(0x89,
++					      add_2reg(0xC0, dreg_hi, dst_hi));
+ 			}
+ 
+ 			/* mov ecx,imm32 */

commit 5fa9a98fb10380e48a398998cd36a85e4ef711d6
+Author: Luke Nelson 
+Date:   Wed Apr 22 10:36:29 2020 -0700
+
+    bpf, x86_32: Fix incorrect encoding in BPF_LDX zero-extension
+    
+    The current JIT uses the following sequence to zero-extend into the
+    upper 32 bits of the destination register for BPF_LDX BPF_{B,H,W},
+    when the destination register is not on the stack:
+    
+      EMIT3(0xC7, add_1reg(0xC0, dst_hi), 0);
+    
+    The problem is that C7 /0 encodes a MOV instruction that requires a 4-byte
+    immediate; the current code emits only 1 byte of the immediate. This
+    means that the first 3 bytes of the next instruction will be treated as
+    the rest of the immediate, breaking the stream of instructions.
+    
+    This patch fixes the problem by instead emitting "xor dst_hi,dst_hi"
+    to clear the upper 32 bits. This fixes the problem and is more efficient
+    than using MOV to load a zero immediate.
+    
+    This bug may not be currently triggerable as BPF_REG_AX is the only
+    register not stored on the stack and the verifier uses it in a limited
+    way, and the verifier implements a zero-extension optimization. But the
+    JIT should avoid emitting incorrect encodings regardless.
+    
+    Fixes: 03f5781be2c7b ("bpf, x86_32: add eBPF JIT compiler for ia32")
+    Signed-off-by: Xi Wang 
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Alexei Starovoitov 
+    Reviewed-by: H. Peter Anvin (Intel) 
+    Acked-by: Wang YanQing 
+    Link: https://lore.kernel.org/bpf/20200422173630.8351-1-luke.r.nels@gmail.com
+
+diff --git a/arch/x86/net/bpf_jit_comp32.c b/arch/x86/net/bpf_jit_comp32.c
+index 4d2a7a764602..cc9ad3892ea6 100644
+--- a/arch/x86/net/bpf_jit_comp32.c
++++ b/arch/x86/net/bpf_jit_comp32.c
+@@ -1854,7 +1854,9 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
+ 					      STACK_VAR(dst_hi));
+ 					EMIT(0x0, 4);
+ 				} else {
+-					EMIT3(0xC7, add_1reg(0xC0, dst_hi), 0);
++					/* xor dst_hi,dst_hi */
++					EMIT2(0x33,
++					      add_2reg(0xC0, dst_hi, dst_hi));
+ 				}
+ 				break;
+ 			case BPF_DW:

commit d2b6c3ab70dbc0069a69c57edd8c96f365f06b7c
+Author: Luke Nelson 
+Date:   Sat Apr 18 16:26:54 2020 -0700
+
+    bpf, selftests: Add test for BPF_STX BPF_B storing R10
+    
+    This patch adds a test to test_verifier that writes the lower 8 bits of
+    R10 (aka FP) using BPF_B to an array map and reads the result back. The
+    expected behavior is that the result should be the same as first copying
+    R10 to R9, and then storing / loading the lower 8 bits of R9.
+    
+    This test catches a bug that was present in the x86-64 JIT that caused
+    an incorrect encoding for BPF_STX BPF_B when the source operand is R10.
+    
+    Signed-off-by: Xi Wang 
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Alexei Starovoitov 
+    Link: https://lore.kernel.org/bpf/20200418232655.23870-2-luke.r.nels@gmail.com
+
+diff --git a/tools/testing/selftests/bpf/verifier/stack_ptr.c b/tools/testing/selftests/bpf/verifier/stack_ptr.c
+index 7276620ef242..8bfeb77c60bd 100644
+--- a/tools/testing/selftests/bpf/verifier/stack_ptr.c
++++ b/tools/testing/selftests/bpf/verifier/stack_ptr.c
+@@ -315,3 +315,43 @@
+ 	},
+ 	.result = ACCEPT,
+ },
++{
++	"store PTR_TO_STACK in R10 to array map using BPF_B",
++	.insns = {
++	/* Load pointer to map. */
++	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
++	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
++	BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
++	BPF_LD_MAP_FD(BPF_REG_1, 0),
++	BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
++	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2),
++	BPF_MOV64_IMM(BPF_REG_0, 2),
++	BPF_EXIT_INSN(),
++	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
++	/* Copy R10 to R9. */
++	BPF_MOV64_REG(BPF_REG_9, BPF_REG_10),
++	/* Pollute other registers with unaligned values. */
++	BPF_MOV64_IMM(BPF_REG_2, -1),
++	BPF_MOV64_IMM(BPF_REG_3, -1),
++	BPF_MOV64_IMM(BPF_REG_4, -1),
++	BPF_MOV64_IMM(BPF_REG_5, -1),
++	BPF_MOV64_IMM(BPF_REG_6, -1),
++	BPF_MOV64_IMM(BPF_REG_7, -1),
++	BPF_MOV64_IMM(BPF_REG_8, -1),
++	/* Store both R9 and R10 with BPF_B and read back. */
++	BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_10, 0),
++	BPF_LDX_MEM(BPF_B, BPF_REG_2, BPF_REG_1, 0),
++	BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_9, 0),
++	BPF_LDX_MEM(BPF_B, BPF_REG_3, BPF_REG_1, 0),
++	/* Should read back as same value. */
++	BPF_JMP_REG(BPF_JEQ, BPF_REG_2, BPF_REG_3, 2),
++	BPF_MOV64_IMM(BPF_REG_0, 1),
++	BPF_EXIT_INSN(),
++	BPF_MOV64_IMM(BPF_REG_0, 42),
++	BPF_EXIT_INSN(),
++	},
++	.fixup_map_array_48b = { 3 },
++	.result = ACCEPT,
++	.retval = 42,
++	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
++},

commit aee194b14dd2b2bde6252b3acf57d36dccfc743a
+Author: Luke Nelson 
+Date:   Sat Apr 18 16:26:53 2020 -0700
+
+    bpf, x86: Fix encoding for lower 8-bit registers in BPF_STX BPF_B
+    
+    This patch fixes an encoding bug in emit_stx for BPF_B when the source
+    register is BPF_REG_FP.
+    
+    The current implementation for BPF_STX BPF_B in emit_stx saves one REX
+    byte when the operands can be encoded using Mod-R/M alone. The lower 8
+    bits of registers %rax, %rbx, %rcx, and %rdx can be accessed without using
+    a REX prefix via %al, %bl, %cl, and %dl, respectively. Other registers,
+    (e.g., %rsi, %rdi, %rbp, %rsp) require a REX prefix to use their 8-bit
+    equivalents (%sil, %dil, %bpl, %spl).
+    
+    The current code checks if the source for BPF_STX BPF_B is BPF_REG_1
+    or BPF_REG_2 (which map to %rdi and %rsi), in which case it emits the
+    required REX prefix. However, it misses the case when the source is
+    BPF_REG_FP (mapped to %rbp).
+    
+    The result is that BPF_STX BPF_B with BPF_REG_FP as the source operand
+    will read from register %ch instead of the correct %bpl. This patch fixes
+    the problem by fixing and refactoring the check on which registers need
+    the extra REX byte. Since no BPF registers map to %rsp, there is no need
+    to handle %spl.
+    
+    Fixes: 622582786c9e0 ("net: filter: x86: internal BPF JIT")
+    Signed-off-by: Xi Wang 
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Alexei Starovoitov 
+    Link: https://lore.kernel.org/bpf/20200418232655.23870-1-luke.r.nels@gmail.com
+
+diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
+index 5ea7c2cf7ab4..42b6709e6dc7 100644
+--- a/arch/x86/net/bpf_jit_comp.c
++++ b/arch/x86/net/bpf_jit_comp.c
+@@ -158,6 +158,19 @@ static bool is_ereg(u32 reg)
+ 			     BIT(BPF_REG_AX));
+ }
+ 
++/*
++ * is_ereg_8l() == true if BPF register 'reg' is mapped to access x86-64
++ * lower 8-bit registers dil,sil,bpl,spl,r8b..r15b, which need extra byte
++ * of encoding. al,cl,dl,bl have simpler encoding.
++ */
++static bool is_ereg_8l(u32 reg)
++{
++	return is_ereg(reg) ||
++	    (1 << reg) & (BIT(BPF_REG_1) |
++			  BIT(BPF_REG_2) |
++			  BIT(BPF_REG_FP));
++}
++
+ static bool is_axreg(u32 reg)
+ {
+ 	return reg == BPF_REG_0;
+@@ -598,9 +611,8 @@ static void emit_stx(u8 **pprog, u32 size, u32 dst_reg, u32 src_reg, int off)
+ 	switch (size) {
+ 	case BPF_B:
+ 		/* Emit 'mov byte ptr [rax + off], al' */
+-		if (is_ereg(dst_reg) || is_ereg(src_reg) ||
+-		    /* We have to add extra byte for x86 SIL, DIL regs */
+-		    src_reg == BPF_REG_1 || src_reg == BPF_REG_2)
++		if (is_ereg(dst_reg) || is_ereg_8l(src_reg))
++			/* Add extra byte for eregs or SIL,DIL,BPL in src_reg */
+ 			EMIT2(add_2mod(0x40, dst_reg, src_reg), 0x88);
+ 		else
+ 			EMIT1(0x88);

commit 4178417cc5359c329790a4a8f4a6604612338cca
+Author: Luke Nelson 
+Date:   Thu Apr 9 15:17:52 2020 -0700
+
+    arm, bpf: Fix offset overflow for BPF_MEM BPF_DW
+    
+    This patch fixes an incorrect check in how immediate memory offsets are
+    computed for BPF_DW on arm.
+    
+    For BPF_LDX/ST/STX + BPF_DW, the 32-bit arm JIT breaks down an 8-byte
+    access into two separate 4-byte accesses using off+0 and off+4. If off
+    fits in imm12, the JIT emits a ldr/str instruction with the immediate
+    and avoids the use of a temporary register. While the current check off
+    <= 0xfff ensures that the first immediate off+0 doesn't overflow imm12,
+    it's not sufficient for the second immediate off+4, which may cause the
+    second access of BPF_DW to read/write the wrong address.
+    
+    This patch fixes the problem by changing the check to
+    off <= 0xfff - 4 for BPF_DW, ensuring off+4 will never overflow.
+    
+    A side effect of simplifying the check is that it now allows using
+    negative immediate offsets in ldr/str. This means that small negative
+    offsets can also avoid the use of a temporary register.
+    
+    This patch introduces no new failures in test_verifier or test_bpf.c.
+    
+    Fixes: c5eae692571d6 ("ARM: net: bpf: improve 64-bit store implementation")
+    Fixes: ec19e02b343db ("ARM: net: bpf: fix LDX instructions")
+    Co-developed-by: Xi Wang 
+    Signed-off-by: Xi Wang 
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Daniel Borkmann 
+    Link: https://lore.kernel.org/bpf/20200409221752.28448-1-luke.r.nels@gmail.com
+
+diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
+index d124f78e20ac..bf85d6db4931 100644
+--- a/arch/arm/net/bpf_jit_32.c
++++ b/arch/arm/net/bpf_jit_32.c
+@@ -1000,21 +1000,35 @@ static inline void emit_a32_mul_r64(const s8 dst[], const s8 src[],
+ 	arm_bpf_put_reg32(dst_hi, rd[0], ctx);
+ }
+ 
++static bool is_ldst_imm(s16 off, const u8 size)
++{
++	s16 off_max = 0;
++
++	switch (size) {
++	case BPF_B:
++	case BPF_W:
++		off_max = 0xfff;
++		break;
++	case BPF_H:
++		off_max = 0xff;
++		break;
++	case BPF_DW:
++		/* Need to make sure off+4 does not overflow. */
++		off_max = 0xfff - 4;
++		break;
++	}
++	return -off_max <= off && off <= off_max;
++}
++
+ /* *(size *)(dst + off) = src */
+ static inline void emit_str_r(const s8 dst, const s8 src[],
+-			      s32 off, struct jit_ctx *ctx, const u8 sz){
++			      s16 off, struct jit_ctx *ctx, const u8 sz){
+ 	const s8 *tmp = bpf2a32[TMP_REG_1];
+-	s32 off_max;
+ 	s8 rd;
+ 
+ 	rd = arm_bpf_get_reg32(dst, tmp[1], ctx);
+ 
+-	if (sz == BPF_H)
+-		off_max = 0xff;
+-	else
+-		off_max = 0xfff;
+-
+-	if (off < 0 || off > off_max) {
++	if (!is_ldst_imm(off, sz)) {
+ 		emit_a32_mov_i(tmp[0], off, ctx);
+ 		emit(ARM_ADD_R(tmp[0], tmp[0], rd), ctx);
+ 		rd = tmp[0];
+@@ -1043,18 +1057,12 @@ static inline void emit_str_r(const s8 dst, const s8 src[],
+ 
+ /* dst = *(size*)(src + off) */
+ static inline void emit_ldx_r(const s8 dst[], const s8 src,
+-			      s32 off, struct jit_ctx *ctx, const u8 sz){
++			      s16 off, struct jit_ctx *ctx, const u8 sz){
+ 	const s8 *tmp = bpf2a32[TMP_REG_1];
+ 	const s8 *rd = is_stacked(dst_lo) ? tmp : dst;
+ 	s8 rm = src;
+-	s32 off_max;
+-
+-	if (sz == BPF_H)
+-		off_max = 0xff;
+-	else
+-		off_max = 0xfff;
+ 
+-	if (off < 0 || off > off_max) {
++	if (!is_ldst_imm(off, sz)) {
+ 		emit_a32_mov_i(tmp[0], off, ctx);
+ 		emit(ARM_ADD_R(tmp[0], tmp[0], src), ctx);
+ 		rm = tmp[0];

commit bb9562cf5c67813034c96afb50bd21130a504441
+Author: Luke Nelson 
+Date:   Wed Apr 8 18:12:29 2020 +0000
+
+    arm, bpf: Fix bugs with ALU64 {RSH, ARSH} BPF_K shift by 0
+    
+    The current arm BPF JIT does not correctly compile RSH or ARSH when the
+    immediate shift amount is 0. This causes the "rsh64 by 0 imm" and "arsh64
+    by 0 imm" BPF selftests to hang the kernel by reaching an instruction
+    the verifier determines to be unreachable.
+    
+    The root cause is in how immediate right shifts are encoded on arm.
+    For LSR and ASR (logical and arithmetic right shift), a bit-pattern
+    of 00000 in the immediate encodes a shift amount of 32. When the BPF
+    immediate is 0, the generated code shifts by 32 instead of the expected
+    behavior (a no-op).
+    
+    This patch fixes the bugs by adding an additional check if the BPF
+    immediate is 0. After the change, the above mentioned BPF selftests pass.
+    
+    Fixes: 39c13c204bb11 ("arm: eBPF JIT compiler")
+    Co-developed-by: Xi Wang 
+    Signed-off-by: Xi Wang 
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Daniel Borkmann 
+    Link: https://lore.kernel.org/bpf/20200408181229.10909-1-luke.r.nels@gmail.com
+
+diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
+index cc29869d12a3..d124f78e20ac 100644
+--- a/arch/arm/net/bpf_jit_32.c
++++ b/arch/arm/net/bpf_jit_32.c
+@@ -929,7 +929,11 @@ static inline void emit_a32_rsh_i64(const s8 dst[],
+ 	rd = arm_bpf_get_reg64(dst, tmp, ctx);
+ 
+ 	/* Do LSR operation */
+-	if (val < 32) {
++	if (val == 0) {
++		/* An immediate value of 0 encodes a shift amount of 32
++		 * for LSR. To shift by 0, don't do anything.
++		 */
++	} else if (val < 32) {
+ 		emit(ARM_MOV_SI(tmp2[1], rd[1], SRTYPE_LSR, val), ctx);
+ 		emit(ARM_ORR_SI(rd[1], tmp2[1], rd[0], SRTYPE_ASL, 32 - val), ctx);
+ 		emit(ARM_MOV_SI(rd[0], rd[0], SRTYPE_LSR, val), ctx);
+@@ -955,7 +959,11 @@ static inline void emit_a32_arsh_i64(const s8 dst[],
+ 	rd = arm_bpf_get_reg64(dst, tmp, ctx);
+ 
+ 	/* Do ARSH operation */
+-	if (val < 32) {
++	if (val == 0) {
++		/* An immediate value of 0 encodes a shift amount of 32
++		 * for ASR. To shift by 0, don't do anything.
++		 */
++	} else if (val < 32) {
+ 		emit(ARM_MOV_SI(tmp2[1], rd[1], SRTYPE_LSR, val), ctx);
+ 		emit(ARM_ORR_SI(rd[1], tmp2[1], rd[0], SRTYPE_ASL, 32 - val), ctx);
+ 		emit(ARM_MOV_SI(rd[0], rd[0], SRTYPE_ASR, val), ctx);

commit 489553dd13a88d8a882db10622ba8b9b58582ce4
+Author: Luke Nelson 
+Date:   Mon Apr 6 22:16:04 2020 +0000
+
+    riscv, bpf: Fix offset range checking for auipc+jalr on RV64
+    
+    The existing code in emit_call on RV64 checks that the PC-relative offset
+    to the function fits in 32 bits before calling emit_jump_and_link to emit
+    an auipc+jalr pair. However, this check is incorrect because offsets in
+    the range [2^31 - 2^11, 2^31 - 1] cannot be encoded using auipc+jalr on
+    RV64 (see discussion [1]). The RISC-V spec has recently been updated
+    to reflect this fact [2, 3].
+    
+    This patch fixes the problem by moving the check on the offset into
+    emit_jump_and_link and modifying it to the correct range of encodable
+    offsets, which is [-2^31 - 2^11, 2^31 - 2^11). This also enforces the
+    check on the offset to other uses of emit_jump_and_link (e.g., BPF_JA)
+    as well.
+    
+    Currently, this bug is unlikely to be triggered, because the memory
+    region from which JITed images are allocated is close enough to kernel
+    text for the offsets to not become too large; and because the bounds on
+    BPF program size are small enough. This patch prevents this problem from
+    becoming an issue if either of these change.
+    
+    [1]: https://groups.google.com/a/groups.riscv.org/forum/#!topic/isa-dev/bwWFhBnnZFQ
+    [2]: https://github.com/riscv/riscv-isa-manual/commit/b1e42e09ac55116dbf9de5e4fb326a5a90e4a993
+    [3]: https://github.com/riscv/riscv-isa-manual/commit/4c1b2066ebd2965a422e41eb262d0a208a7fea07
+    
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Daniel Borkmann 
+    Link: https://lore.kernel.org/bpf/20200406221604.18547-1-luke.r.nels@gmail.com
+
+diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
+index cc1985d8750a..d208a9fd6c52 100644
+--- a/arch/riscv/net/bpf_jit_comp64.c
++++ b/arch/riscv/net/bpf_jit_comp64.c
+@@ -110,6 +110,16 @@ static bool is_32b_int(s64 val)
+ 	return -(1L << 31) <= val && val < (1L << 31);
+ }
+ 
++static bool in_auipc_jalr_range(s64 val)
++{
++	/*
++	 * auipc+jalr can reach any signed PC-relative offset in the range
++	 * [-2^31 - 2^11, 2^31 - 2^11).
++	 */
++	return (-(1L << 31) - (1L << 11)) <= val &&
++		val < ((1L << 31) - (1L << 11));
++}
++
+ static void emit_imm(u8 rd, s64 val, struct rv_jit_context *ctx)
+ {
+ 	/* Note that the immediate from the add is sign-extended,
+@@ -380,20 +390,24 @@ static void emit_sext_32_rd(u8 *rd, struct rv_jit_context *ctx)
+ 	*rd = RV_REG_T2;
+ }
+ 
+-static void emit_jump_and_link(u8 rd, s64 rvoff, bool force_jalr,
+-			       struct rv_jit_context *ctx)
++static int emit_jump_and_link(u8 rd, s64 rvoff, bool force_jalr,
++			      struct rv_jit_context *ctx)
+ {
+ 	s64 upper, lower;
+ 
+ 	if (rvoff && is_21b_int(rvoff) && !force_jalr) {
+ 		emit(rv_jal(rd, rvoff >> 1), ctx);
+-		return;
++		return 0;
++	} else if (in_auipc_jalr_range(rvoff)) {
++		upper = (rvoff + (1 << 11)) >> 12;
++		lower = rvoff & 0xfff;
++		emit(rv_auipc(RV_REG_T1, upper), ctx);
++		emit(rv_jalr(rd, RV_REG_T1, lower), ctx);
++		return 0;
+ 	}
+ 
+-	upper = (rvoff + (1 << 11)) >> 12;
+-	lower = rvoff & 0xfff;
+-	emit(rv_auipc(RV_REG_T1, upper), ctx);
+-	emit(rv_jalr(rd, RV_REG_T1, lower), ctx);
++	pr_err("bpf-jit: target offset 0x%llx is out of range\n", rvoff);
++	return -ERANGE;
+ }
+ 
+ static bool is_signed_bpf_cond(u8 cond)
+@@ -407,18 +421,16 @@ static int emit_call(bool fixed, u64 addr, struct rv_jit_context *ctx)
+ 	s64 off = 0;
+ 	u64 ip;
+ 	u8 rd;
++	int ret;
+ 
+ 	if (addr && ctx->insns) {
+ 		ip = (u64)(long)(ctx->insns + ctx->ninsns);
+ 		off = addr - ip;
+-		if (!is_32b_int(off)) {
+-			pr_err("bpf-jit: target call addr %pK is out of range\n",
+-			       (void *)addr);
+-			return -ERANGE;
+-		}
+ 	}
+ 
+-	emit_jump_and_link(RV_REG_RA, off, !fixed, ctx);
++	ret = emit_jump_and_link(RV_REG_RA, off, !fixed, ctx);
++	if (ret)
++		return ret;
+ 	rd = bpf_to_rv_reg(BPF_REG_0, ctx);
+ 	emit(rv_addi(rd, RV_REG_A0, 0), ctx);
+ 	return 0;
+@@ -429,7 +441,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ {
+ 	bool is64 = BPF_CLASS(insn->code) == BPF_ALU64 ||
+ 		    BPF_CLASS(insn->code) == BPF_JMP;
+-	int s, e, rvoff, i = insn - ctx->prog->insnsi;
++	int s, e, rvoff, ret, i = insn - ctx->prog->insnsi;
+ 	struct bpf_prog_aux *aux = ctx->prog->aux;
+ 	u8 rd = -1, rs = -1, code = insn->code;
+ 	s16 off = insn->off;
+@@ -699,7 +711,9 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 	/* JUMP off */
+ 	case BPF_JMP | BPF_JA:
+ 		rvoff = rv_offset(i, off, ctx);
+-		emit_jump_and_link(RV_REG_ZERO, rvoff, false, ctx);
++		ret = emit_jump_and_link(RV_REG_ZERO, rvoff, false, ctx);
++		if (ret)
++			return ret;
+ 		break;
+ 
+ 	/* IF (dst COND src) JUMP off */
+@@ -801,7 +815,6 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 	case BPF_JMP | BPF_CALL:
+ 	{
+ 		bool fixed;
+-		int ret;
+ 		u64 addr;
+ 
+ 		mark_call(ctx);
+@@ -826,7 +839,9 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 			break;
+ 
+ 		rvoff = epilogue_offset(ctx);
+-		emit_jump_and_link(RV_REG_ZERO, rvoff, false, ctx);
++		ret = emit_jump_and_link(RV_REG_ZERO, rvoff, false, ctx);
++		if (ret)
++			return ret;
+ 		break;
+ 
+ 	/* dst = imm64 */

commit 93e5fbb18cec70b3b5c614f67b65388829113bdd
+Author: Luke Nelson 
+Date:   Thu Mar 5 15:44:13 2020 -0800
+
+    selftests: bpf: Add test for JMP32 JSET BPF_X with upper bits set
+    
+    The existing tests attempt to check that JMP32 JSET ignores the upper
+    bits in the operand registers. However, the tests missed one such bug in
+    the x32 JIT that is only uncovered when a previous instruction pollutes
+    the upper 32 bits of the registers.
+    
+    This patch adds a new test case that catches the bug by first executing
+    a 64-bit JSET to pollute the upper 32-bits of the temporary registers,
+    followed by a 32-bit JSET which should ignore the upper 32 bits.
+    
+    Co-developed-by: Xi Wang 
+    Signed-off-by: Xi Wang 
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Daniel Borkmann 
+    Link: https://lore.kernel.org/bpf/20200305234416.31597-2-luke.r.nels@gmail.com
+
+diff --git a/tools/testing/selftests/bpf/verifier/jmp32.c b/tools/testing/selftests/bpf/verifier/jmp32.c
+index bf0322eb5346..bd5cae4a7f73 100644
+--- a/tools/testing/selftests/bpf/verifier/jmp32.c
++++ b/tools/testing/selftests/bpf/verifier/jmp32.c
+@@ -61,6 +61,21 @@
+ 	},
+ 	.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
+ },
++{
++	"jset32: ignores upper bits",
++	.insns = {
++	BPF_MOV64_IMM(BPF_REG_0, 0),
++	BPF_LD_IMM64(BPF_REG_7, 0x8000000000000000),
++	BPF_LD_IMM64(BPF_REG_8, 0x8000000000000000),
++	BPF_JMP_REG(BPF_JSET, BPF_REG_7, BPF_REG_8, 1),
++	BPF_EXIT_INSN(),
++	BPF_JMP32_REG(BPF_JSET, BPF_REG_7, BPF_REG_8, 1),
++	BPF_MOV64_IMM(BPF_REG_0, 2),
++	BPF_EXIT_INSN(),
++	},
++	.result = ACCEPT,
++	.retval = 2,
++},
+ {
+ 	"jset32: min/max deduction",
+ 	.insns = {

commit 80f1f85036355e5581ec0b99913410345ad3491b
+Author: Luke Nelson 
+Date:   Thu Mar 5 15:44:12 2020 -0800
+
+    bpf, x32: Fix bug with JMP32 JSET BPF_X checking upper bits
+    
+    The current x32 BPF JIT is incorrect for JMP32 JSET BPF_X when the upper
+    32 bits of operand registers are non-zero in certain situations.
+    
+    The problem is in the following code:
+    
+      case BPF_JMP | BPF_JSET | BPF_X:
+      case BPF_JMP32 | BPF_JSET | BPF_X:
+      ...
+    
+      /* and dreg_lo,sreg_lo */
+      EMIT2(0x23, add_2reg(0xC0, sreg_lo, dreg_lo));
+      /* and dreg_hi,sreg_hi */
+      EMIT2(0x23, add_2reg(0xC0, sreg_hi, dreg_hi));
+      /* or dreg_lo,dreg_hi */
+      EMIT2(0x09, add_2reg(0xC0, dreg_lo, dreg_hi));
+    
+    This code checks the upper bits of the operand registers regardless if
+    the BPF instruction is BPF_JMP32 or BPF_JMP64. Registers dreg_hi and
+    dreg_lo are not loaded from the stack for BPF_JMP32, however, they can
+    still be polluted with values from previous instructions.
+    
+    The following BPF program demonstrates the bug. The jset64 instruction
+    loads the temporary registers and performs the jump, since ((u64)r7 &
+    (u64)r8) is non-zero. The jset32 should _not_ be taken, as the lower
+    32 bits are all zero, however, the current JIT will take the branch due
+    the pollution of temporary registers from the earlier jset64.
+    
+      mov64    r0, 0
+      ld64     r7, 0x8000000000000000
+      ld64     r8, 0x8000000000000000
+      jset64   r7, r8, 1
+      exit
+      jset32   r7, r8, 1
+      mov64    r0, 2
+      exit
+    
+    The expected return value of this program is 2; under the buggy x32 JIT
+    it returns 0. The fix is to skip using the upper 32 bits for jset32 and
+    compare the upper 32 bits for jset64 only.
+    
+    All tests in test_bpf.ko and selftests/bpf/test_verifier continue to
+    pass with this change.
+    
+    We found this bug using our automated verification tool, Serval.
+    
+    Fixes: 69f827eb6e14 ("x32: bpf: implement jitting of JMP32")
+    Co-developed-by: Xi Wang 
+    Signed-off-by: Xi Wang 
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Daniel Borkmann 
+    Link: https://lore.kernel.org/bpf/20200305234416.31597-1-luke.r.nels@gmail.com
+
+diff --git a/arch/x86/net/bpf_jit_comp32.c b/arch/x86/net/bpf_jit_comp32.c
+index 393d251798c0..4d2a7a764602 100644
+--- a/arch/x86/net/bpf_jit_comp32.c
++++ b/arch/x86/net/bpf_jit_comp32.c
+@@ -2039,10 +2039,12 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
+ 			}
+ 			/* and dreg_lo,sreg_lo */
+ 			EMIT2(0x23, add_2reg(0xC0, sreg_lo, dreg_lo));
+-			/* and dreg_hi,sreg_hi */
+-			EMIT2(0x23, add_2reg(0xC0, sreg_hi, dreg_hi));
+-			/* or dreg_lo,dreg_hi */
+-			EMIT2(0x09, add_2reg(0xC0, dreg_lo, dreg_hi));
++			if (is_jmp64) {
++				/* and dreg_hi,sreg_hi */
++				EMIT2(0x23, add_2reg(0xC0, sreg_hi, dreg_hi));
++				/* or dreg_lo,dreg_hi */
++				EMIT2(0x09, add_2reg(0xC0, dreg_lo, dreg_hi));
++			}
+ 			goto emit_cond_jmp;
+ 		}
+ 		case BPF_JMP | BPF_JSET | BPF_K:

commit dad737c926b5b286b9c91abbda66811a8a6618e9
+Author: Luke Nelson 
+Date:   Wed Mar 4 21:02:07 2020 -0800
+
+    MAINTAINERS: Add entry for RV32G BPF JIT
+    
+    Add a new entry for the 32-bit RISC-V JIT to MAINTAINERS and change
+    mailing list to netdev and bpf following the guidelines from
+    commit e42da4c62abb ("docs/bpf: Update bpf development Q/A file").
+    
+    Signed-off-by: Xi Wang 
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Daniel Borkmann 
+    Reviewed-by: Björn Töpel 
+    Acked-by: Björn Töpel 
+    Link: https://lore.kernel.org/bpf/20200305050207.4159-5-luke.r.nels@gmail.com
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 8f27f40d22bb..c23884e084be 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -3213,11 +3213,22 @@ L:	bpf@vger.kernel.org
+ S:	Maintained
+ F:	arch/powerpc/net/
+ 
+-BPF JIT for RISC-V (RV64G)
++BPF JIT for RISC-V (32-bit)
++M:	Luke Nelson 
++M:	Xi Wang 
++L:	netdev@vger.kernel.org
++L:	bpf@vger.kernel.org
++S:	Maintained
++F:	arch/riscv/net/
++X:	arch/riscv/net/bpf_jit_comp64.c
++
++BPF JIT for RISC-V (64-bit)
+ M:	Björn Töpel 
+ L:	netdev@vger.kernel.org
++L:	bpf@vger.kernel.org
+ S:	Maintained
+ F:	arch/riscv/net/
++X:	arch/riscv/net/bpf_jit_comp32.c
+ 
+ BPF JIT for S390
+ M:	Ilya Leoshkevich 

commit 06b741521622331eb01b67123e8cdda6ca8be187
+Author: Luke Nelson 
+Date:   Wed Mar 4 21:02:06 2020 -0800
+
+    bpf, doc: Add BPF JIT for RV32G to BPF documentation
+    
+    Update filter.txt and admin-guide to mention the BPF JIT for RV32G.
+    
+    Co-developed-by: Xi Wang 
+    Signed-off-by: Xi Wang 
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Daniel Borkmann 
+    Reviewed-by: Björn Töpel 
+    Acked-by: Björn Töpel 
+    Link: https://lore.kernel.org/bpf/20200305050207.4159-4-luke.r.nels@gmail.com
+
+diff --git a/Documentation/admin-guide/sysctl/net.rst b/Documentation/admin-guide/sysctl/net.rst
+index 287b98708a40..e043c9213388 100644
+--- a/Documentation/admin-guide/sysctl/net.rst
++++ b/Documentation/admin-guide/sysctl/net.rst
+@@ -67,7 +67,8 @@ two flavors of JITs, the newer eBPF JIT currently supported on:
+   - sparc64
+   - mips64
+   - s390x
+-  - riscv
++  - riscv64
++  - riscv32
+ 
+ And the older cBPF JIT supported on the following archs:
+ 
+diff --git a/Documentation/networking/filter.txt b/Documentation/networking/filter.txt
+index c4a328f2d57a..2f0f8b17dade 100644
+--- a/Documentation/networking/filter.txt
++++ b/Documentation/networking/filter.txt
+@@ -606,7 +606,7 @@ before a conversion to the new layout is being done behind the scenes!
+ 
+ Currently, the classic BPF format is being used for JITing on most
+ 32-bit architectures, whereas x86-64, aarch64, s390x, powerpc64,
+-sparc64, arm32, riscv (RV64G) perform JIT compilation from eBPF
++sparc64, arm32, riscv64, riscv32 perform JIT compilation from eBPF
+ instruction set.
+ 
+ Some core changes of the new internal format:

commit 5f316b65e99f109942c556dc8790abd4c75bcb34
+Author: Luke Nelson 
+Date:   Wed Mar 4 21:02:05 2020 -0800
+
+    riscv, bpf: Add RV32G eBPF JIT
+    
+    This is an eBPF JIT for RV32G, adapted from the JIT for RV64G and
+    the 32-bit ARM JIT.
+    
+    There are two main changes required for this to work compared to
+    the RV64 JIT.
+    
+    First, eBPF registers are 64-bit, while RV32G registers are 32-bit.
+    BPF registers either map directly to 2 RISC-V registers, or reside
+    in stack scratch space and are saved and restored when used.
+    
+    Second, many 64-bit ALU operations do not trivially map to 32-bit
+    operations. Operations that move bits between high and low words,
+    such as ADD, LSH, MUL, and others must emulate the 64-bit behavior
+    in terms of 32-bit instructions.
+    
+    This patch also makes related changes to bpf_jit.h, such
+    as adding RISC-V instructions required by the RV32 JIT.
+    
+    Supported features:
+    
+    The RV32 JIT supports the same features and instructions as the
+    RV64 JIT, with the following exceptions:
+    
+    - ALU64 DIV/MOD: Requires loops to implement on 32-bit hardware.
+    
+    - BPF_XADD | BPF_DW: There's no 8-byte atomic instruction in RV32.
+    
+    These features are also unsupported on other BPF JITs for 32-bit
+    architectures.
+    
+    Testing:
+    
+    - lib/test_bpf.c
+    test_bpf: Summary: 378 PASSED, 0 FAILED, [349/366 JIT'ed]
+    test_bpf: test_skb_segment: Summary: 2 PASSED, 0 FAILED
+    
+    The tests that are not JITed are all due to use of 64-bit div/mod
+    or 64-bit xadd.
+    
+    - tools/testing/selftests/bpf/test_verifier.c
+    Summary: 1415 PASSED, 122 SKIPPED, 43 FAILED
+    
+    Tested both with and without BPF JIT hardening.
+    
+    This is the same set of tests that pass using the BPF interpreter
+    with the JIT disabled.
+    
+    Verification and synthesis:
+    
+    We developed the RV32 JIT using our automated verification tool,
+    Serval. We have used Serval in the past to verify patches to the
+    RV64 JIT. We also used Serval to superoptimize the resulting code
+    through program synthesis.
+    
+    You can find the tool and a guide to the approach and results here:
+    https://github.com/uw-unsat/serval-bpf/tree/rv32-jit-v5
+    
+    Co-developed-by: Xi Wang 
+    Signed-off-by: Xi Wang 
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Daniel Borkmann 
+    Reviewed-by: Björn Töpel 
+    Acked-by: Björn Töpel 
+    Link: https://lore.kernel.org/bpf/20200305050207.4159-3-luke.r.nels@gmail.com
+
+diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
+index 73f029eae0cc..e9791717e006 100644
+--- a/arch/riscv/Kconfig
++++ b/arch/riscv/Kconfig
+@@ -56,7 +56,7 @@ config RISCV
+ 	select ARCH_HAS_PTE_SPECIAL
+ 	select ARCH_HAS_MMIOWB
+ 	select ARCH_HAS_DEBUG_VIRTUAL
+-	select HAVE_EBPF_JIT if 64BIT
++	select HAVE_EBPF_JIT
+ 	select EDAC_SUPPORT
+ 	select ARCH_HAS_GIGANTIC_PAGE
+ 	select ARCH_WANT_HUGE_PMD_SHARE if 64BIT
+diff --git a/arch/riscv/net/Makefile b/arch/riscv/net/Makefile
+index 018074dbf986..9a1e5f0a94e5 100644
+--- a/arch/riscv/net/Makefile
++++ b/arch/riscv/net/Makefile
+@@ -1,3 +1,9 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+ 
+-obj-$(CONFIG_BPF_JIT) += bpf_jit_core.o bpf_jit_comp64.o
++obj-$(CONFIG_BPF_JIT) += bpf_jit_core.o
++
++ifeq ($(CONFIG_ARCH_RV64I),y)
++	obj-$(CONFIG_BPF_JIT) += bpf_jit_comp64.o
++else
++	obj-$(CONFIG_BPF_JIT) += bpf_jit_comp32.o
++endif
+diff --git a/arch/riscv/net/bpf_jit.h b/arch/riscv/net/bpf_jit.h
+index 23c123331f94..20e235d06f66 100644
+--- a/arch/riscv/net/bpf_jit.h
++++ b/arch/riscv/net/bpf_jit.h
+@@ -207,6 +207,8 @@ static inline u32 rv_amo_insn(u8 funct5, u8 aq, u8 rl, u8 rs2, u8 rs1,
+ 	return rv_r_insn(funct7, rs2, rs1, funct3, rd, opcode);
+ }
+ 
++/* Instructions shared by both RV32 and RV64. */
++
+ static inline u32 rv_addi(u8 rd, u8 rs1, u16 imm11_0)
+ {
+ 	return rv_i_insn(imm11_0, rs1, 0, rd, 0x13);
+@@ -262,6 +264,11 @@ static inline u32 rv_sub(u8 rd, u8 rs1, u8 rs2)
+ 	return rv_r_insn(0x20, rs2, rs1, 0, rd, 0x33);
+ }
+ 
++static inline u32 rv_sltu(u8 rd, u8 rs1, u8 rs2)
++{
++	return rv_r_insn(0, rs2, rs1, 3, rd, 0x33);
++}
++
+ static inline u32 rv_and(u8 rd, u8 rs1, u8 rs2)
+ {
+ 	return rv_r_insn(0, rs2, rs1, 7, rd, 0x33);
+@@ -297,6 +304,11 @@ static inline u32 rv_mul(u8 rd, u8 rs1, u8 rs2)
+ 	return rv_r_insn(1, rs2, rs1, 0, rd, 0x33);
+ }
+ 
++static inline u32 rv_mulhu(u8 rd, u8 rs1, u8 rs2)
++{
++	return rv_r_insn(1, rs2, rs1, 3, rd, 0x33);
++}
++
+ static inline u32 rv_divu(u8 rd, u8 rs1, u8 rs2)
+ {
+ 	return rv_r_insn(1, rs2, rs1, 5, rd, 0x33);
+@@ -332,21 +344,46 @@ static inline u32 rv_bltu(u8 rs1, u8 rs2, u16 imm12_1)
+ 	return rv_b_insn(imm12_1, rs2, rs1, 6, 0x63);
+ }
+ 
++static inline u32 rv_bgtu(u8 rs1, u8 rs2, u16 imm12_1)
++{
++	return rv_bltu(rs2, rs1, imm12_1);
++}
++
+ static inline u32 rv_bgeu(u8 rs1, u8 rs2, u16 imm12_1)
+ {
+ 	return rv_b_insn(imm12_1, rs2, rs1, 7, 0x63);
+ }
+ 
++static inline u32 rv_bleu(u8 rs1, u8 rs2, u16 imm12_1)
++{
++	return rv_bgeu(rs2, rs1, imm12_1);
++}
++
+ static inline u32 rv_blt(u8 rs1, u8 rs2, u16 imm12_1)
+ {
+ 	return rv_b_insn(imm12_1, rs2, rs1, 4, 0x63);
+ }
+ 
++static inline u32 rv_bgt(u8 rs1, u8 rs2, u16 imm12_1)
++{
++	return rv_blt(rs2, rs1, imm12_1);
++}
++
+ static inline u32 rv_bge(u8 rs1, u8 rs2, u16 imm12_1)
+ {
+ 	return rv_b_insn(imm12_1, rs2, rs1, 5, 0x63);
+ }
+ 
++static inline u32 rv_ble(u8 rs1, u8 rs2, u16 imm12_1)
++{
++	return rv_bge(rs2, rs1, imm12_1);
++}
++
++static inline u32 rv_lw(u8 rd, u16 imm11_0, u8 rs1)
++{
++	return rv_i_insn(imm11_0, rs1, 2, rd, 0x03);
++}
++
+ static inline u32 rv_lbu(u8 rd, u16 imm11_0, u8 rs1)
+ {
+ 	return rv_i_insn(imm11_0, rs1, 4, rd, 0x03);
+@@ -377,6 +414,15 @@ static inline u32 rv_amoadd_w(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
+ 	return rv_amo_insn(0, aq, rl, rs2, rs1, 2, rd, 0x2f);
+ }
+ 
++/*
++ * RV64-only instructions.
++ *
++ * These instructions are not available on RV32.  Wrap them below a #if to
++ * ensure that the RV32 JIT doesn't emit any of these instructions.
++ */
++
++#if __riscv_xlen == 64
++
+ static inline u32 rv_addiw(u8 rd, u8 rs1, u16 imm11_0)
+ {
+ 	return rv_i_insn(imm11_0, rs1, 0, rd, 0x1b);
+@@ -457,6 +503,8 @@ static inline u32 rv_amoadd_d(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
+ 	return rv_amo_insn(0, aq, rl, rs2, rs1, 3, rd, 0x2f);
+ }
+ 
++#endif /* __riscv_xlen == 64 */
++
+ void bpf_jit_build_prologue(struct rv_jit_context *ctx);
+ void bpf_jit_build_epilogue(struct rv_jit_context *ctx);
+ 
+diff --git a/arch/riscv/net/bpf_jit_comp32.c b/arch/riscv/net/bpf_jit_comp32.c
+new file mode 100644
+index 000000000000..302934177760
+--- /dev/null
++++ b/arch/riscv/net/bpf_jit_comp32.c
+@@ -0,0 +1,1310 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * BPF JIT compiler for RV32G
++ *
++ * Copyright (c) 2020 Luke Nelson 
++ * Copyright (c) 2020 Xi Wang 
++ *
++ * The code is based on the BPF JIT compiler for RV64G by Björn Töpel and
++ * the BPF JIT compiler for 32-bit ARM by Shubham Bansal and Mircea Gherzan.
++ */
++
++#include 
++#include 
++#include "bpf_jit.h"
++
++enum {
++	/* Stack layout - these are offsets from (top of stack - 4). */
++	BPF_R6_HI,
++	BPF_R6_LO,
++	BPF_R7_HI,
++	BPF_R7_LO,
++	BPF_R8_HI,
++	BPF_R8_LO,
++	BPF_R9_HI,
++	BPF_R9_LO,
++	BPF_AX_HI,
++	BPF_AX_LO,
++	/* Stack space for BPF_REG_6 through BPF_REG_9 and BPF_REG_AX. */
++	BPF_JIT_SCRATCH_REGS,
++};
++
++#define STACK_OFFSET(k) (-4 - ((k) * 4))
++
++#define TMP_REG_1	(MAX_BPF_JIT_REG + 0)
++#define TMP_REG_2	(MAX_BPF_JIT_REG + 1)
++
++#define RV_REG_TCC		RV_REG_T6
++#define RV_REG_TCC_SAVED	RV_REG_S7
++
++static const s8 bpf2rv32[][2] = {
++	/* Return value from in-kernel function, and exit value from eBPF. */
++	[BPF_REG_0] = {RV_REG_S2, RV_REG_S1},
++	/* Arguments from eBPF program to in-kernel function. */
++	[BPF_REG_1] = {RV_REG_A1, RV_REG_A0},
++	[BPF_REG_2] = {RV_REG_A3, RV_REG_A2},
++	[BPF_REG_3] = {RV_REG_A5, RV_REG_A4},
++	[BPF_REG_4] = {RV_REG_A7, RV_REG_A6},
++	[BPF_REG_5] = {RV_REG_S4, RV_REG_S3},
++	/*
++	 * Callee-saved registers that in-kernel function will preserve.
++	 * Stored on the stack.
++	 */
++	[BPF_REG_6] = {STACK_OFFSET(BPF_R6_HI), STACK_OFFSET(BPF_R6_LO)},
++	[BPF_REG_7] = {STACK_OFFSET(BPF_R7_HI), STACK_OFFSET(BPF_R7_LO)},
++	[BPF_REG_8] = {STACK_OFFSET(BPF_R8_HI), STACK_OFFSET(BPF_R8_LO)},
++	[BPF_REG_9] = {STACK_OFFSET(BPF_R9_HI), STACK_OFFSET(BPF_R9_LO)},
++	/* Read-only frame pointer to access BPF stack. */
++	[BPF_REG_FP] = {RV_REG_S6, RV_REG_S5},
++	/* Temporary register for blinding constants. Stored on the stack. */
++	[BPF_REG_AX] = {STACK_OFFSET(BPF_AX_HI), STACK_OFFSET(BPF_AX_LO)},
++	/*
++	 * Temporary registers used by the JIT to operate on registers stored
++	 * on the stack. Save t0 and t1 to be used as temporaries in generated
++	 * code.
++	 */
++	[TMP_REG_1] = {RV_REG_T3, RV_REG_T2},
++	[TMP_REG_2] = {RV_REG_T5, RV_REG_T4},
++};
++
++static s8 hi(const s8 *r)
++{
++	return r[0];
++}
++
++static s8 lo(const s8 *r)
++{
++	return r[1];
++}
++
++static void emit_imm(const s8 rd, s32 imm, struct rv_jit_context *ctx)
++{
++	u32 upper = (imm + (1 << 11)) >> 12;
++	u32 lower = imm & 0xfff;
++
++	if (upper) {
++		emit(rv_lui(rd, upper), ctx);
++		emit(rv_addi(rd, rd, lower), ctx);
++	} else {
++		emit(rv_addi(rd, RV_REG_ZERO, lower), ctx);
++	}
++}
++
++static void emit_imm32(const s8 *rd, s32 imm, struct rv_jit_context *ctx)
++{
++	/* Emit immediate into lower bits. */
++	emit_imm(lo(rd), imm, ctx);
++
++	/* Sign-extend into upper bits. */
++	if (imm >= 0)
++		emit(rv_addi(hi(rd), RV_REG_ZERO, 0), ctx);
++	else
++		emit(rv_addi(hi(rd), RV_REG_ZERO, -1), ctx);
++}
++
++static void emit_imm64(const s8 *rd, s32 imm_hi, s32 imm_lo,
++		       struct rv_jit_context *ctx)
++{
++	emit_imm(lo(rd), imm_lo, ctx);
++	emit_imm(hi(rd), imm_hi, ctx);
++}
++
++static void __build_epilogue(bool is_tail_call, struct rv_jit_context *ctx)
++{
++	int stack_adjust = ctx->stack_size, store_offset = stack_adjust - 4;
++	const s8 *r0 = bpf2rv32[BPF_REG_0];
++
++	store_offset -= 4 * BPF_JIT_SCRATCH_REGS;
++
++	/* Set return value if not tail call. */
++	if (!is_tail_call) {
++		emit(rv_addi(RV_REG_A0, lo(r0), 0), ctx);
++		emit(rv_addi(RV_REG_A1, hi(r0), 0), ctx);
++	}
++
++	/* Restore callee-saved registers. */
++	emit(rv_lw(RV_REG_RA, store_offset - 0, RV_REG_SP), ctx);
++	emit(rv_lw(RV_REG_FP, store_offset - 4, RV_REG_SP), ctx);
++	emit(rv_lw(RV_REG_S1, store_offset - 8, RV_REG_SP), ctx);
++	emit(rv_lw(RV_REG_S2, store_offset - 12, RV_REG_SP), ctx);
++	emit(rv_lw(RV_REG_S3, store_offset - 16, RV_REG_SP), ctx);
++	emit(rv_lw(RV_REG_S4, store_offset - 20, RV_REG_SP), ctx);
++	emit(rv_lw(RV_REG_S5, store_offset - 24, RV_REG_SP), ctx);
++	emit(rv_lw(RV_REG_S6, store_offset - 28, RV_REG_SP), ctx);
++	emit(rv_lw(RV_REG_S7, store_offset - 32, RV_REG_SP), ctx);
++
++	emit(rv_addi(RV_REG_SP, RV_REG_SP, stack_adjust), ctx);
++
++	if (is_tail_call) {
++		/*
++		 * goto *(t0 + 4);
++		 * Skips first instruction of prologue which initializes tail
++		 * call counter. Assumes t0 contains address of target program,
++		 * see emit_bpf_tail_call.
++		 */
++		emit(rv_jalr(RV_REG_ZERO, RV_REG_T0, 4), ctx);
++	} else {
++		emit(rv_jalr(RV_REG_ZERO, RV_REG_RA, 0), ctx);
++	}
++}
++
++static bool is_stacked(s8 reg)
++{
++	return reg < 0;
++}
++
++static const s8 *bpf_get_reg64(const s8 *reg, const s8 *tmp,
++			       struct rv_jit_context *ctx)
++{
++	if (is_stacked(hi(reg))) {
++		emit(rv_lw(hi(tmp), hi(reg), RV_REG_FP), ctx);
++		emit(rv_lw(lo(tmp), lo(reg), RV_REG_FP), ctx);
++		reg = tmp;
++	}
++	return reg;
++}
++
++static void bpf_put_reg64(const s8 *reg, const s8 *src,
++			  struct rv_jit_context *ctx)
++{
++	if (is_stacked(hi(reg))) {
++		emit(rv_sw(RV_REG_FP, hi(reg), hi(src)), ctx);
++		emit(rv_sw(RV_REG_FP, lo(reg), lo(src)), ctx);
++	}
++}
++
++static const s8 *bpf_get_reg32(const s8 *reg, const s8 *tmp,
++			       struct rv_jit_context *ctx)
++{
++	if (is_stacked(lo(reg))) {
++		emit(rv_lw(lo(tmp), lo(reg), RV_REG_FP), ctx);
++		reg = tmp;
++	}
++	return reg;
++}
++
++static void bpf_put_reg32(const s8 *reg, const s8 *src,
++			  struct rv_jit_context *ctx)
++{
++	if (is_stacked(lo(reg))) {
++		emit(rv_sw(RV_REG_FP, lo(reg), lo(src)), ctx);
++		if (!ctx->prog->aux->verifier_zext)
++			emit(rv_sw(RV_REG_FP, hi(reg), RV_REG_ZERO), ctx);
++	} else if (!ctx->prog->aux->verifier_zext) {
++		emit(rv_addi(hi(reg), RV_REG_ZERO, 0), ctx);
++	}
++}
++
++static void emit_jump_and_link(u8 rd, s32 rvoff, bool force_jalr,
++			       struct rv_jit_context *ctx)
++{
++	s32 upper, lower;
++
++	if (rvoff && is_21b_int(rvoff) && !force_jalr) {
++		emit(rv_jal(rd, rvoff >> 1), ctx);
++		return;
++	}
++
++	upper = (rvoff + (1 << 11)) >> 12;
++	lower = rvoff & 0xfff;
++	emit(rv_auipc(RV_REG_T1, upper), ctx);
++	emit(rv_jalr(rd, RV_REG_T1, lower), ctx);
++}
++
++static void emit_alu_i64(const s8 *dst, s32 imm,
++			 struct rv_jit_context *ctx, const u8 op)
++{
++	const s8 *tmp1 = bpf2rv32[TMP_REG_1];
++	const s8 *rd = bpf_get_reg64(dst, tmp1, ctx);
++
++	switch (op) {
++	case BPF_MOV:
++		emit_imm32(rd, imm, ctx);
++		break;
++	case BPF_AND:
++		if (is_12b_int(imm)) {
++			emit(rv_andi(lo(rd), lo(rd), imm), ctx);
++		} else {
++			emit_imm(RV_REG_T0, imm, ctx);
++			emit(rv_and(lo(rd), lo(rd), RV_REG_T0), ctx);
++		}
++		if (imm >= 0)
++			emit(rv_addi(hi(rd), RV_REG_ZERO, 0), ctx);
++		break;
++	case BPF_OR:
++		if (is_12b_int(imm)) {
++			emit(rv_ori(lo(rd), lo(rd), imm), ctx);
++		} else {
++			emit_imm(RV_REG_T0, imm, ctx);
++			emit(rv_or(lo(rd), lo(rd), RV_REG_T0), ctx);
++		}
++		if (imm < 0)
++			emit(rv_ori(hi(rd), RV_REG_ZERO, -1), ctx);
++		break;
++	case BPF_XOR:
++		if (is_12b_int(imm)) {
++			emit(rv_xori(lo(rd), lo(rd), imm), ctx);
++		} else {
++			emit_imm(RV_REG_T0, imm, ctx);
++			emit(rv_xor(lo(rd), lo(rd), RV_REG_T0), ctx);
++		}
++		if (imm < 0)
++			emit(rv_xori(hi(rd), hi(rd), -1), ctx);
++		break;
++	case BPF_LSH:
++		if (imm >= 32) {
++			emit(rv_slli(hi(rd), lo(rd), imm - 32), ctx);
++			emit(rv_addi(lo(rd), RV_REG_ZERO, 0), ctx);
++		} else if (imm == 0) {
++			/* Do nothing. */
++		} else {
++			emit(rv_srli(RV_REG_T0, lo(rd), 32 - imm), ctx);
++			emit(rv_slli(hi(rd), hi(rd), imm), ctx);
++			emit(rv_or(hi(rd), RV_REG_T0, hi(rd)), ctx);
++			emit(rv_slli(lo(rd), lo(rd), imm), ctx);
++		}
++		break;
++	case BPF_RSH:
++		if (imm >= 32) {
++			emit(rv_srli(lo(rd), hi(rd), imm - 32), ctx);
++			emit(rv_addi(hi(rd), RV_REG_ZERO, 0), ctx);
++		} else if (imm == 0) {
++			/* Do nothing. */
++		} else {
++			emit(rv_slli(RV_REG_T0, hi(rd), 32 - imm), ctx);
++			emit(rv_srli(lo(rd), lo(rd), imm), ctx);
++			emit(rv_or(lo(rd), RV_REG_T0, lo(rd)), ctx);
++			emit(rv_srli(hi(rd), hi(rd), imm), ctx);
++		}
++		break;
++	case BPF_ARSH:
++		if (imm >= 32) {
++			emit(rv_srai(lo(rd), hi(rd), imm - 32), ctx);
++			emit(rv_srai(hi(rd), hi(rd), 31), ctx);
++		} else if (imm == 0) {
++			/* Do nothing. */
++		} else {
++			emit(rv_slli(RV_REG_T0, hi(rd), 32 - imm), ctx);
++			emit(rv_srli(lo(rd), lo(rd), imm), ctx);
++			emit(rv_or(lo(rd), RV_REG_T0, lo(rd)), ctx);
++			emit(rv_srai(hi(rd), hi(rd), imm), ctx);
++		}
++		break;
++	}
++
++	bpf_put_reg64(dst, rd, ctx);
++}
++
++static void emit_alu_i32(const s8 *dst, s32 imm,
++			 struct rv_jit_context *ctx, const u8 op)
++{
++	const s8 *tmp1 = bpf2rv32[TMP_REG_1];
++	const s8 *rd = bpf_get_reg32(dst, tmp1, ctx);
++
++	switch (op) {
++	case BPF_MOV:
++		emit_imm(lo(rd), imm, ctx);
++		break;
++	case BPF_ADD:
++		if (is_12b_int(imm)) {
++			emit(rv_addi(lo(rd), lo(rd), imm), ctx);
++		} else {
++			emit_imm(RV_REG_T0, imm, ctx);
++			emit(rv_add(lo(rd), lo(rd), RV_REG_T0), ctx);
++		}
++		break;
++	case BPF_SUB:
++		if (is_12b_int(-imm)) {
++			emit(rv_addi(lo(rd), lo(rd), -imm), ctx);
++		} else {
++			emit_imm(RV_REG_T0, imm, ctx);
++			emit(rv_sub(lo(rd), lo(rd), RV_REG_T0), ctx);
++		}
++		break;
++	case BPF_AND:
++		if (is_12b_int(imm)) {
++			emit(rv_andi(lo(rd), lo(rd), imm), ctx);
++		} else {
++			emit_imm(RV_REG_T0, imm, ctx);
++			emit(rv_and(lo(rd), lo(rd), RV_REG_T0), ctx);
++		}
++		break;
++	case BPF_OR:
++		if (is_12b_int(imm)) {
++			emit(rv_ori(lo(rd), lo(rd), imm), ctx);
++		} else {
++			emit_imm(RV_REG_T0, imm, ctx);
++			emit(rv_or(lo(rd), lo(rd), RV_REG_T0), ctx);
++		}
++		break;
++	case BPF_XOR:
++		if (is_12b_int(imm)) {
++			emit(rv_xori(lo(rd), lo(rd), imm), ctx);
++		} else {
++			emit_imm(RV_REG_T0, imm, ctx);
++			emit(rv_xor(lo(rd), lo(rd), RV_REG_T0), ctx);
++		}
++		break;
++	case BPF_LSH:
++		if (is_12b_int(imm)) {
++			emit(rv_slli(lo(rd), lo(rd), imm), ctx);
++		} else {
++			emit_imm(RV_REG_T0, imm, ctx);
++			emit(rv_sll(lo(rd), lo(rd), RV_REG_T0), ctx);
++		}
++		break;
++	case BPF_RSH:
++		if (is_12b_int(imm)) {
++			emit(rv_srli(lo(rd), lo(rd), imm), ctx);
++		} else {
++			emit_imm(RV_REG_T0, imm, ctx);
++			emit(rv_srl(lo(rd), lo(rd), RV_REG_T0), ctx);
++		}
++		break;
++	case BPF_ARSH:
++		if (is_12b_int(imm)) {
++			emit(rv_srai(lo(rd), lo(rd), imm), ctx);
++		} else {
++			emit_imm(RV_REG_T0, imm, ctx);
++			emit(rv_sra(lo(rd), lo(rd), RV_REG_T0), ctx);
++		}
++		break;
++	}
++
++	bpf_put_reg32(dst, rd, ctx);
++}
++
++static void emit_alu_r64(const s8 *dst, const s8 *src,
++			 struct rv_jit_context *ctx, const u8 op)
++{
++	const s8 *tmp1 = bpf2rv32[TMP_REG_1];
++	const s8 *tmp2 = bpf2rv32[TMP_REG_2];
++	const s8 *rd = bpf_get_reg64(dst, tmp1, ctx);
++	const s8 *rs = bpf_get_reg64(src, tmp2, ctx);
++
++	switch (op) {
++	case BPF_MOV:
++		emit(rv_addi(lo(rd), lo(rs), 0), ctx);
++		emit(rv_addi(hi(rd), hi(rs), 0), ctx);
++		break;
++	case BPF_ADD:
++		if (rd == rs) {
++			emit(rv_srli(RV_REG_T0, lo(rd), 31), ctx);
++			emit(rv_slli(hi(rd), hi(rd), 1), ctx);
++			emit(rv_or(hi(rd), RV_REG_T0, hi(rd)), ctx);
++			emit(rv_slli(lo(rd), lo(rd), 1), ctx);
++		} else {
++			emit(rv_add(lo(rd), lo(rd), lo(rs)), ctx);
++			emit(rv_sltu(RV_REG_T0, lo(rd), lo(rs)), ctx);
++			emit(rv_add(hi(rd), hi(rd), hi(rs)), ctx);
++			emit(rv_add(hi(rd), hi(rd), RV_REG_T0), ctx);
++		}
++		break;
++	case BPF_SUB:
++		emit(rv_sub(RV_REG_T1, hi(rd), hi(rs)), ctx);
++		emit(rv_sltu(RV_REG_T0, lo(rd), lo(rs)), ctx);
++		emit(rv_sub(hi(rd), RV_REG_T1, RV_REG_T0), ctx);
++		emit(rv_sub(lo(rd), lo(rd), lo(rs)), ctx);
++		break;
++	case BPF_AND:
++		emit(rv_and(lo(rd), lo(rd), lo(rs)), ctx);
++		emit(rv_and(hi(rd), hi(rd), hi(rs)), ctx);
++		break;
++	case BPF_OR:
++		emit(rv_or(lo(rd), lo(rd), lo(rs)), ctx);
++		emit(rv_or(hi(rd), hi(rd), hi(rs)), ctx);
++		break;
++	case BPF_XOR:
++		emit(rv_xor(lo(rd), lo(rd), lo(rs)), ctx);
++		emit(rv_xor(hi(rd), hi(rd), hi(rs)), ctx);
++		break;
++	case BPF_MUL:
++		emit(rv_mul(RV_REG_T0, hi(rs), lo(rd)), ctx);
++		emit(rv_mul(hi(rd), hi(rd), lo(rs)), ctx);
++		emit(rv_mulhu(RV_REG_T1, lo(rd), lo(rs)), ctx);
++		emit(rv_add(hi(rd), hi(rd), RV_REG_T0), ctx);
++		emit(rv_mul(lo(rd), lo(rd), lo(rs)), ctx);
++		emit(rv_add(hi(rd), hi(rd), RV_REG_T1), ctx);
++		break;
++	case BPF_LSH:
++		emit(rv_addi(RV_REG_T0, lo(rs), -32), ctx);
++		emit(rv_blt(RV_REG_T0, RV_REG_ZERO, 8), ctx);
++		emit(rv_sll(hi(rd), lo(rd), RV_REG_T0), ctx);
++		emit(rv_addi(lo(rd), RV_REG_ZERO, 0), ctx);
++		emit(rv_jal(RV_REG_ZERO, 16), ctx);
++		emit(rv_addi(RV_REG_T1, RV_REG_ZERO, 31), ctx);
++		emit(rv_srli(RV_REG_T0, lo(rd), 1), ctx);
++		emit(rv_sub(RV_REG_T1, RV_REG_T1, lo(rs)), ctx);
++		emit(rv_srl(RV_REG_T0, RV_REG_T0, RV_REG_T1), ctx);
++		emit(rv_sll(hi(rd), hi(rd), lo(rs)), ctx);
++		emit(rv_or(hi(rd), RV_REG_T0, hi(rd)), ctx);
++		emit(rv_sll(lo(rd), lo(rd), lo(rs)), ctx);
++		break;
++	case BPF_RSH:
++		emit(rv_addi(RV_REG_T0, lo(rs), -32), ctx);
++		emit(rv_blt(RV_REG_T0, RV_REG_ZERO, 8), ctx);
++		emit(rv_srl(lo(rd), hi(rd), RV_REG_T0), ctx);
++		emit(rv_addi(hi(rd), RV_REG_ZERO, 0), ctx);
++		emit(rv_jal(RV_REG_ZERO, 16), ctx);
++		emit(rv_addi(RV_REG_T1, RV_REG_ZERO, 31), ctx);
++		emit(rv_slli(RV_REG_T0, hi(rd), 1), ctx);
++		emit(rv_sub(RV_REG_T1, RV_REG_T1, lo(rs)), ctx);
++		emit(rv_sll(RV_REG_T0, RV_REG_T0, RV_REG_T1), ctx);
++		emit(rv_srl(lo(rd), lo(rd), lo(rs)), ctx);
++		emit(rv_or(lo(rd), RV_REG_T0, lo(rd)), ctx);
++		emit(rv_srl(hi(rd), hi(rd), lo(rs)), ctx);
++		break;
++	case BPF_ARSH:
++		emit(rv_addi(RV_REG_T0, lo(rs), -32), ctx);
++		emit(rv_blt(RV_REG_T0, RV_REG_ZERO, 8), ctx);
++		emit(rv_sra(lo(rd), hi(rd), RV_REG_T0), ctx);
++		emit(rv_srai(hi(rd), hi(rd), 31), ctx);
++		emit(rv_jal(RV_REG_ZERO, 16), ctx);
++		emit(rv_addi(RV_REG_T1, RV_REG_ZERO, 31), ctx);
++		emit(rv_slli(RV_REG_T0, hi(rd), 1), ctx);
++		emit(rv_sub(RV_REG_T1, RV_REG_T1, lo(rs)), ctx);
++		emit(rv_sll(RV_REG_T0, RV_REG_T0, RV_REG_T1), ctx);
++		emit(rv_srl(lo(rd), lo(rd), lo(rs)), ctx);
++		emit(rv_or(lo(rd), RV_REG_T0, lo(rd)), ctx);
++		emit(rv_sra(hi(rd), hi(rd), lo(rs)), ctx);
++		break;
++	case BPF_NEG:
++		emit(rv_sub(lo(rd), RV_REG_ZERO, lo(rd)), ctx);
++		emit(rv_sltu(RV_REG_T0, RV_REG_ZERO, lo(rd)), ctx);
++		emit(rv_sub(hi(rd), RV_REG_ZERO, hi(rd)), ctx);
++		emit(rv_sub(hi(rd), hi(rd), RV_REG_T0), ctx);
++		break;
++	}
++
++	bpf_put_reg64(dst, rd, ctx);
++}
++
++static void emit_alu_r32(const s8 *dst, const s8 *src,
++			 struct rv_jit_context *ctx, const u8 op)
++{
++	const s8 *tmp1 = bpf2rv32[TMP_REG_1];
++	const s8 *tmp2 = bpf2rv32[TMP_REG_2];
++	const s8 *rd = bpf_get_reg32(dst, tmp1, ctx);
++	const s8 *rs = bpf_get_reg32(src, tmp2, ctx);
++
++	switch (op) {
++	case BPF_MOV:
++		emit(rv_addi(lo(rd), lo(rs), 0), ctx);
++		break;
++	case BPF_ADD:
++		emit(rv_add(lo(rd), lo(rd), lo(rs)), ctx);
++		break;
++	case BPF_SUB:
++		emit(rv_sub(lo(rd), lo(rd), lo(rs)), ctx);
++		break;
++	case BPF_AND:
++		emit(rv_and(lo(rd), lo(rd), lo(rs)), ctx);
++		break;
++	case BPF_OR:
++		emit(rv_or(lo(rd), lo(rd), lo(rs)), ctx);
++		break;
++	case BPF_XOR:
++		emit(rv_xor(lo(rd), lo(rd), lo(rs)), ctx);
++		break;
++	case BPF_MUL:
++		emit(rv_mul(lo(rd), lo(rd), lo(rs)), ctx);
++		break;
++	case BPF_DIV:
++		emit(rv_divu(lo(rd), lo(rd), lo(rs)), ctx);
++		break;
++	case BPF_MOD:
++		emit(rv_remu(lo(rd), lo(rd), lo(rs)), ctx);
++		break;
++	case BPF_LSH:
++		emit(rv_sll(lo(rd), lo(rd), lo(rs)), ctx);
++		break;
++	case BPF_RSH:
++		emit(rv_srl(lo(rd), lo(rd), lo(rs)), ctx);
++		break;
++	case BPF_ARSH:
++		emit(rv_sra(lo(rd), lo(rd), lo(rs)), ctx);
++		break;
++	case BPF_NEG:
++		emit(rv_sub(lo(rd), RV_REG_ZERO, lo(rd)), ctx);
++		break;
++	}
++
++	bpf_put_reg32(dst, rd, ctx);
++}
++
++static int emit_branch_r64(const s8 *src1, const s8 *src2, s32 rvoff,
++			   struct rv_jit_context *ctx, const u8 op)
++{
++	int e, s = ctx->ninsns;
++	const s8 *tmp1 = bpf2rv32[TMP_REG_1];
++	const s8 *tmp2 = bpf2rv32[TMP_REG_2];
++
++	const s8 *rs1 = bpf_get_reg64(src1, tmp1, ctx);
++	const s8 *rs2 = bpf_get_reg64(src2, tmp2, ctx);
++
++	/*
++	 * NO_JUMP skips over the rest of the instructions and the
++	 * emit_jump_and_link, meaning the BPF branch is not taken.
++	 * JUMP skips directly to the emit_jump_and_link, meaning
++	 * the BPF branch is taken.
++	 *
++	 * The fallthrough case results in the BPF branch being taken.
++	 */
++#define NO_JUMP(idx) (6 + (2 * (idx)))
++#define JUMP(idx) (2 + (2 * (idx)))
++
++	switch (op) {
++	case BPF_JEQ:
++		emit(rv_bne(hi(rs1), hi(rs2), NO_JUMP(1)), ctx);
++		emit(rv_bne(lo(rs1), lo(rs2), NO_JUMP(0)), ctx);
++		break;
++	case BPF_JGT:
++		emit(rv_bgtu(hi(rs1), hi(rs2), JUMP(2)), ctx);
++		emit(rv_bltu(hi(rs1), hi(rs2), NO_JUMP(1)), ctx);
++		emit(rv_bleu(lo(rs1), lo(rs2), NO_JUMP(0)), ctx);
++		break;
++	case BPF_JLT:
++		emit(rv_bltu(hi(rs1), hi(rs2), JUMP(2)), ctx);
++		emit(rv_bgtu(hi(rs1), hi(rs2), NO_JUMP(1)), ctx);
++		emit(rv_bgeu(lo(rs1), lo(rs2), NO_JUMP(0)), ctx);
++		break;
++	case BPF_JGE:
++		emit(rv_bgtu(hi(rs1), hi(rs2), JUMP(2)), ctx);
++		emit(rv_bltu(hi(rs1), hi(rs2), NO_JUMP(1)), ctx);
++		emit(rv_bltu(lo(rs1), lo(rs2), NO_JUMP(0)), ctx);
++		break;
++	case BPF_JLE:
++		emit(rv_bltu(hi(rs1), hi(rs2), JUMP(2)), ctx);
++		emit(rv_bgtu(hi(rs1), hi(rs2), NO_JUMP(1)), ctx);
++		emit(rv_bgtu(lo(rs1), lo(rs2), NO_JUMP(0)), ctx);
++		break;
++	case BPF_JNE:
++		emit(rv_bne(hi(rs1), hi(rs2), JUMP(1)), ctx);
++		emit(rv_beq(lo(rs1), lo(rs2), NO_JUMP(0)), ctx);
++		break;
++	case BPF_JSGT:
++		emit(rv_bgt(hi(rs1), hi(rs2), JUMP(2)), ctx);
++		emit(rv_blt(hi(rs1), hi(rs2), NO_JUMP(1)), ctx);
++		emit(rv_bleu(lo(rs1), lo(rs2), NO_JUMP(0)), ctx);
++		break;
++	case BPF_JSLT:
++		emit(rv_blt(hi(rs1), hi(rs2), JUMP(2)), ctx);
++		emit(rv_bgt(hi(rs1), hi(rs2), NO_JUMP(1)), ctx);
++		emit(rv_bgeu(lo(rs1), lo(rs2), NO_JUMP(0)), ctx);
++		break;
++	case BPF_JSGE:
++		emit(rv_bgt(hi(rs1), hi(rs2), JUMP(2)), ctx);
++		emit(rv_blt(hi(rs1), hi(rs2), NO_JUMP(1)), ctx);
++		emit(rv_bltu(lo(rs1), lo(rs2), NO_JUMP(0)), ctx);
++		break;
++	case BPF_JSLE:
++		emit(rv_blt(hi(rs1), hi(rs2), JUMP(2)), ctx);
++		emit(rv_bgt(hi(rs1), hi(rs2), NO_JUMP(1)), ctx);
++		emit(rv_bgtu(lo(rs1), lo(rs2), NO_JUMP(0)), ctx);
++		break;
++	case BPF_JSET:
++		emit(rv_and(RV_REG_T0, hi(rs1), hi(rs2)), ctx);
++		emit(rv_bne(RV_REG_T0, RV_REG_ZERO, JUMP(2)), ctx);
++		emit(rv_and(RV_REG_T0, lo(rs1), lo(rs2)), ctx);
++		emit(rv_beq(RV_REG_T0, RV_REG_ZERO, NO_JUMP(0)), ctx);
++		break;
++	}
++
++#undef NO_JUMP
++#undef JUMP
++
++	e = ctx->ninsns;
++	/* Adjust for extra insns. */
++	rvoff -= (e - s) << 2;
++	emit_jump_and_link(RV_REG_ZERO, rvoff, true, ctx);
++	return 0;
++}
++
++static int emit_bcc(u8 op, u8 rd, u8 rs, int rvoff, struct rv_jit_context *ctx)
++{
++	int e, s = ctx->ninsns;
++	bool far = false;
++	int off;
++
++	if (op == BPF_JSET) {
++		/*
++		 * BPF_JSET is a special case: it has no inverse so we always
++		 * treat it as a far branch.
++		 */
++		far = true;
++	} else if (!is_13b_int(rvoff)) {
++		op = invert_bpf_cond(op);
++		far = true;
++	}
++
++	/*
++	 * For a far branch, the condition is negated and we jump over the
++	 * branch itself, and the two instructions from emit_jump_and_link.
++	 * For a near branch, just use rvoff.
++	 */
++	off = far ? 6 : (rvoff >> 1);
++
++	switch (op) {
++	case BPF_JEQ:
++		emit(rv_beq(rd, rs, off), ctx);
++		break;
++	case BPF_JGT:
++		emit(rv_bgtu(rd, rs, off), ctx);
++		break;
++	case BPF_JLT:
++		emit(rv_bltu(rd, rs, off), ctx);
++		break;
++	case BPF_JGE:
++		emit(rv_bgeu(rd, rs, off), ctx);
++		break;
++	case BPF_JLE:
++		emit(rv_bleu(rd, rs, off), ctx);
++		break;
++	case BPF_JNE:
++		emit(rv_bne(rd, rs, off), ctx);
++		break;
++	case BPF_JSGT:
++		emit(rv_bgt(rd, rs, off), ctx);
++		break;
++	case BPF_JSLT:
++		emit(rv_blt(rd, rs, off), ctx);
++		break;
++	case BPF_JSGE:
++		emit(rv_bge(rd, rs, off), ctx);
++		break;
++	case BPF_JSLE:
++		emit(rv_ble(rd, rs, off), ctx);
++		break;
++	case BPF_JSET:
++		emit(rv_and(RV_REG_T0, rd, rs), ctx);
++		emit(rv_beq(RV_REG_T0, RV_REG_ZERO, off), ctx);
++		break;
++	}
++
++	if (far) {
++		e = ctx->ninsns;
++		/* Adjust for extra insns. */
++		rvoff -= (e - s) << 2;
++		emit_jump_and_link(RV_REG_ZERO, rvoff, true, ctx);
++	}
++	return 0;
++}
++
++static int emit_branch_r32(const s8 *src1, const s8 *src2, s32 rvoff,
++			   struct rv_jit_context *ctx, const u8 op)
++{
++	int e, s = ctx->ninsns;
++	const s8 *tmp1 = bpf2rv32[TMP_REG_1];
++	const s8 *tmp2 = bpf2rv32[TMP_REG_2];
++
++	const s8 *rs1 = bpf_get_reg32(src1, tmp1, ctx);
++	const s8 *rs2 = bpf_get_reg32(src2, tmp2, ctx);
++
++	e = ctx->ninsns;
++	/* Adjust for extra insns. */
++	rvoff -= (e - s) << 2;
++
++	if (emit_bcc(op, lo(rs1), lo(rs2), rvoff, ctx))
++		return -1;
++
++	return 0;
++}
++
++static void emit_call(bool fixed, u64 addr, struct rv_jit_context *ctx)
++{
++	const s8 *r0 = bpf2rv32[BPF_REG_0];
++	const s8 *r5 = bpf2rv32[BPF_REG_5];
++	u32 upper = ((u32)addr + (1 << 11)) >> 12;
++	u32 lower = addr & 0xfff;
++
++	/* R1-R4 already in correct registers---need to push R5 to stack. */
++	emit(rv_addi(RV_REG_SP, RV_REG_SP, -16), ctx);
++	emit(rv_sw(RV_REG_SP, 0, lo(r5)), ctx);
++	emit(rv_sw(RV_REG_SP, 4, hi(r5)), ctx);
++
++	/* Backup TCC. */
++	emit(rv_addi(RV_REG_TCC_SAVED, RV_REG_TCC, 0), ctx);
++
++	/*
++	 * Use lui/jalr pair to jump to absolute address. Don't use emit_imm as
++	 * the number of emitted instructions should not depend on the value of
++	 * addr.
++	 */
++	emit(rv_lui(RV_REG_T1, upper), ctx);
++	emit(rv_jalr(RV_REG_RA, RV_REG_T1, lower), ctx);
++
++	/* Restore TCC. */
++	emit(rv_addi(RV_REG_TCC, RV_REG_TCC_SAVED, 0), ctx);
++
++	/* Set return value and restore stack. */
++	emit(rv_addi(lo(r0), RV_REG_A0, 0), ctx);
++	emit(rv_addi(hi(r0), RV_REG_A1, 0), ctx);
++	emit(rv_addi(RV_REG_SP, RV_REG_SP, 16), ctx);
++}
++
++static int emit_bpf_tail_call(int insn, struct rv_jit_context *ctx)
++{
++	/*
++	 * R1 -> &ctx
++	 * R2 -> &array
++	 * R3 -> index
++	 */
++	int tc_ninsn, off, start_insn = ctx->ninsns;
++	const s8 *arr_reg = bpf2rv32[BPF_REG_2];
++	const s8 *idx_reg = bpf2rv32[BPF_REG_3];
++
++	tc_ninsn = insn ? ctx->offset[insn] - ctx->offset[insn - 1] :
++		ctx->offset[0];
++
++	/* max_entries = array->map.max_entries; */
++	off = offsetof(struct bpf_array, map.max_entries);
++	if (is_12b_check(off, insn))
++		return -1;
++	emit(rv_lw(RV_REG_T1, off, lo(arr_reg)), ctx);
++
++	/*
++	 * if (index >= max_entries)
++	 *   goto out;
++	 */
++	off = (tc_ninsn - (ctx->ninsns - start_insn)) << 2;
++	emit_bcc(BPF_JGE, lo(idx_reg), RV_REG_T1, off, ctx);
++
++	/*
++	 * if ((temp_tcc = tcc - 1) < 0)
++	 *   goto out;
++	 */
++	emit(rv_addi(RV_REG_T1, RV_REG_TCC, -1), ctx);
++	off = (tc_ninsn - (ctx->ninsns - start_insn)) << 2;
++	emit_bcc(BPF_JSLT, RV_REG_T1, RV_REG_ZERO, off, ctx);
++
++	/*
++	 * prog = array->ptrs[index];
++	 * if (!prog)
++	 *   goto out;
++	 */
++	emit(rv_slli(RV_REG_T0, lo(idx_reg), 2), ctx);
++	emit(rv_add(RV_REG_T0, RV_REG_T0, lo(arr_reg)), ctx);
++	off = offsetof(struct bpf_array, ptrs);
++	if (is_12b_check(off, insn))
++		return -1;
++	emit(rv_lw(RV_REG_T0, off, RV_REG_T0), ctx);
++	off = (tc_ninsn - (ctx->ninsns - start_insn)) << 2;
++	emit_bcc(BPF_JEQ, RV_REG_T0, RV_REG_ZERO, off, ctx);
++
++	/*
++	 * tcc = temp_tcc;
++	 * goto *(prog->bpf_func + 4);
++	 */
++	off = offsetof(struct bpf_prog, bpf_func);
++	if (is_12b_check(off, insn))
++		return -1;
++	emit(rv_lw(RV_REG_T0, off, RV_REG_T0), ctx);
++	emit(rv_addi(RV_REG_TCC, RV_REG_T1, 0), ctx);
++	/* Epilogue jumps to *(t0 + 4). */
++	__build_epilogue(true, ctx);
++	return 0;
++}
++
++static int emit_load_r64(const s8 *dst, const s8 *src, s16 off,
++			 struct rv_jit_context *ctx, const u8 size)
++{
++	const s8 *tmp1 = bpf2rv32[TMP_REG_1];
++	const s8 *tmp2 = bpf2rv32[TMP_REG_2];
++	const s8 *rd = bpf_get_reg64(dst, tmp1, ctx);
++	const s8 *rs = bpf_get_reg64(src, tmp2, ctx);
++
++	emit_imm(RV_REG_T0, off, ctx);
++	emit(rv_add(RV_REG_T0, RV_REG_T0, lo(rs)), ctx);
++
++	switch (size) {
++	case BPF_B:
++		emit(rv_lbu(lo(rd), 0, RV_REG_T0), ctx);
++		if (!ctx->prog->aux->verifier_zext)
++			emit(rv_addi(hi(rd), RV_REG_ZERO, 0), ctx);
++		break;
++	case BPF_H:
++		emit(rv_lhu(lo(rd), 0, RV_REG_T0), ctx);
++		if (!ctx->prog->aux->verifier_zext)
++			emit(rv_addi(hi(rd), RV_REG_ZERO, 0), ctx);
++		break;
++	case BPF_W:
++		emit(rv_lw(lo(rd), 0, RV_REG_T0), ctx);
++		if (!ctx->prog->aux->verifier_zext)
++			emit(rv_addi(hi(rd), RV_REG_ZERO, 0), ctx);
++		break;
++	case BPF_DW:
++		emit(rv_lw(lo(rd), 0, RV_REG_T0), ctx);
++		emit(rv_lw(hi(rd), 4, RV_REG_T0), ctx);
++		break;
++	}
++
++	bpf_put_reg64(dst, rd, ctx);
++	return 0;
++}
++
++static int emit_store_r64(const s8 *dst, const s8 *src, s16 off,
++			  struct rv_jit_context *ctx, const u8 size,
++			  const u8 mode)
++{
++	const s8 *tmp1 = bpf2rv32[TMP_REG_1];
++	const s8 *tmp2 = bpf2rv32[TMP_REG_2];
++	const s8 *rd = bpf_get_reg64(dst, tmp1, ctx);
++	const s8 *rs = bpf_get_reg64(src, tmp2, ctx);
++
++	if (mode == BPF_XADD && size != BPF_W)
++		return -1;
++
++	emit_imm(RV_REG_T0, off, ctx);
++	emit(rv_add(RV_REG_T0, RV_REG_T0, lo(rd)), ctx);
++
++	switch (size) {
++	case BPF_B:
++		emit(rv_sb(RV_REG_T0, 0, lo(rs)), ctx);
++		break;
++	case BPF_H:
++		emit(rv_sh(RV_REG_T0, 0, lo(rs)), ctx);
++		break;
++	case BPF_W:
++		switch (mode) {
++		case BPF_MEM:
++			emit(rv_sw(RV_REG_T0, 0, lo(rs)), ctx);
++			break;
++		case BPF_XADD:
++			emit(rv_amoadd_w(RV_REG_ZERO, lo(rs), RV_REG_T0, 0, 0),
++			     ctx);
++			break;
++		}
++		break;
++	case BPF_DW:
++		emit(rv_sw(RV_REG_T0, 0, lo(rs)), ctx);
++		emit(rv_sw(RV_REG_T0, 4, hi(rs)), ctx);
++		break;
++	}
++
++	return 0;
++}
++
++static void emit_rev16(const s8 rd, struct rv_jit_context *ctx)
++{
++	emit(rv_slli(rd, rd, 16), ctx);
++	emit(rv_slli(RV_REG_T1, rd, 8), ctx);
++	emit(rv_srli(rd, rd, 8), ctx);
++	emit(rv_add(RV_REG_T1, rd, RV_REG_T1), ctx);
++	emit(rv_srli(rd, RV_REG_T1, 16), ctx);
++}
++
++static void emit_rev32(const s8 rd, struct rv_jit_context *ctx)
++{
++	emit(rv_addi(RV_REG_T1, RV_REG_ZERO, 0), ctx);
++	emit(rv_andi(RV_REG_T0, rd, 255), ctx);
++	emit(rv_add(RV_REG_T1, RV_REG_T1, RV_REG_T0), ctx);
++	emit(rv_slli(RV_REG_T1, RV_REG_T1, 8), ctx);
++	emit(rv_srli(rd, rd, 8), ctx);
++	emit(rv_andi(RV_REG_T0, rd, 255), ctx);
++	emit(rv_add(RV_REG_T1, RV_REG_T1, RV_REG_T0), ctx);
++	emit(rv_slli(RV_REG_T1, RV_REG_T1, 8), ctx);
++	emit(rv_srli(rd, rd, 8), ctx);
++	emit(rv_andi(RV_REG_T0, rd, 255), ctx);
++	emit(rv_add(RV_REG_T1, RV_REG_T1, RV_REG_T0), ctx);
++	emit(rv_slli(RV_REG_T1, RV_REG_T1, 8), ctx);
++	emit(rv_srli(rd, rd, 8), ctx);
++	emit(rv_andi(RV_REG_T0, rd, 255), ctx);
++	emit(rv_add(RV_REG_T1, RV_REG_T1, RV_REG_T0), ctx);
++	emit(rv_addi(rd, RV_REG_T1, 0), ctx);
++}
++
++static void emit_zext64(const s8 *dst, struct rv_jit_context *ctx)
++{
++	const s8 *rd;
++	const s8 *tmp1 = bpf2rv32[TMP_REG_1];
++
++	rd = bpf_get_reg64(dst, tmp1, ctx);
++	emit(rv_addi(hi(rd), RV_REG_ZERO, 0), ctx);
++	bpf_put_reg64(dst, rd, ctx);
++}
++
++int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
++		      bool extra_pass)
++{
++	bool is64 = BPF_CLASS(insn->code) == BPF_ALU64 ||
++		BPF_CLASS(insn->code) == BPF_JMP;
++	int s, e, rvoff, i = insn - ctx->prog->insnsi;
++	u8 code = insn->code;
++	s16 off = insn->off;
++	s32 imm = insn->imm;
++
++	const s8 *dst = bpf2rv32[insn->dst_reg];
++	const s8 *src = bpf2rv32[insn->src_reg];
++	const s8 *tmp1 = bpf2rv32[TMP_REG_1];
++	const s8 *tmp2 = bpf2rv32[TMP_REG_2];
++
++	switch (code) {
++	case BPF_ALU64 | BPF_MOV | BPF_X:
++
++	case BPF_ALU64 | BPF_ADD | BPF_X:
++	case BPF_ALU64 | BPF_ADD | BPF_K:
++
++	case BPF_ALU64 | BPF_SUB | BPF_X:
++	case BPF_ALU64 | BPF_SUB | BPF_K:
++
++	case BPF_ALU64 | BPF_AND | BPF_X:
++	case BPF_ALU64 | BPF_OR | BPF_X:
++	case BPF_ALU64 | BPF_XOR | BPF_X:
++
++	case BPF_ALU64 | BPF_MUL | BPF_X:
++	case BPF_ALU64 | BPF_MUL | BPF_K:
++
++	case BPF_ALU64 | BPF_LSH | BPF_X:
++	case BPF_ALU64 | BPF_RSH | BPF_X:
++	case BPF_ALU64 | BPF_ARSH | BPF_X:
++		if (BPF_SRC(code) == BPF_K) {
++			emit_imm32(tmp2, imm, ctx);
++			src = tmp2;
++		}
++		emit_alu_r64(dst, src, ctx, BPF_OP(code));
++		break;
++
++	case BPF_ALU64 | BPF_NEG:
++		emit_alu_r64(dst, tmp2, ctx, BPF_OP(code));
++		break;
++
++	case BPF_ALU64 | BPF_DIV | BPF_X:
++	case BPF_ALU64 | BPF_DIV | BPF_K:
++	case BPF_ALU64 | BPF_MOD | BPF_X:
++	case BPF_ALU64 | BPF_MOD | BPF_K:
++		goto notsupported;
++
++	case BPF_ALU64 | BPF_MOV | BPF_K:
++	case BPF_ALU64 | BPF_AND | BPF_K:
++	case BPF_ALU64 | BPF_OR | BPF_K:
++	case BPF_ALU64 | BPF_XOR | BPF_K:
++	case BPF_ALU64 | BPF_LSH | BPF_K:
++	case BPF_ALU64 | BPF_RSH | BPF_K:
++	case BPF_ALU64 | BPF_ARSH | BPF_K:
++		emit_alu_i64(dst, imm, ctx, BPF_OP(code));
++		break;
++
++	case BPF_ALU | BPF_MOV | BPF_X:
++		if (imm == 1) {
++			/* Special mov32 for zext. */
++			emit_zext64(dst, ctx);
++			break;
++		}
++		/* Fallthrough. */
++
++	case BPF_ALU | BPF_ADD | BPF_X:
++	case BPF_ALU | BPF_SUB | BPF_X:
++	case BPF_ALU | BPF_AND | BPF_X:
++	case BPF_ALU | BPF_OR | BPF_X:
++	case BPF_ALU | BPF_XOR | BPF_X:
++
++	case BPF_ALU | BPF_MUL | BPF_X:
++	case BPF_ALU | BPF_MUL | BPF_K:
++
++	case BPF_ALU | BPF_DIV | BPF_X:
++	case BPF_ALU | BPF_DIV | BPF_K:
++
++	case BPF_ALU | BPF_MOD | BPF_X:
++	case BPF_ALU | BPF_MOD | BPF_K:
++
++	case BPF_ALU | BPF_LSH | BPF_X:
++	case BPF_ALU | BPF_RSH | BPF_X:
++	case BPF_ALU | BPF_ARSH | BPF_X:
++		if (BPF_SRC(code) == BPF_K) {
++			emit_imm32(tmp2, imm, ctx);
++			src = tmp2;
++		}
++		emit_alu_r32(dst, src, ctx, BPF_OP(code));
++		break;
++
++	case BPF_ALU | BPF_MOV | BPF_K:
++	case BPF_ALU | BPF_ADD | BPF_K:
++	case BPF_ALU | BPF_SUB | BPF_K:
++	case BPF_ALU | BPF_AND | BPF_K:
++	case BPF_ALU | BPF_OR | BPF_K:
++	case BPF_ALU | BPF_XOR | BPF_K:
++	case BPF_ALU | BPF_LSH | BPF_K:
++	case BPF_ALU | BPF_RSH | BPF_K:
++	case BPF_ALU | BPF_ARSH | BPF_K:
++		/*
++		 * mul,div,mod are handled in the BPF_X case since there are
++		 * no RISC-V I-type equivalents.
++		 */
++		emit_alu_i32(dst, imm, ctx, BPF_OP(code));
++		break;
++
++	case BPF_ALU | BPF_NEG:
++		/*
++		 * src is ignored---choose tmp2 as a dummy register since it
++		 * is not on the stack.
++		 */
++		emit_alu_r32(dst, tmp2, ctx, BPF_OP(code));
++		break;
++
++	case BPF_ALU | BPF_END | BPF_FROM_LE:
++	{
++		const s8 *rd = bpf_get_reg64(dst, tmp1, ctx);
++
++		switch (imm) {
++		case 16:
++			emit(rv_slli(lo(rd), lo(rd), 16), ctx);
++			emit(rv_srli(lo(rd), lo(rd), 16), ctx);
++			/* Fallthrough. */
++		case 32:
++			if (!ctx->prog->aux->verifier_zext)
++				emit(rv_addi(hi(rd), RV_REG_ZERO, 0), ctx);
++			break;
++		case 64:
++			/* Do nothing. */
++			break;
++		default:
++			pr_err("bpf-jit: BPF_END imm %d invalid\n", imm);
++			return -1;
++		}
++
++		bpf_put_reg64(dst, rd, ctx);
++		break;
++	}
++
++	case BPF_ALU | BPF_END | BPF_FROM_BE:
++	{
++		const s8 *rd = bpf_get_reg64(dst, tmp1, ctx);
++
++		switch (imm) {
++		case 16:
++			emit_rev16(lo(rd), ctx);
++			if (!ctx->prog->aux->verifier_zext)
++				emit(rv_addi(hi(rd), RV_REG_ZERO, 0), ctx);
++			break;
++		case 32:
++			emit_rev32(lo(rd), ctx);
++			if (!ctx->prog->aux->verifier_zext)
++				emit(rv_addi(hi(rd), RV_REG_ZERO, 0), ctx);
++			break;
++		case 64:
++			/* Swap upper and lower halves. */
++			emit(rv_addi(RV_REG_T0, lo(rd), 0), ctx);
++			emit(rv_addi(lo(rd), hi(rd), 0), ctx);
++			emit(rv_addi(hi(rd), RV_REG_T0, 0), ctx);
++
++			/* Swap each half. */
++			emit_rev32(lo(rd), ctx);
++			emit_rev32(hi(rd), ctx);
++			break;
++		default:
++			pr_err("bpf-jit: BPF_END imm %d invalid\n", imm);
++			return -1;
++		}
++
++		bpf_put_reg64(dst, rd, ctx);
++		break;
++	}
++
++	case BPF_JMP | BPF_JA:
++		rvoff = rv_offset(i, off, ctx);
++		emit_jump_and_link(RV_REG_ZERO, rvoff, false, ctx);
++		break;
++
++	case BPF_JMP | BPF_CALL:
++	{
++		bool fixed;
++		int ret;
++		u64 addr;
++
++		ret = bpf_jit_get_func_addr(ctx->prog, insn, extra_pass, &addr,
++					    &fixed);
++		if (ret < 0)
++			return ret;
++		emit_call(fixed, addr, ctx);
++		break;
++	}
++
++	case BPF_JMP | BPF_TAIL_CALL:
++		if (emit_bpf_tail_call(i, ctx))
++			return -1;
++		break;
++
++	case BPF_JMP | BPF_JEQ | BPF_X:
++	case BPF_JMP | BPF_JEQ | BPF_K:
++	case BPF_JMP32 | BPF_JEQ | BPF_X:
++	case BPF_JMP32 | BPF_JEQ | BPF_K:
++
++	case BPF_JMP | BPF_JNE | BPF_X:
++	case BPF_JMP | BPF_JNE | BPF_K:
++	case BPF_JMP32 | BPF_JNE | BPF_X:
++	case BPF_JMP32 | BPF_JNE | BPF_K:
++
++	case BPF_JMP | BPF_JLE | BPF_X:
++	case BPF_JMP | BPF_JLE | BPF_K:
++	case BPF_JMP32 | BPF_JLE | BPF_X:
++	case BPF_JMP32 | BPF_JLE | BPF_K:
++
++	case BPF_JMP | BPF_JLT | BPF_X:
++	case BPF_JMP | BPF_JLT | BPF_K:
++	case BPF_JMP32 | BPF_JLT | BPF_X:
++	case BPF_JMP32 | BPF_JLT | BPF_K:
++
++	case BPF_JMP | BPF_JGE | BPF_X:
++	case BPF_JMP | BPF_JGE | BPF_K:
++	case BPF_JMP32 | BPF_JGE | BPF_X:
++	case BPF_JMP32 | BPF_JGE | BPF_K:
++
++	case BPF_JMP | BPF_JGT | BPF_X:
++	case BPF_JMP | BPF_JGT | BPF_K:
++	case BPF_JMP32 | BPF_JGT | BPF_X:
++	case BPF_JMP32 | BPF_JGT | BPF_K:
++
++	case BPF_JMP | BPF_JSLE | BPF_X:
++	case BPF_JMP | BPF_JSLE | BPF_K:
++	case BPF_JMP32 | BPF_JSLE | BPF_X:
++	case BPF_JMP32 | BPF_JSLE | BPF_K:
++
++	case BPF_JMP | BPF_JSLT | BPF_X:
++	case BPF_JMP | BPF_JSLT | BPF_K:
++	case BPF_JMP32 | BPF_JSLT | BPF_X:
++	case BPF_JMP32 | BPF_JSLT | BPF_K:
++
++	case BPF_JMP | BPF_JSGE | BPF_X:
++	case BPF_JMP | BPF_JSGE | BPF_K:
++	case BPF_JMP32 | BPF_JSGE | BPF_X:
++	case BPF_JMP32 | BPF_JSGE | BPF_K:
++
++	case BPF_JMP | BPF_JSGT | BPF_X:
++	case BPF_JMP | BPF_JSGT | BPF_K:
++	case BPF_JMP32 | BPF_JSGT | BPF_X:
++	case BPF_JMP32 | BPF_JSGT | BPF_K:
++
++	case BPF_JMP | BPF_JSET | BPF_X:
++	case BPF_JMP | BPF_JSET | BPF_K:
++	case BPF_JMP32 | BPF_JSET | BPF_X:
++	case BPF_JMP32 | BPF_JSET | BPF_K:
++		rvoff = rv_offset(i, off, ctx);
++		if (BPF_SRC(code) == BPF_K) {
++			s = ctx->ninsns;
++			emit_imm32(tmp2, imm, ctx);
++			src = tmp2;
++			e = ctx->ninsns;
++			rvoff -= (e - s) << 2;
++		}
++
++		if (is64)
++			emit_branch_r64(dst, src, rvoff, ctx, BPF_OP(code));
++		else
++			emit_branch_r32(dst, src, rvoff, ctx, BPF_OP(code));
++		break;
++
++	case BPF_JMP | BPF_EXIT:
++		if (i == ctx->prog->len - 1)
++			break;
++
++		rvoff = epilogue_offset(ctx);
++		emit_jump_and_link(RV_REG_ZERO, rvoff, false, ctx);
++		break;
++
++	case BPF_LD | BPF_IMM | BPF_DW:
++	{
++		struct bpf_insn insn1 = insn[1];
++		s32 imm_lo = imm;
++		s32 imm_hi = insn1.imm;
++		const s8 *rd = bpf_get_reg64(dst, tmp1, ctx);
++
++		emit_imm64(rd, imm_hi, imm_lo, ctx);
++		bpf_put_reg64(dst, rd, ctx);
++		return 1;
++	}
++
++	case BPF_LDX | BPF_MEM | BPF_B:
++	case BPF_LDX | BPF_MEM | BPF_H:
++	case BPF_LDX | BPF_MEM | BPF_W:
++	case BPF_LDX | BPF_MEM | BPF_DW:
++		if (emit_load_r64(dst, src, off, ctx, BPF_SIZE(code)))
++			return -1;
++		break;
++
++	case BPF_ST | BPF_MEM | BPF_B:
++	case BPF_ST | BPF_MEM | BPF_H:
++	case BPF_ST | BPF_MEM | BPF_W:
++	case BPF_ST | BPF_MEM | BPF_DW:
++
++	case BPF_STX | BPF_MEM | BPF_B:
++	case BPF_STX | BPF_MEM | BPF_H:
++	case BPF_STX | BPF_MEM | BPF_W:
++	case BPF_STX | BPF_MEM | BPF_DW:
++	case BPF_STX | BPF_XADD | BPF_W:
++		if (BPF_CLASS(code) == BPF_ST) {
++			emit_imm32(tmp2, imm, ctx);
++			src = tmp2;
++		}
++
++		if (emit_store_r64(dst, src, off, ctx, BPF_SIZE(code),
++				   BPF_MODE(code)))
++			return -1;
++		break;
++
++	/* No hardware support for 8-byte atomics in RV32. */
++	case BPF_STX | BPF_XADD | BPF_DW:
++		/* Fallthrough. */
++
++notsupported:
++		pr_info_once("bpf-jit: not supported: opcode %02x ***\n", code);
++		return -EFAULT;
++
++	default:
++		pr_err("bpf-jit: unknown opcode %02x\n", code);
++		return -EINVAL;
++	}
++
++	return 0;
++}
++
++void bpf_jit_build_prologue(struct rv_jit_context *ctx)
++{
++	/* Make space to save 9 registers: ra, fp, s1--s7. */
++	int stack_adjust = 9 * sizeof(u32), store_offset, bpf_stack_adjust;
++	const s8 *fp = bpf2rv32[BPF_REG_FP];
++	const s8 *r1 = bpf2rv32[BPF_REG_1];
++
++	bpf_stack_adjust = round_up(ctx->prog->aux->stack_depth, 16);
++	stack_adjust += bpf_stack_adjust;
++
++	store_offset = stack_adjust - 4;
++
++	stack_adjust += 4 * BPF_JIT_SCRATCH_REGS;
++
++	/*
++	 * The first instruction sets the tail-call-counter (TCC) register.
++	 * This instruction is skipped by tail calls.
++	 */
++	emit(rv_addi(RV_REG_TCC, RV_REG_ZERO, MAX_TAIL_CALL_CNT), ctx);
++
++	emit(rv_addi(RV_REG_SP, RV_REG_SP, -stack_adjust), ctx);
++
++	/* Save callee-save registers. */
++	emit(rv_sw(RV_REG_SP, store_offset - 0, RV_REG_RA), ctx);
++	emit(rv_sw(RV_REG_SP, store_offset - 4, RV_REG_FP), ctx);
++	emit(rv_sw(RV_REG_SP, store_offset - 8, RV_REG_S1), ctx);
++	emit(rv_sw(RV_REG_SP, store_offset - 12, RV_REG_S2), ctx);
++	emit(rv_sw(RV_REG_SP, store_offset - 16, RV_REG_S3), ctx);
++	emit(rv_sw(RV_REG_SP, store_offset - 20, RV_REG_S4), ctx);
++	emit(rv_sw(RV_REG_SP, store_offset - 24, RV_REG_S5), ctx);
++	emit(rv_sw(RV_REG_SP, store_offset - 28, RV_REG_S6), ctx);
++	emit(rv_sw(RV_REG_SP, store_offset - 32, RV_REG_S7), ctx);
++
++	/* Set fp: used as the base address for stacked BPF registers. */
++	emit(rv_addi(RV_REG_FP, RV_REG_SP, stack_adjust), ctx);
++
++	/* Set up BPF stack pointer. */
++	emit(rv_addi(lo(fp), RV_REG_SP, bpf_stack_adjust), ctx);
++	emit(rv_addi(hi(fp), RV_REG_ZERO, 0), ctx);
++
++	/* Set up context pointer. */
++	emit(rv_addi(lo(r1), RV_REG_A0, 0), ctx);
++	emit(rv_addi(hi(r1), RV_REG_ZERO, 0), ctx);
++
++	ctx->stack_size = stack_adjust;
++}
++
++void bpf_jit_build_epilogue(struct rv_jit_context *ctx)
++{
++	__build_epilogue(false, ctx);
++}

commit ca6cb5447ceca6a87d6b62c9e5d41042c34f7ffa
+Author: Luke Nelson 
+Date:   Wed Mar 4 21:02:04 2020 -0800
+
+    riscv, bpf: Factor common RISC-V JIT code
+    
+    This patch factors out code that can be used by both the RV64 and RV32
+    BPF JITs to a common bpf_jit.h and bpf_jit_core.c.
+    
+    Move struct definitions and macro-like functions to header. Rename
+    rv_sb_insn/rv_uj_insn to rv_b_insn/rv_j_insn to match the RISC-V
+    specification.
+    
+    Move reusable functions emit_body() and bpf_int_jit_compile() to
+    bpf_jit_core.c with minor simplifications. Rename emit_insn() and
+    build_{prologue,epilogue}() to be prefixed with "bpf_jit_" as they are
+    no longer static.
+    
+    Rename bpf_jit_comp.c to bpf_jit_comp64.c to be more explicit.
+    
+    Co-developed-by: Xi Wang 
+    Signed-off-by: Xi Wang 
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Daniel Borkmann 
+    Reviewed-by: Björn Töpel 
+    Acked-by: Björn Töpel 
+    Link: https://lore.kernel.org/bpf/20200305050207.4159-2-luke.r.nels@gmail.com
+
+diff --git a/arch/riscv/net/Makefile b/arch/riscv/net/Makefile
+index ec5b14763316..018074dbf986 100644
+--- a/arch/riscv/net/Makefile
++++ b/arch/riscv/net/Makefile
+@@ -1,2 +1,3 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+-obj-$(CONFIG_BPF_JIT) += bpf_jit_comp.o
++
++obj-$(CONFIG_BPF_JIT) += bpf_jit_core.o bpf_jit_comp64.o
+diff --git a/arch/riscv/net/bpf_jit.h b/arch/riscv/net/bpf_jit.h
+new file mode 100644
+index 000000000000..23c123331f94
+--- /dev/null
++++ b/arch/riscv/net/bpf_jit.h
+@@ -0,0 +1,466 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Common functionality for RV32 and RV64 BPF JIT compilers
++ *
++ * Copyright (c) 2019 Björn Töpel 
++ *
++ */
++
++#ifndef _BPF_JIT_H
++#define _BPF_JIT_H
++
++#include 
++#include 
++#include 
++
++enum {
++	RV_REG_ZERO =	0,	/* The constant value 0 */
++	RV_REG_RA =	1,	/* Return address */
++	RV_REG_SP =	2,	/* Stack pointer */
++	RV_REG_GP =	3,	/* Global pointer */
++	RV_REG_TP =	4,	/* Thread pointer */
++	RV_REG_T0 =	5,	/* Temporaries */
++	RV_REG_T1 =	6,
++	RV_REG_T2 =	7,
++	RV_REG_FP =	8,	/* Saved register/frame pointer */
++	RV_REG_S1 =	9,	/* Saved register */
++	RV_REG_A0 =	10,	/* Function argument/return values */
++	RV_REG_A1 =	11,	/* Function arguments */
++	RV_REG_A2 =	12,
++	RV_REG_A3 =	13,
++	RV_REG_A4 =	14,
++	RV_REG_A5 =	15,
++	RV_REG_A6 =	16,
++	RV_REG_A7 =	17,
++	RV_REG_S2 =	18,	/* Saved registers */
++	RV_REG_S3 =	19,
++	RV_REG_S4 =	20,
++	RV_REG_S5 =	21,
++	RV_REG_S6 =	22,
++	RV_REG_S7 =	23,
++	RV_REG_S8 =	24,
++	RV_REG_S9 =	25,
++	RV_REG_S10 =	26,
++	RV_REG_S11 =	27,
++	RV_REG_T3 =	28,	/* Temporaries */
++	RV_REG_T4 =	29,
++	RV_REG_T5 =	30,
++	RV_REG_T6 =	31,
++};
++
++struct rv_jit_context {
++	struct bpf_prog *prog;
++	u32 *insns;		/* RV insns */
++	int ninsns;
++	int epilogue_offset;
++	int *offset;		/* BPF to RV */
++	unsigned long flags;
++	int stack_size;
++};
++
++struct rv_jit_data {
++	struct bpf_binary_header *header;
++	u8 *image;
++	struct rv_jit_context ctx;
++};
++
++static inline void bpf_fill_ill_insns(void *area, unsigned int size)
++{
++	memset(area, 0, size);
++}
++
++static inline void bpf_flush_icache(void *start, void *end)
++{
++	flush_icache_range((unsigned long)start, (unsigned long)end);
++}
++
++static inline void emit(const u32 insn, struct rv_jit_context *ctx)
++{
++	if (ctx->insns)
++		ctx->insns[ctx->ninsns] = insn;
++
++	ctx->ninsns++;
++}
++
++static inline int epilogue_offset(struct rv_jit_context *ctx)
++{
++	int to = ctx->epilogue_offset, from = ctx->ninsns;
++
++	return (to - from) << 2;
++}
++
++/* Return -1 or inverted cond. */
++static inline int invert_bpf_cond(u8 cond)
++{
++	switch (cond) {
++	case BPF_JEQ:
++		return BPF_JNE;
++	case BPF_JGT:
++		return BPF_JLE;
++	case BPF_JLT:
++		return BPF_JGE;
++	case BPF_JGE:
++		return BPF_JLT;
++	case BPF_JLE:
++		return BPF_JGT;
++	case BPF_JNE:
++		return BPF_JEQ;
++	case BPF_JSGT:
++		return BPF_JSLE;
++	case BPF_JSLT:
++		return BPF_JSGE;
++	case BPF_JSGE:
++		return BPF_JSLT;
++	case BPF_JSLE:
++		return BPF_JSGT;
++	}
++	return -1;
++}
++
++static inline bool is_12b_int(long val)
++{
++	return -(1L << 11) <= val && val < (1L << 11);
++}
++
++static inline int is_12b_check(int off, int insn)
++{
++	if (!is_12b_int(off)) {
++		pr_err("bpf-jit: insn=%d 12b < offset=%d not supported yet!\n",
++		       insn, (int)off);
++		return -1;
++	}
++	return 0;
++}
++
++static inline bool is_13b_int(long val)
++{
++	return -(1L << 12) <= val && val < (1L << 12);
++}
++
++static inline bool is_21b_int(long val)
++{
++	return -(1L << 20) <= val && val < (1L << 20);
++}
++
++static inline int rv_offset(int insn, int off, struct rv_jit_context *ctx)
++{
++	int from, to;
++
++	off++; /* BPF branch is from PC+1, RV is from PC */
++	from = (insn > 0) ? ctx->offset[insn - 1] : 0;
++	to = (insn + off > 0) ? ctx->offset[insn + off - 1] : 0;
++	return (to - from) << 2;
++}
++
++/* Instruction formats. */
++
++static inline u32 rv_r_insn(u8 funct7, u8 rs2, u8 rs1, u8 funct3, u8 rd,
++			    u8 opcode)
++{
++	return (funct7 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) |
++		(rd << 7) | opcode;
++}
++
++static inline u32 rv_i_insn(u16 imm11_0, u8 rs1, u8 funct3, u8 rd, u8 opcode)
++{
++	return (imm11_0 << 20) | (rs1 << 15) | (funct3 << 12) | (rd << 7) |
++		opcode;
++}
++
++static inline u32 rv_s_insn(u16 imm11_0, u8 rs2, u8 rs1, u8 funct3, u8 opcode)
++{
++	u8 imm11_5 = imm11_0 >> 5, imm4_0 = imm11_0 & 0x1f;
++
++	return (imm11_5 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) |
++		(imm4_0 << 7) | opcode;
++}
++
++static inline u32 rv_b_insn(u16 imm12_1, u8 rs2, u8 rs1, u8 funct3, u8 opcode)
++{
++	u8 imm12 = ((imm12_1 & 0x800) >> 5) | ((imm12_1 & 0x3f0) >> 4);
++	u8 imm4_1 = ((imm12_1 & 0xf) << 1) | ((imm12_1 & 0x400) >> 10);
++
++	return (imm12 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) |
++		(imm4_1 << 7) | opcode;
++}
++
++static inline u32 rv_u_insn(u32 imm31_12, u8 rd, u8 opcode)
++{
++	return (imm31_12 << 12) | (rd << 7) | opcode;
++}
++
++static inline u32 rv_j_insn(u32 imm20_1, u8 rd, u8 opcode)
++{
++	u32 imm;
++
++	imm = (imm20_1 & 0x80000) | ((imm20_1 & 0x3ff) << 9) |
++		((imm20_1 & 0x400) >> 2) | ((imm20_1 & 0x7f800) >> 11);
++
++	return (imm << 12) | (rd << 7) | opcode;
++}
++
++static inline u32 rv_amo_insn(u8 funct5, u8 aq, u8 rl, u8 rs2, u8 rs1,
++			      u8 funct3, u8 rd, u8 opcode)
++{
++	u8 funct7 = (funct5 << 2) | (aq << 1) | rl;
++
++	return rv_r_insn(funct7, rs2, rs1, funct3, rd, opcode);
++}
++
++static inline u32 rv_addi(u8 rd, u8 rs1, u16 imm11_0)
++{
++	return rv_i_insn(imm11_0, rs1, 0, rd, 0x13);
++}
++
++static inline u32 rv_andi(u8 rd, u8 rs1, u16 imm11_0)
++{
++	return rv_i_insn(imm11_0, rs1, 7, rd, 0x13);
++}
++
++static inline u32 rv_ori(u8 rd, u8 rs1, u16 imm11_0)
++{
++	return rv_i_insn(imm11_0, rs1, 6, rd, 0x13);
++}
++
++static inline u32 rv_xori(u8 rd, u8 rs1, u16 imm11_0)
++{
++	return rv_i_insn(imm11_0, rs1, 4, rd, 0x13);
++}
++
++static inline u32 rv_slli(u8 rd, u8 rs1, u16 imm11_0)
++{
++	return rv_i_insn(imm11_0, rs1, 1, rd, 0x13);
++}
++
++static inline u32 rv_srli(u8 rd, u8 rs1, u16 imm11_0)
++{
++	return rv_i_insn(imm11_0, rs1, 5, rd, 0x13);
++}
++
++static inline u32 rv_srai(u8 rd, u8 rs1, u16 imm11_0)
++{
++	return rv_i_insn(0x400 | imm11_0, rs1, 5, rd, 0x13);
++}
++
++static inline u32 rv_lui(u8 rd, u32 imm31_12)
++{
++	return rv_u_insn(imm31_12, rd, 0x37);
++}
++
++static inline u32 rv_auipc(u8 rd, u32 imm31_12)
++{
++	return rv_u_insn(imm31_12, rd, 0x17);
++}
++
++static inline u32 rv_add(u8 rd, u8 rs1, u8 rs2)
++{
++	return rv_r_insn(0, rs2, rs1, 0, rd, 0x33);
++}
++
++static inline u32 rv_sub(u8 rd, u8 rs1, u8 rs2)
++{
++	return rv_r_insn(0x20, rs2, rs1, 0, rd, 0x33);
++}
++
++static inline u32 rv_and(u8 rd, u8 rs1, u8 rs2)
++{
++	return rv_r_insn(0, rs2, rs1, 7, rd, 0x33);
++}
++
++static inline u32 rv_or(u8 rd, u8 rs1, u8 rs2)
++{
++	return rv_r_insn(0, rs2, rs1, 6, rd, 0x33);
++}
++
++static inline u32 rv_xor(u8 rd, u8 rs1, u8 rs2)
++{
++	return rv_r_insn(0, rs2, rs1, 4, rd, 0x33);
++}
++
++static inline u32 rv_sll(u8 rd, u8 rs1, u8 rs2)
++{
++	return rv_r_insn(0, rs2, rs1, 1, rd, 0x33);
++}
++
++static inline u32 rv_srl(u8 rd, u8 rs1, u8 rs2)
++{
++	return rv_r_insn(0, rs2, rs1, 5, rd, 0x33);
++}
++
++static inline u32 rv_sra(u8 rd, u8 rs1, u8 rs2)
++{
++	return rv_r_insn(0x20, rs2, rs1, 5, rd, 0x33);
++}
++
++static inline u32 rv_mul(u8 rd, u8 rs1, u8 rs2)
++{
++	return rv_r_insn(1, rs2, rs1, 0, rd, 0x33);
++}
++
++static inline u32 rv_divu(u8 rd, u8 rs1, u8 rs2)
++{
++	return rv_r_insn(1, rs2, rs1, 5, rd, 0x33);
++}
++
++static inline u32 rv_remu(u8 rd, u8 rs1, u8 rs2)
++{
++	return rv_r_insn(1, rs2, rs1, 7, rd, 0x33);
++}
++
++static inline u32 rv_jal(u8 rd, u32 imm20_1)
++{
++	return rv_j_insn(imm20_1, rd, 0x6f);
++}
++
++static inline u32 rv_jalr(u8 rd, u8 rs1, u16 imm11_0)
++{
++	return rv_i_insn(imm11_0, rs1, 0, rd, 0x67);
++}
++
++static inline u32 rv_beq(u8 rs1, u8 rs2, u16 imm12_1)
++{
++	return rv_b_insn(imm12_1, rs2, rs1, 0, 0x63);
++}
++
++static inline u32 rv_bne(u8 rs1, u8 rs2, u16 imm12_1)
++{
++	return rv_b_insn(imm12_1, rs2, rs1, 1, 0x63);
++}
++
++static inline u32 rv_bltu(u8 rs1, u8 rs2, u16 imm12_1)
++{
++	return rv_b_insn(imm12_1, rs2, rs1, 6, 0x63);
++}
++
++static inline u32 rv_bgeu(u8 rs1, u8 rs2, u16 imm12_1)
++{
++	return rv_b_insn(imm12_1, rs2, rs1, 7, 0x63);
++}
++
++static inline u32 rv_blt(u8 rs1, u8 rs2, u16 imm12_1)
++{
++	return rv_b_insn(imm12_1, rs2, rs1, 4, 0x63);
++}
++
++static inline u32 rv_bge(u8 rs1, u8 rs2, u16 imm12_1)
++{
++	return rv_b_insn(imm12_1, rs2, rs1, 5, 0x63);
++}
++
++static inline u32 rv_lbu(u8 rd, u16 imm11_0, u8 rs1)
++{
++	return rv_i_insn(imm11_0, rs1, 4, rd, 0x03);
++}
++
++static inline u32 rv_lhu(u8 rd, u16 imm11_0, u8 rs1)
++{
++	return rv_i_insn(imm11_0, rs1, 5, rd, 0x03);
++}
++
++static inline u32 rv_sb(u8 rs1, u16 imm11_0, u8 rs2)
++{
++	return rv_s_insn(imm11_0, rs2, rs1, 0, 0x23);
++}
++
++static inline u32 rv_sh(u8 rs1, u16 imm11_0, u8 rs2)
++{
++	return rv_s_insn(imm11_0, rs2, rs1, 1, 0x23);
++}
++
++static inline u32 rv_sw(u8 rs1, u16 imm11_0, u8 rs2)
++{
++	return rv_s_insn(imm11_0, rs2, rs1, 2, 0x23);
++}
++
++static inline u32 rv_amoadd_w(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
++{
++	return rv_amo_insn(0, aq, rl, rs2, rs1, 2, rd, 0x2f);
++}
++
++static inline u32 rv_addiw(u8 rd, u8 rs1, u16 imm11_0)
++{
++	return rv_i_insn(imm11_0, rs1, 0, rd, 0x1b);
++}
++
++static inline u32 rv_slliw(u8 rd, u8 rs1, u16 imm11_0)
++{
++	return rv_i_insn(imm11_0, rs1, 1, rd, 0x1b);
++}
++
++static inline u32 rv_srliw(u8 rd, u8 rs1, u16 imm11_0)
++{
++	return rv_i_insn(imm11_0, rs1, 5, rd, 0x1b);
++}
++
++static inline u32 rv_sraiw(u8 rd, u8 rs1, u16 imm11_0)
++{
++	return rv_i_insn(0x400 | imm11_0, rs1, 5, rd, 0x1b);
++}
++
++static inline u32 rv_addw(u8 rd, u8 rs1, u8 rs2)
++{
++	return rv_r_insn(0, rs2, rs1, 0, rd, 0x3b);
++}
++
++static inline u32 rv_subw(u8 rd, u8 rs1, u8 rs2)
++{
++	return rv_r_insn(0x20, rs2, rs1, 0, rd, 0x3b);
++}
++
++static inline u32 rv_sllw(u8 rd, u8 rs1, u8 rs2)
++{
++	return rv_r_insn(0, rs2, rs1, 1, rd, 0x3b);
++}
++
++static inline u32 rv_srlw(u8 rd, u8 rs1, u8 rs2)
++{
++	return rv_r_insn(0, rs2, rs1, 5, rd, 0x3b);
++}
++
++static inline u32 rv_sraw(u8 rd, u8 rs1, u8 rs2)
++{
++	return rv_r_insn(0x20, rs2, rs1, 5, rd, 0x3b);
++}
++
++static inline u32 rv_mulw(u8 rd, u8 rs1, u8 rs2)
++{
++	return rv_r_insn(1, rs2, rs1, 0, rd, 0x3b);
++}
++
++static inline u32 rv_divuw(u8 rd, u8 rs1, u8 rs2)
++{
++	return rv_r_insn(1, rs2, rs1, 5, rd, 0x3b);
++}
++
++static inline u32 rv_remuw(u8 rd, u8 rs1, u8 rs2)
++{
++	return rv_r_insn(1, rs2, rs1, 7, rd, 0x3b);
++}
++
++static inline u32 rv_ld(u8 rd, u16 imm11_0, u8 rs1)
++{
++	return rv_i_insn(imm11_0, rs1, 3, rd, 0x03);
++}
++
++static inline u32 rv_lwu(u8 rd, u16 imm11_0, u8 rs1)
++{
++	return rv_i_insn(imm11_0, rs1, 6, rd, 0x03);
++}
++
++static inline u32 rv_sd(u8 rs1, u16 imm11_0, u8 rs2)
++{
++	return rv_s_insn(imm11_0, rs2, rs1, 3, 0x23);
++}
++
++static inline u32 rv_amoadd_d(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
++{
++	return rv_amo_insn(0, aq, rl, rs2, rs1, 3, rd, 0x2f);
++}
++
++void bpf_jit_build_prologue(struct rv_jit_context *ctx);
++void bpf_jit_build_epilogue(struct rv_jit_context *ctx);
++
++int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
++		      bool extra_pass);
++
++#endif /* _BPF_JIT_H */
+diff --git a/arch/riscv/net/bpf_jit_comp.c b/arch/riscv/net/bpf_jit_comp64.c
+similarity index 69%
+rename from arch/riscv/net/bpf_jit_comp.c
+rename to arch/riscv/net/bpf_jit_comp64.c
+index 483f4ad7f4dc..cc1985d8750a 100644
+--- a/arch/riscv/net/bpf_jit_comp.c
++++ b/arch/riscv/net/bpf_jit_comp64.c
+@@ -7,42 +7,7 @@
+ 
+ #include 
+ #include 
+-#include 
+-
+-enum {
+-	RV_REG_ZERO =	0,	/* The constant value 0 */
+-	RV_REG_RA =	1,	/* Return address */
+-	RV_REG_SP =	2,	/* Stack pointer */
+-	RV_REG_GP =	3,	/* Global pointer */
+-	RV_REG_TP =	4,	/* Thread pointer */
+-	RV_REG_T0 =	5,	/* Temporaries */
+-	RV_REG_T1 =	6,
+-	RV_REG_T2 =	7,
+-	RV_REG_FP =	8,
+-	RV_REG_S1 =	9,	/* Saved registers */
+-	RV_REG_A0 =	10,	/* Function argument/return values */
+-	RV_REG_A1 =	11,	/* Function arguments */
+-	RV_REG_A2 =	12,
+-	RV_REG_A3 =	13,
+-	RV_REG_A4 =	14,
+-	RV_REG_A5 =	15,
+-	RV_REG_A6 =	16,
+-	RV_REG_A7 =	17,
+-	RV_REG_S2 =	18,	/* Saved registers */
+-	RV_REG_S3 =	19,
+-	RV_REG_S4 =	20,
+-	RV_REG_S5 =	21,
+-	RV_REG_S6 =	22,
+-	RV_REG_S7 =	23,
+-	RV_REG_S8 =	24,
+-	RV_REG_S9 =	25,
+-	RV_REG_S10 =	26,
+-	RV_REG_S11 =	27,
+-	RV_REG_T3 =	28,	/* Temporaries */
+-	RV_REG_T4 =	29,
+-	RV_REG_T5 =	30,
+-	RV_REG_T6 =	31,
+-};
++#include "bpf_jit.h"
+ 
+ #define RV_REG_TCC RV_REG_A6
+ #define RV_REG_TCC_SAVED RV_REG_S6 /* Store A6 in S6 if program do calls */
+@@ -73,22 +38,6 @@ enum {
+ 	RV_CTX_F_SEEN_S6 =		RV_REG_S6,
+ };
+ 
+-struct rv_jit_context {
+-	struct bpf_prog *prog;
+-	u32 *insns; /* RV insns */
+-	int ninsns;
+-	int epilogue_offset;
+-	int *offset; /* BPF to RV */
+-	unsigned long flags;
+-	int stack_size;
+-};
+-
+-struct rv_jit_data {
+-	struct bpf_binary_header *header;
+-	u8 *image;
+-	struct rv_jit_context ctx;
+-};
+-
+ static u8 bpf_to_rv_reg(int bpf_reg, struct rv_jit_context *ctx)
+ {
+ 	u8 reg = regmap[bpf_reg];
+@@ -156,346 +105,11 @@ static u8 rv_tail_call_reg(struct rv_jit_context *ctx)
+ 	return RV_REG_A6;
+ }
+ 
+-static void emit(const u32 insn, struct rv_jit_context *ctx)
+-{
+-	if (ctx->insns)
+-		ctx->insns[ctx->ninsns] = insn;
+-
+-	ctx->ninsns++;
+-}
+-
+-static u32 rv_r_insn(u8 funct7, u8 rs2, u8 rs1, u8 funct3, u8 rd, u8 opcode)
+-{
+-	return (funct7 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) |
+-		(rd << 7) | opcode;
+-}
+-
+-static u32 rv_i_insn(u16 imm11_0, u8 rs1, u8 funct3, u8 rd, u8 opcode)
+-{
+-	return (imm11_0 << 20) | (rs1 << 15) | (funct3 << 12) | (rd << 7) |
+-		opcode;
+-}
+-
+-static u32 rv_s_insn(u16 imm11_0, u8 rs2, u8 rs1, u8 funct3, u8 opcode)
+-{
+-	u8 imm11_5 = imm11_0 >> 5, imm4_0 = imm11_0 & 0x1f;
+-
+-	return (imm11_5 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) |
+-		(imm4_0 << 7) | opcode;
+-}
+-
+-static u32 rv_sb_insn(u16 imm12_1, u8 rs2, u8 rs1, u8 funct3, u8 opcode)
+-{
+-	u8 imm12 = ((imm12_1 & 0x800) >> 5) | ((imm12_1 & 0x3f0) >> 4);
+-	u8 imm4_1 = ((imm12_1 & 0xf) << 1) | ((imm12_1 & 0x400) >> 10);
+-
+-	return (imm12 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) |
+-		(imm4_1 << 7) | opcode;
+-}
+-
+-static u32 rv_u_insn(u32 imm31_12, u8 rd, u8 opcode)
+-{
+-	return (imm31_12 << 12) | (rd << 7) | opcode;
+-}
+-
+-static u32 rv_uj_insn(u32 imm20_1, u8 rd, u8 opcode)
+-{
+-	u32 imm;
+-
+-	imm = (imm20_1 & 0x80000) |  ((imm20_1 & 0x3ff) << 9) |
+-	      ((imm20_1 & 0x400) >> 2) | ((imm20_1 & 0x7f800) >> 11);
+-
+-	return (imm << 12) | (rd << 7) | opcode;
+-}
+-
+-static u32 rv_amo_insn(u8 funct5, u8 aq, u8 rl, u8 rs2, u8 rs1,
+-		       u8 funct3, u8 rd, u8 opcode)
+-{
+-	u8 funct7 = (funct5 << 2) | (aq << 1) | rl;
+-
+-	return rv_r_insn(funct7, rs2, rs1, funct3, rd, opcode);
+-}
+-
+-static u32 rv_addiw(u8 rd, u8 rs1, u16 imm11_0)
+-{
+-	return rv_i_insn(imm11_0, rs1, 0, rd, 0x1b);
+-}
+-
+-static u32 rv_addi(u8 rd, u8 rs1, u16 imm11_0)
+-{
+-	return rv_i_insn(imm11_0, rs1, 0, rd, 0x13);
+-}
+-
+-static u32 rv_addw(u8 rd, u8 rs1, u8 rs2)
+-{
+-	return rv_r_insn(0, rs2, rs1, 0, rd, 0x3b);
+-}
+-
+-static u32 rv_add(u8 rd, u8 rs1, u8 rs2)
+-{
+-	return rv_r_insn(0, rs2, rs1, 0, rd, 0x33);
+-}
+-
+-static u32 rv_subw(u8 rd, u8 rs1, u8 rs2)
+-{
+-	return rv_r_insn(0x20, rs2, rs1, 0, rd, 0x3b);
+-}
+-
+-static u32 rv_sub(u8 rd, u8 rs1, u8 rs2)
+-{
+-	return rv_r_insn(0x20, rs2, rs1, 0, rd, 0x33);
+-}
+-
+-static u32 rv_and(u8 rd, u8 rs1, u8 rs2)
+-{
+-	return rv_r_insn(0, rs2, rs1, 7, rd, 0x33);
+-}
+-
+-static u32 rv_or(u8 rd, u8 rs1, u8 rs2)
+-{
+-	return rv_r_insn(0, rs2, rs1, 6, rd, 0x33);
+-}
+-
+-static u32 rv_xor(u8 rd, u8 rs1, u8 rs2)
+-{
+-	return rv_r_insn(0, rs2, rs1, 4, rd, 0x33);
+-}
+-
+-static u32 rv_mulw(u8 rd, u8 rs1, u8 rs2)
+-{
+-	return rv_r_insn(1, rs2, rs1, 0, rd, 0x3b);
+-}
+-
+-static u32 rv_mul(u8 rd, u8 rs1, u8 rs2)
+-{
+-	return rv_r_insn(1, rs2, rs1, 0, rd, 0x33);
+-}
+-
+-static u32 rv_divuw(u8 rd, u8 rs1, u8 rs2)
+-{
+-	return rv_r_insn(1, rs2, rs1, 5, rd, 0x3b);
+-}
+-
+-static u32 rv_divu(u8 rd, u8 rs1, u8 rs2)
+-{
+-	return rv_r_insn(1, rs2, rs1, 5, rd, 0x33);
+-}
+-
+-static u32 rv_remuw(u8 rd, u8 rs1, u8 rs2)
+-{
+-	return rv_r_insn(1, rs2, rs1, 7, rd, 0x3b);
+-}
+-
+-static u32 rv_remu(u8 rd, u8 rs1, u8 rs2)
+-{
+-	return rv_r_insn(1, rs2, rs1, 7, rd, 0x33);
+-}
+-
+-static u32 rv_sllw(u8 rd, u8 rs1, u8 rs2)
+-{
+-	return rv_r_insn(0, rs2, rs1, 1, rd, 0x3b);
+-}
+-
+-static u32 rv_sll(u8 rd, u8 rs1, u8 rs2)
+-{
+-	return rv_r_insn(0, rs2, rs1, 1, rd, 0x33);
+-}
+-
+-static u32 rv_srlw(u8 rd, u8 rs1, u8 rs2)
+-{
+-	return rv_r_insn(0, rs2, rs1, 5, rd, 0x3b);
+-}
+-
+-static u32 rv_srl(u8 rd, u8 rs1, u8 rs2)
+-{
+-	return rv_r_insn(0, rs2, rs1, 5, rd, 0x33);
+-}
+-
+-static u32 rv_sraw(u8 rd, u8 rs1, u8 rs2)
+-{
+-	return rv_r_insn(0x20, rs2, rs1, 5, rd, 0x3b);
+-}
+-
+-static u32 rv_sra(u8 rd, u8 rs1, u8 rs2)
+-{
+-	return rv_r_insn(0x20, rs2, rs1, 5, rd, 0x33);
+-}
+-
+-static u32 rv_lui(u8 rd, u32 imm31_12)
+-{
+-	return rv_u_insn(imm31_12, rd, 0x37);
+-}
+-
+-static u32 rv_slli(u8 rd, u8 rs1, u16 imm11_0)
+-{
+-	return rv_i_insn(imm11_0, rs1, 1, rd, 0x13);
+-}
+-
+-static u32 rv_andi(u8 rd, u8 rs1, u16 imm11_0)
+-{
+-	return rv_i_insn(imm11_0, rs1, 7, rd, 0x13);
+-}
+-
+-static u32 rv_ori(u8 rd, u8 rs1, u16 imm11_0)
+-{
+-	return rv_i_insn(imm11_0, rs1, 6, rd, 0x13);
+-}
+-
+-static u32 rv_xori(u8 rd, u8 rs1, u16 imm11_0)
+-{
+-	return rv_i_insn(imm11_0, rs1, 4, rd, 0x13);
+-}
+-
+-static u32 rv_slliw(u8 rd, u8 rs1, u16 imm11_0)
+-{
+-	return rv_i_insn(imm11_0, rs1, 1, rd, 0x1b);
+-}
+-
+-static u32 rv_srliw(u8 rd, u8 rs1, u16 imm11_0)
+-{
+-	return rv_i_insn(imm11_0, rs1, 5, rd, 0x1b);
+-}
+-
+-static u32 rv_srli(u8 rd, u8 rs1, u16 imm11_0)
+-{
+-	return rv_i_insn(imm11_0, rs1, 5, rd, 0x13);
+-}
+-
+-static u32 rv_sraiw(u8 rd, u8 rs1, u16 imm11_0)
+-{
+-	return rv_i_insn(0x400 | imm11_0, rs1, 5, rd, 0x1b);
+-}
+-
+-static u32 rv_srai(u8 rd, u8 rs1, u16 imm11_0)
+-{
+-	return rv_i_insn(0x400 | imm11_0, rs1, 5, rd, 0x13);
+-}
+-
+-static u32 rv_jal(u8 rd, u32 imm20_1)
+-{
+-	return rv_uj_insn(imm20_1, rd, 0x6f);
+-}
+-
+-static u32 rv_jalr(u8 rd, u8 rs1, u16 imm11_0)
+-{
+-	return rv_i_insn(imm11_0, rs1, 0, rd, 0x67);
+-}
+-
+-static u32 rv_beq(u8 rs1, u8 rs2, u16 imm12_1)
+-{
+-	return rv_sb_insn(imm12_1, rs2, rs1, 0, 0x63);
+-}
+-
+-static u32 rv_bltu(u8 rs1, u8 rs2, u16 imm12_1)
+-{
+-	return rv_sb_insn(imm12_1, rs2, rs1, 6, 0x63);
+-}
+-
+-static u32 rv_bgeu(u8 rs1, u8 rs2, u16 imm12_1)
+-{
+-	return rv_sb_insn(imm12_1, rs2, rs1, 7, 0x63);
+-}
+-
+-static u32 rv_bne(u8 rs1, u8 rs2, u16 imm12_1)
+-{
+-	return rv_sb_insn(imm12_1, rs2, rs1, 1, 0x63);
+-}
+-
+-static u32 rv_blt(u8 rs1, u8 rs2, u16 imm12_1)
+-{
+-	return rv_sb_insn(imm12_1, rs2, rs1, 4, 0x63);
+-}
+-
+-static u32 rv_bge(u8 rs1, u8 rs2, u16 imm12_1)
+-{
+-	return rv_sb_insn(imm12_1, rs2, rs1, 5, 0x63);
+-}
+-
+-static u32 rv_sb(u8 rs1, u16 imm11_0, u8 rs2)
+-{
+-	return rv_s_insn(imm11_0, rs2, rs1, 0, 0x23);
+-}
+-
+-static u32 rv_sh(u8 rs1, u16 imm11_0, u8 rs2)
+-{
+-	return rv_s_insn(imm11_0, rs2, rs1, 1, 0x23);
+-}
+-
+-static u32 rv_sw(u8 rs1, u16 imm11_0, u8 rs2)
+-{
+-	return rv_s_insn(imm11_0, rs2, rs1, 2, 0x23);
+-}
+-
+-static u32 rv_sd(u8 rs1, u16 imm11_0, u8 rs2)
+-{
+-	return rv_s_insn(imm11_0, rs2, rs1, 3, 0x23);
+-}
+-
+-static u32 rv_lbu(u8 rd, u16 imm11_0, u8 rs1)
+-{
+-	return rv_i_insn(imm11_0, rs1, 4, rd, 0x03);
+-}
+-
+-static u32 rv_lhu(u8 rd, u16 imm11_0, u8 rs1)
+-{
+-	return rv_i_insn(imm11_0, rs1, 5, rd, 0x03);
+-}
+-
+-static u32 rv_lwu(u8 rd, u16 imm11_0, u8 rs1)
+-{
+-	return rv_i_insn(imm11_0, rs1, 6, rd, 0x03);
+-}
+-
+-static u32 rv_ld(u8 rd, u16 imm11_0, u8 rs1)
+-{
+-	return rv_i_insn(imm11_0, rs1, 3, rd, 0x03);
+-}
+-
+-static u32 rv_amoadd_w(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
+-{
+-	return rv_amo_insn(0, aq, rl, rs2, rs1, 2, rd, 0x2f);
+-}
+-
+-static u32 rv_amoadd_d(u8 rd, u8 rs2, u8 rs1, u8 aq, u8 rl)
+-{
+-	return rv_amo_insn(0, aq, rl, rs2, rs1, 3, rd, 0x2f);
+-}
+-
+-static u32 rv_auipc(u8 rd, u32 imm31_12)
+-{
+-	return rv_u_insn(imm31_12, rd, 0x17);
+-}
+-
+-static bool is_12b_int(s64 val)
+-{
+-	return -(1 << 11) <= val && val < (1 << 11);
+-}
+-
+-static bool is_13b_int(s64 val)
+-{
+-	return -(1 << 12) <= val && val < (1 << 12);
+-}
+-
+-static bool is_21b_int(s64 val)
+-{
+-	return -(1L << 20) <= val && val < (1L << 20);
+-}
+-
+ static bool is_32b_int(s64 val)
+ {
+ 	return -(1L << 31) <= val && val < (1L << 31);
+ }
+ 
+-static int is_12b_check(int off, int insn)
+-{
+-	if (!is_12b_int(off)) {
+-		pr_err("bpf-jit: insn=%d 12b < offset=%d not supported yet!\n",
+-		       insn, (int)off);
+-		return -1;
+-	}
+-	return 0;
+-}
+-
+ static void emit_imm(u8 rd, s64 val, struct rv_jit_context *ctx)
+ {
+ 	/* Note that the immediate from the add is sign-extended,
+@@ -535,23 +149,6 @@ static void emit_imm(u8 rd, s64 val, struct rv_jit_context *ctx)
+ 		emit(rv_addi(rd, rd, lower), ctx);
+ }
+ 
+-static int rv_offset(int insn, int off, struct rv_jit_context *ctx)
+-{
+-	int from, to;
+-
+-	off++; /* BPF branch is from PC+1, RV is from PC */
+-	from = (insn > 0) ? ctx->offset[insn - 1] : 0;
+-	to = (insn + off > 0) ? ctx->offset[insn + off - 1] : 0;
+-	return (to - from) << 2;
+-}
+-
+-static int epilogue_offset(struct rv_jit_context *ctx)
+-{
+-	int to = ctx->epilogue_offset, from = ctx->ninsns;
+-
+-	return (to - from) << 2;
+-}
+-
+ static void __build_epilogue(bool is_tail_call, struct rv_jit_context *ctx)
+ {
+ 	int stack_adjust = ctx->stack_size, store_offset = stack_adjust - 8;
+@@ -596,34 +193,6 @@ static void __build_epilogue(bool is_tail_call, struct rv_jit_context *ctx)
+ 	     ctx);
+ }
+ 
+-/* return -1 or inverted cond */
+-static int invert_bpf_cond(u8 cond)
+-{
+-	switch (cond) {
+-	case BPF_JEQ:
+-		return BPF_JNE;
+-	case BPF_JGT:
+-		return BPF_JLE;
+-	case BPF_JLT:
+-		return BPF_JGE;
+-	case BPF_JGE:
+-		return BPF_JLT;
+-	case BPF_JLE:
+-		return BPF_JGT;
+-	case BPF_JNE:
+-		return BPF_JEQ;
+-	case BPF_JSGT:
+-		return BPF_JSLE;
+-	case BPF_JSLT:
+-		return BPF_JSGE;
+-	case BPF_JSGE:
+-		return BPF_JSLT;
+-	case BPF_JSLE:
+-		return BPF_JSGT;
+-	}
+-	return -1;
+-}
+-
+ static void emit_bcc(u8 cond, u8 rd, u8 rs, int rvoff,
+ 		     struct rv_jit_context *ctx)
+ {
+@@ -855,8 +424,8 @@ static int emit_call(bool fixed, u64 addr, struct rv_jit_context *ctx)
+ 	return 0;
+ }
+ 
+-static int emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+-		     bool extra_pass)
++int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
++		      bool extra_pass)
+ {
+ 	bool is64 = BPF_CLASS(insn->code) == BPF_ALU64 ||
+ 		    BPF_CLASS(insn->code) == BPF_JMP;
+@@ -1434,7 +1003,7 @@ static int emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 	return 0;
+ }
+ 
+-static void build_prologue(struct rv_jit_context *ctx)
++void bpf_jit_build_prologue(struct rv_jit_context *ctx)
+ {
+ 	int stack_adjust = 0, store_offset, bpf_stack_adjust;
+ 
+@@ -1515,175 +1084,11 @@ static void build_prologue(struct rv_jit_context *ctx)
+ 	ctx->stack_size = stack_adjust;
+ }
+ 
+-static void build_epilogue(struct rv_jit_context *ctx)
++void bpf_jit_build_epilogue(struct rv_jit_context *ctx)
+ {
+ 	__build_epilogue(false, ctx);
+ }
+ 
+-static int build_body(struct rv_jit_context *ctx, bool extra_pass, int *offset)
+-{
+-	const struct bpf_prog *prog = ctx->prog;
+-	int i;
+-
+-	for (i = 0; i < prog->len; i++) {
+-		const struct bpf_insn *insn = &prog->insnsi[i];
+-		int ret;
+-
+-		ret = emit_insn(insn, ctx, extra_pass);
+-		if (ret > 0) {
+-			i++;
+-			if (offset)
+-				offset[i] = ctx->ninsns;
+-			continue;
+-		}
+-		if (offset)
+-			offset[i] = ctx->ninsns;
+-		if (ret)
+-			return ret;
+-	}
+-	return 0;
+-}
+-
+-static void bpf_fill_ill_insns(void *area, unsigned int size)
+-{
+-	memset(area, 0, size);
+-}
+-
+-static void bpf_flush_icache(void *start, void *end)
+-{
+-	flush_icache_range((unsigned long)start, (unsigned long)end);
+-}
+-
+-bool bpf_jit_needs_zext(void)
+-{
+-	return true;
+-}
+-
+-struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
+-{
+-	bool tmp_blinded = false, extra_pass = false;
+-	struct bpf_prog *tmp, *orig_prog = prog;
+-	int pass = 0, prev_ninsns = 0, i;
+-	struct rv_jit_data *jit_data;
+-	unsigned int image_size = 0;
+-	struct rv_jit_context *ctx;
+-
+-	if (!prog->jit_requested)
+-		return orig_prog;
+-
+-	tmp = bpf_jit_blind_constants(prog);
+-	if (IS_ERR(tmp))
+-		return orig_prog;
+-	if (tmp != prog) {
+-		tmp_blinded = true;
+-		prog = tmp;
+-	}
+-
+-	jit_data = prog->aux->jit_data;
+-	if (!jit_data) {
+-		jit_data = kzalloc(sizeof(*jit_data), GFP_KERNEL);
+-		if (!jit_data) {
+-			prog = orig_prog;
+-			goto out;
+-		}
+-		prog->aux->jit_data = jit_data;
+-	}
+-
+-	ctx = &jit_data->ctx;
+-
+-	if (ctx->offset) {
+-		extra_pass = true;
+-		image_size = sizeof(u32) * ctx->ninsns;
+-		goto skip_init_ctx;
+-	}
+-
+-	ctx->prog = prog;
+-	ctx->offset = kcalloc(prog->len, sizeof(int), GFP_KERNEL);
+-	if (!ctx->offset) {
+-		prog = orig_prog;
+-		goto out_offset;
+-	}
+-	for (i = 0; i < prog->len; i++) {
+-		prev_ninsns += 32;
+-		ctx->offset[i] = prev_ninsns;
+-	}
+-
+-	for (i = 0; i < 16; i++) {
+-		pass++;
+-		ctx->ninsns = 0;
+-		if (build_body(ctx, extra_pass, ctx->offset)) {
+-			prog = orig_prog;
+-			goto out_offset;
+-		}
+-		build_prologue(ctx);
+-		ctx->epilogue_offset = ctx->ninsns;
+-		build_epilogue(ctx);
+-
+-		if (ctx->ninsns == prev_ninsns) {
+-			if (jit_data->header)
+-				break;
+-
+-			image_size = sizeof(u32) * ctx->ninsns;
+-			jit_data->header =
+-				bpf_jit_binary_alloc(image_size,
+-						     &jit_data->image,
+-						     sizeof(u32),
+-						     bpf_fill_ill_insns);
+-			if (!jit_data->header) {
+-				prog = orig_prog;
+-				goto out_offset;
+-			}
+-
+-			ctx->insns = (u32 *)jit_data->image;
+-			/* Now, when the image is allocated, the image
+-			 * can potentially shrink more (auipc/jalr ->
+-			 * jal).
+-			 */
+-		}
+-		prev_ninsns = ctx->ninsns;
+-	}
+-
+-	if (i == 16) {
+-		pr_err("bpf-jit: image did not converge in <%d passes!\n", i);
+-		bpf_jit_binary_free(jit_data->header);
+-		prog = orig_prog;
+-		goto out_offset;
+-	}
+-
+-skip_init_ctx:
+-	pass++;
+-	ctx->ninsns = 0;
+-
+-	build_prologue(ctx);
+-	if (build_body(ctx, extra_pass, NULL)) {
+-		bpf_jit_binary_free(jit_data->header);
+-		prog = orig_prog;
+-		goto out_offset;
+-	}
+-	build_epilogue(ctx);
+-
+-	if (bpf_jit_enable > 1)
+-		bpf_jit_dump(prog->len, image_size, pass, ctx->insns);
+-
+-	prog->bpf_func = (void *)ctx->insns;
+-	prog->jited = 1;
+-	prog->jited_len = image_size;
+-
+-	bpf_flush_icache(jit_data->header, ctx->insns + ctx->ninsns);
+-
+-	if (!prog->is_func || extra_pass) {
+-out_offset:
+-		kfree(ctx->offset);
+-		kfree(jit_data);
+-		prog->aux->jit_data = NULL;
+-	}
+-out:
+-	if (tmp_blinded)
+-		bpf_jit_prog_release_other(prog, prog == orig_prog ?
+-					   tmp : orig_prog);
+-	return prog;
+-}
+-
+ void *bpf_jit_alloc_exec(unsigned long size)
+ {
+ 	return __vmalloc_node_range(size, PAGE_SIZE, BPF_JIT_REGION_START,
+diff --git a/arch/riscv/net/bpf_jit_core.c b/arch/riscv/net/bpf_jit_core.c
+new file mode 100644
+index 000000000000..709b94ece3ed
+--- /dev/null
++++ b/arch/riscv/net/bpf_jit_core.c
+@@ -0,0 +1,166 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Common functionality for RV32 and RV64 BPF JIT compilers
++ *
++ * Copyright (c) 2019 Björn Töpel 
++ *
++ */
++
++#include 
++#include 
++#include "bpf_jit.h"
++
++/* Number of iterations to try until offsets converge. */
++#define NR_JIT_ITERATIONS	16
++
++static int build_body(struct rv_jit_context *ctx, bool extra_pass, int *offset)
++{
++	const struct bpf_prog *prog = ctx->prog;
++	int i;
++
++	for (i = 0; i < prog->len; i++) {
++		const struct bpf_insn *insn = &prog->insnsi[i];
++		int ret;
++
++		ret = bpf_jit_emit_insn(insn, ctx, extra_pass);
++		/* BPF_LD | BPF_IMM | BPF_DW: skip the next instruction. */
++		if (ret > 0)
++			i++;
++		if (offset)
++			offset[i] = ctx->ninsns;
++		if (ret < 0)
++			return ret;
++	}
++	return 0;
++}
++
++bool bpf_jit_needs_zext(void)
++{
++	return true;
++}
++
++struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
++{
++	bool tmp_blinded = false, extra_pass = false;
++	struct bpf_prog *tmp, *orig_prog = prog;
++	int pass = 0, prev_ninsns = 0, i;
++	struct rv_jit_data *jit_data;
++	struct rv_jit_context *ctx;
++	unsigned int image_size = 0;
++
++	if (!prog->jit_requested)
++		return orig_prog;
++
++	tmp = bpf_jit_blind_constants(prog);
++	if (IS_ERR(tmp))
++		return orig_prog;
++	if (tmp != prog) {
++		tmp_blinded = true;
++		prog = tmp;
++	}
++
++	jit_data = prog->aux->jit_data;
++	if (!jit_data) {
++		jit_data = kzalloc(sizeof(*jit_data), GFP_KERNEL);
++		if (!jit_data) {
++			prog = orig_prog;
++			goto out;
++		}
++		prog->aux->jit_data = jit_data;
++	}
++
++	ctx = &jit_data->ctx;
++
++	if (ctx->offset) {
++		extra_pass = true;
++		image_size = sizeof(u32) * ctx->ninsns;
++		goto skip_init_ctx;
++	}
++
++	ctx->prog = prog;
++	ctx->offset = kcalloc(prog->len, sizeof(int), GFP_KERNEL);
++	if (!ctx->offset) {
++		prog = orig_prog;
++		goto out_offset;
++	}
++	for (i = 0; i < prog->len; i++) {
++		prev_ninsns += 32;
++		ctx->offset[i] = prev_ninsns;
++	}
++
++	for (i = 0; i < NR_JIT_ITERATIONS; i++) {
++		pass++;
++		ctx->ninsns = 0;
++		if (build_body(ctx, extra_pass, ctx->offset)) {
++			prog = orig_prog;
++			goto out_offset;
++		}
++		bpf_jit_build_prologue(ctx);
++		ctx->epilogue_offset = ctx->ninsns;
++		bpf_jit_build_epilogue(ctx);
++
++		if (ctx->ninsns == prev_ninsns) {
++			if (jit_data->header)
++				break;
++
++			image_size = sizeof(u32) * ctx->ninsns;
++			jit_data->header =
++				bpf_jit_binary_alloc(image_size,
++						     &jit_data->image,
++						     sizeof(u32),
++						     bpf_fill_ill_insns);
++			if (!jit_data->header) {
++				prog = orig_prog;
++				goto out_offset;
++			}
++
++			ctx->insns = (u32 *)jit_data->image;
++			/*
++			 * Now, when the image is allocated, the image can
++			 * potentially shrink more (auipc/jalr -> jal).
++			 */
++		}
++		prev_ninsns = ctx->ninsns;
++	}
++
++	if (i == NR_JIT_ITERATIONS) {
++		pr_err("bpf-jit: image did not converge in <%d passes!\n", i);
++		bpf_jit_binary_free(jit_data->header);
++		prog = orig_prog;
++		goto out_offset;
++	}
++
++skip_init_ctx:
++	pass++;
++	ctx->ninsns = 0;
++
++	bpf_jit_build_prologue(ctx);
++	if (build_body(ctx, extra_pass, NULL)) {
++		bpf_jit_binary_free(jit_data->header);
++		prog = orig_prog;
++		goto out_offset;
++	}
++	bpf_jit_build_epilogue(ctx);
++
++	if (bpf_jit_enable > 1)
++		bpf_jit_dump(prog->len, image_size, pass, ctx->insns);
++
++	prog->bpf_func = (void *)ctx->insns;
++	prog->jited = 1;
++	prog->jited_len = image_size;
++
++	bpf_flush_icache(jit_data->header, ctx->insns + ctx->ninsns);
++
++	if (!prog->is_func || extra_pass) {
++out_offset:
++		kfree(ctx->offset);
++		kfree(jit_data);
++		prog->aux->jit_data = NULL;
++	}
++out:
++
++	if (tmp_blinded)
++		bpf_jit_prog_release_other(prog, prog == orig_prog ?
++					   tmp : orig_prog);
++	return prog;
++}

commit 46dd3d7d287b4f1850a4fe02d74587b5375ec4ab
+Author: Luke Nelson 
+Date:   Thu Jul 4 17:18:02 2019 -0700
+
+    bpf, riscv: Enable zext optimization for more RV64G ALU ops
+    
+    Commit 66d0d5a854a6 ("riscv: bpf: eliminate zero extension code-gen")
+    added the new zero-extension optimization for some BPF ALU operations.
+    
+    Since then, bugs in the JIT that have been fixed in the bpf tree require
+    this optimization to be added to other operations: commit 1e692f09e091
+    ("bpf, riscv: clear high 32 bits for ALU32 add/sub/neg/lsh/rsh/arsh"),
+    and commit fe121ee531d1 ("bpf, riscv: clear target register high 32-bits
+    for and/or/xor on ALU32").
+    
+    Now that these have been merged to bpf-next, the zext optimization can
+    be enabled for the fixed operations.
+    
+    Signed-off-by: Luke Nelson 
+    Cc: Song Liu 
+    Cc: Jiong Wang 
+    Cc: Xi Wang 
+    Acked-by: Björn Töpel 
+    Acked-by: Jiong Wang 
+    Signed-off-by: Daniel Borkmann 
+
+diff --git a/arch/riscv/net/bpf_jit_comp.c b/arch/riscv/net/bpf_jit_comp.c
+index 876cb9c705ce..5451ef3845f2 100644
+--- a/arch/riscv/net/bpf_jit_comp.c
++++ b/arch/riscv/net/bpf_jit_comp.c
+@@ -757,31 +757,31 @@ static int emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 	case BPF_ALU | BPF_ADD | BPF_X:
+ 	case BPF_ALU64 | BPF_ADD | BPF_X:
+ 		emit(is64 ? rv_add(rd, rd, rs) : rv_addw(rd, rd, rs), ctx);
+-		if (!is64)
++		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+ 		break;
+ 	case BPF_ALU | BPF_SUB | BPF_X:
+ 	case BPF_ALU64 | BPF_SUB | BPF_X:
+ 		emit(is64 ? rv_sub(rd, rd, rs) : rv_subw(rd, rd, rs), ctx);
+-		if (!is64)
++		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+ 		break;
+ 	case BPF_ALU | BPF_AND | BPF_X:
+ 	case BPF_ALU64 | BPF_AND | BPF_X:
+ 		emit(rv_and(rd, rd, rs), ctx);
+-		if (!is64)
++		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+ 		break;
+ 	case BPF_ALU | BPF_OR | BPF_X:
+ 	case BPF_ALU64 | BPF_OR | BPF_X:
+ 		emit(rv_or(rd, rd, rs), ctx);
+-		if (!is64)
++		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+ 		break;
+ 	case BPF_ALU | BPF_XOR | BPF_X:
+ 	case BPF_ALU64 | BPF_XOR | BPF_X:
+ 		emit(rv_xor(rd, rd, rs), ctx);
+-		if (!is64)
++		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+ 		break;
+ 	case BPF_ALU | BPF_MUL | BPF_X:
+@@ -811,13 +811,13 @@ static int emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 	case BPF_ALU | BPF_RSH | BPF_X:
+ 	case BPF_ALU64 | BPF_RSH | BPF_X:
+ 		emit(is64 ? rv_srl(rd, rd, rs) : rv_srlw(rd, rd, rs), ctx);
+-		if (!is64)
++		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+ 		break;
+ 	case BPF_ALU | BPF_ARSH | BPF_X:
+ 	case BPF_ALU64 | BPF_ARSH | BPF_X:
+ 		emit(is64 ? rv_sra(rd, rd, rs) : rv_sraw(rd, rd, rs), ctx);
+-		if (!is64)
++		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+ 		break;
+ 
+@@ -826,7 +826,7 @@ static int emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
+ 	case BPF_ALU64 | BPF_NEG:
+ 		emit(is64 ? rv_sub(rd, RV_REG_ZERO, rd) :
+ 		     rv_subw(rd, RV_REG_ZERO, rd), ctx);
+-		if (!is64)
++		if (!is64 && !aux->verifier_zext)
+ 			emit_zext_32(rd, ctx);
+ 		break;
+ 

commit ac8786c72eba67dfc8ae751a75c586289a1b9b1b
+Author: Luke Nelson 
+Date:   Fri Jun 28 22:57:51 2019 -0700
+
+    selftests: bpf: add tests for shifts by zero
+    
+    There are currently no tests for ALU64 shift operations when the shift
+    amount is 0. This adds 6 new tests to make sure they are equivalent
+    to a no-op. The x32 JIT had such bugs that could have been caught by
+    these tests.
+    
+    Cc: Xi Wang 
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Daniel Borkmann 
+
+diff --git a/tools/testing/selftests/bpf/verifier/basic_instr.c b/tools/testing/selftests/bpf/verifier/basic_instr.c
+index ed91a7b9a456..071dbc889e8c 100644
+--- a/tools/testing/selftests/bpf/verifier/basic_instr.c
++++ b/tools/testing/selftests/bpf/verifier/basic_instr.c
+@@ -90,6 +90,91 @@
+ 	},
+ 	.result = ACCEPT,
+ },
++{
++	"lsh64 by 0 imm",
++	.insns = {
++	BPF_LD_IMM64(BPF_REG_0, 1),
++	BPF_LD_IMM64(BPF_REG_1, 1),
++	BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 0),
++	BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 1),
++	BPF_MOV64_IMM(BPF_REG_0, 2),
++	BPF_EXIT_INSN(),
++	},
++	.result = ACCEPT,
++	.retval = 1,
++},
++{
++	"rsh64 by 0 imm",
++	.insns = {
++	BPF_LD_IMM64(BPF_REG_0, 1),
++	BPF_LD_IMM64(BPF_REG_1, 0x100000000LL),
++	BPF_ALU64_REG(BPF_MOV, BPF_REG_2, BPF_REG_1),
++	BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 0),
++	BPF_JMP_REG(BPF_JEQ, BPF_REG_1, BPF_REG_2, 1),
++	BPF_MOV64_IMM(BPF_REG_0, 2),
++	BPF_EXIT_INSN(),
++	},
++	.result = ACCEPT,
++	.retval = 1,
++},
++{
++	"arsh64 by 0 imm",
++	.insns = {
++	BPF_LD_IMM64(BPF_REG_0, 1),
++	BPF_LD_IMM64(BPF_REG_1, 0x100000000LL),
++	BPF_ALU64_REG(BPF_MOV, BPF_REG_2, BPF_REG_1),
++	BPF_ALU64_IMM(BPF_ARSH, BPF_REG_1, 0),
++	BPF_JMP_REG(BPF_JEQ, BPF_REG_1, BPF_REG_2, 1),
++	BPF_MOV64_IMM(BPF_REG_0, 2),
++	BPF_EXIT_INSN(),
++	},
++	.result = ACCEPT,
++	.retval = 1,
++},
++{
++	"lsh64 by 0 reg",
++	.insns = {
++	BPF_LD_IMM64(BPF_REG_0, 1),
++	BPF_LD_IMM64(BPF_REG_1, 1),
++	BPF_LD_IMM64(BPF_REG_2, 0),
++	BPF_ALU64_REG(BPF_LSH, BPF_REG_1, BPF_REG_2),
++	BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 1),
++	BPF_MOV64_IMM(BPF_REG_0, 2),
++	BPF_EXIT_INSN(),
++	},
++	.result = ACCEPT,
++	.retval = 1,
++},
++{
++	"rsh64 by 0 reg",
++	.insns = {
++	BPF_LD_IMM64(BPF_REG_0, 1),
++	BPF_LD_IMM64(BPF_REG_1, 0x100000000LL),
++	BPF_ALU64_REG(BPF_MOV, BPF_REG_2, BPF_REG_1),
++	BPF_LD_IMM64(BPF_REG_3, 0),
++	BPF_ALU64_REG(BPF_RSH, BPF_REG_1, BPF_REG_3),
++	BPF_JMP_REG(BPF_JEQ, BPF_REG_1, BPF_REG_2, 1),
++	BPF_MOV64_IMM(BPF_REG_0, 2),
++	BPF_EXIT_INSN(),
++	},
++	.result = ACCEPT,
++	.retval = 1,
++},
++{
++	"arsh64 by 0 reg",
++	.insns = {
++	BPF_LD_IMM64(BPF_REG_0, 1),
++	BPF_LD_IMM64(BPF_REG_1, 0x100000000LL),
++	BPF_ALU64_REG(BPF_MOV, BPF_REG_2, BPF_REG_1),
++	BPF_LD_IMM64(BPF_REG_3, 0),
++	BPF_ALU64_REG(BPF_ARSH, BPF_REG_1, BPF_REG_3),
++	BPF_JMP_REG(BPF_JEQ, BPF_REG_1, BPF_REG_2, 1),
++	BPF_MOV64_IMM(BPF_REG_0, 2),
++	BPF_EXIT_INSN(),
++	},
++	.result = ACCEPT,
++	.retval = 1,
++},
+ {
+ 	"invalid 64-bit BPF_END",
+ 	.insns = {

commit 6fa632e719eec4d1b1ebf3ddc0b2d667997b057b
+Author: Luke Nelson 
+Date:   Fri Jun 28 22:57:50 2019 -0700
+
+    bpf, x32: Fix bug with ALU64 {LSH, RSH, ARSH} BPF_K shift by 0
+    
+    The current x32 BPF JIT does not correctly compile shift operations when
+    the immediate shift amount is 0. The expected behavior is for this to
+    be a no-op.
+    
+    The following program demonstrates the bug. The expexceted result is 1,
+    but the current JITed code returns 2.
+    
+      r0 = 1
+      r1 = 1
+      r1 <<= 0
+      if r1 == 1 goto end
+      r0 = 2
+    end:
+      exit
+    
+    This patch simplifies the code and fixes the bug.
+    
+    Fixes: 03f5781be2c7 ("bpf, x86_32: add eBPF JIT compiler for ia32")
+    Co-developed-by: Xi Wang 
+    Signed-off-by: Xi Wang 
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Daniel Borkmann 
+
+diff --git a/arch/x86/net/bpf_jit_comp32.c b/arch/x86/net/bpf_jit_comp32.c
+index f34ef513f4f9..1d12d2174085 100644
+--- a/arch/x86/net/bpf_jit_comp32.c
++++ b/arch/x86/net/bpf_jit_comp32.c
+@@ -894,27 +894,10 @@ static inline void emit_ia32_lsh_i64(const u8 dst[], const u32 val,
+ 	}
+ 	/* Do LSH operation */
+ 	if (val < 32) {
+-		/* shl dreg_hi,imm8 */
+-		EMIT3(0xC1, add_1reg(0xE0, dreg_hi), val);
+-		/* mov ebx,dreg_lo */
+-		EMIT2(0x8B, add_2reg(0xC0, dreg_lo, IA32_EBX));
++		/* shld dreg_hi,dreg_lo,imm8 */
++		EMIT4(0x0F, 0xA4, add_2reg(0xC0, dreg_hi, dreg_lo), val);
+ 		/* shl dreg_lo,imm8 */
+ 		EMIT3(0xC1, add_1reg(0xE0, dreg_lo), val);
+-
+-		/* IA32_ECX = 32 - val */
+-		/* mov ecx,val */
+-		EMIT2(0xB1, val);
+-		/* movzx ecx,ecx */
+-		EMIT3(0x0F, 0xB6, add_2reg(0xC0, IA32_ECX, IA32_ECX));
+-		/* neg ecx */
+-		EMIT2(0xF7, add_1reg(0xD8, IA32_ECX));
+-		/* add ecx,32 */
+-		EMIT3(0x83, add_1reg(0xC0, IA32_ECX), 32);
+-
+-		/* shr ebx,cl */
+-		EMIT2(0xD3, add_1reg(0xE8, IA32_EBX));
+-		/* or dreg_hi,ebx */
+-		EMIT2(0x09, add_2reg(0xC0, dreg_hi, IA32_EBX));
+ 	} else if (val >= 32 && val < 64) {
+ 		u32 value = val - 32;
+ 
+@@ -960,27 +943,10 @@ static inline void emit_ia32_rsh_i64(const u8 dst[], const u32 val,
+ 
+ 	/* Do RSH operation */
+ 	if (val < 32) {
+-		/* shr dreg_lo,imm8 */
+-		EMIT3(0xC1, add_1reg(0xE8, dreg_lo), val);
+-		/* mov ebx,dreg_hi */
+-		EMIT2(0x8B, add_2reg(0xC0, dreg_hi, IA32_EBX));
++		/* shrd dreg_lo,dreg_hi,imm8 */
++		EMIT4(0x0F, 0xAC, add_2reg(0xC0, dreg_lo, dreg_hi), val);
+ 		/* shr dreg_hi,imm8 */
+ 		EMIT3(0xC1, add_1reg(0xE8, dreg_hi), val);
+-
+-		/* IA32_ECX = 32 - val */
+-		/* mov ecx,val */
+-		EMIT2(0xB1, val);
+-		/* movzx ecx,ecx */
+-		EMIT3(0x0F, 0xB6, add_2reg(0xC0, IA32_ECX, IA32_ECX));
+-		/* neg ecx */
+-		EMIT2(0xF7, add_1reg(0xD8, IA32_ECX));
+-		/* add ecx,32 */
+-		EMIT3(0x83, add_1reg(0xC0, IA32_ECX), 32);
+-
+-		/* shl ebx,cl */
+-		EMIT2(0xD3, add_1reg(0xE0, IA32_EBX));
+-		/* or dreg_lo,ebx */
+-		EMIT2(0x09, add_2reg(0xC0, dreg_lo, IA32_EBX));
+ 	} else if (val >= 32 && val < 64) {
+ 		u32 value = val - 32;
+ 
+@@ -1025,27 +991,10 @@ static inline void emit_ia32_arsh_i64(const u8 dst[], const u32 val,
+ 	}
+ 	/* Do RSH operation */
+ 	if (val < 32) {
+-		/* shr dreg_lo,imm8 */
+-		EMIT3(0xC1, add_1reg(0xE8, dreg_lo), val);
+-		/* mov ebx,dreg_hi */
+-		EMIT2(0x8B, add_2reg(0xC0, dreg_hi, IA32_EBX));
++		/* shrd dreg_lo,dreg_hi,imm8 */
++		EMIT4(0x0F, 0xAC, add_2reg(0xC0, dreg_lo, dreg_hi), val);
+ 		/* ashr dreg_hi,imm8 */
+ 		EMIT3(0xC1, add_1reg(0xF8, dreg_hi), val);
+-
+-		/* IA32_ECX = 32 - val */
+-		/* mov ecx,val */
+-		EMIT2(0xB1, val);
+-		/* movzx ecx,ecx */
+-		EMIT3(0x0F, 0xB6, add_2reg(0xC0, IA32_ECX, IA32_ECX));
+-		/* neg ecx */
+-		EMIT2(0xF7, add_1reg(0xD8, IA32_ECX));
+-		/* add ecx,32 */
+-		EMIT3(0x83, add_1reg(0xC0, IA32_ECX), 32);
+-
+-		/* shl ebx,cl */
+-		EMIT2(0xD3, add_1reg(0xE0, IA32_EBX));
+-		/* or dreg_lo,ebx */
+-		EMIT2(0x09, add_2reg(0xC0, dreg_lo, IA32_EBX));
+ 	} else if (val >= 32 && val < 64) {
+ 		u32 value = val - 32;
+ 

commit 68a8357ec15bdce55266e9fba8b8b3b8143fa7d2
+Author: Luke Nelson 
+Date:   Fri Jun 28 22:57:49 2019 -0700
+
+    bpf, x32: Fix bug with ALU64 {LSH, RSH, ARSH} BPF_X shift by 0
+    
+    The current x32 BPF JIT for shift operations is not correct when the
+    shift amount in a register is 0. The expected behavior is a no-op, whereas
+    the current implementation changes bits in the destination register.
+    
+    The following example demonstrates the bug. The expected result of this
+    program is 1, but the current JITed code returns 2.
+    
+      r0 = 1
+      r1 = 1
+      r2 = 0
+      r1 <<= r2
+      if r1 == 1 goto end
+      r0 = 2
+    end:
+      exit
+    
+    The bug is caused by an incorrect assumption by the JIT that a shift by
+    32 clear the register. On x32 however, shifts use the lower 5 bits of
+    the source, making a shift by 32 equivalent to a shift by 0.
+    
+    This patch fixes the bug using double-precision shifts, which also
+    simplifies the code.
+    
+    Fixes: 03f5781be2c7 ("bpf, x86_32: add eBPF JIT compiler for ia32")
+    Co-developed-by: Xi Wang 
+    Signed-off-by: Xi Wang 
+    Signed-off-by: Luke Nelson 
+    Signed-off-by: Daniel Borkmann 
+
+diff --git a/arch/x86/net/bpf_jit_comp32.c b/arch/x86/net/bpf_jit_comp32.c
+index b29e82f190c7..f34ef513f4f9 100644
+--- a/arch/x86/net/bpf_jit_comp32.c
++++ b/arch/x86/net/bpf_jit_comp32.c
+@@ -724,9 +724,6 @@ static inline void emit_ia32_lsh_r64(const u8 dst[], const u8 src[],
+ {
+ 	u8 *prog = *pprog;
+ 	int cnt = 0;
+-	static int jmp_label1 = -1;
+-	static int jmp_label2 = -1;
+-	static int jmp_label3 = -1;
+ 	u8 dreg_lo = dstk ? IA32_EAX : dst_lo;
+ 	u8 dreg_hi = dstk ? IA32_EDX : dst_hi;
+ 
+@@ -745,79 +742,23 @@ static inline void emit_ia32_lsh_r64(const u8 dst[], const u8 src[],
+ 		/* mov ecx,src_lo */
+ 		EMIT2(0x8B, add_2reg(0xC0, src_lo, IA32_ECX));
+ 
+-	/* cmp ecx,32 */
+-	EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 32);
+-	/* Jumps when >= 32 */
+-	if (is_imm8(jmp_label(jmp_label1, 2)))
+-		EMIT2(IA32_JAE, jmp_label(jmp_label1, 2));
+-	else
+-		EMIT2_off32(0x0F, IA32_JAE + 0x10, jmp_label(jmp_label1, 6));
+-
+-	/* < 32 */
+-	/* shl dreg_hi,cl */
+-	EMIT2(0xD3, add_1reg(0xE0, dreg_hi));
+-	/* mov ebx,dreg_lo */
+-	EMIT2(0x8B, add_2reg(0xC0, dreg_lo, IA32_EBX));
++	/* shld dreg_hi,dreg_lo,cl */
++	EMIT3(0x0F, 0xA5, add_2reg(0xC0, dreg_hi, dreg_lo));
+ 	/* shl dreg_lo,cl */
+ 	EMIT2(0xD3, add_1reg(0xE0, dreg_lo));
+ 
+-	/* IA32_ECX = -IA32_ECX + 32 */
+-	/* neg ecx */
+-	EMIT2(0xF7, add_1reg(0xD8, IA32_ECX));
+-	/* add ecx,32 */
+-	EMIT3(0x83, add_1reg(0xC0, IA32_ECX), 32);
+-
+-	/* shr ebx,cl */
+-	EMIT2(0xD3, add_1reg(0xE8, IA32_EBX));
+-	/* or dreg_hi,ebx */
+-	EMIT2(0x09, add_2reg(0xC0, dreg_hi, IA32_EBX));
+-
+-	/* goto out; */
+-	if (is_imm8(jmp_label(jmp_label3, 2)))
+-		EMIT2(0xEB, jmp_label(jmp_label3, 2));
+-	else
+-		EMIT1_off32(0xE9, jmp_label(jmp_label3, 5));
+-
+-	/* >= 32 */
+-	if (jmp_label1 == -1)
+-		jmp_label1 = cnt;
++	/* if ecx >= 32, mov dreg_lo into dreg_hi and clear dreg_lo */
+ 
+-	/* cmp ecx,64 */
+-	EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 64);
+-	/* Jumps when >= 64 */
+-	if (is_imm8(jmp_label(jmp_label2, 2)))
+-		EMIT2(IA32_JAE, jmp_label(jmp_label2, 2));
+-	else
+-		EMIT2_off32(0x0F, IA32_JAE + 0x10, jmp_label(jmp_label2, 6));
++	/* cmp ecx,32 */
++	EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 32);
++	/* skip the next two instructions (4 bytes) when < 32 */
++	EMIT2(IA32_JB, 4);
+ 
+-	/* >= 32 && < 64 */
+-	/* sub ecx,32 */
+-	EMIT3(0x83, add_1reg(0xE8, IA32_ECX), 32);
+-	/* shl dreg_lo,cl */
+-	EMIT2(0xD3, add_1reg(0xE0, dreg_lo));
+ 	/* mov dreg_hi,dreg_lo */
+ 	EMIT2(0x89, add_2reg(0xC0, dreg_hi, dreg_lo));
+-
+ 	/* xor dreg_lo,dreg_lo */
+ 	EMIT2(0x33, add_2reg(0xC0, dreg_lo, dreg_lo));
+ 
+-	/* goto out; */
+-	if (is_imm8(jmp_label(jmp_label3, 2)))
+-		EMIT2(0xEB, jmp_label(jmp_label3, 2));
+-	else
+-		EMIT1_off32(0xE9, jmp_label(jmp_label3, 5));
+-
+-	/* >= 64 */
+-	if (jmp_label2 == -1)
+-		jmp_label2 = cnt;
+-	/* xor dreg_lo,dreg_lo */
+-	EMIT2(0x33, add_2reg(0xC0, dreg_lo, dreg_lo));
+-	/* xor dreg_hi,dreg_hi */
+-	EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi));
+-
+-	if (jmp_label3 == -1)
+-		jmp_label3 = cnt;
+-
+ 	if (dstk) {
+ 		/* mov dword ptr [ebp+off],dreg_lo */
+ 		EMIT3(0x89, add_2reg(0x40, IA32_EBP, dreg_lo),
+@@ -836,9 +777,6 @@ static inline void emit_ia32_arsh_r64(const u8 dst[], const u8 src[],
+ {
+ 	u8 *prog = *pprog;
+ 	int cnt = 0;
+-	static int jmp_label1 = -1;
+-	static int jmp_label2 = -1;
+-	static int jmp_label3 = -1;
+ 	u8 dreg_lo = dstk ? IA32_EAX : dst_lo;
+ 	u8 dreg_hi = dstk ? IA32_EDX : dst_hi;
+ 
+@@ -857,78 +795,22 @@ static inline void emit_ia32_arsh_r64(const u8 dst[], const u8 src[],
+ 		/* mov ecx,src_lo */
+ 		EMIT2(0x8B, add_2reg(0xC0, src_lo, IA32_ECX));
+ 
+-	/* cmp ecx,32 */
+-	EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 32);
+-	/* Jumps when >= 32 */
+-	if (is_imm8(jmp_label(jmp_label1, 2)))
+-		EMIT2(IA32_JAE, jmp_label(jmp_label1, 2));
+-	else
+-		EMIT2_off32(0x0F, IA32_JAE + 0x10, jmp_label(jmp_label1, 6));
+-
+-	/* < 32 */
+-	/* lshr dreg_lo,cl */
+-	EMIT2(0xD3, add_1reg(0xE8, dreg_lo));
+-	/* mov ebx,dreg_hi */
+-	EMIT2(0x8B, add_2reg(0xC0, dreg_hi, IA32_EBX));
+-	/* ashr dreg_hi,cl */
++	/* shrd dreg_lo,dreg_hi,cl */
++	EMIT3(0x0F, 0xAD, add_2reg(0xC0, dreg_lo, dreg_hi));
++	/* sar dreg_hi,cl */
+ 	EMIT2(0xD3, add_1reg(0xF8, dreg_hi));
+ 
+-	/* IA32_ECX = -IA32_ECX + 32 */
+-	/* neg ecx */
+-	EMIT2(0xF7, add_1reg(0xD8, IA32_ECX));
+-	/* add ecx,32 */
+-	EMIT3(0x83, add_1reg(0xC0, IA32_ECX), 32);
+-
+-	/* shl ebx,cl */
+-	EMIT2(0xD3, add_1reg(0xE0, IA32_EBX));
+-	/* or dreg_lo,ebx */
+-	EMIT2(0x09, add_2reg(0xC0, dreg_lo, IA32_EBX));
+-
+-	/* goto out; */
+-	if (is_imm8(jmp_label(jmp_label3, 2)))
+-		EMIT2(0xEB, jmp_label(jmp_label3, 2));
+-	else
+-		EMIT1_off32(0xE9, jmp_label(jmp_label3, 5));
+-
+-	/* >= 32 */
+-	if (jmp_label1 == -1)
+-		jmp_label1 = cnt;
++	/* if ecx >= 32, mov dreg_hi to dreg_lo and set/clear dreg_hi depending on sign */
+ 
+-	/* cmp ecx,64 */
+-	EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 64);
+-	/* Jumps when >= 64 */
+-	if (is_imm8(jmp_label(jmp_label2, 2)))
+-		EMIT2(IA32_JAE, jmp_label(jmp_label2, 2));
+-	else
+-		EMIT2_off32(0x0F, IA32_JAE + 0x10, jmp_label(jmp_label2, 6));
++	/* cmp ecx,32 */
++	EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 32);
++	/* skip the next two instructions (5 bytes) when < 32 */
++	EMIT2(IA32_JB, 5);
+ 
+-	/* >= 32 && < 64 */
+-	/* sub ecx,32 */
+-	EMIT3(0x83, add_1reg(0xE8, IA32_ECX), 32);
+-	/* ashr dreg_hi,cl */
+-	EMIT2(0xD3, add_1reg(0xF8, dreg_hi));
+ 	/* mov dreg_lo,dreg_hi */
+ 	EMIT2(0x89, add_2reg(0xC0, dreg_lo, dreg_hi));
+-
+-	/* ashr dreg_hi,imm8 */
+-	EMIT3(0xC1, add_1reg(0xF8, dreg_hi), 31);
+-
+-	/* goto out; */
+-	if (is_imm8(jmp_label(jmp_label3, 2)))
+-		EMIT2(0xEB, jmp_label(jmp_label3, 2));
+-	else
+-		EMIT1_off32(0xE9, jmp_label(jmp_label3, 5));
+-
+-	/* >= 64 */
+-	if (jmp_label2 == -1)
+-		jmp_label2 = cnt;
+-	/* ashr dreg_hi,imm8 */
++	/* sar dreg_hi,31 */
+ 	EMIT3(0xC1, add_1reg(0xF8, dreg_hi), 31);
+-	/* mov dreg_lo,dreg_hi */
+-	EMIT2(0x89, add_2reg(0xC0, dreg_lo, dreg_hi));
+-
+-	if (jmp_label3 == -1)
+-		jmp_label3 = cnt;
+ 
+ 	if (dstk) {
+ 		/* mov dword ptr [ebp+off],dreg_lo */
+@@ -948,9 +830,6 @@ static inline void emit_ia32_rsh_r64(const u8 dst[], const u8 src[], bool dstk,
+ {
+ 	u8 *prog = *pprog;
+ 	int cnt = 0;
+-	static int jmp_label1 = -1;
+-	static int jmp_label2 = -1;
+-	static int jmp_label3 = -1;
+ 	u8 dreg_lo = dstk ? IA32_EAX : dst_lo;
+ 	u8 dreg_hi = dstk ? IA32_EDX : dst_hi;
+ 
+@@ -969,77 +848,23 @@ static inline void emit_ia32_rsh_r64(const u8 dst[], const u8 src[], bool dstk,
+ 		/* mov ecx,src_lo */
+ 		EMIT2(0x8B, add_2reg(0xC0, src_lo, IA32_ECX));
+ 
+-	/* cmp ecx,32 */
+-	EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 32);
+-	/* Jumps when >= 32 */
+-	if (is_imm8(jmp_label(jmp_label1, 2)))
+-		EMIT2(IA32_JAE, jmp_label(jmp_label1, 2));
+-	else
+-		EMIT2_off32(0x0F, IA32_JAE + 0x10, jmp_label(jmp_label1, 6));
+-
+-	/* < 32 */
+-	/* lshr dreg_lo,cl */
+-	EMIT2(0xD3, add_1reg(0xE8, dreg_lo));
+-	/* mov ebx,dreg_hi */
+-	EMIT2(0x8B, add_2reg(0xC0, dreg_hi, IA32_EBX));
++	/* shrd dreg_lo,dreg_hi,cl */
++	EMIT3(0x0F, 0xAD, add_2reg(0xC0, dreg_lo, dreg_hi));
+ 	/* shr dreg_hi,cl */
+ 	EMIT2(0xD3, add_1reg(0xE8, dreg_hi));
+ 
+-	/* IA32_ECX = -IA32_ECX + 32 */
+-	/* neg ecx */
+-	EMIT2(0xF7, add_1reg(0xD8, IA32_ECX));
+-	/* add ecx,32 */
+-	EMIT3(0x83, add_1reg(0xC0, IA32_ECX), 32);
+-
+-	/* shl ebx,cl */
+-	EMIT2(0xD3, add_1reg(0xE0, IA32_EBX));
+-	/* or dreg_lo,ebx */
+-	EMIT2(0x09, add_2reg(0xC0, dreg_lo, IA32_EBX));
++	/* if ecx >= 32, mov dreg_hi to dreg_lo and clear dreg_hi */
+ 
+-	/* goto out; */
+-	if (is_imm8(jmp_label(jmp_label3, 2)))
+-		EMIT2(0xEB, jmp_label(jmp_label3, 2));
+-	else
+-		EMIT1_off32(0xE9, jmp_label(jmp_label3, 5));
+-
+-	/* >= 32 */
+-	if (jmp_label1 == -1)
+-		jmp_label1 = cnt;
+-	/* cmp ecx,64 */
+-	EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 64);
+-	/* Jumps when >= 64 */
+-	if (is_imm8(jmp_label(jmp_label2, 2)))
+-		EMIT2(IA32_JAE, jmp_label(jmp_label2, 2));
+-	else
+-		EMIT2_off32(0x0F, IA32_JAE + 0x10, jmp_label(jmp_label2, 6));
++	/* cmp ecx,32 */
++	EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 32);
++	/* skip the next two instructions (4 bytes) when < 32 */
++	EMIT2(IA32_JB, 4);
+ 
+-	/* >= 32 && < 64 */
+-	/* sub ecx,32 */
+-	EMIT3(0x83, add_1reg(0xE8, IA32_ECX), 32);
+-	/* shr dreg_hi,cl */
+-	EMIT2(0xD3, add_1reg(0xE8, dreg_hi));
+ 	/* mov dreg_lo,dreg_hi */
+ 	EMIT2(0x89, add_2reg(0xC0, dreg_lo, dreg_hi));
+ 	/* xor dreg_hi,dreg_hi */
+ 	EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi));
+ 
+-	/* goto out; */
+-	if (is_imm8(jmp_label(jmp_label3, 2)))
+-		EMIT2(0xEB, jmp_label(jmp_label3, 2));
+-	else
+-		EMIT1_off32(0xE9, jmp_label(jmp_label3, 5));
+-
+-	/* >= 64 */
+-	if (jmp_label2 == -1)
+-		jmp_label2 = cnt;
+-	/* xor dreg_lo,dreg_lo */
+-	EMIT2(0x33, add_2reg(0xC0, dreg_lo, dreg_lo));
+-	/* xor dreg_hi,dreg_hi */
+-	EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi));
+-
+-	if (jmp_label3 == -1)
+-		jmp_label3 = cnt;
+-
+ 	if (dstk) {
+ 		/* mov dword ptr [ebp+off],dreg_lo */
+ 		EMIT3(0x89, add_2reg(0x40, IA32_EBP, dreg_lo),

commit 39d84a58ad6290a43e6503acc8b54ebb7e4ecc54
+Author: Daniel Halperin 
+Date:   Mon Jun 18 11:04:55 2012 +0000
+
+    sctp: fix warning when compiling without IPv6
+    
+    net/sctp/protocol.c: In function ‘sctp_addr_wq_timeout_handler’:
+    net/sctp/protocol.c:676: warning: label ‘free_next’ defined but not used
+    
+    Signed-off-by: Daniel Halperin 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
+index 5942d27b1444..9c90811d1134 100644
+--- a/net/sctp/protocol.c
++++ b/net/sctp/protocol.c
+@@ -673,7 +673,9 @@ void sctp_addr_wq_timeout_handler(unsigned long arg)
+ 				SCTP_DEBUG_PRINTK("sctp_addrwq_timo_handler: sctp_asconf_mgmt failed\n");
+ 			sctp_bh_unlock_sock(sk);
+ 		}
++#if IS_ENABLED(CONFIG_IPV6)
+ free_next:
++#endif
+ 		list_del(&addrw->list);
+ 		kfree(addrw);
+ 	}

commit faa85aa24286a9e14ae7cc797352350c3ac39986
+Author: Daniel Halperin 
+Date:   Tue Jan 3 13:53:16 2012 -0500
+
+    skge: fix warning when CONFIG_PM is defined but not CONFIG_PM_SLEEP
+    
+    drivers/net/ethernet/marvell/skge.c:4046: warning: ‘skge_suspend’ defined but not used
+    drivers/net/ethernet/marvell/skge.c:4071: warning: ‘skge_resume’ defined but not used
+    
+    Signed-off-by: Daniel Halperin 
+    Cc: Stephen Hemminger 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c
+index b3f636813089..18a87a57fc0a 100644
+--- a/drivers/net/ethernet/marvell/skge.c
++++ b/drivers/net/ethernet/marvell/skge.c
+@@ -4042,7 +4042,7 @@ static void __devexit skge_remove(struct pci_dev *pdev)
+ 	pci_set_drvdata(pdev, NULL);
+ }
+ 
+-#ifdef CONFIG_PM
++#ifdef CONFIG_PM_SLEEP
+ static int skge_suspend(struct device *dev)
+ {
+ 	struct pci_dev *pdev = to_pci_dev(dev);
+@@ -4104,7 +4104,7 @@ static SIMPLE_DEV_PM_OPS(skge_pm_ops, skge_suspend, skge_resume);
+ #else
+ 
+ #define SKGE_PM_OPS NULL
+-#endif
++#endif /* CONFIG_PM_SLEEP */
+ 
+ static void skge_shutdown(struct pci_dev *pdev)
+ {

commit f090fba305658fe6e464e2fbd25fad81957ece26
+Author: Daniel Halperin 
+Date:   Thu Aug 25 23:11:15 2011 -0700
+
+    iwlagn: fix compile warnings when CONFIG_PM_SLEEP is not set
+    
+      CC [M]  drivers/net/wireless/iwlwifi/iwl-pci.o
+      drivers/net/wireless/iwlwifi/iwl-pci.c:506: warning: ‘iwl_pci_suspend’ defined but not used
+      drivers/net/wireless/iwlwifi/iwl-pci.c:519: warning: ‘iwl_pci_resume’ defined but not used
+    
+    These are only used if CONFIG_PM_SLEEP is enabled. CONFIG_PM depends
+    (CONFIG_PM_SLEEP || CONFIG_PM_RUNTIME), so it can be set without
+    CONFIG_PM_SLEEP selected.
+    
+    Signed-off-by: Daniel Halperin 
+    Signed-off-by: Wey-Yi Guy 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c
+index 17f3fb241b6f..62c35a5fea80 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-pci.c
++++ b/drivers/net/wireless/iwlwifi/iwl-pci.c
+@@ -506,7 +506,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
+ 	iwl_pci_down(bus);
+ }
+ 
+-#ifdef CONFIG_PM
++#ifdef CONFIG_PM_SLEEP
+ 
+ static int iwl_pci_suspend(struct device *device)
+ {

commit 2e5d04dad1934d97057cbecce59834f78dafc067
+Author: Daniel Halperin 
+Date:   Fri May 27 08:40:28 2011 -0700
+
+    iwlwifi: disambiguate invalid DMA index warnings
+    
+    The exact same error message is used in three different functions in
+    iwlagn. Add the function name to the error string to disambiguate where
+    the error is coming from.
+    
+    Signed-off-by: Daniel Halperin 
+    Signed-off-by: Wey-Yi Guy 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+index f803fb62f8bc..4ab77c8a584c 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
++++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+@@ -408,9 +408,9 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
+ 	unsigned long flags;
+ 
+ 	if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
+-		IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d "
+-			  "is out of range [0-%d] %d %d\n", txq_id,
+-			  index, txq->q.n_bd, txq->q.write_ptr,
++		IWL_ERR(priv, "%s: Read index for DMA queue txq_id (%d) "
++			  "index %d is out of range [0-%d] %d %d\n", __func__,
++			  txq_id, index, txq->q.n_bd, txq->q.write_ptr,
+ 			  txq->q.read_ptr);
+ 		return;
+ 	}
+diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+index 4974cd7837cb..ce7b49139030 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
++++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+@@ -1236,9 +1236,9 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
+ 	struct ieee80211_hdr *hdr;
+ 
+ 	if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) {
+-		IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, "
+-			  "is out of range [0-%d] %d %d.\n", txq_id,
+-			  index, q->n_bd, q->write_ptr, q->read_ptr);
++		IWL_ERR(priv, "%s: Read index for DMA queue txq id (%d), "
++			  "index %d is out of range [0-%d] %d %d.\n", __func__,
++			  txq_id, index, q->n_bd, q->write_ptr, q->read_ptr);
+ 		return 0;
+ 	}
+ 
+diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
+index 686e176b5ebd..1084fe0e8a86 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
++++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
+@@ -753,9 +753,9 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int idx)
+ 	int nfreed = 0;
+ 
+ 	if ((idx >= q->n_bd) || (iwl_queue_used(q, idx) == 0)) {
+-		IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, "
+-			  "is out of range [0-%d] %d %d.\n", txq_id,
+-			  idx, q->n_bd, q->write_ptr, q->read_ptr);
++		IWL_ERR(priv, "%s: Read index for DMA queue txq id (%d), "
++			  "index %d is out of range [0-%d] %d %d.\n", __func__,
++			  txq_id, idx, q->n_bd, q->write_ptr, q->read_ptr);
+ 		return;
+ 	}
+ 

commit 21fdc87248d1d28492c775e05fa92b3c8c7bc8db
+Author: Daniel Halperin 
+Date:   Tue May 31 11:59:30 2011 -0700
+
+    ath9k: fix two more bugs in tx power
+    
+    This is the same fix as
+    
+       commit 841051602e3fa18ea468fe5a177aa92b6eb44b56
+       Author: Matteo Croce 
+       Date:   Fri Dec 3 02:25:08 2010 +0100
+    
+       The ath9k driver subtracts 3 dBm to the txpower as with two radios the
+       signal power is doubled.
+       The resulting value is assigned in an u16 which overflows and makes
+       the card work at full power.
+    
+    in two more places. I grepped the ath tree and didn't find any others.
+    
+    Cc: stable@kernel.org
+    Signed-off-by: Daniel Halperin 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+index 0ca7635d0669..ff8150e46f0e 100644
+--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+@@ -4645,10 +4645,16 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
+ 	case 1:
+ 		break;
+ 	case 2:
+-		scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
++		if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN)
++			scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
++		else
++			scaledPower = 0;
+ 		break;
+ 	case 3:
+-		scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
++		if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN)
++			scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
++		else
++			scaledPower = 0;
+ 		break;
+ 	}
+ 
+diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+index 7856f0d4512d..343fc9f946db 100644
+--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+@@ -524,10 +524,16 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
+ 	case 1:
+ 		break;
+ 	case 2:
+-		scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
++		if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN)
++			scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
++		else
++			scaledPower = 0;
+ 		break;
+ 	case 3:
+-		scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
++		if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN)
++			scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
++		else
++			scaledPower = 0;
+ 		break;
+ 	}
+ 	scaledPower = max((u16)0, scaledPower);

commit 20ba2861b09ae942398eda6d2dc0bf1019a97ddb
+Author: Daniel Halperin 
+Date:   Mon May 16 21:46:28 2011 -0700
+
+    iwlwifi: remove unused parameter from iwl_hcmd_queue_reclaim
+    
+    cmd_index is never used.
+    
+    Signed-off-by: Daniel Halperin 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
+index 54a935ff38fa..686e176b5ebd 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
++++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
+@@ -746,8 +746,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+  * need to be reclaimed. As result, some free space forms.  If there is
+  * enough free space (> low mark), wake the stack that feeds us.
+  */
+-static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id,
+-				   int idx, int cmd_idx)
++static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int idx)
+ {
+ 	struct iwl_tx_queue *txq = &priv->txq[txq_id];
+ 	struct iwl_queue *q = &txq->q;
+@@ -819,7 +818,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+ 
+ 	spin_lock_irqsave(&priv->hcmd_lock, flags);
+ 
+-	iwl_hcmd_queue_reclaim(priv, txq_id, index, cmd_index);
++	iwl_hcmd_queue_reclaim(priv, txq_id, index);
+ 
+ 	if (!(meta->flags & CMD_ASYNC)) {
+ 		clear_bit(STATUS_HCMD_ACTIVE, &priv->status);

commit 8fddddff0ad4ccc2787464207eba9ed3063e69cd
+Author: Daniel Halperin 
+Date:   Tue May 10 19:00:45 2011 -0700
+
+    mac80211: fix contention time computation in minstrel, minstrel_ht
+    
+    When transmitting a frame, the transmitter waits a random number of
+    slots between 0 and cw. Thus, the contention time is (cw / 2) * t_slot
+    which we can represent instead as (cw * t_slot) >> 1. Also fix a few
+    other accounting bugs around contention time, and add comments.
+    
+    Signed-off-by: Daniel Halperin 
+    Signed-off-by: John W. Linville 
+
+diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
+index 778c604d7939..8adac67395f7 100644
+--- a/net/mac80211/rc80211_minstrel.c
++++ b/net/mac80211/rc80211_minstrel.c
+@@ -417,8 +417,8 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
+ 			tx_time_single = mr->ack_time + mr->perfect_tx_time;
+ 
+ 			/* contention window */
+-			tx_time_single += t_slot + min(cw, mp->cw_max);
+-			cw = (cw << 1) | 1;
++			tx_time_single += (t_slot * cw) >> 1;
++			cw = min((cw << 1) | 1, mp->cw_max);
+ 
+ 			tx_time += tx_time_single;
+ 			tx_time_cts += tx_time_single + mi->sp_ack_dur;
+diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
+index dbdebeda097f..3d09c58938e2 100644
+--- a/net/mac80211/rc80211_minstrel_ht.c
++++ b/net/mac80211/rc80211_minstrel_ht.c
+@@ -464,6 +464,7 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
+ 	const struct mcs_group *group;
+ 	unsigned int tx_time, tx_time_rtscts, tx_time_data;
+ 	unsigned int cw = mp->cw_min;
++	unsigned int ctime = 0;
+ 	unsigned int t_slot = 9; /* FIXME */
+ 	unsigned int ampdu_len = MINSTREL_TRUNC(mi->avg_ampdu_len);
+ 
+@@ -480,13 +481,27 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
+ 
+ 	group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
+ 	tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len;
+-	tx_time = 2 * (t_slot + mi->overhead + tx_time_data);
+-	tx_time_rtscts = 2 * (t_slot + mi->overhead_rtscts + tx_time_data);
++
++	/* Contention time for first 2 tries */
++	ctime = (t_slot * cw) >> 1;
++	cw = min((cw << 1) | 1, mp->cw_max);
++	ctime += (t_slot * cw) >> 1;
++	cw = min((cw << 1) | 1, mp->cw_max);
++
++	/* Total TX time for data and Contention after first 2 tries */
++	tx_time = ctime + 2 * (mi->overhead + tx_time_data);
++	tx_time_rtscts = ctime + 2 * (mi->overhead_rtscts + tx_time_data);
++
++	/* See how many more tries we can fit inside segment size */
+ 	do {
+-		cw = (cw << 1) | 1;
+-		cw = min(cw, mp->cw_max);
+-		tx_time += cw + t_slot + mi->overhead;
+-		tx_time_rtscts += cw + t_slot + mi->overhead_rtscts;
++		/* Contention time for this try */
++		ctime = (t_slot * cw) >> 1;
++		cw = min((cw << 1) | 1, mp->cw_max);
++
++		/* Total TX time after this try */
++		tx_time += ctime + mi->overhead + tx_time_data;
++		tx_time_rtscts += ctime + mi->overhead_rtscts + tx_time_data;
++
+ 		if (tx_time_rtscts < mp->segment_size)
+ 			mr->retry_count_rtscts++;
+ 	} while ((tx_time < mp->segment_size) &&

commit 7caa2316bf0434f1150f58cb576542987a0466d7
+Author: Daniel Halperin 
+Date:   Wed Apr 6 12:47:25 2011 -0700
+
+    iwlwifi: fix frame injection for HT channels
+    
+    For some reason, sending QoS configuration causes transmission to stop
+    after a single frame on HT channels when not associated. Removing the
+    extra QoS configuration has no effect on station mode, and fixes
+    injection mode.
+    
+    Signed-off-by: Daniel Halperin 
+    Signed-off-by: Wey-Yi Guy 
+
+diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+index dfdbea6e8f99..fbbde0712fa5 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
++++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+@@ -335,7 +335,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
+ 	struct ieee80211_channel *channel = conf->channel;
+ 	const struct iwl_channel_info *ch_info;
+ 	int ret = 0;
+-	bool ht_changed[NUM_IWL_RXON_CTX] = {};
+ 
+ 	IWL_DEBUG_MAC80211(priv, "changed %#x", changed);
+ 
+@@ -383,10 +382,8 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
+ 
+ 		for_each_context(priv, ctx) {
+ 			/* Configure HT40 channels */
+-			if (ctx->ht.enabled != conf_is_ht(conf)) {
++			if (ctx->ht.enabled != conf_is_ht(conf))
+ 				ctx->ht.enabled = conf_is_ht(conf);
+-				ht_changed[ctx->ctxid] = true;
+-			}
+ 
+ 			if (ctx->ht.enabled) {
+ 				if (conf_is_ht40_minus(conf)) {
+@@ -455,8 +452,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
+ 		if (!memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
+ 			continue;
+ 		iwlagn_commit_rxon(priv, ctx);
+-		if (ht_changed[ctx->ctxid])
+-			iwlagn_update_qos(priv, ctx);
+ 	}
+  out:
+ 	mutex_unlock(&priv->mutex);

commit 499fe9a419d43410be576bcc825658997b6ce822
+Author: Daniel Halperin 
+Date:   Thu Mar 24 16:01:48 2011 -0700
+
+    mac80211: fix aggregation frame release during timeout
+    
+    Suppose the aggregation reorder buffer looks like this:
+    
+    x-T-R1-y-R2,
+    
+    where x and y are frames that have not been received, T is a received
+    frame that has timed out, and R1,R2 are received frames that have not
+    yet timed out. The proper behavior in this scenario is to move the
+    window past x (skipping it), release T and R1, and leave the window at y
+    until y is received or R2 times out.
+    
+    As written, this code will instead leave the window at R1, because it
+    has not yet timed out. Fix this by exiting the reorder loop only when
+    the frame that has not timed out AND there are skipped frames earlier in
+    the current valid window.
+    
+    Signed-off-by: Daniel Halperin 
+    Signed-off-by: John W. Linville 
+
+diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
+index 5c1930ba8ebe..aa5cc37b4921 100644
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -612,7 +612,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw,
+ 				skipped++;
+ 				continue;
+ 			}
+-			if (!time_after(jiffies, tid_agg_rx->reorder_time[j] +
++			if (skipped &&
++			    !time_after(jiffies, tid_agg_rx->reorder_time[j] +
+ 					HT_RX_REORDER_BUF_TIMEOUT))
+ 				goto set_release_timer;
+ 

commit 4263108c2a9028544cf4037fa4e72000ee456c33
+Author: Daniel Halperin 
+Date:   Mon Mar 21 15:27:34 2011 -0700
+
+    iwlwifi: set default aggregation frame limit to 63
+    
+    This gives much better performance at fast 3x3 rates (up to ~160 Mbps).
+    The scheduler will still make most decisions about batch size based on
+    available packets and RX parameters.
+    
+    Signed-off-by: Daniel Halperin 
+    Signed-off-by: Wey-Yi Guy 
+
+diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
+index 288391558afd..cc2151482f31 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
++++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
+@@ -2132,7 +2132,7 @@ struct iwl_link_qual_general_params {
+ #define LINK_QUAL_AGG_DISABLE_START_MAX	(255)
+ #define LINK_QUAL_AGG_DISABLE_START_MIN	(0)
+ 
+-#define LINK_QUAL_AGG_FRAME_LIMIT_DEF	(31)
++#define LINK_QUAL_AGG_FRAME_LIMIT_DEF	(63)
+ #define LINK_QUAL_AGG_FRAME_LIMIT_MAX	(63)
+ #define LINK_QUAL_AGG_FRAME_LIMIT_MIN	(0)
+ 

commit 2520546aecc969372080448a2422b39eedb2a528
+Author: Daniel Halperin 
+Date:   Fri Mar 18 18:48:55 2011 -0700
+
+    iwlwifi: add RATE_MCS_RATE_MSK
+    
+    Throughout the code we use rate_n_flags & 0xff to extract the lower byte
+    of the rate_n_flags u32 that contains the information about the rate.
+    Add a #define and remove the use of the magic number.
+    
+    Signed-off-by: Daniel Halperin 
+    Signed-off-by: Wey-Yi Guy 
+
+diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+index 63b58ecb0dc6..e394e49228ba 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
++++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+@@ -115,13 +115,18 @@ const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = {
+ 	/* FIXME:RS:          ^^    should be INV (legacy) */
+ };
+ 
++static inline u8 rs_extract_rate(u32 rate_n_flags)
++{
++	return (u8)(rate_n_flags & RATE_MCS_RATE_MSK);
++}
++
+ static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)
+ {
+ 	int idx = 0;
+ 
+ 	/* HT rate format */
+ 	if (rate_n_flags & RATE_MCS_HT_MSK) {
+-		idx = (rate_n_flags & 0xff);
++		idx = rs_extract_rate(rate_n_flags);
+ 
+ 		if (idx >= IWL_RATE_MIMO3_6M_PLCP)
+ 			idx = idx - IWL_RATE_MIMO3_6M_PLCP;
+@@ -138,7 +143,8 @@ static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)
+ 	/* legacy rate format, search for match in table */
+ 	} else {
+ 		for (idx = 0; idx < ARRAY_SIZE(iwl_rates); idx++)
+-			if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF))
++			if (iwl_rates[idx].plcp ==
++					rs_extract_rate(rate_n_flags))
+ 				return idx;
+ 	}
+ 
+@@ -239,11 +245,6 @@ static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = {
+ 
+ #define MCS_INDEX_PER_STREAM	(8)
+ 
+-static inline u8 rs_extract_rate(u32 rate_n_flags)
+-{
+-	return (u8)(rate_n_flags & 0xFF);
+-}
+-
+ static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window)
+ {
+ 	window->data = 0;
+diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
+index 4f7c9ce9d8bd..39313acb9cc7 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
++++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
+@@ -310,7 +310,7 @@ static inline u32 iwl_ant_idx_to_flags(u8 ant_idx)
+ 
+ static inline u8 iwl_hw_get_rate(__le32 rate_n_flags)
+ {
+-	return le32_to_cpu(rate_n_flags) & 0xFF;
++	return le32_to_cpu(rate_n_flags) & RATE_MCS_RATE_MSK;
+ }
+ 
+ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
+diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
+index ca42ffa63ed7..288391558afd 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
++++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
+@@ -324,6 +324,8 @@ struct iwl3945_power_per_rate {
+ #define RATE_MCS_SPATIAL_MSK 0x18
+ #define RATE_MCS_HT_DUP_POS 5
+ #define RATE_MCS_HT_DUP_MSK 0x20
++/* Both legacy and HT use bits 7:0 as the CCK/OFDM rate or HT MCS */
++#define RATE_MCS_RATE_MSK 0xff
+ 
+ /* Bit 8: (1) HT format, (0) legacy format in bits 7:0 */
+ #define RATE_MCS_FLAGS_POS 8

commit d0eb633431ec922f8f9b2040f46d9b42a4cec193
+Author: Daniel Halperin 
+Date:   Wed Mar 16 17:17:36 2011 -0700
+
+    iwlwifi: cleanup and bugfix tx aggregation code
+    
+    Since the driver split, there's no need for no_agg_framecnt_info since
+    all devices have this set to false. Secondly, the compressed block ack
+    handling code was broken. Fix this.
+    
+    (1) A shift less than zero simply implies that the buffer wrapped, this
+    is expected. Remove the incorrect comment.
+    
+    (2) The (agg->frame_count > (64-sh)) condition can happen if the last
+    frame is dropped. E.g., if I send 7 frames and the 6th is received but
+    the 7th is lost, the other side may only shift the window 6, not 7
+    frames since the last bit is a 0. This is perfectly fine behavior and
+    doesn't invalidate the feedback.
+    
+    (3) Store the feedback from a Compressed BA in the first newly received
+    frame, rather than the start of the window. This way it will get
+    processed by the rate selection code. Feedback stored in a non-received
+    frame is likely to get overwritten by the retransmission.
+        This is based on the approach taken by minstrel_ht.
+    
+    Signed-off-by: Daniel Halperin 
+    Signed-off-by: Wey-Yi Guy 
+
+diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+index fb63a03a395e..cb8eacd5fdb5 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
++++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+@@ -1263,11 +1263,11 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv,
+ 				 struct iwl_compressed_ba_resp *ba_resp)
+ 
+ {
+-	int i, sh, ack;
++	int sh;
+ 	u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl);
+ 	u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
+-	int successes = 0;
+ 	struct ieee80211_tx_info *info;
++	u64 bitmap, sent_bitmap;
+ 
+ 	if (unlikely(!agg->wait_for_ba))  {
+ 		if (unlikely(ba_resp->bitmap))
+@@ -1281,70 +1281,42 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv,
+ 
+ 	/* Calculate shift to align block-ack bits with our Tx window bits */
+ 	sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4);
+-	if (sh < 0) /* tbw something is wrong with indices */
++	if (sh < 0)
+ 		sh += 0x100;
+ 
+-	if (agg->frame_count > (64 - sh)) {
+-		IWL_DEBUG_TX_REPLY(priv, "more frames than bitmap size");
+-		return -1;
+-	}
+-	if (!priv->cfg->base_params->no_agg_framecnt_info && ba_resp->txed) {
++	/*
++	 * Check for success or failure according to the
++	 * transmitted bitmap and block-ack bitmap
++	 */
++	bitmap = le64_to_cpu(ba_resp->bitmap) >> sh;
++	sent_bitmap = bitmap & agg->bitmap;
++
++	/* Sanity check values reported by uCode */
++	if (ba_resp->txed_2_done > ba_resp->txed) {
++		IWL_DEBUG_TX_REPLY(priv,
++			"bogus sent(%d) and ack(%d) count\n",
++			ba_resp->txed, ba_resp->txed_2_done);
+ 		/*
+-		 * sent and ack information provided by uCode
+-		 * use it instead of figure out ourself
++		 * set txed_2_done = txed,
++		 * so it won't impact rate scale
+ 		 */
+-		if (ba_resp->txed_2_done > ba_resp->txed) {
+-			IWL_DEBUG_TX_REPLY(priv,
+-				"bogus sent(%d) and ack(%d) count\n",
+-				ba_resp->txed, ba_resp->txed_2_done);
+-			/*
+-			 * set txed_2_done = txed,
+-			 * so it won't impact rate scale
+-			 */
+-			ba_resp->txed = ba_resp->txed_2_done;
+-		}
+-		IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n",
+-				ba_resp->txed, ba_resp->txed_2_done);
+-	} else {
+-		u64 bitmap, sent_bitmap;
+-
+-		/* don't use 64-bit values for now */
+-		bitmap = le64_to_cpu(ba_resp->bitmap) >> sh;
+-
+-		/* check for success or failure according to the
+-		 * transmitted bitmap and block-ack bitmap */
+-		sent_bitmap = bitmap & agg->bitmap;
+-
+-		/* For each frame attempted in aggregation,
+-		 * update driver's record of tx frame's status. */
+-		i = 0;
+-		while (sent_bitmap) {
+-			ack = sent_bitmap & 1ULL;
+-			successes += ack;
+-			IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n",
+-				ack ? "ACK" : "NACK", i,
+-				(agg->start_idx + i) & 0xff,
+-				agg->start_idx + i);
+-			sent_bitmap >>= 1;
+-			++i;
+-		}
++		ba_resp->txed = ba_resp->txed_2_done;
++	}
++	IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n",
++			ba_resp->txed, ba_resp->txed_2_done);
+ 
+-		IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n",
+-				   (unsigned long long)bitmap);
++	/* Find the first ACKed frame to store the TX status */
++	while (sent_bitmap && !(sent_bitmap & 1)) {
++		agg->start_idx = (agg->start_idx + 1) & 0xff;
++		sent_bitmap >>= 1;
+ 	}
+ 
+ 	info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb);
+ 	memset(&info->status, 0, sizeof(info->status));
+ 	info->flags |= IEEE80211_TX_STAT_ACK;
+ 	info->flags |= IEEE80211_TX_STAT_AMPDU;
+-	if (!priv->cfg->base_params->no_agg_framecnt_info && ba_resp->txed) {
+-		info->status.ampdu_ack_len = ba_resp->txed_2_done;
+-		info->status.ampdu_len = ba_resp->txed;
+-
+-	} else {
+-		info->status.ampdu_ack_len = successes;
+-		info->status.ampdu_len = agg->frame_count;
+-	}
++	info->status.ampdu_ack_len = ba_resp->txed_2_done;
++	info->status.ampdu_len = ba_resp->txed;
+ 	iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info);
+ 
+ 	return 0;
+diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
+index 1f4f6dd18009..3e680af7ff70 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-core.h
++++ b/drivers/net/wireless/iwlwifi/iwl-core.h
+@@ -281,8 +281,6 @@ struct iwl_mod_params {
+  * @chain_noise_calib_by_driver: driver has the capability to perform
+  *	chain noise calibration operation
+  * @shadow_reg_enable: HW shadhow register bit
+- * @no_agg_framecnt_info: uCode do not provide aggregation frame count
+- *	information
+  */
+ struct iwl_base_params {
+ 	int eeprom_size;
+@@ -312,7 +310,6 @@ struct iwl_base_params {
+ 	const bool sensitivity_calib_by_driver;
+ 	const bool chain_noise_calib_by_driver;
+ 	const bool shadow_reg_enable;
+-	const bool no_agg_framecnt_info;
+ };
+ /*
+  * @advanced_bt_coexist: support advanced bt coexist

commit 374920cb0512f5938fdf1f5af4f9afa7502dd0f9
+Author: Daniel Halperin 
+Date:   Wed Mar 16 19:16:36 2011 -0700
+
+    iwlwifi: limit number of attempts for highest HT rate
+    
+    When filling out its rate scale table, iwlwifi repeats the first HT rate
+    IWL_HT_NUMBER_TRY times. The hardware scheduler will stop using
+    aggregation for any frame that fails LINK_QUAL_AGG_DISABLE_START_DEF
+    times. Currently, both these constants equal 3.
+    
+    If iwlwifi probes a faster rate than the link supports, all frames in a
+    (potentially tens of frames large) batch will fail IWL_HT_NUMBER_TRY
+    times. Because this happens to be as large as
+    LINK_QUAL_AGG_DISABLE_START_DEF, all frames will then be sent
+    individually. This leads to a short, but performance-degrading window
+    where the legacy stop-and-wait MAC takes over.
+    
+    Bounding the initial rate by (LINK_QUAL_AGG_DISABLE_START_DEF-1)
+    attempts makes the third try use a lower rate and hence more be likely
+    to succeed. This somewhat mitigates the above described behavior.
+    
+    Signed-off-by: Daniel Halperin 
+    Signed-off-by: Wey-Yi Guy 
+
+diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+index d03b4734c892..63b58ecb0dc6 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
++++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+@@ -2912,7 +2912,8 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
+ 		ant_toggle_cnt = 1;
+ 		repeat_rate = IWL_NUMBER_TRY;
+ 	} else {
+-		repeat_rate = IWL_HT_NUMBER_TRY;
++		repeat_rate = min(IWL_HT_NUMBER_TRY,
++				  LINK_QUAL_AGG_DISABLE_START_DEF - 1);
+ 	}
+ 
+ 	lq_cmd->general_params.mimo_delimiter =

commit 8d5eab5aa676378b4c9daa62d10d08a0bca04677
+Author: Daniel Halperin 
+Date:   Wed Mar 9 03:10:18 2011 -0800
+
+    mac80211: update minstrel_ht sample rate when probe is set
+    
+    Waiting until the status is received can cause the same rate to be
+    probed multiple times consecutively.
+    
+    Cc: Felix Fietkau 
+    Signed-off-by: Daniel Halperin 
+    Signed-off-by: John W. Linville 
+
+diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
+index 775cf155e94b..bce14fbfc3b6 100644
+--- a/net/mac80211/rc80211_minstrel_ht.c
++++ b/net/mac80211/rc80211_minstrel_ht.c
+@@ -415,10 +415,8 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
+ 		mi->sample_count--;
+ 	}
+ 
+-	if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) {
++	if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
+ 		mi->sample_packets += info->status.ampdu_len;
+-		minstrel_next_sample_idx(mi);
+-	}
+ 
+ 	for (i = 0; !last; i++) {
+ 		last = (i == IEEE80211_TX_MAX_RATES - 1) ||
+@@ -551,13 +549,14 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
+ 	sample_idx = sample_table[mg->column][mg->index];
+ 	mr = &mg->rates[sample_idx];
+ 	sample_idx += mi->sample_group * MCS_GROUP_RATES;
++	minstrel_next_sample_idx(mi);
+ 
+ 	/*
+ 	 * When not using MRR, do not sample if the probability is already
+ 	 * higher than 95% to avoid wasting airtime
+ 	 */
+ 	if (!mp->has_mrr && (mr->probability > MINSTREL_FRAC(95, 100)))
+-		goto next;
++		return -1;
+ 
+ 	/*
+ 	 * Make sure that lower rates get sampled only occasionally,
+@@ -566,17 +565,13 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
+ 	if (minstrel_get_duration(sample_idx) >
+ 	    minstrel_get_duration(mi->max_tp_rate)) {
+ 		if (mr->sample_skipped < 20)
+-			goto next;
++			return -1;
+ 
+ 		if (mi->sample_slow++ > 2)
+-			goto next;
++			return -1;
+ 	}
+ 
+ 	return sample_idx;
+-
+-next:
+-	minstrel_next_sample_idx(mi);
+-	return -1;
+ }
+ 
+ static void

commit 278c2f6faafebe28b9776918ce5fbaef9795c141
+Author: Daniel Halperin 
+Date:   Mon Jun 14 13:10:29 2010 -0700
+
+    iwlwifi: update LQ for bcast station on channel change
+    
+    The rate table in the bcast LQ is computed only when the station is
+    allocated, and chooses the lowest rate for the band. Because of when this
+    occurs, this is the 2.4 GHz band and uses the 0x420a (CCK, 1 Mbps) rate. In 5 GHz
+    beaconing mode, this rate will prevent beacons from being sent and any other
+    packets from being received.
+    
+    We can fix this by re-initializing the bcast station's LQ command when the
+    channel is changed.
+    
+    Signed-off-by: Daniel Halperin 
+    Signed-off-by: Reinette Chatre 
+
+diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
+index 24743b97ba35..1daf159914ad 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
++++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
+@@ -217,6 +217,7 @@ static struct iwl_lib_ops iwl1000_lib = {
+ 		.set_ct_kill = iwl1000_set_ct_threshold,
+ 	 },
+ 	.manage_ibss_station = iwlagn_manage_ibss_station,
++	.update_bcast_station = iwl_update_bcast_station,
+ 	.debugfs_ops = {
+ 		.rx_stats_read = iwl_ucode_rx_stats_read,
+ 		.tx_stats_read = iwl_ucode_tx_stats_read,
+diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
+index 67526a1be025..1dd3bc4c107e 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
++++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
+@@ -2280,6 +2280,7 @@ static struct iwl_lib_ops iwl4965_lib = {
+ 		.set_ct_kill = iwl4965_set_ct_threshold,
+ 	},
+ 	.manage_ibss_station = iwlagn_manage_ibss_station,
++	.update_bcast_station = iwl_update_bcast_station,
+ 	.debugfs_ops = {
+ 		.rx_stats_read = iwl_ucode_rx_stats_read,
+ 		.tx_stats_read = iwl_ucode_tx_stats_read,
+diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
+index fa2dbb56177c..b8f3e20f2c80 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
++++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
+@@ -393,6 +393,7 @@ static struct iwl_lib_ops iwl5000_lib = {
+ 		.set_ct_kill = iwl5000_set_ct_threshold,
+ 	 },
+ 	.manage_ibss_station = iwlagn_manage_ibss_station,
++	.update_bcast_station = iwl_update_bcast_station,
+ 	.debugfs_ops = {
+ 		.rx_stats_read = iwl_ucode_rx_stats_read,
+ 		.tx_stats_read = iwl_ucode_tx_stats_read,
+@@ -455,6 +456,7 @@ static struct iwl_lib_ops iwl5150_lib = {
+ 		.set_ct_kill = iwl5150_set_ct_threshold,
+ 	 },
+ 	.manage_ibss_station = iwlagn_manage_ibss_station,
++	.update_bcast_station = iwl_update_bcast_station,
+ 	.debugfs_ops = {
+ 		.rx_stats_read = iwl_ucode_rx_stats_read,
+ 		.tx_stats_read = iwl_ucode_tx_stats_read,
+diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
+index c909a9c5e5e1..61cf0b3e88c2 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
++++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
+@@ -318,6 +318,7 @@ static struct iwl_lib_ops iwl6000_lib = {
+ 		.set_calib_version = iwl6000_set_calib_version,
+ 	 },
+ 	.manage_ibss_station = iwlagn_manage_ibss_station,
++	.update_bcast_station = iwl_update_bcast_station,
+ 	.debugfs_ops = {
+ 		.rx_stats_read = iwl_ucode_rx_stats_read,
+ 		.tx_stats_read = iwl_ucode_tx_stats_read,
+diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
+index 329e5107b5c3..f47a58ff3252 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-core.c
++++ b/drivers/net/wireless/iwlwifi/iwl-core.c
+@@ -2110,6 +2110,9 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
+ 		iwl_set_flags_for_band(priv, conf->channel->band, priv->vif);
+ 		spin_unlock_irqrestore(&priv->lock, flags);
+ 
++		if (priv->cfg->ops->lib->update_bcast_station)
++			ret = priv->cfg->ops->lib->update_bcast_station(priv);
++
+  set_ch_out:
+ 		/* The list of supported rates and rate mask can be different
+ 		 * for each band; since the band may have changed, reset
+diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
+index cdcb51d8bc21..15930e064022 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-core.h
++++ b/drivers/net/wireless/iwlwifi/iwl-core.h
+@@ -196,6 +196,7 @@ struct iwl_lib_ops {
+ 	/* station management */
+ 	int (*manage_ibss_station)(struct iwl_priv *priv,
+ 				   struct ieee80211_vif *vif, bool add);
++	int (*update_bcast_station)(struct iwl_priv *priv);
+ 	/* recover from tx queue stall */
+ 	void (*recover_from_tx_stall)(unsigned long data);
+ 	/* check for plcp health */
+diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
+index 6a9cd08bd449..9511f03f07e0 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
++++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
+@@ -1259,6 +1259,36 @@ int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq)
+ }
+ EXPORT_SYMBOL_GPL(iwl_alloc_bcast_station);
+ 
++/**
++ * iwl_update_bcast_station - update broadcast station's LQ command
++ *
++ * Only used by iwlagn. Placed here to have all bcast station management
++ * code together.
++ */
++int iwl_update_bcast_station(struct iwl_priv *priv)
++{
++	unsigned long flags;
++	struct iwl_link_quality_cmd *link_cmd;
++	u8 sta_id = priv->hw_params.bcast_sta_id;
++
++	link_cmd = iwl_sta_alloc_lq(priv, sta_id);
++	if (!link_cmd) {
++		IWL_ERR(priv, "Unable to initialize rate scaling for bcast station.\n");
++		return -ENOMEM;
++	}
++
++	spin_lock_irqsave(&priv->sta_lock, flags);
++	if (priv->stations[sta_id].lq)
++		kfree(priv->stations[sta_id].lq);
++	else
++		IWL_DEBUG_INFO(priv, "Bcast station rate scaling has not been initialized yet.\n");
++	priv->stations[sta_id].lq = link_cmd;
++	spin_unlock_irqrestore(&priv->sta_lock, flags);
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(iwl_update_bcast_station);
++
+ void iwl_dealloc_bcast_station(struct iwl_priv *priv)
+ {
+ 	unsigned long flags;
+diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
+index 619bb99d85cf..ba95b1a590a5 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-sta.h
++++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
+@@ -60,6 +60,7 @@ void iwl_restore_stations(struct iwl_priv *priv);
+ void iwl_clear_ucode_stations(struct iwl_priv *priv);
+ int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq);
+ void iwl_dealloc_bcast_station(struct iwl_priv *priv);
++int iwl_update_bcast_station(struct iwl_priv *priv);
+ int iwl_get_free_ucode_key_index(struct iwl_priv *priv);
+ int iwl_send_add_sta(struct iwl_priv *priv,
+ 		     struct iwl_addsta_cmd *sta, u8 flags);

commit f668da2f150948a961d359c65b5e9d62da1290e2
+Author: Daniel Halperin 
+Date:   Tue May 25 10:22:49 2010 -0700
+
+    iwlwifi: fix wrapping when handling aggregated batches
+    
+    Fairly complex code in iwlagn_tx_status_reply_tx handle the status reports for
+    aggregated packet batches sent by the NIC. This code aims to handle the case
+    where the NIC retransmits failed packets from a previous batch; the status
+    information for these packets can sometimes be inserted in the middle of a
+    batch and are actually not in order by sequence number! (I verified this can
+    happen with printk's in the function.)
+    
+    The code in question adaptively identifies the "first" frame of the batch,
+    taking into account that it may not be the one corresponding to the first agg
+    status report, and also handles the case when the set of sent packets wraps the
+    256-character entry buffer. It generates the agg->bitmap field of sent packets
+    which is later compared to the BlockAck response from the receiver to see which
+    frames of those sent in this batch were ACKed. A small logic error (wrapping by
+    0xff==255 instead of 0x100==256) was causing the agg->bitmap to be set
+    incorrectly.
+    
+    Fix this wrapping code, and add extensive comments to clarify what is going on.
+    
+    Signed-off-by: Daniel Halperin 
+    Signed-off-by: Reinette Chatre 
+
+diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+index d339881e1d8f..3577c1eeb77b 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
++++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+@@ -93,6 +93,12 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv,
+ 	} else {
+ 		/* Two or more frames were attempted; expect block-ack */
+ 		u64 bitmap = 0;
++
++		/*
++		 * Start is the lowest frame sent. It may not be the first
++		 * frame in the batch; we figure this out dynamically during
++		 * the following loop.
++		 */
+ 		int start = agg->start_idx;
+ 
+ 		/* Construct bit-map of pending frames within Tx window */
+@@ -131,25 +137,58 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv,
+ 			IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n",
+ 					   i, idx, SEQ_TO_SN(sc));
+ 
++			/*
++			 * sh -> how many frames ahead of the starting frame is
++			 * the current one?
++			 *
++			 * Note that all frames sent in the batch must be in a
++			 * 64-frame window, so this number should be in [0,63].
++			 * If outside of this window, then we've found a new
++			 * "first" frame in the batch and need to change start.
++			 */
+ 			sh = idx - start;
+-			if (sh > 64) {
+-				sh = (start - idx) + 0xff;
++
++			/*
++			 * If >= 64, out of window. start must be at the front
++			 * of the circular buffer, idx must be near the end of
++			 * the buffer, and idx is the new "first" frame. Shift
++			 * the indices around.
++			 */
++			if (sh >= 64) {
++				/* Shift bitmap by start - idx, wrapped */
++				sh = 0x100 - idx + start;
+ 				bitmap = bitmap << sh;
++				/* Now idx is the new start so sh = 0 */
+ 				sh = 0;
+ 				start = idx;
+-			} else if (sh < -64)
+-				sh  = 0xff - (start - idx);
+-			else if (sh < 0) {
++			/*
++			 * If <= -64 then wraps the 256-pkt circular buffer
++			 * (e.g., start = 255 and idx = 0, sh should be 1)
++			 */
++			} else if (sh <= -64) {
++				sh  = 0x100 - start + idx;
++			/*
++			 * If < 0 but > -64, out of window. idx is before start
++			 * but not wrapped. Shift the indices around.
++			 */
++			} else if (sh < 0) {
++				/* Shift by how far start is ahead of idx */
+ 				sh = start - idx;
+-				start = idx;
+ 				bitmap = bitmap << sh;
++				/* Now idx is the new start so sh = 0 */
++				start = idx;
+ 				sh = 0;
+ 			}
++			/* Sequence number start + sh was sent in this batch */
+ 			bitmap |= 1ULL << sh;
+ 			IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n",
+ 					   start, (unsigned long long)bitmap);
+ 		}
+ 
++		/*
++		 * Store the bitmap and possibly the new start, if we wrapped
++		 * the buffer above
++		 */
+ 		agg->bitmap = bitmap;
+ 		agg->start_idx = start;
+ 		IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n",

commit 02cd8dee6e10d6ab7161a3c6f36a60f8894fafdd
+Author: Daniel Halperin 
+Date:   Mon May 24 18:41:30 2010 -0700
+
+    iwlwifi: parse block ack responses correctly
+    
+    Compressed BlockAck frames store the ACKs/NACKs in a 64-bit bitmap that starts
+    at the sequence number of the first frame sent in the aggregated batch. Note
+    that this is a selective ACKnowledgement following selective retransmission;
+    e.g., if frames 1,4-5 in a batch are ACKed then the next transmission will
+    include frames 2-3,6-10 (7 frames). In this latter case, the Compressed
+    BlockAck will not have all meaningful information in the low order bits -- the
+    semantically meaningful bits of the BA will be 0x1f3 (where the low-order frame
+    is seq 2).
+    
+    The driver code originally just looked at the lower (in this case, 7) bits of
+    the BlockAck. In this case, the lower 7 bits of 0x1f3 => only 5 packets,
+    maximum, could ever be ACKed. In reality it should be looking at all of the
+    bits, filtered by those corresponding to packets that were actually sent. This
+    flaw meant that the number of correctly ACked packets could be significantly
+    underreported and might result in asynchronous state between TX and RX sides as
+    well as driver and uCode.
+    
+    Fix this and also add a shortcut that doesn't require the code to loop through
+    all 64 bits of the bitmap but rather stops when no higher packets are ACKed.
+    
+    In my experiments this fix greatly reduces throughput swing, making throughput
+    stable and high. It is also likely related to some of the stalls observed in
+    aggregation mode and maybe some of the buffer underruns observed, e.g.,
+    
+    http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=1968
+    http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2098
+    http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2018
+    
+    Signed-off-by: Daniel Halperin 
+    Signed-off-by: Reinette Chatre 
+
+diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+index 0d3e13b2442f..10a0acdb9dd4 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
++++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+@@ -1208,7 +1208,7 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv,
+ 	int i, sh, ack;
+ 	u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl);
+ 	u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
+-	u64 bitmap;
++	u64 bitmap, sent_bitmap;
+ 	int successes = 0;
+ 	struct ieee80211_tx_info *info;
+ 
+@@ -1236,16 +1236,19 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv,
+ 
+ 	/* check for success or failure according to the
+ 	 * transmitted bitmap and block-ack bitmap */
+-	bitmap &= agg->bitmap;
++	sent_bitmap = bitmap & agg->bitmap;
+ 
+ 	/* For each frame attempted in aggregation,
+ 	 * update driver's record of tx frame's status. */
+-	for (i = 0; i < agg->frame_count ; i++) {
+-		ack = bitmap & (1ULL << i);
+-		successes += !!ack;
++	i = 0;
++	while (sent_bitmap) {
++		ack = sent_bitmap & 1ULL;
++		successes += ack;
+ 		IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n",
+ 			ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff,
+ 			agg->start_idx + i);
++		sent_bitmap >>= 1;
++		++i;
+ 	}
+ 
+ 	info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb);

commit e3a3cd8789e1daf1b5af70d3252cab50cd3824c9
+Author: Daniel Halperin 
+Date:   Sun Apr 18 09:27:58 2010 -0700
+
+    iwlwifi: set AMPDU status variables correctly
+    
+    The TX status code is currently abusing the ampdu_ack_map field (a bitmap) to
+    count the number of successfully received frames.  The comments in mac80211.h
+    show there are actually three different, relevant variables, of which we are
+    currently using two, both incorrectly. Fix this by making
+    
+    - ampdu_ack_len -> the number of ACKed frames (i.e. successes)
+    - ampdu_ack_map -> the bitmap
+    - ampdu_len -> the total number of frames sent (i.e., attempts)
+    
+    to match the header file (and verified with ath9k's usage) and updating Intel's
+    RS code to match.
+    
+    Signed-off-by: Daniel Halperin 
+    Signed-off-by: Reinette Chatre 
+
+diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+index 8f8d5e3e688d..f01f242659c3 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
++++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+@@ -867,14 +867,14 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
+ 		rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type,
+ 				&rs_index);
+ 		rs_collect_tx_data(curr_tbl, rs_index,
+-				   info->status.ampdu_ack_len,
+-				   info->status.ampdu_ack_map);
++				   info->status.ampdu_len,
++				   info->status.ampdu_ack_len);
+ 
+ 		/* Update success/fail counts if not searching for new mode */
+ 		if (lq_sta->stay_in_tbl) {
+-			lq_sta->total_success += info->status.ampdu_ack_map;
+-			lq_sta->total_failed += (info->status.ampdu_ack_len -
+-					info->status.ampdu_ack_map);
++			lq_sta->total_success += info->status.ampdu_ack_len;
++			lq_sta->total_failed += (info->status.ampdu_len -
++					info->status.ampdu_ack_len);
+ 		}
+ 	} else {
+ 	/*
+diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+index 95e263f1d117..c2a5c85542bf 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
++++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+@@ -1233,8 +1233,9 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv,
+ 	memset(&info->status, 0, sizeof(info->status));
+ 	info->flags |= IEEE80211_TX_STAT_ACK;
+ 	info->flags |= IEEE80211_TX_STAT_AMPDU;
+-	info->status.ampdu_ack_map = successes;
+-	info->status.ampdu_ack_len = agg->frame_count;
++	info->status.ampdu_ack_len = successes;
++	info->status.ampdu_ack_map = bitmap;
++	info->status.ampdu_len = agg->frame_count;
+ 	iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info);
+ 
+ 	IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", (unsigned long long)bitmap);

commit 93d95b12b3ba06e0e1f3e43a370ee61539d8cb90
+Author: Daniel Halperin 
+Date:   Sun Apr 18 09:28:18 2010 -0700
+
+    mac80211: fix typo in comments
+    
+    The flag is called IEEE80211_TX_STAT_AMPDU rather than using the whole word
+    STATUS.
+    
+    Signed-off-by: Daniel Halperin 
+    Signed-off-by: John W. Linville 
+
+diff --git a/include/net/mac80211.h b/include/net/mac80211.h
+index 75056dde3817..c49e6adcd8fa 100644
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -397,11 +397,11 @@ struct ieee80211_tx_rate {
+  * @status: union for status data
+  * @driver_data: array of driver_data pointers
+  * @ampdu_ack_len: number of acked aggregated frames.
+- * 	relevant only if IEEE80211_TX_STATUS_AMPDU was set.
++ * 	relevant only if IEEE80211_TX_STAT_AMPDU was set.
+  * @ampdu_ack_map: block ack bit map for the aggregation.
+- * 	relevant only if IEEE80211_TX_STATUS_AMPDU was set.
++ * 	relevant only if IEEE80211_TX_STAT_AMPDU was set.
+  * @ampdu_len: number of aggregated frames.
+- * 	relevant only if IEEE80211_TX_STATUS_AMPDU was set.
++ * 	relevant only if IEEE80211_TX_STAT_AMPDU was set.
+  * @ack_signal: signal strength of the ACK frame
+  */
+ struct ieee80211_tx_info {

commit 5e2f75b8993a0d83d469388b50716dd5551f2eb4
+Author: Dan Halperin 
+Date:   Thu Feb 18 22:01:39 2010 -0800
+
+    iwlwifi: set HT flags after channel in rxon
+    
+    The HT extension channel settings require priv->staging_rxon.channel to be
+    accurate. However, iwl_set_rxon_ht was being called before iwl_set_rxon_channel
+    and thus HT40 could be broken unless another call to iwl_mac_config came in.
+    
+    This problem was recently introduced by "iwlwifi: Fix to set correct ht
+    configuration"
+    
+    The particular setting in which I noticed this was monitor mode:
+    
+            iwconfig wlan0 mode monitor
+            ifconfig wlan0 up
+            ./iw wlan0 set channel 64 HT40-
+            #./iw wlan0 set channel 64 HT40-
+            tcpdump -i wlan0 -y IEEE802_11_RADIO
+    
+    would only catch HT40 packets if I issued the IW command twice.
+    
+    From visual inspection, iwl_set_rxon_channel does not depend on
+    iwl_set_rxon_ht, so simply swapping them should be safe and fixes this problem.
+    
+    Signed-off-by: Daniel Halperin 
+    Acked-by: Wey-Yi Guy 
+    Signed-off-by: Reinette Chatre 
+    CC: stable@kernel.org
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
+index d10bea64fce3..f36f804804fc 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-core.c
++++ b/drivers/net/wireless/iwlwifi/iwl-core.c
+@@ -2744,8 +2744,8 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
+ 		if ((le16_to_cpu(priv->staging_rxon.channel) != ch))
+ 			priv->staging_rxon.flags = 0;
+ 
+-		iwl_set_rxon_ht(priv, ht_conf);
+ 		iwl_set_rxon_channel(priv, conf->channel);
++		iwl_set_rxon_ht(priv, ht_conf);
+ 
+ 		iwl_set_flags_for_band(priv, conf->channel->band);
+ 		spin_unlock_irqrestore(&priv->lock, flags);

commit 49dcc819b077c2d473062e17d5a1373a8b660e02
+Author: Daniel Halperin 
+Date:   Tue Jan 19 10:22:19 2010 -0800
+
+    iwlwifi: optimize power saving
+    
+    In hostap AP mode, every time the client sends the AP
+    a packet the STA_NOTIFY_AWAKE code is sent from mac80211.
+    This results in a command being sent to the uCode even if
+    the client was not asleep.
+    
+    The following simple patch has fixed the issue for me without any
+    degradation that I can find.
+    
+    Signed-off-by: Daniel Halperin 
+    Acked-by: Johannes Berg 
+    Signed-off-by: Reinette Chatre 
+
+diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
+index 4a268927377b..380d2087bf3a 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
++++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
+@@ -3007,6 +3007,8 @@ static void iwl_mac_sta_notify(struct ieee80211_hw *hw,
+ 		break;
+ 	case STA_NOTIFY_AWAKE:
+ 		WARN_ON(!sta_priv->client);
++		if (!sta_priv->asleep)
++			break;
+ 		sta_priv->asleep = false;
+ 		sta_id = iwl_find_station(priv, sta->addr);
+ 		if (sta_id != IWL_INVALID_STATION)

commit ff27fabe62d288038b36f41ac6a2190ed7d15993
+Author: Daniel Halperin 
+Date:   Fri Jan 22 14:22:58 2010 -0800
+
+    iwlwifi: fix throughput degradation in aggregation mode
+    
+    The following commit
+    
+            commit e4da8c37af626001ff704fb29ea14eb58f5f7208
+            Author: Johannes Berg 
+            Date:   Wed Dec 23 13:15:43 2009 +0100
+    
+               mac80211: make off-channel work generic
+    
+    triggered a bug in iwlwifi where HT parameters would not be correctly set in
+    some mac80211 pathways. The aggregation (and possibly other) station flags were
+    not being set, which limited the size of aggregation blocks and reduced
+    throughput at high rates.
+    
+    >From Johannes:
+    """
+    Due to Wey-Yi's patch to use the set-channel command when the channel changes
+    while associated, we don't get a full new RXON. Therefore, we don't re-set the
+    rxon-station either. However, under some circumstances that apparently have
+    gotten more likely mac80211 will first set up the BSS info, then add the
+    station and then switch to an HT channel type.
+    
+    Therefore, the check for "priv->current_ht_config.is_ht" in
+    iwl_rxon_add_station() will hit false and not fill in the HT information.
+    
+    However, that check can just be removed, which is the easiest fix for all this,
+    because the HT capa struct is always there, just could possibly have the
+    ht_supported member set to false.
+    """
+    
+    A sample good link in my 3x3 network improves by approximately 25% TCP
+    throughput. This fixes Bug 2144
+    (http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2144).
+    
+    Signed-off-by: Daniel Halperin 
+    Signed-off-by: Reinette Chatre 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
+index fcac73cf82bc..e0b13fb78653 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
++++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
+@@ -1045,24 +1045,19 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap)
+ 	struct ieee80211_sta_ht_cap *cur_ht_config = NULL;
+ 	u8 sta_id;
+ 
+-	/* Add station to device's station table */
+-
+ 	/*
+-	 * XXX: This check is definitely not correct, if we're an AP
+-	 *	it'll always be false which is not what we want, but
+-	 *	it doesn't look like iwlagn is prepared to be an HT
+-	 *	AP anyway.
++	 * Set HT capabilities. It is ok to set this struct even if not using
++	 * HT config: the priv->current_ht_config.is_ht flag will just be false
+ 	 */
+-	if (priv->current_ht_config.is_ht) {
+-		rcu_read_lock();
+-		sta = ieee80211_find_sta(priv->vif, addr);
+-		if (sta) {
+-			memcpy(&ht_config, &sta->ht_cap, sizeof(ht_config));
+-			cur_ht_config = &ht_config;
+-		}
+-		rcu_read_unlock();
++	rcu_read_lock();
++	sta = ieee80211_find_sta(priv->vif, addr);
++	if (sta) {
++		memcpy(&ht_config, &sta->ht_cap, sizeof(ht_config));
++		cur_ht_config = &ht_config;
+ 	}
++	rcu_read_unlock();
+ 
++	/* Add station to device's station table */
+ 	sta_id = iwl_add_station(priv, addr, is_ap, CMD_SYNC, cur_ht_config);
+ 
+ 	/* Set up default rate scaling table in device's station table */

commit 0c875c28649eac0adb8d2e2efac2186c3089e100
+Author: David Rientjes 
+Date:   Sun Dec 3 11:55:34 2006 -0800
+
+    PCI quirks: remove redundant check
+    
+    Removes redundant check for dev->subordinate; if it is NULL, the function
+    returns before the patch-affected code region.
+    
+    Signed-off-by: David Rientjes 
+    Acked-by: Brice Goglin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
+index 9ca9b9bf6160..757186390d83 100644
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -1688,8 +1688,7 @@ static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev)
+ 	 * a single one having MSI is enough to be sure that MSI are supported.
+ 	 */
+ 	pdev = pci_get_slot(dev->bus, 0);
+-	if (dev->subordinate && !msi_ht_cap_enabled(dev)
+-	    && !msi_ht_cap_enabled(pdev)) {
++	if (!msi_ht_cap_enabled(dev) && !msi_ht_cap_enabled(pdev)) {
+ 		printk(KERN_WARNING "PCI: MSI quirk detected. "
+ 		       "MSI disabled on chipset %s.\n",
+ 		       pci_name(dev));

commit b860e73a5488d9e75c2f2907174cb4277c2f9d21
+Author: David Rientjes 
+Date:   Fri Dec 8 02:40:19 2006 -0800
+
+    [PATCH] video SiS: remove unnecessary variables in SiS_DDC2Delay
+    
+    Remove unnecesary iteration and accumulator variables from SiS_DDC2Delay.
+    
+    Originally spotted by Jesper Juhl .
+    
+    Cc: Jesper Juhl 
+    Cc: Thomas Winischhofer 
+    Signed-off-by: David Rientjes 
+    Cc: "Antonino A. Daplas" 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/video/sis/init301.c b/drivers/video/sis/init301.c
+index f13faddc6181..47e1896cffeb 100644
+--- a/drivers/video/sis/init301.c
++++ b/drivers/video/sis/init301.c
+@@ -445,11 +445,8 @@ SiS_CR36BIOSWord23d(struct SiS_Private *SiS_Pr)
+ void
+ SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime)
+ {
+-   unsigned int i, j;
+-
+-   for(i = 0; i < delaytime; i++) {
+-      j += SiS_GetReg(SiS_Pr->SiS_P3c4,0x05);
+-   }
++   while (delaytime-- > 0)
++      SiS_GetReg(SiS_Pr->SiS_P3c4, 0x05);
+ }
+ 
+ #if defined(SIS300) || defined(SIS315H)

commit a09c17a6fdad9ae5b5ea1c3383080f84ec76ab20
+Author: David Rientjes 
+Date:   Wed Dec 6 20:40:18 2006 -0800
+
+    [PATCH] sys: remove unused variable
+    
+    Remove unused 'new_ruid' variable.
+    
+    Reported by David Binderman .
+    
+    Signed-off-by: David Rientjes 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/kernel/sys.c b/kernel/sys.c
+index c87b461de38d..a0c1a29a507f 100644
+--- a/kernel/sys.c
++++ b/kernel/sys.c
+@@ -1102,14 +1102,14 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
+ asmlinkage long sys_setuid(uid_t uid)
+ {
+ 	int old_euid = current->euid;
+-	int old_ruid, old_suid, new_ruid, new_suid;
++	int old_ruid, old_suid, new_suid;
+ 	int retval;
+ 
+ 	retval = security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_ID);
+ 	if (retval)
+ 		return retval;
+ 
+-	old_ruid = new_ruid = current->uid;
++	old_ruid = current->uid;
+ 	old_suid = current->suid;
+ 	new_suid = old_suid;
+ 	

commit 8de61e69c2feb10e5391cca67a3faf1d2bf77ce0
+Author: David Rientjes 
+Date:   Wed Dec 6 20:40:16 2006 -0800
+
+    [PATCH] fs: remove unused variable
+    
+    Removed unused 'have_pt_gnu_stack' variable.
+    
+    Reported by David Binderman 
+    
+    Signed-off-by: David Rientjes 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
+index 14ea630a857c..be5869d34999 100644
+--- a/fs/binfmt_elf.c
++++ b/fs/binfmt_elf.c
+@@ -544,7 +544,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
+ 	unsigned long reloc_func_desc = 0;
+ 	char passed_fileno[6];
+ 	struct files_struct *files;
+-	int have_pt_gnu_stack, executable_stack = EXSTACK_DEFAULT;
++	int executable_stack = EXSTACK_DEFAULT;
+ 	unsigned long def_flags = 0;
+ 	struct {
+ 		struct elfhdr elf_ex;
+@@ -707,7 +707,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
+ 				executable_stack = EXSTACK_DISABLE_X;
+ 			break;
+ 		}
+-	have_pt_gnu_stack = (i < loc->elf_ex.e_phnum);
+ 
+ 	/* Some simple consistency checks for the interpreter */
+ 	if (elf_interpreter) {

commit f475ff352c5e05d473c462b97c3a13a5b803af5a
+Author: David Rientjes 
+Date:   Thu Dec 7 02:14:13 2006 +0100
+
+    [PATCH] x86-64: remove unused variable
+    
+    Remove unused variable in msr_write().
+    
+    Reported by D Binderman .
+    
+    Cc: H. Peter Anvin 
+    Signed-off-by: David Rientjes 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Andi Kleen 
+
+diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c
+index a773f776c9ea..fd45059c9084 100644
+--- a/arch/i386/kernel/msr.c
++++ b/arch/i386/kernel/msr.c
+@@ -195,7 +195,6 @@ static ssize_t msr_write(struct file *file, const char __user *buf,
+ {
+ 	const u32 __user *tmp = (const u32 __user *)buf;
+ 	u32 data[2];
+-	size_t rv;
+ 	u32 reg = *ppos;
+ 	int cpu = iminor(file->f_dentry->d_inode);
+ 	int err;
+@@ -203,7 +202,7 @@ static ssize_t msr_write(struct file *file, const char __user *buf,
+ 	if (count % 8)
+ 		return -EINVAL;	/* Invalid chunk size */
+ 
+-	for (rv = 0; count; count -= 8) {
++	for (; count; count -= 8) {
+ 		if (copy_from_user(&data, tmp, 8))
+ 			return -EFAULT;
+ 		err = do_wrmsr(cpu, reg, data[0], data[1]);

commit 86bd58bf4c383fde4e99b83ce917b091a072040d
+Author: David Rientjes 
+Date:   Thu Dec 7 02:14:11 2006 +0100
+
+    [PATCH] x86-64: Remove unused GET_APIC_VERSION call from clear_local_APIC
+    
+    Remove unused GET_APIC_VERSION call from clear_local_APIC() and
+    __setup_APIC_LVTT().
+    
+    Reported by D Binderman .
+    
+    Cc: Andi Kleen 
+    Cc: Ingo Molnar 
+    Signed-off-by: David Rientjes 
+    Signed-off-by: Andi Kleen 
+
+diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
+index f0b00d8731cb..124b2d27b4ac 100644
+--- a/arch/x86_64/kernel/apic.c
++++ b/arch/x86_64/kernel/apic.c
+@@ -140,7 +140,6 @@ void clear_local_APIC(void)
+ 		apic_write(APIC_LVTERR, APIC_LVT_MASKED);
+ 	if (maxlvt >= 4)
+ 		apic_write(APIC_LVTPC, APIC_LVT_MASKED);
+-	v = GET_APIC_VERSION(apic_read(APIC_LVR));
+ 	apic_write(APIC_ESR, 0);
+ 	apic_read(APIC_ESR);
+ }
+@@ -736,10 +735,9 @@ void __init init_apic_mappings(void)
+ 
+ static void __setup_APIC_LVTT(unsigned int clocks)
+ {
+-	unsigned int lvtt_value, tmp_value, ver;
++	unsigned int lvtt_value, tmp_value;
+ 	int cpu = smp_processor_id();
+ 
+-	ver = GET_APIC_VERSION(apic_read(APIC_LVR));
+ 	lvtt_value = APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR;
+ 
+ 	if (cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask))

commit 3529833f1ca8790df06ce218b5d9d438776696ed
+Author: David Rientjes 
+Date:   Thu Dec 7 02:14:07 2006 +0100
+
+    [PATCH] i386: substitute __va lookup with pfn_to_kaddr
+    
+    Substitutes allocate_pgdat virtual address lookup with pfn_to_kaddr macro.
+    
+    Signed-off-by: David Rientjes 
+    Signed-off-by: Andi Kleen 
+    Cc: Andi Kleen 
+    Signed-off-by: Andrew Morton 
+
+diff --git a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c
+index ddbdb0336f28..103b76e56a94 100644
+--- a/arch/i386/mm/discontig.c
++++ b/arch/i386/mm/discontig.c
+@@ -168,7 +168,7 @@ static void __init allocate_pgdat(int nid)
+ 	if (nid && node_has_online_mem(nid))
+ 		NODE_DATA(nid) = (pg_data_t *)node_remap_start_vaddr[nid];
+ 	else {
+-		NODE_DATA(nid) = (pg_data_t *)(__va(min_low_pfn << PAGE_SHIFT));
++		NODE_DATA(nid) = (pg_data_t *)(pfn_to_kaddr(min_low_pfn));
+ 		min_low_pfn += PFN_UP(sizeof(pg_data_t));
+ 	}
+ }

commit 92b1f905637bbd79fcd430a09737fd97061eb405
+Author: David Rientjes 
+Date:   Wed Nov 8 19:49:15 2006 -0800
+
+    [PATCH] drivers cris: return on NULL dev_alloc_skb()
+    
+    If the next descriptor array entry cannot be allocated by dev_alloc_skb(),
+    return immediately so it is not dereferenced later.  We cannot register the
+    device with a partial descriptor list.
+    
+    Cc: Mikael Starvik 
+    Signed-off-by: David Rientjes 
+    Cc: Jeff Garzik 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Jeff Garzik 
+
+diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c
+index 966b563e42bb..a03d781f6d0a 100644
+--- a/drivers/net/cris/eth_v10.c
++++ b/drivers/net/cris/eth_v10.c
+@@ -509,6 +509,8 @@ etrax_ethernet_init(void)
+ 		 * does not share cacheline with any other data (to avoid cache bug)
+ 		 */
+ 		RxDescList[i].skb = dev_alloc_skb(MAX_MEDIA_DATA_SIZE + 2 * L1_CACHE_BYTES);
++		if (!RxDescList[i].skb)
++			return -ENOMEM;
+ 		RxDescList[i].descr.ctrl   = 0;
+ 		RxDescList[i].descr.sw_len = MAX_MEDIA_DATA_SIZE;
+ 		RxDescList[i].descr.next   = virt_to_phys(&RxDescList[i + 1]);

commit 2ceaac755423cb93c1bb2f59ebd1a06f027ac095
+Author: David Rientjes 
+Date:   Mon Oct 30 14:19:25 2006 -0800
+
+    [PATCH] net s2io: return on NULL dev_alloc_skb()
+    
+    Checks for NULL dev_alloc_skb() and returns on true to avoid subsequent
+    dereference.
+    
+    Cc: Jeff Garzik 
+    Cc: Christoph Hellwig 
+    Signed-off-by: David Rientjes 
+    Signed-off-by: Jeff Garzik 
+
+diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
+index a231ab7d28dd..33569ec9dbfc 100644
+--- a/drivers/net/s2io.c
++++ b/drivers/net/s2io.c
+@@ -5985,6 +5985,11 @@ static int set_rxd_buffer_pointer(nic_t *sp, RxD_t *rxdp, buffAdd_t *ba,
+ 			((RxD3_t*)rxdp)->Buffer1_ptr = *temp1;
+ 		} else {
+ 			*skb = dev_alloc_skb(size);
++			if (!(*skb)) {
++				DBG_PRINT(ERR_DBG, "%s: dev_alloc_skb failed\n",
++					  dev->name);
++				return -ENOMEM;
++			}
+ 			((RxD3_t*)rxdp)->Buffer2_ptr = *temp2 =
+ 				pci_map_single(sp->pdev, (*skb)->data,
+ 					       dev->mtu + 4,
+@@ -6007,7 +6012,11 @@ static int set_rxd_buffer_pointer(nic_t *sp, RxD_t *rxdp, buffAdd_t *ba,
+ 			((RxD3_t*)rxdp)->Buffer2_ptr = *temp2;
+ 		} else {
+ 			*skb = dev_alloc_skb(size);
+-
++			if (!(*skb)) {
++				DBG_PRINT(ERR_DBG, "%s: dev_alloc_skb failed\n",
++					  dev->name);
++				return -ENOMEM;
++			}
+ 			((RxD3_t*)rxdp)->Buffer0_ptr = *temp0 =
+ 				pci_map_single(sp->pdev, ba->ba_0, BUF0_LEN,
+ 					       PCI_DMA_FROMDEVICE);

commit f3ef9ead31ae995251b420ac98398bd7545bf4e1
+Author: David Rientjes 
+Date:   Mon Sep 25 16:24:57 2006 -0700
+
+    [PATCH] do not free non slab allocated per_cpu_pageset
+    
+    Stops panic associated with attempting to free a non slab-allocated
+    per_cpu_pageset.
+    
+    Signed-off-by: David Rientjes 
+    Acked-by: Christoph Lameter 
+    Cc: 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/mm/page_alloc.c b/mm/page_alloc.c
+index 3b5358a0561f..8a52ba9fe693 100644
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -1845,8 +1845,10 @@ static inline void free_zone_pagesets(int cpu)
+ 	for_each_zone(zone) {
+ 		struct per_cpu_pageset *pset = zone_pcp(zone, cpu);
+ 
++		/* Free per_cpu_pageset if it is slab allocated */
++		if (pset != &boot_pageset[cpu])
++			kfree(pset);
+ 		zone_pcp(zone, cpu) = NULL;
+-		kfree(pset);
+ 	}
+ }
+ 

commit 62fe78e90dc25b269362034487dc450cd8453e8c
+Author: Sam Revitch 
+Date:   Wed May 10 15:09:17 2006 +0200
+
+    [ALSA] hda-codec - Add support for Apple Mac Mini (early 2006)
+    
+    Add support for some audio quirks of the Apple Mac Mini (early 2006)
+    
+    Signed-off-by: Sam Revitch 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
+index 6d8224dc033b..36f199442fdc 100644
+--- a/sound/pci/hda/patch_sigmatel.c
++++ b/sound/pci/hda/patch_sigmatel.c
+@@ -41,6 +41,7 @@
+ #define STAC_REF		0
+ #define STAC_D945GTP3		1
+ #define STAC_D945GTP5		2
++#define STAC_MACMINI		3
+ 
+ struct sigmatel_spec {
+ 	struct snd_kcontrol_new *mixers[4];
+@@ -52,6 +53,7 @@ struct sigmatel_spec {
+ 	unsigned int mic_switch: 1;
+ 	unsigned int alt_switch: 1;
+ 	unsigned int hp_detect: 1;
++	unsigned int gpio_mute: 1;
+ 
+ 	/* playback */
+ 	struct hda_multi_out multiout;
+@@ -293,6 +295,7 @@ static unsigned int *stac922x_brd_tbl[] = {
+ 	ref922x_pin_configs,
+ 	d945gtp3_pin_configs,
+ 	d945gtp5_pin_configs,
++	NULL,		/* STAC_MACMINI */
+ };
+ 
+ static struct hda_board_config stac922x_cfg_tbl[] = {
+@@ -324,6 +327,9 @@ static struct hda_board_config stac922x_cfg_tbl[] = {
+ 	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
+ 	  .pci_subdevice = 0x0417,
+ 	  .config = STAC_D945GTP5 },	/* Intel D975XBK - 5 Stack */
++	{ .pci_subvendor = 0x8384,
++	  .pci_subdevice = 0x7680,
++	  .config = STAC_MACMINI },	/* Apple Mac Mini (early 2006) */
+ 	{} /* terminator */
+ };
+ 
+@@ -841,6 +847,19 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const
+ 		}
+ 	}
+ 
++	if (imux->num_items == 1) {
++		/*
++		 * Set the current input for the muxes.
++		 * The STAC9221 has two input muxes with identical source
++		 * NID lists.  Hopefully this won't get confused.
++		 */
++		for (i = 0; i < spec->num_muxes; i++) {
++			snd_hda_codec_write(codec, spec->mux_nids[i], 0,
++					    AC_VERB_SET_CONNECT_SEL,
++					    imux->items[0].index);
++		}
++	}
++
+ 	return 0;
+ }
+ 
+@@ -946,6 +965,45 @@ static int stac9200_parse_auto_config(struct hda_codec *codec)
+ 	return 1;
+ }
+ 
++/*
++ * Early 2006 Intel Macintoshes with STAC9220X5 codecs seem to have a
++ * funky external mute control using GPIO pins.
++ */
++
++static void stac922x_gpio_mute(struct hda_codec *codec, int pin, int muted)
++{
++	unsigned int gpiostate, gpiomask, gpiodir;
++
++	gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
++				       AC_VERB_GET_GPIO_DATA, 0);
++
++	if (!muted)
++		gpiostate |= (1 << pin);
++	else
++		gpiostate &= ~(1 << pin);
++
++	gpiomask = snd_hda_codec_read(codec, codec->afg, 0,
++				      AC_VERB_GET_GPIO_MASK, 0);
++	gpiomask |= (1 << pin);
++
++	gpiodir = snd_hda_codec_read(codec, codec->afg, 0,
++				     AC_VERB_GET_GPIO_DIRECTION, 0);
++	gpiodir |= (1 << pin);
++
++	/* AppleHDA seems to do this -- WTF is this verb?? */
++	snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0);
++
++	snd_hda_codec_write(codec, codec->afg, 0,
++			    AC_VERB_SET_GPIO_MASK, gpiomask);
++	snd_hda_codec_write(codec, codec->afg, 0,
++			    AC_VERB_SET_GPIO_DIRECTION, gpiodir);
++
++	msleep(1);
++
++	snd_hda_codec_write(codec, codec->afg, 0,
++			    AC_VERB_SET_GPIO_DATA, gpiostate);
++}
++
+ static int stac92xx_init(struct hda_codec *codec)
+ {
+ 	struct sigmatel_spec *spec = codec->spec;
+@@ -982,6 +1040,11 @@ static int stac92xx_init(struct hda_codec *codec)
+ 		stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin,
+ 					 AC_PINCTL_IN_EN);
+ 
++	if (spec->gpio_mute) {
++		stac922x_gpio_mute(codec, 0, 0);
++		stac922x_gpio_mute(codec, 1, 0);
++	}
++
+ 	return 0;
+ }
+ 
+@@ -1132,7 +1195,7 @@ static int patch_stac922x(struct hda_codec *codec)
+ 	spec->board_config = snd_hda_check_board_config(codec, stac922x_cfg_tbl);
+ 	if (spec->board_config < 0)
+                 snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, using BIOS defaults\n");
+-	else {
++	else if (stac922x_brd_tbl[spec->board_config] != NULL) {
+ 		spec->num_pins = 10;
+ 		spec->pin_nids = stac922x_pin_nids;
+ 		spec->pin_configs = stac922x_brd_tbl[spec->board_config];
+@@ -1154,6 +1217,9 @@ static int patch_stac922x(struct hda_codec *codec)
+ 		return err;
+ 	}
+ 
++	if (spec->board_config == STAC_MACMINI)
++		spec->gpio_mute = 1;
++
+ 	codec->patch_ops = stac92xx_patch_ops;
+ 
+ 	return 0;

commit 9c782e3b2083c33b5a14c9955cf15f32ea88116b
+Author: Alex Shepard 
+Date:   Sun Jan 15 01:57:00 2006 +0100
+
+    Spelling fix in IPW2100 and IPW2200 Kconfig entries
+    
+    s/remvoed/removed/
+    
+    Signed-off-by: Alex Shepard 
+    Signed-off-by: Adrian Bunk 
+
+diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
+index c1a6e69f7905..e90687495ccc 100644
+--- a/drivers/net/wireless/Kconfig
++++ b/drivers/net/wireless/Kconfig
+@@ -160,7 +160,7 @@ config IPW2100
+           .
+  
+           If you want to compile the driver as a module ( = code which can be
+-          inserted in and remvoed from the running kernel whenever you want),
++          inserted in and removed from the running kernel whenever you want),
+           say M here and read .  The module
+           will be called ipw2100.ko.
+ 	
+@@ -213,7 +213,7 @@ config IPW2200
+           .
+  
+           If you want to compile the driver as a module ( = code which can be
+-          inserted in and remvoed from the running kernel whenever you want),
++          inserted in and removed from the running kernel whenever you want),
+           say M here and read .  The module
+           will be called ipw2200.ko.
+ 

\ No newline at end of file diff --git a/detail/14.html b/detail/14.html new file mode 100644 index 0000000..319f350 --- /dev/null +++ b/detail/14.html @@ -0,0 +1,11444 @@ +

Patches contributed by Carnegie Mellon University


commit 98d5b61ef5fae7681df27065ad95ee6e30c42243
+Author: Jan Harkes 
+Date:   Mon Nov 8 18:34:55 2021 -0800
+
+    coda: bump module version to 7.2
+    
+    Helps with tracking which patches have been propagated upstream and if
+    users are running the latest known version.
+    
+    Link: https://lkml.kernel.org/r/20210908140308.18491-10-jaharkes@cs.cmu.edu
+    Signed-off-by: Jan Harkes 
+    Cc: Alex Shi 
+    Cc: Jing Yangyang 
+    Cc: Xin Tan 
+    Cc: Xiyu Yang 
+    Cc: Zeal Robot 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
+index 7e23cb22d394..b39580ad4ce5 100644
+--- a/fs/coda/psdev.c
++++ b/fs/coda/psdev.c
+@@ -384,7 +384,7 @@ MODULE_AUTHOR("Jan Harkes, Peter J. Braam");
+ MODULE_DESCRIPTION("Coda Distributed File System VFS interface");
+ MODULE_ALIAS_CHARDEV_MAJOR(CODA_PSDEV_MAJOR);
+ MODULE_LICENSE("GPL");
+-MODULE_VERSION("7.0");
++MODULE_VERSION("7.2");
+ 
+ static int __init init_coda(void)
+ {

commit 5a646fb3a3e2de8bbab19d41826b3e54b09969bc
+Author: Jan Harkes 
+Date:   Mon Nov 8 18:34:45 2021 -0800
+
+    coda: avoid doing bad things on inode type changes during revalidation
+    
+    When Coda discovers an inconsistent object, it turns it into a symlink.
+    However we can't just follow this change in the kernel on an existing file
+    or directory inode that may still have references.
+    
+    This patch removes the inconsistent inode from the inode hash and
+    allocates a new inode for the symlink object.
+    
+    Link: https://lkml.kernel.org/r/20210908140308.18491-7-jaharkes@cs.cmu.edu
+    Signed-off-by: Jan Harkes 
+    Cc: Alex Shi 
+    Cc: Jing Yangyang 
+    Cc: Xin Tan 
+    Cc: Xiyu Yang 
+    Cc: Zeal Robot 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c
+index 06855f6c7902..62a3d2565c26 100644
+--- a/fs/coda/cnode.c
++++ b/fs/coda/cnode.c
+@@ -63,9 +63,10 @@ struct inode * coda_iget(struct super_block * sb, struct CodaFid * fid,
+ 	struct inode *inode;
+ 	struct coda_inode_info *cii;
+ 	unsigned long hash = coda_f2i(fid);
++	umode_t inode_type = coda_inode_type(attr);
+ 
++retry:
+ 	inode = iget5_locked(sb, hash, coda_test_inode, coda_set_inode, fid);
+-
+ 	if (!inode)
+ 		return ERR_PTR(-ENOMEM);
+ 
+@@ -75,11 +76,15 @@ struct inode * coda_iget(struct super_block * sb, struct CodaFid * fid,
+ 		inode->i_ino = hash;
+ 		/* inode is locked and unique, no need to grab cii->c_lock */
+ 		cii->c_mapcount = 0;
++		coda_fill_inode(inode, attr);
+ 		unlock_new_inode(inode);
++	} else if ((inode->i_mode & S_IFMT) != inode_type) {
++		/* Inode has changed type, mark bad and grab a new one */
++		remove_inode_hash(inode);
++		coda_flag_inode(inode, C_PURGE);
++		iput(inode);
++		goto retry;
+ 	}
+-
+-	/* always replace the attributes, type might have changed */
+-	coda_fill_inode(inode, attr);
+ 	return inode;
+ }
+ 
+diff --git a/fs/coda/coda_linux.c b/fs/coda/coda_linux.c
+index 2e1a5a192074..903ca8fa4b9b 100644
+--- a/fs/coda/coda_linux.c
++++ b/fs/coda/coda_linux.c
+@@ -87,28 +87,27 @@ static struct coda_timespec timespec64_to_coda(struct timespec64 ts64)
+ }
+ 
+ /* utility functions below */
++umode_t coda_inode_type(struct coda_vattr *attr)
++{
++	switch (attr->va_type) {
++	case C_VREG:
++		return S_IFREG;
++	case C_VDIR:
++		return S_IFDIR;
++	case C_VLNK:
++		return S_IFLNK;
++	case C_VNON:
++	default:
++		return 0;
++	}
++}
++
+ void coda_vattr_to_iattr(struct inode *inode, struct coda_vattr *attr)
+ {
+-        int inode_type;
+-        /* inode's i_flags, i_ino are set by iget 
+-           XXX: is this all we need ??
+-           */
+-        switch (attr->va_type) {
+-        case C_VNON:
+-                inode_type  = 0;
+-                break;
+-        case C_VREG:
+-                inode_type = S_IFREG;
+-                break;
+-        case C_VDIR:
+-                inode_type = S_IFDIR;
+-                break;
+-        case C_VLNK:
+-                inode_type = S_IFLNK;
+-                break;
+-        default:
+-                inode_type = 0;
+-        }
++	/* inode's i_flags, i_ino are set by iget
++	 * XXX: is this all we need ??
++	 */
++	umode_t inode_type = coda_inode_type(attr);
+ 	inode->i_mode |= inode_type;
+ 
+ 	if (attr->va_mode != (u_short) -1)
+diff --git a/fs/coda/coda_linux.h b/fs/coda/coda_linux.h
+index 3c2947bba5e5..9be281bbcc06 100644
+--- a/fs/coda/coda_linux.h
++++ b/fs/coda/coda_linux.h
+@@ -53,10 +53,11 @@ int coda_getattr(struct user_namespace *, const struct path *, struct kstat *,
+ 		 u32, unsigned int);
+ int coda_setattr(struct user_namespace *, struct dentry *, struct iattr *);
+ 
+-/* this file:  heloers */
++/* this file:  helpers */
+ char *coda_f2s(struct CodaFid *f);
+ int coda_iscontrol(const char *name, size_t length);
+ 
++umode_t coda_inode_type(struct coda_vattr *attr);
+ void coda_vattr_to_iattr(struct inode *, struct coda_vattr *);
+ void coda_iattr_to_vattr(struct iattr *, struct coda_vattr *);
+ unsigned short coda_flags_to_cflags(unsigned short);

commit b2e36228367a8a097c7d15670fad47d77098f56d
+Author: Jan Harkes 
+Date:   Mon Nov 8 18:34:42 2021 -0800
+
+    coda: avoid hidden code duplication in rename
+    
+    We were actually fixing up the directory mtime in both branches after the
+    negative dentry test, it was just that one branch was only flagging the
+    directory inodes to refresh their attributes while the other branch used
+    the optional optimization to set mtime to the current time and not go back
+    to the Coda client.
+    
+    Link: https://lkml.kernel.org/r/20210908140308.18491-6-jaharkes@cs.cmu.edu
+    Signed-off-by: Jan Harkes 
+    Cc: Alex Shi 
+    Cc: Jing Yangyang 
+    Cc: Xin Tan 
+    Cc: Xiyu Yang 
+    Cc: Zeal Robot 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/dir.c b/fs/coda/dir.c
+index 3fd085009f26..328d7a684b63 100644
+--- a/fs/coda/dir.c
++++ b/fs/coda/dir.c
+@@ -317,13 +317,10 @@ static int coda_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
+ 				coda_dir_drop_nlink(old_dir);
+ 				coda_dir_inc_nlink(new_dir);
+ 			}
+-			coda_dir_update_mtime(old_dir);
+-			coda_dir_update_mtime(new_dir);
+ 			coda_flag_inode(d_inode(new_dentry), C_VATTR);
+-		} else {
+-			coda_flag_inode(old_dir, C_VATTR);
+-			coda_flag_inode(new_dir, C_VATTR);
+ 		}
++		coda_dir_update_mtime(old_dir);
++		coda_dir_update_mtime(new_dir);
+ 	}
+ 	return error;
+ }

commit 76097eb7a48a2ddcf4755773bd501c7aa14cbb7d
+Author: Jan Harkes 
+Date:   Mon Nov 8 18:34:39 2021 -0800
+
+    coda: avoid flagging NULL inodes
+    
+    Somehow we hit a negative dentry in coda_rename even after checking with
+    d_really_is_positive.  Maybe something raced and turned the new_dentry
+    negative while we were fixing up directory link counts.
+    
+    Link: https://lkml.kernel.org/r/20210908140308.18491-5-jaharkes@cs.cmu.edu
+    Signed-off-by: Jan Harkes 
+    Cc: Alex Shi 
+    Cc: Jing Yangyang 
+    Cc: Xin Tan 
+    Cc: Xiyu Yang 
+    Cc: Zeal Robot 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/coda_linux.h b/fs/coda/coda_linux.h
+index e7b27754ce78..3c2947bba5e5 100644
+--- a/fs/coda/coda_linux.h
++++ b/fs/coda/coda_linux.h
+@@ -83,6 +83,9 @@ static __inline__ void coda_flag_inode(struct inode *inode, int flag)
+ {
+ 	struct coda_inode_info *cii = ITOC(inode);
+ 
++	if (!inode)
++		return;
++
+ 	spin_lock(&cii->c_lock);
+ 	cii->c_flags |= flag;
+ 	spin_unlock(&cii->c_lock);

commit 3d8e72d97411370aab662e85e2c3a7b26555179c
+Author: Jan Harkes 
+Date:   Mon Nov 8 18:34:33 2021 -0800
+
+    coda: check for async upcall request using local state
+    
+    Originally flagged by Smatch because the code implicitly assumed outSize
+    is not NULL for non-async upcalls because of a flag that was (not) set in
+    req->uc_flags.
+    
+    However req->uc_flags field is in shared state and although the current
+    code will not allow it to be changed before the async request check the
+    code is more robust when it tests against the local outSize variable.
+    
+    Link: https://lkml.kernel.org/r/20210908140308.18491-3-jaharkes@cs.cmu.edu
+    Signed-off-by: Jan Harkes 
+    Cc: Alex Shi 
+    Cc: Jing Yangyang 
+    Cc: Xin Tan 
+    Cc: Xiyu Yang 
+    Cc: Zeal Robot 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
+index eb3b1898da46..59f6cfd06f96 100644
+--- a/fs/coda/upcall.c
++++ b/fs/coda/upcall.c
+@@ -744,7 +744,8 @@ static int coda_upcall(struct venus_comm *vcp,
+ 	list_add_tail(&req->uc_chain, &vcp->vc_pending);
+ 	wake_up_interruptible(&vcp->vc_waitq);
+ 
+-	if (req->uc_flags & CODA_REQ_ASYNC) {
++	/* We can return early on asynchronous requests */
++	if (outSize == NULL) {
+ 		mutex_unlock(&vcp->vc_mutex);
+ 		return 0;
+ 	}

commit 18319cb478de23340fdcb6385b0cc074a5416da7
+Author: Jan Harkes 
+Date:   Mon Nov 8 18:34:30 2021 -0800
+
+    coda: avoid NULL pointer dereference from a bad inode
+    
+    Patch series "Coda updates for -next".
+    
+    The following patch series contains some fixes for the Coda kernel module
+    I've had sitting around and were tested extensively in a development
+    version of the Coda kernel module that lives outside of the main kernel.
+    
+    This patch (of 9):
+    
+    Avoid accessing coda_inode_info from a dentry with a bad inode.
+    
+    Link: https://lkml.kernel.org/r/20210908140308.18491-1-jaharkes@cs.cmu.edu
+    Link: https://lkml.kernel.org/r/20210908140308.18491-2-jaharkes@cs.cmu.edu
+    Signed-off-by: Jan Harkes 
+    Cc: Alex Shi 
+    Cc: Jing Yangyang 
+    Cc: Xin Tan 
+    Cc: Xiyu Yang 
+    Cc: Zeal Robot 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/dir.c b/fs/coda/dir.c
+index d69989c1bac3..3fd085009f26 100644
+--- a/fs/coda/dir.c
++++ b/fs/coda/dir.c
+@@ -499,15 +499,20 @@ static int coda_dentry_revalidate(struct dentry *de, unsigned int flags)
+  */
+ static int coda_dentry_delete(const struct dentry * dentry)
+ {
+-	int flags;
++	struct inode *inode;
++	struct coda_inode_info *cii;
+ 
+ 	if (d_really_is_negative(dentry)) 
+ 		return 0;
+ 
+-	flags = (ITOC(d_inode(dentry))->c_flags) & C_PURGE;
+-	if (is_bad_inode(d_inode(dentry)) || flags) {
++	inode = d_inode(dentry);
++	if (!inode || is_bad_inode(inode))
+ 		return 1;
+-	}
++
++	cii = ITOC(inode);
++	if (cii->c_flags & C_PURGE)
++		return 1;
++
+ 	return 0;
+ }
+ 

commit 6dc280ebeed2c96a2fb933103dafe655a922b9c1
+Author: Jan Harkes 
+Date:   Tue Jul 16 16:28:51 2019 -0700
+
+    coda: remove uapi/linux/coda_psdev.h
+    
+    Nothing is left in this header that is used by userspace.
+    
+    Link: http://lkml.kernel.org/r/bb11378cef94739f2cf89425dd6d302a52c64480.1558117389.git.jaharkes@cs.cmu.edu
+    Signed-off-by: Jan Harkes 
+    Cc: Arnd Bergmann 
+    Cc: Colin Ian King 
+    Cc: Dan Carpenter 
+    Cc: David Howells 
+    Cc: Fabian Frederick 
+    Cc: Mikko Rapeli 
+    Cc: Sam Protsenko 
+    Cc: Yann Droneaud 
+    Cc: Zhouyang Jia 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/coda_psdev.h b/fs/coda/coda_psdev.h
+index 012e16f741a6..801423cbbdfc 100644
+--- a/fs/coda/coda_psdev.h
++++ b/fs/coda/coda_psdev.h
+@@ -3,8 +3,11 @@
+ #define __CODA_PSDEV_H
+ 
+ #include 
++#include 
+ #include 
+-#include 
++
++#define CODA_PSDEV_MAJOR 67
++#define MAX_CODADEVS  5	   /* how many do we allow */
+ 
+ struct kstatfs;
+ 
+diff --git a/include/uapi/linux/coda_psdev.h b/include/uapi/linux/coda_psdev.h
+deleted file mode 100644
+index 3dacb7fad66a..000000000000
+--- a/include/uapi/linux/coda_psdev.h
++++ /dev/null
+@@ -1,10 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+-#ifndef _UAPI__CODA_PSDEV_H
+-#define _UAPI__CODA_PSDEV_H
+-
+-#include 
+-
+-#define CODA_PSDEV_MAJOR 67
+-#define MAX_CODADEVS  5	   /* how many do we allow */
+-
+-#endif /* _UAPI__CODA_PSDEV_H */

commit b6a18c60080fcff0921e81991fec049394fb04e9
+Author: Jan Harkes 
+Date:   Tue Jul 16 16:28:44 2019 -0700
+
+    coda: bump module version
+    
+    The out of tree module version had been bumped several times already,
+    but we haven't kept this in-tree one in sync, partly because most
+    changes go from here to the out-of-tree copy.
+    
+    Link: http://lkml.kernel.org/r/8b0ab50a2da2f0180ac32c79d91811b4d1d0bd8b.1558117389.git.jaharkes@cs.cmu.edu
+    Signed-off-by: Jan Harkes 
+    Cc: Arnd Bergmann 
+    Cc: Colin Ian King 
+    Cc: Dan Carpenter 
+    Cc: David Howells 
+    Cc: Fabian Frederick 
+    Cc: Mikko Rapeli 
+    Cc: Sam Protsenko 
+    Cc: Yann Droneaud 
+    Cc: Zhouyang Jia 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
+index 3ac22a2b97e2..e80bda1de6c5 100644
+--- a/fs/coda/psdev.c
++++ b/fs/coda/psdev.c
+@@ -389,7 +389,7 @@ MODULE_AUTHOR("Jan Harkes, Peter J. Braam");
+ MODULE_DESCRIPTION("Coda Distributed File System VFS interface");
+ MODULE_ALIAS_CHARDEV_MAJOR(CODA_PSDEV_MAJOR);
+ MODULE_LICENSE("GPL");
+-MODULE_VERSION("6.6");
++MODULE_VERSION("6.11");
+ 
+ static int __init init_coda(void)
+ {

commit 5e7c31dfe74703f428220384b2863525957cc160
+Author: Jan Harkes 
+Date:   Tue Jul 16 16:28:35 2019 -0700
+
+    coda: change Coda's user api to use 64-bit time_t in timespec
+    
+    Move the 32-bit time_t problems to userspace.
+    
+    Link: http://lkml.kernel.org/r/8d089068823bfb292a4020f773922fbd82ffad39.1558117389.git.jaharkes@cs.cmu.edu
+    Signed-off-by: Jan Harkes 
+    Cc: Arnd Bergmann 
+    Cc: Colin Ian King 
+    Cc: Dan Carpenter 
+    Cc: David Howells 
+    Cc: Fabian Frederick 
+    Cc: Mikko Rapeli 
+    Cc: Sam Protsenko 
+    Cc: Yann Droneaud 
+    Cc: Zhouyang Jia 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/Documentation/filesystems/coda.txt b/Documentation/filesystems/coda.txt
+index ea5969068895..545262c167c3 100644
+--- a/Documentation/filesystems/coda.txt
++++ b/Documentation/filesystems/coda.txt
+@@ -481,8 +481,8 @@ kernel support.
+ 
+ 
+ 
+-  struct vtimespec {
+-          long            tv_sec;         /* seconds */
++  struct coda_timespec {
++          int64_t         tv_sec;         /* seconds */
+           long            tv_nsec;        /* nanoseconds */
+   };
+ 
+@@ -496,9 +496,9 @@ kernel support.
+           long            va_fileid;      /* file id */
+           u_quad_t        va_size;        /* file size in bytes */
+           long            va_blocksize;   /* blocksize preferred for i/o */
+-          struct vtimespec va_atime;      /* time of last access */
+-          struct vtimespec va_mtime;      /* time of last modification */
+-          struct vtimespec va_ctime;      /* time file changed */
++          struct coda_timespec va_atime;  /* time of last access */
++          struct coda_timespec va_mtime;  /* time of last modification */
++          struct coda_timespec va_ctime;  /* time file changed */
+           u_long          va_gen;         /* generation number of file */
+           u_long          va_flags;       /* flags defined for file */
+           dev_t           va_rdev;        /* device special file represents */
+diff --git a/fs/coda/coda_linux.c b/fs/coda/coda_linux.c
+index 8addcd166908..e4b5f02f0dd4 100644
+--- a/fs/coda/coda_linux.c
++++ b/fs/coda/coda_linux.c
+@@ -66,13 +66,8 @@ unsigned short coda_flags_to_cflags(unsigned short flags)
+ 	return coda_flags;
+ }
+ 
+-static struct timespec64 coda_to_timespec64(struct vtimespec ts)
++static struct timespec64 coda_to_timespec64(struct coda_timespec ts)
+ {
+-	/*
+-	 * We interpret incoming timestamps as 'signed' to match traditional
+-	 * usage and support pre-1970 timestamps, but this breaks in y2038
+-	 * on 32-bit machines.
+-	 */
+ 	struct timespec64 ts64 = {
+ 		.tv_sec = ts.tv_sec,
+ 		.tv_nsec = ts.tv_nsec,
+@@ -81,12 +76,10 @@ static struct timespec64 coda_to_timespec64(struct vtimespec ts)
+ 	return ts64;
+ }
+ 
+-static struct vtimespec timespec64_to_coda(struct timespec64 ts64)
++static struct coda_timespec timespec64_to_coda(struct timespec64 ts64)
+ {
+-	/* clamp the timestamps to the maximum range rather than wrapping */
+-	struct vtimespec ts = {
+-		.tv_sec = lower_32_bits(clamp_t(time64_t, ts64.tv_sec,
+-						LONG_MIN, LONG_MAX)),
++	struct coda_timespec ts = {
++		.tv_sec = ts64.tv_sec,
+ 		.tv_nsec = ts64.tv_nsec,
+ 	};
+ 
+@@ -156,11 +149,11 @@ void coda_iattr_to_vattr(struct iattr *iattr, struct coda_vattr *vattr)
+         vattr->va_uid = (vuid_t) -1; 
+         vattr->va_gid = (vgid_t) -1;
+         vattr->va_size = (off_t) -1;
+-	vattr->va_atime.tv_sec = (long) -1;
++	vattr->va_atime.tv_sec = (int64_t) -1;
+ 	vattr->va_atime.tv_nsec = (long) -1;
+-	vattr->va_mtime.tv_sec = (long) -1;
++	vattr->va_mtime.tv_sec = (int64_t) -1;
+ 	vattr->va_mtime.tv_nsec = (long) -1;
+-	vattr->va_ctime.tv_sec = (long) -1;
++	vattr->va_ctime.tv_sec = (int64_t) -1;
+ 	vattr->va_ctime.tv_nsec = (long) -1;
+         vattr->va_type = C_VNON;
+ 	vattr->va_fileid = -1;
+diff --git a/include/uapi/linux/coda.h b/include/uapi/linux/coda.h
+index fc5f7874208a..5dba636b6e11 100644
+--- a/include/uapi/linux/coda.h
++++ b/include/uapi/linux/coda.h
+@@ -86,10 +86,6 @@ typedef unsigned long long u_quad_t;
+ 
+ #define inline
+ 
+-struct timespec {
+-        long       ts_sec;
+-        long       ts_nsec;
+-};
+ #else  /* DJGPP but not KERNEL */
+ #include 
+ typedef unsigned long long u_quad_t;
+@@ -110,13 +106,6 @@ typedef unsigned long long u_quad_t;
+ #define cdev_t dev_t
+ #endif
+ 
+-#ifdef __CYGWIN32__
+-struct timespec {
+-        time_t  tv_sec;         /* seconds */
+-        long    tv_nsec;        /* nanoseconds */
+-};
+-#endif
+-
+ #ifndef __BIT_TYPES_DEFINED__
+ #define __BIT_TYPES_DEFINED__
+ typedef signed char	      int8_t;
+@@ -211,19 +200,10 @@ struct CodaFid {
+  */
+ enum coda_vtype	{ C_VNON, C_VREG, C_VDIR, C_VBLK, C_VCHR, C_VLNK, C_VSOCK, C_VFIFO, C_VBAD };
+ 
+-#ifdef __linux__
+-/*
+- * This matches the traditional Linux 'timespec' structure binary layout,
+- * before using 64-bit time_t everywhere. Overflows in y2038 on 32-bit
+- * architectures.
+- */
+-struct vtimespec {
+-	long		tv_sec;		/* seconds */
++struct coda_timespec {
++	int64_t		tv_sec;		/* seconds */
+ 	long		tv_nsec;	/* nanoseconds */
+ };
+-#else
+-#define vtimespec timespec
+-#endif
+ 
+ struct coda_vattr {
+ 	long     	va_type;	/* vnode type (for create) */
+@@ -234,9 +214,9 @@ struct coda_vattr {
+ 	long		va_fileid;	/* file id */
+ 	u_quad_t	va_size;	/* file size in bytes */
+ 	long		va_blocksize;	/* blocksize preferred for i/o */
+-	struct vtimespec va_atime;	/* time of last access */
+-	struct vtimespec va_mtime;	/* time of last modification */
+-	struct vtimespec va_ctime;	/* time file changed */
++	struct coda_timespec va_atime;	/* time of last access */
++	struct coda_timespec va_mtime;	/* time of last modification */
++	struct coda_timespec va_ctime;	/* time file changed */
+ 	u_long		va_gen;		/* generation number of file */
+ 	u_long		va_flags;	/* flags defined for file */
+ 	cdev_t	        va_rdev;	/* device special file represents */
+@@ -301,7 +281,8 @@ struct coda_statfs {
+ 
+ #define CIOC_KERNEL_VERSION _IOWR('c', 10, size_t)
+ 
+-#define CODA_KERNEL_VERSION 3 /* 128-bit file identifiers */
++//      CODA_KERNEL_VERSION 3 /* 128-bit file identifiers */
++#define CODA_KERNEL_VERSION 4 /* 64-bit timespec */
+ 
+ /*
+  *        Venus <-> Coda  RPC arguments

commit 2fe7491d219428a32f09948e88bfaf8e71b9a66b
+Author: Jan Harkes 
+Date:   Tue Jul 16 16:28:26 2019 -0700
+
+    uapi linux/coda_psdev.h: move CODA_REQ_ from uapi to kernel side headers
+    
+    These constants only used internally and not exposed to userspace.
+    
+    Link: http://lkml.kernel.org/r/baeafc30dad70d8b422ee679420099c2d8aa7da0.1558117389.git.jaharkes@cs.cmu.edu
+    Signed-off-by: Jan Harkes 
+    Cc: Arnd Bergmann 
+    Cc: Colin Ian King 
+    Cc: Dan Carpenter 
+    Cc: David Howells 
+    Cc: Fabian Frederick 
+    Cc: Mikko Rapeli 
+    Cc: Sam Protsenko 
+    Cc: Yann Droneaud 
+    Cc: Zhouyang Jia 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/coda_psdev.h b/include/linux/coda_psdev.h
+index d1672fd5e638..9487f792770c 100644
+--- a/include/linux/coda_psdev.h
++++ b/include/linux/coda_psdev.h
+@@ -31,6 +31,11 @@ struct upc_req {
+ 	wait_queue_head_t	uc_sleep;   /* process' wait queue */
+ };
+ 
++#define CODA_REQ_ASYNC  0x1
++#define CODA_REQ_READ   0x2
++#define CODA_REQ_WRITE  0x4
++#define CODA_REQ_ABORT  0x8
++
+ static inline struct venus_comm *coda_vcp(struct super_block *sb)
+ {
+ 	return (struct venus_comm *)((sb)->s_fs_info);
+diff --git a/include/uapi/linux/coda_psdev.h b/include/uapi/linux/coda_psdev.h
+index d50d51a57fe4..3dacb7fad66a 100644
+--- a/include/uapi/linux/coda_psdev.h
++++ b/include/uapi/linux/coda_psdev.h
+@@ -7,9 +7,4 @@
+ #define CODA_PSDEV_MAJOR 67
+ #define MAX_CODADEVS  5	   /* how many do we allow */
+ 
+-#define CODA_REQ_ASYNC  0x1
+-#define CODA_REQ_READ   0x2
+-#define CODA_REQ_WRITE  0x4
+-#define CODA_REQ_ABORT  0x8
+-
+ #endif /* _UAPI__CODA_PSDEV_H */

commit 9a05671dd8d85cbce6cf1a00727d5919c1e56192
+Author: Jan Harkes 
+Date:   Tue Jul 16 16:28:23 2019 -0700
+
+    coda: don't try to print names that were considered too long
+    
+    Probably safer to just show the unexpected length and debug it from the
+    userspace side.
+    
+    Link: http://lkml.kernel.org/r/582ae759a4fdfa31a64c35de489fa4efabac09d6.1558117389.git.jaharkes@cs.cmu.edu
+    Signed-off-by: Jan Harkes 
+    Cc: Arnd Bergmann 
+    Cc: Colin Ian King 
+    Cc: Dan Carpenter 
+    Cc: David Howells 
+    Cc: Fabian Frederick 
+    Cc: Mikko Rapeli 
+    Cc: Sam Protsenko 
+    Cc: Yann Droneaud 
+    Cc: Zhouyang Jia 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/dir.c b/fs/coda/dir.c
+index 00876ddadb43..7e103eb8ffcd 100644
+--- a/fs/coda/dir.c
++++ b/fs/coda/dir.c
+@@ -47,8 +47,8 @@ static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, unsig
+ 	int type = 0;
+ 
+ 	if (length > CODA_MAXNAMLEN) {
+-		pr_err("name too long: lookup, %s (%*s)\n",
+-		       coda_i2s(dir), (int)length, name);
++		pr_err("name too long: lookup, %s %zu\n",
++		       coda_i2s(dir), length);
+ 		return ERR_PTR(-ENAMETOOLONG);
+ 	}
+ 

commit 6e51f8aa76b67d0a6eb168fd41a81e8478ae07a9
+Author: Jan Harkes 
+Date:   Tue Jul 16 16:28:16 2019 -0700
+
+    coda: potential buffer overflow in coda_psdev_write()
+    
+    Add checks to make sure the downcall message we got from the Coda cache
+    manager is large enough to contain the data it is supposed to have.
+    i.e.  when we get a CODA_ZAPDIR we can access &out->coda_zapdir.CodaFid.
+    
+    Link: http://lkml.kernel.org/r/894fb6b250add09e4e3935f14649f21284a5cb18.1558117389.git.jaharkes@cs.cmu.edu
+    Signed-off-by: Jan Harkes 
+    Reported-by: Dan Carpenter 
+    Cc: Arnd Bergmann 
+    Cc: Colin Ian King 
+    Cc: David Howells 
+    Cc: Fabian Frederick 
+    Cc: Mikko Rapeli 
+    Cc: Sam Protsenko 
+    Cc: Yann Droneaud 
+    Cc: Zhouyang Jia 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
+index 241f7e04ad04..b4da2812499e 100644
+--- a/fs/coda/psdev.c
++++ b/fs/coda/psdev.c
+@@ -100,8 +100,12 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
+ 	ssize_t retval = 0, count = 0;
+ 	int error;
+ 
++	/* make sure there is enough to copy out the (opcode, unique) values */
++	if (nbytes < (2 * sizeof(u_int32_t)))
++		return -EINVAL;
++
+         /* Peek at the opcode, uniquefier */
+-	if (copy_from_user(&hdr, buf, 2 * sizeof(u_long)))
++	if (copy_from_user(&hdr, buf, 2 * sizeof(u_int32_t)))
+ 	        return -EFAULT;
+ 
+         if (DOWNCALL(hdr.opcode)) {
+@@ -127,7 +131,7 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
+ 		}
+ 
+ 		/* what downcall errors does Venus handle ? */
+-		error = coda_downcall(vcp, hdr.opcode, dcbuf);
++		error = coda_downcall(vcp, hdr.opcode, dcbuf, nbytes);
+ 
+ 		CODA_FREE(dcbuf, nbytes);
+ 		if (error) {
+diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
+index 1175a1722411..cf1e662681a5 100644
+--- a/fs/coda/upcall.c
++++ b/fs/coda/upcall.c
+@@ -804,12 +804,44 @@ static int coda_upcall(struct venus_comm *vcp,
+  *
+  * CODA_REPLACE -- replace one CodaFid with another throughout the name cache */
+ 
+-int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out)
++int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out,
++		  size_t nbytes)
+ {
+ 	struct inode *inode = NULL;
+ 	struct CodaFid *fid = NULL, *newfid;
+ 	struct super_block *sb;
+ 
++	/*
++	 * Make sure we have received enough data from the cache
++	 * manager to populate the necessary fields in the buffer
++	 */
++	switch (opcode) {
++	case CODA_PURGEUSER:
++		if (nbytes < sizeof(struct coda_purgeuser_out))
++			return -EINVAL;
++		break;
++
++	case CODA_ZAPDIR:
++		if (nbytes < sizeof(struct coda_zapdir_out))
++			return -EINVAL;
++		break;
++
++	case CODA_ZAPFILE:
++		if (nbytes < sizeof(struct coda_zapfile_out))
++			return -EINVAL;
++		break;
++
++	case CODA_PURGEFID:
++		if (nbytes < sizeof(struct coda_purgefid_out))
++			return -EINVAL;
++		break;
++
++	case CODA_REPLACE:
++		if (nbytes < sizeof(struct coda_replace_out))
++			return -EINVAL;
++		break;
++	}
++
+ 	/* Handle invalidation requests. */
+ 	mutex_lock(&vcp->vc_mutex);
+ 	sb = vcp->vc_sb;
+diff --git a/include/linux/coda_psdev.h b/include/linux/coda_psdev.h
+index 57d2b2faf6a3..d1672fd5e638 100644
+--- a/include/linux/coda_psdev.h
++++ b/include/linux/coda_psdev.h
+@@ -71,7 +71,8 @@ int venus_symlink(struct super_block *sb, struct CodaFid *fid,
+ int venus_access(struct super_block *sb, struct CodaFid *fid, int mask);
+ int venus_pioctl(struct super_block *sb, struct CodaFid *fid,
+ 		 unsigned int cmd, struct PioctlData *data);
+-int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out);
++int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out,
++		  size_t nbytes);
+ int venus_fsync(struct super_block *sb, struct CodaFid *fid);
+ int venus_statfs(struct dentry *dentry, struct kstatfs *sfs);
+ 

commit 7fa0a1da3dadfd9216df7745a1331fdaa0940d1c
+Author: Jan Harkes 
+Date:   Tue Jul 16 16:28:04 2019 -0700
+
+    coda: pass the host file in vma->vm_file on mmap
+    
+    Patch series "Coda updates".
+    
+    The following patch series is a collection of various fixes for Coda,
+    most of which were collected from linux-fsdevel or linux-kernel but
+    which have as yet not found their way upstream.
+    
+    This patch (of 22):
+    
+    Various file systems expect that vma->vm_file points at their own file
+    handle, several use file_inode(vma->vm_file) to get at their inode or
+    use vma->vm_file->private_data.  However the way Coda wrapped mmap on a
+    host file broke this assumption, vm_file was still pointing at the Coda
+    file and the host file systems would scribble over Coda's inode and
+    private file data.
+    
+    This patch fixes the incorrect expectation and wraps vm_ops->open and
+    vm_ops->close to allow Coda to track when the vm_area_struct is
+    destroyed so we still release the reference on the Coda file handle at
+    the right time.
+    
+    Link: http://lkml.kernel.org/r/0e850c6e59c0b147dc2dcd51a3af004c948c3697.1558117389.git.jaharkes@cs.cmu.edu
+    Signed-off-by: Jan Harkes 
+    Cc: Arnd Bergmann 
+    Cc: Colin Ian King 
+    Cc: Dan Carpenter 
+    Cc: David Howells 
+    Cc: Fabian Frederick 
+    Cc: Mikko Rapeli 
+    Cc: Sam Protsenko 
+    Cc: Yann Droneaud 
+    Cc: Zhouyang Jia 
+    Cc: 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/file.c b/fs/coda/file.c
+index 1cbc1f2298ee..43d371551d2b 100644
+--- a/fs/coda/file.c
++++ b/fs/coda/file.c
+@@ -27,6 +27,13 @@
+ #include "coda_linux.h"
+ #include "coda_int.h"
+ 
++struct coda_vm_ops {
++	atomic_t refcnt;
++	struct file *coda_file;
++	const struct vm_operations_struct *host_vm_ops;
++	struct vm_operations_struct vm_ops;
++};
++
+ static ssize_t
+ coda_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
+ {
+@@ -61,6 +68,34 @@ coda_file_write_iter(struct kiocb *iocb, struct iov_iter *to)
+ 	return ret;
+ }
+ 
++static void
++coda_vm_open(struct vm_area_struct *vma)
++{
++	struct coda_vm_ops *cvm_ops =
++		container_of(vma->vm_ops, struct coda_vm_ops, vm_ops);
++
++	atomic_inc(&cvm_ops->refcnt);
++
++	if (cvm_ops->host_vm_ops && cvm_ops->host_vm_ops->open)
++		cvm_ops->host_vm_ops->open(vma);
++}
++
++static void
++coda_vm_close(struct vm_area_struct *vma)
++{
++	struct coda_vm_ops *cvm_ops =
++		container_of(vma->vm_ops, struct coda_vm_ops, vm_ops);
++
++	if (cvm_ops->host_vm_ops && cvm_ops->host_vm_ops->close)
++		cvm_ops->host_vm_ops->close(vma);
++
++	if (atomic_dec_and_test(&cvm_ops->refcnt)) {
++		vma->vm_ops = cvm_ops->host_vm_ops;
++		fput(cvm_ops->coda_file);
++		kfree(cvm_ops);
++	}
++}
++
+ static int
+ coda_file_mmap(struct file *coda_file, struct vm_area_struct *vma)
+ {
+@@ -68,6 +103,8 @@ coda_file_mmap(struct file *coda_file, struct vm_area_struct *vma)
+ 	struct coda_inode_info *cii;
+ 	struct file *host_file;
+ 	struct inode *coda_inode, *host_inode;
++	struct coda_vm_ops *cvm_ops;
++	int ret;
+ 
+ 	cfi = CODA_FTOC(coda_file);
+ 	BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
+@@ -76,6 +113,13 @@ coda_file_mmap(struct file *coda_file, struct vm_area_struct *vma)
+ 	if (!host_file->f_op->mmap)
+ 		return -ENODEV;
+ 
++	if (WARN_ON(coda_file != vma->vm_file))
++		return -EIO;
++
++	cvm_ops = kmalloc(sizeof(struct coda_vm_ops), GFP_KERNEL);
++	if (!cvm_ops)
++		return -ENOMEM;
++
+ 	coda_inode = file_inode(coda_file);
+ 	host_inode = file_inode(host_file);
+ 
+@@ -89,6 +133,7 @@ coda_file_mmap(struct file *coda_file, struct vm_area_struct *vma)
+ 	 * the container file on us! */
+ 	else if (coda_inode->i_mapping != host_inode->i_mapping) {
+ 		spin_unlock(&cii->c_lock);
++		kfree(cvm_ops);
+ 		return -EBUSY;
+ 	}
+ 
+@@ -97,7 +142,29 @@ coda_file_mmap(struct file *coda_file, struct vm_area_struct *vma)
+ 	cfi->cfi_mapcount++;
+ 	spin_unlock(&cii->c_lock);
+ 
+-	return call_mmap(host_file, vma);
++	vma->vm_file = get_file(host_file);
++	ret = call_mmap(vma->vm_file, vma);
++
++	if (ret) {
++		/* if call_mmap fails, our caller will put coda_file so we
++		 * should drop the reference to the host_file that we got.
++		 */
++		fput(host_file);
++		kfree(cvm_ops);
++	} else {
++		/* here we add redirects for the open/close vm_operations */
++		cvm_ops->host_vm_ops = vma->vm_ops;
++		if (vma->vm_ops)
++			cvm_ops->vm_ops = *vma->vm_ops;
++
++		cvm_ops->vm_ops.open = coda_vm_open;
++		cvm_ops->vm_ops.close = coda_vm_close;
++		cvm_ops->coda_file = coda_file;
++		atomic_set(&cvm_ops->refcnt, 1);
++
++		vma->vm_ops = &cvm_ops->vm_ops;
++	}
++	return ret;
+ }
+ 
+ int coda_open(struct inode *coda_inode, struct file *coda_file)
+@@ -207,4 +274,3 @@ const struct file_operations coda_file_operations = {
+ 	.fsync		= coda_fsync,
+ 	.splice_read	= generic_file_splice_read,
+ };
+-

commit d337b66a4c52c7b04eec661d86c2ef6e168965a2
+Author: Jan Harkes 
+Date:   Wed Sep 27 15:52:12 2017 -0400
+
+    coda: fix 'kernel memory exposure attempt' in fsync
+    
+    When an application called fsync on a file in Coda a small request with
+    just the file identifier was allocated, but the declared length was set
+    to the size of union of all possible upcall requests.
+    
+    This bug has been around for a very long time and is now caught by the
+    extra checking in usercopy that was introduced in Linux-4.8.
+    
+    The exposure happens when the Coda cache manager process reads the fsync
+    upcall request at which point it is killed. As a result there is nobody
+    servicing any further upcalls, trapping any processes that try to access
+    the mounted Coda filesystem.
+    
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Jan Harkes 
+    Signed-off-by: Al Viro 
+
+diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
+index e82357c89979..8cf16d8c5261 100644
+--- a/fs/coda/upcall.c
++++ b/fs/coda/upcall.c
+@@ -446,8 +446,7 @@ int venus_fsync(struct super_block *sb, struct CodaFid *fid)
+ 	UPARG(CODA_FSYNC);
+ 
+ 	inp->coda_fsync.VFid = *fid;
+-	error = coda_upcall(coda_vcp(sb), sizeof(union inputArgs),
+-			    &outsize, inp);
++	error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
+ 
+ 	CODA_FREE(inp, insize);
+ 	return error;

commit 3725e9dd5bef376ab87d41e40c437a6b2a20eb59
+Author: Jan Harkes 
+Date:   Wed Sep 9 15:38:01 2015 -0700
+
+    fs/coda: fix readlink buffer overflow
+    
+    Dan Carpenter discovered a buffer overflow in the Coda file system
+    readlink code.  A userspace file system daemon can return a 4096 byte
+    result which then triggers a one byte write past the allocated readlink
+    result buffer.
+    
+    This does not trigger with an unmodified Coda implementation because Coda
+    has a 1024 byte limit for symbolic links, however other userspace file
+    systems using the Coda kernel module could be affected.
+    
+    Although this is an obvious overflow, I don't think this has to be handled
+    as too sensitive from a security perspective because the overflow is on
+    the Coda userspace daemon side which already needs root to open Coda's
+    kernel device and to mount the file system before we get to the point that
+    links can be read.
+    
+    [akpm@linux-foundation.org: coding-style fixes]
+    Signed-off-by: Jan Harkes 
+    Reported-by: Dan Carpenter 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
+index 9b1ffaa0572e..f6c6c8adbc01 100644
+--- a/fs/coda/upcall.c
++++ b/fs/coda/upcall.c
+@@ -353,7 +353,7 @@ int venus_readlink(struct super_block *sb, struct CodaFid *fid,
+         char *result;
+         
+ 	insize = max_t(unsigned int,
+-		     INSIZE(readlink), OUTSIZE(readlink)+ *length + 1);
++		     INSIZE(readlink), OUTSIZE(readlink)+ *length);
+ 	UPARG(CODA_READLINK);
+ 
+         inp->coda_readlink.VFid = *fid;
+@@ -361,8 +361,8 @@ int venus_readlink(struct super_block *sb, struct CodaFid *fid,
+ 	error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
+ 	if (!error) {
+ 		retlen = outp->coda_readlink.count;
+-		if ( retlen > *length )
+-			retlen = *length;
++		if (retlen >= *length)
++			retlen = *length - 1;
+ 		*length = retlen;
+ 		result =  (char *)outp + (long)outp->coda_readlink.data;
+ 		memcpy(buffer, result, retlen);

commit da47c19e5c746829042933c8f945a71e2b62d6fc
+Author: Yoshihisa Abe 
+Date:   Mon Oct 25 02:03:46 2010 -0400
+
+    Coda: replace BKL with mutex
+    
+    Replace the BKL with a mutex to protect the venus_comm structure which
+    binds the mountpoint with the character device and holds the upcall
+    queues.
+    
+    Signed-off-by: Yoshihisa Abe 
+    Signed-off-by: Jan Harkes 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/inode.c b/fs/coda/inode.c
+index b7fa3e3d772f..7993b96ca348 100644
+--- a/fs/coda/inode.c
++++ b/fs/coda/inode.c
+@@ -15,7 +15,7 @@
+ #include 
+ #include 
+ #include 
+-#include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -145,7 +145,7 @@ static int get_device_index(struct coda_mount_data *data)
+ static int coda_fill_super(struct super_block *sb, void *data, int silent)
+ {
+ 	struct inode *root = NULL;
+-	struct venus_comm *vc = NULL;
++	struct venus_comm *vc;
+ 	struct CodaFid fid;
+ 	int error;
+ 	int idx;
+@@ -159,7 +159,7 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
+ 	printk(KERN_INFO "coda_read_super: device index: %i\n", idx);
+ 
+ 	vc = &coda_comms[idx];
+-	lock_kernel();
++	mutex_lock(&vc->vc_mutex);
+ 
+ 	if (!vc->vc_inuse) {
+ 		printk("coda_read_super: No pseudo device\n");
+@@ -178,7 +178,7 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
+ 		goto unlock_out;
+ 
+ 	vc->vc_sb = sb;
+-	unlock_kernel();
++	mutex_unlock(&vc->vc_mutex);
+ 
+ 	sb->s_fs_info = vc;
+ 	sb->s_flags |= MS_NOATIME;
+@@ -217,20 +217,23 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
+ 	if (root)
+ 		iput(root);
+ 
+-	lock_kernel();
++	mutex_lock(&vc->vc_mutex);
+ 	bdi_destroy(&vc->bdi);
+ 	vc->vc_sb = NULL;
+ 	sb->s_fs_info = NULL;
+ unlock_out:
+-	unlock_kernel();
++	mutex_unlock(&vc->vc_mutex);
+ 	return error;
+ }
+ 
+ static void coda_put_super(struct super_block *sb)
+ {
+-	bdi_destroy(&coda_vcp(sb)->bdi);
+-	coda_vcp(sb)->vc_sb = NULL;
++	struct venus_comm *vcp = coda_vcp(sb);
++	mutex_lock(&vcp->vc_mutex);
++	bdi_destroy(&vcp->bdi);
++	vcp->vc_sb = NULL;
+ 	sb->s_fs_info = NULL;
++	mutex_unlock(&vcp->vc_mutex);
+ 
+ 	printk("Coda: Bye bye.\n");
+ }
+diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
+index 9a9248e632c6..62647a8595e4 100644
+--- a/fs/coda/psdev.c
++++ b/fs/coda/psdev.c
+@@ -35,7 +35,7 @@
+ #include 
+ #include 
+ #include 
+-#include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -67,8 +67,10 @@ static unsigned int coda_psdev_poll(struct file *file, poll_table * wait)
+ 	unsigned int mask = POLLOUT | POLLWRNORM;
+ 
+ 	poll_wait(file, &vcp->vc_waitq, wait);
++	mutex_lock(&vcp->vc_mutex);
+ 	if (!list_empty(&vcp->vc_pending))
+                 mask |= POLLIN | POLLRDNORM;
++	mutex_unlock(&vcp->vc_mutex);
+ 
+ 	return mask;
+ }
+@@ -143,7 +145,7 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
+ 	}
+         
+ 	/* Look for the message on the processing queue. */
+-	lock_kernel();
++	mutex_lock(&vcp->vc_mutex);
+ 	list_for_each(lh, &vcp->vc_processing) {
+ 		tmp = list_entry(lh, struct upc_req , uc_chain);
+ 		if (tmp->uc_unique == hdr.unique) {
+@@ -152,7 +154,7 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
+ 			break;
+ 		}
+ 	}
+-	unlock_kernel();
++	mutex_unlock(&vcp->vc_mutex);
+ 
+ 	if (!req) {
+ 		printk("psdev_write: msg (%d, %d) not found\n", 
+@@ -207,7 +209,7 @@ static ssize_t coda_psdev_read(struct file * file, char __user * buf,
+ 	if (nbytes == 0)
+ 		return 0;
+ 
+-	lock_kernel();
++	mutex_lock(&vcp->vc_mutex);
+ 
+ 	add_wait_queue(&vcp->vc_waitq, &wait);
+ 	set_current_state(TASK_INTERRUPTIBLE);
+@@ -221,7 +223,9 @@ static ssize_t coda_psdev_read(struct file * file, char __user * buf,
+ 			retval = -ERESTARTSYS;
+ 			break;
+ 		}
++		mutex_unlock(&vcp->vc_mutex);
+ 		schedule();
++		mutex_lock(&vcp->vc_mutex);
+ 	}
+ 
+ 	set_current_state(TASK_RUNNING);
+@@ -254,7 +258,7 @@ static ssize_t coda_psdev_read(struct file * file, char __user * buf,
+ 	CODA_FREE(req->uc_data, sizeof(struct coda_in_hdr));
+ 	kfree(req);
+ out:
+-	unlock_kernel();
++	mutex_unlock(&vcp->vc_mutex);
+ 	return (count ? count : retval);
+ }
+ 
+@@ -267,10 +271,10 @@ static int coda_psdev_open(struct inode * inode, struct file * file)
+ 	if (idx < 0 || idx >= MAX_CODADEVS)
+ 		return -ENODEV;
+ 
+-	lock_kernel();
+-
+ 	err = -EBUSY;
+ 	vcp = &coda_comms[idx];
++	mutex_lock(&vcp->vc_mutex);
++
+ 	if (!vcp->vc_inuse) {
+ 		vcp->vc_inuse++;
+ 
+@@ -284,7 +288,7 @@ static int coda_psdev_open(struct inode * inode, struct file * file)
+ 		err = 0;
+ 	}
+ 
+-	unlock_kernel();
++	mutex_unlock(&vcp->vc_mutex);
+ 	return err;
+ }
+ 
+@@ -299,7 +303,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
+ 		return -1;
+ 	}
+ 
+-	lock_kernel();
++	mutex_lock(&vcp->vc_mutex);
+ 
+ 	/* Wakeup clients so they can return. */
+ 	list_for_each_entry_safe(req, tmp, &vcp->vc_pending, uc_chain) {
+@@ -324,7 +328,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
+ 
+ 	file->private_data = NULL;
+ 	vcp->vc_inuse--;
+-	unlock_kernel();
++	mutex_unlock(&vcp->vc_mutex);
+ 	return 0;
+ }
+ 
+@@ -353,9 +357,11 @@ static int init_coda_psdev(void)
+ 		err = PTR_ERR(coda_psdev_class);
+ 		goto out_chrdev;
+ 	}		
+-	for (i = 0; i < MAX_CODADEVS; i++)
++	for (i = 0; i < MAX_CODADEVS; i++) {
++		mutex_init(&(&coda_comms[i])->vc_mutex);
+ 		device_create(coda_psdev_class, NULL,
+ 			      MKDEV(CODA_PSDEV_MAJOR, i), NULL, "cfs%d", i);
++	}
+ 	coda_sysctl_init();
+ 	goto out;
+ 
+diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
+index 4c258cb5266d..c3563cab9758 100644
+--- a/fs/coda/upcall.c
++++ b/fs/coda/upcall.c
+@@ -27,7 +27,7 @@
+ #include 
+ #include 
+ #include 
+-#include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -607,7 +607,8 @@ static void coda_unblock_signals(sigset_t *old)
+ 				 (r)->uc_opcode != CODA_RELEASE) || \
+ 				(r)->uc_flags & CODA_REQ_READ))
+ 
+-static inline void coda_waitfor_upcall(struct upc_req *req)
++static inline void coda_waitfor_upcall(struct venus_comm *vcp,
++				       struct upc_req *req)
+ {
+ 	DECLARE_WAITQUEUE(wait, current);
+ 	unsigned long timeout = jiffies + coda_timeout * HZ;
+@@ -640,10 +641,12 @@ static inline void coda_waitfor_upcall(struct upc_req *req)
+ 			break;
+ 		}
+ 
++		mutex_unlock(&vcp->vc_mutex);
+ 		if (blocked)
+ 			schedule_timeout(HZ);
+ 		else
+ 			schedule();
++		mutex_lock(&vcp->vc_mutex);
+ 	}
+ 	if (blocked)
+ 		coda_unblock_signals(&old);
+@@ -671,7 +674,7 @@ static int coda_upcall(struct venus_comm *vcp,
+ 	struct upc_req *req = NULL, *sig_req;
+ 	int error;
+ 
+-	lock_kernel();
++	mutex_lock(&vcp->vc_mutex);
+ 
+ 	if (!vcp->vc_inuse) {
+ 		printk(KERN_NOTICE "coda: Venus dead, not sending upcall\n");
+@@ -711,7 +714,7 @@ static int coda_upcall(struct venus_comm *vcp,
+ 	 * ENODEV.  */
+ 
+ 	/* Go to sleep.  Wake up on signals only after the timeout. */
+-	coda_waitfor_upcall(req);
++	coda_waitfor_upcall(vcp, req);
+ 
+ 	/* Op went through, interrupt or not... */
+ 	if (req->uc_flags & CODA_REQ_WRITE) {
+@@ -765,7 +768,7 @@ static int coda_upcall(struct venus_comm *vcp,
+ 
+ exit:
+ 	kfree(req);
+-	unlock_kernel();
++	mutex_unlock(&vcp->vc_mutex);
+ 	return error;
+ }
+ 
+@@ -806,11 +809,11 @@ static int coda_upcall(struct venus_comm *vcp,
+ int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out)
+ {
+ 	struct inode *inode = NULL;
+-	struct CodaFid *fid, *newfid;
++	struct CodaFid *fid = NULL, *newfid;
+ 	struct super_block *sb;
+ 
+ 	/* Handle invalidation requests. */
+-	lock_kernel();
++	mutex_lock(&vcp->vc_mutex);
+ 	sb = vcp->vc_sb;
+ 	if (!sb || !sb->s_root)
+ 		goto unlock_out;
+@@ -829,47 +832,53 @@ int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out)
+ 
+ 	case CODA_ZAPDIR:
+ 		fid = &out->coda_zapdir.CodaFid;
+-		inode = coda_fid_to_inode(fid, sb);
+-		if (inode) {
+-			coda_flag_inode_children(inode, C_PURGE);
+-			coda_flag_inode(inode, C_VATTR);
+-		}
+ 		break;
+ 
+ 	case CODA_ZAPFILE:
+ 		fid = &out->coda_zapfile.CodaFid;
+-		inode = coda_fid_to_inode(fid, sb);
+-		if (inode)
+-			coda_flag_inode(inode, C_VATTR);
+ 		break;
+ 
+ 	case CODA_PURGEFID:
+ 		fid = &out->coda_purgefid.CodaFid;
+-		inode = coda_fid_to_inode(fid, sb);
+-		if (inode) {
+-			coda_flag_inode_children(inode, C_PURGE);
+-
+-			/* catch the dentries later if some are still busy */
+-			coda_flag_inode(inode, C_PURGE);
+-			d_prune_aliases(inode);
+-
+-		}
+ 		break;
+ 
+ 	case CODA_REPLACE:
+ 		fid = &out->coda_replace.OldFid;
+-		newfid = &out->coda_replace.NewFid;
+-		inode = coda_fid_to_inode(fid, sb);
+-		if (inode)
+-			coda_replace_fid(inode, fid, newfid);
+ 		break;
+ 	}
++	if (fid)
++		inode = coda_fid_to_inode(fid, sb);
+ 
+ unlock_out:
+-	unlock_kernel();
++	mutex_unlock(&vcp->vc_mutex);
++
++	if (!inode)
++		return 0;
++
++	switch (opcode) {
++	case CODA_ZAPDIR:
++		coda_flag_inode_children(inode, C_PURGE);
++		coda_flag_inode(inode, C_VATTR);
++		break;
++
++	case CODA_ZAPFILE:
++		coda_flag_inode(inode, C_VATTR);
++		break;
++
++	case CODA_PURGEFID:
++		coda_flag_inode_children(inode, C_PURGE);
+ 
+-	if (inode)
+-		iput(inode);
++		/* catch the dentries later if some are still busy */
++		coda_flag_inode(inode, C_PURGE);
++		d_prune_aliases(inode);
++		break;
++
++	case CODA_REPLACE:
++		newfid = &out->coda_replace.NewFid;
++		coda_replace_fid(inode, fid, newfid);
++		break;
++	}
++	iput(inode);
+ 	return 0;
+ }
+ 
+diff --git a/include/linux/coda_psdev.h b/include/linux/coda_psdev.h
+index 1e60c5a41a5b..72f2d2f0af91 100644
+--- a/include/linux/coda_psdev.h
++++ b/include/linux/coda_psdev.h
+@@ -8,6 +8,7 @@
+ 
+ #ifdef __KERNEL__
+ #include 
++#include 
+ 
+ struct kstatfs;
+ 
+@@ -20,6 +21,7 @@ struct venus_comm {
+ 	int                 vc_inuse;
+ 	struct super_block *vc_sb;
+ 	struct backing_dev_info bdi;
++	struct mutex	    vc_mutex;
+ };
+ 
+ 

commit f7cc02b8715618e179242ba9cc10bdc5146ae565
+Author: Yoshihisa Abe 
+Date:   Mon Oct 25 02:03:45 2010 -0400
+
+    Coda: push BKL regions into coda_upcall()
+    
+    Now that shared inode state is locked using the cii->c_lock, the BKL is
+    only used to protect the upcall queues used to communicate with the
+    userspace cache manager. The remaining state is all local and we can
+    push the lock further down into coda_upcall().
+    
+    Signed-off-by: Yoshihisa Abe 
+    Signed-off-by: Jan Harkes 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/dir.c b/fs/coda/dir.c
+index 69fbbea75f1b..96fbeab77f2f 100644
+--- a/fs/coda/dir.c
++++ b/fs/coda/dir.c
+@@ -17,7 +17,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ #include 
+ 
+ #include 
+@@ -117,15 +116,11 @@ static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struc
+ 		goto exit;
+ 	}
+ 
+-	lock_kernel();
+-
+ 	error = venus_lookup(dir->i_sb, coda_i2f(dir), name, length,
+ 			     &type, &resfid);
+ 	if (!error)
+ 		error = coda_cnode_make(&inode, &resfid, dir->i_sb);
+ 
+-	unlock_kernel();
+-
+ 	if (error && error != -ENOENT)
+ 		return ERR_PTR(error);
+ 
+@@ -141,28 +136,24 @@ static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struc
+ 
+ int coda_permission(struct inode *inode, int mask)
+ {
+-        int error = 0;
++	int error;
+ 
+ 	mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
+  
+ 	if (!mask)
+-		return 0; 
++		return 0;
+ 
+ 	if ((mask & MAY_EXEC) && !execute_ok(inode))
+ 		return -EACCES;
+ 
+-	lock_kernel();
+-
+ 	if (coda_cache_check(inode, mask))
+-		goto out; 
++		return 0;
+ 
+-        error = venus_access(inode->i_sb, coda_i2f(inode), mask);
++	error = venus_access(inode->i_sb, coda_i2f(inode), mask);
+     
+ 	if (!error)
+ 		coda_cache_enter(inode, mask);
+ 
+- out:
+-	unlock_kernel();
+ 	return error;
+ }
+ 
+@@ -201,41 +192,34 @@ static inline void coda_dir_drop_nlink(struct inode *dir)
+ /* creation routines: create, mknod, mkdir, link, symlink */
+ static int coda_create(struct inode *dir, struct dentry *de, int mode, struct nameidata *nd)
+ {
+-        int error=0;
++	int error;
+ 	const char *name=de->d_name.name;
+ 	int length=de->d_name.len;
+ 	struct inode *inode;
+ 	struct CodaFid newfid;
+ 	struct coda_vattr attrs;
+ 
+-	lock_kernel();
+-
+-	if (coda_isroot(dir) && coda_iscontrol(name, length)) {
+-		unlock_kernel();
++	if (coda_isroot(dir) && coda_iscontrol(name, length))
+ 		return -EPERM;
+-	}
+ 
+ 	error = venus_create(dir->i_sb, coda_i2f(dir), name, length, 
+ 				0, mode, &newfid, &attrs);
+-
+-        if ( error ) {
+-		unlock_kernel();
+-		d_drop(de);
+-		return error;
+-	}
++	if (error)
++		goto err_out;
+ 
+ 	inode = coda_iget(dir->i_sb, &newfid, &attrs);
+-	if ( IS_ERR(inode) ) {
+-		unlock_kernel();
+-		d_drop(de);
+-		return PTR_ERR(inode);
++	if (IS_ERR(inode)) {
++		error = PTR_ERR(inode);
++		goto err_out;
+ 	}
+ 
+ 	/* invalidate the directory cnode's attributes */
+ 	coda_dir_update_mtime(dir);
+-	unlock_kernel();
+ 	d_instantiate(de, inode);
+ 	return 0;
++err_out:
++	d_drop(de);
++	return error;
+ }
+ 
+ static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
+@@ -247,36 +231,29 @@ static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
+ 	int error;
+ 	struct CodaFid newfid;
+ 
+-	lock_kernel();
+-
+-	if (coda_isroot(dir) && coda_iscontrol(name, len)) {
+-		unlock_kernel();
++	if (coda_isroot(dir) && coda_iscontrol(name, len))
+ 		return -EPERM;
+-	}
+ 
+ 	attrs.va_mode = mode;
+ 	error = venus_mkdir(dir->i_sb, coda_i2f(dir), 
+ 			       name, len, &newfid, &attrs);
+-        
+-        if ( error ) {
+-		unlock_kernel();
+-		d_drop(de);
+-		return error;
+-        }
++	if (error)
++		goto err_out;
+          
+ 	inode = coda_iget(dir->i_sb, &newfid, &attrs);
+-	if ( IS_ERR(inode) ) {
+-		unlock_kernel();
+-		d_drop(de);
+-		return PTR_ERR(inode);
++	if (IS_ERR(inode)) {
++		error = PTR_ERR(inode);
++		goto err_out;
+ 	}
+ 
+ 	/* invalidate the directory cnode's attributes */
+ 	coda_dir_inc_nlink(dir);
+ 	coda_dir_update_mtime(dir);
+-	unlock_kernel();
+ 	d_instantiate(de, inode);
+ 	return 0;
++err_out:
++	d_drop(de);
++	return error;
+ }
+ 
+ /* try to make de an entry in dir_inodde linked to source_de */ 
+@@ -288,52 +265,38 @@ static int coda_link(struct dentry *source_de, struct inode *dir_inode,
+ 	int len = de->d_name.len;
+ 	int error;
+ 
+-	lock_kernel();
+-
+-	if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) {
+-		unlock_kernel();
++	if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
+ 		return -EPERM;
+-	}
+ 
+ 	error = venus_link(dir_inode->i_sb, coda_i2f(inode),
+ 			   coda_i2f(dir_inode), (const char *)name, len);
+-
+ 	if (error) {
+ 		d_drop(de);
+-		goto out;
++		return error;
+ 	}
+ 
+ 	coda_dir_update_mtime(dir_inode);
+ 	atomic_inc(&inode->i_count);
+ 	d_instantiate(de, inode);
+ 	inc_nlink(inode);
+-
+-out:
+-	unlock_kernel();
+-	return(error);
++	return 0;
+ }
+ 
+ 
+ static int coda_symlink(struct inode *dir_inode, struct dentry *de,
+ 			const char *symname)
+ {
+-        const char *name = de->d_name.name;
++	const char *name = de->d_name.name;
+ 	int len = de->d_name.len;
+ 	int symlen;
+-	int error = 0;
+-
+-	lock_kernel();
++	int error;
+ 
+-	if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) {
+-		unlock_kernel();
++	if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
+ 		return -EPERM;
+-	}
+ 
+ 	symlen = strlen(symname);
+-	if ( symlen > CODA_MAXPATHLEN ) {
+-		unlock_kernel();
++	if (symlen > CODA_MAXPATHLEN)
+ 		return -ENAMETOOLONG;
+-	}
+ 
+ 	/*
+ 	 * This entry is now negative. Since we do not create
+@@ -344,10 +307,9 @@ static int coda_symlink(struct inode *dir_inode, struct dentry *de,
+ 			      symname, symlen);
+ 
+ 	/* mtime is no good anymore */
+-	if ( !error )
++	if (!error)
+ 		coda_dir_update_mtime(dir_inode);
+ 
+-	unlock_kernel();
+ 	return error;
+ }
+ 
+@@ -358,17 +320,12 @@ static int coda_unlink(struct inode *dir, struct dentry *de)
+ 	const char *name = de->d_name.name;
+ 	int len = de->d_name.len;
+ 
+-	lock_kernel();
+-
+ 	error = venus_remove(dir->i_sb, coda_i2f(dir), name, len);
+-	if ( error ) {
+-		unlock_kernel();
++	if (error)
+ 		return error;
+-	}
+ 
+ 	coda_dir_update_mtime(dir);
+ 	drop_nlink(de->d_inode);
+-	unlock_kernel();
+ 	return 0;
+ }
+ 
+@@ -378,8 +335,6 @@ static int coda_rmdir(struct inode *dir, struct dentry *de)
+ 	int len = de->d_name.len;
+ 	int error;
+ 
+-	lock_kernel();
+-
+ 	error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len);
+ 	if (!error) {
+ 		/* VFS may delete the child */
+@@ -390,7 +345,6 @@ static int coda_rmdir(struct inode *dir, struct dentry *de)
+ 		coda_dir_drop_nlink(dir);
+ 		coda_dir_update_mtime(dir);
+ 	}
+-	unlock_kernel();
+ 	return error;
+ }
+ 
+@@ -404,15 +358,12 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 	int new_length = new_dentry->d_name.len;
+ 	int error;
+ 
+-	lock_kernel();
+-
+ 	error = venus_rename(old_dir->i_sb, coda_i2f(old_dir),
+ 			     coda_i2f(new_dir), old_length, new_length,
+ 			     (const char *) old_name, (const char *)new_name);
+-
+-	if ( !error ) {
+-		if ( new_dentry->d_inode ) {
+-			if ( S_ISDIR(new_dentry->d_inode->i_mode) ) {
++	if (!error) {
++		if (new_dentry->d_inode) {
++			if (S_ISDIR(new_dentry->d_inode->i_mode)) {
+ 				coda_dir_drop_nlink(old_dir);
+ 				coda_dir_inc_nlink(new_dir);
+ 			}
+@@ -424,8 +375,6 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 			coda_flag_inode(new_dir, C_VATTR);
+ 		}
+ 	}
+-	unlock_kernel();
+-
+ 	return error;
+ }
+ 
+@@ -595,10 +544,7 @@ static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd)
+ 	struct inode *inode = de->d_inode;
+ 	struct coda_inode_info *cii;
+ 
+-	if (!inode)
+-		return 1;
+-	lock_kernel();
+-	if (coda_isroot(inode))
++	if (!inode || coda_isroot(inode))
+ 		goto out;
+ 	if (is_bad_inode(inode))
+ 		goto bad;
+@@ -621,12 +567,9 @@ static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd)
+ 	spin_lock(&cii->c_lock);
+ 	cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
+ 	spin_unlock(&cii->c_lock);
+-
+ bad:
+-	unlock_kernel();
+ 	return 0;
+ out:
+-	unlock_kernel();
+ 	return 1;
+ }
+ 
+@@ -659,20 +602,19 @@ static int coda_dentry_delete(struct dentry * dentry)
+ int coda_revalidate_inode(struct dentry *dentry)
+ {
+ 	struct coda_vattr attr;
+-	int error = 0;
++	int error;
+ 	int old_mode;
+ 	ino_t old_ino;
+ 	struct inode *inode = dentry->d_inode;
+ 	struct coda_inode_info *cii = ITOC(inode);
+ 
+-	lock_kernel();
+-	if ( !cii->c_flags )
+-		goto ok;
++	if (!cii->c_flags)
++		return 0;
+ 
+ 	if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) {
+ 		error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr);
+-		if ( error )
+-			goto return_bad;
++		if (error)
++			return -EIO;
+ 
+ 		/* this inode may be lost if:
+ 		   - it's ino changed 
+@@ -691,7 +633,7 @@ int coda_revalidate_inode(struct dentry *dentry)
+ 		/* the following can happen when a local fid is replaced 
+ 		   with a global one, here we lose and declare the inode bad */
+ 		if (inode->i_ino != old_ino)
+-			goto return_bad;
++			return -EIO;
+ 		
+ 		coda_flag_inode_children(inode, C_FLUSH);
+ 
+@@ -699,12 +641,5 @@ int coda_revalidate_inode(struct dentry *dentry)
+ 		cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
+ 		spin_unlock(&cii->c_lock);
+ 	}
+-
+-ok:
+-	unlock_kernel();
+ 	return 0;
+-
+-return_bad:
+-	unlock_kernel();
+-	return -EIO;
+ }
+diff --git a/fs/coda/file.c b/fs/coda/file.c
+index c4e395781d41..c8b50ba4366a 100644
+--- a/fs/coda/file.c
++++ b/fs/coda/file.c
+@@ -15,7 +15,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ #include 
+ #include 
+ #include 
+@@ -144,8 +143,6 @@ int coda_open(struct inode *coda_inode, struct file *coda_file)
+ 	if (!cfi)
+ 		return -ENOMEM;
+ 
+-	lock_kernel();
+-
+ 	error = venus_open(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags,
+ 			   &host_file);
+ 	if (!host_file)
+@@ -153,7 +150,6 @@ int coda_open(struct inode *coda_inode, struct file *coda_file)
+ 
+ 	if (error) {
+ 		kfree(cfi);
+-		unlock_kernel();
+ 		return error;
+ 	}
+ 
+@@ -165,8 +161,6 @@ int coda_open(struct inode *coda_inode, struct file *coda_file)
+ 
+ 	BUG_ON(coda_file->private_data != NULL);
+ 	coda_file->private_data = cfi;
+-
+-	unlock_kernel();
+ 	return 0;
+ }
+ 
+@@ -177,9 +171,7 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
+ 	struct coda_file_info *cfi;
+ 	struct coda_inode_info *cii;
+ 	struct inode *host_inode;
+-	int err = 0;
+-
+-	lock_kernel();
++	int err;
+ 
+ 	cfi = CODA_FTOC(coda_file);
+ 	BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
+@@ -203,8 +195,6 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
+ 	kfree(coda_file->private_data);
+ 	coda_file->private_data = NULL;
+ 
+-	unlock_kernel();
+-
+ 	/* VFS fput ignores the return value from file_operations->release, so
+ 	 * there is no use returning an error here */
+ 	return 0;
+@@ -215,7 +205,7 @@ int coda_fsync(struct file *coda_file, int datasync)
+ 	struct file *host_file;
+ 	struct inode *coda_inode = coda_file->f_path.dentry->d_inode;
+ 	struct coda_file_info *cfi;
+-	int err = 0;
++	int err;
+ 
+ 	if (!(S_ISREG(coda_inode->i_mode) || S_ISDIR(coda_inode->i_mode) ||
+ 	      S_ISLNK(coda_inode->i_mode)))
+@@ -226,11 +216,8 @@ int coda_fsync(struct file *coda_file, int datasync)
+ 	host_file = cfi->cfi_container;
+ 
+ 	err = vfs_fsync(host_file, datasync);
+-	if ( !err && !datasync ) {
+-		lock_kernel();
++	if (!err && !datasync)
+ 		err = venus_fsync(coda_inode->i_sb, coda_i2f(coda_inode));
+-		unlock_kernel();
+-	}
+ 
+ 	return err;
+ }
+diff --git a/fs/coda/inode.c b/fs/coda/inode.c
+index 0553f3bd7b1b..b7fa3e3d772f 100644
+--- a/fs/coda/inode.c
++++ b/fs/coda/inode.c
+@@ -150,8 +150,6 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
+ 	int error;
+ 	int idx;
+ 
+-	lock_kernel();
+-
+ 	idx = get_device_index((struct coda_mount_data *) data);
+ 
+ 	/* Ignore errors in data, for backward compatibility */
+@@ -161,23 +159,26 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
+ 	printk(KERN_INFO "coda_read_super: device index: %i\n", idx);
+ 
+ 	vc = &coda_comms[idx];
++	lock_kernel();
++
+ 	if (!vc->vc_inuse) {
+ 		printk("coda_read_super: No pseudo device\n");
+-		unlock_kernel();
+-		return -EINVAL;
++		error = -EINVAL;
++		goto unlock_out;
+ 	}
+ 
+-        if ( vc->vc_sb ) {
++	if (vc->vc_sb) {
+ 		printk("coda_read_super: Device already mounted\n");
+-		unlock_kernel();
+-		return -EBUSY;
++		error = -EBUSY;
++		goto unlock_out;
+ 	}
+ 
+ 	error = bdi_setup_and_register(&vc->bdi, "coda", BDI_CAP_MAP_COPY);
+ 	if (error)
+-		goto bdi_err;
++		goto unlock_out;
+ 
+ 	vc->vc_sb = sb;
++	unlock_kernel();
+ 
+ 	sb->s_fs_info = vc;
+ 	sb->s_flags |= MS_NOATIME;
+@@ -206,21 +207,23 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
+ 	printk("coda_read_super: rootinode is %ld dev %s\n", 
+ 	       root->i_ino, root->i_sb->s_id);
+ 	sb->s_root = d_alloc_root(root);
+-	if (!sb->s_root)
++	if (!sb->s_root) {
++		error = -EINVAL;
+ 		goto error;
+-	unlock_kernel();
++	}
+ 	return 0;
+ 
+- error:
+-	bdi_destroy(&vc->bdi);
+- bdi_err:
++error:
+ 	if (root)
+ 		iput(root);
+-	if (vc)
+-		vc->vc_sb = NULL;
+ 
++	lock_kernel();
++	bdi_destroy(&vc->bdi);
++	vc->vc_sb = NULL;
++	sb->s_fs_info = NULL;
++unlock_out:
+ 	unlock_kernel();
+-	return -EINVAL;
++	return error;
+ }
+ 
+ static void coda_put_super(struct super_block *sb)
+@@ -253,8 +256,6 @@ int coda_setattr(struct dentry *de, struct iattr *iattr)
+ 	struct coda_vattr vattr;
+ 	int error;
+ 
+-	lock_kernel();
+-	
+ 	memset(&vattr, 0, sizeof(vattr)); 
+ 
+ 	inode->i_ctime = CURRENT_TIME_SEC;
+@@ -264,13 +265,10 @@ int coda_setattr(struct dentry *de, struct iattr *iattr)
+ 	/* Venus is responsible for truncating the container-file!!! */
+ 	error = venus_setattr(inode->i_sb, coda_i2f(inode), &vattr);
+ 
+-	if ( !error ) {
++	if (!error) {
+ 	        coda_vattr_to_iattr(inode, &vattr); 
+ 		coda_cache_clear_inode(inode);
+ 	}
+-
+-	unlock_kernel();
+-
+ 	return error;
+ }
+ 
+@@ -284,12 +282,8 @@ static int coda_statfs(struct dentry *dentry, struct kstatfs *buf)
+ {
+ 	int error;
+ 	
+-	lock_kernel();
+-
+ 	error = venus_statfs(dentry, buf);
+ 
+-	unlock_kernel();
+-
+ 	if (error) {
+ 		/* fake something like AFS does */
+ 		buf->f_blocks = 9000000;
+diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c
+index 028a9a0f588b..2fd89b5c5c7b 100644
+--- a/fs/coda/pioctl.c
++++ b/fs/coda/pioctl.c
+@@ -23,8 +23,6 @@
+ #include 
+ #include 
+ 
+-#include 
+-
+ /* pioctl ops */
+ static int coda_ioctl_permission(struct inode *inode, int mask);
+ static long coda_pioctl(struct file *filp, unsigned int cmd,
+@@ -58,13 +56,9 @@ static long coda_pioctl(struct file *filp, unsigned int cmd,
+ 	struct inode *target_inode = NULL;
+ 	struct coda_inode_info *cnp;
+ 
+-	lock_kernel();
+-
+ 	/* get the Pioctl data arguments from user space */
+-	if (copy_from_user(&data, (void __user *)user_data, sizeof(data))) {
+-		error = -EINVAL;
+-		goto out;
+-	}
++	if (copy_from_user(&data, (void __user *)user_data, sizeof(data)))
++		return -EINVAL;
+ 
+ 	/*
+ 	 * Look up the pathname. Note that the pathname is in
+@@ -76,13 +70,12 @@ static long coda_pioctl(struct file *filp, unsigned int cmd,
+ 		error = user_lpath(data.path, &path);
+ 
+ 	if (error)
+-		goto out;
+-	else
+-		target_inode = path.dentry->d_inode;
++		return error;
++
++	target_inode = path.dentry->d_inode;
+ 
+ 	/* return if it is not a Coda inode */
+ 	if (target_inode->i_sb != inode->i_sb) {
+-		path_put(&path);
+ 		error = -EINVAL;
+ 		goto out;
+ 	}
+@@ -91,10 +84,7 @@ static long coda_pioctl(struct file *filp, unsigned int cmd,
+ 	cnp = ITOC(target_inode);
+ 
+ 	error = venus_pioctl(inode->i_sb, &(cnp->c_fid), cmd, &data);
+-
+-	path_put(&path);
+-
+ out:
+-	unlock_kernel();
++	path_put(&path);
+ 	return error;
+ }
+diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
+index fdc2f3ef7ecd..9a9248e632c6 100644
+--- a/fs/coda/psdev.c
++++ b/fs/coda/psdev.c
+@@ -108,16 +108,9 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
+ 	        return -EFAULT;
+ 
+         if (DOWNCALL(hdr.opcode)) {
+-		struct super_block *sb = NULL;
+-                union outputArgs *dcbuf;
++		union outputArgs *dcbuf;
+ 		int size = sizeof(*dcbuf);
+ 
+-		sb = vcp->vc_sb;
+-		if ( !sb ) {
+-                        count = nbytes;
+-                        goto out;
+-		}
+-
+ 		if  ( nbytes < sizeof(struct coda_out_hdr) ) {
+ 		        printk("coda_downcall opc %d uniq %d, not enough!\n",
+ 			       hdr.opcode, hdr.unique);
+@@ -137,9 +130,7 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
+ 		}
+ 
+ 		/* what downcall errors does Venus handle ? */
+-		lock_kernel();
+-		error = coda_downcall(hdr.opcode, dcbuf, sb);
+-		unlock_kernel();
++		error = coda_downcall(vcp, hdr.opcode, dcbuf);
+ 
+ 		CODA_FREE(dcbuf, nbytes);
+ 		if (error) {
+diff --git a/fs/coda/symlink.c b/fs/coda/symlink.c
+index 4513b7258458..af78f007a2b0 100644
+--- a/fs/coda/symlink.c
++++ b/fs/coda/symlink.c
+@@ -14,7 +14,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ 
+ #include 
+ #include 
+@@ -29,11 +28,9 @@ static int coda_symlink_filler(struct file *file, struct page *page)
+ 	unsigned int len = PAGE_SIZE;
+ 	char *p = kmap(page);
+ 
+-	lock_kernel();
+ 	cii = ITOC(inode);
+ 
+ 	error = venus_readlink(inode->i_sb, &cii->c_fid, p, &len);
+-	unlock_kernel();
+ 	if (error)
+ 		goto fail;
+ 	SetPageUptodate(page);
+diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
+index b8893ab6f9e6..4c258cb5266d 100644
+--- a/fs/coda/upcall.c
++++ b/fs/coda/upcall.c
+@@ -27,6 +27,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -667,18 +668,23 @@ static int coda_upcall(struct venus_comm *vcp,
+ {
+ 	union outputArgs *out;
+ 	union inputArgs *sig_inputArgs;
+-	struct upc_req *req, *sig_req;
+-	int error = 0;
++	struct upc_req *req = NULL, *sig_req;
++	int error;
++
++	lock_kernel();
+ 
+ 	if (!vcp->vc_inuse) {
+ 		printk(KERN_NOTICE "coda: Venus dead, not sending upcall\n");
+-		return -ENXIO;
++		error = -ENXIO;
++		goto exit;
+ 	}
+ 
+ 	/* Format the request message. */
+ 	req = kmalloc(sizeof(struct upc_req), GFP_KERNEL);
+-	if (!req)
+-		return -ENOMEM;
++	if (!req) {
++		error = -ENOMEM;
++		goto exit;
++	}
+ 
+ 	req->uc_data = (void *)buffer;
+ 	req->uc_flags = 0;
+@@ -759,6 +765,7 @@ static int coda_upcall(struct venus_comm *vcp,
+ 
+ exit:
+ 	kfree(req);
++	unlock_kernel();
+ 	return error;
+ }
+ 
+@@ -796,21 +803,24 @@ static int coda_upcall(struct venus_comm *vcp,
+  *
+  * CODA_REPLACE -- replace one CodaFid with another throughout the name cache */
+ 
+-int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
++int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out)
+ {
+ 	struct inode *inode = NULL;
+ 	struct CodaFid *fid, *newfid;
++	struct super_block *sb;
+ 
+ 	/* Handle invalidation requests. */
+-	if ( !sb || !sb->s_root)
+-		return 0;
++	lock_kernel();
++	sb = vcp->vc_sb;
++	if (!sb || !sb->s_root)
++		goto unlock_out;
+ 
+ 	switch (opcode) {
+ 	case CODA_FLUSH:
+ 		coda_cache_clear_all(sb);
+ 		shrink_dcache_sb(sb);
+ 		if (sb->s_root->d_inode)
+-		    coda_flag_inode(sb->s_root->d_inode, C_FLUSH);
++			coda_flag_inode(sb->s_root->d_inode, C_FLUSH);
+ 		break;
+ 
+ 	case CODA_PURGEUSER:
+@@ -855,9 +865,11 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
+ 		break;
+ 	}
+ 
++unlock_out:
++	unlock_kernel();
++
+ 	if (inode)
+ 		iput(inode);
+-
+ 	return 0;
+ }
+ 
+diff --git a/include/linux/coda_psdev.h b/include/linux/coda_psdev.h
+index 284b520934a0..1e60c5a41a5b 100644
+--- a/include/linux/coda_psdev.h
++++ b/include/linux/coda_psdev.h
+@@ -63,7 +63,7 @@ int venus_symlink(struct super_block *sb, struct CodaFid *fid,
+ int venus_access(struct super_block *sb, struct CodaFid *fid, int mask);
+ int venus_pioctl(struct super_block *sb, struct CodaFid *fid,
+ 		 unsigned int cmd, struct PioctlData *data);
+-int coda_downcall(int opcode, union outputArgs *out, struct super_block *sb);
++int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out);
+ int venus_fsync(struct super_block *sb, struct CodaFid *fid);
+ int venus_statfs(struct dentry *dentry, struct kstatfs *sfs);
+ 

commit b5ce1d83a62fc109d8e815b1fc71dcdb0d26bc49
+Author: Yoshihisa Abe 
+Date:   Mon Oct 25 02:03:44 2010 -0400
+
+    Coda: add spin lock to protect accesses to struct coda_inode_info.
+    
+    We mostly need it to protect cached user permissions. The c_flags field
+    is advisory, reading the wrong value is harmless and in the worst case
+    we hit a slow path where we have to make an extra upcall to the
+    userspace cache manager when revalidating a dentry or inode.
+    
+    Signed-off-by: Yoshihisa Abe 
+    Signed-off-by: Jan Harkes 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/cache.c b/fs/coda/cache.c
+index a5bf5771a22a..9060f08e70cf 100644
+--- a/fs/coda/cache.c
++++ b/fs/coda/cache.c
+@@ -17,6 +17,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ #include 
+@@ -31,19 +32,23 @@ void coda_cache_enter(struct inode *inode, int mask)
+ {
+ 	struct coda_inode_info *cii = ITOC(inode);
+ 
++	spin_lock(&cii->c_lock);
+ 	cii->c_cached_epoch = atomic_read(&permission_epoch);
+ 	if (cii->c_uid != current_fsuid()) {
+ 		cii->c_uid = current_fsuid();
+                 cii->c_cached_perm = mask;
+         } else
+                 cii->c_cached_perm |= mask;
++	spin_unlock(&cii->c_lock);
+ }
+ 
+ /* remove cached acl from an inode */
+ void coda_cache_clear_inode(struct inode *inode)
+ {
+ 	struct coda_inode_info *cii = ITOC(inode);
++	spin_lock(&cii->c_lock);
+ 	cii->c_cached_epoch = atomic_read(&permission_epoch) - 1;
++	spin_unlock(&cii->c_lock);
+ }
+ 
+ /* remove all acl caches */
+@@ -57,13 +62,15 @@ void coda_cache_clear_all(struct super_block *sb)
+ int coda_cache_check(struct inode *inode, int mask)
+ {
+ 	struct coda_inode_info *cii = ITOC(inode);
+-        int hit;
++	int hit;
+ 	
+-        hit = (mask & cii->c_cached_perm) == mask &&
+-		cii->c_uid == current_fsuid() &&
+-		cii->c_cached_epoch == atomic_read(&permission_epoch);
++	spin_lock(&cii->c_lock);
++	hit = (mask & cii->c_cached_perm) == mask &&
++	    cii->c_uid == current_fsuid() &&
++	    cii->c_cached_epoch == atomic_read(&permission_epoch);
++	spin_unlock(&cii->c_lock);
+ 
+-        return hit;
++	return hit;
+ }
+ 
+ 
+diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c
+index a7a780929eec..602240569c89 100644
+--- a/fs/coda/cnode.c
++++ b/fs/coda/cnode.c
+@@ -45,13 +45,15 @@ static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr)
+ static int coda_test_inode(struct inode *inode, void *data)
+ {
+ 	struct CodaFid *fid = (struct CodaFid *)data;
+-	return coda_fideq(&(ITOC(inode)->c_fid), fid);
++	struct coda_inode_info *cii = ITOC(inode);
++	return coda_fideq(&cii->c_fid, fid);
+ }
+ 
+ static int coda_set_inode(struct inode *inode, void *data)
+ {
+ 	struct CodaFid *fid = (struct CodaFid *)data;
+-	ITOC(inode)->c_fid = *fid;
++	struct coda_inode_info *cii = ITOC(inode);
++	cii->c_fid = *fid;
+ 	return 0;
+ }
+ 
+@@ -71,6 +73,7 @@ struct inode * coda_iget(struct super_block * sb, struct CodaFid * fid,
+ 		cii = ITOC(inode);
+ 		/* we still need to set i_ino for things like stat(2) */
+ 		inode->i_ino = hash;
++		/* inode is locked and unique, no need to grab cii->c_lock */
+ 		cii->c_mapcount = 0;
+ 		unlock_new_inode(inode);
+ 	}
+@@ -107,14 +110,20 @@ int coda_cnode_make(struct inode **inode, struct CodaFid *fid, struct super_bloc
+ }
+ 
+ 
++/* Although we treat Coda file identifiers as immutable, there is one
++ * special case for files created during a disconnection where they may
++ * not be globally unique. When an identifier collision is detected we
++ * first try to flush the cached inode from the kernel and finally
++ * resort to renaming/rehashing in-place. Userspace remembers both old
++ * and new values of the identifier to handle any in-flight upcalls.
++ * The real solution is to use globally unique UUIDs as identifiers, but
++ * retrofitting the existing userspace code for this is non-trivial. */
+ void coda_replace_fid(struct inode *inode, struct CodaFid *oldfid, 
+ 		      struct CodaFid *newfid)
+ {
+-	struct coda_inode_info *cii;
++	struct coda_inode_info *cii = ITOC(inode);
+ 	unsigned long hash = coda_f2i(newfid);
+ 	
+-	cii = ITOC(inode);
+-
+ 	BUG_ON(!coda_fideq(&cii->c_fid, oldfid));
+ 
+ 	/* replace fid and rehash inode */
+diff --git a/fs/coda/dir.c b/fs/coda/dir.c
+index ccd98b0f2b0b..69fbbea75f1b 100644
+--- a/fs/coda/dir.c
++++ b/fs/coda/dir.c
+@@ -18,6 +18,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ 
+@@ -617,7 +618,9 @@ static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd)
+ 		goto out;
+ 
+ 	/* clear the flags. */
++	spin_lock(&cii->c_lock);
+ 	cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
++	spin_unlock(&cii->c_lock);
+ 
+ bad:
+ 	unlock_kernel();
+@@ -691,7 +694,10 @@ int coda_revalidate_inode(struct dentry *dentry)
+ 			goto return_bad;
+ 		
+ 		coda_flag_inode_children(inode, C_FLUSH);
++
++		spin_lock(&cii->c_lock);
+ 		cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
++		spin_unlock(&cii->c_lock);
+ 	}
+ 
+ ok:
+diff --git a/fs/coda/file.c b/fs/coda/file.c
+index ad3cd2abeeb4..c4e395781d41 100644
+--- a/fs/coda/file.c
++++ b/fs/coda/file.c
+@@ -16,6 +16,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -109,19 +110,24 @@ coda_file_mmap(struct file *coda_file, struct vm_area_struct *vma)
+ 
+ 	coda_inode = coda_file->f_path.dentry->d_inode;
+ 	host_inode = host_file->f_path.dentry->d_inode;
++
++	cii = ITOC(coda_inode);
++	spin_lock(&cii->c_lock);
+ 	coda_file->f_mapping = host_file->f_mapping;
+ 	if (coda_inode->i_mapping == &coda_inode->i_data)
+ 		coda_inode->i_mapping = host_inode->i_mapping;
+ 
+ 	/* only allow additional mmaps as long as userspace isn't changing
+ 	 * the container file on us! */
+-	else if (coda_inode->i_mapping != host_inode->i_mapping)
++	else if (coda_inode->i_mapping != host_inode->i_mapping) {
++		spin_unlock(&cii->c_lock);
+ 		return -EBUSY;
++	}
+ 
+ 	/* keep track of how often the coda_inode/host_file has been mmapped */
+-	cii = ITOC(coda_inode);
+ 	cii->c_mapcount++;
+ 	cfi->cfi_mapcount++;
++	spin_unlock(&cii->c_lock);
+ 
+ 	return host_file->f_op->mmap(host_file, vma);
+ }
+@@ -185,11 +191,13 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
+ 	cii = ITOC(coda_inode);
+ 
+ 	/* did we mmap this file? */
++	spin_lock(&cii->c_lock);
+ 	if (coda_inode->i_mapping == &host_inode->i_data) {
+ 		cii->c_mapcount -= cfi->cfi_mapcount;
+ 		if (!cii->c_mapcount)
+ 			coda_inode->i_mapping = &coda_inode->i_data;
+ 	}
++	spin_unlock(&cii->c_lock);
+ 
+ 	fput(cfi->cfi_container);
+ 	kfree(coda_file->private_data);
+diff --git a/fs/coda/inode.c b/fs/coda/inode.c
+index bfe8179b1295..0553f3bd7b1b 100644
+--- a/fs/coda/inode.c
++++ b/fs/coda/inode.c
+@@ -16,6 +16,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -51,6 +52,7 @@ static struct inode *coda_alloc_inode(struct super_block *sb)
+ 	ei->c_flags = 0;
+ 	ei->c_uid = 0;
+ 	ei->c_cached_perm = 0;
++	spin_lock_init(&ei->c_lock);
+ 	return &ei->vfs_inode;
+ }
+ 
+diff --git a/include/linux/coda_fs_i.h b/include/linux/coda_fs_i.h
+index b3ef0c461578..e35071b1de0e 100644
+--- a/include/linux/coda_fs_i.h
++++ b/include/linux/coda_fs_i.h
+@@ -10,19 +10,24 @@
+ 
+ #include 
+ #include 
++#include 
+ #include 
+ 
+ /*
+  * coda fs inode data
++ * c_lock protects accesses to c_flags, c_mapcount, c_cached_epoch, c_uid and
++ * c_cached_perm.
++ * vfs_inode is set only when the inode is created and never changes.
++ * c_fid is set when the inode is created and should be considered immutable.
+  */
+ struct coda_inode_info {
+-        struct CodaFid	   c_fid;	/* Coda identifier */
+-        u_short	           c_flags;     /* flags (see below) */
+-	struct list_head   c_cilist;    /* list of all coda inodes */
++	struct CodaFid	   c_fid;	/* Coda identifier */
++	u_short	           c_flags;     /* flags (see below) */
+ 	unsigned int	   c_mapcount;  /* nr of times this inode is mapped */
+ 	unsigned int	   c_cached_epoch; /* epoch for cached permissions */
+ 	vuid_t		   c_uid;	/* fsuid for cached permissions */
+-        unsigned int       c_cached_perm; /* cached access permissions */
++	unsigned int       c_cached_perm; /* cached access permissions */
++	spinlock_t	   c_lock;
+ 	struct inode	   vfs_inode;
+ };
+ 
+diff --git a/include/linux/coda_linux.h b/include/linux/coda_linux.h
+index dcc228aa335a..2e914d0771b9 100644
+--- a/include/linux/coda_linux.h
++++ b/include/linux/coda_linux.h
+@@ -89,7 +89,11 @@ static __inline__ char *coda_i2s(struct inode *inode)
+ /* this will not zap the inode away */
+ static __inline__ void coda_flag_inode(struct inode *inode, int flag)
+ {
+-	ITOC(inode)->c_flags |= flag;
++	struct coda_inode_info *cii = ITOC(inode);
++
++	spin_lock(&cii->c_lock);
++	cii->c_flags |= flag;
++	spin_unlock(&cii->c_lock);
+ }		
+ 
+ #endif

commit 112d421df2fddc0278584b084f4fcfedd144c5f4
+Author: Jan Harkes 
+Date:   Fri Sep 17 23:26:01 2010 -0400
+
+    Coda: mount hangs because of missed REQ_WRITE rename
+    
+    Coda's REQ_* defines were renamed to avoid clashes with the block layer
+    (commit 4aeefdc69f7b: "coda: fixup clash with block layer REQ_*
+    defines").
+    
+    However one was missed and response messages are no longer matched with
+    requests and waiting threads are no longer woken up.  This patch fixes
+    this.
+    
+    Signed-off-by: Jan Harkes 
+    [ Also fixed up whitespace while at it  -Linus ]
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
+index de89645777c7..116af7546cf0 100644
+--- a/fs/coda/psdev.c
++++ b/fs/coda/psdev.c
+@@ -184,8 +184,8 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
+ 	}
+ 
+ 	/* adjust outsize. is this useful ?? */
+-        req->uc_outSize = nbytes;	
+-        req->uc_flags |= REQ_WRITE;
++	req->uc_outSize = nbytes;
++	req->uc_flags |= CODA_REQ_WRITE;
+ 	count = nbytes;
+ 
+ 	/* Convert filedescriptor into a file handle */

commit 8ffd1be6779c86ebc2a1013f43fdcee8bdbba2b7
+Author: Benjamin Gilbert 
+Date:   Mon Oct 19 12:58:55 2009 +0900
+
+    crypto: hash - Remove cra_u.{digest,hash}
+    
+    Remove unused digest_alg and hash_alg structs from crypto_alg union and
+    kill their definitions.  This also ensures that old-style digest/hash
+    algorithms maintained out of tree will break at build time rather than
+    oopsing at runtime.
+    
+    Signed-off-by: Benjamin Gilbert 
+    Signed-off-by: Herbert Xu 
+
+diff --git a/include/linux/crypto.h b/include/linux/crypto.h
+index fd929889e8dc..24d2e30f1b46 100644
+--- a/include/linux/crypto.h
++++ b/include/linux/crypto.h
+@@ -250,29 +250,6 @@ struct cipher_alg {
+ 	void (*cia_decrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
+ };
+ 
+-struct digest_alg {
+-	unsigned int dia_digestsize;
+-	void (*dia_init)(struct crypto_tfm *tfm);
+-	void (*dia_update)(struct crypto_tfm *tfm, const u8 *data,
+-			   unsigned int len);
+-	void (*dia_final)(struct crypto_tfm *tfm, u8 *out);
+-	int (*dia_setkey)(struct crypto_tfm *tfm, const u8 *key,
+-	                  unsigned int keylen);
+-};
+-
+-struct hash_alg {
+-	int (*init)(struct hash_desc *desc);
+-	int (*update)(struct hash_desc *desc, struct scatterlist *sg,
+-		      unsigned int nbytes);
+-	int (*final)(struct hash_desc *desc, u8 *out);
+-	int (*digest)(struct hash_desc *desc, struct scatterlist *sg,
+-		      unsigned int nbytes, u8 *out);
+-	int (*setkey)(struct crypto_hash *tfm, const u8 *key,
+-		      unsigned int keylen);
+-
+-	unsigned int digestsize;
+-};
+-
+ struct compress_alg {
+ 	int (*coa_compress)(struct crypto_tfm *tfm, const u8 *src,
+ 			    unsigned int slen, u8 *dst, unsigned int *dlen);
+@@ -293,8 +270,6 @@ struct rng_alg {
+ #define cra_aead	cra_u.aead
+ #define cra_blkcipher	cra_u.blkcipher
+ #define cra_cipher	cra_u.cipher
+-#define cra_digest	cra_u.digest
+-#define cra_hash	cra_u.hash
+ #define cra_compress	cra_u.compress
+ #define cra_rng		cra_u.rng
+ 
+@@ -320,8 +295,6 @@ struct crypto_alg {
+ 		struct aead_alg aead;
+ 		struct blkcipher_alg blkcipher;
+ 		struct cipher_alg cipher;
+-		struct digest_alg digest;
+-		struct hash_alg hash;
+ 		struct compress_alg compress;
+ 		struct rng_alg rng;
+ 	} cra_u;

commit 085751b96897280cc3087920f8c6e7d1283f6d00
+Author: Benjamin Gilbert 
+Date:   Mon Oct 19 12:57:20 2009 +0900
+
+    crypto: api - Remove digest case from procfs show handler
+    
+    Remove special handling of old-style digest algorithms from the procfs
+    show handler.
+    
+    Signed-off-by: Benjamin Gilbert 
+    Signed-off-by: Herbert Xu 
+
+diff --git a/crypto/proc.c b/crypto/proc.c
+index 5dc07e442fca..ff4cb4a357f9 100644
+--- a/crypto/proc.c
++++ b/crypto/proc.c
+@@ -115,13 +115,6 @@ static int c_show(struct seq_file *m, void *p)
+ 		seq_printf(m, "max keysize  : %u\n",
+ 					alg->cra_cipher.cia_max_keysize);
+ 		break;
+-		
+-	case CRYPTO_ALG_TYPE_DIGEST:
+-		seq_printf(m, "type         : digest\n");
+-		seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
+-		seq_printf(m, "digestsize   : %u\n",
+-		           alg->cra_digest.dia_digestsize);
+-		break;
+ 	case CRYPTO_ALG_TYPE_COMPRESS:
+ 		seq_printf(m, "type         : compression\n");
+ 		break;

commit 2141b6309b1fce535329c195cb5e5274a4c84ebc
+Author: Benjamin Gilbert 
+Date:   Mon Oct 19 12:53:37 2009 +0900
+
+    crypto: hash - Remove legacy hash/digest code
+    
+    6941c3a0 disabled compilation of the legacy digest code but didn't
+    actually remove it.  Rectify this.  Also, remove the crypto_hash_type
+    extern declaration from algapi.h now that the struct is gone.
+    
+    Signed-off-by: Benjamin Gilbert 
+    Signed-off-by: Herbert Xu 
+
+diff --git a/crypto/digest.c b/crypto/digest.c
+deleted file mode 100644
+index 5d3f1303da98..000000000000
+--- a/crypto/digest.c
++++ /dev/null
+@@ -1,240 +0,0 @@
+-/*
+- * Cryptographic API.
+- *
+- * Digest operations.
+- *
+- * Copyright (c) 2002 James Morris 
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the Free
+- * Software Foundation; either version 2 of the License, or (at your option) 
+- * any later version.
+- *
+- */
+-
+-#include 
+-#include 
+-#include 
+-#include 
+-#include 
+-#include 
+-#include 
+-#include 
+-#include 
+-
+-#include "internal.h"
+-
+-static int init(struct hash_desc *desc)
+-{
+-	struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
+-
+-	tfm->__crt_alg->cra_digest.dia_init(tfm);
+-	return 0;
+-}
+-
+-static int update2(struct hash_desc *desc,
+-		   struct scatterlist *sg, unsigned int nbytes)
+-{
+-	struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
+-	unsigned int alignmask = crypto_tfm_alg_alignmask(tfm);
+-
+-	if (!nbytes)
+-		return 0;
+-
+-	for (;;) {
+-		struct page *pg = sg_page(sg);
+-		unsigned int offset = sg->offset;
+-		unsigned int l = sg->length;
+-
+-		if (unlikely(l > nbytes))
+-			l = nbytes;
+-		nbytes -= l;
+-
+-		do {
+-			unsigned int bytes_from_page = min(l, ((unsigned int)
+-							   (PAGE_SIZE)) - 
+-							   offset);
+-			char *src = crypto_kmap(pg, 0);
+-			char *p = src + offset;
+-
+-			if (unlikely(offset & alignmask)) {
+-				unsigned int bytes =
+-					alignmask + 1 - (offset & alignmask);
+-				bytes = min(bytes, bytes_from_page);
+-				tfm->__crt_alg->cra_digest.dia_update(tfm, p,
+-								      bytes);
+-				p += bytes;
+-				bytes_from_page -= bytes;
+-				l -= bytes;
+-			}
+-			tfm->__crt_alg->cra_digest.dia_update(tfm, p,
+-							      bytes_from_page);
+-			crypto_kunmap(src, 0);
+-			crypto_yield(desc->flags);
+-			offset = 0;
+-			pg++;
+-			l -= bytes_from_page;
+-		} while (l > 0);
+-
+-		if (!nbytes)
+-			break;
+-		sg = scatterwalk_sg_next(sg);
+-	}
+-
+-	return 0;
+-}
+-
+-static int update(struct hash_desc *desc,
+-		  struct scatterlist *sg, unsigned int nbytes)
+-{
+-	if (WARN_ON_ONCE(in_irq()))
+-		return -EDEADLK;
+-	return update2(desc, sg, nbytes);
+-}
+-
+-static int final(struct hash_desc *desc, u8 *out)
+-{
+-	struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
+-	unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
+-	struct digest_alg *digest = &tfm->__crt_alg->cra_digest;
+-
+-	if (unlikely((unsigned long)out & alignmask)) {
+-		unsigned long align = alignmask + 1;
+-		unsigned long addr = (unsigned long)crypto_tfm_ctx(tfm);
+-		u8 *dst = (u8 *)ALIGN(addr, align) +
+-			  ALIGN(tfm->__crt_alg->cra_ctxsize, align);
+-
+-		digest->dia_final(tfm, dst);
+-		memcpy(out, dst, digest->dia_digestsize);
+-	} else
+-		digest->dia_final(tfm, out);
+-
+-	return 0;
+-}
+-
+-static int nosetkey(struct crypto_hash *tfm, const u8 *key, unsigned int keylen)
+-{
+-	crypto_hash_clear_flags(tfm, CRYPTO_TFM_RES_MASK);
+-	return -ENOSYS;
+-}
+-
+-static int setkey(struct crypto_hash *hash, const u8 *key, unsigned int keylen)
+-{
+-	struct crypto_tfm *tfm = crypto_hash_tfm(hash);
+-
+-	crypto_hash_clear_flags(hash, CRYPTO_TFM_RES_MASK);
+-	return tfm->__crt_alg->cra_digest.dia_setkey(tfm, key, keylen);
+-}
+-
+-static int digest(struct hash_desc *desc,
+-		  struct scatterlist *sg, unsigned int nbytes, u8 *out)
+-{
+-	if (WARN_ON_ONCE(in_irq()))
+-		return -EDEADLK;
+-
+-	init(desc);
+-	update2(desc, sg, nbytes);
+-	return final(desc, out);
+-}
+-
+-int crypto_init_digest_ops(struct crypto_tfm *tfm)
+-{
+-	struct hash_tfm *ops = &tfm->crt_hash;
+-	struct digest_alg *dalg = &tfm->__crt_alg->cra_digest;
+-
+-	if (dalg->dia_digestsize > PAGE_SIZE / 8)
+-		return -EINVAL;
+-	
+-	ops->init	= init;
+-	ops->update	= update;
+-	ops->final	= final;
+-	ops->digest	= digest;
+-	ops->setkey	= dalg->dia_setkey ? setkey : nosetkey;
+-	ops->digestsize	= dalg->dia_digestsize;
+-	
+-	return 0;
+-}
+-
+-void crypto_exit_digest_ops(struct crypto_tfm *tfm)
+-{
+-}
+-
+-static int digest_async_nosetkey(struct crypto_ahash *tfm_async, const u8 *key,
+-			unsigned int keylen)
+-{
+-	crypto_ahash_clear_flags(tfm_async, CRYPTO_TFM_RES_MASK);
+-	return -ENOSYS;
+-}
+-
+-static int digest_async_setkey(struct crypto_ahash *tfm_async, const u8 *key,
+-			unsigned int keylen)
+-{
+-	struct crypto_tfm    *tfm        = crypto_ahash_tfm(tfm_async);
+-	struct digest_alg    *dalg       = &tfm->__crt_alg->cra_digest;
+-
+-	crypto_ahash_clear_flags(tfm_async, CRYPTO_TFM_RES_MASK);
+-	return dalg->dia_setkey(tfm, key, keylen);
+-}
+-
+-static int digest_async_init(struct ahash_request *req)
+-{
+-	struct crypto_tfm *tfm  = req->base.tfm;
+-	struct digest_alg *dalg = &tfm->__crt_alg->cra_digest;
+-
+-	dalg->dia_init(tfm);
+-	return 0;
+-}
+-
+-static int digest_async_update(struct ahash_request *req)
+-{
+-	struct crypto_tfm *tfm = req->base.tfm;
+-	struct hash_desc  desc = {
+-		.tfm   = __crypto_hash_cast(tfm),
+-		.flags = req->base.flags,
+-	};
+-
+-	update(&desc, req->src, req->nbytes);
+-	return 0;
+-}
+-
+-static int digest_async_final(struct ahash_request *req)
+-{
+-	struct crypto_tfm *tfm  = req->base.tfm;
+-	struct hash_desc  desc = {
+-		.tfm   = __crypto_hash_cast(tfm),
+-		.flags = req->base.flags,
+-	};
+-
+-	final(&desc, req->result);
+-	return 0;
+-}
+-
+-static int digest_async_digest(struct ahash_request *req)
+-{
+-	struct crypto_tfm *tfm  = req->base.tfm;
+-	struct hash_desc  desc = {
+-		.tfm   = __crypto_hash_cast(tfm),
+-		.flags = req->base.flags,
+-	};
+-
+-	return digest(&desc, req->src, req->nbytes, req->result);
+-}
+-
+-int crypto_init_digest_ops_async(struct crypto_tfm *tfm)
+-{
+-	struct ahash_tfm  *crt  = &tfm->crt_ahash;
+-	struct digest_alg *dalg = &tfm->__crt_alg->cra_digest;
+-
+-	if (dalg->dia_digestsize > PAGE_SIZE / 8)
+-		return -EINVAL;
+-
+-	crt->init       = digest_async_init;
+-	crt->update     = digest_async_update;
+-	crt->final      = digest_async_final;
+-	crt->digest     = digest_async_digest;
+-	crt->setkey     = dalg->dia_setkey ? digest_async_setkey :
+-						digest_async_nosetkey;
+-	crt->digestsize = dalg->dia_digestsize;
+-
+-	return 0;
+-}
+diff --git a/crypto/hash.c b/crypto/hash.c
+deleted file mode 100644
+index cb86b19fd105..000000000000
+--- a/crypto/hash.c
++++ /dev/null
+@@ -1,183 +0,0 @@
+-/*
+- * Cryptographic Hash operations.
+- * 
+- * Copyright (c) 2006 Herbert Xu 
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the Free
+- * Software Foundation; either version 2 of the License, or (at your option) 
+- * any later version.
+- */
+-
+-#include 
+-#include 
+-#include 
+-#include 
+-#include 
+-#include 
+-
+-#include "internal.h"
+-
+-static unsigned int crypto_hash_ctxsize(struct crypto_alg *alg, u32 type,
+-					u32 mask)
+-{
+-	return alg->cra_ctxsize;
+-}
+-
+-static int hash_setkey_unaligned(struct crypto_hash *crt, const u8 *key,
+-		                 unsigned int keylen)
+-{
+-	struct crypto_tfm *tfm = crypto_hash_tfm(crt);
+-	struct hash_alg *alg = &tfm->__crt_alg->cra_hash;
+-	unsigned long alignmask = crypto_hash_alignmask(crt);
+-	int ret;
+-	u8 *buffer, *alignbuffer;
+-	unsigned long absize;
+-
+-	absize = keylen + alignmask;
+-	buffer = kmalloc(absize, GFP_ATOMIC);
+-	if (!buffer)
+-		return -ENOMEM;
+-
+-	alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
+-	memcpy(alignbuffer, key, keylen);
+-	ret = alg->setkey(crt, alignbuffer, keylen);
+-	memset(alignbuffer, 0, keylen);
+-	kfree(buffer);
+-	return ret;
+-}
+-
+-static int hash_setkey(struct crypto_hash *crt, const u8 *key,
+-		       unsigned int keylen)
+-{
+-	struct crypto_tfm *tfm = crypto_hash_tfm(crt);
+-	struct hash_alg *alg = &tfm->__crt_alg->cra_hash;
+-	unsigned long alignmask = crypto_hash_alignmask(crt);
+-
+-	if ((unsigned long)key & alignmask)
+-		return hash_setkey_unaligned(crt, key, keylen);
+-
+-	return alg->setkey(crt, key, keylen);
+-}
+-
+-static int hash_async_setkey(struct crypto_ahash *tfm_async, const u8 *key,
+-			unsigned int keylen)
+-{
+-	struct crypto_tfm  *tfm      = crypto_ahash_tfm(tfm_async);
+-	struct crypto_hash *tfm_hash = __crypto_hash_cast(tfm);
+-	struct hash_alg    *alg      = &tfm->__crt_alg->cra_hash;
+-
+-	return alg->setkey(tfm_hash, key, keylen);
+-}
+-
+-static int hash_async_init(struct ahash_request *req)
+-{
+-	struct crypto_tfm *tfm = req->base.tfm;
+-	struct hash_alg   *alg = &tfm->__crt_alg->cra_hash;
+-	struct hash_desc  desc = {
+-		.tfm = __crypto_hash_cast(tfm),
+-		.flags = req->base.flags,
+-	};
+-
+-	return alg->init(&desc);
+-}
+-
+-static int hash_async_update(struct ahash_request *req)
+-{
+-	struct crypto_tfm *tfm = req->base.tfm;
+-	struct hash_alg   *alg = &tfm->__crt_alg->cra_hash;
+-	struct hash_desc  desc = {
+-		.tfm = __crypto_hash_cast(tfm),
+-		.flags = req->base.flags,
+-	};
+-
+-	return alg->update(&desc, req->src, req->nbytes);
+-}
+-
+-static int hash_async_final(struct ahash_request *req)
+-{
+-	struct crypto_tfm *tfm = req->base.tfm;
+-	struct hash_alg   *alg = &tfm->__crt_alg->cra_hash;
+-	struct hash_desc  desc = {
+-		.tfm = __crypto_hash_cast(tfm),
+-		.flags = req->base.flags,
+-	};
+-
+-	return alg->final(&desc, req->result);
+-}
+-
+-static int hash_async_digest(struct ahash_request *req)
+-{
+-	struct crypto_tfm *tfm = req->base.tfm;
+-	struct hash_alg   *alg = &tfm->__crt_alg->cra_hash;
+-	struct hash_desc  desc = {
+-		.tfm = __crypto_hash_cast(tfm),
+-		.flags = req->base.flags,
+-	};
+-
+-	return alg->digest(&desc, req->src, req->nbytes, req->result);
+-}
+-
+-static int crypto_init_hash_ops_async(struct crypto_tfm *tfm)
+-{
+-	struct ahash_tfm *crt = &tfm->crt_ahash;
+-	struct hash_alg  *alg = &tfm->__crt_alg->cra_hash;
+-
+-	crt->init       = hash_async_init;
+-	crt->update     = hash_async_update;
+-	crt->final      = hash_async_final;
+-	crt->digest     = hash_async_digest;
+-	crt->setkey     = hash_async_setkey;
+-	crt->digestsize = alg->digestsize;
+-
+-	return 0;
+-}
+-
+-static int crypto_init_hash_ops_sync(struct crypto_tfm *tfm)
+-{
+-	struct hash_tfm *crt = &tfm->crt_hash;
+-	struct hash_alg *alg = &tfm->__crt_alg->cra_hash;
+-
+-	crt->init       = alg->init;
+-	crt->update     = alg->update;
+-	crt->final      = alg->final;
+-	crt->digest     = alg->digest;
+-	crt->setkey     = hash_setkey;
+-	crt->digestsize = alg->digestsize;
+-
+-	return 0;
+-}
+-
+-static int crypto_init_hash_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
+-{
+-	struct hash_alg *alg = &tfm->__crt_alg->cra_hash;
+-
+-	if (alg->digestsize > PAGE_SIZE / 8)
+-		return -EINVAL;
+-
+-	if ((mask & CRYPTO_ALG_TYPE_HASH_MASK) != CRYPTO_ALG_TYPE_HASH_MASK)
+-		return crypto_init_hash_ops_async(tfm);
+-	else
+-		return crypto_init_hash_ops_sync(tfm);
+-}
+-
+-static void crypto_hash_show(struct seq_file *m, struct crypto_alg *alg)
+-	__attribute__ ((unused));
+-static void crypto_hash_show(struct seq_file *m, struct crypto_alg *alg)
+-{
+-	seq_printf(m, "type         : hash\n");
+-	seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
+-	seq_printf(m, "digestsize   : %u\n", alg->cra_hash.digestsize);
+-}
+-
+-const struct crypto_type crypto_hash_type = {
+-	.ctxsize = crypto_hash_ctxsize,
+-	.init = crypto_init_hash_ops,
+-#ifdef CONFIG_PROC_FS
+-	.show = crypto_hash_show,
+-#endif
+-};
+-EXPORT_SYMBOL_GPL(crypto_hash_type);
+-
+-MODULE_LICENSE("GPL");
+-MODULE_DESCRIPTION("Generic cryptographic hash type");
+diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h
+index 1ffb53f74d37..fc0d575c71e0 100644
+--- a/include/crypto/algapi.h
++++ b/include/crypto/algapi.h
+@@ -106,7 +106,6 @@ struct blkcipher_walk {
+ extern const struct crypto_type crypto_ablkcipher_type;
+ extern const struct crypto_type crypto_aead_type;
+ extern const struct crypto_type crypto_blkcipher_type;
+-extern const struct crypto_type crypto_hash_type;
+ 
+ void crypto_mod_put(struct crypto_alg *alg);
+ 

commit d3fec424b23c47686efcf3f2004c3f1c1cee4d9c
+Author: Jan Harkes 
+Date:   Sat Jul 21 04:37:26 2007 -0700
+
+    coda: remove CODA_STORE/CODA_RELEASE upcalls
+    
+    This is an variation on the patch sent by Christoph Hellwig which kills
+    file_count abuse by the Coda kernel module by moving the coda_flush
+    functionality into coda_release.  However part of reason we were using the
+    coda_flush callback was to allow Coda to pass errors that occur during
+    writeback from the userspace cache manager back to close().
+    
+    As Al Viro explained on linux-fsdevel, it is impossible to guarantee that
+    such errors can in fact be returned back to the caller.  There are many
+    cases where the last reference to a file is not released by the close
+    system call and it is also impossible to pick some close as a 'last-close'
+    and delay it until all other references have been destroyed.
+    
+    The CODA_STORE/CODA_RELEASE upcall combination is clearly a broken design,
+    and it is better to remove it completely.
+    
+    Signed-off-by: Jan Harkes 
+    Cc: Christoph Hellwig 
+    Cc: Al Viro 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/dir.c b/fs/coda/dir.c
+index 8e61236abf4a..f89ff083079b 100644
+--- a/fs/coda/dir.c
++++ b/fs/coda/dir.c
+@@ -86,7 +86,6 @@ const struct file_operations coda_dir_operations = {
+ 	.read		= generic_read_dir,
+ 	.readdir	= coda_readdir,
+ 	.open		= coda_open,
+-	.flush		= coda_flush,
+ 	.release	= coda_release,
+ 	.fsync		= coda_fsync,
+ };
+diff --git a/fs/coda/file.c b/fs/coda/file.c
+index 7594962604c2..29137ff3ca67 100644
+--- a/fs/coda/file.c
++++ b/fs/coda/file.c
+@@ -25,10 +25,6 @@
+ 
+ #include "coda_int.h"
+ 
+-/* if CODA_STORE fails with EOPNOTSUPP, venus clearly doesn't support
+- * CODA_STORE/CODA_RELEASE and we fall back on using the CODA_CLOSE upcall */
+-static int use_coda_close;
+-
+ static ssize_t
+ coda_file_read(struct file *coda_file, char __user *buf, size_t count, loff_t *ppos)
+ {
+@@ -163,47 +159,6 @@ int coda_open(struct inode *coda_inode, struct file *coda_file)
+ 	return 0;
+ }
+ 
+-int coda_flush(struct file *coda_file, fl_owner_t id)
+-{
+-	unsigned short flags = coda_file->f_flags & ~O_EXCL;
+-	unsigned short coda_flags = coda_flags_to_cflags(flags);
+-	struct coda_file_info *cfi;
+-	struct inode *coda_inode;
+-	int err = 0, fcnt;
+-
+-	lock_kernel();
+-
+-	/* last close semantics */
+-	fcnt = file_count(coda_file);
+-	if (fcnt > 1)
+-		goto out;
+-
+-	/* No need to make an upcall when we have not made any modifications
+-	 * to the file */
+-	if ((coda_file->f_flags & O_ACCMODE) == O_RDONLY)
+-		goto out;
+-
+-	if (use_coda_close)
+-		goto out;
+-
+-	cfi = CODA_FTOC(coda_file);
+-	BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
+-
+-	coda_inode = coda_file->f_path.dentry->d_inode;
+-
+-	err = venus_store(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags,
+-			  coda_file->f_uid);
+-
+-	if (err == -EOPNOTSUPP) {
+-		use_coda_close = 1;
+-		err = 0;
+-	}
+-
+-out:
+-	unlock_kernel();
+-	return err;
+-}
+-
+ int coda_release(struct inode *coda_inode, struct file *coda_file)
+ {
+ 	unsigned short flags = (coda_file->f_flags) & (~O_EXCL);
+@@ -215,21 +170,11 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
+ 
+ 	lock_kernel();
+ 
+-	if (!use_coda_close) {
+-		err = venus_release(coda_inode->i_sb, coda_i2f(coda_inode),
+-				    coda_flags);
+-		if (err == -EOPNOTSUPP) {
+-			use_coda_close = 1;
+-			err = 0;
+-		}
+-	}
+-
+ 	cfi = CODA_FTOC(coda_file);
+ 	BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
+ 
+-	if (use_coda_close)
+-		err = venus_close(coda_inode->i_sb, coda_i2f(coda_inode),
+-				  coda_flags, coda_file->f_uid);
++	err = venus_close(coda_inode->i_sb, coda_i2f(coda_inode),
++			  coda_flags, coda_file->f_uid);
+ 
+ 	host_inode = cfi->cfi_container->f_path.dentry->d_inode;
+ 	cii = ITOC(coda_inode);
+@@ -246,7 +191,10 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
+ 	coda_file->private_data = NULL;
+ 
+ 	unlock_kernel();
+-	return err;
++
++	/* VFS fput ignores the return value from file_operations->release, so
++	 * there is no use returning an error here */
++	return 0;
+ }
+ 
+ int coda_fsync(struct file *coda_file, struct dentry *coda_dentry, int datasync)
+@@ -288,7 +236,6 @@ const struct file_operations coda_file_operations = {
+ 	.write		= coda_file_write,
+ 	.mmap		= coda_file_mmap,
+ 	.open		= coda_open,
+-	.flush		= coda_flush,
+ 	.release	= coda_release,
+ 	.fsync		= coda_fsync,
+ 	.splice_read	= coda_file_splice_read,
+diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
+index cd561d2e90b0..cdb4c07a7870 100644
+--- a/fs/coda/upcall.c
++++ b/fs/coda/upcall.c
+@@ -160,55 +160,8 @@ int venus_lookup(struct super_block *sb, struct CodaFid *fid,
+ 	return error;
+ }
+ 
+-int venus_store(struct super_block *sb, struct CodaFid *fid, int flags,
+-                vuid_t uid)
+-{
+-        union inputArgs *inp;
+-        union outputArgs *outp;
+-        int insize, outsize, error;
+-#ifdef CONFIG_CODA_FS_OLD_API
+-	struct coda_cred cred = { 0, };
+-	cred.cr_fsuid = uid;
+-#endif
+-	
+-	insize = SIZE(store);
+-	UPARG(CODA_STORE);
+-	
+-#ifdef CONFIG_CODA_FS_OLD_API
+-	memcpy(&(inp->ih.cred), &cred, sizeof(cred));
+-#else
+-	inp->ih.uid = uid;
+-#endif
+-	
+-        inp->coda_store.VFid = *fid;
+-        inp->coda_store.flags = flags;
+-
+-	error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
+-
+-	CODA_FREE(inp, insize);
+-        return error;
+-}
+-
+-int venus_release(struct super_block *sb, struct CodaFid *fid, int flags)
+-{
+-        union inputArgs *inp;
+-        union outputArgs *outp;
+-        int insize, outsize, error;
+-	
+-	insize = SIZE(release);
+-	UPARG(CODA_RELEASE);
+-	
+-	inp->coda_release.VFid = *fid;
+-	inp->coda_release.flags = flags;
+-
+-	error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
+-
+-	CODA_FREE(inp, insize);
+-	return error;
+-}
+-
+ int venus_close(struct super_block *sb, struct CodaFid *fid, int flags,
+-                vuid_t uid)
++		vuid_t uid)
+ {
+ 	union inputArgs *inp;
+ 	union outputArgs *outp;
+diff --git a/include/linux/coda_linux.h b/include/linux/coda_linux.h
+index c4079b403e9e..1c47a34aa794 100644
+--- a/include/linux/coda_linux.h
++++ b/include/linux/coda_linux.h
+@@ -36,7 +36,6 @@ extern const struct file_operations coda_ioctl_operations;
+ 
+ /* operations shared over more than one file */
+ int coda_open(struct inode *i, struct file *f);
+-int coda_flush(struct file *f, fl_owner_t id);
+ int coda_release(struct inode *i, struct file *f);
+ int coda_permission(struct inode *inode, int mask, struct nameidata *nd);
+ int coda_revalidate_inode(struct dentry *);
+diff --git a/include/linux/coda_psdev.h b/include/linux/coda_psdev.h
+index aa8f454b3b77..07ae8f846055 100644
+--- a/include/linux/coda_psdev.h
++++ b/include/linux/coda_psdev.h
+@@ -33,9 +33,6 @@ int venus_setattr(struct super_block *, struct CodaFid *, struct coda_vattr *);
+ int venus_lookup(struct super_block *sb, struct CodaFid *fid, 
+ 		 const char *name, int length, int *type, 
+ 		 struct CodaFid *resfid);
+-int venus_store(struct super_block *sb, struct CodaFid *fid, int flags,
+-		vuid_t uid);
+-int venus_release(struct super_block *sb, struct CodaFid *fid, int flags);
+ int venus_close(struct super_block *sb, struct CodaFid *fid, int flags,
+ 		vuid_t uid);
+ int venus_open(struct super_block *sb, struct CodaFid *fid, int flags,

commit 5b7f13bd26a0c1d394a1a1f2bb6de5130c3a3843
+Author: Jan Harkes 
+Date:   Thu Jul 19 01:48:52 2007 -0700
+
+    coda: update module information
+    
+    Signed-off-by: Jan Harkes 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
+index e3a0a4164d5d..dcc6aead70f5 100644
+--- a/fs/coda/psdev.c
++++ b/fs/coda/psdev.c
+@@ -373,21 +373,20 @@ static int init_coda_psdev(void)
+ 	return err;
+ }
+ 
+-
+-MODULE_AUTHOR("Peter J. Braam ");
++MODULE_AUTHOR("Jan Harkes, Peter J. Braam");
++MODULE_DESCRIPTION("Coda Distributed File System VFS interface");
++MODULE_ALIAS_CHARDEV_MAJOR(CODA_PSDEV_MAJOR);
+ MODULE_LICENSE("GPL");
++#ifdef CONFIG_CODA_FS_OLD_API
++MODULE_VERSION("5.3.21");
++#else
++MODULE_VERSION("6.6");
++#endif
+ 
+ static int __init init_coda(void)
+ {
+ 	int status;
+ 	int i;
+-	printk(KERN_INFO "Coda Kernel/Venus communications, "
+-#ifdef CONFIG_CODA_FS_OLD_API
+-	       "v5.3.20"
+-#else
+-	       "v6.0.0"
+-#endif
+-	       ", coda@cs.cmu.edu\n");
+ 
+ 	status = coda_init_inodecache();
+ 	if (status)

commit 3cf01f28c303be34f18cb4f6204cf1bdfe12ba7c
+Author: Jan Harkes 
+Date:   Thu Jul 19 01:48:51 2007 -0700
+
+    coda: remove statistics counters from /proc/fs/coda
+    
+    Similar information can easily be obtained with strace -c.
+    
+    Signed-off-by: Jan Harkes 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/coda_int.h b/fs/coda/coda_int.h
+index 9e6338fea514..8ccd5ed81d9c 100644
+--- a/fs/coda/coda_int.h
++++ b/fs/coda/coda_int.h
+@@ -1,12 +1,19 @@
+ #ifndef _CODA_INT_
+ #define _CODA_INT_
+ 
++struct dentry;
++
+ extern struct file_system_type coda_fs_type;
++extern unsigned long coda_timeout;
++extern int coda_hard;
++extern int coda_fake_statfs;
+ 
+ void coda_destroy_inodecache(void);
+ int coda_init_inodecache(void);
+ int coda_fsync(struct file *coda_file, struct dentry *coda_dentry,
+ 	       int datasync);
++void coda_sysctl_init(void);
++void coda_sysctl_clean(void);
+ 
+ #endif  /*  _CODA_INT_  */
+ 
+diff --git a/fs/coda/dir.c b/fs/coda/dir.c
+index 0c6c48ca7496..04a3dd84c993 100644
+--- a/fs/coda/dir.c
++++ b/fs/coda/dir.c
+@@ -25,7 +25,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ 
+ #include "coda_int.h"
+ 
+@@ -148,8 +147,6 @@ int coda_permission(struct inode *inode, int mask, struct nameidata *nd)
+ 
+ 	lock_kernel();
+ 
+-	coda_vfs_stat.permission++;
+-
+ 	if (coda_cache_check(inode, mask))
+ 		goto out; 
+ 
+@@ -206,7 +203,6 @@ static int coda_create(struct inode *dir, struct dentry *de, int mode, struct na
+ 	struct coda_vattr attrs;
+ 
+ 	lock_kernel();
+-	coda_vfs_stat.create++;
+ 
+ 	if (coda_isroot(dir) && coda_iscontrol(name, length)) {
+ 		unlock_kernel();
+@@ -246,7 +242,6 @@ static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
+ 	struct CodaFid newfid;
+ 
+ 	lock_kernel();
+-	coda_vfs_stat.mkdir++;
+ 
+ 	if (coda_isroot(dir) && coda_iscontrol(name, len)) {
+ 		unlock_kernel();
+@@ -288,7 +283,6 @@ static int coda_link(struct dentry *source_de, struct inode *dir_inode,
+ 	int error;
+ 
+ 	lock_kernel();
+-	coda_vfs_stat.link++;
+ 
+ 	if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) {
+ 		unlock_kernel();
+@@ -320,10 +314,9 @@ static int coda_symlink(struct inode *dir_inode, struct dentry *de,
+         const char *name = de->d_name.name;
+ 	int len = de->d_name.len;
+ 	int symlen;
+-        int error=0;
+-        
++	int error = 0;
++
+ 	lock_kernel();
+-	coda_vfs_stat.symlink++;
+ 
+ 	if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) {
+ 		unlock_kernel();
+@@ -360,7 +353,6 @@ int coda_unlink(struct inode *dir, struct dentry *de)
+ 	int len = de->d_name.len;
+ 
+ 	lock_kernel();
+-	coda_vfs_stat.unlink++;
+ 
+ 	error = venus_remove(dir->i_sb, coda_i2f(dir), name, len);
+ 	if ( error ) {
+@@ -381,7 +373,6 @@ int coda_rmdir(struct inode *dir, struct dentry *de)
+ 	int error;
+ 
+ 	lock_kernel();
+-	coda_vfs_stat.rmdir++;
+ 
+ 	error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len);
+ 	if (!error) {
+@@ -408,7 +399,6 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 	int error;
+ 
+ 	lock_kernel();
+-	coda_vfs_stat.rename++;
+ 
+ 	error = venus_rename(old_dir->i_sb, coda_i2f(old_dir),
+ 			     coda_i2f(new_dir), old_length, new_length,
+@@ -445,8 +435,6 @@ int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir)
+ 	BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
+ 	host_file = cfi->cfi_container;
+ 
+-	coda_vfs_stat.readdir++;
+-
+ 	if (!host_file->f_op)
+ 		return -ENOTDIR;
+ 
+diff --git a/fs/coda/file.c b/fs/coda/file.c
+index e7d622709c90..7594962604c2 100644
+--- a/fs/coda/file.c
++++ b/fs/coda/file.c
+@@ -22,7 +22,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ 
+ #include "coda_int.h"
+ 
+@@ -134,8 +133,6 @@ int coda_open(struct inode *coda_inode, struct file *coda_file)
+ 	unsigned short coda_flags = coda_flags_to_cflags(flags);
+ 	struct coda_file_info *cfi;
+ 
+-	coda_vfs_stat.open++;
+-
+ 	cfi = kmalloc(sizeof(struct coda_file_info), GFP_KERNEL);
+ 	if (!cfi)
+ 		return -ENOMEM;
+@@ -176,8 +173,6 @@ int coda_flush(struct file *coda_file, fl_owner_t id)
+ 
+ 	lock_kernel();
+ 
+-	coda_vfs_stat.flush++;
+-
+ 	/* last close semantics */
+ 	fcnt = file_count(coda_file);
+ 	if (fcnt > 1)
+@@ -219,8 +214,7 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
+ 	int err = 0;
+ 
+ 	lock_kernel();
+-	coda_vfs_stat.release++;
+- 
++
+ 	if (!use_coda_close) {
+ 		err = venus_release(coda_inode->i_sb, coda_i2f(coda_inode),
+ 				    coda_flags);
+@@ -271,8 +265,6 @@ int coda_fsync(struct file *coda_file, struct dentry *coda_dentry, int datasync)
+ 	BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
+ 	host_file = cfi->cfi_container;
+ 
+-	coda_vfs_stat.fsync++;
+-
+ 	if (host_file->f_op && host_file->f_op->fsync) {
+ 		host_dentry = host_file->f_path.dentry;
+ 		host_inode = host_dentry->d_inode;
+diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
+index 8a09f19596db..e3a0a4164d5d 100644
+--- a/fs/coda/psdev.c
++++ b/fs/coda/psdev.c
+@@ -45,7 +45,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ 
+ #include "coda_int.h"
+ 
+diff --git a/fs/coda/symlink.c b/fs/coda/symlink.c
+index 76e00a65a75b..4513b7258458 100644
+--- a/fs/coda/symlink.c
++++ b/fs/coda/symlink.c
+@@ -20,7 +20,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ 
+ static int coda_symlink_filler(struct file *file, struct page *page)
+ {
+@@ -32,7 +31,6 @@ static int coda_symlink_filler(struct file *file, struct page *page)
+ 
+ 	lock_kernel();
+ 	cii = ITOC(inode);
+-	coda_vfs_stat.follow_link++;
+ 
+ 	error = venus_readlink(inode->i_sb, &cii->c_fid, p, &len);
+ 	unlock_kernel();
+diff --git a/fs/coda/sysctl.c b/fs/coda/sysctl.c
+index c57a1fa7cf23..81b7771c6465 100644
+--- a/fs/coda/sysctl.c
++++ b/fs/coda/sysctl.c
+@@ -5,181 +5,14 @@
+  * 
+  * Carnegie Mellon encourages users to contribute improvements to
+  * the Coda project. Contact Peter Braam (coda@cs.cmu.edu).
+- * 
+- * CODA operation statistics
+- * (c) March, 1998 Zhanyong Wan 
+- *
+  */
+ 
+-#include 
+-#include 
+ #include 
+-#include 
+-#include 
+-#include 
+-#include 
+-#include 
+-#include 
+-#include 
+-#include 
+-#include 
+ 
+-#include 
+-#include 
+-#include 
+-#include 
+-#include 
+-#include 
++#include "coda_int.h"
+ 
+ static struct ctl_table_header *fs_table_header;
+ 
+-#define CODA_TIMEOUT    3       /* timeout on upcalls to become intrble */
+-#define CODA_HARD       5       /* mount type "hard" or "soft" */
+-#define CODA_VFS 	 6       /* vfs statistics */
+-#define CODA_CACHE_INV 	 9       /* cache invalidation statistics */
+-#define CODA_FAKE_STATFS 10	 /* don't query venus for actual cache usage */
+-
+-struct coda_vfs_stats		coda_vfs_stat;
+-static struct coda_cache_inv_stats	coda_cache_inv_stat;
+-
+-static void reset_coda_vfs_stats( void )
+-{
+-	memset( &coda_vfs_stat, 0, sizeof( coda_vfs_stat ) );
+-}
+-
+-static void reset_coda_cache_inv_stats( void )
+-{
+-	memset( &coda_cache_inv_stat, 0, sizeof( coda_cache_inv_stat ) );
+-}
+-
+-static int do_reset_coda_vfs_stats( ctl_table * table, int write,
+-				    struct file * filp, void __user * buffer,
+-				    size_t * lenp, loff_t * ppos )
+-{
+-	if ( write ) {
+-		reset_coda_vfs_stats();
+-
+-		*ppos += *lenp;
+-	} else {
+-		*lenp = 0;
+-	}
+-
+-	return 0;
+-}
+-
+-static int do_reset_coda_cache_inv_stats( ctl_table * table, int write,
+-					  struct file * filp,
+-					  void __user * buffer,
+-					  size_t * lenp, loff_t * ppos )
+-{
+-	if ( write ) {
+-		reset_coda_cache_inv_stats();
+-
+-		*ppos += *lenp;
+-	} else {
+-		*lenp = 0;
+-	}
+-  
+-	return 0;
+-}
+-
+-static int proc_vfs_stats_show(struct seq_file *m, void *v)
+-{
+-	struct coda_vfs_stats * ps = & coda_vfs_stat;
+-  
+-	seq_printf(m,
+-			"Coda VFS statistics\n"
+-			"===================\n\n"
+-			"File Operations:\n"
+-			"\topen\t\t%9d\n"
+-			"\tflush\t\t%9d\n"
+-			"\trelease\t\t%9d\n"
+-			"\tfsync\t\t%9d\n\n"
+-			"Dir Operations:\n"
+-			"\treaddir\t\t%9d\n\n"
+-			"Inode Operations\n"
+-			"\tcreate\t\t%9d\n"
+-			"\tlookup\t\t%9d\n"
+-			"\tlink\t\t%9d\n"
+-			"\tunlink\t\t%9d\n"
+-			"\tsymlink\t\t%9d\n"
+-			"\tmkdir\t\t%9d\n"
+-			"\trmdir\t\t%9d\n"
+-			"\trename\t\t%9d\n"
+-			"\tpermission\t%9d\n",
+-
+-			/* file operations */
+-			ps->open,
+-			ps->flush,
+-			ps->release,
+-			ps->fsync,
+-
+-			/* dir operations */
+-			ps->readdir,
+-		  
+-			/* inode operations */
+-			ps->create,
+-			ps->lookup,
+-			ps->link,
+-			ps->unlink,
+-			ps->symlink,
+-			ps->mkdir,
+-			ps->rmdir,
+-			ps->rename,
+-			ps->permission); 
+-	return 0;
+-}
+-
+-static int proc_cache_inv_stats_show(struct seq_file *m, void *v)
+-{
+-	struct coda_cache_inv_stats * ps = & coda_cache_inv_stat;
+-  
+-	seq_printf(m,
+-			"Coda cache invalidation statistics\n"
+-			"==================================\n\n"
+-			"flush\t\t%9d\n"
+-			"purge user\t%9d\n"
+-			"zap_dir\t\t%9d\n"
+-			"zap_file\t%9d\n"
+-			"zap_vnode\t%9d\n"
+-			"purge_fid\t%9d\n"
+-			"replace\t\t%9d\n",
+-			ps->flush,
+-			ps->purge_user,
+-			ps->zap_dir,
+-			ps->zap_file,
+-			ps->zap_vnode,
+-			ps->purge_fid,
+-			ps->replace );
+-	return 0;
+-}
+-
+-static int proc_vfs_stats_open(struct inode *inode, struct file *file)
+-{
+-	return single_open(file, proc_vfs_stats_show, NULL);
+-}
+-
+-static int proc_cache_inv_stats_open(struct inode *inode, struct file *file)
+-{
+-	return single_open(file, proc_cache_inv_stats_show, NULL);
+-}
+-
+-static const struct file_operations proc_vfs_stats_fops = {
+-	.owner		= THIS_MODULE,
+-	.open		= proc_vfs_stats_open,
+-	.read		= seq_read,
+-	.llseek		= seq_lseek,
+-	.release	= single_release,
+-};
+-
+-static const struct file_operations proc_cache_inv_stats_fops = {
+-	.owner		= THIS_MODULE,
+-	.open		= proc_cache_inv_stats_open,
+-	.read		= seq_read,
+-	.llseek		= seq_lseek,
+-	.release	= single_release,
+-};
+-
+ static ctl_table coda_table[] = {
+ 	{
+ 		.ctl_name	= CTL_UNNUMBERED,
+@@ -197,22 +30,6 @@ static ctl_table coda_table[] = {
+ 		.mode		= 0644,
+ 		.proc_handler	= &proc_dointvec
+ 	},
+-	{
+-		.ctl_name	= CTL_UNNUMBERED,
+-		.procname	= "vfs_stats",
+-		.data		= NULL,
+-		.maxlen		= 0,
+-		.mode		= 0644,
+-		.proc_handler	= &do_reset_coda_vfs_stats
+-	},
+-	{
+-		.ctl_name	= CTL_UNNUMBERED,
+-		.procname	= "cache_inv_stats",
+-		.data		= NULL,
+-		.maxlen		= 0,
+-		.mode		= 0644,
+-		.proc_handler	= &do_reset_coda_cache_inv_stats
+-	},
+ 	{
+ 		.ctl_name	= CTL_UNNUMBERED,
+ 		.procname	= "fake_statfs",
+@@ -235,59 +52,20 @@ static ctl_table fs_table[] = {
+ };
+ 
+ 
+-#ifdef CONFIG_PROC_FS
+-
+-/*
+- target directory structure:
+-   /proc/fs  (see linux/fs/proc/root.c)
+-   /proc/fs/coda
+-   /proc/fs/coda/{vfs_stats,
+-
+-*/
+-
+-static struct proc_dir_entry* proc_fs_coda;
+-
+-#endif
+-
+ void coda_sysctl_init(void)
+ {
+-	reset_coda_vfs_stats();
+-	reset_coda_cache_inv_stats();
+-
+-#ifdef CONFIG_PROC_FS
+-	proc_fs_coda = proc_mkdir("coda", proc_root_fs);
+-	if (proc_fs_coda) {
+-		struct proc_dir_entry *pde;
+-
+-		proc_fs_coda->owner = THIS_MODULE;
+-		pde = create_proc_entry("vfs_stats", 0, proc_fs_coda);
+-		if (pde)
+-			pde->proc_fops = &proc_vfs_stats_fops;
+-		pde = create_proc_entry("cache_inv_stats", 0, proc_fs_coda);
+-		if (pde)
+-			pde->proc_fops = &proc_cache_inv_stats_fops;
+-	}
+-#endif
+-
+ #ifdef CONFIG_SYSCTL
+ 	if ( !fs_table_header )
+ 		fs_table_header = register_sysctl_table(fs_table);
+-#endif 
++#endif
+ }
+ 
+-void coda_sysctl_clean(void) 
++void coda_sysctl_clean(void)
+ {
+-
+ #ifdef CONFIG_SYSCTL
+ 	if ( fs_table_header ) {
+ 		unregister_sysctl_table(fs_table_header);
+ 		fs_table_header = NULL;
+ 	}
+ #endif
+-
+-#ifdef CONFIG_PROC_FS
+-        remove_proc_entry("cache_inv_stats", proc_fs_coda);
+-        remove_proc_entry("vfs_stats", proc_fs_coda);
+-	remove_proc_entry("coda", proc_root_fs);
+-#endif 
+ }
+diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
+index 9a20a3b1998e..e4e766e5557c 100644
+--- a/fs/coda/upcall.c
++++ b/fs/coda/upcall.c
+@@ -35,7 +35,8 @@
+ #include 
+ #include 
+ #include 
+-#include  
++
++#include "coda_int.h"
+ 
+ static int coda_upcall(struct venus_comm *vc, int inSize, int *outSize,
+ 		       union inputArgs *buffer);
+diff --git a/include/linux/coda_linux.h b/include/linux/coda_linux.h
+index e4ac016ad272..c4079b403e9e 100644
+--- a/include/linux/coda_linux.h
++++ b/include/linux/coda_linux.h
+@@ -43,9 +43,6 @@ int coda_revalidate_inode(struct dentry *);
+ int coda_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+ int coda_setattr(struct dentry *, struct iattr *);
+ 
+-/* global variables */
+-extern int coda_fake_statfs;
+-
+ /* this file:  heloers */
+ static __inline__ struct CodaFid *coda_i2f(struct inode *);
+ static __inline__ char *coda_i2s(struct inode *);
+diff --git a/include/linux/coda_proc.h b/include/linux/coda_proc.h
+deleted file mode 100644
+index 0dc1b0458e75..000000000000
+--- a/include/linux/coda_proc.h
++++ /dev/null
+@@ -1,76 +0,0 @@
+-/*
+- * coda_statis.h
+- * 
+- * CODA operation statistics
+- *
+- * (c) March, 1998
+- * by Michihiro Kuramochi, Zhenyu Xia and Zhanyong Wan
+- * zhanyong.wan@yale.edu
+- *
+- */
+-
+-#ifndef _CODA_PROC_H
+-#define _CODA_PROC_H
+-
+-void coda_sysctl_init(void);
+-void coda_sysctl_clean(void);
+-
+-#include 
+-#include 
+-#include 
+-
+-/* these four files are presented to show the result of the statistics:
+- *
+- *	/proc/fs/coda/vfs_stats
+- *		      cache_inv_stats
+- *
+- * these four files are presented to reset the statistics to 0:
+- *
+- *	/proc/sys/coda/vfs_stats
+- *		       cache_inv_stats
+- */
+-
+-/* VFS operation statistics */
+-struct coda_vfs_stats 
+-{
+-	/* file operations */
+-	int open;
+-	int flush;
+-	int release;
+-	int fsync;
+-
+-	/* dir operations */
+-	int readdir;
+-  
+-	/* inode operations */
+-	int create;
+-	int lookup;
+-	int link;
+-	int unlink;
+-	int symlink;
+-	int mkdir;
+-	int rmdir;
+-	int rename;
+-	int permission;
+-
+-	/* symlink operatoins*/
+-	int follow_link;
+-	int readlink;
+-};
+-
+-/* cache invalidation statistics */
+-struct coda_cache_inv_stats
+-{
+-	int flush;
+-	int purge_user;
+-	int zap_dir;
+-	int zap_file;
+-	int zap_vnode;
+-	int purge_fid;
+-	int replace;
+-};
+-
+-/* these global variables hold the actual statistics data */
+-extern struct coda_vfs_stats		coda_vfs_stat;
+-
+-#endif /* _CODA_PROC_H */
+diff --git a/include/linux/coda_psdev.h b/include/linux/coda_psdev.h
+index 81b2e4c7d7ce..aa8f454b3b77 100644
+--- a/include/linux/coda_psdev.h
++++ b/include/linux/coda_psdev.h
+@@ -69,8 +69,6 @@ int venus_statfs(struct dentry *dentry, struct kstatfs *sfs);
+ 
+ 
+ /* messages between coda filesystem in kernel and Venus */
+-extern int coda_hard;
+-extern unsigned long coda_timeout;
+ struct upc_req {
+ 	struct list_head    uc_chain;
+ 	caddr_t	            uc_data;

commit a1b0aa87647493c0201821ab884e86298d5da7d6
+Author: Jan Harkes 
+Date:   Thu Jul 19 01:48:50 2007 -0700
+
+    coda: remove struct coda_sb_info
+    
+    The sb_info structure only contains a single pointer to the character device,
+    there is no need for the added indirection.
+    
+    Signed-off-by: Jan Harkes 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/cache.c b/fs/coda/cache.c
+index 11538a2b5423..8a2370341c7a 100644
+--- a/fs/coda/cache.c
++++ b/fs/coda/cache.c
+@@ -49,11 +49,6 @@ void coda_cache_clear_inode(struct inode *inode)
+ /* remove all acl caches */
+ void coda_cache_clear_all(struct super_block *sb)
+ {
+-        struct coda_sb_info *sbi;
+-
+-        sbi = coda_sbp(sb);
+-	BUG_ON(!sbi);
+-
+ 	atomic_inc(&permission_epoch);
+ }
+ 
+diff --git a/fs/coda/inode.c b/fs/coda/inode.c
+index 29e441765600..6771a4271e33 100644
+--- a/fs/coda/inode.c
++++ b/fs/coda/inode.c
+@@ -141,11 +141,10 @@ static int get_device_index(struct coda_mount_data *data)
+ 
+ static int coda_fill_super(struct super_block *sb, void *data, int silent)
+ {
+-        struct inode *root = NULL; 
+-	struct coda_sb_info *sbi = NULL;
++	struct inode *root = NULL;
+ 	struct venus_comm *vc = NULL;
+ 	struct CodaFid fid;
+-        int error;
++	int error;
+ 	int idx;
+ 
+ 	idx = get_device_index((struct coda_mount_data *) data);
+@@ -167,16 +166,9 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
+ 		return -EBUSY;
+ 	}
+ 
+-	sbi = kmalloc(sizeof(struct coda_sb_info), GFP_KERNEL);
+-	if(!sbi) {
+-		return -ENOMEM;
+-	}
+-
+ 	vc->vc_sb = sb;
+ 
+-	sbi->sbi_vcomm = vc;
+-
+-	sb->s_fs_info = sbi;
++	sb->s_fs_info = vc;
+ 	sb->s_flags |= MS_NOATIME;
+ 	sb->s_blocksize = 4096;	/* XXXXX  what do we put here?? */
+ 	sb->s_blocksize_bits = 12;
+@@ -207,26 +199,20 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
+         return 0;
+ 
+  error:
+-	if (sbi) {
+-		kfree(sbi);
+-		if(vc)
+-			vc->vc_sb = NULL;		
+-	}
+ 	if (root)
+-                iput(root);
++		iput(root);
++	if (vc)
++		vc->vc_sb = NULL;
+ 
+-        return -EINVAL;
++	return -EINVAL;
+ }
+ 
+ static void coda_put_super(struct super_block *sb)
+ {
+-        struct coda_sb_info *sbi;
+-
+-	sbi = coda_sbp(sb);
+-	sbi->sbi_vcomm->vc_sb = NULL;
++	coda_vcp(sb)->vc_sb = NULL;
++	sb->s_fs_info = NULL;
+ 
+ 	printk("Coda: Bye bye.\n");
+-	kfree(sbi);
+ }
+ 
+ static void coda_clear_inode(struct inode *inode)
+diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
+index 87601e147644..9a20a3b1998e 100644
+--- a/fs/coda/upcall.c
++++ b/fs/coda/upcall.c
+@@ -37,7 +37,7 @@
+ #include 
+ #include  
+ 
+-static int coda_upcall(struct coda_sb_info *mntinfo, int inSize, int *outSize, 
++static int coda_upcall(struct venus_comm *vc, int inSize, int *outSize,
+ 		       union inputArgs *buffer);
+ 
+ static void *alloc_upcall(int opcode, int size)
+@@ -83,7 +83,7 @@ int venus_rootfid(struct super_block *sb, struct CodaFid *fidp)
+         insize = SIZE(root);
+         UPARG(CODA_ROOT);
+ 
+-	error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
++	error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
+ 	if (!error)
+ 		*fidp = outp->coda_root.VFid;
+ 
+@@ -102,7 +102,7 @@ int venus_getattr(struct super_block *sb, struct CodaFid *fid,
+ 	UPARG(CODA_GETATTR);
+         inp->coda_getattr.VFid = *fid;
+ 
+-	error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
++	error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
+ 	if (!error)
+ 		*attr = outp->coda_getattr.attr;
+ 
+@@ -123,7 +123,7 @@ int venus_setattr(struct super_block *sb, struct CodaFid *fid,
+         inp->coda_setattr.VFid = *fid;
+ 	inp->coda_setattr.attr = *vattr;
+ 
+-        error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
++	error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
+ 
+         CODA_FREE(inp, insize);
+         return error;
+@@ -149,7 +149,7 @@ int venus_lookup(struct super_block *sb, struct CodaFid *fid,
+         memcpy((char *)(inp) + offset, name, length);
+         *((char *)inp + offset + length) = '\0';
+ 
+-	error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
++	error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
+ 	if (!error) {
+ 		*resfid = outp->coda_lookup.VFid;
+ 		*type = outp->coda_lookup.vtype;
+@@ -182,7 +182,7 @@ int venus_store(struct super_block *sb, struct CodaFid *fid, int flags,
+         inp->coda_store.VFid = *fid;
+         inp->coda_store.flags = flags;
+ 
+-        error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
++	error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
+ 
+ 	CODA_FREE(inp, insize);
+         return error;
+@@ -200,7 +200,7 @@ int venus_release(struct super_block *sb, struct CodaFid *fid, int flags)
+ 	inp->coda_release.VFid = *fid;
+ 	inp->coda_release.flags = flags;
+ 
+-	error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
++	error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
+ 
+ 	CODA_FREE(inp, insize);
+ 	return error;
+@@ -229,7 +229,7 @@ int venus_close(struct super_block *sb, struct CodaFid *fid, int flags,
+         inp->coda_close.VFid = *fid;
+         inp->coda_close.flags = flags;
+ 
+-        error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
++	error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
+ 
+ 	CODA_FREE(inp, insize);
+         return error;
+@@ -248,7 +248,7 @@ int venus_open(struct super_block *sb, struct CodaFid *fid,
+ 	inp->coda_open_by_fd.VFid = *fid;
+ 	inp->coda_open_by_fd.flags = flags;
+ 
+-	error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
++	error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
+ 	if (!error)
+ 		*fh = outp->coda_open_by_fd.fh;
+ 
+@@ -276,7 +276,7 @@ int venus_mkdir(struct super_block *sb, struct CodaFid *dirfid,
+         memcpy((char *)(inp) + offset, name, length);
+         *((char *)inp + offset + length) = '\0';
+ 
+-	error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
++	error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
+ 	if (!error) {
+ 		*attrs = outp->coda_mkdir.attr;
+ 		*newfid = outp->coda_mkdir.VFid;
+@@ -318,7 +318,7 @@ int venus_rename(struct super_block *sb, struct CodaFid *old_fid,
+         memcpy((char *)(inp) + offset, new_name, new_length);
+         *((char *)inp + offset + new_length) = '\0';
+ 
+-        error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
++	error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
+ 
+ 	CODA_FREE(inp, insize);
+ 	return error;
+@@ -347,7 +347,7 @@ int venus_create(struct super_block *sb, struct CodaFid *dirfid,
+         memcpy((char *)(inp) + offset, name, length);
+         *((char *)inp + offset + length) = '\0';
+ 
+-	error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
++	error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
+ 	if (!error) {
+ 		*attrs = outp->coda_create.attr;
+ 		*newfid = outp->coda_create.VFid;
+@@ -373,8 +373,8 @@ int venus_rmdir(struct super_block *sb, struct CodaFid *dirfid,
+         inp->coda_rmdir.name = offset;
+         memcpy((char *)(inp) + offset, name, length);
+ 	*((char *)inp + offset + length) = '\0';
+-        
+-        error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
++
++	error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
+ 
+ 	CODA_FREE(inp, insize);
+ 	return error;
+@@ -395,8 +395,8 @@ int venus_remove(struct super_block *sb, struct CodaFid *dirfid,
+         inp->coda_remove.name = offset;
+         memcpy((char *)(inp) + offset, name, length);
+ 	*((char *)inp + offset + length) = '\0';
+-        
+-        error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
++
++	error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
+ 
+ 	CODA_FREE(inp, insize);
+ 	return error;
+@@ -417,7 +417,7 @@ int venus_readlink(struct super_block *sb, struct CodaFid *fid,
+ 
+         inp->coda_readlink.VFid = *fid;
+ 
+-	error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
++	error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
+ 	if (!error) {
+ 		retlen = outp->coda_readlink.count;
+ 		if ( retlen > *length )
+@@ -453,8 +453,8 @@ int venus_link(struct super_block *sb, struct CodaFid *fid,
+         /* make sure strings are null terminated */
+         memcpy((char *)(inp) + offset, name, len);
+         *((char *)inp + offset + len) = '\0';
+-        
+-        error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
++
++	error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
+ 
+ 	CODA_FREE(inp, insize);
+         return error;
+@@ -489,7 +489,7 @@ int venus_symlink(struct super_block *sb, struct CodaFid *fid,
+         memcpy((char *)(inp) + offset, name, len);
+         *((char *)inp + offset + len) = '\0';
+ 
+-	error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
++	error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
+ 
+ 	CODA_FREE(inp, insize);
+         return error;
+@@ -504,9 +504,9 @@ int venus_fsync(struct super_block *sb, struct CodaFid *fid)
+ 	insize=SIZE(fsync);
+ 	UPARG(CODA_FSYNC);
+ 
+-        inp->coda_fsync.VFid = *fid;
+-        error = coda_upcall(coda_sbp(sb), sizeof(union inputArgs), 
+-                            &outsize, inp);
++	inp->coda_fsync.VFid = *fid;
++	error = coda_upcall(coda_vcp(sb), sizeof(union inputArgs),
++			    &outsize, inp);
+ 
+ 	CODA_FREE(inp, insize);
+ 	return error;
+@@ -524,7 +524,7 @@ int venus_access(struct super_block *sb, struct CodaFid *fid, int mask)
+         inp->coda_access.VFid = *fid;
+         inp->coda_access.flags = mask;
+ 
+-	error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
++	error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
+ 
+ 	CODA_FREE(inp, insize);
+ 	return error;
+@@ -573,9 +573,9 @@ int venus_pioctl(struct super_block *sb, struct CodaFid *fid,
+ 	        goto exit;
+ 	}
+ 
+-        error = coda_upcall(coda_sbp(sb), SIZE(ioctl) + data->vi.in_size,
+-                            &outsize, inp);
+-        
++	error = coda_upcall(coda_vcp(sb), SIZE(ioctl) + data->vi.in_size,
++			    &outsize, inp);
++
+         if (error) {
+ 	        printk("coda_pioctl: Venus returns: %d for %s\n", 
+ 		       error, coda_f2s(fid));
+@@ -615,7 +615,7 @@ int venus_statfs(struct dentry *dentry, struct kstatfs *sfs)
+ 	insize = max_t(unsigned int, INSIZE(statfs), OUTSIZE(statfs));
+ 	UPARG(CODA_STATFS);
+ 
+-	error = coda_upcall(coda_sbp(dentry->d_sb), insize, &outsize, inp);
++	error = coda_upcall(coda_vcp(dentry->d_sb), insize, &outsize, inp);
+ 	if (!error) {
+ 		sfs->f_blocks = outp->coda_statfs.stat.f_blocks;
+ 		sfs->f_bfree  = outp->coda_statfs.stat.f_bfree;
+@@ -710,28 +710,25 @@ static inline void coda_waitfor_upcall(struct upc_req *req)
+ }
+ 
+ 
+-/* 
+- * coda_upcall will return an error in the case of 
++/*
++ * coda_upcall will return an error in the case of
+  * failed communication with Venus _or_ will peek at Venus
+  * reply and return Venus' error.
+  *
+  * As venus has 2 types of errors, normal errors (positive) and internal
+  * errors (negative), normal errors are negated, while internal errors
+  * are all mapped to -EINTR, while showing a nice warning message. (jh)
+- * 
+  */
+-static int coda_upcall(struct coda_sb_info *sbi,
++static int coda_upcall(struct venus_comm *vcp,
+ 		       int inSize, int *outSize,
+ 		       union inputArgs *buffer)
+ {
+-	struct venus_comm *vcommp;
+ 	union outputArgs *out;
+ 	union inputArgs *sig_inputArgs;
+ 	struct upc_req *req, *sig_req;
+ 	int error = 0;
+ 
+-	vcommp = sbi->sbi_vcomm;
+-	if (!vcommp->vc_inuse) {
++	if (!vcp->vc_inuse) {
+ 		printk(KERN_NOTICE "coda: Venus dead, not sending upcall\n");
+ 		return -ENXIO;
+ 	}
+@@ -746,16 +743,16 @@ static int coda_upcall(struct coda_sb_info *sbi,
+ 	req->uc_inSize = inSize;
+ 	req->uc_outSize = *outSize ? *outSize : inSize;
+ 	req->uc_opcode = ((union inputArgs *)buffer)->ih.opcode;
+-	req->uc_unique = ++vcommp->vc_seq;
++	req->uc_unique = ++vcp->vc_seq;
+ 	init_waitqueue_head(&req->uc_sleep);
+ 
+ 	/* Fill in the common input args. */
+ 	((union inputArgs *)buffer)->ih.unique = req->uc_unique;
+ 
+ 	/* Append msg to pending queue and poke Venus. */
+-	list_add_tail(&req->uc_chain, &vcommp->vc_pending);
++	list_add_tail(&req->uc_chain, &vcp->vc_pending);
+ 
+-	wake_up_interruptible(&vcommp->vc_waitq);
++	wake_up_interruptible(&vcp->vc_waitq);
+ 	/* We can be interrupted while we wait for Venus to process
+ 	 * our request.  If the interrupt occurs before Venus has read
+ 	 * the request, we dequeue and return. If it occurs after the
+@@ -788,7 +785,7 @@ static int coda_upcall(struct coda_sb_info *sbi,
+ 		goto exit;
+ 
+ 	/* Venus saw the upcall, make sure we can send interrupt signal */
+-	if (!vcommp->vc_inuse) {
++	if (!vcp->vc_inuse) {
+ 		printk(KERN_INFO "coda: Venus dead, not sending signal.\n");
+ 		goto exit;
+ 	}
+@@ -815,8 +812,8 @@ static int coda_upcall(struct coda_sb_info *sbi,
+ 	sig_req->uc_outSize = sizeof(struct coda_in_hdr);
+ 
+ 	/* insert at head of queue! */
+-	list_add(&(sig_req->uc_chain), &vcommp->vc_pending);
+-	wake_up_interruptible(&vcommp->vc_waitq);
++	list_add(&(sig_req->uc_chain), &vcp->vc_pending);
++	wake_up_interruptible(&vcp->vc_waitq);
+ 
+ exit:
+ 	kfree(req);
+diff --git a/include/linux/coda_psdev.h b/include/linux/coda_psdev.h
+index f28c2f7fd454..81b2e4c7d7ce 100644
+--- a/include/linux/coda_psdev.h
++++ b/include/linux/coda_psdev.h
+@@ -8,11 +8,6 @@
+ 
+ struct kstatfs;
+ 
+-struct coda_sb_info
+-{
+-	struct venus_comm *sbi_vcomm;
+-};
+-
+ /* communication pending/processing queues */
+ struct venus_comm {
+ 	u_long		    vc_seq;
+@@ -24,9 +19,9 @@ struct venus_comm {
+ };
+ 
+ 
+-static inline struct coda_sb_info *coda_sbp(struct super_block *sb)
++static inline struct venus_comm *coda_vcp(struct super_block *sb)
+ {
+-    return ((struct coda_sb_info *)((sb)->s_fs_info));
++	return (struct venus_comm *)((sb)->s_fs_info);
+ }
+ 
+ 

commit 5fd31e9a67dd6c80e49240514cf854c1f054aca2
+Author: Jan Harkes 
+Date:   Thu Jul 19 01:48:49 2007 -0700
+
+    coda: cleanup downcall handler
+    
+    Signed-off-by: Jan Harkes 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
+index 097dbb2fd6f5..87601e147644 100644
+--- a/fs/coda/upcall.c
++++ b/fs/coda/upcall.c
+@@ -859,77 +859,66 @@ static int coda_upcall(struct coda_sb_info *sbi,
+ 
+ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
+ {
++	struct inode *inode = NULL;
++	struct CodaFid *fid, *newfid;
++
+ 	/* Handle invalidation requests. */
+-          if ( !sb || !sb->s_root || !sb->s_root->d_inode)
+-		  return 0; 
+-
+-	  switch (opcode) {
+-
+-	  case CODA_FLUSH : {
+-		   coda_cache_clear_all(sb);
+-		   shrink_dcache_sb(sb);
+-		   coda_flag_inode(sb->s_root->d_inode, C_FLUSH);
+-		   return(0);
+-	  }
+-
+-	  case CODA_PURGEUSER : {
+-		   coda_cache_clear_all(sb);
+-		   return(0);
+-	  }
+-
+-	  case CODA_ZAPDIR : {
+-	          struct inode *inode;
+-		  struct CodaFid *fid = &out->coda_zapdir.CodaFid;
+-
+-		  inode = coda_fid_to_inode(fid, sb);
+-		  if (inode) {
+-			  coda_flag_inode_children(inode, C_PURGE);
+-	                  coda_flag_inode(inode, C_VATTR);
+-			  iput(inode);
+-		  }
+-		  
+-		  return(0);
+-	  }
+-
+-	  case CODA_ZAPFILE : {
+-	          struct inode *inode;
+-		  struct CodaFid *fid = &out->coda_zapfile.CodaFid;
+-		  inode = coda_fid_to_inode(fid, sb);
+-		  if ( inode ) {
+-	                  coda_flag_inode(inode, C_VATTR);
+-			  iput(inode);
+-		  }
+-		  return 0;
+-	  }
+-
+-	  case CODA_PURGEFID : {
+-	          struct inode *inode;
+-		  struct CodaFid *fid = &out->coda_purgefid.CodaFid;
+-		  inode = coda_fid_to_inode(fid, sb);
+-		  if ( inode ) { 
++	if ( !sb || !sb->s_root)
++		return 0;
++
++	switch (opcode) {
++	case CODA_FLUSH:
++		coda_cache_clear_all(sb);
++		shrink_dcache_sb(sb);
++		if (sb->s_root->d_inode)
++		    coda_flag_inode(sb->s_root->d_inode, C_FLUSH);
++		break;
++
++	case CODA_PURGEUSER:
++		coda_cache_clear_all(sb);
++		break;
++
++	case CODA_ZAPDIR:
++		fid = &out->coda_zapdir.CodaFid;
++		inode = coda_fid_to_inode(fid, sb);
++		if (inode) {
++			coda_flag_inode_children(inode, C_PURGE);
++			coda_flag_inode(inode, C_VATTR);
++		}
++		break;
++
++	case CODA_ZAPFILE:
++		fid = &out->coda_zapfile.CodaFid;
++		inode = coda_fid_to_inode(fid, sb);
++		if (inode)
++			coda_flag_inode(inode, C_VATTR);
++		break;
++
++	case CODA_PURGEFID:
++		fid = &out->coda_purgefid.CodaFid;
++		inode = coda_fid_to_inode(fid, sb);
++		if (inode) {
+ 			coda_flag_inode_children(inode, C_PURGE);
+ 
+ 			/* catch the dentries later if some are still busy */
+ 			coda_flag_inode(inode, C_PURGE);
+ 			d_prune_aliases(inode);
+ 
+-			iput(inode);
+-		  }
+-		  return 0;
+-	  }
+-
+-	  case CODA_REPLACE : {
+-	          struct inode *inode;
+-		  struct CodaFid *oldfid = &out->coda_replace.OldFid;
+-		  struct CodaFid *newfid = &out->coda_replace.NewFid;
+-		  inode = coda_fid_to_inode(oldfid, sb);
+-		  if ( inode ) { 
+-			  coda_replace_fid(inode, oldfid, newfid);
+-			  iput(inode);
+-		  }
+-		  return 0;
+-	  }
+-	  }
+-	  return 0;
++		}
++		break;
++
++	case CODA_REPLACE:
++		fid = &out->coda_replace.OldFid;
++		newfid = &out->coda_replace.NewFid;
++		inode = coda_fid_to_inode(fid, sb);
++		if (inode)
++			coda_replace_fid(inode, fid, newfid);
++		break;
++	}
++
++	if (inode)
++		iput(inode);
++
++	return 0;
+ }
+ 

commit ed36f723676b208053d0655cee7e7f1601a2d356
+Author: Jan Harkes 
+Date:   Thu Jul 19 01:48:49 2007 -0700
+
+    coda: cleanup coda_lookup, use dsplice_alias
+    
+    Signed-off-by: Jan Harkes 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/dir.c b/fs/coda/dir.c
+index 47ac9e21a590..0c6c48ca7496 100644
+--- a/fs/coda/dir.c
++++ b/fs/coda/dir.c
+@@ -97,58 +97,45 @@ const struct file_operations coda_dir_operations = {
+ /* access routines: lookup, readlink, permission */
+ static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struct nameidata *nd)
+ {
+-	struct inode *res_inode = NULL;
++	struct inode *inode = NULL;
+ 	struct CodaFid resfid = { { 0, } };
+-	int dropme = 0; /* to indicate entry should not be cached */
+ 	int type = 0;
+ 	int error = 0;
+ 	const char *name = entry->d_name.name;
+ 	size_t length = entry->d_name.len;
+-	
+-	if ( length > CODA_MAXNAMLEN ) {
+-	        printk("name too long: lookup, %s (%*s)\n", 
++
++	if (length > CODA_MAXNAMLEN) {
++		printk(KERN_ERR "name too long: lookup, %s (%*s)\n",
+ 		       coda_i2s(dir), (int)length, name);
+ 		return ERR_PTR(-ENAMETOOLONG);
+ 	}
+ 
++	/* control object, create inode on the fly */
++	if (coda_isroot(dir) && coda_iscontrol(name, length)) {
++		error = coda_cnode_makectl(&inode, dir->i_sb);
++		type = CODA_NOCACHE;
++		goto exit;
++	}
++
+ 	lock_kernel();
+-        /* control object, create inode on the fly */
+-        if (coda_isroot(dir) && coda_iscontrol(name, length)) {
+-	        error = coda_cnode_makectl(&res_inode, dir->i_sb);
+-		dropme = 1;
+-                goto exit;
+-        }
+ 
+-	error = venus_lookup(dir->i_sb, coda_i2f(dir), 
+-			     (const char *)name, length, &type, &resfid);
++	error = venus_lookup(dir->i_sb, coda_i2f(dir), name, length,
++			     &type, &resfid);
++	if (!error)
++		error = coda_cnode_make(&inode, &resfid, dir->i_sb);
+ 
+-	res_inode = NULL;
+-	if (!error) {
+-		if (type & CODA_NOCACHE) {
+-			type &= (~CODA_NOCACHE);
+-			dropme = 1;
+-		}
++	unlock_kernel();
+ 
+-	    	error = coda_cnode_make(&res_inode, &resfid, dir->i_sb);
+-		if (error) {
+-			unlock_kernel();
+-			return ERR_PTR(error);
+-		}
+-	} else if (error != -ENOENT) {
+-		unlock_kernel();
++	if (error && error != -ENOENT)
+ 		return ERR_PTR(error);
+-	}
+ 
+ exit:
+-	entry->d_time = 0;
+ 	entry->d_op = &coda_dentry_operations;
+-	d_add(entry, res_inode);
+-	if ( dropme ) {
+-		d_drop(entry);
+-		coda_flag_inode(res_inode, C_VATTR);
+-	}
+-	unlock_kernel();
+-        return NULL;
++
++	if (inode && (type & CODA_NOCACHE))
++		coda_flag_inode(inode, C_VATTR | C_PURGE);
++
++	return d_splice_alias(inode, entry);
+ }
+ 
+ 

commit 970648eb03cca7d7405f9a3a5d3fe29929e48aa6
+Author: Jan Harkes 
+Date:   Thu Jul 19 01:48:48 2007 -0700
+
+    coda: ignore returned values when upcalls return errors
+    
+    Venus returns an ENOENT error on open, so we shouldn't try to grab the
+    filehandle for the returned fd.
+    
+    Signed-off-by: Jan Harkes 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
+index 330de7dbdcf8..097dbb2fd6f5 100644
+--- a/fs/coda/upcall.c
++++ b/fs/coda/upcall.c
+@@ -84,12 +84,8 @@ int venus_rootfid(struct super_block *sb, struct CodaFid *fidp)
+         UPARG(CODA_ROOT);
+ 
+ 	error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
+-	
+-	if (error) {
+-	        printk("coda_get_rootfid: error %d\n", error);
+-	} else {
++	if (!error)
+ 		*fidp = outp->coda_root.VFid;
+-	}
+ 
+ 	CODA_FREE(inp, insize);
+ 	return error;
+@@ -106,9 +102,9 @@ int venus_getattr(struct super_block *sb, struct CodaFid *fid,
+ 	UPARG(CODA_GETATTR);
+         inp->coda_getattr.VFid = *fid;
+ 
+-        error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
+-	
+-	*attr = outp->coda_getattr.attr;
++	error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
++	if (!error)
++		*attr = outp->coda_getattr.attr;
+ 
+ 	CODA_FREE(inp, insize);
+         return error;
+@@ -153,10 +149,11 @@ int venus_lookup(struct super_block *sb, struct CodaFid *fid,
+         memcpy((char *)(inp) + offset, name, length);
+         *((char *)inp + offset + length) = '\0';
+ 
+-        error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
+-
+-	*resfid = outp->coda_lookup.VFid;
+-	*type = outp->coda_lookup.vtype;
++	error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
++	if (!error) {
++		*resfid = outp->coda_lookup.VFid;
++		*type = outp->coda_lookup.vtype;
++	}
+ 
+ 	CODA_FREE(inp, insize);
+ 	return error;
+@@ -278,11 +275,12 @@ int venus_mkdir(struct super_block *sb, struct CodaFid *dirfid,
+         /* Venus must get null terminated string */
+         memcpy((char *)(inp) + offset, name, length);
+         *((char *)inp + offset + length) = '\0';
+-        
+-        error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
+ 
+-	*attrs = outp->coda_mkdir.attr;
+-	*newfid = outp->coda_mkdir.VFid;
++	error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
++	if (!error) {
++		*attrs = outp->coda_mkdir.attr;
++		*newfid = outp->coda_mkdir.VFid;
++	}
+ 
+ 	CODA_FREE(inp, insize);
+ 	return error;        
+@@ -348,11 +346,12 @@ int venus_create(struct super_block *sb, struct CodaFid *dirfid,
+         /* Venus must get null terminated string */
+         memcpy((char *)(inp) + offset, name, length);
+         *((char *)inp + offset + length) = '\0';
+-                
+-        error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
+ 
+-	*attrs = outp->coda_create.attr;
+-	*newfid = outp->coda_create.VFid;
++	error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
++	if (!error) {
++		*attrs = outp->coda_create.attr;
++		*newfid = outp->coda_create.VFid;
++	}
+ 
+ 	CODA_FREE(inp, insize);
+ 	return error;        
+@@ -417,19 +416,18 @@ int venus_readlink(struct super_block *sb, struct CodaFid *fid,
+ 	UPARG(CODA_READLINK);
+ 
+         inp->coda_readlink.VFid = *fid;
+-    
+-        error =  coda_upcall(coda_sbp(sb), insize, &outsize, inp);
+-	
+-	if (! error) {
+-                retlen = outp->coda_readlink.count;
++
++	error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
++	if (!error) {
++		retlen = outp->coda_readlink.count;
+ 		if ( retlen > *length )
+-		        retlen = *length;
++			retlen = *length;
+ 		*length = retlen;
+ 		result =  (char *)outp + (long)outp->coda_readlink.data;
+ 		memcpy(buffer, result, retlen);
+ 		*(buffer + retlen) = '\0';
+ 	}
+-        
++
+         CODA_FREE(inp, insize);
+         return error;
+ }
+@@ -617,16 +615,13 @@ int venus_statfs(struct dentry *dentry, struct kstatfs *sfs)
+ 	insize = max_t(unsigned int, INSIZE(statfs), OUTSIZE(statfs));
+ 	UPARG(CODA_STATFS);
+ 
+-        error = coda_upcall(coda_sbp(dentry->d_sb), insize, &outsize, inp);
+-	
+-        if (!error) {
++	error = coda_upcall(coda_sbp(dentry->d_sb), insize, &outsize, inp);
++	if (!error) {
+ 		sfs->f_blocks = outp->coda_statfs.stat.f_blocks;
+ 		sfs->f_bfree  = outp->coda_statfs.stat.f_bfree;
+ 		sfs->f_bavail = outp->coda_statfs.stat.f_bavail;
+ 		sfs->f_files  = outp->coda_statfs.stat.f_files;
+ 		sfs->f_ffree  = outp->coda_statfs.stat.f_ffree;
+-	} else {
+-		printk("coda_statfs: Venus returns: %d\n", error);
+ 	}
+ 
+         CODA_FREE(inp, insize);

commit 37461e1957e6262278342a0c1a78e46996b7ff88
+Author: Jan Harkes 
+Date:   Thu Jul 19 01:48:48 2007 -0700
+
+    coda: replace upc_alloc/upc_free with kmalloc/kfree
+    
+    Signed-off-by: Jan Harkes 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
+index 6818c20372ca..8a09f19596db 100644
+--- a/fs/coda/psdev.c
++++ b/fs/coda/psdev.c
+@@ -49,8 +49,6 @@
+ 
+ #include "coda_int.h"
+ 
+-#define upc_free(r) kfree(r)
+-
+ /* statistics */
+ int           coda_hard;         /* allows signals during upcalls */
+ unsigned long coda_timeout = 30; /* .. secs, then signals will dequeue */
+@@ -264,7 +262,7 @@ static ssize_t coda_psdev_read(struct file * file, char __user * buf,
+ 	}
+ 
+ 	CODA_FREE(req->uc_data, sizeof(struct coda_in_hdr));
+-	upc_free(req);
++	kfree(req);
+ out:
+ 	unlock_kernel();
+ 	return (count ? count : retval);
+@@ -320,7 +318,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
+ 		/* Async requests need to be freed here */
+ 		if (req->uc_flags & REQ_ASYNC) {
+ 			CODA_FREE(req->uc_data, sizeof(struct coda_in_hdr));
+-			upc_free(req);
++			kfree(req);
+ 			continue;
+ 		}
+ 		req->uc_flags |= REQ_ABORT;
+diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
+index ad65ee01790f..330de7dbdcf8 100644
+--- a/fs/coda/upcall.c
++++ b/fs/coda/upcall.c
+@@ -37,9 +37,6 @@
+ #include 
+ #include  
+ 
+-#define upc_alloc() kmalloc(sizeof(struct upc_req), GFP_KERNEL)
+-#define upc_free(r) kfree(r)
+-
+ static int coda_upcall(struct coda_sb_info *mntinfo, int inSize, int *outSize, 
+ 		       union inputArgs *buffer);
+ 
+@@ -745,7 +742,7 @@ static int coda_upcall(struct coda_sb_info *sbi,
+ 	}
+ 
+ 	/* Format the request message. */
+-	req = upc_alloc();
++	req = kmalloc(sizeof(struct upc_req), GFP_KERNEL);
+ 	if (!req)
+ 		return -ENOMEM;
+ 
+@@ -802,12 +799,12 @@ static int coda_upcall(struct coda_sb_info *sbi,
+ 	}
+ 
+ 	error = -ENOMEM;
+-	sig_req = upc_alloc();
++	sig_req = kmalloc(sizeof(struct upc_req), GFP_KERNEL);
+ 	if (!sig_req) goto exit;
+ 
+ 	CODA_ALLOC((sig_req->uc_data), char *, sizeof(struct coda_in_hdr));
+ 	if (!sig_req->uc_data) {
+-		upc_free(sig_req);
++		kfree(sig_req);
+ 		goto exit;
+ 	}
+ 
+@@ -827,7 +824,7 @@ static int coda_upcall(struct coda_sb_info *sbi,
+ 	wake_up_interruptible(&vcommp->vc_waitq);
+ 
+ exit:
+-	upc_free(req);
++	kfree(req);
+ 	return error;
+ }
+ 

commit 978752534e94b50c8078b229134a37bad9db88b2
+Author: Jan Harkes 
+Date:   Thu Jul 19 01:48:47 2007 -0700
+
+    coda: avoid lockdep warning in coda_readdir
+    
+    Signed-off-by: Jan Harkes 
+    Cc: Al Viro 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/dir.c b/fs/coda/dir.c
+index 01f55f447d82..47ac9e21a590 100644
+--- a/fs/coda/dir.c
++++ b/fs/coda/dir.c
+@@ -43,15 +43,15 @@ static int coda_rename(struct inode *old_inode, struct dentry *old_dentry,
+                        struct inode *new_inode, struct dentry *new_dentry);
+ 
+ /* dir file-ops */
+-static int coda_readdir(struct file *file, void *dirent, filldir_t filldir);
++static int coda_readdir(struct file *file, void *buf, filldir_t filldir);
+ 
+ /* dentry ops */
+ static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd);
+ static int coda_dentry_delete(struct dentry *);
+ 
+ /* support routines */
+-static int coda_venus_readdir(struct file *filp, filldir_t filldir,
+-			      void *dirent, struct dentry *dir);
++static int coda_venus_readdir(struct file *coda_file, void *buf,
++			      filldir_t filldir);
+ 
+ /* same as fs/bad_inode.c */
+ static int coda_return_EIO(void)
+@@ -448,12 +448,10 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 
+ 
+ /* file operations for directories */
+-int coda_readdir(struct file *coda_file, void *dirent, filldir_t filldir)
++int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir)
+ {
+-	struct dentry *coda_dentry = coda_file->f_path.dentry;
+ 	struct coda_file_info *cfi;
+ 	struct file *host_file;
+-	struct inode *host_inode;
+ 	int ret;
+ 
+ 	cfi = CODA_FTOC(coda_file);
+@@ -462,30 +460,31 @@ int coda_readdir(struct file *coda_file, void *dirent, filldir_t filldir)
+ 
+ 	coda_vfs_stat.readdir++;
+ 
+-	host_inode = host_file->f_path.dentry->d_inode;
+-	mutex_lock(&host_inode->i_mutex);
+-	host_file->f_pos = coda_file->f_pos;
+-
+-	if (!host_file->f_op->readdir) {
+-		/* Venus: we must read Venus dirents from the file */
+-		ret = coda_venus_readdir(host_file, filldir, dirent, coda_dentry);
+-	} else {
+-		/* potemkin case: we were handed a directory inode. */
+-		/* Yuk, we can't call vfs_readdir because we are already
+-		 * holding the inode semaphore. */
+-		ret = -ENOTDIR;
+-		if (!host_file->f_op || !host_file->f_op->readdir)
+-			goto out;
++	if (!host_file->f_op)
++		return -ENOTDIR;
++
++	if (host_file->f_op->readdir)
++	{
++		/* potemkin case: we were handed a directory inode.
++		 * We can't use vfs_readdir because we have to keep the file
++		 * position in sync between the coda_file and the host_file.
++		 * and as such we need grab the inode mutex. */
++		struct inode *host_inode = host_file->f_path.dentry->d_inode;
++
++		mutex_lock(&host_inode->i_mutex);
++		host_file->f_pos = coda_file->f_pos;
+ 
+ 		ret = -ENOENT;
+ 		if (!IS_DEADDIR(host_inode)) {
+-			ret = host_file->f_op->readdir(host_file, dirent, filldir);
++			ret = host_file->f_op->readdir(host_file, buf, filldir);
+ 			file_accessed(host_file);
+ 		}
++
++		coda_file->f_pos = host_file->f_pos;
++		mutex_unlock(&host_inode->i_mutex);
+ 	}
+-out:
+-	coda_file->f_pos = host_file->f_pos;
+-	mutex_unlock(&host_inode->i_mutex);
++	else /* Venus: we must read Venus dirents from a file */
++		ret = coda_venus_readdir(coda_file, buf, filldir);
+ 
+ 	return ret;
+ }
+@@ -510,57 +509,68 @@ static inline unsigned int CDT2DT(unsigned char cdt)
+ }
+ 
+ /* support routines */
+-static int coda_venus_readdir(struct file *filp, filldir_t filldir,
+-			      void *dirent, struct dentry *dir)
++static int coda_venus_readdir(struct file *coda_file, void *buf,
++			      filldir_t filldir)
+ {
+ 	int result = 0; /* # of entries returned */
++	struct coda_file_info *cfi;
++	struct coda_inode_info *cii;
++	struct file *host_file;
++	struct dentry *de;
+ 	struct venus_dirent *vdir;
+ 	unsigned long vdir_size =
+ 	    (unsigned long)(&((struct venus_dirent *)0)->d_name);
+ 	unsigned int type;
+ 	struct qstr name;
+ 	ino_t ino;
+-	int ret, i;
++	int ret;
++
++	cfi = CODA_FTOC(coda_file);
++	BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
++	host_file = cfi->cfi_container;
++
++	de = coda_file->f_path.dentry;
++	cii = ITOC(de->d_inode);
+ 
+ 	vdir = kmalloc(sizeof(*vdir), GFP_KERNEL);
+ 	if (!vdir) return -ENOMEM;
+ 
+-	i = filp->f_pos;
+-	switch(i) {
++	switch (coda_file->f_pos) {
+ 	case 0:
+-		ret = filldir(dirent, ".", 1, 0, dir->d_inode->i_ino, DT_DIR);
++		ret = filldir(buf, ".", 1, 0, de->d_inode->i_ino, DT_DIR);
+ 		if (ret < 0) break;
+ 		result++;
+-		filp->f_pos++;
++		coda_file->f_pos++;
+ 		/* fallthrough */
+ 	case 1:
+-		ret = filldir(dirent, "..", 2, 1, dir->d_parent->d_inode->i_ino, DT_DIR);
++		ret = filldir(buf, "..", 2, 1, de->d_parent->d_inode->i_ino, DT_DIR);
+ 		if (ret < 0) break;
+ 		result++;
+-		filp->f_pos++;
++		coda_file->f_pos++;
+ 		/* fallthrough */
+ 	default:
+ 	while (1) {
+ 		/* read entries from the directory file */
+-		ret = kernel_read(filp, filp->f_pos - 2, (char *)vdir,
++		ret = kernel_read(host_file, coda_file->f_pos - 2, (char *)vdir,
+ 				  sizeof(*vdir));
+ 		if (ret < 0) {
+-			printk("coda_venus_readdir: read dir failed %d\n", ret);
++			printk(KERN_ERR "coda readdir: read dir %s failed %d\n",
++			       coda_f2s(&cii->c_fid), ret);
+ 			break;
+ 		}
+ 		if (ret == 0) break; /* end of directory file reached */
+ 
+ 		/* catch truncated reads */
+ 		if (ret < vdir_size || ret < vdir_size + vdir->d_namlen) {
+-			printk("coda_venus_readdir: short read: %ld\n",
+-			       filp->f_path.dentry->d_inode->i_ino);
++			printk(KERN_ERR "coda readdir: short read on %s\n",
++			       coda_f2s(&cii->c_fid));
+ 			ret = -EBADF;
+ 			break;
+ 		}
+ 		/* validate whether the directory file actually makes sense */
+ 		if (vdir->d_reclen < vdir_size + vdir->d_namlen) {
+-			printk("coda_venus_readdir: Invalid dir: %ld\n",
+-			       filp->f_path.dentry->d_inode->i_ino);
++			printk(KERN_ERR "coda readdir: invalid dir %s\n",
++			       coda_f2s(&cii->c_fid));
+ 			ret = -EBADF;
+ 			break;
+ 		}
+@@ -579,21 +589,21 @@ static int coda_venus_readdir(struct file *filp, filldir_t filldir,
+ 			 * userspace doesn't have to worry about breaking
+ 			 * getcwd by having mismatched inode numbers for
+ 			 * internal volume mountpoints. */
+-			ino = find_inode_number(dir, &name);
++			ino = find_inode_number(de, &name);
+ 			if (!ino) ino = vdir->d_fileno;
+ 
+ 			type = CDT2DT(vdir->d_type);
+-			ret = filldir(dirent, name.name, name.len, filp->f_pos,
+-				      ino, type); 
++			ret = filldir(buf, name.name, name.len,
++				      coda_file->f_pos, ino, type);
+ 			/* failure means no space for filling in this round */
+ 			if (ret < 0) break;
+ 			result++;
+ 		}
+ 		/* we'll always have progress because d_reclen is unsigned and
+ 		 * we've already established it is non-zero. */
+-		filp->f_pos += vdir->d_reclen;
++		coda_file->f_pos += vdir->d_reclen;
++	}
+ 	}
+-	} 
+ 	kfree(vdir);
+ 	return result ? result : ret;
+ }

commit d9664c95afe5baa92ea56eff6a1c18e7b7a2cbe7
+Author: Jan Harkes 
+Date:   Thu Jul 19 01:48:46 2007 -0700
+
+    coda: block signals during upcall processing
+    
+    We ignore signals for about 30 seconds to give userspace a chance to see the
+    upcall.  As we did not block signals we ended up in a busy loop for the
+    remainder of the period when a signal is received.
+    
+    Signed-off-by: Jan Harkes 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
+index 44332efa8411..ad65ee01790f 100644
+--- a/fs/coda/upcall.c
++++ b/fs/coda/upcall.c
+@@ -638,42 +638,83 @@ int venus_statfs(struct dentry *dentry, struct kstatfs *sfs)
+ 
+ /*
+  * coda_upcall and coda_downcall routines.
+- * 
+  */
++static void block_signals(sigset_t *old)
++{
++	spin_lock_irq(¤t->sighand->siglock);
++	*old = current->blocked;
++
++	sigfillset(¤t->blocked);
++	sigdelset(¤t->blocked, SIGKILL);
++	sigdelset(¤t->blocked, SIGSTOP);
++	sigdelset(¤t->blocked, SIGINT);
++
++	recalc_sigpending();
++	spin_unlock_irq(¤t->sighand->siglock);
++}
++
++static void unblock_signals(sigset_t *old)
++{
++	spin_lock_irq(¤t->sighand->siglock);
++	current->blocked = *old;
++	recalc_sigpending();
++	spin_unlock_irq(¤t->sighand->siglock);
++}
++
++/* Don't allow signals to interrupt the following upcalls before venus
++ * has seen them,
++ * - CODA_CLOSE or CODA_RELEASE upcall  (to avoid reference count problems)
++ * - CODA_STORE				(to avoid data loss)
++ */
++#define CODA_INTERRUPTIBLE(r) (!coda_hard && \
++			       (((r)->uc_opcode != CODA_CLOSE && \
++				 (r)->uc_opcode != CODA_STORE && \
++				 (r)->uc_opcode != CODA_RELEASE) || \
++				(r)->uc_flags & REQ_READ))
+ 
+-static inline void coda_waitfor_upcall(struct upc_req *vmp)
++static inline void coda_waitfor_upcall(struct upc_req *req)
+ {
+ 	DECLARE_WAITQUEUE(wait, current);
++	unsigned long timeout = jiffies + coda_timeout * HZ;
++	sigset_t old;
++	int blocked;
+ 
+-	vmp->uc_posttime = jiffies;
++	block_signals(&old);
++	blocked = 1;
+ 
+-	add_wait_queue(&vmp->uc_sleep, &wait);
++	add_wait_queue(&req->uc_sleep, &wait);
+ 	for (;;) {
+-		if ( !coda_hard && vmp->uc_opcode != CODA_CLOSE ) 
++		if (CODA_INTERRUPTIBLE(req))
+ 			set_current_state(TASK_INTERRUPTIBLE);
+ 		else
+ 			set_current_state(TASK_UNINTERRUPTIBLE);
+ 
+ 		/* got a reply */
+-		if ( vmp->uc_flags & ( REQ_WRITE | REQ_ABORT ) )
++		if (req->uc_flags & (REQ_WRITE | REQ_ABORT))
+ 			break;
+ 
+-		if ( !coda_hard && vmp->uc_opcode != CODA_CLOSE && signal_pending(current) ) {
+-			/* if this process really wants to die, let it go */
+-			if ( sigismember(&(current->pending.signal), SIGKILL) ||
+-			     sigismember(&(current->pending.signal), SIGINT) )
+-				break;
+-			/* signal is present: after timeout always return 
+-			   really smart idea, probably useless ... */
+-			if ( jiffies - vmp->uc_posttime > coda_timeout * HZ )
+-				break; 
++		if (blocked && time_after(jiffies, timeout) &&
++		    CODA_INTERRUPTIBLE(req))
++		{
++			unblock_signals(&old);
++			blocked = 0;
+ 		}
+-		schedule();
++
++		if (signal_pending(current)) {
++			list_del(&req->uc_chain);
++			break;
++		}
++
++		if (blocked)
++			schedule_timeout(HZ);
++		else
++			schedule();
+ 	}
+-	remove_wait_queue(&vmp->uc_sleep, &wait);
+-	set_current_state(TASK_RUNNING);
++	if (blocked)
++		unblock_signals(&old);
+ 
+-	return;
++	remove_wait_queue(&req->uc_sleep, &wait);
++	set_current_state(TASK_RUNNING);
+ }
+ 
+ 
+@@ -750,8 +791,6 @@ static int coda_upcall(struct coda_sb_info *sbi,
+ 		goto exit;
+ 	}
+ 
+-	list_del(&(req->uc_chain));
+-
+ 	/* Interrupted before venus read it. */
+ 	if (!(req->uc_flags & REQ_READ))
+ 		goto exit;
+diff --git a/include/linux/coda_psdev.h b/include/linux/coda_psdev.h
+index b541bb3d1f4b..f28c2f7fd454 100644
+--- a/include/linux/coda_psdev.h
++++ b/include/linux/coda_psdev.h
+@@ -85,7 +85,6 @@ struct upc_req {
+ 	u_short	            uc_opcode;  /* copied from data to save lookup */
+ 	int		    uc_unique;
+ 	wait_queue_head_t   uc_sleep;   /* process' wait queue */
+-	unsigned long       uc_posttime;
+ };
+ 
+ #define REQ_ASYNC  0x1

commit fe71b5f3871af2c281a08acd4bedd2da25e46bc3
+Author: Jan Harkes 
+Date:   Thu Jul 19 01:48:46 2007 -0700
+
+    coda: cleanup for upcall handling path
+    
+    Make the code that processes upcall responses more straightforward, uncovered
+    at least one bad assumption.  We trusted that vc_inuse would be 0 when upcalls
+    are aborted, however the device may have been reopened.
+    
+    Signed-off-by: Jan Harkes 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
+index a44ca4155fd5..44332efa8411 100644
+--- a/fs/coda/upcall.c
++++ b/fs/coda/upcall.c
+@@ -687,27 +687,27 @@ static inline void coda_waitfor_upcall(struct upc_req *vmp)
+  * are all mapped to -EINTR, while showing a nice warning message. (jh)
+  * 
+  */
+-static int coda_upcall(struct coda_sb_info *sbi, 
+-		int inSize, int *outSize, 
+-		union inputArgs *buffer) 
++static int coda_upcall(struct coda_sb_info *sbi,
++		       int inSize, int *outSize,
++		       union inputArgs *buffer)
+ {
+ 	struct venus_comm *vcommp;
+ 	union outputArgs *out;
+-	struct upc_req *req;
++	union inputArgs *sig_inputArgs;
++	struct upc_req *req, *sig_req;
+ 	int error = 0;
+ 
+ 	vcommp = sbi->sbi_vcomm;
+-	if ( !vcommp->vc_inuse ) {
+-		printk("No pseudo device in upcall comms at %p\n", vcommp);
+-                return -ENXIO;
++	if (!vcommp->vc_inuse) {
++		printk(KERN_NOTICE "coda: Venus dead, not sending upcall\n");
++		return -ENXIO;
+ 	}
+ 
+ 	/* Format the request message. */
+ 	req = upc_alloc();
+-	if (!req) {
+-		printk("Failed to allocate upc_req structure\n");
++	if (!req)
+ 		return -ENOMEM;
+-	}
++
+ 	req->uc_data = (void *)buffer;
+ 	req->uc_flags = 0;
+ 	req->uc_inSize = inSize;
+@@ -715,13 +715,13 @@ static int coda_upcall(struct coda_sb_info *sbi,
+ 	req->uc_opcode = ((union inputArgs *)buffer)->ih.opcode;
+ 	req->uc_unique = ++vcommp->vc_seq;
+ 	init_waitqueue_head(&req->uc_sleep);
+-	
++
+ 	/* Fill in the common input args. */
+ 	((union inputArgs *)buffer)->ih.unique = req->uc_unique;
+ 
+ 	/* Append msg to pending queue and poke Venus. */
+-	list_add_tail(&(req->uc_chain), &vcommp->vc_pending);
+-        
++	list_add_tail(&req->uc_chain, &vcommp->vc_pending);
++
+ 	wake_up_interruptible(&vcommp->vc_waitq);
+ 	/* We can be interrupted while we wait for Venus to process
+ 	 * our request.  If the interrupt occurs before Venus has read
+@@ -735,64 +735,59 @@ static int coda_upcall(struct coda_sb_info *sbi,
+ 	/* Go to sleep.  Wake up on signals only after the timeout. */
+ 	coda_waitfor_upcall(req);
+ 
+-	if (vcommp->vc_inuse) {      /* i.e. Venus is still alive */
+-	    /* Op went through, interrupt or not... */
+-	    if (req->uc_flags & REQ_WRITE) {
++	/* Op went through, interrupt or not... */
++	if (req->uc_flags & REQ_WRITE) {
+ 		out = (union outputArgs *)req->uc_data;
+ 		/* here we map positive Venus errors to kernel errors */
+ 		error = -out->oh.result;
+ 		*outSize = req->uc_outSize;
+ 		goto exit;
+-	    }
+-	    if ( !(req->uc_flags & REQ_READ) && signal_pending(current)) { 
+-		/* Interrupted before venus read it. */
+-		list_del(&(req->uc_chain));
+-		/* perhaps the best way to convince the app to
+-		   give up? */
+-		error = -EINTR;
++	}
++
++	error = -EINTR;
++	if ((req->uc_flags & REQ_ABORT) || !signal_pending(current)) {
++		printk(KERN_WARNING "coda: Unexpected interruption.\n");
+ 		goto exit;
+-	    } 
+-	    if ( (req->uc_flags & REQ_READ) && signal_pending(current) ) {
+-		    /* interrupted after Venus did its read, send signal */
+-		    union inputArgs *sig_inputArgs;
+-		    struct upc_req *sig_req;
+-		    
+-		    list_del(&(req->uc_chain));
+-		    error = -ENOMEM;
+-		    sig_req = upc_alloc();
+-		    if (!sig_req) goto exit;
+-
+-		    CODA_ALLOC((sig_req->uc_data), char *, sizeof(struct coda_in_hdr));
+-		    if (!sig_req->uc_data) {
+-			upc_free(sig_req);
+-			goto exit;
+-		    }
+-		    
+-		    error = -EINTR;
+-		    sig_inputArgs = (union inputArgs *)sig_req->uc_data;
+-		    sig_inputArgs->ih.opcode = CODA_SIGNAL;
+-		    sig_inputArgs->ih.unique = req->uc_unique;
+-		    
+-		    sig_req->uc_flags = REQ_ASYNC;
+-		    sig_req->uc_opcode = sig_inputArgs->ih.opcode;
+-		    sig_req->uc_unique = sig_inputArgs->ih.unique;
+-		    sig_req->uc_inSize = sizeof(struct coda_in_hdr);
+-		    sig_req->uc_outSize = sizeof(struct coda_in_hdr);
+-		    
+-		    /* insert at head of queue! */
+-		    list_add(&(sig_req->uc_chain), &vcommp->vc_pending);
+-		    wake_up_interruptible(&vcommp->vc_waitq);
+-	    } else {
+-		    printk("Coda: Strange interruption..\n");
+-		    error = -EINTR;
+-	    }
+-	} else {	/* If venus died i.e. !VC_OPEN(vcommp) */
+-	        printk("coda_upcall: Venus dead on (op,un) (%d.%d) flags %d\n",
+-		       req->uc_opcode, req->uc_unique, req->uc_flags);
+-		error = -ENODEV;
+ 	}
+ 
+- exit:
++	list_del(&(req->uc_chain));
++
++	/* Interrupted before venus read it. */
++	if (!(req->uc_flags & REQ_READ))
++		goto exit;
++
++	/* Venus saw the upcall, make sure we can send interrupt signal */
++	if (!vcommp->vc_inuse) {
++		printk(KERN_INFO "coda: Venus dead, not sending signal.\n");
++		goto exit;
++	}
++
++	error = -ENOMEM;
++	sig_req = upc_alloc();
++	if (!sig_req) goto exit;
++
++	CODA_ALLOC((sig_req->uc_data), char *, sizeof(struct coda_in_hdr));
++	if (!sig_req->uc_data) {
++		upc_free(sig_req);
++		goto exit;
++	}
++
++	error = -EINTR;
++	sig_inputArgs = (union inputArgs *)sig_req->uc_data;
++	sig_inputArgs->ih.opcode = CODA_SIGNAL;
++	sig_inputArgs->ih.unique = req->uc_unique;
++
++	sig_req->uc_flags = REQ_ASYNC;
++	sig_req->uc_opcode = sig_inputArgs->ih.opcode;
++	sig_req->uc_unique = sig_inputArgs->ih.unique;
++	sig_req->uc_inSize = sizeof(struct coda_in_hdr);
++	sig_req->uc_outSize = sizeof(struct coda_in_hdr);
++
++	/* insert at head of queue! */
++	list_add(&(sig_req->uc_chain), &vcommp->vc_pending);
++	wake_up_interruptible(&vcommp->vc_waitq);
++
++exit:
+ 	upc_free(req);
+ 	return error;
+ }

commit 87065519633af79e0577e32a58dcd9cf3c45a8a0
+Author: Jan Harkes 
+Date:   Thu Jul 19 01:48:45 2007 -0700
+
+    coda: cleanup /dev/cfs open and close handling
+    
+    - Make sure device index is not a negative number.
+    - Unlink queued requests when the device is closed to avoid passing them
+      to the next opener.
+    
+    Signed-off-by: Jan Harkes 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
+index 09382d47a4e1..6818c20372ca 100644
+--- a/fs/coda/psdev.c
++++ b/fs/coda/psdev.c
+@@ -272,56 +272,51 @@ static ssize_t coda_psdev_read(struct file * file, char __user * buf,
+ 
+ static int coda_psdev_open(struct inode * inode, struct file * file)
+ {
+-        struct venus_comm *vcp;
+-	int idx;
++	struct venus_comm *vcp;
++	int idx, err;
+ 
+-	lock_kernel();
+ 	idx = iminor(inode);
+-	if(idx >= MAX_CODADEVS) {
+-		unlock_kernel();
++	if (idx < 0 || idx >= MAX_CODADEVS)
+ 		return -ENODEV;
+-	}
+ 
++	lock_kernel();
++
++	err = -EBUSY;
+ 	vcp = &coda_comms[idx];
+-	if(vcp->vc_inuse) {
+-		unlock_kernel();
+-		return -EBUSY;
+-	}
+-	
+-	if (!vcp->vc_inuse++) {
++	if (!vcp->vc_inuse) {
++		vcp->vc_inuse++;
++
+ 		INIT_LIST_HEAD(&vcp->vc_pending);
+ 		INIT_LIST_HEAD(&vcp->vc_processing);
+ 		init_waitqueue_head(&vcp->vc_waitq);
+ 		vcp->vc_sb = NULL;
+ 		vcp->vc_seq = 0;
++
++		file->private_data = vcp;
++		err = 0;
+ 	}
+-	
+-	file->private_data = vcp;
+ 
+ 	unlock_kernel();
+-        return 0;
++	return err;
+ }
+ 
+ 
+ static int coda_psdev_release(struct inode * inode, struct file * file)
+ {
+-        struct venus_comm *vcp = (struct venus_comm *) file->private_data;
+-        struct upc_req *req, *tmp;
++	struct venus_comm *vcp = (struct venus_comm *) file->private_data;
++	struct upc_req *req, *tmp;
+ 
+-	lock_kernel();
+-	if ( !vcp->vc_inuse ) {
+-		unlock_kernel();
++	if (!vcp || !vcp->vc_inuse ) {
+ 		printk("psdev_release: Not open.\n");
+ 		return -1;
+ 	}
+ 
+-	if (--vcp->vc_inuse) {
+-		unlock_kernel();
+-		return 0;
+-	}
+-        
+-        /* Wakeup clients so they can return. */
++	lock_kernel();
++
++	/* Wakeup clients so they can return. */
+ 	list_for_each_entry_safe(req, tmp, &vcp->vc_pending, uc_chain) {
++		list_del(&req->uc_chain);
++
+ 		/* Async requests need to be freed here */
+ 		if (req->uc_flags & REQ_ASYNC) {
+ 			CODA_FREE(req->uc_data, sizeof(struct coda_in_hdr));
+@@ -330,13 +325,17 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
+ 		}
+ 		req->uc_flags |= REQ_ABORT;
+ 		wake_up(&req->uc_sleep);
+-        }
+-        
+-	list_for_each_entry(req, &vcp->vc_processing, uc_chain) {
++	}
++
++	list_for_each_entry_safe(req, tmp, &vcp->vc_processing, uc_chain) {
++		list_del(&req->uc_chain);
++
+ 		req->uc_flags |= REQ_ABORT;
+-	        wake_up(&req->uc_sleep);
+-        }
++		wake_up(&req->uc_sleep);
++	}
+ 
++	file->private_data = NULL;
++	vcp->vc_inuse--;
+ 	unlock_kernel();
+ 	return 0;
+ }
+diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
+index 1651b918219a..a44ca4155fd5 100644
+--- a/fs/coda/upcall.c
++++ b/fs/coda/upcall.c
+@@ -641,8 +641,7 @@ int venus_statfs(struct dentry *dentry, struct kstatfs *sfs)
+  * 
+  */
+ 
+-static inline void coda_waitfor_upcall(struct upc_req *vmp,
+-				       struct venus_comm *vcommp)
++static inline void coda_waitfor_upcall(struct upc_req *vmp)
+ {
+ 	DECLARE_WAITQUEUE(wait, current);
+ 
+@@ -655,10 +654,6 @@ static inline void coda_waitfor_upcall(struct upc_req *vmp,
+ 		else
+ 			set_current_state(TASK_UNINTERRUPTIBLE);
+ 
+-                /* venus died */
+-                if ( !vcommp->vc_inuse )
+-                        break;
+-
+ 		/* got a reply */
+ 		if ( vmp->uc_flags & ( REQ_WRITE | REQ_ABORT ) )
+ 			break;
+@@ -738,7 +733,7 @@ static int coda_upcall(struct coda_sb_info *sbi,
+ 	 * ENODEV.  */
+ 
+ 	/* Go to sleep.  Wake up on signals only after the timeout. */
+-	coda_waitfor_upcall(req, vcommp);
++	coda_waitfor_upcall(req);
+ 
+ 	if (vcommp->vc_inuse) {      /* i.e. Venus is still alive */
+ 	    /* Op went through, interrupt or not... */

commit ed31a7dd636b296746c131b7386023aa1ef84309
+Author: Jan Harkes 
+Date:   Thu Jul 19 01:48:44 2007 -0700
+
+    coda: use ilookup5
+    
+    Signed-off-by: Jan Harkes 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c
+index 28c872747f81..a7a780929eec 100644
+--- a/fs/coda/cnode.c
++++ b/fs/coda/cnode.c
+@@ -55,11 +55,6 @@ static int coda_set_inode(struct inode *inode, void *data)
+ 	return 0;
+ }
+ 
+-static int coda_fail_inode(struct inode *inode, void *data)
+-{
+-	return -1;
+-}
+-
+ struct inode * coda_iget(struct super_block * sb, struct CodaFid * fid,
+ 			 struct coda_vattr * attr)
+ {
+@@ -141,7 +136,7 @@ struct inode *coda_fid_to_inode(struct CodaFid *fid, struct super_block *sb)
+ 		return NULL;
+ 	}
+ 
+-	inode = iget5_locked(sb, hash, coda_test_inode, coda_fail_inode, fid);
++	inode = ilookup5(sb, hash, coda_test_inode, fid);
+ 	if ( !inode )
+ 		return NULL;
+ 

commit fac1f0e34026a656174102ebad4d1cd71cd4fe2c
+Author: Jan Harkes 
+Date:   Thu Jul 19 01:48:44 2007 -0700
+
+    coda: coda doesn't track atime
+    
+    Set MS_NOATIME flag to avoid unnecessary calls when the coda inode is
+    accessed.
+    
+    Also, set statfs.f_bsize to 4k.  1k is obviously too small for the suggested
+    IO size.
+    
+    Signed-off-by: Jan Harkes 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/inode.c b/fs/coda/inode.c
+index dbff1bd4fb96..29e441765600 100644
+--- a/fs/coda/inode.c
++++ b/fs/coda/inode.c
+@@ -83,7 +83,7 @@ void coda_destroy_inodecache(void)
+ 
+ static int coda_remount(struct super_block *sb, int *flags, char *data)
+ {
+-	*flags |= MS_NODIRATIME;
++	*flags |= MS_NOATIME;
+ 	return 0;
+ }
+ 
+@@ -176,12 +176,12 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
+ 
+ 	sbi->sbi_vcomm = vc;
+ 
+-        sb->s_fs_info = sbi;
+-	sb->s_flags |= MS_NODIRATIME; /* probably even noatime */
+-        sb->s_blocksize = 1024;	/* XXXXX  what do we put here?? */
+-        sb->s_blocksize_bits = 10;
+-        sb->s_magic = CODA_SUPER_MAGIC;
+-        sb->s_op = &coda_super_operations;
++	sb->s_fs_info = sbi;
++	sb->s_flags |= MS_NOATIME;
++	sb->s_blocksize = 4096;	/* XXXXX  what do we put here?? */
++	sb->s_blocksize_bits = 12;
++	sb->s_magic = CODA_SUPER_MAGIC;
++	sb->s_op = &coda_super_operations;
+ 
+ 	/* get root fid from Venus: this needs the root inode */
+ 	error = venus_rootfid(sb, &fid);
+@@ -296,7 +296,7 @@ static int coda_statfs(struct dentry *dentry, struct kstatfs *buf)
+ 
+ 	/* and fill in the rest */
+ 	buf->f_type = CODA_SUPER_MAGIC;
+-	buf->f_bsize = 1024;
++	buf->f_bsize = 4096;
+ 	buf->f_namelen = CODA_MAXNAMLEN;
+ 
+ 	return 0; 

commit 8c6d21528406ec719aaea9d589876fd105c31646
+Author: Jan Harkes 
+Date:   Thu Jul 19 01:48:43 2007 -0700
+
+    coda: allow removal of busy directories
+    
+    A directory without children may still be busy when it is the cwd for some
+    process.  We can safely remove such a directory because the VFS prevents
+    further operations.  Also we don't need to call d_delete as it is already
+    called in vfs_rmdir.
+    
+    Signed-off-by: Jan Harkes 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/dir.c b/fs/coda/dir.c
+index 56a3b76b91ca..01f55f447d82 100644
+--- a/fs/coda/dir.c
++++ b/fs/coda/dir.c
+@@ -391,28 +391,23 @@ int coda_rmdir(struct inode *dir, struct dentry *de)
+ {
+ 	const char *name = de->d_name.name;
+ 	int len = de->d_name.len;
+-        int error;
++	int error;
+ 
+ 	lock_kernel();
+ 	coda_vfs_stat.rmdir++;
+ 
+-	if (!d_unhashed(de)) {
+-		unlock_kernel();
+-		return -EBUSY;
+-	}
+ 	error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len);
++	if (!error) {
++		/* VFS may delete the child */
++		if (de->d_inode)
++		    de->d_inode->i_nlink = 0;
+ 
+-	if ( error ) {
+-		unlock_kernel();
+-		return error;
++		/* fix the link count of the parent */
++		coda_dir_drop_nlink(dir);
++		coda_dir_update_mtime(dir);
+ 	}
+-
+-	coda_dir_drop_nlink(dir);
+-	coda_dir_update_mtime(dir);
+-	drop_nlink(de->d_inode);
+-	d_delete(de);
+ 	unlock_kernel();
+-	return 0;
++	return error;
+ }
+ 
+ /* rename */

commit d728900cd5502927158db747c653007cf72e2e49
+Author: Jan Harkes 
+Date:   Thu Jul 19 01:48:43 2007 -0700
+
+    coda: fix nlink updates for directories
+    
+    The Coda client sets the directory link count to 1 when it isn't sure how many
+    subdirectories we have.  In this case we shouldn't change the link count in
+    the kernel when a subdirectory is created or removed.
+    
+    Signed-off-by: Jan Harkes 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/dir.c b/fs/coda/dir.c
+index 898a86dde8f5..56a3b76b91ca 100644
+--- a/fs/coda/dir.c
++++ b/fs/coda/dir.c
+@@ -173,12 +173,11 @@ int coda_permission(struct inode *inode, int mask, struct nameidata *nd)
+ 
+  out:
+ 	unlock_kernel();
+-
+-        return error; 
++	return error;
+ }
+ 
+ 
+-static inline void coda_dir_changed(struct inode *dir, int link)
++static inline void coda_dir_update_mtime(struct inode *dir)
+ {
+ #ifdef REQUERY_VENUS_FOR_MTIME
+ 	/* invalidate the directory cnode's attributes so we refetch the
+@@ -186,12 +185,27 @@ static inline void coda_dir_changed(struct inode *dir, int link)
+ 	coda_flag_inode(dir, C_VATTR);
+ #else
+ 	/* optimistically we can also act as if our nose bleeds. The
+-         * granularity of the mtime is coarse anyways so we might actually be
+-         * right most of the time. Note: we only do this for directories. */
++	 * granularity of the mtime is coarse anyways so we might actually be
++	 * right most of the time. Note: we only do this for directories. */
+ 	dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
+ #endif
+-	if (link)
+-		dir->i_nlink += link;
++}
++
++/* we have to wrap inc_nlink/drop_nlink because sometimes userspace uses a
++ * trick to fool GNU find's optimizations. If we can't be sure of the link
++ * (because of volume mount points) we set i_nlink to 1 which forces find
++ * to consider every child as a possible directory. We should also never
++ * see an increment or decrement for deleted directories where i_nlink == 0 */
++static inline void coda_dir_inc_nlink(struct inode *dir)
++{
++	if (dir->i_nlink >= 2)
++		inc_nlink(dir);
++}
++
++static inline void coda_dir_drop_nlink(struct inode *dir)
++{
++	if (dir->i_nlink > 2)
++		drop_nlink(dir);
+ }
+ 
+ /* creation routines: create, mknod, mkdir, link, symlink */
+@@ -229,10 +243,10 @@ static int coda_create(struct inode *dir, struct dentry *de, int mode, struct na
+ 	}
+ 
+ 	/* invalidate the directory cnode's attributes */
+-	coda_dir_changed(dir, 0);
++	coda_dir_update_mtime(dir);
+ 	unlock_kernel();
+ 	d_instantiate(de, inode);
+-        return 0;
++	return 0;
+ }
+ 
+ static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
+@@ -268,12 +282,13 @@ static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
+ 		d_drop(de);
+ 		return PTR_ERR(inode);
+ 	}
+-	
++
+ 	/* invalidate the directory cnode's attributes */
+-	coda_dir_changed(dir, 1);
++	coda_dir_inc_nlink(dir);
++	coda_dir_update_mtime(dir);
+ 	unlock_kernel();
+ 	d_instantiate(de, inode);
+-        return 0;
++	return 0;
+ }
+ 
+ /* try to make de an entry in dir_inodde linked to source_de */ 
+@@ -296,16 +311,16 @@ static int coda_link(struct dentry *source_de, struct inode *dir_inode,
+ 	error = venus_link(dir_inode->i_sb, coda_i2f(inode),
+ 			   coda_i2f(dir_inode), (const char *)name, len);
+ 
+-	if (error) { 
++	if (error) {
+ 		d_drop(de);
+ 		goto out;
+ 	}
+ 
+-	coda_dir_changed(dir_inode, 0);
++	coda_dir_update_mtime(dir_inode);
+ 	atomic_inc(&inode->i_count);
+ 	d_instantiate(de, inode);
+ 	inc_nlink(inode);
+-        
++
+ out:
+ 	unlock_kernel();
+ 	return(error);
+@@ -336,18 +351,18 @@ static int coda_symlink(struct inode *dir_inode, struct dentry *de,
+ 
+ 	/*
+ 	 * This entry is now negative. Since we do not create
+-	 * an inode for the entry we have to drop it. 
++	 * an inode for the entry we have to drop it.
+ 	 */
+ 	d_drop(de);
+-	error = venus_symlink(dir_inode->i_sb, coda_i2f(dir_inode), name, len, 
++	error = venus_symlink(dir_inode->i_sb, coda_i2f(dir_inode), name, len,
+ 			      symname, symlen);
+ 
+ 	/* mtime is no good anymore */
+ 	if ( !error )
+-		coda_dir_changed(dir_inode, 0);
++		coda_dir_update_mtime(dir_inode);
+ 
+ 	unlock_kernel();
+-        return error;
++	return error;
+ }
+ 
+ /* destruction routines: unlink, rmdir */
+@@ -360,17 +375,16 @@ int coda_unlink(struct inode *dir, struct dentry *de)
+ 	lock_kernel();
+ 	coda_vfs_stat.unlink++;
+ 
+-        error = venus_remove(dir->i_sb, coda_i2f(dir), name, len);
+-        if ( error ) {
++	error = venus_remove(dir->i_sb, coda_i2f(dir), name, len);
++	if ( error ) {
+ 		unlock_kernel();
+-                return error;
+-        }
++		return error;
++	}
+ 
+-	coda_dir_changed(dir, 0);
++	coda_dir_update_mtime(dir);
+ 	drop_nlink(de->d_inode);
+ 	unlock_kernel();
+-
+-        return 0;
++	return 0;
+ }
+ 
+ int coda_rmdir(struct inode *dir, struct dentry *de)
+@@ -388,49 +402,49 @@ int coda_rmdir(struct inode *dir, struct dentry *de)
+ 	}
+ 	error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len);
+ 
+-        if ( error ) {
++	if ( error ) {
+ 		unlock_kernel();
+-                return error;
+-        }
++		return error;
++	}
+ 
+-	coda_dir_changed(dir, -1);
++	coda_dir_drop_nlink(dir);
++	coda_dir_update_mtime(dir);
+ 	drop_nlink(de->d_inode);
+ 	d_delete(de);
+ 	unlock_kernel();
+-
+-        return 0;
++	return 0;
+ }
+ 
+ /* rename */
+-static int coda_rename(struct inode *old_dir, struct dentry *old_dentry, 
++static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 		       struct inode *new_dir, struct dentry *new_dentry)
+ {
+-        const char *old_name = old_dentry->d_name.name;
+-        const char *new_name = new_dentry->d_name.name;
++	const char *old_name = old_dentry->d_name.name;
++	const char *new_name = new_dentry->d_name.name;
+ 	int old_length = old_dentry->d_name.len;
+ 	int new_length = new_dentry->d_name.len;
+-        int link_adjust = 0;
+-        int error;
++	int error;
+ 
+ 	lock_kernel();
+ 	coda_vfs_stat.rename++;
+ 
+-        error = venus_rename(old_dir->i_sb, coda_i2f(old_dir), 
+-			     coda_i2f(new_dir), old_length, new_length, 
++	error = venus_rename(old_dir->i_sb, coda_i2f(old_dir),
++			     coda_i2f(new_dir), old_length, new_length,
+ 			     (const char *) old_name, (const char *)new_name);
+ 
+-        if ( !error ) {
++	if ( !error ) {
+ 		if ( new_dentry->d_inode ) {
+-			if ( S_ISDIR(new_dentry->d_inode->i_mode) )
+-                        	link_adjust = 1;
+-
+-                        coda_dir_changed(old_dir, -link_adjust);
+-                        coda_dir_changed(new_dir,  link_adjust);
++			if ( S_ISDIR(new_dentry->d_inode->i_mode) ) {
++				coda_dir_drop_nlink(old_dir);
++				coda_dir_inc_nlink(new_dir);
++			}
++			coda_dir_update_mtime(old_dir);
++			coda_dir_update_mtime(new_dir);
+ 			coda_flag_inode(new_dentry->d_inode, C_VATTR);
+ 		} else {
+ 			coda_flag_inode(old_dir, C_VATTR);
+ 			coda_flag_inode(new_dir, C_VATTR);
+-                }
++		}
+ 	}
+ 	unlock_kernel();
+ 

commit 56ee3547940f895a2cf20f2ac462fbeaee55fa2a
+Author: Jan Harkes 
+Date:   Thu Jul 19 01:48:42 2007 -0700
+
+    coda: correctly invalidate cached access rights
+    
+    Change the epoch value to forces a refresh instead of clearing the cached
+    rights mask and block all further accesses to the object.
+    
+    Signed-off-by: Jan Harkes 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/cache.c b/fs/coda/cache.c
+index fcb88fa8d2f2..11538a2b5423 100644
+--- a/fs/coda/cache.c
++++ b/fs/coda/cache.c
+@@ -43,7 +43,7 @@ void coda_cache_enter(struct inode *inode, int mask)
+ void coda_cache_clear_inode(struct inode *inode)
+ {
+ 	struct coda_inode_info *cii = ITOC(inode);
+-        cii->c_cached_perm = 0;
++	cii->c_cached_epoch = atomic_read(&permission_epoch) - 1;
+ }
+ 
+ /* remove all acl caches */

commit 38c2e4370da495813ca93d7cad31ed5090e8c310
+Author: Jan Harkes 
+Date:   Thu Jul 19 01:48:41 2007 -0700
+
+    coda: do not grab an uninitialized fd when the open upcall returns an error
+    
+    When open fails the fd in the response is uninitialized and we ended up taking
+    a reference on the file struct and never released it.
+    
+    Signed-off-by: Jan Harkes 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/coda/file.c b/fs/coda/file.c
+index 99dbe866816d..e7d622709c90 100644
+--- a/fs/coda/file.c
++++ b/fs/coda/file.c
+@@ -143,8 +143,11 @@ int coda_open(struct inode *coda_inode, struct file *coda_file)
+ 	lock_kernel();
+ 
+ 	error = venus_open(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags,
+-			   &host_file); 
+-	if (error || !host_file) {
++			   &host_file);
++	if (!host_file)
++		error = -EIO;
++
++	if (error) {
+ 		kfree(cfi);
+ 		unlock_kernel();
+ 		return error;
+diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
+index 803aacf0d49c..09382d47a4e1 100644
+--- a/fs/coda/psdev.c
++++ b/fs/coda/psdev.c
+@@ -195,7 +195,8 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
+ 	if (req->uc_opcode == CODA_OPEN_BY_FD) {
+ 		struct coda_open_by_fd_out *outp =
+ 			(struct coda_open_by_fd_out *)req->uc_data;
+-		outp->fh = fget(outp->fd);
++		if (!outp->oh.result)
++			outp->fh = fget(outp->fd);
+ 	}
+ 
+         wake_up(&req->uc_sleep);
+diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
+index 5faacdb1a479..1651b918219a 100644
+--- a/fs/coda/upcall.c
++++ b/fs/coda/upcall.c
+@@ -251,12 +251,12 @@ int venus_open(struct super_block *sb, struct CodaFid *fid,
+ 	insize = SIZE(open_by_fd);
+ 	UPARG(CODA_OPEN_BY_FD);
+ 
+-        inp->coda_open.VFid = *fid;
+-        inp->coda_open.flags = flags;
++	inp->coda_open_by_fd.VFid = *fid;
++	inp->coda_open_by_fd.flags = flags;
+ 
+-        error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
+-
+-	*fh = outp->coda_open_by_fd.fh;
++	error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
++	if (!error)
++		*fh = outp->coda_open_by_fd.fh;
+ 
+ 	CODA_FREE(inp, insize);
+ 	return error;

commit 7deeed13170e634adc4552ff94588d6301a3da83
+Author: Benjamin Gilbert 
+Date:   Tue Jun 19 09:05:21 2007 +0200
+
+    [TRIVIAL PATCH] Kill blk_congestion_wait() stub for !CONFIG_BLOCK
+    
+    blk_congestion_wait() doesn't exist anymore, but there's still a stub
+    in blkdev.h for the !CONFIG_BLOCK case.  Kill it.
+    
+    Signed-off-by: Benjamin Gilbert 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
+index db5b00a792f5..fae138bd2207 100644
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -868,11 +868,6 @@ void kblockd_flush_work(struct work_struct *work);
+  */
+ #define buffer_heads_over_limit 0
+ 
+-static inline long blk_congestion_wait(int rw, long timeout)
+-{
+-	return io_schedule_timeout(timeout);
+-}
+-
+ static inline long nr_blockdev_pages(void)
+ {
+ 	return 0;

commit d4473b9b778f39f0b5da870a9a96b5778861c60b
+Author: Eric Cooper 
+Date:   Sat Jul 29 20:10:54 2017 -0400
+
+    rtc: m41t80: enable wakealarm when "wakeup-source" is specified
+    
+    Don't require an IRQ if the wakeup-source device-tree property is present.
+    
+    Signed-off-by: Eric Cooper 
+    Signed-off-by: Alexandre Belloni 
+
+diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
+index 8940e9e43ea0..412a4e04de79 100644
+--- a/drivers/rtc/rtc-m41t80.c
++++ b/drivers/rtc/rtc-m41t80.c
+@@ -927,6 +927,7 @@ static int m41t80_probe(struct i2c_client *client,
+ 	struct rtc_device *rtc = NULL;
+ 	struct rtc_time tm;
+ 	struct m41t80_data *m41t80_data = NULL;
++	bool wakeup_source = false;
+ 
+ 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK |
+ 				     I2C_FUNC_SMBUS_BYTE_DATA)) {
+@@ -947,6 +948,10 @@ static int m41t80_probe(struct i2c_client *client,
+ 		m41t80_data->features = id->driver_data;
+ 	i2c_set_clientdata(client, m41t80_data);
+ 
++#ifdef CONFIG_OF
++	wakeup_source = of_property_read_bool(client->dev.of_node,
++					      "wakeup-source");
++#endif
+ 	if (client->irq > 0) {
+ 		rc = devm_request_threaded_irq(&client->dev, client->irq,
+ 					       NULL, m41t80_handle_irq,
+@@ -955,14 +960,16 @@ static int m41t80_probe(struct i2c_client *client,
+ 		if (rc) {
+ 			dev_warn(&client->dev, "unable to request IRQ, alarms disabled\n");
+ 			client->irq = 0;
+-		} else {
+-			m41t80_rtc_ops.read_alarm = m41t80_read_alarm;
+-			m41t80_rtc_ops.set_alarm = m41t80_set_alarm;
+-			m41t80_rtc_ops.alarm_irq_enable = m41t80_alarm_irq_enable;
+-			/* Enable the wakealarm */
+-			device_init_wakeup(&client->dev, true);
++			wakeup_source = false;
+ 		}
+ 	}
++	if (client->irq > 0 || wakeup_source) {
++		m41t80_rtc_ops.read_alarm = m41t80_read_alarm;
++		m41t80_rtc_ops.set_alarm = m41t80_set_alarm;
++		m41t80_rtc_ops.alarm_irq_enable = m41t80_alarm_irq_enable;
++		/* Enable the wakealarm */
++		device_init_wakeup(&client->dev, true);
++	}
+ 
+ 	rtc = devm_rtc_device_register(&client->dev, client->name,
+ 				       &m41t80_rtc_ops, THIS_MODULE);
+@@ -970,6 +977,10 @@ static int m41t80_probe(struct i2c_client *client,
+ 		return PTR_ERR(rtc);
+ 
+ 	m41t80_data->rtc = rtc;
++	if (client->irq <= 0) {
++		/* We cannot support UIE mode if we do not have an IRQ line */
++		rtc->uie_unsupported = 1;
++	}
+ 
+ 	/* Make sure HT (Halt Update) bit is cleared */
+ 	rc = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_HOUR);

commit def7ac806a9ac035abf0e7573ccc8bbfd38e163c
+Author: Gabriel Somlo 
+Date:   Tue Mar 8 13:30:50 2016 -0500
+
+    firmware: qemu_fw_cfg.c: hold ACPI global lock during device access
+    
+    Allowing for the future possibility of implementing AML-based
+    (i.e., firmware-triggered) access to the QEMU fw_cfg device,
+    acquire the global ACPI lock when accessing the device on behalf
+    of the guest-side sysfs driver, to prevent any potential race
+    conditions.
+    
+    Suggested-by: Michael S. Tsirkin 
+    Signed-off-by: Gabriel Somlo 
+    Signed-off-by: Michael S. Tsirkin 
+
+diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
+index e4c471413d46..815c4a5cae54 100644
+--- a/drivers/firmware/qemu_fw_cfg.c
++++ b/drivers/firmware/qemu_fw_cfg.c
+@@ -77,12 +77,28 @@ static inline u16 fw_cfg_sel_endianness(u16 key)
+ static inline void fw_cfg_read_blob(u16 key,
+ 				    void *buf, loff_t pos, size_t count)
+ {
++	u32 glk;
++	acpi_status status;
++
++	/* If we have ACPI, ensure mutual exclusion against any potential
++	 * device access by the firmware, e.g. via AML methods:
++	 */
++	status = acpi_acquire_global_lock(ACPI_WAIT_FOREVER, &glk);
++	if (ACPI_FAILURE(status) && status != AE_NOT_CONFIGURED) {
++		/* Should never get here */
++		WARN(1, "fw_cfg_read_blob: Failed to lock ACPI!\n");
++		memset(buf, 0, count);
++		return;
++	}
++
+ 	mutex_lock(&fw_cfg_dev_lock);
+ 	iowrite16(fw_cfg_sel_endianness(key), fw_cfg_reg_ctrl);
+ 	while (pos-- > 0)
+ 		ioread8(fw_cfg_reg_data);
+ 	ioread8_rep(fw_cfg_reg_data, buf, count);
+ 	mutex_unlock(&fw_cfg_dev_lock);
++
++	acpi_release_global_lock(glk);
+ }
+ 
+ /* clean up fw_cfg device i/o */

commit 00411b7b1e3ec477b75bb83ccd417c7609832db6
+Author: Gabriel Somlo 
+Date:   Mon Feb 22 16:18:18 2016 -0500
+
+    firmware: fw_cfg register offsets on supported architectures only
+    
+    Refrain from defining default fw_cfg register offsets on
+    unsupported architectures -- throw an error instead. If
+    QEMU were to add fw_cfg support on additional architectures,
+    we should add them to the FW_CFG_SYSFS depends statement in
+    drivers/firmware/Kconfig, and provide default values for
+    register offsets in drivers/firmware/qemu_fw_cfg.c at that
+    time.
+    
+    Suggested-by: Michael S. Tsirkin 
+    Signed-off-by: Gabriel Somlo 
+    Acked-by: Michael S. Tsirkin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
+index fedbff55a7f3..7bba76c0206c 100644
+--- a/drivers/firmware/qemu_fw_cfg.c
++++ b/drivers/firmware/qemu_fw_cfg.c
+@@ -109,9 +109,7 @@ static void fw_cfg_io_cleanup(void)
+ #  define FW_CFG_CTRL_OFF 0x00
+ #  define FW_CFG_DATA_OFF 0x01
+ # else
+-#  warning "QEMU FW_CFG may not be available on this architecture!"
+-#  define FW_CFG_CTRL_OFF 0x00
+-#  define FW_CFG_DATA_OFF 0x01
++#  error "QEMU FW_CFG not available on this architecture!"
+ # endif
+ #endif
+ 

commit 92aed5d6ba90c2031c8d321a02e7af3d4cb05b8d
+Author: Gabriel Somlo 
+Date:   Thu Jan 28 09:23:14 2016 -0500
+
+    devicetree: update documentation for fw_cfg ARM bindings
+    
+    Remove fw_cfg hardware interface details from
+    Documentation/devicetree/bindings/arm/fw-cfg.txt,
+    and replace them with a pointer to the authoritative
+    documentation in the QEMU source tree.
+    
+    Signed-off-by: Gabriel Somlo 
+    Cc: Laszlo Ersek 
+    Acked-by: Rob Herring 
+    Reviewed-by: Laszlo Ersek 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/devicetree/bindings/arm/fw-cfg.txt b/Documentation/devicetree/bindings/arm/fw-cfg.txt
+index 953fb640d9c4..fd54e1db2156 100644
+--- a/Documentation/devicetree/bindings/arm/fw-cfg.txt
++++ b/Documentation/devicetree/bindings/arm/fw-cfg.txt
+@@ -11,43 +11,9 @@ QEMU exposes the control and data register to ARM guests as memory mapped
+ registers; their location is communicated to the guest's UEFI firmware in the
+ DTB that QEMU places at the bottom of the guest's DRAM.
+ 
+-The guest writes a selector value (a key) to the selector register, and then
+-can read the corresponding data (produced by QEMU) via the data register. If
+-the selected entry is writable, the guest can rewrite it through the data
+-register.
++The authoritative guest-side hardware interface documentation to the fw_cfg
++device can be found in "docs/specs/fw_cfg.txt" in the QEMU source tree.
+ 
+-The selector register takes keys in big endian byte order.
+-
+-The data register allows accesses with 8, 16, 32 and 64-bit width (only at
+-offset 0 of the register). Accesses larger than a byte are interpreted as
+-arrays, bundled together only for better performance. The bytes constituting
+-such a word, in increasing address order, correspond to the bytes that would
+-have been transferred by byte-wide accesses in chronological order.
+-
+-The interface allows guest firmware to download various parameters and blobs
+-that affect how the firmware works and what tables it installs for the guest
+-OS. For example, boot order of devices, ACPI tables, SMBIOS tables, kernel and
+-initrd images for direct kernel booting, virtual machine UUID, SMP information,
+-virtual NUMA topology, and so on.
+-
+-The authoritative registry of the valid selector values and their meanings is
+-the QEMU source code; the structure of the data blobs corresponding to the
+-individual key values is also defined in the QEMU source code.
+-
+-The presence of the registers can be verified by selecting the "signature" blob
+-with key 0x0000, and reading four bytes from the data register. The returned
+-signature is "QEMU".
+-
+-The outermost protocol (involving the write / read sequences of the control and
+-data registers) is expected to be versioned, and/or described by feature bits.
+-The interface revision / feature bitmap can be retrieved with key 0x0001. The
+-blob to be read from the data register has size 4, and it is to be interpreted
+-as a uint32_t value in little endian byte order. The current value
+-(corresponding to the above outer protocol) is zero.
+-
+-The guest kernel is not expected to use these registers (although it is
+-certainly allowed to); the device tree bindings are documented here because
+-this is where device tree bindings reside in general.
+ 
+ Required properties:
+ 

commit 246c46ebaeaef17814dc5a8830d16e7f1b01116b
+Author: Gabriel Somlo 
+Date:   Thu Jan 28 09:23:13 2016 -0500
+
+    firmware: create directory hierarchy for sysfs fw_cfg entries
+    
+    Each fw_cfg entry of type "file" has an associated 56-char,
+    nul-terminated ASCII string which represents its name. While
+    the fw_cfg device doesn't itself impose any specific naming
+    convention, QEMU developers have traditionally used path name
+    semantics (i.e. "etc/acpi/rsdp") to descriptively name the
+    various fw_cfg "blobs" passed into the guest.
+    
+    This patch attempts, on a best effort basis, to create a
+    directory hierarchy representing the content of fw_cfg file
+    names, under /sys/firmware/qemu_fw_cfg/by_name.
+    
+    Upon successful creation of all directories representing the
+    "dirname" portion of a fw_cfg file, a symlink will be created
+    to represent the "basename", pointing at the appropriate
+    /sys/firmware/qemu_fw_cfg/by_key entry. If a file name is not
+    suitable for this procedure (e.g., if its basename or dirname
+    components collide with an already existing dirname component
+    or basename, respectively) the corresponding fw_cfg blob is
+    skipped and will remain available in sysfs only by its selector
+    key value.
+    
+    Signed-off-by: Gabriel Somlo 
+    Cc: Andy Lutomirski 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/ABI/testing/sysfs-firmware-qemu_fw_cfg b/Documentation/ABI/testing/sysfs-firmware-qemu_fw_cfg
+index e9e58d4ea60a..011dda4f8e8a 100644
+--- a/Documentation/ABI/testing/sysfs-firmware-qemu_fw_cfg
++++ b/Documentation/ABI/testing/sysfs-firmware-qemu_fw_cfg
+@@ -56,3 +56,45 @@ Description:
+ 			  entry via the control register, and reading a number
+ 			  of bytes equal to the blob size from the data
+ 			  register.
++
++		--- Listing fw_cfg blobs by file name ---
++
++		While the fw_cfg device does not impose any specific naming
++		convention on the blobs registered in the file directory,
++		QEMU developers have traditionally used path name semantics
++		to give each blob a descriptive name. For example:
++
++			"bootorder"
++			"genroms/kvmvapic.bin"
++			"etc/e820"
++			"etc/boot-fail-wait"
++			"etc/system-states"
++			"etc/table-loader"
++			"etc/acpi/rsdp"
++			"etc/acpi/tables"
++			"etc/smbios/smbios-tables"
++			"etc/smbios/smbios-anchor"
++			...
++
++		In addition to the listing by unique selector key described
++		above, the fw_cfg sysfs driver also attempts to build a tree
++		of directories matching the path name components of fw_cfg
++		blob names, ending in symlinks to the by_key entry for each
++		"basename", as illustrated below (assume current directory is
++		/sys/firmware):
++
++		    qemu_fw_cfg/by_name/bootorder -> ../by_key/38
++		    qemu_fw_cfg/by_name/etc/e820 -> ../../by_key/35
++		    qemu_fw_cfg/by_name/etc/acpi/rsdp -> ../../../by_key/41
++		    ...
++
++		Construction of the directory tree and symlinks is done on a
++		"best-effort" basis, as there is no guarantee that components
++		of fw_cfg blob names are always "well behaved". I.e., there is
++		the possibility that a symlink (basename) will conflict with
++		a dirname component of another fw_cfg blob, in which case the
++		creation of the offending /sys/firmware/qemu_fw_cfg/by_name
++		entry will be skipped.
++
++		The authoritative list of entries will continue to be found
++		under the /sys/firmware/qemu_fw_cfg/by_key directory.
+diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
+index 83e8a5c8f887..19f6851be87f 100644
+--- a/drivers/firmware/qemu_fw_cfg.c
++++ b/drivers/firmware/qemu_fw_cfg.c
+@@ -334,9 +334,103 @@ static struct bin_attribute fw_cfg_sysfs_attr_raw = {
+ 	.read = fw_cfg_sysfs_read_raw,
+ };
+ 
+-/* kobjects representing top-level and by_key folders */
++/*
++ * Create a kset subdirectory matching each '/' delimited dirname token
++ * in 'name', starting with sysfs kset/folder 'dir'; At the end, create
++ * a symlink directed at the given 'target'.
++ * NOTE: We do this on a best-effort basis, since 'name' is not guaranteed
++ * to be a well-behaved path name. Whenever a symlink vs. kset directory
++ * name collision occurs, the kernel will issue big scary warnings while
++ * refusing to add the offending link or directory. We follow up with our
++ * own, slightly less scary error messages explaining the situation :)
++ */
++static int fw_cfg_build_symlink(struct kset *dir,
++				struct kobject *target, const char *name)
++{
++	int ret;
++	struct kset *subdir;
++	struct kobject *ko;
++	char *name_copy, *p, *tok;
++
++	if (!dir || !target || !name || !*name)
++		return -EINVAL;
++
++	/* clone a copy of name for parsing */
++	name_copy = p = kstrdup(name, GFP_KERNEL);
++	if (!name_copy)
++		return -ENOMEM;
++
++	/* create folders for each dirname token, then symlink for basename */
++	while ((tok = strsep(&p, "/")) && *tok) {
++
++		/* last (basename) token? If so, add symlink here */
++		if (!p || !*p) {
++			ret = sysfs_create_link(&dir->kobj, target, tok);
++			break;
++		}
++
++		/* does the current dir contain an item named after tok ? */
++		ko = kset_find_obj(dir, tok);
++		if (ko) {
++			/* drop reference added by kset_find_obj */
++			kobject_put(ko);
++
++			/* ko MUST be a kset - we're about to use it as one ! */
++			if (ko->ktype != dir->kobj.ktype) {
++				ret = -EINVAL;
++				break;
++			}
++
++			/* descend into already existing subdirectory */
++			dir = to_kset(ko);
++		} else {
++			/* create new subdirectory kset */
++			subdir = kzalloc(sizeof(struct kset), GFP_KERNEL);
++			if (!subdir) {
++				ret = -ENOMEM;
++				break;
++			}
++			subdir->kobj.kset = dir;
++			subdir->kobj.ktype = dir->kobj.ktype;
++			ret = kobject_set_name(&subdir->kobj, "%s", tok);
++			if (ret) {
++				kfree(subdir);
++				break;
++			}
++			ret = kset_register(subdir);
++			if (ret) {
++				kfree(subdir);
++				break;
++			}
++
++			/* descend into newly created subdirectory */
++			dir = subdir;
++		}
++	}
++
++	/* we're done with cloned copy of name */
++	kfree(name_copy);
++	return ret;
++}
++
++/* recursively unregister fw_cfg/by_name/ kset directory tree */
++static void fw_cfg_kset_unregister_recursive(struct kset *kset)
++{
++	struct kobject *k, *next;
++
++	list_for_each_entry_safe(k, next, &kset->list, entry)
++		/* all set members are ksets too, but check just in case... */
++		if (k->ktype == kset->kobj.ktype)
++			fw_cfg_kset_unregister_recursive(to_kset(k));
++
++	/* symlinks are cleanly and automatically removed with the directory */
++	kset_unregister(kset);
++}
++
++/* kobjects & kset representing top-level, by_key, and by_name folders */
+ static struct kobject *fw_cfg_top_ko;
+ static struct kobject *fw_cfg_sel_ko;
++static struct kset *fw_cfg_fname_kset;
+ 
+ /* register an individual fw_cfg file */
+ static int fw_cfg_register_file(const struct fw_cfg_file *f)
+@@ -363,6 +457,9 @@ static int fw_cfg_register_file(const struct fw_cfg_file *f)
+ 	if (err)
+ 		goto err_add_raw;
+ 
++	/* try adding "/sys/firmware/qemu_fw_cfg/by_name/" symlink */
++	fw_cfg_build_symlink(fw_cfg_fname_kset, &entry->kobj, entry->f.name);
++
+ 	/* success, add entry to global cache */
+ 	fw_cfg_sysfs_cache_enlist(entry);
+ 	return 0;
+@@ -417,18 +514,21 @@ static int fw_cfg_sysfs_probe(struct platform_device *pdev)
+ 
+ 	/* NOTE: If we supported multiple fw_cfg devices, we'd first create
+ 	 * a subdirectory named after e.g. pdev->id, then hang per-device
+-	 * by_key subdirectories underneath it. However, only
++	 * by_key (and by_name) subdirectories underneath it. However, only
+ 	 * one fw_cfg device exist system-wide, so if one was already found
+ 	 * earlier, we might as well stop here.
+ 	 */
+ 	if (fw_cfg_sel_ko)
+ 		return -EBUSY;
+ 
+-	/* create by_key subdirectory of /sys/firmware/qemu_fw_cfg/ */
++	/* create by_key and by_name subdirs of /sys/firmware/qemu_fw_cfg/ */
+ 	err = -ENOMEM;
+ 	fw_cfg_sel_ko = kobject_create_and_add("by_key", fw_cfg_top_ko);
+ 	if (!fw_cfg_sel_ko)
+ 		goto err_sel;
++	fw_cfg_fname_kset = kset_create_and_add("by_name", NULL, fw_cfg_top_ko);
++	if (!fw_cfg_fname_kset)
++		goto err_name;
+ 
+ 	/* initialize fw_cfg device i/o from platform data */
+ 	err = fw_cfg_do_platform_probe(pdev);
+@@ -457,6 +557,8 @@ static int fw_cfg_sysfs_probe(struct platform_device *pdev)
+ err_rev:
+ 	fw_cfg_io_cleanup();
+ err_probe:
++	fw_cfg_kset_unregister_recursive(fw_cfg_fname_kset);
++err_name:
+ 	fw_cfg_kobj_cleanup(fw_cfg_sel_ko);
+ err_sel:
+ 	return err;
+@@ -466,6 +568,7 @@ static int fw_cfg_sysfs_remove(struct platform_device *pdev)
+ {
+ 	pr_debug("fw_cfg: unloading.\n");
+ 	fw_cfg_sysfs_cache_cleanup();
++	fw_cfg_kset_unregister_recursive(fw_cfg_fname_kset);
+ 	fw_cfg_kobj_cleanup(fw_cfg_sel_ko);
+ 	fw_cfg_io_cleanup();
+ 	return 0;

commit 75f3e8e47f381074801d0034874d20c638d9e3d9
+Author: Gabriel Somlo 
+Date:   Thu Jan 28 09:23:11 2016 -0500
+
+    firmware: introduce sysfs driver for QEMU's fw_cfg device
+    
+    Make fw_cfg entries of type "file" available via sysfs. Entries
+    are listed under /sys/firmware/qemu_fw_cfg/by_key, in folders
+    named after each entry's selector key. Filename, selector value,
+    and size read-only attributes are included for each entry. Also,
+    a "raw" attribute allows retrieval of the full binary content of
+    each entry.
+    
+    The fw_cfg device can be instantiated automatically from ACPI or
+    the Device Tree, or manually by using a kernel module (or command
+    line) parameter, with a syntax outlined in the documentation file.
+    
+    Signed-off-by: Gabriel Somlo 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/ABI/testing/sysfs-firmware-qemu_fw_cfg b/Documentation/ABI/testing/sysfs-firmware-qemu_fw_cfg
+new file mode 100644
+index 000000000000..e9e58d4ea60a
+--- /dev/null
++++ b/Documentation/ABI/testing/sysfs-firmware-qemu_fw_cfg
+@@ -0,0 +1,58 @@
++What:		/sys/firmware/qemu_fw_cfg/
++Date:		August 2015
++Contact:	Gabriel Somlo 
++Description:
++		Several different architectures supported by QEMU (x86, arm,
++		sun4*, ppc/mac) are provisioned with a firmware configuration
++		(fw_cfg) device, originally intended as a way for the host to
++		provide configuration data to the guest firmware. Starting
++		with QEMU v2.4, arbitrary fw_cfg file entries may be specified
++		by the user on the command line, which makes fw_cfg additionally
++		useful as an out-of-band, asynchronous mechanism for providing
++		configuration data to the guest userspace.
++
++		The authoritative guest-side hardware interface documentation
++		to the fw_cfg device can be found in "docs/specs/fw_cfg.txt"
++		in the QEMU source tree.
++
++		=== SysFS fw_cfg Interface ===
++
++		The fw_cfg sysfs interface described in this document is only
++		intended to display discoverable blobs (i.e., those registered
++		with the file directory), as there is no way to determine the
++		presence or size of "legacy" blobs (with selector keys between
++		0x0002 and 0x0018) programmatically.
++
++		All fw_cfg information is shown under:
++
++			/sys/firmware/qemu_fw_cfg/
++
++		The only legacy blob displayed is the fw_cfg device revision:
++
++			/sys/firmware/qemu_fw_cfg/rev
++
++		--- Discoverable fw_cfg blobs by selector key ---
++
++		All discoverable blobs listed in the fw_cfg file directory are
++		displayed as entries named after their unique selector key
++		value, e.g.:
++
++			/sys/firmware/qemu_fw_cfg/by_key/32
++			/sys/firmware/qemu_fw_cfg/by_key/33
++			/sys/firmware/qemu_fw_cfg/by_key/34
++			...
++
++		Each such fw_cfg sysfs entry has the following values exported
++		as attributes:
++
++		name  	: The 56-byte nul-terminated ASCII string used as the
++			  blob's 'file name' in the fw_cfg directory.
++		size  	: The length of the blob, as given in the fw_cfg
++			  directory.
++		key	: The value of the blob's selector key as given in the
++			  fw_cfg directory. This value is the same as used in
++			  the parent directory name.
++		raw	: The raw bytes of the blob, obtained by selecting the
++			  entry via the control register, and reading a number
++			  of bytes equal to the blob size from the data
++			  register.
+diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
+index 49a3a1185bb6..5130f74ae3bd 100644
+--- a/drivers/firmware/Kconfig
++++ b/drivers/firmware/Kconfig
+@@ -161,6 +161,25 @@ config RASPBERRYPI_FIRMWARE
+ 	  This option enables support for communicating with the firmware on the
+ 	  Raspberry Pi.
+ 
++config FW_CFG_SYSFS
++	tristate "QEMU fw_cfg device support in sysfs"
++	depends on SYSFS && (ARM || ARM64 || PPC_PMAC || SPARC || X86)
++	default n
++	help
++	  Say Y or M here to enable the exporting of the QEMU firmware
++	  configuration (fw_cfg) file entries via sysfs. Entries are
++	  found under /sys/firmware/fw_cfg when this option is enabled
++	  and loaded.
++
++config FW_CFG_SYSFS_CMDLINE
++	bool "QEMU fw_cfg device parameter parsing"
++	depends on FW_CFG_SYSFS
++	help
++	  Allow the qemu_fw_cfg device to be initialized via the kernel
++	  command line or using a module parameter.
++	  WARNING: Using incorrect parameters (base address in particular)
++	  may crash your system.
++
+ config QCOM_SCM
+ 	bool
+ 	depends on ARM || ARM64
+diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
+index 48dd4175297e..474bada56fcd 100644
+--- a/drivers/firmware/Makefile
++++ b/drivers/firmware/Makefile
+@@ -14,6 +14,7 @@ obj-$(CONFIG_ISCSI_IBFT_FIND)	+= iscsi_ibft_find.o
+ obj-$(CONFIG_ISCSI_IBFT)	+= iscsi_ibft.o
+ obj-$(CONFIG_FIRMWARE_MEMMAP)	+= memmap.o
+ obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o
++obj-$(CONFIG_FW_CFG_SYSFS)	+= qemu_fw_cfg.o
+ obj-$(CONFIG_QCOM_SCM)		+= qcom_scm.o
+ obj-$(CONFIG_QCOM_SCM_64)	+= qcom_scm-64.o
+ obj-$(CONFIG_QCOM_SCM_32)	+= qcom_scm-32.o
+diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
+new file mode 100644
+index 000000000000..83e8a5c8f887
+--- /dev/null
++++ b/drivers/firmware/qemu_fw_cfg.c
+@@ -0,0 +1,648 @@
++/*
++ * drivers/firmware/qemu_fw_cfg.c
++ *
++ * Copyright 2015 Carnegie Mellon University
++ *
++ * Expose entries from QEMU's firmware configuration (fw_cfg) device in
++ * sysfs (read-only, under "/sys/firmware/qemu_fw_cfg/...").
++ *
++ * The fw_cfg device may be instantiated via either an ACPI node (on x86
++ * and select subsets of aarch64), a Device Tree node (on arm), or using
++ * a kernel module (or command line) parameter with the following syntax:
++ *
++ *      [fw_cfg.]ioport=@[::]
++ * or
++ *      [fw_cfg.]mmio=@[::]
++ *
++ * where:
++ *           := size of ioport or mmio range
++ *           := physical base address of ioport or mmio range
++ *       := (optional) offset of control register
++ *       := (optional) offset of data register
++ *
++ * e.g.:
++ *      fw_cfg.ioport=2@0x510:0:1		(the default on x86)
++ * or
++ *      fw_cfg.mmio=0xA@0x9020000:8:0		(the default on arm)
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++MODULE_AUTHOR("Gabriel L. Somlo ");
++MODULE_DESCRIPTION("QEMU fw_cfg sysfs support");
++MODULE_LICENSE("GPL");
++
++/* selector key values for "well-known" fw_cfg entries */
++#define FW_CFG_SIGNATURE  0x00
++#define FW_CFG_ID         0x01
++#define FW_CFG_FILE_DIR   0x19
++
++/* size in bytes of fw_cfg signature */
++#define FW_CFG_SIG_SIZE 4
++
++/* fw_cfg "file name" is up to 56 characters (including terminating nul) */
++#define FW_CFG_MAX_FILE_PATH 56
++
++/* fw_cfg file directory entry type */
++struct fw_cfg_file {
++	u32 size;
++	u16 select;
++	u16 reserved;
++	char name[FW_CFG_MAX_FILE_PATH];
++};
++
++/* fw_cfg device i/o register addresses */
++static bool fw_cfg_is_mmio;
++static phys_addr_t fw_cfg_p_base;
++static resource_size_t fw_cfg_p_size;
++static void __iomem *fw_cfg_dev_base;
++static void __iomem *fw_cfg_reg_ctrl;
++static void __iomem *fw_cfg_reg_data;
++
++/* atomic access to fw_cfg device (potentially slow i/o, so using mutex) */
++static DEFINE_MUTEX(fw_cfg_dev_lock);
++
++/* pick appropriate endianness for selector key */
++static inline u16 fw_cfg_sel_endianness(u16 key)
++{
++	return fw_cfg_is_mmio ? cpu_to_be16(key) : cpu_to_le16(key);
++}
++
++/* read chunk of given fw_cfg blob (caller responsible for sanity-check) */
++static inline void fw_cfg_read_blob(u16 key,
++				    void *buf, loff_t pos, size_t count)
++{
++	mutex_lock(&fw_cfg_dev_lock);
++	iowrite16(fw_cfg_sel_endianness(key), fw_cfg_reg_ctrl);
++	while (pos-- > 0)
++		ioread8(fw_cfg_reg_data);
++	ioread8_rep(fw_cfg_reg_data, buf, count);
++	mutex_unlock(&fw_cfg_dev_lock);
++}
++
++/* clean up fw_cfg device i/o */
++static void fw_cfg_io_cleanup(void)
++{
++	if (fw_cfg_is_mmio) {
++		iounmap(fw_cfg_dev_base);
++		release_mem_region(fw_cfg_p_base, fw_cfg_p_size);
++	} else {
++		ioport_unmap(fw_cfg_dev_base);
++		release_region(fw_cfg_p_base, fw_cfg_p_size);
++	}
++}
++
++/* arch-specific ctrl & data register offsets are not available in ACPI, DT */
++#if !(defined(FW_CFG_CTRL_OFF) && defined(FW_CTRL_DATA_OFF))
++# if (defined(CONFIG_ARM) || defined(CONFIG_ARM64))
++#  define FW_CFG_CTRL_OFF 0x08
++#  define FW_CFG_DATA_OFF 0x00
++# elif (defined(CONFIG_PPC_PMAC) || defined(CONFIG_SPARC32)) /* ppc/mac,sun4m */
++#  define FW_CFG_CTRL_OFF 0x00
++#  define FW_CFG_DATA_OFF 0x02
++# elif (defined(CONFIG_X86) || defined(CONFIG_SPARC64)) /* x86, sun4u */
++#  define FW_CFG_CTRL_OFF 0x00
++#  define FW_CFG_DATA_OFF 0x01
++# else
++#  warning "QEMU FW_CFG may not be available on this architecture!"
++#  define FW_CFG_CTRL_OFF 0x00
++#  define FW_CFG_DATA_OFF 0x01
++# endif
++#endif
++
++/* initialize fw_cfg device i/o from platform data */
++static int fw_cfg_do_platform_probe(struct platform_device *pdev)
++{
++	char sig[FW_CFG_SIG_SIZE];
++	struct resource *range, *ctrl, *data;
++
++	/* acquire i/o range details */
++	fw_cfg_is_mmio = false;
++	range = platform_get_resource(pdev, IORESOURCE_IO, 0);
++	if (!range) {
++		fw_cfg_is_mmio = true;
++		range = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++		if (!range)
++			return -EINVAL;
++	}
++	fw_cfg_p_base = range->start;
++	fw_cfg_p_size = resource_size(range);
++
++	if (fw_cfg_is_mmio) {
++		if (!request_mem_region(fw_cfg_p_base,
++					fw_cfg_p_size, "fw_cfg_mem"))
++			return -EBUSY;
++		fw_cfg_dev_base = ioremap(fw_cfg_p_base, fw_cfg_p_size);
++		if (!fw_cfg_dev_base) {
++			release_mem_region(fw_cfg_p_base, fw_cfg_p_size);
++			return -EFAULT;
++		}
++	} else {
++		if (!request_region(fw_cfg_p_base,
++				    fw_cfg_p_size, "fw_cfg_io"))
++			return -EBUSY;
++		fw_cfg_dev_base = ioport_map(fw_cfg_p_base, fw_cfg_p_size);
++		if (!fw_cfg_dev_base) {
++			release_region(fw_cfg_p_base, fw_cfg_p_size);
++			return -EFAULT;
++		}
++	}
++
++	/* were custom register offsets provided (e.g. on the command line)? */
++	ctrl = platform_get_resource_byname(pdev, IORESOURCE_REG, "ctrl");
++	data = platform_get_resource_byname(pdev, IORESOURCE_REG, "data");
++	if (ctrl && data) {
++		fw_cfg_reg_ctrl = fw_cfg_dev_base + ctrl->start;
++		fw_cfg_reg_data = fw_cfg_dev_base + data->start;
++	} else {
++		/* use architecture-specific offsets */
++		fw_cfg_reg_ctrl = fw_cfg_dev_base + FW_CFG_CTRL_OFF;
++		fw_cfg_reg_data = fw_cfg_dev_base + FW_CFG_DATA_OFF;
++	}
++
++	/* verify fw_cfg device signature */
++	fw_cfg_read_blob(FW_CFG_SIGNATURE, sig, 0, FW_CFG_SIG_SIZE);
++	if (memcmp(sig, "QEMU", FW_CFG_SIG_SIZE) != 0) {
++		fw_cfg_io_cleanup();
++		return -ENODEV;
++	}
++
++	return 0;
++}
++
++/* fw_cfg revision attribute, in /sys/firmware/qemu_fw_cfg top-level dir. */
++static u32 fw_cfg_rev;
++
++static ssize_t fw_cfg_showrev(struct kobject *k, struct attribute *a, char *buf)
++{
++	return sprintf(buf, "%u\n", fw_cfg_rev);
++}
++
++static const struct {
++	struct attribute attr;
++	ssize_t (*show)(struct kobject *k, struct attribute *a, char *buf);
++} fw_cfg_rev_attr = {
++	.attr = { .name = "rev", .mode = S_IRUSR },
++	.show = fw_cfg_showrev,
++};
++
++/* fw_cfg_sysfs_entry type */
++struct fw_cfg_sysfs_entry {
++	struct kobject kobj;
++	struct fw_cfg_file f;
++	struct list_head list;
++};
++
++/* get fw_cfg_sysfs_entry from kobject member */
++static inline struct fw_cfg_sysfs_entry *to_entry(struct kobject *kobj)
++{
++	return container_of(kobj, struct fw_cfg_sysfs_entry, kobj);
++}
++
++/* fw_cfg_sysfs_attribute type */
++struct fw_cfg_sysfs_attribute {
++	struct attribute attr;
++	ssize_t (*show)(struct fw_cfg_sysfs_entry *entry, char *buf);
++};
++
++/* get fw_cfg_sysfs_attribute from attribute member */
++static inline struct fw_cfg_sysfs_attribute *to_attr(struct attribute *attr)
++{
++	return container_of(attr, struct fw_cfg_sysfs_attribute, attr);
++}
++
++/* global cache of fw_cfg_sysfs_entry objects */
++static LIST_HEAD(fw_cfg_entry_cache);
++
++/* kobjects removed lazily by kernel, mutual exclusion needed */
++static DEFINE_SPINLOCK(fw_cfg_cache_lock);
++
++static inline void fw_cfg_sysfs_cache_enlist(struct fw_cfg_sysfs_entry *entry)
++{
++	spin_lock(&fw_cfg_cache_lock);
++	list_add_tail(&entry->list, &fw_cfg_entry_cache);
++	spin_unlock(&fw_cfg_cache_lock);
++}
++
++static inline void fw_cfg_sysfs_cache_delist(struct fw_cfg_sysfs_entry *entry)
++{
++	spin_lock(&fw_cfg_cache_lock);
++	list_del(&entry->list);
++	spin_unlock(&fw_cfg_cache_lock);
++}
++
++static void fw_cfg_sysfs_cache_cleanup(void)
++{
++	struct fw_cfg_sysfs_entry *entry, *next;
++
++	list_for_each_entry_safe(entry, next, &fw_cfg_entry_cache, list) {
++		/* will end up invoking fw_cfg_sysfs_cache_delist()
++		 * via each object's release() method (i.e. destructor)
++		 */
++		kobject_put(&entry->kobj);
++	}
++}
++
++/* default_attrs: per-entry attributes and show methods */
++
++#define FW_CFG_SYSFS_ATTR(_attr) \
++struct fw_cfg_sysfs_attribute fw_cfg_sysfs_attr_##_attr = { \
++	.attr = { .name = __stringify(_attr), .mode = S_IRUSR }, \
++	.show = fw_cfg_sysfs_show_##_attr, \
++}
++
++static ssize_t fw_cfg_sysfs_show_size(struct fw_cfg_sysfs_entry *e, char *buf)
++{
++	return sprintf(buf, "%u\n", e->f.size);
++}
++
++static ssize_t fw_cfg_sysfs_show_key(struct fw_cfg_sysfs_entry *e, char *buf)
++{
++	return sprintf(buf, "%u\n", e->f.select);
++}
++
++static ssize_t fw_cfg_sysfs_show_name(struct fw_cfg_sysfs_entry *e, char *buf)
++{
++	return sprintf(buf, "%s\n", e->f.name);
++}
++
++static FW_CFG_SYSFS_ATTR(size);
++static FW_CFG_SYSFS_ATTR(key);
++static FW_CFG_SYSFS_ATTR(name);
++
++static struct attribute *fw_cfg_sysfs_entry_attrs[] = {
++	&fw_cfg_sysfs_attr_size.attr,
++	&fw_cfg_sysfs_attr_key.attr,
++	&fw_cfg_sysfs_attr_name.attr,
++	NULL,
++};
++
++/* sysfs_ops: find fw_cfg_[entry, attribute] and call appropriate show method */
++static ssize_t fw_cfg_sysfs_attr_show(struct kobject *kobj, struct attribute *a,
++				      char *buf)
++{
++	struct fw_cfg_sysfs_entry *entry = to_entry(kobj);
++	struct fw_cfg_sysfs_attribute *attr = to_attr(a);
++
++	return attr->show(entry, buf);
++}
++
++static const struct sysfs_ops fw_cfg_sysfs_attr_ops = {
++	.show = fw_cfg_sysfs_attr_show,
++};
++
++/* release: destructor, to be called via kobject_put() */
++static void fw_cfg_sysfs_release_entry(struct kobject *kobj)
++{
++	struct fw_cfg_sysfs_entry *entry = to_entry(kobj);
++
++	fw_cfg_sysfs_cache_delist(entry);
++	kfree(entry);
++}
++
++/* kobj_type: ties together all properties required to register an entry */
++static struct kobj_type fw_cfg_sysfs_entry_ktype = {
++	.default_attrs = fw_cfg_sysfs_entry_attrs,
++	.sysfs_ops = &fw_cfg_sysfs_attr_ops,
++	.release = fw_cfg_sysfs_release_entry,
++};
++
++/* raw-read method and attribute */
++static ssize_t fw_cfg_sysfs_read_raw(struct file *filp, struct kobject *kobj,
++				     struct bin_attribute *bin_attr,
++				     char *buf, loff_t pos, size_t count)
++{
++	struct fw_cfg_sysfs_entry *entry = to_entry(kobj);
++
++	if (pos > entry->f.size)
++		return -EINVAL;
++
++	if (count > entry->f.size - pos)
++		count = entry->f.size - pos;
++
++	fw_cfg_read_blob(entry->f.select, buf, pos, count);
++	return count;
++}
++
++static struct bin_attribute fw_cfg_sysfs_attr_raw = {
++	.attr = { .name = "raw", .mode = S_IRUSR },
++	.read = fw_cfg_sysfs_read_raw,
++};
++
++/* kobjects representing top-level and by_key folders */
++static struct kobject *fw_cfg_top_ko;
++static struct kobject *fw_cfg_sel_ko;
++
++/* register an individual fw_cfg file */
++static int fw_cfg_register_file(const struct fw_cfg_file *f)
++{
++	int err;
++	struct fw_cfg_sysfs_entry *entry;
++
++	/* allocate new entry */
++	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
++	if (!entry)
++		return -ENOMEM;
++
++	/* set file entry information */
++	memcpy(&entry->f, f, sizeof(struct fw_cfg_file));
++
++	/* register entry under "/sys/firmware/qemu_fw_cfg/by_key/" */
++	err = kobject_init_and_add(&entry->kobj, &fw_cfg_sysfs_entry_ktype,
++				   fw_cfg_sel_ko, "%d", entry->f.select);
++	if (err)
++		goto err_register;
++
++	/* add raw binary content access */
++	err = sysfs_create_bin_file(&entry->kobj, &fw_cfg_sysfs_attr_raw);
++	if (err)
++		goto err_add_raw;
++
++	/* success, add entry to global cache */
++	fw_cfg_sysfs_cache_enlist(entry);
++	return 0;
++
++err_add_raw:
++	kobject_del(&entry->kobj);
++err_register:
++	kfree(entry);
++	return err;
++}
++
++/* iterate over all fw_cfg directory entries, registering each one */
++static int fw_cfg_register_dir_entries(void)
++{
++	int ret = 0;
++	u32 count, i;
++	struct fw_cfg_file *dir;
++	size_t dir_size;
++
++	fw_cfg_read_blob(FW_CFG_FILE_DIR, &count, 0, sizeof(count));
++	count = be32_to_cpu(count);
++	dir_size = count * sizeof(struct fw_cfg_file);
++
++	dir = kmalloc(dir_size, GFP_KERNEL);
++	if (!dir)
++		return -ENOMEM;
++
++	fw_cfg_read_blob(FW_CFG_FILE_DIR, dir, sizeof(count), dir_size);
++
++	for (i = 0; i < count; i++) {
++		dir[i].size = be32_to_cpu(dir[i].size);
++		dir[i].select = be16_to_cpu(dir[i].select);
++		ret = fw_cfg_register_file(&dir[i]);
++		if (ret)
++			break;
++	}
++
++	kfree(dir);
++	return ret;
++}
++
++/* unregister top-level or by_key folder */
++static inline void fw_cfg_kobj_cleanup(struct kobject *kobj)
++{
++	kobject_del(kobj);
++	kobject_put(kobj);
++}
++
++static int fw_cfg_sysfs_probe(struct platform_device *pdev)
++{
++	int err;
++
++	/* NOTE: If we supported multiple fw_cfg devices, we'd first create
++	 * a subdirectory named after e.g. pdev->id, then hang per-device
++	 * by_key subdirectories underneath it. However, only
++	 * one fw_cfg device exist system-wide, so if one was already found
++	 * earlier, we might as well stop here.
++	 */
++	if (fw_cfg_sel_ko)
++		return -EBUSY;
++
++	/* create by_key subdirectory of /sys/firmware/qemu_fw_cfg/ */
++	err = -ENOMEM;
++	fw_cfg_sel_ko = kobject_create_and_add("by_key", fw_cfg_top_ko);
++	if (!fw_cfg_sel_ko)
++		goto err_sel;
++
++	/* initialize fw_cfg device i/o from platform data */
++	err = fw_cfg_do_platform_probe(pdev);
++	if (err)
++		goto err_probe;
++
++	/* get revision number, add matching top-level attribute */
++	fw_cfg_read_blob(FW_CFG_ID, &fw_cfg_rev, 0, sizeof(fw_cfg_rev));
++	fw_cfg_rev = le32_to_cpu(fw_cfg_rev);
++	err = sysfs_create_file(fw_cfg_top_ko, &fw_cfg_rev_attr.attr);
++	if (err)
++		goto err_rev;
++
++	/* process fw_cfg file directory entry, registering each file */
++	err = fw_cfg_register_dir_entries();
++	if (err)
++		goto err_dir;
++
++	/* success */
++	pr_debug("fw_cfg: loaded.\n");
++	return 0;
++
++err_dir:
++	fw_cfg_sysfs_cache_cleanup();
++	sysfs_remove_file(fw_cfg_top_ko, &fw_cfg_rev_attr.attr);
++err_rev:
++	fw_cfg_io_cleanup();
++err_probe:
++	fw_cfg_kobj_cleanup(fw_cfg_sel_ko);
++err_sel:
++	return err;
++}
++
++static int fw_cfg_sysfs_remove(struct platform_device *pdev)
++{
++	pr_debug("fw_cfg: unloading.\n");
++	fw_cfg_sysfs_cache_cleanup();
++	fw_cfg_kobj_cleanup(fw_cfg_sel_ko);
++	fw_cfg_io_cleanup();
++	return 0;
++}
++
++static const struct of_device_id fw_cfg_sysfs_mmio_match[] = {
++	{ .compatible = "qemu,fw-cfg-mmio", },
++	{},
++};
++MODULE_DEVICE_TABLE(of, fw_cfg_sysfs_mmio_match);
++
++#ifdef CONFIG_ACPI
++static const struct acpi_device_id fw_cfg_sysfs_acpi_match[] = {
++	{ "QEMU0002", },
++	{},
++};
++MODULE_DEVICE_TABLE(acpi, fw_cfg_sysfs_acpi_match);
++#endif
++
++static struct platform_driver fw_cfg_sysfs_driver = {
++	.probe = fw_cfg_sysfs_probe,
++	.remove = fw_cfg_sysfs_remove,
++	.driver = {
++		.name = "fw_cfg",
++		.of_match_table = fw_cfg_sysfs_mmio_match,
++		.acpi_match_table = ACPI_PTR(fw_cfg_sysfs_acpi_match),
++	},
++};
++
++#ifdef CONFIG_FW_CFG_SYSFS_CMDLINE
++
++static struct platform_device *fw_cfg_cmdline_dev;
++
++/* this probably belongs in e.g. include/linux/types.h,
++ * but right now we are the only ones doing it...
++ */
++#ifdef CONFIG_PHYS_ADDR_T_64BIT
++#define __PHYS_ADDR_PREFIX "ll"
++#else
++#define __PHYS_ADDR_PREFIX ""
++#endif
++
++/* use special scanf/printf modifier for phys_addr_t, resource_size_t */
++#define PH_ADDR_SCAN_FMT "@%" __PHYS_ADDR_PREFIX "i%n" \
++			 ":%" __PHYS_ADDR_PREFIX "i" \
++			 ":%" __PHYS_ADDR_PREFIX "i%n"
++
++#define PH_ADDR_PR_1_FMT "0x%" __PHYS_ADDR_PREFIX "x@" \
++			 "0x%" __PHYS_ADDR_PREFIX "x"
++
++#define PH_ADDR_PR_3_FMT PH_ADDR_PR_1_FMT \
++			 ":%" __PHYS_ADDR_PREFIX "u" \
++			 ":%" __PHYS_ADDR_PREFIX "u"
++
++static int fw_cfg_cmdline_set(const char *arg, const struct kernel_param *kp)
++{
++	struct resource res[3] = {};
++	char *str;
++	phys_addr_t base;
++	resource_size_t size, ctrl_off, data_off;
++	int processed, consumed = 0;
++
++	/* only one fw_cfg device can exist system-wide, so if one
++	 * was processed on the command line already, we might as
++	 * well stop here.
++	 */
++	if (fw_cfg_cmdline_dev) {
++		/* avoid leaking previously registered device */
++		platform_device_unregister(fw_cfg_cmdline_dev);
++		return -EINVAL;
++	}
++
++	/* consume "" portion of command line argument */
++	size = memparse(arg, &str);
++
++	/* get "@[::]" chunks */
++	processed = sscanf(str, PH_ADDR_SCAN_FMT,
++			   &base, &consumed,
++			   &ctrl_off, &data_off, &consumed);
++
++	/* sscanf() must process precisely 1 or 3 chunks:
++	 *  is mandatory, optionally followed by 
++	 * and ;
++	 * there must be no extra characters after the last chunk,
++	 * so str[consumed] must be '\0'.
++	 */
++	if (str[consumed] ||
++	    (processed != 1 && processed != 3))
++		return -EINVAL;
++
++	res[0].start = base;
++	res[0].end = base + size - 1;
++	res[0].flags = !strcmp(kp->name, "mmio") ? IORESOURCE_MEM :
++						   IORESOURCE_IO;
++
++	/* insert register offsets, if provided */
++	if (processed > 1) {
++		res[1].name = "ctrl";
++		res[1].start = ctrl_off;
++		res[1].flags = IORESOURCE_REG;
++		res[2].name = "data";
++		res[2].start = data_off;
++		res[2].flags = IORESOURCE_REG;
++	}
++
++	/* "processed" happens to nicely match the number of resources
++	 * we need to pass in to this platform device.
++	 */
++	fw_cfg_cmdline_dev = platform_device_register_simple("fw_cfg",
++					PLATFORM_DEVID_NONE, res, processed);
++	if (IS_ERR(fw_cfg_cmdline_dev))
++		return PTR_ERR(fw_cfg_cmdline_dev);
++
++	return 0;
++}
++
++static int fw_cfg_cmdline_get(char *buf, const struct kernel_param *kp)
++{
++	/* stay silent if device was not configured via the command
++	 * line, or if the parameter name (ioport/mmio) doesn't match
++	 * the device setting
++	 */
++	if (!fw_cfg_cmdline_dev ||
++	    (!strcmp(kp->name, "mmio") ^
++	     (fw_cfg_cmdline_dev->resource[0].flags == IORESOURCE_MEM)))
++		return 0;
++
++	switch (fw_cfg_cmdline_dev->num_resources) {
++	case 1:
++		return snprintf(buf, PAGE_SIZE, PH_ADDR_PR_1_FMT,
++				resource_size(&fw_cfg_cmdline_dev->resource[0]),
++				fw_cfg_cmdline_dev->resource[0].start);
++	case 3:
++		return snprintf(buf, PAGE_SIZE, PH_ADDR_PR_3_FMT,
++				resource_size(&fw_cfg_cmdline_dev->resource[0]),
++				fw_cfg_cmdline_dev->resource[0].start,
++				fw_cfg_cmdline_dev->resource[1].start,
++				fw_cfg_cmdline_dev->resource[2].start);
++	}
++
++	/* Should never get here */
++	WARN(1, "Unexpected number of resources: %d\n",
++		fw_cfg_cmdline_dev->num_resources);
++	return 0;
++}
++
++static const struct kernel_param_ops fw_cfg_cmdline_param_ops = {
++	.set = fw_cfg_cmdline_set,
++	.get = fw_cfg_cmdline_get,
++};
++
++device_param_cb(ioport, &fw_cfg_cmdline_param_ops, NULL, S_IRUSR);
++device_param_cb(mmio, &fw_cfg_cmdline_param_ops, NULL, S_IRUSR);
++
++#endif /* CONFIG_FW_CFG_SYSFS_CMDLINE */
++
++static int __init fw_cfg_sysfs_init(void)
++{
++	/* create /sys/firmware/qemu_fw_cfg/ top level directory */
++	fw_cfg_top_ko = kobject_create_and_add("qemu_fw_cfg", firmware_kobj);
++	if (!fw_cfg_top_ko)
++		return -ENOMEM;
++
++	return platform_driver_register(&fw_cfg_sysfs_driver);
++}
++
++static void __exit fw_cfg_sysfs_exit(void)
++{
++	platform_driver_unregister(&fw_cfg_sysfs_driver);
++
++#ifdef CONFIG_FW_CFG_SYSFS_CMDLINE
++	platform_device_unregister(fw_cfg_cmdline_dev);
++#endif
++
++	/* clean up /sys/firmware/qemu_fw_cfg/ */
++	fw_cfg_kobj_cleanup(fw_cfg_top_ko);
++}
++
++module_init(fw_cfg_sysfs_init);
++module_exit(fw_cfg_sysfs_exit);

commit 2fe829aca9d7bed5fd6b49c6a1452e5e486b6cc3
+Author: Gabriel Somlo 
+Date:   Thu Jan 28 09:23:12 2016 -0500
+
+    kobject: export kset_find_obj() for module use
+    
+    Signed-off-by: Gabriel Somlo 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/lib/kobject.c b/lib/kobject.c
+index 7cbccd2b4c72..445dcaeb0f56 100644
+--- a/lib/kobject.c
++++ b/lib/kobject.c
+@@ -861,6 +861,7 @@ struct kobject *kset_find_obj(struct kset *kset, const char *name)
+ 	spin_unlock(&kset->list_lock);
+ 	return ret;
+ }
++EXPORT_SYMBOL_GPL(kset_find_obj);
+ 
+ static void kset_release(struct kobject *kobj)
+ {

commit fa40ae34441286b2cb595468ef781e24573e9e7d
+Author: Gabriel Somlo 
+Date:   Mon Aug 10 15:51:43 2015 -0400
+
+    kobject: move EXPORT_SYMBOL() macros next to corresponding definitions
+    
+    Move EXPORT_SYMBOL() macros in kobject.c from the end of the file
+    next to the function definitions to which they belong.
+    
+    Signed-off-by: Gabriel Somlo 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/lib/kobject.c b/lib/kobject.c
+index 3e3a5c3cb330..055407746266 100644
+--- a/lib/kobject.c
++++ b/lib/kobject.c
+@@ -568,6 +568,7 @@ void kobject_del(struct kobject *kobj)
+ 	kobject_put(kobj->parent);
+ 	kobj->parent = NULL;
+ }
++EXPORT_SYMBOL(kobject_del);
+ 
+ /**
+  * kobject_get - increment refcount for object.
+@@ -584,6 +585,7 @@ struct kobject *kobject_get(struct kobject *kobj)
+ 	}
+ 	return kobj;
+ }
++EXPORT_SYMBOL(kobject_get);
+ 
+ static struct kobject * __must_check kobject_get_unless_zero(struct kobject *kobj)
+ {
+@@ -675,6 +677,7 @@ void kobject_put(struct kobject *kobj)
+ 		kref_put(&kobj->kref, kobject_release);
+ 	}
+ }
++EXPORT_SYMBOL(kobject_put);
+ 
+ static void dynamic_kobj_release(struct kobject *kobj)
+ {
+@@ -803,6 +806,7 @@ int kset_register(struct kset *k)
+ 	kobject_uevent(&k->kobj, KOBJ_ADD);
+ 	return 0;
+ }
++EXPORT_SYMBOL(kset_register);
+ 
+ /**
+  * kset_unregister - remove a kset.
+@@ -815,6 +819,7 @@ void kset_unregister(struct kset *k)
+ 	kobject_del(&k->kobj);
+ 	kobject_put(&k->kobj);
+ }
++EXPORT_SYMBOL(kset_unregister);
+ 
+ /**
+  * kset_find_obj - search for object in kset.
+@@ -1051,10 +1056,3 @@ void kobj_ns_drop(enum kobj_ns_type type, void *ns)
+ 		kobj_ns_ops_tbl[type]->drop_ns(ns);
+ 	spin_unlock(&kobj_ns_type_lock);
+ }
+-
+-EXPORT_SYMBOL(kobject_get);
+-EXPORT_SYMBOL(kobject_put);
+-EXPORT_SYMBOL(kobject_del);
+-
+-EXPORT_SYMBOL(kset_register);
+-EXPORT_SYMBOL(kset_unregister);

commit 9c15364f83201802e995cbf72d833e5e1b3b9adb
+Author: Eric Cooper 
+Date:   Wed Feb 2 17:16:11 2011 -0500
+
+    [ARM] Kirkwood: enable PCIe for kexec
+    
+    Use the machine-specific kexec_reinit hook to make sure
+    PCIe is enabled before starting a new kernel.
+    
+    Signed-off-by: Eric Cooper 
+    Signed-off-by: Nicolas Pitre 
+
+diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
+index 3688123b5ad8..966df630b76f 100644
+--- a/arch/arm/mach-kirkwood/common.c
++++ b/arch/arm/mach-kirkwood/common.c
+@@ -21,6 +21,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -1003,6 +1004,10 @@ void __init kirkwood_init(void)
+ 	kirkwood_xor0_init();
+ 	kirkwood_xor1_init();
+ 	kirkwood_crypto_init();
++
++#ifdef CONFIG_KEXEC 
++	kexec_reinit = kirkwood_enable_pcie;
++#endif
+ }
+ 
+ static int __init kirkwood_clock_gate(void)

commit 0e0cdd37709ba7ac9f0bff5de1b22f1b7987b04c
+Author: Eric Cooper 
+Date:   Wed Feb 2 17:16:10 2011 -0500
+
+    [ARM] Kirkwood: enable PCIe before reading device ID register
+    
+    PCIe may have been disabled (by kirkwood_clock_gate)
+    if this kernel was started by kexec.  Make sure PCIe
+    is enabled before attempting to access the device ID
+    register, otherwise the system will hang.
+    
+    Signed-off-by: Eric Cooper 
+    Signed-off-by: Nicolas Pitre 
+
+diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h
+index 95bb0a73adfb..a35b86235772 100644
+--- a/arch/arm/mach-kirkwood/common.h
++++ b/arch/arm/mach-kirkwood/common.h
+@@ -32,6 +32,7 @@ void kirkwood_init_irq(void);
+ extern struct mbus_dram_target_info kirkwood_mbus_dram_info;
+ void kirkwood_setup_cpu_mbus(void);
+ 
++void kirkwood_enable_pcie(void);
+ void kirkwood_pcie_id(u32 *dev, u32 *rev);
+ 
+ void kirkwood_ehci_init(void);
+diff --git a/arch/arm/mach-kirkwood/pcie.c b/arch/arm/mach-kirkwood/pcie.c
+index 513ad3102d7c..ca294ff6d5be 100644
+--- a/arch/arm/mach-kirkwood/pcie.c
++++ b/arch/arm/mach-kirkwood/pcie.c
+@@ -18,8 +18,16 @@
+ #include 
+ #include "common.h"
+ 
++void kirkwood_enable_pcie(void)
++{
++	u32 curr = readl(CLOCK_GATING_CTRL);
++	if (!(curr & CGC_PEX0))
++		writel(curr | CGC_PEX0, CLOCK_GATING_CTRL);
++}
++
+ void __init kirkwood_pcie_id(u32 *dev, u32 *rev)
+ {
++	kirkwood_enable_pcie();
+ 	*dev = orion_pcie_dev_id((void __iomem *)PCIE_VIRT_BASE);
+ 	*rev = orion_pcie_rev((void __iomem *)PCIE_VIRT_BASE);
+ }

commit 868d172b8ac23070418ec6265195e88e8d5dbe92
+Author: Eric Cooper 
+Date:   Wed Feb 2 17:16:09 2011 -0500
+
+    [ARM] add machine-specific hook to machine_kexec
+    
+    Provide the option to call a machine-specific function
+    before kexec'ing a new kernel.
+    
+    Signed-off-by: Eric Cooper 
+    Signed-off-by: Nicolas Pitre 
+
+diff --git a/arch/arm/include/asm/kexec.h b/arch/arm/include/asm/kexec.h
+index c0094d8edae4..c2b9b4bdec00 100644
+--- a/arch/arm/include/asm/kexec.h
++++ b/arch/arm/include/asm/kexec.h
+@@ -50,6 +50,9 @@ static inline void crash_setup_regs(struct pt_regs *newregs,
+ 	}
+ }
+ 
++/* Function pointer to optional machine-specific reinitialization */
++extern void (*kexec_reinit)(void);
++
+ #endif /* __ASSEMBLY__ */
+ 
+ #endif /* CONFIG_KEXEC */
+diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
+index 30ead135ff5f..e59bbd496c39 100644
+--- a/arch/arm/kernel/machine_kexec.c
++++ b/arch/arm/kernel/machine_kexec.c
+@@ -75,6 +75,11 @@ void machine_crash_shutdown(struct pt_regs *regs)
+ 	printk(KERN_INFO "Loading crashdump kernel...\n");
+ }
+ 
++/*
++ * Function pointer to optional machine-specific reinitialization
++ */
++void (*kexec_reinit)(void);
++
+ void machine_kexec(struct kimage *image)
+ {
+ 	unsigned long page_list;
+@@ -104,6 +109,8 @@ void machine_kexec(struct kimage *image)
+ 			   (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);
+ 	printk(KERN_INFO "Bye!\n");
+ 
++	if (kexec_reinit)
++		kexec_reinit();
+ 	local_irq_disable();
+ 	local_fiq_disable();
+ 	setup_mm_for_reboot(0); /* mode is not used, so just pass 0*/

commit 709406494c0ed7da843bad624f6b16f9a2df4a6c
+Author: Eric Cooper 
+Date:   Wed Sep 15 10:49:41 2010 -0400
+
+    [ARM] Kirkwood: support for Seagate DockStar
+    
+    This patch adds support for the Seagate FreeAgent DockStar,
+    a Marvell SheevaPlug variant.
+    
+    Signed-off-by: Eric Cooper 
+    Signed-off-by: Nicolas Pitre 
+
+diff --git a/arch/arm/configs/kirkwood_defconfig b/arch/arm/configs/kirkwood_defconfig
+index ccc9c9959b82..2f7042813765 100644
+--- a/arch/arm/configs/kirkwood_defconfig
++++ b/arch/arm/configs/kirkwood_defconfig
+@@ -15,6 +15,7 @@ CONFIG_MACH_MV88F6281GTW_GE=y
+ CONFIG_MACH_SHEEVAPLUG=y
+ CONFIG_MACH_ESATA_SHEEVAPLUG=y
+ CONFIG_MACH_GURUPLUG=y
++CONFIG_MACH_DOCKSTAR=y
+ CONFIG_MACH_TS219=y
+ CONFIG_MACH_TS41X=y
+ CONFIG_MACH_OPENRD_BASE=y
+diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig
+index cc25501b57fa..3d5d66e7aaa0 100644
+--- a/arch/arm/mach-kirkwood/Kconfig
++++ b/arch/arm/mach-kirkwood/Kconfig
+@@ -58,6 +58,12 @@ config MACH_TS41X
+ 	  QNAP TS-410, TS-410U, TS-419P and TS-419U Turbo NAS
+ 	  devices.
+ 
++config MACH_DOCKSTAR
++	bool "Seagate FreeAgent DockStar"
++	help
++	  Say 'Y' here if you want your kernel to support the
++	  Seagate FreeAgent DockStar.
++
+ config MACH_OPENRD
+         bool
+ 
+diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile
+index 295d7baa6ae1..9e43e953226e 100644
+--- a/arch/arm/mach-kirkwood/Makefile
++++ b/arch/arm/mach-kirkwood/Makefile
+@@ -7,6 +7,7 @@ obj-$(CONFIG_MACH_MV88F6281GTW_GE)	+= mv88f6281gtw_ge-setup.o
+ obj-$(CONFIG_MACH_SHEEVAPLUG)		+= sheevaplug-setup.o
+ obj-$(CONFIG_MACH_ESATA_SHEEVAPLUG)	+= sheevaplug-setup.o
+ obj-$(CONFIG_MACH_GURUPLUG)		+= guruplug-setup.o
++obj-$(CONFIG_MACH_DOCKSTAR)		+= dockstar-setup.o
+ obj-$(CONFIG_MACH_TS219)		+= ts219-setup.o tsx1x-common.o
+ obj-$(CONFIG_MACH_TS41X)		+= ts41x-setup.o tsx1x-common.o
+ obj-$(CONFIG_MACH_OPENRD)		+= openrd-setup.o
+diff --git a/arch/arm/mach-kirkwood/dockstar-setup.c b/arch/arm/mach-kirkwood/dockstar-setup.c
+new file mode 100644
+index 000000000000..a90475d5059c
+--- /dev/null
++++ b/arch/arm/mach-kirkwood/dockstar-setup.c
+@@ -0,0 +1,112 @@
++/*
++ * arch/arm/mach-kirkwood/dockstar-setup.c
++ *
++ * Seagate FreeAgent DockStar Setup
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2.  This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include "common.h"
++#include "mpp.h"
++
++static struct mtd_partition dockstar_nand_parts[] = {
++	{
++		.name = "u-boot",
++		.offset = 0,
++		.size = SZ_1M
++	}, {
++		.name = "uImage",
++		.offset = MTDPART_OFS_NXTBLK,
++		.size = SZ_4M
++	}, {
++		.name = "root",
++		.offset = MTDPART_OFS_NXTBLK,
++		.size = MTDPART_SIZ_FULL
++	},
++};
++
++static struct mv643xx_eth_platform_data dockstar_ge00_data = {
++	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
++};
++
++static struct gpio_led dockstar_led_pins[] = {
++	{
++		.name			= "dockstar:green:health",
++		.default_trigger	= "default-on",
++		.gpio			= 46,
++		.active_low		= 1,
++	},
++	{
++		.name			= "dockstar:orange:misc",
++		.default_trigger	= "none",
++		.gpio			= 47,
++		.active_low		= 1,
++	},
++};
++
++static struct gpio_led_platform_data dockstar_led_data = {
++	.leds		= dockstar_led_pins,
++	.num_leds	= ARRAY_SIZE(dockstar_led_pins),
++};
++
++static struct platform_device dockstar_leds = {
++	.name	= "leds-gpio",
++	.id	= -1,
++	.dev	= {
++		.platform_data	= &dockstar_led_data,
++	}
++};
++
++static unsigned int dockstar_mpp_config[] __initdata = {
++	MPP29_GPIO,	/* USB Power Enable */
++	MPP46_GPIO,	/* LED green */
++	MPP47_GPIO,	/* LED orange */
++	0
++};
++
++static void __init dockstar_init(void)
++{
++	/*
++	 * Basic setup. Needs to be called early.
++	 */
++	kirkwood_init();
++
++	/* setup gpio pin select */
++	kirkwood_mpp_conf(dockstar_mpp_config);
++
++	kirkwood_uart0_init();
++	kirkwood_nand_init(ARRAY_AND_SIZE(dockstar_nand_parts), 25);
++
++	if (gpio_request(29, "USB Power Enable") != 0 ||
++	    gpio_direction_output(29, 1) != 0)
++		printk(KERN_ERR "can't set up GPIO 29 (USB Power Enable)\n");
++	kirkwood_ehci_init();
++
++	kirkwood_ge00_init(&dockstar_ge00_data);
++
++	platform_device_register(&dockstar_leds);
++}
++
++MACHINE_START(DOCKSTAR, "Seagate FreeAgent DockStar")
++	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
++	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
++	.boot_params	= 0x00000100,
++	.init_machine	= dockstar_init,
++	.map_io		= kirkwood_map_io,
++	.init_irq	= kirkwood_init_irq,
++	.timer		= &kirkwood_timer,
++MACHINE_END

commit 096486eece7ef38cf1ee46b704482c75c4010fb1
+Author: Nik A. Melchior 
+Date:   Mon Jun 21 12:47:05 2010 +0800
+
+    ACPI video: fix string mismatch for Sony SR290 laptop
+    
+    Fix string mismatch for Sony SR290 laptop.
+    https://bugzilla.kernel.org/show_bug.cgi?id=12904#c45
+    
+    Signed-off-by: Nik A. Melchior 
+    Signed-off-by: Len Brown 
+
+diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
+index 01381be05e96..2bb28b9d91c4 100644
+--- a/drivers/acpi/blacklist.c
++++ b/drivers/acpi/blacklist.c
+@@ -214,7 +214,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
+ 	.ident = "Sony VGN-SR290J",
+ 	.matches = {
+ 		     DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+-		     DMI_MATCH(DMI_PRODUCT_NAME, "Sony VGN-SR290J"),
++		     DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR290J"),
+ 		},
+ 	},
+ 	{

commit e59f87966adef2cb03d419530e3ade5159487d6d
+Author: Eric Cooper 
+Date:   Thu Mar 13 12:55:46 2008 +0100
+
+    eeepc-laptop: add base driver
+    
+    This patch is based on Eric Cooper's work to clean the original asus_acpi
+    given by Asus.  It's a platform driver (/sys/devices/platform/eeepc/)
+    wich support:
+         - hotkeys - wlan on/off - camera on/off - cardr on/off
+    
+    Signed-off-by: Corentin Chary 
+    Signed-off-by: Len Brown 
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index c1dd1ae7b133..37debda36661 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -1531,6 +1531,13 @@ L:	bluesmoke-devel@lists.sourceforge.net
+ W:	bluesmoke.sourceforge.net
+ S:	Maintained
+ 
++EEEPC LAPTOP EXTRAS DRIVER
++P:	Corentin Chary
++M:	corentincj@iksaif.net
++L:	acpi4asus-user@lists.sourceforge.net
++W:	http://sourceforge.net/projects/acpi4asus
++S:	Maintained
++
+ EEPRO100 NETWORK DRIVER
+ P:	Andrey V. Savochkin
+ M:	saw@saw.sw.com.sg
+diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
+index 297a48f85446..2264127afac7 100644
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -351,6 +351,17 @@ config INTEL_MENLOW
+ 
+ 	  If unsure, say N.
+ 
++config EEEPC_LAPTOP
++	tristate "Eee PC Hotkey Driver (EXPERIMENTAL)"
++	depends on X86
++	depends on ACPI
++	depends on EXPERIMENTAL
++	---help---
++	  This driver supports the Fn-Fx keys on Eee PC laptops.
++	  It also adds the ability to switch camera/wlan on/off.
++
++	  If you have an Eee PC laptop, say Y or M here.
++
+ config ENCLOSURE_SERVICES
+ 	tristate "Enclosure Services"
+ 	default n
+diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
+index 5914da434854..1952875a272e 100644
+--- a/drivers/misc/Makefile
++++ b/drivers/misc/Makefile
+@@ -7,7 +7,8 @@ obj-$(CONFIG_IBM_ASM)		+= ibmasm/
+ obj-$(CONFIG_HDPU_FEATURES)	+= hdpuftrs/
+ obj-$(CONFIG_MSI_LAPTOP)     += msi-laptop.o
+ obj-$(CONFIG_ACER_WMI)     += acer-wmi.o
+-obj-$(CONFIG_ASUS_LAPTOP)     += asus-laptop.o
++obj-$(CONFIG_ASUS_LAPTOP)	+= asus-laptop.o
++obj-$(CONFIG_EEEPC_LAPTOP)	+= eeepc-laptop.o
+ obj-$(CONFIG_ATMEL_PWM)		+= atmel_pwm.o
+ obj-$(CONFIG_ATMEL_SSC)		+= atmel-ssc.o
+ obj-$(CONFIG_ATMEL_TCLIB)	+= atmel_tclib.o
+diff --git a/drivers/misc/eeepc-laptop.c b/drivers/misc/eeepc-laptop.c
+new file mode 100644
+index 000000000000..e34ff97530cd
+--- /dev/null
++++ b/drivers/misc/eeepc-laptop.c
+@@ -0,0 +1,442 @@
++/*
++ *  eepc-laptop.c - Asus Eee PC extras
++ *
++ *  Based on asus_acpi.c as patched for the Eee PC by Asus:
++ *  ftp://ftp.asus.com/pub/ASUS/EeePC/701/ASUS_ACPI_071126.rar
++ *  Based on eee.c from eeepc-linux
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#define EEEPC_LAPTOP_VERSION	"0.1"
++
++#define EEEPC_HOTK_NAME		"Eee PC Hotkey Driver"
++#define EEEPC_HOTK_FILE		"eeepc"
++#define EEEPC_HOTK_CLASS	"hotkey"
++#define EEEPC_HOTK_DEVICE_NAME	"Hotkey"
++#define EEEPC_HOTK_HID		"ASUS010"
++
++#define EEEPC_LOG	EEEPC_HOTK_FILE ": "
++#define EEEPC_ERR	KERN_ERR	EEEPC_LOG
++#define EEEPC_WARNING	KERN_WARNING	EEEPC_LOG
++#define EEEPC_NOTICE	KERN_NOTICE	EEEPC_LOG
++#define EEEPC_INFO	KERN_INFO	EEEPC_LOG
++
++/*
++ * Definitions for Asus EeePC
++ */
++#define	NOTIFY_WLAN_ON	0x10
++
++enum {
++	DISABLE_ASL_WLAN = 0x0001,
++	DISABLE_ASL_BLUETOOTH = 0x0002,
++	DISABLE_ASL_IRDA = 0x0004,
++	DISABLE_ASL_CAMERA = 0x0008,
++	DISABLE_ASL_TV = 0x0010,
++	DISABLE_ASL_GPS = 0x0020,
++	DISABLE_ASL_DISPLAYSWITCH = 0x0040,
++	DISABLE_ASL_MODEM = 0x0080,
++	DISABLE_ASL_CARDREADER = 0x0100
++};
++
++enum {
++	CM_ASL_WLAN = 0,
++	CM_ASL_BLUETOOTH,
++	CM_ASL_IRDA,
++	CM_ASL_1394,
++	CM_ASL_CAMERA,
++	CM_ASL_TV,
++	CM_ASL_GPS,
++	CM_ASL_DVDROM,
++	CM_ASL_DISPLAYSWITCH,
++	CM_ASL_PANELBRIGHT,
++	CM_ASL_BIOSFLASH,
++	CM_ASL_ACPIFLASH,
++	CM_ASL_CPUFV,
++	CM_ASL_CPUTEMPERATURE,
++	CM_ASL_FANCPU,
++	CM_ASL_FANCHASSIS,
++	CM_ASL_USBPORT1,
++	CM_ASL_USBPORT2,
++	CM_ASL_USBPORT3,
++	CM_ASL_MODEM,
++	CM_ASL_CARDREADER,
++	CM_ASL_LID
++};
++
++const char *cm_getv[] = {
++	"WLDG", NULL, NULL, NULL,
++	"CAMG", NULL, NULL, NULL,
++	NULL, "PBLG", NULL, NULL,
++	"CFVG", NULL, NULL, NULL,
++	"USBG", NULL, NULL, "MODG",
++	"CRDG", "LIDG"
++};
++
++const char *cm_setv[] = {
++	"WLDS", NULL, NULL, NULL,
++	"CAMS", NULL, NULL, NULL,
++	"SDSP", "PBLS", "HDPS", NULL,
++	"CFVS", NULL, NULL, NULL,
++	"USBG", NULL, NULL, "MODS",
++	"CRDS", NULL
++};
++
++/*
++ * This is the main structure, we can use it to store useful information
++ * about the hotk device
++ */
++struct eeepc_hotk {
++	struct acpi_device *device;	/* the device we are in */
++	acpi_handle handle;		/* the handle of the hotk device */
++	u32 cm_supported;		/* the control methods supported
++					   by this BIOS */
++	uint init_flag;			/* Init flags */
++	u16 event_count[128];		/* count for each event */
++};
++
++/* The actual device the driver binds to */
++static struct eeepc_hotk *ehotk;
++
++/* Platform device/driver */
++static struct platform_driver platform_driver = {
++	.driver = {
++		.name = EEEPC_HOTK_FILE,
++		.owner = THIS_MODULE,
++	}
++};
++
++static struct platform_device *platform_device;
++
++/*
++ * The hotkey driver declaration
++ */
++static int eeepc_hotk_add(struct acpi_device *device);
++static int eeepc_hotk_remove(struct acpi_device *device, int type);
++
++static const struct acpi_device_id eeepc_device_ids[] = {
++	{EEEPC_HOTK_HID, 0},
++	{"", 0},
++};
++MODULE_DEVICE_TABLE(acpi, eeepc_device_ids);
++
++static struct acpi_driver eeepc_hotk_driver = {
++	.name = EEEPC_HOTK_NAME,
++	.class = EEEPC_HOTK_CLASS,
++	.ids = eeepc_device_ids,
++	.ops = {
++		.add = eeepc_hotk_add,
++		.remove = eeepc_hotk_remove,
++	},
++};
++
++MODULE_AUTHOR("Corentin Chary, Eric Cooper");
++MODULE_DESCRIPTION(EEEPC_HOTK_NAME);
++MODULE_LICENSE("GPL");
++
++/*
++ * ACPI Helpers
++ */
++static int write_acpi_int(acpi_handle handle, const char *method, int val,
++			  struct acpi_buffer *output)
++{
++	struct acpi_object_list params;
++	union acpi_object in_obj;
++	acpi_status status;
++
++	params.count = 1;
++	params.pointer = &in_obj;
++	in_obj.type = ACPI_TYPE_INTEGER;
++	in_obj.integer.value = val;
++
++	status = acpi_evaluate_object(handle, (char *)method, ¶ms, output);
++	return (status == AE_OK ? 0 : -1);
++}
++
++static int read_acpi_int(acpi_handle handle, const char *method, int *val)
++{
++	acpi_status status;
++	ulong result;
++
++	status = acpi_evaluate_integer(handle, (char *)method, NULL, &result);
++	if (ACPI_FAILURE(status)) {
++		*val = -1;
++		return -1;
++	} else {
++		*val = result;
++		return 0;
++	}
++}
++
++static int set_acpi(int cm, int value)
++{
++	if (ehotk->cm_supported & (0x1 << cm)) {
++		const char *method = cm_setv[cm];
++		if (method == NULL)
++			return -ENODEV;
++		if (write_acpi_int(ehotk->handle, method, value, NULL))
++			printk(EEEPC_WARNING "Error writing %s\n", method);
++	}
++	return 0;
++}
++
++static int get_acpi(int cm)
++{
++	int value = -1;
++	if ((ehotk->cm_supported & (0x1 << cm))) {
++		const char *method = cm_getv[cm];
++		if (method == NULL)
++			return -ENODEV;
++		if (read_acpi_int(ehotk->handle, method, &value))
++			printk(EEEPC_WARNING "Error reading %s\n", method);
++	}
++	return value;
++}
++
++/*
++ * Sys helpers
++ */
++static int parse_arg(const char *buf, unsigned long count, int *val)
++{
++	if (!count)
++		return 0;
++	if (sscanf(buf, "%i", val) != 1)
++		return -EINVAL;
++	return count;
++}
++
++static ssize_t store_sys_acpi(int cm, const char *buf, size_t count)
++{
++	int rv, value;
++
++	rv = parse_arg(buf, count, &value);
++	if (rv > 0)
++		set_acpi(cm, value);
++	return rv;
++}
++
++static ssize_t show_sys_acpi(int cm, char *buf)
++{
++	return sprintf(buf, "%d\n", get_acpi(cm));
++}
++
++#define EEEPC_CREATE_DEVICE_ATTR(_name, _cm)				\
++	static ssize_t show_##_name(struct device *dev,			\
++				    struct device_attribute *attr,	\
++				    char *buf)				\
++	{								\
++		return show_sys_acpi(_cm, buf);				\
++	}								\
++	static ssize_t store_##_name(struct device *dev,		\
++				     struct device_attribute *attr,	\
++				     const char *buf, size_t count)	\
++	{								\
++		return store_sys_acpi(_cm, buf, count);			\
++	}								\
++	static struct device_attribute dev_attr_##_name = {		\
++		.attr = {						\
++			.name = __stringify(_name),			\
++			.mode = 0644 },					\
++		.show   = show_##_name,					\
++		.store  = store_##_name,				\
++	}
++
++EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA);
++EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER);
++EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH);
++EEEPC_CREATE_DEVICE_ATTR(wlan, CM_ASL_WLAN);
++
++static struct attribute *platform_attributes[] = {
++	&dev_attr_camera.attr,
++	&dev_attr_cardr.attr,
++	&dev_attr_disp.attr,
++	&dev_attr_wlan.attr,
++	NULL
++};
++
++static struct attribute_group platform_attribute_group = {
++	.attrs = platform_attributes
++};
++
++/*
++ * Hotkey functions
++ */
++static int eeepc_hotk_check(void)
++{
++	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
++	int result;
++
++	result = acpi_bus_get_status(ehotk->device);
++	if (result)
++		return result;
++	if (ehotk->device->status.present) {
++		if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag,
++				    &buffer)) {
++			printk(EEEPC_ERR "Hotkey initialization failed\n");
++			return -ENODEV;
++		} else {
++			printk(EEEPC_NOTICE "Hotkey init flags 0x%x\n",
++			       ehotk->init_flag);
++		}
++		/* get control methods supported */
++		if (read_acpi_int(ehotk->handle, "CMSG"
++				   , &ehotk->cm_supported)) {
++			printk(EEEPC_ERR
++			       "Get control methods supported failed\n");
++			return -ENODEV;
++		} else {
++			printk(EEEPC_INFO
++			       "Get control methods supported: 0x%x\n",
++			       ehotk->cm_supported);
++		}
++	} else {
++		printk(EEEPC_ERR "Hotkey device not present, aborting\n");
++		return -EINVAL;
++	}
++	return 0;
++}
++
++static void notify_wlan(u32 *event)
++{
++	/* if DISABLE_ASL_WLAN is set, the notify code for fn+f2
++	   will always be 0x10 */
++	if (ehotk->cm_supported & (0x1 << CM_ASL_WLAN)) {
++		const char *method = cm_getv[CM_ASL_WLAN];
++		int value;
++		if (read_acpi_int(ehotk->handle, method, &value))
++			printk(EEEPC_WARNING "Error reading %s\n",
++			       method);
++		else if (value == 1)
++			*event = 0x11;
++	}
++}
++
++static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
++{
++	if (!ehotk)
++		return;
++	if (event == NOTIFY_WLAN_ON && (DISABLE_ASL_WLAN & ehotk->init_flag))
++		notify_wlan(&event);
++	acpi_bus_generate_proc_event(ehotk->device, event,
++				     ehotk->event_count[event % 128]++);
++}
++
++static int eeepc_hotk_add(struct acpi_device *device)
++{
++	acpi_status status = AE_OK;
++	int result;
++
++	if (!device)
++		 return -EINVAL;
++	printk(EEEPC_NOTICE EEEPC_HOTK_NAME "\n");
++	ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL);
++	if (!ehotk)
++		return -ENOMEM;
++	ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
++	ehotk->handle = device->handle;
++	strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME);
++	strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS);
++	acpi_driver_data(device) = ehotk;
++	ehotk->device = device;
++	result = eeepc_hotk_check();
++	if (result)
++		goto end;
++	status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY,
++					     eeepc_hotk_notify, ehotk);
++	if (ACPI_FAILURE(status))
++		printk(EEEPC_ERR "Error installing notify handler\n");
++ end:
++	if (result) {
++		kfree(ehotk);
++		ehotk = NULL;
++	}
++	return result;
++}
++
++static int eeepc_hotk_remove(struct acpi_device *device, int type)
++{
++	acpi_status status = 0;
++
++	if (!device || !acpi_driver_data(device))
++		 return -EINVAL;
++	status = acpi_remove_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY,
++					    eeepc_hotk_notify);
++	if (ACPI_FAILURE(status))
++		printk(EEEPC_ERR "Error removing notify handler\n");
++	kfree(ehotk);
++	return 0;
++}
++
++/*
++ * exit/init
++ */
++static void __exit eeepc_laptop_exit(void)
++{
++	acpi_bus_unregister_driver(&eeepc_hotk_driver);
++	sysfs_remove_group(&platform_device->dev.kobj,
++			   &platform_attribute_group);
++	platform_device_unregister(platform_device);
++	platform_driver_unregister(&platform_driver);
++}
++
++static int __init eeepc_laptop_init(void)
++{
++	struct device *dev;
++	int result;
++
++	if (acpi_disabled)
++		return -ENODEV;
++	result = acpi_bus_register_driver(&eeepc_hotk_driver);
++	if (result < 0)
++		return result;
++	if (!ehotk) {
++		acpi_bus_unregister_driver(&eeepc_hotk_driver);
++		return -ENODEV;
++	}
++	dev = acpi_get_physical_device(ehotk->device->handle);
++	/* Register platform stuff */
++	result = platform_driver_register(&platform_driver);
++	if (result)
++		goto fail_platform_driver;
++	platform_device = platform_device_alloc(EEEPC_HOTK_FILE, -1);
++	if (!platform_device) {
++		result = -ENOMEM;
++		goto fail_platform_device1;
++	}
++	result = platform_device_add(platform_device);
++	if (result)
++		goto fail_platform_device2;
++	result = sysfs_create_group(&platform_device->dev.kobj,
++				    &platform_attribute_group);
++	if (result)
++		goto fail_sysfs;
++	return 0;
++fail_sysfs:
++	platform_device_del(platform_device);
++fail_platform_device2:
++	platform_device_put(platform_device);
++fail_platform_device1:
++	platform_driver_unregister(&platform_driver);
++fail_platform_driver:
++	return result;
++}
++
++module_init(eeepc_laptop_init);
++module_exit(eeepc_laptop_exit);

commit bbc60c18ed17df75270da504bbd8f7bc4a52d43d
+Author: Michael Abd-El-Malek 
+Date:   Fri Apr 4 02:33:48 2008 -0700
+
+    xen: fix grant table bug
+    
+    fix memory corruption and crash due to mis-sized grant table.
+    
+    A PV OS has two grant table data structures: the grant table itself
+    and a free list.  The free list is composed of an array of pages,
+    which grow dynamically as the guest OS requires more grants.  While
+    the grant table contains 8-byte entries, the free list contains 4-byte
+    entries.  So we have half as many pages in the free list than in the
+    grant table.
+    
+    There was a bug in the free list allocation code. The free list was
+    indexed as if it was the same size as the grant table.  But it's only
+    half as large.  So memory got corrupted, and I was seeing crashes in
+    the slab allocator later on.
+    
+    Taken from:
+    
+      http://xenbits.xensource.com/linux-2.6.18-xen.hg?rev/4018c0da3360
+    
+    Signed-off-by: Michael Abd-El-Malek 
+    Signed-off-by: Mark McLoughlin 
+    Signed-off-by: Jeremy Fitzhardinge 
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
+index ea94dbabf9a9..d85dc6d41c2a 100644
+--- a/drivers/xen/grant-table.c
++++ b/drivers/xen/grant-table.c
+@@ -381,11 +381,15 @@ EXPORT_SYMBOL_GPL(gnttab_cancel_free_callback);
+ static int grow_gnttab_list(unsigned int more_frames)
+ {
+ 	unsigned int new_nr_grant_frames, extra_entries, i;
++	unsigned int nr_glist_frames, new_nr_glist_frames;
+ 
+ 	new_nr_grant_frames = nr_grant_frames + more_frames;
+ 	extra_entries       = more_frames * GREFS_PER_GRANT_FRAME;
+ 
+-	for (i = nr_grant_frames; i < new_nr_grant_frames; i++) {
++	nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP;
++	new_nr_glist_frames =
++		(new_nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP;
++	for (i = nr_glist_frames; i < new_nr_glist_frames; i++) {
+ 		gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_ATOMIC);
+ 		if (!gnttab_list[i])
+ 			goto grow_nomem;
+@@ -407,7 +411,7 @@ static int grow_gnttab_list(unsigned int more_frames)
+ 	return 0;
+ 
+ grow_nomem:
+-	for ( ; i >= nr_grant_frames; i--)
++	for ( ; i >= nr_glist_frames; i--)
+ 		free_page((unsigned long) gnttab_list[i]);
+ 	return -ENOMEM;
+ }
+@@ -530,7 +534,7 @@ static int gnttab_expand(unsigned int req_entries)
+ static int __devinit gnttab_init(void)
+ {
+ 	int i;
+-	unsigned int max_nr_glist_frames;
++	unsigned int max_nr_glist_frames, nr_glist_frames;
+ 	unsigned int nr_init_grefs;
+ 
+ 	if (!is_running_on_xen())
+@@ -543,15 +547,15 @@ static int __devinit gnttab_init(void)
+ 	 * grant reference free list on the current hypervisor.
+ 	 */
+ 	max_nr_glist_frames = (boot_max_nr_grant_frames *
+-			       GREFS_PER_GRANT_FRAME /
+-			       (PAGE_SIZE / sizeof(grant_ref_t)));
++			       GREFS_PER_GRANT_FRAME / RPP);
+ 
+ 	gnttab_list = kmalloc(max_nr_glist_frames * sizeof(grant_ref_t *),
+ 			      GFP_KERNEL);
+ 	if (gnttab_list == NULL)
+ 		return -ENOMEM;
+ 
+-	for (i = 0; i < nr_grant_frames; i++) {
++	nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP;
++	for (i = 0; i < nr_glist_frames; i++) {
+ 		gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL);
+ 		if (gnttab_list[i] == NULL)
+ 			goto ini_nomem;

commit 439d9eadf648a9d62ab74c64b0e7432b3a15ec3b
+Author: Spencer Baugh 
+Date:   Sat Dec 20 15:48:13 2014 -0500
+
+    lustre: ptlrpc: add "ptlrpc_internal.h" to sec_gc.c
+    
+    ptlrpc_internal.h contains the prototypes for sptlrpc_gc_init() and
+    sptlrpc_gc_fini(), which are defined in sec_gc.c.
+    
+    This removes the following sparse warnings:
+    
+    drivers/staging/lustre/lustre/ptlrpc/sec_gc.c:217:5: warning: symbol 'sptlrpc_gc_init' was not declared. Should it be static?
+    drivers/staging/lustre/lustre/ptlrpc/sec_gc.c:241:6: warning: symbol 'sptlrpc_gc_fini' was not declared. Should it be static?
+    
+    Signed-off-by: Spencer Baugh 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c b/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c
+index c500aff66193..81de68edb04e 100644
+--- a/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c
++++ b/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c
+@@ -47,6 +47,8 @@
+ #include "../include/lustre_net.h"
+ #include "../include/lustre_sec.h"
+ 
++#include "ptlrpc_internal.h"
++
+ #define SEC_GC_INTERVAL (30 * 60)
+ 
+ 

commit 727543d639efe4abb4be8ce56a1065c32dbac918
+Author: Spencer Baugh 
+Date:   Sun Sep 14 11:21:11 2014 -0400
+
+    staging: lustre: fix pointer whitespace style
+    
+    Fix errors reported by checkpatch of this kind:
+    ERROR: "foo * bar" should be "foo *bar"
+    
+    Signed-off-by: Spencer Baugh 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/lustre/lustre/include/lustre_import.h b/drivers/staging/lustre/lustre/include/lustre_import.h
+index 7bf82e03ed63..51f3e98f94e2 100644
+--- a/drivers/staging/lustre/lustre/include/lustre_import.h
++++ b/drivers/staging/lustre/lustre/include/lustre_import.h
+@@ -103,9 +103,9 @@ enum lustre_imp_state {
+ };
+ 
+ /** Returns test string representation of numeric import state \a state */
+-static inline char * ptlrpc_import_state_name(enum lustre_imp_state state)
++static inline char *ptlrpc_import_state_name(enum lustre_imp_state state)
+ {
+-	static char* import_state_names[] = {
++	static char *import_state_names[] = {
+ 		"", "CLOSED",  "NEW", "DISCONN",
+ 		"CONNECTING", "REPLAY", "REPLAY_LOCKS", "REPLAY_WAIT",
+ 		"RECOVER", "FULL", "EVICTED",

commit db7b4b391e2f301d6d18ded41628ce458cbd4129
+Author: Spencer Baugh 
+Date:   Sun Sep 14 11:21:10 2014 -0400
+
+    staging: lustre: fix function definition style
+    
+    Fix errors reported by checkpatch of this kind:
+    ERROR: open brace '{' following function declarations go on the next line
+    
+    Signed-off-by: Spencer Baugh 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/lustre/lustre/include/lustre_import.h b/drivers/staging/lustre/lustre/include/lustre_import.h
+index 8304a55b92f9..7bf82e03ed63 100644
+--- a/drivers/staging/lustre/lustre/include/lustre_import.h
++++ b/drivers/staging/lustre/lustre/include/lustre_import.h
+@@ -346,21 +346,24 @@ static inline unsigned int at_timeout2est(unsigned int val)
+ 	return (max((val << 2) / 5, 5U) - 4);
+ }
+ 
+-static inline void at_reset(struct adaptive_timeout *at, int val) {
++static inline void at_reset(struct adaptive_timeout *at, int val)
++{
+ 	spin_lock(&at->at_lock);
+ 	at->at_current = val;
+ 	at->at_worst_ever = val;
+ 	at->at_worst_time = get_seconds();
+ 	spin_unlock(&at->at_lock);
+ }
+-static inline void at_init(struct adaptive_timeout *at, int val, int flags) {
++static inline void at_init(struct adaptive_timeout *at, int val, int flags)
++{
+ 	memset(at, 0, sizeof(*at));
+ 	spin_lock_init(&at->at_lock);
+ 	at->at_flags = flags;
+ 	at_reset(at, val);
+ }
+ extern unsigned int at_min;
+-static inline int at_get(struct adaptive_timeout *at) {
++static inline int at_get(struct adaptive_timeout *at)
++{
+ 	return (at->at_current > at_min) ? at->at_current : at_min;
+ }
+ int at_measured(struct adaptive_timeout *at, unsigned int val);

commit 77ceab8ea590d7dc6c8f055ce43dfebd74428107
+Author: Ben Blum 
+Date:   Wed Nov 2 13:38:07 2011 -0700
+
+    cgroups: don't attach task to subsystem if migration failed
+    
+    If a task has exited to the point it has called cgroup_exit() already,
+    then we can't migrate it to another cgroup anymore.
+    
+    This can happen when we are attaching a task to a new cgroup between the
+    call to ->can_attach_task() on subsystems and the migration that is
+    eventually tried in cgroup_task_migrate().
+    
+    In this case cgroup_task_migrate() returns -ESRCH and we don't want to
+    attach the task to the subsystems because the attachment to the new cgroup
+    itself failed.
+    
+    Fix this by only calling ->attach_task() on the subsystems if the cgroup
+    migration succeeded.
+    
+    Reported-by: Oleg Nesterov 
+    Signed-off-by: Ben Blum 
+    Acked-by: Paul Menage 
+    Cc: Li Zefan 
+    Cc: Tejun Heo 
+    Signed-off-by: Frederic Weisbecker 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/kernel/cgroup.c b/kernel/cgroup.c
+index 64b0e73402df..8386b21224ef 100644
+--- a/kernel/cgroup.c
++++ b/kernel/cgroup.c
+@@ -2135,14 +2135,17 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
+ 		oldcgrp = task_cgroup_from_root(tsk, root);
+ 		if (cgrp == oldcgrp)
+ 			continue;
+-		/* attach each task to each subsystem */
+-		for_each_subsys(root, ss) {
+-			if (ss->attach_task)
+-				ss->attach_task(cgrp, tsk);
+-		}
+ 		/* if the thread is PF_EXITING, it can just get skipped. */
+ 		retval = cgroup_task_migrate(cgrp, oldcgrp, tsk, true);
+-		BUG_ON(retval != 0 && retval != -ESRCH);
++		if (retval == 0) {
++			/* attach each task to each subsystem */
++			for_each_subsys(root, ss) {
++				if (ss->attach_task)
++					ss->attach_task(cgrp, tsk);
++			}
++		} else {
++			BUG_ON(retval != -ESRCH);
++		}
+ 	}
+ 	/* nothing is sensitive to fork() after this point. */
+ 

commit 33ef6b6984403a688189317ef46bb3caab3b70e0
+Author: Ben Blum 
+Date:   Wed Nov 2 13:38:05 2011 -0700
+
+    cgroups: more safe tasklist locking in cgroup_attach_proc
+    
+    Fix unstable tasklist locking in cgroup_attach_proc.
+    
+    According to this thread - https://lkml.org/lkml/2011/7/27/243 - RCU is
+    not sufficient to guarantee the tasklist is stable w.r.t.  de_thread and
+    exit.  Taking tasklist_lock for reading, instead of rcu_read_lock, ensures
+    proper exclusion.
+    
+    Signed-off-by: Ben Blum 
+    Acked-by: Paul Menage 
+    Cc: Oleg Nesterov 
+    Cc: Frederic Weisbecker 
+    Cc: "Paul E. McKenney" 
+    Cc: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/kernel/cgroup.c b/kernel/cgroup.c
+index 453100a4159d..64b0e73402df 100644
+--- a/kernel/cgroup.c
++++ b/kernel/cgroup.c
+@@ -2027,7 +2027,7 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
+ 		goto out_free_group_list;
+ 
+ 	/* prevent changes to the threadgroup list while we take a snapshot. */
+-	rcu_read_lock();
++	read_lock(&tasklist_lock);
+ 	if (!thread_group_leader(leader)) {
+ 		/*
+ 		 * a race with de_thread from another thread's exec() may strip
+@@ -2036,7 +2036,7 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
+ 		 * throw this task away and try again (from cgroup_procs_write);
+ 		 * this is "double-double-toil-and-trouble-check locking".
+ 		 */
+-		rcu_read_unlock();
++		read_unlock(&tasklist_lock);
+ 		retval = -EAGAIN;
+ 		goto out_free_group_list;
+ 	}
+@@ -2057,7 +2057,7 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
+ 	} while_each_thread(leader, tsk);
+ 	/* remember the number of threads in the array for later. */
+ 	group_size = i;
+-	rcu_read_unlock();
++	read_unlock(&tasklist_lock);
+ 
+ 	/*
+ 	 * step 1: check that we can legitimately attach to the cgroup.

commit d846687d7f84e45f23ecf3846dbb43312a1206dd
+Author: Ben Blum 
+Date:   Thu May 26 16:25:21 2011 -0700
+
+    cgroups: use flex_array in attach_proc
+    
+    Convert cgroup_attach_proc to use flex_array.
+    
+    The cgroup_attach_proc implementation requires a pre-allocated array to
+    store task pointers to atomically move a thread-group, but asking for a
+    monolithic array with kmalloc() may be unreliable for very large groups.
+    Using flex_array provides the same functionality with less risk of
+    failure.
+    
+    This is a post-patch for cgroup-procs-write.patch.
+    
+    Signed-off-by: Ben Blum 
+    Cc: "Eric W. Biederman" 
+    Cc: Li Zefan 
+    Cc: Matt Helsley 
+    Reviewed-by: Paul Menage 
+    Cc: Oleg Nesterov 
+    Cc: David Rientjes 
+    Cc: Miao Xie 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/kernel/cgroup.c b/kernel/cgroup.c
+index 5e6a9745f0e7..00a884342d3d 100644
+--- a/kernel/cgroup.c
++++ b/kernel/cgroup.c
+@@ -57,6 +57,7 @@
+ #include  /* TODO: replace with more sophisticated array */
+ #include 
+ #include 
++#include  /* used in cgroup_attach_proc */
+ 
+ #include 
+ 
+@@ -1995,7 +1996,7 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
+ 	struct cgroupfs_root *root = cgrp->root;
+ 	/* threadgroup list cursor and array */
+ 	struct task_struct *tsk;
+-	struct task_struct **group;
++	struct flex_array *group;
+ 	/*
+ 	 * we need to make sure we have css_sets for all the tasks we're
+ 	 * going to move -before- we actually start moving them, so that in
+@@ -2012,9 +2013,15 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
+ 	 * and if threads exit, this will just be an over-estimate.
+ 	 */
+ 	group_size = get_nr_threads(leader);
+-	group = kmalloc(group_size * sizeof(*group), GFP_KERNEL);
++	/* flex_array supports very large thread-groups better than kmalloc. */
++	group = flex_array_alloc(sizeof(struct task_struct *), group_size,
++				 GFP_KERNEL);
+ 	if (!group)
+ 		return -ENOMEM;
++	/* pre-allocate to guarantee space while iterating in rcu read-side. */
++	retval = flex_array_prealloc(group, 0, group_size - 1, GFP_KERNEL);
++	if (retval)
++		goto out_free_group_list;
+ 
+ 	/* prevent changes to the threadgroup list while we take a snapshot. */
+ 	rcu_read_lock();
+@@ -2037,7 +2044,12 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
+ 		/* as per above, nr_threads may decrease, but not increase. */
+ 		BUG_ON(i >= group_size);
+ 		get_task_struct(tsk);
+-		group[i] = tsk;
++		/*
++		 * saying GFP_ATOMIC has no effect here because we did prealloc
++		 * earlier, but it's good form to communicate our expectations.
++		 */
++		retval = flex_array_put_ptr(group, i, tsk, GFP_ATOMIC);
++		BUG_ON(retval != 0);
+ 		i++;
+ 	} while_each_thread(leader, tsk);
+ 	/* remember the number of threads in the array for later. */
+@@ -2059,7 +2071,8 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
+ 		if (ss->can_attach_task) {
+ 			/* run on each task in the threadgroup. */
+ 			for (i = 0; i < group_size; i++) {
+-				retval = ss->can_attach_task(cgrp, group[i]);
++				tsk = flex_array_get_ptr(group, i);
++				retval = ss->can_attach_task(cgrp, tsk);
+ 				if (retval) {
+ 					failed_ss = ss;
+ 					cancel_failed_ss = true;
+@@ -2075,7 +2088,7 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
+ 	 */
+ 	INIT_LIST_HEAD(&newcg_list);
+ 	for (i = 0; i < group_size; i++) {
+-		tsk = group[i];
++		tsk = flex_array_get_ptr(group, i);
+ 		/* nothing to do if this task is already in the cgroup */
+ 		oldcgrp = task_cgroup_from_root(tsk, root);
+ 		if (cgrp == oldcgrp)
+@@ -2114,7 +2127,7 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
+ 			ss->pre_attach(cgrp);
+ 	}
+ 	for (i = 0; i < group_size; i++) {
+-		tsk = group[i];
++		tsk = flex_array_get_ptr(group, i);
+ 		/* leave current thread as it is if it's already there */
+ 		oldcgrp = task_cgroup_from_root(tsk, root);
+ 		if (cgrp == oldcgrp)
+@@ -2167,10 +2180,12 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
+ 		}
+ 	}
+ 	/* clean up the array of referenced threads in the group. */
+-	for (i = 0; i < group_size; i++)
+-		put_task_struct(group[i]);
++	for (i = 0; i < group_size; i++) {
++		tsk = flex_array_get_ptr(group, i);
++		put_task_struct(tsk);
++	}
+ out_free_group_list:
+-	kfree(group);
++	flex_array_free(group);
+ 	return retval;
+ }
+ 

commit 74a1166dfe1135dcc168d35fa5261aa7e087011b
+Author: Ben Blum 
+Date:   Thu May 26 16:25:20 2011 -0700
+
+    cgroups: make procs file writable
+    
+    Make procs file writable to move all threads by tgid at once.
+    
+    Add functionality that enables users to move all threads in a threadgroup
+    at once to a cgroup by writing the tgid to the 'cgroup.procs' file.  This
+    current implementation makes use of a per-threadgroup rwsem that's taken
+    for reading in the fork() path to prevent newly forking threads within the
+    threadgroup from "escaping" while the move is in progress.
+    
+    Signed-off-by: Ben Blum 
+    Cc: "Eric W. Biederman" 
+    Cc: Li Zefan 
+    Cc: Matt Helsley 
+    Reviewed-by: Paul Menage 
+    Cc: Oleg Nesterov 
+    Cc: David Rientjes 
+    Cc: Miao Xie 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/Documentation/cgroups/cgroups.txt b/Documentation/cgroups/cgroups.txt
+index b3bd3bdbe202..8c4f3466c894 100644
+--- a/Documentation/cgroups/cgroups.txt
++++ b/Documentation/cgroups/cgroups.txt
+@@ -236,7 +236,8 @@ containing the following files describing that cgroup:
+  - cgroup.procs: list of tgids in the cgroup.  This list is not
+    guaranteed to be sorted or free of duplicate tgids, and userspace
+    should sort/uniquify the list if this property is required.
+-   This is a read-only file, for now.
++   Writing a thread group id into this file moves all threads in that
++   group into this cgroup.
+  - notify_on_release flag: run the release agent on exit?
+  - release_agent: the path to use for release notifications (this file
+    exists in the top cgroup only)
+@@ -430,6 +431,12 @@ You can attach the current shell task by echoing 0:
+ 
+ # echo 0 > tasks
+ 
++You can use the cgroup.procs file instead of the tasks file to move all
++threads in a threadgroup at once. Echoing the pid of any task in a
++threadgroup to cgroup.procs causes all tasks in that threadgroup to be
++be attached to the cgroup. Writing 0 to cgroup.procs moves all tasks
++in the writing task's threadgroup.
++
+ Note: Since every task is always a member of exactly one cgroup in each
+ mounted hierarchy, to remove a task from its current cgroup you must
+ move it into a new cgroup (possibly the root cgroup) by writing to the
+diff --git a/kernel/cgroup.c b/kernel/cgroup.c
+index 38fb0ad1cb46..5e6a9745f0e7 100644
+--- a/kernel/cgroup.c
++++ b/kernel/cgroup.c
+@@ -1735,6 +1735,76 @@ int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen)
+ }
+ EXPORT_SYMBOL_GPL(cgroup_path);
+ 
++/*
++ * cgroup_task_migrate - move a task from one cgroup to another.
++ *
++ * 'guarantee' is set if the caller promises that a new css_set for the task
++ * will already exist. If not set, this function might sleep, and can fail with
++ * -ENOMEM. Otherwise, it can only fail with -ESRCH.
++ */
++static int cgroup_task_migrate(struct cgroup *cgrp, struct cgroup *oldcgrp,
++			       struct task_struct *tsk, bool guarantee)
++{
++	struct css_set *oldcg;
++	struct css_set *newcg;
++
++	/*
++	 * get old css_set. we need to take task_lock and refcount it, because
++	 * an exiting task can change its css_set to init_css_set and drop its
++	 * old one without taking cgroup_mutex.
++	 */
++	task_lock(tsk);
++	oldcg = tsk->cgroups;
++	get_css_set(oldcg);
++	task_unlock(tsk);
++
++	/* locate or allocate a new css_set for this task. */
++	if (guarantee) {
++		/* we know the css_set we want already exists. */
++		struct cgroup_subsys_state *template[CGROUP_SUBSYS_COUNT];
++		read_lock(&css_set_lock);
++		newcg = find_existing_css_set(oldcg, cgrp, template);
++		BUG_ON(!newcg);
++		get_css_set(newcg);
++		read_unlock(&css_set_lock);
++	} else {
++		might_sleep();
++		/* find_css_set will give us newcg already referenced. */
++		newcg = find_css_set(oldcg, cgrp);
++		if (!newcg) {
++			put_css_set(oldcg);
++			return -ENOMEM;
++		}
++	}
++	put_css_set(oldcg);
++
++	/* if PF_EXITING is set, the tsk->cgroups pointer is no longer safe. */
++	task_lock(tsk);
++	if (tsk->flags & PF_EXITING) {
++		task_unlock(tsk);
++		put_css_set(newcg);
++		return -ESRCH;
++	}
++	rcu_assign_pointer(tsk->cgroups, newcg);
++	task_unlock(tsk);
++
++	/* Update the css_set linked lists if we're using them */
++	write_lock(&css_set_lock);
++	if (!list_empty(&tsk->cg_list))
++		list_move(&tsk->cg_list, &newcg->tasks);
++	write_unlock(&css_set_lock);
++
++	/*
++	 * We just gained a reference on oldcg by taking it from the task. As
++	 * trading it for newcg is protected by cgroup_mutex, we're safe to drop
++	 * it here; it will be freed under RCU.
++	 */
++	put_css_set(oldcg);
++
++	set_bit(CGRP_RELEASABLE, &oldcgrp->flags);
++	return 0;
++}
++
+ /**
+  * cgroup_attach_task - attach task 'tsk' to cgroup 'cgrp'
+  * @cgrp: the cgroup the task is attaching to
+@@ -1745,11 +1815,9 @@ EXPORT_SYMBOL_GPL(cgroup_path);
+  */
+ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
+ {
+-	int retval = 0;
++	int retval;
+ 	struct cgroup_subsys *ss, *failed_ss = NULL;
+ 	struct cgroup *oldcgrp;
+-	struct css_set *cg;
+-	struct css_set *newcg;
+ 	struct cgroupfs_root *root = cgrp->root;
+ 
+ 	/* Nothing to do if the task is already in that cgroup */
+@@ -1780,36 +1848,9 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
+ 		}
+ 	}
+ 
+-	task_lock(tsk);
+-	cg = tsk->cgroups;
+-	get_css_set(cg);
+-	task_unlock(tsk);
+-	/*
+-	 * Locate or allocate a new css_set for this task,
+-	 * based on its final set of cgroups
+-	 */
+-	newcg = find_css_set(cg, cgrp);
+-	put_css_set(cg);
+-	if (!newcg) {
+-		retval = -ENOMEM;
+-		goto out;
+-	}
+-
+-	task_lock(tsk);
+-	if (tsk->flags & PF_EXITING) {
+-		task_unlock(tsk);
+-		put_css_set(newcg);
+-		retval = -ESRCH;
++	retval = cgroup_task_migrate(cgrp, oldcgrp, tsk, false);
++	if (retval)
+ 		goto out;
+-	}
+-	rcu_assign_pointer(tsk->cgroups, newcg);
+-	task_unlock(tsk);
+-
+-	/* Update the css_set linked lists if we're using them */
+-	write_lock(&css_set_lock);
+-	if (!list_empty(&tsk->cg_list))
+-		list_move(&tsk->cg_list, &newcg->tasks);
+-	write_unlock(&css_set_lock);
+ 
+ 	for_each_subsys(root, ss) {
+ 		if (ss->pre_attach)
+@@ -1819,9 +1860,8 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
+ 		if (ss->attach)
+ 			ss->attach(ss, cgrp, oldcgrp, tsk);
+ 	}
+-	set_bit(CGRP_RELEASABLE, &oldcgrp->flags);
++
+ 	synchronize_rcu();
+-	put_css_set(cg);
+ 
+ 	/*
+ 	 * wake up rmdir() waiter. the rmdir should fail since the cgroup
+@@ -1871,49 +1911,356 @@ int cgroup_attach_task_all(struct task_struct *from, struct task_struct *tsk)
+ EXPORT_SYMBOL_GPL(cgroup_attach_task_all);
+ 
+ /*
+- * Attach task with pid 'pid' to cgroup 'cgrp'. Call with cgroup_mutex
+- * held. May take task_lock of task
++ * cgroup_attach_proc works in two stages, the first of which prefetches all
++ * new css_sets needed (to make sure we have enough memory before committing
++ * to the move) and stores them in a list of entries of the following type.
++ * TODO: possible optimization: use css_set->rcu_head for chaining instead
++ */
++struct cg_list_entry {
++	struct css_set *cg;
++	struct list_head links;
++};
++
++static bool css_set_check_fetched(struct cgroup *cgrp,
++				  struct task_struct *tsk, struct css_set *cg,
++				  struct list_head *newcg_list)
++{
++	struct css_set *newcg;
++	struct cg_list_entry *cg_entry;
++	struct cgroup_subsys_state *template[CGROUP_SUBSYS_COUNT];
++
++	read_lock(&css_set_lock);
++	newcg = find_existing_css_set(cg, cgrp, template);
++	if (newcg)
++		get_css_set(newcg);
++	read_unlock(&css_set_lock);
++
++	/* doesn't exist at all? */
++	if (!newcg)
++		return false;
++	/* see if it's already in the list */
++	list_for_each_entry(cg_entry, newcg_list, links) {
++		if (cg_entry->cg == newcg) {
++			put_css_set(newcg);
++			return true;
++		}
++	}
++
++	/* not found */
++	put_css_set(newcg);
++	return false;
++}
++
++/*
++ * Find the new css_set and store it in the list in preparation for moving the
++ * given task to the given cgroup. Returns 0 or -ENOMEM.
++ */
++static int css_set_prefetch(struct cgroup *cgrp, struct css_set *cg,
++			    struct list_head *newcg_list)
++{
++	struct css_set *newcg;
++	struct cg_list_entry *cg_entry;
++
++	/* ensure a new css_set will exist for this thread */
++	newcg = find_css_set(cg, cgrp);
++	if (!newcg)
++		return -ENOMEM;
++	/* add it to the list */
++	cg_entry = kmalloc(sizeof(struct cg_list_entry), GFP_KERNEL);
++	if (!cg_entry) {
++		put_css_set(newcg);
++		return -ENOMEM;
++	}
++	cg_entry->cg = newcg;
++	list_add(&cg_entry->links, newcg_list);
++	return 0;
++}
++
++/**
++ * cgroup_attach_proc - attach all threads in a threadgroup to a cgroup
++ * @cgrp: the cgroup to attach to
++ * @leader: the threadgroup leader task_struct of the group to be attached
++ *
++ * Call holding cgroup_mutex and the threadgroup_fork_lock of the leader. Will
++ * take task_lock of each thread in leader's threadgroup individually in turn.
++ */
++int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
++{
++	int retval, i, group_size;
++	struct cgroup_subsys *ss, *failed_ss = NULL;
++	bool cancel_failed_ss = false;
++	/* guaranteed to be initialized later, but the compiler needs this */
++	struct cgroup *oldcgrp = NULL;
++	struct css_set *oldcg;
++	struct cgroupfs_root *root = cgrp->root;
++	/* threadgroup list cursor and array */
++	struct task_struct *tsk;
++	struct task_struct **group;
++	/*
++	 * we need to make sure we have css_sets for all the tasks we're
++	 * going to move -before- we actually start moving them, so that in
++	 * case we get an ENOMEM we can bail out before making any changes.
++	 */
++	struct list_head newcg_list;
++	struct cg_list_entry *cg_entry, *temp_nobe;
++
++	/*
++	 * step 0: in order to do expensive, possibly blocking operations for
++	 * every thread, we cannot iterate the thread group list, since it needs
++	 * rcu or tasklist locked. instead, build an array of all threads in the
++	 * group - threadgroup_fork_lock prevents new threads from appearing,
++	 * and if threads exit, this will just be an over-estimate.
++	 */
++	group_size = get_nr_threads(leader);
++	group = kmalloc(group_size * sizeof(*group), GFP_KERNEL);
++	if (!group)
++		return -ENOMEM;
++
++	/* prevent changes to the threadgroup list while we take a snapshot. */
++	rcu_read_lock();
++	if (!thread_group_leader(leader)) {
++		/*
++		 * a race with de_thread from another thread's exec() may strip
++		 * us of our leadership, making while_each_thread unsafe to use
++		 * on this task. if this happens, there is no choice but to
++		 * throw this task away and try again (from cgroup_procs_write);
++		 * this is "double-double-toil-and-trouble-check locking".
++		 */
++		rcu_read_unlock();
++		retval = -EAGAIN;
++		goto out_free_group_list;
++	}
++	/* take a reference on each task in the group to go in the array. */
++	tsk = leader;
++	i = 0;
++	do {
++		/* as per above, nr_threads may decrease, but not increase. */
++		BUG_ON(i >= group_size);
++		get_task_struct(tsk);
++		group[i] = tsk;
++		i++;
++	} while_each_thread(leader, tsk);
++	/* remember the number of threads in the array for later. */
++	group_size = i;
++	rcu_read_unlock();
++
++	/*
++	 * step 1: check that we can legitimately attach to the cgroup.
++	 */
++	for_each_subsys(root, ss) {
++		if (ss->can_attach) {
++			retval = ss->can_attach(ss, cgrp, leader);
++			if (retval) {
++				failed_ss = ss;
++				goto out_cancel_attach;
++			}
++		}
++		/* a callback to be run on every thread in the threadgroup. */
++		if (ss->can_attach_task) {
++			/* run on each task in the threadgroup. */
++			for (i = 0; i < group_size; i++) {
++				retval = ss->can_attach_task(cgrp, group[i]);
++				if (retval) {
++					failed_ss = ss;
++					cancel_failed_ss = true;
++					goto out_cancel_attach;
++				}
++			}
++		}
++	}
++
++	/*
++	 * step 2: make sure css_sets exist for all threads to be migrated.
++	 * we use find_css_set, which allocates a new one if necessary.
++	 */
++	INIT_LIST_HEAD(&newcg_list);
++	for (i = 0; i < group_size; i++) {
++		tsk = group[i];
++		/* nothing to do if this task is already in the cgroup */
++		oldcgrp = task_cgroup_from_root(tsk, root);
++		if (cgrp == oldcgrp)
++			continue;
++		/* get old css_set pointer */
++		task_lock(tsk);
++		if (tsk->flags & PF_EXITING) {
++			/* ignore this task if it's going away */
++			task_unlock(tsk);
++			continue;
++		}
++		oldcg = tsk->cgroups;
++		get_css_set(oldcg);
++		task_unlock(tsk);
++		/* see if the new one for us is already in the list? */
++		if (css_set_check_fetched(cgrp, tsk, oldcg, &newcg_list)) {
++			/* was already there, nothing to do. */
++			put_css_set(oldcg);
++		} else {
++			/* we don't already have it. get new one. */
++			retval = css_set_prefetch(cgrp, oldcg, &newcg_list);
++			put_css_set(oldcg);
++			if (retval)
++				goto out_list_teardown;
++		}
++	}
++
++	/*
++	 * step 3: now that we're guaranteed success wrt the css_sets, proceed
++	 * to move all tasks to the new cgroup, calling ss->attach_task for each
++	 * one along the way. there are no failure cases after here, so this is
++	 * the commit point.
++	 */
++	for_each_subsys(root, ss) {
++		if (ss->pre_attach)
++			ss->pre_attach(cgrp);
++	}
++	for (i = 0; i < group_size; i++) {
++		tsk = group[i];
++		/* leave current thread as it is if it's already there */
++		oldcgrp = task_cgroup_from_root(tsk, root);
++		if (cgrp == oldcgrp)
++			continue;
++		/* attach each task to each subsystem */
++		for_each_subsys(root, ss) {
++			if (ss->attach_task)
++				ss->attach_task(cgrp, tsk);
++		}
++		/* if the thread is PF_EXITING, it can just get skipped. */
++		retval = cgroup_task_migrate(cgrp, oldcgrp, tsk, true);
++		BUG_ON(retval != 0 && retval != -ESRCH);
++	}
++	/* nothing is sensitive to fork() after this point. */
++
++	/*
++	 * step 4: do expensive, non-thread-specific subsystem callbacks.
++	 * TODO: if ever a subsystem needs to know the oldcgrp for each task
++	 * being moved, this call will need to be reworked to communicate that.
++	 */
++	for_each_subsys(root, ss) {
++		if (ss->attach)
++			ss->attach(ss, cgrp, oldcgrp, leader);
++	}
++
++	/*
++	 * step 5: success! and cleanup
++	 */
++	synchronize_rcu();
++	cgroup_wakeup_rmdir_waiter(cgrp);
++	retval = 0;
++out_list_teardown:
++	/* clean up the list of prefetched css_sets. */
++	list_for_each_entry_safe(cg_entry, temp_nobe, &newcg_list, links) {
++		list_del(&cg_entry->links);
++		put_css_set(cg_entry->cg);
++		kfree(cg_entry);
++	}
++out_cancel_attach:
++	/* same deal as in cgroup_attach_task */
++	if (retval) {
++		for_each_subsys(root, ss) {
++			if (ss == failed_ss) {
++				if (cancel_failed_ss && ss->cancel_attach)
++					ss->cancel_attach(ss, cgrp, leader);
++				break;
++			}
++			if (ss->cancel_attach)
++				ss->cancel_attach(ss, cgrp, leader);
++		}
++	}
++	/* clean up the array of referenced threads in the group. */
++	for (i = 0; i < group_size; i++)
++		put_task_struct(group[i]);
++out_free_group_list:
++	kfree(group);
++	return retval;
++}
++
++/*
++ * Find the task_struct of the task to attach by vpid and pass it along to the
++ * function to attach either it or all tasks in its threadgroup. Will take
++ * cgroup_mutex; may take task_lock of task.
+  */
+-static int attach_task_by_pid(struct cgroup *cgrp, u64 pid)
++static int attach_task_by_pid(struct cgroup *cgrp, u64 pid, bool threadgroup)
+ {
+ 	struct task_struct *tsk;
+ 	const struct cred *cred = current_cred(), *tcred;
+ 	int ret;
+ 
++	if (!cgroup_lock_live_group(cgrp))
++		return -ENODEV;
++
+ 	if (pid) {
+ 		rcu_read_lock();
+ 		tsk = find_task_by_vpid(pid);
+-		if (!tsk || tsk->flags & PF_EXITING) {
++		if (!tsk) {
+ 			rcu_read_unlock();
++			cgroup_unlock();
++			return -ESRCH;
++		}
++		if (threadgroup) {
++			/*
++			 * RCU protects this access, since tsk was found in the
++			 * tid map. a race with de_thread may cause group_leader
++			 * to stop being the leader, but cgroup_attach_proc will
++			 * detect it later.
++			 */
++			tsk = tsk->group_leader;
++		} else if (tsk->flags & PF_EXITING) {
++			/* optimization for the single-task-only case */
++			rcu_read_unlock();
++			cgroup_unlock();
+ 			return -ESRCH;
+ 		}
+ 
++		/*
++		 * even if we're attaching all tasks in the thread group, we
++		 * only need to check permissions on one of them.
++		 */
+ 		tcred = __task_cred(tsk);
+ 		if (cred->euid &&
+ 		    cred->euid != tcred->uid &&
+ 		    cred->euid != tcred->suid) {
+ 			rcu_read_unlock();
++			cgroup_unlock();
+ 			return -EACCES;
+ 		}
+ 		get_task_struct(tsk);
+ 		rcu_read_unlock();
+ 	} else {
+-		tsk = current;
++		if (threadgroup)
++			tsk = current->group_leader;
++		else
++			tsk = current;
+ 		get_task_struct(tsk);
+ 	}
+ 
+-	ret = cgroup_attach_task(cgrp, tsk);
++	if (threadgroup) {
++		threadgroup_fork_write_lock(tsk);
++		ret = cgroup_attach_proc(cgrp, tsk);
++		threadgroup_fork_write_unlock(tsk);
++	} else {
++		ret = cgroup_attach_task(cgrp, tsk);
++	}
+ 	put_task_struct(tsk);
++	cgroup_unlock();
+ 	return ret;
+ }
+ 
+ static int cgroup_tasks_write(struct cgroup *cgrp, struct cftype *cft, u64 pid)
++{
++	return attach_task_by_pid(cgrp, pid, false);
++}
++
++static int cgroup_procs_write(struct cgroup *cgrp, struct cftype *cft, u64 tgid)
+ {
+ 	int ret;
+-	if (!cgroup_lock_live_group(cgrp))
+-		return -ENODEV;
+-	ret = attach_task_by_pid(cgrp, pid);
+-	cgroup_unlock();
++	do {
++		/*
++		 * attach_proc fails with -EAGAIN if threadgroup leadership
++		 * changes in the middle of the operation, in which case we need
++		 * to find the task_struct for the new leader and start over.
++		 */
++		ret = attach_task_by_pid(cgrp, tgid, true);
++	} while (ret == -EAGAIN);
+ 	return ret;
+ }
+ 
+@@ -3270,9 +3617,9 @@ static struct cftype files[] = {
+ 	{
+ 		.name = CGROUP_FILE_GENERIC_PREFIX "procs",
+ 		.open = cgroup_procs_open,
+-		/* .write_u64 = cgroup_procs_write, TODO */
++		.write_u64 = cgroup_procs_write,
+ 		.release = cgroup_pidlist_release,
+-		.mode = S_IRUGO,
++		.mode = S_IRUGO | S_IWUSR,
+ 	},
+ 	{
+ 		.name = "notify_on_release",

commit f780bdb7c1c73009cb57adcf99ef50027d80bf3c
+Author: Ben Blum 
+Date:   Thu May 26 16:25:19 2011 -0700
+
+    cgroups: add per-thread subsystem callbacks
+    
+    Add cgroup subsystem callbacks for per-thread attachment in atomic contexts
+    
+    Add can_attach_task(), pre_attach(), and attach_task() as new callbacks
+    for cgroups's subsystem interface.  Unlike can_attach and attach, these
+    are for per-thread operations, to be called potentially many times when
+    attaching an entire threadgroup.
+    
+    Also, the old "bool threadgroup" interface is removed, as replaced by
+    this.  All subsystems are modified for the new interface - of note is
+    cpuset, which requires from/to nodemasks for attach to be globally scoped
+    (though per-cpuset would work too) to persist from its pre_attach to
+    attach_task and attach.
+    
+    This is a pre-patch for cgroup-procs-writable.patch.
+    
+    Signed-off-by: Ben Blum 
+    Cc: "Eric W. Biederman" 
+    Cc: Li Zefan 
+    Cc: Matt Helsley 
+    Reviewed-by: Paul Menage 
+    Cc: Oleg Nesterov 
+    Cc: David Rientjes 
+    Cc: Miao Xie 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/Documentation/cgroups/cgroups.txt b/Documentation/cgroups/cgroups.txt
+index aedf1bd02fdd..b3bd3bdbe202 100644
+--- a/Documentation/cgroups/cgroups.txt
++++ b/Documentation/cgroups/cgroups.txt
+@@ -575,7 +575,7 @@ rmdir() will fail with it. From this behavior, pre_destroy() can be
+ called multiple times against a cgroup.
+ 
+ int can_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
+-	       struct task_struct *task, bool threadgroup)
++	       struct task_struct *task)
+ (cgroup_mutex held by caller)
+ 
+ Called prior to moving a task into a cgroup; if the subsystem
+@@ -584,9 +584,14 @@ task is passed, then a successful result indicates that *any*
+ unspecified task can be moved into the cgroup. Note that this isn't
+ called on a fork. If this method returns 0 (success) then this should
+ remain valid while the caller holds cgroup_mutex and it is ensured that either
+-attach() or cancel_attach() will be called in future. If threadgroup is
+-true, then a successful result indicates that all threads in the given
+-thread's threadgroup can be moved together.
++attach() or cancel_attach() will be called in future.
++
++int can_attach_task(struct cgroup *cgrp, struct task_struct *tsk);
++(cgroup_mutex held by caller)
++
++As can_attach, but for operations that must be run once per task to be
++attached (possibly many when using cgroup_attach_proc). Called after
++can_attach.
+ 
+ void cancel_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
+ 	       struct task_struct *task, bool threadgroup)
+@@ -598,15 +603,24 @@ function, so that the subsystem can implement a rollback. If not, not necessary.
+ This will be called only about subsystems whose can_attach() operation have
+ succeeded.
+ 
++void pre_attach(struct cgroup *cgrp);
++(cgroup_mutex held by caller)
++
++For any non-per-thread attachment work that needs to happen before
++attach_task. Needed by cpuset.
++
+ void attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
+-	    struct cgroup *old_cgrp, struct task_struct *task,
+-	    bool threadgroup)
++	    struct cgroup *old_cgrp, struct task_struct *task)
+ (cgroup_mutex held by caller)
+ 
+ Called after the task has been attached to the cgroup, to allow any
+ post-attachment activity that requires memory allocations or blocking.
+-If threadgroup is true, the subsystem should take care of all threads
+-in the specified thread's threadgroup. Currently does not support any
++
++void attach_task(struct cgroup *cgrp, struct task_struct *tsk);
++(cgroup_mutex held by caller)
++
++As attach, but for operations that must be run once per task to be attached,
++like can_attach_task. Called before attach. Currently does not support any
+ subsystem that might need the old_cgrp for every thread in the group.
+ 
+ void fork(struct cgroup_subsy *ss, struct task_struct *task)
+diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
+index 07371cfdfae6..bcaf16ee6ad1 100644
+--- a/block/blk-cgroup.c
++++ b/block/blk-cgroup.c
+@@ -30,10 +30,8 @@ EXPORT_SYMBOL_GPL(blkio_root_cgroup);
+ 
+ static struct cgroup_subsys_state *blkiocg_create(struct cgroup_subsys *,
+ 						  struct cgroup *);
+-static int blkiocg_can_attach(struct cgroup_subsys *, struct cgroup *,
+-			      struct task_struct *, bool);
+-static void blkiocg_attach(struct cgroup_subsys *, struct cgroup *,
+-			   struct cgroup *, struct task_struct *, bool);
++static int blkiocg_can_attach_task(struct cgroup *, struct task_struct *);
++static void blkiocg_attach_task(struct cgroup *, struct task_struct *);
+ static void blkiocg_destroy(struct cgroup_subsys *, struct cgroup *);
+ static int blkiocg_populate(struct cgroup_subsys *, struct cgroup *);
+ 
+@@ -46,8 +44,8 @@ static int blkiocg_populate(struct cgroup_subsys *, struct cgroup *);
+ struct cgroup_subsys blkio_subsys = {
+ 	.name = "blkio",
+ 	.create = blkiocg_create,
+-	.can_attach = blkiocg_can_attach,
+-	.attach = blkiocg_attach,
++	.can_attach_task = blkiocg_can_attach_task,
++	.attach_task = blkiocg_attach_task,
+ 	.destroy = blkiocg_destroy,
+ 	.populate = blkiocg_populate,
+ #ifdef CONFIG_BLK_CGROUP
+@@ -1616,9 +1614,7 @@ blkiocg_create(struct cgroup_subsys *subsys, struct cgroup *cgroup)
+  * of the main cic data structures.  For now we allow a task to change
+  * its cgroup only if it's the only owner of its ioc.
+  */
+-static int blkiocg_can_attach(struct cgroup_subsys *subsys,
+-				struct cgroup *cgroup, struct task_struct *tsk,
+-				bool threadgroup)
++static int blkiocg_can_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
+ {
+ 	struct io_context *ioc;
+ 	int ret = 0;
+@@ -1633,9 +1629,7 @@ static int blkiocg_can_attach(struct cgroup_subsys *subsys,
+ 	return ret;
+ }
+ 
+-static void blkiocg_attach(struct cgroup_subsys *subsys, struct cgroup *cgroup,
+-				struct cgroup *prev, struct task_struct *tsk,
+-				bool threadgroup)
++static void blkiocg_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
+ {
+ 	struct io_context *ioc;
+ 
+diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
+index 5ac7ebc36dbb..1e6cde21fa3f 100644
+--- a/include/linux/cgroup.h
++++ b/include/linux/cgroup.h
+@@ -467,12 +467,14 @@ struct cgroup_subsys {
+ 	int (*pre_destroy)(struct cgroup_subsys *ss, struct cgroup *cgrp);
+ 	void (*destroy)(struct cgroup_subsys *ss, struct cgroup *cgrp);
+ 	int (*can_attach)(struct cgroup_subsys *ss, struct cgroup *cgrp,
+-			  struct task_struct *tsk, bool threadgroup);
++			  struct task_struct *tsk);
++	int (*can_attach_task)(struct cgroup *cgrp, struct task_struct *tsk);
+ 	void (*cancel_attach)(struct cgroup_subsys *ss, struct cgroup *cgrp,
+-			  struct task_struct *tsk, bool threadgroup);
++			      struct task_struct *tsk);
++	void (*pre_attach)(struct cgroup *cgrp);
++	void (*attach_task)(struct cgroup *cgrp, struct task_struct *tsk);
+ 	void (*attach)(struct cgroup_subsys *ss, struct cgroup *cgrp,
+-			struct cgroup *old_cgrp, struct task_struct *tsk,
+-			bool threadgroup);
++		       struct cgroup *old_cgrp, struct task_struct *tsk);
+ 	void (*fork)(struct cgroup_subsys *ss, struct task_struct *task);
+ 	void (*exit)(struct cgroup_subsys *ss, struct cgroup *cgrp,
+ 			struct cgroup *old_cgrp, struct task_struct *task);
+diff --git a/kernel/cgroup.c b/kernel/cgroup.c
+index 909a35510af5..38fb0ad1cb46 100644
+--- a/kernel/cgroup.c
++++ b/kernel/cgroup.c
+@@ -1759,7 +1759,7 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
+ 
+ 	for_each_subsys(root, ss) {
+ 		if (ss->can_attach) {
+-			retval = ss->can_attach(ss, cgrp, tsk, false);
++			retval = ss->can_attach(ss, cgrp, tsk);
+ 			if (retval) {
+ 				/*
+ 				 * Remember on which subsystem the can_attach()
+@@ -1771,6 +1771,13 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
+ 				goto out;
+ 			}
+ 		}
++		if (ss->can_attach_task) {
++			retval = ss->can_attach_task(cgrp, tsk);
++			if (retval) {
++				failed_ss = ss;
++				goto out;
++			}
++		}
+ 	}
+ 
+ 	task_lock(tsk);
+@@ -1805,8 +1812,12 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
+ 	write_unlock(&css_set_lock);
+ 
+ 	for_each_subsys(root, ss) {
++		if (ss->pre_attach)
++			ss->pre_attach(cgrp);
++		if (ss->attach_task)
++			ss->attach_task(cgrp, tsk);
+ 		if (ss->attach)
+-			ss->attach(ss, cgrp, oldcgrp, tsk, false);
++			ss->attach(ss, cgrp, oldcgrp, tsk);
+ 	}
+ 	set_bit(CGRP_RELEASABLE, &oldcgrp->flags);
+ 	synchronize_rcu();
+@@ -1829,7 +1840,7 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
+ 				 */
+ 				break;
+ 			if (ss->cancel_attach)
+-				ss->cancel_attach(ss, cgrp, tsk, false);
++				ss->cancel_attach(ss, cgrp, tsk);
+ 		}
+ 	}
+ 	return retval;
+diff --git a/kernel/cgroup_freezer.c b/kernel/cgroup_freezer.c
+index e7bebb7c6c38..e691818d7e45 100644
+--- a/kernel/cgroup_freezer.c
++++ b/kernel/cgroup_freezer.c
+@@ -160,7 +160,7 @@ static void freezer_destroy(struct cgroup_subsys *ss,
+  */
+ static int freezer_can_attach(struct cgroup_subsys *ss,
+ 			      struct cgroup *new_cgroup,
+-			      struct task_struct *task, bool threadgroup)
++			      struct task_struct *task)
+ {
+ 	struct freezer *freezer;
+ 
+@@ -172,26 +172,17 @@ static int freezer_can_attach(struct cgroup_subsys *ss,
+ 	if (freezer->state != CGROUP_THAWED)
+ 		return -EBUSY;
+ 
++	return 0;
++}
++
++static int freezer_can_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
++{
+ 	rcu_read_lock();
+-	if (__cgroup_freezing_or_frozen(task)) {
++	if (__cgroup_freezing_or_frozen(tsk)) {
+ 		rcu_read_unlock();
+ 		return -EBUSY;
+ 	}
+ 	rcu_read_unlock();
+-
+-	if (threadgroup) {
+-		struct task_struct *c;
+-
+-		rcu_read_lock();
+-		list_for_each_entry_rcu(c, &task->thread_group, thread_group) {
+-			if (__cgroup_freezing_or_frozen(c)) {
+-				rcu_read_unlock();
+-				return -EBUSY;
+-			}
+-		}
+-		rcu_read_unlock();
+-	}
+-
+ 	return 0;
+ }
+ 
+@@ -390,6 +381,9 @@ struct cgroup_subsys freezer_subsys = {
+ 	.populate	= freezer_populate,
+ 	.subsys_id	= freezer_subsys_id,
+ 	.can_attach	= freezer_can_attach,
++	.can_attach_task = freezer_can_attach_task,
++	.pre_attach	= NULL,
++	.attach_task	= NULL,
+ 	.attach		= NULL,
+ 	.fork		= freezer_fork,
+ 	.exit		= NULL,
+diff --git a/kernel/cpuset.c b/kernel/cpuset.c
+index 2bb8c2e98fff..55b297d78adc 100644
+--- a/kernel/cpuset.c
++++ b/kernel/cpuset.c
+@@ -1367,14 +1367,10 @@ static int fmeter_getrate(struct fmeter *fmp)
+ 	return val;
+ }
+ 
+-/* Protected by cgroup_lock */
+-static cpumask_var_t cpus_attach;
+-
+ /* Called by cgroups to determine if a cpuset is usable; cgroup_mutex held */
+ static int cpuset_can_attach(struct cgroup_subsys *ss, struct cgroup *cont,
+-			     struct task_struct *tsk, bool threadgroup)
++			     struct task_struct *tsk)
+ {
+-	int ret;
+ 	struct cpuset *cs = cgroup_cs(cont);
+ 
+ 	if (cpumask_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed))
+@@ -1391,29 +1387,42 @@ static int cpuset_can_attach(struct cgroup_subsys *ss, struct cgroup *cont,
+ 	if (tsk->flags & PF_THREAD_BOUND)
+ 		return -EINVAL;
+ 
+-	ret = security_task_setscheduler(tsk);
+-	if (ret)
+-		return ret;
+-	if (threadgroup) {
+-		struct task_struct *c;
+-
+-		rcu_read_lock();
+-		list_for_each_entry_rcu(c, &tsk->thread_group, thread_group) {
+-			ret = security_task_setscheduler(c);
+-			if (ret) {
+-				rcu_read_unlock();
+-				return ret;
+-			}
+-		}
+-		rcu_read_unlock();
+-	}
+ 	return 0;
+ }
+ 
+-static void cpuset_attach_task(struct task_struct *tsk, nodemask_t *to,
+-			       struct cpuset *cs)
++static int cpuset_can_attach_task(struct cgroup *cgrp, struct task_struct *task)
++{
++	return security_task_setscheduler(task);
++}
++
++/*
++ * Protected by cgroup_lock. The nodemasks must be stored globally because
++ * dynamically allocating them is not allowed in pre_attach, and they must
++ * persist among pre_attach, attach_task, and attach.
++ */
++static cpumask_var_t cpus_attach;
++static nodemask_t cpuset_attach_nodemask_from;
++static nodemask_t cpuset_attach_nodemask_to;
++
++/* Set-up work for before attaching each task. */
++static void cpuset_pre_attach(struct cgroup *cont)
++{
++	struct cpuset *cs = cgroup_cs(cont);
++
++	if (cs == &top_cpuset)
++		cpumask_copy(cpus_attach, cpu_possible_mask);
++	else
++		guarantee_online_cpus(cs, cpus_attach);
++
++	guarantee_online_mems(cs, &cpuset_attach_nodemask_to);
++}
++
++/* Per-thread attachment work. */
++static void cpuset_attach_task(struct cgroup *cont, struct task_struct *tsk)
+ {
+ 	int err;
++	struct cpuset *cs = cgroup_cs(cont);
++
+ 	/*
+ 	 * can_attach beforehand should guarantee that this doesn't fail.
+ 	 * TODO: have a better way to handle failure here
+@@ -1421,45 +1430,29 @@ static void cpuset_attach_task(struct task_struct *tsk, nodemask_t *to,
+ 	err = set_cpus_allowed_ptr(tsk, cpus_attach);
+ 	WARN_ON_ONCE(err);
+ 
+-	cpuset_change_task_nodemask(tsk, to);
++	cpuset_change_task_nodemask(tsk, &cpuset_attach_nodemask_to);
+ 	cpuset_update_task_spread_flag(cs, tsk);
+-
+ }
+ 
+ static void cpuset_attach(struct cgroup_subsys *ss, struct cgroup *cont,
+-			  struct cgroup *oldcont, struct task_struct *tsk,
+-			  bool threadgroup)
++			  struct cgroup *oldcont, struct task_struct *tsk)
+ {
+ 	struct mm_struct *mm;
+ 	struct cpuset *cs = cgroup_cs(cont);
+ 	struct cpuset *oldcs = cgroup_cs(oldcont);
+-	static nodemask_t to;		/* protected by cgroup_mutex */
+ 
+-	if (cs == &top_cpuset) {
+-		cpumask_copy(cpus_attach, cpu_possible_mask);
+-	} else {
+-		guarantee_online_cpus(cs, cpus_attach);
+-	}
+-	guarantee_online_mems(cs, &to);
+-
+-	/* do per-task migration stuff possibly for each in the threadgroup */
+-	cpuset_attach_task(tsk, &to, cs);
+-	if (threadgroup) {
+-		struct task_struct *c;
+-		rcu_read_lock();
+-		list_for_each_entry_rcu(c, &tsk->thread_group, thread_group) {
+-			cpuset_attach_task(c, &to, cs);
+-		}
+-		rcu_read_unlock();
+-	}
+-
+-	/* change mm; only needs to be done once even if threadgroup */
+-	to = cs->mems_allowed;
++	/*
++	 * Change mm, possibly for multiple threads in a threadgroup. This is
++	 * expensive and may sleep.
++	 */
++	cpuset_attach_nodemask_from = oldcs->mems_allowed;
++	cpuset_attach_nodemask_to = cs->mems_allowed;
+ 	mm = get_task_mm(tsk);
+ 	if (mm) {
+-		mpol_rebind_mm(mm, &to);
++		mpol_rebind_mm(mm, &cpuset_attach_nodemask_to);
+ 		if (is_memory_migrate(cs))
+-			cpuset_migrate_mm(mm, &oldcs->mems_allowed, &to);
++			cpuset_migrate_mm(mm, &cpuset_attach_nodemask_from,
++					  &cpuset_attach_nodemask_to);
+ 		mmput(mm);
+ 	}
+ }
+@@ -1911,6 +1904,9 @@ struct cgroup_subsys cpuset_subsys = {
+ 	.create = cpuset_create,
+ 	.destroy = cpuset_destroy,
+ 	.can_attach = cpuset_can_attach,
++	.can_attach_task = cpuset_can_attach_task,
++	.pre_attach = cpuset_pre_attach,
++	.attach_task = cpuset_attach_task,
+ 	.attach = cpuset_attach,
+ 	.populate = cpuset_populate,
+ 	.post_clone = cpuset_post_clone,
+diff --git a/kernel/sched.c b/kernel/sched.c
+index 2d12893b8b0f..5e43e9dc65d1 100644
+--- a/kernel/sched.c
++++ b/kernel/sched.c
+@@ -8764,42 +8764,10 @@ cpu_cgroup_can_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
+ 	return 0;
+ }
+ 
+-static int
+-cpu_cgroup_can_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
+-		      struct task_struct *tsk, bool threadgroup)
+-{
+-	int retval = cpu_cgroup_can_attach_task(cgrp, tsk);
+-	if (retval)
+-		return retval;
+-	if (threadgroup) {
+-		struct task_struct *c;
+-		rcu_read_lock();
+-		list_for_each_entry_rcu(c, &tsk->thread_group, thread_group) {
+-			retval = cpu_cgroup_can_attach_task(cgrp, c);
+-			if (retval) {
+-				rcu_read_unlock();
+-				return retval;
+-			}
+-		}
+-		rcu_read_unlock();
+-	}
+-	return 0;
+-}
+-
+ static void
+-cpu_cgroup_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
+-		  struct cgroup *old_cont, struct task_struct *tsk,
+-		  bool threadgroup)
++cpu_cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
+ {
+ 	sched_move_task(tsk);
+-	if (threadgroup) {
+-		struct task_struct *c;
+-		rcu_read_lock();
+-		list_for_each_entry_rcu(c, &tsk->thread_group, thread_group) {
+-			sched_move_task(c);
+-		}
+-		rcu_read_unlock();
+-	}
+ }
+ 
+ static void
+@@ -8887,8 +8855,8 @@ struct cgroup_subsys cpu_cgroup_subsys = {
+ 	.name		= "cpu",
+ 	.create		= cpu_cgroup_create,
+ 	.destroy	= cpu_cgroup_destroy,
+-	.can_attach	= cpu_cgroup_can_attach,
+-	.attach		= cpu_cgroup_attach,
++	.can_attach_task = cpu_cgroup_can_attach_task,
++	.attach_task	= cpu_cgroup_attach_task,
+ 	.exit		= cpu_cgroup_exit,
+ 	.populate	= cpu_cgroup_populate,
+ 	.subsys_id	= cpu_cgroup_subsys_id,
+diff --git a/mm/memcontrol.c b/mm/memcontrol.c
+index d5fd3dcd3f2e..fc259926c170 100644
+--- a/mm/memcontrol.c
++++ b/mm/memcontrol.c
+@@ -4953,8 +4953,7 @@ static void mem_cgroup_clear_mc(void)
+ 
+ static int mem_cgroup_can_attach(struct cgroup_subsys *ss,
+ 				struct cgroup *cgroup,
+-				struct task_struct *p,
+-				bool threadgroup)
++				struct task_struct *p)
+ {
+ 	int ret = 0;
+ 	struct mem_cgroup *mem = mem_cgroup_from_cont(cgroup);
+@@ -4993,8 +4992,7 @@ static int mem_cgroup_can_attach(struct cgroup_subsys *ss,
+ 
+ static void mem_cgroup_cancel_attach(struct cgroup_subsys *ss,
+ 				struct cgroup *cgroup,
+-				struct task_struct *p,
+-				bool threadgroup)
++				struct task_struct *p)
+ {
+ 	mem_cgroup_clear_mc();
+ }
+@@ -5112,8 +5110,7 @@ static void mem_cgroup_move_charge(struct mm_struct *mm)
+ static void mem_cgroup_move_task(struct cgroup_subsys *ss,
+ 				struct cgroup *cont,
+ 				struct cgroup *old_cont,
+-				struct task_struct *p,
+-				bool threadgroup)
++				struct task_struct *p)
+ {
+ 	struct mm_struct *mm;
+ 
+@@ -5131,22 +5128,19 @@ static void mem_cgroup_move_task(struct cgroup_subsys *ss,
+ #else	/* !CONFIG_MMU */
+ static int mem_cgroup_can_attach(struct cgroup_subsys *ss,
+ 				struct cgroup *cgroup,
+-				struct task_struct *p,
+-				bool threadgroup)
++				struct task_struct *p)
+ {
+ 	return 0;
+ }
+ static void mem_cgroup_cancel_attach(struct cgroup_subsys *ss,
+ 				struct cgroup *cgroup,
+-				struct task_struct *p,
+-				bool threadgroup)
++				struct task_struct *p)
+ {
+ }
+ static void mem_cgroup_move_task(struct cgroup_subsys *ss,
+ 				struct cgroup *cont,
+ 				struct cgroup *old_cont,
+-				struct task_struct *p,
+-				bool threadgroup)
++				struct task_struct *p)
+ {
+ }
+ #endif
+diff --git a/security/device_cgroup.c b/security/device_cgroup.c
+index 8d9c48f13774..cd1f779fa51d 100644
+--- a/security/device_cgroup.c
++++ b/security/device_cgroup.c
+@@ -62,8 +62,7 @@ static inline struct dev_cgroup *task_devcgroup(struct task_struct *task)
+ struct cgroup_subsys devices_subsys;
+ 
+ static int devcgroup_can_attach(struct cgroup_subsys *ss,
+-		struct cgroup *new_cgroup, struct task_struct *task,
+-		bool threadgroup)
++		struct cgroup *new_cgroup, struct task_struct *task)
+ {
+ 	if (current != task && !capable(CAP_SYS_ADMIN))
+ 			return -EPERM;

commit 4714d1d32d97239fb5ae3e10521d3f133a899b66
+Author: Ben Blum 
+Date:   Thu May 26 16:25:18 2011 -0700
+
+    cgroups: read-write lock CLONE_THREAD forking per threadgroup
+    
+    Adds functionality to read/write lock CLONE_THREAD fork()ing per-threadgroup
+    
+    Add an rwsem that lives in a threadgroup's signal_struct that's taken for
+    reading in the fork path, under CONFIG_CGROUPS.  If another part of the
+    kernel later wants to use such a locking mechanism, the CONFIG_CGROUPS
+    ifdefs should be changed to a higher-up flag that CGROUPS and the other
+    system would both depend on.
+    
+    This is a pre-patch for cgroup-procs-write.patch.
+    
+    Signed-off-by: Ben Blum 
+    Cc: "Eric W. Biederman" 
+    Cc: Li Zefan 
+    Cc: Matt Helsley 
+    Reviewed-by: Paul Menage 
+    Cc: Oleg Nesterov 
+    Cc: David Rientjes 
+    Cc: Miao Xie 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/init_task.h b/include/linux/init_task.h
+index bafc58c00fc3..580f70c02391 100644
+--- a/include/linux/init_task.h
++++ b/include/linux/init_task.h
+@@ -22,6 +22,14 @@
+ extern struct files_struct init_files;
+ extern struct fs_struct init_fs;
+ 
++#ifdef CONFIG_CGROUPS
++#define INIT_THREADGROUP_FORK_LOCK(sig)					\
++	.threadgroup_fork_lock =					\
++		__RWSEM_INITIALIZER(sig.threadgroup_fork_lock),
++#else
++#define INIT_THREADGROUP_FORK_LOCK(sig)
++#endif
++
+ #define INIT_SIGNALS(sig) {						\
+ 	.nr_threads	= 1,						\
+ 	.wait_chldexit	= __WAIT_QUEUE_HEAD_INITIALIZER(sig.wait_chldexit),\
+@@ -38,6 +46,7 @@ extern struct fs_struct init_fs;
+ 	},								\
+ 	.cred_guard_mutex =						\
+ 		 __MUTEX_INITIALIZER(sig.cred_guard_mutex),		\
++	INIT_THREADGROUP_FORK_LOCK(sig)					\
+ }
+ 
+ extern struct nsproxy init_nsproxy;
+diff --git a/include/linux/sched.h b/include/linux/sched.h
+index f18300eddfcb..dc8871295a5a 100644
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -513,6 +513,7 @@ struct thread_group_cputimer {
+ 	spinlock_t lock;
+ };
+ 
++#include 
+ struct autogroup;
+ 
+ /*
+@@ -632,6 +633,16 @@ struct signal_struct {
+ 	unsigned audit_tty;
+ 	struct tty_audit_buf *tty_audit_buf;
+ #endif
++#ifdef CONFIG_CGROUPS
++	/*
++	 * The threadgroup_fork_lock prevents threads from forking with
++	 * CLONE_THREAD while held for writing. Use this for fork-sensitive
++	 * threadgroup-wide operations. It's taken for reading in fork.c in
++	 * copy_process().
++	 * Currently only needed write-side by cgroups.
++	 */
++	struct rw_semaphore threadgroup_fork_lock;
++#endif
+ 
+ 	int oom_adj;		/* OOM kill score adjustment (bit shift) */
+ 	int oom_score_adj;	/* OOM kill score adjustment */
+@@ -2323,6 +2334,31 @@ static inline void unlock_task_sighand(struct task_struct *tsk,
+ 	spin_unlock_irqrestore(&tsk->sighand->siglock, *flags);
+ }
+ 
++/* See the declaration of threadgroup_fork_lock in signal_struct. */
++#ifdef CONFIG_CGROUPS
++static inline void threadgroup_fork_read_lock(struct task_struct *tsk)
++{
++	down_read(&tsk->signal->threadgroup_fork_lock);
++}
++static inline void threadgroup_fork_read_unlock(struct task_struct *tsk)
++{
++	up_read(&tsk->signal->threadgroup_fork_lock);
++}
++static inline void threadgroup_fork_write_lock(struct task_struct *tsk)
++{
++	down_write(&tsk->signal->threadgroup_fork_lock);
++}
++static inline void threadgroup_fork_write_unlock(struct task_struct *tsk)
++{
++	up_write(&tsk->signal->threadgroup_fork_lock);
++}
++#else
++static inline void threadgroup_fork_read_lock(struct task_struct *tsk) {}
++static inline void threadgroup_fork_read_unlock(struct task_struct *tsk) {}
++static inline void threadgroup_fork_write_lock(struct task_struct *tsk) {}
++static inline void threadgroup_fork_write_unlock(struct task_struct *tsk) {}
++#endif
++
+ #ifndef __HAVE_THREAD_FUNCTIONS
+ 
+ #define task_thread_info(task)	((struct thread_info *)(task)->stack)
+diff --git a/kernel/fork.c b/kernel/fork.c
+index 8e7e135d0817..1fa9d940e301 100644
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -957,6 +957,10 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
+ 	tty_audit_fork(sig);
+ 	sched_autogroup_fork(sig);
+ 
++#ifdef CONFIG_CGROUPS
++	init_rwsem(&sig->threadgroup_fork_lock);
++#endif
++
+ 	sig->oom_adj = current->signal->oom_adj;
+ 	sig->oom_score_adj = current->signal->oom_score_adj;
+ 	sig->oom_score_adj_min = current->signal->oom_score_adj_min;
+@@ -1138,6 +1142,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
+ 	monotonic_to_bootbased(&p->real_start_time);
+ 	p->io_context = NULL;
+ 	p->audit_context = NULL;
++	if (clone_flags & CLONE_THREAD)
++		threadgroup_fork_read_lock(current);
+ 	cgroup_fork(p);
+ #ifdef CONFIG_NUMA
+ 	p->mempolicy = mpol_dup(p->mempolicy);
+@@ -1342,6 +1348,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
+ 	write_unlock_irq(&tasklist_lock);
+ 	proc_fork_connector(p);
+ 	cgroup_post_fork(p);
++	if (clone_flags & CLONE_THREAD)
++		threadgroup_fork_read_unlock(current);
+ 	perf_event_fork(p);
+ 	return p;
+ 
+@@ -1380,6 +1388,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
+ 	mpol_put(p->mempolicy);
+ bad_fork_cleanup_cgroup:
+ #endif
++	if (clone_flags & CLONE_THREAD)
++		threadgroup_fork_read_unlock(current);
+ 	cgroup_exit(p, cgroup_callbacks_done);
+ 	delayacct_tsk_free(p);
+ 	module_put(task_thread_info(p)->exec_domain->module);

commit 8e039d84b323c4503c4d56863faa47c783660826
+Author: Ben Blum 
+Date:   Tue Mar 23 05:24:03 2010 +0000
+
+    cgroups: net_cls as module
+    
+    Allows the net_cls cgroup subsystem to be compiled as a module
+    
+    This patch modifies net/sched/cls_cgroup.c to allow the net_cls subsystem
+    to be optionally compiled as a module instead of builtin.  The
+    cgroup_subsys struct is moved around a bit to allow the subsys_id to be
+    either declared as a compile-time constant by the cgroup_subsys.h include
+    in cgroup.h, or, if it's a module, initialized within the struct by
+    cgroup_load_subsys.
+    
+    Signed-off-by: Ben Blum 
+    Acked-by: Li Zefan 
+    Cc: Paul Menage 
+    Cc: "David S. Miller" 
+    Cc: KAMEZAWA Hiroyuki 
+    Cc: Lai Jiangshan 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/sched/Kconfig b/net/sched/Kconfig
+index 21f9c7678aa3..2f691fb180d1 100644
+--- a/net/sched/Kconfig
++++ b/net/sched/Kconfig
+@@ -328,13 +328,16 @@ config NET_CLS_FLOW
+ 	  module will be called cls_flow.
+ 
+ config NET_CLS_CGROUP
+-	bool "Control Group Classifier"
++	tristate "Control Group Classifier"
+ 	select NET_CLS
+ 	depends on CGROUPS
+ 	---help---
+ 	  Say Y here if you want to classify packets based on the control
+ 	  cgroup of their process.
+ 
++	  To compile this code as a module, choose M here: the
++	  module will be called cls_cgroup.
++
+ config NET_EMATCH
+ 	bool "Extended Matches"
+ 	select NET_CLS
+diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c
+index e4877ca6727c..7f27d2c15e08 100644
+--- a/net/sched/cls_cgroup.c
++++ b/net/sched/cls_cgroup.c
+@@ -24,6 +24,25 @@ struct cgroup_cls_state
+ 	u32 classid;
+ };
+ 
++static struct cgroup_subsys_state *cgrp_create(struct cgroup_subsys *ss,
++					       struct cgroup *cgrp);
++static void cgrp_destroy(struct cgroup_subsys *ss, struct cgroup *cgrp);
++static int cgrp_populate(struct cgroup_subsys *ss, struct cgroup *cgrp);
++
++struct cgroup_subsys net_cls_subsys = {
++	.name		= "net_cls",
++	.create		= cgrp_create,
++	.destroy	= cgrp_destroy,
++	.populate	= cgrp_populate,
++#ifdef CONFIG_NET_CLS_CGROUP
++	.subsys_id	= net_cls_subsys_id,
++#else
++#define net_cls_subsys_id net_cls_subsys.subsys_id
++#endif
++	.module		= THIS_MODULE,
++};
++
++
+ static inline struct cgroup_cls_state *cgrp_cls_state(struct cgroup *cgrp)
+ {
+ 	return container_of(cgroup_subsys_state(cgrp, net_cls_subsys_id),
+@@ -79,14 +98,6 @@ static int cgrp_populate(struct cgroup_subsys *ss, struct cgroup *cgrp)
+ 	return cgroup_add_files(cgrp, ss, ss_files, ARRAY_SIZE(ss_files));
+ }
+ 
+-struct cgroup_subsys net_cls_subsys = {
+-	.name		= "net_cls",
+-	.create		= cgrp_create,
+-	.destroy	= cgrp_destroy,
+-	.populate	= cgrp_populate,
+-	.subsys_id	= net_cls_subsys_id,
+-};
+-
+ struct cls_cgroup_head
+ {
+ 	u32			handle;
+@@ -277,12 +288,19 @@ static struct tcf_proto_ops cls_cgroup_ops __read_mostly = {
+ 
+ static int __init init_cgroup_cls(void)
+ {
+-	return register_tcf_proto_ops(&cls_cgroup_ops);
++	int ret = register_tcf_proto_ops(&cls_cgroup_ops);
++	if (ret)
++		return ret;
++	ret = cgroup_load_subsys(&net_cls_subsys);
++	if (ret)
++		unregister_tcf_proto_ops(&cls_cgroup_ops);
++	return ret;
+ }
+ 
+ static void __exit exit_cgroup_cls(void)
+ {
+ 	unregister_tcf_proto_ops(&cls_cgroup_ops);
++	cgroup_unload_subsys(&net_cls_subsys);
+ }
+ 
+ module_init(init_cgroup_cls);

commit 67523c48aa74d5637848edeccf285af1c60bf14a
+Author: Ben Blum 
+Date:   Wed Mar 10 15:22:11 2010 -0800
+
+    cgroups: blkio subsystem as module
+    
+    Modify the Block I/O cgroup subsystem to be able to be built as a module.
+    As the CFQ disk scheduler optionally depends on blk-cgroup, config options
+    in block/Kconfig, block/Kconfig.iosched, and block/blk-cgroup.h are
+    enhanced to support the new module dependency.
+    
+    Signed-off-by: Ben Blum 
+    Cc: Li Zefan 
+    Cc: Paul Menage 
+    Cc: "David S. Miller" 
+    Cc: KAMEZAWA Hiroyuki 
+    Cc: Lai Jiangshan 
+    Cc: Vivek Goyal 
+    Cc: Jens Axboe 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/block/Kconfig b/block/Kconfig
+index e20fbde0875c..62a5921321cd 100644
+--- a/block/Kconfig
++++ b/block/Kconfig
+@@ -78,7 +78,7 @@ config BLK_DEV_INTEGRITY
+ 	Protection.  If in doubt, say N.
+ 
+ config BLK_CGROUP
+-	bool
++	tristate
+ 	depends on CGROUPS
+ 	default n
+ 	---help---
+diff --git a/block/Kconfig.iosched b/block/Kconfig.iosched
+index b71abfb0d726..fc71cf071fb2 100644
+--- a/block/Kconfig.iosched
++++ b/block/Kconfig.iosched
+@@ -23,6 +23,7 @@ config IOSCHED_DEADLINE
+ 
+ config IOSCHED_CFQ
+ 	tristate "CFQ I/O scheduler"
++	select BLK_CGROUP if CFQ_GROUP_IOSCHED
+ 	default y
+ 	---help---
+ 	  The CFQ I/O scheduler tries to distribute bandwidth equally
+@@ -35,7 +36,6 @@ config IOSCHED_CFQ
+ config CFQ_GROUP_IOSCHED
+ 	bool "CFQ Group Scheduling support"
+ 	depends on IOSCHED_CFQ && CGROUPS
+-	select BLK_CGROUP
+ 	default n
+ 	---help---
+ 	  Enable group IO scheduling in CFQ.
+diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
+index c85d74cae200..4b686ad08eaa 100644
+--- a/block/blk-cgroup.c
++++ b/block/blk-cgroup.c
+@@ -23,6 +23,31 @@ static LIST_HEAD(blkio_list);
+ struct blkio_cgroup blkio_root_cgroup = { .weight = 2*BLKIO_WEIGHT_DEFAULT };
+ EXPORT_SYMBOL_GPL(blkio_root_cgroup);
+ 
++static struct cgroup_subsys_state *blkiocg_create(struct cgroup_subsys *,
++						  struct cgroup *);
++static int blkiocg_can_attach(struct cgroup_subsys *, struct cgroup *,
++			      struct task_struct *, bool);
++static void blkiocg_attach(struct cgroup_subsys *, struct cgroup *,
++			   struct cgroup *, struct task_struct *, bool);
++static void blkiocg_destroy(struct cgroup_subsys *, struct cgroup *);
++static int blkiocg_populate(struct cgroup_subsys *, struct cgroup *);
++
++struct cgroup_subsys blkio_subsys = {
++	.name = "blkio",
++	.create = blkiocg_create,
++	.can_attach = blkiocg_can_attach,
++	.attach = blkiocg_attach,
++	.destroy = blkiocg_destroy,
++	.populate = blkiocg_populate,
++#ifdef CONFIG_BLK_CGROUP
++	/* note: blkio_subsys_id is otherwise defined in blk-cgroup.h */
++	.subsys_id = blkio_subsys_id,
++#endif
++	.use_id = 1,
++	.module = THIS_MODULE,
++};
++EXPORT_SYMBOL_GPL(blkio_subsys);
++
+ struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup)
+ {
+ 	return container_of(cgroup_subsys_state(cgroup, blkio_subsys_id),
+@@ -253,7 +278,8 @@ static void blkiocg_destroy(struct cgroup_subsys *subsys, struct cgroup *cgroup)
+ done:
+ 	free_css_id(&blkio_subsys, &blkcg->css);
+ 	rcu_read_unlock();
+-	kfree(blkcg);
++	if (blkcg != &blkio_root_cgroup)
++		kfree(blkcg);
+ }
+ 
+ static struct cgroup_subsys_state *
+@@ -319,17 +345,6 @@ static void blkiocg_attach(struct cgroup_subsys *subsys, struct cgroup *cgroup,
+ 	task_unlock(tsk);
+ }
+ 
+-struct cgroup_subsys blkio_subsys = {
+-	.name = "blkio",
+-	.create = blkiocg_create,
+-	.can_attach = blkiocg_can_attach,
+-	.attach = blkiocg_attach,
+-	.destroy = blkiocg_destroy,
+-	.populate = blkiocg_populate,
+-	.subsys_id = blkio_subsys_id,
+-	.use_id = 1,
+-};
+-
+ void blkio_policy_register(struct blkio_policy_type *blkiop)
+ {
+ 	spin_lock(&blkio_list_lock);
+@@ -345,3 +360,17 @@ void blkio_policy_unregister(struct blkio_policy_type *blkiop)
+ 	spin_unlock(&blkio_list_lock);
+ }
+ EXPORT_SYMBOL_GPL(blkio_policy_unregister);
++
++static int __init init_cgroup_blkio(void)
++{
++	return cgroup_load_subsys(&blkio_subsys);
++}
++
++static void __exit exit_cgroup_blkio(void)
++{
++	cgroup_unload_subsys(&blkio_subsys);
++}
++
++module_init(init_cgroup_blkio);
++module_exit(exit_cgroup_blkio);
++MODULE_LICENSE("GPL");
+diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h
+index 84bf745fa775..8ccc20464dae 100644
+--- a/block/blk-cgroup.h
++++ b/block/blk-cgroup.h
+@@ -15,7 +15,13 @@
+ 
+ #include 
+ 
+-#ifdef CONFIG_BLK_CGROUP
++#if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE)
++
++#ifndef CONFIG_BLK_CGROUP
++/* When blk-cgroup is a module, its subsys_id isn't a compile-time constant */
++extern struct cgroup_subsys blkio_subsys;
++#define blkio_subsys_id blkio_subsys.subsys_id
++#endif
+ 
+ struct blkio_cgroup {
+ 	struct cgroup_subsys_state css;
+@@ -91,7 +97,7 @@ static inline void blkiocg_update_blkio_group_dequeue_stats(
+ 			struct blkio_group *blkg, unsigned long dequeue) {}
+ #endif
+ 
+-#ifdef CONFIG_BLK_CGROUP
++#if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE)
+ extern struct blkio_cgroup blkio_root_cgroup;
+ extern struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup);
+ extern void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
+diff --git a/include/linux/iocontext.h b/include/linux/iocontext.h
+index 1195a806fe0c..a0bb301afac0 100644
+--- a/include/linux/iocontext.h
++++ b/include/linux/iocontext.h
+@@ -42,7 +42,7 @@ struct io_context {
+ 	unsigned short ioprio;
+ 	unsigned short ioprio_changed;
+ 
+-#ifdef CONFIG_BLK_CGROUP
++#if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE)
+ 	unsigned short cgroup_changed;
+ #endif
+ 
+diff --git a/kernel/cgroup.c b/kernel/cgroup.c
+index aa889c96cc74..521591dbab2f 100644
+--- a/kernel/cgroup.c
++++ b/kernel/cgroup.c
+@@ -705,6 +705,7 @@ void cgroup_lock(void)
+ {
+ 	mutex_lock(&cgroup_mutex);
+ }
++EXPORT_SYMBOL_GPL(cgroup_lock);
+ 
+ /**
+  * cgroup_unlock - release lock on cgroup changes
+@@ -715,6 +716,7 @@ void cgroup_unlock(void)
+ {
+ 	mutex_unlock(&cgroup_mutex);
+ }
++EXPORT_SYMBOL_GPL(cgroup_unlock);
+ 
+ /*
+  * A couple of forward declarations required, due to cyclic reference loop:
+@@ -1639,6 +1641,7 @@ int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen)
+ 	memmove(buf, start, buf + buflen - start);
+ 	return 0;
+ }
++EXPORT_SYMBOL_GPL(cgroup_path);
+ 
+ /**
+  * cgroup_attach_task - attach task 'tsk' to cgroup 'cgrp'
+@@ -1805,6 +1808,7 @@ bool cgroup_lock_live_group(struct cgroup *cgrp)
+ 	}
+ 	return true;
+ }
++EXPORT_SYMBOL_GPL(cgroup_lock_live_group);
+ 
+ static int cgroup_release_agent_write(struct cgroup *cgrp, struct cftype *cft,
+ 				      const char *buffer)
+@@ -4082,6 +4086,7 @@ void __css_put(struct cgroup_subsys_state *css, int count)
+ 	rcu_read_unlock();
+ 	WARN_ON_ONCE(val < 1);
+ }
++EXPORT_SYMBOL_GPL(__css_put);
+ 
+ /*
+  * Notify userspace when a cgroup is released, by running the
+@@ -4197,6 +4202,7 @@ unsigned short css_id(struct cgroup_subsys_state *css)
+ 		return cssid->id;
+ 	return 0;
+ }
++EXPORT_SYMBOL_GPL(css_id);
+ 
+ unsigned short css_depth(struct cgroup_subsys_state *css)
+ {
+@@ -4206,6 +4212,7 @@ unsigned short css_depth(struct cgroup_subsys_state *css)
+ 		return cssid->depth;
+ 	return 0;
+ }
++EXPORT_SYMBOL_GPL(css_depth);
+ 
+ bool css_is_ancestor(struct cgroup_subsys_state *child,
+ 		    const struct cgroup_subsys_state *root)
+@@ -4242,6 +4249,7 @@ void free_css_id(struct cgroup_subsys *ss, struct cgroup_subsys_state *css)
+ 	spin_unlock(&ss->id_lock);
+ 	call_rcu(&id->rcu_head, __free_css_id_cb);
+ }
++EXPORT_SYMBOL_GPL(free_css_id);
+ 
+ /*
+  * This is called by init or create(). Then, calls to this function are
+@@ -4358,6 +4366,7 @@ struct cgroup_subsys_state *css_lookup(struct cgroup_subsys *ss, int id)
+ 
+ 	return rcu_dereference(cssid->css);
+ }
++EXPORT_SYMBOL_GPL(css_lookup);
+ 
+ /**
+  * css_get_next - lookup next cgroup under specified hierarchy.

commit cf5d5941fda647fe3d2f2d00cf9e0245236a5f08
+Author: Ben Blum 
+Date:   Wed Mar 10 15:22:09 2010 -0800
+
+    cgroups: subsystem module unloading
+    
+    Provides support for unloading modular subsystems.
+    
+    This patch adds a new function cgroup_unload_subsys which is to be used
+    for removing a loaded subsystem during module deletion.  Reference
+    counting of the subsystems' modules is moved from once (at load time) to
+    once per attached hierarchy (in parse_cgroupfs_options and
+    rebind_subsystems) (i.e., 0 or 1).
+    
+    Signed-off-by: Ben Blum 
+    Acked-by: Li Zefan 
+    Cc: Paul Menage 
+    Cc: "David S. Miller" 
+    Cc: KAMEZAWA Hiroyuki 
+    Cc: Lai Jiangshan 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/Documentation/cgroups/cgroups.txt b/Documentation/cgroups/cgroups.txt
+index ae8a037a761e..764007b63921 100644
+--- a/Documentation/cgroups/cgroups.txt
++++ b/Documentation/cgroups/cgroups.txt
+@@ -489,8 +489,9 @@ Each subsystem should:
+ - define a cgroup_subsys object called _subsys
+ 
+ If a subsystem can be compiled as a module, it should also have in its
+-module initcall a call to cgroup_load_subsys(&its_subsys_struct). It
+-should also set its_subsys.module = THIS_MODULE in its .c file.
++module initcall a call to cgroup_load_subsys(), and in its exitcall a
++call to cgroup_unload_subsys(). It should also set its_subsys.module =
++THIS_MODULE in its .c file.
+ 
+ Each subsystem may export the following methods. The only mandatory
+ methods are create/destroy. Any others that are null are presumed to
+diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
+index 402ce477c47e..2a59d3101e5d 100644
+--- a/include/linux/cgroup.h
++++ b/include/linux/cgroup.h
+@@ -38,6 +38,7 @@ extern void cgroup_exit(struct task_struct *p, int run_callbacks);
+ extern int cgroupstats_build(struct cgroupstats *stats,
+ 				struct dentry *dentry);
+ extern int cgroup_load_subsys(struct cgroup_subsys *ss);
++extern void cgroup_unload_subsys(struct cgroup_subsys *ss);
+ 
+ extern const struct file_operations proc_cgroup_operations;
+ 
+@@ -271,7 +272,8 @@ struct css_set {
+ 	/*
+ 	 * Set of subsystem states, one for each subsystem. This array
+ 	 * is immutable after creation apart from the init_css_set
+-	 * during subsystem registration (at boot time).
++	 * during subsystem registration (at boot time) and modular subsystem
++	 * loading/unloading.
+ 	 */
+ 	struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];
+ 
+diff --git a/kernel/cgroup.c b/kernel/cgroup.c
+index 2cae38e64c59..aa889c96cc74 100644
+--- a/kernel/cgroup.c
++++ b/kernel/cgroup.c
+@@ -894,7 +894,9 @@ void cgroup_release_and_wakeup_rmdir(struct cgroup_subsys_state *css)
+ }
+ 
+ /*
+- * Call with cgroup_mutex held.
++ * Call with cgroup_mutex held. Drops reference counts on modules, including
++ * any duplicate ones that parse_cgroupfs_options took. If this function
++ * returns an error, no reference counts are touched.
+  */
+ static int rebind_subsystems(struct cgroupfs_root *root,
+ 			      unsigned long final_bits)
+@@ -950,6 +952,7 @@ static int rebind_subsystems(struct cgroupfs_root *root,
+ 			if (ss->bind)
+ 				ss->bind(ss, cgrp);
+ 			mutex_unlock(&ss->hierarchy_mutex);
++			/* refcount was already taken, and we're keeping it */
+ 		} else if (bit & removed_bits) {
+ 			/* We're removing this subsystem */
+ 			BUG_ON(ss == NULL);
+@@ -963,10 +966,20 @@ static int rebind_subsystems(struct cgroupfs_root *root,
+ 			subsys[i]->root = &rootnode;
+ 			list_move(&ss->sibling, &rootnode.subsys_list);
+ 			mutex_unlock(&ss->hierarchy_mutex);
++			/* subsystem is now free - drop reference on module */
++			module_put(ss->module);
+ 		} else if (bit & final_bits) {
+ 			/* Subsystem state should already exist */
+ 			BUG_ON(ss == NULL);
+ 			BUG_ON(!cgrp->subsys[i]);
++			/*
++			 * a refcount was taken, but we already had one, so
++			 * drop the extra reference.
++			 */
++			module_put(ss->module);
++#ifdef CONFIG_MODULE_UNLOAD
++			BUG_ON(ss->module && !module_refcount(ss->module));
++#endif
+ 		} else {
+ 			/* Subsystem state shouldn't exist */
+ 			BUG_ON(cgrp->subsys[i]);
+@@ -1010,13 +1023,16 @@ struct cgroup_sb_opts {
+ 
+ /*
+  * Convert a hierarchy specifier into a bitmask of subsystems and flags. Call
+- * with cgroup_mutex held to protect the subsys[] array.
++ * with cgroup_mutex held to protect the subsys[] array. This function takes
++ * refcounts on subsystems to be used, unless it returns error, in which case
++ * no refcounts are taken.
+  */
+-static int parse_cgroupfs_options(char *data,
+-				     struct cgroup_sb_opts *opts)
++static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
+ {
+ 	char *token, *o = data ?: "all";
+ 	unsigned long mask = (unsigned long)-1;
++	int i;
++	bool module_pin_failed = false;
+ 
+ 	BUG_ON(!mutex_is_locked(&cgroup_mutex));
+ 
+@@ -1031,7 +1047,6 @@ static int parse_cgroupfs_options(char *data,
+ 			return -EINVAL;
+ 		if (!strcmp(token, "all")) {
+ 			/* Add all non-disabled subsystems */
+-			int i;
+ 			opts->subsys_bits = 0;
+ 			for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+ 				struct cgroup_subsys *ss = subsys[i];
+@@ -1054,7 +1069,6 @@ static int parse_cgroupfs_options(char *data,
+ 			if (!opts->release_agent)
+ 				return -ENOMEM;
+ 		} else if (!strncmp(token, "name=", 5)) {
+-			int i;
+ 			const char *name = token + 5;
+ 			/* Can't specify an empty name */
+ 			if (!strlen(name))
+@@ -1078,7 +1092,6 @@ static int parse_cgroupfs_options(char *data,
+ 				return -ENOMEM;
+ 		} else {
+ 			struct cgroup_subsys *ss;
+-			int i;
+ 			for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+ 				ss = subsys[i];
+ 				if (ss == NULL)
+@@ -1117,9 +1130,54 @@ static int parse_cgroupfs_options(char *data,
+ 	if (!opts->subsys_bits && !opts->name)
+ 		return -EINVAL;
+ 
++	/*
++	 * Grab references on all the modules we'll need, so the subsystems
++	 * don't dance around before rebind_subsystems attaches them. This may
++	 * take duplicate reference counts on a subsystem that's already used,
++	 * but rebind_subsystems handles this case.
++	 */
++	for (i = CGROUP_BUILTIN_SUBSYS_COUNT; i < CGROUP_SUBSYS_COUNT; i++) {
++		unsigned long bit = 1UL << i;
++
++		if (!(bit & opts->subsys_bits))
++			continue;
++		if (!try_module_get(subsys[i]->module)) {
++			module_pin_failed = true;
++			break;
++		}
++	}
++	if (module_pin_failed) {
++		/*
++		 * oops, one of the modules was going away. this means that we
++		 * raced with a module_delete call, and to the user this is
++		 * essentially a "subsystem doesn't exist" case.
++		 */
++		for (i--; i >= CGROUP_BUILTIN_SUBSYS_COUNT; i--) {
++			/* drop refcounts only on the ones we took */
++			unsigned long bit = 1UL << i;
++
++			if (!(bit & opts->subsys_bits))
++				continue;
++			module_put(subsys[i]->module);
++		}
++		return -ENOENT;
++	}
++
+ 	return 0;
+ }
+ 
++static void drop_parsed_module_refcounts(unsigned long subsys_bits)
++{
++	int i;
++	for (i = CGROUP_BUILTIN_SUBSYS_COUNT; i < CGROUP_SUBSYS_COUNT; i++) {
++		unsigned long bit = 1UL << i;
++
++		if (!(bit & subsys_bits))
++			continue;
++		module_put(subsys[i]->module);
++	}
++}
++
+ static int cgroup_remount(struct super_block *sb, int *flags, char *data)
+ {
+ 	int ret = 0;
+@@ -1136,21 +1194,19 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data)
+ 	if (ret)
+ 		goto out_unlock;
+ 
+-	/* Don't allow flags to change at remount */
+-	if (opts.flags != root->flags) {
+-		ret = -EINVAL;
+-		goto out_unlock;
+-	}
+-
+-	/* Don't allow name to change at remount */
+-	if (opts.name && strcmp(opts.name, root->name)) {
++	/* Don't allow flags or name to change at remount */
++	if (opts.flags != root->flags ||
++	    (opts.name && strcmp(opts.name, root->name))) {
+ 		ret = -EINVAL;
++		drop_parsed_module_refcounts(opts.subsys_bits);
+ 		goto out_unlock;
+ 	}
+ 
+ 	ret = rebind_subsystems(root, opts.subsys_bits);
+-	if (ret)
++	if (ret) {
++		drop_parsed_module_refcounts(opts.subsys_bits);
+ 		goto out_unlock;
++	}
+ 
+ 	/* (re)populate subsystem files */
+ 	cgroup_populate_dir(cgrp);
+@@ -1349,7 +1405,7 @@ static int cgroup_get_sb(struct file_system_type *fs_type,
+ 	new_root = cgroup_root_from_opts(&opts);
+ 	if (IS_ERR(new_root)) {
+ 		ret = PTR_ERR(new_root);
+-		goto out_err;
++		goto drop_modules;
+ 	}
+ 	opts.new_root = new_root;
+ 
+@@ -1358,7 +1414,7 @@ static int cgroup_get_sb(struct file_system_type *fs_type,
+ 	if (IS_ERR(sb)) {
+ 		ret = PTR_ERR(sb);
+ 		cgroup_drop_root(opts.new_root);
+-		goto out_err;
++		goto drop_modules;
+ 	}
+ 
+ 	root = sb->s_fs_info;
+@@ -1414,6 +1470,11 @@ static int cgroup_get_sb(struct file_system_type *fs_type,
+ 			free_cg_links(&tmp_cg_links);
+ 			goto drop_new_super;
+ 		}
++		/*
++		 * There must be no failure case after here, since rebinding
++		 * takes care of subsystems' refcounts, which are explicitly
++		 * dropped in the failure exit path.
++		 */
+ 
+ 		/* EBUSY should be the only error here */
+ 		BUG_ON(ret);
+@@ -1452,6 +1513,8 @@ static int cgroup_get_sb(struct file_system_type *fs_type,
+ 		 * any) is not needed
+ 		 */
+ 		cgroup_drop_root(opts.new_root);
++		/* no subsys rebinding, so refcounts don't change */
++		drop_parsed_module_refcounts(opts.subsys_bits);
+ 	}
+ 
+ 	simple_set_mnt(mnt, sb);
+@@ -1461,6 +1524,8 @@ static int cgroup_get_sb(struct file_system_type *fs_type,
+ 
+  drop_new_super:
+ 	deactivate_locked_super(sb);
++ drop_modules:
++	drop_parsed_module_refcounts(opts.subsys_bits);
+  out_err:
+ 	kfree(opts.release_agent);
+ 	kfree(opts.name);
+@@ -3422,19 +3487,71 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
+ 	lockdep_set_class(&ss->hierarchy_mutex, &ss->subsys_key);
+ 	ss->active = 1;
+ 
+-	/*
+-	 * pin the subsystem's module so it doesn't go away. this shouldn't
+-	 * fail, since the module's initcall calls us.
+-	 * TODO: with module unloading, move this elsewhere
+-	 */
+-	BUG_ON(!try_module_get(ss->module));
+-
+ 	/* success! */
+ 	mutex_unlock(&cgroup_mutex);
+ 	return 0;
+ }
+ EXPORT_SYMBOL_GPL(cgroup_load_subsys);
+ 
++/**
++ * cgroup_unload_subsys: unload a modular subsystem
++ * @ss: the subsystem to unload
++ *
++ * This function should be called in a modular subsystem's exitcall. When this
++ * function is invoked, the refcount on the subsystem's module will be 0, so
++ * the subsystem will not be attached to any hierarchy.
++ */
++void cgroup_unload_subsys(struct cgroup_subsys *ss)
++{
++	struct cg_cgroup_link *link;
++	struct hlist_head *hhead;
++
++	BUG_ON(ss->module == NULL);
++
++	/*
++	 * we shouldn't be called if the subsystem is in use, and the use of
++	 * try_module_get in parse_cgroupfs_options should ensure that it
++	 * doesn't start being used while we're killing it off.
++	 */
++	BUG_ON(ss->root != &rootnode);
++
++	mutex_lock(&cgroup_mutex);
++	/* deassign the subsys_id */
++	BUG_ON(ss->subsys_id < CGROUP_BUILTIN_SUBSYS_COUNT);
++	subsys[ss->subsys_id] = NULL;
++
++	/* remove subsystem from rootnode's list of subsystems */
++	list_del(&ss->sibling);
++
++	/*
++	 * disentangle the css from all css_sets attached to the dummytop. as
++	 * in loading, we need to pay our respects to the hashtable gods.
++	 */
++	write_lock(&css_set_lock);
++	list_for_each_entry(link, &dummytop->css_sets, cgrp_link_list) {
++		struct css_set *cg = link->cg;
++
++		hlist_del(&cg->hlist);
++		BUG_ON(!cg->subsys[ss->subsys_id]);
++		cg->subsys[ss->subsys_id] = NULL;
++		hhead = css_set_hash(cg->subsys);
++		hlist_add_head(&cg->hlist, hhead);
++	}
++	write_unlock(&css_set_lock);
++
++	/*
++	 * remove subsystem's css from the dummytop and free it - need to free
++	 * before marking as null because ss->destroy needs the cgrp->subsys
++	 * pointer to find their state. note that this also takes care of
++	 * freeing the css_id.
++	 */
++	ss->destroy(ss, dummytop);
++	dummytop->subsys[ss->subsys_id] = NULL;
++
++	mutex_unlock(&cgroup_mutex);
++}
++EXPORT_SYMBOL_GPL(cgroup_unload_subsys);
++
+ /**
+  * cgroup_init_early - cgroup initialization at system boot
+  *

commit e6a1105ba08b265023dd71a4174fb4a29ebc7083
+Author: Ben Blum 
+Date:   Wed Mar 10 15:22:09 2010 -0800
+
+    cgroups: subsystem module loading interface
+    
+    Add interface between cgroups subsystem management and module loading
+    
+    This patch implements rudimentary module-loading support for cgroups -
+    namely, a cgroup_load_subsys (similar to cgroup_init_subsys) for use as a
+    module initcall, and a struct module pointer in struct cgroup_subsys.
+    
+    Several functions that might be wanted by modules have had EXPORT_SYMBOL
+    added to them, but it's unclear exactly which functions want it and which
+    won't.
+    
+    Signed-off-by: Ben Blum 
+    Acked-by: Li Zefan 
+    Cc: Paul Menage 
+    Cc: "David S. Miller" 
+    Cc: KAMEZAWA Hiroyuki 
+    Cc: Lai Jiangshan 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/Documentation/cgroups/cgroups.txt b/Documentation/cgroups/cgroups.txt
+index d45082653e3d..ae8a037a761e 100644
+--- a/Documentation/cgroups/cgroups.txt
++++ b/Documentation/cgroups/cgroups.txt
+@@ -488,6 +488,10 @@ Each subsystem should:
+ - add an entry in linux/cgroup_subsys.h
+ - define a cgroup_subsys object called _subsys
+ 
++If a subsystem can be compiled as a module, it should also have in its
++module initcall a call to cgroup_load_subsys(&its_subsys_struct). It
++should also set its_subsys.module = THIS_MODULE in its .c file.
++
+ Each subsystem may export the following methods. The only mandatory
+ methods are create/destroy. Any others that are null are presumed to
+ be successful no-ops.
+diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
+index 28319a9fe569..402ce477c47e 100644
+--- a/include/linux/cgroup.h
++++ b/include/linux/cgroup.h
+@@ -37,6 +37,7 @@ extern void cgroup_post_fork(struct task_struct *p);
+ extern void cgroup_exit(struct task_struct *p, int run_callbacks);
+ extern int cgroupstats_build(struct cgroupstats *stats,
+ 				struct dentry *dentry);
++extern int cgroup_load_subsys(struct cgroup_subsys *ss);
+ 
+ extern const struct file_operations proc_cgroup_operations;
+ 
+@@ -486,6 +487,9 @@ struct cgroup_subsys {
+ 	/* used when use_id == true */
+ 	struct idr idr;
+ 	spinlock_t id_lock;
++
++	/* should be defined only by modular subsystems */
++	struct module *module;
+ };
+ 
+ #define SUBSYS(_x) extern struct cgroup_subsys _x ## _subsys;
+diff --git a/kernel/cgroup.c b/kernel/cgroup.c
+index c92fb9549358..2cae38e64c59 100644
+--- a/kernel/cgroup.c
++++ b/kernel/cgroup.c
+@@ -44,6 +44,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -254,7 +255,8 @@ struct cg_cgroup_link {
+ static struct css_set init_css_set;
+ static struct cg_cgroup_link init_css_set_link;
+ 
+-static int cgroup_subsys_init_idr(struct cgroup_subsys *ss);
++static int cgroup_init_idr(struct cgroup_subsys *ss,
++			   struct cgroup_subsys_state *css);
+ 
+ /* css_set_lock protects the list of css_set objects, and the
+  * chain of tasks off each css_set.  Nests outside task->alloc_lock
+@@ -2125,6 +2127,7 @@ int cgroup_add_file(struct cgroup *cgrp,
+ 		error = PTR_ERR(dentry);
+ 	return error;
+ }
++EXPORT_SYMBOL_GPL(cgroup_add_file);
+ 
+ int cgroup_add_files(struct cgroup *cgrp,
+ 			struct cgroup_subsys *subsys,
+@@ -2139,6 +2142,7 @@ int cgroup_add_files(struct cgroup *cgrp,
+ 	}
+ 	return 0;
+ }
++EXPORT_SYMBOL_GPL(cgroup_add_files);
+ 
+ /**
+  * cgroup_task_count - count the number of tasks in a cgroup.
+@@ -3292,7 +3296,144 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
+ 	mutex_init(&ss->hierarchy_mutex);
+ 	lockdep_set_class(&ss->hierarchy_mutex, &ss->subsys_key);
+ 	ss->active = 1;
++
++	/* this function shouldn't be used with modular subsystems, since they
++	 * need to register a subsys_id, among other things */
++	BUG_ON(ss->module);
++}
++
++/**
++ * cgroup_load_subsys: load and register a modular subsystem at runtime
++ * @ss: the subsystem to load
++ *
++ * This function should be called in a modular subsystem's initcall. If the
++ * subsytem is built as a module, it will be assigned a new subsys_id and set
++ * up for use. If the subsystem is built-in anyway, work is delegated to the
++ * simpler cgroup_init_subsys.
++ */
++int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
++{
++	int i;
++	struct cgroup_subsys_state *css;
++
++	/* check name and function validity */
++	if (ss->name == NULL || strlen(ss->name) > MAX_CGROUP_TYPE_NAMELEN ||
++	    ss->create == NULL || ss->destroy == NULL)
++		return -EINVAL;
++
++	/*
++	 * we don't support callbacks in modular subsystems. this check is
++	 * before the ss->module check for consistency; a subsystem that could
++	 * be a module should still have no callbacks even if the user isn't
++	 * compiling it as one.
++	 */
++	if (ss->fork || ss->exit)
++		return -EINVAL;
++
++	/*
++	 * an optionally modular subsystem is built-in: we want to do nothing,
++	 * since cgroup_init_subsys will have already taken care of it.
++	 */
++	if (ss->module == NULL) {
++		/* a few sanity checks */
++		BUG_ON(ss->subsys_id >= CGROUP_BUILTIN_SUBSYS_COUNT);
++		BUG_ON(subsys[ss->subsys_id] != ss);
++		return 0;
++	}
++
++	/*
++	 * need to register a subsys id before anything else - for example,
++	 * init_cgroup_css needs it.
++	 */
++	mutex_lock(&cgroup_mutex);
++	/* find the first empty slot in the array */
++	for (i = CGROUP_BUILTIN_SUBSYS_COUNT; i < CGROUP_SUBSYS_COUNT; i++) {
++		if (subsys[i] == NULL)
++			break;
++	}
++	if (i == CGROUP_SUBSYS_COUNT) {
++		/* maximum number of subsystems already registered! */
++		mutex_unlock(&cgroup_mutex);
++		return -EBUSY;
++	}
++	/* assign ourselves the subsys_id */
++	ss->subsys_id = i;
++	subsys[i] = ss;
++
++	/*
++	 * no ss->create seems to need anything important in the ss struct, so
++	 * this can happen first (i.e. before the rootnode attachment).
++	 */
++	css = ss->create(ss, dummytop);
++	if (IS_ERR(css)) {
++		/* failure case - need to deassign the subsys[] slot. */
++		subsys[i] = NULL;
++		mutex_unlock(&cgroup_mutex);
++		return PTR_ERR(css);
++	}
++
++	list_add(&ss->sibling, &rootnode.subsys_list);
++	ss->root = &rootnode;
++
++	/* our new subsystem will be attached to the dummy hierarchy. */
++	init_cgroup_css(css, ss, dummytop);
++	/* init_idr must be after init_cgroup_css because it sets css->id. */
++	if (ss->use_id) {
++		int ret = cgroup_init_idr(ss, css);
++		if (ret) {
++			dummytop->subsys[ss->subsys_id] = NULL;
++			ss->destroy(ss, dummytop);
++			subsys[i] = NULL;
++			mutex_unlock(&cgroup_mutex);
++			return ret;
++		}
++	}
++
++	/*
++	 * Now we need to entangle the css into the existing css_sets. unlike
++	 * in cgroup_init_subsys, there are now multiple css_sets, so each one
++	 * will need a new pointer to it; done by iterating the css_set_table.
++	 * furthermore, modifying the existing css_sets will corrupt the hash
++	 * table state, so each changed css_set will need its hash recomputed.
++	 * this is all done under the css_set_lock.
++	 */
++	write_lock(&css_set_lock);
++	for (i = 0; i < CSS_SET_TABLE_SIZE; i++) {
++		struct css_set *cg;
++		struct hlist_node *node, *tmp;
++		struct hlist_head *bucket = &css_set_table[i], *new_bucket;
++
++		hlist_for_each_entry_safe(cg, node, tmp, bucket, hlist) {
++			/* skip entries that we already rehashed */
++			if (cg->subsys[ss->subsys_id])
++				continue;
++			/* remove existing entry */
++			hlist_del(&cg->hlist);
++			/* set new value */
++			cg->subsys[ss->subsys_id] = css;
++			/* recompute hash and restore entry */
++			new_bucket = css_set_hash(cg->subsys);
++			hlist_add_head(&cg->hlist, new_bucket);
++		}
++	}
++	write_unlock(&css_set_lock);
++
++	mutex_init(&ss->hierarchy_mutex);
++	lockdep_set_class(&ss->hierarchy_mutex, &ss->subsys_key);
++	ss->active = 1;
++
++	/*
++	 * pin the subsystem's module so it doesn't go away. this shouldn't
++	 * fail, since the module's initcall calls us.
++	 * TODO: with module unloading, move this elsewhere
++	 */
++	BUG_ON(!try_module_get(ss->module));
++
++	/* success! */
++	mutex_unlock(&cgroup_mutex);
++	return 0;
+ }
++EXPORT_SYMBOL_GPL(cgroup_load_subsys);
+ 
+ /**
+  * cgroup_init_early - cgroup initialization at system boot
+@@ -3364,7 +3505,7 @@ int __init cgroup_init(void)
+ 		if (!ss->early_init)
+ 			cgroup_init_subsys(ss);
+ 		if (ss->use_id)
+-			cgroup_subsys_init_idr(ss);
++			cgroup_init_idr(ss, init_css_set.subsys[ss->subsys_id]);
+ 	}
+ 
+ 	/* Add init_css_set to the hash table */
+@@ -4033,15 +4174,14 @@ static struct css_id *get_new_cssid(struct cgroup_subsys *ss, int depth)
+ 
+ }
+ 
+-static int __init cgroup_subsys_init_idr(struct cgroup_subsys *ss)
++static int __init_or_module cgroup_init_idr(struct cgroup_subsys *ss,
++					    struct cgroup_subsys_state *rootcss)
+ {
+ 	struct css_id *newid;
+-	struct cgroup_subsys_state *rootcss;
+ 
+ 	spin_lock_init(&ss->id_lock);
+ 	idr_init(&ss->idr);
+ 
+-	rootcss = init_css_set.subsys[ss->subsys_id];
+ 	newid = get_new_cssid(ss, 0);
+ 	if (IS_ERR(newid))
+ 		return PTR_ERR(newid);

commit aae8aab40367036931608fdaf9e2dc568b516f19
+Author: Ben Blum 
+Date:   Wed Mar 10 15:22:07 2010 -0800
+
+    cgroups: revamp subsys array
+    
+    This patch series provides the ability for cgroup subsystems to be
+    compiled as modules both within and outside the kernel tree.  This is
+    mainly useful for classifiers and subsystems that hook into components
+    that are already modules.  cls_cgroup and blkio-cgroup serve as the
+    example use cases for this feature.
+    
+    It provides an interface cgroup_load_subsys() and cgroup_unload_subsys()
+    which modular subsystems can use to register and depart during runtime.
+    The net_cls classifier subsystem serves as the example for a subsystem
+    which can be converted into a module using these changes.
+    
+    Patch #1 sets up the subsys[] array so its contents can be dynamic as
+    modules appear and (eventually) disappear.  Iterations over the array are
+    modified to handle when subsystems are absent, and the dynamic section of
+    the array is protected by cgroup_mutex.
+    
+    Patch #2 implements an interface for modules to load subsystems, called
+    cgroup_load_subsys, similar to cgroup_init_subsys, and adds a module
+    pointer in struct cgroup_subsys.
+    
+    Patch #3 adds a mechanism for unloading modular subsystems, which includes
+    a more advanced rework of the rudimentary reference counting introduced in
+    patch 2.
+    
+    Patch #4 modifies the net_cls subsystem, which already had some module
+    declarations, to be configurable as a module, which also serves as a
+    simple proof-of-concept.
+    
+    Part of implementing patches 2 and 4 involved updating css pointers in
+    each css_set when the module appears or leaves.  In doing this, it was
+    discovered that css_sets always remain linked to the dummy cgroup,
+    regardless of whether or not any subsystems are actually bound to it
+    (i.e., not mounted on an actual hierarchy).  The subsystem loading and
+    unloading code therefore should keep in mind the special cases where the
+    added subsystem is the only one in the dummy cgroup (and therefore all
+    css_sets need to be linked back into it) and where the removed subsys was
+    the only one in the dummy cgroup (and therefore all css_sets should be
+    unlinked from it) - however, as all css_sets always stay attached to the
+    dummy cgroup anyway, these cases are ignored.  Any fix that addresses this
+    issue should also make sure these cases are addressed in the subsystem
+    loading and unloading code.
+    
+    This patch:
+    
+    Make subsys[] able to be dynamically populated to support modular
+    subsystems
+    
+    This patch reworks the way the subsys[] array is used so that subsystems
+    can register themselves after boot time, and enables the internals of
+    cgroups to be able to handle when subsystems are not present or may
+    appear/disappear.
+    
+    Signed-off-by: Ben Blum 
+    Acked-by: Li Zefan 
+    Cc: Paul Menage 
+    Cc: "David S. Miller" 
+    Cc: KAMEZAWA Hiroyuki 
+    Cc: Lai Jiangshan 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
+index 14160b5b693f..28319a9fe569 100644
+--- a/include/linux/cgroup.h
++++ b/include/linux/cgroup.h
+@@ -40,13 +40,19 @@ extern int cgroupstats_build(struct cgroupstats *stats,
+ 
+ extern const struct file_operations proc_cgroup_operations;
+ 
+-/* Define the enumeration of all cgroup subsystems */
++/* Define the enumeration of all builtin cgroup subsystems */
+ #define SUBSYS(_x) _x ## _subsys_id,
+ enum cgroup_subsys_id {
+ #include 
+-	CGROUP_SUBSYS_COUNT
++	CGROUP_BUILTIN_SUBSYS_COUNT
+ };
+ #undef SUBSYS
++/*
++ * This define indicates the maximum number of subsystems that can be loaded
++ * at once. We limit to this many since cgroupfs_root has subsys_bits to keep
++ * track of all of them.
++ */
++#define CGROUP_SUBSYS_COUNT (BITS_PER_BYTE*sizeof(unsigned long))
+ 
+ /* Per-subsystem/per-cgroup state maintained by the system. */
+ struct cgroup_subsys_state {
+diff --git a/kernel/cgroup.c b/kernel/cgroup.c
+index cace83ddbcdc..c92fb9549358 100644
+--- a/kernel/cgroup.c
++++ b/kernel/cgroup.c
+@@ -57,10 +57,14 @@
+ 
+ static DEFINE_MUTEX(cgroup_mutex);
+ 
+-/* Generate an array of cgroup subsystem pointers */
++/*
++ * Generate an array of cgroup subsystem pointers. At boot time, this is
++ * populated up to CGROUP_BUILTIN_SUBSYS_COUNT, and modular subsystems are
++ * registered after that. The mutable section of this array is protected by
++ * cgroup_mutex.
++ */
+ #define SUBSYS(_x) &_x ## _subsys,
+-
+-static struct cgroup_subsys *subsys[] = {
++static struct cgroup_subsys *subsys[CGROUP_SUBSYS_COUNT] = {
+ #include 
+ };
+ 
+@@ -448,8 +452,11 @@ static struct css_set *find_existing_css_set(
+ 	struct hlist_node *node;
+ 	struct css_set *cg;
+ 
+-	/* Built the set of subsystem state objects that we want to
+-	 * see in the new css_set */
++	/*
++	 * Build the set of subsystem state objects that we want to see in the
++	 * new css_set. while subsystems can change globally, the entries here
++	 * won't change, so no need for locking.
++	 */
+ 	for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+ 		if (root->subsys_bits & (1UL << i)) {
+ 			/* Subsystem is in this hierarchy. So we want
+@@ -884,7 +891,9 @@ void cgroup_release_and_wakeup_rmdir(struct cgroup_subsys_state *css)
+ 	css_put(css);
+ }
+ 
+-
++/*
++ * Call with cgroup_mutex held.
++ */
+ static int rebind_subsystems(struct cgroupfs_root *root,
+ 			      unsigned long final_bits)
+ {
+@@ -892,6 +901,8 @@ static int rebind_subsystems(struct cgroupfs_root *root,
+ 	struct cgroup *cgrp = &root->top_cgroup;
+ 	int i;
+ 
++	BUG_ON(!mutex_is_locked(&cgroup_mutex));
++
+ 	removed_bits = root->actual_subsys_bits & ~final_bits;
+ 	added_bits = final_bits & ~root->actual_subsys_bits;
+ 	/* Check that any added subsystems are currently free */
+@@ -900,6 +911,12 @@ static int rebind_subsystems(struct cgroupfs_root *root,
+ 		struct cgroup_subsys *ss = subsys[i];
+ 		if (!(bit & added_bits))
+ 			continue;
++		/*
++		 * Nobody should tell us to do a subsys that doesn't exist:
++		 * parse_cgroupfs_options should catch that case and refcounts
++		 * ensure that subsystems won't disappear once selected.
++		 */
++		BUG_ON(ss == NULL);
+ 		if (ss->root != &rootnode) {
+ 			/* Subsystem isn't free */
+ 			return -EBUSY;
+@@ -919,6 +936,7 @@ static int rebind_subsystems(struct cgroupfs_root *root,
+ 		unsigned long bit = 1UL << i;
+ 		if (bit & added_bits) {
+ 			/* We're binding this subsystem to this hierarchy */
++			BUG_ON(ss == NULL);
+ 			BUG_ON(cgrp->subsys[i]);
+ 			BUG_ON(!dummytop->subsys[i]);
+ 			BUG_ON(dummytop->subsys[i]->cgroup != dummytop);
+@@ -932,6 +950,7 @@ static int rebind_subsystems(struct cgroupfs_root *root,
+ 			mutex_unlock(&ss->hierarchy_mutex);
+ 		} else if (bit & removed_bits) {
+ 			/* We're removing this subsystem */
++			BUG_ON(ss == NULL);
+ 			BUG_ON(cgrp->subsys[i] != dummytop->subsys[i]);
+ 			BUG_ON(cgrp->subsys[i]->cgroup != cgrp);
+ 			mutex_lock(&ss->hierarchy_mutex);
+@@ -944,6 +963,7 @@ static int rebind_subsystems(struct cgroupfs_root *root,
+ 			mutex_unlock(&ss->hierarchy_mutex);
+ 		} else if (bit & final_bits) {
+ 			/* Subsystem state should already exist */
++			BUG_ON(ss == NULL);
+ 			BUG_ON(!cgrp->subsys[i]);
+ 		} else {
+ 			/* Subsystem state shouldn't exist */
+@@ -986,14 +1006,18 @@ struct cgroup_sb_opts {
+ 
+ };
+ 
+-/* Convert a hierarchy specifier into a bitmask of subsystems and
+- * flags. */
++/*
++ * Convert a hierarchy specifier into a bitmask of subsystems and flags. Call
++ * with cgroup_mutex held to protect the subsys[] array.
++ */
+ static int parse_cgroupfs_options(char *data,
+ 				     struct cgroup_sb_opts *opts)
+ {
+ 	char *token, *o = data ?: "all";
+ 	unsigned long mask = (unsigned long)-1;
+ 
++	BUG_ON(!mutex_is_locked(&cgroup_mutex));
++
+ #ifdef CONFIG_CPUSETS
+ 	mask = ~(1UL << cpuset_subsys_id);
+ #endif
+@@ -1009,6 +1033,8 @@ static int parse_cgroupfs_options(char *data,
+ 			opts->subsys_bits = 0;
+ 			for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+ 				struct cgroup_subsys *ss = subsys[i];
++				if (ss == NULL)
++					continue;
+ 				if (!ss->disabled)
+ 					opts->subsys_bits |= 1ul << i;
+ 			}
+@@ -1053,6 +1079,8 @@ static int parse_cgroupfs_options(char *data,
+ 			int i;
+ 			for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+ 				ss = subsys[i];
++				if (ss == NULL)
++					continue;
+ 				if (!strcmp(token, ss->name)) {
+ 					if (!ss->disabled)
+ 						set_bit(i, &opts->subsys_bits);
+@@ -1306,7 +1334,9 @@ static int cgroup_get_sb(struct file_system_type *fs_type,
+ 	struct cgroupfs_root *new_root;
+ 
+ 	/* First find the desired set of subsystems */
++	mutex_lock(&cgroup_mutex);
+ 	ret = parse_cgroupfs_options(data, &opts);
++	mutex_unlock(&cgroup_mutex);
+ 	if (ret)
+ 		goto out_err;
+ 
+@@ -2918,8 +2948,14 @@ static void cgroup_lock_hierarchy(struct cgroupfs_root *root)
+ 	/* We need to take each hierarchy_mutex in a consistent order */
+ 	int i;
+ 
++	/*
++	 * No worry about a race with rebind_subsystems that might mess up the
++	 * locking order, since both parties are under cgroup_mutex.
++	 */
+ 	for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+ 		struct cgroup_subsys *ss = subsys[i];
++		if (ss == NULL)
++			continue;
+ 		if (ss->root == root)
+ 			mutex_lock(&ss->hierarchy_mutex);
+ 	}
+@@ -2931,6 +2967,8 @@ static void cgroup_unlock_hierarchy(struct cgroupfs_root *root)
+ 
+ 	for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+ 		struct cgroup_subsys *ss = subsys[i];
++		if (ss == NULL)
++			continue;
+ 		if (ss->root == root)
+ 			mutex_unlock(&ss->hierarchy_mutex);
+ 	}
+@@ -3054,11 +3092,16 @@ static int cgroup_has_css_refs(struct cgroup *cgrp)
+ 	 * synchronization other than RCU, and the subsystem linked
+ 	 * list isn't RCU-safe */
+ 	int i;
++	/*
++	 * We won't need to lock the subsys array, because the subsystems
++	 * we're concerned about aren't going anywhere since our cgroup root
++	 * has a reference on them.
++	 */
+ 	for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+ 		struct cgroup_subsys *ss = subsys[i];
+ 		struct cgroup_subsys_state *css;
+-		/* Skip subsystems not in this hierarchy */
+-		if (ss->root != cgrp->root)
++		/* Skip subsystems not present or not in this hierarchy */
++		if (ss == NULL || ss->root != cgrp->root)
+ 			continue;
+ 		css = cgrp->subsys[ss->subsys_id];
+ 		/* When called from check_for_release() it's possible
+@@ -3279,7 +3322,8 @@ int __init cgroup_init_early(void)
+ 	for (i = 0; i < CSS_SET_TABLE_SIZE; i++)
+ 		INIT_HLIST_HEAD(&css_set_table[i]);
+ 
+-	for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
++	/* at bootup time, we don't worry about modular subsystems */
++	for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
+ 		struct cgroup_subsys *ss = subsys[i];
+ 
+ 		BUG_ON(!ss->name);
+@@ -3314,7 +3358,8 @@ int __init cgroup_init(void)
+ 	if (err)
+ 		return err;
+ 
+-	for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
++	/* at bootup time, we don't worry about modular subsystems */
++	for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
+ 		struct cgroup_subsys *ss = subsys[i];
+ 		if (!ss->early_init)
+ 			cgroup_init_subsys(ss);
+@@ -3423,9 +3468,16 @@ static int proc_cgroupstats_show(struct seq_file *m, void *v)
+ 	int i;
+ 
+ 	seq_puts(m, "#subsys_name\thierarchy\tnum_cgroups\tenabled\n");
++	/*
++	 * ideally we don't want subsystems moving around while we do this.
++	 * cgroup_mutex is also necessary to guarantee an atomic snapshot of
++	 * subsys/hierarchy state.
++	 */
+ 	mutex_lock(&cgroup_mutex);
+ 	for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+ 		struct cgroup_subsys *ss = subsys[i];
++		if (ss == NULL)
++			continue;
+ 		seq_printf(m, "%s\t%d\t%d\t%d\n",
+ 			   ss->name, ss->root->hierarchy_id,
+ 			   ss->root->number_of_cgroups, !ss->disabled);
+@@ -3483,7 +3535,12 @@ void cgroup_fork_callbacks(struct task_struct *child)
+ {
+ 	if (need_forkexit_callback) {
+ 		int i;
+-		for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
++		/*
++		 * forkexit callbacks are only supported for builtin
++		 * subsystems, and the builtin section of the subsys array is
++		 * immutable, so we don't need to lock the subsys array here.
++		 */
++		for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
+ 			struct cgroup_subsys *ss = subsys[i];
+ 			if (ss->fork)
+ 				ss->fork(ss, child);
+@@ -3552,7 +3609,11 @@ void cgroup_exit(struct task_struct *tsk, int run_callbacks)
+ 	struct css_set *cg;
+ 
+ 	if (run_callbacks && need_forkexit_callback) {
+-		for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
++		/*
++		 * modular subsystems can't use callbacks, so no need to lock
++		 * the subsys array
++		 */
++		for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
+ 			struct cgroup_subsys *ss = subsys[i];
+ 			if (ss->exit)
+ 				ss->exit(ss, tsk);
+@@ -3844,8 +3905,11 @@ static int __init cgroup_disable(char *str)
+ 	while ((token = strsep(&str, ",")) != NULL) {
+ 		if (!*token)
+ 			continue;
+-
+-		for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
++		/*
++		 * cgroup_disable, being at boot time, can't know about module
++		 * subsystems, so we don't worry about them.
++		 */
++		for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
+ 			struct cgroup_subsys *ss = subsys[i];
+ 
+ 			if (!strcmp(token, ss->name)) {

commit 69ac59647e66c1b53fb98fe8b6d0f2099cffad60
+Author: Chaskiel Grundman 
+Date:   Fri Sep 9 13:01:54 2005 -0700
+
+    [PATCH] alpha: process_reloc_for_got confuses r_offset and r_addend
+    
+    arch/alpha/kernel/module.c:process_reloc_for_got(), which figures out how big
+    the .got section for a module should be, appears to be confusing r_offset (the
+    file offset that the relocation needs to be applied to) with r_addend (the
+    offset of the relocation's actual target address from the address of the
+    relocation's symbol).  Because of this, one .got entry is allocated for each
+    relocation instead of one each unique symbol/addend.
+    
+    In the module I am working with, this causes the .got section to be almost 10
+    times larger than it needs to be (75544 bytes instead of 7608 bytes).  As the
+    .got is accessed with global-pointer-relative instructions, it needs to be
+    within the 64k gp "zone", and a 75544 byte .got clearly does not fit.  The
+    result of this is that relocation overflows are detected during module load
+    and the load is aborted.
+    
+    Change struct got_entry/process_reloc_for_got to fix this.
+    
+    Acked-by: Richard Henderson 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/alpha/kernel/module.c b/arch/alpha/kernel/module.c
+index fc271e316a38..aac6d4b22f7a 100644
+--- a/arch/alpha/kernel/module.c
++++ b/arch/alpha/kernel/module.c
+@@ -47,7 +47,7 @@ module_free(struct module *mod, void *module_region)
+ 
+ struct got_entry {
+ 	struct got_entry *next;
+-	Elf64_Addr r_offset;
++	Elf64_Sxword r_addend;
+ 	int got_offset;
+ };
+ 
+@@ -57,14 +57,14 @@ process_reloc_for_got(Elf64_Rela *rela,
+ {
+ 	unsigned long r_sym = ELF64_R_SYM (rela->r_info);
+ 	unsigned long r_type = ELF64_R_TYPE (rela->r_info);
+-	Elf64_Addr r_offset = rela->r_offset;
++	Elf64_Sxword r_addend = rela->r_addend;
+ 	struct got_entry *g;
+ 
+ 	if (r_type != R_ALPHA_LITERAL)
+ 		return;
+ 
+ 	for (g = chains + r_sym; g ; g = g->next)
+-		if (g->r_offset == r_offset) {
++		if (g->r_addend == r_addend) {
+ 			if (g->got_offset == 0) {
+ 				g->got_offset = *poffset;
+ 				*poffset += 8;
+@@ -74,7 +74,7 @@ process_reloc_for_got(Elf64_Rela *rela,
+ 
+ 	g = kmalloc (sizeof (*g), GFP_KERNEL);
+ 	g->next = chains[r_sym].next;
+-	g->r_offset = r_offset;
++	g->r_addend = r_addend;
+ 	g->got_offset = *poffset;
+ 	*poffset += 8;
+ 	chains[r_sym].next = g;

commit 3e66d0138c05d9792f458b96581afdb314bc66d6
+Author: Christopher R. Baker 
+Date:   Sat Mar 8 11:00:20 2014 -0500
+
+    can: populate netdev::dev_id for udev discrimination
+    
+    My objective is to be able to totally discriminate CAN ports on multi-port
+    cards via udev so as to rename them to semantically interesting/unique names
+    for my system (e.g., "ecuCAN" and "auxCAN" instead of "can0" and "can1").
+    
+    The following patch assigns the dev_id field to match the channel number on all
+    multi-channel devices. I can only test my two-port Peak PCI card, but it works
+    as expected: ATTRS{dev_id} now expresses the port number and my udev rules now
+    unambiguously pick out and rename my individual CAN ports.
+    
+    Signed-off-by: Christopher R. Baker 
+    Tested-by: Oliver Hartkopp  [PEAK PCAN-USB pro and EMS PCMCIA]
+    Signed-off-by: Marc Kleine-Budde 
+
+diff --git a/drivers/net/can/sja1000/ems_pci.c b/drivers/net/can/sja1000/ems_pci.c
+index d790b874ca79..fd13dbf07d9c 100644
+--- a/drivers/net/can/sja1000/ems_pci.c
++++ b/drivers/net/can/sja1000/ems_pci.c
+@@ -323,6 +323,7 @@ static int ems_pci_add_card(struct pci_dev *pdev,
+ 			priv->cdr = EMS_PCI_CDR;
+ 
+ 			SET_NETDEV_DEV(dev, &pdev->dev);
++			dev->dev_id = i;
+ 
+ 			if (card->version == 1)
+ 				/* reset int flag of pita */
+diff --git a/drivers/net/can/sja1000/ems_pcmcia.c b/drivers/net/can/sja1000/ems_pcmcia.c
+index 9e535f2ef52b..381de998d2f1 100644
+--- a/drivers/net/can/sja1000/ems_pcmcia.c
++++ b/drivers/net/can/sja1000/ems_pcmcia.c
+@@ -211,6 +211,7 @@ static int ems_pcmcia_add_card(struct pcmcia_device *pdev, unsigned long base)
+ 		priv = netdev_priv(dev);
+ 		priv->priv = card;
+ 		SET_NETDEV_DEV(dev, &pdev->dev);
++		dev->dev_id = i;
+ 
+ 		priv->irq_flags = IRQF_SHARED;
+ 		dev->irq = pdev->irq;
+diff --git a/drivers/net/can/sja1000/kvaser_pci.c b/drivers/net/can/sja1000/kvaser_pci.c
+index c96eb14699d5..23b8e1324e25 100644
+--- a/drivers/net/can/sja1000/kvaser_pci.c
++++ b/drivers/net/can/sja1000/kvaser_pci.c
+@@ -270,6 +270,7 @@ static int kvaser_pci_add_chan(struct pci_dev *pdev, int channel,
+ 		 priv->reg_base, board->conf_addr, dev->irq);
+ 
+ 	SET_NETDEV_DEV(dev, &pdev->dev);
++	dev->dev_id = channel;
+ 
+ 	/* Register SJA1000 device */
+ 	err = register_sja1000dev(dev);
+diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c
+index 065ca49eb45e..c540e3d12e3d 100644
+--- a/drivers/net/can/sja1000/peak_pci.c
++++ b/drivers/net/can/sja1000/peak_pci.c
+@@ -642,6 +642,7 @@ static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 		icr |= chan->icr_mask;
+ 
+ 		SET_NETDEV_DEV(dev, &pdev->dev);
++		dev->dev_id = i;
+ 
+ 		/* Create chain of SJA1000 devices */
+ 		chan->prev_dev = pci_get_drvdata(pdev);
+diff --git a/drivers/net/can/sja1000/peak_pcmcia.c b/drivers/net/can/sja1000/peak_pcmcia.c
+index f7ad754dd2aa..dd56133cc461 100644
+--- a/drivers/net/can/sja1000/peak_pcmcia.c
++++ b/drivers/net/can/sja1000/peak_pcmcia.c
+@@ -550,6 +550,7 @@ static int pcan_add_channels(struct pcan_pccard *card)
+ 		priv = netdev_priv(netdev);
+ 		priv->priv = card;
+ 		SET_NETDEV_DEV(netdev, &pdev->dev);
++		netdev->dev_id = i;
+ 
+ 		priv->irq_flags = IRQF_SHARED;
+ 		netdev->irq = pdev->irq;
+diff --git a/drivers/net/can/sja1000/plx_pci.c b/drivers/net/can/sja1000/plx_pci.c
+index fbb61a0d901f..ec39b7cb2287 100644
+--- a/drivers/net/can/sja1000/plx_pci.c
++++ b/drivers/net/can/sja1000/plx_pci.c
+@@ -587,6 +587,7 @@ static int plx_pci_add_card(struct pci_dev *pdev,
+ 			priv->cdr = ci->cdr;
+ 
+ 			SET_NETDEV_DEV(dev, &pdev->dev);
++			dev->dev_id = i;
+ 
+ 			/* Register SJA1000 device */
+ 			err = register_sja1000dev(dev);
+diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c
+index 3766bd90f3ed..7d8c8f3672dd 100644
+--- a/drivers/net/can/softing/softing_main.c
++++ b/drivers/net/can/softing/softing_main.c
+@@ -833,6 +833,7 @@ static int softing_pdev_probe(struct platform_device *pdev)
+ 			ret = -ENOMEM;
+ 			goto netdev_failed;
+ 		}
++		netdev->dev_id = j;
+ 		priv = netdev_priv(card->net[j]);
+ 		priv->index = j;
+ 		ret = softing_netdev_register(netdev);
+diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c
+index 1f8ce91adbd3..b7c9e8b11460 100644
+--- a/drivers/net/can/usb/esd_usb2.c
++++ b/drivers/net/can/usb/esd_usb2.c
+@@ -1025,6 +1025,7 @@ static int esd_usb2_probe_one_net(struct usb_interface *intf, int index)
+ 	netdev->netdev_ops = &esd_usb2_netdev_ops;
+ 
+ 	SET_NETDEV_DEV(netdev, &intf->dev);
++	netdev->dev_id = index;
+ 
+ 	err = register_candev(netdev);
+ 	if (err) {
+diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c
+index ea596b53a5ae..4ca46edc061d 100644
+--- a/drivers/net/can/usb/kvaser_usb.c
++++ b/drivers/net/can/usb/kvaser_usb.c
+@@ -1530,6 +1530,7 @@ static int kvaser_usb_init_one(struct usb_interface *intf,
+ 	netdev->netdev_ops = &kvaser_usb_netdev_ops;
+ 
+ 	SET_NETDEV_DEV(netdev, &intf->dev);
++	netdev->dev_id = channel;
+ 
+ 	dev->nets[channel] = priv;
+ 
+diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
+index 93e4a55a6c23..644e6ab8a489 100644
+--- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c
++++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
+@@ -770,6 +770,7 @@ static int peak_usb_create_dev(struct peak_usb_adapter *peak_usb_adapter,
+ 	usb_set_intfdata(intf, dev);
+ 
+ 	SET_NETDEV_DEV(netdev, &intf->dev);
++	netdev->dev_id = ctrl_idx;
+ 
+ 	err = register_candev(netdev);
+ 	if (err) {

commit a14848275b04f3193b9d9e9c745a4fae37f11f2f
+Author: Justin Carlson 
+Date:   Sun Sep 24 11:52:12 2006 +0300
+
+    USB: add SeaLevel 2106 SeaLINK support to ftdi_sio
+    
+    We have a couple of these USB-Serial converters around; they're slightly
+    different from the 2104 models in that they can handle 500Kb/sec over RS422.
+    The existing ftdi driver seems to work just fine if we add in the
+    appropriate IDs.
+    
+    Patch is against 2.6.17.6, but should apply cleanly to pretty much
+    anything recent.
+    
+    From: Justin Carlson 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
+index b94d1bdb174e..e774a27c6c98 100644
+--- a/drivers/usb/serial/ftdi_sio.c
++++ b/drivers/usb/serial/ftdi_sio.c
+@@ -344,6 +344,7 @@ static struct usb_device_id id_table_combined [] = {
+ 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) },
+ 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2103_PID) },
+ 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2104_PID) },
++	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2106_PID) },
+ 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_1_PID) },
+ 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_2_PID) },
+ 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_1_PID) },
+diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
+index 5bada7fa28e9..f0edb87d2dd5 100644
+--- a/drivers/usb/serial/ftdi_sio.h
++++ b/drivers/usb/serial/ftdi_sio.h
+@@ -111,6 +111,7 @@
+ #define SEALEVEL_2102_PID	0x2102	/* SeaLINK+485 (2102) */
+ #define SEALEVEL_2103_PID	0x2103	/* SeaLINK+232I (2103) */
+ #define SEALEVEL_2104_PID	0x2104	/* SeaLINK+485I (2104) */
++#define SEALEVEL_2106_PID	0x9020	/* SeaLINK+422 (2106) */
+ #define SEALEVEL_2201_1_PID	0x2211	/* SeaPORT+2/232 (2201) Port 1 */
+ #define SEALEVEL_2201_2_PID	0x2221	/* SeaPORT+2/232 (2201) Port 2 */
+ #define SEALEVEL_2202_1_PID	0x2212	/* SeaPORT+2/485 (2202) Port 1 */

\ No newline at end of file diff --git a/detail/15.html b/detail/15.html new file mode 100644 index 0000000..be0be41 --- /dev/null +++ b/detail/15.html @@ -0,0 +1,16194 @@ +

Patches contributed by California Institute of Technology


commit aef5976fc52a497ac8161f54164c786c771d3ae8
+Author: Ira W. Snyder 
+Date:   Fri Jan 31 13:35:32 2014 -0800
+
+    tools/liblockdep: Add include directory to allow tests to compile
+    
+    All of the programs in the tests directory require the
+    liblockdep/mutex.h header in order to compile. Add the include directory
+    to the compiler options so that the tests can be built with the provided
+    Makefile.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Sasha Levin 
+
+diff --git a/tools/lib/lockdep/Makefile b/tools/lib/lockdep/Makefile
+index da8b7aa3d351..e8dd7497f57a 100644
+--- a/tools/lib/lockdep/Makefile
++++ b/tools/lib/lockdep/Makefile
+@@ -112,7 +112,7 @@ export Q VERBOSE
+ 
+ LIBLOCKDEP_VERSION = $(LL_VERSION).$(LL_PATCHLEVEL).$(LL_EXTRAVERSION)
+ 
+-INCLUDES = -I. -I/usr/local/include -I./uinclude $(CONFIG_INCLUDES)
++INCLUDES = -I. -I/usr/local/include -I./uinclude -I./include $(CONFIG_INCLUDES)
+ 
+ # Set compile option CFLAGS if not set elsewhere
+ CFLAGS ?= -g -DCONFIG_LOCKDEP -DCONFIG_STACKTRACE -DCONFIG_PROVE_LOCKING -DBITS_PER_LONG=__WORDSIZE -DLIBLOCKDEP_VERSION='"$(LIBLOCKDEP_VERSION)"' -rdynamic -O0 -g

commit 75759827bbe78e53330de2c5e061ecec7fa6f86e
+Author: Ira W. Snyder 
+Date:   Fri Jan 31 13:35:31 2014 -0800
+
+    tools/liblockdep: Fix include of asm/hash.h
+    
+    Commit 71ae8aac ("lib: introduce arch optimized hash library")
+    added an include to  for setting up an architecture
+    specific fast hash.
+    
+    This patch mirrors the fix used for perf, titled "tools: perf: util: fix
+    include for non x86 architectures".
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Sasha Levin 
+
+diff --git a/tools/lib/lockdep/uinclude/asm/hash.h b/tools/lib/lockdep/uinclude/asm/hash.h
+new file mode 100644
+index 000000000000..d82b170bb216
+--- /dev/null
++++ b/tools/lib/lockdep/uinclude/asm/hash.h
+@@ -0,0 +1,6 @@
++#ifndef __ASM_GENERIC_HASH_H
++#define __ASM_GENERIC_HASH_H
++
++/* Stub */
++
++#endif /* __ASM_GENERIC_HASH_H */

commit 367d896dafe1b5f49bee75d3a419b9eb9936ae26
+Author: Ira W. Snyder 
+Date:   Fri Jan 31 15:30:54 2014 -0800
+
+    tools/liblockdep: Fix initialization code path
+    
+    This makes initialization actually happen. Without it, initialization is
+    always skipped due to an incorrect conditional statement.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Sasha Levin 
+
+diff --git a/tools/lib/lockdep/preload.c b/tools/lib/lockdep/preload.c
+index f8465a811aa5..23bd69cb5ade 100644
+--- a/tools/lib/lockdep/preload.c
++++ b/tools/lib/lockdep/preload.c
+@@ -418,7 +418,7 @@ int pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
+ 
+ __attribute__((constructor)) static void init_preload(void)
+ {
+-	if (__init_state != done)
++	if (__init_state == done)
+ 		return;
+ 
+ #ifndef __GLIBC__

commit 73615c8669ef1c497c942cae0d5079b95824332a
+Author: Ira W. Snyder 
+Date:   Wed Jan 29 09:58:25 2014 -0800
+
+    can: janz-ican3: fix uninitialized variable warnings
+    
+    Analysis of the code shows that the struct ican3_msg variable cannot be
+    used uninitialized. Error conditions are checked and the loop terminates
+    before calling the ican3_handle_message() function with an uninitialized
+    value.
+    
+    Signed-off-by: Ira W. Snyder 
+    Acked-by: Oliver Hartkopp 
+    Signed-off-by: Marc Kleine-Budde 
+
+diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c
+index e24e6690d672..07f0ba03cd59 100644
+--- a/drivers/net/can/janz-ican3.c
++++ b/drivers/net/can/janz-ican3.c
+@@ -1322,7 +1322,7 @@ static int ican3_napi(struct napi_struct *napi, int budget)
+ 
+ 	/* process all communication messages */
+ 	while (true) {
+-		struct ican3_msg msg;
++		struct ican3_msg uninitialized_var(msg);
+ 		ret = ican3_recv_msg(mod, &msg);
+ 		if (ret)
+ 			break;

commit e21093ef6fb4cbecdf926102286dbe280ae965db
+Author: Ira W. Snyder 
+Date:   Tue Sep 11 15:58:15 2012 -0700
+
+    can: janz-ican3: fix support for older hardware revisions
+    
+    The Revision 1.0 Janz CMOD-IO Carrier Board does not have support for
+    the reset registers. To support older hardware, the code is changed to
+    use the hardware reset register on the Janz VMOD-ICAN3 hardware itself.
+    
+    Cc: stable 
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Marc Kleine-Budde 
+
+diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c
+index 98ee43819911..7edadee487ba 100644
+--- a/drivers/net/can/janz-ican3.c
++++ b/drivers/net/can/janz-ican3.c
+@@ -1391,7 +1391,6 @@ static irqreturn_t ican3_irq(int irq, void *dev_id)
+  */
+ static int ican3_reset_module(struct ican3_dev *mod)
+ {
+-	u8 val = 1 << mod->num;
+ 	unsigned long start;
+ 	u8 runold, runnew;
+ 
+@@ -1405,8 +1404,7 @@ static int ican3_reset_module(struct ican3_dev *mod)
+ 	runold = ioread8(mod->dpm + TARGET_RUNNING);
+ 
+ 	/* reset the module */
+-	iowrite8(val, &mod->ctrl->reset_assert);
+-	iowrite8(val, &mod->ctrl->reset_deassert);
++	iowrite8(0x00, &mod->dpmctrl->hwreset);
+ 
+ 	/* wait until the module has finished resetting and is running */
+ 	start = jiffies;

commit 3b5c6b9e49f78f07ebcd34b38c1185e57a0fd9eb
+Author: Ira W. Snyder 
+Date:   Wed Jul 18 15:33:18 2012 -0700
+
+    can: janz-ican3: add support for one shot mode
+    
+    The Janz VMOD-ICAN3 hardware has support for one shot packet
+    transmission. This means that a packet will be attempted to be sent
+    once, with no automatic retries.
+    
+    The SocketCAN core has a controller-wide setting for this mode:
+    CAN_CTRLMODE_ONE_SHOT. The Janz VMOD-ICAN3 hardware supports this flag
+    on a per-packet level, but the SocketCAN core does not.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Marc Kleine-Budde 
+
+diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c
+index e06ec403521a..98ee43819911 100644
+--- a/drivers/net/can/janz-ican3.c
++++ b/drivers/net/can/janz-ican3.c
+@@ -116,6 +116,7 @@
+ #define ICAN3_BUSERR_QUOTA_MAX	255
+ 
+ /* Janz ICAN3 CAN Frame Conversion */
++#define ICAN3_SNGL	0x02
+ #define ICAN3_ECHO	0x10
+ #define ICAN3_EFF_RTR	0x40
+ #define ICAN3_SFF_RTR	0x10
+@@ -848,6 +849,10 @@ static void can_frame_to_ican3(struct ican3_dev *mod,
+ 	desc->data[0] |= cf->can_dlc;
+ 	desc->data[1] |= ICAN3_ECHO;
+ 
++	/* support single transmission (no retries) mode */
++	if (mod->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
++		desc->data[1] |= ICAN3_SNGL;
++
+ 	if (cf->can_id & CAN_RTR_FLAG)
+ 		desc->data[0] |= ICAN3_EFF_RTR;
+ 
+@@ -1810,7 +1815,8 @@ static int __devinit ican3_probe(struct platform_device *pdev)
+ 	mod->can.do_set_mode = ican3_set_mode;
+ 	mod->can.do_get_berr_counter = ican3_get_berr_counter;
+ 	mod->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES
+-				    | CAN_CTRLMODE_BERR_REPORTING;
++				    | CAN_CTRLMODE_BERR_REPORTING
++				    | CAN_CTRLMODE_ONE_SHOT;
+ 
+ 	/* find our IRQ number */
+ 	mod->irq = platform_get_irq(pdev, 0);

commit 30df5888e4a244093c1b403b55ef889c97824f7b
+Author: Ira W. Snyder 
+Date:   Wed Jul 18 15:33:17 2012 -0700
+
+    can: janz-ican3: avoid firmware lockup caused by infinite bus error quota
+    
+    If the bus error quota is set to infinite and the host CPU cannot keep
+    up, the Janz VMOD-ICAN3 firmware will stop responding to control
+    messages until the controller is reset.
+    
+    The firmware will automatically stop sending bus error messages when the
+    quota is reached, and will only resume sending bus error messages when
+    the quota is re-set to a positive value.
+    
+    This limitation is worked around by setting the bus error quota to one
+    message, and then re-setting the quota to one message every time a bus
+    error message is received. By doing this, the firmware never stops
+    responding to control messages. The CAN bus can be reset without a
+    hard-reset of the controller card.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Marc Kleine-Budde 
+
+diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c
+index 47f8f6b4fef9..e06ec403521a 100644
+--- a/drivers/net/can/janz-ican3.c
++++ b/drivers/net/can/janz-ican3.c
+@@ -972,6 +972,16 @@ static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg)
+ 			stats->rx_errors++;
+ 		}
+ 
++		/*
++		 * The controller automatically disables bus-error interrupts
++		 * and therefore we must re-enable them.
++		 */
++		ret = ican3_set_buserror(mod, 1);
++		if (ret) {
++			dev_err(mod->dev, "unable to re-enable bus-error\n");
++			return ret;
++		}
++
+ 		/* bus error reporting is off, return immediately */
+ 		if (!(mod->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING))
+ 			return 0;
+@@ -1451,7 +1461,7 @@ static int __devinit ican3_startup_module(struct ican3_dev *mod)
+ 	}
+ 
+ 	/* default to "bus errors enabled" */
+-	ret = ican3_set_buserror(mod, ICAN3_BUSERR_QUOTA_MAX);
++	ret = ican3_set_buserror(mod, 1);
+ 	if (ret) {
+ 		dev_err(mod->dev, "unable to set bus-error\n");
+ 		return ret;

commit 83702f69272e4591a91a27eb58eade1bcd361dae
+Author: Ira W. Snyder 
+Date:   Thu Jul 19 08:54:42 2012 -0700
+
+    can: janz-ican3: fix support for CAN_RAW_RECV_OWN_MSGS
+    
+    The Janz VMOD-ICAN3 firmware does not support any sort of TX-done
+    notification or interrupt. The driver previously used the hardware
+    loopback to attempt to work around this deficiency, but this caused all
+    sockets to receive all messages, even if CAN_RAW_RECV_OWN_MSGS is off.
+    
+    Using the new function ican3_cmp_echo_skb(), we can drop the loopback
+    messages and return the original skbs. This fixes the issues with
+    CAN_RAW_RECV_OWN_MSGS.
+    
+    A private skb queue is used to store the echo skbs. This avoids the need
+    for any index management.
+    
+    Due to a lack of TX-error interrupts, bus errors are permanently
+    enabled, and are used as a TX-error notification. This is used to drop
+    an echo skb when transmission fails. Bus error packets are not generated
+    if the user has not enabled bus error reporting.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Marc Kleine-Budde 
+
+diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c
+index 4a5a8fb53a2f..47f8f6b4fef9 100644
+--- a/drivers/net/can/janz-ican3.c
++++ b/drivers/net/can/janz-ican3.c
+@@ -220,6 +220,9 @@ struct ican3_dev {
+ 	/* old and new style host interface */
+ 	unsigned int iftype;
+ 
++	/* queue for echo packets */
++	struct sk_buff_head echoq;
++
+ 	/*
+ 	 * Any function which changes the current DPM page must hold this
+ 	 * lock while it is performing data accesses. This ensures that the
+@@ -925,7 +928,7 @@ static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg)
+ 	struct net_device *dev = mod->ndev;
+ 	struct net_device_stats *stats = &dev->stats;
+ 	enum can_state state = mod->can.state;
+-	u8 status, isrc, rxerr, txerr;
++	u8 isrc, ecc, status, rxerr, txerr;
+ 	struct can_frame *cf;
+ 	struct sk_buff *skb;
+ 
+@@ -941,15 +944,43 @@ static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg)
+ 		return -EINVAL;
+ 	}
+ 
+-	skb = alloc_can_err_skb(dev, &cf);
+-	if (skb == NULL)
+-		return -ENOMEM;
+-
+ 	isrc = msg->data[0];
++	ecc = msg->data[2];
+ 	status = msg->data[3];
+ 	rxerr = msg->data[4];
+ 	txerr = msg->data[5];
+ 
++	/*
++	 * This hardware lacks any support other than bus error messages to
++	 * determine if packet transmission has failed.
++	 *
++	 * When TX errors happen, one echo skb needs to be dropped from the
++	 * front of the queue.
++	 *
++	 * A small bit of code is duplicated here and below, to avoid error
++	 * skb allocation when it will just be freed immediately.
++	 */
++	if (isrc == CEVTIND_BEI) {
++		int ret;
++		dev_dbg(mod->dev, "bus error interrupt\n");
++
++		/* TX error */
++		if (!(ecc & ECC_DIR)) {
++			kfree_skb(skb_dequeue(&mod->echoq));
++			stats->tx_errors++;
++		} else {
++			stats->rx_errors++;
++		}
++
++		/* bus error reporting is off, return immediately */
++		if (!(mod->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING))
++			return 0;
++	}
++
++	skb = alloc_can_err_skb(dev, &cf);
++	if (skb == NULL)
++		return -ENOMEM;
++
+ 	/* data overrun interrupt */
+ 	if (isrc == CEVTIND_DOI || isrc == CEVTIND_LOST) {
+ 		dev_dbg(mod->dev, "data overrun interrupt\n");
+@@ -978,9 +1009,6 @@ static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg)
+ 
+ 	/* bus error interrupt */
+ 	if (isrc == CEVTIND_BEI) {
+-		u8 ecc = msg->data[2];
+-
+-		dev_dbg(mod->dev, "bus error interrupt\n");
+ 		mod->can.can_stats.bus_error++;
+ 		cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+ 
+@@ -1000,12 +1028,8 @@ static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg)
+ 			break;
+ 		}
+ 
+-		if (!(ecc & ECC_DIR)) {
++		if (!(ecc & ECC_DIR))
+ 			cf->data[2] |= CAN_ERR_PROT_TX;
+-			stats->tx_errors++;
+-		} else {
+-			stats->rx_errors++;
+-		}
+ 
+ 		cf->data[6] = txerr;
+ 		cf->data[7] = rxerr;
+@@ -1089,6 +1113,88 @@ static void ican3_handle_message(struct ican3_dev *mod, struct ican3_msg *msg)
+ 	}
+ }
+ 
++/*
++ * The ican3 needs to store all echo skbs, and therefore cannot
++ * use the generic infrastructure for this.
++ */
++static void ican3_put_echo_skb(struct ican3_dev *mod, struct sk_buff *skb)
++{
++	struct sock *srcsk = skb->sk;
++
++	if (atomic_read(&skb->users) != 1) {
++		struct sk_buff *old_skb = skb;
++
++		skb = skb_clone(old_skb, GFP_ATOMIC);
++		kfree_skb(old_skb);
++		if (!skb)
++			return;
++	} else {
++		skb_orphan(skb);
++	}
++
++	skb->sk = srcsk;
++
++	/* save this skb for tx interrupt echo handling */
++	skb_queue_tail(&mod->echoq, skb);
++}
++
++static unsigned int ican3_get_echo_skb(struct ican3_dev *mod)
++{
++	struct sk_buff *skb = skb_dequeue(&mod->echoq);
++	struct can_frame *cf;
++	u8 dlc;
++
++	/* this should never trigger unless there is a driver bug */
++	if (!skb) {
++		netdev_err(mod->ndev, "BUG: echo skb not occupied\n");
++		return 0;
++	}
++
++	cf = (struct can_frame *)skb->data;
++	dlc = cf->can_dlc;
++
++	/* check flag whether this packet has to be looped back */
++	if (skb->pkt_type != PACKET_LOOPBACK) {
++		kfree_skb(skb);
++		return dlc;
++	}
++
++	skb->protocol = htons(ETH_P_CAN);
++	skb->pkt_type = PACKET_BROADCAST;
++	skb->ip_summed = CHECKSUM_UNNECESSARY;
++	skb->dev = mod->ndev;
++	netif_receive_skb(skb);
++	return dlc;
++}
++
++/*
++ * Compare an skb with an existing echo skb
++ *
++ * This function will be used on devices which have a hardware loopback.
++ * On these devices, this function can be used to compare a received skb
++ * with the saved echo skbs so that the hardware echo skb can be dropped.
++ *
++ * Returns true if the skb's are identical, false otherwise.
++ */
++static bool ican3_echo_skb_matches(struct ican3_dev *mod, struct sk_buff *skb)
++{
++	struct can_frame *cf = (struct can_frame *)skb->data;
++	struct sk_buff *echo_skb = skb_peek(&mod->echoq);
++	struct can_frame *echo_cf;
++
++	if (!echo_skb)
++		return false;
++
++	echo_cf = (struct can_frame *)echo_skb->data;
++	if (cf->can_id != echo_cf->can_id)
++		return false;
++
++	if (cf->can_dlc != echo_cf->can_dlc)
++		return false;
++
++	return memcmp(cf->data, echo_cf->data, cf->can_dlc) == 0;
++}
++
+ /*
+  * Check that there is room in the TX ring to transmit another skb
+  *
+@@ -1099,6 +1205,10 @@ static bool ican3_txok(struct ican3_dev *mod)
+ 	struct ican3_fast_desc __iomem *desc;
+ 	u8 control;
+ 
++	/* check that we have echo queue space */
++	if (skb_queue_len(&mod->echoq) >= ICAN3_TX_BUFFERS)
++		return false;
++
+ 	/* copy the control bits of the descriptor */
+ 	ican3_set_page(mod, mod->fasttx_start + (mod->fasttx_num / 16));
+ 	desc = mod->dpm + ((mod->fasttx_num % 16) * sizeof(*desc));
+@@ -1149,10 +1259,27 @@ static int ican3_recv_skb(struct ican3_dev *mod)
+ 	/* convert the ICAN3 frame into Linux CAN format */
+ 	ican3_to_can_frame(mod, &desc, cf);
+ 
+-	/* receive the skb, update statistics */
+-	netif_receive_skb(skb);
++	/*
++	 * If this is an ECHO frame received from the hardware loopback
++	 * feature, use the skb saved in the ECHO stack instead. This allows
++	 * the Linux CAN core to support CAN_RAW_RECV_OWN_MSGS correctly.
++	 *
++	 * Since this is a confirmation of a successfully transmitted packet
++	 * sent from this host, update the transmit statistics.
++	 *
++	 * Also, the netdevice queue needs to be allowed to send packets again.
++	 */
++	if (ican3_echo_skb_matches(mod, skb)) {
++		stats->tx_packets++;
++		stats->tx_bytes += ican3_get_echo_skb(mod);
++		kfree_skb(skb);
++		goto err_noalloc;
++	}
++
++	/* update statistics, receive the skb */
+ 	stats->rx_packets++;
+ 	stats->rx_bytes += cf->can_dlc;
++	netif_receive_skb(skb);
+ 
+ err_noalloc:
+ 	/* toggle the valid bit and return the descriptor to the ring */
+@@ -1175,13 +1302,13 @@ static int ican3_recv_skb(struct ican3_dev *mod)
+ static int ican3_napi(struct napi_struct *napi, int budget)
+ {
+ 	struct ican3_dev *mod = container_of(napi, struct ican3_dev, napi);
+-	struct ican3_msg msg;
+ 	unsigned long flags;
+ 	int received = 0;
+ 	int ret;
+ 
+ 	/* process all communication messages */
+ 	while (true) {
++		struct ican3_msg msg;
+ 		ret = ican3_recv_msg(mod, &msg);
+ 		if (ret)
+ 			break;
+@@ -1353,7 +1480,6 @@ static int __devinit ican3_startup_module(struct ican3_dev *mod)
+ static int ican3_open(struct net_device *ndev)
+ {
+ 	struct ican3_dev *mod = netdev_priv(ndev);
+-	u8 quota;
+ 	int ret;
+ 
+ 	/* open the CAN layer */
+@@ -1363,19 +1489,6 @@ static int ican3_open(struct net_device *ndev)
+ 		return ret;
+ 	}
+ 
+-	/* set the bus error generation state appropriately */
+-	if (mod->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
+-		quota = ICAN3_BUSERR_QUOTA_MAX;
+-	else
+-		quota = 0;
+-
+-	ret = ican3_set_buserror(mod, quota);
+-	if (ret) {
+-		dev_err(mod->dev, "unable to set bus-error\n");
+-		close_candev(ndev);
+-		return ret;
+-	}
+-
+ 	/* bring the bus online */
+ 	ret = ican3_set_bus_state(mod, true);
+ 	if (ret) {
+@@ -1407,6 +1520,9 @@ static int ican3_stop(struct net_device *ndev)
+ 		return ret;
+ 	}
+ 
++	/* drop all outstanding echo skbs */
++	skb_queue_purge(&mod->echoq);
++
+ 	/* close the CAN layer */
+ 	close_candev(ndev);
+ 	return 0;
+@@ -1415,7 +1531,6 @@ static int ican3_stop(struct net_device *ndev)
+ static int ican3_xmit(struct sk_buff *skb, struct net_device *ndev)
+ {
+ 	struct ican3_dev *mod = netdev_priv(ndev);
+-	struct net_device_stats *stats = &ndev->stats;
+ 	struct can_frame *cf = (struct can_frame *)skb->data;
+ 	struct ican3_fast_desc desc;
+ 	void __iomem *desc_addr;
+@@ -1428,8 +1543,7 @@ static int ican3_xmit(struct sk_buff *skb, struct net_device *ndev)
+ 
+ 	/* check that we can actually transmit */
+ 	if (!ican3_txok(mod)) {
+-		dev_err(mod->dev, "no free descriptors, stopping queue\n");
+-		netif_stop_queue(ndev);
++		dev_err(mod->dev, "BUG: no free descriptors\n");
+ 		spin_unlock_irqrestore(&mod->lock, flags);
+ 		return NETDEV_TX_BUSY;
+ 	}
+@@ -1443,6 +1557,14 @@ static int ican3_xmit(struct sk_buff *skb, struct net_device *ndev)
+ 	/* convert the Linux CAN frame into ICAN3 format */
+ 	can_frame_to_ican3(mod, cf, &desc);
+ 
++	/*
++	 * This hardware doesn't have TX-done notifications, so we'll try and
++	 * emulate it the best we can using ECHO skbs. Add the skb to the ECHO
++	 * stack. Upon packet reception, check if the ECHO skb and received
++	 * skb match, and use that to wake the queue.
++	 */
++	ican3_put_echo_skb(mod, skb);
++
+ 	/*
+ 	 * the programming manual says that you must set the IVALID bit, then
+ 	 * interrupt, then set the valid bit. Quite weird, but it seems to be
+@@ -1461,19 +1583,7 @@ static int ican3_xmit(struct sk_buff *skb, struct net_device *ndev)
+ 	mod->fasttx_num = (desc.control & DESC_WRAP) ? 0
+ 						     : (mod->fasttx_num + 1);
+ 
+-	/* update statistics */
+-	stats->tx_packets++;
+-	stats->tx_bytes += cf->can_dlc;
+-	kfree_skb(skb);
+-
+-	/*
+-	 * This hardware doesn't have TX-done notifications, so we'll try and
+-	 * emulate it the best we can using ECHO skbs. Get the next TX
+-	 * descriptor, and see if we have room to send. If not, stop the queue.
+-	 * It will be woken when the ECHO skb for the current packet is recv'd.
+-	 */
+-
+-	/* copy the control bits of the descriptor */
++	/* if there is no free descriptor space, stop the transmit queue */
+ 	if (!ican3_txok(mod))
+ 		netif_stop_queue(ndev);
+ 
+@@ -1669,6 +1779,7 @@ static int __devinit ican3_probe(struct platform_device *pdev)
+ 	mod->dev = &pdev->dev;
+ 	mod->num = pdata->modno;
+ 	netif_napi_add(ndev, &mod->napi, ican3_napi, ICAN3_RX_BUFFERS);
++	skb_queue_head_init(&mod->echoq);
+ 	spin_lock_init(&mod->lock);
+ 	init_completion(&mod->termination_comp);
+ 	init_completion(&mod->buserror_comp);

commit 88b587039c1ad4e7a981bea3269eeb02a1a2a14b
+Author: Ira W. Snyder 
+Date:   Thu Jul 19 08:54:18 2012 -0700
+
+    can: janz-ican3: fix error and byte counters
+    
+    The error and byte counter statistics were being incremented
+    incorrectly. For example, a TX error would be counted both in tx_errors
+    and rx_errors.
+    
+    This corrects the problem so that tx_errors and rx_errors are only
+    incremented for errors caused by packets sent to the bus. Error packets
+    generated by the driver are not counted.
+    
+    The byte counters are only increased for packets which are actually
+    transmitted or received from the bus. Error packets generated by the
+    driver are not counted.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Marc Kleine-Budde 
+
+diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c
+index b19aca591c7a..4a5a8fb53a2f 100644
+--- a/drivers/net/can/janz-ican3.c
++++ b/drivers/net/can/janz-ican3.c
+@@ -907,8 +907,8 @@ static void ican3_handle_msglost(struct ican3_dev *mod, struct ican3_msg *msg)
+ 	if (skb) {
+ 		cf->can_id |= CAN_ERR_CRTL;
+ 		cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
++		stats->rx_over_errors++;
+ 		stats->rx_errors++;
+-		stats->rx_bytes += cf->can_dlc;
+ 		netif_rx(skb);
+ 	}
+ }
+@@ -982,7 +982,6 @@ static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg)
+ 
+ 		dev_dbg(mod->dev, "bus error interrupt\n");
+ 		mod->can.can_stats.bus_error++;
+-		stats->rx_errors++;
+ 		cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+ 
+ 		switch (ecc & ECC_MASK) {
+@@ -1001,8 +1000,12 @@ static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg)
+ 			break;
+ 		}
+ 
+-		if ((ecc & ECC_DIR) == 0)
++		if (!(ecc & ECC_DIR)) {
+ 			cf->data[2] |= CAN_ERR_PROT_TX;
++			stats->tx_errors++;
++		} else {
++			stats->rx_errors++;
++		}
+ 
+ 		cf->data[6] = txerr;
+ 		cf->data[7] = rxerr;
+@@ -1028,8 +1031,6 @@ static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg)
+ 	}
+ 
+ 	mod->can.state = state;
+-	stats->rx_errors++;
+-	stats->rx_bytes += cf->can_dlc;
+ 	netif_rx(skb);
+ 	return 0;
+ }

commit 007890d726602c925077381500f0b633cfacd711
+Author: Ira W. Snyder 
+Date:   Wed Jul 18 15:33:14 2012 -0700
+
+    can: janz-ican3: drop invalid skbs
+    
+    The commit which added the janz-ican3 driver and commit
+    3ccd4c61 "can: Unify droping of invalid tx skbs and netdev stats" were
+    committed into mainline Linux during the same merge window.
+    
+    Therefore, the addition of this code to the janz-ican3 driver was
+    forgotten. This patch adds the expected code.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Marc Kleine-Budde 
+
+diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c
+index f41623d003e1..754b803fa926 100644
+--- a/drivers/net/can/janz-ican3.c
++++ b/drivers/net/can/janz-ican3.c
+@@ -1420,6 +1420,9 @@ static int ican3_xmit(struct sk_buff *skb, struct net_device *ndev)
+ 	void __iomem *desc_addr;
+ 	unsigned long flags;
+ 
++	if (can_dropped_invalid_skb(ndev, skb))
++		return NETDEV_TX_OK;
++
+ 	spin_lock_irqsave(&mod->lock, flags);
+ 
+ 	/* check that we can actually transmit */

commit 8456a9196f7696421eecffdbab5d785f852d95e8
+Author: Ira W. Snyder 
+Date:   Wed Jul 18 15:33:13 2012 -0700
+
+    can: janz-ican3: remove dead code
+    
+    The code which used this variable was removed during review, before the
+    driver was added to mainline Linux. It is now dead code, and can be
+    removed.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Marc Kleine-Budde 
+
+diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c
+index e7d1532d5f1b..f41623d003e1 100644
+--- a/drivers/net/can/janz-ican3.c
++++ b/drivers/net/can/janz-ican3.c
+@@ -235,7 +235,6 @@ struct ican3_dev {
+ 
+ 	/* fast host interface */
+ 	unsigned int fastrx_start;
+-	unsigned int fastrx_int;
+ 	unsigned int fastrx_num;
+ 	unsigned int fasttx_start;
+ 	unsigned int fasttx_num;
+@@ -454,7 +453,6 @@ static void __devinit ican3_init_fast_host_interface(struct ican3_dev *mod)
+ 	/* save the start recv page */
+ 	mod->fastrx_start = mod->free_page;
+ 	mod->fastrx_num = 0;
+-	mod->fastrx_int = 0;
+ 
+ 	/* build a single fast tohost queue descriptor */
+ 	memset(&desc, 0, sizeof(desc));

commit 30ec5a2cb17d78482de0cf9e38721410d48c086d
+Author: Ira W. Snyder 
+Date:   Fri Jan 6 11:29:19 2012 -0800
+
+    mtd: cfi: AMD/Fujitsu compatibles: add panic write support
+    
+    This allows the mtdoops driver to work on flash chips using the
+    AMD/Fujitsu compatible command set.
+    
+    As the code comments note, the locks used throughout the normal code
+    paths in the driver are ignored, so that the chance of writing out the
+    kernel's last messages are maximized.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Artem Bityutskiy 
+    Signed-off-by: David Woodhouse 
+
+diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
+index 8d70895a58d6..e2d94bb1d7c8 100644
+--- a/drivers/mtd/chips/cfi_cmdset_0002.c
++++ b/drivers/mtd/chips/cfi_cmdset_0002.c
+@@ -59,6 +59,9 @@ static void cfi_amdstd_resume (struct mtd_info *);
+ static int cfi_amdstd_reboot(struct notifier_block *, unsigned long, void *);
+ static int cfi_amdstd_secsi_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
+ 
++static int cfi_amdstd_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
++				  size_t *retlen, const u_char *buf);
++
+ static void cfi_amdstd_destroy(struct mtd_info *);
+ 
+ struct mtd_info *cfi_cmdset_0002(struct map_info *, int);
+@@ -443,6 +446,7 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
+ 	pr_debug("MTD %s(): write buffer size %d\n", __func__,
+ 			mtd->writebufsize);
+ 
++	mtd->panic_write = cfi_amdstd_panic_write;
+ 	mtd->reboot_notifier.notifier_call = cfi_amdstd_reboot;
+ 
+ 	if (cfi->cfi_mode==CFI_MODE_CFI){
+@@ -1562,6 +1566,242 @@ static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len,
+ 	return 0;
+ }
+ 
++/*
++ * Wait for the flash chip to become ready to write data
++ *
++ * This is only called during the panic_write() path. When panic_write()
++ * is called, the kernel is in the process of a panic, and will soon be
++ * dead. Therefore we don't take any locks, and attempt to get access
++ * to the chip as soon as possible.
++ */
++static int cfi_amdstd_panic_wait(struct map_info *map, struct flchip *chip,
++				 unsigned long adr)
++{
++	struct cfi_private *cfi = map->fldrv_priv;
++	int retries = 10;
++	int i;
++
++	/*
++	 * If the driver thinks the chip is idle, and no toggle bits
++	 * are changing, then the chip is actually idle for sure.
++	 */
++	if (chip->state == FL_READY && chip_ready(map, adr))
++		return 0;
++
++	/*
++	 * Try several times to reset the chip and then wait for it
++	 * to become idle. The upper limit of a few milliseconds of
++	 * delay isn't a big problem: the kernel is dying anyway. It
++	 * is more important to save the messages.
++	 */
++	while (retries > 0) {
++		const unsigned long timeo = (HZ / 1000) + 1;
++
++		/* send the reset command */
++		map_write(map, CMD(0xF0), chip->start);
++
++		/* wait for the chip to become ready */
++		for (i = 0; i < jiffies_to_usecs(timeo); i++) {
++			if (chip_ready(map, adr))
++				return 0;
++
++			udelay(1);
++		}
++	}
++
++	/* the chip never became ready */
++	return -EBUSY;
++}
++
++/*
++ * Write out one word of data to a single flash chip during a kernel panic
++ *
++ * This is only called during the panic_write() path. When panic_write()
++ * is called, the kernel is in the process of a panic, and will soon be
++ * dead. Therefore we don't take any locks, and attempt to get access
++ * to the chip as soon as possible.
++ *
++ * The implementation of this routine is intentionally similar to
++ * do_write_oneword(), in order to ease code maintenance.
++ */
++static int do_panic_write_oneword(struct map_info *map, struct flchip *chip,
++				  unsigned long adr, map_word datum)
++{
++	const unsigned long uWriteTimeout = (HZ / 1000) + 1;
++	struct cfi_private *cfi = map->fldrv_priv;
++	int retry_cnt = 0;
++	map_word oldd;
++	int ret = 0;
++	int i;
++
++	adr += chip->start;
++
++	ret = cfi_amdstd_panic_wait(map, chip, adr);
++	if (ret)
++		return ret;
++
++	pr_debug("MTD %s(): PANIC WRITE 0x%.8lx(0x%.8lx)\n",
++			__func__, adr, datum.x[0]);
++
++	/*
++	 * Check for a NOP for the case when the datum to write is already
++	 * present - it saves time and works around buggy chips that corrupt
++	 * data at other locations when 0xff is written to a location that
++	 * already contains 0xff.
++	 */
++	oldd = map_read(map, adr);
++	if (map_word_equal(map, oldd, datum)) {
++		pr_debug("MTD %s(): NOP\n", __func__);
++		goto op_done;
++	}
++
++	ENABLE_VPP(map);
++
++retry:
++	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
++	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
++	cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
++	map_write(map, datum, adr);
++
++	for (i = 0; i < jiffies_to_usecs(uWriteTimeout); i++) {
++		if (chip_ready(map, adr))
++			break;
++
++		udelay(1);
++	}
++
++	if (!chip_good(map, adr, datum)) {
++		/* reset on all failures. */
++		map_write(map, CMD(0xF0), chip->start);
++		/* FIXME - should have reset delay before continuing */
++
++		if (++retry_cnt <= MAX_WORD_RETRIES)
++			goto retry;
++
++		ret = -EIO;
++	}
++
++op_done:
++	DISABLE_VPP(map);
++	return ret;
++}
++
++/*
++ * Write out some data during a kernel panic
++ *
++ * This is used by the mtdoops driver to save the dying messages from a
++ * kernel which has panic'd.
++ *
++ * This routine ignores all of the locking used throughout the rest of the
++ * driver, in order to ensure that the data gets written out no matter what
++ * state this driver (and the flash chip itself) was in when the kernel crashed.
++ *
++ * The implementation of this routine is intentionally similar to
++ * cfi_amdstd_write_words(), in order to ease code maintenance.
++ */
++static int cfi_amdstd_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
++				  size_t *retlen, const u_char *buf)
++{
++	struct map_info *map = mtd->priv;
++	struct cfi_private *cfi = map->fldrv_priv;
++	unsigned long ofs, chipstart;
++	int ret = 0;
++	int chipnum;
++
++	*retlen = 0;
++	if (!len)
++		return 0;
++
++	chipnum = to >> cfi->chipshift;
++	ofs = to - (chipnum << cfi->chipshift);
++	chipstart = cfi->chips[chipnum].start;
++
++	/* If it's not bus aligned, do the first byte write */
++	if (ofs & (map_bankwidth(map) - 1)) {
++		unsigned long bus_ofs = ofs & ~(map_bankwidth(map) - 1);
++		int i = ofs - bus_ofs;
++		int n = 0;
++		map_word tmp_buf;
++
++		ret = cfi_amdstd_panic_wait(map, &cfi->chips[chipnum], bus_ofs);
++		if (ret)
++			return ret;
++
++		/* Load 'tmp_buf' with old contents of flash */
++		tmp_buf = map_read(map, bus_ofs + chipstart);
++
++		/* Number of bytes to copy from buffer */
++		n = min_t(int, len, map_bankwidth(map) - i);
++
++		tmp_buf = map_word_load_partial(map, tmp_buf, buf, i, n);
++
++		ret = do_panic_write_oneword(map, &cfi->chips[chipnum],
++					     bus_ofs, tmp_buf);
++		if (ret)
++			return ret;
++
++		ofs += n;
++		buf += n;
++		(*retlen) += n;
++		len -= n;
++
++		if (ofs >> cfi->chipshift) {
++			chipnum++;
++			ofs = 0;
++			if (chipnum == cfi->numchips)
++				return 0;
++		}
++	}
++
++	/* We are now aligned, write as much as possible */
++	while (len >= map_bankwidth(map)) {
++		map_word datum;
++
++		datum = map_word_load(map, buf);
++
++		ret = do_panic_write_oneword(map, &cfi->chips[chipnum],
++					     ofs, datum);
++		if (ret)
++			return ret;
++
++		ofs += map_bankwidth(map);
++		buf += map_bankwidth(map);
++		(*retlen) += map_bankwidth(map);
++		len -= map_bankwidth(map);
++
++		if (ofs >> cfi->chipshift) {
++			chipnum++;
++			ofs = 0;
++			if (chipnum == cfi->numchips)
++				return 0;
++
++			chipstart = cfi->chips[chipnum].start;
++		}
++	}
++
++	/* Write the trailing bytes if any */
++	if (len & (map_bankwidth(map) - 1)) {
++		map_word tmp_buf;
++
++		ret = cfi_amdstd_panic_wait(map, &cfi->chips[chipnum], ofs);
++		if (ret)
++			return ret;
++
++		tmp_buf = map_read(map, ofs + chipstart);
++
++		tmp_buf = map_word_load_partial(map, tmp_buf, buf, 0, len);
++
++		ret = do_panic_write_oneword(map, &cfi->chips[chipnum],
++					     ofs, tmp_buf);
++		if (ret)
++			return ret;
++
++		(*retlen) += len;
++	}
++
++	return 0;
++}
++
+ 
+ /*
+  * Handle devices with one erase region, that only implement

commit 6c15d7afbb2f9e2d3114b513306dae736b56f535
+Author: Ira Snyder 
+Date:   Thu Jan 26 11:00:14 2012 +0000
+
+    carma-fpga: fix race between data dumping and DMA callback
+    
+    When the system is under heavy load, we occasionally saw a problem where
+    the system would get a legitimate interrupt when they should be
+    disabled.
+    
+    This was caused by the data_dma_cb() DMA callback unconditionally
+    re-enabling FPGA interrupts even when data dumping is disabled. When
+    data dumping was re-enabled, the irq handler would fire while a DMA was
+    in progress. The "BUG_ON(priv->inflight != NULL);" during the second
+    invocation of the DMA callback caused the system to crash.
+    
+    To fix the issue, the priv->enabled boolean is moved under the
+    protection of the priv->lock spinlock. The DMA callback checks the
+    boolean to know whether to re-enable FPGA interrupts before it returns.
+    
+    Now that it is fixed, the driver keeps FPGA interrupts disabled when it
+    expects that they are disabled, fixing the bug.
+    
+    Signed-off-by: Ira W. Snyder 
+    Cc: Benjamin Herrenschmidt 
+    Signed-off-by: Benjamin Herrenschmidt 
+
+diff --git a/drivers/misc/carma/carma-fpga.c b/drivers/misc/carma/carma-fpga.c
+index 4fd896deda0d..0cfc5bf13fa5 100644
+--- a/drivers/misc/carma/carma-fpga.c
++++ b/drivers/misc/carma/carma-fpga.c
+@@ -560,6 +560,9 @@ static void data_enable_interrupts(struct fpga_device *priv)
+ 
+ 	/* flush the writes */
+ 	fpga_read_reg(priv, 0, MMAP_REG_STATUS);
++	fpga_read_reg(priv, 1, MMAP_REG_STATUS);
++	fpga_read_reg(priv, 2, MMAP_REG_STATUS);
++	fpga_read_reg(priv, 3, MMAP_REG_STATUS);
+ 
+ 	/* switch back to the external interrupt source */
+ 	iowrite32be(0x3F, priv->regs + SYS_IRQ_SOURCE_CTL);
+@@ -591,8 +594,12 @@ static void data_dma_cb(void *data)
+ 	list_move_tail(&priv->inflight->entry, &priv->used);
+ 	priv->inflight = NULL;
+ 
+-	/* clear the FPGA status and re-enable interrupts */
+-	data_enable_interrupts(priv);
++	/*
++	 * If data dumping is still enabled, then clear the FPGA
++	 * status registers and re-enable FPGA interrupts
++	 */
++	if (priv->enabled)
++		data_enable_interrupts(priv);
+ 
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+@@ -708,6 +715,15 @@ static irqreturn_t data_irq(int irq, void *dev_id)
+ 
+ 	spin_lock(&priv->lock);
+ 
++	/*
++	 * This is an error case that should never happen.
++	 *
++	 * If this driver has a bug and manages to re-enable interrupts while
++	 * a DMA is in progress, then we will hit this statement and should
++	 * start paying attention immediately.
++	 */
++	BUG_ON(priv->inflight != NULL);
++
+ 	/* hide the interrupt by switching the IRQ driver to GPIO */
+ 	data_disable_interrupts(priv);
+ 
+@@ -762,11 +778,15 @@ static irqreturn_t data_irq(int irq, void *dev_id)
+  */
+ static int data_device_enable(struct fpga_device *priv)
+ {
++	bool enabled;
+ 	u32 val;
+ 	int ret;
+ 
+ 	/* multiple enables are safe: they do nothing */
+-	if (priv->enabled)
++	spin_lock_irq(&priv->lock);
++	enabled = priv->enabled;
++	spin_unlock_irq(&priv->lock);
++	if (enabled)
+ 		return 0;
+ 
+ 	/* check that the FPGAs are programmed */
+@@ -797,6 +817,9 @@ static int data_device_enable(struct fpga_device *priv)
+ 		goto out_error;
+ 	}
+ 
++	/* prevent the FPGAs from generating interrupts */
++	data_disable_interrupts(priv);
++
+ 	/* hookup the irq handler */
+ 	ret = request_irq(priv->irq, data_irq, IRQF_SHARED, drv_name, priv);
+ 	if (ret) {
+@@ -804,11 +827,13 @@ static int data_device_enable(struct fpga_device *priv)
+ 		goto out_error;
+ 	}
+ 
+-	/* switch to the external FPGA IRQ line */
+-	data_enable_interrupts(priv);
+-
+-	/* success, we're enabled */
++	/* allow the DMA callback to re-enable FPGA interrupts */
++	spin_lock_irq(&priv->lock);
+ 	priv->enabled = true;
++	spin_unlock_irq(&priv->lock);
++
++	/* allow the FPGAs to generate interrupts */
++	data_enable_interrupts(priv);
+ 	return 0;
+ 
+ out_error:
+@@ -834,41 +859,40 @@ static int data_device_enable(struct fpga_device *priv)
+  */
+ static int data_device_disable(struct fpga_device *priv)
+ {
+-	int ret;
++	spin_lock_irq(&priv->lock);
+ 
+ 	/* allow multiple disable */
+-	if (!priv->enabled)
++	if (!priv->enabled) {
++		spin_unlock_irq(&priv->lock);
+ 		return 0;
++	}
++
++	/*
++	 * Mark the device disabled
++	 *
++	 * This stops DMA callbacks from re-enabling interrupts
++	 */
++	priv->enabled = false;
+ 
+-	/* switch to the internal GPIO IRQ line */
++	/* prevent the FPGAs from generating interrupts */
+ 	data_disable_interrupts(priv);
+ 
++	/* wait until all ongoing DMA has finished */
++	while (priv->inflight != NULL) {
++		spin_unlock_irq(&priv->lock);
++		wait_event(priv->wait, priv->inflight == NULL);
++		spin_lock_irq(&priv->lock);
++	}
++
++	spin_unlock_irq(&priv->lock);
++
+ 	/* unhook the irq handler */
+ 	free_irq(priv->irq, priv);
+ 
+-	/*
+-	 * wait for all outstanding DMA to complete
+-	 *
+-	 * Device interrupts are disabled, therefore another buffer cannot
+-	 * be marked inflight.
+-	 */
+-	ret = wait_event_interruptible(priv->wait, priv->inflight == NULL);
+-	if (ret)
+-		return ret;
+-
+ 	/* free the correlation table */
+ 	sg_free_table(&priv->corl_table);
+ 	priv->corl_nents = 0;
+ 
+-	/*
+-	 * We are taking the spinlock not to protect priv->enabled, but instead
+-	 * to make sure that there are no readers in the process of altering
+-	 * the free or used lists while we are setting this flag.
+-	 */
+-	spin_lock_irq(&priv->lock);
+-	priv->enabled = false;
+-	spin_unlock_irq(&priv->lock);
+-
+ 	/* free all buffers: the free and used lists are not being changed */
+ 	data_free_buffers(priv);
+ 	return 0;
+@@ -896,15 +920,6 @@ static unsigned int list_num_entries(struct list_head *list)
+ static int data_debug_show(struct seq_file *f, void *offset)
+ {
+ 	struct fpga_device *priv = f->private;
+-	int ret;
+-
+-	/*
+-	 * Lock the mutex first, so that we get an accurate value for enable
+-	 * Lock the spinlock next, to get accurate list counts
+-	 */
+-	ret = mutex_lock_interruptible(&priv->mutex);
+-	if (ret)
+-		return ret;
+ 
+ 	spin_lock_irq(&priv->lock);
+ 
+@@ -917,7 +932,6 @@ static int data_debug_show(struct seq_file *f, void *offset)
+ 	seq_printf(f, "num_dropped: %d\n", priv->num_dropped);
+ 
+ 	spin_unlock_irq(&priv->lock);
+-	mutex_unlock(&priv->mutex);
+ 	return 0;
+ }
+ 
+@@ -970,7 +984,13 @@ static ssize_t data_en_show(struct device *dev, struct device_attribute *attr,
+ 			    char *buf)
+ {
+ 	struct fpga_device *priv = dev_get_drvdata(dev);
+-	return snprintf(buf, PAGE_SIZE, "%u\n", priv->enabled);
++	int ret;
++
++	spin_lock_irq(&priv->lock);
++	ret = snprintf(buf, PAGE_SIZE, "%u\n", priv->enabled);
++	spin_unlock_irq(&priv->lock);
++
++	return ret;
+ }
+ 
+ static ssize_t data_en_set(struct device *dev, struct device_attribute *attr,
+@@ -986,6 +1006,7 @@ static ssize_t data_en_set(struct device *dev, struct device_attribute *attr,
+ 		return -EINVAL;
+ 	}
+ 
++	/* protect against concurrent enable/disable */
+ 	ret = mutex_lock_interruptible(&priv->mutex);
+ 	if (ret)
+ 		return ret;

commit 75ff85a81680e5779383aa6210a4f89ed76e40ec
+Author: Ira Snyder 
+Date:   Thu Jan 26 10:59:54 2012 +0000
+
+    carma-fpga: fix lockdep warning
+    
+    Lockdep occasionally complains with the message:
+    INFO: HARDIRQ-safe -> HARDIRQ-unsafe lock order detected
+    
+    This is caused by calling videobuf_dma_unmap() under spin_lock_irq(). To
+    fix the warning, we drop the lock before unmapping and freeing the
+    buffer.
+    
+    Signed-off-by: Ira W. Snyder 
+    Cc: Benjamin Herrenschmidt 
+    Signed-off-by: Benjamin Herrenschmidt 
+
+diff --git a/drivers/misc/carma/carma-fpga.c b/drivers/misc/carma/carma-fpga.c
+index 14e974b2a781..4fd896deda0d 100644
+--- a/drivers/misc/carma/carma-fpga.c
++++ b/drivers/misc/carma/carma-fpga.c
+@@ -1079,6 +1079,7 @@ static ssize_t data_read(struct file *filp, char __user *ubuf, size_t count,
+ 	struct fpga_reader *reader = filp->private_data;
+ 	struct fpga_device *priv = reader->priv;
+ 	struct list_head *used = &priv->used;
++	bool drop_buffer = false;
+ 	struct data_buf *dbuf;
+ 	size_t avail;
+ 	void *data;
+@@ -1166,10 +1167,12 @@ static ssize_t data_read(struct file *filp, char __user *ubuf, size_t count,
+ 	 * One of two things has happened, the device is disabled, or the
+ 	 * device has been reconfigured underneath us. In either case, we
+ 	 * should just throw away the buffer.
++	 *
++	 * Lockdep complains if this is done under the spinlock, so we
++	 * handle it during the unlock path.
+ 	 */
+ 	if (!priv->enabled || dbuf->size != priv->bufsize) {
+-		videobuf_dma_unmap(priv->dev, &dbuf->vb);
+-		data_free_buffer(dbuf);
++		drop_buffer = true;
+ 		goto out_unlock;
+ 	}
+ 
+@@ -1178,6 +1181,12 @@ static ssize_t data_read(struct file *filp, char __user *ubuf, size_t count,
+ 
+ out_unlock:
+ 	spin_unlock_irq(&priv->lock);
++
++	if (drop_buffer) {
++		videobuf_dma_unmap(priv->dev, &dbuf->vb);
++		data_free_buffer(dbuf);
++	}
++
+ 	return count;
+ }
+ 

commit 40c8cefaaf12734327db7199a56e60058d98e7b6
+Author: Ira Snyder 
+Date:   Fri Jan 6 12:34:07 2012 +0000
+
+    powerpc: Fix kernel log of oops/panic instruction dump
+    
+    A kernel oops/panic prints an instruction dump showing several
+    instructions before and after the instruction which caused the
+    oops/panic.
+    
+    The code intended that the faulting instruction be enclosed in angle
+    brackets, however a bug caused the faulting instruction to be
+    interpreted by printk() as the message log level.
+    
+    To fix this, the KERN_CONT log level is added before the actual text of
+    the printed message.
+    
+    === Before the patch ===
+    
+    [ 1081.587266] Instruction dump:
+    [ 1081.590236] 7c000110 7c0000f8 5400077c 552907f6 7d290378 992b0003 4e800020 38000001
+    [ 1081.598034] 3d20c03a 9009a114 7c0004ac 39200000
+    [ 1081.602500]  4e800020 3803ffd0 2b800009
+    
+    <4>[ 1081.587266] Instruction dump:
+    <4>[ 1081.590236] 7c000110 7c0000f8 5400077c 552907f6 7d290378 992b0003 4e800020 38000001
+    <4>[ 1081.598034] 3d20c03a 9009a114 7c0004ac 39200000
+    <98090000>[ 1081.602500]  4e800020 3803ffd0 2b800009
+    
+    === After the patch ===
+    
+    [   51.385216] Instruction dump:
+    [   51.388186] 7c000110 7c0000f8 5400077c 552907f6 7d290378 992b0003 4e800020 38000001
+    [   51.395986] 3d20c03a 9009a114 7c0004ac 39200000 <98090000> 4e800020 3803ffd0 2b800009
+    
+    <4>[   51.385216] Instruction dump:
+    <4>[   51.388186] 7c000110 7c0000f8 5400077c 552907f6 7d290378 992b0003 4e800020 38000001
+    <4>[   51.395986] 3d20c03a 9009a114 7c0004ac 39200000 <98090000> 4e800020 3803ffd0 2b800009
+    
+    Signed-off-by: Ira W. Snyder 
+    Cc: Paul Mackerras 
+    Cc: Benjamin Herrenschmidt 
+    Cc: linuxppc-dev@lists.ozlabs.org
+    Signed-off-by: Benjamin Herrenschmidt 
+
+diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
+index ebe5766781aa..d817ab018486 100644
+--- a/arch/powerpc/kernel/process.c
++++ b/arch/powerpc/kernel/process.c
+@@ -566,12 +566,12 @@ static void show_instructions(struct pt_regs *regs)
+ 		 */
+ 		if (!__kernel_text_address(pc) ||
+ 		     __get_user(instr, (unsigned int __user *)pc)) {
+-			printk("XXXXXXXX ");
++			printk(KERN_CONT "XXXXXXXX ");
+ 		} else {
+ 			if (regs->nip == pc)
+-				printk("<%08x> ", instr);
++				printk(KERN_CONT "<%08x> ", instr);
+ 			else
+-				printk("%08x ", instr);
++				printk(KERN_CONT "%08x ", instr);
+ 		}
+ 
+ 		pc += sizeof(int);

commit 0e1d715b5b982ee0099f3fbf6ad47dc8bda518a6
+Author: Ira Snyder 
+Date:   Fri Feb 11 13:34:30 2011 +0000
+
+    misc: Add CARMA DATA-FPGA Programmer support
+    
+    This adds support for programming the data processing FPGAs on the OVRO
+    CARMA board. These FPGAs have a special programming sequence that
+    requires that we program the Freescale DMA engine, which is only
+    available inside the kernel.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Benjamin Herrenschmidt 
+
+diff --git a/drivers/misc/carma/Kconfig b/drivers/misc/carma/Kconfig
+index 4be183f7e6f1..c90370ed712b 100644
+--- a/drivers/misc/carma/Kconfig
++++ b/drivers/misc/carma/Kconfig
+@@ -7,3 +7,11 @@ config CARMA_FPGA
+ 	  Say Y here to include support for communicating with the data
+ 	  processing FPGAs on the OVRO CARMA board.
+ 
++config CARMA_FPGA_PROGRAM
++	tristate "CARMA DATA-FPGA Programmer"
++	depends on FSL_SOC && PPC_83xx && MEDIA_SUPPORT && HAS_DMA && FSL_DMA
++	select VIDEOBUF_DMA_SG
++	default n
++	help
++	  Say Y here to include support for programming the data processing
++	  FPGAs on the OVRO CARMA board.
+diff --git a/drivers/misc/carma/Makefile b/drivers/misc/carma/Makefile
+index 0b69fa787953..ff36ac2ce534 100644
+--- a/drivers/misc/carma/Makefile
++++ b/drivers/misc/carma/Makefile
+@@ -1 +1,2 @@
+ obj-$(CONFIG_CARMA_FPGA)		+= carma-fpga.o
++obj-$(CONFIG_CARMA_FPGA_PROGRAM)	+= carma-fpga-program.o
+diff --git a/drivers/misc/carma/carma-fpga-program.c b/drivers/misc/carma/carma-fpga-program.c
+new file mode 100644
+index 000000000000..7ce6065dc20e
+--- /dev/null
++++ b/drivers/misc/carma/carma-fpga-program.c
+@@ -0,0 +1,1141 @@
++/*
++ * CARMA Board DATA-FPGA Programmer
++ *
++ * Copyright (c) 2009-2011 Ira W. Snyder 
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++
++/* MPC8349EMDS specific get_immrbase() */
++#include 
++
++static const char drv_name[] = "carma-fpga-program";
++
++/*
++ * Firmware images are always this exact size
++ *
++ * 12849552 bytes for a CARMA Digitizer Board (EP2S90 FPGAs)
++ * 18662880 bytes for a CARMA Correlator Board (EP2S130 FPGAs)
++ */
++#define FW_SIZE_EP2S90		12849552
++#define FW_SIZE_EP2S130		18662880
++
++struct fpga_dev {
++	struct miscdevice miscdev;
++
++	/* Reference count */
++	struct kref ref;
++
++	/* Device Registers */
++	struct device *dev;
++	void __iomem *regs;
++	void __iomem *immr;
++
++	/* Freescale DMA Device */
++	struct dma_chan *chan;
++
++	/* Interrupts */
++	int irq, status;
++	struct completion completion;
++
++	/* FPGA Bitfile */
++	struct mutex lock;
++
++	struct videobuf_dmabuf vb;
++	bool vb_allocated;
++
++	/* max size and written bytes */
++	size_t fw_size;
++	size_t bytes;
++};
++
++/*
++ * FPGA Bitfile Helpers
++ */
++
++/**
++ * fpga_drop_firmware_data() - drop the bitfile image from memory
++ * @priv: the driver's private data structure
++ *
++ * LOCKING: must hold priv->lock
++ */
++static void fpga_drop_firmware_data(struct fpga_dev *priv)
++{
++	videobuf_dma_free(&priv->vb);
++	priv->vb_allocated = false;
++	priv->bytes = 0;
++}
++
++/*
++ * Private Data Reference Count
++ */
++
++static void fpga_dev_remove(struct kref *ref)
++{
++	struct fpga_dev *priv = container_of(ref, struct fpga_dev, ref);
++
++	/* free any firmware image that was not programmed */
++	fpga_drop_firmware_data(priv);
++
++	mutex_destroy(&priv->lock);
++	kfree(priv);
++}
++
++/*
++ * LED Trigger (could be a seperate module)
++ */
++
++/*
++ * NOTE: this whole thing does have the problem that whenever the led's are
++ * NOTE: first set to use the fpga trigger, they could be in the wrong state
++ */
++
++DEFINE_LED_TRIGGER(ledtrig_fpga);
++
++static void ledtrig_fpga_programmed(bool enabled)
++{
++	if (enabled)
++		led_trigger_event(ledtrig_fpga, LED_FULL);
++	else
++		led_trigger_event(ledtrig_fpga, LED_OFF);
++}
++
++/*
++ * FPGA Register Helpers
++ */
++
++/* Register Definitions */
++#define FPGA_CONFIG_CONTROL		0x40
++#define FPGA_CONFIG_STATUS		0x44
++#define FPGA_CONFIG_FIFO_SIZE		0x48
++#define FPGA_CONFIG_FIFO_USED		0x4C
++#define FPGA_CONFIG_TOTAL_BYTE_COUNT	0x50
++#define FPGA_CONFIG_CUR_BYTE_COUNT	0x54
++
++#define FPGA_FIFO_ADDRESS		0x3000
++
++static int fpga_fifo_size(void __iomem *regs)
++{
++	return ioread32be(regs + FPGA_CONFIG_FIFO_SIZE);
++}
++
++#define CFG_STATUS_ERR_MASK	0xfffe
++
++static int fpga_config_error(void __iomem *regs)
++{
++	return ioread32be(regs + FPGA_CONFIG_STATUS) & CFG_STATUS_ERR_MASK;
++}
++
++static int fpga_fifo_empty(void __iomem *regs)
++{
++	return ioread32be(regs + FPGA_CONFIG_FIFO_USED) == 0;
++}
++
++static void fpga_fifo_write(void __iomem *regs, u32 val)
++{
++	iowrite32be(val, regs + FPGA_FIFO_ADDRESS);
++}
++
++static void fpga_set_byte_count(void __iomem *regs, u32 count)
++{
++	iowrite32be(count, regs + FPGA_CONFIG_TOTAL_BYTE_COUNT);
++}
++
++#define CFG_CTL_ENABLE	(1 << 0)
++#define CFG_CTL_RESET	(1 << 1)
++#define CFG_CTL_DMA	(1 << 2)
++
++static void fpga_programmer_enable(struct fpga_dev *priv, bool dma)
++{
++	u32 val;
++
++	val = (dma) ? (CFG_CTL_ENABLE | CFG_CTL_DMA) : CFG_CTL_ENABLE;
++	iowrite32be(val, priv->regs + FPGA_CONFIG_CONTROL);
++}
++
++static void fpga_programmer_disable(struct fpga_dev *priv)
++{
++	iowrite32be(0x0, priv->regs + FPGA_CONFIG_CONTROL);
++}
++
++static void fpga_dump_registers(struct fpga_dev *priv)
++{
++	u32 control, status, size, used, total, curr;
++
++	/* good status: do nothing */
++	if (priv->status == 0)
++		return;
++
++	/* Dump all status registers */
++	control = ioread32be(priv->regs + FPGA_CONFIG_CONTROL);
++	status = ioread32be(priv->regs + FPGA_CONFIG_STATUS);
++	size = ioread32be(priv->regs + FPGA_CONFIG_FIFO_SIZE);
++	used = ioread32be(priv->regs + FPGA_CONFIG_FIFO_USED);
++	total = ioread32be(priv->regs + FPGA_CONFIG_TOTAL_BYTE_COUNT);
++	curr = ioread32be(priv->regs + FPGA_CONFIG_CUR_BYTE_COUNT);
++
++	dev_err(priv->dev, "Configuration failed, dumping status registers\n");
++	dev_err(priv->dev, "Control:    0x%.8x\n", control);
++	dev_err(priv->dev, "Status:     0x%.8x\n", status);
++	dev_err(priv->dev, "FIFO Size:  0x%.8x\n", size);
++	dev_err(priv->dev, "FIFO Used:  0x%.8x\n", used);
++	dev_err(priv->dev, "FIFO Total: 0x%.8x\n", total);
++	dev_err(priv->dev, "FIFO Curr:  0x%.8x\n", curr);
++}
++
++/*
++ * FPGA Power Supply Code
++ */
++
++#define CTL_PWR_CONTROL		0x2006
++#define CTL_PWR_STATUS		0x200A
++#define CTL_PWR_FAIL		0x200B
++
++#define PWR_CONTROL_ENABLE	0x01
++
++#define PWR_STATUS_ERROR_MASK	0x10
++#define PWR_STATUS_GOOD		0x0f
++
++/*
++ * Determine if the FPGA power is good for all supplies
++ */
++static bool fpga_power_good(struct fpga_dev *priv)
++{
++	u8 val;
++
++	val = ioread8(priv->regs + CTL_PWR_STATUS);
++	if (val & PWR_STATUS_ERROR_MASK)
++		return false;
++
++	return val == PWR_STATUS_GOOD;
++}
++
++/*
++ * Disable the FPGA power supplies
++ */
++static void fpga_disable_power_supplies(struct fpga_dev *priv)
++{
++	unsigned long start;
++	u8 val;
++
++	iowrite8(0x0, priv->regs + CTL_PWR_CONTROL);
++
++	/*
++	 * Wait 500ms for the power rails to discharge
++	 *
++	 * Without this delay, the CTL-CPLD state machine can get into a
++	 * state where it is waiting for the power-goods to assert, but they
++	 * never do. This only happens when enabling and disabling the
++	 * power sequencer very rapidly.
++	 *
++	 * The loop below will also wait for the power goods to de-assert,
++	 * but testing has shown that they are always disabled by the time
++	 * the sleep completes. However, omitting the sleep and only waiting
++	 * for the power-goods to de-assert was not sufficient to ensure
++	 * that the power sequencer would not wedge itself.
++	 */
++	msleep(500);
++
++	start = jiffies;
++	while (time_before(jiffies, start + HZ)) {
++		val = ioread8(priv->regs + CTL_PWR_STATUS);
++		if (!(val & PWR_STATUS_GOOD))
++			break;
++
++		usleep_range(5000, 10000);
++	}
++
++	val = ioread8(priv->regs + CTL_PWR_STATUS);
++	if (val & PWR_STATUS_GOOD) {
++		dev_err(priv->dev, "power disable failed: "
++				   "power goods: status 0x%.2x\n", val);
++	}
++
++	if (val & PWR_STATUS_ERROR_MASK) {
++		dev_err(priv->dev, "power disable failed: "
++				   "alarm bit set: status 0x%.2x\n", val);
++	}
++}
++
++/**
++ * fpga_enable_power_supplies() - enable the DATA-FPGA power supplies
++ * @priv: the driver's private data structure
++ *
++ * Enable the DATA-FPGA power supplies, waiting up to 1 second for
++ * them to enable successfully.
++ *
++ * Returns 0 on success, -ERRNO otherwise
++ */
++static int fpga_enable_power_supplies(struct fpga_dev *priv)
++{
++	unsigned long start = jiffies;
++
++	if (fpga_power_good(priv)) {
++		dev_dbg(priv->dev, "power was already good\n");
++		return 0;
++	}
++
++	iowrite8(PWR_CONTROL_ENABLE, priv->regs + CTL_PWR_CONTROL);
++	while (time_before(jiffies, start + HZ)) {
++		if (fpga_power_good(priv))
++			return 0;
++
++		usleep_range(5000, 10000);
++	}
++
++	return fpga_power_good(priv) ? 0 : -ETIMEDOUT;
++}
++
++/*
++ * Determine if the FPGA power supplies are all enabled
++ */
++static bool fpga_power_enabled(struct fpga_dev *priv)
++{
++	u8 val;
++
++	val = ioread8(priv->regs + CTL_PWR_CONTROL);
++	if (val & PWR_CONTROL_ENABLE)
++		return true;
++
++	return false;
++}
++
++/*
++ * Determine if the FPGA's are programmed and running correctly
++ */
++static bool fpga_running(struct fpga_dev *priv)
++{
++	if (!fpga_power_good(priv))
++		return false;
++
++	/* Check the config done bit */
++	return ioread32be(priv->regs + FPGA_CONFIG_STATUS) & (1 << 18);
++}
++
++/*
++ * FPGA Programming Code
++ */
++
++/**
++ * fpga_program_block() - put a block of data into the programmer's FIFO
++ * @priv: the driver's private data structure
++ * @buf: the data to program
++ * @count: the length of data to program (must be a multiple of 4 bytes)
++ *
++ * Returns 0 on success, -ERRNO otherwise
++ */
++static int fpga_program_block(struct fpga_dev *priv, void *buf, size_t count)
++{
++	u32 *data = buf;
++	int size = fpga_fifo_size(priv->regs);
++	int i, len;
++	unsigned long timeout;
++
++	/* enforce correct data length for the FIFO */
++	BUG_ON(count % 4 != 0);
++
++	while (count > 0) {
++
++		/* Get the size of the block to write (maximum is FIFO_SIZE) */
++		len = min_t(size_t, count, size);
++		timeout = jiffies + HZ / 4;
++
++		/* Write the block */
++		for (i = 0; i < len / 4; i++)
++			fpga_fifo_write(priv->regs, data[i]);
++
++		/* Update the amounts left */
++		count -= len;
++		data += len / 4;
++
++		/* Wait for the fifo to empty */
++		while (true) {
++
++			if (fpga_fifo_empty(priv->regs)) {
++				break;
++			} else {
++				dev_dbg(priv->dev, "Fifo not empty\n");
++				cpu_relax();
++			}
++
++			if (fpga_config_error(priv->regs)) {
++				dev_err(priv->dev, "Error detected\n");
++				return -EIO;
++			}
++
++			if (time_after(jiffies, timeout)) {
++				dev_err(priv->dev, "Fifo drain timeout\n");
++				return -ETIMEDOUT;
++			}
++
++			usleep_range(5000, 10000);
++		}
++	}
++
++	return 0;
++}
++
++/**
++ * fpga_program_cpu() - program the DATA-FPGA's using the CPU
++ * @priv: the driver's private data structure
++ *
++ * This is useful when the DMA programming method fails. It is possible to
++ * wedge the Freescale DMA controller such that the DMA programming method
++ * always fails. This method has always succeeded.
++ *
++ * Returns 0 on success, -ERRNO otherwise
++ */
++static noinline int fpga_program_cpu(struct fpga_dev *priv)
++{
++	int ret;
++
++	/* Disable the programmer */
++	fpga_programmer_disable(priv);
++
++	/* Set the total byte count */
++	fpga_set_byte_count(priv->regs, priv->bytes);
++	dev_dbg(priv->dev, "total byte count %u bytes\n", priv->bytes);
++
++	/* Enable the controller for programming */
++	fpga_programmer_enable(priv, false);
++	dev_dbg(priv->dev, "enabled the controller\n");
++
++	/* Write each chunk of the FPGA bitfile to FPGA programmer */
++	ret = fpga_program_block(priv, priv->vb.vaddr, priv->bytes);
++	if (ret)
++		goto out_disable_controller;
++
++	/* Wait for the interrupt handler to signal that programming finished */
++	ret = wait_for_completion_timeout(&priv->completion, 2 * HZ);
++	if (!ret) {
++		dev_err(priv->dev, "Timed out waiting for completion\n");
++		ret = -ETIMEDOUT;
++		goto out_disable_controller;
++	}
++
++	/* Retrieve the status from the interrupt handler */
++	ret = priv->status;
++
++out_disable_controller:
++	fpga_programmer_disable(priv);
++	return ret;
++}
++
++#define FIFO_DMA_ADDRESS	0xf0003000
++#define FIFO_MAX_LEN		4096
++
++/**
++ * fpga_program_dma() - program the DATA-FPGA's using the DMA engine
++ * @priv: the driver's private data structure
++ *
++ * Program the DATA-FPGA's using the Freescale DMA engine. This requires that
++ * the engine is programmed such that the hardware DMA request lines can
++ * control the entire DMA transaction. The system controller FPGA then
++ * completely offloads the programming from the CPU.
++ *
++ * Returns 0 on success, -ERRNO otherwise
++ */
++static noinline int fpga_program_dma(struct fpga_dev *priv)
++{
++	struct videobuf_dmabuf *vb = &priv->vb;
++	struct dma_chan *chan = priv->chan;
++	struct dma_async_tx_descriptor *tx;
++	size_t num_pages, len, avail = 0;
++	struct dma_slave_config config;
++	struct scatterlist *sg;
++	struct sg_table table;
++	dma_cookie_t cookie;
++	int ret, i;
++
++	/* Disable the programmer */
++	fpga_programmer_disable(priv);
++
++	/* Allocate a scatterlist for the DMA destination */
++	num_pages = DIV_ROUND_UP(priv->bytes, FIFO_MAX_LEN);
++	ret = sg_alloc_table(&table, num_pages, GFP_KERNEL);
++	if (ret) {
++		dev_err(priv->dev, "Unable to allocate dst scatterlist\n");
++		ret = -ENOMEM;
++		goto out_return;
++	}
++
++	/*
++	 * This is an ugly hack
++	 *
++	 * We fill in a scatterlist as if it were mapped for DMA. This is
++	 * necessary because there exists no better structure for this
++	 * inside the kernel code.
++	 *
++	 * As an added bonus, we can use the DMAEngine API for all of this,
++	 * rather than inventing another extremely similar API.
++	 */
++	avail = priv->bytes;
++	for_each_sg(table.sgl, sg, num_pages, i) {
++		len = min_t(size_t, avail, FIFO_MAX_LEN);
++		sg_dma_address(sg) = FIFO_DMA_ADDRESS;
++		sg_dma_len(sg) = len;
++
++		avail -= len;
++	}
++
++	/* Map the buffer for DMA */
++	ret = videobuf_dma_map(priv->dev, &priv->vb);
++	if (ret) {
++		dev_err(priv->dev, "Unable to map buffer for DMA\n");
++		goto out_free_table;
++	}
++
++	/*
++	 * Configure the DMA channel to transfer FIFO_SIZE / 2 bytes per
++	 * transaction, and then put it under external control
++	 */
++	memset(&config, 0, sizeof(config));
++	config.direction = DMA_TO_DEVICE;
++	config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
++	config.dst_maxburst = fpga_fifo_size(priv->regs) / 2 / 4;
++	ret = chan->device->device_control(chan, DMA_SLAVE_CONFIG,
++					   (unsigned long)&config);
++	if (ret) {
++		dev_err(priv->dev, "DMA slave configuration failed\n");
++		goto out_dma_unmap;
++	}
++
++	ret = chan->device->device_control(chan, FSLDMA_EXTERNAL_START, 1);
++	if (ret) {
++		dev_err(priv->dev, "DMA external control setup failed\n");
++		goto out_dma_unmap;
++	}
++
++	/* setup and submit the DMA transaction */
++	tx = chan->device->device_prep_dma_sg(chan,
++					      table.sgl, num_pages,
++					      vb->sglist, vb->sglen, 0);
++	if (!tx) {
++		dev_err(priv->dev, "Unable to prep DMA transaction\n");
++		ret = -ENOMEM;
++		goto out_dma_unmap;
++	}
++
++	cookie = tx->tx_submit(tx);
++	if (dma_submit_error(cookie)) {
++		dev_err(priv->dev, "Unable to submit DMA transaction\n");
++		ret = -ENOMEM;
++		goto out_dma_unmap;
++	}
++
++	dma_async_memcpy_issue_pending(chan);
++
++	/* Set the total byte count */
++	fpga_set_byte_count(priv->regs, priv->bytes);
++	dev_dbg(priv->dev, "total byte count %u bytes\n", priv->bytes);
++
++	/* Enable the controller for DMA programming */
++	fpga_programmer_enable(priv, true);
++	dev_dbg(priv->dev, "enabled the controller\n");
++
++	/* Wait for the interrupt handler to signal that programming finished */
++	ret = wait_for_completion_timeout(&priv->completion, 2 * HZ);
++	if (!ret) {
++		dev_err(priv->dev, "Timed out waiting for completion\n");
++		ret = -ETIMEDOUT;
++		goto out_disable_controller;
++	}
++
++	/* Retrieve the status from the interrupt handler */
++	ret = priv->status;
++
++out_disable_controller:
++	fpga_programmer_disable(priv);
++out_dma_unmap:
++	videobuf_dma_unmap(priv->dev, vb);
++out_free_table:
++	sg_free_table(&table);
++out_return:
++	return ret;
++}
++
++/*
++ * Interrupt Handling
++ */
++
++static irqreturn_t fpga_irq(int irq, void *dev_id)
++{
++	struct fpga_dev *priv = dev_id;
++
++	/* Save the status */
++	priv->status = fpga_config_error(priv->regs) ? -EIO : 0;
++	dev_dbg(priv->dev, "INTERRUPT status %d\n", priv->status);
++	fpga_dump_registers(priv);
++
++	/* Disabling the programmer clears the interrupt */
++	fpga_programmer_disable(priv);
++
++	/* Notify any waiters */
++	complete(&priv->completion);
++
++	return IRQ_HANDLED;
++}
++
++/*
++ * SYSFS Helpers
++ */
++
++/**
++ * fpga_do_stop() - deconfigure (reset) the DATA-FPGA's
++ * @priv: the driver's private data structure
++ *
++ * LOCKING: must hold priv->lock
++ */
++static int fpga_do_stop(struct fpga_dev *priv)
++{
++	u32 val;
++
++	/* Set the led to unprogrammed */
++	ledtrig_fpga_programmed(false);
++
++	/* Pulse the config line to reset the FPGA's */
++	val = CFG_CTL_ENABLE | CFG_CTL_RESET;
++	iowrite32be(val, priv->regs + FPGA_CONFIG_CONTROL);
++	iowrite32be(0x0, priv->regs + FPGA_CONFIG_CONTROL);
++
++	return 0;
++}
++
++static noinline int fpga_do_program(struct fpga_dev *priv)
++{
++	int ret;
++
++	if (priv->bytes != priv->fw_size) {
++		dev_err(priv->dev, "Incorrect bitfile size: got %zu bytes, "
++				   "should be %zu bytes\n",
++				   priv->bytes, priv->fw_size);
++		return -EINVAL;
++	}
++
++	if (!fpga_power_enabled(priv)) {
++		dev_err(priv->dev, "Power not enabled\n");
++		return -EINVAL;
++	}
++
++	if (!fpga_power_good(priv)) {
++		dev_err(priv->dev, "Power not good\n");
++		return -EINVAL;
++	}
++
++	/* Set the LED to unprogrammed */
++	ledtrig_fpga_programmed(false);
++
++	/* Try to program the FPGA's using DMA */
++	ret = fpga_program_dma(priv);
++
++	/* If DMA failed or doesn't exist, try with CPU */
++	if (ret) {
++		dev_warn(priv->dev, "Falling back to CPU programming\n");
++		ret = fpga_program_cpu(priv);
++	}
++
++	if (ret) {
++		dev_err(priv->dev, "Unable to program FPGA's\n");
++		return ret;
++	}
++
++	/* Drop the firmware bitfile from memory */
++	fpga_drop_firmware_data(priv);
++
++	dev_dbg(priv->dev, "FPGA programming successful\n");
++	ledtrig_fpga_programmed(true);
++
++	return 0;
++}
++
++/*
++ * File Operations
++ */
++
++static int fpga_open(struct inode *inode, struct file *filp)
++{
++	/*
++	 * The miscdevice layer puts our struct miscdevice into the
++	 * filp->private_data field. We use this to find our private
++	 * data and then overwrite it with our own private structure.
++	 */
++	struct fpga_dev *priv = container_of(filp->private_data,
++					     struct fpga_dev, miscdev);
++	unsigned int nr_pages;
++	int ret;
++
++	/* We only allow one process at a time */
++	ret = mutex_lock_interruptible(&priv->lock);
++	if (ret)
++		return ret;
++
++	filp->private_data = priv;
++	kref_get(&priv->ref);
++
++	/* Truncation: drop any existing data */
++	if (filp->f_flags & O_TRUNC)
++		priv->bytes = 0;
++
++	/* Check if we have already allocated a buffer */
++	if (priv->vb_allocated)
++		return 0;
++
++	/* Allocate a buffer to hold enough data for the bitfile */
++	nr_pages = DIV_ROUND_UP(priv->fw_size, PAGE_SIZE);
++	ret = videobuf_dma_init_kernel(&priv->vb, DMA_TO_DEVICE, nr_pages);
++	if (ret) {
++		dev_err(priv->dev, "unable to allocate data buffer\n");
++		mutex_unlock(&priv->lock);
++		kref_put(&priv->ref, fpga_dev_remove);
++		return ret;
++	}
++
++	priv->vb_allocated = true;
++	return 0;
++}
++
++static int fpga_release(struct inode *inode, struct file *filp)
++{
++	struct fpga_dev *priv = filp->private_data;
++
++	mutex_unlock(&priv->lock);
++	kref_put(&priv->ref, fpga_dev_remove);
++	return 0;
++}
++
++static ssize_t fpga_write(struct file *filp, const char __user *buf,
++			  size_t count, loff_t *f_pos)
++{
++	struct fpga_dev *priv = filp->private_data;
++
++	/* FPGA bitfiles have an exact size: disallow anything else */
++	if (priv->bytes >= priv->fw_size)
++		return -ENOSPC;
++
++	count = min_t(size_t, priv->fw_size - priv->bytes, count);
++	if (copy_from_user(priv->vb.vaddr + priv->bytes, buf, count))
++		return -EFAULT;
++
++	priv->bytes += count;
++	return count;
++}
++
++static ssize_t fpga_read(struct file *filp, char __user *buf, size_t count,
++			 loff_t *f_pos)
++{
++	struct fpga_dev *priv = filp->private_data;
++
++	count = min_t(size_t, priv->bytes - *f_pos, count);
++	if (copy_to_user(buf, priv->vb.vaddr + *f_pos, count))
++		return -EFAULT;
++
++	*f_pos += count;
++	return count;
++}
++
++static loff_t fpga_llseek(struct file *filp, loff_t offset, int origin)
++{
++	struct fpga_dev *priv = filp->private_data;
++	loff_t newpos;
++
++	/* only read-only opens are allowed to seek */
++	if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
++		return -EINVAL;
++
++	switch (origin) {
++	case SEEK_SET: /* seek relative to the beginning of the file */
++		newpos = offset;
++		break;
++	case SEEK_CUR: /* seek relative to current position in the file */
++		newpos = filp->f_pos + offset;
++		break;
++	case SEEK_END: /* seek relative to the end of the file */
++		newpos = priv->fw_size - offset;
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	/* check for sanity */
++	if (newpos > priv->fw_size)
++		return -EINVAL;
++
++	filp->f_pos = newpos;
++	return newpos;
++}
++
++static const struct file_operations fpga_fops = {
++	.open		= fpga_open,
++	.release	= fpga_release,
++	.write		= fpga_write,
++	.read		= fpga_read,
++	.llseek		= fpga_llseek,
++};
++
++/*
++ * Device Attributes
++ */
++
++static ssize_t pfail_show(struct device *dev, struct device_attribute *attr,
++			  char *buf)
++{
++	struct fpga_dev *priv = dev_get_drvdata(dev);
++	u8 val;
++
++	val = ioread8(priv->regs + CTL_PWR_FAIL);
++	return snprintf(buf, PAGE_SIZE, "0x%.2x\n", val);
++}
++
++static ssize_t pgood_show(struct device *dev, struct device_attribute *attr,
++			  char *buf)
++{
++	struct fpga_dev *priv = dev_get_drvdata(dev);
++	return snprintf(buf, PAGE_SIZE, "%d\n", fpga_power_good(priv));
++}
++
++static ssize_t penable_show(struct device *dev, struct device_attribute *attr,
++			    char *buf)
++{
++	struct fpga_dev *priv = dev_get_drvdata(dev);
++	return snprintf(buf, PAGE_SIZE, "%d\n", fpga_power_enabled(priv));
++}
++
++static ssize_t penable_store(struct device *dev, struct device_attribute *attr,
++			     const char *buf, size_t count)
++{
++	struct fpga_dev *priv = dev_get_drvdata(dev);
++	unsigned long val;
++	int ret;
++
++	if (strict_strtoul(buf, 0, &val))
++		return -EINVAL;
++
++	if (val) {
++		ret = fpga_enable_power_supplies(priv);
++		if (ret)
++			return ret;
++	} else {
++		fpga_do_stop(priv);
++		fpga_disable_power_supplies(priv);
++	}
++
++	return count;
++}
++
++static ssize_t program_show(struct device *dev, struct device_attribute *attr,
++			    char *buf)
++{
++	struct fpga_dev *priv = dev_get_drvdata(dev);
++	return snprintf(buf, PAGE_SIZE, "%d\n", fpga_running(priv));
++}
++
++static ssize_t program_store(struct device *dev, struct device_attribute *attr,
++			     const char *buf, size_t count)
++{
++	struct fpga_dev *priv = dev_get_drvdata(dev);
++	unsigned long val;
++	int ret;
++
++	if (strict_strtoul(buf, 0, &val))
++		return -EINVAL;
++
++	/* We can't have an image writer and be programming simultaneously */
++	if (mutex_lock_interruptible(&priv->lock))
++		return -ERESTARTSYS;
++
++	/* Program or Reset the FPGA's */
++	ret = val ? fpga_do_program(priv) : fpga_do_stop(priv);
++	if (ret)
++		goto out_unlock;
++
++	/* Success */
++	ret = count;
++
++out_unlock:
++	mutex_unlock(&priv->lock);
++	return ret;
++}
++
++static DEVICE_ATTR(power_fail, S_IRUGO, pfail_show, NULL);
++static DEVICE_ATTR(power_good, S_IRUGO, pgood_show, NULL);
++static DEVICE_ATTR(power_enable, S_IRUGO | S_IWUSR,
++		   penable_show, penable_store);
++
++static DEVICE_ATTR(program, S_IRUGO | S_IWUSR,
++		   program_show, program_store);
++
++static struct attribute *fpga_attributes[] = {
++	&dev_attr_power_fail.attr,
++	&dev_attr_power_good.attr,
++	&dev_attr_power_enable.attr,
++	&dev_attr_program.attr,
++	NULL,
++};
++
++static const struct attribute_group fpga_attr_group = {
++	.attrs = fpga_attributes,
++};
++
++/*
++ * OpenFirmware Device Subsystem
++ */
++
++#define SYS_REG_VERSION		0x00
++#define SYS_REG_GEOGRAPHIC	0x10
++
++static bool dma_filter(struct dma_chan *chan, void *data)
++{
++	/*
++	 * DMA Channel #0 is the only acceptable device
++	 *
++	 * This probably won't survive an unload/load cycle of the Freescale
++	 * DMAEngine driver, but that won't be a problem
++	 */
++	return chan->chan_id == 0 && chan->device->dev_id == 0;
++}
++
++static int fpga_of_remove(struct platform_device *op)
++{
++	struct fpga_dev *priv = dev_get_drvdata(&op->dev);
++	struct device *this_device = priv->miscdev.this_device;
++
++	sysfs_remove_group(&this_device->kobj, &fpga_attr_group);
++	misc_deregister(&priv->miscdev);
++
++	free_irq(priv->irq, priv);
++	irq_dispose_mapping(priv->irq);
++
++	/* make sure the power supplies are off */
++	fpga_disable_power_supplies(priv);
++
++	/* unmap registers */
++	iounmap(priv->immr);
++	iounmap(priv->regs);
++
++	dma_release_channel(priv->chan);
++
++	/* drop our reference to the private data structure */
++	kref_put(&priv->ref, fpga_dev_remove);
++	return 0;
++}
++
++/* CTL-CPLD Version Register */
++#define CTL_CPLD_VERSION	0x2000
++
++static int fpga_of_probe(struct platform_device *op,
++			 const struct of_device_id *match)
++{
++	struct device_node *of_node = op->dev.of_node;
++	struct device *this_device;
++	struct fpga_dev *priv;
++	dma_cap_mask_t mask;
++	u32 ver;
++	int ret;
++
++	/* Allocate private data */
++	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
++	if (!priv) {
++		dev_err(&op->dev, "Unable to allocate private data\n");
++		ret = -ENOMEM;
++		goto out_return;
++	}
++
++	/* Setup the miscdevice */
++	priv->miscdev.minor = MISC_DYNAMIC_MINOR;
++	priv->miscdev.name = drv_name;
++	priv->miscdev.fops = &fpga_fops;
++
++	kref_init(&priv->ref);
++
++	dev_set_drvdata(&op->dev, priv);
++	priv->dev = &op->dev;
++	mutex_init(&priv->lock);
++	init_completion(&priv->completion);
++	videobuf_dma_init(&priv->vb);
++
++	dev_set_drvdata(priv->dev, priv);
++	dma_cap_zero(mask);
++	dma_cap_set(DMA_MEMCPY, mask);
++	dma_cap_set(DMA_INTERRUPT, mask);
++	dma_cap_set(DMA_SLAVE, mask);
++	dma_cap_set(DMA_SG, mask);
++
++	/* Get control of DMA channel #0 */
++	priv->chan = dma_request_channel(mask, dma_filter, NULL);
++	if (!priv->chan) {
++		dev_err(&op->dev, "Unable to acquire DMA channel #0\n");
++		ret = -ENODEV;
++		goto out_free_priv;
++	}
++
++	/* Remap the registers for use */
++	priv->regs = of_iomap(of_node, 0);
++	if (!priv->regs) {
++		dev_err(&op->dev, "Unable to ioremap registers\n");
++		ret = -ENOMEM;
++		goto out_dma_release_channel;
++	}
++
++	/* Remap the IMMR for use */
++	priv->immr = ioremap(get_immrbase(), 0x100000);
++	if (!priv->immr) {
++		dev_err(&op->dev, "Unable to ioremap IMMR\n");
++		ret = -ENOMEM;
++		goto out_unmap_regs;
++	}
++
++	/*
++	 * Check that external DMA is configured
++	 *
++	 * U-Boot does this for us, but we should check it and bail out if
++	 * there is a problem. Failing to have this register setup correctly
++	 * will cause the DMA controller to transfer a single cacheline
++	 * worth of data, then wedge itself.
++	 */
++	if ((ioread32be(priv->immr + 0x114) & 0xE00) != 0xE00) {
++		dev_err(&op->dev, "External DMA control not configured\n");
++		ret = -ENODEV;
++		goto out_unmap_immr;
++	}
++
++	/*
++	 * Check the CTL-CPLD version
++	 *
++	 * This driver uses the CTL-CPLD DATA-FPGA power sequencer, and we
++	 * don't want to run on any version of the CTL-CPLD that does not use
++	 * a compatible register layout.
++	 *
++	 * v2: changed register layout, added power sequencer
++	 * v3: added glitch filter on the i2c overcurrent/overtemp outputs
++	 */
++	ver = ioread8(priv->regs + CTL_CPLD_VERSION);
++	if (ver != 0x02 && ver != 0x03) {
++		dev_err(&op->dev, "CTL-CPLD is not version 0x02 or 0x03!\n");
++		ret = -ENODEV;
++		goto out_unmap_immr;
++	}
++
++	/* Set the exact size that the firmware image should be */
++	ver = ioread32be(priv->regs + SYS_REG_VERSION);
++	priv->fw_size = (ver & (1 << 18)) ? FW_SIZE_EP2S130 : FW_SIZE_EP2S90;
++
++	/* Find the correct IRQ number */
++	priv->irq = irq_of_parse_and_map(of_node, 0);
++	if (priv->irq == NO_IRQ) {
++		dev_err(&op->dev, "Unable to find IRQ line\n");
++		ret = -ENODEV;
++		goto out_unmap_immr;
++	}
++
++	/* Request the IRQ */
++	ret = request_irq(priv->irq, fpga_irq, IRQF_SHARED, drv_name, priv);
++	if (ret) {
++		dev_err(&op->dev, "Unable to request IRQ %d\n", priv->irq);
++		ret = -ENODEV;
++		goto out_irq_dispose_mapping;
++	}
++
++	/* Reset and stop the FPGA's, just in case */
++	fpga_do_stop(priv);
++
++	/* Register the miscdevice */
++	ret = misc_register(&priv->miscdev);
++	if (ret) {
++		dev_err(&op->dev, "Unable to register miscdevice\n");
++		goto out_free_irq;
++	}
++
++	/* Create the sysfs files */
++	this_device = priv->miscdev.this_device;
++	dev_set_drvdata(this_device, priv);
++	ret = sysfs_create_group(&this_device->kobj, &fpga_attr_group);
++	if (ret) {
++		dev_err(&op->dev, "Unable to create sysfs files\n");
++		goto out_misc_deregister;
++	}
++
++	dev_info(priv->dev, "CARMA FPGA Programmer: %s rev%s with %s FPGAs\n",
++			(ver & (1 << 17)) ? "Correlator" : "Digitizer",
++			(ver & (1 << 16)) ? "B" : "A",
++			(ver & (1 << 18)) ? "EP2S130" : "EP2S90");
++
++	return 0;
++
++out_misc_deregister:
++	misc_deregister(&priv->miscdev);
++out_free_irq:
++	free_irq(priv->irq, priv);
++out_irq_dispose_mapping:
++	irq_dispose_mapping(priv->irq);
++out_unmap_immr:
++	iounmap(priv->immr);
++out_unmap_regs:
++	iounmap(priv->regs);
++out_dma_release_channel:
++	dma_release_channel(priv->chan);
++out_free_priv:
++	kref_put(&priv->ref, fpga_dev_remove);
++out_return:
++	return ret;
++}
++
++static struct of_device_id fpga_of_match[] = {
++	{ .compatible = "carma,fpga-programmer", },
++	{},
++};
++
++static struct of_platform_driver fpga_of_driver = {
++	.probe		= fpga_of_probe,
++	.remove		= fpga_of_remove,
++	.driver		= {
++		.name		= drv_name,
++		.of_match_table	= fpga_of_match,
++		.owner		= THIS_MODULE,
++	},
++};
++
++/*
++ * Module Init / Exit
++ */
++
++static int __init fpga_init(void)
++{
++	led_trigger_register_simple("fpga", &ledtrig_fpga);
++	return of_register_platform_driver(&fpga_of_driver);
++}
++
++static void __exit fpga_exit(void)
++{
++	of_unregister_platform_driver(&fpga_of_driver);
++	led_trigger_unregister_simple(ledtrig_fpga);
++}
++
++MODULE_AUTHOR("Ira W. Snyder ");
++MODULE_DESCRIPTION("CARMA Board DATA-FPGA Programmer");
++MODULE_LICENSE("GPL");
++
++module_init(fpga_init);
++module_exit(fpga_exit);

commit c186f0e177275e83728d7acfdf4a1b68793a7038
+Author: Ira Snyder 
+Date:   Fri Feb 11 13:34:29 2011 +0000
+
+    misc: Add CARMA DATA-FPGA Access Driver
+    
+    This driver allows userspace to access the data processing FPGAs on the
+    OVRO CARMA board. It has two modes of operation:
+    
+    1) random access
+    
+    This allows users to poke any DATA-FPGA registers by using mmap to map
+    the address region directly into their memory map.
+    
+    2) correlation dumping
+    
+    When correlating, the DATA-FPGA's have special requirements for getting
+    the data out of their memory before the next correlation. This nominally
+    happens at 64Hz (every 15.625ms). If the data is not dumped before the
+    next correlation, data is lost.
+    
+    The data dumping driver handles buffering up to 1 second worth of
+    correlation data from the FPGAs. This lowers the realtime scheduling
+    requirements for the userspace process reading the device.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Benjamin Herrenschmidt 
+
+diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
+index 4e007c6a4b44..d80dcdee88f3 100644
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -481,5 +481,6 @@ source "drivers/misc/cb710/Kconfig"
+ source "drivers/misc/iwmc3200top/Kconfig"
+ source "drivers/misc/ti-st/Kconfig"
+ source "drivers/misc/lis3lv02d/Kconfig"
++source "drivers/misc/carma/Kconfig"
+ 
+ endif # MISC_DEVICES
+diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
+index f5468602961f..848e8464faab 100644
+--- a/drivers/misc/Makefile
++++ b/drivers/misc/Makefile
+@@ -44,3 +44,4 @@ obj-$(CONFIG_PCH_PHUB)		+= pch_phub.o
+ obj-y				+= ti-st/
+ obj-$(CONFIG_AB8500_PWM)	+= ab8500-pwm.o
+ obj-y				+= lis3lv02d/
++obj-y				+= carma/
+diff --git a/drivers/misc/carma/Kconfig b/drivers/misc/carma/Kconfig
+new file mode 100644
+index 000000000000..4be183f7e6f1
+--- /dev/null
++++ b/drivers/misc/carma/Kconfig
+@@ -0,0 +1,9 @@
++config CARMA_FPGA
++	tristate "CARMA DATA-FPGA Access Driver"
++	depends on FSL_SOC && PPC_83xx && MEDIA_SUPPORT && HAS_DMA && FSL_DMA
++	select VIDEOBUF_DMA_SG
++	default n
++	help
++	  Say Y here to include support for communicating with the data
++	  processing FPGAs on the OVRO CARMA board.
++
+diff --git a/drivers/misc/carma/Makefile b/drivers/misc/carma/Makefile
+new file mode 100644
+index 000000000000..0b69fa787953
+--- /dev/null
++++ b/drivers/misc/carma/Makefile
+@@ -0,0 +1 @@
++obj-$(CONFIG_CARMA_FPGA)		+= carma-fpga.o
+diff --git a/drivers/misc/carma/carma-fpga.c b/drivers/misc/carma/carma-fpga.c
+new file mode 100644
+index 000000000000..3965821fef17
+--- /dev/null
++++ b/drivers/misc/carma/carma-fpga.c
+@@ -0,0 +1,1433 @@
++/*
++ * CARMA DATA-FPGA Access Driver
++ *
++ * Copyright (c) 2009-2011 Ira W. Snyder 
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++/*
++ * FPGA Memory Dump Format
++ *
++ * FPGA #0 control registers (32 x 32-bit words)
++ * FPGA #1 control registers (32 x 32-bit words)
++ * FPGA #2 control registers (32 x 32-bit words)
++ * FPGA #3 control registers (32 x 32-bit words)
++ * SYSFPGA control registers (32 x 32-bit words)
++ * FPGA #0 correlation array (NUM_CORL0 correlation blocks)
++ * FPGA #1 correlation array (NUM_CORL1 correlation blocks)
++ * FPGA #2 correlation array (NUM_CORL2 correlation blocks)
++ * FPGA #3 correlation array (NUM_CORL3 correlation blocks)
++ *
++ * Each correlation array consists of:
++ *
++ * Correlation Data      (2 x NUM_LAGSn x 32-bit words)
++ * Pipeline Metadata     (2 x NUM_METAn x 32-bit words)
++ * Quantization Counters (2 x NUM_QCNTn x 32-bit words)
++ *
++ * The NUM_CORLn, NUM_LAGSn, NUM_METAn, and NUM_QCNTn values come from
++ * the FPGA configuration registers. They do not change once the FPGA's
++ * have been programmed, they only change on re-programming.
++ */
++
++/*
++ * Basic Description:
++ *
++ * This driver is used to capture correlation spectra off of the four data
++ * processing FPGAs. The FPGAs are often reprogrammed at runtime, therefore
++ * this driver supports dynamic enable/disable of capture while the device
++ * remains open.
++ *
++ * The nominal capture rate is 64Hz (every 15.625ms). To facilitate this fast
++ * capture rate, all buffers are pre-allocated to avoid any potentially long
++ * running memory allocations while capturing.
++ *
++ * There are two lists and one pointer which are used to keep track of the
++ * different states of data buffers.
++ *
++ * 1) free list
++ * This list holds all empty data buffers which are ready to receive data.
++ *
++ * 2) inflight pointer
++ * This pointer holds the currently inflight data buffer. This buffer is having
++ * data copied into it by the DMA engine.
++ *
++ * 3) used list
++ * This list holds data buffers which have been filled, and are waiting to be
++ * read by userspace.
++ *
++ * All buffers start life on the free list, then move successively to the
++ * inflight pointer, and then to the used list. After they have been read by
++ * userspace, they are moved back to the free list. The cycle repeats as long
++ * as necessary.
++ *
++ * It should be noted that all buffers are mapped and ready for DMA when they
++ * are on any of the three lists. They are only unmapped when they are in the
++ * process of being read by userspace.
++ */
++
++/*
++ * Notes on the IRQ masking scheme:
++ *
++ * The IRQ masking scheme here is different than most other hardware. The only
++ * way for the DATA-FPGAs to detect if the kernel has taken too long to copy
++ * the data is if the status registers are not cleared before the next
++ * correlation data dump is ready.
++ *
++ * The interrupt line is connected to the status registers, such that when they
++ * are cleared, the interrupt is de-asserted. Therein lies our problem. We need
++ * to schedule a long-running DMA operation and return from the interrupt
++ * handler quickly, but we cannot clear the status registers.
++ *
++ * To handle this, the system controller FPGA has the capability to connect the
++ * interrupt line to a user-controlled GPIO pin. This pin is driven high
++ * (unasserted) and left that way. To mask the interrupt, we change the
++ * interrupt source to the GPIO pin. Tada, we hid the interrupt. :)
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++
++/* system controller registers */
++#define SYS_IRQ_SOURCE_CTL	0x24
++#define SYS_IRQ_OUTPUT_EN	0x28
++#define SYS_IRQ_OUTPUT_DATA	0x2C
++#define SYS_IRQ_INPUT_DATA	0x30
++#define SYS_FPGA_CONFIG_STATUS	0x44
++
++/* GPIO IRQ line assignment */
++#define IRQ_CORL_DONE		0x10
++
++/* FPGA registers */
++#define MMAP_REG_VERSION	0x00
++#define MMAP_REG_CORL_CONF1	0x08
++#define MMAP_REG_CORL_CONF2	0x0C
++#define MMAP_REG_STATUS		0x48
++
++#define SYS_FPGA_BLOCK		0xF0000000
++
++#define DATA_FPGA_START		0x400000
++#define DATA_FPGA_SIZE		0x80000
++
++static const char drv_name[] = "carma-fpga";
++
++#define NUM_FPGA	4
++
++#define MIN_DATA_BUFS	8
++#define MAX_DATA_BUFS	64
++
++struct fpga_info {
++	unsigned int num_lag_ram;
++	unsigned int blk_size;
++};
++
++struct data_buf {
++	struct list_head entry;
++	struct videobuf_dmabuf vb;
++	size_t size;
++};
++
++struct fpga_device {
++	/* character device */
++	struct miscdevice miscdev;
++	struct device *dev;
++	struct mutex mutex;
++
++	/* reference count */
++	struct kref ref;
++
++	/* FPGA registers and information */
++	struct fpga_info info[NUM_FPGA];
++	void __iomem *regs;
++	int irq;
++
++	/* FPGA Physical Address/Size Information */
++	resource_size_t phys_addr;
++	size_t phys_size;
++
++	/* DMA structures */
++	struct sg_table corl_table;
++	unsigned int corl_nents;
++	struct dma_chan *chan;
++
++	/* Protection for all members below */
++	spinlock_t lock;
++
++	/* Device enable/disable flag */
++	bool enabled;
++
++	/* Correlation data buffers */
++	wait_queue_head_t wait;
++	struct list_head free;
++	struct list_head used;
++	struct data_buf *inflight;
++
++	/* Information about data buffers */
++	unsigned int num_dropped;
++	unsigned int num_buffers;
++	size_t bufsize;
++	struct dentry *dbg_entry;
++};
++
++struct fpga_reader {
++	struct fpga_device *priv;
++	struct data_buf *buf;
++	off_t buf_start;
++};
++
++static void fpga_device_release(struct kref *ref)
++{
++	struct fpga_device *priv = container_of(ref, struct fpga_device, ref);
++
++	/* the last reader has exited, cleanup the last bits */
++	mutex_destroy(&priv->mutex);
++	kfree(priv);
++}
++
++/*
++ * Data Buffer Allocation Helpers
++ */
++
++/**
++ * data_free_buffer() - free a single data buffer and all allocated memory
++ * @buf: the buffer to free
++ *
++ * This will free all of the pages allocated to the given data buffer, and
++ * then free the structure itself
++ */
++static void data_free_buffer(struct data_buf *buf)
++{
++	/* It is ok to free a NULL buffer */
++	if (!buf)
++		return;
++
++	/* free all memory */
++	videobuf_dma_free(&buf->vb);
++	kfree(buf);
++}
++
++/**
++ * data_alloc_buffer() - allocate and fill a data buffer with pages
++ * @bytes: the number of bytes required
++ *
++ * This allocates all space needed for a data buffer. It must be mapped before
++ * use in a DMA transaction using videobuf_dma_map().
++ *
++ * Returns NULL on failure
++ */
++static struct data_buf *data_alloc_buffer(const size_t bytes)
++{
++	unsigned int nr_pages;
++	struct data_buf *buf;
++	int ret;
++
++	/* calculate the number of pages necessary */
++	nr_pages = DIV_ROUND_UP(bytes, PAGE_SIZE);
++
++	/* allocate the buffer structure */
++	buf = kzalloc(sizeof(*buf), GFP_KERNEL);
++	if (!buf)
++		goto out_return;
++
++	/* initialize internal fields */
++	INIT_LIST_HEAD(&buf->entry);
++	buf->size = bytes;
++
++	/* allocate the videobuf */
++	videobuf_dma_init(&buf->vb);
++	ret = videobuf_dma_init_kernel(&buf->vb, DMA_FROM_DEVICE, nr_pages);
++	if (ret)
++		goto out_free_buf;
++
++	return buf;
++
++out_free_buf:
++	kfree(buf);
++out_return:
++	return NULL;
++}
++
++/**
++ * data_free_buffers() - free all allocated buffers
++ * @priv: the driver's private data structure
++ *
++ * Free all buffers allocated by the driver (except those currently in the
++ * process of being read by userspace).
++ *
++ * LOCKING: must hold dev->mutex
++ * CONTEXT: user
++ */
++static void data_free_buffers(struct fpga_device *priv)
++{
++	struct data_buf *buf, *tmp;
++
++	/* the device should be stopped, no DMA in progress */
++	BUG_ON(priv->inflight != NULL);
++
++	list_for_each_entry_safe(buf, tmp, &priv->free, entry) {
++		list_del_init(&buf->entry);
++		videobuf_dma_unmap(priv->dev, &buf->vb);
++		data_free_buffer(buf);
++	}
++
++	list_for_each_entry_safe(buf, tmp, &priv->used, entry) {
++		list_del_init(&buf->entry);
++		videobuf_dma_unmap(priv->dev, &buf->vb);
++		data_free_buffer(buf);
++	}
++
++	priv->num_buffers = 0;
++	priv->bufsize = 0;
++}
++
++/**
++ * data_alloc_buffers() - allocate 1 seconds worth of data buffers
++ * @priv: the driver's private data structure
++ *
++ * Allocate enough buffers for a whole second worth of data
++ *
++ * This routine will attempt to degrade nicely by succeeding even if a full
++ * second worth of data buffers could not be allocated, as long as a minimum
++ * number were allocated. In this case, it will print a message to the kernel
++ * log.
++ *
++ * The device must not be modifying any lists when this is called.
++ *
++ * CONTEXT: user
++ * LOCKING: must hold dev->mutex
++ *
++ * Returns 0 on success, -ERRNO otherwise
++ */
++static int data_alloc_buffers(struct fpga_device *priv)
++{
++	struct data_buf *buf;
++	int i, ret;
++
++	for (i = 0; i < MAX_DATA_BUFS; i++) {
++
++		/* allocate a buffer */
++		buf = data_alloc_buffer(priv->bufsize);
++		if (!buf)
++			break;
++
++		/* map it for DMA */
++		ret = videobuf_dma_map(priv->dev, &buf->vb);
++		if (ret) {
++			data_free_buffer(buf);
++			break;
++		}
++
++		/* add it to the list of free buffers */
++		list_add_tail(&buf->entry, &priv->free);
++		priv->num_buffers++;
++	}
++
++	/* Make sure we allocated the minimum required number of buffers */
++	if (priv->num_buffers < MIN_DATA_BUFS) {
++		dev_err(priv->dev, "Unable to allocate enough data buffers\n");
++		data_free_buffers(priv);
++		return -ENOMEM;
++	}
++
++	/* Warn if we are running in a degraded state, but do not fail */
++	if (priv->num_buffers < MAX_DATA_BUFS) {
++		dev_warn(priv->dev,
++			 "Unable to allocate %d buffers, using %d buffers instead\n",
++			 MAX_DATA_BUFS, i);
++	}
++
++	return 0;
++}
++
++/*
++ * DMA Operations Helpers
++ */
++
++/**
++ * fpga_start_addr() - get the physical address a DATA-FPGA
++ * @priv: the driver's private data structure
++ * @fpga: the DATA-FPGA number (zero based)
++ */
++static dma_addr_t fpga_start_addr(struct fpga_device *priv, unsigned int fpga)
++{
++	return priv->phys_addr + 0x400000 + (0x80000 * fpga);
++}
++
++/**
++ * fpga_block_addr() - get the physical address of a correlation data block
++ * @priv: the driver's private data structure
++ * @fpga: the DATA-FPGA number (zero based)
++ * @blknum: the correlation block number (zero based)
++ */
++static dma_addr_t fpga_block_addr(struct fpga_device *priv, unsigned int fpga,
++				  unsigned int blknum)
++{
++	return fpga_start_addr(priv, fpga) + (0x10000 * (1 + blknum));
++}
++
++#define REG_BLOCK_SIZE	(32 * 4)
++
++/**
++ * data_setup_corl_table() - create the scatterlist for correlation dumps
++ * @priv: the driver's private data structure
++ *
++ * Create the scatterlist for transferring a correlation dump from the
++ * DATA FPGAs. This structure will be reused for each buffer than needs
++ * to be filled with correlation data.
++ *
++ * Returns 0 on success, -ERRNO otherwise
++ */
++static int data_setup_corl_table(struct fpga_device *priv)
++{
++	struct sg_table *table = &priv->corl_table;
++	struct scatterlist *sg;
++	struct fpga_info *info;
++	int i, j, ret;
++
++	/* Calculate the number of entries needed */
++	priv->corl_nents = (1 + NUM_FPGA) * REG_BLOCK_SIZE;
++	for (i = 0; i < NUM_FPGA; i++)
++		priv->corl_nents += priv->info[i].num_lag_ram;
++
++	/* Allocate the scatterlist table */
++	ret = sg_alloc_table(table, priv->corl_nents, GFP_KERNEL);
++	if (ret) {
++		dev_err(priv->dev, "unable to allocate DMA table\n");
++		return ret;
++	}
++
++	/* Add the DATA FPGA registers to the scatterlist */
++	sg = table->sgl;
++	for (i = 0; i < NUM_FPGA; i++) {
++		sg_dma_address(sg) = fpga_start_addr(priv, i);
++		sg_dma_len(sg) = REG_BLOCK_SIZE;
++		sg = sg_next(sg);
++	}
++
++	/* Add the SYS-FPGA registers to the scatterlist */
++	sg_dma_address(sg) = SYS_FPGA_BLOCK;
++	sg_dma_len(sg) = REG_BLOCK_SIZE;
++	sg = sg_next(sg);
++
++	/* Add the FPGA correlation data blocks to the scatterlist */
++	for (i = 0; i < NUM_FPGA; i++) {
++		info = &priv->info[i];
++		for (j = 0; j < info->num_lag_ram; j++) {
++			sg_dma_address(sg) = fpga_block_addr(priv, i, j);
++			sg_dma_len(sg) = info->blk_size;
++			sg = sg_next(sg);
++		}
++	}
++
++	/*
++	 * All physical addresses and lengths are present in the structure
++	 * now. It can be reused for every FPGA DATA interrupt
++	 */
++	return 0;
++}
++
++/*
++ * FPGA Register Access Helpers
++ */
++
++static void fpga_write_reg(struct fpga_device *priv, unsigned int fpga,
++			   unsigned int reg, u32 val)
++{
++	const int fpga_start = DATA_FPGA_START + (fpga * DATA_FPGA_SIZE);
++	iowrite32be(val, priv->regs + fpga_start + reg);
++}
++
++static u32 fpga_read_reg(struct fpga_device *priv, unsigned int fpga,
++			 unsigned int reg)
++{
++	const int fpga_start = DATA_FPGA_START + (fpga * DATA_FPGA_SIZE);
++	return ioread32be(priv->regs + fpga_start + reg);
++}
++
++/**
++ * data_calculate_bufsize() - calculate the data buffer size required
++ * @priv: the driver's private data structure
++ *
++ * Calculate the total buffer size needed to hold a single block
++ * of correlation data
++ *
++ * CONTEXT: user
++ *
++ * Returns 0 on success, -ERRNO otherwise
++ */
++static int data_calculate_bufsize(struct fpga_device *priv)
++{
++	u32 num_corl, num_lags, num_meta, num_qcnt, num_pack;
++	u32 conf1, conf2, version;
++	u32 num_lag_ram, blk_size;
++	int i;
++
++	/* Each buffer starts with the 5 FPGA register areas */
++	priv->bufsize = (1 + NUM_FPGA) * REG_BLOCK_SIZE;
++
++	/* Read and store the configuration data for each FPGA */
++	for (i = 0; i < NUM_FPGA; i++) {
++		version = fpga_read_reg(priv, i, MMAP_REG_VERSION);
++		conf1 = fpga_read_reg(priv, i, MMAP_REG_CORL_CONF1);
++		conf2 = fpga_read_reg(priv, i, MMAP_REG_CORL_CONF2);
++
++		/* minor version 2 and later */
++		if ((version & 0x000000FF) >= 2) {
++			num_corl = (conf1 & 0x000000F0) >> 4;
++			num_pack = (conf1 & 0x00000F00) >> 8;
++			num_lags = (conf1 & 0x00FFF000) >> 12;
++			num_meta = (conf1 & 0x7F000000) >> 24;
++			num_qcnt = (conf2 & 0x00000FFF) >> 0;
++		} else {
++			num_corl = (conf1 & 0x000000F0) >> 4;
++			num_pack = 1; /* implied */
++			num_lags = (conf1 & 0x000FFF00) >> 8;
++			num_meta = (conf1 & 0x7FF00000) >> 20;
++			num_qcnt = (conf2 & 0x00000FFF) >> 0;
++		}
++
++		num_lag_ram = (num_corl + num_pack - 1) / num_pack;
++		blk_size = ((num_pack * num_lags) + num_meta + num_qcnt) * 8;
++
++		priv->info[i].num_lag_ram = num_lag_ram;
++		priv->info[i].blk_size = blk_size;
++		priv->bufsize += num_lag_ram * blk_size;
++
++		dev_dbg(priv->dev, "FPGA %d NUM_CORL: %d\n", i, num_corl);
++		dev_dbg(priv->dev, "FPGA %d NUM_PACK: %d\n", i, num_pack);
++		dev_dbg(priv->dev, "FPGA %d NUM_LAGS: %d\n", i, num_lags);
++		dev_dbg(priv->dev, "FPGA %d NUM_META: %d\n", i, num_meta);
++		dev_dbg(priv->dev, "FPGA %d NUM_QCNT: %d\n", i, num_qcnt);
++		dev_dbg(priv->dev, "FPGA %d BLK_SIZE: %d\n", i, blk_size);
++	}
++
++	dev_dbg(priv->dev, "TOTAL BUFFER SIZE: %zu bytes\n", priv->bufsize);
++	return 0;
++}
++
++/*
++ * Interrupt Handling
++ */
++
++/**
++ * data_disable_interrupts() - stop the device from generating interrupts
++ * @priv: the driver's private data structure
++ *
++ * Hide interrupts by switching to GPIO interrupt source
++ *
++ * LOCKING: must hold dev->lock
++ */
++static void data_disable_interrupts(struct fpga_device *priv)
++{
++	/* hide the interrupt by switching the IRQ driver to GPIO */
++	iowrite32be(0x2F, priv->regs + SYS_IRQ_SOURCE_CTL);
++}
++
++/**
++ * data_enable_interrupts() - allow the device to generate interrupts
++ * @priv: the driver's private data structure
++ *
++ * Unhide interrupts by switching to the FPGA interrupt source. At the
++ * same time, clear the DATA-FPGA status registers.
++ *
++ * LOCKING: must hold dev->lock
++ */
++static void data_enable_interrupts(struct fpga_device *priv)
++{
++	/* clear the actual FPGA corl_done interrupt */
++	fpga_write_reg(priv, 0, MMAP_REG_STATUS, 0x0);
++	fpga_write_reg(priv, 1, MMAP_REG_STATUS, 0x0);
++	fpga_write_reg(priv, 2, MMAP_REG_STATUS, 0x0);
++	fpga_write_reg(priv, 3, MMAP_REG_STATUS, 0x0);
++
++	/* flush the writes */
++	fpga_read_reg(priv, 0, MMAP_REG_STATUS);
++
++	/* switch back to the external interrupt source */
++	iowrite32be(0x3F, priv->regs + SYS_IRQ_SOURCE_CTL);
++}
++
++/**
++ * data_dma_cb() - DMAEngine callback for DMA completion
++ * @data: the driver's private data structure
++ *
++ * Complete a DMA transfer from the DATA-FPGA's
++ *
++ * This is called via the DMA callback mechanism, and will handle moving the
++ * completed DMA transaction to the used list, and then wake any processes
++ * waiting for new data
++ *
++ * CONTEXT: any, softirq expected
++ */
++static void data_dma_cb(void *data)
++{
++	struct fpga_device *priv = data;
++	unsigned long flags;
++
++	spin_lock_irqsave(&priv->lock, flags);
++
++	/* If there is no inflight buffer, we've got a bug */
++	BUG_ON(priv->inflight == NULL);
++
++	/* Move the inflight buffer onto the used list */
++	list_move_tail(&priv->inflight->entry, &priv->used);
++	priv->inflight = NULL;
++
++	/* clear the FPGA status and re-enable interrupts */
++	data_enable_interrupts(priv);
++
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	/*
++	 * We've changed both the inflight and used lists, so we need
++	 * to wake up any processes that are blocking for those events
++	 */
++	wake_up(&priv->wait);
++}
++
++/**
++ * data_submit_dma() - prepare and submit the required DMA to fill a buffer
++ * @priv: the driver's private data structure
++ * @buf: the data buffer
++ *
++ * Prepare and submit the necessary DMA transactions to fill a correlation
++ * data buffer.
++ *
++ * LOCKING: must hold dev->lock
++ * CONTEXT: hardirq only
++ *
++ * Returns 0 on success, -ERRNO otherwise
++ */
++static int data_submit_dma(struct fpga_device *priv, struct data_buf *buf)
++{
++	struct scatterlist *dst_sg, *src_sg;
++	unsigned int dst_nents, src_nents;
++	struct dma_chan *chan = priv->chan;
++	struct dma_async_tx_descriptor *tx;
++	dma_cookie_t cookie;
++	dma_addr_t dst, src;
++
++	dst_sg = buf->vb.sglist;
++	dst_nents = buf->vb.sglen;
++
++	src_sg = priv->corl_table.sgl;
++	src_nents = priv->corl_nents;
++
++	/*
++	 * All buffers passed to this function should be ready and mapped
++	 * for DMA already. Therefore, we don't need to do anything except
++	 * submit it to the Freescale DMA Engine for processing
++	 */
++
++	/* setup the scatterlist to scatterlist transfer */
++	tx = chan->device->device_prep_dma_sg(chan,
++					      dst_sg, dst_nents,
++					      src_sg, src_nents,
++					      0);
++	if (!tx) {
++		dev_err(priv->dev, "unable to prep scatterlist DMA\n");
++		return -ENOMEM;
++	}
++
++	/* submit the transaction to the DMA controller */
++	cookie = tx->tx_submit(tx);
++	if (dma_submit_error(cookie)) {
++		dev_err(priv->dev, "unable to submit scatterlist DMA\n");
++		return -ENOMEM;
++	}
++
++	/* Prepare the re-read of the SYS-FPGA block */
++	dst = sg_dma_address(dst_sg) + (NUM_FPGA * REG_BLOCK_SIZE);
++	src = SYS_FPGA_BLOCK;
++	tx = chan->device->device_prep_dma_memcpy(chan, dst, src,
++						  REG_BLOCK_SIZE,
++						  DMA_PREP_INTERRUPT);
++	if (!tx) {
++		dev_err(priv->dev, "unable to prep SYS-FPGA DMA\n");
++		return -ENOMEM;
++	}
++
++	/* Setup the callback */
++	tx->callback = data_dma_cb;
++	tx->callback_param = priv;
++
++	/* submit the transaction to the DMA controller */
++	cookie = tx->tx_submit(tx);
++	if (dma_submit_error(cookie)) {
++		dev_err(priv->dev, "unable to submit SYS-FPGA DMA\n");
++		return -ENOMEM;
++	}
++
++	return 0;
++}
++
++#define CORL_DONE	0x1
++#define CORL_ERR	0x2
++
++static irqreturn_t data_irq(int irq, void *dev_id)
++{
++	struct fpga_device *priv = dev_id;
++	bool submitted = false;
++	struct data_buf *buf;
++	u32 status;
++	int i;
++
++	/* detect spurious interrupts via FPGA status */
++	for (i = 0; i < 4; i++) {
++		status = fpga_read_reg(priv, i, MMAP_REG_STATUS);
++		if (!(status & (CORL_DONE | CORL_ERR))) {
++			dev_err(priv->dev, "spurious irq detected (FPGA)\n");
++			return IRQ_NONE;
++		}
++	}
++
++	/* detect spurious interrupts via raw IRQ pin readback */
++	status = ioread32be(priv->regs + SYS_IRQ_INPUT_DATA);
++	if (status & IRQ_CORL_DONE) {
++		dev_err(priv->dev, "spurious irq detected (IRQ)\n");
++		return IRQ_NONE;
++	}
++
++	spin_lock(&priv->lock);
++
++	/* hide the interrupt by switching the IRQ driver to GPIO */
++	data_disable_interrupts(priv);
++
++	/* If there are no free buffers, drop this data */
++	if (list_empty(&priv->free)) {
++		priv->num_dropped++;
++		goto out;
++	}
++
++	buf = list_first_entry(&priv->free, struct data_buf, entry);
++	list_del_init(&buf->entry);
++	BUG_ON(buf->size != priv->bufsize);
++
++	/* Submit a DMA transfer to get the correlation data */
++	if (data_submit_dma(priv, buf)) {
++		dev_err(priv->dev, "Unable to setup DMA transfer\n");
++		list_move_tail(&buf->entry, &priv->free);
++		goto out;
++	}
++
++	/* Save the buffer for the DMA callback */
++	priv->inflight = buf;
++	submitted = true;
++
++	/* Start the DMA Engine */
++	dma_async_memcpy_issue_pending(priv->chan);
++
++out:
++	/* If no DMA was submitted, re-enable interrupts */
++	if (!submitted)
++		data_enable_interrupts(priv);
++
++	spin_unlock(&priv->lock);
++	return IRQ_HANDLED;
++}
++
++/*
++ * Realtime Device Enable Helpers
++ */
++
++/**
++ * data_device_enable() - enable the device for buffered dumping
++ * @priv: the driver's private data structure
++ *
++ * Enable the device for buffered dumping. Allocates buffers and hooks up
++ * the interrupt handler. When this finishes, data will come pouring in.
++ *
++ * LOCKING: must hold dev->mutex
++ * CONTEXT: user context only
++ *
++ * Returns 0 on success, -ERRNO otherwise
++ */
++static int data_device_enable(struct fpga_device *priv)
++{
++	u32 val;
++	int ret;
++
++	/* multiple enables are safe: they do nothing */
++	if (priv->enabled)
++		return 0;
++
++	/* check that the FPGAs are programmed */
++	val = ioread32be(priv->regs + SYS_FPGA_CONFIG_STATUS);
++	if (!(val & (1 << 18))) {
++		dev_err(priv->dev, "DATA-FPGAs are not enabled\n");
++		return -ENODATA;
++	}
++
++	/* read the FPGAs to calculate the buffer size */
++	ret = data_calculate_bufsize(priv);
++	if (ret) {
++		dev_err(priv->dev, "unable to calculate buffer size\n");
++		goto out_error;
++	}
++
++	/* allocate the correlation data buffers */
++	ret = data_alloc_buffers(priv);
++	if (ret) {
++		dev_err(priv->dev, "unable to allocate buffers\n");
++		goto out_error;
++	}
++
++	/* setup the source scatterlist for dumping correlation data */
++	ret = data_setup_corl_table(priv);
++	if (ret) {
++		dev_err(priv->dev, "unable to setup correlation DMA table\n");
++		goto out_error;
++	}
++
++	/* hookup the irq handler */
++	ret = request_irq(priv->irq, data_irq, IRQF_SHARED, drv_name, priv);
++	if (ret) {
++		dev_err(priv->dev, "unable to request IRQ handler\n");
++		goto out_error;
++	}
++
++	/* switch to the external FPGA IRQ line */
++	data_enable_interrupts(priv);
++
++	/* success, we're enabled */
++	priv->enabled = true;
++	return 0;
++
++out_error:
++	sg_free_table(&priv->corl_table);
++	priv->corl_nents = 0;
++
++	data_free_buffers(priv);
++	return ret;
++}
++
++/**
++ * data_device_disable() - disable the device for buffered dumping
++ * @priv: the driver's private data structure
++ *
++ * Disable the device for buffered dumping. Stops new DMA transactions from
++ * being generated, waits for all outstanding DMA to complete, and then frees
++ * all buffers.
++ *
++ * LOCKING: must hold dev->mutex
++ * CONTEXT: user only
++ *
++ * Returns 0 on success, -ERRNO otherwise
++ */
++static int data_device_disable(struct fpga_device *priv)
++{
++	int ret;
++
++	/* allow multiple disable */
++	if (!priv->enabled)
++		return 0;
++
++	/* switch to the internal GPIO IRQ line */
++	data_disable_interrupts(priv);
++
++	/* unhook the irq handler */
++	free_irq(priv->irq, priv);
++
++	/*
++	 * wait for all outstanding DMA to complete
++	 *
++	 * Device interrupts are disabled, therefore another buffer cannot
++	 * be marked inflight.
++	 */
++	ret = wait_event_interruptible(priv->wait, priv->inflight == NULL);
++	if (ret)
++		return ret;
++
++	/* free the correlation table */
++	sg_free_table(&priv->corl_table);
++	priv->corl_nents = 0;
++
++	/*
++	 * We are taking the spinlock not to protect priv->enabled, but instead
++	 * to make sure that there are no readers in the process of altering
++	 * the free or used lists while we are setting this flag.
++	 */
++	spin_lock_irq(&priv->lock);
++	priv->enabled = false;
++	spin_unlock_irq(&priv->lock);
++
++	/* free all buffers: the free and used lists are not being changed */
++	data_free_buffers(priv);
++	return 0;
++}
++
++/*
++ * DEBUGFS Interface
++ */
++#ifdef CONFIG_DEBUG_FS
++
++/*
++ * Count the number of entries in the given list
++ */
++static unsigned int list_num_entries(struct list_head *list)
++{
++	struct list_head *entry;
++	unsigned int ret = 0;
++
++	list_for_each(entry, list)
++		ret++;
++
++	return ret;
++}
++
++static int data_debug_show(struct seq_file *f, void *offset)
++{
++	struct fpga_device *priv = f->private;
++	int ret;
++
++	/*
++	 * Lock the mutex first, so that we get an accurate value for enable
++	 * Lock the spinlock next, to get accurate list counts
++	 */
++	ret = mutex_lock_interruptible(&priv->mutex);
++	if (ret)
++		return ret;
++
++	spin_lock_irq(&priv->lock);
++
++	seq_printf(f, "enabled: %d\n", priv->enabled);
++	seq_printf(f, "bufsize: %d\n", priv->bufsize);
++	seq_printf(f, "num_buffers: %d\n", priv->num_buffers);
++	seq_printf(f, "num_free: %d\n", list_num_entries(&priv->free));
++	seq_printf(f, "inflight: %d\n", priv->inflight != NULL);
++	seq_printf(f, "num_used: %d\n", list_num_entries(&priv->used));
++	seq_printf(f, "num_dropped: %d\n", priv->num_dropped);
++
++	spin_unlock_irq(&priv->lock);
++	mutex_unlock(&priv->mutex);
++	return 0;
++}
++
++static int data_debug_open(struct inode *inode, struct file *file)
++{
++	return single_open(file, data_debug_show, inode->i_private);
++}
++
++static const struct file_operations data_debug_fops = {
++	.owner		= THIS_MODULE,
++	.open		= data_debug_open,
++	.read		= seq_read,
++	.llseek		= seq_lseek,
++	.release	= single_release,
++};
++
++static int data_debugfs_init(struct fpga_device *priv)
++{
++	priv->dbg_entry = debugfs_create_file(drv_name, S_IRUGO, NULL, priv,
++					      &data_debug_fops);
++	if (IS_ERR(priv->dbg_entry))
++		return PTR_ERR(priv->dbg_entry);
++
++	return 0;
++}
++
++static void data_debugfs_exit(struct fpga_device *priv)
++{
++	debugfs_remove(priv->dbg_entry);
++}
++
++#else
++
++static inline int data_debugfs_init(struct fpga_device *priv)
++{
++	return 0;
++}
++
++static inline void data_debugfs_exit(struct fpga_device *priv)
++{
++}
++
++#endif	/* CONFIG_DEBUG_FS */
++
++/*
++ * SYSFS Attributes
++ */
++
++static ssize_t data_en_show(struct device *dev, struct device_attribute *attr,
++			    char *buf)
++{
++	struct fpga_device *priv = dev_get_drvdata(dev);
++	return snprintf(buf, PAGE_SIZE, "%u\n", priv->enabled);
++}
++
++static ssize_t data_en_set(struct device *dev, struct device_attribute *attr,
++			   const char *buf, size_t count)
++{
++	struct fpga_device *priv = dev_get_drvdata(dev);
++	unsigned long enable;
++	int ret;
++
++	ret = strict_strtoul(buf, 0, &enable);
++	if (ret) {
++		dev_err(priv->dev, "unable to parse enable input\n");
++		return -EINVAL;
++	}
++
++	ret = mutex_lock_interruptible(&priv->mutex);
++	if (ret)
++		return ret;
++
++	if (enable)
++		ret = data_device_enable(priv);
++	else
++		ret = data_device_disable(priv);
++
++	if (ret) {
++		dev_err(priv->dev, "device %s failed\n",
++			enable ? "enable" : "disable");
++		count = ret;
++		goto out_unlock;
++	}
++
++out_unlock:
++	mutex_unlock(&priv->mutex);
++	return count;
++}
++
++static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO, data_en_show, data_en_set);
++
++static struct attribute *data_sysfs_attrs[] = {
++	&dev_attr_enable.attr,
++	NULL,
++};
++
++static const struct attribute_group rt_sysfs_attr_group = {
++	.attrs = data_sysfs_attrs,
++};
++
++/*
++ * FPGA Realtime Data Character Device
++ */
++
++static int data_open(struct inode *inode, struct file *filp)
++{
++	/*
++	 * The miscdevice layer puts our struct miscdevice into the
++	 * filp->private_data field. We use this to find our private
++	 * data and then overwrite it with our own private structure.
++	 */
++	struct fpga_device *priv = container_of(filp->private_data,
++						struct fpga_device, miscdev);
++	struct fpga_reader *reader;
++	int ret;
++
++	/* allocate private data */
++	reader = kzalloc(sizeof(*reader), GFP_KERNEL);
++	if (!reader)
++		return -ENOMEM;
++
++	reader->priv = priv;
++	reader->buf = NULL;
++
++	filp->private_data = reader;
++	ret = nonseekable_open(inode, filp);
++	if (ret) {
++		dev_err(priv->dev, "nonseekable-open failed\n");
++		kfree(reader);
++		return ret;
++	}
++
++	/*
++	 * success, increase the reference count of the private data structure
++	 * so that it doesn't disappear if the device is unbound
++	 */
++	kref_get(&priv->ref);
++	return 0;
++}
++
++static int data_release(struct inode *inode, struct file *filp)
++{
++	struct fpga_reader *reader = filp->private_data;
++	struct fpga_device *priv = reader->priv;
++
++	/* free the per-reader structure */
++	data_free_buffer(reader->buf);
++	kfree(reader);
++	filp->private_data = NULL;
++
++	/* decrement our reference count to the private data */
++	kref_put(&priv->ref, fpga_device_release);
++	return 0;
++}
++
++static ssize_t data_read(struct file *filp, char __user *ubuf, size_t count,
++			 loff_t *f_pos)
++{
++	struct fpga_reader *reader = filp->private_data;
++	struct fpga_device *priv = reader->priv;
++	struct list_head *used = &priv->used;
++	struct data_buf *dbuf;
++	size_t avail;
++	void *data;
++	int ret;
++
++	/* check if we already have a partial buffer */
++	if (reader->buf) {
++		dbuf = reader->buf;
++		goto have_buffer;
++	}
++
++	spin_lock_irq(&priv->lock);
++
++	/* Block until there is at least one buffer on the used list */
++	while (list_empty(used)) {
++		spin_unlock_irq(&priv->lock);
++
++		if (filp->f_flags & O_NONBLOCK)
++			return -EAGAIN;
++
++		ret = wait_event_interruptible(priv->wait, !list_empty(used));
++		if (ret)
++			return ret;
++
++		spin_lock_irq(&priv->lock);
++	}
++
++	/* Grab the first buffer off of the used list */
++	dbuf = list_first_entry(used, struct data_buf, entry);
++	list_del_init(&dbuf->entry);
++
++	spin_unlock_irq(&priv->lock);
++
++	/* Buffers are always mapped: unmap it */
++	videobuf_dma_unmap(priv->dev, &dbuf->vb);
++
++	/* save the buffer for later */
++	reader->buf = dbuf;
++	reader->buf_start = 0;
++
++have_buffer:
++	/* Get the number of bytes available */
++	avail = dbuf->size - reader->buf_start;
++	data = dbuf->vb.vaddr + reader->buf_start;
++
++	/* Get the number of bytes we can transfer */
++	count = min(count, avail);
++
++	/* Copy the data to the userspace buffer */
++	if (copy_to_user(ubuf, data, count))
++		return -EFAULT;
++
++	/* Update the amount of available space */
++	avail -= count;
++
++	/*
++	 * If there is still some data available, save the buffer for the
++	 * next userspace call to read() and return
++	 */
++	if (avail > 0) {
++		reader->buf_start += count;
++		reader->buf = dbuf;
++		return count;
++	}
++
++	/*
++	 * Get the buffer ready to be reused for DMA
++	 *
++	 * If it fails, we pretend that the read never happed and return
++	 * -EFAULT to userspace. The read will be retried.
++	 */
++	ret = videobuf_dma_map(priv->dev, &dbuf->vb);
++	if (ret) {
++		dev_err(priv->dev, "unable to remap buffer for DMA\n");
++		return -EFAULT;
++	}
++
++	/* Lock against concurrent enable/disable */
++	spin_lock_irq(&priv->lock);
++
++	/* the reader is finished with this buffer */
++	reader->buf = NULL;
++
++	/*
++	 * One of two things has happened, the device is disabled, or the
++	 * device has been reconfigured underneath us. In either case, we
++	 * should just throw away the buffer.
++	 */
++	if (!priv->enabled || dbuf->size != priv->bufsize) {
++		videobuf_dma_unmap(priv->dev, &dbuf->vb);
++		data_free_buffer(dbuf);
++		goto out_unlock;
++	}
++
++	/* The buffer is safe to reuse, so add it back to the free list */
++	list_add_tail(&dbuf->entry, &priv->free);
++
++out_unlock:
++	spin_unlock_irq(&priv->lock);
++	return count;
++}
++
++static unsigned int data_poll(struct file *filp, struct poll_table_struct *tbl)
++{
++	struct fpga_reader *reader = filp->private_data;
++	struct fpga_device *priv = reader->priv;
++	unsigned int mask = 0;
++
++	poll_wait(filp, &priv->wait, tbl);
++
++	if (!list_empty(&priv->used))
++		mask |= POLLIN | POLLRDNORM;
++
++	return mask;
++}
++
++static int data_mmap(struct file *filp, struct vm_area_struct *vma)
++{
++	struct fpga_reader *reader = filp->private_data;
++	struct fpga_device *priv = reader->priv;
++	unsigned long offset, vsize, psize, addr;
++
++	/* VMA properties */
++	offset = vma->vm_pgoff << PAGE_SHIFT;
++	vsize = vma->vm_end - vma->vm_start;
++	psize = priv->phys_size - offset;
++	addr = (priv->phys_addr + offset) >> PAGE_SHIFT;
++
++	/* Check against the FPGA region's physical memory size */
++	if (vsize > psize) {
++		dev_err(priv->dev, "requested mmap mapping too large\n");
++		return -EINVAL;
++	}
++
++	/* IO memory (stop cacheing) */
++	vma->vm_flags |= VM_IO | VM_RESERVED;
++	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
++
++	return io_remap_pfn_range(vma, vma->vm_start, addr, vsize,
++				  vma->vm_page_prot);
++}
++
++static const struct file_operations data_fops = {
++	.owner		= THIS_MODULE,
++	.open		= data_open,
++	.release	= data_release,
++	.read		= data_read,
++	.poll		= data_poll,
++	.mmap		= data_mmap,
++	.llseek		= no_llseek,
++};
++
++/*
++ * OpenFirmware Device Subsystem
++ */
++
++static bool dma_filter(struct dma_chan *chan, void *data)
++{
++	/*
++	 * DMA Channel #0 is used for the FPGA Programmer, so ignore it
++	 *
++	 * This probably won't survive an unload/load cycle of the Freescale
++	 * DMAEngine driver, but that won't be a problem
++	 */
++	if (chan->chan_id == 0 && chan->device->dev_id == 0)
++		return false;
++
++	return true;
++}
++
++static int data_of_probe(struct platform_device *op,
++			 const struct of_device_id *match)
++{
++	struct device_node *of_node = op->dev.of_node;
++	struct device *this_device;
++	struct fpga_device *priv;
++	struct resource res;
++	dma_cap_mask_t mask;
++	int ret;
++
++	/* Allocate private data */
++	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
++	if (!priv) {
++		dev_err(&op->dev, "Unable to allocate device private data\n");
++		ret = -ENOMEM;
++		goto out_return;
++	}
++
++	dev_set_drvdata(&op->dev, priv);
++	priv->dev = &op->dev;
++	kref_init(&priv->ref);
++	mutex_init(&priv->mutex);
++
++	dev_set_drvdata(priv->dev, priv);
++	spin_lock_init(&priv->lock);
++	INIT_LIST_HEAD(&priv->free);
++	INIT_LIST_HEAD(&priv->used);
++	init_waitqueue_head(&priv->wait);
++
++	/* Setup the misc device */
++	priv->miscdev.minor = MISC_DYNAMIC_MINOR;
++	priv->miscdev.name = drv_name;
++	priv->miscdev.fops = &data_fops;
++
++	/* Get the physical address of the FPGA registers */
++	ret = of_address_to_resource(of_node, 0, &res);
++	if (ret) {
++		dev_err(&op->dev, "Unable to find FPGA physical address\n");
++		ret = -ENODEV;
++		goto out_free_priv;
++	}
++
++	priv->phys_addr = res.start;
++	priv->phys_size = resource_size(&res);
++
++	/* ioremap the registers for use */
++	priv->regs = of_iomap(of_node, 0);
++	if (!priv->regs) {
++		dev_err(&op->dev, "Unable to ioremap registers\n");
++		ret = -ENOMEM;
++		goto out_free_priv;
++	}
++
++	dma_cap_zero(mask);
++	dma_cap_set(DMA_MEMCPY, mask);
++	dma_cap_set(DMA_INTERRUPT, mask);
++	dma_cap_set(DMA_SLAVE, mask);
++	dma_cap_set(DMA_SG, mask);
++
++	/* Request a DMA channel */
++	priv->chan = dma_request_channel(mask, dma_filter, NULL);
++	if (!priv->chan) {
++		dev_err(&op->dev, "Unable to request DMA channel\n");
++		ret = -ENODEV;
++		goto out_unmap_regs;
++	}
++
++	/* Find the correct IRQ number */
++	priv->irq = irq_of_parse_and_map(of_node, 0);
++	if (priv->irq == NO_IRQ) {
++		dev_err(&op->dev, "Unable to find IRQ line\n");
++		ret = -ENODEV;
++		goto out_release_dma;
++	}
++
++	/* Drive the GPIO for FPGA IRQ high (no interrupt) */
++	iowrite32be(IRQ_CORL_DONE, priv->regs + SYS_IRQ_OUTPUT_DATA);
++
++	/* Register the miscdevice */
++	ret = misc_register(&priv->miscdev);
++	if (ret) {
++		dev_err(&op->dev, "Unable to register miscdevice\n");
++		goto out_irq_dispose_mapping;
++	}
++
++	/* Create the debugfs files */
++	ret = data_debugfs_init(priv);
++	if (ret) {
++		dev_err(&op->dev, "Unable to create debugfs files\n");
++		goto out_misc_deregister;
++	}
++
++	/* Create the sysfs files */
++	this_device = priv->miscdev.this_device;
++	dev_set_drvdata(this_device, priv);
++	ret = sysfs_create_group(&this_device->kobj, &rt_sysfs_attr_group);
++	if (ret) {
++		dev_err(&op->dev, "Unable to create sysfs files\n");
++		goto out_data_debugfs_exit;
++	}
++
++	dev_info(&op->dev, "CARMA FPGA Realtime Data Driver Loaded\n");
++	return 0;
++
++out_data_debugfs_exit:
++	data_debugfs_exit(priv);
++out_misc_deregister:
++	misc_deregister(&priv->miscdev);
++out_irq_dispose_mapping:
++	irq_dispose_mapping(priv->irq);
++out_release_dma:
++	dma_release_channel(priv->chan);
++out_unmap_regs:
++	iounmap(priv->regs);
++out_free_priv:
++	kref_put(&priv->ref, fpga_device_release);
++out_return:
++	return ret;
++}
++
++static int data_of_remove(struct platform_device *op)
++{
++	struct fpga_device *priv = dev_get_drvdata(&op->dev);
++	struct device *this_device = priv->miscdev.this_device;
++
++	/* remove all sysfs files, now the device cannot be re-enabled */
++	sysfs_remove_group(&this_device->kobj, &rt_sysfs_attr_group);
++
++	/* remove all debugfs files */
++	data_debugfs_exit(priv);
++
++	/* disable the device from generating data */
++	data_device_disable(priv);
++
++	/* remove the character device to stop new readers from appearing */
++	misc_deregister(&priv->miscdev);
++
++	/* cleanup everything not needed by readers */
++	irq_dispose_mapping(priv->irq);
++	dma_release_channel(priv->chan);
++	iounmap(priv->regs);
++
++	/* release our reference */
++	kref_put(&priv->ref, fpga_device_release);
++	return 0;
++}
++
++static struct of_device_id data_of_match[] = {
++	{ .compatible = "carma,carma-fpga", },
++	{},
++};
++
++static struct of_platform_driver data_of_driver = {
++	.probe		= data_of_probe,
++	.remove		= data_of_remove,
++	.driver		= {
++		.name		= drv_name,
++		.of_match_table	= data_of_match,
++		.owner		= THIS_MODULE,
++	},
++};
++
++/*
++ * Module Init / Exit
++ */
++
++static int __init data_init(void)
++{
++	return of_register_platform_driver(&data_of_driver);
++}
++
++static void __exit data_exit(void)
++{
++	of_unregister_platform_driver(&data_of_driver);
++}
++
++MODULE_AUTHOR("Ira W. Snyder ");
++MODULE_DESCRIPTION("CARMA DATA-FPGA Access Driver");
++MODULE_LICENSE("GPL");
++
++module_init(data_init);
++module_exit(data_exit);

commit 8faa7cf828bca1745a4ed599876567f5afc47544
+Author: Ira W. Snyder 
+Date:   Thu Apr 7 10:33:03 2011 -0700
+
+    dt/fsldma: fix build warning caused by of_platform_device changes
+    
+    Commit 000061245a6797d542854106463b6b20fbdcb12e, "dt/powerpc:
+    Eliminate users of of_platform_{,un}register_driver" forgot to convert
+    the type of structure passed into platform_device_register() when it
+    was converted from of_platform_device_register. Fix it.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Grant Likely 
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index 6b396759e7f5..8a781540590c 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -1448,7 +1448,7 @@ static const struct of_device_id fsldma_of_ids[] = {
+ 	{}
+ };
+ 
+-static struct of_platform_driver fsldma_of_driver = {
++static struct platform_driver fsldma_of_driver = {
+ 	.driver = {
+ 		.name = "fsl-elo-dma",
+ 		.owner = THIS_MODULE,

commit a00ae34ac8bc8a5897d9b6b9b685c39b955b14b9
+Author: Ira Snyder 
+Date:   Thu Mar 3 07:55:01 2011 +0000
+
+    fsldma: make halt behave nicely on all supported controllers
+    
+    The original dma_halt() function set the CA (channel abort) bit on both
+    the 83xx and 85xx controllers. This is incorrect on the 83xx, where this
+    bit means TEM (transfer error mask) instead. The 83xx doesn't support
+    channel abort, so we only do this operation on 85xx.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Dan Williams 
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index d300de456c90..8670a5012122 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -221,13 +221,26 @@ static void dma_halt(struct fsldma_chan *chan)
+ 	u32 mode;
+ 	int i;
+ 
++	/* read the mode register */
+ 	mode = DMA_IN(chan, &chan->regs->mr, 32);
+-	mode |= FSL_DMA_MR_CA;
+-	DMA_OUT(chan, &chan->regs->mr, mode, 32);
+ 
+-	mode &= ~(FSL_DMA_MR_CS | FSL_DMA_MR_EMS_EN | FSL_DMA_MR_CA);
++	/*
++	 * The 85xx controller supports channel abort, which will stop
++	 * the current transfer. On 83xx, this bit is the transfer error
++	 * mask bit, which should not be changed.
++	 */
++	if ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
++		mode |= FSL_DMA_MR_CA;
++		DMA_OUT(chan, &chan->regs->mr, mode, 32);
++
++		mode &= ~FSL_DMA_MR_CA;
++	}
++
++	/* stop the DMA controller */
++	mode &= ~(FSL_DMA_MR_CS | FSL_DMA_MR_EMS_EN);
+ 	DMA_OUT(chan, &chan->regs->mr, mode, 32);
+ 
++	/* wait for the DMA controller to become idle */
+ 	for (i = 0; i < 100; i++) {
+ 		if (dma_is_idle(chan))
+ 			return;

commit dc8d4091575ba81e886ebcdfd1e559c981f82f86
+Author: Ira Snyder 
+Date:   Thu Mar 3 07:55:00 2011 +0000
+
+    fsldma: reduce locking during descriptor cleanup
+    
+    This merges the fsl_chan_ld_cleanup() function into the dma_do_tasklet()
+    function to reduce locking overhead. In the best case, we will be able
+    to keep the DMA controller busy while we are freeing used descriptors.
+    In all cases, the spinlock is grabbed two times fewer than before on
+    each transaction.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Dan Williams 
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index 526579df6033..d300de456c90 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -881,66 +881,16 @@ static void fsldma_cleanup_descriptor(struct fsldma_chan *chan,
+ 	dma_pool_free(chan->desc_pool, desc, txd->phys);
+ }
+ 
+-/**
+- * fsl_chan_ld_cleanup - Clean up link descriptors
+- * @chan : Freescale DMA channel
+- *
+- * This function is run after the queue of running descriptors has been
+- * executed by the DMA engine. It will run any callbacks, and then free
+- * the descriptors.
+- *
+- * HARDWARE STATE: idle
+- */
+-static void fsl_chan_ld_cleanup(struct fsldma_chan *chan)
+-{
+-	struct fsl_desc_sw *desc, *_desc;
+-	LIST_HEAD(ld_cleanup);
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&chan->desc_lock, flags);
+-
+-	/* update the cookie if we have some descriptors to cleanup */
+-	if (!list_empty(&chan->ld_running)) {
+-		dma_cookie_t cookie;
+-
+-		desc = to_fsl_desc(chan->ld_running.prev);
+-		cookie = desc->async_tx.cookie;
+-
+-		chan->completed_cookie = cookie;
+-		chan_dbg(chan, "completed cookie=%d\n", cookie);
+-	}
+-
+-	/*
+-	 * move the descriptors to a temporary list so we can drop the lock
+-	 * during the entire cleanup operation
+-	 */
+-	list_splice_tail_init(&chan->ld_running, &ld_cleanup);
+-
+-	spin_unlock_irqrestore(&chan->desc_lock, flags);
+-
+-	/* Run the callback for each descriptor, in order */
+-	list_for_each_entry_safe(desc, _desc, &ld_cleanup, node) {
+-
+-		/* Remove from the list of transactions */
+-		list_del(&desc->node);
+-
+-		/* Run all cleanup for this descriptor */
+-		fsldma_cleanup_descriptor(chan, desc);
+-	}
+-}
+-
+ /**
+  * fsl_chan_xfer_ld_queue - transfer any pending transactions
+  * @chan : Freescale DMA channel
+  *
+  * HARDWARE STATE: idle
++ * LOCKING: must hold chan->desc_lock
+  */
+ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan)
+ {
+ 	struct fsl_desc_sw *desc;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&chan->desc_lock, flags);
+ 
+ 	/*
+ 	 * If the list of pending descriptors is empty, then we
+@@ -948,7 +898,7 @@ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan)
+ 	 */
+ 	if (list_empty(&chan->ld_pending)) {
+ 		chan_dbg(chan, "no pending LDs\n");
+-		goto out_unlock;
++		return;
+ 	}
+ 
+ 	/*
+@@ -958,7 +908,7 @@ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan)
+ 	 */
+ 	if (!chan->idle) {
+ 		chan_dbg(chan, "DMA controller still busy\n");
+-		goto out_unlock;
++		return;
+ 	}
+ 
+ 	/*
+@@ -996,9 +946,6 @@ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan)
+ 
+ 	dma_start(chan);
+ 	chan->idle = false;
+-
+-out_unlock:
+-	spin_unlock_irqrestore(&chan->desc_lock, flags);
+ }
+ 
+ /**
+@@ -1008,7 +955,11 @@ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan)
+ static void fsl_dma_memcpy_issue_pending(struct dma_chan *dchan)
+ {
+ 	struct fsldma_chan *chan = to_fsl_chan(dchan);
++	unsigned long flags;
++
++	spin_lock_irqsave(&chan->desc_lock, flags);
+ 	fsl_chan_xfer_ld_queue(chan);
++	spin_unlock_irqrestore(&chan->desc_lock, flags);
+ }
+ 
+ /**
+@@ -1109,20 +1060,53 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
+ static void dma_do_tasklet(unsigned long data)
+ {
+ 	struct fsldma_chan *chan = (struct fsldma_chan *)data;
++	struct fsl_desc_sw *desc, *_desc;
++	LIST_HEAD(ld_cleanup);
+ 	unsigned long flags;
+ 
+ 	chan_dbg(chan, "tasklet entry\n");
+ 
+-	/* run all callbacks, free all used descriptors */
+-	fsl_chan_ld_cleanup(chan);
+-
+-	/* the channel is now idle */
+ 	spin_lock_irqsave(&chan->desc_lock, flags);
++
++	/* update the cookie if we have some descriptors to cleanup */
++	if (!list_empty(&chan->ld_running)) {
++		dma_cookie_t cookie;
++
++		desc = to_fsl_desc(chan->ld_running.prev);
++		cookie = desc->async_tx.cookie;
++
++		chan->completed_cookie = cookie;
++		chan_dbg(chan, "completed_cookie=%d\n", cookie);
++	}
++
++	/*
++	 * move the descriptors to a temporary list so we can drop the lock
++	 * during the entire cleanup operation
++	 */
++	list_splice_tail_init(&chan->ld_running, &ld_cleanup);
++
++	/* the hardware is now idle and ready for more */
+ 	chan->idle = true;
+-	spin_unlock_irqrestore(&chan->desc_lock, flags);
+ 
+-	/* start any pending transactions automatically */
++	/*
++	 * Start any pending transactions automatically
++	 *
++	 * In the ideal case, we keep the DMA controller busy while we go
++	 * ahead and free the descriptors below.
++	 */
+ 	fsl_chan_xfer_ld_queue(chan);
++	spin_unlock_irqrestore(&chan->desc_lock, flags);
++
++	/* Run the callback for each descriptor, in order */
++	list_for_each_entry_safe(desc, _desc, &ld_cleanup, node) {
++
++		/* Remove from the list of transactions */
++		list_del(&desc->node);
++
++		/* Run all cleanup for this descriptor */
++		fsldma_cleanup_descriptor(chan, desc);
++	}
++
+ 	chan_dbg(chan, "tasklet exit\n");
+ }
+ 

commit 9c4d1e7bdeb1ed4dc0c3341d40662a6fbc5f2dc2
+Author: Ira Snyder 
+Date:   Thu Mar 3 07:54:59 2011 +0000
+
+    fsldma: support async_tx dependencies and automatic unmapping
+    
+    Previous to this patch, the dma_run_dependencies() function has been
+    called while holding desc_lock. This function can call tx_submit() for
+    other descriptors, which may try to re-grab the lock. Avoid this by
+    moving the descriptors to be cleaned up to a temporary list, and
+    dropping the lock before cleanup.
+    
+    At the same time, add support for automatic unmapping of src and dst
+    buffers, as offered by the DMAEngine API.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Dan Williams 
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index 6e9ad6edc4af..526579df6033 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -83,6 +83,11 @@ static void set_desc_cnt(struct fsldma_chan *chan,
+ 	hw->count = CPU_TO_DMA(chan, count, 32);
+ }
+ 
++static u32 get_desc_cnt(struct fsldma_chan *chan, struct fsl_desc_sw *desc)
++{
++	return DMA_TO_CPU(chan, desc->hw.count, 32);
++}
++
+ static void set_desc_src(struct fsldma_chan *chan,
+ 			 struct fsl_dma_ld_hw *hw, dma_addr_t src)
+ {
+@@ -93,6 +98,16 @@ static void set_desc_src(struct fsldma_chan *chan,
+ 	hw->src_addr = CPU_TO_DMA(chan, snoop_bits | src, 64);
+ }
+ 
++static dma_addr_t get_desc_src(struct fsldma_chan *chan,
++			       struct fsl_desc_sw *desc)
++{
++	u64 snoop_bits;
++
++	snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
++		? ((u64)FSL_DMA_SATR_SREADTYPE_SNOOP_READ << 32) : 0;
++	return DMA_TO_CPU(chan, desc->hw.src_addr, 64) & ~snoop_bits;
++}
++
+ static void set_desc_dst(struct fsldma_chan *chan,
+ 			 struct fsl_dma_ld_hw *hw, dma_addr_t dst)
+ {
+@@ -103,6 +118,16 @@ static void set_desc_dst(struct fsldma_chan *chan,
+ 	hw->dst_addr = CPU_TO_DMA(chan, snoop_bits | dst, 64);
+ }
+ 
++static dma_addr_t get_desc_dst(struct fsldma_chan *chan,
++			       struct fsl_desc_sw *desc)
++{
++	u64 snoop_bits;
++
++	snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
++		? ((u64)FSL_DMA_DATR_DWRITETYPE_SNOOP_WRITE << 32) : 0;
++	return DMA_TO_CPU(chan, desc->hw.dst_addr, 64) & ~snoop_bits;
++}
++
+ static void set_desc_next(struct fsldma_chan *chan,
+ 			  struct fsl_dma_ld_hw *hw, dma_addr_t next)
+ {
+@@ -805,6 +830,57 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
+ 	return 0;
+ }
+ 
++/**
++ * fsldma_cleanup_descriptor - cleanup and free a single link descriptor
++ * @chan: Freescale DMA channel
++ * @desc: descriptor to cleanup and free
++ *
++ * This function is used on a descriptor which has been executed by the DMA
++ * controller. It will run any callbacks, submit any dependencies, and then
++ * free the descriptor.
++ */
++static void fsldma_cleanup_descriptor(struct fsldma_chan *chan,
++				      struct fsl_desc_sw *desc)
++{
++	struct dma_async_tx_descriptor *txd = &desc->async_tx;
++	struct device *dev = chan->common.device->dev;
++	dma_addr_t src = get_desc_src(chan, desc);
++	dma_addr_t dst = get_desc_dst(chan, desc);
++	u32 len = get_desc_cnt(chan, desc);
++
++	/* Run the link descriptor callback function */
++	if (txd->callback) {
++#ifdef FSL_DMA_LD_DEBUG
++		chan_dbg(chan, "LD %p callback\n", desc);
++#endif
++		txd->callback(txd->callback_param);
++	}
++
++	/* Run any dependencies */
++	dma_run_dependencies(txd);
++
++	/* Unmap the dst buffer, if requested */
++	if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
++		if (txd->flags & DMA_COMPL_DEST_UNMAP_SINGLE)
++			dma_unmap_single(dev, dst, len, DMA_FROM_DEVICE);
++		else
++			dma_unmap_page(dev, dst, len, DMA_FROM_DEVICE);
++	}
++
++	/* Unmap the src buffer, if requested */
++	if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
++		if (txd->flags & DMA_COMPL_SRC_UNMAP_SINGLE)
++			dma_unmap_single(dev, src, len, DMA_TO_DEVICE);
++		else
++			dma_unmap_page(dev, src, len, DMA_TO_DEVICE);
++	}
++
++#ifdef FSL_DMA_LD_DEBUG
++	chan_dbg(chan, "LD %p free\n", desc);
++#endif
++	dma_pool_free(chan->desc_pool, desc, txd->phys);
++}
++
+ /**
+  * fsl_chan_ld_cleanup - Clean up link descriptors
+  * @chan : Freescale DMA channel
+@@ -818,56 +894,39 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
+ static void fsl_chan_ld_cleanup(struct fsldma_chan *chan)
+ {
+ 	struct fsl_desc_sw *desc, *_desc;
++	LIST_HEAD(ld_cleanup);
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&chan->desc_lock, flags);
+ 
+-	/* if the ld_running list is empty, there is nothing to do */
+-	if (list_empty(&chan->ld_running)) {
+-		chan_dbg(chan, "no descriptors to cleanup\n");
+-		goto out_unlock;
++	/* update the cookie if we have some descriptors to cleanup */
++	if (!list_empty(&chan->ld_running)) {
++		dma_cookie_t cookie;
++
++		desc = to_fsl_desc(chan->ld_running.prev);
++		cookie = desc->async_tx.cookie;
++
++		chan->completed_cookie = cookie;
++		chan_dbg(chan, "completed cookie=%d\n", cookie);
+ 	}
+ 
+ 	/*
+-	 * Get the last descriptor, update the cookie to it
+-	 *
+-	 * This is done before callbacks run so that clients can check the
+-	 * status of their DMA transfer inside the callback.
++	 * move the descriptors to a temporary list so we can drop the lock
++	 * during the entire cleanup operation
+ 	 */
+-	desc = to_fsl_desc(chan->ld_running.prev);
+-	chan->completed_cookie = desc->async_tx.cookie;
+-	chan_dbg(chan, "completed_cookie = %d\n", chan->completed_cookie);
++	list_splice_tail_init(&chan->ld_running, &ld_cleanup);
++
++	spin_unlock_irqrestore(&chan->desc_lock, flags);
+ 
+ 	/* Run the callback for each descriptor, in order */
+-	list_for_each_entry_safe(desc, _desc, &chan->ld_running, node) {
+-		dma_async_tx_callback callback;
+-		void *callback_param;
++	list_for_each_entry_safe(desc, _desc, &ld_cleanup, node) {
+ 
+-		/* Remove from the list of running transactions */
++		/* Remove from the list of transactions */
+ 		list_del(&desc->node);
+ 
+-		/* Run the link descriptor callback function */
+-		callback = desc->async_tx.callback;
+-		callback_param = desc->async_tx.callback_param;
+-		if (callback) {
+-			spin_unlock_irqrestore(&chan->desc_lock, flags);
+-#ifdef FSL_DMA_LD_DEBUG
+-			chan_dbg(chan, "LD %p callback\n", desc);
+-#endif
+-			callback(callback_param);
+-			spin_lock_irqsave(&chan->desc_lock, flags);
+-		}
+-
+-		/* Run any dependencies, then free the descriptor */
+-		dma_run_dependencies(&desc->async_tx);
+-#ifdef FSL_DMA_LD_DEBUG
+-		chan_dbg(chan, "LD %p free\n", desc);
+-#endif
+-		dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
++		/* Run all cleanup for this descriptor */
++		fsldma_cleanup_descriptor(chan, desc);
+ 	}
+-
+-out_unlock:
+-	spin_unlock_irqrestore(&chan->desc_lock, flags);
+ }
+ 
+ /**

commit f04cd40701deace2efb9edd7120e59366bda2118
+Author: Ira Snyder 
+Date:   Thu Mar 3 07:54:58 2011 +0000
+
+    fsldma: fix controller lockups
+    
+    Enabling poisoning in the dmapool API quickly showed that the DMA
+    controller was fetching descriptors that should not have been in use.
+    This has caused intermittent controller lockups during testing.
+    
+    I have been unable to figure out the exact set of conditions which cause
+    this to happen. However, I believe it is related to the driver using the
+    hardware registers to track whether the controller is busy or not. The
+    code can incorrectly decide that the hardware is idle due to lag between
+    register writes and the hardware actually becoming busy.
+    
+    To fix this, the driver has been reworked to explicitly track the state
+    of the hardware, rather than try to guess what it is doing based on the
+    register values.
+    
+    This has passed dmatest with 10 threads per channel, 100000 iterations
+    per thread several times without error. Previously, this would fail
+    within a few seconds.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Dan Williams 
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index 5da1a4a817e3..6e9ad6edc4af 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -68,11 +68,6 @@ static dma_addr_t get_cdar(struct fsldma_chan *chan)
+ 	return DMA_IN(chan, &chan->regs->cdar, 64) & ~FSL_DMA_SNEN;
+ }
+ 
+-static dma_addr_t get_ndar(struct fsldma_chan *chan)
+-{
+-	return DMA_IN(chan, &chan->regs->ndar, 64);
+-}
+-
+ static u32 get_bcr(struct fsldma_chan *chan)
+ {
+ 	return DMA_IN(chan, &chan->regs->bcr, 32);
+@@ -143,13 +138,11 @@ static void dma_init(struct fsldma_chan *chan)
+ 	case FSL_DMA_IP_85XX:
+ 		/* Set the channel to below modes:
+ 		 * EIE - Error interrupt enable
+-		 * EOSIE - End of segments interrupt enable (basic mode)
+ 		 * EOLNIE - End of links interrupt enable
+ 		 * BWC - Bandwidth sharing among channels
+ 		 */
+ 		DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_BWC
+-				| FSL_DMA_MR_EIE | FSL_DMA_MR_EOLNIE
+-				| FSL_DMA_MR_EOSIE, 32);
++				| FSL_DMA_MR_EIE | FSL_DMA_MR_EOLNIE, 32);
+ 		break;
+ 	case FSL_DMA_IP_83XX:
+ 		/* Set the channel to below modes:
+@@ -168,25 +161,32 @@ static int dma_is_idle(struct fsldma_chan *chan)
+ 	return (!(sr & FSL_DMA_SR_CB)) || (sr & FSL_DMA_SR_CH);
+ }
+ 
++/*
++ * Start the DMA controller
++ *
++ * Preconditions:
++ * - the CDAR register must point to the start descriptor
++ * - the MRn[CS] bit must be cleared
++ */
+ static void dma_start(struct fsldma_chan *chan)
+ {
+ 	u32 mode;
+ 
+ 	mode = DMA_IN(chan, &chan->regs->mr, 32);
+ 
+-	if ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
+-		if (chan->feature & FSL_DMA_CHAN_PAUSE_EXT) {
+-			DMA_OUT(chan, &chan->regs->bcr, 0, 32);
+-			mode |= FSL_DMA_MR_EMP_EN;
+-		} else {
+-			mode &= ~FSL_DMA_MR_EMP_EN;
+-		}
++	if (chan->feature & FSL_DMA_CHAN_PAUSE_EXT) {
++		DMA_OUT(chan, &chan->regs->bcr, 0, 32);
++		mode |= FSL_DMA_MR_EMP_EN;
++	} else {
++		mode &= ~FSL_DMA_MR_EMP_EN;
+ 	}
+ 
+-	if (chan->feature & FSL_DMA_CHAN_START_EXT)
++	if (chan->feature & FSL_DMA_CHAN_START_EXT) {
+ 		mode |= FSL_DMA_MR_EMS_EN;
+-	else
++	} else {
++		mode &= ~FSL_DMA_MR_EMS_EN;
+ 		mode |= FSL_DMA_MR_CS;
++	}
+ 
+ 	DMA_OUT(chan, &chan->regs->mr, mode, 32);
+ }
+@@ -760,14 +760,15 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
+ 
+ 	switch (cmd) {
+ 	case DMA_TERMINATE_ALL:
++		spin_lock_irqsave(&chan->desc_lock, flags);
++
+ 		/* Halt the DMA engine */
+ 		dma_halt(chan);
+ 
+-		spin_lock_irqsave(&chan->desc_lock, flags);
+-
+ 		/* Remove and free all of the descriptors in the LD queue */
+ 		fsldma_free_desc_list(chan, &chan->ld_pending);
+ 		fsldma_free_desc_list(chan, &chan->ld_running);
++		chan->idle = true;
+ 
+ 		spin_unlock_irqrestore(&chan->desc_lock, flags);
+ 		return 0;
+@@ -805,76 +806,43 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
+ }
+ 
+ /**
+- * fsl_dma_update_completed_cookie - Update the completed cookie.
++ * fsl_chan_ld_cleanup - Clean up link descriptors
+  * @chan : Freescale DMA channel
+  *
+- * CONTEXT: hardirq
++ * This function is run after the queue of running descriptors has been
++ * executed by the DMA engine. It will run any callbacks, and then free
++ * the descriptors.
++ *
++ * HARDWARE STATE: idle
+  */
+-static void fsl_dma_update_completed_cookie(struct fsldma_chan *chan)
++static void fsl_chan_ld_cleanup(struct fsldma_chan *chan)
+ {
+-	struct fsl_desc_sw *desc;
++	struct fsl_desc_sw *desc, *_desc;
+ 	unsigned long flags;
+-	dma_cookie_t cookie;
+ 
+ 	spin_lock_irqsave(&chan->desc_lock, flags);
+ 
++	/* if the ld_running list is empty, there is nothing to do */
+ 	if (list_empty(&chan->ld_running)) {
+-		chan_dbg(chan, "no running descriptors\n");
++		chan_dbg(chan, "no descriptors to cleanup\n");
+ 		goto out_unlock;
+ 	}
+ 
+-	/* Get the last descriptor, update the cookie to that */
++	/*
++	 * Get the last descriptor, update the cookie to it
++	 *
++	 * This is done before callbacks run so that clients can check the
++	 * status of their DMA transfer inside the callback.
++	 */
+ 	desc = to_fsl_desc(chan->ld_running.prev);
+-	if (dma_is_idle(chan))
+-		cookie = desc->async_tx.cookie;
+-	else {
+-		cookie = desc->async_tx.cookie - 1;
+-		if (unlikely(cookie < DMA_MIN_COOKIE))
+-			cookie = DMA_MAX_COOKIE;
+-	}
+-
+-	chan->completed_cookie = cookie;
+-
+-out_unlock:
+-	spin_unlock_irqrestore(&chan->desc_lock, flags);
+-}
+-
+-/**
+- * fsldma_desc_status - Check the status of a descriptor
+- * @chan: Freescale DMA channel
+- * @desc: DMA SW descriptor
+- *
+- * This function will return the status of the given descriptor
+- */
+-static enum dma_status fsldma_desc_status(struct fsldma_chan *chan,
+-					  struct fsl_desc_sw *desc)
+-{
+-	return dma_async_is_complete(desc->async_tx.cookie,
+-				     chan->completed_cookie,
+-				     chan->common.cookie);
+-}
+-
+-/**
+- * fsl_chan_ld_cleanup - Clean up link descriptors
+- * @chan : Freescale DMA channel
+- *
+- * This function clean up the ld_queue of DMA channel.
+- */
+-static void fsl_chan_ld_cleanup(struct fsldma_chan *chan)
+-{
+-	struct fsl_desc_sw *desc, *_desc;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&chan->desc_lock, flags);
++	chan->completed_cookie = desc->async_tx.cookie;
++	chan_dbg(chan, "completed_cookie = %d\n", chan->completed_cookie);
+ 
+-	chan_dbg(chan, "chan completed_cookie = %d\n", chan->completed_cookie);
++	/* Run the callback for each descriptor, in order */
+ 	list_for_each_entry_safe(desc, _desc, &chan->ld_running, node) {
+ 		dma_async_tx_callback callback;
+ 		void *callback_param;
+ 
+-		if (fsldma_desc_status(chan, desc) == DMA_IN_PROGRESS)
+-			break;
+-
+ 		/* Remove from the list of running transactions */
+ 		list_del(&desc->node);
+ 
+@@ -898,6 +866,7 @@ static void fsl_chan_ld_cleanup(struct fsldma_chan *chan)
+ 		dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
+ 	}
+ 
++out_unlock:
+ 	spin_unlock_irqrestore(&chan->desc_lock, flags);
+ }
+ 
+@@ -905,10 +874,7 @@ static void fsl_chan_ld_cleanup(struct fsldma_chan *chan)
+  * fsl_chan_xfer_ld_queue - transfer any pending transactions
+  * @chan : Freescale DMA channel
+  *
+- * This will make sure that any pending transactions will be run.
+- * If the DMA controller is idle, it will be started. Otherwise,
+- * the DMA controller's interrupt handler will start any pending
+- * transactions when it becomes idle.
++ * HARDWARE STATE: idle
+  */
+ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan)
+ {
+@@ -927,22 +893,15 @@ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan)
+ 	}
+ 
+ 	/*
+-	 * The DMA controller is not idle, which means the interrupt
+-	 * handler will start any queued transactions when it runs
+-	 * at the end of the current transaction
++	 * The DMA controller is not idle, which means that the interrupt
++	 * handler will start any queued transactions when it runs after
++	 * this transaction finishes
+ 	 */
+-	if (!dma_is_idle(chan)) {
++	if (!chan->idle) {
+ 		chan_dbg(chan, "DMA controller still busy\n");
+ 		goto out_unlock;
+ 	}
+ 
+-	/*
+-	 * TODO:
+-	 * make sure the dma_halt() function really un-wedges the
+-	 * controller as much as possible
+-	 */
+-	dma_halt(chan);
+-
+ 	/*
+ 	 * If there are some link descriptors which have not been
+ 	 * transferred, we need to start the controller
+@@ -952,15 +911,32 @@ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan)
+ 	 * Move all elements from the queue of pending transactions
+ 	 * onto the list of running transactions
+ 	 */
++	chan_dbg(chan, "idle, starting controller\n");
+ 	desc = list_first_entry(&chan->ld_pending, struct fsl_desc_sw, node);
+ 	list_splice_tail_init(&chan->ld_pending, &chan->ld_running);
+ 
++	/*
++	 * The 85xx DMA controller doesn't clear the channel start bit
++	 * automatically at the end of a transfer. Therefore we must clear
++	 * it in software before starting the transfer.
++	 */
++	if ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
++		u32 mode;
++
++		mode = DMA_IN(chan, &chan->regs->mr, 32);
++		mode &= ~FSL_DMA_MR_CS;
++		DMA_OUT(chan, &chan->regs->mr, mode, 32);
++	}
++
+ 	/*
+ 	 * Program the descriptor's address into the DMA controller,
+ 	 * then start the DMA transaction
+ 	 */
+ 	set_cdar(chan, desc->async_tx.phys);
++	get_cdar(chan);
++
+ 	dma_start(chan);
++	chan->idle = false;
+ 
+ out_unlock:
+ 	spin_unlock_irqrestore(&chan->desc_lock, flags);
+@@ -985,16 +961,18 @@ static enum dma_status fsl_tx_status(struct dma_chan *dchan,
+ 					struct dma_tx_state *txstate)
+ {
+ 	struct fsldma_chan *chan = to_fsl_chan(dchan);
+-	dma_cookie_t last_used;
+ 	dma_cookie_t last_complete;
++	dma_cookie_t last_used;
++	unsigned long flags;
+ 
+-	fsl_chan_ld_cleanup(chan);
++	spin_lock_irqsave(&chan->desc_lock, flags);
+ 
+-	last_used = dchan->cookie;
+ 	last_complete = chan->completed_cookie;
++	last_used = dchan->cookie;
+ 
+-	dma_set_tx_state(txstate, last_complete, last_used, 0);
++	spin_unlock_irqrestore(&chan->desc_lock, flags);
+ 
++	dma_set_tx_state(txstate, last_complete, last_used, 0);
+ 	return dma_async_is_complete(cookie, last_complete, last_used);
+ }
+ 
+@@ -1005,8 +983,6 @@ static enum dma_status fsl_tx_status(struct dma_chan *dchan,
+ static irqreturn_t fsldma_chan_irq(int irq, void *data)
+ {
+ 	struct fsldma_chan *chan = data;
+-	int update_cookie = 0;
+-	int xfer_ld_q = 0;
+ 	u32 stat;
+ 
+ 	/* save and clear the status register */
+@@ -1014,6 +990,7 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
+ 	set_sr(chan, stat);
+ 	chan_dbg(chan, "irq: stat = 0x%x\n", stat);
+ 
++	/* check that this was really our device */
+ 	stat &= ~(FSL_DMA_SR_CB | FSL_DMA_SR_CH);
+ 	if (!stat)
+ 		return IRQ_NONE;
+@@ -1028,28 +1005,9 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
+ 	 */
+ 	if (stat & FSL_DMA_SR_PE) {
+ 		chan_dbg(chan, "irq: Programming Error INT\n");
+-		if (get_bcr(chan) == 0) {
+-			/* BCR register is 0, this is a DMA_INTERRUPT async_tx.
+-			 * Now, update the completed cookie, and continue the
+-			 * next uncompleted transfer.
+-			 */
+-			update_cookie = 1;
+-			xfer_ld_q = 1;
+-		}
+ 		stat &= ~FSL_DMA_SR_PE;
+-	}
+-
+-	/*
+-	 * If the link descriptor segment transfer finishes,
+-	 * we will recycle the used descriptor.
+-	 */
+-	if (stat & FSL_DMA_SR_EOSI) {
+-		chan_dbg(chan, "irq: End-of-segments INT\n");
+-		chan_dbg(chan, "irq: clndar 0x%llx, nlndar 0x%llx\n",
+-			(unsigned long long)get_cdar(chan),
+-			(unsigned long long)get_ndar(chan));
+-		stat &= ~FSL_DMA_SR_EOSI;
+-		update_cookie = 1;
++		if (get_bcr(chan) != 0)
++			chan_err(chan, "Programming Error!\n");
+ 	}
+ 
+ 	/*
+@@ -1059,8 +1017,6 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
+ 	if (stat & FSL_DMA_SR_EOCDI) {
+ 		chan_dbg(chan, "irq: End-of-Chain link INT\n");
+ 		stat &= ~FSL_DMA_SR_EOCDI;
+-		update_cookie = 1;
+-		xfer_ld_q = 1;
+ 	}
+ 
+ 	/*
+@@ -1071,25 +1027,44 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
+ 	if (stat & FSL_DMA_SR_EOLNI) {
+ 		chan_dbg(chan, "irq: End-of-link INT\n");
+ 		stat &= ~FSL_DMA_SR_EOLNI;
+-		xfer_ld_q = 1;
+ 	}
+ 
+-	if (update_cookie)
+-		fsl_dma_update_completed_cookie(chan);
+-	if (xfer_ld_q)
+-		fsl_chan_xfer_ld_queue(chan);
++	/* check that the DMA controller is really idle */
++	if (!dma_is_idle(chan))
++		chan_err(chan, "irq: controller not idle!\n");
++
++	/* check that we handled all of the bits */
+ 	if (stat)
+-		chan_dbg(chan, "irq: unhandled sr 0x%08x\n", stat);
++		chan_err(chan, "irq: unhandled sr 0x%08x\n", stat);
+ 
+-	chan_dbg(chan, "irq: Exit\n");
++	/*
++	 * Schedule the tasklet to handle all cleanup of the current
++	 * transaction. It will start a new transaction if there is
++	 * one pending.
++	 */
+ 	tasklet_schedule(&chan->tasklet);
++	chan_dbg(chan, "irq: Exit\n");
+ 	return IRQ_HANDLED;
+ }
+ 
+ static void dma_do_tasklet(unsigned long data)
+ {
+ 	struct fsldma_chan *chan = (struct fsldma_chan *)data;
++	unsigned long flags;
++
++	chan_dbg(chan, "tasklet entry\n");
++
++	/* run all callbacks, free all used descriptors */
+ 	fsl_chan_ld_cleanup(chan);
++
++	/* the channel is now idle */
++	spin_lock_irqsave(&chan->desc_lock, flags);
++	chan->idle = true;
++	spin_unlock_irqrestore(&chan->desc_lock, flags);
++
++	/* start any pending transactions automatically */
++	fsl_chan_xfer_ld_queue(chan);
++	chan_dbg(chan, "tasklet exit\n");
+ }
+ 
+ static irqreturn_t fsldma_ctrl_irq(int irq, void *data)
+@@ -1269,6 +1244,7 @@ static int __devinit fsl_dma_chan_probe(struct fsldma_device *fdev,
+ 	spin_lock_init(&chan->desc_lock);
+ 	INIT_LIST_HEAD(&chan->ld_pending);
+ 	INIT_LIST_HEAD(&chan->ld_running);
++	chan->idle = true;
+ 
+ 	chan->common.device = &fdev->common;
+ 
+diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
+index 49189dacd5f4..9cb5aa57c677 100644
+--- a/drivers/dma/fsldma.h
++++ b/drivers/dma/fsldma.h
+@@ -148,6 +148,7 @@ struct fsldma_chan {
+ 	int id;				/* Raw id of this channel */
+ 	struct tasklet_struct tasklet;
+ 	u32 feature;
++	bool idle;			/* DMA controller is idle */
+ 
+ 	void (*toggle_ext_pause)(struct fsldma_chan *fsl_chan, int enable);
+ 	void (*toggle_ext_start)(struct fsldma_chan *fsl_chan, int enable);

commit 31f4306c83a2daa3e348056b720de511bffe5a9b
+Author: Ira Snyder 
+Date:   Thu Mar 3 07:54:57 2011 +0000
+
+    fsldma: minor codingstyle and consistency fixes
+    
+    This fixes some minor violations of the coding style. It also changes
+    the style of the device_prep_dma_*() function definitions so they are
+    identical.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Dan Williams 
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index 82b8e9f9c7bf..5da1a4a817e3 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -89,7 +89,7 @@ static void set_desc_cnt(struct fsldma_chan *chan,
+ }
+ 
+ static void set_desc_src(struct fsldma_chan *chan,
+-				struct fsl_dma_ld_hw *hw, dma_addr_t src)
++			 struct fsl_dma_ld_hw *hw, dma_addr_t src)
+ {
+ 	u64 snoop_bits;
+ 
+@@ -99,7 +99,7 @@ static void set_desc_src(struct fsldma_chan *chan,
+ }
+ 
+ static void set_desc_dst(struct fsldma_chan *chan,
+-				struct fsl_dma_ld_hw *hw, dma_addr_t dst)
++			 struct fsl_dma_ld_hw *hw, dma_addr_t dst)
+ {
+ 	u64 snoop_bits;
+ 
+@@ -109,7 +109,7 @@ static void set_desc_dst(struct fsldma_chan *chan,
+ }
+ 
+ static void set_desc_next(struct fsldma_chan *chan,
+-				struct fsl_dma_ld_hw *hw, dma_addr_t next)
++			  struct fsl_dma_ld_hw *hw, dma_addr_t next)
+ {
+ 	u64 snoop_bits;
+ 
+@@ -118,8 +118,7 @@ static void set_desc_next(struct fsldma_chan *chan,
+ 	hw->next_ln_addr = CPU_TO_DMA(chan, snoop_bits | next, 64);
+ }
+ 
+-static void set_ld_eol(struct fsldma_chan *chan,
+-			struct fsl_desc_sw *desc)
++static void set_ld_eol(struct fsldma_chan *chan, struct fsl_desc_sw *desc)
+ {
+ 	u64 snoop_bits;
+ 
+@@ -338,8 +337,7 @@ static void fsl_chan_toggle_ext_start(struct fsldma_chan *chan, int enable)
+ 		chan->feature &= ~FSL_DMA_CHAN_START_EXT;
+ }
+ 
+-static void append_ld_queue(struct fsldma_chan *chan,
+-			    struct fsl_desc_sw *desc)
++static void append_ld_queue(struct fsldma_chan *chan, struct fsl_desc_sw *desc)
+ {
+ 	struct fsl_desc_sw *tail = to_fsl_desc(chan->ld_pending.prev);
+ 
+@@ -380,8 +378,8 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
+ 	cookie = chan->common.cookie;
+ 	list_for_each_entry(child, &desc->tx_list, node) {
+ 		cookie++;
+-		if (cookie < 0)
+-			cookie = 1;
++		if (cookie < DMA_MIN_COOKIE)
++			cookie = DMA_MIN_COOKIE;
+ 
+ 		child->async_tx.cookie = cookie;
+ 	}
+@@ -402,8 +400,7 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
+  *
+  * Return - The descriptor allocated. NULL for failed.
+  */
+-static struct fsl_desc_sw *fsl_dma_alloc_descriptor(
+-					struct fsldma_chan *chan)
++static struct fsl_desc_sw *fsl_dma_alloc_descriptor(struct fsldma_chan *chan)
+ {
+ 	struct fsl_desc_sw *desc;
+ 	dma_addr_t pdesc;
+@@ -427,7 +424,6 @@ static struct fsl_desc_sw *fsl_dma_alloc_descriptor(
+ 	return desc;
+ }
+ 
+-
+ /**
+  * fsl_dma_alloc_chan_resources - Allocate resources for DMA channel.
+  * @chan : Freescale DMA channel
+@@ -537,14 +533,15 @@ fsl_dma_prep_interrupt(struct dma_chan *dchan, unsigned long flags)
+ 	/* Insert the link descriptor to the LD ring */
+ 	list_add_tail(&new->node, &new->tx_list);
+ 
+-	/* Set End-of-link to the last link descriptor of new list*/
++	/* Set End-of-link to the last link descriptor of new list */
+ 	set_ld_eol(chan, new);
+ 
+ 	return &new->async_tx;
+ }
+ 
+-static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+-	struct dma_chan *dchan, dma_addr_t dma_dst, dma_addr_t dma_src,
++static struct dma_async_tx_descriptor *
++fsl_dma_prep_memcpy(struct dma_chan *dchan,
++	dma_addr_t dma_dst, dma_addr_t dma_src,
+ 	size_t len, unsigned long flags)
+ {
+ 	struct fsldma_chan *chan;
+@@ -594,7 +591,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+ 	new->async_tx.flags = flags; /* client is in control of this ack */
+ 	new->async_tx.cookie = -EBUSY;
+ 
+-	/* Set End-of-link to the last link descriptor of new list*/
++	/* Set End-of-link to the last link descriptor of new list */
+ 	set_ld_eol(chan, new);
+ 
+ 	return &first->async_tx;
+diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
+index 113e7134010b..49189dacd5f4 100644
+--- a/drivers/dma/fsldma.h
++++ b/drivers/dma/fsldma.h
+@@ -102,8 +102,8 @@ struct fsl_desc_sw {
+ } __attribute__((aligned(32)));
+ 
+ struct fsldma_chan_regs {
+-	u32 mr;	/* 0x00 - Mode Register */
+-	u32 sr;	/* 0x04 - Status Register */
++	u32 mr;		/* 0x00 - Mode Register */
++	u32 sr;		/* 0x04 - Status Register */
+ 	u64 cdar;	/* 0x08 - Current descriptor address register */
+ 	u64 sar;	/* 0x10 - Source Address Register */
+ 	u64 dar;	/* 0x18 - Destination Address Register */

commit 0ab09c36818ca88f65c88f4d8c6d067fbf10578d
+Author: Ira Snyder 
+Date:   Thu Mar 3 07:54:56 2011 +0000
+
+    fsldma: improve link descriptor debugging
+    
+    This adds better tracking to link descriptor allocations, callbacks, and
+    frees. This makes it much easier to track errors with link descriptors.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Dan Williams 
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index e535cd13f7cc..82b8e9f9c7bf 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -420,6 +420,10 @@ static struct fsl_desc_sw *fsl_dma_alloc_descriptor(
+ 	desc->async_tx.tx_submit = fsl_dma_tx_submit;
+ 	desc->async_tx.phys = pdesc;
+ 
++#ifdef FSL_DMA_LD_DEBUG
++	chan_dbg(chan, "LD %p allocated\n", desc);
++#endif
++
+ 	return desc;
+ }
+ 
+@@ -470,6 +474,9 @@ static void fsldma_free_desc_list(struct fsldma_chan *chan,
+ 
+ 	list_for_each_entry_safe(desc, _desc, list, node) {
+ 		list_del(&desc->node);
++#ifdef FSL_DMA_LD_DEBUG
++		chan_dbg(chan, "LD %p free\n", desc);
++#endif
+ 		dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
+ 	}
+ }
+@@ -481,6 +488,9 @@ static void fsldma_free_desc_list_reverse(struct fsldma_chan *chan,
+ 
+ 	list_for_each_entry_safe_reverse(desc, _desc, list, node) {
+ 		list_del(&desc->node);
++#ifdef FSL_DMA_LD_DEBUG
++		chan_dbg(chan, "LD %p free\n", desc);
++#endif
+ 		dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
+ 	}
+ }
+@@ -557,9 +567,6 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+ 			chan_err(chan, "%s\n", msg_ld_oom);
+ 			goto fail;
+ 		}
+-#ifdef FSL_DMA_LD_DEBUG
+-		chan_dbg(chan, "new link desc alloc %p\n", new);
+-#endif
+ 
+ 		copy = min(len, (size_t)FSL_DMA_BCR_MAX_CNT);
+ 
+@@ -645,9 +652,6 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_sg(struct dma_chan *dchan,
+ 			chan_err(chan, "%s\n", msg_ld_oom);
+ 			goto fail;
+ 		}
+-#ifdef FSL_DMA_LD_DEBUG
+-		chan_dbg(chan, "new link desc alloc %p\n", new);
+-#endif
+ 
+ 		set_desc_cnt(chan, &new->hw, len);
+ 		set_desc_src(chan, &new->hw, src);
+@@ -882,13 +886,18 @@ static void fsl_chan_ld_cleanup(struct fsldma_chan *chan)
+ 		callback_param = desc->async_tx.callback_param;
+ 		if (callback) {
+ 			spin_unlock_irqrestore(&chan->desc_lock, flags);
++#ifdef FSL_DMA_LD_DEBUG
+ 			chan_dbg(chan, "LD %p callback\n", desc);
++#endif
+ 			callback(callback_param);
+ 			spin_lock_irqsave(&chan->desc_lock, flags);
+ 		}
+ 
+ 		/* Run any dependencies, then free the descriptor */
+ 		dma_run_dependencies(&desc->async_tx);
++#ifdef FSL_DMA_LD_DEBUG
++		chan_dbg(chan, "LD %p free\n", desc);
++#endif
+ 		dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
+ 	}
+ 

commit b158471ef63bf399165db96e945a828096502d9d
+Author: Ira Snyder 
+Date:   Thu Mar 3 07:54:55 2011 +0000
+
+    fsldma: use channel name in printk output
+    
+    This makes debugging the driver much easier when multiple channels are
+    running concurrently. In addition, you can see how much descriptor
+    memory each channel has allocated via the dmapool API in sysfs.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Dan Williams 
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index 2e1af4555b0f..e535cd13f7cc 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -37,7 +37,12 @@
+ 
+ #include "fsldma.h"
+ 
+-static const char msg_ld_oom[] = "No free memory for link descriptor\n";
++#define chan_dbg(chan, fmt, arg...)					\
++	dev_dbg(chan->dev, "%s: " fmt, chan->name, ##arg)
++#define chan_err(chan, fmt, arg...)					\
++	dev_err(chan->dev, "%s: " fmt, chan->name, ##arg)
++
++static const char msg_ld_oom[] = "No free memory for link descriptor";
+ 
+ /*
+  * Register Helpers
+@@ -207,7 +212,7 @@ static void dma_halt(struct fsldma_chan *chan)
+ 	}
+ 
+ 	if (!dma_is_idle(chan))
+-		dev_err(chan->dev, "DMA halt timeout!\n");
++		chan_err(chan, "DMA halt timeout!\n");
+ }
+ 
+ /**
+@@ -405,7 +410,7 @@ static struct fsl_desc_sw *fsl_dma_alloc_descriptor(
+ 
+ 	desc = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &pdesc);
+ 	if (!desc) {
+-		dev_dbg(chan->dev, "out of memory for link desc\n");
++		chan_dbg(chan, "out of memory for link descriptor\n");
+ 		return NULL;
+ 	}
+ 
+@@ -439,13 +444,11 @@ static int fsl_dma_alloc_chan_resources(struct dma_chan *dchan)
+ 	 * We need the descriptor to be aligned to 32bytes
+ 	 * for meeting FSL DMA specification requirement.
+ 	 */
+-	chan->desc_pool = dma_pool_create("fsl_dma_engine_desc_pool",
+-					  chan->dev,
++	chan->desc_pool = dma_pool_create(chan->name, chan->dev,
+ 					  sizeof(struct fsl_desc_sw),
+ 					  __alignof__(struct fsl_desc_sw), 0);
+ 	if (!chan->desc_pool) {
+-		dev_err(chan->dev, "unable to allocate channel %d "
+-				   "descriptor pool\n", chan->id);
++		chan_err(chan, "unable to allocate descriptor pool\n");
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -491,7 +494,7 @@ static void fsl_dma_free_chan_resources(struct dma_chan *dchan)
+ 	struct fsldma_chan *chan = to_fsl_chan(dchan);
+ 	unsigned long flags;
+ 
+-	dev_dbg(chan->dev, "Free all channel resources.\n");
++	chan_dbg(chan, "free all channel resources\n");
+ 	spin_lock_irqsave(&chan->desc_lock, flags);
+ 	fsldma_free_desc_list(chan, &chan->ld_pending);
+ 	fsldma_free_desc_list(chan, &chan->ld_running);
+@@ -514,7 +517,7 @@ fsl_dma_prep_interrupt(struct dma_chan *dchan, unsigned long flags)
+ 
+ 	new = fsl_dma_alloc_descriptor(chan);
+ 	if (!new) {
+-		dev_err(chan->dev, msg_ld_oom);
++		chan_err(chan, "%s\n", msg_ld_oom);
+ 		return NULL;
+ 	}
+ 
+@@ -551,11 +554,11 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+ 		/* Allocate the link descriptor from DMA pool */
+ 		new = fsl_dma_alloc_descriptor(chan);
+ 		if (!new) {
+-			dev_err(chan->dev, msg_ld_oom);
++			chan_err(chan, "%s\n", msg_ld_oom);
+ 			goto fail;
+ 		}
+ #ifdef FSL_DMA_LD_DEBUG
+-		dev_dbg(chan->dev, "new link desc alloc %p\n", new);
++		chan_dbg(chan, "new link desc alloc %p\n", new);
+ #endif
+ 
+ 		copy = min(len, (size_t)FSL_DMA_BCR_MAX_CNT);
+@@ -639,11 +642,11 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_sg(struct dma_chan *dchan,
+ 		/* allocate and populate the descriptor */
+ 		new = fsl_dma_alloc_descriptor(chan);
+ 		if (!new) {
+-			dev_err(chan->dev, msg_ld_oom);
++			chan_err(chan, "%s\n", msg_ld_oom);
+ 			goto fail;
+ 		}
+ #ifdef FSL_DMA_LD_DEBUG
+-		dev_dbg(chan->dev, "new link desc alloc %p\n", new);
++		chan_dbg(chan, "new link desc alloc %p\n", new);
+ #endif
+ 
+ 		set_desc_cnt(chan, &new->hw, len);
+@@ -815,7 +818,7 @@ static void fsl_dma_update_completed_cookie(struct fsldma_chan *chan)
+ 	spin_lock_irqsave(&chan->desc_lock, flags);
+ 
+ 	if (list_empty(&chan->ld_running)) {
+-		dev_dbg(chan->dev, "no running descriptors\n");
++		chan_dbg(chan, "no running descriptors\n");
+ 		goto out_unlock;
+ 	}
+ 
+@@ -863,7 +866,7 @@ static void fsl_chan_ld_cleanup(struct fsldma_chan *chan)
+ 
+ 	spin_lock_irqsave(&chan->desc_lock, flags);
+ 
+-	dev_dbg(chan->dev, "chan completed_cookie = %d\n", chan->completed_cookie);
++	chan_dbg(chan, "chan completed_cookie = %d\n", chan->completed_cookie);
+ 	list_for_each_entry_safe(desc, _desc, &chan->ld_running, node) {
+ 		dma_async_tx_callback callback;
+ 		void *callback_param;
+@@ -879,7 +882,7 @@ static void fsl_chan_ld_cleanup(struct fsldma_chan *chan)
+ 		callback_param = desc->async_tx.callback_param;
+ 		if (callback) {
+ 			spin_unlock_irqrestore(&chan->desc_lock, flags);
+-			dev_dbg(chan->dev, "LD %p callback\n", desc);
++			chan_dbg(chan, "LD %p callback\n", desc);
+ 			callback(callback_param);
+ 			spin_lock_irqsave(&chan->desc_lock, flags);
+ 		}
+@@ -913,7 +916,7 @@ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan)
+ 	 * don't need to do any work at all
+ 	 */
+ 	if (list_empty(&chan->ld_pending)) {
+-		dev_dbg(chan->dev, "no pending LDs\n");
++		chan_dbg(chan, "no pending LDs\n");
+ 		goto out_unlock;
+ 	}
+ 
+@@ -923,7 +926,7 @@ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan)
+ 	 * at the end of the current transaction
+ 	 */
+ 	if (!dma_is_idle(chan)) {
+-		dev_dbg(chan->dev, "DMA controller still busy\n");
++		chan_dbg(chan, "DMA controller still busy\n");
+ 		goto out_unlock;
+ 	}
+ 
+@@ -1003,14 +1006,14 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
+ 	/* save and clear the status register */
+ 	stat = get_sr(chan);
+ 	set_sr(chan, stat);
+-	dev_dbg(chan->dev, "irq: channel %d, stat = 0x%x\n", chan->id, stat);
++	chan_dbg(chan, "irq: stat = 0x%x\n", stat);
+ 
+ 	stat &= ~(FSL_DMA_SR_CB | FSL_DMA_SR_CH);
+ 	if (!stat)
+ 		return IRQ_NONE;
+ 
+ 	if (stat & FSL_DMA_SR_TE)
+-		dev_err(chan->dev, "Transfer Error!\n");
++		chan_err(chan, "Transfer Error!\n");
+ 
+ 	/*
+ 	 * Programming Error
+@@ -1018,7 +1021,7 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
+ 	 * triger a PE interrupt.
+ 	 */
+ 	if (stat & FSL_DMA_SR_PE) {
+-		dev_dbg(chan->dev, "irq: Programming Error INT\n");
++		chan_dbg(chan, "irq: Programming Error INT\n");
+ 		if (get_bcr(chan) == 0) {
+ 			/* BCR register is 0, this is a DMA_INTERRUPT async_tx.
+ 			 * Now, update the completed cookie, and continue the
+@@ -1035,8 +1038,8 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
+ 	 * we will recycle the used descriptor.
+ 	 */
+ 	if (stat & FSL_DMA_SR_EOSI) {
+-		dev_dbg(chan->dev, "irq: End-of-segments INT\n");
+-		dev_dbg(chan->dev, "irq: clndar 0x%llx, nlndar 0x%llx\n",
++		chan_dbg(chan, "irq: End-of-segments INT\n");
++		chan_dbg(chan, "irq: clndar 0x%llx, nlndar 0x%llx\n",
+ 			(unsigned long long)get_cdar(chan),
+ 			(unsigned long long)get_ndar(chan));
+ 		stat &= ~FSL_DMA_SR_EOSI;
+@@ -1048,7 +1051,7 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
+ 	 * and start the next transfer if it exist.
+ 	 */
+ 	if (stat & FSL_DMA_SR_EOCDI) {
+-		dev_dbg(chan->dev, "irq: End-of-Chain link INT\n");
++		chan_dbg(chan, "irq: End-of-Chain link INT\n");
+ 		stat &= ~FSL_DMA_SR_EOCDI;
+ 		update_cookie = 1;
+ 		xfer_ld_q = 1;
+@@ -1060,7 +1063,7 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
+ 	 * prepare next transfer.
+ 	 */
+ 	if (stat & FSL_DMA_SR_EOLNI) {
+-		dev_dbg(chan->dev, "irq: End-of-link INT\n");
++		chan_dbg(chan, "irq: End-of-link INT\n");
+ 		stat &= ~FSL_DMA_SR_EOLNI;
+ 		xfer_ld_q = 1;
+ 	}
+@@ -1070,9 +1073,9 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
+ 	if (xfer_ld_q)
+ 		fsl_chan_xfer_ld_queue(chan);
+ 	if (stat)
+-		dev_dbg(chan->dev, "irq: unhandled sr 0x%02x\n", stat);
++		chan_dbg(chan, "irq: unhandled sr 0x%08x\n", stat);
+ 
+-	dev_dbg(chan->dev, "irq: Exit\n");
++	chan_dbg(chan, "irq: Exit\n");
+ 	tasklet_schedule(&chan->tasklet);
+ 	return IRQ_HANDLED;
+ }
+@@ -1128,7 +1131,7 @@ static void fsldma_free_irqs(struct fsldma_device *fdev)
+ 	for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++) {
+ 		chan = fdev->chan[i];
+ 		if (chan && chan->irq != NO_IRQ) {
+-			dev_dbg(fdev->dev, "free channel %d IRQ\n", chan->id);
++			chan_dbg(chan, "free per-channel IRQ\n");
+ 			free_irq(chan->irq, chan);
+ 		}
+ 	}
+@@ -1155,19 +1158,16 @@ static int fsldma_request_irqs(struct fsldma_device *fdev)
+ 			continue;
+ 
+ 		if (chan->irq == NO_IRQ) {
+-			dev_err(fdev->dev, "no interrupts property defined for "
+-					   "DMA channel %d. Please fix your "
+-					   "device tree\n", chan->id);
++			chan_err(chan, "interrupts property missing in device tree\n");
+ 			ret = -ENODEV;
+ 			goto out_unwind;
+ 		}
+ 
+-		dev_dbg(fdev->dev, "request channel %d IRQ\n", chan->id);
++		chan_dbg(chan, "request per-channel IRQ\n");
+ 		ret = request_irq(chan->irq, fsldma_chan_irq, IRQF_SHARED,
+ 				  "fsldma-chan", chan);
+ 		if (ret) {
+-			dev_err(fdev->dev, "unable to request IRQ for DMA "
+-					   "channel %d\n", chan->id);
++			chan_err(chan, "unable to request per-channel IRQ\n");
+ 			goto out_unwind;
+ 		}
+ 	}
+@@ -1242,6 +1242,7 @@ static int __devinit fsl_dma_chan_probe(struct fsldma_device *fdev,
+ 
+ 	fdev->chan[chan->id] = chan;
+ 	tasklet_init(&chan->tasklet, dma_do_tasklet, (unsigned long)chan);
++	snprintf(chan->name, sizeof(chan->name), "chan%d", chan->id);
+ 
+ 	/* Initialize the channel */
+ 	dma_init(chan);
+diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
+index ba9f403c0fbe..113e7134010b 100644
+--- a/drivers/dma/fsldma.h
++++ b/drivers/dma/fsldma.h
+@@ -135,6 +135,7 @@ struct fsldma_device {
+ #define FSL_DMA_CHAN_START_EXT	0x00002000
+ 
+ struct fsldma_chan {
++	char name[8];			/* Channel name */
+ 	struct fsldma_chan_regs __iomem *regs;
+ 	dma_cookie_t completed_cookie;	/* The maximum cookie completed */
+ 	spinlock_t desc_lock;		/* Descriptor operation lock */

commit e8bd84df27c5921a9ac866aef06e044590ac118f
+Author: Ira Snyder 
+Date:   Thu Mar 3 07:54:54 2011 +0000
+
+    fsldma: move related helper functions near each other
+    
+    This is a purely cosmetic cleanup. It is nice to have related functions
+    right next to each other in the code.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Dan Williams 
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index 4de947a450fc..2e1af4555b0f 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -39,33 +39,9 @@
+ 
+ static const char msg_ld_oom[] = "No free memory for link descriptor\n";
+ 
+-static void dma_init(struct fsldma_chan *chan)
+-{
+-	/* Reset the channel */
+-	DMA_OUT(chan, &chan->regs->mr, 0, 32);
+-
+-	switch (chan->feature & FSL_DMA_IP_MASK) {
+-	case FSL_DMA_IP_85XX:
+-		/* Set the channel to below modes:
+-		 * EIE - Error interrupt enable
+-		 * EOSIE - End of segments interrupt enable (basic mode)
+-		 * EOLNIE - End of links interrupt enable
+-		 * BWC - Bandwidth sharing among channels
+-		 */
+-		DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_BWC
+-				| FSL_DMA_MR_EIE | FSL_DMA_MR_EOLNIE
+-				| FSL_DMA_MR_EOSIE, 32);
+-		break;
+-	case FSL_DMA_IP_83XX:
+-		/* Set the channel to below modes:
+-		 * EOTIE - End-of-transfer interrupt enable
+-		 * PRC_RM - PCI read multiple
+-		 */
+-		DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_EOTIE
+-				| FSL_DMA_MR_PRC_RM, 32);
+-		break;
+-	}
+-}
++/*
++ * Register Helpers
++ */
+ 
+ static void set_sr(struct fsldma_chan *chan, u32 val)
+ {
+@@ -77,6 +53,30 @@ static u32 get_sr(struct fsldma_chan *chan)
+ 	return DMA_IN(chan, &chan->regs->sr, 32);
+ }
+ 
++static void set_cdar(struct fsldma_chan *chan, dma_addr_t addr)
++{
++	DMA_OUT(chan, &chan->regs->cdar, addr | FSL_DMA_SNEN, 64);
++}
++
++static dma_addr_t get_cdar(struct fsldma_chan *chan)
++{
++	return DMA_IN(chan, &chan->regs->cdar, 64) & ~FSL_DMA_SNEN;
++}
++
++static dma_addr_t get_ndar(struct fsldma_chan *chan)
++{
++	return DMA_IN(chan, &chan->regs->ndar, 64);
++}
++
++static u32 get_bcr(struct fsldma_chan *chan)
++{
++	return DMA_IN(chan, &chan->regs->bcr, 32);
++}
++
++/*
++ * Descriptor Helpers
++ */
++
+ static void set_desc_cnt(struct fsldma_chan *chan,
+ 				struct fsl_dma_ld_hw *hw, u32 count)
+ {
+@@ -113,24 +113,49 @@ static void set_desc_next(struct fsldma_chan *chan,
+ 	hw->next_ln_addr = CPU_TO_DMA(chan, snoop_bits | next, 64);
+ }
+ 
+-static void set_cdar(struct fsldma_chan *chan, dma_addr_t addr)
++static void set_ld_eol(struct fsldma_chan *chan,
++			struct fsl_desc_sw *desc)
+ {
+-	DMA_OUT(chan, &chan->regs->cdar, addr | FSL_DMA_SNEN, 64);
+-}
++	u64 snoop_bits;
+ 
+-static dma_addr_t get_cdar(struct fsldma_chan *chan)
+-{
+-	return DMA_IN(chan, &chan->regs->cdar, 64) & ~FSL_DMA_SNEN;
+-}
++	snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_83XX)
++		? FSL_DMA_SNEN : 0;
+ 
+-static dma_addr_t get_ndar(struct fsldma_chan *chan)
+-{
+-	return DMA_IN(chan, &chan->regs->ndar, 64);
++	desc->hw.next_ln_addr = CPU_TO_DMA(chan,
++		DMA_TO_CPU(chan, desc->hw.next_ln_addr, 64) | FSL_DMA_EOL
++			| snoop_bits, 64);
+ }
+ 
+-static u32 get_bcr(struct fsldma_chan *chan)
++/*
++ * DMA Engine Hardware Control Helpers
++ */
++
++static void dma_init(struct fsldma_chan *chan)
+ {
+-	return DMA_IN(chan, &chan->regs->bcr, 32);
++	/* Reset the channel */
++	DMA_OUT(chan, &chan->regs->mr, 0, 32);
++
++	switch (chan->feature & FSL_DMA_IP_MASK) {
++	case FSL_DMA_IP_85XX:
++		/* Set the channel to below modes:
++		 * EIE - Error interrupt enable
++		 * EOSIE - End of segments interrupt enable (basic mode)
++		 * EOLNIE - End of links interrupt enable
++		 * BWC - Bandwidth sharing among channels
++		 */
++		DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_BWC
++				| FSL_DMA_MR_EIE | FSL_DMA_MR_EOLNIE
++				| FSL_DMA_MR_EOSIE, 32);
++		break;
++	case FSL_DMA_IP_83XX:
++		/* Set the channel to below modes:
++		 * EOTIE - End-of-transfer interrupt enable
++		 * PRC_RM - PCI read multiple
++		 */
++		DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_EOTIE
++				| FSL_DMA_MR_PRC_RM, 32);
++		break;
++	}
+ }
+ 
+ static int dma_is_idle(struct fsldma_chan *chan)
+@@ -185,19 +210,6 @@ static void dma_halt(struct fsldma_chan *chan)
+ 		dev_err(chan->dev, "DMA halt timeout!\n");
+ }
+ 
+-static void set_ld_eol(struct fsldma_chan *chan,
+-			struct fsl_desc_sw *desc)
+-{
+-	u64 snoop_bits;
+-
+-	snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_83XX)
+-		? FSL_DMA_SNEN : 0;
+-
+-	desc->hw.next_ln_addr = CPU_TO_DMA(chan,
+-		DMA_TO_CPU(chan, desc->hw.next_ln_addr, 64) | FSL_DMA_EOL
+-			| snoop_bits, 64);
+-}
+-
+ /**
+  * fsl_chan_set_src_loop_size - Set source address hold transfer size
+  * @chan : Freescale DMA channel

commit b203bd3f6b9c3db3b1979c2ff79bb2b9be8f03a3
+Author: Ira Snyder 
+Date:   Thu Mar 3 07:54:53 2011 +0000
+
+    dmatest: fix automatic buffer unmap type
+    
+    The dmatest code relies on the DMAEngine API to automatically call
+    dma_unmap_single() on src buffers. The flags it passes are incorrect,
+    fix them.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Dan Williams 
+
+diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
+index 5589358b684d..7e1b0aa0ca50 100644
+--- a/drivers/dma/dmatest.c
++++ b/drivers/dma/dmatest.c
+@@ -285,7 +285,12 @@ static int dmatest_func(void *data)
+ 
+ 	set_user_nice(current, 10);
+ 
+-	flags = DMA_CTRL_ACK | DMA_COMPL_SKIP_DEST_UNMAP | DMA_PREP_INTERRUPT;
++	/*
++	 * src buffers are freed by the DMAEngine code with dma_unmap_single()
++	 * dst buffers are freed by ourselves below
++	 */
++	flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT
++	      | DMA_COMPL_SKIP_DEST_UNMAP | DMA_COMPL_SRC_UNMAP_SINGLE;
+ 
+ 	while (!kthread_should_stop()
+ 	       && !(iterations && total_tests >= iterations)) {

commit 0a6bf658c3b9d1d0e520d320b6392c8680c2e381
+Author: Ira W. Snyder 
+Date:   Mon Dec 13 11:42:30 2010 -0500
+
+    hwmon: (ltc4215) make sysfs file match the alarm cause
+    
+    The ltc4215 driver used the chip's "power good" status bit to provide
+    the power1_alarm file. This is wrong: the chip is really reporting the
+    status of one of the monitored voltages.
+    
+    Change the sysfs file from power1_alarm to in2_min_alarm instead. This
+    matches the voltage that the chip is raising an alarm for.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Guenter Roeck 
+
+diff --git a/drivers/hwmon/ltc4215.c b/drivers/hwmon/ltc4215.c
+index 00d975eb5b83..c7e6d8e81656 100644
+--- a/drivers/hwmon/ltc4215.c
++++ b/drivers/hwmon/ltc4215.c
+@@ -205,7 +205,6 @@ LTC4215_ALARM(curr1_max_alarm,	(1 << 2),	LTC4215_STATUS);
+ 
+ /* Power (virtual) */
+ LTC4215_POWER(power1_input);
+-LTC4215_ALARM(power1_alarm,	(1 << 3),	LTC4215_STATUS);
+ 
+ /* Input Voltage */
+ LTC4215_VOLTAGE(in1_input,			LTC4215_ADIN);
+@@ -214,6 +213,7 @@ LTC4215_ALARM(in1_min_alarm,	(1 << 1),	LTC4215_STATUS);
+ 
+ /* Output Voltage */
+ LTC4215_VOLTAGE(in2_input,			LTC4215_SOURCE);
++LTC4215_ALARM(in2_min_alarm,	(1 << 3),	LTC4215_STATUS);
+ 
+ /* Finally, construct an array of pointers to members of the above objects,
+  * as required for sysfs_create_group()
+@@ -223,13 +223,13 @@ static struct attribute *ltc4215_attributes[] = {
+ 	&sensor_dev_attr_curr1_max_alarm.dev_attr.attr,
+ 
+ 	&sensor_dev_attr_power1_input.dev_attr.attr,
+-	&sensor_dev_attr_power1_alarm.dev_attr.attr,
+ 
+ 	&sensor_dev_attr_in1_input.dev_attr.attr,
+ 	&sensor_dev_attr_in1_max_alarm.dev_attr.attr,
+ 	&sensor_dev_attr_in1_min_alarm.dev_attr.attr,
+ 
+ 	&sensor_dev_attr_in2_input.dev_attr.attr,
++	&sensor_dev_attr_in2_min_alarm.dev_attr.attr,
+ 
+ 	NULL,
+ };

commit 0d688662aab9d80078be82aa5aea561346643298
+Author: Ira Snyder 
+Date:   Thu Sep 30 11:46:47 2010 +0000
+
+    ste_dma40: implement support for scatterlist to scatterlist copy
+    
+    Now that the DMAEngine API has support for scatterlist to scatterlist
+    copy, implement support for the STE DMA40 DMA controller.
+    
+    Cc: Linus Walleij 
+    Acked-by: Per Fridén 
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Dan Williams 
+
+diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
+index 17e2600a00cf..d5fd098e22e8 100644
+--- a/drivers/dma/ste_dma40.c
++++ b/drivers/dma/ste_dma40.c
+@@ -1857,6 +1857,18 @@ static struct dma_async_tx_descriptor *d40_prep_memcpy(struct dma_chan *chan,
+ 	return NULL;
+ }
+ 
++static struct dma_async_tx_descriptor *
++d40_prep_sg(struct dma_chan *chan,
++	    struct scatterlist *dst_sg, unsigned int dst_nents,
++	    struct scatterlist *src_sg, unsigned int src_nents,
++	    unsigned long dma_flags)
++{
++	if (dst_nents != src_nents)
++		return NULL;
++
++	return stedma40_memcpy_sg(chan, dst_sg, src_sg, dst_nents, dma_flags);
++}
++
+ static int d40_prep_slave_sg_log(struct d40_desc *d40d,
+ 				 struct d40_chan *d40c,
+ 				 struct scatterlist *sgl,
+@@ -2281,6 +2293,7 @@ static int __init d40_dmaengine_init(struct d40_base *base,
+ 	base->dma_slave.device_alloc_chan_resources = d40_alloc_chan_resources;
+ 	base->dma_slave.device_free_chan_resources = d40_free_chan_resources;
+ 	base->dma_slave.device_prep_dma_memcpy = d40_prep_memcpy;
++	base->dma_slave.device_prep_dma_sg = d40_prep_sg;
+ 	base->dma_slave.device_prep_slave_sg = d40_prep_slave_sg;
+ 	base->dma_slave.device_tx_status = d40_tx_status;
+ 	base->dma_slave.device_issue_pending = d40_issue_pending;
+@@ -2301,10 +2314,12 @@ static int __init d40_dmaengine_init(struct d40_base *base,
+ 
+ 	dma_cap_zero(base->dma_memcpy.cap_mask);
+ 	dma_cap_set(DMA_MEMCPY, base->dma_memcpy.cap_mask);
++	dma_cap_set(DMA_SG, base->dma_slave.cap_mask);
+ 
+ 	base->dma_memcpy.device_alloc_chan_resources = d40_alloc_chan_resources;
+ 	base->dma_memcpy.device_free_chan_resources = d40_free_chan_resources;
+ 	base->dma_memcpy.device_prep_dma_memcpy = d40_prep_memcpy;
++	base->dma_slave.device_prep_dma_sg = d40_prep_sg;
+ 	base->dma_memcpy.device_prep_slave_sg = d40_prep_slave_sg;
+ 	base->dma_memcpy.device_tx_status = d40_tx_status;
+ 	base->dma_memcpy.device_issue_pending = d40_issue_pending;
+@@ -2331,10 +2346,12 @@ static int __init d40_dmaengine_init(struct d40_base *base,
+ 	dma_cap_zero(base->dma_both.cap_mask);
+ 	dma_cap_set(DMA_SLAVE, base->dma_both.cap_mask);
+ 	dma_cap_set(DMA_MEMCPY, base->dma_both.cap_mask);
++	dma_cap_set(DMA_SG, base->dma_slave.cap_mask);
+ 
+ 	base->dma_both.device_alloc_chan_resources = d40_alloc_chan_resources;
+ 	base->dma_both.device_free_chan_resources = d40_free_chan_resources;
+ 	base->dma_both.device_prep_dma_memcpy = d40_prep_memcpy;
++	base->dma_slave.device_prep_dma_sg = d40_prep_sg;
+ 	base->dma_both.device_prep_slave_sg = d40_prep_slave_sg;
+ 	base->dma_both.device_tx_status = d40_tx_status;
+ 	base->dma_both.device_issue_pending = d40_issue_pending;

commit 968f19ae802fdc6b6b6b5af6fe79cf23d281be0f
+Author: Ira Snyder 
+Date:   Thu Sep 30 11:46:46 2010 +0000
+
+    fsldma: improved DMA_SLAVE support
+    
+    Now that the generic DMAEngine API has support for scatterlist to
+    scatterlist copying, the device_prep_slave_sg() portion of the
+    DMA_SLAVE API is no longer necessary and has been removed.
+    
+    However, the device_control() portion of the DMA_SLAVE API is still
+    useful to control device specific parameters, such as externally
+    controlled DMA transfers and maximum burst length.
+    
+    A special dma_ctrl_cmd has been added to enable externally controlled
+    DMA transfers. This is currently specific to the Freescale DMA
+    controller, but can easily be made generic when another user is found.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Dan Williams 
+
+diff --git a/arch/powerpc/include/asm/fsldma.h b/arch/powerpc/include/asm/fsldma.h
+deleted file mode 100644
+index debc5ed96d6e..000000000000
+--- a/arch/powerpc/include/asm/fsldma.h
++++ /dev/null
+@@ -1,137 +0,0 @@
+-/*
+- * Freescale MPC83XX / MPC85XX DMA Controller
+- *
+- * Copyright (c) 2009 Ira W. Snyder 
+- *
+- * This file is licensed under the terms of the GNU General Public License
+- * version 2. This program is licensed "as is" without any warranty of any
+- * kind, whether express or implied.
+- */
+-
+-#ifndef __ARCH_POWERPC_ASM_FSLDMA_H__
+-#define __ARCH_POWERPC_ASM_FSLDMA_H__
+-
+-#include 
+-#include 
+-
+-/*
+- * Definitions for the Freescale DMA controller's DMA_SLAVE implemention
+- *
+- * The Freescale DMA_SLAVE implementation was designed to handle many-to-many
+- * transfers. An example usage would be an accelerated copy between two
+- * scatterlists. Another example use would be an accelerated copy from
+- * multiple non-contiguous device buffers into a single scatterlist.
+- *
+- * A DMA_SLAVE transaction is defined by a struct fsl_dma_slave. This
+- * structure contains a list of hardware addresses that should be copied
+- * to/from the scatterlist passed into device_prep_slave_sg(). The structure
+- * also has some fields to enable hardware-specific features.
+- */
+-
+-/**
+- * struct fsl_dma_hw_addr
+- * @entry: linked list entry
+- * @address: the hardware address
+- * @length: length to transfer
+- *
+- * Holds a single physical hardware address / length pair for use
+- * with the DMAEngine DMA_SLAVE API.
+- */
+-struct fsl_dma_hw_addr {
+-	struct list_head entry;
+-
+-	dma_addr_t address;
+-	size_t length;
+-};
+-
+-/**
+- * struct fsl_dma_slave
+- * @addresses: a linked list of struct fsl_dma_hw_addr structures
+- * @request_count: value for DMA request count
+- * @src_loop_size: setup and enable constant source-address DMA transfers
+- * @dst_loop_size: setup and enable constant destination address DMA transfers
+- * @external_start: enable externally started DMA transfers
+- * @external_pause: enable externally paused DMA transfers
+- *
+- * Holds a list of address / length pairs for use with the DMAEngine
+- * DMA_SLAVE API implementation for the Freescale DMA controller.
+- */
+-struct fsl_dma_slave {
+-
+-	/* List of hardware address/length pairs */
+-	struct list_head addresses;
+-
+-	/* Support for extra controller features */
+-	unsigned int request_count;
+-	unsigned int src_loop_size;
+-	unsigned int dst_loop_size;
+-	bool external_start;
+-	bool external_pause;
+-};
+-
+-/**
+- * fsl_dma_slave_append - add an address/length pair to a struct fsl_dma_slave
+- * @slave: the &struct fsl_dma_slave to add to
+- * @address: the hardware address to add
+- * @length: the length of bytes to transfer from @address
+- *
+- * Add a hardware address/length pair to a struct fsl_dma_slave. Returns 0 on
+- * success, -ERRNO otherwise.
+- */
+-static inline int fsl_dma_slave_append(struct fsl_dma_slave *slave,
+-				       dma_addr_t address, size_t length)
+-{
+-	struct fsl_dma_hw_addr *addr;
+-
+-	addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
+-	if (!addr)
+-		return -ENOMEM;
+-
+-	INIT_LIST_HEAD(&addr->entry);
+-	addr->address = address;
+-	addr->length = length;
+-
+-	list_add_tail(&addr->entry, &slave->addresses);
+-	return 0;
+-}
+-
+-/**
+- * fsl_dma_slave_free - free a struct fsl_dma_slave
+- * @slave: the struct fsl_dma_slave to free
+- *
+- * Free a struct fsl_dma_slave and all associated address/length pairs
+- */
+-static inline void fsl_dma_slave_free(struct fsl_dma_slave *slave)
+-{
+-	struct fsl_dma_hw_addr *addr, *tmp;
+-
+-	if (slave) {
+-		list_for_each_entry_safe(addr, tmp, &slave->addresses, entry) {
+-			list_del(&addr->entry);
+-			kfree(addr);
+-		}
+-
+-		kfree(slave);
+-	}
+-}
+-
+-/**
+- * fsl_dma_slave_alloc - allocate a struct fsl_dma_slave
+- * @gfp: the flags to pass to kmalloc when allocating this structure
+- *
+- * Allocate a struct fsl_dma_slave for use by the DMA_SLAVE API. Returns a new
+- * struct fsl_dma_slave on success, or NULL on failure.
+- */
+-static inline struct fsl_dma_slave *fsl_dma_slave_alloc(gfp_t gfp)
+-{
+-	struct fsl_dma_slave *slave;
+-
+-	slave = kzalloc(sizeof(*slave), gfp);
+-	if (!slave)
+-		return NULL;
+-
+-	INIT_LIST_HEAD(&slave->addresses);
+-	return slave;
+-}
+-
+-#endif /* __ARCH_POWERPC_ASM_FSLDMA_H__ */
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index 1ed29d10a5fa..286c3ac6bdcc 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -35,7 +35,6 @@
+ #include 
+ #include 
+ 
+-#include 
+ #include "fsldma.h"
+ 
+ static const char msg_ld_oom[] = "No free memory for link descriptor\n";
+@@ -719,207 +718,70 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
+ 	struct dma_chan *dchan, struct scatterlist *sgl, unsigned int sg_len,
+ 	enum dma_data_direction direction, unsigned long flags)
+ {
+-	struct fsldma_chan *chan;
+-	struct fsl_desc_sw *first = NULL, *prev = NULL, *new = NULL;
+-	struct fsl_dma_slave *slave;
+-	size_t copy;
+-
+-	int i;
+-	struct scatterlist *sg;
+-	size_t sg_used;
+-	size_t hw_used;
+-	struct fsl_dma_hw_addr *hw;
+-	dma_addr_t dma_dst, dma_src;
+-
+-	if (!dchan)
+-		return NULL;
+-
+-	if (!dchan->private)
+-		return NULL;
+-
+-	chan = to_fsl_chan(dchan);
+-	slave = dchan->private;
+-
+-	if (list_empty(&slave->addresses))
+-		return NULL;
+-
+-	hw = list_first_entry(&slave->addresses, struct fsl_dma_hw_addr, entry);
+-	hw_used = 0;
+-
+ 	/*
+-	 * Build the hardware transaction to copy from the scatterlist to
+-	 * the hardware, or from the hardware to the scatterlist
++	 * This operation is not supported on the Freescale DMA controller
+ 	 *
+-	 * If you are copying from the hardware to the scatterlist and it
+-	 * takes two hardware entries to fill an entire page, then both
+-	 * hardware entries will be coalesced into the same page
+-	 *
+-	 * If you are copying from the scatterlist to the hardware and a
+-	 * single page can fill two hardware entries, then the data will
+-	 * be read out of the page into the first hardware entry, and so on
++	 * However, we need to provide the function pointer to allow the
++	 * device_control() method to work.
+ 	 */
+-	for_each_sg(sgl, sg, sg_len, i) {
+-		sg_used = 0;
+-
+-		/* Loop until the entire scatterlist entry is used */
+-		while (sg_used < sg_dma_len(sg)) {
+-
+-			/*
+-			 * If we've used up the current hardware address/length
+-			 * pair, we need to load a new one
+-			 *
+-			 * This is done in a while loop so that descriptors with
+-			 * length == 0 will be skipped
+-			 */
+-			while (hw_used >= hw->length) {
+-
+-				/*
+-				 * If the current hardware entry is the last
+-				 * entry in the list, we're finished
+-				 */
+-				if (list_is_last(&hw->entry, &slave->addresses))
+-					goto finished;
+-
+-				/* Get the next hardware address/length pair */
+-				hw = list_entry(hw->entry.next,
+-						struct fsl_dma_hw_addr, entry);
+-				hw_used = 0;
+-			}
+-
+-			/* Allocate the link descriptor from DMA pool */
+-			new = fsl_dma_alloc_descriptor(chan);
+-			if (!new) {
+-				dev_err(chan->dev, "No free memory for "
+-						       "link descriptor\n");
+-				goto fail;
+-			}
+-#ifdef FSL_DMA_LD_DEBUG
+-			dev_dbg(chan->dev, "new link desc alloc %p\n", new);
+-#endif
+-
+-			/*
+-			 * Calculate the maximum number of bytes to transfer,
+-			 * making sure it is less than the DMA controller limit
+-			 */
+-			copy = min_t(size_t, sg_dma_len(sg) - sg_used,
+-					     hw->length - hw_used);
+-			copy = min_t(size_t, copy, FSL_DMA_BCR_MAX_CNT);
+-
+-			/*
+-			 * DMA_FROM_DEVICE
+-			 * from the hardware to the scatterlist
+-			 *
+-			 * DMA_TO_DEVICE
+-			 * from the scatterlist to the hardware
+-			 */
+-			if (direction == DMA_FROM_DEVICE) {
+-				dma_src = hw->address + hw_used;
+-				dma_dst = sg_dma_address(sg) + sg_used;
+-			} else {
+-				dma_src = sg_dma_address(sg) + sg_used;
+-				dma_dst = hw->address + hw_used;
+-			}
+-
+-			/* Fill in the descriptor */
+-			set_desc_cnt(chan, &new->hw, copy);
+-			set_desc_src(chan, &new->hw, dma_src);
+-			set_desc_dst(chan, &new->hw, dma_dst);
+-
+-			/*
+-			 * If this is not the first descriptor, chain the
+-			 * current descriptor after the previous descriptor
+-			 */
+-			if (!first) {
+-				first = new;
+-			} else {
+-				set_desc_next(chan, &prev->hw,
+-					      new->async_tx.phys);
+-			}
+-
+-			new->async_tx.cookie = 0;
+-			async_tx_ack(&new->async_tx);
+-
+-			prev = new;
+-			sg_used += copy;
+-			hw_used += copy;
+-
+-			/* Insert the link descriptor into the LD ring */
+-			list_add_tail(&new->node, &first->tx_list);
+-		}
+-	}
+-
+-finished:
+-
+-	/* All of the hardware address/length pairs had length == 0 */
+-	if (!first || !new)
+-		return NULL;
+-
+-	new->async_tx.flags = flags;
+-	new->async_tx.cookie = -EBUSY;
+-
+-	/* Set End-of-link to the last link descriptor of new list */
+-	set_ld_eol(chan, new);
+-
+-	/* Enable extra controller features */
+-	if (chan->set_src_loop_size)
+-		chan->set_src_loop_size(chan, slave->src_loop_size);
+-
+-	if (chan->set_dst_loop_size)
+-		chan->set_dst_loop_size(chan, slave->dst_loop_size);
+-
+-	if (chan->toggle_ext_start)
+-		chan->toggle_ext_start(chan, slave->external_start);
+-
+-	if (chan->toggle_ext_pause)
+-		chan->toggle_ext_pause(chan, slave->external_pause);
+-
+-	if (chan->set_request_count)
+-		chan->set_request_count(chan, slave->request_count);
+-
+-	return &first->async_tx;
+-
+-fail:
+-	/* If first was not set, then we failed to allocate the very first
+-	 * descriptor, and we're done */
+-	if (!first)
+-		return NULL;
+-
+-	/*
+-	 * First is set, so all of the descriptors we allocated have been added
+-	 * to first->tx_list, INCLUDING "first" itself. Therefore we
+-	 * must traverse the list backwards freeing each descriptor in turn
+-	 *
+-	 * We're re-using variables for the loop, oh well
+-	 */
+-	fsldma_free_desc_list_reverse(chan, &first->tx_list);
+ 	return NULL;
+ }
+ 
+ static int fsl_dma_device_control(struct dma_chan *dchan,
+ 				  enum dma_ctrl_cmd cmd, unsigned long arg)
+ {
++	struct dma_slave_config *config;
+ 	struct fsldma_chan *chan;
+ 	unsigned long flags;
+-
+-	/* Only supports DMA_TERMINATE_ALL */
+-	if (cmd != DMA_TERMINATE_ALL)
+-		return -ENXIO;
++	int size;
+ 
+ 	if (!dchan)
+ 		return -EINVAL;
+ 
+ 	chan = to_fsl_chan(dchan);
+ 
+-	/* Halt the DMA engine */
+-	dma_halt(chan);
++	switch (cmd) {
++	case DMA_TERMINATE_ALL:
++		/* Halt the DMA engine */
++		dma_halt(chan);
+ 
+-	spin_lock_irqsave(&chan->desc_lock, flags);
++		spin_lock_irqsave(&chan->desc_lock, flags);
+ 
+-	/* Remove and free all of the descriptors in the LD queue */
+-	fsldma_free_desc_list(chan, &chan->ld_pending);
+-	fsldma_free_desc_list(chan, &chan->ld_running);
++		/* Remove and free all of the descriptors in the LD queue */
++		fsldma_free_desc_list(chan, &chan->ld_pending);
++		fsldma_free_desc_list(chan, &chan->ld_running);
+ 
+-	spin_unlock_irqrestore(&chan->desc_lock, flags);
++		spin_unlock_irqrestore(&chan->desc_lock, flags);
++		return 0;
++
++	case DMA_SLAVE_CONFIG:
++		config = (struct dma_slave_config *)arg;
++
++		/* make sure the channel supports setting burst size */
++		if (!chan->set_request_count)
++			return -ENXIO;
++
++		/* we set the controller burst size depending on direction */
++		if (config->direction == DMA_TO_DEVICE)
++			size = config->dst_addr_width * config->dst_maxburst;
++		else
++			size = config->src_addr_width * config->src_maxburst;
++
++		chan->set_request_count(chan, size);
++		return 0;
++
++	case FSLDMA_EXTERNAL_START:
++
++		/* make sure the channel supports external start */
++		if (!chan->toggle_ext_start)
++			return -ENXIO;
++
++		chan->toggle_ext_start(chan, arg);
++		return 0;
++
++	default:
++		return -ENXIO;
++	}
+ 
+ 	return 0;
+ }
+diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
+index 2c9ee98f6c77..885f35211675 100644
+--- a/include/linux/dmaengine.h
++++ b/include/linux/dmaengine.h
+@@ -120,12 +120,15 @@ enum dma_ctrl_flags {
+  * configuration data in statically from the platform). An additional
+  * argument of struct dma_slave_config must be passed in with this
+  * command.
++ * @FSLDMA_EXTERNAL_START: this command will put the Freescale DMA controller
++ * into external start mode.
+  */
+ enum dma_ctrl_cmd {
+ 	DMA_TERMINATE_ALL,
+ 	DMA_PAUSE,
+ 	DMA_RESUME,
+ 	DMA_SLAVE_CONFIG,
++	FSLDMA_EXTERNAL_START,
+ };
+ 
+ /**

commit c14330417ef2050f4bf38ac20e125785fea14351
+Author: Ira Snyder 
+Date:   Thu Sep 30 11:46:45 2010 +0000
+
+    fsldma: implement support for scatterlist to scatterlist copy
+    
+    Now that the DMAEngine API has support for scatterlist to scatterlist
+    copy, implement support for the Freescale DMA controller.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Dan Williams 
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index cea08bed9cf9..1ed29d10a5fa 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -38,6 +38,8 @@
+ #include 
+ #include "fsldma.h"
+ 
++static const char msg_ld_oom[] = "No free memory for link descriptor\n";
++
+ static void dma_init(struct fsldma_chan *chan)
+ {
+ 	/* Reset the channel */
+@@ -499,7 +501,7 @@ fsl_dma_prep_interrupt(struct dma_chan *dchan, unsigned long flags)
+ 
+ 	new = fsl_dma_alloc_descriptor(chan);
+ 	if (!new) {
+-		dev_err(chan->dev, "No free memory for link descriptor\n");
++		dev_err(chan->dev, msg_ld_oom);
+ 		return NULL;
+ 	}
+ 
+@@ -536,8 +538,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+ 		/* Allocate the link descriptor from DMA pool */
+ 		new = fsl_dma_alloc_descriptor(chan);
+ 		if (!new) {
+-			dev_err(chan->dev,
+-					"No free memory for link descriptor\n");
++			dev_err(chan->dev, msg_ld_oom);
+ 			goto fail;
+ 		}
+ #ifdef FSL_DMA_LD_DEBUG
+@@ -583,6 +584,125 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+ 	return NULL;
+ }
+ 
++static struct dma_async_tx_descriptor *fsl_dma_prep_sg(struct dma_chan *dchan,
++	struct scatterlist *dst_sg, unsigned int dst_nents,
++	struct scatterlist *src_sg, unsigned int src_nents,
++	unsigned long flags)
++{
++	struct fsl_desc_sw *first = NULL, *prev = NULL, *new = NULL;
++	struct fsldma_chan *chan = to_fsl_chan(dchan);
++	size_t dst_avail, src_avail;
++	dma_addr_t dst, src;
++	size_t len;
++
++	/* basic sanity checks */
++	if (dst_nents == 0 || src_nents == 0)
++		return NULL;
++
++	if (dst_sg == NULL || src_sg == NULL)
++		return NULL;
++
++	/*
++	 * TODO: should we check that both scatterlists have the same
++	 * TODO: number of bytes in total? Is that really an error?
++	 */
++
++	/* get prepared for the loop */
++	dst_avail = sg_dma_len(dst_sg);
++	src_avail = sg_dma_len(src_sg);
++
++	/* run until we are out of scatterlist entries */
++	while (true) {
++
++		/* create the largest transaction possible */
++		len = min_t(size_t, src_avail, dst_avail);
++		len = min_t(size_t, len, FSL_DMA_BCR_MAX_CNT);
++		if (len == 0)
++			goto fetch;
++
++		dst = sg_dma_address(dst_sg) + sg_dma_len(dst_sg) - dst_avail;
++		src = sg_dma_address(src_sg) + sg_dma_len(src_sg) - src_avail;
++
++		/* allocate and populate the descriptor */
++		new = fsl_dma_alloc_descriptor(chan);
++		if (!new) {
++			dev_err(chan->dev, msg_ld_oom);
++			goto fail;
++		}
++#ifdef FSL_DMA_LD_DEBUG
++		dev_dbg(chan->dev, "new link desc alloc %p\n", new);
++#endif
++
++		set_desc_cnt(chan, &new->hw, len);
++		set_desc_src(chan, &new->hw, src);
++		set_desc_dst(chan, &new->hw, dst);
++
++		if (!first)
++			first = new;
++		else
++			set_desc_next(chan, &prev->hw, new->async_tx.phys);
++
++		new->async_tx.cookie = 0;
++		async_tx_ack(&new->async_tx);
++		prev = new;
++
++		/* Insert the link descriptor to the LD ring */
++		list_add_tail(&new->node, &first->tx_list);
++
++		/* update metadata */
++		dst_avail -= len;
++		src_avail -= len;
++
++fetch:
++		/* fetch the next dst scatterlist entry */
++		if (dst_avail == 0) {
++
++			/* no more entries: we're done */
++			if (dst_nents == 0)
++				break;
++
++			/* fetch the next entry: if there are no more: done */
++			dst_sg = sg_next(dst_sg);
++			if (dst_sg == NULL)
++				break;
++
++			dst_nents--;
++			dst_avail = sg_dma_len(dst_sg);
++		}
++
++		/* fetch the next src scatterlist entry */
++		if (src_avail == 0) {
++
++			/* no more entries: we're done */
++			if (src_nents == 0)
++				break;
++
++			/* fetch the next entry: if there are no more: done */
++			src_sg = sg_next(src_sg);
++			if (src_sg == NULL)
++				break;
++
++			src_nents--;
++			src_avail = sg_dma_len(src_sg);
++		}
++	}
++
++	new->async_tx.flags = flags; /* client is in control of this ack */
++	new->async_tx.cookie = -EBUSY;
++
++	/* Set End-of-link to the last link descriptor of new list */
++	set_ld_eol(chan, new);
++
++	return &first->async_tx;
++
++fail:
++	if (!first)
++		return NULL;
++
++	fsldma_free_desc_list_reverse(chan, &first->tx_list);
++	return NULL;
++}
++
+ /**
+  * fsl_dma_prep_slave_sg - prepare descriptors for a DMA_SLAVE transaction
+  * @chan: DMA channel
+@@ -1327,11 +1447,13 @@ static int __devinit fsldma_of_probe(struct platform_device *op,
+ 
+ 	dma_cap_set(DMA_MEMCPY, fdev->common.cap_mask);
+ 	dma_cap_set(DMA_INTERRUPT, fdev->common.cap_mask);
++	dma_cap_set(DMA_SG, fdev->common.cap_mask);
+ 	dma_cap_set(DMA_SLAVE, fdev->common.cap_mask);
+ 	fdev->common.device_alloc_chan_resources = fsl_dma_alloc_chan_resources;
+ 	fdev->common.device_free_chan_resources = fsl_dma_free_chan_resources;
+ 	fdev->common.device_prep_dma_interrupt = fsl_dma_prep_interrupt;
+ 	fdev->common.device_prep_dma_memcpy = fsl_dma_prep_memcpy;
++	fdev->common.device_prep_dma_sg = fsl_dma_prep_sg;
+ 	fdev->common.device_tx_status = fsl_tx_status;
+ 	fdev->common.device_issue_pending = fsl_dma_memcpy_issue_pending;
+ 	fdev->common.device_prep_slave_sg = fsl_dma_prep_slave_sg;

commit a86ee03ce6f279ebe581a7a8c0c4393eaeb789ee
+Author: Ira Snyder 
+Date:   Thu Sep 30 11:46:44 2010 +0000
+
+    dma: add support for scatterlist to scatterlist copy
+    
+    This adds support for scatterlist to scatterlist DMA transfers. A
+    similar interface is exposed by the fsldma driver (through the DMA_SLAVE
+    API) and by the ste_dma40 driver (through an exported function).
+    
+    This patch paves the way for making this type of copy operation a part
+    of the generic DMAEngine API. Futher patches will add support in
+    individual drivers.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Dan Williams 
+
+diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
+index 9d31d5eb95c1..db403b8ccabd 100644
+--- a/drivers/dma/dmaengine.c
++++ b/drivers/dma/dmaengine.c
+@@ -690,6 +690,8 @@ int dma_async_device_register(struct dma_device *device)
+ 		!device->device_prep_dma_memset);
+ 	BUG_ON(dma_has_cap(DMA_INTERRUPT, device->cap_mask) &&
+ 		!device->device_prep_dma_interrupt);
++	BUG_ON(dma_has_cap(DMA_SG, device->cap_mask) &&
++		!device->device_prep_dma_sg);
+ 	BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) &&
+ 		!device->device_prep_slave_sg);
+ 	BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) &&
+diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
+index e2106495cc11..2c9ee98f6c77 100644
+--- a/include/linux/dmaengine.h
++++ b/include/linux/dmaengine.h
+@@ -64,6 +64,7 @@ enum dma_transaction_type {
+ 	DMA_PQ_VAL,
+ 	DMA_MEMSET,
+ 	DMA_INTERRUPT,
++	DMA_SG,
+ 	DMA_PRIVATE,
+ 	DMA_ASYNC_TX,
+ 	DMA_SLAVE,
+@@ -473,6 +474,11 @@ struct dma_device {
+ 		unsigned long flags);
+ 	struct dma_async_tx_descriptor *(*device_prep_dma_interrupt)(
+ 		struct dma_chan *chan, unsigned long flags);
++	struct dma_async_tx_descriptor *(*device_prep_dma_sg)(
++		struct dma_chan *chan,
++		struct scatterlist *dst_sg, unsigned int dst_nents,
++		struct scatterlist *src_sg, unsigned int src_nents,
++		unsigned long flags);
+ 
+ 	struct dma_async_tx_descriptor *(*device_prep_slave_sg)(
+ 		struct dma_chan *chan, struct scatterlist *sgl,

commit 399f1e30ac17b77d383444aff480c7390f5adf2a
+Author: Ira W. Snyder 
+Date:   Thu Sep 30 15:15:27 2010 -0700
+
+    kfifo: fix scatterlist usage
+    
+    The kfifo_dma family of functions use sg_mark_end() on the last element in
+    their scatterlist.  This forces use of a fresh scatterlist for each DMA
+    operation, which makes recycling a single scatterlist impossible.
+    
+    Change the behavior of the kfifo_dma functions to match the usage of the
+    dma_map_sg function.  This means that users must respect the returned
+    nents value.  The sample code is updated to reflect the change.
+    
+    This bug is trivial to cause: call kfifo_dma_in_prepare() such that it
+    prepares a scatterlist with a single entry comprising the whole fifo.
+    This is the case when you map the entirety of a newly created empty fifo.
+    This causes the setup_sgl() function to mark the first scatterlist entry
+    as the end of the chain, no matter what comes after it.
+    
+    Afterwards, add and remove some data from the fifo such that another call
+    to kfifo_dma_in_prepare() will create two scatterlist entries.  It returns
+    nents=2.  However, due to the previous sg_mark_end() call, sg_is_last()
+    will now return true for the first scatterlist element.  This causes the
+    sample code to print a single scatterlist element when it should print
+    two.
+    
+    By removing the call to sg_mark_end(), we make the API as similar as
+    possible to the DMA mapping API.  All users are required to respect the
+    returned nents.
+    
+    Signed-off-by: Ira W. Snyder 
+    Cc: Stefani Seibold 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/kernel/kfifo.c b/kernel/kfifo.c
+index 6b5580c57644..01a0700e873f 100644
+--- a/kernel/kfifo.c
++++ b/kernel/kfifo.c
+@@ -365,8 +365,6 @@ static unsigned int setup_sgl(struct __kfifo *fifo, struct scatterlist *sgl,
+ 	n = setup_sgl_buf(sgl, fifo->data + off, nents, l);
+ 	n += setup_sgl_buf(sgl + n, fifo->data, nents - n, len - l);
+ 
+-	if (n)
+-		sg_mark_end(sgl + n - 1);
+ 	return n;
+ }
+ 
+diff --git a/samples/kfifo/dma-example.c b/samples/kfifo/dma-example.c
+index ee03a4f0b64f..06473791c08a 100644
+--- a/samples/kfifo/dma-example.c
++++ b/samples/kfifo/dma-example.c
+@@ -24,6 +24,7 @@ static int __init example_init(void)
+ {
+ 	int			i;
+ 	unsigned int		ret;
++	unsigned int		nents;
+ 	struct scatterlist	sg[10];
+ 
+ 	printk(KERN_INFO "DMA fifo test start\n");
+@@ -61,9 +62,9 @@ static int __init example_init(void)
+ 	 * byte at the beginning, after the kfifo_skip().
+ 	 */
+ 	sg_init_table(sg, ARRAY_SIZE(sg));
+-	ret = kfifo_dma_in_prepare(&fifo, sg, ARRAY_SIZE(sg), FIFO_SIZE);
+-	printk(KERN_INFO "DMA sgl entries: %d\n", ret);
+-	if (!ret) {
++	nents = kfifo_dma_in_prepare(&fifo, sg, ARRAY_SIZE(sg), FIFO_SIZE);
++	printk(KERN_INFO "DMA sgl entries: %d\n", nents);
++	if (!nents) {
+ 		/* fifo is full and no sgl was created */
+ 		printk(KERN_WARNING "error kfifo_dma_in_prepare\n");
+ 		return -EIO;
+@@ -71,7 +72,7 @@ static int __init example_init(void)
+ 
+ 	/* receive data */
+ 	printk(KERN_INFO "scatterlist for receive:\n");
+-	for (i = 0; i < ARRAY_SIZE(sg); i++) {
++	for (i = 0; i < nents; i++) {
+ 		printk(KERN_INFO
+ 		"sg[%d] -> "
+ 		"page_link 0x%.8lx offset 0x%.8x length 0x%.8x\n",
+@@ -91,16 +92,16 @@ static int __init example_init(void)
+ 	kfifo_dma_in_finish(&fifo, ret);
+ 
+ 	/* Prepare to transmit data, example: 8 bytes */
+-	ret = kfifo_dma_out_prepare(&fifo, sg, ARRAY_SIZE(sg), 8);
+-	printk(KERN_INFO "DMA sgl entries: %d\n", ret);
+-	if (!ret) {
++	nents = kfifo_dma_out_prepare(&fifo, sg, ARRAY_SIZE(sg), 8);
++	printk(KERN_INFO "DMA sgl entries: %d\n", nents);
++	if (!nents) {
+ 		/* no data was available and no sgl was created */
+ 		printk(KERN_WARNING "error kfifo_dma_out_prepare\n");
+ 		return -EIO;
+ 	}
+ 
+ 	printk(KERN_INFO "scatterlist for transmit:\n");
+-	for (i = 0; i < ARRAY_SIZE(sg); i++) {
++	for (i = 0; i < nents; i++) {
+ 		printk(KERN_INFO
+ 		"sg[%d] -> "
+ 		"page_link 0x%.8lx offset 0x%.8x length 0x%.8x\n",

commit 94131e174fedd9f3f9bb148cee4be12f2d46d68e
+Author: Ira W. Snyder 
+Date:   Thu Sep 9 16:37:58 2010 -0700
+
+    arch/powerpc/include/asm/fsldma.h needs slab.h
+    
+    The slab.h header is required to use the kmalloc() family of functions.
+    Due to recent kernel changes, this header must be directly included by
+    code that calls into the memory allocator.
+    
+    Without this patch, any code which includes this header fails to build.
+    
+    Signed-off-by: Ira W. Snyder 
+    Cc: Dan Williams 
+    Cc: Benjamin Herrenschmidt 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/powerpc/include/asm/fsldma.h b/arch/powerpc/include/asm/fsldma.h
+index a67aeed17d40..debc5ed96d6e 100644
+--- a/arch/powerpc/include/asm/fsldma.h
++++ b/arch/powerpc/include/asm/fsldma.h
+@@ -11,6 +11,7 @@
+ #ifndef __ARCH_POWERPC_ASM_FSLDMA_H__
+ #define __ARCH_POWERPC_ASM_FSLDMA_H__
+ 
++#include 
+ #include 
+ 
+ /*

commit 5950ec8d3e47a08ec0b678a0e0ba5d1b9b62dd8e
+Author: Ira W. Snyder 
+Date:   Sat Aug 14 21:08:49 2010 +0200
+
+    hwmon: (ltc4245) Expose all GPIO pins as analog voltages
+    
+    Add support for exposing all GPIO pins as analog voltages. Though this is
+    not an ideal use of the chip, some hardware engineers may decide that the
+    LTC4245 meets their design requirements when studying the datasheet.
+    
+    The GPIO pins are sampled in round-robin fashion, meaning that a slow
+    reader will see stale data. A userspace application can detect this,
+    because it will get -EAGAIN when reading from a sysfs file which contains
+    stale data.
+    
+    Users can choose to use this feature on a per-chip basis by using either
+    platform data or the OF device tree (where applicable).
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Jean Delvare 
+
+diff --git a/Documentation/hwmon/ltc4245 b/Documentation/hwmon/ltc4245
+index 86b5880d8502..b478b0864965 100644
+--- a/Documentation/hwmon/ltc4245
++++ b/Documentation/hwmon/ltc4245
+@@ -72,9 +72,31 @@ in6_min_alarm		5v  output undervoltage alarm
+ in7_min_alarm		3v  output undervoltage alarm
+ in8_min_alarm		Vee (-12v) output undervoltage alarm
+ 
+-in9_input		GPIO voltage data
++in9_input		GPIO voltage data (see note 1)
++in10_input		GPIO voltage data (see note 1)
++in11_input		GPIO voltage data (see note 1)
+ 
+ power1_input		12v power usage (mW)
+ power2_input		5v  power usage (mW)
+ power3_input		3v  power usage (mW)
+ power4_input		Vee (-12v) power usage (mW)
++
++
++Note 1
++------
++
++If you have NOT configured the driver to sample all GPIO pins as analog
++voltages, then the in10_input and in11_input sysfs attributes will not be
++created. The driver will sample the GPIO pin that is currently connected to the
++ADC as an analog voltage, and report the value in in9_input.
++
++If you have configured the driver to sample all GPIO pins as analog voltages,
++then they will be sampled in round-robin fashion. If userspace reads too
++slowly, -EAGAIN will be returned when you read the sysfs attribute containing
++the sensor reading.
++
++The LTC4245 chip can be configured to sample all GPIO pins with two methods:
++1) platform data -- see include/linux/i2c/ltc4245.h
++2) OF device tree -- add the "ltc4245,use-extra-gpios" property to each chip
++
++The default mode of operation is to sample a single GPIO pin.
+diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c
+index 21d201befc2c..659308329308 100644
+--- a/drivers/hwmon/ltc4245.c
++++ b/drivers/hwmon/ltc4245.c
+@@ -21,6 +21,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ /* Here are names of the chip's registers (a.k.a. commands) */
+ enum ltc4245_cmd {
+@@ -60,8 +61,72 @@ struct ltc4245_data {
+ 
+ 	/* Voltage registers */
+ 	u8 vregs[0x0d];
++
++	/* GPIO ADC registers */
++	bool use_extra_gpios;
++	int gpios[3];
+ };
+ 
++/*
++ * Update the readings from the GPIO pins. If the driver has been configured to
++ * sample all GPIO's as analog voltages, a round-robin sampling method is used.
++ * Otherwise, only the configured GPIO pin is sampled.
++ *
++ * LOCKING: must hold data->update_lock
++ */
++static void ltc4245_update_gpios(struct device *dev)
++{
++	struct i2c_client *client = to_i2c_client(dev);
++	struct ltc4245_data *data = i2c_get_clientdata(client);
++	u8 gpio_curr, gpio_next, gpio_reg;
++	int i;
++
++	/* no extra gpio support, we're basically done */
++	if (!data->use_extra_gpios) {
++		data->gpios[0] = data->vregs[LTC4245_GPIOADC - 0x10];
++		return;
++	}
++
++	/*
++	 * If the last reading was too long ago, then we mark all old GPIO
++	 * readings as stale by setting them to -EAGAIN
++	 */
++	if (time_after(jiffies, data->last_updated + 5 * HZ)) {
++		dev_dbg(&client->dev, "Marking GPIOs invalid\n");
++		for (i = 0; i < ARRAY_SIZE(data->gpios); i++)
++			data->gpios[i] = -EAGAIN;
++	}
++
++	/*
++	 * Get the current GPIO pin
++	 *
++	 * The datasheet calls these GPIO[1-3], but we'll calculate the zero
++	 * based array index instead, and call them GPIO[0-2]. This is much
++	 * easier to think about.
++	 */
++	gpio_curr = (data->cregs[LTC4245_GPIO] & 0xc0) >> 6;
++	if (gpio_curr > 0)
++		gpio_curr -= 1;
++
++	/* Read the GPIO voltage from the GPIOADC register */
++	data->gpios[gpio_curr] = data->vregs[LTC4245_GPIOADC - 0x10];
++
++	/* Find the next GPIO pin to read */
++	gpio_next = (gpio_curr + 1) % ARRAY_SIZE(data->gpios);
++
++	/*
++	 * Calculate the correct setting for the GPIO register so it will
++	 * sample the next GPIO pin
++	 */
++	gpio_reg = (data->cregs[LTC4245_GPIO] & 0x3f) | ((gpio_next + 1) << 6);
++
++	/* Update the GPIO register */
++	i2c_smbus_write_byte_data(client, LTC4245_GPIO, gpio_reg);
++
++	/* Update saved data */
++	data->cregs[LTC4245_GPIO] = gpio_reg;
++}
++
+ static struct ltc4245_data *ltc4245_update_device(struct device *dev)
+ {
+ 	struct i2c_client *client = to_i2c_client(dev);
+@@ -93,6 +158,9 @@ static struct ltc4245_data *ltc4245_update_device(struct device *dev)
+ 				data->vregs[i] = val;
+ 		}
+ 
++		/* Update GPIO readings */
++		ltc4245_update_gpios(dev);
++
+ 		data->last_updated = jiffies;
+ 		data->valid = 1;
+ 	}
+@@ -233,6 +301,22 @@ static ssize_t ltc4245_show_alarm(struct device *dev,
+ 	return snprintf(buf, PAGE_SIZE, "%u\n", (reg & mask) ? 1 : 0);
+ }
+ 
++static ssize_t ltc4245_show_gpio(struct device *dev,
++				 struct device_attribute *da,
++				 char *buf)
++{
++	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
++	struct ltc4245_data *data = ltc4245_update_device(dev);
++	int val = data->gpios[attr->index];
++
++	/* handle stale GPIO's */
++	if (val < 0)
++		return val;
++
++	/* Convert to millivolts and print */
++	return snprintf(buf, PAGE_SIZE, "%u\n", val * 10);
++}
++
+ /* These macros are used below in constructing device attribute objects
+  * for use with sysfs_create_group() to make a sysfs device file
+  * for each register.
+@@ -254,6 +338,10 @@ static ssize_t ltc4245_show_alarm(struct device *dev,
+ 	static SENSOR_DEVICE_ATTR_2(name, S_IRUGO, \
+ 	ltc4245_show_alarm, NULL, (mask), reg)
+ 
++#define LTC4245_GPIO_VOLTAGE(name, gpio_num) \
++	static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
++	ltc4245_show_gpio, NULL, gpio_num)
++
+ /* Construct a sensor_device_attribute structure for each register */
+ 
+ /* Input voltages */
+@@ -293,7 +381,9 @@ LTC4245_ALARM(in7_min_alarm,	(1 << 2),	LTC4245_FAULT2);
+ LTC4245_ALARM(in8_min_alarm,	(1 << 3),	LTC4245_FAULT2);
+ 
+ /* GPIO voltages */
+-LTC4245_VOLTAGE(in9_input,			LTC4245_GPIOADC);
++LTC4245_GPIO_VOLTAGE(in9_input,			0);
++LTC4245_GPIO_VOLTAGE(in10_input,		1);
++LTC4245_GPIO_VOLTAGE(in11_input,		2);
+ 
+ /* Power Consumption (virtual) */
+ LTC4245_POWER(power1_input,			LTC4245_12VSENSE);
+@@ -304,7 +394,7 @@ LTC4245_POWER(power4_input,			LTC4245_VEESENSE);
+ /* Finally, construct an array of pointers to members of the above objects,
+  * as required for sysfs_create_group()
+  */
+-static struct attribute *ltc4245_attributes[] = {
++static struct attribute *ltc4245_std_attributes[] = {
+ 	&sensor_dev_attr_in1_input.dev_attr.attr,
+ 	&sensor_dev_attr_in2_input.dev_attr.attr,
+ 	&sensor_dev_attr_in3_input.dev_attr.attr,
+@@ -345,10 +435,77 @@ static struct attribute *ltc4245_attributes[] = {
+ 	NULL,
+ };
+ 
+-static const struct attribute_group ltc4245_group = {
+-	.attrs = ltc4245_attributes,
++static struct attribute *ltc4245_gpio_attributes[] = {
++	&sensor_dev_attr_in10_input.dev_attr.attr,
++	&sensor_dev_attr_in11_input.dev_attr.attr,
++	NULL,
++};
++
++static const struct attribute_group ltc4245_std_group = {
++	.attrs = ltc4245_std_attributes,
++};
++
++static const struct attribute_group ltc4245_gpio_group = {
++	.attrs = ltc4245_gpio_attributes,
+ };
+ 
++static int ltc4245_sysfs_create_groups(struct i2c_client *client)
++{
++	struct ltc4245_data *data = i2c_get_clientdata(client);
++	struct device *dev = &client->dev;
++	int ret;
++
++	/* register the standard sysfs attributes */
++	ret = sysfs_create_group(&dev->kobj, <c4245_std_group);
++	if (ret) {
++		dev_err(dev, "unable to register standard attributes\n");
++		return ret;
++	}
++
++	/* if we're using the extra gpio support, register it's attributes */
++	if (data->use_extra_gpios) {
++		ret = sysfs_create_group(&dev->kobj, <c4245_gpio_group);
++		if (ret) {
++			dev_err(dev, "unable to register gpio attributes\n");
++			sysfs_remove_group(&dev->kobj, <c4245_std_group);
++			return ret;
++		}
++	}
++
++	return 0;
++}
++
++static void ltc4245_sysfs_remove_groups(struct i2c_client *client)
++{
++	struct ltc4245_data *data = i2c_get_clientdata(client);
++	struct device *dev = &client->dev;
++
++	if (data->use_extra_gpios)
++		sysfs_remove_group(&dev->kobj, <c4245_gpio_group);
++
++	sysfs_remove_group(&dev->kobj, <c4245_std_group);
++}
++
++static bool ltc4245_use_extra_gpios(struct i2c_client *client)
++{
++	struct ltc4245_platform_data *pdata = dev_get_platdata(&client->dev);
++#ifdef CONFIG_OF
++	struct device_node *np = client->dev.of_node;
++#endif
++
++	/* prefer platform data */
++	if (pdata)
++		return pdata->use_extra_gpios;
++
++#ifdef CONFIG_OF
++	/* fallback on OF */
++	if (of_find_property(np, "ltc4245,use-extra-gpios", NULL))
++		return true;
++#endif
++
++	return false;
++}
++
+ static int ltc4245_probe(struct i2c_client *client,
+ 			 const struct i2c_device_id *id)
+ {
+@@ -367,15 +524,16 @@ static int ltc4245_probe(struct i2c_client *client,
+ 
+ 	i2c_set_clientdata(client, data);
+ 	mutex_init(&data->update_lock);
++	data->use_extra_gpios = ltc4245_use_extra_gpios(client);
+ 
+ 	/* Initialize the LTC4245 chip */
+ 	i2c_smbus_write_byte_data(client, LTC4245_FAULT1, 0x00);
+ 	i2c_smbus_write_byte_data(client, LTC4245_FAULT2, 0x00);
+ 
+ 	/* Register sysfs hooks */
+-	ret = sysfs_create_group(&client->dev.kobj, <c4245_group);
++	ret = ltc4245_sysfs_create_groups(client);
+ 	if (ret)
+-		goto out_sysfs_create_group;
++		goto out_sysfs_create_groups;
+ 
+ 	data->hwmon_dev = hwmon_device_register(&client->dev);
+ 	if (IS_ERR(data->hwmon_dev)) {
+@@ -386,8 +544,8 @@ static int ltc4245_probe(struct i2c_client *client,
+ 	return 0;
+ 
+ out_hwmon_device_register:
+-	sysfs_remove_group(&client->dev.kobj, <c4245_group);
+-out_sysfs_create_group:
++	ltc4245_sysfs_remove_groups(client);
++out_sysfs_create_groups:
+ 	kfree(data);
+ out_kzalloc:
+ 	return ret;
+@@ -398,8 +556,7 @@ static int ltc4245_remove(struct i2c_client *client)
+ 	struct ltc4245_data *data = i2c_get_clientdata(client);
+ 
+ 	hwmon_device_unregister(data->hwmon_dev);
+-	sysfs_remove_group(&client->dev.kobj, <c4245_group);
+-
++	ltc4245_sysfs_remove_groups(client);
+ 	kfree(data);
+ 
+ 	return 0;
+diff --git a/include/linux/i2c/ltc4245.h b/include/linux/i2c/ltc4245.h
+new file mode 100644
+index 000000000000..56bda4be0016
+--- /dev/null
++++ b/include/linux/i2c/ltc4245.h
+@@ -0,0 +1,21 @@
++/*
++ * Platform Data for LTC4245 hardware monitor chip
++ *
++ * Copyright (c) 2010 Ira W. Snyder 
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#ifndef LINUX_LTC4245_H
++#define LINUX_LTC4245_H
++
++#include 
++
++struct ltc4245_platform_data {
++	bool use_extra_gpios;
++};
++
++#endif /* LINUX_LTC4245_H */

commit 800e69fbd2faea906cabd10ddb77e36410f2bd9c
+Author: Ira W. Snyder 
+Date:   Wed Apr 7 10:08:01 2010 +0200
+
+    gpio: Add support for Janz VMOD-TTL Digital IO module
+    
+    The Janz VMOD-TTL is a MODULbus daughterboard which fits onto any MODULbus
+    carrier board. It essentially consists of some various logic and a Zilog
+    Z8536 CIO Counter/Timer and Parallel IO Unit.
+    
+    The board must be physically configured with jumpers to enable a user to
+    drive output signals. I am only interested in outputs, so I have made this
+    driver as simple as possible. It only supports a very minimal subset of the
+    features provided by the Z8536 chip.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Samuel Ortiz 
+
+diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
+index 56eb0c59c512..0e9c16b5bbce 100644
+--- a/drivers/gpio/Kconfig
++++ b/drivers/gpio/Kconfig
+@@ -325,4 +325,14 @@ config GPIO_UCB1400
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called ucb1400_gpio.
+ 
++comment "MODULbus GPIO expanders:"
++
++config GPIO_JANZ_TTL
++	tristate "Janz VMOD-TTL Digital IO Module"
++	depends on MFD_JANZ_CMODIO
++	help
++	  This enables support for the Janz VMOD-TTL Digital IO module.
++	  This driver provides support for driving the pins in output
++	  mode only. Input mode is not supported.
++
+ endif
+diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
+index d3226d395a90..94a96c51c741 100644
+--- a/drivers/gpio/Makefile
++++ b/drivers/gpio/Makefile
+@@ -29,3 +29,4 @@ obj-$(CONFIG_GPIO_WM8350)	+= wm8350-gpiolib.o
+ obj-$(CONFIG_GPIO_WM8994)	+= wm8994-gpio.o
+ obj-$(CONFIG_GPIO_SCH)		+= sch_gpio.o
+ obj-$(CONFIG_GPIO_RDC321X)	+= rdc321x-gpio.o
++obj-$(CONFIG_GPIO_JANZ_TTL)	+= janz-ttl.o
+diff --git a/drivers/gpio/janz-ttl.c b/drivers/gpio/janz-ttl.c
+new file mode 100644
+index 000000000000..813ac077e5d7
+--- /dev/null
++++ b/drivers/gpio/janz-ttl.c
+@@ -0,0 +1,258 @@
++/*
++ * Janz MODULbus VMOD-TTL GPIO Driver
++ *
++ * Copyright (c) 2010 Ira W. Snyder 
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++
++#define DRV_NAME "janz-ttl"
++
++#define PORTA_DIRECTION		0x23
++#define PORTB_DIRECTION		0x2B
++#define PORTC_DIRECTION		0x06
++#define PORTA_IOCTL		0x24
++#define PORTB_IOCTL		0x2C
++#define PORTC_IOCTL		0x07
++
++#define MASTER_INT_CTL		0x00
++#define MASTER_CONF_CTL		0x01
++
++#define CONF_PAE		(1 << 2)
++#define CONF_PBE		(1 << 7)
++#define CONF_PCE		(1 << 4)
++
++struct ttl_control_regs {
++	__be16 portc;
++	__be16 portb;
++	__be16 porta;
++	__be16 control;
++};
++
++struct ttl_module {
++	struct gpio_chip gpio;
++
++	/* base address of registers */
++	struct ttl_control_regs __iomem *regs;
++
++	u8 portc_shadow;
++	u8 portb_shadow;
++	u8 porta_shadow;
++
++	spinlock_t lock;
++};
++
++static int ttl_get_value(struct gpio_chip *gpio, unsigned offset)
++{
++	struct ttl_module *mod = dev_get_drvdata(gpio->dev);
++	u8 *shadow;
++	int ret;
++
++	if (offset < 8) {
++		shadow = &mod->porta_shadow;
++	} else if (offset < 16) {
++		shadow = &mod->portb_shadow;
++		offset -= 8;
++	} else {
++		shadow = &mod->portc_shadow;
++		offset -= 16;
++	}
++
++	spin_lock(&mod->lock);
++	ret = *shadow & (1 << offset);
++	spin_unlock(&mod->lock);
++	return ret;
++}
++
++static void ttl_set_value(struct gpio_chip *gpio, unsigned offset, int value)
++{
++	struct ttl_module *mod = dev_get_drvdata(gpio->dev);
++	void __iomem *port;
++	u8 *shadow;
++
++	if (offset < 8) {
++		port = &mod->regs->porta;
++		shadow = &mod->porta_shadow;
++	} else if (offset < 16) {
++		port = &mod->regs->portb;
++		shadow = &mod->portb_shadow;
++		offset -= 8;
++	} else {
++		port = &mod->regs->portc;
++		shadow = &mod->portc_shadow;
++		offset -= 16;
++	}
++
++	spin_lock(&mod->lock);
++	if (value)
++		*shadow |= (1 << offset);
++	else
++		*shadow &= ~(1 << offset);
++
++	iowrite16be(*shadow, port);
++	spin_unlock(&mod->lock);
++}
++
++static void __devinit ttl_write_reg(struct ttl_module *mod, u8 reg, u16 val)
++{
++	iowrite16be(reg, &mod->regs->control);
++	iowrite16be(val, &mod->regs->control);
++}
++
++static void __devinit ttl_setup_device(struct ttl_module *mod)
++{
++	/* reset the device to a known state */
++	iowrite16be(0x0000, &mod->regs->control);
++	iowrite16be(0x0001, &mod->regs->control);
++	iowrite16be(0x0000, &mod->regs->control);
++
++	/* put all ports in open-drain mode */
++	ttl_write_reg(mod, PORTA_IOCTL, 0x00ff);
++	ttl_write_reg(mod, PORTB_IOCTL, 0x00ff);
++	ttl_write_reg(mod, PORTC_IOCTL, 0x000f);
++
++	/* set all ports as outputs */
++	ttl_write_reg(mod, PORTA_DIRECTION, 0x0000);
++	ttl_write_reg(mod, PORTB_DIRECTION, 0x0000);
++	ttl_write_reg(mod, PORTC_DIRECTION, 0x0000);
++
++	/* set all ports to drive zeroes */
++	iowrite16be(0x0000, &mod->regs->porta);
++	iowrite16be(0x0000, &mod->regs->portb);
++	iowrite16be(0x0000, &mod->regs->portc);
++
++	/* enable all ports */
++	ttl_write_reg(mod, MASTER_CONF_CTL, CONF_PAE | CONF_PBE | CONF_PCE);
++}
++
++static int __devinit ttl_probe(struct platform_device *pdev)
++{
++	struct janz_platform_data *pdata;
++	struct device *dev = &pdev->dev;
++	struct ttl_module *mod;
++	struct gpio_chip *gpio;
++	struct resource *res;
++	int ret;
++
++	pdata = pdev->dev.platform_data;
++	if (!pdata) {
++		dev_err(dev, "no platform data\n");
++		ret = -ENXIO;
++		goto out_return;
++	}
++
++	mod = kzalloc(sizeof(*mod), GFP_KERNEL);
++	if (!mod) {
++		dev_err(dev, "unable to allocate private data\n");
++		ret = -ENOMEM;
++		goto out_return;
++	}
++
++	platform_set_drvdata(pdev, mod);
++	spin_lock_init(&mod->lock);
++
++	/* get access to the MODULbus registers for this module */
++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	if (!res) {
++		dev_err(dev, "MODULbus registers not found\n");
++		ret = -ENODEV;
++		goto out_free_mod;
++	}
++
++	mod->regs = ioremap(res->start, resource_size(res));
++	if (!mod->regs) {
++		dev_err(dev, "MODULbus registers not ioremap\n");
++		ret = -ENOMEM;
++		goto out_free_mod;
++	}
++
++	ttl_setup_device(mod);
++
++	/* Initialize the GPIO data structures */
++	gpio = &mod->gpio;
++	gpio->dev = &pdev->dev;
++	gpio->label = pdev->name;
++	gpio->get = ttl_get_value;
++	gpio->set = ttl_set_value;
++	gpio->owner = THIS_MODULE;
++
++	/* request dynamic allocation */
++	gpio->base = -1;
++	gpio->ngpio = 20;
++
++	ret = gpiochip_add(gpio);
++	if (ret) {
++		dev_err(dev, "unable to add GPIO chip\n");
++		goto out_iounmap_regs;
++	}
++
++	dev_info(&pdev->dev, "module %d: registered GPIO device\n",
++			     pdata->modno);
++	return 0;
++
++out_iounmap_regs:
++	iounmap(mod->regs);
++out_free_mod:
++	kfree(mod);
++out_return:
++	return ret;
++}
++
++static int __devexit ttl_remove(struct platform_device *pdev)
++{
++	struct ttl_module *mod = platform_get_drvdata(pdev);
++	struct device *dev = &pdev->dev;
++	int ret;
++
++	ret = gpiochip_remove(&mod->gpio);
++	if (ret) {
++		dev_err(dev, "unable to remove GPIO chip\n");
++		return ret;
++	}
++
++	iounmap(mod->regs);
++	kfree(mod);
++	return 0;
++}
++
++static struct platform_driver ttl_driver = {
++	.driver		= {
++		.name	= DRV_NAME,
++		.owner	= THIS_MODULE,
++	},
++	.probe		= ttl_probe,
++	.remove		= __devexit_p(ttl_remove),
++};
++
++static int __init ttl_init(void)
++{
++	return platform_driver_register(&ttl_driver);
++}
++
++static void __exit ttl_exit(void)
++{
++	platform_driver_unregister(&ttl_driver);
++}
++
++MODULE_AUTHOR("Ira W. Snyder ");
++MODULE_DESCRIPTION("Janz MODULbus VMOD-TTL Driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:janz-ttl");
++
++module_init(ttl_init);
++module_exit(ttl_exit);

commit 631eb227849e3bfdec2d2e628ee5a3f962db82e2
+Author: Ira W. Snyder 
+Date:   Mon Mar 29 09:58:51 2010 -0700
+
+    can: Add support for Janz VMOD-ICAN3 Intelligent CAN module
+    
+    The Janz VMOD-ICAN3 is a MODULbus daughterboard which fits onto any
+    MODULbus carrier board. It is an intelligent CAN controller with a
+    microcontroller and associated firmware.
+    
+    Signed-off-by: Ira W. Snyder 
+    Acked-by: Wolfgang Grandegger 
+    Acked-by: David S. Miller 
+    Signed-off-by: Samuel Ortiz 
+
+diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
+index 05b751719bd5..2c5227c02fa0 100644
+--- a/drivers/net/can/Kconfig
++++ b/drivers/net/can/Kconfig
+@@ -63,6 +63,16 @@ config CAN_BFIN
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called bfin_can.
+ 
++config CAN_JANZ_ICAN3
++	tristate "Janz VMOD-ICAN3 Intelligent CAN controller"
++	depends on CAN_DEV && MFD_JANZ_CMODIO
++	---help---
++	  Driver for Janz VMOD-ICAN3 Intelligent CAN controller module, which
++	  connects to a MODULbus carrier board.
++
++	  This driver can also be built as a module. If so, the module will be
++	  called janz-ican3.ko.
++
+ source "drivers/net/can/mscan/Kconfig"
+ 
+ source "drivers/net/can/sja1000/Kconfig"
+diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
+index 7a702f28d01c..9047cd066fea 100644
+--- a/drivers/net/can/Makefile
++++ b/drivers/net/can/Makefile
+@@ -15,5 +15,6 @@ obj-$(CONFIG_CAN_AT91)		+= at91_can.o
+ obj-$(CONFIG_CAN_TI_HECC)	+= ti_hecc.o
+ obj-$(CONFIG_CAN_MCP251X)	+= mcp251x.o
+ obj-$(CONFIG_CAN_BFIN)		+= bfin_can.o
++obj-$(CONFIG_CAN_JANZ_ICAN3)	+= janz-ican3.o
+ 
+ ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
+diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c
+new file mode 100644
+index 000000000000..6e533dcc36c0
+--- /dev/null
++++ b/drivers/net/can/janz-ican3.c
+@@ -0,0 +1,1830 @@
++/*
++ * Janz MODULbus VMOD-ICAN3 CAN Interface Driver
++ *
++ * Copyright (c) 2010 Ira W. Snyder 
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++#include 
++#include 
++#include 
++
++#include 
++
++/* the DPM has 64k of memory, organized into 256x 256 byte pages */
++#define DPM_NUM_PAGES		256
++#define DPM_PAGE_SIZE		256
++#define DPM_PAGE_ADDR(p)	((p) * DPM_PAGE_SIZE)
++
++/* JANZ ICAN3 "old-style" host interface queue page numbers */
++#define QUEUE_OLD_CONTROL	0
++#define QUEUE_OLD_RB0		1
++#define QUEUE_OLD_RB1		2
++#define QUEUE_OLD_WB0		3
++#define QUEUE_OLD_WB1		4
++
++/* Janz ICAN3 "old-style" host interface control registers */
++#define MSYNC_PEER		0x00		/* ICAN only */
++#define MSYNC_LOCL		0x01		/* host only */
++#define TARGET_RUNNING		0x02
++
++#define MSYNC_RB0		0x01
++#define MSYNC_RB1		0x02
++#define MSYNC_RBLW		0x04
++#define MSYNC_RB_MASK		(MSYNC_RB0 | MSYNC_RB1)
++
++#define MSYNC_WB0		0x10
++#define MSYNC_WB1		0x20
++#define MSYNC_WBLW		0x40
++#define MSYNC_WB_MASK		(MSYNC_WB0 | MSYNC_WB1)
++
++/* Janz ICAN3 "new-style" host interface queue page numbers */
++#define QUEUE_TOHOST		5
++#define QUEUE_FROMHOST_MID	6
++#define QUEUE_FROMHOST_HIGH	7
++#define QUEUE_FROMHOST_LOW	8
++
++/* The first free page in the DPM is #9 */
++#define DPM_FREE_START		9
++
++/* Janz ICAN3 "new-style" and "fast" host interface descriptor flags */
++#define DESC_VALID		0x80
++#define DESC_WRAP		0x40
++#define DESC_INTERRUPT		0x20
++#define DESC_IVALID		0x10
++#define DESC_LEN(len)		(len)
++
++/* Janz ICAN3 Firmware Messages */
++#define MSG_CONNECTI		0x02
++#define MSG_DISCONNECT		0x03
++#define MSG_IDVERS		0x04
++#define MSG_MSGLOST		0x05
++#define MSG_NEWHOSTIF		0x08
++#define MSG_INQUIRY		0x0a
++#define MSG_SETAFILMASK		0x10
++#define MSG_INITFDPMQUEUE	0x11
++#define MSG_HWCONF		0x12
++#define MSG_FMSGLOST		0x15
++#define MSG_CEVTIND		0x37
++#define MSG_CBTRREQ		0x41
++#define MSG_COFFREQ		0x42
++#define MSG_CONREQ		0x43
++#define MSG_CCONFREQ		0x47
++
++/*
++ * Janz ICAN3 CAN Inquiry Message Types
++ *
++ * NOTE: there appears to be a firmware bug here. You must send
++ * NOTE: INQUIRY_STATUS and expect to receive an INQUIRY_EXTENDED
++ * NOTE: response. The controller never responds to a message with
++ * NOTE: the INQUIRY_EXTENDED subspec :(
++ */
++#define INQUIRY_STATUS		0x00
++#define INQUIRY_TERMINATION	0x01
++#define INQUIRY_EXTENDED	0x04
++
++/* Janz ICAN3 CAN Set Acceptance Filter Mask Message Types */
++#define SETAFILMASK_REJECT	0x00
++#define SETAFILMASK_FASTIF	0x02
++
++/* Janz ICAN3 CAN Hardware Configuration Message Types */
++#define HWCONF_TERMINATE_ON	0x01
++#define HWCONF_TERMINATE_OFF	0x00
++
++/* Janz ICAN3 CAN Event Indication Message Types */
++#define CEVTIND_EI		0x01
++#define CEVTIND_DOI		0x02
++#define CEVTIND_LOST		0x04
++#define CEVTIND_FULL		0x08
++#define CEVTIND_BEI		0x10
++
++#define CEVTIND_CHIP_SJA1000	0x02
++
++#define ICAN3_BUSERR_QUOTA_MAX	255
++
++/* Janz ICAN3 CAN Frame Conversion */
++#define ICAN3_ECHO	0x10
++#define ICAN3_EFF_RTR	0x40
++#define ICAN3_SFF_RTR	0x10
++#define ICAN3_EFF	0x80
++
++#define ICAN3_CAN_TYPE_MASK	0x0f
++#define ICAN3_CAN_TYPE_SFF	0x00
++#define ICAN3_CAN_TYPE_EFF	0x01
++
++#define ICAN3_CAN_DLC_MASK	0x0f
++
++/*
++ * SJA1000 Status and Error Register Definitions
++ *
++ * Copied from drivers/net/can/sja1000/sja1000.h
++ */
++
++/* status register content */
++#define SR_BS		0x80
++#define SR_ES		0x40
++#define SR_TS		0x20
++#define SR_RS		0x10
++#define SR_TCS		0x08
++#define SR_TBS		0x04
++#define SR_DOS		0x02
++#define SR_RBS		0x01
++
++#define SR_CRIT (SR_BS|SR_ES)
++
++/* ECC register */
++#define ECC_SEG		0x1F
++#define ECC_DIR		0x20
++#define ECC_ERR		6
++#define ECC_BIT		0x00
++#define ECC_FORM	0x40
++#define ECC_STUFF	0x80
++#define ECC_MASK	0xc0
++
++/* Number of buffers for use in the "new-style" host interface */
++#define ICAN3_NEW_BUFFERS	16
++
++/* Number of buffers for use in the "fast" host interface */
++#define ICAN3_TX_BUFFERS	512
++#define ICAN3_RX_BUFFERS	1024
++
++/* SJA1000 Clock Input */
++#define ICAN3_CAN_CLOCK		8000000
++
++/* Driver Name */
++#define DRV_NAME "janz-ican3"
++
++/* DPM Control Registers -- starts at offset 0x100 in the MODULbus registers */
++struct ican3_dpm_control {
++	/* window address register */
++	u8 window_address;
++	u8 unused1;
++
++	/*
++	 * Read access: clear interrupt from microcontroller
++	 * Write access: send interrupt to microcontroller
++	 */
++	u8 interrupt;
++	u8 unused2;
++
++	/* write-only: reset all hardware on the module */
++	u8 hwreset;
++	u8 unused3;
++
++	/* write-only: generate an interrupt to the TPU */
++	u8 tpuinterrupt;
++};
++
++struct ican3_dev {
++
++	/* must be the first member */
++	struct can_priv can;
++
++	/* CAN network device */
++	struct net_device *ndev;
++	struct napi_struct napi;
++
++	/* Device for printing */
++	struct device *dev;
++
++	/* module number */
++	unsigned int num;
++
++	/* base address of registers and IRQ */
++	struct janz_cmodio_onboard_regs __iomem *ctrl;
++	struct ican3_dpm_control __iomem *dpmctrl;
++	void __iomem *dpm;
++	int irq;
++
++	/* CAN bus termination status */
++	struct completion termination_comp;
++	bool termination_enabled;
++
++	/* CAN bus error status registers */
++	struct completion buserror_comp;
++	struct can_berr_counter bec;
++
++	/* old and new style host interface */
++	unsigned int iftype;
++
++	/*
++	 * Any function which changes the current DPM page must hold this
++	 * lock while it is performing data accesses. This ensures that the
++	 * function will not be preempted and end up reading data from a
++	 * different DPM page than it expects.
++	 */
++	spinlock_t lock;
++
++	/* new host interface */
++	unsigned int rx_int;
++	unsigned int rx_num;
++	unsigned int tx_num;
++
++	/* fast host interface */
++	unsigned int fastrx_start;
++	unsigned int fastrx_int;
++	unsigned int fastrx_num;
++	unsigned int fasttx_start;
++	unsigned int fasttx_num;
++
++	/* first free DPM page */
++	unsigned int free_page;
++};
++
++struct ican3_msg {
++	u8 control;
++	u8 spec;
++	__le16 len;
++	u8 data[252];
++};
++
++struct ican3_new_desc {
++	u8 control;
++	u8 pointer;
++};
++
++struct ican3_fast_desc {
++	u8 control;
++	u8 command;
++	u8 data[14];
++};
++
++/* write to the window basic address register */
++static inline void ican3_set_page(struct ican3_dev *mod, unsigned int page)
++{
++	BUG_ON(page >= DPM_NUM_PAGES);
++	iowrite8(page, &mod->dpmctrl->window_address);
++}
++
++/*
++ * ICAN3 "old-style" host interface
++ */
++
++/*
++ * Recieve a message from the ICAN3 "old-style" firmware interface
++ *
++ * LOCKING: must hold mod->lock
++ *
++ * returns 0 on success, -ENOMEM when no message exists
++ */
++static int ican3_old_recv_msg(struct ican3_dev *mod, struct ican3_msg *msg)
++{
++	unsigned int mbox, mbox_page;
++	u8 locl, peer, xord;
++
++	/* get the MSYNC registers */
++	ican3_set_page(mod, QUEUE_OLD_CONTROL);
++	peer = ioread8(mod->dpm + MSYNC_PEER);
++	locl = ioread8(mod->dpm + MSYNC_LOCL);
++	xord = locl ^ peer;
++
++	if ((xord & MSYNC_RB_MASK) == 0x00) {
++		dev_dbg(mod->dev, "no mbox for reading\n");
++		return -ENOMEM;
++	}
++
++	/* find the first free mbox to read */
++	if ((xord & MSYNC_RB_MASK) == MSYNC_RB_MASK)
++		mbox = (xord & MSYNC_RBLW) ? MSYNC_RB0 : MSYNC_RB1;
++	else
++		mbox = (xord & MSYNC_RB0) ? MSYNC_RB0 : MSYNC_RB1;
++
++	/* copy the message */
++	mbox_page = (mbox == MSYNC_RB0) ? QUEUE_OLD_RB0 : QUEUE_OLD_RB1;
++	ican3_set_page(mod, mbox_page);
++	memcpy_fromio(msg, mod->dpm, sizeof(*msg));
++
++	/*
++	 * notify the firmware that the read buffer is available
++	 * for it to fill again
++	 */
++	locl ^= mbox;
++
++	ican3_set_page(mod, QUEUE_OLD_CONTROL);
++	iowrite8(locl, mod->dpm + MSYNC_LOCL);
++	return 0;
++}
++
++/*
++ * Send a message through the "old-style" firmware interface
++ *
++ * LOCKING: must hold mod->lock
++ *
++ * returns 0 on success, -ENOMEM when no free space exists
++ */
++static int ican3_old_send_msg(struct ican3_dev *mod, struct ican3_msg *msg)
++{
++	unsigned int mbox, mbox_page;
++	u8 locl, peer, xord;
++
++	/* get the MSYNC registers */
++	ican3_set_page(mod, QUEUE_OLD_CONTROL);
++	peer = ioread8(mod->dpm + MSYNC_PEER);
++	locl = ioread8(mod->dpm + MSYNC_LOCL);
++	xord = locl ^ peer;
++
++	if ((xord & MSYNC_WB_MASK) == MSYNC_WB_MASK) {
++		dev_err(mod->dev, "no mbox for writing\n");
++		return -ENOMEM;
++	}
++
++	/* calculate a free mbox to use */
++	mbox = (xord & MSYNC_WB0) ? MSYNC_WB1 : MSYNC_WB0;
++
++	/* copy the message to the DPM */
++	mbox_page = (mbox == MSYNC_WB0) ? QUEUE_OLD_WB0 : QUEUE_OLD_WB1;
++	ican3_set_page(mod, mbox_page);
++	memcpy_toio(mod->dpm, msg, sizeof(*msg));
++
++	locl ^= mbox;
++	if (mbox == MSYNC_WB1)
++		locl |= MSYNC_WBLW;
++
++	ican3_set_page(mod, QUEUE_OLD_CONTROL);
++	iowrite8(locl, mod->dpm + MSYNC_LOCL);
++	return 0;
++}
++
++/*
++ * ICAN3 "new-style" Host Interface Setup
++ */
++
++static void __devinit ican3_init_new_host_interface(struct ican3_dev *mod)
++{
++	struct ican3_new_desc desc;
++	unsigned long flags;
++	void __iomem *dst;
++	int i;
++
++	spin_lock_irqsave(&mod->lock, flags);
++
++	/* setup the internal datastructures for RX */
++	mod->rx_num = 0;
++	mod->rx_int = 0;
++
++	/* tohost queue descriptors are in page 5 */
++	ican3_set_page(mod, QUEUE_TOHOST);
++	dst = mod->dpm;
++
++	/* initialize the tohost (rx) queue descriptors: pages 9-24 */
++	for (i = 0; i < ICAN3_NEW_BUFFERS; i++) {
++		desc.control = DESC_INTERRUPT | DESC_LEN(1); /* I L=1 */
++		desc.pointer = mod->free_page;
++
++		/* set wrap flag on last buffer */
++		if (i == ICAN3_NEW_BUFFERS - 1)
++			desc.control |= DESC_WRAP;
++
++		memcpy_toio(dst, &desc, sizeof(desc));
++		dst += sizeof(desc);
++		mod->free_page++;
++	}
++
++	/* fromhost (tx) mid queue descriptors are in page 6 */
++	ican3_set_page(mod, QUEUE_FROMHOST_MID);
++	dst = mod->dpm;
++
++	/* setup the internal datastructures for TX */
++	mod->tx_num = 0;
++
++	/* initialize the fromhost mid queue descriptors: pages 25-40 */
++	for (i = 0; i < ICAN3_NEW_BUFFERS; i++) {
++		desc.control = DESC_VALID | DESC_LEN(1); /* V L=1 */
++		desc.pointer = mod->free_page;
++
++		/* set wrap flag on last buffer */
++		if (i == ICAN3_NEW_BUFFERS - 1)
++			desc.control |= DESC_WRAP;
++
++		memcpy_toio(dst, &desc, sizeof(desc));
++		dst += sizeof(desc);
++		mod->free_page++;
++	}
++
++	/* fromhost hi queue descriptors are in page 7 */
++	ican3_set_page(mod, QUEUE_FROMHOST_HIGH);
++	dst = mod->dpm;
++
++	/* initialize only a single buffer in the fromhost hi queue (unused) */
++	desc.control = DESC_VALID | DESC_WRAP | DESC_LEN(1); /* VW L=1 */
++	desc.pointer = mod->free_page;
++	memcpy_toio(dst, &desc, sizeof(desc));
++	mod->free_page++;
++
++	/* fromhost low queue descriptors are in page 8 */
++	ican3_set_page(mod, QUEUE_FROMHOST_LOW);
++	dst = mod->dpm;
++
++	/* initialize only a single buffer in the fromhost low queue (unused) */
++	desc.control = DESC_VALID | DESC_WRAP | DESC_LEN(1); /* VW L=1 */
++	desc.pointer = mod->free_page;
++	memcpy_toio(dst, &desc, sizeof(desc));
++	mod->free_page++;
++
++	spin_unlock_irqrestore(&mod->lock, flags);
++}
++
++/*
++ * ICAN3 Fast Host Interface Setup
++ */
++
++static void __devinit ican3_init_fast_host_interface(struct ican3_dev *mod)
++{
++	struct ican3_fast_desc desc;
++	unsigned long flags;
++	unsigned int addr;
++	void __iomem *dst;
++	int i;
++
++	spin_lock_irqsave(&mod->lock, flags);
++
++	/* save the start recv page */
++	mod->fastrx_start = mod->free_page;
++	mod->fastrx_num = 0;
++	mod->fastrx_int = 0;
++
++	/* build a single fast tohost queue descriptor */
++	memset(&desc, 0, sizeof(desc));
++	desc.control = 0x00;
++	desc.command = 1;
++
++	/* build the tohost queue descriptor ring in memory */
++	addr = 0;
++	for (i = 0; i < ICAN3_RX_BUFFERS; i++) {
++
++		/* set the wrap bit on the last buffer */
++		if (i == ICAN3_RX_BUFFERS - 1)
++			desc.control |= DESC_WRAP;
++
++		/* switch to the correct page */
++		ican3_set_page(mod, mod->free_page);
++
++		/* copy the descriptor to the DPM */
++		dst = mod->dpm + addr;
++		memcpy_toio(dst, &desc, sizeof(desc));
++		addr += sizeof(desc);
++
++		/* move to the next page if necessary */
++		if (addr >= DPM_PAGE_SIZE) {
++			addr = 0;
++			mod->free_page++;
++		}
++	}
++
++	/* make sure we page-align the next queue */
++	if (addr != 0)
++		mod->free_page++;
++
++	/* save the start xmit page */
++	mod->fasttx_start = mod->free_page;
++	mod->fasttx_num = 0;
++
++	/* build a single fast fromhost queue descriptor */
++	memset(&desc, 0, sizeof(desc));
++	desc.control = DESC_VALID;
++	desc.command = 1;
++
++	/* build the fromhost queue descriptor ring in memory */
++	addr = 0;
++	for (i = 0; i < ICAN3_TX_BUFFERS; i++) {
++
++		/* set the wrap bit on the last buffer */
++		if (i == ICAN3_TX_BUFFERS - 1)
++			desc.control |= DESC_WRAP;
++
++		/* switch to the correct page */
++		ican3_set_page(mod, mod->free_page);
++
++		/* copy the descriptor to the DPM */
++		dst = mod->dpm + addr;
++		memcpy_toio(dst, &desc, sizeof(desc));
++		addr += sizeof(desc);
++
++		/* move to the next page if necessary */
++		if (addr >= DPM_PAGE_SIZE) {
++			addr = 0;
++			mod->free_page++;
++		}
++	}
++
++	spin_unlock_irqrestore(&mod->lock, flags);
++}
++
++/*
++ * ICAN3 "new-style" Host Interface Message Helpers
++ */
++
++/*
++ * LOCKING: must hold mod->lock
++ */
++static int ican3_new_send_msg(struct ican3_dev *mod, struct ican3_msg *msg)
++{
++	struct ican3_new_desc desc;
++	void __iomem *desc_addr = mod->dpm + (mod->tx_num * sizeof(desc));
++
++	/* switch to the fromhost mid queue, and read the buffer descriptor */
++	ican3_set_page(mod, QUEUE_FROMHOST_MID);
++	memcpy_fromio(&desc, desc_addr, sizeof(desc));
++
++	if (!(desc.control & DESC_VALID)) {
++		dev_dbg(mod->dev, "%s: no free buffers\n", __func__);
++		return -ENOMEM;
++	}
++
++	/* switch to the data page, copy the data */
++	ican3_set_page(mod, desc.pointer);
++	memcpy_toio(mod->dpm, msg, sizeof(*msg));
++
++	/* switch back to the descriptor, set the valid bit, write it back */
++	ican3_set_page(mod, QUEUE_FROMHOST_MID);
++	desc.control ^= DESC_VALID;
++	memcpy_toio(desc_addr, &desc, sizeof(desc));
++
++	/* update the tx number */
++	mod->tx_num = (desc.control & DESC_WRAP) ? 0 : (mod->tx_num + 1);
++	return 0;
++}
++
++/*
++ * LOCKING: must hold mod->lock
++ */
++static int ican3_new_recv_msg(struct ican3_dev *mod, struct ican3_msg *msg)
++{
++	struct ican3_new_desc desc;
++	void __iomem *desc_addr = mod->dpm + (mod->rx_num * sizeof(desc));
++
++	/* switch to the tohost queue, and read the buffer descriptor */
++	ican3_set_page(mod, QUEUE_TOHOST);
++	memcpy_fromio(&desc, desc_addr, sizeof(desc));
++
++	if (!(desc.control & DESC_VALID)) {
++		dev_dbg(mod->dev, "%s: no buffers to recv\n", __func__);
++		return -ENOMEM;
++	}
++
++	/* switch to the data page, copy the data */
++	ican3_set_page(mod, desc.pointer);
++	memcpy_fromio(msg, mod->dpm, sizeof(*msg));
++
++	/* switch back to the descriptor, toggle the valid bit, write it back */
++	ican3_set_page(mod, QUEUE_TOHOST);
++	desc.control ^= DESC_VALID;
++	memcpy_toio(desc_addr, &desc, sizeof(desc));
++
++	/* update the rx number */
++	mod->rx_num = (desc.control & DESC_WRAP) ? 0 : (mod->rx_num + 1);
++	return 0;
++}
++
++/*
++ * Message Send / Recv Helpers
++ */
++
++static int ican3_send_msg(struct ican3_dev *mod, struct ican3_msg *msg)
++{
++	unsigned long flags;
++	int ret;
++
++	spin_lock_irqsave(&mod->lock, flags);
++
++	if (mod->iftype == 0)
++		ret = ican3_old_send_msg(mod, msg);
++	else
++		ret = ican3_new_send_msg(mod, msg);
++
++	spin_unlock_irqrestore(&mod->lock, flags);
++	return ret;
++}
++
++static int ican3_recv_msg(struct ican3_dev *mod, struct ican3_msg *msg)
++{
++	unsigned long flags;
++	int ret;
++
++	spin_lock_irqsave(&mod->lock, flags);
++
++	if (mod->iftype == 0)
++		ret = ican3_old_recv_msg(mod, msg);
++	else
++		ret = ican3_new_recv_msg(mod, msg);
++
++	spin_unlock_irqrestore(&mod->lock, flags);
++	return ret;
++}
++
++/*
++ * Quick Pre-constructed Messages
++ */
++
++static int __devinit ican3_msg_connect(struct ican3_dev *mod)
++{
++	struct ican3_msg msg;
++
++	memset(&msg, 0, sizeof(msg));
++	msg.spec = MSG_CONNECTI;
++	msg.len = cpu_to_le16(0);
++
++	return ican3_send_msg(mod, &msg);
++}
++
++static int __devexit ican3_msg_disconnect(struct ican3_dev *mod)
++{
++	struct ican3_msg msg;
++
++	memset(&msg, 0, sizeof(msg));
++	msg.spec = MSG_DISCONNECT;
++	msg.len = cpu_to_le16(0);
++
++	return ican3_send_msg(mod, &msg);
++}
++
++static int __devinit ican3_msg_newhostif(struct ican3_dev *mod)
++{
++	struct ican3_msg msg;
++	int ret;
++
++	memset(&msg, 0, sizeof(msg));
++	msg.spec = MSG_NEWHOSTIF;
++	msg.len = cpu_to_le16(0);
++
++	/* If we're not using the old interface, switching seems bogus */
++	WARN_ON(mod->iftype != 0);
++
++	ret = ican3_send_msg(mod, &msg);
++	if (ret)
++		return ret;
++
++	/* mark the module as using the new host interface */
++	mod->iftype = 1;
++	return 0;
++}
++
++static int __devinit ican3_msg_fasthostif(struct ican3_dev *mod)
++{
++	struct ican3_msg msg;
++	unsigned int addr;
++
++	memset(&msg, 0, sizeof(msg));
++	msg.spec = MSG_INITFDPMQUEUE;
++	msg.len = cpu_to_le16(8);
++
++	/* write the tohost queue start address */
++	addr = DPM_PAGE_ADDR(mod->fastrx_start);
++	msg.data[0] = addr & 0xff;
++	msg.data[1] = (addr >> 8) & 0xff;
++	msg.data[2] = (addr >> 16) & 0xff;
++	msg.data[3] = (addr >> 24) & 0xff;
++
++	/* write the fromhost queue start address */
++	addr = DPM_PAGE_ADDR(mod->fasttx_start);
++	msg.data[4] = addr & 0xff;
++	msg.data[5] = (addr >> 8) & 0xff;
++	msg.data[6] = (addr >> 16) & 0xff;
++	msg.data[7] = (addr >> 24) & 0xff;
++
++	/* If we're not using the new interface yet, we cannot do this */
++	WARN_ON(mod->iftype != 1);
++
++	return ican3_send_msg(mod, &msg);
++}
++
++/*
++ * Setup the CAN filter to either accept or reject all
++ * messages from the CAN bus.
++ */
++static int __devinit ican3_set_id_filter(struct ican3_dev *mod, bool accept)
++{
++	struct ican3_msg msg;
++	int ret;
++
++	/* Standard Frame Format */
++	memset(&msg, 0, sizeof(msg));
++	msg.spec = MSG_SETAFILMASK;
++	msg.len = cpu_to_le16(5);
++	msg.data[0] = 0x00; /* IDLo LSB */
++	msg.data[1] = 0x00; /* IDLo MSB */
++	msg.data[2] = 0xff; /* IDHi LSB */
++	msg.data[3] = 0x07; /* IDHi MSB */
++
++	/* accept all frames for fast host if, or reject all frames */
++	msg.data[4] = accept ? SETAFILMASK_FASTIF : SETAFILMASK_REJECT;
++
++	ret = ican3_send_msg(mod, &msg);
++	if (ret)
++		return ret;
++
++	/* Extended Frame Format */
++	memset(&msg, 0, sizeof(msg));
++	msg.spec = MSG_SETAFILMASK;
++	msg.len = cpu_to_le16(13);
++	msg.data[0] = 0;    /* MUX = 0 */
++	msg.data[1] = 0x00; /* IDLo LSB */
++	msg.data[2] = 0x00;
++	msg.data[3] = 0x00;
++	msg.data[4] = 0x20; /* IDLo MSB */
++	msg.data[5] = 0xff; /* IDHi LSB */
++	msg.data[6] = 0xff;
++	msg.data[7] = 0xff;
++	msg.data[8] = 0x3f; /* IDHi MSB */
++
++	/* accept all frames for fast host if, or reject all frames */
++	msg.data[9] = accept ? SETAFILMASK_FASTIF : SETAFILMASK_REJECT;
++
++	return ican3_send_msg(mod, &msg);
++}
++
++/*
++ * Bring the CAN bus online or offline
++ */
++static int ican3_set_bus_state(struct ican3_dev *mod, bool on)
++{
++	struct ican3_msg msg;
++
++	memset(&msg, 0, sizeof(msg));
++	msg.spec = on ? MSG_CONREQ : MSG_COFFREQ;
++	msg.len = cpu_to_le16(0);
++
++	return ican3_send_msg(mod, &msg);
++}
++
++static int ican3_set_termination(struct ican3_dev *mod, bool on)
++{
++	struct ican3_msg msg;
++
++	memset(&msg, 0, sizeof(msg));
++	msg.spec = MSG_HWCONF;
++	msg.len = cpu_to_le16(2);
++	msg.data[0] = 0x00;
++	msg.data[1] = on ? HWCONF_TERMINATE_ON : HWCONF_TERMINATE_OFF;
++
++	return ican3_send_msg(mod, &msg);
++}
++
++static int ican3_send_inquiry(struct ican3_dev *mod, u8 subspec)
++{
++	struct ican3_msg msg;
++
++	memset(&msg, 0, sizeof(msg));
++	msg.spec = MSG_INQUIRY;
++	msg.len = cpu_to_le16(2);
++	msg.data[0] = subspec;
++	msg.data[1] = 0x00;
++
++	return ican3_send_msg(mod, &msg);
++}
++
++static int ican3_set_buserror(struct ican3_dev *mod, u8 quota)
++{
++	struct ican3_msg msg;
++
++	memset(&msg, 0, sizeof(msg));
++	msg.spec = MSG_CCONFREQ;
++	msg.len = cpu_to_le16(2);
++	msg.data[0] = 0x00;
++	msg.data[1] = quota;
++
++	return ican3_send_msg(mod, &msg);
++}
++
++/*
++ * ICAN3 to Linux CAN Frame Conversion
++ */
++
++static void ican3_to_can_frame(struct ican3_dev *mod,
++			       struct ican3_fast_desc *desc,
++			       struct can_frame *cf)
++{
++	if ((desc->command & ICAN3_CAN_TYPE_MASK) == ICAN3_CAN_TYPE_SFF) {
++		if (desc->data[1] & ICAN3_SFF_RTR)
++			cf->can_id |= CAN_RTR_FLAG;
++
++		cf->can_id |= desc->data[0] << 3;
++		cf->can_id |= (desc->data[1] & 0xe0) >> 5;
++		cf->can_dlc = desc->data[1] & ICAN3_CAN_DLC_MASK;
++		memcpy(cf->data, &desc->data[2], sizeof(cf->data));
++	} else {
++		cf->can_dlc = desc->data[0] & ICAN3_CAN_DLC_MASK;
++		if (desc->data[0] & ICAN3_EFF_RTR)
++			cf->can_id |= CAN_RTR_FLAG;
++
++		if (desc->data[0] & ICAN3_EFF) {
++			cf->can_id |= CAN_EFF_FLAG;
++			cf->can_id |= desc->data[2] << 21; /* 28-21 */
++			cf->can_id |= desc->data[3] << 13; /* 20-13 */
++			cf->can_id |= desc->data[4] << 5;  /* 12-5  */
++			cf->can_id |= (desc->data[5] & 0xf8) >> 3;
++		} else {
++			cf->can_id |= desc->data[2] << 3;  /* 10-3  */
++			cf->can_id |= desc->data[3] >> 5;  /* 2-0   */
++		}
++
++		memcpy(cf->data, &desc->data[6], sizeof(cf->data));
++	}
++}
++
++static void can_frame_to_ican3(struct ican3_dev *mod,
++			       struct can_frame *cf,
++			       struct ican3_fast_desc *desc)
++{
++	/* clear out any stale data in the descriptor */
++	memset(desc->data, 0, sizeof(desc->data));
++
++	/* we always use the extended format, with the ECHO flag set */
++	desc->command = ICAN3_CAN_TYPE_EFF;
++	desc->data[0] |= cf->can_dlc;
++	desc->data[1] |= ICAN3_ECHO;
++
++	if (cf->can_id & CAN_RTR_FLAG)
++		desc->data[0] |= ICAN3_EFF_RTR;
++
++	/* pack the id into the correct places */
++	if (cf->can_id & CAN_EFF_FLAG) {
++		desc->data[0] |= ICAN3_EFF;
++		desc->data[2] = (cf->can_id & 0x1fe00000) >> 21; /* 28-21 */
++		desc->data[3] = (cf->can_id & 0x001fe000) >> 13; /* 20-13 */
++		desc->data[4] = (cf->can_id & 0x00001fe0) >> 5;  /* 12-5  */
++		desc->data[5] = (cf->can_id & 0x0000001f) << 3;  /* 4-0   */
++	} else {
++		desc->data[2] = (cf->can_id & 0x7F8) >> 3; /* bits 10-3 */
++		desc->data[3] = (cf->can_id & 0x007) << 5; /* bits 2-0  */
++	}
++
++	/* copy the data bits into the descriptor */
++	memcpy(&desc->data[6], cf->data, sizeof(cf->data));
++}
++
++/*
++ * Interrupt Handling
++ */
++
++/*
++ * Handle an ID + Version message response from the firmware. We never generate
++ * this message in production code, but it is very useful when debugging to be
++ * able to display this message.
++ */
++static void ican3_handle_idvers(struct ican3_dev *mod, struct ican3_msg *msg)
++{
++	dev_dbg(mod->dev, "IDVERS response: %s\n", msg->data);
++}
++
++static void ican3_handle_msglost(struct ican3_dev *mod, struct ican3_msg *msg)
++{
++	struct net_device *dev = mod->ndev;
++	struct net_device_stats *stats = &dev->stats;
++	struct can_frame *cf;
++	struct sk_buff *skb;
++
++	/*
++	 * Report that communication messages with the microcontroller firmware
++	 * are being lost. These are never CAN frames, so we do not generate an
++	 * error frame for userspace
++	 */
++	if (msg->spec == MSG_MSGLOST) {
++		dev_err(mod->dev, "lost %d control messages\n", msg->data[0]);
++		return;
++	}
++
++	/*
++	 * Oops, this indicates that we have lost messages in the fast queue,
++	 * which are exclusively CAN messages. Our driver isn't reading CAN
++	 * frames fast enough.
++	 *
++	 * We'll pretend that the SJA1000 told us that it ran out of buffer
++	 * space, because there is not a better message for this.
++	 */
++	skb = alloc_can_err_skb(dev, &cf);
++	if (skb) {
++		cf->can_id |= CAN_ERR_CRTL;
++		cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
++		stats->rx_errors++;
++		stats->rx_bytes += cf->can_dlc;
++		netif_rx(skb);
++	}
++}
++
++/*
++ * Handle CAN Event Indication Messages from the firmware
++ *
++ * The ICAN3 firmware provides the values of some SJA1000 registers when it
++ * generates this message. The code below is largely copied from the
++ * drivers/net/can/sja1000/sja1000.c file, and adapted as necessary
++ */
++static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg)
++{
++	struct net_device *dev = mod->ndev;
++	struct net_device_stats *stats = &dev->stats;
++	enum can_state state = mod->can.state;
++	u8 status, isrc, rxerr, txerr;
++	struct can_frame *cf;
++	struct sk_buff *skb;
++
++	/* we can only handle the SJA1000 part */
++	if (msg->data[1] != CEVTIND_CHIP_SJA1000) {
++		dev_err(mod->dev, "unable to handle errors on non-SJA1000\n");
++		return -ENODEV;
++	}
++
++	/* check the message length for sanity */
++	if (le16_to_cpu(msg->len) < 6) {
++		dev_err(mod->dev, "error message too short\n");
++		return -EINVAL;
++	}
++
++	skb = alloc_can_err_skb(dev, &cf);
++	if (skb == NULL)
++		return -ENOMEM;
++
++	isrc = msg->data[0];
++	status = msg->data[3];
++	rxerr = msg->data[4];
++	txerr = msg->data[5];
++
++	/* data overrun interrupt */
++	if (isrc == CEVTIND_DOI || isrc == CEVTIND_LOST) {
++		dev_dbg(mod->dev, "data overrun interrupt\n");
++		cf->can_id |= CAN_ERR_CRTL;
++		cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
++		stats->rx_over_errors++;
++		stats->rx_errors++;
++	}
++
++	/* error warning + passive interrupt */
++	if (isrc == CEVTIND_EI) {
++		dev_dbg(mod->dev, "error warning + passive interrupt\n");
++		if (status & SR_BS) {
++			state = CAN_STATE_BUS_OFF;
++			cf->can_id |= CAN_ERR_BUSOFF;
++			can_bus_off(dev);
++		} else if (status & SR_ES) {
++			if (rxerr >= 128 || txerr >= 128)
++				state = CAN_STATE_ERROR_PASSIVE;
++			else
++				state = CAN_STATE_ERROR_WARNING;
++		} else {
++			state = CAN_STATE_ERROR_ACTIVE;
++		}
++	}
++
++	/* bus error interrupt */
++	if (isrc == CEVTIND_BEI) {
++		u8 ecc = msg->data[2];
++
++		dev_dbg(mod->dev, "bus error interrupt\n");
++		mod->can.can_stats.bus_error++;
++		stats->rx_errors++;
++		cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
++
++		switch (ecc & ECC_MASK) {
++		case ECC_BIT:
++			cf->data[2] |= CAN_ERR_PROT_BIT;
++			break;
++		case ECC_FORM:
++			cf->data[2] |= CAN_ERR_PROT_FORM;
++			break;
++		case ECC_STUFF:
++			cf->data[2] |= CAN_ERR_PROT_STUFF;
++			break;
++		default:
++			cf->data[2] |= CAN_ERR_PROT_UNSPEC;
++			cf->data[3] = ecc & ECC_SEG;
++			break;
++		}
++
++		if ((ecc & ECC_DIR) == 0)
++			cf->data[2] |= CAN_ERR_PROT_TX;
++
++		cf->data[6] = txerr;
++		cf->data[7] = rxerr;
++	}
++
++	if (state != mod->can.state && (state == CAN_STATE_ERROR_WARNING ||
++					state == CAN_STATE_ERROR_PASSIVE)) {
++		cf->can_id |= CAN_ERR_CRTL;
++		if (state == CAN_STATE_ERROR_WARNING) {
++			mod->can.can_stats.error_warning++;
++			cf->data[1] = (txerr > rxerr) ?
++				CAN_ERR_CRTL_TX_WARNING :
++				CAN_ERR_CRTL_RX_WARNING;
++		} else {
++			mod->can.can_stats.error_passive++;
++			cf->data[1] = (txerr > rxerr) ?
++				CAN_ERR_CRTL_TX_PASSIVE :
++				CAN_ERR_CRTL_RX_PASSIVE;
++		}
++
++		cf->data[6] = txerr;
++		cf->data[7] = rxerr;
++	}
++
++	mod->can.state = state;
++	stats->rx_errors++;
++	stats->rx_bytes += cf->can_dlc;
++	netif_rx(skb);
++	return 0;
++}
++
++static void ican3_handle_inquiry(struct ican3_dev *mod, struct ican3_msg *msg)
++{
++	switch (msg->data[0]) {
++	case INQUIRY_STATUS:
++	case INQUIRY_EXTENDED:
++		mod->bec.rxerr = msg->data[5];
++		mod->bec.txerr = msg->data[6];
++		complete(&mod->buserror_comp);
++		break;
++	case INQUIRY_TERMINATION:
++		mod->termination_enabled = msg->data[6] & HWCONF_TERMINATE_ON;
++		complete(&mod->termination_comp);
++		break;
++	default:
++		dev_err(mod->dev, "recieved an unknown inquiry response\n");
++		break;
++	}
++}
++
++static void ican3_handle_unknown_message(struct ican3_dev *mod,
++					struct ican3_msg *msg)
++{
++	dev_warn(mod->dev, "recieved unknown message: spec 0x%.2x length %d\n",
++			   msg->spec, le16_to_cpu(msg->len));
++}
++
++/*
++ * Handle a control message from the firmware
++ */
++static void ican3_handle_message(struct ican3_dev *mod, struct ican3_msg *msg)
++{
++	dev_dbg(mod->dev, "%s: modno %d spec 0x%.2x len %d bytes\n", __func__,
++			   mod->num, msg->spec, le16_to_cpu(msg->len));
++
++	switch (msg->spec) {
++	case MSG_IDVERS:
++		ican3_handle_idvers(mod, msg);
++		break;
++	case MSG_MSGLOST:
++	case MSG_FMSGLOST:
++		ican3_handle_msglost(mod, msg);
++		break;
++	case MSG_CEVTIND:
++		ican3_handle_cevtind(mod, msg);
++		break;
++	case MSG_INQUIRY:
++		ican3_handle_inquiry(mod, msg);
++		break;
++	default:
++		ican3_handle_unknown_message(mod, msg);
++		break;
++	}
++}
++
++/*
++ * Check that there is room in the TX ring to transmit another skb
++ *
++ * LOCKING: must hold mod->lock
++ */
++static bool ican3_txok(struct ican3_dev *mod)
++{
++	struct ican3_fast_desc __iomem *desc;
++	u8 control;
++
++	/* copy the control bits of the descriptor */
++	ican3_set_page(mod, mod->fasttx_start + (mod->fasttx_num / 16));
++	desc = mod->dpm + ((mod->fasttx_num % 16) * sizeof(*desc));
++	control = ioread8(&desc->control);
++
++	/* if the control bits are not valid, then we have no more space */
++	if (!(control & DESC_VALID))
++		return false;
++
++	return true;
++}
++
++/*
++ * Recieve one CAN frame from the hardware
++ *
++ * This works like the core of a NAPI function, but is intended to be called
++ * from workqueue context instead. This driver already needs a workqueue to
++ * process control messages, so we use the workqueue instead of using NAPI.
++ * This was done to simplify locking.
++ *
++ * CONTEXT: must be called from user context
++ */
++static int ican3_recv_skb(struct ican3_dev *mod)
++{
++	struct net_device *ndev = mod->ndev;
++	struct net_device_stats *stats = &ndev->stats;
++	struct ican3_fast_desc desc;
++	void __iomem *desc_addr;
++	struct can_frame *cf;
++	struct sk_buff *skb;
++	unsigned long flags;
++
++	spin_lock_irqsave(&mod->lock, flags);
++
++	/* copy the whole descriptor */
++	ican3_set_page(mod, mod->fastrx_start + (mod->fastrx_num / 16));
++	desc_addr = mod->dpm + ((mod->fastrx_num % 16) * sizeof(desc));
++	memcpy_fromio(&desc, desc_addr, sizeof(desc));
++
++	spin_unlock_irqrestore(&mod->lock, flags);
++
++	/* check that we actually have a CAN frame */
++	if (!(desc.control & DESC_VALID))
++		return -ENOBUFS;
++
++	/* allocate an skb */
++	skb = alloc_can_skb(ndev, &cf);
++	if (unlikely(skb == NULL)) {
++		stats->rx_dropped++;
++		goto err_noalloc;
++	}
++
++	/* convert the ICAN3 frame into Linux CAN format */
++	ican3_to_can_frame(mod, &desc, cf);
++
++	/* receive the skb, update statistics */
++	netif_receive_skb(skb);
++	stats->rx_packets++;
++	stats->rx_bytes += cf->can_dlc;
++
++err_noalloc:
++	/* toggle the valid bit and return the descriptor to the ring */
++	desc.control ^= DESC_VALID;
++
++	spin_lock_irqsave(&mod->lock, flags);
++
++	ican3_set_page(mod, mod->fastrx_start + (mod->fastrx_num / 16));
++	memcpy_toio(desc_addr, &desc, 1);
++
++	/* update the next buffer pointer */
++	mod->fastrx_num = (desc.control & DESC_WRAP) ? 0
++						     : (mod->fastrx_num + 1);
++
++	/* there are still more buffers to process */
++	spin_unlock_irqrestore(&mod->lock, flags);
++	return 0;
++}
++
++static int ican3_napi(struct napi_struct *napi, int budget)
++{
++	struct ican3_dev *mod = container_of(napi, struct ican3_dev, napi);
++	struct ican3_msg msg;
++	unsigned long flags;
++	int received = 0;
++	int ret;
++
++	/* process all communication messages */
++	while (true) {
++		ret = ican3_recv_msg(mod, &msg);
++		if (ret)
++			break;
++
++		ican3_handle_message(mod, &msg);
++	}
++
++	/* process all CAN frames from the fast interface */
++	while (received < budget) {
++		ret = ican3_recv_skb(mod);
++		if (ret)
++			break;
++
++		received++;
++	}
++
++	/* We have processed all packets that the adapter had, but it
++	 * was less than our budget, stop polling */
++	if (received < budget)
++		napi_complete(napi);
++
++	spin_lock_irqsave(&mod->lock, flags);
++
++	/* Wake up the transmit queue if necessary */
++	if (netif_queue_stopped(mod->ndev) && ican3_txok(mod))
++		netif_wake_queue(mod->ndev);
++
++	spin_unlock_irqrestore(&mod->lock, flags);
++
++	/* re-enable interrupt generation */
++	iowrite8(1 << mod->num, &mod->ctrl->int_enable);
++	return received;
++}
++
++static irqreturn_t ican3_irq(int irq, void *dev_id)
++{
++	struct ican3_dev *mod = dev_id;
++	u8 stat;
++
++	/*
++	 * The interrupt status register on this device reports interrupts
++	 * as zeroes instead of using ones like most other devices
++	 */
++	stat = ioread8(&mod->ctrl->int_disable) & (1 << mod->num);
++	if (stat == (1 << mod->num))
++		return IRQ_NONE;
++
++	/* clear the MODULbus interrupt from the microcontroller */
++	ioread8(&mod->dpmctrl->interrupt);
++
++	/* disable interrupt generation, schedule the NAPI poller */
++	iowrite8(1 << mod->num, &mod->ctrl->int_disable);
++	napi_schedule(&mod->napi);
++	return IRQ_HANDLED;
++}
++
++/*
++ * Firmware reset, startup, and shutdown
++ */
++
++/*
++ * Reset an ICAN module to its power-on state
++ *
++ * CONTEXT: no network device registered
++ * LOCKING: work function disabled
++ */
++static int ican3_reset_module(struct ican3_dev *mod)
++{
++	u8 val = 1 << mod->num;
++	unsigned long start;
++	u8 runold, runnew;
++
++	/* disable interrupts so no more work is scheduled */
++	iowrite8(1 << mod->num, &mod->ctrl->int_disable);
++
++	/* flush any pending work */
++	flush_scheduled_work();
++
++	/* the first unallocated page in the DPM is #9 */
++	mod->free_page = DPM_FREE_START;
++
++	ican3_set_page(mod, QUEUE_OLD_CONTROL);
++	runold = ioread8(mod->dpm + TARGET_RUNNING);
++
++	/* reset the module */
++	iowrite8(val, &mod->ctrl->reset_assert);
++	iowrite8(val, &mod->ctrl->reset_deassert);
++
++	/* wait until the module has finished resetting and is running */
++	start = jiffies;
++	do {
++		ican3_set_page(mod, QUEUE_OLD_CONTROL);
++		runnew = ioread8(mod->dpm + TARGET_RUNNING);
++		if (runnew == (runold ^ 0xff))
++			return 0;
++
++		msleep(10);
++	} while (time_before(jiffies, start + HZ / 4));
++
++	dev_err(mod->dev, "failed to reset CAN module\n");
++	return -ETIMEDOUT;
++}
++
++static void __devexit ican3_shutdown_module(struct ican3_dev *mod)
++{
++	ican3_msg_disconnect(mod);
++	ican3_reset_module(mod);
++}
++
++/*
++ * Startup an ICAN module, bringing it into fast mode
++ */
++static int __devinit ican3_startup_module(struct ican3_dev *mod)
++{
++	int ret;
++
++	ret = ican3_reset_module(mod);
++	if (ret) {
++		dev_err(mod->dev, "unable to reset module\n");
++		return ret;
++	}
++
++	/* re-enable interrupts so we can send messages */
++	iowrite8(1 << mod->num, &mod->ctrl->int_enable);
++
++	ret = ican3_msg_connect(mod);
++	if (ret) {
++		dev_err(mod->dev, "unable to connect to module\n");
++		return ret;
++	}
++
++	ican3_init_new_host_interface(mod);
++	ret = ican3_msg_newhostif(mod);
++	if (ret) {
++		dev_err(mod->dev, "unable to switch to new-style interface\n");
++		return ret;
++	}
++
++	/* default to "termination on" */
++	ret = ican3_set_termination(mod, true);
++	if (ret) {
++		dev_err(mod->dev, "unable to enable termination\n");
++		return ret;
++	}
++
++	/* default to "bus errors enabled" */
++	ret = ican3_set_buserror(mod, ICAN3_BUSERR_QUOTA_MAX);
++	if (ret) {
++		dev_err(mod->dev, "unable to set bus-error\n");
++		return ret;
++	}
++
++	ican3_init_fast_host_interface(mod);
++	ret = ican3_msg_fasthostif(mod);
++	if (ret) {
++		dev_err(mod->dev, "unable to switch to fast host interface\n");
++		return ret;
++	}
++
++	ret = ican3_set_id_filter(mod, true);
++	if (ret) {
++		dev_err(mod->dev, "unable to set acceptance filter\n");
++		return ret;
++	}
++
++	return 0;
++}
++
++/*
++ * CAN Network Device
++ */
++
++static int ican3_open(struct net_device *ndev)
++{
++	struct ican3_dev *mod = netdev_priv(ndev);
++	u8 quota;
++	int ret;
++
++	/* open the CAN layer */
++	ret = open_candev(ndev);
++	if (ret) {
++		dev_err(mod->dev, "unable to start CAN layer\n");
++		return ret;
++	}
++
++	/* set the bus error generation state appropriately */
++	if (mod->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
++		quota = ICAN3_BUSERR_QUOTA_MAX;
++	else
++		quota = 0;
++
++	ret = ican3_set_buserror(mod, quota);
++	if (ret) {
++		dev_err(mod->dev, "unable to set bus-error\n");
++		close_candev(ndev);
++		return ret;
++	}
++
++	/* bring the bus online */
++	ret = ican3_set_bus_state(mod, true);
++	if (ret) {
++		dev_err(mod->dev, "unable to set bus-on\n");
++		close_candev(ndev);
++		return ret;
++	}
++
++	/* start up the network device */
++	mod->can.state = CAN_STATE_ERROR_ACTIVE;
++	netif_start_queue(ndev);
++
++	return 0;
++}
++
++static int ican3_stop(struct net_device *ndev)
++{
++	struct ican3_dev *mod = netdev_priv(ndev);
++	int ret;
++
++	/* stop the network device xmit routine */
++	netif_stop_queue(ndev);
++	mod->can.state = CAN_STATE_STOPPED;
++
++	/* bring the bus offline, stop receiving packets */
++	ret = ican3_set_bus_state(mod, false);
++	if (ret) {
++		dev_err(mod->dev, "unable to set bus-off\n");
++		return ret;
++	}
++
++	/* close the CAN layer */
++	close_candev(ndev);
++	return 0;
++}
++
++static int ican3_xmit(struct sk_buff *skb, struct net_device *ndev)
++{
++	struct ican3_dev *mod = netdev_priv(ndev);
++	struct net_device_stats *stats = &ndev->stats;
++	struct can_frame *cf = (struct can_frame *)skb->data;
++	struct ican3_fast_desc desc;
++	void __iomem *desc_addr;
++	unsigned long flags;
++
++	spin_lock_irqsave(&mod->lock, flags);
++
++	/* check that we can actually transmit */
++	if (!ican3_txok(mod)) {
++		dev_err(mod->dev, "no free descriptors, stopping queue\n");
++		netif_stop_queue(ndev);
++		spin_unlock_irqrestore(&mod->lock, flags);
++		return NETDEV_TX_BUSY;
++	}
++
++	/* copy the control bits of the descriptor */
++	ican3_set_page(mod, mod->fasttx_start + (mod->fasttx_num / 16));
++	desc_addr = mod->dpm + ((mod->fasttx_num % 16) * sizeof(desc));
++	memset(&desc, 0, sizeof(desc));
++	memcpy_fromio(&desc, desc_addr, 1);
++
++	/* convert the Linux CAN frame into ICAN3 format */
++	can_frame_to_ican3(mod, cf, &desc);
++
++	/*
++	 * the programming manual says that you must set the IVALID bit, then
++	 * interrupt, then set the valid bit. Quite weird, but it seems to be
++	 * required for this to work
++	 */
++	desc.control |= DESC_IVALID;
++	memcpy_toio(desc_addr, &desc, sizeof(desc));
++
++	/* generate a MODULbus interrupt to the microcontroller */
++	iowrite8(0x01, &mod->dpmctrl->interrupt);
++
++	desc.control ^= DESC_VALID;
++	memcpy_toio(desc_addr, &desc, sizeof(desc));
++
++	/* update the next buffer pointer */
++	mod->fasttx_num = (desc.control & DESC_WRAP) ? 0
++						     : (mod->fasttx_num + 1);
++
++	/* update statistics */
++	stats->tx_packets++;
++	stats->tx_bytes += cf->can_dlc;
++	kfree_skb(skb);
++
++	/*
++	 * This hardware doesn't have TX-done notifications, so we'll try and
++	 * emulate it the best we can using ECHO skbs. Get the next TX
++	 * descriptor, and see if we have room to send. If not, stop the queue.
++	 * It will be woken when the ECHO skb for the current packet is recv'd.
++	 */
++
++	/* copy the control bits of the descriptor */
++	if (!ican3_txok(mod))
++		netif_stop_queue(ndev);
++
++	spin_unlock_irqrestore(&mod->lock, flags);
++	return NETDEV_TX_OK;
++}
++
++static const struct net_device_ops ican3_netdev_ops = {
++	.ndo_open	= ican3_open,
++	.ndo_stop	= ican3_stop,
++	.ndo_start_xmit	= ican3_xmit,
++};
++
++/*
++ * Low-level CAN Device
++ */
++
++/* This structure was stolen from drivers/net/can/sja1000/sja1000.c */
++static struct can_bittiming_const ican3_bittiming_const = {
++	.name = DRV_NAME,
++	.tseg1_min = 1,
++	.tseg1_max = 16,
++	.tseg2_min = 1,
++	.tseg2_max = 8,
++	.sjw_max = 4,
++	.brp_min = 1,
++	.brp_max = 64,
++	.brp_inc = 1,
++};
++
++/*
++ * This routine was stolen from drivers/net/can/sja1000/sja1000.c
++ *
++ * The bittiming register command for the ICAN3 just sets the bit timing
++ * registers on the SJA1000 chip directly
++ */
++static int ican3_set_bittiming(struct net_device *ndev)
++{
++	struct ican3_dev *mod = netdev_priv(ndev);
++	struct can_bittiming *bt = &mod->can.bittiming;
++	struct ican3_msg msg;
++	u8 btr0, btr1;
++
++	btr0 = ((bt->brp - 1) & 0x3f) | (((bt->sjw - 1) & 0x3) << 6);
++	btr1 = ((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) |
++		(((bt->phase_seg2 - 1) & 0x7) << 4);
++	if (mod->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
++		btr1 |= 0x80;
++
++	memset(&msg, 0, sizeof(msg));
++	msg.spec = MSG_CBTRREQ;
++	msg.len = cpu_to_le16(4);
++	msg.data[0] = 0x00;
++	msg.data[1] = 0x00;
++	msg.data[2] = btr0;
++	msg.data[3] = btr1;
++
++	return ican3_send_msg(mod, &msg);
++}
++
++static int ican3_set_mode(struct net_device *ndev, enum can_mode mode)
++{
++	struct ican3_dev *mod = netdev_priv(ndev);
++	int ret;
++
++	if (mode != CAN_MODE_START)
++		return -ENOTSUPP;
++
++	/* bring the bus online */
++	ret = ican3_set_bus_state(mod, true);
++	if (ret) {
++		dev_err(mod->dev, "unable to set bus-on\n");
++		return ret;
++	}
++
++	/* start up the network device */
++	mod->can.state = CAN_STATE_ERROR_ACTIVE;
++
++	if (netif_queue_stopped(ndev))
++		netif_wake_queue(ndev);
++
++	return 0;
++}
++
++static int ican3_get_berr_counter(const struct net_device *ndev,
++				  struct can_berr_counter *bec)
++{
++	struct ican3_dev *mod = netdev_priv(ndev);
++	int ret;
++
++	ret = ican3_send_inquiry(mod, INQUIRY_STATUS);
++	if (ret)
++		return ret;
++
++	ret = wait_for_completion_timeout(&mod->buserror_comp, HZ);
++	if (ret <= 0) {
++		dev_info(mod->dev, "%s timed out\n", __func__);
++		return -ETIMEDOUT;
++	}
++
++	bec->rxerr = mod->bec.rxerr;
++	bec->txerr = mod->bec.txerr;
++	return 0;
++}
++
++/*
++ * Sysfs Attributes
++ */
++
++static ssize_t ican3_sysfs_show_term(struct device *dev,
++				     struct device_attribute *attr,
++				     char *buf)
++{
++	struct ican3_dev *mod = netdev_priv(to_net_dev(dev));
++	int ret;
++
++	ret = ican3_send_inquiry(mod, INQUIRY_TERMINATION);
++	if (ret)
++		return ret;
++
++	ret = wait_for_completion_timeout(&mod->termination_comp, HZ);
++	if (ret <= 0) {
++		dev_info(mod->dev, "%s timed out\n", __func__);
++		return -ETIMEDOUT;
++	}
++
++	return snprintf(buf, PAGE_SIZE, "%u\n", mod->termination_enabled);
++}
++
++static ssize_t ican3_sysfs_set_term(struct device *dev,
++				    struct device_attribute *attr,
++				    const char *buf, size_t count)
++{
++	struct ican3_dev *mod = netdev_priv(to_net_dev(dev));
++	unsigned long enable;
++	int ret;
++
++	if (strict_strtoul(buf, 0, &enable))
++		return -EINVAL;
++
++	ret = ican3_set_termination(mod, enable);
++	if (ret)
++		return ret;
++
++	return count;
++}
++
++static DEVICE_ATTR(termination, S_IWUGO | S_IRUGO, ican3_sysfs_show_term,
++						   ican3_sysfs_set_term);
++
++static struct attribute *ican3_sysfs_attrs[] = {
++	&dev_attr_termination.attr,
++	NULL,
++};
++
++static struct attribute_group ican3_sysfs_attr_group = {
++	.attrs = ican3_sysfs_attrs,
++};
++
++/*
++ * PCI Subsystem
++ */
++
++static int __devinit ican3_probe(struct platform_device *pdev)
++{
++	struct janz_platform_data *pdata;
++	struct net_device *ndev;
++	struct ican3_dev *mod;
++	struct resource *res;
++	struct device *dev;
++	int ret;
++
++	pdata = pdev->dev.platform_data;
++	if (!pdata)
++		return -ENXIO;
++
++	dev_dbg(&pdev->dev, "probe: module number %d\n", pdata->modno);
++
++	/* save the struct device for printing */
++	dev = &pdev->dev;
++
++	/* allocate the CAN device and private data */
++	ndev = alloc_candev(sizeof(*mod), 0);
++	if (!ndev) {
++		dev_err(dev, "unable to allocate CANdev\n");
++		ret = -ENOMEM;
++		goto out_return;
++	}
++
++	platform_set_drvdata(pdev, ndev);
++	mod = netdev_priv(ndev);
++	mod->ndev = ndev;
++	mod->dev = &pdev->dev;
++	mod->num = pdata->modno;
++	netif_napi_add(ndev, &mod->napi, ican3_napi, ICAN3_RX_BUFFERS);
++	spin_lock_init(&mod->lock);
++	init_completion(&mod->termination_comp);
++	init_completion(&mod->buserror_comp);
++
++	/* setup device-specific sysfs attributes */
++	ndev->sysfs_groups[0] = &ican3_sysfs_attr_group;
++
++	/* the first unallocated page in the DPM is 9 */
++	mod->free_page = DPM_FREE_START;
++
++	ndev->netdev_ops = &ican3_netdev_ops;
++	ndev->flags |= IFF_ECHO;
++	SET_NETDEV_DEV(ndev, &pdev->dev);
++
++	mod->can.clock.freq = ICAN3_CAN_CLOCK;
++	mod->can.bittiming_const = &ican3_bittiming_const;
++	mod->can.do_set_bittiming = ican3_set_bittiming;
++	mod->can.do_set_mode = ican3_set_mode;
++	mod->can.do_get_berr_counter = ican3_get_berr_counter;
++	mod->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES
++				    | CAN_CTRLMODE_BERR_REPORTING;
++
++	/* find our IRQ number */
++	mod->irq = platform_get_irq(pdev, 0);
++	if (mod->irq < 0) {
++		dev_err(dev, "IRQ line not found\n");
++		ret = -ENODEV;
++		goto out_free_ndev;
++	}
++
++	ndev->irq = mod->irq;
++
++	/* get access to the MODULbus registers for this module */
++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	if (!res) {
++		dev_err(dev, "MODULbus registers not found\n");
++		ret = -ENODEV;
++		goto out_free_ndev;
++	}
++
++	mod->dpm = ioremap(res->start, resource_size(res));
++	if (!mod->dpm) {
++		dev_err(dev, "MODULbus registers not ioremap\n");
++		ret = -ENOMEM;
++		goto out_free_ndev;
++	}
++
++	mod->dpmctrl = mod->dpm + DPM_PAGE_SIZE;
++
++	/* get access to the control registers for this module */
++	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++	if (!res) {
++		dev_err(dev, "CONTROL registers not found\n");
++		ret = -ENODEV;
++		goto out_iounmap_dpm;
++	}
++
++	mod->ctrl = ioremap(res->start, resource_size(res));
++	if (!mod->ctrl) {
++		dev_err(dev, "CONTROL registers not ioremap\n");
++		ret = -ENOMEM;
++		goto out_iounmap_dpm;
++	}
++
++	/* disable our IRQ, then hookup the IRQ handler */
++	iowrite8(1 << mod->num, &mod->ctrl->int_disable);
++	ret = request_irq(mod->irq, ican3_irq, IRQF_SHARED, DRV_NAME, mod);
++	if (ret) {
++		dev_err(dev, "unable to request IRQ\n");
++		goto out_iounmap_ctrl;
++	}
++
++	/* reset and initialize the CAN controller into fast mode */
++	napi_enable(&mod->napi);
++	ret = ican3_startup_module(mod);
++	if (ret) {
++		dev_err(dev, "%s: unable to start CANdev\n", __func__);
++		goto out_free_irq;
++	}
++
++	/* register with the Linux CAN layer */
++	ret = register_candev(ndev);
++	if (ret) {
++		dev_err(dev, "%s: unable to register CANdev\n", __func__);
++		goto out_free_irq;
++	}
++
++	dev_info(dev, "module %d: registered CAN device\n", pdata->modno);
++	return 0;
++
++out_free_irq:
++	napi_disable(&mod->napi);
++	iowrite8(1 << mod->num, &mod->ctrl->int_disable);
++	free_irq(mod->irq, mod);
++out_iounmap_ctrl:
++	iounmap(mod->ctrl);
++out_iounmap_dpm:
++	iounmap(mod->dpm);
++out_free_ndev:
++	free_candev(ndev);
++out_return:
++	return ret;
++}
++
++static int __devexit ican3_remove(struct platform_device *pdev)
++{
++	struct net_device *ndev = platform_get_drvdata(pdev);
++	struct ican3_dev *mod = netdev_priv(ndev);
++
++	/* unregister the netdevice, stop interrupts */
++	unregister_netdev(ndev);
++	napi_disable(&mod->napi);
++	iowrite8(1 << mod->num, &mod->ctrl->int_disable);
++	free_irq(mod->irq, mod);
++
++	/* put the module into reset */
++	ican3_shutdown_module(mod);
++
++	/* unmap all registers */
++	iounmap(mod->ctrl);
++	iounmap(mod->dpm);
++
++	free_candev(ndev);
++
++	return 0;
++}
++
++static struct platform_driver ican3_driver = {
++	.driver		= {
++		.name	= DRV_NAME,
++		.owner	= THIS_MODULE,
++	},
++	.probe		= ican3_probe,
++	.remove		= __devexit_p(ican3_remove),
++};
++
++static int __init ican3_init(void)
++{
++	return platform_driver_register(&ican3_driver);
++}
++
++static void __exit ican3_exit(void)
++{
++	platform_driver_unregister(&ican3_driver);
++}
++
++MODULE_AUTHOR("Ira W. Snyder ");
++MODULE_DESCRIPTION("Janz MODULbus VMOD-ICAN3 Driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:janz-ican3");
++
++module_init(ican3_init);
++module_exit(ican3_exit);

commit bd3581323cc02aefc79a21780a4ca8c578642892
+Author: Ira W. Snyder 
+Date:   Wed Apr 7 09:43:00 2010 +0200
+
+    mfd: Janz CMOD-IO PCI MODULbus Carrier Board support
+    
+    The Janz CMOD-IO PCI MODULbus carrier board is a PCI to MODULbus bridge,
+    which may host many different types of MODULbus daughterboards, including
+    CAN and GPIO controllers.
+    
+    Signed-off-by: Ira W. Snyder 
+    Reviewed-by: Wolfgang Grandegger 
+    Signed-off-by: Samuel Ortiz 
+
+diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
+index 93d0e31c0438..05c137d16b04 100644
+--- a/drivers/mfd/Kconfig
++++ b/drivers/mfd/Kconfig
+@@ -418,6 +418,16 @@ config MFD_RDC321X
+ 	  southbridge which provides access to GPIOs and Watchdog using the
+ 	  southbridge PCI device configuration space.
+ 
++config MFD_JANZ_CMODIO
++	tristate "Support for Janz CMOD-IO PCI MODULbus Carrier Board"
++	select MFD_CORE
++	depends on PCI
++	help
++	  This is the core driver for the Janz CMOD-IO PCI MODULbus
++	  carrier board. This device is a PCI to MODULbus bridge which may
++	  host many different types of MODULbus daughterboards, including
++	  CAN and GPIO controllers.
++
+ endmenu
+ 
+ menu "Multimedia Capabilities Port drivers"
+diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
+index f177e064b31b..21eff85b288a 100644
+--- a/drivers/mfd/Makefile
++++ b/drivers/mfd/Makefile
+@@ -65,3 +65,4 @@ obj-$(CONFIG_MFD_TIMBERDALE)    += timberdale.o
+ obj-$(CONFIG_PMIC_ADP5520)	+= adp5520.o
+ obj-$(CONFIG_LPC_SCH)		+= lpc_sch.o
+ obj-$(CONFIG_MFD_RDC321X)	+= rdc321x-southbridge.o
++obj-$(CONFIG_MFD_JANZ_CMODIO)	+= janz-cmodio.o
+diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c
+new file mode 100644
+index 000000000000..9ed630799acc
+--- /dev/null
++++ b/drivers/mfd/janz-cmodio.c
+@@ -0,0 +1,304 @@
++/*
++ * Janz CMOD-IO MODULbus Carrier Board PCI Driver
++ *
++ * Copyright (c) 2010 Ira W. Snyder 
++ *
++ * Lots of inspiration and code was copied from drivers/mfd/sm501.c
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++
++#define DRV_NAME "janz-cmodio"
++
++/* Size of each MODULbus module in PCI BAR4 */
++#define CMODIO_MODULBUS_SIZE	0x200
++
++/* Maximum number of MODULbus modules on a CMOD-IO carrier board */
++#define CMODIO_MAX_MODULES	4
++
++/* Module Parameters */
++static unsigned int num_modules = CMODIO_MAX_MODULES;
++static unsigned char *modules[CMODIO_MAX_MODULES] = {
++	"empty", "empty", "empty", "empty",
++};
++
++module_param_array(modules, charp, &num_modules, S_IRUGO);
++MODULE_PARM_DESC(modules, "MODULbus modules attached to the carrier board");
++
++/* Unique Device Id */
++static unsigned int cmodio_id;
++
++struct cmodio_device {
++	/* Parent PCI device */
++	struct pci_dev *pdev;
++
++	/* PLX control registers */
++	struct janz_cmodio_onboard_regs __iomem *ctrl;
++
++	/* hex switch position */
++	u8 hex;
++
++	/* mfd-core API */
++	struct mfd_cell cells[CMODIO_MAX_MODULES];
++	struct resource resources[3 * CMODIO_MAX_MODULES];
++	struct janz_platform_data pdata[CMODIO_MAX_MODULES];
++};
++
++/*
++ * Subdevices using the mfd-core API
++ */
++
++static int __devinit cmodio_setup_subdevice(struct cmodio_device *priv,
++					    char *name, unsigned int devno,
++					    unsigned int modno)
++{
++	struct janz_platform_data *pdata;
++	struct mfd_cell *cell;
++	struct resource *res;
++	struct pci_dev *pci;
++
++	pci = priv->pdev;
++	cell = &priv->cells[devno];
++	res = &priv->resources[devno * 3];
++	pdata = &priv->pdata[devno];
++
++	cell->name = name;
++	cell->resources = res;
++	cell->num_resources = 3;
++
++	/* Setup the subdevice ID -- must be unique */
++	cell->id = cmodio_id++;
++
++	/* Add platform data */
++	pdata->modno = modno;
++	cell->platform_data = pdata;
++	cell->data_size = sizeof(*pdata);
++
++	/* MODULbus registers -- PCI BAR3 is big-endian MODULbus access */
++	res->flags = IORESOURCE_MEM;
++	res->parent = &pci->resource[3];
++	res->start = pci->resource[3].start + (CMODIO_MODULBUS_SIZE * modno);
++	res->end = res->start + CMODIO_MODULBUS_SIZE - 1;
++	res++;
++
++	/* PLX Control Registers -- PCI BAR4 is interrupt and other registers */
++	res->flags = IORESOURCE_MEM;
++	res->parent = &pci->resource[4];
++	res->start = pci->resource[4].start;
++	res->end = pci->resource[4].end;
++	res++;
++
++	/*
++	 * IRQ
++	 *
++	 * The start and end fields are used as an offset to the irq_base
++	 * parameter passed into the mfd_add_devices() function call. All
++	 * devices share the same IRQ.
++	 */
++	res->flags = IORESOURCE_IRQ;
++	res->parent = NULL;
++	res->start = 0;
++	res->end = 0;
++	res++;
++
++	return 0;
++}
++
++/* Probe each submodule using kernel parameters */
++static int __devinit cmodio_probe_submodules(struct cmodio_device *priv)
++{
++	struct pci_dev *pdev = priv->pdev;
++	unsigned int num_probed = 0;
++	char *name;
++	int i;
++
++	for (i = 0; i < num_modules; i++) {
++		name = modules[i];
++		if (!strcmp(name, "") || !strcmp(name, "empty"))
++			continue;
++
++		dev_dbg(&priv->pdev->dev, "MODULbus %d: name %s\n", i, name);
++		cmodio_setup_subdevice(priv, name, num_probed, i);
++		num_probed++;
++	}
++
++	/* print an error message if no modules were probed */
++	if (num_probed == 0) {
++		dev_err(&priv->pdev->dev, "no MODULbus modules specified, "
++					  "please set the ``modules'' kernel "
++					  "parameter according to your "
++					  "hardware configuration\n");
++		return -ENODEV;
++	}
++
++	return mfd_add_devices(&pdev->dev, 0, priv->cells,
++			       num_probed, NULL, pdev->irq);
++}
++
++/*
++ * SYSFS Attributes
++ */
++
++static ssize_t mbus_show(struct device *dev, struct device_attribute *attr,
++			 char *buf)
++{
++	struct cmodio_device *priv = dev_get_drvdata(dev);
++
++	return snprintf(buf, PAGE_SIZE, "%x\n", priv->hex);
++}
++
++static DEVICE_ATTR(modulbus_number, S_IRUGO, mbus_show, NULL);
++
++static struct attribute *cmodio_sysfs_attrs[] = {
++	&dev_attr_modulbus_number.attr,
++	NULL,
++};
++
++static const struct attribute_group cmodio_sysfs_attr_group = {
++	.attrs = cmodio_sysfs_attrs,
++};
++
++/*
++ * PCI Driver
++ */
++
++static int __devinit cmodio_pci_probe(struct pci_dev *dev,
++				      const struct pci_device_id *id)
++{
++	struct cmodio_device *priv;
++	int ret;
++
++	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
++	if (!priv) {
++		dev_err(&dev->dev, "unable to allocate private data\n");
++		ret = -ENOMEM;
++		goto out_return;
++	}
++
++	pci_set_drvdata(dev, priv);
++	priv->pdev = dev;
++
++	/* Hardware Initialization */
++	ret = pci_enable_device(dev);
++	if (ret) {
++		dev_err(&dev->dev, "unable to enable device\n");
++		goto out_free_priv;
++	}
++
++	pci_set_master(dev);
++	ret = pci_request_regions(dev, DRV_NAME);
++	if (ret) {
++		dev_err(&dev->dev, "unable to request regions\n");
++		goto out_pci_disable_device;
++	}
++
++	/* Onboard configuration registers */
++	priv->ctrl = pci_ioremap_bar(dev, 4);
++	if (!priv->ctrl) {
++		dev_err(&dev->dev, "unable to remap onboard regs\n");
++		ret = -ENOMEM;
++		goto out_pci_release_regions;
++	}
++
++	/* Read the hex switch on the carrier board */
++	priv->hex = ioread8(&priv->ctrl->int_enable);
++
++	/* Add the MODULbus number (hex switch value) to the device's sysfs */
++	ret = sysfs_create_group(&dev->dev.kobj, &cmodio_sysfs_attr_group);
++	if (ret) {
++		dev_err(&dev->dev, "unable to create sysfs attributes\n");
++		goto out_unmap_ctrl;
++	}
++
++	/*
++	 * Disable all interrupt lines, each submodule will enable its
++	 * own interrupt line if needed
++	 */
++	iowrite8(0xf, &priv->ctrl->int_disable);
++
++	/* Register drivers for all submodules */
++	ret = cmodio_probe_submodules(priv);
++	if (ret) {
++		dev_err(&dev->dev, "unable to probe submodules\n");
++		goto out_sysfs_remove_group;
++	}
++
++	return 0;
++
++out_sysfs_remove_group:
++	sysfs_remove_group(&dev->dev.kobj, &cmodio_sysfs_attr_group);
++out_unmap_ctrl:
++	iounmap(priv->ctrl);
++out_pci_release_regions:
++	pci_release_regions(dev);
++out_pci_disable_device:
++	pci_disable_device(dev);
++out_free_priv:
++	kfree(priv);
++out_return:
++	return ret;
++}
++
++static void __devexit cmodio_pci_remove(struct pci_dev *dev)
++{
++	struct cmodio_device *priv = pci_get_drvdata(dev);
++
++	mfd_remove_devices(&dev->dev);
++	sysfs_remove_group(&dev->dev.kobj, &cmodio_sysfs_attr_group);
++	iounmap(priv->ctrl);
++	pci_release_regions(dev);
++	pci_disable_device(dev);
++	kfree(priv);
++}
++
++#define PCI_VENDOR_ID_JANZ		0x13c3
++
++/* The list of devices that this module will support */
++static DEFINE_PCI_DEVICE_TABLE(cmodio_pci_ids) = {
++	{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_JANZ, 0x0101 },
++	{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_JANZ, 0x0100 },
++	{ 0, }
++};
++MODULE_DEVICE_TABLE(pci, cmodio_pci_ids);
++
++static struct pci_driver cmodio_pci_driver = {
++	.name     = DRV_NAME,
++	.id_table = cmodio_pci_ids,
++	.probe    = cmodio_pci_probe,
++	.remove   = __devexit_p(cmodio_pci_remove),
++};
++
++/*
++ * Module Init / Exit
++ */
++
++static int __init cmodio_init(void)
++{
++	return pci_register_driver(&cmodio_pci_driver);
++}
++
++static void __exit cmodio_exit(void)
++{
++	pci_unregister_driver(&cmodio_pci_driver);
++}
++
++MODULE_AUTHOR("Ira W. Snyder ");
++MODULE_DESCRIPTION("Janz CMOD-IO PCI MODULbus Carrier Board Driver");
++MODULE_LICENSE("GPL");
++
++module_init(cmodio_init);
++module_exit(cmodio_exit);
+diff --git a/include/linux/mfd/janz.h b/include/linux/mfd/janz.h
+new file mode 100644
+index 000000000000..e9994c469803
+--- /dev/null
++++ b/include/linux/mfd/janz.h
+@@ -0,0 +1,54 @@
++/*
++ * Common Definitions for Janz MODULbus devices
++ *
++ * Copyright (c) 2010 Ira W. Snyder 
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#ifndef JANZ_H
++#define JANZ_H
++
++struct janz_platform_data {
++	/* MODULbus Module Number */
++	unsigned int modno;
++};
++
++/* PLX bridge chip onboard registers */
++struct janz_cmodio_onboard_regs {
++	u8 unused1;
++
++	/*
++	 * Read access: interrupt status
++	 * Write access: interrupt disable
++	 */
++	u8 int_disable;
++	u8 unused2;
++
++	/*
++	 * Read access: MODULbus number (hex switch)
++	 * Write access: interrupt enable
++	 */
++	u8 int_enable;
++	u8 unused3;
++
++	/* write-only */
++	u8 reset_assert;
++	u8 unused4;
++
++	/* write-only */
++	u8 reset_deassert;
++	u8 unused5;
++
++	/* read-write access to serial EEPROM */
++	u8 eep;
++	u8 unused6;
++
++	/* write-only access to EEPROM chip select */
++	u8 enid;
++};
++
++#endif /* JANZ_H */

commit df16dd53c575d0cb9dbee20a3149927c862a9ff6
+Author: Ira W. Snyder 
+Date:   Thu May 27 19:59:02 2010 +0200
+
+    hwmon: (ltc4245) Read only one GPIO pin
+    
+    Read only one of the GPIO pins as an analog voltage. The ADC can be
+    switched to a different GPIO pin at runtime, but this is not supported.
+    
+    Previously, this driver would report the analog voltage of the currently
+    selected GPIO pin as all three GPIO voltages: in9_input, in10_input and
+    in11_input.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Jean Delvare 
+    Cc: stable@kernel.org
+
+diff --git a/Documentation/hwmon/ltc4245 b/Documentation/hwmon/ltc4245
+index 02838a47d862..86b5880d8502 100644
+--- a/Documentation/hwmon/ltc4245
++++ b/Documentation/hwmon/ltc4245
+@@ -72,9 +72,7 @@ in6_min_alarm		5v  output undervoltage alarm
+ in7_min_alarm		3v  output undervoltage alarm
+ in8_min_alarm		Vee (-12v) output undervoltage alarm
+ 
+-in9_input		GPIO #1 voltage data
+-in10_input		GPIO #2 voltage data
+-in11_input		GPIO #3 voltage data
++in9_input		GPIO voltage data
+ 
+ power1_input		12v power usage (mW)
+ power2_input		5v  power usage (mW)
+diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c
+index 65c232a9d0c5..21d201befc2c 100644
+--- a/drivers/hwmon/ltc4245.c
++++ b/drivers/hwmon/ltc4245.c
+@@ -45,9 +45,7 @@ enum ltc4245_cmd {
+ 	LTC4245_VEEIN			= 0x19,
+ 	LTC4245_VEESENSE		= 0x1a,
+ 	LTC4245_VEEOUT			= 0x1b,
+-	LTC4245_GPIOADC1		= 0x1c,
+-	LTC4245_GPIOADC2		= 0x1d,
+-	LTC4245_GPIOADC3		= 0x1e,
++	LTC4245_GPIOADC			= 0x1c,
+ };
+ 
+ struct ltc4245_data {
+@@ -61,7 +59,7 @@ struct ltc4245_data {
+ 	u8 cregs[0x08];
+ 
+ 	/* Voltage registers */
+-	u8 vregs[0x0f];
++	u8 vregs[0x0d];
+ };
+ 
+ static struct ltc4245_data *ltc4245_update_device(struct device *dev)
+@@ -86,7 +84,7 @@ static struct ltc4245_data *ltc4245_update_device(struct device *dev)
+ 				data->cregs[i] = val;
+ 		}
+ 
+-		/* Read voltage registers -- 0x10 to 0x1f */
++		/* Read voltage registers -- 0x10 to 0x1c */
+ 		for (i = 0; i < ARRAY_SIZE(data->vregs); i++) {
+ 			val = i2c_smbus_read_byte_data(client, i+0x10);
+ 			if (unlikely(val < 0))
+@@ -128,9 +126,7 @@ static int ltc4245_get_voltage(struct device *dev, u8 reg)
+ 	case LTC4245_VEEOUT:
+ 		voltage = regval * -55;
+ 		break;
+-	case LTC4245_GPIOADC1:
+-	case LTC4245_GPIOADC2:
+-	case LTC4245_GPIOADC3:
++	case LTC4245_GPIOADC:
+ 		voltage = regval * 10;
+ 		break;
+ 	default:
+@@ -297,9 +293,7 @@ LTC4245_ALARM(in7_min_alarm,	(1 << 2),	LTC4245_FAULT2);
+ LTC4245_ALARM(in8_min_alarm,	(1 << 3),	LTC4245_FAULT2);
+ 
+ /* GPIO voltages */
+-LTC4245_VOLTAGE(in9_input,			LTC4245_GPIOADC1);
+-LTC4245_VOLTAGE(in10_input,			LTC4245_GPIOADC2);
+-LTC4245_VOLTAGE(in11_input,			LTC4245_GPIOADC3);
++LTC4245_VOLTAGE(in9_input,			LTC4245_GPIOADC);
+ 
+ /* Power Consumption (virtual) */
+ LTC4245_POWER(power1_input,			LTC4245_12VSENSE);
+@@ -342,8 +336,6 @@ static struct attribute *ltc4245_attributes[] = {
+ 	&sensor_dev_attr_in8_min_alarm.dev_attr.attr,
+ 
+ 	&sensor_dev_attr_in9_input.dev_attr.attr,
+-	&sensor_dev_attr_in10_input.dev_attr.attr,
+-	&sensor_dev_attr_in11_input.dev_attr.attr,
+ 
+ 	&sensor_dev_attr_power1_input.dev_attr.attr,
+ 	&sensor_dev_attr_power2_input.dev_attr.attr,

commit d2b847d489ee4e9921bc61f47c3d0e992692fc0f
+Author: Ira W. Snyder 
+Date:   Thu May 27 19:58:45 2010 +0200
+
+    hwmon: Add description of the update_rate sysfs attribute
+    
+    The update_rate attribute can be used by drivers to let userspace choose
+    the update rate of the chip, if it is configurable.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Jean Delvare 
+
+diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface
+index 3de6b0bcb147..d4e2917c6f18 100644
+--- a/Documentation/hwmon/sysfs-interface
++++ b/Documentation/hwmon/sysfs-interface
+@@ -80,9 +80,9 @@ All entries (except name) are optional, and should only be created in a
+ given driver if the chip has the feature.
+ 
+ 
+-********
+-* Name *
+-********
++*********************
++* Global attributes *
++*********************
+ 
+ name		The chip name.
+ 		This should be a short, lowercase string, not containing
+@@ -91,6 +91,13 @@ name		The chip name.
+ 		I2C devices get this attribute created automatically.
+ 		RO
+ 
++update_rate	The rate at which the chip will update readings.
++		Unit: millisecond
++		RW
++		Some devices have a variable update rate. This attribute
++		can be used to change the update rate to the desired
++		frequency.
++
+ 
+ ************
+ * Voltages *

commit 8c3c7a256f7ab142dfbcee2d8633dbce5a36fde7
+Author: Ira W. Snyder 
+Date:   Thu May 27 19:58:44 2010 +0200
+
+    hwmon: (lm90) Use programmed update rate
+    
+    The lm90 driver programs the sensor chip to update its readings at 2 Hz
+    (500 ms between readings). However, the driver only does reads from the
+    chip at intervals of 2 * HZ (2000 ms between readings). Change the driver
+    update rate to the programmed update rate.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Jean Delvare 
+
+diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
+index 7cc2708871ab..760ef72eea56 100644
+--- a/drivers/hwmon/lm90.c
++++ b/drivers/hwmon/lm90.c
+@@ -982,7 +982,8 @@ static struct lm90_data *lm90_update_device(struct device *dev)
+ 
+ 	mutex_lock(&data->update_lock);
+ 
+-	if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
++	if (time_after(jiffies, data->last_updated + HZ / 2 + HZ / 10)
++	 || !data->valid) {
+ 		u8 h, l;
+ 
+ 		dev_dbg(&client->dev, "Updating lm90 data.\n");

commit 3f6ea84a3035cc0ef7488f8e93bc76766799e082
+Author: Ira W. Snyder 
+Date:   Thu Apr 1 11:43:30 2010 -0700
+
+    PCI: read memory ranges out of Broadcom CNB20LE host bridge
+    
+    Read the memory ranges behind the Broadcom CNB20LE host bridge out of the
+    hardware. This allows PCI hotplugging to work, since we know which memory
+    range to allocate PCI BAR's from.
+    
+    The x86 PCI code automatically prefers the ACPI _CRS information when it is
+    available. In that case, this information is not used.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Jesse Barnes 
+
+diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
+index 9458685902bd..677b87d60a36 100644
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -1931,6 +1931,14 @@ config PCI_MMCONFIG
+ 	bool "Support mmconfig PCI config space access"
+ 	depends on X86_64 && PCI && ACPI
+ 
++config PCI_CNB20LE_QUIRK
++	bool "Read CNB20LE Host Bridge Windows"
++	depends on PCI
++	help
++	  Read the PCI windows out of the CNB20LE host bridge. This allows
++	  PCI hotplug to work on systems with the CNB20LE chipset which do
++	  not have ACPI.
++
+ config DMAR
+ 	bool "Support for DMA Remapping Devices (EXPERIMENTAL)"
+ 	depends on PCI_MSI && ACPI && EXPERIMENTAL
+diff --git a/arch/x86/pci/Makefile b/arch/x86/pci/Makefile
+index b110d97fb925..a0207a7fdf39 100644
+--- a/arch/x86/pci/Makefile
++++ b/arch/x86/pci/Makefile
+@@ -18,6 +18,8 @@ obj-$(CONFIG_X86_MRST)		+= mrst.o
+ obj-y				+= common.o early.o
+ obj-y				+= amd_bus.o bus_numa.o
+ 
++obj-$(CONFIG_PCI_CNB20LE_QUIRK)	+= broadcom_bus.o
++
+ ifeq ($(CONFIG_PCI_DEBUG),y)
+ EXTRA_CFLAGS += -DDEBUG
+ endif
+diff --git a/arch/x86/pci/broadcom_bus.c b/arch/x86/pci/broadcom_bus.c
+new file mode 100644
+index 000000000000..0846a5bbbfbd
+--- /dev/null
++++ b/arch/x86/pci/broadcom_bus.c
+@@ -0,0 +1,101 @@
++/*
++ * Read address ranges from a Broadcom CNB20LE Host Bridge
++ *
++ * Copyright (c) 2010 Ira W. Snyder 
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include "bus_numa.h"
++
++static void __devinit cnb20le_res(struct pci_dev *dev)
++{
++	struct pci_root_info *info;
++	struct resource res;
++	u16 word1, word2;
++	u8 fbus, lbus;
++	int i;
++
++	/*
++	 * The x86_pci_root_bus_res_quirks() function already refuses to use
++	 * this information if ACPI _CRS was used. Therefore, we don't bother
++	 * checking if ACPI is enabled, and just generate the information
++	 * for both the ACPI _CRS and no ACPI cases.
++	 */
++
++	info = &pci_root_info[pci_root_num];
++	pci_root_num++;
++
++	/* read the PCI bus numbers */
++	pci_read_config_byte(dev, 0x44, &fbus);
++	pci_read_config_byte(dev, 0x45, &lbus);
++	info->bus_min = fbus;
++	info->bus_max = lbus;
++
++	/*
++	 * Add the legacy IDE ports on bus 0
++	 *
++	 * These do not exist anywhere in the bridge registers, AFAICT. I do
++	 * not have the datasheet, so this is the best I can do.
++	 */
++	if (fbus == 0) {
++		update_res(info, 0x01f0, 0x01f7, IORESOURCE_IO, 0);
++		update_res(info, 0x03f6, 0x03f6, IORESOURCE_IO, 0);
++		update_res(info, 0x0170, 0x0177, IORESOURCE_IO, 0);
++		update_res(info, 0x0376, 0x0376, IORESOURCE_IO, 0);
++		update_res(info, 0xffa0, 0xffaf, IORESOURCE_IO, 0);
++	}
++
++	/* read the non-prefetchable memory window */
++	pci_read_config_word(dev, 0xc0, &word1);
++	pci_read_config_word(dev, 0xc2, &word2);
++	if (word1 != word2) {
++		res.start = (word1 << 16) | 0x0000;
++		res.end   = (word2 << 16) | 0xffff;
++		res.flags = IORESOURCE_MEM;
++		update_res(info, res.start, res.end, res.flags, 0);
++	}
++
++	/* read the prefetchable memory window */
++	pci_read_config_word(dev, 0xc4, &word1);
++	pci_read_config_word(dev, 0xc6, &word2);
++	if (word1 != word2) {
++		res.start = (word1 << 16) | 0x0000;
++		res.end   = (word2 << 16) | 0xffff;
++		res.flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
++		update_res(info, res.start, res.end, res.flags, 0);
++	}
++
++	/* read the IO port window */
++	pci_read_config_word(dev, 0xd0, &word1);
++	pci_read_config_word(dev, 0xd2, &word2);
++	if (word1 != word2) {
++		res.start = word1;
++		res.end   = word2;
++		res.flags = IORESOURCE_IO;
++		update_res(info, res.start, res.end, res.flags, 0);
++	}
++
++	/* print information about this host bridge */
++	res.start = fbus;
++	res.end   = lbus;
++	res.flags = IORESOURCE_BUS;
++	dev_info(&dev->dev, "CNB20LE PCI Host Bridge (domain %04x %pR)\n",
++			    pci_domain_nr(dev->bus), &res);
++
++	for (i = 0; i < info->res_num; i++)
++		dev_info(&dev->dev, "host bridge window %pR\n", &info->res[i]);
++}
++
++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_LE,
++			cnb20le_res);
++

commit ac6ec5b1de5d1d5afcbe88d73c05df71dca0ac39
+Author: Ira W. Snyder 
+Date:   Mon Dec 21 16:26:45 2009 -0800
+
+    serial: 8250_pci: add support for MCS9865 / SYBA 6x Serial Port Card
+    
+    This patch is heavily based on an earlier patch found on the linux-serial
+    mailing list [1], written by Darius Augulis.
+    
+    The previous incarnation of this patch only supported a 2x serial port
+    card.  I have added support for my SYBA 6x serial port card, and tested on
+    x86.
+    
+    [1]: http://marc.info/?l=linux-serial&m=124975806304760
+    
+    Signed-off-by: Ira W. Snyder 
+    Cc: Darius Augulis 
+    Cc: Greg KH 
+    Cc: Alan Cox 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
+index ad113b0f62db..0950fa40684f 100644
+--- a/drivers/parport/parport_pc.c
++++ b/drivers/parport/parport_pc.c
+@@ -2908,6 +2908,7 @@ enum parport_pc_pci_cards {
+ 	netmos_9805,
+ 	netmos_9815,
+ 	netmos_9901,
++	netmos_9865,
+ 	quatech_sppxp100,
+ };
+ 
+@@ -2989,6 +2990,7 @@ static struct parport_pc_pci {
+ 	/* netmos_9805 */               { 1, { { 0, -1 }, } },
+ 	/* netmos_9815 */               { 2, { { 0, -1 }, { 2, -1 }, } },
+ 	/* netmos_9901 */               { 1, { { 0, -1 }, } },
++	/* netmos_9865 */               { 1, { { 0, -1 }, } },
+ 	/* quatech_sppxp100 */		{ 1, { { 0, 1 }, } },
+ };
+ 
+@@ -3092,6 +3094,10 @@ static const struct pci_device_id parport_pc_pci_tbl[] = {
+ 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 },
+ 	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901,
+ 	  0xA000, 0x2000, 0, 0, netmos_9901 },
++	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
++	  0xA000, 0x1000, 0, 0, netmos_9865 },
++	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
++	  0xA000, 0x2000, 0, 0, netmos_9865 },
+ 	/* Quatech SPPXP-100 Parallel port PCI ExpressCard */
+ 	{ PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_SPPXP_100,
+ 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, quatech_sppxp100 },
+diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
+index b28af13c45a1..8b18c3ce3898 100644
+--- a/drivers/serial/8250_pci.c
++++ b/drivers/serial/8250_pci.c
+@@ -760,7 +760,8 @@ static int pci_netmos_init(struct pci_dev *dev)
+ 	/* subdevice 0x00PS means 

parallel, serial */ + unsigned int num_serial = dev->subsystem_device & 0xf; + +- if (dev->device == PCI_DEVICE_ID_NETMOS_9901) ++ if ((dev->device == PCI_DEVICE_ID_NETMOS_9901) || ++ (dev->device == PCI_DEVICE_ID_NETMOS_9865)) + return 0; + if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM && + dev->subsystem_device == 0x0299) +@@ -1479,6 +1480,7 @@ enum pci_board_num_t { + + pbn_b0_bt_1_115200, + pbn_b0_bt_2_115200, ++ pbn_b0_bt_4_115200, + pbn_b0_bt_8_115200, + + pbn_b0_bt_1_460800, +@@ -1703,6 +1705,12 @@ static struct pciserial_board pci_boards[] __devinitdata = { + .base_baud = 115200, + .uart_offset = 8, + }, ++ [pbn_b0_bt_4_115200] = { ++ .flags = FL_BASE0|FL_BASE_BARS, ++ .num_ports = 4, ++ .base_baud = 115200, ++ .uart_offset = 8, ++ }, + [pbn_b0_bt_8_115200] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 8, +@@ -3648,6 +3656,18 @@ static struct pci_device_id serial_pci_tbl[] = { + 0xA000, 0x1000, + 0, 0, pbn_b0_1_115200 }, + ++ /* ++ * Best Connectivity PCI Multi I/O cards ++ */ ++ ++ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865, ++ 0xA000, 0x1000, ++ 0, 0, pbn_b0_1_115200 }, ++ ++ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865, ++ 0xA000, 0x3004, ++ 0, 0, pbn_b0_bt_4_115200 }, ++ + /* + * These entries match devices with class COMMUNICATION_SERIAL, + * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL +diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h +index 0be824320580..3ec4003f5e64 100644 +--- a/include/linux/pci_ids.h ++++ b/include/linux/pci_ids.h +@@ -2697,6 +2697,7 @@ + #define PCI_DEVICE_ID_NETMOS_9835 0x9835 + #define PCI_DEVICE_ID_NETMOS_9845 0x9845 + #define PCI_DEVICE_ID_NETMOS_9855 0x9855 ++#define PCI_DEVICE_ID_NETMOS_9865 0x9865 + #define PCI_DEVICE_ID_NETMOS_9901 0x9901 + + #define PCI_VENDOR_ID_3COM_2 0xa727


commit 9c3a50b7d7ec45da34e73cac66cde12dd6092dd8
+Author: Ira Snyder 
+Date:   Wed Jan 6 13:34:06 2010 +0000
+
+    fsldma: major cleanups and fixes
+    
+    Fix locking. Use two queues in the driver, one for pending transacions, and
+    one for transactions which are actually running on the hardware. Call
+    dma_run_dependencies() on descriptor cleanup so that the async_tx API works
+    correctly.
+    
+    There are a number of places throughout the code where lists of descriptors
+    are freed in a loop. Create functions to handle this, and use them instead
+    of open-coding the loop each time.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Dan Williams 
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index 7b5f88cb495b..19011c20390b 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -61,7 +61,6 @@ static void dma_init(struct fsldma_chan *chan)
+ 				| FSL_DMA_MR_PRC_RM, 32);
+ 		break;
+ 	}
+-
+ }
+ 
+ static void set_sr(struct fsldma_chan *chan, u32 val)
+@@ -120,11 +119,6 @@ static dma_addr_t get_cdar(struct fsldma_chan *chan)
+ 	return DMA_IN(chan, &chan->regs->cdar, 64) & ~FSL_DMA_SNEN;
+ }
+ 
+-static void set_ndar(struct fsldma_chan *chan, dma_addr_t addr)
+-{
+-	DMA_OUT(chan, &chan->regs->ndar, addr, 64);
+-}
+-
+ static dma_addr_t get_ndar(struct fsldma_chan *chan)
+ {
+ 	return DMA_IN(chan, &chan->regs->ndar, 64);
+@@ -178,11 +172,12 @@ static void dma_halt(struct fsldma_chan *chan)
+ 
+ 	for (i = 0; i < 100; i++) {
+ 		if (dma_is_idle(chan))
+-			break;
++			return;
++
+ 		udelay(10);
+ 	}
+ 
+-	if (i >= 100 && !dma_is_idle(chan))
++	if (!dma_is_idle(chan))
+ 		dev_err(chan->dev, "DMA halt timeout!\n");
+ }
+ 
+@@ -199,27 +194,6 @@ static void set_ld_eol(struct fsldma_chan *chan,
+ 			| snoop_bits, 64);
+ }
+ 
+-static void append_ld_queue(struct fsldma_chan *chan,
+-		struct fsl_desc_sw *new_desc)
+-{
+-	struct fsl_desc_sw *queue_tail = to_fsl_desc(chan->ld_queue.prev);
+-
+-	if (list_empty(&chan->ld_queue))
+-		return;
+-
+-	/* Link to the new descriptor physical address and
+-	 * Enable End-of-segment interrupt for
+-	 * the last link descriptor.
+-	 * (the previous node's next link descriptor)
+-	 *
+-	 * For FSL_DMA_IP_83xx, the snoop enable bit need be set.
+-	 */
+-	queue_tail->hw.next_ln_addr = CPU_TO_DMA(chan,
+-			new_desc->async_tx.phys | FSL_DMA_EOSIE |
+-			(((chan->feature & FSL_DMA_IP_MASK)
+-				== FSL_DMA_IP_83XX) ? FSL_DMA_SNEN : 0), 64);
+-}
+-
+ /**
+  * fsl_chan_set_src_loop_size - Set source address hold transfer size
+  * @chan : Freescale DMA channel
+@@ -343,6 +317,31 @@ static void fsl_chan_toggle_ext_start(struct fsldma_chan *chan, int enable)
+ 		chan->feature &= ~FSL_DMA_CHAN_START_EXT;
+ }
+ 
++static void append_ld_queue(struct fsldma_chan *chan,
++			    struct fsl_desc_sw *desc)
++{
++	struct fsl_desc_sw *tail = to_fsl_desc(chan->ld_pending.prev);
++
++	if (list_empty(&chan->ld_pending))
++		goto out_splice;
++
++	/*
++	 * Add the hardware descriptor to the chain of hardware descriptors
++	 * that already exists in memory.
++	 *
++	 * This will un-set the EOL bit of the existing transaction, and the
++	 * last link in this transaction will become the EOL descriptor.
++	 */
++	set_desc_next(chan, &tail->hw, desc->async_tx.phys);
++
++	/*
++	 * Add the software descriptor and all children to the list
++	 * of pending transactions
++	 */
++out_splice:
++	list_splice_tail_init(&desc->tx_list, &chan->ld_pending);
++}
++
+ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
+ {
+ 	struct fsldma_chan *chan = to_fsl_chan(tx->chan);
+@@ -351,9 +350,12 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
+ 	unsigned long flags;
+ 	dma_cookie_t cookie;
+ 
+-	/* cookie increment and adding to ld_queue must be atomic */
+ 	spin_lock_irqsave(&chan->desc_lock, flags);
+ 
++	/*
++	 * assign cookies to all of the software descriptors
++	 * that make up this transaction
++	 */
+ 	cookie = chan->common.cookie;
+ 	list_for_each_entry(child, &desc->tx_list, node) {
+ 		cookie++;
+@@ -364,8 +366,9 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
+ 	}
+ 
+ 	chan->common.cookie = cookie;
++
++	/* put this transaction onto the tail of the pending queue */
+ 	append_ld_queue(chan, desc);
+-	list_splice_init(&desc->tx_list, chan->ld_queue.prev);
+ 
+ 	spin_unlock_irqrestore(&chan->desc_lock, flags);
+ 
+@@ -381,20 +384,22 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
+ static struct fsl_desc_sw *fsl_dma_alloc_descriptor(
+ 					struct fsldma_chan *chan)
+ {
++	struct fsl_desc_sw *desc;
+ 	dma_addr_t pdesc;
+-	struct fsl_desc_sw *desc_sw;
+-
+-	desc_sw = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &pdesc);
+-	if (desc_sw) {
+-		memset(desc_sw, 0, sizeof(struct fsl_desc_sw));
+-		INIT_LIST_HEAD(&desc_sw->tx_list);
+-		dma_async_tx_descriptor_init(&desc_sw->async_tx,
+-						&chan->common);
+-		desc_sw->async_tx.tx_submit = fsl_dma_tx_submit;
+-		desc_sw->async_tx.phys = pdesc;
++
++	desc = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &pdesc);
++	if (!desc) {
++		dev_dbg(chan->dev, "out of memory for link desc\n");
++		return NULL;
+ 	}
+ 
+-	return desc_sw;
++	memset(desc, 0, sizeof(*desc));
++	INIT_LIST_HEAD(&desc->tx_list);
++	dma_async_tx_descriptor_init(&desc->async_tx, &chan->common);
++	desc->async_tx.tx_submit = fsl_dma_tx_submit;
++	desc->async_tx.phys = pdesc;
++
++	return desc;
+ }
+ 
+ 
+@@ -414,21 +419,53 @@ static int fsl_dma_alloc_chan_resources(struct dma_chan *dchan)
+ 	if (chan->desc_pool)
+ 		return 1;
+ 
+-	/* We need the descriptor to be aligned to 32bytes
++	/*
++	 * We need the descriptor to be aligned to 32bytes
+ 	 * for meeting FSL DMA specification requirement.
+ 	 */
+ 	chan->desc_pool = dma_pool_create("fsl_dma_engine_desc_pool",
+-			chan->dev, sizeof(struct fsl_desc_sw),
+-			32, 0);
++					  chan->dev,
++					  sizeof(struct fsl_desc_sw),
++					  __alignof__(struct fsl_desc_sw), 0);
+ 	if (!chan->desc_pool) {
+-		dev_err(chan->dev, "No memory for channel %d "
+-			"descriptor dma pool.\n", chan->id);
+-		return 0;
++		dev_err(chan->dev, "unable to allocate channel %d "
++				   "descriptor pool\n", chan->id);
++		return -ENOMEM;
+ 	}
+ 
++	/* there is at least one descriptor free to be allocated */
+ 	return 1;
+ }
+ 
++/**
++ * fsldma_free_desc_list - Free all descriptors in a queue
++ * @chan: Freescae DMA channel
++ * @list: the list to free
++ *
++ * LOCKING: must hold chan->desc_lock
++ */
++static void fsldma_free_desc_list(struct fsldma_chan *chan,
++				  struct list_head *list)
++{
++	struct fsl_desc_sw *desc, *_desc;
++
++	list_for_each_entry_safe(desc, _desc, list, node) {
++		list_del(&desc->node);
++		dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
++	}
++}
++
++static void fsldma_free_desc_list_reverse(struct fsldma_chan *chan,
++					  struct list_head *list)
++{
++	struct fsl_desc_sw *desc, *_desc;
++
++	list_for_each_entry_safe_reverse(desc, _desc, list, node) {
++		list_del(&desc->node);
++		dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
++	}
++}
++
+ /**
+  * fsl_dma_free_chan_resources - Free all resources of the channel.
+  * @chan : Freescale DMA channel
+@@ -436,23 +473,15 @@ static int fsl_dma_alloc_chan_resources(struct dma_chan *dchan)
+ static void fsl_dma_free_chan_resources(struct dma_chan *dchan)
+ {
+ 	struct fsldma_chan *chan = to_fsl_chan(dchan);
+-	struct fsl_desc_sw *desc, *_desc;
+ 	unsigned long flags;
+ 
+ 	dev_dbg(chan->dev, "Free all channel resources.\n");
+ 	spin_lock_irqsave(&chan->desc_lock, flags);
+-	list_for_each_entry_safe(desc, _desc, &chan->ld_queue, node) {
+-#ifdef FSL_DMA_LD_DEBUG
+-		dev_dbg(chan->dev,
+-				"LD %p will be released.\n", desc);
+-#endif
+-		list_del(&desc->node);
+-		/* free link descriptor */
+-		dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
+-	}
++	fsldma_free_desc_list(chan, &chan->ld_pending);
++	fsldma_free_desc_list(chan, &chan->ld_running);
+ 	spin_unlock_irqrestore(&chan->desc_lock, flags);
+-	dma_pool_destroy(chan->desc_pool);
+ 
++	dma_pool_destroy(chan->desc_pool);
+ 	chan->desc_pool = NULL;
+ }
+ 
+@@ -491,7 +520,6 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+ {
+ 	struct fsldma_chan *chan;
+ 	struct fsl_desc_sw *first = NULL, *prev = NULL, *new;
+-	struct list_head *list;
+ 	size_t copy;
+ 
+ 	if (!dchan)
+@@ -550,12 +578,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+ 	if (!first)
+ 		return NULL;
+ 
+-	list = &first->tx_list;
+-	list_for_each_entry_safe_reverse(new, prev, list, node) {
+-		list_del(&new->node);
+-		dma_pool_free(chan->desc_pool, new, new->async_tx.phys);
+-	}
+-
++	fsldma_free_desc_list_reverse(chan, &first->tx_list);
+ 	return NULL;
+ }
+ 
+@@ -578,7 +601,6 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
+ 	struct fsldma_chan *chan;
+ 	struct fsl_desc_sw *first = NULL, *prev = NULL, *new = NULL;
+ 	struct fsl_dma_slave *slave;
+-	struct list_head *tx_list;
+ 	size_t copy;
+ 
+ 	int i;
+@@ -748,19 +770,13 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
+ 	 *
+ 	 * We're re-using variables for the loop, oh well
+ 	 */
+-	tx_list = &first->tx_list;
+-	list_for_each_entry_safe_reverse(new, prev, tx_list, node) {
+-		list_del_init(&new->node);
+-		dma_pool_free(chan->desc_pool, new, new->async_tx.phys);
+-	}
+-
++	fsldma_free_desc_list_reverse(chan, &first->tx_list);
+ 	return NULL;
+ }
+ 
+ static void fsl_dma_device_terminate_all(struct dma_chan *dchan)
+ {
+ 	struct fsldma_chan *chan;
+-	struct fsl_desc_sw *desc, *tmp;
+ 	unsigned long flags;
+ 
+ 	if (!dchan)
+@@ -774,10 +790,8 @@ static void fsl_dma_device_terminate_all(struct dma_chan *dchan)
+ 	spin_lock_irqsave(&chan->desc_lock, flags);
+ 
+ 	/* Remove and free all of the descriptors in the LD queue */
+-	list_for_each_entry_safe(desc, tmp, &chan->ld_queue, node) {
+-		list_del(&desc->node);
+-		dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
+-	}
++	fsldma_free_desc_list(chan, &chan->ld_pending);
++	fsldma_free_desc_list(chan, &chan->ld_running);
+ 
+ 	spin_unlock_irqrestore(&chan->desc_lock, flags);
+ }
+@@ -785,31 +799,48 @@ static void fsl_dma_device_terminate_all(struct dma_chan *dchan)
+ /**
+  * fsl_dma_update_completed_cookie - Update the completed cookie.
+  * @chan : Freescale DMA channel
++ *
++ * CONTEXT: hardirq
+  */
+ static void fsl_dma_update_completed_cookie(struct fsldma_chan *chan)
+ {
+-	struct fsl_desc_sw *cur_desc, *desc;
+-	dma_addr_t ld_phy;
+-
+-	ld_phy = get_cdar(chan) & FSL_DMA_NLDA_MASK;
++	struct fsl_desc_sw *desc;
++	unsigned long flags;
++	dma_cookie_t cookie;
+ 
+-	if (ld_phy) {
+-		cur_desc = NULL;
+-		list_for_each_entry(desc, &chan->ld_queue, node)
+-			if (desc->async_tx.phys == ld_phy) {
+-				cur_desc = desc;
+-				break;
+-			}
++	spin_lock_irqsave(&chan->desc_lock, flags);
+ 
+-		if (cur_desc && cur_desc->async_tx.cookie) {
+-			if (dma_is_idle(chan))
+-				chan->completed_cookie =
+-					cur_desc->async_tx.cookie;
+-			else
+-				chan->completed_cookie =
+-					cur_desc->async_tx.cookie - 1;
+-		}
++	if (list_empty(&chan->ld_running)) {
++		dev_dbg(chan->dev, "no running descriptors\n");
++		goto out_unlock;
+ 	}
++
++	/* Get the last descriptor, update the cookie to that */
++	desc = to_fsl_desc(chan->ld_running.prev);
++	if (dma_is_idle(chan))
++		cookie = desc->async_tx.cookie;
++	else
++		cookie = desc->async_tx.cookie - 1;
++
++	chan->completed_cookie = cookie;
++
++out_unlock:
++	spin_unlock_irqrestore(&chan->desc_lock, flags);
++}
++
++/**
++ * fsldma_desc_status - Check the status of a descriptor
++ * @chan: Freescale DMA channel
++ * @desc: DMA SW descriptor
++ *
++ * This function will return the status of the given descriptor
++ */
++static enum dma_status fsldma_desc_status(struct fsldma_chan *chan,
++					  struct fsl_desc_sw *desc)
++{
++	return dma_async_is_complete(desc->async_tx.cookie,
++				     chan->completed_cookie,
++				     chan->common.cookie);
+ }
+ 
+ /**
+@@ -817,8 +848,6 @@ static void fsl_dma_update_completed_cookie(struct fsldma_chan *chan)
+  * @chan : Freescale DMA channel
+  *
+  * This function clean up the ld_queue of DMA channel.
+- * If 'in_intr' is set, the function will move the link descriptor to
+- * the recycle list. Otherwise, free it directly.
+  */
+ static void fsl_chan_ld_cleanup(struct fsldma_chan *chan)
+ {
+@@ -827,80 +856,95 @@ static void fsl_chan_ld_cleanup(struct fsldma_chan *chan)
+ 
+ 	spin_lock_irqsave(&chan->desc_lock, flags);
+ 
+-	dev_dbg(chan->dev, "chan completed_cookie = %d\n",
+-			chan->completed_cookie);
+-	list_for_each_entry_safe(desc, _desc, &chan->ld_queue, node) {
++	dev_dbg(chan->dev, "chan completed_cookie = %d\n", chan->completed_cookie);
++	list_for_each_entry_safe(desc, _desc, &chan->ld_running, node) {
+ 		dma_async_tx_callback callback;
+ 		void *callback_param;
+ 
+-		if (dma_async_is_complete(desc->async_tx.cookie,
+-			    chan->completed_cookie, chan->common.cookie)
+-				== DMA_IN_PROGRESS)
++		if (fsldma_desc_status(chan, desc) == DMA_IN_PROGRESS)
+ 			break;
+ 
+-		callback = desc->async_tx.callback;
+-		callback_param = desc->async_tx.callback_param;
+-
+-		/* Remove from ld_queue list */
++		/* Remove from the list of running transactions */
+ 		list_del(&desc->node);
+ 
+-		dev_dbg(chan->dev, "link descriptor %p will be recycle.\n",
+-				desc);
+-		dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
+-
+ 		/* Run the link descriptor callback function */
++		callback = desc->async_tx.callback;
++		callback_param = desc->async_tx.callback_param;
+ 		if (callback) {
+ 			spin_unlock_irqrestore(&chan->desc_lock, flags);
+-			dev_dbg(chan->dev, "link descriptor %p callback\n",
+-					desc);
++			dev_dbg(chan->dev, "LD %p callback\n", desc);
+ 			callback(callback_param);
+ 			spin_lock_irqsave(&chan->desc_lock, flags);
+ 		}
++
++		/* Run any dependencies, then free the descriptor */
++		dma_run_dependencies(&desc->async_tx);
++		dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
+ 	}
++
+ 	spin_unlock_irqrestore(&chan->desc_lock, flags);
+ }
+ 
+ /**
+- * fsl_chan_xfer_ld_queue - Transfer link descriptors in channel ld_queue.
++ * fsl_chan_xfer_ld_queue - transfer any pending transactions
+  * @chan : Freescale DMA channel
++ *
++ * This will make sure that any pending transactions will be run.
++ * If the DMA controller is idle, it will be started. Otherwise,
++ * the DMA controller's interrupt handler will start any pending
++ * transactions when it becomes idle.
+  */
+ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan)
+ {
+-	struct list_head *ld_node;
+-	dma_addr_t next_dst_addr;
++	struct fsl_desc_sw *desc;
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&chan->desc_lock, flags);
+ 
+-	if (!dma_is_idle(chan))
++	/*
++	 * If the list of pending descriptors is empty, then we
++	 * don't need to do any work at all
++	 */
++	if (list_empty(&chan->ld_pending)) {
++		dev_dbg(chan->dev, "no pending LDs\n");
+ 		goto out_unlock;
++	}
+ 
++	/*
++	 * The DMA controller is not idle, which means the interrupt
++	 * handler will start any queued transactions when it runs
++	 * at the end of the current transaction
++	 */
++	if (!dma_is_idle(chan)) {
++		dev_dbg(chan->dev, "DMA controller still busy\n");
++		goto out_unlock;
++	}
++
++	/*
++	 * TODO:
++	 * make sure the dma_halt() function really un-wedges the
++	 * controller as much as possible
++	 */
+ 	dma_halt(chan);
+ 
+-	/* If there are some link descriptors
+-	 * not transfered in queue. We need to start it.
++	/*
++	 * If there are some link descriptors which have not been
++	 * transferred, we need to start the controller
+ 	 */
+ 
+-	/* Find the first un-transfer desciptor */
+-	for (ld_node = chan->ld_queue.next;
+-		(ld_node != &chan->ld_queue)
+-			&& (dma_async_is_complete(
+-				to_fsl_desc(ld_node)->async_tx.cookie,
+-				chan->completed_cookie,
+-				chan->common.cookie) == DMA_SUCCESS);
+-		ld_node = ld_node->next);
+-
+-	if (ld_node != &chan->ld_queue) {
+-		/* Get the ld start address from ld_queue */
+-		next_dst_addr = to_fsl_desc(ld_node)->async_tx.phys;
+-		dev_dbg(chan->dev, "xfer LDs staring from 0x%llx\n",
+-				(unsigned long long)next_dst_addr);
+-		set_cdar(chan, next_dst_addr);
+-		dma_start(chan);
+-	} else {
+-		set_cdar(chan, 0);
+-		set_ndar(chan, 0);
+-	}
++	/*
++	 * Move all elements from the queue of pending transactions
++	 * onto the list of running transactions
++	 */
++	desc = list_first_entry(&chan->ld_pending, struct fsl_desc_sw, node);
++	list_splice_tail_init(&chan->ld_pending, &chan->ld_running);
++
++	/*
++	 * Program the descriptor's address into the DMA controller,
++	 * then start the DMA transaction
++	 */
++	set_cdar(chan, desc->async_tx.phys);
++	dma_start(chan);
+ 
+ out_unlock:
+ 	spin_unlock_irqrestore(&chan->desc_lock, flags);
+@@ -913,30 +957,6 @@ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan)
+ static void fsl_dma_memcpy_issue_pending(struct dma_chan *dchan)
+ {
+ 	struct fsldma_chan *chan = to_fsl_chan(dchan);
+-
+-#ifdef FSL_DMA_LD_DEBUG
+-	struct fsl_desc_sw *ld;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&chan->desc_lock, flags);
+-	if (list_empty(&chan->ld_queue)) {
+-		spin_unlock_irqrestore(&chan->desc_lock, flags);
+-		return;
+-	}
+-
+-	dev_dbg(chan->dev, "--memcpy issue--\n");
+-	list_for_each_entry(ld, &chan->ld_queue, node) {
+-		int i;
+-		dev_dbg(chan->dev, "Ch %d, LD %08x\n",
+-				chan->id, ld->async_tx.phys);
+-		for (i = 0; i < 8; i++)
+-			dev_dbg(chan->dev, "LD offset %d: %08x\n",
+-					i, *(((u32 *)&ld->hw) + i));
+-	}
+-	dev_dbg(chan->dev, "----------------\n");
+-	spin_unlock_irqrestore(&chan->desc_lock, flags);
+-#endif
+-
+ 	fsl_chan_xfer_ld_queue(chan);
+ }
+ 
+@@ -978,10 +998,10 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
+ 	int xfer_ld_q = 0;
+ 	u32 stat;
+ 
++	/* save and clear the status register */
+ 	stat = get_sr(chan);
+-	dev_dbg(chan->dev, "event: channel %d, stat = 0x%x\n",
+-						chan->id, stat);
+-	set_sr(chan, stat);		/* Clear the event register */
++	set_sr(chan, stat);
++	dev_dbg(chan->dev, "irq: channel %d, stat = 0x%x\n", chan->id, stat);
+ 
+ 	stat &= ~(FSL_DMA_SR_CB | FSL_DMA_SR_CH);
+ 	if (!stat)
+@@ -990,12 +1010,13 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
+ 	if (stat & FSL_DMA_SR_TE)
+ 		dev_err(chan->dev, "Transfer Error!\n");
+ 
+-	/* Programming Error
++	/*
++	 * Programming Error
+ 	 * The DMA_INTERRUPT async_tx is a NULL transfer, which will
+ 	 * triger a PE interrupt.
+ 	 */
+ 	if (stat & FSL_DMA_SR_PE) {
+-		dev_dbg(chan->dev, "event: Programming Error INT\n");
++		dev_dbg(chan->dev, "irq: Programming Error INT\n");
+ 		if (get_bcr(chan) == 0) {
+ 			/* BCR register is 0, this is a DMA_INTERRUPT async_tx.
+ 			 * Now, update the completed cookie, and continue the
+@@ -1007,34 +1028,37 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
+ 		stat &= ~FSL_DMA_SR_PE;
+ 	}
+ 
+-	/* If the link descriptor segment transfer finishes,
++	/*
++	 * If the link descriptor segment transfer finishes,
+ 	 * we will recycle the used descriptor.
+ 	 */
+ 	if (stat & FSL_DMA_SR_EOSI) {
+-		dev_dbg(chan->dev, "event: End-of-segments INT\n");
+-		dev_dbg(chan->dev, "event: clndar 0x%llx, nlndar 0x%llx\n",
++		dev_dbg(chan->dev, "irq: End-of-segments INT\n");
++		dev_dbg(chan->dev, "irq: clndar 0x%llx, nlndar 0x%llx\n",
+ 			(unsigned long long)get_cdar(chan),
+ 			(unsigned long long)get_ndar(chan));
+ 		stat &= ~FSL_DMA_SR_EOSI;
+ 		update_cookie = 1;
+ 	}
+ 
+-	/* For MPC8349, EOCDI event need to update cookie
++	/*
++	 * For MPC8349, EOCDI event need to update cookie
+ 	 * and start the next transfer if it exist.
+ 	 */
+ 	if (stat & FSL_DMA_SR_EOCDI) {
+-		dev_dbg(chan->dev, "event: End-of-Chain link INT\n");
++		dev_dbg(chan->dev, "irq: End-of-Chain link INT\n");
+ 		stat &= ~FSL_DMA_SR_EOCDI;
+ 		update_cookie = 1;
+ 		xfer_ld_q = 1;
+ 	}
+ 
+-	/* If it current transfer is the end-of-transfer,
++	/*
++	 * If it current transfer is the end-of-transfer,
+ 	 * we should clear the Channel Start bit for
+ 	 * prepare next transfer.
+ 	 */
+ 	if (stat & FSL_DMA_SR_EOLNI) {
+-		dev_dbg(chan->dev, "event: End-of-link INT\n");
++		dev_dbg(chan->dev, "irq: End-of-link INT\n");
+ 		stat &= ~FSL_DMA_SR_EOLNI;
+ 		xfer_ld_q = 1;
+ 	}
+@@ -1044,10 +1068,9 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
+ 	if (xfer_ld_q)
+ 		fsl_chan_xfer_ld_queue(chan);
+ 	if (stat)
+-		dev_dbg(chan->dev, "event: unhandled sr 0x%02x\n",
+-					stat);
++		dev_dbg(chan->dev, "irq: unhandled sr 0x%02x\n", stat);
+ 
+-	dev_dbg(chan->dev, "event: Exit\n");
++	dev_dbg(chan->dev, "irq: Exit\n");
+ 	tasklet_schedule(&chan->tasklet);
+ 	return IRQ_HANDLED;
+ }
+@@ -1235,7 +1258,8 @@ static int __devinit fsl_dma_chan_probe(struct fsldma_device *fdev,
+ 	}
+ 
+ 	spin_lock_init(&chan->desc_lock);
+-	INIT_LIST_HEAD(&chan->ld_queue);
++	INIT_LIST_HEAD(&chan->ld_pending);
++	INIT_LIST_HEAD(&chan->ld_running);
+ 
+ 	chan->common.device = &fdev->common;
+ 
+diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
+index ea3b19c8708c..cb4d6ff51597 100644
+--- a/drivers/dma/fsldma.h
++++ b/drivers/dma/fsldma.h
+@@ -131,7 +131,8 @@ struct fsldma_chan {
+ 	struct fsldma_chan_regs __iomem *regs;
+ 	dma_cookie_t completed_cookie;	/* The maximum cookie completed */
+ 	spinlock_t desc_lock;		/* Descriptor operation lock */
+-	struct list_head ld_queue;	/* Link descriptors queue */
++	struct list_head ld_pending;	/* Link descriptors queue */
++	struct list_head ld_running;	/* Link descriptors queue */
+ 	struct dma_chan common;		/* DMA common channel */
+ 	struct dma_pool *desc_pool;	/* Descriptors pool */
+ 	struct device *dev;		/* Channel device */

commit a1c03319018061304be28d131073ac13a5cb86fb
+Author: Ira Snyder 
+Date:   Wed Jan 6 13:34:05 2010 +0000
+
+    fsldma: rename fsl_chan to chan
+    
+    The name fsl_chan seems too long, so it has been shortened to chan. There
+    are only a few places where the higher level "struct dma_chan *chan" name
+    conflicts. These have been changed to "struct dma_chan *dchan" instead.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Dan Williams 
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index 6a905929ef01..7b5f88cb495b 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -37,19 +37,19 @@
+ #include 
+ #include "fsldma.h"
+ 
+-static void dma_init(struct fsldma_chan *fsl_chan)
++static void dma_init(struct fsldma_chan *chan)
+ {
+ 	/* Reset the channel */
+-	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, 0, 32);
++	DMA_OUT(chan, &chan->regs->mr, 0, 32);
+ 
+-	switch (fsl_chan->feature & FSL_DMA_IP_MASK) {
++	switch (chan->feature & FSL_DMA_IP_MASK) {
+ 	case FSL_DMA_IP_85XX:
+ 		/* Set the channel to below modes:
+ 		 * EIE - Error interrupt enable
+ 		 * EOSIE - End of segments interrupt enable (basic mode)
+ 		 * EOLNIE - End of links interrupt enable
+ 		 */
+-		DMA_OUT(fsl_chan, &fsl_chan->regs->mr, FSL_DMA_MR_EIE
++		DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_EIE
+ 				| FSL_DMA_MR_EOLNIE | FSL_DMA_MR_EOSIE, 32);
+ 		break;
+ 	case FSL_DMA_IP_83XX:
+@@ -57,154 +57,154 @@ static void dma_init(struct fsldma_chan *fsl_chan)
+ 		 * EOTIE - End-of-transfer interrupt enable
+ 		 * PRC_RM - PCI read multiple
+ 		 */
+-		DMA_OUT(fsl_chan, &fsl_chan->regs->mr, FSL_DMA_MR_EOTIE
++		DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_EOTIE
+ 				| FSL_DMA_MR_PRC_RM, 32);
+ 		break;
+ 	}
+ 
+ }
+ 
+-static void set_sr(struct fsldma_chan *fsl_chan, u32 val)
++static void set_sr(struct fsldma_chan *chan, u32 val)
+ {
+-	DMA_OUT(fsl_chan, &fsl_chan->regs->sr, val, 32);
++	DMA_OUT(chan, &chan->regs->sr, val, 32);
+ }
+ 
+-static u32 get_sr(struct fsldma_chan *fsl_chan)
++static u32 get_sr(struct fsldma_chan *chan)
+ {
+-	return DMA_IN(fsl_chan, &fsl_chan->regs->sr, 32);
++	return DMA_IN(chan, &chan->regs->sr, 32);
+ }
+ 
+-static void set_desc_cnt(struct fsldma_chan *fsl_chan,
++static void set_desc_cnt(struct fsldma_chan *chan,
+ 				struct fsl_dma_ld_hw *hw, u32 count)
+ {
+-	hw->count = CPU_TO_DMA(fsl_chan, count, 32);
++	hw->count = CPU_TO_DMA(chan, count, 32);
+ }
+ 
+-static void set_desc_src(struct fsldma_chan *fsl_chan,
++static void set_desc_src(struct fsldma_chan *chan,
+ 				struct fsl_dma_ld_hw *hw, dma_addr_t src)
+ {
+ 	u64 snoop_bits;
+ 
+-	snoop_bits = ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
++	snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
+ 		? ((u64)FSL_DMA_SATR_SREADTYPE_SNOOP_READ << 32) : 0;
+-	hw->src_addr = CPU_TO_DMA(fsl_chan, snoop_bits | src, 64);
++	hw->src_addr = CPU_TO_DMA(chan, snoop_bits | src, 64);
+ }
+ 
+-static void set_desc_dst(struct fsldma_chan *fsl_chan,
++static void set_desc_dst(struct fsldma_chan *chan,
+ 				struct fsl_dma_ld_hw *hw, dma_addr_t dst)
+ {
+ 	u64 snoop_bits;
+ 
+-	snoop_bits = ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
++	snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
+ 		? ((u64)FSL_DMA_DATR_DWRITETYPE_SNOOP_WRITE << 32) : 0;
+-	hw->dst_addr = CPU_TO_DMA(fsl_chan, snoop_bits | dst, 64);
++	hw->dst_addr = CPU_TO_DMA(chan, snoop_bits | dst, 64);
+ }
+ 
+-static void set_desc_next(struct fsldma_chan *fsl_chan,
++static void set_desc_next(struct fsldma_chan *chan,
+ 				struct fsl_dma_ld_hw *hw, dma_addr_t next)
+ {
+ 	u64 snoop_bits;
+ 
+-	snoop_bits = ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_83XX)
++	snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_83XX)
+ 		? FSL_DMA_SNEN : 0;
+-	hw->next_ln_addr = CPU_TO_DMA(fsl_chan, snoop_bits | next, 64);
++	hw->next_ln_addr = CPU_TO_DMA(chan, snoop_bits | next, 64);
+ }
+ 
+-static void set_cdar(struct fsldma_chan *fsl_chan, dma_addr_t addr)
++static void set_cdar(struct fsldma_chan *chan, dma_addr_t addr)
+ {
+-	DMA_OUT(fsl_chan, &fsl_chan->regs->cdar, addr | FSL_DMA_SNEN, 64);
++	DMA_OUT(chan, &chan->regs->cdar, addr | FSL_DMA_SNEN, 64);
+ }
+ 
+-static dma_addr_t get_cdar(struct fsldma_chan *fsl_chan)
++static dma_addr_t get_cdar(struct fsldma_chan *chan)
+ {
+-	return DMA_IN(fsl_chan, &fsl_chan->regs->cdar, 64) & ~FSL_DMA_SNEN;
++	return DMA_IN(chan, &chan->regs->cdar, 64) & ~FSL_DMA_SNEN;
+ }
+ 
+-static void set_ndar(struct fsldma_chan *fsl_chan, dma_addr_t addr)
++static void set_ndar(struct fsldma_chan *chan, dma_addr_t addr)
+ {
+-	DMA_OUT(fsl_chan, &fsl_chan->regs->ndar, addr, 64);
++	DMA_OUT(chan, &chan->regs->ndar, addr, 64);
+ }
+ 
+-static dma_addr_t get_ndar(struct fsldma_chan *fsl_chan)
++static dma_addr_t get_ndar(struct fsldma_chan *chan)
+ {
+-	return DMA_IN(fsl_chan, &fsl_chan->regs->ndar, 64);
++	return DMA_IN(chan, &chan->regs->ndar, 64);
+ }
+ 
+-static u32 get_bcr(struct fsldma_chan *fsl_chan)
++static u32 get_bcr(struct fsldma_chan *chan)
+ {
+-	return DMA_IN(fsl_chan, &fsl_chan->regs->bcr, 32);
++	return DMA_IN(chan, &chan->regs->bcr, 32);
+ }
+ 
+-static int dma_is_idle(struct fsldma_chan *fsl_chan)
++static int dma_is_idle(struct fsldma_chan *chan)
+ {
+-	u32 sr = get_sr(fsl_chan);
++	u32 sr = get_sr(chan);
+ 	return (!(sr & FSL_DMA_SR_CB)) || (sr & FSL_DMA_SR_CH);
+ }
+ 
+-static void dma_start(struct fsldma_chan *fsl_chan)
++static void dma_start(struct fsldma_chan *chan)
+ {
+ 	u32 mode;
+ 
+-	mode = DMA_IN(fsl_chan, &fsl_chan->regs->mr, 32);
++	mode = DMA_IN(chan, &chan->regs->mr, 32);
+ 
+-	if ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
+-		if (fsl_chan->feature & FSL_DMA_CHAN_PAUSE_EXT) {
+-			DMA_OUT(fsl_chan, &fsl_chan->regs->bcr, 0, 32);
++	if ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
++		if (chan->feature & FSL_DMA_CHAN_PAUSE_EXT) {
++			DMA_OUT(chan, &chan->regs->bcr, 0, 32);
+ 			mode |= FSL_DMA_MR_EMP_EN;
+ 		} else {
+ 			mode &= ~FSL_DMA_MR_EMP_EN;
+ 		}
+ 	}
+ 
+-	if (fsl_chan->feature & FSL_DMA_CHAN_START_EXT)
++	if (chan->feature & FSL_DMA_CHAN_START_EXT)
+ 		mode |= FSL_DMA_MR_EMS_EN;
+ 	else
+ 		mode |= FSL_DMA_MR_CS;
+ 
+-	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, mode, 32);
++	DMA_OUT(chan, &chan->regs->mr, mode, 32);
+ }
+ 
+-static void dma_halt(struct fsldma_chan *fsl_chan)
++static void dma_halt(struct fsldma_chan *chan)
+ {
+ 	u32 mode;
+ 	int i;
+ 
+-	mode = DMA_IN(fsl_chan, &fsl_chan->regs->mr, 32);
++	mode = DMA_IN(chan, &chan->regs->mr, 32);
+ 	mode |= FSL_DMA_MR_CA;
+-	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, mode, 32);
++	DMA_OUT(chan, &chan->regs->mr, mode, 32);
+ 
+ 	mode &= ~(FSL_DMA_MR_CS | FSL_DMA_MR_EMS_EN | FSL_DMA_MR_CA);
+-	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, mode, 32);
++	DMA_OUT(chan, &chan->regs->mr, mode, 32);
+ 
+ 	for (i = 0; i < 100; i++) {
+-		if (dma_is_idle(fsl_chan))
++		if (dma_is_idle(chan))
+ 			break;
+ 		udelay(10);
+ 	}
+ 
+-	if (i >= 100 && !dma_is_idle(fsl_chan))
+-		dev_err(fsl_chan->dev, "DMA halt timeout!\n");
++	if (i >= 100 && !dma_is_idle(chan))
++		dev_err(chan->dev, "DMA halt timeout!\n");
+ }
+ 
+-static void set_ld_eol(struct fsldma_chan *fsl_chan,
++static void set_ld_eol(struct fsldma_chan *chan,
+ 			struct fsl_desc_sw *desc)
+ {
+ 	u64 snoop_bits;
+ 
+-	snoop_bits = ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_83XX)
++	snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_83XX)
+ 		? FSL_DMA_SNEN : 0;
+ 
+-	desc->hw.next_ln_addr = CPU_TO_DMA(fsl_chan,
+-		DMA_TO_CPU(fsl_chan, desc->hw.next_ln_addr, 64) | FSL_DMA_EOL
++	desc->hw.next_ln_addr = CPU_TO_DMA(chan,
++		DMA_TO_CPU(chan, desc->hw.next_ln_addr, 64) | FSL_DMA_EOL
+ 			| snoop_bits, 64);
+ }
+ 
+-static void append_ld_queue(struct fsldma_chan *fsl_chan,
++static void append_ld_queue(struct fsldma_chan *chan,
+ 		struct fsl_desc_sw *new_desc)
+ {
+-	struct fsl_desc_sw *queue_tail = to_fsl_desc(fsl_chan->ld_queue.prev);
++	struct fsl_desc_sw *queue_tail = to_fsl_desc(chan->ld_queue.prev);
+ 
+-	if (list_empty(&fsl_chan->ld_queue))
++	if (list_empty(&chan->ld_queue))
+ 		return;
+ 
+ 	/* Link to the new descriptor physical address and
+@@ -214,15 +214,15 @@ static void append_ld_queue(struct fsldma_chan *fsl_chan,
+ 	 *
+ 	 * For FSL_DMA_IP_83xx, the snoop enable bit need be set.
+ 	 */
+-	queue_tail->hw.next_ln_addr = CPU_TO_DMA(fsl_chan,
++	queue_tail->hw.next_ln_addr = CPU_TO_DMA(chan,
+ 			new_desc->async_tx.phys | FSL_DMA_EOSIE |
+-			(((fsl_chan->feature & FSL_DMA_IP_MASK)
++			(((chan->feature & FSL_DMA_IP_MASK)
+ 				== FSL_DMA_IP_83XX) ? FSL_DMA_SNEN : 0), 64);
+ }
+ 
+ /**
+  * fsl_chan_set_src_loop_size - Set source address hold transfer size
+- * @fsl_chan : Freescale DMA channel
++ * @chan : Freescale DMA channel
+  * @size     : Address loop size, 0 for disable loop
+  *
+  * The set source address hold transfer size. The source
+@@ -231,11 +231,11 @@ static void append_ld_queue(struct fsldma_chan *fsl_chan,
+  * read data from SA, SA + 1, SA + 2, SA + 3, then loop back to SA,
+  * SA + 1 ... and so on.
+  */
+-static void fsl_chan_set_src_loop_size(struct fsldma_chan *fsl_chan, int size)
++static void fsl_chan_set_src_loop_size(struct fsldma_chan *chan, int size)
+ {
+ 	u32 mode;
+ 
+-	mode = DMA_IN(fsl_chan, &fsl_chan->regs->mr, 32);
++	mode = DMA_IN(chan, &chan->regs->mr, 32);
+ 
+ 	switch (size) {
+ 	case 0:
+@@ -249,12 +249,12 @@ static void fsl_chan_set_src_loop_size(struct fsldma_chan *fsl_chan, int size)
+ 		break;
+ 	}
+ 
+-	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, mode, 32);
++	DMA_OUT(chan, &chan->regs->mr, mode, 32);
+ }
+ 
+ /**
+  * fsl_chan_set_dst_loop_size - Set destination address hold transfer size
+- * @fsl_chan : Freescale DMA channel
++ * @chan : Freescale DMA channel
+  * @size     : Address loop size, 0 for disable loop
+  *
+  * The set destination address hold transfer size. The destination
+@@ -263,11 +263,11 @@ static void fsl_chan_set_src_loop_size(struct fsldma_chan *fsl_chan, int size)
+  * write data to TA, TA + 1, TA + 2, TA + 3, then loop back to TA,
+  * TA + 1 ... and so on.
+  */
+-static void fsl_chan_set_dst_loop_size(struct fsldma_chan *fsl_chan, int size)
++static void fsl_chan_set_dst_loop_size(struct fsldma_chan *chan, int size)
+ {
+ 	u32 mode;
+ 
+-	mode = DMA_IN(fsl_chan, &fsl_chan->regs->mr, 32);
++	mode = DMA_IN(chan, &chan->regs->mr, 32);
+ 
+ 	switch (size) {
+ 	case 0:
+@@ -281,12 +281,12 @@ static void fsl_chan_set_dst_loop_size(struct fsldma_chan *fsl_chan, int size)
+ 		break;
+ 	}
+ 
+-	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, mode, 32);
++	DMA_OUT(chan, &chan->regs->mr, mode, 32);
+ }
+ 
+ /**
+  * fsl_chan_set_request_count - Set DMA Request Count for external control
+- * @fsl_chan : Freescale DMA channel
++ * @chan : Freescale DMA channel
+  * @size     : Number of bytes to transfer in a single request
+  *
+  * The Freescale DMA channel can be controlled by the external signal DREQ#.
+@@ -296,38 +296,38 @@ static void fsl_chan_set_dst_loop_size(struct fsldma_chan *fsl_chan, int size)
+  *
+  * A size of 0 disables external pause control. The maximum size is 1024.
+  */
+-static void fsl_chan_set_request_count(struct fsldma_chan *fsl_chan, int size)
++static void fsl_chan_set_request_count(struct fsldma_chan *chan, int size)
+ {
+ 	u32 mode;
+ 
+ 	BUG_ON(size > 1024);
+ 
+-	mode = DMA_IN(fsl_chan, &fsl_chan->regs->mr, 32);
++	mode = DMA_IN(chan, &chan->regs->mr, 32);
+ 	mode |= (__ilog2(size) << 24) & 0x0f000000;
+ 
+-	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, mode, 32);
++	DMA_OUT(chan, &chan->regs->mr, mode, 32);
+ }
+ 
+ /**
+  * fsl_chan_toggle_ext_pause - Toggle channel external pause status
+- * @fsl_chan : Freescale DMA channel
++ * @chan : Freescale DMA channel
+  * @enable   : 0 is disabled, 1 is enabled.
+  *
+  * The Freescale DMA channel can be controlled by the external signal DREQ#.
+  * The DMA Request Count feature should be used in addition to this feature
+  * to set the number of bytes to transfer before pausing the channel.
+  */
+-static void fsl_chan_toggle_ext_pause(struct fsldma_chan *fsl_chan, int enable)
++static void fsl_chan_toggle_ext_pause(struct fsldma_chan *chan, int enable)
+ {
+ 	if (enable)
+-		fsl_chan->feature |= FSL_DMA_CHAN_PAUSE_EXT;
++		chan->feature |= FSL_DMA_CHAN_PAUSE_EXT;
+ 	else
+-		fsl_chan->feature &= ~FSL_DMA_CHAN_PAUSE_EXT;
++		chan->feature &= ~FSL_DMA_CHAN_PAUSE_EXT;
+ }
+ 
+ /**
+  * fsl_chan_toggle_ext_start - Toggle channel external start status
+- * @fsl_chan : Freescale DMA channel
++ * @chan : Freescale DMA channel
+  * @enable   : 0 is disabled, 1 is enabled.
+  *
+  * If enable the external start, the channel can be started by an
+@@ -335,26 +335,26 @@ static void fsl_chan_toggle_ext_pause(struct fsldma_chan *fsl_chan, int enable)
+  * transfer immediately. The DMA channel will wait for the
+  * control pin asserted.
+  */
+-static void fsl_chan_toggle_ext_start(struct fsldma_chan *fsl_chan, int enable)
++static void fsl_chan_toggle_ext_start(struct fsldma_chan *chan, int enable)
+ {
+ 	if (enable)
+-		fsl_chan->feature |= FSL_DMA_CHAN_START_EXT;
++		chan->feature |= FSL_DMA_CHAN_START_EXT;
+ 	else
+-		fsl_chan->feature &= ~FSL_DMA_CHAN_START_EXT;
++		chan->feature &= ~FSL_DMA_CHAN_START_EXT;
+ }
+ 
+ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
+ {
+-	struct fsldma_chan *fsl_chan = to_fsl_chan(tx->chan);
++	struct fsldma_chan *chan = to_fsl_chan(tx->chan);
+ 	struct fsl_desc_sw *desc = tx_to_fsl_desc(tx);
+ 	struct fsl_desc_sw *child;
+ 	unsigned long flags;
+ 	dma_cookie_t cookie;
+ 
+ 	/* cookie increment and adding to ld_queue must be atomic */
+-	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
++	spin_lock_irqsave(&chan->desc_lock, flags);
+ 
+-	cookie = fsl_chan->common.cookie;
++	cookie = chan->common.cookie;
+ 	list_for_each_entry(child, &desc->tx_list, node) {
+ 		cookie++;
+ 		if (cookie < 0)
+@@ -363,33 +363,33 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
+ 		desc->async_tx.cookie = cookie;
+ 	}
+ 
+-	fsl_chan->common.cookie = cookie;
+-	append_ld_queue(fsl_chan, desc);
+-	list_splice_init(&desc->tx_list, fsl_chan->ld_queue.prev);
++	chan->common.cookie = cookie;
++	append_ld_queue(chan, desc);
++	list_splice_init(&desc->tx_list, chan->ld_queue.prev);
+ 
+-	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
++	spin_unlock_irqrestore(&chan->desc_lock, flags);
+ 
+ 	return cookie;
+ }
+ 
+ /**
+  * fsl_dma_alloc_descriptor - Allocate descriptor from channel's DMA pool.
+- * @fsl_chan : Freescale DMA channel
++ * @chan : Freescale DMA channel
+  *
+  * Return - The descriptor allocated. NULL for failed.
+  */
+ static struct fsl_desc_sw *fsl_dma_alloc_descriptor(
+-					struct fsldma_chan *fsl_chan)
++					struct fsldma_chan *chan)
+ {
+ 	dma_addr_t pdesc;
+ 	struct fsl_desc_sw *desc_sw;
+ 
+-	desc_sw = dma_pool_alloc(fsl_chan->desc_pool, GFP_ATOMIC, &pdesc);
++	desc_sw = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &pdesc);
+ 	if (desc_sw) {
+ 		memset(desc_sw, 0, sizeof(struct fsl_desc_sw));
+ 		INIT_LIST_HEAD(&desc_sw->tx_list);
+ 		dma_async_tx_descriptor_init(&desc_sw->async_tx,
+-						&fsl_chan->common);
++						&chan->common);
+ 		desc_sw->async_tx.tx_submit = fsl_dma_tx_submit;
+ 		desc_sw->async_tx.phys = pdesc;
+ 	}
+@@ -400,29 +400,29 @@ static struct fsl_desc_sw *fsl_dma_alloc_descriptor(
+ 
+ /**
+  * fsl_dma_alloc_chan_resources - Allocate resources for DMA channel.
+- * @fsl_chan : Freescale DMA channel
++ * @chan : Freescale DMA channel
+  *
+  * This function will create a dma pool for descriptor allocation.
+  *
+  * Return - The number of descriptors allocated.
+  */
+-static int fsl_dma_alloc_chan_resources(struct dma_chan *chan)
++static int fsl_dma_alloc_chan_resources(struct dma_chan *dchan)
+ {
+-	struct fsldma_chan *fsl_chan = to_fsl_chan(chan);
++	struct fsldma_chan *chan = to_fsl_chan(dchan);
+ 
+ 	/* Has this channel already been allocated? */
+-	if (fsl_chan->desc_pool)
++	if (chan->desc_pool)
+ 		return 1;
+ 
+ 	/* We need the descriptor to be aligned to 32bytes
+ 	 * for meeting FSL DMA specification requirement.
+ 	 */
+-	fsl_chan->desc_pool = dma_pool_create("fsl_dma_engine_desc_pool",
+-			fsl_chan->dev, sizeof(struct fsl_desc_sw),
++	chan->desc_pool = dma_pool_create("fsl_dma_engine_desc_pool",
++			chan->dev, sizeof(struct fsl_desc_sw),
+ 			32, 0);
+-	if (!fsl_chan->desc_pool) {
+-		dev_err(fsl_chan->dev, "No memory for channel %d "
+-			"descriptor dma pool.\n", fsl_chan->id);
++	if (!chan->desc_pool) {
++		dev_err(chan->dev, "No memory for channel %d "
++			"descriptor dma pool.\n", chan->id);
+ 		return 0;
+ 	}
+ 
+@@ -431,45 +431,45 @@ static int fsl_dma_alloc_chan_resources(struct dma_chan *chan)
+ 
+ /**
+  * fsl_dma_free_chan_resources - Free all resources of the channel.
+- * @fsl_chan : Freescale DMA channel
++ * @chan : Freescale DMA channel
+  */
+-static void fsl_dma_free_chan_resources(struct dma_chan *chan)
++static void fsl_dma_free_chan_resources(struct dma_chan *dchan)
+ {
+-	struct fsldma_chan *fsl_chan = to_fsl_chan(chan);
++	struct fsldma_chan *chan = to_fsl_chan(dchan);
+ 	struct fsl_desc_sw *desc, *_desc;
+ 	unsigned long flags;
+ 
+-	dev_dbg(fsl_chan->dev, "Free all channel resources.\n");
+-	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
+-	list_for_each_entry_safe(desc, _desc, &fsl_chan->ld_queue, node) {
++	dev_dbg(chan->dev, "Free all channel resources.\n");
++	spin_lock_irqsave(&chan->desc_lock, flags);
++	list_for_each_entry_safe(desc, _desc, &chan->ld_queue, node) {
+ #ifdef FSL_DMA_LD_DEBUG
+-		dev_dbg(fsl_chan->dev,
++		dev_dbg(chan->dev,
+ 				"LD %p will be released.\n", desc);
+ #endif
+ 		list_del(&desc->node);
+ 		/* free link descriptor */
+-		dma_pool_free(fsl_chan->desc_pool, desc, desc->async_tx.phys);
++		dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
+ 	}
+-	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
+-	dma_pool_destroy(fsl_chan->desc_pool);
++	spin_unlock_irqrestore(&chan->desc_lock, flags);
++	dma_pool_destroy(chan->desc_pool);
+ 
+-	fsl_chan->desc_pool = NULL;
++	chan->desc_pool = NULL;
+ }
+ 
+ static struct dma_async_tx_descriptor *
+-fsl_dma_prep_interrupt(struct dma_chan *chan, unsigned long flags)
++fsl_dma_prep_interrupt(struct dma_chan *dchan, unsigned long flags)
+ {
+-	struct fsldma_chan *fsl_chan;
++	struct fsldma_chan *chan;
+ 	struct fsl_desc_sw *new;
+ 
+-	if (!chan)
++	if (!dchan)
+ 		return NULL;
+ 
+-	fsl_chan = to_fsl_chan(chan);
++	chan = to_fsl_chan(dchan);
+ 
+-	new = fsl_dma_alloc_descriptor(fsl_chan);
++	new = fsl_dma_alloc_descriptor(chan);
+ 	if (!new) {
+-		dev_err(fsl_chan->dev, "No free memory for link descriptor\n");
++		dev_err(chan->dev, "No free memory for link descriptor\n");
+ 		return NULL;
+ 	}
+ 
+@@ -480,51 +480,51 @@ fsl_dma_prep_interrupt(struct dma_chan *chan, unsigned long flags)
+ 	list_add_tail(&new->node, &new->tx_list);
+ 
+ 	/* Set End-of-link to the last link descriptor of new list*/
+-	set_ld_eol(fsl_chan, new);
++	set_ld_eol(chan, new);
+ 
+ 	return &new->async_tx;
+ }
+ 
+ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+-	struct dma_chan *chan, dma_addr_t dma_dst, dma_addr_t dma_src,
++	struct dma_chan *dchan, dma_addr_t dma_dst, dma_addr_t dma_src,
+ 	size_t len, unsigned long flags)
+ {
+-	struct fsldma_chan *fsl_chan;
++	struct fsldma_chan *chan;
+ 	struct fsl_desc_sw *first = NULL, *prev = NULL, *new;
+ 	struct list_head *list;
+ 	size_t copy;
+ 
+-	if (!chan)
++	if (!dchan)
+ 		return NULL;
+ 
+ 	if (!len)
+ 		return NULL;
+ 
+-	fsl_chan = to_fsl_chan(chan);
++	chan = to_fsl_chan(dchan);
+ 
+ 	do {
+ 
+ 		/* Allocate the link descriptor from DMA pool */
+-		new = fsl_dma_alloc_descriptor(fsl_chan);
++		new = fsl_dma_alloc_descriptor(chan);
+ 		if (!new) {
+-			dev_err(fsl_chan->dev,
++			dev_err(chan->dev,
+ 					"No free memory for link descriptor\n");
+ 			goto fail;
+ 		}
+ #ifdef FSL_DMA_LD_DEBUG
+-		dev_dbg(fsl_chan->dev, "new link desc alloc %p\n", new);
++		dev_dbg(chan->dev, "new link desc alloc %p\n", new);
+ #endif
+ 
+ 		copy = min(len, (size_t)FSL_DMA_BCR_MAX_CNT);
+ 
+-		set_desc_cnt(fsl_chan, &new->hw, copy);
+-		set_desc_src(fsl_chan, &new->hw, dma_src);
+-		set_desc_dst(fsl_chan, &new->hw, dma_dst);
++		set_desc_cnt(chan, &new->hw, copy);
++		set_desc_src(chan, &new->hw, dma_src);
++		set_desc_dst(chan, &new->hw, dma_dst);
+ 
+ 		if (!first)
+ 			first = new;
+ 		else
+-			set_desc_next(fsl_chan, &prev->hw, new->async_tx.phys);
++			set_desc_next(chan, &prev->hw, new->async_tx.phys);
+ 
+ 		new->async_tx.cookie = 0;
+ 		async_tx_ack(&new->async_tx);
+@@ -542,7 +542,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+ 	new->async_tx.cookie = -EBUSY;
+ 
+ 	/* Set End-of-link to the last link descriptor of new list*/
+-	set_ld_eol(fsl_chan, new);
++	set_ld_eol(chan, new);
+ 
+ 	return &first->async_tx;
+ 
+@@ -553,7 +553,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+ 	list = &first->tx_list;
+ 	list_for_each_entry_safe_reverse(new, prev, list, node) {
+ 		list_del(&new->node);
+-		dma_pool_free(fsl_chan->desc_pool, new, new->async_tx.phys);
++		dma_pool_free(chan->desc_pool, new, new->async_tx.phys);
+ 	}
+ 
+ 	return NULL;
+@@ -572,10 +572,10 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+  * chan->private variable.
+  */
+ static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
+-	struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len,
++	struct dma_chan *dchan, struct scatterlist *sgl, unsigned int sg_len,
+ 	enum dma_data_direction direction, unsigned long flags)
+ {
+-	struct fsldma_chan *fsl_chan;
++	struct fsldma_chan *chan;
+ 	struct fsl_desc_sw *first = NULL, *prev = NULL, *new = NULL;
+ 	struct fsl_dma_slave *slave;
+ 	struct list_head *tx_list;
+@@ -588,14 +588,14 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
+ 	struct fsl_dma_hw_addr *hw;
+ 	dma_addr_t dma_dst, dma_src;
+ 
+-	if (!chan)
++	if (!dchan)
+ 		return NULL;
+ 
+-	if (!chan->private)
++	if (!dchan->private)
+ 		return NULL;
+ 
+-	fsl_chan = to_fsl_chan(chan);
+-	slave = chan->private;
++	chan = to_fsl_chan(dchan);
++	slave = dchan->private;
+ 
+ 	if (list_empty(&slave->addresses))
+ 		return NULL;
+@@ -644,14 +644,14 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
+ 			}
+ 
+ 			/* Allocate the link descriptor from DMA pool */
+-			new = fsl_dma_alloc_descriptor(fsl_chan);
++			new = fsl_dma_alloc_descriptor(chan);
+ 			if (!new) {
+-				dev_err(fsl_chan->dev, "No free memory for "
++				dev_err(chan->dev, "No free memory for "
+ 						       "link descriptor\n");
+ 				goto fail;
+ 			}
+ #ifdef FSL_DMA_LD_DEBUG
+-			dev_dbg(fsl_chan->dev, "new link desc alloc %p\n", new);
++			dev_dbg(chan->dev, "new link desc alloc %p\n", new);
+ #endif
+ 
+ 			/*
+@@ -678,9 +678,9 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
+ 			}
+ 
+ 			/* Fill in the descriptor */
+-			set_desc_cnt(fsl_chan, &new->hw, copy);
+-			set_desc_src(fsl_chan, &new->hw, dma_src);
+-			set_desc_dst(fsl_chan, &new->hw, dma_dst);
++			set_desc_cnt(chan, &new->hw, copy);
++			set_desc_src(chan, &new->hw, dma_src);
++			set_desc_dst(chan, &new->hw, dma_dst);
+ 
+ 			/*
+ 			 * If this is not the first descriptor, chain the
+@@ -689,7 +689,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
+ 			if (!first) {
+ 				first = new;
+ 			} else {
+-				set_desc_next(fsl_chan, &prev->hw,
++				set_desc_next(chan, &prev->hw,
+ 					      new->async_tx.phys);
+ 			}
+ 
+@@ -715,23 +715,23 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
+ 	new->async_tx.cookie = -EBUSY;
+ 
+ 	/* Set End-of-link to the last link descriptor of new list */
+-	set_ld_eol(fsl_chan, new);
++	set_ld_eol(chan, new);
+ 
+ 	/* Enable extra controller features */
+-	if (fsl_chan->set_src_loop_size)
+-		fsl_chan->set_src_loop_size(fsl_chan, slave->src_loop_size);
++	if (chan->set_src_loop_size)
++		chan->set_src_loop_size(chan, slave->src_loop_size);
+ 
+-	if (fsl_chan->set_dst_loop_size)
+-		fsl_chan->set_dst_loop_size(fsl_chan, slave->dst_loop_size);
++	if (chan->set_dst_loop_size)
++		chan->set_dst_loop_size(chan, slave->dst_loop_size);
+ 
+-	if (fsl_chan->toggle_ext_start)
+-		fsl_chan->toggle_ext_start(fsl_chan, slave->external_start);
++	if (chan->toggle_ext_start)
++		chan->toggle_ext_start(chan, slave->external_start);
+ 
+-	if (fsl_chan->toggle_ext_pause)
+-		fsl_chan->toggle_ext_pause(fsl_chan, slave->external_pause);
++	if (chan->toggle_ext_pause)
++		chan->toggle_ext_pause(chan, slave->external_pause);
+ 
+-	if (fsl_chan->set_request_count)
+-		fsl_chan->set_request_count(fsl_chan, slave->request_count);
++	if (chan->set_request_count)
++		chan->set_request_count(chan, slave->request_count);
+ 
+ 	return &first->async_tx;
+ 
+@@ -751,62 +751,62 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
+ 	tx_list = &first->tx_list;
+ 	list_for_each_entry_safe_reverse(new, prev, tx_list, node) {
+ 		list_del_init(&new->node);
+-		dma_pool_free(fsl_chan->desc_pool, new, new->async_tx.phys);
++		dma_pool_free(chan->desc_pool, new, new->async_tx.phys);
+ 	}
+ 
+ 	return NULL;
+ }
+ 
+-static void fsl_dma_device_terminate_all(struct dma_chan *chan)
++static void fsl_dma_device_terminate_all(struct dma_chan *dchan)
+ {
+-	struct fsldma_chan *fsl_chan;
++	struct fsldma_chan *chan;
+ 	struct fsl_desc_sw *desc, *tmp;
+ 	unsigned long flags;
+ 
+-	if (!chan)
++	if (!dchan)
+ 		return;
+ 
+-	fsl_chan = to_fsl_chan(chan);
++	chan = to_fsl_chan(dchan);
+ 
+ 	/* Halt the DMA engine */
+-	dma_halt(fsl_chan);
++	dma_halt(chan);
+ 
+-	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
++	spin_lock_irqsave(&chan->desc_lock, flags);
+ 
+ 	/* Remove and free all of the descriptors in the LD queue */
+-	list_for_each_entry_safe(desc, tmp, &fsl_chan->ld_queue, node) {
++	list_for_each_entry_safe(desc, tmp, &chan->ld_queue, node) {
+ 		list_del(&desc->node);
+-		dma_pool_free(fsl_chan->desc_pool, desc, desc->async_tx.phys);
++		dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
+ 	}
+ 
+-	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
++	spin_unlock_irqrestore(&chan->desc_lock, flags);
+ }
+ 
+ /**
+  * fsl_dma_update_completed_cookie - Update the completed cookie.
+- * @fsl_chan : Freescale DMA channel
++ * @chan : Freescale DMA channel
+  */
+-static void fsl_dma_update_completed_cookie(struct fsldma_chan *fsl_chan)
++static void fsl_dma_update_completed_cookie(struct fsldma_chan *chan)
+ {
+ 	struct fsl_desc_sw *cur_desc, *desc;
+ 	dma_addr_t ld_phy;
+ 
+-	ld_phy = get_cdar(fsl_chan) & FSL_DMA_NLDA_MASK;
++	ld_phy = get_cdar(chan) & FSL_DMA_NLDA_MASK;
+ 
+ 	if (ld_phy) {
+ 		cur_desc = NULL;
+-		list_for_each_entry(desc, &fsl_chan->ld_queue, node)
++		list_for_each_entry(desc, &chan->ld_queue, node)
+ 			if (desc->async_tx.phys == ld_phy) {
+ 				cur_desc = desc;
+ 				break;
+ 			}
+ 
+ 		if (cur_desc && cur_desc->async_tx.cookie) {
+-			if (dma_is_idle(fsl_chan))
+-				fsl_chan->completed_cookie =
++			if (dma_is_idle(chan))
++				chan->completed_cookie =
+ 					cur_desc->async_tx.cookie;
+ 			else
+-				fsl_chan->completed_cookie =
++				chan->completed_cookie =
+ 					cur_desc->async_tx.cookie - 1;
+ 		}
+ 	}
+@@ -814,27 +814,27 @@ static void fsl_dma_update_completed_cookie(struct fsldma_chan *fsl_chan)
+ 
+ /**
+  * fsl_chan_ld_cleanup - Clean up link descriptors
+- * @fsl_chan : Freescale DMA channel
++ * @chan : Freescale DMA channel
+  *
+  * This function clean up the ld_queue of DMA channel.
+  * If 'in_intr' is set, the function will move the link descriptor to
+  * the recycle list. Otherwise, free it directly.
+  */
+-static void fsl_chan_ld_cleanup(struct fsldma_chan *fsl_chan)
++static void fsl_chan_ld_cleanup(struct fsldma_chan *chan)
+ {
+ 	struct fsl_desc_sw *desc, *_desc;
+ 	unsigned long flags;
+ 
+-	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
++	spin_lock_irqsave(&chan->desc_lock, flags);
+ 
+-	dev_dbg(fsl_chan->dev, "chan completed_cookie = %d\n",
+-			fsl_chan->completed_cookie);
+-	list_for_each_entry_safe(desc, _desc, &fsl_chan->ld_queue, node) {
++	dev_dbg(chan->dev, "chan completed_cookie = %d\n",
++			chan->completed_cookie);
++	list_for_each_entry_safe(desc, _desc, &chan->ld_queue, node) {
+ 		dma_async_tx_callback callback;
+ 		void *callback_param;
+ 
+ 		if (dma_async_is_complete(desc->async_tx.cookie,
+-			    fsl_chan->completed_cookie, fsl_chan->common.cookie)
++			    chan->completed_cookie, chan->common.cookie)
+ 				== DMA_IN_PROGRESS)
+ 			break;
+ 
+@@ -844,119 +844,119 @@ static void fsl_chan_ld_cleanup(struct fsldma_chan *fsl_chan)
+ 		/* Remove from ld_queue list */
+ 		list_del(&desc->node);
+ 
+-		dev_dbg(fsl_chan->dev, "link descriptor %p will be recycle.\n",
++		dev_dbg(chan->dev, "link descriptor %p will be recycle.\n",
+ 				desc);
+-		dma_pool_free(fsl_chan->desc_pool, desc, desc->async_tx.phys);
++		dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
+ 
+ 		/* Run the link descriptor callback function */
+ 		if (callback) {
+-			spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
+-			dev_dbg(fsl_chan->dev, "link descriptor %p callback\n",
++			spin_unlock_irqrestore(&chan->desc_lock, flags);
++			dev_dbg(chan->dev, "link descriptor %p callback\n",
+ 					desc);
+ 			callback(callback_param);
+-			spin_lock_irqsave(&fsl_chan->desc_lock, flags);
++			spin_lock_irqsave(&chan->desc_lock, flags);
+ 		}
+ 	}
+-	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
++	spin_unlock_irqrestore(&chan->desc_lock, flags);
+ }
+ 
+ /**
+  * fsl_chan_xfer_ld_queue - Transfer link descriptors in channel ld_queue.
+- * @fsl_chan : Freescale DMA channel
++ * @chan : Freescale DMA channel
+  */
+-static void fsl_chan_xfer_ld_queue(struct fsldma_chan *fsl_chan)
++static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan)
+ {
+ 	struct list_head *ld_node;
+ 	dma_addr_t next_dst_addr;
+ 	unsigned long flags;
+ 
+-	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
++	spin_lock_irqsave(&chan->desc_lock, flags);
+ 
+-	if (!dma_is_idle(fsl_chan))
++	if (!dma_is_idle(chan))
+ 		goto out_unlock;
+ 
+-	dma_halt(fsl_chan);
++	dma_halt(chan);
+ 
+ 	/* If there are some link descriptors
+ 	 * not transfered in queue. We need to start it.
+ 	 */
+ 
+ 	/* Find the first un-transfer desciptor */
+-	for (ld_node = fsl_chan->ld_queue.next;
+-		(ld_node != &fsl_chan->ld_queue)
++	for (ld_node = chan->ld_queue.next;
++		(ld_node != &chan->ld_queue)
+ 			&& (dma_async_is_complete(
+ 				to_fsl_desc(ld_node)->async_tx.cookie,
+-				fsl_chan->completed_cookie,
+-				fsl_chan->common.cookie) == DMA_SUCCESS);
++				chan->completed_cookie,
++				chan->common.cookie) == DMA_SUCCESS);
+ 		ld_node = ld_node->next);
+ 
+-	if (ld_node != &fsl_chan->ld_queue) {
++	if (ld_node != &chan->ld_queue) {
+ 		/* Get the ld start address from ld_queue */
+ 		next_dst_addr = to_fsl_desc(ld_node)->async_tx.phys;
+-		dev_dbg(fsl_chan->dev, "xfer LDs staring from 0x%llx\n",
++		dev_dbg(chan->dev, "xfer LDs staring from 0x%llx\n",
+ 				(unsigned long long)next_dst_addr);
+-		set_cdar(fsl_chan, next_dst_addr);
+-		dma_start(fsl_chan);
++		set_cdar(chan, next_dst_addr);
++		dma_start(chan);
+ 	} else {
+-		set_cdar(fsl_chan, 0);
+-		set_ndar(fsl_chan, 0);
++		set_cdar(chan, 0);
++		set_ndar(chan, 0);
+ 	}
+ 
+ out_unlock:
+-	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
++	spin_unlock_irqrestore(&chan->desc_lock, flags);
+ }
+ 
+ /**
+  * fsl_dma_memcpy_issue_pending - Issue the DMA start command
+- * @fsl_chan : Freescale DMA channel
++ * @chan : Freescale DMA channel
+  */
+-static void fsl_dma_memcpy_issue_pending(struct dma_chan *chan)
++static void fsl_dma_memcpy_issue_pending(struct dma_chan *dchan)
+ {
+-	struct fsldma_chan *fsl_chan = to_fsl_chan(chan);
++	struct fsldma_chan *chan = to_fsl_chan(dchan);
+ 
+ #ifdef FSL_DMA_LD_DEBUG
+ 	struct fsl_desc_sw *ld;
+ 	unsigned long flags;
+ 
+-	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
+-	if (list_empty(&fsl_chan->ld_queue)) {
+-		spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
++	spin_lock_irqsave(&chan->desc_lock, flags);
++	if (list_empty(&chan->ld_queue)) {
++		spin_unlock_irqrestore(&chan->desc_lock, flags);
+ 		return;
+ 	}
+ 
+-	dev_dbg(fsl_chan->dev, "--memcpy issue--\n");
+-	list_for_each_entry(ld, &fsl_chan->ld_queue, node) {
++	dev_dbg(chan->dev, "--memcpy issue--\n");
++	list_for_each_entry(ld, &chan->ld_queue, node) {
+ 		int i;
+-		dev_dbg(fsl_chan->dev, "Ch %d, LD %08x\n",
+-				fsl_chan->id, ld->async_tx.phys);
++		dev_dbg(chan->dev, "Ch %d, LD %08x\n",
++				chan->id, ld->async_tx.phys);
+ 		for (i = 0; i < 8; i++)
+-			dev_dbg(fsl_chan->dev, "LD offset %d: %08x\n",
++			dev_dbg(chan->dev, "LD offset %d: %08x\n",
+ 					i, *(((u32 *)&ld->hw) + i));
+ 	}
+-	dev_dbg(fsl_chan->dev, "----------------\n");
+-	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
++	dev_dbg(chan->dev, "----------------\n");
++	spin_unlock_irqrestore(&chan->desc_lock, flags);
+ #endif
+ 
+-	fsl_chan_xfer_ld_queue(fsl_chan);
++	fsl_chan_xfer_ld_queue(chan);
+ }
+ 
+ /**
+  * fsl_dma_is_complete - Determine the DMA status
+- * @fsl_chan : Freescale DMA channel
++ * @chan : Freescale DMA channel
+  */
+-static enum dma_status fsl_dma_is_complete(struct dma_chan *chan,
++static enum dma_status fsl_dma_is_complete(struct dma_chan *dchan,
+ 					dma_cookie_t cookie,
+ 					dma_cookie_t *done,
+ 					dma_cookie_t *used)
+ {
+-	struct fsldma_chan *fsl_chan = to_fsl_chan(chan);
++	struct fsldma_chan *chan = to_fsl_chan(dchan);
+ 	dma_cookie_t last_used;
+ 	dma_cookie_t last_complete;
+ 
+-	fsl_chan_ld_cleanup(fsl_chan);
++	fsl_chan_ld_cleanup(chan);
+ 
+-	last_used = chan->cookie;
+-	last_complete = fsl_chan->completed_cookie;
++	last_used = dchan->cookie;
++	last_complete = chan->completed_cookie;
+ 
+ 	if (done)
+ 		*done = last_complete;
+@@ -973,30 +973,30 @@ static enum dma_status fsl_dma_is_complete(struct dma_chan *chan,
+ 
+ static irqreturn_t fsldma_chan_irq(int irq, void *data)
+ {
+-	struct fsldma_chan *fsl_chan = data;
+-	u32 stat;
++	struct fsldma_chan *chan = data;
+ 	int update_cookie = 0;
+ 	int xfer_ld_q = 0;
++	u32 stat;
+ 
+-	stat = get_sr(fsl_chan);
+-	dev_dbg(fsl_chan->dev, "event: channel %d, stat = 0x%x\n",
+-						fsl_chan->id, stat);
+-	set_sr(fsl_chan, stat);		/* Clear the event register */
++	stat = get_sr(chan);
++	dev_dbg(chan->dev, "event: channel %d, stat = 0x%x\n",
++						chan->id, stat);
++	set_sr(chan, stat);		/* Clear the event register */
+ 
+ 	stat &= ~(FSL_DMA_SR_CB | FSL_DMA_SR_CH);
+ 	if (!stat)
+ 		return IRQ_NONE;
+ 
+ 	if (stat & FSL_DMA_SR_TE)
+-		dev_err(fsl_chan->dev, "Transfer Error!\n");
++		dev_err(chan->dev, "Transfer Error!\n");
+ 
+ 	/* Programming Error
+ 	 * The DMA_INTERRUPT async_tx is a NULL transfer, which will
+ 	 * triger a PE interrupt.
+ 	 */
+ 	if (stat & FSL_DMA_SR_PE) {
+-		dev_dbg(fsl_chan->dev, "event: Programming Error INT\n");
+-		if (get_bcr(fsl_chan) == 0) {
++		dev_dbg(chan->dev, "event: Programming Error INT\n");
++		if (get_bcr(chan) == 0) {
+ 			/* BCR register is 0, this is a DMA_INTERRUPT async_tx.
+ 			 * Now, update the completed cookie, and continue the
+ 			 * next uncompleted transfer.
+@@ -1011,10 +1011,10 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
+ 	 * we will recycle the used descriptor.
+ 	 */
+ 	if (stat & FSL_DMA_SR_EOSI) {
+-		dev_dbg(fsl_chan->dev, "event: End-of-segments INT\n");
+-		dev_dbg(fsl_chan->dev, "event: clndar 0x%llx, nlndar 0x%llx\n",
+-			(unsigned long long)get_cdar(fsl_chan),
+-			(unsigned long long)get_ndar(fsl_chan));
++		dev_dbg(chan->dev, "event: End-of-segments INT\n");
++		dev_dbg(chan->dev, "event: clndar 0x%llx, nlndar 0x%llx\n",
++			(unsigned long long)get_cdar(chan),
++			(unsigned long long)get_ndar(chan));
+ 		stat &= ~FSL_DMA_SR_EOSI;
+ 		update_cookie = 1;
+ 	}
+@@ -1023,7 +1023,7 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
+ 	 * and start the next transfer if it exist.
+ 	 */
+ 	if (stat & FSL_DMA_SR_EOCDI) {
+-		dev_dbg(fsl_chan->dev, "event: End-of-Chain link INT\n");
++		dev_dbg(chan->dev, "event: End-of-Chain link INT\n");
+ 		stat &= ~FSL_DMA_SR_EOCDI;
+ 		update_cookie = 1;
+ 		xfer_ld_q = 1;
+@@ -1034,28 +1034,28 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
+ 	 * prepare next transfer.
+ 	 */
+ 	if (stat & FSL_DMA_SR_EOLNI) {
+-		dev_dbg(fsl_chan->dev, "event: End-of-link INT\n");
++		dev_dbg(chan->dev, "event: End-of-link INT\n");
+ 		stat &= ~FSL_DMA_SR_EOLNI;
+ 		xfer_ld_q = 1;
+ 	}
+ 
+ 	if (update_cookie)
+-		fsl_dma_update_completed_cookie(fsl_chan);
++		fsl_dma_update_completed_cookie(chan);
+ 	if (xfer_ld_q)
+-		fsl_chan_xfer_ld_queue(fsl_chan);
++		fsl_chan_xfer_ld_queue(chan);
+ 	if (stat)
+-		dev_dbg(fsl_chan->dev, "event: unhandled sr 0x%02x\n",
++		dev_dbg(chan->dev, "event: unhandled sr 0x%02x\n",
+ 					stat);
+ 
+-	dev_dbg(fsl_chan->dev, "event: Exit\n");
+-	tasklet_schedule(&fsl_chan->tasklet);
++	dev_dbg(chan->dev, "event: Exit\n");
++	tasklet_schedule(&chan->tasklet);
+ 	return IRQ_HANDLED;
+ }
+ 
+ static void dma_do_tasklet(unsigned long data)
+ {
+-	struct fsldma_chan *fsl_chan = (struct fsldma_chan *)data;
+-	fsl_chan_ld_cleanup(fsl_chan);
++	struct fsldma_chan *chan = (struct fsldma_chan *)data;
++	fsl_chan_ld_cleanup(chan);
+ }
+ 
+ static irqreturn_t fsldma_ctrl_irq(int irq, void *data)
+@@ -1171,24 +1171,24 @@ static int fsldma_request_irqs(struct fsldma_device *fdev)
+ static int __devinit fsl_dma_chan_probe(struct fsldma_device *fdev,
+ 	struct device_node *node, u32 feature, const char *compatible)
+ {
+-	struct fsldma_chan *fchan;
++	struct fsldma_chan *chan;
+ 	struct resource res;
+ 	int err;
+ 
+ 	/* alloc channel */
+-	fchan = kzalloc(sizeof(*fchan), GFP_KERNEL);
+-	if (!fchan) {
++	chan = kzalloc(sizeof(*chan), GFP_KERNEL);
++	if (!chan) {
+ 		dev_err(fdev->dev, "no free memory for DMA channels!\n");
+ 		err = -ENOMEM;
+ 		goto out_return;
+ 	}
+ 
+ 	/* ioremap registers for use */
+-	fchan->regs = of_iomap(node, 0);
+-	if (!fchan->regs) {
++	chan->regs = of_iomap(node, 0);
++	if (!chan->regs) {
+ 		dev_err(fdev->dev, "unable to ioremap registers\n");
+ 		err = -ENOMEM;
+-		goto out_free_fchan;
++		goto out_free_chan;
+ 	}
+ 
+ 	err = of_address_to_resource(node, 0, &res);
+@@ -1197,74 +1197,74 @@ static int __devinit fsl_dma_chan_probe(struct fsldma_device *fdev,
+ 		goto out_iounmap_regs;
+ 	}
+ 
+-	fchan->feature = feature;
++	chan->feature = feature;
+ 	if (!fdev->feature)
+-		fdev->feature = fchan->feature;
++		fdev->feature = chan->feature;
+ 
+ 	/*
+ 	 * If the DMA device's feature is different than the feature
+ 	 * of its channels, report the bug
+ 	 */
+-	WARN_ON(fdev->feature != fchan->feature);
++	WARN_ON(fdev->feature != chan->feature);
+ 
+-	fchan->dev = fdev->dev;
+-	fchan->id = ((res.start - 0x100) & 0xfff) >> 7;
+-	if (fchan->id >= FSL_DMA_MAX_CHANS_PER_DEVICE) {
++	chan->dev = fdev->dev;
++	chan->id = ((res.start - 0x100) & 0xfff) >> 7;
++	if (chan->id >= FSL_DMA_MAX_CHANS_PER_DEVICE) {
+ 		dev_err(fdev->dev, "too many channels for device\n");
+ 		err = -EINVAL;
+ 		goto out_iounmap_regs;
+ 	}
+ 
+-	fdev->chan[fchan->id] = fchan;
+-	tasklet_init(&fchan->tasklet, dma_do_tasklet, (unsigned long)fchan);
++	fdev->chan[chan->id] = chan;
++	tasklet_init(&chan->tasklet, dma_do_tasklet, (unsigned long)chan);
+ 
+ 	/* Initialize the channel */
+-	dma_init(fchan);
++	dma_init(chan);
+ 
+ 	/* Clear cdar registers */
+-	set_cdar(fchan, 0);
++	set_cdar(chan, 0);
+ 
+-	switch (fchan->feature & FSL_DMA_IP_MASK) {
++	switch (chan->feature & FSL_DMA_IP_MASK) {
+ 	case FSL_DMA_IP_85XX:
+-		fchan->toggle_ext_pause = fsl_chan_toggle_ext_pause;
++		chan->toggle_ext_pause = fsl_chan_toggle_ext_pause;
+ 	case FSL_DMA_IP_83XX:
+-		fchan->toggle_ext_start = fsl_chan_toggle_ext_start;
+-		fchan->set_src_loop_size = fsl_chan_set_src_loop_size;
+-		fchan->set_dst_loop_size = fsl_chan_set_dst_loop_size;
+-		fchan->set_request_count = fsl_chan_set_request_count;
++		chan->toggle_ext_start = fsl_chan_toggle_ext_start;
++		chan->set_src_loop_size = fsl_chan_set_src_loop_size;
++		chan->set_dst_loop_size = fsl_chan_set_dst_loop_size;
++		chan->set_request_count = fsl_chan_set_request_count;
+ 	}
+ 
+-	spin_lock_init(&fchan->desc_lock);
+-	INIT_LIST_HEAD(&fchan->ld_queue);
++	spin_lock_init(&chan->desc_lock);
++	INIT_LIST_HEAD(&chan->ld_queue);
+ 
+-	fchan->common.device = &fdev->common;
++	chan->common.device = &fdev->common;
+ 
+ 	/* find the IRQ line, if it exists in the device tree */
+-	fchan->irq = irq_of_parse_and_map(node, 0);
++	chan->irq = irq_of_parse_and_map(node, 0);
+ 
+ 	/* Add the channel to DMA device channel list */
+-	list_add_tail(&fchan->common.device_node, &fdev->common.channels);
++	list_add_tail(&chan->common.device_node, &fdev->common.channels);
+ 	fdev->common.chancnt++;
+ 
+-	dev_info(fdev->dev, "#%d (%s), irq %d\n", fchan->id, compatible,
+-		 fchan->irq != NO_IRQ ? fchan->irq : fdev->irq);
++	dev_info(fdev->dev, "#%d (%s), irq %d\n", chan->id, compatible,
++		 chan->irq != NO_IRQ ? chan->irq : fdev->irq);
+ 
+ 	return 0;
+ 
+ out_iounmap_regs:
+-	iounmap(fchan->regs);
+-out_free_fchan:
+-	kfree(fchan);
++	iounmap(chan->regs);
++out_free_chan:
++	kfree(chan);
+ out_return:
+ 	return err;
+ }
+ 
+-static void fsl_dma_chan_remove(struct fsldma_chan *fchan)
++static void fsl_dma_chan_remove(struct fsldma_chan *chan)
+ {
+-	irq_dispose_mapping(fchan->irq);
+-	list_del(&fchan->common.device_node);
+-	iounmap(fchan->regs);
+-	kfree(fchan);
++	irq_dispose_mapping(chan->irq);
++	list_del(&chan->common.device_node);
++	iounmap(chan->regs);
++	kfree(chan);
+ }
+ 
+ static int __devinit fsldma_of_probe(struct of_device *op,

commit d3f620b2c4fecdc8e060b70e8d92d29fc01c6126
+Author: Ira Snyder 
+Date:   Wed Jan 6 13:34:04 2010 +0000
+
+    fsldma: simplify IRQ probing and handling
+    
+    The IRQ probing is needlessly complex. All off the 83xx device trees in
+    arch/powerpc/boot/dts/ specify 5 interrupts per DMA controller: one for the
+    controller, and one for each channel. These interrupts are all attached to
+    the same IRQ line.
+    
+    This causes an interesting situation if two channels interrupt at the same
+    time. The per-controller handler will handle the first channel, and the
+    per-channel handler will handle the remaining channels.
+    
+    Instead of this mess, we fix the bug in the per-controller handler, and
+    make it handle all channels that generated an interrupt. When a
+    per-controller handler is specified in the device tree, we prefer to use
+    the shared handler instead of the per-channel handler.
+    
+    The 85xx/86xx controllers do not have a per-controller interrupt, and
+    instead use a per-channel interrupt. This behavior has not been changed.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Dan Williams 
+
+diff --git a/Documentation/powerpc/dts-bindings/fsl/dma.txt b/Documentation/powerpc/dts-bindings/fsl/dma.txt
+index 0732cdd05ba1..2a4b4bce6110 100644
+--- a/Documentation/powerpc/dts-bindings/fsl/dma.txt
++++ b/Documentation/powerpc/dts-bindings/fsl/dma.txt
+@@ -44,21 +44,29 @@ Example:
+ 			compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
+ 			cell-index = <0>;
+ 			reg = <0 0x80>;
++			interrupt-parent = <&ipic>;
++			interrupts = <71 8>;
+ 		};
+ 		dma-channel@80 {
+ 			compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
+ 			cell-index = <1>;
+ 			reg = <0x80 0x80>;
++			interrupt-parent = <&ipic>;
++			interrupts = <71 8>;
+ 		};
+ 		dma-channel@100 {
+ 			compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
+ 			cell-index = <2>;
+ 			reg = <0x100 0x80>;
++			interrupt-parent = <&ipic>;
++			interrupts = <71 8>;
+ 		};
+ 		dma-channel@180 {
+ 			compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
+ 			cell-index = <3>;
+ 			reg = <0x180 0x80>;
++			interrupt-parent = <&ipic>;
++			interrupts = <71 8>;
+ 		};
+ 	};
+ 
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index 507b29716bbd..6a905929ef01 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -967,6 +967,10 @@ static enum dma_status fsl_dma_is_complete(struct dma_chan *chan,
+ 	return dma_async_is_complete(cookie, last_complete, last_used);
+ }
+ 
++/*----------------------------------------------------------------------------*/
++/* Interrupt Handling                                                         */
++/*----------------------------------------------------------------------------*/
++
+ static irqreturn_t fsldma_chan_irq(int irq, void *data)
+ {
+ 	struct fsldma_chan *fsl_chan = data;
+@@ -1048,24 +1052,116 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static irqreturn_t fsldma_irq(int irq, void *data)
++static void dma_do_tasklet(unsigned long data)
++{
++	struct fsldma_chan *fsl_chan = (struct fsldma_chan *)data;
++	fsl_chan_ld_cleanup(fsl_chan);
++}
++
++static irqreturn_t fsldma_ctrl_irq(int irq, void *data)
+ {
+ 	struct fsldma_device *fdev = data;
+-	int ch_nr;
+-	u32 gsr;
++	struct fsldma_chan *chan;
++	unsigned int handled = 0;
++	u32 gsr, mask;
++	int i;
+ 
+ 	gsr = (fdev->feature & FSL_DMA_BIG_ENDIAN) ? in_be32(fdev->regs)
+-			: in_le32(fdev->regs);
+-	ch_nr = (32 - ffs(gsr)) / 8;
++						   : in_le32(fdev->regs);
++	mask = 0xff000000;
++	dev_dbg(fdev->dev, "IRQ: gsr 0x%.8x\n", gsr);
+ 
+-	return fdev->chan[ch_nr] ? fsldma_chan_irq(irq,
+-			fdev->chan[ch_nr]) : IRQ_NONE;
++	for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++) {
++		chan = fdev->chan[i];
++		if (!chan)
++			continue;
++
++		if (gsr & mask) {
++			dev_dbg(fdev->dev, "IRQ: chan %d\n", chan->id);
++			fsldma_chan_irq(irq, chan);
++			handled++;
++		}
++
++		gsr &= ~mask;
++		mask >>= 8;
++	}
++
++	return IRQ_RETVAL(handled);
+ }
+ 
+-static void dma_do_tasklet(unsigned long data)
++static void fsldma_free_irqs(struct fsldma_device *fdev)
+ {
+-	struct fsldma_chan *fsl_chan = (struct fsldma_chan *)data;
+-	fsl_chan_ld_cleanup(fsl_chan);
++	struct fsldma_chan *chan;
++	int i;
++
++	if (fdev->irq != NO_IRQ) {
++		dev_dbg(fdev->dev, "free per-controller IRQ\n");
++		free_irq(fdev->irq, fdev);
++		return;
++	}
++
++	for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++) {
++		chan = fdev->chan[i];
++		if (chan && chan->irq != NO_IRQ) {
++			dev_dbg(fdev->dev, "free channel %d IRQ\n", chan->id);
++			free_irq(chan->irq, chan);
++		}
++	}
++}
++
++static int fsldma_request_irqs(struct fsldma_device *fdev)
++{
++	struct fsldma_chan *chan;
++	int ret;
++	int i;
++
++	/* if we have a per-controller IRQ, use that */
++	if (fdev->irq != NO_IRQ) {
++		dev_dbg(fdev->dev, "request per-controller IRQ\n");
++		ret = request_irq(fdev->irq, fsldma_ctrl_irq, IRQF_SHARED,
++				  "fsldma-controller", fdev);
++		return ret;
++	}
++
++	/* no per-controller IRQ, use the per-channel IRQs */
++	for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++) {
++		chan = fdev->chan[i];
++		if (!chan)
++			continue;
++
++		if (chan->irq == NO_IRQ) {
++			dev_err(fdev->dev, "no interrupts property defined for "
++					   "DMA channel %d. Please fix your "
++					   "device tree\n", chan->id);
++			ret = -ENODEV;
++			goto out_unwind;
++		}
++
++		dev_dbg(fdev->dev, "request channel %d IRQ\n", chan->id);
++		ret = request_irq(chan->irq, fsldma_chan_irq, IRQF_SHARED,
++				  "fsldma-chan", chan);
++		if (ret) {
++			dev_err(fdev->dev, "unable to request IRQ for DMA "
++					   "channel %d\n", chan->id);
++			goto out_unwind;
++		}
++	}
++
++	return 0;
++
++out_unwind:
++	for (/* none */; i >= 0; i--) {
++		chan = fdev->chan[i];
++		if (!chan)
++			continue;
++
++		if (chan->irq == NO_IRQ)
++			continue;
++
++		free_irq(chan->irq, chan);
++	}
++
++	return ret;
+ }
+ 
+ /*----------------------------------------------------------------------------*/
+@@ -1143,29 +1239,18 @@ static int __devinit fsl_dma_chan_probe(struct fsldma_device *fdev,
+ 
+ 	fchan->common.device = &fdev->common;
+ 
++	/* find the IRQ line, if it exists in the device tree */
++	fchan->irq = irq_of_parse_and_map(node, 0);
++
+ 	/* Add the channel to DMA device channel list */
+ 	list_add_tail(&fchan->common.device_node, &fdev->common.channels);
+ 	fdev->common.chancnt++;
+ 
+-	fchan->irq = irq_of_parse_and_map(node, 0);
+-	if (fchan->irq != NO_IRQ) {
+-		err = request_irq(fchan->irq, &fsldma_chan_irq,
+-				  IRQF_SHARED, "fsldma-channel", fchan);
+-		if (err) {
+-			dev_err(fdev->dev, "unable to request IRQ "
+-					   "for channel %d\n", fchan->id);
+-			goto out_list_del;
+-		}
+-	}
+-
+ 	dev_info(fdev->dev, "#%d (%s), irq %d\n", fchan->id, compatible,
+ 		 fchan->irq != NO_IRQ ? fchan->irq : fdev->irq);
+ 
+ 	return 0;
+ 
+-out_list_del:
+-	irq_dispose_mapping(fchan->irq);
+-	list_del_init(&fchan->common.device_node);
+ out_iounmap_regs:
+ 	iounmap(fchan->regs);
+ out_free_fchan:
+@@ -1176,11 +1261,7 @@ static int __devinit fsl_dma_chan_probe(struct fsldma_device *fdev,
+ 
+ static void fsl_dma_chan_remove(struct fsldma_chan *fchan)
+ {
+-	if (fchan->irq != NO_IRQ) {
+-		free_irq(fchan->irq, fchan);
+-		irq_dispose_mapping(fchan->irq);
+-	}
+-
++	irq_dispose_mapping(fchan->irq);
+ 	list_del(&fchan->common.device_node);
+ 	iounmap(fchan->regs);
+ 	kfree(fchan);
+@@ -1211,6 +1292,9 @@ static int __devinit fsldma_of_probe(struct of_device *op,
+ 		goto out_free_fdev;
+ 	}
+ 
++	/* map the channel IRQ if it exists, but don't hookup the handler yet */
++	fdev->irq = irq_of_parse_and_map(op->node, 0);
++
+ 	dma_cap_set(DMA_MEMCPY, fdev->common.cap_mask);
+ 	dma_cap_set(DMA_INTERRUPT, fdev->common.cap_mask);
+ 	dma_cap_set(DMA_SLAVE, fdev->common.cap_mask);
+@@ -1224,16 +1308,6 @@ static int __devinit fsldma_of_probe(struct of_device *op,
+ 	fdev->common.device_terminate_all = fsl_dma_device_terminate_all;
+ 	fdev->common.dev = &op->dev;
+ 
+-	fdev->irq = irq_of_parse_and_map(op->node, 0);
+-	if (fdev->irq != NO_IRQ) {
+-		err = request_irq(fdev->irq, &fsldma_irq, IRQF_SHARED,
+-				  "fsldma-device", fdev);
+-		if (err) {
+-			dev_err(&op->dev, "unable to request IRQ\n");
+-			goto out_iounmap_regs;
+-		}
+-	}
+-
+ 	dev_set_drvdata(&op->dev, fdev);
+ 
+ 	/*
+@@ -1255,12 +1329,24 @@ static int __devinit fsldma_of_probe(struct of_device *op,
+ 		}
+ 	}
+ 
++	/*
++	 * Hookup the IRQ handler(s)
++	 *
++	 * If we have a per-controller interrupt, we prefer that to the
++	 * per-channel interrupts to reduce the number of shared interrupt
++	 * handlers on the same IRQ line
++	 */
++	err = fsldma_request_irqs(fdev);
++	if (err) {
++		dev_err(fdev->dev, "unable to request IRQs\n");
++		goto out_free_fdev;
++	}
++
+ 	dma_async_device_register(&fdev->common);
+ 	return 0;
+ 
+-out_iounmap_regs:
+-	iounmap(fdev->regs);
+ out_free_fdev:
++	irq_dispose_mapping(fdev->irq);
+ 	kfree(fdev);
+ out_return:
+ 	return err;
+@@ -1274,14 +1360,13 @@ static int fsldma_of_remove(struct of_device *op)
+ 	fdev = dev_get_drvdata(&op->dev);
+ 	dma_async_device_unregister(&fdev->common);
+ 
++	fsldma_free_irqs(fdev);
++
+ 	for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++) {
+ 		if (fdev->chan[i])
+ 			fsl_dma_chan_remove(fdev->chan[i]);
+ 	}
+ 
+-	if (fdev->irq != NO_IRQ)
+-		free_irq(fdev->irq, fdev);
+-
+ 	iounmap(fdev->regs);
+ 	dev_set_drvdata(&op->dev, NULL);
+ 	kfree(fdev);

commit e7a29151de1bd52081f27f149b68074fac0323be
+Author: Ira Snyder 
+Date:   Wed Jan 6 13:34:03 2010 +0000
+
+    fsldma: clean up the OF subsystem routines
+    
+    This fixes some errors in the cleanup paths of the OF subsystem, including
+    missing checks for ioremap failing. Also, some variables were renamed for
+    brevity.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Dan Williams 
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index c2db7541c22b..507b29716bbd 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -40,7 +40,7 @@
+ static void dma_init(struct fsldma_chan *fsl_chan)
+ {
+ 	/* Reset the channel */
+-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, 0, 32);
++	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, 0, 32);
+ 
+ 	switch (fsl_chan->feature & FSL_DMA_IP_MASK) {
+ 	case FSL_DMA_IP_85XX:
+@@ -49,7 +49,7 @@ static void dma_init(struct fsldma_chan *fsl_chan)
+ 		 * EOSIE - End of segments interrupt enable (basic mode)
+ 		 * EOLNIE - End of links interrupt enable
+ 		 */
+-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, FSL_DMA_MR_EIE
++		DMA_OUT(fsl_chan, &fsl_chan->regs->mr, FSL_DMA_MR_EIE
+ 				| FSL_DMA_MR_EOLNIE | FSL_DMA_MR_EOSIE, 32);
+ 		break;
+ 	case FSL_DMA_IP_83XX:
+@@ -57,7 +57,7 @@ static void dma_init(struct fsldma_chan *fsl_chan)
+ 		 * EOTIE - End-of-transfer interrupt enable
+ 		 * PRC_RM - PCI read multiple
+ 		 */
+-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, FSL_DMA_MR_EOTIE
++		DMA_OUT(fsl_chan, &fsl_chan->regs->mr, FSL_DMA_MR_EOTIE
+ 				| FSL_DMA_MR_PRC_RM, 32);
+ 		break;
+ 	}
+@@ -66,12 +66,12 @@ static void dma_init(struct fsldma_chan *fsl_chan)
+ 
+ static void set_sr(struct fsldma_chan *fsl_chan, u32 val)
+ {
+-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->sr, val, 32);
++	DMA_OUT(fsl_chan, &fsl_chan->regs->sr, val, 32);
+ }
+ 
+ static u32 get_sr(struct fsldma_chan *fsl_chan)
+ {
+-	return DMA_IN(fsl_chan, &fsl_chan->reg_base->sr, 32);
++	return DMA_IN(fsl_chan, &fsl_chan->regs->sr, 32);
+ }
+ 
+ static void set_desc_cnt(struct fsldma_chan *fsl_chan,
+@@ -112,27 +112,27 @@ static void set_desc_next(struct fsldma_chan *fsl_chan,
+ 
+ static void set_cdar(struct fsldma_chan *fsl_chan, dma_addr_t addr)
+ {
+-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->cdar, addr | FSL_DMA_SNEN, 64);
++	DMA_OUT(fsl_chan, &fsl_chan->regs->cdar, addr | FSL_DMA_SNEN, 64);
+ }
+ 
+ static dma_addr_t get_cdar(struct fsldma_chan *fsl_chan)
+ {
+-	return DMA_IN(fsl_chan, &fsl_chan->reg_base->cdar, 64) & ~FSL_DMA_SNEN;
++	return DMA_IN(fsl_chan, &fsl_chan->regs->cdar, 64) & ~FSL_DMA_SNEN;
+ }
+ 
+ static void set_ndar(struct fsldma_chan *fsl_chan, dma_addr_t addr)
+ {
+-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->ndar, addr, 64);
++	DMA_OUT(fsl_chan, &fsl_chan->regs->ndar, addr, 64);
+ }
+ 
+ static dma_addr_t get_ndar(struct fsldma_chan *fsl_chan)
+ {
+-	return DMA_IN(fsl_chan, &fsl_chan->reg_base->ndar, 64);
++	return DMA_IN(fsl_chan, &fsl_chan->regs->ndar, 64);
+ }
+ 
+ static u32 get_bcr(struct fsldma_chan *fsl_chan)
+ {
+-	return DMA_IN(fsl_chan, &fsl_chan->reg_base->bcr, 32);
++	return DMA_IN(fsl_chan, &fsl_chan->regs->bcr, 32);
+ }
+ 
+ static int dma_is_idle(struct fsldma_chan *fsl_chan)
+@@ -145,11 +145,11 @@ static void dma_start(struct fsldma_chan *fsl_chan)
+ {
+ 	u32 mode;
+ 
+-	mode = DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32);
++	mode = DMA_IN(fsl_chan, &fsl_chan->regs->mr, 32);
+ 
+ 	if ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
+ 		if (fsl_chan->feature & FSL_DMA_CHAN_PAUSE_EXT) {
+-			DMA_OUT(fsl_chan, &fsl_chan->reg_base->bcr, 0, 32);
++			DMA_OUT(fsl_chan, &fsl_chan->regs->bcr, 0, 32);
+ 			mode |= FSL_DMA_MR_EMP_EN;
+ 		} else {
+ 			mode &= ~FSL_DMA_MR_EMP_EN;
+@@ -161,7 +161,7 @@ static void dma_start(struct fsldma_chan *fsl_chan)
+ 	else
+ 		mode |= FSL_DMA_MR_CS;
+ 
+-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, mode, 32);
++	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, mode, 32);
+ }
+ 
+ static void dma_halt(struct fsldma_chan *fsl_chan)
+@@ -169,12 +169,12 @@ static void dma_halt(struct fsldma_chan *fsl_chan)
+ 	u32 mode;
+ 	int i;
+ 
+-	mode = DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32);
++	mode = DMA_IN(fsl_chan, &fsl_chan->regs->mr, 32);
+ 	mode |= FSL_DMA_MR_CA;
+-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, mode, 32);
++	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, mode, 32);
+ 
+ 	mode &= ~(FSL_DMA_MR_CS | FSL_DMA_MR_EMS_EN | FSL_DMA_MR_CA);
+-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, mode, 32);
++	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, mode, 32);
+ 
+ 	for (i = 0; i < 100; i++) {
+ 		if (dma_is_idle(fsl_chan))
+@@ -235,7 +235,7 @@ static void fsl_chan_set_src_loop_size(struct fsldma_chan *fsl_chan, int size)
+ {
+ 	u32 mode;
+ 
+-	mode = DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32);
++	mode = DMA_IN(fsl_chan, &fsl_chan->regs->mr, 32);
+ 
+ 	switch (size) {
+ 	case 0:
+@@ -249,7 +249,7 @@ static void fsl_chan_set_src_loop_size(struct fsldma_chan *fsl_chan, int size)
+ 		break;
+ 	}
+ 
+-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, mode, 32);
++	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, mode, 32);
+ }
+ 
+ /**
+@@ -267,7 +267,7 @@ static void fsl_chan_set_dst_loop_size(struct fsldma_chan *fsl_chan, int size)
+ {
+ 	u32 mode;
+ 
+-	mode = DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32);
++	mode = DMA_IN(fsl_chan, &fsl_chan->regs->mr, 32);
+ 
+ 	switch (size) {
+ 	case 0:
+@@ -281,7 +281,7 @@ static void fsl_chan_set_dst_loop_size(struct fsldma_chan *fsl_chan, int size)
+ 		break;
+ 	}
+ 
+-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, mode, 32);
++	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, mode, 32);
+ }
+ 
+ /**
+@@ -302,10 +302,10 @@ static void fsl_chan_set_request_count(struct fsldma_chan *fsl_chan, int size)
+ 
+ 	BUG_ON(size > 1024);
+ 
+-	mode = DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32);
++	mode = DMA_IN(fsl_chan, &fsl_chan->regs->mr, 32);
+ 	mode |= (__ilog2(size) << 24) & 0x0f000000;
+ 
+-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, mode, 32);
++	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, mode, 32);
+ }
+ 
+ /**
+@@ -967,7 +967,7 @@ static enum dma_status fsl_dma_is_complete(struct dma_chan *chan,
+ 	return dma_async_is_complete(cookie, last_complete, last_used);
+ }
+ 
+-static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
++static irqreturn_t fsldma_chan_irq(int irq, void *data)
+ {
+ 	struct fsldma_chan *fsl_chan = data;
+ 	u32 stat;
+@@ -1048,17 +1048,17 @@ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static irqreturn_t fsl_dma_do_interrupt(int irq, void *data)
++static irqreturn_t fsldma_irq(int irq, void *data)
+ {
+ 	struct fsldma_device *fdev = data;
+ 	int ch_nr;
+ 	u32 gsr;
+ 
+-	gsr = (fdev->feature & FSL_DMA_BIG_ENDIAN) ? in_be32(fdev->reg_base)
+-			: in_le32(fdev->reg_base);
++	gsr = (fdev->feature & FSL_DMA_BIG_ENDIAN) ? in_be32(fdev->regs)
++			: in_le32(fdev->regs);
+ 	ch_nr = (32 - ffs(gsr)) / 8;
+ 
+-	return fdev->chan[ch_nr] ? fsl_dma_chan_do_interrupt(irq,
++	return fdev->chan[ch_nr] ? fsldma_chan_irq(irq,
+ 			fdev->chan[ch_nr]) : IRQ_NONE;
+ }
+ 
+@@ -1075,140 +1075,142 @@ static void dma_do_tasklet(unsigned long data)
+ static int __devinit fsl_dma_chan_probe(struct fsldma_device *fdev,
+ 	struct device_node *node, u32 feature, const char *compatible)
+ {
+-	struct fsldma_chan *new_fsl_chan;
++	struct fsldma_chan *fchan;
+ 	struct resource res;
+ 	int err;
+ 
+ 	/* alloc channel */
+-	new_fsl_chan = kzalloc(sizeof(*new_fsl_chan), GFP_KERNEL);
+-	if (!new_fsl_chan) {
+-		dev_err(fdev->dev, "No free memory for allocating "
+-				"dma channels!\n");
+-		return -ENOMEM;
++	fchan = kzalloc(sizeof(*fchan), GFP_KERNEL);
++	if (!fchan) {
++		dev_err(fdev->dev, "no free memory for DMA channels!\n");
++		err = -ENOMEM;
++		goto out_return;
++	}
++
++	/* ioremap registers for use */
++	fchan->regs = of_iomap(node, 0);
++	if (!fchan->regs) {
++		dev_err(fdev->dev, "unable to ioremap registers\n");
++		err = -ENOMEM;
++		goto out_free_fchan;
+ 	}
+ 
+-	/* get dma channel register base */
+ 	err = of_address_to_resource(node, 0, &res);
+ 	if (err) {
+-		dev_err(fdev->dev, "Can't get %s property 'reg'\n",
+-				node->full_name);
+-		goto err_no_reg;
++		dev_err(fdev->dev, "unable to find 'reg' property\n");
++		goto out_iounmap_regs;
+ 	}
+ 
+-	new_fsl_chan->feature = feature;
+-
++	fchan->feature = feature;
+ 	if (!fdev->feature)
+-		fdev->feature = new_fsl_chan->feature;
++		fdev->feature = fchan->feature;
+ 
+-	/* If the DMA device's feature is different than its channels',
+-	 * report the bug.
++	/*
++	 * If the DMA device's feature is different than the feature
++	 * of its channels, report the bug
+ 	 */
+-	WARN_ON(fdev->feature != new_fsl_chan->feature);
+-
+-	new_fsl_chan->dev = fdev->dev;
+-	new_fsl_chan->reg_base = ioremap(res.start, resource_size(&res));
+-	new_fsl_chan->id = ((res.start - 0x100) & 0xfff) >> 7;
+-	if (new_fsl_chan->id >= FSL_DMA_MAX_CHANS_PER_DEVICE) {
+-		dev_err(fdev->dev, "There is no %d channel!\n",
+-				new_fsl_chan->id);
++	WARN_ON(fdev->feature != fchan->feature);
++
++	fchan->dev = fdev->dev;
++	fchan->id = ((res.start - 0x100) & 0xfff) >> 7;
++	if (fchan->id >= FSL_DMA_MAX_CHANS_PER_DEVICE) {
++		dev_err(fdev->dev, "too many channels for device\n");
+ 		err = -EINVAL;
+-		goto err_no_chan;
++		goto out_iounmap_regs;
+ 	}
+-	fdev->chan[new_fsl_chan->id] = new_fsl_chan;
+-	tasklet_init(&new_fsl_chan->tasklet, dma_do_tasklet,
+-			(unsigned long)new_fsl_chan);
+ 
+-	/* Init the channel */
+-	dma_init(new_fsl_chan);
++	fdev->chan[fchan->id] = fchan;
++	tasklet_init(&fchan->tasklet, dma_do_tasklet, (unsigned long)fchan);
++
++	/* Initialize the channel */
++	dma_init(fchan);
+ 
+ 	/* Clear cdar registers */
+-	set_cdar(new_fsl_chan, 0);
++	set_cdar(fchan, 0);
+ 
+-	switch (new_fsl_chan->feature & FSL_DMA_IP_MASK) {
++	switch (fchan->feature & FSL_DMA_IP_MASK) {
+ 	case FSL_DMA_IP_85XX:
+-		new_fsl_chan->toggle_ext_pause = fsl_chan_toggle_ext_pause;
++		fchan->toggle_ext_pause = fsl_chan_toggle_ext_pause;
+ 	case FSL_DMA_IP_83XX:
+-		new_fsl_chan->toggle_ext_start = fsl_chan_toggle_ext_start;
+-		new_fsl_chan->set_src_loop_size = fsl_chan_set_src_loop_size;
+-		new_fsl_chan->set_dst_loop_size = fsl_chan_set_dst_loop_size;
+-		new_fsl_chan->set_request_count = fsl_chan_set_request_count;
++		fchan->toggle_ext_start = fsl_chan_toggle_ext_start;
++		fchan->set_src_loop_size = fsl_chan_set_src_loop_size;
++		fchan->set_dst_loop_size = fsl_chan_set_dst_loop_size;
++		fchan->set_request_count = fsl_chan_set_request_count;
+ 	}
+ 
+-	spin_lock_init(&new_fsl_chan->desc_lock);
+-	INIT_LIST_HEAD(&new_fsl_chan->ld_queue);
++	spin_lock_init(&fchan->desc_lock);
++	INIT_LIST_HEAD(&fchan->ld_queue);
+ 
+-	new_fsl_chan->common.device = &fdev->common;
++	fchan->common.device = &fdev->common;
+ 
+ 	/* Add the channel to DMA device channel list */
+-	list_add_tail(&new_fsl_chan->common.device_node,
+-			&fdev->common.channels);
++	list_add_tail(&fchan->common.device_node, &fdev->common.channels);
+ 	fdev->common.chancnt++;
+ 
+-	new_fsl_chan->irq = irq_of_parse_and_map(node, 0);
+-	if (new_fsl_chan->irq != NO_IRQ) {
+-		err = request_irq(new_fsl_chan->irq,
+-					&fsl_dma_chan_do_interrupt, IRQF_SHARED,
+-					"fsldma-channel", new_fsl_chan);
++	fchan->irq = irq_of_parse_and_map(node, 0);
++	if (fchan->irq != NO_IRQ) {
++		err = request_irq(fchan->irq, &fsldma_chan_irq,
++				  IRQF_SHARED, "fsldma-channel", fchan);
+ 		if (err) {
+-			dev_err(fdev->dev, "DMA channel %s request_irq error "
+-				"with return %d\n", node->full_name, err);
+-			goto err_no_irq;
++			dev_err(fdev->dev, "unable to request IRQ "
++					   "for channel %d\n", fchan->id);
++			goto out_list_del;
+ 		}
+ 	}
+ 
+-	dev_info(fdev->dev, "#%d (%s), irq %d\n", new_fsl_chan->id,
+-		 compatible,
+-		 new_fsl_chan->irq != NO_IRQ ? new_fsl_chan->irq : fdev->irq);
++	dev_info(fdev->dev, "#%d (%s), irq %d\n", fchan->id, compatible,
++		 fchan->irq != NO_IRQ ? fchan->irq : fdev->irq);
+ 
+ 	return 0;
+ 
+-err_no_irq:
+-	list_del(&new_fsl_chan->common.device_node);
+-err_no_chan:
+-	iounmap(new_fsl_chan->reg_base);
+-err_no_reg:
+-	kfree(new_fsl_chan);
++out_list_del:
++	irq_dispose_mapping(fchan->irq);
++	list_del_init(&fchan->common.device_node);
++out_iounmap_regs:
++	iounmap(fchan->regs);
++out_free_fchan:
++	kfree(fchan);
++out_return:
+ 	return err;
+ }
+ 
+ static void fsl_dma_chan_remove(struct fsldma_chan *fchan)
+ {
+-	if (fchan->irq != NO_IRQ)
++	if (fchan->irq != NO_IRQ) {
+ 		free_irq(fchan->irq, fchan);
++		irq_dispose_mapping(fchan->irq);
++	}
++
+ 	list_del(&fchan->common.device_node);
+-	iounmap(fchan->reg_base);
++	iounmap(fchan->regs);
+ 	kfree(fchan);
+ }
+ 
+-static int __devinit fsldma_of_probe(struct of_device *dev,
++static int __devinit fsldma_of_probe(struct of_device *op,
+ 			const struct of_device_id *match)
+ {
+-	int err;
+ 	struct fsldma_device *fdev;
+ 	struct device_node *child;
+-	struct resource res;
++	int err;
+ 
+ 	fdev = kzalloc(sizeof(*fdev), GFP_KERNEL);
+ 	if (!fdev) {
+-		dev_err(&dev->dev, "No enough memory for 'priv'\n");
+-		return -ENOMEM;
++		dev_err(&op->dev, "No enough memory for 'priv'\n");
++		err = -ENOMEM;
++		goto out_return;
+ 	}
+-	fdev->dev = &dev->dev;
++
++	fdev->dev = &op->dev;
+ 	INIT_LIST_HEAD(&fdev->common.channels);
+ 
+-	/* get DMA controller register base */
+-	err = of_address_to_resource(dev->node, 0, &res);
+-	if (err) {
+-		dev_err(&dev->dev, "Can't get %s property 'reg'\n",
+-				dev->node->full_name);
+-		goto err_no_reg;
++	/* ioremap the registers for use */
++	fdev->regs = of_iomap(op->node, 0);
++	if (!fdev->regs) {
++		dev_err(&op->dev, "unable to ioremap registers\n");
++		err = -ENOMEM;
++		goto out_free_fdev;
+ 	}
+ 
+-	dev_info(&dev->dev, "Probe the Freescale DMA driver for %s "
+-			"controller at 0x%llx...\n",
+-			match->compatible, (unsigned long long)res.start);
+-	fdev->reg_base = ioremap(res.start, resource_size(&res));
+-
+ 	dma_cap_set(DMA_MEMCPY, fdev->common.cap_mask);
+ 	dma_cap_set(DMA_INTERRUPT, fdev->common.cap_mask);
+ 	dma_cap_set(DMA_SLAVE, fdev->common.cap_mask);
+@@ -1220,66 +1222,69 @@ static int __devinit fsldma_of_probe(struct of_device *dev,
+ 	fdev->common.device_issue_pending = fsl_dma_memcpy_issue_pending;
+ 	fdev->common.device_prep_slave_sg = fsl_dma_prep_slave_sg;
+ 	fdev->common.device_terminate_all = fsl_dma_device_terminate_all;
+-	fdev->common.dev = &dev->dev;
++	fdev->common.dev = &op->dev;
+ 
+-	fdev->irq = irq_of_parse_and_map(dev->node, 0);
++	fdev->irq = irq_of_parse_and_map(op->node, 0);
+ 	if (fdev->irq != NO_IRQ) {
+-		err = request_irq(fdev->irq, &fsl_dma_do_interrupt, IRQF_SHARED,
+-					"fsldma-device", fdev);
++		err = request_irq(fdev->irq, &fsldma_irq, IRQF_SHARED,
++				  "fsldma-device", fdev);
+ 		if (err) {
+-			dev_err(&dev->dev, "DMA device request_irq error "
+-				"with return %d\n", err);
+-			goto err;
++			dev_err(&op->dev, "unable to request IRQ\n");
++			goto out_iounmap_regs;
+ 		}
+ 	}
+ 
+-	dev_set_drvdata(&(dev->dev), fdev);
++	dev_set_drvdata(&op->dev, fdev);
+ 
+-	/* We cannot use of_platform_bus_probe() because there is no
+-	 * of_platform_bus_remove.  Instead, we manually instantiate every DMA
++	/*
++	 * We cannot use of_platform_bus_probe() because there is no
++	 * of_platform_bus_remove(). Instead, we manually instantiate every DMA
+ 	 * channel object.
+ 	 */
+-	for_each_child_of_node(dev->node, child) {
+-		if (of_device_is_compatible(child, "fsl,eloplus-dma-channel"))
++	for_each_child_of_node(op->node, child) {
++		if (of_device_is_compatible(child, "fsl,eloplus-dma-channel")) {
+ 			fsl_dma_chan_probe(fdev, child,
+ 				FSL_DMA_IP_85XX | FSL_DMA_BIG_ENDIAN,
+ 				"fsl,eloplus-dma-channel");
+-		if (of_device_is_compatible(child, "fsl,elo-dma-channel"))
++		}
++
++		if (of_device_is_compatible(child, "fsl,elo-dma-channel")) {
+ 			fsl_dma_chan_probe(fdev, child,
+ 				FSL_DMA_IP_83XX | FSL_DMA_LITTLE_ENDIAN,
+ 				"fsl,elo-dma-channel");
++		}
+ 	}
+ 
+ 	dma_async_device_register(&fdev->common);
+ 	return 0;
+ 
+-err:
+-	iounmap(fdev->reg_base);
+-err_no_reg:
++out_iounmap_regs:
++	iounmap(fdev->regs);
++out_free_fdev:
+ 	kfree(fdev);
++out_return:
+ 	return err;
+ }
+ 
+-static int fsldma_of_remove(struct of_device *of_dev)
++static int fsldma_of_remove(struct of_device *op)
+ {
+ 	struct fsldma_device *fdev;
+ 	unsigned int i;
+ 
+-	fdev = dev_get_drvdata(&of_dev->dev);
+-
++	fdev = dev_get_drvdata(&op->dev);
+ 	dma_async_device_unregister(&fdev->common);
+ 
+-	for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++)
++	for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++) {
+ 		if (fdev->chan[i])
+ 			fsl_dma_chan_remove(fdev->chan[i]);
++	}
+ 
+ 	if (fdev->irq != NO_IRQ)
+ 		free_irq(fdev->irq, fdev);
+ 
+-	iounmap(fdev->reg_base);
+-
++	iounmap(fdev->regs);
++	dev_set_drvdata(&op->dev, NULL);
+ 	kfree(fdev);
+-	dev_set_drvdata(&of_dev->dev, NULL);
+ 
+ 	return 0;
+ }
+diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
+index a67b8e3df0fa..ea3b19c8708c 100644
+--- a/drivers/dma/fsldma.h
++++ b/drivers/dma/fsldma.h
+@@ -108,7 +108,7 @@ struct fsldma_chan;
+ #define FSL_DMA_MAX_CHANS_PER_DEVICE 4
+ 
+ struct fsldma_device {
+-	void __iomem *reg_base;	/* DGSR register base */
++	void __iomem *regs;	/* DGSR register base */
+ 	struct device *dev;
+ 	struct dma_device common;
+ 	struct fsldma_chan *chan[FSL_DMA_MAX_CHANS_PER_DEVICE];
+@@ -128,7 +128,7 @@ struct fsldma_device {
+ #define FSL_DMA_CHAN_START_EXT	0x00002000
+ 
+ struct fsldma_chan {
+-	struct fsldma_chan_regs __iomem *reg_base;
++	struct fsldma_chan_regs __iomem *regs;
+ 	dma_cookie_t completed_cookie;	/* The maximum cookie completed */
+ 	spinlock_t desc_lock;		/* Descriptor operation lock */
+ 	struct list_head ld_queue;	/* Link descriptors queue */

commit 738f5f7e1ae876448cb7d9c82bea258b69386647
+Author: Ira Snyder 
+Date:   Wed Jan 6 13:34:02 2010 +0000
+
+    fsldma: rename dest to dst for uniformity
+    
+    Most functions in the standard library use "dst" as a parameter, rather
+    than "dest". This renames all use of "dest" to "dst" to match the usual
+    convention.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Dan Williams 
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index 6795d96e3629..c2db7541c22b 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -90,14 +90,14 @@ static void set_desc_src(struct fsldma_chan *fsl_chan,
+ 	hw->src_addr = CPU_TO_DMA(fsl_chan, snoop_bits | src, 64);
+ }
+ 
+-static void set_desc_dest(struct fsldma_chan *fsl_chan,
+-				struct fsl_dma_ld_hw *hw, dma_addr_t dest)
++static void set_desc_dst(struct fsldma_chan *fsl_chan,
++				struct fsl_dma_ld_hw *hw, dma_addr_t dst)
+ {
+ 	u64 snoop_bits;
+ 
+ 	snoop_bits = ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
+ 		? ((u64)FSL_DMA_DATR_DWRITETYPE_SNOOP_WRITE << 32) : 0;
+-	hw->dst_addr = CPU_TO_DMA(fsl_chan, snoop_bits | dest, 64);
++	hw->dst_addr = CPU_TO_DMA(fsl_chan, snoop_bits | dst, 64);
+ }
+ 
+ static void set_desc_next(struct fsldma_chan *fsl_chan,
+@@ -253,7 +253,7 @@ static void fsl_chan_set_src_loop_size(struct fsldma_chan *fsl_chan, int size)
+ }
+ 
+ /**
+- * fsl_chan_set_dest_loop_size - Set destination address hold transfer size
++ * fsl_chan_set_dst_loop_size - Set destination address hold transfer size
+  * @fsl_chan : Freescale DMA channel
+  * @size     : Address loop size, 0 for disable loop
+  *
+@@ -263,7 +263,7 @@ static void fsl_chan_set_src_loop_size(struct fsldma_chan *fsl_chan, int size)
+  * write data to TA, TA + 1, TA + 2, TA + 3, then loop back to TA,
+  * TA + 1 ... and so on.
+  */
+-static void fsl_chan_set_dest_loop_size(struct fsldma_chan *fsl_chan, int size)
++static void fsl_chan_set_dst_loop_size(struct fsldma_chan *fsl_chan, int size)
+ {
+ 	u32 mode;
+ 
+@@ -486,7 +486,7 @@ fsl_dma_prep_interrupt(struct dma_chan *chan, unsigned long flags)
+ }
+ 
+ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+-	struct dma_chan *chan, dma_addr_t dma_dest, dma_addr_t dma_src,
++	struct dma_chan *chan, dma_addr_t dma_dst, dma_addr_t dma_src,
+ 	size_t len, unsigned long flags)
+ {
+ 	struct fsldma_chan *fsl_chan;
+@@ -519,7 +519,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+ 
+ 		set_desc_cnt(fsl_chan, &new->hw, copy);
+ 		set_desc_src(fsl_chan, &new->hw, dma_src);
+-		set_desc_dest(fsl_chan, &new->hw, dma_dest);
++		set_desc_dst(fsl_chan, &new->hw, dma_dst);
+ 
+ 		if (!first)
+ 			first = new;
+@@ -532,7 +532,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+ 		prev = new;
+ 		len -= copy;
+ 		dma_src += copy;
+-		dma_dest += copy;
++		dma_dst += copy;
+ 
+ 		/* Insert the link descriptor to the LD ring */
+ 		list_add_tail(&new->node, &first->tx_list);
+@@ -680,7 +680,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
+ 			/* Fill in the descriptor */
+ 			set_desc_cnt(fsl_chan, &new->hw, copy);
+ 			set_desc_src(fsl_chan, &new->hw, dma_src);
+-			set_desc_dest(fsl_chan, &new->hw, dma_dst);
++			set_desc_dst(fsl_chan, &new->hw, dma_dst);
+ 
+ 			/*
+ 			 * If this is not the first descriptor, chain the
+@@ -721,8 +721,8 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
+ 	if (fsl_chan->set_src_loop_size)
+ 		fsl_chan->set_src_loop_size(fsl_chan, slave->src_loop_size);
+ 
+-	if (fsl_chan->set_dest_loop_size)
+-		fsl_chan->set_dest_loop_size(fsl_chan, slave->dst_loop_size);
++	if (fsl_chan->set_dst_loop_size)
++		fsl_chan->set_dst_loop_size(fsl_chan, slave->dst_loop_size);
+ 
+ 	if (fsl_chan->toggle_ext_start)
+ 		fsl_chan->toggle_ext_start(fsl_chan, slave->external_start);
+@@ -867,7 +867,7 @@ static void fsl_chan_ld_cleanup(struct fsldma_chan *fsl_chan)
+ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *fsl_chan)
+ {
+ 	struct list_head *ld_node;
+-	dma_addr_t next_dest_addr;
++	dma_addr_t next_dst_addr;
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
+@@ -892,10 +892,10 @@ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *fsl_chan)
+ 
+ 	if (ld_node != &fsl_chan->ld_queue) {
+ 		/* Get the ld start address from ld_queue */
+-		next_dest_addr = to_fsl_desc(ld_node)->async_tx.phys;
++		next_dst_addr = to_fsl_desc(ld_node)->async_tx.phys;
+ 		dev_dbg(fsl_chan->dev, "xfer LDs staring from 0x%llx\n",
+-				(unsigned long long)next_dest_addr);
+-		set_cdar(fsl_chan, next_dest_addr);
++				(unsigned long long)next_dst_addr);
++		set_cdar(fsl_chan, next_dst_addr);
+ 		dma_start(fsl_chan);
+ 	} else {
+ 		set_cdar(fsl_chan, 0);
+@@ -1130,7 +1130,7 @@ static int __devinit fsl_dma_chan_probe(struct fsldma_device *fdev,
+ 	case FSL_DMA_IP_83XX:
+ 		new_fsl_chan->toggle_ext_start = fsl_chan_toggle_ext_start;
+ 		new_fsl_chan->set_src_loop_size = fsl_chan_set_src_loop_size;
+-		new_fsl_chan->set_dest_loop_size = fsl_chan_set_dest_loop_size;
++		new_fsl_chan->set_dst_loop_size = fsl_chan_set_dst_loop_size;
+ 		new_fsl_chan->set_request_count = fsl_chan_set_request_count;
+ 	}
+ 
+diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
+index f8c2baa6f41e..a67b8e3df0fa 100644
+--- a/drivers/dma/fsldma.h
++++ b/drivers/dma/fsldma.h
+@@ -143,7 +143,7 @@ struct fsldma_chan {
+ 	void (*toggle_ext_pause)(struct fsldma_chan *fsl_chan, int enable);
+ 	void (*toggle_ext_start)(struct fsldma_chan *fsl_chan, int enable);
+ 	void (*set_src_loop_size)(struct fsldma_chan *fsl_chan, int size);
+-	void (*set_dest_loop_size)(struct fsldma_chan *fsl_chan, int size);
++	void (*set_dst_loop_size)(struct fsldma_chan *fsl_chan, int size);
+ 	void (*set_request_count)(struct fsldma_chan *fsl_chan, int size);
+ };
+ 

commit a4f56d4b103d4e5d1a59a9118db0185a6bd1a83b
+Author: Ira Snyder 
+Date:   Wed Jan 6 13:34:01 2010 +0000
+
+    fsldma: rename struct fsl_dma_chan to struct fsldma_chan
+    
+    This is the beginning of a cleanup which will change all instances of
+    "fsl_dma" to "fsldma" to match the name of the driver itself.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Dan Williams 
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index 0b4e6383f480..6795d96e3629 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -37,7 +37,7 @@
+ #include 
+ #include "fsldma.h"
+ 
+-static void dma_init(struct fsl_dma_chan *fsl_chan)
++static void dma_init(struct fsldma_chan *fsl_chan)
+ {
+ 	/* Reset the channel */
+ 	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, 0, 32);
+@@ -64,23 +64,23 @@ static void dma_init(struct fsl_dma_chan *fsl_chan)
+ 
+ }
+ 
+-static void set_sr(struct fsl_dma_chan *fsl_chan, u32 val)
++static void set_sr(struct fsldma_chan *fsl_chan, u32 val)
+ {
+ 	DMA_OUT(fsl_chan, &fsl_chan->reg_base->sr, val, 32);
+ }
+ 
+-static u32 get_sr(struct fsl_dma_chan *fsl_chan)
++static u32 get_sr(struct fsldma_chan *fsl_chan)
+ {
+ 	return DMA_IN(fsl_chan, &fsl_chan->reg_base->sr, 32);
+ }
+ 
+-static void set_desc_cnt(struct fsl_dma_chan *fsl_chan,
++static void set_desc_cnt(struct fsldma_chan *fsl_chan,
+ 				struct fsl_dma_ld_hw *hw, u32 count)
+ {
+ 	hw->count = CPU_TO_DMA(fsl_chan, count, 32);
+ }
+ 
+-static void set_desc_src(struct fsl_dma_chan *fsl_chan,
++static void set_desc_src(struct fsldma_chan *fsl_chan,
+ 				struct fsl_dma_ld_hw *hw, dma_addr_t src)
+ {
+ 	u64 snoop_bits;
+@@ -90,7 +90,7 @@ static void set_desc_src(struct fsl_dma_chan *fsl_chan,
+ 	hw->src_addr = CPU_TO_DMA(fsl_chan, snoop_bits | src, 64);
+ }
+ 
+-static void set_desc_dest(struct fsl_dma_chan *fsl_chan,
++static void set_desc_dest(struct fsldma_chan *fsl_chan,
+ 				struct fsl_dma_ld_hw *hw, dma_addr_t dest)
+ {
+ 	u64 snoop_bits;
+@@ -100,7 +100,7 @@ static void set_desc_dest(struct fsl_dma_chan *fsl_chan,
+ 	hw->dst_addr = CPU_TO_DMA(fsl_chan, snoop_bits | dest, 64);
+ }
+ 
+-static void set_desc_next(struct fsl_dma_chan *fsl_chan,
++static void set_desc_next(struct fsldma_chan *fsl_chan,
+ 				struct fsl_dma_ld_hw *hw, dma_addr_t next)
+ {
+ 	u64 snoop_bits;
+@@ -110,38 +110,38 @@ static void set_desc_next(struct fsl_dma_chan *fsl_chan,
+ 	hw->next_ln_addr = CPU_TO_DMA(fsl_chan, snoop_bits | next, 64);
+ }
+ 
+-static void set_cdar(struct fsl_dma_chan *fsl_chan, dma_addr_t addr)
++static void set_cdar(struct fsldma_chan *fsl_chan, dma_addr_t addr)
+ {
+ 	DMA_OUT(fsl_chan, &fsl_chan->reg_base->cdar, addr | FSL_DMA_SNEN, 64);
+ }
+ 
+-static dma_addr_t get_cdar(struct fsl_dma_chan *fsl_chan)
++static dma_addr_t get_cdar(struct fsldma_chan *fsl_chan)
+ {
+ 	return DMA_IN(fsl_chan, &fsl_chan->reg_base->cdar, 64) & ~FSL_DMA_SNEN;
+ }
+ 
+-static void set_ndar(struct fsl_dma_chan *fsl_chan, dma_addr_t addr)
++static void set_ndar(struct fsldma_chan *fsl_chan, dma_addr_t addr)
+ {
+ 	DMA_OUT(fsl_chan, &fsl_chan->reg_base->ndar, addr, 64);
+ }
+ 
+-static dma_addr_t get_ndar(struct fsl_dma_chan *fsl_chan)
++static dma_addr_t get_ndar(struct fsldma_chan *fsl_chan)
+ {
+ 	return DMA_IN(fsl_chan, &fsl_chan->reg_base->ndar, 64);
+ }
+ 
+-static u32 get_bcr(struct fsl_dma_chan *fsl_chan)
++static u32 get_bcr(struct fsldma_chan *fsl_chan)
+ {
+ 	return DMA_IN(fsl_chan, &fsl_chan->reg_base->bcr, 32);
+ }
+ 
+-static int dma_is_idle(struct fsl_dma_chan *fsl_chan)
++static int dma_is_idle(struct fsldma_chan *fsl_chan)
+ {
+ 	u32 sr = get_sr(fsl_chan);
+ 	return (!(sr & FSL_DMA_SR_CB)) || (sr & FSL_DMA_SR_CH);
+ }
+ 
+-static void dma_start(struct fsl_dma_chan *fsl_chan)
++static void dma_start(struct fsldma_chan *fsl_chan)
+ {
+ 	u32 mode;
+ 
+@@ -164,7 +164,7 @@ static void dma_start(struct fsl_dma_chan *fsl_chan)
+ 	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, mode, 32);
+ }
+ 
+-static void dma_halt(struct fsl_dma_chan *fsl_chan)
++static void dma_halt(struct fsldma_chan *fsl_chan)
+ {
+ 	u32 mode;
+ 	int i;
+@@ -186,7 +186,7 @@ static void dma_halt(struct fsl_dma_chan *fsl_chan)
+ 		dev_err(fsl_chan->dev, "DMA halt timeout!\n");
+ }
+ 
+-static void set_ld_eol(struct fsl_dma_chan *fsl_chan,
++static void set_ld_eol(struct fsldma_chan *fsl_chan,
+ 			struct fsl_desc_sw *desc)
+ {
+ 	u64 snoop_bits;
+@@ -199,7 +199,7 @@ static void set_ld_eol(struct fsl_dma_chan *fsl_chan,
+ 			| snoop_bits, 64);
+ }
+ 
+-static void append_ld_queue(struct fsl_dma_chan *fsl_chan,
++static void append_ld_queue(struct fsldma_chan *fsl_chan,
+ 		struct fsl_desc_sw *new_desc)
+ {
+ 	struct fsl_desc_sw *queue_tail = to_fsl_desc(fsl_chan->ld_queue.prev);
+@@ -231,7 +231,7 @@ static void append_ld_queue(struct fsl_dma_chan *fsl_chan,
+  * read data from SA, SA + 1, SA + 2, SA + 3, then loop back to SA,
+  * SA + 1 ... and so on.
+  */
+-static void fsl_chan_set_src_loop_size(struct fsl_dma_chan *fsl_chan, int size)
++static void fsl_chan_set_src_loop_size(struct fsldma_chan *fsl_chan, int size)
+ {
+ 	u32 mode;
+ 
+@@ -263,7 +263,7 @@ static void fsl_chan_set_src_loop_size(struct fsl_dma_chan *fsl_chan, int size)
+  * write data to TA, TA + 1, TA + 2, TA + 3, then loop back to TA,
+  * TA + 1 ... and so on.
+  */
+-static void fsl_chan_set_dest_loop_size(struct fsl_dma_chan *fsl_chan, int size)
++static void fsl_chan_set_dest_loop_size(struct fsldma_chan *fsl_chan, int size)
+ {
+ 	u32 mode;
+ 
+@@ -296,7 +296,7 @@ static void fsl_chan_set_dest_loop_size(struct fsl_dma_chan *fsl_chan, int size)
+  *
+  * A size of 0 disables external pause control. The maximum size is 1024.
+  */
+-static void fsl_chan_set_request_count(struct fsl_dma_chan *fsl_chan, int size)
++static void fsl_chan_set_request_count(struct fsldma_chan *fsl_chan, int size)
+ {
+ 	u32 mode;
+ 
+@@ -317,7 +317,7 @@ static void fsl_chan_set_request_count(struct fsl_dma_chan *fsl_chan, int size)
+  * The DMA Request Count feature should be used in addition to this feature
+  * to set the number of bytes to transfer before pausing the channel.
+  */
+-static void fsl_chan_toggle_ext_pause(struct fsl_dma_chan *fsl_chan, int enable)
++static void fsl_chan_toggle_ext_pause(struct fsldma_chan *fsl_chan, int enable)
+ {
+ 	if (enable)
+ 		fsl_chan->feature |= FSL_DMA_CHAN_PAUSE_EXT;
+@@ -335,7 +335,7 @@ static void fsl_chan_toggle_ext_pause(struct fsl_dma_chan *fsl_chan, int enable)
+  * transfer immediately. The DMA channel will wait for the
+  * control pin asserted.
+  */
+-static void fsl_chan_toggle_ext_start(struct fsl_dma_chan *fsl_chan, int enable)
++static void fsl_chan_toggle_ext_start(struct fsldma_chan *fsl_chan, int enable)
+ {
+ 	if (enable)
+ 		fsl_chan->feature |= FSL_DMA_CHAN_START_EXT;
+@@ -345,7 +345,7 @@ static void fsl_chan_toggle_ext_start(struct fsl_dma_chan *fsl_chan, int enable)
+ 
+ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
+ {
+-	struct fsl_dma_chan *fsl_chan = to_fsl_chan(tx->chan);
++	struct fsldma_chan *fsl_chan = to_fsl_chan(tx->chan);
+ 	struct fsl_desc_sw *desc = tx_to_fsl_desc(tx);
+ 	struct fsl_desc_sw *child;
+ 	unsigned long flags;
+@@ -379,7 +379,7 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
+  * Return - The descriptor allocated. NULL for failed.
+  */
+ static struct fsl_desc_sw *fsl_dma_alloc_descriptor(
+-					struct fsl_dma_chan *fsl_chan)
++					struct fsldma_chan *fsl_chan)
+ {
+ 	dma_addr_t pdesc;
+ 	struct fsl_desc_sw *desc_sw;
+@@ -408,7 +408,7 @@ static struct fsl_desc_sw *fsl_dma_alloc_descriptor(
+  */
+ static int fsl_dma_alloc_chan_resources(struct dma_chan *chan)
+ {
+-	struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan);
++	struct fsldma_chan *fsl_chan = to_fsl_chan(chan);
+ 
+ 	/* Has this channel already been allocated? */
+ 	if (fsl_chan->desc_pool)
+@@ -435,7 +435,7 @@ static int fsl_dma_alloc_chan_resources(struct dma_chan *chan)
+  */
+ static void fsl_dma_free_chan_resources(struct dma_chan *chan)
+ {
+-	struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan);
++	struct fsldma_chan *fsl_chan = to_fsl_chan(chan);
+ 	struct fsl_desc_sw *desc, *_desc;
+ 	unsigned long flags;
+ 
+@@ -459,7 +459,7 @@ static void fsl_dma_free_chan_resources(struct dma_chan *chan)
+ static struct dma_async_tx_descriptor *
+ fsl_dma_prep_interrupt(struct dma_chan *chan, unsigned long flags)
+ {
+-	struct fsl_dma_chan *fsl_chan;
++	struct fsldma_chan *fsl_chan;
+ 	struct fsl_desc_sw *new;
+ 
+ 	if (!chan)
+@@ -489,7 +489,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+ 	struct dma_chan *chan, dma_addr_t dma_dest, dma_addr_t dma_src,
+ 	size_t len, unsigned long flags)
+ {
+-	struct fsl_dma_chan *fsl_chan;
++	struct fsldma_chan *fsl_chan;
+ 	struct fsl_desc_sw *first = NULL, *prev = NULL, *new;
+ 	struct list_head *list;
+ 	size_t copy;
+@@ -575,7 +575,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
+ 	struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len,
+ 	enum dma_data_direction direction, unsigned long flags)
+ {
+-	struct fsl_dma_chan *fsl_chan;
++	struct fsldma_chan *fsl_chan;
+ 	struct fsl_desc_sw *first = NULL, *prev = NULL, *new = NULL;
+ 	struct fsl_dma_slave *slave;
+ 	struct list_head *tx_list;
+@@ -759,7 +759,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
+ 
+ static void fsl_dma_device_terminate_all(struct dma_chan *chan)
+ {
+-	struct fsl_dma_chan *fsl_chan;
++	struct fsldma_chan *fsl_chan;
+ 	struct fsl_desc_sw *desc, *tmp;
+ 	unsigned long flags;
+ 
+@@ -786,7 +786,7 @@ static void fsl_dma_device_terminate_all(struct dma_chan *chan)
+  * fsl_dma_update_completed_cookie - Update the completed cookie.
+  * @fsl_chan : Freescale DMA channel
+  */
+-static void fsl_dma_update_completed_cookie(struct fsl_dma_chan *fsl_chan)
++static void fsl_dma_update_completed_cookie(struct fsldma_chan *fsl_chan)
+ {
+ 	struct fsl_desc_sw *cur_desc, *desc;
+ 	dma_addr_t ld_phy;
+@@ -820,7 +820,7 @@ static void fsl_dma_update_completed_cookie(struct fsl_dma_chan *fsl_chan)
+  * If 'in_intr' is set, the function will move the link descriptor to
+  * the recycle list. Otherwise, free it directly.
+  */
+-static void fsl_chan_ld_cleanup(struct fsl_dma_chan *fsl_chan)
++static void fsl_chan_ld_cleanup(struct fsldma_chan *fsl_chan)
+ {
+ 	struct fsl_desc_sw *desc, *_desc;
+ 	unsigned long flags;
+@@ -864,7 +864,7 @@ static void fsl_chan_ld_cleanup(struct fsl_dma_chan *fsl_chan)
+  * fsl_chan_xfer_ld_queue - Transfer link descriptors in channel ld_queue.
+  * @fsl_chan : Freescale DMA channel
+  */
+-static void fsl_chan_xfer_ld_queue(struct fsl_dma_chan *fsl_chan)
++static void fsl_chan_xfer_ld_queue(struct fsldma_chan *fsl_chan)
+ {
+ 	struct list_head *ld_node;
+ 	dma_addr_t next_dest_addr;
+@@ -912,7 +912,7 @@ static void fsl_chan_xfer_ld_queue(struct fsl_dma_chan *fsl_chan)
+  */
+ static void fsl_dma_memcpy_issue_pending(struct dma_chan *chan)
+ {
+-	struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan);
++	struct fsldma_chan *fsl_chan = to_fsl_chan(chan);
+ 
+ #ifdef FSL_DMA_LD_DEBUG
+ 	struct fsl_desc_sw *ld;
+@@ -949,7 +949,7 @@ static enum dma_status fsl_dma_is_complete(struct dma_chan *chan,
+ 					dma_cookie_t *done,
+ 					dma_cookie_t *used)
+ {
+-	struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan);
++	struct fsldma_chan *fsl_chan = to_fsl_chan(chan);
+ 	dma_cookie_t last_used;
+ 	dma_cookie_t last_complete;
+ 
+@@ -969,7 +969,7 @@ static enum dma_status fsl_dma_is_complete(struct dma_chan *chan,
+ 
+ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
+ {
+-	struct fsl_dma_chan *fsl_chan = (struct fsl_dma_chan *)data;
++	struct fsldma_chan *fsl_chan = data;
+ 	u32 stat;
+ 	int update_cookie = 0;
+ 	int xfer_ld_q = 0;
+@@ -1050,9 +1050,9 @@ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
+ 
+ static irqreturn_t fsl_dma_do_interrupt(int irq, void *data)
+ {
+-	struct fsl_dma_device *fdev = (struct fsl_dma_device *)data;
+-	u32 gsr;
++	struct fsldma_device *fdev = data;
+ 	int ch_nr;
++	u32 gsr;
+ 
+ 	gsr = (fdev->feature & FSL_DMA_BIG_ENDIAN) ? in_be32(fdev->reg_base)
+ 			: in_le32(fdev->reg_base);
+@@ -1064,19 +1064,23 @@ static irqreturn_t fsl_dma_do_interrupt(int irq, void *data)
+ 
+ static void dma_do_tasklet(unsigned long data)
+ {
+-	struct fsl_dma_chan *fsl_chan = (struct fsl_dma_chan *)data;
++	struct fsldma_chan *fsl_chan = (struct fsldma_chan *)data;
+ 	fsl_chan_ld_cleanup(fsl_chan);
+ }
+ 
+-static int __devinit fsl_dma_chan_probe(struct fsl_dma_device *fdev,
++/*----------------------------------------------------------------------------*/
++/* OpenFirmware Subsystem                                                     */
++/*----------------------------------------------------------------------------*/
++
++static int __devinit fsl_dma_chan_probe(struct fsldma_device *fdev,
+ 	struct device_node *node, u32 feature, const char *compatible)
+ {
+-	struct fsl_dma_chan *new_fsl_chan;
++	struct fsldma_chan *new_fsl_chan;
+ 	struct resource res;
+ 	int err;
+ 
+ 	/* alloc channel */
+-	new_fsl_chan = kzalloc(sizeof(struct fsl_dma_chan), GFP_KERNEL);
++	new_fsl_chan = kzalloc(sizeof(*new_fsl_chan), GFP_KERNEL);
+ 	if (!new_fsl_chan) {
+ 		dev_err(fdev->dev, "No free memory for allocating "
+ 				"dma channels!\n");
+@@ -1167,7 +1171,7 @@ static int __devinit fsl_dma_chan_probe(struct fsl_dma_device *fdev,
+ 	return err;
+ }
+ 
+-static void fsl_dma_chan_remove(struct fsl_dma_chan *fchan)
++static void fsl_dma_chan_remove(struct fsldma_chan *fchan)
+ {
+ 	if (fchan->irq != NO_IRQ)
+ 		free_irq(fchan->irq, fchan);
+@@ -1176,15 +1180,15 @@ static void fsl_dma_chan_remove(struct fsl_dma_chan *fchan)
+ 	kfree(fchan);
+ }
+ 
+-static int __devinit of_fsl_dma_probe(struct of_device *dev,
++static int __devinit fsldma_of_probe(struct of_device *dev,
+ 			const struct of_device_id *match)
+ {
+ 	int err;
+-	struct fsl_dma_device *fdev;
++	struct fsldma_device *fdev;
+ 	struct device_node *child;
+ 	struct resource res;
+ 
+-	fdev = kzalloc(sizeof(struct fsl_dma_device), GFP_KERNEL);
++	fdev = kzalloc(sizeof(*fdev), GFP_KERNEL);
+ 	if (!fdev) {
+ 		dev_err(&dev->dev, "No enough memory for 'priv'\n");
+ 		return -ENOMEM;
+@@ -1256,9 +1260,9 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev,
+ 	return err;
+ }
+ 
+-static int of_fsl_dma_remove(struct of_device *of_dev)
++static int fsldma_of_remove(struct of_device *of_dev)
+ {
+-	struct fsl_dma_device *fdev;
++	struct fsldma_device *fdev;
+ 	unsigned int i;
+ 
+ 	fdev = dev_get_drvdata(&of_dev->dev);
+@@ -1280,39 +1284,43 @@ static int of_fsl_dma_remove(struct of_device *of_dev)
+ 	return 0;
+ }
+ 
+-static struct of_device_id of_fsl_dma_ids[] = {
++static struct of_device_id fsldma_of_ids[] = {
+ 	{ .compatible = "fsl,eloplus-dma", },
+ 	{ .compatible = "fsl,elo-dma", },
+ 	{}
+ };
+ 
+-static struct of_platform_driver of_fsl_dma_driver = {
+-	.name = "fsl-elo-dma",
+-	.match_table = of_fsl_dma_ids,
+-	.probe = of_fsl_dma_probe,
+-	.remove = of_fsl_dma_remove,
++static struct of_platform_driver fsldma_of_driver = {
++	.name		= "fsl-elo-dma",
++	.match_table	= fsldma_of_ids,
++	.probe		= fsldma_of_probe,
++	.remove		= fsldma_of_remove,
+ };
+ 
+-static __init int of_fsl_dma_init(void)
++/*----------------------------------------------------------------------------*/
++/* Module Init / Exit                                                         */
++/*----------------------------------------------------------------------------*/
++
++static __init int fsldma_init(void)
+ {
+ 	int ret;
+ 
+ 	pr_info("Freescale Elo / Elo Plus DMA driver\n");
+ 
+-	ret = of_register_platform_driver(&of_fsl_dma_driver);
++	ret = of_register_platform_driver(&fsldma_of_driver);
+ 	if (ret)
+ 		pr_err("fsldma: failed to register platform driver\n");
+ 
+ 	return ret;
+ }
+ 
+-static void __exit of_fsl_dma_exit(void)
++static void __exit fsldma_exit(void)
+ {
+-	of_unregister_platform_driver(&of_fsl_dma_driver);
++	of_unregister_platform_driver(&fsldma_of_driver);
+ }
+ 
+-subsys_initcall(of_fsl_dma_init);
+-module_exit(of_fsl_dma_exit);
++subsys_initcall(fsldma_init);
++module_exit(fsldma_exit);
+ 
+ MODULE_DESCRIPTION("Freescale Elo / Elo Plus DMA driver");
+ MODULE_LICENSE("GPL");
+diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
+index dbb5b5cce4c2..f8c2baa6f41e 100644
+--- a/drivers/dma/fsldma.h
++++ b/drivers/dma/fsldma.h
+@@ -94,7 +94,7 @@ struct fsl_desc_sw {
+ 	struct dma_async_tx_descriptor async_tx;
+ } __attribute__((aligned(32)));
+ 
+-struct fsl_dma_chan_regs {
++struct fsldma_chan_regs {
+ 	u32 mr;	/* 0x00 - Mode Register */
+ 	u32 sr;	/* 0x04 - Status Register */
+ 	u64 cdar;	/* 0x08 - Current descriptor address register */
+@@ -104,19 +104,19 @@ struct fsl_dma_chan_regs {
+ 	u64 ndar;	/* 0x24 - Next Descriptor Address Register */
+ };
+ 
+-struct fsl_dma_chan;
++struct fsldma_chan;
+ #define FSL_DMA_MAX_CHANS_PER_DEVICE 4
+ 
+-struct fsl_dma_device {
++struct fsldma_device {
+ 	void __iomem *reg_base;	/* DGSR register base */
+ 	struct device *dev;
+ 	struct dma_device common;
+-	struct fsl_dma_chan *chan[FSL_DMA_MAX_CHANS_PER_DEVICE];
++	struct fsldma_chan *chan[FSL_DMA_MAX_CHANS_PER_DEVICE];
+ 	u32 feature;		/* The same as DMA channels */
+ 	int irq;		/* Channel IRQ */
+ };
+ 
+-/* Define macros for fsl_dma_chan->feature property */
++/* Define macros for fsldma_chan->feature property */
+ #define FSL_DMA_LITTLE_ENDIAN	0x00000000
+ #define FSL_DMA_BIG_ENDIAN	0x00000001
+ 
+@@ -127,8 +127,8 @@ struct fsl_dma_device {
+ #define FSL_DMA_CHAN_PAUSE_EXT	0x00001000
+ #define FSL_DMA_CHAN_START_EXT	0x00002000
+ 
+-struct fsl_dma_chan {
+-	struct fsl_dma_chan_regs __iomem *reg_base;
++struct fsldma_chan {
++	struct fsldma_chan_regs __iomem *reg_base;
+ 	dma_cookie_t completed_cookie;	/* The maximum cookie completed */
+ 	spinlock_t desc_lock;		/* Descriptor operation lock */
+ 	struct list_head ld_queue;	/* Link descriptors queue */
+@@ -140,14 +140,14 @@ struct fsl_dma_chan {
+ 	struct tasklet_struct tasklet;
+ 	u32 feature;
+ 
+-	void (*toggle_ext_pause)(struct fsl_dma_chan *fsl_chan, int enable);
+-	void (*toggle_ext_start)(struct fsl_dma_chan *fsl_chan, int enable);
+-	void (*set_src_loop_size)(struct fsl_dma_chan *fsl_chan, int size);
+-	void (*set_dest_loop_size)(struct fsl_dma_chan *fsl_chan, int size);
+-	void (*set_request_count)(struct fsl_dma_chan *fsl_chan, int size);
++	void (*toggle_ext_pause)(struct fsldma_chan *fsl_chan, int enable);
++	void (*toggle_ext_start)(struct fsldma_chan *fsl_chan, int enable);
++	void (*set_src_loop_size)(struct fsldma_chan *fsl_chan, int size);
++	void (*set_dest_loop_size)(struct fsldma_chan *fsl_chan, int size);
++	void (*set_request_count)(struct fsldma_chan *fsl_chan, int size);
+ };
+ 
+-#define to_fsl_chan(chan) container_of(chan, struct fsl_dma_chan, common)
++#define to_fsl_chan(chan) container_of(chan, struct fsldma_chan, common)
+ #define to_fsl_desc(lh) container_of(lh, struct fsl_desc_sw, node)
+ #define tx_to_fsl_desc(tx) container_of(tx, struct fsl_desc_sw, async_tx)
+ 

commit 4ce0e953f6286777452bf07c83056342d6b9b257
+Author: Ira Snyder 
+Date:   Wed Jan 6 13:34:00 2010 +0000
+
+    fsldma: remove unused structure members
+    
+    Remove some unused members from the fsldma data structures. A few trivial
+    uses of struct resource were converted to use the stack rather than keeping
+    the memory allocated for the lifetime of the driver.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Dan Williams 
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index 0bad741765c6..0b4e6383f480 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -1072,6 +1072,7 @@ static int __devinit fsl_dma_chan_probe(struct fsl_dma_device *fdev,
+ 	struct device_node *node, u32 feature, const char *compatible)
+ {
+ 	struct fsl_dma_chan *new_fsl_chan;
++	struct resource res;
+ 	int err;
+ 
+ 	/* alloc channel */
+@@ -1083,7 +1084,7 @@ static int __devinit fsl_dma_chan_probe(struct fsl_dma_device *fdev,
+ 	}
+ 
+ 	/* get dma channel register base */
+-	err = of_address_to_resource(node, 0, &new_fsl_chan->reg);
++	err = of_address_to_resource(node, 0, &res);
+ 	if (err) {
+ 		dev_err(fdev->dev, "Can't get %s property 'reg'\n",
+ 				node->full_name);
+@@ -1101,10 +1102,8 @@ static int __devinit fsl_dma_chan_probe(struct fsl_dma_device *fdev,
+ 	WARN_ON(fdev->feature != new_fsl_chan->feature);
+ 
+ 	new_fsl_chan->dev = fdev->dev;
+-	new_fsl_chan->reg_base = ioremap(new_fsl_chan->reg.start,
+-			new_fsl_chan->reg.end - new_fsl_chan->reg.start + 1);
+-
+-	new_fsl_chan->id = ((new_fsl_chan->reg.start - 0x100) & 0xfff) >> 7;
++	new_fsl_chan->reg_base = ioremap(res.start, resource_size(&res));
++	new_fsl_chan->id = ((res.start - 0x100) & 0xfff) >> 7;
+ 	if (new_fsl_chan->id >= FSL_DMA_MAX_CHANS_PER_DEVICE) {
+ 		dev_err(fdev->dev, "There is no %d channel!\n",
+ 				new_fsl_chan->id);
+@@ -1183,6 +1182,7 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev,
+ 	int err;
+ 	struct fsl_dma_device *fdev;
+ 	struct device_node *child;
++	struct resource res;
+ 
+ 	fdev = kzalloc(sizeof(struct fsl_dma_device), GFP_KERNEL);
+ 	if (!fdev) {
+@@ -1193,7 +1193,7 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev,
+ 	INIT_LIST_HEAD(&fdev->common.channels);
+ 
+ 	/* get DMA controller register base */
+-	err = of_address_to_resource(dev->node, 0, &fdev->reg);
++	err = of_address_to_resource(dev->node, 0, &res);
+ 	if (err) {
+ 		dev_err(&dev->dev, "Can't get %s property 'reg'\n",
+ 				dev->node->full_name);
+@@ -1202,9 +1202,8 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev,
+ 
+ 	dev_info(&dev->dev, "Probe the Freescale DMA driver for %s "
+ 			"controller at 0x%llx...\n",
+-			match->compatible, (unsigned long long)fdev->reg.start);
+-	fdev->reg_base = ioremap(fdev->reg.start, fdev->reg.end
+-						- fdev->reg.start + 1);
++			match->compatible, (unsigned long long)res.start);
++	fdev->reg_base = ioremap(res.start, resource_size(&res));
+ 
+ 	dma_cap_set(DMA_MEMCPY, fdev->common.cap_mask);
+ 	dma_cap_set(DMA_INTERRUPT, fdev->common.cap_mask);
+diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
+index 0df14cbb8ca3..dbb5b5cce4c2 100644
+--- a/drivers/dma/fsldma.h
++++ b/drivers/dma/fsldma.h
+@@ -92,8 +92,6 @@ struct fsl_desc_sw {
+ 	struct list_head node;
+ 	struct list_head tx_list;
+ 	struct dma_async_tx_descriptor async_tx;
+-	struct list_head *ld;
+-	void *priv;
+ } __attribute__((aligned(32)));
+ 
+ struct fsl_dma_chan_regs {
+@@ -111,7 +109,6 @@ struct fsl_dma_chan;
+ 
+ struct fsl_dma_device {
+ 	void __iomem *reg_base;	/* DGSR register base */
+-	struct resource reg;	/* Resource for register */
+ 	struct device *dev;
+ 	struct dma_device common;
+ 	struct fsl_dma_chan *chan[FSL_DMA_MAX_CHANS_PER_DEVICE];
+@@ -138,7 +135,6 @@ struct fsl_dma_chan {
+ 	struct dma_chan common;		/* DMA common channel */
+ 	struct dma_pool *desc_pool;	/* Descriptors pool */
+ 	struct device *dev;		/* Channel device */
+-	struct resource reg;		/* Resource for register */
+ 	int irq;			/* Channel IRQ */
+ 	int id;				/* Raw id of this channel */
+ 	struct tasklet_struct tasklet;

commit 272ca655090978bdaa2630fc44fb2c03da5576fd
+Author: Ira Snyder 
+Date:   Wed Jan 6 13:33:59 2010 +0000
+
+    fsldma: reduce kernel text size
+    
+    Some of the functions are written in a way where they use multiple reads
+    and writes where a single read/write pair could suffice. This shrinks the
+    kernel text size measurably, while making the functions easier to
+    understand.
+    
+    add/remove: 0/0 grow/shrink: 1/4 up/down: 4/-196 (-192)
+    function                                     old     new   delta
+    fsl_chan_set_request_count                   120     124      +4
+    dma_halt                                     300     272     -28
+    fsl_chan_set_src_loop_size                   208     156     -52
+    fsl_chan_set_dest_loop_size                  208     156     -52
+    fsl_chan_xfer_ld_queue                       500     436     -64
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Dan Williams 
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index 296f9e747fac..0bad741765c6 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -143,43 +143,45 @@ static int dma_is_idle(struct fsl_dma_chan *fsl_chan)
+ 
+ static void dma_start(struct fsl_dma_chan *fsl_chan)
+ {
+-	u32 mr_set = 0;
+-
+-	if (fsl_chan->feature & FSL_DMA_CHAN_PAUSE_EXT) {
+-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->bcr, 0, 32);
+-		mr_set |= FSL_DMA_MR_EMP_EN;
+-	} else if ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
+-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
+-			DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32)
+-				& ~FSL_DMA_MR_EMP_EN, 32);
++	u32 mode;
++
++	mode = DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32);
++
++	if ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
++		if (fsl_chan->feature & FSL_DMA_CHAN_PAUSE_EXT) {
++			DMA_OUT(fsl_chan, &fsl_chan->reg_base->bcr, 0, 32);
++			mode |= FSL_DMA_MR_EMP_EN;
++		} else {
++			mode &= ~FSL_DMA_MR_EMP_EN;
++		}
+ 	}
+ 
+ 	if (fsl_chan->feature & FSL_DMA_CHAN_START_EXT)
+-		mr_set |= FSL_DMA_MR_EMS_EN;
++		mode |= FSL_DMA_MR_EMS_EN;
+ 	else
+-		mr_set |= FSL_DMA_MR_CS;
++		mode |= FSL_DMA_MR_CS;
+ 
+-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
+-			DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32)
+-			| mr_set, 32);
++	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, mode, 32);
+ }
+ 
+ static void dma_halt(struct fsl_dma_chan *fsl_chan)
+ {
++	u32 mode;
+ 	int i;
+ 
+-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
+-		DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) | FSL_DMA_MR_CA,
+-		32);
+-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
+-		DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) & ~(FSL_DMA_MR_CS
+-		| FSL_DMA_MR_EMS_EN | FSL_DMA_MR_CA), 32);
++	mode = DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32);
++	mode |= FSL_DMA_MR_CA;
++	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, mode, 32);
++
++	mode &= ~(FSL_DMA_MR_CS | FSL_DMA_MR_EMS_EN | FSL_DMA_MR_CA);
++	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, mode, 32);
+ 
+ 	for (i = 0; i < 100; i++) {
+ 		if (dma_is_idle(fsl_chan))
+ 			break;
+ 		udelay(10);
+ 	}
++
+ 	if (i >= 100 && !dma_is_idle(fsl_chan))
+ 		dev_err(fsl_chan->dev, "DMA halt timeout!\n");
+ }
+@@ -231,22 +233,23 @@ static void append_ld_queue(struct fsl_dma_chan *fsl_chan,
+  */
+ static void fsl_chan_set_src_loop_size(struct fsl_dma_chan *fsl_chan, int size)
+ {
++	u32 mode;
++
++	mode = DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32);
++
+ 	switch (size) {
+ 	case 0:
+-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
+-			DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) &
+-			(~FSL_DMA_MR_SAHE), 32);
++		mode &= ~FSL_DMA_MR_SAHE;
+ 		break;
+ 	case 1:
+ 	case 2:
+ 	case 4:
+ 	case 8:
+-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
+-			DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) |
+-			FSL_DMA_MR_SAHE | (__ilog2(size) << 14),
+-			32);
++		mode |= FSL_DMA_MR_SAHE | (__ilog2(size) << 14);
+ 		break;
+ 	}
++
++	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, mode, 32);
+ }
+ 
+ /**
+@@ -262,22 +265,23 @@ static void fsl_chan_set_src_loop_size(struct fsl_dma_chan *fsl_chan, int size)
+  */
+ static void fsl_chan_set_dest_loop_size(struct fsl_dma_chan *fsl_chan, int size)
+ {
++	u32 mode;
++
++	mode = DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32);
++
+ 	switch (size) {
+ 	case 0:
+-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
+-			DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) &
+-			(~FSL_DMA_MR_DAHE), 32);
++		mode &= ~FSL_DMA_MR_DAHE;
+ 		break;
+ 	case 1:
+ 	case 2:
+ 	case 4:
+ 	case 8:
+-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
+-			DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) |
+-			FSL_DMA_MR_DAHE | (__ilog2(size) << 16),
+-			32);
++		mode |= FSL_DMA_MR_DAHE | (__ilog2(size) << 16);
+ 		break;
+ 	}
++
++	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, mode, 32);
+ }
+ 
+ /**
+@@ -294,11 +298,14 @@ static void fsl_chan_set_dest_loop_size(struct fsl_dma_chan *fsl_chan, int size)
+  */
+ static void fsl_chan_set_request_count(struct fsl_dma_chan *fsl_chan, int size)
+ {
++	u32 mode;
++
+ 	BUG_ON(size > 1024);
+-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
+-		DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32)
+-			| ((__ilog2(size) << 24) & 0x0f000000),
+-		32);
++
++	mode = DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32);
++	mode |= (__ilog2(size) << 24) & 0x0f000000;
++
++	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, mode, 32);
+ }
+ 
+ /**

commit 0616fb003d4f799c4be62275242fc7ff9a968f84
+Author: Ira W. Snyder 
+Date:   Mon Oct 26 16:50:10 2009 -0700
+
+    edac: i5400 fix missing CONFIG_PCI define
+    
+    When building without CONFIG_PCI the edac_pci_idx variable is unused,
+    causing a build-time warning.  Wrap the variable in #ifdef CONFIG_PCI,
+    just like the rest of the PCI support.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Doug Thompson 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
+index 157f6504f25e..cf27402af97b 100644
+--- a/drivers/edac/mpc85xx_edac.c
++++ b/drivers/edac/mpc85xx_edac.c
+@@ -26,7 +26,9 @@
+ #include "mpc85xx_edac.h"
+ 
+ static int edac_dev_idx;
++#ifdef CONFIG_PCI
+ static int edac_pci_idx;
++#endif
+ static int edac_mc_idx;
+ 
+ static u32 orig_ddr_err_disable;

commit b4846251727a38a7f248e41308c060995371dd05
+Author: Ira W. Snyder 
+Date:   Wed Sep 23 15:57:25 2009 -0700
+
+    edac: mpc85xx add mpc83xx support
+    
+    Add support for the Freescale MPC83xx memory controller to the existing
+    driver for the Freescale MPC85xx memory controller.  The only difference
+    between the two processors are in the CS_BNDS register parsing code, which
+    has been changed so it will work on both processors.
+    
+    The L2 cache controller does not exist on the MPC83xx, but the OF
+    subsystem will not use the driver if the device is not present in the OF
+    device tree.
+    
+    I had to change the nr_pages calculation to make the math work out.  I
+    checked it on my board and did the math by hand for a 64GB 85xx using 64K
+    pages.  In both cases, nr_pages * PAGE_SIZE comes out to the correct
+    value.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Doug Thompson 
+    Cc: Kumar Gala 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
+index a3ca18e2d7cf..b82ad57c1082 100644
+--- a/drivers/edac/Kconfig
++++ b/drivers/edac/Kconfig
+@@ -176,11 +176,11 @@ config EDAC_I5100
+ 	  San Clemente MCH.
+ 
+ config EDAC_MPC85XX
+-	tristate "Freescale MPC85xx"
+-	depends on EDAC_MM_EDAC && FSL_SOC && MPC85xx
++	tristate "Freescale MPC83xx / MPC85xx"
++	depends on EDAC_MM_EDAC && FSL_SOC && (PPC_83xx || MPC85xx)
+ 	help
+ 	  Support for error detection and correction on the Freescale
+-	  MPC8560, MPC8540, MPC8548
++	  MPC8349, MPC8560, MPC8540, MPC8548
+ 
+ config EDAC_MV64X60
+ 	tristate "Marvell MV64x60"
+diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
+index 1dd405e0e550..157f6504f25e 100644
+--- a/drivers/edac/mpc85xx_edac.c
++++ b/drivers/edac/mpc85xx_edac.c
+@@ -41,7 +41,9 @@ static u32 orig_pci_err_en;
+ #endif
+ 
+ static u32 orig_l2_err_disable;
++#ifdef CONFIG_MPC85xx
+ static u32 orig_hid1[2];
++#endif
+ 
+ /************************ MC SYSFS parts ***********************************/
+ 
+@@ -789,19 +791,20 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci)
+ 		csrow = &mci->csrows[index];
+ 		cs_bnds = in_be32(pdata->mc_vbase + MPC85XX_MC_CS_BNDS_0 +
+ 				  (index * MPC85XX_MC_CS_BNDS_OFS));
+-		start = (cs_bnds & 0xfff0000) << 4;
+-		end = ((cs_bnds & 0xfff) << 20);
+-		if (start)
+-			start |= 0xfffff;
+-		if (end)
+-			end |= 0xfffff;
++
++		start = (cs_bnds & 0xffff0000) >> 16;
++		end   = (cs_bnds & 0x0000ffff);
+ 
+ 		if (start == end)
+ 			continue;	/* not populated */
+ 
++		start <<= (24 - PAGE_SHIFT);
++		end   <<= (24 - PAGE_SHIFT);
++		end    |= (1 << (24 - PAGE_SHIFT)) - 1;
++
+ 		csrow->first_page = start >> PAGE_SHIFT;
+ 		csrow->last_page = end >> PAGE_SHIFT;
+-		csrow->nr_pages = csrow->last_page + 1 - csrow->first_page;
++		csrow->nr_pages = end + 1 - start;
+ 		csrow->grain = 8;
+ 		csrow->mtype = mtype;
+ 		csrow->dtype = DEV_UNKNOWN;
+@@ -985,6 +988,7 @@ static struct of_device_id mpc85xx_mc_err_of_match[] = {
+ 	{ .compatible = "fsl,mpc8560-memory-controller", },
+ 	{ .compatible = "fsl,mpc8568-memory-controller", },
+ 	{ .compatible = "fsl,mpc8572-memory-controller", },
++	{ .compatible = "fsl,mpc8349-memory-controller", },
+ 	{ .compatible = "fsl,p2020-memory-controller", },
+ 	{},
+ };
+@@ -1001,13 +1005,13 @@ static struct of_platform_driver mpc85xx_mc_err_driver = {
+ 		   },
+ };
+ 
+-
++#ifdef CONFIG_MPC85xx
+ static void __init mpc85xx_mc_clear_rfxe(void *data)
+ {
+ 	orig_hid1[smp_processor_id()] = mfspr(SPRN_HID1);
+ 	mtspr(SPRN_HID1, (orig_hid1[smp_processor_id()] & ~0x20000));
+ }
+-
++#endif
+ 
+ static int __init mpc85xx_mc_init(void)
+ {
+@@ -1040,26 +1044,32 @@ static int __init mpc85xx_mc_init(void)
+ 		printk(KERN_WARNING EDAC_MOD_STR "PCI fails to register\n");
+ #endif
+ 
++#ifdef CONFIG_MPC85xx
+ 	/*
+ 	 * need to clear HID1[RFXE] to disable machine check int
+ 	 * so we can catch it
+ 	 */
+ 	if (edac_op_state == EDAC_OPSTATE_INT)
+ 		on_each_cpu(mpc85xx_mc_clear_rfxe, NULL, 0);
++#endif
+ 
+ 	return 0;
+ }
+ 
+ module_init(mpc85xx_mc_init);
+ 
++#ifdef CONFIG_MPC85xx
+ static void __exit mpc85xx_mc_restore_hid1(void *data)
+ {
+ 	mtspr(SPRN_HID1, orig_hid1[smp_processor_id()]);
+ }
++#endif
+ 
+ static void __exit mpc85xx_mc_exit(void)
+ {
++#ifdef CONFIG_MPC85xx
+ 	on_each_cpu(mpc85xx_mc_restore_hid1, NULL, 0);
++#endif
+ #ifdef CONFIG_PCI
+ 	of_unregister_platform_driver(&mpc85xx_pci_err_driver);
+ #endif

commit 58f055e5314856a3badfa61fe144347903488989
+Author: Ira W. Snyder 
+Date:   Wed Sep 23 22:59:44 2009 +0200
+
+    hwmon: (ltc4245) Clear faults at startup
+    
+    When power is applied to the ltc4245 chip it sometimes reports spurious
+    faults, which are exposed as alarms in the hwmon output. Clear the fault
+    register when the driver is installed to clear the alarms.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Jean Delvare 
+
+diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c
+index 034b2c515848..e38964333612 100644
+--- a/drivers/hwmon/ltc4245.c
++++ b/drivers/hwmon/ltc4245.c
+@@ -382,7 +382,8 @@ static int ltc4245_probe(struct i2c_client *client,
+ 	mutex_init(&data->update_lock);
+ 
+ 	/* Initialize the LTC4245 chip */
+-	/* TODO */
++	i2c_smbus_write_byte_data(client, LTC4245_FAULT1, 0x00);
++	i2c_smbus_write_byte_data(client, LTC4245_FAULT2, 0x00);
+ 
+ 	/* Register sysfs hooks */
+ 	ret = sysfs_create_group(&client->dev.kobj, <c4245_group);

commit b6b9d69602aec2c869dd2ca730aab2cc58473c2d
+Author: Ira W. Snyder 
+Date:   Wed Sep 23 22:59:43 2009 +0200
+
+    hwmon: (ltc4215) Clear faults at startup
+    
+    When power is applied to the ltc4215 chip it sometimes reports spurious
+    faults. The faults are not yet exposed via sysfs, however it may be useful
+    for userspace to read the fault register directly with the i2cget command.
+    Clear the fault register when the driver is installed so userspace doesn't
+    have to worry about spurious fault indications.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Jean Delvare 
+
+diff --git a/drivers/hwmon/ltc4215.c b/drivers/hwmon/ltc4215.c
+index 9386e2a39211..6c9a04136e0a 100644
+--- a/drivers/hwmon/ltc4215.c
++++ b/drivers/hwmon/ltc4215.c
+@@ -259,7 +259,7 @@ static int ltc4215_probe(struct i2c_client *client,
+ 	mutex_init(&data->update_lock);
+ 
+ 	/* Initialize the LTC4215 chip */
+-	/* TODO */
++	i2c_smbus_write_byte_data(client, LTC4215_FAULT, 0x00);
+ 
+ 	/* Register sysfs hooks */
+ 	ret = sysfs_create_group(&client->dev.kobj, <c4215_group);

commit 49dc9efed05ad3e49000097ce1ec31cd3bbc909b
+Author: Ira Snyder 
+Date:   Wed Sep 23 22:59:41 2009 +0200
+
+    hwmon: (adm1031) Add sysfs files for temperature offsets
+    
+    The ADM1030/ADM1031 chips have temperature offset registers, for both the
+    local and remote temperature sensors. Following the example set forth in
+    the LM90/ADM1032 driver, expose the offset registers to userspace.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Jean Delvare 
+
+diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c
+index 789441830cd8..56905955352c 100644
+--- a/drivers/hwmon/adm1031.c
++++ b/drivers/hwmon/adm1031.c
+@@ -37,6 +37,7 @@
+ #define ADM1031_REG_PWM			(0x22)
+ #define ADM1031_REG_FAN_MIN(nr)		(0x10 + (nr))
+ 
++#define ADM1031_REG_TEMP_OFFSET(nr)	(0x0d + (nr))
+ #define ADM1031_REG_TEMP_MAX(nr)	(0x14 + 4 * (nr))
+ #define ADM1031_REG_TEMP_MIN(nr)	(0x15 + 4 * (nr))
+ #define ADM1031_REG_TEMP_CRIT(nr)	(0x16 + 4 * (nr))
+@@ -93,6 +94,7 @@ struct adm1031_data {
+ 	u8 auto_temp_min[3];
+ 	u8 auto_temp_off[3];
+ 	u8 auto_temp_max[3];
++	s8 temp_offset[3];
+ 	s8 temp_min[3];
+ 	s8 temp_max[3];
+ 	s8 temp_crit[3];
+@@ -145,6 +147,10 @@ adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int value)
+ 
+ #define TEMP_FROM_REG_EXT(val, ext)	(TEMP_FROM_REG(val) + (ext) * 125)
+ 
++#define TEMP_OFFSET_TO_REG(val)		(TEMP_TO_REG(val) & 0x8f)
++#define TEMP_OFFSET_FROM_REG(val)	TEMP_FROM_REG((val) < 0 ? \
++						      (val) | 0x70 : (val))
++
+ #define FAN_FROM_REG(reg, div)		((reg) ? (11250 * 60) / ((reg) * (div)) : 0)
+ 
+ static int FAN_TO_REG(int reg, int div)
+@@ -585,6 +591,14 @@ static ssize_t show_temp(struct device *dev,
+ 	    (((data->ext_temp[nr] >> ((nr - 1) * 3)) & 7));
+ 	return sprintf(buf, "%d\n", TEMP_FROM_REG_EXT(data->temp[nr], ext));
+ }
++static ssize_t show_temp_offset(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	int nr = to_sensor_dev_attr(attr)->index;
++	struct adm1031_data *data = adm1031_update_device(dev);
++	return sprintf(buf, "%d\n",
++		       TEMP_OFFSET_FROM_REG(data->temp_offset[nr]));
++}
+ static ssize_t show_temp_min(struct device *dev,
+ 			     struct device_attribute *attr, char *buf)
+ {
+@@ -606,6 +620,24 @@ static ssize_t show_temp_crit(struct device *dev,
+ 	struct adm1031_data *data = adm1031_update_device(dev);
+ 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr]));
+ }
++static ssize_t set_temp_offset(struct device *dev,
++			       struct device_attribute *attr, const char *buf,
++			       size_t count)
++{
++	struct i2c_client *client = to_i2c_client(dev);
++	struct adm1031_data *data = i2c_get_clientdata(client);
++	int nr = to_sensor_dev_attr(attr)->index;
++	int val;
++
++	val = simple_strtol(buf, NULL, 10);
++	val = SENSORS_LIMIT(val, -15000, 15000);
++	mutex_lock(&data->update_lock);
++	data->temp_offset[nr] = TEMP_OFFSET_TO_REG(val);
++	adm1031_write_value(client, ADM1031_REG_TEMP_OFFSET(nr),
++			    data->temp_offset[nr]);
++	mutex_unlock(&data->update_lock);
++	return count;
++}
+ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
+ 			    const char *buf, size_t count)
+ {
+@@ -661,6 +693,8 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
+ #define temp_reg(offset)						\
+ static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO,		\
+ 		show_temp, NULL, offset - 1);				\
++static SENSOR_DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR,	\
++		show_temp_offset, set_temp_offset, offset - 1);		\
+ static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR,	\
+ 		show_temp_min, set_temp_min, offset - 1);		\
+ static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,	\
+@@ -714,6 +748,7 @@ static struct attribute *adm1031_attributes[] = {
+ 	&sensor_dev_attr_pwm1.dev_attr.attr,
+ 	&sensor_dev_attr_auto_fan1_channel.dev_attr.attr,
+ 	&sensor_dev_attr_temp1_input.dev_attr.attr,
++	&sensor_dev_attr_temp1_offset.dev_attr.attr,
+ 	&sensor_dev_attr_temp1_min.dev_attr.attr,
+ 	&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
+ 	&sensor_dev_attr_temp1_max.dev_attr.attr,
+@@ -721,6 +756,7 @@ static struct attribute *adm1031_attributes[] = {
+ 	&sensor_dev_attr_temp1_crit.dev_attr.attr,
+ 	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
+ 	&sensor_dev_attr_temp2_input.dev_attr.attr,
++	&sensor_dev_attr_temp2_offset.dev_attr.attr,
+ 	&sensor_dev_attr_temp2_min.dev_attr.attr,
+ 	&sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
+ 	&sensor_dev_attr_temp2_max.dev_attr.attr,
+@@ -757,6 +793,7 @@ static struct attribute *adm1031_attributes_opt[] = {
+ 	&sensor_dev_attr_pwm2.dev_attr.attr,
+ 	&sensor_dev_attr_auto_fan2_channel.dev_attr.attr,
+ 	&sensor_dev_attr_temp3_input.dev_attr.attr,
++	&sensor_dev_attr_temp3_offset.dev_attr.attr,
+ 	&sensor_dev_attr_temp3_min.dev_attr.attr,
+ 	&sensor_dev_attr_temp3_min_alarm.dev_attr.attr,
+ 	&sensor_dev_attr_temp3_max.dev_attr.attr,
+@@ -937,6 +974,9 @@ static struct adm1031_data *adm1031_update_device(struct device *dev)
+ 			}
+ 			data->temp[chan] = newh;
+ 
++			data->temp_offset[chan] =
++			    adm1031_read_value(client,
++					       ADM1031_REG_TEMP_OFFSET(chan));
+ 			data->temp_min[chan] =
+ 			    adm1031_read_value(client,
+ 					       ADM1031_REG_TEMP_MIN(chan));

commit bbea0b6e0d214ef1511b9c6ccf3af26b38f0af7d
+Author: Ira Snyder 
+Date:   Tue Sep 8 17:53:04 2009 -0700
+
+    fsldma: Add DMA_SLAVE support
+    
+    Use the DMA_SLAVE capability of the DMAEngine API to copy/from a
+    scatterlist into an arbitrary list of hardware address/length pairs.
+    
+    This allows a single DMA transaction to copy data from several different
+    devices into a scatterlist at the same time.
+    
+    This also adds support to enable some controller-specific features such as
+    external start and external pause for a DMA transaction.
+    
+    [dan.j.williams@intel.com: rebased on tx_list movement]
+    Signed-off-by: Ira W. Snyder 
+    Acked-by: Li Yang 
+    Acked-by: Kumar Gala 
+    Signed-off-by: Dan Williams 
+
+diff --git a/arch/powerpc/include/asm/fsldma.h b/arch/powerpc/include/asm/fsldma.h
+new file mode 100644
+index 000000000000..a67aeed17d40
+--- /dev/null
++++ b/arch/powerpc/include/asm/fsldma.h
+@@ -0,0 +1,136 @@
++/*
++ * Freescale MPC83XX / MPC85XX DMA Controller
++ *
++ * Copyright (c) 2009 Ira W. Snyder 
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++#ifndef __ARCH_POWERPC_ASM_FSLDMA_H__
++#define __ARCH_POWERPC_ASM_FSLDMA_H__
++
++#include 
++
++/*
++ * Definitions for the Freescale DMA controller's DMA_SLAVE implemention
++ *
++ * The Freescale DMA_SLAVE implementation was designed to handle many-to-many
++ * transfers. An example usage would be an accelerated copy between two
++ * scatterlists. Another example use would be an accelerated copy from
++ * multiple non-contiguous device buffers into a single scatterlist.
++ *
++ * A DMA_SLAVE transaction is defined by a struct fsl_dma_slave. This
++ * structure contains a list of hardware addresses that should be copied
++ * to/from the scatterlist passed into device_prep_slave_sg(). The structure
++ * also has some fields to enable hardware-specific features.
++ */
++
++/**
++ * struct fsl_dma_hw_addr
++ * @entry: linked list entry
++ * @address: the hardware address
++ * @length: length to transfer
++ *
++ * Holds a single physical hardware address / length pair for use
++ * with the DMAEngine DMA_SLAVE API.
++ */
++struct fsl_dma_hw_addr {
++	struct list_head entry;
++
++	dma_addr_t address;
++	size_t length;
++};
++
++/**
++ * struct fsl_dma_slave
++ * @addresses: a linked list of struct fsl_dma_hw_addr structures
++ * @request_count: value for DMA request count
++ * @src_loop_size: setup and enable constant source-address DMA transfers
++ * @dst_loop_size: setup and enable constant destination address DMA transfers
++ * @external_start: enable externally started DMA transfers
++ * @external_pause: enable externally paused DMA transfers
++ *
++ * Holds a list of address / length pairs for use with the DMAEngine
++ * DMA_SLAVE API implementation for the Freescale DMA controller.
++ */
++struct fsl_dma_slave {
++
++	/* List of hardware address/length pairs */
++	struct list_head addresses;
++
++	/* Support for extra controller features */
++	unsigned int request_count;
++	unsigned int src_loop_size;
++	unsigned int dst_loop_size;
++	bool external_start;
++	bool external_pause;
++};
++
++/**
++ * fsl_dma_slave_append - add an address/length pair to a struct fsl_dma_slave
++ * @slave: the &struct fsl_dma_slave to add to
++ * @address: the hardware address to add
++ * @length: the length of bytes to transfer from @address
++ *
++ * Add a hardware address/length pair to a struct fsl_dma_slave. Returns 0 on
++ * success, -ERRNO otherwise.
++ */
++static inline int fsl_dma_slave_append(struct fsl_dma_slave *slave,
++				       dma_addr_t address, size_t length)
++{
++	struct fsl_dma_hw_addr *addr;
++
++	addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
++	if (!addr)
++		return -ENOMEM;
++
++	INIT_LIST_HEAD(&addr->entry);
++	addr->address = address;
++	addr->length = length;
++
++	list_add_tail(&addr->entry, &slave->addresses);
++	return 0;
++}
++
++/**
++ * fsl_dma_slave_free - free a struct fsl_dma_slave
++ * @slave: the struct fsl_dma_slave to free
++ *
++ * Free a struct fsl_dma_slave and all associated address/length pairs
++ */
++static inline void fsl_dma_slave_free(struct fsl_dma_slave *slave)
++{
++	struct fsl_dma_hw_addr *addr, *tmp;
++
++	if (slave) {
++		list_for_each_entry_safe(addr, tmp, &slave->addresses, entry) {
++			list_del(&addr->entry);
++			kfree(addr);
++		}
++
++		kfree(slave);
++	}
++}
++
++/**
++ * fsl_dma_slave_alloc - allocate a struct fsl_dma_slave
++ * @gfp: the flags to pass to kmalloc when allocating this structure
++ *
++ * Allocate a struct fsl_dma_slave for use by the DMA_SLAVE API. Returns a new
++ * struct fsl_dma_slave on success, or NULL on failure.
++ */
++static inline struct fsl_dma_slave *fsl_dma_slave_alloc(gfp_t gfp)
++{
++	struct fsl_dma_slave *slave;
++
++	slave = kzalloc(sizeof(*slave), gfp);
++	if (!slave)
++		return NULL;
++
++	INIT_LIST_HEAD(&slave->addresses);
++	return slave;
++}
++
++#endif /* __ARCH_POWERPC_ASM_FSLDMA_H__ */
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index 7a0cb6064f83..296f9e747fac 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -34,6 +34,7 @@
+ #include 
+ #include 
+ 
++#include 
+ #include "fsldma.h"
+ 
+ static void dma_init(struct fsl_dma_chan *fsl_chan)
+@@ -551,6 +552,229 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+ 	return NULL;
+ }
+ 
++/**
++ * fsl_dma_prep_slave_sg - prepare descriptors for a DMA_SLAVE transaction
++ * @chan: DMA channel
++ * @sgl: scatterlist to transfer to/from
++ * @sg_len: number of entries in @scatterlist
++ * @direction: DMA direction
++ * @flags: DMAEngine flags
++ *
++ * Prepare a set of descriptors for a DMA_SLAVE transaction. Following the
++ * DMA_SLAVE API, this gets the device-specific information from the
++ * chan->private variable.
++ */
++static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
++	struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len,
++	enum dma_data_direction direction, unsigned long flags)
++{
++	struct fsl_dma_chan *fsl_chan;
++	struct fsl_desc_sw *first = NULL, *prev = NULL, *new = NULL;
++	struct fsl_dma_slave *slave;
++	struct list_head *tx_list;
++	size_t copy;
++
++	int i;
++	struct scatterlist *sg;
++	size_t sg_used;
++	size_t hw_used;
++	struct fsl_dma_hw_addr *hw;
++	dma_addr_t dma_dst, dma_src;
++
++	if (!chan)
++		return NULL;
++
++	if (!chan->private)
++		return NULL;
++
++	fsl_chan = to_fsl_chan(chan);
++	slave = chan->private;
++
++	if (list_empty(&slave->addresses))
++		return NULL;
++
++	hw = list_first_entry(&slave->addresses, struct fsl_dma_hw_addr, entry);
++	hw_used = 0;
++
++	/*
++	 * Build the hardware transaction to copy from the scatterlist to
++	 * the hardware, or from the hardware to the scatterlist
++	 *
++	 * If you are copying from the hardware to the scatterlist and it
++	 * takes two hardware entries to fill an entire page, then both
++	 * hardware entries will be coalesced into the same page
++	 *
++	 * If you are copying from the scatterlist to the hardware and a
++	 * single page can fill two hardware entries, then the data will
++	 * be read out of the page into the first hardware entry, and so on
++	 */
++	for_each_sg(sgl, sg, sg_len, i) {
++		sg_used = 0;
++
++		/* Loop until the entire scatterlist entry is used */
++		while (sg_used < sg_dma_len(sg)) {
++
++			/*
++			 * If we've used up the current hardware address/length
++			 * pair, we need to load a new one
++			 *
++			 * This is done in a while loop so that descriptors with
++			 * length == 0 will be skipped
++			 */
++			while (hw_used >= hw->length) {
++
++				/*
++				 * If the current hardware entry is the last
++				 * entry in the list, we're finished
++				 */
++				if (list_is_last(&hw->entry, &slave->addresses))
++					goto finished;
++
++				/* Get the next hardware address/length pair */
++				hw = list_entry(hw->entry.next,
++						struct fsl_dma_hw_addr, entry);
++				hw_used = 0;
++			}
++
++			/* Allocate the link descriptor from DMA pool */
++			new = fsl_dma_alloc_descriptor(fsl_chan);
++			if (!new) {
++				dev_err(fsl_chan->dev, "No free memory for "
++						       "link descriptor\n");
++				goto fail;
++			}
++#ifdef FSL_DMA_LD_DEBUG
++			dev_dbg(fsl_chan->dev, "new link desc alloc %p\n", new);
++#endif
++
++			/*
++			 * Calculate the maximum number of bytes to transfer,
++			 * making sure it is less than the DMA controller limit
++			 */
++			copy = min_t(size_t, sg_dma_len(sg) - sg_used,
++					     hw->length - hw_used);
++			copy = min_t(size_t, copy, FSL_DMA_BCR_MAX_CNT);
++
++			/*
++			 * DMA_FROM_DEVICE
++			 * from the hardware to the scatterlist
++			 *
++			 * DMA_TO_DEVICE
++			 * from the scatterlist to the hardware
++			 */
++			if (direction == DMA_FROM_DEVICE) {
++				dma_src = hw->address + hw_used;
++				dma_dst = sg_dma_address(sg) + sg_used;
++			} else {
++				dma_src = sg_dma_address(sg) + sg_used;
++				dma_dst = hw->address + hw_used;
++			}
++
++			/* Fill in the descriptor */
++			set_desc_cnt(fsl_chan, &new->hw, copy);
++			set_desc_src(fsl_chan, &new->hw, dma_src);
++			set_desc_dest(fsl_chan, &new->hw, dma_dst);
++
++			/*
++			 * If this is not the first descriptor, chain the
++			 * current descriptor after the previous descriptor
++			 */
++			if (!first) {
++				first = new;
++			} else {
++				set_desc_next(fsl_chan, &prev->hw,
++					      new->async_tx.phys);
++			}
++
++			new->async_tx.cookie = 0;
++			async_tx_ack(&new->async_tx);
++
++			prev = new;
++			sg_used += copy;
++			hw_used += copy;
++
++			/* Insert the link descriptor into the LD ring */
++			list_add_tail(&new->node, &first->tx_list);
++		}
++	}
++
++finished:
++
++	/* All of the hardware address/length pairs had length == 0 */
++	if (!first || !new)
++		return NULL;
++
++	new->async_tx.flags = flags;
++	new->async_tx.cookie = -EBUSY;
++
++	/* Set End-of-link to the last link descriptor of new list */
++	set_ld_eol(fsl_chan, new);
++
++	/* Enable extra controller features */
++	if (fsl_chan->set_src_loop_size)
++		fsl_chan->set_src_loop_size(fsl_chan, slave->src_loop_size);
++
++	if (fsl_chan->set_dest_loop_size)
++		fsl_chan->set_dest_loop_size(fsl_chan, slave->dst_loop_size);
++
++	if (fsl_chan->toggle_ext_start)
++		fsl_chan->toggle_ext_start(fsl_chan, slave->external_start);
++
++	if (fsl_chan->toggle_ext_pause)
++		fsl_chan->toggle_ext_pause(fsl_chan, slave->external_pause);
++
++	if (fsl_chan->set_request_count)
++		fsl_chan->set_request_count(fsl_chan, slave->request_count);
++
++	return &first->async_tx;
++
++fail:
++	/* If first was not set, then we failed to allocate the very first
++	 * descriptor, and we're done */
++	if (!first)
++		return NULL;
++
++	/*
++	 * First is set, so all of the descriptors we allocated have been added
++	 * to first->tx_list, INCLUDING "first" itself. Therefore we
++	 * must traverse the list backwards freeing each descriptor in turn
++	 *
++	 * We're re-using variables for the loop, oh well
++	 */
++	tx_list = &first->tx_list;
++	list_for_each_entry_safe_reverse(new, prev, tx_list, node) {
++		list_del_init(&new->node);
++		dma_pool_free(fsl_chan->desc_pool, new, new->async_tx.phys);
++	}
++
++	return NULL;
++}
++
++static void fsl_dma_device_terminate_all(struct dma_chan *chan)
++{
++	struct fsl_dma_chan *fsl_chan;
++	struct fsl_desc_sw *desc, *tmp;
++	unsigned long flags;
++
++	if (!chan)
++		return;
++
++	fsl_chan = to_fsl_chan(chan);
++
++	/* Halt the DMA engine */
++	dma_halt(fsl_chan);
++
++	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
++
++	/* Remove and free all of the descriptors in the LD queue */
++	list_for_each_entry_safe(desc, tmp, &fsl_chan->ld_queue, node) {
++		list_del(&desc->node);
++		dma_pool_free(fsl_chan->desc_pool, desc, desc->async_tx.phys);
++	}
++
++	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
++}
++
+ /**
+  * fsl_dma_update_completed_cookie - Update the completed cookie.
+  * @fsl_chan : Freescale DMA channel
+@@ -977,12 +1201,15 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev,
+ 
+ 	dma_cap_set(DMA_MEMCPY, fdev->common.cap_mask);
+ 	dma_cap_set(DMA_INTERRUPT, fdev->common.cap_mask);
++	dma_cap_set(DMA_SLAVE, fdev->common.cap_mask);
+ 	fdev->common.device_alloc_chan_resources = fsl_dma_alloc_chan_resources;
+ 	fdev->common.device_free_chan_resources = fsl_dma_free_chan_resources;
+ 	fdev->common.device_prep_dma_interrupt = fsl_dma_prep_interrupt;
+ 	fdev->common.device_prep_dma_memcpy = fsl_dma_prep_memcpy;
+ 	fdev->common.device_is_tx_complete = fsl_dma_is_complete;
+ 	fdev->common.device_issue_pending = fsl_dma_memcpy_issue_pending;
++	fdev->common.device_prep_slave_sg = fsl_dma_prep_slave_sg;
++	fdev->common.device_terminate_all = fsl_dma_device_terminate_all;
+ 	fdev->common.dev = &dev->dev;
+ 
+ 	fdev->irq = irq_of_parse_and_map(dev->node, 0);

commit e6c7ecb64e08ef346cb7062b4a5421f00bc602bd
+Author: Ira Snyder 
+Date:   Tue Sep 8 17:53:04 2009 -0700
+
+    fsldma: split apart external pause and request count features
+    
+    When using the Freescale DMA controller in external control mode, both the
+    request count and external pause bits need to be setup correctly. This was
+    being done with the same function.
+    
+    The 83xx controller lacks the external pause feature, but has a similar
+    feature called external start. This feature requires that the request count
+    bits be setup correctly.
+    
+    Split the function into two parts, to make it possible to use the external
+    start feature on the 83xx controller.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Dan Williams 
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index 73dd74823195..7a0cb6064f83 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -280,28 +280,40 @@ static void fsl_chan_set_dest_loop_size(struct fsl_dma_chan *fsl_chan, int size)
+ }
+ 
+ /**
+- * fsl_chan_toggle_ext_pause - Toggle channel external pause status
++ * fsl_chan_set_request_count - Set DMA Request Count for external control
+  * @fsl_chan : Freescale DMA channel
+- * @size     : Pause control size, 0 for disable external pause control.
+- *             The maximum is 1024.
++ * @size     : Number of bytes to transfer in a single request
++ *
++ * The Freescale DMA channel can be controlled by the external signal DREQ#.
++ * The DMA request count is how many bytes are allowed to transfer before
++ * pausing the channel, after which a new assertion of DREQ# resumes channel
++ * operation.
+  *
+- * The Freescale DMA channel can be controlled by the external
+- * signal DREQ#. The pause control size is how many bytes are allowed
+- * to transfer before pausing the channel, after which a new assertion
+- * of DREQ# resumes channel operation.
++ * A size of 0 disables external pause control. The maximum size is 1024.
+  */
+-static void fsl_chan_toggle_ext_pause(struct fsl_dma_chan *fsl_chan, int size)
++static void fsl_chan_set_request_count(struct fsl_dma_chan *fsl_chan, int size)
+ {
+-	if (size > 1024)
+-		return;
++	BUG_ON(size > 1024);
++	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
++		DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32)
++			| ((__ilog2(size) << 24) & 0x0f000000),
++		32);
++}
+ 
+-	if (size) {
+-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
+-			DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32)
+-				| ((__ilog2(size) << 24) & 0x0f000000),
+-			32);
++/**
++ * fsl_chan_toggle_ext_pause - Toggle channel external pause status
++ * @fsl_chan : Freescale DMA channel
++ * @enable   : 0 is disabled, 1 is enabled.
++ *
++ * The Freescale DMA channel can be controlled by the external signal DREQ#.
++ * The DMA Request Count feature should be used in addition to this feature
++ * to set the number of bytes to transfer before pausing the channel.
++ */
++static void fsl_chan_toggle_ext_pause(struct fsl_dma_chan *fsl_chan, int enable)
++{
++	if (enable)
+ 		fsl_chan->feature |= FSL_DMA_CHAN_PAUSE_EXT;
+-	} else
++	else
+ 		fsl_chan->feature &= ~FSL_DMA_CHAN_PAUSE_EXT;
+ }
+ 
+@@ -885,6 +897,7 @@ static int __devinit fsl_dma_chan_probe(struct fsl_dma_device *fdev,
+ 		new_fsl_chan->toggle_ext_start = fsl_chan_toggle_ext_start;
+ 		new_fsl_chan->set_src_loop_size = fsl_chan_set_src_loop_size;
+ 		new_fsl_chan->set_dest_loop_size = fsl_chan_set_dest_loop_size;
++		new_fsl_chan->set_request_count = fsl_chan_set_request_count;
+ 	}
+ 
+ 	spin_lock_init(&new_fsl_chan->desc_lock);
+diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
+index 4493afed53f0..0df14cbb8ca3 100644
+--- a/drivers/dma/fsldma.h
++++ b/drivers/dma/fsldma.h
+@@ -144,10 +144,11 @@ struct fsl_dma_chan {
+ 	struct tasklet_struct tasklet;
+ 	u32 feature;
+ 
+-	void (*toggle_ext_pause)(struct fsl_dma_chan *fsl_chan, int size);
++	void (*toggle_ext_pause)(struct fsl_dma_chan *fsl_chan, int enable);
+ 	void (*toggle_ext_start)(struct fsl_dma_chan *fsl_chan, int enable);
+ 	void (*set_src_loop_size)(struct fsl_dma_chan *fsl_chan, int size);
+ 	void (*set_dest_loop_size)(struct fsl_dma_chan *fsl_chan, int size);
++	void (*set_request_count)(struct fsl_dma_chan *fsl_chan, int size);
+ };
+ 
+ #define to_fsl_chan(chan) container_of(chan, struct fsl_dma_chan, common)

commit 43a1a3ed6bf5a1b9ae197b4f5f20033baf19db61
+Author: Ira Snyder 
+Date:   Thu May 28 09:26:40 2009 +0000
+
+    fsldma: do not clear bandwidth control bits on the 83xx controller
+    
+    The 83xx controller does not support the external pause feature. The bit
+    in the mode register that controls external pause on the 85xx controller
+    happens to be part of the bandwidth control settings for the 83xx
+    controller.
+    
+    This patch fixes the driver so that it only clears the external pause bit
+    if the hardware is the 85xx controller. When driving the 83xx controller,
+    the bit is left untouched. This follows the existing convention that mode
+    registers settings are not touched unless necessary.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Dan Williams 
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index 10bcf0cb0efc..6e60c77a145c 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -147,10 +147,11 @@ static void dma_start(struct fsl_dma_chan *fsl_chan)
+ 	if (fsl_chan->feature & FSL_DMA_CHAN_PAUSE_EXT) {
+ 		DMA_OUT(fsl_chan, &fsl_chan->reg_base->bcr, 0, 32);
+ 		mr_set |= FSL_DMA_MR_EMP_EN;
+-	} else
++	} else if ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
+ 		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
+ 			DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32)
+ 				& ~FSL_DMA_MR_EMP_EN, 32);
++	}
+ 
+ 	if (fsl_chan->feature & FSL_DMA_CHAN_START_EXT)
+ 		mr_set |= FSL_DMA_MR_EMS_EN;

commit be30b226f2ae618cd719e40267d9923db1db9001
+Author: Ira Snyder 
+Date:   Thu May 28 09:20:42 2009 +0000
+
+    fsldma: enable external start for the 83xx controller
+    
+    The 83xx controller has external start capability, but lacks external pause
+    capability. Hook up the external start function pointer for the 83xx
+    controller.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Dan Williams 
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index a1cb25e277b5..10bcf0cb0efc 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -877,9 +877,9 @@ static int __devinit fsl_dma_chan_probe(struct fsl_dma_device *fdev,
+ 
+ 	switch (new_fsl_chan->feature & FSL_DMA_IP_MASK) {
+ 	case FSL_DMA_IP_85XX:
+-		new_fsl_chan->toggle_ext_start = fsl_chan_toggle_ext_start;
+ 		new_fsl_chan->toggle_ext_pause = fsl_chan_toggle_ext_pause;
+ 	case FSL_DMA_IP_83XX:
++		new_fsl_chan->toggle_ext_start = fsl_chan_toggle_ext_start;
+ 		new_fsl_chan->set_src_loop_size = fsl_chan_set_src_loop_size;
+ 		new_fsl_chan->set_dest_loop_size = fsl_chan_set_dest_loop_size;
+ 	}

commit a7aea373b4ca428f1be2c1fedd2f26c8e3f2864d
+Author: Ira W. Snyder 
+Date:   Thu Apr 23 16:17:54 2009 -0700
+
+    fsldma: use PCI Read Multiple command
+    
+    By default, the Freescale 83xx DMA controller uses the PCI Read Line
+    command when reading data over the PCI bus. Setting the controller to use
+    the PCI Read Multiple command instead allows the controller to read much
+    larger bursts of data, which provides a drastic speed increase.
+    
+    The slowdown due to using PCI Read Line was only observed when a PCI-to-PCI
+    bridge was between the devices trying to communicate.
+    
+    A simple test driver showed an increase from 4MB/sec to 116MB/sec when
+    performing DMA over the PCI bus. Using DMA to transfer between blocks of
+    local SDRAM showed no change in performance with this patch. The dmatest
+    driver was also used to verify the correctness of the transfers, and showed
+    no errors.
+    
+    Signed-off-by: Ira W. Snyder 
+    Acked-by: Timur Tabi 
+    Acked-by: Kumar Gala 
+    Signed-off-by: Dan Williams 
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index f18d1bde0439..a1cb25e277b5 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -12,6 +12,11 @@
+  *   also fit for MPC8560, MPC8555, MPC8548, MPC8641, and etc.
+  *   The support for MPC8349 DMA contorller is also added.
+  *
++ * This driver instructs the DMA controller to issue the PCI Read Multiple
++ * command for PCI read operations, instead of using the default PCI Read Line
++ * command. Please be aware that this setting may result in read pre-fetching
++ * on some platforms.
++ *
+  * This is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+  * the Free Software Foundation; either version 2 of the License, or
+@@ -49,9 +54,10 @@ static void dma_init(struct fsl_dma_chan *fsl_chan)
+ 	case FSL_DMA_IP_83XX:
+ 		/* Set the channel to below modes:
+ 		 * EOTIE - End-of-transfer interrupt enable
++		 * PRC_RM - PCI read multiple
+ 		 */
+-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, FSL_DMA_MR_EOTIE,
+-				32);
++		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, FSL_DMA_MR_EOTIE
++				| FSL_DMA_MR_PRC_RM, 32);
+ 		break;
+ 	}
+ 
+diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
+index 4f21a512d848..dc7f26865797 100644
+--- a/drivers/dma/fsldma.h
++++ b/drivers/dma/fsldma.h
+@@ -38,6 +38,7 @@
+ 
+ /* Special MR definition for MPC8349 */
+ #define FSL_DMA_MR_EOTIE	0x00000080
++#define FSL_DMA_MR_PRC_RM	0x00000800
+ 
+ #define FSL_DMA_SR_CH		0x00000020
+ #define FSL_DMA_SR_PE		0x00000010

commit 2e077f8e8337e52eef3c39c24c31e103b11a0326
+Author: Ira Snyder 
+Date:   Fri May 15 09:59:46 2009 -0700
+
+    fsldma: fix memory leak on error path in fsl_dma_prep_memcpy()
+    
+    When preparing a memcpy operation, if the kernel fails to allocate memory
+    for a link descriptor after the first link descriptor has already been
+    allocated, then some memory will never be released. Fix the problem by
+    walking the list of allocated descriptors backwards, and freeing the
+    allocated descriptors back into the DMA pool.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Li Yang 
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index ff9194d7ebb7..15783102bf17 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -462,8 +462,8 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+ {
+ 	struct fsl_dma_chan *fsl_chan;
+ 	struct fsl_desc_sw *first = NULL, *prev = NULL, *new;
++	struct list_head *list;
+ 	size_t copy;
+-	LIST_HEAD(link_chain);
+ 
+ 	if (!chan)
+ 		return NULL;
+@@ -480,7 +480,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+ 		if (!new) {
+ 			dev_err(fsl_chan->dev,
+ 					"No free memory for link descriptor\n");
+-			return NULL;
++			goto fail;
+ 		}
+ #ifdef FSL_DMA_LD_DEBUG
+ 		dev_dbg(fsl_chan->dev, "new link desc alloc %p\n", new);
+@@ -515,7 +515,19 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+ 	/* Set End-of-link to the last link descriptor of new list*/
+ 	set_ld_eol(fsl_chan, new);
+ 
+-	return first ? &first->async_tx : NULL;
++	return &first->async_tx;
++
++fail:
++	if (!first)
++		return NULL;
++
++	list = &first->async_tx.tx_list;
++	list_for_each_entry_safe_reverse(new, prev, list, node) {
++		list_del(&new->node);
++		dma_pool_free(fsl_chan->desc_pool, new, new->async_tx.phys);
++	}
++
++	return NULL;
+ }
+ 
+ /**

commit 776c8943f2766f2819fafd88fdfbaf418ecd6e41
+Author: Ira Snyder 
+Date:   Fri May 15 11:33:20 2009 -0700
+
+    fsldma: snooping is not enabled for last entry in descriptor chain
+    
+    On the 83xx controller, snooping is necessary for the DMA controller to
+    ensure cache coherence with the CPU when transferring to/from RAM.
+    
+    The last descriptor in a chain will always have the End-of-Chain interrupt
+    bit set, so we can set the snoop bit while adding the End-of-Chain
+    interrupt bit.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Li Yang 
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index 7313a1ae5f83..ff9194d7ebb7 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -179,9 +179,14 @@ static void dma_halt(struct fsl_dma_chan *fsl_chan)
+ static void set_ld_eol(struct fsl_dma_chan *fsl_chan,
+ 			struct fsl_desc_sw *desc)
+ {
++	u64 snoop_bits;
++
++	snoop_bits = ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_83XX)
++		? FSL_DMA_SNEN : 0;
++
+ 	desc->hw.next_ln_addr = CPU_TO_DMA(fsl_chan,
+-		DMA_TO_CPU(fsl_chan, desc->hw.next_ln_addr, 64)	| FSL_DMA_EOL,
+-		64);
++		DMA_TO_CPU(fsl_chan, desc->hw.next_ln_addr, 64) | FSL_DMA_EOL
++			| snoop_bits, 64);
+ }
+ 
+ static void append_ld_queue(struct fsl_dma_chan *fsl_chan,

commit bcfb7465c03a8c62c89da374677df56f6b894d44
+Author: Ira Snyder 
+Date:   Fri May 15 14:27:16 2009 -0700
+
+    fsldma: fix infinite loop on multi-descriptor DMA chain completion
+    
+    When creating a DMA transaction with multiple descriptors, the async_tx
+    cookie is set to 0 for each descriptor in the chain, excluding the last
+    descriptor, whose cookie is set to -EBUSY.
+    
+    When fsl_dma_tx_submit() is run, it only assigns a cookie to the first
+    descriptor. All of the remaining descriptors keep their original value,
+    including the last descriptor, which is set to -EBUSY.
+    
+    After the DMA completes, the driver will update the last completed cookie
+    to be -EBUSY, which is an error code instead of a valid cookie. This causes
+    dma_async_is_complete() to always return DMA_IN_PROGRESS.
+    
+    This causes the fsldma driver to never cleanup the queue of link
+    descriptors, and the driver will re-run the DMA transaction on the hardware
+    each time it receives the End-of-Chain interrupt. This causes an infinite
+    loop.
+    
+    With this patch, fsl_dma_tx_submit() is changed to assign a cookie to every
+    descriptor in the chain. The rest of the code then works without problems.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Li Yang 
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index a4151c3bb78b..7313a1ae5f83 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -313,8 +313,8 @@ static void fsl_chan_toggle_ext_start(struct fsl_dma_chan *fsl_chan, int enable)
+ 
+ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
+ {
+-	struct fsl_desc_sw *desc = tx_to_fsl_desc(tx);
+ 	struct fsl_dma_chan *fsl_chan = to_fsl_chan(tx->chan);
++	struct fsl_desc_sw *desc;
+ 	unsigned long flags;
+ 	dma_cookie_t cookie;
+ 
+@@ -322,14 +322,17 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
+ 	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
+ 
+ 	cookie = fsl_chan->common.cookie;
+-	cookie++;
+-	if (cookie < 0)
+-		cookie = 1;
+-	desc->async_tx.cookie = cookie;
+-	fsl_chan->common.cookie = desc->async_tx.cookie;
+-
+-	append_ld_queue(fsl_chan, desc);
+-	list_splice_init(&desc->async_tx.tx_list, fsl_chan->ld_queue.prev);
++	list_for_each_entry(desc, &tx->tx_list, node) {
++		cookie++;
++		if (cookie < 0)
++			cookie = 1;
++
++		desc->async_tx.cookie = cookie;
++	}
++
++	fsl_chan->common.cookie = cookie;
++	append_ld_queue(fsl_chan, tx_to_fsl_desc(tx));
++	list_splice_init(&tx->tx_list, fsl_chan->ld_queue.prev);
+ 
+ 	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
+ 

commit 138ef0185177a6d221d24b6aa8f12d867fbbef90
+Author: Ira Snyder 
+Date:   Tue May 19 15:42:13 2009 -0700
+
+    fsldma: fix "DMA halt timeout!" errors
+    
+    When using the DMA controller from multiple threads at the same time, it is
+    possible to get lots of "DMA halt timeout!" errors printed to the kernel
+    log.
+    
+    This occurs due to a race between fsl_dma_memcpy_issue_pending() and the
+    interrupt handler, fsl_dma_chan_do_interrupt(). Both call the
+    fsl_chan_xfer_ld_queue() function, which does not protect against
+    concurrent accesses to dma_halt() and dma_start().
+    
+    The existing spinlock is moved to cover the dma_halt() and dma_start()
+    functions. Testing shows that the "DMA halt timeout!" errors disappear.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Li Yang 
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index 391b1bd7098b..a4151c3bb78b 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -598,15 +598,16 @@ static void fsl_chan_xfer_ld_queue(struct fsl_dma_chan *fsl_chan)
+ 	dma_addr_t next_dest_addr;
+ 	unsigned long flags;
+ 
++	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
++
+ 	if (!dma_is_idle(fsl_chan))
+-		return;
++		goto out_unlock;
+ 
+ 	dma_halt(fsl_chan);
+ 
+ 	/* If there are some link descriptors
+ 	 * not transfered in queue. We need to start it.
+ 	 */
+-	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
+ 
+ 	/* Find the first un-transfer desciptor */
+ 	for (ld_node = fsl_chan->ld_queue.next;
+@@ -617,8 +618,6 @@ static void fsl_chan_xfer_ld_queue(struct fsl_dma_chan *fsl_chan)
+ 				fsl_chan->common.cookie) == DMA_SUCCESS);
+ 		ld_node = ld_node->next);
+ 
+-	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
+-
+ 	if (ld_node != &fsl_chan->ld_queue) {
+ 		/* Get the ld start address from ld_queue */
+ 		next_dest_addr = to_fsl_desc(ld_node)->async_tx.phys;
+@@ -630,6 +629,9 @@ static void fsl_chan_xfer_ld_queue(struct fsl_dma_chan *fsl_chan)
+ 		set_cdar(fsl_chan, 0);
+ 		set_ndar(fsl_chan, 0);
+ 	}
++
++out_unlock:
++	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
+ }
+ 
+ /**

commit 72f5de92e199f96cfcea125aefc76c138d8c553c
+Author: Ira Snyder 
+Date:   Tue Mar 31 15:24:29 2009 -0700
+
+    hwmon: Add LTC4215 driver
+    
+    Add Linux support for the Linear Technology LTC4215 Hot Swap controller
+    I2C monitoring interface.
+    
+    I have tested the driver with my board, and it appears to work fine.  With
+    the power supplies disabled, it reads 11.93V input, 1.93V output, no
+    current and no power.  With the supplies enabled, it reads 11.93V input,
+    11.98V output, no current, no power.  I'm not drawing any current at the
+    moment, so this is reasonable.  The value in the sense register never
+    reads anything except 0, so I expect to get zero from the current and
+    power calculations.
+    
+    I didn't attempt to support changing any of the chip's settings or
+    enabling the FET.  I'm not sure even how to do that and still fit within
+    the hwmon framework.  :)
+    
+    Signed-off-by: Ira W. Snyder 
+    Cc: Jean Delvare 
+    Cc: "Mark M. Hoffman" 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/Documentation/hwmon/ltc4215 b/Documentation/hwmon/ltc4215
+new file mode 100644
+index 000000000000..2e6a21eb656c
+--- /dev/null
++++ b/Documentation/hwmon/ltc4215
+@@ -0,0 +1,50 @@
++Kernel driver ltc4215
++=====================
++
++Supported chips:
++  * Linear Technology LTC4215
++    Prefix: 'ltc4215'
++    Addresses scanned: 0x44
++    Datasheet:
++        http://www.linear.com/pc/downloadDocument.do?navId=H0,C1,C1003,C1006,C1163,P17572,D12697
++
++Author: Ira W. Snyder 
++
++
++Description
++-----------
++
++The LTC4215 controller allows a board to be safely inserted and removed
++from a live backplane.
++
++
++Usage Notes
++-----------
++
++This driver does not probe for LTC4215 devices, due to the fact that some
++of the possible addresses are unfriendly to probing. You will need to use
++the "force" parameter to tell the driver where to find the device.
++
++Example: the following will load the driver for an LTC4215 at address 0x44
++on I2C bus #0:
++$ modprobe ltc4215 force=0,0x44
++
++
++Sysfs entries
++-------------
++
++The LTC4215 has built-in limits for overvoltage, undervoltage, and
++undercurrent warnings. This makes it very likely that the reference
++circuit will be used.
++
++in1_input		input voltage
++in2_input		output voltage
++
++in1_min_alarm		input undervoltage alarm
++in1_max_alarm		input overvoltage alarm
++
++curr1_input		current
++curr1_max_alarm		overcurrent alarm
++
++power1_input		power usage
++power1_alarm		power bad alarm
+diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
+index 8a91c9971558..bc6810c22dd7 100644
+--- a/drivers/hwmon/Kconfig
++++ b/drivers/hwmon/Kconfig
+@@ -571,6 +571,17 @@ config SENSORS_LM93
+ 	  This driver can also be built as a module.  If so, the module
+ 	  will be called lm93.
+ 
++config SENSORS_LTC4215
++	tristate "Linear Technology LTC4215"
++	depends on I2C && EXPERIMENTAL
++	default n
++	help
++	  If you say yes here you get support for Linear Technology LTC4215
++	  Hot Swap Controller I2C interface.
++
++	  This driver can also be built as a module. If so, the module will
++	  be called ltc4215.
++
+ config SENSORS_LTC4245
+ 	tristate "Linear Technology LTC4245"
+ 	depends on I2C && EXPERIMENTAL
+diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
+index 81c88822a3eb..4da261d16abf 100644
+--- a/drivers/hwmon/Makefile
++++ b/drivers/hwmon/Makefile
+@@ -65,6 +65,7 @@ obj-$(CONFIG_SENSORS_LM90)	+= lm90.o
+ obj-$(CONFIG_SENSORS_LM92)	+= lm92.o
+ obj-$(CONFIG_SENSORS_LM93)	+= lm93.o
+ obj-$(CONFIG_SENSORS_LM95241)	+= lm95241.o
++obj-$(CONFIG_SENSORS_LTC4215)	+= ltc4215.o
+ obj-$(CONFIG_SENSORS_LTC4245)	+= ltc4245.o
+ obj-$(CONFIG_SENSORS_MAX1111)	+= max1111.o
+ obj-$(CONFIG_SENSORS_MAX1619)	+= max1619.o
+diff --git a/drivers/hwmon/ltc4215.c b/drivers/hwmon/ltc4215.c
+new file mode 100644
+index 000000000000..9386e2a39211
+--- /dev/null
++++ b/drivers/hwmon/ltc4215.c
+@@ -0,0 +1,364 @@
++/*
++ * Driver for Linear Technology LTC4215 I2C Hot Swap Controller
++ *
++ * Copyright (C) 2009 Ira W. Snyder 
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License.
++ *
++ * Datasheet:
++ * http://www.linear.com/pc/downloadDocument.do?navId=H0,C1,C1003,C1006,C1163,P17572,D12697
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
++
++/* Insmod parameters */
++I2C_CLIENT_INSMOD_1(ltc4215);
++
++/* Here are names of the chip's registers (a.k.a. commands) */
++enum ltc4215_cmd {
++	LTC4215_CONTROL			= 0x00, /* rw */
++	LTC4215_ALERT			= 0x01, /* rw */
++	LTC4215_STATUS			= 0x02, /* ro */
++	LTC4215_FAULT			= 0x03, /* rw */
++	LTC4215_SENSE			= 0x04, /* rw */
++	LTC4215_SOURCE			= 0x05, /* rw */
++	LTC4215_ADIN			= 0x06, /* rw */
++};
++
++struct ltc4215_data {
++	struct device *hwmon_dev;
++
++	struct mutex update_lock;
++	bool valid;
++	unsigned long last_updated; /* in jiffies */
++
++	/* Registers */
++	u8 regs[7];
++};
++
++static struct ltc4215_data *ltc4215_update_device(struct device *dev)
++{
++	struct i2c_client *client = to_i2c_client(dev);
++	struct ltc4215_data *data = i2c_get_clientdata(client);
++	s32 val;
++	int i;
++
++	mutex_lock(&data->update_lock);
++
++	/* The chip's A/D updates 10 times per second */
++	if (time_after(jiffies, data->last_updated + HZ / 10) || !data->valid) {
++
++		dev_dbg(&client->dev, "Starting ltc4215 update\n");
++
++		/* Read all registers */
++		for (i = 0; i < ARRAY_SIZE(data->regs); i++) {
++			val = i2c_smbus_read_byte_data(client, i);
++			if (unlikely(val < 0))
++				data->regs[i] = 0;
++			else
++				data->regs[i] = val;
++		}
++
++		data->last_updated = jiffies;
++		data->valid = 1;
++	}
++
++	mutex_unlock(&data->update_lock);
++
++	return data;
++}
++
++/* Return the voltage from the given register in millivolts */
++static int ltc4215_get_voltage(struct device *dev, u8 reg)
++{
++	struct ltc4215_data *data = ltc4215_update_device(dev);
++	const u8 regval = data->regs[reg];
++	u32 voltage = 0;
++
++	switch (reg) {
++	case LTC4215_SENSE:
++		/* 151 uV per increment */
++		voltage = regval * 151 / 1000;
++		break;
++	case LTC4215_SOURCE:
++		/* 60.5 mV per increment */
++		voltage = regval * 605 / 10;
++		break;
++	case LTC4215_ADIN:
++		/* The ADIN input is divided by 12.5, and has 4.82 mV
++		 * per increment, so we have the additional multiply */
++		voltage = regval * 482 * 125 / 1000;
++		break;
++	default:
++		/* If we get here, the developer messed up */
++		WARN_ON_ONCE(1);
++		break;
++	}
++
++	return voltage;
++}
++
++/* Return the current from the sense resistor in mA */
++static unsigned int ltc4215_get_current(struct device *dev)
++{
++	struct ltc4215_data *data = ltc4215_update_device(dev);
++
++	/* The strange looking conversions that follow are fixed-point
++	 * math, since we cannot do floating point in the kernel.
++	 *
++	 * Step 1: convert sense register to microVolts
++	 * Step 2: convert voltage to milliAmperes
++	 *
++	 * If you play around with the V=IR equation, you come up with
++	 * the following: X uV / Y mOhm == Z mA
++	 *
++	 * With the resistors that are fractions of a milliOhm, we multiply
++	 * the voltage and resistance by 10, to shift the decimal point.
++	 * Now we can use the normal division operator again.
++	 */
++
++	/* Calculate voltage in microVolts (151 uV per increment) */
++	const unsigned int voltage = data->regs[LTC4215_SENSE] * 151;
++
++	/* Calculate current in milliAmperes (4 milliOhm sense resistor) */
++	const unsigned int curr = voltage / 4;
++
++	return curr;
++}
++
++static ssize_t ltc4215_show_voltage(struct device *dev,
++				    struct device_attribute *da,
++				    char *buf)
++{
++	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
++	const int voltage = ltc4215_get_voltage(dev, attr->index);
++
++	return snprintf(buf, PAGE_SIZE, "%d\n", voltage);
++}
++
++static ssize_t ltc4215_show_current(struct device *dev,
++				    struct device_attribute *da,
++				    char *buf)
++{
++	const unsigned int curr = ltc4215_get_current(dev);
++
++	return snprintf(buf, PAGE_SIZE, "%u\n", curr);
++}
++
++static ssize_t ltc4215_show_power(struct device *dev,
++				  struct device_attribute *da,
++				  char *buf)
++{
++	const unsigned int curr = ltc4215_get_current(dev);
++	const int output_voltage = ltc4215_get_voltage(dev, LTC4215_ADIN);
++
++	/* current in mA * voltage in mV == power in uW */
++	const unsigned int power = abs(output_voltage * curr);
++
++	return snprintf(buf, PAGE_SIZE, "%u\n", power);
++}
++
++static ssize_t ltc4215_show_alarm(struct device *dev,
++					  struct device_attribute *da,
++					  char *buf)
++{
++	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(da);
++	struct ltc4215_data *data = ltc4215_update_device(dev);
++	const u8 reg = data->regs[attr->index];
++	const u32 mask = attr->nr;
++
++	return snprintf(buf, PAGE_SIZE, "%u\n", (reg & mask) ? 1 : 0);
++}
++
++/* These macros are used below in constructing device attribute objects
++ * for use with sysfs_create_group() to make a sysfs device file
++ * for each register.
++ */
++
++#define LTC4215_VOLTAGE(name, ltc4215_cmd_idx) \
++	static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
++	ltc4215_show_voltage, NULL, ltc4215_cmd_idx)
++
++#define LTC4215_CURRENT(name) \
++	static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
++	ltc4215_show_current, NULL, 0);
++
++#define LTC4215_POWER(name) \
++	static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
++	ltc4215_show_power, NULL, 0);
++
++#define LTC4215_ALARM(name, mask, reg) \
++	static SENSOR_DEVICE_ATTR_2(name, S_IRUGO, \
++	ltc4215_show_alarm, NULL, (mask), reg)
++
++/* Construct a sensor_device_attribute structure for each register */
++
++/* Current */
++LTC4215_CURRENT(curr1_input);
++LTC4215_ALARM(curr1_max_alarm,	(1 << 2),	LTC4215_STATUS);
++
++/* Power (virtual) */
++LTC4215_POWER(power1_input);
++LTC4215_ALARM(power1_alarm,	(1 << 3),	LTC4215_STATUS);
++
++/* Input Voltage */
++LTC4215_VOLTAGE(in1_input,			LTC4215_ADIN);
++LTC4215_ALARM(in1_max_alarm,	(1 << 0),	LTC4215_STATUS);
++LTC4215_ALARM(in1_min_alarm,	(1 << 1),	LTC4215_STATUS);
++
++/* Output Voltage */
++LTC4215_VOLTAGE(in2_input,			LTC4215_SOURCE);
++
++/* Finally, construct an array of pointers to members of the above objects,
++ * as required for sysfs_create_group()
++ */
++static struct attribute *ltc4215_attributes[] = {
++	&sensor_dev_attr_curr1_input.dev_attr.attr,
++	&sensor_dev_attr_curr1_max_alarm.dev_attr.attr,
++
++	&sensor_dev_attr_power1_input.dev_attr.attr,
++	&sensor_dev_attr_power1_alarm.dev_attr.attr,
++
++	&sensor_dev_attr_in1_input.dev_attr.attr,
++	&sensor_dev_attr_in1_max_alarm.dev_attr.attr,
++	&sensor_dev_attr_in1_min_alarm.dev_attr.attr,
++
++	&sensor_dev_attr_in2_input.dev_attr.attr,
++
++	NULL,
++};
++
++static const struct attribute_group ltc4215_group = {
++	.attrs = ltc4215_attributes,
++};
++
++static int ltc4215_probe(struct i2c_client *client,
++			 const struct i2c_device_id *id)
++{
++	struct ltc4215_data *data;
++	int ret;
++
++	data = kzalloc(sizeof(*data), GFP_KERNEL);
++	if (!data) {
++		ret = -ENOMEM;
++		goto out_kzalloc;
++	}
++
++	i2c_set_clientdata(client, data);
++	mutex_init(&data->update_lock);
++
++	/* Initialize the LTC4215 chip */
++	/* TODO */
++
++	/* Register sysfs hooks */
++	ret = sysfs_create_group(&client->dev.kobj, <c4215_group);
++	if (ret)
++		goto out_sysfs_create_group;
++
++	data->hwmon_dev = hwmon_device_register(&client->dev);
++	if (IS_ERR(data->hwmon_dev)) {
++		ret = PTR_ERR(data->hwmon_dev);
++		goto out_hwmon_device_register;
++	}
++
++	return 0;
++
++out_hwmon_device_register:
++	sysfs_remove_group(&client->dev.kobj, <c4215_group);
++out_sysfs_create_group:
++	kfree(data);
++out_kzalloc:
++	return ret;
++}
++
++static int ltc4215_remove(struct i2c_client *client)
++{
++	struct ltc4215_data *data = i2c_get_clientdata(client);
++
++	hwmon_device_unregister(data->hwmon_dev);
++	sysfs_remove_group(&client->dev.kobj, <c4215_group);
++
++	kfree(data);
++
++	return 0;
++}
++
++static int ltc4215_detect(struct i2c_client *client,
++			  int kind,
++			  struct i2c_board_info *info)
++{
++	struct i2c_adapter *adapter = client->adapter;
++
++	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
++		return -ENODEV;
++
++	if (kind < 0) {		/* probed detection - check the chip type */
++		s32 v;		/* 8 bits from the chip, or -ERRNO */
++
++		/*
++		 * Register 0x01 bit b7 is reserved, expect 0
++		 * Register 0x03 bit b6 and b7 are reserved, expect 0
++		 */
++		v = i2c_smbus_read_byte_data(client, LTC4215_ALERT);
++		if (v < 0 || (v & (1 << 7)) != 0)
++			return -ENODEV;
++
++		v = i2c_smbus_read_byte_data(client, LTC4215_FAULT);
++		if (v < 0 || (v & ((1 << 6) | (1 << 7))) != 0)
++				return -ENODEV;
++	}
++
++	strlcpy(info->type, "ltc4215", I2C_NAME_SIZE);
++	dev_info(&adapter->dev, "ltc4215 %s at address 0x%02x\n",
++			kind < 0 ? "probed" : "forced",
++			client->addr);
++
++	return 0;
++}
++
++static const struct i2c_device_id ltc4215_id[] = {
++	{ "ltc4215", ltc4215 },
++	{ }
++};
++MODULE_DEVICE_TABLE(i2c, ltc4215_id);
++
++/* This is the driver that will be inserted */
++static struct i2c_driver ltc4215_driver = {
++	.class		= I2C_CLASS_HWMON,
++	.driver = {
++		.name	= "ltc4215",
++	},
++	.probe		= ltc4215_probe,
++	.remove		= ltc4215_remove,
++	.id_table	= ltc4215_id,
++	.detect		= ltc4215_detect,
++	.address_data	= &addr_data,
++};
++
++static int __init ltc4215_init(void)
++{
++	return i2c_add_driver(<c4215_driver);
++}
++
++static void __exit ltc4215_exit(void)
++{
++	i2c_del_driver(<c4215_driver);
++}
++
++MODULE_AUTHOR("Ira W. Snyder ");
++MODULE_DESCRIPTION("LTC4215 driver");
++MODULE_LICENSE("GPL");
++
++module_init(ltc4215_init);
++module_exit(ltc4215_exit);

commit 8527bec548e01a29c6d1928d20d6d3be71861482
+Author: Ira W. Snyder 
+Date:   Mon Jan 26 21:00:33 2009 -0800
+
+    virtio_net: use correct accessors for scatterlists
+    
+    Without this fix, virtio_net makes incorrect usage of scatterlists. It sets
+    the end of the scatterlist chain after the first element, despite the fact
+    that more entries come after it.
+    
+    If you try to run dma_map_sg() on one of the scatterlists given to you by
+    add_buf(), you will get a null pointer oops.
+    
+    Signed-off-by: Ira W. Snyder 
+    Signed-off-by: Rusty Russell 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
+index 63ef2a8905fb..c68808336c8c 100644
+--- a/drivers/net/virtio_net.c
++++ b/drivers/net/virtio_net.c
+@@ -287,7 +287,7 @@ static void try_fill_recv_maxbufs(struct virtnet_info *vi)
+ 		skb_put(skb, MAX_PACKET_LEN);
+ 
+ 		hdr = skb_vnet_hdr(skb);
+-		sg_init_one(sg, hdr, sizeof(*hdr));
++		sg_set_buf(sg, hdr, sizeof(*hdr));
+ 
+ 		if (vi->big_packets) {
+ 			for (i = 0; i < MAX_SKB_FRAGS; i++) {
+@@ -488,9 +488,9 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
+ 
+ 	/* Encode metadata header at front. */
+ 	if (vi->mergeable_rx_bufs)
+-		sg_init_one(sg, mhdr, sizeof(*mhdr));
++		sg_set_buf(sg, mhdr, sizeof(*mhdr));
+ 	else
+-		sg_init_one(sg, hdr, sizeof(*hdr));
++		sg_set_buf(sg, hdr, sizeof(*hdr));
+ 
+ 	num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1;
+ 

commit 6e34b187bc216fc632769fb8b906d3a29ccd8f14
+Author: Ira Snyder 
+Date:   Wed Jan 7 16:37:32 2009 +0100
+
+    hwmon: Add LTC4245 driver
+    
+    Add Linux support for the Linear Technology LTC4245 Multiple Supply Hot
+    Swap controller I2C monitoring interface.
+    
+    Signed-off-by: Ira W. Snyder 
+    Acked-by: Hans de Goede 
+    Signed-off-by: Jean Delvare 
+
+diff --git a/Documentation/hwmon/ltc4245 b/Documentation/hwmon/ltc4245
+new file mode 100644
+index 000000000000..bae7a3adc5d8
+--- /dev/null
++++ b/Documentation/hwmon/ltc4245
+@@ -0,0 +1,81 @@
++Kernel driver ltc4245
++=====================
++
++Supported chips:
++  * Linear Technology LTC4245
++    Prefix: 'ltc4245'
++    Addresses scanned: 0x20-0x3f
++    Datasheet:
++        http://www.linear.com/pc/downloadDocument.do?navId=H0,C1,C1003,C1006,C1140,P19392,D13517
++
++Author: Ira W. Snyder 
++
++
++Description
++-----------
++
++The LTC4245 controller allows a board to be safely inserted and removed
++from a live backplane in multiple supply systems such as CompactPCI and
++PCI Express.
++
++
++Usage Notes
++-----------
++
++This driver does not probe for LTC4245 devices, due to the fact that some
++of the possible addresses are unfriendly to probing. You will need to use
++the "force" parameter to tell the driver where to find the device.
++
++Example: the following will load the driver for an LTC4245 at address 0x23
++on I2C bus #1:
++$ modprobe ltc4245 force=1,0x23
++
++
++Sysfs entries
++-------------
++
++The LTC4245 has built-in limits for over and under current warnings. This
++makes it very likely that the reference circuit will be used.
++
++This driver uses the values in the datasheet to change the register values
++into the values specified in the sysfs-interface document. The current readings
++rely on the sense resistors listed in Table 2: "Sense Resistor Values".
++
++in1_input		12v input voltage (mV)
++in2_input		5v  input voltage (mV)
++in3_input		3v  input voltage (mV)
++in4_input		Vee (-12v) input voltage (mV)
++
++in1_min_alarm		12v input undervoltage alarm
++in2_min_alarm		5v  input undervoltage alarm
++in3_min_alarm		3v  input undervoltage alarm
++in4_min_alarm		Vee (-12v) input undervoltage alarm
++
++curr1_input		12v current (mA)
++curr2_input		5v  current (mA)
++curr3_input		3v  current (mA)
++curr4_input		Vee (-12v) current (mA)
++
++curr1_max_alarm		12v overcurrent alarm
++curr2_max_alarm		5v  overcurrent alarm
++curr3_max_alarm		3v  overcurrent alarm
++curr4_max_alarm		Vee (-12v) overcurrent alarm
++
++in5_input		12v output voltage (mV)
++in6_input		5v  output voltage (mV)
++in7_input		3v  output voltage (mV)
++in8_input		Vee (-12v) output voltage (mV)
++
++in5_min_alarm		12v output undervoltage alarm
++in6_min_alarm		5v  output undervoltage alarm
++in7_min_alarm		3v  output undervoltage alarm
++in8_min_alarm		Vee (-12v) output undervoltage alarm
++
++in9_input		GPIO #1 voltage data
++in10_input		GPIO #2 voltage data
++in11_input		GPIO #3 voltage data
++
++power1_input		12v power usage (mW)
++power2_input		5v  power usage (mW)
++power3_input		3v  power usage (mW)
++power4_input		Vee (-12v) power usage (mW)
+diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
+index cc611e4b7896..1ef1205b4e8c 100644
+--- a/drivers/hwmon/Kconfig
++++ b/drivers/hwmon/Kconfig
+@@ -549,6 +549,17 @@ config SENSORS_LM93
+ 	  This driver can also be built as a module.  If so, the module
+ 	  will be called lm93.
+ 
++config SENSORS_LTC4245
++	tristate "Linear Technology LTC4245"
++	depends on I2C && EXPERIMENTAL
++	default n
++	help
++	  If you say yes here you get support for Linear Technology LTC4245
++	  Multiple Supply Hot Swap Controller I2C interface.
++
++	  This driver can also be built as a module. If so, the module will
++	  be called ltc4245.
++
+ config SENSORS_MAX1111
+ 	tristate "Maxim MAX1111 Multichannel, Serial 8-bit ADC chip"
+ 	depends on SPI_MASTER
+diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
+index 58fc5be5355d..8fd124eff646 100644
+--- a/drivers/hwmon/Makefile
++++ b/drivers/hwmon/Makefile
+@@ -62,6 +62,7 @@ obj-$(CONFIG_SENSORS_LM87)	+= lm87.o
+ obj-$(CONFIG_SENSORS_LM90)	+= lm90.o
+ obj-$(CONFIG_SENSORS_LM92)	+= lm92.o
+ obj-$(CONFIG_SENSORS_LM93)	+= lm93.o
++obj-$(CONFIG_SENSORS_LTC4245)	+= ltc4245.o
+ obj-$(CONFIG_SENSORS_MAX1111)	+= max1111.o
+ obj-$(CONFIG_SENSORS_MAX1619)	+= max1619.o
+ obj-$(CONFIG_SENSORS_MAX6650)	+= max6650.o
+diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c
+new file mode 100644
+index 000000000000..034b2c515848
+--- /dev/null
++++ b/drivers/hwmon/ltc4245.c
+@@ -0,0 +1,567 @@
++/*
++ * Driver for Linear Technology LTC4245 I2C Multiple Supply Hot Swap Controller
++ *
++ * Copyright (C) 2008 Ira W. Snyder 
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License.
++ *
++ * This driver is based on the ds1621 and ina209 drivers.
++ *
++ * Datasheet:
++ * http://www.linear.com/pc/downloadDocument.do?navId=H0,C1,C1003,C1006,C1140,P19392,D13517
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++/* Valid addresses are 0x20 - 0x3f
++ *
++ * For now, we do not probe, since some of these addresses
++ * are known to be unfriendly to probing */
++static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
++
++/* Insmod parameters */
++I2C_CLIENT_INSMOD_1(ltc4245);
++
++/* Here are names of the chip's registers (a.k.a. commands) */
++enum ltc4245_cmd {
++	LTC4245_STATUS			= 0x00, /* readonly */
++	LTC4245_ALERT			= 0x01,
++	LTC4245_CONTROL			= 0x02,
++	LTC4245_ON			= 0x03,
++	LTC4245_FAULT1			= 0x04,
++	LTC4245_FAULT2			= 0x05,
++	LTC4245_GPIO			= 0x06,
++	LTC4245_ADCADR			= 0x07,
++
++	LTC4245_12VIN			= 0x10,
++	LTC4245_12VSENSE		= 0x11,
++	LTC4245_12VOUT			= 0x12,
++	LTC4245_5VIN			= 0x13,
++	LTC4245_5VSENSE			= 0x14,
++	LTC4245_5VOUT			= 0x15,
++	LTC4245_3VIN			= 0x16,
++	LTC4245_3VSENSE			= 0x17,
++	LTC4245_3VOUT			= 0x18,
++	LTC4245_VEEIN			= 0x19,
++	LTC4245_VEESENSE		= 0x1a,
++	LTC4245_VEEOUT			= 0x1b,
++	LTC4245_GPIOADC1		= 0x1c,
++	LTC4245_GPIOADC2		= 0x1d,
++	LTC4245_GPIOADC3		= 0x1e,
++};
++
++struct ltc4245_data {
++	struct device *hwmon_dev;
++
++	struct mutex update_lock;
++	bool valid;
++	unsigned long last_updated; /* in jiffies */
++
++	/* Control registers */
++	u8 cregs[0x08];
++
++	/* Voltage registers */
++	u8 vregs[0x0f];
++};
++
++static struct ltc4245_data *ltc4245_update_device(struct device *dev)
++{
++	struct i2c_client *client = to_i2c_client(dev);
++	struct ltc4245_data *data = i2c_get_clientdata(client);
++	s32 val;
++	int i;
++
++	mutex_lock(&data->update_lock);
++
++	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
++
++		dev_dbg(&client->dev, "Starting ltc4245 update\n");
++
++		/* Read control registers -- 0x00 to 0x07 */
++		for (i = 0; i < ARRAY_SIZE(data->cregs); i++) {
++			val = i2c_smbus_read_byte_data(client, i);
++			if (unlikely(val < 0))
++				data->cregs[i] = 0;
++			else
++				data->cregs[i] = val;
++		}
++
++		/* Read voltage registers -- 0x10 to 0x1f */
++		for (i = 0; i < ARRAY_SIZE(data->vregs); i++) {
++			val = i2c_smbus_read_byte_data(client, i+0x10);
++			if (unlikely(val < 0))
++				data->vregs[i] = 0;
++			else
++				data->vregs[i] = val;
++		}
++
++		data->last_updated = jiffies;
++		data->valid = 1;
++	}
++
++	mutex_unlock(&data->update_lock);
++
++	return data;
++}
++
++/* Return the voltage from the given register in millivolts */
++static int ltc4245_get_voltage(struct device *dev, u8 reg)
++{
++	struct ltc4245_data *data = ltc4245_update_device(dev);
++	const u8 regval = data->vregs[reg - 0x10];
++	u32 voltage = 0;
++
++	switch (reg) {
++	case LTC4245_12VIN:
++	case LTC4245_12VOUT:
++		voltage = regval * 55;
++		break;
++	case LTC4245_5VIN:
++	case LTC4245_5VOUT:
++		voltage = regval * 22;
++		break;
++	case LTC4245_3VIN:
++	case LTC4245_3VOUT:
++		voltage = regval * 15;
++		break;
++	case LTC4245_VEEIN:
++	case LTC4245_VEEOUT:
++		voltage = regval * -55;
++		break;
++	case LTC4245_GPIOADC1:
++	case LTC4245_GPIOADC2:
++	case LTC4245_GPIOADC3:
++		voltage = regval * 10;
++		break;
++	default:
++		/* If we get here, the developer messed up */
++		WARN_ON_ONCE(1);
++		break;
++	}
++
++	return voltage;
++}
++
++/* Return the current in the given sense register in milliAmperes */
++static unsigned int ltc4245_get_current(struct device *dev, u8 reg)
++{
++	struct ltc4245_data *data = ltc4245_update_device(dev);
++	const u8 regval = data->vregs[reg - 0x10];
++	unsigned int voltage;
++	unsigned int curr;
++
++	/* The strange looking conversions that follow are fixed-point
++	 * math, since we cannot do floating point in the kernel.
++	 *
++	 * Step 1: convert sense register to microVolts
++	 * Step 2: convert voltage to milliAmperes
++	 *
++	 * If you play around with the V=IR equation, you come up with
++	 * the following: X uV / Y mOhm == Z mA
++	 *
++	 * With the resistors that are fractions of a milliOhm, we multiply
++	 * the voltage and resistance by 10, to shift the decimal point.
++	 * Now we can use the normal division operator again.
++	 */
++
++	switch (reg) {
++	case LTC4245_12VSENSE:
++		voltage = regval * 250; /* voltage in uV */
++		curr = voltage / 50; /* sense resistor 50 mOhm */
++		break;
++	case LTC4245_5VSENSE:
++		voltage = regval * 125; /* voltage in uV */
++		curr = (voltage * 10) / 35; /* sense resistor 3.5 mOhm */
++		break;
++	case LTC4245_3VSENSE:
++		voltage = regval * 125; /* voltage in uV */
++		curr = (voltage * 10) / 25; /* sense resistor 2.5 mOhm */
++		break;
++	case LTC4245_VEESENSE:
++		voltage = regval * 250; /* voltage in uV */
++		curr = voltage / 100; /* sense resistor 100 mOhm */
++		break;
++	default:
++		/* If we get here, the developer messed up */
++		WARN_ON_ONCE(1);
++		curr = 0;
++		break;
++	}
++
++	return curr;
++}
++
++static ssize_t ltc4245_show_voltage(struct device *dev,
++				    struct device_attribute *da,
++				    char *buf)
++{
++	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
++	const int voltage = ltc4245_get_voltage(dev, attr->index);
++
++	return snprintf(buf, PAGE_SIZE, "%d\n", voltage);
++}
++
++static ssize_t ltc4245_show_current(struct device *dev,
++				    struct device_attribute *da,
++				    char *buf)
++{
++	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
++	const unsigned int curr = ltc4245_get_current(dev, attr->index);
++
++	return snprintf(buf, PAGE_SIZE, "%u\n", curr);
++}
++
++static ssize_t ltc4245_show_power(struct device *dev,
++				  struct device_attribute *da,
++				  char *buf)
++{
++	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
++	const unsigned int curr = ltc4245_get_current(dev, attr->index);
++	const int output_voltage = ltc4245_get_voltage(dev, attr->index+1);
++
++	/* current in mA * voltage in mV == power in uW */
++	const unsigned int power = abs(output_voltage * curr);
++
++	return snprintf(buf, PAGE_SIZE, "%u\n", power);
++}
++
++static ssize_t ltc4245_show_alarm(struct device *dev,
++					  struct device_attribute *da,
++					  char *buf)
++{
++	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(da);
++	struct ltc4245_data *data = ltc4245_update_device(dev);
++	const u8 reg = data->cregs[attr->index];
++	const u32 mask = attr->nr;
++
++	return snprintf(buf, PAGE_SIZE, "%u\n", (reg & mask) ? 1 : 0);
++}
++
++/* These macros are used below in constructing device attribute objects
++ * for use with sysfs_create_group() to make a sysfs device file
++ * for each register.
++ */
++
++#define LTC4245_VOLTAGE(name, ltc4245_cmd_idx) \
++	static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
++	ltc4245_show_voltage, NULL, ltc4245_cmd_idx)
++
++#define LTC4245_CURRENT(name, ltc4245_cmd_idx) \
++	static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
++	ltc4245_show_current, NULL, ltc4245_cmd_idx)
++
++#define LTC4245_POWER(name, ltc4245_cmd_idx) \
++	static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
++	ltc4245_show_power, NULL, ltc4245_cmd_idx)
++
++#define LTC4245_ALARM(name, mask, reg) \
++	static SENSOR_DEVICE_ATTR_2(name, S_IRUGO, \
++	ltc4245_show_alarm, NULL, (mask), reg)
++
++/* Construct a sensor_device_attribute structure for each register */
++
++/* Input voltages */
++LTC4245_VOLTAGE(in1_input,			LTC4245_12VIN);
++LTC4245_VOLTAGE(in2_input,			LTC4245_5VIN);
++LTC4245_VOLTAGE(in3_input,			LTC4245_3VIN);
++LTC4245_VOLTAGE(in4_input,			LTC4245_VEEIN);
++
++/* Input undervoltage alarms */
++LTC4245_ALARM(in1_min_alarm,	(1 << 0),	LTC4245_FAULT1);
++LTC4245_ALARM(in2_min_alarm,	(1 << 1),	LTC4245_FAULT1);
++LTC4245_ALARM(in3_min_alarm,	(1 << 2),	LTC4245_FAULT1);
++LTC4245_ALARM(in4_min_alarm,	(1 << 3),	LTC4245_FAULT1);
++
++/* Currents (via sense resistor) */
++LTC4245_CURRENT(curr1_input,			LTC4245_12VSENSE);
++LTC4245_CURRENT(curr2_input,			LTC4245_5VSENSE);
++LTC4245_CURRENT(curr3_input,			LTC4245_3VSENSE);
++LTC4245_CURRENT(curr4_input,			LTC4245_VEESENSE);
++
++/* Overcurrent alarms */
++LTC4245_ALARM(curr1_max_alarm,	(1 << 4),	LTC4245_FAULT1);
++LTC4245_ALARM(curr2_max_alarm,	(1 << 5),	LTC4245_FAULT1);
++LTC4245_ALARM(curr3_max_alarm,	(1 << 6),	LTC4245_FAULT1);
++LTC4245_ALARM(curr4_max_alarm,	(1 << 7),	LTC4245_FAULT1);
++
++/* Output voltages */
++LTC4245_VOLTAGE(in5_input,			LTC4245_12VOUT);
++LTC4245_VOLTAGE(in6_input,			LTC4245_5VOUT);
++LTC4245_VOLTAGE(in7_input,			LTC4245_3VOUT);
++LTC4245_VOLTAGE(in8_input,			LTC4245_VEEOUT);
++
++/* Power Bad alarms */
++LTC4245_ALARM(in5_min_alarm,	(1 << 0),	LTC4245_FAULT2);
++LTC4245_ALARM(in6_min_alarm,	(1 << 1),	LTC4245_FAULT2);
++LTC4245_ALARM(in7_min_alarm,	(1 << 2),	LTC4245_FAULT2);
++LTC4245_ALARM(in8_min_alarm,	(1 << 3),	LTC4245_FAULT2);
++
++/* GPIO voltages */
++LTC4245_VOLTAGE(in9_input,			LTC4245_GPIOADC1);
++LTC4245_VOLTAGE(in10_input,			LTC4245_GPIOADC2);
++LTC4245_VOLTAGE(in11_input,			LTC4245_GPIOADC3);
++
++/* Power Consumption (virtual) */
++LTC4245_POWER(power1_input,			LTC4245_12VSENSE);
++LTC4245_POWER(power2_input,			LTC4245_5VSENSE);
++LTC4245_POWER(power3_input,			LTC4245_3VSENSE);
++LTC4245_POWER(power4_input,			LTC4245_VEESENSE);
++
++/* Finally, construct an array of pointers to members of the above objects,
++ * as required for sysfs_create_group()
++ */
++static struct attribute *ltc4245_attributes[] = {
++	&sensor_dev_attr_in1_input.dev_attr.attr,
++	&sensor_dev_attr_in2_input.dev_attr.attr,
++	&sensor_dev_attr_in3_input.dev_attr.attr,
++	&sensor_dev_attr_in4_input.dev_attr.attr,
++
++	&sensor_dev_attr_in1_min_alarm.dev_attr.attr,
++	&sensor_dev_attr_in2_min_alarm.dev_attr.attr,
++	&sensor_dev_attr_in3_min_alarm.dev_attr.attr,
++	&sensor_dev_attr_in4_min_alarm.dev_attr.attr,
++
++	&sensor_dev_attr_curr1_input.dev_attr.attr,
++	&sensor_dev_attr_curr2_input.dev_attr.attr,
++	&sensor_dev_attr_curr3_input.dev_attr.attr,
++	&sensor_dev_attr_curr4_input.dev_attr.attr,
++
++	&sensor_dev_attr_curr1_max_alarm.dev_attr.attr,
++	&sensor_dev_attr_curr2_max_alarm.dev_attr.attr,
++	&sensor_dev_attr_curr3_max_alarm.dev_attr.attr,
++	&sensor_dev_attr_curr4_max_alarm.dev_attr.attr,
++
++	&sensor_dev_attr_in5_input.dev_attr.attr,
++	&sensor_dev_attr_in6_input.dev_attr.attr,
++	&sensor_dev_attr_in7_input.dev_attr.attr,
++	&sensor_dev_attr_in8_input.dev_attr.attr,
++
++	&sensor_dev_attr_in5_min_alarm.dev_attr.attr,
++	&sensor_dev_attr_in6_min_alarm.dev_attr.attr,
++	&sensor_dev_attr_in7_min_alarm.dev_attr.attr,
++	&sensor_dev_attr_in8_min_alarm.dev_attr.attr,
++
++	&sensor_dev_attr_in9_input.dev_attr.attr,
++	&sensor_dev_attr_in10_input.dev_attr.attr,
++	&sensor_dev_attr_in11_input.dev_attr.attr,
++
++	&sensor_dev_attr_power1_input.dev_attr.attr,
++	&sensor_dev_attr_power2_input.dev_attr.attr,
++	&sensor_dev_attr_power3_input.dev_attr.attr,
++	&sensor_dev_attr_power4_input.dev_attr.attr,
++
++	NULL,
++};
++
++static const struct attribute_group ltc4245_group = {
++	.attrs = ltc4245_attributes,
++};
++
++static int ltc4245_probe(struct i2c_client *client,
++			 const struct i2c_device_id *id)
++{
++	struct ltc4245_data *data;
++	int ret;
++
++	data = kzalloc(sizeof(*data), GFP_KERNEL);
++	if (!data) {
++		ret = -ENOMEM;
++		goto out_kzalloc;
++	}
++
++	i2c_set_clientdata(client, data);
++	mutex_init(&data->update_lock);
++
++	/* Initialize the LTC4245 chip */
++	/* TODO */
++
++	/* Register sysfs hooks */
++	ret = sysfs_create_group(&client->dev.kobj, <c4245_group);
++	if (ret)
++		goto out_sysfs_create_group;
++
++	data->hwmon_dev = hwmon_device_register(&client->dev);
++	if (IS_ERR(data->hwmon_dev)) {
++		ret = PTR_ERR(data->hwmon_dev);
++		goto out_hwmon_device_register;
++	}
++
++	return 0;
++
++out_hwmon_device_register:
++	sysfs_remove_group(&client->dev.kobj, <c4245_group);
++out_sysfs_create_group:
++	kfree(data);
++out_kzalloc:
++	return ret;
++}
++
++static int ltc4245_remove(struct i2c_client *client)
++{
++	struct ltc4245_data *data = i2c_get_clientdata(client);
++
++	hwmon_device_unregister(data->hwmon_dev);
++	sysfs_remove_group(&client->dev.kobj, <c4245_group);
++
++	kfree(data);
++
++	return 0;
++}
++
++/* Check that some bits in a control register appear at all possible
++ * locations without changing value
++ *
++ * @client: the i2c client to use
++ * @reg: the register to read
++ * @bits: the bits to check (0xff checks all bits,
++ *                           0x03 checks only the last two bits)
++ *
++ * return -ERRNO if the register read failed
++ * return -ENODEV if the register value doesn't stay constant at all
++ * possible addresses
++ *
++ * return 0 for success
++ */
++static int ltc4245_check_control_reg(struct i2c_client *client, u8 reg, u8 bits)
++{
++	int i;
++	s32 v, voff1, voff2;
++
++	/* Read register and check for error */
++	v = i2c_smbus_read_byte_data(client, reg);
++	if (v < 0)
++		return v;
++
++	v &= bits;
++
++	for (i = 0x00; i < 0xff; i += 0x20) {
++
++		voff1 = i2c_smbus_read_byte_data(client, reg + i);
++		if (voff1 < 0)
++			return voff1;
++
++		voff2 = i2c_smbus_read_byte_data(client, reg + i + 0x08);
++		if (voff2 < 0)
++			return voff2;
++
++		voff1 &= bits;
++		voff2 &= bits;
++
++		if (v != voff1 || v != voff2)
++			return -ENODEV;
++	}
++
++	return 0;
++}
++
++static int ltc4245_detect(struct i2c_client *client,
++			  int kind,
++			  struct i2c_board_info *info)
++{
++	struct i2c_adapter *adapter = client->adapter;
++
++	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
++		return -ENODEV;
++
++	if (kind < 0) {		/* probed detection - check the chip type */
++		s32 v;		/* 8 bits from the chip, or -ERRNO */
++
++		/* Chip registers 0x00-0x07 are control registers
++		 * Chip registers 0x10-0x1f are data registers
++		 *
++		 * Address bits b7-b5 are ignored. This makes the chip "repeat"
++		 * in steps of 0x20. Any control registers should appear with
++		 * the same values across all duplicated addresses.
++		 *
++		 * Register 0x02 bit b2 is reserved, expect 0
++		 * Register 0x07 bits b7 to b4 are reserved, expect 0
++		 *
++		 * Registers 0x01, 0x02 are control registers and should not
++		 * change on their own.
++		 *
++		 * Register 0x06 bits b6 and b7 are control bits, and should
++		 * not change on their own.
++		 *
++		 * Register 0x07 bits b3 to b0 are control bits, and should
++		 * not change on their own.
++		 */
++
++		/* read register 0x02 reserved bit, expect 0 */
++		v = i2c_smbus_read_byte_data(client, LTC4245_CONTROL);
++		if (v < 0 || (v & 0x04) != 0)
++			return -ENODEV;
++
++		/* read register 0x07 reserved bits, expect 0 */
++		v = i2c_smbus_read_byte_data(client, LTC4245_ADCADR);
++		if (v < 0 || (v & 0xf0) != 0)
++			return -ENODEV;
++
++		/* check that the alert register appears at all locations */
++		if (ltc4245_check_control_reg(client, LTC4245_ALERT, 0xff))
++			return -ENODEV;
++
++		/* check that the control register appears at all locations */
++		if (ltc4245_check_control_reg(client, LTC4245_CONTROL, 0xff))
++			return -ENODEV;
++
++		/* check that register 0x06 bits b6 and b7 stay constant */
++		if (ltc4245_check_control_reg(client, LTC4245_GPIO, 0xc0))
++			return -ENODEV;
++
++		/* check that register 0x07 bits b3-b0 stay constant */
++		if (ltc4245_check_control_reg(client, LTC4245_ADCADR, 0x0f))
++			return -ENODEV;
++	}
++
++	strlcpy(info->type, "ltc4245", I2C_NAME_SIZE);
++	dev_info(&adapter->dev, "ltc4245 %s at address 0x%02x\n",
++			kind < 0 ? "probed" : "forced",
++			client->addr);
++
++	return 0;
++}
++
++static const struct i2c_device_id ltc4245_id[] = {
++	{ "ltc4245", ltc4245 },
++	{ }
++};
++MODULE_DEVICE_TABLE(i2c, ltc4245_id);
++
++/* This is the driver that will be inserted */
++static struct i2c_driver ltc4245_driver = {
++	.class		= I2C_CLASS_HWMON,
++	.driver = {
++		.name	= "ltc4245",
++	},
++	.probe		= ltc4245_probe,
++	.remove		= ltc4245_remove,
++	.id_table	= ltc4245_id,
++	.detect		= ltc4245_detect,
++	.address_data	= &addr_data,
++};
++
++static int __init ltc4245_init(void)
++{
++	return i2c_add_driver(<c4245_driver);
++}
++
++static void __exit ltc4245_exit(void)
++{
++	i2c_del_driver(<c4245_driver);
++}
++
++MODULE_AUTHOR("Ira W. Snyder ");
++MODULE_DESCRIPTION("LTC4245 driver");
++MODULE_LICENSE("GPL");
++
++module_init(ltc4245_init);
++module_exit(ltc4245_exit);

commit c87f883edbe969ca68c21dfa8a29674c828c22a3
+Author: Rumen Ivanov Zarev 
+Date:   Tue Sep 6 13:39:32 2005 -0700
+
+    [PATCH] PCI: Unhide SMBus on Compaq Evo N620c
+    
+    Trivial patch against 2.6.13 to unhide SMBus on Compaq Evo N620c laptop using
+    Intel 82855PM chipset.
+    
+    Signed-off-by: Rumen Zarev 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
+index 4f0c1bd3674a..11ca44387cb0 100644
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -876,6 +876,12 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
+                        case 0xC00C: /* Samsung P35 notebook */
+                                asus_hides_smbus = 1;
+                        }
++	} else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ)) {
++		if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB)
++			switch(dev->subsystem_device) {
++			case 0x0058: /* Compaq Evo N620c */
++				asus_hides_smbus = 1;
++			}
+ 	}
+ }
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82845_HB,	asus_hides_smbus_hostbridge );

\ No newline at end of file diff --git a/detail/17.html b/detail/17.html new file mode 100644 index 0000000..57e77b4 --- /dev/null +++ b/detail/17.html @@ -0,0 +1,7288 @@ +

Patches contributed by University of Queensland


commit e30b9d6c641dbd9687a5605b2151a2a83d2e8770
+Author: Chris Pascoe 
+Date:   Sat Nov 24 04:34:42 2007 -0300
+
+    V4L/DVB (12821): tm6000: update USB request names and clean up i2c routine
+    
+    Update the descriptions of the USB request types so that they match what
+    we now know they do.
+    
+    Rework the i2c_xfer function so that it is more explicit what sort of I2C
+    transfers it is that the tm6000 can't perform.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/staging/tm6000/tm6000-i2c.c b/drivers/staging/tm6000/tm6000-i2c.c
+index 8569cfca8f82..12e2c98e5433 100644
+--- a/drivers/staging/tm6000/tm6000-i2c.c
++++ b/drivers/staging/tm6000/tm6000-i2c.c
+@@ -73,7 +73,7 @@ static int tm6000_i2c_scan(struct i2c_adapter *i2c_adap, int addr)
+ 	/* This sends addr + 1 byte with 0 */
+ 	rc = tm6000_read_write_usb (dev,
+ 		USB_DIR_IN | USB_TYPE_VENDOR,
+-		REQ_16_SET_GET_I2CSEQ,
++		REQ_16_SET_GET_I2C_WR1_RDN,
+ 		addr, 0,
+ 		buf, 0);
+ 	msleep(10);
+@@ -94,82 +94,61 @@ static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,
+ {
+ 	struct tm6000_core *dev = i2c_adap->algo_data;
+ 	int addr, rc, i, byte;
+-	int prev_reg = -1;
+ 
+ 	if (num <= 0)
+ 		return 0;
+ 	for (i = 0; i < num; i++) {
+-		addr = (msgs[i].addr << 1) &0xff;
++		addr = (msgs[i].addr << 1) & 0xff;
+ 		i2c_dprintk(2,"%s %s addr=0x%x len=%d:",
+ 			 (msgs[i].flags & I2C_M_RD) ? "read" : "write",
+ 			 i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
+ 		if (!msgs[i].len) {
+ 			/* Do I2C scan */
+-			rc=tm6000_i2c_scan(i2c_adap, addr);
++			rc = tm6000_i2c_scan(i2c_adap, addr);
+ 		} else if (msgs[i].flags & I2C_M_RD) {
+-			/* Read bytes */
+-	/* I2C is assumed to have always a subaddr at the first byte of the
+-	   message bus. Also, the first i2c value of the answer is returned
+-	   out of message data.
+-	 */
+-			/* SMBus Read Byte command */
+-			if (prev_reg < 0)
+-				printk("XXX read from unknown prev_reg\n");
+-			rc = tm6000_read_write_usb (dev,
+-				USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+-				REQ_16_SET_GET_I2CSEQ,
+-				addr | (prev_reg << 8), 0,
+-				msgs[i].buf, msgs[i].len);
+-			if (prev_reg >= 0)
+-				prev_reg += msgs[i].len;
+-			if (i2c_debug>=2) {
+-				for (byte = 0; byte < msgs[i].len; byte++) {
++			/* read request without preceding register selection */
++			/*
++			 * The TM6000 only supports a read transaction
++			 * immediately after a 1 or 2 byte write to select
++			 * a register.  We cannot fulfil this request.
++			 */
++			i2c_dprintk(2, " read without preceding write not"
++				       " supported");
++			rc = -EOPNOTSUPP;
++			goto err;
++		} else if (i + 1 < num && msgs[i].len <= 2 &&
++			   (msgs[i + 1].flags & I2C_M_RD) &&
++			   msgs[i].addr == msgs[i + 1].addr) {
++			/* 1 or 2 byte write followed by a read */
++			if (i2c_debug >= 2)
++				for (byte = 0; byte < msgs[i].len; byte++)
+ 					printk(" %02x", msgs[i].buf[byte]);
+-				}
+-			}
+-		} else if (i+1 < num && msgs[i].len == 2 &&
+-			   (msgs[i+1].flags & I2C_M_RD) &&
+-			   msgs[i].addr == msgs[i+1].addr) {
+-			i2c_dprintk(2, "msg %d: write 2, read %d", i,
+-				    msgs[i+1].len);
+-			/* Write 2 Read N command */
++			i2c_dprintk(2, "; joined to read %s len=%d:",
++				    i == num - 2 ? "stop" : "nonstop",
++				    msgs[i + 1].len);
+ 			rc = tm6000_read_write_usb (dev,
+ 				USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+-				REQ_14_SET_GET_EEPROM_PAGE, /* XXX wrong name */
+-				addr | msgs[i].buf[0] << 8, msgs[i].buf[1],
+-				msgs[i+1].buf, msgs[i+1].len);
++				msgs[i].len == 1 ? REQ_16_SET_GET_I2C_WR1_RDN
++						 : REQ_14_SET_GET_I2C_WR2_RDN,
++				addr | msgs[i].buf[0] << 8,
++				msgs[i].len == 1 ? 0 : msgs[i].buf[1],
++				msgs[i + 1].buf, msgs[i + 1].len);
+ 			i++;
+-			if (i2c_debug>=2) {
+-				for (byte = 0; byte < msgs[i].len; byte++) {
++			if (i2c_debug >= 2)
++				for (byte = 0; byte < msgs[i].len; byte++)
+ 					printk(" %02x", msgs[i].buf[byte]);
+-				}
+-			}
+-			prev_reg = -1;
+ 		} else {
+ 			/* write bytes */
+-			if (i2c_debug>=2) {
++			if (i2c_debug >= 2)
+ 				for (byte = 0; byte < msgs[i].len; byte++)
+ 					printk(" %02x", msgs[i].buf[byte]);
+-			}
+-
+-			/* SMBus Write Byte command followed by a read command */
+-			if(msgs[i].len == 1 && i+1 < num && msgs[i+1].flags & I2C_M_RD
+-					    && msgs[i+1].addr == msgs[i].addr) {
+-				prev_reg = msgs[i].buf[0];
+-				if (i2c_debug >= 2)
+-					printk("\n");
+-				continue;
+-			}
+-
+-			rc = tm6000_read_write_usb (dev,
++			rc = tm6000_read_write_usb(dev,
+ 				USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+-				REQ_16_SET_GET_I2CSEQ,
+-				addr|(*msgs[i].buf)<<8, 0,
+-				msgs[i].buf+1, msgs[i].len-1);
+-
+-			prev_reg = -1;
++				REQ_16_SET_GET_I2C_WR1_RDN,
++				addr | msgs[i].buf[0] << 8, 0,
++				msgs[i].buf + 1, msgs[i].len - 1);
+ 		}
+-		if (i2c_debug>=2)
++		if (i2c_debug >= 2)
+ 			printk("\n");
+ 		if (rc < 0)
+ 			goto err;
+@@ -181,7 +160,6 @@ static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,
+ 	return rc;
+ }
+ 
+-
+ static int tm6000_i2c_eeprom(struct tm6000_core *dev,
+ 			     unsigned char *eedata, int len)
+ {
+@@ -196,7 +174,7 @@ static int tm6000_i2c_eeprom(struct tm6000_core *dev,
+ 	*p = i;
+ 	rc = tm6000_read_write_usb (dev,
+ 		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+-		REQ_16_SET_GET_I2CSEQ, 0xa0 | i<<8, 0, p, 1);
++		REQ_16_SET_GET_I2C_WR1_RDN, 0xa0 | i<<8, 0, p, 1);
+ 		if (rc < 1) {
+ 			if (p == eedata)
+ 				goto noeeprom;
+@@ -273,7 +251,7 @@ static void dec_use(struct i2c_adapter *adap)
+ #define mass_write(addr, reg, data...)					\
+ 	{ const static u8 _val[] = data;				\
+ 	rc=tm6000_read_write_usb(dev,USB_DIR_OUT | USB_TYPE_VENDOR,	\
+-	REQ_16_SET_GET_I2CSEQ,(reg<<8)+addr, 0x00, (u8 *) _val,		\
++	REQ_16_SET_GET_I2C_WR1_RDN,(reg<<8)+addr, 0x00, (u8 *) _val,	\
+ 	ARRAY_SIZE(_val));						\
+ 	if (rc<0) {							\
+ 		printk(KERN_ERR "Error on line %d: %d\n",__LINE__,rc);	\
+diff --git a/drivers/staging/tm6000/tm6000-regs.h b/drivers/staging/tm6000/tm6000-regs.h
+index 414852e69fce..9b6456e18426 100644
+--- a/drivers/staging/tm6000/tm6000-regs.h
++++ b/drivers/staging/tm6000/tm6000-regs.h
+@@ -38,11 +38,11 @@
+ #define REQ_11_SET_EEPROM_ADDR		11
+ #define REQ_12_SET_GET_EEPROMBYTE	12
+ #define REQ_13_GET_EEPROM_SEQREAD	13
+-#define REQ_14_SET_GET_EEPROM_PAGE	14
++#define REQ_14_SET_GET_I2C_WR2_RDN	14
+ #define REQ_15_SET_GET_I2CBYTE		15
+ 	/* Write: Subaddr, Slave Addr, value, 0 */
+ 	/* Read : Subaddr, Slave Addr, value, 1 */
+-#define REQ_16_SET_GET_I2CSEQ		16
++#define REQ_16_SET_GET_I2C_WR1_RDN	16
+ 	/* Subaddr, Slave Addr, 0, length */
+ #define REQ_17_SET_GET_I2CFP		17
+ 	/* Write: Slave Addr, register, value */

commit cf9e1509c278c3d5005f222539813933e4dc345c
+Author: Christopher Pascoe 
+Date:   Fri Nov 23 13:18:56 2007 -0300
+
+    V4L/DVB (12820): tm6000: fix i2c readings
+    
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/staging/tm6000/tm6000-i2c.c b/drivers/staging/tm6000/tm6000-i2c.c
+index c0327d724eb2..8569cfca8f82 100644
+--- a/drivers/staging/tm6000/tm6000-i2c.c
++++ b/drivers/staging/tm6000/tm6000-i2c.c
+@@ -94,7 +94,7 @@ static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,
+ {
+ 	struct tm6000_core *dev = i2c_adap->algo_data;
+ 	int addr, rc, i, byte;
+-	u8 prev_reg = 0;
++	int prev_reg = -1;
+ 
+ 	if (num <= 0)
+ 		return 0;
+@@ -113,16 +113,38 @@ static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,
+ 	   out of message data.
+ 	 */
+ 			/* SMBus Read Byte command */
++			if (prev_reg < 0)
++				printk("XXX read from unknown prev_reg\n");
+ 			rc = tm6000_read_write_usb (dev,
+ 				USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 				REQ_16_SET_GET_I2CSEQ,
+ 				addr | (prev_reg << 8), 0,
+ 				msgs[i].buf, msgs[i].len);
++			if (prev_reg >= 0)
++				prev_reg += msgs[i].len;
+ 			if (i2c_debug>=2) {
+ 				for (byte = 0; byte < msgs[i].len; byte++) {
+ 					printk(" %02x", msgs[i].buf[byte]);
+ 				}
+ 			}
++		} else if (i+1 < num && msgs[i].len == 2 &&
++			   (msgs[i+1].flags & I2C_M_RD) &&
++			   msgs[i].addr == msgs[i+1].addr) {
++			i2c_dprintk(2, "msg %d: write 2, read %d", i,
++				    msgs[i+1].len);
++			/* Write 2 Read N command */
++			rc = tm6000_read_write_usb (dev,
++				USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
++				REQ_14_SET_GET_EEPROM_PAGE, /* XXX wrong name */
++				addr | msgs[i].buf[0] << 8, msgs[i].buf[1],
++				msgs[i+1].buf, msgs[i+1].len);
++			i++;
++			if (i2c_debug>=2) {
++				for (byte = 0; byte < msgs[i].len; byte++) {
++					printk(" %02x", msgs[i].buf[byte]);
++				}
++			}
++			prev_reg = -1;
+ 		} else {
+ 			/* write bytes */
+ 			if (i2c_debug>=2) {
+@@ -134,6 +156,8 @@ static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,
+ 			if(msgs[i].len == 1 && i+1 < num && msgs[i+1].flags & I2C_M_RD
+ 					    && msgs[i+1].addr == msgs[i].addr) {
+ 				prev_reg = msgs[i].buf[0];
++				if (i2c_debug >= 2)
++					printk("\n");
+ 				continue;
+ 			}
+ 
+@@ -143,12 +167,7 @@ static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,
+ 				addr|(*msgs[i].buf)<<8, 0,
+ 				msgs[i].buf+1, msgs[i].len-1);
+ 
+-			if(msgs[i].len >= 1) {
+-				prev_reg = msgs[i].buf[0];
+-			}
+-			else {
+-				prev_reg = 0;
+-			}
++			prev_reg = -1;
+ 		}
+ 		if (i2c_debug>=2)
+ 			printk("\n");

commit d4dc673da9a94716ca2410306c1b36b5faf6c4cc
+Author: Christopher Pascoe 
+Date:   Mon Apr 27 11:27:04 2009 -0300
+
+    V4L/DVB (11626): cx23885: Two fixes for DViCO FusionHDTV DVB-T Dual Express
+    
+    Two fixes for DViCO FusionHDTV DVB-T Dual Express:
+    
+     * Reset correct tuner when reinitializing xc3028.
+     * Disable the I2C gate control to avoid locking up the I2C bus.
+    
+    Tested-by: John Knops 
+    Reviewed-by: Steven Toth 
+    Signed-off-by: Christopher Pascoe 
+    Signed-off-by: Devin Heitmueller 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c
+index a3c0565be1a9..6d6293f7d428 100644
+--- a/drivers/media/video/cx23885/cx23885-cards.c
++++ b/drivers/media/video/cx23885/cx23885-cards.c
+@@ -441,9 +441,9 @@ int cx23885_tuner_callback(void *priv, int component, int command, int arg)
+ 	case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
+ 		/* Two identical tuners on two different i2c buses,
+ 		 * we need to reset the correct gpio. */
+-		if (port->nr == 0)
++		if (port->nr == 1)
+ 			bitmask = 0x01;
+-		else if (port->nr == 1)
++		else if (port->nr == 2)
+ 			bitmask = 0x04;
+ 		break;
+ 	}
+diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c
+index f48454ab3900..0c49a98213c4 100644
+--- a/drivers/media/video/cx23885/cx23885-dvb.c
++++ b/drivers/media/video/cx23885/cx23885-dvb.c
+@@ -314,6 +314,7 @@ static struct zl10353_config dvico_fusionhdtv_xc3028 = {
+ 	.demod_address = 0x0f,
+ 	.if2           = 45600,
+ 	.no_tuner      = 1,
++	.disable_i2c_gate_ctrl = 1,
+ };
+ 
+ static struct stv0900_config netup_stv0900_config = {

commit ade0815c16734e8c25dbac9faf5b5d63bcccd533
+Author: Douglas Kosovic 
+Date:   Thu Jan 22 23:07:26 2009 -0300
+
+    V4L/DVB (10299): bttv: Add support for IVCE-8784 support for V4L2 bttv driver
+    
+    It's a quad Bt878 PCI-e x1 capture board that's basically the same as the
+    IVC-200 (quad Bt878 PCI) capture board that's currently supported in
+    the V4L2 bttv driver.
+    
+    Manufacturer's web page for IVCE-8784 with photo and info:
+      http://www.iei.com.tw/en/product_IPC.asp?model=IVCE-8784
+    
+    Signed-off-by: Douglas Kosovic 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv
+index 0d93fa1ac25e..4dfe62641374 100644
+--- a/Documentation/video4linux/CARDLIST.bttv
++++ b/Documentation/video4linux/CARDLIST.bttv
+@@ -154,3 +154,4 @@
+ 153 -> PHYTEC VD-012 (bt878)
+ 154 -> PHYTEC VD-012-X1 (bt878)
+ 155 -> PHYTEC VD-012-X2 (bt878)
++156 -> IVCE-8784                                           [0000:f050,0001:f050,0002:f050,0003:f050]
+diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c
+index d24dcc025e37..9dfd8c70e4fb 100644
+--- a/drivers/media/video/bt8xx/bttv-cards.c
++++ b/drivers/media/video/bt8xx/bttv-cards.c
+@@ -246,6 +246,10 @@ static struct CARD {
+ 	{ 0xa182ff0d, BTTV_BOARD_IVC120,        "IVC-120G" },
+ 	{ 0xa182ff0e, BTTV_BOARD_IVC120,        "IVC-120G" },
+ 	{ 0xa182ff0f, BTTV_BOARD_IVC120,        "IVC-120G" },
++	{ 0xf0500000, BTTV_BOARD_IVCE8784,      "IVCE-8784" },
++	{ 0xf0500001, BTTV_BOARD_IVCE8784,      "IVCE-8784" },
++	{ 0xf0500002, BTTV_BOARD_IVCE8784,      "IVCE-8784" },
++	{ 0xf0500003, BTTV_BOARD_IVCE8784,      "IVCE-8784" },
+ 
+ 	{ 0x41424344, BTTV_BOARD_GRANDTEC,      "GrandTec Multi Capture" },
+ 	{ 0x01020304, BTTV_BOARD_XGUARD,        "Grandtec Grand X-Guard" },
+@@ -2162,6 +2166,19 @@ struct tvcard bttv_tvcards[] = {
+ 		.muxsel         = { 2 },
+ 		.pll            = PLL_28,
+ 	},
++	[BTTV_BOARD_IVCE8784] = {
++		.name           = "IVCE-8784",
++		.video_inputs   = 1,
++		.audio_inputs   = 0,
++		.tuner          = UNSET,
++		.tuner_type     = UNSET,
++		.tuner_addr     = ADDR_UNSET,
++		.radio_addr     = ADDR_UNSET,
++		.svhs           = UNSET,
++		.gpiomask       = 0xdf,
++		.muxsel         = { 2 },
++		.pll            = PLL_28,
++	},
+ 	[BTTV_BOARD_XGUARD] = {
+ 		.name           = "Grand X-Guard / Trust 814PCI",
+ 		.video_inputs   = 16,
+diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h
+index 529bf6cf634d..a7bcad171823 100644
+--- a/drivers/media/video/bt8xx/bttv.h
++++ b/drivers/media/video/bt8xx/bttv.h
+@@ -180,6 +180,7 @@
+ #define BTTV_BOARD_VD012		   0x99
+ #define BTTV_BOARD_VD012_X1		   0x9a
+ #define BTTV_BOARD_VD012_X2		   0x9b
++#define BTTV_BOARD_IVCE8784		   0x9c
+ 
+ 
+ /* more card-specific defines */

commit 8765561fc88131bbc9a6246010c15b63595ec35e
+Author: Chris Pascoe 
+Date:   Tue Apr 22 14:45:15 2008 -0300
+
+    V4L/DVB (7259): FusionHDTV DVB-T Pro tuning problem fixes
+    
+    It seems that on this board, the demodulator provides the pullup on the I2C
+    bus, which means that calling i2c_gate_ctrl crashes the bus.  Turn this off
+    and the xc3028 can talk OK.  Also fix some GPIO related settings that
+    became more clear through working on this.
+    
+    Some changes made by Mauro Chehab to allow merging it with some
+    other xc3028 patches.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
+index 1dc70f27f7f9..1fe6b9da9815 100644
+--- a/drivers/media/video/cx88/cx88-cards.c
++++ b/drivers/media/video/cx88/cx88-cards.c
+@@ -2038,11 +2038,9 @@ static int cx88_dvico_xc2028_callback(void *ptr, int command, int arg)
+ 
+ 	switch (command) {
+ 	case XC2028_TUNER_RESET:
+-		cx_set(MO_GP0_IO, 0x0200);
+-		cx_clear(MO_GP0_IO, 0x02);
+-		mdelay(100);
+-		cx_set(MO_GP0_IO, 0x02);
+-		mdelay(100);
++		cx_write(MO_GP0_IO, 0x101000);
++		mdelay(5);
++		cx_set(MO_GP0_IO, 0x101010);
+ 		break;
+ 	default:
+ 		return -EINVAL;
+@@ -2302,6 +2300,13 @@ static void cx88_card_setup(struct cx88_core *core)
+ 		cx_write(MO_GP0_IO, 0x000007f8);
+ 		cx_write(MO_GP1_IO, 0x00000001);
+ 		break;
++	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
++		/* GPIO0:0 is hooked to demod reset */
++		/* GPIO0:4 is hooked to xc3028 reset */
++		cx_write(MO_GP0_IO, 0x00111100);
++		msleep(1);
++		cx_write(MO_GP0_IO, 0x00111111);
++		break;
+ 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
+ 		/* GPIO0:6 is hooked to FX2 reset pin */
+ 		cx_set(MO_GP0_IO, 0x00004040);
+@@ -2312,7 +2317,6 @@ static void cx88_card_setup(struct cx88_core *core)
+ 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
+ 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
+ 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
+-	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
+ 		/* GPIO0:0 is hooked to mt352 reset pin */
+ 		cx_set(MO_GP0_IO, 0x00000101);
+ 		cx_clear(MO_GP0_IO, 0x00000001);
+diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
+index 591037d8d14f..ae2a0f5f0806 100644
+--- a/drivers/media/video/cx88/cx88-dvb.c
++++ b/drivers/media/video/cx88/cx88-dvb.c
+@@ -588,6 +588,14 @@ static int dvb_register(struct cx8802_dev *dev)
+ 			dev->dvb.frontend = dvb_attach(mt352_attach,
+ 						&dvico_fusionhdtv_mt352_xc3028,
+ 						&dev->core->i2c_adap);
++		/*
++		 * On this board, the demod provides the I2C bus pullup.
++		 * We must not permit gate_ctrl to be performed, or
++		 * the xc3028 cannot communicate on the bus.
++		 */
++		if (dev->dvb.frontend)
++			dev->dvb.frontend->ops.i2c_gate_ctrl = NULL;
++
+ 		attach_xc3028 = 1;
+ 		break;
+ 	case CX88_BOARD_PCHDTV_HD3000:

commit b3fb91d20ca111316854a166ff88b0c8c0f2388b
+Author: Chris Pascoe 
+Date:   Tue Apr 22 14:45:15 2008 -0300
+
+    V4L/DVB (7258): Support DVB-T tuning on the DViCO FusionHDTV DVB-T Pro
+    
+    Add support for tuning DVB-T channels on DViCO's FusionHDTV DVB-T Pro board.
+    
+    The IR remote and analog tuner are not supported at this time.
+    
+    Some changes made by Mauro Chehab to allow merging it with some other xc3028
+    patches.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88
+index c92795b6e697..423da1543815 100644
+--- a/Documentation/video4linux/CARDLIST.cx88
++++ b/Documentation/video4linux/CARDLIST.cx88
+@@ -62,3 +62,4 @@
+  61 -> Winfast TV2000 XP Global                            [107d:6f18]
+  62 -> PowerColor Real Angel 330                           [14f1:ea3d]
+  63 -> Geniatech X8000-MT DVBT                             [14f1:8852]
++ 64 -> DViCO FusionHDTV DVB-T PRO                          [18ac:db30]
+diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
+index d07286fa21f5..1dc70f27f7f9 100644
+--- a/drivers/media/video/cx88/cx88-cards.c
++++ b/drivers/media/video/cx88/cx88-cards.c
+@@ -1543,7 +1543,24 @@ static const struct cx88_board cx88_boards[] = {
+ 		       .gpio3  = 0x00000000,
+ 	       },
+ 	       .mpeg           = CX88_MPEG_DVB,
+-       }
++       },
++       [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO] = {
++	       .name           = "DViCO FusionHDTV DVB-T PRO",
++	       .tuner_type     = TUNER_ABSENT, /* XXX: Has XC3028 */
++	       .radio_type     = UNSET,
++	       .tuner_addr     = ADDR_UNSET,
++	       .radio_addr     = ADDR_UNSET,
++	       .input          = { {
++		       .type   = CX88_VMUX_COMPOSITE1,
++		       .vmux   = 1,
++		       .gpio0  = 0x000067df,
++		}, {
++		       .type   = CX88_VMUX_SVIDEO,
++		       .vmux   = 2,
++		       .gpio0  = 0x000067df,
++	       } },
++	       .mpeg           = CX88_MPEG_DVB,
++       },
+ };
+ 
+ /* ------------------------------------------------------------------ */
+@@ -1748,7 +1765,11 @@ static const struct cx88_subid cx88_subids[] = {
+ 		.subdevice = 0xdb11,
+ 		.card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS,
+ 		/* Re-branded DViCO: UltraView DVB-T Plus */
+-	},{
++	}, {
++		.subvendor = 0x18ac,
++		.subdevice = 0xdb30,
++		.card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO,
++	}, {
+ 		.subvendor = 0x17de,
+ 		.subdevice = 0x0840,
+ 		.card      = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT,
+@@ -2009,6 +2030,28 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data)
+ 		CX88_RADIO : 0;
+ }
+ 
++/* ------------------------------------------------------------------- */
++/* some Divco specific stuff                                           */
++static int cx88_dvico_xc2028_callback(void *ptr, int command, int arg)
++{
++	struct cx88_core *core = ptr;
++
++	switch (command) {
++	case XC2028_TUNER_RESET:
++		cx_set(MO_GP0_IO, 0x0200);
++		cx_clear(MO_GP0_IO, 0x02);
++		mdelay(100);
++		cx_set(MO_GP0_IO, 0x02);
++		mdelay(100);
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	return 0;
++}
++
++
+ /* ----------------------------------------------------------------------- */
+ /* some Geniatech specific stuff                                           */
+ 
+@@ -2098,6 +2141,8 @@ static int cx88_xc2028_tuner_callback(void *priv, int command, int arg)
+ 	case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
+ 	case CX88_BOARD_GENIATECH_X8000_MT:
+ 		return cx88_xc3028_geniatech_tuner_callback(priv, command, arg);
++	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
++		return cx88_dvico_xc2028_callback(priv, command, arg);
+ 	}
+ 
+ 	switch (command) {
+@@ -2267,6 +2312,7 @@ static void cx88_card_setup(struct cx88_core *core)
+ 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
+ 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
+ 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
++	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
+ 		/* GPIO0:0 is hooked to mt352 reset pin */
+ 		cx_set(MO_GP0_IO, 0x00000101);
+ 		cx_clear(MO_GP0_IO, 0x00000001);
+@@ -2338,9 +2384,18 @@ static void cx88_card_setup(struct cx88_core *core)
+ 
+ 		ctl.fname   = XC2028_DEFAULT_FIRMWARE;
+ 		ctl.max_len = 64;
+-		/* FIXME: Those should be device-dependent */
+-		ctl.demod = XC3028_FE_OREN538;
+-		ctl.mts = 1;
++
++		switch (core->boardnr) {
++		case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
++			ctl.scode_table = XC3028_FE_ZARLINK456;
++			break;
++		case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
++			ctl.demod = XC3028_FE_OREN538;
++			break;
++		default:
++			ctl.demod = XC3028_FE_OREN538;
++			ctl.mts = 1;
++		}
+ 
+ 		xc2028_cfg.tuner = TUNER_XC2028;
+ 		xc2028_cfg.priv  = &ctl;
+diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
+index c786d951a04b..591037d8d14f 100644
+--- a/drivers/media/video/cx88/cx88-dvb.c
++++ b/drivers/media/video/cx88/cx88-dvb.c
+@@ -237,6 +237,19 @@ static struct zl10353_config dvico_fusionhdtv_hybrid = {
+ 	.no_tuner      = 1,
+ };
+ 
++static struct zl10353_config dvico_fusionhdtv_xc3028 = {
++	.demod_address = 0x0f,
++	.if2           = 45600,
++	.no_tuner      = 1,
++};
++
++static struct mt352_config dvico_fusionhdtv_mt352_xc3028 = {
++	.demod_address = 0x0f,
++	.if2 = 4560,
++	.no_tuner = 1,
++	.demod_init = dvico_fusionhdtv_demod_init,
++};
++
+ static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = {
+ 	.demod_address = 0x0f,
+ };
+@@ -567,6 +580,16 @@ static int dvb_register(struct cx8802_dev *dev)
+ 				   DVB_PLL_THOMSON_FE6600);
+ 		}
+ 		break;
++	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
++		dev->dvb.frontend = dvb_attach(zl10353_attach,
++					       &dvico_fusionhdtv_xc3028,
++					       &dev->core->i2c_adap);
++		if (dev->dvb.frontend == NULL)
++			dev->dvb.frontend = dvb_attach(mt352_attach,
++						&dvico_fusionhdtv_mt352_xc3028,
++						&dev->core->i2c_adap);
++		attach_xc3028 = 1;
++		break;
+ 	case CX88_BOARD_PCHDTV_HD3000:
+ 		dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
+ 					       &dev->core->i2c_adap);
+diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
+index 5145bf2f5557..9df3f198a4df 100644
+--- a/drivers/media/video/cx88/cx88.h
++++ b/drivers/media/video/cx88/cx88.h
+@@ -216,6 +216,7 @@ extern struct sram_channel cx88_sram_channels[];
+ #define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL 61
+ #define CX88_BOARD_POWERCOLOR_REAL_ANGEL   62
+ #define CX88_BOARD_GENIATECH_X8000_MT      63
++#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO 64
+ 
+ enum cx88_itype {
+ 	CX88_VMUX_COMPOSITE1 = 1,

commit 0aaa22e554c0934625faf79deea42bfecbdbc23d
+Author: Douglas Kosovic 
+Date:   Tue Jan 29 15:02:50 2008 +0100
+
+    [ALSA] hda-codec - Add Dell T3400 support
+    
+    Added the support for Dell T3400 with AD1984 codec chip.
+    ALSA bug#3699:
+            https://bugtrack.alsa-project.org/alsa-bug/view.php?id=3699
+    
+    Signed-off-by: Douglas Kosovic 
+    Signed-off-by: Takashi Iwai 
+    Signed-off-by: Jaroslav Kysela 
+
+diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
+index 73f5012326ba..e985cf5e0410 100644
+--- a/Documentation/sound/alsa/ALSA-Configuration.txt
++++ b/Documentation/sound/alsa/ALSA-Configuration.txt
+@@ -926,6 +926,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
+ 	AD1984
+ 	  basic		default configuration
+ 	  thinkpad	Lenovo Thinkpad T61/X61
++	  dell		Dell T3400
+ 
+ 	AD1986A
+ 	  6stack	6-jack, separate surrounds (default)
+diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
+index 845e949a7f63..19f08846d6fc 100644
+--- a/sound/pci/hda/patch_analog.c
++++ b/sound/pci/hda/patch_analog.c
+@@ -3141,6 +3141,20 @@ static struct hda_input_mux ad1984_thinkpad_capture_source = {
+ 	},
+ };
+ 
++
++/*
++ * Dell Precision T3400
++ */
++static struct hda_input_mux ad1984_dell_desktop_capture_source = {
++	.num_items = 3,
++	.items = {
++		{ "Front Mic", 0x0 },
++		{ "Line-In", 0x1 },
++		{ "Mix", 0x3 },
++	},
++};
++
++
+ static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
+ 	HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
+ 	/* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
+@@ -3200,6 +3214,44 @@ static struct hda_verb ad1984_thinkpad_init_verbs[] = {
+ 	{ } /* end */
+ };
+ 
++/*
++ * Dell Precision T3400
++ */
++static struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = {
++	HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
++	HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
++	HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
++	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
++	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
++	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
++	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
++	HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT),
++	HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT),
++	/*
++	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x20, 0x03, HDA_INPUT),
++	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x20, 0x03, HDA_INPUT),
++	*/
++	HDA_CODEC_VOLUME("Line-In Boost", 0x15, 0x0, HDA_INPUT),
++	HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
++	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
++	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
++	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
++	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
++	{
++		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++		/* The multiple "Capture Source" controls confuse alsamixer
++		 * So call somewhat different..
++		 */
++		/* .name = "Capture Source", */
++		.name = "Input Source",
++		.count = 2,
++		.info = ad198x_mux_enum_info,
++		.get = ad198x_mux_enum_get,
++		.put = ad198x_mux_enum_put,
++	},
++	{ } /* end */
++};
++
+ /* Digial MIC ADC NID 0x05 + 0x06 */
+ static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo,
+ 				   struct hda_codec *codec,
+@@ -3253,17 +3305,20 @@ static int ad1984_build_pcms(struct hda_codec *codec)
+ enum {
+ 	AD1984_BASIC,
+ 	AD1984_THINKPAD,
++	AD1984_DELL_DESKTOP,
+ 	AD1984_MODELS
+ };
+ 
+ static const char *ad1984_models[AD1984_MODELS] = {
+ 	[AD1984_BASIC]		= "basic",
+ 	[AD1984_THINKPAD]	= "thinkpad",
++	[AD1984_DELL_DESKTOP]	= "dell_desktop",
+ };
+ 
+ static struct snd_pci_quirk ad1984_cfg_tbl[] = {
+ 	/* Lenovo Thinkpad T61/X61 */
+ 	SND_PCI_QUIRK(0x17aa, 0, "Lenovo Thinkpad", AD1984_THINKPAD),
++	SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
+ 	{}
+ };
+ 
+@@ -3290,6 +3345,11 @@ static int patch_ad1984(struct hda_codec *codec)
+ 		spec->mixers[0] = ad1984_thinkpad_mixers;
+ 		spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;
+ 		break;
++	case AD1984_DELL_DESKTOP:
++		spec->multiout.dig_out_nid = 0;
++		spec->input_mux = &ad1984_dell_desktop_capture_source;
++		spec->mixers[0] = ad1984_dell_desktop_mixers;
++		break;
+ 	}
+ 	return 0;
+ }

commit ef207feddf826f099562b239543c447e68991b84
+Author: Chris Pascoe 
+Date:   Sun Dec 2 09:30:55 2007 -0300
+
+    V4L/DVB (6897): xc2028: ignore HAS_IF during specific S-Code type searches
+    
+    If we are selecting the S-Code firmware to load by name, then we must mask
+    off the HAS_IF bit during the search.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index ddd94f1d6a6f..1817bf67dad1 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -395,6 +395,7 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
+ {
+ 	struct xc2028_data *priv = fe->tuner_priv;
+ 	int                 i, best_i = -1, best_nr_matches = 0;
++	unsigned int        ign_firm_type_mask = 0;
+ 
+ 	tuner_dbg("%s called, want type=", __FUNCTION__);
+ 	if (debug) {
+@@ -412,16 +413,18 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
+ 
+ 	if (type & BASE)
+ 		type &= BASE_TYPES;
+-	else if (type & SCODE)
++	else if (type & SCODE) {
+ 		type &= SCODE_TYPES;
+-	else if (type & DTV_TYPES)
++		ign_firm_type_mask = HAS_IF;
++	} else if (type & DTV_TYPES)
+ 		type &= DTV_TYPES;
+ 	else if (type & STD_SPECIFIC_TYPES)
+ 		type &= STD_SPECIFIC_TYPES;
+ 
+ 	/* Seek for exact match */
+ 	for (i = 0; i < priv->firm_size; i++) {
+-		if ((type == priv->firm[i].type) && (*id == priv->firm[i].id))
++		if ((type == (priv->firm[i].type & ~ign_firm_type_mask)) &&
++		    (*id == priv->firm[i].id))
+ 			goto found;
+ 	}
+ 
+@@ -430,7 +433,7 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
+ 		v4l2_std_id match_mask;
+ 		int nr_matches;
+ 
+-		if (type != priv->firm[i].type)
++		if (type != (priv->firm[i].type & ~ign_firm_type_mask))
+ 			continue;
+ 
+ 		match_mask = *id & priv->firm[i].id;

commit 5e3c5967da48b54e5d4ee528b51b565e2f7a3178
+Author: Chris Pascoe 
+Date:   Sat Dec 15 03:31:09 2007 -0300
+
+    V4L/DVB (6857): cx23885: correctly join I2C writes and reads from same address
+    
+    When an I2C message specifies a write then a read from the same I2C address,
+    we need to tell the chip to not release the bus between the message parts.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c
+index 08e92df33168..20f3fb450f88 100644
+--- a/drivers/media/video/cx23885/cx23885-i2c.c
++++ b/drivers/media/video/cx23885/cx23885-i2c.c
+@@ -37,8 +37,10 @@ static unsigned int i2c_scan = 0;
+ module_param(i2c_scan, int, 0444);
+ MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
+ 
+-#define dprintk(level,fmt, arg...)	if (i2c_debug >= level) \
+-	printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg)
++#define dprintk(level, fmt, arg...)	do { \
++	if (i2c_debug >= level) \
++		printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg); \
++	} while (0)
+ 
+ #define I2C_WAIT_DELAY 32
+ #define I2C_WAIT_RETRY 64
+@@ -77,14 +79,18 @@ static int i2c_wait_done(struct i2c_adapter *i2c_adap)
+ }
+ 
+ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
+-			 const struct i2c_msg *msg, int last)
++			 const struct i2c_msg *msg, int joined_rlen)
+ {
+ 	struct cx23885_i2c *bus = i2c_adap->algo_data;
+ 	struct cx23885_dev *dev = bus->dev;
+ 	u32 wdata, addr, ctrl;
+ 	int retval, cnt;
+ 
+-	dprintk(1, "%s(msg->len=%d, last=%d)\n", __FUNCTION__, msg->len, last);
++	if (joined_rlen)
++		dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __FUNCTION__,
++			msg->len, joined_rlen);
++	else
++		dprintk(1, "%s(msg->len=%d)\n", __FUNCTION__, msg->len);
+ 
+ 	/* Deal with i2c probe functions with zero payload */
+ 	if (msg->len == 0) {
+@@ -107,6 +113,8 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
+ 
+ 	if (msg->len > 1)
+ 		ctrl |= I2C_NOSTOP | I2C_EXTEND;
++	else if (joined_rlen)
++		ctrl |= I2C_NOSTOP;
+ 
+ 	cx_write(bus->reg_addr, addr);
+ 	cx_write(bus->reg_wdata, wdata);
+@@ -130,6 +138,8 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
+ 
+ 		if (cnt < msg->len - 1)
+ 			ctrl |= I2C_NOSTOP | I2C_EXTEND;
++		else if (joined_rlen)
++			ctrl |= I2C_NOSTOP;
+ 
+ 		cx_write(bus->reg_addr, addr);
+ 		cx_write(bus->reg_wdata, wdata);
+@@ -151,19 +161,22 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
+  eio:
+ 	retval = -EIO;
+  err:
+-	printk(" ERR: %d\n", retval);
++	if (i2c_debug)
++		printk(" ERR: %d\n", retval);
+ 	return retval;
+ }
+ 
+ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
+-			 const struct i2c_msg *msg, int last)
++			 const struct i2c_msg *msg, int joined)
+ {
+ 	struct cx23885_i2c *bus = i2c_adap->algo_data;
+ 	struct cx23885_dev *dev = bus->dev;
+ 	u32 ctrl, cnt;
+ 	int retval;
+ 
+-	dprintk(1, "%s(msg->len=%d, last=%d)\n", __FUNCTION__, msg->len, last);
++
++	if (i2c_debug && !joined)
++		dprintk(1, "%s(msg->len=%d)\n", __FUNCTION__, msg->len);
+ 
+ 	/* Deal with i2c probe functions with zero payload */
+ 	if (msg->len == 0) {
+@@ -179,8 +192,12 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
+ 		return 0;
+ 	}
+ 
+-	if (i2c_debug)
+-		printk(" addr << 1) + 1);
++	if (i2c_debug) {
++		if (joined)
++			printk(" R");
++		else
++			printk(" addr << 1) + 1);
++	}
+ 
+ 	for(cnt = 0; cnt < msg->len; cnt++) {
+ 
+@@ -209,7 +226,8 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
+  eio:
+ 	retval = -EIO;
+  err:
+-	printk(" ERR: %d\n", retval);
++	if (i2c_debug)
++		printk(" ERR: %d\n", retval);
+ 	return retval;
+ }
+ 
+@@ -227,15 +245,22 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap,
+ 			__FUNCTION__, num, msgs[i].addr, msgs[i].len);
+ 		if (msgs[i].flags & I2C_M_RD) {
+ 			/* read */
+-			retval = i2c_readbytes(i2c_adap, &msgs[i], i+1 == num);
++			retval = i2c_readbytes(i2c_adap, &msgs[i], 0);
++		} else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
++			   msgs[i].addr == msgs[i + 1].addr) {
++			/* write then read from same address */
++			retval = i2c_sendbytes(i2c_adap, &msgs[i],
++					       msgs[i + 1].len);
+ 			if (retval < 0)
+ 				goto err;
++			i++;
++			retval = i2c_readbytes(i2c_adap, &msgs[i], 1);
+ 		} else {
+ 			/* write */
+-			retval = i2c_sendbytes(i2c_adap, &msgs[i], i+1 == num);
+-			if (retval < 0)
+-				goto err;
++			retval = i2c_sendbytes(i2c_adap, &msgs[i], 0);
+ 		}
++		if (retval < 0)
++			goto err;
+ 	}
+ 	return num;
+ 

commit bc514710889ebb975be9e84ca9c04f698225b656
+Author: Chris Pascoe 
+Date:   Sat Dec 15 03:24:00 2007 -0300
+
+    V4L/DVB (6856): zl10353: improve tuning parameters and update register map
+    
+    Some more I2C traces and a experimentation with register values on
+    both the ZL10353 and MT352 mean that I can now guess at what more
+    of the ZL10353 registers do.
+    
+    Guess at the registers' names (based on the equivalent names in MT352)
+    and update set_parameters/get_parameters with the new knowledge.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c
+index e874ec8df60c..276e3b631dc2 100644
+--- a/drivers/media/dvb/frontends/zl10353.c
++++ b/drivers/media/dvb/frontends/zl10353.c
+@@ -36,6 +36,8 @@ struct zl10353_state {
+ 	struct dvb_frontend frontend;
+ 
+ 	struct zl10353_config config;
++
++	enum fe_bandwidth bandwidth;
+ };
+ 
+ static int debug;
+@@ -195,27 +197,156 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
+ {
+ 	struct zl10353_state *state = fe->demodulator_priv;
+ 	u16 nominal_rate, input_freq;
+-	u8 pllbuf[6] = { 0x67 };
++	u8 pllbuf[6] = { 0x67 }, acq_ctl = 0;
++	u16 tps = 0;
++	struct dvb_ofdm_parameters *op = ¶m->u.ofdm;
+ 
+-	/* These settings set "auto-everything" and start the FSM. */
+-	zl10353_single_write(fe, 0x55, 0x80);
++	zl10353_single_write(fe, RESET, 0x80);
+ 	udelay(200);
+ 	zl10353_single_write(fe, 0xEA, 0x01);
+ 	udelay(200);
+ 	zl10353_single_write(fe, 0xEA, 0x00);
+ 
+-	zl10353_single_write(fe, 0x56, 0x28);
+-	zl10353_single_write(fe, 0x89, 0x20);
+-	zl10353_single_write(fe, 0x5E, 0x00);
++	zl10353_single_write(fe, AGC_TARGET, 0x28);
++
++	if (op->transmission_mode != TRANSMISSION_MODE_AUTO)
++		acq_ctl |= (1 << 0);
++	if (op->guard_interval != GUARD_INTERVAL_AUTO)
++		acq_ctl |= (1 << 1);
++	zl10353_single_write(fe, ACQ_CTL, acq_ctl);
+ 
+-	zl10353_calc_nominal_rate(fe, param->u.ofdm.bandwidth, &nominal_rate);
++	switch (op->bandwidth) {
++	case BANDWIDTH_6_MHZ:
++		/* These are extrapolated from the 7 and 8MHz values */
++		zl10353_single_write(fe, MCLK_RATIO, 0x97);
++		zl10353_single_write(fe, 0x64, 0x34);
++		break;
++	case BANDWIDTH_7_MHZ:
++		zl10353_single_write(fe, MCLK_RATIO, 0x86);
++		zl10353_single_write(fe, 0x64, 0x35);
++		break;
++	case BANDWIDTH_8_MHZ:
++	default:
++		zl10353_single_write(fe, MCLK_RATIO, 0x75);
++		zl10353_single_write(fe, 0x64, 0x36);
++	}
++
++	zl10353_calc_nominal_rate(fe, op->bandwidth, &nominal_rate);
+ 	zl10353_single_write(fe, TRL_NOMINAL_RATE_1, msb(nominal_rate));
+ 	zl10353_single_write(fe, TRL_NOMINAL_RATE_0, lsb(nominal_rate));
++	state->bandwidth = op->bandwidth;
+ 
+ 	zl10353_calc_input_freq(fe, &input_freq);
+ 	zl10353_single_write(fe, INPUT_FREQ_1, msb(input_freq));
+ 	zl10353_single_write(fe, INPUT_FREQ_0, lsb(input_freq));
+ 
++	/* Hint at TPS settings */
++	switch (op->code_rate_HP) {
++	case FEC_2_3:
++		tps |= (1 << 7);
++		break;
++	case FEC_3_4:
++		tps |= (2 << 7);
++		break;
++	case FEC_5_6:
++		tps |= (3 << 7);
++		break;
++	case FEC_7_8:
++		tps |= (4 << 7);
++		break;
++	case FEC_1_2:
++	case FEC_AUTO:
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	switch (op->code_rate_LP) {
++	case FEC_2_3:
++		tps |= (1 << 4);
++		break;
++	case FEC_3_4:
++		tps |= (2 << 4);
++		break;
++	case FEC_5_6:
++		tps |= (3 << 4);
++		break;
++	case FEC_7_8:
++		tps |= (4 << 4);
++		break;
++	case FEC_1_2:
++	case FEC_AUTO:
++		break;
++	case FEC_NONE:
++		if (op->hierarchy_information == HIERARCHY_AUTO ||
++		    op->hierarchy_information == HIERARCHY_NONE)
++			break;
++	default:
++		return -EINVAL;
++	}
++
++	switch (op->constellation) {
++	case QPSK:
++		break;
++	case QAM_AUTO:
++	case QAM_16:
++		tps |= (1 << 13);
++		break;
++	case QAM_64:
++		tps |= (2 << 13);
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	switch (op->transmission_mode) {
++	case TRANSMISSION_MODE_2K:
++	case TRANSMISSION_MODE_AUTO:
++		break;
++	case TRANSMISSION_MODE_8K:
++		tps |= (1 << 0);
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	switch (op->guard_interval) {
++	case GUARD_INTERVAL_1_32:
++	case GUARD_INTERVAL_AUTO:
++		break;
++	case GUARD_INTERVAL_1_16:
++		tps |= (1 << 2);
++		break;
++	case GUARD_INTERVAL_1_8:
++		tps |= (2 << 2);
++		break;
++	case GUARD_INTERVAL_1_4:
++		tps |= (3 << 2);
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	switch (op->hierarchy_information) {
++	case HIERARCHY_AUTO:
++	case HIERARCHY_NONE:
++		break;
++	case HIERARCHY_1:
++		tps |= (1 << 10);
++		break;
++	case HIERARCHY_2:
++		tps |= (2 << 10);
++		break;
++	case HIERARCHY_4:
++		tps |= (3 << 10);
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	zl10353_single_write(fe, TPS_GIVEN_1, msb(tps));
++	zl10353_single_write(fe, TPS_GIVEN_0, lsb(tps));
++
+ 	if (fe->ops.i2c_gate_ctrl)
+ 		fe->ops.i2c_gate_ctrl(fe, 0);
+ 
+@@ -244,12 +375,97 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
+ 	else
+ 		zl10353_single_write(fe, TUNER_GO, 0x01);
+ 
+-	udelay(250);
+-	zl10353_single_write(fe, 0xE4, 0x00);
+-	zl10353_single_write(fe, 0xE5, 0x2A);
+-	zl10353_single_write(fe, 0xE9, 0x02);
+-	zl10353_single_write(fe, 0xE7, 0x40);
+-	zl10353_single_write(fe, 0xE8, 0x10);
++	return 0;
++}
++
++static int zl10353_get_parameters(struct dvb_frontend *fe,
++				  struct dvb_frontend_parameters *param)
++{
++	struct zl10353_state *state = fe->demodulator_priv;
++	struct dvb_ofdm_parameters *op = ¶m->u.ofdm;
++	int s6, s9;
++	u16 tps;
++	static const u8 tps_fec_to_api[8] = {
++		FEC_1_2,
++		FEC_2_3,
++		FEC_3_4,
++		FEC_5_6,
++		FEC_7_8,
++		FEC_AUTO,
++		FEC_AUTO,
++		FEC_AUTO
++	};
++
++	s6 = zl10353_read_register(state, STATUS_6);
++	s9 = zl10353_read_register(state, STATUS_9);
++	if (s6 < 0 || s9 < 0)
++		return -EREMOTEIO;
++	if ((s6 & (1 << 5)) == 0 || (s9 & (1 << 4)) == 0)
++		return -EINVAL;	/* no FE or TPS lock */
++
++	tps = zl10353_read_register(state, TPS_RECEIVED_1) << 8 |
++	      zl10353_read_register(state, TPS_RECEIVED_0);
++
++	op->code_rate_HP = tps_fec_to_api[(tps >> 7) & 7];
++	op->code_rate_LP = tps_fec_to_api[(tps >> 4) & 7];
++
++	switch ((tps >> 13) & 3) {
++	case 0:
++		op->constellation = QPSK;
++		break;
++	case 1:
++		op->constellation = QAM_16;
++		break;
++	case 2:
++		op->constellation = QAM_64;
++		break;
++	default:
++		op->constellation = QAM_AUTO;
++		break;
++	}
++
++	op->transmission_mode = (tps & 0x01) ? TRANSMISSION_MODE_8K :
++					       TRANSMISSION_MODE_2K;
++
++	switch ((tps >> 2) & 3) {
++	case 0:
++		op->guard_interval = GUARD_INTERVAL_1_32;
++		break;
++	case 1:
++		op->guard_interval = GUARD_INTERVAL_1_16;
++		break;
++	case 2:
++		op->guard_interval = GUARD_INTERVAL_1_8;
++		break;
++	case 3:
++		op->guard_interval = GUARD_INTERVAL_1_4;
++		break;
++	default:
++		op->guard_interval = GUARD_INTERVAL_AUTO;
++		break;
++	}
++
++	switch ((tps >> 10) & 7) {
++	case 0:
++		op->hierarchy_information = HIERARCHY_NONE;
++		break;
++	case 1:
++		op->hierarchy_information = HIERARCHY_1;
++		break;
++	case 2:
++		op->hierarchy_information = HIERARCHY_2;
++		break;
++	case 3:
++		op->hierarchy_information = HIERARCHY_4;
++		break;
++	default:
++		op->hierarchy_information = HIERARCHY_AUTO;
++		break;
++	}
++
++	param->frequency = 0;
++	op->bandwidth = state->bandwidth;
++	param->inversion = INVERSION_AUTO;
+ 
+ 	return 0;
+ }
+@@ -438,6 +654,7 @@ static struct dvb_frontend_ops zl10353_ops = {
+ 	.write = zl10353_write,
+ 
+ 	.set_frontend = zl10353_set_parameters,
++	.get_frontend = zl10353_get_parameters,
+ 	.get_tune_settings = zl10353_get_tune_settings,
+ 
+ 	.read_status = zl10353_read_status,
+diff --git a/drivers/media/dvb/frontends/zl10353_priv.h b/drivers/media/dvb/frontends/zl10353_priv.h
+index fcad9221945e..055ff1f7e349 100644
+--- a/drivers/media/dvb/frontends/zl10353_priv.h
++++ b/drivers/media/dvb/frontends/zl10353_priv.h
+@@ -46,13 +46,28 @@ enum zl10353_reg_addr {
+ 	RS_ERR_CNT_0       = 0x13,
+ 	RS_UBC_1           = 0x14,
+ 	RS_UBC_0           = 0x15,
++	TPS_RECEIVED_1     = 0x1D,
++	TPS_RECEIVED_0     = 0x1E,
++	TPS_CURRENT_1      = 0x1F,
++	TPS_CURRENT_0      = 0x20,
++	RESET              = 0x55,
++	AGC_TARGET         = 0x56,
++	MCLK_RATIO         = 0x5C,
++	ACQ_CTL            = 0x5E,
+ 	TRL_NOMINAL_RATE_1 = 0x65,
+ 	TRL_NOMINAL_RATE_0 = 0x66,
+ 	INPUT_FREQ_1       = 0x6C,
+ 	INPUT_FREQ_0       = 0x6D,
++	TPS_GIVEN_1        = 0x6E,
++	TPS_GIVEN_0        = 0x6F,
+ 	TUNER_GO           = 0x70,
+ 	FSM_GO             = 0x71,
+ 	CHIP_ID            = 0x7F,
++	CHAN_STEP_1        = 0xE4,
++	CHAN_STEP_0        = 0xE5,
++	OFDM_LOCK_TIME     = 0xE7,
++	FEC_LOCK_TIME      = 0xE8,
++	ACQ_DELAY          = 0xE9,
+ };
+ 
+ #endif                          /* _ZL10353_PRIV_ */

commit 3dfefc50ff45744ffb97ce0bf9c213a3fb6d5d3d
+Author: Chris Pascoe 
+Date:   Sun Dec 2 10:07:06 2007 -0300
+
+    V4L/DVB (6855): xc2028: select DTV78 firmware if tuning 7MHz VHF / 8MHz UHF
+    
+    It seems that the DTV78 firmware is intended for use in locations where
+    VHF channels have 7MHz bandwidth and UHF channels have 8MHz bandwidth.
+    If we switch to DTV78 firmware when we detect this condition, we can
+    avoid firmware reloads when switching between VHF and UHF transponders.
+    
+    Place the state for this in the control structure so that card drivers
+    can hint to us to use DTV78 firmware from the first tuning attempt.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index 63a6fca1f8cf..0565edd224bc 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -998,20 +998,27 @@ static int xc2028_set_params(struct dvb_frontend *fe,
+ 		return -EINVAL;
+ 	}
+ 
+-	/* FIXME:
+-	  There are two Scodes that will never be selected:
+-		DTV78 ZARLINK456, DTV78 DIBCOM52
+-	  When it should opt for DTV78 instead of DTV7 or DTV8?
+-	*/
+ 	switch (bw) {
+ 	case BANDWIDTH_8_MHZ:
+-		type |= DTV8 | F8MHZ;
++		if (p->frequency < 470000000)
++			priv->ctrl.vhfbw7 = 0;
++		else
++			priv->ctrl.uhfbw8 = 1;
++		type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV8;
++		type |= F8MHZ;
+ 		break;
+ 	case BANDWIDTH_7_MHZ:
+-		type |= DTV7 | F8MHZ;
++		if (p->frequency < 470000000)
++			priv->ctrl.vhfbw7 = 1;
++		else
++			priv->ctrl.uhfbw8 = 0;
++		type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV7;
++		type |= F8MHZ;
+ 		break;
+ 	case BANDWIDTH_6_MHZ:
+-		type |= DTV6 ;
++		type |= DTV6;
++		priv->ctrl.vhfbw7 = 0;
++		priv->ctrl.uhfbw8 = 0;
+ 		break;
+ 	default:
+ 		tuner_err("error: bandwidth not supported.\n");
+diff --git a/drivers/media/video/tuner-xc2028.h b/drivers/media/video/tuner-xc2028.h
+index 1fe8b195960c..7462629b98fd 100644
+--- a/drivers/media/video/tuner-xc2028.h
++++ b/drivers/media/video/tuner-xc2028.h
+@@ -30,6 +30,8 @@ struct xc2028_ctrl {
+ 	unsigned int		mts   :1;
+ 	unsigned int		d2633 :1;
+ 	unsigned int		input1:1;
++	unsigned int		vhfbw7:1;
++	unsigned int		uhfbw8:1;
+ 	unsigned int		demod;
+ };
+ 

commit 897b842296f1285a6b58e9170f7017022e2e2603
+Author: Chris Pascoe 
+Date:   Sun Dec 2 09:39:18 2007 -0300
+
+    V4L/DVB (6854): xc2028: be more specific about when applying offset for 7MHz channels
+    
+    We have been inserting a mystery 500kHz offset for tuning 7MHz channels,
+    however some experimentation reveals it is only needed under certain
+    conditions with specific firmware combinations.  Document these and only
+    apply the offset when we know it is required.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index a6b05dfd6703..63a6fca1f8cf 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -875,7 +875,16 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
+ 		rc = send_seq(priv, {0x00, 0x00});
+ 	} else {
+ 		offset = 2750000;
+-		if (priv->cur_fw.type & DTV7)
++		/*
++		 * We must adjust the offset by 500kHz in two cases in order
++		 * to correctly center the IF output:
++		 * 1) When the ZARLINK456 or DIBCOM52 tables were explicitly
++		 *    selected and a 7MHz channel is tuned;
++		 * 2) When tuning a VHF channel with DTV78 firmware.
++		 */
++		if (((priv->cur_fw.type & DTV7) &&
++		     (priv->cur_fw.scode_table & (ZARLINK456 | DIBCOM52))) ||
++		    ((priv->cur_fw.type & DTV78) && freq < 470000000))
+ 			offset -= 500000;
+ 	}
+ 

commit 9ca01e780f8966a7a94f88ef5c54f340e117abea
+Author: Chris Pascoe 
+Date:   Sun Dec 2 06:54:17 2007 -0300
+
+    V4L/DVB (6853): xc2028: check HAS_IF flag against table
+    
+    When searching for the right S-Code table to load, check the HAS_IF flag
+    against the firmware we are checking instead of against the the "type"
+    requested.  We already ignore the scode type requested if the caller passed
+    an int_freq; this makes the search by frequency consistent with that behaviour.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index 81cc7f607d4e..a6b05dfd6703 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -592,7 +592,7 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type,
+ 	} else {
+ 		for (pos = 0; pos < priv->firm_size; pos++) {
+ 			if ((priv->firm[pos].int_freq == int_freq) &&
+-			    (type & HAS_IF))
++			    (priv->firm[pos].type & HAS_IF))
+ 				break;
+ 		}
+ 		if (pos == priv->firm_size)
+@@ -601,7 +601,7 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type,
+ 
+ 	p = priv->firm[pos].ptr;
+ 
+-	if (type & HAS_IF) {
++	if (priv->firm[pos].type & HAS_IF) {
+ 		if (priv->firm[pos].size != 12 * 16 || scode >= 16)
+ 			return -EINVAL;
+ 		p += 12 * scode;

commit ad35ce9e3e03b1515c8581bababb0e64d05cf1ad
+Author: Chris Pascoe 
+Date:   Sun Dec 2 06:36:42 2007 -0300
+
+    V4L/DVB (6852): xc2028: s-code offset should not modify internal control structure
+    
+    Don't modify the control structure that was provided at attach when applying
+    an offset to the S-Code, otherwise it will be incorrect on subsequent tunes.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index 416c717eb78e..81cc7f607d4e 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -956,6 +956,7 @@ static int xc2028_set_params(struct dvb_frontend *fe,
+ 	struct xc2028_data *priv = fe->tuner_priv;
+ 	unsigned int       type=0;
+ 	fe_bandwidth_t     bw = BANDWIDTH_8_MHZ;
++	u16                demod = 0;
+ 
+ 	tuner_dbg("%s called\n", __FUNCTION__);
+ 
+@@ -1009,10 +1010,10 @@ static int xc2028_set_params(struct dvb_frontend *fe,
+ 
+ 	/* All S-code tables need a 200kHz shift */
+ 	if (priv->ctrl.demod)
+-		priv->ctrl.demod += 200;
++		demod = priv->ctrl.demod + 200;
+ 
+ 	return generic_set_freq(fe, p->frequency,
+-				T_DIGITAL_TV, type, 0, priv->ctrl.demod);
++				T_DIGITAL_TV, type, 0, demod);
+ }
+ 
+ static int xc2028_sleep(struct dvb_frontend *fe)

commit e026268870b5f05a3f74b37816d96ed3b19a9e33
+Author: Chris Pascoe 
+Date:   Sun Dec 2 06:30:50 2007 -0300
+
+    V4L/DVB (6851): xc2028: include int_freq in firmware version display
+    
+    Add "int_freq" to the debugging output when selecting firmware and the
+    HAS_IF flag when dumping firmware during load.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index fd248a19c259..416c717eb78e 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -144,7 +144,8 @@ static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val)
+ 	return 0;
+ }
+ 
+-void dump_firm_type(unsigned int type)
++#define dump_firm_type(t) 	dump_firm_type_and_int_freq(t, 0)
++void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq)
+ {
+ 	 if (type & BASE)
+ 		printk("BASE ");
+@@ -206,6 +207,8 @@ void dump_firm_type(unsigned int type)
+ 		printk("INPUT2 ");
+ 	 if (type & SCODE)
+ 		printk("SCODE ");
++	 if (type & HAS_IF)
++		printk("HAS_IF_%d ", int_freq);
+ }
+ 
+ static  v4l2_std_id parse_audio_std_option(void)
+@@ -350,9 +353,9 @@ static int load_all_firmwares(struct dvb_frontend *fe)
+ 		}
+ 		tuner_dbg("Reading firmware type ");
+ 		if (debug) {
+-			dump_firm_type(type);
++			dump_firm_type_and_int_freq(type, int_freq);
+ 			printk("(%x), id %llx, size=%d.\n",
+-				   type, (unsigned long long)id, size);
++			       type, (unsigned long long)id, size);
+ 		}
+ 
+ 		memcpy(priv->firm[n].ptr, p, size);
+@@ -612,7 +615,8 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type,
+ 	}
+ 
+ 	tuner_info("Loading SCODE for type=");
+-	dump_firm_type(priv->firm[pos].type);
++	dump_firm_type_and_int_freq(priv->firm[pos].type,
++				    priv->firm[pos].int_freq);
+ 	printk("(%x), id %016llx.\n", priv->firm[pos].type,
+ 	       (unsigned long long)*id);
+ 
+@@ -670,11 +674,15 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type,
+ 	tuner_dbg("checking firmware, user requested type=");
+ 	if (debug) {
+ 		dump_firm_type(new_fw.type);
+-		printk("(%x), id %016llx, scode_tbl ", new_fw.type,
++		printk("(%x), id %016llx, ", new_fw.type,
+ 		       (unsigned long long)new_fw.std_req);
+-		dump_firm_type(priv->ctrl.scode_table);
+-		printk("(%x), scode_nr %d\n", priv->ctrl.scode_table,
+-		       new_fw.scode_nr);
++		if (!int_freq) {
++			printk("scode_tbl ");
++			dump_firm_type(priv->ctrl.scode_table);
++			printk("(%x), ", priv->ctrl.scode_table);
++		} else
++			printk("int_freq %d, ", new_fw.int_freq);
++		printk("scode_nr %d\n", new_fw.scode_nr);
+ 	}
+ 
+ 	/* No need to reload base firmware if it matches */

commit a1dcd9de648c8cf21abaeca7f77885665eed4117
+Author: Chris Pascoe 
+Date:   Tue Nov 20 08:17:54 2007 -0300
+
+    V4L/DVB (6656): zl10353: store frequencies in 0.1kHz to eliminate rounding errors
+    
+    Whilst reanalysing my formulas I realised it was no longer possible to get the
+    right values for a 36.1667MHz IF due to rounding problems.
+    
+    Storing frequencies in units of 0.1kHz makes it possible to calculate these
+    again correctly.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
+index c44b9799efaa..deeb3871a2aa 100644
+--- a/drivers/media/dvb/dvb-usb/cxusb.c
++++ b/drivers/media/dvb/dvb-usb/cxusb.c
+@@ -435,7 +435,7 @@ static struct mt352_config cxusb_mt352_config = {
+ 
+ static struct zl10353_config cxusb_zl10353_xc3028_config = {
+ 	.demod_address = 0x0f,
+-	.if2 = 4560,
++	.if2 = 45600,
+ 	.no_tuner = 1,
+ 	.parallel_ts = 1,
+ };
+diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c
+index 1736c6ac39cc..091fbcced006 100644
+--- a/drivers/media/dvb/frontends/zl10353.c
++++ b/drivers/media/dvb/frontends/zl10353.c
+@@ -123,9 +123,10 @@ static void zl10353_calc_nominal_rate(struct dvb_frontend *fe,
+ 				      enum fe_bandwidth bandwidth,
+ 				      u16 *nominal_rate)
+ {
+-	u32 adc_clock = 45056; /* 45.056 MHz */
+-	u8 bw;
+ 	struct zl10353_state *state = fe->demodulator_priv;
++	u32 adc_clock = 450560; /* 45.056 MHz */
++	u64 value;
++	u8 bw;
+ 
+ 	if (state->config.adc_clock)
+ 		adc_clock = state->config.adc_clock;
+@@ -143,7 +144,9 @@ static void zl10353_calc_nominal_rate(struct dvb_frontend *fe,
+ 		break;
+ 	}
+ 
+-	*nominal_rate = (bw * (1 << 23) / 7 * 125 + adc_clock / 2) / adc_clock;
++	value = (bw * (u64)10 * (1 << 23) / 7 * 125 + adc_clock / 2);
++	do_div(value, adc_clock);
++	*nominal_rate = value;
+ 
+ 	dprintk("%s: bw %d, adc_clock %d => 0x%x\n",
+ 		__FUNCTION__, bw, adc_clock, *nominal_rate);
+@@ -153,8 +156,8 @@ static void zl10353_calc_input_freq(struct dvb_frontend *fe,
+ 				    u16 *input_freq)
+ {
+ 	struct zl10353_state *state = fe->demodulator_priv;
+-	u32 adc_clock = 45056;	/* 45.056 MHz */
+-	int if2 = 36167;	/* 36.167 MHz */
++	u32 adc_clock = 450560;	/* 45.056  MHz */
++	int if2 = 361667;	/* 36.1667 MHz */
+ 	int ife;
+ 	u64 value;
+ 
+@@ -170,7 +173,7 @@ static void zl10353_calc_input_freq(struct dvb_frontend *fe,
+ 		if (ife > adc_clock / 2)
+ 			ife = adc_clock - ife;
+ 	}
+-	value = 65536ULL * ife + adc_clock / 2;
++	value = (u64)65536 * ife + adc_clock / 2;
+ 	do_div(value, adc_clock);
+ 	*input_freq = -value;
+ 
+diff --git a/drivers/media/dvb/frontends/zl10353.h b/drivers/media/dvb/frontends/zl10353.h
+index 2660cec93f83..fc734c22b5fa 100644
+--- a/drivers/media/dvb/frontends/zl10353.h
++++ b/drivers/media/dvb/frontends/zl10353.h
+@@ -29,9 +29,9 @@ struct zl10353_config
+ 	/* demodulator's I2C address */
+ 	u8 demod_address;
+ 
+-	/* frequencies in kHz */
+-	int adc_clock;	/* default: 45056 */
+-	int if2;	/* default: 36167 */
++	/* frequencies in units of 0.1kHz */
++	int adc_clock;	/* default: 450560 (45.056  MHz) */
++	int if2;	/* default: 361667 (36.1667 MHz) */
+ 
+ 	/* set if no pll is connected to the secondary i2c bus */
+ 	int no_tuner;
+@@ -50,6 +50,6 @@ static inline struct dvb_frontend* zl10353_attach(const struct zl10353_config *c
+ 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ 	return NULL;
+ }
+-#endif // CONFIG_DVB_ZL10353
++#endif /* CONFIG_DVB_ZL10353 */
+ 
+ #endif /* ZL10353_H */

commit 702a67624e4bc9c7056418b576af928940b7dbb9
+Author: Chris Pascoe 
+Date:   Tue Nov 20 03:34:11 2007 -0300
+
+    V4L/DVB (6655): Add support for MT352-based DViCO FusionHDTV DVB-T NANO devices
+    
+    There are at least three variants of the DViCO FusionHDTV DVB-T NANO that
+    share the same USB device ID.  The first (ZL10353 w/ firmware in ROM) is
+    already supported; the latter two both require firmware and have either
+    an MT352 or ZL10353 demodulator, and have a different IR receiver from the
+    first.
+    
+    This introduces a new identify_state that can tell the difference between a
+    "warm" device which is running the embedded firmware, and a "cold" device
+    that needs us to upload firmware to it before it will work.  We patch the
+    uploaded device ID (like we do for other bluebird devices) to make it easy
+    to identify the particular device variant when it reattaches.
+    
+    NB: These devices use a different firmware file from previous bluebird
+        devices.  You need a new firmware file to make this work.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
+index f6fa2c22b0bf..c44b9799efaa 100644
+--- a/drivers/media/dvb/dvb-usb/cxusb.c
++++ b/drivers/media/dvb/dvb-usb/cxusb.c
+@@ -440,6 +440,13 @@ static struct zl10353_config cxusb_zl10353_xc3028_config = {
+ 	.parallel_ts = 1,
+ };
+ 
++static struct mt352_config cxusb_mt352_xc3028_config = {
++	.demod_address = 0x0f,
++	.if2 = 4560,
++	.no_tuner = 1,
++	.demod_init = cxusb_mt352_demod_init,
++};
++
+ /* Callbacks for DVB USB */
+ static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
+ {
+@@ -639,30 +646,63 @@ static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap)
+ 				   &adap->dev->i2c_adap)) != NULL)
+ 		return 0;
+ 
++	if ((adap->fe = dvb_attach(mt352_attach,
++				   &cxusb_mt352_xc3028_config,
++				   &adap->dev->i2c_adap)) != NULL)
++		return 0;
++
+ 	return -EIO;
+ }
+ 
++/*
++ * DViCO has shipped two devices with the same USB ID, but only one of them
++ * needs a firmware download.  Check the device class details to see if they
++ * have non-default values to decide whether the device is actually cold or
++ * not, and forget a match if it turns out we selected the wrong device.
++ */
++static int bluebird_fx2_identify_state(struct usb_device *udev,
++				       struct dvb_usb_device_properties *props,
++				       struct dvb_usb_device_description **desc,
++				       int *cold)
++{
++	int wascold = *cold;
++
++	*cold = udev->descriptor.bDeviceClass == 0xff &&
++		udev->descriptor.bDeviceSubClass == 0xff &&
++		udev->descriptor.bDeviceProtocol == 0xff;
++
++	if (*cold && !wascold)
++		*desc = NULL;
++
++	return 0;
++}
++
+ /*
+  * DViCO bluebird firmware needs the "warm" product ID to be patched into the
+  * firmware file before download.
+  */
+ 
+-#define BLUEBIRD_01_ID_OFFSET 6638
++static const int dvico_firmware_id_offsets[] = { 6638, 3204 };
+ static int bluebird_patch_dvico_firmware_download(struct usb_device *udev,
+ 						  const struct firmware *fw)
+ {
+-	if (fw->size < BLUEBIRD_01_ID_OFFSET + 4)
+-		return -EINVAL;
++	int pos;
++
++	for (pos = 0; pos < ARRAY_SIZE(dvico_firmware_id_offsets); pos++) {
++		int idoff = dvico_firmware_id_offsets[pos];
+ 
+-	if (fw->data[BLUEBIRD_01_ID_OFFSET] == (USB_VID_DVICO & 0xff) &&
+-	    fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) {
++		if (fw->size < idoff + 4)
++			continue;
+ 
+-		fw->data[BLUEBIRD_01_ID_OFFSET + 2] =
+-			le16_to_cpu(udev->descriptor.idProduct) + 1;
+-		fw->data[BLUEBIRD_01_ID_OFFSET + 3] =
+-			le16_to_cpu(udev->descriptor.idProduct) >> 8;
++		if (fw->data[idoff] == (USB_VID_DVICO & 0xff) &&
++		    fw->data[idoff + 1] == USB_VID_DVICO >> 8) {
++			fw->data[idoff + 2] =
++				le16_to_cpu(udev->descriptor.idProduct) + 1;
++			fw->data[idoff + 3] =
++				le16_to_cpu(udev->descriptor.idProduct) >> 8;
+ 
+-		return usb_cypress_load_firmware(udev, fw, CYPRESS_FX2);
++			return usb_cypress_load_firmware(udev, fw, CYPRESS_FX2);
++		}
+ 	}
+ 
+ 	return -EINVAL;
+@@ -676,6 +716,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties;
+ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties;
+ static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties;
+ static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties;
++static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties;
+ 
+ static int cxusb_probe(struct usb_interface *intf,
+ 		       const struct usb_device_id *id)
+@@ -686,7 +727,8 @@ static int cxusb_probe(struct usb_interface *intf,
+ 		dvb_usb_device_init(intf,&cxusb_bluebird_lgz201_properties,THIS_MODULE,NULL) == 0 ||
+ 		dvb_usb_device_init(intf,&cxusb_bluebird_dtt7579_properties,THIS_MODULE,NULL) == 0 ||
+ 		dvb_usb_device_init(intf,&cxusb_bluebird_dualdig4_properties,THIS_MODULE,NULL) == 0 ||
+-		dvb_usb_device_init(intf,&cxusb_bluebird_nano2_properties,THIS_MODULE,NULL) == 0) {
++		dvb_usb_device_init(intf,&cxusb_bluebird_nano2_properties,THIS_MODULE,NULL) == 0 ||
++		dvb_usb_device_init(intf,&cxusb_bluebird_nano2_needsfirmware_properties,THIS_MODULE,NULL) == 0) {
+ 		return 0;
+ 	}
+ 
+@@ -709,6 +751,7 @@ static struct usb_device_id cxusb_table [] = {
+ 	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) },
+ 	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4) },
+ 	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2) },
++	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM) },
+ 	{}		/* Terminating entry */
+ };
+ MODULE_DEVICE_TABLE (usb, cxusb_table);
+@@ -1018,6 +1061,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = {
+ 	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
+ 
+ 	.usb_ctrl         = CYPRESS_FX2,
++	.identify_state   = bluebird_fx2_identify_state,
+ 
+ 	.size_of_priv     = sizeof(struct cxusb_state),
+ 
+@@ -1061,6 +1105,56 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = {
+ 	}
+ };
+ 
++static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties = {
++	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
++
++	.usb_ctrl          = DEVICE_SPECIFIC,
++	.firmware          = "dvb-usb-bluebird-02.fw",
++	.download_firmware = bluebird_patch_dvico_firmware_download,
++	.identify_state    = bluebird_fx2_identify_state,
++
++	.size_of_priv      = sizeof(struct cxusb_state),
++
++	.num_adapters = 1,
++	.adapter = {
++		{
++			.streaming_ctrl   = cxusb_streaming_ctrl,
++			.frontend_attach  = cxusb_nano2_frontend_attach,
++			.tuner_attach     = cxusb_dvico_xc3028_tuner_attach,
++			/* parameter for the MPEG2-data transfer */
++			.stream = {
++				.type = USB_BULK,
++				.count = 5,
++				.endpoint = 0x02,
++				.u = {
++					.bulk = {
++						.buffersize = 8192,
++					}
++				}
++			},
++		},
++	},
++
++	.power_ctrl       = cxusb_nano2_power_ctrl,
++
++	.i2c_algo         = &cxusb_i2c_algo,
++
++	.generic_bulk_ctrl_endpoint = 0x01,
++
++	.rc_interval      = 100,
++	.rc_key_map       = dvico_portable_rc_keys,
++	.rc_key_map_size  = ARRAY_SIZE(dvico_portable_rc_keys),
++	.rc_query         = cxusb_rc_query,
++
++	.num_device_descs = 1,
++	.devices = {
++		{   "DViCO FusionHDTV DVB-T NANO2 w/o firmware",
++			{ &cxusb_table[14], NULL },
++			{ &cxusb_table[15], NULL },
++		},
++	}
++};
++
+ static struct usb_driver cxusb_driver = {
+ 	.name		= "dvb_usb_cxusb",
+ 	.probe		= cxusb_probe,
+diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+index 53496985ddfd..c94d993a6eff 100644
+--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
++++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+@@ -149,6 +149,7 @@
+ #define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM		0xdb59
+ #define USB_PID_DVICO_BLUEBIRD_DUAL_4			0xdb78
+ #define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2		0xdb70
++#define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM	0xdb71
+ #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD		0xdb54
+ #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM		0xdb55
+ #define USB_PID_MEDION_MD95700				0x0932

commit c6e62a3a398d62e8ae366ac1465911db0ac7fc0b
+Author: Chris Pascoe 
+Date:   Tue Nov 20 02:49:41 2007 -0300
+
+    V4L/DVB (6654): mt352: support oversampled IF input
+    
+    Rework the input frequency calculation so that it produces the right values
+    when the ADC oversamples the IF input.
+    
+    This means MT352 devices can now process a near-zero IF (according to the,
+    specs 4.57MHz is supported with the default crystal).
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb/frontends/mt352.c b/drivers/media/dvb/frontends/mt352.c
+index 5dd9b731f6f2..7cd190b6f015 100644
+--- a/drivers/media/dvb/frontends/mt352.c
++++ b/drivers/media/dvb/frontends/mt352.c
+@@ -152,7 +152,13 @@ static void mt352_calc_input_freq(struct mt352_state* state,
+ 	if (state->config.if2)
+ 		if2 = state->config.if2;
+ 
+-	ife = (2*adc_clock - if2);
++	if (adc_clock >= if2 * 2)
++		ife = if2;
++	else {
++		ife = adc_clock - (if2 % adc_clock);
++		if (ife > adc_clock / 2)
++			ife = adc_clock - ife;
++	}
+ 	value = -16374 * ife / adc_clock;
+ 	dprintk("%s: if2 %d, ife %d, adc_clock %d => %d / 0x%x\n",
+ 		__FUNCTION__, if2, ife, adc_clock, value, value & 0x3fff);

commit 5ccaf905015c83a9b28e8496b4504b9b8dc25a80
+Author: Chris Pascoe 
+Date:   Tue Nov 20 01:53:31 2007 -0300
+
+    V4L/DVB (6653): Add support for the DViCO FusionHDTV NANO2 w/ZL10353 and firmware
+    
+    Add support for the DViCO FusionHDTV DVB-T NANO with zl10353 demodulator and
+    firmware in ROM on the device.
+    
+    Again, this is based on the great work of Mike Krufky with my modifications
+    to use the in-tree XC2028 driver.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
+index ec8516ac8105..f6fa2c22b0bf 100644
+--- a/drivers/media/dvb/dvb-usb/cxusb.c
++++ b/drivers/media/dvb/dvb-usb/cxusb.c
+@@ -98,6 +98,11 @@ static void cxusb_bluebird_gpio_pulse(struct dvb_usb_device *d, u8 pin, int low)
+ 	cxusb_bluebird_gpio_rw(d, pin, low ? pin : 0);
+ }
+ 
++static void cxusb_nano2_led(struct dvb_usb_device *d, int onoff)
++{
++	cxusb_bluebird_gpio_rw(d, 0x40, onoff ? 0 : 0x40);
++}
++
+ /* I2C */
+ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+ 			  int num)
+@@ -200,6 +205,17 @@ static int cxusb_bluebird_power_ctrl(struct dvb_usb_device *d, int onoff)
+ 		return 0;
+ }
+ 
++static int cxusb_nano2_power_ctrl(struct dvb_usb_device *d, int onoff)
++{
++	int rc = 0;
++
++	rc = cxusb_power_ctrl(d, onoff);
++	if (!onoff)
++		cxusb_nano2_led(d, 0);
++
++	return rc;
++}
++
+ static int cxusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+ {
+ 	u8 buf[2] = { 0x03, 0x00 };
+@@ -606,6 +622,26 @@ static int cxusb_dualdig4_frontend_attach(struct dvb_usb_adapter *adap)
+ 	return 0;
+ }
+ 
++static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap)
++{
++	if (usb_set_interface(adap->dev->udev, 0, 1) < 0)
++		err("set interface failed");
++
++	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
++
++	/* reset the tuner and demodulator */
++	cxusb_bluebird_gpio_rw(adap->dev, 0x04, 0);
++	cxusb_bluebird_gpio_pulse(adap->dev, 0x01, 1);
++	cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
++
++	if ((adap->fe = dvb_attach(zl10353_attach,
++				   &cxusb_zl10353_xc3028_config,
++				   &adap->dev->i2c_adap)) != NULL)
++		return 0;
++
++	return -EIO;
++}
++
+ /*
+  * DViCO bluebird firmware needs the "warm" product ID to be patched into the
+  * firmware file before download.
+@@ -639,6 +675,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties;
+ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties;
+ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties;
+ static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties;
++static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties;
+ 
+ static int cxusb_probe(struct usb_interface *intf,
+ 		       const struct usb_device_id *id)
+@@ -648,7 +685,8 @@ static int cxusb_probe(struct usb_interface *intf,
+ 		dvb_usb_device_init(intf,&cxusb_bluebird_dee1601_properties,THIS_MODULE,NULL) == 0 ||
+ 		dvb_usb_device_init(intf,&cxusb_bluebird_lgz201_properties,THIS_MODULE,NULL) == 0 ||
+ 		dvb_usb_device_init(intf,&cxusb_bluebird_dtt7579_properties,THIS_MODULE,NULL) == 0 ||
+-		dvb_usb_device_init(intf,&cxusb_bluebird_dualdig4_properties,THIS_MODULE,NULL) == 0) {
++		dvb_usb_device_init(intf,&cxusb_bluebird_dualdig4_properties,THIS_MODULE,NULL) == 0 ||
++		dvb_usb_device_init(intf,&cxusb_bluebird_nano2_properties,THIS_MODULE,NULL) == 0) {
+ 		return 0;
+ 	}
+ 
+@@ -670,6 +708,7 @@ static struct usb_device_id cxusb_table [] = {
+ 	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD) },
+ 	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) },
+ 	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4) },
++	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2) },
+ 	{}		/* Terminating entry */
+ };
+ MODULE_DEVICE_TABLE (usb, cxusb_table);
+@@ -975,6 +1014,53 @@ static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties = {
+ 	}
+ };
+ 
++static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = {
++	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
++
++	.usb_ctrl         = CYPRESS_FX2,
++
++	.size_of_priv     = sizeof(struct cxusb_state),
++
++	.num_adapters = 1,
++	.adapter = {
++		{
++			.streaming_ctrl   = cxusb_streaming_ctrl,
++			.frontend_attach  = cxusb_nano2_frontend_attach,
++			.tuner_attach     = cxusb_dvico_xc3028_tuner_attach,
++			/* parameter for the MPEG2-data transfer */
++			.stream = {
++				.type = USB_BULK,
++				.count = 5,
++				.endpoint = 0x02,
++				.u = {
++					.bulk = {
++						.buffersize = 8192,
++					}
++				}
++			},
++		},
++	},
++
++	.power_ctrl       = cxusb_nano2_power_ctrl,
++
++	.i2c_algo         = &cxusb_i2c_algo,
++
++	.generic_bulk_ctrl_endpoint = 0x01,
++
++	.rc_interval      = 100,
++	.rc_key_map       = dvico_portable_rc_keys,
++	.rc_key_map_size  = ARRAY_SIZE(dvico_portable_rc_keys),
++	.rc_query         = cxusb_bluebird2_rc_query,
++
++	.num_device_descs = 1,
++	.devices = {
++		{   "DViCO FusionHDTV DVB-T NANO2",
++			{ NULL },
++			{ &cxusb_table[14], NULL },
++		},
++	}
++};
++
+ static struct usb_driver cxusb_driver = {
+ 	.name		= "dvb_usb_cxusb",
+ 	.probe		= cxusb_probe,
+diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+index 6f14c853ffea..53496985ddfd 100644
+--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
++++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+@@ -148,6 +148,7 @@
+ #define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD		0xdb58
+ #define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM		0xdb59
+ #define USB_PID_DVICO_BLUEBIRD_DUAL_4			0xdb78
++#define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2		0xdb70
+ #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD		0xdb54
+ #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM		0xdb55
+ #define USB_PID_MEDION_MD95700				0x0932

commit 1ad0b796a3fa3d1c1a7d16be7c70b626da2940a9
+Author: Chris Pascoe 
+Date:   Mon Nov 19 23:43:13 2007 -0300
+
+    V4L/DVB (6652): xc2028: try non-8MHZ init1 firmware
+    
+    When loading init1 firmware, there may not be an 8MHz specific version.
+    Load the non-8MHz version if it exists.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index 5b646fed340f..429e81be697e 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -706,6 +706,9 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
+ 	tuner_dbg("Load init1 firmware, if exists\n");
+ 
+ 	rc = load_firmware(fe, BASE | INIT1 | new_fw.type, &std0);
++	if (rc == -ENOENT)
++		rc = load_firmware(fe, (BASE | INIT1 | new_fw.type) & ~F8MHZ,
++				   &std0);
+ 	if (rc < 0 && rc != -ENOENT) {
+ 		tuner_err("Error %d while loading init1 firmware\n",
+ 			  rc);

commit 11a9eff9b66b1cf860faa84084328d798d18834c
+Author: Chris Pascoe 
+Date:   Mon Nov 19 23:18:36 2007 -0300
+
+    V4L/DVB (6651): xc2028: mask off type correctly when searching for standard-specific types
+    
+    When searching for standard-specific analog firmware, only certain
+    type bits are valid, much like for DTV.  Mask them off when finding
+    the firmware to load.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-xc2028-types.h b/drivers/media/video/tuner-xc2028-types.h
+index 6cee48193c47..c0dc6ec19f09 100644
+--- a/drivers/media/video/tuner-xc2028-types.h
++++ b/drivers/media/video/tuner-xc2028-types.h
+@@ -43,6 +43,8 @@
+ /* There's a FM | BASE firmware + FM specific firmware (std=0) */
+ #define	FM		(1<<10)
+ 
++#define STD_SPECIFIC_TYPES (MTS|FM|LCD|NOGD)
++
+ /* Applies only for FM firmware
+    Makes it use RF input 1 (pin #2) instead of input 2 (pin #4)
+  */
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index 115738d75f3e..5b646fed340f 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -403,7 +403,9 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
+ 	else if (type & SCODE)
+ 		type &= SCODE_TYPES;
+ 	else if (type & DTV_TYPES)
+-		type = type & DTV_TYPES;
++		type &= DTV_TYPES;
++	else if (type & STD_SPECIFIC_TYPES)
++		type &= STD_SPECIFIC_TYPES;
+ 
+ 	/* Seek for exact match */
+ 	for (i = 0; i < priv->firm_size; i++) {

commit 47bd5bc6486a5288aa3002533c24c8e9e564f9ac
+Author: Chris Pascoe 
+Date:   Mon Nov 19 23:11:37 2007 -0300
+
+    V4L/DVB (6650): xc2028: base firmwares should have std0
+    
+    When loading BASE firmware, we must use std = 0.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index 8f9ccaee9bb5..115738d75f3e 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -614,6 +614,7 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
+ 	unsigned int		type = 0;
+ 	struct firmware_properties new_fw;
+ 	u16			version, hwmodel;
++	v4l2_std_id		std0;
+ 
+ 	tuner_dbg("%s called\n", __FUNCTION__);
+ 
+@@ -690,7 +691,9 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
+ 	if (rc < 0)
+ 		goto fail;
+ 
+-	rc = load_firmware(fe, BASE | new_fw.type, &new_fw.id);
++	/* BASE firmwares are all std0 */
++	std0 = 0;
++	rc = load_firmware(fe, BASE | new_fw.type, &std0);
+ 	if (rc < 0) {
+ 		tuner_err("Error %d while loading base firmware\n",
+ 			  rc);
+@@ -700,7 +703,7 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
+ 	/* Load INIT1, if needed */
+ 	tuner_dbg("Load init1 firmware, if exists\n");
+ 
+-	rc = load_firmware(fe, BASE | INIT1 | new_fw.type, &new_fw.id);
++	rc = load_firmware(fe, BASE | INIT1 | new_fw.type, &std0);
+ 	if (rc < 0 && rc != -ENOENT) {
+ 		tuner_err("Error %d while loading init1 firmware\n",
+ 			  rc);

commit aeb012bbf460171b75ba17dc064a543f7256521f
+Author: Chris Pascoe 
+Date:   Mon Nov 19 21:57:10 2007 -0300
+
+    V4L/DVB (6649): Add support for the DViCO FusionHDTV Dual Digital 4
+    
+    Add support for DViCO's Dual Digital 4 with xc3028 tuner, zl10353 DVB-T
+    demodulator and a new-style I2C IR remote control receiver.
+    
+    This would not have been possible without the work of and advice from
+    Mike Krufky, who originally got the Dual Digital 4 and second-gen DVB-T
+    NANO devices working with the out-of-tree XC3028 driver.
+    
+    I converted it to use the in-tree XC3028 driver (after making it suitable
+    for our use), and added the IR remote control support based on his advice.
+    
+    NB: a firmware package is required to use this device.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
+index 74eeb168f241..ec8516ac8105 100644
+--- a/drivers/media/dvb/dvb-usb/cxusb.c
++++ b/drivers/media/dvb/dvb-usb/cxusb.c
+@@ -15,7 +15,7 @@
+  *
+  * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de)
+  * Copyright (C) 2006 Michael Krufky (mkrufky@linuxtv.org)
+- * Copyright (C) 2006 Chris Pascoe (c.pascoe@itee.uq.edu.au)
++ * Copyright (C) 2006, 2007 Chris Pascoe (c.pascoe@itee.uq.edu.au)
+  *
+  *   This program is free software; you can redistribute it and/or modify it
+  *   under the terms of the GNU General Public License as published by the Free
+@@ -30,6 +30,8 @@
+ #include "mt352.h"
+ #include "mt352_priv.h"
+ #include "zl10353.h"
++#include "tuner-xc2028.h"
++#include "tuner-xc2028-types.h"
+ 
+ /* debug */
+ static int dvb_usb_cxusb_debug;
+@@ -73,6 +75,29 @@ static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff)
+ 	st->gpio_write_state[GPIO_TUNER] = onoff;
+ }
+ 
++static int cxusb_bluebird_gpio_rw(struct dvb_usb_device *d, u8 changemask,
++				 u8 newval)
++{
++	u8 o[2], gpio_state;
++	int rc;
++
++	o[0] = 0xff & ~changemask;	/* mask of bits to keep */
++	o[1] = newval & changemask;	/* new values for bits  */
++
++	rc = cxusb_ctrl_msg(d, CMD_BLUEBIRD_GPIO_RW, o, 2, &gpio_state, 1);
++	if (rc < 0 || (gpio_state & changemask) != (newval & changemask))
++		deb_info("bluebird_gpio_write failed.\n");
++
++	return rc < 0 ? rc : gpio_state;
++}
++
++static void cxusb_bluebird_gpio_pulse(struct dvb_usb_device *d, u8 pin, int low)
++{
++	cxusb_bluebird_gpio_rw(d, pin, low ? 0 : pin);
++	msleep(5);
++	cxusb_bluebird_gpio_rw(d, pin, low ? pin : 0);
++}
++
+ /* I2C */
+ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+ 			  int num)
+@@ -210,6 +235,34 @@ static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+ 	return 0;
+ }
+ 
++static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event,
++				    int *state)
++{
++	struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
++	u8 ircode[4];
++	int i;
++	struct i2c_msg msg = { .addr = 0x6b, .flags = I2C_M_RD,
++			       .buf = ircode, .len = 4 };
++
++	*event = 0;
++	*state = REMOTE_NO_KEY_PRESSED;
++
++	if (cxusb_i2c_xfer(&d->i2c_adap, &msg, 1) != 1)
++		return 0;
++
++	for (i = 0; i < d->props.rc_key_map_size; i++) {
++		if (keymap[i].custom == ircode[1] &&
++		    keymap[i].data == ircode[2]) {
++			*event = keymap[i].event;
++			*state = REMOTE_KEY_PRESSED;
++
++			return 0;
++		}
++	}
++
++	return 0;
++}
++
+ static struct dvb_usb_rc_key dvico_mce_rc_keys[] = {
+ 	{ 0xfe, 0x02, KEY_TV },
+ 	{ 0xfe, 0x0e, KEY_MP3 },
+@@ -364,6 +417,13 @@ static struct mt352_config cxusb_mt352_config = {
+ 	.demod_init    = cxusb_mt352_demod_init,
+ };
+ 
++static struct zl10353_config cxusb_zl10353_xc3028_config = {
++	.demod_address = 0x0f,
++	.if2 = 4560,
++	.no_tuner = 1,
++	.parallel_ts = 1,
++};
++
+ /* Callbacks for DVB USB */
+ static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
+ {
+@@ -399,6 +459,52 @@ static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap)
+ 	return 0;
+ }
+ 
++static int dvico_bluebird_xc2028_callback(void *ptr, int command, int arg)
++{
++	struct dvb_usb_device *d = ptr;
++
++	switch (command) {
++	case XC2028_TUNER_RESET:
++		deb_info("%s: XC2028_TUNER_RESET %d\n", __FUNCTION__, arg);
++		cxusb_bluebird_gpio_pulse(d, 0x01, 1);
++		break;
++	case XC2028_RESET_CLK:
++		deb_info("%s: XC2028_RESET_CLK %d\n", __FUNCTION__, arg);
++		break;
++	default:
++		deb_info("%s: unknown command %d, arg %d\n", __FUNCTION__,
++			 command, arg);
++		return -EINVAL;
++	}
++
++	return 0;
++}
++
++static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap)
++{
++	struct dvb_frontend	 *fe;
++	struct xc2028_config	  cfg = {
++		.i2c_adap  = &adap->dev->i2c_adap,
++		.i2c_addr  = 0x61,
++		.video_dev = adap->dev,
++		.callback  = dvico_bluebird_xc2028_callback,
++	};
++	static struct xc2028_ctrl ctl = {
++		.type        = XC2028_FIRM_NORMAL,
++		.fname       = "xc3028-dvico-au-01.fw",
++		.max_len     = 64,
++		.scode_table = ZARLINK456,
++	};
++
++	fe = dvb_attach(xc2028_attach, adap->fe, &cfg);
++	if (fe == NULL || fe->ops.tuner_ops.set_config == NULL)
++		return -EIO;
++
++	fe->ops.tuner_ops.set_config(fe, &ctl);
++
++	return 0;
++}
++
+ static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap)
+ {
+ 	u8 b;
+@@ -460,6 +566,46 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap)
+ 	return -EIO;
+ }
+ 
++static int cxusb_dualdig4_frontend_attach(struct dvb_usb_adapter *adap)
++{
++	u8 ircode[4];
++	int i;
++	struct i2c_msg msg = { .addr = 0x6b, .flags = I2C_M_RD,
++			       .buf = ircode, .len = 4 };
++
++	if (usb_set_interface(adap->dev->udev, 0, 1) < 0)
++		err("set interface failed");
++
++	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
++
++	/* reset the tuner and demodulator */
++	cxusb_bluebird_gpio_rw(adap->dev, 0x04, 0);
++	cxusb_bluebird_gpio_pulse(adap->dev, 0x01, 1);
++	cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
++
++	if ((adap->fe = dvb_attach(zl10353_attach,
++				   &cxusb_zl10353_xc3028_config,
++				   &adap->dev->i2c_adap)) == NULL)
++		return -EIO;
++
++	/* try to determine if there is no IR decoder on the I2C bus */
++	for (i = 0; adap->dev->props.rc_key_map != NULL && i < 5; i++) {
++		msleep(20);
++		if (cxusb_i2c_xfer(&adap->dev->i2c_adap, &msg, 1) != 1)
++			goto no_IR;
++		if (ircode[0] == 0 && ircode[1] == 0)
++			continue;
++		if (ircode[2] + ircode[3] != 0xff) {
++no_IR:
++			adap->dev->props.rc_key_map = NULL;
++			info("No IR receiver detected on this device.");
++			break;
++		}
++	}
++
++	return 0;
++}
++
+ /*
+  * DViCO bluebird firmware needs the "warm" product ID to be patched into the
+  * firmware file before download.
+@@ -492,6 +638,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties;
+ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties;
+ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties;
+ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties;
++static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties;
+ 
+ static int cxusb_probe(struct usb_interface *intf,
+ 		       const struct usb_device_id *id)
+@@ -500,7 +647,8 @@ static int cxusb_probe(struct usb_interface *intf,
+ 		dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 ||
+ 		dvb_usb_device_init(intf,&cxusb_bluebird_dee1601_properties,THIS_MODULE,NULL) == 0 ||
+ 		dvb_usb_device_init(intf,&cxusb_bluebird_lgz201_properties,THIS_MODULE,NULL) == 0 ||
+-		dvb_usb_device_init(intf,&cxusb_bluebird_dtt7579_properties,THIS_MODULE,NULL) == 0) {
++		dvb_usb_device_init(intf,&cxusb_bluebird_dtt7579_properties,THIS_MODULE,NULL) == 0 ||
++		dvb_usb_device_init(intf,&cxusb_bluebird_dualdig4_properties,THIS_MODULE,NULL) == 0) {
+ 		return 0;
+ 	}
+ 
+@@ -521,6 +669,7 @@ static struct usb_device_id cxusb_table [] = {
+ 	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM) },
+ 	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD) },
+ 	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) },
++	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4) },
+ 	{}		/* Terminating entry */
+ };
+ MODULE_DEVICE_TABLE (usb, cxusb_table);
+@@ -779,6 +928,53 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = {
+ 	}
+ };
+ 
++static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties = {
++	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
++
++	.usb_ctrl         = CYPRESS_FX2,
++
++	.size_of_priv     = sizeof(struct cxusb_state),
++
++	.num_adapters = 1,
++	.adapter = {
++		{
++			.streaming_ctrl   = cxusb_streaming_ctrl,
++			.frontend_attach  = cxusb_dualdig4_frontend_attach,
++			.tuner_attach     = cxusb_dvico_xc3028_tuner_attach,
++			/* parameter for the MPEG2-data transfer */
++			.stream = {
++				.type = USB_BULK,
++				.count = 5,
++				.endpoint = 0x02,
++				.u = {
++					.bulk = {
++						.buffersize = 8192,
++					}
++				}
++			},
++		},
++	},
++
++	.power_ctrl       = cxusb_power_ctrl,
++
++	.i2c_algo         = &cxusb_i2c_algo,
++
++	.generic_bulk_ctrl_endpoint = 0x01,
++
++	.rc_interval      = 100,
++	.rc_key_map       = dvico_mce_rc_keys,
++	.rc_key_map_size  = ARRAY_SIZE(dvico_mce_rc_keys),
++	.rc_query         = cxusb_bluebird2_rc_query,
++
++	.num_device_descs = 1,
++	.devices = {
++		{   "DViCO FusionHDTV DVB-T Dual Digital 4",
++			{ NULL },
++			{ &cxusb_table[13], NULL },
++		},
++	}
++};
++
+ static struct usb_driver cxusb_driver = {
+ 	.name		= "dvb_usb_cxusb",
+ 	.probe		= cxusb_probe,
+diff --git a/drivers/media/dvb/dvb-usb/cxusb.h b/drivers/media/dvb/dvb-usb/cxusb.h
+index 79ca7abb89a5..4768a2c35517 100644
+--- a/drivers/media/dvb/dvb-usb/cxusb.h
++++ b/drivers/media/dvb/dvb-usb/cxusb.h
+@@ -5,6 +5,8 @@
+ #include "dvb-usb.h"
+ 
+ /* usb commands - some of it are guesses, don't have a reference yet */
++#define CMD_BLUEBIRD_GPIO_RW 0x05
++
+ #define CMD_I2C_WRITE     0x08
+ #define CMD_I2C_READ      0x09
+ 
+diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+index d6d96308cbaa..6f14c853ffea 100644
+--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
++++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+@@ -147,6 +147,7 @@
+ #define USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM		0xdb51
+ #define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD		0xdb58
+ #define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM		0xdb59
++#define USB_PID_DVICO_BLUEBIRD_DUAL_4			0xdb78
+ #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD		0xdb54
+ #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM		0xdb55
+ #define USB_PID_MEDION_MD95700				0x0932

commit 45819c381fc4fb342dc091f30eef4b56193e34d5
+Author: Chris Pascoe 
+Date:   Mon Nov 19 11:41:20 2007 -0300
+
+    V4L/DVB (6648): xc2028: add sleep hook
+    
+    Add sleep method to enable putting the tuner into standby mode.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index cc6fa2fa859b..8f9ccaee9bb5 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -929,6 +929,28 @@ static int xc2028_set_params(struct dvb_frontend *fe,
+ 
+ }
+ 
++static int xc2028_sleep(struct dvb_frontend *fe)
++{
++	struct xc2028_data *priv = fe->tuner_priv;
++	int rc = 0;
++
++	tuner_dbg("%s called\n", __FUNCTION__);
++
++	mutex_lock(&priv->lock);
++
++	if (priv->firm_version < 0x0202)
++		rc = send_seq(priv, {0x00, 0x08, 0x00, 0x00});
++	else
++		rc = send_seq(priv, {0x80, 0x08, 0x00, 0x00});
++
++	priv->cur_fw.type = 0;	/* need firmware reload */
++
++	mutex_unlock(&priv->lock);
++
++	return rc;
++}
++
++
+ static int xc2028_dvb_release(struct dvb_frontend *fe)
+ {
+ 	struct xc2028_data *priv = fe->tuner_priv;
+@@ -1009,6 +1031,7 @@ static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = {
+ 	.get_frequency     = xc2028_get_frequency,
+ 	.get_rf_strength   = xc2028_signal,
+ 	.set_params        = xc2028_set_params,
++	.sleep             = xc2028_sleep,
+ 
+ };
+ 

commit 8bf799a6217f6336fb95f37bf1b130003404bd7b
+Author: Chris Pascoe 
+Date:   Mon Nov 19 11:35:45 2007 -0300
+
+    V4L/DVB (6647): xc2028: retry firmware load if tuner does not respond
+    
+    In practice, the tuner occasionally fails to respond correctly after a
+    firmware load.  Retry the firmware load if the firmware/hardware version
+    we read back from the tuner after programming does not match what we
+    expect.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index 8140d8ad0792..cc6fa2fa859b 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -75,6 +75,9 @@ struct xc2028_data {
+ 	int			firm_size;
+ 	__u16			firm_version;
+ 
++	__u16			hwmodel;
++	__u16			hwvers;
++
+ 	struct xc2028_ctrl	ctrl;
+ 
+ 	struct firmware_properties cur_fw;
+@@ -607,7 +610,7 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
+ 			  v4l2_std_id std, fe_bandwidth_t bandwidth)
+ {
+ 	struct xc2028_data      *priv = fe->tuner_priv;
+-	int			rc = 0;
++	int			rc = 0, is_retry = 0;
+ 	unsigned int		type = 0;
+ 	struct firmware_properties new_fw;
+ 	u16			version, hwmodel;
+@@ -654,6 +657,7 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
+ 		};
+ 	}
+ 
++retry:
+ 	new_fw.type = type;
+ 	new_fw.id = std;
+ 	new_fw.std_req = std;
+@@ -739,14 +743,34 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
+ 			&new_fw.id, new_fw.scode_nr);
+ 
+ check_device:
+-	xc2028_get_reg(priv, 0x0004, &version);
+-	xc2028_get_reg(priv, 0x0008, &hwmodel);
++	if (xc2028_get_reg(priv, 0x0004, &version) < 0 ||
++	    xc2028_get_reg(priv, 0x0008, &hwmodel) < 0) {
++		tuner_err("Unable to read tuner registers.\n");
++		goto fail;
++	}
+ 
+ 	tuner_info("Device is Xceive %d version %d.%d, "
+ 		   "firmware version %d.%d\n",
+ 		   hwmodel, (version & 0xf000) >> 12, (version & 0xf00) >> 8,
+ 		   (version & 0xf0) >> 4, version & 0xf);
+ 
++	/* Check firmware version against what we downloaded. */
++	if (priv->firm_version != ((version & 0xf0) << 4 | (version & 0x0f))) {
++		tuner_err("Incorrect readback of firmware version.\n");
++		goto fail;
++	}
++
++	/* Check that the tuner hardware model remains consistent over time. */
++	if (priv->hwmodel == 0 && (hwmodel == 2028 || hwmodel == 3028)) {
++		priv->hwmodel = hwmodel;
++		priv->hwvers  = version & 0xff00;
++	} else if (priv->hwmodel == 0 || priv->hwmodel != hwmodel ||
++		   priv->hwvers != (version & 0xff00)) {
++		tuner_err("Read invalid device hardware information - tuner "
++			  "hung?\n");
++		goto fail;
++	}
++
+ 	memcpy(&priv->cur_fw, &new_fw, sizeof(priv->cur_fw));
+ 
+ 	/*
+@@ -761,6 +785,13 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
+ 
+ fail:
+ 	memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
++	if (!is_retry) {
++		msleep(50);
++		is_retry = 1;
++		tuner_dbg("Retrying firmware load\n");
++		goto retry;
++	}
++
+ 	if (rc == -ENOENT)
+ 		rc = -EINVAL;
+ 	return rc;

commit e0f0b37a3e624440b1b0e8a5978b367895226e75
+Author: Chris Pascoe 
+Date:   Mon Nov 19 11:22:03 2007 -0300
+
+    V4L/DVB (6646): xc2028: rework firmware (re)loading process
+    
+    Define a list of valid "firmware types" for each combination of BASE,
+    DTV and SCODEs.  By masking the appropriate firmware bits off we can
+    just use one "type" for the firmware searching and also flag when we
+    are looking for a BASE, DTV or SCODE type firmware.  This makes it
+    much easier to track if we need to change device modes or flash an
+    individual firmware part.
+    
+    Add a structure to remember what firmware properties we have.  This
+    contains the currently loaded/wanted  base firmware (type), video std
+    (id), video std requested (std_req), scode file and number in use.
+    
+    Incorporate said structure into the tuner private data.
+    
+    When checking whether the current firmware needs to be reloaded, first
+    figure out exactly what "type" of firmware we want (base, std and
+    scode), and then proceed to load the appropriate matching base,
+    std-specific and scode records iff there are any changes required.
+    This removes guesswork from the process because we no longer need to
+    individually code a check for every tuning parameter's interactions.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-xc2028-types.h b/drivers/media/video/tuner-xc2028-types.h
+index a9e2e0562d99..6cee48193c47 100644
+--- a/drivers/media/video/tuner-xc2028-types.h
++++ b/drivers/media/video/tuner-xc2028-types.h
+@@ -8,6 +8,7 @@
+ 
+ /* BASE firmware should be loaded before any other firmware */
+ #define BASE		(1<<0)
++#define BASE_TYPES	(BASE|F8MHZ|MTS|FM|INPUT1|INPUT2|INIT1)
+ 
+ /* F8MHZ marks BASE firmwares for 8 MHz Bandwidth */
+ #define F8MHZ		(1<<1)
+@@ -37,6 +38,8 @@
+ #define DTV78		(1<<8)
+ #define DTV8		(1<<9)
+ 
++#define DTV_TYPES	(D2620|D2633|DTV6|QAM|DTV7|DTV78|DTV8|ATSC)
++
+ /* There's a FM | BASE firmware + FM specific firmware (std=0) */
+ #define	FM		(1<<10)
+ 
+@@ -60,6 +63,7 @@
+ /* Old firmwares were broken into init0 and init1 */
+ #define INIT1		(1<<14)
+ 
++/* SCODE firmware selects particular behaviours */
+ #define MONO           (1 << 15)
+ #define ATSC           (1 << 16)
+ #define IF             (1 << 17)
+@@ -76,6 +80,10 @@
+ #define INPUT2         (1 << 28)
+ #define SCODE          (1 << 29)
+ 
++#define SCODE_TYPES	(MTS|DTV6|QAM|DTV7|DTV78|DTV8|LCD|NOGD|MONO|ATSC|IF| \
++			 LG60|ATI638|OREN538|OREN36|TOYOTA388|TOYOTA794|     \
++			 DIBCOM52|ZARLINK456|CHINA|F6MHZ|SCODE)
++
+ /* Newer types to be moved to videodev2.h */
+ 
+ #define V4L2_STD_SECAM_K3	(0x04000000)
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index a5efd5f6e57c..8140d8ad0792 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -54,6 +54,14 @@ struct firmware_description {
+ 	unsigned int  size;
+ };
+ 
++struct firmware_properties {
++	unsigned int	type;
++	v4l2_std_id	id;
++	v4l2_std_id	std_req;
++	unsigned int	scode_table;
++	int 		scode_nr;
++};
++
+ struct xc2028_data {
+ 	struct list_head        xc2028_list;
+ 	struct tuner_i2c_props  i2c_props;
+@@ -69,14 +77,7 @@ struct xc2028_data {
+ 
+ 	struct xc2028_ctrl	ctrl;
+ 
+-	v4l2_std_id		firm_type;	   /* video stds supported
+-							by current firmware */
+-	fe_bandwidth_t		bandwidth;	   /* Firmware bandwidth:
+-							      6M, 7M or 8M */
+-	int			need_load_generic; /* The generic firmware
+-							      were loaded? */
+-	enum tuner_mode	mode;
+-	struct i2c_client	*i2c_client;
++	struct firmware_properties cur_fw;
+ 
+ 	struct mutex lock;
+ };
+@@ -234,7 +235,8 @@ static void free_firmware(struct xc2028_data *priv)
+ 
+ 	priv->firm = NULL;
+ 	priv->firm_size = 0;
+-	priv->need_load_generic = 1;
++
++	memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
+ }
+ 
+ static int load_all_firmwares(struct dvb_frontend *fe)
+@@ -393,6 +395,13 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
+ 	if (((type & ~SCODE) == 0) && (*id == 0))
+ 		*id = V4L2_STD_PAL;
+ 
++	if (type & BASE)
++		type &= BASE_TYPES;
++	else if (type & SCODE)
++		type &= SCODE_TYPES;
++	else if (type & DTV_TYPES)
++		type = type & DTV_TYPES;
++
+ 	/* Seek for exact match */
+ 	for (i = 0; i < priv->firm_size; i++) {
+ 		if ((type == priv->firm[i].type) && (*id == priv->firm[i].id))
+@@ -598,11 +607,10 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
+ 			  v4l2_std_id std, fe_bandwidth_t bandwidth)
+ {
+ 	struct xc2028_data      *priv = fe->tuner_priv;
+-	int			rc;
++	int			rc = 0;
++	unsigned int		type = 0;
++	struct firmware_properties new_fw;
+ 	u16			version, hwmodel;
+-	v4l2_std_id		std0 = 0;
+-	unsigned int		type0 = 0, type = 0;
+-	int			change_digital_bandwidth;
+ 
+ 	tuner_dbg("%s called\n", __FUNCTION__);
+ 
+@@ -617,61 +625,19 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
+ 			return rc;
+ 	}
+ 
+-	tuner_dbg("I am in mode %u and I should switch to mode %i\n",
+-		   priv->mode, new_mode);
+-
+-	/* first of all, determine whether we have switched the mode */
+-	if (new_mode != priv->mode) {
+-		priv->mode = new_mode;
+-		priv->need_load_generic = 1;
+-	}
+-
+-	change_digital_bandwidth = (priv->mode == T_DIGITAL_TV
+-				    && bandwidth != priv->bandwidth) ? 1 : 0;
+-	tuner_dbg("old bandwidth %u, new bandwidth %u\n", priv->bandwidth,
+-		   bandwidth);
+-
+-	if (priv->need_load_generic) {
+-		/* Reset is needed before loading firmware */
+-		rc = priv->tuner_callback(priv->video_dev,
+-					  XC2028_TUNER_RESET, 0);
+-		if (rc < 0)
+-			return rc;
+-
+-		type0 = BASE;
+-
+-		if (priv->ctrl.type == XC2028_FIRM_MTS)
+-			type0 |= MTS;
+-
+-		if (bandwidth == BANDWIDTH_7_MHZ ||
+-		    bandwidth == BANDWIDTH_8_MHZ)
+-			type0 |= F8MHZ;
+-
+-		/* FIXME: How to load FM and FM|INPUT1 firmwares? */
+-
+-		rc = load_firmware(fe, type0, &std0);
+-		if (rc < 0) {
+-			tuner_err("Error %d while loading generic firmware\n",
+-				  rc);
+-			return rc;
+-		}
+-
+-		priv->need_load_generic = 0;
+-		priv->firm_type = 0;
+-		if (priv->mode == T_DIGITAL_TV)
+-			change_digital_bandwidth = 1;
+-	}
++	if (priv->ctrl.type == XC2028_FIRM_MTS)
++		type |= MTS;
++	if (bandwidth == BANDWIDTH_7_MHZ || bandwidth == BANDWIDTH_8_MHZ)
++		type |= F8MHZ;
+ 
+-	tuner_dbg("I should change bandwidth %u\n", change_digital_bandwidth);
++	/* FIXME: How to load FM and FM|INPUT1 firmwares? */
+ 
+-	if (change_digital_bandwidth) {
++	if (new_mode == T_DIGITAL_TV) {
+ 		if (priv->ctrl.d2633)
+ 			type |= D2633;
+ 		else
+ 			type |= D2620;
+ 
+-		/* FIXME: When should select a DTV78 firmware?
+-		 */
+ 		switch (bandwidth) {
+ 		case BANDWIDTH_8_MHZ:
+ 			type |= DTV8;
+@@ -683,49 +649,96 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
+ 			/* FIXME: Should allow select also ATSC */
+ 			type |= DTV6 | QAM;
+ 			break;
+-
+ 		default:
+ 			tuner_err("error: bandwidth not supported.\n");
+ 		};
+-		priv->bandwidth = bandwidth;
+ 	}
+ 
+-	if (!change_digital_bandwidth && priv->mode == T_DIGITAL_TV)
+-		return 0;
++	new_fw.type = type;
++	new_fw.id = std;
++	new_fw.std_req = std;
++	new_fw.scode_table = SCODE | priv->ctrl.scode_table;
++	new_fw.scode_nr = 0;
++
++	tuner_dbg("checking firmware, user requested type=");
++	if (debug) {
++		dump_firm_type(new_fw.type);
++		printk("(%x), id %016llx, scode_tbl ", new_fw.type,
++		       (unsigned long long)new_fw.std_req);
++		dump_firm_type(priv->ctrl.scode_table);
++		printk("(%x), scode_nr %d\n", priv->ctrl.scode_table,
++		       new_fw.scode_nr);
++	}
++
++	/* No need to reload base firmware if it matches */
++	if (((BASE | new_fw.type) & BASE_TYPES) ==
++	    (priv->cur_fw.type & BASE_TYPES)) {
++		tuner_dbg("BASE firmware not changed.\n");
++		goto skip_base;
++	}
++
++	/* Updating BASE - forget about all currently loaded firmware */
++	memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
++
++	/* Reset is needed before loading firmware */
++	rc = priv->tuner_callback(priv->video_dev,
++				  XC2028_TUNER_RESET, 0);
++	if (rc < 0)
++		goto fail;
++
++	rc = load_firmware(fe, BASE | new_fw.type, &new_fw.id);
++	if (rc < 0) {
++		tuner_err("Error %d while loading base firmware\n",
++			  rc);
++		goto fail;
++	}
+ 
+ 	/* Load INIT1, if needed */
+ 	tuner_dbg("Load init1 firmware, if exists\n");
+-	type0 = BASE | INIT1;
+-	if (priv->ctrl.type == XC2028_FIRM_MTS)
+-		type0 |= MTS;
+ 
+-	/* FIXME: Should handle errors - if INIT1 found */
+-	rc = load_firmware(fe, type0, &std0);
++	rc = load_firmware(fe, BASE | INIT1 | new_fw.type, &new_fw.id);
++	if (rc < 0 && rc != -ENOENT) {
++		tuner_err("Error %d while loading init1 firmware\n",
++			  rc);
++		goto fail;
++	}
+ 
+-	/* FIXME: Should add support for FM radio
++skip_base:
++	/*
++	 * No need to reload standard specific firmware if base firmware
++	 * was not reloaded and requested video standards have not changed.
+ 	 */
+-
+-	if (priv->ctrl.type == XC2028_FIRM_MTS)
+-		type |= MTS;
+-
+-	if (priv->firm_type & std) {
++	if (priv->cur_fw.type == (BASE | new_fw.type) &&
++	    priv->cur_fw.std_req == std) {
+ 		tuner_dbg("Std-specific firmware already loaded.\n");
+-		return 0;
++		goto skip_std_specific;
+ 	}
+ 
++	/* Reloading std-specific firmware forces a SCODE update */
++	priv->cur_fw.scode_table = 0;
++
+ 	/* Add audio hack to std mask */
+-	std |= parse_audio_std_option();
++	if (new_mode == T_ANALOG_TV)
++		new_fw.id |= parse_audio_std_option();
+ 
+-	rc = load_firmware(fe, type, &std);
++	rc = load_firmware(fe, new_fw.type, &new_fw.id);
+ 	if (rc < 0)
+-		return rc;
++		goto fail;
++
++skip_std_specific:
++	if (priv->cur_fw.scode_table == new_fw.scode_table &&
++	    priv->cur_fw.scode_nr == new_fw.scode_nr) {
++		tuner_dbg("SCODE firmware already loaded.\n");
++		goto check_device;
++	}
+ 
+ 	/* Load SCODE firmware, if exists */
+-	tuner_dbg("Trying to load scode 0\n");
+-	type |= SCODE;
++	tuner_dbg("Trying to load scode %d\n", new_fw.scode_nr);
+ 
+-	rc = load_scode(fe, type, &std, 0);
++	rc = load_scode(fe, new_fw.type | new_fw.scode_table,
++			&new_fw.id, new_fw.scode_nr);
+ 
++check_device:
+ 	xc2028_get_reg(priv, 0x0004, &version);
+ 	xc2028_get_reg(priv, 0x0008, &hwmodel);
+ 
+@@ -734,9 +747,23 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
+ 		   hwmodel, (version & 0xf000) >> 12, (version & 0xf00) >> 8,
+ 		   (version & 0xf0) >> 4, version & 0xf);
+ 
+-	priv->firm_type = std;
++	memcpy(&priv->cur_fw, &new_fw, sizeof(priv->cur_fw));
++
++	/*
++	 * By setting BASE in cur_fw.type only after successfully loading all
++	 * firmwares, we can:
++	 * 1. Identify that BASE firmware with type=0 has been loaded;
++	 * 2. Tell whether BASE firmware was just changed the next time through.
++	 */
++	priv->cur_fw.type |= BASE;
+ 
+ 	return 0;
++
++fail:
++	memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
++	if (rc == -ENOENT)
++		rc = -EINVAL;
++	return rc;
+ }
+ 
+ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
+@@ -785,16 +812,10 @@ static int generic_set_tv_freq(struct dvb_frontend *fe, u32 freq /* in Hz */ ,
+ 	mutex_lock(&priv->lock);
+ 
+ 	/* HACK: It seems that specific firmware need to be reloaded
+-	   when freq is changed */
+-
+-	priv->firm_type = 0;
+-
+-	/* Reset GPIO 1 */
+-	rc = priv->tuner_callback(priv->video_dev, XC2028_TUNER_RESET, 0);
+-	if (rc < 0)
+-		goto ret;
++	   when watching analog TV and freq is changed */
++	if (new_mode != T_DIGITAL_TV)
++		priv->cur_fw.type = 0;
+ 
+-	msleep(10);
+ 	tuner_dbg("should set frequency %d kHz\n", freq / 1000);
+ 
+ 	if (check_firmware(fe, new_mode, std, bandwidth) < 0)
+@@ -802,7 +823,7 @@ static int generic_set_tv_freq(struct dvb_frontend *fe, u32 freq /* in Hz */ ,
+ 
+ 	if (new_mode == T_DIGITAL_TV) {
+ 		offset = 2750000;
+-		if (priv->bandwidth == BANDWIDTH_7_MHZ)
++		if (priv->cur_fw.type & DTV7)
+ 			offset -= 500000;
+ 	}
+ 
+@@ -994,9 +1015,6 @@ void *xc2028_attach(struct dvb_frontend *fe, struct xc2028_config *cfg)
+ 			return NULL;
+ 		}
+ 
+-		priv->bandwidth = BANDWIDTH_6_MHZ;
+-		priv->need_load_generic = 1;
+-		priv->mode = T_UNINITIALIZED;
+ 		priv->i2c_props.addr = cfg->i2c_addr;
+ 		priv->i2c_props.adap = cfg->i2c_adap;
+ 		priv->video_dev = video_dev;
+diff --git a/drivers/media/video/tuner-xc2028.h b/drivers/media/video/tuner-xc2028.h
+index 4edc4b735c84..16259b14ce90 100644
+--- a/drivers/media/video/tuner-xc2028.h
++++ b/drivers/media/video/tuner-xc2028.h
+@@ -21,6 +21,7 @@ struct xc2028_ctrl {
+ 	char			*fname;
+ 	int			max_len;
+ 	int			d2633:1;
++	unsigned int		scode_table;
+ };
+ 
+ struct xc2028_config {

commit 59a636e50f339f91880b3a1e395829c43cc6541a
+Author: Chris Pascoe 
+Date:   Mon Nov 19 10:23:17 2007 -0300
+
+    V4L/DVB (6645): xc2028: allow selection of D2633 firmware
+    
+    Add a bit to select D2633 DTV firmware to struct xc2028_ctrl, so that it can
+    be enabled via .set_config.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index fbaab68fd05c..a5efd5f6e57c 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -665,9 +665,10 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
+ 	tuner_dbg("I should change bandwidth %u\n", change_digital_bandwidth);
+ 
+ 	if (change_digital_bandwidth) {
+-
+-		/*FIXME: Should allow selecting between D2620 and D2633 */
+-		type |= D2620;
++		if (priv->ctrl.d2633)
++			type |= D2633;
++		else
++			type |= D2620;
+ 
+ 		/* FIXME: When should select a DTV78 firmware?
+ 		 */
+diff --git a/drivers/media/video/tuner-xc2028.h b/drivers/media/video/tuner-xc2028.h
+index a20eeb4935d0..4edc4b735c84 100644
+--- a/drivers/media/video/tuner-xc2028.h
++++ b/drivers/media/video/tuner-xc2028.h
+@@ -20,6 +20,7 @@ struct xc2028_ctrl {
+ 	enum xc2028_firm_type	type;
+ 	char			*fname;
+ 	int			max_len;
++	int			d2633:1;
+ };
+ 
+ struct xc2028_config {

commit d7b22c5cfef28d21051331622f9595993a083cc4
+Author: Chris Pascoe 
+Date:   Mon Nov 19 10:12:45 2007 -0300
+
+    V4L/DVB (6644): xc2028: use correct offset into scode firmware
+    
+    When validating and loading SCODE firmware we need to take into account the
+    two-byte size header before each entry.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index 3edf5be47197..fbaab68fd05c 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -565,9 +565,17 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type,
+ 
+ 	p = priv->firm[pos].ptr;
+ 
+-	if ((priv->firm[pos].size != 12 * 16) || (scode >= 16))
++	/* 16 SCODE entries per file; each SCODE entry is 12 bytes and
++	 * has a 2-byte size header in the firmware format. */
++	if (priv->firm[pos].size != 14 * 16 || scode >= 16 ||
++	    le16_to_cpu(*(__u16 *)(p + 14 * scode)) != 12)
+ 		return -EINVAL;
+ 
++	tuner_info("Loading SCODE for type=");
++	dump_firm_type(priv->firm[pos].type);
++	printk("(%x), id %016llx.\n", priv->firm[pos].type,
++	       (unsigned long long)*id);
++
+ 	if (priv->firm_version < 0x0202)
+ 		rc = send_seq(priv, {0x20, 0x00, 0x00, 0x00});
+ 	else
+@@ -575,7 +583,7 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type,
+ 	if (rc < 0)
+ 		return -EIO;
+ 
+-	rc = i2c_send(priv, p + 12 * scode, 12);
++	rc = i2c_send(priv, p + 14 * scode + 2, 12);
+ 	if (rc < 0)
+ 		return -EIO;
+ 

commit b1535293dc816f01b0934718c370f9533c7d635e
+Author: Chris Pascoe 
+Date:   Mon Nov 19 10:04:06 2007 -0300
+
+    V4L/DVB (6643): xc2028: use best match instead of first partial match during firmware selection
+    
+    Rather than picking the first video standard firmware that supports any of
+    the standards that the user has requested, try to select one that supports
+    as many of them as possible.  This improves the likelihood that the firmware
+    we select will support the user's desired TV standard.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index e19449603d73..3edf5be47197 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -377,9 +377,13 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
+ 			 v4l2_std_id *id)
+ {
+ 	struct xc2028_data *priv = fe->tuner_priv;
+-	int                i;
++	int                 i, best_i = -1, best_nr_matches = 0;
+ 
+-	tuner_dbg("%s called\n", __FUNCTION__);
++	tuner_dbg("%s called, want type=", __FUNCTION__);
++	if (debug) {
++		dump_firm_type(type);
++		printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
++	}
+ 
+ 	if (!priv->firm) {
+ 		tuner_err("Error! firmware not loaded\n");
+@@ -397,20 +401,45 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
+ 
+ 	/* Seek for generic video standard match */
+ 	for (i = 0; i < priv->firm_size; i++) {
+-		if ((type == priv->firm[i].type) && (*id & priv->firm[i].id))
+-			goto found;
++		v4l2_std_id match_mask;
++		int nr_matches;
++
++		if (type != priv->firm[i].type)
++			continue;
++
++		match_mask = *id & priv->firm[i].id;
++		if (!match_mask)
++			continue;
++
++		if ((*id & match_mask) == *id)
++			goto found; /* Supports all the requested standards */
++
++		nr_matches = hweight64(match_mask);
++		if (nr_matches > best_nr_matches) {
++			best_nr_matches = nr_matches;
++			best_i = i;
++		}
++	}
++
++	if (best_nr_matches > 0) {
++		tuner_dbg("Selecting best matching firmware (%d bits) for "
++			  "type=", best_nr_matches);
++		dump_firm_type(type);
++		printk("(%x), id %016llx:\n", type, (unsigned long long)*id);
++		i = best_i;
++		goto found;
+ 	}
+ 
+ 	/*FIXME: Would make sense to seek for type "hint" match ? */
+ 
+-	i = -EINVAL;
++	i = -ENOENT;
+ 	goto ret;
+ 
+ found:
+ 	*id = priv->firm[i].id;
+ 
+ ret:
+-	tuner_dbg("%s firmware for type=", (i < 0)? "Can't find": "Found");
++	tuner_dbg("%s firmware for type=", (i < 0) ? "Can't find" : "Found");
+ 	if (debug) {
+ 		dump_firm_type(type);
+ 		printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
+@@ -432,8 +461,9 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
+ 		return pos;
+ 
+ 	tuner_info("Loading firmware for type=");
+-	dump_firm_type(type);
+-	printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
++	dump_firm_type(priv->firm[pos].type);
++	printk("(%x), id %016llx.\n", priv->firm[pos].type,
++	       (unsigned long long)*id);
+ 
+ 	p = priv->firm[pos].ptr;
+ 	endp = p + priv->firm[pos].size;

commit 0a196b6fa9b42a2bb49733b37565aaaa97ffb07f
+Author: Chris Pascoe 
+Date:   Mon Nov 19 09:29:59 2007 -0300
+
+    V4L/DVB (6642): xc2028: don't duplicate max_len in priv
+    
+    There is no need to duplicate the max_len field from the ctrl structure
+    in the private data.  If we use it directly from priv->ctrl, we can memcpy
+    the structure (apart from strings) to reduce maintenance as it grows.
+    
+    Enforce a minimum max_len length of 8 data bytes (+ 1 address byte) as seems
+    to be required by the tuner.
+    
+    Also, use kstrdup instead of open coding the string duplication.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index c921d6009a8b..e19449603d73 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -75,9 +75,6 @@ struct xc2028_data {
+ 							      6M, 7M or 8M */
+ 	int			need_load_generic; /* The generic firmware
+ 							      were loaded? */
+-
+-	int			max_len;	/* Max firmware chunk */
+-
+ 	enum tuner_mode	mode;
+ 	struct i2c_client	*i2c_client;
+ 
+@@ -426,7 +423,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
+ {
+ 	struct xc2028_data *priv = fe->tuner_priv;
+ 	int                pos, rc;
+-	unsigned char      *p, *endp, buf[priv->max_len];
++	unsigned char      *p, *endp, buf[priv->ctrl.max_len];
+ 
+ 	tuner_dbg("%s called\n", __FUNCTION__);
+ 
+@@ -505,8 +502,8 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
+ 
+ 		/* Sends message chunks */
+ 		while (size > 0) {
+-			int len = (size < priv->max_len - 1) ?
+-				   size : priv->max_len - 1;
++			int len = (size < priv->ctrl.max_len - 1) ?
++				   size : priv->ctrl.max_len - 1;
+ 
+ 			memcpy(buf + 1, p, len);
+ 
+@@ -881,32 +878,30 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
+ {
+ 	struct xc2028_data *priv = fe->tuner_priv;
+ 	struct xc2028_ctrl *p    = priv_cfg;
++	int                 rc   = 0;
+ 
+ 	tuner_dbg("%s called\n", __FUNCTION__);
+ 
+ 	mutex_lock(&priv->lock);
+ 
+-	priv->ctrl.type = p->type;
+-
+-	if (p->fname) {
+-		kfree(priv->ctrl.fname);
++	kfree(priv->ctrl.fname);
++	free_firmware(priv);
+ 
+-		priv->ctrl.fname = kmalloc(strlen(p->fname) + 1, GFP_KERNEL);
+-		if (priv->ctrl.fname == NULL) {
+-			mutex_unlock(&priv->lock);
+-			return -ENOMEM;
+-		}
++	memcpy(&priv->ctrl, p, sizeof(priv->ctrl));
++	priv->ctrl.fname = NULL;
+ 
+-		free_firmware(priv);
+-		strcpy(priv->ctrl.fname, p->fname);
++	if (p->fname) {
++		priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL);
++		if (priv->ctrl.fname == NULL)
++			rc = -ENOMEM;
+ 	}
+ 
+-	if (p->max_len > 0)
+-		priv->max_len = p->max_len;
++	if (priv->ctrl.max_len < 9)
++		priv->ctrl.max_len = 13;
+ 
+ 	mutex_unlock(&priv->lock);
+ 
+-	return 0;
++	return rc;
+ }
+ 
+ static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = {
+@@ -967,7 +962,7 @@ void *xc2028_attach(struct dvb_frontend *fe, struct xc2028_config *cfg)
+ 		priv->i2c_props.adap = cfg->i2c_adap;
+ 		priv->video_dev = video_dev;
+ 		priv->tuner_callback = cfg->callback;
+-		priv->max_len = 13;
++		priv->ctrl.max_len = 13;
+ 
+ 		mutex_init(&priv->lock);
+ 

commit a44f1c43dfa98e2eb763968890157bfaf9001add
+Author: Chris Pascoe 
+Date:   Mon Nov 19 06:35:26 2007 -0300
+
+    V4L/DVB (6641): xc2028: correct tuner offset for 7MHz DTV
+    
+    7MHz bandwidth DVB-T needs an adjusted offset at the PLL to ensure the IF
+    output is correctly centered.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index adef80e627b8..c921d6009a8b 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -764,8 +764,11 @@ static int generic_set_tv_freq(struct dvb_frontend *fe, u32 freq /* in Hz */ ,
+ 	if (check_firmware(fe, new_mode, std, bandwidth) < 0)
+ 		goto ret;
+ 
+-	if (new_mode == T_DIGITAL_TV)
++	if (new_mode == T_DIGITAL_TV) {
+ 		offset = 2750000;
++		if (priv->bandwidth == BANDWIDTH_7_MHZ)
++			offset -= 500000;
++	}
+ 
+ 	div = (freq - offset + DIV / 2) / DIV;
+ 

commit ddf1c5f1d78c1ce30a7e6b2447670fc0e103bb62
+Author: Chris Pascoe 
+Date:   Mon Nov 19 06:33:16 2007 -0300
+
+    V4L/DVB (6640): xc2028: correctly select 8MHz firmware
+    
+    We were using priv->bandwidth to select the base firmware to load, not the
+    requested bandwidth value, oops.  Also, 7MHz Digital TV needs 8MHz base
+    firmware loaded.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index e85992f970f7..adef80e627b8 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -608,7 +608,8 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
+ 		if (priv->ctrl.type == XC2028_FIRM_MTS)
+ 			type0 |= MTS;
+ 
+-		if (priv->bandwidth == 8)
++		if (bandwidth == BANDWIDTH_7_MHZ ||
++		    bandwidth == BANDWIDTH_8_MHZ)
+ 			type0 |= F8MHZ;
+ 
+ 		/* FIXME: How to load FM and FM|INPUT1 firmwares? */
+@@ -814,7 +815,8 @@ static int xc2028_set_tv_freq(struct dvb_frontend *fe,
+ 	tuner_dbg("%s called\n", __FUNCTION__);
+ 
+ 	return generic_set_tv_freq(fe, 62500l * p->frequency, T_ANALOG_TV,
+-				   p->std, BANDWIDTH_8_MHZ /* NOT USED */);
++				   p->std, BANDWIDTH_8_MHZ);
++				   /* XXX Are some analog standards 6MHz? */
+ }
+ 
+ static int xc2028_set_params(struct dvb_frontend *fe,

commit 2ce4b3aa7c3c199466ae9f5ed32ea177912c8c3a
+Author: Chris Pascoe 
+Date:   Mon Nov 19 06:20:17 2007 -0300
+
+    V4L/DVB (6639): xc2028: correct divisor length
+    
+    The frequency divisor should only be four bytes long.  Also, display the
+    frequency and divisor correctly in the debug output.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index 7c86971a8d64..e85992f970f7 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -740,7 +740,7 @@ static int generic_set_tv_freq(struct dvb_frontend *fe, u32 freq /* in Hz */ ,
+ {
+ 	struct xc2028_data *priv = fe->tuner_priv;
+ 	int		   rc = -EINVAL;
+-	unsigned char	   buf[5];
++	unsigned char	   buf[4];
+ 	u32		   div, offset = 0;
+ 
+ 	tuner_dbg("%s called\n", __FUNCTION__);
+@@ -758,7 +758,7 @@ static int generic_set_tv_freq(struct dvb_frontend *fe, u32 freq /* in Hz */ ,
+ 		goto ret;
+ 
+ 	msleep(10);
+-	tuner_dbg("should set frequency %d kHz)\n", freq / 1000);
++	tuner_dbg("should set frequency %d kHz\n", freq / 1000);
+ 
+ 	if (check_firmware(fe, new_mode, std, bandwidth) < 0)
+ 		goto ret;
+@@ -769,7 +769,6 @@ static int generic_set_tv_freq(struct dvb_frontend *fe, u32 freq /* in Hz */ ,
+ 	div = (freq - offset + DIV / 2) / DIV;
+ 
+ 	/* CMD= Set frequency */
+-
+ 	if (priv->firm_version < 0x0202)
+ 		rc = send_seq(priv, {0x00, 0x02, 0x00, 0x00});
+ 	else
+@@ -787,7 +786,6 @@ static int generic_set_tv_freq(struct dvb_frontend *fe, u32 freq /* in Hz */ ,
+ 	buf[1] = 0xff & (div >> 16);
+ 	buf[2] = 0xff & (div >> 8);
+ 	buf[3] = 0xff & (div);
+-	buf[4] = 0;
+ 
+ 	rc = i2c_send(priv, buf, sizeof(buf));
+ 	if (rc < 0)
+@@ -796,9 +794,9 @@ static int generic_set_tv_freq(struct dvb_frontend *fe, u32 freq /* in Hz */ ,
+ 
+ 	priv->frequency = freq;
+ 
+-	tuner_dbg("divider= %02x %02x %02x %02x (freq=%d.%02d)\n",
+-	       buf[1], buf[2], buf[3], buf[4],
+-	       freq / 1000000, (freq % 1000000) / 10000);
++	tuner_dbg("divisor= %02x %02x %02x %02x (freq=%d.%03d)\n",
++	       buf[0], buf[1], buf[2], buf[3],
++	       freq / 1000000, (freq % 1000000) / 1000);
+ 
+ 	rc = 0;
+ 

commit 06fd82dc7bdc6045bf8d6c1438d2a33ffb1cf337
+Author: Chris Pascoe 
+Date:   Mon Nov 19 06:06:08 2007 -0300
+
+    V4L/DVB (6638): xc2028: firmware loading cleanup
+    
+    Hold the private lock over set_config and set priv->firm_size to 0 after a
+    failed firmware load to prevent firmware accidentally being freed on us.
+    
+    Clean up the firmware load/error messages somewhat and rename priv->version
+    to priv->firm_version to make it clear which "version" it is.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index 7e558decad84..7c86971a8d64 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -65,8 +65,7 @@ struct xc2028_data {
+ 
+ 	struct firmware_description *firm;
+ 	int			firm_size;
+-
+-	__u16			version;
++	__u16			firm_version;
+ 
+ 	struct xc2028_ctrl	ctrl;
+ 
+@@ -237,6 +236,7 @@ static void free_firmware(struct xc2028_data *priv)
+ 	kfree(priv->firm);
+ 
+ 	priv->firm = NULL;
++	priv->firm_size = 0;
+ 	priv->need_load_generic = 1;
+ }
+ 
+@@ -251,7 +251,7 @@ static int load_all_firmwares(struct dvb_frontend *fe)
+ 
+ 	tuner_dbg("%s called\n", __FUNCTION__);
+ 
+-	tuner_info("Reading firmware %s\n", priv->ctrl.fname);
++	tuner_dbg("Reading firmware %s\n", priv->ctrl.fname);
+ 	rc = request_firmware(&fw, priv->ctrl.fname,
+ 			      &priv->i2c_props.adap->dev);
+ 	if (rc < 0) {
+@@ -267,40 +267,34 @@ static int load_all_firmwares(struct dvb_frontend *fe)
+ 	p = fw->data;
+ 	endp = p + fw->size;
+ 
+-	if (fw->size < sizeof(name) - 1 + 2) {
+-		tuner_err("Error: firmware size is zero!\n");
+-		rc = -EINVAL;
+-		goto done;
++	if (fw->size < sizeof(name) - 1 + 2 + 2) {
++		tuner_err("Error: firmware file %s has invalid size!\n",
++			  priv->ctrl.fname);
++		goto corrupt;
+ 	}
+ 
+ 	memcpy(name, p, sizeof(name) - 1);
+ 	name[sizeof(name) - 1] = 0;
+ 	p += sizeof(name) - 1;
+ 
+-	priv->version = le16_to_cpu(*(__u16 *) p);
++	priv->firm_version = le16_to_cpu(*(__u16 *) p);
+ 	p += 2;
+ 
+-	tuner_info("Firmware: %s, ver %d.%d\n", name,
+-		   priv->version >> 8, priv->version & 0xff);
+-
+-	if (p + 2 > endp)
+-		goto corrupt;
+-
+ 	n_array = le16_to_cpu(*(__u16 *) p);
+ 	p += 2;
+ 
+-	tuner_info("There are %d firmwares at %s\n",
+-		   n_array, priv->ctrl.fname);
++	tuner_info("Loading %d firmware images from %s, type: %s, ver %d.%d\n",
++		   n_array, priv->ctrl.fname, name,
++		   priv->firm_version >> 8, priv->firm_version & 0xff);
+ 
+ 	priv->firm = kzalloc(sizeof(*priv->firm) * n_array, GFP_KERNEL);
+-
+-	if (!fw) {
+-		tuner_err("Not enough memory for reading firmware.\n");
++	if (priv->firm == NULL) {
++		tuner_err("Not enough memory to load firmware file.\n");
+ 		rc = -ENOMEM;
+-		goto done;
++		goto err;
+ 	}
+-
+ 	priv->firm_size = n_array;
++
+ 	n = -1;
+ 	while (p < endp) {
+ 		__u32 type, size;
+@@ -308,7 +302,8 @@ static int load_all_firmwares(struct dvb_frontend *fe)
+ 
+ 		n++;
+ 		if (n >= n_array) {
+-			tuner_err("Too much firmwares at the file\n");
++			tuner_err("More firmware images in file than "
++				  "were expected!\n");
+ 			goto corrupt;
+ 		}
+ 
+@@ -338,15 +333,17 @@ static int load_all_firmwares(struct dvb_frontend *fe)
+ 		}
+ 
+ 		priv->firm[n].ptr = kzalloc(size, GFP_KERNEL);
+-		if (!priv->firm[n].ptr) {
+-			tuner_err("Not enough memory.\n");
++		if (priv->firm[n].ptr == NULL) {
++			tuner_err("Not enough memory to load firmware file.\n");
+ 			rc = -ENOMEM;
+ 			goto err;
+ 		}
+-		tuner_info("Reading firmware type ");
+-		dump_firm_type(type);
+-		printk("(%x), id %llx, size=%d.\n",
+-			   type, (unsigned long long)id, size);
++		tuner_dbg("Reading firmware type ");
++		if (debug) {
++			dump_firm_type(type);
++			printk("(%x), id %llx, size=%d.\n",
++				   type, (unsigned long long)id, size);
++		}
+ 
+ 		memcpy(priv->firm[n].ptr, p, size);
+ 		priv->firm[n].type = type;
+@@ -368,13 +365,13 @@ static int load_all_firmwares(struct dvb_frontend *fe)
+ 	tuner_err("Error: firmware file is corrupted!\n");
+ 
+ err:
+-	tuner_info("Releasing loaded firmware file.\n");
+-
++	tuner_info("Releasing partially loaded firmware file.\n");
+ 	free_firmware(priv);
+ 
+ done:
+ 	release_firmware(fw);
+-	tuner_dbg("Firmware files loaded.\n");
++	if (rc == 0)
++		tuner_dbg("Firmware files loaded.\n");
+ 
+ 	return rc;
+ }
+@@ -442,11 +439,6 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
+ 	printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
+ 
+ 	p = priv->firm[pos].ptr;
+-
+-	if (!p) {
+-		tuner_err("Firmware pointer were freed!");
+-		return -EINVAL;
+-	}
+ 	endp = p + priv->firm[pos].size;
+ 
+ 	while (p < endp) {
+@@ -546,15 +538,10 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type,
+ 
+ 	p = priv->firm[pos].ptr;
+ 
+-	if (!p) {
+-		tuner_err("Firmware pointer were freed!");
+-		return -EINVAL;
+-	}
+-
+ 	if ((priv->firm[pos].size != 12 * 16) || (scode >= 16))
+ 		return -EINVAL;
+ 
+-	if (priv->version < 0x0202)
++	if (priv->firm_version < 0x0202)
+ 		rc = send_seq(priv, {0x20, 0x00, 0x00, 0x00});
+ 	else
+ 		rc = send_seq(priv, {0xa0, 0x00, 0x00, 0x00});
+@@ -783,7 +770,7 @@ static int generic_set_tv_freq(struct dvb_frontend *fe, u32 freq /* in Hz */ ,
+ 
+ 	/* CMD= Set frequency */
+ 
+-	if (priv->version < 0x0202)
++	if (priv->firm_version < 0x0202)
+ 		rc = send_seq(priv, {0x00, 0x02, 0x00, 0x00});
+ 	else
+ 		rc = send_seq(priv, {0x80, 0x02, 0x00, 0x00});
+@@ -868,6 +855,7 @@ static int xc2028_dvb_release(struct dvb_frontend *fe)
+ 
+ 		free_firmware(priv);
+ 		kfree(priv);
++		fe->tuner_priv = NULL;
+ 	}
+ 
+ 	mutex_unlock(&xc2028_list_mutex);
+@@ -893,14 +881,18 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
+ 
+ 	tuner_dbg("%s called\n", __FUNCTION__);
+ 
++	mutex_lock(&priv->lock);
++
+ 	priv->ctrl.type = p->type;
+ 
+ 	if (p->fname) {
+ 		kfree(priv->ctrl.fname);
+ 
+ 		priv->ctrl.fname = kmalloc(strlen(p->fname) + 1, GFP_KERNEL);
+-		if (!priv->ctrl.fname)
++		if (priv->ctrl.fname == NULL) {
++			mutex_unlock(&priv->lock);
+ 			return -ENOMEM;
++		}
+ 
+ 		free_firmware(priv);
+ 		strcpy(priv->ctrl.fname, p->fname);
+@@ -909,6 +901,8 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
+ 	if (p->max_len > 0)
+ 		priv->max_len = p->max_len;
+ 
++	mutex_unlock(&priv->lock);
++
+ 	return 0;
+ }
+ 

commit b32f9fb962d593e3c5a61092a79434714f405ef5
+Author: Chris Pascoe 
+Date:   Mon Nov 19 04:53:50 2007 -0300
+
+    V4L/DVB (6637): xc2028: add missing break
+    
+    Add break to stop us from following the default failure path even upon success.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index ac7f3e1d32f4..7e558decad84 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -485,6 +485,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
+ 						  (*p) & 0x7f);
+ 					return -EINVAL;
+ 				}
++				break;
+ 			default:
+ 				tuner_info("Invalid RESET code %d\n",
+ 					   size & 0x7f);

commit aa501be989f5df58c4732d5eb1989e5ca6479d90
+Author: Chris Pascoe 
+Date:   Mon Nov 19 04:45:38 2007 -0300
+
+    V4L/DVB (6636): xc2028: protect device list
+    
+    Protect refcount changes and modifications to xc2028_list with a mutex.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index a01231a0410d..ac7f3e1d32f4 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -44,6 +44,8 @@ MODULE_PARM_DESC(audio_std,
+ 	"NICAM/B\n");
+ 
+ static LIST_HEAD(xc2028_list);
++static DEFINE_MUTEX(xc2028_list_mutex);
++
+ /* struct for storing firmware table */
+ struct firmware_description {
+ 	unsigned int  type;
+@@ -854,6 +856,8 @@ static int xc2028_dvb_release(struct dvb_frontend *fe)
+ 
+ 	tuner_dbg("%s called\n", __FUNCTION__);
+ 
++	mutex_lock(&xc2028_list_mutex);
++
+ 	priv->count--;
+ 
+ 	if (!priv->count) {
+@@ -865,6 +869,8 @@ static int xc2028_dvb_release(struct dvb_frontend *fe)
+ 		kfree(priv);
+ 	}
+ 
++	mutex_unlock(&xc2028_list_mutex);
++
+ 	return 0;
+ }
+ 
+@@ -940,6 +946,8 @@ void *xc2028_attach(struct dvb_frontend *fe, struct xc2028_config *cfg)
+ 
+ 	video_dev = cfg->video_dev;
+ 
++	mutex_lock(&xc2028_list_mutex);
++
+ 	list_for_each_entry(priv, &xc2028_list, xc2028_list) {
+ 		if (priv->video_dev == cfg->video_dev) {
+ 			video_dev = NULL;
+@@ -949,8 +957,10 @@ void *xc2028_attach(struct dvb_frontend *fe, struct xc2028_config *cfg)
+ 
+ 	if (video_dev) {
+ 		priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+-		if (priv == NULL)
++		if (priv == NULL) {
++			mutex_unlock(&xc2028_list_mutex);
+ 			return NULL;
++		}
+ 
+ 		priv->bandwidth = BANDWIDTH_6_MHZ;
+ 		priv->need_load_generic = 1;
+@@ -974,6 +984,8 @@ void *xc2028_attach(struct dvb_frontend *fe, struct xc2028_config *cfg)
+ 
+ 	tuner_info("type set to %s\n", "XCeive xc2028/xc3028 tuner");
+ 
++	mutex_unlock(&xc2028_list_mutex);
++
+ 	return fe;
+ }
+ 

commit 91240dd92474d4124f80b00e6200052b275a99a1
+Author: Chris Pascoe 
+Date:   Mon Nov 19 04:38:53 2007 -0300
+
+    V4L/DVB (6635): xc2028: v4l2_std_id needs to be long long to display completely
+    
+    Cast v4l2_std_id variables to unsigned long long so they will printk properly.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index c208f1f5e72c..a01231a0410d 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -330,7 +330,7 @@ static int load_all_firmwares(struct dvb_frontend *fe)
+ 			dump_firm_type(type);
+ 			printk("(%x), id %llx is corrupted "
+ 			       "(size=%d, expected %d)\n",
+-			       type, id,
++			       type, (unsigned long long)id,
+ 			       (unsigned)(endp - p), size);
+ 			goto corrupt;
+ 		}
+@@ -343,8 +343,8 @@ static int load_all_firmwares(struct dvb_frontend *fe)
+ 		}
+ 		tuner_info("Reading firmware type ");
+ 		dump_firm_type(type);
+-		printk("(%x), id %lx, size=%d.\n",
+-			   type, (unsigned long)id, size);
++		printk("(%x), id %llx, size=%d.\n",
++			   type, (unsigned long long)id, size);
+ 
+ 		memcpy(priv->firm[n].ptr, p, size);
+ 		priv->firm[n].type = type;
+@@ -417,7 +417,7 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
+ 	tuner_dbg("%s firmware for type=", (i < 0)? "Can't find": "Found");
+ 	if (debug) {
+ 		dump_firm_type(type);
+-		printk("(%x), id %08lx.\n", type, (unsigned long)*id);
++		printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
+ 	}
+ 	return i;
+ }
+@@ -437,7 +437,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
+ 
+ 	tuner_info("Loading firmware for type=");
+ 	dump_firm_type(type);
+-	printk("(%x), id %08lx.\n", type, (unsigned long)*id);
++	printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
+ 
+ 	p = priv->firm[pos].ptr;
+ 

commit 3157ecef3bce47df74427d6656fa8592bfe8d2d7
+Author: Chris Pascoe 
+Date:   Mon Nov 19 04:34:29 2007 -0300
+
+    V4L/DVB (6634): xc2028: error messages missing whitespace
+    
+    Fix some missing spaces in errors that may be emitted during attach failure.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index a49a4e886897..c208f1f5e72c 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -928,13 +928,13 @@ void *xc2028_attach(struct dvb_frontend *fe, struct xc2028_config *cfg)
+ 	void               *video_dev;
+ 
+ 	if (debug)
+-		printk(KERN_DEBUG PREFIX "Xcv2028/3028 init called!\n");
++		printk(KERN_DEBUG PREFIX ": Xcv2028/3028 init called!\n");
+ 
+ 	if (NULL == cfg->video_dev)
+ 		return NULL;
+ 
+ 	if (!fe) {
+-		printk(KERN_ERR PREFIX "No frontend!\n");
++		printk(KERN_ERR PREFIX ": No frontend!\n");
+ 		return NULL;
+ 	}
+ 

commit 7d58d1117ec02f5fe22ddd03ca08fe2a8c777ea2
+Author: Chris Pascoe 
+Date:   Mon Nov 19 04:31:58 2007 -0300
+
+    V4L/DVB (6633): xc2028: make register reads atomic
+    
+    Issuing register reads as a separate address write and data read transactions
+    means that other I2C activity could occur in between and state could get out
+    of sync.  Issue both the write and read in a single transaction so that the
+    i2c layer can prevent other users accessing the bus until we are complete.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-i2c.h b/drivers/media/video/tuner-i2c.h
+index b5ac189ba40f..d7cf72c3fd71 100644
+--- a/drivers/media/video/tuner-i2c.h
++++ b/drivers/media/video/tuner-i2c.h
+@@ -46,6 +46,19 @@ static inline int tuner_i2c_xfer_recv(struct tuner_i2c_props *props, char *buf,
+ 	return (ret == 1) ? len : ret;
+ }
+ 
++static inline int tuner_i2c_xfer_send_recv(struct tuner_i2c_props *props,
++					   char *obuf, int olen,
++					   char *ibuf, int ilen)
++{
++	struct i2c_msg msg[2] = { { .addr = props->addr, .flags = 0,
++				    .buf = obuf, .len = olen },
++				  { .addr = props->addr, .flags = I2C_M_RD,
++				    .buf = ibuf, .len = ilen } };
++	int ret = i2c_transfer(props->adap, msg, 2);
++
++	return (ret == 2) ? ilen : ret;
++}
++
+ #ifndef __TUNER_DRIVER_H__
+ #define tuner_warn(fmt, arg...) do {					\
+ 	printk(KERN_WARNING "%s %d-%04x: " fmt, PREFIX,			\
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index 166fede7d0e3..a49a4e886897 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -101,6 +101,16 @@ struct xc2028_data {
+ 	_rc;								\
+ })
+ 
++#define i2c_send_recv(priv, obuf, osize, ibuf, isize) ({		\
++	int _rc;							\
++	_rc = tuner_i2c_xfer_send_recv(&priv->i2c_props, obuf, osize,	\
++				       ibuf, isize);			\
++	if (isize != _rc)						\
++		tuner_err("i2c input error: rc = %d (should be %d)\n",	\
++			   _rc, (int)isize); 				\
++	_rc;								\
++})
++
+ #define send_seq(priv, data...)	({					\
+ 	static u8 _val[] = data;					\
+ 	int _rc;							\
+@@ -113,25 +123,21 @@ struct xc2028_data {
+ 	_rc;								\
+ })
+ 
+-static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg)
++static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val)
+ {
+-	int rc;
+ 	unsigned char buf[2];
++	unsigned char ibuf[2];
+ 
+-	tuner_dbg("%s called\n", __FUNCTION__);
++	tuner_dbg("%s %04x called\n", __FUNCTION__, reg);
+ 
+-	buf[0] = reg>>8;
++	buf[0] = reg >> 8;
+ 	buf[1] = (unsigned char) reg;
+ 
+-	rc = i2c_send(priv, buf, 2);
+-	if (rc < 0)
+-		return rc;
+-
+-	rc = i2c_rcv(priv, buf, 2);
+-	if (rc < 0)
+-		return rc;
++	if (i2c_send_recv(priv, buf, 2, ibuf, 2) != 2)
++		return -EIO;
+ 
+-	return (buf[1]) | (buf[0] << 8);
++	*val = (ibuf[1]) | (ibuf[0] << 8);
++	return 0;
+ }
+ 
+ void dump_firm_type(unsigned int type)
+@@ -567,7 +573,8 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
+ 			  v4l2_std_id std, fe_bandwidth_t bandwidth)
+ {
+ 	struct xc2028_data      *priv = fe->tuner_priv;
+-	int			rc, version, hwmodel;
++	int			rc;
++	u16			version, hwmodel;
+ 	v4l2_std_id		std0 = 0;
+ 	unsigned int		type0 = 0, type = 0;
+ 	int			change_digital_bandwidth;
+@@ -692,8 +699,8 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
+ 
+ 	rc = load_scode(fe, type, &std, 0);
+ 
+-	version = xc2028_get_reg(priv, 0x0004);
+-	hwmodel = xc2028_get_reg(priv, 0x0008);
++	xc2028_get_reg(priv, 0x0004, &version);
++	xc2028_get_reg(priv, 0x0008, &hwmodel);
+ 
+ 	tuner_info("Device is Xceive %d version %d.%d, "
+ 		   "firmware version %d.%d\n",
+@@ -708,33 +715,31 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
+ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
+ {
+ 	struct xc2028_data *priv = fe->tuner_priv;
+-	int                frq_lock, signal = 0;
++	u16                 frq_lock, signal = 0;
++	int                 rc;
+ 
+ 	tuner_dbg("%s called\n", __FUNCTION__);
+ 
+ 	mutex_lock(&priv->lock);
+ 
+-	*strength = 0;
+-
+ 	/* Sync Lock Indicator */
+-	frq_lock = xc2028_get_reg(priv, 0x0002);
+-	if (frq_lock <= 0)
++	rc = xc2028_get_reg(priv, 0x0002, &frq_lock);
++	if (rc < 0 || frq_lock == 0)
+ 		goto ret;
+ 
+ 	/* Frequency is locked. Return signal quality */
+ 
+ 	/* Get SNR of the video signal */
+-	signal = xc2028_get_reg(priv, 0x0040);
+-
+-	if (signal <= 0)
+-		signal = frq_lock;
++	rc = xc2028_get_reg(priv, 0x0040, &signal);
++	if (rc < 0)
++		signal = -frq_lock;
+ 
+ ret:
+ 	mutex_unlock(&priv->lock);
+ 
+ 	*strength = signal;
+ 
+-	return 0;
++	return rc;
+ }
+ 
+ #define DIV 15625

commit e155d908f72cc429b538c101ee8ffcd10a44b69b
+Author: Chris Pascoe 
+Date:   Mon Nov 19 04:16:47 2007 -0300
+
+    V4L/DVB (6632): xc2028: fix inverted logic in audio standard check
+    
+    strcasecmp returns 0 on match, not true.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index 6e23fad0e560..166fede7d0e3 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -200,17 +200,17 @@ void dump_firm_type(unsigned int type)
+ 
+ static  v4l2_std_id parse_audio_std_option(void)
+ {
+-	if (strcasecmp(audio_std, "A2"))
++	if (strcasecmp(audio_std, "A2") == 0)
+ 		return V4L2_STD_A2;
+-	if (strcasecmp(audio_std, "A2/A"))
++	if (strcasecmp(audio_std, "A2/A") == 0)
+ 		return V4L2_STD_A2_A;
+-	if (strcasecmp(audio_std, "A2/B"))
++	if (strcasecmp(audio_std, "A2/B") == 0)
+ 		return V4L2_STD_A2_B;
+-	if (strcasecmp(audio_std, "NICAM"))
++	if (strcasecmp(audio_std, "NICAM") == 0)
+ 		return V4L2_STD_NICAM;
+-	if (strcasecmp(audio_std, "NICAM/A"))
++	if (strcasecmp(audio_std, "NICAM/A") == 0)
+ 		return V4L2_STD_NICAM_A;
+-	if (strcasecmp(audio_std, "NICAM/B"))
++	if (strcasecmp(audio_std, "NICAM/B") == 0)
+ 		return V4L2_STD_NICAM_B;
+ 
+ 	return 0;

commit 47cc5b78102b4e9993ea1c054b4f077cf7aac7db
+Author: Chris Pascoe 
+Date:   Mon Nov 19 04:14:23 2007 -0300
+
+    V4L/DVB (6631): xc2028: eliminate i2c macro side-effects
+    
+    The I2C macros have side effects and send_seq could cause a return from
+    a function with a mutex held.  Change them to behave like real functions.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index d23b33a1f696..6e23fad0e560 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -83,31 +83,35 @@ struct xc2028_data {
+ 	struct mutex lock;
+ };
+ 
+-#define i2c_send(rc, priv, buf, size) do {				\
+-	rc = tuner_i2c_xfer_send(&priv->i2c_props, buf, size);		\
+-	if (size != rc)							\
+-		tuner_err("i2c output error: rc = %d (should be %d)\n",	\
+-			   rc, (int)size);				\
+-} while (0)
+-
+-#define i2c_rcv(rc, priv, buf, size) do {				\
+-	rc = tuner_i2c_xfer_recv(&priv->i2c_props, buf, size);		\
+-	if (size != rc)							\
++#define i2c_send(priv, buf, size) ({					\
++	int _rc;							\
++	_rc = tuner_i2c_xfer_send(&priv->i2c_props, buf, size);		\
++	if (size != _rc)						\
++		tuner_info("i2c output error: rc = %d (should be %d)\n",\
++			   _rc, (int)size);				\
++	_rc;								\
++})
++
++#define i2c_rcv(priv, buf, size) ({					\
++	int _rc;							\
++	_rc = tuner_i2c_xfer_recv(&priv->i2c_props, buf, size);		\
++	if (size != _rc)						\
+ 		tuner_err("i2c input error: rc = %d (should be %d)\n",	\
+-			   rc, (int)size); 				\
+-} while (0)
++			   _rc, (int)size); 				\
++	_rc;								\
++})
+ 
+-#define send_seq(priv, data...)	do {					\
+-	int rc;								\
++#define send_seq(priv, data...)	({					\
+ 	static u8 _val[] = data;					\
++	int _rc;							\
+ 	if (sizeof(_val) !=						\
+-			(rc = tuner_i2c_xfer_send(&priv->i2c_props,	\
++			(_rc = tuner_i2c_xfer_send(&priv->i2c_props,	\
+ 						_val, sizeof(_val)))) {	\
+-		tuner_err("Error on line %d: %d\n", __LINE__, rc);	\
+-		return -EINVAL;						\
+-	}								\
+-	msleep(10);							\
+-} while (0)
++		tuner_err("Error on line %d: %d\n", __LINE__, _rc);	\
++	} else 								\
++		msleep(10);						\
++	_rc;								\
++})
+ 
+ static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg)
+ {
+@@ -119,11 +123,11 @@ static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg)
+ 	buf[0] = reg>>8;
+ 	buf[1] = (unsigned char) reg;
+ 
+-	i2c_send(rc, priv, buf, 2);
++	rc = i2c_send(priv, buf, 2);
+ 	if (rc < 0)
+ 		return rc;
+ 
+-	i2c_rcv(rc, priv, buf, 2);
++	rc = i2c_rcv(priv, buf, 2);
+ 	if (rc < 0)
+ 		return rc;
+ 
+@@ -505,7 +509,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
+ 
+ 			memcpy(buf + 1, p, len);
+ 
+-			i2c_send(rc, priv, buf, len + 1);
++			rc = i2c_send(priv, buf, len + 1);
+ 			if (rc < 0) {
+ 				tuner_err("%d returned from send\n", rc);
+ 				return -EINVAL;
+@@ -541,15 +545,20 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type,
+ 	if ((priv->firm[pos].size != 12 * 16) || (scode >= 16))
+ 		return -EINVAL;
+ 
+-	if (priv->version < 0x0202) {
+-		send_seq(priv, {0x20, 0x00, 0x00, 0x00});
+-	} else {
+-		send_seq(priv, {0xa0, 0x00, 0x00, 0x00});
+-	}
++	if (priv->version < 0x0202)
++		rc = send_seq(priv, {0x20, 0x00, 0x00, 0x00});
++	else
++		rc = send_seq(priv, {0xa0, 0x00, 0x00, 0x00});
++	if (rc < 0)
++		return -EIO;
+ 
+-	i2c_send(rc, priv, p + 12 * scode, 12);
++	rc = i2c_send(priv, p + 12 * scode, 12);
++	if (rc < 0)
++		return -EIO;
+ 
+-	send_seq(priv, {0x00, 0x8c});
++	rc = send_seq(priv, {0x00, 0x8c});
++	if (rc < 0)
++		return -EIO;
+ 
+ 	return 0;
+ }
+@@ -766,11 +775,12 @@ static int generic_set_tv_freq(struct dvb_frontend *fe, u32 freq /* in Hz */ ,
+ 
+ 	/* CMD= Set frequency */
+ 
+-	if (priv->version < 0x0202) {
+-		send_seq(priv, {0x00, 0x02, 0x00, 0x00});
+-	} else {
+-		send_seq(priv, {0x80, 0x02, 0x00, 0x00});
+-	}
++	if (priv->version < 0x0202)
++		rc = send_seq(priv, {0x00, 0x02, 0x00, 0x00});
++	else
++		rc = send_seq(priv, {0x80, 0x02, 0x00, 0x00});
++	if (rc < 0)
++		goto ret;
+ 
+ 	rc = priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1);
+ 	if (rc < 0)
+@@ -784,7 +794,7 @@ static int generic_set_tv_freq(struct dvb_frontend *fe, u32 freq /* in Hz */ ,
+ 	buf[3] = 0xff & (div);
+ 	buf[4] = 0;
+ 
+-	i2c_send(rc, priv, buf, sizeof(buf));
++	rc = i2c_send(priv, buf, sizeof(buf));
+ 	if (rc < 0)
+ 		goto ret;
+ 	msleep(100);

commit 794604c3efb511b74fb664af72c5dd7046e91075
+Author: Chris Pascoe 
+Date:   Mon Nov 19 03:55:45 2007 -0300
+
+    V4L/DVB (6630): zl10353: calculate input frequency register instead of using hardcoded value
+    
+    Now we know the zl10353's correct ADC clock, we can calculate the input
+    frequency registers correctly instead of just blindly setting them.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c
+index 9bfdc01fed2c..1736c6ac39cc 100644
+--- a/drivers/media/dvb/frontends/zl10353.c
++++ b/drivers/media/dvb/frontends/zl10353.c
+@@ -1,7 +1,7 @@
+ /*
+  * Driver for Zarlink DVB-T ZL10353 demodulator
+  *
+- * Copyright (C) 2006 Christopher Pascoe 
++ * Copyright (C) 2006, 2007 Christopher Pascoe 
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+@@ -16,7 +16,7 @@
+  *
+  * You should have received a copy of the GNU General Public License
+  * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+  */
+ 
+ #include 
+@@ -25,6 +25,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include "dvb_frontend.h"
+ #include "zl10353_priv.h"
+@@ -148,6 +149,35 @@ static void zl10353_calc_nominal_rate(struct dvb_frontend *fe,
+ 		__FUNCTION__, bw, adc_clock, *nominal_rate);
+ }
+ 
++static void zl10353_calc_input_freq(struct dvb_frontend *fe,
++				    u16 *input_freq)
++{
++	struct zl10353_state *state = fe->demodulator_priv;
++	u32 adc_clock = 45056;	/* 45.056 MHz */
++	int if2 = 36167;	/* 36.167 MHz */
++	int ife;
++	u64 value;
++
++	if (state->config.adc_clock)
++		adc_clock = state->config.adc_clock;
++	if (state->config.if2)
++		if2 = state->config.if2;
++
++	if (adc_clock >= if2 * 2)
++		ife = if2;
++	else {
++		ife = adc_clock - (if2 % adc_clock);
++		if (ife > adc_clock / 2)
++			ife = adc_clock - ife;
++	}
++	value = 65536ULL * ife + adc_clock / 2;
++	do_div(value, adc_clock);
++	*input_freq = -value;
++
++	dprintk("%s: if2 %d, ife %d, adc_clock %d => %d / 0x%x\n",
++		__FUNCTION__, if2, ife, adc_clock, -(int)value, *input_freq);
++}
++
+ static int zl10353_sleep(struct dvb_frontend *fe)
+ {
+ 	static u8 zl10353_softdown[] = { 0x50, 0x0C, 0x44 };
+@@ -160,7 +190,7 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
+ 				  struct dvb_frontend_parameters *param)
+ {
+ 	struct zl10353_state *state = fe->demodulator_priv;
+-	u16 nominal_rate;
++	u16 nominal_rate, input_freq;
+ 	u8 pllbuf[6] = { 0x67 };
+ 
+ 	/* These settings set "auto-everything" and start the FSM. */
+@@ -178,8 +208,10 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
+ 	zl10353_single_write(fe, TRL_NOMINAL_RATE_1, msb(nominal_rate));
+ 	zl10353_single_write(fe, TRL_NOMINAL_RATE_0, lsb(nominal_rate));
+ 
+-	zl10353_single_write(fe, 0x6C, 0xCD);
+-	zl10353_single_write(fe, 0x6D, 0x7E);
++	zl10353_calc_input_freq(fe, &input_freq);
++	zl10353_single_write(fe, INPUT_FREQ_1, msb(input_freq));
++	zl10353_single_write(fe, INPUT_FREQ_0, lsb(input_freq));
++
+ 	if (fe->ops.i2c_gate_ctrl)
+ 		fe->ops.i2c_gate_ctrl(fe, 0);
+ 
+diff --git a/drivers/media/dvb/frontends/zl10353.h b/drivers/media/dvb/frontends/zl10353.h
+index 1c3d494a6da9..2660cec93f83 100644
+--- a/drivers/media/dvb/frontends/zl10353.h
++++ b/drivers/media/dvb/frontends/zl10353.h
+@@ -1,7 +1,7 @@
+ /*
+  *  Driver for Zarlink DVB-T ZL10353 demodulator
+  *
+- *  Copyright (C) 2006 Christopher Pascoe 
++ *  Copyright (C) 2006, 2007 Christopher Pascoe 
+  *
+  *  This program is free software; you can redistribute it and/or modify
+  *  it under the terms of the GNU General Public License as published by
+@@ -31,6 +31,7 @@ struct zl10353_config
+ 
+ 	/* frequencies in kHz */
+ 	int adc_clock;	/* default: 45056 */
++	int if2;	/* default: 36167 */
+ 
+ 	/* set if no pll is connected to the secondary i2c bus */
+ 	int no_tuner;
+diff --git a/drivers/media/dvb/frontends/zl10353_priv.h b/drivers/media/dvb/frontends/zl10353_priv.h
+index 42855dfe31a7..fcad9221945e 100644
+--- a/drivers/media/dvb/frontends/zl10353_priv.h
++++ b/drivers/media/dvb/frontends/zl10353_priv.h
+@@ -1,7 +1,7 @@
+ /*
+  *  Driver for Zarlink DVB-T ZL10353 demodulator
+  *
+- *  Copyright (C) 2006 Christopher Pascoe 
++ *  Copyright (C) 2006, 2007 Christopher Pascoe 
+  *
+  *  This program is free software; you can redistribute it and/or modify
+  *  it under the terms of the GNU General Public License as published by
+@@ -16,7 +16,7 @@
+  *
+  *  You should have received a copy of the GNU General Public License
+  *  along with this program; if not, write to the Free Software
+- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+  */
+ 
+ #ifndef _ZL10353_PRIV_
+@@ -48,6 +48,8 @@ enum zl10353_reg_addr {
+ 	RS_UBC_0           = 0x15,
+ 	TRL_NOMINAL_RATE_1 = 0x65,
+ 	TRL_NOMINAL_RATE_0 = 0x66,
++	INPUT_FREQ_1       = 0x6C,
++	INPUT_FREQ_0       = 0x6D,
+ 	TUNER_GO           = 0x70,
+ 	FSM_GO             = 0x71,
+ 	CHIP_ID            = 0x7F,

commit 58d834ea89664b41e6e21ed2d8dc5680d0dd76b6
+Author: Chris Pascoe 
+Date:   Mon Nov 19 03:32:06 2007 -0300
+
+    V4L/DVB (6628): zl10353: Improve support for boards without a tuner on secondary i2c
+    
+    Issue FSM_GO instead of TUNER_GO if there is no tuner attached to the
+    secondary i2c bus.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c
+index 0106df4c55e8..9bfdc01fed2c 100644
+--- a/drivers/media/dvb/frontends/zl10353.c
++++ b/drivers/media/dvb/frontends/zl10353.c
+@@ -183,35 +183,31 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
+ 	if (fe->ops.i2c_gate_ctrl)
+ 		fe->ops.i2c_gate_ctrl(fe, 0);
+ 
+-	// if there is no attached secondary tuner, we call set_params to program
+-	// a potential tuner attached somewhere else
++	/*
++	 * If there is no tuner attached to the secondary I2C bus, we call
++	 * set_params to program a potential tuner attached somewhere else.
++	 * Otherwise, we update the PLL registers via calc_regs.
++	 */
+ 	if (state->config.no_tuner) {
+ 		if (fe->ops.tuner_ops.set_params) {
+ 			fe->ops.tuner_ops.set_params(fe, param);
+ 			if (fe->ops.i2c_gate_ctrl)
+ 				fe->ops.i2c_gate_ctrl(fe, 0);
+ 		}
+-	}
+-
+-	// if pllbuf is defined, retrieve the settings
+-	if (fe->ops.tuner_ops.calc_regs) {
+-		fe->ops.tuner_ops.calc_regs(fe, param, pllbuf+1, 5);
++	} else if (fe->ops.tuner_ops.calc_regs) {
++		fe->ops.tuner_ops.calc_regs(fe, param, pllbuf + 1, 5);
+ 		pllbuf[1] <<= 1;
+-	} else {
+-		// fake pllbuf settings
+-		pllbuf[1] = 0x61 << 1;
+-		pllbuf[2] = 0;
+-		pllbuf[3] = 0;
+-		pllbuf[3] = 0;
+-		pllbuf[4] = 0;
++		zl10353_write(fe, pllbuf, sizeof(pllbuf));
+ 	}
+ 
+-	// there is no call to _just_ start decoding, so we send the pllbuf anyway
+-	// even if there isn't a PLL attached to the secondary bus
+-	zl10353_write(fe, pllbuf, sizeof(pllbuf));
+-
+ 	zl10353_single_write(fe, 0x5F, 0x13);
+-	zl10353_single_write(fe, 0x70, 0x01);
++
++	/* If no attached tuner or invalid PLL registers, just start the FSM. */
++	if (state->config.no_tuner || fe->ops.tuner_ops.calc_regs == NULL)
++		zl10353_single_write(fe, FSM_GO, 0x01);
++	else
++		zl10353_single_write(fe, TUNER_GO, 0x01);
++
+ 	udelay(250);
+ 	zl10353_single_write(fe, 0xE4, 0x00);
+ 	zl10353_single_write(fe, 0xE5, 0x2A);
+diff --git a/drivers/media/dvb/frontends/zl10353_priv.h b/drivers/media/dvb/frontends/zl10353_priv.h
+index 4962434b35e7..42855dfe31a7 100644
+--- a/drivers/media/dvb/frontends/zl10353_priv.h
++++ b/drivers/media/dvb/frontends/zl10353_priv.h
+@@ -48,6 +48,8 @@ enum zl10353_reg_addr {
+ 	RS_UBC_0           = 0x15,
+ 	TRL_NOMINAL_RATE_1 = 0x65,
+ 	TRL_NOMINAL_RATE_0 = 0x66,
++	TUNER_GO           = 0x70,
++	FSM_GO             = 0x71,
+ 	CHIP_ID            = 0x7F,
+ };
+ 

commit a644e4a3e95f8ca6eca019c92d8dfde101150687
+Author: Chris Pascoe 
+Date:   Mon Nov 19 03:05:09 2007 -0300
+
+    V4L/DVB (6627): CXUSB: handle write then read from different address
+    
+    The path to perform a read immediately after a write was not checking that
+    the address being read from was the same as the one that was written.
+    
+    Handling this case correctly should mean that we now can handle more than
+    two i2c messages at a time.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
+index 016a3780b714..74eeb168f241 100644
+--- a/drivers/media/dvb/dvb-usb/cxusb.c
++++ b/drivers/media/dvb/dvb-usb/cxusb.c
+@@ -83,9 +83,6 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+ 	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ 		return -EAGAIN;
+ 
+-	if (num > 2)
+-		warn("more than two i2c messages at a time is not handled yet. TODO.");
+-
+ 	for (i = 0; i < num; i++) {
+ 
+ 		if (d->udev->descriptor.idVendor == USB_VID_MEDION)
+@@ -111,8 +108,9 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+ 				break;
+ 			}
+ 			memcpy(msg[i].buf, &ibuf[1], msg[i].len);
+-		} else if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
+-			/* write then read */
++		} else if (i+1 < num && (msg[i+1].flags & I2C_M_RD) &&
++			   msg[i].addr == msg[i+1].addr) {
++			/* write to then read from same address */
+ 			u8 obuf[3+msg[i].len], ibuf[1+msg[i+1].len];
+ 			obuf[0] = msg[i].len;
+ 			obuf[1] = msg[i+1].len;

commit 272479d7ab067344d118e7633b624bf98f8896f3
+Author: Chris Pascoe 
+Date:   Mon Nov 19 03:01:22 2007 -0300
+
+    V4L/DVB (6626): CXUSB: support only-read i2c requests
+    
+    Any i2c read request that was not immediately preceded by a write request was
+    incorrectly taking the write path.  Add the capability to handle individual
+    read requests.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
+index 86fbd6c73ea9..016a3780b714 100644
+--- a/drivers/media/dvb/dvb-usb/cxusb.c
++++ b/drivers/media/dvb/dvb-usb/cxusb.c
+@@ -98,8 +98,21 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+ 				break;
+ 			}
+ 
+-		/* read request */
+-		if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
++		if (msg[i].flags & I2C_M_RD) {
++			/* read only */
++			u8 obuf[3], ibuf[1+msg[i].len];
++			obuf[0] = 0;
++			obuf[1] = msg[i].len;
++			obuf[2] = msg[i].addr;
++			if (cxusb_ctrl_msg(d, CMD_I2C_READ,
++					   obuf, 3,
++					   ibuf, 1+msg[i].len) < 0) {
++				warn("i2c read failed");
++				break;
++			}
++			memcpy(msg[i].buf, &ibuf[1], msg[i].len);
++		} else if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
++			/* write then read */
+ 			u8 obuf[3+msg[i].len], ibuf[1+msg[i+1].len];
+ 			obuf[0] = msg[i].len;
+ 			obuf[1] = msg[i+1].len;
+@@ -117,7 +130,8 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+ 			memcpy(msg[i+1].buf, &ibuf[1], msg[i+1].len);
+ 
+ 			i++;
+-		} else { /* write */
++		} else {
++			/* write only */
+ 			u8 obuf[2+msg[i].len], ibuf;
+ 			obuf[0] = msg[i].addr;
+ 			obuf[1] = msg[i].len;

commit 13e001dfe3aeb9e7b05445af76e5b47235e81285
+Author: Chris Pascoe 
+Date:   Mon Nov 19 02:48:27 2007 -0300
+
+    V4L/DVB (6625): CXUSB: i2c transfer failure notification
+    
+    The i2c master_xfer routine should return a negative result if not all
+    transfers completed successfully.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
+index b4a3f7baf1b7..86fbd6c73ea9 100644
+--- a/drivers/media/dvb/dvb-usb/cxusb.c
++++ b/drivers/media/dvb/dvb-usb/cxusb.c
+@@ -132,7 +132,7 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+ 	}
+ 
+ 	mutex_unlock(&d->i2c_mutex);
+-	return i;
++	return i == num ? num : -EREMOTEIO;
+ }
+ 
+ static u32 cxusb_i2c_func(struct i2c_adapter *adapter)

commit b17f109df1cd9fe1009501d59e466701106590d7
+Author: Chris Pascoe 
+Date:   Mon Nov 19 02:42:44 2007 -0300
+
+    V4L/DVB (6624): CXUSB: return control message transfer result to caller
+    
+    Callers to cxusb_ctrl_msg currently do not receive any indication that their
+    transfer failed.  Return the true return code from dvb_usb_generic_{rw,write}.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
+index 5b6431ea38c1..b4a3f7baf1b7 100644
+--- a/drivers/media/dvb/dvb-usb/cxusb.c
++++ b/drivers/media/dvb/dvb-usb/cxusb.c
+@@ -49,11 +49,9 @@ static int cxusb_ctrl_msg(struct dvb_usb_device *d,
+ 	sndbuf[0] = cmd;
+ 	memcpy(&sndbuf[1], wbuf, wlen);
+ 	if (wo)
+-		dvb_usb_generic_write(d, sndbuf, 1+wlen);
++		return dvb_usb_generic_write(d, sndbuf, 1+wlen);
+ 	else
+-		dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0);
+-
+-	return 0;
++		return dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0);
+ }
+ 
+ /* GPIO */

commit 78f3b0b672c79df9ffa55399a7d6fc4b173e9b4b
+Author: Chris Pascoe 
+Date:   Mon Nov 19 03:47:07 2007 -0300
+
+    V4L/DVB (6629): zl10353: fix default adc_clock and TRL nominal rate calculation
+    
+    The default adc_clock for the zl10353 is different from what was originally
+    thought to be the case and the TRL nominal rate formula was incorrect as a
+    result.  Use a better (and hopefully now correct) formula.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c
+index a97a7fd2c891..0106df4c55e8 100644
+--- a/drivers/media/dvb/frontends/zl10353.c
++++ b/drivers/media/dvb/frontends/zl10353.c
+@@ -122,7 +122,7 @@ static void zl10353_calc_nominal_rate(struct dvb_frontend *fe,
+ 				      enum fe_bandwidth bandwidth,
+ 				      u16 *nominal_rate)
+ {
+-	u32 adc_clock = 22528; /* 20.480 MHz on the board(!?) */
++	u32 adc_clock = 45056; /* 45.056 MHz */
+ 	u8 bw;
+ 	struct zl10353_state *state = fe->demodulator_priv;
+ 
+@@ -142,7 +142,7 @@ static void zl10353_calc_nominal_rate(struct dvb_frontend *fe,
+ 		break;
+ 	}
+ 
+-	*nominal_rate = (64 * bw * (1<<16) / (7 * 8) * 4000 / adc_clock + 2) / 4;
++	*nominal_rate = (bw * (1 << 23) / 7 * 125 + adc_clock / 2) / adc_clock;
+ 
+ 	dprintk("%s: bw %d, adc_clock %d => 0x%x\n",
+ 		__FUNCTION__, bw, adc_clock, *nominal_rate);
+diff --git a/drivers/media/dvb/frontends/zl10353.h b/drivers/media/dvb/frontends/zl10353.h
+index cb274dc12b82..1c3d494a6da9 100644
+--- a/drivers/media/dvb/frontends/zl10353.h
++++ b/drivers/media/dvb/frontends/zl10353.h
+@@ -30,7 +30,7 @@ struct zl10353_config
+ 	u8 demod_address;
+ 
+ 	/* frequencies in kHz */
+-	int adc_clock;  // default: 22528
++	int adc_clock;	/* default: 45056 */
+ 
+ 	/* set if no pll is connected to the secondary i2c bus */
+ 	int no_tuner;

commit 6345f0f6428cc7a3f73b83624c6f97629a9fddd1
+Author: Chris Pascoe 
+Date:   Sat Feb 10 10:19:16 2007 -0300
+
+    V4L/DVB (5218): Zl10353: register definitions update
+    
+    Update the descriptions of "discovered" registers on the zl10353, using the
+    equivalaent mt352 register names.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c
+index dbb53ba6f414..245f9b7dddfa 100644
+--- a/drivers/media/dvb/frontends/zl10353.c
++++ b/drivers/media/dvb/frontends/zl10353.c
+@@ -258,9 +258,9 @@ static int zl10353_read_ber(struct dvb_frontend *fe, u32 *ber)
+ {
+ 	struct zl10353_state *state = fe->demodulator_priv;
+ 
+-	*ber = zl10353_read_register(state, 0x11) << 16 |
+-	       zl10353_read_register(state, 0x12) << 8 |
+-	       zl10353_read_register(state, 0x13);
++	*ber = zl10353_read_register(state, RS_ERR_CNT_2) << 16 |
++	       zl10353_read_register(state, RS_ERR_CNT_1) << 8 |
++	       zl10353_read_register(state, RS_ERR_CNT_0);
+ 
+ 	return 0;
+ }
+@@ -269,8 +269,8 @@ static int zl10353_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+ {
+ 	struct zl10353_state *state = fe->demodulator_priv;
+ 
+-	u16 signal = zl10353_read_register(state, 0x0a) << 10 |
+-		     zl10353_read_register(state, 0x0b) << 2 | 3;
++	u16 signal = zl10353_read_register(state, AGC_GAIN_1) << 10 |
++		     zl10353_read_register(state, AGC_GAIN_0) << 2 | 3;
+ 
+ 	*strength = ~signal;
+ 
+@@ -295,8 +295,8 @@ static int zl10353_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+ {
+ 	struct zl10353_state *state = fe->demodulator_priv;
+ 
+-	*ucblocks = zl10353_read_register(state, 0x14) << 8 |
+-		    zl10353_read_register(state, 0x15);
++	*ucblocks = zl10353_read_register(state, RS_UBC_1) << 8 |
++		    zl10353_read_register(state, RS_UBC_0);
+ 
+ 	return 0;
+ }
+diff --git a/drivers/media/dvb/frontends/zl10353_priv.h b/drivers/media/dvb/frontends/zl10353_priv.h
+index d2186927f8f1..4962434b35e7 100644
+--- a/drivers/media/dvb/frontends/zl10353_priv.h
++++ b/drivers/media/dvb/frontends/zl10353_priv.h
+@@ -38,7 +38,14 @@ enum zl10353_reg_addr {
+ 	STATUS_7           = 0x07,
+ 	STATUS_8           = 0x08,
+ 	STATUS_9           = 0x09,
++	AGC_GAIN_1         = 0x0A,
++	AGC_GAIN_0         = 0x0B,
+ 	SNR                = 0x10,
++	RS_ERR_CNT_2       = 0x11,
++	RS_ERR_CNT_1       = 0x12,
++	RS_ERR_CNT_0       = 0x13,
++	RS_UBC_1           = 0x14,
++	RS_UBC_0           = 0x15,
+ 	TRL_NOMINAL_RATE_1 = 0x65,
+ 	TRL_NOMINAL_RATE_0 = 0x66,
+ 	CHIP_ID            = 0x7F,

commit 67b60aad168cfdd40ffec12f14b93e2e68f7d486
+Author: Chris Pascoe 
+Date:   Sat Feb 10 10:17:57 2007 -0300
+
+    V4L/DVB (5215): Experimental support for signal strength/BER/uncorrectable count
+    
+    After studying many hours worth of register dumps of MT352 and ZL10353 fed
+    with identically damaged RF signals I have made an educated guess at which
+    registers contain the AGC level, bit error rate and uncorrectable error
+    count values.
+    Implement the IOCTLs that return these values to userspace.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c
+index a1b0afbd47ba..0d8241de89ee 100644
+--- a/drivers/media/dvb/frontends/zl10353.c
++++ b/drivers/media/dvb/frontends/zl10353.c
+@@ -213,6 +213,29 @@ static int zl10353_read_status(struct dvb_frontend *fe, fe_status_t *status)
+ 	return 0;
+ }
+ 
++static int zl10353_read_ber(struct dvb_frontend *fe, u32 *ber)
++{
++	struct zl10353_state *state = fe->demodulator_priv;
++
++	*ber = zl10353_read_register(state, 0x11) << 16 |
++	       zl10353_read_register(state, 0x12) << 8 |
++	       zl10353_read_register(state, 0x13);
++
++	return 0;
++}
++
++static int zl10353_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
++{
++	struct zl10353_state *state = fe->demodulator_priv;
++
++	u16 signal = zl10353_read_register(state, 0x0a) << 10 |
++		     zl10353_read_register(state, 0x0b) << 2 | 3;
++
++	*strength = ~signal;
++
++	return 0;
++}
++
+ static int zl10353_read_snr(struct dvb_frontend *fe, u16 *snr)
+ {
+ 	struct zl10353_state *state = fe->demodulator_priv;
+@@ -227,6 +250,16 @@ static int zl10353_read_snr(struct dvb_frontend *fe, u16 *snr)
+ 	return 0;
+ }
+ 
++static int zl10353_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
++{
++	struct zl10353_state *state = fe->demodulator_priv;
++
++	*ucblocks = zl10353_read_register(state, 0x14) << 8 |
++		    zl10353_read_register(state, 0x15);
++
++	return 0;
++}
++
+ static int zl10353_get_tune_settings(struct dvb_frontend *fe,
+ 				     struct dvb_frontend_tune_settings
+ 					 *fe_tune_settings)
+@@ -325,7 +358,10 @@ static struct dvb_frontend_ops zl10353_ops = {
+ 	.get_tune_settings = zl10353_get_tune_settings,
+ 
+ 	.read_status = zl10353_read_status,
++	.read_ber = zl10353_read_ber,
++	.read_signal_strength = zl10353_read_signal_strength,
+ 	.read_snr = zl10353_read_snr,
++	.read_ucblocks = zl10353_read_ucblocks,
+ };
+ 
+ module_param(debug_regs, int, 0644);

commit d536e9c41f78c9959c585181f8a1e7fe8b157197
+Author: Chris Pascoe 
+Date:   Thu Aug 10 03:22:21 2006 -0300
+
+    V4L/DVB (4497): Reset USB part of DViCO Dual Digital during PCI driver attach
+    
+    If the FX2 does not reset properly during reboot, it can present an
+    invalid USB device ID and fail to attach.  Prevent this situation
+    from occuring by resetting the USB part of the card when the PCI part
+    probes.
+    Also fix the GPIO configurations so that analog capture will not
+    inadvertantly reset the USB part.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
+index ba3ff57bba75..29ba5d53ce34 100644
+--- a/drivers/media/video/cx88/cx88-cards.c
++++ b/drivers/media/video/cx88/cx88-cards.c
+@@ -1041,11 +1041,11 @@ struct cx88_board cx88_boards[] = {
+ 		.input          = {{
+ 			.type   = CX88_VMUX_COMPOSITE1,
+ 			.vmux   = 1,
+-			.gpio0  = 0x000027df,
++			.gpio0  = 0x000067df,
+ 		 },{
+ 			.type   = CX88_VMUX_SVIDEO,
+ 			.vmux   = 2,
+-			.gpio0  = 0x000027df,
++			.gpio0  = 0x000067df,
+ 		}},
+ 		.dvb            = 1,
+ 	},
+@@ -1759,9 +1759,15 @@ void cx88_card_setup(struct cx88_core *core)
+ 		cx_write(MO_GP0_IO, 0x000007f8);
+ 		cx_write(MO_GP1_IO, 0x00000001);
+ 		break;
++	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
++		/* GPIO0:6 is hooked to FX2 reset pin */
++		cx_set(MO_GP0_IO, 0x00004040);
++		cx_clear(MO_GP0_IO, 0x00000040);
++		msleep(1000);
++		cx_set(MO_GP0_IO, 0x00004040);
++		/* FALLTHROUGH */
+ 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
+ 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
+-	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
+ 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
+ 		/* GPIO0:0 is hooked to mt352 reset pin */
+ 		cx_set(MO_GP0_IO, 0x00000101);

commit fc3398d8b317bebe542f57c65572d9b9f52112f7
+Author: Chris Pascoe 
+Date:   Thu Aug 10 03:17:42 2006 -0300
+
+    V4L/DVB (4496): Tuning tweaks for ZL10353
+    
+    More register setup which improves the ZL10353's tuning characteristics.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c
+index 84abbaf362fb..0e9b59af271e 100644
+--- a/drivers/media/dvb/frontends/zl10353.c
++++ b/drivers/media/dvb/frontends/zl10353.c
+@@ -140,6 +140,8 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
+ 	zl10353_single_write(fe, 0x5E, 0x00);
+ 	zl10353_single_write(fe, 0x65, 0x5A);
+ 	zl10353_single_write(fe, 0x66, 0xE9);
++	zl10353_single_write(fe, 0x6C, 0xCD);
++	zl10353_single_write(fe, 0x6D, 0x7E);
+ 	zl10353_single_write(fe, 0x62, 0x0A);
+ 
+ 	// if there is no attached secondary tuner, we call set_params to program
+@@ -168,6 +170,7 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
+ 	// even if there isn't a PLL attached to the secondary bus
+ 	zl10353_write(fe, pllbuf, sizeof(pllbuf));
+ 
++	zl10353_single_write(fe, 0x5F, 0x13);
+ 	zl10353_single_write(fe, 0x70, 0x01);
+ 	udelay(250);
+ 	zl10353_single_write(fe, 0xE4, 0x00);

commit 8fb957841b2f4311e6418dcbef24564e4cebb87d
+Author: Chris Pascoe 
+Date:   Thu Aug 10 03:17:16 2006 -0300
+
+    V4L/DVB (4495): Fix "no data from ZL10353 based USB tuner" problem
+    
+    Force parallel transport stream output on the ZL10353 attached to a
+    bluebird device.
+    Addresses the problem where a frontend lock was observed, but no MPEG
+    transport data was received.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
+index ac72e7ed9fcc..c710c0176e07 100644
+--- a/drivers/media/dvb/dvb-usb/cxusb.c
++++ b/drivers/media/dvb/dvb-usb/cxusb.c
+@@ -349,6 +349,7 @@ static struct mt352_config cxusb_dee1601_config = {
+ 
+ static struct zl10353_config cxusb_zl10353_dee1601_config = {
+ 	.demod_address = 0x0f,
++	.parallel_ts = 1,
+ };
+ 
+ static struct mt352_config cxusb_mt352_config = {
+diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c
+index 953fb55d87b6..84abbaf362fb 100644
+--- a/drivers/media/dvb/frontends/zl10353.c
++++ b/drivers/media/dvb/frontends/zl10353.c
+@@ -243,9 +243,12 @@ static int zl10353_init(struct dvb_frontend *fe)
+ 
+ 	if (debug_regs)
+ 		zl10353_dump_regs(fe);
++	if (state->config.parallel_ts)
++		zl10353_reset_attach[2] &= ~0x20;
+ 
+ 	/* Do a "hard" reset if not already done */
+-	if (zl10353_read_register(state, 0x50) != 0x03) {
++	if (zl10353_read_register(state, 0x50) != zl10353_reset_attach[1] ||
++	    zl10353_read_register(state, 0x51) != zl10353_reset_attach[2]) {
+ 		rc = zl10353_write(fe, zl10353_reset_attach,
+ 				   sizeof(zl10353_reset_attach));
+ 		if (debug_regs)
+diff --git a/drivers/media/dvb/frontends/zl10353.h b/drivers/media/dvb/frontends/zl10353.h
+index 6aec655d8814..79a947215c4d 100644
+--- a/drivers/media/dvb/frontends/zl10353.h
++++ b/drivers/media/dvb/frontends/zl10353.h
+@@ -31,6 +31,9 @@ struct zl10353_config
+ 
+ 	/* set if no pll is connected to the secondary i2c bus */
+ 	int no_tuner;
++
++	/* set if parallel ts output is required */
++	int parallel_ts;
+ };
+ 
+ #if defined(CONFIG_DVB_ZL10353) || defined(CONFIG_DVB_ZL10353_MODULE)

commit 47922e9c3f583adf05a23842ff98f3b0bf7eec6d
+Author: Chris Pascoe 
+Date:   Sat Aug 5 23:47:16 2006 -0300
+
+    V4L/DVB (4441): Flexcop/nxt200x attach fix
+    
+    Address another case where the test in dvb-pll to see if a tuner's
+    PLL responds when attaching may fail.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+index 0c3bab37d8df..b8ba87863457 100644
+--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
++++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+@@ -527,7 +527,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
+ 	/* try the air atsc 2nd generation (nxt2002) */
+ 	if ((fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
+ 		fc->dev_type          = FC_AIR_ATSC2;
+-		dvb_attach(dvb_pll_attach, fc->fe, 0x61, &fc->i2c_adap, &dvb_pll_samsung_tbmv);
++		dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, &dvb_pll_samsung_tbmv);
+ 		info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
+ 	} else
+ 	/* try the air atsc 3nd generation (lgdt3303) */

commit c162dff6437d5f66c272b1811074ee32c53d17b9
+Author: Chris Pascoe 
+Date:   Tue Aug 8 15:48:08 2006 -0300
+
+    V4L/DVB (4436): Dvb-pll support for MT352/ZL10353 based tuners.
+    
+    Typical wiring of MT352 and ZL10353 based tuners differs from dvb-pll's
+    expectation that the PLL is directly accessible.  On these boards, the
+    PLL is actually hidden behind the demodulator, and as such can only be
+    accessed via the demodulator's interface.  It was failing to communicate
+    with the PLL during an attach test and subsequently not connecting the
+    tuner ops.
+    By passing a NULL I2C bus handle to dvb_pll_attach, this accessibility
+    check can be bypassed.  Do this for the affected boards.  Also fix a
+    possible NULL dereference at sleep time, which would otherwise be
+    exposed by this change.
+    
+    Signed-off-by: Chris Pascoe 
+    Acked-by: Andrew de Quincey 
+    Acked-by: Manu Abraham 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
+index c92877baada2..b7e7108ee5b3 100644
+--- a/drivers/media/dvb/frontends/dvb-pll.c
++++ b/drivers/media/dvb/frontends/dvb-pll.c
+@@ -493,6 +493,9 @@ static int dvb_pll_sleep(struct dvb_frontend *fe)
+ 	int i;
+ 	int result;
+ 
++	if (priv->i2c == NULL)
++		return -EINVAL;
++
+ 	for (i = 0; i < priv->pll_desc->count; i++) {
+ 		if (priv->pll_desc->entries[i].limit == 0)
+ 			break;
+diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
+index 81654954c338..b39b3629f1d0 100644
+--- a/drivers/media/video/cx88/cx88-dvb.c
++++ b/drivers/media/video/cx88/cx88-dvb.c
+@@ -543,8 +543,7 @@ static int dvb_register(struct cx8802_dev *dev)
+ 						 &dev->core->i2c_adap);
+ 		if (dev->dvb.frontend != NULL) {
+ 			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
+-				       &dev->core->i2c_adap,
+-				       &dvb_pll_thomson_dtt7579);
++				   NULL, &dvb_pll_thomson_dtt7579);
+ 			break;
+ 		}
+ 		/* ZL10353 replaces MT352 on later cards */
+@@ -552,8 +551,7 @@ static int dvb_register(struct cx8802_dev *dev)
+ 						   &dev->core->i2c_adap);
+ 		if (dev->dvb.frontend != NULL) {
+ 			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
+-				       &dev->core->i2c_adap,
+-				       &dvb_pll_thomson_dtt7579);
++				   NULL, &dvb_pll_thomson_dtt7579);
+ 		}
+ 		break;
+ 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
+@@ -563,8 +561,7 @@ static int dvb_register(struct cx8802_dev *dev)
+ 						 &dev->core->i2c_adap);
+ 		if (dev->dvb.frontend != NULL) {
+ 			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+-				       &dev->core->i2c_adap,
+-				       &dvb_pll_thomson_dtt7579);
++				   NULL, &dvb_pll_thomson_dtt7579);
+ 			break;
+ 		}
+ 		/* ZL10353 replaces MT352 on later cards */
+@@ -572,8 +569,7 @@ static int dvb_register(struct cx8802_dev *dev)
+ 						   &dev->core->i2c_adap);
+ 		if (dev->dvb.frontend != NULL) {
+ 			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+-				       &dev->core->i2c_adap,
+-				       &dvb_pll_thomson_dtt7579);
++				   NULL, &dvb_pll_thomson_dtt7579);
+ 		}
+ 		break;
+ 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
+@@ -581,8 +577,7 @@ static int dvb_register(struct cx8802_dev *dev)
+ 						 &dev->core->i2c_adap);
+ 		if (dev->dvb.frontend != NULL) {
+ 			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+-				       &dev->core->i2c_adap,
+-				       &dvb_pll_lg_z201);
++				   NULL, &dvb_pll_lg_z201);
+ 		}
+ 		break;
+ 	case CX88_BOARD_KWORLD_DVB_T:
+@@ -592,8 +587,7 @@ static int dvb_register(struct cx8802_dev *dev)
+ 						 &dev->core->i2c_adap);
+ 		if (dev->dvb.frontend != NULL) {
+ 			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+-				       &dev->core->i2c_adap,
+-				       &dvb_pll_unknown_1);
++				   NULL, &dvb_pll_unknown_1);
+ 		}
+ 		break;
+ 	case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:

commit 69b27e3dfebff8f59e979d57263e1cd83c4d8370
+Author: Chris Pascoe 
+Date:   Tue Feb 28 20:23:11 2006 -0300
+
+    V4L/DVB (3410): Move DViCO hybrid initialisation data from stack.
+    
+    The init_data array is never changed and need not be on the stack.
+    Turn it into a static variable.
+    
+    Signed-off-by: Michael Krufky 
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
+index d91e5b3a64ef..f655567a8ecd 100644
+--- a/drivers/media/video/cx88/cx88-cards.c
++++ b/drivers/media/video/cx88/cx88-cards.c
+@@ -1435,7 +1435,7 @@ static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core)
+ {
+ 	struct i2c_msg msg = { .addr = 0x45, .flags = 0 };
+ 	int i, err;
+-	u8 init_bufs[13][5] = {
++	static u8 init_bufs[13][5] = {
+ 		{ 0x10, 0x00, 0x20, 0x01, 0x03 },
+ 		{ 0x10, 0x10, 0x01, 0x00, 0x21 },
+ 		{ 0x10, 0x10, 0x10, 0x00, 0xCA },

commit 780dfef37e2c941985b708f67aa0074edc922bea
+Author: Chris Pascoe 
+Date:   Tue Feb 28 08:34:59 2006 -0300
+
+    V4L/DVB (3408): DViCO FusionHDTV DVB-T Hybrid and ZL10353-based FusionHDTV DVB-T Plus support
+    
+    Add support for the FE6600 tuner used on the DVB-T Hybrid board.
+    Add support for the Zarlink ZL10353 DVB-T demodulator, which supersedes the
+    MT352, used on the DViCO FusionHDTV DVB-T Hybrid and later model Plus boards.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88
+index d852ad4f93a2..3b39a91b24bd 100644
+--- a/Documentation/video4linux/CARDLIST.cx88
++++ b/Documentation/video4linux/CARDLIST.cx88
+@@ -44,3 +44,4 @@
+  43 -> KWorld/VStream XPert DVB-T with cx22702             [17de:08a1]
+  44 -> DViCO FusionHDTV DVB-T Dual Digital                 [18ac:db50,18ac:db54]
+  45 -> KWorld HardwareMpegTV XPert                         [17de:0840]
++ 46 -> DViCO FusionHDTV DVB-T Hybrid                       [18ac:db40,18ac:db44]
+diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner
+index de48438d5115..ab344c94c0a2 100644
+--- a/Documentation/video4linux/CARDLIST.tuner
++++ b/Documentation/video4linux/CARDLIST.tuner
+@@ -70,3 +70,4 @@ tuner=68 - Philips TUV1236D ATSC/NTSC dual in
+ tuner=69 - Tena TNF 5335 MF
+ tuner=70 - Samsung TCPN 2121P30A
+ tuner=71 - Xceive xc3028
++tuner=72 - FE6600
+diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
+index c676b1e23ab0..a1a894d81040 100644
+--- a/drivers/media/dvb/frontends/Kconfig
++++ b/drivers/media/dvb/frontends/Kconfig
+@@ -116,6 +116,12 @@ config DVB_MT352
+ 	help
+ 	  A DVB-T tuner module. Say Y when you want to support this frontend.
+ 
++config DVB_ZL10353
++	tristate "Zarlink ZL10353 based"
++	depends on DVB_CORE
++	help
++	  A DVB-T tuner module. Say Y when you want to support this frontend.
++
+ config DVB_DIB3000MB
+ 	tristate "DiBcom 3000M-B"
+ 	depends on DVB_CORE
+diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
+index 1af769cd90c0..d09b6071fbaf 100644
+--- a/drivers/media/dvb/frontends/Makefile
++++ b/drivers/media/dvb/frontends/Makefile
+@@ -20,6 +20,7 @@ obj-$(CONFIG_DVB_TDA1004X) += tda1004x.o
+ obj-$(CONFIG_DVB_SP887X) += sp887x.o
+ obj-$(CONFIG_DVB_NXT6000) += nxt6000.o
+ obj-$(CONFIG_DVB_MT352) += mt352.o
++obj-$(CONFIG_DVB_ZL10353) += zl10353.o
+ obj-$(CONFIG_DVB_CX22702) += cx22702.o
+ obj-$(CONFIG_DVB_TDA10021) += tda10021.o
+ obj-$(CONFIG_DVB_STV0297) += stv0297.o
+diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
+index 4f682534df42..8a4c904d3a27 100644
+--- a/drivers/media/dvb/frontends/dvb-pll.c
++++ b/drivers/media/dvb/frontends/dvb-pll.c
+@@ -404,6 +404,21 @@ struct dvb_pll_desc dvb_pll_philips_td1316 = {
+ };
+ EXPORT_SYMBOL(dvb_pll_philips_td1316);
+ 
++/* FE6600 used on DViCO Hybrid */
++struct dvb_pll_desc dvb_pll_unknown_fe6600 = {
++	.name = "FE6600",
++	.min =  44250000,
++	.max = 858000000,
++	.count = 4,
++	.entries = {
++		{ 250000000, 36213333, 166667, 0xb4, 0x12 },
++		{ 455000000, 36213333, 166667, 0xfe, 0x11 },
++		{ 775500000, 36213333, 166667, 0xbc, 0x18 },
++		{ 999999999, 36213333, 166667, 0xf4, 0x18 },
++	}
++};
++EXPORT_SYMBOL(dvb_pll_unknown_fe6600);
++
+ /* ----------------------------------------------------------- */
+ /* code                                                        */
+ 
+diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h
+index 56c3cd76a7fa..8a7f0b941c38 100644
+--- a/drivers/media/dvb/frontends/dvb-pll.h
++++ b/drivers/media/dvb/frontends/dvb-pll.h
+@@ -42,6 +42,8 @@ extern struct dvb_pll_desc dvb_pll_samsung_tbmv;
+ extern struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261;
+ extern struct dvb_pll_desc dvb_pll_philips_td1316;
+ 
++extern struct dvb_pll_desc dvb_pll_unknown_fe6600;
++
+ int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
+ 		      u32 freq, int bandwidth);
+ 
+diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c
+new file mode 100644
+index 000000000000..23846c4452ad
+--- /dev/null
++++ b/drivers/media/dvb/frontends/zl10353.c
+@@ -0,0 +1,311 @@
++/*
++ * Driver for Zarlink DVB-T ZL10353 demodulator
++ *
++ * Copyright (C) 2006 Christopher Pascoe 
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include "dvb_frontend.h"
++#include "zl10353_priv.h"
++#include "zl10353.h"
++
++struct zl10353_state {
++	struct i2c_adapter *i2c;
++	struct dvb_frontend frontend;
++	struct dvb_frontend_ops ops;
++
++	struct zl10353_config config;
++};
++
++static int debug_regs = 0;
++
++static int zl10353_single_write(struct dvb_frontend *fe, u8 reg, u8 val)
++{
++	struct zl10353_state *state = fe->demodulator_priv;
++	u8 buf[2] = { reg, val };
++	struct i2c_msg msg = { .addr = state->config.demod_address, .flags = 0,
++			       .buf = buf, .len = 2 };
++	int err = i2c_transfer(state->i2c, &msg, 1);
++	if (err != 1) {
++		printk("zl10353: write to reg %x failed (err = %d)!\n", reg, err);
++		return err;
++	}
++	return 0;
++}
++
++int zl10353_write(struct dvb_frontend *fe, u8 *ibuf, int ilen)
++{
++	int err, i;
++	for (i = 0; i < ilen - 1; i++)
++		if ((err = zl10353_single_write(fe, ibuf[0] + i, ibuf[i + 1])))
++			return err;
++
++	return 0;
++}
++
++static int zl10353_read_register(struct zl10353_state *state, u8 reg)
++{
++	int ret;
++	u8 b0[1] = { reg };
++	u8 b1[1] = { 0 };
++	struct i2c_msg msg[2] = { { .addr = state->config.demod_address,
++				    .flags = 0,
++				    .buf = b0, .len = 1 },
++				  { .addr = state->config.demod_address,
++				    .flags = I2C_M_RD,
++				    .buf = b1, .len = 1 } };
++
++	ret = i2c_transfer(state->i2c, msg, 2);
++
++	if (ret != 2) {
++		printk("%s: readreg error (reg=%d, ret==%i)\n",
++		       __FUNCTION__, reg, ret);
++		return ret;
++	}
++
++	return b1[0];
++}
++
++void zl10353_dump_regs(struct dvb_frontend *fe)
++{
++	struct zl10353_state *state = fe->demodulator_priv;
++	char buf[52], buf2[4];
++	int ret;
++	u8 reg;
++
++	/* Dump all registers. */
++	for (reg = 0; ; reg++) {
++		if (reg % 16 == 0) {
++			if (reg)
++				printk(KERN_DEBUG "%s\n", buf);
++			sprintf(buf, "%02x: ", reg);
++		}
++		ret = zl10353_read_register(state, reg);
++		if (ret >= 0)
++			sprintf(buf2, "%02x ", (u8)ret);
++		else
++			strcpy(buf2, "-- ");
++		strcat(buf, buf2);
++		if (reg == 0xff)
++			break;
++	}
++	printk(KERN_DEBUG "%s\n", buf);
++}
++
++static int zl10353_sleep(struct dvb_frontend *fe)
++{
++	static u8 zl10353_softdown[] = { 0x50, 0x0C, 0x44 };
++
++	zl10353_write(fe, zl10353_softdown, sizeof(zl10353_softdown));
++	return 0;
++}
++
++static int zl10353_set_parameters(struct dvb_frontend *fe,
++				  struct dvb_frontend_parameters *param)
++{
++	struct zl10353_state *state = fe->demodulator_priv;
++	u8 pllbuf[6] = { 0x67 };
++
++	/* These settings set "auto-everything" and start the FSM. */
++	zl10353_single_write(fe, 0x55, 0x80);
++	udelay(200);
++	zl10353_single_write(fe, 0xEA, 0x01);
++	udelay(200);
++	zl10353_single_write(fe, 0xEA, 0x00);
++
++	zl10353_single_write(fe, 0x56, 0x28);
++	zl10353_single_write(fe, 0x89, 0x20);
++	zl10353_single_write(fe, 0x5E, 0x00);
++	zl10353_single_write(fe, 0x65, 0x5A);
++	zl10353_single_write(fe, 0x66, 0xE9);
++	zl10353_single_write(fe, 0x62, 0x0A);
++
++	state->config.pll_set(fe, param, pllbuf + 1);
++	zl10353_write(fe, pllbuf, sizeof(pllbuf));
++
++	zl10353_single_write(fe, 0x70, 0x01);
++	udelay(250);
++	zl10353_single_write(fe, 0xE4, 0x00);
++	zl10353_single_write(fe, 0xE5, 0x2A);
++	zl10353_single_write(fe, 0xE9, 0x02);
++	zl10353_single_write(fe, 0xE7, 0x40);
++	zl10353_single_write(fe, 0xE8, 0x10);
++
++	return 0;
++}
++
++static int zl10353_read_status(struct dvb_frontend *fe, fe_status_t *status)
++{
++	struct zl10353_state *state = fe->demodulator_priv;
++	int s6, s7, s8;
++
++	if ((s6 = zl10353_read_register(state, STATUS_6)) < 0)
++		return -EREMOTEIO;
++	if ((s7 = zl10353_read_register(state, STATUS_7)) < 0)
++		return -EREMOTEIO;
++	if ((s8 = zl10353_read_register(state, STATUS_8)) < 0)
++		return -EREMOTEIO;
++
++	*status = 0;
++	if (s6 & (1 << 2))
++		*status |= FE_HAS_CARRIER;
++	if (s6 & (1 << 1))
++		*status |= FE_HAS_VITERBI;
++	if (s6 & (1 << 5))
++		*status |= FE_HAS_LOCK;
++	if (s7 & (1 << 4))
++		*status |= FE_HAS_SYNC;
++	if (s8 & (1 << 6))
++		*status |= FE_HAS_SIGNAL;
++
++	if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) !=
++	    (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC))
++		*status &= ~FE_HAS_LOCK;
++
++	return 0;
++}
++
++static int zl10353_read_snr(struct dvb_frontend *fe, u16 *snr)
++{
++	struct zl10353_state *state = fe->demodulator_priv;
++	u8 _snr;
++
++	if (debug_regs)
++		zl10353_dump_regs(fe);
++
++	_snr = zl10353_read_register(state, SNR);
++	*snr = (_snr << 8) | _snr;
++
++	return 0;
++}
++
++static int zl10353_get_tune_settings(struct dvb_frontend *fe,
++				     struct dvb_frontend_tune_settings
++					 *fe_tune_settings)
++{
++	fe_tune_settings->min_delay_ms = 1000;
++	fe_tune_settings->step_size = 0;
++	fe_tune_settings->max_drift = 0;
++
++	return 0;
++}
++
++static int zl10353_init(struct dvb_frontend *fe)
++{
++	struct zl10353_state *state = fe->demodulator_priv;
++	u8 zl10353_reset_attach[6] = { 0x50, 0x03, 0x64, 0x46, 0x15, 0x0F };
++	int rc = 0;
++
++	if (debug_regs)
++		zl10353_dump_regs(fe);
++
++	/* Do a "hard" reset if not already done */
++	if (zl10353_read_register(state, 0x50) != 0x03) {
++		rc = zl10353_write(fe, zl10353_reset_attach,
++				   sizeof(zl10353_reset_attach));
++		if (debug_regs)
++			zl10353_dump_regs(fe);
++	}
++
++	return 0;
++}
++
++static void zl10353_release(struct dvb_frontend *fe)
++{
++	struct zl10353_state *state = fe->demodulator_priv;
++
++	kfree(state);
++}
++
++static struct dvb_frontend_ops zl10353_ops;
++
++struct dvb_frontend *zl10353_attach(const struct zl10353_config *config,
++				    struct i2c_adapter *i2c)
++{
++	struct zl10353_state *state = NULL;
++
++	/* allocate memory for the internal state */
++	state = kzalloc(sizeof(struct zl10353_state), GFP_KERNEL);
++	if (state == NULL)
++		goto error;
++
++	/* setup the state */
++	state->i2c = i2c;
++	memcpy(&state->config, config, sizeof(struct zl10353_config));
++	memcpy(&state->ops, &zl10353_ops, sizeof(struct dvb_frontend_ops));
++
++	/* check if the demod is there */
++	if (zl10353_read_register(state, CHIP_ID) != ID_ZL10353)
++		goto error;
++
++	/* create dvb_frontend */
++	state->frontend.ops = &state->ops;
++	state->frontend.demodulator_priv = state;
++
++	return &state->frontend;
++error:
++	kfree(state);
++	return NULL;
++}
++
++static struct dvb_frontend_ops zl10353_ops = {
++
++	.info = {
++		.name			= "Zarlink ZL10353 DVB-T",
++		.type			= FE_OFDM,
++		.frequency_min		= 174000000,
++		.frequency_max		= 862000000,
++		.frequency_stepsize	= 166667,
++		.frequency_tolerance	= 0,
++		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
++			FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
++			FE_CAN_FEC_AUTO |
++			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
++			FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
++			FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER |
++			FE_CAN_MUTE_TS
++	},
++
++	.release = zl10353_release,
++
++	.init = zl10353_init,
++	.sleep = zl10353_sleep,
++
++	.set_frontend = zl10353_set_parameters,
++	.get_tune_settings = zl10353_get_tune_settings,
++
++	.read_status = zl10353_read_status,
++	.read_snr = zl10353_read_snr,
++};
++
++module_param(debug_regs, int, 0644);
++MODULE_PARM_DESC(debug_regs, "Turn on/off frontend register dumps (default:off).");
++
++MODULE_DESCRIPTION("Zarlink ZL10353 DVB-T demodulator driver");
++MODULE_AUTHOR("Chris Pascoe");
++MODULE_LICENSE("GPL");
++
++EXPORT_SYMBOL(zl10353_attach);
++EXPORT_SYMBOL(zl10353_write);
+diff --git a/drivers/media/dvb/frontends/zl10353.h b/drivers/media/dvb/frontends/zl10353.h
+new file mode 100644
+index 000000000000..5cc4ae718d8c
+--- /dev/null
++++ b/drivers/media/dvb/frontends/zl10353.h
+@@ -0,0 +1,43 @@
++/*
++ *  Driver for Zarlink DVB-T ZL10353 demodulator
++ *
++ *  Copyright (C) 2006 Christopher Pascoe 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
++ */
++
++#ifndef ZL10353_H
++#define ZL10353_H
++
++#include 
++
++struct zl10353_config
++{
++	/* demodulator's I2C address */
++	u8 demod_address;
++
++	/* function which configures the PLL buffer (for secondary I2C
++	 * connected tuner) or tunes the PLL (for direct connected tuner) */
++	int (*pll_set)(struct dvb_frontend *fe,
++		       struct dvb_frontend_parameters *params, u8 *pllbuf);
++};
++
++extern struct dvb_frontend* zl10353_attach(const struct zl10353_config *config,
++					   struct i2c_adapter *i2c);
++
++extern int zl10353_write(struct dvb_frontend *fe, u8 *ibuf, int ilen);
++
++#endif /* ZL10353_H */
+diff --git a/drivers/media/dvb/frontends/zl10353_priv.h b/drivers/media/dvb/frontends/zl10353_priv.h
+new file mode 100644
+index 000000000000..b72224bd7dde
+--- /dev/null
++++ b/drivers/media/dvb/frontends/zl10353_priv.h
+@@ -0,0 +1,42 @@
++/*
++ *  Driver for Zarlink DVB-T ZL10353 demodulator
++ *
++ *  Copyright (C) 2006 Christopher Pascoe 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
++ */
++
++#ifndef _ZL10353_PRIV_
++#define _ZL10353_PRIV_
++
++#define ID_ZL10353	0x14
++
++enum zl10353_reg_addr {
++	INTERRUPT_0	= 0x00,
++	INTERRUPT_1	= 0x01,
++	INTERRUPT_2	= 0x02,
++	INTERRUPT_3	= 0x03,
++	INTERRUPT_4	= 0x04,
++	INTERRUPT_5	= 0x05,
++	STATUS_6	= 0x06,
++	STATUS_7	= 0x07,
++	STATUS_8	= 0x08,
++	STATUS_9	= 0x09,
++	SNR		= 0x10,
++	CHIP_ID		= 0x7F,
++};
++
++#endif                          /* _ZL10353_PRIV_ */
+diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile
+index 2b902784facc..6482b9aa6a1f 100644
+--- a/drivers/media/video/cx88/Makefile
++++ b/drivers/media/video/cx88/Makefile
+@@ -17,6 +17,7 @@ extra-cflags-$(CONFIG_DVB_CX22702)   += -DHAVE_CX22702=1
+ extra-cflags-$(CONFIG_DVB_OR51132)   += -DHAVE_OR51132=1
+ extra-cflags-$(CONFIG_DVB_LGDT330X)  += -DHAVE_LGDT330X=1
+ extra-cflags-$(CONFIG_DVB_MT352)     += -DHAVE_MT352=1
++extra-cflags-$(CONFIG_DVB_ZL10353)   += -DHAVE_ZL10353=1
+ extra-cflags-$(CONFIG_DVB_NXT200X)   += -DHAVE_NXT200X=1
+ extra-cflags-$(CONFIG_DVB_CX24123)   += -DHAVE_CX24123=1
+ extra-cflags-$(CONFIG_VIDEO_CX88_VP3054)+= -DHAVE_VP3054_I2C=1
+diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
+index 44e27dc646ae..d91e5b3a64ef 100644
+--- a/drivers/media/video/cx88/cx88-cards.c
++++ b/drivers/media/video/cx88/cx88-cards.c
+@@ -1071,6 +1071,27 @@ struct cx88_board cx88_boards[] = {
+ 			.gpio2  = 0x00ff,
+ 		},
+ 	},
++	[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID] = {
++		.name           = "DViCO FusionHDTV DVB-T Hybrid",
++		.tuner_type     = TUNER_FE6600,
++		.radio_type     = UNSET,
++		.tuner_addr	= ADDR_UNSET,
++		.radio_addr	= ADDR_UNSET,
++		.input          = {{
++			.type   = CX88_VMUX_TELEVISION,
++			.vmux   = 0,
++			.gpio0  = 0x0000a75f,
++		},{
++			.type   = CX88_VMUX_COMPOSITE1,
++			.vmux   = 1,
++			.gpio0  = 0x0000a75b,
++		},{
++			.type   = CX88_VMUX_SVIDEO,
++			.vmux   = 2,
++			.gpio0  = 0x0000a75b,
++		}},
++		.dvb            = 1,
++	},
+ 
+ };
+ const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
+@@ -1281,6 +1302,14 @@ struct cx88_subid cx88_subids[] = {
+ 		.subvendor = 0x17de,
+ 		.subdevice = 0x0840,
+ 		.card      = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT,
++	},{
++		.subvendor = 0x18ac,
++		.subdevice = 0xdb40,
++		.card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID,
++	},{
++		.subvendor = 0x18ac,
++		.subdevice = 0xdb44,
++		.card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID,
+ 	},
+ };
+ const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids);
+@@ -1399,6 +1428,40 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data)
+ 	core->has_radio  = gdi_tuner[eeprom_data[0x0d]].fm;
+ }
+ 
++/* ----------------------------------------------------------------------- */
++/* some DViCO specific stuff                                               */
++
++static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core)
++{
++	struct i2c_msg msg = { .addr = 0x45, .flags = 0 };
++	int i, err;
++	u8 init_bufs[13][5] = {
++		{ 0x10, 0x00, 0x20, 0x01, 0x03 },
++		{ 0x10, 0x10, 0x01, 0x00, 0x21 },
++		{ 0x10, 0x10, 0x10, 0x00, 0xCA },
++		{ 0x10, 0x10, 0x12, 0x00, 0x08 },
++		{ 0x10, 0x10, 0x13, 0x00, 0x0A },
++		{ 0x10, 0x10, 0x16, 0x01, 0xC0 },
++		{ 0x10, 0x10, 0x22, 0x01, 0x3D },
++		{ 0x10, 0x10, 0x73, 0x01, 0x2E },
++		{ 0x10, 0x10, 0x72, 0x00, 0xC5 },
++		{ 0x10, 0x10, 0x71, 0x01, 0x97 },
++		{ 0x10, 0x10, 0x70, 0x00, 0x0F },
++		{ 0x10, 0x10, 0xB0, 0x00, 0x01 },
++		{ 0x03, 0x0C },
++	};
++
++	for (i = 0; i < 13; i++) {
++		msg.buf = init_bufs[i];
++		msg.len = (i != 12 ? 5 : 2);
++		err = i2c_transfer(&core->i2c_adap, &msg, 1);
++		if (err != 1) {
++			printk("dvico_fusionhdtv_hybrid_init buf %d failed (err = %d)!\n", i, err);
++			return;
++		}
++	}
++}
++
+ /* ----------------------------------------------------------------------- */
+ 
+ void cx88_card_list(struct cx88_core *core, struct pci_dev *pci)
+@@ -1465,11 +1528,15 @@ void cx88_card_setup(struct cx88_core *core)
+ 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
+ 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
+ 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
++	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
+ 		/* GPIO0:0 is hooked to mt352 reset pin */
+ 		cx_set(MO_GP0_IO, 0x00000101);
+ 		cx_clear(MO_GP0_IO, 0x00000001);
+ 		msleep(1);
+ 		cx_set(MO_GP0_IO, 0x00000101);
++		if (0 == core->i2c_rc &&
++		    core->board == CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID)
++			dvico_fusionhdtv_hybrid_init(core);
+ 		break;
+ 	case CX88_BOARD_KWORLD_DVB_T:
+ 	case CX88_BOARD_DNTV_LIVE_DVB_T:
+diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
+index e48aa3f6e500..2c97d3f7101a 100644
+--- a/drivers/media/video/cx88/cx88-dvb.c
++++ b/drivers/media/video/cx88/cx88-dvb.c
+@@ -40,6 +40,9 @@
+ #  include "cx88-vp3054-i2c.h"
+ # endif
+ #endif
++#ifdef HAVE_ZL10353
++# include "zl10353.h"
++#endif
+ #ifdef HAVE_CX22702
+ # include "cx22702.h"
+ #endif
+@@ -111,6 +114,21 @@ static struct videobuf_queue_ops dvb_qops = {
+ 
+ /* ------------------------------------------------------------------ */
+ 
++#if defined(HAVE_MT352) || defined(HAVE_ZL10353)
++static int zarlink_pll_set(struct dvb_frontend *fe,
++			      struct dvb_frontend_parameters *params,
++			      u8 *pllbuf)
++{
++	struct cx8802_dev *dev = fe->dvb->priv;
++
++	pllbuf[0] = dev->core->pll_addr << 1;
++	dvb_pll_configure(dev->core->pll_desc, pllbuf + 1,
++			  params->frequency,
++			  params->u.ofdm.bandwidth);
++	return 0;
++}
++#endif
++
+ #ifdef HAVE_MT352
+ static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe)
+ {
+@@ -176,35 +194,22 @@ static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe)
+ 	return 0;
+ }
+ 
+-static int mt352_pll_set(struct dvb_frontend* fe,
+-			 struct dvb_frontend_parameters* params,
+-			 u8* pllbuf)
+-{
+-	struct cx8802_dev *dev= fe->dvb->priv;
+-
+-	pllbuf[0] = dev->core->pll_addr << 1;
+-	dvb_pll_configure(dev->core->pll_desc, pllbuf+1,
+-			  params->frequency,
+-			  params->u.ofdm.bandwidth);
+-	return 0;
+-}
+-
+ static struct mt352_config dvico_fusionhdtv = {
+ 	.demod_address = 0x0F,
+ 	.demod_init    = dvico_fusionhdtv_demod_init,
+-	.pll_set       = mt352_pll_set,
++	.pll_set       = zarlink_pll_set,
+ };
+ 
+ static struct mt352_config dntv_live_dvbt_config = {
+ 	.demod_address = 0x0f,
+ 	.demod_init    = dntv_live_dvbt_demod_init,
+-	.pll_set       = mt352_pll_set,
++	.pll_set       = zarlink_pll_set,
+ };
+ 
+ static struct mt352_config dvico_fusionhdtv_dual = {
+ 	.demod_address = 0x0F,
+ 	.demod_init    = dvico_dual_demod_init,
+-	.pll_set       = mt352_pll_set,
++	.pll_set       = zarlink_pll_set,
+ };
+ 
+ #ifdef HAVE_VP3054_I2C
+@@ -294,6 +299,46 @@ static struct mt352_config dntv_live_dvbt_pro_config = {
+ #endif
+ #endif
+ 
++#ifdef HAVE_ZL10353
++static int dvico_hybrid_tune_pll(struct dvb_frontend *fe,
++				 struct dvb_frontend_parameters *params,
++				 u8 *pllbuf)
++{
++	struct cx8802_dev *dev= fe->dvb->priv;
++	struct i2c_msg msg =
++		{ .addr = dev->core->pll_addr, .flags = 0,
++		  .buf = pllbuf + 1, .len = 4 };
++	int err;
++
++	pllbuf[0] = dev->core->pll_addr << 1;
++	dvb_pll_configure(dev->core->pll_desc, pllbuf + 1,
++			  params->frequency,
++			  params->u.ofdm.bandwidth);
++
++	if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
++		printk(KERN_WARNING "cx88-dvb: %s error "
++			   "(addr %02x <- %02x, err = %i)\n",
++			   __FUNCTION__, pllbuf[0], pllbuf[1], err);
++		if (err < 0)
++			return err;
++		else
++			return -EREMOTEIO;
++	}
++
++	return 0;
++}
++
++static struct zl10353_config dvico_fusionhdtv_hybrid = {
++	.demod_address = 0x0F,
++	.pll_set       = dvico_hybrid_tune_pll,
++};
++
++static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = {
++	.demod_address = 0x0F,
++	.pll_set       = zarlink_pll_set,
++};
++#endif
++
+ #ifdef HAVE_CX22702
+ static struct cx22702_config connexant_refboard_config = {
+ 	.demod_address = 0x43,
+@@ -500,16 +545,27 @@ static int dvb_register(struct cx8802_dev *dev)
+ 						   &dev->core->i2c_adap);
+ 		break;
+ #endif
++#if defined(HAVE_MT352) || defined(HAVE_ZL10353)
++	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
++		dev->core->pll_addr = 0x60;
++		dev->core->pll_desc = &dvb_pll_thomson_dtt7579;
+ #ifdef HAVE_MT352
+-	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
+-		dev->core->pll_addr = 0x61;
+-		dev->core->pll_desc = &dvb_pll_lg_z201;
+ 		dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv,
+ 						 &dev->core->i2c_adap);
++		if (dev->dvb.frontend != NULL)
++			break;
++#endif
++#ifdef HAVE_ZL10353
++		/* ZL10353 replaces MT352 on later cards */
++		dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_plus_v1_1,
++						   &dev->core->i2c_adap);
++#endif
+ 		break;
+-	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
+-		dev->core->pll_addr = 0x60;
+-		dev->core->pll_desc = &dvb_pll_thomson_dtt7579;
++#endif /* HAVE_MT352 || HAVE_ZL10353 */
++#ifdef HAVE_MT352
++	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
++		dev->core->pll_addr = 0x61;
++		dev->core->pll_desc = &dvb_pll_lg_z201;
+ 		dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv,
+ 						 &dev->core->i2c_adap);
+ 		break;
+@@ -540,6 +596,14 @@ static int dvb_register(struct cx8802_dev *dev)
+ 						 &dev->core->i2c_adap);
+ 		break;
+ #endif
++#ifdef HAVE_ZL10353
++	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
++		dev->core->pll_addr = 0x61;
++		dev->core->pll_desc = &dvb_pll_unknown_fe6600;
++		dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_hybrid,
++						   &dev->core->i2c_adap);
++		break;
++#endif
+ #ifdef HAVE_OR51132
+ 	case CX88_BOARD_PCHDTV_HD3000:
+ 		dev->dvb.frontend = or51132_attach(&pchdtv_hd3000,
+diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
+index a4cf2473eacf..21738b664bc9 100644
+--- a/drivers/media/video/cx88/cx88.h
++++ b/drivers/media/video/cx88/cx88.h
+@@ -189,6 +189,7 @@ extern struct sram_channel cx88_sram_channels[];
+ #define CX88_BOARD_KWORLD_DVB_T_CX22702    43
+ #define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL 44
+ #define CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT 45
++#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID 46
+ 
+ enum cx88_itype {
+ 	CX88_VMUX_COMPOSITE1 = 1,
+diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c
+index 15761dd8607d..d10cfd400f2b 100644
+--- a/drivers/media/video/tuner-types.c
++++ b/drivers/media/video/tuner-types.c
+@@ -983,6 +983,22 @@ static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = {
+ 	},
+ };
+ 
++/* ------------ TUNER_FE6600 - DViCO Hybrid PAL ------------ */
++
++static struct tuner_range tuner_fe6600_ranges[] = {
++	{ 16 * 160.00 /*MHz*/, 0xfe, 0x11, },
++	{ 16 * 442.00 /*MHz*/, 0xf6, 0x12, },
++	{ 16 * 999.99        , 0xf6, 0x18, },
++};
++
++static struct tuner_params tuner_fe6600_params[] = {
++	{
++		.type   = TUNER_PARAM_TYPE_PAL,
++		.ranges = tuner_fe6600_ranges,
++		.count  = ARRAY_SIZE(tuner_fe6600_ranges),
++	},
++};
++
+ /* --------------------------------------------------------------------- */
+ 
+ struct tunertype tuners[] = {
+@@ -1354,6 +1370,10 @@ struct tunertype tuners[] = {
+ 		.name	= "Xceive xc3028",
+ 		/* see xc3028.c for details */
+ 	},
++	[TUNER_FE6600] = { /* */
++		.name   = "FE6600",
++		.params = tuner_fe6600_params,
++	},
+ };
+ 
+ unsigned const int tuner_count = ARRAY_SIZE(tuners);
+diff --git a/include/media/tuner.h b/include/media/tuner.h
+index f51759c0d180..039c77e02d34 100644
+--- a/include/media/tuner.h
++++ b/include/media/tuner.h
+@@ -116,9 +116,10 @@
+ #define TUNER_PHILIPS_TUV1236D		68	/* ATI HDTV Wonder */
+ #define TUNER_TNF_5335MF                69	/* Sabrent Bt848   */
+ #define TUNER_SAMSUNG_TCPN_2121P30A     70 	/* Hauppauge PVR-500MCE NTSC */
+-
+ #define TUNER_XCEIVE_XC3028		71
+ 
++#define TUNER_FE6600			72	/* DViCO FusionHDTV DVB-T Hybrid */
++
+ /* tv card specific */
+ #define TDA9887_PRESENT 		(1<<0)
+ #define TDA9887_PORT1_INACTIVE 		(1<<1)

commit 4055d392aa0256462758b40cedb9eb7d564de93a
+Author: Chris Pascoe 
+Date:   Tue Feb 7 06:49:11 2006 -0200
+
+    V4L/DVB (3308): Use parallel transport for FusionHDTV Dual Digital USB
+    
+    Use the parallel transport function of the MT352 in USB demodulator of the
+    Dual Digital board.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Michael Krufky 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
+index f14003736afe..650536a4169c 100644
+--- a/drivers/media/dvb/dvb-usb/cxusb.c
++++ b/drivers/media/dvb/dvb-usb/cxusb.c
+@@ -234,7 +234,7 @@ static struct dvb_usb_rc_key dvico_mce_rc_keys[] = {
+ 
+ static int cxusb_dee1601_demod_init(struct dvb_frontend* fe)
+ {
+-	static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x38 };
++	static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x28 };
+ 	static u8 reset []         = { RESET,      0x80 };
+ 	static u8 adc_ctl_1_cfg [] = { ADC_CTL_1,  0x40 };
+ 	static u8 agc_cfg []       = { AGC_TARGET, 0x28, 0x20 };

commit d9ed881c66525ac0d95fbf76a46187a5de43be2d
+Author: Chris Pascoe 
+Date:   Tue Feb 7 06:49:11 2006 -0200
+
+    V4L/DVB (3308): Use parallel transport for FusionHDTV Dual Digital USB
+    
+    Use the parallel transport function of the MT352 in USB demodulator of the
+    Dual Digital board.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Michael Krufky 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
+index f14003736afe..650536a4169c 100644
+--- a/drivers/media/dvb/dvb-usb/cxusb.c
++++ b/drivers/media/dvb/dvb-usb/cxusb.c
+@@ -234,7 +234,7 @@ static struct dvb_usb_rc_key dvico_mce_rc_keys[] = {
+ 
+ static int cxusb_dee1601_demod_init(struct dvb_frontend* fe)
+ {
+-	static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x38 };
++	static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x28 };
+ 	static u8 reset []         = { RESET,      0x80 };
+ 	static u8 adc_ctl_1_cfg [] = { ADC_CTL_1,  0x40 };
+ 	static u8 agc_cfg []       = { AGC_TARGET, 0x28, 0x20 };

commit 30367bfda384ccb96c0fe35aaa001c7624e9fd01
+Author: Chris Pascoe 
+Date:   Wed Jan 11 19:40:01 2006 -0200
+
+    V4L/DVB (3339): Activate remote control on HVR1100
+    
+    
+    - Add a missing case which was preventing the operation of the HVR1100
+    remote.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
+index 286c85b6bdf9..da2ad5c4b553 100644
+--- a/drivers/media/video/cx88/cx88-input.c
++++ b/drivers/media/video/cx88/cx88-input.c
+@@ -697,6 +697,7 @@ void cx88_ir_irq(struct cx88_core *core)
+ 	case CX88_BOARD_HAUPPAUGE_DVB_T1:
+ 	case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
+ 	case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
++	case CX88_BOARD_HAUPPAUGE_HVR1100:
+ 		ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
+ 		ir_dprintk("biphase decoded: %x\n", ircode);
+ 		if ((ircode & 0xfffff000) != 0x3000)

commit b9f4ad57f70b8a29851b4f4247294f4aba6ae815
+Author: Chris Pascoe 
+Date:   Mon Jan 9 18:21:39 2006 -0200
+
+    V4L/DVB (3329): cx88_subids whitespace cleanup
+    
+    - Clean up a recently introduced spaces vs tabs whitespace problem.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
+index a5b939622f82..a76d54503b6f 100644
+--- a/drivers/media/video/cx88/cx88-cards.c
++++ b/drivers/media/video/cx88/cx88-cards.c
+@@ -1237,14 +1237,14 @@ struct cx88_subid cx88_subids[] = {
+ 		.subdevice = 0x0025,
+ 		.card      = CX88_BOARD_DNTV_LIVE_DVB_T_PRO,
+ 	},{
+-	       .subvendor = 0x17de,
+-	       .subdevice = 0x08a1,
+-	       .card      = CX88_BOARD_KWORLD_DVB_T_CX22702,
++		.subvendor = 0x17de,
++		.subdevice = 0x08a1,
++		.card      = CX88_BOARD_KWORLD_DVB_T_CX22702,
+ 	},{
+ 		.subvendor = 0x18ac,
+ 		.subdevice = 0xdb50,
+ 		.card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL,
+-       }
++	},
+ };
+ const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids);
+ 

commit 3d7d027a9bf41437aa93baf14a1aada521ad9b12
+Author: Chris Pascoe 
+Date:   Mon Jan 9 18:21:31 2006 -0200
+
+    V4L/DVB (3315): Use correct AGC settings for DNTV Live! DVB-T Pro
+    
+    - My original settings for this board were incorrect and resulted in
+    an increased number of signal dropouts.  Replace this with the settings
+    from the Windows driver.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
+index 8a5997bf4ccd..42c012aaa849 100644
+--- a/drivers/media/video/cx88/cx88-dvb.c
++++ b/drivers/media/video/cx88/cx88-dvb.c
+@@ -112,7 +112,7 @@ static struct videobuf_queue_ops dvb_qops = {
+ /* ------------------------------------------------------------------ */
+ 
+ #ifdef HAVE_MT352
+-static int generic_mt352_demod_init(struct dvb_frontend* fe)
++static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe)
+ {
+ 	static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x39 };
+ 	static u8 reset []         = { RESET,      0x80 };
+@@ -191,7 +191,7 @@ static int mt352_pll_set(struct dvb_frontend* fe,
+ 
+ static struct mt352_config dvico_fusionhdtv = {
+ 	.demod_address = 0x0F,
+-	.demod_init    = generic_mt352_demod_init,
++	.demod_init    = dvico_fusionhdtv_demod_init,
+ 	.pll_set       = mt352_pll_set,
+ };
+ 
+@@ -208,6 +208,29 @@ static struct mt352_config dvico_fusionhdtv_dual = {
+ };
+ 
+ #ifdef HAVE_VP3054_I2C
++static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe)
++{
++	static u8 clock_config []  = { 0x89, 0x38, 0x38 };
++	static u8 reset []         = { 0x50, 0x80 };
++	static u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 };
++	static u8 agc_cfg []       = { 0x67, 0x10, 0x20, 0x00, 0xFF, 0xFF,
++				       0x00, 0xFF, 0x00, 0x40, 0x40 };
++	static u8 dntv_extra[]     = { 0xB5, 0x7A };
++	static u8 capt_range_cfg[] = { 0x75, 0x32 };
++
++	mt352_write(fe, clock_config,   sizeof(clock_config));
++	udelay(2000);
++	mt352_write(fe, reset,          sizeof(reset));
++	mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
++
++	mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
++	udelay(2000);
++	mt352_write(fe, dntv_extra,     sizeof(dntv_extra));
++	mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
++
++	return 0;
++}
++
+ static int philips_fmd1216_pll_init(struct dvb_frontend *fe)
+ {
+ 	struct cx8802_dev *dev= fe->dvb->priv;
+@@ -265,7 +288,7 @@ static int dntv_live_dvbt_pro_pll_set(struct dvb_frontend* fe,
+ static struct mt352_config dntv_live_dvbt_pro_config = {
+ 	.demod_address = 0x0f,
+ 	.no_tuner      = 1,
+-	.demod_init    = generic_mt352_demod_init,
++	.demod_init    = dntv_live_dvbt_pro_demod_init,
+ 	.pll_set       = dntv_live_dvbt_pro_pll_set,
+ };
+ #endif

commit 7c239703a942117c3446ca06af537fc3ea12fb24
+Author: Chris Pascoe 
+Date:   Mon Jan 9 18:21:29 2006 -0200
+
+    V4L/DVB (3312): DViCO USB IR Remote support
+    
+    - Add support for the remote control receiver inside the DViCO FusionHDTV
+    DVB-T Dual Digital, and a keymap for the MCE remote bundled with it.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
+index 9622a79d6e68..163b69405b95 100644
+--- a/drivers/media/dvb/dvb-usb/cxusb.c
++++ b/drivers/media/dvb/dvb-usb/cxusb.c
+@@ -15,6 +15,7 @@
+  * part
+  *
+  * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de)
++ * Copyright (C) 2006 Chris Pascoe (c.pascoe@itee.uq.edu.au)
+  *
+  *	This program is free software; you can redistribute it and/or modify it
+  *	under the terms of the GNU General Public License as published by the Free
+@@ -159,6 +160,30 @@ static int cxusb_streaming_ctrl(struct dvb_usb_device *d, int onoff)
+ 	return 0;
+ }
+ 
++static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
++{
++	struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
++	u8 irCode[4];
++	int i;
++
++	cxusb_ctrl_msg(d, CMD_GET_IR_CODE, NULL, 0, irCode, 4);
++
++	*event = 0;
++	*state = REMOTE_NO_KEY_PRESSED;
++
++	for (i = 0; i < d->props.rc_key_map_size; i++) {
++		if (keymap[i].custom == irCode[2] &&
++		    keymap[i].data == irCode[3]) {
++			*event = keymap[i].event;
++			*state = REMOTE_KEY_PRESSED;
++
++			return 0;
++		}
++	}
++
++	return 0;
++}
++
+ static int cxusb_dee1601_demod_init(struct dvb_frontend* fe)
+ {
+ 	static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x38 };
+@@ -372,6 +397,54 @@ static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties = {
+ 	}
+ };
+ 
++struct dvb_usb_rc_key dvico_mce_rc_keys[] = {
++	{ 0xfe, 0x02, KEY_TV },
++	{ 0xfe, 0x0e, KEY_MP3 },
++	{ 0xfe, 0x1a, KEY_DVD },
++	{ 0xfe, 0x1e, KEY_FAVORITES },
++	{ 0xfe, 0x16, KEY_SETUP },
++	{ 0xfe, 0x46, KEY_POWER2 },
++	{ 0xfe, 0x0a, KEY_EPG },
++	{ 0xfe, 0x49, KEY_BACK },
++	{ 0xfe, 0x4d, KEY_MENU },
++	{ 0xfe, 0x51, KEY_UP },
++	{ 0xfe, 0x5b, KEY_LEFT },
++	{ 0xfe, 0x5f, KEY_RIGHT },
++	{ 0xfe, 0x53, KEY_DOWN },
++	{ 0xfe, 0x5e, KEY_OK },
++	{ 0xfe, 0x59, KEY_INFO },
++	{ 0xfe, 0x55, KEY_TAB },
++	{ 0xfe, 0x0f, KEY_PREVIOUSSONG },/* Replay */
++	{ 0xfe, 0x12, KEY_NEXTSONG },	/* Skip */
++	{ 0xfe, 0x42, KEY_ENTER	 },	/* Windows/Start */
++	{ 0xfe, 0x15, KEY_VOLUMEUP },
++	{ 0xfe, 0x05, KEY_VOLUMEDOWN },
++	{ 0xfe, 0x11, KEY_CHANNELUP },
++	{ 0xfe, 0x09, KEY_CHANNELDOWN },
++	{ 0xfe, 0x52, KEY_CAMERA },
++	{ 0xfe, 0x5a, KEY_TUNER },	/* Live */
++	{ 0xfe, 0x19, KEY_OPEN },
++	{ 0xfe, 0x0b, KEY_1 },
++	{ 0xfe, 0x17, KEY_2 },
++	{ 0xfe, 0x1b, KEY_3 },
++	{ 0xfe, 0x07, KEY_4 },
++	{ 0xfe, 0x50, KEY_5 },
++	{ 0xfe, 0x54, KEY_6 },
++	{ 0xfe, 0x48, KEY_7 },
++	{ 0xfe, 0x4c, KEY_8 },
++	{ 0xfe, 0x58, KEY_9 },
++	{ 0xfe, 0x13, KEY_ANGLE },	/* Aspect */
++	{ 0xfe, 0x03, KEY_0 },
++	{ 0xfe, 0x1f, KEY_ZOOM },
++	{ 0xfe, 0x43, KEY_REWIND },
++	{ 0xfe, 0x47, KEY_PLAYPAUSE },
++	{ 0xfe, 0x4f, KEY_FASTFORWARD },
++	{ 0xfe, 0x57, KEY_MUTE },
++	{ 0xfe, 0x0d, KEY_STOP },
++	{ 0xfe, 0x01, KEY_RECORD },
++	{ 0xfe, 0x4e, KEY_POWER },
++};
++
+ static struct dvb_usb_properties cxusb_bluebird_dee1601_properties = {
+ 	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
+ 
+@@ -389,6 +462,11 @@ static struct dvb_usb_properties cxusb_bluebird_dee1601_properties = {
+ 
+ 	.i2c_algo         = &cxusb_i2c_algo,
+ 
++	.rc_interval      = 150,
++	.rc_key_map       = dvico_mce_rc_keys,
++	.rc_key_map_size  = ARRAY_SIZE(dvico_mce_rc_keys),
++	.rc_query         = cxusb_rc_query,
++
+ 	.generic_bulk_ctrl_endpoint = 0x01,
+ 	/* parameter for the MPEG2-data transfer */
+ 	.urb = {
+diff --git a/drivers/media/dvb/dvb-usb/cxusb.h b/drivers/media/dvb/dvb-usb/cxusb.h
+index 135c2a81f581..087c99427853 100644
+--- a/drivers/media/dvb/dvb-usb/cxusb.h
++++ b/drivers/media/dvb/dvb-usb/cxusb.h
+@@ -21,6 +21,8 @@ extern int dvb_usb_cxusb_debug;
+ #define CMD_STREAMING_ON  0x36
+ #define CMD_STREAMING_OFF 0x37
+ 
++#define CMD_GET_IR_CODE   0x47
++
+ #define CMD_ANALOG        0x50
+ #define CMD_DIGITAL       0x51
+ 

commit 43eabb4e2284146f8bfae8730ae41c218b724b7d
+Author: Chris Pascoe 
+Date:   Mon Jan 9 18:21:28 2006 -0200
+
+    V4L/DVB (3311): DViCO FusionHDTV DVB-T Dual Digital PCI support
+    
+    - Support for DVB reception on the PCI half of the DViCO DVB-T Dual Digital.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88
+index 3d02b1f27d28..34b6e59f2968 100644
+--- a/Documentation/video4linux/CARDLIST.cx88
++++ b/Documentation/video4linux/CARDLIST.cx88
+@@ -42,3 +42,4 @@
+  41 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile)  [0070:9800,0070:9802]
+  42 -> digitalnow DNTV Live! DVB-T Pro                     [1822:0025]
+  43 -> KWorld/VStream XPert DVB-T with cx22702             [17de:08a1]
++ 44 -> DViCO FusionHDTV DVB-T Dual Digital                 [18ac:db50]
+diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
+index ae2fdf62c8ba..a5b939622f82 100644
+--- a/drivers/media/video/cx88/cx88-cards.c
++++ b/drivers/media/video/cx88/cx88-cards.c
+@@ -1031,6 +1031,23 @@ struct cx88_board cx88_boards[] = {
+ 		}},
+ 		.dvb            = 1,
+ 	},
++	[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL] = {
++		.name           = "DViCO FusionHDTV DVB-T Dual Digital",
++		.tuner_type     = TUNER_ABSENT, /* No analog tuner */
++		.radio_type     = UNSET,
++		.tuner_addr	= ADDR_UNSET,
++		.radio_addr	= ADDR_UNSET,
++		.input          = {{
++			.type   = CX88_VMUX_COMPOSITE1,
++			.vmux   = 1,
++			.gpio0  = 0x000027df,
++		 },{
++			.type   = CX88_VMUX_SVIDEO,
++			.vmux   = 2,
++			.gpio0  = 0x000027df,
++		}},
++		.dvb            = 1,
++	},
+ 
+ };
+ const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
+@@ -1223,6 +1240,10 @@ struct cx88_subid cx88_subids[] = {
+ 	       .subvendor = 0x17de,
+ 	       .subdevice = 0x08a1,
+ 	       .card      = CX88_BOARD_KWORLD_DVB_T_CX22702,
++	},{
++		.subvendor = 0x18ac,
++		.subdevice = 0xdb50,
++		.card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL,
+        }
+ };
+ const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids);
+@@ -1405,6 +1426,7 @@ void cx88_card_setup(struct cx88_core *core)
+ 		break;
+ 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
+ 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
++	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
+ 		/* GPIO0:0 is hooked to mt352 reset pin */
+ 		cx_set(MO_GP0_IO, 0x00000101);
+ 		cx_clear(MO_GP0_IO, 0x00000001);
+diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
+index dad8a0d564fb..8a5997bf4ccd 100644
+--- a/drivers/media/video/cx88/cx88-dvb.c
++++ b/drivers/media/video/cx88/cx88-dvb.c
+@@ -132,6 +132,27 @@ static int generic_mt352_demod_init(struct dvb_frontend* fe)
+ 	return 0;
+ }
+ 
++static int dvico_dual_demod_init(struct dvb_frontend *fe)
++{
++	static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x38 };
++	static u8 reset []         = { RESET,      0x80 };
++	static u8 adc_ctl_1_cfg [] = { ADC_CTL_1,  0x40 };
++	static u8 agc_cfg []       = { AGC_TARGET, 0x28, 0x20 };
++	static u8 gpp_ctl_cfg []   = { GPP_CTL,    0x33 };
++	static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
++
++	mt352_write(fe, clock_config,   sizeof(clock_config));
++	udelay(200);
++	mt352_write(fe, reset,          sizeof(reset));
++	mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
++
++	mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
++	mt352_write(fe, gpp_ctl_cfg,    sizeof(gpp_ctl_cfg));
++	mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
++
++	return 0;
++}
++
+ static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe)
+ {
+ 	static u8 clock_config []  = { 0x89, 0x38, 0x39 };
+@@ -180,6 +201,12 @@ static struct mt352_config dntv_live_dvbt_config = {
+ 	.pll_set       = mt352_pll_set,
+ };
+ 
++static struct mt352_config dvico_fusionhdtv_dual = {
++	.demod_address = 0x0F,
++	.demod_init    = dvico_dual_demod_init,
++	.pll_set       = mt352_pll_set,
++};
++
+ #ifdef HAVE_VP3054_I2C
+ static int philips_fmd1216_pll_init(struct dvb_frontend *fe)
+ {
+@@ -481,6 +508,14 @@ static int dvb_register(struct cx8802_dev *dev)
+ 		printk("%s: built without vp3054 support\n", dev->core->name);
+ #endif
+ 		break;
++	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
++		/* The tin box says DEE1601, but it seems to be DTT7579
++		 * compatible, with a slightly different MT352 AGC gain. */
++		dev->core->pll_addr = 0x61;
++		dev->core->pll_desc = &dvb_pll_thomson_dtt7579;
++		dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dual,
++						 &dev->core->i2c_adap);
++		break;
+ #endif
+ #ifdef HAVE_OR51132
+ 	case CX88_BOARD_PCHDTV_HD3000:
+diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
+index 120e5049a46f..e9fd55b57fa6 100644
+--- a/drivers/media/video/cx88/cx88.h
++++ b/drivers/media/video/cx88/cx88.h
+@@ -186,6 +186,7 @@ extern struct sram_channel cx88_sram_channels[];
+ #define CX88_BOARD_HAUPPAUGE_HVR1100LP     41
+ #define CX88_BOARD_DNTV_LIVE_DVB_T_PRO     42
+ #define CX88_BOARD_KWORLD_DVB_T_CX22702    43
++#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL 44
+ 
+ enum cx88_itype {
+ 	CX88_VMUX_COMPOSITE1 = 1,

commit 0029ee143d66ca89d0e8b074abb452cf4ca2c53c
+Author: Chris Pascoe 
+Date:   Mon Jan 9 18:21:28 2006 -0200
+
+    V4L/DVB (3310): DViCO Dual Digital DVB-T / USB bluebird updates
+    
+    - Add support for the USB portion of the DViCO Dual Digital board.
+    Patch correct "warm" USB IDs into bluebird firmware before download.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
+index 2c1b1e5992a3..9622a79d6e68 100644
+--- a/drivers/media/dvb/dvb-usb/cxusb.c
++++ b/drivers/media/dvb/dvb-usb/cxusb.c
+@@ -26,6 +26,8 @@
+ 
+ #include "cx22702.h"
+ #include "lgdt330x.h"
++#include "mt352.h"
++#include "mt352_priv.h"
+ 
+ /* debug */
+ int dvb_usb_cxusb_debug;
+@@ -157,6 +159,27 @@ static int cxusb_streaming_ctrl(struct dvb_usb_device *d, int onoff)
+ 	return 0;
+ }
+ 
++static int cxusb_dee1601_demod_init(struct dvb_frontend* fe)
++{
++	static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x38 };
++	static u8 reset []         = { RESET,      0x80 };
++	static u8 adc_ctl_1_cfg [] = { ADC_CTL_1,  0x40 };
++	static u8 agc_cfg []       = { AGC_TARGET, 0x28, 0x20 };
++	static u8 gpp_ctl_cfg []   = { GPP_CTL,    0x33 };
++	static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
++
++	mt352_write(fe, clock_config,   sizeof(clock_config));
++	udelay(200);
++	mt352_write(fe, reset,          sizeof(reset));
++	mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
++
++	mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
++	mt352_write(fe, gpp_ctl_cfg,    sizeof(gpp_ctl_cfg));
++	mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
++
++	return 0;
++}
++
+ struct cx22702_config cxusb_cx22702_config = {
+ 	.demod_address = 0x63,
+ 
+@@ -172,6 +195,12 @@ struct lgdt330x_config cxusb_lgdt330x_config = {
+ 	.pll_set       = dvb_usb_pll_set_i2c,
+ };
+ 
++struct mt352_config cxusb_dee1601_config = {
++	.demod_address = 0x0f,
++	.demod_init    = cxusb_dee1601_demod_init,
++	.pll_set       = dvb_usb_pll_set,
++};
++
+ /* Callbacks for DVB USB */
+ static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_device *d)
+ {
+@@ -193,6 +222,13 @@ static int cxusb_lgh064f_tuner_attach(struct dvb_usb_device *d)
+ 	return 0;
+ }
+ 
++static int cxusb_dee1601_tuner_attach(struct dvb_usb_device *d)
++{
++	d->pll_addr = 0x61;
++	d->pll_desc = &dvb_pll_thomson_dtt7579;
++	return 0;
++}
++
+ static int cxusb_cx22702_frontend_attach(struct dvb_usb_device *d)
+ {
+ 	u8 b;
+@@ -220,15 +256,31 @@ static int cxusb_lgdt330x_frontend_attach(struct dvb_usb_device *d)
+ 	return -EIO;
+ }
+ 
++static int cxusb_dee1601_frontend_attach(struct dvb_usb_device *d)
++{
++	if (usb_set_interface(d->udev,0,0) < 0)
++		err("set interface failed");
++
++	cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
++
++	if ((d->fe = mt352_attach(&cxusb_dee1601_config, &d->i2c_adap)) != NULL)
++		return 0;
++
++	return -EIO;
++}
++
+ /* DVB USB Driver stuff */
+ static struct dvb_usb_properties cxusb_medion_properties;
+ static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties;
++static struct dvb_usb_properties cxusb_bluebird_dee1601_properties;
+ 
+ static int cxusb_probe(struct usb_interface *intf,
+ 		const struct usb_device_id *id)
+ {
+ 	if (dvb_usb_device_init(intf,&cxusb_medion_properties,THIS_MODULE,NULL) == 0 ||
+-		dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0) {
++		dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 ||
++		dvb_usb_device_init(intf,&cxusb_bluebird_dee1601_properties,THIS_MODULE,NULL) == 0
++		){
+ 		return 0;
+ 	}
+ 
+@@ -239,6 +291,8 @@ static struct usb_device_id cxusb_table [] = {
+ 		{ USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) },
+ 		{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) },
+ 		{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_WARM) },
++		{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DEE1601_COLD) },
++		{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DEE1601_WARM) },
+ 		{}		/* Terminating entry */
+ };
+ MODULE_DEVICE_TABLE (usb, cxusb_table);
+@@ -318,6 +372,45 @@ static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties = {
+ 	}
+ };
+ 
++static struct dvb_usb_properties cxusb_bluebird_dee1601_properties = {
++	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
++
++	.usb_ctrl         = CYPRESS_FX2,
++	.firmware         = "dvb-usb-bluebird-01.fw",
++	/* use usb alt setting 0 for EP4 transfer (dvb-t),
++	   use usb alt setting 7 for EP2 transfer (atsc) */
++
++	.size_of_priv     = sizeof(struct cxusb_state),
++
++	.streaming_ctrl   = cxusb_streaming_ctrl,
++	.power_ctrl       = cxusb_power_ctrl,
++	.frontend_attach  = cxusb_dee1601_frontend_attach,
++	.tuner_attach     = cxusb_dee1601_tuner_attach,
++
++	.i2c_algo         = &cxusb_i2c_algo,
++
++	.generic_bulk_ctrl_endpoint = 0x01,
++	/* parameter for the MPEG2-data transfer */
++	.urb = {
++		.type = DVB_USB_BULK,
++		.count = 5,
++		.endpoint = 0x04,
++		.u = {
++			.bulk = {
++				.buffersize = 8192,
++			}
++		}
++	},
++
++	.num_device_descs = 1,
++	.devices = {
++		{   "DViCO FusionHDTV DVB-T Dual USB",
++			{ &cxusb_table[3], NULL },
++			{ &cxusb_table[4], NULL },
++		},
++	}
++};
++
+ static struct usb_driver cxusb_driver = {
+ 	.name		= "dvb_usb_cxusb",
+ 	.probe		= cxusb_probe,
+diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
+index 51ce7403999b..b2670476c3f2 100644
+--- a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
++++ b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
+@@ -74,6 +74,27 @@ static int usb_cypress_load_firmware(struct usb_device *udev, const struct firmw
+ 	return ret;
+ }
+ 
++/*
++ * DViCO bluebird firmware needs the "warm" product ID to be patched into the
++ * firmware file before download.
++ */
++#define BLUEBIRD_01_ID_OFFSET 6638
++static int dvb_usb_patch_dvico_firmware(struct usb_device *udev, const struct firmware *fw)
++{
++	if (fw->size < BLUEBIRD_01_ID_OFFSET + 4)
++		return -EINVAL;
++
++	if (fw->data[BLUEBIRD_01_ID_OFFSET] == (USB_VID_DVICO & 0xff) &&
++	    fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) {
++		fw->data[BLUEBIRD_01_ID_OFFSET + 2] = udev->descriptor.idProduct + 1;
++		fw->data[BLUEBIRD_01_ID_OFFSET + 3] = udev->descriptor.idProduct >> 8;
++
++		return 0;
++	}
++
++	return -EINVAL;
++}
++
+ int dvb_usb_download_firmware(struct usb_device *udev, struct dvb_usb_properties *props)
+ {
+ 	int ret;
+@@ -88,6 +109,12 @@ int dvb_usb_download_firmware(struct usb_device *udev, struct dvb_usb_properties
+ 
+ 	info("downloading firmware from file '%s'",props->firmware);
+ 
++	if (le16_to_cpu(udev->descriptor.idVendor) == USB_VID_DVICO) {
++		ret = dvb_usb_patch_dvico_firmware(udev, fw);
++		if (ret != 0)
++			warn("this firmware file not recognised");
++	}
++
+ 	switch (props->usb_ctrl) {
+ 		case CYPRESS_AN2135:
+ 		case CYPRESS_AN2235:
+diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+index 784adfe1c070..d22934383226 100644
+--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
++++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+@@ -86,13 +86,15 @@
+ #define USB_PID_WINTV_NOVA_T_USB2_COLD		0x9300
+ #define USB_PID_WINTV_NOVA_T_USB2_WARM		0x9301
+ #define USB_PID_NEBULA_DIGITV				0x0201
+-#define USB_PID_DVICO_BLUEBIRD_LGZ201		0xdb00
+-#define USB_PID_DVICO_BLUEBIRD_TH7579		0xdb10
+ #define USB_PID_DVICO_BLUEBIRD_LGDT			0xd820
+-#define USB_PID_DVICO_BLUEBIRD_LGZ201_1		0xdb01
+-#define USB_PID_DVICO_BLUEBIRD_TH7579_2		0xdb11
+ #define USB_PID_DVICO_BLUEBIRD_LG064F_COLD		0xd500
+-#define USB_PID_DVICO_BLUEBIRD_LG064F_WARM		0xd700
++#define USB_PID_DVICO_BLUEBIRD_LG064F_WARM		0xd501
++#define USB_PID_DVICO_BLUEBIRD_LGZ201_COLD		0xdb00
++#define USB_PID_DVICO_BLUEBIRD_LGZ201_WARM		0xdb01
++#define USB_PID_DVICO_BLUEBIRD_TH7579_COLD		0xdb10
++#define USB_PID_DVICO_BLUEBIRD_TH7579_WARM		0xdb11
++#define USB_PID_DVICO_BLUEBIRD_DEE1601_COLD		0xdb50
++#define USB_PID_DVICO_BLUEBIRD_DEE1601_WARM		0xdb51
+ #define USB_PID_MEDION_MD95700				0x0932
+ #define USB_PID_KYE_DVB_T_COLD				0x701e
+ #define USB_PID_KYE_DVB_T_WARM				0x701f

commit fc40b261db15d010455ad0a4e2ac59da2ced730f
+Author: Chris Pascoe 
+Date:   Mon Jan 9 15:25:35 2006 -0200
+
+    V4L/DVB (3220): Add support for VP-3054 HDTV board
+    
+    
+    - Added support for VP-3054 (aka DigitalNow DNTV Live! DVB-T Pro!).
+    - This board has a secondary I2C bus and remote control.
+    - Added a new module to handle secondary I2C bus on this board.
+    
+    Signed-off-by: Chris Pascoe 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88
+index bb93a0a1871c..956cf833e931 100644
+--- a/Documentation/video4linux/CARDLIST.cx88
++++ b/Documentation/video4linux/CARDLIST.cx88
+@@ -40,3 +40,4 @@
+  39 -> KWorld DVB-S 100                                    [17de:08b2]
+  40 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid                [0070:9400,0070:9402]
+  41 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile)  [0070:9800,0070:9802]
++ 42 -> digitalnow DNTV Live! DVB-T Pro                     [1822:0025]
+diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile
+index 90a7ace55f64..e4b2134fe567 100644
+--- a/drivers/media/video/cx88/Makefile
++++ b/drivers/media/video/cx88/Makefile
+@@ -4,7 +4,7 @@ cx8800-objs	:= cx88-video.o cx88-vbi.o
+ cx8802-objs	:= cx88-mpeg.o
+ 
+ obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o cx8802.o cx88-blackbird.o
+-obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
++obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o cx88-vp3054-i2c.o
+ 
+ EXTRA_CFLAGS += -I$(src)/..
+ EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
+@@ -17,5 +17,6 @@ extra-cflags-$(CONFIG_DVB_LGDT330X)  += -DHAVE_LGDT330X=1
+ extra-cflags-$(CONFIG_DVB_MT352)     += -DHAVE_MT352=1
+ extra-cflags-$(CONFIG_DVB_NXT200X)   += -DHAVE_NXT200X=1
+ extra-cflags-$(CONFIG_DVB_CX24123)   += -DHAVE_CX24123=1
++extra-cflags-$(CONFIG_VIDEO_CX88_DVB)+= -DHAVE_VP3054_I2C=1
+ 
+ EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
+diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
+index 85798e1fa047..6b17d1e1e520 100644
+--- a/drivers/media/video/cx88/cx88-cards.c
++++ b/drivers/media/video/cx88/cx88-cards.c
+@@ -982,6 +982,33 @@ struct cx88_board cx88_boards[] = {
+ 		/* fixme: Add radio support */
+ 		.dvb		= 1,
+ 	},
++	[CX88_BOARD_DNTV_LIVE_DVB_T_PRO] = {
++		.name           = "digitalnow DNTV Live! DVB-T Pro",
++		.tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
++		.radio_type     = UNSET,
++		.tuner_addr	= ADDR_UNSET,
++		.radio_addr	= ADDR_UNSET,
++		.tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE |
++				  TDA9887_PORT2_ACTIVE,
++		.input          = {{
++			.type   = CX88_VMUX_TELEVISION,
++			.vmux   = 0,
++			.gpio0  = 0xf80808,
++		},{
++			.type   = CX88_VMUX_COMPOSITE1,
++			.vmux   = 1,
++			.gpio0	= 0xf80808,
++		},{
++			.type   = CX88_VMUX_SVIDEO,
++			.vmux   = 2,
++			.gpio0	= 0xf80808,
++		}},
++		.radio = {
++			 .type  = CX88_RADIO,
++			 .gpio0 = 0xf80808,
++		},
++		.dvb            = 1,
++	},
+ };
+ const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
+ 
+@@ -1165,6 +1192,10 @@ struct cx88_subid cx88_subids[] = {
+ 		.subvendor = 0x0070,
+ 		.subdevice = 0x9001,
+ 		.card      = CX88_BOARD_HAUPPAUGE_DVB_T1,
++	},{
++		.subvendor = 0x1822,
++		.subdevice = 0x0025,
++		.card      = CX88_BOARD_DNTV_LIVE_DVB_T_PRO,
+ 	},
+ };
+ const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids);
+@@ -1362,6 +1393,9 @@ void cx88_card_setup(struct cx88_core *core)
+ 		cx_clear(MO_GP0_IO, 0x00000007);
+ 		cx_set(MO_GP2_IO, 0x00000101);
+ 		break;
++	case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
++		cx_write(MO_GP0_IO, 0x00080808);
++		break;
+ 	case CX88_BOARD_ATI_HDTVWONDER:
+ 		if (0 == core->i2c_rc) {
+ 			/* enable tuner */
+diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
+index ed5cfe5f5c0e..201050478711 100644
+--- a/drivers/media/video/cx88/cx88-dvb.c
++++ b/drivers/media/video/cx88/cx88-dvb.c
+@@ -3,7 +3,7 @@
+  * device driver for Conexant 2388x based TV cards
+  * MPEG Transport Stream (DVB) routines
+  *
+- * (c) 2004 Chris Pascoe 
++ * (c) 2004, 2005 Chris Pascoe 
+  * (c) 2004 Gerd Knorr  [SuSE Labs]
+  *
+  *  This program is free software; you can redistribute it and/or modify
+@@ -35,6 +35,9 @@
+ #ifdef HAVE_MT352
+ # include "mt352.h"
+ # include "mt352_priv.h"
++# ifdef HAVE_VP3054_I2C
++#  include "cx88-vp3054-i2c.h"
++# endif
+ #endif
+ #ifdef HAVE_CX22702
+ # include "cx22702.h"
+@@ -108,7 +111,7 @@ static struct videobuf_queue_ops dvb_qops = {
+ /* ------------------------------------------------------------------ */
+ 
+ #ifdef HAVE_MT352
+-static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe)
++static int generic_mt352_demod_init(struct dvb_frontend* fe)
+ {
+ 	static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x39 };
+ 	static u8 reset []         = { RESET,      0x80 };
+@@ -166,7 +169,7 @@ static int mt352_pll_set(struct dvb_frontend* fe,
+ 
+ static struct mt352_config dvico_fusionhdtv = {
+ 	.demod_address = 0x0F,
+-	.demod_init    = dvico_fusionhdtv_demod_init,
++	.demod_init    = generic_mt352_demod_init,
+ 	.pll_set       = mt352_pll_set,
+ };
+ 
+@@ -175,6 +178,69 @@ static struct mt352_config dntv_live_dvbt_config = {
+ 	.demod_init    = dntv_live_dvbt_demod_init,
+ 	.pll_set       = mt352_pll_set,
+ };
++
++#ifdef HAVE_VP3054_I2C
++static int philips_fmd1216_pll_init(struct dvb_frontend *fe)
++{
++	struct cx8802_dev *dev= fe->dvb->priv;
++
++	/* this message is to set up ATC and ALC */
++	static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0xa0 };
++	struct i2c_msg msg =
++		{ .addr = dev->core->pll_addr, .flags = 0,
++		  .buf = fmd1216_init, .len = sizeof(fmd1216_init) };
++	int err;
++
++	if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
++		if (err < 0)
++			return err;
++		else
++			return -EREMOTEIO;
++	}
++
++	return 0;
++}
++
++static int dntv_live_dvbt_pro_pll_set(struct dvb_frontend* fe,
++				      struct dvb_frontend_parameters* params,
++				      u8* pllbuf)
++{
++	struct cx8802_dev *dev= fe->dvb->priv;
++	struct i2c_msg msg =
++		{ .addr = dev->core->pll_addr, .flags = 0,
++		  .buf = pllbuf+1, .len = 4 };
++	int err;
++
++	/* Switch PLL to DVB mode */
++	err = philips_fmd1216_pll_init(fe);
++	if (err)
++		return err;
++
++	/* Tune PLL */
++	pllbuf[0] = dev->core->pll_addr << 1;
++	dvb_pll_configure(dev->core->pll_desc, pllbuf+1,
++			  params->frequency,
++			  params->u.ofdm.bandwidth);
++	if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
++		printk(KERN_WARNING "cx88-dvb: %s error "
++			   "(addr %02x <- %02x, err = %i)\n",
++			   __FUNCTION__, pllbuf[0], pllbuf[1], err);
++		if (err < 0)
++			return err;
++		else
++			return -EREMOTEIO;
++	}
++
++	return 0;
++}
++
++static struct mt352_config dntv_live_dvbt_pro_config = {
++	.demod_address = 0x0f,
++	.no_tuner      = 1,
++	.demod_init    = generic_mt352_demod_init,
++	.pll_set       = dntv_live_dvbt_pro_pll_set,
++};
++#endif
+ #endif
+ 
+ #ifdef HAVE_CX22702
+@@ -403,6 +469,16 @@ static int dvb_register(struct cx8802_dev *dev)
+ 		dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config,
+ 						 &dev->core->i2c_adap);
+ 		break;
++	case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
++#ifdef HAVE_VP3054_I2C
++		dev->core->pll_addr = 0x61;
++		dev->core->pll_desc = &dvb_pll_fmd1216me;
++		dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_pro_config,
++			&((struct vp3054_i2c_state *)dev->card_priv)->adap);
++#else
++		printk("%s: built without vp3054 support\n", dev->core->name);
++#endif
++		break;
+ #endif
+ #ifdef HAVE_OR51132
+ 	case CX88_BOARD_PCHDTV_HD3000:
+@@ -532,6 +608,12 @@ static int __devinit dvb_probe(struct pci_dev *pci_dev,
+ 	if (0 != err)
+ 		goto fail_free;
+ 
++#ifdef HAVE_VP3054_I2C
++	err = vp3054_i2c_probe(dev);
++	if (0 != err)
++		goto fail_free;
++#endif
++
+ 	/* dvb stuff */
+ 	printk("%s/2: cx2388x based dvb card\n", core->name);
+ 	videobuf_queue_init(&dev->dvb.dvbq, &dvb_qops,
+@@ -567,6 +649,10 @@ static void __devexit dvb_remove(struct pci_dev *pci_dev)
+ 	/* dvb */
+ 	videobuf_dvb_unregister(&dev->dvb);
+ 
++#ifdef HAVE_VP3054_I2C
++	vp3054_i2c_remove(dev);
++#endif
++
+ 	/* common */
+ 	cx8802_fini_common(dev);
+ 	cx88_core_put(dev->core,dev->pci);
+diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
+index 649bbf7bcc29..f40f97026b84 100644
+--- a/drivers/media/video/cx88/cx88-input.c
++++ b/drivers/media/video/cx88/cx88-input.c
+@@ -5,7 +5,7 @@
+  *
+  * Copyright (c) 2003 Pavel Machek
+  * Copyright (c) 2004 Gerd Knorr
+- * Copyright (c) 2004 Chris Pascoe
++ * Copyright (c) 2004, 2005 Chris Pascoe
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+@@ -305,6 +305,66 @@ static IR_KEYTAB_TYPE ir_codes_avertv_303[IR_KEYTAB_SIZE] = {
+ 
+ /* ---------------------------------------------------------------------- */
+ 
++/* DigitalNow DNTV Live! DVB-T Pro Remote */
++static IR_KEYTAB_TYPE ir_codes_dntv_live_dvbt_pro[IR_KEYTAB_SIZE] = {
++	[ 0x16 ] = KEY_POWER,
++	[ 0x5b ] = KEY_HOME,
++
++	[ 0x55 ] = KEY_TV,		/* live tv */
++	[ 0x58 ] = KEY_TUNER,		/* digital Radio */
++	[ 0x5a ] = KEY_RADIO,		/* FM radio */
++	[ 0x59 ] = KEY_DVD,		/* dvd menu */
++	[ 0x03 ] = KEY_1,
++	[ 0x01 ] = KEY_2,
++	[ 0x06 ] = KEY_3,
++	[ 0x09 ] = KEY_4,
++	[ 0x1d ] = KEY_5,
++	[ 0x1f ] = KEY_6,
++	[ 0x0d ] = KEY_7,
++	[ 0x19 ] = KEY_8,
++	[ 0x1b ] = KEY_9,
++	[ 0x0c ] = KEY_CANCEL,
++	[ 0x15 ] = KEY_0,
++	[ 0x4a ] = KEY_CLEAR,
++	[ 0x13 ] = KEY_BACK,
++	[ 0x00 ] = KEY_TAB,
++	[ 0x4b ] = KEY_UP,
++	[ 0x4e ] = KEY_LEFT,
++	[ 0x4f ] = KEY_OK,
++	[ 0x52 ] = KEY_RIGHT,
++	[ 0x51 ] = KEY_DOWN,
++	[ 0x1e ] = KEY_VOLUMEUP,
++	[ 0x0a ] = KEY_VOLUMEDOWN,
++	[ 0x02 ] = KEY_CHANNELDOWN,
++	[ 0x05 ] = KEY_CHANNELUP,
++	[ 0x11 ] = KEY_RECORD,
++	[ 0x14 ] = KEY_PLAY,
++	[ 0x4c ] = KEY_PAUSE,
++	[ 0x1a ] = KEY_STOP,
++	[ 0x40 ] = KEY_REWIND,
++	[ 0x12 ] = KEY_FASTFORWARD,
++	[ 0x41 ] = KEY_PREVIOUSSONG,	/* replay |< */
++	[ 0x42 ] = KEY_NEXTSONG,	/* skip >| */
++	[ 0x54 ] = KEY_CAMERA,		/* capture */
++	[ 0x50 ] = KEY_LANGUAGE,	/* sap */
++	[ 0x47 ] = KEY_TV2,		/* pip */
++	[ 0x4d ] = KEY_SCREEN,
++	[ 0x43 ] = KEY_SUBTITLE,
++	[ 0x10 ] = KEY_MUTE,
++	[ 0x49 ] = KEY_AUDIO,		/* l/r */
++	[ 0x07 ] = KEY_SLEEP,
++	[ 0x08 ] = KEY_VIDEO,		/* a/v */
++	[ 0x0e ] = KEY_PREVIOUS,	/* recall */
++	[ 0x45 ] = KEY_ZOOM,		/* zoom + */
++	[ 0x46 ] = KEY_ANGLE,		/* zoom - */
++	[ 0x56 ] = KEY_RED,
++	[ 0x57 ] = KEY_GREEN,
++	[ 0x5c ] = KEY_YELLOW,
++	[ 0x5d ] = KEY_BLUE,
++};
++
++/* ---------------------------------------------------------------------- */
++
+ struct cx88_IR {
+ 	struct cx88_core *core;
+ 	struct input_dev *input;
+@@ -313,7 +373,7 @@ struct cx88_IR {
+ 	char phys[32];
+ 
+ 	/* sample from gpio pin 16 */
+-	int sampling;
++	u32 sampling;
+ 	u32 samples[16];
+ 	int scount;
+ 	unsigned long release;
+@@ -431,7 +491,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
+ 	case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
+ 		ir_codes = ir_codes_cinergy_1400;
+ 		ir_type = IR_TYPE_PD;
+-		ir->sampling = 1;
++		ir->sampling = 0xeb04; /* address */
+ 		break;
+ 	case CX88_BOARD_HAUPPAUGE:
+ 	case CX88_BOARD_HAUPPAUGE_DVB_T1:
+@@ -484,6 +544,11 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
+ 		ir->mask_keydown = 0x02;
+ 		ir->polling      = 50; /* ms */
+ 		break;
++	case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
++		ir_codes = ir_codes_dntv_live_dvbt_pro;
++		ir_type = IR_TYPE_PD;
++		ir->sampling = 0xff00; /* address */
++		break;
+ 	}
+ 
+ 	if (NULL == ir_codes) {
+@@ -541,6 +606,10 @@ int cx88_ir_fini(struct cx88_core *core)
+ 	if (NULL == ir)
+ 		return 0;
+ 
++	if (ir->sampling) {
++		cx_write(MO_DDSCFG_IO, 0x0);
++		core->pci_irqmask &= ~(1 << 18);
++	}
+ 	if (ir->polling) {
+ 		del_timer(&ir->timer);
+ 		flush_scheduled_work();
+@@ -592,6 +661,7 @@ void cx88_ir_irq(struct cx88_core *core)
+ 	/* decode it */
+ 	switch (core->board) {
+ 	case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
++	case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
+ 		ircode = ir_decode_pulsedistance(ir->samples, ir->scount, 1, 4);
+ 
+ 		if (ircode == 0xffffffff) { /* decoding error */
+@@ -607,7 +677,7 @@ void cx88_ir_irq(struct cx88_core *core)
+ 			break;
+ 		}
+ 
+-		if ((ircode & 0xffff) != 0xeb04) { /* wrong address */
++		if ((ircode & 0xffff) != (ir->sampling & 0xffff)) { /* wrong address */
+ 			ir_dprintk("pulse distance decoded wrong address\n");
+ 			break;
+ 		}
+diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.c b/drivers/media/video/cx88/cx88-vp3054-i2c.c
+new file mode 100644
+index 000000000000..372cd29cedbd
+--- /dev/null
++++ b/drivers/media/video/cx88/cx88-vp3054-i2c.c
+@@ -0,0 +1,173 @@
++/*
++
++    cx88-vp3054-i2c.c  --  support for the secondary I2C bus of the
++			   DNTV Live! DVB-T Pro (VP-3054), wired as:
++			   GPIO[0] -> SCL, GPIO[1] -> SDA
++
++    (c) 2005 Chris Pascoe 
++
++    This program is free software; you can redistribute it and/or modify
++    it under the terms of the GNU General Public License as published by
++    the Free Software Foundation; either version 2 of the License, or
++    (at your option) any later version.
++
++    This program is distributed in the hope that it will be useful,
++    but WITHOUT ANY WARRANTY; without even the implied warranty of
++    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++    GNU General Public License for more details.
++
++    You should have received a copy of the GNU General Public License
++    along with this program; if not, write to the Free Software
++    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++*/
++
++#include 
++#include 
++#include 
++
++#include 
++
++#include "cx88.h"
++#include "cx88-vp3054-i2c.h"
++
++
++/* ----------------------------------------------------------------------- */
++
++static void vp3054_bit_setscl(void *data, int state)
++{
++	struct cx8802_dev *dev = data;
++	struct cx88_core *core = dev->core;
++	struct vp3054_i2c_state *vp3054_i2c = dev->card_priv;
++
++	if (state) {
++		vp3054_i2c->state |=  0x0001;	/* SCL high */
++		vp3054_i2c->state &= ~0x0100;	/* external pullup */
++	} else {
++		vp3054_i2c->state &= ~0x0001;	/* SCL low */
++		vp3054_i2c->state |=  0x0100;	/* drive pin */
++	}
++	cx_write(MO_GP0_IO, 0x010000 | vp3054_i2c->state);
++	cx_read(MO_GP0_IO);
++}
++
++static void vp3054_bit_setsda(void *data, int state)
++{
++	struct cx8802_dev *dev = data;
++	struct cx88_core *core = dev->core;
++	struct vp3054_i2c_state *vp3054_i2c = dev->card_priv;
++
++	if (state) {
++		vp3054_i2c->state |=  0x0002;	/* SDA high */
++		vp3054_i2c->state &= ~0x0200;	/* tristate pin */
++	} else {
++		vp3054_i2c->state &= ~0x0002;	/* SDA low */
++		vp3054_i2c->state |=  0x0200;	/* drive pin */
++	}
++	cx_write(MO_GP0_IO, 0x020000 | vp3054_i2c->state);
++	cx_read(MO_GP0_IO);
++}
++
++static int vp3054_bit_getscl(void *data)
++{
++	struct cx8802_dev *dev = data;
++	struct cx88_core *core = dev->core;
++	u32 state;
++
++	state = cx_read(MO_GP0_IO);
++	return (state & 0x01) ? 1 : 0;
++}
++
++static int vp3054_bit_getsda(void *data)
++{
++	struct cx8802_dev *dev = data;
++	struct cx88_core *core = dev->core;
++	u32 state;
++
++	state = cx_read(MO_GP0_IO);
++	return (state & 0x02) ? 1 : 0;
++}
++
++/* ----------------------------------------------------------------------- */
++
++static struct i2c_algo_bit_data vp3054_i2c_algo_template = {
++	.setsda  = vp3054_bit_setsda,
++	.setscl  = vp3054_bit_setscl,
++	.getsda  = vp3054_bit_getsda,
++	.getscl  = vp3054_bit_getscl,
++	.udelay  = 16,
++	.mdelay  = 10,
++	.timeout = 200,
++};
++
++/* ----------------------------------------------------------------------- */
++
++static struct i2c_adapter vp3054_i2c_adap_template = {
++	.name              = "cx2388x",
++	.owner             = THIS_MODULE,
++	.id                = I2C_HW_B_CX2388x,
++};
++
++static struct i2c_client vp3054_i2c_client_template = {
++	.name	= "VP-3054",
++};
++
++int vp3054_i2c_probe(struct cx8802_dev *dev)
++{
++	struct cx88_core *core = dev->core;
++	struct vp3054_i2c_state *vp3054_i2c;
++	int rc;
++
++	if (core->board != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
++		return 0;
++
++	dev->card_priv = kzalloc(sizeof(*vp3054_i2c), GFP_KERNEL);
++	if (dev->card_priv == NULL)
++		return -ENOMEM;
++	vp3054_i2c = dev->card_priv;
++
++	memcpy(&vp3054_i2c->adap, &vp3054_i2c_adap_template,
++	       sizeof(vp3054_i2c->adap));
++	memcpy(&vp3054_i2c->algo, &vp3054_i2c_algo_template,
++	       sizeof(vp3054_i2c->algo));
++	memcpy(&vp3054_i2c->client, &vp3054_i2c_client_template,
++	       sizeof(vp3054_i2c->client));
++
++	vp3054_i2c->adap.class |= I2C_CLASS_TV_DIGITAL;
++
++	vp3054_i2c->adap.dev.parent = &dev->pci->dev;
++	strlcpy(vp3054_i2c->adap.name, core->name,
++		sizeof(vp3054_i2c->adap.name));
++	vp3054_i2c->algo.data = dev;
++	i2c_set_adapdata(&vp3054_i2c->adap, dev);
++	vp3054_i2c->adap.algo_data = &vp3054_i2c->algo;
++	vp3054_i2c->client.adapter = &vp3054_i2c->adap;
++
++	vp3054_bit_setscl(dev,1);
++	vp3054_bit_setsda(dev,1);
++
++	rc = i2c_bit_add_bus(&vp3054_i2c->adap);
++	if (0 != rc) {
++		printk("%s: vp3054_i2c register FAILED\n", core->name);
++
++		kfree(dev->card_priv);
++		dev->card_priv = NULL;
++	}
++
++	return rc;
++}
++
++void vp3054_i2c_remove(struct cx8802_dev *dev)
++{
++	struct vp3054_i2c_state *vp3054_i2c = dev->card_priv;
++
++	if (vp3054_i2c == NULL ||
++	    dev->core->board != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
++		return;
++
++	i2c_bit_del_bus(&vp3054_i2c->adap);
++	kfree(vp3054_i2c);
++}
++
++EXPORT_SYMBOL(vp3054_i2c_probe);
++EXPORT_SYMBOL(vp3054_i2c_remove);
+diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.h b/drivers/media/video/cx88/cx88-vp3054-i2c.h
+new file mode 100644
+index 000000000000..b7a0a04d2423
+--- /dev/null
++++ b/drivers/media/video/cx88/cx88-vp3054-i2c.h
+@@ -0,0 +1,35 @@
++/*
++
++    cx88-vp3054-i2c.h  --  support for the secondary I2C bus of the
++			   DNTV Live! DVB-T Pro (VP-3054), wired as:
++			   GPIO[0] -> SCL, GPIO[1] -> SDA
++
++    (c) 2005 Chris Pascoe 
++
++    This program is free software; you can redistribute it and/or modify
++    it under the terms of the GNU General Public License as published by
++    the Free Software Foundation; either version 2 of the License, or
++    (at your option) any later version.
++
++    This program is distributed in the hope that it will be useful,
++    but WITHOUT ANY WARRANTY; without even the implied warranty of
++    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++    GNU General Public License for more details.
++
++    You should have received a copy of the GNU General Public License
++    along with this program; if not, write to the Free Software
++    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++*/
++
++/* ----------------------------------------------------------------------- */
++struct vp3054_i2c_state {
++	struct i2c_adapter         adap;
++	struct i2c_algo_bit_data   algo;
++	struct i2c_client          client;
++	u32                        state;
++};
++
++/* ----------------------------------------------------------------------- */
++int  vp3054_i2c_probe(struct cx8802_dev *dev);
++void vp3054_i2c_remove(struct cx8802_dev *dev);
+diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
+index 0bbf68b325c4..6d370d1b333f 100644
+--- a/drivers/media/video/cx88/cx88.h
++++ b/drivers/media/video/cx88/cx88.h
+@@ -184,6 +184,7 @@ extern struct sram_channel cx88_sram_channels[];
+ #define CX88_BOARD_KWORLD_DVBS_100         39
+ #define CX88_BOARD_HAUPPAUGE_HVR1100       40
+ #define CX88_BOARD_HAUPPAUGE_HVR1100LP     41
++#define CX88_BOARD_DNTV_LIVE_DVB_T_PRO     42
+ 
+ enum cx88_itype {
+ 	CX88_VMUX_COMPOSITE1 = 1,
+@@ -422,6 +423,8 @@ struct cx8802_dev {
+ 	struct videobuf_dvb        dvb;
+ 	void*                      fe_handle;
+ 	int                        (*fe_release)(void *handle);
++
++	void			   *card_priv;
+ 	/* for switching modulation types */
+ 	unsigned char              ts_gen_cntrl;
+ 

commit 889aee805a0c286e33965cc678ea16672d6c5666
+Author: Christopher Pascoe 
+Date:   Mon Jan 9 15:25:28 2006 -0200
+
+    V4L/DVB (3192): Fix bttv sub-device unregister
+    
+    
+    - Fixes sub-device release for BTTV. Without this, DVB modules can't be reloaded
+    
+    Signed-off-by: Ricardo Cerqueira 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
+index 4e25c92ac8c4..69a147b85f1a 100644
+--- a/drivers/media/video/bttv-driver.c
++++ b/drivers/media/video/bttv-driver.c
+@@ -4075,8 +4075,6 @@ static int __devinit bttv_probe(struct pci_dev *dev,
+ 	}
+ 
+ 	/* add subdevices */
+-	if (btv->has_remote)
+-		bttv_sub_add_device(&btv->c, "remote");
+ 	if (bttv_tvcards[btv->c.type].has_dvb)
+ 		bttv_sub_add_device(&btv->c, "dvb");
+ 
+@@ -4117,7 +4115,7 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev)
+ 	btv->shutdown=1;
+ 	wake_up(&btv->gpioq);
+ 	bttv_input_fini(btv);
+-	//bttv_sub_del_devices(&btv->c);
++	bttv_sub_del_devices(&btv->c);
+ 
+ 	/* unregister i2c_bus + input */
+ 	fini_bttv_i2c(btv);

\ No newline at end of file diff --git a/detail/18.html b/detail/18.html new file mode 100644 index 0000000..a4e3c11 --- /dev/null +++ b/detail/18.html @@ -0,0 +1,3297 @@ +

Patches contributed by Huazhong University of Science and Technology


commit daacef89cd1bb7e345539db10e979e1b78451591
+Author: Dongliang Mu 
+Date:   Fri Sep 1 14:25:48 2023 +0800
+
+    soc: loongson: loongson2_guts: Convert to devm_platform_ioremap_resource()
+    
+    Use devm_platform_ioremap_resource() to simplify code.
+    
+    Signed-off-by: Dongliang Mu 
+    Signed-off-by: Binbin Zhou 
+    Signed-off-by: Arnd Bergmann 
+
+diff --git a/drivers/soc/loongson/loongson2_guts.c b/drivers/soc/loongson/loongson2_guts.c
+index bace4bc8e03b..d97c77a9a4a2 100644
+--- a/drivers/soc/loongson/loongson2_guts.c
++++ b/drivers/soc/loongson/loongson2_guts.c
+@@ -94,7 +94,6 @@ static int loongson2_guts_probe(struct platform_device *pdev)
+ {
+ 	struct device_node *root, *np = pdev->dev.of_node;
+ 	struct device *dev = &pdev->dev;
+-	struct resource *res;
+ 	const struct loongson2_soc_die_attr *soc_die;
+ 	const char *machine;
+ 	u32 svr;
+@@ -106,8 +105,7 @@ static int loongson2_guts_probe(struct platform_device *pdev)
+ 
+ 	guts->little_endian = of_property_read_bool(np, "little-endian");
+ 
+-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-	guts->regs = ioremap(res->start, res->end - res->start + 1);
++	guts->regs = devm_platform_ioremap_resource(pdev, 0);
+ 	if (IS_ERR(guts->regs))
+ 		return PTR_ERR(guts->regs);
+ 

commit dc73b20593544f8e1b78dded909296f2777076d0
+Author: Dongliang Mu 
+Date:   Tue Sep 5 09:35:56 2023 +0800
+
+    wifi: ath9k: clean up function ath9k_hif_usb_resume
+    
+    In ath9k_hif_usb_resume, the error handling code calls
+    ath9k_hif_usb_dealloc_urbs twice in different paths.
+    
+    To unify the error handling code, we move the else branch before
+    the if branch and drop one level of indentation of the if branch.
+    
+    In addition, move the ret variable at the end of variable declarations
+    to be reverse x-mas tree order.
+    
+    Note that this patch does not incur any functionability change.
+    
+    Signed-off-by: Dongliang Mu 
+    Reviewed-by: Dan Carpenter 
+    Acked-by: Toke Høiland-Jørgensen 
+    Signed-off-by: Kalle Valo 
+    Link: https://lore.kernel.org/r/20230905013556.2595854-1-dzm91@hust.edu.cn
+
+diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
+index e5414435b141..90cfe39aa433 100644
+--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
++++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
+@@ -1481,31 +1481,31 @@ static int ath9k_hif_usb_resume(struct usb_interface *interface)
+ {
+ 	struct hif_device_usb *hif_dev = usb_get_intfdata(interface);
+ 	struct htc_target *htc_handle = hif_dev->htc_handle;
+-	int ret;
+ 	const struct firmware *fw;
++	int ret;
+ 
+ 	ret = ath9k_hif_usb_alloc_urbs(hif_dev);
+ 	if (ret)
+ 		return ret;
+ 
+-	if (hif_dev->flags & HIF_USB_READY) {
+-		/* request cached firmware during suspend/resume cycle */
+-		ret = request_firmware(&fw, hif_dev->fw_name,
+-				       &hif_dev->udev->dev);
+-		if (ret)
+-			goto fail_resume;
+-
+-		hif_dev->fw_data = fw->data;
+-		hif_dev->fw_size = fw->size;
+-		ret = ath9k_hif_usb_download_fw(hif_dev);
+-		release_firmware(fw);
+-		if (ret)
+-			goto fail_resume;
+-	} else {
+-		ath9k_hif_usb_dealloc_urbs(hif_dev);
+-		return -EIO;
++	if (!(hif_dev->flags & HIF_USB_READY)) {
++		ret = -EIO;
++		goto fail_resume;
+ 	}
+ 
++	/* request cached firmware during suspend/resume cycle */
++	ret = request_firmware(&fw, hif_dev->fw_name,
++			       &hif_dev->udev->dev);
++	if (ret)
++		goto fail_resume;
++
++	hif_dev->fw_data = fw->data;
++	hif_dev->fw_size = fw->size;
++	ret = ath9k_hif_usb_download_fw(hif_dev);
++	release_firmware(fw);
++	if (ret)
++		goto fail_resume;
++
+ 	mdelay(100);
+ 
+ 	ret = ath9k_htc_resume(htc_handle);

commit 99e25b17d2a3e3b486b4f6f90a740d51245da1f2
+Author: Dongliang Mu 
+Date:   Wed Nov 16 09:45:50 2022 +0800
+
+    pcmcia: typo fix
+    
+    themselfves -> themselves
+    
+    Signed-off-by: Dongliang Mu 
+    Signed-off-by: Dominik Brodowski 
+
+diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
+index d78091e79a0f..e9e31c638a67 100644
+--- a/drivers/pcmcia/pcmcia_resource.c
++++ b/drivers/pcmcia/pcmcia_resource.c
+@@ -684,7 +684,7 @@ EXPORT_SYMBOL(pcmcia_request_io);
+  * pcmcia_request_irq() is a wrapper around request_irq() which allows
+  * the PCMCIA core to clean up the registration in pcmcia_disable_device().
+  * Drivers are free to use request_irq() directly, but then they need to
+- * call free_irq() themselfves, too. Also, only %IRQF_SHARED capable IRQ
++ * call free_irq() themselves, too. Also, only %IRQF_SHARED capable IRQ
+  * handlers are allowed.
+  */
+ int __must_check pcmcia_request_irq(struct pcmcia_device *p_dev,

commit 1d40165047456923fa4343d519353d9440cd68df
+Author: Guoqing Cai 
+Date:   Thu Apr 13 17:57:39 2023 +0800
+
+    fs: jbd2: fix an incorrect warn log
+    
+    In jbd2_journal_load(), when journal_reset fails, it prints an incorrect
+    warn log.
+    
+    Fix this by changing the goto statement to return statement.
+    
+    Also, return actual error code from jbd2_journal_recover() and journal_reset().
+    
+    Signed-off-by: Guoqing Cai 
+    Reviewed-by: Jan Kara 
+    Link: https://lore.kernel.org/r/20230413095740.2222066-1-u202112087@hust.edu.cn
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index fbce16fedaa4..5c223032f77a 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -2089,8 +2089,11 @@ int jbd2_journal_load(journal_t *journal)
+ 
+ 	/* Let the recovery code check whether it needs to recover any
+ 	 * data from the journal. */
+-	if (jbd2_journal_recover(journal))
+-		goto recovery_error;
++	err = jbd2_journal_recover(journal);
++	if (err) {
++		pr_warn("JBD2: journal recovery failed\n");
++		return err;
++	}
+ 
+ 	if (journal->j_failed_commit) {
+ 		printk(KERN_ERR "JBD2: journal transaction %u on %s "
+@@ -2107,15 +2110,14 @@ int jbd2_journal_load(journal_t *journal)
+ 	/* OK, we've finished with the dynamic journal bits:
+ 	 * reinitialise the dynamic contents of the superblock in memory
+ 	 * and reset them on disk. */
+-	if (journal_reset(journal))
+-		goto recovery_error;
++	err = journal_reset(journal);
++	if (err) {
++		pr_warn("JBD2: journal reset failed\n");
++		return err;
++	}
+ 
+ 	journal->j_flags |= JBD2_LOADED;
+ 	return 0;
+-
+-recovery_error:
+-	printk(KERN_WARNING "JBD2: recovery failed\n");
+-	return -EIO;
+ }
+ 
+ /**

commit 061115fbfb2ce5870c9a004d68dc63138c07c782
+Author: Dongliang Mu 
+Date:   Sun Jul 23 12:04:02 2023 +0800
+
+    wifi: ath9k: fix printk specifier
+    
+    Smatch reports:
+    
+    ath_pci_probe() warn: argument 4 to %lx specifier is cast from pointer
+    ath_ahb_probe() warn: argument 4 to %lx specifier is cast from pointer
+    
+    Fix it by modifying %lx to %p in the printk format string.
+    
+    Note that with this change, the pointer address will be printed as a
+    hashed value by default. This is appropriate because the kernel
+    should not leak kernel pointers to user space in an informational
+    message. If someone wants to see the real address for debugging
+    purposes, this can be achieved with the no_hash_pointers kernel option.
+    
+    Signed-off-by: Dongliang Mu 
+    Acked-by: Toke Høiland-Jørgensen 
+    Signed-off-by: Kalle Valo 
+    Link: https://lore.kernel.org/r/20230723040403.296723-1-dzm91@hust.edu.cn
+
+diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
+index 9cd12b20b18d..9bfaadfa6c00 100644
+--- a/drivers/net/wireless/ath/ath9k/ahb.c
++++ b/drivers/net/wireless/ath/ath9k/ahb.c
+@@ -132,8 +132,8 @@ static int ath_ahb_probe(struct platform_device *pdev)
+ 
+ 	ah = sc->sc_ah;
+ 	ath9k_hw_name(ah, hw_name, sizeof(hw_name));
+-	wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
+-		   hw_name, (unsigned long)mem, irq);
++	wiphy_info(hw->wiphy, "%s mem=0x%p, irq=%d\n",
++		   hw_name, mem, irq);
+ 
+ 	return 0;
+ 
+diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
+index a09f9d223f3d..0633589b85c2 100644
+--- a/drivers/net/wireless/ath/ath9k/pci.c
++++ b/drivers/net/wireless/ath/ath9k/pci.c
+@@ -988,8 +988,8 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	sc->sc_ah->msi_reg = 0;
+ 
+ 	ath9k_hw_name(sc->sc_ah, hw_name, sizeof(hw_name));
+-	wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
+-		   hw_name, (unsigned long)sc->mem, pdev->irq);
++	wiphy_info(hw->wiphy, "%s mem=0x%p, irq=%d\n",
++		   hw_name, sc->mem, pdev->irq);
+ 
+ 	return 0;
+ 

commit b9c7141f384097fa4fa67d2f72e5731d628aef7c
+Author: Dongliang Mu 
+Date:   Mon Feb 27 18:24:08 2023 +0800
+
+    drivers: usb: smsusb: fix error handling code in smsusb_init_device
+    
+    The previous commit 4b208f8b561f ("[media] siano: register media controller
+    earlier")moves siano_media_device_register before smscore_register_device,
+    and adds corresponding error handling code if smscore_register_device
+    fails. However, it misses the following error handling code of
+    smsusb_init_device.
+    
+    Fix this by moving error handling code at the end of smsusb_init_device
+    and adding a goto statement in the following error handling parts.
+    
+    Fixes: 4b208f8b561f ("[media] siano: register media controller earlier")
+    Signed-off-by: Dongliang Mu 
+    Signed-off-by: Hans Verkuil 
+
+diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c
+index 640737d3b8ae..8a39cac76c58 100644
+--- a/drivers/media/usb/siano/smsusb.c
++++ b/drivers/media/usb/siano/smsusb.c
+@@ -455,12 +455,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
+ 	rc = smscore_register_device(¶ms, &dev->coredev, 0, mdev);
+ 	if (rc < 0) {
+ 		pr_err("smscore_register_device(...) failed, rc %d\n", rc);
+-		smsusb_term_device(intf);
+-#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+-		media_device_unregister(mdev);
+-#endif
+-		kfree(mdev);
+-		return rc;
++		goto err_unregister_device;
+ 	}
+ 
+ 	smscore_set_board_id(dev->coredev, board_id);
+@@ -477,8 +472,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
+ 	rc = smsusb_start_streaming(dev);
+ 	if (rc < 0) {
+ 		pr_err("smsusb_start_streaming(...) failed\n");
+-		smsusb_term_device(intf);
+-		return rc;
++		goto err_unregister_device;
+ 	}
+ 
+ 	dev->state = SMSUSB_ACTIVE;
+@@ -486,13 +480,20 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
+ 	rc = smscore_start_device(dev->coredev);
+ 	if (rc < 0) {
+ 		pr_err("smscore_start_device(...) failed\n");
+-		smsusb_term_device(intf);
+-		return rc;
++		goto err_unregister_device;
+ 	}
+ 
+ 	pr_debug("device 0x%p created\n", dev);
+ 
+ 	return rc;
++
++err_unregister_device:
++	smsusb_term_device(intf);
++#ifdef CONFIG_MEDIA_CONTROLLER_DVB
++	media_device_unregister(mdev);
++#endif
++	kfree(mdev);
++	return rc;
+ }
+ 
+ static int smsusb_probe(struct usb_interface *intf,

commit cd9489623c29aa2f8cc07088168afb6e0d5ef06d
+Author: Shuai Jiang 
+Date:   Tue Apr 18 21:56:12 2023 +0800
+
+    i2c: qup: Add missing unwind goto in qup_i2c_probe()
+    
+    Smatch Warns:
+            drivers/i2c/busses/i2c-qup.c:1784 qup_i2c_probe()
+            warn: missing unwind goto?
+    
+    The goto label "fail_runtime" and "fail" will disable qup->pclk,
+    but here qup->pclk failed to obtain, in order to be consistent,
+    change the direct return to goto label "fail_dma".
+    
+    Fixes: 9cedf3b2f099 ("i2c: qup: Add bam dma capabilities")
+    Signed-off-by: Shuai Jiang 
+    Reviewed-by: Dongliang Mu 
+    Reviewed-by: Andi Shyti 
+    Signed-off-by: Wolfram Sang 
+    Cc:  # v4.6+
+
+diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
+index 2e153f2f71b6..78682388e02e 100644
+--- a/drivers/i2c/busses/i2c-qup.c
++++ b/drivers/i2c/busses/i2c-qup.c
+@@ -1752,16 +1752,21 @@ static int qup_i2c_probe(struct platform_device *pdev)
+ 	if (!clk_freq || clk_freq > I2C_MAX_FAST_MODE_PLUS_FREQ) {
+ 		dev_err(qup->dev, "clock frequency not supported %d\n",
+ 			clk_freq);
+-		return -EINVAL;
++		ret = -EINVAL;
++		goto fail_dma;
+ 	}
+ 
+ 	qup->base = devm_platform_ioremap_resource(pdev, 0);
+-	if (IS_ERR(qup->base))
+-		return PTR_ERR(qup->base);
++	if (IS_ERR(qup->base)) {
++		ret = PTR_ERR(qup->base);
++		goto fail_dma;
++	}
+ 
+ 	qup->irq = platform_get_irq(pdev, 0);
+-	if (qup->irq < 0)
+-		return qup->irq;
++	if (qup->irq < 0) {
++		ret = qup->irq;
++		goto fail_dma;
++	}
+ 
+ 	if (has_acpi_companion(qup->dev)) {
+ 		ret = device_property_read_u32(qup->dev,
+@@ -1775,13 +1780,15 @@ static int qup_i2c_probe(struct platform_device *pdev)
+ 		qup->clk = devm_clk_get(qup->dev, "core");
+ 		if (IS_ERR(qup->clk)) {
+ 			dev_err(qup->dev, "Could not get core clock\n");
+-			return PTR_ERR(qup->clk);
++			ret = PTR_ERR(qup->clk);
++			goto fail_dma;
+ 		}
+ 
+ 		qup->pclk = devm_clk_get(qup->dev, "iface");
+ 		if (IS_ERR(qup->pclk)) {
+ 			dev_err(qup->dev, "Could not get iface clock\n");
+-			return PTR_ERR(qup->pclk);
++			ret = PTR_ERR(qup->pclk);
++			goto fail_dma;
+ 		}
+ 		qup_i2c_enable_clocks(qup);
+ 		src_clk_freq = clk_get_rate(qup->clk);

commit 9e1a1ee93f6b08aad5ee645073f7c7b115f71e15
+Author: Wang Zhang 
+Date:   Fri May 26 15:05:33 2023 +0800
+
+    i2c: ocores: use devm_ managed clks
+    
+    Smatch complains that:
+    drivers/i2c/busses/i2c-ocores.c:704 ocores_i2c_probe()
+    warn: missing unwind goto?
+    
+    If any wrong occurs in ocores_i2c_of_probe, the i2c->clk needs to be
+    released. But the function returns directly without freeing the clock.
+    
+    Fix this by updating the code to use devm_clk_get_optional_enabled()
+    instead. Use dev_err_probe() where appropriate as well since we are
+    changing those statements.
+    
+    Fixes: f5f35a92e44a ("i2c: ocores: Add irq support for sparc")
+    Signed-off-by: Wang Zhang 
+    Reviewed-by: Andi Shyti 
+    Reviewed-by: Andrew Lunn 
+    Signed-off-by: Wolfram Sang 
+
+diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
+index 0742b84a11eb..4ac77e57bbbf 100644
+--- a/drivers/i2c/busses/i2c-ocores.c
++++ b/drivers/i2c/busses/i2c-ocores.c
+@@ -552,28 +552,20 @@ static int ocores_i2c_of_probe(struct platform_device *pdev,
+ 							&clock_frequency);
+ 	i2c->bus_clock_khz = 100;
+ 
+-	i2c->clk = devm_clk_get(&pdev->dev, NULL);
+-
+-	if (!IS_ERR(i2c->clk)) {
+-		int ret = clk_prepare_enable(i2c->clk);
+-
+-		if (ret) {
+-			dev_err(&pdev->dev,
+-				"clk_prepare_enable failed: %d\n", ret);
+-			return ret;
+-		}
+-		i2c->ip_clock_khz = clk_get_rate(i2c->clk) / 1000;
+-		if (clock_frequency_present)
+-			i2c->bus_clock_khz = clock_frequency / 1000;
+-	}
+-
++	i2c->clk = devm_clk_get_optional_enabled(&pdev->dev, NULL);
++	if (IS_ERR(i2c->clk))
++		return dev_err_probe(&pdev->dev, PTR_ERR(i2c->clk),
++				     "devm_clk_get_optional_enabled failed\n");
++
++	i2c->ip_clock_khz = clk_get_rate(i2c->clk) / 1000;
++	if (clock_frequency_present)
++		i2c->bus_clock_khz = clock_frequency / 1000;
+ 	if (i2c->ip_clock_khz == 0) {
+ 		if (of_property_read_u32(np, "opencores,ip-clock-frequency",
+ 						&val)) {
+ 			if (!clock_frequency_present) {
+ 				dev_err(&pdev->dev,
+ 					"Missing required parameter 'opencores,ip-clock-frequency'\n");
+-				clk_disable_unprepare(i2c->clk);
+ 				return -ENODEV;
+ 			}
+ 			i2c->ip_clock_khz = clock_frequency / 1000;
+@@ -678,8 +670,7 @@ static int ocores_i2c_probe(struct platform_device *pdev)
+ 		default:
+ 			dev_err(&pdev->dev, "Unsupported I/O width (%d)\n",
+ 				i2c->reg_io_width);
+-			ret = -EINVAL;
+-			goto err_clk;
++			return -EINVAL;
+ 		}
+ 	}
+ 
+@@ -710,13 +701,13 @@ static int ocores_i2c_probe(struct platform_device *pdev)
+ 						   pdev->name, i2c);
+ 		if (ret) {
+ 			dev_err(&pdev->dev, "Cannot claim IRQ\n");
+-			goto err_clk;
++			return ret;
+ 		}
+ 	}
+ 
+ 	ret = ocores_init(&pdev->dev, i2c);
+ 	if (ret)
+-		goto err_clk;
++		return ret;
+ 
+ 	/* hook up driver to tree */
+ 	platform_set_drvdata(pdev, i2c);
+@@ -728,7 +719,7 @@ static int ocores_i2c_probe(struct platform_device *pdev)
+ 	/* add i2c adapter to i2c tree */
+ 	ret = i2c_add_adapter(&i2c->adap);
+ 	if (ret)
+-		goto err_clk;
++		return ret;
+ 
+ 	/* add in known devices to the bus */
+ 	if (pdata) {
+@@ -737,10 +728,6 @@ static int ocores_i2c_probe(struct platform_device *pdev)
+ 	}
+ 
+ 	return 0;
+-
+-err_clk:
+-	clk_disable_unprepare(i2c->clk);
+-	return ret;
+ }
+ 
+ static void ocores_i2c_remove(struct platform_device *pdev)
+@@ -754,9 +741,6 @@ static void ocores_i2c_remove(struct platform_device *pdev)
+ 
+ 	/* remove adapter & data */
+ 	i2c_del_adapter(&i2c->adap);
+-
+-	if (!IS_ERR(i2c->clk))
+-		clk_disable_unprepare(i2c->clk);
+ }
+ 
+ #ifdef CONFIG_PM_SLEEP
+@@ -769,28 +753,22 @@ static int ocores_i2c_suspend(struct device *dev)
+ 	ctrl &= ~(OCI2C_CTRL_EN | OCI2C_CTRL_IEN);
+ 	oc_setreg(i2c, OCI2C_CONTROL, ctrl);
+ 
+-	if (!IS_ERR(i2c->clk))
+-		clk_disable_unprepare(i2c->clk);
++	clk_disable_unprepare(i2c->clk);
+ 	return 0;
+ }
+ 
+ static int ocores_i2c_resume(struct device *dev)
+ {
+ 	struct ocores_i2c *i2c = dev_get_drvdata(dev);
++	unsigned long rate;
++	int ret;
+ 
+-	if (!IS_ERR(i2c->clk)) {
+-		unsigned long rate;
+-		int ret = clk_prepare_enable(i2c->clk);
+-
+-		if (ret) {
+-			dev_err(dev,
+-				"clk_prepare_enable failed: %d\n", ret);
+-			return ret;
+-		}
+-		rate = clk_get_rate(i2c->clk) / 1000;
+-		if (rate)
+-			i2c->ip_clock_khz = rate;
+-	}
++	ret = clk_prepare_enable(i2c->clk);
++	if (ret)
++		return dev_err_probe(dev, ret, "clk_prepare_enable failed\n");
++	rate = clk_get_rate(i2c->clk) / 1000;
++	if (rate)
++		i2c->ip_clock_khz = rate;
+ 	return ocores_init(dev, i2c);
+ }
+ 

commit 8b5bf64c89c7100c921bd807ba39b2eb003061ab
+Author: Feng Mingxi 
+Date:   Tue Apr 25 06:56:11 2023 +0000
+
+    clocksource/drivers/cadence-ttc: Fix memory leak in ttc_timer_probe
+    
+    Smatch reports:
+    drivers/clocksource/timer-cadence-ttc.c:529 ttc_timer_probe()
+    warn: 'timer_baseaddr' from of_iomap() not released on lines: 498,508,516.
+    
+    timer_baseaddr may have the problem of not being released after use,
+    I replaced it with the devm_of_iomap() function and added the clk_put()
+    function to cleanup the "clk_ce" and "clk_cs".
+    
+    Fixes: e932900a3279 ("arm: zynq: Use standard timer binding")
+    Fixes: 70504f311d4b ("clocksource/drivers/cadence_ttc: Convert init function to return error")
+    Signed-off-by: Feng Mingxi 
+    Reviewed-by: Dongliang Mu 
+    Acked-by: Michal Simek 
+    Signed-off-by: Daniel Lezcano 
+    Link: https://lore.kernel.org/r/20230425065611.702917-1-m202271825@hust.edu.cn
+
+diff --git a/drivers/clocksource/timer-cadence-ttc.c b/drivers/clocksource/timer-cadence-ttc.c
+index 4efd0cf3b602..0d52e28fea4d 100644
+--- a/drivers/clocksource/timer-cadence-ttc.c
++++ b/drivers/clocksource/timer-cadence-ttc.c
+@@ -486,10 +486,10 @@ static int __init ttc_timer_probe(struct platform_device *pdev)
+ 	 * and use it. Note that the event timer uses the interrupt and it's the
+ 	 * 2nd TTC hence the irq_of_parse_and_map(,1)
+ 	 */
+-	timer_baseaddr = of_iomap(timer, 0);
+-	if (!timer_baseaddr) {
++	timer_baseaddr = devm_of_iomap(&pdev->dev, timer, 0, NULL);
++	if (IS_ERR(timer_baseaddr)) {
+ 		pr_err("ERROR: invalid timer base address\n");
+-		return -ENXIO;
++		return PTR_ERR(timer_baseaddr);
+ 	}
+ 
+ 	irq = irq_of_parse_and_map(timer, 1);
+@@ -513,20 +513,27 @@ static int __init ttc_timer_probe(struct platform_device *pdev)
+ 	clk_ce = of_clk_get(timer, clksel);
+ 	if (IS_ERR(clk_ce)) {
+ 		pr_err("ERROR: timer input clock not found\n");
+-		return PTR_ERR(clk_ce);
++		ret = PTR_ERR(clk_ce);
++		goto put_clk_cs;
+ 	}
+ 
+ 	ret = ttc_setup_clocksource(clk_cs, timer_baseaddr, timer_width);
+ 	if (ret)
+-		return ret;
++		goto put_clk_ce;
+ 
+ 	ret = ttc_setup_clockevent(clk_ce, timer_baseaddr + 4, irq);
+ 	if (ret)
+-		return ret;
++		goto put_clk_ce;
+ 
+ 	pr_info("%pOFn #0 at %p, irq=%d\n", timer, timer_baseaddr, irq);
+ 
+ 	return 0;
++
++put_clk_ce:
++	clk_put(clk_ce);
++put_clk_cs:
++	clk_put(clk_cs);
++	return ret;
+ }
+ 
+ static const struct of_device_id ttc_timer_of_match[] = {

commit 095bb8ba45f28ed15296eb5b7662e03e57d5e34e
+Author: Yi Yingao 
+Date:   Tue May 9 16:52:36 2023 +0800
+
+    nvmem: sunplus-ocotp: release otp->clk before return
+    
+    Smatch reports:
+    drivers/nvmem/sunplus-ocotp.c:205 sp_ocotp_probe()
+    warn: 'otp->clk' from clk_prepare() not released on lines: 196.
+    
+    In the function sp_ocotp_probe(struct platform_device *pdev), otp->clk may
+    not be released before return.
+    
+    To fix this issue, using function clk_unprepare() to release otp->clk.
+    
+    Fixes: 8747ec2e9762 ("nvmem: Add driver for OCOTP in Sunplus SP7021")
+    Signed-off-by: Yi Yingao 
+    Reviewed-by: Dongliang Mu 
+    Message-ID: <20230509085237.5917-1-m202271736@hust.edu.cn>
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/nvmem/sunplus-ocotp.c b/drivers/nvmem/sunplus-ocotp.c
+index 52b928a7a6d5..f85350b17d67 100644
+--- a/drivers/nvmem/sunplus-ocotp.c
++++ b/drivers/nvmem/sunplus-ocotp.c
+@@ -192,9 +192,11 @@ static int sp_ocotp_probe(struct platform_device *pdev)
+ 	sp_ocotp_nvmem_config.dev = dev;
+ 
+ 	nvmem = devm_nvmem_register(dev, &sp_ocotp_nvmem_config);
+-	if (IS_ERR(nvmem))
+-		return dev_err_probe(&pdev->dev, PTR_ERR(nvmem),
++	if (IS_ERR(nvmem)) {
++		ret = dev_err_probe(&pdev->dev, PTR_ERR(nvmem),
+ 						"register nvmem device fail\n");
++		goto err;
++	}
+ 
+ 	platform_set_drvdata(pdev, nvmem);
+ 
+@@ -203,6 +205,9 @@ static int sp_ocotp_probe(struct platform_device *pdev)
+ 		(int)OTP_WORD_SIZE, (int)QAC628_OTP_SIZE);
+ 
+ 	return 0;
++err:
++	clk_unprepare(otp->clk);
++	return ret;
+ }
+ 
+ static const struct of_device_id sp_ocotp_dt_ids[] = {

commit 3db7285e044144fd88a356f5b641b9cd4b231a77
+Author: Bosi Zhang 
+Date:   Sat Apr 22 08:43:31 2023 +0000
+
+    clk: mediatek: fix of_iomap memory leak
+    
+    Smatch reports:
+    drivers/clk/mediatek/clk-mtk.c:583 mtk_clk_simple_probe() warn:
+        'base' from of_iomap() not released on lines: 496.
+    
+    This problem was also found in linux-next. In mtk_clk_simple_probe(),
+    base is not released when handling errors
+    if clk_data is not existed, which may cause a leak.
+    So free_base should be added here to release base.
+    
+    Fixes: c58cd0e40ffa ("clk: mediatek: Add mtk_clk_simple_probe() to simplify clock providers")
+    Signed-off-by: Bosi Zhang 
+    Reviewed-by: Dongliang Mu 
+    Link: https://lore.kernel.org/r/20230422084331.47198-1-u201911157@hust.edu.cn
+    Signed-off-by: Stephen Boyd 
+
+diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
+index fd2214c3242f..3c50f48e93a7 100644
+--- a/drivers/clk/mediatek/clk-mtk.c
++++ b/drivers/clk/mediatek/clk-mtk.c
+@@ -500,8 +500,10 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev,
+ 	num_clks += mcd->num_mux_clks + mcd->num_divider_clks;
+ 
+ 	clk_data = mtk_alloc_clk_data(num_clks);
+-	if (!clk_data)
+-		return -ENOMEM;
++	if (!clk_data) {
++		r = -ENOMEM;
++		goto free_base;
++	}
+ 
+ 	if (mcd->fixed_clks) {
+ 		r = mtk_clk_register_fixed_clks(mcd->fixed_clks,
+@@ -599,6 +601,7 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev,
+ 					      mcd->num_fixed_clks, clk_data);
+ free_data:
+ 	mtk_free_clk_data(clk_data);
++free_base:
+ 	if (mcd->shared_io && base)
+ 		iounmap(base);
+ 	return r;

commit 878b02d5f3b56cb090dbe2c70c89273be144087f
+Author: Yuxing Liu 
+Date:   Wed May 3 07:06:07 2023 +0000
+
+    clk: imx: clk-imx8mp: improve error handling in imx8mp_clocks_probe()
+    
+    Replace of_iomap() and kzalloc() with devm_of_iomap() and devm_kzalloc()
+    which can automatically release the related memory when the device
+    or driver is removed or unloaded to avoid potential memory leak.
+    
+    In this case, iounmap(anatop_base) in line 427,433 are removed
+    as manual release is not required.
+    
+    Besides, referring to clk-imx8mq.c, check the return code of
+    of_clk_add_hw_provider, if it returns negtive, print error info
+    and unregister hws, which makes the program more robust.
+    
+    Fixes: 9c140d992676 ("clk: imx: Add support for i.MX8MP clock driver")
+    Signed-off-by: Yuxing Liu 
+    Reviewed-by: Dongliang Mu 
+    Reviewed-by: Abel Vesa 
+    Link: https://lore.kernel.org/r/20230503070607.2462-1-lyx2022@hust.edu.cn
+    Signed-off-by: Abel Vesa 
+
+diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c
+index f26ae8de4cc6..1469249386dd 100644
+--- a/drivers/clk/imx/clk-imx8mp.c
++++ b/drivers/clk/imx/clk-imx8mp.c
+@@ -414,25 +414,22 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
+ 	struct device *dev = &pdev->dev;
+ 	struct device_node *np;
+ 	void __iomem *anatop_base, *ccm_base;
++	int err;
+ 
+ 	np = of_find_compatible_node(NULL, NULL, "fsl,imx8mp-anatop");
+-	anatop_base = of_iomap(np, 0);
++	anatop_base = devm_of_iomap(dev, np, 0, NULL);
+ 	of_node_put(np);
+-	if (WARN_ON(!anatop_base))
+-		return -ENOMEM;
++	if (WARN_ON(IS_ERR(anatop_base)))
++		return PTR_ERR(anatop_base);
+ 
+ 	np = dev->of_node;
+ 	ccm_base = devm_platform_ioremap_resource(pdev, 0);
+-	if (WARN_ON(IS_ERR(ccm_base))) {
+-		iounmap(anatop_base);
++	if (WARN_ON(IS_ERR(ccm_base)))
+ 		return PTR_ERR(ccm_base);
+-	}
+ 
+-	clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, IMX8MP_CLK_END), GFP_KERNEL);
+-	if (WARN_ON(!clk_hw_data)) {
+-		iounmap(anatop_base);
++	clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws, IMX8MP_CLK_END), GFP_KERNEL);
++	if (WARN_ON(!clk_hw_data))
+ 		return -ENOMEM;
+-	}
+ 
+ 	clk_hw_data->num = IMX8MP_CLK_END;
+ 	hws = clk_hw_data->hws;
+@@ -722,7 +719,12 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
+ 
+ 	imx_check_clk_hws(hws, IMX8MP_CLK_END);
+ 
+-	of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
++	err = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
++	if (err < 0) {
++		dev_err(dev, "failed to register hws for i.MX8MP\n");
++		imx_unregister_hw_clocks(hws, IMX8MP_CLK_END);
++		return err;
++	}
+ 
+ 	imx_register_uart_clocks();
+ 

commit e02ba11b457647050cb16e7cad16cec3c252fade
+Author: Zhanhao Hu 
+Date:   Thu Jun 1 03:38:25 2023 +0000
+
+    clk: imx93: fix memory leak and missing unwind goto in imx93_clocks_probe
+    
+    In function probe(), it returns directly without unregistered hws
+    when error occurs.
+    
+    Fix this by adding 'goto unregister_hws;' on line 295 and
+    line 310.
+    
+    Use devm_kzalloc() instead of kzalloc() to automatically
+    free the memory using devm_kfree() when error occurs.
+    
+    Replace of_iomap() with devm_of_iomap() to automatically
+    handle the unused ioremap region and delete 'iounmap(anatop_base);'
+    in unregister_hws.
+    
+    Fixes: 24defbe194b6 ("clk: imx: add i.MX93 clk")
+    Signed-off-by: Zhanhao Hu 
+    Reviewed-by: Abel Vesa 
+    Link: https://lore.kernel.org/r/20230601033825.336558-1-zero12113@hust.edu.cn
+    Signed-off-by: Abel Vesa 
+
+diff --git a/drivers/clk/imx/clk-imx93.c b/drivers/clk/imx/clk-imx93.c
+index 07b4a043e449..b6c7c2725906 100644
+--- a/drivers/clk/imx/clk-imx93.c
++++ b/drivers/clk/imx/clk-imx93.c
+@@ -264,7 +264,7 @@ static int imx93_clocks_probe(struct platform_device *pdev)
+ 	void __iomem *base, *anatop_base;
+ 	int i, ret;
+ 
+-	clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
++	clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws,
+ 					  IMX93_CLK_END), GFP_KERNEL);
+ 	if (!clk_hw_data)
+ 		return -ENOMEM;
+@@ -288,10 +288,12 @@ static int imx93_clocks_probe(struct platform_device *pdev)
+ 								    "sys_pll_pfd2", 1, 2);
+ 
+ 	np = of_find_compatible_node(NULL, NULL, "fsl,imx93-anatop");
+-	anatop_base = of_iomap(np, 0);
++	anatop_base = devm_of_iomap(dev, np, 0, NULL);
+ 	of_node_put(np);
+-	if (WARN_ON(!anatop_base))
+-		return -ENOMEM;
++	if (WARN_ON(IS_ERR(anatop_base))) {
++		ret = PTR_ERR(base);
++		goto unregister_hws;
++	}
+ 
+ 	clks[IMX93_CLK_ARM_PLL] = imx_clk_fracn_gppll_integer("arm_pll", "osc_24m",
+ 							      anatop_base + 0x1000,
+@@ -304,8 +306,8 @@ static int imx93_clocks_probe(struct platform_device *pdev)
+ 	np = dev->of_node;
+ 	base = devm_platform_ioremap_resource(pdev, 0);
+ 	if (WARN_ON(IS_ERR(base))) {
+-		iounmap(anatop_base);
+-		return PTR_ERR(base);
++		ret = PTR_ERR(base);
++		goto unregister_hws;
+ 	}
+ 
+ 	for (i = 0; i < ARRAY_SIZE(root_array); i++) {
+@@ -345,7 +347,6 @@ static int imx93_clocks_probe(struct platform_device *pdev)
+ 
+ unregister_hws:
+ 	imx_unregister_hw_clocks(clks, IMX93_CLK_END);
+-	iounmap(anatop_base);
+ 
+ 	return ret;
+ }

commit 188d070de9132667956f5aadd98d2bd87d3eac89
+Author: Hao Luo 
+Date:   Tue Apr 11 09:51:07 2023 +0800
+
+    clk: imx: clk-imx8mn: fix memory leak in imx8mn_clocks_probe
+    
+    Use devm_of_iomap() instead of of_iomap() to automatically handle
+    the unused ioremap region.
+    
+    If any error occurs, regions allocated by kzalloc() will leak,
+    but using devm_kzalloc() instead will automatically free the memory
+    using devm_kfree().
+    
+    Fixes: daeb14545514 ("clk: imx: imx8mn: Switch to clk_hw based API")
+    Fixes: 96d6392b54db ("clk: imx: Add support for i.MX8MN clock driver")
+    Signed-off-by: Hao Luo 
+    Reviewed-by: Dongliang Mu 
+    Reviewed-by: Peng Fan 
+    Link: https://lore.kernel.org/r/20230411015107.2645-1-m202171776@hust.edu.cn
+    Signed-off-by: Abel Vesa 
+
+diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c
+index 4b23a4648600..4bd1ed11353b 100644
+--- a/drivers/clk/imx/clk-imx8mn.c
++++ b/drivers/clk/imx/clk-imx8mn.c
+@@ -323,7 +323,7 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
+ 	void __iomem *base;
+ 	int ret;
+ 
+-	clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
++	clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws,
+ 					  IMX8MN_CLK_END), GFP_KERNEL);
+ 	if (WARN_ON(!clk_hw_data))
+ 		return -ENOMEM;
+@@ -340,10 +340,10 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
+ 	hws[IMX8MN_CLK_EXT4] = imx_get_clk_hw_by_name(np, "clk_ext4");
+ 
+ 	np = of_find_compatible_node(NULL, NULL, "fsl,imx8mn-anatop");
+-	base = of_iomap(np, 0);
++	base = devm_of_iomap(dev, np, 0, NULL);
+ 	of_node_put(np);
+-	if (WARN_ON(!base)) {
+-		ret = -ENOMEM;
++	if (WARN_ON(IS_ERR(base))) {
++		ret = PTR_ERR(base);
+ 		goto unregister_hws;
+ 	}
+ 

commit 1b280598ab3bd8a2dc8b96a12530d5b1ee7a8f4a
+Author: Kai Ma 
+Date:   Tue Apr 18 11:34:51 2023 +0000
+
+    clk: imx: clk-imxrt1050: fix memory leak in imxrt1050_clocks_probe
+    
+    Use devm_of_iomap() instead of of_iomap() to automatically
+    handle the unused ioremap region. If any error occurs, regions allocated by
+    kzalloc() will leak, but using devm_kzalloc() instead will automatically
+    free the memory using devm_kfree().
+    
+    Also, fix error handling of hws by adding unregister_hws label, which
+    unregisters remaining hws when iomap failed.
+    
+    Fixes: 7154b046d8f3 ("clk: imx: Add initial support for i.MXRT1050 clock driver")
+    Signed-off-by: Kai Ma 
+    Reviewed-by: Peng Fan 
+    Acked-by: Jesse Taube 
+    Reviewed-by: Abel Vesa 
+    Link: https://lore.kernel.org/r/20230418113451.151312-1-kaima@hust.edu.cn
+    Signed-off-by: Abel Vesa 
+
+diff --git a/drivers/clk/imx/clk-imxrt1050.c b/drivers/clk/imx/clk-imxrt1050.c
+index fd5c51fc92c0..08d155feb035 100644
+--- a/drivers/clk/imx/clk-imxrt1050.c
++++ b/drivers/clk/imx/clk-imxrt1050.c
+@@ -42,7 +42,7 @@ static int imxrt1050_clocks_probe(struct platform_device *pdev)
+ 	struct device_node *anp;
+ 	int ret;
+ 
+-	clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
++	clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws,
+ 					  IMXRT1050_CLK_END), GFP_KERNEL);
+ 	if (WARN_ON(!clk_hw_data))
+ 		return -ENOMEM;
+@@ -53,10 +53,12 @@ static int imxrt1050_clocks_probe(struct platform_device *pdev)
+ 	hws[IMXRT1050_CLK_OSC] = imx_get_clk_hw_by_name(np, "osc");
+ 
+ 	anp = of_find_compatible_node(NULL, NULL, "fsl,imxrt-anatop");
+-	pll_base = of_iomap(anp, 0);
++	pll_base = devm_of_iomap(dev, anp, 0, NULL);
+ 	of_node_put(anp);
+-	if (WARN_ON(!pll_base))
+-		return -ENOMEM;
++	if (WARN_ON(IS_ERR(pll_base))) {
++		ret = PTR_ERR(pll_base);
++		goto unregister_hws;
++	}
+ 
+ 	/* Anatop clocks */
+ 	hws[IMXRT1050_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0UL);
+@@ -104,8 +106,10 @@ static int imxrt1050_clocks_probe(struct platform_device *pdev)
+ 
+ 	/* CCM clocks */
+ 	ccm_base = devm_platform_ioremap_resource(pdev, 0);
+-	if (WARN_ON(IS_ERR(ccm_base)))
+-		return PTR_ERR(ccm_base);
++	if (WARN_ON(IS_ERR(ccm_base))) {
++		ret = PTR_ERR(ccm_base);
++		goto unregister_hws;
++	}
+ 
+ 	hws[IMXRT1050_CLK_ARM_PODF] = imx_clk_hw_divider("arm_podf", "pll1_arm", ccm_base + 0x10, 0, 3);
+ 	hws[IMXRT1050_CLK_PRE_PERIPH_SEL] = imx_clk_hw_mux("pre_periph_sel", ccm_base + 0x18, 18, 2,
+@@ -149,8 +153,12 @@ static int imxrt1050_clocks_probe(struct platform_device *pdev)
+ 	ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
+ 	if (ret < 0) {
+ 		dev_err(dev, "Failed to register clks for i.MXRT1050.\n");
+-		imx_unregister_hw_clocks(hws, IMXRT1050_CLK_END);
++		goto unregister_hws;
+ 	}
++	return 0;
++
++unregister_hws:
++	imx_unregister_hw_clocks(hws, IMXRT1050_CLK_END);
+ 	return ret;
+ }
+ static const struct of_device_id imxrt1050_clk_of_match[] = {

commit 342161c11403ea00e9febc16baab1d883d589d04
+Author: Li Yang 
+Date:   Thu Apr 20 22:08:31 2023 +0800
+
+    usb: phy: phy-tahvo: fix memory leak in tahvo_usb_probe()
+    
+    Smatch reports:
+    drivers/usb/phy/phy-tahvo.c: tahvo_usb_probe()
+    warn: missing unwind goto?
+    
+    After geting irq, if ret < 0, it will return without error handling to
+    free memory.
+    Just add error handling to fix this problem.
+    
+    Fixes: 0d45a1373e66 ("usb: phy: tahvo: add IRQ check")
+    Signed-off-by: Li Yang 
+    Reviewed-by: Dongliang Mu 
+    Link: https://lore.kernel.org/r/20230420140832.9110-1-lidaxian@hust.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/phy/phy-tahvo.c b/drivers/usb/phy/phy-tahvo.c
+index 47562d49dfc1..5cac31c6029b 100644
+--- a/drivers/usb/phy/phy-tahvo.c
++++ b/drivers/usb/phy/phy-tahvo.c
+@@ -391,7 +391,7 @@ static int tahvo_usb_probe(struct platform_device *pdev)
+ 
+ 	tu->irq = ret = platform_get_irq(pdev, 0);
+ 	if (ret < 0)
+-		return ret;
++		goto err_remove_phy;
+ 	ret = request_threaded_irq(tu->irq, NULL, tahvo_usb_vbus_interrupt,
+ 				   IRQF_ONESHOT,
+ 				   "tahvo-vbus", tu);

commit c60738de85f40b0b9f5cb23c21f9246e5a47908c
+Author: Junyan Ye 
+Date:   Mon May 8 12:36:41 2023 +0800
+
+    PCI: ftpci100: Release the clock resources
+    
+    Smatch reported:
+    1. drivers/pci/controller/pci-ftpci100.c:526 faraday_pci_probe() warn:
+    'clk' from clk_prepare_enable() not released on lines: 442,451,462,478,512,517.
+    2. drivers/pci/controller/pci-ftpci100.c:526 faraday_pci_probe() warn:
+    'p->bus_clk' from clk_prepare_enable() not released on lines: 451,462,478,512,517.
+    
+    The clock resource is obtained by devm_clk_get(), and then
+    clk_prepare_enable() makes the clock resource ready for use. After that,
+    clk_disable_unprepare() should be called to release the clock resource
+    when it is no longer needed. However, while doing some error handling
+    in faraday_pci_probe(), clk_disable_unprepare() is not called to release
+    clk and p->bus_clk before returning. These return lines are exactly 442,
+    451, 462, 478, 512, 517.
+    
+    Fix this warning by replacing devm_clk_get() with devm_clk_get_enabled(),
+    which is equivalent to devm_clk_get() + clk_prepare_enable(). And with
+    devm_clk_get_enabled(), the clock will automatically be disabled,
+    unprepared and freed when the device is unbound from the bus.
+    
+    Link: https://lore.kernel.org/r/20230508043641.23807-1-yejunyan@hust.edu.cn
+    Fixes: b3c433efb8a3 ("PCI: faraday: Fix wrong pointer passed to PTR_ERR()")
+    Fixes: 2eeb02b28579 ("PCI: faraday: Add clock handling")
+    Fixes: 783a862563f7 ("PCI: faraday: Use pci_parse_request_of_pci_ranges()")
+    Fixes: d3c68e0a7e34 ("PCI: faraday: Add Faraday Technology FTPCI100 PCI Host Bridge driver")
+    Fixes: f1e8bd21e39e ("PCI: faraday: Convert IRQ masking to raw PCI config accessors")
+    Signed-off-by: Junyan Ye 
+    Signed-off-by: Lorenzo Pieralisi 
+    Reviewed-by: Dongliang Mu 
+    Reviewed-by: Linus Walleij 
+
+diff --git a/drivers/pci/controller/pci-ftpci100.c b/drivers/pci/controller/pci-ftpci100.c
+index ecd3009df586..6e7981d2ed5e 100644
+--- a/drivers/pci/controller/pci-ftpci100.c
++++ b/drivers/pci/controller/pci-ftpci100.c
+@@ -429,22 +429,12 @@ static int faraday_pci_probe(struct platform_device *pdev)
+ 	p->dev = dev;
+ 
+ 	/* Retrieve and enable optional clocks */
+-	clk = devm_clk_get(dev, "PCLK");
++	clk = devm_clk_get_enabled(dev, "PCLK");
+ 	if (IS_ERR(clk))
+ 		return PTR_ERR(clk);
+-	ret = clk_prepare_enable(clk);
+-	if (ret) {
+-		dev_err(dev, "could not prepare PCLK\n");
+-		return ret;
+-	}
+-	p->bus_clk = devm_clk_get(dev, "PCICLK");
++	p->bus_clk = devm_clk_get_enabled(dev, "PCICLK");
+ 	if (IS_ERR(p->bus_clk))
+ 		return PTR_ERR(p->bus_clk);
+-	ret = clk_prepare_enable(p->bus_clk);
+-	if (ret) {
+-		dev_err(dev, "could not prepare PCICLK\n");
+-		return ret;
+-	}
+ 
+ 	p->base = devm_platform_ioremap_resource(pdev, 0);
+ 	if (IS_ERR(p->base))

commit 072210c725c4938682e58236eeeb19a2ddd0b817
+Author: Dongliang Mu 
+Date:   Thu Mar 16 21:32:36 2023 +0800
+
+    wifi: ray_cs: add sanity check on local->sram/rmem/amem
+    
+    The ray_config uses ray_release as its unified error handling function.
+    However, it does not know if local->sram/rmem/amem succeeds or not.
+    
+    Fix this by adding sanity check on local->sram/rmem/amem in the
+    ray_relase.
+    
+    Signed-off-by: Dongliang Mu 
+    Signed-off-by: Kalle Valo 
+    Link: https://lore.kernel.org/r/20230316133236.556198-3-dzm91@hust.edu.cn
+
+diff --git a/drivers/net/wireless/legacy/ray_cs.c b/drivers/net/wireless/legacy/ray_cs.c
+index 93eaf3dba6a9..4b53a9c70e7e 100644
+--- a/drivers/net/wireless/legacy/ray_cs.c
++++ b/drivers/net/wireless/legacy/ray_cs.c
+@@ -738,9 +738,12 @@ static void ray_release(struct pcmcia_device *link)
+ 
+ 	del_timer_sync(&local->timer);
+ 
+-	iounmap(local->sram);
+-	iounmap(local->rmem);
+-	iounmap(local->amem);
++	if (local->sram)
++		iounmap(local->sram);
++	if (local->rmem)
++		iounmap(local->rmem);
++	if (local->amem)
++		iounmap(local->amem);
+ 	pcmcia_disable_device(link);
+ 
+ 	dev_dbg(&link->dev, "ray_release ending\n");

commit daef020558bc34e8031263aa7cf9e803d709f93a
+Author: Dongliang Mu 
+Date:   Thu Mar 16 21:32:35 2023 +0800
+
+    wifi: ray_cs: remove one redundant del_timer
+    
+    In ray_detach, it and its child function ray_release both call
+    del_timer(_sync) on the same timer.
+    
+    Fix this by removing the del_timer_sync in the ray_detach, and revising
+    the del_timer to del_timer_sync.
+    
+    Signed-off-by: Dongliang Mu 
+    Signed-off-by: Kalle Valo 
+    Link: https://lore.kernel.org/r/20230316133236.556198-2-dzm91@hust.edu.cn
+
+diff --git a/drivers/net/wireless/legacy/ray_cs.c b/drivers/net/wireless/legacy/ray_cs.c
+index 38782d4c4694..93eaf3dba6a9 100644
+--- a/drivers/net/wireless/legacy/ray_cs.c
++++ b/drivers/net/wireless/legacy/ray_cs.c
+@@ -328,7 +328,6 @@ static int ray_probe(struct pcmcia_device *p_dev)
+ static void ray_detach(struct pcmcia_device *link)
+ {
+ 	struct net_device *dev;
+-	ray_dev_t *local;
+ 
+ 	dev_dbg(&link->dev, "ray_detach\n");
+ 
+@@ -337,9 +336,6 @@ static void ray_detach(struct pcmcia_device *link)
+ 
+ 	ray_release(link);
+ 
+-	local = netdev_priv(dev);
+-	del_timer_sync(&local->timer);
+-
+ 	if (link->priv) {
+ 		unregister_netdev(dev);
+ 		free_netdev(dev);
+@@ -740,7 +736,7 @@ static void ray_release(struct pcmcia_device *link)
+ 
+ 	dev_dbg(&link->dev, "ray_release\n");
+ 
+-	del_timer(&local->timer);
++	del_timer_sync(&local->timer);
+ 
+ 	iounmap(local->sram);
+ 	iounmap(local->rmem);

commit 2e2fe5ac695a00ab03cab4db1f4d6be07168ed9d
+Author: Yuchen Yang 
+Date:   Fri May 5 22:12:55 2023 +0800
+
+    scsi: 3w-xxxx: Add error handling for initialization failure in tw_probe()
+    
+    Smatch complains that:
+    
+    tw_probe() warn: missing error code 'retval'
+    
+    This patch adds error checking to tw_probe() to handle initialization
+    failure. If tw_reset_sequence() function returns a non-zero value, the
+    function will return -EINVAL to indicate initialization failure.
+    
+    Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+    Signed-off-by: Yuchen Yang 
+    Link: https://lore.kernel.org/r/20230505141259.7730-1-u202114568@hust.edu.cn
+    Reviewed-by: Dan Carpenter 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
+index 36c34ced0cc1..f39c9ec2e781 100644
+--- a/drivers/scsi/3w-xxxx.c
++++ b/drivers/scsi/3w-xxxx.c
+@@ -2305,8 +2305,10 @@ static int tw_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
+ 	TW_DISABLE_INTERRUPTS(tw_dev);
+ 
+ 	/* Initialize the card */
+-	if (tw_reset_sequence(tw_dev))
++	if (tw_reset_sequence(tw_dev)) {
++		retval = -EINVAL;
+ 		goto out_release_mem_region;
++	}
+ 
+ 	/* Set host specific parameters */
+ 	host->max_id = TW_MAX_UNITS;

commit ec014683c564fb74fc68e8f5e84691d3b3839d24
+Author: Chao Wang 
+Date:   Mon Apr 17 03:04:21 2023 +0000
+
+    iommu/rockchip: Fix unwind goto issue
+    
+    Smatch complains that
+    drivers/iommu/rockchip-iommu.c:1306 rk_iommu_probe() warn: missing unwind goto?
+    
+    The rk_iommu_probe function, after obtaining the irq value through
+    platform_get_irq, directly returns an error if the returned value
+    is negative, without releasing any resources.
+    
+    Fix this by adding a new error handling label "err_pm_disable" and
+    use a goto statement to redirect to the error handling process. In
+    order to preserve the original semantics, set err to the value of irq.
+    
+    Fixes: 1aa55ca9b14a ("iommu/rockchip: Move irq request past pm_runtime_enable")
+    Signed-off-by: Chao Wang 
+    Reviewed-by: Dongliang Mu 
+    Reviewed-by: Heiko Stuebner 
+    Link: https://lore.kernel.org/r/20230417030421.2777-1-D202280639@hust.edu.cn
+    Signed-off-by: Joerg Roedel 
+
+diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
+index ea5a3088bb7e..4054030c3237 100644
+--- a/drivers/iommu/rockchip-iommu.c
++++ b/drivers/iommu/rockchip-iommu.c
+@@ -1335,20 +1335,22 @@ static int rk_iommu_probe(struct platform_device *pdev)
+ 	for (i = 0; i < iommu->num_irq; i++) {
+ 		int irq = platform_get_irq(pdev, i);
+ 
+-		if (irq < 0)
+-			return irq;
++		if (irq < 0) {
++			err = irq;
++			goto err_pm_disable;
++		}
+ 
+ 		err = devm_request_irq(iommu->dev, irq, rk_iommu_irq,
+ 				       IRQF_SHARED, dev_name(dev), iommu);
+-		if (err) {
+-			pm_runtime_disable(dev);
+-			goto err_remove_sysfs;
+-		}
++		if (err)
++			goto err_pm_disable;
+ 	}
+ 
+ 	dma_set_mask_and_coherent(dev, rk_ops->dma_bit_mask);
+ 
+ 	return 0;
++err_pm_disable:
++	pm_runtime_disable(dev);
+ err_remove_sysfs:
+ 	iommu_device_sysfs_remove(&iommu->iommu);
+ err_put_group:

commit 27b2ed5b6d53cd62fc61c3f259ae52f5cac23b66
+Author: Jiakai Luo 
+Date:   Sat Apr 22 06:34:06 2023 -0700
+
+    iio: adc: mxs-lradc: fix the order of two cleanup operations
+    
+    Smatch reports:
+    drivers/iio/adc/mxs-lradc-adc.c:766 mxs_lradc_adc_probe() warn:
+    missing unwind goto?
+    
+    the order of three init operation:
+    1.mxs_lradc_adc_trigger_init
+    2.iio_triggered_buffer_setup
+    3.mxs_lradc_adc_hw_init
+    
+    thus, the order of three cleanup operation should be:
+    1.mxs_lradc_adc_hw_stop
+    2.iio_triggered_buffer_cleanup
+    3.mxs_lradc_adc_trigger_remove
+    
+    we exchange the order of two cleanup operations,
+    introducing the following differences:
+    1.if mxs_lradc_adc_trigger_init fails, returns directly;
+    2.if trigger_init succeeds but iio_triggered_buffer_setup fails,
+    goto err_trig and remove the trigger.
+    
+    In addition, we also reorder the unwind that goes on in the
+    remove() callback to match the new ordering.
+    
+    Fixes: 6dd112b9f85e ("iio: adc: mxs-lradc: Add support for ADC driver")
+    Signed-off-by: Jiakai Luo 
+    Reviewed-by: Dongliang Mu 
+    Link: https://lore.kernel.org/r/20230422133407.72908-1-jkluo@hust.edu.cn
+    Cc: 
+    Signed-off-by: Jonathan Cameron 
+
+diff --git a/drivers/iio/adc/mxs-lradc-adc.c b/drivers/iio/adc/mxs-lradc-adc.c
+index bca79a93cbe4..a50f39143d3e 100644
+--- a/drivers/iio/adc/mxs-lradc-adc.c
++++ b/drivers/iio/adc/mxs-lradc-adc.c
+@@ -757,13 +757,13 @@ static int mxs_lradc_adc_probe(struct platform_device *pdev)
+ 
+ 	ret = mxs_lradc_adc_trigger_init(iio);
+ 	if (ret)
+-		goto err_trig;
++		return ret;
+ 
+ 	ret = iio_triggered_buffer_setup(iio, &iio_pollfunc_store_time,
+ 					 &mxs_lradc_adc_trigger_handler,
+ 					 &mxs_lradc_adc_buffer_ops);
+ 	if (ret)
+-		return ret;
++		goto err_trig;
+ 
+ 	adc->vref_mv = mxs_lradc_adc_vref_mv[lradc->soc];
+ 
+@@ -801,9 +801,9 @@ static int mxs_lradc_adc_probe(struct platform_device *pdev)
+ 
+ err_dev:
+ 	mxs_lradc_adc_hw_stop(adc);
+-	mxs_lradc_adc_trigger_remove(iio);
+-err_trig:
+ 	iio_triggered_buffer_cleanup(iio);
++err_trig:
++	mxs_lradc_adc_trigger_remove(iio);
+ 	return ret;
+ }
+ 
+@@ -814,8 +814,8 @@ static int mxs_lradc_adc_remove(struct platform_device *pdev)
+ 
+ 	iio_device_unregister(iio);
+ 	mxs_lradc_adc_hw_stop(adc);
+-	mxs_lradc_adc_trigger_remove(iio);
+ 	iio_triggered_buffer_cleanup(iio);
++	mxs_lradc_adc_trigger_remove(iio);
+ 
+ 	return 0;
+ }

commit 8ab5fc55d7f65d58a3c3aeadf11bdf60267cd2bd
+Author: Ke Zhang 
+Date:   Fri Apr 28 11:16:36 2023 +0800
+
+    serial: arc_uart: fix of_iomap leak in `arc_serial_probe`
+    
+    Smatch reports:
+    
+    drivers/tty/serial/arc_uart.c:631 arc_serial_probe() warn:
+    'port->membase' from of_iomap() not released on lines: 631.
+    
+    In arc_serial_probe(), if uart_add_one_port() fails,
+    port->membase is not released, which would cause a resource leak.
+    
+    To fix this, I replace of_iomap with devm_platform_ioremap_resource.
+    
+    Fixes: 8dbe1d5e09a7 ("serial/arc: inline the probe helper")
+    Signed-off-by: Ke Zhang 
+    Reviewed-by: Dongliang Mu 
+    Link: https://lore.kernel.org/r/20230428031636.44642-1-m202171830@hust.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
+index 59e25f2b6632..4b2512eef577 100644
+--- a/drivers/tty/serial/arc_uart.c
++++ b/drivers/tty/serial/arc_uart.c
+@@ -606,10 +606,11 @@ static int arc_serial_probe(struct platform_device *pdev)
+ 	}
+ 	uart->baud = val;
+ 
+-	port->membase = of_iomap(np, 0);
+-	if (!port->membase)
++	port->membase = devm_platform_ioremap_resource(pdev, 0);
++	if (IS_ERR(port->membase)) {
+ 		/* No point of dev_err since UART itself is hosed here */
+-		return -ENXIO;
++		return PTR_ERR(port->membase);
++	}
+ 
+ 	port->irq = irq_of_parse_and_map(np, 0);
+ 

commit 5a6bef734247c7a8c19511664ff77634ab86f45b
+Author: Zongjie Li 
+Date:   Tue May 9 19:27:26 2023 +0800
+
+    fbdev: arcfb: Fix error handling in arcfb_probe()
+    
+    Smatch complains that:
+    arcfb_probe() warn: 'irq' from request_irq() not released on lines: 587.
+    
+    Fix error handling in the arcfb_probe() function. If IO addresses are
+    not provided or framebuffer registration fails, the code will jump to
+    the err_addr or err_register_fb label to release resources.
+    If IRQ request fails, previously allocated resources will be freed.
+    
+    Fixes: 1154ea7dcd8e ("[PATCH] Framebuffer driver for Arc LCD board")
+    Signed-off-by: Zongjie Li 
+    Reviewed-by: Dongliang Mu 
+    Signed-off-by: Helge Deller 
+
+diff --git a/drivers/video/fbdev/arcfb.c b/drivers/video/fbdev/arcfb.c
+index 45e64016db32..024d0ee4f04f 100644
+--- a/drivers/video/fbdev/arcfb.c
++++ b/drivers/video/fbdev/arcfb.c
+@@ -523,7 +523,7 @@ static int arcfb_probe(struct platform_device *dev)
+ 
+ 	info = framebuffer_alloc(sizeof(struct arcfb_par), &dev->dev);
+ 	if (!info)
+-		goto err;
++		goto err_fb_alloc;
+ 
+ 	info->screen_base = (char __iomem *)videomemory;
+ 	info->fbops = &arcfb_ops;
+@@ -535,7 +535,7 @@ static int arcfb_probe(struct platform_device *dev)
+ 
+ 	if (!dio_addr || !cio_addr || !c2io_addr) {
+ 		printk(KERN_WARNING "no IO addresses supplied\n");
+-		goto err1;
++		goto err_addr;
+ 	}
+ 	par->dio_addr = dio_addr;
+ 	par->cio_addr = cio_addr;
+@@ -551,12 +551,12 @@ static int arcfb_probe(struct platform_device *dev)
+ 			printk(KERN_INFO
+ 				"arcfb: Failed req IRQ %d\n", par->irq);
+ 			retval = -EBUSY;
+-			goto err1;
++			goto err_addr;
+ 		}
+ 	}
+ 	retval = register_framebuffer(info);
+ 	if (retval < 0)
+-		goto err1;
++		goto err_register_fb;
+ 	platform_set_drvdata(dev, info);
+ 	fb_info(info, "Arc frame buffer device, using %dK of video memory\n",
+ 		videomemorysize >> 10);
+@@ -580,9 +580,12 @@ static int arcfb_probe(struct platform_device *dev)
+ 	}
+ 
+ 	return 0;
+-err1:
++
++err_register_fb:
++	free_irq(par->irq, info);
++err_addr:
+ 	framebuffer_release(info);
+-err:
++err_fb_alloc:
+ 	vfree(videomemory);
+ 	return retval;
+ }

commit 123ee07ba5b7123e0ce0e0f9d64938026c16a2ce
+Author: XuDong Liu 
+Date:   Sun Apr 30 19:23:46 2023 +0800
+
+    drm: sun4i_tcon: use devm_clk_get_enabled in `sun4i_tcon_init_clocks`
+    
+    Smatch reports:
+    drivers/gpu/drm/sun4i/sun4i_tcon.c:805 sun4i_tcon_init_clocks() warn:
+    'tcon->clk' from clk_prepare_enable() not released on lines: 792,801.
+    
+    In the function sun4i_tcon_init_clocks(), tcon->clk and tcon->sclk0 are
+    not disabled in the error handling, which affects the release of
+    these variable. Although sun4i_tcon_bind(), which calls
+    sun4i_tcon_init_clocks(), use sun4i_tcon_free_clocks to disable the
+    variables mentioned, but the error handling branch of
+    sun4i_tcon_init_clocks() ignores the required disable process.
+    
+    To fix this issue, use the devm_clk_get_enabled to automatically
+    balance enable and disabled calls. As original implementation use
+    sun4i_tcon_free_clocks() to disable clk explicitly, we delete the
+    related calls and error handling that are no longer needed.
+    
+    Fixes: 9026e0d122ac ("drm: Add Allwinner A10 Display Engine support")
+    Fixes: b14e945bda8a ("drm/sun4i: tcon: Prepare and enable TCON channel 0 clock at init")
+    Fixes: 8e9240472522 ("drm/sun4i: support TCONs without channel 1")
+    Fixes: 34d698f6e349 ("drm/sun4i: Add has_channel_0 TCON quirk")
+    Signed-off-by: XuDong Liu 
+    Reviewed-by: Dongliang Mu 
+    Signed-off-by: Maxime Ripard 
+    Link: https://patchwork.freedesktop.org/patch/msgid/20230430112347.4689-1-m202071377@hust.edu.cn
+
+diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
+index b263de7a8237..6a52fb12cbfb 100644
+--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
++++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
+@@ -784,21 +784,19 @@ static irqreturn_t sun4i_tcon_handler(int irq, void *private)
+ static int sun4i_tcon_init_clocks(struct device *dev,
+ 				  struct sun4i_tcon *tcon)
+ {
+-	tcon->clk = devm_clk_get(dev, "ahb");
++	tcon->clk = devm_clk_get_enabled(dev, "ahb");
+ 	if (IS_ERR(tcon->clk)) {
+ 		dev_err(dev, "Couldn't get the TCON bus clock\n");
+ 		return PTR_ERR(tcon->clk);
+ 	}
+-	clk_prepare_enable(tcon->clk);
+ 
+ 	if (tcon->quirks->has_channel_0) {
+-		tcon->sclk0 = devm_clk_get(dev, "tcon-ch0");
++		tcon->sclk0 = devm_clk_get_enabled(dev, "tcon-ch0");
+ 		if (IS_ERR(tcon->sclk0)) {
+ 			dev_err(dev, "Couldn't get the TCON channel 0 clock\n");
+ 			return PTR_ERR(tcon->sclk0);
+ 		}
+ 	}
+-	clk_prepare_enable(tcon->sclk0);
+ 
+ 	if (tcon->quirks->has_channel_1) {
+ 		tcon->sclk1 = devm_clk_get(dev, "tcon-ch1");
+@@ -811,12 +809,6 @@ static int sun4i_tcon_init_clocks(struct device *dev,
+ 	return 0;
+ }
+ 
+-static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon)
+-{
+-	clk_disable_unprepare(tcon->sclk0);
+-	clk_disable_unprepare(tcon->clk);
+-}
+-
+ static int sun4i_tcon_init_irq(struct device *dev,
+ 			       struct sun4i_tcon *tcon)
+ {
+@@ -1229,14 +1221,14 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
+ 	ret = sun4i_tcon_init_regmap(dev, tcon);
+ 	if (ret) {
+ 		dev_err(dev, "Couldn't init our TCON regmap\n");
+-		goto err_free_clocks;
++		goto err_assert_reset;
+ 	}
+ 
+ 	if (tcon->quirks->has_channel_0) {
+ 		ret = sun4i_dclk_create(dev, tcon);
+ 		if (ret) {
+ 			dev_err(dev, "Couldn't create our TCON dot clock\n");
+-			goto err_free_clocks;
++			goto err_assert_reset;
+ 		}
+ 	}
+ 
+@@ -1299,8 +1291,6 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
+ err_free_dclk:
+ 	if (tcon->quirks->has_channel_0)
+ 		sun4i_dclk_free(tcon);
+-err_free_clocks:
+-	sun4i_tcon_free_clocks(tcon);
+ err_assert_reset:
+ 	reset_control_assert(tcon->lcd_rst);
+ 	return ret;
+@@ -1314,7 +1304,6 @@ static void sun4i_tcon_unbind(struct device *dev, struct device *master,
+ 	list_del(&tcon->list);
+ 	if (tcon->quirks->has_channel_0)
+ 		sun4i_dclk_free(tcon);
+-	sun4i_tcon_free_clocks(tcon);
+ }
+ 
+ static const struct component_ops sun4i_tcon_ops = {

commit f025312b089474a54e4859f3453771314d9e3d4f
+Author: Jinhong Zhu 
+Date:   Tue May 2 22:00:21 2023 +0800
+
+    scsi: qedf: Fix NULL dereference in error handling
+    
+    Smatch reported:
+    
+    drivers/scsi/qedf/qedf_main.c:3056 qedf_alloc_global_queues()
+    warn: missing unwind goto?
+    
+    At this point in the function, nothing has been allocated so we can return
+    directly. In particular the "qedf->global_queues" have not been allocated
+    so calling qedf_free_global_queues() will lead to a NULL dereference when
+    we check if (!gl[i]) and "gl" is NULL.
+    
+    Fixes: 61d8658b4a43 ("scsi: qedf: Add QLogic FastLinQ offload FCoE driver framework.")
+    Signed-off-by: Jinhong Zhu 
+    Link: https://lore.kernel.org/r/20230502140022.2852-1-jinhongzhu@hust.edu.cn
+    Reviewed-by: Dan Carpenter 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c
+index 3b64de81ea0d..2a31ddc99dde 100644
+--- a/drivers/scsi/qedf/qedf_main.c
++++ b/drivers/scsi/qedf/qedf_main.c
+@@ -3041,9 +3041,8 @@ static int qedf_alloc_global_queues(struct qedf_ctx *qedf)
+ 	 * addresses of our queues
+ 	 */
+ 	if (!qedf->p_cpuq) {
+-		status = -EINVAL;
+ 		QEDF_ERR(&qedf->dbg_ctx, "p_cpuq is NULL.\n");
+-		goto mem_alloc_failure;
++		return -EINVAL;
+ 	}
+ 
+ 	qedf->global_queues = kzalloc((sizeof(struct global_queue *)

commit f3dc7bb037d813ab7da84f488dd485f0fce66347
+Author: Wang Jikai 
+Date:   Fri Apr 21 09:22:00 2023 +0000
+
+    wifi: mt7601u: delete dead code checking debugfs returns
+    
+    Smatch reports that:
+    drivers/net/wireless/mediatek/mt7601u/debugfs.c:130
+    mt7601u_init_debugfs() warn: 'dir' is an error pointer or valid".
+    
+    Debugfs code is not supposed to need error checking so instead of
+    changing this to if (IS_ERR()) the correct thing is to just delete
+    the dead code.
+    
+    Signed-off-by: Wang Jikai 
+    Acked-by: Jakub Kicinski 
+    Signed-off-by: Kalle Valo 
+    Link: https://lore.kernel.org/r/20230421092200.24456-1-wangjikai@hust.edu.cn
+
+diff --git a/drivers/net/wireless/mediatek/mt7601u/debugfs.c b/drivers/net/wireless/mediatek/mt7601u/debugfs.c
+index 230b0e1061a7..dbddf256921b 100644
+--- a/drivers/net/wireless/mediatek/mt7601u/debugfs.c
++++ b/drivers/net/wireless/mediatek/mt7601u/debugfs.c
+@@ -127,8 +127,6 @@ void mt7601u_init_debugfs(struct mt7601u_dev *dev)
+ 	struct dentry *dir;
+ 
+ 	dir = debugfs_create_dir("mt7601u", dev->hw->wiphy->debugfsdir);
+-	if (!dir)
+-		return;
+ 
+ 	debugfs_create_u8("temperature", 0400, dir, &dev->raw_temp);
+ 	debugfs_create_u32("temp_mode", 0400, dir, &dev->temp_mode);

commit 0d727e1856ef22dd9337199430258cb64cbbc658
+Author: Ruliang Lin 
+Date:   Thu May 4 14:50:53 2023 +0800
+
+    ALSA: caiaq: input: Add error handling for unsupported input methods in `snd_usb_caiaq_input_init`
+    
+    Smatch complains that:
+    snd_usb_caiaq_input_init() warn: missing error code 'ret'
+    
+    This patch adds a new case to handle the situation where the
+    device does not support any input methods in the
+    `snd_usb_caiaq_input_init` function. It returns an `-EINVAL` error code
+    to indicate that no input methods are supported on the device.
+    
+    Fixes: 523f1dce3743 ("[ALSA] Add Native Instrument usb audio device support")
+    Signed-off-by: Ruliang Lin 
+    Reviewed-by: Dongliang Mu 
+    Acked-by: Daniel Mack 
+    Link: https://lore.kernel.org/r/20230504065054.3309-1-u202112092@hust.edu.cn
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/usb/caiaq/input.c b/sound/usb/caiaq/input.c
+index 1e2cf2f08eec..84f26dce7f5d 100644
+--- a/sound/usb/caiaq/input.c
++++ b/sound/usb/caiaq/input.c
+@@ -804,6 +804,7 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *cdev)
+ 
+ 	default:
+ 		/* no input methods supported on this device */
++		ret = -EINVAL;
+ 		goto exit_free_idev;
+ 	}
+ 

commit a3e9a9a5971164933e0d247125897c2e54587c6b
+Author: Kang Chen 
+Date:   Wed Apr 19 10:07:49 2023 +0800
+
+    thermal/drivers/mediatek: Change clk_prepare_enable to devm_clk_get_enabled in mtk_thermal_probe
+    
+    Use devm_clk_get_enabled to do automatic resource management.
+    Meanwhile, remove error handling labels in the probe function and
+    the whole remove function.
+    
+    Signed-off-by: Kang Chen 
+    Reviewed-by: Dongliang Mu 
+    Signed-off-by: Daniel Lezcano 
+    Link: https://lore.kernel.org/r/20230419020749.621257-2-void0red@hust.edu.cn
+
+diff --git a/drivers/thermal/mediatek/auxadc_thermal.c b/drivers/thermal/mediatek/auxadc_thermal.c
+index 49bcd5304802..b59fe4307b0a 100644
+--- a/drivers/thermal/mediatek/auxadc_thermal.c
++++ b/drivers/thermal/mediatek/auxadc_thermal.c
+@@ -1206,14 +1206,6 @@ static int mtk_thermal_probe(struct platform_device *pdev)
+ 
+ 	mt->conf = of_device_get_match_data(&pdev->dev);
+ 
+-	mt->clk_peri_therm = devm_clk_get(&pdev->dev, "therm");
+-	if (IS_ERR(mt->clk_peri_therm))
+-		return PTR_ERR(mt->clk_peri_therm);
+-
+-	mt->clk_auxadc = devm_clk_get(&pdev->dev, "auxadc");
+-	if (IS_ERR(mt->clk_auxadc))
+-		return PTR_ERR(mt->clk_auxadc);
+-
+ 	mt->thermal_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
+ 	if (IS_ERR(mt->thermal_base))
+ 		return PTR_ERR(mt->thermal_base);
+@@ -1272,16 +1264,18 @@ static int mtk_thermal_probe(struct platform_device *pdev)
+ 	if (ret)
+ 		return ret;
+ 
+-	ret = clk_prepare_enable(mt->clk_auxadc);
+-	if (ret) {
++	mt->clk_auxadc = devm_clk_get_enabled(&pdev->dev, "auxadc");
++	if (IS_ERR(mt->clk_auxadc)) {
++		ret = PTR_ERR(mt->clk_auxadc);
+ 		dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret);
+ 		return ret;
+ 	}
+ 
+-	ret = clk_prepare_enable(mt->clk_peri_therm);
+-	if (ret) {
++	mt->clk_peri_therm = devm_clk_get_enabled(&pdev->dev, "therm");
++	if (IS_ERR(mt->clk_peri_therm)) {
++		ret = PTR_ERR(mt->clk_peri_therm);
+ 		dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret);
+-		goto err_disable_clk_auxadc;
++		return ret;
+ 	}
+ 
+ 	mtk_thermal_turn_on_buffer(mt, apmixed_base);
+@@ -1305,38 +1299,18 @@ static int mtk_thermal_probe(struct platform_device *pdev)
+ 
+ 	tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt,
+ 					      &mtk_thermal_ops);
+-	if (IS_ERR(tzdev)) {
+-		ret = PTR_ERR(tzdev);
+-		goto err_disable_clk_peri_therm;
+-	}
++	if (IS_ERR(tzdev))
++		return PTR_ERR(tzdev);
+ 
+ 	ret = devm_thermal_add_hwmon_sysfs(&pdev->dev, tzdev);
+ 	if (ret)
+ 		dev_warn(&pdev->dev, "error in thermal_add_hwmon_sysfs");
+ 
+ 	return 0;
+-
+-err_disable_clk_peri_therm:
+-	clk_disable_unprepare(mt->clk_peri_therm);
+-err_disable_clk_auxadc:
+-	clk_disable_unprepare(mt->clk_auxadc);
+-
+-	return ret;
+-}
+-
+-static int mtk_thermal_remove(struct platform_device *pdev)
+-{
+-	struct mtk_thermal *mt = platform_get_drvdata(pdev);
+-
+-	clk_disable_unprepare(mt->clk_peri_therm);
+-	clk_disable_unprepare(mt->clk_auxadc);
+-
+-	return 0;
+ }
+ 
+ static struct platform_driver mtk_thermal_driver = {
+ 	.probe = mtk_thermal_probe,
+-	.remove = mtk_thermal_remove,
+ 	.driver = {
+ 		.name = "mtk-thermal",
+ 		.of_match_table = mtk_thermal_of_match,

commit f05c7b7d9ea9477fcc388476c6f4ade8c66d2d26
+Author: Kang Chen 
+Date:   Wed Apr 19 10:07:48 2023 +0800
+
+    thermal/drivers/mediatek: Use devm_of_iomap to avoid resource leak in mtk_thermal_probe
+    
+    Smatch reports:
+    1. mtk_thermal_probe() warn: 'apmixed_base' from of_iomap() not released.
+    2. mtk_thermal_probe() warn: 'auxadc_base' from of_iomap() not released.
+    
+    The original code forgets to release iomap resource when handling errors,
+    fix it by switch to devm_of_iomap.
+    
+    Fixes: 89945047b166 ("thermal: mediatek: Add tsensor support for V2 thermal system")
+    Signed-off-by: Kang Chen 
+    Reviewed-by: Dongliang Mu 
+    Reviewed-by: AngeloGioacchino Del Regno 
+    Signed-off-by: Daniel Lezcano 
+    Link: https://lore.kernel.org/r/20230419020749.621257-1-void0red@hust.edu.cn
+
+diff --git a/drivers/thermal/mediatek/auxadc_thermal.c b/drivers/thermal/mediatek/auxadc_thermal.c
+index e908c8e9d558..49bcd5304802 100644
+--- a/drivers/thermal/mediatek/auxadc_thermal.c
++++ b/drivers/thermal/mediatek/auxadc_thermal.c
+@@ -1232,7 +1232,12 @@ static int mtk_thermal_probe(struct platform_device *pdev)
+ 		return -ENODEV;
+ 	}
+ 
+-	auxadc_base = of_iomap(auxadc, 0);
++	auxadc_base = devm_of_iomap(&pdev->dev, auxadc, 0, NULL);
++	if (IS_ERR(auxadc_base)) {
++		of_node_put(auxadc);
++		return PTR_ERR(auxadc_base);
++	}
++
+ 	auxadc_phys_base = of_get_phys_base(auxadc);
+ 
+ 	of_node_put(auxadc);
+@@ -1248,7 +1253,12 @@ static int mtk_thermal_probe(struct platform_device *pdev)
+ 		return -ENODEV;
+ 	}
+ 
+-	apmixed_base = of_iomap(apmixedsys, 0);
++	apmixed_base = devm_of_iomap(&pdev->dev, apmixedsys, 0, NULL);
++	if (IS_ERR(apmixed_base)) {
++		of_node_put(apmixedsys);
++		return PTR_ERR(apmixed_base);
++	}
++
+ 	apmixed_phys_base = of_get_phys_base(apmixedsys);
+ 
+ 	of_node_put(apmixedsys);

commit d325c34d9e7e38d371c0a299d415e9b07f66a1fb
+Author: Gencen Gan 
+Date:   Mon Apr 24 23:28:01 2023 +0800
+
+    net: amd: Fix link leak when verifying config failed
+    
+    After failing to verify configuration, it returns directly without
+    releasing link, which may cause memory leak.
+    
+    Paolo Abeni thinks that the whole code of this driver is quite
+    "suboptimal" and looks unmainatained since at least ~15y, so he
+    suggests that we could simply remove the whole driver, please
+    take it into consideration.
+    
+    Simon Horman suggests that the fix label should be set to
+    "Linux-2.6.12-rc2" considering that the problem has existed
+    since the driver was introduced and the commit above doesn't
+    seem to exist in net/net-next.
+    
+    Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+    Signed-off-by: Gan Gecen 
+    Reviewed-by: Dongliang Mu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/amd/nmclan_cs.c b/drivers/net/ethernet/amd/nmclan_cs.c
+index 823a329a921f..0dd391c84c13 100644
+--- a/drivers/net/ethernet/amd/nmclan_cs.c
++++ b/drivers/net/ethernet/amd/nmclan_cs.c
+@@ -651,7 +651,7 @@ static int nmclan_config(struct pcmcia_device *link)
+     } else {
+       pr_notice("mace id not found: %x %x should be 0x40 0x?9\n",
+ 		sig[0], sig[1]);
+-      return -ENODEV;
++      goto failed;
+     }
+   }
+ 

commit e515c330d7e22692d03475740fa45d179281cdf7
+Author: Jianuo Kuang 
+Date:   Mon Apr 24 10:41:40 2023 +0800
+
+    drivers: nfc: nfcsim: remove return value check of `dev_dir`
+    
+    Smatch complains that:
+    nfcsim_debugfs_init_dev() warn: 'dev_dir' is an error pointer or valid
+    
+    According to the documentation of the debugfs_create_dir() function,
+    there is no need to check the return value of this function.
+    Just delete the dead code.
+    
+    Signed-off-by: Jianuo Kuang 
+    Reviewed-by: Dongliang Mu 
+    Reviewed-by: Krzysztof Kozlowski 
+    Link: https://lore.kernel.org/r/20230424024140.34607-1-u202110722@hust.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/drivers/nfc/nfcsim.c b/drivers/nfc/nfcsim.c
+index 85bf8d586c70..44eeb17ae48d 100644
+--- a/drivers/nfc/nfcsim.c
++++ b/drivers/nfc/nfcsim.c
+@@ -367,11 +367,6 @@ static void nfcsim_debugfs_init_dev(struct nfcsim *dev)
+ 	}
+ 
+ 	dev_dir = debugfs_create_dir(devname, nfcsim_debugfs_root);
+-	if (!dev_dir) {
+-		NFCSIM_ERR(dev, "Could not create debugfs entries for nfc%d\n",
+-			   idx);
+-		return;
+-	}
+ 
+ 	debugfs_create_u8("dropframe", 0664, dev_dir, &dev->dropframe);
+ }

commit fb73556386e074e9bee9fa2d253aeaefe4e063e0
+Author: Qinrun Dai 
+Date:   Thu Apr 13 13:50:37 2023 +0000
+
+    clocksource/drivers/davinci: Fix memory leak in davinci_timer_register when init fails
+    
+    Smatch reports:
+    drivers/clocksource/timer-davinci.c:332 davinci_timer_register()
+    warn: 'base' from ioremap() not released on lines: 274.
+    
+    Fix this and other potential memory leak problems
+    by adding a set of corresponding exit lables.
+    
+    Fixes: 721154f972aa ("clocksource/drivers/davinci: Add support for clockevents")
+    Signed-off-by: Qinrun Dai 
+    Link: https://lore.kernel.org/r/20230413135037.1505799-1-flno@hust.edu.cn
+    Signed-off-by: Daniel Lezcano 
+
+diff --git a/drivers/clocksource/timer-davinci.c b/drivers/clocksource/timer-davinci.c
+index 9996c0542520..b1c248498be4 100644
+--- a/drivers/clocksource/timer-davinci.c
++++ b/drivers/clocksource/timer-davinci.c
+@@ -257,21 +257,25 @@ int __init davinci_timer_register(struct clk *clk,
+ 				resource_size(&timer_cfg->reg),
+ 				"davinci-timer")) {
+ 		pr_err("Unable to request memory region\n");
+-		return -EBUSY;
++		rv = -EBUSY;
++		goto exit_clk_disable;
+ 	}
+ 
+ 	base = ioremap(timer_cfg->reg.start, resource_size(&timer_cfg->reg));
+ 	if (!base) {
+ 		pr_err("Unable to map the register range\n");
+-		return -ENOMEM;
++		rv = -ENOMEM;
++		goto exit_mem_region;
+ 	}
+ 
+ 	davinci_timer_init(base);
+ 	tick_rate = clk_get_rate(clk);
+ 
+ 	clockevent = kzalloc(sizeof(*clockevent), GFP_KERNEL);
+-	if (!clockevent)
+-		return -ENOMEM;
++	if (!clockevent) {
++		rv = -ENOMEM;
++		goto exit_iounmap_base;
++	}
+ 
+ 	clockevent->dev.name = "tim12";
+ 	clockevent->dev.features = CLOCK_EVT_FEAT_ONESHOT;
+@@ -296,7 +300,7 @@ int __init davinci_timer_register(struct clk *clk,
+ 			 "clockevent/tim12", clockevent);
+ 	if (rv) {
+ 		pr_err("Unable to request the clockevent interrupt\n");
+-		return rv;
++		goto exit_free_clockevent;
+ 	}
+ 
+ 	davinci_clocksource.dev.rating = 300;
+@@ -323,13 +327,27 @@ int __init davinci_timer_register(struct clk *clk,
+ 	rv = clocksource_register_hz(&davinci_clocksource.dev, tick_rate);
+ 	if (rv) {
+ 		pr_err("Unable to register clocksource\n");
+-		return rv;
++		goto exit_free_irq;
+ 	}
+ 
+ 	sched_clock_register(davinci_timer_read_sched_clock,
+ 			     DAVINCI_TIMER_CLKSRC_BITS, tick_rate);
+ 
+ 	return 0;
++
++exit_free_irq:
++	free_irq(timer_cfg->irq[DAVINCI_TIMER_CLOCKEVENT_IRQ].start,
++			clockevent);
++exit_free_clockevent:
++	kfree(clockevent);
++exit_iounmap_base:
++	iounmap(base);
++exit_mem_region:
++	release_mem_region(timer_cfg->reg.start,
++			   resource_size(&timer_cfg->reg));
++exit_clk_disable:
++	clk_disable_unprepare(clk);
++	return rv;
+ }
+ 
+ static int __init of_davinci_timer_register(struct device_node *np)

commit d184d60aa301e424cd0cf7de90b40744710a2417
+Author: Zhengkang Huang 
+Date:   Wed Apr 19 18:03:03 2023 +0800
+
+    platform/chrome: wilco_ec: remove return value check of debugfs_create_dir()
+    
+    Smatch complains that:
+    wilco_ec_debugfs_probe() warn: 'debug_info->dir' is an error
+    pointer or valid
+    
+    Debugfs checks are generally not supposed to be checked
+    for errors and it is not necessary here.
+    
+    Just delete the dead code.
+    
+    Signed-off-by: Zhengkang Huang 
+    Reviewed-by: Dongliang Mu 
+    Signed-off-by: Tzung-Bi Shih 
+    Link: https://lore.kernel.org/r/20230419100303.343379-1-zkhuang@hust.edu.cn
+
+diff --git a/drivers/platform/chrome/wilco_ec/debugfs.c b/drivers/platform/chrome/wilco_ec/debugfs.c
+index a812788a0bdc..7a13f13b16cd 100644
+--- a/drivers/platform/chrome/wilco_ec/debugfs.c
++++ b/drivers/platform/chrome/wilco_ec/debugfs.c
+@@ -251,8 +251,6 @@ static int wilco_ec_debugfs_probe(struct platform_device *pdev)
+ 		return 0;
+ 	debug_info->ec = ec;
+ 	debug_info->dir = debugfs_create_dir("wilco_ec", NULL);
+-	if (!debug_info->dir)
+-		return 0;
+ 	debugfs_create_file("raw", 0644, debug_info->dir, NULL, &fops_raw);
+ 	debugfs_create_file("h1_gpio", 0444, debug_info->dir, ec,
+ 			    &fops_h1_gpio);

commit 3c690a0d64f5964977050a91b6bba8de09c13d94
+Author: Lanzhe Li 
+Date:   Sun Apr 9 21:02:29 2023 +0800
+
+    Bluetooth: fix inconsistent indenting
+    
+    Fixed a wrong indentation before "return".This line uses a 7 space
+    indent instead of a tab.
+    
+    Signed-off-by: Lanzhe Li 
+    Signed-off-by: Luiz Augusto von Dentz 
+
+diff --git a/net/bluetooth/hci_debugfs.c b/net/bluetooth/hci_debugfs.c
+index b7f682922a16..ec0df2f9188e 100644
+--- a/net/bluetooth/hci_debugfs.c
++++ b/net/bluetooth/hci_debugfs.c
+@@ -189,7 +189,7 @@ static int uuids_show(struct seq_file *f, void *p)
+ 	}
+ 	hci_dev_unlock(hdev);
+ 
+-       return 0;
++	return 0;
+ }
+ 
+ DEFINE_SHOW_ATTRIBUTE(uuids);

commit b148b9abc8444c9e0579a6bbe47b2da6adf5a150
+Author: Wang Zhang 
+Date:   Fri Apr 21 23:10:09 2023 +0800
+
+    net: ethernet: mediatek: remove return value check of `mtk_wed_hw_add_debugfs`
+    
+    Smatch complains that:
+    mtk_wed_hw_add_debugfs() warn: 'dir' is an error pointer or valid
+    
+    Debugfs checks are generally not supposed to be checked
+    for errors and it is not necessary here.
+    
+    fix it by just deleting the dead code.
+    
+    Signed-off-by: Wang Zhang 
+    Reviewed-by: Dongliang Mu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
+index 56f663439721..b244c02c5b51 100644
+--- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
++++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
+@@ -252,8 +252,6 @@ void mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw)
+ 
+ 	snprintf(hw->dirname, sizeof(hw->dirname), "wed%d", hw->index);
+ 	dir = debugfs_create_dir(hw->dirname, NULL);
+-	if (!dir)
+-		return;
+ 
+ 	hw->debugfs_dir = dir;
+ 	debugfs_create_u32("regidx", 0600, dir, &hw->debugfs_reg);

commit eb74bfcfa99415f1a65ce021b8ac2256b7ed50bc
+Author: Yingsha Xu 
+Date:   Wed Apr 19 18:45:47 2023 +0800
+
+    wifi: mac80211: remove return value check of debugfs_create_dir()
+    
+    Smatch complains that:
+    debugfs_hw_add() warn: 'statsd' is an error pointer or valid
+    
+    Debugfs checks are generally not supposed to be checked for errors
+    and it is not necessary here.
+    
+    Just delete the dead code.
+    
+    Signed-off-by: Yingsha Xu 
+    Reviewed-by: Dongliang Mu 
+    Link: https://lore.kernel.org/r/20230419104548.30124-1-ysxu@hust.edu.cn
+    Signed-off-by: Johannes Berg 
+
+diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
+index dfb9f55e2685..207f772bd8ce 100644
+--- a/net/mac80211/debugfs.c
++++ b/net/mac80211/debugfs.c
+@@ -673,10 +673,6 @@ void debugfs_hw_add(struct ieee80211_local *local)
+ 
+ 	statsd = debugfs_create_dir("statistics", phyd);
+ 
+-	/* if the dir failed, don't put all the other things into the root! */
+-	if (!statsd)
+-		return;
+-
+ #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+ 	DEBUGFS_STATS_ADD(dot11TransmittedFragmentCount);
+ 	DEBUGFS_STATS_ADD(dot11MulticastTransmittedFrameCount);

commit d6f712f53b79f5017cdcefafb7a5aea9ec52da5d
+Author: Yinhao Hu 
+Date:   Wed Apr 12 13:58:52 2023 +0800
+
+    usb: chipidea: fix missing goto in `ci_hdrc_probe`
+    
+    From the comment of ci_usb_phy_init, it returns an error code if
+    usb_phy_init has failed, and it should do some clean up, not just
+    return directly.
+    
+    Fix this by goto the error handling.
+    
+    Fixes: 74475ede784d ("usb: chipidea: move PHY operation to core")
+    Reviewed-by: Dongliang Mu 
+    Acked-by: Peter Chen 
+    Signed-off-by: Yinhao Hu 
+    Link: https://lore.kernel.org/r/20230412055852.971991-1-dddddd@hust.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
+index d1d252c87e4f..798cb077867a 100644
+--- a/drivers/usb/chipidea/core.c
++++ b/drivers/usb/chipidea/core.c
+@@ -1108,7 +1108,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
+ 	ret = ci_usb_phy_init(ci);
+ 	if (ret) {
+ 		dev_err(dev, "unable to init phy: %d\n", ret);
+-		return ret;
++		goto ulpi_exit;
+ 	}
+ 
+ 	ci->hw_bank.phys = res->start;

commit 359f5b0d4e26b7a7bcc574d6148b31a17cefe47d
+Author: Li Lanzhe 
+Date:   Wed Apr 19 07:50:29 2023 -0400
+
+    spi: spi-rockchip: Fix missing unwind goto in rockchip_sfc_probe()
+    
+    If devm_request_irq() fails, then we are directly return 'ret' without
+    clk_disable_unprepare(sfc->clk) and clk_disable_unprepare(sfc->hclk).
+    
+    Fix this by changing direct return to a goto 'err_irq'.
+    
+    Fixes: 0b89fc0a367e ("spi: rockchip-sfc: add rockchip serial flash controller")
+    Signed-off-by: Li Lanzhe 
+    Reviewed-by: Dongliang Mu 
+    Link: https://lore.kernel.org/r/20230419115030.6029-1-u202212060@hust.edu.cn
+    Signed-off-by: Mark Brown 
+
+diff --git a/drivers/spi/spi-rockchip-sfc.c b/drivers/spi/spi-rockchip-sfc.c
+index bd87d3c92dd3..69347b6bf60c 100644
+--- a/drivers/spi/spi-rockchip-sfc.c
++++ b/drivers/spi/spi-rockchip-sfc.c
+@@ -632,7 +632,7 @@ static int rockchip_sfc_probe(struct platform_device *pdev)
+ 	if (ret) {
+ 		dev_err(dev, "Failed to request irq\n");
+ 
+-		return ret;
++		goto err_irq;
+ 	}
+ 
+ 	ret = rockchip_sfc_init(sfc);

commit 1c34890273a020d61d6127ade3f68ed1cb21c16a
+Author: Liliang Ye 
+Date:   Mon Apr 3 23:26:47 2023 +0800
+
+    ASoC: fsl_mqs: move of_node_put() to the correct location
+    
+    of_node_put() should have been done directly after
+    mqs_priv->regmap = syscon_node_to_regmap(gpr_np);
+    otherwise it creates a reference leak on the success path.
+    
+    To fix this, of_node_put() is moved to the correct location, and change
+    all the gotos to direct returns.
+    
+    Fixes: a9d273671440 ("ASoC: fsl_mqs: Fix error handling in probe")
+    Signed-off-by: Liliang Ye 
+    Reviewed-by: Dan Carpenter 
+    Link: https://lore.kernel.org/r/20230403152647.17638-1-yll@hust.edu.cn
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/fsl/fsl_mqs.c b/sound/soc/fsl/fsl_mqs.c
+index 3fb3d3e4d09a..49ae7f6267d3 100644
+--- a/sound/soc/fsl/fsl_mqs.c
++++ b/sound/soc/fsl/fsl_mqs.c
+@@ -210,10 +210,10 @@ static int fsl_mqs_probe(struct platform_device *pdev)
+ 		}
+ 
+ 		mqs_priv->regmap = syscon_node_to_regmap(gpr_np);
++		of_node_put(gpr_np);
+ 		if (IS_ERR(mqs_priv->regmap)) {
+ 			dev_err(&pdev->dev, "failed to get gpr regmap\n");
+-			ret = PTR_ERR(mqs_priv->regmap);
+-			goto err_free_gpr_np;
++			return PTR_ERR(mqs_priv->regmap);
+ 		}
+ 	} else {
+ 		regs = devm_platform_ioremap_resource(pdev, 0);
+@@ -242,8 +242,7 @@ static int fsl_mqs_probe(struct platform_device *pdev)
+ 	if (IS_ERR(mqs_priv->mclk)) {
+ 		dev_err(&pdev->dev, "failed to get the clock: %ld\n",
+ 			PTR_ERR(mqs_priv->mclk));
+-		ret = PTR_ERR(mqs_priv->mclk);
+-		goto err_free_gpr_np;
++		return PTR_ERR(mqs_priv->mclk);
+ 	}
+ 
+ 	dev_set_drvdata(&pdev->dev, mqs_priv);
+@@ -252,13 +251,9 @@ static int fsl_mqs_probe(struct platform_device *pdev)
+ 	ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_fsl_mqs,
+ 			&fsl_mqs_dai, 1);
+ 	if (ret)
+-		goto err_free_gpr_np;
+-	return 0;
+-
+-err_free_gpr_np:
+-	of_node_put(gpr_np);
++		return ret;
+ 
+-	return ret;
++	return 0;
+ }
+ 
+ static void fsl_mqs_remove(struct platform_device *pdev)

commit 5c47cdebbaeb7724df6f9f46917c93e53f791547
+Author: Jiefeng Li 
+Date:   Wed Apr 12 14:22:34 2023 +0800
+
+    wifi: mt76: mt7921: fix missing unwind goto in `mt7921u_probe`
+    
+    `mt7921u_dma_init` can only return zero or negative number according to its
+    definition. When it returns non-zero number, there exists an error and this
+    function should handle this error rather than return directly.
+    
+    Fixes: 0d2afe09fad5 ("mt76: mt7921: add mt7921u driver")
+    Signed-off-by: Jiefeng Li 
+    Reviewed-by: Dongliang Mu 
+    Reviewed-by: Sridhar Samudrala 
+    Signed-off-by: Felix Fietkau 
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
+index 9b05e4577cdf..1f302c430339 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
+@@ -259,7 +259,7 @@ static int mt7921u_probe(struct usb_interface *usb_intf,
+ 
+ 	ret = mt7921u_dma_init(dev, false);
+ 	if (ret)
+-		return ret;
++		goto error;
+ 
+ 	hw = mt76_hw(dev);
+ 	/* check hw sg support in order to enable AMSDU */

commit c4a413e56d16a2ae84e6d8992f215c4dcc7fac20
+Author: YAN SHI 
+Date:   Wed Apr 12 11:35:29 2023 +0800
+
+    regulator: stm32-pwr: fix of_iomap leak
+    
+    Smatch reports:
+    drivers/regulator/stm32-pwr.c:166 stm32_pwr_regulator_probe() warn:
+    'base' from of_iomap() not released on lines: 151,166.
+    
+    In stm32_pwr_regulator_probe(), base is not released
+    when devm_kzalloc() fails to allocate memory or
+    devm_regulator_register() fails to register a new regulator device,
+    which may cause a leak.
+    
+    To fix this issue, replace of_iomap() with
+    devm_platform_ioremap_resource(). devm_platform_ioremap_resource()
+    is a specialized function for platform devices.
+    It allows 'base' to be automatically released whether the probe
+    function succeeds or fails.
+    
+    Besides, use IS_ERR(base) instead of !base
+    as the return value of devm_platform_ioremap_resource()
+    can either be a pointer to the remapped memory or
+    an ERR_PTR() encoded error code if the operation fails.
+    
+    Fixes: dc62f951a6a8 ("regulator: stm32-pwr: Fix return value check in stm32_pwr_regulator_probe()")
+    Signed-off-by: YAN SHI 
+    Reported-by: kernel test robot 
+    Link: https://lore.kernel.org/oe-kbuild-all/202304111750.o2643eJN-lkp@intel.com/
+    Reviewed-by: Dongliang Mu 
+    Link: https://lore.kernel.org/r/20230412033529.18890-1-m202071378@hust.edu.cn
+    Signed-off-by: Mark Brown 
+
+diff --git a/drivers/regulator/stm32-pwr.c b/drivers/regulator/stm32-pwr.c
+index 2803a199826f..68aa9d92953d 100644
+--- a/drivers/regulator/stm32-pwr.c
++++ b/drivers/regulator/stm32-pwr.c
+@@ -129,17 +129,16 @@ static const struct regulator_desc stm32_pwr_desc[] = {
+ 
+ static int stm32_pwr_regulator_probe(struct platform_device *pdev)
+ {
+-	struct device_node *np = pdev->dev.of_node;
+ 	struct stm32_pwr_reg *priv;
+ 	void __iomem *base;
+ 	struct regulator_dev *rdev;
+ 	struct regulator_config config = { };
+ 	int i, ret = 0;
+ 
+-	base = of_iomap(np, 0);
+-	if (!base) {
++	base = devm_platform_ioremap_resource(pdev, 0);
++	if (IS_ERR(base)) {
+ 		dev_err(&pdev->dev, "Unable to map IO memory\n");
+-		return -ENOMEM;
++		return PTR_ERR(base);
+ 	}
+ 
+ 	config.dev = &pdev->dev;

commit d93ee84e3eb5d1afc081e57ca37f1411a01f2c94
+Author: Ying Liu 
+Date:   Wed Apr 12 01:09:12 2023 +0800
+
+    ASoC: tas5720: add missing unwind goto in tas5720_codec_probe
+    
+    Smatch complains that missing unwind goto in tas5720_codec_probe.
+    
+    When tas5720 has an invalid devtype, it is expected to invoke
+    regulator_bulk_disable to handle the failure. But the default
+    option return an error code directly. Fix it by reusing the
+    probe_fail label.
+    
+    Signed-off-by: Ying Liu 
+    Link: https://lore.kernel.org/r/20230411170912.1939906-1-lyre@hust.edu.cn
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/codecs/tas5720.c b/sound/soc/codecs/tas5720.c
+index de6d01c8fdd3..4d27b60bd804 100644
+--- a/sound/soc/codecs/tas5720.c
++++ b/sound/soc/codecs/tas5720.c
+@@ -339,7 +339,8 @@ static int tas5720_codec_probe(struct snd_soc_component *component)
+ 		break;
+ 	default:
+ 		dev_err(component->dev, "unexpected private driver data\n");
+-		return -EINVAL;
++		ret = -EINVAL;
++		goto probe_fail;
+ 	}
+ 
+ 	if (device_id != expected_device_id)

commit 8bfb89f6149ea8e790f58abad1f4a84066d86c91
+Author: Jun Chen 
+Date:   Mon Apr 10 10:37:23 2023 +0800
+
+    scsi: lpfc: Silence an incorrect device output
+    
+    In lpfc_sli4_pci_mem_unset(), case LPFC_SLI_INTF_IF_TYPE_1 does not have a
+    break statement, resulting in an incorrect device output.
+    
+    Fix this by adding a break statement before the default option.
+    
+    Signed-off-by: Jun Chen 
+    Link: https://lore.kernel.org/r/20230410023724.3209455-1-jun_c@hust.edu.cn
+    Reviewed-by: Dongliang Mu 
+    Reviewed-by: Justin Tee 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
+index 3b0642dc023b..92e7197087bf 100644
+--- a/drivers/scsi/lpfc/lpfc_init.c
++++ b/drivers/scsi/lpfc/lpfc_init.c
+@@ -12107,6 +12107,7 @@ lpfc_sli4_pci_mem_unset(struct lpfc_hba *phba)
+ 			iounmap(phba->sli4_hba.dpp_regs_memmap_p);
+ 		break;
+ 	case LPFC_SLI_INTF_IF_TYPE_1:
++		break;
+ 	default:
+ 		dev_printk(KERN_ERR, &phba->pcidev->dev,
+ 			   "FATAL - unsupported SLI4 interface type - %d\n",

commit 91a0c0c1413239d0548b5aac4c82f38f6d53a91e
+Author: Shuchang Li 
+Date:   Tue Apr 4 15:21:32 2023 +0800
+
+    scsi: lpfc: Fix ioremap issues in lpfc_sli4_pci_mem_setup()
+    
+    When if_type equals zero and pci_resource_start(pdev, PCI_64BIT_BAR4)
+    returns false, drbl_regs_memmap_p is not remapped. This passes a NULL
+    pointer to iounmap(), which can trigger a WARN() on certain arches.
+    
+    When if_type equals six and pci_resource_start(pdev, PCI_64BIT_BAR4)
+    returns true, drbl_regs_memmap_p may has been remapped and
+    ctrl_regs_memmap_p is not remapped. This is a resource leak and passes a
+    NULL pointer to iounmap().
+    
+    To fix these issues, we need to add null checks before iounmap(), and
+    change some goto labels.
+    
+    Fixes: 1351e69fc6db ("scsi: lpfc: Add push-to-adapter support to sli4")
+    Signed-off-by: Shuchang Li 
+    Link: https://lore.kernel.org/r/20230404072133.1022-1-lishuchang@hust.edu.cn
+    Reviewed-by: Justin Tee 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
+index a9e36c73cfc5..3b0642dc023b 100644
+--- a/drivers/scsi/lpfc/lpfc_init.c
++++ b/drivers/scsi/lpfc/lpfc_init.c
+@@ -12024,7 +12024,7 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba)
+ 				goto out_iounmap_all;
+ 		} else {
+ 			error = -ENOMEM;
+-			goto out_iounmap_all;
++			goto out_iounmap_ctrl;
+ 		}
+ 	}
+ 
+@@ -12042,7 +12042,7 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba)
+ 			dev_err(&pdev->dev,
+ 			   "ioremap failed for SLI4 HBA dpp registers.\n");
+ 			error = -ENOMEM;
+-			goto out_iounmap_ctrl;
++			goto out_iounmap_all;
+ 		}
+ 		phba->pci_bar4_memmap_p = phba->sli4_hba.dpp_regs_memmap_p;
+ 	}
+@@ -12067,9 +12067,11 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba)
+ 	return 0;
+ 
+ out_iounmap_all:
+-	iounmap(phba->sli4_hba.drbl_regs_memmap_p);
++	if (phba->sli4_hba.drbl_regs_memmap_p)
++		iounmap(phba->sli4_hba.drbl_regs_memmap_p);
+ out_iounmap_ctrl:
+-	iounmap(phba->sli4_hba.ctrl_regs_memmap_p);
++	if (phba->sli4_hba.ctrl_regs_memmap_p)
++		iounmap(phba->sli4_hba.ctrl_regs_memmap_p);
+ out_iounmap_conf:
+ 	iounmap(phba->sli4_hba.conf_regs_memmap_p);
+ 

commit fb4a624f88f658c7b7ae124452bd42eaa8ac7168
+Author: Xu Biang 
+Date:   Thu Apr 6 06:28:01 2023 -0700
+
+    ALSA: firewire-tascam: add missing unwind goto in snd_tscm_stream_start_duplex()
+    
+    Smatch Warns:
+    sound/firewire/tascam/tascam-stream.c:493 snd_tscm_stream_start_duplex()
+    warn: missing unwind goto?
+    
+    The direct return will cause the stream list of "&tscm->domain" unemptied
+    and the session in "tscm" unfinished if amdtp_domain_start() returns with
+    an error.
+    
+    Fix this by changing the direct return to a goto which will empty the
+    stream list of "&tscm->domain" and finish the session in "tscm".
+    
+    The snd_tscm_stream_start_duplex() function is called in the prepare
+    callback of PCM. According to "ALSA Kernel API Documentation", the prepare
+    callback of PCM will be called many times at each setup. So, if the
+    "&d->streams" list is not emptied, when the prepare callback is called
+    next time, snd_tscm_stream_start_duplex() will receive -EBUSY from
+    amdtp_domain_add_stream() that tries to add an existing stream to the
+    domain. The error handling code after the "error" label will be executed
+    in this case, and the "&d->streams" list will be emptied. So not emptying
+    the "&d->streams" list will not cause an issue. But it is more efficient
+    and readable to empty it on the first error by changing the direct return
+    to a goto statement.
+    
+    The session in "tscm" has been begun before amdtp_domain_start(), so it
+    needs to be finished when amdtp_domain_start() fails.
+    
+    Fixes: c281d46a51e3 ("ALSA: firewire-tascam: support AMDTP domain")
+    Signed-off-by: Xu Biang 
+    Reviewed-by: Dan Carpenter 
+    Acked-by: Takashi Sakamoto 
+    Cc: 
+    Link: https://lore.kernel.org/r/20230406132801.105108-1-xubiang@hust.edu.cn
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/firewire/tascam/tascam-stream.c b/sound/firewire/tascam/tascam-stream.c
+index 53e094cc411f..dfe783d01d7d 100644
+--- a/sound/firewire/tascam/tascam-stream.c
++++ b/sound/firewire/tascam/tascam-stream.c
+@@ -490,7 +490,7 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate)
+ 		// packet is important for media clock recovery.
+ 		err = amdtp_domain_start(&tscm->domain, tx_init_skip_cycles, true, true);
+ 		if (err < 0)
+-			return err;
++			goto error;
+ 
+ 		if (!amdtp_domain_wait_ready(&tscm->domain, READY_TIMEOUT_MS)) {
+ 			err = -ETIMEDOUT;

commit 194f8692302cbf31d8072f3fc2710fb04720d8a0
+Author: Zihao Wang 
+Date:   Tue Apr 4 16:46:22 2023 +0800
+
+    ASoC: tegra20_ac97: Add missing unwind goto in tegra20_ac97_platform_probe()
+    
+    Smatch Warns:
+            sound/soc/tegra/tegra20_ac97.c:321 tegra20_ac97_platform_probe()
+            warn: missing unwind goto?
+    
+    The goto will set the "soc_ac97_ops" and "soc_ac97_bus" operations to
+    NULL.  But they are already NULL at this point so it is a no-op.
+    However, just for consistency, change the direct return to a goto.  No
+    functional change.
+    
+    Signed-off-by: Zihao Wang 
+    Reviewed-by: Dan Carpenter 
+    Link: https://lore.kernel.org/r/20230404084622.1202-1-u202012060@hust.edu.cn
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c
+index fea6955f7f43..c498145e76e0 100644
+--- a/sound/soc/tegra/tegra20_ac97.c
++++ b/sound/soc/tegra/tegra20_ac97.c
+@@ -318,7 +318,8 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev)
+ 	ac97->reset = devm_reset_control_get_exclusive(&pdev->dev, "ac97");
+ 	if (IS_ERR(ac97->reset)) {
+ 		dev_err(&pdev->dev, "Can't retrieve ac97 reset\n");
+-		return PTR_ERR(ac97->reset);
++		ret = PTR_ERR(ac97->reset);
++		goto err;
+ 	}
+ 
+ 	ac97->clk_ac97 = devm_clk_get(&pdev->dev, NULL);

commit fc187a46a8e682f0f1167b230792b88de01ceaa0
+Author: Li Yang 
+Date:   Fri Mar 31 17:55:44 2023 +0800
+
+    soc: renesas: renesas-soc: Release 'chipid' from ioremap()
+    
+    Smatch reports:
+    
+    drivers/soc/renesas/renesas-soc.c:536 renesas_soc_init() warn:
+    'chipid' from ioremap() not released on lines: 475.
+    
+    If soc_dev_atrr allocation is failed, function renesas_soc_init()
+    will return without releasing 'chipid' from ioremap().
+    
+    Fix this by adding function iounmap().
+    
+    Fixes: cb5508e47e60 ("soc: renesas: Add support for reading product revision for RZ/G2L family")
+    Signed-off-by: Li Yang 
+    Reviewed-by: Dan Carpenter 
+    Reviewed-by: Geert Uytterhoeven 
+    Link: https://lore.kernel.org/r/20230331095545.31823-1-lidaxian@hust.edu.cn
+    Signed-off-by: Geert Uytterhoeven 
+
+diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c
+index 4ba893e45427..42af7c09f743 100644
+--- a/drivers/soc/renesas/renesas-soc.c
++++ b/drivers/soc/renesas/renesas-soc.c
+@@ -469,8 +469,11 @@ static int __init renesas_soc_init(void)
+ 	}
+ 
+ 	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+-	if (!soc_dev_attr)
++	if (!soc_dev_attr) {
++		if (chipid)
++			iounmap(chipid);
+ 		return -ENOMEM;
++	}
+ 
+ 	np = of_find_node_by_path("/");
+ 	of_property_read_string(np, "model", &soc_dev_attr->machine);

commit c3fbced9af885a6f217fd95509a613d6590916ce
+Author: Zhaoyang Li 
+Date:   Mon Mar 27 19:54:22 2023 +0800
+
+    soc: bcm: brcmstb: biuctrl: fix of_iomap leak
+    
+    Smatch reports:
+    
+    drivers/soc/bcm/brcmstb/biuctrl.c:291 setup_hifcpubiuctrl_regs() warn:
+    'cpubiuctrl_base' from of_iomap() not released on lines: 291.
+    
+    This is because in setup_hifcpubiuctrl_regs(),
+    cpubiuctrl_base is not released when handle error, which may cause a leak.
+    To fix this, iounmap is added when handle error.
+    
+    Fixes: 22f7a9116eba ("soc: brcmstb: Correct CPU_CREDIT_REG offset for Brahma-B53 CPUs")
+    Signed-off-by: Zhaoyang Li 
+    Reviewed-by: Dan Carpenter 
+    Reviewed-by: Dongliang Mu 
+    Link: https://lore.kernel.org/r/20230327115422.1536615-1-lizhaoyang04@hust.edu.cn
+    Signed-off-by: Florian Fainelli 
+
+diff --git a/drivers/soc/bcm/brcmstb/biuctrl.c b/drivers/soc/bcm/brcmstb/biuctrl.c
+index e1d7b4543248..364ddbe365c2 100644
+--- a/drivers/soc/bcm/brcmstb/biuctrl.c
++++ b/drivers/soc/bcm/brcmstb/biuctrl.c
+@@ -288,6 +288,10 @@ static int __init setup_hifcpubiuctrl_regs(struct device_node *np)
+ 	if (BRCM_ID(family_id) == 0x7260 && BRCM_REV(family_id) == 0)
+ 		cpubiuctrl_regs = b53_cpubiuctrl_no_wb_regs;
+ out:
++	if (ret && cpubiuctrl_base) {
++		iounmap(cpubiuctrl_base);
++		cpubiuctrl_base = NULL;
++	}
+ 	return ret;
+ }
+ 

commit db2c2b161d4a8f4a81e6f643848b1531517a67a5
+Author: Mingxuan Xiang 
+Date:   Fri Mar 24 14:09:34 2023 +0800
+
+    usb: dwc3: host: remove dead code in dwc3_host_get_irq()
+    
+    According to the description of platform_get_irq()
+     * Return: non-zero IRQ number on success,
+                            negative error number on failure.
+    and the code, platform_get_irq() will return -EINVAL
+    instead of IRQ0.
+    
+    So platform_get_irq() no longer returns 0, there is no
+    need to check whether the return value is 0.
+    
+    Found by Smatch:
+    drivers/usb/dwc3/host.c:60 dwc3_host_get_irq()
+            warn: platform_get_irq() does not return zero
+    
+    Signed-off-by: Mingxuan Xiang 
+    Reviewed-by: Dan Carpenter 
+    Acked-by: Thinh Nguyen 
+    Link: https://lore.kernel.org/r/20230324060934.1686859-1-mx_xiang@hust.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
+index f6f13e7f1ba1..61f57fe5bb78 100644
+--- a/drivers/usb/dwc3/host.c
++++ b/drivers/usb/dwc3/host.c
+@@ -52,13 +52,8 @@ static int dwc3_host_get_irq(struct dwc3 *dwc)
+ 		goto out;
+ 
+ 	irq = platform_get_irq(dwc3_pdev, 0);
+-	if (irq > 0) {
++	if (irq > 0)
+ 		dwc3_host_fill_xhci_irq_res(dwc, irq, NULL);
+-		goto out;
+-	}
+-
+-	if (!irq)
+-		irq = -EINVAL;
+ 
+ out:
+ 	return irq;

commit f33642224e38d7e0d59336e10e7b4e370b1c4506
+Author: SongJingyi 
+Date:   Fri Mar 24 11:14:06 2023 +0800
+
+    ptp_qoriq: fix memory leak in probe()
+    
+    Smatch complains that:
+    drivers/ptp/ptp_qoriq.c ptp_qoriq_probe()
+    warn: 'base' from ioremap() not released.
+    
+    Fix this by revising the parameter from 'ptp_qoriq->base' to 'base'.
+    This is only a bug if ptp_qoriq_init() returns on the
+    first -ENODEV error path.
+    For other error paths ptp_qoriq->base and base are the same.
+    And this change makes the code more readable.
+    
+    Fixes: 7f4399ba405b ("ptp_qoriq: fix NULL access if ptp dt node missing")
+    Signed-off-by: SongJingyi 
+    Reviewed-by: Dan Carpenter 
+    Reviewed-by: Dongliang Mu 
+    Link: https://lore.kernel.org/r/20230324031406.1895159-1-u201912584@hust.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/drivers/ptp/ptp_qoriq.c b/drivers/ptp/ptp_qoriq.c
+index 61530167efe4..350154e4c2b5 100644
+--- a/drivers/ptp/ptp_qoriq.c
++++ b/drivers/ptp/ptp_qoriq.c
+@@ -637,7 +637,7 @@ static int ptp_qoriq_probe(struct platform_device *dev)
+ 	return 0;
+ 
+ no_clock:
+-	iounmap(ptp_qoriq->base);
++	iounmap(base);
+ no_ioremap:
+ 	release_resource(ptp_qoriq->rsrc);
+ no_resource:

commit 813cc94c7847ae4a17e9f744fb4dbdf7df6bd732
+Author: Tianyi Jing 
+Date:   Sat Mar 18 22:38:51 2023 +0800
+
+    hwmon: (xgene) Fix ioremap and memremap leak
+    
+    Smatch reports:
+    
+    drivers/hwmon/xgene-hwmon.c:757 xgene_hwmon_probe() warn:
+    'ctx->pcc_comm_addr' from ioremap() not released on line: 757.
+    
+    This is because in drivers/hwmon/xgene-hwmon.c:701 xgene_hwmon_probe(),
+    ioremap and memremap is not released, which may cause a leak.
+    
+    To fix this, ioremap and memremap is modified to devm_ioremap and
+    devm_memremap.
+    
+    Signed-off-by: Tianyi Jing 
+    Reviewed-by: Dongliang Mu 
+    Link: https://lore.kernel.org/r/20230318143851.2191625-1-jingfelix@hust.edu.cn
+    [groeck: Fixed formatting and subject]
+    Signed-off-by: Guenter Roeck 
+
+diff --git a/drivers/hwmon/xgene-hwmon.c b/drivers/hwmon/xgene-hwmon.c
+index d1abea49f01b..78d9f52e2a71 100644
+--- a/drivers/hwmon/xgene-hwmon.c
++++ b/drivers/hwmon/xgene-hwmon.c
+@@ -698,14 +698,14 @@ static int xgene_hwmon_probe(struct platform_device *pdev)
+ 		ctx->comm_base_addr = pcc_chan->shmem_base_addr;
+ 		if (ctx->comm_base_addr) {
+ 			if (version == XGENE_HWMON_V2)
+-				ctx->pcc_comm_addr = (void __force *)ioremap(
+-							ctx->comm_base_addr,
+-							pcc_chan->shmem_size);
++				ctx->pcc_comm_addr = (void __force *)devm_ioremap(&pdev->dev,
++								  ctx->comm_base_addr,
++								  pcc_chan->shmem_size);
+ 			else
+-				ctx->pcc_comm_addr = memremap(
+-							ctx->comm_base_addr,
+-							pcc_chan->shmem_size,
+-							MEMREMAP_WB);
++				ctx->pcc_comm_addr = devm_memremap(&pdev->dev,
++								   ctx->comm_base_addr,
++								   pcc_chan->shmem_size,
++								   MEMREMAP_WB);
+ 		} else {
+ 			dev_err(&pdev->dev, "Failed to get PCC comm region\n");
+ 			rc = -ENODEV;

commit 8d13d50b157655247cdb3a69aca7836b58ff8735
+Author: Dongliang Mu 
+Date:   Thu Mar 9 12:01:06 2023 +0800
+
+    platform/x86/intel: tpmi: Revise the comment of intel_vsec_add_aux
+    
+    intel_vsec_add_aux() is resource managed including res and
+    feature_vsec_dev memory.
+    
+    Fix this by revising the comment of intel_vsec_add_aux since res variable
+    will also be freed in the intel_vsec_add_aux.
+    
+    Signed-off-by: Dongliang Mu 
+    Link: https://lore.kernel.org/r/20230309040107.534716-3-dzm91@hust.edu.cn
+    Reviewed-by: Hans de Goede 
+    Signed-off-by: Hans de Goede 
+
+diff --git a/drivers/platform/x86/intel/tpmi.c b/drivers/platform/x86/intel/tpmi.c
+index a8733c43e4ab..a5227951decc 100644
+--- a/drivers/platform/x86/intel/tpmi.c
++++ b/drivers/platform/x86/intel/tpmi.c
+@@ -239,8 +239,8 @@ static int tpmi_create_device(struct intel_tpmi_info *tpmi_info,
+ 	/*
+ 	 * intel_vsec_add_aux() is resource managed, no explicit
+ 	 * delete is required on error or on module unload.
+-	 * feature_vsec_dev memory is also freed as part of device
+-	 * delete.
++	 * feature_vsec_dev and res memory are also freed as part of
++	 * device deletion.
+ 	 */
+ 	return intel_vsec_add_aux(vsec_dev->pcidev, &vsec_dev->auxdev.dev,
+ 				  feature_vsec_dev, feature_id_name);

commit 4d5a2a7d2c97dbd658533eea5f79dab1ad5dc0ee
+Author: Dongliang Mu 
+Date:   Thu Mar 9 12:01:05 2023 +0800
+
+    platform/x86/intel: tpmi: Fix double free in tpmi_create_device()
+    
+    The previous commit 6a192c0cbf38 ("platform/x86/intel/tpmi: Fix
+    double free reported by Smatch") incorrectly handle the deallocation of
+    res variable. As shown in the comment, intel_vsec_add_aux handles all
+    the deallocation of res and feature_vsec_dev. Therefore, kfree(res) can
+    still cause double free if intel_vsec_add_aux returns error.
+    
+    Fix this by adjusting the error handling part in tpmi_create_device,
+    following the function intel_vsec_add_dev.
+    
+    Fixes: 6a192c0cbf38 ("platform/x86/intel/tpmi: Fix double free reported by Smatch")
+    Signed-off-by: Dongliang Mu 
+    Link: https://lore.kernel.org/r/20230309040107.534716-2-dzm91@hust.edu.cn
+    Reviewed-by: Hans de Goede 
+    Signed-off-by: Hans de Goede 
+
+diff --git a/drivers/platform/x86/intel/tpmi.c b/drivers/platform/x86/intel/tpmi.c
+index c999732b0f1e..a8733c43e4ab 100644
+--- a/drivers/platform/x86/intel/tpmi.c
++++ b/drivers/platform/x86/intel/tpmi.c
+@@ -203,7 +203,7 @@ static int tpmi_create_device(struct intel_tpmi_info *tpmi_info,
+ 	struct intel_vsec_device *feature_vsec_dev;
+ 	struct resource *res, *tmp;
+ 	const char *name;
+-	int ret, i;
++	int i;
+ 
+ 	name = intel_tpmi_name(pfs->pfs_header.tpmi_id);
+ 	if (!name)
+@@ -215,8 +215,8 @@ static int tpmi_create_device(struct intel_tpmi_info *tpmi_info,
+ 
+ 	feature_vsec_dev = kzalloc(sizeof(*feature_vsec_dev), GFP_KERNEL);
+ 	if (!feature_vsec_dev) {
+-		ret = -ENOMEM;
+-		goto free_res;
++		kfree(res);
++		return -ENOMEM;
+ 	}
+ 
+ 	snprintf(feature_id_name, sizeof(feature_id_name), "tpmi-%s", name);
+@@ -242,17 +242,8 @@ static int tpmi_create_device(struct intel_tpmi_info *tpmi_info,
+ 	 * feature_vsec_dev memory is also freed as part of device
+ 	 * delete.
+ 	 */
+-	ret = intel_vsec_add_aux(vsec_dev->pcidev, &vsec_dev->auxdev.dev,
+-				 feature_vsec_dev, feature_id_name);
+-	if (ret)
+-		goto free_res;
+-
+-	return 0;
+-
+-free_res:
+-	kfree(res);
+-
+-	return ret;
++	return intel_vsec_add_aux(vsec_dev->pcidev, &vsec_dev->auxdev.dev,
++				  feature_vsec_dev, feature_id_name);
+ }
+ 
+ static int tpmi_create_devices(struct intel_tpmi_info *tpmi_info)

commit da0ba0ccce54059d6c6b788a75099bfce95126da
+Author: Dongliang Mu 
+Date:   Thu Mar 9 12:01:07 2023 +0800
+
+    platform/x86/intel: vsec: Fix a memory leak in intel_vsec_add_aux
+    
+    The first error handling code in intel_vsec_add_aux misses the
+    deallocation of intel_vsec_dev->resource.
+    
+    Fix this by adding kfree(intel_vsec_dev->resource) in the error handling
+    code.
+    
+    Reviewed-by: David E. Box 
+    Signed-off-by: Dongliang Mu 
+    Link: https://lore.kernel.org/r/20230309040107.534716-4-dzm91@hust.edu.cn
+    Reviewed-by: Hans de Goede 
+    Signed-off-by: Hans de Goede 
+
+diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c
+index 13decf36c6de..2311c16cb975 100644
+--- a/drivers/platform/x86/intel/vsec.c
++++ b/drivers/platform/x86/intel/vsec.c
+@@ -154,6 +154,7 @@ int intel_vsec_add_aux(struct pci_dev *pdev, struct device *parent,
+ 	ret = ida_alloc(intel_vsec_dev->ida, GFP_KERNEL);
+ 	mutex_unlock(&vsec_ida_lock);
+ 	if (ret < 0) {
++		kfree(intel_vsec_dev->resource);
+ 		kfree(intel_vsec_dev);
+ 		return ret;
+ 	}

commit fb37fdd02856e45e78209d32522029c9f77fe7b7
+Author: Cheng Ziqiu 
+Date:   Tue Mar 14 15:01:30 2023 +0800
+
+    iio: adc: at91-sama5d2_adc: remove dead code in at91_adc_probe()
+    
+    From the comment of platform_get_irq(), it only returns non-zero IRQ
+    number and negative error number, other than zero.
+    
+    Fix this by removing the if condition.
+    
+    Signed-off-by: Cheng Ziqiu 
+    Reviewed-by: Dongliang Mu 
+    Reviewed-by: Claudiu Beznea 
+    Link: https://lore.kernel.org/r/20230314070130.60581-1-chengziqiu@hust.edu.cn
+    Signed-off-by: Jonathan Cameron 
+
+diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
+index b5d0c9ee284c..30554026a7fe 100644
+--- a/drivers/iio/adc/at91-sama5d2_adc.c
++++ b/drivers/iio/adc/at91-sama5d2_adc.c
+@@ -2400,12 +2400,8 @@ static int at91_adc_probe(struct platform_device *pdev)
+ 	st->dma_st.phys_addr = res->start;
+ 
+ 	st->irq = platform_get_irq(pdev, 0);
+-	if (st->irq <= 0) {
+-		if (!st->irq)
+-			st->irq = -ENXIO;
+-
++	if (st->irq < 0)
+ 		return st->irq;
+-	}
+ 
+ 	st->per_clk = devm_clk_get(&pdev->dev, "adc_clk");
+ 	if (IS_ERR(st->per_clk))

commit 984cfd55e0c99e80b2e5b1dc6b2bf98608af7ff9
+Author: Dongliang Mu 
+Date:   Wed Mar 8 16:32:31 2023 +0800
+
+    net: ieee802154: remove an unnecessary null pointer check
+    
+    llsec_parse_seclevel has the null pointer check at its begining. Compared
+    with nl802154_add_llsec_seclevel, nl802154_del_llsec_seclevel has a
+    redundant null pointer check of info->attrs[NL802154_ATTR_SEC_LEVEL]
+    before llsec_parse_seclevel.
+    
+    Fix this issue by removing the null pointer check in
+    nl802154_del_llsec_seclevel.
+    
+    Signed-off-by: Dongliang Mu 
+    Link: https://lore.kernel.org/r/20230308083231.460015-1-dzm91@hust.edu.cn
+    Signed-off-by: Stefan Schmidt 
+
+diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c
+index d8f4379d4fa6..832e3c50816c 100644
+--- a/net/ieee802154/nl802154.c
++++ b/net/ieee802154/nl802154.c
+@@ -2488,8 +2488,7 @@ static int nl802154_del_llsec_seclevel(struct sk_buff *skb,
+ 	if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
+ 		return -EOPNOTSUPP;
+ 
+-	if (!info->attrs[NL802154_ATTR_SEC_LEVEL] ||
+-	    llsec_parse_seclevel(info->attrs[NL802154_ATTR_SEC_LEVEL],
++	if (llsec_parse_seclevel(info->attrs[NL802154_ATTR_SEC_LEVEL],
+ 				 &sl) < 0)
+ 		return -EINVAL;
+ 

commit cbffe6b3b2bdf6064135f715242feb2f9094190f
+Author: Dongliang Mu 
+Date:   Mon Mar 6 10:45:23 2023 +0800
+
+    i2c: davinci: remove dead code in probe
+    
+    From the comment of platform_get_irq, it only returns non-zero IRQ
+    number and negative error number, other than zero.
+    
+    Fix this by removing the if condition.
+    
+    Signed-off-by: Dongliang Mu 
+    Reviewed-by: Bartosz Golaszewski 
+    Signed-off-by: Wolfram Sang 
+
+diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
+index c836cf884185..9750310f2c96 100644
+--- a/drivers/i2c/busses/i2c-davinci.c
++++ b/drivers/i2c/busses/i2c-davinci.c
+@@ -764,11 +764,8 @@ static int davinci_i2c_probe(struct platform_device *pdev)
+ 	int r, irq;
+ 
+ 	irq = platform_get_irq(pdev, 0);
+-	if (irq <= 0) {
+-		if (!irq)
+-			irq = -ENXIO;
++	if (irq < 0)
+ 		return dev_err_probe(&pdev->dev, irq, "can't get irq resource\n");
+-	}
+ 
+ 	dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_i2c_dev),
+ 			GFP_KERNEL);

commit 4fa1387261e725a418066f8f46ea87a6ba0e5be1
+Author: Yalong Zou 
+Date:   Thu Mar 9 23:08:15 2023 +0800
+
+    usb: remove dead code in dwc3_gadget_get_irq
+    
+    platform_get_irq() only return non-zero irq number on success, or
+    negative error number on failure.
+    
+    There is no need to check the return value of platform_get_irq()
+    to determine the return value of dwc3_gadget_get_irq(), removing
+    them to solve this problem.
+    
+    Signed-off-by: Yalong Zou 
+    Signed-off-by: Dongliang Mu 
+    Link: https://lore.kernel.org/r/20230309150815.1884260-1-yalongz@hust.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
+index 07989c645a94..a1ebb30c15fa 100644
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -4402,11 +4402,6 @@ static int dwc3_gadget_get_irq(struct dwc3 *dwc)
+ 		goto out;
+ 
+ 	irq = platform_get_irq(dwc3_pdev, 0);
+-	if (irq > 0)
+-		goto out;
+-
+-	if (!irq)
+-		irq = -EINVAL;
+ 
+ out:
+ 	return irq;

commit 48181d285623198c33bb9698992502687b258efa
+Author: Dongliang Mu 
+Date:   Thu Mar 9 10:16:36 2023 +0800
+
+    wifi: rtw88: fix memory leak in rtw_usb_probe()
+    
+    drivers/net/wireless/realtek/rtw88/usb.c:876 rtw_usb_probe()
+    warn: 'hw' from ieee80211_alloc_hw() not released on lines: 811
+    
+    Fix this by modifying return to a goto statement.
+    
+    Signed-off-by: Dongliang Mu 
+    Reviewed-by: Ping-Ke Shih 
+    Signed-off-by: Kalle Valo 
+    Link: https://lore.kernel.org/r/20230309021636.528601-1-dzm91@hust.edu.cn
+
+diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
+index 2a8336b1847a..68e1b782d199 100644
+--- a/drivers/net/wireless/realtek/rtw88/usb.c
++++ b/drivers/net/wireless/realtek/rtw88/usb.c
+@@ -808,7 +808,7 @@ int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
+ 
+ 	ret = rtw_usb_alloc_rx_bufs(rtwusb);
+ 	if (ret)
+-		return ret;
++		goto err_release_hw;
+ 
+ 	ret = rtw_core_init(rtwdev);
+ 	if (ret)

commit cd53860edd5e66f2faaf1bfbaef81d4be9109c82
+Author: Dongliang Mu 
+Date:   Fri Nov 18 22:14:06 2022 +0800
+
+    fbdev: da8xx-fb: add missing regulator_disable() in fb_probe
+    
+    The error handling code in fb_probe misses regulator_disable if
+    regulator_enable is called successfully. The previous commit only
+    adds regulator_disable in the .remove(), forgetting the error
+    handling code in the .probe.
+    
+    Fix this by adding a new error label to call regulator_disable.
+    
+    Fixes: 611097d5daea("fbdev: da8xx: add support for a regulator")
+    Signed-off-by: Dongliang Mu 
+    Signed-off-by: Helge Deller 
+
+diff --git a/drivers/video/fbdev/da8xx-fb.c b/drivers/video/fbdev/da8xx-fb.c
+index 11922b009ed7..cd07e401b326 100644
+--- a/drivers/video/fbdev/da8xx-fb.c
++++ b/drivers/video/fbdev/da8xx-fb.c
+@@ -1431,7 +1431,7 @@ static int fb_probe(struct platform_device *device)
+ 		dev_err(&device->dev,
+ 			"GLCD: kmalloc for frame buffer failed\n");
+ 		ret = -EINVAL;
+-		goto err_release_fb;
++		goto err_disable_reg;
+ 	}
+ 
+ 	da8xx_fb_info->screen_base = (char __iomem *) par->vram_virt;
+@@ -1475,7 +1475,7 @@ static int fb_probe(struct platform_device *device)
+ 
+ 	ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0);
+ 	if (ret)
+-		goto err_release_fb;
++		goto err_disable_reg;
+ 	da8xx_fb_info->cmap.len = par->palette_sz;
+ 
+ 	/* initialize var_screeninfo */
+@@ -1529,6 +1529,9 @@ static int fb_probe(struct platform_device *device)
+ err_dealloc_cmap:
+ 	fb_dealloc_cmap(&da8xx_fb_info->cmap);
+ 
++err_disable_reg:
++	if (par->lcd_supply)
++		regulator_disable(par->lcd_supply);
+ err_release_fb:
+ 	framebuffer_release(da8xx_fb_info);
+ 

commit b76449ee75e21acfe9fa4c653d8598f191ed7d68
+Author: Dongliang Mu 
+Date:   Fri Nov 11 13:49:49 2022 +0800
+
+    fbdev: smscufx: fix error handling code in ufx_usb_probe
+    
+    The current error handling code in ufx_usb_probe have many unmatching
+    issues, e.g., missing ufx_free_usb_list, destroy_modedb label should
+    only include framebuffer_release, fb_dealloc_cmap only matches
+    fb_alloc_cmap.
+    
+    My local syzkaller reports a memory leak bug:
+    
+    memory leak in ufx_usb_probe
+    
+    BUG: memory leak
+    unreferenced object 0xffff88802f879580 (size 128):
+      comm "kworker/0:7", pid 17416, jiffies 4295067474 (age 46.710s)
+      hex dump (first 32 bytes):
+        80 21 7c 2e 80 88 ff ff 18 d0 d0 0c 80 88 ff ff  .!|.............
+        00 d0 d0 0c 80 88 ff ff e0 ff ff ff 0f 00 00 00  ................
+      backtrace:
+        [] kmalloc_trace+0x20/0x90 mm/slab_common.c:1045
+        [] kmalloc include/linux/slab.h:553 [inline]
+        [] kzalloc include/linux/slab.h:689 [inline]
+        [] ufx_alloc_urb_list drivers/video/fbdev/smscufx.c:1873 [inline]
+        [] ufx_usb_probe+0x11c/0x15a0 drivers/video/fbdev/smscufx.c:1655
+        [] usb_probe_interface+0x177/0x370 drivers/usb/core/driver.c:396
+        [] call_driver_probe drivers/base/dd.c:560 [inline]
+        [] really_probe+0x12d/0x390 drivers/base/dd.c:639
+        [] __driver_probe_device+0xbf/0x140 drivers/base/dd.c:778
+        [] driver_probe_device+0x2a/0x120 drivers/base/dd.c:808
+        [] __device_attach_driver+0xf7/0x150 drivers/base/dd.c:936
+        [] bus_for_each_drv+0xb7/0x100 drivers/base/bus.c:427
+        [] __device_attach+0x105/0x2d0 drivers/base/dd.c:1008
+        [] bus_probe_device+0xc6/0xe0 drivers/base/bus.c:487
+        [] device_add+0x642/0xdc0 drivers/base/core.c:3517
+        [] usb_set_configuration+0x8ef/0xb80 drivers/usb/core/message.c:2170
+        [] usb_generic_driver_probe+0x8c/0xc0 drivers/usb/core/generic.c:238
+        [] usb_probe_device+0x5c/0x140 drivers/usb/core/driver.c:293
+        [] call_driver_probe drivers/base/dd.c:560 [inline]
+        [] really_probe+0x12d/0x390 drivers/base/dd.c:639
+        [] __driver_probe_device+0xbf/0x140 drivers/base/dd.c:778
+    
+    Fix this bug by rewriting the error handling code in ufx_usb_probe.
+    
+    Reported-by: syzkaller 
+    Tested-by: Dongliang Mu 
+    Signed-off-by: Dongliang Mu 
+    Signed-off-by: Helge Deller 
+
+diff --git a/drivers/video/fbdev/smscufx.c b/drivers/video/fbdev/smscufx.c
+index 9343b7a4ac89..2ad6e98ce10d 100644
+--- a/drivers/video/fbdev/smscufx.c
++++ b/drivers/video/fbdev/smscufx.c
+@@ -1622,7 +1622,7 @@ static int ufx_usb_probe(struct usb_interface *interface,
+ 	struct usb_device *usbdev;
+ 	struct ufx_data *dev;
+ 	struct fb_info *info;
+-	int retval;
++	int retval = -ENOMEM;
+ 	u32 id_rev, fpga_rev;
+ 
+ 	/* usb initialization */
+@@ -1654,15 +1654,17 @@ static int ufx_usb_probe(struct usb_interface *interface,
+ 
+ 	if (!ufx_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) {
+ 		dev_err(dev->gdev, "ufx_alloc_urb_list failed\n");
+-		goto e_nomem;
++		goto put_ref;
+ 	}
+ 
+ 	/* We don't register a new USB class. Our client interface is fbdev */
+ 
+ 	/* allocates framebuffer driver structure, not framebuffer memory */
+ 	info = framebuffer_alloc(0, &usbdev->dev);
+-	if (!info)
+-		goto e_nomem;
++	if (!info) {
++		dev_err(dev->gdev, "framebuffer_alloc failed\n");
++		goto free_urb_list;
++	}
+ 
+ 	dev->info = info;
+ 	info->par = dev;
+@@ -1705,22 +1707,34 @@ static int ufx_usb_probe(struct usb_interface *interface,
+ 	check_warn_goto_error(retval, "unable to find common mode for display and adapter");
+ 
+ 	retval = ufx_reg_set_bits(dev, 0x4000, 0x00000001);
+-	check_warn_goto_error(retval, "error %d enabling graphics engine", retval);
++	if (retval < 0) {
++		dev_err(dev->gdev, "error %d enabling graphics engine", retval);
++		goto setup_modes;
++	}
+ 
+ 	/* ready to begin using device */
+ 	atomic_set(&dev->usb_active, 1);
+ 
+ 	dev_dbg(dev->gdev, "checking var");
+ 	retval = ufx_ops_check_var(&info->var, info);
+-	check_warn_goto_error(retval, "error %d ufx_ops_check_var", retval);
++	if (retval < 0) {
++		dev_err(dev->gdev, "error %d ufx_ops_check_var", retval);
++		goto reset_active;
++	}
+ 
+ 	dev_dbg(dev->gdev, "setting par");
+ 	retval = ufx_ops_set_par(info);
+-	check_warn_goto_error(retval, "error %d ufx_ops_set_par", retval);
++	if (retval < 0) {
++		dev_err(dev->gdev, "error %d ufx_ops_set_par", retval);
++		goto reset_active;
++	}
+ 
+ 	dev_dbg(dev->gdev, "registering framebuffer");
+ 	retval = register_framebuffer(info);
+-	check_warn_goto_error(retval, "error %d register_framebuffer", retval);
++	if (retval < 0) {
++		dev_err(dev->gdev, "error %d register_framebuffer", retval);
++		goto reset_active;
++	}
+ 
+ 	dev_info(dev->gdev, "SMSC UDX USB device /dev/fb%d attached. %dx%d resolution."
+ 		" Using %dK framebuffer memory\n", info->node,
+@@ -1728,21 +1742,23 @@ static int ufx_usb_probe(struct usb_interface *interface,
+ 
+ 	return 0;
+ 
+-error:
+-	fb_dealloc_cmap(&info->cmap);
+-destroy_modedb:
++reset_active:
++	atomic_set(&dev->usb_active, 0);
++setup_modes:
+ 	fb_destroy_modedb(info->monspecs.modedb);
+ 	vfree(info->screen_base);
+ 	fb_destroy_modelist(&info->modelist);
++error:
++	fb_dealloc_cmap(&info->cmap);
++destroy_modedb:
+ 	framebuffer_release(info);
++free_urb_list:
++	if (dev->urbs.count > 0)
++		ufx_free_urb_list(dev);
+ put_ref:
+ 	kref_put(&dev->kref, ufx_free); /* ref for framebuffer */
+ 	kref_put(&dev->kref, ufx_free); /* last ref from kref_init */
+ 	return retval;
+-
+-e_nomem:
+-	retval = -ENOMEM;
+-	goto put_ref;
+ }
+ 
+ static void ufx_usb_disconnect(struct usb_interface *interface)

commit aa9832e4501264a43db671bba09fe4d8bc39fcff
+Author: Dongliang Mu 
+Date:   Mon Oct 24 19:00:30 2022 +0800
+
+    can: ucan: ucan_disconnect(): change unregister_netdev() to unregister_candev()
+    
+    From API pairing, change unregister_netdev() to unregister_candev()
+    since the registration function is register_candev(). Actually, they
+    are the same.
+    
+    Signed-off-by: Dongliang Mu 
+    Link: https://lore.kernel.org/all/20221024110033.727542-1-dzm91@hust.edu.cn
+    [mkl: adjust subject + commit message]
+    Signed-off-by: Marc Kleine-Budde 
+
+diff --git a/drivers/net/can/usb/ucan.c b/drivers/net/can/usb/ucan.c
+index b53e709943bc..a1734f1c0148 100644
+--- a/drivers/net/can/usb/ucan.c
++++ b/drivers/net/can/usb/ucan.c
+@@ -1582,7 +1582,7 @@ static void ucan_disconnect(struct usb_interface *intf)
+ 	usb_set_intfdata(intf, NULL);
+ 
+ 	if (up) {
+-		unregister_netdev(up->netdev);
++		unregister_candev(up->netdev);
+ 		free_candev(up->netdev);
+ 	}
+ }

commit b1a09b63684cea56774786ca14c13b7041ffee63
+Author: Dongliang Mu 
+Date:   Mon Oct 24 17:02:52 2022 +0800
+
+    can: mcp251x: mcp251x_can_probe(): add missing unregister_candev() in error path
+    
+    In mcp251x_can_probe(), if mcp251x_gpio_setup() fails, it forgets to
+    unregister the CAN device.
+    
+    Fix this by unregistering can device in mcp251x_can_probe().
+    
+    Fixes: 2d52dabbef60 ("can: mcp251x: add GPIO support")
+    Signed-off-by: Dongliang Mu 
+    Link: https://lore.kernel.org/all/20221024090256.717236-1-dzm91@hust.edu.cn
+    [mkl: adjust label]
+    Signed-off-by: Marc Kleine-Budde 
+
+diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c
+index c320de474f40..24883a65ca66 100644
+--- a/drivers/net/can/spi/mcp251x.c
++++ b/drivers/net/can/spi/mcp251x.c
+@@ -1415,11 +1415,14 @@ static int mcp251x_can_probe(struct spi_device *spi)
+ 
+ 	ret = mcp251x_gpio_setup(priv);
+ 	if (ret)
+-		goto error_probe;
++		goto out_unregister_candev;
+ 
+ 	netdev_info(net, "MCP%x successfully initialized.\n", priv->model);
+ 	return 0;
+ 
++out_unregister_candev:
++	unregister_candev(net);
++
+ error_probe:
+ 	destroy_workqueue(priv->wq);
+ 	priv->wq = NULL;

commit 3e5b3418827cefb5e1cc658806f02965791b8f07
+Author: Dongliang Mu 
+Date:   Mon Oct 24 19:48:07 2022 +0800
+
+    can: mscan: mpc5xxx: mpc5xxx_can_probe(): add missing put_clock() in error path
+    
+    The commit 1149108e2fbf ("can: mscan: improve clock API use") only
+    adds put_clock() in mpc5xxx_can_remove() function, forgetting to add
+    put_clock() in the error handling code.
+    
+    Fix this bug by adding put_clock() in the error handling code.
+    
+    Fixes: 1149108e2fbf ("can: mscan: improve clock API use")
+    Signed-off-by: Dongliang Mu 
+    Link: https://lore.kernel.org/all/20221024133828.35881-1-mkl@pengutronix.de
+    Signed-off-by: Marc Kleine-Budde 
+
+diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
+index c469b2f3e57d..b0ed798ae70f 100644
+--- a/drivers/net/can/mscan/mpc5xxx_can.c
++++ b/drivers/net/can/mscan/mpc5xxx_can.c
+@@ -322,14 +322,14 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
+ 					       &mscan_clksrc);
+ 	if (!priv->can.clock.freq) {
+ 		dev_err(&ofdev->dev, "couldn't get MSCAN clock properties\n");
+-		goto exit_free_mscan;
++		goto exit_put_clock;
+ 	}
+ 
+ 	err = register_mscandev(dev, mscan_clksrc);
+ 	if (err) {
+ 		dev_err(&ofdev->dev, "registering %s failed (err=%d)\n",
+ 			DRV_NAME, err);
+-		goto exit_free_mscan;
++		goto exit_put_clock;
+ 	}
+ 
+ 	dev_info(&ofdev->dev, "MSCAN at 0x%p, irq %d, clock %d Hz\n",
+@@ -337,7 +337,9 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
+ 
+ 	return 0;
+ 
+-exit_free_mscan:
++exit_put_clock:
++	if (data->put_clock)
++		data->put_clock(ofdev);
+ 	free_candev(dev);
+ exit_dispose_irq:
+ 	irq_dispose_mapping(irq);

commit 90732f1769165dcf0778d723ad188f6441a930f5
+Author: Dongliang Mu 
+Date:   Sun Oct 9 15:23:05 2022 +0800
+
+    usb: cdns3: adjust the partial logic of cdnsp_pci_remove
+    
+    In cdnsp_pci_remove, if pci_is_enabled returns true, it will
+    call cdns_remove; else it will call kfree. Then both control flow
+    goes to pci_dev_put.
+    
+    Adjust this logic by modifying it to an if else.
+    
+    Signed-off-by: Dongliang Mu 
+    Acked-by: Pawel Laszczak 
+    Link: https://lore.kernel.org/r/20221009072305.1593707-1-dzm91@hust.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/cdns3/cdnsp-pci.c b/drivers/usb/cdns3/cdnsp-pci.c
+index fe8a114c586c..efd54ed918b9 100644
+--- a/drivers/usb/cdns3/cdnsp-pci.c
++++ b/drivers/usb/cdns3/cdnsp-pci.c
+@@ -192,14 +192,12 @@ static void cdnsp_pci_remove(struct pci_dev *pdev)
+ 	if (pci_dev_run_wake(pdev))
+ 		pm_runtime_get_noresume(&pdev->dev);
+ 
+-	if (!pci_is_enabled(func)) {
++	if (pci_is_enabled(func)) {
++		cdns_remove(cdnsp);
++	} else {
+ 		kfree(cdnsp);
+-		goto pci_put;
+ 	}
+ 
+-	cdns_remove(cdnsp);
+-
+-pci_put:
+ 	pci_dev_put(func);
+ }
+ 

\ No newline at end of file diff --git a/detail/19.html b/detail/19.html new file mode 100644 index 0000000..9dd682a --- /dev/null +++ b/detail/19.html @@ -0,0 +1,1967 @@ +

Patches contributed by University of Georgia


commit f311ade3a7adf31658ed882aaab9f9879fdccef7
+Author: Wenwen Wang 
+Date:   Sat Feb 1 20:38:38 2020 +0000
+
+    btrfs: ref-verify: fix memory leaks
+    
+    In btrfs_ref_tree_mod(), 'ref' and 'ra' are allocated through kzalloc() and
+    kmalloc(), respectively. In the following code, if an error occurs, the
+    execution will be redirected to 'out' or 'out_unlock' and the function will
+    be exited. However, on some of the paths, 'ref' and 'ra' are not
+    deallocated, leading to memory leaks. For example, if 'action' is
+    BTRFS_ADD_DELAYED_EXTENT, add_block_entry() will be invoked. If the return
+    value indicates an error, the execution will be redirected to 'out'. But,
+    'ref' is not deallocated on this path, causing a memory leak.
+    
+    To fix the above issues, deallocate both 'ref' and 'ra' before exiting from
+    the function when an error is encountered.
+    
+    CC: stable@vger.kernel.org # 4.15+
+    Signed-off-by: Wenwen Wang 
+    Reviewed-by: David Sterba 
+    Signed-off-by: David Sterba 
+
+diff --git a/fs/btrfs/ref-verify.c b/fs/btrfs/ref-verify.c
+index b57f3618e58e..454a1015d026 100644
+--- a/fs/btrfs/ref-verify.c
++++ b/fs/btrfs/ref-verify.c
+@@ -744,6 +744,7 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info,
+ 		 */
+ 		be = add_block_entry(fs_info, bytenr, num_bytes, ref_root);
+ 		if (IS_ERR(be)) {
++			kfree(ref);
+ 			kfree(ra);
+ 			ret = PTR_ERR(be);
+ 			goto out;
+@@ -757,6 +758,8 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info,
+ 			"re-allocated a block that still has references to it!");
+ 			dump_block_entry(fs_info, be);
+ 			dump_ref_action(fs_info, ra);
++			kfree(ref);
++			kfree(ra);
+ 			goto out_unlock;
+ 		}
+ 
+@@ -819,6 +822,7 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info,
+ "dropping a ref for a existing root that doesn't have a ref on the block");
+ 				dump_block_entry(fs_info, be);
+ 				dump_ref_action(fs_info, ra);
++				kfree(ref);
+ 				kfree(ra);
+ 				goto out_unlock;
+ 			}
+@@ -834,6 +838,7 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info,
+ "attempting to add another ref for an existing ref on a tree block");
+ 			dump_block_entry(fs_info, be);
+ 			dump_ref_action(fs_info, ra);
++			kfree(ref);
+ 			kfree(ra);
+ 			goto out_unlock;
+ 		}

commit 123c23c6a7b7ecd2a3d6060bea1d94019f71fd66
+Author: Wenwen Wang 
+Date:   Mon Feb 3 03:47:53 2020 +0000
+
+    NFS: Fix memory leaks
+    
+    In _nfs42_proc_copy(), 'res->commit_res.verf' is allocated through
+    kzalloc() if 'args->sync' is true. In the following code, if
+    'res->synchronous' is false, handle_async_copy() will be invoked. If an
+    error occurs during the invocation, the following code will not be executed
+    and the error will be returned . However, the allocated
+    'res->commit_res.verf' is not deallocated, leading to a memory leak. This
+    is also true if the invocation of process_copy_commit() returns an error.
+    
+    To fix the above leaks, redirect the execution to the 'out' label if an
+    error is encountered.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Anna Schumaker 
+
+diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c
+index 9637aad36bdc..e2ae54b35dfe 100644
+--- a/fs/nfs/nfs42proc.c
++++ b/fs/nfs/nfs42proc.c
+@@ -343,14 +343,14 @@ static ssize_t _nfs42_proc_copy(struct file *src,
+ 		status = handle_async_copy(res, dst_server, src_server, src,
+ 				dst, &args->src_stateid, restart);
+ 		if (status)
+-			return status;
++			goto out;
+ 	}
+ 
+ 	if ((!res->synchronous || !args->sync) &&
+ 			res->write_res.verifier.committed != NFS_FILE_SYNC) {
+ 		status = process_copy_commit(dst, pos_dst, res);
+ 		if (status)
+-			return status;
++			goto out;
+ 	}
+ 
+ 	truncate_pagecache_range(dst_inode, pos_dst,

commit fa865ba183d61c1ec8cbcab8573159c3b72b89a4
+Author: Wenwen Wang 
+Date:   Sat Jan 25 14:33:29 2020 +0000
+
+    firestream: fix memory leaks
+    
+    In fs_open(), 'vcc' is allocated through kmalloc() and assigned to
+    'atm_vcc->dev_data.' In the following execution, if an error occurs, e.g.,
+    there is no more free channel, an error code EBUSY or ENOMEM will be
+    returned. However, 'vcc' is not deallocated, leading to memory leaks. Note
+    that, in normal cases where fs_open() returns 0, 'vcc' will be deallocated
+    in fs_close(). But, if fs_open() fails, there is no guarantee that
+    fs_close() will be invoked.
+    
+    To fix this issue, deallocate 'vcc' before the error code is returned.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c
+index aad00d2b28f5..cc87004d5e2d 100644
+--- a/drivers/atm/firestream.c
++++ b/drivers/atm/firestream.c
+@@ -912,6 +912,7 @@ static int fs_open(struct atm_vcc *atm_vcc)
+ 			}
+ 			if (!to) {
+ 				printk ("No more free channels for FS50..\n");
++				kfree(vcc);
+ 				return -EBUSY;
+ 			}
+ 			vcc->channo = dev->channo;
+@@ -922,6 +923,7 @@ static int fs_open(struct atm_vcc *atm_vcc)
+ 			if (((DO_DIRECTION(rxtp) && dev->atm_vccs[vcc->channo])) ||
+ 			    ( DO_DIRECTION(txtp) && test_bit (vcc->channo, dev->tx_inuse))) {
+ 				printk ("Channel is in use for FS155.\n");
++				kfree(vcc);
+ 				return -EBUSY;
+ 			}
+ 		}
+@@ -935,6 +937,7 @@ static int fs_open(struct atm_vcc *atm_vcc)
+ 			    tc, sizeof (struct fs_transmit_config));
+ 		if (!tc) {
+ 			fs_dprintk (FS_DEBUG_OPEN, "fs: can't alloc transmit_config.\n");
++			kfree(vcc);
+ 			return -ENOMEM;
+ 		}
+ 

commit 8472ba62154058b64ebb83d5f57259a352d28697
+Author: Wenwen Wang 
+Date:   Mon Aug 12 00:59:21 2019 -0500
+
+    e1000: fix memory leaks
+    
+    In e1000_set_ringparam(), 'tx_old' and 'rx_old' are not deallocated if
+    e1000_up() fails, leading to memory leaks. Refactor the code to fix this
+    issue.
+    
+    Signed-off-by: Wenwen Wang 
+    Tested-by: Aaron Brown 
+    Signed-off-by: Jeff Kirsher 
+
+diff --git a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
+index 71d3d8854d8f..be56e631d693 100644
+--- a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
++++ b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
+@@ -607,6 +607,7 @@ static int e1000_set_ringparam(struct net_device *netdev,
+ 	for (i = 0; i < adapter->num_rx_queues; i++)
+ 		rxdr[i].count = rxdr->count;
+ 
++	err = 0;
+ 	if (netif_running(adapter->netdev)) {
+ 		/* Try to get new resources before deleting old */
+ 		err = e1000_setup_all_rx_resources(adapter);
+@@ -627,14 +628,13 @@ static int e1000_set_ringparam(struct net_device *netdev,
+ 		adapter->rx_ring = rxdr;
+ 		adapter->tx_ring = txdr;
+ 		err = e1000_up(adapter);
+-		if (err)
+-			goto err_setup;
+ 	}
+ 	kfree(tx_old);
+ 	kfree(rx_old);
+ 
+ 	clear_bit(__E1000_RESETTING, &adapter->flags);
+-	return 0;
++	return err;
++
+ err_setup_tx:
+ 	e1000_free_all_rx_resources(adapter);
+ err_setup_rx:
+@@ -646,7 +646,6 @@ static int e1000_set_ringparam(struct net_device *netdev,
+ err_alloc_tx:
+ 	if (netif_running(adapter->netdev))
+ 		e1000_up(adapter);
+-err_setup:
+ 	clear_bit(__E1000_RESETTING, &adapter->flags);
+ 	return err;
+ }

commit 334f5b61a6f29834e881923b98d1e27e5ce9620d
+Author: Wenwen Wang 
+Date:   Thu Aug 15 16:04:31 2019 -0500
+
+    ath10k: add cleanup in ath10k_sta_state()
+    
+    If 'sta->tdls' is false, no cleanup is executed, leading to memory/resource
+    leaks, e.g., 'arsta->tx_stats'. To fix this issue, perform cleanup before
+    go to the 'exit' label.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Kalle Valo 
+
+diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
+index ba167f4356cf..578d1c06ed87 100644
+--- a/drivers/net/wireless/ath/ath10k/mac.c
++++ b/drivers/net/wireless/ath/ath10k/mac.c
+@@ -6559,8 +6559,12 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
+ 
+ 		spin_unlock_bh(&ar->data_lock);
+ 
+-		if (!sta->tdls)
++		if (!sta->tdls) {
++			ath10k_peer_delete(ar, arvif->vdev_id, sta->addr);
++			ath10k_mac_dec_num_stations(arvif, sta);
++			kfree(arsta->tx_stats);
+ 			goto exit;
++		}
+ 
+ 		ret = ath10k_wmi_update_fw_tdls_state(ar, arvif->vdev_id,
+ 						      WMI_TDLS_ENABLE_ACTIVE);

commit 137e92fd14959506269d58e08dae35c0bb745211
+Author: Wenwen Wang 
+Date:   Sun Aug 18 11:36:44 2019 -0500
+
+    mtd: sm_ftl: Fix memory leak in sm_init_zone() error path
+    
+    In sm_init_zone(), 'zone->lba_to_phys_table' is allocated through
+    kmalloc_array() and 'zone->free_sectors' is allocated in kfifo_alloc()
+    respectively. However, they are not deallocated in the following execution
+    if sm_read_sector() fails, leading to memory leaks. To fix this issue, free
+    them before returning -EIO.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Richard Weinberger 
+
+diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c
+index dfc47a444b90..4744bf94ad9a 100644
+--- a/drivers/mtd/sm_ftl.c
++++ b/drivers/mtd/sm_ftl.c
+@@ -774,8 +774,11 @@ static int sm_init_zone(struct sm_ftl *ftl, int zone_num)
+ 			continue;
+ 
+ 		/* Read the oob of first sector */
+-		if (sm_read_sector(ftl, zone_num, block, 0, NULL, &oob))
++		if (sm_read_sector(ftl, zone_num, block, 0, NULL, &oob)) {
++			kfifo_free(&zone->free_sectors);
++			kfree(zone->lba_to_phys_table);
+ 			return -EIO;
++		}
+ 
+ 		/* Test to see if block is erased. It is enough to test
+ 			first sector, because erase happens in one shot */

commit 6a379f67454a3c740671ed6c7793b76ffecef50b
+Author: Wenwen Wang 
+Date:   Mon Aug 19 16:55:04 2019 -0500
+
+    jffs2: Fix memory leak in jffs2_scan_eraseblock() error path
+    
+    In jffs2_scan_eraseblock(), 'sumptr' is allocated through kmalloc() if
+    'sumlen' is larger than 'buf_size'. However, it is not deallocated in the
+    following execution if jffs2_fill_scan_buf() fails, leading to a memory
+    leak bug. To fix this issue, free 'sumptr' before returning the error.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Richard Weinberger 
+
+diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
+index 90431dd613b8..5f7e284e0df3 100644
+--- a/fs/jffs2/scan.c
++++ b/fs/jffs2/scan.c
+@@ -527,8 +527,11 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
+ 					err = jffs2_fill_scan_buf(c, sumptr, 
+ 								  jeb->offset + c->sector_size - sumlen,
+ 								  sumlen - buf_len);				
+-					if (err)
++					if (err) {
++						if (sumlen > buf_size)
++							kfree(sumptr);
+ 						return err;
++					}
+ 				}
+ 			}
+ 

commit 9163e0184bd7d5f779934d34581843f699ad2ffd
+Author: Wenwen Wang 
+Date:   Mon Aug 19 23:44:24 2019 -0500
+
+    ubifs: Fix memory leak bug in alloc_ubifs_info() error path
+    
+    In ubifs_mount(), 'c' is allocated through kzalloc() in alloc_ubifs_info().
+    However, it is not deallocated in the following execution if
+    ubifs_fill_super() fails, leading to a memory leak bug. To fix this issue,
+    free 'c' before going to the 'out_deact' label.
+    
+    Fixes: 1e51764a3c2a ("UBIFS: add new flash file system")
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Richard Weinberger 
+
+diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
+index 8c1d571334bc..fe9231fc4702 100644
+--- a/fs/ubifs/super.c
++++ b/fs/ubifs/super.c
+@@ -2256,8 +2256,10 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags,
+ 		}
+ 	} else {
+ 		err = ubifs_fill_super(sb, data, flags & SB_SILENT ? 1 : 0);
+-		if (err)
++		if (err) {
++			kfree(c);
+ 			goto out_deact;
++		}
+ 		/* We do not support atime */
+ 		sb->s_flags |= SB_ACTIVE;
+ 		if (IS_ENABLED(CONFIG_UBIFS_ATIME_SUPPORT))

commit 7992e00469c485f108a7f0da08be34b0fa441f79
+Author: Wenwen Wang 
+Date:   Mon Aug 19 22:24:50 2019 -0500
+
+    ubifs: Fix memory leak in __ubifs_node_verify_hmac error path
+    
+    In __ubifs_node_verify_hmac(), 'hmac' is allocated through kmalloc().
+    However, it is not deallocated in the following execution if
+    ubifs_node_calc_hmac() fails, leading to a memory leak bug. To fix this
+    issue, free 'hmac' before returning the error.
+    
+    Fixes: 49525e5eecca ("ubifs: Add helper functions for authentication support")
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Richard Weinberger 
+
+diff --git a/fs/ubifs/auth.c b/fs/ubifs/auth.c
+index d9af2de9084a..8cdbd53d780c 100644
+--- a/fs/ubifs/auth.c
++++ b/fs/ubifs/auth.c
+@@ -479,8 +479,10 @@ int __ubifs_node_verify_hmac(const struct ubifs_info *c, const void *node,
+ 		return -ENOMEM;
+ 
+ 	err = ubifs_node_calc_hmac(c, node, len, ofs_hmac, hmac);
+-	if (err)
++	if (err) {
++		kfree(hmac);
+ 		return err;
++	}
+ 
+ 	err = crypto_memneq(hmac, node + ofs_hmac, hmac_len);
+ 

commit ce4d8b16e64d062f1c6271a0068dbbbba2dee620
+Author: Wenwen Wang 
+Date:   Mon Aug 19 22:03:46 2019 -0500
+
+    ubifs: Fix memory leak in read_znode() error path
+    
+    In read_znode(), the indexing node 'idx' is allocated by kmalloc().
+    However, it is not deallocated in the following execution if
+    ubifs_node_check_hash() fails, leading to a memory leak bug. To fix this
+    issue, free 'idx' before returning the error.
+    
+    Fixes: 16a26b20d2af ("ubifs: authentication: Add hashes to index nodes")
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Richard Weinberger 
+
+diff --git a/fs/ubifs/tnc_misc.c b/fs/ubifs/tnc_misc.c
+index 6f293f662d98..49cb34c3f324 100644
+--- a/fs/ubifs/tnc_misc.c
++++ b/fs/ubifs/tnc_misc.c
+@@ -284,6 +284,7 @@ static int read_znode(struct ubifs_info *c, struct ubifs_zbranch *zzbr,
+ 	err = ubifs_node_check_hash(c, idx, zzbr->hash);
+ 	if (err) {
+ 		ubifs_bad_hash(c, idx, zzbr->hash, lnum, offs);
++		kfree(idx);
+ 		return err;
+ 	}
+ 

commit 22d11eacc32cab558e2620b6aad55d07e661847c
+Author: Wenwen Wang 
+Date:   Sun Aug 11 15:07:47 2019 -0500
+
+    ixgbe: fix memory leaks
+    
+    In ixgbe_configure_clsu32(), 'jump', 'input', and 'mask' are allocated
+    through kzalloc() respectively in a for loop body. Then,
+    ixgbe_clsu32_build_input() is invoked to build the input. If this process
+    fails, next iteration of the for loop will be executed. However, the
+    allocated 'jump', 'input', and 'mask' are not deallocated on this execution
+    path, leading to memory leaks.
+    
+    Signed-off-by: Wenwen Wang 
+    Tested-by: Andrew Bowers 
+    Signed-off-by: Jeff Kirsher 
+
+diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+index 99df595abfba..95c0827dfd4c 100644
+--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+@@ -9490,6 +9490,10 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
+ 				jump->mat = nexthdr[i].jump;
+ 				adapter->jump_tables[link_uhtid] = jump;
+ 				break;
++			} else {
++				kfree(mask);
++				kfree(input);
++				kfree(jump);
+ 			}
+ 		}
+ 		return 0;

commit 145a32fe57e3ce195f52611ebadd0df911a56615
+Author: Wenwen Wang 
+Date:   Thu Aug 15 22:50:02 2019 -0500
+
+    airo: fix memory leaks
+    
+    In proc_BSSList_open(), 'file->private_data' is allocated through kzalloc()
+    and 'data->rbuffer' is allocated through kmalloc(). In the following
+    execution, if an error occurs, they are not deallocated, leading to memory
+    leaks. To fix this issue, free the allocated memory regions before
+    returning the error.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Kalle Valo 
+
+diff --git a/drivers/net/wireless/cisco/airo.c b/drivers/net/wireless/cisco/airo.c
+index 9342ffbe1e81..f43c06569ea1 100644
+--- a/drivers/net/wireless/cisco/airo.c
++++ b/drivers/net/wireless/cisco/airo.c
+@@ -5441,11 +5441,18 @@ static int proc_BSSList_open( struct inode *inode, struct file *file ) {
+ 			Cmd cmd;
+ 			Resp rsp;
+ 
+-			if (ai->flags & FLAG_RADIO_MASK) return -ENETDOWN;
++			if (ai->flags & FLAG_RADIO_MASK) {
++				kfree(data->rbuffer);
++				kfree(file->private_data);
++				return -ENETDOWN;
++			}
+ 			memset(&cmd, 0, sizeof(cmd));
+ 			cmd.cmd=CMD_LISTBSS;
+-			if (down_interruptible(&ai->sem))
++			if (down_interruptible(&ai->sem)) {
++				kfree(data->rbuffer);
++				kfree(file->private_data);
+ 				return -ERESTARTSYS;
++			}
+ 			issuecommand(ai, &cmd, &rsp);
+ 			up(&ai->sem);
+ 			data->readlen = 0;

commit 29b49958cf73b439b17fa29e9a25210809a6c01c
+Author: Wenwen Wang 
+Date:   Tue Aug 20 22:44:19 2019 -0500
+
+    ACPI / PCI: fix acpi_pci_irq_enable() memory leak
+    
+    In acpi_pci_irq_enable(), 'entry' is allocated by kzalloc() in
+    acpi_pci_irq_check_entry() (invoked from acpi_pci_irq_lookup()). However,
+    it is not deallocated if acpi_pci_irq_valid() returns false, leading to a
+    memory leak. To fix this issue, free 'entry' before returning 0.
+    
+    Fixes: e237a5518425 ("x86/ACPI/PCI: Recognize that Interrupt Line 255 means "not connected"")
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
+index d2549ae65e1b..dea8a60e18a4 100644
+--- a/drivers/acpi/pci_irq.c
++++ b/drivers/acpi/pci_irq.c
+@@ -449,8 +449,10 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
+ 		 * No IRQ known to the ACPI subsystem - maybe the BIOS /
+ 		 * driver reported one, then use it. Exit in any case.
+ 		 */
+-		if (!acpi_pci_irq_valid(dev, pin))
++		if (!acpi_pci_irq_valid(dev, pin)) {
++			kfree(entry);
+ 			return 0;
++		}
+ 
+ 		if (acpi_isa_register_gsi(dev))
+ 			dev_warn(&dev->dev, "PCI INT %c: no GSI\n",

commit 03d1571d9513369c17e6848476763ebbd10ec2cb
+Author: Wenwen Wang 
+Date:   Fri Aug 16 00:08:27 2019 -0500
+
+    ACPI: custom_method: fix memory leaks
+    
+    In cm_write(), 'buf' is allocated through kzalloc(). In the following
+    execution, if an error occurs, 'buf' is not deallocated, leading to memory
+    leaks. To fix this issue, free 'buf' before returning the error.
+    
+    Fixes: 526b4af47f44 ("ACPI: Split out custom_method functionality into an own driver")
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/acpi/custom_method.c b/drivers/acpi/custom_method.c
+index b2ef4c2ec955..fd66a736621c 100644
+--- a/drivers/acpi/custom_method.c
++++ b/drivers/acpi/custom_method.c
+@@ -49,8 +49,10 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf,
+ 	if ((*ppos > max_size) ||
+ 	    (*ppos + count > max_size) ||
+ 	    (*ppos + count < count) ||
+-	    (count > uncopied_bytes))
++	    (count > uncopied_bytes)) {
++		kfree(buf);
+ 		return -EINVAL;
++	}
+ 
+ 	if (copy_from_user(buf + (*ppos), user_buf, count)) {
+ 		kfree(buf);
+@@ -70,6 +72,7 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf,
+ 		add_taint(TAINT_OVERRIDDEN_ACPI_TABLE, LOCKDEP_NOW_UNRELIABLE);
+ 	}
+ 
++	kfree(buf);
+ 	return count;
+ }
+ 

commit e027a2dea5fdde05740a98f571fc2903060559ce
+Author: Wenwen Wang 
+Date:   Mon Aug 19 16:00:02 2019 -0500
+
+    hwmon (coretemp) Fix a memory leak bug
+    
+    In coretemp_init(), 'zone_devices' is allocated through kcalloc().
+    However, it is not deallocated in the following execution if
+    platform_driver_register() fails, leading to a memory leak. To fix this
+    issue, introduce the 'outzone' label to free 'zone_devices' before
+    returning the error.
+    
+    Signed-off-by: Wenwen Wang 
+    Link: https://lore.kernel.org/r/1566248402-6538-1-git-send-email-wenwen@cs.uga.edu
+    Signed-off-by: Guenter Roeck 
+
+diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
+index fe6618e49dc4..d855c78fb8be 100644
+--- a/drivers/hwmon/coretemp.c
++++ b/drivers/hwmon/coretemp.c
+@@ -736,7 +736,7 @@ static int __init coretemp_init(void)
+ 
+ 	err = platform_driver_register(&coretemp_driver);
+ 	if (err)
+-		return err;
++		goto outzone;
+ 
+ 	err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "hwmon/coretemp:online",
+ 				coretemp_cpu_online, coretemp_cpu_offline);
+@@ -747,6 +747,7 @@ static int __init coretemp_init(void)
+ 
+ outdrv:
+ 	platform_driver_unregister(&coretemp_driver);
++outzone:
+ 	kfree(zone_devices);
+ 	return err;
+ }

commit 6ca5989e44d3a33710aef8c3f3e8e72156913412
+Author: Wenwen Wang 
+Date:   Sun Aug 18 03:40:04 2019 -0300
+
+    media: ti-vpe: Add cleanup in vpdma_list_cleanup()
+    
+    If an error occurs in this function, no cleanup is executed, leading to
+    memory/resource leaks. To fix this issue, introduce two labels to perform
+    the cleanup work.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/ti-vpe/vpdma.c b/drivers/media/platform/ti-vpe/vpdma.c
+index fd37d79e1619..53d27cd6e10a 100644
+--- a/drivers/media/platform/ti-vpe/vpdma.c
++++ b/drivers/media/platform/ti-vpe/vpdma.c
+@@ -445,23 +445,25 @@ int vpdma_list_cleanup(struct vpdma_data *vpdma, int list_num,
+ 
+ 	ret = vpdma_map_desc_buf(vpdma, &abort_list.buf);
+ 	if (ret)
+-		return ret;
++		goto free_desc;
+ 	ret = vpdma_submit_descs(vpdma, &abort_list, list_num);
+ 	if (ret)
+-		return ret;
++		goto unmap_desc;
+ 
+ 	while (vpdma_list_busy(vpdma, list_num) && --timeout)
+ 		;
+ 
+ 	if (timeout == 0) {
+ 		dev_err(&vpdma->pdev->dev, "Timed out cleaning up VPDMA list\n");
+-		return -EBUSY;
++		ret = -EBUSY;
+ 	}
+ 
++unmap_desc:
+ 	vpdma_unmap_desc_buf(vpdma, &abort_list.buf);
++free_desc:
+ 	vpdma_free_desc_buf(&abort_list.buf);
+ 
+-	return 0;
++	return ret;
+ }
+ EXPORT_SYMBOL(vpdma_list_cleanup);
+ 

commit 51d47e578a74c687bd71e462ef7db039ce38a964
+Author: Wenwen Wang 
+Date:   Sun Aug 18 02:58:53 2019 -0300
+
+    media: fdp1: Fix a memory leak bug
+    
+    In fdp1_open(), 'ctx' is allocated through kzalloc(). However, it is not
+    deallocated if v4l2_ctrl_new_std() fails, leading to a memory leak bug. To
+    fix this issue, free 'ctx' before going to the 'done' label.
+    
+    Signed-off-by: Wenwen Wang 
+    Reviewed-by: Kieran Bingham 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/rcar_fdp1.c b/drivers/media/platform/rcar_fdp1.c
+index c23ec127c277..cb93a13e1777 100644
+--- a/drivers/media/platform/rcar_fdp1.c
++++ b/drivers/media/platform/rcar_fdp1.c
+@@ -2122,6 +2122,7 @@ static int fdp1_open(struct file *file)
+ 	if (ctx->hdl.error) {
+ 		ret = ctx->hdl.error;
+ 		v4l2_ctrl_handler_free(&ctx->hdl);
++		kfree(ctx);
+ 		goto done;
+ 	}
+ 

commit 42e64117d3b4a759013f77bbcf25ab6700e55de7
+Author: Wenwen Wang 
+Date:   Sun Aug 18 02:40:14 2019 -0300
+
+    media: saa7146: add cleanup in hexium_attach()
+    
+    If saa7146_register_device() fails, no cleanup is executed, leading to
+    memory/resource leaks. To fix this issue, perform necessary cleanup work
+    before returning the error.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/pci/saa7146/hexium_gemini.c b/drivers/media/pci/saa7146/hexium_gemini.c
+index dca20a3d98e2..f96226930670 100644
+--- a/drivers/media/pci/saa7146/hexium_gemini.c
++++ b/drivers/media/pci/saa7146/hexium_gemini.c
+@@ -292,6 +292,9 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d
+ 	ret = saa7146_register_device(&hexium->video_dev, dev, "hexium gemini", VFL_TYPE_GRABBER);
+ 	if (ret < 0) {
+ 		pr_err("cannot register capture v4l2 device. skipping.\n");
++		saa7146_vv_release(dev);
++		i2c_del_adapter(&hexium->i2c_adapter);
++		kfree(hexium);
+ 		return ret;
+ 	}
+ 

commit 725a28290a53bcc02a3de1c1bf64a416d567b283
+Author: Wenwen Wang 
+Date:   Sat Aug 17 03:14:54 2019 -0300
+
+    media: usb: cx231xx-417: fix a memory leak bug
+    
+    In cx231xx_load_firmware(), 'p_buffer' is allocated through vmalloc() to
+    hold the firmware. However, after the usage, it is not deallocated, leading
+    to a memory leak bug.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c
+index 30624376679b..6d218a036966 100644
+--- a/drivers/media/usb/cx231xx/cx231xx-417.c
++++ b/drivers/media/usb/cx231xx/cx231xx-417.c
+@@ -1051,6 +1051,7 @@ static int cx231xx_load_firmware(struct cx231xx *dev)
+ 	p_current_fw = p_fw;
+ 	vfree(p_current_fw);
+ 	p_current_fw = NULL;
++	vfree(p_buffer);
+ 	uninitGPIO(dev);
+ 	release_firmware(firmware);
+ 	dprintk(1, "Firmware upload successful.\n");

commit 1c770f0f52dca1a2323c594f01f5ec6f1dddc97f
+Author: Wenwen Wang 
+Date:   Sat Aug 17 02:27:46 2019 -0300
+
+    media: cpia2_usb: fix memory leaks
+    
+    In submit_urbs(), 'cam->sbuf[i].data' is allocated through kmalloc_array().
+    However, it is not deallocated if the following allocation for urbs fails.
+    To fix this issue, free 'cam->sbuf[i].data' if usb_alloc_urb() fails.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/usb/cpia2/cpia2_usb.c b/drivers/media/usb/cpia2/cpia2_usb.c
+index 17468f7d78ed..3ab80a7b4498 100644
+--- a/drivers/media/usb/cpia2/cpia2_usb.c
++++ b/drivers/media/usb/cpia2/cpia2_usb.c
+@@ -676,6 +676,10 @@ static int submit_urbs(struct camera_data *cam)
+ 		if (!urb) {
+ 			for (j = 0; j < i; j++)
+ 				usb_free_urb(cam->sbuf[j].urb);
++			for (j = 0; j < NUM_SBUF; j++) {
++				kfree(cam->sbuf[j].data);
++				cam->sbuf[j].data = NULL;
++			}
+ 			return -ENOMEM;
+ 		}
+ 

commit 86aa04f4c2215912fcca6728f2dcf174f7e31fc4
+Author: Wenwen Wang 
+Date:   Sun Aug 18 21:46:04 2019 -0500
+
+    mtd: rawnand: Fix a memory leak bug
+    
+    In nand_scan_bbt(), a temporary buffer 'buf' is allocated through
+    vmalloc(). However, if check_create() fails, 'buf' is not deallocated,
+    leading to a memory leak bug. To fix this issue, free 'buf' before
+    returning the error.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Miquel Raynal 
+
+diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c
+index 2ef15ef94525..96045d60471e 100644
+--- a/drivers/mtd/nand/raw/nand_bbt.c
++++ b/drivers/mtd/nand/raw/nand_bbt.c
+@@ -1232,7 +1232,7 @@ static int nand_scan_bbt(struct nand_chip *this, struct nand_bbt_descr *bd)
+ 	if (!td) {
+ 		if ((res = nand_memory_bbt(this, bd))) {
+ 			pr_err("nand_bbt: can't scan flash and build the RAM-based BBT\n");
+-			goto err;
++			goto err_free_bbt;
+ 		}
+ 		return 0;
+ 	}
+@@ -1245,7 +1245,7 @@ static int nand_scan_bbt(struct nand_chip *this, struct nand_bbt_descr *bd)
+ 	buf = vmalloc(len);
+ 	if (!buf) {
+ 		res = -ENOMEM;
+-		goto err;
++		goto err_free_bbt;
+ 	}
+ 
+ 	/* Is the bbt at a given page? */
+@@ -1258,7 +1258,7 @@ static int nand_scan_bbt(struct nand_chip *this, struct nand_bbt_descr *bd)
+ 
+ 	res = check_create(this, buf, bd);
+ 	if (res)
+-		goto err;
++		goto err_free_buf;
+ 
+ 	/* Prevent the bbt regions from erasing / writing */
+ 	mark_bbt_region(this, td);
+@@ -1268,7 +1268,9 @@ static int nand_scan_bbt(struct nand_chip *this, struct nand_bbt_descr *bd)
+ 	vfree(buf);
+ 	return 0;
+ 
+-err:
++err_free_buf:
++	vfree(buf);
++err_free_bbt:
+ 	kfree(this->bbt);
+ 	this->bbt = NULL;
+ 	return res;

commit d83aef09aaa50bdafbb32981859128299abf32eb
+Author: Wenwen Wang 
+Date:   Sun Aug 18 10:52:49 2019 -0500
+
+    mtd: onenand_base: Fix a memory leak bug
+    
+    In onenand_scan(), if CONFIG_MTD_ONENAND_VERIFY_WRITE is defined,
+    'this->verify_buf' is allocated through kzalloc(). However, it is not
+    deallocated in the following execution, if the allocation for
+    'this->oob_buf' fails, leading to a memory leak bug. To fix this issue,
+    free 'this->verify_buf' before returning the error.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Miquel Raynal 
+
+diff --git a/drivers/mtd/nand/onenand/onenand_base.c b/drivers/mtd/nand/onenand/onenand_base.c
+index a1f8fe1abb10..dd9fced3a283 100644
+--- a/drivers/mtd/nand/onenand/onenand_base.c
++++ b/drivers/mtd/nand/onenand/onenand_base.c
+@@ -3879,6 +3879,9 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
+ 		if (!this->oob_buf) {
+ 			if (this->options & ONENAND_PAGEBUF_ALLOC) {
+ 				this->options &= ~ONENAND_PAGEBUF_ALLOC;
++#ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE
++				kfree(this->verify_buf);
++#endif
+ 				kfree(this->page_buf);
+ 			}
+ 			return -ENOMEM;

commit de0e4fd2f07ce3bbdb69dfb8d9426b7227451b69
+Author: Wenwen Wang 
+Date:   Tue Aug 20 23:46:36 2019 -0500
+
+    qed: Add cleanup in qed_slowpath_start()
+    
+    If qed_mcp_send_drv_version() fails, no cleanup is executed, leading to
+    memory leaks. To fix this issue, introduce the label 'err4' to perform the
+    cleanup work before returning the error.
+    
+    Signed-off-by: Wenwen Wang 
+    Acked-by: Sudarsana Reddy Kalluru 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
+index 829dd60ab937..1efff7f68ef6 100644
+--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
++++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
+@@ -1325,7 +1325,7 @@ static int qed_slowpath_start(struct qed_dev *cdev,
+ 					      &drv_version);
+ 		if (rc) {
+ 			DP_NOTICE(cdev, "Failed sending drv version command\n");
+-			return rc;
++			goto err4;
+ 		}
+ 	}
+ 
+@@ -1333,6 +1333,8 @@ static int qed_slowpath_start(struct qed_dev *cdev,
+ 
+ 	return 0;
+ 
++err4:
++	qed_ll2_dealloc_if(cdev);
+ err3:
+ 	qed_hw_stop(cdev);
+ err2:

commit fcd5ce4b3936242e6679875a4d3c3acfc8743e15
+Author: Wenwen Wang 
+Date:   Sun Aug 18 00:45:40 2019 -0300
+
+    media: dvb-core: fix a memory leak bug
+    
+    In dvb_create_media_entity(), 'dvbdev->entity' is allocated through
+    kzalloc(). Then, 'dvbdev->pads' is allocated through kcalloc(). However, if
+    kcalloc() fails, the allocated 'dvbdev->entity' is not deallocated, leading
+    to a memory leak bug. To fix this issue, free 'dvbdev->entity' before
+    returning -ENOMEM.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Sean Young 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c
+index d7532f5a352a..917fe034af37 100644
+--- a/drivers/media/dvb-core/dvbdev.c
++++ b/drivers/media/dvb-core/dvbdev.c
+@@ -339,8 +339,10 @@ static int dvb_create_media_entity(struct dvb_device *dvbdev,
+ 	if (npads) {
+ 		dvbdev->pads = kcalloc(npads, sizeof(*dvbdev->pads),
+ 				       GFP_KERNEL);
+-		if (!dvbdev->pads)
++		if (!dvbdev->pads) {
++			kfree(dvbdev->entity);
+ 			return -ENOMEM;
++		}
+ 	}
+ 
+ 	switch (type) {

commit 2f6451ed8b5223a28eab81116dd2f901c0dc9f4a
+Author: Wenwen Wang 
+Date:   Sat Aug 17 04:04:04 2019 -0300
+
+    media: dvb-frontends: fix a memory leak bug
+    
+    In cx24117_load_firmware(), 'buf' is allocated through kmalloc() to hold
+    the firmware. However, if i2c_transfer() fails, it is not deallocated,
+    leading to a memory leak bug.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Sean Young 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb-frontends/cx24117.c b/drivers/media/dvb-frontends/cx24117.c
+index 42697a5999f7..9fccc906d85a 100644
+--- a/drivers/media/dvb-frontends/cx24117.c
++++ b/drivers/media/dvb-frontends/cx24117.c
+@@ -619,8 +619,10 @@ static int cx24117_load_firmware(struct dvb_frontend *fe,
+ 
+ 	/* send fw */
+ 	ret = i2c_transfer(state->priv->i2c, &msg, 1);
+-	if (ret < 0)
++	if (ret < 0) {
++		kfree(buf);
+ 		return ret;
++	}
+ 
+ 	kfree(buf);
+ 

commit 8c3d3cdbd5dde9bc87d556d2daa9d771ac5254dc
+Author: Wenwen Wang 
+Date:   Sat Aug 17 03:42:24 2019 -0300
+
+    media: dvb-frontends: fix memory leaks
+    
+    In dib7000pc_detection(), 'tx' and 'rx' are allocated through kzalloc()
+    respectively. However, if DiB7000PC is detected, they are not deallocated,
+    leading to memory leaks. To fix this issue, create a label to free 'tx' and
+    'rx' before returning from the function.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Sean Young 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb-frontends/dib7000p.c b/drivers/media/dvb-frontends/dib7000p.c
+index 52f5e697c5dc..0d22c700016d 100644
+--- a/drivers/media/dvb-frontends/dib7000p.c
++++ b/drivers/media/dvb-frontends/dib7000p.c
+@@ -2036,7 +2036,8 @@ static int dib7000pc_detection(struct i2c_adapter *i2c_adap)
+ 	if (i2c_transfer(i2c_adap, msg, 2) == 2)
+ 		if (rx[0] == 0x01 && rx[1] == 0xb3) {
+ 			dprintk("-D-  DiB7000PC detected\n");
+-			return 1;
++			ret = 1;
++			goto out;
+ 		}
+ 
+ 	msg[0].addr = msg[1].addr = 0x40;
+@@ -2044,11 +2045,13 @@ static int dib7000pc_detection(struct i2c_adapter *i2c_adap)
+ 	if (i2c_transfer(i2c_adap, msg, 2) == 2)
+ 		if (rx[0] == 0x01 && rx[1] == 0xb3) {
+ 			dprintk("-D-  DiB7000PC detected\n");
+-			return 1;
++			ret = 1;
++			goto out;
+ 		}
+ 
+ 	dprintk("-D-  DiB7000PC not detected\n");
+ 
++out:
+ 	kfree(rx);
+ rx_memory_error:
+ 	kfree(tx);

commit 1e672e3644940d83bd94e7cb46bac6bb3627de02
+Author: Wenwen Wang 
+Date:   Tue Aug 20 22:21:21 2019 -0500
+
+    NFSv4: Fix a memory leak bug
+    
+    In nfs4_try_migration(), if nfs4_begin_drain_session() fails, the
+    previously allocated 'page' and 'locations' are not deallocated, leading to
+    memory leaks. To fix this issue, go to the 'out' label to free 'page' and
+    'locations' before returning the error.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Anna Schumaker 
+
+diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
+index cad4e064b328..e916aba7a799 100644
+--- a/fs/nfs/nfs4state.c
++++ b/fs/nfs/nfs4state.c
+@@ -2095,8 +2095,10 @@ static int nfs4_try_migration(struct nfs_server *server, const struct cred *cred
+ 	}
+ 
+ 	status = nfs4_begin_drain_session(clp);
+-	if (status != 0)
+-		return status;
++	if (status != 0) {
++		result = status;
++		goto out;
++	}
+ 
+ 	status = nfs4_replace_transport(server, locations);
+ 	if (status != 0) {

commit dc1a3e8e0cc6b2293b48c044710e63395aeb4fb4
+Author: Wenwen Wang 
+Date:   Sun Aug 18 19:18:34 2019 -0500
+
+    dm raid: add missing cleanup in raid_ctr()
+    
+    If rs_prepare_reshape() fails, no cleanup is executed, leading to
+    leak of the raid_set structure allocated at the beginning of
+    raid_ctr(). To fix this issue, go to the label 'bad' if the error
+    occurs.
+    
+    Fixes: 11e4723206683 ("dm raid: stop keeping raid set frozen altogether")
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Mike Snitzer 
+
+diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
+index 8a60a4a070ac..1f933dd197cd 100644
+--- a/drivers/md/dm-raid.c
++++ b/drivers/md/dm-raid.c
+@@ -3194,7 +3194,7 @@ static int raid_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+ 			  */
+ 			r = rs_prepare_reshape(rs);
+ 			if (r)
+-				return r;
++				goto bad;
+ 
+ 			/* Reshaping ain't recovery, so disable recovery */
+ 			rs_setup_recovery(rs, MaxSector);

commit 313aca5a9c781a19537e6cc882511c13eff3bdba
+Author: Wenwen Wang 
+Date:   Mon Aug 19 12:16:00 2019 -0500
+
+    mtd: spi-nor: fix a memory leak bug
+    
+    In spi_nor_parse_4bait(), 'dwords' is allocated through kmalloc(). However,
+    it is not deallocated in the following execution if spi_nor_read_sfdp()
+    fails, leading to a memory leak. To fix this issue, free 'dwords' before
+    returning the error.
+    
+    Fixes: 816873eaeec6 ("mtd: spi-nor: parse SFDP 4-byte Address Instruction Table")
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Tudor Ambarus 
+
+diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
+index ba99d903eda0..fdf776cac3c7 100644
+--- a/drivers/mtd/spi-nor/spi-nor.c
++++ b/drivers/mtd/spi-nor/spi-nor.c
+@@ -3957,7 +3957,7 @@ static int spi_nor_parse_4bait(struct spi_nor *nor,
+ 	addr = SFDP_PARAM_HEADER_PTP(param_header);
+ 	ret = spi_nor_read_sfdp(nor, addr, len, dwords);
+ 	if (ret)
+-		return ret;
++		goto out;
+ 
+ 	/* Fix endianness of the 4BAIT DWORDs. */
+ 	for (i = 0; i < SFDP_4BAIT_DWORD_MAX; i++)

commit 60e2dde1e91ae0addb21ac380cc36ebee7534e49
+Author: Wenwen Wang 
+Date:   Mon Aug 19 15:41:42 2019 -0500
+
+    led: triggers: Fix a memory leak bug
+    
+    In led_trigger_set(), 'event' is allocated in kasprintf(). However, it is
+    not deallocated in the following execution if the label 'err_activate' or
+    'err_add_groups' is entered, leading to memory leaks. To fix this issue,
+    free 'event' before returning the error.
+    
+    Fixes: 52c47742f79d ("leds: triggers: send uevent when changing triggers")
+    Signed-off-by: Wenwen Wang 
+    Acked-by: Pavel Machek 
+    Signed-off-by: Jacek Anaszewski 
+
+diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
+index 8d11a5e23227..eff1bda8b520 100644
+--- a/drivers/leds/led-triggers.c
++++ b/drivers/leds/led-triggers.c
+@@ -173,6 +173,7 @@ int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
+ 	list_del(&led_cdev->trig_list);
+ 	write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock, flags);
+ 	led_set_brightness(led_cdev, LED_OFF);
++	kfree(event);
+ 
+ 	return ret;
+ }

commit 2323d7baab2b18d87d9bc267452e387aa9f0060a
+Author: Wenwen Wang 
+Date:   Sun Aug 18 13:54:46 2019 -0500
+
+    infiniband: hfi1: fix memory leaks
+    
+    In fault_opcodes_write(), 'data' is allocated through kcalloc(). However,
+    it is not deallocated in the following execution if an error occurs,
+    leading to memory leaks. To fix this issue, introduce the 'free_data' label
+    to free 'data' before returning the error.
+    
+    Signed-off-by: Wenwen Wang 
+    Reviewed-by: Leon Romanovsky 
+    Acked-by: Dennis Dalessandro 
+    Link: https://lore.kernel.org/r/1566154486-3713-1-git-send-email-wenwen@cs.uga.edu
+    Signed-off-by: Doug Ledford 
+
+diff --git a/drivers/infiniband/hw/hfi1/fault.c b/drivers/infiniband/hw/hfi1/fault.c
+index 814324d17295..986c12153e62 100644
+--- a/drivers/infiniband/hw/hfi1/fault.c
++++ b/drivers/infiniband/hw/hfi1/fault.c
+@@ -141,12 +141,14 @@ static ssize_t fault_opcodes_write(struct file *file, const char __user *buf,
+ 	if (!data)
+ 		return -ENOMEM;
+ 	copy = min(len, datalen - 1);
+-	if (copy_from_user(data, buf, copy))
+-		return -EFAULT;
++	if (copy_from_user(data, buf, copy)) {
++		ret = -EFAULT;
++		goto free_data;
++	}
+ 
+ 	ret = debugfs_file_get(file->f_path.dentry);
+ 	if (unlikely(ret))
+-		return ret;
++		goto free_data;
+ 	ptr = data;
+ 	token = ptr;
+ 	for (ptr = data; *ptr; ptr = end + 1, token = ptr) {
+@@ -195,6 +197,7 @@ static ssize_t fault_opcodes_write(struct file *file, const char __user *buf,
+ 	ret = len;
+ 
+ 	debugfs_file_put(file->f_path.dentry);
++free_data:
+ 	kfree(data);
+ 	return ret;
+ }

commit b08afa064c320e5d85cdc27228426b696c4c8dae
+Author: Wenwen Wang 
+Date:   Sun Aug 18 14:29:31 2019 -0500
+
+    infiniband: hfi1: fix a memory leak bug
+    
+    In fault_opcodes_read(), 'data' is not deallocated if debugfs_file_get()
+    fails, leading to a memory leak. To fix this bug, introduce the 'free_data'
+    label to free 'data' before returning the error.
+    
+    Signed-off-by: Wenwen Wang 
+    Reviewed-by: Leon Romanovsky 
+    Acked-by: Dennis Dalessandro 
+    Link: https://lore.kernel.org/r/1566156571-4335-1-git-send-email-wenwen@cs.uga.edu
+    Signed-off-by: Doug Ledford 
+
+diff --git a/drivers/infiniband/hw/hfi1/fault.c b/drivers/infiniband/hw/hfi1/fault.c
+index 93613e5def9b..814324d17295 100644
+--- a/drivers/infiniband/hw/hfi1/fault.c
++++ b/drivers/infiniband/hw/hfi1/fault.c
+@@ -214,7 +214,7 @@ static ssize_t fault_opcodes_read(struct file *file, char __user *buf,
+ 		return -ENOMEM;
+ 	ret = debugfs_file_get(file->f_path.dentry);
+ 	if (unlikely(ret))
+-		return ret;
++		goto free_data;
+ 	bit = find_first_bit(fault->opcodes, bitsize);
+ 	while (bit < bitsize) {
+ 		zero = find_next_zero_bit(fault->opcodes, bitsize, bit);
+@@ -232,6 +232,7 @@ static ssize_t fault_opcodes_read(struct file *file, char __user *buf,
+ 	data[size - 1] = '\n';
+ 	data[size] = '\0';
+ 	ret = simple_read_from_buffer(buf, len, pos, data, size);
++free_data:
+ 	kfree(data);
+ 	return ret;
+ }

commit 5c1baaa82cea2c815a5180ded402a7cd455d1810
+Author: Wenwen Wang 
+Date:   Sun Aug 18 15:23:01 2019 -0500
+
+    IB/mlx4: Fix memory leaks
+    
+    In mlx4_ib_alloc_pv_bufs(), 'tun_qp->tx_ring' is allocated through
+    kcalloc(). However, it is not always deallocated in the following execution
+    if an error occurs, leading to memory leaks. To fix this issue, free
+    'tun_qp->tx_ring' whenever an error occurs.
+    
+    Signed-off-by: Wenwen Wang 
+    Acked-by: Leon Romanovsky 
+    Link: https://lore.kernel.org/r/1566159781-4642-1-git-send-email-wenwen@cs.uga.edu
+    Signed-off-by: Doug Ledford 
+
+diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
+index 68c951491a08..57079110af9b 100644
+--- a/drivers/infiniband/hw/mlx4/mad.c
++++ b/drivers/infiniband/hw/mlx4/mad.c
+@@ -1677,8 +1677,6 @@ static int mlx4_ib_alloc_pv_bufs(struct mlx4_ib_demux_pv_ctx *ctx,
+ 				    tx_buf_size, DMA_TO_DEVICE);
+ 		kfree(tun_qp->tx_ring[i].buf.addr);
+ 	}
+-	kfree(tun_qp->tx_ring);
+-	tun_qp->tx_ring = NULL;
+ 	i = MLX4_NUM_TUNNEL_BUFS;
+ err:
+ 	while (i > 0) {
+@@ -1687,6 +1685,8 @@ static int mlx4_ib_alloc_pv_bufs(struct mlx4_ib_demux_pv_ctx *ctx,
+ 				    rx_buf_size, DMA_FROM_DEVICE);
+ 		kfree(tun_qp->ring[i].addr);
+ 	}
++	kfree(tun_qp->tx_ring);
++	tun_qp->tx_ring = NULL;
+ 	kfree(tun_qp->ring);
+ 	tun_qp->ring = NULL;
+ 	return -ENOMEM;

commit 962411b05a6d3342aa649e39cda1704c1fc042c6
+Author: Wenwen Wang 
+Date:   Fri Aug 16 01:56:08 2019 -0500
+
+    dmaengine: ti: omap-dma: Add cleanup in omap_dma_probe()
+    
+    If devm_request_irq() fails to disable all interrupts, no cleanup is
+    performed before retuning the error. To fix this issue, invoke
+    omap_dma_free() to do the cleanup.
+    
+    Signed-off-by: Wenwen Wang 
+    Acked-by: Peter Ujfalusi 
+    Link: https://lore.kernel.org/r/1565938570-7528-1-git-send-email-wenwen@cs.uga.edu
+    Signed-off-by: Vinod Koul 
+
+diff --git a/drivers/dma/ti/omap-dma.c b/drivers/dma/ti/omap-dma.c
+index ba27802efcd0..d07c0d5de7a2 100644
+--- a/drivers/dma/ti/omap-dma.c
++++ b/drivers/dma/ti/omap-dma.c
+@@ -1540,8 +1540,10 @@ static int omap_dma_probe(struct platform_device *pdev)
+ 
+ 		rc = devm_request_irq(&pdev->dev, irq, omap_dma_irq,
+ 				      IRQF_SHARED, "omap-dma-engine", od);
+-		if (rc)
++		if (rc) {
++			omap_dma_free(od);
+ 			return rc;
++		}
+ 	}
+ 
+ 	if (omap_dma_glbl_read(od, CAPS_0) & CAPS_0_SUPPORT_LL123)

commit 2c231c0c1dec42192aca0f87f2dc68b8f0cbc7d2
+Author: Wenwen Wang 
+Date:   Fri Aug 16 01:48:55 2019 -0500
+
+    dmaengine: ti: dma-crossbar: Fix a memory leak bug
+    
+    In ti_dra7_xbar_probe(), 'rsv_events' is allocated through kcalloc(). Then
+    of_property_read_u32_array() is invoked to search for the property.
+    However, if this process fails, 'rsv_events' is not deallocated, leading to
+    a memory leak bug. To fix this issue, free 'rsv_events' before returning
+    the error.
+    
+    Signed-off-by: Wenwen Wang 
+    Acked-by: Peter Ujfalusi 
+    Link: https://lore.kernel.org/r/1565938136-7249-1-git-send-email-wenwen@cs.uga.edu
+    Signed-off-by: Vinod Koul 
+
+diff --git a/drivers/dma/ti/dma-crossbar.c b/drivers/dma/ti/dma-crossbar.c
+index ad2f0a4cd6a4..f255056696ee 100644
+--- a/drivers/dma/ti/dma-crossbar.c
++++ b/drivers/dma/ti/dma-crossbar.c
+@@ -391,8 +391,10 @@ static int ti_dra7_xbar_probe(struct platform_device *pdev)
+ 
+ 		ret = of_property_read_u32_array(node, pname, (u32 *)rsv_events,
+ 						 nelm * 2);
+-		if (ret)
++		if (ret) {
++			kfree(rsv_events);
+ 			return ret;
++		}
+ 
+ 		for (i = 0; i < nelm; i++) {
+ 			ti_dra7_xbar_reserve(rsv_events[i][0], rsv_events[i][1],

commit cfddf9f4c9f038c91c6c61d5cf3a161731b5c418
+Author: Wenwen Wang 
+Date:   Mon Aug 19 18:47:34 2019 -0500
+
+    locks: fix a memory leak bug in __break_lease()
+    
+    In __break_lease(), the file lock 'new_fl' is allocated in lease_alloc().
+    However, it is not deallocated in the following execution if
+    smp_load_acquire() fails, leading to a memory leak bug. To fix this issue,
+    free 'new_fl' before returning the error.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Jeff Layton 
+
+diff --git a/fs/locks.c b/fs/locks.c
+index 24d1db632f6c..a364ebc5cec3 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -1592,7 +1592,7 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
+ 	ctx = smp_load_acquire(&inode->i_flctx);
+ 	if (!ctx) {
+ 		WARN_ON_ONCE(1);
+-		return error;
++		goto free_lock;
+ 	}
+ 
+ 	percpu_down_read(&file_rwsem);
+@@ -1672,6 +1672,7 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
+ 	spin_unlock(&ctx->flc_lock);
+ 	percpu_up_read(&file_rwsem);
+ 	locks_dispose_list(&dispose);
++free_lock:
+ 	locks_free_lock(new_fl);
+ 	return error;
+ }

commit b4a81b87a4cfe2bb26a4a943b748d96a43ef20e8
+Author: Wenwen Wang 
+Date:   Tue Aug 20 00:33:54 2019 -0500
+
+    ecryptfs: fix a memory leak bug in ecryptfs_init_messaging()
+    
+    In ecryptfs_init_messaging(), if the allocation for 'ecryptfs_msg_ctx_arr'
+    fails, the previously allocated 'ecryptfs_daemon_hash' is not deallocated,
+    leading to a memory leak bug. To fix this issue, free
+    'ecryptfs_daemon_hash' before returning the error.
+    
+    Cc: stable@vger.kernel.org
+    Fixes: 88b4a07e6610 ("[PATCH] eCryptfs: Public key transport mechanism")
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Tyler Hicks 
+
+diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c
+index d668e60b85b5..c05ca39aa449 100644
+--- a/fs/ecryptfs/messaging.c
++++ b/fs/ecryptfs/messaging.c
+@@ -379,6 +379,7 @@ int __init ecryptfs_init_messaging(void)
+ 					* ecryptfs_message_buf_len),
+ 				       GFP_KERNEL);
+ 	if (!ecryptfs_msg_ctx_arr) {
++		kfree(ecryptfs_daemon_hash);
+ 		rc = -ENOMEM;
+ 		goto out;
+ 	}

commit fe2e082f5da5b4a0a92ae32978f81507ef37ec66
+Author: Wenwen Wang 
+Date:   Tue Aug 20 00:16:40 2019 -0500
+
+    ecryptfs: fix a memory leak bug in parse_tag_1_packet()
+    
+    In parse_tag_1_packet(), if tag 1 packet contains a key larger than
+    ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES, no cleanup is executed, leading to a
+    memory leak on the allocated 'auth_tok_list_item'. To fix this issue, go to
+    the label 'out_free' to perform the cleanup work.
+    
+    Cc: stable@vger.kernel.org
+    Fixes: dddfa461fc89 ("[PATCH] eCryptfs: Public key; packet management")
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Tyler Hicks 
+
+diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
+index 216fbe6a4837..4dc09638de8f 100644
+--- a/fs/ecryptfs/keystore.c
++++ b/fs/ecryptfs/keystore.c
+@@ -1304,7 +1304,7 @@ parse_tag_1_packet(struct ecryptfs_crypt_stat *crypt_stat,
+ 		printk(KERN_WARNING "Tag 1 packet contains key larger "
+ 		       "than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES\n");
+ 		rc = -EINVAL;
+-		goto out;
++		goto out_free;
+ 	}
+ 	memcpy((*new_auth_tok)->session_key.encrypted_key,
+ 	       &data[(*packet_size)], (body_size - (ECRYPTFS_SIG_SIZE + 2)));

commit 44ef3a03252844a8753479b0cea7f29e4a804bdc
+Author: Wenwen Wang 
+Date:   Thu Aug 15 15:29:51 2019 -0500
+
+    wimax/i2400m: fix a memory leak bug
+    
+    In i2400m_barker_db_init(), 'options_orig' is allocated through kstrdup()
+    to hold the original command line options. Then, the options are parsed.
+    However, if an error occurs during the parsing process, 'options_orig' is
+    not deallocated, leading to a memory leak bug. To fix this issue, free
+    'options_orig' before returning the error.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c
+index e9fc168bb734..489cba9b284d 100644
+--- a/drivers/net/wimax/i2400m/fw.c
++++ b/drivers/net/wimax/i2400m/fw.c
+@@ -351,13 +351,15 @@ int i2400m_barker_db_init(const char *_options)
+ 			}
+ 			result = i2400m_barker_db_add(barker);
+ 			if (result < 0)
+-				goto error_add;
++				goto error_parse_add;
+ 		}
+ 		kfree(options_orig);
+ 	}
+ 	return 0;
+ 
++error_parse_add:
+ error_parse:
++	kfree(options_orig);
+ error_add:
+ 	kfree(i2400m_barker_db);
+ 	return result;

commit f1472cb09f11ddb41d4be84f0650835cb65a9073
+Author: Wenwen Wang 
+Date:   Wed Aug 14 13:56:43 2019 -0500
+
+    net: kalmia: fix memory leaks
+    
+    In kalmia_init_and_get_ethernet_addr(), 'usb_buf' is allocated through
+    kmalloc(). In the following execution, if the 'status' returned by
+    kalmia_send_init_packet() is not 0, 'usb_buf' is not deallocated, leading
+    to memory leaks. To fix this issue, add the 'out' label to free 'usb_buf'.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/usb/kalmia.c b/drivers/net/usb/kalmia.c
+index d62b6706a537..fc5895f85cee 100644
+--- a/drivers/net/usb/kalmia.c
++++ b/drivers/net/usb/kalmia.c
+@@ -113,16 +113,16 @@ kalmia_init_and_get_ethernet_addr(struct usbnet *dev, u8 *ethernet_addr)
+ 	status = kalmia_send_init_packet(dev, usb_buf, ARRAY_SIZE(init_msg_1),
+ 					 usb_buf, 24);
+ 	if (status != 0)
+-		return status;
++		goto out;
+ 
+ 	memcpy(usb_buf, init_msg_2, 12);
+ 	status = kalmia_send_init_packet(dev, usb_buf, ARRAY_SIZE(init_msg_2),
+ 					 usb_buf, 28);
+ 	if (status != 0)
+-		return status;
++		goto out;
+ 
+ 	memcpy(ethernet_addr, usb_buf + 10, ETH_ALEN);
+-
++out:
+ 	kfree(usb_buf);
+ 	return status;
+ }

commit 1eca92eef18719027d394bf1a2d276f43e7cf886
+Author: Wenwen Wang 
+Date:   Wed Aug 14 13:03:38 2019 -0500
+
+    cx82310_eth: fix a memory leak bug
+    
+    In cx82310_bind(), 'dev->partial_data' is allocated through kmalloc().
+    Then, the execution waits for the firmware to become ready. If the firmware
+    is not ready in time, the execution is terminated. However, the allocated
+    'dev->partial_data' is not deallocated on this path, leading to a memory
+    leak bug. To fix this issue, free 'dev->partial_data' before returning the
+    error.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/usb/cx82310_eth.c b/drivers/net/usb/cx82310_eth.c
+index 5519248a791e..32b08b18e120 100644
+--- a/drivers/net/usb/cx82310_eth.c
++++ b/drivers/net/usb/cx82310_eth.c
+@@ -163,7 +163,8 @@ static int cx82310_bind(struct usbnet *dev, struct usb_interface *intf)
+ 	}
+ 	if (!timeout) {
+ 		dev_err(&udev->dev, "firmware not ready in time\n");
+-		return -ETIMEDOUT;
++		ret = -ETIMEDOUT;
++		goto err;
+ 	}
+ 
+ 	/* enable ethernet mode (?) */

commit b9cbf8a64865b50fd0f4a3915fa00ac7365cdf8f
+Author: Wenwen Wang 
+Date:   Wed Aug 14 11:23:13 2019 -0500
+
+    lan78xx: Fix memory leaks
+    
+    In lan78xx_probe(), a new urb is allocated through usb_alloc_urb() and
+    saved to 'dev->urb_intr'. However, in the following execution, if an error
+    occurs, 'dev->urb_intr' is not deallocated, leading to memory leaks. To fix
+    this issue, invoke usb_free_urb() to free the allocated urb before
+    returning from the function.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
+index 3d92ea6fcc02..f033fee225a1 100644
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -3792,7 +3792,7 @@ static int lan78xx_probe(struct usb_interface *intf,
+ 	ret = register_netdev(netdev);
+ 	if (ret != 0) {
+ 		netif_err(dev, probe, netdev, "couldn't register the device\n");
+-		goto out3;
++		goto out4;
+ 	}
+ 
+ 	usb_set_intfdata(intf, dev);
+@@ -3807,12 +3807,14 @@ static int lan78xx_probe(struct usb_interface *intf,
+ 
+ 	ret = lan78xx_phy_init(dev);
+ 	if (ret < 0)
+-		goto out4;
++		goto out5;
+ 
+ 	return 0;
+ 
+-out4:
++out5:
+ 	unregister_netdev(netdev);
++out4:
++	usb_free_urb(dev->urb_intr);
+ out3:
+ 	lan78xx_unbind(dev, intf);
+ out2:

commit 20fb7c7a39b5c719e2e619673b5f5729ee7d2306
+Author: Wenwen Wang 
+Date:   Wed Aug 14 01:38:39 2019 -0500
+
+    net: myri10ge: fix memory leaks
+    
+    In myri10ge_probe(), myri10ge_alloc_slices() is invoked to allocate slices
+    related structures. Later on, myri10ge_request_irq() is used to get an irq.
+    However, if this process fails, the allocated slices related structures are
+    not deallocated, leading to memory leaks. To fix this issue, revise the
+    target label of the goto statement to 'abort_with_slices'.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+index d8b7fba96d58..337b0cbfd153 100644
+--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
++++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+@@ -3919,7 +3919,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	 * setup (if available). */
+ 	status = myri10ge_request_irq(mgp);
+ 	if (status != 0)
+-		goto abort_with_firmware;
++		goto abort_with_slices;
+ 	myri10ge_free_irq(mgp);
+ 
+ 	/* Save configuration space to be restored if the

commit 6f967f8b1be7001b31c46429f2ee7d275af2190f
+Author: Wenwen Wang 
+Date:   Wed Aug 14 00:14:49 2019 -0500
+
+    liquidio: add cleanup in octeon_setup_iq()
+    
+    If oct->fn_list.enable_io_queues() fails, no cleanup is executed, leading
+    to memory/resource leaks. To fix this issue, invoke
+    octeon_delete_instr_queue() before returning from the function.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/cavium/liquidio/request_manager.c b/drivers/net/ethernet/cavium/liquidio/request_manager.c
+index 032224178b64..6dd65f9b347c 100644
+--- a/drivers/net/ethernet/cavium/liquidio/request_manager.c
++++ b/drivers/net/ethernet/cavium/liquidio/request_manager.c
+@@ -237,8 +237,10 @@ int octeon_setup_iq(struct octeon_device *oct,
+ 	}
+ 
+ 	oct->num_iqs++;
+-	if (oct->fn_list.enable_io_queues(oct))
++	if (oct->fn_list.enable_io_queues(oct)) {
++		octeon_delete_instr_queue(oct, iq_no);
+ 		return 1;
++	}
+ 
+ 	return 0;
+ }

commit c554336efa9bbc28d6ec14efbee3c7d63c61a34f
+Author: Wenwen Wang 
+Date:   Tue Aug 13 04:18:52 2019 -0500
+
+    cxgb4: fix a memory leak bug
+    
+    In blocked_fl_write(), 't' is not deallocated if bitmap_parse_user() fails,
+    leading to a memory leak bug. To fix this issue, free t before returning
+    the error.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
+index 02959035ed3f..d692251ee252 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
++++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
+@@ -3236,8 +3236,10 @@ static ssize_t blocked_fl_write(struct file *filp, const char __user *ubuf,
+ 		return -ENOMEM;
+ 
+ 	err = bitmap_parse_user(ubuf, count, t, adap->sge.egr_sz);
+-	if (err)
++	if (err) {
++		kvfree(t);
+ 		return err;
++	}
+ 
+ 	bitmap_copy(adap->sge.blocked_fl, t, adap->sge.egr_sz);
+ 	kvfree(t);

commit 48ec7014c56e5eb2fbf6f479896143622d834f3b
+Author: Wenwen Wang 
+Date:   Mon Aug 12 14:11:35 2019 -0500
+
+    net/mlx4_en: fix a memory leak bug
+    
+    In mlx4_en_config_rss_steer(), 'rss_map->indir_qp' is allocated through
+    kzalloc(). After that, mlx4_qp_alloc() is invoked to configure RSS
+    indirection. However, if mlx4_qp_alloc() fails, the allocated
+    'rss_map->indir_qp' is not deallocated, leading to a memory leak bug.
+    
+    To fix the above issue, add the 'qp_alloc_err' label to free
+    'rss_map->indir_qp'.
+    
+    Fixes: 4931c6ef04b4 ("net/mlx4_en: Optimized single ring steering")
+    Signed-off-by: Wenwen Wang 
+    Reviewed-by: Tariq Toukan 
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+index 6c01314e87b0..db3552f2d087 100644
+--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
++++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+@@ -1187,7 +1187,7 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
+ 	err = mlx4_qp_alloc(mdev->dev, priv->base_qpn, rss_map->indir_qp);
+ 	if (err) {
+ 		en_err(priv, "Failed to allocate RSS indirection QP\n");
+-		goto rss_err;
++		goto qp_alloc_err;
+ 	}
+ 
+ 	rss_map->indir_qp->event = mlx4_en_sqp_event;
+@@ -1241,6 +1241,7 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
+ 		       MLX4_QP_STATE_RST, NULL, 0, 0, rss_map->indir_qp);
+ 	mlx4_qp_remove(mdev->dev, rss_map->indir_qp);
+ 	mlx4_qp_free(mdev->dev, rss_map->indir_qp);
++qp_alloc_err:
+ 	kfree(rss_map->indir_qp);
+ 	rss_map->indir_qp = NULL;
+ rss_err:

commit ae78ca3cf3d9e9f914bfcd0bc5c389ff18b9c2e0
+Author: Wenwen Wang 
+Date:   Sun Aug 11 12:23:22 2019 -0500
+
+    xen/blkback: fix memory leaks
+    
+    In read_per_ring_refs(), after 'req' and related memory regions are
+    allocated, xen_blkif_map() is invoked to map the shared frame, irq, and
+    etc. However, if this mapping process fails, no cleanup is performed,
+    leading to memory leaks. To fix this issue, invoke the cleanup before
+    returning the error.
+    
+    Acked-by: Roger Pau Monné 
+    Reviewed-by: Boris Ostrovsky 
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c
+index 3ac6a5d18071..b90dbcd99c03 100644
+--- a/drivers/block/xen-blkback/xenbus.c
++++ b/drivers/block/xen-blkback/xenbus.c
+@@ -965,6 +965,7 @@ static int read_per_ring_refs(struct xen_blkif_ring *ring, const char *dir)
+ 		}
+ 	}
+ 
++	err = -ENOMEM;
+ 	for (i = 0; i < nr_grefs * XEN_BLKIF_REQS_PER_PAGE; i++) {
+ 		req = kzalloc(sizeof(*req), GFP_KERNEL);
+ 		if (!req)
+@@ -987,7 +988,7 @@ static int read_per_ring_refs(struct xen_blkif_ring *ring, const char *dir)
+ 	err = xen_blkif_map(ring, ring_ref, nr_grefs, evtchn);
+ 	if (err) {
+ 		xenbus_dev_fatal(dev, err, "mapping ring-ref port %u", evtchn);
+-		return err;
++		goto fail;
+ 	}
+ 
+ 	return 0;
+@@ -1007,8 +1008,7 @@ static int read_per_ring_refs(struct xen_blkif_ring *ring, const char *dir)
+ 		}
+ 		kfree(req);
+ 	}
+-	return -ENOMEM;
+-
++	return err;
+ }
+ 
+ static int connect_ring(struct backend_info *be)

commit 7afe9a4e56658bd659660ea10671831664469e5f
+Author: Wenwen Wang 
+Date:   Sun Aug 11 13:33:06 2019 -0500
+
+    i3c: master: fix a memory leak bug
+    
+    In i3c_master_getmwl_locked(), the buffer used for the dest payload data is
+    allocated using kzalloc() in i3c_ccc_cmd_dest_init(). Later on, the length
+    of the dest payload data is checked against 'sizeof(*mwl)'. If they are not
+    equal, -EIO is returned to indicate the error. However, the allocated
+    buffer is not deallocated on this path, leading to a memory leak.
+    
+    To fix the above issue, free the buffer before returning the error.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Boris Brezillon 
+
+diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
+index a38fdf325d30..8ff527263f46 100644
+--- a/drivers/i3c/master.c
++++ b/drivers/i3c/master.c
+@@ -1041,8 +1041,10 @@ static int i3c_master_getmwl_locked(struct i3c_master_controller *master,
+ 	if (ret)
+ 		goto out;
+ 
+-	if (dest.payload.len != sizeof(*mwl))
+-		return -EIO;
++	if (dest.payload.len != sizeof(*mwl)) {
++		ret = -EIO;
++		goto out;
++	}
+ 
+ 	info->max_write_len = be16_to_cpu(mwl->len);
+ 

commit cfef67f016e4c00a2f423256fc678a6967a9fc09
+Author: Wenwen Wang 
+Date:   Fri Aug 9 23:29:48 2019 -0500
+
+    ALSA: hda - Fix a memory leak bug
+    
+    In snd_hda_parse_generic_codec(), 'spec' is allocated through kzalloc().
+    Then, the pin widgets in 'codec' are parsed. However, if the parsing
+    process fails, 'spec' is not deallocated, leading to a memory leak.
+    
+    To fix the above issue, free 'spec' before returning the error.
+    
+    Fixes: 352f7f914ebb ("ALSA: hda - Merge Realtek parser code to generic parser")
+    Signed-off-by: Wenwen Wang 
+    Cc: 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
+index 485edaba0037..8f2beb1f3ae4 100644
+--- a/sound/pci/hda/hda_generic.c
++++ b/sound/pci/hda/hda_generic.c
+@@ -6100,7 +6100,7 @@ static int snd_hda_parse_generic_codec(struct hda_codec *codec)
+ 
+ 	err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0);
+ 	if (err < 0)
+-		return err;
++		goto error;
+ 
+ 	err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg);
+ 	if (err < 0)

commit 1be3c1fae6c1e1f5bb982b255d2034034454527a
+Author: Wenwen Wang 
+Date:   Thu Aug 8 00:50:58 2019 -0500
+
+    ALSA: firewire: fix a memory leak bug
+    
+    In iso_packets_buffer_init(), 'b->packets' is allocated through
+    kmalloc_array(). Then, the aligned packet size is checked. If it is
+    larger than PAGE_SIZE, -EINVAL will be returned to indicate the error.
+    However, the allocated 'b->packets' is not deallocated on this path,
+    leading to a memory leak.
+    
+    To fix the above issue, free 'b->packets' before returning the error code.
+    
+    Fixes: 31ef9134eb52 ("ALSA: add LaCie FireWire Speakers/Griffin FireWave Surround driver")
+    Signed-off-by: Wenwen Wang 
+    Reviewed-by: Takashi Sakamoto 
+    Cc:  # v2.6.39+
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/firewire/packets-buffer.c b/sound/firewire/packets-buffer.c
+index 0d35359d25cd..0ecafd0c6722 100644
+--- a/sound/firewire/packets-buffer.c
++++ b/sound/firewire/packets-buffer.c
+@@ -37,7 +37,7 @@ int iso_packets_buffer_init(struct iso_packets_buffer *b, struct fw_unit *unit,
+ 	packets_per_page = PAGE_SIZE / packet_size;
+ 	if (WARN_ON(!packets_per_page)) {
+ 		err = -EINVAL;
+-		goto error;
++		goto err_packets;
+ 	}
+ 	pages = DIV_ROUND_UP(count, packets_per_page);
+ 

commit c7cd7c748a3250ca33509f9235efab9c803aca09
+Author: Wenwen Wang 
+Date:   Thu Aug 8 00:15:21 2019 -0500
+
+    sound: fix a memory leak bug
+    
+    In sound_insert_unit(), the controlling structure 's' is allocated through
+    kmalloc(). Then it is added to the sound driver list by invoking
+    __sound_insert_unit(). Later on, if __register_chrdev() fails, 's' is
+    removed from the list through __sound_remove_unit(). If 'index' is not less
+    than 0, -EBUSY is returned to indicate the error. However, 's' is not
+    deallocated on this execution path, leading to a memory leak bug.
+    
+    To fix the above issue, free 's' before -EBUSY is returned.
+    
+    Signed-off-by: Wenwen Wang 
+    Cc: 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/sound_core.c b/sound/sound_core.c
+index b730d97c4de6..90d118cd9164 100644
+--- a/sound/sound_core.c
++++ b/sound/sound_core.c
+@@ -275,7 +275,8 @@ static int sound_insert_unit(struct sound_unit **list, const struct file_operati
+ 				goto retry;
+ 			}
+ 			spin_unlock(&sound_loader_lock);
+-			return -EBUSY;
++			r = -EBUSY;
++			goto fail;
+ 		}
+ 	}
+ 

commit 3d92aa45fbfd7319e3a19f4ec59fd32b3862b723
+Author: Wenwen Wang 
+Date:   Wed Aug 7 04:08:51 2019 -0500
+
+    ALSA: hiface: fix multiple memory leak bugs
+    
+    In hiface_pcm_init(), 'rt' is firstly allocated through kzalloc(). Later
+    on, hiface_pcm_init_urb() is invoked to initialize 'rt->out_urbs[i]'. In
+    hiface_pcm_init_urb(), 'rt->out_urbs[i].buffer' is allocated through
+    kzalloc().  However, if hiface_pcm_init_urb() fails, both 'rt' and
+    'rt->out_urbs[i].buffer' are not deallocated, leading to memory leak bugs.
+    Also, 'rt->out_urbs[i].buffer' is not deallocated if snd_pcm_new() fails.
+    
+    To fix the above issues, free 'rt' and 'rt->out_urbs[i].buffer'.
+    
+    Fixes: a91c3fb2f842 ("Add M2Tech hiFace USB-SPDIF driver")
+    Signed-off-by: Wenwen Wang 
+    Cc: 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/usb/hiface/pcm.c b/sound/usb/hiface/pcm.c
+index 14fc1e1d5d13..c406497c5919 100644
+--- a/sound/usb/hiface/pcm.c
++++ b/sound/usb/hiface/pcm.c
+@@ -600,14 +600,13 @@ int hiface_pcm_init(struct hiface_chip *chip, u8 extra_freq)
+ 		ret = hiface_pcm_init_urb(&rt->out_urbs[i], chip, OUT_EP,
+ 				    hiface_pcm_out_urb_handler);
+ 		if (ret < 0)
+-			return ret;
++			goto error;
+ 	}
+ 
+ 	ret = snd_pcm_new(chip->card, "USB-SPDIF Audio", 0, 1, 0, &pcm);
+ 	if (ret < 0) {
+-		kfree(rt);
+ 		dev_err(&chip->dev->dev, "Cannot create pcm instance\n");
+-		return ret;
++		goto error;
+ 	}
+ 
+ 	pcm->private_data = rt;
+@@ -620,4 +619,10 @@ int hiface_pcm_init(struct hiface_chip *chip, u8 extra_freq)
+ 
+ 	chip->pcm = rt;
+ 	return 0;
++
++error:
++	for (i = 0; i < PCM_N_URBS; i++)
++		kfree(rt->out_urbs[i].buffer);
++	kfree(rt);
++	return ret;
+ }

commit a67060201b746a308b1674f66bf289c9faef6d09
+Author: Wenwen Wang 
+Date:   Tue Aug 6 03:00:27 2019 -0400
+
+    ALSA: usb-audio: fix a memory leak bug
+    
+    In snd_usb_get_audioformat_uac3(), a structure for channel maps 'chmap' is
+    allocated through kzalloc() before the execution goto 'found_clock'.
+    However, this structure is not deallocated if the memory allocation for
+    'pd' fails, leading to a memory leak bug.
+    
+    To fix the above issue, free 'fp->chmap' before returning NULL.
+    
+    Fixes: 7edf3b5e6a45 ("ALSA: usb-audio: AudioStreaming Power Domain parsing")
+    Signed-off-by: Wenwen Wang 
+    Cc: 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/usb/stream.c b/sound/usb/stream.c
+index 7ee9d17d0143..e852c7fd6109 100644
+--- a/sound/usb/stream.c
++++ b/sound/usb/stream.c
+@@ -1043,6 +1043,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
+ 
+ 		pd = kzalloc(sizeof(*pd), GFP_KERNEL);
+ 		if (!pd) {
++			kfree(fp->chmap);
+ 			kfree(fp->rate_table);
+ 			kfree(fp);
+ 			return NULL;

commit d4fddac5a51c378c5d3e68658816c37132611e1f
+Author: Wenwen Wang 
+Date:   Sun Jul 14 01:11:35 2019 -0500
+
+    test_firmware: fix a memory leak bug
+    
+    In test_firmware_init(), the buffer pointed to by the global pointer
+    'test_fw_config' is allocated through kzalloc(). Then, the buffer is
+    initialized in __test_firmware_config_init(). In the case that the
+    initialization fails, the following execution in test_firmware_init() needs
+    to be terminated with an error code returned to indicate this failure.
+    However, the allocated buffer is not freed on this execution path, leading
+    to a memory leak bug.
+    
+    To fix the above issue, free the allocated buffer before returning from
+    test_firmware_init().
+    
+    Signed-off-by: Wenwen Wang 
+    Link: https://lore.kernel.org/r/1563084696-6865-1-git-send-email-wang6495@umn.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/lib/test_firmware.c b/lib/test_firmware.c
+index 83ea6c4e623c..6ca97a63b3d6 100644
+--- a/lib/test_firmware.c
++++ b/lib/test_firmware.c
+@@ -886,8 +886,11 @@ static int __init test_firmware_init(void)
+ 		return -ENOMEM;
+ 
+ 	rc = __test_firmware_config_init();
+-	if (rc)
++	if (rc) {
++		kfree(test_fw_config);
++		pr_err("could not init firmware test config: %d\n", rc);
+ 		return rc;
++	}
+ 
+ 	rc = misc_register(&test_fw_misc_device);
+ 	if (rc) {

commit 45004d66f2a28d78f543fb2ffbc133e31dc2d162
+Author: Wenwen Wang 
+Date:   Mon Jul 22 08:57:44 2019 -0500
+
+    ASoC: dapm: fix a memory leak bug
+    
+    In snd_soc_dapm_new_control_unlocked(), a kernel buffer is allocated in
+    dapm_cnew_widget() to hold the new dapm widget. Then, different actions are
+    taken according to the id of the widget, i.e., 'w->id'. If any failure
+    occurs during this process, snd_soc_dapm_new_control_unlocked() should be
+    terminated by going to the 'request_failed' label. However, the allocated
+    kernel buffer is not freed on this code path, leading to a memory leak bug.
+    
+    To fix the above issue, free the buffer before returning from
+    snd_soc_dapm_new_control_unlocked() through the 'request_failed' label.
+    
+    Signed-off-by: Wenwen Wang 
+    Link: https://lore.kernel.org/r/1563803864-2809-1-git-send-email-wang6495@umn.edu
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
+index 9cd87e47ee8f..656cb5cd9cd8 100644
+--- a/sound/soc/soc-dapm.c
++++ b/sound/soc/soc-dapm.c
+@@ -3704,6 +3704,8 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,
+ 		dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n",
+ 			w->name, ret);
+ 
++	kfree_const(w->sname);
++	kfree(w);
+ 	return ERR_PTR(ret);
+ }
+ 

commit 15a78ba1844a8e052c1226f930133de4cef4e7ad
+Author: Wenwen Wang 
+Date:   Sat Jul 20 07:22:45 2019 -0500
+
+    netfilter: ebtables: fix a memory leak bug in compat
+    
+    In compat_do_replace(), a temporary buffer is allocated through vmalloc()
+    to hold entries copied from the user space. The buffer address is firstly
+    saved to 'newinfo->entries', and later on assigned to 'entries_tmp'. Then
+    the entries in this temporary buffer is copied to the internal kernel
+    structure through compat_copy_entries(). If this copy process fails,
+    compat_do_replace() should be terminated. However, the allocated temporary
+    buffer is not freed on this path, leading to a memory leak.
+    
+    To fix the bug, free the buffer before returning from compat_do_replace().
+    
+    Signed-off-by: Wenwen Wang 
+    Reviewed-by: Florian Westphal 
+    Signed-off-by: Pablo Neira Ayuso 
+
+diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
+index 963dfdc14827..fd84b48e48b5 100644
+--- a/net/bridge/netfilter/ebtables.c
++++ b/net/bridge/netfilter/ebtables.c
+@@ -2261,8 +2261,10 @@ static int compat_do_replace(struct net *net, void __user *user,
+ 	state.buf_kern_len = size64;
+ 
+ 	ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state);
+-	if (WARN_ON(ret < 0))
++	if (WARN_ON(ret < 0)) {
++		vfree(entries_tmp);
+ 		goto out_unlock;
++	}
+ 
+ 	vfree(entries_tmp);
+ 	tmp.entries_size = size64;

commit e7bf90e5afe3aa1d1282c1635a49e17a32c4ecec
+Author: Wenwen Wang 
+Date:   Thu Jul 11 14:22:02 2019 -0500
+
+    block/bio-integrity: fix a memory leak bug
+    
+    In bio_integrity_prep(), a kernel buffer is allocated through kmalloc() to
+    hold integrity metadata. Later on, the buffer will be attached to the bio
+    structure through bio_integrity_add_page(), which returns the number of
+    bytes of integrity metadata attached. Due to unexpected situations,
+    bio_integrity_add_page() may return 0. As a result, bio_integrity_prep()
+    needs to be terminated with 'false' returned to indicate this error.
+    However, the allocated kernel buffer is not freed on this execution path,
+    leading to a memory leak.
+    
+    To fix this issue, free the allocated buffer before returning from
+    bio_integrity_prep().
+    
+    Reviewed-by: Ming Lei 
+    Acked-by: Martin K. Petersen 
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/bio-integrity.c b/block/bio-integrity.c
+index 4db620849515..fb95dbb21dd8 100644
+--- a/block/bio-integrity.c
++++ b/block/bio-integrity.c
+@@ -276,8 +276,12 @@ bool bio_integrity_prep(struct bio *bio)
+ 		ret = bio_integrity_add_page(bio, virt_to_page(buf),
+ 					     bytes, offset);
+ 
+-		if (ret == 0)
+-			return false;
++		if (ret == 0) {
++			printk(KERN_ERR "could not attach integrity payload\n");
++			kfree(buf);
++			status = BLK_STS_RESOURCE;
++			goto err_end_io;
++		}
+ 
+ 		if (ret < bytes)
+ 			break;

\ No newline at end of file diff --git a/detail/2.html b/detail/2.html new file mode 100644 index 0000000..725f406 --- /dev/null +++ b/detail/2.html @@ -0,0 +1,190817 @@ +

Patches contributed by Harvard University


commit 5d7cf67f72ae34d38e090bdfa673da4aefe4048e
+Author: Alan Stern 
+Date:   Tue Aug 8 20:44:48 2023 -0400
+
+    Fix nomenclature for USB and PCI wireless devices
+    
+    A mouse that uses a USB connection is called a "USB mouse" device (or
+    "USB mouse" for short), not a "mouse USB" device.  By analogy, a WiFi
+    adapter that connects to the host computer via USB is a "USB wireless"
+    device, not a "wireless USB" device.  (The latter term more properly
+    refers to a defunct Wireless USB specification, which described a
+    technology for sending USB protocol messages over an ultra wideband
+    radio link.)
+    
+    Similarly for a WiFi adapter card that plugs into a PCIe slot: It is a
+    "PCIe wireless" device, not a "wireless PCIe" device.
+    
+    Rephrase the text in the kernel source where the word ordering is
+    wrong.
+    
+    Signed-off-by: Alan Stern 
+    Reviewed-by: Greg Kroah-Hartman 
+    Signed-off-by: Kalle Valo 
+    Link: https://lore.kernel.org/r/57da7c80-0e48-41b5-8427-884a02648f55@rowland.harvard.edu
+
+diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
+index a7f44f6335fb..3ef414b613bf 100644
+--- a/drivers/net/wireless/ath/ath10k/pci.c
++++ b/drivers/net/wireless/ath/ath10k/pci.c
+@@ -3816,7 +3816,7 @@ static void __exit ath10k_pci_exit(void)
+ module_exit(ath10k_pci_exit);
+ 
+ MODULE_AUTHOR("Qualcomm Atheros");
+-MODULE_DESCRIPTION("Driver support for Qualcomm Atheros 802.11ac WLAN PCIe/AHB devices");
++MODULE_DESCRIPTION("Driver support for Qualcomm Atheros PCIe/AHB 802.11ac WLAN devices");
+ MODULE_LICENSE("Dual BSD/GPL");
+ 
+ /* QCA988x 2.0 firmware files */
+diff --git a/drivers/net/wireless/ath/ath10k/usb.c b/drivers/net/wireless/ath/ath10k/usb.c
+index b0067af685b1..3c482baacec1 100644
+--- a/drivers/net/wireless/ath/ath10k/usb.c
++++ b/drivers/net/wireless/ath/ath10k/usb.c
+@@ -1126,5 +1126,5 @@ static struct usb_driver ath10k_usb_driver = {
+ module_usb_driver(ath10k_usb_driver);
+ 
+ MODULE_AUTHOR("Atheros Communications, Inc.");
+-MODULE_DESCRIPTION("Driver support for Qualcomm Atheros 802.11ac WLAN USB devices");
++MODULE_DESCRIPTION("Driver support for Qualcomm Atheros USB 802.11ac WLAN devices");
+ MODULE_LICENSE("Dual BSD/GPL");
+diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
+index 5fd08ffc2a9f..9573bd959cac 100644
+--- a/drivers/net/wireless/ath/ath11k/pci.c
++++ b/drivers/net/wireless/ath/ath11k/pci.c
+@@ -1036,7 +1036,7 @@ static void ath11k_pci_exit(void)
+ 
+ module_exit(ath11k_pci_exit);
+ 
+-MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax WLAN PCIe devices");
++MODULE_DESCRIPTION("Driver support for Qualcomm Technologies PCIe 802.11ax WLAN devices");
+ MODULE_LICENSE("Dual BSD/GPL");
+ 
+ /* firmware files */
+diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c
+index 5990a55801f0..bd689efa7daa 100644
+--- a/drivers/net/wireless/ath/ath12k/pci.c
++++ b/drivers/net/wireless/ath/ath12k/pci.c
+@@ -1409,5 +1409,5 @@ static void ath12k_pci_exit(void)
+ 
+ module_exit(ath12k_pci_exit);
+ 
+-MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11be WLAN PCIe devices");
++MODULE_DESCRIPTION("Driver support for Qualcomm Technologies PCIe 802.11be WLAN devices");
+ MODULE_LICENSE("Dual BSD/GPL");
+diff --git a/drivers/net/wireless/atmel/at76c50x-usb.c b/drivers/net/wireless/atmel/at76c50x-usb.c
+index 009bca34ece3..447b51cff8f9 100644
+--- a/drivers/net/wireless/atmel/at76c50x-usb.c
++++ b/drivers/net/wireless/atmel/at76c50x-usb.c
+@@ -10,7 +10,7 @@
+  * Copyright (c) 2007 Kalle Valo 
+  * Copyright (c) 2010 Sebastian Smolorz 
+  *
+- * This file is part of the Berlios driver for WLAN USB devices based on the
++ * This file is part of the Berlios driver for USB WLAN devices based on the
+  * Atmel AT76C503A/505/505A.
+  *
+  * Some iw_handler code was taken from airo.c, (C) 1999 Benjamin Reed
+@@ -143,7 +143,7 @@ static const struct usb_device_id dev_table[] = {
+ 	{ USB_DEVICE(0x0cde, 0x0001), USB_DEVICE_DATA(BOARD_503_ISL3861) },
+ 	/* Dynalink/Askey WLL013 (intersil) */
+ 	{ USB_DEVICE(0x069a, 0x0320), USB_DEVICE_DATA(BOARD_503_ISL3861) },
+-	/* EZ connect 11Mpbs Wireless USB Adapter SMC2662W v1 */
++	/* EZ connect 11Mpbs USB Wireless Adapter SMC2662W v1 */
+ 	{ USB_DEVICE(0x0d5c, 0xa001), USB_DEVICE_DATA(BOARD_503_ISL3861) },
+ 	/* BenQ AWL300 */
+ 	{ USB_DEVICE(0x04a5, 0x9000), USB_DEVICE_DATA(BOARD_503_ISL3861) },
+@@ -195,7 +195,7 @@ static const struct usb_device_id dev_table[] = {
+ 	{ USB_DEVICE(0x04a5, 0x9001), USB_DEVICE_DATA(BOARD_503) },
+ 	/* 3Com 3CRSHEW696 */
+ 	{ USB_DEVICE(0x0506, 0x0a01), USB_DEVICE_DATA(BOARD_503) },
+-	/* Siemens Santis ADSL WLAN USB adapter WLL 013 */
++	/* Siemens Santis ADSL USB WLAN adapter WLL 013 */
+ 	{ USB_DEVICE(0x0681, 0x001b), USB_DEVICE_DATA(BOARD_503) },
+ 	/* Belkin F5D6050, version 2 */
+ 	{ USB_DEVICE(0x050d, 0x0050), USB_DEVICE_DATA(BOARD_503) },
+@@ -238,7 +238,7 @@ static const struct usb_device_id dev_table[] = {
+ 	{ USB_DEVICE(0x1915, 0x2233), USB_DEVICE_DATA(BOARD_505_2958) },
+ 	/* Xterasys XN-2122B, IBlitzz BWU613B/BWU613SB */
+ 	{ USB_DEVICE(0x12fd, 0x1001), USB_DEVICE_DATA(BOARD_505_2958) },
+-	/* Corega WLAN USB Stick 11 */
++	/* Corega USB WLAN Stick 11 */
+ 	{ USB_DEVICE(0x07aa, 0x7613), USB_DEVICE_DATA(BOARD_505_2958) },
+ 	/* Microstar MSI Box MS6978 */
+ 	{ USB_DEVICE(0x0db0, 0x1020), USB_DEVICE_DATA(BOARD_505_2958) },
+diff --git a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
+index dd31929261ab..866e0230df25 100644
+--- a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
++++ b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
+@@ -129,18 +129,18 @@ MODULE_FIRMWARE("orinoco_ezusb_fw");
+ 
+ #define USB_AVAYA8_VENDOR_ID     0x0D98
+ #define USB_AVAYAE_VENDOR_ID     0x0D9E
+-#define USB_AVAYA_WIRELESS_ID    0x0300 /* Avaya Wireless USB Card */
++#define USB_AVAYA_WIRELESS_ID    0x0300 /* Avaya USB Wireless Card */
+ 
+ #define USB_AGERE_VENDOR_ID      0x0D4E /* Agere Systems */
+-#define USB_AGERE_MODEL0801_ID   0x1000 /* Wireless USB Card Model 0801 */
+-#define USB_AGERE_MODEL0802_ID   0x1001 /* Wireless USB Card Model 0802 */
+-#define USB_AGERE_REBRANDED_ID   0x047A /* WLAN USB Card */
++#define USB_AGERE_MODEL0801_ID   0x1000 /* USB Wireless Card Model 0801 */
++#define USB_AGERE_MODEL0802_ID   0x1001 /* USB Wireless Card Model 0802 */
++#define USB_AGERE_REBRANDED_ID   0x047A /* USB WLAN Card */
+ 
+ #define USB_ELSA_VENDOR_ID       0x05CC
+ #define USB_ELSA_AIRLANCER_ID    0x3100 /* ELSA AirLancer USB-11 */
+ 
+ #define USB_LEGEND_VENDOR_ID     0x0E7C
+-#define USB_LEGEND_JOYNET_ID     0x0300 /* Joynet WLAN USB Card */
++#define USB_LEGEND_JOYNET_ID     0x0300 /* Joynet USB WLAN Card */
+ 
+ #define USB_SAMSUNG_VENDOR_ID    0x04E8
+ #define USB_SAMSUNG_SEW2001U1_ID 0x5002 /* Samsung SEW-2001u Card */
+@@ -154,7 +154,7 @@ MODULE_FIRMWARE("orinoco_ezusb_fw");
+ #define USB_FUJITSU_E1100_ID     0x1002 /* connect2AIR WLAN E-1100 USB */
+ 
+ #define USB_2WIRE_VENDOR_ID      0x1630
+-#define USB_2WIRE_WIRELESS_ID    0xff81 /* 2Wire Wireless USB adapter */
++#define USB_2WIRE_WIRELESS_ID    0xff81 /* 2Wire USB Wireless adapter */
+ 
+ 
+ #define EZUSB_REQUEST_FW_TRANS		0xA0
+diff --git a/drivers/net/wireless/legacy/rndis_wlan.c b/drivers/net/wireless/legacy/rndis_wlan.c
+index 712038d46bdb..e7fea7ded6d5 100644
+--- a/drivers/net/wireless/legacy/rndis_wlan.c
++++ b/drivers/net/wireless/legacy/rndis_wlan.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0-or-later
+ /*
+- * Driver for RNDIS based wireless USB devices.
++ * Driver for RNDIS based USB wireless devices.
+  *
+  * Copyright (C) 2007 by Bjorge Dijkstra 
+  * Copyright (C) 2008-2009 by Jussi Kivilinna 
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7603/Kconfig
+index 6a0080f1d91c..dd16acfd9735 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7603/Kconfig
++++ b/drivers/net/wireless/mediatek/mt76/mt7603/Kconfig
+@@ -5,7 +5,7 @@ config MT7603E
+ 	depends on MAC80211
+ 	depends on PCI
+ 	help
+-	  This adds support for MT7603E wireless PCIe devices and the WLAN core
++	  This adds support for MT7603E PCIe wireless devices and the WLAN core
+ 	  on MT7628/MT7688 SoC devices. This family supports IEEE 802.11n 2x2
+ 	  to 300Mbps PHY rate
+ 
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig
+index 30fba36ff46b..1ab1439143f4 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig
++++ b/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig
+@@ -11,7 +11,7 @@ config MT7615E
+ 	depends on MAC80211
+ 	depends on PCI
+ 	help
+-	  This adds support for MT7615-based wireless PCIe devices,
++	  This adds support for MT7615-based PCIe wireless devices,
+ 	  which support concurrent dual-band operation at both 5GHz
+ 	  and 2.4GHz, IEEE 802.11ac 4x4:4SS 1733Mbps PHY rate, wave2
+ 	  MU-MIMO up to 4 users/group and 160MHz channels.
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig b/drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig
+index 7c88ed8b8f1e..3ed888782a70 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig
++++ b/drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig
+@@ -10,7 +10,7 @@ config MT76x0U
+ 	depends on MAC80211
+ 	depends on USB
+ 	help
+-	  This adds support for MT7610U-based wireless USB 2.0 dongles,
++	  This adds support for MT7610U-based USB 2.0 wireless dongles,
+ 	  which comply with IEEE 802.11ac standards and support 1x1
+ 	  433Mbps PHY rate.
+ 
+@@ -22,7 +22,7 @@ config MT76x0E
+ 	depends on MAC80211
+ 	depends on PCI
+ 	help
+-	  This adds support for MT7610/MT7630-based wireless PCIe devices,
++	  This adds support for MT7610/MT7630-based PCIe wireless devices,
+ 	  which comply with IEEE 802.11ac standards and support 1x1
+ 	  433Mbps PHY rate.
+ 
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig b/drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig
+index 5fd4973e32df..482a32b70ddf 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig
++++ b/drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig
+@@ -9,7 +9,7 @@ config MT76x2E
+ 	depends on MAC80211
+ 	depends on PCI
+ 	help
+-	  This adds support for MT7612/MT7602/MT7662-based wireless PCIe
++	  This adds support for MT7612/MT7602/MT7662-based PCIe wireless
+ 	  devices, which comply with IEEE 802.11ac standards and support
+ 	  2SS to 866Mbit/s PHY rate.
+ 
+@@ -22,7 +22,7 @@ config MT76x2U
+ 	depends on MAC80211
+ 	depends on USB
+ 	help
+-	  This adds support for MT7612U-based wireless USB 3.0 dongles,
++	  This adds support for MT7612U-based USB 3.0 wireless dongles,
+ 	  which comply with IEEE 802.11ac standards and support 2SS to
+ 	  866Mbit/s PHY rate.
+ 
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig
+index 896ec38c23d9..193112c49bd1 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig
++++ b/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig
+@@ -7,7 +7,7 @@ config MT7915E
+ 	depends on PCI
+ 	select RELAY
+ 	help
+-	  This adds support for MT7915-based wireless PCIe devices,
++	  This adds support for MT7915-based PCIe wireless devices,
+ 	  which support concurrent dual-band operation at both 5GHz
+ 	  and 2.4GHz IEEE 802.11ax 4x4:4SS 1024-QAM, 160MHz channels,
+ 	  OFDMA, spatial reuse and dual carrier modulation.
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig
+index 1afa2f662e47..bb44d4a5e2dc 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig
++++ b/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig
+@@ -7,7 +7,7 @@ config MT7996E
+ 	depends on MAC80211
+ 	depends on PCI
+ 	help
+-	  This adds support for MT7996-based wireless PCIe devices,
++	  This adds support for MT7996-based PCIe wireless devices,
+ 	  which support concurrent tri-band operation at 6GHz, 5GHz,
+ 	  and 2.4GHz IEEE 802.11be 4x4:4SS 4096-QAM, 320MHz channels.
+ 
+diff --git a/drivers/net/wireless/mediatek/mt7601u/Kconfig b/drivers/net/wireless/mediatek/mt7601u/Kconfig
+index 4a8b96280670..4880fc053d9d 100644
+--- a/drivers/net/wireless/mediatek/mt7601u/Kconfig
++++ b/drivers/net/wireless/mediatek/mt7601u/Kconfig
+@@ -4,4 +4,4 @@ config MT7601U
+ 	depends on MAC80211
+ 	depends on USB
+ 	help
+-	  This adds support for MT7601U-based wireless USB dongles.
++	  This adds support for MT7601U-based USB wireless dongles.
+diff --git a/drivers/net/wireless/purelifi/plfxlc/Kconfig b/drivers/net/wireless/purelifi/plfxlc/Kconfig
+index 4e0be27a5e0e..dd5fca480d7e 100644
+--- a/drivers/net/wireless/purelifi/plfxlc/Kconfig
++++ b/drivers/net/wireless/purelifi/plfxlc/Kconfig
+@@ -3,7 +3,7 @@ config PLFXLC
+ 	tristate "pureLiFi X, XL, XC device support"
+ 	depends on CFG80211 && MAC80211 && USB
+ 	help
+-	   This option adds support for pureLiFi LiFi wireless USB
++	   This option adds support for pureLiFi LiFi USB wireless
+ 	   adapters. The pureLiFi X, XL, XC USB devices are based on
+ 	   802.11 OFDM PHY but uses light as the transmission medium.
+ 	   The driver supports common 802.11 encryption/authentication
+diff --git a/drivers/net/wireless/ralink/rt2x00/Kconfig b/drivers/net/wireless/ralink/rt2x00/Kconfig
+index dcccc290a7f5..d1fd66d44a7e 100644
+--- a/drivers/net/wireless/ralink/rt2x00/Kconfig
++++ b/drivers/net/wireless/ralink/rt2x00/Kconfig
+@@ -170,7 +170,7 @@ config RT2800USB_RT35XX
+ config RT2800USB_RT3573
+ 	bool "rt2800usb - Include support for rt3573 devices (EXPERIMENTAL)"
+ 	help
+-	  This enables support for RT3573 chipset based wireless USB devices
++	  This enables support for RT3573 chipset based USB wireless devices
+ 	  in the rt2800usb driver.
+ 
+ config RT2800USB_RT53XX
+diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c
+index 44a8fff34cdd..2bfc0e822b8d 100644
+--- a/drivers/net/wireless/realtek/rtw88/pci.c
++++ b/drivers/net/wireless/realtek/rtw88/pci.c
+@@ -1828,5 +1828,5 @@ void rtw_pci_shutdown(struct pci_dev *pdev)
+ EXPORT_SYMBOL(rtw_pci_shutdown);
+ 
+ MODULE_AUTHOR("Realtek Corporation");
+-MODULE_DESCRIPTION("Realtek 802.11ac wireless PCI driver");
++MODULE_DESCRIPTION("Realtek PCI 802.11ac wireless driver");
+ MODULE_LICENSE("Dual BSD/GPL");
+diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
+index 91ed6d10ba8a..95b9d933158f 100644
+--- a/drivers/net/wireless/realtek/rtw88/usb.c
++++ b/drivers/net/wireless/realtek/rtw88/usb.c
+@@ -909,5 +909,5 @@ void rtw_usb_disconnect(struct usb_interface *intf)
+ EXPORT_SYMBOL(rtw_usb_disconnect);
+ 
+ MODULE_AUTHOR("Realtek Corporation");
+-MODULE_DESCRIPTION("Realtek 802.11ac wireless USB driver");
++MODULE_DESCRIPTION("Realtek USB 802.11ac wireless driver");
+ MODULE_LICENSE("Dual BSD/GPL");
+diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c
+index 9402f1a0caea..3a4bfc44142b 100644
+--- a/drivers/net/wireless/realtek/rtw89/pci.c
++++ b/drivers/net/wireless/realtek/rtw89/pci.c
+@@ -3939,5 +3939,5 @@ void rtw89_pci_remove(struct pci_dev *pdev)
+ EXPORT_SYMBOL(rtw89_pci_remove);
+ 
+ MODULE_AUTHOR("Realtek Corporation");
+-MODULE_DESCRIPTION("Realtek 802.11ax wireless PCI driver");
++MODULE_DESCRIPTION("Realtek PCI 802.11ax wireless driver");
+ MODULE_LICENSE("Dual BSD/GPL");
+diff --git a/drivers/net/wireless/zydas/zd1201.c b/drivers/net/wireless/zydas/zd1201.c
+index a85fe7e4c6d4..2814df1ecc78 100644
+--- a/drivers/net/wireless/zydas/zd1201.c
++++ b/drivers/net/wireless/zydas/zd1201.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ /*
+- *	Driver for ZyDAS zd1201 based wireless USB devices.
++ *	Driver for ZyDAS zd1201 based USB wireless devices.
+  *
+  *	Copyright (c) 2004, 2005 Jeroen Vreeken (pe1rxq@amsat.org)
+  *
+@@ -23,8 +23,8 @@
+ #include "zd1201.h"
+ 
+ static const struct usb_device_id zd1201_table[] = {
+-	{USB_DEVICE(0x0586, 0x3400)}, /* Peabird Wireless USB Adapter */
+-	{USB_DEVICE(0x0ace, 0x1201)}, /* ZyDAS ZD1201 Wireless USB Adapter */
++	{USB_DEVICE(0x0586, 0x3400)}, /* Peabird USB Wireless Adapter */
++	{USB_DEVICE(0x0ace, 0x1201)}, /* ZyDAS ZD1201 USB Wireless Adapter */
+ 	{USB_DEVICE(0x050d, 0x6051)}, /* Belkin F5D6051 usb  adapter */
+ 	{USB_DEVICE(0x0db0, 0x6823)}, /* MSI UB11B usb  adapter */
+ 	{USB_DEVICE(0x1044, 0x8004)}, /* Gigabyte GN-WLBZ101 */
+diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
+index 62b71e8e3567..ff1b70269ccb 100644
+--- a/drivers/platform/x86/eeepc-laptop.c
++++ b/drivers/platform/x86/eeepc-laptop.c
+@@ -1394,7 +1394,7 @@ static int eeepc_acpi_add(struct acpi_device *device)
+ 	 * and machine-specific scripts find the fixed name convenient.  But
+ 	 * It's also good for us to exclude multiple instances because both
+ 	 * our hwmon and our wlan rfkill subdevice use global ACPI objects
+-	 * (the EC and the wlan PCI slot respectively).
++	 * (the EC and the PCI wlan slot respectively).
+ 	 */
+ 	result = eeepc_platform_init(eeepc);
+ 	if (result)
+diff --git a/drivers/staging/wlan-ng/prism2usb.c b/drivers/staging/wlan-ng/prism2usb.c
+index 80e36d03c4e2..0e0ccef4871e 100644
+--- a/drivers/staging/wlan-ng/prism2usb.c
++++ b/drivers/staging/wlan-ng/prism2usb.c
+@@ -11,45 +11,45 @@
+ 
+ static const struct usb_device_id usb_prism_tbl[] = {
+ 	PRISM_DEV(0x04bb, 0x0922, "IOData AirPort WN-B11/USBS"),
+-	PRISM_DEV(0x07aa, 0x0012, "Corega Wireless LAN USB Stick-11"),
+-	PRISM_DEV(0x09aa, 0x3642, "Prism2.x 11Mbps WLAN USB Adapter"),
+-	PRISM_DEV(0x1668, 0x0408, "Actiontec Prism2.5 11Mbps WLAN USB Adapter"),
+-	PRISM_DEV(0x1668, 0x0421, "Actiontec Prism2.5 11Mbps WLAN USB Adapter"),
+-	PRISM_DEV(0x1915, 0x2236, "Linksys WUSB11v3.0 11Mbps WLAN USB Adapter"),
+-	PRISM_DEV(0x066b, 0x2212, "Linksys WUSB11v2.5 11Mbps WLAN USB Adapter"),
+-	PRISM_DEV(0x066b, 0x2213, "Linksys WUSB12v1.1 11Mbps WLAN USB Adapter"),
++	PRISM_DEV(0x07aa, 0x0012, "Corega USB Wireless LAN Stick-11"),
++	PRISM_DEV(0x09aa, 0x3642, "Prism2.x 11Mbps USB WLAN Adapter"),
++	PRISM_DEV(0x1668, 0x0408, "Actiontec Prism2.5 11Mbps USB WLAN Adapter"),
++	PRISM_DEV(0x1668, 0x0421, "Actiontec Prism2.5 11Mbps USB WLAN Adapter"),
++	PRISM_DEV(0x1915, 0x2236, "Linksys WUSB11v3.0 11Mbps USB WLAN Adapter"),
++	PRISM_DEV(0x066b, 0x2212, "Linksys WUSB11v2.5 11Mbps USB WLAN Adapter"),
++	PRISM_DEV(0x066b, 0x2213, "Linksys WUSB12v1.1 11Mbps USB WLAN Adapter"),
+ 	PRISM_DEV(0x0411, 0x0016, "Melco WLI-USB-S11 11Mbps WLAN Adapter"),
+-	PRISM_DEV(0x08de, 0x7a01, "PRISM25 IEEE 802.11 Mini USB Adapter"),
+-	PRISM_DEV(0x8086, 0x1111, "Intel PRO/Wireless 2011B LAN USB Adapter"),
++	PRISM_DEV(0x08de, 0x7a01, "PRISM25 USB IEEE 802.11 Mini Adapter"),
++	PRISM_DEV(0x8086, 0x1111, "Intel PRO/Wireless 2011B USB LAN Adapter"),
+ 	PRISM_DEV(0x0d8e, 0x7a01, "PRISM25 IEEE 802.11 Mini USB Adapter"),
+-	PRISM_DEV(0x045e, 0x006e, "Microsoft MN510 Wireless USB Adapter"),
++	PRISM_DEV(0x045e, 0x006e, "Microsoft MN510 USB Wireless Adapter"),
+ 	PRISM_DEV(0x0967, 0x0204, "Acer Warplink USB Adapter"),
+ 	PRISM_DEV(0x0cde, 0x0002, "Z-Com 725/726 Prism2.5 USB/USB Integrated"),
+-	PRISM_DEV(0x0cde, 0x0005, "Z-Com Xl735 Wireless 802.11b USB Adapter"),
+-	PRISM_DEV(0x413c, 0x8100, "Dell TrueMobile 1180 Wireless USB Adapter"),
+-	PRISM_DEV(0x0b3b, 0x1601, "ALLNET 0193 11Mbps WLAN USB Adapter"),
+-	PRISM_DEV(0x0b3b, 0x1602, "ZyXEL ZyAIR B200 Wireless USB Adapter"),
+-	PRISM_DEV(0x0baf, 0x00eb, "USRobotics USR1120 Wireless USB Adapter"),
++	PRISM_DEV(0x0cde, 0x0005, "Z-Com Xl735 USB Wireless 802.11b Adapter"),
++	PRISM_DEV(0x413c, 0x8100, "Dell TrueMobile 1180 USB Wireless Adapter"),
++	PRISM_DEV(0x0b3b, 0x1601, "ALLNET 0193 11Mbps USB WLAN Adapter"),
++	PRISM_DEV(0x0b3b, 0x1602, "ZyXEL ZyAIR B200 USB Wireless Adapter"),
++	PRISM_DEV(0x0baf, 0x00eb, "USRobotics USR1120 USB Wireless Adapter"),
+ 	PRISM_DEV(0x0411, 0x0027, "Melco WLI-USB-KS11G 11Mbps WLAN Adapter"),
+ 	PRISM_DEV(0x04f1, 0x3009, "JVC MP-XP7250 Builtin USB WLAN Adapter"),
+ 	PRISM_DEV(0x0846, 0x4110, "NetGear MA111"),
+ 	PRISM_DEV(0x03f3, 0x0020, "Adaptec AWN-8020 USB WLAN Adapter"),
+-	PRISM_DEV(0x2821, 0x3300, "ASUS-WL140 / Hawking HighDB Wireless USB Adapter"),
+-	PRISM_DEV(0x2001, 0x3700, "DWL-122 Wireless USB Adapter"),
+-	PRISM_DEV(0x2001, 0x3702, "DWL-120 Rev F Wireless USB Adapter"),
++	PRISM_DEV(0x2821, 0x3300, "ASUS-WL140 / Hawking HighDB USB Wireless Adapter"),
++	PRISM_DEV(0x2001, 0x3700, "DWL-122 USB Wireless Adapter"),
++	PRISM_DEV(0x2001, 0x3702, "DWL-120 Rev F USB Wireless Adapter"),
+ 	PRISM_DEV(0x50c2, 0x4013, "Averatec USB WLAN Adapter"),
+-	PRISM_DEV(0x2c02, 0x14ea, "Planex GW-US11H WLAN USB Adapter"),
+-	PRISM_DEV(0x124a, 0x168b, "Airvast PRISM3 WLAN USB Adapter"),
++	PRISM_DEV(0x2c02, 0x14ea, "Planex GW-US11H USB WLAN Adapter"),
++	PRISM_DEV(0x124a, 0x168b, "Airvast PRISM3 USB WLAN Adapter"),
+ 	PRISM_DEV(0x083a, 0x3503, "T-Sinus 111 USB WLAN Adapter"),
+ 	PRISM_DEV(0x0411, 0x0044, "Melco WLI-USB-KB11 11Mbps WLAN Adapter"),
+-	PRISM_DEV(0x1668, 0x6106, "ROPEX FreeLan 802.11b USB Adapter"),
+-	PRISM_DEV(0x124a, 0x4017, "Pheenet WL-503IA 802.11b USB Adapter"),
++	PRISM_DEV(0x1668, 0x6106, "ROPEX FreeLan USB 802.11b Adapter"),
++	PRISM_DEV(0x124a, 0x4017, "Pheenet WL-503IA USB 802.11b Adapter"),
+ 	PRISM_DEV(0x0bb2, 0x0302, "Ambit Microsystems Corp."),
+-	PRISM_DEV(0x9016, 0x182d, "Sitecom WL-022 802.11b USB Adapter"),
++	PRISM_DEV(0x9016, 0x182d, "Sitecom WL-022 USB 802.11b Adapter"),
+ 	PRISM_DEV(0x0543, 0x0f01,
+ 		  "ViewSonic Airsync USB Adapter 11Mbps (Prism2.5)"),
+ 	PRISM_DEV(0x067c, 0x1022,
+-		  "Siemens SpeedStream 1022 11Mbps WLAN USB Adapter"),
++		  "Siemens SpeedStream 1022 11Mbps USB WLAN Adapter"),
+ 	PRISM_DEV(0x049f, 0x0033,
+ 		  "Compaq/Intel W100 PRO/Wireless 11Mbps multiport WLAN Adapter"),
+ 	{ } /* terminator */

commit 55c3e571d2a0aabef4f1354604443f1c415d2e85
+Author: Alan Stern 
+Date:   Fri Aug 11 13:47:04 2023 -0400
+
+    USB: gadget: f_mass_storage: Fix unused variable warning
+    
+    Fix a "variable set but not used" warning in f_mass_storage.c.  rc is
+    used if verbose debugging is enabled but not otherwise.
+    
+    Signed-off-by: Alan Stern 
+    Fixes: d5e2b67aae79 ("USB: g_mass_storage: template f_mass_storage.c file created")
+    Link: https://lore.kernel.org/r/cfed16c7-aa46-494b-ba84-b0e0dc99be3a@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c
+index da07e45ae6df..722a3ab2b337 100644
+--- a/drivers/usb/gadget/function/f_mass_storage.c
++++ b/drivers/usb/gadget/function/f_mass_storage.c
+@@ -927,7 +927,7 @@ static void invalidate_sub(struct fsg_lun *curlun)
+ {
+ 	struct file	*filp = curlun->filp;
+ 	struct inode	*inode = file_inode(filp);
+-	unsigned long	rc;
++	unsigned long __maybe_unused	rc;
+ 
+ 	rc = invalidate_mapping_pages(inode->i_mapping, 0, -1);
+ 	VLDBG(curlun, "invalidate_mapping_pages -> %ld\n", rc);

commit 159a98afc88e88f588077afe818081d67f50a5e0
+Author: Alan Stern 
+Date:   Fri Aug 11 13:44:38 2023 -0400
+
+    USB: gadget: core: Add missing kerneldoc for vbus_work
+    
+    Add a missing kerneldoc description of the vbus_work field in struct usb_udc.
+    
+    Signed-off-by: Alan Stern 
+    Fixes: 50966da807c8 ("usb: gadget: udc: core: Offload usb_udc_vbus_handler processing")
+    Link: https://lore.kernel.org/r/1e5e7cda-b2c8-4917-9952-4354f365ede0@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
+index cd58f2a4e7f3..3bd0dec0cf6f 100644
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -40,6 +40,7 @@ static const struct bus_type gadget_bus_type;
+  * @allow_connect: Indicates whether UDC is allowed to be pulled up.
+  * Set/cleared by gadget_(un)bind_driver() after gadget driver is bound or
+  * unbound.
++ * @vbus_work: work routine to handle VBUS status change notifications.
+  * @connect_lock: protects udc->started, gadget->connect,
+  * gadget->allow_connect and gadget->deactivate. The routines
+  * usb_gadget_connect_locked(), usb_gadget_disconnect_locked(),

commit 59cf445754566984fd55af19ba7146c76e6627bc
+Author: Alan Stern 
+Date:   Fri Aug 11 13:38:46 2023 -0400
+
+    USB: core: Fix oversight in SuperSpeed initialization
+    
+    Commit 85d07c556216 ("USB: core: Unite old scheme and new scheme
+    descriptor reads") altered the way USB devices are enumerated
+    following detection, and in the process it messed up the
+    initialization of SuperSpeed (or faster) devices:
+    
+    [   31.650759] usb 2-1: new SuperSpeed Plus Gen 2x1 USB device number 2 using xhci_hcd
+    [   31.663107] usb 2-1: device descriptor read/8, error -71
+    [   31.952697] usb 2-1: new SuperSpeed Plus Gen 2x1 USB device number 3 using xhci_hcd
+    [   31.965122] usb 2-1: device descriptor read/8, error -71
+    [   32.080991] usb usb2-port1: attempt power cycle
+    ...
+    
+    The problem was caused by the commit forgetting that in SuperSpeed or
+    faster devices, the device descriptor uses a logarithmic encoding of
+    the bMaxPacketSize0 value.  (For some reason I thought the 255 case in
+    the switch statement was meant for these devices, but it isn't -- it
+    was meant for Wireless USB and is no longer needed.)
+    
+    We can fix the oversight by testing for buf->bMaxPacketSize0 = 9
+    (meaning 512, the actual maxpacket size for ep0 on all SuperSpeed
+    devices) and straightening out the logic that checks and adjusts our
+    initial guesses of the maxpacket value.
+    
+    Reported-and-tested-by: Thinh Nguyen 
+    Closes: https://lore.kernel.org/linux-usb/20230810002257.nadxmfmrobkaxgnz@synopsys.com/
+    Signed-off-by: Alan Stern 
+    Fixes: 85d07c556216 ("USB: core: Unite old scheme and new scheme descriptor reads")
+    Link: https://lore.kernel.org/r/8809e6c5-59d5-4d2d-ac8f-6d106658ad73@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index b3c09e4c8492..3c54b218301c 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -4728,7 +4728,7 @@ static int get_bMaxPacketSize0(struct usb_device *udev,
+ 				buf, size,
+ 				initial_descriptor_timeout);
+ 		switch (buf->bMaxPacketSize0) {
+-		case 8: case 16: case 32: case 64: case 255:
++		case 8: case 16: case 32: case 64: case 9:
+ 			if (buf->bDescriptorType == USB_DT_DEVICE) {
+ 				rc = buf->bMaxPacketSize0;
+ 				break;
+@@ -5015,23 +5015,35 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ 	if (retval)
+ 		goto fail;
+ 
+-	if (maxp0 == 0xff || udev->speed >= USB_SPEED_SUPER)
+-		i = 512;
+-	else
+-		i = maxp0;
+-	if (usb_endpoint_maxp(&udev->ep0.desc) != i) {
+-		if (udev->speed == USB_SPEED_LOW ||
+-				!(i == 8 || i == 16 || i == 32 || i == 64)) {
+-			dev_err(&udev->dev, "Invalid ep0 maxpacket: %d\n", i);
+-			retval = -EMSGSIZE;
+-			goto fail;
+-		}
++	/*
++	 * Check the ep0 maxpacket guess and correct it if necessary.
++	 * maxp0 is the value stored in the device descriptor;
++	 * i is the value it encodes (logarithmic for SuperSpeed or greater).
++	 */
++	i = maxp0;
++	if (udev->speed >= USB_SPEED_SUPER) {
++		if (maxp0 <= 16)
++			i = 1 << maxp0;
++		else
++			i = 0;		/* Invalid */
++	}
++	if (usb_endpoint_maxp(&udev->ep0.desc) == i) {
++		;	/* Initial ep0 maxpacket guess is right */
++	} else if ((udev->speed == USB_SPEED_FULL ||
++				udev->speed == USB_SPEED_HIGH) &&
++			(i == 8 || i == 16 || i == 32 || i == 64)) {
++		/* Initial guess is wrong; use the descriptor's value */
+ 		if (udev->speed == USB_SPEED_FULL)
+ 			dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
+ 		else
+ 			dev_warn(&udev->dev, "Using ep0 maxpacket: %d\n", i);
+ 		udev->ep0.desc.wMaxPacketSize = cpu_to_le16(i);
+ 		usb_ep0_reinit(udev);
++	} else {
++		/* Initial guess is wrong and descriptor's value is invalid */
++		dev_err(&udev->dev, "Invalid ep0 maxpacket: %d\n", maxp0);
++		retval = -EMSGSIZE;
++		goto fail;
+ 	}
+ 
+ 	descr = usb_get_device_descriptor(udev);

commit 5198c0eeb8ff98ee673a2420ba96d93c477c6ef4
+Author: Alan Stern 
+Date:   Fri Aug 11 11:47:15 2023 -0400
+
+    USB: core: Fix unused variable warning in usb_alloc_dev()
+    
+    The kernel test robot reported that a recent commit caused a "variable
+    set but not used" warning.  As a result of that commit, the variable
+    no longer serves any purpose; it should be removed.
+    
+    Reported-by: kernel test robot 
+    Closes: https://lore.kernel.org/oe-kbuild-all/202308092350.HR4PVHUt-lkp@intel.com/
+    Signed-off-by: Alan Stern 
+    Fixes: 1e4c574225cc ("USB: Remove remnants of Wireless USB and UWB")
+    Link: https://lore.kernel.org/r/7223cc66-f006-42ae-9f30-a6c546bf97a7@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 0945ff8df500..2a938cf47ccd 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -645,7 +645,6 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
+ {
+ 	struct usb_device *dev;
+ 	struct usb_hcd *usb_hcd = bus_to_hcd(bus);
+-	unsigned root_hub = 0;
+ 	unsigned raw_port = port1;
+ 
+ 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+@@ -695,7 +694,6 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
+ 		dev->dev.parent = bus->controller;
+ 		device_set_of_node_from_dev(&dev->dev, bus->sysdev);
+ 		dev_set_name(&dev->dev, "usb%d", bus->busnum);
+-		root_hub = 1;
+ 	} else {
+ 		/* match any labeling on the hubs; it's one-based */
+ 		if (parent->devpath[0] == '0') {

commit f176638af476c6d46257cc3303f5c7cf47d5967d
+Author: Alan Stern 
+Date:   Tue Aug 8 20:44:35 2023 -0400
+
+    USB: Remove Wireless USB and UWB documentation
+    
+    Support for Wireless USB and Ultra WideBand was removed in 2020 by
+    commit caa6772db4c1 ("Staging: remove wusbcore and UWB from the kernel
+    tree.").  But the documentation files were left behind.
+    
+    Let's get rid of that out-of-date documentation.
+    
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/015d4310-bcd3-4ba4-9a0e-3664f281a9be@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/CREDITS b/CREDITS
+index 8b4882024635..f33a33fd2371 100644
+--- a/CREDITS
++++ b/CREDITS
+@@ -666,11 +666,6 @@ S: Tamsui town, Taipei county,
+ S: Taiwan 251
+ S: Republic of China
+ 
+-N: Reinette Chatre
+-E: reinette.chatre@intel.com
+-D: WiMedia Link Protocol implementation
+-D: UWB stack bits and pieces
+-
+ N: Michael Elizabeth Chastain
+ E: mec@shout.net
+ D: Configure, Menuconfig, xconfig
+@@ -3023,12 +3018,6 @@ S: Demonstratsii 8-382
+ S: Tula 300000
+ S: Russia
+ 
+-N: Inaky Perez-Gonzalez
+-E: inaky.perez-gonzalez@intel.com
+-D: UWB stack, HWA-RC driver and HWA-HC drivers
+-D: Wireless USB additions to the USB stack
+-D: WiMedia Link Protocol bits and pieces
+-
+ N: Gordon Peters
+ E: GordPeters@smarttech.com
+ D: Isochronous receive for IEEE 1394 driver (OHCI module).
+diff --git a/Documentation/ABI/testing/sysfs-bus-umc b/Documentation/ABI/testing/sysfs-bus-umc
+deleted file mode 100644
+index 948fec412446..000000000000
+--- a/Documentation/ABI/testing/sysfs-bus-umc
++++ /dev/null
+@@ -1,28 +0,0 @@
+-What:           /sys/bus/umc/
+-Date:           July 2008
+-KernelVersion:  2.6.27
+-Contact:        David Vrabel 
+-Description:
+-                The Wireless Host Controller Interface (WHCI)
+-                specification describes a PCI-based device with
+-                multiple capabilities; the UWB Multi-interface
+-                Controller (UMC).
+-
+-                The umc bus presents each of the individual
+-                capabilties as a device.
+-
+-What:           /sys/bus/umc/devices/.../capability_id
+-Date:           July 2008
+-KernelVersion:  2.6.27
+-Contact:        David Vrabel 
+-Description:
+-                The ID of this capability, with 0 being the radio
+-                controller capability.
+-
+-What:           /sys/bus/umc/devices/.../version
+-Date:           July 2008
+-KernelVersion:  2.6.27
+-Contact:        David Vrabel 
+-Description:
+-                The specification version this capability's hardware
+-                interface complies with.
+diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb
+index be663258b9b7..a44bfe020061 100644
+--- a/Documentation/ABI/testing/sysfs-bus-usb
++++ b/Documentation/ABI/testing/sysfs-bus-usb
+@@ -28,40 +28,6 @@ Description:
+ 		drivers, non-authorized one are not.  By default, wired
+ 		USB devices are authorized.
+ 
+-		Certified Wireless USB devices are not authorized
+-		initially and should be (by writing 1) after the
+-		device has been authenticated.
+-
+-What:		/sys/bus/usb/device/.../wusb_cdid
+-Date:		July 2008
+-KernelVersion:	2.6.27
+-Contact:	David Vrabel 
+-Description:
+-		For Certified Wireless USB devices only.
+-
+-		A devices's CDID, as 16 space-separated hex octets.
+-
+-What:		/sys/bus/usb/device/.../wusb_ck
+-Date:		July 2008
+-KernelVersion:	2.6.27
+-Contact:	David Vrabel 
+-Description:
+-		For Certified Wireless USB devices only.
+-
+-		Write the device's connection key (CK) to start the
+-		authentication of the device.  The CK is 16
+-		space-separated hex octets.
+-
+-What:		/sys/bus/usb/device/.../wusb_disconnect
+-Date:		July 2008
+-KernelVersion:	2.6.27
+-Contact:	David Vrabel 
+-Description:
+-		For Certified Wireless USB devices only.
+-
+-		Write a 1 to force the device to disconnect
+-		(equivalent to unplugging a wired USB device).
+-
+ What:		/sys/bus/usb/drivers/.../new_id
+ Date:		October 2011
+ Contact:	linux-usb@vger.kernel.org
+diff --git a/Documentation/ABI/testing/sysfs-class-uwb_rc b/Documentation/ABI/testing/sysfs-class-uwb_rc
+deleted file mode 100644
+index a7ea169dc4eb..000000000000
+--- a/Documentation/ABI/testing/sysfs-class-uwb_rc
++++ /dev/null
+@@ -1,156 +0,0 @@
+-What:           /sys/class/uwb_rc
+-Date:           July 2008
+-KernelVersion:  2.6.27
+-Contact:        linux-usb@vger.kernel.org
+-Description:
+-                Interfaces for WiMedia Ultra Wideband Common Radio
+-                Platform (UWB) radio controllers.
+-
+-                Familiarity with the ECMA-368 'High Rate Ultra
+-                Wideband MAC and PHY Specification' is assumed.
+-
+-What:           /sys/class/uwb_rc/beacon_timeout_ms
+-Date:           July 2008
+-KernelVersion:  2.6.27
+-Description:
+-                If no beacons are received from a device for at least
+-                this time, the device will be considered to have gone
+-                and it will be removed.  The default is 3 superframes
+-                (~197 ms) as required by the specification.
+-
+-What:           /sys/class/uwb_rc/uwb/
+-Date:           July 2008
+-KernelVersion:  2.6.27
+-Contact:        linux-usb@vger.kernel.org
+-Description:
+-                An individual UWB radio controller.
+-
+-What:           /sys/class/uwb_rc/uwb/beacon
+-Date:           July 2008
+-KernelVersion:  2.6.27
+-Contact:        linux-usb@vger.kernel.org
+-Description:
+-                Write:
+-
+-                
+-
+-                to force a specific channel to be used when beaconing,
+-                or, if  is -1, to prohibit beaconing.  If
+-                 is 0, then the default channel selection
+-                algorithm will be used.  Valid channels depends on the
+-                radio controller's supported band groups.
+-
+-                Reading returns the currently active channel, or -1 if
+-                the radio controller is not beaconing.
+-
+-What:           /sys/class/uwb_rc/uwb/ASIE
+-Date:           August 2014
+-KernelVersion:  3.18
+-Contact:        linux-usb@vger.kernel.org
+-Description:
+-
+-                The application-specific information element (ASIE)
+-                included in this device's beacon, in space separated
+-                hex octets.
+-
+-                Reading returns the current ASIE.  Writing replaces
+-                the current ASIE with the one written.
+-
+-What:           /sys/class/uwb_rc/uwb/scan
+-Date:           July 2008
+-KernelVersion:  2.6.27
+-Contact:        linux-usb@vger.kernel.org
+-Description:
+-                Write:
+-
+-                  []
+-
+-                to start (or stop) scanning on a channel.   is one of:
+-
+-		   ==   =======================================
+-                    0   scan
+-                    1   scan outside BP
+-                    2   scan while inactive
+-                    3   scanning disabled
+-                    4   scan (with start time of )
+-		   ==   =======================================
+-
+-What:           /sys/class/uwb_rc/uwb/mac_address
+-Date:           July 2008
+-KernelVersion:  2.6.27
+-Contact:        linux-usb@vger.kernel.org
+-Description:
+-                The EUI-48, in colon-separated hex octets, for this
+-                radio controller.  A write will change the radio
+-                controller's EUI-48 but only do so while the device is
+-                not beaconing or scanning.
+-
+-What:           /sys/class/uwb_rc/uwb/wusbhc
+-Date:           July 2008
+-KernelVersion:  2.6.27
+-Contact:        linux-usb@vger.kernel.org
+-Description:
+-                A symlink to the device (if any) of the WUSB Host
+-                Controller PAL using this radio controller.
+-
+-What:           /sys/class/uwb_rc/uwb//
+-Date:           July 2008
+-KernelVersion:  2.6.27
+-Contact:        linux-usb@vger.kernel.org
+-Description:
+-                A neighbour UWB device that has either been detected
+-                as part of a scan or is a member of the radio
+-                controllers beacon group.
+-
+-What:           /sys/class/uwb_rc/uwb//BPST
+-Date:           July 2008
+-KernelVersion:  2.6.27
+-Contact:        linux-usb@vger.kernel.org
+-Description:
+-                The time (using the radio controllers internal 1 ms
+-                interval superframe timer) of the last beacon from
+-                this device was received.
+-
+-What:           /sys/class/uwb_rc/uwb//DevAddr
+-Date:           July 2008
+-KernelVersion:  2.6.27
+-Contact:        linux-usb@vger.kernel.org
+-Description:
+-                The current DevAddr of this device in colon separated
+-                hex octets.
+-
+-What:           /sys/class/uwb_rc/uwb//EUI_48
+-Date:           July 2008
+-KernelVersion:  2.6.27
+-Contact:        linux-usb@vger.kernel.org
+-Description:
+-
+-                The EUI-48 of this device in colon separated hex
+-                octets.
+-
+-What:           /sys/class/uwb_rc/uwb//IEs
+-Date:           July 2008
+-KernelVersion:  2.6.27
+-Contact:        linux-usb@vger.kernel.org
+-Description:
+-                The latest IEs included in this device's beacon, in
+-                space separated hex octets with one IE per line.
+-
+-What:           /sys/class/uwb_rc/uwb//LQE
+-Date:           July 2008
+-KernelVersion:  2.6.27
+-Contact:        linux-usb@vger.kernel.org
+-Description:
+-                Link Quality Estimate - the Signal to Noise Ratio
+-                (SNR) of all packets received from this device in dB.
+-                This gives an estimate on a suitable PHY rate. Refer
+-                to [ECMA-368] section 13.3 for more details.
+-
+-What:           /sys/class/uwb_rc/uwb//RSSI
+-Date:           July 2008
+-KernelVersion:  2.6.27
+-Contact:        linux-usb@vger.kernel.org
+-Description:
+-                Received Signal Strength Indication - the strength of
+-                the received signal in dB.  LQE is a more useful
+-                measure of the radio link quality.
+diff --git a/Documentation/ABI/testing/sysfs-class-uwb_rc-wusbhc b/Documentation/ABI/testing/sysfs-class-uwb_rc-wusbhc
+deleted file mode 100644
+index 55eb55cac92e..000000000000
+--- a/Documentation/ABI/testing/sysfs-class-uwb_rc-wusbhc
++++ /dev/null
+@@ -1,57 +0,0 @@
+-What:           /sys/class/uwb_rc/uwb/wusbhc/wusb_chid
+-Date:           July 2008
+-KernelVersion:  2.6.27
+-Contact:        David Vrabel 
+-Description:
+-                Write the CHID (16 space-separated hex octets) for this host controller.
+-                This starts the host controller, allowing it to accept connection from
+-                WUSB devices.
+-
+-                Set an all zero CHID to stop the host controller.
+-
+-What:           /sys/class/uwb_rc/uwb/wusbhc/wusb_trust_timeout
+-Date:           July 2008
+-KernelVersion:  2.6.27
+-Contact:        David Vrabel 
+-Description:
+-                Devices that haven't sent a WUSB packet to the host
+-                within 'wusb_trust_timeout' ms are considered to have
+-                disconnected and are removed.  The default value of
+-                4000 ms is the value required by the WUSB
+-                specification.
+-
+-                Since this relates to security (specifically, the
+-                lifetime of PTKs and GTKs) it should not be changed
+-                from the default.
+-
+-What:           /sys/class/uwb_rc/uwb/wusbhc/wusb_phy_rate
+-Date:           August 2009
+-KernelVersion:  2.6.32
+-Contact:        David Vrabel 
+-Description:
+-                The maximum PHY rate to use for all connected devices.
+-                This is only of limited use for testing and
+-                development as the hardware's automatic rate
+-                adaptation is better then this simple control.
+-
+-                Refer to [ECMA-368] section 10.3.1.1 for the value to
+-                use.
+-
+-What:           /sys/class/uwb_rc/uwb/wusbhc/wusb_dnts
+-Date:           June 2013
+-KernelVersion:  3.11
+-Contact:        Thomas Pugliese 
+-Description:
+-                The device notification time slot (DNTS) count and inverval in
+-                milliseconds that the WUSB host should use.  This controls how
+-                often the devices will have the opportunity to send
+-                notifications to the host.
+-
+-What:           /sys/class/uwb_rc/uwb/wusbhc/wusb_retry_count
+-Date:           June 2013
+-KernelVersion:  3.11
+-Contact:        Thomas Pugliese 
+-Description:
+-                The number of retries that the WUSB host should attempt
+-                before reporting an error for a bus transaction.  The range of
+-                valid values is [0..15], where 0 indicates infinite retries.
+diff --git a/Documentation/ABI/testing/sysfs-wusb_cbaf b/Documentation/ABI/testing/sysfs-wusb_cbaf
+deleted file mode 100644
+index 2969d3694ec0..000000000000
+--- a/Documentation/ABI/testing/sysfs-wusb_cbaf
++++ /dev/null
+@@ -1,101 +0,0 @@
+-What:           /sys/bus/usb/drivers/wusb_cbaf/.../wusb_*
+-Date:           August 2008
+-KernelVersion:  2.6.27
+-Contact:        David Vrabel 
+-Description:
+-                Various files for managing Cable Based Association of
+-                (wireless) USB devices.
+-
+-                The sequence of operations should be:
+-
+-                1. Device is plugged in.
+-
+-                2. The connection manager (CM) sees a device with CBA capability.
+-                   (the wusb_chid etc. files in /sys/devices/blah/OURDEVICE).
+-
+-                3. The CM writes the host name, supported band groups,
+-                   and the CHID (host ID) into the wusb_host_name,
+-                   wusb_host_band_groups and wusb_chid files. These
+-                   get sent to the device and the CDID (if any) for
+-                   this host is requested.
+-
+-                4. The CM can verify that the device's supported band
+-                   groups (wusb_device_band_groups) are compatible
+-                   with the host.
+-
+-                5. The CM reads the wusb_cdid file.
+-
+-                6. The CM looks it up its database.
+-
+-                   - If it has a matching CHID,CDID entry, the device
+-                     has been authorized before and nothing further
+-                     needs to be done.
+-
+-                   - If the CDID is zero (or the CM doesn't find a
+-                     matching CDID in its database), the device is
+-                     assumed to be not known.  The CM may associate
+-                     the host with device by: writing a randomly
+-                     generated CDID to wusb_cdid and then a random CK
+-                     to wusb_ck (this uploads the new CC to the
+-                     device).
+-
+-                     CMD may choose to prompt the user before
+-                     associating with a new device.
+-
+-                7. Device is unplugged.
+-
+-                References:
+-                  [WUSB-AM]
+-			    Association Models Supplement to the
+-                            Certified Wireless Universal Serial Bus
+-                            Specification, version 1.0.
+-
+-What:           /sys/bus/usb/drivers/wusb_cbaf/.../wusb_chid
+-Date:           August 2008
+-KernelVersion:  2.6.27
+-Contact:        David Vrabel 
+-Description:
+-                The CHID of the host formatted as 16 space-separated
+-                hex octets.
+-
+-                Writes fetches device's supported band groups and the
+-                the CDID for any existing association with this host.
+-
+-What:           /sys/bus/usb/drivers/wusb_cbaf/.../wusb_host_name
+-Date:           August 2008
+-KernelVersion:  2.6.27
+-Contact:        David Vrabel 
+-Description:
+-                A friendly name for the host as a UTF-8 encoded string.
+-
+-What:           /sys/bus/usb/drivers/wusb_cbaf/.../wusb_host_band_groups
+-Date:           August 2008
+-KernelVersion:  2.6.27
+-Contact:        David Vrabel 
+-Description:
+-                The band groups supported by the host, in the format
+-                defined in [WUSB-AM].
+-
+-What:           /sys/bus/usb/drivers/wusb_cbaf/.../wusb_device_band_groups
+-Date:           August 2008
+-KernelVersion:  2.6.27
+-Contact:        David Vrabel 
+-Description:
+-                The band groups supported by the device, in the format
+-                defined in [WUSB-AM].
+-
+-What:           /sys/bus/usb/drivers/wusb_cbaf/.../wusb_cdid
+-Date:           August 2008
+-KernelVersion:  2.6.27
+-Contact:        David Vrabel 
+-Description:
+-                The device's CDID formatted as 16 space-separated hex
+-                octets.
+-
+-What:           /sys/bus/usb/drivers/wusb_cbaf/.../wusb_ck
+-Date:           August 2008
+-KernelVersion:  2.6.27
+-Contact:        David Vrabel 
+-Description:
+-                Write 16 space-separated random, hex octets to
+-                associate with the device.
+diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
+index a1457995fd41..29fbb38ca759 100644
+--- a/Documentation/admin-guide/kernel-parameters.txt
++++ b/Documentation/admin-guide/kernel-parameters.txt
+@@ -6607,7 +6607,7 @@
+ 
+ 	usbcore.authorized_default=
+ 			[USB] Default USB device authorization:
+-			(default -1 = authorized except for wireless USB,
++			(default -1 = authorized (same as 1),
+ 			0 = not authorized, 1 = authorized, 2 = authorized
+ 			if device connected to internal port)
+ 
+diff --git a/Documentation/driver-api/usb/usb.rst b/Documentation/driver-api/usb/usb.rst
+index 0fcd75ee5897..fb41768696ec 100644
+--- a/Documentation/driver-api/usb/usb.rst
++++ b/Documentation/driver-api/usb/usb.rst
+@@ -777,8 +777,7 @@ Speed may be:
+ 	======= ======================================================
+ 	1.5	Mbit/s for low speed USB
+ 	12	Mbit/s for full speed USB
+-	480	Mbit/s for high speed USB (added for USB 2.0);
+-		also used for Wireless USB, which has no fixed speed
++	480	Mbit/s for high speed USB (added for USB 2.0)
+ 	5000	Mbit/s for SuperSpeed USB (added for USB 3.0)
+ 	======= ======================================================
+ 
+diff --git a/Documentation/usb/authorization.rst b/Documentation/usb/authorization.rst
+index 9e53909d04c2..150a14970e95 100644
+--- a/Documentation/usb/authorization.rst
++++ b/Documentation/usb/authorization.rst
+@@ -33,12 +33,9 @@ Remove the lock down::
+ 
+ 	$ echo 1 > /sys/bus/usb/devices/usbX/authorized_default
+ 
+-By default, Wired USB devices are authorized by default to
+-connect. Wireless USB hosts deauthorize by default all new connected
+-devices (this is so because we need to do an authentication phase
+-before authorizing). Writing "2" to the authorized_default attribute
+-causes kernel to only authorize by default devices connected to internal
+-USB ports.
++By default, all USB devices are authorized.  Writing "2" to the
++authorized_default attribute causes the kernel to authorize by default
++only devices connected to internal USB ports.
+ 
+ 
+ Example system lockdown (lame)

commit 1e4c574225cc5a0553115e5eb5787d1474db5b0f
+Author: Alan Stern 
+Date:   Tue Aug 8 20:44:18 2023 -0400
+
+    USB: Remove remnants of Wireless USB and UWB
+    
+    Wireless USB has long been defunct, and kernel support for it was
+    removed in 2020 by commit caa6772db4c1 ("Staging: remove wusbcore and
+    UWB from the kernel tree.").
+    
+    Nevertheless, some vestiges of the old implementation still clutter up
+    the USB subsystem and one or two other places.  Let's get rid of them
+    once and for all.
+    
+    The only parts still left are the user-facing APIs in
+    include/uapi/linux/usb/ch9.h.  (There are also a couple of misleading
+    instances, such as the Sierra Wireless USB modem, which is a USB modem
+    made by Sierra Wireless.)
+    
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/b4f2710f-a2de-4fb0-b50f-76776f3a961b@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
+index 5e5c7bf51174..1584665fe3cb 100644
+--- a/drivers/net/wireless/mediatek/mt76/usb.c
++++ b/drivers/net/wireless/mediatek/mt76/usb.c
+@@ -286,8 +286,7 @@ static bool mt76u_check_sg(struct mt76_dev *dev)
+ 	struct usb_device *udev = interface_to_usbdev(uintf);
+ 
+ 	return (!disable_usb_sg && udev->bus->sg_tablesize > 0 &&
+-		(udev->bus->no_sg_constraint ||
+-		 udev->speed == USB_SPEED_WIRELESS));
++		udev->bus->no_sg_constraint);
+ }
+ 
+ static int
+diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
+index 725b8dbcfe5f..b19e38d5fd10 100644
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -1051,9 +1051,6 @@ int usb_get_bos_descriptor(struct usb_device *dev)
+ 		}
+ 
+ 		switch (cap_type) {
+-		case USB_CAP_TYPE_WIRELESS_USB:
+-			/* Wireless USB cap descriptor is handled by wusb */
+-			break;
+ 		case USB_CAP_TYPE_EXT:
+ 			dev->bos->ext_cap =
+ 				(struct usb_ext_cap_descriptor *)buffer;
+diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
+index 2c14a9636056..a247da73f34d 100644
+--- a/drivers/usb/core/devices.c
++++ b/drivers/usb/core/devices.c
+@@ -424,7 +424,6 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,
+ 	case USB_SPEED_UNKNOWN:		/* usb 1.1 root hub code */
+ 	case USB_SPEED_FULL:
+ 		speed = "12"; break;
+-	case USB_SPEED_WIRELESS:	/* Wireless has no real fixed speed */
+ 	case USB_SPEED_HIGH:
+ 		speed = "480"; break;
+ 	case USB_SPEED_SUPER:
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 6af0a31ff147..12b6dfeaf658 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -156,27 +156,6 @@ static const u8 usb3_rh_dev_descriptor[18] = {
+ 	0x01        /*  __u8  bNumConfigurations; */
+ };
+ 
+-/* usb 2.5 (wireless USB 1.0) root hub device descriptor */
+-static const u8 usb25_rh_dev_descriptor[18] = {
+-	0x12,       /*  __u8  bLength; */
+-	USB_DT_DEVICE, /* __u8 bDescriptorType; Device */
+-	0x50, 0x02, /*  __le16 bcdUSB; v2.5 */
+-
+-	0x09,	    /*  __u8  bDeviceClass; HUB_CLASSCODE */
+-	0x00,	    /*  __u8  bDeviceSubClass; */
+-	0x00,       /*  __u8  bDeviceProtocol; [ usb 2.0 no TT ] */
+-	0xFF,       /*  __u8  bMaxPacketSize0; always 0xFF (WUSB Spec 7.4.1). */
+-
+-	0x6b, 0x1d, /*  __le16 idVendor; Linux Foundation 0x1d6b */
+-	0x02, 0x00, /*  __le16 idProduct; device 0x0002 */
+-	KERNEL_VER, KERNEL_REL, /*  __le16 bcdDevice */
+-
+-	0x03,       /*  __u8  iManufacturer; */
+-	0x02,       /*  __u8  iProduct; */
+-	0x01,       /*  __u8  iSerialNumber; */
+-	0x01        /*  __u8  bNumConfigurations; */
+-};
+-
+ /* usb 2.0 root hub device descriptor */
+ static const u8 usb2_rh_dev_descriptor[18] = {
+ 	0x12,       /*  __u8  bLength; */
+@@ -368,7 +347,7 @@ static const u8 ss_rh_config_descriptor[] = {
+ };
+ 
+ /* authorized_default behaviour:
+- * -1 is authorized for all devices except wireless (old behaviour)
++ * -1 is authorized for all devices (leftover from wireless USB)
+  * 0 is unauthorized for all devices
+  * 1 is authorized for all devices
+  * 2 is authorized for internal devices
+@@ -383,7 +362,7 @@ module_param(authorized_default, int, S_IRUGO|S_IWUSR);
+ MODULE_PARM_DESC(authorized_default,
+ 		"Default USB device authorization: 0 is not authorized, 1 is "
+ 		"authorized, 2 is authorized for internal devices, -1 is "
+-		"authorized except for wireless USB (default, old behaviour)");
++		"authorized (default, same as 1)");
+ /*-------------------------------------------------------------------------*/
+ 
+ /**
+@@ -578,9 +557,6 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
+ 			case HCD_USB3:
+ 				bufp = usb3_rh_dev_descriptor;
+ 				break;
+-			case HCD_USB25:
+-				bufp = usb25_rh_dev_descriptor;
+-				break;
+ 			case HCD_USB2:
+ 				bufp = usb2_rh_dev_descriptor;
+ 				break;
+@@ -602,7 +578,6 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
+ 				bufp = ss_rh_config_descriptor;
+ 				len = sizeof ss_rh_config_descriptor;
+ 				break;
+-			case HCD_USB25:
+ 			case HCD_USB2:
+ 				bufp = hs_rh_config_descriptor;
+ 				len = sizeof hs_rh_config_descriptor;
+@@ -2848,18 +2823,14 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ 		hcd->dev_policy = USB_DEVICE_AUTHORIZE_NONE;
+ 		break;
+ 
+-	case USB_AUTHORIZE_ALL:
+-		hcd->dev_policy = USB_DEVICE_AUTHORIZE_ALL;
+-		break;
+-
+ 	case USB_AUTHORIZE_INTERNAL:
+ 		hcd->dev_policy = USB_DEVICE_AUTHORIZE_INTERNAL;
+ 		break;
+ 
++	case USB_AUTHORIZE_ALL:
+ 	case USB_AUTHORIZE_WIRED:
+ 	default:
+-		hcd->dev_policy = hcd->wireless ?
+-			USB_DEVICE_AUTHORIZE_NONE : USB_DEVICE_AUTHORIZE_ALL;
++		hcd->dev_policy = USB_DEVICE_AUTHORIZE_ALL;
+ 		break;
+ 	}
+ 
+@@ -2903,9 +2874,6 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ 	case HCD_USB2:
+ 		rhdev->speed = USB_SPEED_HIGH;
+ 		break;
+-	case HCD_USB25:
+-		rhdev->speed = USB_SPEED_WIRELESS;
+-		break;
+ 	case HCD_USB3:
+ 		rhdev->speed = USB_SPEED_SUPER;
+ 		break;
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 878913f4b4b3..b3c09e4c8492 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2140,22 +2140,6 @@ EXPORT_SYMBOL_GPL(usb_set_device_state);
+  * USB-3.0 buses the address is assigned by the controller hardware
+  * and it usually is not the same as the device number.
+  *
+- * WUSB devices are simple: they have no hubs behind, so the mapping
+- * device <-> virtual port number becomes 1:1. Why? to simplify the
+- * life of the device connection logic in
+- * drivers/usb/wusbcore/devconnect.c. When we do the initial secret
+- * handshake we need to assign a temporary address in the unauthorized
+- * space. For simplicity we use the first virtual port number found to
+- * be free [drivers/usb/wusbcore/devconnect.c:wusbhc_devconnect_ack()]
+- * and that becomes it's address [X < 128] or its unauthorized address
+- * [X | 0x80].
+- *
+- * We add 1 as an offset to the one-based USB-stack port number
+- * (zero-based wusb virtual port index) for two reasons: (a) dev addr
+- * 0 is reserved by USB for default address; (b) Linux's USB stack
+- * uses always #1 for the root hub of the controller. So USB stack's
+- * port #1, which is wusb virtual-port #0 has address #2.
+- *
+  * Devices connected under xHCI are not as simple.  The host controller
+  * supports virtualization, so the hardware assigns device addresses and
+  * the HCD must setup data structures before issuing a set address
+@@ -2168,19 +2152,13 @@ static void choose_devnum(struct usb_device *udev)
+ 
+ 	/* be safe when more hub events are proceed in parallel */
+ 	mutex_lock(&bus->devnum_next_mutex);
+-	if (udev->wusb) {
+-		devnum = udev->portnum + 1;
+-		BUG_ON(test_bit(devnum, bus->devmap.devicemap));
+-	} else {
+-		/* Try to allocate the next devnum beginning at
+-		 * bus->devnum_next. */
+-		devnum = find_next_zero_bit(bus->devmap.devicemap, 128,
+-					    bus->devnum_next);
+-		if (devnum >= 128)
+-			devnum = find_next_zero_bit(bus->devmap.devicemap,
+-						    128, 1);
+-		bus->devnum_next = (devnum >= 127 ? 1 : devnum + 1);
+-	}
++
++	/* Try to allocate the next devnum beginning at bus->devnum_next. */
++	devnum = find_next_zero_bit(bus->devmap.devicemap, 128,
++			bus->devnum_next);
++	if (devnum >= 128)
++		devnum = find_next_zero_bit(bus->devmap.devicemap, 128, 1);
++	bus->devnum_next = (devnum >= 127 ? 1 : devnum + 1);
+ 	if (devnum < 128) {
+ 		set_bit(devnum, bus->devmap.devicemap);
+ 		udev->devnum = devnum;
+@@ -2198,9 +2176,7 @@ static void release_devnum(struct usb_device *udev)
+ 
+ static void update_devnum(struct usb_device *udev, int devnum)
+ {
+-	/* The address for a WUSB device is managed by wusbcore. */
+-	if (!udev->wusb)
+-		udev->devnum = devnum;
++	udev->devnum = devnum;
+ 	if (!udev->devaddr)
+ 		udev->devaddr = (u8)devnum;
+ }
+@@ -2693,20 +2669,6 @@ int usb_authorize_device(struct usb_device *usb_dev)
+ 		goto error_autoresume;
+ 	}
+ 
+-	if (usb_dev->wusb) {
+-		struct usb_device_descriptor *descr;
+-
+-		descr = usb_get_device_descriptor(usb_dev);
+-		if (IS_ERR(descr)) {
+-			result = PTR_ERR(descr);
+-			dev_err(&usb_dev->dev, "can't re-read device descriptor for "
+-				"authorization: %d\n", result);
+-			goto error_device_descriptor;
+-		}
+-		usb_dev->descriptor = *descr;
+-		kfree(descr);
+-	}
+-
+ 	usb_dev->authorized = 1;
+ 	/* Choose and set the configuration.  This registers the interfaces
+ 	 * with the driver core and lets interface drivers bind to them.
+@@ -2723,7 +2685,6 @@ int usb_authorize_device(struct usb_device *usb_dev)
+ 	}
+ 	dev_info(&usb_dev->dev, "authorized to connect\n");
+ 
+-error_device_descriptor:
+ 	usb_autosuspend_device(usb_dev);
+ error_autoresume:
+ out_authorized:
+@@ -2806,17 +2767,6 @@ static enum usb_ssp_rate get_port_ssp_rate(struct usb_device *hdev,
+ 	return USB_SSP_GEN_UNKNOWN;
+ }
+ 
+-/* Returns 1 if @hub is a WUSB root hub, 0 otherwise */
+-static unsigned hub_is_wusb(struct usb_hub *hub)
+-{
+-	struct usb_hcd *hcd;
+-	if (hub->hdev->parent != NULL)  /* not a root hub? */
+-		return 0;
+-	hcd = bus_to_hcd(hub->hdev->bus);
+-	return hcd->wireless;
+-}
+-
+-
+ #ifdef CONFIG_USB_FEW_INIT_RETRIES
+ #define PORT_RESET_TRIES	2
+ #define SET_ADDRESS_TRIES	1
+@@ -2969,9 +2919,7 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
+ 		udev->tx_lanes = 1;
+ 		udev->ssp_rate = USB_SSP_GEN_UNKNOWN;
+ 	}
+-	if (hub_is_wusb(hub))
+-		udev->speed = USB_SPEED_WIRELESS;
+-	else if (udev->ssp_rate != USB_SSP_GEN_UNKNOWN)
++	if (udev->ssp_rate != USB_SSP_GEN_UNKNOWN)
+ 		udev->speed = USB_SPEED_SUPER_PLUS;
+ 	else if (hub_is_superspeed(hub->hdev))
+ 		udev->speed = USB_SPEED_SUPER;
+@@ -4880,13 +4828,10 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ 	if (initial) {
+ 		/* USB 2.0 section 5.5.3 talks about ep0 maxpacket ...
+ 		 * it's fixed size except for full speed devices.
+-		 * For Wireless USB devices, ep0 max packet is always 512 (tho
+-		 * reported as 0xff in the device descriptor). WUSB1.0[4.8.1].
+ 		 */
+ 		switch (udev->speed) {
+ 		case USB_SPEED_SUPER_PLUS:
+ 		case USB_SPEED_SUPER:
+-		case USB_SPEED_WIRELESS:	/* fixed at 512 */
+ 			udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512);
+ 			break;
+ 		case USB_SPEED_HIGH:		/* fixed at 64 */
+@@ -4907,10 +4852,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ 		}
+ 	}
+ 
+-	if (udev->speed == USB_SPEED_WIRELESS)
+-		speed = "variable speed Wireless";
+-	else
+-		speed = usb_speed_string(udev->speed);
++	speed = usb_speed_string(udev->speed);
+ 
+ 	/*
+ 	 * The controller driver may be NULL if the controller device
+@@ -5003,50 +4945,44 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ 			}
+ 		}
+ 
++		for (operations = 0; operations < SET_ADDRESS_TRIES; ++operations) {
++			retval = hub_set_address(udev, devnum);
++			if (retval >= 0)
++				break;
++			msleep(200);
++		}
++		if (retval < 0) {
++			if (retval != -ENODEV)
++				dev_err(&udev->dev, "device not accepting address %d, error %d\n",
++						devnum, retval);
++			goto fail;
++		}
++		if (udev->speed >= USB_SPEED_SUPER) {
++			devnum = udev->devnum;
++			dev_info(&udev->dev,
++					"%s SuperSpeed%s%s USB device number %d using %s\n",
++					(udev->config) ? "reset" : "new",
++				 (udev->speed == USB_SPEED_SUPER_PLUS) ?
++						" Plus" : "",
++				 (udev->ssp_rate == USB_SSP_GEN_2x2) ?
++						" Gen 2x2" :
++				 (udev->ssp_rate == USB_SSP_GEN_2x1) ?
++						" Gen 2x1" :
++				 (udev->ssp_rate == USB_SSP_GEN_1x2) ?
++						" Gen 1x2" : "",
++				 devnum, driver_name);
++		}
++
+ 		/*
+-		 * If device is WUSB, we already assigned an
+-		 * unauthorized address in the Connect Ack sequence;
+-		 * authorization will assign the final address.
++		 * cope with hardware quirkiness:
++		 *  - let SET_ADDRESS settle, some device hardware wants it
++		 *  - read ep0 maxpacket even for high and low speed,
+ 		 */
+-		if (udev->wusb == 0) {
+-			for (operations = 0; operations < SET_ADDRESS_TRIES; ++operations) {
+-				retval = hub_set_address(udev, devnum);
+-				if (retval >= 0)
+-					break;
+-				msleep(200);
+-			}
+-			if (retval < 0) {
+-				if (retval != -ENODEV)
+-					dev_err(&udev->dev, "device not accepting address %d, error %d\n",
+-							devnum, retval);
+-				goto fail;
+-			}
+-			if (udev->speed >= USB_SPEED_SUPER) {
+-				devnum = udev->devnum;
+-				dev_info(&udev->dev,
+-						"%s SuperSpeed%s%s USB device number %d using %s\n",
+-						(udev->config) ? "reset" : "new",
+-					 (udev->speed == USB_SPEED_SUPER_PLUS) ?
+-							" Plus" : "",
+-					 (udev->ssp_rate == USB_SSP_GEN_2x2) ?
+-							" Gen 2x2" :
+-					 (udev->ssp_rate == USB_SSP_GEN_2x1) ?
+-							" Gen 2x1" :
+-					 (udev->ssp_rate == USB_SSP_GEN_1x2) ?
+-							" Gen 1x2" : "",
+-					 devnum, driver_name);
+-			}
++		msleep(10);
+ 
+-			/* cope with hardware quirkiness:
+-			 *  - let SET_ADDRESS settle, some device hardware wants it
+-			 *  - read ep0 maxpacket even for high and low speed,
+-			 */
+-			msleep(10);
+-			if (do_new_scheme)
+-				break;
+-		}
++		if (do_new_scheme)
++			break;
+ 
+-		/* !do_new_scheme || wusb */
+ 		maxp0 = get_bMaxPacketSize0(udev, buf, 8, retries == 0);
+ 		if (maxp0 < 0) {
+ 			retval = maxp0;
+@@ -5128,7 +5064,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ 
+ 	usb_detect_quirks(udev);
+ 
+-	if (udev->wusb == 0 && le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0201) {
++	if (le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0201) {
+ 		retval = usb_get_bos_descriptor(udev);
+ 		if (!retval) {
+ 			udev->lpm_capable = usb_device_supports_lpm(udev);
+@@ -5404,7 +5340,6 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
+ 		usb_set_device_state(udev, USB_STATE_POWERED);
+ 		udev->bus_mA = hub->mA_per_port;
+ 		udev->level = hdev->level + 1;
+-		udev->wusb = hub_is_wusb(hub);
+ 
+ 		/* Devices connected to SuperSpeed hubs are USB 3.0 or later */
+ 		if (hub_is_superspeed(hub->hdev))
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 323dc02becbe..5d21718afb05 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -161,9 +161,6 @@ static ssize_t speed_show(struct device *dev, struct device_attribute *attr,
+ 	case USB_SPEED_HIGH:
+ 		speed = "480";
+ 		break;
+-	case USB_SPEED_WIRELESS:
+-		speed = "480";
+-		break;
+ 	case USB_SPEED_SUPER:
+ 		speed = "5000";
+ 		break;
+diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
+index 9f3c54032556..7576920e2d5a 100644
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -480,8 +480,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 			urb->iso_frame_desc[n].status = -EXDEV;
+ 			urb->iso_frame_desc[n].actual_length = 0;
+ 		}
+-	} else if (urb->num_sgs && !urb->dev->bus->no_sg_constraint &&
+-			dev->speed != USB_SPEED_WIRELESS) {
++	} else if (urb->num_sgs && !urb->dev->bus->no_sg_constraint) {
+ 		struct scatterlist *sg;
+ 		int i;
+ 
+@@ -540,17 +539,9 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 	case USB_ENDPOINT_XFER_ISOC:
+ 	case USB_ENDPOINT_XFER_INT:
+ 		/* too small? */
+-		switch (dev->speed) {
+-		case USB_SPEED_WIRELESS:
+-			if ((urb->interval < 6)
+-				&& (xfertype == USB_ENDPOINT_XFER_INT))
+-				return -EINVAL;
+-			fallthrough;
+-		default:
+-			if (urb->interval <= 0)
+-				return -EINVAL;
+-			break;
+-		}
++		if (urb->interval <= 0)
++			return -EINVAL;
++
+ 		/* too big? */
+ 		switch (dev->speed) {
+ 		case USB_SPEED_SUPER_PLUS:
+@@ -560,10 +551,6 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 				return -EINVAL;
+ 			max = 1 << 15;
+ 			break;
+-		case USB_SPEED_WIRELESS:
+-			if (urb->interval > 16)
+-				return -EINVAL;
+-			break;
+ 		case USB_SPEED_HIGH:	/* units are microframes */
+ 			/* NOTE usb handles 2^15 */
+ 			if (urb->interval > (1024 * 8))
+@@ -587,10 +574,8 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 		default:
+ 			return -EINVAL;
+ 		}
+-		if (dev->speed != USB_SPEED_WIRELESS) {
+-			/* Round down to a power of 2, no more than max */
+-			urb->interval = min(max, 1 << ilog2(urb->interval));
+-		}
++		/* Round down to a power of 2, no more than max */
++		urb->interval = min(max, 1 << ilog2(urb->interval));
+ 	}
+ 
+ 	return usb_hcd_submit_urb(urb, mem_flags);
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index bba87e5b7f8a..0945ff8df500 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -602,14 +602,6 @@ struct device_type usb_device_type = {
+ #endif
+ };
+ 
+-
+-/* Returns 1 if @usb_bus is WUSB, 0 otherwise */
+-static unsigned usb_bus_is_wusb(struct usb_bus *bus)
+-{
+-	struct usb_hcd *hcd = bus_to_hcd(bus);
+-	return hcd->wireless;
+-}
+-
+ static bool usb_dev_authorized(struct usb_device *dev, struct usb_hcd *hcd)
+ {
+ 	struct usb_hub *hub;
+@@ -749,9 +741,6 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
+ #endif
+ 
+ 	dev->authorized = usb_dev_authorized(dev, usb_hcd);
+-	if (!root_hub)
+-		dev->wusb = usb_bus_is_wusb(bus) ? 1 : 0;
+-
+ 	return dev;
+ }
+ EXPORT_SYMBOL_GPL(usb_alloc_dev);
+diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
+index 19a402123de0..8714ab5bf04d 100644
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -1108,9 +1108,6 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
+ 		slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_LS);
+ 		max_packets = MAX_PACKET(8);
+ 		break;
+-	case USB_SPEED_WIRELESS:
+-		xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n");
+-		return -EINVAL;
+ 	default:
+ 		/* Speed was set earlier, this shouldn't happen. */
+ 		return -EINVAL;
+diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
+index fae994f679d4..e1b1b64a0723 100644
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -2194,7 +2194,6 @@ static unsigned int xhci_get_block_size(struct usb_device *udev)
+ 	case USB_SPEED_SUPER_PLUS:
+ 		return SS_BLOCK;
+ 	case USB_SPEED_UNKNOWN:
+-	case USB_SPEED_WIRELESS:
+ 	default:
+ 		/* Should never happen */
+ 		return 1;
+@@ -2555,10 +2554,7 @@ static void xhci_drop_ep_from_interval_table(struct xhci_hcd *xhci,
+ 	case USB_SPEED_HIGH:
+ 		interval_bw->overhead[HS_OVERHEAD_TYPE] -= 1;
+ 		break;
+-	case USB_SPEED_SUPER:
+-	case USB_SPEED_SUPER_PLUS:
+-	case USB_SPEED_UNKNOWN:
+-	case USB_SPEED_WIRELESS:
++	default:
+ 		/* Should never happen because only LS/FS/HS endpoints will get
+ 		 * added to the endpoint list.
+ 		 */
+@@ -2615,10 +2611,7 @@ static void xhci_add_ep_to_interval_table(struct xhci_hcd *xhci,
+ 	case USB_SPEED_HIGH:
+ 		interval_bw->overhead[HS_OVERHEAD_TYPE] += 1;
+ 		break;
+-	case USB_SPEED_SUPER:
+-	case USB_SPEED_SUPER_PLUS:
+-	case USB_SPEED_UNKNOWN:
+-	case USB_SPEED_WIRELESS:
++	default:
+ 		/* Should never happen because only LS/FS/HS endpoints will get
+ 		 * added to the endpoint list.
+ 		 */
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 25f8e62a30ec..a21074861f91 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -25,7 +25,6 @@
+ 
+ struct usb_device;
+ struct usb_driver;
+-struct wusb_dev;
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+@@ -425,7 +424,6 @@ struct usb_host_config {
+ struct usb_host_bos {
+ 	struct usb_bos_descriptor	*desc;
+ 
+-	/* wireless cap descriptor is handled by wusb */
+ 	struct usb_ext_cap_descriptor	*ext_cap;
+ 	struct usb_ss_cap_descriptor	*ss_cap;
+ 	struct usb_ssp_cap_descriptor	*ssp_cap;
+@@ -612,7 +610,6 @@ struct usb3_lpm_parameters {
+  *	WUSB devices are not, until we authorize them from user space.
+  *	FIXME -- complete doc
+  * @authenticated: Crypto authentication passed
+- * @wusb: device is Wireless USB
+  * @lpm_capable: device supports LPM
+  * @lpm_devinit_allow: Allow USB3 device initiated LPM, exit latency is in range
+  * @usb2_hw_lpm_capable: device can perform USB2 hardware LPM
+@@ -634,8 +631,6 @@ struct usb3_lpm_parameters {
+  * @do_remote_wakeup:  remote wakeup should be enabled
+  * @reset_resume: needs reset instead of resume
+  * @port_is_suspended: the upstream port is suspended (L2 or U3)
+- * @wusb_dev: if this is a Wireless USB device, link to the WUSB
+- *	specific data for the device.
+  * @slot_id: Slot ID assigned by xHCI
+  * @removable: Device can be physically removed from this port
+  * @l1_params: best effor service latency for USB2 L1 LPM state, and L1 timeout.
+@@ -696,7 +691,6 @@ struct usb_device {
+ 	unsigned have_langid:1;
+ 	unsigned authorized:1;
+ 	unsigned authenticated:1;
+-	unsigned wusb:1;
+ 	unsigned lpm_capable:1;
+ 	unsigned lpm_devinit_allow:1;
+ 	unsigned usb2_hw_lpm_capable:1;
+@@ -727,7 +721,6 @@ struct usb_device {
+ 	unsigned reset_resume:1;
+ 	unsigned port_is_suspended:1;
+ 
+-	struct wusb_dev *wusb_dev;
+ 	int slot_id;
+ 	struct usb2_lpm_parameters l1_params;
+ 	struct usb3_lpm_parameters u1_params;
+@@ -1742,11 +1735,6 @@ static inline void usb_fill_bulk_urb(struct urb *urb,
+  * encoding of the endpoint interval, and express polling intervals in
+  * microframes (eight per millisecond) rather than in frames (one per
+  * millisecond).
+- *
+- * Wireless USB also uses the logarithmic encoding, but specifies it in units of
+- * 128us instead of 125us.  For Wireless USB devices, the interval is passed
+- * through to the host controller, rather than being translated into microframe
+- * units.
+  */
+ static inline void usb_fill_int_urb(struct urb *urb,
+ 				    struct usb_device *dev,
+diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h
+index 969e7dba6358..c93b410b314a 100644
+--- a/include/linux/usb/ch9.h
++++ b/include/linux/usb/ch9.h
+@@ -3,7 +3,7 @@
+  * This file holds USB constants and structures that are needed for
+  * USB device APIs.  These are used by the USB device model, which is
+  * defined in chapter 9 of the USB 2.0 specification and in the
+- * Wireless USB 1.0 (spread around).  Linux has several APIs in C that
++ * Wireless USB 1.0 spec (now defunct).  Linux has several APIs in C that
+  * need these:
+  *
+  * - the host side Linux-USB kernel driver API;
+@@ -14,9 +14,6 @@
+  * act either as a USB host or as a USB device.  That means the host and
+  * device side APIs benefit from working well together.
+  *
+- * There's also "Wireless USB", using low power short range radios for
+- * peripheral interconnection but otherwise building on the USB framework.
+- *
+  * Note all descriptors are declared '__attribute__((packed))' so that:
+  *
+  * [a] they never get padded, either internally (USB spec writers
+diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
+index 07531c4f4350..6014340ba980 100644
+--- a/include/linux/usb/composite.h
++++ b/include/linux/usb/composite.h
+@@ -450,29 +450,6 @@ static inline struct usb_composite_driver *to_cdriver(
+  *
+  * One of these devices is allocated and initialized before the
+  * associated device driver's bind() is called.
+- *
+- * OPEN ISSUE:  it appears that some WUSB devices will need to be
+- * built by combining a normal (wired) gadget with a wireless one.
+- * This revision of the gadget framework should probably try to make
+- * sure doing that won't hurt too much.
+- *
+- * One notion for how to handle Wireless USB devices involves:
+- *
+- * (a) a second gadget here, discovery mechanism TBD, but likely
+- *     needing separate "register/unregister WUSB gadget" calls;
+- * (b) updates to usb_gadget to include flags "is it wireless",
+- *     "is it wired", plus (presumably in a wrapper structure)
+- *     bandgroup and PHY info;
+- * (c) presumably a wireless_ep wrapping a usb_ep, and reporting
+- *     wireless-specific parameters like maxburst and maxsequence;
+- * (d) configurations that are specific to wireless links;
+- * (e) function drivers that understand wireless configs and will
+- *     support wireless for (additional) function instances;
+- * (f) a function to support association setup (like CBAF), not
+- *     necessarily requiring a wireless adapter;
+- * (g) composite device setup that can create one or more wireless
+- *     configs, including appropriate association setup support;
+- * (h) more, TBD.
+  */
+ struct usb_composite_dev {
+ 	struct usb_gadget		*gadget;
+diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
+index 4e9623e8492b..61d4f0b793dc 100644
+--- a/include/linux/usb/hcd.h
++++ b/include/linux/usb/hcd.h
+@@ -154,7 +154,6 @@ struct usb_hcd {
+ 	/* The next flag is a stopgap, to be removed when all the HCDs
+ 	 * support the new root-hub polling mechanism. */
+ 	unsigned		uses_new_polling:1;
+-	unsigned		wireless:1;	/* Wireless USB HCD */
+ 	unsigned		has_tt:1;	/* Integrated TT in root hub */
+ 	unsigned		amd_resume_bug:1; /* AMD remote wakeup quirk */
+ 	unsigned		can_do_streams:1; /* HC supports streams */
+@@ -249,7 +248,6 @@ struct hc_driver {
+ #define	HCD_SHARED	0x0004		/* Two (or more) usb_hcds share HW */
+ #define	HCD_USB11	0x0010		/* USB 1.1 */
+ #define	HCD_USB2	0x0020		/* USB 2.0 */
+-#define	HCD_USB25	0x0030		/* Wireless USB 1.0 (USB 2.5)*/
+ #define	HCD_USB3	0x0040		/* USB 3.0 */
+ #define	HCD_USB31	0x0050		/* USB 3.1 */
+ #define	HCD_USB32	0x0060		/* USB 3.2 */
+diff --git a/include/uapi/linux/usb/ch11.h b/include/uapi/linux/usb/ch11.h
+index fb0cd24c392c..ce4c83f2e66a 100644
+--- a/include/uapi/linux/usb/ch11.h
++++ b/include/uapi/linux/usb/ch11.h
+@@ -15,10 +15,8 @@
+ /* This is arbitrary.
+  * From USB 2.0 spec Table 11-13, offset 7, a hub can
+  * have up to 255 ports. The most yet reported is 10.
+- *
+- * Current Wireless USB host hardware (Intel i1480 for example) allows
+- * up to 22 devices to connect. Upcoming hardware might raise that
+- * limit. Because the arrays need to add a bit for hub status data, we
++ * Upcoming hardware might raise that limit.
++ * Because the arrays need to add a bit for hub status data, we
+  * use 31, so plus one evens out to four bytes.
+  */
+ #define USB_MAXCHILDREN		31
+diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h
+index 62d318377379..8a147abfc680 100644
+--- a/include/uapi/linux/usb/ch9.h
++++ b/include/uapi/linux/usb/ch9.h
+@@ -3,7 +3,7 @@
+  * This file holds USB constants and structures that are needed for
+  * USB device APIs.  These are used by the USB device model, which is
+  * defined in chapter 9 of the USB 2.0 specification and in the
+- * Wireless USB 1.0 (spread around).  Linux has several APIs in C that
++ * Wireless USB 1.0 spec (now defunct).  Linux has several APIs in C that
+  * need these:
+  *
+  * - the master/host side Linux-USB kernel driver API;
+@@ -14,9 +14,6 @@
+  * act either as a USB master/host or as a USB slave/device.  That means
+  * the master and slave side APIs benefit from working well together.
+  *
+- * There's also "Wireless USB", using low power short range radios for
+- * peripheral interconnection but otherwise building on the USB framework.
+- *
+  * Note all descriptors are declared '__attribute__((packed))' so that:
+  *
+  * [a] they never get padded, either internally (USB spec writers

commit ff33299ec8bb80cdcc073ad9c506bd79bb2ed20b
+Author: Alan Stern 
+Date:   Fri Aug 4 15:14:14 2023 -0400
+
+    USB: core: Fix race by not overwriting udev->descriptor in hub_port_init()
+    
+    Syzbot reported an out-of-bounds read in sysfs.c:read_descriptors():
+    
+    BUG: KASAN: slab-out-of-bounds in read_descriptors+0x263/0x280 drivers/usb/core/sysfs.c:883
+    Read of size 8 at addr ffff88801e78b8c8 by task udevd/5011
+    
+    CPU: 0 PID: 5011 Comm: udevd Not tainted 6.4.0-rc6-syzkaller-00195-g40f71e7cd3c6 #0
+    Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 05/27/2023
+    Call Trace:
+     
+     __dump_stack lib/dump_stack.c:88 [inline]
+     dump_stack_lvl+0xd9/0x150 lib/dump_stack.c:106
+     print_address_description.constprop.0+0x2c/0x3c0 mm/kasan/report.c:351
+     print_report mm/kasan/report.c:462 [inline]
+     kasan_report+0x11c/0x130 mm/kasan/report.c:572
+     read_descriptors+0x263/0x280 drivers/usb/core/sysfs.c:883
+    ...
+    Allocated by task 758:
+    ...
+     __do_kmalloc_node mm/slab_common.c:966 [inline]
+     __kmalloc+0x5e/0x190 mm/slab_common.c:979
+     kmalloc include/linux/slab.h:563 [inline]
+     kzalloc include/linux/slab.h:680 [inline]
+     usb_get_configuration+0x1f7/0x5170 drivers/usb/core/config.c:887
+     usb_enumerate_device drivers/usb/core/hub.c:2407 [inline]
+     usb_new_device+0x12b0/0x19d0 drivers/usb/core/hub.c:2545
+    
+    As analyzed by Khazhy Kumykov, the cause of this bug is a race between
+    read_descriptors() and hub_port_init(): The first routine uses a field
+    in udev->descriptor, not expecting it to change, while the second
+    overwrites it.
+    
+    Prior to commit 45bf39f8df7f ("USB: core: Don't hold device lock while
+    reading the "descriptors" sysfs file") this race couldn't occur,
+    because the routines were mutually exclusive thanks to the device
+    locking.  Removing that locking from read_descriptors() exposed it to
+    the race.
+    
+    The best way to fix the bug is to keep hub_port_init() from changing
+    udev->descriptor once udev has been initialized and registered.
+    Drivers expect the descriptors stored in the kernel to be immutable;
+    we should not undermine this expectation.  In fact, this change should
+    have been made long ago.
+    
+    So now hub_port_init() will take an additional argument, specifying a
+    buffer in which to store the device descriptor it reads.  (If udev has
+    not yet been initialized, the buffer pointer will be NULL and then
+    hub_port_init() will store the device descriptor in udev as before.)
+    This eliminates the data race responsible for the out-of-bounds read.
+    
+    The changes to hub_port_init() appear more extensive than they really
+    are, because of indentation changes resulting from an attempt to avoid
+    writing to other parts of the usb_device structure after it has been
+    initialized.  Similar changes should be made to the code that reads
+    the BOS descriptor, but that can be handled in a separate patch later
+    on.  This patch is sufficient to fix the bug found by syzbot.
+    
+    Reported-and-tested-by: syzbot+18996170f8096c6174d0@syzkaller.appspotmail.com
+    Closes: https://lore.kernel.org/linux-usb/000000000000c0ffe505fe86c9ca@google.com/#r
+    Signed-off-by: Alan Stern 
+    Cc: Khazhy Kumykov 
+    Fixes: 45bf39f8df7f ("USB: core: Don't hold device lock while reading the "descriptors" sysfs file")
+    Cc: stable@vger.kernel.org
+    Link: https://lore.kernel.org/r/b958b47a-9a46-4c22-a9f9-e42e42c31251@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 9279c8ccbcf2..878913f4b4b3 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -4816,10 +4816,17 @@ static int get_bMaxPacketSize0(struct usb_device *udev,
+  * the port lock.  For a newly detected device that is not accessible
+  * through any global pointers, it's not necessary to lock the device,
+  * but it is still necessary to lock the port.
++ *
++ * For a newly detected device, @dev_descr must be NULL.  The device
++ * descriptor retrieved from the device will then be stored in
++ * @udev->descriptor.  For an already existing device, @dev_descr
++ * must be non-NULL.  The device descriptor will be stored there,
++ * not in @udev->descriptor, because descriptors for registered
++ * devices are meant to be immutable.
+  */
+ static int
+ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+-		int retry_counter)
++		int retry_counter, struct usb_device_descriptor *dev_descr)
+ {
+ 	struct usb_device	*hdev = hub->hdev;
+ 	struct usb_hcd		*hcd = bus_to_hcd(hdev->bus);
+@@ -4831,6 +4838,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ 	int			devnum = udev->devnum;
+ 	const char		*driver_name;
+ 	bool			do_new_scheme;
++	const bool		initial = !dev_descr;
+ 	int			maxp0;
+ 	struct usb_device_descriptor	*buf, *descr;
+ 
+@@ -4869,32 +4877,34 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ 	}
+ 	oldspeed = udev->speed;
+ 
+-	/* USB 2.0 section 5.5.3 talks about ep0 maxpacket ...
+-	 * it's fixed size except for full speed devices.
+-	 * For Wireless USB devices, ep0 max packet is always 512 (tho
+-	 * reported as 0xff in the device descriptor). WUSB1.0[4.8.1].
+-	 */
+-	switch (udev->speed) {
+-	case USB_SPEED_SUPER_PLUS:
+-	case USB_SPEED_SUPER:
+-	case USB_SPEED_WIRELESS:	/* fixed at 512 */
+-		udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512);
+-		break;
+-	case USB_SPEED_HIGH:		/* fixed at 64 */
+-		udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
+-		break;
+-	case USB_SPEED_FULL:		/* 8, 16, 32, or 64 */
+-		/* to determine the ep0 maxpacket size, try to read
+-		 * the device descriptor to get bMaxPacketSize0 and
+-		 * then correct our initial guess.
++	if (initial) {
++		/* USB 2.0 section 5.5.3 talks about ep0 maxpacket ...
++		 * it's fixed size except for full speed devices.
++		 * For Wireless USB devices, ep0 max packet is always 512 (tho
++		 * reported as 0xff in the device descriptor). WUSB1.0[4.8.1].
+ 		 */
+-		udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
+-		break;
+-	case USB_SPEED_LOW:		/* fixed at 8 */
+-		udev->ep0.desc.wMaxPacketSize = cpu_to_le16(8);
+-		break;
+-	default:
+-		goto fail;
++		switch (udev->speed) {
++		case USB_SPEED_SUPER_PLUS:
++		case USB_SPEED_SUPER:
++		case USB_SPEED_WIRELESS:	/* fixed at 512 */
++			udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512);
++			break;
++		case USB_SPEED_HIGH:		/* fixed at 64 */
++			udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
++			break;
++		case USB_SPEED_FULL:		/* 8, 16, 32, or 64 */
++			/* to determine the ep0 maxpacket size, try to read
++			 * the device descriptor to get bMaxPacketSize0 and
++			 * then correct our initial guess.
++			 */
++			udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
++			break;
++		case USB_SPEED_LOW:		/* fixed at 8 */
++			udev->ep0.desc.wMaxPacketSize = cpu_to_le16(8);
++			break;
++		default:
++			goto fail;
++		}
+ 	}
+ 
+ 	if (udev->speed == USB_SPEED_WIRELESS)
+@@ -4917,22 +4927,24 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ 	if (udev->speed < USB_SPEED_SUPER)
+ 		dev_info(&udev->dev,
+ 				"%s %s USB device number %d using %s\n",
+-				(udev->config) ? "reset" : "new", speed,
++				(initial ? "new" : "reset"), speed,
+ 				devnum, driver_name);
+ 
+-	/* Set up TT records, if needed  */
+-	if (hdev->tt) {
+-		udev->tt = hdev->tt;
+-		udev->ttport = hdev->ttport;
+-	} else if (udev->speed != USB_SPEED_HIGH
+-			&& hdev->speed == USB_SPEED_HIGH) {
+-		if (!hub->tt.hub) {
+-			dev_err(&udev->dev, "parent hub has no TT\n");
+-			retval = -EINVAL;
+-			goto fail;
++	if (initial) {
++		/* Set up TT records, if needed  */
++		if (hdev->tt) {
++			udev->tt = hdev->tt;
++			udev->ttport = hdev->ttport;
++		} else if (udev->speed != USB_SPEED_HIGH
++				&& hdev->speed == USB_SPEED_HIGH) {
++			if (!hub->tt.hub) {
++				dev_err(&udev->dev, "parent hub has no TT\n");
++				retval = -EINVAL;
++				goto fail;
++			}
++			udev->tt = &hub->tt;
++			udev->ttport = port1;
+ 		}
+-		udev->tt = &hub->tt;
+-		udev->ttport = port1;
+ 	}
+ 
+ 	/* Why interleave GET_DESCRIPTOR and SET_ADDRESS this way?
+@@ -4966,6 +4978,12 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ 
+ 			maxp0 = get_bMaxPacketSize0(udev, buf,
+ 					GET_DESCRIPTOR_BUFSIZE, retries == 0);
++			if (maxp0 > 0 && !initial &&
++					maxp0 != udev->descriptor.bMaxPacketSize0) {
++				dev_err(&udev->dev, "device reset changed ep0 maxpacket size!\n");
++				retval = -ENODEV;
++				goto fail;
++			}
+ 
+ 			retval = hub_port_reset(hub, port1, udev, delay, false);
+ 			if (retval < 0)		/* error or disconnect */
+@@ -5039,6 +5057,12 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ 		} else {
+ 			u32 delay;
+ 
++			if (!initial && maxp0 != udev->descriptor.bMaxPacketSize0) {
++				dev_err(&udev->dev, "device reset changed ep0 maxpacket size!\n");
++				retval = -ENODEV;
++				goto fail;
++			}
++
+ 			delay = udev->parent->hub_delay;
+ 			udev->hub_delay = min_t(u32, delay,
+ 						USB_TP_TRANSMISSION_DELAY_MAX);
+@@ -5082,7 +5106,10 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ 					retval);
+ 		goto fail;
+ 	}
+-	udev->descriptor = *descr;
++	if (initial)
++		udev->descriptor = *descr;
++	else
++		*dev_descr = *descr;
+ 	kfree(descr);
+ 
+ 	/*
+@@ -5392,7 +5419,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
+ 		}
+ 
+ 		/* reset (non-USB 3.0 devices) and get descriptor */
+-		status = hub_port_init(hub, udev, port1, i);
++		status = hub_port_init(hub, udev, port1, i, NULL);
+ 		if (status < 0)
+ 			goto loop;
+ 
+@@ -6022,7 +6049,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
+ 	struct usb_device		*parent_hdev = udev->parent;
+ 	struct usb_hub			*parent_hub;
+ 	struct usb_hcd			*hcd = bus_to_hcd(udev->bus);
+-	struct usb_device_descriptor	descriptor = udev->descriptor;
++	struct usb_device_descriptor	descriptor;
+ 	struct usb_host_bos		*bos;
+ 	int				i, j, ret = 0;
+ 	int				port1 = udev->portnum;
+@@ -6058,7 +6085,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
+ 		/* ep0 maxpacket size may change; let the HCD know about it.
+ 		 * Other endpoints will be handled by re-enumeration. */
+ 		usb_ep0_reinit(udev);
+-		ret = hub_port_init(parent_hub, udev, port1, i);
++		ret = hub_port_init(parent_hub, udev, port1, i, &descriptor);
+ 		if (ret >= 0 || ret == -ENOTCONN || ret == -ENODEV)
+ 			break;
+ 	}
+@@ -6070,7 +6097,6 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
+ 	/* Device might have changed firmware (DFU or similar) */
+ 	if (descriptors_changed(udev, &descriptor, bos)) {
+ 		dev_info(&udev->dev, "device firmware changed\n");
+-		udev->descriptor = descriptor;	/* for disconnect() calls */
+ 		goto re_enumerate;
+ 	}
+ 

commit de28e469da75359a2bb8cd8778b78aa64b1be1f4
+Author: Alan Stern 
+Date:   Fri Aug 4 15:12:21 2023 -0400
+
+    USB: core: Change usb_get_device_descriptor() API
+    
+    The usb_get_device_descriptor() routine reads the device descriptor
+    from the udev device and stores it directly in udev->descriptor.  This
+    interface is error prone, because the USB subsystem expects in-memory
+    copies of a device's descriptors to be immutable once the device has
+    been initialized.
+    
+    The interface is changed so that the device descriptor is left in a
+    kmalloc-ed buffer, not copied into the usb_device structure.  A
+    pointer to the buffer is returned to the caller, who is then
+    responsible for kfree-ing it.  The corresponding changes needed in the
+    various callers are fairly small.
+    
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/d0111bb6-56c1-4f90-adf2-6cfe152f6561@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 8300baedafd2..6af0a31ff147 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -983,6 +983,7 @@ static int register_root_hub(struct usb_hcd *hcd)
+ {
+ 	struct device *parent_dev = hcd->self.controller;
+ 	struct usb_device *usb_dev = hcd->self.root_hub;
++	struct usb_device_descriptor *descr;
+ 	const int devnum = 1;
+ 	int retval;
+ 
+@@ -994,13 +995,16 @@ static int register_root_hub(struct usb_hcd *hcd)
+ 	mutex_lock(&usb_bus_idr_lock);
+ 
+ 	usb_dev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
+-	retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE);
+-	if (retval != sizeof usb_dev->descriptor) {
++	descr = usb_get_device_descriptor(usb_dev);
++	if (IS_ERR(descr)) {
++		retval = PTR_ERR(descr);
+ 		mutex_unlock(&usb_bus_idr_lock);
+ 		dev_dbg (parent_dev, "can't read %s device descriptor %d\n",
+ 				dev_name(&usb_dev->dev), retval);
+-		return (retval < 0) ? retval : -EMSGSIZE;
++		return retval;
+ 	}
++	usb_dev->descriptor = *descr;
++	kfree(descr);
+ 
+ 	if (le16_to_cpu(usb_dev->descriptor.bcdUSB) >= 0x0201) {
+ 		retval = usb_get_bos_descriptor(usb_dev);
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 91abcd904d04..9279c8ccbcf2 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2694,12 +2694,17 @@ int usb_authorize_device(struct usb_device *usb_dev)
+ 	}
+ 
+ 	if (usb_dev->wusb) {
+-		result = usb_get_device_descriptor(usb_dev, sizeof(usb_dev->descriptor));
+-		if (result < 0) {
++		struct usb_device_descriptor *descr;
++
++		descr = usb_get_device_descriptor(usb_dev);
++		if (IS_ERR(descr)) {
++			result = PTR_ERR(descr);
+ 			dev_err(&usb_dev->dev, "can't re-read device descriptor for "
+ 				"authorization: %d\n", result);
+ 			goto error_device_descriptor;
+ 		}
++		usb_dev->descriptor = *descr;
++		kfree(descr);
+ 	}
+ 
+ 	usb_dev->authorized = 1;
+@@ -4827,7 +4832,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ 	const char		*driver_name;
+ 	bool			do_new_scheme;
+ 	int			maxp0;
+-	struct usb_device_descriptor	*buf;
++	struct usb_device_descriptor	*buf, *descr;
+ 
+ 	buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO);
+ 	if (!buf)
+@@ -5069,15 +5074,16 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ 		usb_ep0_reinit(udev);
+ 	}
+ 
+-	retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);
+-	if (retval < (signed)sizeof(udev->descriptor)) {
++	descr = usb_get_device_descriptor(udev);
++	if (IS_ERR(descr)) {
++		retval = PTR_ERR(descr);
+ 		if (retval != -ENODEV)
+ 			dev_err(&udev->dev, "device descriptor read/all, error %d\n",
+ 					retval);
+-		if (retval >= 0)
+-			retval = -ENOMSG;
+ 		goto fail;
+ 	}
++	udev->descriptor = *descr;
++	kfree(descr);
+ 
+ 	/*
+ 	 * Some superspeed devices have finished the link training process
+@@ -5196,7 +5202,7 @@ hub_power_remaining(struct usb_hub *hub)
+ 
+ 
+ static int descriptors_changed(struct usb_device *udev,
+-		struct usb_device_descriptor *old_device_descriptor,
++		struct usb_device_descriptor *new_device_descriptor,
+ 		struct usb_host_bos *old_bos)
+ {
+ 	int		changed = 0;
+@@ -5207,8 +5213,8 @@ static int descriptors_changed(struct usb_device *udev,
+ 	int		length;
+ 	char		*buf;
+ 
+-	if (memcmp(&udev->descriptor, old_device_descriptor,
+-			sizeof(*old_device_descriptor)) != 0)
++	if (memcmp(&udev->descriptor, new_device_descriptor,
++			sizeof(*new_device_descriptor)) != 0)
+ 		return 1;
+ 
+ 	if ((old_bos && !udev->bos) || (!old_bos && udev->bos))
+@@ -5533,9 +5539,8 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ {
+ 	struct usb_port *port_dev = hub->ports[port1 - 1];
+ 	struct usb_device *udev = port_dev->child;
+-	struct usb_device_descriptor descriptor;
++	struct usb_device_descriptor *descr;
+ 	int status = -ENODEV;
+-	int retval;
+ 
+ 	dev_dbg(&port_dev->dev, "status %04x, change %04x, %s\n", portstatus,
+ 			portchange, portspeed(hub, portstatus));
+@@ -5562,23 +5567,20 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 			 * changed device descriptors before resuscitating the
+ 			 * device.
+ 			 */
+-			descriptor = udev->descriptor;
+-			retval = usb_get_device_descriptor(udev,
+-					sizeof(udev->descriptor));
+-			if (retval < 0) {
++			descr = usb_get_device_descriptor(udev);
++			if (IS_ERR(descr)) {
+ 				dev_dbg(&udev->dev,
+-						"can't read device descriptor %d\n",
+-						retval);
++						"can't read device descriptor %ld\n",
++						PTR_ERR(descr));
+ 			} else {
+-				if (descriptors_changed(udev, &descriptor,
++				if (descriptors_changed(udev, descr,
+ 						udev->bos)) {
+ 					dev_dbg(&udev->dev,
+ 							"device descriptor has changed\n");
+-					/* for disconnect() calls */
+-					udev->descriptor = descriptor;
+ 				} else {
+ 					status = 0; /* Nothing to do */
+ 				}
++				kfree(descr);
+ 			}
+ #ifdef CONFIG_PM
+ 		} else if (udev->state == USB_STATE_SUSPENDED &&
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 0d2bfc909019..077dfe48d01c 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1041,40 +1041,35 @@ char *usb_cache_string(struct usb_device *udev, int index)
+ EXPORT_SYMBOL_GPL(usb_cache_string);
+ 
+ /*
+- * usb_get_device_descriptor - (re)reads the device descriptor (usbcore)
+- * @dev: the device whose device descriptor is being updated
+- * @size: how much of the descriptor to read
++ * usb_get_device_descriptor - read the device descriptor
++ * @udev: the device whose device descriptor should be read
+  *
+  * Context: task context, might sleep.
+  *
+- * Updates the copy of the device descriptor stored in the device structure,
+- * which dedicates space for this purpose.
+- *
+  * Not exported, only for use by the core.  If drivers really want to read
+  * the device descriptor directly, they can call usb_get_descriptor() with
+  * type = USB_DT_DEVICE and index = 0.
+  *
+- * This call is synchronous, and may not be used in an interrupt context.
+- *
+- * Return: The number of bytes received on success, or else the status code
+- * returned by the underlying usb_control_msg() call.
++ * Returns: a pointer to a dynamically allocated usb_device_descriptor
++ * structure (which the caller must deallocate), or an ERR_PTR value.
+  */
+-int usb_get_device_descriptor(struct usb_device *dev, unsigned int size)
++struct usb_device_descriptor *usb_get_device_descriptor(struct usb_device *udev)
+ {
+ 	struct usb_device_descriptor *desc;
+ 	int ret;
+ 
+-	if (size > sizeof(*desc))
+-		return -EINVAL;
+ 	desc = kmalloc(sizeof(*desc), GFP_NOIO);
+ 	if (!desc)
+-		return -ENOMEM;
++		return ERR_PTR(-ENOMEM);
++
++	ret = usb_get_descriptor(udev, USB_DT_DEVICE, 0, desc, sizeof(*desc));
++	if (ret == sizeof(*desc))
++		return desc;
+ 
+-	ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size);
+ 	if (ret >= 0)
+-		memcpy(&dev->descriptor, desc, size);
++		ret = -EMSGSIZE;
+ 	kfree(desc);
+-	return ret;
++	return ERR_PTR(ret);
+ }
+ 
+ /*
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 69ca59841083..60363153fc3f 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -43,8 +43,8 @@ extern bool usb_endpoint_is_ignored(struct usb_device *udev,
+ 		struct usb_endpoint_descriptor *epd);
+ extern int usb_remove_device(struct usb_device *udev);
+ 
+-extern int usb_get_device_descriptor(struct usb_device *dev,
+-		unsigned int size);
++extern struct usb_device_descriptor *usb_get_device_descriptor(
++		struct usb_device *udev);
+ extern int usb_set_isoch_delay(struct usb_device *dev);
+ extern int usb_get_bos_descriptor(struct usb_device *dev);
+ extern void usb_release_bos_descriptor(struct usb_device *dev);

commit 85d07c55621676d47d873d2749b88f783cd4d5a1
+Author: Alan Stern 
+Date:   Fri Aug 4 15:10:59 2023 -0400
+
+    USB: core: Unite old scheme and new scheme descriptor reads
+    
+    In preparation for reworking the usb_get_device_descriptor() routine,
+    it is desirable to unite the two different code paths responsible for
+    initially determining endpoint 0's maximum packet size in a newly
+    discovered USB device.  Making this determination presents a
+    chicken-and-egg sort of problem, in that the only way to learn the
+    maxpacket value is to get it from the device descriptor retrieved from
+    the device, but communicating with the device to retrieve a descriptor
+    requires us to know beforehand the ep0 maxpacket size.
+    
+    In practice this problem is solved in two different ways, referred to
+    in hub.c as the "old scheme" and the "new scheme".  The old scheme
+    (which is the approach recommended by the USB-2 spec) involves asking
+    the device to send just the first eight bytes of its device
+    descriptor.  Such a transfer uses packets containing no more than
+    eight bytes each, and every USB device must have an ep0 maxpacket size
+    >= 8, so this should succeed.  Since the bMaxPacketSize0 field of the
+    device descriptor lies within the first eight bytes, this is all we
+    need.
+    
+    The new scheme is an imitation of the technique used in an early
+    Windows USB implementation, giving it the happy advantage of working
+    with a wide variety of devices (some of them at the time would not
+    work with the old scheme, although that's probably less true now).  It
+    involves making an initial guess of the ep0 maxpacket size, asking the
+    device to send up to 64 bytes worth of its device descriptor (which is
+    only 18 bytes long), and then resetting the device to clear any error
+    condition that might have resulted from the guess being wrong.  The
+    initial guess is determined by the connection speed; it should be
+    correct in all cases other than full speed, for which the allowed
+    values are 8, 16, 32, and 64 (in this case the initial guess is 64).
+    
+    The reason for this patch is that the old- and new-scheme parts of
+    hub_port_init() use different code paths, one involving
+    usb_get_device_descriptor() and one not, for their initial reads of
+    the device descriptor.  Since these reads have essentially the same
+    purpose and are made under essentially the same circumstances, this is
+    illogical.  It makes more sense to have both of them use a common
+    subroutine.
+    
+    This subroutine does basically what the new scheme's code did, because
+    that approach is more general than the one used by the old scheme.  It
+    only needs to know how many bytes to transfer and whether or not it is
+    being called for the first iteration of a retry loop (in case of
+    certain time-out errors).  There are two main differences from the
+    former code:
+    
+            We initialize the bDescriptorType field of the transfer buffer
+            to 0 before performing the transfer, to avoid possibly
+            accessing an uninitialized value afterward.
+    
+            We read the device descriptor into a temporary buffer rather
+            than storing it directly into udev->descriptor, which the old
+            scheme implementation used to do.
+    
+    Since the whole point of this first read of the device descriptor is
+    to determine the bMaxPacketSize0 value, that is what the new routine
+    returns (or an error code).  The value is stored in a local variable
+    rather than in udev->descriptor.  As a side effect, this necessitates
+    moving a section of code that checks the bcdUSB field for SuperSpeed
+    devices until after the full device descriptor has been retrieved.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Oliver Neukum 
+    Link: https://lore.kernel.org/r/495cb5d4-f956-4f4a-a875-1e67e9489510@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index fcbad9e86328..91abcd904d04 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -4741,6 +4741,67 @@ static int hub_enable_device(struct usb_device *udev)
+ 	return hcd->driver->enable_device(hcd, udev);
+ }
+ 
++/*
++ * Get the bMaxPacketSize0 value during initialization by reading the
++ * device's device descriptor.  Since we don't already know this value,
++ * the transfer is unsafe and it ignores I/O errors, only testing for
++ * reasonable received values.
++ *
++ * For "old scheme" initialization, size will be 8 so we read just the
++ * start of the device descriptor, which should work okay regardless of
++ * the actual bMaxPacketSize0 value.  For "new scheme" initialization,
++ * size will be 64 (and buf will point to a sufficiently large buffer),
++ * which might not be kosher according to the USB spec but it's what
++ * Windows does and what many devices expect.
++ *
++ * Returns: bMaxPacketSize0 or a negative error code.
++ */
++static int get_bMaxPacketSize0(struct usb_device *udev,
++		struct usb_device_descriptor *buf, int size, bool first_time)
++{
++	int i, rc;
++
++	/*
++	 * Retry on all errors; some devices are flakey.
++	 * 255 is for WUSB devices, we actually need to use
++	 * 512 (WUSB1.0[4.8.1]).
++	 */
++	for (i = 0; i < GET_MAXPACKET0_TRIES; ++i) {
++		/* Start with invalid values in case the transfer fails */
++		buf->bDescriptorType = buf->bMaxPacketSize0 = 0;
++		rc = usb_control_msg(udev, usb_rcvaddr0pipe(),
++				USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
++				USB_DT_DEVICE << 8, 0,
++				buf, size,
++				initial_descriptor_timeout);
++		switch (buf->bMaxPacketSize0) {
++		case 8: case 16: case 32: case 64: case 255:
++			if (buf->bDescriptorType == USB_DT_DEVICE) {
++				rc = buf->bMaxPacketSize0;
++				break;
++			}
++			fallthrough;
++		default:
++			if (rc >= 0)
++				rc = -EPROTO;
++			break;
++		}
++
++		/*
++		 * Some devices time out if they are powered on
++		 * when already connected. They need a second
++		 * reset, so return early. But only on the first
++		 * attempt, lest we get into a time-out/reset loop.
++		 */
++		if (rc > 0 || (rc == -ETIMEDOUT && first_time &&
++				udev->speed > USB_SPEED_FULL))
++			break;
++	}
++	return rc;
++}
++
++#define GET_DESCRIPTOR_BUFSIZE	64
++
+ /* Reset device, (re)assign address, get device descriptor.
+  * Device connection must be stable, no more debouncing needed.
+  * Returns device in USB_STATE_ADDRESS, except on error.
+@@ -4765,6 +4826,12 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ 	int			devnum = udev->devnum;
+ 	const char		*driver_name;
+ 	bool			do_new_scheme;
++	int			maxp0;
++	struct usb_device_descriptor	*buf;
++
++	buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO);
++	if (!buf)
++		return -ENOMEM;
+ 
+ 	/* root hub ports have a slightly longer reset period
+ 	 * (from USB 2.0 spec, section 7.1.7.5)
+@@ -4884,9 +4951,6 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ 		}
+ 
+ 		if (do_new_scheme) {
+-			struct usb_device_descriptor *buf;
+-			int r = 0;
+-
+ 			retval = hub_enable_device(udev);
+ 			if (retval < 0) {
+ 				dev_err(&udev->dev,
+@@ -4895,52 +4959,8 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ 				goto fail;
+ 			}
+ 
+-#define GET_DESCRIPTOR_BUFSIZE	64
+-			buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO);
+-			if (!buf) {
+-				retval = -ENOMEM;
+-				continue;
+-			}
+-
+-			/* Retry on all errors; some devices are flakey.
+-			 * 255 is for WUSB devices, we actually need to use
+-			 * 512 (WUSB1.0[4.8.1]).
+-			 */
+-			for (operations = 0; operations < GET_MAXPACKET0_TRIES;
+-					++operations) {
+-				buf->bMaxPacketSize0 = 0;
+-				r = usb_control_msg(udev, usb_rcvaddr0pipe(),
+-					USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+-					USB_DT_DEVICE << 8, 0,
+-					buf, GET_DESCRIPTOR_BUFSIZE,
+-					initial_descriptor_timeout);
+-				switch (buf->bMaxPacketSize0) {
+-				case 8: case 16: case 32: case 64: case 255:
+-					if (buf->bDescriptorType ==
+-							USB_DT_DEVICE) {
+-						r = 0;
+-						break;
+-					}
+-					fallthrough;
+-				default:
+-					if (r == 0)
+-						r = -EPROTO;
+-					break;
+-				}
+-				/*
+-				 * Some devices time out if they are powered on
+-				 * when already connected. They need a second
+-				 * reset. But only on the first attempt,
+-				 * lest we get into a time out/reset loop
+-				 */
+-				if (r == 0 || (r == -ETIMEDOUT &&
+-						retries == 0 &&
+-						udev->speed > USB_SPEED_FULL))
+-					break;
+-			}
+-			udev->descriptor.bMaxPacketSize0 =
+-					buf->bMaxPacketSize0;
+-			kfree(buf);
++			maxp0 = get_bMaxPacketSize0(udev, buf,
++					GET_DESCRIPTOR_BUFSIZE, retries == 0);
+ 
+ 			retval = hub_port_reset(hub, port1, udev, delay, false);
+ 			if (retval < 0)		/* error or disconnect */
+@@ -4951,14 +4971,13 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ 				retval = -ENODEV;
+ 				goto fail;
+ 			}
+-			if (r) {
+-				if (r != -ENODEV)
++			if (maxp0 < 0) {
++				if (maxp0 != -ENODEV)
+ 					dev_err(&udev->dev, "device descriptor read/64, error %d\n",
+-							r);
+-				retval = -EMSGSIZE;
++							maxp0);
++				retval = maxp0;
+ 				continue;
+ 			}
+-#undef GET_DESCRIPTOR_BUFSIZE
+ 		}
+ 
+ 		/*
+@@ -5004,19 +5023,17 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ 				break;
+ 		}
+ 
+-		retval = usb_get_device_descriptor(udev, 8);
+-		if (retval < 8) {
++		/* !do_new_scheme || wusb */
++		maxp0 = get_bMaxPacketSize0(udev, buf, 8, retries == 0);
++		if (maxp0 < 0) {
++			retval = maxp0;
+ 			if (retval != -ENODEV)
+ 				dev_err(&udev->dev,
+ 					"device descriptor read/8, error %d\n",
+ 					retval);
+-			if (retval >= 0)
+-				retval = -EMSGSIZE;
+ 		} else {
+ 			u32 delay;
+ 
+-			retval = 0;
+-
+ 			delay = udev->parent->hub_delay;
+ 			udev->hub_delay = min_t(u32, delay,
+ 						USB_TP_TRANSMISSION_DELAY_MAX);
+@@ -5033,27 +5050,10 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ 	if (retval)
+ 		goto fail;
+ 
+-	/*
+-	 * Some superspeed devices have finished the link training process
+-	 * and attached to a superspeed hub port, but the device descriptor
+-	 * got from those devices show they aren't superspeed devices. Warm
+-	 * reset the port attached by the devices can fix them.
+-	 */
+-	if ((udev->speed >= USB_SPEED_SUPER) &&
+-			(le16_to_cpu(udev->descriptor.bcdUSB) < 0x0300)) {
+-		dev_err(&udev->dev, "got a wrong device descriptor, "
+-				"warm reset device\n");
+-		hub_port_reset(hub, port1, udev,
+-				HUB_BH_RESET_TIME, true);
+-		retval = -EINVAL;
+-		goto fail;
+-	}
+-
+-	if (udev->descriptor.bMaxPacketSize0 == 0xff ||
+-			udev->speed >= USB_SPEED_SUPER)
++	if (maxp0 == 0xff || udev->speed >= USB_SPEED_SUPER)
+ 		i = 512;
+ 	else
+-		i = udev->descriptor.bMaxPacketSize0;
++		i = maxp0;
+ 	if (usb_endpoint_maxp(&udev->ep0.desc) != i) {
+ 		if (udev->speed == USB_SPEED_LOW ||
+ 				!(i == 8 || i == 16 || i == 32 || i == 64)) {
+@@ -5079,6 +5079,20 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ 		goto fail;
+ 	}
+ 
++	/*
++	 * Some superspeed devices have finished the link training process
++	 * and attached to a superspeed hub port, but the device descriptor
++	 * got from those devices show they aren't superspeed devices. Warm
++	 * reset the port attached by the devices can fix them.
++	 */
++	if ((udev->speed >= USB_SPEED_SUPER) &&
++			(le16_to_cpu(udev->descriptor.bcdUSB) < 0x0300)) {
++		dev_err(&udev->dev, "got a wrong device descriptor, warm reset device\n");
++		hub_port_reset(hub, port1, udev, HUB_BH_RESET_TIME, true);
++		retval = -EINVAL;
++		goto fail;
++	}
++
+ 	usb_detect_quirks(udev);
+ 
+ 	if (udev->wusb == 0 && le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0201) {
+@@ -5101,6 +5115,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ 		hub_port_disable(hub, port1, 0);
+ 		update_devnum(udev, devnum);	/* for disconnect processing */
+ 	}
++	kfree(buf);
+ 	return retval;
+ }
+ 

commit a6ff6e7a9dd69364547751db0f626a10a6d628d2
+Author: Alan Stern 
+Date:   Wed Aug 2 13:49:02 2023 -0400
+
+    usb-storage: alauda: Fix uninit-value in alauda_check_media()
+    
+    Syzbot got KMSAN to complain about access to an uninitialized value in
+    the alauda subdriver of usb-storage:
+    
+    BUG: KMSAN: uninit-value in alauda_transport+0x462/0x57f0
+    drivers/usb/storage/alauda.c:1137
+    CPU: 0 PID: 12279 Comm: usb-storage Not tainted 5.3.0-rc7+ #0
+    Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
+    Google 01/01/2011
+    Call Trace:
+      __dump_stack lib/dump_stack.c:77 [inline]
+      dump_stack+0x191/0x1f0 lib/dump_stack.c:113
+      kmsan_report+0x13a/0x2b0 mm/kmsan/kmsan_report.c:108
+      __msan_warning+0x73/0xe0 mm/kmsan/kmsan_instr.c:250
+      alauda_check_media+0x344/0x3310 drivers/usb/storage/alauda.c:460
+    
+    The problem is that alauda_check_media() doesn't verify that its USB
+    transfer succeeded before trying to use the received data.  What
+    should happen if the transfer fails isn't entirely clear, but a
+    reasonably conservative approach is to pretend that no media is
+    present.
+    
+    A similar problem exists in a usb_stor_dbg() call in
+    alauda_get_media_status().  In this case, when an error occurs the
+    call is redundant, because usb_stor_ctrl_transfer() already will print
+    a debugging message.
+    
+    Finally, unrelated to the uninitialized memory access, is the fact
+    that alauda_check_media() performs DMA to a buffer on the stack.
+    Fortunately usb-storage provides a general purpose DMA-able buffer for
+    uses like this.  We'll use it instead.
+    
+    Reported-and-tested-by: syzbot+e7d46eb426883fb97efd@syzkaller.appspotmail.com
+    Closes: https://lore.kernel.org/all/0000000000007d25ff059457342d@google.com/T/
+    Suggested-by: Christophe JAILLET 
+    Signed-off-by: Alan Stern 
+    Fixes: e80b0fade09e ("[PATCH] USB Storage: add alauda support")
+    Cc: 
+    Link: https://lore.kernel.org/r/693d5d5e-f09b-42d0-8ed9-1f96cd30bcce@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c
+index 5e912dd29b4c..115f05a6201a 100644
+--- a/drivers/usb/storage/alauda.c
++++ b/drivers/usb/storage/alauda.c
+@@ -318,7 +318,8 @@ static int alauda_get_media_status(struct us_data *us, unsigned char *data)
+ 	rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe,
+ 		command, 0xc0, 0, 1, data, 2);
+ 
+-	usb_stor_dbg(us, "Media status %02X %02X\n", data[0], data[1]);
++	if (rc == USB_STOR_XFER_GOOD)
++		usb_stor_dbg(us, "Media status %02X %02X\n", data[0], data[1]);
+ 
+ 	return rc;
+ }
+@@ -454,9 +455,14 @@ static int alauda_init_media(struct us_data *us)
+ static int alauda_check_media(struct us_data *us)
+ {
+ 	struct alauda_info *info = (struct alauda_info *) us->extra;
+-	unsigned char status[2];
++	unsigned char *status = us->iobuf;
++	int rc;
+ 
+-	alauda_get_media_status(us, status);
++	rc = alauda_get_media_status(us, status);
++	if (rc != USB_STOR_XFER_GOOD) {
++		status[0] = 0xF0;	/* Pretend there's no media */
++		status[1] = 0;
++	}
+ 
+ 	/* Check for no media or door open */
+ 	if ((status[0] & 0x80) || ((status[0] & 0x1F) == 0x10)

commit 65dadb2beeb7360232b09ebc4585b54475dfee06
+Author: Alan Stern 
+Date:   Sat Jul 29 10:59:38 2023 -0400
+
+    USB: Gadget: core: Help prevent panic during UVC unconfigure
+    
+    Avichal Rakesh reported a kernel panic that occurred when the UVC
+    gadget driver was removed from a gadget's configuration.  The panic
+    involves a somewhat complicated interaction between the kernel driver
+    and a userspace component (as described in the Link tag below), but
+    the analysis did make one thing clear: The Gadget core should
+    accomodate gadget drivers calling usb_gadget_deactivate() as part of
+    their unbind procedure.
+    
+    Currently this doesn't work.  gadget_unbind_driver() calls
+    driver->unbind() while holding the udc->connect_lock mutex, and
+    usb_gadget_deactivate() attempts to acquire that mutex, which will
+    result in a deadlock.
+    
+    The simple fix is for gadget_unbind_driver() to release the mutex when
+    invoking the ->unbind() callback.  There is no particular reason for
+    it to be holding the mutex at that time, and the mutex isn't held
+    while the ->bind() callback is invoked.  So we'll drop the mutex
+    before performing the unbind callback and reacquire it afterward.
+    
+    We'll also add a couple of comments to usb_gadget_activate() and
+    usb_gadget_deactivate().  Because they run in process context they
+    must not be called from a gadget driver's ->disconnect() callback,
+    which (according to the kerneldoc for struct usb_gadget_driver in
+    include/linux/usb/gadget.h) may run in interrupt context.  This may
+    help prevent similar bugs from arising in the future.
+    
+    Reported-and-tested-by: Avichal Rakesh 
+    Signed-off-by: Alan Stern 
+    Fixes: 286d9975a838 ("usb: gadget: udc: core: Prevent soft_connect_store() race")
+    Link: https://lore.kernel.org/linux-usb/4d7aa3f4-22d9-9f5a-3d70-1bd7148ff4ba@google.com/
+    Cc: Badhri Jagan Sridharan 
+    Cc: 
+    Link: https://lore.kernel.org/r/48b2f1f1-0639-46bf-bbfc-98cb05a24914@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
+index cd58f2a4e7f3..7d49d8a0b00c 100644
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -822,6 +822,9 @@ EXPORT_SYMBOL_GPL(usb_gadget_disconnect);
+  * usb_gadget_activate() is called.  For example, user mode components may
+  * need to be activated before the system can talk to hosts.
+  *
++ * This routine may sleep; it must not be called in interrupt context
++ * (such as from within a gadget driver's disconnect() callback).
++ *
+  * Returns zero on success, else negative errno.
+  */
+ int usb_gadget_deactivate(struct usb_gadget *gadget)
+@@ -860,6 +863,8 @@ EXPORT_SYMBOL_GPL(usb_gadget_deactivate);
+  * This routine activates gadget which was previously deactivated with
+  * usb_gadget_deactivate() call. It calls usb_gadget_connect() if needed.
+  *
++ * This routine may sleep; it must not be called in interrupt context.
++ *
+  * Returns zero on success, else negative errno.
+  */
+ int usb_gadget_activate(struct usb_gadget *gadget)
+@@ -1638,7 +1643,11 @@ static void gadget_unbind_driver(struct device *dev)
+ 	usb_gadget_disable_async_callbacks(udc);
+ 	if (gadget->irq)
+ 		synchronize_irq(gadget->irq);
++	mutex_unlock(&udc->connect_lock);
++
+ 	udc->driver->unbind(gadget);
++
++	mutex_lock(&udc->connect_lock);
+ 	usb_gadget_udc_stop_locked(udc);
+ 	mutex_unlock(&udc->connect_lock);
+ 

commit 5e1627cb43ddf1b24b92eb26f8d958a3f5676ccb
+Author: Alan Stern 
+Date:   Wed Jul 12 10:15:10 2023 -0400
+
+    net: usbnet: Fix WARNING in usbnet_start_xmit/usb_submit_urb
+    
+    The syzbot fuzzer identified a problem in the usbnet driver:
+    
+    usb 1-1: BOGUS urb xfer, pipe 3 != type 1
+    WARNING: CPU: 0 PID: 754 at drivers/usb/core/urb.c:504 usb_submit_urb+0xed6/0x1880 drivers/usb/core/urb.c:504
+    Modules linked in:
+    CPU: 0 PID: 754 Comm: kworker/0:2 Not tainted 6.4.0-rc7-syzkaller-00014-g692b7dc87ca6 #0
+    Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 05/27/2023
+    Workqueue: mld mld_ifc_work
+    RIP: 0010:usb_submit_urb+0xed6/0x1880 drivers/usb/core/urb.c:504
+    Code: 7c 24 18 e8 2c b4 5b fb 48 8b 7c 24 18 e8 42 07 f0 fe 41 89 d8 44 89 e1 4c 89 ea 48 89 c6 48 c7 c7 a0 c9 fc 8a e8 5a 6f 23 fb <0f> 0b e9 58 f8 ff ff e8 fe b3 5b fb 48 81 c5 c0 05 00 00 e9 84 f7
+    RSP: 0018:ffffc9000463f568 EFLAGS: 00010086
+    RAX: 0000000000000000 RBX: 0000000000000001 RCX: 0000000000000000
+    RDX: ffff88801eb28000 RSI: ffffffff814c03b7 RDI: 0000000000000001
+    RBP: ffff8881443b7190 R08: 0000000000000001 R09: 0000000000000000
+    R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000000003
+    R13: ffff88802a77cb18 R14: 0000000000000003 R15: ffff888018262500
+    FS:  0000000000000000(0000) GS:ffff8880b9800000(0000) knlGS:0000000000000000
+    CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+    CR2: 0000556a99c15a18 CR3: 0000000028c71000 CR4: 0000000000350ef0
+    Call Trace:
+     
+     usbnet_start_xmit+0xfe5/0x2190 drivers/net/usb/usbnet.c:1453
+     __netdev_start_xmit include/linux/netdevice.h:4918 [inline]
+     netdev_start_xmit include/linux/netdevice.h:4932 [inline]
+     xmit_one net/core/dev.c:3578 [inline]
+     dev_hard_start_xmit+0x187/0x700 net/core/dev.c:3594
+    ...
+    
+    This bug is caused by the fact that usbnet trusts the bulk endpoint
+    addresses its probe routine receives in the driver_info structure, and
+    it does not check to see that these endpoints actually exist and have
+    the expected type and directions.
+    
+    The fix is simply to add such a check.
+    
+    Reported-and-tested-by: syzbot+63ee658b9a100ffadbe2@syzkaller.appspotmail.com
+    Closes: https://lore.kernel.org/linux-usb/000000000000a56e9105d0cec021@google.com/
+    Signed-off-by: Alan Stern 
+    CC: Oliver Neukum 
+    Link: https://lore.kernel.org/r/ea152b6d-44df-4f8a-95c6-4db51143dcc1@rowland.harvard.edu
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
+index 283ffddda821..2d14b0d78541 100644
+--- a/drivers/net/usb/usbnet.c
++++ b/drivers/net/usb/usbnet.c
+@@ -1775,6 +1775,10 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
+ 	} else if (!info->in || !info->out)
+ 		status = usbnet_get_endpoints (dev, udev);
+ 	else {
++		u8 ep_addrs[3] = {
++			info->in + USB_DIR_IN, info->out + USB_DIR_OUT, 0
++		};
++
+ 		dev->in = usb_rcvbulkpipe (xdev, info->in);
+ 		dev->out = usb_sndbulkpipe (xdev, info->out);
+ 		if (!(info->flags & FLAG_NO_SETINT))
+@@ -1784,6 +1788,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
+ 		else
+ 			status = 0;
+ 
++		if (status == 0 && !usb_check_bulk_endpoints(udev, ep_addrs))
++			status = -EINVAL;
+ 	}
+ 	if (status >= 0 && dev->status)
+ 		status = init_status (dev, udev);

commit ed9de4ed39875706607fb08118a58344ae6c5f42
+Author: Alan Stern 
+Date:   Fri May 19 15:32:30 2023 -0400
+
+    fbdev: udlfb: Fix endpoint check
+    
+    The syzbot fuzzer detected a problem in the udlfb driver, caused by an
+    endpoint not having the expected type:
+    
+    usb 1-1: Read EDID byte 0 failed: -71
+    usb 1-1: Unable to get valid EDID from device/display
+    ------------[ cut here ]------------
+    usb 1-1: BOGUS urb xfer, pipe 3 != type 1
+    WARNING: CPU: 0 PID: 9 at drivers/usb/core/urb.c:504 usb_submit_urb+0xed6/0x1880
+    drivers/usb/core/urb.c:504
+    Modules linked in:
+    CPU: 0 PID: 9 Comm: kworker/0:1 Not tainted
+    6.4.0-rc1-syzkaller-00016-ga4422ff22142 #0
+    Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google
+    04/28/2023
+    Workqueue: usb_hub_wq hub_event
+    RIP: 0010:usb_submit_urb+0xed6/0x1880 drivers/usb/core/urb.c:504
+    ...
+    Call Trace:
+     
+     dlfb_submit_urb+0x92/0x180 drivers/video/fbdev/udlfb.c:1980
+     dlfb_set_video_mode+0x21f0/0x2950 drivers/video/fbdev/udlfb.c:315
+     dlfb_ops_set_par+0x2a7/0x8d0 drivers/video/fbdev/udlfb.c:1111
+     dlfb_usb_probe+0x149a/0x2710 drivers/video/fbdev/udlfb.c:1743
+    
+    The current approach for this issue failed to catch the problem
+    because it only checks for the existence of a bulk-OUT endpoint; it
+    doesn't check whether this endpoint is the one that the driver will
+    actually use.
+    
+    We can fix the problem by instead checking that the endpoint used by
+    the driver does exist and is bulk-OUT.
+    
+    Reported-and-tested-by: syzbot+0e22d63dcebb802b9bc8@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    CC: Pavel Skripkin 
+    Fixes: aaf7dbe07385 ("video: fbdev: udlfb: properly check endpoint type")
+    Signed-off-by: Helge Deller 
+
+diff --git a/drivers/video/fbdev/udlfb.c b/drivers/video/fbdev/udlfb.c
+index 216d49c9d47e..256d9b61f4ea 100644
+--- a/drivers/video/fbdev/udlfb.c
++++ b/drivers/video/fbdev/udlfb.c
+@@ -27,6 +27,8 @@
+ #include 

commit 94d25e9128988c6a1fc9070f6e98215a95795bd8
+Author: Alan Stern 
+Date:   Mon May 1 14:22:35 2023 -0400
+
+    USB: usbtmc: Fix direction for 0-length ioctl control messages
+    
+    The syzbot fuzzer found a problem in the usbtmc driver: When a user
+    submits an ioctl for a 0-length control transfer, the driver does not
+    check that the direction is set to OUT:
+    
+    ------------[ cut here ]------------
+    usb 3-1: BOGUS control dir, pipe 80000b80 doesn't match bRequestType fd
+    WARNING: CPU: 0 PID: 5100 at drivers/usb/core/urb.c:411 usb_submit_urb+0x14a7/0x1880 drivers/usb/core/urb.c:411
+    Modules linked in:
+    CPU: 0 PID: 5100 Comm: syz-executor428 Not tainted 6.3.0-syzkaller-12049-g58390c8ce1bd #0
+    Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/14/2023
+    RIP: 0010:usb_submit_urb+0x14a7/0x1880 drivers/usb/core/urb.c:411
+    Code: 7c 24 40 e8 1b 13 5c fb 48 8b 7c 24 40 e8 21 1d f0 fe 45 89 e8 44 89 f1 4c 89 e2 48 89 c6 48 c7 c7 e0 b5 fc 8a e8 19 c8 23 fb <0f> 0b e9 9f ee ff ff e8 ed 12 5c fb 0f b6 1d 12 8a 3c 08 31 ff 41
+    RSP: 0018:ffffc90003d2fb00 EFLAGS: 00010282
+    RAX: 0000000000000000 RBX: ffff8880789e9058 RCX: 0000000000000000
+    RDX: ffff888029593b80 RSI: ffffffff814c1447 RDI: 0000000000000001
+    RBP: ffff88801ea742f8 R08: 0000000000000001 R09: 0000000000000000
+    R10: 0000000000000001 R11: 0000000000000001 R12: ffff88802915e528
+    R13: 00000000000000fd R14: 0000000080000b80 R15: ffff8880222b3100
+    FS:  0000555556ca63c0(0000) GS:ffff8880b9800000(0000) knlGS:0000000000000000
+    CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+    CR2: 00007f9ef4d18150 CR3: 0000000073e5b000 CR4: 00000000003506f0
+    DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+    DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+    Call Trace:
+     
+     usb_start_wait_urb+0x101/0x4b0 drivers/usb/core/message.c:58
+     usb_internal_control_msg drivers/usb/core/message.c:102 [inline]
+     usb_control_msg+0x320/0x4a0 drivers/usb/core/message.c:153
+     usbtmc_ioctl_request drivers/usb/class/usbtmc.c:1954 [inline]
+     usbtmc_ioctl+0x1b3d/0x2840 drivers/usb/class/usbtmc.c:2097
+    
+    To fix this, we must override the direction in the bRequestType field
+    of the control request structure when the length is 0.
+    
+    Reported-and-tested-by: syzbot+ce77725b89b7bd52425c@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/linux-usb/000000000000716a3705f9adb8ee@google.com/
+    CC: 
+    Link: https://lore.kernel.org/r/ede1ee02-b718-49e7-a44c-51339fec706b@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
+index 4bb6d304eb4b..311007b1d904 100644
+--- a/drivers/usb/class/usbtmc.c
++++ b/drivers/usb/class/usbtmc.c
+@@ -1928,6 +1928,8 @@ static int usbtmc_ioctl_request(struct usbtmc_device_data *data,
+ 
+ 	if (request.req.wLength > USBTMC_BUFSIZE)
+ 		return -EMSGSIZE;
++	if (request.req.wLength == 0)	/* Length-0 requests are never IN */
++		request.req.bRequestType &= ~USB_DIR_IN;
+ 
+ 	is_in = request.req.bRequestType & USB_DIR_IN;
+ 

commit 76e31045ba030e94e72105c01b2e98f543d175ac
+Author: Alan Stern 
+Date:   Mon Apr 10 15:40:05 2023 -0400
+
+    media: radio-shark: Add endpoint checks
+    
+    The syzbot fuzzer was able to provoke a WARNING from the radio-shark2
+    driver:
+    
+    ------------[ cut here ]------------
+    usb 1-1: BOGUS urb xfer, pipe 1 != type 3
+    WARNING: CPU: 0 PID: 3271 at drivers/usb/core/urb.c:504 usb_submit_urb+0xed2/0x1880 drivers/usb/core/urb.c:504
+    Modules linked in:
+    CPU: 0 PID: 3271 Comm: kworker/0:3 Not tainted 6.1.0-rc4-syzkaller #0
+    Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022
+    Workqueue: usb_hub_wq hub_event
+    RIP: 0010:usb_submit_urb+0xed2/0x1880 drivers/usb/core/urb.c:504
+    Code: 7c 24 18 e8 00 36 ea fb 48 8b 7c 24 18 e8 36 1c 02 ff 41 89 d8 44 89 e1 4c 89 ea 48 89 c6 48 c7 c7 a0 b6 90 8a e8 9a 29 b8 03 <0f> 0b e9 58 f8 ff ff e8 d2 35 ea fb 48 81 c5 c0 05 00 00 e9 84 f7
+    RSP: 0018:ffffc90003876dd0 EFLAGS: 00010282
+    RAX: 0000000000000000 RBX: 0000000000000003 RCX: 0000000000000000
+    RDX: ffff8880750b0040 RSI: ffffffff816152b8 RDI: fffff5200070edac
+    RBP: ffff8880172d81e0 R08: 0000000000000005 R09: 0000000000000000
+    R10: 0000000080000000 R11: 0000000000000000 R12: 0000000000000001
+    R13: ffff8880285c5040 R14: 0000000000000002 R15: ffff888017158200
+    FS:  0000000000000000(0000) GS:ffff8880b9a00000(0000) knlGS:0000000000000000
+    CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+    CR2: 00007ffe03235b90 CR3: 000000000bc8e000 CR4: 00000000003506f0
+    DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+    DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+    Call Trace:
+     
+     usb_start_wait_urb+0x101/0x4b0 drivers/usb/core/message.c:58
+     usb_bulk_msg+0x226/0x550 drivers/usb/core/message.c:387
+     shark_write_reg+0x1ff/0x2e0 drivers/media/radio/radio-shark2.c:88
+    ...
+    
+    The problem was caused by the fact that the driver does not check
+    whether the endpoints it uses are actually present and have the
+    appropriate types.  This can be fixed by adding a simple check of
+    these endpoints (and similarly for the radio-shark driver).
+    
+    Link: https://syzkaller.appspot.com/bug?extid=4b3f8190f6e13b3efd74
+    Reported-and-tested-by: syzbot+4b3f8190f6e13b3efd74@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/e2858ab4-4adf-46e5-bbf6-c56742034547@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/media/radio/radio-shark.c b/drivers/media/radio/radio-shark.c
+index 8230da828d0e..127a3be0e0f0 100644
+--- a/drivers/media/radio/radio-shark.c
++++ b/drivers/media/radio/radio-shark.c
+@@ -316,6 +316,16 @@ static int usb_shark_probe(struct usb_interface *intf,
+ {
+ 	struct shark_device *shark;
+ 	int retval = -ENOMEM;
++	static const u8 ep_addresses[] = {
++		SHARK_IN_EP | USB_DIR_IN,
++		SHARK_OUT_EP | USB_DIR_OUT,
++		0};
++
++	/* Are the expected endpoints present? */
++	if (!usb_check_int_endpoints(intf, ep_addresses)) {
++		dev_err(&intf->dev, "Invalid radioSHARK device\n");
++		return -EINVAL;
++	}
+ 
+ 	shark = kzalloc(sizeof(struct shark_device), GFP_KERNEL);
+ 	if (!shark)
+diff --git a/drivers/media/radio/radio-shark2.c b/drivers/media/radio/radio-shark2.c
+index d150f12382c6..f1c5c0a6a335 100644
+--- a/drivers/media/radio/radio-shark2.c
++++ b/drivers/media/radio/radio-shark2.c
+@@ -282,6 +282,16 @@ static int usb_shark_probe(struct usb_interface *intf,
+ {
+ 	struct shark_device *shark;
+ 	int retval = -ENOMEM;
++	static const u8 ep_addresses[] = {
++		SHARK_IN_EP | USB_DIR_IN,
++		SHARK_OUT_EP | USB_DIR_OUT,
++		0};
++
++	/* Are the expected endpoints present? */
++	if (!usb_check_int_endpoints(intf, ep_addresses)) {
++		dev_err(&intf->dev, "Invalid radioSHARK2 device\n");
++		return -EINVAL;
++	}
+ 
+ 	shark = kzalloc(sizeof(struct shark_device), GFP_KERNEL);
+ 	if (!shark)

commit df05a9b05e466a46725564528b277d0c570d0104
+Author: Alan Stern 
+Date:   Mon Apr 10 15:38:22 2023 -0400
+
+    USB: sisusbvga: Add endpoint checks
+    
+    The syzbot fuzzer was able to provoke a WARNING from the sisusbvga driver:
+    
+    ------------[ cut here ]------------
+    usb 1-1: BOGUS urb xfer, pipe 3 != type 1
+    WARNING: CPU: 1 PID: 26 at drivers/usb/core/urb.c:504 usb_submit_urb+0xed6/0x1880 drivers/usb/core/urb.c:504
+    Modules linked in:
+    CPU: 1 PID: 26 Comm: kworker/1:1 Not tainted 6.2.0-rc5-syzkaller-00199-g5af6ce704936 #0
+    Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/12/2023
+    Workqueue: usb_hub_wq hub_event
+    RIP: 0010:usb_submit_urb+0xed6/0x1880 drivers/usb/core/urb.c:504
+    Code: 7c 24 18 e8 6c 50 80 fb 48 8b 7c 24 18 e8 62 1a 01 ff 41 89 d8 44 89 e1 4c 89 ea 48 89 c6 48 c7 c7 60 b1 fa 8a e8 84 b0 be 03 <0f> 0b e9 58 f8 ff ff e8 3e 50 80 fb 48 81 c5 c0 05 00 00 e9 84 f7
+    RSP: 0018:ffffc90000a1ed18 EFLAGS: 00010282
+    RAX: 0000000000000000 RBX: 0000000000000001 RCX: 0000000000000000
+    RDX: ffff888012783a80 RSI: ffffffff816680ec RDI: fffff52000143d95
+    RBP: ffff888079020000 R08: 0000000000000005 R09: 0000000000000000
+    R10: 0000000080000000 R11: 0000000000000000 R12: 0000000000000003
+    R13: ffff888017d33370 R14: 0000000000000003 R15: ffff888021213600
+    FS:  0000000000000000(0000) GS:ffff8880b9900000(0000) knlGS:0000000000000000
+    CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+    CR2: 00005592753a60b0 CR3: 0000000022899000 CR4: 00000000003506e0
+    DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+    DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+    Call Trace:
+     
+     sisusb_bulkout_msg drivers/usb/misc/sisusbvga/sisusbvga.c:224 [inline]
+     sisusb_send_bulk_msg.constprop.0+0x904/0x1230 drivers/usb/misc/sisusbvga/sisusbvga.c:379
+     sisusb_send_bridge_packet drivers/usb/misc/sisusbvga/sisusbvga.c:567 [inline]
+     sisusb_do_init_gfxdevice drivers/usb/misc/sisusbvga/sisusbvga.c:2077 [inline]
+     sisusb_init_gfxdevice+0x87b/0x4000 drivers/usb/misc/sisusbvga/sisusbvga.c:2177
+     sisusb_probe+0x9cd/0xbe2 drivers/usb/misc/sisusbvga/sisusbvga.c:2869
+    ...
+    
+    The problem was caused by the fact that the driver does not check
+    whether the endpoints it uses are actually present and have the
+    appropriate types.  This can be fixed by adding a simple check of
+    the endpoints.
+    
+    Link: https://syzkaller.appspot.com/bug?extid=23be03b56c5259385d79
+    Reported-and-tested-by: syzbot+23be03b56c5259385d79@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/48ef98f7-51ae-4f63-b8d3-0ef2004bb60a@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/misc/sisusbvga/sisusbvga.c b/drivers/usb/misc/sisusbvga/sisusbvga.c
+index 654a79fd3231..febf34f9f049 100644
+--- a/drivers/usb/misc/sisusbvga/sisusbvga.c
++++ b/drivers/usb/misc/sisusbvga/sisusbvga.c
+@@ -2778,6 +2778,20 @@ static int sisusb_probe(struct usb_interface *intf,
+ 	struct usb_device *dev = interface_to_usbdev(intf);
+ 	struct sisusb_usb_data *sisusb;
+ 	int retval = 0, i;
++	static const u8 ep_addresses[] = {
++		SISUSB_EP_GFX_IN | USB_DIR_IN,
++		SISUSB_EP_GFX_OUT | USB_DIR_OUT,
++		SISUSB_EP_GFX_BULK_OUT | USB_DIR_OUT,
++		SISUSB_EP_GFX_LBULK_OUT | USB_DIR_OUT,
++		SISUSB_EP_BRIDGE_IN | USB_DIR_IN,
++		SISUSB_EP_BRIDGE_OUT | USB_DIR_OUT,
++		0};
++
++	/* Are the expected endpoints present? */
++	if (!usb_check_bulk_endpoints(intf, ep_addresses)) {
++		dev_err(&intf->dev, "Invalid USB2VGA device\n");
++		return -EINVAL;
++	}
+ 
+ 	dev_info(&dev->dev, "USB2VGA dongle found at address %d\n",
+ 			dev->devnum);

commit 13890626501ffda22b18213ddaf7930473da5792
+Author: Alan Stern 
+Date:   Mon Apr 10 15:37:07 2023 -0400
+
+    USB: core: Add routines for endpoint checks in old drivers
+    
+    Many of the older USB drivers in the Linux USB stack were written
+    based simply on a vendor's device specification.  They use the
+    endpoint information in the spec and assume these endpoints will
+    always be present, with the properties listed, in any device matching
+    the given vendor and product IDs.
+    
+    While that may have been true back then, with spoofing and fuzzing it
+    is not true any more.  More and more we are finding that those old
+    drivers need to perform at least a minimum of checking before they try
+    to use any endpoint other than ep0.
+    
+    To make this checking as simple as possible, we now add a couple of
+    utility routines to the USB core.  usb_check_bulk_endpoints() and
+    usb_check_int_endpoints() take an interface pointer together with a
+    list of endpoint addresses (numbers and directions).  They check that
+    the interface's current alternate setting includes endpoints with
+    those addresses and that each of these endpoints has the right type:
+    bulk or interrupt, respectively.
+    
+    Although we already have usb_find_common_endpoints() and related
+    routines meant for a similar purpose, they are not well suited for
+    this kind of checking.  Those routines find endpoints of various
+    kinds, but only one (either the first or the last) of each kind, and
+    they don't verify that the endpoints' addresses agree with what the
+    caller expects.
+    
+    In theory the new routines could be more general: They could take a
+    particular altsetting as their argument instead of always using the
+    interface's current altsetting.  In practice I think this won't matter
+    too much; multiple altsettings tend to be used for transferring media
+    (audio or visual) over isochronous endpoints, not bulk or interrupt.
+    Drivers for such devices will generally require more sophisticated
+    checking than these simplistic routines provide.
+    
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/dd2c8e8c-2c87-44ea-ba17-c64b97e201c9@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 34742fbbd84d..901ec732321c 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -206,6 +206,82 @@ int usb_find_common_endpoints_reverse(struct usb_host_interface *alt,
+ }
+ EXPORT_SYMBOL_GPL(usb_find_common_endpoints_reverse);
+ 
++/**
++ * usb_find_endpoint() - Given an endpoint address, search for the endpoint's
++ * usb_host_endpoint structure in an interface's current altsetting.
++ * @intf: the interface whose current altsetting should be searched
++ * @ep_addr: the endpoint address (number and direction) to find
++ *
++ * Search the altsetting's list of endpoints for one with the specified address.
++ *
++ * Return: Pointer to the usb_host_endpoint if found, %NULL otherwise.
++ */
++static const struct usb_host_endpoint *usb_find_endpoint(
++		const struct usb_interface *intf, unsigned int ep_addr)
++{
++	int n;
++	const struct usb_host_endpoint *ep;
++
++	n = intf->cur_altsetting->desc.bNumEndpoints;
++	ep = intf->cur_altsetting->endpoint;
++	for (; n > 0; (--n, ++ep)) {
++		if (ep->desc.bEndpointAddress == ep_addr)
++			return ep;
++	}
++	return NULL;
++}
++
++/**
++ * usb_check_bulk_endpoints - Check whether an interface's current altsetting
++ * contains a set of bulk endpoints with the given addresses.
++ * @intf: the interface whose current altsetting should be searched
++ * @ep_addrs: 0-terminated array of the endpoint addresses (number and
++ * direction) to look for
++ *
++ * Search for endpoints with the specified addresses and check their types.
++ *
++ * Return: %true if all the endpoints are found and are bulk, %false otherwise.
++ */
++bool usb_check_bulk_endpoints(
++		const struct usb_interface *intf, const u8 *ep_addrs)
++{
++	const struct usb_host_endpoint *ep;
++
++	for (; *ep_addrs; ++ep_addrs) {
++		ep = usb_find_endpoint(intf, *ep_addrs);
++		if (!ep || !usb_endpoint_xfer_bulk(&ep->desc))
++			return false;
++	}
++	return true;
++}
++EXPORT_SYMBOL_GPL(usb_check_bulk_endpoints);
++
++/**
++ * usb_check_int_endpoints - Check whether an interface's current altsetting
++ * contains a set of interrupt endpoints with the given addresses.
++ * @intf: the interface whose current altsetting should be searched
++ * @ep_addrs: 0-terminated array of the endpoint addresses (number and
++ * direction) to look for
++ *
++ * Search for endpoints with the specified addresses and check their types.
++ *
++ * Return: %true if all the endpoints are found and are interrupt,
++ * %false otherwise.
++ */
++bool usb_check_int_endpoints(
++		const struct usb_interface *intf, const u8 *ep_addrs)
++{
++	const struct usb_host_endpoint *ep;
++
++	for (; *ep_addrs; ++ep_addrs) {
++		ep = usb_find_endpoint(intf, *ep_addrs);
++		if (!ep || !usb_endpoint_xfer_int(&ep->desc))
++			return false;
++	}
++	return true;
++}
++EXPORT_SYMBOL_GPL(usb_check_int_endpoints);
++
+ /**
+  * usb_find_alt_setting() - Given a configuration, find the alternate setting
+  * for the given interface.
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index d510fabcafa2..4ae0466c846c 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -291,6 +291,11 @@ void usb_put_intf(struct usb_interface *intf);
+ #define USB_MAXINTERFACES	32
+ #define USB_MAXIADS		(USB_MAXINTERFACES/2)
+ 
++bool usb_check_bulk_endpoints(
++		const struct usb_interface *intf, const u8 *ep_addrs);
++bool usb_check_int_endpoints(
++		const struct usb_interface *intf, const u8 *ep_addrs);
++
+ /*
+  * USB Resume Timer: Every Host controller driver should drive the resume
+  * signalling on the bus for the amount of time defined by this macro.

commit de0418053215482cc61843244fc7c1385ddf63a7
+Author: Alan Stern 
+Date:   Fri Feb 24 10:30:48 2023 -0500
+
+    tools/memory-model: Add documentation about SRCU read-side critical sections
+    
+    Expand the discussion of SRCU and its read-side critical sections in
+    the Linux Kernel Memory Model documentation file explanation.txt.  The
+    new material discusses recent changes to the memory model made in
+    commit 6cd244c87428 ("tools/memory-model: Provide exact SRCU
+    semantics").
+    
+    Signed-off-by: Alan Stern 
+    Co-developed-by: Joel Fernandes (Google) 
+    Signed-off-by: Joel Fernandes (Google) 
+    Reviewed-by: Akira Yokosawa 
+    Cc: Andrea Parri 
+    Cc: Boqun Feng 
+    Cc: Jade Alglave 
+    Cc: Jonas Oberhauser 
+    Cc: Luc Maranget 
+    Cc: "Paul E. McKenney" 
+    Cc: Peter Zijlstra 
+    CC: Will Deacon 
+    Signed-off-by: Paul E. McKenney 
+
+diff --git a/tools/memory-model/Documentation/explanation.txt b/tools/memory-model/Documentation/explanation.txt
+index 8e7085238470..6dc8b3642458 100644
+--- a/tools/memory-model/Documentation/explanation.txt
++++ b/tools/memory-model/Documentation/explanation.txt
+@@ -28,9 +28,10 @@ Explanation of the Linux-Kernel Memory Consistency Model
+   20. THE HAPPENS-BEFORE RELATION: hb
+   21. THE PROPAGATES-BEFORE RELATION: pb
+   22. RCU RELATIONS: rcu-link, rcu-gp, rcu-rscsi, rcu-order, rcu-fence, and rb
+-  23. LOCKING
+-  24. PLAIN ACCESSES AND DATA RACES
+-  25. ODDS AND ENDS
++  23. SRCU READ-SIDE CRITICAL SECTIONS
++  24. LOCKING
++  25. PLAIN ACCESSES AND DATA RACES
++  26. ODDS AND ENDS
+ 
+ 
+ 
+@@ -1848,14 +1849,169 @@ section in P0 both starts before P1's grace period does and ends
+ before it does, and the critical section in P2 both starts after P1's
+ grace period does and ends after it does.
+ 
+-Addendum: The LKMM now supports SRCU (Sleepable Read-Copy-Update) in
+-addition to normal RCU.  The ideas involved are much the same as
+-above, with new relations srcu-gp and srcu-rscsi added to represent
+-SRCU grace periods and read-side critical sections.  There is a
+-restriction on the srcu-gp and srcu-rscsi links that can appear in an
+-rcu-order sequence (the srcu-rscsi links must be paired with srcu-gp
+-links having the same SRCU domain with proper nesting); the details
+-are relatively unimportant.
++The LKMM supports SRCU (Sleepable Read-Copy-Update) in addition to
++normal RCU.  The ideas involved are much the same as above, with new
++relations srcu-gp and srcu-rscsi added to represent SRCU grace periods
++and read-side critical sections.  However, there are some significant
++differences between RCU read-side critical sections and their SRCU
++counterparts, as described in the next section.
++
++
++SRCU READ-SIDE CRITICAL SECTIONS
++--------------------------------
++
++The LKMM uses the srcu-rscsi relation to model SRCU read-side critical
++sections.  They differ from RCU read-side critical sections in the
++following respects:
++
++1.	Unlike the analogous RCU primitives, synchronize_srcu(),
++	srcu_read_lock(), and srcu_read_unlock() take a pointer to a
++	struct srcu_struct as an argument.  This structure is called
++	an SRCU domain, and calls linked by srcu-rscsi must have the
++	same domain.  Read-side critical sections and grace periods
++	associated with different domains are independent of one
++	another; the SRCU version of the RCU Guarantee applies only
++	to pairs of critical sections and grace periods having the
++	same domain.
++
++2.	srcu_read_lock() returns a value, called the index, which must
++	be passed to the matching srcu_read_unlock() call.  Unlike
++	rcu_read_lock() and rcu_read_unlock(), an srcu_read_lock()
++	call does not always have to match the next unpaired
++	srcu_read_unlock().  In fact, it is possible for two SRCU
++	read-side critical sections to overlap partially, as in the
++	following example (where s is an srcu_struct and idx1 and idx2
++	are integer variables):
++
++		idx1 = srcu_read_lock(&s);	// Start of first RSCS
++		idx2 = srcu_read_lock(&s);	// Start of second RSCS
++		srcu_read_unlock(&s, idx1);	// End of first RSCS
++		srcu_read_unlock(&s, idx2);	// End of second RSCS
++
++	The matching is determined entirely by the domain pointer and
++	index value.  By contrast, if the calls had been
++	rcu_read_lock() and rcu_read_unlock() then they would have
++	created two nested (fully overlapping) read-side critical
++	sections: an inner one and an outer one.
++
++3.	The srcu_down_read() and srcu_up_read() primitives work
++	exactly like srcu_read_lock() and srcu_read_unlock(), except
++	that matching calls don't have to execute on the same CPU.
++	(The names are meant to be suggestive of operations on
++	semaphores.)  Since the matching is determined by the domain
++	pointer and index value, these primitives make it possible for
++	an SRCU read-side critical section to start on one CPU and end
++	on another, so to speak.
++
++In order to account for these properties of SRCU, the LKMM models
++srcu_read_lock() as a special type of load event (which is
++appropriate, since it takes a memory location as argument and returns
++a value, just as a load does) and srcu_read_unlock() as a special type
++of store event (again appropriate, since it takes as arguments a
++memory location and a value).  These loads and stores are annotated as
++belonging to the "srcu-lock" and "srcu-unlock" event classes
++respectively.
++
++This approach allows the LKMM to tell whether two events are
++associated with the same SRCU domain, simply by checking whether they
++access the same memory location (i.e., they are linked by the loc
++relation).  It also gives a way to tell which unlock matches a
++particular lock, by checking for the presence of a data dependency
++from the load (srcu-lock) to the store (srcu-unlock).  For example,
++given the situation outlined earlier (with statement labels added):
++
++	A: idx1 = srcu_read_lock(&s);
++	B: idx2 = srcu_read_lock(&s);
++	C: srcu_read_unlock(&s, idx1);
++	D: srcu_read_unlock(&s, idx2);
++
++the LKMM will treat A and B as loads from s yielding values saved in
++idx1 and idx2 respectively.  Similarly, it will treat C and D as
++though they stored the values from idx1 and idx2 in s.  The end result
++is much as if we had written:
++
++	A: idx1 = READ_ONCE(s);
++	B: idx2 = READ_ONCE(s);
++	C: WRITE_ONCE(s, idx1);
++	D: WRITE_ONCE(s, idx2);
++
++except for the presence of the special srcu-lock and srcu-unlock
++annotations.  You can see at once that we have A ->data C and
++B ->data D.  These dependencies tell the LKMM that C is the
++srcu-unlock event matching srcu-lock event A, and D is the
++srcu-unlock event matching srcu-lock event B.
++
++This approach is admittedly a hack, and it has the potential to lead
++to problems.  For example, in:
++
++	idx1 = srcu_read_lock(&s);
++	srcu_read_unlock(&s, idx1);
++	idx2 = srcu_read_lock(&s);
++	srcu_read_unlock(&s, idx2);
++
++the LKMM will believe that idx2 must have the same value as idx1,
++since it reads from the immediately preceding store of idx1 in s.
++Fortunately this won't matter, assuming that litmus tests never do
++anything with SRCU index values other than pass them to
++srcu_read_unlock() or srcu_up_read() calls.
++
++However, sometimes it is necessary to store an index value in a
++shared variable temporarily.  In fact, this is the only way for
++srcu_down_read() to pass the index it gets to an srcu_up_read() call
++on a different CPU.  In more detail, we might have soething like:
++
++	struct srcu_struct s;
++	int x;
++
++	P0()
++	{
++		int r0;
++
++		A: r0 = srcu_down_read(&s);
++		B: WRITE_ONCE(x, r0);
++	}
++
++	P1()
++	{
++		int r1;
++
++		C: r1 = READ_ONCE(x);
++		D: srcu_up_read(&s, r1);
++	}
++
++Assuming that P1 executes after P0 and does read the index value
++stored in x, we can write this (using brackets to represent event
++annotations) as:
++
++	A[srcu-lock] ->data B[once] ->rf C[once] ->data D[srcu-unlock].
++
++The LKMM defines a carry-srcu-data relation to express this pattern;
++it permits an arbitrarily long sequence of
++
++	data ; rf
++
++pairs (that is, a data link followed by an rf link) to occur between
++an srcu-lock event and the final data dependency leading to the
++matching srcu-unlock event.  carry-srcu-data is complicated by the
++need to ensure that none of the intermediate store events in this
++sequence are instances of srcu-unlock.  This is necessary because in a
++pattern like the one above:
++
++	A: idx1 = srcu_read_lock(&s);
++	B: srcu_read_unlock(&s, idx1);
++	C: idx2 = srcu_read_lock(&s);
++	D: srcu_read_unlock(&s, idx2);
++
++the LKMM treats B as a store to the variable s and C as a load from
++that variable, creating an undesirable rf link from B to C:
++
++	A ->data B ->rf C ->data D.
++
++This would cause carry-srcu-data to mistakenly extend a data
++dependency from A to D, giving the impression that D was the
++srcu-unlock event matching A's srcu-lock.  To avoid such problems,
++carry-srcu-data does not accept sequences in which the ends of any of
++the intermediate ->data links (B above) is an srcu-unlock event.
+ 
+ 
+ LOCKING

commit 614e40faf5ae30113f94b00106ce690602f10fc2
+Author: Alan Stern 
+Date:   Wed Jan 25 15:21:42 2023 -0500
+
+    tools/memory-model: Provide exact SRCU semantics
+    
+    LKMM has long provided only approximate handling of SRCU read-side
+    critical sections.  This has not been a pressing problem because LKMM's
+    traditional handling is correct for the common cases of non-overlapping
+    and properly nested critical sections.  However, LKMM's traditional
+    handling of partially overlapping critical sections incorrectly fuses
+    them into one large critical section.
+    
+    For example, consider the following litmus test:
+    
+    ------------------------------------------------------------------------
+    
+    C C-srcu-nest-5
+    
+    (*
+     * Result: Sometimes
+     *
+     * This demonstrates non-nested overlapping of SRCU read-side critical
+     * sections.  Unlike RCU, SRCU critical sections do not unconditionally
+     * nest.
+     *)
+    
+    {}
+    
+    P0(int *x, int *y, struct srcu_struct *s1)
+    {
+            int r1;
+            int r2;
+            int r3;
+            int r4;
+    
+            r3 = srcu_read_lock(s1);
+            r2 = READ_ONCE(*y);
+            r4 = srcu_read_lock(s1);
+            srcu_read_unlock(s1, r3);
+            r1 = READ_ONCE(*x);
+            srcu_read_unlock(s1, r4);
+    }
+    
+    P1(int *x, int *y, struct srcu_struct *s1)
+    {
+            WRITE_ONCE(*y, 1);
+            synchronize_srcu(s1);
+            WRITE_ONCE(*x, 1);
+    }
+    
+    locations [0:r1]
+    exists (0:r1=1 /\ 0:r2=0)
+    
+    ------------------------------------------------------------------------
+    
+    Current mainline incorrectly flattens the two critical sections into
+    one larger critical section, giving "Never" instead of the correct
+    "Sometimes":
+    
+    ------------------------------------------------------------------------
+    
+    $ herd7 -conf linux-kernel.cfg C-srcu-nest-5.litmus
+    Test C-srcu-nest-5 Allowed
+    States 3
+    0:r1=0; 0:r2=0;
+    0:r1=0; 0:r2=1;
+    0:r1=1; 0:r2=1;
+    No
+    Witnesses
+    Positive: 0 Negative: 3
+    Flag srcu-bad-nesting
+    Condition exists (0:r1=1 /\ 0:r2=0)
+    Observation C-srcu-nest-5 Never 0 3
+    Time C-srcu-nest-5 0.01
+    Hash=e692c106cf3e84e20f12991dc438ff1b
+    
+    ------------------------------------------------------------------------
+    
+    To its credit, it does complain about bad nesting.  But with this
+    commit we get the following result, which has the virtue of being
+    correct:
+    
+    ------------------------------------------------------------------------
+    
+    $ herd7 -conf linux-kernel.cfg C-srcu-nest-5.litmus
+    Test C-srcu-nest-5 Allowed
+    States 4
+    0:r1=0; 0:r2=0;
+    0:r1=0; 0:r2=1;
+    0:r1=1; 0:r2=0;
+    0:r1=1; 0:r2=1;
+    Ok
+    Witnesses
+    Positive: 1 Negative: 3
+    Condition exists (0:r1=1 /\ 0:r2=0)
+    Observation C-srcu-nest-5 Sometimes 1 3
+    Time C-srcu-nest-5 0.05
+    Hash=e692c106cf3e84e20f12991dc438ff1b
+    
+    ------------------------------------------------------------------------
+    
+    In addition, there are new srcu_down_read() and srcu_up_read()
+    functions on their way to mainline.  Roughly speaking, these are to
+    srcu_read_lock() and srcu_read_unlock() as down() and up() are to
+    mutex_lock() and mutex_unlock().  The key point is that
+    srcu_down_read() can execute in one process and the matching
+    srcu_up_read() in another, as shown in this litmus test:
+    
+    ------------------------------------------------------------------------
+    
+    C C-srcu-nest-6
+    
+    (*
+     * Result: Never
+     *
+     * This would be valid for srcu_down_read() and srcu_up_read().
+     *)
+    
+    {}
+    
+    P0(int *x, int *y, struct srcu_struct *s1, int *idx, int *f)
+    {
+            int r2;
+            int r3;
+    
+            r3 = srcu_down_read(s1);
+            WRITE_ONCE(*idx, r3);
+            r2 = READ_ONCE(*y);
+            smp_store_release(f, 1);
+    }
+    
+    P1(int *x, int *y, struct srcu_struct *s1, int *idx, int *f)
+    {
+            int r1;
+            int r3;
+            int r4;
+    
+            r4 = smp_load_acquire(f);
+            r1 = READ_ONCE(*x);
+            r3 = READ_ONCE(*idx);
+            srcu_up_read(s1, r3);
+    }
+    
+    P2(int *x, int *y, struct srcu_struct *s1)
+    {
+            WRITE_ONCE(*y, 1);
+            synchronize_srcu(s1);
+            WRITE_ONCE(*x, 1);
+    }
+    
+    locations [0:r1]
+    filter (1:r4=1)
+    exists (1:r1=1 /\ 0:r2=0)
+    
+    ------------------------------------------------------------------------
+    
+    When run on current mainline, this litmus test gets a complaint about
+    an unknown macro srcu_down_read().  With this commit:
+    
+    ------------------------------------------------------------------------
+    
+    herd7 -conf linux-kernel.cfg C-srcu-nest-6.litmus
+    Test C-srcu-nest-6 Allowed
+    States 3
+    0:r1=0; 0:r2=0; 1:r1=0;
+    0:r1=0; 0:r2=1; 1:r1=0;
+    0:r1=0; 0:r2=1; 1:r1=1;
+    No
+    Witnesses
+    Positive: 0 Negative: 3
+    Condition exists (1:r1=1 /\ 0:r2=0)
+    Observation C-srcu-nest-6 Never 0 3
+    Time C-srcu-nest-6 0.02
+    Hash=c1f20257d052ca5e899be508bedcb2a1
+    
+    ------------------------------------------------------------------------
+    
+    Note that the user must supply the flag "f" and the "filter" clause,
+    similar to what must be done to emulate call_rcu().
+    
+    The commit works by treating srcu_read_lock()/srcu_down_read() as
+    loads and srcu_read_unlock()/srcu_up_read() as stores.  This allows us
+    to determine which unlock matches which lock by looking for a data
+    dependency between them.  In order for this to work properly, the data
+    dependencies have to be tracked through stores to intermediate
+    variables such as "idx" in the litmus test above; this is handled by
+    the new carry-srcu-data relation.  But it's important here (and in the
+    existing carry-dep relation) to avoid tracking the dependencies
+    through SRCU unlock stores.  Otherwise, in situations resembling:
+    
+            A: r1 = srcu_read_lock(s);
+            B: srcu_read_unlock(s, r1);
+            C: r2 = srcu_read_lock(s);
+            D: srcu_read_unlock(s, r2);
+    
+    it would look as if D was dependent on both A and C, because "s" would
+    appear to be an intermediate variable written by B and read by C.
+    This explains the complications in the definitions of carry-srcu-dep
+    and carry-dep.
+    
+    As a debugging aid, the commit adds a check for errors in which the
+    value returned by one call to srcu_read_lock()/srcu_down_read() is
+    passed to more than one instance of srcu_read_unlock()/srcu_up_read().
+    
+    Finally, since these SRCU-related primitives are now treated as
+    ordinary reads and writes, we have to add them into the lists of
+    marked accesses (i.e., not subject to data races) and lock-related
+    accesses (i.e., one shouldn't try to access an srcu_struct with a
+    non-lock-related primitive such as READ_ONCE() or a plain write).
+    
+    Portions of this approach were suggested by Boqun Feng and Jonas
+    Oberhauser.
+    
+    [ paulmck: Fix space-before-tab whitespace nit. ]
+    
+    Reported-by: Paul E. McKenney 
+    Signed-off-by: Alan Stern 
+    Reviewed-by: Jonas Oberhauser 
+    Signed-off-by: Paul E. McKenney 
+
+diff --git a/tools/memory-model/linux-kernel.bell b/tools/memory-model/linux-kernel.bell
+index b92fdf7f6eeb..ce068700939c 100644
+--- a/tools/memory-model/linux-kernel.bell
++++ b/tools/memory-model/linux-kernel.bell
+@@ -58,20 +58,13 @@ flag ~empty Rcu-lock \ domain(rcu-rscs) as unmatched-rcu-lock
+ flag ~empty Rcu-unlock \ range(rcu-rscs) as unmatched-rcu-unlock
+ 
+ (* Compute matching pairs of nested Srcu-lock and Srcu-unlock *)
+-let srcu-rscs = let rec
+-	    unmatched-locks = Srcu-lock \ domain(matched)
+-	and unmatched-unlocks = Srcu-unlock \ range(matched)
+-	and unmatched = unmatched-locks | unmatched-unlocks
+-	and unmatched-po = ([unmatched] ; po ; [unmatched]) & loc
+-	and unmatched-locks-to-unlocks =
+-		([unmatched-locks] ; po ; [unmatched-unlocks]) & loc
+-	and matched = matched | (unmatched-locks-to-unlocks \
+-		(unmatched-po ; unmatched-po))
+-	in matched
++let carry-srcu-data = (data ; [~ Srcu-unlock] ; rf)*
++let srcu-rscs = ([Srcu-lock] ; carry-srcu-data ; data ; [Srcu-unlock]) & loc
+ 
+ (* Validate nesting *)
+ flag ~empty Srcu-lock \ domain(srcu-rscs) as unmatched-srcu-lock
+ flag ~empty Srcu-unlock \ range(srcu-rscs) as unmatched-srcu-unlock
++flag ~empty (srcu-rscs^-1 ; srcu-rscs) \ id as multiple-srcu-matches
+ 
+ (* Check for use of synchronize_srcu() inside an RCU critical section *)
+ flag ~empty rcu-rscs & (po ; [Sync-srcu] ; po) as invalid-sleep
+@@ -81,11 +74,11 @@ flag ~empty different-values(srcu-rscs) as srcu-bad-value-match
+ 
+ (* Compute marked and plain memory accesses *)
+ let Marked = (~M) | IW | Once | Release | Acquire | domain(rmw) | range(rmw) |
+-		LKR | LKW | UL | LF | RL | RU
++		LKR | LKW | UL | LF | RL | RU | Srcu-lock | Srcu-unlock
+ let Plain = M \ Marked
+ 
+ (* Redefine dependencies to include those carried through plain accesses *)
+-let carry-dep = (data ; rfi)*
++let carry-dep = (data ; [~ Srcu-unlock] ; rfi)*
+ let addr = carry-dep ; addr
+ let ctrl = carry-dep ; ctrl
+ let data = carry-dep ; data
+diff --git a/tools/memory-model/linux-kernel.def b/tools/memory-model/linux-kernel.def
+index a6b6fbc9d0b2..88a39601f525 100644
+--- a/tools/memory-model/linux-kernel.def
++++ b/tools/memory-model/linux-kernel.def
+@@ -50,8 +50,10 @@ synchronize_rcu() { __fence{sync-rcu}; }
+ synchronize_rcu_expedited() { __fence{sync-rcu}; }
+ 
+ // SRCU
+-srcu_read_lock(X)  __srcu{srcu-lock}(X)
+-srcu_read_unlock(X,Y) { __srcu{srcu-unlock}(X,Y); }
++srcu_read_lock(X) __load{srcu-lock}(*X)
++srcu_read_unlock(X,Y) { __store{srcu-unlock}(*X,Y); }
++srcu_down_read(X) __load{srcu-lock}(*X)
++srcu_up_read(X,Y) { __store{srcu-unlock}(*X,Y); }
+ synchronize_srcu(X)  { __srcu{sync-srcu}(X); }
+ synchronize_srcu_expedited(X)  { __srcu{sync-srcu}(X); }
+ 
+diff --git a/tools/memory-model/lock.cat b/tools/memory-model/lock.cat
+index 6b52f365d73a..53b5a492739d 100644
+--- a/tools/memory-model/lock.cat
++++ b/tools/memory-model/lock.cat
+@@ -36,9 +36,9 @@ let RU = try RU with emptyset
+ (* Treat RL as a kind of LF: a read with no ordering properties *)
+ let LF = LF | RL
+ 
+-(* There should be no ordinary R or W accesses to spinlocks *)
+-let ALL-LOCKS = LKR | LKW | UL | LF | RU
+-flag ~empty [M \ IW] ; loc ; [ALL-LOCKS] as mixed-lock-accesses
++(* There should be no ordinary R or W accesses to spinlocks or SRCU structs *)
++let ALL-LOCKS = LKR | LKW | UL | LF | RU | Srcu-lock | Srcu-unlock | Sync-srcu
++flag ~empty [M \ IW \ ALL-LOCKS] ; loc ; [ALL-LOCKS] as mixed-lock-accesses
+ 
+ (* Link Lock-Reads to their RMW-partner Lock-Writes *)
+ let lk-rmw = ([LKR] ; po-loc ; [LKW]) \ (po ; po)

commit 627c9ad04f01221b4396f3df839c5dd994f327b4
+Author: Alan Stern 
+Date:   Wed Jan 25 15:20:51 2023 -0500
+
+    tools/memory-model: Update some warning labels
+    
+    Some of the warning labels used in the LKMM are unfortunately
+    ambiguous.  In particular, the same warning is used for both an
+    unmatched rcu_read_lock() call and for an unmatched rcu_read_unlock()
+    call.  Likewise for the srcu_* equivalents.  Also, the warning about
+    passing a wrong value to srcu_read_unlock() -- i.e., a value different
+    from the one returned by the matching srcu_read_lock() -- talks about
+    bad nesting rather than non-matching values.
+    
+    Let's update the warning labels to make their meanings more clear.
+    
+    Signed-off-by: Alan Stern 
+    Reviewed-by: Jonas Oberhauser 
+    Acked-by: Andrea Parri 
+    Signed-off-by: Paul E. McKenney 
+
+diff --git a/tools/memory-model/linux-kernel.bell b/tools/memory-model/linux-kernel.bell
+index 70a9073dec3e..dc464854d28a 100644
+--- a/tools/memory-model/linux-kernel.bell
++++ b/tools/memory-model/linux-kernel.bell
+@@ -53,8 +53,8 @@ let rcu-rscs = let rec
+ 	in matched
+ 
+ (* Validate nesting *)
+-flag ~empty Rcu-lock \ domain(rcu-rscs) as unbalanced-rcu-locking
+-flag ~empty Rcu-unlock \ range(rcu-rscs) as unbalanced-rcu-locking
++flag ~empty Rcu-lock \ domain(rcu-rscs) as unmatched-rcu-lock
++flag ~empty Rcu-unlock \ range(rcu-rscs) as unmatched-rcu-unlock
+ 
+ (* Compute matching pairs of nested Srcu-lock and Srcu-unlock *)
+ let srcu-rscs = let rec
+@@ -69,14 +69,14 @@ let srcu-rscs = let rec
+ 	in matched
+ 
+ (* Validate nesting *)
+-flag ~empty Srcu-lock \ domain(srcu-rscs) as unbalanced-srcu-locking
+-flag ~empty Srcu-unlock \ range(srcu-rscs) as unbalanced-srcu-locking
++flag ~empty Srcu-lock \ domain(srcu-rscs) as unmatched-srcu-lock
++flag ~empty Srcu-unlock \ range(srcu-rscs) as unmatched-srcu-unlock
+ 
+ (* Check for use of synchronize_srcu() inside an RCU critical section *)
+ flag ~empty rcu-rscs & (po ; [Sync-srcu] ; po) as invalid-sleep
+ 
+ (* Validate SRCU dynamic match *)
+-flag ~empty different-values(srcu-rscs) as srcu-bad-nesting
++flag ~empty different-values(srcu-rscs) as srcu-bad-value-match
+ 
+ (* Compute marked and plain memory accesses *)
+ let Marked = (~M) | IW | Once | Release | Acquire | domain(rmw) | range(rmw) |

commit 93fd565919cf897adf7e1da81cace1a46e4db7f4
+Author: Alan Stern 
+Date:   Fri Feb 3 14:32:09 2023 -0500
+
+    net: USB: Fix wrong-direction WARNING in plusb.c
+    
+    The syzbot fuzzer detected a bug in the plusb network driver: A
+    zero-length control-OUT transfer was treated as a read instead of a
+    write.  In modern kernels this error provokes a WARNING:
+    
+    usb 1-1: BOGUS control dir, pipe 80000280 doesn't match bRequestType c0
+    WARNING: CPU: 0 PID: 4645 at drivers/usb/core/urb.c:411
+    usb_submit_urb+0x14a7/0x1880 drivers/usb/core/urb.c:411
+    Modules linked in:
+    CPU: 1 PID: 4645 Comm: dhcpcd Not tainted
+    6.2.0-rc6-syzkaller-00050-g9f266ccaa2f5 #0
+    Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google
+    01/12/2023
+    RIP: 0010:usb_submit_urb+0x14a7/0x1880 drivers/usb/core/urb.c:411
+    ...
+    Call Trace:
+     
+     usb_start_wait_urb+0x101/0x4b0 drivers/usb/core/message.c:58
+     usb_internal_control_msg drivers/usb/core/message.c:102 [inline]
+     usb_control_msg+0x320/0x4a0 drivers/usb/core/message.c:153
+     __usbnet_read_cmd+0xb9/0x390 drivers/net/usb/usbnet.c:2010
+     usbnet_read_cmd+0x96/0xf0 drivers/net/usb/usbnet.c:2068
+     pl_vendor_req drivers/net/usb/plusb.c:60 [inline]
+     pl_set_QuickLink_features drivers/net/usb/plusb.c:75 [inline]
+     pl_reset+0x2f/0xf0 drivers/net/usb/plusb.c:85
+     usbnet_open+0xcc/0x5d0 drivers/net/usb/usbnet.c:889
+     __dev_open+0x297/0x4d0 net/core/dev.c:1417
+     __dev_change_flags+0x587/0x750 net/core/dev.c:8530
+     dev_change_flags+0x97/0x170 net/core/dev.c:8602
+     devinet_ioctl+0x15a2/0x1d70 net/ipv4/devinet.c:1147
+     inet_ioctl+0x33f/0x380 net/ipv4/af_inet.c:979
+     sock_do_ioctl+0xcc/0x230 net/socket.c:1169
+     sock_ioctl+0x1f8/0x680 net/socket.c:1286
+     vfs_ioctl fs/ioctl.c:51 [inline]
+     __do_sys_ioctl fs/ioctl.c:870 [inline]
+     __se_sys_ioctl fs/ioctl.c:856 [inline]
+     __x64_sys_ioctl+0x197/0x210 fs/ioctl.c:856
+     do_syscall_x64 arch/x86/entry/common.c:50 [inline]
+     do_syscall_64+0x39/0xb0 arch/x86/entry/common.c:80
+     entry_SYSCALL_64_after_hwframe+0x63/0xcd
+    
+    The fix is to call usbnet_write_cmd() instead of usbnet_read_cmd() and
+    remove the USB_DIR_IN flag.
+    
+    Reported-and-tested-by: syzbot+2a0e7abd24f1eb90ce25@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    Fixes: 090ffa9d0e90 ("[PATCH] USB: usbnet (9/9) module for pl2301/2302 cables")
+    CC: stable@vger.kernel.org
+    Link: https://lore.kernel.org/r/00000000000052099f05f3b3e298@google.com/
+    Link: https://lore.kernel.org/r/Y91hOew3nW56Ki4O@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/usb/plusb.c b/drivers/net/usb/plusb.c
+index 2c82fbcaab22..7a2b0094de51 100644
+--- a/drivers/net/usb/plusb.c
++++ b/drivers/net/usb/plusb.c
+@@ -57,9 +57,7 @@
+ static inline int
+ pl_vendor_req(struct usbnet *dev, u8 req, u8 val, u8 index)
+ {
+-	return usbnet_read_cmd(dev, req,
+-				USB_DIR_IN | USB_TYPE_VENDOR |
+-				USB_RECIP_DEVICE,
++	return usbnet_write_cmd(dev, req, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 				val, index, NULL, 0);
+ }
+ 

commit 811d581194f7412eda97acc03d17fc77824b561f
+Author: Alan Stern 
+Date:   Fri Feb 3 14:32:09 2023 -0500
+
+    net: USB: Fix wrong-direction WARNING in plusb.c
+    
+    The syzbot fuzzer detected a bug in the plusb network driver: A
+    zero-length control-OUT transfer was treated as a read instead of a
+    write.  In modern kernels this error provokes a WARNING:
+    
+    usb 1-1: BOGUS control dir, pipe 80000280 doesn't match bRequestType c0
+    WARNING: CPU: 0 PID: 4645 at drivers/usb/core/urb.c:411
+    usb_submit_urb+0x14a7/0x1880 drivers/usb/core/urb.c:411
+    Modules linked in:
+    CPU: 1 PID: 4645 Comm: dhcpcd Not tainted
+    6.2.0-rc6-syzkaller-00050-g9f266ccaa2f5 #0
+    Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google
+    01/12/2023
+    RIP: 0010:usb_submit_urb+0x14a7/0x1880 drivers/usb/core/urb.c:411
+    ...
+    Call Trace:
+     
+     usb_start_wait_urb+0x101/0x4b0 drivers/usb/core/message.c:58
+     usb_internal_control_msg drivers/usb/core/message.c:102 [inline]
+     usb_control_msg+0x320/0x4a0 drivers/usb/core/message.c:153
+     __usbnet_read_cmd+0xb9/0x390 drivers/net/usb/usbnet.c:2010
+     usbnet_read_cmd+0x96/0xf0 drivers/net/usb/usbnet.c:2068
+     pl_vendor_req drivers/net/usb/plusb.c:60 [inline]
+     pl_set_QuickLink_features drivers/net/usb/plusb.c:75 [inline]
+     pl_reset+0x2f/0xf0 drivers/net/usb/plusb.c:85
+     usbnet_open+0xcc/0x5d0 drivers/net/usb/usbnet.c:889
+     __dev_open+0x297/0x4d0 net/core/dev.c:1417
+     __dev_change_flags+0x587/0x750 net/core/dev.c:8530
+     dev_change_flags+0x97/0x170 net/core/dev.c:8602
+     devinet_ioctl+0x15a2/0x1d70 net/ipv4/devinet.c:1147
+     inet_ioctl+0x33f/0x380 net/ipv4/af_inet.c:979
+     sock_do_ioctl+0xcc/0x230 net/socket.c:1169
+     sock_ioctl+0x1f8/0x680 net/socket.c:1286
+     vfs_ioctl fs/ioctl.c:51 [inline]
+     __do_sys_ioctl fs/ioctl.c:870 [inline]
+     __se_sys_ioctl fs/ioctl.c:856 [inline]
+     __x64_sys_ioctl+0x197/0x210 fs/ioctl.c:856
+     do_syscall_x64 arch/x86/entry/common.c:50 [inline]
+     do_syscall_64+0x39/0xb0 arch/x86/entry/common.c:80
+     entry_SYSCALL_64_after_hwframe+0x63/0xcd
+    
+    The fix is to call usbnet_write_cmd() instead of usbnet_read_cmd() and
+    remove the USB_DIR_IN flag.
+    
+    Reported-and-tested-by: syzbot+2a0e7abd24f1eb90ce25@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    Fixes: 090ffa9d0e90 ("[PATCH] USB: usbnet (9/9) module for pl2301/2302 cables")
+    CC: stable@vger.kernel.org
+    Link: https://lore.kernel.org/r/00000000000052099f05f3b3e298@google.com/
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/usb/plusb.c b/drivers/net/usb/plusb.c
+index 2c82fbcaab22..7a2b0094de51 100644
+--- a/drivers/net/usb/plusb.c
++++ b/drivers/net/usb/plusb.c
+@@ -57,9 +57,7 @@
+ static inline int
+ pl_vendor_req(struct usbnet *dev, u8 req, u8 val, u8 index)
+ {
+-	return usbnet_read_cmd(dev, req,
+-				USB_DIR_IN | USB_TYPE_VENDOR |
+-				USB_RECIP_DEVICE,
++	return usbnet_write_cmd(dev, req, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 				val, index, NULL, 0);
+ }
+ 

commit 45bf39f8df7f05efb83b302c65ae3b9bc92b7065
+Author: Alan Stern 
+Date:   Tue Jan 31 15:49:04 2023 -0500
+
+    USB: core: Don't hold device lock while reading the "descriptors" sysfs file
+    
+    Ever since commit 83e83ecb79a8 ("usb: core: get config and string
+    descriptors for unauthorized devices") was merged in 2013, there has
+    been no mechanism for reallocating the rawdescriptors buffers in
+    struct usb_device after the initial enumeration.  Before that commit,
+    the buffers would be deallocated when a device was deauthorized and
+    reallocated when it was authorized and enumerated.
+    
+    This means that the locking in the read_descriptors() routine is not
+    needed, since the buffers it reads will never be reallocated while the
+    routine is running.  This locking can interfere with user programs
+    trying to read a hub's descriptors via sysfs while new child devices
+    of the hub are being initialized, since the hub is locked during this
+    procedure.
+    
+    Since the locking in read_descriptors() hasn't been needed for over
+    nine years, we can remove it.
+    
+    Reported-and-tested-by: Troels Liebe Bentsen 
+    Signed-off-by: Alan Stern 
+    CC: stable@vger.kernel.org
+    Link: https://lore.kernel.org/r/Y9l+wDTRbuZABzsE@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 9eca403af2a8..97a0f8faea6e 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2389,9 +2389,8 @@ static int usb_enumerate_device_otg(struct usb_device *udev)
+  * usb_enumerate_device - Read device configs/intfs/otg (usbcore-internal)
+  * @udev: newly addressed device (in ADDRESS state)
+  *
+- * This is only called by usb_new_device() and usb_authorize_device()
+- * and FIXME -- all comments that apply to them apply here wrt to
+- * environment.
++ * This is only called by usb_new_device() -- all comments that apply there
++ * apply here wrt to environment.
+  *
+  * If the device is WUSB and not authorized, we don't attempt to read
+  * the string descriptors, as they will be errored out by the device
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 8217032dfb85..b63f78e48c74 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -869,11 +869,7 @@ read_descriptors(struct file *filp, struct kobject *kobj,
+ 	size_t srclen, n;
+ 	int cfgno;
+ 	void *src;
+-	int retval;
+ 
+-	retval = usb_lock_device_interruptible(udev);
+-	if (retval < 0)
+-		return -EINTR;
+ 	/* The binary attribute begins with the device descriptor.
+ 	 * Following that are the raw descriptor entries for all the
+ 	 * configurations (config plus subsidiary descriptors).
+@@ -898,7 +894,6 @@ read_descriptors(struct file *filp, struct kobject *kobj,
+ 			off -= srclen;
+ 		}
+ 	}
+-	usb_unlock_device(udev);
+ 	return count - nleft;
+ }
+ 

commit d18dcfe9860e842f394e37ba01ca9440ab2178f4
+Author: Alan Stern 
+Date:   Fri Dec 23 09:59:09 2022 -0500
+
+    USB: gadgetfs: Fix race between mounting and unmounting
+    
+    The syzbot fuzzer and Gerald Lee have identified a use-after-free bug
+    in the gadgetfs driver, involving processes concurrently mounting and
+    unmounting the gadgetfs filesystem.  In particular, gadgetfs_fill_super()
+    can race with gadgetfs_kill_sb(), causing the latter to deallocate
+    the_device while the former is using it.  The output from KASAN says,
+    in part:
+    
+    BUG: KASAN: use-after-free in instrument_atomic_read_write include/linux/instrumented.h:102 [inline]
+    BUG: KASAN: use-after-free in atomic_fetch_sub_release include/linux/atomic/atomic-instrumented.h:176 [inline]
+    BUG: KASAN: use-after-free in __refcount_sub_and_test include/linux/refcount.h:272 [inline]
+    BUG: KASAN: use-after-free in __refcount_dec_and_test include/linux/refcount.h:315 [inline]
+    BUG: KASAN: use-after-free in refcount_dec_and_test include/linux/refcount.h:333 [inline]
+    BUG: KASAN: use-after-free in put_dev drivers/usb/gadget/legacy/inode.c:159 [inline]
+    BUG: KASAN: use-after-free in gadgetfs_kill_sb+0x33/0x100 drivers/usb/gadget/legacy/inode.c:2086
+    Write of size 4 at addr ffff8880276d7840 by task syz-executor126/18689
+    
+    CPU: 0 PID: 18689 Comm: syz-executor126 Not tainted 6.1.0-syzkaller #0
+    Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022
+    Call Trace:
+     
+    ...
+     atomic_fetch_sub_release include/linux/atomic/atomic-instrumented.h:176 [inline]
+     __refcount_sub_and_test include/linux/refcount.h:272 [inline]
+     __refcount_dec_and_test include/linux/refcount.h:315 [inline]
+     refcount_dec_and_test include/linux/refcount.h:333 [inline]
+     put_dev drivers/usb/gadget/legacy/inode.c:159 [inline]
+     gadgetfs_kill_sb+0x33/0x100 drivers/usb/gadget/legacy/inode.c:2086
+     deactivate_locked_super+0xa7/0xf0 fs/super.c:332
+     vfs_get_super fs/super.c:1190 [inline]
+     get_tree_single+0xd0/0x160 fs/super.c:1207
+     vfs_get_tree+0x88/0x270 fs/super.c:1531
+     vfs_fsconfig_locked fs/fsopen.c:232 [inline]
+    
+    The simplest solution is to ensure that gadgetfs_fill_super() and
+    gadgetfs_kill_sb() are serialized by making them both acquire a new
+    mutex.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: syzbot+33d7ad66d65044b93f16@syzkaller.appspotmail.com
+    Reported-and-tested-by: Gerald Lee 
+    Link: https://lore.kernel.org/linux-usb/CAO3qeMVzXDP-JU6v1u5Ags6Q-bb35kg3=C6d04DjzA9ffa5x1g@mail.gmail.com/
+    Fixes: e5d82a7360d1 ("vfs: Convert gadgetfs to use the new mount API")
+    CC: 
+    Link: https://lore.kernel.org/r/Y6XCPXBpn3tmjdCC@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
+index 01c3ead7d1b4..d605bc2e7e8f 100644
+--- a/drivers/usb/gadget/legacy/inode.c
++++ b/drivers/usb/gadget/legacy/inode.c
+@@ -229,6 +229,7 @@ static void put_ep (struct ep_data *data)
+  */
+ 
+ static const char *CHIP;
++static DEFINE_MUTEX(sb_mutex);		/* Serialize superblock operations */
+ 
+ /*----------------------------------------------------------------------*/
+ 
+@@ -2010,13 +2011,20 @@ gadgetfs_fill_super (struct super_block *sb, struct fs_context *fc)
+ {
+ 	struct inode	*inode;
+ 	struct dev_data	*dev;
++	int		rc;
+ 
+-	if (the_device)
+-		return -ESRCH;
++	mutex_lock(&sb_mutex);
++
++	if (the_device) {
++		rc = -ESRCH;
++		goto Done;
++	}
+ 
+ 	CHIP = usb_get_gadget_udc_name();
+-	if (!CHIP)
+-		return -ENODEV;
++	if (!CHIP) {
++		rc = -ENODEV;
++		goto Done;
++	}
+ 
+ 	/* superblock */
+ 	sb->s_blocksize = PAGE_SIZE;
+@@ -2053,13 +2061,17 @@ gadgetfs_fill_super (struct super_block *sb, struct fs_context *fc)
+ 	 * from binding to a controller.
+ 	 */
+ 	the_device = dev;
+-	return 0;
++	rc = 0;
++	goto Done;
+ 
+-Enomem:
++ Enomem:
+ 	kfree(CHIP);
+ 	CHIP = NULL;
++	rc = -ENOMEM;
+ 
+-	return -ENOMEM;
++ Done:
++	mutex_unlock(&sb_mutex);
++	return rc;
+ }
+ 
+ /* "mount -t gadgetfs path /dev/gadget" ends up here */
+@@ -2081,6 +2093,7 @@ static int gadgetfs_init_fs_context(struct fs_context *fc)
+ static void
+ gadgetfs_kill_sb (struct super_block *sb)
+ {
++	mutex_lock(&sb_mutex);
+ 	kill_litter_super (sb);
+ 	if (the_device) {
+ 		put_dev (the_device);
+@@ -2088,6 +2101,7 @@ gadgetfs_kill_sb (struct super_block *sb)
+ 	}
+ 	kfree(CHIP);
+ 	CHIP = NULL;
++	mutex_unlock(&sb_mutex);
+ }
+ 
+ /*----------------------------------------------------------------------*/

commit ebd50e2947de9d2675b800a6a29748d0ed7d7fd4
+Author: Alan Stern 
+Date:   Wed Nov 16 15:48:01 2022 -0500
+
+    tools: memory-model: Add rmw-sequences to the LKMM
+    
+    Viktor (as relayed by Jonas) has pointed out a weakness in the Linux
+    Kernel Memory Model.  Namely, the memory ordering properties of atomic
+    operations are not monotonic: An atomic op with full-barrier semantics
+    does not always provide ordering as strong as one with release-barrier
+    semantics.
+    
+    The following litmus test illustrates the problem:
+    
+    --------------------------------------------------
+    C atomics-not-monotonic
+    
+    {}
+    
+    P0(int *x, atomic_t *y)
+    {
+            WRITE_ONCE(*x, 1);
+            smp_wmb();
+            atomic_set(y, 1);
+    }
+    
+    P1(atomic_t *y)
+    {
+            int r1;
+    
+            r1 = atomic_inc_return(y);
+    }
+    
+    P2(int *x, atomic_t *y)
+    {
+            int r2;
+            int r3;
+    
+            r2 = atomic_read(y);
+            smp_rmb();
+            r3 = READ_ONCE(*x);
+    }
+    
+    exists (2:r2=2 /\ 2:r3=0)
+    --------------------------------------------------
+    
+    The litmus test is allowed as shown with atomic_inc_return(), which
+    has full-barrier semantics.  But if the operation is changed to
+    atomic_inc_return_release(), which only has release-barrier semantics,
+    the litmus test is forbidden.  Clearly this violates monotonicity.
+    
+    The reason is because the LKMM treats full-barrier atomic ops as if
+    they were written:
+    
+            mb();
+            load();
+            store();
+            mb();
+    
+    (where the load() and store() are the two parts of an atomic RMW op),
+    whereas it treats release-barrier atomic ops as if they were written:
+    
+            load();
+            release_barrier();
+            store();
+    
+    The difference is that here the release barrier orders the load part
+    of the atomic op before the store part with A-cumulativity, whereas
+    the mb()'s above do not.  This means that release-barrier atomics can
+    effectively extend the cumul-fence relation but full-barrier atomics
+    cannot.
+    
+    To resolve this problem we introduce the rmw-sequence relation,
+    representing an arbitrarily long sequence of atomic RMW operations in
+    which each operation reads from the previous one, and explicitly allow
+    it to extend cumul-fence.  This modification of the memory model is
+    sound; it holds for PPC because of B-cumulativity, it holds for TSO
+    and ARM64 because of other-multicopy atomicity, and we can assume that
+    atomic ops on all other architectures will be implemented so as to
+    make it hold for them.
+    
+    For similar reasons we also allow rmw-sequence to extend the
+    w-post-bounded relation, which is analogous to cumul-fence in some
+    ways.
+    
+    Reported-by: Viktor Vafeiadis 
+    Signed-off-by: Alan Stern 
+    Reviewed-by: Jonas Oberhauser 
+    Signed-off-by: Paul E. McKenney 
+
+diff --git a/tools/memory-model/Documentation/explanation.txt b/tools/memory-model/Documentation/explanation.txt
+index 11a1d2d4f681..e901b47236c3 100644
+--- a/tools/memory-model/Documentation/explanation.txt
++++ b/tools/memory-model/Documentation/explanation.txt
+@@ -1007,6 +1007,36 @@ order.  Equivalently,
+ where the rmw relation links the read and write events making up each
+ atomic update.  This is what the LKMM's "atomic" axiom says.
+ 
++Atomic rmw updates play one more role in the LKMM: They can form "rmw
++sequences".  An rmw sequence is simply a bunch of atomic updates where
++each update reads from the previous one.  Written using events, it
++looks like this:
++
++	Z0 ->rf Y1 ->rmw Z1 ->rf ... ->rf Yn ->rmw Zn,
++
++where Z0 is some store event and n can be any number (even 0, in the
++degenerate case).  We write this relation as: Z0 ->rmw-sequence Zn.
++Note that this implies Z0 and Zn are stores to the same variable.
++
++Rmw sequences have a special property in the LKMM: They can extend the
++cumul-fence relation.  That is, if we have:
++
++	U ->cumul-fence X -> rmw-sequence Y
++
++then also U ->cumul-fence Y.  Thinking about this in terms of the
++operational model, U ->cumul-fence X says that the store U propagates
++to each CPU before the store X does.  Then the fact that X and Y are
++linked by an rmw sequence means that U also propagates to each CPU
++before Y does.  In an analogous way, rmw sequences can also extend
++the w-post-bounded relation defined below in the PLAIN ACCESSES AND
++DATA RACES section.
++
++(The notion of rmw sequences in the LKMM is similar to, but not quite
++the same as, that of release sequences in the C11 memory model.  They
++were added to the LKMM to fix an obscure bug; without them, atomic
++updates with full-barrier semantics did not always guarantee ordering
++at least as strong as atomic updates with release-barrier semantics.)
++
+ 
+ THE PRESERVED PROGRAM ORDER RELATION: ppo
+ -----------------------------------------
+diff --git a/tools/memory-model/linux-kernel.cat b/tools/memory-model/linux-kernel.cat
+index d70315fddef6..07f884f9b2bf 100644
+--- a/tools/memory-model/linux-kernel.cat
++++ b/tools/memory-model/linux-kernel.cat
+@@ -74,8 +74,9 @@ let ppo = to-r | to-w | fence | (po-unlock-lock-po & int)
+ 
+ (* Propagation: Ordering from release operations and strong fences. *)
+ let A-cumul(r) = (rfe ; [Marked])? ; r
++let rmw-sequence = (rf ; rmw)*
+ let cumul-fence = [Marked] ; (A-cumul(strong-fence | po-rel) | wmb |
+-	po-unlock-lock-po) ; [Marked]
++	po-unlock-lock-po) ; [Marked] ; rmw-sequence
+ let prop = [Marked] ; (overwrite & ext)? ; cumul-fence* ;
+ 	[Marked] ; rfe? ; [Marked]
+ 
+@@ -174,7 +175,7 @@ let vis = cumul-fence* ; rfe? ; [Marked] ;
+ let w-pre-bounded = [Marked] ; (addr | fence)?
+ let r-pre-bounded = [Marked] ; (addr | nonrw-fence |
+ 	([R4rmb] ; fencerel(Rmb) ; [~Noreturn]))?
+-let w-post-bounded = fence? ; [Marked]
++let w-post-bounded = fence? ; [Marked] ; rmw-sequence
+ let r-post-bounded = (nonrw-fence | ([~Noreturn] ; fencerel(Rmb) ; [R4rmb]))? ;
+ 	[Marked]
+ 

commit 7a09c1269702db8eccb6f718da2b00173e1e0034
+Author: Alan Stern 
+Date:   Wed Nov 2 14:13:19 2022 -0400
+
+    USB: core: Change configuration warnings to notices
+    
+    It has been pointed out that the kernel log messages warning about
+    problems in USB configuration and related descriptors are vexing for
+    users.  The warning log level has a fairly high priority, but the user
+    can do nothing to fix the underlying errors in the device's firmware.
+    
+    To reduce the amount of useless information produced by tools that
+    filter high-priority log messages, we can change these warnings to
+    notices, i.e., change dev_warn() to dev_notice().  The same holds for
+    a few messages that currently use dev_err(): Unless they indicate a
+    failure that might make a device unusable (such as inability to
+    transfer a config descriptor), change them to dev_notice() also.
+    
+    Link: https://bugzilla.kernel.org/show_bug.cgi?id=216630
+    Suggested-by: Artem S. Tashkinov 
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/Y2KzPx0h6z1jXCuN@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
+index 48bc8a4814ac..725b8dbcfe5f 100644
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -61,7 +61,7 @@ static void usb_parse_ssp_isoc_endpoint_companion(struct device *ddev,
+ 	desc = (struct usb_ssp_isoc_ep_comp_descriptor *) buffer;
+ 	if (desc->bDescriptorType != USB_DT_SSP_ISOC_ENDPOINT_COMP ||
+ 	    size < USB_DT_SSP_ISOC_EP_COMP_SIZE) {
+-		dev_warn(ddev, "Invalid SuperSpeedPlus isoc endpoint companion"
++		dev_notice(ddev, "Invalid SuperSpeedPlus isoc endpoint companion"
+ 			 "for config %d interface %d altsetting %d ep %d.\n",
+ 			 cfgno, inum, asnum, ep->desc.bEndpointAddress);
+ 		return;
+@@ -83,7 +83,7 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
+ 
+ 	if (desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP ||
+ 			size < USB_DT_SS_EP_COMP_SIZE) {
+-		dev_warn(ddev, "No SuperSpeed endpoint companion for config %d "
++		dev_notice(ddev, "No SuperSpeed endpoint companion for config %d "
+ 				" interface %d altsetting %d ep %d: "
+ 				"using minimum values\n",
+ 				cfgno, inum, asnum, ep->desc.bEndpointAddress);
+@@ -109,13 +109,13 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
+ 
+ 	/* Check the various values */
+ 	if (usb_endpoint_xfer_control(&ep->desc) && desc->bMaxBurst != 0) {
+-		dev_warn(ddev, "Control endpoint with bMaxBurst = %d in "
++		dev_notice(ddev, "Control endpoint with bMaxBurst = %d in "
+ 				"config %d interface %d altsetting %d ep %d: "
+ 				"setting to zero\n", desc->bMaxBurst,
+ 				cfgno, inum, asnum, ep->desc.bEndpointAddress);
+ 		ep->ss_ep_comp.bMaxBurst = 0;
+ 	} else if (desc->bMaxBurst > 15) {
+-		dev_warn(ddev, "Endpoint with bMaxBurst = %d in "
++		dev_notice(ddev, "Endpoint with bMaxBurst = %d in "
+ 				"config %d interface %d altsetting %d ep %d: "
+ 				"setting to 15\n", desc->bMaxBurst,
+ 				cfgno, inum, asnum, ep->desc.bEndpointAddress);
+@@ -125,7 +125,7 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
+ 	if ((usb_endpoint_xfer_control(&ep->desc) ||
+ 			usb_endpoint_xfer_int(&ep->desc)) &&
+ 				desc->bmAttributes != 0) {
+-		dev_warn(ddev, "%s endpoint with bmAttributes = %d in "
++		dev_notice(ddev, "%s endpoint with bmAttributes = %d in "
+ 				"config %d interface %d altsetting %d ep %d: "
+ 				"setting to zero\n",
+ 				usb_endpoint_xfer_control(&ep->desc) ? "Control" : "Bulk",
+@@ -134,7 +134,7 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
+ 		ep->ss_ep_comp.bmAttributes = 0;
+ 	} else if (usb_endpoint_xfer_bulk(&ep->desc) &&
+ 			desc->bmAttributes > 16) {
+-		dev_warn(ddev, "Bulk endpoint with more than 65536 streams in "
++		dev_notice(ddev, "Bulk endpoint with more than 65536 streams in "
+ 				"config %d interface %d altsetting %d ep %d: "
+ 				"setting to max\n",
+ 				cfgno, inum, asnum, ep->desc.bEndpointAddress);
+@@ -142,7 +142,7 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
+ 	} else if (usb_endpoint_xfer_isoc(&ep->desc) &&
+ 		   !USB_SS_SSP_ISOC_COMP(desc->bmAttributes) &&
+ 		   USB_SS_MULT(desc->bmAttributes) > 3) {
+-		dev_warn(ddev, "Isoc endpoint has Mult of %d in "
++		dev_notice(ddev, "Isoc endpoint has Mult of %d in "
+ 				"config %d interface %d altsetting %d ep %d: "
+ 				"setting to 3\n",
+ 				USB_SS_MULT(desc->bmAttributes),
+@@ -160,7 +160,7 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
+ 	else
+ 		max_tx = 999999;
+ 	if (le16_to_cpu(desc->wBytesPerInterval) > max_tx) {
+-		dev_warn(ddev, "%s endpoint with wBytesPerInterval of %d in "
++		dev_notice(ddev, "%s endpoint with wBytesPerInterval of %d in "
+ 				"config %d interface %d altsetting %d ep %d: "
+ 				"setting to %d\n",
+ 				usb_endpoint_xfer_isoc(&ep->desc) ? "Isoc" : "Int",
+@@ -273,7 +273,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
+ 	else if (d->bLength >= USB_DT_ENDPOINT_SIZE)
+ 		n = USB_DT_ENDPOINT_SIZE;
+ 	else {
+-		dev_warn(ddev, "config %d interface %d altsetting %d has an "
++		dev_notice(ddev, "config %d interface %d altsetting %d has an "
+ 		    "invalid endpoint descriptor of length %d, skipping\n",
+ 		    cfgno, inum, asnum, d->bLength);
+ 		goto skip_to_next_endpoint_or_interface_descriptor;
+@@ -281,7 +281,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
+ 
+ 	i = d->bEndpointAddress & ~USB_ENDPOINT_DIR_MASK;
+ 	if (i >= 16 || i == 0) {
+-		dev_warn(ddev, "config %d interface %d altsetting %d has an "
++		dev_notice(ddev, "config %d interface %d altsetting %d has an "
+ 		    "invalid endpoint with address 0x%X, skipping\n",
+ 		    cfgno, inum, asnum, d->bEndpointAddress);
+ 		goto skip_to_next_endpoint_or_interface_descriptor;
+@@ -293,7 +293,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
+ 
+ 	/* Check for duplicate endpoint addresses */
+ 	if (config_endpoint_is_duplicate(config, inum, asnum, d)) {
+-		dev_warn(ddev, "config %d interface %d altsetting %d has a duplicate endpoint with address 0x%X, skipping\n",
++		dev_notice(ddev, "config %d interface %d altsetting %d has a duplicate endpoint with address 0x%X, skipping\n",
+ 				cfgno, inum, asnum, d->bEndpointAddress);
+ 		goto skip_to_next_endpoint_or_interface_descriptor;
+ 	}
+@@ -301,7 +301,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
+ 	/* Ignore some endpoints */
+ 	if (udev->quirks & USB_QUIRK_ENDPOINT_IGNORE) {
+ 		if (usb_endpoint_is_ignored(udev, ifp, d)) {
+-			dev_warn(ddev, "config %d interface %d altsetting %d has an ignored endpoint with address 0x%X, skipping\n",
++			dev_notice(ddev, "config %d interface %d altsetting %d has an ignored endpoint with address 0x%X, skipping\n",
+ 					cfgno, inum, asnum,
+ 					d->bEndpointAddress);
+ 			goto skip_to_next_endpoint_or_interface_descriptor;
+@@ -378,7 +378,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
+ 		}
+ 	}
+ 	if (d->bInterval < i || d->bInterval > j) {
+-		dev_warn(ddev, "config %d interface %d altsetting %d "
++		dev_notice(ddev, "config %d interface %d altsetting %d "
+ 		    "endpoint 0x%X has an invalid bInterval %d, "
+ 		    "changing to %d\n",
+ 		    cfgno, inum, asnum,
+@@ -391,7 +391,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
+ 	 * them usable, we will try treating them as Interrupt endpoints.
+ 	 */
+ 	if (udev->speed == USB_SPEED_LOW && usb_endpoint_xfer_bulk(d)) {
+-		dev_warn(ddev, "config %d interface %d altsetting %d "
++		dev_notice(ddev, "config %d interface %d altsetting %d "
+ 		    "endpoint 0x%X is Bulk; changing to Interrupt\n",
+ 		    cfgno, inum, asnum, d->bEndpointAddress);
+ 		endpoint->desc.bmAttributes = USB_ENDPOINT_XFER_INT;
+@@ -408,7 +408,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
+ 	 */
+ 	maxp = le16_to_cpu(endpoint->desc.wMaxPacketSize);
+ 	if (maxp == 0 && !(usb_endpoint_xfer_isoc(d) && asnum == 0)) {
+-		dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has invalid wMaxPacketSize 0\n",
++		dev_notice(ddev, "config %d interface %d altsetting %d endpoint 0x%X has invalid wMaxPacketSize 0\n",
+ 		    cfgno, inum, asnum, d->bEndpointAddress);
+ 	}
+ 
+@@ -439,7 +439,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
+ 	j = maxpacket_maxes[usb_endpoint_type(&endpoint->desc)];
+ 
+ 	if (maxp > j) {
+-		dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has invalid maxpacket %d, setting to %d\n",
++		dev_notice(ddev, "config %d interface %d altsetting %d endpoint 0x%X has invalid maxpacket %d, setting to %d\n",
+ 		    cfgno, inum, asnum, d->bEndpointAddress, maxp, j);
+ 		maxp = j;
+ 		endpoint->desc.wMaxPacketSize = cpu_to_le16(i | maxp);
+@@ -452,7 +452,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
+ 	 */
+ 	if (udev->speed == USB_SPEED_HIGH && usb_endpoint_xfer_bulk(d)) {
+ 		if (maxp != 512)
+-			dev_warn(ddev, "config %d interface %d altsetting %d "
++			dev_notice(ddev, "config %d interface %d altsetting %d "
+ 				"bulk endpoint 0x%X has invalid maxpacket %d\n",
+ 				cfgno, inum, asnum, d->bEndpointAddress,
+ 				maxp);
+@@ -533,7 +533,7 @@ static int usb_parse_interface(struct device *ddev, int cfgno,
+ 	      i < intfc->num_altsetting;
+ 	     (++i, ++alt)) {
+ 		if (alt->desc.bAlternateSetting == asnum) {
+-			dev_warn(ddev, "Duplicate descriptor for config %d "
++			dev_notice(ddev, "Duplicate descriptor for config %d "
+ 			    "interface %d altsetting %d, skipping\n",
+ 			    cfgno, inum, asnum);
+ 			goto skip_to_next_interface_descriptor;
+@@ -559,7 +559,7 @@ static int usb_parse_interface(struct device *ddev, int cfgno,
+ 	num_ep = num_ep_orig = alt->desc.bNumEndpoints;
+ 	alt->desc.bNumEndpoints = 0;		/* Use as a counter */
+ 	if (num_ep > USB_MAXENDPOINTS) {
+-		dev_warn(ddev, "too many endpoints for config %d interface %d "
++		dev_notice(ddev, "too many endpoints for config %d interface %d "
+ 		    "altsetting %d: %d, using maximum allowed: %d\n",
+ 		    cfgno, inum, asnum, num_ep, USB_MAXENDPOINTS);
+ 		num_ep = USB_MAXENDPOINTS;
+@@ -590,7 +590,7 @@ static int usb_parse_interface(struct device *ddev, int cfgno,
+ 	}
+ 
+ 	if (n != num_ep_orig)
+-		dev_warn(ddev, "config %d interface %d altsetting %d has %d "
++		dev_notice(ddev, "config %d interface %d altsetting %d has %d "
+ 		    "endpoint descriptor%s, different from the interface "
+ 		    "descriptor's value: %d\n",
+ 		    cfgno, inum, asnum, n, plural(n), num_ep_orig);
+@@ -625,7 +625,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+ 	if (config->desc.bDescriptorType != USB_DT_CONFIG ||
+ 	    config->desc.bLength < USB_DT_CONFIG_SIZE ||
+ 	    config->desc.bLength > size) {
+-		dev_err(ddev, "invalid descriptor for config index %d: "
++		dev_notice(ddev, "invalid descriptor for config index %d: "
+ 		    "type = 0x%X, length = %d\n", cfgidx,
+ 		    config->desc.bDescriptorType, config->desc.bLength);
+ 		return -EINVAL;
+@@ -636,7 +636,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+ 	size -= config->desc.bLength;
+ 
+ 	if (nintf > USB_MAXINTERFACES) {
+-		dev_warn(ddev, "config %d has too many interfaces: %d, "
++		dev_notice(ddev, "config %d has too many interfaces: %d, "
+ 		    "using maximum allowed: %d\n",
+ 		    cfgno, nintf, USB_MAXINTERFACES);
+ 		nintf = USB_MAXINTERFACES;
+@@ -650,7 +650,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+ 	     (buffer2 += header->bLength, size2 -= header->bLength)) {
+ 
+ 		if (size2 < sizeof(struct usb_descriptor_header)) {
+-			dev_warn(ddev, "config %d descriptor has %d excess "
++			dev_notice(ddev, "config %d descriptor has %d excess "
+ 			    "byte%s, ignoring\n",
+ 			    cfgno, size2, plural(size2));
+ 			break;
+@@ -658,7 +658,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+ 
+ 		header = (struct usb_descriptor_header *) buffer2;
+ 		if ((header->bLength > size2) || (header->bLength < 2)) {
+-			dev_warn(ddev, "config %d has an invalid descriptor "
++			dev_notice(ddev, "config %d has an invalid descriptor "
+ 			    "of length %d, skipping remainder of the config\n",
+ 			    cfgno, header->bLength);
+ 			break;
+@@ -670,7 +670,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+ 
+ 			d = (struct usb_interface_descriptor *) header;
+ 			if (d->bLength < USB_DT_INTERFACE_SIZE) {
+-				dev_warn(ddev, "config %d has an invalid "
++				dev_notice(ddev, "config %d has an invalid "
+ 				    "interface descriptor of length %d, "
+ 				    "skipping\n", cfgno, d->bLength);
+ 				continue;
+@@ -680,7 +680,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+ 
+ 			if ((dev->quirks & USB_QUIRK_HONOR_BNUMINTERFACES) &&
+ 			    n >= nintf_orig) {
+-				dev_warn(ddev, "config %d has more interface "
++				dev_notice(ddev, "config %d has more interface "
+ 				    "descriptors, than it declares in "
+ 				    "bNumInterfaces, ignoring interface "
+ 				    "number: %d\n", cfgno, inum);
+@@ -688,7 +688,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+ 			}
+ 
+ 			if (inum >= nintf_orig)
+-				dev_warn(ddev, "config %d has an invalid "
++				dev_notice(ddev, "config %d has an invalid "
+ 				    "interface number: %d but max is %d\n",
+ 				    cfgno, inum, nintf_orig - 1);
+ 
+@@ -713,14 +713,14 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+ 
+ 			d = (struct usb_interface_assoc_descriptor *)header;
+ 			if (d->bLength < USB_DT_INTERFACE_ASSOCIATION_SIZE) {
+-				dev_warn(ddev,
++				dev_notice(ddev,
+ 					 "config %d has an invalid interface association descriptor of length %d, skipping\n",
+ 					 cfgno, d->bLength);
+ 				continue;
+ 			}
+ 
+ 			if (iad_num == USB_MAXIADS) {
+-				dev_warn(ddev, "found more Interface "
++				dev_notice(ddev, "found more Interface "
+ 					       "Association Descriptors "
+ 					       "than allocated for in "
+ 					       "configuration %d\n", cfgno);
+@@ -731,7 +731,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+ 
+ 		} else if (header->bDescriptorType == USB_DT_DEVICE ||
+ 			    header->bDescriptorType == USB_DT_CONFIG)
+-			dev_warn(ddev, "config %d contains an unexpected "
++			dev_notice(ddev, "config %d contains an unexpected "
+ 			    "descriptor of type 0x%X, skipping\n",
+ 			    cfgno, header->bDescriptorType);
+ 
+@@ -740,11 +740,11 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+ 	config->desc.wTotalLength = cpu_to_le16(buffer2 - buffer0);
+ 
+ 	if (n != nintf)
+-		dev_warn(ddev, "config %d has %d interface%s, different from "
++		dev_notice(ddev, "config %d has %d interface%s, different from "
+ 		    "the descriptor's value: %d\n",
+ 		    cfgno, n, plural(n), nintf_orig);
+ 	else if (n == 0)
+-		dev_warn(ddev, "config %d has no interfaces?\n", cfgno);
++		dev_notice(ddev, "config %d has no interfaces?\n", cfgno);
+ 	config->desc.bNumInterfaces = nintf = n;
+ 
+ 	/* Check for missing interface numbers */
+@@ -754,7 +754,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+ 				break;
+ 		}
+ 		if (j >= nintf)
+-			dev_warn(ddev, "config %d has no interface number "
++			dev_notice(ddev, "config %d has no interface number "
+ 			    "%d\n", cfgno, i);
+ 	}
+ 
+@@ -762,7 +762,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+ 	for (i = 0; i < nintf; ++i) {
+ 		j = nalts[i];
+ 		if (j > USB_MAXALTSETTING) {
+-			dev_warn(ddev, "too many alternate settings for "
++			dev_notice(ddev, "too many alternate settings for "
+ 			    "config %d interface %d: %d, "
+ 			    "using maximum allowed: %d\n",
+ 			    cfgno, inums[i], j, USB_MAXALTSETTING);
+@@ -811,7 +811,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+ 					break;
+ 			}
+ 			if (n >= intfc->num_altsetting)
+-				dev_warn(ddev, "config %d interface %d has no "
++				dev_notice(ddev, "config %d interface %d has no "
+ 				    "altsetting %d\n", cfgno, inums[i], j);
+ 		}
+ 	}
+@@ -868,7 +868,7 @@ int usb_get_configuration(struct usb_device *dev)
+ 	int result;
+ 
+ 	if (ncfg > USB_MAXCONFIG) {
+-		dev_warn(ddev, "too many configurations: %d, "
++		dev_notice(ddev, "too many configurations: %d, "
+ 		    "using maximum allowed: %d\n", ncfg, USB_MAXCONFIG);
+ 		dev->descriptor.bNumConfigurations = ncfg = USB_MAXCONFIG;
+ 	}
+@@ -902,7 +902,7 @@ int usb_get_configuration(struct usb_device *dev)
+ 			    "descriptor/%s: %d\n", cfgno, "start", result);
+ 			if (result != -EPIPE)
+ 				goto err;
+-			dev_err(ddev, "chopping to %d config(s)\n", cfgno);
++			dev_notice(ddev, "chopping to %d config(s)\n", cfgno);
+ 			dev->descriptor.bNumConfigurations = cfgno;
+ 			break;
+ 		} else if (result < 4) {
+@@ -934,7 +934,7 @@ int usb_get_configuration(struct usb_device *dev)
+ 			goto err;
+ 		}
+ 		if (result < length) {
+-			dev_warn(ddev, "config index %d descriptor too short "
++			dev_notice(ddev, "config index %d descriptor too short "
+ 			    "(expected %i, got %i)\n", cfgno, length, result);
+ 			length = result;
+ 		}
+@@ -993,7 +993,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
+ 	/* Get BOS descriptor */
+ 	ret = usb_get_descriptor(dev, USB_DT_BOS, 0, bos, USB_DT_BOS_SIZE);
+ 	if (ret < USB_DT_BOS_SIZE || bos->bLength < USB_DT_BOS_SIZE) {
+-		dev_err(ddev, "unable to get BOS descriptor or descriptor too short\n");
++		dev_notice(ddev, "unable to get BOS descriptor or descriptor too short\n");
+ 		if (ret >= 0)
+ 			ret = -ENOMSG;
+ 		kfree(bos);
+@@ -1021,7 +1021,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
+ 
+ 	ret = usb_get_descriptor(dev, USB_DT_BOS, 0, buffer, total_len);
+ 	if (ret < total_len) {
+-		dev_err(ddev, "unable to get BOS descriptor set\n");
++		dev_notice(ddev, "unable to get BOS descriptor set\n");
+ 		if (ret >= 0)
+ 			ret = -ENOMSG;
+ 		goto err;
+@@ -1046,7 +1046,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
+ 		}
+ 
+ 		if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) {
+-			dev_warn(ddev, "descriptor type invalid, skip\n");
++			dev_notice(ddev, "descriptor type invalid, skip\n");
+ 			continue;
+ 		}
+ 

commit 41fd1cb6151439b205ac7611883d85ae14250172
+Author: Alan Stern 
+Date:   Fri Aug 26 21:31:40 2022 +0200
+
+    media: mceusb: Use new usb_control_msg_*() routines
+    
+    Automatic kernel fuzzing led to a WARN about invalid pipe direction in
+    the mceusb driver:
+    
+    ------------[ cut here ]------------
+    usb 6-1: BOGUS control dir, pipe 80000380 doesn't match bRequestType 40
+    WARNING: CPU: 0 PID: 2465 at drivers/usb/core/urb.c:410
+    usb_submit_urb+0x1326/0x1820 drivers/usb/core/urb.c:410
+    Modules linked in:
+    CPU: 0 PID: 2465 Comm: kworker/0:2 Not tainted 5.19.0-rc4-00208-g69cb6c6556ad #1
+    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
+    1.13.0-1ubuntu1.1 04/01/2014
+    Workqueue: usb_hub_wq hub_event
+    RIP: 0010:usb_submit_urb+0x1326/0x1820 drivers/usb/core/urb.c:410
+    Code: 7c 24 40 e8 ac 23 91 fd 48 8b 7c 24 40 e8 b2 70 1b ff 45 89 e8
+    44 89 f1 4c 89 e2 48 89 c6 48 c7 c7 a0 30 a9 86 e8 48 07 11 02 <0f> 0b
+    e9 1c f0 ff ff e8 7e 23 91 fd 0f b6 1d 63 22 83 05 31 ff 41
+    RSP: 0018:ffffc900032becf0 EFLAGS: 00010282
+    RAX: 0000000000000000 RBX: ffff8881100f3058 RCX: 0000000000000000
+    RDX: ffffc90004961000 RSI: ffff888114c6d580 RDI: fffff52000657d90
+    RBP: ffff888105ad90f0 R08: ffffffff812c3638 R09: 0000000000000000
+    R10: 0000000000000005 R11: ffffed1023504ef1 R12: ffff888105ad9000
+    R13: 0000000000000040 R14: 0000000080000380 R15: ffff88810ba96500
+    FS: 0000000000000000(0000) GS:ffff88811a800000(0000) knlGS:0000000000000000
+    CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+    CR2: 00007ffe810bda58 CR3: 000000010b720000 CR4: 0000000000350ef0
+    Call Trace:
+    
+    usb_start_wait_urb+0x101/0x4c0 drivers/usb/core/message.c:58
+    usb_internal_control_msg drivers/usb/core/message.c:102 [inline]
+    usb_control_msg+0x31c/0x4a0 drivers/usb/core/message.c:153
+    mceusb_gen1_init drivers/media/rc/mceusb.c:1431 [inline]
+    mceusb_dev_probe+0x258e/0x33f0 drivers/media/rc/mceusb.c:1807
+    
+    The reason for the warning is clear enough; the driver sends an
+    unusual read request on endpoint 0 but does not set the USB_DIR_IN bit
+    in the bRequestType field.
+    
+    More importantly, the whole situation can be avoided and the driver
+    simplified by converting it over to the relatively new
+    usb_control_msg_recv() and usb_control_msg_send() routines.  That's
+    what this fix does.
+    
+    Reported-and-tested-by: Rondreis 
+    Link: https://lore.kernel.org/all/CAB7eexLLApHJwZfMQ=X-PtRhw0BgO+5KcSMS05FNUYejJXqtSA@mail.gmail.com/
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Sean Young 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
+index 0834d5f866fd..39d2b03e2631 100644
+--- a/drivers/media/rc/mceusb.c
++++ b/drivers/media/rc/mceusb.c
+@@ -1416,42 +1416,37 @@ static void mceusb_gen1_init(struct mceusb_dev *ir)
+ {
+ 	int ret;
+ 	struct device *dev = ir->dev;
+-	char *data;
+-
+-	data = kzalloc(USB_CTRL_MSG_SZ, GFP_KERNEL);
+-	if (!data) {
+-		dev_err(dev, "%s: memory allocation failed!", __func__);
+-		return;
+-	}
++	char data[USB_CTRL_MSG_SZ];
+ 
+ 	/*
+ 	 * This is a strange one. Windows issues a set address to the device
+ 	 * on the receive control pipe and expect a certain value pair back
+ 	 */
+-	ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
+-			      USB_REQ_SET_ADDRESS, USB_TYPE_VENDOR, 0, 0,
+-			      data, USB_CTRL_MSG_SZ, 3000);
++	ret = usb_control_msg_recv(ir->usbdev, 0, USB_REQ_SET_ADDRESS,
++				   USB_DIR_IN | USB_TYPE_VENDOR,
++				   0, 0, data, USB_CTRL_MSG_SZ, 3000,
++				   GFP_KERNEL);
+ 	dev_dbg(dev, "set address - ret = %d", ret);
+ 	dev_dbg(dev, "set address - data[0] = %d, data[1] = %d",
+ 						data[0], data[1]);
+ 
+ 	/* set feature: bit rate 38400 bps */
+-	ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
+-			      USB_REQ_SET_FEATURE, USB_TYPE_VENDOR,
+-			      0xc04e, 0x0000, NULL, 0, 3000);
++	ret = usb_control_msg_send(ir->usbdev, 0,
++				   USB_REQ_SET_FEATURE, USB_TYPE_VENDOR,
++				   0xc04e, 0x0000, NULL, 0, 3000, GFP_KERNEL);
+ 
+ 	dev_dbg(dev, "set feature - ret = %d", ret);
+ 
+ 	/* bRequest 4: set char length to 8 bits */
+-	ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
+-			      4, USB_TYPE_VENDOR,
+-			      0x0808, 0x0000, NULL, 0, 3000);
++	ret = usb_control_msg_send(ir->usbdev, 0,
++				   4, USB_TYPE_VENDOR,
++				   0x0808, 0x0000, NULL, 0, 3000, GFP_KERNEL);
+ 	dev_dbg(dev, "set char length - retB = %d", ret);
+ 
+ 	/* bRequest 2: set handshaking to use DTR/DSR */
+-	ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
+-			      2, USB_TYPE_VENDOR,
+-			      0x0000, 0x0100, NULL, 0, 3000);
++	ret = usb_control_msg_send(ir->usbdev, 0,
++				   2, USB_TYPE_VENDOR,
++				   0x0000, 0x0100, NULL, 0, 3000, GFP_KERNEL);
+ 	dev_dbg(dev, "set handshake  - retC = %d", ret);
+ 
+ 	/* device resume */
+@@ -1459,8 +1454,6 @@ static void mceusb_gen1_init(struct mceusb_dev *ir)
+ 
+ 	/* get hw/sw revision? */
+ 	mce_command_out(ir, GET_REVISION, sizeof(GET_REVISION));
+-
+-	kfree(data);
+ }
+ 
+ static void mceusb_gen2_init(struct mceusb_dev *ir)

commit 766a96dc558385be735a370db867e302c8f22153
+Author: Alan Stern 
+Date:   Thu Sep 1 10:36:34 2022 -0400
+
+    USB: core: Fix RST error in hub.c
+    
+    A recent commit added an invalid RST expression to a kerneldoc comment
+    in hub.c.  The fix is trivial.
+    
+    Fixes: 9c6d778800b9 ("USB: core: Prevent nested device-reset calls")
+    Cc: 
+    Reported-by: Stephen Rothwell 
+    Reviewed-by: Bagas Sanjaya 
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/YxDDcsLtRZ7c20pq@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index d4b1e70d1498..bbab424b0d55 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -6039,7 +6039,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
+  *
+  * Return: The same as for usb_reset_and_verify_device().
+  * However, if a reset is already in progress (for instance, if a
+- * driver doesn't have pre_ or post_reset() callbacks, and while
++ * driver doesn't have pre_reset() or post_reset() callbacks, and while
+  * being unbound or re-bound during the ongoing reset its disconnect()
+  * or probe() routine tries to perform a second, nested reset), the
+  * routine returns -EINPROGRESS.

commit 608e58a0f4617977178131f5f68a3fce1d3f5316
+Author: Alan Stern 
+Date:   Fri Aug 26 15:31:40 2022 -0400
+
+    media: mceusb: Use new usb_control_msg_*() routines
+    
+    Automatic kernel fuzzing led to a WARN about invalid pipe direction in
+    the mceusb driver:
+    
+    ------------[ cut here ]------------
+    usb 6-1: BOGUS control dir, pipe 80000380 doesn't match bRequestType 40
+    WARNING: CPU: 0 PID: 2465 at drivers/usb/core/urb.c:410
+    usb_submit_urb+0x1326/0x1820 drivers/usb/core/urb.c:410
+    Modules linked in:
+    CPU: 0 PID: 2465 Comm: kworker/0:2 Not tainted 5.19.0-rc4-00208-g69cb6c6556ad #1
+    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
+    1.13.0-1ubuntu1.1 04/01/2014
+    Workqueue: usb_hub_wq hub_event
+    RIP: 0010:usb_submit_urb+0x1326/0x1820 drivers/usb/core/urb.c:410
+    Code: 7c 24 40 e8 ac 23 91 fd 48 8b 7c 24 40 e8 b2 70 1b ff 45 89 e8
+    44 89 f1 4c 89 e2 48 89 c6 48 c7 c7 a0 30 a9 86 e8 48 07 11 02 <0f> 0b
+    e9 1c f0 ff ff e8 7e 23 91 fd 0f b6 1d 63 22 83 05 31 ff 41
+    RSP: 0018:ffffc900032becf0 EFLAGS: 00010282
+    RAX: 0000000000000000 RBX: ffff8881100f3058 RCX: 0000000000000000
+    RDX: ffffc90004961000 RSI: ffff888114c6d580 RDI: fffff52000657d90
+    RBP: ffff888105ad90f0 R08: ffffffff812c3638 R09: 0000000000000000
+    R10: 0000000000000005 R11: ffffed1023504ef1 R12: ffff888105ad9000
+    R13: 0000000000000040 R14: 0000000080000380 R15: ffff88810ba96500
+    FS: 0000000000000000(0000) GS:ffff88811a800000(0000) knlGS:0000000000000000
+    CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+    CR2: 00007ffe810bda58 CR3: 000000010b720000 CR4: 0000000000350ef0
+    Call Trace:
+    
+    usb_start_wait_urb+0x101/0x4c0 drivers/usb/core/message.c:58
+    usb_internal_control_msg drivers/usb/core/message.c:102 [inline]
+    usb_control_msg+0x31c/0x4a0 drivers/usb/core/message.c:153
+    mceusb_gen1_init drivers/media/rc/mceusb.c:1431 [inline]
+    mceusb_dev_probe+0x258e/0x33f0 drivers/media/rc/mceusb.c:1807
+    
+    The reason for the warning is clear enough; the driver sends an
+    unusual read request on endpoint 0 but does not set the USB_DIR_IN bit
+    in the bRequestType field.
+    
+    More importantly, the whole situation can be avoided and the driver
+    simplified by converting it over to the relatively new
+    usb_control_msg_recv() and usb_control_msg_send() routines.  That's
+    what this fix does.
+    
+    Link: https://lore.kernel.org/all/CAB7eexLLApHJwZfMQ=X-PtRhw0BgO+5KcSMS05FNUYejJXqtSA@mail.gmail.com/
+    Cc: Mauro Carvalho Chehab 
+    Cc: stable@vger.kernel.org
+    Reported-and-tested-by: Rondreis 
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/YwkfnBFCSEVC6XZu@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
+index 0834d5f866fd..39d2b03e2631 100644
+--- a/drivers/media/rc/mceusb.c
++++ b/drivers/media/rc/mceusb.c
+@@ -1416,42 +1416,37 @@ static void mceusb_gen1_init(struct mceusb_dev *ir)
+ {
+ 	int ret;
+ 	struct device *dev = ir->dev;
+-	char *data;
+-
+-	data = kzalloc(USB_CTRL_MSG_SZ, GFP_KERNEL);
+-	if (!data) {
+-		dev_err(dev, "%s: memory allocation failed!", __func__);
+-		return;
+-	}
++	char data[USB_CTRL_MSG_SZ];
+ 
+ 	/*
+ 	 * This is a strange one. Windows issues a set address to the device
+ 	 * on the receive control pipe and expect a certain value pair back
+ 	 */
+-	ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
+-			      USB_REQ_SET_ADDRESS, USB_TYPE_VENDOR, 0, 0,
+-			      data, USB_CTRL_MSG_SZ, 3000);
++	ret = usb_control_msg_recv(ir->usbdev, 0, USB_REQ_SET_ADDRESS,
++				   USB_DIR_IN | USB_TYPE_VENDOR,
++				   0, 0, data, USB_CTRL_MSG_SZ, 3000,
++				   GFP_KERNEL);
+ 	dev_dbg(dev, "set address - ret = %d", ret);
+ 	dev_dbg(dev, "set address - data[0] = %d, data[1] = %d",
+ 						data[0], data[1]);
+ 
+ 	/* set feature: bit rate 38400 bps */
+-	ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
+-			      USB_REQ_SET_FEATURE, USB_TYPE_VENDOR,
+-			      0xc04e, 0x0000, NULL, 0, 3000);
++	ret = usb_control_msg_send(ir->usbdev, 0,
++				   USB_REQ_SET_FEATURE, USB_TYPE_VENDOR,
++				   0xc04e, 0x0000, NULL, 0, 3000, GFP_KERNEL);
+ 
+ 	dev_dbg(dev, "set feature - ret = %d", ret);
+ 
+ 	/* bRequest 4: set char length to 8 bits */
+-	ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
+-			      4, USB_TYPE_VENDOR,
+-			      0x0808, 0x0000, NULL, 0, 3000);
++	ret = usb_control_msg_send(ir->usbdev, 0,
++				   4, USB_TYPE_VENDOR,
++				   0x0808, 0x0000, NULL, 0, 3000, GFP_KERNEL);
+ 	dev_dbg(dev, "set char length - retB = %d", ret);
+ 
+ 	/* bRequest 2: set handshaking to use DTR/DSR */
+-	ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
+-			      2, USB_TYPE_VENDOR,
+-			      0x0000, 0x0100, NULL, 0, 3000);
++	ret = usb_control_msg_send(ir->usbdev, 0,
++				   2, USB_TYPE_VENDOR,
++				   0x0000, 0x0100, NULL, 0, 3000, GFP_KERNEL);
+ 	dev_dbg(dev, "set handshake  - retC = %d", ret);
+ 
+ 	/* device resume */
+@@ -1459,8 +1454,6 @@ static void mceusb_gen1_init(struct mceusb_dev *ir)
+ 
+ 	/* get hw/sw revision? */
+ 	mce_command_out(ir, GET_REVISION, sizeof(GET_REVISION));
+-
+-	kfree(data);
+ }
+ 
+ static void mceusb_gen2_init(struct mceusb_dev *ir)

commit 9c6d778800b921bde3bff3cff5003d1650f942d1
+Author: Alan Stern 
+Date:   Fri Aug 26 15:31:32 2022 -0400
+
+    USB: core: Prevent nested device-reset calls
+    
+    Automatic kernel fuzzing revealed a recursive locking violation in
+    usb-storage:
+    
+    ============================================
+    WARNING: possible recursive locking detected
+    5.18.0 #3 Not tainted
+    --------------------------------------------
+    kworker/1:3/1205 is trying to acquire lock:
+    ffff888018638db8 (&us_interface_key[i]){+.+.}-{3:3}, at:
+    usb_stor_pre_reset+0x35/0x40 drivers/usb/storage/usb.c:230
+    
+    but task is already holding lock:
+    ffff888018638db8 (&us_interface_key[i]){+.+.}-{3:3}, at:
+    usb_stor_pre_reset+0x35/0x40 drivers/usb/storage/usb.c:230
+    
+    ...
+    
+    stack backtrace:
+    CPU: 1 PID: 1205 Comm: kworker/1:3 Not tainted 5.18.0 #3
+    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
+    1.13.0-1ubuntu1.1 04/01/2014
+    Workqueue: usb_hub_wq hub_event
+    Call Trace:
+    
+    __dump_stack lib/dump_stack.c:88 [inline]
+    dump_stack_lvl+0xcd/0x134 lib/dump_stack.c:106
+    print_deadlock_bug kernel/locking/lockdep.c:2988 [inline]
+    check_deadlock kernel/locking/lockdep.c:3031 [inline]
+    validate_chain kernel/locking/lockdep.c:3816 [inline]
+    __lock_acquire.cold+0x152/0x3ca kernel/locking/lockdep.c:5053
+    lock_acquire kernel/locking/lockdep.c:5665 [inline]
+    lock_acquire+0x1ab/0x520 kernel/locking/lockdep.c:5630
+    __mutex_lock_common kernel/locking/mutex.c:603 [inline]
+    __mutex_lock+0x14f/0x1610 kernel/locking/mutex.c:747
+    usb_stor_pre_reset+0x35/0x40 drivers/usb/storage/usb.c:230
+    usb_reset_device+0x37d/0x9a0 drivers/usb/core/hub.c:6109
+    r871xu_dev_remove+0x21a/0x270 drivers/staging/rtl8712/usb_intf.c:622
+    usb_unbind_interface+0x1bd/0x890 drivers/usb/core/driver.c:458
+    device_remove drivers/base/dd.c:545 [inline]
+    device_remove+0x11f/0x170 drivers/base/dd.c:537
+    __device_release_driver drivers/base/dd.c:1222 [inline]
+    device_release_driver_internal+0x1a7/0x2f0 drivers/base/dd.c:1248
+    usb_driver_release_interface+0x102/0x180 drivers/usb/core/driver.c:627
+    usb_forced_unbind_intf+0x4d/0xa0 drivers/usb/core/driver.c:1118
+    usb_reset_device+0x39b/0x9a0 drivers/usb/core/hub.c:6114
+    
+    This turned out not to be an error in usb-storage but rather a nested
+    device reset attempt.  That is, as the rtl8712 driver was being
+    unbound from a composite device in preparation for an unrelated USB
+    reset (that driver does not have pre_reset or post_reset callbacks),
+    its ->remove routine called usb_reset_device() -- thus nesting one
+    reset call within another.
+    
+    Performing a reset as part of disconnect processing is a questionable
+    practice at best.  However, the bug report points out that the USB
+    core does not have any protection against nested resets.  Adding a
+    reset_in_progress flag and testing it will prevent such errors in the
+    future.
+    
+    Link: https://lore.kernel.org/all/CAB7eexKUpvX-JNiLzhXBDWgfg2T9e9_0Tw4HQ6keN==voRbP0g@mail.gmail.com/
+    Cc: stable@vger.kernel.org
+    Reported-and-tested-by: Rondreis 
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/YwkflDxvg0KWqyZK@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 2633acde7ac1..d4b1e70d1498 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -6038,6 +6038,11 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
+  * the reset is over (using their post_reset method).
+  *
+  * Return: The same as for usb_reset_and_verify_device().
++ * However, if a reset is already in progress (for instance, if a
++ * driver doesn't have pre_ or post_reset() callbacks, and while
++ * being unbound or re-bound during the ongoing reset its disconnect()
++ * or probe() routine tries to perform a second, nested reset), the
++ * routine returns -EINPROGRESS.
+  *
+  * Note:
+  * The caller must own the device lock.  For example, it's safe to use
+@@ -6071,6 +6076,10 @@ int usb_reset_device(struct usb_device *udev)
+ 		return -EISDIR;
+ 	}
+ 
++	if (udev->reset_in_progress)
++		return -EINPROGRESS;
++	udev->reset_in_progress = 1;
++
+ 	port_dev = hub->ports[udev->portnum - 1];
+ 
+ 	/*
+@@ -6135,6 +6144,7 @@ int usb_reset_device(struct usb_device *udev)
+ 
+ 	usb_autosuspend_device(udev);
+ 	memalloc_noio_restore(noio_flag);
++	udev->reset_in_progress = 0;
+ 	return ret;
+ }
+ EXPORT_SYMBOL_GPL(usb_reset_device);
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index f7a9914fc97f..9ff1ad4dfad1 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -575,6 +575,7 @@ struct usb3_lpm_parameters {
+  * @devaddr: device address, XHCI: assigned by HW, others: same as devnum
+  * @can_submit: URBs may be submitted
+  * @persist_enabled:  USB_PERSIST enabled for this device
++ * @reset_in_progress: the device is being reset
+  * @have_langid: whether string_langid is valid
+  * @authorized: policy has said we can use it;
+  *	(user space) policy determines if we authorize this device to be
+@@ -662,6 +663,7 @@ struct usb_device {
+ 
+ 	unsigned can_submit:1;
+ 	unsigned persist_enabled:1;
++	unsigned reset_in_progress:1;
+ 	unsigned have_langid:1;
+ 	unsigned authorized:1;
+ 	unsigned authenticated:1;

commit 1016fc0c096c92dd0e6e0541daac7a7868169903
+Author: Alan Stern 
+Date:   Fri Aug 26 15:31:17 2022 -0400
+
+    USB: gadget: Fix obscure lockdep violation for udc_mutex
+    
+    A recent commit expanding the scope of the udc_lock mutex in the
+    gadget core managed to cause an obscure and slightly bizarre lockdep
+    violation.  In abbreviated form:
+    
+    ======================================================
+    WARNING: possible circular locking dependency detected
+    5.19.0-rc7+ #12510 Not tainted
+    ------------------------------------------------------
+    udevadm/312 is trying to acquire lock:
+    ffff80000aae1058 (udc_lock){+.+.}-{3:3}, at: usb_udc_uevent+0x54/0xe0
+    
+    but task is already holding lock:
+    ffff000002277548 (kn->active#4){++++}-{0:0}, at: kernfs_seq_start+0x34/0xe0
+    
+    which lock already depends on the new lock.
+    
+    the existing dependency chain (in reverse order) is:
+    
+    -> #3 (kn->active#4){++++}-{0:0}:
+            lock_acquire+0x68/0x84
+            __kernfs_remove+0x268/0x380
+            kernfs_remove_by_name_ns+0x58/0xac
+            sysfs_remove_file_ns+0x18/0x24
+            device_del+0x15c/0x440
+    
+    -> #2 (device_links_lock){+.+.}-{3:3}:
+            lock_acquire+0x68/0x84
+            __mutex_lock+0x9c/0x430
+            mutex_lock_nested+0x38/0x64
+            device_link_remove+0x3c/0xa0
+            _regulator_put.part.0+0x168/0x190
+            regulator_put+0x3c/0x54
+            devm_regulator_release+0x14/0x20
+    
+    -> #1 (regulator_list_mutex){+.+.}-{3:3}:
+            lock_acquire+0x68/0x84
+            __mutex_lock+0x9c/0x430
+            mutex_lock_nested+0x38/0x64
+            regulator_lock_dependent+0x54/0x284
+            regulator_enable+0x34/0x80
+            phy_power_on+0x24/0x130
+            __dwc2_lowlevel_hw_enable+0x100/0x130
+            dwc2_lowlevel_hw_enable+0x18/0x40
+            dwc2_hsotg_udc_start+0x6c/0x2f0
+            gadget_bind_driver+0x124/0x1f4
+    
+    -> #0 (udc_lock){+.+.}-{3:3}:
+            __lock_acquire+0x1298/0x20cc
+            lock_acquire.part.0+0xe0/0x230
+            lock_acquire+0x68/0x84
+            __mutex_lock+0x9c/0x430
+            mutex_lock_nested+0x38/0x64
+            usb_udc_uevent+0x54/0xe0
+    
+    Evidently this was caused by the scope of udc_mutex being too large.
+    The mutex is only meant to protect udc->driver along with a few other
+    things.  As far as I can tell, there's no reason for the mutex to be
+    held while the gadget core calls a gadget driver's ->bind or ->unbind
+    routine, or while a UDC is being started or stopped.  (This accounts
+    for link #1 in the chain above, where the mutex is held while the
+    dwc2_hsotg_udc is started as part of driver probing.)
+    
+    Gadget drivers' ->disconnect callbacks are problematic.  Even though
+    usb_gadget_disconnect() will now acquire the udc_mutex, there's a
+    window in usb_gadget_bind_driver() between the times when the mutex is
+    released and the ->bind callback is invoked.  If a disconnect occurred
+    during that window, we could call the driver's ->disconnect routine
+    before its ->bind routine.  To prevent this from happening, it will be
+    necessary to prevent a UDC from connecting while it has no gadget
+    driver.  This should be done already but it doesn't seem to be;
+    currently usb_gadget_connect() has no check for this.  Such a check
+    will have to be added later.
+    
+    Some degree of mutual exclusion is required in soft_connect_store(),
+    which can dereference udc->driver at arbitrary times since it is a
+    sysfs callback.  The solution here is to acquire the gadget's device
+    lock rather than the udc_mutex.  Since the driver core guarantees that
+    the device lock is always held during driver binding and unbinding,
+    this will make the accesses in soft_connect_store() mutually exclusive
+    with any changes to udc->driver.
+    
+    Lastly, it turns out there is one place which should hold the
+    udc_mutex but currently does not: The function_show() routine needs
+    protection while it dereferences udc->driver.  The missing lock and
+    unlock calls are added.
+    
+    Link: https://lore.kernel.org/all/b2ba4245-9917-e399-94c8-03a383e7070e@samsung.com/
+    Fixes: 2191c00855b0 ("USB: gadget: Fix use-after-free Read in usb_udc_uevent()")
+    Cc: Felipe Balbi 
+    Cc: stable@vger.kernel.org
+    Reported-by: Marek Szyprowski 
+    Tested-by: Marek Szyprowski 
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/YwkfhdxA/I2nOcK7@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
+index cafcf260394c..c63c0c2cf649 100644
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -736,7 +736,10 @@ int usb_gadget_disconnect(struct usb_gadget *gadget)
+ 	ret = gadget->ops->pullup(gadget, 0);
+ 	if (!ret) {
+ 		gadget->connected = 0;
+-		gadget->udc->driver->disconnect(gadget);
++		mutex_lock(&udc_lock);
++		if (gadget->udc->driver)
++			gadget->udc->driver->disconnect(gadget);
++		mutex_unlock(&udc_lock);
+ 	}
+ 
+ out:
+@@ -1489,7 +1492,6 @@ static int gadget_bind_driver(struct device *dev)
+ 
+ 	usb_gadget_udc_set_speed(udc, driver->max_speed);
+ 
+-	mutex_lock(&udc_lock);
+ 	ret = driver->bind(udc->gadget, driver);
+ 	if (ret)
+ 		goto err_bind;
+@@ -1499,7 +1501,6 @@ static int gadget_bind_driver(struct device *dev)
+ 		goto err_start;
+ 	usb_gadget_enable_async_callbacks(udc);
+ 	usb_udc_connect_control(udc);
+-	mutex_unlock(&udc_lock);
+ 
+ 	kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
+ 	return 0;
+@@ -1512,6 +1513,7 @@ static int gadget_bind_driver(struct device *dev)
+ 		dev_err(&udc->dev, "failed to start %s: %d\n",
+ 			driver->function, ret);
+ 
++	mutex_lock(&udc_lock);
+ 	udc->driver = NULL;
+ 	driver->is_bound = false;
+ 	mutex_unlock(&udc_lock);
+@@ -1529,7 +1531,6 @@ static void gadget_unbind_driver(struct device *dev)
+ 
+ 	kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
+ 
+-	mutex_lock(&udc_lock);
+ 	usb_gadget_disconnect(gadget);
+ 	usb_gadget_disable_async_callbacks(udc);
+ 	if (gadget->irq)
+@@ -1537,6 +1538,7 @@ static void gadget_unbind_driver(struct device *dev)
+ 	udc->driver->unbind(gadget);
+ 	usb_gadget_udc_stop(udc);
+ 
++	mutex_lock(&udc_lock);
+ 	driver->is_bound = false;
+ 	udc->driver = NULL;
+ 	mutex_unlock(&udc_lock);
+@@ -1612,7 +1614,7 @@ static ssize_t soft_connect_store(struct device *dev,
+ 	struct usb_udc		*udc = container_of(dev, struct usb_udc, dev);
+ 	ssize_t			ret;
+ 
+-	mutex_lock(&udc_lock);
++	device_lock(&udc->gadget->dev);
+ 	if (!udc->driver) {
+ 		dev_err(dev, "soft-connect without a gadget driver\n");
+ 		ret = -EOPNOTSUPP;
+@@ -1633,7 +1635,7 @@ static ssize_t soft_connect_store(struct device *dev,
+ 
+ 	ret = n;
+ out:
+-	mutex_unlock(&udc_lock);
++	device_unlock(&udc->gadget->dev);
+ 	return ret;
+ }
+ static DEVICE_ATTR_WO(soft_connect);
+@@ -1652,11 +1654,15 @@ static ssize_t function_show(struct device *dev, struct device_attribute *attr,
+ 			     char *buf)
+ {
+ 	struct usb_udc		*udc = container_of(dev, struct usb_udc, dev);
+-	struct usb_gadget_driver *drv = udc->driver;
++	struct usb_gadget_driver *drv;
++	int			rc = 0;
+ 
+-	if (!drv || !drv->function)
+-		return 0;
+-	return scnprintf(buf, PAGE_SIZE, "%s\n", drv->function);
++	mutex_lock(&udc_lock);
++	drv = udc->driver;
++	if (drv && drv->function)
++		rc = scnprintf(buf, PAGE_SIZE, "%s\n", drv->function);
++	mutex_unlock(&udc_lock);
++	return rc;
+ }
+ static DEVICE_ATTR_RO(function);
+ 

commit 2191c00855b03aa59c20e698be713d952d51fc18
+Author: Alan Stern 
+Date:   Thu Jul 21 11:07:10 2022 -0400
+
+    USB: gadget: Fix use-after-free Read in usb_udc_uevent()
+    
+    The syzbot fuzzer found a race between uevent callbacks and gadget
+    driver unregistration that can cause a use-after-free bug:
+    
+    ---------------------------------------------------------------
+    BUG: KASAN: use-after-free in usb_udc_uevent+0x11f/0x130
+    drivers/usb/gadget/udc/core.c:1732
+    Read of size 8 at addr ffff888078ce2050 by task udevd/2968
+    
+    CPU: 1 PID: 2968 Comm: udevd Not tainted 5.19.0-rc4-next-20220628-syzkaller #0
+    Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google
+    06/29/2022
+    Call Trace:
+     
+     __dump_stack lib/dump_stack.c:88 [inline]
+     dump_stack_lvl+0xcd/0x134 lib/dump_stack.c:106
+     print_address_description mm/kasan/report.c:317 [inline]
+     print_report.cold+0x2ba/0x719 mm/kasan/report.c:433
+     kasan_report+0xbe/0x1f0 mm/kasan/report.c:495
+     usb_udc_uevent+0x11f/0x130 drivers/usb/gadget/udc/core.c:1732
+     dev_uevent+0x290/0x770 drivers/base/core.c:2424
+    ---------------------------------------------------------------
+    
+    The bug occurs because usb_udc_uevent() dereferences udc->driver but
+    does so without acquiring the udc_lock mutex, which protects this
+    field.  If the gadget driver is unbound from the udc concurrently with
+    uevent processing, the driver structure may be accessed after it has
+    been deallocated.
+    
+    To prevent the race, we make sure that the routine holds the mutex
+    around the racing accesses.
+    
+    Link: 
+    CC: stable@vger.kernel.org # fc274c1e9973
+    Reported-and-tested-by: syzbot+b0de012ceb1e2a97891b@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/YtlrnhHyrHsSky9m@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
+index 7886497253cc..cafcf260394c 100644
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -1728,13 +1728,14 @@ static int usb_udc_uevent(struct device *dev, struct kobj_uevent_env *env)
+ 		return ret;
+ 	}
+ 
+-	if (udc->driver) {
++	mutex_lock(&udc_lock);
++	if (udc->driver)
+ 		ret = add_uevent_var(env, "USB_UDC_DRIVER=%s",
+ 				udc->driver->function);
+-		if (ret) {
+-			dev_err(dev, "failed to add uevent USB_UDC_DRIVER\n");
+-			return ret;
+-		}
++	mutex_unlock(&udc_lock);
++	if (ret) {
++		dev_err(dev, "failed to add uevent USB_UDC_DRIVER\n");
++		return ret;
+ 	}
+ 
+ 	return 0;

commit 90bc2af24638659da56397ff835f3c95a948f991
+Author: Alan Stern 
+Date:   Wed Jun 22 10:46:31 2022 -0400
+
+    USB: gadget: Fix double-free bug in raw_gadget driver
+    
+    Re-reading a recently merged fix to the raw_gadget driver showed that
+    it inadvertently introduced a double-free bug in a failure pathway.
+    If raw_ioctl_init() encounters an error after the driver ID number has
+    been allocated, it deallocates the ID number before returning.  But
+    when dev_free() runs later on, it will then try to deallocate the ID
+    number a second time.
+    
+    Closely related to this issue is another error in the recent fix: The
+    ID number is stored in the raw_dev structure before the code checks to
+    see whether the structure has already been initialized, in which case
+    the new ID number would overwrite the earlier value.
+    
+    The solution to both bugs is to keep the new ID number in a local
+    variable, and store it in the raw_dev structure only after the check
+    for prior initialization.  No errors can occur after that point, so
+    the double-free will never happen.
+    
+    Fixes: f2d8c2606825 ("usb: gadget: Fix non-unique driver names in raw-gadget driver")
+    CC: Andrey Konovalov 
+    CC: 
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/YrMrRw5AyIZghN0v@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/legacy/raw_gadget.c b/drivers/usb/gadget/legacy/raw_gadget.c
+index 5c8481cef35f..2acece16b890 100644
+--- a/drivers/usb/gadget/legacy/raw_gadget.c
++++ b/drivers/usb/gadget/legacy/raw_gadget.c
+@@ -430,6 +430,7 @@ static int raw_release(struct inode *inode, struct file *fd)
+ static int raw_ioctl_init(struct raw_dev *dev, unsigned long value)
+ {
+ 	int ret = 0;
++	int driver_id_number;
+ 	struct usb_raw_init arg;
+ 	char *udc_driver_name;
+ 	char *udc_device_name;
+@@ -452,10 +453,9 @@ static int raw_ioctl_init(struct raw_dev *dev, unsigned long value)
+ 		return -EINVAL;
+ 	}
+ 
+-	ret = ida_alloc(&driver_id_numbers, GFP_KERNEL);
+-	if (ret < 0)
+-		return ret;
+-	dev->driver_id_number = ret;
++	driver_id_number = ida_alloc(&driver_id_numbers, GFP_KERNEL);
++	if (driver_id_number < 0)
++		return driver_id_number;
+ 
+ 	driver_driver_name = kmalloc(DRIVER_DRIVER_NAME_LENGTH_MAX, GFP_KERNEL);
+ 	if (!driver_driver_name) {
+@@ -463,7 +463,7 @@ static int raw_ioctl_init(struct raw_dev *dev, unsigned long value)
+ 		goto out_free_driver_id_number;
+ 	}
+ 	snprintf(driver_driver_name, DRIVER_DRIVER_NAME_LENGTH_MAX,
+-				DRIVER_NAME ".%d", dev->driver_id_number);
++				DRIVER_NAME ".%d", driver_id_number);
+ 
+ 	udc_driver_name = kmalloc(UDC_NAME_LENGTH_MAX, GFP_KERNEL);
+ 	if (!udc_driver_name) {
+@@ -507,6 +507,7 @@ static int raw_ioctl_init(struct raw_dev *dev, unsigned long value)
+ 	dev->driver.driver.name = driver_driver_name;
+ 	dev->driver.udc_name = udc_device_name;
+ 	dev->driver.match_existing_only = 1;
++	dev->driver_id_number = driver_id_number;
+ 
+ 	dev->state = STATE_DEV_INITIALIZED;
+ 	spin_unlock_irqrestore(&dev->lock, flags);
+@@ -521,7 +522,7 @@ static int raw_ioctl_init(struct raw_dev *dev, unsigned long value)
+ out_free_driver_driver_name:
+ 	kfree(driver_driver_name);
+ out_free_driver_id_number:
+-	ida_free(&driver_id_numbers, dev->driver_id_number);
++	ida_free(&driver_id_numbers, driver_id_number);
+ 	return ret;
+ }
+ 

commit f2d8c2606825317b77db1f9ba0fc26ef26160b30
+Author: Alan Stern 
+Date:   Mon Jun 13 10:17:03 2022 -0400
+
+    usb: gadget: Fix non-unique driver names in raw-gadget driver
+    
+    In a report for a separate bug (which has already been fixed by commit
+    5f0b5f4d50fa "usb: gadget: fix race when gadget driver register via
+    ioctl") in the raw-gadget driver, the syzbot console log included
+    error messages caused by attempted registration of a new driver with
+    the same name as an existing driver:
+    
+    > kobject_add_internal failed for raw-gadget with -EEXIST, don't try to register things with the same name in the same directory.
+    > UDC core: USB Raw Gadget: driver registration failed: -17
+    > misc raw-gadget: fail, usb_gadget_register_driver returned -17
+    
+    These errors arise because raw_gadget.c registers a separate UDC
+    driver for each of the UDC instances it creates, but these drivers all
+    have the same name: "raw-gadget".  Until recently this wasn't a
+    problem, but when the "gadget" bus was added and UDC drivers were
+    registered on this bus, it became possible for name conflicts to cause
+    the registrations to fail.  The reason is simply that the bus code in
+    the driver core uses the driver name as a sysfs directory name (e.g.,
+    /sys/bus/gadget/drivers/raw-gadget/), and you can't create two
+    directories with the same pathname.
+    
+    To fix this problem, the driver names used by raw-gadget are made
+    distinct by appending a unique ID number: "raw-gadget.N", with a
+    different value of N for each driver instance.  And to avoid the
+    proliferation of error handling code in the raw_ioctl_init() routine,
+    the error return paths are refactored into the common pattern (goto
+    statements leading to cleanup code at the end of the routine).
+    
+    Link: https://lore.kernel.org/all/0000000000008c664105dffae2eb@google.com/
+    Fixes: fc274c1e9973 "USB: gadget: Add a new bus for gadgets"
+    CC: Andrey Konovalov 
+    CC: 
+    Reported-and-tested-by: syzbot+02b16343704b3af1667e@syzkaller.appspotmail.com
+    Reviewed-by: Andrey Konovalov 
+    Acked-by: Hillf Danton 
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/YqdG32w+3h8c1s7z@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/legacy/raw_gadget.c b/drivers/usb/gadget/legacy/raw_gadget.c
+index 241740024c50..5c8481cef35f 100644
+--- a/drivers/usb/gadget/legacy/raw_gadget.c
++++ b/drivers/usb/gadget/legacy/raw_gadget.c
+@@ -11,6 +11,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -36,6 +37,9 @@ MODULE_LICENSE("GPL");
+ 
+ /*----------------------------------------------------------------------*/
+ 
++static DEFINE_IDA(driver_id_numbers);
++#define DRIVER_DRIVER_NAME_LENGTH_MAX	32
++
+ #define RAW_EVENT_QUEUE_SIZE	16
+ 
+ struct raw_event_queue {
+@@ -161,6 +165,9 @@ struct raw_dev {
+ 	/* Reference to misc device: */
+ 	struct device			*dev;
+ 
++	/* Make driver names unique */
++	int				driver_id_number;
++
+ 	/* Protected by lock: */
+ 	enum dev_state			state;
+ 	bool				gadget_registered;
+@@ -189,6 +196,7 @@ static struct raw_dev *dev_new(void)
+ 	spin_lock_init(&dev->lock);
+ 	init_completion(&dev->ep0_done);
+ 	raw_event_queue_init(&dev->queue);
++	dev->driver_id_number = -1;
+ 	return dev;
+ }
+ 
+@@ -199,6 +207,9 @@ static void dev_free(struct kref *kref)
+ 
+ 	kfree(dev->udc_name);
+ 	kfree(dev->driver.udc_name);
++	kfree(dev->driver.driver.name);
++	if (dev->driver_id_number >= 0)
++		ida_free(&driver_id_numbers, dev->driver_id_number);
+ 	if (dev->req) {
+ 		if (dev->ep0_urb_queued)
+ 			usb_ep_dequeue(dev->gadget->ep0, dev->req);
+@@ -422,6 +433,7 @@ static int raw_ioctl_init(struct raw_dev *dev, unsigned long value)
+ 	struct usb_raw_init arg;
+ 	char *udc_driver_name;
+ 	char *udc_device_name;
++	char *driver_driver_name;
+ 	unsigned long flags;
+ 
+ 	if (copy_from_user(&arg, (void __user *)value, sizeof(arg)))
+@@ -440,36 +452,44 @@ static int raw_ioctl_init(struct raw_dev *dev, unsigned long value)
+ 		return -EINVAL;
+ 	}
+ 
++	ret = ida_alloc(&driver_id_numbers, GFP_KERNEL);
++	if (ret < 0)
++		return ret;
++	dev->driver_id_number = ret;
++
++	driver_driver_name = kmalloc(DRIVER_DRIVER_NAME_LENGTH_MAX, GFP_KERNEL);
++	if (!driver_driver_name) {
++		ret = -ENOMEM;
++		goto out_free_driver_id_number;
++	}
++	snprintf(driver_driver_name, DRIVER_DRIVER_NAME_LENGTH_MAX,
++				DRIVER_NAME ".%d", dev->driver_id_number);
++
+ 	udc_driver_name = kmalloc(UDC_NAME_LENGTH_MAX, GFP_KERNEL);
+-	if (!udc_driver_name)
+-		return -ENOMEM;
++	if (!udc_driver_name) {
++		ret = -ENOMEM;
++		goto out_free_driver_driver_name;
++	}
+ 	ret = strscpy(udc_driver_name, &arg.driver_name[0],
+ 				UDC_NAME_LENGTH_MAX);
+-	if (ret < 0) {
+-		kfree(udc_driver_name);
+-		return ret;
+-	}
++	if (ret < 0)
++		goto out_free_udc_driver_name;
+ 	ret = 0;
+ 
+ 	udc_device_name = kmalloc(UDC_NAME_LENGTH_MAX, GFP_KERNEL);
+ 	if (!udc_device_name) {
+-		kfree(udc_driver_name);
+-		return -ENOMEM;
++		ret = -ENOMEM;
++		goto out_free_udc_driver_name;
+ 	}
+ 	ret = strscpy(udc_device_name, &arg.device_name[0],
+ 				UDC_NAME_LENGTH_MAX);
+-	if (ret < 0) {
+-		kfree(udc_driver_name);
+-		kfree(udc_device_name);
+-		return ret;
+-	}
++	if (ret < 0)
++		goto out_free_udc_device_name;
+ 	ret = 0;
+ 
+ 	spin_lock_irqsave(&dev->lock, flags);
+ 	if (dev->state != STATE_DEV_OPENED) {
+ 		dev_dbg(dev->dev, "fail, device is not opened\n");
+-		kfree(udc_driver_name);
+-		kfree(udc_device_name);
+ 		ret = -EINVAL;
+ 		goto out_unlock;
+ 	}
+@@ -484,14 +504,24 @@ static int raw_ioctl_init(struct raw_dev *dev, unsigned long value)
+ 	dev->driver.suspend = gadget_suspend;
+ 	dev->driver.resume = gadget_resume;
+ 	dev->driver.reset = gadget_reset;
+-	dev->driver.driver.name = DRIVER_NAME;
++	dev->driver.driver.name = driver_driver_name;
+ 	dev->driver.udc_name = udc_device_name;
+ 	dev->driver.match_existing_only = 1;
+ 
+ 	dev->state = STATE_DEV_INITIALIZED;
++	spin_unlock_irqrestore(&dev->lock, flags);
++	return ret;
+ 
+ out_unlock:
+ 	spin_unlock_irqrestore(&dev->lock, flags);
++out_free_udc_device_name:
++	kfree(udc_device_name);
++out_free_udc_driver_name:
++	kfree(udc_driver_name);
++out_free_driver_driver_name:
++	kfree(driver_driver_name);
++out_free_driver_id_number:
++	ida_free(&driver_id_numbers, dev->driver_id_number);
+ 	return ret;
+ }
+ 

commit f9d76d15072caf1ec5558fa7cc6d93c7b9d33488
+Author: Alan Stern 
+Date:   Tue May 10 11:51:29 2022 -0400
+
+    USB: gadget: Add ID numbers to gadget names
+    
+    Putting USB gadgets on a new bus of their own encounters a problem
+    when multiple gadgets are present: They all have the same name!  The
+    driver core fails with a "sys: cannot create duplicate filename" error
+    when creating any of the /sys/bus/gadget/devices/
+    symbolic links after the first.
+    
+    This patch fixes the problem by adding a ".N" suffix to each gadget's
+    name when the gadget is registered (where N is a unique ID number),
+    thus making the names distinct.
+    
+    Reported-and-tested-by: Geert Uytterhoeven 
+    Signed-off-by: Alan Stern 
+    Reviewed-by: Geert Uytterhoeven 
+    Fixes: fc274c1e9973 ("USB: gadget: Add a new bus for gadgets")
+    Link: https://lore.kernel.org/r/YnqKAXKyp9Vq/pbn@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
+index 3281d8a3dae7..7886497253cc 100644
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -12,6 +12,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -23,6 +24,8 @@
+ 
+ #include "trace.h"
+ 
++static DEFINE_IDA(gadget_id_numbers);
++
+ static struct bus_type gadget_bus_type;
+ 
+ /**
+@@ -1248,7 +1251,6 @@ static void usb_udc_nop_release(struct device *dev)
+ void usb_initialize_gadget(struct device *parent, struct usb_gadget *gadget,
+ 		void (*release)(struct device *dev))
+ {
+-	dev_set_name(&gadget->dev, "gadget");
+ 	INIT_WORK(&gadget->work, usb_gadget_state_work);
+ 	gadget->dev.parent = parent;
+ 
+@@ -1304,12 +1306,21 @@ int usb_add_gadget(struct usb_gadget *gadget)
+ 	usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
+ 	udc->vbus = true;
+ 
++	ret = ida_alloc(&gadget_id_numbers, GFP_KERNEL);
++	if (ret < 0)
++		goto err_del_udc;
++	gadget->id_number = ret;
++	dev_set_name(&gadget->dev, "gadget.%d", ret);
++
+ 	ret = device_add(&gadget->dev);
+ 	if (ret)
+-		goto err_del_udc;
++		goto err_free_id;
+ 
+ 	return 0;
+ 
++ err_free_id:
++	ida_free(&gadget_id_numbers, gadget->id_number);
++
+  err_del_udc:
+ 	flush_work(&gadget->work);
+ 	device_del(&udc->dev);
+@@ -1417,6 +1428,7 @@ void usb_del_gadget(struct usb_gadget *gadget)
+ 	kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
+ 	flush_work(&gadget->work);
+ 	device_del(&gadget->dev);
++	ida_free(&gadget_id_numbers, gadget->id_number);
+ 	device_unregister(&udc->dev);
+ }
+ EXPORT_SYMBOL_GPL(usb_del_gadget);
+diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
+index cf7af8a0a6e9..3ad58b7a0824 100644
+--- a/include/linux/usb/gadget.h
++++ b/include/linux/usb/gadget.h
+@@ -386,6 +386,7 @@ struct usb_gadget_ops {
+  * @lpm_capable: If the gadget max_speed is FULL or HIGH, this flag
+  *	indicates that it supports LPM as per the LPM ECN & errata.
+  * @irq: the interrupt number for device controller.
++ * @id_number: a unique ID number for ensuring that gadget names are distinct
+  *
+  * Gadgets have a mostly-portable "gadget driver" implementing device
+  * functions, handling all usb configurations and interfaces.  Gadget
+@@ -446,6 +447,7 @@ struct usb_gadget {
+ 	unsigned			connected:1;
+ 	unsigned			lpm_capable:1;
+ 	int				irq;
++	int				id_number;
+ };
+ #define work_to_gadget(w)	(container_of((w), struct usb_gadget, work))
+ 

commit fc274c1e997314bf47f6a62c79b5d7e554ed59c4
+Author: Alan Stern 
+Date:   Sat Apr 23 21:35:51 2022 -0400
+
+    USB: gadget: Add a new bus for gadgets
+    
+    This patch adds a "gadget" bus and uses it for registering gadgets and
+    their drivers.  From now on, bindings will be managed by the driver
+    core rather than through ad-hoc manipulations in the UDC core.
+    
+    As part of this change, the driver_pending_list is removed.  The UDC
+    core won't need to keep track of unbound drivers for later binding,
+    because the driver core handles all of that for us.
+    
+    However, we do need one new feature: a way to prevent gadget drivers
+    from being bound to more than one gadget at a time.  The existing code
+    does this automatically, but the driver core doesn't -- it's perfectly
+    happy to bind a single driver to all the matching devices on the bus.
+    The patch adds a new bitflag to the usb_gadget_driver structure for
+    this purpose.
+    
+    A nice side effect of this change is a reduction in the total lines of
+    code, since now the driver core will do part of the work that the UDC
+    used to do.
+    
+    A possible future patch could add udc devices to the gadget bus, say
+    as a separate device type.
+    
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/YmSpdxaDNeC2BBOf@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
+index a878e7afacdd..61790592b2c8 100644
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -23,6 +23,8 @@
+ 
+ #include "trace.h"
+ 
++static struct bus_type gadget_bus_type;
++
+ /**
+  * struct usb_udc - describes one usb device controller
+  * @driver: the gadget driver pointer. For use by the class code
+@@ -47,11 +49,9 @@ struct usb_udc {
+ 
+ static struct class *udc_class;
+ static LIST_HEAD(udc_list);
+-static LIST_HEAD(gadget_driver_pending_list);
+-static DEFINE_MUTEX(udc_lock);
+ 
+-static int udc_bind_to_driver(struct usb_udc *udc,
+-		struct usb_gadget_driver *driver);
++/* Protects udc_list, udc->driver, driver->is_bound, and related calls */
++static DEFINE_MUTEX(udc_lock);
+ 
+ /* ------------------------------------------------------------------------- */
+ 
+@@ -1238,24 +1238,6 @@ static void usb_udc_nop_release(struct device *dev)
+ 	dev_vdbg(dev, "%s\n", __func__);
+ }
+ 
+-/* should be called with udc_lock held */
+-static int check_pending_gadget_drivers(struct usb_udc *udc)
+-{
+-	struct usb_gadget_driver *driver;
+-	int ret = 0;
+-
+-	list_for_each_entry(driver, &gadget_driver_pending_list, pending)
+-		if (!driver->udc_name || strcmp(driver->udc_name,
+-						dev_name(&udc->dev)) == 0) {
+-			ret = udc_bind_to_driver(udc, driver);
+-			if (ret != -EPROBE_DEFER)
+-				list_del_init(&driver->pending);
+-			break;
+-		}
+-
+-	return ret;
+-}
+-
+ /**
+  * usb_initialize_gadget - initialize a gadget and its embedded struct device
+  * @parent: the parent device to this udc. Usually the controller driver's
+@@ -1276,6 +1258,7 @@ void usb_initialize_gadget(struct device *parent, struct usb_gadget *gadget,
+ 		gadget->dev.release = usb_udc_nop_release;
+ 
+ 	device_initialize(&gadget->dev);
++	gadget->dev.bus = &gadget_bus_type;
+ }
+ EXPORT_SYMBOL_GPL(usb_initialize_gadget);
+ 
+@@ -1312,6 +1295,7 @@ int usb_add_gadget(struct usb_gadget *gadget)
+ 
+ 	mutex_lock(&udc_lock);
+ 	list_add_tail(&udc->list, &udc_list);
++	mutex_unlock(&udc_lock);
+ 
+ 	ret = device_add(&udc->dev);
+ 	if (ret)
+@@ -1324,23 +1308,14 @@ int usb_add_gadget(struct usb_gadget *gadget)
+ 	if (ret)
+ 		goto err_del_udc;
+ 
+-	/* pick up one of pending gadget drivers */
+-	ret = check_pending_gadget_drivers(udc);
+-	if (ret)
+-		goto err_del_gadget;
+-
+-	mutex_unlock(&udc_lock);
+-
+ 	return 0;
+ 
+- err_del_gadget:
+-	device_del(&gadget->dev);
+-
+  err_del_udc:
+ 	flush_work(&gadget->work);
+ 	device_del(&udc->dev);
+ 
+  err_unlist_udc:
++	mutex_lock(&udc_lock);
+ 	list_del(&udc->list);
+ 	mutex_unlock(&udc_lock);
+ 
+@@ -1419,24 +1394,6 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
+ }
+ EXPORT_SYMBOL_GPL(usb_add_gadget_udc);
+ 
+-static void usb_gadget_remove_driver(struct usb_udc *udc)
+-{
+-	dev_dbg(&udc->dev, "unregistering UDC driver [%s]\n",
+-			udc->driver->function);
+-
+-	kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
+-
+-	usb_gadget_disconnect(udc->gadget);
+-	usb_gadget_disable_async_callbacks(udc);
+-	if (udc->gadget->irq)
+-		synchronize_irq(udc->gadget->irq);
+-	udc->driver->unbind(udc->gadget);
+-	usb_gadget_udc_stop(udc);
+-
+-	udc->driver = NULL;
+-	udc->gadget->dev.driver = NULL;
+-}
+-
+ /**
+  * usb_del_gadget - deletes a gadget and unregisters its udc
+  * @gadget: the gadget to be deleted.
+@@ -1455,13 +1412,6 @@ void usb_del_gadget(struct usb_gadget *gadget)
+ 
+ 	mutex_lock(&udc_lock);
+ 	list_del(&udc->list);
+-
+-	if (udc->driver) {
+-		struct usb_gadget_driver *driver = udc->driver;
+-
+-		usb_gadget_remove_driver(udc);
+-		list_add(&driver->pending, &gadget_driver_pending_list);
+-	}
+ 	mutex_unlock(&udc_lock);
+ 
+ 	kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
+@@ -1486,123 +1436,147 @@ EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
+ 
+ /* ------------------------------------------------------------------------- */
+ 
+-static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver)
++static int gadget_match_driver(struct device *dev, struct device_driver *drv)
+ {
+-	int ret;
++	struct usb_gadget *gadget = dev_to_usb_gadget(dev);
++	struct usb_udc *udc = gadget->udc;
++	struct usb_gadget_driver *driver = container_of(drv,
++			struct usb_gadget_driver, driver);
++
++	/* If the driver specifies a udc_name, it must match the UDC's name */
++	if (driver->udc_name &&
++			strcmp(driver->udc_name, dev_name(&udc->dev)) != 0)
++		return 0;
++
++	/* If the driver is already bound to a gadget, it doesn't match */
++	if (driver->is_bound)
++		return 0;
++
++	/* Otherwise any gadget driver matches any UDC */
++	return 1;
++}
+ 
+-	dev_dbg(&udc->dev, "registering UDC driver [%s]\n",
+-			driver->function);
++static int gadget_bind_driver(struct device *dev)
++{
++	struct usb_gadget *gadget = dev_to_usb_gadget(dev);
++	struct usb_udc *udc = gadget->udc;
++	struct usb_gadget_driver *driver = container_of(dev->driver,
++			struct usb_gadget_driver, driver);
++	int ret = 0;
+ 
++	mutex_lock(&udc_lock);
++	if (driver->is_bound) {
++		mutex_unlock(&udc_lock);
++		return -ENXIO;		/* Driver binds to only one gadget */
++	}
++	driver->is_bound = true;
+ 	udc->driver = driver;
+-	udc->gadget->dev.driver = &driver->driver;
++	mutex_unlock(&udc_lock);
++
++	dev_dbg(&udc->dev, "binding gadget driver [%s]\n", driver->function);
+ 
+ 	usb_gadget_udc_set_speed(udc, driver->max_speed);
+ 
++	mutex_lock(&udc_lock);
+ 	ret = driver->bind(udc->gadget, driver);
+ 	if (ret)
+-		goto err1;
++		goto err_bind;
++
+ 	ret = usb_gadget_udc_start(udc);
+-	if (ret) {
+-		driver->unbind(udc->gadget);
+-		goto err1;
+-	}
++	if (ret)
++		goto err_start;
+ 	usb_gadget_enable_async_callbacks(udc);
+ 	usb_udc_connect_control(udc);
++	mutex_unlock(&udc_lock);
+ 
+ 	kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
+ 	return 0;
+-err1:
++
++ err_start:
++	driver->unbind(udc->gadget);
++
++ err_bind:
+ 	if (ret != -EISNAM)
+ 		dev_err(&udc->dev, "failed to start %s: %d\n",
+-			udc->driver->function, ret);
++			driver->function, ret);
++
+ 	udc->driver = NULL;
+-	udc->gadget->dev.driver = NULL;
++	driver->is_bound = false;
++	mutex_unlock(&udc_lock);
++
+ 	return ret;
+ }
+ 
+-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
++static void gadget_unbind_driver(struct device *dev)
++{
++	struct usb_gadget *gadget = dev_to_usb_gadget(dev);
++	struct usb_udc *udc = gadget->udc;
++	struct usb_gadget_driver *driver = udc->driver;
++
++	dev_dbg(&udc->dev, "unbinding gadget driver [%s]\n", driver->function);
++
++	kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
++
++	mutex_lock(&udc_lock);
++	usb_gadget_disconnect(gadget);
++	usb_gadget_disable_async_callbacks(udc);
++	if (gadget->irq)
++		synchronize_irq(gadget->irq);
++	udc->driver->unbind(gadget);
++	usb_gadget_udc_stop(udc);
++
++	driver->is_bound = false;
++	udc->driver = NULL;
++	mutex_unlock(&udc_lock);
++}
++
++/* ------------------------------------------------------------------------- */
++
++int usb_gadget_register_driver_owner(struct usb_gadget_driver *driver,
++		struct module *owner, const char *mod_name)
+ {
+-	struct usb_udc		*udc = NULL, *iter;
+-	int			ret = -ENODEV;
++	int ret;
+ 
+ 	if (!driver || !driver->bind || !driver->setup)
+ 		return -EINVAL;
+ 
++	driver->driver.bus = &gadget_bus_type;
++	driver->driver.owner = owner;
++	driver->driver.mod_name = mod_name;
++	ret = driver_register(&driver->driver);
++	if (ret) {
++		pr_warn("%s: driver registration failed: %d\n",
++				driver->function, ret);
++		return ret;
++	}
++
+ 	mutex_lock(&udc_lock);
+-	if (driver->udc_name) {
+-		list_for_each_entry(iter, &udc_list, list) {
+-			ret = strcmp(driver->udc_name, dev_name(&iter->dev));
+-			if (ret)
+-				continue;
+-			udc = iter;
+-			break;
+-		}
+-		if (ret)
+-			ret = -ENODEV;
+-		else if (udc->driver)
++	if (!driver->is_bound) {
++		if (driver->match_existing_only) {
++			pr_warn("%s: couldn't find an available UDC or it's busy\n",
++					driver->function);
+ 			ret = -EBUSY;
+-		else
+-			goto found;
+-	} else {
+-		list_for_each_entry(iter, &udc_list, list) {
+-			/* For now we take the first one */
+-			if (iter->driver)
+-				continue;
+-			udc = iter;
+-			goto found;
++		} else {
++			pr_info("%s: couldn't find an available UDC\n",
++					driver->function);
+ 		}
+-	}
+-
+-	if (!driver->match_existing_only) {
+-		list_add_tail(&driver->pending, &gadget_driver_pending_list);
+-		pr_info("couldn't find an available UDC - added [%s] to list of pending drivers\n",
+-			driver->function);
+ 		ret = 0;
+ 	}
+-
+ 	mutex_unlock(&udc_lock);
++
+ 	if (ret)
+-		pr_warn("couldn't find an available UDC or it's busy: %d\n", ret);
+-	return ret;
+-found:
+-	ret = udc_bind_to_driver(udc, driver);
+-	mutex_unlock(&udc_lock);
++		driver_unregister(&driver->driver);
+ 	return ret;
+ }
+-EXPORT_SYMBOL_GPL(usb_gadget_register_driver);
++EXPORT_SYMBOL_GPL(usb_gadget_register_driver_owner);
+ 
+ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+ {
+-	struct usb_udc		*udc = NULL;
+-	int			ret = -ENODEV;
+-
+ 	if (!driver || !driver->unbind)
+ 		return -EINVAL;
+ 
+-	mutex_lock(&udc_lock);
+-	list_for_each_entry(udc, &udc_list, list) {
+-		if (udc->driver == driver) {
+-			usb_gadget_remove_driver(udc);
+-			usb_gadget_set_state(udc->gadget,
+-					     USB_STATE_NOTATTACHED);
+-
+-			/* Maybe there is someone waiting for this UDC? */
+-			check_pending_gadget_drivers(udc);
+-			/*
+-			 * For now we ignore bind errors as probably it's
+-			 * not a valid reason to fail other's gadget unbind
+-			 */
+-			ret = 0;
+-			break;
+-		}
+-	}
+-
+-	if (ret) {
+-		list_del(&driver->pending);
+-		ret = 0;
+-	}
+-	mutex_unlock(&udc_lock);
+-	return ret;
++	driver_unregister(&driver->driver);
++	return 0;
+ }
+ EXPORT_SYMBOL_GPL(usb_gadget_unregister_driver);
+ 
+@@ -1754,8 +1728,17 @@ static int usb_udc_uevent(struct device *dev, struct kobj_uevent_env *env)
+ 	return 0;
+ }
+ 
++static struct bus_type gadget_bus_type = {
++	.name = "gadget",
++	.probe = gadget_bind_driver,
++	.remove = gadget_unbind_driver,
++	.match = gadget_match_driver,
++};
++
+ static int __init usb_udc_init(void)
+ {
++	int rc;
++
+ 	udc_class = class_create(THIS_MODULE, "udc");
+ 	if (IS_ERR(udc_class)) {
+ 		pr_err("failed to create udc class --> %ld\n",
+@@ -1764,12 +1747,17 @@ static int __init usb_udc_init(void)
+ 	}
+ 
+ 	udc_class->dev_uevent = usb_udc_uevent;
+-	return 0;
++
++	rc = bus_register(&gadget_bus_type);
++	if (rc)
++		class_destroy(udc_class);
++	return rc;
+ }
+ subsys_initcall(usb_udc_init);
+ 
+ static void __exit usb_udc_exit(void)
+ {
++	bus_unregister(&gadget_bus_type);
+ 	class_destroy(udc_class);
+ }
+ module_exit(usb_udc_exit);
+diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
+index 5830b8a903da..cf7af8a0a6e9 100644
+--- a/include/linux/usb/gadget.h
++++ b/include/linux/usb/gadget.h
+@@ -664,9 +664,9 @@ static inline int usb_gadget_check_config(struct usb_gadget *gadget)
+  * @driver: Driver model state for this driver.
+  * @udc_name: A name of UDC this driver should be bound to. If udc_name is NULL,
+  *	this driver will be bound to any available UDC.
+- * @pending: UDC core private data used for deferred probe of this driver.
+- * @match_existing_only: If udc is not found, return an error and don't add this
+- *      gadget driver to list of pending driver
++ * @match_existing_only: If udc is not found, return an error and fail
++ *	the driver registration
++ * @is_bound: Allow a driver to be bound to only one gadget
+  *
+  * Devices are disabled till a gadget driver successfully bind()s, which
+  * means the driver will handle setup() requests needed to enumerate (and
+@@ -729,8 +729,8 @@ struct usb_gadget_driver {
+ 	struct device_driver	driver;
+ 
+ 	char			*udc_name;
+-	struct list_head	pending;
+ 	unsigned                match_existing_only:1;
++	bool			is_bound:1;
+ };
+ 
+ 
+@@ -740,22 +740,30 @@ struct usb_gadget_driver {
+ /* driver modules register and unregister, as usual.
+  * these calls must be made in a context that can sleep.
+  *
+- * these will usually be implemented directly by the hardware-dependent
+- * usb bus interface driver, which will only support a single driver.
++ * A gadget driver can be bound to only one gadget at a time.
+  */
+ 
+ /**
+- * usb_gadget_register_driver - register a gadget driver
++ * usb_gadget_register_driver_owner - register a gadget driver
+  * @driver: the driver being registered
++ * @owner: the driver module
++ * @mod_name: the driver module's build name
+  * Context: can sleep
+  *
+  * Call this in your gadget driver's module initialization function,
+- * to tell the underlying usb controller driver about your driver.
++ * to tell the underlying UDC controller driver about your driver.
+  * The @bind() function will be called to bind it to a gadget before this
+  * registration call returns.  It's expected that the @bind() function will
+  * be in init sections.
++ *
++ * Use the macro defined below instead of calling this directly.
+  */
+-int usb_gadget_register_driver(struct usb_gadget_driver *driver);
++int usb_gadget_register_driver_owner(struct usb_gadget_driver *driver,
++		struct module *owner, const char *mod_name);
++
++/* use a define to avoid include chaining to get THIS_MODULE & friends */
++#define usb_gadget_register_driver(driver) \
++	usb_gadget_register_driver_owner(driver, THIS_MODULE, KBUILD_MODNAME)
+ 
+ /**
+  * usb_gadget_unregister_driver - unregister a gadget driver

commit d59f6d958596b54b722605657c3b56a79843695a
+Author: Alan Stern 
+Date:   Sat Apr 23 21:34:34 2022 -0400
+
+    USB: gadget: Fix mistakes in UDC core kerneldoc
+    
+    This patch fixes some minor mistakes in the UDC core's kerneldoc.
+    
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/YmSpKpnWR8WWEk/p@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
+index 014daa07eb8c..a878e7afacdd 100644
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -1262,9 +1262,6 @@ static int check_pending_gadget_drivers(struct usb_udc *udc)
+  * device.
+  * @gadget: the gadget to be initialized.
+  * @release: a gadget release function.
+- *
+- * Returns zero on success, negative errno otherwise.
+- * Calls the gadget release function in the latter case.
+  */
+ void usb_initialize_gadget(struct device *parent, struct usb_gadget *gadget,
+ 		void (*release)(struct device *dev))
+@@ -1441,11 +1438,10 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
+ }
+ 
+ /**
+- * usb_del_gadget - deletes @udc from udc_list
+- * @gadget: the gadget to be removed.
++ * usb_del_gadget - deletes a gadget and unregisters its udc
++ * @gadget: the gadget to be deleted.
+  *
+- * This will call usb_gadget_unregister_driver() if
+- * the @udc is still busy.
++ * This will unbind @gadget, if it is bound.
+  * It will not do a final usb_put_gadget().
+  */
+ void usb_del_gadget(struct usb_gadget *gadget)
+@@ -1476,8 +1472,8 @@ void usb_del_gadget(struct usb_gadget *gadget)
+ EXPORT_SYMBOL_GPL(usb_del_gadget);
+ 
+ /**
+- * usb_del_gadget_udc - deletes @udc from udc_list
+- * @gadget: the gadget to be removed.
++ * usb_del_gadget_udc - unregisters a gadget
++ * @gadget: the gadget to be unregistered.
+  *
+  * Calls usb_del_gadget() and does a final usb_put_gadget().
+  */

commit 6ebb449f9f25e0da804d1247b4ffcc361321494d
+Author: Alan Stern 
+Date:   Sat Apr 23 21:33:29 2022 -0400
+
+    USB: gadget: Register udc before gadget
+    
+    In preparation for adding a "gadget" bus, this patch reverses the
+    order of registration of udc and gadget devices in usb_add_gadget().
+    
+    The current code adds the gadget device first, probably because that
+    was more convenient at the time and the order didn't really matter.
+    But with the upcoming change, adding the gadget will cause driver
+    probing to occur.  Unwinding that on the error pathway will become
+    much more obtrusive, not to mention the fact that a gadget driver
+    might not work properly before the udc is registered.  It's better to
+    register the udc device first, particularly since that doesn't involve
+    a bus or driver binding and therefore is simpler to unwind.
+    
+    For symmetry, the order of unregistration in usb_del_gadget() is
+    likewise reversed.
+    
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/YmSo6fU1FlNq8cOZ@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
+index f0cce482b74a..014daa07eb8c 100644
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -1308,10 +1308,6 @@ int usb_add_gadget(struct usb_gadget *gadget)
+ 	if (ret)
+ 		goto err_put_udc;
+ 
+-	ret = device_add(&gadget->dev);
+-	if (ret)
+-		goto err_put_udc;
+-
+ 	udc->gadget = gadget;
+ 	gadget->udc = udc;
+ 
+@@ -1327,15 +1323,22 @@ int usb_add_gadget(struct usb_gadget *gadget)
+ 	usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
+ 	udc->vbus = true;
+ 
++	ret = device_add(&gadget->dev);
++	if (ret)
++		goto err_del_udc;
++
+ 	/* pick up one of pending gadget drivers */
+ 	ret = check_pending_gadget_drivers(udc);
+ 	if (ret)
+-		goto err_del_udc;
++		goto err_del_gadget;
+ 
+ 	mutex_unlock(&udc_lock);
+ 
+ 	return 0;
+ 
++ err_del_gadget:
++	device_del(&gadget->dev);
++
+  err_del_udc:
+ 	flush_work(&gadget->work);
+ 	device_del(&udc->dev);
+@@ -1344,8 +1347,6 @@ int usb_add_gadget(struct usb_gadget *gadget)
+ 	list_del(&udc->list);
+ 	mutex_unlock(&udc_lock);
+ 
+-	device_del(&gadget->dev);
+-
+  err_put_udc:
+ 	put_device(&udc->dev);
+ 
+@@ -1469,8 +1470,8 @@ void usb_del_gadget(struct usb_gadget *gadget)
+ 
+ 	kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
+ 	flush_work(&gadget->work);
+-	device_unregister(&udc->dev);
+ 	device_del(&gadget->dev);
++	device_unregister(&udc->dev);
+ }
+ EXPORT_SYMBOL_GPL(usb_del_gadget);
+ 

commit af1969a2d734d6272c0640b50c3ed31e59e203a9
+Author: Alan Stern 
+Date:   Sat Apr 23 20:42:03 2022 -0400
+
+    USB: gadget: Rename usb_gadget_probe_driver()
+    
+    In preparation for adding a "gadget" bus, this patch renames
+    usb_gadget_probe_driver() to usb_gadget_register_driver().  The new
+    name will be more accurate, since gadget drivers will be registered on
+    the gadget bus and the probing will be done by the driver core, not
+    the UDC core.
+    
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/YmSc29YZvxgT5fEJ@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
+index 2eaeaae96759..403563c06477 100644
+--- a/drivers/usb/gadget/composite.c
++++ b/drivers/usb/gadget/composite.c
+@@ -2505,7 +2505,7 @@ int usb_composite_probe(struct usb_composite_driver *driver)
+ 	gadget_driver->driver.name = driver->name;
+ 	gadget_driver->max_speed = driver->max_speed;
+ 
+-	return usb_gadget_probe_driver(gadget_driver);
++	return usb_gadget_register_driver(gadget_driver);
+ }
+ EXPORT_SYMBOL_GPL(usb_composite_probe);
+ 
+diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
+index 1fb837d9271e..4141206bb0ed 100644
+--- a/drivers/usb/gadget/configfs.c
++++ b/drivers/usb/gadget/configfs.c
+@@ -284,7 +284,7 @@ static ssize_t gadget_dev_desc_UDC_store(struct config_item *item,
+ 			goto err;
+ 		}
+ 		gi->composite.gadget_driver.udc_name = name;
+-		ret = usb_gadget_probe_driver(&gi->composite.gadget_driver);
++		ret = usb_gadget_register_driver(&gi->composite.gadget_driver);
+ 		if (ret) {
+ 			gi->composite.gadget_driver.udc_name = NULL;
+ 			goto err;
+diff --git a/drivers/usb/gadget/legacy/dbgp.c b/drivers/usb/gadget/legacy/dbgp.c
+index 6bcbad382580..b62e45235e8e 100644
+--- a/drivers/usb/gadget/legacy/dbgp.c
++++ b/drivers/usb/gadget/legacy/dbgp.c
+@@ -422,7 +422,7 @@ static struct usb_gadget_driver dbgp_driver = {
+ 
+ static int __init dbgp_init(void)
+ {
+-	return usb_gadget_probe_driver(&dbgp_driver);
++	return usb_gadget_register_driver(&dbgp_driver);
+ }
+ 
+ static void __exit dbgp_exit(void)
+diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
+index 0c01e749f9ea..79990597c39f 100644
+--- a/drivers/usb/gadget/legacy/inode.c
++++ b/drivers/usb/gadget/legacy/inode.c
+@@ -1873,7 +1873,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
+ 	else
+ 		gadgetfs_driver.max_speed = USB_SPEED_FULL;
+ 
+-	value = usb_gadget_probe_driver(&gadgetfs_driver);
++	value = usb_gadget_register_driver(&gadgetfs_driver);
+ 	if (value != 0) {
+ 		spin_lock_irq(&dev->lock);
+ 		goto fail;
+diff --git a/drivers/usb/gadget/legacy/raw_gadget.c b/drivers/usb/gadget/legacy/raw_gadget.c
+index 8d40a1f2ec57..b3be8db1ff63 100644
+--- a/drivers/usb/gadget/legacy/raw_gadget.c
++++ b/drivers/usb/gadget/legacy/raw_gadget.c
+@@ -510,12 +510,12 @@ static int raw_ioctl_run(struct raw_dev *dev, unsigned long value)
+ 	}
+ 	spin_unlock_irqrestore(&dev->lock, flags);
+ 
+-	ret = usb_gadget_probe_driver(&dev->driver);
++	ret = usb_gadget_register_driver(&dev->driver);
+ 
+ 	spin_lock_irqsave(&dev->lock, flags);
+ 	if (ret) {
+ 		dev_err(dev->dev,
+-			"fail, usb_gadget_probe_driver returned %d\n", ret);
++			"fail, usb_gadget_register_driver returned %d\n", ret);
+ 		dev->state = STATE_DEV_FAILED;
+ 		goto out_unlock;
+ 	}
+diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
+index 85b194011a16..f0cce482b74a 100644
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -1523,7 +1523,7 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
+ 	return ret;
+ }
+ 
+-int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
++int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+ {
+ 	struct usb_udc		*udc = NULL, *iter;
+ 	int			ret = -ENODEV;
+@@ -1572,7 +1572,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
+ 	mutex_unlock(&udc_lock);
+ 	return ret;
+ }
+-EXPORT_SYMBOL_GPL(usb_gadget_probe_driver);
++EXPORT_SYMBOL_GPL(usb_gadget_register_driver);
+ 
+ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+ {
+diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
+index 10fe57cf40be..5830b8a903da 100644
+--- a/include/linux/usb/gadget.h
++++ b/include/linux/usb/gadget.h
+@@ -745,7 +745,7 @@ struct usb_gadget_driver {
+  */
+ 
+ /**
+- * usb_gadget_probe_driver - probe a gadget driver
++ * usb_gadget_register_driver - register a gadget driver
+  * @driver: the driver being registered
+  * Context: can sleep
+  *
+@@ -755,7 +755,7 @@ struct usb_gadget_driver {
+  * registration call returns.  It's expected that the @bind() function will
+  * be in init sections.
+  */
+-int usb_gadget_probe_driver(struct usb_gadget_driver *driver);
++int usb_gadget_register_driver(struct usb_gadget_driver *driver);
+ 
+ /**
+  * usb_gadget_unregister_driver - unregister a gadget driver

commit 1892bf90677abcad7f06e897e308f5c3e3618dd4
+Author: Alan Stern 
+Date:   Thu Mar 17 16:39:10 2022 -0400
+
+    USB: usb-storage: Fix use of bitfields for hardware data in ene_ub6250.c
+    
+    The kernel test robot found a problem with the ene_ub6250 subdriver in
+    usb-storage: It uses structures containing bitfields to represent
+    hardware bits in its SD_STATUS, MS_STATUS, and SM_STATUS bytes.  This
+    is not safe; it presumes a particular bit ordering and it assumes the
+    compiler will not insert padding, neither of which is guaranteed.
+    
+    This patch fixes the problem by changing the structures to simple u8
+    values, with the bitfields replaced by bitmask constants.
+    
+    CC: 
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/YjOcbuU106UpJ/V8@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c
+index 5f7d678502be..6012603f3630 100644
+--- a/drivers/usb/storage/ene_ub6250.c
++++ b/drivers/usb/storage/ene_ub6250.c
+@@ -237,36 +237,33 @@ static struct us_unusual_dev ene_ub6250_unusual_dev_list[] = {
+ #define memstick_logaddr(logadr1, logadr0) ((((u16)(logadr1)) << 8) | (logadr0))
+ 
+ 
+-struct SD_STATUS {
+-	u8    Insert:1;
+-	u8    Ready:1;
+-	u8    MediaChange:1;
+-	u8    IsMMC:1;
+-	u8    HiCapacity:1;
+-	u8    HiSpeed:1;
+-	u8    WtP:1;
+-	u8    Reserved:1;
+-};
+-
+-struct MS_STATUS {
+-	u8    Insert:1;
+-	u8    Ready:1;
+-	u8    MediaChange:1;
+-	u8    IsMSPro:1;
+-	u8    IsMSPHG:1;
+-	u8    Reserved1:1;
+-	u8    WtP:1;
+-	u8    Reserved2:1;
+-};
+-
+-struct SM_STATUS {
+-	u8    Insert:1;
+-	u8    Ready:1;
+-	u8    MediaChange:1;
+-	u8    Reserved:3;
+-	u8    WtP:1;
+-	u8    IsMS:1;
+-};
++/* SD_STATUS bits */
++#define SD_Insert	BIT(0)
++#define SD_Ready	BIT(1)
++#define SD_MediaChange	BIT(2)
++#define SD_IsMMC	BIT(3)
++#define SD_HiCapacity	BIT(4)
++#define SD_HiSpeed	BIT(5)
++#define SD_WtP		BIT(6)
++			/* Bit 7 reserved */
++
++/* MS_STATUS bits */
++#define MS_Insert	BIT(0)
++#define MS_Ready	BIT(1)
++#define MS_MediaChange	BIT(2)
++#define MS_IsMSPro	BIT(3)
++#define MS_IsMSPHG	BIT(4)
++			/* Bit 5 reserved */
++#define MS_WtP		BIT(6)
++			/* Bit 7 reserved */
++
++/* SM_STATUS bits */
++#define SM_Insert	BIT(0)
++#define SM_Ready	BIT(1)
++#define SM_MediaChange	BIT(2)
++			/* Bits 3-5 reserved */
++#define SM_WtP		BIT(6)
++#define SM_IsMS		BIT(7)
+ 
+ struct ms_bootblock_cis {
+ 	u8 bCistplDEVICE[6];    /* 0 */
+@@ -437,9 +434,9 @@ struct ene_ub6250_info {
+ 	u8		*bbuf;
+ 
+ 	/* for 6250 code */
+-	struct SD_STATUS	SD_Status;
+-	struct MS_STATUS	MS_Status;
+-	struct SM_STATUS	SM_Status;
++	u8		SD_Status;
++	u8		MS_Status;
++	u8		SM_Status;
+ 
+ 	/* ----- SD Control Data ---------------- */
+ 	/*SD_REGISTER SD_Regs; */
+@@ -602,7 +599,7 @@ static int sd_scsi_test_unit_ready(struct us_data *us, struct scsi_cmnd *srb)
+ {
+ 	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+ 
+-	if (info->SD_Status.Insert && info->SD_Status.Ready)
++	if ((info->SD_Status & SD_Insert) && (info->SD_Status & SD_Ready))
+ 		return USB_STOR_TRANSPORT_GOOD;
+ 	else {
+ 		ene_sd_init(us);
+@@ -622,7 +619,7 @@ static int sd_scsi_mode_sense(struct us_data *us, struct scsi_cmnd *srb)
+ 		0x0b, 0x00, 0x80, 0x08, 0x00, 0x00,
+ 		0x71, 0xc0, 0x00, 0x00, 0x02, 0x00 };
+ 
+-	if (info->SD_Status.WtP)
++	if (info->SD_Status & SD_WtP)
+ 		usb_stor_set_xfer_buf(mediaWP, 12, srb);
+ 	else
+ 		usb_stor_set_xfer_buf(mediaNoWP, 12, srb);
+@@ -641,9 +638,9 @@ static int sd_scsi_read_capacity(struct us_data *us, struct scsi_cmnd *srb)
+ 	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+ 
+ 	usb_stor_dbg(us, "sd_scsi_read_capacity\n");
+-	if (info->SD_Status.HiCapacity) {
++	if (info->SD_Status & SD_HiCapacity) {
+ 		bl_len = 0x200;
+-		if (info->SD_Status.IsMMC)
++		if (info->SD_Status & SD_IsMMC)
+ 			bl_num = info->HC_C_SIZE-1;
+ 		else
+ 			bl_num = (info->HC_C_SIZE + 1) * 1024 - 1;
+@@ -693,7 +690,7 @@ static int sd_scsi_read(struct us_data *us, struct scsi_cmnd *srb)
+ 		return USB_STOR_TRANSPORT_ERROR;
+ 	}
+ 
+-	if (info->SD_Status.HiCapacity)
++	if (info->SD_Status & SD_HiCapacity)
+ 		bnByte = bn;
+ 
+ 	/* set up the command wrapper */
+@@ -733,7 +730,7 @@ static int sd_scsi_write(struct us_data *us, struct scsi_cmnd *srb)
+ 		return USB_STOR_TRANSPORT_ERROR;
+ 	}
+ 
+-	if (info->SD_Status.HiCapacity)
++	if (info->SD_Status & SD_HiCapacity)
+ 		bnByte = bn;
+ 
+ 	/* set up the command wrapper */
+@@ -1456,7 +1453,7 @@ static int ms_scsi_test_unit_ready(struct us_data *us, struct scsi_cmnd *srb)
+ 	struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
+ 
+ 	/* pr_info("MS_SCSI_Test_Unit_Ready\n"); */
+-	if (info->MS_Status.Insert && info->MS_Status.Ready) {
++	if ((info->MS_Status & MS_Insert) && (info->MS_Status & MS_Ready)) {
+ 		return USB_STOR_TRANSPORT_GOOD;
+ 	} else {
+ 		ene_ms_init(us);
+@@ -1476,7 +1473,7 @@ static int ms_scsi_mode_sense(struct us_data *us, struct scsi_cmnd *srb)
+ 		0x0b, 0x00, 0x80, 0x08, 0x00, 0x00,
+ 		0x71, 0xc0, 0x00, 0x00, 0x02, 0x00 };
+ 
+-	if (info->MS_Status.WtP)
++	if (info->MS_Status & MS_WtP)
+ 		usb_stor_set_xfer_buf(mediaWP, 12, srb);
+ 	else
+ 		usb_stor_set_xfer_buf(mediaNoWP, 12, srb);
+@@ -1495,7 +1492,7 @@ static int ms_scsi_read_capacity(struct us_data *us, struct scsi_cmnd *srb)
+ 
+ 	usb_stor_dbg(us, "ms_scsi_read_capacity\n");
+ 	bl_len = 0x200;
+-	if (info->MS_Status.IsMSPro)
++	if (info->MS_Status & MS_IsMSPro)
+ 		bl_num = info->MSP_TotalBlock - 1;
+ 	else
+ 		bl_num = info->MS_Lib.NumberOfLogBlock * info->MS_Lib.blockSize * 2 - 1;
+@@ -1650,7 +1647,7 @@ static int ms_scsi_read(struct us_data *us, struct scsi_cmnd *srb)
+ 	if (bn > info->bl_num)
+ 		return USB_STOR_TRANSPORT_ERROR;
+ 
+-	if (info->MS_Status.IsMSPro) {
++	if (info->MS_Status & MS_IsMSPro) {
+ 		result = ene_load_bincode(us, MSP_RW_PATTERN);
+ 		if (result != USB_STOR_XFER_GOOD) {
+ 			usb_stor_dbg(us, "Load MPS RW pattern Fail !!\n");
+@@ -1751,7 +1748,7 @@ static int ms_scsi_write(struct us_data *us, struct scsi_cmnd *srb)
+ 	if (bn > info->bl_num)
+ 		return USB_STOR_TRANSPORT_ERROR;
+ 
+-	if (info->MS_Status.IsMSPro) {
++	if (info->MS_Status & MS_IsMSPro) {
+ 		result = ene_load_bincode(us, MSP_RW_PATTERN);
+ 		if (result != USB_STOR_XFER_GOOD) {
+ 			pr_info("Load MSP RW pattern Fail !!\n");
+@@ -1859,12 +1856,12 @@ static int ene_get_card_status(struct us_data *us, u8 *buf)
+ 
+ 	tmpreg = (u16) reg4b;
+ 	reg4b = *(u32 *)(&buf[0x14]);
+-	if (info->SD_Status.HiCapacity && !info->SD_Status.IsMMC)
++	if ((info->SD_Status & SD_HiCapacity) && !(info->SD_Status & SD_IsMMC))
+ 		info->HC_C_SIZE = (reg4b >> 8) & 0x3fffff;
+ 
+ 	info->SD_C_SIZE = ((tmpreg & 0x03) << 10) | (u16)(reg4b >> 22);
+ 	info->SD_C_SIZE_MULT = (u8)(reg4b >> 7)  & 0x07;
+-	if (info->SD_Status.HiCapacity && info->SD_Status.IsMMC)
++	if ((info->SD_Status & SD_HiCapacity) && (info->SD_Status & SD_IsMMC))
+ 		info->HC_C_SIZE = *(u32 *)(&buf[0x100]);
+ 
+ 	if (info->SD_READ_BL_LEN > SD_BLOCK_LEN) {
+@@ -2076,6 +2073,7 @@ static int ene_ms_init(struct us_data *us)
+ 	u16 MSP_BlockSize, MSP_UserAreaBlocks;
+ 	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+ 	u8 *bbuf = info->bbuf;
++	unsigned int s;
+ 
+ 	printk(KERN_INFO "transport --- ENE_MSInit\n");
+ 
+@@ -2100,15 +2098,16 @@ static int ene_ms_init(struct us_data *us)
+ 		return USB_STOR_TRANSPORT_ERROR;
+ 	}
+ 	/* the same part to test ENE */
+-	info->MS_Status = *(struct MS_STATUS *) bbuf;
+-
+-	if (info->MS_Status.Insert && info->MS_Status.Ready) {
+-		printk(KERN_INFO "Insert     = %x\n", info->MS_Status.Insert);
+-		printk(KERN_INFO "Ready      = %x\n", info->MS_Status.Ready);
+-		printk(KERN_INFO "IsMSPro    = %x\n", info->MS_Status.IsMSPro);
+-		printk(KERN_INFO "IsMSPHG    = %x\n", info->MS_Status.IsMSPHG);
+-		printk(KERN_INFO "WtP= %x\n", info->MS_Status.WtP);
+-		if (info->MS_Status.IsMSPro) {
++	info->MS_Status = bbuf[0];
++
++	s = info->MS_Status;
++	if ((s & MS_Insert) && (s & MS_Ready)) {
++		printk(KERN_INFO "Insert     = %x\n", !!(s & MS_Insert));
++		printk(KERN_INFO "Ready      = %x\n", !!(s & MS_Ready));
++		printk(KERN_INFO "IsMSPro    = %x\n", !!(s & MS_IsMSPro));
++		printk(KERN_INFO "IsMSPHG    = %x\n", !!(s & MS_IsMSPHG));
++		printk(KERN_INFO "WtP= %x\n", !!(s & MS_WtP));
++		if (s & MS_IsMSPro) {
+ 			MSP_BlockSize      = (bbuf[6] << 8) | bbuf[7];
+ 			MSP_UserAreaBlocks = (bbuf[10] << 8) | bbuf[11];
+ 			info->MSP_TotalBlock = MSP_BlockSize * MSP_UserAreaBlocks;
+@@ -2169,17 +2168,17 @@ static int ene_sd_init(struct us_data *us)
+ 		return USB_STOR_TRANSPORT_ERROR;
+ 	}
+ 
+-	info->SD_Status =  *(struct SD_STATUS *) bbuf;
+-	if (info->SD_Status.Insert && info->SD_Status.Ready) {
+-		struct SD_STATUS *s = &info->SD_Status;
++	info->SD_Status = bbuf[0];
++	if ((info->SD_Status & SD_Insert) && (info->SD_Status & SD_Ready)) {
++		unsigned int s = info->SD_Status;
+ 
+ 		ene_get_card_status(us, bbuf);
+-		usb_stor_dbg(us, "Insert     = %x\n", s->Insert);
+-		usb_stor_dbg(us, "Ready      = %x\n", s->Ready);
+-		usb_stor_dbg(us, "IsMMC      = %x\n", s->IsMMC);
+-		usb_stor_dbg(us, "HiCapacity = %x\n", s->HiCapacity);
+-		usb_stor_dbg(us, "HiSpeed    = %x\n", s->HiSpeed);
+-		usb_stor_dbg(us, "WtP        = %x\n", s->WtP);
++		usb_stor_dbg(us, "Insert     = %x\n", !!(s & SD_Insert));
++		usb_stor_dbg(us, "Ready      = %x\n", !!(s & SD_Ready));
++		usb_stor_dbg(us, "IsMMC      = %x\n", !!(s & SD_IsMMC));
++		usb_stor_dbg(us, "HiCapacity = %x\n", !!(s & SD_HiCapacity));
++		usb_stor_dbg(us, "HiSpeed    = %x\n", !!(s & SD_HiSpeed));
++		usb_stor_dbg(us, "WtP        = %x\n", !!(s & SD_WtP));
+ 	} else {
+ 		usb_stor_dbg(us, "SD Card Not Ready --- %x\n", bbuf[0]);
+ 		return USB_STOR_TRANSPORT_ERROR;
+@@ -2201,14 +2200,14 @@ static int ene_init(struct us_data *us)
+ 
+ 	misc_reg03 = bbuf[0];
+ 	if (misc_reg03 & 0x01) {
+-		if (!info->SD_Status.Ready) {
++		if (!(info->SD_Status & SD_Ready)) {
+ 			result = ene_sd_init(us);
+ 			if (result != USB_STOR_XFER_GOOD)
+ 				return USB_STOR_TRANSPORT_ERROR;
+ 		}
+ 	}
+ 	if (misc_reg03 & 0x02) {
+-		if (!info->MS_Status.Ready) {
++		if (!(info->MS_Status & MS_Ready)) {
+ 			result = ene_ms_init(us);
+ 			if (result != USB_STOR_XFER_GOOD)
+ 				return USB_STOR_TRANSPORT_ERROR;
+@@ -2307,14 +2306,14 @@ static int ene_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 
+ 	/*US_DEBUG(usb_stor_show_command(us, srb)); */
+ 	scsi_set_resid(srb, 0);
+-	if (unlikely(!(info->SD_Status.Ready || info->MS_Status.Ready)))
++	if (unlikely(!(info->SD_Status & SD_Ready) || (info->MS_Status & MS_Ready)))
+ 		result = ene_init(us);
+ 	if (result == USB_STOR_XFER_GOOD) {
+ 		result = USB_STOR_TRANSPORT_ERROR;
+-		if (info->SD_Status.Ready)
++		if (info->SD_Status & SD_Ready)
+ 			result = sd_scsi_irp(us, srb);
+ 
+-		if (info->MS_Status.Ready)
++		if (info->MS_Status & MS_Ready)
+ 			result = ms_scsi_irp(us, srb);
+ 	}
+ 	return result;
+@@ -2378,7 +2377,6 @@ static int ene_ub6250_probe(struct usb_interface *intf,
+ 
+ static int ene_ub6250_resume(struct usb_interface *iface)
+ {
+-	u8 tmp = 0;
+ 	struct us_data *us = usb_get_intfdata(iface);
+ 	struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
+ 
+@@ -2390,17 +2388,16 @@ static int ene_ub6250_resume(struct usb_interface *iface)
+ 	mutex_unlock(&us->dev_mutex);
+ 
+ 	info->Power_IsResum = true;
+-	/*info->SD_Status.Ready = 0; */
+-	info->SD_Status = *(struct SD_STATUS *)&tmp;
+-	info->MS_Status = *(struct MS_STATUS *)&tmp;
+-	info->SM_Status = *(struct SM_STATUS *)&tmp;
++	/* info->SD_Status &= ~SD_Ready; */
++	info->SD_Status = 0;
++	info->MS_Status = 0;
++	info->SM_Status = 0;
+ 
+ 	return 0;
+ }
+ 
+ static int ene_ub6250_reset_resume(struct usb_interface *iface)
+ {
+-	u8 tmp = 0;
+ 	struct us_data *us = usb_get_intfdata(iface);
+ 	struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
+ 
+@@ -2412,10 +2409,10 @@ static int ene_ub6250_reset_resume(struct usb_interface *iface)
+ 	 * the device
+ 	 */
+ 	info->Power_IsResum = true;
+-	/*info->SD_Status.Ready = 0; */
+-	info->SD_Status = *(struct SD_STATUS *)&tmp;
+-	info->MS_Status = *(struct MS_STATUS *)&tmp;
+-	info->SM_Status = *(struct SM_STATUS *)&tmp;
++	/* info->SD_Status &= ~SD_Ready; */
++	info->SD_Status = 0;
++	info->MS_Status = 0;
++	info->SM_Status = 0;
+ 
+ 	return 0;
+ }

commit 16b1941eac2bd499f065a6739a40ce0011a3d740
+Author: Alan Stern 
+Date:   Sat Mar 5 21:47:22 2022 -0500
+
+    usb: gadget: Fix use-after-free bug by not setting udc->dev.driver
+    
+    The syzbot fuzzer found a use-after-free bug:
+    
+    BUG: KASAN: use-after-free in dev_uevent+0x712/0x780 drivers/base/core.c:2320
+    Read of size 8 at addr ffff88802b934098 by task udevd/3689
+    
+    CPU: 2 PID: 3689 Comm: udevd Not tainted 5.17.0-rc4-syzkaller-00229-g4f12b742eb2b #0
+    Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.14.0-2 04/01/2014
+    Call Trace:
+     
+     __dump_stack lib/dump_stack.c:88 [inline]
+     dump_stack_lvl+0xcd/0x134 lib/dump_stack.c:106
+     print_address_description.constprop.0.cold+0x8d/0x303 mm/kasan/report.c:255
+     __kasan_report mm/kasan/report.c:442 [inline]
+     kasan_report.cold+0x83/0xdf mm/kasan/report.c:459
+     dev_uevent+0x712/0x780 drivers/base/core.c:2320
+     uevent_show+0x1b8/0x380 drivers/base/core.c:2391
+     dev_attr_show+0x4b/0x90 drivers/base/core.c:2094
+    
+    Although the bug manifested in the driver core, the real cause was a
+    race with the gadget core.  dev_uevent() does:
+    
+            if (dev->driver)
+                    add_uevent_var(env, "DRIVER=%s", dev->driver->name);
+    
+    and between the test and the dereference of dev->driver, the gadget
+    core sets dev->driver to NULL.
+    
+    The race wouldn't occur if the gadget core registered its devices on
+    a real bus, using the standard synchronization techniques of the
+    driver core.  However, it's not necessary to make such a large change
+    in order to fix this bug; all we need to do is make sure that
+    udc->dev.driver is always NULL.
+    
+    In fact, there is no reason for udc->dev.driver ever to be set to
+    anything, let alone to the value it currently gets: the address of the
+    gadget's driver.  After all, a gadget driver only knows how to manage
+    a gadget, not how to manage a UDC.
+    
+    This patch simply removes the statements in the gadget core that touch
+    udc->dev.driver.
+    
+    Fixes: 2ccea03a8f7e ("usb: gadget: introduce UDC Class")
+    CC: 
+    Reported-and-tested-by: syzbot+348b571beb5eeb70a582@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/YiQgukfFFbBnwJ/9@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
+index 568534a0d17c..c109b069f511 100644
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -1436,7 +1436,6 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
+ 	usb_gadget_udc_stop(udc);
+ 
+ 	udc->driver = NULL;
+-	udc->dev.driver = NULL;
+ 	udc->gadget->dev.driver = NULL;
+ }
+ 
+@@ -1498,7 +1497,6 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
+ 			driver->function);
+ 
+ 	udc->driver = driver;
+-	udc->dev.driver = &driver->driver;
+ 	udc->gadget->dev.driver = &driver->driver;
+ 
+ 	usb_gadget_udc_set_speed(udc, driver->max_speed);
+@@ -1521,7 +1519,6 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
+ 		dev_err(&udc->dev, "failed to start %s: %d\n",
+ 			udc->driver->function, ret);
+ 	udc->driver = NULL;
+-	udc->dev.driver = NULL;
+ 	udc->gadget->dev.driver = NULL;
+ 	return ret;
+ }

commit e9b667a82cdcfe21d590344447d65daed52b353b
+Author: Alan Stern 
+Date:   Thu Mar 3 16:00:17 2022 -0500
+
+    usb: usbtmc: Fix bug in pipe direction for control transfers
+    
+    The syzbot fuzzer reported a minor bug in the usbtmc driver:
+    
+    usb 5-1: BOGUS control dir, pipe 80001e80 doesn't match bRequestType 0
+    WARNING: CPU: 0 PID: 3813 at drivers/usb/core/urb.c:412
+    usb_submit_urb+0x13a5/0x1970 drivers/usb/core/urb.c:410
+    Modules linked in:
+    CPU: 0 PID: 3813 Comm: syz-executor122 Not tainted
+    5.17.0-rc5-syzkaller-00306-g2293be58d6a1 #0
+    ...
+    Call Trace:
+     
+     usb_start_wait_urb+0x113/0x530 drivers/usb/core/message.c:58
+     usb_internal_control_msg drivers/usb/core/message.c:102 [inline]
+     usb_control_msg+0x2a5/0x4b0 drivers/usb/core/message.c:153
+     usbtmc_ioctl_request drivers/usb/class/usbtmc.c:1947 [inline]
+    
+    The problem is that usbtmc_ioctl_request() uses usb_rcvctrlpipe() for
+    all of its transfers, whether they are in or out.  It's easy to fix.
+    
+    CC: 
+    Reported-and-tested-by: syzbot+a48e3d1a875240cab5de@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/YiEsYTPEE6lOCOA5@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
+index 73f419adce61..4bb6d304eb4b 100644
+--- a/drivers/usb/class/usbtmc.c
++++ b/drivers/usb/class/usbtmc.c
+@@ -1919,6 +1919,7 @@ static int usbtmc_ioctl_request(struct usbtmc_device_data *data,
+ 	struct usbtmc_ctrlrequest request;
+ 	u8 *buffer = NULL;
+ 	int rv;
++	unsigned int is_in, pipe;
+ 	unsigned long res;
+ 
+ 	res = copy_from_user(&request, arg, sizeof(struct usbtmc_ctrlrequest));
+@@ -1928,12 +1929,14 @@ static int usbtmc_ioctl_request(struct usbtmc_device_data *data,
+ 	if (request.req.wLength > USBTMC_BUFSIZE)
+ 		return -EMSGSIZE;
+ 
++	is_in = request.req.bRequestType & USB_DIR_IN;
++
+ 	if (request.req.wLength) {
+ 		buffer = kmalloc(request.req.wLength, GFP_KERNEL);
+ 		if (!buffer)
+ 			return -ENOMEM;
+ 
+-		if ((request.req.bRequestType & USB_DIR_IN) == 0) {
++		if (!is_in) {
+ 			/* Send control data to device */
+ 			res = copy_from_user(buffer, request.data,
+ 					     request.req.wLength);
+@@ -1944,8 +1947,12 @@ static int usbtmc_ioctl_request(struct usbtmc_device_data *data,
+ 		}
+ 	}
+ 
++	if (is_in)
++		pipe = usb_rcvctrlpipe(data->usb_dev, 0);
++	else
++		pipe = usb_sndctrlpipe(data->usb_dev, 0);
+ 	rv = usb_control_msg(data->usb_dev,
+-			usb_rcvctrlpipe(data->usb_dev, 0),
++			pipe,
+ 			request.req.bRequest,
+ 			request.req.bRequestType,
+ 			request.req.wValue,
+@@ -1957,7 +1964,7 @@ static int usbtmc_ioctl_request(struct usbtmc_device_data *data,
+ 		goto exit;
+ 	}
+ 
+-	if (rv && (request.req.bRequestType & USB_DIR_IN)) {
++	if (rv && is_in) {
+ 		/* Read control data from device */
+ 		res = copy_to_user(request.data, buffer, rv);
+ 		if (res)

commit f6a9a2d64dd168b7d71076c0e6b2be7db7cb7399
+Author: Alan Stern 
+Date:   Fri Feb 25 09:38:25 2022 -0500
+
+    USB: core: Update kerneldoc for usb_get_dev() and usb_get_intf()
+    
+    The kerneldoc for usb_get_dev() and usb_get_intf() says that drivers
+    should always refcount the references they hold for the usb_device or
+    usb_interface structure, respectively.  But this is an overstatement:
+    In many cases drivers do not access these references after they have
+    been unbound, and in such cases refcounting is unnecessary.
+    
+    This patch updates the kerneldoc for the two routines, explaining when
+    a driver does not need to increment and decrement the refcount.  This
+    should help dispel misconceptions which might otherwise afflict
+    programmers new to the USB subsystem.
+    
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/Yhjp4Rp9Alipmwtq@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 2ce3667ec6fa..2f71636af6e1 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -688,6 +688,10 @@ EXPORT_SYMBOL_GPL(usb_alloc_dev);
+  * Drivers for USB interfaces should normally record such references in
+  * their probe() methods, when they bind to an interface, and release
+  * them by calling usb_put_dev(), in their disconnect() methods.
++ * However, if a driver does not access the usb_device structure after
++ * its disconnect() method returns then refcounting is not necessary,
++ * because the USB core guarantees that a usb_device will not be
++ * deallocated until after all of its interface drivers have been unbound.
+  *
+  * Return: A pointer to the device with the incremented reference counter.
+  */
+@@ -722,6 +726,10 @@ EXPORT_SYMBOL_GPL(usb_put_dev);
+  * Drivers for USB interfaces should normally record such references in
+  * their probe() methods, when they bind to an interface, and release
+  * them by calling usb_put_intf(), in their disconnect() methods.
++ * However, if a driver does not access the usb_interface structure after
++ * its disconnect() method returns then refcounting is not necessary,
++ * because the USB core guarantees that a usb_interface will not be
++ * deallocated until after its driver has been unbound.
+  *
+  * Return: A pointer to the interface with the incremented reference counter.
+  */

commit e2b665f612ca2ddc61c3d54817a3a780aee6b251
+Author: Alan Stern 
+Date:   Tue Feb 1 14:00:08 2022 -0500
+
+    tools/memory-model: Explain syntactic and semantic dependencies
+    
+    Paul Heidekrüger pointed out that the Linux Kernel Memory Model
+    documentation doesn't mention the distinction between syntactic and
+    semantic dependencies.  This is an important difference, because the
+    compiler can easily break dependencies that are only syntactic, not
+    semantic.
+    
+    This patch adds a few paragraphs to the LKMM documentation explaining
+    these issues and illustrating how they can matter.
+    
+    Suggested-by: Paul Heidekrüger 
+    Reviewed-by: Akira Yokosawa 
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Paul E. McKenney 
+
+diff --git a/tools/memory-model/Documentation/explanation.txt b/tools/memory-model/Documentation/explanation.txt
+index 394ee57d58f2..ee819a402b69 100644
+--- a/tools/memory-model/Documentation/explanation.txt
++++ b/tools/memory-model/Documentation/explanation.txt
+@@ -485,6 +485,57 @@ have R ->po X.  It wouldn't make sense for a computation to depend
+ somehow on a value that doesn't get loaded from shared memory until
+ later in the code!
+ 
++Here's a trick question: When is a dependency not a dependency?  Answer:
++When it is purely syntactic rather than semantic.  We say a dependency
++between two accesses is purely syntactic if the second access doesn't
++actually depend on the result of the first.  Here is a trivial example:
++
++	r1 = READ_ONCE(x);
++	WRITE_ONCE(y, r1 * 0);
++
++There appears to be a data dependency from the load of x to the store
++of y, since the value to be stored is computed from the value that was
++loaded.  But in fact, the value stored does not really depend on
++anything since it will always be 0.  Thus the data dependency is only
++syntactic (it appears to exist in the code) but not semantic (the
++second access will always be the same, regardless of the value of the
++first access).  Given code like this, a compiler could simply discard
++the value returned by the load from x, which would certainly destroy
++any dependency.  (The compiler is not permitted to eliminate entirely
++the load generated for a READ_ONCE() -- that's one of the nice
++properties of READ_ONCE() -- but it is allowed to ignore the load's
++value.)
++
++It's natural to object that no one in their right mind would write
++code like the above.  However, macro expansions can easily give rise
++to this sort of thing, in ways that often are not apparent to the
++programmer.
++
++Another mechanism that can lead to purely syntactic dependencies is
++related to the notion of "undefined behavior".  Certain program
++behaviors are called "undefined" in the C language specification,
++which means that when they occur there are no guarantees at all about
++the outcome.  Consider the following example:
++
++	int a[1];
++	int i;
++
++	r1 = READ_ONCE(i);
++	r2 = READ_ONCE(a[r1]);
++
++Access beyond the end or before the beginning of an array is one kind
++of undefined behavior.  Therefore the compiler doesn't have to worry
++about what will happen if r1 is nonzero, and it can assume that r1
++will always be zero regardless of the value actually loaded from i.
++(If the assumption turns out to be wrong the resulting behavior will
++be undefined anyway, so the compiler doesn't care!)  Thus the value
++from the load can be discarded, breaking the address dependency.
++
++The LKMM is unaware that purely syntactic dependencies are different
++from semantic dependencies and therefore mistakenly predicts that the
++accesses in the two examples above will be ordered.  This is another
++example of how the compiler can undermine the memory model.  Be warned.
++
+ 
+ THE READS-FROM RELATION: rf, rfi, and rfe
+ -----------------------------------------

commit 26fbe9772b8c459687930511444ce443011f86bf
+Author: Alan Stern 
+Date:   Mon Jan 24 15:23:45 2022 -0500
+
+    USB: core: Fix hang in usb_kill_urb by adding memory barriers
+    
+    The syzbot fuzzer has identified a bug in which processes hang waiting
+    for usb_kill_urb() to return.  It turns out the issue is not unlinking
+    the URB; that works just fine.  Rather, the problem arises when the
+    wakeup notification that the URB has completed is not received.
+    
+    The reason is memory-access ordering on SMP systems.  In outline form,
+    usb_kill_urb() and __usb_hcd_giveback_urb() operating concurrently on
+    different CPUs perform the following actions:
+    
+    CPU 0                                   CPU 1
+    ----------------------------            ---------------------------------
+    usb_kill_urb():                         __usb_hcd_giveback_urb():
+      ...                                     ...
+      atomic_inc(&urb->reject);               atomic_dec(&urb->use_count);
+      ...                                     ...
+      wait_event(usb_kill_urb_queue,
+            atomic_read(&urb->use_count) == 0);
+                                              if (atomic_read(&urb->reject))
+                                                    wake_up(&usb_kill_urb_queue);
+    
+    Confining your attention to urb->reject and urb->use_count, you can
+    see that the overall pattern of accesses on CPU 0 is:
+    
+            write urb->reject, then read urb->use_count;
+    
+    whereas the overall pattern of accesses on CPU 1 is:
+    
+            write urb->use_count, then read urb->reject.
+    
+    This pattern is referred to in memory-model circles as SB (for "Store
+    Buffering"), and it is well known that without suitable enforcement of
+    the desired order of accesses -- in the form of memory barriers -- it
+    is entirely possible for one or both CPUs to execute their reads ahead
+    of their writes.  The end result will be that sometimes CPU 0 sees the
+    old un-decremented value of urb->use_count while CPU 1 sees the old
+    un-incremented value of urb->reject.  Consequently CPU 0 ends up on
+    the wait queue and never gets woken up, leading to the observed hang
+    in usb_kill_urb().
+    
+    The same pattern of accesses occurs in usb_poison_urb() and the
+    failure pathway of usb_hcd_submit_urb().
+    
+    The problem is fixed by adding suitable memory barriers.  To provide
+    proper memory-access ordering in the SB pattern, a full barrier is
+    required on both CPUs.  The atomic_inc() and atomic_dec() accesses
+    themselves don't provide any memory ordering, but since they are
+    present, we can use the optimized smp_mb__after_atomic() memory
+    barrier in the various routines to obtain the desired effect.
+    
+    This patch adds the necessary memory barriers.
+    
+    CC: 
+    Reported-and-tested-by: syzbot+76629376e06e2c2ad626@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/Ye8K0QYee0Q0Nna2@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 3e01dd6e509b..d9712c2602af 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1563,6 +1563,13 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+ 		urb->hcpriv = NULL;
+ 		INIT_LIST_HEAD(&urb->urb_list);
+ 		atomic_dec(&urb->use_count);
++		/*
++		 * Order the write of urb->use_count above before the read
++		 * of urb->reject below.  Pairs with the memory barriers in
++		 * usb_kill_urb() and usb_poison_urb().
++		 */
++		smp_mb__after_atomic();
++
+ 		atomic_dec(&urb->dev->urbnum);
+ 		if (atomic_read(&urb->reject))
+ 			wake_up(&usb_kill_urb_queue);
+@@ -1665,6 +1672,13 @@ static void __usb_hcd_giveback_urb(struct urb *urb)
+ 
+ 	usb_anchor_resume_wakeups(anchor);
+ 	atomic_dec(&urb->use_count);
++	/*
++	 * Order the write of urb->use_count above before the read
++	 * of urb->reject below.  Pairs with the memory barriers in
++	 * usb_kill_urb() and usb_poison_urb().
++	 */
++	smp_mb__after_atomic();
++
+ 	if (unlikely(atomic_read(&urb->reject)))
+ 		wake_up(&usb_kill_urb_queue);
+ 	usb_put_urb(urb);
+diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
+index 30727729a44c..33d62d7e3929 100644
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -715,6 +715,12 @@ void usb_kill_urb(struct urb *urb)
+ 	if (!(urb && urb->dev && urb->ep))
+ 		return;
+ 	atomic_inc(&urb->reject);
++	/*
++	 * Order the write of urb->reject above before the read
++	 * of urb->use_count below.  Pairs with the barriers in
++	 * __usb_hcd_giveback_urb() and usb_hcd_submit_urb().
++	 */
++	smp_mb__after_atomic();
+ 
+ 	usb_hcd_unlink_urb(urb, -ENOENT);
+ 	wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0);
+@@ -756,6 +762,12 @@ void usb_poison_urb(struct urb *urb)
+ 	if (!urb)
+ 		return;
+ 	atomic_inc(&urb->reject);
++	/*
++	 * Order the write of urb->reject above before the read
++	 * of urb->use_count below.  Pairs with the barriers in
++	 * __usb_hcd_giveback_urb() and usb_hcd_submit_urb().
++	 */
++	smp_mb__after_atomic();
+ 
+ 	if (!urb->dev || !urb->ep)
+ 		return;

commit 5b67b315037250a61861119683e7fcb509deea25
+Author: Alan Stern 
+Date:   Mon Jan 24 15:14:40 2022 -0500
+
+    usb-storage: Add unusual-devs entry for VL817 USB-SATA bridge
+    
+    Two people have reported (and mentioned numerous other reports on the
+    web) that VIA's VL817 USB-SATA bridge does not work with the uas
+    driver.  Typical log messages are:
+    
+    [ 3606.232149] sd 14:0:0:0: [sdg] tag#2 uas_zap_pending 0 uas-tag 1 inflight: CMD
+    [ 3606.232154] sd 14:0:0:0: [sdg] tag#2 CDB: Write(16) 8a 00 00 00 00 00 18 0c c9 80 00 00 00 80 00 00
+    [ 3606.306257] usb 4-4.4: reset SuperSpeed Plus Gen 2x1 USB device number 11 using xhci_hcd
+    [ 3606.328584] scsi host14: uas_eh_device_reset_handler success
+    
+    Surprisingly, the devices do seem to work okay for some other people.
+    The cause of the differing behaviors is not known.
+    
+    In the hope of getting the devices to work for the most users, even at
+    the possible cost of degraded performance for some, this patch adds an
+    unusual_devs entry for the VL817 to block it from binding to the uas
+    driver by default.  Users will be able to override this entry by means
+    of a module parameter, if they want.
+    
+    CC: 
+    Reported-by: DocMAX 
+    Reported-and-tested-by: Thomas Weißschuh 
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/Ye8IsK2sjlEv1rqU@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 29191d33c0e3..1a05e3dcfec8 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -2301,6 +2301,16 @@ UNUSUAL_DEV(  0x2027, 0xa001, 0x0000, 0x9999,
+ 		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init,
+ 		US_FL_SCM_MULT_TARG ),
+ 
++/*
++ * Reported by DocMAX 
++ * and Thomas Weißschuh 
++ */
++UNUSUAL_DEV( 0x2109, 0x0715, 0x9999, 0x9999,
++		"VIA Labs, Inc.",
++		"VL817 SATA Bridge",
++		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
++		US_FL_IGNORE_UAS),
++
+ UNUSUAL_DEV( 0x2116, 0x0320, 0x0001, 0x0001,
+ 		"ST",
+ 		"2A",

commit 0f663729bb4afc92a9986b66131ebd5b8a9254d1
+Author: Alan Stern 
+Date:   Sat Jan 1 14:52:14 2022 -0500
+
+    USB: core: Fix bug in resuming hub's handling of wakeup requests
+    
+    Bugzilla #213839 reports a 7-port hub that doesn't work properly when
+    devices are plugged into some of the ports; the kernel goes into an
+    unending disconnect/reinitialize loop as shown in the bug report.
+    
+    This "7-port hub" comprises two four-port hubs with one plugged into
+    the other; the failures occur when a device is plugged into one of the
+    downstream hub's ports.  (These hubs have other problems too.  For
+    example, they bill themselves as USB-2.0 compliant but they only run
+    at full speed.)
+    
+    It turns out that the failures are caused by bugs in both the kernel
+    and the hub.  The hub's bug is that it reports a different
+    bmAttributes value in its configuration descriptor following a remote
+    wakeup (0xe0 before, 0xc0 after -- the wakeup-support bit has
+    changed).
+    
+    The kernel's bug is inside the hub driver's resume handler.  When
+    hub_activate() sees that one of the hub's downstream ports got a
+    wakeup request from a child device, it notes this fact by setting the
+    corresponding bit in the hub->change_bits variable.  But this variable
+    is meant for connection changes, not wakeup events; setting it causes
+    the driver to believe the downstream port has been disconnected and
+    then connected again (in addition to having received a wakeup
+    request).
+    
+    Because of this, the hub driver then tries to check whether the device
+    currently plugged into the downstream port is the same as the device
+    that had been attached there before.  Normally this check succeeds and
+    wakeup handling continues with no harm done (which is why the bug
+    remained undetected until now).  But with these dodgy hubs, the check
+    fails because the config descriptor has changed.  This causes the hub
+    driver to reinitialize the child device, leading to the
+    disconnect/reinitialize loop described in the bug report.
+    
+    The proper way to note reception of a downstream wakeup request is
+    to set a bit in the hub->event_bits variable instead of
+    hub->change_bits.  That way the hub driver will realize that something
+    has happened to the port but will not think the port and child device
+    have been disconnected.  This patch makes that change.
+    
+    Cc: 
+    Tested-by: Jonathan McDowell 
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/YdCw7nSfWYPKWQoD@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 721794f0f494..47a1c8bddf86 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1228,7 +1228,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ 			 */
+ 			if (portchange || (hub_is_superspeed(hub->hdev) &&
+ 						port_resumed))
+-				set_bit(port1, hub->change_bits);
++				set_bit(port1, hub->event_bits);
+ 
+ 		} else if (udev->persist_enabled) {
+ #ifdef CONFIG_PM

commit 1d7d4c07932e04355d6e6528d44a2f2c9e354346
+Author: Alan Stern 
+Date:   Fri Dec 31 21:07:12 2021 -0500
+
+    USB: Fix "slab-out-of-bounds Write" bug in usb_hcd_poll_rh_status
+    
+    When the USB core code for getting root-hub status reports was
+    originally written, it was assumed that the hub driver would be its
+    only caller.  But this isn't true now; user programs can use usbfs to
+    communicate with root hubs and get status reports.  When they do this,
+    they may use a transfer_buffer that is smaller than the data returned
+    by the HCD, which will lead to a buffer overflow error when
+    usb_hcd_poll_rh_status() tries to store the status data.  This was
+    discovered by syzbot:
+    
+    BUG: KASAN: slab-out-of-bounds in memcpy include/linux/fortify-string.h:225 [inline]
+    BUG: KASAN: slab-out-of-bounds in usb_hcd_poll_rh_status+0x5f4/0x780 drivers/usb/core/hcd.c:776
+    Write of size 2 at addr ffff88801da403c0 by task syz-executor133/4062
+    
+    This patch fixes the bug by reducing the amount of status data if it
+    won't fit in the transfer_buffer.  If some data gets discarded then
+    the URB's completion status is set to -EOVERFLOW rather than 0, to let
+    the user know what happened.
+    
+    Reported-and-tested-by: syzbot+3ae6a2b06f131ab9849f@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    Cc: 
+    Link: https://lore.kernel.org/r/Yc+3UIQJ2STbxNua@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 9ffc63ae65ac..3e01dd6e509b 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -753,6 +753,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
+ {
+ 	struct urb	*urb;
+ 	int		length;
++	int		status;
+ 	unsigned long	flags;
+ 	char		buffer[6];	/* Any root hubs with > 31 ports? */
+ 
+@@ -770,11 +771,17 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
+ 		if (urb) {
+ 			clear_bit(HCD_FLAG_POLL_PENDING, &hcd->flags);
+ 			hcd->status_urb = NULL;
++			if (urb->transfer_buffer_length >= length) {
++				status = 0;
++			} else {
++				status = -EOVERFLOW;
++				length = urb->transfer_buffer_length;
++			}
+ 			urb->actual_length = length;
+ 			memcpy(urb->transfer_buffer, buffer, length);
+ 
+ 			usb_hcd_unlink_urb_from_ep(hcd, urb);
+-			usb_hcd_giveback_urb(hcd, urb, 0);
++			usb_hcd_giveback_urb(hcd, urb, status);
+ 		} else {
+ 			length = 0;
+ 			set_bit(HCD_FLAG_POLL_PENDING, &hcd->flags);

commit 6e1fcab00a23f7fe9f4fe9704905a790efa1eeab
+Author: Alan Stern 
+Date:   Mon Dec 20 19:21:26 2021 +0800
+
+    scsi: block: pm: Always set request queue runtime active in blk_post_runtime_resume()
+    
+    John Garry reported a deadlock that occurs when trying to access a
+    runtime-suspended SATA device.  For obscure reasons, the rescan procedure
+    causes the link to be hard-reset, which disconnects the device.
+    
+    The rescan tries to carry out a runtime resume when accessing the device.
+    scsi_rescan_device() holds the SCSI device lock and won't release it until
+    it can put commands onto the device's block queue.  This can't happen until
+    the queue is successfully runtime-resumed or the device is unregistered.
+    But the runtime resume fails because the device is disconnected, and
+    __scsi_remove_device() can't do the unregistration because it can't get the
+    device lock.
+    
+    The best way to resolve this deadlock appears to be to allow the block
+    queue to start running again even after an unsuccessful runtime resume.
+    The idea is that the driver or the SCSI error handler will need to be able
+    to use the queue to resolve the runtime resume failure.
+    
+    This patch removes the err argument to blk_post_runtime_resume() and makes
+    the routine act as though the resume was successful always.  This fixes the
+    deadlock.
+    
+    Link: https://lore.kernel.org/r/1639999298-244569-4-git-send-email-chenxiang66@hisilicon.com
+    Fixes: e27829dc92e5 ("scsi: serialize ->rescan against ->remove")
+    Reported-and-tested-by: John Garry 
+    Reviewed-by: Bart Van Assche 
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Xiang Chen 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/block/blk-pm.c b/block/blk-pm.c
+index 17bd020268d4..2dad62cc1572 100644
+--- a/block/blk-pm.c
++++ b/block/blk-pm.c
+@@ -163,27 +163,19 @@ EXPORT_SYMBOL(blk_pre_runtime_resume);
+ /**
+  * blk_post_runtime_resume - Post runtime resume processing
+  * @q: the queue of the device
+- * @err: return value of the device's runtime_resume function
+  *
+  * Description:
+- *    Update the queue's runtime status according to the return value of the
+- *    device's runtime_resume function. If the resume was successful, call
+- *    blk_set_runtime_active() to do the real work of restarting the queue.
++ *    For historical reasons, this routine merely calls blk_set_runtime_active()
++ *    to do the real work of restarting the queue.  It does this regardless of
++ *    whether the device's runtime-resume succeeded; even if it failed the
++ *    driver or error handler will need to communicate with the device.
+  *
+  *    This function should be called near the end of the device's
+  *    runtime_resume callback.
+  */
+-void blk_post_runtime_resume(struct request_queue *q, int err)
++void blk_post_runtime_resume(struct request_queue *q)
+ {
+-	if (!q->dev)
+-		return;
+-	if (!err) {
+-		blk_set_runtime_active(q);
+-	} else {
+-		spin_lock_irq(&q->queue_lock);
+-		q->rpm_status = RPM_SUSPENDED;
+-		spin_unlock_irq(&q->queue_lock);
+-	}
++	blk_set_runtime_active(q);
+ }
+ EXPORT_SYMBOL(blk_post_runtime_resume);
+ 
+@@ -201,7 +193,7 @@ EXPORT_SYMBOL(blk_post_runtime_resume);
+  * runtime PM status and re-enable peeking requests from the queue. It
+  * should be called before first request is added to the queue.
+  *
+- * This function is also called by blk_post_runtime_resume() for successful
++ * This function is also called by blk_post_runtime_resume() for
+  * runtime resumes.  It does everything necessary to restart the queue.
+  */
+ void blk_set_runtime_active(struct request_queue *q)
+diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
+index 0e841e8761c5..d581613d87c7 100644
+--- a/drivers/scsi/scsi_pm.c
++++ b/drivers/scsi/scsi_pm.c
+@@ -180,7 +180,7 @@ static int sdev_runtime_resume(struct device *dev)
+ 	blk_pre_runtime_resume(sdev->request_queue);
+ 	if (pm && pm->runtime_resume)
+ 		err = pm->runtime_resume(dev);
+-	blk_post_runtime_resume(sdev->request_queue, err);
++	blk_post_runtime_resume(sdev->request_queue);
+ 
+ 	return err;
+ }
+diff --git a/include/linux/blk-pm.h b/include/linux/blk-pm.h
+index b80c65aba249..2580e05a8ab6 100644
+--- a/include/linux/blk-pm.h
++++ b/include/linux/blk-pm.h
+@@ -14,7 +14,7 @@ extern void blk_pm_runtime_init(struct request_queue *q, struct device *dev);
+ extern int blk_pre_runtime_suspend(struct request_queue *q);
+ extern void blk_post_runtime_suspend(struct request_queue *q, int err);
+ extern void blk_pre_runtime_resume(struct request_queue *q);
+-extern void blk_post_runtime_resume(struct request_queue *q, int err);
++extern void blk_post_runtime_resume(struct request_queue *q);
+ extern void blk_set_runtime_active(struct request_queue *q);
+ #else
+ static inline void blk_pm_runtime_init(struct request_queue *q,

commit 846cbf98cbef20376b1a95fa3734c435543f3519
+Author: Alan Stern 
+Date:   Sat Oct 2 15:02:17 2021 -0400
+
+    USB: EHCI: Improve port index sanitizing
+    
+    Now that Kees Cook has added a definition for HCS_N_PORTS_MAX in
+    commit 72dd1843232c ("USB: EHCI: Add register array bounds to HCS
+    ports"), the code in ehci_hub_control() which sanitizes port index
+    values can be improved a little.
+    
+    The idea behind this change is that it prevents a possible
+    out-of-bounds pointer computation, which the compiler might be able to
+    detect since the port_status[] array now has a fixed length rather
+    than a variable length.
+    
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/20211002190217.GA537967@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index c4f6a2559a98..efe30e3be22f 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -745,12 +745,13 @@ int ehci_hub_control(
+ 	unsigned	selector;
+ 
+ 	/*
+-	 * Avoid underflow while calculating (wIndex & 0xff) - 1.
+-	 * The compiler might deduce that wIndex can never be 0 and then
+-	 * optimize away the tests for !wIndex below.
++	 * Avoid out-of-bounds values while calculating the port index
++	 * from wIndex.  The compiler doesn't like pointers to invalid
++	 * addresses, even if they are never used.
+ 	 */
+-	temp = wIndex & 0xff;
+-	temp -= (temp > 0);
++	temp = (wIndex - 1) & 0xff;
++	if (temp >= HCS_N_PORTS_MAX)
++		temp = 0;
+ 	status_reg = &ehci->regs->port_status[temp];
+ 	hostpc_reg = &ehci->regs->hostpc[temp];
+ 

commit ae8709b296d80c7f45aa1f35c0e7659ad69edce1
+Author: Alan Stern 
+Date:   Fri Sep 3 13:53:12 2021 -0400
+
+    USB: core: Make do_proc_control() and do_proc_bulk() killable
+    
+    The USBDEVFS_CONTROL and USBDEVFS_BULK ioctls invoke
+    usb_start_wait_urb(), which contains an uninterruptible wait with a
+    user-specified timeout value.  If timeout value is very large and the
+    device being accessed does not respond in a reasonable amount of time,
+    the kernel will complain about "Task X blocked for more than N
+    seconds", as found in testing by syzbot:
+    
+    INFO: task syz-executor.0:8700 blocked for more than 143 seconds.
+          Not tainted 5.14.0-rc7-syzkaller #0
+    "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+    task:syz-executor.0  state:D stack:23192 pid: 8700 ppid:  8455 flags:0x00004004
+    Call Trace:
+     context_switch kernel/sched/core.c:4681 [inline]
+     __schedule+0xc07/0x11f0 kernel/sched/core.c:5938
+     schedule+0x14b/0x210 kernel/sched/core.c:6017
+     schedule_timeout+0x98/0x2f0 kernel/time/timer.c:1857
+     do_wait_for_common+0x2da/0x480 kernel/sched/completion.c:85
+     __wait_for_common kernel/sched/completion.c:106 [inline]
+     wait_for_common kernel/sched/completion.c:117 [inline]
+     wait_for_completion_timeout+0x46/0x60 kernel/sched/completion.c:157
+     usb_start_wait_urb+0x167/0x550 drivers/usb/core/message.c:63
+     do_proc_bulk+0x978/0x1080 drivers/usb/core/devio.c:1236
+     proc_bulk drivers/usb/core/devio.c:1273 [inline]
+     usbdev_do_ioctl drivers/usb/core/devio.c:2547 [inline]
+     usbdev_ioctl+0x3441/0x6b10 drivers/usb/core/devio.c:2713
+    ...
+    
+    To fix this problem, this patch replaces usbfs's calls to
+    usb_control_msg() and usb_bulk_msg() with special-purpose code that
+    does essentially the same thing (as recommended in the comment for
+    usb_start_wait_urb()), except that it always uses a killable wait and
+    it uses GFP_KERNEL rather than GFP_NOIO.
+    
+    Reported-and-tested-by: syzbot+ada0f7d3d9fd2016d927@syzkaller.appspotmail.com
+    Suggested-by: Oliver Neukum 
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/20210903175312.GA468440@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 9618ba622a2d..fa66e6e58792 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -32,6 +32,7 @@
+ #include 
+ #include 
+ #include 	/* for usbcore internals */
++#include 
+ #include 
+ #include 
+ #include 
+@@ -1102,14 +1103,55 @@ static int usbdev_release(struct inode *inode, struct file *file)
+ 	return 0;
+ }
+ 
++static void usbfs_blocking_completion(struct urb *urb)
++{
++	complete((struct completion *) urb->context);
++}
++
++/*
++ * Much like usb_start_wait_urb, but returns status separately from
++ * actual_length and uses a killable wait.
++ */
++static int usbfs_start_wait_urb(struct urb *urb, int timeout,
++		unsigned int *actlen)
++{
++	DECLARE_COMPLETION_ONSTACK(ctx);
++	unsigned long expire;
++	int rc;
++
++	urb->context = &ctx;
++	urb->complete = usbfs_blocking_completion;
++	*actlen = 0;
++	rc = usb_submit_urb(urb, GFP_KERNEL);
++	if (unlikely(rc))
++		return rc;
++
++	expire = (timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT);
++	rc = wait_for_completion_killable_timeout(&ctx, expire);
++	if (rc <= 0) {
++		usb_kill_urb(urb);
++		*actlen = urb->actual_length;
++		if (urb->status != -ENOENT)
++			;	/* Completed before it was killed */
++		else if (rc < 0)
++			return -EINTR;
++		else
++			return -ETIMEDOUT;
++	}
++	*actlen = urb->actual_length;
++	return urb->status;
++}
++
+ static int do_proc_control(struct usb_dev_state *ps,
+ 		struct usbdevfs_ctrltransfer *ctrl)
+ {
+ 	struct usb_device *dev = ps->dev;
+ 	unsigned int tmo;
+ 	unsigned char *tbuf;
+-	unsigned wLength;
++	unsigned int wLength, actlen;
+ 	int i, pipe, ret;
++	struct urb *urb = NULL;
++	struct usb_ctrlrequest *dr = NULL;
+ 
+ 	ret = check_ctrlrecip(ps, ctrl->bRequestType, ctrl->bRequest,
+ 			      ctrl->wIndex);
+@@ -1122,51 +1164,63 @@ static int do_proc_control(struct usb_dev_state *ps,
+ 			sizeof(struct usb_ctrlrequest));
+ 	if (ret)
+ 		return ret;
++
++	ret = -ENOMEM;
+ 	tbuf = (unsigned char *)__get_free_page(GFP_KERNEL);
+-	if (!tbuf) {
+-		ret = -ENOMEM;
++	if (!tbuf)
+ 		goto done;
+-	}
++	urb = usb_alloc_urb(0, GFP_NOIO);
++	if (!urb)
++		goto done;
++	dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
++	if (!dr)
++		goto done;
++
++	dr->bRequestType = ctrl->bRequestType;
++	dr->bRequest = ctrl->bRequest;
++	dr->wValue = cpu_to_le16(ctrl->wValue);
++	dr->wIndex = cpu_to_le16(ctrl->wIndex);
++	dr->wLength = cpu_to_le16(ctrl->wLength);
++
+ 	tmo = ctrl->timeout;
+ 	snoop(&dev->dev, "control urb: bRequestType=%02x "
+ 		"bRequest=%02x wValue=%04x "
+ 		"wIndex=%04x wLength=%04x\n",
+ 		ctrl->bRequestType, ctrl->bRequest, ctrl->wValue,
+ 		ctrl->wIndex, ctrl->wLength);
+-	if ((ctrl->bRequestType & USB_DIR_IN) && ctrl->wLength) {
++
++	if ((ctrl->bRequestType & USB_DIR_IN) && wLength) {
+ 		pipe = usb_rcvctrlpipe(dev, 0);
+-		snoop_urb(dev, NULL, pipe, ctrl->wLength, tmo, SUBMIT, NULL, 0);
++		usb_fill_control_urb(urb, dev, pipe, (unsigned char *) dr, tbuf,
++				wLength, NULL, NULL);
++		snoop_urb(dev, NULL, pipe, wLength, tmo, SUBMIT, NULL, 0);
+ 
+ 		usb_unlock_device(dev);
+-		i = usb_control_msg(dev, pipe, ctrl->bRequest,
+-				    ctrl->bRequestType, ctrl->wValue, ctrl->wIndex,
+-				    tbuf, ctrl->wLength, tmo);
++		i = usbfs_start_wait_urb(urb, tmo, &actlen);
+ 		usb_lock_device(dev);
+-		snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE,
+-			  tbuf, max(i, 0));
+-		if ((i > 0) && ctrl->wLength) {
+-			if (copy_to_user(ctrl->data, tbuf, i)) {
++		snoop_urb(dev, NULL, pipe, actlen, i, COMPLETE, tbuf, actlen);
++		if (!i && actlen) {
++			if (copy_to_user(ctrl->data, tbuf, actlen)) {
+ 				ret = -EFAULT;
+-				goto done;
++				goto recv_fault;
+ 			}
+ 		}
+ 	} else {
+-		if (ctrl->wLength) {
+-			if (copy_from_user(tbuf, ctrl->data, ctrl->wLength)) {
++		if (wLength) {
++			if (copy_from_user(tbuf, ctrl->data, wLength)) {
+ 				ret = -EFAULT;
+ 				goto done;
+ 			}
+ 		}
+ 		pipe = usb_sndctrlpipe(dev, 0);
+-		snoop_urb(dev, NULL, pipe, ctrl->wLength, tmo, SUBMIT,
+-			tbuf, ctrl->wLength);
++		usb_fill_control_urb(urb, dev, pipe, (unsigned char *) dr, tbuf,
++				wLength, NULL, NULL);
++		snoop_urb(dev, NULL, pipe, wLength, tmo, SUBMIT, tbuf, wLength);
+ 
+ 		usb_unlock_device(dev);
+-		i = usb_control_msg(dev, pipe, ctrl->bRequest,
+-				    ctrl->bRequestType, ctrl->wValue, ctrl->wIndex,
+-				    tbuf, ctrl->wLength, tmo);
++		i = usbfs_start_wait_urb(urb, tmo, &actlen);
+ 		usb_lock_device(dev);
+-		snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE, NULL, 0);
++		snoop_urb(dev, NULL, pipe, actlen, i, COMPLETE, NULL, 0);
+ 	}
+ 	if (i < 0 && i != -EPIPE) {
+ 		dev_printk(KERN_DEBUG, &dev->dev, "usbfs: USBDEVFS_CONTROL "
+@@ -1174,8 +1228,15 @@ static int do_proc_control(struct usb_dev_state *ps,
+ 			   current->comm, ctrl->bRequestType, ctrl->bRequest,
+ 			   ctrl->wLength, i);
+ 	}
+-	ret = i;
++	ret = (i < 0 ? i : actlen);
++
++ recv_fault:
++	/* Linger a bit, prior to the next control message. */
++	if (dev->quirks & USB_QUIRK_DELAY_CTRL_MSG)
++		msleep(200);
+  done:
++	kfree(dr);
++	usb_free_urb(urb);
+ 	free_page((unsigned long) tbuf);
+ 	usbfs_decrease_memory_usage(PAGE_SIZE + sizeof(struct urb) +
+ 			sizeof(struct usb_ctrlrequest));
+@@ -1195,10 +1256,11 @@ static int do_proc_bulk(struct usb_dev_state *ps,
+ 		struct usbdevfs_bulktransfer *bulk)
+ {
+ 	struct usb_device *dev = ps->dev;
+-	unsigned int tmo, len1, pipe;
+-	int len2;
++	unsigned int tmo, len1, len2, pipe;
+ 	unsigned char *tbuf;
+ 	int i, ret;
++	struct urb *urb = NULL;
++	struct usb_host_endpoint *ep;
+ 
+ 	ret = findintfep(ps->dev, bulk->ep);
+ 	if (ret < 0)
+@@ -1206,14 +1268,17 @@ static int do_proc_bulk(struct usb_dev_state *ps,
+ 	ret = checkintf(ps, ret);
+ 	if (ret)
+ 		return ret;
++
++	len1 = bulk->len;
++	if (len1 < 0 || len1 >= (INT_MAX - sizeof(struct urb)))
++		return -EINVAL;
++
+ 	if (bulk->ep & USB_DIR_IN)
+ 		pipe = usb_rcvbulkpipe(dev, bulk->ep & 0x7f);
+ 	else
+ 		pipe = usb_sndbulkpipe(dev, bulk->ep & 0x7f);
+-	if (!usb_maxpacket(dev, pipe, !(bulk->ep & USB_DIR_IN)))
+-		return -EINVAL;
+-	len1 = bulk->len;
+-	if (len1 >= (INT_MAX - sizeof(struct urb)))
++	ep = usb_pipe_endpoint(dev, pipe);
++	if (!ep || !usb_endpoint_maxp(&ep->desc))
+ 		return -EINVAL;
+ 	ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb));
+ 	if (ret)
+@@ -1223,17 +1288,29 @@ static int do_proc_bulk(struct usb_dev_state *ps,
+ 	 * len1 can be almost arbitrarily large.  Don't WARN if it's
+ 	 * too big, just fail the request.
+ 	 */
++	ret = -ENOMEM;
+ 	tbuf = kmalloc(len1, GFP_KERNEL | __GFP_NOWARN);
+-	if (!tbuf) {
+-		ret = -ENOMEM;
++	if (!tbuf)
++		goto done;
++	urb = usb_alloc_urb(0, GFP_KERNEL);
++	if (!urb)
+ 		goto done;
++
++	if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
++			USB_ENDPOINT_XFER_INT) {
++		pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);
++		usb_fill_int_urb(urb, dev, pipe, tbuf, len1,
++				NULL, NULL, ep->desc.bInterval);
++	} else {
++		usb_fill_bulk_urb(urb, dev, pipe, tbuf, len1, NULL, NULL);
+ 	}
++
+ 	tmo = bulk->timeout;
+ 	if (bulk->ep & 0x80) {
+ 		snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, NULL, 0);
+ 
+ 		usb_unlock_device(dev);
+-		i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
++		i = usbfs_start_wait_urb(urb, tmo, &len2);
+ 		usb_lock_device(dev);
+ 		snoop_urb(dev, NULL, pipe, len2, i, COMPLETE, tbuf, len2);
+ 
+@@ -1253,12 +1330,13 @@ static int do_proc_bulk(struct usb_dev_state *ps,
+ 		snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, tbuf, len1);
+ 
+ 		usb_unlock_device(dev);
+-		i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
++		i = usbfs_start_wait_urb(urb, tmo, &len2);
+ 		usb_lock_device(dev);
+ 		snoop_urb(dev, NULL, pipe, len2, i, COMPLETE, NULL, 0);
+ 	}
+ 	ret = (i < 0 ? i : len2);
+  done:
++	usb_free_urb(urb);
+ 	kfree(tbuf);
+ 	usbfs_decrease_memory_usage(len1 + sizeof(struct urb));
+ 	return ret;

commit d2f311ec91984adb219ac6985d4dd72c37ae734d
+Author: Alan Stern 
+Date:   Wed Sep 1 12:36:06 2021 -0400
+
+    HID: usbhid: Simplify code in hid_submit_ctrl()
+    
+    This patch makes a small simplification to the code in
+    hid_submit_ctrl().  The test for maxpacket being > 0 is unnecessary,
+    because endpoint 0 always has a maxpacket value which is >= 8.
+    
+    Furthermore, endpoint 0's maxpacket value is always a power of 2, so
+    instead of open-coding the round-to-next-multiple computation we can
+    call the optimized round_up() routine.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Benjamin Tissoires 
+    Acked-by: Benjamin Tissoires 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index c56cb03c1551..2dcaf31eb9cd 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -388,14 +388,10 @@ static int hid_submit_ctrl(struct hid_device *hid)
+ 		usbhid->urbctrl->pipe = usb_rcvctrlpipe(hid_to_usb_dev(hid), 0);
+ 		maxpacket = usb_maxpacket(hid_to_usb_dev(hid),
+ 					  usbhid->urbctrl->pipe, 0);
+-		if (maxpacket > 0) {
+-			len += (len == 0);    /* Don't allow 0-length reports */
+-			len = DIV_ROUND_UP(len, maxpacket);
+-			len *= maxpacket;
+-			if (len > usbhid->bufsize)
+-				len = usbhid->bufsize;
+-		} else
+-			len = 0;
++		len += (len == 0);	/* Don't allow 0-length reports */
++		len = round_up(len, maxpacket);
++		if (len > usbhid->bufsize)
++			len = usbhid->bufsize;
+ 	}
+ 	usbhid->urbctrl->transfer_buffer_length = len;
+ 	usbhid->urbctrl->dev = hid_to_usb_dev(hid);

commit 0a824efdb724e07574bafcd2c2486b2a3de35ff6
+Author: Alan Stern 
+Date:   Wed Sep 1 12:36:00 2021 -0400
+
+    HID: usbhid: Fix warning caused by 0-length input reports
+    
+    Syzbot found a warning caused by hid_submit_ctrl() submitting a
+    control request to transfer a 0-length input report:
+    
+            usb 1-1: BOGUS control dir, pipe 80000280 doesn't match bRequestType a1
+    
+    (The warning message is a little difficult to understand.  It means
+    that the control request claims to be for an IN transfer but this
+    contradicts the USB spec, which requires 0-length control transfers
+    always to be in the OUT direction.)
+    
+    Now, a zero-length report isn't good for anything and there's no
+    reason for a device to have one, but the fuzzer likes to pick out
+    these weird edge cases.  In the future, perhaps we will decide to
+    reject 0-length reports at probe time.  For now, the simplest approach
+    for avoiding these warnings is to pretend that the report actually has
+    length 1.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: syzbot+9b57a46bf1801ce2a2ca@syzkaller.appspotmail.com
+    Tested-by: Oleksandr Natalenko 
+    Tested-by: Benjamin Tissoires 
+    Acked-by: Benjamin Tissoires 
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index 6b8690878435..c56cb03c1551 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -389,6 +389,7 @@ static int hid_submit_ctrl(struct hid_device *hid)
+ 		maxpacket = usb_maxpacket(hid_to_usb_dev(hid),
+ 					  usbhid->urbctrl->pipe, 0);
+ 		if (maxpacket > 0) {
++			len += (len == 0);    /* Don't allow 0-length reports */
+ 			len = DIV_ROUND_UP(len, maxpacket);
+ 			len *= maxpacket;
+ 			if (len > usbhid->bufsize)

commit b0863f1927323110e3d0d69f6adb6a91018a9a3c
+Author: Alan Stern 
+Date:   Mon Jul 12 14:54:36 2021 -0400
+
+    USB: core: Fix incorrect pipe calculation in do_proc_control()
+    
+    When the user submits a control URB via usbfs, the user supplies the
+    bRequestType value and the kernel uses it to compute the pipe value.
+    However, do_proc_control() performs this computation incorrectly in
+    the case where the bRequestType direction bit is set to USB_DIR_IN and
+    the URB's transfer length is 0: The pipe's direction is also set to IN
+    but it should be OUT, which is the direction the actual transfer will
+    use regardless of bRequestType.
+    
+    Commit 5cc59c418fde ("USB: core: WARN if pipe direction != setup
+    packet direction") added a check to compare the direction bit in the
+    pipe value to a control URB's actual direction and to WARN if they are
+    different.  This can be triggered by the incorrect computation
+    mentioned above, as found by syzbot.
+    
+    This patch fixes the computation, thus avoiding the WARNing.
+    
+    Reported-and-tested-by: syzbot+72af3105289dcb4c055b@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/20210712185436.GB326369@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index b97464498763..9618ba622a2d 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -1133,7 +1133,7 @@ static int do_proc_control(struct usb_dev_state *ps,
+ 		"wIndex=%04x wLength=%04x\n",
+ 		ctrl->bRequestType, ctrl->bRequest, ctrl->wValue,
+ 		ctrl->wIndex, ctrl->wLength);
+-	if (ctrl->bRequestType & 0x80) {
++	if ((ctrl->bRequestType & USB_DIR_IN) && ctrl->wLength) {
+ 		pipe = usb_rcvctrlpipe(dev, 0);
+ 		snoop_urb(dev, NULL, pipe, ctrl->wLength, tmo, SUBMIT, NULL, 0);
+ 

commit 60dfe484cef45293e631b3a6e8995f1689818172
+Author: Alan Stern 
+Date:   Mon Jun 7 11:23:07 2021 -0400
+
+    USB: core: Avoid WARNings for 0-length descriptor requests
+    
+    The USB core has utility routines to retrieve various types of
+    descriptors.  These routines will now provoke a WARN if they are asked
+    to retrieve 0 bytes (USB "receive" requests must not have zero
+    length), so avert this by checking the size argument at the start.
+    
+    CC: Johan Hovold 
+    Reported-and-tested-by: syzbot+7dbcd9ff34dc4ed45240@syzkaller.appspotmail.com
+    Reviewed-by: Johan Hovold 
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/20210607152307.GD1768031@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 30e9e680c74c..4d59d927ae3e 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -783,6 +783,9 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type,
+ 	int i;
+ 	int result;
+ 
++	if (size <= 0)		/* No point in asking for no data */
++		return -EINVAL;
++
+ 	memset(buf, 0, size);	/* Make sure we parse really received data */
+ 
+ 	for (i = 0; i < 3; ++i) {
+@@ -832,6 +835,9 @@ static int usb_get_string(struct usb_device *dev, unsigned short langid,
+ 	int i;
+ 	int result;
+ 
++	if (size <= 0)		/* No point in asking for no data */
++		return -EINVAL;
++
+ 	for (i = 0; i < 3; ++i) {
+ 		/* retry on length 0 or stall; some devices are flakey */
+ 		result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),

commit 87191ca9f90244d4e003fbe5c77390b5e585a5ef
+Author: Alan Stern 
+Date:   Thu May 20 16:22:06 2021 -0400
+
+    USB: UDC: Implement udc_async_callbacks in net2272
+    
+    This patch adds a udc_async_callbacks handler to the net2272 UDC
+    driver, which will prevent a theoretical race during gadget unbinding.
+    
+    The net2272 driver is sufficiently complicated that I didn't want to
+    mess around with IRQ settings.  Instead, the patch simply adds a new
+    flag to control async callbacks, and checks the flag before issuing
+    any of them.
+    
+    Acked-by: Felipe Balbi 
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/20210520202206.GF1216852@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c
+index 89f479b78d80..7c38057dcb4a 100644
+--- a/drivers/usb/gadget/udc/net2272.c
++++ b/drivers/usb/gadget/udc/net2272.c
+@@ -1150,6 +1150,7 @@ net2272_pullup(struct usb_gadget *_gadget, int is_on)
+ static int net2272_start(struct usb_gadget *_gadget,
+ 		struct usb_gadget_driver *driver);
+ static int net2272_stop(struct usb_gadget *_gadget);
++static void net2272_async_callbacks(struct usb_gadget *_gadget, bool enable);
+ 
+ static const struct usb_gadget_ops net2272_ops = {
+ 	.get_frame	= net2272_get_frame,
+@@ -1158,6 +1159,7 @@ static const struct usb_gadget_ops net2272_ops = {
+ 	.pullup		= net2272_pullup,
+ 	.udc_start	= net2272_start,
+ 	.udc_stop	= net2272_stop,
++	.udc_async_callbacks = net2272_async_callbacks,
+ };
+ 
+ /*---------------------------------------------------------------------------*/
+@@ -1476,7 +1478,7 @@ stop_activity(struct net2272 *dev, struct usb_gadget_driver *driver)
+ 		net2272_dequeue_all(&dev->ep[i]);
+ 
+ 	/* report disconnect; the driver is already quiesced */
+-	if (driver) {
++	if (dev->async_callbacks && driver) {
+ 		spin_unlock(&dev->lock);
+ 		driver->disconnect(&dev->gadget);
+ 		spin_lock(&dev->lock);
+@@ -1501,6 +1503,15 @@ static int net2272_stop(struct usb_gadget *_gadget)
+ 	return 0;
+ }
+ 
++static void net2272_async_callbacks(struct usb_gadget *_gadget, bool enable)
++{
++	struct net2272	*dev = container_of(_gadget, struct net2272, gadget);
++
++	spin_lock_irq(&dev->lock);
++	dev->async_callbacks = enable;
++	spin_unlock_irq(&dev->lock);
++}
++
+ /*---------------------------------------------------------------------------*/
+ /* handle ep-a/ep-b dma completions */
+ static void
+@@ -1910,9 +1921,11 @@ net2272_handle_stat0_irqs(struct net2272 *dev, u8 stat)
+ 				u.r.bRequestType, u.r.bRequest,
+ 				u.r.wValue, u.r.wIndex,
+ 				net2272_ep_read(ep, EP_CFG));
+-			spin_unlock(&dev->lock);
+-			tmp = dev->driver->setup(&dev->gadget, &u.r);
+-			spin_lock(&dev->lock);
++			if (dev->async_callbacks) {
++				spin_unlock(&dev->lock);
++				tmp = dev->driver->setup(&dev->gadget, &u.r);
++				spin_lock(&dev->lock);
++			}
+ 		}
+ 
+ 		/* stall ep0 on error */
+@@ -1994,14 +2007,14 @@ net2272_handle_stat1_irqs(struct net2272 *dev, u8 stat)
+ 			if (disconnect || reset) {
+ 				stop_activity(dev, dev->driver);
+ 				net2272_ep0_start(dev);
+-				spin_unlock(&dev->lock);
+-				if (reset)
+-					usb_gadget_udc_reset
+-						(&dev->gadget, dev->driver);
+-				else
+-					(dev->driver->disconnect)
+-						(&dev->gadget);
+-				spin_lock(&dev->lock);
++				if (dev->async_callbacks) {
++					spin_unlock(&dev->lock);
++					if (reset)
++						usb_gadget_udc_reset(&dev->gadget, dev->driver);
++					else
++						(dev->driver->disconnect)(&dev->gadget);
++					spin_lock(&dev->lock);
++				}
+ 				return;
+ 			}
+ 		}
+@@ -2015,14 +2028,14 @@ net2272_handle_stat1_irqs(struct net2272 *dev, u8 stat)
+ 	if (stat & tmp) {
+ 		net2272_write(dev, IRQSTAT1, tmp);
+ 		if (stat & (1 << SUSPEND_REQUEST_INTERRUPT)) {
+-			if (dev->driver->suspend)
++			if (dev->async_callbacks && dev->driver->suspend)
+ 				dev->driver->suspend(&dev->gadget);
+ 			if (!enable_suspend) {
+ 				stat &= ~(1 << SUSPEND_REQUEST_INTERRUPT);
+ 				dev_dbg(dev->dev, "Suspend disabled, ignoring\n");
+ 			}
+ 		} else {
+-			if (dev->driver->resume)
++			if (dev->async_callbacks && dev->driver->resume)
+ 				dev->driver->resume(&dev->gadget);
+ 		}
+ 		stat &= ~tmp;
+diff --git a/drivers/usb/gadget/udc/net2272.h b/drivers/usb/gadget/udc/net2272.h
+index c669308111c2..a9994f737588 100644
+--- a/drivers/usb/gadget/udc/net2272.h
++++ b/drivers/usb/gadget/udc/net2272.h
+@@ -442,6 +442,7 @@ struct net2272 {
+ 	         softconnect:1,
+ 	         wakeup:1,
+ 		 added:1,
++		 async_callbacks:1,
+ 	         dma_eot_polarity:1,
+ 	         dma_dack_polarity:1,
+ 	         dma_dreq_polarity:1,

commit b42e8090ba93526d6063108b25e5fc0f11f58770
+Author: Alan Stern 
+Date:   Thu May 20 16:22:00 2021 -0400
+
+    USB: UDC: Implement udc_async_callbacks in net2280
+    
+    This patch adds a udc_async_callbacks handler to the net2280 UDC
+    driver, which will prevent a theoretical race during gadget unbinding.
+    
+    The net2280 driver is sufficiently complicated that I didn't want to
+    mess around with IRQ settings.  Instead, the patch simply adds a new
+    flag to control async callbacks, and checks the flag before issuing
+    any of them.
+    
+    Acked-by: Felipe Balbi 
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/20210520202200.GE1216852@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c
+index fc9f99fe7f37..0e0458e3662b 100644
+--- a/drivers/usb/gadget/udc/net2280.c
++++ b/drivers/usb/gadget/udc/net2280.c
+@@ -1617,6 +1617,7 @@ static struct usb_ep *net2280_match_ep(struct usb_gadget *_gadget,
+ static int net2280_start(struct usb_gadget *_gadget,
+ 		struct usb_gadget_driver *driver);
+ static int net2280_stop(struct usb_gadget *_gadget);
++static void net2280_async_callbacks(struct usb_gadget *_gadget, bool enable);
+ 
+ static const struct usb_gadget_ops net2280_ops = {
+ 	.get_frame	= net2280_get_frame,
+@@ -1625,6 +1626,7 @@ static const struct usb_gadget_ops net2280_ops = {
+ 	.pullup		= net2280_pullup,
+ 	.udc_start	= net2280_start,
+ 	.udc_stop	= net2280_stop,
++	.udc_async_callbacks = net2280_async_callbacks,
+ 	.match_ep	= net2280_match_ep,
+ };
+ 
+@@ -2472,7 +2474,7 @@ static void stop_activity(struct net2280 *dev, struct usb_gadget_driver *driver)
+ 		nuke(&dev->ep[i]);
+ 
+ 	/* report disconnect; the driver is already quiesced */
+-	if (driver) {
++	if (dev->async_callbacks && driver) {
+ 		spin_unlock(&dev->lock);
+ 		driver->disconnect(&dev->gadget);
+ 		spin_lock(&dev->lock);
+@@ -2502,6 +2504,15 @@ static int net2280_stop(struct usb_gadget *_gadget)
+ 	return 0;
+ }
+ 
++static void net2280_async_callbacks(struct usb_gadget *_gadget, bool enable)
++{
++	struct net2280	*dev = container_of(_gadget, struct net2280, gadget);
++
++	spin_lock_irq(&dev->lock);
++	dev->async_callbacks = enable;
++	spin_unlock_irq(&dev->lock);
++}
++
+ /*-------------------------------------------------------------------------*/
+ 
+ /* handle ep0, ep-e, ep-f with 64 byte packets: packet per irq.
+@@ -3042,9 +3053,11 @@ static void handle_stat0_irqs_superspeed(struct net2280 *dev,
+ 				readl(&ep->cfg->ep_cfg));
+ 
+ 		ep->responded = 0;
+-		spin_unlock(&dev->lock);
+-		tmp = dev->driver->setup(&dev->gadget, &r);
+-		spin_lock(&dev->lock);
++		if (dev->async_callbacks) {
++			spin_unlock(&dev->lock);
++			tmp = dev->driver->setup(&dev->gadget, &r);
++			spin_lock(&dev->lock);
++		}
+ 	}
+ do_stall3:
+ 	if (tmp < 0) {
+@@ -3284,9 +3297,11 @@ static void handle_stat0_irqs(struct net2280 *dev, u32 stat)
+ 				w_value, w_index, w_length,
+ 				readl(&ep->cfg->ep_cfg));
+ 			ep->responded = 0;
+-			spin_unlock(&dev->lock);
+-			tmp = dev->driver->setup(&dev->gadget, &u.r);
+-			spin_lock(&dev->lock);
++			if (dev->async_callbacks) {
++				spin_unlock(&dev->lock);
++				tmp = dev->driver->setup(&dev->gadget, &u.r);
++				spin_lock(&dev->lock);
++			}
+ 		}
+ 
+ 		/* stall ep0 on error */
+@@ -3391,14 +3406,14 @@ __acquires(dev->lock)
+ 			if (disconnect || reset) {
+ 				stop_activity(dev, dev->driver);
+ 				ep0_start(dev);
+-				spin_unlock(&dev->lock);
+-				if (reset)
+-					usb_gadget_udc_reset
+-						(&dev->gadget, dev->driver);
+-				else
+-					(dev->driver->disconnect)
+-						(&dev->gadget);
+-				spin_lock(&dev->lock);
++				if (dev->async_callbacks) {
++					spin_unlock(&dev->lock);
++					if (reset)
++						usb_gadget_udc_reset(&dev->gadget, dev->driver);
++					else
++						(dev->driver->disconnect)(&dev->gadget);
++					spin_lock(&dev->lock);
++				}
+ 				return;
+ 			}
+ 		}
+@@ -3419,12 +3434,12 @@ __acquires(dev->lock)
+ 		writel(tmp, &dev->regs->irqstat1);
+ 		spin_unlock(&dev->lock);
+ 		if (stat & BIT(SUSPEND_REQUEST_INTERRUPT)) {
+-			if (dev->driver->suspend)
++			if (dev->async_callbacks && dev->driver->suspend)
+ 				dev->driver->suspend(&dev->gadget);
+ 			if (!enable_suspend)
+ 				stat &= ~BIT(SUSPEND_REQUEST_INTERRUPT);
+ 		} else {
+-			if (dev->driver->resume)
++			if (dev->async_callbacks && dev->driver->resume)
+ 				dev->driver->resume(&dev->gadget);
+ 			/* at high speed, note erratum 0133 */
+ 		}
+diff --git a/drivers/usb/gadget/udc/net2280.h b/drivers/usb/gadget/udc/net2280.h
+index 7da3dc1e9729..34716a9f4926 100644
+--- a/drivers/usb/gadget/udc/net2280.h
++++ b/drivers/usb/gadget/udc/net2280.h
+@@ -162,6 +162,7 @@ struct net2280 {
+ 					ltm_enable:1,
+ 					wakeup_enable:1,
+ 					addressed_state:1,
++					async_callbacks:1,
+ 					bug7734_patched:1;
+ 	u16				chiprev;
+ 	int enhanced_mode;

commit 04145a03db9d78469e0817ab3a767c76c0fb0947
+Author: Alan Stern 
+Date:   Thu May 20 16:21:52 2021 -0400
+
+    USB: UDC: Implement udc_async_callbacks in dummy-hcd
+    
+    This patch adds a udc_async_callbacks handler to the dummy-hcd UDC
+    driver, which will prevent a theoretical race during gadget unbinding.
+    
+    The implementation is simple, since dummy-hcd already has a flag to
+    keep track of whether emulated IRQs are enabled.  All the handler has
+    to do is store the enable value in the flag, and avoid setting the
+    flag prematurely.
+    
+    Acked-by: Felipe Balbi 
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/20210520202152.GD1216852@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
+index 7db773c87379..a2d956af42a2 100644
+--- a/drivers/usb/gadget/udc/dummy_hcd.c
++++ b/drivers/usb/gadget/udc/dummy_hcd.c
+@@ -934,6 +934,15 @@ static void dummy_udc_set_speed(struct usb_gadget *_gadget,
+ 	dummy_udc_update_ep0(dum);
+ }
+ 
++static void dummy_udc_async_callbacks(struct usb_gadget *_gadget, bool enable)
++{
++	struct dummy	*dum = gadget_dev_to_dummy(&_gadget->dev);
++
++	spin_lock_irq(&dum->lock);
++	dum->ints_enabled = enable;
++	spin_unlock_irq(&dum->lock);
++}
++
+ static int dummy_udc_start(struct usb_gadget *g,
+ 		struct usb_gadget_driver *driver);
+ static int dummy_udc_stop(struct usb_gadget *g);
+@@ -946,6 +955,7 @@ static const struct usb_gadget_ops dummy_ops = {
+ 	.udc_start	= dummy_udc_start,
+ 	.udc_stop	= dummy_udc_stop,
+ 	.udc_set_speed	= dummy_udc_set_speed,
++	.udc_async_callbacks = dummy_udc_async_callbacks,
+ };
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -1005,7 +1015,6 @@ static int dummy_udc_start(struct usb_gadget *g,
+ 	spin_lock_irq(&dum->lock);
+ 	dum->devstatus = 0;
+ 	dum->driver = driver;
+-	dum->ints_enabled = 1;
+ 	spin_unlock_irq(&dum->lock);
+ 
+ 	return 0;

commit 7dc0c55e9f302e7048e040ee4437437bbea1e2cd
+Author: Alan Stern 
+Date:   Thu May 20 16:21:44 2021 -0400
+
+    USB: UDC core: Add udc_async_callbacks gadget op
+    
+    The Gadget API has a theoretical race when a gadget driver is unbound.
+    Although the pull-up is turned off before the driver's ->unbind
+    callback runs, if the USB cable were to be unplugged at just the wrong
+    moment there would be nothing to prevent the UDC driver from invoking
+    the ->disconnect callback after the unbind has finished.  In theory,
+    other asynchronous callbacks could also happen during the time before
+    the UDC driver's udc_stop routine is called, and the gadget driver
+    would not be prepared to handle any of them.
+    
+    We need a way to tell UDC drivers to stop issuing asynchronous (that is,
+    ->suspend, ->resume, ->disconnect, ->reset, or ->setup) callbacks at
+    some point after the pull-up has been turned off and before the
+    ->unbind callback runs.  This patch adds a new ->udc_async_callbacks
+    callback to the usb_gadget_ops structure for precisely this purpose,
+    and it adds the corresponding support to the UDC core.
+    
+    Later patches in this series add support for udc_async_callbacks to
+    several UDC drivers.
+    
+    Acked-by: Felipe Balbi 
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/20210520202144.GC1216852@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
+index 493ff93f7dda..b7f0b1ebaaa8 100644
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -1147,6 +1147,53 @@ static inline void usb_gadget_udc_set_speed(struct usb_udc *udc,
+ 		gadget->ops->udc_set_speed(gadget, s);
+ }
+ 
++/**
++ * usb_gadget_enable_async_callbacks - tell usb device controller to enable asynchronous callbacks
++ * @udc: The UDC which should enable async callbacks
++ *
++ * This routine is used when binding gadget drivers.  It undoes the effect
++ * of usb_gadget_disable_async_callbacks(); the UDC driver should enable IRQs
++ * (if necessary) and resume issuing callbacks.
++ *
++ * This routine will always be called in process context.
++ */
++static inline void usb_gadget_enable_async_callbacks(struct usb_udc *udc)
++{
++	struct usb_gadget *gadget = udc->gadget;
++
++	if (gadget->ops->udc_async_callbacks)
++		gadget->ops->udc_async_callbacks(gadget, true);
++}
++
++/**
++ * usb_gadget_disable_async_callbacks - tell usb device controller to disable asynchronous callbacks
++ * @udc: The UDC which should disable async callbacks
++ *
++ * This routine is used when unbinding gadget drivers.  It prevents a race:
++ * The UDC driver doesn't know when the gadget driver's ->unbind callback
++ * runs, so unless it is told to disable asynchronous callbacks, it might
++ * issue a callback (such as ->disconnect) after the unbind has completed.
++ *
++ * After this function runs, the UDC driver must suppress all ->suspend,
++ * ->resume, ->disconnect, ->reset, and ->setup callbacks to the gadget driver
++ * until async callbacks are again enabled.  A simple-minded but effective
++ * way to accomplish this is to tell the UDC hardware not to generate any
++ * more IRQs.
++ *
++ * Request completion callbacks must still be issued.  However, it's okay
++ * to defer them until the request is cancelled, since the pull-up will be
++ * turned off during the time period when async callbacks are disabled.
++ *
++ * This routine will always be called in process context.
++ */
++static inline void usb_gadget_disable_async_callbacks(struct usb_udc *udc)
++{
++	struct usb_gadget *gadget = udc->gadget;
++
++	if (gadget->ops->udc_async_callbacks)
++		gadget->ops->udc_async_callbacks(gadget, false);
++}
++
+ /**
+  * usb_udc_release - release the usb_udc struct
+  * @dev: the dev member within usb_udc
+@@ -1361,6 +1408,7 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
+ 	kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
+ 
+ 	usb_gadget_disconnect(udc->gadget);
++	usb_gadget_disable_async_callbacks(udc);
+ 	if (udc->gadget->irq)
+ 		synchronize_irq(udc->gadget->irq);
+ 	udc->driver->unbind(udc->gadget);
+@@ -1442,6 +1490,7 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
+ 		driver->unbind(udc->gadget);
+ 		goto err1;
+ 	}
++	usb_gadget_enable_async_callbacks(udc);
+ 	usb_udc_connect_control(udc);
+ 
+ 	kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
+diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
+index 8811eb96e5cc..75c7538e350a 100644
+--- a/include/linux/usb/gadget.h
++++ b/include/linux/usb/gadget.h
+@@ -325,6 +325,7 @@ struct usb_gadget_ops {
+ 	void	(*udc_set_speed)(struct usb_gadget *, enum usb_device_speed);
+ 	void	(*udc_set_ssp_rate)(struct usb_gadget *gadget,
+ 			enum usb_ssp_rate rate);
++	void	(*udc_async_callbacks)(struct usb_gadget *gadget, bool enable);
+ 	struct usb_ep *(*match_ep)(struct usb_gadget *,
+ 			struct usb_endpoint_descriptor *,
+ 			struct usb_ss_ep_comp_descriptor *);

commit 7652dd2c5cb7b656471cc801d619fe24120643a3
+Author: Alan Stern 
+Date:   Wed May 26 11:32:44 2021 -0400
+
+    USB: core: Check buffer length matches wLength for control transfers
+    
+    A type of inconsistency that can show up in control URBs is when the
+    setup packet's wLength value does not match the URB's
+    transfer_buffer_length field.  The two should always be equal;
+    differences could lead to information leaks or undefined behavior for
+    OUT transfers or overruns for IN transfers.
+    
+    This patch adds a test for such mismatches during URB submission.  If
+    the test fails, the submission is rejected with a -EBADR error code
+    (which is not used elsewhere in the USB core), and a debugging message
+    is logged for people interested in tracking down these errors.
+    
+    Reviewed-by: Johan Hovold 
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/20210526153244.GA1400430@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/driver-api/usb/error-codes.rst b/Documentation/driver-api/usb/error-codes.rst
+index a3e84bfac776..8f9790c2d6f8 100644
+--- a/Documentation/driver-api/usb/error-codes.rst
++++ b/Documentation/driver-api/usb/error-codes.rst
+@@ -61,6 +61,9 @@ USB-specific:
+ 			(c) requested data transfer length is invalid: negative
+ 			    or too large for the host controller.
+ 
++``-EBADR``		The wLength value in a control URB's setup packet does
++			not match the URB's transfer_buffer_length.
++
+ ``-ENOSPC``		This request would overcommit the usb bandwidth reserved
+ 			for periodic transfers (interrupt, isochronous).
+ 
+diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
+index 279b3921ff8f..30727729a44c 100644
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -410,6 +410,12 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 		dev_WARN_ONCE(&dev->dev, (usb_pipeout(urb->pipe) != is_out),
+ 				"BOGUS control dir, pipe %x doesn't match bRequestType %x\n",
+ 				urb->pipe, setup->bRequestType);
++		if (le16_to_cpu(setup->wLength) != urb->transfer_buffer_length) {
++			dev_dbg(&dev->dev, "BOGUS control len %d doesn't match transfer length %d\n",
++					le16_to_cpu(setup->wLength),
++					urb->transfer_buffer_length);
++			return -EBADR;
++		}
+ 	} else {
+ 		is_out = usb_endpoint_dir_out(&ep->desc);
+ 	}

commit 5cc59c418fde9d02859996707b9d5dfd2941c50b
+Author: Alan Stern 
+Date:   Fri May 21 22:16:23 2021 -0400
+
+    USB: core: WARN if pipe direction != setup packet direction
+    
+    When a control URB is submitted, the direction indicated by URB's pipe
+    member is supposed to match the direction indicated by the setup
+    packet's bRequestType member.  A mismatch could lead to trouble,
+    depending on which field the host controller drivers use for
+    determining the actual direction.
+    
+    This shouldn't ever happen; it would represent a careless bug in a
+    kernel driver somewhere.  This patch adds a dev_WARN_ONCE to let
+    people know about the potential problem.
+    
+    Suggested-by: "Geoffrey D. Bennett" 
+    Reviewed-by: Johan Hovold 
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/20210522021623.GB1260282@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
+index 357b149b20d3..279b3921ff8f 100644
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -407,6 +407,9 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 			return -ENOEXEC;
+ 		is_out = !(setup->bRequestType & USB_DIR_IN) ||
+ 				!setup->wLength;
++		dev_WARN_ONCE(&dev->dev, (usb_pipeout(urb->pipe) != is_out),
++				"BOGUS control dir, pipe %x doesn't match bRequestType %x\n",
++				urb->pipe, setup->bRequestType);
+ 	} else {
+ 		is_out = usb_endpoint_dir_out(&ep->desc);
+ 	}

commit 4f2629ea67e7225c3fd292c7fe4f5b3c9d6392de
+Author: Alan Stern 
+Date:   Tue May 18 16:18:35 2021 -0400
+
+    USB: usbfs: Don't WARN about excessively large memory allocations
+    
+    Syzbot found that the kernel generates a WARNing if the user tries to
+    submit a bulk transfer through usbfs with a buffer that is way too
+    large.  This isn't a bug in the kernel; it's merely an invalid request
+    from the user and the usbfs code does handle it correctly.
+    
+    In theory the same thing can happen with async transfers, or with the
+    packet descriptor table for isochronous transfers.
+    
+    To prevent the MM subsystem from complaining about these bad
+    allocation requests, add the __GFP_NOWARN flag to the kmalloc calls
+    for these buffers.
+    
+    CC: Andrew Morton 
+    CC: 
+    Reported-and-tested-by: syzbot+882a85c0c8ec4a3e2281@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/20210518201835.GA1140918@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 533236366a03..2218941d35a3 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -1218,7 +1218,12 @@ static int do_proc_bulk(struct usb_dev_state *ps,
+ 	ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb));
+ 	if (ret)
+ 		return ret;
+-	tbuf = kmalloc(len1, GFP_KERNEL);
++
++	/*
++	 * len1 can be almost arbitrarily large.  Don't WARN if it's
++	 * too big, just fail the request.
++	 */
++	tbuf = kmalloc(len1, GFP_KERNEL | __GFP_NOWARN);
+ 	if (!tbuf) {
+ 		ret = -ENOMEM;
+ 		goto done;
+@@ -1696,7 +1701,7 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
+ 	if (num_sgs) {
+ 		as->urb->sg = kmalloc_array(num_sgs,
+ 					    sizeof(struct scatterlist),
+-					    GFP_KERNEL);
++					    GFP_KERNEL | __GFP_NOWARN);
+ 		if (!as->urb->sg) {
+ 			ret = -ENOMEM;
+ 			goto error;
+@@ -1731,7 +1736,7 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
+ 					(uurb_start - as->usbm->vm_start);
+ 		} else {
+ 			as->urb->transfer_buffer = kmalloc(uurb->buffer_length,
+-					GFP_KERNEL);
++					GFP_KERNEL | __GFP_NOWARN);
+ 			if (!as->urb->transfer_buffer) {
+ 				ret = -ENOMEM;
+ 				goto error;

commit 2c412337cfe655bcc6adff8904fc653a1678f70f
+Author: Alan Stern 
+Date:   Thu Apr 8 11:22:09 2021 -0400
+
+    PM: runtime: Add documentation for pm_runtime_resume_and_get()
+    
+    Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to
+    deal with usage counter") added a new runtime-PM API function without
+    updating the documentation in runtime_pm.rst.
+    
+    Add the missing documentation.
+    
+    Signed-off-by: Alan Stern 
+    Fixes: dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with usage counter")
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/Documentation/power/runtime_pm.rst b/Documentation/power/runtime_pm.rst
+index d9c777b18f7a..18ae21bf7f92 100644
+--- a/Documentation/power/runtime_pm.rst
++++ b/Documentation/power/runtime_pm.rst
+@@ -339,6 +339,10 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
+       checked additionally, and -EACCES means that 'power.disable_depth' is
+       different from 0
+ 
++  `int pm_runtime_resume_and_get(struct device *dev);`
++    - run pm_runtime_resume(dev) and if successful, increment the device's
++      usage counter; return the result of pm_runtime_resume
++
+   `int pm_request_idle(struct device *dev);`
+     - submit a request to execute the subsystem-level idle callback for the
+       device (the request is represented by a work item in pm_wq); returns 0 on

commit 546aa0e4ea6ed81b6c51baeebc4364542fa3f3a7
+Author: Alan Stern 
+Date:   Wed Mar 17 15:06:54 2021 -0400
+
+    usb-storage: Add quirk to defeat Kindle's automatic unload
+    
+    Matthias reports that the Amazon Kindle automatically removes its
+    emulated media if it doesn't receive another SCSI command within about
+    one second after a SYNCHRONIZE CACHE.  It does so even when the host
+    has sent a PREVENT MEDIUM REMOVAL command.  The reason for this
+    behavior isn't clear, although it's not hard to make some guesses.
+    
+    At any rate, the results can be unexpected for anyone who tries to
+    access the Kindle in an unusual fashion, and in theory they can lead
+    to data loss (for example, if one file is closed and synchronized
+    while other files are still in the middle of being written).
+    
+    To avoid such problems, this patch creates a new usb-storage quirks
+    flag telling the driver always to issue a REQUEST SENSE following a
+    SYNCHRONIZE CACHE command, and adds an unusual_devs entry for the
+    Kindle with the flag set.  This is sufficient to prevent the Kindle
+    from doing its automatic unload, without interfering with proper
+    operation.
+    
+    Another possible way to deal with this would be to increase the
+    frequency of TEST UNIT READY polling that the kernel normally carries
+    out for removable-media storage devices.  However that would increase
+    the overall load on the system and it is not as reliable, because the
+    user can override the polling interval.  Changing the driver's
+    behavior is safer and has minimal overhead.
+    
+    CC: 
+    Reported-and-tested-by: Matthias Schwarzott 
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/20210317190654.GA497856@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+index 5eb895b19c55..f4304ce69350 100644
+--- a/drivers/usb/storage/transport.c
++++ b/drivers/usb/storage/transport.c
+@@ -656,6 +656,13 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 		need_auto_sense = 1;
+ 	}
+ 
++	/* Some devices (Kindle) require another command after SYNC CACHE */
++	if ((us->fflags & US_FL_SENSE_AFTER_SYNC) &&
++			srb->cmnd[0] == SYNCHRONIZE_CACHE) {
++		usb_stor_dbg(us, "-- sense after SYNC CACHE\n");
++		need_auto_sense = 1;
++	}
++
+ 	/*
+ 	 * If we have a failure, we're going to do a REQUEST_SENSE 
+ 	 * automatically.  Note that we differentiate between a command
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 5732e9691f08..efa972be2ee3 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -2211,6 +2211,18 @@ UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200,
+ 		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ 		US_FL_NO_READ_DISC_INFO ),
+ 
++/*
++ * Reported by Matthias Schwarzott 
++ * The Amazon Kindle treats SYNCHRONIZE CACHE as an indication that
++ * the host may be finished with it, and automatically ejects its
++ * emulated media unless it receives another command within one second.
++ */
++UNUSUAL_DEV( 0x1949, 0x0004, 0x0000, 0x9999,
++		"Amazon",
++		"Kindle",
++		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
++		US_FL_SENSE_AFTER_SYNC ),
++
+ /*
+  * Reported by Oliver Neukum 
+  * This device morphes spontaneously into another device if the access
+diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
+index 6b03fdd69d27..712363c7a2e8 100644
+--- a/include/linux/usb_usual.h
++++ b/include/linux/usb_usual.h
+@@ -86,6 +86,8 @@
+ 		/* lies about caching, so always sync */	\
+ 	US_FLAG(NO_SAME, 0x40000000)				\
+ 		/* Cannot handle WRITE_SAME */			\
++	US_FLAG(SENSE_AFTER_SYNC, 0x80000000)			\
++		/* Do REQUEST_SENSE after SYNCHRONIZE_CACHE */	\
+ 
+ #define US_FLAG(name, value)	US_FL_##name = value ,
+ enum { US_DO_ALL_FLAGS };

commit 6e6aa61d81194c01283880950df563b1b9abec46
+Author: Alan Stern 
+Date:   Wed Jan 13 14:45:10 2021 -0500
+
+    USB: gadget: dummy-hcd: Fix errors in port-reset handling
+    
+    Commit c318840fb2a4 ("USB: Gadget: dummy-hcd: Fix shift-out-of-bounds
+    bug") messed up the way dummy-hcd handles requests to turn on the
+    RESET port feature (I didn't notice that the original switch case
+    ended with a fallthrough).  The call to set_link_state() was
+    inadvertently removed, as was the code to set the USB_PORT_STAT_RESET
+    flag when the speed is USB2.
+    
+    In addition, the original code never checked whether the port was
+    connected before handling the port-reset request.  There was a check
+    for the port being powered, but it was removed by that commit!  In
+    practice this doesn't matter much because the kernel doesn't try to
+    reset disconnected ports, but it's still bad form.
+    
+    This patch fixes these problems by changing the fallthrough to break,
+    adding back in the missing set_link_state() call, setting the
+    port-reset status flag, adding a port-is-connected test, and removing
+    a redundant assignment statement.
+    
+    Fixes: c318840fb2a4 ("USB: Gadget: dummy-hcd: Fix shift-out-of-bounds bug")
+    CC: 
+    Acked-by: Felipe Balbi 
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/20210113194510.GA1290698@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
+index 1a953f44183a..57067763b100 100644
+--- a/drivers/usb/gadget/udc/dummy_hcd.c
++++ b/drivers/usb/gadget/udc/dummy_hcd.c
+@@ -2270,17 +2270,20 @@ static int dummy_hub_control(
+ 			}
+ 			fallthrough;
+ 		case USB_PORT_FEAT_RESET:
++			if (!(dum_hcd->port_status & USB_PORT_STAT_CONNECTION))
++				break;
+ 			/* if it's already enabled, disable */
+ 			if (hcd->speed == HCD_USB3) {
+-				dum_hcd->port_status = 0;
+ 				dum_hcd->port_status =
+ 					(USB_SS_PORT_STAT_POWER |
+ 					 USB_PORT_STAT_CONNECTION |
+ 					 USB_PORT_STAT_RESET);
+-			} else
++			} else {
+ 				dum_hcd->port_status &= ~(USB_PORT_STAT_ENABLE
+ 					| USB_PORT_STAT_LOW_SPEED
+ 					| USB_PORT_STAT_HIGH_SPEED);
++				dum_hcd->port_status |= USB_PORT_STAT_RESET;
++			}
+ 			/*
+ 			 * We want to reset device status. All but the
+ 			 * Self powered feature
+@@ -2292,7 +2295,8 @@ static int dummy_hub_control(
+ 			 * interval? Is it still 50msec as for HS?
+ 			 */
+ 			dum_hcd->re_timeout = jiffies + msecs_to_jiffies(50);
+-			fallthrough;
++			set_link_state(dum_hcd);
++			break;
+ 		case USB_PORT_FEAT_C_CONNECTION:
+ 		case USB_PORT_FEAT_C_RESET:
+ 		case USB_PORT_FEAT_C_ENABLE:

commit c318840fb2a42ce25febc95c4c19357acf1ae5ca
+Author: Alan Stern 
+Date:   Wed Dec 30 11:20:44 2020 -0500
+
+    USB: Gadget: dummy-hcd: Fix shift-out-of-bounds bug
+    
+    The dummy-hcd driver was written under the assumption that all the
+    parameters in URBs sent to its root hub would be valid.  With URBs
+    sent from userspace via usbfs, that assumption can be violated.
+    
+    In particular, the driver doesn't fully check the port-feature values
+    stored in the wValue entry of Clear-Port-Feature and Set-Port-Feature
+    requests.  Values that are too large can cause the driver to perform
+    an invalid left shift of more than 32 bits.  Ironically, two of those
+    left shifts are unnecessary, because they implement Set-Port-Feature
+    requests that hubs are not required to support, according to section
+    11.24.2.13 of the USB-2.0 spec.
+    
+    This patch adds the appropriate checks for the port feature selector
+    values and removes the unnecessary feature settings.  It also rejects
+    requests to set the TEST feature or to set or clear the INDICATOR and
+    C_OVERCURRENT features, as none of these are relevant to dummy-hcd's
+    root-hub emulation.
+    
+    CC: 
+    Reported-and-tested-by: syzbot+5925509f78293baa7331@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/20201230162044.GA727759@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
+index ab5e978b5052..1a953f44183a 100644
+--- a/drivers/usb/gadget/udc/dummy_hcd.c
++++ b/drivers/usb/gadget/udc/dummy_hcd.c
+@@ -2118,9 +2118,21 @@ static int dummy_hub_control(
+ 				dum_hcd->port_status &= ~USB_PORT_STAT_POWER;
+ 			set_link_state(dum_hcd);
+ 			break;
+-		default:
++		case USB_PORT_FEAT_ENABLE:
++		case USB_PORT_FEAT_C_ENABLE:
++		case USB_PORT_FEAT_C_SUSPEND:
++			/* Not allowed for USB-3 */
++			if (hcd->speed == HCD_USB3)
++				goto error;
++			fallthrough;
++		case USB_PORT_FEAT_C_CONNECTION:
++		case USB_PORT_FEAT_C_RESET:
+ 			dum_hcd->port_status &= ~(1 << wValue);
+ 			set_link_state(dum_hcd);
++			break;
++		default:
++		/* Disallow INDICATOR and C_OVER_CURRENT */
++			goto error;
+ 		}
+ 		break;
+ 	case GetHubDescriptor:
+@@ -2281,18 +2293,17 @@ static int dummy_hub_control(
+ 			 */
+ 			dum_hcd->re_timeout = jiffies + msecs_to_jiffies(50);
+ 			fallthrough;
++		case USB_PORT_FEAT_C_CONNECTION:
++		case USB_PORT_FEAT_C_RESET:
++		case USB_PORT_FEAT_C_ENABLE:
++		case USB_PORT_FEAT_C_SUSPEND:
++			/* Not allowed for USB-3, and ignored for USB-2 */
++			if (hcd->speed == HCD_USB3)
++				goto error;
++			break;
+ 		default:
+-			if (hcd->speed == HCD_USB3) {
+-				if ((dum_hcd->port_status &
+-				     USB_SS_PORT_STAT_POWER) != 0) {
+-					dum_hcd->port_status |= (1 << wValue);
+-				}
+-			} else
+-				if ((dum_hcd->port_status &
+-				     USB_PORT_STAT_POWER) != 0) {
+-					dum_hcd->port_status |= (1 << wValue);
+-				}
+-			set_link_state(dum_hcd);
++		/* Disallow TEST, INDICATOR, and C_OVER_CURRENT */
++			goto error;
+ 		}
+ 		break;
+ 	case GetPortErrorCount:

commit 52abca64fd9410ea6c9a3a74eab25663b403d7da
+Author: Alan Stern 
+Date:   Tue Dec 8 21:29:51 2020 -0800
+
+    scsi: block: Do not accept any requests while suspended
+    
+    blk_queue_enter() accepts BLK_MQ_REQ_PM requests independent of the runtime
+    power management state. Now that SCSI domain validation no longer depends
+    on this behavior, modify the behavior of blk_queue_enter() as follows:
+    
+       - Do not accept any requests while suspended.
+    
+       - Only process power management requests while suspending or resuming.
+    
+    Submitting BLK_MQ_REQ_PM requests to a device that is runtime suspended
+    causes runtime-suspended devices not to resume as they should. The request
+    which should cause a runtime resume instead gets issued directly, without
+    resuming the device first. Of course the device can't handle it properly,
+    the I/O fails, and the device remains suspended.
+    
+    The problem is fixed by checking that the queue's runtime-PM status isn't
+    RPM_SUSPENDED before allowing a request to be issued, and queuing a
+    runtime-resume request if it is.  In particular, the inline
+    blk_pm_request_resume() routine is renamed blk_pm_resume_queue() and the
+    code is unified by merging the surrounding checks into the routine.  If the
+    queue isn't set up for runtime PM, or there currently is no restriction on
+    allowed requests, the request is allowed.  Likewise if the BLK_MQ_REQ_PM
+    flag is set and the status isn't RPM_SUSPENDED.  Otherwise a runtime resume
+    is queued and the request is blocked until conditions are more suitable.
+    
+    [ bvanassche: modified commit message and removed Cc: stable because
+      without the previous patches from this series this patch would break
+      parallel SCSI domain validation + introduced queue_rpm_status() ]
+    
+    Link: https://lore.kernel.org/r/20201209052951.16136-9-bvanassche@acm.org
+    Cc: Jens Axboe 
+    Cc: Christoph Hellwig 
+    Cc: Hannes Reinecke 
+    Cc: Can Guo 
+    Cc: Stanley Chu 
+    Cc: Ming Lei 
+    Cc: Rafael J. Wysocki 
+    Reported-and-tested-by: Martin Kepplinger 
+    Reviewed-by: Hannes Reinecke 
+    Reviewed-by: Can Guo 
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Bart Van Assche 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/block/blk-core.c b/block/blk-core.c
+index a00bce9f46d8..2d53e2ff48ff 100644
+--- a/block/blk-core.c
++++ b/block/blk-core.c
+@@ -18,6 +18,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -440,7 +441,8 @@ int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags)
+ 			 * responsible for ensuring that that counter is
+ 			 * globally visible before the queue is unfrozen.
+ 			 */
+-			if (pm || !blk_queue_pm_only(q)) {
++			if ((pm && queue_rpm_status(q) != RPM_SUSPENDED) ||
++			    !blk_queue_pm_only(q)) {
+ 				success = true;
+ 			} else {
+ 				percpu_ref_put(&q->q_usage_counter);
+@@ -465,8 +467,7 @@ int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags)
+ 
+ 		wait_event(q->mq_freeze_wq,
+ 			   (!q->mq_freeze_depth &&
+-			    (pm || (blk_pm_request_resume(q),
+-				    !blk_queue_pm_only(q)))) ||
++			    blk_pm_resume_queue(pm, q)) ||
+ 			   blk_queue_dying(q));
+ 		if (blk_queue_dying(q))
+ 			return -ENODEV;
+diff --git a/block/blk-pm.h b/block/blk-pm.h
+index ea5507d23e75..a2283cc9f716 100644
+--- a/block/blk-pm.h
++++ b/block/blk-pm.h
+@@ -6,11 +6,14 @@
+ #include 
+ 
+ #ifdef CONFIG_PM
+-static inline void blk_pm_request_resume(struct request_queue *q)
++static inline int blk_pm_resume_queue(const bool pm, struct request_queue *q)
+ {
+-	if (q->dev && (q->rpm_status == RPM_SUSPENDED ||
+-		       q->rpm_status == RPM_SUSPENDING))
+-		pm_request_resume(q->dev);
++	if (!q->dev || !blk_queue_pm_only(q))
++		return 1;	/* Nothing to do */
++	if (pm && q->rpm_status != RPM_SUSPENDED)
++		return 1;	/* Request allowed */
++	pm_request_resume(q->dev);
++	return 0;
+ }
+ 
+ static inline void blk_pm_mark_last_busy(struct request *rq)
+@@ -44,8 +47,9 @@ static inline void blk_pm_put_request(struct request *rq)
+ 		--rq->q->nr_pending;
+ }
+ #else
+-static inline void blk_pm_request_resume(struct request_queue *q)
++static inline int blk_pm_resume_queue(const bool pm, struct request_queue *q)
+ {
++	return 1;
+ }
+ 
+ static inline void blk_pm_mark_last_busy(struct request *rq)
+diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
+index 7d4b746f7e6a..2b6fc3fb3a99 100644
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -692,6 +692,18 @@ static inline bool queue_is_mq(struct request_queue *q)
+ 	return q->mq_ops;
+ }
+ 
++#ifdef CONFIG_PM
++static inline enum rpm_status queue_rpm_status(struct request_queue *q)
++{
++	return q->rpm_status;
++}
++#else
++static inline enum rpm_status queue_rpm_status(struct request_queue *q)
++{
++	return RPM_ACTIVE;
++}
++#endif
++
+ static inline enum blk_zoned_model
+ blk_queue_zoned_model(struct request_queue *q)
+ {

commit b175d273d4e4100b66e68f0675fef7a3c07a7957
+Author: Alan Stern 
+Date:   Tue Dec 8 11:30:42 2020 -0500
+
+    USB: legotower: fix logical error in recent commit
+    
+    Commit d9f0d82f06c6 ("USB: legousbtower: use usb_control_msg_recv()")
+    contained an elementary logical error.  The check of the return code
+    from the new usb_control_msg_recv() function was inverted.
+    
+    Reported-and-tested-by: syzbot+9be25235b7a69b24d117@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/20201208163042.GD1298255@rowland.harvard.edu
+    Fixes: d9f0d82f06c6 ("USB: legousbtower: use usb_control_msg_recv()")
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
+index ba655b4af4fc..1c9e09138c10 100644
+--- a/drivers/usb/misc/legousbtower.c
++++ b/drivers/usb/misc/legousbtower.c
+@@ -797,7 +797,7 @@ static int tower_probe(struct usb_interface *interface, const struct usb_device_
+ 				      &get_version_reply,
+ 				      sizeof(get_version_reply),
+ 				      1000, GFP_KERNEL);
+-	if (!result) {
++	if (result) {
+ 		dev_err(idev, "get version request failed: %d\n", result);
+ 		retval = result;
+ 		goto error;

commit e469d0b09a19496e1972a20974bbf55b728151eb
+Author: Alan Stern 
+Date:   Wed Dec 2 18:20:04 2020 +0100
+
+    media: gspca: Fix memory leak in probe
+    
+    The gspca driver leaks memory when a probe fails.  gspca_dev_probe2()
+    calls v4l2_device_register(), which takes a reference to the
+    underlying device node (in this case, a USB interface).  But the
+    failure pathway neglects to call v4l2_device_unregister(), the routine
+    responsible for dropping this reference.  Consequently the memory for
+    the USB interface and its device never gets released.
+    
+    This patch adds the missing function call.
+    
+    Reported-and-tested-by: syzbot+44e64397bd81d5e84cba@syzkaller.appspotmail.com
+    
+    Signed-off-by: Alan Stern 
+    CC: 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c
+index c295f642d352..158c8e28ed2c 100644
+--- a/drivers/media/usb/gspca/gspca.c
++++ b/drivers/media/usb/gspca/gspca.c
+@@ -1575,6 +1575,7 @@ int gspca_dev_probe2(struct usb_interface *intf,
+ 		input_unregister_device(gspca_dev->input_dev);
+ #endif
+ 	v4l2_ctrl_handler_free(gspca_dev->vdev.ctrl_handler);
++	v4l2_device_unregister(&gspca_dev->v4l2_dev);
+ 	kfree(gspca_dev->usb_buf);
+ 	kfree(gspca_dev);
+ 	return ret;

commit f3bc432aa8a7a2bfe9ebb432502be5c5d979d7fe
+Author: Alan Stern 
+Date:   Thu Nov 19 12:02:28 2020 -0500
+
+    USB: core: Change %pK for __user pointers to %px
+    
+    Commit 2f964780c03b ("USB: core: replace %p with %pK") used the %pK
+    format specifier for a bunch of __user pointers.  But as the 'K' in
+    the specifier indicates, it is meant for kernel pointers.  The reason
+    for the %pK specifier is to avoid leaks of kernel addresses, but when
+    the pointer is to an address in userspace the security implications
+    are minimal.  In particular, no kernel information is leaked.
+    
+    This patch changes the __user %pK specifiers (used in a bunch of
+    debugging output lines) to %px, which will always print the actual
+    address with no mangling.  (Notably, there is no printk format
+    specifier particularly intended for __user pointers.)
+    
+    Fixes: 2f964780c03b ("USB: core: replace %p with %pK")
+    CC: Vamsi Krishna Samavedam 
+    CC: 
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/20201119170228.GB576844@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index e96a858a1218..533236366a03 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -482,11 +482,11 @@ static void snoop_urb(struct usb_device *udev,
+ 
+ 	if (userurb) {		/* Async */
+ 		if (when == SUBMIT)
+-			dev_info(&udev->dev, "userurb %pK, ep%d %s-%s, "
++			dev_info(&udev->dev, "userurb %px, ep%d %s-%s, "
+ 					"length %u\n",
+ 					userurb, ep, t, d, length);
+ 		else
+-			dev_info(&udev->dev, "userurb %pK, ep%d %s-%s, "
++			dev_info(&udev->dev, "userurb %px, ep%d %s-%s, "
+ 					"actual_length %u status %d\n",
+ 					userurb, ep, t, d, length,
+ 					timeout_or_status);
+@@ -1997,7 +1997,7 @@ static int proc_reapurb(struct usb_dev_state *ps, void __user *arg)
+ 	if (as) {
+ 		int retval;
+ 
+-		snoop(&ps->dev->dev, "reap %pK\n", as->userurb);
++		snoop(&ps->dev->dev, "reap %px\n", as->userurb);
+ 		retval = processcompl(as, (void __user * __user *)arg);
+ 		free_async(as);
+ 		return retval;
+@@ -2014,7 +2014,7 @@ static int proc_reapurbnonblock(struct usb_dev_state *ps, void __user *arg)
+ 
+ 	as = async_getcompleted(ps);
+ 	if (as) {
+-		snoop(&ps->dev->dev, "reap %pK\n", as->userurb);
++		snoop(&ps->dev->dev, "reap %px\n", as->userurb);
+ 		retval = processcompl(as, (void __user * __user *)arg);
+ 		free_async(as);
+ 	} else {
+@@ -2142,7 +2142,7 @@ static int proc_reapurb_compat(struct usb_dev_state *ps, void __user *arg)
+ 	if (as) {
+ 		int retval;
+ 
+-		snoop(&ps->dev->dev, "reap %pK\n", as->userurb);
++		snoop(&ps->dev->dev, "reap %px\n", as->userurb);
+ 		retval = processcompl_compat(as, (void __user * __user *)arg);
+ 		free_async(as);
+ 		return retval;
+@@ -2159,7 +2159,7 @@ static int proc_reapurbnonblock_compat(struct usb_dev_state *ps, void __user *ar
+ 
+ 	as = async_getcompleted(ps);
+ 	if (as) {
+-		snoop(&ps->dev->dev, "reap %pK\n", as->userurb);
++		snoop(&ps->dev->dev, "reap %px\n", as->userurb);
+ 		retval = processcompl_compat(as, (void __user * __user *)arg);
+ 		free_async(as);
+ 	} else {
+@@ -2624,7 +2624,7 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
+ #endif
+ 
+ 	case USBDEVFS_DISCARDURB:
+-		snoop(&dev->dev, "%s: DISCARDURB %pK\n", __func__, p);
++		snoop(&dev->dev, "%s: DISCARDURB %px\n", __func__, p);
+ 		ret = proc_unlinkurb(ps, p);
+ 		break;
+ 

commit 184eead057cc7e803558269babc1f2cfb9113ad1
+Author: Alan Stern 
+Date:   Thu Nov 19 12:00:40 2020 -0500
+
+    USB: core: Fix regression in Hercules audio card
+    
+    Commit 3e4f8e21c4f2 ("USB: core: fix check for duplicate endpoints")
+    aimed to make the USB stack more reliable by detecting and skipping
+    over endpoints that are duplicated between interfaces.  This caused a
+    regression for a Hercules audio card (reported as Bugzilla #208357),
+    which contains such non-compliant duplications.  Although the
+    duplications are harmless, skipping the valid endpoints prevented the
+    device from working.
+    
+    This patch fixes the regression by adding ENDPOINT_IGNORE quirks for
+    the Hercules card, telling the kernel to ignore the invalid duplicate
+    endpoints and thereby allowing the valid endpoints to be used as
+    intended.
+    
+    Fixes: 3e4f8e21c4f2 ("USB: core: fix check for duplicate endpoints")
+    CC: 
+    Reported-by: Alexander Chalikiopoulos 
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/20201119170040.GA576844@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index f536ea9fe945..fad31ccd1fa8 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -348,6 +348,10 @@ static const struct usb_device_id usb_quirk_list[] = {
+ 	/* Guillemot Webcam Hercules Dualpix Exchange*/
+ 	{ USB_DEVICE(0x06f8, 0x3005), .driver_info = USB_QUIRK_RESET_RESUME },
+ 
++	/* Guillemot Hercules DJ Console audio card (BZ 208357) */
++	{ USB_DEVICE(0x06f8, 0xb000), .driver_info =
++			USB_QUIRK_ENDPOINT_IGNORE },
++
+ 	/* Midiman M-Audio Keystation 88es */
+ 	{ USB_DEVICE(0x0763, 0x0192), .driver_info = USB_QUIRK_RESET_RESUME },
+ 
+@@ -525,6 +529,8 @@ static const struct usb_device_id usb_amd_resume_quirk_list[] = {
+  * Matched for devices with USB_QUIRK_ENDPOINT_IGNORE.
+  */
+ static const struct usb_device_id usb_endpoint_ignore[] = {
++	{ USB_DEVICE_INTERFACE_NUMBER(0x06f8, 0xb000, 5), .driver_info = 0x01 },
++	{ USB_DEVICE_INTERFACE_NUMBER(0x06f8, 0xb000, 5), .driver_info = 0x81 },
+ 	{ USB_DEVICE_INTERFACE_NUMBER(0x0926, 0x0202, 1), .driver_info = 0x85 },
+ 	{ USB_DEVICE_INTERFACE_NUMBER(0x0926, 0x0208, 1), .driver_info = 0x85 },
+ 	{ }

commit afaa2e745a246c5ab95103a65b1ed00101e1bc63
+Author: Alan Stern 
+Date:   Mon Nov 2 09:58:21 2020 -0500
+
+    USB: Add NO_LPM quirk for Kingston flash drive
+    
+    In Bugzilla #208257, Julien Humbert reports that a 32-GB Kingston
+    flash drive spontaneously disconnects and reconnects, over and over.
+    Testing revealed that disabling Link Power Management for the drive
+    fixed the problem.
+    
+    This patch adds a quirk entry for that drive to turn off LPM permanently.
+    
+    CC: Hans de Goede 
+    CC: 
+    Reported-and-tested-by: Julien Humbert 
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/20201102145821.GA1478741@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index 10574fa3f927..a1e3a037a289 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -378,6 +378,9 @@ static const struct usb_device_id usb_quirk_list[] = {
+ 	{ USB_DEVICE(0x0926, 0x3333), .driver_info =
+ 			USB_QUIRK_CONFIG_INTF_STRINGS },
+ 
++	/* Kingston DataTraveler 3.0 */
++	{ USB_DEVICE(0x0951, 0x1666), .driver_info = USB_QUIRK_NO_LPM },
++
+ 	/* X-Rite/Gretag-Macbeth Eye-One Pro display colorimeter */
+ 	{ USB_DEVICE(0x0971, 0x2000), .driver_info = USB_QUIRK_NO_SET_INTF },
+ 

commit 9270e1a744f8ed953009b0e94b26ed0912d9ec1c
+Author: Alan Stern 
+Date:   Sat Oct 3 21:40:22 2020 -0400
+
+    tools: memory-model: Document that the LKMM can easily miss control dependencies
+    
+    Add a small section to the litmus-tests.txt documentation file for
+    the Linux Kernel Memory Model explaining that the memory model often
+    fails to recognize certain control dependencies.
+    
+    Suggested-by: Akira Yokosawa 
+    Signed-off-by: Alan Stern 
+    Reviewed-by: Joel Fernandes (Google) 
+    Signed-off-by: Paul E. McKenney 
+
+diff --git a/tools/memory-model/Documentation/litmus-tests.txt b/tools/memory-model/Documentation/litmus-tests.txt
+index 2f840dcd15cf..8a9d5d2787f9 100644
+--- a/tools/memory-model/Documentation/litmus-tests.txt
++++ b/tools/memory-model/Documentation/litmus-tests.txt
+@@ -946,6 +946,23 @@ Limitations of the Linux-kernel memory model (LKMM) include:
+ 	carrying a dependency, then the compiler can break that dependency
+ 	by substituting a constant of that value.
+ 
++	Conversely, LKMM sometimes doesn't recognize that a particular
++	optimization is not allowed, and as a result, thinks that a
++	dependency is not present (because the optimization would break it).
++	The memory model misses some pretty obvious control dependencies
++	because of this limitation.  A simple example is:
++
++		r1 = READ_ONCE(x);
++		if (r1 == 0)
++			smp_mb();
++		WRITE_ONCE(y, 1);
++
++	There is a control dependency from the READ_ONCE to the WRITE_ONCE,
++	even when r1 is nonzero, but LKMM doesn't realize this and thinks
++	that the write may execute before the read if r1 != 0.  (Yes, that
++	doesn't make sense if you think about it, but the memory model's
++	intelligence is limited.)
++
+ 2.	Multiple access sizes for a single variable are not supported,
+ 	and neither are misaligned or partially overlapping accesses.
+ 

commit fb6f076d543414cec709401ec65e5f8e6985d77a
+Author: Alan Stern 
+Date:   Mon Sep 28 11:22:17 2020 -0400
+
+    USB: hub: Add Kconfig option to reduce number of port initialization retries
+    
+    Description based on one by Yasushi Asano:
+    
+    According to 6.7.22 A-UUT “Device No Response” for connection timeout
+    of USB OTG and EH automated compliance plan v1.2, enumeration failure
+    has to be detected within 30 seconds.  However, the old and new
+    enumeration schemes each make a total of 12 attempts, and each attempt
+    can take 5 seconds to time out, so the PET test fails.
+    
+    This patch adds a new Kconfig option (CONFIG_USB_FEW_INIT_RETRIES);
+    when the option is set all the initialization retry loops except the
+    outermost are reduced to a single iteration.  This reduces the total
+    number of attempts to four, allowing Linux hosts to pass the PET test.
+    
+    The new option is disabled by default to preserve the existing
+    behavior.  The reduced number of retries may fail to initialize a few
+    devices that currently do work, but for the most part there should be
+    no change.  And in cases where the initialization does fail, it will
+    fail much more quickly.
+    
+    Reported-and-tested-by: yasushi asano 
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/20200928152217.GB134701@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
+index dfacc478a8fc..351ede4b5de2 100644
+--- a/drivers/usb/core/Kconfig
++++ b/drivers/usb/core/Kconfig
+@@ -32,6 +32,20 @@ config USB_DEFAULT_PERSIST
+ 	  If you have any questions about this, say Y here, only say N
+ 	  if you know exactly what you are doing.
+ 
++config USB_FEW_INIT_RETRIES
++	bool "Limit USB device initialization to only a few retries"
++	help
++	  When a new USB device is detected, the kernel tries very hard
++	  to initialize and enumerate it, with lots of nested retry loops.
++	  This almost always works, but when it fails it can take a long time.
++	  This option tells the kernel to make only a few retry attempts,
++	  so that the total time required for a failed initialization is
++	  no more than 30 seconds (as required by the USB OTG spec).
++
++	  Say N here unless you require new-device enumeration failure to
++	  occur within 30 seconds (as might be needed in an embedded
++	  application).
++
+ config USB_DYNAMIC_MINORS
+ 	bool "Dynamic USB minor allocation"
+ 	help
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 70eaf4ab236f..17202b2ee063 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2705,10 +2705,20 @@ static unsigned hub_is_wusb(struct usb_hub *hub)
+ }
+ 
+ 
++#ifdef CONFIG_USB_FEW_INIT_RETRIES
++#define PORT_RESET_TRIES	2
++#define SET_ADDRESS_TRIES	1
++#define GET_DESCRIPTOR_TRIES	1
++#define GET_MAXPACKET0_TRIES	1
++#define PORT_INIT_TRIES		4
++
++#else
+ #define PORT_RESET_TRIES	5
+ #define SET_ADDRESS_TRIES	2
+ #define GET_DESCRIPTOR_TRIES	2
++#define GET_MAXPACKET0_TRIES	3
+ #define PORT_INIT_TRIES		4
++#endif	/* CONFIG_USB_FEW_INIT_RETRIES */
+ 
+ #define HUB_ROOT_RESET_TIME	60	/* times are in msec */
+ #define HUB_SHORT_RESET_TIME	10
+@@ -4691,7 +4701,8 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ 			 * 255 is for WUSB devices, we actually need to use
+ 			 * 512 (WUSB1.0[4.8.1]).
+ 			 */
+-			for (operations = 0; operations < 3; ++operations) {
++			for (operations = 0; operations < GET_MAXPACKET0_TRIES;
++					++operations) {
+ 				buf->bMaxPacketSize0 = 0;
+ 				r = usb_control_msg(udev, usb_rcvaddr0pipe(),
+ 					USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,

commit 19502e6911e4ef4a036344eed36274bb18225033
+Author: Alan Stern 
+Date:   Mon Sep 28 11:20:50 2020 -0400
+
+    USB: hub: Clean up use of port initialization schemes and retries
+    
+    The SET_CONFIG_TRIES macro in hub.c is badly named; it controls the
+    number of port-initialization retry attempts rather than the number of
+    Set-Configuration attempts.  Furthermore, the USE_NEW_SCHEME macro and
+    use_new_scheme() function are written in a very confusing manner,
+    making it almost impossible to figure out exactly what they do or
+    check that they are correct.
+    
+    This patch renames SET_CONFIG_TRIES to PORT_INIT_TRIES, removes
+    USE_NEW_SCHEME entirely, and rewrites use_new_scheme() to be much more
+    transparent, with added comments explaining how it works.  The patch
+    also pulls the single call site of use_new_scheme() out from the
+    Get-Descriptor retry loop (where it returns the same value each time)
+    and renames the local variable used to store the result.
+    
+    The overall effect is a minor cleanup.  However, there is one
+    functional change: If the "use_both_schemes" module parameter isn't
+    set (by default it is set), the existing code does only two retry
+    iterations.  After this patch it will always perform four, regardless
+    of the parameter's value.
+    
+    Signed-off-by: Alan Stern 
+    Link: https://lore.kernel.org/r/20200928152050.GA134701@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 5b768b80d1ee..70eaf4ab236f 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2708,8 +2708,7 @@ static unsigned hub_is_wusb(struct usb_hub *hub)
+ #define PORT_RESET_TRIES	5
+ #define SET_ADDRESS_TRIES	2
+ #define GET_DESCRIPTOR_TRIES	2
+-#define SET_CONFIG_TRIES	(2 * (use_both_schemes + 1))
+-#define USE_NEW_SCHEME(i, scheme)	((i) / 2 == (int)(scheme))
++#define PORT_INIT_TRIES		4
+ 
+ #define HUB_ROOT_RESET_TIME	60	/* times are in msec */
+ #define HUB_SHORT_RESET_TIME	10
+@@ -2717,23 +2716,31 @@ static unsigned hub_is_wusb(struct usb_hub *hub)
+ #define HUB_LONG_RESET_TIME	200
+ #define HUB_RESET_TIMEOUT	800
+ 
+-/*
+- * "New scheme" enumeration causes an extra state transition to be
+- * exposed to an xhci host and causes USB3 devices to receive control
+- * commands in the default state.  This has been seen to cause
+- * enumeration failures, so disable this enumeration scheme for USB3
+- * devices.
+- */
+ static bool use_new_scheme(struct usb_device *udev, int retry,
+ 			   struct usb_port *port_dev)
+ {
+ 	int old_scheme_first_port =
+-		port_dev->quirks & USB_PORT_QUIRK_OLD_SCHEME;
++		(port_dev->quirks & USB_PORT_QUIRK_OLD_SCHEME) ||
++		old_scheme_first;
+ 
++	/*
++	 * "New scheme" enumeration causes an extra state transition to be
++	 * exposed to an xhci host and causes USB3 devices to receive control
++	 * commands in the default state.  This has been seen to cause
++	 * enumeration failures, so disable this enumeration scheme for USB3
++	 * devices.
++	 */
+ 	if (udev->speed >= USB_SPEED_SUPER)
+ 		return false;
+ 
+-	return USE_NEW_SCHEME(retry, old_scheme_first_port || old_scheme_first);
++	/*
++	 * If use_both_schemes is set, use the first scheme (whichever
++	 * it is) for the larger half of the retries, then use the other
++	 * scheme.  Otherwise, use the first scheme for all the retries.
++	 */
++	if (use_both_schemes && retry >= (PORT_INIT_TRIES + 1) / 2)
++		return old_scheme_first_port;	/* Second half */
++	return !old_scheme_first_port;		/* First half or all */
+ }
+ 
+ /* Is a USB 3.0 port in the Inactive or Compliance Mode state?
+@@ -4545,6 +4552,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ 	const char		*speed;
+ 	int			devnum = udev->devnum;
+ 	const char		*driver_name;
++	bool			do_new_scheme;
+ 
+ 	/* root hub ports have a slightly longer reset period
+ 	 * (from USB 2.0 spec, section 7.1.7.5)
+@@ -4657,14 +4665,13 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ 	 * first 8 bytes of the device descriptor to get the ep0 maxpacket
+ 	 * value.
+ 	 */
+-	for (retries = 0; retries < GET_DESCRIPTOR_TRIES; (++retries, msleep(100))) {
+-		bool did_new_scheme = false;
++	do_new_scheme = use_new_scheme(udev, retry_counter, port_dev);
+ 
+-		if (use_new_scheme(udev, retry_counter, port_dev)) {
++	for (retries = 0; retries < GET_DESCRIPTOR_TRIES; (++retries, msleep(100))) {
++		if (do_new_scheme) {
+ 			struct usb_device_descriptor *buf;
+ 			int r = 0;
+ 
+-			did_new_scheme = true;
+ 			retval = hub_enable_device(udev);
+ 			if (retval < 0) {
+ 				dev_err(&udev->dev,
+@@ -4773,11 +4780,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ 			 *  - read ep0 maxpacket even for high and low speed,
+ 			 */
+ 			msleep(10);
+-			/* use_new_scheme() checks the speed which may have
+-			 * changed since the initial look so we cache the result
+-			 * in did_new_scheme
+-			 */
+-			if (did_new_scheme)
++			if (do_new_scheme)
+ 				break;
+ 		}
+ 
+@@ -5106,7 +5109,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
+ 		unit_load = 100;
+ 
+ 	status = 0;
+-	for (i = 0; i < SET_CONFIG_TRIES; i++) {
++	for (i = 0; i < PORT_INIT_TRIES; i++) {
+ 
+ 		/* reallocate for each attempt, since references
+ 		 * to the previous one can escape in various ways
+@@ -5239,7 +5242,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
+ 			break;
+ 
+ 		/* When halfway through our retry count, power-cycle the port */
+-		if (i == (SET_CONFIG_TRIES / 2) - 1) {
++		if (i == (PORT_INIT_TRIES - 1) / 2) {
+ 			dev_info(&port_dev->dev, "attempt power cycle\n");
+ 			usb_hub_set_port_power(hdev, hub, port1, false);
+ 			msleep(2 * hub_power_on_good_delay(hub));
+@@ -5770,7 +5773,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
+ 	bos = udev->bos;
+ 	udev->bos = NULL;
+ 
+-	for (i = 0; i < SET_CONFIG_TRIES; ++i) {
++	for (i = 0; i < PORT_INIT_TRIES; ++i) {
+ 
+ 		/* ep0 maxpacket size may change; let the HCD know about it.
+ 		 * Other endpoints will be handled by re-enumeration. */

commit 9b719c7119e77e8ddeefe4772c554d2863579c2b
+Author: Alan Stern 
+Date:   Fri Aug 21 10:55:46 2020 +0800
+
+    USB: UDC: net2272: Fix memory leaks
+    
+    Like net2280 (on which it was based), the net2272 UDC driver has a
+    problem with leaking memory along some of its failure pathways.  It
+    also has another problem, not previously noted, in that some of the
+    failure pathways will call usb_del_gadget_udc() without first calling
+    usb_add_gadget_udc_release().  And it leaks memory by calling kfree()
+    when it should call put_device().
+    
+    Until now it has been impossible to handle the memory leaks, because of
+    lack of support in the UDC core for separately initializing and adding
+    gadgets, or for separately deleting and freeing gadgets.  An earlier
+    patch in this series adds the necessary support, making it possible to
+    fix the outstanding problems properly.
+    
+    This patch adds an "added" flag to the net2272 structure to indicate
+    whether or not the gadget has been registered (and thus whether or not
+    to call usb_del_gadget()), and it fixes the deallocation issues by
+    calling usb_put_gadget() at the appropriate places.
+    
+    A similar memory leak issue, apparently never before recognized, stems
+    from the fact that the driver never initializes the drvdata field in
+    the gadget's embedded struct device!  Evidently this wasn't noticed
+    because the pointer is only ever used as an argument to kfree(), which
+    doesn't mind getting called with a NULL pointer. In fact, the drvdata
+    for gadget device will be written by usb_composite_dev structure if
+    any gadget class is loaded, so it needs to use usb_gadget structure
+    to get net2280 private data.
+    
+    CC: Anton Vasilyev 
+    CC: Evgeny Novikov 
+    CC: Benjamin Herrenschmidt 
+    Reviewed-by: Greg Kroah-Hartman 
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Peter Chen 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c
+index 440bcb3b6c23..23a735641c3d 100644
+--- a/drivers/usb/gadget/udc/net2272.c
++++ b/drivers/usb/gadget/udc/net2272.c
+@@ -2195,7 +2195,8 @@ static int net2272_present(struct net2272 *dev)
+ static void
+ net2272_gadget_release(struct device *_dev)
+ {
+-	struct net2272 *dev = dev_get_drvdata(_dev);
++	struct net2272 *dev = container_of(_dev, struct net2272, gadget.dev);
++
+ 	kfree(dev);
+ }
+ 
+@@ -2204,7 +2205,8 @@ net2272_gadget_release(struct device *_dev)
+ static void
+ net2272_remove(struct net2272 *dev)
+ {
+-	usb_del_gadget_udc(&dev->gadget);
++	if (dev->added)
++		usb_del_gadget(&dev->gadget);
+ 	free_irq(dev->irq, dev);
+ 	iounmap(dev->base_addr);
+ 	device_remove_file(dev->dev, &dev_attr_registers);
+@@ -2234,6 +2236,7 @@ static struct net2272 *net2272_probe_init(struct device *dev, unsigned int irq)
+ 
+ 	/* the "gadget" abstracts/virtualizes the controller */
+ 	ret->gadget.name = driver_name;
++	usb_initialize_gadget(dev, &ret->gadget, net2272_gadget_release);
+ 
+ 	return ret;
+ }
+@@ -2272,10 +2275,10 @@ net2272_probe_fin(struct net2272 *dev, unsigned int irqflags)
+ 	if (ret)
+ 		goto err_irq;
+ 
+-	ret = usb_add_gadget_udc_release(dev->dev, &dev->gadget,
+-			net2272_gadget_release);
++	ret = usb_add_gadget(&dev->gadget);
+ 	if (ret)
+ 		goto err_add_udc;
++	dev->added = 1;
+ 
+ 	return 0;
+ 
+@@ -2450,7 +2453,7 @@ net2272_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ 
+ 	if (pci_enable_device(pdev) < 0) {
+ 		ret = -ENODEV;
+-		goto err_free;
++		goto err_put;
+ 	}
+ 
+ 	pci_set_master(pdev);
+@@ -2473,8 +2476,8 @@ net2272_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ 
+  err_pci:
+ 	pci_disable_device(pdev);
+- err_free:
+-	kfree(dev);
++ err_put:
++	usb_put_gadget(&dev->gadget);
+ 
+ 	return ret;
+ }
+@@ -2535,7 +2538,7 @@ net2272_pci_remove(struct pci_dev *pdev)
+ 
+ 	pci_disable_device(pdev);
+ 
+-	kfree(dev);
++	usb_put_gadget(&dev->gadget);
+ }
+ 
+ /* Table of matching PCI IDs */
+@@ -2648,7 +2651,7 @@ net2272_plat_probe(struct platform_device *pdev)
+  err_req:
+ 	release_mem_region(base, len);
+  err:
+-	kfree(dev);
++	usb_put_gadget(&dev->gadget);
+ 
+ 	return ret;
+ }
+@@ -2663,7 +2666,7 @@ net2272_plat_remove(struct platform_device *pdev)
+ 	release_mem_region(pdev->resource[0].start,
+ 		resource_size(&pdev->resource[0]));
+ 
+-	kfree(dev);
++	usb_put_gadget(&dev->gadget);
+ 
+ 	return 0;
+ }
+diff --git a/drivers/usb/gadget/udc/net2272.h b/drivers/usb/gadget/udc/net2272.h
+index 87d0ab9ffeeb..c669308111c2 100644
+--- a/drivers/usb/gadget/udc/net2272.h
++++ b/drivers/usb/gadget/udc/net2272.h
+@@ -441,6 +441,7 @@ struct net2272 {
+ 	unsigned protocol_stall:1,
+ 	         softconnect:1,
+ 	         wakeup:1,
++		 added:1,
+ 	         dma_eot_polarity:1,
+ 	         dma_dack_polarity:1,
+ 	         dma_dreq_polarity:1,

commit f770fbec4165b1acfabdeadb01ad6008d2c537b5
+Author: Alan Stern 
+Date:   Fri Aug 21 10:55:45 2020 +0800
+
+    USB: UDC: net2280: Fix memory leaks
+    
+    As Anton and Evgeny have noted, the net2280 UDC driver has a problem
+    with leaking memory along some of its failure pathways.  It also has
+    another problem, not previously noted, in that some of the failure
+    pathways will call usb_del_gadget_udc() without first calling
+    usb_add_gadget_udc_release().  And it leaks memory by calling kfree()
+    when it should call put_device().
+    
+    Previous attempts to fix the problems have failed because of lack of
+    support in the UDC core for separately initializing and adding
+    gadgets, or for separately deleting and freeing gadgets.  The previous
+    patch in this series adds the necessary support, making it possible to
+    fix the outstanding problems properly.
+    
+    This patch adds an "added" flag to the net2280 structure to indicate
+    whether or not the gadget has been registered (and thus whether or not
+    to call usb_del_gadget()), and it fixes the deallocation issues by
+    calling usb_put_gadget() at the appropriate point.
+    
+    A similar memory leak issue, apparently never before recognized, stems
+    from the fact that the driver never initializes the drvdata field in
+    the gadget's embedded struct device!  Evidently this wasn't noticed
+    because the pointer is only ever used as an argument to kfree(), which
+    doesn't mind getting called with a NULL pointer. In fact, the drvdata
+    for gadget device will be written by usb_composite_dev structure if
+    any gadget class is loaded, so it needs to use usb_gadget structure
+    to get net2280 private data.
+    
+    CC: Benjamin Herrenschmidt 
+    Reported-by: Anton Vasilyev 
+    Reported-by: Evgeny Novikov 
+    Reviewed-by: Greg Kroah-Hartman 
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Peter Chen 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c
+index 7530bd9a08c4..d50bc6e19f2a 100644
+--- a/drivers/usb/gadget/udc/net2280.c
++++ b/drivers/usb/gadget/udc/net2280.c
+@@ -3561,7 +3561,7 @@ static irqreturn_t net2280_irq(int irq, void *_dev)
+ 
+ static void gadget_release(struct device *_dev)
+ {
+-	struct net2280	*dev = dev_get_drvdata(_dev);
++	struct net2280	*dev = container_of(_dev, struct net2280, gadget.dev);
+ 
+ 	kfree(dev);
+ }
+@@ -3572,7 +3572,8 @@ static void net2280_remove(struct pci_dev *pdev)
+ {
+ 	struct net2280		*dev = pci_get_drvdata(pdev);
+ 
+-	usb_del_gadget_udc(&dev->gadget);
++	if (dev->added)
++		usb_del_gadget(&dev->gadget);
+ 
+ 	BUG_ON(dev->driver);
+ 
+@@ -3603,6 +3604,7 @@ static void net2280_remove(struct pci_dev *pdev)
+ 	device_remove_file(&pdev->dev, &dev_attr_registers);
+ 
+ 	ep_info(dev, "unbind\n");
++	usb_put_gadget(&dev->gadget);
+ }
+ 
+ /* wrap this driver around the specified device, but
+@@ -3624,6 +3626,7 @@ static int net2280_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	}
+ 
+ 	pci_set_drvdata(pdev, dev);
++	usb_initialize_gadget(&pdev->dev, &dev->gadget, gadget_release);
+ 	spin_lock_init(&dev->lock);
+ 	dev->quirks = id->driver_data;
+ 	dev->pdev = pdev;
+@@ -3774,10 +3777,10 @@ static int net2280_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	if (retval)
+ 		goto done;
+ 
+-	retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
+-			gadget_release);
++	retval = usb_add_gadget(&dev->gadget);
+ 	if (retval)
+ 		goto done;
++	dev->added = 1;
+ 	return 0;
+ 
+ done:
+diff --git a/drivers/usb/gadget/udc/net2280.h b/drivers/usb/gadget/udc/net2280.h
+index 85d3ca1698ba..7da3dc1e9729 100644
+--- a/drivers/usb/gadget/udc/net2280.h
++++ b/drivers/usb/gadget/udc/net2280.h
+@@ -156,6 +156,7 @@ struct net2280 {
+ 					softconnect : 1,
+ 					got_irq : 1,
+ 					region:1,
++					added:1,
+ 					u1_enable:1,
+ 					u2_enable:1,
+ 					ltm_enable:1,

commit 3301c215a2bb94b5a0afcb444bbe9bf2a395a65d
+Author: Alan Stern 
+Date:   Fri Aug 21 10:55:44 2020 +0800
+
+    USB: UDC: Expand device model API interface
+    
+    The routines used by the UDC core to interface with the kernel's
+    device model, namely usb_add_gadget_udc(),
+    usb_add_gadget_udc_release(), and usb_del_gadget_udc(), provide access
+    to only a subset of the device model's full API.  They include
+    functionality equivalent to device_register() and device_unregister()
+    for gadgets, but they omit device_initialize(), device_add(),
+    device_del(), get_device(), and put_device().
+    
+    This patch expands the UDC API by adding usb_initialize_gadget(),
+    usb_add_gadget(), usb_del_gadget(), usb_get_gadget(), and
+    usb_put_gadget() to fill in the gap.  It rewrites the existing
+    routines to call the new ones.
+    
+    CC: Anton Vasilyev 
+    CC: Evgeny Novikov 
+    CC: Benjamin Herrenschmidt 
+    Reviewed-by: Greg Kroah-Hartman 
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Peter Chen 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
+index 4f82bcd31fd3..2b6770d9fb3f 100644
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -1164,21 +1164,18 @@ static int check_pending_gadget_drivers(struct usb_udc *udc)
+ }
+ 
+ /**
+- * usb_add_gadget_udc_release - adds a new gadget to the udc class driver list
++ * usb_initialize_gadget - initialize a gadget and its embedded struct device
+  * @parent: the parent device to this udc. Usually the controller driver's
+  * device.
+- * @gadget: the gadget to be added to the list.
++ * @gadget: the gadget to be initialized.
+  * @release: a gadget release function.
+  *
+  * Returns zero on success, negative errno otherwise.
+  * Calls the gadget release function in the latter case.
+  */
+-int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
++void usb_initialize_gadget(struct device *parent, struct usb_gadget *gadget,
+ 		void (*release)(struct device *dev))
+ {
+-	struct usb_udc		*udc;
+-	int			ret = -ENOMEM;
+-
+ 	dev_set_name(&gadget->dev, "gadget");
+ 	INIT_WORK(&gadget->work, usb_gadget_state_work);
+ 	gadget->dev.parent = parent;
+@@ -1189,17 +1186,32 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
+ 		gadget->dev.release = usb_udc_nop_release;
+ 
+ 	device_initialize(&gadget->dev);
++}
++EXPORT_SYMBOL_GPL(usb_initialize_gadget);
++
++/**
++ * usb_add_gadget - adds a new gadget to the udc class driver list
++ * @gadget: the gadget to be added to the list.
++ *
++ * Returns zero on success, negative errno otherwise.
++ * Does not do a final usb_put_gadget() if an error occurs.
++ */
++int usb_add_gadget(struct usb_gadget *gadget)
++{
++	struct usb_udc		*udc;
++	int			ret = -ENOMEM;
+ 
+ 	udc = kzalloc(sizeof(*udc), GFP_KERNEL);
+ 	if (!udc)
+-		goto err_put_gadget;
++		goto error;
+ 
+ 	device_initialize(&udc->dev);
+ 	udc->dev.release = usb_udc_release;
+ 	udc->dev.class = udc_class;
+ 	udc->dev.groups = usb_udc_attr_groups;
+-	udc->dev.parent = parent;
+-	ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj));
++	udc->dev.parent = gadget->dev.parent;
++	ret = dev_set_name(&udc->dev, "%s",
++			kobject_name(&gadget->dev.parent->kobj));
+ 	if (ret)
+ 		goto err_put_udc;
+ 
+@@ -1242,8 +1254,30 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
+  err_put_udc:
+ 	put_device(&udc->dev);
+ 
+- err_put_gadget:
+-	put_device(&gadget->dev);
++ error:
++	return ret;
++}
++EXPORT_SYMBOL_GPL(usb_add_gadget);
++
++/**
++ * usb_add_gadget_udc_release - adds a new gadget to the udc class driver list
++ * @parent: the parent device to this udc. Usually the controller driver's
++ * device.
++ * @gadget: the gadget to be added to the list.
++ * @release: a gadget release function.
++ *
++ * Returns zero on success, negative errno otherwise.
++ * Calls the gadget release function in the latter case.
++ */
++int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
++		void (*release)(struct device *dev))
++{
++	int	ret;
++
++	usb_initialize_gadget(parent, gadget, release);
++	ret = usb_add_gadget(gadget);
++	if (ret)
++		usb_put_gadget(gadget);
+ 	return ret;
+ }
+ EXPORT_SYMBOL_GPL(usb_add_gadget_udc_release);
+@@ -1311,13 +1345,14 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
+ }
+ 
+ /**
+- * usb_del_gadget_udc - deletes @udc from udc_list
++ * usb_del_gadget - deletes @udc from udc_list
+  * @gadget: the gadget to be removed.
+  *
+- * This, will call usb_gadget_unregister_driver() if
++ * This will call usb_gadget_unregister_driver() if
+  * the @udc is still busy.
++ * It will not do a final usb_put_gadget().
+  */
+-void usb_del_gadget_udc(struct usb_gadget *gadget)
++void usb_del_gadget(struct usb_gadget *gadget)
+ {
+ 	struct usb_udc *udc = gadget->udc;
+ 
+@@ -1340,7 +1375,20 @@ void usb_del_gadget_udc(struct usb_gadget *gadget)
+ 	kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
+ 	flush_work(&gadget->work);
+ 	device_unregister(&udc->dev);
+-	device_unregister(&gadget->dev);
++	device_del(&gadget->dev);
++}
++EXPORT_SYMBOL_GPL(usb_del_gadget);
++
++/**
++ * usb_del_gadget_udc - deletes @udc from udc_list
++ * @gadget: the gadget to be removed.
++ *
++ * Calls usb_del_gadget() and does a final usb_put_gadget().
++ */
++void usb_del_gadget_udc(struct usb_gadget *gadget)
++{
++	usb_del_gadget(gadget);
++	usb_put_gadget(gadget);
+ 	memset(&gadget->dev, 0x00, sizeof(gadget->dev));
+ }
+ EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
+diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
+index 52ce1f6b8f83..e7351d64f11f 100644
+--- a/include/linux/usb/gadget.h
++++ b/include/linux/usb/gadget.h
+@@ -436,6 +436,7 @@ struct usb_gadget {
+ };
+ #define work_to_gadget(w)	(container_of((w), struct usb_gadget, work))
+ 
++/* Interface to the device model */
+ static inline void set_gadget_data(struct usb_gadget *gadget, void *data)
+ 	{ dev_set_drvdata(&gadget->dev, data); }
+ static inline void *get_gadget_data(struct usb_gadget *gadget)
+@@ -444,6 +445,26 @@ static inline struct usb_gadget *dev_to_usb_gadget(struct device *dev)
+ {
+ 	return container_of(dev, struct usb_gadget, dev);
+ }
++static inline struct usb_gadget *usb_get_gadget(struct usb_gadget *gadget)
++{
++	get_device(&gadget->dev);
++	return gadget;
++}
++static inline void usb_put_gadget(struct usb_gadget *gadget)
++{
++	put_device(&gadget->dev);
++}
++extern void usb_initialize_gadget(struct device *parent,
++		struct usb_gadget *gadget, void (*release)(struct device *dev));
++extern int usb_add_gadget(struct usb_gadget *gadget);
++extern void usb_del_gadget(struct usb_gadget *gadget);
++
++/* Legacy device-model interface */
++extern int usb_add_gadget_udc_release(struct device *parent,
++		struct usb_gadget *gadget, void (*release)(struct device *dev));
++extern int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget);
++extern void usb_del_gadget_udc(struct usb_gadget *gadget);
++extern char *usb_get_gadget_udc_name(void);
+ 
+ /* iterates the non-control endpoints; 'tmp' is a struct usb_ep pointer */
+ #define gadget_for_each_ep(tmp, gadget) \
+@@ -735,12 +756,6 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver);
+  */
+ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver);
+ 
+-extern int usb_add_gadget_udc_release(struct device *parent,
+-		struct usb_gadget *gadget, void (*release)(struct device *dev));
+-extern int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget);
+-extern void usb_del_gadget_udc(struct usb_gadget *gadget);
+-extern char *usb_get_gadget_udc_name(void);
+-
+ /*-------------------------------------------------------------------------*/
+ 
+ /* utility to simplify dealing with string descriptors */

commit 20934c0de13b49a072fb1e0ca79fe0fe0e40eae5
+Author: Alan Stern 
+Date:   Wed Aug 26 10:32:29 2020 -0400
+
+    usb: storage: Add unusual_uas entry for Sony PSZ drives
+    
+    The PSZ-HA* family of USB disk drives from Sony can't handle the
+    REPORT OPCODES command when using the UAS protocol.  This patch adds
+    an appropriate quirks entry.
+    
+    Reported-and-tested-by: Till Dörges 
+    Signed-off-by: Alan Stern 
+    CC: 
+    Link: https://lore.kernel.org/r/20200826143229.GB400430@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_uas.h b/drivers/usb/storage/unusual_uas.h
+index 971f8a4354c8..711ab240058c 100644
+--- a/drivers/usb/storage/unusual_uas.h
++++ b/drivers/usb/storage/unusual_uas.h
+@@ -28,6 +28,13 @@
+  * and don't forget to CC: the USB development list 
+  */
+ 
++/* Reported-by: Till Dörges  */
++UNUSUAL_DEV(0x054c, 0x087d, 0x0000, 0x9999,
++		"Sony",
++		"PSZ-HA*",
++		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
++		US_FL_NO_REPORT_OPCODES),
++
+ /* Reported-by: Julian Groß  */
+ UNUSUAL_DEV(0x059f, 0x105f, 0x0000, 0x9999,
+ 		"LaCie",

commit 068834a2773b6a12805105cfadbb3d4229fc6e0a
+Author: Alan Stern 
+Date:   Wed Aug 26 15:46:24 2020 -0400
+
+    USB: quirks: Ignore duplicate endpoint on Sound Devices MixPre-D
+    
+    The Sound Devices MixPre-D audio card suffers from the same defect
+    as the Sound Devices USBPre2: an endpoint shared between a normal
+    audio interface and a vendor-specific interface, in violation of the
+    USB spec.  Since the USB core now treats duplicated endpoints as bugs
+    and ignores them, the audio endpoint isn't available and the card
+    can't be used for audio capture.
+    
+    Along the same lines as commit bdd1b147b802 ("USB: quirks: blacklist
+    duplicate ep on Sound Devices USBPre2"), this patch adds a quirks
+    entry saying to ignore ep5in for interface 1, leaving it available for
+    use with standard audio interface 2.
+    
+    Reported-and-tested-by: Jean-Christophe Barnoud 
+    Signed-off-by: Alan Stern 
+    CC: 
+    Fixes: 3e4f8e21c4f2 ("USB: core: fix check for duplicate endpoints")
+    Link: https://lore.kernel.org/r/20200826194624.GA412633@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index d1f38956b210..f232914de5fd 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -370,6 +370,10 @@ static const struct usb_device_id usb_quirk_list[] = {
+ 	{ USB_DEVICE(0x0926, 0x0202), .driver_info =
+ 			USB_QUIRK_ENDPOINT_IGNORE },
+ 
++	/* Sound Devices MixPre-D */
++	{ USB_DEVICE(0x0926, 0x0208), .driver_info =
++			USB_QUIRK_ENDPOINT_IGNORE },
++
+ 	/* Keytouch QWERTY Panel keyboard */
+ 	{ USB_DEVICE(0x0926, 0x3333), .driver_info =
+ 			USB_QUIRK_CONFIG_INTF_STRINGS },
+@@ -511,6 +515,7 @@ static const struct usb_device_id usb_amd_resume_quirk_list[] = {
+  */
+ static const struct usb_device_id usb_endpoint_ignore[] = {
+ 	{ USB_DEVICE_INTERFACE_NUMBER(0x0926, 0x0202, 1), .driver_info = 0x85 },
++	{ USB_DEVICE_INTERFACE_NUMBER(0x0926, 0x0208, 1), .driver_info = 0x85 },
+ 	{ }
+ };
+ 

commit f176ede3a3bde5b398a6777a7f9ff091baa2d3ff
+Author: Alan Stern 
+Date:   Mon Aug 10 14:29:54 2020 -0400
+
+    USB: yurex: Fix bad gfp argument
+    
+    The syzbot fuzzer identified a bug in the yurex driver: It passes
+    GFP_KERNEL as a memory-allocation flag to usb_submit_urb() at a time
+    when its state is TASK_INTERRUPTIBLE, not TASK_RUNNING:
+    
+    do not call blocking ops when !TASK_RUNNING; state=1 set at [<00000000370c7c68>] prepare_to_wait+0xb1/0x2a0 kernel/sched/wait.c:247
+    WARNING: CPU: 1 PID: 340 at kernel/sched/core.c:7253 __might_sleep+0x135/0x190
+    kernel/sched/core.c:7253
+    Kernel panic - not syncing: panic_on_warn set ...
+    CPU: 1 PID: 340 Comm: syz-executor677 Not tainted 5.8.0-syzkaller #0
+    Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google
+    01/01/2011
+    Call Trace:
+     __dump_stack lib/dump_stack.c:77 [inline]
+     dump_stack+0xf6/0x16e lib/dump_stack.c:118
+     panic+0x2aa/0x6e1 kernel/panic.c:231
+     __warn.cold+0x20/0x50 kernel/panic.c:600
+     report_bug+0x1bd/0x210 lib/bug.c:198
+     handle_bug+0x41/0x80 arch/x86/kernel/traps.c:234
+     exc_invalid_op+0x14/0x40 arch/x86/kernel/traps.c:254
+     asm_exc_invalid_op+0x12/0x20 arch/x86/include/asm/idtentry.h:536
+    RIP: 0010:__might_sleep+0x135/0x190 kernel/sched/core.c:7253
+    Code: 65 48 8b 1c 25 40 ef 01 00 48 8d 7b 10 48 89 fe 48 c1 ee 03 80 3c 06 00 75
+    2b 48 8b 73 10 48 c7 c7 e0 9e 06 86 e8 ed 12 f6 ff <0f> 0b e9 46 ff ff ff e8 1f
+    b2 4b 00 e9 29 ff ff ff e8 15 b2 4b 00
+    RSP: 0018:ffff8881cdb77a28 EFLAGS: 00010282
+    RAX: 0000000000000000 RBX: ffff8881c6458000 RCX: 0000000000000000
+    RDX: ffff8881c6458000 RSI: ffffffff8129ec93 RDI: ffffed1039b6ef37
+    RBP: ffffffff86fdade2 R08: 0000000000000001 R09: ffff8881db32f54f
+    R10: 0000000000000000 R11: 0000000030343354 R12: 00000000000001f2
+    R13: 0000000000000000 R14: 0000000000000068 R15: ffffffff83c1b1aa
+     slab_pre_alloc_hook.constprop.0+0xea/0x200 mm/slab.h:498
+     slab_alloc_node mm/slub.c:2816 [inline]
+     slab_alloc mm/slub.c:2900 [inline]
+     kmem_cache_alloc_trace+0x46/0x220 mm/slub.c:2917
+     kmalloc include/linux/slab.h:554 [inline]
+     dummy_urb_enqueue+0x7a/0x880 drivers/usb/gadget/udc/dummy_hcd.c:1251
+     usb_hcd_submit_urb+0x2b2/0x22d0 drivers/usb/core/hcd.c:1547
+     usb_submit_urb+0xb4e/0x13e0 drivers/usb/core/urb.c:570
+     yurex_write+0x3ea/0x820 drivers/usb/misc/yurex.c:495
+    
+    This patch changes the call to use GFP_ATOMIC instead of GFP_KERNEL.
+    
+    Reported-and-tested-by: syzbot+c2c3302f9c601a4b1be2@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    CC: 
+    Link: https://lore.kernel.org/r/20200810182954.GB307778@rowland.harvard.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c
+index 6e7d34e7fec4..b2e09883c7e2 100644
+--- a/drivers/usb/misc/yurex.c
++++ b/drivers/usb/misc/yurex.c
+@@ -492,7 +492,7 @@ static ssize_t yurex_write(struct file *file, const char __user *user_buffer,
+ 	prepare_to_wait(&dev->waitq, &wait, TASK_INTERRUPTIBLE);
+ 	dev_dbg(&dev->interface->dev, "%s - submit %c\n", __func__,
+ 		dev->cntl_buffer[0]);
+-	retval = usb_submit_urb(dev->cntl_urb, GFP_KERNEL);
++	retval = usb_submit_urb(dev->cntl_urb, GFP_ATOMIC);
+ 	if (retval >= 0)
+ 		timeout = schedule_timeout(YUREX_WRITE_TIMEOUT);
+ 	finish_wait(&dev->waitq, &wait);

commit 8f38f8e0a30e1c33cdfc48eba2bd63ac2eae373a
+Author: Alan Stern 
+Date:   Mon Jul 6 11:14:36 2020 -0400
+
+    scsi: block: pm: Simplify resume handling
+    
+    Commit 05d18ae1cc8a ("scsi: pm: Balance pm_only counter of request queue
+    during system resume") fixed a problem in the block layer's runtime-PM
+    code: blk_set_runtime_active() failed to call blk_clear_pm_only().
+    However, the commit's implementation was awkward; it forced the SCSI
+    system-resume handler to choose whether to call blk_post_runtime_resume()
+    or blk_set_runtime_active(), depending on whether or not the SCSI device
+    had previously been runtime suspended.
+    
+    This patch simplifies the situation considerably by adding the missing
+    function call directly into blk_set_runtime_active() (under the condition
+    that the queue is not already in the RPM_ACTIVE state).  This allows the
+    SCSI routine to revert back to its original form.  Furthermore, making this
+    change reveals that blk_post_runtime_resume() (in its success pathway) does
+    exactly the same thing as blk_set_runtime_active().  The duplicate code is
+    easily removed by making one routine call the other.
+    
+    No functional changes are intended.
+    
+    Link: https://lore.kernel.org/r/20200706151436.GA702867@rowland.harvard.edu
+    CC: Can Guo 
+    CC: Bart Van Assche 
+    Reviewed-by: Bart Van Assche 
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/block/blk-pm.c b/block/blk-pm.c
+index 1adc1cd748b4..b85234d758f7 100644
+--- a/block/blk-pm.c
++++ b/block/blk-pm.c
+@@ -164,9 +164,8 @@ EXPORT_SYMBOL(blk_pre_runtime_resume);
+  *
+  * Description:
+  *    Update the queue's runtime status according to the return value of the
+- *    device's runtime_resume function. If it is successfully resumed, process
+- *    the requests that are queued into the device's queue when it is resuming
+- *    and then mark last busy and initiate autosuspend for it.
++ *    device's runtime_resume function. If the resume was successful, call
++ *    blk_set_runtime_active() to do the real work of restarting the queue.
+  *
+  *    This function should be called near the end of the device's
+  *    runtime_resume callback.
+@@ -175,19 +174,13 @@ void blk_post_runtime_resume(struct request_queue *q, int err)
+ {
+ 	if (!q->dev)
+ 		return;
+-
+-	spin_lock_irq(&q->queue_lock);
+ 	if (!err) {
+-		q->rpm_status = RPM_ACTIVE;
+-		pm_runtime_mark_last_busy(q->dev);
+-		pm_request_autosuspend(q->dev);
++		blk_set_runtime_active(q);
+ 	} else {
++		spin_lock_irq(&q->queue_lock);
+ 		q->rpm_status = RPM_SUSPENDED;
++		spin_unlock_irq(&q->queue_lock);
+ 	}
+-	spin_unlock_irq(&q->queue_lock);
+-
+-	if (!err)
+-		blk_clear_pm_only(q);
+ }
+ EXPORT_SYMBOL(blk_post_runtime_resume);
+ 
+@@ -204,15 +197,25 @@ EXPORT_SYMBOL(blk_post_runtime_resume);
+  * This function can be used in driver's resume hook to correct queue
+  * runtime PM status and re-enable peeking requests from the queue. It
+  * should be called before first request is added to the queue.
++ *
++ * This function is also called by blk_post_runtime_resume() for successful
++ * runtime resumes.  It does everything necessary to restart the queue.
+  */
+ void blk_set_runtime_active(struct request_queue *q)
+ {
+-	if (q->dev) {
+-		spin_lock_irq(&q->queue_lock);
+-		q->rpm_status = RPM_ACTIVE;
+-		pm_runtime_mark_last_busy(q->dev);
+-		pm_request_autosuspend(q->dev);
+-		spin_unlock_irq(&q->queue_lock);
+-	}
++	int old_status;
++
++	if (!q->dev)
++		return;
++
++	spin_lock_irq(&q->queue_lock);
++	old_status = q->rpm_status;
++	q->rpm_status = RPM_ACTIVE;
++	pm_runtime_mark_last_busy(q->dev);
++	pm_request_autosuspend(q->dev);
++	spin_unlock_irq(&q->queue_lock);
++
++	if (old_status != RPM_ACTIVE)
++		blk_clear_pm_only(q);
+ }
+ EXPORT_SYMBOL(blk_set_runtime_active);
+diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
+index 5f0ad8b32e3a..3717eea37ecb 100644
+--- a/drivers/scsi/scsi_pm.c
++++ b/drivers/scsi/scsi_pm.c
+@@ -80,10 +80,6 @@ static int scsi_dev_type_resume(struct device *dev,
+ 	dev_dbg(dev, "scsi resume: %d\n", err);
+ 
+ 	if (err == 0) {
+-		bool was_runtime_suspended;
+-
+-		was_runtime_suspended = pm_runtime_suspended(dev);
+-
+ 		pm_runtime_disable(dev);
+ 		err = pm_runtime_set_active(dev);
+ 		pm_runtime_enable(dev);
+@@ -97,10 +93,8 @@ static int scsi_dev_type_resume(struct device *dev,
+ 		 */
+ 		if (!err && scsi_is_sdev_device(dev)) {
+ 			struct scsi_device *sdev = to_scsi_device(dev);
+-			if (was_runtime_suspended)
+-				blk_post_runtime_resume(sdev->request_queue, 0);
+-			else
+-				blk_set_runtime_active(sdev->request_queue);
++
++			blk_set_runtime_active(sdev->request_queue);
+ 		}
+ 	}
+ 

commit ac854131d9844f79e2fdcef67a7707227538d78a
+Author: Alan Stern 
+Date:   Fri May 1 16:07:28 2020 -0400
+
+    USB: core: Fix misleading driver bug report
+    
+    The syzbot fuzzer found a race between URB submission to endpoint 0
+    and device reset.  Namely, during the reset we call usb_ep0_reinit()
+    because the characteristics of ep0 may have changed (if the reset
+    follows a firmware update, for example).  While usb_ep0_reinit() is
+    running there is a brief period during which the pointers stored in
+    udev->ep_in[0] and udev->ep_out[0] are set to NULL, and if an URB is
+    submitted to ep0 during that period, usb_urb_ep_type_check() will
+    report it as a driver bug.  In the absence of those pointers, the
+    routine thinks that the endpoint doesn't exist.  The log message looks
+    like this:
+    
+    ------------[ cut here ]------------
+    usb 2-1: BOGUS urb xfer, pipe 2 != type 2
+    WARNING: CPU: 0 PID: 9241 at drivers/usb/core/urb.c:478
+    usb_submit_urb+0x1188/0x1460 drivers/usb/core/urb.c:478
+    
+    Now, although submitting an URB while the device is being reset is a
+    questionable thing to do, it shouldn't count as a driver bug as severe
+    as submitting an URB for an endpoint that doesn't exist.  Indeed,
+    endpoint 0 always exists, even while the device is in its unconfigured
+    state.
+    
+    To prevent these misleading driver bug reports, this patch updates
+    usb_disable_endpoint() to avoid clearing the ep_in[] and ep_out[]
+    pointers when the endpoint being disabled is ep0.  There's no danger
+    of leaving a stale pointer in place, because the usb_host_endpoint
+    structure being pointed to is stored permanently in udev->ep0; it
+    doesn't get deallocated until the entire usb_device structure does.
+    
+    Reported-and-tested-by: syzbot+db339689b2101f6f6071@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    
+    Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.2005011558590.903-100000@netrider.rowland.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index a48678a0c83a..6197938dcc2d 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1144,11 +1144,11 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr,
+ 
+ 	if (usb_endpoint_out(epaddr)) {
+ 		ep = dev->ep_out[epnum];
+-		if (reset_hardware)
++		if (reset_hardware && epnum != 0)
+ 			dev->ep_out[epnum] = NULL;
+ 	} else {
+ 		ep = dev->ep_in[epnum];
+-		if (reset_hardware)
++		if (reset_hardware && epnum != 0)
+ 			dev->ep_in[epnum] = NULL;
+ 	}
+ 	if (ep) {

commit 0ed08faded1da03eb3def61502b27f81aef2e615
+Author: Alan Stern 
+Date:   Wed Apr 22 16:18:48 2020 -0400
+
+    HID: usbhid: Fix race between usbhid_close() and usbhid_stop()
+    
+    The syzbot fuzzer discovered a bad race between in the usbhid driver
+    between usbhid_stop() and usbhid_close().  In particular,
+    usbhid_stop() does:
+    
+            usb_free_urb(usbhid->urbin);
+            ...
+            usbhid->urbin = NULL; /* don't mess up next start */
+    
+    and usbhid_close() does:
+    
+            usb_kill_urb(usbhid->urbin);
+    
+    with no mutual exclusion.  If the two routines happen to run
+    concurrently so that usb_kill_urb() is called in between the
+    usb_free_urb() and the NULL assignment, it will access the
+    deallocated urb structure -- a use-after-free bug.
+    
+    This patch adds a mutex to the usbhid private structure and uses it to
+    enforce mutual exclusion of the usbhid_start(), usbhid_stop(),
+    usbhid_open() and usbhid_close() callbacks.
+    
+    Reported-and-tested-by: syzbot+7bf5a7b0f0a1f9446f4c@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    CC: 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index c7bc9db5b192..17a638f15082 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -682,16 +682,21 @@ static int usbhid_open(struct hid_device *hid)
+ 	struct usbhid_device *usbhid = hid->driver_data;
+ 	int res;
+ 
++	mutex_lock(&usbhid->mutex);
++
+ 	set_bit(HID_OPENED, &usbhid->iofl);
+ 
+-	if (hid->quirks & HID_QUIRK_ALWAYS_POLL)
+-		return 0;
++	if (hid->quirks & HID_QUIRK_ALWAYS_POLL) {
++		res = 0;
++		goto Done;
++	}
+ 
+ 	res = usb_autopm_get_interface(usbhid->intf);
+ 	/* the device must be awake to reliably request remote wakeup */
+ 	if (res < 0) {
+ 		clear_bit(HID_OPENED, &usbhid->iofl);
+-		return -EIO;
++		res = -EIO;
++		goto Done;
+ 	}
+ 
+ 	usbhid->intf->needs_remote_wakeup = 1;
+@@ -725,6 +730,9 @@ static int usbhid_open(struct hid_device *hid)
+ 		msleep(50);
+ 
+ 	clear_bit(HID_RESUME_RUNNING, &usbhid->iofl);
++
++ Done:
++	mutex_unlock(&usbhid->mutex);
+ 	return res;
+ }
+ 
+@@ -732,6 +740,8 @@ static void usbhid_close(struct hid_device *hid)
+ {
+ 	struct usbhid_device *usbhid = hid->driver_data;
+ 
++	mutex_lock(&usbhid->mutex);
++
+ 	/*
+ 	 * Make sure we don't restart data acquisition due to
+ 	 * a resumption we no longer care about by avoiding racing
+@@ -743,12 +753,13 @@ static void usbhid_close(struct hid_device *hid)
+ 		clear_bit(HID_IN_POLLING, &usbhid->iofl);
+ 	spin_unlock_irq(&usbhid->lock);
+ 
+-	if (hid->quirks & HID_QUIRK_ALWAYS_POLL)
+-		return;
++	if (!(hid->quirks & HID_QUIRK_ALWAYS_POLL)) {
++		hid_cancel_delayed_stuff(usbhid);
++		usb_kill_urb(usbhid->urbin);
++		usbhid->intf->needs_remote_wakeup = 0;
++	}
+ 
+-	hid_cancel_delayed_stuff(usbhid);
+-	usb_kill_urb(usbhid->urbin);
+-	usbhid->intf->needs_remote_wakeup = 0;
++	mutex_unlock(&usbhid->mutex);
+ }
+ 
+ /*
+@@ -1057,6 +1068,8 @@ static int usbhid_start(struct hid_device *hid)
+ 	unsigned int n, insize = 0;
+ 	int ret;
+ 
++	mutex_lock(&usbhid->mutex);
++
+ 	clear_bit(HID_DISCONNECTED, &usbhid->iofl);
+ 
+ 	usbhid->bufsize = HID_MIN_BUFFER_SIZE;
+@@ -1177,6 +1190,8 @@ static int usbhid_start(struct hid_device *hid)
+ 		usbhid_set_leds(hid);
+ 		device_set_wakeup_enable(&dev->dev, 1);
+ 	}
++
++	mutex_unlock(&usbhid->mutex);
+ 	return 0;
+ 
+ fail:
+@@ -1187,6 +1202,7 @@ static int usbhid_start(struct hid_device *hid)
+ 	usbhid->urbout = NULL;
+ 	usbhid->urbctrl = NULL;
+ 	hid_free_buffers(dev, hid);
++	mutex_unlock(&usbhid->mutex);
+ 	return ret;
+ }
+ 
+@@ -1202,6 +1218,8 @@ static void usbhid_stop(struct hid_device *hid)
+ 		usbhid->intf->needs_remote_wakeup = 0;
+ 	}
+ 
++	mutex_lock(&usbhid->mutex);
++
+ 	clear_bit(HID_STARTED, &usbhid->iofl);
+ 	spin_lock_irq(&usbhid->lock);	/* Sync with error and led handlers */
+ 	set_bit(HID_DISCONNECTED, &usbhid->iofl);
+@@ -1222,6 +1240,8 @@ static void usbhid_stop(struct hid_device *hid)
+ 	usbhid->urbout = NULL;
+ 
+ 	hid_free_buffers(hid_to_usb_dev(hid), hid);
++
++	mutex_unlock(&usbhid->mutex);
+ }
+ 
+ static int usbhid_power(struct hid_device *hid, int lvl)
+@@ -1382,6 +1402,7 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
+ 	INIT_WORK(&usbhid->reset_work, hid_reset);
+ 	timer_setup(&usbhid->io_retry, hid_retry_timeout, 0);
+ 	spin_lock_init(&usbhid->lock);
++	mutex_init(&usbhid->mutex);
+ 
+ 	ret = hid_add_device(hid);
+ 	if (ret) {
+diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h
+index 8620408bd7af..75fe85d3d27a 100644
+--- a/drivers/hid/usbhid/usbhid.h
++++ b/drivers/hid/usbhid/usbhid.h
+@@ -80,6 +80,7 @@ struct usbhid_device {
+ 	dma_addr_t outbuf_dma;                                          /* Output buffer dma */
+ 	unsigned long last_out;							/* record of last output for timeouts */
+ 
++	struct mutex mutex;						/* start/stop/open/close */
+ 	spinlock_t lock;						/* fifo spinlock */
+ 	unsigned long iofl;                                             /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
+ 	struct timer_list io_retry;                                     /* Retry timer */

commit 598cc93005636e32a98ed003b0158329827c0ccb
+Author: Alan Stern 
+Date:   Sat Apr 25 16:35:40 2020 -0400
+
+    PM: sleep: Helpful edits for devices.rst documentation
+    
+    Here are some minor edits of the devices.rst documentation file,
+    intended to improve the clarity and add a couple of missing details.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/Documentation/driver-api/pm/devices.rst b/Documentation/driver-api/pm/devices.rst
+index 782cb37073a3..946ad0b94e31 100644
+--- a/Documentation/driver-api/pm/devices.rst
++++ b/Documentation/driver-api/pm/devices.rst
+@@ -349,7 +349,7 @@ the phases are: ``prepare``, ``suspend``, ``suspend_late``, ``suspend_noirq``.
+ 	PM core will skip the ``suspend``, ``suspend_late`` and
+ 	``suspend_noirq`` phases as well as all of the corresponding phases of
+ 	the subsequent device resume for all of these devices.	In that case,
+-	the ``->complete`` callback will be invoked directly after the
++	the ``->complete`` callback will be the next one invoked after the
+ 	``->prepare`` callback and is entirely responsible for putting the
+ 	device into a consistent state as appropriate.
+ 
+@@ -383,11 +383,15 @@ the phases are: ``prepare``, ``suspend``, ``suspend_late``, ``suspend_noirq``.
+ 	``->suspend`` methods provided by subsystems (bus types and PM domains
+ 	in particular) must follow an additional rule regarding what can be done
+ 	to the devices before their drivers' ``->suspend`` methods are called.
+-	Namely, they can only resume the devices from runtime suspend by
+-	calling :c:func:`pm_runtime_resume` for them, if that is necessary, and
++	Namely, they may resume the devices from runtime suspend by
++	calling :c:func:`pm_runtime_resume` for them, if that is necessary, but
+ 	they must not update the state of the devices in any other way at that
+ 	time (in case the drivers need to resume the devices from runtime
+-	suspend in their ``->suspend`` methods).
++	suspend in their ``->suspend`` methods).  In fact, the PM core prevents
++	subsystems or drivers from putting devices into runtime suspend at
++	these times by calling :c:func:`pm_runtime_get_noresume` before issuing
++	the ``->prepare`` callback (and calling :c:func:`pm_runtime_put` after
++	issuing the ``->complete`` callback).
+ 
+     3.	For a number of devices it is convenient to split suspend into the
+ 	"quiesce device" and "save device state" phases, in which cases
+@@ -459,22 +463,22 @@ When resuming from freeze, standby or memory sleep, the phases are:
+ 
+ 	Note, however, that new children may be registered below the device as
+ 	soon as the ``->resume`` callbacks occur; it's not necessary to wait
+-	until the ``complete`` phase with that.
++	until the ``complete`` phase runs.
+ 
+ 	Moreover, if the preceding ``->prepare`` callback returned a positive
+ 	number, the device may have been left in runtime suspend throughout the
+-	whole system suspend and resume (the ``suspend``, ``suspend_late``,
+-	``suspend_noirq`` phases of system suspend and the ``resume_noirq``,
+-	``resume_early``, ``resume`` phases of system resume may have been
+-	skipped for it).  In that case, the ``->complete`` callback is entirely
++	whole system suspend and resume (its ``->suspend``, ``->suspend_late``,
++	``->suspend_noirq``, ``->resume_noirq``,
++	``->resume_early``, and ``->resume`` callbacks may have been
++	skipped).  In that case, the ``->complete`` callback is entirely
+ 	responsible for putting the device into a consistent state after system
+ 	suspend if necessary.  [For example, it may need to queue up a runtime
+ 	resume request for the device for this purpose.]  To check if that is
+ 	the case, the ``->complete`` callback can consult the device's
+-	``power.direct_complete`` flag.  Namely, if that flag is set when the
+-	``->complete`` callback is being run, it has been called directly after
+-	the preceding ``->prepare`` and special actions may be required
+-	to make the device work correctly afterward.
++	``power.direct_complete`` flag.  If that flag is set when the
++	``->complete`` callback is being run then the direct-complete mechanism
++	was used, and special actions may be required to make the device work
++	correctly afterward.
+ 
+ At the end of these phases, drivers should be as functional as they were before
+ suspending: I/O can be performed using DMA and IRQs, and the relevant clocks are
+@@ -575,10 +579,12 @@ and the phases are similar.
+ 
+ The ``->poweroff``, ``->poweroff_late`` and ``->poweroff_noirq`` callbacks
+ should do essentially the same things as the ``->suspend``, ``->suspend_late``
+-and ``->suspend_noirq`` callbacks, respectively.  The only notable difference is
++and ``->suspend_noirq`` callbacks, respectively.  A notable difference is
+ that they need not store the device register values, because the registers
+ should already have been stored during the ``freeze``, ``freeze_late`` or
+-``freeze_noirq`` phases.
++``freeze_noirq`` phases.  Also, on many machines the firmware will power-down
++the entire system, so it is not necessary for the callback to put the device in
++a low-power state.
+ 
+ 
+ Leaving Hibernation
+@@ -764,11 +770,10 @@ device driver in question.
+ 
+ If it is necessary to resume a device from runtime suspend during a system-wide
+ transition into a sleep state, that can be done by calling
+-:c:func:`pm_runtime_resume` for it from the ``->suspend`` callback (or its
+-couterpart for transitions related to hibernation) of either the device's driver
+-or a subsystem responsible for it (for example, a bus type or a PM domain).
+-That is guaranteed to work by the requirement that subsystems must not change
+-the state of devices (possibly except for resuming them from runtime suspend)
++:c:func:`pm_runtime_resume` from the ``->suspend`` callback (or the ``->freeze``
++or ``->poweroff`` callback for transitions related to hibernation) of either the
++device's driver or its subsystem (for example, a bus type or a PM domain).
++However, subsystems must not otherwise change the runtime status of devices
+ from their ``->prepare`` and ``->suspend`` callbacks (or equivalent) *before*
+ invoking device drivers' ``->suspend`` callbacks (or equivalent).
+ 
+@@ -779,27 +784,29 @@ The ``DPM_FLAG_SMART_SUSPEND`` Driver Flag
+ 
+ Some bus types and PM domains have a policy to resume all devices from runtime
+ suspend upfront in their ``->suspend`` callbacks, but that may not be really
+-necessary if the driver of the device can cope with runtime-suspended devices.
+-The driver can indicate that by setting ``DPM_FLAG_SMART_SUSPEND`` in
+-:c:member:`power.driver_flags` at the probe time with the help of the
++necessary if the device's driver can cope with runtime-suspended devices.
++The driver can indicate this by setting ``DPM_FLAG_SMART_SUSPEND`` in
++:c:member:`power.driver_flags` at probe time, with the assistance of the
+ :c:func:`dev_pm_set_driver_flags` helper routine.
+ 
+-However, setting that flag also causes the PM core and middle-layer code
++Setting that flag causes the PM core and middle-layer code
+ (bus types, PM domains etc.) to skip the ``->suspend_late`` and
+ ``->suspend_noirq`` callbacks provided by the driver if the device remains in
+-runtime suspend during the ``suspend_late`` phase of system-wide suspend (or
+-during the ``poweroff_late`` or ``freeze_late`` phase of hibernation),
+-after runtime PM was disabled for it.  [Without doing that, the same driver
++runtime suspend throughout those phases of the system-wide suspend (and
++similarly for the "freeze" and "poweroff" parts of system hibernation).
++[Otherwise the same driver
+ callback might be executed twice in a row for the same device, which would not
+ be valid in general.]  If the middle-layer system-wide PM callbacks are present
+-for the device, they are responsible for doing the above, and the PM core takes
+-care of it otherwise.
++for the device then they are responsible for skipping these driver callbacks;
++if not then the PM core skips them.  The subsystem callback routines can
++determine whether they need to skip the driver callbacks by testing the return
++value from the :c:func:`dev_pm_skip_suspend` helper function.
+ 
+-In addition, with ``DPM_FLAG_SMART_SUSPEND`` set, the driver's ``->thaw_late``
+-and ``->thaw_noirq`` callbacks are skipped if the device remained in runtime
+-suspend during the preceding "freeze" transition related to hibernation.
+-Again, if the middle-layer callbacks are present for the device, they are
+-responsible for doing that, or the PM core takes care of it otherwise.
++In addition, with ``DPM_FLAG_SMART_SUSPEND`` set, the driver's ``->thaw_noirq``
++and ``->thaw_early`` callbacks are skipped in hibernation if the device remained
++in runtime suspend throughout the preceding "freeze" transition.  Again, if the
++middle-layer callbacks are present for the device, they are responsible for
++doing this, otherwise the PM core takes care of it.
+ 
+ 
+ The ``DPM_FLAG_MAY_SKIP_RESUME`` Driver Flag
+@@ -820,17 +827,20 @@ indicate to the PM core and middle-layer code that they allow their "noirq" and
+ after system-wide PM transitions to the working state.  Whether or not that is
+ the case generally depends on the state of the device before the given system
+ suspend-resume cycle and on the type of the system transition under way.
+-In particular, the "restore" and "thaw" transitions related to hibernation are
+-not affected by ``DPM_FLAG_MAY_SKIP_RESUME`` at all.  [All devices are always
+-resumed during the "restore" transition and whether or not any driver callbacks
+-are skipped during the "freeze" transition depends whether or not the
+-``DPM_FLAG_SMART_SUSPEND`` flag is set (see `above `_).]
++In particular, the "thaw" and "restore" transitions related to hibernation are
++not affected by ``DPM_FLAG_MAY_SKIP_RESUME`` at all.  [All callbacks are
++issued during the "restore" transition regardless of the flag settings,
++and whether or not any driver callbacks
++are skipped during the "thaw" transition depends whether or not the
++``DPM_FLAG_SMART_SUSPEND`` flag is set (see `above `_).
++In addition, a device is not allowed to remain in runtime suspend if any of its
++children will be returned to full power.]
+ 
+ The ``DPM_FLAG_MAY_SKIP_RESUME`` flag is taken into account in combination with
+ the :c:member:`power.may_skip_resume` status bit set by the PM core during the
+ "suspend" phase of suspend-type transitions.  If the driver or the middle layer
+ has a reason to prevent the driver's "noirq" and "early" resume callbacks from
+-being skipped during the subsequent resume transition of the system, it should
++being skipped during the subsequent system resume transition, it should
+ clear :c:member:`power.may_skip_resume` in its ``->suspend``, ``->suspend_late``
+ or ``->suspend_noirq`` callback.  [Note that the drivers setting
+ ``DPM_FLAG_SMART_SUSPEND`` need to clear :c:member:`power.may_skip_resume` in
+@@ -845,8 +855,8 @@ not they should be skipped can be determined by evaluating the
+ If that function returns ``true``, the driver's "noirq" and "early" resume
+ callbacks should be skipped and the device's runtime PM status will be set to
+ "suspended" by the PM core.  Otherwise, if the device was runtime-suspended
+-during the preceding system-wide suspend transition and
+-``DPM_FLAG_SMART_SUSPEND`` is set for it, its runtime PM status will be set to
++during the preceding system-wide suspend transition and its
++``DPM_FLAG_SMART_SUSPEND`` is set, its runtime PM status will be set to
+ "active" by the PM core.  [Hence, the drivers that do not set
+ ``DPM_FLAG_SMART_SUSPEND`` should not expect the runtime PM status of their
+ devices to be changed from "suspended" to "active" by the PM core during

commit a6cd27e9b594ccf4bf525969c1077f2dbe515476
+Author: Alan Stern 
+Date:   Wed Apr 22 16:20:19 2020 -0400
+
+    USB: core: Replace an empty statement with a debug message
+    
+    This patch adds a dev_dbg() message to usb_create_sysfs_intf_files().
+    The message is not expected ever to appear; it's real purpose is to
+    satisfy the __must_check attribute on device_create_file() without
+    triggering a compiler warning about an empty statement.
+    
+    In fact we don't really care if the sysfs attribute file doesn't get
+    created.  The interface string descriptor is purely informational and
+    hardly ever present.
+    
+    Suggested-by: NeilBrown 
+    Signed-off-by: Alan Stern 
+    
+    Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.2004221618500.11262-100000@iolanthe.rowland.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 9f4320b9d7fc..a2ca38e25e0c 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -1262,8 +1262,10 @@ void usb_create_sysfs_intf_files(struct usb_interface *intf)
+ 
+ 	if (!alt->string && !(udev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
+ 		alt->string = usb_cache_string(udev, alt->desc.iInterface);
+-	if (alt->string && device_create_file(&intf->dev, &dev_attr_interface))
+-		;	/* We don't actually care if the function fails. */
++	if (alt->string && device_create_file(&intf->dev, &dev_attr_interface)) {
++		/* This is not a serious error */
++		dev_dbg(&intf->dev, "interface string descriptor file not created\n");
++	}
+ 	intf->sysfs_files_created = 1;
+ }
+ 

commit 94f9c8c3c404ee1f7aaff81ad4f24aec4e34a78b
+Author: Alan Stern 
+Date:   Wed Apr 22 16:14:57 2020 -0400
+
+    usb-storage: Add unusual_devs entry for JMicron JMS566
+    
+    Cyril Roelandt reports that his JMicron JMS566 USB-SATA bridge fails
+    to handle WRITE commands with the FUA bit set, even though it claims
+    to support FUA.  (Oddly enough, a later version of the same bridge,
+    version 2.03 as opposed to 1.14, doesn't claim to support FUA.  Also
+    oddly, the bridge _does_ support FUA when using the UAS transport
+    instead of the Bulk-Only transport -- but this device was blacklisted
+    for uas in commit bc3bdb12bbb3 ("usb-storage: Disable UAS on JMicron
+    SATA enclosure") for apparently unrelated reasons.)
+    
+    This patch adds a usb-storage unusual_devs entry with the BROKEN_FUA
+    flag.  This allows the bridge to work properly with usb-storage.
+    
+    Reported-and-tested-by: Cyril Roelandt 
+    Signed-off-by: Alan Stern 
+    CC: 
+    
+    Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.2004221613110.11262-100000@iolanthe.rowland.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 1880f3e13f57..f6c3681fa2e9 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -2323,6 +2323,13 @@ UNUSUAL_DEV(  0x3340, 0xffff, 0x0000, 0x0000,
+ 		USB_SC_DEVICE,USB_PR_DEVICE,NULL,
+ 		US_FL_MAX_SECTORS_64 ),
+ 
++/* Reported by Cyril Roelandt  */
++UNUSUAL_DEV(  0x357d, 0x7788, 0x0114, 0x0114,
++		"JMicron",
++		"USB to ATA/ATAPI Bridge",
++		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
++		US_FL_BROKEN_FUA ),
++
+ /* Reported by Andrey Rahmatullin  */
+ UNUSUAL_DEV(  0x4102, 0x1020, 0x0100,  0x0100,
+ 		"iRiver",

commit 3155f4f40811c5d7e3c686215051acf504e05565
+Author: Alan Stern 
+Date:   Wed Apr 22 16:13:08 2020 -0400
+
+    USB: hub: Revert commit bd0e6c9614b9 ("usb: hub: try old enumeration scheme first for high speed devices")
+    
+    Commit bd0e6c9614b9 ("usb: hub: try old enumeration scheme first for
+    high speed devices") changed the way the hub driver enumerates
+    high-speed devices.  Instead of using the "new" enumeration scheme
+    first and switching to the "old" scheme if that doesn't work, we start
+    with the "old" scheme.  In theory this is better because the "old"
+    scheme is slightly faster -- it involves resetting the device only
+    once instead of twice.
+    
+    However, for a long time Windows used only the "new" scheme.  Zeng Tao
+    said that Windows 8 and later use the "old" scheme for high-speed
+    devices, but apparently there are some devices that don't like it.
+    William Bader reports that the Ricoh webcam built into his Sony Vaio
+    laptop not only doesn't enumerate under the "old" scheme, it gets hung
+    up so badly that it won't then enumerate under the "new" scheme!  Only
+    a cold reset will fix it.
+    
+    Therefore we will revert the commit and go back to trying the "new"
+    scheme first for high-speed devices.
+    
+    Reported-and-tested-by: William Bader 
+    Ref: https://bugzilla.kernel.org/show_bug.cgi?id=207219
+    Signed-off-by: Alan Stern 
+    Fixes: bd0e6c9614b9 ("usb: hub: try old enumeration scheme first for high speed devices")
+    CC: Zeng Tao 
+    CC: 
+    
+    Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.2004221611230.11262-100000@iolanthe.rowland.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
+index f2a93c8679e8..7bc83f3d9bdf 100644
+--- a/Documentation/admin-guide/kernel-parameters.txt
++++ b/Documentation/admin-guide/kernel-parameters.txt
+@@ -5187,8 +5187,7 @@
+ 
+ 	usbcore.old_scheme_first=
+ 			[USB] Start with the old device initialization
+-			scheme,  applies only to low and full-speed devices
+-			 (default 0 = off).
++			scheme (default 0 = off).
+ 
+ 	usbcore.usbfs_memory_mb=
+ 			[USB] Memory limit (in MB) for buffers allocated by
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 83549f009ced..2b6565c06c23 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2728,13 +2728,11 @@ static bool use_new_scheme(struct usb_device *udev, int retry,
+ {
+ 	int old_scheme_first_port =
+ 		port_dev->quirks & USB_PORT_QUIRK_OLD_SCHEME;
+-	int quick_enumeration = (udev->speed == USB_SPEED_HIGH);
+ 
+ 	if (udev->speed >= USB_SPEED_SUPER)
+ 		return false;
+ 
+-	return USE_NEW_SCHEME(retry, old_scheme_first_port || old_scheme_first
+-			      || quick_enumeration);
++	return USE_NEW_SCHEME(retry, old_scheme_first_port || old_scheme_first);
+ }
+ 
+ /* Is a USB 3.0 port in the Inactive or Compliance Mode state?

commit 9f952e26295d977dbfc6fedeaf8c4f112c818d37
+Author: Alan Stern 
+Date:   Wed Apr 22 16:09:51 2020 -0400
+
+    USB: hub: Fix handling of connect changes during sleep
+    
+    Commit 8099f58f1ecd ("USB: hub: Don't record a connect-change event
+    during reset-resume") wasn't very well conceived.  The problem it
+    tried to fix was that if a connect-change event occurred while the
+    system was asleep (such as a device disconnecting itself from the bus
+    when it is suspended and then reconnecting when it resumes)
+    requiring a reset-resume during the system wakeup transition, the hub
+    port's change_bit entry would remain set afterward.  This would cause
+    the hub driver to believe another connect-change event had occurred
+    after the reset-resume, which was wrong and would lead the driver to
+    send unnecessary requests to the device (which could interfere with a
+    firmware update).
+    
+    The commit tried to fix this by not setting the change_bit during the
+    wakeup.  But this was the wrong thing to do; it means that when a
+    device is unplugged while the system is asleep, the hub driver doesn't
+    realize anything has happened: The change_bit flag which would tell it
+    to handle the disconnect event is clear.
+    
+    The commit needs to be reverted and the problem fixed in a different
+    way.  Fortunately an alternative solution was noted in the commit's
+    Changelog: We can continue to set the change_bit entry in
+    hub_activate() but then clear it when a reset-resume occurs.  That way
+    the the hub driver will see the change_bit when a device is
+    disconnected but won't see it when the device is still present.
+    
+    That's what this patch does.
+    
+    Reported-and-tested-by: Peter Chen 
+    Signed-off-by: Alan Stern 
+    Fixes: 8099f58f1ecd ("USB: hub: Don't record a connect-change event during reset-resume")
+    Tested-by: Paul Zimmerman 
+    CC: 
+    
+    Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.2004221602480.11262-100000@iolanthe.rowland.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 54cd8ef795ec..83549f009ced 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1223,6 +1223,11 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ #ifdef CONFIG_PM
+ 			udev->reset_resume = 1;
+ #endif
++			/* Don't set the change_bits when the device
++			 * was powered off.
++			 */
++			if (test_bit(port1, hub->power_bits))
++				set_bit(port1, hub->change_bits);
+ 
+ 		} else {
+ 			/* The power session is gone; tell hub_wq */
+@@ -3088,6 +3093,15 @@ static int check_port_resume_type(struct usb_device *udev,
+ 		if (portchange & USB_PORT_STAT_C_ENABLE)
+ 			usb_clear_port_feature(hub->hdev, port1,
+ 					USB_PORT_FEAT_C_ENABLE);
++
++		/*
++		 * Whatever made this reset-resume necessary may have
++		 * turned on the port1 bit in hub->change_bits.  But after
++		 * a successful reset-resume we want the bit to be clear;
++		 * if it was on it would indicate that something happened
++		 * following the reset-resume.
++		 */
++		clear_bit(port1, hub->change_bits);
+ 	}
+ 
+ 	return status;

commit 056ad39ee9253873522f6469c3364964a322912b
+Author: Alan Stern 
+Date:   Sat Mar 28 16:18:11 2020 -0400
+
+    USB: core: Fix free-while-in-use bug in the USB S-Glibrary
+    
+    FuzzUSB (a variant of syzkaller) found a free-while-still-in-use bug
+    in the USB scatter-gather library:
+    
+    BUG: KASAN: use-after-free in atomic_read
+    include/asm-generic/atomic-instrumented.h:26 [inline]
+    BUG: KASAN: use-after-free in usb_hcd_unlink_urb+0x5f/0x170
+    drivers/usb/core/hcd.c:1607
+    Read of size 4 at addr ffff888065379610 by task kworker/u4:1/27
+    
+    CPU: 1 PID: 27 Comm: kworker/u4:1 Not tainted 5.5.11 #2
+    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
+    1.10.2-1ubuntu1 04/01/2014
+    Workqueue: scsi_tmf_2 scmd_eh_abort_handler
+    Call Trace:
+     __dump_stack lib/dump_stack.c:77 [inline]
+     dump_stack+0xce/0x128 lib/dump_stack.c:118
+     print_address_description.constprop.4+0x21/0x3c0 mm/kasan/report.c:374
+     __kasan_report+0x153/0x1cb mm/kasan/report.c:506
+     kasan_report+0x12/0x20 mm/kasan/common.c:639
+     check_memory_region_inline mm/kasan/generic.c:185 [inline]
+     check_memory_region+0x152/0x1b0 mm/kasan/generic.c:192
+     __kasan_check_read+0x11/0x20 mm/kasan/common.c:95
+     atomic_read include/asm-generic/atomic-instrumented.h:26 [inline]
+     usb_hcd_unlink_urb+0x5f/0x170 drivers/usb/core/hcd.c:1607
+     usb_unlink_urb+0x72/0xb0 drivers/usb/core/urb.c:657
+     usb_sg_cancel+0x14e/0x290 drivers/usb/core/message.c:602
+     usb_stor_stop_transport+0x5e/0xa0 drivers/usb/storage/transport.c:937
+    
+    This bug occurs when cancellation of the S-G transfer races with
+    transfer completion.  When that happens, usb_sg_cancel() may continue
+    to access the transfer's URBs after usb_sg_wait() has freed them.
+    
+    The bug is caused by the fact that usb_sg_cancel() does not take any
+    sort of reference to the transfer, and so there is nothing to prevent
+    the URBs from being deallocated while the routine is trying to use
+    them.  The fix is to take such a reference by incrementing the
+    transfer's io->count field while the cancellation is in progres and
+    decrementing it afterward.  The transfer's URBs are not deallocated
+    until io->complete is triggered, which happens when io->count reaches
+    zero.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Kyungtae Kim 
+    CC: 
+    
+    Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.2003281615140.14837-100000@netrider.rowland.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index d5f834f16993..a48678a0c83a 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -589,12 +589,13 @@ void usb_sg_cancel(struct usb_sg_request *io)
+ 	int i, retval;
+ 
+ 	spin_lock_irqsave(&io->lock, flags);
+-	if (io->status) {
++	if (io->status || io->count == 0) {
+ 		spin_unlock_irqrestore(&io->lock, flags);
+ 		return;
+ 	}
+ 	/* shut everything down */
+ 	io->status = -ECONNRESET;
++	io->count++;		/* Keep the request alive until we're done */
+ 	spin_unlock_irqrestore(&io->lock, flags);
+ 
+ 	for (i = io->entries - 1; i >= 0; --i) {
+@@ -608,6 +609,12 @@ void usb_sg_cancel(struct usb_sg_request *io)
+ 			dev_warn(&io->dev->dev, "%s, unlink --> %d\n",
+ 				 __func__, retval);
+ 	}
++
++	spin_lock_irqsave(&io->lock, flags);
++	io->count--;
++	if (!io->count)
++		complete(&io->complete);
++	spin_unlock_irqrestore(&io->lock, flags);
+ }
+ EXPORT_SYMBOL_GPL(usb_sg_cancel);
+ 

commit 8099f58f1ecddf4f374f4828a3dff8397c7cbd74
+Author: Alan Stern 
+Date:   Fri Jan 31 10:39:26 2020 -0500
+
+    USB: hub: Don't record a connect-change event during reset-resume
+    
+    Paul Zimmerman reports that his USB Bluetooth adapter sometimes
+    crashes following system resume, when it receives a
+    Get-Device-Descriptor request while it is busy doing something else.
+    
+    Such a request was added by commit a4f55d8b8c14 ("usb: hub: Check
+    device descriptor before resusciation").  It gets sent when the hub
+    driver's work thread checks whether a connect-change event on an
+    enabled port really indicates a new device has been connected, as
+    opposed to an old device momentarily disconnecting and then
+    reconnecting (which can happen with xHCI host controllers, since they
+    automatically enable connected ports).
+    
+    The same kind of thing occurs when a port's power session is lost
+    during system suspend.  When the system wakes up it sees a
+    connect-change event on the port, and if the child device's
+    persist_enabled flag was set then hub_activate() sets the device's
+    reset_resume flag as well as the port's bit in hub->change_bits.  The
+    reset-resume code then takes responsibility for checking that the same
+    device is still attached to the port, and it does this as part of the
+    device's resume pathway.  By the time the hub driver's work thread
+    starts up again, the device has already been fully reinitialized and
+    is busy doing its own thing.  There's no need for the work thread to
+    do the same check a second time, and in fact this unnecessary check is
+    what caused the problem that Paul observed.
+    
+    Note that performing the unnecessary check is not actually a bug.
+    Devices are supposed to be able to send descriptors back to the host
+    even when they are busy doing something else.  The underlying cause of
+    Paul's problem lies in his Bluetooth adapter.  Nevertheless, we
+    shouldn't perform the same check twice in a row -- and as a nice side
+    benefit, removing the extra check allows the Bluetooth adapter to work
+    more reliably.
+    
+    The work thread performs its check when it sees that the port's bit is
+    set in hub->change_bits.  In this situation that bit is interpreted as
+    though a connect-change event had occurred on the port _after_ the
+    reset-resume, which is not what actually happened.
+    
+    One possible fix would be to make the reset-resume code clear the
+    port's bit in hub->change_bits.  But it seems simpler to just avoid
+    setting the bit during hub_activate() in the first place.  That's what
+    this patch does.
+    
+    (Proving that the patch is correct when CONFIG_PM is disabled requires
+    a little thought.  In that setting hub_activate() will be called only
+    for initialization and resets, since there won't be any resumes or
+    reset-resumes.  During initialization and hub resets the hub doesn't
+    have any child devices, and so this code path never gets executed.)
+    
+    Reported-and-tested-by: Paul Zimmerman 
+    Signed-off-by: Alan Stern 
+    Link: https://marc.info/?t=157949360700001&r=1&w=2
+    CC: David Heinzelmann 
+    CC: 
+    Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.2001311037460.1577-100000@iolanthe.rowland.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index de94fa4a4ca7..1d212f82c69b 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1219,11 +1219,6 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ #ifdef CONFIG_PM
+ 			udev->reset_resume = 1;
+ #endif
+-			/* Don't set the change_bits when the device
+-			 * was powered off.
+-			 */
+-			if (test_bit(port1, hub->power_bits))
+-				set_bit(port1, hub->change_bits);
+ 
+ 		} else {
+ 			/* The power session is gone; tell hub_wq */

commit fdd64df7b9d1e20dbe28c9c205682b66ad821e6c
+Author: Alan Stern 
+Date:   Fri Jan 17 10:47:13 2020 -0500
+
+    USB: usbfs: Always unlink URBs in reverse order
+    
+    When the kernel unlinks a bunch of URBs for a single endpoint, it
+    should always unlink them in reverse order.  This eliminates any
+    possibility that some URB x will be unlinked before it can execute but
+    the following URB x+1 will execute before it can be unlinked.  Such an
+    event would be bad, for obvious reasons.
+    
+    Chris Dickens pointed out that usbfs doesn't behave this way when it
+    is unbound from an interface.  All pending URBs are cancelled, but in
+    the order of submission.  This patch changes the behavior to make the
+    unlinks occur in reverse order.  It similarly changes the behavior
+    when usbfs cancels the continuation URBs for a BULK endpoint.
+    
+    Suggested-by: Chris Dickens 
+    Signed-off-by: Alan Stern 
+    
+    Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.2001171045380.1571-100000@iolanthe.rowland.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 12bb5722b420..6833c918abce 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -574,7 +574,7 @@ __acquires(ps->lock)
+ 
+ 	/* Now carefully unlink all the marked pending URBs */
+  rescan:
+-	list_for_each_entry(as, &ps->async_pending, asynclist) {
++	list_for_each_entry_reverse(as, &ps->async_pending, asynclist) {
+ 		if (as->bulk_status == AS_UNLINK) {
+ 			as->bulk_status = 0;		/* Only once */
+ 			urb = as->urb;
+@@ -636,7 +636,7 @@ static void destroy_async(struct usb_dev_state *ps, struct list_head *list)
+ 
+ 	spin_lock_irqsave(&ps->lock, flags);
+ 	while (!list_empty(list)) {
+-		as = list_entry(list->next, struct async, asynclist);
++		as = list_last_entry(list, struct async, asynclist);
+ 		list_del_init(&as->asynclist);
+ 		urb = as->urb;
+ 		usb_get_urb(urb);

commit 2548288b4fb059b2da9ceada172ef763077e8a59
+Author: Alan Stern 
+Date:   Mon Jan 6 10:43:42 2020 -0500
+
+    USB: Fix: Don't skip endpoint descriptors with maxpacket=0
+    
+    It turns out that even though endpoints with a maxpacket length of 0
+    aren't useful for data transfer, the descriptors do serve other
+    purposes.  In particular, skipping them will also skip over other
+    class-specific descriptors for classes such as UVC.  This unexpected
+    side effect has caused some UVC cameras to stop working.
+    
+    In addition, the USB spec requires that when isochronous endpoint
+    descriptors are present in an interface's altsetting 0 (which is true
+    on some devices), the maxpacket size _must_ be set to 0.  Warning
+    about such things seems like a bad idea.
+    
+    This patch updates an earlier commit which would log a warning and
+    skip these endpoint descriptors.  Now we only log a warning, and we
+    don't even do that for isochronous endpoints in altsetting 0.
+    
+    We don't need to worry about preventing endpoints with maxpacket = 0
+    from ever being used for data transfers; usb_submit_urb() already
+    checks for this.
+    
+    Reported-and-tested-by: Roger Whittaker 
+    Fixes: d482c7bb0541 ("USB: Skip endpoints with 0 maxpacket length")
+    Signed-off-by: Alan Stern 
+    CC: Laurent Pinchart 
+    Link: https://marc.info/?l=linux-usb&m=157790377329882&w=2
+    Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.2001061040270.1514-100000@iolanthe.rowland.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
+index 21291950cc97..26bc05e48d8a 100644
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -392,12 +392,16 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
+ 			endpoint->desc.wMaxPacketSize = cpu_to_le16(8);
+ 	}
+ 
+-	/* Validate the wMaxPacketSize field */
++	/*
++	 * Validate the wMaxPacketSize field.
++	 * Some devices have isochronous endpoints in altsetting 0;
++	 * the USB-2 spec requires such endpoints to have wMaxPacketSize = 0
++	 * (see the end of section 5.6.3), so don't warn about them.
++	 */
+ 	maxp = usb_endpoint_maxp(&endpoint->desc);
+-	if (maxp == 0) {
+-		dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has wMaxPacketSize 0, skipping\n",
++	if (maxp == 0 && !(usb_endpoint_xfer_isoc(d) && asnum == 0)) {
++		dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has invalid wMaxPacketSize 0\n",
+ 		    cfgno, inum, asnum, d->bEndpointAddress);
+-		goto skip_to_next_endpoint_or_interface_descriptor;
+ 	}
+ 
+ 	/* Find the highest legal maxpacket size for this endpoint */

commit 8ec321e96e056de84022c032ffea253431a83c3c
+Author: Alan Stern 
+Date:   Tue Dec 10 16:26:11 2019 -0500
+
+    HID: Fix slab-out-of-bounds read in hid_field_extract
+    
+    The syzbot fuzzer found a slab-out-of-bounds bug in the HID report
+    handler.  The bug was caused by a report descriptor which included a
+    field with size 12 bits and count 4899, for a total size of 7349
+    bytes.
+    
+    The usbhid driver uses at most a single-page 4-KB buffer for reports.
+    In the test there wasn't any problem about overflowing the buffer,
+    since only one byte was received from the device.  Rather, the bug
+    occurred when the HID core tried to extract the data from the report
+    fields, which caused it to try reading data beyond the end of the
+    allocated buffer.
+    
+    This patch fixes the problem by rejecting any report whose total
+    length exceeds the HID_MAX_BUFFER_SIZE limit (minus one byte to allow
+    for a possible report index).  In theory a device could have a report
+    longer than that, but if there was such a thing we wouldn't handle it
+    correctly anyway.
+    
+    Reported-and-tested-by: syzbot+09ef48aa58261464b621@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    CC: 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
+index e0b241bd3070..851fe54ea59e 100644
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -288,6 +288,12 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
+ 	offset = report->size;
+ 	report->size += parser->global.report_size * parser->global.report_count;
+ 
++	/* Total size check: Allow for possible report index byte */
++	if (report->size > (HID_MAX_BUFFER_SIZE - 1) << 3) {
++		hid_err(parser->device, "report is too long\n");
++		return -1;
++	}
++
+ 	if (!parser->local.usage_index) /* Ignore padding fields */
+ 		return 0;
+ 

commit 54f83b8c8ea9b22082a496deadf90447a326954e
+Author: Alan Stern 
+Date:   Mon Oct 28 10:54:26 2019 -0400
+
+    USB: gadget: Reject endpoints with 0 maxpacket value
+    
+    Endpoints with a maxpacket length of 0 are probably useless.  They
+    can't transfer any data, and it's not at all unlikely that a UDC will
+    crash or hang when trying to handle a non-zero-length usb_request for
+    such an endpoint.  Indeed, dummy-hcd gets a divide error when trying
+    to calculate the remainder of a transfer length by the maxpacket
+    value, as discovered by the syzbot fuzzer.
+    
+    Currently the gadget core does not check for endpoints having a
+    maxpacket value of 0.  This patch adds a check to usb_ep_enable(),
+    preventing such endpoints from being used.
+    
+    As far as I know, none of the gadget drivers in the kernel tries to
+    create an endpoint with maxpacket = 0, but until now there has been
+    nothing to prevent userspace programs under gadgetfs or configfs from
+    doing it.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: syzbot+8ab8bf161038a8768553@syzkaller.appspotmail.com
+    CC: 
+    Acked-by: Felipe Balbi 
+    
+    Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.1910281052370.1485-100000@iolanthe.rowland.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
+index 92af8dc98c3d..51fa614b4079 100644
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -98,6 +98,17 @@ int usb_ep_enable(struct usb_ep *ep)
+ 	if (ep->enabled)
+ 		goto out;
+ 
++	/* UDC drivers can't handle endpoints with maxpacket size 0 */
++	if (usb_endpoint_maxp(ep->desc) == 0) {
++		/*
++		 * We should log an error message here, but we can't call
++		 * dev_err() because there's no way to find the gadget
++		 * given only ep.
++		 */
++		ret = -EINVAL;
++		goto out;
++	}
++
+ 	ret = ep->ops->enable(ep, ep->desc);
+ 	if (ret)
+ 		goto out;

commit 1186f86a71130a7635a20843e355bb880c7349b2
+Author: Alan Stern 
+Date:   Wed Oct 23 11:34:33 2019 -0400
+
+    UAS: Revert commit 3ae62a42090f ("UAS: fix alignment of scatter/gather segments")
+    
+    Commit 3ae62a42090f ("UAS: fix alignment of scatter/gather segments"),
+    copying a similar commit for usb-storage, attempted to solve a problem
+    involving scatter-gather I/O and USB/IP by setting the
+    virt_boundary_mask for mass-storage devices.
+    
+    However, it now turns out that the analogous change in usb-storage
+    interacted badly with commit 09324d32d2a0 ("block: force an unlimited
+    segment size on queues with a virt boundary"), which was added later.
+    A typical error message is:
+    
+            ehci-pci 0000:00:13.2: swiotlb buffer is full (sz: 327680 bytes),
+            total 32768 (slots), used 97 (slots)
+    
+    There is no longer any reason to keep the virt_boundary_mask setting
+    in the uas driver.  It was needed in the first place only for
+    handling devices with a block size smaller than the maxpacket size and
+    where the host controller was not capable of fully general
+    scatter-gather operation (that is, able to merge two SG segments into
+    a single USB packet).  But:
+    
+            High-speed or slower connections never use a bulk maxpacket
+            value larger than 512;
+    
+            The SCSI layer does not handle block devices with a block size
+            smaller than 512 bytes;
+    
+            All the host controllers capable of SuperSpeed operation can
+            handle fully general SG;
+    
+            Since commit ea44d190764b ("usbip: Implement SG support to
+            vhci-hcd and stub driver") was merged, the USB/IP driver can
+            also handle SG.
+    
+    Therefore all supported device/controller combinations should be okay
+    with no need for any special virt_boundary_mask.  So in order to head
+    off potential problems similar to those affecting usb-storage, this
+    patch reverts commit 3ae62a42090f.
+    
+    Signed-off-by: Alan Stern 
+    CC: Oliver Neukum 
+    CC: 
+    Acked-by: Christoph Hellwig 
+    Fixes: 3ae62a42090f ("UAS: fix alignment of scatter/gather segments")
+    Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.1910231132470.1878-100000@iolanthe.rowland.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
+index bf80d6f81f58..34538253f12c 100644
+--- a/drivers/usb/storage/uas.c
++++ b/drivers/usb/storage/uas.c
+@@ -789,29 +789,9 @@ static int uas_slave_alloc(struct scsi_device *sdev)
+ {
+ 	struct uas_dev_info *devinfo =
+ 		(struct uas_dev_info *)sdev->host->hostdata;
+-	int maxp;
+ 
+ 	sdev->hostdata = devinfo;
+ 
+-	/*
+-	 * We have two requirements here. We must satisfy the requirements
+-	 * of the physical HC and the demands of the protocol, as we
+-	 * definitely want no additional memory allocation in this path
+-	 * ruling out using bounce buffers.
+-	 *
+-	 * For a transmission on USB to continue we must never send
+-	 * a package that is smaller than maxpacket. Hence the length of each
+-         * scatterlist element except the last must be divisible by the
+-         * Bulk maxpacket value.
+-	 * If the HC does not ensure that through SG,
+-	 * the upper layer must do that. We must assume nothing
+-	 * about the capabilities off the HC, so we use the most
+-	 * pessimistic requirement.
+-	 */
+-
+-	maxp = usb_maxpacket(devinfo->udev, devinfo->data_in_pipe, 0);
+-	blk_queue_virt_boundary(sdev->request_queue, maxp - 1);
+-
+ 	/*
+ 	 * The protocol has no requirements on alignment in the strict sense.
+ 	 * Controllers may or may not have alignment restrictions.

commit 9a976949613132977098fc49510b46fa8678d864
+Author: Alan Stern 
+Date:   Mon Oct 21 11:48:06 2019 -0400
+
+    usb-storage: Revert commit 747668dbc061 ("usb-storage: Set virt_boundary_mask to avoid SG overflows")
+    
+    Commit 747668dbc061 ("usb-storage: Set virt_boundary_mask to avoid SG
+    overflows") attempted to solve a problem involving scatter-gather I/O
+    and USB/IP by setting the virt_boundary_mask for mass-storage devices.
+    
+    However, it now turns out that this interacts badly with commit
+    09324d32d2a0 ("block: force an unlimited segment size on queues with a
+    virt boundary"), which was added later.  A typical error message is:
+    
+            ehci-pci 0000:00:13.2: swiotlb buffer is full (sz: 327680 bytes),
+            total 32768 (slots), used 97 (slots)
+    
+    There is no longer any reason to keep the virt_boundary_mask setting
+    for usb-storage.  It was needed in the first place only for handling
+    devices with a block size smaller than the maxpacket size and where
+    the host controller was not capable of fully general scatter-gather
+    operation (that is, able to merge two SG segments into a single USB
+    packet).  But:
+    
+            High-speed or slower connections never use a bulk maxpacket
+            value larger than 512;
+    
+            The SCSI layer does not handle block devices with a block size
+            smaller than 512 bytes;
+    
+            All the host controllers capable of SuperSpeed operation can
+            handle fully general SG;
+    
+            Since commit ea44d190764b ("usbip: Implement SG support to
+            vhci-hcd and stub driver") was merged, the USB/IP driver can
+            also handle SG.
+    
+    Therefore all supported device/controller combinations should be okay
+    with no need for any special virt_boundary_mask.  So in order to fix
+    the swiotlb problem, this patch reverts commit 747668dbc061.
+    
+    Reported-and-tested-by: Piergiorgio Sartor 
+    Link: https://marc.info/?l=linux-usb&m=157134199501202&w=2
+    Signed-off-by: Alan Stern 
+    CC: Seth Bollinger 
+    CC: 
+    Fixes: 747668dbc061 ("usb-storage: Set virt_boundary_mask to avoid SG overflows")
+    Acked-by: Christoph Hellwig 
+    Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.1910211145520.1673-100000@iolanthe.rowland.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index 6737fab94959..54a3c8195c96 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -68,7 +68,6 @@ static const char* host_info(struct Scsi_Host *host)
+ static int slave_alloc (struct scsi_device *sdev)
+ {
+ 	struct us_data *us = host_to_us(sdev->host);
+-	int maxp;
+ 
+ 	/*
+ 	 * Set the INQUIRY transfer length to 36.  We don't use any of
+@@ -77,15 +76,6 @@ static int slave_alloc (struct scsi_device *sdev)
+ 	 */
+ 	sdev->inquiry_len = 36;
+ 
+-	/*
+-	 * USB has unusual scatter-gather requirements: the length of each
+-	 * scatterlist element except the last must be divisible by the
+-	 * Bulk maxpacket value.  Fortunately this value is always a
+-	 * power of 2.  Inform the block layer about this requirement.
+-	 */
+-	maxp = usb_maxpacket(us->pusb_dev, us->recv_bulk_pipe, 0);
+-	blk_queue_virt_boundary(sdev->request_queue, maxp - 1);
+-
+ 	/*
+ 	 * Some host controllers may have alignment requirements.
+ 	 * We'll play it safe by requiring 512-byte alignment always.

commit d482c7bb0541d19dea8bff437a9f3c5563b5b2d2
+Author: Alan Stern 
+Date:   Mon Oct 28 10:52:35 2019 -0400
+
+    USB: Skip endpoints with 0 maxpacket length
+    
+    Endpoints with a maxpacket length of 0 are probably useless.  They
+    can't transfer any data, and it's not at all unlikely that an HCD will
+    crash or hang when trying to handle an URB for such an endpoint.
+    
+    Currently the USB core does not check for endpoints having a maxpacket
+    value of 0.  This patch adds a check, printing a warning and skipping
+    over any endpoints it catches.
+    
+    Now, the USB spec does not rule out endpoints having maxpacket = 0.
+    But since they wouldn't have any practical use, there doesn't seem to
+    be any good reason for us to accept them.
+    
+    Signed-off-by: Alan Stern 
+    
+    Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.1910281050420.1485-100000@iolanthe.rowland.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
+index 151a74a54386..1ac1095bfeac 100644
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -348,6 +348,11 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
+ 
+ 	/* Validate the wMaxPacketSize field */
+ 	maxp = usb_endpoint_maxp(&endpoint->desc);
++	if (maxp == 0) {
++		dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has wMaxPacketSize 0, skipping\n",
++		    cfgno, inum, asnum, d->bEndpointAddress);
++		goto skip_to_next_endpoint_or_interface_descriptor;
++	}
+ 
+ 	/* Find the highest legal maxpacket size for this endpoint */
+ 	i = 0;		/* additional transactions per microframe */

commit 9e08117c9d4efc1e1bc6fce83dab856d9fd284b6
+Author: Alan Stern 
+Date:   Mon Oct 7 12:09:53 2019 -0300
+
+    media: usbvision: Fix races among open, close, and disconnect
+    
+    Visual inspection of the usbvision driver shows that it suffers from
+    three races between its open, close, and disconnect handlers.  In
+    particular, the driver is careful to update its usbvision->user and
+    usbvision->remove_pending flags while holding the private mutex, but:
+    
+            usbvision_v4l2_close() and usbvision_radio_close() don't hold
+            the mutex while they check the value of
+            usbvision->remove_pending;
+    
+            usbvision_disconnect() doesn't hold the mutex while checking
+            the value of usbvision->user; and
+    
+            also, usbvision_v4l2_open() and usbvision_radio_open() don't
+            check whether the device has been unplugged before allowing
+            the user to open the device files.
+    
+    Each of these can potentially lead to usbvision_release() being called
+    twice and use-after-free errors.
+    
+    This patch fixes the races by reading the flags while the mutex is
+    still held and checking for pending removes before allowing an open to
+    succeed.
+    
+    Signed-off-by: Alan Stern 
+    CC: 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c
+index 62dec73aec6e..93d36aab824f 100644
+--- a/drivers/media/usb/usbvision/usbvision-video.c
++++ b/drivers/media/usb/usbvision/usbvision-video.c
+@@ -314,6 +314,10 @@ static int usbvision_v4l2_open(struct file *file)
+ 	if (mutex_lock_interruptible(&usbvision->v4l2_lock))
+ 		return -ERESTARTSYS;
+ 
++	if (usbvision->remove_pending) {
++		err_code = -ENODEV;
++		goto unlock;
++	}
+ 	if (usbvision->user) {
+ 		err_code = -EBUSY;
+ 	} else {
+@@ -377,6 +381,7 @@ static int usbvision_v4l2_open(struct file *file)
+ static int usbvision_v4l2_close(struct file *file)
+ {
+ 	struct usb_usbvision *usbvision = video_drvdata(file);
++	int r;
+ 
+ 	PDEBUG(DBG_IO, "close");
+ 
+@@ -391,9 +396,10 @@ static int usbvision_v4l2_close(struct file *file)
+ 	usbvision_scratch_free(usbvision);
+ 
+ 	usbvision->user--;
++	r = usbvision->remove_pending;
+ 	mutex_unlock(&usbvision->v4l2_lock);
+ 
+-	if (usbvision->remove_pending) {
++	if (r) {
+ 		printk(KERN_INFO "%s: Final disconnect\n", __func__);
+ 		usbvision_release(usbvision);
+ 		return 0;
+@@ -1064,6 +1070,11 @@ static int usbvision_radio_open(struct file *file)
+ 
+ 	if (mutex_lock_interruptible(&usbvision->v4l2_lock))
+ 		return -ERESTARTSYS;
++
++	if (usbvision->remove_pending) {
++		err_code = -ENODEV;
++		goto out;
++	}
+ 	err_code = v4l2_fh_open(file);
+ 	if (err_code)
+ 		goto out;
+@@ -1096,6 +1107,7 @@ static int usbvision_radio_open(struct file *file)
+ static int usbvision_radio_close(struct file *file)
+ {
+ 	struct usb_usbvision *usbvision = video_drvdata(file);
++	int r;
+ 
+ 	PDEBUG(DBG_IO, "");
+ 
+@@ -1109,9 +1121,10 @@ static int usbvision_radio_close(struct file *file)
+ 	usbvision_audio_off(usbvision);
+ 	usbvision->radio = 0;
+ 	usbvision->user--;
++	r = usbvision->remove_pending;
+ 	mutex_unlock(&usbvision->v4l2_lock);
+ 
+-	if (usbvision->remove_pending) {
++	if (r) {
+ 		printk(KERN_INFO "%s: Final disconnect\n", __func__);
+ 		v4l2_fh_release(file);
+ 		usbvision_release(usbvision);
+@@ -1543,6 +1556,7 @@ static int usbvision_probe(struct usb_interface *intf,
+ static void usbvision_disconnect(struct usb_interface *intf)
+ {
+ 	struct usb_usbvision *usbvision = to_usbvision(usb_get_intfdata(intf));
++	int u;
+ 
+ 	PDEBUG(DBG_PROBE, "");
+ 
+@@ -1559,13 +1573,14 @@ static void usbvision_disconnect(struct usb_interface *intf)
+ 	v4l2_device_disconnect(&usbvision->v4l2_dev);
+ 	usbvision_i2c_unregister(usbvision);
+ 	usbvision->remove_pending = 1;	/* Now all ISO data will be ignored */
++	u = usbvision->user;
+ 
+ 	usb_put_dev(usbvision->dev);
+ 	usbvision->dev = NULL;	/* USB device is no more */
+ 
+ 	mutex_unlock(&usbvision->v4l2_lock);
+ 
+-	if (usbvision->user) {
++	if (u) {
+ 		printk(KERN_INFO "%s: In use, disconnect pending\n",
+ 		       __func__);
+ 		wake_up_interruptible(&usbvision->wait_frame);

commit c7a191464078262bf799136317c95824e26a222b
+Author: Alan Stern 
+Date:   Mon Oct 7 12:09:04 2019 -0300
+
+    media: usbvision: Fix invalid accesses after device disconnect
+    
+    The syzbot fuzzer found two invalid-access bugs in the usbvision
+    driver.  These bugs occur when userspace keeps the device file open
+    after the device has been disconnected and usbvision_disconnect() has
+    set usbvision->dev to NULL:
+    
+            When the device file is closed, usbvision_radio_close() tries
+            to issue a usb_set_interface() call, passing the NULL pointer
+            as its first argument.
+    
+            If userspace performs a querycap ioctl call, vidioc_querycap()
+            calls usb_make_path() with the same NULL pointer.
+    
+    This patch fixes the problems by making the appropriate tests
+    beforehand.  Note that vidioc_querycap() is protected by
+    usbvision->v4l2_lock, acquired in a higher layer of the V4L2
+    subsystem.
+    
+    Reported-and-tested-by: syzbot+7fa38a608b1075dfd634@syzkaller.appspotmail.com
+    
+    Signed-off-by: Alan Stern 
+    CC: 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c
+index cdc66adda755..62dec73aec6e 100644
+--- a/drivers/media/usb/usbvision/usbvision-video.c
++++ b/drivers/media/usb/usbvision/usbvision-video.c
+@@ -453,6 +453,9 @@ static int vidioc_querycap(struct file *file, void  *priv,
+ {
+ 	struct usb_usbvision *usbvision = video_drvdata(file);
+ 
++	if (!usbvision->dev)
++		return -ENODEV;
++
+ 	strscpy(vc->driver, "USBVision", sizeof(vc->driver));
+ 	strscpy(vc->card,
+ 		usbvision_device_data[usbvision->dev_model].model_string,
+@@ -1099,8 +1102,9 @@ static int usbvision_radio_close(struct file *file)
+ 	mutex_lock(&usbvision->v4l2_lock);
+ 	/* Set packet size to 0 */
+ 	usbvision->iface_alt = 0;
+-	usb_set_interface(usbvision->dev, usbvision->iface,
+-				    usbvision->iface_alt);
++	if (usbvision->dev)
++		usb_set_interface(usbvision->dev, usbvision->iface,
++				  usbvision->iface_alt);
+ 
+ 	usbvision_audio_off(usbvision);
+ 	usbvision->radio = 0;

commit c58a80170169305f7a088e8ebb61231e3095b5cd
+Author: Alan Stern 
+Date:   Tue Oct 1 13:40:19 2019 -0400
+
+    tools/memory-model/Documentation: Add plain accesses and data races to explanation.txt
+    
+    This patch updates the Linux Kernel Memory Model's explanation.txt
+    file by adding a section devoted to the model's handling of plain
+    accesses and data-race detection.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Andrea Parri 
+    Signed-off-by: Paul E. McKenney 
+
+diff --git a/tools/memory-model/Documentation/explanation.txt b/tools/memory-model/Documentation/explanation.txt
+index ecf6cccea5c3..e91a2eb19592 100644
+--- a/tools/memory-model/Documentation/explanation.txt
++++ b/tools/memory-model/Documentation/explanation.txt
+@@ -29,7 +29,8 @@ Explanation of the Linux-Kernel Memory Consistency Model
+   21. THE PROPAGATES-BEFORE RELATION: pb
+   22. RCU RELATIONS: rcu-link, rcu-gp, rcu-rscsi, rcu-order, rcu-fence, and rb
+   23. LOCKING
+-  24. ODDS AND ENDS
++  24. PLAIN ACCESSES AND DATA RACES
++  25. ODDS AND ENDS
+ 
+ 
+ 
+@@ -42,8 +43,7 @@ linux-kernel.bell and linux-kernel.cat files that make up the formal
+ version of the model; they are extremely terse and their meanings are
+ far from clear.
+ 
+-This document describes the ideas underlying the LKMM, but excluding
+-the modeling of bare C (or plain) shared memory accesses.  It is meant
++This document describes the ideas underlying the LKMM.  It is meant
+ for people who want to understand how the model was designed.  It does
+ not go into the details of the code in the .bell and .cat files;
+ rather, it explains in English what the code expresses symbolically.
+@@ -857,7 +857,7 @@ outlined above.  These restrictions involve the necessity of
+ maintaining cache coherence and the fact that a CPU can't operate on a
+ value before it knows what that value is, among other things.
+ 
+-The formal version of the LKMM is defined by five requirements, or
++The formal version of the LKMM is defined by six requirements, or
+ axioms:
+ 
+ 	Sequential consistency per variable: This requires that the
+@@ -877,10 +877,14 @@ axioms:
+ 	grace periods obey the rules of RCU, in particular, the
+ 	Grace-Period Guarantee.
+ 
++	Plain-coherence: This requires that plain memory accesses
++	(those not using READ_ONCE(), WRITE_ONCE(), etc.) must obey
++	the operational model's rules regarding cache coherence.
++
+ The first and second are quite common; they can be found in many
+ memory models (such as those for C11/C++11).  The "happens-before" and
+ "propagation" axioms have analogs in other memory models as well.  The
+-"rcu" axiom is specific to the LKMM.
++"rcu" and "plain-coherence" axioms are specific to the LKMM.
+ 
+ Each of these axioms is discussed below.
+ 
+@@ -1915,6 +1919,521 @@ architectures supported by the Linux kernel, albeit for various
+ differing reasons.
+ 
+ 
++PLAIN ACCESSES AND DATA RACES
++-----------------------------
++
++In the LKMM, memory accesses such as READ_ONCE(x), atomic_inc(&y),
++smp_load_acquire(&z), and so on are collectively referred to as
++"marked" accesses, because they are all annotated with special
++operations of one kind or another.  Ordinary C-language memory
++accesses such as x or y = 0 are simply called "plain" accesses.
++
++Early versions of the LKMM had nothing to say about plain accesses.
++The C standard allows compilers to assume that the variables affected
++by plain accesses are not concurrently read or written by any other
++threads or CPUs.  This leaves compilers free to implement all manner
++of transformations or optimizations of code containing plain accesses,
++making such code very difficult for a memory model to handle.
++
++Here is just one example of a possible pitfall:
++
++	int a = 6;
++	int *x = &a;
++
++	P0()
++	{
++		int *r1;
++		int r2 = 0;
++
++		r1 = x;
++		if (r1 != NULL)
++			r2 = READ_ONCE(*r1);
++	}
++
++	P1()
++	{
++		WRITE_ONCE(x, NULL);
++	}
++
++On the face of it, one would expect that when this code runs, the only
++possible final values for r2 are 6 and 0, depending on whether or not
++P1's store to x propagates to P0 before P0's load from x executes.
++But since P0's load from x is a plain access, the compiler may decide
++to carry out the load twice (for the comparison against NULL, then again
++for the READ_ONCE()) and eliminate the temporary variable r1.  The
++object code generated for P0 could therefore end up looking rather
++like this:
++
++	P0()
++	{
++		int r2 = 0;
++
++		if (x != NULL)
++			r2 = READ_ONCE(*x);
++	}
++
++And now it is obvious that this code runs the risk of dereferencing a
++NULL pointer, because P1's store to x might propagate to P0 after the
++test against NULL has been made but before the READ_ONCE() executes.
++If the original code had said "r1 = READ_ONCE(x)" instead of "r1 = x",
++the compiler would not have performed this optimization and there
++would be no possibility of a NULL-pointer dereference.
++
++Given the possibility of transformations like this one, the LKMM
++doesn't try to predict all possible outcomes of code containing plain
++accesses.  It is instead content to determine whether the code
++violates the compiler's assumptions, which would render the ultimate
++outcome undefined.
++
++In technical terms, the compiler is allowed to assume that when the
++program executes, there will not be any data races.  A "data race"
++occurs when two conflicting memory accesses execute concurrently;
++two memory accesses "conflict" if:
++
++	they access the same location,
++
++	they occur on different CPUs (or in different threads on the
++	same CPU),
++
++	at least one of them is a plain access,
++
++	and at least one of them is a store.
++
++The LKMM tries to determine whether a program contains two conflicting
++accesses which may execute concurrently; if it does then the LKMM says
++there is a potential data race and makes no predictions about the
++program's outcome.
++
++Determining whether two accesses conflict is easy; you can see that
++all the concepts involved in the definition above are already part of
++the memory model.  The hard part is telling whether they may execute
++concurrently.  The LKMM takes a conservative attitude, assuming that
++accesses may be concurrent unless it can prove they cannot.
++
++If two memory accesses aren't concurrent then one must execute before
++the other.  Therefore the LKMM decides two accesses aren't concurrent
++if they can be connected by a sequence of hb, pb, and rb links
++(together referred to as xb, for "executes before").  However, there
++are two complicating factors.
++
++If X is a load and X executes before a store Y, then indeed there is
++no danger of X and Y being concurrent.  After all, Y can't have any
++effect on the value obtained by X until the memory subsystem has
++propagated Y from its own CPU to X's CPU, which won't happen until
++some time after Y executes and thus after X executes.  But if X is a
++store, then even if X executes before Y it is still possible that X
++will propagate to Y's CPU just as Y is executing.  In such a case X
++could very well interfere somehow with Y, and we would have to
++consider X and Y to be concurrent.
++
++Therefore when X is a store, for X and Y to be non-concurrent the LKMM
++requires not only that X must execute before Y but also that X must
++propagate to Y's CPU before Y executes.  (Or vice versa, of course, if
++Y executes before X -- then Y must propagate to X's CPU before X
++executes if Y is a store.)  This is expressed by the visibility
++relation (vis), where X ->vis Y is defined to hold if there is an
++intermediate event Z such that:
++
++	X is connected to Z by a possibly empty sequence of
++	cumul-fence links followed by an optional rfe link (if none of
++	these links are present, X and Z are the same event),
++
++and either:
++
++	Z is connected to Y by a strong-fence link followed by a
++	possibly empty sequence of xb links,
++
++or:
++
++	Z is on the same CPU as Y and is connected to Y by a possibly
++	empty sequence of xb links (again, if the sequence is empty it
++	means Z and Y are the same event).
++
++The motivations behind this definition are straightforward:
++
++	cumul-fence memory barriers force stores that are po-before
++	the barrier to propagate to other CPUs before stores that are
++	po-after the barrier.
++
++	An rfe link from an event W to an event R says that R reads
++	from W, which certainly means that W must have propagated to
++	R's CPU before R executed.
++
++	strong-fence memory barriers force stores that are po-before
++	the barrier, or that propagate to the barrier's CPU before the
++	barrier executes, to propagate to all CPUs before any events
++	po-after the barrier can execute.
++
++To see how this works out in practice, consider our old friend, the MP
++pattern (with fences and statement labels, but without the conditional
++test):
++
++	int buf = 0, flag = 0;
++
++	P0()
++	{
++		X: WRITE_ONCE(buf, 1);
++		   smp_wmb();
++		W: WRITE_ONCE(flag, 1);
++	}
++
++	P1()
++	{
++		int r1;
++		int r2 = 0;
++
++		Z: r1 = READ_ONCE(flag);
++		   smp_rmb();
++		Y: r2 = READ_ONCE(buf);
++	}
++
++The smp_wmb() memory barrier gives a cumul-fence link from X to W, and
++assuming r1 = 1 at the end, there is an rfe link from W to Z.  This
++means that the store to buf must propagate from P0 to P1 before Z
++executes.  Next, Z and Y are on the same CPU and the smp_rmb() fence
++provides an xb link from Z to Y (i.e., it forces Z to execute before
++Y).  Therefore we have X ->vis Y: X must propagate to Y's CPU before Y
++executes.
++
++The second complicating factor mentioned above arises from the fact
++that when we are considering data races, some of the memory accesses
++are plain.  Now, although we have not said so explicitly, up to this
++point most of the relations defined by the LKMM (ppo, hb, prop,
++cumul-fence, pb, and so on -- including vis) apply only to marked
++accesses.
++
++There are good reasons for this restriction.  The compiler is not
++allowed to apply fancy transformations to marked accesses, and
++consequently each such access in the source code corresponds more or
++less directly to a single machine instruction in the object code.  But
++plain accesses are a different story; the compiler may combine them,
++split them up, duplicate them, eliminate them, invent new ones, and
++who knows what else.  Seeing a plain access in the source code tells
++you almost nothing about what machine instructions will end up in the
++object code.
++
++Fortunately, the compiler isn't completely free; it is subject to some
++limitations.  For one, it is not allowed to introduce a data race into
++the object code if the source code does not already contain a data
++race (if it could, memory models would be useless and no multithreaded
++code would be safe!).  For another, it cannot move a plain access past
++a compiler barrier.
++
++A compiler barrier is a kind of fence, but as the name implies, it
++only affects the compiler; it does not necessarily have any effect on
++how instructions are executed by the CPU.  In Linux kernel source
++code, the barrier() function is a compiler barrier.  It doesn't give
++rise directly to any machine instructions in the object code; rather,
++it affects how the compiler generates the rest of the object code.
++Given source code like this:
++
++	... some memory accesses ...
++	barrier();
++	... some other memory accesses ...
++
++the barrier() function ensures that the machine instructions
++corresponding to the first group of accesses will all end po-before
++any machine instructions corresponding to the second group of accesses
++-- even if some of the accesses are plain.  (Of course, the CPU may
++then execute some of those accesses out of program order, but we
++already know how to deal with such issues.)  Without the barrier()
++there would be no such guarantee; the two groups of accesses could be
++intermingled or even reversed in the object code.
++
++The LKMM doesn't say much about the barrier() function, but it does
++require that all fences are also compiler barriers.  In addition, it
++requires that the ordering properties of memory barriers such as
++smp_rmb() or smp_store_release() apply to plain accesses as well as to
++marked accesses.
++
++This is the key to analyzing data races.  Consider the MP pattern
++again, now using plain accesses for buf:
++
++	int buf = 0, flag = 0;
++
++	P0()
++	{
++		U: buf = 1;
++		   smp_wmb();
++		X: WRITE_ONCE(flag, 1);
++	}
++
++	P1()
++	{
++		int r1;
++		int r2 = 0;
++
++		Y: r1 = READ_ONCE(flag);
++		   if (r1) {
++			   smp_rmb();
++			V: r2 = buf;
++		   }
++	}
++
++This program does not contain a data race.  Although the U and V
++accesses conflict, the LKMM can prove they are not concurrent as
++follows:
++
++	The smp_wmb() fence in P0 is both a compiler barrier and a
++	cumul-fence.  It guarantees that no matter what hash of
++	machine instructions the compiler generates for the plain
++	access U, all those instructions will be po-before the fence.
++	Consequently U's store to buf, no matter how it is carried out
++	at the machine level, must propagate to P1 before X's store to
++	flag does.
++
++	X and Y are both marked accesses.  Hence an rfe link from X to
++	Y is a valid indicator that X propagated to P1 before Y
++	executed, i.e., X ->vis Y.  (And if there is no rfe link then
++	r1 will be 0, so V will not be executed and ipso facto won't
++	race with U.)
++
++	The smp_rmb() fence in P1 is a compiler barrier as well as a
++	fence.  It guarantees that all the machine-level instructions
++	corresponding to the access V will be po-after the fence, and
++	therefore any loads among those instructions will execute
++	after the fence does and hence after Y does.
++
++Thus U's store to buf is forced to propagate to P1 before V's load
++executes (assuming V does execute), ruling out the possibility of a
++data race between them.
++
++This analysis illustrates how the LKMM deals with plain accesses in
++general.  Suppose R is a plain load and we want to show that R
++executes before some marked access E.  We can do this by finding a
++marked access X such that R and X are ordered by a suitable fence and
++X ->xb* E.  If E was also a plain access, we would also look for a
++marked access Y such that X ->xb* Y, and Y and E are ordered by a
++fence.  We describe this arrangement by saying that R is
++"post-bounded" by X and E is "pre-bounded" by Y.
++
++In fact, we go one step further: Since R is a read, we say that R is
++"r-post-bounded" by X.  Similarly, E would be "r-pre-bounded" or
++"w-pre-bounded" by Y, depending on whether E was a store or a load.
++This distinction is needed because some fences affect only loads
++(i.e., smp_rmb()) and some affect only stores (smp_wmb()); otherwise
++the two types of bounds are the same.  And as a degenerate case, we
++say that a marked access pre-bounds and post-bounds itself (e.g., if R
++above were a marked load then X could simply be taken to be R itself.)
++
++The need to distinguish between r- and w-bounding raises yet another
++issue.  When the source code contains a plain store, the compiler is
++allowed to put plain loads of the same location into the object code.
++For example, given the source code:
++
++	x = 1;
++
++the compiler is theoretically allowed to generate object code that
++looks like:
++
++	if (x != 1)
++		x = 1;
++
++thereby adding a load (and possibly replacing the store entirely).
++For this reason, whenever the LKMM requires a plain store to be
++w-pre-bounded or w-post-bounded by a marked access, it also requires
++the store to be r-pre-bounded or r-post-bounded, so as to handle cases
++where the compiler adds a load.
++
++(This may be overly cautious.  We don't know of any examples where a
++compiler has augmented a store with a load in this fashion, and the
++Linux kernel developers would probably fight pretty hard to change a
++compiler if it ever did this.  Still, better safe than sorry.)
++
++Incidentally, the other tranformation -- augmenting a plain load by
++adding in a store to the same location -- is not allowed.  This is
++because the compiler cannot know whether any other CPUs might perform
++a concurrent load from that location.  Two concurrent loads don't
++constitute a race (they can't interfere with each other), but a store
++does race with a concurrent load.  Thus adding a store might create a
++data race where one was not already present in the source code,
++something the compiler is forbidden to do.  Augmenting a store with a
++load, on the other hand, is acceptable because doing so won't create a
++data race unless one already existed.
++
++The LKMM includes a second way to pre-bound plain accesses, in
++addition to fences: an address dependency from a marked load.  That
++is, in the sequence:
++
++	p = READ_ONCE(ptr);
++	r = *p;
++
++the LKMM says that the marked load of ptr pre-bounds the plain load of
++*p; the marked load must execute before any of the machine
++instructions corresponding to the plain load.  This is a reasonable
++stipulation, since after all, the CPU can't perform the load of *p
++until it knows what value p will hold.  Furthermore, without some
++assumption like this one, some usages typical of RCU would count as
++data races.  For example:
++
++	int a = 1, b;
++	int *ptr = &a;
++
++	P0()
++	{
++		b = 2;
++		rcu_assign_pointer(ptr, &b);
++	}
++
++	P1()
++	{
++		int *p;
++		int r;
++
++		rcu_read_lock();
++		p = rcu_dereference(ptr);
++		r = *p;
++		rcu_read_unlock();
++	}
++
++(In this example the rcu_read_lock() and rcu_read_unlock() calls don't
++really do anything, because there aren't any grace periods.  They are
++included merely for the sake of good form; typically P0 would call
++synchronize_rcu() somewhere after the rcu_assign_pointer().)
++
++rcu_assign_pointer() performs a store-release, so the plain store to b
++is definitely w-post-bounded before the store to ptr, and the two
++stores will propagate to P1 in that order.  However, rcu_dereference()
++is only equivalent to READ_ONCE().  While it is a marked access, it is
++not a fence or compiler barrier.  Hence the only guarantee we have
++that the load of ptr in P1 is r-pre-bounded before the load of *p
++(thus avoiding a race) is the assumption about address dependencies.
++
++This is a situation where the compiler can undermine the memory model,
++and a certain amount of care is required when programming constructs
++like this one.  In particular, comparisons between the pointer and
++other known addresses can cause trouble.  If you have something like:
++
++	p = rcu_dereference(ptr);
++	if (p == &x)
++		r = *p;
++
++then the compiler just might generate object code resembling:
++
++	p = rcu_dereference(ptr);
++	if (p == &x)
++		r = x;
++
++or even:
++
++	rtemp = x;
++	p = rcu_dereference(ptr);
++	if (p == &x)
++		r = rtemp;
++
++which would invalidate the memory model's assumption, since the CPU
++could now perform the load of x before the load of ptr (there might be
++a control dependency but no address dependency at the machine level).
++
++Finally, it turns out there is a situation in which a plain write does
++not need to be w-post-bounded: when it is separated from the
++conflicting access by a fence.  At first glance this may seem
++impossible.  After all, to be conflicting the second access has to be
++on a different CPU from the first, and fences don't link events on
++different CPUs.  Well, normal fences don't -- but rcu-fence can!
++Here's an example:
++
++	int x, y;
++
++	P0()
++	{
++		WRITE_ONCE(x, 1);
++		synchronize_rcu();
++		y = 3;
++	}
++
++	P1()
++	{
++		rcu_read_lock();
++		if (READ_ONCE(x) == 0)
++			y = 2;
++		rcu_read_unlock();
++	}
++
++Do the plain stores to y race?  Clearly not if P1 reads a non-zero
++value for x, so let's assume the READ_ONCE(x) does obtain 0.  This
++means that the read-side critical section in P1 must finish executing
++before the grace period in P0 does, because RCU's Grace-Period
++Guarantee says that otherwise P0's store to x would have propagated to
++P1 before the critical section started and so would have been visible
++to the READ_ONCE().  (Another way of putting it is that the fre link
++from the READ_ONCE() to the WRITE_ONCE() gives rise to an rcu-link
++between those two events.)
++
++This means there is an rcu-fence link from P1's "y = 2" store to P0's
++"y = 3" store, and consequently the first must propagate from P1 to P0
++before the second can execute.  Therefore the two stores cannot be
++concurrent and there is no race, even though P1's plain store to y
++isn't w-post-bounded by any marked accesses.
++
++Putting all this material together yields the following picture.  For
++two conflicting stores W and W', where W ->co W', the LKMM says the
++stores don't race if W can be linked to W' by a
++
++	w-post-bounded ; vis ; w-pre-bounded
++
++sequence.  If W is plain then they also have to be linked by an
++
++	r-post-bounded ; xb* ; w-pre-bounded
++
++sequence, and if W' is plain then they also have to be linked by a
++
++	w-post-bounded ; vis ; r-pre-bounded
++
++sequence.  For a conflicting load R and store W, the LKMM says the two
++accesses don't race if R can be linked to W by an
++
++	r-post-bounded ; xb* ; w-pre-bounded
++
++sequence or if W can be linked to R by a
++
++	w-post-bounded ; vis ; r-pre-bounded
++
++sequence.  For the cases involving a vis link, the LKMM also accepts
++sequences in which W is linked to W' or R by a
++
++	strong-fence ; xb* ; {w and/or r}-pre-bounded
++
++sequence with no post-bounding, and in every case the LKMM also allows
++the link simply to be a fence with no bounding at all.  If no sequence
++of the appropriate sort exists, the LKMM says that the accesses race.
++
++There is one more part of the LKMM related to plain accesses (although
++not to data races) we should discuss.  Recall that many relations such
++as hb are limited to marked accesses only.  As a result, the
++happens-before, propagates-before, and rcu axioms (which state that
++various relation must not contain a cycle) doesn't apply to plain
++accesses.  Nevertheless, we do want to rule out such cycles, because
++they don't make sense even for plain accesses.
++
++To this end, the LKMM imposes three extra restrictions, together
++called the "plain-coherence" axiom because of their resemblance to the
++rules used by the operational model to ensure cache coherence (that
++is, the rules governing the memory subsystem's choice of a store to
++satisfy a load request and its determination of where a store will
++fall in the coherence order):
++
++	If R and W conflict and it is possible to link R to W by one
++	of the xb* sequences listed above, then W ->rfe R is not
++	allowed (i.e., a load cannot read from a store that it
++	executes before, even if one or both is plain).
++
++	If W and R conflict and it is possible to link W to R by one
++	of the vis sequences listed above, then R ->fre W is not
++	allowed (i.e., if a store is visible to a load then the load
++	must read from that store or one coherence-after it).
++
++	If W and W' conflict and it is possible to link W to W' by one
++	of the vis sequences listed above, then W' ->co W is not
++	allowed (i.e., if one store is visible to a second then the
++	second must come after the first in the coherence order).
++
++This is the extent to which the LKMM deals with plain accesses.
++Perhaps it could say more (for example, plain accesses might
++contribute to the ppo relation), but at the moment it seems that this
++minimal, conservative approach is good enough.
++
++
+ ODDS AND ENDS
+ -------------
+ 
+@@ -1962,6 +2481,16 @@ treated as READ_ONCE() and rcu_assign_pointer() is treated as
+ smp_store_release() -- which is basically how the Linux kernel treats
+ them.
+ 
++Although we said that plain accesses are not linked by the ppo
++relation, they do contribute to it indirectly.  Namely, when there is
++an address dependency from a marked load R to a plain store W,
++followed by smp_wmb() and then a marked store W', the LKMM creates a
++ppo link from R to W'.  The reasoning behind this is perhaps a little
++shaky, but essentially it says there is no way to generate object code
++for this source code in which W' could execute before R.  Just as with
++pre-bounding by address dependencies, it is possible for the compiler
++to undermine this relation if sufficient care is not taken.
++
+ There are a few oddball fences which need special treatment:
+ smp_mb__before_atomic(), smp_mb__after_atomic(), and
+ smp_mb__after_spinlock().  The LKMM uses fence events with special

commit ddc82999f02580f93f9be2b8fb3b10f6139fb281
+Author: Alan Stern 
+Date:   Tue Oct 1 13:40:11 2019 -0400
+
+    tools/memory-model/Documentation: Put redefinition of rcu-fence into explanation.txt
+    
+    This patch updates the Linux Kernel Memory Model's explanation.txt
+    file to incorporate the introduction of the rcu-order relation and
+    the redefinition of rcu-fence made by commit 15aa25cbf0cc
+    ("tools/memory-model: Change definition of rcu-fence").
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Andrea Parri 
+    Signed-off-by: Paul E. McKenney 
+
+diff --git a/tools/memory-model/Documentation/explanation.txt b/tools/memory-model/Documentation/explanation.txt
+index 1b5264559cd6..ecf6cccea5c3 100644
+--- a/tools/memory-model/Documentation/explanation.txt
++++ b/tools/memory-model/Documentation/explanation.txt
+@@ -27,7 +27,7 @@ Explanation of the Linux-Kernel Memory Consistency Model
+   19. AND THEN THERE WAS ALPHA
+   20. THE HAPPENS-BEFORE RELATION: hb
+   21. THE PROPAGATES-BEFORE RELATION: pb
+-  22. RCU RELATIONS: rcu-link, rcu-gp, rcu-rscsi, rcu-fence, and rb
++  22. RCU RELATIONS: rcu-link, rcu-gp, rcu-rscsi, rcu-order, rcu-fence, and rb
+   23. LOCKING
+   24. ODDS AND ENDS
+ 
+@@ -1425,8 +1425,8 @@ they execute means that it cannot have cycles.  This requirement is
+ the content of the LKMM's "propagation" axiom.
+ 
+ 
+-RCU RELATIONS: rcu-link, rcu-gp, rcu-rscsi, rcu-fence, and rb
+--------------------------------------------------------------
++RCU RELATIONS: rcu-link, rcu-gp, rcu-rscsi, rcu-order, rcu-fence, and rb
++------------------------------------------------------------------------
+ 
+ RCU (Read-Copy-Update) is a powerful synchronization mechanism.  It
+ rests on two concepts: grace periods and read-side critical sections.
+@@ -1536,29 +1536,29 @@ Z's CPU before Z begins but doesn't propagate to some other CPU until
+ after X ends.)  Similarly, X ->rcu-rscsi Y ->rcu-link Z says that X is
+ the end of a critical section which starts before Z begins.
+ 
+-The LKMM goes on to define the rcu-fence relation as a sequence of
++The LKMM goes on to define the rcu-order relation as a sequence of
+ rcu-gp and rcu-rscsi links separated by rcu-link links, in which the
+ number of rcu-gp links is >= the number of rcu-rscsi links.  For
+ example:
+ 
+ 	X ->rcu-gp Y ->rcu-link Z ->rcu-rscsi T ->rcu-link U ->rcu-gp V
+ 
+-would imply that X ->rcu-fence V, because this sequence contains two
++would imply that X ->rcu-order V, because this sequence contains two
+ rcu-gp links and one rcu-rscsi link.  (It also implies that
+-X ->rcu-fence T and Z ->rcu-fence V.)  On the other hand:
++X ->rcu-order T and Z ->rcu-order V.)  On the other hand:
+ 
+ 	X ->rcu-rscsi Y ->rcu-link Z ->rcu-rscsi T ->rcu-link U ->rcu-gp V
+ 
+-does not imply X ->rcu-fence V, because the sequence contains only
++does not imply X ->rcu-order V, because the sequence contains only
+ one rcu-gp link but two rcu-rscsi links.
+ 
+-The rcu-fence relation is important because the Grace Period Guarantee
+-means that rcu-fence acts kind of like a strong fence.  In particular,
+-E ->rcu-fence F implies not only that E begins before F ends, but also
+-that any write po-before E will propagate to every CPU before any
+-instruction po-after F can execute.  (However, it does not imply that
+-E must execute before F; in fact, each synchronize_rcu() fence event
+-is linked to itself by rcu-fence as a degenerate case.)
++The rcu-order relation is important because the Grace Period Guarantee
++means that rcu-order links act kind of like strong fences.  In
++particular, E ->rcu-order F implies not only that E begins before F
++ends, but also that any write po-before E will propagate to every CPU
++before any instruction po-after F can execute.  (However, it does not
++imply that E must execute before F; in fact, each synchronize_rcu()
++fence event is linked to itself by rcu-order as a degenerate case.)
+ 
+ To prove this in full generality requires some intellectual effort.
+ We'll consider just a very simple case:
+@@ -1585,7 +1585,26 @@ G's CPU before G starts must propagate to every CPU before C starts.
+ In particular, the write propagates to every CPU before F finishes
+ executing and hence before any instruction po-after F can execute.
+ This sort of reasoning can be extended to handle all the situations
+-covered by rcu-fence.
++covered by rcu-order.
++
++The rcu-fence relation is a simple extension of rcu-order.  While
++rcu-order only links certain fence events (calls to synchronize_rcu(),
++rcu_read_lock(), or rcu_read_unlock()), rcu-fence links any events
++that are separated by an rcu-order link.  This is analogous to the way
++the strong-fence relation links events that are separated by an
++smp_mb() fence event (as mentioned above, rcu-order links act kind of
++like strong fences).  Written symbolically, X ->rcu-fence Y means
++there are fence events E and F such that:
++
++	X ->po E ->rcu-order F ->po Y.
++
++From the discussion above, we see this implies not only that X
++executes before Y, but also (if X is a store) that X propagates to
++every CPU before Y executes.  Thus rcu-fence is sort of a
++"super-strong" fence: Unlike the original strong fences (smp_mb() and
++synchronize_rcu()), rcu-fence is able to link events on different
++CPUs.  (Perhaps this fact should lead us to say that rcu-fence isn't
++really a fence at all!)
+ 
+ Finally, the LKMM defines the RCU-before (rb) relation in terms of
+ rcu-fence.  This is done in essentially the same way as the pb
+@@ -1596,7 +1615,7 @@ before F, just as E ->pb F does (and for much the same reasons).
+ Putting this all together, the LKMM expresses the Grace Period
+ Guarantee by requiring that the rb relation does not contain a cycle.
+ Equivalently, this "rcu" axiom requires that there are no events E
+-and F with E ->rcu-link F ->rcu-fence E.  Or to put it a third way,
++and F with E ->rcu-link F ->rcu-order E.  Or to put it a third way,
+ the axiom requires that there are no cycles consisting of rcu-gp and
+ rcu-rscsi alternating with rcu-link, where the number of rcu-gp links
+ is >= the number of rcu-rscsi links.
+@@ -1750,7 +1769,7 @@ addition to normal RCU.  The ideas involved are much the same as
+ above, with new relations srcu-gp and srcu-rscsi added to represent
+ SRCU grace periods and read-side critical sections.  There is a
+ restriction on the srcu-gp and srcu-rscsi links that can appear in an
+-rcu-fence sequence (the srcu-rscsi links must be paired with srcu-gp
++rcu-order sequence (the srcu-rscsi links must be paired with srcu-gp
+ links having the same SRCU domain with proper nesting); the details
+ are relatively unimportant.
+ 

commit 3321ea12907abd477ff7e9bf5f365524b8f1f2fc
+Author: Alan Stern 
+Date:   Tue Oct 1 13:39:47 2019 -0400
+
+    tools/memory-model/Documentation: Fix typos in explanation.txt
+    
+    This patch fixes a few minor typos and improves word usage in a few
+    places in the Linux Kernel Memory Model's explanation.txt file.
+    
+    Signed-off-by: Alan Stern 
+    Reviewed-by: Joel Fernandes (Google) 
+    Acked-by: Andrea Parri 
+    Signed-off-by: Paul E. McKenney 
+
+diff --git a/tools/memory-model/Documentation/explanation.txt b/tools/memory-model/Documentation/explanation.txt
+index 488f11f6c588..1b5264559cd6 100644
+--- a/tools/memory-model/Documentation/explanation.txt
++++ b/tools/memory-model/Documentation/explanation.txt
+@@ -206,7 +206,7 @@ goes like this:
+ 	P0 stores 1 to buf before storing 1 to flag, since it executes
+ 	its instructions in order.
+ 
+-	Since an instruction (in this case, P1's store to flag) cannot
++	Since an instruction (in this case, P0's store to flag) cannot
+ 	execute before itself, the specified outcome is impossible.
+ 
+ However, real computer hardware almost never follows the Sequential
+@@ -419,7 +419,7 @@ example:
+ 
+ The object code might call f(5) either before or after g(6); the
+ memory model cannot assume there is a fixed program order relation
+-between them.  (In fact, if the functions are inlined then the
++between them.  (In fact, if the function calls are inlined then the
+ compiler might even interleave their object code.)
+ 
+ 
+@@ -499,7 +499,7 @@ different CPUs (external reads-from, or rfe).
+ 
+ For our purposes, a memory location's initial value is treated as
+ though it had been written there by an imaginary initial store that
+-executes on a separate CPU before the program runs.
++executes on a separate CPU before the main program runs.
+ 
+ Usage of the rf relation implicitly assumes that loads will always
+ read from a single store.  It doesn't apply properly in the presence
+@@ -955,7 +955,7 @@ atomic update.  This is what the LKMM's "atomic" axiom says.
+ THE PRESERVED PROGRAM ORDER RELATION: ppo
+ -----------------------------------------
+ 
+-There are many situations where a CPU is obligated to execute two
++There are many situations where a CPU is obliged to execute two
+ instructions in program order.  We amalgamate them into the ppo (for
+ "preserved program order") relation, which links the po-earlier
+ instruction to the po-later instruction and is thus a sub-relation of
+@@ -1572,7 +1572,7 @@ and there are events X, Y and a read-side critical section C such that:
+ 
+ 	2. X comes "before" Y in some sense (including rfe, co and fr);
+ 
+-	2. Y is po-before Z;
++	3. Y is po-before Z;
+ 
+ 	4. Z is the rcu_read_unlock() event marking the end of C;
+ 

commit daebf24a8e8c6064cba3a330db9fe9376a137d2c
+Author: Alan Stern 
+Date:   Fri Sep 6 16:57:22 2019 -0400
+
+    tools/memory-model: Fix data race detection for unordered store and load
+    
+    Currently the Linux Kernel Memory Model gives an incorrect response
+    for the following litmus test:
+    
+    C plain-WWC
+    
+    {}
+    
+    P0(int *x)
+    {
+            WRITE_ONCE(*x, 2);
+    }
+    
+    P1(int *x, int *y)
+    {
+            int r1;
+            int r2;
+            int r3;
+    
+            r1 = READ_ONCE(*x);
+            if (r1 == 2) {
+                    smp_rmb();
+                    r2 = *x;
+            }
+            smp_rmb();
+            r3 = READ_ONCE(*x);
+            WRITE_ONCE(*y, r3 - 1);
+    }
+    
+    P2(int *x, int *y)
+    {
+            int r4;
+    
+            r4 = READ_ONCE(*y);
+            if (r4 > 0)
+                    WRITE_ONCE(*x, 1);
+    }
+    
+    exists (x=2 /\ 1:r2=2 /\ 2:r4=1)
+    
+    The memory model says that the plain read of *x in P1 races with the
+    WRITE_ONCE(*x) in P2.
+    
+    The problem is that we have a write W and a read R related by neither
+    fre or rfe, but rather W ->coe W' ->rfe R, where W' is an intermediate
+    write (the WRITE_ONCE() in P0).  In this situation there is no
+    particular ordering between W and R, so either a wr-vis link from W to
+    R or an rw-xbstar link from R to W would prove that the accesses
+    aren't concurrent.
+    
+    But the LKMM only looks for a wr-vis link, which is equivalent to
+    assuming that W must execute before R.  This is not necessarily true
+    on non-multicopy-atomic systems, as the WWC pattern demonstrates.
+    
+    This patch changes the LKMM to accept either a wr-vis or a reverse
+    rw-xbstar link as a proof of non-concurrency.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Andrea Parri 
+    Signed-off-by: Paul E. McKenney 
+
+diff --git a/tools/memory-model/linux-kernel.cat b/tools/memory-model/linux-kernel.cat
+index ea2ff4b94074..2a9b4fe4a84e 100644
+--- a/tools/memory-model/linux-kernel.cat
++++ b/tools/memory-model/linux-kernel.cat
+@@ -197,7 +197,7 @@ empty (wr-incoh | rw-incoh | ww-incoh) as plain-coherence
+ (* Actual races *)
+ let ww-nonrace = ww-vis & ((Marked * W) | rw-xbstar) & ((W * Marked) | wr-vis)
+ let ww-race = (pre-race & co) \ ww-nonrace
+-let wr-race = (pre-race & (co? ; rf)) \ wr-vis
++let wr-race = (pre-race & (co? ; rf)) \ wr-vis \ rw-xbstar^-1
+ let rw-race = (pre-race & fr) \ rw-xbstar
+ 
+ flag ~empty (ww-race | wr-race | rw-race) as data-race

commit 32a0721c6620b77504916dac0cea8ad497c4878a
+Author: Alan Stern 
+Date:   Tue Sep 17 12:47:23 2019 -0400
+
+    USB: yurex: Don't retry on unexpected errors
+    
+    According to Greg KH, it has been generally agreed that when a USB
+    driver encounters an unknown error (or one it can't handle directly),
+    it should just give up instead of going into a potentially infinite
+    retry loop.
+    
+    The three codes -EPROTO, -EILSEQ, and -ETIME fall into this category.
+    They can be caused by bus errors such as packet loss or corruption,
+    attempting to communicate with a disconnected device, or by malicious
+    firmware.  Nowadays the extent of packet loss or corruption is
+    negligible, so it should be safe for a driver to give up whenever one
+    of these errors occurs.
+    
+    Although the yurex driver handles -EILSEQ errors in this way, it
+    doesn't do the same for -EPROTO (as discovered by the syzbot fuzzer)
+    or other unrecognized errors.  This patch adjusts the driver so that
+    it doesn't log an error message for -EPROTO or -ETIME, and it doesn't
+    retry after any errors.
+    
+    Reported-and-tested-by: syzbot+b24d736f18a1541ad550@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    CC: Tomoki Sekiyama 
+    CC: 
+    
+    Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.1909171245410.1590-100000@iolanthe.rowland.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c
+index 6715a128e6c8..8d52d4336c29 100644
+--- a/drivers/usb/misc/yurex.c
++++ b/drivers/usb/misc/yurex.c
+@@ -132,6 +132,7 @@ static void yurex_interrupt(struct urb *urb)
+ 	switch (status) {
+ 	case 0: /*success*/
+ 		break;
++	/* The device is terminated or messed up, give up */
+ 	case -EOVERFLOW:
+ 		dev_err(&dev->interface->dev,
+ 			"%s - overflow with length %d, actual length is %d\n",
+@@ -140,12 +141,13 @@ static void yurex_interrupt(struct urb *urb)
+ 	case -ENOENT:
+ 	case -ESHUTDOWN:
+ 	case -EILSEQ:
+-		/* The device is terminated, clean up */
++	case -EPROTO:
++	case -ETIME:
+ 		return;
+ 	default:
+ 		dev_err(&dev->interface->dev,
+ 			"%s - unknown status received: %d\n", __func__, status);
+-		goto exit;
++		return;
+ 	}
+ 
+ 	/* handle received message */
+@@ -177,7 +179,6 @@ static void yurex_interrupt(struct urb *urb)
+ 		break;
+ 	}
+ 
+-exit:
+ 	retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
+ 	if (retval) {
+ 		dev_err(&dev->interface->dev, "%s - usb_submit_urb failed: %d\n",

commit d9d4b1e46d9543a82c23f6df03f4ad697dab361b
+Author: Alan Stern 
+Date:   Thu Oct 3 14:53:59 2019 -0400
+
+    HID: Fix assumption that devices have inputs
+    
+    The syzbot fuzzer found a slab-out-of-bounds write bug in the hid-gaff
+    driver.  The problem is caused by the driver's assumption that the
+    device must have an input report.  While this will be true for all
+    normal HID input devices, a suitably malicious device can violate the
+    assumption.
+    
+    The same assumption is present in over a dozen other HID drivers.
+    This patch fixes them by checking that the list of hid_inputs for the
+    hid_device is nonempty before allowing it to be used.
+    
+    Reported-and-tested-by: syzbot+403741a091bf41d4ae79@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    CC: 
+    Signed-off-by: Benjamin Tissoires 
+
+diff --git a/drivers/hid/hid-axff.c b/drivers/hid/hid-axff.c
+index 6654c1550e2e..fbe4e16ab029 100644
+--- a/drivers/hid/hid-axff.c
++++ b/drivers/hid/hid-axff.c
+@@ -63,13 +63,20 @@ static int axff_init(struct hid_device *hid)
+ {
+ 	struct axff_device *axff;
+ 	struct hid_report *report;
+-	struct hid_input *hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
++	struct hid_input *hidinput;
+ 	struct list_head *report_list =&hid->report_enum[HID_OUTPUT_REPORT].report_list;
+-	struct input_dev *dev = hidinput->input;
++	struct input_dev *dev;
+ 	int field_count = 0;
+ 	int i, j;
+ 	int error;
+ 
++	if (list_empty(&hid->inputs)) {
++		hid_err(hid, "no inputs found\n");
++		return -ENODEV;
++	}
++	hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
++	dev = hidinput->input;
++
+ 	if (list_empty(report_list)) {
+ 		hid_err(hid, "no output reports found\n");
+ 		return -ENODEV;
+diff --git a/drivers/hid/hid-dr.c b/drivers/hid/hid-dr.c
+index 17e17f9a597b..947f19f8685f 100644
+--- a/drivers/hid/hid-dr.c
++++ b/drivers/hid/hid-dr.c
+@@ -75,13 +75,19 @@ static int drff_init(struct hid_device *hid)
+ {
+ 	struct drff_device *drff;
+ 	struct hid_report *report;
+-	struct hid_input *hidinput = list_first_entry(&hid->inputs,
+-						struct hid_input, list);
++	struct hid_input *hidinput;
+ 	struct list_head *report_list =
+ 			&hid->report_enum[HID_OUTPUT_REPORT].report_list;
+-	struct input_dev *dev = hidinput->input;
++	struct input_dev *dev;
+ 	int error;
+ 
++	if (list_empty(&hid->inputs)) {
++		hid_err(hid, "no inputs found\n");
++		return -ENODEV;
++	}
++	hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
++	dev = hidinput->input;
++
+ 	if (list_empty(report_list)) {
+ 		hid_err(hid, "no output reports found\n");
+ 		return -ENODEV;
+diff --git a/drivers/hid/hid-emsff.c b/drivers/hid/hid-emsff.c
+index 7cd5651872d3..c34f2e5a049f 100644
+--- a/drivers/hid/hid-emsff.c
++++ b/drivers/hid/hid-emsff.c
+@@ -47,13 +47,19 @@ static int emsff_init(struct hid_device *hid)
+ {
+ 	struct emsff_device *emsff;
+ 	struct hid_report *report;
+-	struct hid_input *hidinput = list_first_entry(&hid->inputs,
+-						struct hid_input, list);
++	struct hid_input *hidinput;
+ 	struct list_head *report_list =
+ 			&hid->report_enum[HID_OUTPUT_REPORT].report_list;
+-	struct input_dev *dev = hidinput->input;
++	struct input_dev *dev;
+ 	int error;
+ 
++	if (list_empty(&hid->inputs)) {
++		hid_err(hid, "no inputs found\n");
++		return -ENODEV;
++	}
++	hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
++	dev = hidinput->input;
++
+ 	if (list_empty(report_list)) {
+ 		hid_err(hid, "no output reports found\n");
+ 		return -ENODEV;
+diff --git a/drivers/hid/hid-gaff.c b/drivers/hid/hid-gaff.c
+index 0f95c96b70f8..ecbd3995a4eb 100644
+--- a/drivers/hid/hid-gaff.c
++++ b/drivers/hid/hid-gaff.c
+@@ -64,14 +64,20 @@ static int gaff_init(struct hid_device *hid)
+ {
+ 	struct gaff_device *gaff;
+ 	struct hid_report *report;
+-	struct hid_input *hidinput = list_entry(hid->inputs.next,
+-						struct hid_input, list);
++	struct hid_input *hidinput;
+ 	struct list_head *report_list =
+ 			&hid->report_enum[HID_OUTPUT_REPORT].report_list;
+ 	struct list_head *report_ptr = report_list;
+-	struct input_dev *dev = hidinput->input;
++	struct input_dev *dev;
+ 	int error;
+ 
++	if (list_empty(&hid->inputs)) {
++		hid_err(hid, "no inputs found\n");
++		return -ENODEV;
++	}
++	hidinput = list_entry(hid->inputs.next, struct hid_input, list);
++	dev = hidinput->input;
++
+ 	if (list_empty(report_list)) {
+ 		hid_err(hid, "no output reports found\n");
+ 		return -ENODEV;
+diff --git a/drivers/hid/hid-holtekff.c b/drivers/hid/hid-holtekff.c
+index 10a720558830..8619b80c834c 100644
+--- a/drivers/hid/hid-holtekff.c
++++ b/drivers/hid/hid-holtekff.c
+@@ -124,13 +124,19 @@ static int holtekff_init(struct hid_device *hid)
+ {
+ 	struct holtekff_device *holtekff;
+ 	struct hid_report *report;
+-	struct hid_input *hidinput = list_entry(hid->inputs.next,
+-						struct hid_input, list);
++	struct hid_input *hidinput;
+ 	struct list_head *report_list =
+ 			&hid->report_enum[HID_OUTPUT_REPORT].report_list;
+-	struct input_dev *dev = hidinput->input;
++	struct input_dev *dev;
+ 	int error;
+ 
++	if (list_empty(&hid->inputs)) {
++		hid_err(hid, "no inputs found\n");
++		return -ENODEV;
++	}
++	hidinput = list_entry(hid->inputs.next, struct hid_input, list);
++	dev = hidinput->input;
++
+ 	if (list_empty(report_list)) {
+ 		hid_err(hid, "no output report found\n");
+ 		return -ENODEV;
+diff --git a/drivers/hid/hid-lg2ff.c b/drivers/hid/hid-lg2ff.c
+index dd1a6c3a7de6..73d07e35f12a 100644
+--- a/drivers/hid/hid-lg2ff.c
++++ b/drivers/hid/hid-lg2ff.c
+@@ -50,11 +50,17 @@ int lg2ff_init(struct hid_device *hid)
+ {
+ 	struct lg2ff_device *lg2ff;
+ 	struct hid_report *report;
+-	struct hid_input *hidinput = list_entry(hid->inputs.next,
+-						struct hid_input, list);
+-	struct input_dev *dev = hidinput->input;
++	struct hid_input *hidinput;
++	struct input_dev *dev;
+ 	int error;
+ 
++	if (list_empty(&hid->inputs)) {
++		hid_err(hid, "no inputs found\n");
++		return -ENODEV;
++	}
++	hidinput = list_entry(hid->inputs.next, struct hid_input, list);
++	dev = hidinput->input;
++
+ 	/* Check that the report looks ok */
+ 	report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7);
+ 	if (!report)
+diff --git a/drivers/hid/hid-lg3ff.c b/drivers/hid/hid-lg3ff.c
+index 9ecb6fd06203..b7e1949f3cf7 100644
+--- a/drivers/hid/hid-lg3ff.c
++++ b/drivers/hid/hid-lg3ff.c
+@@ -117,12 +117,19 @@ static const signed short ff3_joystick_ac[] = {
+ 
+ int lg3ff_init(struct hid_device *hid)
+ {
+-	struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+-	struct input_dev *dev = hidinput->input;
++	struct hid_input *hidinput;
++	struct input_dev *dev;
+ 	const signed short *ff_bits = ff3_joystick_ac;
+ 	int error;
+ 	int i;
+ 
++	if (list_empty(&hid->inputs)) {
++		hid_err(hid, "no inputs found\n");
++		return -ENODEV;
++	}
++	hidinput = list_entry(hid->inputs.next, struct hid_input, list);
++	dev = hidinput->input;
++
+ 	/* Check that the report looks ok */
+ 	if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 35))
+ 		return -ENODEV;
+diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
+index 03f0220062ca..5e6a0cef2a06 100644
+--- a/drivers/hid/hid-lg4ff.c
++++ b/drivers/hid/hid-lg4ff.c
+@@ -1253,8 +1253,8 @@ static int lg4ff_handle_multimode_wheel(struct hid_device *hid, u16 *real_produc
+ 
+ int lg4ff_init(struct hid_device *hid)
+ {
+-	struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+-	struct input_dev *dev = hidinput->input;
++	struct hid_input *hidinput;
++	struct input_dev *dev;
+ 	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+ 	struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+ 	const struct usb_device_descriptor *udesc = &(hid_to_usb_dev(hid)->descriptor);
+@@ -1266,6 +1266,13 @@ int lg4ff_init(struct hid_device *hid)
+ 	int mmode_ret, mmode_idx = -1;
+ 	u16 real_product_id;
+ 
++	if (list_empty(&hid->inputs)) {
++		hid_err(hid, "no inputs found\n");
++		return -ENODEV;
++	}
++	hidinput = list_entry(hid->inputs.next, struct hid_input, list);
++	dev = hidinput->input;
++
+ 	/* Check that the report looks ok */
+ 	if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7))
+ 		return -1;
+diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c
+index c79a6ec43745..aed4ddc397a9 100644
+--- a/drivers/hid/hid-lgff.c
++++ b/drivers/hid/hid-lgff.c
+@@ -115,12 +115,19 @@ static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude)
+ 
+ int lgff_init(struct hid_device* hid)
+ {
+-	struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+-	struct input_dev *dev = hidinput->input;
++	struct hid_input *hidinput;
++	struct input_dev *dev;
+ 	const signed short *ff_bits = ff_joystick;
+ 	int error;
+ 	int i;
+ 
++	if (list_empty(&hid->inputs)) {
++		hid_err(hid, "no inputs found\n");
++		return -ENODEV;
++	}
++	hidinput = list_entry(hid->inputs.next, struct hid_input, list);
++	dev = hidinput->input;
++
+ 	/* Check that the report looks ok */
+ 	if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7))
+ 		return -ENODEV;
+diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
+index 0179f7ed77e5..1ac1ecc1e67c 100644
+--- a/drivers/hid/hid-logitech-hidpp.c
++++ b/drivers/hid/hid-logitech-hidpp.c
+@@ -2084,8 +2084,8 @@ static void hidpp_ff_destroy(struct ff_device *ff)
+ static int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index)
+ {
+ 	struct hid_device *hid = hidpp->hid_dev;
+-	struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+-	struct input_dev *dev = hidinput->input;
++	struct hid_input *hidinput;
++	struct input_dev *dev;
+ 	const struct usb_device_descriptor *udesc = &(hid_to_usb_dev(hid)->descriptor);
+ 	const u16 bcdDevice = le16_to_cpu(udesc->bcdDevice);
+ 	struct ff_device *ff;
+@@ -2094,6 +2094,13 @@ static int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index)
+ 	int error, j, num_slots;
+ 	u8 version;
+ 
++	if (list_empty(&hid->inputs)) {
++		hid_err(hid, "no inputs found\n");
++		return -ENODEV;
++	}
++	hidinput = list_entry(hid->inputs.next, struct hid_input, list);
++	dev = hidinput->input;
++
+ 	if (!dev) {
+ 		hid_err(hid, "Struct input_dev not set!\n");
+ 		return -EINVAL;
+diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c
+index 2cf83856f2e4..2d8b589201a4 100644
+--- a/drivers/hid/hid-microsoft.c
++++ b/drivers/hid/hid-microsoft.c
+@@ -328,11 +328,17 @@ static int ms_play_effect(struct input_dev *dev, void *data,
+ 
+ static int ms_init_ff(struct hid_device *hdev)
+ {
+-	struct hid_input *hidinput = list_entry(hdev->inputs.next,
+-						struct hid_input, list);
+-	struct input_dev *input_dev = hidinput->input;
++	struct hid_input *hidinput;
++	struct input_dev *input_dev;
+ 	struct ms_data *ms = hid_get_drvdata(hdev);
+ 
++	if (list_empty(&hdev->inputs)) {
++		hid_err(hdev, "no inputs found\n");
++		return -ENODEV;
++	}
++	hidinput = list_entry(hdev->inputs.next, struct hid_input, list);
++	input_dev = hidinput->input;
++
+ 	if (!(ms->quirks & MS_QUIRK_FF))
+ 		return 0;
+ 
+diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
+index 73c0f7a95e2d..4c6ed6ef31f1 100644
+--- a/drivers/hid/hid-sony.c
++++ b/drivers/hid/hid-sony.c
+@@ -2254,9 +2254,15 @@ static int sony_play_effect(struct input_dev *dev, void *data,
+ 
+ static int sony_init_ff(struct sony_sc *sc)
+ {
+-	struct hid_input *hidinput = list_entry(sc->hdev->inputs.next,
+-						struct hid_input, list);
+-	struct input_dev *input_dev = hidinput->input;
++	struct hid_input *hidinput;
++	struct input_dev *input_dev;
++
++	if (list_empty(&sc->hdev->inputs)) {
++		hid_err(sc->hdev, "no inputs found\n");
++		return -ENODEV;
++	}
++	hidinput = list_entry(sc->hdev->inputs.next, struct hid_input, list);
++	input_dev = hidinput->input;
+ 
+ 	input_set_capability(input_dev, EV_FF, FF_RUMBLE);
+ 	return input_ff_create_memless(input_dev, NULL, sony_play_effect);
+diff --git a/drivers/hid/hid-tmff.c b/drivers/hid/hid-tmff.c
+index bdfc5ff3b2c5..90acef304536 100644
+--- a/drivers/hid/hid-tmff.c
++++ b/drivers/hid/hid-tmff.c
+@@ -124,12 +124,18 @@ static int tmff_init(struct hid_device *hid, const signed short *ff_bits)
+ 	struct tmff_device *tmff;
+ 	struct hid_report *report;
+ 	struct list_head *report_list;
+-	struct hid_input *hidinput = list_entry(hid->inputs.next,
+-							struct hid_input, list);
+-	struct input_dev *input_dev = hidinput->input;
++	struct hid_input *hidinput;
++	struct input_dev *input_dev;
+ 	int error;
+ 	int i;
+ 
++	if (list_empty(&hid->inputs)) {
++		hid_err(hid, "no inputs found\n");
++		return -ENODEV;
++	}
++	hidinput = list_entry(hid->inputs.next, struct hid_input, list);
++	input_dev = hidinput->input;
++
+ 	tmff = kzalloc(sizeof(struct tmff_device), GFP_KERNEL);
+ 	if (!tmff)
+ 		return -ENOMEM;
+diff --git a/drivers/hid/hid-zpff.c b/drivers/hid/hid-zpff.c
+index f90959e94028..3abaca045869 100644
+--- a/drivers/hid/hid-zpff.c
++++ b/drivers/hid/hid-zpff.c
+@@ -54,11 +54,17 @@ static int zpff_init(struct hid_device *hid)
+ {
+ 	struct zpff_device *zpff;
+ 	struct hid_report *report;
+-	struct hid_input *hidinput = list_entry(hid->inputs.next,
+-						struct hid_input, list);
+-	struct input_dev *dev = hidinput->input;
++	struct hid_input *hidinput;
++	struct input_dev *dev;
+ 	int i, error;
+ 
++	if (list_empty(&hid->inputs)) {
++		hid_err(hid, "no inputs found\n");
++		return -ENODEV;
++	}
++	hidinput = list_entry(hid->inputs.next, struct hid_input, list);
++	dev = hidinput->input;
++
+ 	for (i = 0; i < 4; i++) {
+ 		report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, i, 1);
+ 		if (!report)

commit 98375b86c79137416e9fd354177b85e768c16e56
+Author: Alan Stern 
+Date:   Wed Sep 4 11:54:20 2019 -0400
+
+    HID: prodikeys: Fix general protection fault during probe
+    
+    The syzbot fuzzer provoked a general protection fault in the
+    hid-prodikeys driver:
+    
+    kasan: CONFIG_KASAN_INLINE enabled
+    kasan: GPF could be caused by NULL-ptr deref or user memory access
+    general protection fault: 0000 [#1] SMP KASAN
+    CPU: 0 PID: 12 Comm: kworker/0:1 Not tainted 5.3.0-rc5+ #28
+    Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
+    Google 01/01/2011
+    Workqueue: usb_hub_wq hub_event
+    RIP: 0010:pcmidi_submit_output_report drivers/hid/hid-prodikeys.c:300  [inline]
+    RIP: 0010:pcmidi_set_operational drivers/hid/hid-prodikeys.c:558 [inline]
+    RIP: 0010:pcmidi_snd_initialise drivers/hid/hid-prodikeys.c:686 [inline]
+    RIP: 0010:pk_probe+0xb51/0xfd0 drivers/hid/hid-prodikeys.c:836
+    Code: 0f 85 50 04 00 00 48 8b 04 24 4c 89 7d 10 48 8b 58 08 e8 b2 53 e4 fc
+    48 8b 54 24 20 48 b8 00 00 00 00 00 fc ff df 48 c1 ea 03 <80> 3c 02 00 0f
+    85 13 04 00 00 48 ba 00 00 00 00 00 fc ff df 49 8b
+    
+    The problem is caused by the fact that pcmidi_get_output_report() will
+    return an error if the HID device doesn't provide the right sort of
+    output report, but pcmidi_set_operational() doesn't bother to check
+    the return code and assumes the function call always succeeds.
+    
+    This patch adds the missing check and aborts the probe operation if
+    necessary.
+    
+    Reported-and-tested-by: syzbot+1088533649dafa1c9004@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    CC: 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c
+index 21544ebff855..5a3b3d974d84 100644
+--- a/drivers/hid/hid-prodikeys.c
++++ b/drivers/hid/hid-prodikeys.c
+@@ -551,10 +551,14 @@ static void pcmidi_setup_extra_keys(
+ 
+ static int pcmidi_set_operational(struct pcmidi_snd *pm)
+ {
++	int rc;
++
+ 	if (pm->ifnum != 1)
+ 		return 0; /* only set up ONCE for interace 1 */
+ 
+-	pcmidi_get_output_report(pm);
++	rc = pcmidi_get_output_report(pm);
++	if (rc < 0)
++		return rc;
+ 	pcmidi_submit_output_report(pm, 0xc1);
+ 	return 0;
+ }
+@@ -683,7 +687,11 @@ static int pcmidi_snd_initialise(struct pcmidi_snd *pm)
+ 	spin_lock_init(&pm->rawmidi_in_lock);
+ 
+ 	init_sustain_timers(pm);
+-	pcmidi_set_operational(pm);
++	err = pcmidi_set_operational(pm);
++	if (err < 0) {
++		pk_error("failed to find output report\n");
++		goto fail_register;
++	}
+ 
+ 	/* register it */
+ 	err = snd_card_register(card);

commit 3dd550a2d36596a1b0ee7955da3b611c031d3873
+Author: Alan Stern 
+Date:   Wed Sep 4 11:56:27 2019 -0400
+
+    USB: usbcore: Fix slab-out-of-bounds bug during device reset
+    
+    The syzbot fuzzer provoked a slab-out-of-bounds error in the USB core:
+    
+    BUG: KASAN: slab-out-of-bounds in memcmp+0xa6/0xb0 lib/string.c:904
+    Read of size 1 at addr ffff8881d175bed6 by task kworker/0:3/2746
+    
+    CPU: 0 PID: 2746 Comm: kworker/0:3 Not tainted 5.3.0-rc5+ #28
+    Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
+    Google 01/01/2011
+    Workqueue: usb_hub_wq hub_event
+    Call Trace:
+      __dump_stack lib/dump_stack.c:77 [inline]
+      dump_stack+0xca/0x13e lib/dump_stack.c:113
+      print_address_description+0x6a/0x32c mm/kasan/report.c:351
+      __kasan_report.cold+0x1a/0x33 mm/kasan/report.c:482
+      kasan_report+0xe/0x12 mm/kasan/common.c:612
+      memcmp+0xa6/0xb0 lib/string.c:904
+      memcmp include/linux/string.h:400 [inline]
+      descriptors_changed drivers/usb/core/hub.c:5579 [inline]
+      usb_reset_and_verify_device+0x564/0x1300 drivers/usb/core/hub.c:5729
+      usb_reset_device+0x4c1/0x920 drivers/usb/core/hub.c:5898
+      rt2x00usb_probe+0x53/0x7af
+    drivers/net/wireless/ralink/rt2x00/rt2x00usb.c:806
+    
+    The error occurs when the descriptors_changed() routine (called during
+    a device reset) attempts to compare the old and new BOS and capability
+    descriptors.  The length it uses for the comparison is the
+    wTotalLength value stored in BOS descriptor, but this value is not
+    necessarily the same as the length actually allocated for the
+    descriptors.  If it is larger the routine will call memcmp() with a
+    length that is too big, thus reading beyond the end of the allocated
+    region and leading to this fault.
+    
+    The kernel reads the BOS descriptor twice: first to get the total
+    length of all the capability descriptors, and second to read it along
+    with all those other descriptors.  A malicious (or very faulty) device
+    may send different values for the BOS descriptor fields each time.
+    The memory area will be allocated using the wTotalLength value read
+    the first time, but stored within it will be the value read the second
+    time.
+    
+    To prevent this possibility from causing any errors, this patch
+    modifies the BOS descriptor after it has been read the second time:
+    It sets the wTotalLength field to the actual length of the descriptors
+    that were read in and validated.  Then the memcpy() call, or any other
+    code using these descriptors, will be able to rely on wTotalLength
+    being valid.
+    
+    Reported-and-tested-by: syzbot+35f4d916c623118d576e@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    CC: 
+    Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.1909041154260.1722-100000@iolanthe.rowland.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
+index 9d6cb709ca7b..151a74a54386 100644
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -921,7 +921,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
+ 	struct usb_bos_descriptor *bos;
+ 	struct usb_dev_cap_header *cap;
+ 	struct usb_ssp_cap_descriptor *ssp_cap;
+-	unsigned char *buffer;
++	unsigned char *buffer, *buffer0;
+ 	int length, total_len, num, i, ssac;
+ 	__u8 cap_type;
+ 	int ret;
+@@ -966,10 +966,12 @@ int usb_get_bos_descriptor(struct usb_device *dev)
+ 			ret = -ENOMSG;
+ 		goto err;
+ 	}
++
++	buffer0 = buffer;
+ 	total_len -= length;
++	buffer += length;
+ 
+ 	for (i = 0; i < num; i++) {
+-		buffer += length;
+ 		cap = (struct usb_dev_cap_header *)buffer;
+ 
+ 		if (total_len < sizeof(*cap) || total_len < cap->bLength) {
+@@ -983,8 +985,6 @@ int usb_get_bos_descriptor(struct usb_device *dev)
+ 			break;
+ 		}
+ 
+-		total_len -= length;
+-
+ 		if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) {
+ 			dev_warn(ddev, "descriptor type invalid, skip\n");
+ 			continue;
+@@ -1019,7 +1019,11 @@ int usb_get_bos_descriptor(struct usb_device *dev)
+ 		default:
+ 			break;
+ 		}
++
++		total_len -= length;
++		buffer += length;
+ 	}
++	dev->bos->desc->wTotalLength = cpu_to_le16(buffer - buffer0);
+ 
+ 	return 0;
+ 

commit 9472aff16ca0fd9351eea7773facef364743088f
+Author: Alan Stern 
+Date:   Thu Aug 8 13:34:08 2019 -0400
+
+    USB: rio500: Fix lockdep violation
+    
+    The syzbot fuzzer found a lockdep violation in the rio500 driver:
+    
+            ======================================================
+            WARNING: possible circular locking dependency detected
+            5.3.0-rc2+ #23 Not tainted
+            ------------------------------------------------------
+            syz-executor.2/20386 is trying to acquire lock:
+            00000000772249c6 (rio500_mutex){+.+.}, at: open_rio+0x16/0xc0
+            drivers/usb/misc/rio500.c:64
+    
+            but task is already holding lock:
+            00000000d3e8f4b9 (minor_rwsem){++++}, at: usb_open+0x23/0x270
+            drivers/usb/core/file.c:39
+    
+            which lock already depends on the new lock.
+    
+    The problem is that the driver's open_rio() routine is called while
+    the usbcore's minor_rwsem is locked for reading, and it acquires the
+    rio500_mutex; whereas conversely, probe_rio() and disconnect_rio()
+    first acquire the rio500_mutex and then call usb_register_dev() or
+    usb_deregister_dev(), which lock minor_rwsem for writing.
+    
+    The correct ordering of acquisition should be: minor_rwsem first, then
+    rio500_mutex (since the locking in open_rio() cannot be changed).
+    Thus, the probe and disconnect routines should avoid holding
+    rio500_mutex while doing their registration and deregistration.
+    
+    This patch adjusts the code in those two routines to do just that.  It
+    also relies on the fact that the probe and disconnect routines are
+    protected by the device mutex, so the initial test of rio->present
+    needs no extra locking.
+    
+    Reported-by: syzbot+7bbcbe9c9ff0cd49592a@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    Fixes: d710734b0677 ("USB: rio500: simplify locking")
+    Acked-by: Oliver Neukum 
+    CC: 
+    
+    Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.1908081329240.1319-100000@iolanthe.rowland.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c
+index 27e9c78a791e..30cae5e1954d 100644
+--- a/drivers/usb/misc/rio500.c
++++ b/drivers/usb/misc/rio500.c
+@@ -454,51 +454,55 @@ static int probe_rio(struct usb_interface *intf,
+ {
+ 	struct usb_device *dev = interface_to_usbdev(intf);
+ 	struct rio_usb_data *rio = &rio_instance;
+-	int retval = 0;
++	int retval = -ENOMEM;
++	char *ibuf, *obuf;
+ 
+-	mutex_lock(&rio500_mutex);
+ 	if (rio->present) {
+ 		dev_info(&intf->dev, "Second USB Rio at address %d refused\n", dev->devnum);
+-		retval = -EBUSY;
+-		goto bail_out;
+-	} else {
+-		dev_info(&intf->dev, "USB Rio found at address %d\n", dev->devnum);
+-	}
+-
+-	retval = usb_register_dev(intf, &usb_rio_class);
+-	if (retval) {
+-		dev_err(&dev->dev,
+-			"Not able to get a minor for this device.\n");
+-		retval = -ENOMEM;
+-		goto bail_out;
++		return -EBUSY;
+ 	}
++	dev_info(&intf->dev, "USB Rio found at address %d\n", dev->devnum);
+ 
+-	rio->rio_dev = dev;
+-
+-	if (!(rio->obuf = kmalloc(OBUF_SIZE, GFP_KERNEL))) {
++	obuf = kmalloc(OBUF_SIZE, GFP_KERNEL);
++	if (!obuf) {
+ 		dev_err(&dev->dev,
+ 			"probe_rio: Not enough memory for the output buffer\n");
+-		usb_deregister_dev(intf, &usb_rio_class);
+-		retval = -ENOMEM;
+-		goto bail_out;
++		goto err_obuf;
+ 	}
+-	dev_dbg(&intf->dev, "obuf address:%p\n", rio->obuf);
++	dev_dbg(&intf->dev, "obuf address: %p\n", obuf);
+ 
+-	if (!(rio->ibuf = kmalloc(IBUF_SIZE, GFP_KERNEL))) {
++	ibuf = kmalloc(IBUF_SIZE, GFP_KERNEL);
++	if (!ibuf) {
+ 		dev_err(&dev->dev,
+ 			"probe_rio: Not enough memory for the input buffer\n");
+-		usb_deregister_dev(intf, &usb_rio_class);
+-		kfree(rio->obuf);
+-		retval = -ENOMEM;
+-		goto bail_out;
++		goto err_ibuf;
+ 	}
+-	dev_dbg(&intf->dev, "ibuf address:%p\n", rio->ibuf);
++	dev_dbg(&intf->dev, "ibuf address: %p\n", ibuf);
+ 
+-	usb_set_intfdata (intf, rio);
++	mutex_lock(&rio500_mutex);
++	rio->rio_dev = dev;
++	rio->ibuf = ibuf;
++	rio->obuf = obuf;
+ 	rio->present = 1;
+-bail_out:
+ 	mutex_unlock(&rio500_mutex);
+ 
++	retval = usb_register_dev(intf, &usb_rio_class);
++	if (retval) {
++		dev_err(&dev->dev,
++			"Not able to get a minor for this device.\n");
++		goto err_register;
++	}
++
++	usb_set_intfdata(intf, rio);
++	return retval;
++
++ err_register:
++	mutex_lock(&rio500_mutex);
++	rio->present = 0;
++	mutex_unlock(&rio500_mutex);
++ err_ibuf:
++	kfree(obuf);
++ err_obuf:
+ 	return retval;
+ }
+ 
+@@ -507,10 +511,10 @@ static void disconnect_rio(struct usb_interface *intf)
+ 	struct rio_usb_data *rio = usb_get_intfdata (intf);
+ 
+ 	usb_set_intfdata (intf, NULL);
+-	mutex_lock(&rio500_mutex);
+ 	if (rio) {
+ 		usb_deregister_dev(intf, &usb_rio_class);
+ 
++		mutex_lock(&rio500_mutex);
+ 		if (rio->isopen) {
+ 			rio->isopen = 0;
+ 			/* better let it finish - the release will do whats needed */
+@@ -524,8 +528,8 @@ static void disconnect_rio(struct usb_interface *intf)
+ 		dev_info(&intf->dev, "USB Rio disconnected.\n");
+ 
+ 		rio->present = 0;
++		mutex_unlock(&rio500_mutex);
+ 	}
+-	mutex_unlock(&rio500_mutex);
+ }
+ 
+ static const struct usb_device_id rio_table[] = {

commit 5f9242775bb61f390f0885f23fc16397262c7538
+Author: Alan Stern 
+Date:   Tue Aug 20 16:00:21 2019 -0400
+
+    HID: logitech: Fix general protection fault caused by Logitech driver
+    
+    The syzbot fuzzer found a general protection fault in the HID subsystem:
+    
+    kasan: CONFIG_KASAN_INLINE enabled
+    kasan: GPF could be caused by NULL-ptr deref or user memory access
+    general protection fault: 0000 [#1] SMP KASAN
+    CPU: 0 PID: 3715 Comm: syz-executor.3 Not tainted 5.2.0-rc6+ #15
+    Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
+    Google 01/01/2011
+    RIP: 0010:__pm_runtime_resume+0x49/0x180 drivers/base/power/runtime.c:1069
+    Code: ed 74 d5 fe 45 85 ed 0f 85 9a 00 00 00 e8 6f 73 d5 fe 48 8d bd c1 02
+    00 00 48 b8 00 00 00 00 00 fc ff df 48 89 fa 48 c1 ea 03 <0f> b6 04 02 48
+    89 fa 83 e2 07 38 d0 7f 08 84 c0 0f 85 fe 00 00 00
+    RSP: 0018:ffff8881d99d78e0 EFLAGS: 00010202
+    RAX: dffffc0000000000 RBX: 0000000000000020 RCX: ffffc90003f3f000
+    RDX: 0000000416d8686d RSI: ffffffff82676841 RDI: 00000020b6c3436a
+    RBP: 00000020b6c340a9 R08: ffff8881c6d64800 R09: fffffbfff0e84c25
+    R10: ffff8881d99d7940 R11: ffffffff87426127 R12: 0000000000000004
+    R13: 0000000000000000 R14: ffff8881d9b94000 R15: ffffffff897f9048
+    FS:  00007f047f542700(0000) GS:ffff8881db200000(0000) knlGS:0000000000000000
+    CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+    CR2: 0000001b30f21000 CR3: 00000001ca032000 CR4: 00000000001406f0
+    DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+    DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+    Call Trace:
+      pm_runtime_get_sync include/linux/pm_runtime.h:226 [inline]
+      usb_autopm_get_interface+0x1b/0x50 drivers/usb/core/driver.c:1707
+      usbhid_power+0x7c/0xe0 drivers/hid/usbhid/hid-core.c:1234
+      hid_hw_power include/linux/hid.h:1038 [inline]
+      hidraw_open+0x20d/0x740 drivers/hid/hidraw.c:282
+      chrdev_open+0x219/0x5c0 fs/char_dev.c:413
+      do_dentry_open+0x497/0x1040 fs/open.c:778
+      do_last fs/namei.c:3416 [inline]
+      path_openat+0x1430/0x3ff0 fs/namei.c:3533
+      do_filp_open+0x1a1/0x280 fs/namei.c:3563
+      do_sys_open+0x3c0/0x580 fs/open.c:1070
+      do_syscall_64+0xb7/0x560 arch/x86/entry/common.c:301
+      entry_SYSCALL_64_after_hwframe+0x49/0xbe
+    
+    It turns out the fault was caused by a bug in the HID Logitech driver,
+    which violates the requirement that every pathway calling
+    hid_hw_start() must also call hid_hw_stop().  This patch fixes the bug
+    by making sure the requirement is met.
+    
+    Reported-and-tested-by: syzbot+3cbe5cd105d2ad56a1df@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    CC: 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
+index 5008a3dc28f4..0dc7cdfc56f7 100644
+--- a/drivers/hid/hid-lg.c
++++ b/drivers/hid/hid-lg.c
+@@ -818,7 +818,7 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
+ 
+ 		if (!buf) {
+ 			ret = -ENOMEM;
+-			goto err_free;
++			goto err_stop;
+ 		}
+ 
+ 		ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(cbuf),
+@@ -850,9 +850,12 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
+ 		ret = lg4ff_init(hdev);
+ 
+ 	if (ret)
+-		goto err_free;
++		goto err_stop;
+ 
+ 	return 0;
++
++err_stop:
++	hid_hw_stop(hdev);
+ err_free:
+ 	kfree(drv_data);
+ 	return ret;
+@@ -863,8 +866,7 @@ static void lg_remove(struct hid_device *hdev)
+ 	struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
+ 	if (drv_data->quirks & LG_FF4)
+ 		lg4ff_deinit(hdev);
+-	else
+-		hid_hw_stop(hdev);
++	hid_hw_stop(hdev);
+ 	kfree(drv_data);
+ }
+ 
+diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
+index cefba038520c..03f0220062ca 100644
+--- a/drivers/hid/hid-lg4ff.c
++++ b/drivers/hid/hid-lg4ff.c
+@@ -1477,7 +1477,6 @@ int lg4ff_deinit(struct hid_device *hid)
+ 		}
+ 	}
+ #endif
+-	hid_hw_stop(hid);
+ 	drv_data->device_props = NULL;
+ 
+ 	kfree(entry);

commit 416dacb819f59180e4d86a5550052033ebb6d72c
+Author: Alan Stern 
+Date:   Wed Aug 21 13:27:12 2019 -0400
+
+    HID: hidraw: Fix invalid read in hidraw_ioctl
+    
+    The syzbot fuzzer has reported a pair of problems in the
+    hidraw_ioctl() function: slab-out-of-bounds read and use-after-free
+    read.  An example of the first:
+    
+    BUG: KASAN: slab-out-of-bounds in strlen+0x79/0x90 lib/string.c:525
+    Read of size 1 at addr ffff8881c8035f38 by task syz-executor.4/2833
+    
+    CPU: 1 PID: 2833 Comm: syz-executor.4 Not tainted 5.3.0-rc2+ #1
+    Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
+    Google 01/01/2011
+    Call Trace:
+      __dump_stack lib/dump_stack.c:77 [inline]
+      dump_stack+0xca/0x13e lib/dump_stack.c:113
+      print_address_description+0x6a/0x32c mm/kasan/report.c:351
+      __kasan_report.cold+0x1a/0x33 mm/kasan/report.c:482
+      kasan_report+0xe/0x12 mm/kasan/common.c:612
+      strlen+0x79/0x90 lib/string.c:525
+      strlen include/linux/string.h:281 [inline]
+      hidraw_ioctl+0x245/0xae0 drivers/hid/hidraw.c:446
+      vfs_ioctl fs/ioctl.c:46 [inline]
+      file_ioctl fs/ioctl.c:509 [inline]
+      do_vfs_ioctl+0xd2d/0x1330 fs/ioctl.c:696
+      ksys_ioctl+0x9b/0xc0 fs/ioctl.c:713
+      __do_sys_ioctl fs/ioctl.c:720 [inline]
+      __se_sys_ioctl fs/ioctl.c:718 [inline]
+      __x64_sys_ioctl+0x6f/0xb0 fs/ioctl.c:718
+      do_syscall_64+0xb7/0x580 arch/x86/entry/common.c:296
+      entry_SYSCALL_64_after_hwframe+0x49/0xbe
+    RIP: 0033:0x459829
+    Code: fd b7 fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48 89 f7
+    48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff
+    ff 0f 83 cb b7 fb ff c3 66 2e 0f 1f 84 00 00 00 00
+    RSP: 002b:00007f7a68f6dc78 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
+    RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 0000000000459829
+    RDX: 0000000000000000 RSI: 0000000080404805 RDI: 0000000000000004
+    RBP: 000000000075bf20 R08: 0000000000000000 R09: 0000000000000000
+    R10: 0000000000000000 R11: 0000000000000246 R12: 00007f7a68f6e6d4
+    R13: 00000000004c21de R14: 00000000004d5620 R15: 00000000ffffffff
+    
+    The two problems have the same cause: hidraw_ioctl() fails to test
+    whether the device has been removed.  This patch adds the missing test.
+    
+    Reported-and-tested-by: syzbot+5a6c4ec678a0c6ee84ba@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    CC: 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
+index 006bd6f4f653..62ef47a730b0 100644
+--- a/drivers/hid/hidraw.c
++++ b/drivers/hid/hidraw.c
+@@ -370,7 +370,7 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
+ 
+ 	mutex_lock(&minors_lock);
+ 	dev = hidraw_table[minor];
+-	if (!dev) {
++	if (!dev || !dev->exist) {
+ 		ret = -ENODEV;
+ 		goto out;
+ 	}

commit 4ed3350539aa931f58c939fcd803c7510584e143
+Author: Alan Stern 
+Date:   Tue Aug 13 16:15:38 2019 -0400
+
+    USB: usbfs: Add a capability flag for runtime suspend
+    
+    The recent commit 7794f486ed0b ("usbfs: Add ioctls for runtime power
+    management") neglected to add a corresponding capability flag.  This
+    patch rectifies the omission.
+    
+    Signed-off-by: Alan Stern 
+    CC: Mayuresh Kulkarni 
+    
+    Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.1908131613490.1941-100000@iolanthe.rowland.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 5db7b6dbcb44..24d4a801ca64 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -44,6 +44,12 @@
+ 
+ #include "usb.h"
+ 
++#ifdef CONFIG_PM
++#define MAYBE_CAP_SUSPEND	USBDEVFS_CAP_SUSPEND
++#else
++#define MAYBE_CAP_SUSPEND	0
++#endif
++
+ #define USB_MAXBUS			64
+ #define USB_DEVICE_MAX			(USB_MAXBUS * 128)
+ #define USB_SG_SIZE			16384 /* split-size for large txs */
+@@ -2310,7 +2316,8 @@ static int proc_get_capabilities(struct usb_dev_state *ps, void __user *arg)
+ 
+ 	caps = USBDEVFS_CAP_ZERO_PACKET | USBDEVFS_CAP_NO_PACKET_SIZE_LIM |
+ 			USBDEVFS_CAP_REAP_AFTER_DISCONNECT | USBDEVFS_CAP_MMAP |
+-			USBDEVFS_CAP_DROP_PRIVILEGES | USBDEVFS_CAP_CONNINFO_EX;
++			USBDEVFS_CAP_DROP_PRIVILEGES |
++			USBDEVFS_CAP_CONNINFO_EX | MAYBE_CAP_SUSPEND;
+ 	if (!ps->dev->bus->no_stop_on_short)
+ 		caps |= USBDEVFS_CAP_BULK_CONTINUATION;
+ 	if (ps->dev->bus->sg_tablesize)
+diff --git a/include/uapi/linux/usbdevice_fs.h b/include/uapi/linux/usbdevice_fs.h
+index d24bbb6d3ca1..cf525cddeb94 100644
+--- a/include/uapi/linux/usbdevice_fs.h
++++ b/include/uapi/linux/usbdevice_fs.h
+@@ -158,6 +158,7 @@ struct usbdevfs_hub_portinfo {
+ #define USBDEVFS_CAP_MMAP			0x20
+ #define USBDEVFS_CAP_DROP_PRIVILEGES		0x40
+ #define USBDEVFS_CAP_CONNINFO_EX		0x80
++#define USBDEVFS_CAP_SUSPEND			0x100
+ 
+ /* USBDEVFS_DISCONNECT_CLAIM flags & struct */
+ 

commit 303911cfc5b95d33687d9046133ff184cf5043ff
+Author: Alan Stern 
+Date:   Mon Aug 12 16:11:07 2019 -0400
+
+    USB: core: Fix races in character device registration and deregistraion
+    
+    The syzbot fuzzer has found two (!) races in the USB character device
+    registration and deregistration routines.  This patch fixes the races.
+    
+    The first race results from the fact that usb_deregister_dev() sets
+    usb_minors[intf->minor] to NULL before calling device_destroy() on the
+    class device.  This leaves a window during which another thread can
+    allocate the same minor number but will encounter a duplicate name
+    error when it tries to register its own class device.  A typical error
+    message in the system log would look like:
+    
+        sysfs: cannot create duplicate filename '/class/usbmisc/ldusb0'
+    
+    The patch fixes this race by destroying the class device first.
+    
+    The second race is in usb_register_dev().  When that routine runs, it
+    first allocates a minor number, then drops minor_rwsem, and then
+    creates the class device.  If the device creation fails, the minor
+    number is deallocated and the whole routine returns an error.  But
+    during the time while minor_rwsem was dropped, there is a window in
+    which the minor number is allocated and so another thread can
+    successfully open the device file.  Typically this results in
+    use-after-free errors or invalid accesses when the other thread closes
+    its open file reference, because the kernel then tries to release
+    resources that were already deallocated when usb_register_dev()
+    failed.  The patch fixes this race by keeping minor_rwsem locked
+    throughout the entire routine.
+    
+    Reported-and-tested-by: syzbot+30cf45ebfe0b0c4847a1@syzkaller.appspotmail.com
+    Signed-off-by: Alan Stern 
+    CC: 
+    Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.1908121607590.1659-100000@iolanthe.rowland.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
+index 65de6f73b672..558890ada0e5 100644
+--- a/drivers/usb/core/file.c
++++ b/drivers/usb/core/file.c
+@@ -193,9 +193,10 @@ int usb_register_dev(struct usb_interface *intf,
+ 		intf->minor = minor;
+ 		break;
+ 	}
+-	up_write(&minor_rwsem);
+-	if (intf->minor < 0)
++	if (intf->minor < 0) {
++		up_write(&minor_rwsem);
+ 		return -EXFULL;
++	}
+ 
+ 	/* create a usb class device for this usb interface */
+ 	snprintf(name, sizeof(name), class_driver->name, minor - minor_base);
+@@ -203,12 +204,11 @@ int usb_register_dev(struct usb_interface *intf,
+ 				      MKDEV(USB_MAJOR, minor), class_driver,
+ 				      "%s", kbasename(name));
+ 	if (IS_ERR(intf->usb_dev)) {
+-		down_write(&minor_rwsem);
+ 		usb_minors[minor] = NULL;
+ 		intf->minor = -1;
+-		up_write(&minor_rwsem);
+ 		retval = PTR_ERR(intf->usb_dev);
+ 	}
++	up_write(&minor_rwsem);
+ 	return retval;
+ }
+ EXPORT_SYMBOL_GPL(usb_register_dev);
+@@ -234,12 +234,12 @@ void usb_deregister_dev(struct usb_interface *intf,
+ 		return;
+ 
+ 	dev_dbg(&intf->dev, "removing %d minor\n", intf->minor);
++	device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor));
+ 
+ 	down_write(&minor_rwsem);
+ 	usb_minors[intf->minor] = NULL;
+ 	up_write(&minor_rwsem);
+ 
+-	device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor));
+ 	intf->usb_dev = NULL;
+ 	intf->minor = -1;
+ 	destroy_usb_class();

commit 7794f486ed0b1fa8022dd0a27b9babf86a46d1cf
+Author: Alan Stern 
+Date:   Wed Aug 7 10:29:50 2019 -0400
+
+    usbfs: Add ioctls for runtime power management
+    
+    It has been requested that usbfs should implement runtime power
+    management, instead of forcing the device to remain at full power as
+    long as the device file is open.  This patch introduces that new
+    feature.
+    
+    It does so by adding three new usbfs ioctls:
+    
+            USBDEVFS_FORBID_SUSPEND: Prevents the device from going into
+            runtime suspend (and causes a resume if the device is already
+            suspended).
+    
+            USBDEVFS_ALLOW_SUSPEND: Allows the device to go into runtime
+            suspend.  Some time may elapse before the device actually is
+            suspended, depending on things like the autosuspend delay.
+    
+            USBDEVFS_WAIT_FOR_RESUME: Blocks until the call is interrupted
+            by a signal or at least one runtime resume has occurred since
+            the most recent ALLOW_SUSPEND ioctl call (which may mean
+            immediately, even if the device is currently suspended).  In
+            the latter case, the device is prevented from suspending again
+            just as if FORBID_SUSPEND was called before the ioctl returns.
+    
+    For backward compatibility, when the device file is first opened
+    runtime suspends are forbidden.  The userspace program can then allow
+    suspends whenever it wants, and either resume the device directly (by
+    forbidding suspends again) or wait for a resume from some other source
+    (such as a remote wakeup).  URBs submitted to a suspended device will
+    fail or will complete with an appropriate error code.
+    
+    This combination of ioctls is sufficient for user programs to have
+    nearly the same degree of control over a device's runtime power
+    behavior as kernel drivers do.
+    
+    Still lacking is documentation for the new ioctls.  I intend to add it
+    later, after the existing documentation for the usbfs userspace API is
+    straightened out into a reasonable form.
+    
+    Suggested-by: Mayuresh Kulkarni 
+    Signed-off-by: Alan Stern 
+    
+    Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.1908071013220.1514-100000@iolanthe.rowland.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index b265ab5405f9..cdd34dcb2395 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -48,6 +48,9 @@
+ #define USB_DEVICE_MAX			(USB_MAXBUS * 128)
+ #define USB_SG_SIZE			16384 /* split-size for large txs */
+ 
++/* Mutual exclusion for ps->list in resume vs. release and remove */
++static DEFINE_MUTEX(usbfs_mutex);
++
+ struct usb_dev_state {
+ 	struct list_head list;      /* state list */
+ 	struct usb_device *dev;
+@@ -57,14 +60,17 @@ struct usb_dev_state {
+ 	struct list_head async_completed;
+ 	struct list_head memory_list;
+ 	wait_queue_head_t wait;     /* wake up if a request completed */
++	wait_queue_head_t wait_for_resume;   /* wake up upon runtime resume */
+ 	unsigned int discsignr;
+ 	struct pid *disc_pid;
+ 	const struct cred *cred;
+ 	sigval_t disccontext;
+ 	unsigned long ifclaimed;
+ 	u32 disabled_bulk_eps;
+-	bool privileges_dropped;
+ 	unsigned long interface_allowed_mask;
++	int not_yet_resumed;
++	bool suspend_allowed;
++	bool privileges_dropped;
+ };
+ 
+ struct usb_memory {
+@@ -694,9 +700,7 @@ static void driver_disconnect(struct usb_interface *intf)
+ 	destroy_async_on_interface(ps, ifnum);
+ }
+ 
+-/* The following routines are merely placeholders.  There is no way
+- * to inform a user task about suspend or resumes.
+- */
++/* We don't care about suspend/resume of claimed interfaces */
+ static int driver_suspend(struct usb_interface *intf, pm_message_t msg)
+ {
+ 	return 0;
+@@ -707,12 +711,32 @@ static int driver_resume(struct usb_interface *intf)
+ 	return 0;
+ }
+ 
++/* The following routines apply to the entire device, not interfaces */
++void usbfs_notify_suspend(struct usb_device *udev)
++{
++	/* We don't need to handle this */
++}
++
++void usbfs_notify_resume(struct usb_device *udev)
++{
++	struct usb_dev_state *ps;
++
++	/* Protect against simultaneous remove or release */
++	mutex_lock(&usbfs_mutex);
++	list_for_each_entry(ps, &udev->filelist, list) {
++		WRITE_ONCE(ps->not_yet_resumed, 0);
++		wake_up_all(&ps->wait_for_resume);
++	}
++	mutex_unlock(&usbfs_mutex);
++}
++
+ struct usb_driver usbfs_driver = {
+ 	.name =		"usbfs",
+ 	.probe =	driver_probe,
+ 	.disconnect =	driver_disconnect,
+ 	.suspend =	driver_suspend,
+ 	.resume =	driver_resume,
++	.supports_autosuspend = 1,
+ };
+ 
+ static int claimintf(struct usb_dev_state *ps, unsigned int ifnum)
+@@ -997,9 +1021,12 @@ static int usbdev_open(struct inode *inode, struct file *file)
+ 	INIT_LIST_HEAD(&ps->async_completed);
+ 	INIT_LIST_HEAD(&ps->memory_list);
+ 	init_waitqueue_head(&ps->wait);
++	init_waitqueue_head(&ps->wait_for_resume);
+ 	ps->disc_pid = get_pid(task_pid(current));
+ 	ps->cred = get_current_cred();
+ 	smp_wmb();
++
++	/* Can't race with resume; the device is already active */
+ 	list_add_tail(&ps->list, &dev->filelist);
+ 	file->private_data = ps;
+ 	usb_unlock_device(dev);
+@@ -1025,7 +1052,10 @@ static int usbdev_release(struct inode *inode, struct file *file)
+ 	usb_lock_device(dev);
+ 	usb_hub_release_all_ports(dev, ps);
+ 
++	/* Protect against simultaneous resume */
++	mutex_lock(&usbfs_mutex);
+ 	list_del_init(&ps->list);
++	mutex_unlock(&usbfs_mutex);
+ 
+ 	for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed);
+ 			ifnum++) {
+@@ -1033,7 +1063,8 @@ static int usbdev_release(struct inode *inode, struct file *file)
+ 			releaseintf(ps, ifnum);
+ 	}
+ 	destroy_all_async(ps);
+-	usb_autosuspend_device(dev);
++	if (!ps->suspend_allowed)
++		usb_autosuspend_device(dev);
+ 	usb_unlock_device(dev);
+ 	usb_put_dev(dev);
+ 	put_pid(ps->disc_pid);
+@@ -2384,6 +2415,47 @@ static int proc_drop_privileges(struct usb_dev_state *ps, void __user *arg)
+ 	return 0;
+ }
+ 
++static int proc_forbid_suspend(struct usb_dev_state *ps)
++{
++	int ret = 0;
++
++	if (ps->suspend_allowed) {
++		ret = usb_autoresume_device(ps->dev);
++		if (ret == 0)
++			ps->suspend_allowed = false;
++		else if (ret != -ENODEV)
++			ret = -EIO;
++	}
++	return ret;
++}
++
++static int proc_allow_suspend(struct usb_dev_state *ps)
++{
++	if (!connected(ps))
++		return -ENODEV;
++
++	WRITE_ONCE(ps->not_yet_resumed, 1);
++	if (!ps->suspend_allowed) {
++		usb_autosuspend_device(ps->dev);
++		ps->suspend_allowed = true;
++	}
++	return 0;
++}
++
++static int proc_wait_for_resume(struct usb_dev_state *ps)
++{
++	int ret;
++
++	usb_unlock_device(ps->dev);
++	ret = wait_event_interruptible(ps->wait_for_resume,
++			READ_ONCE(ps->not_yet_resumed) == 0);
++	usb_lock_device(ps->dev);
++
++	if (ret != 0)
++		return -EINTR;
++	return proc_forbid_suspend(ps);
++}
++
+ /*
+  * NOTE:  All requests here that have interface numbers as parameters
+  * are assuming that somehow the configuration has been prevented from
+@@ -2578,6 +2650,15 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
+ 	case USBDEVFS_GET_SPEED:
+ 		ret = ps->dev->speed;
+ 		break;
++	case USBDEVFS_FORBID_SUSPEND:
++		ret = proc_forbid_suspend(ps);
++		break;
++	case USBDEVFS_ALLOW_SUSPEND:
++		ret = proc_allow_suspend(ps);
++		break;
++	case USBDEVFS_WAIT_FOR_RESUME:
++		ret = proc_wait_for_resume(ps);
++		break;
+ 	}
+ 
+ 	/* Handle variable-length commands */
+@@ -2651,15 +2732,20 @@ static void usbdev_remove(struct usb_device *udev)
+ {
+ 	struct usb_dev_state *ps;
+ 
++	/* Protect against simultaneous resume */
++	mutex_lock(&usbfs_mutex);
+ 	while (!list_empty(&udev->filelist)) {
+ 		ps = list_entry(udev->filelist.next, struct usb_dev_state, list);
+ 		destroy_all_async(ps);
+ 		wake_up_all(&ps->wait);
++		WRITE_ONCE(ps->not_yet_resumed, 0);
++		wake_up_all(&ps->wait_for_resume);
+ 		list_del_init(&ps->list);
+ 		if (ps->discsignr)
+ 			kill_pid_usb_asyncio(ps->discsignr, EPIPE, ps->disccontext,
+ 					     ps->disc_pid, ps->cred);
+ 	}
++	mutex_unlock(&usbfs_mutex);
+ }
+ 
+ static int usbdev_notify(struct notifier_block *self,
+diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
+index 1ac9c1e5f773..38f8b3e31762 100644
+--- a/drivers/usb/core/generic.c
++++ b/drivers/usb/core/generic.c
+@@ -257,6 +257,8 @@ static int generic_suspend(struct usb_device *udev, pm_message_t msg)
+ 	else
+ 		rc = usb_port_suspend(udev, msg);
+ 
++	if (rc == 0)
++		usbfs_notify_suspend(udev);
+ 	return rc;
+ }
+ 
+@@ -273,6 +275,9 @@ static int generic_resume(struct usb_device *udev, pm_message_t msg)
+ 		rc = hcd_bus_resume(udev, msg);
+ 	else
+ 		rc = usb_port_resume(udev, msg);
++
++	if (rc == 0)
++		usbfs_notify_resume(udev);
+ 	return rc;
+ }
+ 
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index bd8d01f85a13..2932d1ec5def 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -95,6 +95,9 @@ extern int usb_runtime_idle(struct device *dev);
+ extern int usb_enable_usb2_hardware_lpm(struct usb_device *udev);
+ extern int usb_disable_usb2_hardware_lpm(struct usb_device *udev);
+ 
++extern void usbfs_notify_suspend(struct usb_device *udev);
++extern void usbfs_notify_resume(struct usb_device *udev);
++
+ #else
+ 
+ static inline int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+diff --git a/include/uapi/linux/usbdevice_fs.h b/include/uapi/linux/usbdevice_fs.h
+index 78efe870c2b7..d24bbb6d3ca1 100644
+--- a/include/uapi/linux/usbdevice_fs.h
++++ b/include/uapi/linux/usbdevice_fs.h
+@@ -223,5 +223,8 @@ struct usbdevfs_streams {
+  * extending size of the data returned.
+  */
+ #define USBDEVFS_CONNINFO_EX(len)  _IOC(_IOC_READ, 'U', 32, len)
++#define USBDEVFS_FORBID_SUSPEND    _IO('U', 33)
++#define USBDEVFS_ALLOW_SUSPEND     _IO('U', 34)
++#define USBDEVFS_WAIT_FOR_RESUME   _IO('U', 35)
+ 
+ #endif /* _UAPI_LINUX_USBDEVICE_FS_H */

commit 257adc0fbe9f0a26695f4d68bdbf2886f5a3ecd0
+Author: Alan Stern 
+Date:   Tue Jun 25 16:00:26 2019 -0400
+
+    USB: core: Fix compiler warnings in devio.c
+    
+    In the current kernel, devio.c generates a number of compiler warnings
+    about taking the address of a member of a packed structure.  The
+    warnings all look like this one:
+    
+            drivers/usb/core/devio.c: In function ‘proc_do_submiturb’:
+            drivers/usb/core/devio.c:1489:43: warning: taking address of packed member of ‘struct usb_ctrlrequest’ may result in an unaligned pointer value [-Waddress-of-packed-member]
+             1489 |   if (uurb->buffer_length < (le16_to_cpup(&dr->wLength) + 8)) {
+                  |                                           ^~~~~~~~~~~~
+    
+    These warnings can easily be eliminated by changing various
+    le16_to_cpup() calls to use le16_to_cpu() instead.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 0100a54165cd..a951ce69f10e 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -1510,15 +1510,15 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
+ 			ret = -EFAULT;
+ 			goto error;
+ 		}
+-		if (uurb->buffer_length < (le16_to_cpup(&dr->wLength) + 8)) {
++		if (uurb->buffer_length < (le16_to_cpu(dr->wLength) + 8)) {
+ 			ret = -EINVAL;
+ 			goto error;
+ 		}
+ 		ret = check_ctrlrecip(ps, dr->bRequestType, dr->bRequest,
+-				      le16_to_cpup(&dr->wIndex));
++				      le16_to_cpu(dr->wIndex));
+ 		if (ret)
+ 			goto error;
+-		uurb->buffer_length = le16_to_cpup(&dr->wLength);
++		uurb->buffer_length = le16_to_cpu(dr->wLength);
+ 		uurb->buffer += 8;
+ 		if ((dr->bRequestType & USB_DIR_IN) && uurb->buffer_length) {
+ 			is_in = 1;
+@@ -1533,9 +1533,9 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
+ 			"bRequest=%02x wValue=%04x "
+ 			"wIndex=%04x wLength=%04x\n",
+ 			dr->bRequestType, dr->bRequest,
+-			__le16_to_cpup(&dr->wValue),
+-			__le16_to_cpup(&dr->wIndex),
+-			__le16_to_cpup(&dr->wLength));
++			__le16_to_cpu(dr->wValue),
++			__le16_to_cpu(dr->wIndex),
++			__le16_to_cpu(dr->wLength));
+ 		u = sizeof(struct usb_ctrlrequest);
+ 		break;
+ 

commit ffed60971f3d95923b99ea970862c6ab6a22c20f
+Author: Alan Stern 
+Date:   Tue Jun 25 16:03:58 2019 -0400
+
+    USB: core: Remove usbfs_mutex
+    
+    Commit 4a2a8a2cce86 ("usbfs: private mutex for open, release, and
+    remove") is now obsolete.  The commit was created back when we had
+    to handle both usbfs device nodes and the old usbdevfs filesystem
+    (/proc/bus/usb/), but usbdevfs no longer exists.
+    
+    This means there's no longer any need to hold a mutex during two
+    separate removal operations (and thus during an entire notifier chain
+    call).  Furthermore, the one remaining remove/release pair doesn't
+    race with open thanks to the synchronization provided by the device
+    model core in bus_find_device().  Remove and release don't race with
+    each other because they both run with the device lock held.
+    
+    The upshot is that usbfs_mutex isn't needed any more.  This patch
+    removes it entirely.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 186790b06b11..0100a54165cd 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -48,9 +48,6 @@
+ #define USB_DEVICE_MAX			(USB_MAXBUS * 128)
+ #define USB_SG_SIZE			16384 /* split-size for large txs */
+ 
+-/* Mutual exclusion for removal, open, and release */
+-DEFINE_MUTEX(usbfs_mutex);
+-
+ struct usb_dev_state {
+ 	struct list_head list;      /* state list */
+ 	struct usb_device *dev;
+@@ -979,15 +976,9 @@ static int usbdev_open(struct inode *inode, struct file *file)
+ 
+ 	ret = -ENODEV;
+ 
+-	/* Protect against simultaneous removal or release */
+-	mutex_lock(&usbfs_mutex);
+-
+ 	/* usbdev device-node */
+ 	if (imajor(inode) == USB_DEVICE_MAJOR)
+ 		dev = usbdev_lookup_by_devt(inode->i_rdev);
+-
+-	mutex_unlock(&usbfs_mutex);
+-
+ 	if (!dev)
+ 		goto out_free_ps;
+ 
+diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c
+index ab474b11523e..e6143663778f 100644
+--- a/drivers/usb/core/notify.c
++++ b/drivers/usb/core/notify.c
+@@ -53,11 +53,8 @@ void usb_notify_add_device(struct usb_device *udev)
+ 
+ void usb_notify_remove_device(struct usb_device *udev)
+ {
+-	/* Protect against simultaneous usbfs open */
+-	mutex_lock(&usbfs_mutex);
+ 	blocking_notifier_call_chain(&usb_notifier_list,
+ 			USB_DEVICE_REMOVE, udev);
+-	mutex_unlock(&usbfs_mutex);
+ }
+ 
+ void usb_notify_add_bus(struct usb_bus *ubus)
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index d95a5358f73d..bd8d01f85a13 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -169,7 +169,6 @@ extern const struct attribute_group *usb_device_groups[];
+ extern const struct attribute_group *usb_interface_groups[];
+ 
+ /* usbfs stuff */
+-extern struct mutex usbfs_mutex;
+ extern struct usb_driver usbfs_driver;
+ extern const struct file_operations usbfs_devices_fops;
+ extern const struct file_operations usbdev_file_operations;

commit 6e41e2257f1094acc37618bf6c856115374c6922
+Author: Alan Stern 
+Date:   Mon May 20 10:44:21 2019 -0400
+
+    p54usb: Fix race between disconnect and firmware loading
+    
+    The syzbot fuzzer found a bug in the p54 USB wireless driver.  The
+    issue involves a race between disconnect and the firmware-loader
+    callback routine, and it has several aspects.
+    
+    One big problem is that when the firmware can't be loaded, the
+    callback routine tries to unbind the driver from the USB _device_ (by
+    calling device_release_driver) instead of from the USB _interface_ to
+    which it is actually bound (by calling usb_driver_release_interface).
+    
+    The race involves access to the private data structure.  The driver's
+    disconnect handler waits for a completion that is signalled by the
+    firmware-loader callback routine.  As soon as the completion is
+    signalled, you have to assume that the private data structure may have
+    been deallocated by the disconnect handler -- even if the firmware was
+    loaded without errors.  However, the callback routine does access the
+    private data several times after that point.
+    
+    Another problem is that, in order to ensure that the USB device
+    structure hasn't been freed when the callback routine runs, the driver
+    takes a reference to it.  This isn't good enough any more, because now
+    that the callback routine calls usb_driver_release_interface, it has
+    to ensure that the interface structure hasn't been freed.
+    
+    Finally, the driver takes an unnecessary reference to the USB device
+    structure in the probe function and drops the reference in the
+    disconnect handler.  This extra reference doesn't accomplish anything,
+    because the USB core already guarantees that a device structure won't
+    be deallocated while a driver is still bound to any of its interfaces.
+    
+    To fix these problems, this patch makes the following changes:
+    
+            Call usb_driver_release_interface() rather than
+            device_release_driver().
+    
+            Don't signal the completion until after the important
+            information has been copied out of the private data structure,
+            and don't refer to the private data at all thereafter.
+    
+            Lock udev (the interface's parent) before unbinding the driver
+            instead of locking udev->parent.
+    
+            During the firmware loading process, take a reference to the
+            USB interface instead of the USB device.
+    
+            Don't take an unnecessary reference to the device during probe
+            (and then don't drop it during disconnect).
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: syzbot+200d4bb11b23d929335f@syzkaller.appspotmail.com
+    CC: 
+    Acked-by: Christian Lamparter 
+    Signed-off-by: Kalle Valo 
+
+diff --git a/drivers/net/wireless/intersil/p54/p54usb.c b/drivers/net/wireless/intersil/p54/p54usb.c
+index b0b86f701061..15661da6eedc 100644
+--- a/drivers/net/wireless/intersil/p54/p54usb.c
++++ b/drivers/net/wireless/intersil/p54/p54usb.c
+@@ -33,6 +33,8 @@ MODULE_ALIAS("prism54usb");
+ MODULE_FIRMWARE("isl3886usb");
+ MODULE_FIRMWARE("isl3887usb");
+ 
++static struct usb_driver p54u_driver;
++
+ /*
+  * Note:
+  *
+@@ -921,9 +923,9 @@ static void p54u_load_firmware_cb(const struct firmware *firmware,
+ {
+ 	struct p54u_priv *priv = context;
+ 	struct usb_device *udev = priv->udev;
++	struct usb_interface *intf = priv->intf;
+ 	int err;
+ 
+-	complete(&priv->fw_wait_load);
+ 	if (firmware) {
+ 		priv->fw = firmware;
+ 		err = p54u_start_ops(priv);
+@@ -932,26 +934,22 @@ static void p54u_load_firmware_cb(const struct firmware *firmware,
+ 		dev_err(&udev->dev, "Firmware not found.\n");
+ 	}
+ 
+-	if (err) {
+-		struct device *parent = priv->udev->dev.parent;
+-
+-		dev_err(&udev->dev, "failed to initialize device (%d)\n", err);
+-
+-		if (parent)
+-			device_lock(parent);
++	complete(&priv->fw_wait_load);
++	/*
++	 * At this point p54u_disconnect may have already freed
++	 * the "priv" context. Do not use it anymore!
++	 */
++	priv = NULL;
+ 
+-		device_release_driver(&udev->dev);
+-		/*
+-		 * At this point p54u_disconnect has already freed
+-		 * the "priv" context. Do not use it anymore!
+-		 */
+-		priv = NULL;
++	if (err) {
++		dev_err(&intf->dev, "failed to initialize device (%d)\n", err);
+ 
+-		if (parent)
+-			device_unlock(parent);
++		usb_lock_device(udev);
++		usb_driver_release_interface(&p54u_driver, intf);
++		usb_unlock_device(udev);
+ 	}
+ 
+-	usb_put_dev(udev);
++	usb_put_intf(intf);
+ }
+ 
+ static int p54u_load_firmware(struct ieee80211_hw *dev,
+@@ -972,14 +970,14 @@ static int p54u_load_firmware(struct ieee80211_hw *dev,
+ 	dev_info(&priv->udev->dev, "Loading firmware file %s\n",
+ 	       p54u_fwlist[i].fw);
+ 
+-	usb_get_dev(udev);
++	usb_get_intf(intf);
+ 	err = request_firmware_nowait(THIS_MODULE, 1, p54u_fwlist[i].fw,
+ 				      device, GFP_KERNEL, priv,
+ 				      p54u_load_firmware_cb);
+ 	if (err) {
+ 		dev_err(&priv->udev->dev, "(p54usb) cannot load firmware %s "
+ 					  "(%d)!\n", p54u_fwlist[i].fw, err);
+-		usb_put_dev(udev);
++		usb_put_intf(intf);
+ 	}
+ 
+ 	return err;
+@@ -1011,8 +1009,6 @@ static int p54u_probe(struct usb_interface *intf,
+ 	skb_queue_head_init(&priv->rx_queue);
+ 	init_usb_anchor(&priv->submitted);
+ 
+-	usb_get_dev(udev);
+-
+ 	/* really lazy and simple way of figuring out if we're a 3887 */
+ 	/* TODO: should just stick the identification in the device table */
+ 	i = intf->altsetting->desc.bNumEndpoints;
+@@ -1053,10 +1049,8 @@ static int p54u_probe(struct usb_interface *intf,
+ 		priv->upload_fw = p54u_upload_firmware_net2280;
+ 	}
+ 	err = p54u_load_firmware(dev, intf);
+-	if (err) {
+-		usb_put_dev(udev);
++	if (err)
+ 		p54_free_common(dev);
+-	}
+ 	return err;
+ }
+ 
+@@ -1072,7 +1066,6 @@ static void p54u_disconnect(struct usb_interface *intf)
+ 	wait_for_completion(&priv->fw_wait_load);
+ 	p54_unregister_common(dev);
+ 
+-	usb_put_dev(interface_to_usbdev(intf));
+ 	release_firmware(priv->fw);
+ 	p54_free_common(dev);
+ }

commit 4289ee7d5a8343eaddd0986f8fb492868e2f546f
+Author: Alan Stern 
+Date:   Thu Jun 20 11:55:58 2019 -0400
+
+    tools/memory-model: Improve data-race detection
+    
+    Herbert Xu recently reported a problem concerning RCU and compiler
+    barriers.  In the course of discussing the problem, he put forth a
+    litmus test which illustrated a serious defect in the Linux Kernel
+    Memory Model's data-race-detection code [1].
+    
+    The defect was that the LKMM assumed visibility and executes-before
+    ordering of plain accesses had to be mediated by marked accesses.  In
+    Herbert's litmus test this wasn't so, and the LKMM claimed the litmus
+    test was allowed and contained a data race although neither is true.
+    
+    In fact, plain accesses can be ordered by fences even in the absence
+    of marked accesses.  In most cases this doesn't matter, because most
+    fences only order accesses within a single thread.  But the rcu-fence
+    relation is different; it can order (and induce visibility between)
+    accesses in different threads -- events which otherwise might be
+    concurrent.  This makes it relevant to data-race detection.
+    
+    This patch makes two changes to the memory model to incorporate the
+    new insight:
+    
+            If a store is separated by a fence from another access,
+            the store is necessarily visible to the other access (as
+            reflected in the ww-vis and wr-vis relations).  Similarly,
+            if a load is separated by a fence from another access then
+            the load necessarily executes before the other access (as
+            reflected in the rw-xbstar relation).
+    
+            If a store is separated by a strong fence from a marked access
+            then it is necessarily visible to any access that executes
+            after the marked access (as reflected in the ww-vis and wr-vis
+            relations).
+    
+    With these changes, the LKMM gives the desired result for Herbert's
+    litmus test and other related ones [2].
+    
+    [1]     https://lore.kernel.org/lkml/Pine.LNX.4.44L0.1906041026570.1731-100000@iolanthe.rowland.org/
+    
+    [2]     https://github.com/paulmckrcu/litmus/blob/master/manual/plain/C-S-rcunoderef-1.litmus
+            https://github.com/paulmckrcu/litmus/blob/master/manual/plain/C-S-rcunoderef-2.litmus
+            https://github.com/paulmckrcu/litmus/blob/master/manual/plain/C-S-rcunoderef-3.litmus
+            https://github.com/paulmckrcu/litmus/blob/master/manual/plain/C-S-rcunoderef-4.litmus
+            https://github.com/paulmckrcu/litmus/blob/master/manual/plain/strong-vis.litmus
+    
+    Reported-by: Herbert Xu 
+    Signed-off-by: Alan Stern 
+    Acked-by: Andrea Parri 
+    Signed-off-by: Paul E. McKenney 
+    Tested-by: Akira Yokosawa 
+
+diff --git a/tools/memory-model/linux-kernel.cat b/tools/memory-model/linux-kernel.cat
+index ca2f4297b4e6..ea2ff4b94074 100644
+--- a/tools/memory-model/linux-kernel.cat
++++ b/tools/memory-model/linux-kernel.cat
+@@ -179,9 +179,11 @@ let r-post-bounded = (nonrw-fence | ([~Noreturn] ; fencerel(Rmb) ; [R4rmb]))? ;
+ 	[Marked]
+ 
+ (* Visibility and executes-before for plain accesses *)
+-let ww-vis = w-post-bounded ; vis ; w-pre-bounded
+-let wr-vis = w-post-bounded ; vis ; r-pre-bounded
+-let rw-xbstar = r-post-bounded ; xbstar ; w-pre-bounded
++let ww-vis = fence | (strong-fence ; xbstar ; w-pre-bounded) |
++	(w-post-bounded ; vis ; w-pre-bounded)
++let wr-vis = fence | (strong-fence ; xbstar ; r-pre-bounded) |
++	(w-post-bounded ; vis ; r-pre-bounded)
++let rw-xbstar = fence | (r-post-bounded ; xbstar ; w-pre-bounded)
+ 
+ (* Potential races *)
+ let pre-race = ext & ((Plain * M) | ((M \ IW) * Plain))

commit 15aa25cbf0ccc4bd63ed6f2a8065decb7f5e6f89
+Author: Alan Stern 
+Date:   Thu Jun 20 11:55:46 2019 -0400
+
+    tools/memory-model: Change definition of rcu-fence
+    
+    The rcu-fence relation in the Linux Kernel Memory Model is not well
+    named.  It doesn't act like any other fence relation, in that it does
+    not relate events before a fence to events after that fence.  All it
+    does is relate certain RCU events to one another (those that are
+    ordered by the RCU Guarantee); this induces an actual
+    strong-fence-like relation linking events preceding the first RCU
+    event to those following the second.
+    
+    This patch renames rcu-fence, now called rcu-order.  It adds a new
+    definition of rcu-fence, something which should have been present all
+    along because it is used in the rb relation.  And it modifies the
+    fence and strong-fence relations by making them incorporate the new
+    rcu-fence.
+    
+    As a result of this change, there is no longer any need to define
+    full-fence in the section for detecting data races.  It can simply be
+    replaced by the updated strong-fence relation.
+    
+    This change should have no effect on the operation of the memory model.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Andrea Parri 
+    Signed-off-by: Paul E. McKenney 
+
+diff --git a/tools/memory-model/linux-kernel.cat b/tools/memory-model/linux-kernel.cat
+index 8b61218c99fd..ca2f4297b4e6 100644
+--- a/tools/memory-model/linux-kernel.cat
++++ b/tools/memory-model/linux-kernel.cat
+@@ -122,24 +122,28 @@ let rcu-link = po? ; hb* ; pb* ; prop ; po
+ 
+ (*
+  * Any sequence containing at least as many grace periods as RCU read-side
+- * critical sections (joined by rcu-link) acts as a generalized strong fence.
++ * critical sections (joined by rcu-link) induces order like a generalized
++ * inter-CPU strong fence.
+  * Likewise for SRCU grace periods and read-side critical sections, provided
+  * the synchronize_srcu() and srcu_read_[un]lock() calls refer to the same
+  * struct srcu_struct location.
+  *)
+-let rec rcu-fence = rcu-gp | srcu-gp |
++let rec rcu-order = rcu-gp | srcu-gp |
+ 	(rcu-gp ; rcu-link ; rcu-rscsi) |
+ 	((srcu-gp ; rcu-link ; srcu-rscsi) & loc) |
+ 	(rcu-rscsi ; rcu-link ; rcu-gp) |
+ 	((srcu-rscsi ; rcu-link ; srcu-gp) & loc) |
+-	(rcu-gp ; rcu-link ; rcu-fence ; rcu-link ; rcu-rscsi) |
+-	((srcu-gp ; rcu-link ; rcu-fence ; rcu-link ; srcu-rscsi) & loc) |
+-	(rcu-rscsi ; rcu-link ; rcu-fence ; rcu-link ; rcu-gp) |
+-	((srcu-rscsi ; rcu-link ; rcu-fence ; rcu-link ; srcu-gp) & loc) |
+-	(rcu-fence ; rcu-link ; rcu-fence)
++	(rcu-gp ; rcu-link ; rcu-order ; rcu-link ; rcu-rscsi) |
++	((srcu-gp ; rcu-link ; rcu-order ; rcu-link ; srcu-rscsi) & loc) |
++	(rcu-rscsi ; rcu-link ; rcu-order ; rcu-link ; rcu-gp) |
++	((srcu-rscsi ; rcu-link ; rcu-order ; rcu-link ; srcu-gp) & loc) |
++	(rcu-order ; rcu-link ; rcu-order)
++let rcu-fence = po ; rcu-order ; po?
++let fence = fence | rcu-fence
++let strong-fence = strong-fence | rcu-fence
+ 
+ (* rb orders instructions just as pb does *)
+-let rb = prop ; po ; rcu-fence ; po? ; hb* ; pb* ; [Marked]
++let rb = prop ; rcu-fence ; hb* ; pb* ; [Marked]
+ 
+ irreflexive rb as rcu
+ 
+@@ -163,9 +167,8 @@ flag ~empty mixed-accesses as mixed-accesses
+ 
+ (* Executes-before and visibility *)
+ let xbstar = (hb | pb | rb)*
+-let full-fence = strong-fence | (po ; rcu-fence ; po?)
+ let vis = cumul-fence* ; rfe? ; [Marked] ;
+-	((full-fence ; [Marked] ; xbstar) | (xbstar & int))
++	((strong-fence ; [Marked] ; xbstar) | (xbstar & int))
+ 
+ (* Boundaries for lifetimes of plain accesses *)
+ let w-pre-bounded = [Marked] ; (addr | fence)?

commit f9de417121001879d92a86960647adb06b5b81bf
+Author: Alan Stern 
+Date:   Thu Jun 20 11:55:36 2019 -0400
+
+    tools/memory-model: Expand definition of barrier
+    
+    Commit 66be4e66a7f4 ("rcu: locking and unlocking need to always be at
+    least barriers") added compiler barriers back into rcu_read_lock() and
+    rcu_read_unlock().  Furthermore, srcu_read_lock() and
+    srcu_read_unlock() have always contained compiler barriers.
+    
+    The Linux Kernel Memory Model ought to know about these barriers.
+    This patch adds them into the memory model.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Andrea Parri 
+    Signed-off-by: Paul E. McKenney 
+
+diff --git a/tools/memory-model/linux-kernel.cat b/tools/memory-model/linux-kernel.cat
+index 36d367054811..8b61218c99fd 100644
+--- a/tools/memory-model/linux-kernel.cat
++++ b/tools/memory-model/linux-kernel.cat
+@@ -45,7 +45,8 @@ let strong-fence = mb | gp
+ let nonrw-fence = strong-fence | po-rel | acq-po
+ let fence = nonrw-fence | wmb | rmb
+ let barrier = fencerel(Barrier | Rmb | Wmb | Mb | Sync-rcu | Sync-srcu |
+-		Before-atomic | After-atomic | Acquire | Release) |
++		Before-atomic | After-atomic | Acquire | Release |
++		Rcu-lock | Rcu-unlock | Srcu-lock | Srcu-unlock) |
+ 	(po ; [Release]) | ([Acquire] ; po)
+ 
+ (**********************************)

commit 2966f8d440c3d2b6ef6c44093a9f9c42701a077a
+Author: Alan Stern 
+Date:   Fri May 3 13:13:44 2019 -0400
+
+    Documentation: atomic_t.txt: Explain ordering provided by smp_mb__{before,after}_atomic()
+    
+    The description of smp_mb__before_atomic() and smp_mb__after_atomic()
+    in Documentation/atomic_t.txt is slightly terse and misleading.  It
+    does not clearly state which other instructions are ordered by these
+    barriers.
+    
+    This improves the text to make the actual ordering implications clear,
+    and also to explain how these barriers differ from a RELEASE or
+    ACQUIRE ordering.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Jonathan Corbet 
+    Cc: Peter Zijlstra 
+    Acked-by: Andrea Parri 
+    Signed-off-by: Paul E. McKenney 
+
+diff --git a/Documentation/atomic_t.txt b/Documentation/atomic_t.txt
+index dca3fb0554db..b3afe69d03a1 100644
+--- a/Documentation/atomic_t.txt
++++ b/Documentation/atomic_t.txt
+@@ -187,8 +187,14 @@ The barriers:
+ 
+   smp_mb__{before,after}_atomic()
+ 
+-only apply to the RMW ops and can be used to augment/upgrade the ordering
+-inherent to the used atomic op. These barriers provide a full smp_mb().
++only apply to the RMW atomic ops and can be used to augment/upgrade the
++ordering inherent to the op. These barriers act almost like a full smp_mb():
++smp_mb__before_atomic() orders all earlier accesses against the RMW op
++itself and all accesses following it, and smp_mb__after_atomic() orders all
++later accesses against the RMW op and all accesses preceding it. However,
++accesses between the smp_mb__{before,after}_atomic() and the RMW op are not
++ordered, so it is advisable to place the barrier right next to the RMW atomic
++op whenever possible.
+ 
+ These helper barriers exist because architectures have varying implicit
+ ordering on their SMP atomic primitives. For example our TSO architectures
+@@ -212,7 +218,9 @@ Further, while something like:
+   atomic_dec(&X);
+ 
+ is a 'typical' RELEASE pattern, the barrier is strictly stronger than
+-a RELEASE. Similarly for something like:
++a RELEASE because it orders preceding instructions against both the read
++and write parts of the atomic_dec(), and against all following instructions
++as well. Similarly, something like:
+ 
+   atomic_inc(&X);
+   smp_mb__after_atomic();
+@@ -244,7 +252,8 @@ strictly stronger than ACQUIRE. As illustrated:
+ 
+ This should not happen; but a hypothetical atomic_inc_acquire() --
+ (void)atomic_fetch_inc_acquire() for instance -- would allow the outcome,
+-since then:
++because it would not order the W part of the RMW against the following
++WRITE_ONCE.  Thus:
+ 
+   P1			P2
+ 

commit 0031e38adf38779acce5737f4905b9f60750b674
+Author: Alan Stern 
+Date:   Mon Apr 22 12:18:09 2019 -0400
+
+    tools/memory-model: Add data-race detection
+    
+    This patch adds data-race detection to the Linux-Kernel Memory Model.
+    As part of this effort, support is added for:
+    
+            compiler barriers (the barrier() function), and
+    
+            a new Preserved Program Order term: (addr ; [Plain] ; wmb)
+    
+    Data races are marked with a special Flag warning in herd.  It is
+    not guaranteed that the model will provide accurate predictions when a
+    data race is present.
+    
+    The patch does not include documentation for the data-race detection
+    facility.  The basic design has been explained in various emails, and
+    a separate documentation patch will be submitted later.
+    
+    This work is based on an earlier formulation of data races for the
+    LKMM by Andrea Parri.
+    
+    Signed-off-by: Alan Stern 
+    Reviewed-by: Andrea Parri 
+    Signed-off-by: Paul E. McKenney 
+
+diff --git a/tools/memory-model/linux-kernel.bell b/tools/memory-model/linux-kernel.bell
+index b60eb5a01053..5be86b1025e8 100644
+--- a/tools/memory-model/linux-kernel.bell
++++ b/tools/memory-model/linux-kernel.bell
+@@ -24,6 +24,7 @@ instructions RMW[{'once,'acquire,'release}]
+ enum Barriers = 'wmb (*smp_wmb*) ||
+ 		'rmb (*smp_rmb*) ||
+ 		'mb (*smp_mb*) ||
++		'barrier (*barrier*) ||
+ 		'rcu-lock (*rcu_read_lock*)  ||
+ 		'rcu-unlock (*rcu_read_unlock*) ||
+ 		'sync-rcu (*synchronize_rcu*) ||
+diff --git a/tools/memory-model/linux-kernel.cat b/tools/memory-model/linux-kernel.cat
+index ff354e5ffd4b..36d367054811 100644
+--- a/tools/memory-model/linux-kernel.cat
++++ b/tools/memory-model/linux-kernel.cat
+@@ -44,6 +44,9 @@ let strong-fence = mb | gp
+ 
+ let nonrw-fence = strong-fence | po-rel | acq-po
+ let fence = nonrw-fence | wmb | rmb
++let barrier = fencerel(Barrier | Rmb | Wmb | Mb | Sync-rcu | Sync-srcu |
++		Before-atomic | After-atomic | Acquire | Release) |
++	(po ; [Release]) | ([Acquire] ; po)
+ 
+ (**********************************)
+ (* Fundamental coherence ordering *)
+@@ -64,7 +67,7 @@ empty rmw & (fre ; coe) as atomic
+ let dep = addr | data
+ let rwdep = (dep | ctrl) ; [W]
+ let overwrite = co | fr
+-let to-w = rwdep | (overwrite & int)
++let to-w = rwdep | (overwrite & int) | (addr ; [Plain] ; wmb)
+ let to-r = addr | (dep ; [Marked] ; rfi)
+ let ppo = to-r | to-w | fence | (po-unlock-rf-lock-po & int)
+ 
+@@ -147,3 +150,48 @@ irreflexive rb as rcu
+  * let xb = hb | pb | rb
+  * acyclic xb as executes-before
+  *)
++
++(*********************************)
++(* Plain accesses and data races *)
++(*********************************)
++
++(* Warn about plain writes and marked accesses in the same region *)
++let mixed-accesses = ([Plain & W] ; (po-loc \ barrier) ; [Marked]) |
++	([Marked] ; (po-loc \ barrier) ; [Plain & W])
++flag ~empty mixed-accesses as mixed-accesses
++
++(* Executes-before and visibility *)
++let xbstar = (hb | pb | rb)*
++let full-fence = strong-fence | (po ; rcu-fence ; po?)
++let vis = cumul-fence* ; rfe? ; [Marked] ;
++	((full-fence ; [Marked] ; xbstar) | (xbstar & int))
++
++(* Boundaries for lifetimes of plain accesses *)
++let w-pre-bounded = [Marked] ; (addr | fence)?
++let r-pre-bounded = [Marked] ; (addr | nonrw-fence |
++	([R4rmb] ; fencerel(Rmb) ; [~Noreturn]))?
++let w-post-bounded = fence? ; [Marked]
++let r-post-bounded = (nonrw-fence | ([~Noreturn] ; fencerel(Rmb) ; [R4rmb]))? ;
++	[Marked]
++
++(* Visibility and executes-before for plain accesses *)
++let ww-vis = w-post-bounded ; vis ; w-pre-bounded
++let wr-vis = w-post-bounded ; vis ; r-pre-bounded
++let rw-xbstar = r-post-bounded ; xbstar ; w-pre-bounded
++
++(* Potential races *)
++let pre-race = ext & ((Plain * M) | ((M \ IW) * Plain))
++
++(* Coherence requirements for plain accesses *)
++let wr-incoh = pre-race & rf & rw-xbstar^-1
++let rw-incoh = pre-race & fr & wr-vis^-1
++let ww-incoh = pre-race & co & ww-vis^-1
++empty (wr-incoh | rw-incoh | ww-incoh) as plain-coherence
++
++(* Actual races *)
++let ww-nonrace = ww-vis & ((Marked * W) | rw-xbstar) & ((W * Marked) | wr-vis)
++let ww-race = (pre-race & co) \ ww-nonrace
++let wr-race = (pre-race & (co? ; rf)) \ wr-vis
++let rw-race = (pre-race & fr) \ rw-xbstar
++
++flag ~empty (ww-race | wr-race | rw-race) as data-race
+diff --git a/tools/memory-model/linux-kernel.def b/tools/memory-model/linux-kernel.def
+index 551eeaa389d4..ef0f3c1850de 100644
+--- a/tools/memory-model/linux-kernel.def
++++ b/tools/memory-model/linux-kernel.def
+@@ -24,6 +24,7 @@ smp_mb__before_atomic() { __fence{before-atomic}; }
+ smp_mb__after_atomic() { __fence{after-atomic}; }
+ smp_mb__after_spinlock() { __fence{after-spinlock}; }
+ smp_mb__after_unlock_lock() { __fence{after-unlock-lock}; }
++barrier() { __fence{barrier}; }
+ 
+ // Exchange
+ xchg(X,V)  __xchg{mb}(X,V)

commit d1a84ab190137cc2a980b6979b1f2790d51b2d87
+Author: Alan Stern 
+Date:   Mon Apr 22 12:17:58 2019 -0400
+
+    tools/memory-model: Add definitions of plain and marked accesses
+    
+    This patch adds definitions for marked and plain accesses to the
+    Linux-Kernel Memory Model.  It also modifies the definitions of the
+    existing parts of the model (including the cumul-fence, prop, hb, pb,
+    and rb relations) so as to make them apply only to marked accesses.
+    
+    Signed-off-by: Alan Stern 
+    Reviewed-by: Andrea Parri 
+    Signed-off-by: Paul E. McKenney 
+
+diff --git a/tools/memory-model/linux-kernel.bell b/tools/memory-model/linux-kernel.bell
+index def9131d3d8e..b60eb5a01053 100644
+--- a/tools/memory-model/linux-kernel.bell
++++ b/tools/memory-model/linux-kernel.bell
+@@ -76,3 +76,8 @@ flag ~empty rcu-rscs & (po ; [Sync-srcu] ; po) as invalid-sleep
+ 
+ (* Validate SRCU dynamic match *)
+ flag ~empty different-values(srcu-rscs) as srcu-bad-nesting
++
++(* Compute marked and plain memory accesses *)
++let Marked = (~M) | IW | Once | Release | Acquire | domain(rmw) | range(rmw) |
++		LKR | LKW | UL | LF | RL | RU
++let Plain = M \ Marked
+diff --git a/tools/memory-model/linux-kernel.cat b/tools/memory-model/linux-kernel.cat
+index 834107022c50..ff354e5ffd4b 100644
+--- a/tools/memory-model/linux-kernel.cat
++++ b/tools/memory-model/linux-kernel.cat
+@@ -65,19 +65,21 @@ let dep = addr | data
+ let rwdep = (dep | ctrl) ; [W]
+ let overwrite = co | fr
+ let to-w = rwdep | (overwrite & int)
+-let to-r = addr | (dep ; rfi)
++let to-r = addr | (dep ; [Marked] ; rfi)
+ let ppo = to-r | to-w | fence | (po-unlock-rf-lock-po & int)
+ 
+ (* Propagation: Ordering from release operations and strong fences. *)
+-let A-cumul(r) = rfe? ; r
+-let cumul-fence = A-cumul(strong-fence | po-rel) | wmb | po-unlock-rf-lock-po
+-let prop = (overwrite & ext)? ; cumul-fence* ; rfe?
++let A-cumul(r) = (rfe ; [Marked])? ; r
++let cumul-fence = [Marked] ; (A-cumul(strong-fence | po-rel) | wmb |
++	po-unlock-rf-lock-po) ; [Marked]
++let prop = [Marked] ; (overwrite & ext)? ; cumul-fence* ;
++	[Marked] ; rfe? ; [Marked]
+ 
+ (*
+  * Happens Before: Ordering from the passage of time.
+  * No fences needed here for prop because relation confined to one process.
+  *)
+-let hb = ppo | rfe | ((prop \ id) & int)
++let hb = [Marked] ; (ppo | rfe | ((prop \ id) & int)) ; [Marked]
+ acyclic hb as happens-before
+ 
+ (****************************************)
+@@ -85,7 +87,7 @@ acyclic hb as happens-before
+ (****************************************)
+ 
+ (* Propagation: Each non-rf link needs a strong fence. *)
+-let pb = prop ; strong-fence ; hb*
++let pb = prop ; strong-fence ; hb* ; [Marked]
+ acyclic pb as propagation
+ 
+ (*******)
+@@ -133,7 +135,7 @@ let rec rcu-fence = rcu-gp | srcu-gp |
+ 	(rcu-fence ; rcu-link ; rcu-fence)
+ 
+ (* rb orders instructions just as pb does *)
+-let rb = prop ; po ; rcu-fence ; po? ; hb* ; pb*
++let rb = prop ; po ; rcu-fence ; po? ; hb* ; pb* ; [Marked]
+ 
+ irreflexive rb as rcu
+ 

commit 4494dd58fbb477e54c129c1d8ef477aad433eba0
+Author: Alan Stern 
+Date:   Mon Apr 22 12:17:45 2019 -0400
+
+    tools/memory-model: Prepare for data-race detection
+    
+    This patch makes some slight alterations to linux-kernel.cat in
+    preparation for adding support for data-race detection to the
+    Linux-Kernel Memory Model.
+    
+            The definitions of relations involved in Acquire, Release, and
+            unlock-lock ordering are moved up earlier in the source file.
+    
+            The rmb relation is factored through the new R4rmb class: the
+            class of reads to which rmb will apply.
+    
+            The definition of the fence relation is moved earlier, and it
+            is split up into read- and write-fences (rmb and wmb) and all
+            the others.
+    
+    This should not make any functional changes.
+    
+    Signed-off-by: Alan Stern 
+    Reviewed-by: Andrea Parri 
+    Signed-off-by: Paul E. McKenney 
+
+diff --git a/tools/memory-model/linux-kernel.cat b/tools/memory-model/linux-kernel.cat
+index 8dcb37835b61..834107022c50 100644
+--- a/tools/memory-model/linux-kernel.cat
++++ b/tools/memory-model/linux-kernel.cat
+@@ -24,8 +24,14 @@ include "lock.cat"
+ (* Basic relations *)
+ (*******************)
+ 
++(* Release Acquire *)
++let acq-po = [Acquire] ; po ; [M]
++let po-rel = [M] ; po ; [Release]
++let po-unlock-rf-lock-po = po ; [UL] ; rf ; [LKR] ; po
++
+ (* Fences *)
+-let rmb = [R \ Noreturn] ; fencerel(Rmb) ; [R \ Noreturn]
++let R4rmb = R \ Noreturn	(* Reads for which rmb works *)
++let rmb = [R4rmb] ; fencerel(Rmb) ; [R4rmb]
+ let wmb = [W] ; fencerel(Wmb) ; [W]
+ let mb = ([M] ; fencerel(Mb) ; [M]) |
+ 	([M] ; fencerel(Before-atomic) ; [RMW] ; po? ; [M]) |
+@@ -34,13 +40,10 @@ let mb = ([M] ; fencerel(Mb) ; [M]) |
+ 	([M] ; po ; [UL] ; (co | po) ; [LKW] ;
+ 		fencerel(After-unlock-lock) ; [M])
+ let gp = po ; [Sync-rcu | Sync-srcu] ; po?
+-
+ let strong-fence = mb | gp
+ 
+-(* Release Acquire *)
+-let acq-po = [Acquire] ; po ; [M]
+-let po-rel = [M] ; po ; [Release]
+-let po-unlock-rf-lock-po = po ; [UL] ; rf ; [LKR] ; po
++let nonrw-fence = strong-fence | po-rel | acq-po
++let fence = nonrw-fence | wmb | rmb
+ 
+ (**********************************)
+ (* Fundamental coherence ordering *)
+@@ -63,7 +66,6 @@ let rwdep = (dep | ctrl) ; [W]
+ let overwrite = co | fr
+ let to-w = rwdep | (overwrite & int)
+ let to-r = addr | (dep ; rfi)
+-let fence = strong-fence | wmb | po-rel | rmb | acq-po
+ let ppo = to-r | to-w | fence | (po-unlock-rf-lock-po & int)
+ 
+ (* Propagation: Ordering from release operations and strong fences. *)

commit 45457c01171fd1488a7000d1751c06ed8560ee38
+Author: Alan Stern 
+Date:   Tue May 21 11:38:07 2019 -0400
+
+    media: usb: siano: Fix false-positive "uninitialized variable" warning
+    
+    GCC complains about an apparently uninitialized variable recently
+    added to smsusb_init_device().  It's a false positive, but to silence
+    the warning this patch adds a trivial initialization.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: kbuild test robot 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c
+index 27ad14a3f831..59b3c124b49d 100644
+--- a/drivers/media/usb/siano/smsusb.c
++++ b/drivers/media/usb/siano/smsusb.c
+@@ -400,7 +400,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
+ 	struct smsusb_device_t *dev;
+ 	void *mdev;
+ 	int i, rc;
+-	int in_maxp;
++	int in_maxp = 0;
+ 
+ 	/* create device object */
+ 	dev = kzalloc(sizeof(struct smsusb_device_t), GFP_KERNEL);

commit 31e0456de5be379b10fea0fa94a681057114a96e
+Author: Alan Stern 
+Date:   Tue May 7 12:39:47 2019 -0400
+
+    media: usb: siano: Fix general protection fault in smsusb
+    
+    The syzkaller USB fuzzer found a general-protection-fault bug in the
+    smsusb part of the Siano DVB driver.  The fault occurs during probe
+    because the driver assumes without checking that the device has both
+    IN and OUT endpoints and the IN endpoint is ep1.
+    
+    By slightly rearranging the driver's initialization code, we can make
+    the appropriate checks early on and thus avoid the problem.  If the
+    expected endpoints aren't present, the new code safely returns -ENODEV
+    from the probe routine.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: syzbot+53f029db71c19a47325a@syzkaller.appspotmail.com
+    CC: 
+    Reviewed-by: Johan Hovold 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c
+index 4fc03ec8a4f1..27ad14a3f831 100644
+--- a/drivers/media/usb/siano/smsusb.c
++++ b/drivers/media/usb/siano/smsusb.c
+@@ -400,6 +400,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
+ 	struct smsusb_device_t *dev;
+ 	void *mdev;
+ 	int i, rc;
++	int in_maxp;
+ 
+ 	/* create device object */
+ 	dev = kzalloc(sizeof(struct smsusb_device_t), GFP_KERNEL);
+@@ -411,6 +412,24 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
+ 	dev->udev = interface_to_usbdev(intf);
+ 	dev->state = SMSUSB_DISCONNECTED;
+ 
++	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
++		struct usb_endpoint_descriptor *desc =
++				&intf->cur_altsetting->endpoint[i].desc;
++
++		if (desc->bEndpointAddress & USB_DIR_IN) {
++			dev->in_ep = desc->bEndpointAddress;
++			in_maxp = usb_endpoint_maxp(desc);
++		} else {
++			dev->out_ep = desc->bEndpointAddress;
++		}
++	}
++
++	pr_debug("in_ep = %02x, out_ep = %02x\n", dev->in_ep, dev->out_ep);
++	if (!dev->in_ep || !dev->out_ep) {	/* Missing endpoints? */
++		smsusb_term_device(intf);
++		return -ENODEV;
++	}
++
+ 	params.device_type = sms_get_board(board_id)->type;
+ 
+ 	switch (params.device_type) {
+@@ -425,24 +444,12 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
+ 		/* fall-thru */
+ 	default:
+ 		dev->buffer_size = USB2_BUFFER_SIZE;
+-		dev->response_alignment =
+-		    le16_to_cpu(dev->udev->ep_in[1]->desc.wMaxPacketSize) -
+-		    sizeof(struct sms_msg_hdr);
++		dev->response_alignment = in_maxp - sizeof(struct sms_msg_hdr);
+ 
+ 		params.flags |= SMS_DEVICE_FAMILY2;
+ 		break;
+ 	}
+ 
+-	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
+-		if (intf->cur_altsetting->endpoint[i].desc. bEndpointAddress & USB_DIR_IN)
+-			dev->in_ep = intf->cur_altsetting->endpoint[i].desc.bEndpointAddress;
+-		else
+-			dev->out_ep = intf->cur_altsetting->endpoint[i].desc.bEndpointAddress;
+-	}
+-
+-	pr_debug("in_ep = %02x, out_ep = %02x\n",
+-		dev->in_ep, dev->out_ep);
+-
+ 	params.device = &dev->udev->dev;
+ 	params.usb_device = dev->udev;
+ 	params.buffer_size = dev->buffer_size;

commit a03ff54460817c76105f81f3aa8ef655759ccc9a
+Author: Alan Stern 
+Date:   Mon May 13 13:14:29 2019 -0400
+
+    USB: Fix slab-out-of-bounds write in usb_get_bos_descriptor
+    
+    The syzkaller USB fuzzer found a slab-out-of-bounds write bug in the
+    USB core, caused by a failure to check the actual size of a BOS
+    descriptor.  This patch adds a check to make sure the descriptor is at
+    least as large as it is supposed to be, so that the code doesn't
+    inadvertently access memory beyond the end of the allocated region
+    when assigning to dev->bos->desc->bNumDeviceCaps later on.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: syzbot+71f1e64501a309fcc012@syzkaller.appspotmail.com
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
+index 20ff036b4c22..9d6cb709ca7b 100644
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -932,8 +932,8 @@ int usb_get_bos_descriptor(struct usb_device *dev)
+ 
+ 	/* Get BOS descriptor */
+ 	ret = usb_get_descriptor(dev, USB_DT_BOS, 0, bos, USB_DT_BOS_SIZE);
+-	if (ret < USB_DT_BOS_SIZE) {
+-		dev_err(ddev, "unable to get BOS descriptor\n");
++	if (ret < USB_DT_BOS_SIZE || bos->bLength < USB_DT_BOS_SIZE) {
++		dev_err(ddev, "unable to get BOS descriptor or descriptor too short\n");
+ 		if (ret >= 0)
+ 			ret = -ENOMSG;
+ 		kfree(bos);

commit de497f634609aa1710fef4b6d833a037120369cc
+Author: Alan Stern 
+Date:   Mon Apr 15 13:35:46 2019 -0400
+
+    USB: UDC: net22{80,72}: remove mistaken test of req->zero
+    
+    The net2280 UDC driver (and also net2272, probably via copy-and-paste)
+    incorrectly checks the req->zero flag during OUT transfers, after
+    copying data from the UDC's FIFO into memory.  This makes no sense at
+    all; the "zero" flag indicates that an extra zero-length packet should
+    be appended to an IN transfer if the length is an even multiple of the
+    maxpacket size.  It has nothing to do with OUT transfers.
+    
+    In practice this doesn't cause any problems because gadget drivers
+    never set req->zero for OUT transfers anyway.  Still, it is an error
+    and unnecessary code, so this patch removes the check.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c
+index c2011cd7df8c..564aeee1a1fe 100644
+--- a/drivers/usb/gadget/udc/net2272.c
++++ b/drivers/usb/gadget/udc/net2272.c
+@@ -573,8 +573,7 @@ net2272_read_fifo(struct net2272_ep *ep, struct net2272_request *req)
+ 
+ 		/* completion */
+ 		if (unlikely(cleanup || is_short ||
+-				((req->req.actual == req->req.length)
+-				 && !req->req.zero))) {
++				req->req.actual == req->req.length)) {
+ 
+ 			if (cleanup) {
+ 				net2272_out_flush(ep);
+diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c
+index b17473a00b43..b6bbe2e448ba 100644
+--- a/drivers/usb/gadget/udc/net2280.c
++++ b/drivers/usb/gadget/udc/net2280.c
+@@ -789,8 +789,7 @@ static int read_fifo(struct net2280_ep *ep, struct net2280_request *req)
+ 		(void) readl(&ep->regs->ep_rsp);
+ 	}
+ 
+-	return is_short || ((req->req.actual == req->req.length) &&
+-			!req->req.zero);
++	return is_short || req->req.actual == req->req.length;
+ }
+ 
+ /* fill out dma descriptor to match a given request */

commit 6574abe69946589bf0f69cf9b32f6a2c71ae764f
+Author: Alan Stern 
+Date:   Mon Apr 15 13:36:58 2019 -0400
+
+    USB: UDC: net2280: Remove redundant "if" condition
+    
+    The net2280 driver includes an unnecessary test for an endpoint's
+    queue being empty.  The test is redundant; it sits inside a
+    conditional block of an "if" statement which already tests the
+    endpoint's queue.
+    
+    This patch removes the redundant test.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c
+index 898339e5df10..b17473a00b43 100644
+--- a/drivers/usb/gadget/udc/net2280.c
++++ b/drivers/usb/gadget/udc/net2280.c
+@@ -1058,7 +1058,7 @@ net2280_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+ 			/* PIO ... stuff the fifo, or unblock it.  */
+ 			if (ep->is_in)
+ 				write_fifo(ep, _req);
+-			else if (list_empty(&ep->queue)) {
++			else {
+ 				u32	s;
+ 
+ 				/* OUT FIFO might have packet(s) buffered */

commit 50896c410354432e8e7baf97fcdd7df265e683ae
+Author: Alan Stern 
+Date:   Thu Apr 18 13:12:07 2019 -0400
+
+    USB: dummy-hcd: Fix failure to give back unlinked URBs
+    
+    The syzkaller USB fuzzer identified a failure mode in which dummy-hcd
+    would never give back an unlinked URB.  This causes usb_kill_urb() to
+    hang, leading to WARNINGs and unkillable threads.
+    
+    In dummy-hcd, all URBs are given back by the dummy_timer() routine as
+    it scans through the list of pending URBS.  Failure to give back URBs
+    can be caused by failure to start or early exit from the scanning
+    loop.  The code currently has two such pathways: One is triggered when
+    an unsupported bus transfer speed is encountered, and the other by
+    exhausting the simulated bandwidth for USB transfers during a frame.
+    
+    This patch removes those two paths, thereby allowing all unlinked URBs
+    to be given back in a timely manner.  It adds a check for the bus
+    speed when the gadget first starts running, so that dummy_timer() will
+    never thereafter encounter an unsupported speed.  And it prevents the
+    loop from exiting as soon as the total bandwidth has been used up (the
+    scanning loop continues, giving back unlinked URBs as they are found,
+    but not transferring any more data).
+    
+    Thanks to Andrey Konovalov for manually running the syzkaller fuzzer
+    to help track down the source of the bug.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: syzbot+d919b0f29d7b5a4994b9@syzkaller.appspotmail.com
+    CC: 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
+index baf72f95f0f1..213b52508621 100644
+--- a/drivers/usb/gadget/udc/dummy_hcd.c
++++ b/drivers/usb/gadget/udc/dummy_hcd.c
+@@ -979,8 +979,18 @@ static int dummy_udc_start(struct usb_gadget *g,
+ 	struct dummy_hcd	*dum_hcd = gadget_to_dummy_hcd(g);
+ 	struct dummy		*dum = dum_hcd->dum;
+ 
+-	if (driver->max_speed == USB_SPEED_UNKNOWN)
++	switch (g->speed) {
++	/* All the speeds we support */
++	case USB_SPEED_LOW:
++	case USB_SPEED_FULL:
++	case USB_SPEED_HIGH:
++	case USB_SPEED_SUPER:
++		break;
++	default:
++		dev_err(dummy_dev(dum_hcd), "Unsupported driver max speed %d\n",
++				driver->max_speed);
+ 		return -EINVAL;
++	}
+ 
+ 	/*
+ 	 * SLAVE side init ... the layer above hardware, which
+@@ -1784,9 +1794,10 @@ static void dummy_timer(struct timer_list *t)
+ 		/* Bus speed is 500000 bytes/ms, so use a little less */
+ 		total = 490000;
+ 		break;
+-	default:
++	default:	/* Can't happen */
+ 		dev_err(dummy_dev(dum_hcd), "bogus device speed\n");
+-		return;
++		total = 0;
++		break;
+ 	}
+ 
+ 	/* FIXME if HZ != 1000 this will probably misbehave ... */
+@@ -1828,7 +1839,7 @@ static void dummy_timer(struct timer_list *t)
+ 
+ 		/* Used up this frame's bandwidth? */
+ 		if (total <= 0)
+-			break;
++			continue;
+ 
+ 		/* find the gadget's ep for this request (if configured) */
+ 		address = usb_pipeendpoint (urb->pipe);

commit c114944d7d67f24e71562fcfc18d550ab787e4d4
+Author: Alan Stern 
+Date:   Mon Apr 22 11:16:04 2019 -0400
+
+    USB: w1 ds2490: Fix bug caused by improper use of altsetting array
+    
+    The syzkaller USB fuzzer spotted a slab-out-of-bounds bug in the
+    ds2490 driver.  This bug is caused by improper use of the altsetting
+    array in the usb_interface structure (the array's entries are not
+    always stored in numerical order), combined with a naive assumption
+    that all interfaces probed by the driver will have the expected number
+    of altsettings.
+    
+    The bug can be fixed by replacing references to the possibly
+    non-existent intf->altsetting[alt] entry with the guaranteed-to-exist
+    intf->cur_altsetting entry.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: syzbot+d65f673b847a1a96cdba@syzkaller.appspotmail.com
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c
+index 0f4ecfcdb549..a9fb77585272 100644
+--- a/drivers/w1/masters/ds2490.c
++++ b/drivers/w1/masters/ds2490.c
+@@ -1016,15 +1016,15 @@ static int ds_probe(struct usb_interface *intf,
+ 	/* alternative 3, 1ms interrupt (greatly speeds search), 64 byte bulk */
+ 	alt = 3;
+ 	err = usb_set_interface(dev->udev,
+-		intf->altsetting[alt].desc.bInterfaceNumber, alt);
++		intf->cur_altsetting->desc.bInterfaceNumber, alt);
+ 	if (err) {
+ 		dev_err(&dev->udev->dev, "Failed to set alternative setting %d "
+ 			"for %d interface: err=%d.\n", alt,
+-			intf->altsetting[alt].desc.bInterfaceNumber, err);
++			intf->cur_altsetting->desc.bInterfaceNumber, err);
+ 		goto err_out_clear;
+ 	}
+ 
+-	iface_desc = &intf->altsetting[alt];
++	iface_desc = intf->cur_altsetting;
+ 	if (iface_desc->desc.bNumEndpoints != NUM_EP-1) {
+ 		pr_info("Num endpoints=%d. It is not DS9490R.\n",
+ 			iface_desc->desc.bNumEndpoints);

commit ef61eb43ada6c1d6b94668f0f514e4c268093ff3
+Author: Alan Stern 
+Date:   Tue Apr 23 14:48:29 2019 -0400
+
+    USB: yurex: Fix protection fault after device removal
+    
+    The syzkaller USB fuzzer found a general-protection-fault bug in the
+    yurex driver.  The fault occurs when a device has been unplugged; the
+    driver's interrupt-URB handler logs an error message referring to the
+    device by name, after the device has been unregistered and its name
+    deallocated.
+    
+    This problem is caused by the fact that the interrupt URB isn't
+    cancelled until the driver's private data structure is released, which
+    can happen long after the device is gone.  The cure is to make sure
+    that the interrupt URB is killed before yurex_disconnect() returns;
+    this is exactly the sort of thing that usb_poison_urb() was meant for.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: syzbot+2eb9121678bdb36e6d57@syzkaller.appspotmail.com
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c
+index 6d9fd5f64903..7b306aa22d25 100644
+--- a/drivers/usb/misc/yurex.c
++++ b/drivers/usb/misc/yurex.c
+@@ -314,6 +314,7 @@ static void yurex_disconnect(struct usb_interface *interface)
+ 	usb_deregister_dev(interface, &yurex_class);
+ 
+ 	/* prevent more I/O from starting */
++	usb_poison_urb(dev->urb);
+ 	mutex_lock(&dev->io_mutex);
+ 	dev->interface = NULL;
+ 	mutex_unlock(&dev->io_mutex);

commit c2b71462d294cf517a0bc6e4fd6424d7cee5596f
+Author: Alan Stern 
+Date:   Fri Apr 19 13:52:38 2019 -0400
+
+    USB: core: Fix bug caused by duplicate interface PM usage counter
+    
+    The syzkaller fuzzer reported a bug in the USB hub driver which turned
+    out to be caused by a negative runtime-PM usage counter.  This allowed
+    a hub to be runtime suspended at a time when the driver did not expect
+    it.  The symptom is a WARNING issued because the hub's status URB is
+    submitted while it is already active:
+    
+            URB 0000000031fb463e submitted while active
+            WARNING: CPU: 0 PID: 2917 at drivers/usb/core/urb.c:363
+    
+    The negative runtime-PM usage count was caused by an unfortunate
+    design decision made when runtime PM was first implemented for USB.
+    At that time, USB class drivers were allowed to unbind from their
+    interfaces without balancing the usage counter (i.e., leaving it with
+    a positive count).  The core code would take care of setting the
+    counter back to 0 before allowing another driver to bind to the
+    interface.
+    
+    Later on when runtime PM was implemented for the entire kernel, the
+    opposite decision was made: Drivers were required to balance their
+    runtime-PM get and put calls.  In order to maintain backward
+    compatibility, however, the USB subsystem adapted to the new
+    implementation by keeping an independent usage counter for each
+    interface and using it to automatically adjust the normal usage
+    counter back to 0 whenever a driver was unbound.
+    
+    This approach involves duplicating information, but what is worse, it
+    doesn't work properly in cases where a USB class driver delays
+    decrementing the usage counter until after the driver's disconnect()
+    routine has returned and the counter has been adjusted back to 0.
+    Doing so would cause the usage counter to become negative.  There's
+    even a warning about this in the USB power management documentation!
+    
+    As it happens, this is exactly what the hub driver does.  The
+    kick_hub_wq() routine increments the runtime-PM usage counter, and the
+    corresponding decrement is carried out by hub_event() in the context
+    of the hub_wq work-queue thread.  This work routine may sometimes run
+    after the driver has been unbound from its interface, and when it does
+    it causes the usage counter to go negative.
+    
+    It is not possible for hub_disconnect() to wait for a pending
+    hub_event() call to finish, because hub_disconnect() is called with
+    the device lock held and hub_event() acquires that lock.  The only
+    feasible fix is to reverse the original design decision: remove the
+    duplicate interface-specific usage counter and require USB drivers to
+    balance their runtime PM gets and puts.  As far as I know, all
+    existing drivers currently do this.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: syzbot+7634edaea4d0b341c625@syzkaller.appspotmail.com
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/driver-api/usb/power-management.rst b/Documentation/driver-api/usb/power-management.rst
+index 79beb807996b..4a74cf6f2797 100644
+--- a/Documentation/driver-api/usb/power-management.rst
++++ b/Documentation/driver-api/usb/power-management.rst
+@@ -370,11 +370,15 @@ autosuspend the interface's device.  When the usage counter is = 0
+ then the interface is considered to be idle, and the kernel may
+ autosuspend the device.
+ 
+-Drivers need not be concerned about balancing changes to the usage
+-counter; the USB core will undo any remaining "get"s when a driver
+-is unbound from its interface.  As a corollary, drivers must not call
+-any of the ``usb_autopm_*`` functions after their ``disconnect``
+-routine has returned.
++Drivers must be careful to balance their overall changes to the usage
++counter.  Unbalanced "get"s will remain in effect when a driver is
++unbound from its interface, preventing the device from going into
++runtime suspend should the interface be bound to a driver again.  On
++the other hand, drivers are allowed to achieve this balance by calling
++the ``usb_autopm_*`` functions even after their ``disconnect`` routine
++has returned -- say from within a work-queue routine -- provided they
++retain an active reference to the interface (via ``usb_get_intf`` and
++``usb_put_intf``).
+ 
+ Drivers using the async routines are responsible for their own
+ synchronization and mutual exclusion.
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 8987cec9549d..ebcadaad89d1 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -473,11 +473,6 @@ static int usb_unbind_interface(struct device *dev)
+ 		pm_runtime_disable(dev);
+ 	pm_runtime_set_suspended(dev);
+ 
+-	/* Undo any residual pm_autopm_get_interface_* calls */
+-	for (r = atomic_read(&intf->pm_usage_cnt); r > 0; --r)
+-		usb_autopm_put_interface_no_suspend(intf);
+-	atomic_set(&intf->pm_usage_cnt, 0);
+-
+ 	if (!error)
+ 		usb_autosuspend_device(udev);
+ 
+@@ -1633,7 +1628,6 @@ void usb_autopm_put_interface(struct usb_interface *intf)
+ 	int			status;
+ 
+ 	usb_mark_last_busy(udev);
+-	atomic_dec(&intf->pm_usage_cnt);
+ 	status = pm_runtime_put_sync(&intf->dev);
+ 	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
+ 			__func__, atomic_read(&intf->dev.power.usage_count),
+@@ -1662,7 +1656,6 @@ void usb_autopm_put_interface_async(struct usb_interface *intf)
+ 	int			status;
+ 
+ 	usb_mark_last_busy(udev);
+-	atomic_dec(&intf->pm_usage_cnt);
+ 	status = pm_runtime_put(&intf->dev);
+ 	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
+ 			__func__, atomic_read(&intf->dev.power.usage_count),
+@@ -1684,7 +1677,6 @@ void usb_autopm_put_interface_no_suspend(struct usb_interface *intf)
+ 	struct usb_device	*udev = interface_to_usbdev(intf);
+ 
+ 	usb_mark_last_busy(udev);
+-	atomic_dec(&intf->pm_usage_cnt);
+ 	pm_runtime_put_noidle(&intf->dev);
+ }
+ EXPORT_SYMBOL_GPL(usb_autopm_put_interface_no_suspend);
+@@ -1715,8 +1707,6 @@ int usb_autopm_get_interface(struct usb_interface *intf)
+ 	status = pm_runtime_get_sync(&intf->dev);
+ 	if (status < 0)
+ 		pm_runtime_put_sync(&intf->dev);
+-	else
+-		atomic_inc(&intf->pm_usage_cnt);
+ 	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
+ 			__func__, atomic_read(&intf->dev.power.usage_count),
+ 			status);
+@@ -1750,8 +1740,6 @@ int usb_autopm_get_interface_async(struct usb_interface *intf)
+ 	status = pm_runtime_get(&intf->dev);
+ 	if (status < 0 && status != -EINPROGRESS)
+ 		pm_runtime_put_noidle(&intf->dev);
+-	else
+-		atomic_inc(&intf->pm_usage_cnt);
+ 	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
+ 			__func__, atomic_read(&intf->dev.power.usage_count),
+ 			status);
+@@ -1775,7 +1763,6 @@ void usb_autopm_get_interface_no_resume(struct usb_interface *intf)
+ 	struct usb_device	*udev = interface_to_usbdev(intf);
+ 
+ 	usb_mark_last_busy(udev);
+-	atomic_inc(&intf->pm_usage_cnt);
+ 	pm_runtime_get_noresume(&intf->dev);
+ }
+ EXPORT_SYMBOL_GPL(usb_autopm_get_interface_no_resume);
+diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c
+index 31b024441938..cc794e25a0b6 100644
+--- a/drivers/usb/storage/realtek_cr.c
++++ b/drivers/usb/storage/realtek_cr.c
+@@ -763,18 +763,16 @@ static void rts51x_suspend_timer_fn(struct timer_list *t)
+ 		break;
+ 	case RTS51X_STAT_IDLE:
+ 	case RTS51X_STAT_SS:
+-		usb_stor_dbg(us, "RTS51X_STAT_SS, intf->pm_usage_cnt:%d, power.usage:%d\n",
+-			     atomic_read(&us->pusb_intf->pm_usage_cnt),
++		usb_stor_dbg(us, "RTS51X_STAT_SS, power.usage:%d\n",
+ 			     atomic_read(&us->pusb_intf->dev.power.usage_count));
+ 
+-		if (atomic_read(&us->pusb_intf->pm_usage_cnt) > 0) {
++		if (atomic_read(&us->pusb_intf->dev.power.usage_count) > 0) {
+ 			usb_stor_dbg(us, "Ready to enter SS state\n");
+ 			rts51x_set_stat(chip, RTS51X_STAT_SS);
+ 			/* ignore mass storage interface's children */
+ 			pm_suspend_ignore_children(&us->pusb_intf->dev, true);
+ 			usb_autopm_put_interface_async(us->pusb_intf);
+-			usb_stor_dbg(us, "RTS51X_STAT_SS 01, intf->pm_usage_cnt:%d, power.usage:%d\n",
+-				     atomic_read(&us->pusb_intf->pm_usage_cnt),
++			usb_stor_dbg(us, "RTS51X_STAT_SS 01, power.usage:%d\n",
+ 				     atomic_read(&us->pusb_intf->dev.power.usage_count));
+ 		}
+ 		break;
+@@ -807,11 +805,10 @@ static void rts51x_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 	int ret;
+ 
+ 	if (working_scsi(srb)) {
+-		usb_stor_dbg(us, "working scsi, intf->pm_usage_cnt:%d, power.usage:%d\n",
+-			     atomic_read(&us->pusb_intf->pm_usage_cnt),
++		usb_stor_dbg(us, "working scsi, power.usage:%d\n",
+ 			     atomic_read(&us->pusb_intf->dev.power.usage_count));
+ 
+-		if (atomic_read(&us->pusb_intf->pm_usage_cnt) <= 0) {
++		if (atomic_read(&us->pusb_intf->dev.power.usage_count) <= 0) {
+ 			ret = usb_autopm_get_interface(us->pusb_intf);
+ 			usb_stor_dbg(us, "working scsi, ret=%d\n", ret);
+ 		}
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 5e49e82c4368..ff010d1fd1c7 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -200,7 +200,6 @@ usb_find_last_int_out_endpoint(struct usb_host_interface *alt,
+  * @dev: driver model's view of this device
+  * @usb_dev: if an interface is bound to the USB major, this will point
+  *	to the sysfs representation for that device.
+- * @pm_usage_cnt: PM usage counter for this interface
+  * @reset_ws: Used for scheduling resets from atomic context.
+  * @resetting_device: USB core reset the device, so use alt setting 0 as
+  *	current; needs bandwidth alloc after reset.
+@@ -257,7 +256,6 @@ struct usb_interface {
+ 
+ 	struct device dev;		/* interface specific device info */
+ 	struct device *usb_dev;
+-	atomic_t pm_usage_cnt;		/* usage counter for autosuspend */
+ 	struct work_struct reset_ws;	/* for resets in atomic context */
+ };
+ #define	to_usb_interface(d) container_of(d, struct usb_interface, dev)

commit fc834e607ae3d18e1a20bca3f9a2d7f52ea7a2be
+Author: Alan Stern 
+Date:   Thu Apr 18 13:12:07 2019 -0400
+
+    USB: dummy-hcd: Fix failure to give back unlinked URBs
+    
+    The syzkaller USB fuzzer identified a failure mode in which dummy-hcd
+    would never give back an unlinked URB.  This causes usb_kill_urb() to
+    hang, leading to WARNINGs and unkillable threads.
+    
+    In dummy-hcd, all URBs are given back by the dummy_timer() routine as
+    it scans through the list of pending URBS.  Failure to give back URBs
+    can be caused by failure to start or early exit from the scanning
+    loop.  The code currently has two such pathways: One is triggered when
+    an unsupported bus transfer speed is encountered, and the other by
+    exhausting the simulated bandwidth for USB transfers during a frame.
+    
+    This patch removes those two paths, thereby allowing all unlinked URBs
+    to be given back in a timely manner.  It adds a check for the bus
+    speed when the gadget first starts running, so that dummy_timer() will
+    never thereafter encounter an unsupported speed.  And it prevents the
+    loop from exiting as soon as the total bandwidth has been used up (the
+    scanning loop continues, giving back unlinked URBs as they are found,
+    but not transferring any more data).
+    
+    Thanks to Andrey Konovalov for manually running the syzkaller fuzzer
+    to help track down the source of the bug.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: syzbot+d919b0f29d7b5a4994b9@syzkaller.appspotmail.com
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
+index baf72f95f0f1..213b52508621 100644
+--- a/drivers/usb/gadget/udc/dummy_hcd.c
++++ b/drivers/usb/gadget/udc/dummy_hcd.c
+@@ -979,8 +979,18 @@ static int dummy_udc_start(struct usb_gadget *g,
+ 	struct dummy_hcd	*dum_hcd = gadget_to_dummy_hcd(g);
+ 	struct dummy		*dum = dum_hcd->dum;
+ 
+-	if (driver->max_speed == USB_SPEED_UNKNOWN)
++	switch (g->speed) {
++	/* All the speeds we support */
++	case USB_SPEED_LOW:
++	case USB_SPEED_FULL:
++	case USB_SPEED_HIGH:
++	case USB_SPEED_SUPER:
++		break;
++	default:
++		dev_err(dummy_dev(dum_hcd), "Unsupported driver max speed %d\n",
++				driver->max_speed);
+ 		return -EINVAL;
++	}
+ 
+ 	/*
+ 	 * SLAVE side init ... the layer above hardware, which
+@@ -1784,9 +1794,10 @@ static void dummy_timer(struct timer_list *t)
+ 		/* Bus speed is 500000 bytes/ms, so use a little less */
+ 		total = 490000;
+ 		break;
+-	default:
++	default:	/* Can't happen */
+ 		dev_err(dummy_dev(dum_hcd), "bogus device speed\n");
+-		return;
++		total = 0;
++		break;
+ 	}
+ 
+ 	/* FIXME if HZ != 1000 this will probably misbehave ... */
+@@ -1828,7 +1839,7 @@ static void dummy_timer(struct timer_list *t)
+ 
+ 		/* Used up this frame's bandwidth? */
+ 		if (total <= 0)
+-			break;
++			continue;
+ 
+ 		/* find the gadget's ep for this request (if configured) */
+ 		address = usb_pipeendpoint (urb->pipe);

commit 381419fa720060ba48b7bbc483be787d5b1dca6f
+Author: Alan Stern 
+Date:   Tue Apr 16 10:50:01 2019 -0400
+
+    USB: core: Don't unbind interfaces following device reset failure
+    
+    The SCSI core does not like to have devices or hosts unregistered
+    while error recovery is in progress.  Trying to do so can lead to
+    self-deadlock: Part of the removal code tries to obtain a lock already
+    held by the error handler.
+    
+    This can cause problems for the usb-storage and uas drivers, because
+    their error handler routines perform a USB reset, and if the reset
+    fails then the USB core automatically goes on to unbind all drivers
+    from the device's interfaces -- all while still in the context of the
+    SCSI error handler.
+    
+    As it turns out, practically all the scenarios leading to a USB reset
+    failure end up causing a device disconnect (the main error pathway in
+    usb_reset_and_verify_device(), at the end of the routine, calls
+    hub_port_logical_disconnect() before returning).  As a result, the
+    hub_wq thread will soon become aware of the problem and will unbind
+    all the device's drivers in its own context, not in the
+    error-handler's context.
+    
+    This means that usb_reset_device() does not need to call
+    usb_unbind_and_rebind_marked_interfaces() in cases where
+    usb_reset_and_verify_device() has returned an error, because hub_wq
+    will take care of everything anyway.
+    
+    This particular problem was observed in somewhat artificial
+    circumstances, by using usbfs to tell a hub to power-down a port
+    connected to a USB-3 mass storage device using the UAS protocol.  With
+    the port turned off, the currently executing command timed out and the
+    error handler started running.  The USB reset naturally failed,
+    because the hub port was off, and the error handler deadlocked as
+    described above.  Not carrying out the call to
+    usb_unbind_and_rebind_marked_interfaces() fixes this issue.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Kento Kobayashi 
+    Tested-by: Kento Kobayashi 
+    CC: Bart Van Assche 
+    CC: Martin K. Petersen 
+    CC: Jacky Cao 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 15a2934dc29d..1949134f72e6 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -5901,7 +5901,10 @@ int usb_reset_device(struct usb_device *udev)
+ 					cintf->needs_binding = 1;
+ 			}
+ 		}
+-		usb_unbind_and_rebind_marked_interfaces(udev);
++
++		/* If the reset failed, hub_wq will unbind drivers later */
++		if (ret == 0)
++			usb_unbind_and_rebind_marked_interfaces(udev);
+ 	}
+ 
+ 	usb_autosuspend_device(udev);

commit 747668dbc061b3e62bc1982767a3a1f9815fcf0e
+Author: Alan Stern 
+Date:   Mon Apr 15 13:19:25 2019 -0400
+
+    usb-storage: Set virt_boundary_mask to avoid SG overflows
+    
+    The USB subsystem has always had an unusual requirement for its
+    scatter-gather transfers: Each element in the scatterlist (except the
+    last one) must have a length divisible by the bulk maxpacket size.
+    This is a particular issue for USB mass storage, which uses SG lists
+    created by the block layer rather than setting up its own.
+    
+    So far we have scraped by okay because most devices have a logical
+    block size of 512 bytes or larger, and the bulk maxpacket sizes for
+    USB 2 and below are all <= 512.  However, USB 3 has a bulk maxpacket
+    size of 1024.  Since the xhci-hcd driver includes native SG support,
+    this hasn't mattered much.  But now people are trying to use USB-3
+    mass storage devices with USBIP, and the vhci-hcd driver currently
+    does not have full SG support.
+    
+    The result is an overflow error, when the driver attempts to implement
+    an SG transfer of 63 512-byte blocks as a single
+    3584-byte (7 blocks) transfer followed by seven 4096-byte (8 blocks)
+    transfers.  The device instead sends 31 1024-byte packets followed by
+    a 512-byte packet, and this overruns the first SG buffer.
+    
+    Ideally this would be fixed by adding better SG support to vhci-hcd.
+    But for now it appears we can work around the problem by
+    asking the block layer to respect the maxpacket limitation, through
+    the use of the virt_boundary_mask.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Seth Bollinger 
+    Tested-by: Seth Bollinger 
+    CC: Ming Lei 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index a73ea495d5a7..59190d88fa9f 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -65,6 +65,7 @@ static const char* host_info(struct Scsi_Host *host)
+ static int slave_alloc (struct scsi_device *sdev)
+ {
+ 	struct us_data *us = host_to_us(sdev->host);
++	int maxp;
+ 
+ 	/*
+ 	 * Set the INQUIRY transfer length to 36.  We don't use any of
+@@ -74,20 +75,17 @@ static int slave_alloc (struct scsi_device *sdev)
+ 	sdev->inquiry_len = 36;
+ 
+ 	/*
+-	 * USB has unusual DMA-alignment requirements: Although the
+-	 * starting address of each scatter-gather element doesn't matter,
+-	 * the length of each element except the last must be divisible
+-	 * by the Bulk maxpacket value.  There's currently no way to
+-	 * express this by block-layer constraints, so we'll cop out
+-	 * and simply require addresses to be aligned at 512-byte
+-	 * boundaries.  This is okay since most block I/O involves
+-	 * hardware sectors that are multiples of 512 bytes in length,
+-	 * and since host controllers up through USB 2.0 have maxpacket
+-	 * values no larger than 512.
+-	 *
+-	 * But it doesn't suffice for Wireless USB, where Bulk maxpacket
+-	 * values can be as large as 2048.  To make that work properly
+-	 * will require changes to the block layer.
++	 * USB has unusual scatter-gather requirements: the length of each
++	 * scatterlist element except the last must be divisible by the
++	 * Bulk maxpacket value.  Fortunately this value is always a
++	 * power of 2.  Inform the block layer about this requirement.
++	 */
++	maxp = usb_maxpacket(us->pusb_dev, us->recv_bulk_pipe, 0);
++	blk_queue_virt_boundary(sdev->request_queue, maxp - 1);
++
++	/*
++	 * Some host controllers may have alignment requirements.
++	 * We'll play it safe by requiring 512-byte alignment always.
+ 	 */
+ 	blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
+ 

commit c01c348ecdc66085e44912c97368809612231520
+Author: Alan Stern 
+Date:   Mon Apr 15 11:51:38 2019 -0400
+
+    USB: core: Fix unterminated string returned by usb_string()
+    
+    Some drivers (such as the vub300 MMC driver) expect usb_string() to
+    return a properly NUL-terminated string, even when an error occurs.
+    (In fact, vub300's probe routine doesn't bother to check the return
+    code from usb_string().)  When the driver goes on to use an
+    unterminated string, it leads to kernel errors such as
+    stack-out-of-bounds, as found by the syzkaller USB fuzzer.
+    
+    An out-of-range string index argument is not at all unlikely, given
+    that some devices don't provide string descriptors and therefore list
+    0 as the value for their string indexes.  This patch makes
+    usb_string() return a properly terminated empty string along with the
+    -EINVAL error code when an out-of-range index is encountered.
+    
+    And since a USB string index is a single-byte value, indexes >= 256
+    are just as invalid as values of 0 or below.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: syzbot+b75b85111c10b8d680f1@syzkaller.appspotmail.com
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 82239f27c4cc..e844bb7b5676 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -820,9 +820,11 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
+ 
+ 	if (dev->state == USB_STATE_SUSPENDED)
+ 		return -EHOSTUNREACH;
+-	if (size <= 0 || !buf || !index)
++	if (size <= 0 || !buf)
+ 		return -EINVAL;
+ 	buf[0] = 0;
++	if (index <= 0 || index >= 256)
++		return -EINVAL;
+ 	tbuf = kmalloc(256, GFP_NOIO);
+ 	if (!tbuf)
+ 		return -ENOMEM;

commit 648e717586f2a832687fe44e2e0afb7a6fdea232
+Author: Alan Stern 
+Date:   Tue Dec 11 11:38:53 2018 -0500
+
+    tools/memory-model: Update Documentation/explanation.txt to include SRCU support
+    
+    The recent commit adding support for SRCU to the Linux Kernel Memory
+    Model ended up changing the names and meanings of several relations.
+    This patch updates the explanation.txt documentation file to reflect
+    those changes.
+    
+    It also revises the statement of the RCU Guarantee to a more accurate
+    form, and it adds a short paragraph mentioning the new support for SRCU.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Akira Yokosawa 
+    Cc: Andrea Parri 
+    Cc: Boqun Feng 
+    Cc: Daniel Lustig 
+    Cc: David Howells 
+    Cc: Jade Alglave 
+    Cc: Luc Maranget 
+    Cc: Nicholas Piggin 
+    Cc: "Paul E. McKenney" 
+    Cc: Peter Zijlstra 
+    Cc: Will Deacon 
+    Signed-off-by: Paul E. McKenney 
+    Acked-by: Andrea Parri 
+
+diff --git a/tools/memory-model/Documentation/explanation.txt b/tools/memory-model/Documentation/explanation.txt
+index 35bff92cc773..68caa9a976d0 100644
+--- a/tools/memory-model/Documentation/explanation.txt
++++ b/tools/memory-model/Documentation/explanation.txt
+@@ -27,7 +27,7 @@ Explanation of the Linux-Kernel Memory Consistency Model
+   19. AND THEN THERE WAS ALPHA
+   20. THE HAPPENS-BEFORE RELATION: hb
+   21. THE PROPAGATES-BEFORE RELATION: pb
+-  22. RCU RELATIONS: rcu-link, gp, rscs, rcu-fence, and rb
++  22. RCU RELATIONS: rcu-link, rcu-gp, rcu-rscsi, rcu-fence, and rb
+   23. LOCKING
+   24. ODDS AND ENDS
+ 
+@@ -1430,8 +1430,8 @@ they execute means that it cannot have cycles.  This requirement is
+ the content of the LKMM's "propagation" axiom.
+ 
+ 
+-RCU RELATIONS: rcu-link, gp, rscs, rcu-fence, and rb
+-----------------------------------------------------
++RCU RELATIONS: rcu-link, rcu-gp, rcu-rscsi, rcu-fence, and rb
++-------------------------------------------------------------
+ 
+ RCU (Read-Copy-Update) is a powerful synchronization mechanism.  It
+ rests on two concepts: grace periods and read-side critical sections.
+@@ -1446,17 +1446,19 @@ As far as memory models are concerned, RCU's main feature is its
+ Grace-Period Guarantee, which states that a critical section can never
+ span a full grace period.  In more detail, the Guarantee says:
+ 
+-	If a critical section starts before a grace period then it
+-	must end before the grace period does.  In addition, every
+-	store that propagates to the critical section's CPU before the
+-	end of the critical section must propagate to every CPU before
+-	the end of the grace period.
++	For any critical section C and any grace period G, at least
++	one of the following statements must hold:
+ 
+-	If a critical section ends after a grace period ends then it
+-	must start after the grace period does.  In addition, every
+-	store that propagates to the grace period's CPU before the
+-	start of the grace period must propagate to every CPU before
+-	the start of the critical section.
++(1)	C ends before G does, and in addition, every store that
++	propagates to C's CPU before the end of C must propagate to
++	every CPU before G ends.
++
++(2)	G starts before C does, and in addition, every store that
++	propagates to G's CPU before the start of G must propagate
++	to every CPU before C starts.
++
++In particular, it is not possible for a critical section to both start
++before and end after a grace period.
+ 
+ Here is a simple example of RCU in action:
+ 
+@@ -1483,10 +1485,11 @@ The Grace Period Guarantee tells us that when this code runs, it will
+ never end with r1 = 1 and r2 = 0.  The reasoning is as follows.  r1 = 1
+ means that P0's store to x propagated to P1 before P1 called
+ synchronize_rcu(), so P0's critical section must have started before
+-P1's grace period.  On the other hand, r2 = 0 means that P0's store to
+-y, which occurs before the end of the critical section, did not
+-propagate to P1 before the end of the grace period, violating the
+-Guarantee.
++P1's grace period, contrary to part (2) of the Guarantee.  On the
++other hand, r2 = 0 means that P0's store to y, which occurs before the
++end of the critical section, did not propagate to P1 before the end of
++the grace period, contrary to part (1).  Together the results violate
++the Guarantee.
+ 
+ In the kernel's implementations of RCU, the requirements for stores
+ to propagate to every CPU are fulfilled by placing strong fences at
+@@ -1504,11 +1507,11 @@ before" or "ends after" a grace period?  Some aspects of the meaning
+ are pretty obvious, as in the example above, but the details aren't
+ entirely clear.  The LKMM formalizes this notion by means of the
+ rcu-link relation.  rcu-link encompasses a very general notion of
+-"before": Among other things, X ->rcu-link Z includes cases where X
+-happens-before or is equal to some event Y which is equal to or comes
+-before Z in the coherence order.  When Y = Z this says that X ->rfe Z
+-implies X ->rcu-link Z.  In addition, when Y = X it says that X ->fr Z
+-and X ->co Z each imply X ->rcu-link Z.
++"before": If E and F are RCU fence events (i.e., rcu_read_lock(),
++rcu_read_unlock(), or synchronize_rcu()) then among other things,
++E ->rcu-link F includes cases where E is po-before some memory-access
++event X, F is po-after some memory-access event Y, and we have any of
++X ->rfe Y, X ->co Y, or X ->fr Y.
+ 
+ The formal definition of the rcu-link relation is more than a little
+ obscure, and we won't give it here.  It is closely related to the pb
+@@ -1516,171 +1519,173 @@ relation, and the details don't matter unless you want to comb through
+ a somewhat lengthy formal proof.  Pretty much all you need to know
+ about rcu-link is the information in the preceding paragraph.
+ 
+-The LKMM also defines the gp and rscs relations.  They bring grace
+-periods and read-side critical sections into the picture, in the
++The LKMM also defines the rcu-gp and rcu-rscsi relations.  They bring
++grace periods and read-side critical sections into the picture, in the
+ following way:
+ 
+-	E ->gp F means there is a synchronize_rcu() fence event S such
+-	that E ->po S and either S ->po F or S = F.  In simple terms,
+-	there is a grace period po-between E and F.
++	E ->rcu-gp F means that E and F are in fact the same event,
++	and that event is a synchronize_rcu() fence (i.e., a grace
++	period).
+ 
+-	E ->rscs F means there is a critical section delimited by an
+-	rcu_read_lock() fence L and an rcu_read_unlock() fence U, such
+-	that E ->po U and either L ->po F or L = F.  You can think of
+-	this as saying that E and F are in the same critical section
+-	(in fact, it also allows E to be po-before the start of the
+-	critical section and F to be po-after the end).
++	E ->rcu-rscsi F means that E and F are the rcu_read_unlock()
++	and rcu_read_lock() fence events delimiting some read-side
++	critical section.  (The 'i' at the end of the name emphasizes
++	that this relation is "inverted": It links the end of the
++	critical section to the start.)
+ 
+ If we think of the rcu-link relation as standing for an extended
+-"before", then X ->gp Y ->rcu-link Z says that X executes before a
+-grace period which ends before Z executes.  (In fact it covers more
+-than this, because it also includes cases where X executes before a
+-grace period and some store propagates to Z's CPU before Z executes
+-but doesn't propagate to some other CPU until after the grace period
+-ends.)  Similarly, X ->rscs Y ->rcu-link Z says that X is part of (or
+-before the start of) a critical section which starts before Z
+-executes.
+-
+-The LKMM goes on to define the rcu-fence relation as a sequence of gp
+-and rscs links separated by rcu-link links, in which the number of gp
+-links is >= the number of rscs links.  For example:
++"before", then X ->rcu-gp Y ->rcu-link Z roughly says that X is a
++grace period which ends before Z begins.  (In fact it covers more than
++this, because it also includes cases where some store propagates to
++Z's CPU before Z begins but doesn't propagate to some other CPU until
++after X ends.)  Similarly, X ->rcu-rscsi Y ->rcu-link Z says that X is
++the end of a critical section which starts before Z begins.
++
++The LKMM goes on to define the rcu-fence relation as a sequence of
++rcu-gp and rcu-rscsi links separated by rcu-link links, in which the
++number of rcu-gp links is >= the number of rcu-rscsi links.  For
++example:
+ 
+-	X ->gp Y ->rcu-link Z ->rscs T ->rcu-link U ->gp V
++	X ->rcu-gp Y ->rcu-link Z ->rcu-rscsi T ->rcu-link U ->rcu-gp V
+ 
+ would imply that X ->rcu-fence V, because this sequence contains two
+-gp links and only one rscs link.  (It also implies that X ->rcu-fence T
+-and Z ->rcu-fence V.)  On the other hand:
++rcu-gp links and one rcu-rscsi link.  (It also implies that
++X ->rcu-fence T and Z ->rcu-fence V.)  On the other hand:
+ 
+-	X ->rscs Y ->rcu-link Z ->rscs T ->rcu-link U ->gp V
++	X ->rcu-rscsi Y ->rcu-link Z ->rcu-rscsi T ->rcu-link U ->rcu-gp V
+ 
+ does not imply X ->rcu-fence V, because the sequence contains only
+-one gp link but two rscs links.
++one rcu-gp link but two rcu-rscsi links.
+ 
+ The rcu-fence relation is important because the Grace Period Guarantee
+ means that rcu-fence acts kind of like a strong fence.  In particular,
+-if W is a write and we have W ->rcu-fence Z, the Guarantee says that W
+-will propagate to every CPU before Z executes.
++E ->rcu-fence F implies not only that E begins before F ends, but also
++that any write po-before E will propagate to every CPU before any
++instruction po-after F can execute.  (However, it does not imply that
++E must execute before F; in fact, each synchronize_rcu() fence event
++is linked to itself by rcu-fence as a degenerate case.)
+ 
+ To prove this in full generality requires some intellectual effort.
+ We'll consider just a very simple case:
+ 
+-	W ->gp X ->rcu-link Y ->rscs Z.
++	G ->rcu-gp W ->rcu-link Z ->rcu-rscsi F.
+ 
+-This formula means that there is a grace period G and a critical
+-section C such that:
++This formula means that G and W are the same event (a grace period),
++and there are events X, Y and a read-side critical section C such that:
+ 
+-	1. W is po-before G;
++	1. G = W is po-before or equal to X;
+ 
+-	2. X is equal to or po-after G;
++	2. X comes "before" Y in some sense (including rfe, co and fr);
+ 
+-	3. X comes "before" Y in some sense;
++	2. Y is po-before Z;
+ 
+-	4. Y is po-before the end of C;
++	4. Z is the rcu_read_unlock() event marking the end of C;
+ 
+-	5. Z is equal to or po-after the start of C.
++	5. F is the rcu_read_lock() event marking the start of C.
+ 
+-From 2 - 4 we deduce that the grace period G ends before the critical
+-section C.  Then the second part of the Grace Period Guarantee says
+-not only that G starts before C does, but also that W (which executes
+-on G's CPU before G starts) must propagate to every CPU before C
+-starts.  In particular, W propagates to every CPU before Z executes
+-(or finishes executing, in the case where Z is equal to the
+-rcu_read_lock() fence event which starts C.)  This sort of reasoning
+-can be expanded to handle all the situations covered by rcu-fence.
++From 1 - 4 we deduce that the grace period G ends before the critical
++section C.  Then part (2) of the Grace Period Guarantee says not only
++that G starts before C does, but also that any write which executes on
++G's CPU before G starts must propagate to every CPU before C starts.
++In particular, the write propagates to every CPU before F finishes
++executing and hence before any instruction po-after F can execute.
++This sort of reasoning can be extended to handle all the situations
++covered by rcu-fence.
+ 
+ Finally, the LKMM defines the RCU-before (rb) relation in terms of
+ rcu-fence.  This is done in essentially the same way as the pb
+ relation was defined in terms of strong-fence.  We will omit the
+-details; the end result is that E ->rb F implies E must execute before
+-F, just as E ->pb F does (and for much the same reasons).
++details; the end result is that E ->rb F implies E must execute
++before F, just as E ->pb F does (and for much the same reasons).
+ 
+ Putting this all together, the LKMM expresses the Grace Period
+ Guarantee by requiring that the rb relation does not contain a cycle.
+-Equivalently, this "rcu" axiom requires that there are no events E and
+-F with E ->rcu-link F ->rcu-fence E.  Or to put it a third way, the
+-axiom requires that there are no cycles consisting of gp and rscs
+-alternating with rcu-link, where the number of gp links is >= the
+-number of rscs links.
++Equivalently, this "rcu" axiom requires that there are no events E
++and F with E ->rcu-link F ->rcu-fence E.  Or to put it a third way,
++the axiom requires that there are no cycles consisting of rcu-gp and
++rcu-rscsi alternating with rcu-link, where the number of rcu-gp links
++is >= the number of rcu-rscsi links.
+ 
+ Justifying the axiom isn't easy, but it is in fact a valid
+ formalization of the Grace Period Guarantee.  We won't attempt to go
+ through the detailed argument, but the following analysis gives a
+-taste of what is involved.  Suppose we have a violation of the first
+-part of the Guarantee: A critical section starts before a grace
+-period, and some store propagates to the critical section's CPU before
+-the end of the critical section but doesn't propagate to some other
+-CPU until after the end of the grace period.
++taste of what is involved.  Suppose both parts of the Guarantee are
++violated: A critical section starts before a grace period, and some
++store propagates to the critical section's CPU before the end of the
++critical section but doesn't propagate to some other CPU until after
++the end of the grace period.
+ 
+ Putting symbols to these ideas, let L and U be the rcu_read_lock() and
+ rcu_read_unlock() fence events delimiting the critical section in
+ question, and let S be the synchronize_rcu() fence event for the grace
+ period.  Saying that the critical section starts before S means there
+-are events E and F where E is po-after L (which marks the start of the
+-critical section), E is "before" F in the sense of the rcu-link
+-relation, and F is po-before the grace period S:
++are events Q and R where Q is po-after L (which marks the start of the
++critical section), Q is "before" R in the sense used by the rcu-link
++relation, and R is po-before the grace period S.  Thus we have:
+ 
+-	L ->po E ->rcu-link F ->po S.
++	L ->rcu-link S.
+ 
+-Let W be the store mentioned above, let Z come before the end of the
++Let W be the store mentioned above, let Y come before the end of the
+ critical section and witness that W propagates to the critical
+-section's CPU by reading from W, and let Y on some arbitrary CPU be a
+-witness that W has not propagated to that CPU, where Y happens after
++section's CPU by reading from W, and let Z on some arbitrary CPU be a
++witness that W has not propagated to that CPU, where Z happens after
+ some event X which is po-after S.  Symbolically, this amounts to:
+ 
+-	S ->po X ->hb* Y ->fr W ->rf Z ->po U.
++	S ->po X ->hb* Z ->fr W ->rf Y ->po U.
+ 
+-The fr link from Y to W indicates that W has not propagated to Y's CPU
+-at the time that Y executes.  From this, it can be shown (see the
+-discussion of the rcu-link relation earlier) that X and Z are related
+-by rcu-link, yielding:
++The fr link from Z to W indicates that W has not propagated to Z's CPU
++at the time that Z executes.  From this, it can be shown (see the
++discussion of the rcu-link relation earlier) that S and U are related
++by rcu-link:
+ 
+-	S ->po X ->rcu-link Z ->po U.
++	S ->rcu-link U.
+ 
+-The formulas say that S is po-between F and X, hence F ->gp X.  They
+-also say that Z comes before the end of the critical section and E
+-comes after its start, hence Z ->rscs E.  From all this we obtain:
++Since S is a grace period we have S ->rcu-gp S, and since L and U are
++the start and end of the critical section C we have U ->rcu-rscsi L.
++From this we obtain:
+ 
+-	F ->gp X ->rcu-link Z ->rscs E ->rcu-link F,
++	S ->rcu-gp S ->rcu-link U ->rcu-rscsi L ->rcu-link S,
+ 
+ a forbidden cycle.  Thus the "rcu" axiom rules out this violation of
+ the Grace Period Guarantee.
+ 
+ For something a little more down-to-earth, let's see how the axiom
+ works out in practice.  Consider the RCU code example from above, this
+-time with statement labels added to the memory access instructions:
++time with statement labels added:
+ 
+ 	int x, y;
+ 
+ 	P0()
+ 	{
+-		rcu_read_lock();
+-		W: WRITE_ONCE(x, 1);
+-		X: WRITE_ONCE(y, 1);
+-		rcu_read_unlock();
++		L: rcu_read_lock();
++		X: WRITE_ONCE(x, 1);
++		Y: WRITE_ONCE(y, 1);
++		U: rcu_read_unlock();
+ 	}
+ 
+ 	P1()
+ 	{
+ 		int r1, r2;
+ 
+-		Y: r1 = READ_ONCE(x);
+-		synchronize_rcu();
+-		Z: r2 = READ_ONCE(y);
++		Z: r1 = READ_ONCE(x);
++		S: synchronize_rcu();
++		W: r2 = READ_ONCE(y);
+ 	}
+ 
+ 
+-If r2 = 0 at the end then P0's store at X overwrites the value that
+-P1's load at Z reads from, so we have Z ->fre X and thus Z ->rcu-link X.
+-In addition, there is a synchronize_rcu() between Y and Z, so therefore
+-we have Y ->gp Z.
++If r2 = 0 at the end then P0's store at Y overwrites the value that
++P1's load at W reads from, so we have W ->fre Y.  Since S ->po W and
++also Y ->po U, we get S ->rcu-link U.  In addition, S ->rcu-gp S
++because S is a grace period.
+ 
+-If r1 = 1 at the end then P1's load at Y reads from P0's store at W,
+-so we have W ->rcu-link Y.  In addition, W and X are in the same critical
+-section, so therefore we have X ->rscs W.
++If r1 = 1 at the end then P1's load at Z reads from P0's store at X,
++so we have X ->rfe Z.  Together with L ->po X and Z ->po S, this
++yields L ->rcu-link S.  And since L and U are the start and end of a
++critical section, we have U ->rcu-rscsi L.
+ 
+-Then X ->rscs W ->rcu-link Y ->gp Z ->rcu-link X is a forbidden cycle,
+-violating the "rcu" axiom.  Hence the outcome is not allowed by the
+-LKMM, as we would expect.
++Then U ->rcu-rscsi L ->rcu-link S ->rcu-gp S ->rcu-link U is a
++forbidden cycle, violating the "rcu" axiom.  Hence the outcome is not
++allowed by the LKMM, as we would expect.
+ 
+ For contrast, let's see what can happen in a more complicated example:
+ 
+@@ -1690,51 +1695,52 @@ For contrast, let's see what can happen in a more complicated example:
+ 	{
+ 		int r0;
+ 
+-		rcu_read_lock();
+-		W: r0 = READ_ONCE(x);
+-		X: WRITE_ONCE(y, 1);
+-		rcu_read_unlock();
++		L0: rcu_read_lock();
++		    r0 = READ_ONCE(x);
++		    WRITE_ONCE(y, 1);
++		U0: rcu_read_unlock();
+ 	}
+ 
+ 	P1()
+ 	{
+ 		int r1;
+ 
+-		Y: r1 = READ_ONCE(y);
+-		synchronize_rcu();
+-		Z: WRITE_ONCE(z, 1);
++		    r1 = READ_ONCE(y);
++		S1: synchronize_rcu();
++		    WRITE_ONCE(z, 1);
+ 	}
+ 
+ 	P2()
+ 	{
+ 		int r2;
+ 
+-		rcu_read_lock();
+-		U: r2 = READ_ONCE(z);
+-		V: WRITE_ONCE(x, 1);
+-		rcu_read_unlock();
++		L2: rcu_read_lock();
++		    r2 = READ_ONCE(z);
++		    WRITE_ONCE(x, 1);
++		U2: rcu_read_unlock();
+ 	}
+ 
+ If r0 = r1 = r2 = 1 at the end, then similar reasoning to before shows
+-that W ->rscs X ->rcu-link Y ->gp Z ->rcu-link U ->rscs V ->rcu-link W.
+-However this cycle is not forbidden, because the sequence of relations
+-contains fewer instances of gp (one) than of rscs (two).  Consequently
+-the outcome is allowed by the LKMM.  The following instruction timing
+-diagram shows how it might actually occur:
++that U0 ->rcu-rscsi L0 ->rcu-link S1 ->rcu-gp S1 ->rcu-link U2 ->rcu-rscsi
++L2 ->rcu-link U0.  However this cycle is not forbidden, because the
++sequence of relations contains fewer instances of rcu-gp (one) than of
++rcu-rscsi (two).  Consequently the outcome is allowed by the LKMM.
++The following instruction timing diagram shows how it might actually
++occur:
+ 
+ P0			P1			P2
+ --------------------	--------------------	--------------------
+ rcu_read_lock()
+-X: WRITE_ONCE(y, 1)
+-			Y: r1 = READ_ONCE(y)
++WRITE_ONCE(y, 1)
++			r1 = READ_ONCE(y)
+ 			synchronize_rcu() starts
+ 			.			rcu_read_lock()
+-			.			V: WRITE_ONCE(x, 1)
+-W: r0 = READ_ONCE(x)	.
++			.			WRITE_ONCE(x, 1)
++r0 = READ_ONCE(x)	.
+ rcu_read_unlock()	.
+ 			synchronize_rcu() ends
+-			Z: WRITE_ONCE(z, 1)
+-						U: r2 = READ_ONCE(z)
++			WRITE_ONCE(z, 1)
++						r2 = READ_ONCE(z)
+ 						rcu_read_unlock()
+ 
+ This requires P0 and P2 to execute their loads and stores out of
+@@ -1744,6 +1750,15 @@ section in P0 both starts before P1's grace period does and ends
+ before it does, and the critical section in P2 both starts after P1's
+ grace period does and ends after it does.
+ 
++Addendum: The LKMM now supports SRCU (Sleepable Read-Copy-Update) in
++addition to normal RCU.  The ideas involved are much the same as
++above, with new relations srcu-gp and srcu-rscsi added to represent
++SRCU grace periods and read-side critical sections.  There is a
++restriction on the srcu-gp and srcu-rscsi links that can appear in an
++rcu-fence sequence (the srcu-rscsi links must be paired with srcu-gp
++links having the same SRCU domain with proper nesting); the details
++are relatively unimportant.
++
+ 
+ LOCKING
+ -------

commit a3f600d92da564ad35f237c8aeab268ca49377cc
+Author: Alan Stern 
+Date:   Thu Nov 15 11:20:37 2018 -0500
+
+    tools/memory-model: Add SRCU support
+    
+    Add support for SRCU.  Herd creates srcu events and linux-kernel.def
+    associates them with three possible annotations (srcu-lock,
+    srcu-unlock, and sync-srcu) corresponding to the API routines
+    srcu_read_lock(), srcu_read_unlock(), and synchronize_srcu().
+    
+    The linux-kernel.bell file now declares the annotations
+    and determines matching lock/unlock pairs delimiting SRCU read-side
+    critical sections, and it also checks for synchronize_srcu() calls
+    inside an RCU critical section (which would generate a "sleeping in
+    atomic context" error in real kernel code).  The linux-kernel.cat file
+    now adds SRCU-induced ordering, analogous to the existing RCU-induced
+    ordering, to the gp and rcu-fence relations.
+    
+    Curiously enough, these small changes to the model's .cat code are all
+    that is needed to describe SRCU.
+    
+    Portions of this patch (linux-kernel.def and the first hunk in
+    linux-kernel.bell) were written by Luc Maranget.
+    
+    Signed-off-by: Alan Stern 
+    CC: Luc Maranget 
+    Signed-off-by: Paul E. McKenney 
+    Tested-by: Andrea Parri 
+
+diff --git a/tools/memory-model/linux-kernel.bell b/tools/memory-model/linux-kernel.bell
+index 353c8d68e030..9c42cd9ddcb4 100644
+--- a/tools/memory-model/linux-kernel.bell
++++ b/tools/memory-model/linux-kernel.bell
+@@ -33,6 +33,12 @@ enum Barriers = 'wmb (*smp_wmb*) ||
+ 		'after-unlock-lock (*smp_mb__after_unlock_lock*)
+ instructions F[Barriers]
+ 
++(* SRCU *)
++enum SRCU = 'srcu-lock || 'srcu-unlock || 'sync-srcu
++instructions SRCU[SRCU]
++(* All srcu events *)
++let Srcu = Srcu-lock | Srcu-unlock | Sync-srcu
++
+ (* Compute matching pairs of nested Rcu-lock and Rcu-unlock *)
+ let rcu-rscs = let rec
+ 	    unmatched-locks = Rcu-lock \ domain(matched)
+@@ -48,3 +54,22 @@ let rcu-rscs = let rec
+ (* Validate nesting *)
+ flag ~empty Rcu-lock \ domain(rcu-rscs) as unbalanced-rcu-locking
+ flag ~empty Rcu-unlock \ range(rcu-rscs) as unbalanced-rcu-locking
++
++(* Compute matching pairs of nested Srcu-lock and Srcu-unlock *)
++let srcu-rscs = let rec
++	    unmatched-locks = Srcu-lock \ domain(matched)
++	and unmatched-unlocks = Srcu-unlock \ range(matched)
++	and unmatched = unmatched-locks | unmatched-unlocks
++	and unmatched-po = ([unmatched] ; po ; [unmatched]) & loc
++	and unmatched-locks-to-unlocks =
++		([unmatched-locks] ; po ; [unmatched-unlocks]) & loc
++	and matched = matched | (unmatched-locks-to-unlocks \
++		(unmatched-po ; unmatched-po))
++	in matched
++
++(* Validate nesting *)
++flag ~empty Srcu-lock \ domain(srcu-rscs) as unbalanced-srcu-locking
++flag ~empty Srcu-unlock \ range(srcu-rscs) as unbalanced-srcu-locking
++
++(* Check for use of synchronize_srcu() inside an RCU critical section *)
++flag ~empty rcu-rscs & (po ; [Sync-srcu] ; po) as invalid-sleep
+diff --git a/tools/memory-model/linux-kernel.cat b/tools/memory-model/linux-kernel.cat
+index b8e6197f05af..8dcb37835b61 100644
+--- a/tools/memory-model/linux-kernel.cat
++++ b/tools/memory-model/linux-kernel.cat
+@@ -33,7 +33,7 @@ let mb = ([M] ; fencerel(Mb) ; [M]) |
+ 	([M] ; po? ; [LKW] ; fencerel(After-spinlock) ; [M]) |
+ 	([M] ; po ; [UL] ; (co | po) ; [LKW] ;
+ 		fencerel(After-unlock-lock) ; [M])
+-let gp = po ; [Sync-rcu] ; po?
++let gp = po ; [Sync-rcu | Sync-srcu] ; po?
+ 
+ let strong-fence = mb | gp
+ 
+@@ -92,15 +92,18 @@ acyclic pb as propagation
+ 
+ (*
+  * Effects of read-side critical sections proceed from the rcu_read_unlock()
+- * backwards on the one hand, and from the rcu_read_lock() forwards on the
+- * other hand.
++ * or srcu_read_unlock() backwards on the one hand, and from the
++ * rcu_read_lock() or srcu_read_lock() forwards on the other hand.
+  *
+  * In the definition of rcu-fence below, the po term at the left-hand side
+  * of each disjunct and the po? term at the right-hand end have been factored
+  * out.  They have been moved into the definitions of rcu-link and rb.
++ * This was necessary in order to apply the "& loc" tests correctly.
+  *)
+ let rcu-gp = [Sync-rcu]		(* Compare with gp *)
++let srcu-gp = [Sync-srcu]
+ let rcu-rscsi = rcu-rscs^-1
++let srcu-rscsi = srcu-rscs^-1
+ 
+ (*
+  * The synchronize_rcu() strong fence is special in that it can order not
+@@ -112,12 +115,19 @@ let rcu-link = po? ; hb* ; pb* ; prop ; po
+ (*
+  * Any sequence containing at least as many grace periods as RCU read-side
+  * critical sections (joined by rcu-link) acts as a generalized strong fence.
++ * Likewise for SRCU grace periods and read-side critical sections, provided
++ * the synchronize_srcu() and srcu_read_[un]lock() calls refer to the same
++ * struct srcu_struct location.
+  *)
+-let rec rcu-fence = rcu-gp |
++let rec rcu-fence = rcu-gp | srcu-gp |
+ 	(rcu-gp ; rcu-link ; rcu-rscsi) |
++	((srcu-gp ; rcu-link ; srcu-rscsi) & loc) |
+ 	(rcu-rscsi ; rcu-link ; rcu-gp) |
++	((srcu-rscsi ; rcu-link ; srcu-gp) & loc) |
+ 	(rcu-gp ; rcu-link ; rcu-fence ; rcu-link ; rcu-rscsi) |
++	((srcu-gp ; rcu-link ; rcu-fence ; rcu-link ; srcu-rscsi) & loc) |
+ 	(rcu-rscsi ; rcu-link ; rcu-fence ; rcu-link ; rcu-gp) |
++	((srcu-rscsi ; rcu-link ; rcu-fence ; rcu-link ; srcu-gp) & loc) |
+ 	(rcu-fence ; rcu-link ; rcu-fence)
+ 
+ (* rb orders instructions just as pb does *)
+diff --git a/tools/memory-model/linux-kernel.def b/tools/memory-model/linux-kernel.def
+index b27911cc087d..1d6a120cde14 100644
+--- a/tools/memory-model/linux-kernel.def
++++ b/tools/memory-model/linux-kernel.def
+@@ -47,6 +47,11 @@ rcu_read_unlock() { __fence{rcu-unlock}; }
+ synchronize_rcu() { __fence{sync-rcu}; }
+ synchronize_rcu_expedited() { __fence{sync-rcu}; }
+ 
++// SRCU
++srcu_read_lock(X)  __srcu{srcu-lock}(X)
++srcu_read_unlock(X,Y) { __srcu{srcu-unlock}(X); }
++synchronize_srcu(X)  { __srcu{sync-srcu}(X); }
++
+ // Atomic
+ atomic_read(X) READ_ONCE(*X)
+ atomic_set(X,V) { WRITE_ONCE(*X,V); }

commit 284749b0aebbf3ab26ff92198545aea36165f6bf
+Author: Alan Stern 
+Date:   Thu Nov 15 11:19:58 2018 -0500
+
+    tools/memory-model: Refactor some RCU relations
+    
+    In preparation for adding support for SRCU, refactor the definitions
+    of rcu-fence, rcu-rscsi, rcu-link, and rb by moving the po and po?
+    terms from the first two to the second two.  An rcu-gp relation is
+    added; it is equivalent to gp with the po and po? terms removed.
+    
+    This is necessary because for SRCU, we will have to use the loc
+    relation to check that the terms at the start and end of each disjunct
+    in the definition of rcu-fence refer to the same srcu_struct
+    location.  If these terms are hidden behind po and po?, there's no way
+    to carry out this check.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Paul E. McKenney 
+    Tested-by: Andrea Parri 
+
+diff --git a/tools/memory-model/linux-kernel.cat b/tools/memory-model/linux-kernel.cat
+index ab9de9c1234b..b8e6197f05af 100644
+--- a/tools/memory-model/linux-kernel.cat
++++ b/tools/memory-model/linux-kernel.cat
+@@ -91,32 +91,37 @@ acyclic pb as propagation
+ (*******)
+ 
+ (*
+- * Effect of read-side critical section proceeds from the rcu_read_lock()
+- * onward on the one hand and from the rcu_read_unlock() backwards on the
++ * Effects of read-side critical sections proceed from the rcu_read_unlock()
++ * backwards on the one hand, and from the rcu_read_lock() forwards on the
+  * other hand.
++ *
++ * In the definition of rcu-fence below, the po term at the left-hand side
++ * of each disjunct and the po? term at the right-hand end have been factored
++ * out.  They have been moved into the definitions of rcu-link and rb.
+  *)
+-let rcu-rscsi = po ; rcu-rscs^-1 ; po?
++let rcu-gp = [Sync-rcu]		(* Compare with gp *)
++let rcu-rscsi = rcu-rscs^-1
+ 
+ (*
+  * The synchronize_rcu() strong fence is special in that it can order not
+  * one but two non-rf relations, but only in conjunction with an RCU
+  * read-side critical section.
+  *)
+-let rcu-link = hb* ; pb* ; prop
++let rcu-link = po? ; hb* ; pb* ; prop ; po
+ 
+ (*
+  * Any sequence containing at least as many grace periods as RCU read-side
+  * critical sections (joined by rcu-link) acts as a generalized strong fence.
+  *)
+-let rec rcu-fence = gp |
+-	(gp ; rcu-link ; rcu-rscsi) |
+-	(rcu-rscsi ; rcu-link ; gp) |
+-	(gp ; rcu-link ; rcu-fence ; rcu-link ; rcu-rscsi) |
+-	(rcu-rscsi ; rcu-link ; rcu-fence ; rcu-link ; gp) |
++let rec rcu-fence = rcu-gp |
++	(rcu-gp ; rcu-link ; rcu-rscsi) |
++	(rcu-rscsi ; rcu-link ; rcu-gp) |
++	(rcu-gp ; rcu-link ; rcu-fence ; rcu-link ; rcu-rscsi) |
++	(rcu-rscsi ; rcu-link ; rcu-fence ; rcu-link ; rcu-gp) |
+ 	(rcu-fence ; rcu-link ; rcu-fence)
+ 
+ (* rb orders instructions just as pb does *)
+-let rb = prop ; rcu-fence ; hb* ; pb*
++let rb = prop ; po ; rcu-fence ; po? ; hb* ; pb*
+ 
+ irreflexive rb as rcu
+ 

commit 0172d9e322035bf7bb66a7dfdd795c38d71dbba9
+Author: Alan Stern 
+Date:   Thu Nov 15 11:19:44 2018 -0500
+
+    tools/memory-model: Rename some RCU relations
+    
+    In preparation for adding support for SRCU, rename "crit" to
+    "rcu-rscs", rename "rscs" to "rcu-rscsi", and remove the restriction
+    to only the outermost level of nesting.
+    
+    The name change is needed for disambiguating RCU read-side critical
+    sections from SRCU read-side critical sections.  Adding the "i" at the
+    end of "rcu-rscsi" emphasizes that the relation is inverted; it links
+    rcu_read_unlock() events to their corresponding preceding
+    rcu_read_lock() events.
+    
+    The restriction to outermost nesting levels was never essential; it
+    was included mostly to show that it could be done.  Rather than add
+    equivalent unnecessary code for SRCU lock nesting, it seemed better to
+    remove the existing code.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Paul E. McKenney 
+    Tested-by: Andrea Parri 
+
+diff --git a/tools/memory-model/linux-kernel.bell b/tools/memory-model/linux-kernel.bell
+index 796513362c05..353c8d68e030 100644
+--- a/tools/memory-model/linux-kernel.bell
++++ b/tools/memory-model/linux-kernel.bell
+@@ -34,7 +34,7 @@ enum Barriers = 'wmb (*smp_wmb*) ||
+ instructions F[Barriers]
+ 
+ (* Compute matching pairs of nested Rcu-lock and Rcu-unlock *)
+-let matched = let rec
++let rcu-rscs = let rec
+ 	    unmatched-locks = Rcu-lock \ domain(matched)
+ 	and unmatched-unlocks = Rcu-unlock \ range(matched)
+ 	and unmatched = unmatched-locks | unmatched-unlocks
+@@ -46,8 +46,5 @@ let matched = let rec
+ 	in matched
+ 
+ (* Validate nesting *)
+-flag ~empty Rcu-lock \ domain(matched) as unbalanced-rcu-locking
+-flag ~empty Rcu-unlock \ range(matched) as unbalanced-rcu-locking
+-
+-(* Outermost level of nesting only *)
+-let crit = matched \ (po^-1 ; matched ; po^-1)
++flag ~empty Rcu-lock \ domain(rcu-rscs) as unbalanced-rcu-locking
++flag ~empty Rcu-unlock \ range(rcu-rscs) as unbalanced-rcu-locking
+diff --git a/tools/memory-model/linux-kernel.cat b/tools/memory-model/linux-kernel.cat
+index 8f23c74a96fd..ab9de9c1234b 100644
+--- a/tools/memory-model/linux-kernel.cat
++++ b/tools/memory-model/linux-kernel.cat
+@@ -95,7 +95,7 @@ acyclic pb as propagation
+  * onward on the one hand and from the rcu_read_unlock() backwards on the
+  * other hand.
+  *)
+-let rscs = po ; crit^-1 ; po?
++let rcu-rscsi = po ; rcu-rscs^-1 ; po?
+ 
+ (*
+  * The synchronize_rcu() strong fence is special in that it can order not
+@@ -109,10 +109,10 @@ let rcu-link = hb* ; pb* ; prop
+  * critical sections (joined by rcu-link) acts as a generalized strong fence.
+  *)
+ let rec rcu-fence = gp |
+-	(gp ; rcu-link ; rscs) |
+-	(rscs ; rcu-link ; gp) |
+-	(gp ; rcu-link ; rcu-fence ; rcu-link ; rscs) |
+-	(rscs ; rcu-link ; rcu-fence ; rcu-link ; gp) |
++	(gp ; rcu-link ; rcu-rscsi) |
++	(rcu-rscsi ; rcu-link ; gp) |
++	(gp ; rcu-link ; rcu-fence ; rcu-link ; rcu-rscsi) |
++	(rcu-rscsi ; rcu-link ; rcu-fence ; rcu-link ; gp) |
+ 	(rcu-fence ; rcu-link ; rcu-fence)
+ 
+ (* rb orders instructions just as pb does *)

commit 1e19a520a9258f3c7286826e7172e56bf6da86dc
+Author: Alan Stern 
+Date:   Tue Feb 5 14:33:02 2019 -0500
+
+    USB: gadget: Improve kerneldoc for usb_ep_dequeue()
+    
+    Commit bf594c1070f5 ("USB: gadget: Document that certain ep operations
+    can be called in interrupt context") documented that usb_ep_dequeue()
+    may be called in a non-process context.  It follows that the routine
+    must not sleep or wait for events.
+    
+    However, the routine's existing kerneldoc seems to imply that it will
+    wait until the request being cancelled has fully completed.  This is
+    not so, and thus the comment needs to be improved.  Misunderstanding
+    this point may very well have been responsible for a bug recently
+    uncovered in the f_fs function.
+    
+    The updated comment explicitly says that the routine may return before
+    the request's completion handler is called.
+    
+    Signed-off-by: Alan Stern 
+    CC: John Stultz 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
+index 87d6b12779f2..7cf34beb50df 100644
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -281,10 +281,10 @@ EXPORT_SYMBOL_GPL(usb_ep_queue);
+  * @ep:the endpoint associated with the request
+  * @req:the request being canceled
+  *
+- * If the request is still active on the endpoint, it is dequeued and its
+- * completion routine is called (with status -ECONNRESET); else a negative
+- * error code is returned. This is guaranteed to happen before the call to
+- * usb_ep_dequeue() returns.
++ * If the request is still active on the endpoint, it is dequeued and
++ * eventually its completion routine is called (with status -ECONNRESET);
++ * else a negative error code is returned.  This routine is asynchronous,
++ * that is, it may return before the completion routine runs.
+  *
+  * Note that some hardware can't clear out write fifos (to unlink the request
+  * at the head of the queue) except as part of disconnecting from usb. Such

commit d81bb019d7bb30091e3c796102c00935d6dd7ca9
+Author: Alan Stern 
+Date:   Wed Nov 28 11:25:58 2018 -0500
+
+    USB: Fix invalid-free bug in port_over_current_notify()
+    
+    Syzbot and KASAN found the following invalid-free bug in
+    port_over_current_notify():
+    
+    --------------------------------------------------------------------------
+    BUG: KASAN: double-free or invalid-free in port_over_current_notify
+    drivers/usb/core/hub.c:5192 [inline]
+    BUG: KASAN: double-free or invalid-free in port_event
+    drivers/usb/core/hub.c:5241 [inline]
+    BUG: KASAN: double-free or invalid-free in hub_event+0xd97/0x4140
+    drivers/usb/core/hub.c:5384
+    
+    CPU: 1 PID: 32710 Comm: kworker/1:3 Not tainted 4.20.0-rc3+ #129
+    Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
+    Google 01/01/2011
+    Workqueue: usb_hub_wq hub_event
+    Call Trace:
+      __dump_stack lib/dump_stack.c:77 [inline]
+      dump_stack+0x244/0x39d lib/dump_stack.c:113
+      print_address_description.cold.7+0x9/0x1ff mm/kasan/report.c:256
+      kasan_report_invalid_free+0x64/0xa0 mm/kasan/report.c:336
+      __kasan_slab_free+0x13a/0x150 mm/kasan/kasan.c:501
+      kasan_slab_free+0xe/0x10 mm/kasan/kasan.c:528
+      __cache_free mm/slab.c:3498 [inline]
+      kfree+0xcf/0x230 mm/slab.c:3817
+      port_over_current_notify drivers/usb/core/hub.c:5192 [inline]
+      port_event drivers/usb/core/hub.c:5241 [inline]
+      hub_event+0xd97/0x4140 drivers/usb/core/hub.c:5384
+      process_one_work+0xc90/0x1c40 kernel/workqueue.c:2153
+      worker_thread+0x17f/0x1390 kernel/workqueue.c:2296
+      kthread+0x35a/0x440 kernel/kthread.c:246
+      ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:352
+    --------------------------------------------------------------------------
+    
+    The problem is caused by use of a static array to store
+    environment-string pointers.  When the routine is called by multiple
+    threads concurrently, the pointers from one thread can overwrite those
+    from another.
+    
+    The solution is to use an ordinary automatic array instead of a static
+    array.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: syzbot+98881958e1410ec7e53c@syzkaller.appspotmail.com
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 0f9381b69a3b..528664059a12 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -5163,7 +5163,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ /* Handle notifying userspace about hub over-current events */
+ static void port_over_current_notify(struct usb_port *port_dev)
+ {
+-	static char *envp[] = { NULL, NULL, NULL };
++	char *envp[3];
+ 	struct device *hub_dev;
+ 	char *port_dev_path;
+ 
+@@ -5187,6 +5187,7 @@ static void port_over_current_notify(struct usb_port *port_dev)
+ 	if (!envp[1])
+ 		goto exit;
+ 
++	envp[2] = NULL;
+ 	kobject_uevent_env(&hub_dev->kobj, KOBJ_CHANGE, envp);
+ 
+ 	kfree(envp[1]);

commit 665c365a77fbfeabe52694aedf3446d5f2f1ce42
+Author: Alan Stern 
+Date:   Mon Oct 15 16:55:04 2018 -0400
+
+    USB: fix the usbfs flag sanitization for control transfers
+    
+    Commit 7a68d9fb8510 ("USB: usbdevfs: sanitize flags more") checks the
+    transfer flags for URBs submitted from userspace via usbfs.  However,
+    the check for whether the USBDEVFS_URB_SHORT_NOT_OK flag should be
+    allowed for a control transfer was added in the wrong place, before
+    the code has properly determined the direction of the control
+    transfer.  (Control transfers are special because for them, the
+    direction is set by the bRequestType byte of the Setup packet rather
+    than direction bit of the endpoint address.)
+    
+    This patch moves code which sets up the allow_short flag for control
+    transfers down after is_in has been set to the correct value.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: syzbot+24a30223a4b609bb802e@syzkaller.appspotmail.com
+    Fixes: 7a68d9fb8510 ("USB: usbdevfs: sanitize flags more")
+    CC: Oliver Neukum 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 244417d0dfd1..ffccd40ea67d 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -1474,8 +1474,6 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
+ 	u = 0;
+ 	switch (uurb->type) {
+ 	case USBDEVFS_URB_TYPE_CONTROL:
+-		if (is_in)
+-			allow_short = true;
+ 		if (!usb_endpoint_xfer_control(&ep->desc))
+ 			return -EINVAL;
+ 		/* min 8 byte setup packet */
+@@ -1505,6 +1503,8 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
+ 			is_in = 0;
+ 			uurb->endpoint &= ~USB_DIR_IN;
+ 		}
++		if (is_in)
++			allow_short = true;
+ 		snoop(&ps->dev->dev, "control urb: bRequestType=%02x "
+ 			"bRequest=%02x wValue=%04x "
+ 			"wIndex=%04x wLength=%04x\n",

commit 3b766f45355775fc5c404b7ff88f3fd3e9d77f86
+Author: Alan Stern 
+Date:   Tue Oct 2 10:18:40 2018 -0400
+
+    USB: net2280: Remove ->disconnect() callback from net2280_pullup()
+    
+    The net2280 UDC driver invokes the gadget driver's ->disconnect()
+    callback routine when the net2280_pullup() routine turns off the D+
+    pullup.  This is now unnecessary, because the gadget core performs the
+    callback on our behalf.  This patch removes the unneeded callback.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c
+index b02ab2a8d927..e7dae5379e04 100644
+--- a/drivers/usb/gadget/udc/net2280.c
++++ b/drivers/usb/gadget/udc/net2280.c
+@@ -1550,9 +1550,6 @@ static int net2280_pullup(struct usb_gadget *_gadget, int is_on)
+ 
+ 	spin_unlock_irqrestore(&dev->lock, flags);
+ 
+-	if (!is_on && dev->driver)
+-		dev->driver->disconnect(&dev->gadget);
+-
+ 	return 0;
+ }
+ 

commit 6e89e831a90172bc3d34ecbba52af5b9c4a447d1
+Author: Alan Stern 
+Date:   Wed Sep 26 11:29:17 2018 -0700
+
+    tools/memory-model: Add extra ordering for locks and remove it for ordinary release/acquire
+    
+    More than one kernel developer has expressed the opinion that the LKMM
+    should enforce ordering of writes by locking.  In other words, given
+    the following code:
+    
+            WRITE_ONCE(x, 1);
+            spin_unlock(&s):
+            spin_lock(&s);
+            WRITE_ONCE(y, 1);
+    
+    the stores to x and y should be propagated in order to all other CPUs,
+    even though those other CPUs might not access the lock s.  In terms of
+    the memory model, this means expanding the cumul-fence relation.
+    
+    Locks should also provide read-read (and read-write) ordering in a
+    similar way.  Given:
+    
+            READ_ONCE(x);
+            spin_unlock(&s);
+            spin_lock(&s);
+            READ_ONCE(y);           // or WRITE_ONCE(y, 1);
+    
+    the load of x should be executed before the load of (or store to) y.
+    The LKMM already provides this ordering, but it provides it even in
+    the case where the two accesses are separated by a release/acquire
+    pair of fences rather than unlock/lock.  This would prevent
+    architectures from using weakly ordered implementations of release and
+    acquire, which seems like an unnecessary restriction.  The patch
+    therefore removes the ordering requirement from the LKMM for that
+    case.
+    
+    There are several arguments both for and against this change.  Let us
+    refer to these enhanced ordering properties by saying that the LKMM
+    would require locks to be RCtso (a bit of a misnomer, but analogous to
+    RCpc and RCsc) and it would require ordinary acquire/release only to
+    be RCpc.  (Note: In the following, the phrase "all supported
+    architectures" is meant not to include RISC-V.  Although RISC-V is
+    indeed supported by the kernel, the implementation is still somewhat
+    in a state of flux and therefore statements about it would be
+    premature.)
+    
+    Pros:
+    
+            The kernel already provides RCtso ordering for locks on all
+            supported architectures, even though this is not stated
+            explicitly anywhere.  Therefore the LKMM should formalize it.
+    
+            In theory, guaranteeing RCtso ordering would reduce the need
+            for additional barrier-like constructs meant to increase the
+            ordering strength of locks.
+    
+            Will Deacon and Peter Zijlstra are strongly in favor of
+            formalizing the RCtso requirement.  Linus Torvalds and Will
+            would like to go even further, requiring locks to have RCsc
+            behavior (ordering preceding writes against later reads), but
+            they recognize that this would incur a noticeable performance
+            degradation on the POWER architecture.  Linus also points out
+            that people have made the mistake, in the past, of assuming
+            that locking has stronger ordering properties than is
+            currently guaranteed, and this change would reduce the
+            likelihood of such mistakes.
+    
+            Not requiring ordinary acquire/release to be any stronger than
+            RCpc may prove advantageous for future architectures, allowing
+            them to implement smp_load_acquire() and smp_store_release()
+            with more efficient machine instructions than would be
+            possible if the operations had to be RCtso.  Will and Linus
+            approve this rationale, hypothetical though it is at the
+            moment (it may end up affecting the RISC-V implementation).
+            The same argument may or may not apply to RMW-acquire/release;
+            see also the second Con entry below.
+    
+            Linus feels that locks should be easy for people to use
+            without worrying about memory consistency issues, since they
+            are so pervasive in the kernel, whereas acquire/release is
+            much more of an "experts only" tool.  Requiring locks to be
+            RCtso is a step in this direction.
+    
+    Cons:
+    
+            Andrea Parri and Luc Maranget think that locks should have the
+            same ordering properties as ordinary acquire/release (indeed,
+            Luc points out that the names "acquire" and "release" derive
+            from the usage of locks).  Andrea points out that having
+            different ordering properties for different forms of acquires
+            and releases is not only unnecessary, it would also be
+            confusing and unmaintainable.
+    
+            Locks are constructed from lower-level primitives, typically
+            RMW-acquire (for locking) and ordinary release (for unlock).
+            It is illogical to require stronger ordering properties from
+            the high-level operations than from the low-level operations
+            they comprise.  Thus, this change would make
+    
+                    while (cmpxchg_acquire(&s, 0, 1) != 0)
+                            cpu_relax();
+    
+            an incorrect implementation of spin_lock(&s) as far as the
+            LKMM is concerned.  In theory this weakness can be ameliorated
+            by changing the LKMM even further, requiring
+            RMW-acquire/release also to be RCtso (which it already is on
+            all supported architectures).
+    
+            As far as I know, nobody has singled out any examples of code
+            in the kernel that actually relies on locks being RCtso.
+            (People mumble about RCU and the scheduler, but nobody has
+            pointed to any actual code.  If there are any real cases,
+            their number is likely quite small.)  If RCtso ordering is not
+            needed, why require it?
+    
+            A handful of locking constructs (qspinlocks, qrwlocks, and
+            mcs_spinlocks) are built on top of smp_cond_load_acquire()
+            instead of an RMW-acquire instruction.  It currently provides
+            only the ordinary acquire semantics, not the stronger ordering
+            this patch would require of locks.  In theory this could be
+            ameliorated by requiring smp_cond_load_acquire() in
+            combination with ordinary release also to be RCtso (which is
+            currently true on all supported architectures).
+    
+            On future weakly ordered architectures, people may be able to
+            implement locks in a non-RCtso fashion with significant
+            performance improvement.  Meeting the RCtso requirement would
+            necessarily add run-time overhead.
+    
+    Overall, the technical aspects of these arguments seem relatively
+    minor, and it appears mostly to boil down to a matter of opinion.
+    Since the opinions of senior kernel maintainers such as Linus,
+    Peter, and Will carry more weight than those of Luc and Andrea, this
+    patch changes the model in accordance with the maintainers' wishes.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Paul E. McKenney 
+    Reviewed-by: Will Deacon 
+    Reviewed-by: Andrea Parri 
+    Acked-by: Peter Zijlstra (Intel) 
+    Cc: Alexander Shishkin 
+    Cc: Arnaldo Carvalho de Melo 
+    Cc: Jiri Olsa 
+    Cc: Linus Torvalds 
+    Cc: Peter Zijlstra 
+    Cc: Stephane Eranian 
+    Cc: Thomas Gleixner 
+    Cc: Vince Weaver 
+    Cc: akiyks@gmail.com
+    Cc: boqun.feng@gmail.com
+    Cc: dhowells@redhat.com
+    Cc: j.alglave@ucl.ac.uk
+    Cc: linux-arch@vger.kernel.org
+    Cc: luc.maranget@inria.fr
+    Cc: npiggin@gmail.com
+    Cc: parri.andrea@gmail.com
+    Link: http://lkml.kernel.org/r/20180926182920.27644-2-paulmck@linux.ibm.com
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/tools/memory-model/Documentation/explanation.txt b/tools/memory-model/Documentation/explanation.txt
+index 0cbd1ef8f86d..35bff92cc773 100644
+--- a/tools/memory-model/Documentation/explanation.txt
++++ b/tools/memory-model/Documentation/explanation.txt
+@@ -28,7 +28,8 @@ Explanation of the Linux-Kernel Memory Consistency Model
+   20. THE HAPPENS-BEFORE RELATION: hb
+   21. THE PROPAGATES-BEFORE RELATION: pb
+   22. RCU RELATIONS: rcu-link, gp, rscs, rcu-fence, and rb
+-  23. ODDS AND ENDS
++  23. LOCKING
++  24. ODDS AND ENDS
+ 
+ 
+ 
+@@ -1067,28 +1068,6 @@ allowing out-of-order writes like this to occur.  The model avoided
+ violating the write-write coherence rule by requiring the CPU not to
+ send the W write to the memory subsystem at all!)
+ 
+-There is one last example of preserved program order in the LKMM: when
+-a load-acquire reads from an earlier store-release.  For example:
+-
+-	smp_store_release(&x, 123);
+-	r1 = smp_load_acquire(&x);
+-
+-If the smp_load_acquire() ends up obtaining the 123 value that was
+-stored by the smp_store_release(), the LKMM says that the load must be
+-executed after the store; the store cannot be forwarded to the load.
+-This requirement does not arise from the operational model, but it
+-yields correct predictions on all architectures supported by the Linux
+-kernel, although for differing reasons.
+-
+-On some architectures, including x86 and ARMv8, it is true that the
+-store cannot be forwarded to the load.  On others, including PowerPC
+-and ARMv7, smp_store_release() generates object code that starts with
+-a fence and smp_load_acquire() generates object code that ends with a
+-fence.  The upshot is that even though the store may be forwarded to
+-the load, it is still true that any instruction preceding the store
+-will be executed before the load or any following instructions, and
+-the store will be executed before any instruction following the load.
+-
+ 
+ AND THEN THERE WAS ALPHA
+ ------------------------
+@@ -1766,6 +1745,147 @@ before it does, and the critical section in P2 both starts after P1's
+ grace period does and ends after it does.
+ 
+ 
++LOCKING
++-------
++
++The LKMM includes locking.  In fact, there is special code for locking
++in the formal model, added in order to make tools run faster.
++However, this special code is intended to be more or less equivalent
++to concepts we have already covered.  A spinlock_t variable is treated
++the same as an int, and spin_lock(&s) is treated almost the same as:
++
++	while (cmpxchg_acquire(&s, 0, 1) != 0)
++		cpu_relax();
++
++This waits until s is equal to 0 and then atomically sets it to 1,
++and the read part of the cmpxchg operation acts as an acquire fence.
++An alternate way to express the same thing would be:
++
++	r = xchg_acquire(&s, 1);
++
++along with a requirement that at the end, r = 0.  Similarly,
++spin_trylock(&s) is treated almost the same as:
++
++	return !cmpxchg_acquire(&s, 0, 1);
++
++which atomically sets s to 1 if it is currently equal to 0 and returns
++true if it succeeds (the read part of the cmpxchg operation acts as an
++acquire fence only if the operation is successful).  spin_unlock(&s)
++is treated almost the same as:
++
++	smp_store_release(&s, 0);
++
++The "almost" qualifiers above need some explanation.  In the LKMM, the
++store-release in a spin_unlock() and the load-acquire which forms the
++first half of the atomic rmw update in a spin_lock() or a successful
++spin_trylock() -- we can call these things lock-releases and
++lock-acquires -- have two properties beyond those of ordinary releases
++and acquires.
++
++First, when a lock-acquire reads from a lock-release, the LKMM
++requires that every instruction po-before the lock-release must
++execute before any instruction po-after the lock-acquire.  This would
++naturally hold if the release and acquire operations were on different
++CPUs, but the LKMM says it holds even when they are on the same CPU.
++For example:
++
++	int x, y;
++	spinlock_t s;
++
++	P0()
++	{
++		int r1, r2;
++
++		spin_lock(&s);
++		r1 = READ_ONCE(x);
++		spin_unlock(&s);
++		spin_lock(&s);
++		r2 = READ_ONCE(y);
++		spin_unlock(&s);
++	}
++
++	P1()
++	{
++		WRITE_ONCE(y, 1);
++		smp_wmb();
++		WRITE_ONCE(x, 1);
++	}
++
++Here the second spin_lock() reads from the first spin_unlock(), and
++therefore the load of x must execute before the load of y.  Thus we
++cannot have r1 = 1 and r2 = 0 at the end (this is an instance of the
++MP pattern).
++
++This requirement does not apply to ordinary release and acquire
++fences, only to lock-related operations.  For instance, suppose P0()
++in the example had been written as:
++
++	P0()
++	{
++		int r1, r2, r3;
++
++		r1 = READ_ONCE(x);
++		smp_store_release(&s, 1);
++		r3 = smp_load_acquire(&s);
++		r2 = READ_ONCE(y);
++	}
++
++Then the CPU would be allowed to forward the s = 1 value from the
++smp_store_release() to the smp_load_acquire(), executing the
++instructions in the following order:
++
++		r3 = smp_load_acquire(&s);	// Obtains r3 = 1
++		r2 = READ_ONCE(y);
++		r1 = READ_ONCE(x);
++		smp_store_release(&s, 1);	// Value is forwarded
++
++and thus it could load y before x, obtaining r2 = 0 and r1 = 1.
++
++Second, when a lock-acquire reads from a lock-release, and some other
++stores W and W' occur po-before the lock-release and po-after the
++lock-acquire respectively, the LKMM requires that W must propagate to
++each CPU before W' does.  For example, consider:
++
++	int x, y;
++	spinlock_t x;
++
++	P0()
++	{
++		spin_lock(&s);
++		WRITE_ONCE(x, 1);
++		spin_unlock(&s);
++	}
++
++	P1()
++	{
++		int r1;
++
++		spin_lock(&s);
++		r1 = READ_ONCE(x);
++		WRITE_ONCE(y, 1);
++		spin_unlock(&s);
++	}
++
++	P2()
++	{
++		int r2, r3;
++
++		r2 = READ_ONCE(y);
++		smp_rmb();
++		r3 = READ_ONCE(x);
++	}
++
++If r1 = 1 at the end then the spin_lock() in P1 must have read from
++the spin_unlock() in P0.  Hence the store to x must propagate to P2
++before the store to y does, so we cannot have r2 = 1 and r3 = 0.
++
++These two special requirements for lock-release and lock-acquire do
++not arise from the operational model.  Nevertheless, kernel developers
++have come to expect and rely on them because they do hold on all
++architectures supported by the Linux kernel, albeit for various
++differing reasons.
++
++
+ ODDS AND ENDS
+ -------------
+ 
+@@ -1831,26 +1951,6 @@ they behave as follows:
+ 	events and the events preceding them against all po-later
+ 	events.
+ 
+-The LKMM includes locking.  In fact, there is special code for locking
+-in the formal model, added in order to make tools run faster.
+-However, this special code is intended to be exactly equivalent to
+-concepts we have already covered.  A spinlock_t variable is treated
+-the same as an int, and spin_lock(&s) is treated the same as:
+-
+-	while (cmpxchg_acquire(&s, 0, 1) != 0)
+-		cpu_relax();
+-
+-which waits until s is equal to 0 and then atomically sets it to 1,
+-and where the read part of the atomic update is also an acquire fence.
+-An alternate way to express the same thing would be:
+-
+-	r = xchg_acquire(&s, 1);
+-
+-along with a requirement that at the end, r = 0.  spin_unlock(&s) is
+-treated the same as:
+-
+-	smp_store_release(&s, 0);
+-
+ Interestingly, RCU and locking each introduce the possibility of
+ deadlock.  When faced with code sequences such as:
+ 
+diff --git a/tools/memory-model/linux-kernel.cat b/tools/memory-model/linux-kernel.cat
+index 59b5cbe6b624..882fc33274ac 100644
+--- a/tools/memory-model/linux-kernel.cat
++++ b/tools/memory-model/linux-kernel.cat
+@@ -38,7 +38,7 @@ let strong-fence = mb | gp
+ (* Release Acquire *)
+ let acq-po = [Acquire] ; po ; [M]
+ let po-rel = [M] ; po ; [Release]
+-let rfi-rel-acq = [Release] ; rfi ; [Acquire]
++let po-unlock-rf-lock-po = po ; [UL] ; rf ; [LKR] ; po
+ 
+ (**********************************)
+ (* Fundamental coherence ordering *)
+@@ -60,13 +60,13 @@ let dep = addr | data
+ let rwdep = (dep | ctrl) ; [W]
+ let overwrite = co | fr
+ let to-w = rwdep | (overwrite & int)
+-let to-r = addr | (dep ; rfi) | rfi-rel-acq
++let to-r = addr | (dep ; rfi)
+ let fence = strong-fence | wmb | po-rel | rmb | acq-po
+-let ppo = to-r | to-w | fence
++let ppo = to-r | to-w | fence | (po-unlock-rf-lock-po & int)
+ 
+ (* Propagation: Ordering from release operations and strong fences. *)
+ let A-cumul(r) = rfe? ; r
+-let cumul-fence = A-cumul(strong-fence | po-rel) | wmb
++let cumul-fence = A-cumul(strong-fence | po-rel) | wmb | po-unlock-rf-lock-po
+ let prop = (overwrite & ext)? ; cumul-fence* ; rfe?
+ 
+ (*
+diff --git a/tools/memory-model/litmus-tests/ISA2+pooncelock+pooncelock+pombonce.litmus b/tools/memory-model/litmus-tests/ISA2+pooncelock+pooncelock+pombonce.litmus
+index 0f749e419b34..094d58df7789 100644
+--- a/tools/memory-model/litmus-tests/ISA2+pooncelock+pooncelock+pombonce.litmus
++++ b/tools/memory-model/litmus-tests/ISA2+pooncelock+pooncelock+pombonce.litmus
+@@ -1,11 +1,10 @@
+ C ISA2+pooncelock+pooncelock+pombonce
+ 
+ (*
+- * Result: Sometimes
++ * Result: Never
+  *
+- * This test shows that the ordering provided by a lock-protected S
+- * litmus test (P0() and P1()) are not visible to external process P2().
+- * This is likely to change soon.
++ * This test shows that write-write ordering provided by locks
++ * (in P0() and P1()) is visible to external process P2().
+  *)
+ 
+ {}

commit 0a55187a1ec8c03d0619e7ce41d10fdc39cff036
+Author: Alan Stern 
+Date:   Fri Aug 10 15:32:25 2018 -0400
+
+    USB: gadget core: Issue ->disconnect() callback from usb_gadget_disconnect()
+    
+    The gadget documentation doesn't state clearly whether a gadget
+    driver's ->disconnect() callback should be invoked when the D+ pullup
+    is turned off.  Some UDC drivers do this and some don't.  This patch
+    settles the issue by making the core function usb_gadget_disconnect()
+    issue the callback, so that UDC drivers don't need to worry about it.
+    
+    A description of the new behavior is added to the function's
+    kerneldoc.  Also, the patch removes a few superseded callbacks from
+    other core routines.
+    
+    Future patches will remove the ->disconnect() calls from the UDC
+    drivers that make them, as they are now unnecessary.  Until all those
+    patches are merged gadget drivers may receive extra ->disconnect()
+    callbacks, but this should be harmless.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
+index af88b48c1cea..87d6b12779f2 100644
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -690,6 +690,9 @@ EXPORT_SYMBOL_GPL(usb_gadget_connect);
+  * as a disconnect (when a VBUS session is active).  Not all systems
+  * support software pullup controls.
+  *
++ * Following a successful disconnect, invoke the ->disconnect() callback
++ * for the current gadget driver so that UDC drivers don't need to.
++ *
+  * Returns zero on success, else negative errno.
+  */
+ int usb_gadget_disconnect(struct usb_gadget *gadget)
+@@ -711,8 +714,10 @@ int usb_gadget_disconnect(struct usb_gadget *gadget)
+ 	}
+ 
+ 	ret = gadget->ops->pullup(gadget, 0);
+-	if (!ret)
++	if (!ret) {
+ 		gadget->connected = 0;
++		gadget->udc->driver->disconnect(gadget);
++	}
+ 
+ out:
+ 	trace_usb_gadget_disconnect(gadget, ret);
+@@ -1281,7 +1286,6 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
+ 	kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
+ 
+ 	usb_gadget_disconnect(udc->gadget);
+-	udc->driver->disconnect(udc->gadget);
+ 	udc->driver->unbind(udc->gadget);
+ 	usb_gadget_udc_stop(udc);
+ 
+@@ -1471,7 +1475,6 @@ static ssize_t soft_connect_store(struct device *dev,
+ 		usb_gadget_connect(udc->gadget);
+ 	} else if (sysfs_streq(buf, "disconnect")) {
+ 		usb_gadget_disconnect(udc->gadget);
+-		udc->driver->disconnect(udc->gadget);
+ 		usb_gadget_udc_stop(udc);
+ 	} else {
+ 		dev_err(dev, "unsupported command '%s'\n", buf);

commit c9a4cb204e9eb7fa7dfbe3f7d3a674fa530aa193
+Author: Alan Stern 
+Date:   Mon Sep 10 14:00:53 2018 -0400
+
+    USB: handle NULL config in usb_find_alt_setting()
+    
+    usb_find_alt_setting() takes a pointer to a struct usb_host_config as
+    an argument; it searches for an interface with specified interface and
+    alternate setting numbers in that config.  However, it crashes if the
+    usb_host_config pointer argument is NULL.
+    
+    Since this is a general-purpose routine, available for use in many
+    places, we want to to be more robust.  This patch makes it return NULL
+    whenever the config argument is NULL.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: syzbot+19c3aaef85a89d451eac@syzkaller.appspotmail.com
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 623be3174fb3..79d8bd7a612e 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -228,6 +228,8 @@ struct usb_host_interface *usb_find_alt_setting(
+ 	struct usb_interface_cache *intf_cache = NULL;
+ 	int i;
+ 
++	if (!config)
++		return NULL;
+ 	for (i = 0; i < config->desc.bNumInterfaces; i++) {
+ 		if (config->intf_cache[i]->altsetting[0].desc.bInterfaceNumber
+ 				== iface_num) {

commit bd729f9d67aa9a303d8925bb8c4f06af25f407d1
+Author: Alan Stern 
+Date:   Mon Sep 10 13:59:59 2018 -0400
+
+    USB: fix error handling in usb_driver_claim_interface()
+    
+    The syzbot fuzzing project found a use-after-free bug in the USB
+    core.  The bug was caused by usbfs not unbinding from an interface
+    when the USB device file was closed, which led another process to
+    attempt the unbind later on, after the private data structure had been
+    deallocated.
+    
+    The reason usbfs did not unbind the interface at the appropriate time
+    was because it thought the interface had never been claimed in the
+    first place.  This was caused by the fact that
+    usb_driver_claim_interface() does not clean up properly when
+    device_bind_driver() returns an error.  Although the error code gets
+    passed back to the caller, the iface->dev.driver pointer remains set
+    and iface->condition remains equal to USB_INTERFACE_BOUND.
+    
+    This patch adds proper error handling to usb_driver_claim_interface().
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: syzbot+f84aa7209ccec829536f@syzkaller.appspotmail.com
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 7652dcb57998..a1f225f077cd 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -550,6 +550,21 @@ int usb_driver_claim_interface(struct usb_driver *driver,
+ 	if (device_is_registered(dev))
+ 		retval = device_bind_driver(dev);
+ 
++	if (retval) {
++		dev->driver = NULL;
++		usb_set_intfdata(iface, NULL);
++		iface->needs_remote_wakeup = 0;
++		iface->condition = USB_INTERFACE_UNBOUND;
++
++		/*
++		 * Unbound interfaces are always runtime-PM-disabled
++		 * and runtime-PM-suspended
++		 */
++		if (driver->supports_autosuspend)
++			pm_runtime_disable(dev);
++		pm_runtime_set_suspended(dev);
++	}
++
+ 	return retval;
+ }
+ EXPORT_SYMBOL_GPL(usb_driver_claim_interface);

commit c183813fcee44a249339b7c46e1ad271ca1870aa
+Author: Alan Stern 
+Date:   Mon Sep 10 13:58:51 2018 -0400
+
+    USB: remove LPM management from usb_driver_claim_interface()
+    
+    usb_driver_claim_interface() disables and re-enables Link Power
+    Management, but it shouldn't do either one, for the reasons listed
+    below.  This patch removes the two LPM-related function calls from the
+    routine.
+    
+    The reason for disabling LPM in the analogous function
+    usb_probe_interface() is so that drivers won't have to deal with
+    unwanted LPM transitions in their probe routine.  But
+    usb_driver_claim_interface() doesn't call the driver's probe routine
+    (or any other callbacks), so that reason doesn't apply here.
+    
+    Furthermore, no driver other than usbfs will ever call
+    usb_driver_claim_interface() unless it is already bound to another
+    interface in the same device, which means disabling LPM here would be
+    redundant.  usbfs doesn't interact with LPM at all.
+    
+    Lastly, the error return from usb_unlocked_disable_lpm() isn't handled
+    properly; the code doesn't clean up its earlier actions before
+    returning.
+    
+    Signed-off-by: Alan Stern 
+    Fixes: 8306095fd2c1 ("USB: Disable USB 3.0 LPM in critical sections.")
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index e76e95f62f76..7652dcb57998 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -512,7 +512,6 @@ int usb_driver_claim_interface(struct usb_driver *driver,
+ 	struct device *dev;
+ 	struct usb_device *udev;
+ 	int retval = 0;
+-	int lpm_disable_error = -ENODEV;
+ 
+ 	if (!iface)
+ 		return -ENODEV;
+@@ -533,16 +532,6 @@ int usb_driver_claim_interface(struct usb_driver *driver,
+ 
+ 	iface->condition = USB_INTERFACE_BOUND;
+ 
+-	/* See the comment about disabling LPM in usb_probe_interface(). */
+-	if (driver->disable_hub_initiated_lpm) {
+-		lpm_disable_error = usb_unlocked_disable_lpm(udev);
+-		if (lpm_disable_error) {
+-			dev_err(&iface->dev, "%s Failed to disable LPM for driver %s\n",
+-				__func__, driver->name);
+-			return -ENOMEM;
+-		}
+-	}
+-
+ 	/* Claimed interfaces are initially inactive (suspended) and
+ 	 * runtime-PM-enabled, but only if the driver has autosuspend
+ 	 * support.  Otherwise they are marked active, to prevent the
+@@ -561,10 +550,6 @@ int usb_driver_claim_interface(struct usb_driver *driver,
+ 	if (device_is_registered(dev))
+ 		retval = device_bind_driver(dev);
+ 
+-	/* Attempt to re-enable USB3 LPM, if the disable was successful. */
+-	if (!lpm_disable_error)
+-		usb_unlocked_enable_lpm(udev);
+-
+ 	return retval;
+ }
+ EXPORT_SYMBOL_GPL(usb_driver_claim_interface);

commit 87f88dfcde0ecde2a1136b8364099dddb9895b12
+Author: Alan Stern 
+Date:   Tue Aug 28 10:57:25 2018 -0400
+
+    USB: OHCI: Remove USB bus reset delay from OHCI handover code
+    
+    Paul pointed out that the 50-ms sleep during OHCI initialization takes
+    up a large fraction of a system's boot time.  Things get worse when
+    there are two OHCI controllers present, each requiring 50 ms.
+    
+    However, there really is no need to send a 50-ms reset signal out all
+    the root-hub ports during initialization.  The ports themselves will
+    be disabled, and the only way to enable a port is to reset it.
+    Therefore all attached USB devices will receive a proper reset in any
+    case.  The controller reset does not need to be long enough to reset
+    those other devices, so the 50-ms delay isn't necessary.
+    
+    Without the delay, there is no remaining incentive for skipping the
+    reset when the controller is already in the RESET state.  This patch
+    removes the test, issuing the command unconditionally, and removes the
+    following delay.
+    
+    Signed-off-by: Alan Stern 
+    Suggested-by: Paul Menzel 
+    Tested-by: Paul Menzel 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
+index 3625a5c1a41b..3ce71cbfbb58 100644
+--- a/drivers/usb/host/pci-quirks.c
++++ b/drivers/usb/host/pci-quirks.c
+@@ -783,15 +783,9 @@ static void quirk_usb_handoff_ohci(struct pci_dev *pdev)
+ 	/* disable interrupts */
+ 	writel((u32) ~0, base + OHCI_INTRDISABLE);
+ 
+-	/* Reset the USB bus, if the controller isn't already in RESET */
+-	if (control & OHCI_HCFS) {
+-		/* Go into RESET, preserving RWC (and possibly IR) */
+-		writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL);
+-		readl(base + OHCI_CONTROL);
+-
+-		/* drive bus reset for at least 50 ms (7.1.7.5) */
+-		msleep(50);
+-	}
++	/* Go into the USB_RESET state, preserving RWC (and possibly IR) */
++	writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL);
++	readl(base + OHCI_CONTROL);
+ 
+ 	/* software reset of the controller, preserving HcFmInterval */
+ 	if (!no_fminterval)

commit dec3c23c9aa1815f07d98ae0375b4cbc10971e13
+Author: Alan Stern 
+Date:   Wed Aug 8 11:20:39 2018 -0400
+
+    USB: net2280: Fix erroneous synchronization change
+    
+    Commit f16443a034c7 ("USB: gadgetfs, dummy-hcd, net2280: fix locking
+    for callbacks") was based on a serious misunderstanding.  It
+    introduced regressions into both the dummy-hcd and net2280 drivers.
+    
+    The problem in dummy-hcd was fixed by commit 7dbd8f4cabd9 ("USB:
+    dummy-hcd: Fix erroneous synchronization change"), but the problem in
+    net2280 remains.  Namely: the ->disconnect(), ->suspend(), ->resume(),
+    and ->reset() callbacks must be invoked without the private lock held;
+    otherwise a deadlock will occur when the callback routine tries to
+    interact with the UDC driver.
+    
+    This patch largely is a reversion of the relevant parts of
+    f16443a034c7.  It also drops the private lock around the calls to
+    ->suspend() and ->resume() (something the earlier patch forgot to do).
+    This is safe from races with device interrupts because it occurs
+    within the interrupt handler.
+    
+    Finally, the patch changes where the ->disconnect() callback is
+    invoked when net2280_pullup() turns the pullup off.  Rather than
+    making the callback from within stop_activity() at a time when dropping
+    the private lock could be unsafe, the callback is moved to a point
+    after the lock has already been dropped.
+    
+    Signed-off-by: Alan Stern 
+    Fixes: f16443a034c7 ("USB: gadgetfs, dummy-hcd, net2280: fix locking for callbacks")
+    Reported-by: D. Ziesche 
+    Tested-by: D. Ziesche 
+    CC: 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c
+index 318246d8b2e2..b02ab2a8d927 100644
+--- a/drivers/usb/gadget/udc/net2280.c
++++ b/drivers/usb/gadget/udc/net2280.c
+@@ -1545,11 +1545,14 @@ static int net2280_pullup(struct usb_gadget *_gadget, int is_on)
+ 		writel(tmp | BIT(USB_DETECT_ENABLE), &dev->usb->usbctl);
+ 	} else {
+ 		writel(tmp & ~BIT(USB_DETECT_ENABLE), &dev->usb->usbctl);
+-		stop_activity(dev, dev->driver);
++		stop_activity(dev, NULL);
+ 	}
+ 
+ 	spin_unlock_irqrestore(&dev->lock, flags);
+ 
++	if (!is_on && dev->driver)
++		dev->driver->disconnect(&dev->gadget);
++
+ 	return 0;
+ }
+ 
+@@ -2466,8 +2469,11 @@ static void stop_activity(struct net2280 *dev, struct usb_gadget_driver *driver)
+ 		nuke(&dev->ep[i]);
+ 
+ 	/* report disconnect; the driver is already quiesced */
+-	if (driver)
++	if (driver) {
++		spin_unlock(&dev->lock);
+ 		driver->disconnect(&dev->gadget);
++		spin_lock(&dev->lock);
++	}
+ 
+ 	usb_reinit(dev);
+ }
+@@ -3341,6 +3347,8 @@ static void handle_stat0_irqs(struct net2280 *dev, u32 stat)
+ 		BIT(PCI_RETRY_ABORT_INTERRUPT))
+ 
+ static void handle_stat1_irqs(struct net2280 *dev, u32 stat)
++__releases(dev->lock)
++__acquires(dev->lock)
+ {
+ 	struct net2280_ep	*ep;
+ 	u32			tmp, num, mask, scratch;
+@@ -3381,12 +3389,14 @@ static void handle_stat1_irqs(struct net2280 *dev, u32 stat)
+ 			if (disconnect || reset) {
+ 				stop_activity(dev, dev->driver);
+ 				ep0_start(dev);
++				spin_unlock(&dev->lock);
+ 				if (reset)
+ 					usb_gadget_udc_reset
+ 						(&dev->gadget, dev->driver);
+ 				else
+ 					(dev->driver->disconnect)
+ 						(&dev->gadget);
++				spin_lock(&dev->lock);
+ 				return;
+ 			}
+ 		}
+@@ -3405,6 +3415,7 @@ static void handle_stat1_irqs(struct net2280 *dev, u32 stat)
+ 	tmp = BIT(SUSPEND_REQUEST_CHANGE_INTERRUPT);
+ 	if (stat & tmp) {
+ 		writel(tmp, &dev->regs->irqstat1);
++		spin_unlock(&dev->lock);
+ 		if (stat & BIT(SUSPEND_REQUEST_INTERRUPT)) {
+ 			if (dev->driver->suspend)
+ 				dev->driver->suspend(&dev->gadget);
+@@ -3415,6 +3426,7 @@ static void handle_stat1_irqs(struct net2280 *dev, u32 stat)
+ 				dev->driver->resume(&dev->gadget);
+ 			/* at high speed, note erratum 0133 */
+ 		}
++		spin_lock(&dev->lock);
+ 		stat &= ~tmp;
+ 	}
+ 

commit bf594c1070f5c34a2576a725eef69cba2686b98d
+Author: Alan Stern 
+Date:   Fri Jun 29 13:52:20 2018 -0400
+
+    USB: gadget: Document that certain ep operations can be called in interrupt context
+    
+    This documentation patch specifies that certain USB gadget endpoint
+    operations may be called in interrupt context:
+    
+            usb_ep_queue, usb_ep_dequeue, usb_ep_set_halt,
+            usb_ep_clear_halt, usb_ep_set_wedge, usb_ep_fifo_status,
+            and usb_ep_fifo_flush;
+    
+    while others must be called in process context:
+    
+            usb_ep_enable and usb_ep_disable.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
+index cab5e4f09924..af88b48c1cea 100644
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -87,6 +87,8 @@ EXPORT_SYMBOL_GPL(usb_ep_set_maxpacket_limit);
+  * configurable, with more generic names like "ep-a".  (remember that for
+  * USB, "in" means "towards the USB master".)
+  *
++ * This routine must be called in process context.
++ *
+  * returns zero, or a negative error code.
+  */
+ int usb_ep_enable(struct usb_ep *ep)
+@@ -119,6 +121,8 @@ EXPORT_SYMBOL_GPL(usb_ep_enable);
+  * gadget drivers must call usb_ep_enable() again before queueing
+  * requests to the endpoint.
+  *
++ * This routine must be called in process context.
++ *
+  * returns zero, or a negative error code.
+  */
+ int usb_ep_disable(struct usb_ep *ep)
+@@ -241,6 +245,8 @@ EXPORT_SYMBOL_GPL(usb_ep_free_request);
+  * Note that @req's ->complete() callback must never be called from
+  * within usb_ep_queue() as that can create deadlock situations.
+  *
++ * This routine may be called in interrupt context.
++ *
+  * Returns zero, or a negative error code.  Endpoints that are not enabled
+  * report errors; errors will also be
+  * reported when the usb peripheral is disconnected.
+@@ -284,6 +290,8 @@ EXPORT_SYMBOL_GPL(usb_ep_queue);
+  * at the head of the queue) except as part of disconnecting from usb. Such
+  * restrictions prevent drivers from supporting configuration changes,
+  * even to configuration zero (a "chapter 9" requirement).
++ *
++ * This routine may be called in interrupt context.
+  */
+ int usb_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
+ {
+@@ -311,6 +319,8 @@ EXPORT_SYMBOL_GPL(usb_ep_dequeue);
+  * current altsetting, see usb_ep_clear_halt().  When switching altsettings,
+  * it's simplest to use usb_ep_enable() or usb_ep_disable() for the endpoints.
+  *
++ * This routine may be called in interrupt context.
++ *
+  * Returns zero, or a negative error code.  On success, this call sets
+  * underlying hardware state that blocks data transfers.
+  * Attempts to halt IN endpoints will fail (returning -EAGAIN) if any
+@@ -336,6 +346,8 @@ EXPORT_SYMBOL_GPL(usb_ep_set_halt);
+  * for endpoints that aren't reconfigured, after clearing any other state
+  * in the endpoint's i/o queue.
+  *
++ * This routine may be called in interrupt context.
++ *
+  * Returns zero, or a negative error code.  On success, this call clears
+  * the underlying hardware state reflecting endpoint halt and data toggle.
+  * Note that some hardware can't support this request (like pxa2xx_udc),
+@@ -360,6 +372,8 @@ EXPORT_SYMBOL_GPL(usb_ep_clear_halt);
+  * requests. If the gadget driver clears the halt status, it will
+  * automatically unwedge the endpoint.
+  *
++ * This routine may be called in interrupt context.
++ *
+  * Returns zero on success, else negative errno.
+  */
+ int usb_ep_set_wedge(struct usb_ep *ep)
+@@ -388,6 +402,8 @@ EXPORT_SYMBOL_GPL(usb_ep_set_wedge);
+  * written OUT to it by the host.  Drivers that need precise handling for
+  * fault reporting or recovery may need to use this call.
+  *
++ * This routine may be called in interrupt context.
++ *
+  * This returns the number of such bytes in the fifo, or a negative
+  * errno if the endpoint doesn't use a FIFO or doesn't support such
+  * precise handling.
+@@ -415,6 +431,8 @@ EXPORT_SYMBOL_GPL(usb_ep_fifo_status);
+  * an endpoint fifo after abnormal transaction terminations.  The call
+  * must never be used except when endpoint is not being used for any
+  * protocol translation.
++ *
++ * This routine may be called in interrupt context.
+  */
+ void usb_ep_fifo_flush(struct usb_ep *ep)
+ {

commit 8f9cc83c06d44081d7c7e179f778cbeb4d074fa7
+Author: Alan Stern 
+Date:   Fri Jun 8 16:59:57 2018 -0400
+
+    USB: xhci-hcd: Add get_resuming_ports method
+    
+    This patch adds support for the new get_resuming_ports HCD method to
+    the xhci-hcd driver.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Mathias Nyman 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
+index a4b95d019f84..7e2a531ba321 100644
+--- a/drivers/usb/host/xhci-hub.c
++++ b/drivers/usb/host/xhci-hub.c
+@@ -1684,4 +1684,15 @@ int xhci_bus_resume(struct usb_hcd *hcd)
+ 	return 0;
+ }
+ 
++unsigned long xhci_get_resuming_ports(struct usb_hcd *hcd)
++{
++	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
++	struct xhci_bus_state *bus_state;
++
++	bus_state = &xhci->bus_state[hcd_index(hcd)];
++
++	/* USB3 port wakeups are reported via usb_wakeup_notification() */
++	return bus_state->resuming_ports;	/* USB2 ports only */
++}
++
+ #endif	/* CONFIG_PM */
+diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
+index 8c8da2d657fa..2f239cb3deaf 100644
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -5081,6 +5081,7 @@ static const struct hc_driver xhci_hc_driver = {
+ 	.hub_status_data =	xhci_hub_status_data,
+ 	.bus_suspend =		xhci_bus_suspend,
+ 	.bus_resume =		xhci_bus_resume,
++	.get_resuming_ports =	xhci_get_resuming_ports,
+ 
+ 	/*
+ 	 * call back when device connected and addressed
+diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
+index 939e2f86b595..ece5891240f0 100644
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -2110,9 +2110,11 @@ void xhci_hc_died(struct xhci_hcd *xhci);
+ #ifdef CONFIG_PM
+ int xhci_bus_suspend(struct usb_hcd *hcd);
+ int xhci_bus_resume(struct usb_hcd *hcd);
++unsigned long xhci_get_resuming_ports(struct usb_hcd *hcd);
+ #else
+ #define	xhci_bus_suspend	NULL
+ #define	xhci_bus_resume		NULL
++#define	xhci_get_resuming_ports	NULL
+ #endif	/* CONFIG_PM */
+ 
+ u32 xhci_port_state_to_neutral(u32 state);

commit 00d423c8d0132915f4204b330343420c271b9142
+Author: Alan Stern 
+Date:   Fri Jun 8 16:59:50 2018 -0400
+
+    USB: ehci-hcd: Add get_resuming_ports method
+    
+    This patch adds support for the new get_resuming_ports HCD method to
+    the ehci-hcd driver.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 89c47ae5c7d3..8608ac513fb7 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1226,6 +1226,7 @@ static const struct hc_driver ehci_hc_driver = {
+ 	.bus_resume =		ehci_bus_resume,
+ 	.relinquish_port =	ehci_relinquish_port,
+ 	.port_handed_over =	ehci_port_handed_over,
++	.get_resuming_ports =	ehci_get_resuming_ports,
+ 
+ 	/*
+ 	 * device support
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index d7641cbdee43..ce0eaf7d7c12 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -512,10 +512,18 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 	return -ESHUTDOWN;
+ }
+ 
++static unsigned long ehci_get_resuming_ports(struct usb_hcd *hcd)
++{
++	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
++
++	return ehci->resuming_ports;
++}
++
+ #else
+ 
+ #define ehci_bus_suspend	NULL
+ #define ehci_bus_resume		NULL
++#define ehci_get_resuming_ports	NULL
+ 
+ #endif	/* CONFIG_PM */
+ 

commit 379cacc5e566f7197bdeb1ea3e99219d3e880c0a
+Author: Alan Stern 
+Date:   Fri Jun 8 16:59:37 2018 -0400
+
+    USB: Report wakeup events on root-hub ports
+    
+    When a USB device attached to a root-hub port sends a wakeup request
+    to a sleeping system, we do not report the wakeup event to the PM
+    core.  This is because a system resume involves waking up all
+    suspended USB ports as quickly as possible; without the normal
+    USB_RESUME_TIMEOUT delay, the host controller driver doesn't set the
+    USB_PORT_STAT_C_SUSPEND flag and so usb_port_resume() doesn't realize
+    that a wakeup request was received.
+    
+    However, some environments (such as Chrome OS) want to have all wakeup
+    events reported so they can be ascribed to the appropriate device.  To
+    accommodate these environments, this patch adds a new routine to the
+    hub driver and a corresponding new HCD method to be used when a root
+    hub resumes.  The HCD method returns a bitmap of ports that have
+    initiated a wakeup signal but not yet completed resuming.  The hub
+    driver can then report to the PM core that the child devices attached
+    to these ports initiated a wakeup event.
+    
+    Signed-off-by: Alan Stern 
+    Suggested-by: Anshuman Gupta 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index fcae521df29b..fef5af7aab92 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -3656,12 +3656,54 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+ 	return 0;
+ }
+ 
++/* Report wakeup requests from the ports of a resuming root hub */
++static void report_wakeup_requests(struct usb_hub *hub)
++{
++	struct usb_device	*hdev = hub->hdev;
++	struct usb_device	*udev;
++	struct usb_hcd		*hcd;
++	unsigned long		resuming_ports;
++	int			i;
++
++	if (hdev->parent)
++		return;		/* Not a root hub */
++
++	hcd = bus_to_hcd(hdev->bus);
++	if (hcd->driver->get_resuming_ports) {
++
++		/*
++		 * The get_resuming_ports() method returns a bitmap (origin 0)
++		 * of ports which have started wakeup signaling but have not
++		 * yet finished resuming.  During system resume we will
++		 * resume all the enabled ports, regardless of any wakeup
++		 * signals, which means the wakeup requests would be lost.
++		 * To prevent this, report them to the PM core here.
++		 */
++		resuming_ports = hcd->driver->get_resuming_ports(hcd);
++		for (i = 0; i < hdev->maxchild; ++i) {
++			if (test_bit(i, &resuming_ports)) {
++				udev = hub->ports[i]->child;
++				if (udev)
++					pm_wakeup_event(&udev->dev, 0);
++			}
++		}
++	}
++}
++
+ static int hub_resume(struct usb_interface *intf)
+ {
+ 	struct usb_hub *hub = usb_get_intfdata(intf);
+ 
+ 	dev_dbg(&intf->dev, "%s\n", __func__);
+ 	hub_activate(hub, HUB_RESUME);
++
++	/*
++	 * This should be called only for system resume, not runtime resume.
++	 * We can't tell the difference here, so some wakeup requests will be
++	 * reported at the wrong time or more than once.  This shouldn't
++	 * matter much, so long as they do get reported.
++	 */
++	report_wakeup_requests(hub);
+ 	return 0;
+ }
+ 
+diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
+index 34a6ded6f319..97e2ddec18b1 100644
+--- a/include/linux/usb/hcd.h
++++ b/include/linux/usb/hcd.h
+@@ -322,6 +322,7 @@ struct hc_driver {
+ 	int	(*bus_suspend)(struct usb_hcd *);
+ 	int	(*bus_resume)(struct usb_hcd *);
+ 	int	(*start_port_reset)(struct usb_hcd *, unsigned port_num);
++	unsigned long	(*get_resuming_ports)(struct usb_hcd *);
+ 
+ 		/* force handover of high-speed port to full-speed companion */
+ 	void	(*relinquish_port)(struct usb_hcd *, int);

commit cee0321a404fe6b43d1f4364639c8ffe2f2b37d1
+Author: Alan Stern 
+Date:   Mon May 14 16:33:53 2018 -0700
+
+    tools/memory-model: Remove out-of-date comments and code from lock.cat
+    
+    lock.cat contains old comments and code referring to the possibility
+    of LKR events that are not part of an RMW pair.  This is a holdover
+    from when I though we might end up using LKR events to implement
+    spin_is_locked().  Reword the comments to remove this assumption and
+    replace domain(lk-rmw) in the code with LKR.
+    
+    Tested-by: Andrea Parri 
+    [ paulmck: Pulled as lock-nest into previous line as discussed. ]
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Paul E. McKenney 
+    Cc: Akira Yokosawa 
+    Cc: Andrew Morton 
+    Cc: Boqun Feng 
+    Cc: David Howells 
+    Cc: Jade Alglave 
+    Cc: Linus Torvalds 
+    Cc: Luc Maranget 
+    Cc: Nicholas Piggin 
+    Cc: Peter Zijlstra 
+    Cc: Thomas Gleixner 
+    Cc: Will Deacon 
+    Cc: linux-arch@vger.kernel.org
+    Cc: parri.andrea@gmail.com
+    Link: http://lkml.kernel.org/r/1526340837-12222-15-git-send-email-paulmck@linux.vnet.ibm.com
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/tools/memory-model/lock.cat b/tools/memory-model/lock.cat
+index 7217cd4941a4..cd002a33ca8a 100644
+--- a/tools/memory-model/lock.cat
++++ b/tools/memory-model/lock.cat
+@@ -47,18 +47,15 @@ flag ~empty [M \ IW] ; loc ; [ALL-LOCKS] as mixed-lock-accesses
+ let lk-rmw = ([LKR] ; po-loc ; [LKW]) \ (po ; po)
+ let rmw = rmw | lk-rmw
+ 
++(* The litmus test is invalid if an LKR/LKW event is not part of an RMW pair *)
++flag ~empty LKW \ range(lk-rmw) as unpaired-LKW
++flag ~empty LKR \ domain(lk-rmw) as unpaired-LKR
++
+ (*
+- * A paired LKR must always see an unlocked value; spin_lock() calls nested
++ * An LKR must always see an unlocked value; spin_lock() calls nested
+  * inside a critical section (for the same lock) always deadlock.
+  *)
+-empty ([LKW] ; po-loc ; [domain(lk-rmw)]) \ (po-loc ; [UL] ; po-loc)
+-	as lock-nest
+-
+-(* The litmus test is invalid if an LKW event is not part of an RMW pair *)
+-flag ~empty LKW \ range(lk-rmw) as unpaired-LKW
+-
+-(* This will be allowed if we implement spin_is_locked() *)
+-flag ~empty LKR \ domain(lk-rmw) as unpaired-LKR
++empty ([LKW] ; po-loc ; [LKR]) \ (po-loc ; [UL] ; po-loc) as lock-nest
+ 
+ (* The final value of a spinlock should not be tested *)
+ flag ~empty [FW] ; loc ; [ALL-LOCKS] as lock-final

commit 30b795df11a1a9dd7fc50c1ff4677343b67cb379
+Author: Alan Stern 
+Date:   Mon May 14 16:33:52 2018 -0700
+
+    tools/memory-model: Improve mixed-access checking in lock.cat
+    
+    The code in lock.cat which checks for normal read/write accesses to
+    spinlock variables doesn't take into account the newly added RL and RU
+    events.  Add them into the test, and move the resulting code up near
+    the start of the file, since a violation would indicate a pretty
+    severe conceptual error in a litmus test.
+    
+    Tested-by: Andrea Parri 
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Paul E. McKenney 
+    Cc: Akira Yokosawa 
+    Cc: Andrew Morton 
+    Cc: Boqun Feng 
+    Cc: David Howells 
+    Cc: Jade Alglave 
+    Cc: Linus Torvalds 
+    Cc: Luc Maranget 
+    Cc: Nicholas Piggin 
+    Cc: Peter Zijlstra 
+    Cc: Thomas Gleixner 
+    Cc: Will Deacon 
+    Cc: linux-arch@vger.kernel.org
+    Cc: parri.andrea@gmail.com
+    Link: http://lkml.kernel.org/r/1526340837-12222-14-git-send-email-paulmck@linux.vnet.ibm.com
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/tools/memory-model/lock.cat b/tools/memory-model/lock.cat
+index df74de2148f6..7217cd4941a4 100644
+--- a/tools/memory-model/lock.cat
++++ b/tools/memory-model/lock.cat
+@@ -32,6 +32,17 @@ include "cross.cat"
+  * LKW, LF, RL, and RU have no ordering properties.
+  *)
+ 
++(* Backward compatibility *)
++let RL = try RL with emptyset
++let RU = try RU with emptyset
++
++(* Treat RL as a kind of LF: a read with no ordering properties *)
++let LF = LF | RL
++
++(* There should be no ordinary R or W accesses to spinlocks *)
++let ALL-LOCKS = LKR | LKW | UL | LF | RU
++flag ~empty [M \ IW] ; loc ; [ALL-LOCKS] as mixed-lock-accesses
++
+ (* Link Lock-Reads to their RMW-partner Lock-Writes *)
+ let lk-rmw = ([LKR] ; po-loc ; [LKW]) \ (po ; po)
+ let rmw = rmw | lk-rmw
+@@ -49,20 +60,9 @@ flag ~empty LKW \ range(lk-rmw) as unpaired-LKW
+ (* This will be allowed if we implement spin_is_locked() *)
+ flag ~empty LKR \ domain(lk-rmw) as unpaired-LKR
+ 
+-(* There should be no ordinary R or W accesses to spinlocks *)
+-let ALL-LOCKS = LKR | LKW | UL | LF
+-flag ~empty [M \ IW] ; loc ; [ALL-LOCKS] as mixed-lock-accesses
+-
+ (* The final value of a spinlock should not be tested *)
+ flag ~empty [FW] ; loc ; [ALL-LOCKS] as lock-final
+ 
+-(* Backward compatibility *)
+-let RL = try RL with emptyset
+-let RU = try RU with emptyset
+-
+-(* Treat RL as a kind of LF: a read with no ordering properties *)
+-let LF = LF | RL
+-
+ (*
+  * Put lock operations in their appropriate classes, but leave UL out of W
+  * until after the co relation has been generated.

commit fd0359dbac3df00d1c6c22769e7d647b16b920cc
+Author: Alan Stern 
+Date:   Mon May 14 16:33:51 2018 -0700
+
+    tools/memory-model: Improve comments in lock.cat
+    
+    This patch improves the comments in tools/memory-model/lock.cat.  In
+    addition to making the text more uniform and removing redundant
+    comments, it adds a description of all the possible locking events
+    that herd can generate.
+    
+    Tested-by: Andrea Parri 
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Paul E. McKenney 
+    Cc: Akira Yokosawa 
+    Cc: Andrew Morton 
+    Cc: Boqun Feng 
+    Cc: David Howells 
+    Cc: Jade Alglave 
+    Cc: Linus Torvalds 
+    Cc: Luc Maranget 
+    Cc: Nicholas Piggin 
+    Cc: Peter Zijlstra 
+    Cc: Thomas Gleixner 
+    Cc: Will Deacon 
+    Cc: linux-arch@vger.kernel.org
+    Cc: parri.andrea@gmail.com
+    Link: http://lkml.kernel.org/r/1526340837-12222-13-git-send-email-paulmck@linux.vnet.ibm.com
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/tools/memory-model/lock.cat b/tools/memory-model/lock.cat
+index 1f6d67e79065..df74de2148f6 100644
+--- a/tools/memory-model/lock.cat
++++ b/tools/memory-model/lock.cat
+@@ -4,15 +4,35 @@
+  * Copyright (C) 2017 Alan Stern 
+  *)
+ 
+-(* Generate coherence orders and handle lock operations *)
+ (*
+- * Warning, crashes with herd7 versions strictly before 7.48.
+- * spin_islocked is functional from version 7.49.
++ * Generate coherence orders and handle lock operations
+  *
++ * Warning: spin_is_locked() crashes herd7 versions strictly before 7.48.
++ * spin_is_locked() is functional from herd7 version 7.49.
+  *)
++
+ include "cross.cat"
+ 
+-(* From lock reads to their partner lock writes *)
++(*
++ * The lock-related events generated by herd are as follows:
++ *
++ * LKR		Lock-Read: the read part of a spin_lock() or successful
++ *			spin_trylock() read-modify-write event pair
++ * LKW		Lock-Write: the write part of a spin_lock() or successful
++ *			spin_trylock() RMW event pair
++ * UL		Unlock: a spin_unlock() event
++ * LF		Lock-Fail: a failed spin_trylock() event
++ * RL		Read-Locked: a spin_is_locked() event which returns True
++ * RU		Read-Unlocked: a spin_is_locked() event which returns False
++ *
++ * LKR and LKW events always come paired, like all RMW event sequences.
++ *
++ * LKR, LF, RL, and RU are read events; LKR has Acquire ordering.
++ * LKW and UL are write events; UL has Release ordering.
++ * LKW, LF, RL, and RU have no ordering properties.
++ *)
++
++(* Link Lock-Reads to their RMW-partner Lock-Writes *)
+ let lk-rmw = ([LKR] ; po-loc ; [LKW]) \ (po ; po)
+ let rmw = rmw | lk-rmw
+ 
+@@ -29,18 +49,16 @@ flag ~empty LKW \ range(lk-rmw) as unpaired-LKW
+ (* This will be allowed if we implement spin_is_locked() *)
+ flag ~empty LKR \ domain(lk-rmw) as unpaired-LKR
+ 
+-(* There should be no R or W accesses to spinlocks *)
++(* There should be no ordinary R or W accesses to spinlocks *)
+ let ALL-LOCKS = LKR | LKW | UL | LF
+ flag ~empty [M \ IW] ; loc ; [ALL-LOCKS] as mixed-lock-accesses
+ 
+ (* The final value of a spinlock should not be tested *)
+ flag ~empty [FW] ; loc ; [ALL-LOCKS] as lock-final
+ 
+-(*
+- * Backward compatibility
+- *)
+-let RL = try RL with emptyset (* defined herd7 >= 7.49 *)
+-let RU = try RU with emptyset (* defined herd7 >= 7.49 *)
++(* Backward compatibility *)
++let RL = try RL with emptyset
++let RU = try RU with emptyset
+ 
+ (* Treat RL as a kind of LF: a read with no ordering properties *)
+ let LF = LF | RL
+@@ -55,7 +73,6 @@ let W = W | LKW
+ let Release = Release | UL
+ let Acquire = Acquire | LKR
+ 
+-
+ (* Match LKW events to their corresponding UL events *)
+ let critical = ([LKW] ; po-loc ; [UL]) \ (po-loc ; [LKW | UL] ; po-loc)
+ 
+@@ -65,7 +82,6 @@ flag ~empty UL \ range(critical) as unmatched-unlock
+ let UNMATCHED-LKW = LKW \ domain(critical)
+ empty ([UNMATCHED-LKW] ; loc ; [UNMATCHED-LKW]) \ id as unmatched-locks
+ 
+-
+ (* rfi for LF events: link each LKW to the LF events in its critical section *)
+ let rfi-lf = ([LKW] ; po-loc ; [LF]) \ ([LKW] ; po-loc ; [UL] ; po-loc)
+ 
+@@ -86,18 +102,23 @@ let all-possible-rfe-lf =
+ with rfe-lf from cross(all-possible-rfe-lf)
+ let rf-lf = rfe-lf | rfi-lf
+ 
+-(* Read from unlock, ie islocked returning false, slightly different *)
++(*
++ * RU, i.e., spin_is_locked() returning False, is slightly different.
++ * We rely on the memory model to rule out cases where spin_is_locked()
++ * within one of the lock's critical sections returns False.
++ *)
+ 
+-(* islocked returning false can read from the last po-previous unlock *)
++(* rfi for RU events: an RU may read from the last po-previous UL *)
+ let rfi-ru = ([UL] ; po-loc ; [RU]) \ ([UL] ; po-loc ; [LKW] ; po-loc)
+ 
+-(* any islocked returning false can read from any external unlock *)
++(* rfe for RU events: an RU may read from an external UL or the initial write *)
+ let all-possible-rfe-ru =
+    let possible-rfe-ru r =
+      let pair-to-relation p = p ++ 0
+      in map pair-to-relation (((UL|IW) * {r}) & loc & ext)
+   in map possible-rfe-ru RU
+ 
++(* Generate all rf relations for RU events *)
+ with rfe-ru from cross(all-possible-rfe-ru)
+ let rf-ru = rfe-ru | rfi-ru
+ 

commit 8559183ccaec97454b2515ac426f113967256cf9
+Author: Alan Stern 
+Date:   Mon May 14 16:33:50 2018 -0700
+
+    tools/memory-model: Remove duplicated code from lock.cat
+    
+    This patch simplifies the implementation of spin_is_locked in the
+    LKMM.  It capitalizes on the fact that a failed spin_trylock() and a
+    spin_is_locked() which returns True have exactly the same semantics
+    (those of READ_ONCE) and ordering properties (none).  Therefore the
+    two kinds of events can be combined and handled by the same code,
+    instead of treated separately as they are currently.
+    
+    Tested-by: Andrea Parri 
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Paul E. McKenney 
+    Cc: Akira Yokosawa 
+    Cc: Andrew Morton 
+    Cc: Boqun Feng 
+    Cc: David Howells 
+    Cc: Jade Alglave 
+    Cc: Linus Torvalds 
+    Cc: Luc Maranget 
+    Cc: Nicholas Piggin 
+    Cc: Peter Zijlstra 
+    Cc: Thomas Gleixner 
+    Cc: Will Deacon 
+    Cc: linux-arch@vger.kernel.org
+    Cc: parri.andrea@gmail.com
+    Link: http://lkml.kernel.org/r/1526340837-12222-12-git-send-email-paulmck@linux.vnet.ibm.com
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/tools/memory-model/lock.cat b/tools/memory-model/lock.cat
+index 3b1439edc818..1f6d67e79065 100644
+--- a/tools/memory-model/lock.cat
++++ b/tools/memory-model/lock.cat
+@@ -41,11 +41,15 @@ flag ~empty [FW] ; loc ; [ALL-LOCKS] as lock-final
+  *)
+ let RL = try RL with emptyset (* defined herd7 >= 7.49 *)
+ let RU = try RU with emptyset (* defined herd7 >= 7.49 *)
++
++(* Treat RL as a kind of LF: a read with no ordering properties *)
++let LF = LF | RL
++
+ (*
+  * Put lock operations in their appropriate classes, but leave UL out of W
+  * until after the co relation has been generated.
+  *)
+-let R = R | LKR | LF | RL | RU
++let R = R | LKR | LF | RU
+ let W = W | LKW
+ 
+ let Release = Release | UL
+@@ -80,28 +84,8 @@ let all-possible-rfe-lf =
+ 
+ (* Generate all rf relations for LF events *)
+ with rfe-lf from cross(all-possible-rfe-lf)
+-
+ let rf-lf = rfe-lf | rfi-lf
+ 
+-(* rf for RL events, ie islocked returning true, similar to LF above *)
+-
+-(* islocked returning true inside a critical section
+- * must read from the opening lock
+- *)
+-let rfi-rl = ([LKW] ; po-loc ; [RL]) \ ([LKW] ; po-loc ; [UL] ; po-loc)
+-
+-(* islocked returning true outside critical sections can match any
+- * external lock.
+- *)
+-let all-possible-rfe-rl =
+-  let possible-rfe-lf r =
+-    let pair-to-relation p = p ++ 0
+-    in map pair-to-relation ((LKW * {r}) & loc & ext)
+-  in map possible-rfe-lf (RL \ range(rfi-rl))
+-
+-with rfe-rl from cross(all-possible-rfe-rl)
+-let rf-rl = rfe-rl | rfi-rl
+-
+ (* Read from unlock, ie islocked returning false, slightly different *)
+ 
+ (* islocked returning false can read from the last po-previous unlock *)
+@@ -118,7 +102,7 @@ with rfe-ru from cross(all-possible-rfe-ru)
+ let rf-ru = rfe-ru | rfi-ru
+ 
+ (* Final rf relation *)
+-let rf = rf | rf-lf | rf-rl | rf-ru
++let rf = rf | rf-lf | rf-ru
+ 
+ (* Generate all co relations, including LKW events but not UL *)
+ let co0 = co0 | ([IW] ; loc ; [LKW]) |

commit 9d036883a17969caf8796d1fce813af0ab016986
+Author: Alan Stern 
+Date:   Mon May 14 16:33:40 2018 -0700
+
+    tools/memory-model: Redefine rb in terms of rcu-fence
+    
+    This patch reorganizes the definition of rb in the Linux Kernel Memory
+    Consistency Model.  The relation is now expressed in terms of
+    rcu-fence, which consists of a sequence of gp and rscs links separated
+    by rcu-link links, in which the number of occurrences of gp is >= the
+    number of occurrences of rscs.
+    
+    Arguments similar to those published in
+    http://diy.inria.fr/linux/long.pdf show that rcu-fence behaves like an
+    inter-CPU strong fence.  Furthermore, the definition of rb in terms of
+    rcu-fence is highly analogous to the definition of pb in terms of
+    strong-fence, which can help explain why rcu-path expresses a form of
+    temporal ordering.
+    
+    This change should not affect the semantics of the memory model, just
+    its internal organization.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Paul E. McKenney 
+    Reviewed-by: Boqun Feng 
+    Reviewed-by: Andrea Parri 
+    Cc: Andrew Morton 
+    Cc: Linus Torvalds 
+    Cc: Peter Zijlstra 
+    Cc: Thomas Gleixner 
+    Cc: Will Deacon 
+    Cc: akiyks@gmail.com
+    Cc: dhowells@redhat.com
+    Cc: j.alglave@ucl.ac.uk
+    Cc: linux-arch@vger.kernel.org
+    Cc: luc.maranget@inria.fr
+    Cc: npiggin@gmail.com
+    Link: http://lkml.kernel.org/r/1526340837-12222-2-git-send-email-paulmck@linux.vnet.ibm.com
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/tools/memory-model/Documentation/explanation.txt b/tools/memory-model/Documentation/explanation.txt
+index 1a387d703212..1b09f3175a1f 100644
+--- a/tools/memory-model/Documentation/explanation.txt
++++ b/tools/memory-model/Documentation/explanation.txt
+@@ -27,7 +27,7 @@ Explanation of the Linux-Kernel Memory Consistency Model
+   19. AND THEN THERE WAS ALPHA
+   20. THE HAPPENS-BEFORE RELATION: hb
+   21. THE PROPAGATES-BEFORE RELATION: pb
+-  22. RCU RELATIONS: rcu-link, gp-link, rscs-link, and rb
++  22. RCU RELATIONS: rcu-link, gp, rscs, rcu-fence, and rb
+   23. ODDS AND ENDS
+ 
+ 
+@@ -1451,8 +1451,8 @@ they execute means that it cannot have cycles.  This requirement is
+ the content of the LKMM's "propagation" axiom.
+ 
+ 
+-RCU RELATIONS: rcu-link, gp-link, rscs-link, and rb
+----------------------------------------------------
++RCU RELATIONS: rcu-link, gp, rscs, rcu-fence, and rb
++----------------------------------------------------
+ 
+ RCU (Read-Copy-Update) is a powerful synchronization mechanism.  It
+ rests on two concepts: grace periods and read-side critical sections.
+@@ -1537,49 +1537,100 @@ relation, and the details don't matter unless you want to comb through
+ a somewhat lengthy formal proof.  Pretty much all you need to know
+ about rcu-link is the information in the preceding paragraph.
+ 
+-The LKMM goes on to define the gp-link and rscs-link relations.  They
+-bring grace periods and read-side critical sections into the picture,
+-in the following way:
++The LKMM also defines the gp and rscs relations.  They bring grace
++periods and read-side critical sections into the picture, in the
++following way:
+ 
+-	E ->gp-link F means there is a synchronize_rcu() fence event S
+-	and an event X such that E ->po S, either S ->po X or S = X,
+-	and X ->rcu-link F.  In other words, E and F are linked by a
+-	grace period followed by an instance of rcu-link.
++	E ->gp F means there is a synchronize_rcu() fence event S such
++	that E ->po S and either S ->po F or S = F.  In simple terms,
++	there is a grace period po-between E and F.
+ 
+-	E ->rscs-link F means there is a critical section delimited by
+-	an rcu_read_lock() fence L and an rcu_read_unlock() fence U,
+-	and an event X such that E ->po U, either L ->po X or L = X,
+-	and X ->rcu-link F.  Roughly speaking, this says that some
+-	event in the same critical section as E is linked by rcu-link
+-	to F.
++	E ->rscs F means there is a critical section delimited by an
++	rcu_read_lock() fence L and an rcu_read_unlock() fence U, such
++	that E ->po U and either L ->po F or L = F.  You can think of
++	this as saying that E and F are in the same critical section
++	(in fact, it also allows E to be po-before the start of the
++	critical section and F to be po-after the end).
+ 
+ If we think of the rcu-link relation as standing for an extended
+-"before", then E ->gp-link F says that E executes before a grace
+-period which ends before F executes.  (In fact it covers more than
+-this, because it also includes cases where E executes before a grace
+-period and some store propagates to F's CPU before F executes and
+-doesn't propagate to some other CPU until after the grace period
+-ends.)  Similarly, E ->rscs-link F says that E is part of (or before
+-the start of) a critical section which starts before F executes.
++"before", then X ->gp Y ->rcu-link Z says that X executes before a
++grace period which ends before Z executes.  (In fact it covers more
++than this, because it also includes cases where X executes before a
++grace period and some store propagates to Z's CPU before Z executes
++but doesn't propagate to some other CPU until after the grace period
++ends.)  Similarly, X ->rscs Y ->rcu-link Z says that X is part of (or
++before the start of) a critical section which starts before Z
++executes.
++
++The LKMM goes on to define the rcu-fence relation as a sequence of gp
++and rscs links separated by rcu-link links, in which the number of gp
++links is >= the number of rscs links.  For example:
++
++	X ->gp Y ->rcu-link Z ->rscs T ->rcu-link U ->gp V
++
++would imply that X ->rcu-fence V, because this sequence contains two
++gp links and only one rscs link.  (It also implies that X ->rcu-fence T
++and Z ->rcu-fence V.)  On the other hand:
++
++	X ->rscs Y ->rcu-link Z ->rscs T ->rcu-link U ->gp V
++
++does not imply X ->rcu-fence V, because the sequence contains only
++one gp link but two rscs links.
++
++The rcu-fence relation is important because the Grace Period Guarantee
++means that rcu-fence acts kind of like a strong fence.  In particular,
++if W is a write and we have W ->rcu-fence Z, the Guarantee says that W
++will propagate to every CPU before Z executes.
++
++To prove this in full generality requires some intellectual effort.
++We'll consider just a very simple case:
++
++	W ->gp X ->rcu-link Y ->rscs Z.
++
++This formula means that there is a grace period G and a critical
++section C such that:
++
++	1. W is po-before G;
++
++	2. X is equal to or po-after G;
++
++	3. X comes "before" Y in some sense;
++
++	4. Y is po-before the end of C;
++
++	5. Z is equal to or po-after the start of C.
++
++From 2 - 4 we deduce that the grace period G ends before the critical
++section C.  Then the second part of the Grace Period Guarantee says
++not only that G starts before C does, but also that W (which executes
++on G's CPU before G starts) must propagate to every CPU before C
++starts.  In particular, W propagates to every CPU before Z executes
++(or finishes executing, in the case where Z is equal to the
++rcu_read_lock() fence event which starts C.)  This sort of reasoning
++can be expanded to handle all the situations covered by rcu-fence.
++
++Finally, the LKMM defines the RCU-before (rb) relation in terms of
++rcu-fence.  This is done in essentially the same way as the pb
++relation was defined in terms of strong-fence.  We will omit the
++details; the end result is that E ->rb F implies E must execute before
++F, just as E ->pb F does (and for much the same reasons).
+ 
+ Putting this all together, the LKMM expresses the Grace Period
+-Guarantee by requiring that there are no cycles consisting of gp-link
+-and rscs-link links in which the number of gp-link instances is >= the
+-number of rscs-link instances.  It does this by defining the rb
+-relation to link events E and F whenever it is possible to pass from E
+-to F by a sequence of gp-link and rscs-link links with at least as
+-many of the former as the latter.  The LKMM's "rcu" axiom then says
+-that there are no events E with E ->rb E.
+-
+-Justifying this axiom takes some intellectual effort, but it is in
+-fact a valid formalization of the Grace Period Guarantee.  We won't
+-attempt to go through the detailed argument, but the following
+-analysis gives a taste of what is involved.  Suppose we have a
+-violation of the first part of the Guarantee: A critical section
+-starts before a grace period, and some store propagates to the
+-critical section's CPU before the end of the critical section but
+-doesn't propagate to some other CPU until after the end of the grace
+-period.
++Guarantee by requiring that the rb relation does not contain a cycle.
++Equivalently, this "rcu" axiom requires that there are no events E and
++F with E ->rcu-link F ->rcu-fence E.  Or to put it a third way, the
++axiom requires that there are no cycles consisting of gp and rscs
++alternating with rcu-link, where the number of gp links is >= the
++number of rscs links.
++
++Justifying the axiom isn't easy, but it is in fact a valid
++formalization of the Grace Period Guarantee.  We won't attempt to go
++through the detailed argument, but the following analysis gives a
++taste of what is involved.  Suppose we have a violation of the first
++part of the Guarantee: A critical section starts before a grace
++period, and some store propagates to the critical section's CPU before
++the end of the critical section but doesn't propagate to some other
++CPU until after the end of the grace period.
+ 
+ Putting symbols to these ideas, let L and U be the rcu_read_lock() and
+ rcu_read_unlock() fence events delimiting the critical section in
+@@ -1606,11 +1657,14 @@ by rcu-link, yielding:
+ 
+ 	S ->po X ->rcu-link Z ->po U.
+ 
+-The formulas say that S is po-between F and X, hence F ->gp-link Z
+-via X.  They also say that Z comes before the end of the critical
+-section and E comes after its start, hence Z ->rscs-link F via E.  But
+-now we have a forbidden cycle: F ->gp-link Z ->rscs-link F.  Thus the
+-"rcu" axiom rules out this violation of the Grace Period Guarantee.
++The formulas say that S is po-between F and X, hence F ->gp X.  They
++also say that Z comes before the end of the critical section and E
++comes after its start, hence Z ->rscs E.  From all this we obtain:
++
++	F ->gp X ->rcu-link Z ->rscs E ->rcu-link F,
++
++a forbidden cycle.  Thus the "rcu" axiom rules out this violation of
++the Grace Period Guarantee.
+ 
+ For something a little more down-to-earth, let's see how the axiom
+ works out in practice.  Consider the RCU code example from above, this
+@@ -1639,15 +1693,15 @@ time with statement labels added to the memory access instructions:
+ If r2 = 0 at the end then P0's store at X overwrites the value that
+ P1's load at Z reads from, so we have Z ->fre X and thus Z ->rcu-link X.
+ In addition, there is a synchronize_rcu() between Y and Z, so therefore
+-we have Y ->gp-link X.
++we have Y ->gp Z.
+ 
+ If r1 = 1 at the end then P1's load at Y reads from P0's store at W,
+ so we have W ->rcu-link Y.  In addition, W and X are in the same critical
+-section, so therefore we have X ->rscs-link Y.
++section, so therefore we have X ->rscs W.
+ 
+-This gives us a cycle, Y ->gp-link X ->rscs-link Y, with one gp-link
+-and one rscs-link, violating the "rcu" axiom.  Hence the outcome is
+-not allowed by the LKMM, as we would expect.
++Then X ->rscs W ->rcu-link Y ->gp Z ->rcu-link X is a forbidden cycle,
++violating the "rcu" axiom.  Hence the outcome is not allowed by the
++LKMM, as we would expect.
+ 
+ For contrast, let's see what can happen in a more complicated example:
+ 
+@@ -1683,15 +1737,11 @@ For contrast, let's see what can happen in a more complicated example:
+ 	}
+ 
+ If r0 = r1 = r2 = 1 at the end, then similar reasoning to before shows
+-that W ->rscs-link Y via X, Y ->gp-link U via Z, and U ->rscs-link W
+-via V.  And just as before, this gives a cycle:
+-
+-	W ->rscs-link Y ->gp-link U ->rscs-link W.
+-
+-However, this cycle has fewer gp-link instances than rscs-link
+-instances, and consequently the outcome is not forbidden by the LKMM.
+-The following instruction timing diagram shows how it might actually
+-occur:
++that W ->rscs X ->rcu-link Y ->gp Z ->rcu-link U ->rscs V ->rcu-link W.
++However this cycle is not forbidden, because the sequence of relations
++contains fewer instances of gp (one) than of rscs (two).  Consequently
++the outcome is allowed by the LKMM.  The following instruction timing
++diagram shows how it might actually occur:
+ 
+ P0			P1			P2
+ --------------------	--------------------	--------------------
+diff --git a/tools/memory-model/linux-kernel.cat b/tools/memory-model/linux-kernel.cat
+index cdf682859d4e..1e5c4653dd12 100644
+--- a/tools/memory-model/linux-kernel.cat
++++ b/tools/memory-model/linux-kernel.cat
+@@ -102,20 +102,27 @@ let rscs = po ; crit^-1 ; po?
+  *)
+ let rcu-link = hb* ; pb* ; prop
+ 
+-(* Chains that affect the RCU grace-period guarantee *)
+-let gp-link = gp ; rcu-link
+-let rscs-link = rscs ; rcu-link
+-
+ (*
+- * A cycle containing at least as many grace periods as RCU read-side
+- * critical sections is forbidden.
++ * Any sequence containing at least as many grace periods as RCU read-side
++ * critical sections (joined by rcu-link) acts as a generalized strong fence.
+  *)
+-let rec rb =
+-	gp-link |
+-	(gp-link ; rscs-link) |
+-	(rscs-link ; gp-link) |
+-	(rb ; rb) |
+-	(gp-link ; rb ; rscs-link) |
+-	(rscs-link ; rb ; gp-link)
++let rec rcu-fence = gp |
++	(gp ; rcu-link ; rscs) |
++	(rscs ; rcu-link ; gp) |
++	(gp ; rcu-link ; rcu-fence ; rcu-link ; rscs) |
++	(rscs ; rcu-link ; rcu-fence ; rcu-link ; gp) |
++	(rcu-fence ; rcu-link ; rcu-fence)
++
++(* rb orders instructions just as pb does *)
++let rb = prop ; rcu-fence ; hb* ; pb*
+ 
+ irreflexive rb as rcu
++
++(*
++ * The happens-before, propagation, and rcu constraints are all
++ * expressions of temporal ordering.  They could be replaced by
++ * a single constraint on an "executes-before" relation, xb:
++ *
++ * let xb = hb | pb | rb
++ * acyclic xb as executes-before
++ *)

commit 1ee2da5f9b5a8e814b397b77a08d44fed5f96a4a
+Author: Alan Stern 
+Date:   Mon May 14 16:33:39 2018 -0700
+
+    tools/memory-model: Rename link and rcu-path to rcu-link and rb
+    
+    This patch makes a simple non-functional change to the RCU portion of
+    the Linux Kernel Memory Consistency Model by renaming the "link" and
+    "rcu-path" relations to "rcu-link" and "rb", respectively.
+    
+    The name "link" was an unfortunate choice, because it was too generic
+    and subject to confusion with other meanings of the same word, which
+    occur quite often in LKMM documentation.  The name "rcu-path" is not
+    very appropriate, because the relation is analogous to the
+    happens-before (hb) and propagates-before (pb) relations -- although
+    that fact won't become apparent until the second patch in this series.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Paul E. McKenney 
+    Acked-by: Andrea Parri 
+    Cc: Andrew Morton 
+    Cc: Linus Torvalds 
+    Cc: Peter Zijlstra 
+    Cc: Thomas Gleixner 
+    Cc: Will Deacon 
+    Cc: akiyks@gmail.com
+    Cc: boqun.feng@gmail.com
+    Cc: dhowells@redhat.com
+    Cc: j.alglave@ucl.ac.uk
+    Cc: linux-arch@vger.kernel.org
+    Cc: luc.maranget@inria.fr
+    Cc: npiggin@gmail.com
+    Link: http://lkml.kernel.org/r/1526340837-12222-1-git-send-email-paulmck@linux.vnet.ibm.com
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/tools/memory-model/Documentation/explanation.txt b/tools/memory-model/Documentation/explanation.txt
+index a727c82bd434..1a387d703212 100644
+--- a/tools/memory-model/Documentation/explanation.txt
++++ b/tools/memory-model/Documentation/explanation.txt
+@@ -27,7 +27,7 @@ Explanation of the Linux-Kernel Memory Consistency Model
+   19. AND THEN THERE WAS ALPHA
+   20. THE HAPPENS-BEFORE RELATION: hb
+   21. THE PROPAGATES-BEFORE RELATION: pb
+-  22. RCU RELATIONS: link, gp-link, rscs-link, and rcu-path
++  22. RCU RELATIONS: rcu-link, gp-link, rscs-link, and rb
+   23. ODDS AND ENDS
+ 
+ 
+@@ -1451,8 +1451,8 @@ they execute means that it cannot have cycles.  This requirement is
+ the content of the LKMM's "propagation" axiom.
+ 
+ 
+-RCU RELATIONS: link, gp-link, rscs-link, and rcu-path
+------------------------------------------------------
++RCU RELATIONS: rcu-link, gp-link, rscs-link, and rb
++---------------------------------------------------
+ 
+ RCU (Read-Copy-Update) is a powerful synchronization mechanism.  It
+ rests on two concepts: grace periods and read-side critical sections.
+@@ -1509,8 +1509,8 @@ y, which occurs before the end of the critical section, did not
+ propagate to P1 before the end of the grace period, violating the
+ Guarantee.
+ 
+-In the kernel's implementations of RCU, the business about stores
+-propagating to every CPU is realized by placing strong fences at
++In the kernel's implementations of RCU, the requirements for stores
++to propagate to every CPU are fulfilled by placing strong fences at
+ suitable places in the RCU-related code.  Thus, if a critical section
+ starts before a grace period does then the critical section's CPU will
+ execute an smp_mb() fence after the end of the critical section and
+@@ -1523,19 +1523,19 @@ executes.
+ What exactly do we mean by saying that a critical section "starts
+ before" or "ends after" a grace period?  Some aspects of the meaning
+ are pretty obvious, as in the example above, but the details aren't
+-entirely clear.  The LKMM formalizes this notion by means of a
+-relation with the unfortunately generic name "link".  It is a very
+-general relation; among other things, X ->link Z includes cases where
+-X happens-before or is equal to some event Y which is equal to or
+-comes before Z in the coherence order.  Taking Y = Z, this says that
+-X ->rfe Z implies X ->link Z, and taking Y = X, it says that X ->fr Z
+-and X ->co Z each imply X ->link Z.
+-
+-The formal definition of the link relation is more than a little
++entirely clear.  The LKMM formalizes this notion by means of the
++rcu-link relation.  rcu-link encompasses a very general notion of
++"before": Among other things, X ->rcu-link Z includes cases where X
++happens-before or is equal to some event Y which is equal to or comes
++before Z in the coherence order.  When Y = Z this says that X ->rfe Z
++implies X ->rcu-link Z.  In addition, when Y = X it says that X ->fr Z
++and X ->co Z each imply X ->rcu-link Z.
++
++The formal definition of the rcu-link relation is more than a little
+ obscure, and we won't give it here.  It is closely related to the pb
+ relation, and the details don't matter unless you want to comb through
+ a somewhat lengthy formal proof.  Pretty much all you need to know
+-about link is the information in the preceding paragraph.
++about rcu-link is the information in the preceding paragraph.
+ 
+ The LKMM goes on to define the gp-link and rscs-link relations.  They
+ bring grace periods and read-side critical sections into the picture,
+@@ -1543,32 +1543,33 @@ in the following way:
+ 
+ 	E ->gp-link F means there is a synchronize_rcu() fence event S
+ 	and an event X such that E ->po S, either S ->po X or S = X,
+-	and X ->link F.  In other words, E and F are connected by a
+-	grace period followed by an instance of link.
++	and X ->rcu-link F.  In other words, E and F are linked by a
++	grace period followed by an instance of rcu-link.
+ 
+ 	E ->rscs-link F means there is a critical section delimited by
+ 	an rcu_read_lock() fence L and an rcu_read_unlock() fence U,
+ 	and an event X such that E ->po U, either L ->po X or L = X,
+-	and X ->link F.  Roughly speaking, this says that some event
+-	in the same critical section as E is connected by link to F.
+-
+-If we think of the link relation as standing for an extended "before",
+-then E ->gp-link F says that E executes before a grace period which
+-ends before F executes.  (In fact it says more than this, because it
+-includes cases where E executes before a grace period and some store
+-propagates to F's CPU before F executes and doesn't propagate to some
+-other CPU until after the grace period ends.)  Similarly,
+-E ->rscs-link F says that E is part of (or before the start of) a
+-critical section which starts before F executes.
++	and X ->rcu-link F.  Roughly speaking, this says that some
++	event in the same critical section as E is linked by rcu-link
++	to F.
++
++If we think of the rcu-link relation as standing for an extended
++"before", then E ->gp-link F says that E executes before a grace
++period which ends before F executes.  (In fact it covers more than
++this, because it also includes cases where E executes before a grace
++period and some store propagates to F's CPU before F executes and
++doesn't propagate to some other CPU until after the grace period
++ends.)  Similarly, E ->rscs-link F says that E is part of (or before
++the start of) a critical section which starts before F executes.
+ 
+ Putting this all together, the LKMM expresses the Grace Period
+ Guarantee by requiring that there are no cycles consisting of gp-link
+-and rscs-link connections in which the number of gp-link instances is
+->= the number of rscs-link instances.  It does this by defining the
+-rcu-path relation to link events E and F whenever it is possible to
+-pass from E to F by a sequence of gp-link and rscs-link connections
+-with at least as many of the former as the latter.  The LKMM's "rcu"
+-axiom then says that there are no events E such that E ->rcu-path E.
++and rscs-link links in which the number of gp-link instances is >= the
++number of rscs-link instances.  It does this by defining the rb
++relation to link events E and F whenever it is possible to pass from E
++to F by a sequence of gp-link and rscs-link links with at least as
++many of the former as the latter.  The LKMM's "rcu" axiom then says
++that there are no events E with E ->rb E.
+ 
+ Justifying this axiom takes some intellectual effort, but it is in
+ fact a valid formalization of the Grace Period Guarantee.  We won't
+@@ -1585,10 +1586,10 @@ rcu_read_unlock() fence events delimiting the critical section in
+ question, and let S be the synchronize_rcu() fence event for the grace
+ period.  Saying that the critical section starts before S means there
+ are events E and F where E is po-after L (which marks the start of the
+-critical section), E is "before" F in the sense of the link relation,
+-and F is po-before the grace period S:
++critical section), E is "before" F in the sense of the rcu-link
++relation, and F is po-before the grace period S:
+ 
+-	L ->po E ->link F ->po S.
++	L ->po E ->rcu-link F ->po S.
+ 
+ Let W be the store mentioned above, let Z come before the end of the
+ critical section and witness that W propagates to the critical
+@@ -1600,12 +1601,12 @@ some event X which is po-after S.  Symbolically, this amounts to:
+ 
+ The fr link from Y to W indicates that W has not propagated to Y's CPU
+ at the time that Y executes.  From this, it can be shown (see the
+-discussion of the link relation earlier) that X and Z are connected by
+-link, yielding:
++discussion of the rcu-link relation earlier) that X and Z are related
++by rcu-link, yielding:
+ 
+-	S ->po X ->link Z ->po U.
++	S ->po X ->rcu-link Z ->po U.
+ 
+-These formulas say that S is po-between F and X, hence F ->gp-link Z
++The formulas say that S is po-between F and X, hence F ->gp-link Z
+ via X.  They also say that Z comes before the end of the critical
+ section and E comes after its start, hence Z ->rscs-link F via E.  But
+ now we have a forbidden cycle: F ->gp-link Z ->rscs-link F.  Thus the
+@@ -1635,13 +1636,13 @@ time with statement labels added to the memory access instructions:
+ 	}
+ 
+ 
+-If r2 = 0 at the end then P0's store at X overwrites the value
+-that P1's load at Z reads from, so we have Z ->fre X and thus
+-Z ->link X.  In addition, there is a synchronize_rcu() between Y and
+-Z, so therefore we have Y ->gp-link X.
++If r2 = 0 at the end then P0's store at X overwrites the value that
++P1's load at Z reads from, so we have Z ->fre X and thus Z ->rcu-link X.
++In addition, there is a synchronize_rcu() between Y and Z, so therefore
++we have Y ->gp-link X.
+ 
+ If r1 = 1 at the end then P1's load at Y reads from P0's store at W,
+-so we have W ->link Y.  In addition, W and X are in the same critical
++so we have W ->rcu-link Y.  In addition, W and X are in the same critical
+ section, so therefore we have X ->rscs-link Y.
+ 
+ This gives us a cycle, Y ->gp-link X ->rscs-link Y, with one gp-link
+diff --git a/tools/memory-model/linux-kernel.cat b/tools/memory-model/linux-kernel.cat
+index df97db03b6c2..cdf682859d4e 100644
+--- a/tools/memory-model/linux-kernel.cat
++++ b/tools/memory-model/linux-kernel.cat
+@@ -100,22 +100,22 @@ let rscs = po ; crit^-1 ; po?
+  * one but two non-rf relations, but only in conjunction with an RCU
+  * read-side critical section.
+  *)
+-let link = hb* ; pb* ; prop
++let rcu-link = hb* ; pb* ; prop
+ 
+ (* Chains that affect the RCU grace-period guarantee *)
+-let gp-link = gp ; link
+-let rscs-link = rscs ; link
++let gp-link = gp ; rcu-link
++let rscs-link = rscs ; rcu-link
+ 
+ (*
+  * A cycle containing at least as many grace periods as RCU read-side
+  * critical sections is forbidden.
+  *)
+-let rec rcu-path =
++let rec rb =
+ 	gp-link |
+ 	(gp-link ; rscs-link) |
+ 	(rscs-link ; gp-link) |
+-	(rcu-path ; rcu-path) |
+-	(gp-link ; rcu-path ; rscs-link) |
+-	(rscs-link ; rcu-path ; gp-link)
++	(rb ; rb) |
++	(gp-link ; rb ; rscs-link) |
++	(rscs-link ; rb ; gp-link)
+ 
+-irreflexive rcu-path as rcu
++irreflexive rb as rcu

commit fb5ee84ea72c5f1b6cabdd1c9d6e8648995ca7c6
+Author: Alan Stern 
+Date:   Thu May 3 11:04:48 2018 -0400
+
+    USB: Accept bulk endpoints with 1024-byte maxpacket
+    
+    Some non-compliant high-speed USB devices have bulk endpoints with a
+    1024-byte maxpacket size.  Although such endpoints don't work with
+    xHCI host controllers, they do work with EHCI controllers.  We used to
+    accept these invalid sizes (with a warning), but we no longer do
+    because of an unintentional change introduced by commit aed9d65ac327
+    ("USB: validate wMaxPacketValue entries in endpoint descriptors").
+    
+    This patch restores the old behavior, so that people with these
+    peculiar devices can use them without patching their kernels by hand.
+    
+    Signed-off-by: Alan Stern 
+    Suggested-by: Elvinas 
+    Fixes: aed9d65ac327 ("USB: validate wMaxPacketValue entries in endpoint descriptors")
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
+index c821b4b9647e..7b5cb28ffb35 100644
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -191,7 +191,9 @@ static const unsigned short full_speed_maxpacket_maxes[4] = {
+ static const unsigned short high_speed_maxpacket_maxes[4] = {
+ 	[USB_ENDPOINT_XFER_CONTROL] = 64,
+ 	[USB_ENDPOINT_XFER_ISOC] = 1024,
+-	[USB_ENDPOINT_XFER_BULK] = 512,
++
++	/* Bulk should be 512, but some devices use 1024: we will warn below */
++	[USB_ENDPOINT_XFER_BULK] = 1024,
+ 	[USB_ENDPOINT_XFER_INT] = 1024,
+ };
+ static const unsigned short super_speed_maxpacket_maxes[4] = {

commit 5d1332a8eabd8bd5b8c322d45542968ee6f113be
+Author: Alan Stern 
+Date:   Tue Mar 27 10:27:06 2018 -0400
+
+    usb: gadget: udc: core: Document the relation between usb_ep_queue() and completion callback
+    
+    Improve the kerneldoc for usb_ep_queue() to note explicitly that the
+    request's completion routine will be called if and only if the return
+    value is 0.  The corresponding fact about usb_submit_urb() for the
+    host-side API has long been documented, and this has always been the
+    intention for the gadget API.  But until now, documentation seems to
+    have been lacking.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
+index 842814bc0e4f..cab5e4f09924 100644
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -244,6 +244,12 @@ EXPORT_SYMBOL_GPL(usb_ep_free_request);
+  * Returns zero, or a negative error code.  Endpoints that are not enabled
+  * report errors; errors will also be
+  * reported when the usb peripheral is disconnected.
++ *
++ * If and only if @req is successfully queued (the return value is zero),
++ * @req->complete() will be called exactly once, when the Gadget core and
++ * UDC are finished with the request.  When the completion function is called,
++ * control of the request is returned to the device driver which submitted it.
++ * The completion handler may then immediately free or reuse @req.
+  */
+ int usb_ep_queue(struct usb_ep *ep,
+ 			       struct usb_request *req, gfp_t gfp_flags)

commit bd5c0ba2cd78a4c116726ead84f8f37dc92d043e
+Author: Alan Stern 
+Date:   Wed Mar 7 09:27:40 2018 -0800
+
+    tools/memory-model: Finish the removal of rb-dep, smp_read_barrier_depends(), and lockless_dereference()
+    
+    Commit:
+    
+      bf28ae562744 ("tools/memory-model: Remove rb-dep, smp_read_barrier_depends, and lockless_dereference")
+    
+    was merged too early, while it was still in RFC form.  This patch adds in
+    the missing pieces.
+    
+    Akira pointed out some typos in the original patch, and he noted that
+    cheatsheet.txt should indicate that READ_ONCE() now implies an address
+    dependency.  Andrea suggested documenting the relationship betwwen
+    unsuccessful RMW operations and address dependencies.
+    
+    Andrea pointed out that the macro for rcu_dereference() in linux.def
+    should now use the "once" annotation instead of "deref".  He also
+    suggested that the comments should mention commit:
+    
+      5a8897cc7631 ("locking/atomics/alpha: Add smp_read_barrier_depends() to _release()/_relaxed() atomics")
+    
+    ... as an important precursor, and he contributed commit:
+    
+      cb13b424e986 ("locking/xchg/alpha: Add unconditional memory barrier to cmpxchg()")
+    
+    which is another prerequisite.
+    
+    Suggested-by: Akira Yokosawa 
+    Suggested-by: Andrea Parri 
+    Signed-off-by: Alan Stern 
+    [ Fixed read_read_lock() typo reported by Akira. ]
+    Signed-off-by: Paul E. McKenney 
+    Acked-by: Andrea Parri 
+    Acked-by: Akira Yokosawa 
+    Cc: Linus Torvalds 
+    Cc: Peter Zijlstra 
+    Cc: Thomas Gleixner 
+    Cc: boqun.feng@gmail.com
+    Cc: dhowells@redhat.com
+    Cc: j.alglave@ucl.ac.uk
+    Cc: linux-arch@vger.kernel.org
+    Cc: luc.maranget@inria.fr
+    Cc: npiggin@gmail.com
+    Cc: will.deacon@arm.com
+    Fixes: bf28ae562744 ("tools/memory-model: Remove rb-dep, smp_read_barrier_depends, and lockless_dereference")
+    Link: http://lkml.kernel.org/r/1520443660-16858-4-git-send-email-paulmck@linux.vnet.ibm.com
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/tools/memory-model/Documentation/cheatsheet.txt b/tools/memory-model/Documentation/cheatsheet.txt
+index 04e458acd6d4..956b1ae4aafb 100644
+--- a/tools/memory-model/Documentation/cheatsheet.txt
++++ b/tools/memory-model/Documentation/cheatsheet.txt
+@@ -1,11 +1,11 @@
+                                   Prior Operation     Subsequent Operation
+                                   ---------------  ---------------------------
+                                C  Self  R  W  RWM  Self  R  W  DR  DW  RMW  SV
+-                              __  ----  -  -  ---  ----  -  -  --  --  ---  --
++                              --  ----  -  -  ---  ----  -  -  --  --  ---  --
+ 
+ Store, e.g., WRITE_ONCE()            Y                                       Y
+-Load, e.g., READ_ONCE()              Y                              Y        Y
+-Unsuccessful RMW operation           Y                              Y        Y
++Load, e.g., READ_ONCE()              Y                          Y   Y        Y
++Unsuccessful RMW operation           Y                          Y   Y        Y
+ rcu_dereference()                    Y                          Y   Y        Y
+ Successful *_acquire()               R                   Y  Y   Y   Y    Y   Y
+ Successful *_release()         C        Y  Y    Y     W                      Y
+diff --git a/tools/memory-model/Documentation/explanation.txt b/tools/memory-model/Documentation/explanation.txt
+index dae8b8cb2ad3..a727c82bd434 100644
+--- a/tools/memory-model/Documentation/explanation.txt
++++ b/tools/memory-model/Documentation/explanation.txt
+@@ -826,7 +826,7 @@ A-cumulative; they only affect the propagation of stores that are
+ executed on C before the fence (i.e., those which precede the fence in
+ program order).
+ 
+-read_lock(), rcu_read_unlock(), and synchronize_rcu() fences have
++rcu_read_lock(), rcu_read_unlock(), and synchronize_rcu() fences have
+ other properties which we discuss later.
+ 
+ 
+@@ -1138,7 +1138,7 @@ final effect is that even though the two loads really are executed in
+ program order, it appears that they aren't.
+ 
+ This could not have happened if the local cache had processed the
+-incoming stores in FIFO order.  In constrast, other architectures
++incoming stores in FIFO order.  By contrast, other architectures
+ maintain at least the appearance of FIFO order.
+ 
+ In practice, this difficulty is solved by inserting a special fence
+diff --git a/tools/memory-model/linux-kernel.def b/tools/memory-model/linux-kernel.def
+index 5dfb9c7f3462..397e4e67e8c8 100644
+--- a/tools/memory-model/linux-kernel.def
++++ b/tools/memory-model/linux-kernel.def
+@@ -13,7 +13,7 @@ WRITE_ONCE(X,V) { __store{once}(X,V); }
+ smp_store_release(X,V) { __store{release}(*X,V); }
+ smp_load_acquire(X) __load{acquire}(*X)
+ rcu_assign_pointer(X,V) { __store{release}(X,V); }
+-rcu_dereference(X) __load{deref}(X)
++rcu_dereference(X) __load{once}(X)
+ 
+ // Fences
+ smp_mb() { __fence{mb} ; }

commit bf28ae5627442355dbb8d99238da4fb95c2dd4ec
+Author: Alan Stern 
+Date:   Tue Feb 20 15:25:12 2018 -0800
+
+    tools/memory-model: Remove rb-dep, smp_read_barrier_depends, and lockless_dereference
+    
+    Since commit 76ebbe78f739 ("locking/barriers: Add implicit
+    smp_read_barrier_depends() to READ_ONCE()") was merged for the 4.15
+    kernel, it has not been necessary to use smp_read_barrier_depends().
+    Similarly, commit 59ecbbe7b31c ("locking/barriers: Kill
+    lockless_dereference()") removed lockless_dereference() from the
+    kernel.
+    
+    Since these primitives are no longer part of the kernel, they do not
+    belong in the Linux Kernel Memory Consistency Model.  This patch
+    removes them, along with the internal rb-dep relation, and updates the
+    revelant documentation.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Paul E. McKenney 
+    Acked-by: Peter Zijlstra 
+    Cc: Linus Torvalds 
+    Cc: Thomas Gleixner 
+    Cc: akiyks@gmail.com
+    Cc: boqun.feng@gmail.com
+    Cc: dhowells@redhat.com
+    Cc: j.alglave@ucl.ac.uk
+    Cc: linux-arch@vger.kernel.org
+    Cc: luc.maranget@inria.fr
+    Cc: nborisov@suse.com
+    Cc: npiggin@gmail.com
+    Cc: parri.andrea@gmail.com
+    Cc: will.deacon@arm.com
+    Link: http://lkml.kernel.org/r/1519169112-20593-12-git-send-email-paulmck@linux.vnet.ibm.com
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/tools/memory-model/Documentation/cheatsheet.txt b/tools/memory-model/Documentation/cheatsheet.txt
+index 1917712bce99..04e458acd6d4 100644
+--- a/tools/memory-model/Documentation/cheatsheet.txt
++++ b/tools/memory-model/Documentation/cheatsheet.txt
+@@ -6,8 +6,7 @@
+ Store, e.g., WRITE_ONCE()            Y                                       Y
+ Load, e.g., READ_ONCE()              Y                              Y        Y
+ Unsuccessful RMW operation           Y                              Y        Y
+-smp_read_barrier_depends()              Y                       Y   Y
+-*_dereference()                      Y                          Y   Y        Y
++rcu_dereference()                    Y                          Y   Y        Y
+ Successful *_acquire()               R                   Y  Y   Y   Y    Y   Y
+ Successful *_release()         C        Y  Y    Y     W                      Y
+ smp_rmb()                               Y       R        Y      Y        R
+diff --git a/tools/memory-model/Documentation/explanation.txt b/tools/memory-model/Documentation/explanation.txt
+index 867e0ea69b6d..dae8b8cb2ad3 100644
+--- a/tools/memory-model/Documentation/explanation.txt
++++ b/tools/memory-model/Documentation/explanation.txt
+@@ -1,5 +1,5 @@
+-Explanation of the Linux-Kernel Memory Model
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++Explanation of the Linux-Kernel Memory Consistency Model
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ 
+ :Author: Alan Stern 
+ :Created: October 2017
+@@ -35,25 +35,24 @@ Explanation of the Linux-Kernel Memory Model
+ INTRODUCTION
+ ------------
+ 
+-The Linux-kernel memory model (LKMM) is rather complex and obscure.
+-This is particularly evident if you read through the linux-kernel.bell
+-and linux-kernel.cat files that make up the formal version of the
+-memory model; they are extremely terse and their meanings are far from
+-clear.
++The Linux-kernel memory consistency model (LKMM) is rather complex and
++obscure.  This is particularly evident if you read through the
++linux-kernel.bell and linux-kernel.cat files that make up the formal
++version of the model; they are extremely terse and their meanings are
++far from clear.
+ 
+ This document describes the ideas underlying the LKMM.  It is meant
+-for people who want to understand how the memory model was designed.
+-It does not go into the details of the code in the .bell and .cat
+-files; rather, it explains in English what the code expresses
+-symbolically.
++for people who want to understand how the model was designed.  It does
++not go into the details of the code in the .bell and .cat files;
++rather, it explains in English what the code expresses symbolically.
+ 
+ Sections 2 (BACKGROUND) through 5 (ORDERING AND CYCLES) are aimed
+-toward beginners; they explain what memory models are and the basic
+-notions shared by all such models.  People already familiar with these
+-concepts can skim or skip over them.  Sections 6 (EVENTS) through 12
+-(THE FROM_READS RELATION) describe the fundamental relations used in
+-many memory models.  Starting in Section 13 (AN OPERATIONAL MODEL),
+-the workings of the LKMM itself are covered.
++toward beginners; they explain what memory consistency models are and
++the basic notions shared by all such models.  People already familiar
++with these concepts can skim or skip over them.  Sections 6 (EVENTS)
++through 12 (THE FROM_READS RELATION) describe the fundamental
++relations used in many models.  Starting in Section 13 (AN OPERATIONAL
++MODEL), the workings of the LKMM itself are covered.
+ 
+ Warning: The code examples in this document are not written in the
+ proper format for litmus tests.  They don't include a header line, the
+@@ -827,8 +826,8 @@ A-cumulative; they only affect the propagation of stores that are
+ executed on C before the fence (i.e., those which precede the fence in
+ program order).
+ 
+-smp_read_barrier_depends(), rcu_read_lock(), rcu_read_unlock(), and
+-synchronize_rcu() fences have other properties which we discuss later.
++read_lock(), rcu_read_unlock(), and synchronize_rcu() fences have
++other properties which we discuss later.
+ 
+ 
+ PROPAGATION ORDER RELATION: cumul-fence
+@@ -988,8 +987,8 @@ Another possibility, not mentioned earlier but discussed in the next
+ section, is:
+ 
+ 	X and Y are both loads, X ->addr Y (i.e., there is an address
+-	dependency from X to Y), and an smp_read_barrier_depends()
+-	fence occurs between them.
++	dependency from X to Y), and X is a READ_ONCE() or an atomic
++	access.
+ 
+ Dependencies can also cause instructions to be executed in program
+ order.  This is uncontroversial when the second instruction is a
+@@ -1015,9 +1014,9 @@ After all, a CPU cannot ask the memory subsystem to load a value from
+ a particular location before it knows what that location is.  However,
+ the split-cache design used by Alpha can cause it to behave in a way
+ that looks as if the loads were executed out of order (see the next
+-section for more details).  For this reason, the LKMM does not include
+-address dependencies between read events in the ppo relation unless an
+-smp_read_barrier_depends() fence is present.
++section for more details).  The kernel includes a workaround for this
++problem when the loads come from READ_ONCE(), and therefore the LKMM
++includes address dependencies to loads in the ppo relation.
+ 
+ On the other hand, dependencies can indirectly affect the ordering of
+ two loads.  This happens when there is a dependency from a load to a
+@@ -1114,11 +1113,12 @@ code such as the following:
+ 		int *r1;
+ 		int r2;
+ 
+-		r1 = READ_ONCE(ptr);
++		r1 = ptr;
+ 		r2 = READ_ONCE(*r1);
+ 	}
+ 
+-can malfunction on Alpha systems.  It is quite possible that r1 = &x
++can malfunction on Alpha systems (notice that P1 uses an ordinary load
++to read ptr instead of READ_ONCE()).  It is quite possible that r1 = &x
+ and r2 = 0 at the end, in spite of the address dependency.
+ 
+ At first glance this doesn't seem to make sense.  We know that the
+@@ -1141,11 +1141,15 @@ This could not have happened if the local cache had processed the
+ incoming stores in FIFO order.  In constrast, other architectures
+ maintain at least the appearance of FIFO order.
+ 
+-In practice, this difficulty is solved by inserting an
+-smp_read_barrier_depends() fence between P1's two loads.  The effect
+-of this fence is to cause the CPU not to execute any po-later
+-instructions until after the local cache has finished processing all
+-the stores it has already received.  Thus, if the code was changed to:
++In practice, this difficulty is solved by inserting a special fence
++between P1's two loads when the kernel is compiled for the Alpha
++architecture.  In fact, as of version 4.15, the kernel automatically
++adds this fence (called smp_read_barrier_depends() and defined as
++nothing at all on non-Alpha builds) after every READ_ONCE() and atomic
++load.  The effect of the fence is to cause the CPU not to execute any
++po-later instructions until after the local cache has finished
++processing all the stores it has already received.  Thus, if the code
++was changed to:
+ 
+ 	P1()
+ 	{
+@@ -1153,13 +1157,15 @@ the stores it has already received.  Thus, if the code was changed to:
+ 		int r2;
+ 
+ 		r1 = READ_ONCE(ptr);
+-		smp_read_barrier_depends();
+ 		r2 = READ_ONCE(*r1);
+ 	}
+ 
+ then we would never get r1 = &x and r2 = 0.  By the time P1 executed
+ its second load, the x = 1 store would already be fully processed by
+-the local cache and available for satisfying the read request.
++the local cache and available for satisfying the read request.  Thus
++we have yet another reason why shared data should always be read with
++READ_ONCE() or another synchronization primitive rather than accessed
++directly.
+ 
+ The LKMM requires that smp_rmb(), acquire fences, and strong fences
+ share this property with smp_read_barrier_depends(): They do not allow
+@@ -1751,11 +1757,10 @@ no further involvement from the CPU.  Since the CPU doesn't ever read
+ the value of x, there is nothing for the smp_rmb() fence to act on.
+ 
+ The LKMM defines a few extra synchronization operations in terms of
+-things we have already covered.  In particular, rcu_dereference() and
+-lockless_dereference() are both treated as a READ_ONCE() followed by
+-smp_read_barrier_depends() -- which also happens to be how they are
+-defined in include/linux/rcupdate.h and include/linux/compiler.h,
+-respectively.
++things we have already covered.  In particular, rcu_dereference() is
++treated as READ_ONCE() and rcu_assign_pointer() is treated as
++smp_store_release() -- which is basically how the Linux kernel treats
++them.
+ 
+ There are a few oddball fences which need special treatment:
+ smp_mb__before_atomic(), smp_mb__after_atomic(), and
+diff --git a/tools/memory-model/linux-kernel.bell b/tools/memory-model/linux-kernel.bell
+index 18885ad15de9..432c7cf71b23 100644
+--- a/tools/memory-model/linux-kernel.bell
++++ b/tools/memory-model/linux-kernel.bell
+@@ -24,7 +24,6 @@ instructions RMW[{'once,'acquire,'release}]
+ enum Barriers = 'wmb (*smp_wmb*) ||
+ 		'rmb (*smp_rmb*) ||
+ 		'mb (*smp_mb*) ||
+-		'rb_dep (*smp_read_barrier_depends*) ||
+ 		'rcu-lock (*rcu_read_lock*)  ||
+ 		'rcu-unlock (*rcu_read_unlock*) ||
+ 		'sync-rcu (*synchronize_rcu*) ||
+diff --git a/tools/memory-model/linux-kernel.cat b/tools/memory-model/linux-kernel.cat
+index f0d27f813ec2..df97db03b6c2 100644
+--- a/tools/memory-model/linux-kernel.cat
++++ b/tools/memory-model/linux-kernel.cat
+@@ -25,7 +25,6 @@ include "lock.cat"
+ (*******************)
+ 
+ (* Fences *)
+-let rb-dep = [R] ; fencerel(Rb_dep) ; [R]
+ let rmb = [R \ Noreturn] ; fencerel(Rmb) ; [R \ Noreturn]
+ let wmb = [W] ; fencerel(Wmb) ; [W]
+ let mb = ([M] ; fencerel(Mb) ; [M]) |
+@@ -61,11 +60,9 @@ let dep = addr | data
+ let rwdep = (dep | ctrl) ; [W]
+ let overwrite = co | fr
+ let to-w = rwdep | (overwrite & int)
+-let rrdep = addr | (dep ; rfi)
+-let strong-rrdep = rrdep+ & rb-dep
+-let to-r = strong-rrdep | rfi-rel-acq
++let to-r = addr | (dep ; rfi) | rfi-rel-acq
+ let fence = strong-fence | wmb | po-rel | rmb | acq-po
+-let ppo = rrdep* ; (to-r | to-w | fence)
++let ppo = to-r | to-w | fence
+ 
+ (* Propagation: Ordering from release operations and strong fences. *)
+ let A-cumul(r) = rfe? ; r
+diff --git a/tools/memory-model/linux-kernel.def b/tools/memory-model/linux-kernel.def
+index f5a1eb04cb64..5dfb9c7f3462 100644
+--- a/tools/memory-model/linux-kernel.def
++++ b/tools/memory-model/linux-kernel.def
+@@ -13,14 +13,12 @@ WRITE_ONCE(X,V) { __store{once}(X,V); }
+ smp_store_release(X,V) { __store{release}(*X,V); }
+ smp_load_acquire(X) __load{acquire}(*X)
+ rcu_assign_pointer(X,V) { __store{release}(X,V); }
+-lockless_dereference(X) __load{lderef}(X)
+ rcu_dereference(X) __load{deref}(X)
+ 
+ // Fences
+ smp_mb() { __fence{mb} ; }
+ smp_rmb() { __fence{rmb} ; }
+ smp_wmb() { __fence{wmb} ; }
+-smp_read_barrier_depends() { __fence{rb_dep}; }
+ smp_mb__before_atomic() { __fence{before-atomic} ; }
+ smp_mb__after_atomic() { __fence{after-atomic} ; }
+ smp_mb__after_spinlock() { __fence{after-spinlock} ; }

commit 556bb7d252ae42d4653557325670e665087c38ad
+Author: Alan Stern 
+Date:   Tue Feb 20 15:25:10 2018 -0800
+
+    tools/memory-model: Add a S lock-based external-view litmus test
+    
+    This commit adds a litmus test in which P0() and P1() form a lock-based S
+    litmus test, with the addition of P2(), which observes P0()'s and P1()'s
+    accesses with a full memory barrier but without the lock.  This litmus
+    test asks whether writes carried out by two different processes under the
+    same lock will be seen in order by a third process not holding that lock.
+    The answer to this question is "yes" for all architectures supporting
+    the Linux kernel, but is "no" according to the current version of LKMM.
+    
+    A patch to LKMM is under development.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Paul E. McKenney 
+    Acked-by: Peter Zijlstra 
+    Cc: Linus Torvalds 
+    Cc: Thomas Gleixner 
+    Cc: akiyks@gmail.com
+    Cc: boqun.feng@gmail.com
+    Cc: dhowells@redhat.com
+    Cc: j.alglave@ucl.ac.uk
+    Cc: linux-arch@vger.kernel.org
+    Cc: luc.maranget@inria.fr
+    Cc: nborisov@suse.com
+    Cc: npiggin@gmail.com
+    Cc: parri.andrea@gmail.com
+    Cc: will.deacon@arm.com
+    Link: http://lkml.kernel.org/r/1519169112-20593-10-git-send-email-paulmck@linux.vnet.ibm.com
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/tools/memory-model/litmus-tests/ISA2+pooncelock+pooncelock+pombonce.litmus b/tools/memory-model/litmus-tests/ISA2+pooncelock+pooncelock+pombonce.litmus
+new file mode 100644
+index 000000000000..7a39a0aaa976
+--- /dev/null
++++ b/tools/memory-model/litmus-tests/ISA2+pooncelock+pooncelock+pombonce.litmus
+@@ -0,0 +1,41 @@
++C ISA2+pooncelock+pooncelock+pombonce.litmus
++
++(*
++ * Result: Sometimes
++ *
++ * This test shows that the ordering provided by a lock-protected S
++ * litmus test (P0() and P1()) are not visible to external process P2().
++ * This is likely to change soon.
++ *)
++
++{}
++
++P0(int *x, int *y, spinlock_t *mylock)
++{
++	spin_lock(mylock);
++	WRITE_ONCE(*x, 1);
++	WRITE_ONCE(*y, 1);
++	spin_unlock(mylock);
++}
++
++P1(int *y, int *z, spinlock_t *mylock)
++{
++	int r0;
++
++	spin_lock(mylock);
++	r0 = READ_ONCE(*y);
++	WRITE_ONCE(*z, 1);
++	spin_unlock(mylock);
++}
++
++P2(int *x, int *z)
++{
++	int r1;
++	int r2;
++
++	r2 = READ_ONCE(*z);
++	smp_mb();
++	r1 = READ_ONCE(*x);
++}
++
++exists (1:r0=1 /\ 2:r2=1 /\ 2:r1=0)

commit 7ae2c3c280db183ca9ada2675c34ec2f7378abfa
+Author: Alan Stern 
+Date:   Wed Jan 3 12:51:51 2018 -0500
+
+    USB: UDC core: fix double-free in usb_add_gadget_udc_release
+    
+    The error-handling pathways in usb_add_gadget_udc_release() are messed
+    up.  Aside from the uninformative statement labels, they can deallocate
+    the udc structure after calling put_device(), which is a double-free.
+    This was observed by KASAN in automatic testing.
+    
+    This patch cleans up the routine.  It preserves the requirement that
+    when any failure occurs, we call put_device(&gadget->dev).
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Fengguang Wu 
+    CC: 
+    Reviewed-by: Peter Chen 
+    Acked-by: Felipe Balbi 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
+index 93eff7dec2f5..1b3efb14aec7 100644
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -1147,11 +1147,7 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
+ 
+ 	udc = kzalloc(sizeof(*udc), GFP_KERNEL);
+ 	if (!udc)
+-		goto err1;
+-
+-	ret = device_add(&gadget->dev);
+-	if (ret)
+-		goto err2;
++		goto err_put_gadget;
+ 
+ 	device_initialize(&udc->dev);
+ 	udc->dev.release = usb_udc_release;
+@@ -1160,7 +1156,11 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
+ 	udc->dev.parent = parent;
+ 	ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj));
+ 	if (ret)
+-		goto err3;
++		goto err_put_udc;
++
++	ret = device_add(&gadget->dev);
++	if (ret)
++		goto err_put_udc;
+ 
+ 	udc->gadget = gadget;
+ 	gadget->udc = udc;
+@@ -1170,7 +1170,7 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
+ 
+ 	ret = device_add(&udc->dev);
+ 	if (ret)
+-		goto err4;
++		goto err_unlist_udc;
+ 
+ 	usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
+ 	udc->vbus = true;
+@@ -1178,27 +1178,25 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
+ 	/* pick up one of pending gadget drivers */
+ 	ret = check_pending_gadget_drivers(udc);
+ 	if (ret)
+-		goto err5;
++		goto err_del_udc;
+ 
+ 	mutex_unlock(&udc_lock);
+ 
+ 	return 0;
+ 
+-err5:
++ err_del_udc:
+ 	device_del(&udc->dev);
+ 
+-err4:
++ err_unlist_udc:
+ 	list_del(&udc->list);
+ 	mutex_unlock(&udc_lock);
+ 
+-err3:
+-	put_device(&udc->dev);
+ 	device_del(&gadget->dev);
+ 
+-err2:
+-	kfree(udc);
++ err_put_udc:
++	put_device(&udc->dev);
+ 
+-err1:
++ err_put_gadget:
+ 	put_device(&gadget->dev);
+ 	return ret;
+ }

commit 48a4ff1c7bb5a32d2e396b03132d20d552c0eca7
+Author: Alan Stern 
+Date:   Tue Dec 12 14:25:13 2017 -0500
+
+    USB: core: prevent malicious bNumInterfaces overflow
+    
+    A malicious USB device with crafted descriptors can cause the kernel
+    to access unallocated memory by setting the bNumInterfaces value too
+    high in a configuration descriptor.  Although the value is adjusted
+    during parsing, this adjustment is skipped in one of the error return
+    paths.
+    
+    This patch prevents the problem by setting bNumInterfaces to 0
+    initially.  The existing code already sets it to the proper value
+    after parsing is complete.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Andrey Konovalov 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
+index 55b198ba629b..78e92d29f8d9 100644
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -555,6 +555,9 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+ 	unsigned iad_num = 0;
+ 
+ 	memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE);
++	nintf = nintf_orig = config->desc.bNumInterfaces;
++	config->desc.bNumInterfaces = 0;	// Adjusted later
++
+ 	if (config->desc.bDescriptorType != USB_DT_CONFIG ||
+ 	    config->desc.bLength < USB_DT_CONFIG_SIZE ||
+ 	    config->desc.bLength > size) {
+@@ -568,7 +571,6 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
+ 	buffer += config->desc.bLength;
+ 	size -= config->desc.bLength;
+ 
+-	nintf = nintf_orig = config->desc.bNumInterfaces;
+ 	if (nintf > USB_MAXINTERFACES) {
+ 		dev_warn(ddev, "config %d has too many interfaces: %d, "
+ 		    "using maximum allowed: %d\n",

commit aa15d3d257f9edcb8d15ed27e228d1c0080cb919
+Author: Alan Stern 
+Date:   Mon Dec 11 11:58:21 2017 -0500
+
+    USB: remove the URB_NO_FSBR flag
+    
+    The URB_NO_FSBR flag has never really been used.  It was introduced as
+    a potential way for UHCI to minimize PCI bus usage (by not attempting
+    full-speed bulk and control transfers more than once per frame), but
+    the flag was not set by any drivers.
+    
+    There's no point in keeping it around.  This patch simplifies the API
+    by removing it.  Unfortunately, it does have to be kept as part of the
+    usbfs ABI, but at least we can document in
+    include/uapi/linux/usbdevice_fs.h that it doesn't do anything.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Shuah Khan 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/usb/usbip_protocol.txt b/Documentation/usb/usbip_protocol.txt
+index 16b6fe27284c..c7a0f4c7e7f1 100644
+--- a/Documentation/usb/usbip_protocol.txt
++++ b/Documentation/usb/usbip_protocol.txt
+@@ -274,7 +274,6 @@ USBIP_CMD_SUBMIT: Submit an URB
+   URB_SHORT_NOT_OK        | 0x00000001 | only in | only in   | only in  | no
+   URB_ISO_ASAP            | 0x00000002 | no      | no        | no       | yes
+   URB_NO_TRANSFER_DMA_MAP | 0x00000004 | yes     | yes       | yes      | yes
+-  URB_NO_FSBR             | 0x00000020 | yes     | no        | no       | no
+   URB_ZERO_PACKET         | 0x00000040 | no      | no        | only out | no
+   URB_NO_INTERRUPT        | 0x00000080 | yes     | yes       | yes      | yes
+   URB_FREE_BUFFER         | 0x00000100 | yes     | yes       | yes      | yes
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 705c573d0257..808b370f1737 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -1677,8 +1677,6 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
+ 		u |= URB_ISO_ASAP;
+ 	if (uurb->flags & USBDEVFS_URB_SHORT_NOT_OK && is_in)
+ 		u |= URB_SHORT_NOT_OK;
+-	if (uurb->flags & USBDEVFS_URB_NO_FSBR)
+-		u |= URB_NO_FSBR;
+ 	if (uurb->flags & USBDEVFS_URB_ZERO_PACKET)
+ 		u |= URB_ZERO_PACKET;
+ 	if (uurb->flags & USBDEVFS_URB_NO_INTERRUPT)
+diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
+index 9fdf137c4865..796c9b149728 100644
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -479,9 +479,6 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 		if (is_out)
+ 			allowed |= URB_ZERO_PACKET;
+ 		/* FALLTHROUGH */
+-	case USB_ENDPOINT_XFER_CONTROL:
+-		allowed |= URB_NO_FSBR;	/* only affects UHCI */
+-		/* FALLTHROUGH */
+ 	default:			/* all non-iso endpoints */
+ 		if (!is_out)
+ 			allowed |= URB_SHORT_NOT_OK;
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index d40438238938..35fcb826152c 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -73,8 +73,7 @@ static void uhci_add_fsbr(struct uhci_hcd *uhci, struct urb *urb)
+ {
+ 	struct urb_priv *urbp = urb->hcpriv;
+ 
+-	if (!(urb->transfer_flags & URB_NO_FSBR))
+-		urbp->fsbr = 1;
++	urbp->fsbr = 1;
+ }
+ 
+ static void uhci_urbp_wants_fsbr(struct uhci_hcd *uhci, struct urb_priv *urbp)
+diff --git a/drivers/usb/usbip/stub_rx.c b/drivers/usb/usbip/stub_rx.c
+index 536e037f541f..7a9aa9ff485d 100644
+--- a/drivers/usb/usbip/stub_rx.c
++++ b/drivers/usb/usbip/stub_rx.c
+@@ -412,9 +412,6 @@ static void masking_bogus_flags(struct urb *urb)
+ 		if (is_out)
+ 			allowed |= URB_ZERO_PACKET;
+ 		/* FALLTHROUGH */
+-	case USB_ENDPOINT_XFER_CONTROL:
+-		allowed |= URB_NO_FSBR;	/* only affects UHCI */
+-		/* FALLTHROUGH */
+ 	default:			/* all non-iso endpoints */
+ 		if (!is_out)
+ 			allowed |= URB_SHORT_NOT_OK;
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index fbbe974661f2..fe665a0d5bce 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -1293,7 +1293,6 @@ extern int usb_disabled(void);
+ #define URB_ISO_ASAP		0x0002	/* iso-only; use the first unexpired
+ 					 * slot in the schedule */
+ #define URB_NO_TRANSFER_DMA_MAP	0x0004	/* urb->transfer_dma valid on submit */
+-#define URB_NO_FSBR		0x0020	/* UHCI-specific */
+ #define URB_ZERO_PACKET		0x0040	/* Finish bulk OUT with short packet */
+ #define URB_NO_INTERRUPT	0x0080	/* HINT: no non-error interrupt
+ 					 * needed */
+diff --git a/include/uapi/linux/usbdevice_fs.h b/include/uapi/linux/usbdevice_fs.h
+index 70ed5338d447..964e87217be4 100644
+--- a/include/uapi/linux/usbdevice_fs.h
++++ b/include/uapi/linux/usbdevice_fs.h
+@@ -79,7 +79,7 @@ struct usbdevfs_connectinfo {
+ #define USBDEVFS_URB_SHORT_NOT_OK	0x01
+ #define USBDEVFS_URB_ISO_ASAP		0x02
+ #define USBDEVFS_URB_BULK_CONTINUATION	0x04
+-#define USBDEVFS_URB_NO_FSBR		0x20
++#define USBDEVFS_URB_NO_FSBR		0x20	/* Not used */
+ #define USBDEVFS_URB_ZERO_PACKET	0x40
+ #define USBDEVFS_URB_NO_INTERRUPT	0x80
+ 

commit 2ef47001b3ee3ded579b7532ebdcf8680e4d8c54
+Author: Alan Stern 
+Date:   Wed Nov 8 12:23:17 2017 -0500
+
+    USB: usbfs: compute urb->actual_length for isochronous
+    
+    The USB kerneldoc says that the actual_length field "is read in
+    non-iso completion functions", but the usbfs driver uses it for all
+    URB types in processcompl().  Since not all of the host controller
+    drivers set actual_length for isochronous URBs, programs using usbfs
+    with some host controllers don't work properly.  For example, Minas
+    reports that a USB camera controlled by libusb doesn't work properly
+    with a dwc2 controller.
+    
+    It doesn't seem worthwhile to change the HCDs and the documentation,
+    since the in-kernel USB class drivers evidently don't rely on
+    actual_length for isochronous transfers.  The easiest solution is for
+    usbfs to calculate the actual_length value for itself, by adding up
+    the lengths of the individual packets in an isochronous transfer.
+    
+    Signed-off-by: Alan Stern 
+    CC: Minas Harutyunyan 
+    Reported-and-tested-by: wlf 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index c3aaafc25a04..2edb4e7b2ab8 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -1820,6 +1820,18 @@ static int proc_unlinkurb(struct usb_dev_state *ps, void __user *arg)
+ 	return 0;
+ }
+ 
++static void compute_isochronous_actual_length(struct urb *urb)
++{
++	unsigned int i;
++
++	if (urb->number_of_packets > 0) {
++		urb->actual_length = 0;
++		for (i = 0; i < urb->number_of_packets; i++)
++			urb->actual_length +=
++					urb->iso_frame_desc[i].actual_length;
++	}
++}
++
+ static int processcompl(struct async *as, void __user * __user *arg)
+ {
+ 	struct urb *urb = as->urb;
+@@ -1827,6 +1839,7 @@ static int processcompl(struct async *as, void __user * __user *arg)
+ 	void __user *addr = as->userurb;
+ 	unsigned int i;
+ 
++	compute_isochronous_actual_length(urb);
+ 	if (as->userbuffer && urb->actual_length) {
+ 		if (copy_urb_data_to_user(as->userbuffer, urb))
+ 			goto err_out;
+@@ -1995,6 +2008,7 @@ static int processcompl_compat(struct async *as, void __user * __user *arg)
+ 	void __user *addr = as->userurb;
+ 	unsigned int i;
+ 
++	compute_isochronous_actual_length(urb);
+ 	if (as->userbuffer && urb->actual_length) {
+ 		if (copy_urb_data_to_user(as->userbuffer, urb))
+ 			return -EFAULT;

commit 32bf9fd50ff439184ddcf925cfb3c6bc0138f7c5
+Author: Alan Stern 
+Date:   Wed Oct 25 10:40:05 2017 -0400
+
+    usb-storage: make use of srb local variable
+    
+    Commit 8b52291a0743 ("usb-storage: fix deadlock involving host lock
+    and scsi_done") added a local variable to usb_stor_control_thread() in
+    the usb-storage driver.  This local variable holds the value of
+    us->srb, for use after the host lock has been released.
+    
+    But as long as we have the value in a local variable, we may as well
+    use it instead of dereferencing the us pointer all over the place.
+    This patch makes no functional change; it just makes the code a little
+    shorter and a little neater.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 0dceb9fa3a06..1ae2b8554a88 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -332,7 +332,7 @@ static int usb_stor_control_thread(void * __us)
+ 
+ 		/* When we are called with no command pending, we're done */
+ 		srb = us->srb;
+-		if (us->srb == NULL) {
++		if (srb == NULL) {
+ 			scsi_unlock(host);
+ 			mutex_unlock(&us->dev_mutex);
+ 			usb_stor_dbg(us, "-- exiting\n");
+@@ -341,7 +341,7 @@ static int usb_stor_control_thread(void * __us)
+ 
+ 		/* has the command timed out *already* ? */
+ 		if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
+-			us->srb->result = DID_ABORT << 16;
++			srb->result = DID_ABORT << 16;
+ 			goto SkipForAbort;
+ 		}
+ 
+@@ -351,35 +351,35 @@ static int usb_stor_control_thread(void * __us)
+ 		 * reject the command if the direction indicator
+ 		 * is UNKNOWN
+ 		 */
+-		if (us->srb->sc_data_direction == DMA_BIDIRECTIONAL) {
++		if (srb->sc_data_direction == DMA_BIDIRECTIONAL) {
+ 			usb_stor_dbg(us, "UNKNOWN data direction\n");
+-			us->srb->result = DID_ERROR << 16;
++			srb->result = DID_ERROR << 16;
+ 		}
+ 
+ 		/*
+ 		 * reject if target != 0 or if LUN is higher than
+ 		 * the maximum known LUN
+ 		 */
+-		else if (us->srb->device->id &&
++		else if (srb->device->id &&
+ 				!(us->fflags & US_FL_SCM_MULT_TARG)) {
+ 			usb_stor_dbg(us, "Bad target number (%d:%llu)\n",
+-				     us->srb->device->id,
+-				     us->srb->device->lun);
+-			us->srb->result = DID_BAD_TARGET << 16;
++				     srb->device->id,
++				     srb->device->lun);
++			srb->result = DID_BAD_TARGET << 16;
+ 		}
+ 
+-		else if (us->srb->device->lun > us->max_lun) {
++		else if (srb->device->lun > us->max_lun) {
+ 			usb_stor_dbg(us, "Bad LUN (%d:%llu)\n",
+-				     us->srb->device->id,
+-				     us->srb->device->lun);
+-			us->srb->result = DID_BAD_TARGET << 16;
++				     srb->device->id,
++				     srb->device->lun);
++			srb->result = DID_BAD_TARGET << 16;
+ 		}
+ 
+ 		/*
+ 		 * Handle those devices which need us to fake
+ 		 * their inquiry data
+ 		 */
+-		else if ((us->srb->cmnd[0] == INQUIRY) &&
++		else if ((srb->cmnd[0] == INQUIRY) &&
+ 			    (us->fflags & US_FL_FIX_INQUIRY)) {
+ 			unsigned char data_ptr[36] = {
+ 			    0x00, 0x80, 0x02, 0x02,
+@@ -387,13 +387,13 @@ static int usb_stor_control_thread(void * __us)
+ 
+ 			usb_stor_dbg(us, "Faking INQUIRY command\n");
+ 			fill_inquiry_response(us, data_ptr, 36);
+-			us->srb->result = SAM_STAT_GOOD;
++			srb->result = SAM_STAT_GOOD;
+ 		}
+ 
+ 		/* we've got a command, let's do it! */
+ 		else {
+-			US_DEBUG(usb_stor_show_command(us, us->srb));
+-			us->proto_handler(us->srb, us);
++			US_DEBUG(usb_stor_show_command(us, srb));
++			us->proto_handler(srb, us);
+ 			usb_mark_last_busy(us->pusb_dev);
+ 		}
+ 
+@@ -401,7 +401,7 @@ static int usb_stor_control_thread(void * __us)
+ 		scsi_lock(host);
+ 
+ 		/* was the command aborted? */
+-		if (us->srb->result == DID_ABORT << 16) {
++		if (srb->result == DID_ABORT << 16) {
+ SkipForAbort:
+ 			usb_stor_dbg(us, "scsi command aborted\n");
+ 			srb = NULL;	/* Don't call srb->scsi_done() */

commit 1c0edc3633b56000e18d82fc241e3995ca18a69e
+Author: Alan Stern 
+Date:   Wed Oct 18 12:49:38 2017 -0400
+
+    USB: core: fix out-of-bounds access bug in usb_get_bos_descriptor()
+    
+    Andrey used the syzkaller fuzzer to find an out-of-bounds memory
+    access in usb_get_bos_descriptor().  The code wasn't checking that the
+    next usb_dev_cap_header structure could fit into the remaining buffer
+    space.
+    
+    This patch fixes the error and also reduces the bNumDeviceCaps field
+    in the header to match the actual number of capabilities found, in
+    cases where there are fewer than expected.
+    
+    Reported-by: Andrey Konovalov 
+    Signed-off-by: Alan Stern 
+    Tested-by: Andrey Konovalov 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
+index 68b54bd88d1e..883549ee946c 100644
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -960,10 +960,12 @@ int usb_get_bos_descriptor(struct usb_device *dev)
+ 	for (i = 0; i < num; i++) {
+ 		buffer += length;
+ 		cap = (struct usb_dev_cap_header *)buffer;
+-		length = cap->bLength;
+ 
+-		if (total_len < length)
++		if (total_len < sizeof(*cap) || total_len < cap->bLength) {
++			dev->bos->desc->bNumDeviceCaps = i;
+ 			break;
++		}
++		length = cap->bLength;
+ 		total_len -= length;
+ 
+ 		if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) {

commit 7c80f9e4a588f1925b07134bb2e3689335f6c6d8
+Author: Alan Stern 
+Date:   Fri Sep 29 10:54:24 2017 -0400
+
+    usb: usbtest: fix NULL pointer dereference
+    
+    If the usbtest driver encounters a device with an IN bulk endpoint but
+    no OUT bulk endpoint, it will try to dereference a NULL pointer
+    (out->desc.bEndpointAddress).  The problem can be solved by adding a
+    missing test.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Andrey Konovalov 
+    Tested-by: Andrey Konovalov 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
+index 113e38bfe0ef..b3fc602b2e24 100644
+--- a/drivers/usb/misc/usbtest.c
++++ b/drivers/usb/misc/usbtest.c
+@@ -202,12 +202,13 @@ get_endpoints(struct usbtest_dev *dev, struct usb_interface *intf)
+ 			return tmp;
+ 	}
+ 
+-	if (in) {
++	if (in)
+ 		dev->in_pipe = usb_rcvbulkpipe(udev,
+ 			in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
++	if (out)
+ 		dev->out_pipe = usb_sndbulkpipe(udev,
+ 			out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+-	}
++
+ 	if (iso_in) {
+ 		dev->iso_in = &iso_in->desc;
+ 		dev->in_iso_pipe = usb_rcvisocpipe(udev,

commit ab219221a5064abfff9f78c323c4a257b16cdb81
+Author: Alan Stern 
+Date:   Fri Oct 6 10:27:44 2017 -0400
+
+    USB: dummy-hcd: Fix deadlock caused by disconnect detection
+    
+    The dummy-hcd driver calls the gadget driver's disconnect callback
+    under the wrong conditions.  It should invoke the callback when Vbus
+    power is turned off, but instead it does so when the D+ pullup is
+    turned off.
+    
+    This can cause a deadlock in the composite core when a gadget driver
+    is unregistered:
+    
+    [   88.361471] ============================================
+    [   88.362014] WARNING: possible recursive locking detected
+    [   88.362580] 4.14.0-rc2+ #9 Not tainted
+    [   88.363010] --------------------------------------------
+    [   88.363561] v4l_id/526 is trying to acquire lock:
+    [   88.364062]  (&(&cdev->lock)->rlock){....}, at: [] composite_disconnect+0x43/0x100 [libcomposite]
+    [   88.365051]
+    [   88.365051] but task is already holding lock:
+    [   88.365826]  (&(&cdev->lock)->rlock){....}, at: [] usb_function_deactivate+0x29/0x80 [libcomposite]
+    [   88.366858]
+    [   88.366858] other info that might help us debug this:
+    [   88.368301]  Possible unsafe locking scenario:
+    [   88.368301]
+    [   88.369304]        CPU0
+    [   88.369701]        ----
+    [   88.370101]   lock(&(&cdev->lock)->rlock);
+    [   88.370623]   lock(&(&cdev->lock)->rlock);
+    [   88.371145]
+    [   88.371145]  *** DEADLOCK ***
+    [   88.371145]
+    [   88.372211]  May be due to missing lock nesting notation
+    [   88.372211]
+    [   88.373191] 2 locks held by v4l_id/526:
+    [   88.373715]  #0:  (&(&cdev->lock)->rlock){....}, at: [] usb_function_deactivate+0x29/0x80 [libcomposite]
+    [   88.374814]  #1:  (&(&dum_hcd->dum->lock)->rlock){....}, at: [] dummy_pullup+0x7d/0xf0 [dummy_hcd]
+    [   88.376289]
+    [   88.376289] stack backtrace:
+    [   88.377726] CPU: 0 PID: 526 Comm: v4l_id Not tainted 4.14.0-rc2+ #9
+    [   88.378557] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1 04/01/2014
+    [   88.379504] Call Trace:
+    [   88.380019]  dump_stack+0x86/0xc7
+    [   88.380605]  __lock_acquire+0x841/0x1120
+    [   88.381252]  lock_acquire+0xd5/0x1c0
+    [   88.381865]  ? composite_disconnect+0x43/0x100 [libcomposite]
+    [   88.382668]  _raw_spin_lock_irqsave+0x40/0x54
+    [   88.383357]  ? composite_disconnect+0x43/0x100 [libcomposite]
+    [   88.384290]  composite_disconnect+0x43/0x100 [libcomposite]
+    [   88.385490]  set_link_state+0x2d4/0x3c0 [dummy_hcd]
+    [   88.386436]  dummy_pullup+0xa7/0xf0 [dummy_hcd]
+    [   88.387195]  usb_gadget_disconnect+0xd8/0x160 [udc_core]
+    [   88.387990]  usb_gadget_deactivate+0xd3/0x160 [udc_core]
+    [   88.388793]  usb_function_deactivate+0x64/0x80 [libcomposite]
+    [   88.389628]  uvc_function_disconnect+0x1e/0x40 [usb_f_uvc]
+    
+    This patch changes the code to test the port-power status bit rather
+    than the port-connect status bit when deciding whether to isue the
+    callback.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: David Tulloh 
+    CC: 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
+index b17618a55f1b..f04e91ef9e7c 100644
+--- a/drivers/usb/gadget/udc/dummy_hcd.c
++++ b/drivers/usb/gadget/udc/dummy_hcd.c
+@@ -419,6 +419,7 @@ static void set_link_state_by_speed(struct dummy_hcd *dum_hcd)
+ static void set_link_state(struct dummy_hcd *dum_hcd)
+ {
+ 	struct dummy *dum = dum_hcd->dum;
++	unsigned int power_bit;
+ 
+ 	dum_hcd->active = 0;
+ 	if (dum->pullup)
+@@ -429,17 +430,19 @@ static void set_link_state(struct dummy_hcd *dum_hcd)
+ 			return;
+ 
+ 	set_link_state_by_speed(dum_hcd);
++	power_bit = (dummy_hcd_to_hcd(dum_hcd)->speed == HCD_USB3 ?
++			USB_SS_PORT_STAT_POWER : USB_PORT_STAT_POWER);
+ 
+ 	if ((dum_hcd->port_status & USB_PORT_STAT_ENABLE) == 0 ||
+ 	     dum_hcd->active)
+ 		dum_hcd->resuming = 0;
+ 
+ 	/* Currently !connected or in reset */
+-	if ((dum_hcd->port_status & USB_PORT_STAT_CONNECTION) == 0 ||
++	if ((dum_hcd->port_status & power_bit) == 0 ||
+ 			(dum_hcd->port_status & USB_PORT_STAT_RESET) != 0) {
+-		unsigned disconnect = USB_PORT_STAT_CONNECTION &
++		unsigned int disconnect = power_bit &
+ 				dum_hcd->old_status & (~dum_hcd->port_status);
+-		unsigned reset = USB_PORT_STAT_RESET &
++		unsigned int reset = USB_PORT_STAT_RESET &
+ 				(~dum_hcd->old_status) & dum_hcd->port_status;
+ 
+ 		/* Report reset and disconnect events to the driver */

commit c9f20aafc939cc4091757c4d033feb010445f15d
+Author: Alan Stern 
+Date:   Tue Sep 26 15:15:58 2017 -0400
+
+    USB: dummy-hcd: remove unsupported isochronous endpoints
+    
+    The dummy-hcd driver doesn't support emulation of isochronous
+    transfers.  Therefore it doesn't need to export isochronous endpoint
+    descriptors; they can be commented out.
+    
+    Also, the comments in the source code don't express clearly enough the
+    fact that isochronous isn't supported.  They need to be more explicit.
+    
+    Finally, change the error status value we use (in theory) for
+    isochronous URBs.  checkpatch complains about ENOSYS; EINVAL is more
+    appropriate (it is documented to mean "ISO madness").
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Felipe Balbi 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
+index d177d63e16d7..671338827951 100644
+--- a/drivers/usb/gadget/udc/dummy_hcd.c
++++ b/drivers/usb/gadget/udc/dummy_hcd.c
+@@ -23,6 +23,8 @@
+  *
+  * Having this all in one kernel can help some stages of development,
+  * bypassing some hardware (and driver) issues.  UML could help too.
++ *
++ * Note: The emulation does not include isochronous transfers!
+  */
+ 
+ #include 
+@@ -137,6 +139,9 @@ static const struct {
+ 		.caps = _caps, \
+ 	}
+ 
++/* we don't provide isochronous endpoints since we don't support them */
++#define TYPE_BULK_OR_INT	(USB_EP_CAPS_TYPE_BULK | USB_EP_CAPS_TYPE_INT)
++
+ 	/* everyone has ep0 */
+ 	EP_INFO(ep0name,
+ 		USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
+@@ -145,64 +150,72 @@ static const struct {
+ 		USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ 	EP_INFO("ep2out-bulk",
+ 		USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
++/*
+ 	EP_INFO("ep3in-iso",
+ 		USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
+ 	EP_INFO("ep4out-iso",
+ 		USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
++*/
+ 	EP_INFO("ep5in-int",
+ 		USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
+ 	EP_INFO("ep6in-bulk",
+ 		USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ 	EP_INFO("ep7out-bulk",
+ 		USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
++/*
+ 	EP_INFO("ep8in-iso",
+ 		USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
+ 	EP_INFO("ep9out-iso",
+ 		USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
++*/
+ 	EP_INFO("ep10in-int",
+ 		USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
+ 	EP_INFO("ep11in-bulk",
+ 		USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ 	EP_INFO("ep12out-bulk",
+ 		USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
++/*
+ 	EP_INFO("ep13in-iso",
+ 		USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
+ 	EP_INFO("ep14out-iso",
+ 		USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
++*/
+ 	EP_INFO("ep15in-int",
+ 		USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
++
+ 	/* or like sa1100: two fixed function endpoints */
+ 	EP_INFO("ep1out-bulk",
+ 		USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ 	EP_INFO("ep2in-bulk",
+ 		USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
++
+ 	/* and now some generic EPs so we have enough in multi config */
+ 	EP_INFO("ep3out",
+-		USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
++		USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_OUT)),
+ 	EP_INFO("ep4in",
+-		USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
++		USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_IN)),
+ 	EP_INFO("ep5out",
+-		USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
++		USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_OUT)),
+ 	EP_INFO("ep6out",
+-		USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
++		USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_OUT)),
+ 	EP_INFO("ep7in",
+-		USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
++		USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_IN)),
+ 	EP_INFO("ep8out",
+-		USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
++		USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_OUT)),
+ 	EP_INFO("ep9in",
+-		USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
++		USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_IN)),
+ 	EP_INFO("ep10out",
+-		USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
++		USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_OUT)),
+ 	EP_INFO("ep11out",
+-		USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
++		USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_OUT)),
+ 	EP_INFO("ep12in",
+-		USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
++		USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_IN)),
+ 	EP_INFO("ep13out",
+-		USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
++		USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_OUT)),
+ 	EP_INFO("ep14in",
+-		USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
++		USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_IN)),
+ 	EP_INFO("ep15out",
+-		USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
++		USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_OUT)),
+ 
+ #undef EP_INFO
+ };
+@@ -1923,13 +1936,17 @@ static void dummy_timer(unsigned long _dum_hcd)
+ 		limit = total;
+ 		switch (usb_pipetype(urb->pipe)) {
+ 		case PIPE_ISOCHRONOUS:
+-			/* FIXME is it urb->interval since the last xfer?
+-			 * use urb->iso_frame_desc[i].
+-			 * complete whether or not ep has requests queued.
+-			 * report random errors, to debug drivers.
++			/*
++			 * We don't support isochronous.  But if we did,
++			 * here are some of the issues we'd have to face:
++			 *
++			 * Is it urb->interval since the last xfer?
++			 * Use urb->iso_frame_desc[i].
++			 * Complete whether or not ep has requests queued.
++			 * Report random errors, to debug drivers.
+ 			 */
+ 			limit = max(limit, periodic_bytes(dum, ep));
+-			status = -ENOSYS;
++			status = -EINVAL;	/* fail all xfers */
+ 			break;
+ 
+ 		case PIPE_INTERRUPT:

commit ffc4ea79bc06f42283da10ea06bb17b9a3e2b2b4
+Author: Alan Stern 
+Date:   Tue Sep 26 15:16:05 2017 -0400
+
+    USB: dummy-hcd: bandwidth limits for non-bulk transfers
+    
+    Part of the emulation performed by dummy-hcd is accounting for
+    bandwidth utilization.  The total amount of data transferred in a
+    single frame is supposed to be no larger than an actual USB connection
+    could accommodate.
+    
+    Currently the driver performs bandwidth limiting only for bulk
+    transfers; control and periodic transfers are effectively unlimited.
+    (Presumably drivers were not expected to request extremely large
+    control or interrupt transfers.)  This patch improves the situation
+    somewhat by restricting them as well.
+    
+    The emulation still isn't perfect.  On a real system, even 0-length
+    transfers use some bandwidth because of transaction overhead
+    (IN, OUT, ACK, NACK packets) and packet overhead (SYNC, PID, bit
+    stuffing, CRC, EOP).  Adding in those factors is left as an exercise
+    for a later patch.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
+index b17618a55f1b..d177d63e16d7 100644
+--- a/drivers/usb/gadget/udc/dummy_hcd.c
++++ b/drivers/usb/gadget/udc/dummy_hcd.c
+@@ -1766,6 +1766,7 @@ static void dummy_timer(unsigned long _dum_hcd)
+ 	int			i;
+ 
+ 	/* simplistic model for one frame's bandwidth */
++	/* FIXME: account for transaction and packet overhead */
+ 	switch (dum->gadget.speed) {
+ 	case USB_SPEED_LOW:
+ 		total = 8/*bytes*/ * 12/*packets*/;
+@@ -1810,7 +1811,6 @@ static void dummy_timer(unsigned long _dum_hcd)
+ 		struct dummy_request	*req;
+ 		u8			address;
+ 		struct dummy_ep		*ep = NULL;
+-		int			type;
+ 		int			status = -EINPROGRESS;
+ 
+ 		/* stop when we reach URBs queued after the timer interrupt */
+@@ -1822,14 +1822,10 @@ static void dummy_timer(unsigned long _dum_hcd)
+ 			goto return_urb;
+ 		else if (dum_hcd->rh_state != DUMMY_RH_RUNNING)
+ 			continue;
+-		type = usb_pipetype(urb->pipe);
+ 
+-		/* used up this frame's non-periodic bandwidth?
+-		 * FIXME there's infinite bandwidth for control and
+-		 * periodic transfers ... unrealistic.
+-		 */
+-		if (total <= 0 && type == PIPE_BULK)
+-			continue;
++		/* Used up this frame's bandwidth? */
++		if (total <= 0)
++			break;
+ 
+ 		/* find the gadget's ep for this request (if configured) */
+ 		address = usb_pipeendpoint (urb->pipe);

commit 0902b1f44a72558aece92f074154044861681f84
+Author: Alan Stern 
+Date:   Fri Sep 1 07:53:34 2017 -0700
+
+    memory-barriers: Rework multicopy-atomicity section
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Paul E. McKenney 
+
+diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
+index b6882680247e..7deee1441640 100644
+--- a/Documentation/memory-barriers.txt
++++ b/Documentation/memory-barriers.txt
+@@ -1343,13 +1343,13 @@ MULTICOPY ATOMICITY
+ 
+ Multicopy atomicity is a deeply intuitive notion about ordering that is
+ not always provided by real computer systems, namely that a given store
+-is visible at the same time to all CPUs, or, alternatively, that all
+-CPUs agree on the order in which all stores took place.  However, use of
+-full multicopy atomicity would rule out valuable hardware optimizations,
+-so a weaker form called ``other multicopy atomicity'' instead guarantees
+-that a given store is observed at the same time by all -other- CPUs.  The
+-remainder of this document discusses this weaker form, but for brevity
+-will call it simply ``multicopy atomicity''.
++becomes visible at the same time to all CPUs, or, alternatively, that all
++CPUs agree on the order in which all stores become visible.  However,
++support of full multicopy atomicity would rule out valuable hardware
++optimizations, so a weaker form called ``other multicopy atomicity''
++instead guarantees only that a given store becomes visible at the same
++time to all -other- CPUs.  The remainder of this document discusses this
++weaker form, but for brevity will call it simply ``multicopy atomicity''.
+ 
+ The following example demonstrates multicopy atomicity:
+ 
+@@ -1360,24 +1360,26 @@ The following example demonstrates multicopy atomicity:
+ 					
+ 				STORE Y=r1		LOAD X
+ 
+-Suppose that CPU 2's load from X returns 1 which it then stores to Y and
+-that CPU 3's load from Y returns 1.  This indicates that CPU 2's load
+-from X in some sense follows CPU 1's store to X and that CPU 2's store
+-to Y in some sense preceded CPU 3's load from Y.  The question is then
+-"Can CPU 3's load from X return 0?"
++Suppose that CPU 2's load from X returns 1, which it then stores to Y,
++and CPU 3's load from Y returns 1.  This indicates that CPU 1's store
++to X precedes CPU 2's load from X and that CPU 2's store to Y precedes
++CPU 3's load from Y.  In addition, the memory barriers guarantee that
++CPU 2 executes its load before its store, and CPU 3 loads from Y before
++it loads from X.  The question is then "Can CPU 3's load from X return 0?"
+ 
+-Because CPU 3's load from X in some sense came after CPU 2's load, it
++Because CPU 3's load from X in some sense comes after CPU 2's load, it
+ is natural to expect that CPU 3's load from X must therefore return 1.
+-This expectation is an example of multicopy atomicity: if a load executing
+-on CPU A follows a load from the same variable executing on CPU B, then
+-an understandable but incorrect expectation is that CPU A's load must
+-either return the same value that CPU B's load did, or must return some
+-later value.
+-
+-In the Linux kernel, the above use of a general memory barrier compensates
+-for any lack of multicopy atomicity.  Therefore, in the above example,
+-if CPU 2's load from X returns 1 and its load from Y returns 0, and CPU 3's
+-load from Y returns 1, then CPU 3's load from X must also return 1.
++This expectation follows from multicopy atomicity: if a load executing
++on CPU B follows a load from the same variable executing on CPU A (and
++CPU A did not originally store the value which it read), then on
++multicopy-atomic systems, CPU B's load must return either the same value
++that CPU A's load did or some later value.  However, the Linux kernel
++does not require systems to be multicopy atomic.
++
++The use of a general memory barrier in the example above compensates
++for any lack of multicopy atomicity.  In the example, if CPU 2's load
++from X returns 1 and CPU 3's load from Y returns 1, then CPU 3's load
++from X must indeed also return 1.
+ 
+ However, dependencies, read barriers, and write barriers are not always
+ able to compensate for non-multicopy atomicity.  For example, suppose
+@@ -1396,11 +1398,11 @@ this example, it is perfectly legal for CPU 2's load from X to return 1,
+ CPU 3's load from Y to return 1, and its load from X to return 0.
+ 
+ The key point is that although CPU 2's data dependency orders its load
+-and store, it does not guarantee to order CPU 1's store.  Therefore,
+-if this example runs on a non-multicopy-atomic system where CPUs 1 and 2
+-share a store buffer or a level of cache, CPU 2 might have early access
+-to CPU 1's writes.  A general barrier is therefore required to ensure
+-that all CPUs agree on the combined order of CPU 1's and CPU 2's accesses.
++and store, it does not guarantee to order CPU 1's store.  Thus, if this
++example runs on a non-multicopy-atomic system where CPUs 1 and 2 share a
++store buffer or a level of cache, CPU 2 might have early access to CPU 1's
++writes.  General barriers are therefore required to ensure that all CPUs
++agree on the combined order of multiple accesses.
+ 
+ General barriers can compensate not only for non-multicopy atomicity,
+ but can also generate additional ordering that can ensure that -all-

commit 7dbd8f4cabd96db5a50513de9d83a8105a5ffc81
+Author: Alan Stern 
+Date:   Tue Sep 26 15:15:49 2017 -0400
+
+    USB: dummy-hcd: Fix erroneous synchronization change
+    
+    A recent change to the synchronization in dummy-hcd was incorrect.
+    The issue was that dummy_udc_stop() contained no locking and therefore
+    could race with various gadget driver callbacks, and the fix was to
+    add locking and issue the callbacks with the private spinlock held.
+    
+    UDC drivers aren't supposed to do this.  Gadget driver callback
+    routines are allowed to invoke functions in the UDC driver, and these
+    functions will generally try to acquire the private spinlock.  This
+    would deadlock the driver.
+    
+    The correct solution is to drop the spinlock before issuing callbacks,
+    and avoid races by emulating the synchronize_irq() call that all real
+    UDC drivers must perform in their ->udc_stop() routines after
+    disabling interrupts.  This involves adding a flag to dummy-hcd's
+    private structure to keep track of whether interrupts are supposed to
+    be enabled, and adding a counter to keep track of ongoing callbacks so
+    that dummy_udc_stop() can wait for them all to finish.
+    
+    A real UDC driver won't receive disconnect, reset, suspend, resume, or
+    setup events once it has disabled interrupts.  dummy-hcd will receive
+    them but won't try to issue any gadget driver callbacks, which should
+    be just as good.
+    
+    Signed-off-by: Alan Stern 
+    Fixes: f16443a034c7 ("USB: gadgetfs, dummy-hcd, net2280: fix locking for callbacks")
+    CC: 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
+index b2ab9cc33fec..b17618a55f1b 100644
+--- a/drivers/usb/gadget/udc/dummy_hcd.c
++++ b/drivers/usb/gadget/udc/dummy_hcd.c
+@@ -255,11 +255,13 @@ struct dummy {
+ 	 */
+ 	struct dummy_ep			ep[DUMMY_ENDPOINTS];
+ 	int				address;
++	int				callback_usage;
+ 	struct usb_gadget		gadget;
+ 	struct usb_gadget_driver	*driver;
+ 	struct dummy_request		fifo_req;
+ 	u8				fifo_buf[FIFO_SIZE];
+ 	u16				devstatus;
++	unsigned			ints_enabled:1;
+ 	unsigned			udc_suspended:1;
+ 	unsigned			pullup:1;
+ 
+@@ -441,18 +443,27 @@ static void set_link_state(struct dummy_hcd *dum_hcd)
+ 				(~dum_hcd->old_status) & dum_hcd->port_status;
+ 
+ 		/* Report reset and disconnect events to the driver */
+-		if (dum->driver && (disconnect || reset)) {
++		if (dum->ints_enabled && (disconnect || reset)) {
+ 			stop_activity(dum);
++			++dum->callback_usage;
++			spin_unlock(&dum->lock);
+ 			if (reset)
+ 				usb_gadget_udc_reset(&dum->gadget, dum->driver);
+ 			else
+ 				dum->driver->disconnect(&dum->gadget);
++			spin_lock(&dum->lock);
++			--dum->callback_usage;
+ 		}
+-	} else if (dum_hcd->active != dum_hcd->old_active) {
++	} else if (dum_hcd->active != dum_hcd->old_active &&
++			dum->ints_enabled) {
++		++dum->callback_usage;
++		spin_unlock(&dum->lock);
+ 		if (dum_hcd->old_active && dum->driver->suspend)
+ 			dum->driver->suspend(&dum->gadget);
+ 		else if (!dum_hcd->old_active &&  dum->driver->resume)
+ 			dum->driver->resume(&dum->gadget);
++		spin_lock(&dum->lock);
++		--dum->callback_usage;
+ 	}
+ 
+ 	dum_hcd->old_status = dum_hcd->port_status;
+@@ -973,8 +984,11 @@ static int dummy_udc_start(struct usb_gadget *g,
+ 	 * can't enumerate without help from the driver we're binding.
+ 	 */
+ 
++	spin_lock_irq(&dum->lock);
+ 	dum->devstatus = 0;
+ 	dum->driver = driver;
++	dum->ints_enabled = 1;
++	spin_unlock_irq(&dum->lock);
+ 
+ 	return 0;
+ }
+@@ -985,6 +999,16 @@ static int dummy_udc_stop(struct usb_gadget *g)
+ 	struct dummy		*dum = dum_hcd->dum;
+ 
+ 	spin_lock_irq(&dum->lock);
++	dum->ints_enabled = 0;
++	stop_activity(dum);
++
++	/* emulate synchronize_irq(): wait for callbacks to finish */
++	while (dum->callback_usage > 0) {
++		spin_unlock_irq(&dum->lock);
++		usleep_range(1000, 2000);
++		spin_lock_irq(&dum->lock);
++	}
++
+ 	dum->driver = NULL;
+ 	spin_unlock_irq(&dum->lock);
+ 
+@@ -1529,6 +1553,8 @@ static struct dummy_ep *find_endpoint(struct dummy *dum, u8 address)
+ 	if (!is_active((dum->gadget.speed == USB_SPEED_SUPER ?
+ 			dum->ss_hcd : dum->hs_hcd)))
+ 		return NULL;
++	if (!dum->ints_enabled)
++		return NULL;
+ 	if ((address & ~USB_DIR_IN) == 0)
+ 		return &dum->ep[0];
+ 	for (i = 1; i < DUMMY_ENDPOINTS; i++) {
+@@ -1870,10 +1896,12 @@ static void dummy_timer(unsigned long _dum_hcd)
+ 			 * until setup() returns; no reentrancy issues etc.
+ 			 */
+ 			if (value > 0) {
++				++dum->callback_usage;
+ 				spin_unlock(&dum->lock);
+ 				value = dum->driver->setup(&dum->gadget,
+ 						&setup);
+ 				spin_lock(&dum->lock);
++				--dum->callback_usage;
+ 
+ 				if (value >= 0) {
+ 					/* no delays (max 64KB data stage) */

commit 0173a68bfb0ad1c72a6ee39cc485aa2c97540b98
+Author: Alan Stern 
+Date:   Tue Sep 26 15:15:40 2017 -0400
+
+    USB: dummy-hcd: fix infinite-loop resubmission bug
+    
+    The dummy-hcd HCD/UDC emulator tries not to do too much work during
+    each timer interrupt.  But it doesn't try very hard; currently all
+    it does is limit the total amount of bulk data transferred.  Other
+    transfer types aren't limited, and URBs that transfer no data (because
+    of an error, perhaps) don't count toward the limit, even though on a
+    real USB bus they would consume at least a minimum overhead.
+    
+    This means it's possible to get the driver stuck in an infinite loop,
+    for example, if the host class driver resubmits an URB every time it
+    completes (which is common for interrupt URBs).  Each time the URB is
+    resubmitted it gets added to the end of the pending-URBs list, and
+    dummy-hcd doesn't stop until that list is empty.  Andrey Konovalov was
+    able to trigger this failure mode using the syzkaller fuzzer.
+    
+    This patch fixes the infinite-loop problem by restricting the URBs
+    handled during each timer interrupt to those that were already on the
+    pending list when the interrupt routine started.  Newly added URBs
+    won't be processed until the next timer interrupt.  The problem of
+    properly accounting for non-bulk bandwidth (as well as packet and
+    transaction overhead) is not addressed here.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Andrey Konovalov 
+    Tested-by: Andrey Konovalov 
+    CC: 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
+index d515ec31afe4..b2ab9cc33fec 100644
+--- a/drivers/usb/gadget/udc/dummy_hcd.c
++++ b/drivers/usb/gadget/udc/dummy_hcd.c
+@@ -237,6 +237,8 @@ struct dummy_hcd {
+ 
+ 	struct usb_device		*udev;
+ 	struct list_head		urbp_list;
++	struct urbp			*next_frame_urbp;
++
+ 	u32				stream_en_ep;
+ 	u8				num_stream[30 / 2];
+ 
+@@ -1250,6 +1252,8 @@ static int dummy_urb_enqueue(
+ 
+ 	list_add_tail(&urbp->urbp_list, &dum_hcd->urbp_list);
+ 	urb->hcpriv = urbp;
++	if (!dum_hcd->next_frame_urbp)
++		dum_hcd->next_frame_urbp = urbp;
+ 	if (usb_pipetype(urb->pipe) == PIPE_CONTROL)
+ 		urb->error_count = 1;		/* mark as a new urb */
+ 
+@@ -1766,6 +1770,7 @@ static void dummy_timer(unsigned long _dum_hcd)
+ 		spin_unlock_irqrestore(&dum->lock, flags);
+ 		return;
+ 	}
++	dum_hcd->next_frame_urbp = NULL;
+ 
+ 	for (i = 0; i < DUMMY_ENDPOINTS; i++) {
+ 		if (!ep_info[i].name)
+@@ -1782,6 +1787,10 @@ static void dummy_timer(unsigned long _dum_hcd)
+ 		int			type;
+ 		int			status = -EINPROGRESS;
+ 
++		/* stop when we reach URBs queued after the timer interrupt */
++		if (urbp == dum_hcd->next_frame_urbp)
++			break;
++
+ 		urb = urbp->urb;
+ 		if (urb->unlinked)
+ 			goto return_urb;

commit fe659bcc9b173bcfdd958ce2aec75e47651e74e1
+Author: Alan Stern 
+Date:   Tue Sep 26 15:15:22 2017 -0400
+
+    USB: dummy-hcd: fix connection failures (wrong speed)
+    
+    The dummy-hcd UDC driver is not careful about the way it handles
+    connection speeds.  It ignores the module parameter that is supposed
+    to govern the maximum connection speed and it doesn't set the HCD
+    flags properly for the case where it ends up running at full speed.
+    
+    The result is that in many cases, gadget enumeration over dummy-hcd
+    fails because the bMaxPacketSize byte in the device descriptor is set
+    incorrectly.  For example, the default settings call for a high-speed
+    connection, but the maxpacket value for ep0 ends up being set for a
+    Super-Speed connection.
+    
+    This patch fixes the problem by initializing the gadget's max_speed
+    and the HCD flags correctly.
+    
+    Signed-off-by: Alan Stern 
+    CC: 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
+index b1e21b3be6e1..d515ec31afe4 100644
+--- a/drivers/usb/gadget/udc/dummy_hcd.c
++++ b/drivers/usb/gadget/udc/dummy_hcd.c
+@@ -1036,7 +1036,12 @@ static int dummy_udc_probe(struct platform_device *pdev)
+ 	memzero_explicit(&dum->gadget, sizeof(struct usb_gadget));
+ 	dum->gadget.name = gadget_name;
+ 	dum->gadget.ops = &dummy_ops;
+-	dum->gadget.max_speed = USB_SPEED_SUPER;
++	if (mod_data.is_super_speed)
++		dum->gadget.max_speed = USB_SPEED_SUPER;
++	else if (mod_data.is_high_speed)
++		dum->gadget.max_speed = USB_SPEED_HIGH;
++	else
++		dum->gadget.max_speed = USB_SPEED_FULL;
+ 
+ 	dum->gadget.dev.parent = &pdev->dev;
+ 	init_dummy_udc_hw(dum);
+@@ -2560,8 +2565,6 @@ static struct hc_driver dummy_hcd = {
+ 	.product_desc =		"Dummy host controller",
+ 	.hcd_priv_size =	sizeof(struct dummy_hcd),
+ 
+-	.flags =		HCD_USB3 | HCD_SHARED,
+-
+ 	.reset =		dummy_setup,
+ 	.start =		dummy_start,
+ 	.stop =			dummy_stop,
+@@ -2590,8 +2593,12 @@ static int dummy_hcd_probe(struct platform_device *pdev)
+ 	dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
+ 	dum = *((void **)dev_get_platdata(&pdev->dev));
+ 
+-	if (!mod_data.is_super_speed)
++	if (mod_data.is_super_speed)
++		dummy_hcd.flags = HCD_USB3 | HCD_SHARED;
++	else if (mod_data.is_high_speed)
+ 		dummy_hcd.flags = HCD_USB2;
++	else
++		dummy_hcd.flags = HCD_USB11;
+ 	hs_hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, dev_name(&pdev->dev));
+ 	if (!hs_hcd)
+ 		return -ENOMEM;

commit 1fbbb78f25d1291274f320462bf6908906f538db
+Author: Alan Stern 
+Date:   Thu Sep 21 13:22:00 2017 -0400
+
+    USB: g_mass_storage: Fix deadlock when driver is unbound
+    
+    As a holdover from the old g_file_storage gadget, the g_mass_storage
+    legacy gadget driver attempts to unregister itself when its main
+    operating thread terminates (if it hasn't been unregistered already).
+    This is not strictly necessary; it was never more than an attempt to
+    have the gadget fail cleanly if something went wrong and the main
+    thread was killed.
+    
+    However, now that the UDC core manages gadget drivers independently of
+    UDC drivers, this scheme doesn't work any more.  A simple test:
+    
+            modprobe dummy-hcd
+            modprobe g-mass-storage file=...
+            rmmod dummy-hcd
+    
+    ends up in a deadlock with the following backtrace:
+    
+     sysrq: SysRq : Show Blocked State
+       task                PC stack   pid father
+     file-storage    D    0  1130      2 0x00000000
+     Call Trace:
+      __schedule+0x53e/0x58c
+      schedule+0x6e/0x77
+      schedule_preempt_disabled+0xd/0xf
+      __mutex_lock.isra.1+0x129/0x224
+      ? _raw_spin_unlock_irqrestore+0x12/0x14
+      __mutex_lock_slowpath+0x12/0x14
+      mutex_lock+0x28/0x2b
+      usb_gadget_unregister_driver+0x29/0x9b [udc_core]
+      usb_composite_unregister+0x10/0x12 [libcomposite]
+      msg_cleanup+0x1d/0x20 [g_mass_storage]
+      msg_thread_exits+0xd/0xdd7 [g_mass_storage]
+      fsg_main_thread+0x1395/0x13d6 [usb_f_mass_storage]
+      ? __schedule+0x573/0x58c
+      kthread+0xd9/0xdb
+      ? do_set_interface+0x25c/0x25c [usb_f_mass_storage]
+      ? init_completion+0x1e/0x1e
+      ret_from_fork+0x19/0x24
+     rmmod           D    0  1155    683 0x00000000
+     Call Trace:
+      __schedule+0x53e/0x58c
+      schedule+0x6e/0x77
+      schedule_timeout+0x26/0xbc
+      ? __schedule+0x573/0x58c
+      do_wait_for_common+0xb3/0x128
+      ? usleep_range+0x81/0x81
+      ? wake_up_q+0x3f/0x3f
+      wait_for_common+0x2e/0x45
+      wait_for_completion+0x17/0x19
+      fsg_common_put+0x34/0x81 [usb_f_mass_storage]
+      fsg_free_inst+0x13/0x1e [usb_f_mass_storage]
+      usb_put_function_instance+0x1a/0x25 [libcomposite]
+      msg_unbind+0x2a/0x42 [g_mass_storage]
+      __composite_unbind+0x4a/0x6f [libcomposite]
+      composite_unbind+0x12/0x14 [libcomposite]
+      usb_gadget_remove_driver+0x4f/0x77 [udc_core]
+      usb_del_gadget_udc+0x52/0xcc [udc_core]
+      dummy_udc_remove+0x27/0x2c [dummy_hcd]
+      platform_drv_remove+0x1d/0x31
+      device_release_driver_internal+0xe9/0x16d
+      device_release_driver+0x11/0x13
+      bus_remove_device+0xd2/0xe2
+      device_del+0x19f/0x221
+      ? selinux_capable+0x22/0x27
+      platform_device_del+0x21/0x63
+      platform_device_unregister+0x10/0x1a
+      cleanup+0x20/0x817 [dummy_hcd]
+      SyS_delete_module+0x10c/0x197
+      ? ____fput+0xd/0xf
+      ? task_work_run+0x55/0x62
+      ? prepare_exit_to_usermode+0x65/0x75
+      do_fast_syscall_32+0x86/0xc3
+      entry_SYSENTER_32+0x4e/0x7c
+    
+    What happens is that removing the dummy-hcd driver causes the UDC core
+    to unbind the gadget driver, which it does while holding the udc_lock
+    mutex.  The unbind routine in g_mass_storage tells the main thread to
+    exit and waits for it to terminate.
+    
+    But as mentioned above, when the main thread exits it tries to
+    unregister the mass-storage function driver.  Via the composite
+    framework this ends up calling usb_gadget_unregister_driver(), which
+    tries to acquire the udc_lock mutex.  The result is deadlock.
+    
+    The simplest way to fix the problem is not to be so clever: The main
+    thread doesn't have to unregister the function driver.  The side
+    effects won't be so terrible; if the gadget is still attached to a USB
+    host when the main thread is killed, it will appear to the host as
+    though the gadget's firmware has crashed -- a reasonably accurate
+    interpretation, and an all-too-common occurrence for USB mass-storage
+    devices.
+    
+    In fact, the code to unregister the driver when the main thread exits
+    is specific to g-mass-storage; it is not used when f-mass-storage is
+    included as a function in a larger composite device.  Therefore the
+    entire mechanism responsible for this (the fsg_operations structure
+    with its ->thread_exits method, the fsg_common_set_ops() routine, and
+    the msg_thread_exits() callback routine) can all be eliminated.  Even
+    the msg_registered bitflag can be removed, because now the driver is
+    unregistered in only one place rather than in two places.
+    
+    Signed-off-by: Alan Stern 
+    CC: 
+    Acked-by: Felipe Balbi 
+    Acked-by: Michal Nazarewicz 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c
+index d6bd0244b008..5153e29870c3 100644
+--- a/drivers/usb/gadget/function/f_mass_storage.c
++++ b/drivers/usb/gadget/function/f_mass_storage.c
+@@ -307,8 +307,6 @@ struct fsg_common {
+ 	struct completion	thread_notifier;
+ 	struct task_struct	*thread_task;
+ 
+-	/* Callback functions. */
+-	const struct fsg_operations	*ops;
+ 	/* Gadget's private data. */
+ 	void			*private_data;
+ 
+@@ -2438,6 +2436,7 @@ static void handle_exception(struct fsg_common *common)
+ static int fsg_main_thread(void *common_)
+ {
+ 	struct fsg_common	*common = common_;
++	int			i;
+ 
+ 	/*
+ 	 * Allow the thread to be killed by a signal, but set the signal mask
+@@ -2476,21 +2475,16 @@ static int fsg_main_thread(void *common_)
+ 	common->thread_task = NULL;
+ 	spin_unlock_irq(&common->lock);
+ 
+-	if (!common->ops || !common->ops->thread_exits
+-	 || common->ops->thread_exits(common) < 0) {
+-		int i;
++	/* Eject media from all LUNs */
+ 
+-		down_write(&common->filesem);
+-		for (i = 0; i < ARRAY_SIZE(common->luns); i++) {
+-			struct fsg_lun *curlun = common->luns[i];
+-			if (!curlun || !fsg_lun_is_open(curlun))
+-				continue;
++	down_write(&common->filesem);
++	for (i = 0; i < ARRAY_SIZE(common->luns); i++) {
++		struct fsg_lun *curlun = common->luns[i];
+ 
++		if (curlun && fsg_lun_is_open(curlun))
+ 			fsg_lun_close(curlun);
+-			curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT;
+-		}
+-		up_write(&common->filesem);
+ 	}
++	up_write(&common->filesem);
+ 
+ 	/* Let fsg_unbind() know the thread has exited */
+ 	complete_and_exit(&common->thread_notifier, 0);
+@@ -2681,13 +2675,6 @@ void fsg_common_remove_luns(struct fsg_common *common)
+ }
+ EXPORT_SYMBOL_GPL(fsg_common_remove_luns);
+ 
+-void fsg_common_set_ops(struct fsg_common *common,
+-			const struct fsg_operations *ops)
+-{
+-	common->ops = ops;
+-}
+-EXPORT_SYMBOL_GPL(fsg_common_set_ops);
+-
+ void fsg_common_free_buffers(struct fsg_common *common)
+ {
+ 	_fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers);
+diff --git a/drivers/usb/gadget/function/f_mass_storage.h b/drivers/usb/gadget/function/f_mass_storage.h
+index d3902313b8ac..dc05ca0c4359 100644
+--- a/drivers/usb/gadget/function/f_mass_storage.h
++++ b/drivers/usb/gadget/function/f_mass_storage.h
+@@ -60,17 +60,6 @@ struct fsg_module_parameters {
+ struct fsg_common;
+ 
+ /* FSF callback functions */
+-struct fsg_operations {
+-	/*
+-	 * Callback function to call when thread exits.  If no
+-	 * callback is set or it returns value lower then zero MSF
+-	 * will force eject all LUNs it operates on (including those
+-	 * marked as non-removable or with prevent_medium_removal flag
+-	 * set).
+-	 */
+-	int (*thread_exits)(struct fsg_common *common);
+-};
+-
+ struct fsg_lun_opts {
+ 	struct config_group group;
+ 	struct fsg_lun *lun;
+@@ -142,9 +131,6 @@ void fsg_common_remove_lun(struct fsg_lun *lun);
+ 
+ void fsg_common_remove_luns(struct fsg_common *common);
+ 
+-void fsg_common_set_ops(struct fsg_common *common,
+-			const struct fsg_operations *ops);
+-
+ int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg,
+ 			  unsigned int id, const char *name,
+ 			  const char **name_pfx);
+diff --git a/drivers/usb/gadget/legacy/mass_storage.c b/drivers/usb/gadget/legacy/mass_storage.c
+index e99ab57ee3e5..fcba59782f26 100644
+--- a/drivers/usb/gadget/legacy/mass_storage.c
++++ b/drivers/usb/gadget/legacy/mass_storage.c
+@@ -107,15 +107,6 @@ static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS;
+ 
+ FSG_MODULE_PARAMETERS(/* no prefix */, mod_data);
+ 
+-static unsigned long msg_registered;
+-static void msg_cleanup(void);
+-
+-static int msg_thread_exits(struct fsg_common *common)
+-{
+-	msg_cleanup();
+-	return 0;
+-}
+-
+ static int msg_do_config(struct usb_configuration *c)
+ {
+ 	struct fsg_opts *opts;
+@@ -154,9 +145,6 @@ static struct usb_configuration msg_config_driver = {
+ 
+ static int msg_bind(struct usb_composite_dev *cdev)
+ {
+-	static const struct fsg_operations ops = {
+-		.thread_exits = msg_thread_exits,
+-	};
+ 	struct fsg_opts *opts;
+ 	struct fsg_config config;
+ 	int status;
+@@ -173,8 +161,6 @@ static int msg_bind(struct usb_composite_dev *cdev)
+ 	if (status)
+ 		goto fail;
+ 
+-	fsg_common_set_ops(opts->common, &ops);
+-
+ 	status = fsg_common_set_cdev(opts->common, cdev, config.can_stall);
+ 	if (status)
+ 		goto fail_set_cdev;
+@@ -256,18 +242,12 @@ MODULE_LICENSE("GPL");
+ 
+ static int __init msg_init(void)
+ {
+-	int ret;
+-
+-	ret = usb_composite_probe(&msg_driver);
+-	set_bit(0, &msg_registered);
+-
+-	return ret;
++	return usb_composite_probe(&msg_driver);
+ }
+ module_init(msg_init);
+ 
+-static void msg_cleanup(void)
++static void __exit msg_cleanup(void)
+ {
+-	if (test_and_clear_bit(0, &msg_registered))
+-		usb_composite_unregister(&msg_driver);
++	usb_composite_unregister(&msg_driver);
+ }
+ module_exit(msg_cleanup);

commit 520b72fc64debf8a86c3853b8e486aa5982188f0
+Author: Alan Stern 
+Date:   Thu Sep 21 13:23:58 2017 -0400
+
+    USB: gadgetfs: Fix crash caused by inadequate synchronization
+    
+    The gadgetfs driver (drivers/usb/gadget/legacy/inode.c) was written
+    before the UDC and composite frameworks were adopted; it is a legacy
+    driver.  As such, it expects that once bound to a UDC controller, it
+    will not be unbound until it unregisters itself.
+    
+    However, the UDC framework does unbind function drivers while they are
+    still registered.  When this happens, it can cause the gadgetfs driver
+    to misbehave or crash.  For example, userspace can cause a crash by
+    opening the device file and doing an ioctl call before setting up a
+    configuration (found by Andrey Konovalov using the syzkaller fuzzer).
+    
+    This patch adds checks and synchronization to prevent these bad
+    behaviors.  It adds a udc_usage counter that the driver increments at
+    times when it is using a gadget interface without holding the private
+    spinlock.  The unbind routine waits for this counter to go to 0 before
+    returning, thereby ensuring that the UDC is no longer in use.
+    
+    The patch also adds a check in the dev_ioctl() routine to make sure
+    the driver is bound to a UDC before dereferencing the gadget pointer,
+    and it makes destroy_ep_files() synchronize with the endpoint I/O
+    routines, to prevent the user from accessing an endpoint data
+    structure after it has been removed.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Andrey Konovalov 
+    Tested-by: Andrey Konovalov 
+    CC: 
+    Acked-by: Felipe Balbi 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
+index 956b3dc7c3a4..5c28bee327e1 100644
+--- a/drivers/usb/gadget/legacy/inode.c
++++ b/drivers/usb/gadget/legacy/inode.c
+@@ -28,7 +28,7 @@
+ #include 
+ #include 
+ #include 
+-
++#include 
+ #include 
+ #include 
+ 
+@@ -116,6 +116,7 @@ enum ep0_state {
+ struct dev_data {
+ 	spinlock_t			lock;
+ 	refcount_t			count;
++	int				udc_usage;
+ 	enum ep0_state			state;		/* P: lock */
+ 	struct usb_gadgetfs_event	event [N_EVENT];
+ 	unsigned			ev_next;
+@@ -513,9 +514,9 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
+ 		INIT_WORK(&priv->work, ep_user_copy_worker);
+ 		schedule_work(&priv->work);
+ 	}
+-	spin_unlock(&epdata->dev->lock);
+ 
+ 	usb_ep_free_request(ep, req);
++	spin_unlock(&epdata->dev->lock);
+ 	put_ep(epdata);
+ }
+ 
+@@ -939,9 +940,11 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
+ 			struct usb_request	*req = dev->req;
+ 
+ 			if ((retval = setup_req (ep, req, 0)) == 0) {
++				++dev->udc_usage;
+ 				spin_unlock_irq (&dev->lock);
+ 				retval = usb_ep_queue (ep, req, GFP_KERNEL);
+ 				spin_lock_irq (&dev->lock);
++				--dev->udc_usage;
+ 			}
+ 			dev->state = STATE_DEV_CONNECTED;
+ 
+@@ -1134,6 +1137,7 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
+ 			retval = setup_req (dev->gadget->ep0, dev->req, len);
+ 			if (retval == 0) {
+ 				dev->state = STATE_DEV_CONNECTED;
++				++dev->udc_usage;
+ 				spin_unlock_irq (&dev->lock);
+ 				if (copy_from_user (dev->req->buf, buf, len))
+ 					retval = -EFAULT;
+@@ -1145,6 +1149,7 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
+ 						GFP_KERNEL);
+ 				}
+ 				spin_lock_irq(&dev->lock);
++				--dev->udc_usage;
+ 				if (retval < 0) {
+ 					clean_req (dev->gadget->ep0, dev->req);
+ 				} else
+@@ -1246,9 +1251,21 @@ static long dev_ioctl (struct file *fd, unsigned code, unsigned long value)
+ 	struct usb_gadget	*gadget = dev->gadget;
+ 	long ret = -ENOTTY;
+ 
+-	if (gadget->ops->ioctl)
++	spin_lock_irq(&dev->lock);
++	if (dev->state == STATE_DEV_OPENED ||
++			dev->state == STATE_DEV_UNBOUND) {
++		/* Not bound to a UDC */
++	} else if (gadget->ops->ioctl) {
++		++dev->udc_usage;
++		spin_unlock_irq(&dev->lock);
++
+ 		ret = gadget->ops->ioctl (gadget, code, value);
+ 
++		spin_lock_irq(&dev->lock);
++		--dev->udc_usage;
++	}
++	spin_unlock_irq(&dev->lock);
++
+ 	return ret;
+ }
+ 
+@@ -1466,10 +1483,12 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
+ 				if (value < 0)
+ 					break;
+ 
++				++dev->udc_usage;
+ 				spin_unlock (&dev->lock);
+ 				value = usb_ep_queue (gadget->ep0, dev->req,
+ 							GFP_KERNEL);
+ 				spin_lock (&dev->lock);
++				--dev->udc_usage;
+ 				if (value < 0) {
+ 					clean_req (gadget->ep0, dev->req);
+ 					break;
+@@ -1493,8 +1512,12 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
+ 		req->length = value;
+ 		req->zero = value < w_length;
+ 
++		++dev->udc_usage;
+ 		spin_unlock (&dev->lock);
+ 		value = usb_ep_queue (gadget->ep0, req, GFP_KERNEL);
++		spin_lock(&dev->lock);
++		--dev->udc_usage;
++		spin_unlock(&dev->lock);
+ 		if (value < 0) {
+ 			DBG (dev, "ep_queue --> %d\n", value);
+ 			req->status = 0;
+@@ -1521,21 +1544,24 @@ static void destroy_ep_files (struct dev_data *dev)
+ 		/* break link to FS */
+ 		ep = list_first_entry (&dev->epfiles, struct ep_data, epfiles);
+ 		list_del_init (&ep->epfiles);
++		spin_unlock_irq (&dev->lock);
++
+ 		dentry = ep->dentry;
+ 		ep->dentry = NULL;
+ 		parent = d_inode(dentry->d_parent);
+ 
+ 		/* break link to controller */
++		mutex_lock(&ep->lock);
+ 		if (ep->state == STATE_EP_ENABLED)
+ 			(void) usb_ep_disable (ep->ep);
+ 		ep->state = STATE_EP_UNBOUND;
+ 		usb_ep_free_request (ep->ep, ep->req);
+ 		ep->ep = NULL;
++		mutex_unlock(&ep->lock);
++
+ 		wake_up (&ep->wait);
+ 		put_ep (ep);
+ 
+-		spin_unlock_irq (&dev->lock);
+-
+ 		/* break link to dcache */
+ 		inode_lock(parent);
+ 		d_delete (dentry);
+@@ -1606,6 +1632,11 @@ gadgetfs_unbind (struct usb_gadget *gadget)
+ 
+ 	spin_lock_irq (&dev->lock);
+ 	dev->state = STATE_DEV_UNBOUND;
++	while (dev->udc_usage > 0) {
++		spin_unlock_irq(&dev->lock);
++		usleep_range(1000, 2000);
++		spin_lock_irq(&dev->lock);
++	}
+ 	spin_unlock_irq (&dev->lock);
+ 
+ 	destroy_ep_files (dev);

commit 6e76c01e71551cb221c1f3deacb9dcd9a7346784
+Author: Alan Stern 
+Date:   Thu Sep 21 16:12:01 2017 -0400
+
+    USB: gadgetfs: fix copy_to_user while holding spinlock
+    
+    The gadgetfs driver as a long-outstanding FIXME, regarding a call of
+    copy_to_user() made while holding a spinlock.  This patch fixes the
+    issue by dropping the spinlock and using the dev->udc_usage mechanism
+    introduced by another recent patch to guard against status changes
+    while the lock isn't held.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Andrey Konovalov 
+    CC: 
+    Acked-by: Felipe Balbi 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
+index 684900fcfe24..956b3dc7c3a4 100644
+--- a/drivers/usb/gadget/legacy/inode.c
++++ b/drivers/usb/gadget/legacy/inode.c
+@@ -983,11 +983,14 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
+ 				retval = -EIO;
+ 			else {
+ 				len = min (len, (size_t)dev->req->actual);
+-// FIXME don't call this with the spinlock held ...
++				++dev->udc_usage;
++				spin_unlock_irq(&dev->lock);
+ 				if (copy_to_user (buf, dev->req->buf, len))
+ 					retval = -EFAULT;
+ 				else
+ 					retval = len;
++				spin_lock_irq(&dev->lock);
++				--dev->udc_usage;
+ 				clean_req (dev->gadget->ep0, dev->req);
+ 				/* NOTE userspace can't yet choose to stall */
+ 			}

commit 786de92b3cb26012d3d0f00ee37adf14527f35c4
+Author: Alan Stern 
+Date:   Fri Sep 22 11:56:49 2017 -0400
+
+    USB: uas: fix bug in handling of alternate settings
+    
+    The uas driver has a subtle bug in the way it handles alternate
+    settings.  The uas_find_uas_alt_setting() routine returns an
+    altsetting value (the bAlternateSetting number in the descriptor), but
+    uas_use_uas_driver() then treats that value as an index to the
+    intf->altsetting array, which it isn't.
+    
+    Normally this doesn't cause any problems because the various
+    alternate settings have bAlternateSetting values 0, 1, 2, ..., so the
+    value is equal to the index in the array.  But this is not guaranteed,
+    and Andrey Konovalov used the syzkaller fuzzer with KASAN to get a
+    slab-out-of-bounds error by violating this assumption.
+    
+    This patch fixes the bug by making uas_find_uas_alt_setting() return a
+    pointer to the altsetting entry rather than either the value or the
+    index.  Pointers are less subject to misinterpretation.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Andrey Konovalov 
+    Tested-by: Andrey Konovalov 
+    CC: Oliver Neukum 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/uas-detect.h b/drivers/usb/storage/uas-detect.h
+index f58caa9e6a27..a155cd02bce2 100644
+--- a/drivers/usb/storage/uas-detect.h
++++ b/drivers/usb/storage/uas-detect.h
+@@ -9,7 +9,8 @@ static int uas_is_interface(struct usb_host_interface *intf)
+ 		intf->desc.bInterfaceProtocol == USB_PR_UAS);
+ }
+ 
+-static int uas_find_uas_alt_setting(struct usb_interface *intf)
++static struct usb_host_interface *uas_find_uas_alt_setting(
++		struct usb_interface *intf)
+ {
+ 	int i;
+ 
+@@ -17,10 +18,10 @@ static int uas_find_uas_alt_setting(struct usb_interface *intf)
+ 		struct usb_host_interface *alt = &intf->altsetting[i];
+ 
+ 		if (uas_is_interface(alt))
+-			return alt->desc.bAlternateSetting;
++			return alt;
+ 	}
+ 
+-	return -ENODEV;
++	return NULL;
+ }
+ 
+ static int uas_find_endpoints(struct usb_host_interface *alt,
+@@ -58,14 +59,14 @@ static int uas_use_uas_driver(struct usb_interface *intf,
+ 	struct usb_device *udev = interface_to_usbdev(intf);
+ 	struct usb_hcd *hcd = bus_to_hcd(udev->bus);
+ 	unsigned long flags = id->driver_info;
+-	int r, alt;
+-
++	struct usb_host_interface *alt;
++	int r;
+ 
+ 	alt = uas_find_uas_alt_setting(intf);
+-	if (alt < 0)
++	if (!alt)
+ 		return 0;
+ 
+-	r = uas_find_endpoints(&intf->altsetting[alt], eps);
++	r = uas_find_endpoints(alt, eps);
+ 	if (r < 0)
+ 		return 0;
+ 
+diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
+index cfb1e3bbd434..63cf981ed81c 100644
+--- a/drivers/usb/storage/uas.c
++++ b/drivers/usb/storage/uas.c
+@@ -873,14 +873,14 @@ MODULE_DEVICE_TABLE(usb, uas_usb_ids);
+ static int uas_switch_interface(struct usb_device *udev,
+ 				struct usb_interface *intf)
+ {
+-	int alt;
++	struct usb_host_interface *alt;
+ 
+ 	alt = uas_find_uas_alt_setting(intf);
+-	if (alt < 0)
+-		return alt;
++	if (!alt)
++		return -ENODEV;
+ 
+-	return usb_set_interface(udev,
+-			intf->altsetting[0].desc.bInterfaceNumber, alt);
++	return usb_set_interface(udev, alt->desc.bInterfaceNumber,
++			alt->desc.bAlternateSetting);
+ }
+ 
+ static int uas_configure_endpoints(struct uas_dev_info *devinfo)

commit 113f6eb6d50cfa5e2a1cdcf1678b12661fa272ab
+Author: Alan Stern 
+Date:   Thu Sep 21 15:59:30 2017 -0400
+
+    usb-storage: unusual_devs entry to fix write-access regression for Seagate external drives
+    
+    Kris Lindgren reports that without the NO_WP_DETECT flag, his Seagate
+    external disk drive fails all write accesses.  This regresssion dates
+    back approximately to the start of the 4.x kernel releases.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Kris Lindgren 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 5a70c33ef0e0..eb06d88b41d6 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -1459,6 +1459,13 @@ UNUSUAL_DEV( 0x0bc2, 0x3010, 0x0000, 0x0000,
+ 		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ 		US_FL_SANE_SENSE ),
+ 
++/* Reported by Kris Lindgren  */
++UNUSUAL_DEV( 0x0bc2, 0x3332, 0x0000, 0x9999,
++		"Seagate",
++		"External",
++		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
++		US_FL_NO_WP_DETECT ),
++
+ UNUSUAL_DEV(  0x0d49, 0x7310, 0x0000, 0x9999,
+ 		"Maxtor",
+ 		"USB to SATA",

commit a4fd4a724d6c30ad671046d83be2e9be2f11d275
+Author: Alan Stern 
+Date:   Thu Sep 21 16:02:05 2017 -0400
+
+    usb-storage: fix bogus hardware error messages for ATA pass-thru devices
+    
+    Ever since commit a621bac3044e ("scsi_lib: correctly retry failed zero
+    length REQ_TYPE_FS commands"), people have been getting bogus error
+    messages for USB disk drives using ATA pass-thru.  For example:
+    
+    [ 1344.880193] sd 6:0:0:0: [sdb] Attached SCSI disk
+    [ 1345.069152] sd 6:0:0:0: [sdb] tag#0 FAILED Result: hostbyte=DID_ERROR driverbyte=DRIVER_SENSE
+    [ 1345.069159] sd 6:0:0:0: [sdb] tag#0 Sense Key : Hardware Error [current] [descriptor]
+    [ 1345.069162] sd 6:0:0:0: [sdb] tag#0 Add. Sense: No additional sense information
+    [ 1345.069168] sd 6:0:0:0: [sdb] tag#0 CDB: ATA command pass through(16) 85 06 20 00 00 00 00 00 00 00 00 00 00 00 e5 00
+    [ 1345.172252] sd 6:0:0:0: [sdb] tag#0 FAILED Result: hostbyte=DID_ERROR driverbyte=DRIVER_SENSE
+    [ 1345.172258] sd 6:0:0:0: [sdb] tag#0 Sense Key : Hardware Error [current] [descriptor]
+    [ 1345.172261] sd 6:0:0:0: [sdb] tag#0 Add. Sense: No additional sense information
+    [ 1345.172266] sd 6:0:0:0: [sdb] tag#0 CDB: ATA command pass through(12)/Blank a1 06 20 da 00 00 4f c2 00 b0 00 00
+    
+    These messages can be quite annoying, because programs like udisks2
+    provoke them every 10 minutes or so.  Other programs can also have
+    this effect, such as those in smartmontools.
+    
+    I don't fully understand how that commit induced the SCSI core to log
+    these error messages, but the underlying cause for them is code added
+    to usb-storage by commit f1a0743bc0e7 ("USB: storage: When a device
+    returns no sense data, call it a Hardware Error").  At the time it was
+    necessary to do this, in order to prevent an infinite retry loop with
+    some not-so-great mass storage devices.
+    
+    However, the ATA pass-thru protocol uses SCSI sense data to return
+    command status values, and some devices always report Check Condition
+    status for ATA pass-thru commands to ensure that the host retrieves
+    the sense data, even if the command succeeded.  This violates the USB
+    mass-storage protocol (Check Condition status is supposed to mean the
+    command failed), but we can't help that.
+    
+    This patch attempts to mitigate the problem of these bogus error
+    reports by changing usb-storage.  The HARDWARE ERROR sense key will be
+    inserted only for commands that aren't ATA pass-thru.
+    
+    Thanks to Ewan Milne for pointing out that this mechanism was present
+    in usb-storage.  8 years after writing it, I had completely forgotten
+    its existence.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Kris Lindgren 
+    Ref: https://bugzilla.redhat.com/show_bug.cgi?id=1351305
+    CC: Ewan D. Milne 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+index 1a59f335b063..a3ccb899df60 100644
+--- a/drivers/usb/storage/transport.c
++++ b/drivers/usb/storage/transport.c
+@@ -834,13 +834,25 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 			if (result == USB_STOR_TRANSPORT_GOOD) {
+ 				srb->result = SAM_STAT_GOOD;
+ 				srb->sense_buffer[0] = 0x0;
++			}
++
++			/*
++			 * ATA-passthru commands use sense data to report
++			 * the command completion status, and often devices
++			 * return Check Condition status when nothing is
++			 * wrong.
++			 */
++			else if (srb->cmnd[0] == ATA_16 ||
++					srb->cmnd[0] == ATA_12) {
++				/* leave the data alone */
++			}
+ 
+ 			/*
+ 			 * If there was a problem, report an unspecified
+ 			 * hardware error to prevent the higher layers from
+ 			 * entering an infinite retry loop.
+ 			 */
+-			} else {
++			else {
+ 				srb->result = DID_ERROR << 16;
+ 				if ((sshdr.response_code & 0x72) == 0x72)
+ 					srb->sense_buffer[1] = HARDWARE_ERROR;

commit afd7fd81f22bf90474216515dbd6088f9bd70343
+Author: Alan Stern 
+Date:   Thu Aug 17 14:49:55 2017 -0400
+
+    USB: Gadget core: fix inconsistency in the interface tousb_add_gadget_udc_release()
+    
+    The usb_add_gadget_udc_release() routine in the USB gadget core will
+    sometimes but not always call the gadget's release function when an
+    error occurs.  More specifically, if the struct usb_udc allocation
+    fails then the release function is not called, and for other errors it
+    is.
+    
+    As a result, users of this routine cannot know whether they need to
+    deallocate the memory containing the gadget structure following an
+    error.  This leads to unavoidable memory leaks or double frees.
+    
+    This patch fixes the problem by splitting the existing
+    device_register() call into device_initialize() and device_add(), and
+    doing the udc allocation in between.  That way, even if the allocation
+    fails it is still possible to call device_del(), and so the release
+    function will be always called following an error.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Alexey Khoroshilov 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
+index c1cef6a11ecb..75c51ca4ee0f 100644
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -1133,6 +1133,7 @@ static int check_pending_gadget_drivers(struct usb_udc *udc)
+  * @release: a gadget release function.
+  *
+  * Returns zero on success, negative errno otherwise.
++ * Calls the gadget release function in the latter case.
+  */
+ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
+ 		void (*release)(struct device *dev))
+@@ -1140,10 +1141,6 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
+ 	struct usb_udc		*udc;
+ 	int			ret = -ENOMEM;
+ 
+-	udc = kzalloc(sizeof(*udc), GFP_KERNEL);
+-	if (!udc)
+-		goto err1;
+-
+ 	dev_set_name(&gadget->dev, "gadget");
+ 	INIT_WORK(&gadget->work, usb_gadget_state_work);
+ 	gadget->dev.parent = parent;
+@@ -1153,7 +1150,13 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
+ 	else
+ 		gadget->dev.release = usb_udc_nop_release;
+ 
+-	ret = device_register(&gadget->dev);
++	device_initialize(&gadget->dev);
++
++	udc = kzalloc(sizeof(*udc), GFP_KERNEL);
++	if (!udc)
++		goto err1;
++
++	ret = device_add(&gadget->dev);
+ 	if (ret)
+ 		goto err2;
+ 
+@@ -1200,10 +1203,10 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
+ 	device_del(&gadget->dev);
+ 
+ err2:
+-	put_device(&gadget->dev);
+ 	kfree(udc);
+ 
+ err1:
++	put_device(&gadget->dev);
+ 	return ret;
+ }
+ EXPORT_SYMBOL_GPL(usb_add_gadget_udc_release);

commit 94c43b9897abf4ea366ed4dba027494e080c7050
+Author: Alan Stern 
+Date:   Tue Aug 1 10:41:56 2017 -0400
+
+    USB: Check for dropped connection before switching to full speed
+    
+    Some buggy USB disk adapters disconnect and reconnect multiple times
+    during the enumeration procedure.  This may lead to a device
+    connecting at full speed instead of high speed, because when the USB
+    stack sees that a device isn't able to enumerate at high speed, it
+    tries to hand the connection over to a full-speed companion
+    controller.
+    
+    The logic for doing this is careful to check that the device is still
+    connected.  But this check is inadequate if the device disconnects and
+    reconnects before the check is done.  The symptom is that a device
+    works, but much more slowly than it is capable of operating.
+    
+    The situation was made worse recently by commit 22547c4cc4fe ("usb:
+    hub: Wait for connection to be reestablished after port reset"), which
+    increases the delay following a reset before a disconnect is
+    recognized, thus giving the device more time to reconnect.
+    
+    This patch makes the check more robust.  If the device was
+    disconnected at any time during enumeration, we will now skip the
+    full-speed handover.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Zdenek Kabelac 
+    Reviewed-by: Guenter Roeck 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 6e6797d145dd..822f8c50e423 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -4725,7 +4725,8 @@ hub_power_remaining(struct usb_hub *hub)
+ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
+ 		u16 portchange)
+ {
+-	int status, i;
++	int status = -ENODEV;
++	int i;
+ 	unsigned unit_load;
+ 	struct usb_device *hdev = hub->hdev;
+ 	struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
+@@ -4929,9 +4930,10 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
+ 
+ done:
+ 	hub_port_disable(hub, port1, 1);
+-	if (hcd->driver->relinquish_port && !hub->hdev->parent)
+-		hcd->driver->relinquish_port(hcd, port1);
+-
++	if (hcd->driver->relinquish_port && !hub->hdev->parent) {
++		if (status != -ENOTCONN && status != -ENODEV)
++			hcd->driver->relinquish_port(hcd, port1);
++	}
+ }
+ 
+ /* Handle physical or logical connection change events.

commit 8b52291a0743fc4db4a7495c846a6f31ee84d282
+Author: Alan Stern 
+Date:   Wed Jul 26 11:49:19 2017 -0400
+
+    usb-storage: fix deadlock involving host lock and scsi_done
+    
+    Christoph Hellwig says that since version 4.12, the kernel switched to
+    using blk-mq by default.  The old code used a softirq for handling
+    request completions, but blk-mq can handle completions in the caller's
+    context.  This may cause a problem for usb-storage, because it invokes
+    the ->scsi_done callback while holding the host lock, and the
+    completion routine sometimes tries to acquire the same lock (when
+    running the error handler, for example).
+    
+    The consequence is that the existing code will sometimes deadlock upon
+    error completion of a SCSI command (with a lockdep warning).
+    
+    This is easy enough to fix, since usb-storage doesn't really need to
+    hold the host lock while the callback runs.  It was simpler to write
+    it that way, but moving the call outside the locked region is pretty
+    easy and there's no downside.  That's what this patch does.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Arthur Marsh 
+    CC: Christoph Hellwig 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 06615934fed1..0dceb9fa3a06 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -315,6 +315,7 @@ static int usb_stor_control_thread(void * __us)
+ {
+ 	struct us_data *us = (struct us_data *)__us;
+ 	struct Scsi_Host *host = us_to_host(us);
++	struct scsi_cmnd *srb;
+ 
+ 	for (;;) {
+ 		usb_stor_dbg(us, "*** thread sleeping\n");
+@@ -330,6 +331,7 @@ static int usb_stor_control_thread(void * __us)
+ 		scsi_lock(host);
+ 
+ 		/* When we are called with no command pending, we're done */
++		srb = us->srb;
+ 		if (us->srb == NULL) {
+ 			scsi_unlock(host);
+ 			mutex_unlock(&us->dev_mutex);
+@@ -398,14 +400,11 @@ static int usb_stor_control_thread(void * __us)
+ 		/* lock access to the state */
+ 		scsi_lock(host);
+ 
+-		/* indicate that the command is done */
+-		if (us->srb->result != DID_ABORT << 16) {
+-			usb_stor_dbg(us, "scsi cmd done, result=0x%x\n",
+-				     us->srb->result);
+-			us->srb->scsi_done(us->srb);
+-		} else {
++		/* was the command aborted? */
++		if (us->srb->result == DID_ABORT << 16) {
+ SkipForAbort:
+ 			usb_stor_dbg(us, "scsi command aborted\n");
++			srb = NULL;	/* Don't call srb->scsi_done() */
+ 		}
+ 
+ 		/*
+@@ -429,6 +428,13 @@ static int usb_stor_control_thread(void * __us)
+ 
+ 		/* unlock the device pointers */
+ 		mutex_unlock(&us->dev_mutex);
++
++		/* now that the locks are released, notify the SCSI core */
++		if (srb) {
++			usb_stor_dbg(us, "scsi cmd done, result=0x%x\n",
++					srb->result);
++			srb->scsi_done(srb);
++		}
+ 	} /* for (;;) */
+ 
+ 	/* Wait until we are told to stop */

commit f16443a034c7aa359ddf6f0f9bc40d01ca31faea
+Author: Alan Stern 
+Date:   Tue Jun 13 15:23:42 2017 -0400
+
+    USB: gadgetfs, dummy-hcd, net2280: fix locking for callbacks
+    
+    Using the syzkaller kernel fuzzer, Andrey Konovalov generated the
+    following error in gadgetfs:
+    
+    > BUG: KASAN: use-after-free in __lock_acquire+0x3069/0x3690
+    > kernel/locking/lockdep.c:3246
+    > Read of size 8 at addr ffff88003a2bdaf8 by task kworker/3:1/903
+    >
+    > CPU: 3 PID: 903 Comm: kworker/3:1 Not tainted 4.12.0-rc4+ #35
+    > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
+    > Workqueue: usb_hub_wq hub_event
+    > Call Trace:
+    >  __dump_stack lib/dump_stack.c:16 [inline]
+    >  dump_stack+0x292/0x395 lib/dump_stack.c:52
+    >  print_address_description+0x78/0x280 mm/kasan/report.c:252
+    >  kasan_report_error mm/kasan/report.c:351 [inline]
+    >  kasan_report+0x230/0x340 mm/kasan/report.c:408
+    >  __asan_report_load8_noabort+0x19/0x20 mm/kasan/report.c:429
+    >  __lock_acquire+0x3069/0x3690 kernel/locking/lockdep.c:3246
+    >  lock_acquire+0x22d/0x560 kernel/locking/lockdep.c:3855
+    >  __raw_spin_lock include/linux/spinlock_api_smp.h:142 [inline]
+    >  _raw_spin_lock+0x2f/0x40 kernel/locking/spinlock.c:151
+    >  spin_lock include/linux/spinlock.h:299 [inline]
+    >  gadgetfs_suspend+0x89/0x130 drivers/usb/gadget/legacy/inode.c:1682
+    >  set_link_state+0x88e/0xae0 drivers/usb/gadget/udc/dummy_hcd.c:455
+    >  dummy_hub_control+0xd7e/0x1fb0 drivers/usb/gadget/udc/dummy_hcd.c:2074
+    >  rh_call_control drivers/usb/core/hcd.c:689 [inline]
+    >  rh_urb_enqueue drivers/usb/core/hcd.c:846 [inline]
+    >  usb_hcd_submit_urb+0x92f/0x20b0 drivers/usb/core/hcd.c:1650
+    >  usb_submit_urb+0x8b2/0x12c0 drivers/usb/core/urb.c:542
+    >  usb_start_wait_urb+0x148/0x5b0 drivers/usb/core/message.c:56
+    >  usb_internal_control_msg drivers/usb/core/message.c:100 [inline]
+    >  usb_control_msg+0x341/0x4d0 drivers/usb/core/message.c:151
+    >  usb_clear_port_feature+0x74/0xa0 drivers/usb/core/hub.c:412
+    >  hub_port_disable+0x123/0x510 drivers/usb/core/hub.c:4177
+    >  hub_port_init+0x1ed/0x2940 drivers/usb/core/hub.c:4648
+    >  hub_port_connect drivers/usb/core/hub.c:4826 [inline]
+    >  hub_port_connect_change drivers/usb/core/hub.c:4999 [inline]
+    >  port_event drivers/usb/core/hub.c:5105 [inline]
+    >  hub_event+0x1ae1/0x3d40 drivers/usb/core/hub.c:5185
+    >  process_one_work+0xc08/0x1bd0 kernel/workqueue.c:2097
+    >  process_scheduled_works kernel/workqueue.c:2157 [inline]
+    >  worker_thread+0xb2b/0x1860 kernel/workqueue.c:2233
+    >  kthread+0x363/0x440 kernel/kthread.c:231
+    >  ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:424
+    >
+    > Allocated by task 9958:
+    >  save_stack_trace+0x1b/0x20 arch/x86/kernel/stacktrace.c:59
+    >  save_stack+0x43/0xd0 mm/kasan/kasan.c:513
+    >  set_track mm/kasan/kasan.c:525 [inline]
+    >  kasan_kmalloc+0xad/0xe0 mm/kasan/kasan.c:617
+    >  kmem_cache_alloc_trace+0x87/0x280 mm/slub.c:2745
+    >  kmalloc include/linux/slab.h:492 [inline]
+    >  kzalloc include/linux/slab.h:665 [inline]
+    >  dev_new drivers/usb/gadget/legacy/inode.c:170 [inline]
+    >  gadgetfs_fill_super+0x24f/0x540 drivers/usb/gadget/legacy/inode.c:1993
+    >  mount_single+0xf6/0x160 fs/super.c:1192
+    >  gadgetfs_mount+0x31/0x40 drivers/usb/gadget/legacy/inode.c:2019
+    >  mount_fs+0x9c/0x2d0 fs/super.c:1223
+    >  vfs_kern_mount.part.25+0xcb/0x490 fs/namespace.c:976
+    >  vfs_kern_mount fs/namespace.c:2509 [inline]
+    >  do_new_mount fs/namespace.c:2512 [inline]
+    >  do_mount+0x41b/0x2d90 fs/namespace.c:2834
+    >  SYSC_mount fs/namespace.c:3050 [inline]
+    >  SyS_mount+0xb0/0x120 fs/namespace.c:3027
+    >  entry_SYSCALL_64_fastpath+0x1f/0xbe
+    >
+    > Freed by task 9960:
+    >  save_stack_trace+0x1b/0x20 arch/x86/kernel/stacktrace.c:59
+    >  save_stack+0x43/0xd0 mm/kasan/kasan.c:513
+    >  set_track mm/kasan/kasan.c:525 [inline]
+    >  kasan_slab_free+0x72/0xc0 mm/kasan/kasan.c:590
+    >  slab_free_hook mm/slub.c:1357 [inline]
+    >  slab_free_freelist_hook mm/slub.c:1379 [inline]
+    >  slab_free mm/slub.c:2961 [inline]
+    >  kfree+0xed/0x2b0 mm/slub.c:3882
+    >  put_dev+0x124/0x160 drivers/usb/gadget/legacy/inode.c:163
+    >  gadgetfs_kill_sb+0x33/0x60 drivers/usb/gadget/legacy/inode.c:2027
+    >  deactivate_locked_super+0x8d/0xd0 fs/super.c:309
+    >  deactivate_super+0x21e/0x310 fs/super.c:340
+    >  cleanup_mnt+0xb7/0x150 fs/namespace.c:1112
+    >  __cleanup_mnt+0x1b/0x20 fs/namespace.c:1119
+    >  task_work_run+0x1a0/0x280 kernel/task_work.c:116
+    >  exit_task_work include/linux/task_work.h:21 [inline]
+    >  do_exit+0x18a8/0x2820 kernel/exit.c:878
+    >  do_group_exit+0x14e/0x420 kernel/exit.c:982
+    >  get_signal+0x784/0x1780 kernel/signal.c:2318
+    >  do_signal+0xd7/0x2130 arch/x86/kernel/signal.c:808
+    >  exit_to_usermode_loop+0x1ac/0x240 arch/x86/entry/common.c:157
+    >  prepare_exit_to_usermode arch/x86/entry/common.c:194 [inline]
+    >  syscall_return_slowpath+0x3ba/0x410 arch/x86/entry/common.c:263
+    >  entry_SYSCALL_64_fastpath+0xbc/0xbe
+    >
+    > The buggy address belongs to the object at ffff88003a2bdae0
+    >  which belongs to the cache kmalloc-1024 of size 1024
+    > The buggy address is located 24 bytes inside of
+    >  1024-byte region [ffff88003a2bdae0, ffff88003a2bdee0)
+    > The buggy address belongs to the page:
+    > page:ffffea0000e8ae00 count:1 mapcount:0 mapping:          (null)
+    > index:0x0 compound_mapcount: 0
+    > flags: 0x100000000008100(slab|head)
+    > raw: 0100000000008100 0000000000000000 0000000000000000 0000000100170017
+    > raw: ffffea0000ed3020 ffffea0000f5f820 ffff88003e80efc0 0000000000000000
+    > page dumped because: kasan: bad access detected
+    >
+    > Memory state around the buggy address:
+    >  ffff88003a2bd980: fb fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
+    >  ffff88003a2bda00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
+    > >ffff88003a2bda80: fc fc fc fc fc fc fc fc fc fc fc fc fb fb fb fb
+    >                                                                 ^
+    >  ffff88003a2bdb00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+    >  ffff88003a2bdb80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+    > ==================================================================
+    
+    What this means is that the gadgetfs_suspend() routine was trying to
+    access dev->lock after it had been deallocated.  The root cause is a
+    race in the dummy_hcd driver; the dummy_udc_stop() routine can race
+    with the rest of the driver because it contains no locking.  And even
+    when proper locking is added, it can still race with the
+    set_link_state() function because that function incorrectly drops the
+    private spinlock before invoking any gadget driver callbacks.
+    
+    The result of this race, as seen above, is that set_link_state() can
+    invoke a callback in gadgetfs even after gadgetfs has been unbound
+    from dummy_hcd's UDC and its private data structures have been
+    deallocated.
+    
+    include/linux/usb/gadget.h documents that the ->reset, ->disconnect,
+    ->suspend, and ->resume callbacks may be invoked in interrupt context.
+    In general this is necessary, to prevent races with gadget driver
+    removal.  This patch fixes dummy_hcd to retain the spinlock across
+    these calls, and it adds a spinlock acquisition to dummy_udc_stop() to
+    prevent the race.
+    
+    The net2280 driver makes the same mistake of dropping the private
+    spinlock for its ->disconnect and ->reset callback invocations.  The
+    patch fixes it too.
+    
+    Lastly, since gadgetfs_suspend() may be invoked in interrupt context,
+    it cannot assume that interrupts are enabled when it runs.  It must
+    use spin_lock_irqsave() instead of spin_lock_irq().  The patch fixes
+    that bug as well.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Andrey Konovalov 
+    CC: 
+    Acked-by: Felipe Balbi 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
+index 5ffd879f7886..684900fcfe24 100644
+--- a/drivers/usb/gadget/legacy/inode.c
++++ b/drivers/usb/gadget/legacy/inode.c
+@@ -1679,9 +1679,10 @@ static void
+ gadgetfs_suspend (struct usb_gadget *gadget)
+ {
+ 	struct dev_data		*dev = get_gadget_data (gadget);
++	unsigned long		flags;
+ 
+ 	INFO (dev, "suspended from state %d\n", dev->state);
+-	spin_lock (&dev->lock);
++	spin_lock_irqsave(&dev->lock, flags);
+ 	switch (dev->state) {
+ 	case STATE_DEV_SETUP:		// VERY odd... host died??
+ 	case STATE_DEV_CONNECTED:
+@@ -1692,7 +1693,7 @@ gadgetfs_suspend (struct usb_gadget *gadget)
+ 	default:
+ 		break;
+ 	}
+-	spin_unlock (&dev->lock);
++	spin_unlock_irqrestore(&dev->lock, flags);
+ }
+ 
+ static struct usb_gadget_driver gadgetfs_driver = {
+diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
+index ccabb51cb98d..7635fd7cc328 100644
+--- a/drivers/usb/gadget/udc/dummy_hcd.c
++++ b/drivers/usb/gadget/udc/dummy_hcd.c
+@@ -442,23 +442,16 @@ static void set_link_state(struct dummy_hcd *dum_hcd)
+ 		/* Report reset and disconnect events to the driver */
+ 		if (dum->driver && (disconnect || reset)) {
+ 			stop_activity(dum);
+-			spin_unlock(&dum->lock);
+ 			if (reset)
+ 				usb_gadget_udc_reset(&dum->gadget, dum->driver);
+ 			else
+ 				dum->driver->disconnect(&dum->gadget);
+-			spin_lock(&dum->lock);
+ 		}
+ 	} else if (dum_hcd->active != dum_hcd->old_active) {
+-		if (dum_hcd->old_active && dum->driver->suspend) {
+-			spin_unlock(&dum->lock);
++		if (dum_hcd->old_active && dum->driver->suspend)
+ 			dum->driver->suspend(&dum->gadget);
+-			spin_lock(&dum->lock);
+-		} else if (!dum_hcd->old_active &&  dum->driver->resume) {
+-			spin_unlock(&dum->lock);
++		else if (!dum_hcd->old_active &&  dum->driver->resume)
+ 			dum->driver->resume(&dum->gadget);
+-			spin_lock(&dum->lock);
+-		}
+ 	}
+ 
+ 	dum_hcd->old_status = dum_hcd->port_status;
+@@ -983,7 +976,9 @@ static int dummy_udc_stop(struct usb_gadget *g)
+ 	struct dummy_hcd	*dum_hcd = gadget_to_dummy_hcd(g);
+ 	struct dummy		*dum = dum_hcd->dum;
+ 
++	spin_lock_irq(&dum->lock);
+ 	dum->driver = NULL;
++	spin_unlock_irq(&dum->lock);
+ 
+ 	return 0;
+ }
+diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c
+index 6cf07857eaca..f2cbd7f8005e 100644
+--- a/drivers/usb/gadget/udc/net2280.c
++++ b/drivers/usb/gadget/udc/net2280.c
+@@ -2470,11 +2470,8 @@ static void stop_activity(struct net2280 *dev, struct usb_gadget_driver *driver)
+ 		nuke(&dev->ep[i]);
+ 
+ 	/* report disconnect; the driver is already quiesced */
+-	if (driver) {
+-		spin_unlock(&dev->lock);
++	if (driver)
+ 		driver->disconnect(&dev->gadget);
+-		spin_lock(&dev->lock);
+-	}
+ 
+ 	usb_reinit(dev);
+ }
+@@ -3348,8 +3345,6 @@ static void handle_stat0_irqs(struct net2280 *dev, u32 stat)
+ 		BIT(PCI_RETRY_ABORT_INTERRUPT))
+ 
+ static void handle_stat1_irqs(struct net2280 *dev, u32 stat)
+-__releases(dev->lock)
+-__acquires(dev->lock)
+ {
+ 	struct net2280_ep	*ep;
+ 	u32			tmp, num, mask, scratch;
+@@ -3390,14 +3385,12 @@ __acquires(dev->lock)
+ 			if (disconnect || reset) {
+ 				stop_activity(dev, dev->driver);
+ 				ep0_start(dev);
+-				spin_unlock(&dev->lock);
+ 				if (reset)
+ 					usb_gadget_udc_reset
+ 						(&dev->gadget, dev->driver);
+ 				else
+ 					(dev->driver->disconnect)
+ 						(&dev->gadget);
+-				spin_lock(&dev->lock);
+ 				return;
+ 			}
+ 		}

commit c01b244ad848ac7f0faa141182db80650a8a761a
+Author: Alan Stern 
+Date:   Mon Jun 5 10:28:01 2017 -0400
+
+    USB: add usbfs ioctl to retrieve the connection speed
+    
+    The usbfs interface does not provide any way for the user to learn the
+    speed at which a device is connected.  The current API includes a
+    USBDEVFS_CONNECTINFO ioctl, but all it provides is the device's
+    address and a one-bit value indicating whether the connection is low
+    speed.  That may have sufficed in the era of USB-1.1, but it isn't
+    good enough today.
+    
+    This patch introduces a new ioctl, USBDEVFS_GET_SPEED, which returns a
+    numeric value indicating the speed of the connection: unknown, low,
+    full, high, wireless, super, or super-plus.
+    
+    Similar information (not exactly the same) is available through sysfs,
+    but it seems reasonable to provide the actual value in usbfs.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Reinhard Huck 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 8e6ef671be9b..0e7d0e81a7cb 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -2537,6 +2537,9 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
+ 	case USBDEVFS_DROP_PRIVILEGES:
+ 		ret = proc_drop_privileges(ps, p);
+ 		break;
++	case USBDEVFS_GET_SPEED:
++		ret = ps->dev->speed;
++		break;
+ 	}
+ 
+  done:
+diff --git a/include/uapi/linux/usbdevice_fs.h b/include/uapi/linux/usbdevice_fs.h
+index a8653a6f40df..0bbfd4abd2e3 100644
+--- a/include/uapi/linux/usbdevice_fs.h
++++ b/include/uapi/linux/usbdevice_fs.h
+@@ -156,6 +156,11 @@ struct usbdevfs_streams {
+ 	unsigned char eps[0];
+ };
+ 
++/*
++ * USB_SPEED_* values returned by USBDEVFS_GET_SPEED are defined in
++ * linux/usb/ch9.h
++ */
++
+ #define USBDEVFS_CONTROL           _IOWR('U', 0, struct usbdevfs_ctrltransfer)
+ #define USBDEVFS_CONTROL32           _IOWR('U', 0, struct usbdevfs_ctrltransfer32)
+ #define USBDEVFS_BULK              _IOWR('U', 2, struct usbdevfs_bulktransfer)
+@@ -190,5 +195,6 @@ struct usbdevfs_streams {
+ #define USBDEVFS_ALLOC_STREAMS     _IOR('U', 28, struct usbdevfs_streams)
+ #define USBDEVFS_FREE_STREAMS      _IOR('U', 29, struct usbdevfs_streams)
+ #define USBDEVFS_DROP_PRIVILEGES   _IOW('U', 30, __u32)
++#define USBDEVFS_GET_SPEED         _IO('U', 31)
+ 
+ #endif /* _UAPI_LINUX_USBDEVICE_FS_H */

commit f50b878fed33e360d01dcdc31a8eeb1815d033d5
+Author: Alan Stern 
+Date:   Thu Jun 8 13:55:59 2017 -0400
+
+    USB: gadget: fix GPF in gadgetfs
+    
+    A NULL-pointer dereference bug in gadgetfs was uncovered by syzkaller:
+    
+    > kasan: GPF could be caused by NULL-ptr deref or user memory access
+    > general protection fault: 0000 [#1] SMP KASAN
+    > Dumping ftrace buffer:
+    >    (ftrace buffer empty)
+    > Modules linked in:
+    > CPU: 2 PID: 4820 Comm: syz-executor0 Not tainted 4.12.0-rc4+ #5
+    > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
+    > task: ffff880039542dc0 task.stack: ffff88003bdd0000
+    > RIP: 0010:__list_del_entry_valid+0x7e/0x170 lib/list_debug.c:51
+    > RSP: 0018:ffff88003bdd6e50 EFLAGS: 00010246
+    > RAX: dffffc0000000000 RBX: 0000000000000000 RCX: 0000000000010000
+    > RDX: 0000000000000000 RSI: ffffffff86504948 RDI: ffffffff86504950
+    > RBP: ffff88003bdd6e68 R08: ffff880039542dc0 R09: ffffffff8778ce00
+    > R10: ffff88003bdd6e68 R11: dffffc0000000000 R12: 0000000000000000
+    > R13: dffffc0000000000 R14: 1ffff100077badd2 R15: ffffffff864d2e40
+    > FS:  0000000000000000(0000) GS:ffff88006dc00000(0000) knlGS:0000000000000000
+    > CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+    > CR2: 000000002014aff9 CR3: 0000000006022000 CR4: 00000000000006e0
+    > Call Trace:
+    >  __list_del_entry include/linux/list.h:116 [inline]
+    >  list_del include/linux/list.h:124 [inline]
+    >  usb_gadget_unregister_driver+0x166/0x4c0 drivers/usb/gadget/udc/core.c:1387
+    >  dev_release+0x80/0x160 drivers/usb/gadget/legacy/inode.c:1187
+    >  __fput+0x332/0x7f0 fs/file_table.c:209
+    >  ____fput+0x15/0x20 fs/file_table.c:245
+    >  task_work_run+0x19b/0x270 kernel/task_work.c:116
+    >  exit_task_work include/linux/task_work.h:21 [inline]
+    >  do_exit+0x18a3/0x2820 kernel/exit.c:878
+    >  do_group_exit+0x149/0x420 kernel/exit.c:982
+    >  get_signal+0x77f/0x1780 kernel/signal.c:2318
+    >  do_signal+0xd2/0x2130 arch/x86/kernel/signal.c:808
+    >  exit_to_usermode_loop+0x1a7/0x240 arch/x86/entry/common.c:157
+    >  prepare_exit_to_usermode arch/x86/entry/common.c:194 [inline]
+    >  syscall_return_slowpath+0x3ba/0x410 arch/x86/entry/common.c:263
+    >  entry_SYSCALL_64_fastpath+0xbc/0xbe
+    > RIP: 0033:0x4461f9
+    > RSP: 002b:00007fdac2b1ecf8 EFLAGS: 00000246 ORIG_RAX: 00000000000000ca
+    > RAX: fffffffffffffe00 RBX: 00000000007080c8 RCX: 00000000004461f9
+    > RDX: 0000000000000000 RSI: 0000000000000000 RDI: 00000000007080c8
+    > RBP: 00000000007080a8 R08: 0000000000000000 R09: 0000000000000000
+    > R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
+    > R13: 0000000000000000 R14: 00007fdac2b1f9c0 R15: 00007fdac2b1f700
+    > Code: 00 00 00 00 ad de 49 39 c4 74 6a 48 b8 00 02 00 00 00 00 ad de
+    > 48 89 da 48 39 c3 74 74 48 c1 ea 03 48 b8 00 00 00 00 00 fc ff df <80>
+    > 3c 02 00 0f 85 92 00 00 00 48 8b 13 48 39 f2 75 66 49 8d 7c
+    > RIP: __list_del_entry_valid+0x7e/0x170 lib/list_debug.c:51 RSP: ffff88003bdd6e50
+    > ---[ end trace 30e94b1eec4831c8 ]---
+    > Kernel panic - not syncing: Fatal exception
+    
+    The bug was caused by dev_release() failing to turn off its
+    gadget_registered flag after unregistering the gadget driver.  As a
+    result, when a later user closed the device file before writing a
+    valid set of descriptors, dev_release() thought the gadget had been
+    registered and tried to unregister it, even though it had not been.
+    This led to the NULL pointer dereference.
+    
+    The fix is simple: turn off the flag when the gadget is unregistered.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Andrey Konovalov 
+    CC: 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
+index b9ca0a26cbd9..5ffd879f7886 100644
+--- a/drivers/usb/gadget/legacy/inode.c
++++ b/drivers/usb/gadget/legacy/inode.c
+@@ -1183,8 +1183,10 @@ dev_release (struct inode *inode, struct file *fd)
+ 
+ 	/* closing ep0 === shutdown all */
+ 
+-	if (dev->gadget_registered)
++	if (dev->gadget_registered) {
+ 		usb_gadget_unregister_driver (&gadgetfs_driver);
++		dev->gadget_registered = false;
++	}
+ 
+ 	/* at this point "good" hardware has disconnected the
+ 	 * device from USB; the host won't see it any more.

commit 5fcf93795e6b72368cd98cd541b6d4bbe8804320
+Author: Alan Stern 
+Date:   Tue May 16 11:48:20 2017 -0400
+
+    USB: ene_usb6250: turn off the Removable flag
+    
+    In the ene_usb6250 sub-driver for usb-storage, the INQUIRY data
+    returned by the driver indicates that the device has removable media.
+    While this is technically correct (memory cards can be removed from
+    the reader), it is not useful because the device automatically
+    disconnects itself from the USB bus when no media is present.
+    
+    In addition, the driver does not support the PREVENT-ALLOW MEDIUM
+    REMOVAL and START STOP UNIT commands, and this can cause
+    user-interface frameworks to get confused when the user asks for the
+    card to be removed or ejected.
+    
+    This patch fixes the problem by changing the INQUIRY data to specify
+    non-removable media; in practice this value works much better.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Andreas Hartmann 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c
+index a5ccdefed31e..22b850a1ce06 100644
+--- a/drivers/usb/storage/ene_ub6250.c
++++ b/drivers/usb/storage/ene_ub6250.c
+@@ -596,7 +596,7 @@ static int do_scsi_request_sense(struct us_data *us, struct scsi_cmnd *srb)
+ static int do_scsi_inquiry(struct us_data *us, struct scsi_cmnd *srb)
+ {
+ 	unsigned char data_ptr[36] = {
+-		0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55,
++		0x00, 0x00, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55,
+ 		0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, 0x20, 0x43, 0x61,
+ 		0x72, 0x64, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20,
+ 		0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30 };

commit f8efdabd14532c47e5420dc593c2a13028e42140
+Author: Alan Stern 
+Date:   Tue May 16 11:48:10 2017 -0400
+
+    USB: ene_usb6250: remove subroutine duplication
+    
+    In the ene_usb6250 sub-driver for usb-storage, the sd_scsi_inquiry()
+    and ms_scsi_inquiry() subroutines (one meant for use with SD memory
+    cards and the other for use with MS memory cards) are exact
+    duplicates.  This patch removes the duplication by creating a single
+    do_scsi_inquiry() command and using it instead of the other two.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Andreas Hartmann 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c
+index 44aca29ad6cc..a5ccdefed31e 100644
+--- a/drivers/usb/storage/ene_ub6250.c
++++ b/drivers/usb/storage/ene_ub6250.c
+@@ -593,6 +593,18 @@ static int do_scsi_request_sense(struct us_data *us, struct scsi_cmnd *srb)
+ 	return USB_STOR_TRANSPORT_GOOD;
+ }
+ 
++static int do_scsi_inquiry(struct us_data *us, struct scsi_cmnd *srb)
++{
++	unsigned char data_ptr[36] = {
++		0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55,
++		0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, 0x20, 0x43, 0x61,
++		0x72, 0x64, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20,
++		0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30 };
++
++	usb_stor_set_xfer_buf(data_ptr, 36, srb);
++	return USB_STOR_TRANSPORT_GOOD;
++}
++
+ static int sd_scsi_test_unit_ready(struct us_data *us, struct scsi_cmnd *srb)
+ {
+ 	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+@@ -607,18 +619,6 @@ static int sd_scsi_test_unit_ready(struct us_data *us, struct scsi_cmnd *srb)
+ 	return USB_STOR_TRANSPORT_GOOD;
+ }
+ 
+-static int sd_scsi_inquiry(struct us_data *us, struct scsi_cmnd *srb)
+-{
+-	unsigned char data_ptr[36] = {
+-		0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55,
+-		0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, 0x20, 0x43, 0x61,
+-		0x72, 0x64, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20,
+-		0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30 };
+-
+-	usb_stor_set_xfer_buf(data_ptr, 36, srb);
+-	return USB_STOR_TRANSPORT_GOOD;
+-}
+-
+ static int sd_scsi_mode_sense(struct us_data *us, struct scsi_cmnd *srb)
+ {
+ 	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+@@ -1462,19 +1462,6 @@ static int ms_scsi_test_unit_ready(struct us_data *us, struct scsi_cmnd *srb)
+ 	return USB_STOR_TRANSPORT_GOOD;
+ }
+ 
+-static int ms_scsi_inquiry(struct us_data *us, struct scsi_cmnd *srb)
+-{
+-	/* pr_info("MS_SCSI_Inquiry\n"); */
+-	unsigned char data_ptr[36] = {
+-		0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55,
+-		0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, 0x20, 0x43, 0x61,
+-		0x72, 0x64, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20,
+-		0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30};
+-
+-	usb_stor_set_xfer_buf(data_ptr, 36, srb);
+-	return USB_STOR_TRANSPORT_GOOD;
+-}
+-
+ static int ms_scsi_mode_sense(struct us_data *us, struct scsi_cmnd *srb)
+ {
+ 	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+@@ -2236,7 +2223,7 @@ static int sd_scsi_irp(struct us_data *us, struct scsi_cmnd *srb)
+ 		result = do_scsi_request_sense(us, srb);
+ 		break; /* 0x03 */
+ 	case INQUIRY:
+-		result = sd_scsi_inquiry(us, srb);
++		result = do_scsi_inquiry(us, srb);
+ 		break; /* 0x12 */
+ 	case MODE_SENSE:
+ 		result = sd_scsi_mode_sense(us, srb);
+@@ -2281,7 +2268,7 @@ static int ms_scsi_irp(struct us_data *us, struct scsi_cmnd *srb)
+ 		result = do_scsi_request_sense(us, srb);
+ 		break; /* 0x03 */
+ 	case INQUIRY:
+-		result = ms_scsi_inquiry(us, srb);
++		result = do_scsi_inquiry(us, srb);
+ 		break; /* 0x12 */
+ 	case MODE_SENSE:
+ 		result = ms_scsi_mode_sense(us, srb);

commit ce553bd103c161df2676ff201746bff8ca512715
+Author: Alan Stern 
+Date:   Tue May 16 11:48:01 2017 -0400
+
+    USB: ene_usb6250: implement REQUEST SENSE
+    
+    In the ene_usb6250 sub-driver for usb-storage, there is no support for
+    the REQUEST SENSE command.  This command is issued whenever a failure
+    occurs, and without it the driver has no way to tell the SCSI core
+    what the reason for the failure was.
+    
+    This patch adds a do_scsi_request_sense() routine to the driver.  The
+    new routine reports the error code stored by the previous command.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Andreas Hartmann 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c
+index 107018447551..44aca29ad6cc 100644
+--- a/drivers/usb/storage/ene_ub6250.c
++++ b/drivers/usb/storage/ene_ub6250.c
+@@ -95,12 +95,12 @@ static struct us_unusual_dev ene_ub6250_unusual_dev_list[] = {
+ #define REG_HW_TRAP1        0xFF89
+ 
+ /* SRB Status */
+-#define SS_SUCCESS                  0x00      /* No Sense */
+-#define SS_NOT_READY                0x02
+-#define SS_MEDIUM_ERR               0x03
+-#define SS_HW_ERR                   0x04
+-#define SS_ILLEGAL_REQUEST          0x05
+-#define SS_UNIT_ATTENTION           0x06
++#define SS_SUCCESS		0x000000	/* No Sense */
++#define SS_NOT_READY		0x023A00	/* Medium not present */
++#define SS_MEDIUM_ERR		0x031100	/* Unrecovered read error */
++#define SS_HW_ERR		0x040800	/* Communication failure */
++#define SS_ILLEGAL_REQUEST	0x052000	/* Invalid command */
++#define SS_UNIT_ATTENTION	0x062900	/* Reset occurred */
+ 
+ /* ENE Load FW Pattern */
+ #define SD_INIT1_PATTERN   1
+@@ -577,6 +577,22 @@ static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg)
+ 	return USB_STOR_TRANSPORT_GOOD;
+ }
+ 
++static int do_scsi_request_sense(struct us_data *us, struct scsi_cmnd *srb)
++{
++	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
++	unsigned char buf[18];
++
++	memset(buf, 0, 18);
++	buf[0] = 0x70;				/* Current error */
++	buf[2] = info->SrbStatus >> 16;		/* Sense key */
++	buf[7] = 10;				/* Additional length */
++	buf[12] = info->SrbStatus >> 8;		/* ASC */
++	buf[13] = info->SrbStatus;		/* ASCQ */
++
++	usb_stor_set_xfer_buf(buf, sizeof(buf), srb);
++	return USB_STOR_TRANSPORT_GOOD;
++}
++
+ static int sd_scsi_test_unit_ready(struct us_data *us, struct scsi_cmnd *srb)
+ {
+ 	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+@@ -2212,11 +2228,13 @@ static int sd_scsi_irp(struct us_data *us, struct scsi_cmnd *srb)
+ 	int    result;
+ 	struct ene_ub6250_info *info = (struct ene_ub6250_info *)us->extra;
+ 
+-	info->SrbStatus = SS_SUCCESS;
+ 	switch (srb->cmnd[0]) {
+ 	case TEST_UNIT_READY:
+ 		result = sd_scsi_test_unit_ready(us, srb);
+ 		break; /* 0x00 */
++	case REQUEST_SENSE:
++		result = do_scsi_request_sense(us, srb);
++		break; /* 0x03 */
+ 	case INQUIRY:
+ 		result = sd_scsi_inquiry(us, srb);
+ 		break; /* 0x12 */
+@@ -2242,6 +2260,8 @@ static int sd_scsi_irp(struct us_data *us, struct scsi_cmnd *srb)
+ 		result = USB_STOR_TRANSPORT_FAILED;
+ 		break;
+ 	}
++	if (result == USB_STOR_TRANSPORT_GOOD)
++		info->SrbStatus = SS_SUCCESS;
+ 	return result;
+ }
+ 
+@@ -2252,11 +2272,14 @@ static int ms_scsi_irp(struct us_data *us, struct scsi_cmnd *srb)
+ {
+ 	int result;
+ 	struct ene_ub6250_info *info = (struct ene_ub6250_info *)us->extra;
+-	info->SrbStatus = SS_SUCCESS;
++
+ 	switch (srb->cmnd[0]) {
+ 	case TEST_UNIT_READY:
+ 		result = ms_scsi_test_unit_ready(us, srb);
+ 		break; /* 0x00 */
++	case REQUEST_SENSE:
++		result = do_scsi_request_sense(us, srb);
++		break; /* 0x03 */
+ 	case INQUIRY:
+ 		result = ms_scsi_inquiry(us, srb);
+ 		break; /* 0x12 */
+@@ -2277,6 +2300,8 @@ static int ms_scsi_irp(struct us_data *us, struct scsi_cmnd *srb)
+ 		result = USB_STOR_TRANSPORT_FAILED;
+ 		break;
+ 	}
++	if (result == USB_STOR_TRANSPORT_GOOD)
++		info->SrbStatus = SS_SUCCESS;
+ 	return result;
+ }
+ 

commit aa18c4b6e0e39bfb00af48734ec24bc189ac9909
+Author: Alan Stern 
+Date:   Tue May 16 11:47:52 2017 -0400
+
+    USB: ene_usb6250: fix SCSI residue overwriting
+    
+    In the ene_usb6250 sub-driver for usb-storage, the SCSI residue is not
+    reported correctly.  The residue is initialized to 0, but this value
+    is overwritten whenever the driver sends firmware to the card reader
+    before performing the current command.  As a result, a valid READ or
+    WRITE operation appears to have failed, causing the SCSI core to retry
+    the command multiple times and eventually fail.
+    
+    This patch fixes the problem by resetting the SCSI residue to 0 after
+    sending firmware to the device.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Andreas Hartmann 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c
+index 80cd67841074..107018447551 100644
+--- a/drivers/usb/storage/ene_ub6250.c
++++ b/drivers/usb/storage/ene_ub6250.c
+@@ -1929,6 +1929,8 @@ static int ene_load_bincode(struct us_data *us, unsigned char flag)
+ 	bcb->CDB[0] = 0xEF;
+ 
+ 	result = ene_send_scsi_cmd(us, FDIR_WRITE, buf, 0);
++	if (us->srb != NULL)
++		scsi_set_resid(us->srb, 0);
+ 	info->BIN_FLAG = flag;
+ 	kfree(buf);
+ 

commit 4b309f1c4972c8f09e03ac64fc63510dbf5591a4
+Author: Alan Stern 
+Date:   Tue May 16 11:47:42 2017 -0400
+
+    USB: ene_usb6250: fix first command execution
+    
+    In the ene_usb6250 sub-driver for usb-storage, the ene_transport()
+    routine is supposed to initialize the driver before executing the
+    current command, if the initialization has not already been performed.
+    However, a bug in the routine causes it to skip the command after
+    doing the initialization.  Also, the routine does not return an
+    appropriate error code if either the initialization or the command
+    fails.
+    
+    As a result of the first bug, the first command (a SCSI INQUIRY) is
+    not carried out.  The results can be seen in the system log, in the
+    form of a warning message and empty or garbage INQUIRY data:
+    
+    Apr 18 22:40:08 notebook2 kernel: scsi host6: scsi scan: INQUIRY result too short (5), using 36
+    Apr 18 22:40:08 notebook2 kernel: scsi 6:0:0:0: Direct-Access                                    PQ: 0 ANSI: 0
+    
+    This patch fixes both errors.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Andreas Hartmann 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c
+index 369f3c24815a..80cd67841074 100644
+--- a/drivers/usb/storage/ene_ub6250.c
++++ b/drivers/usb/storage/ene_ub6250.c
+@@ -2280,21 +2280,22 @@ static int ms_scsi_irp(struct us_data *us, struct scsi_cmnd *srb)
+ 
+ static int ene_transport(struct scsi_cmnd *srb, struct us_data *us)
+ {
+-	int result = 0;
++	int result = USB_STOR_XFER_GOOD;
+ 	struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
+ 
+ 	/*US_DEBUG(usb_stor_show_command(us, srb)); */
+ 	scsi_set_resid(srb, 0);
+-	if (unlikely(!(info->SD_Status.Ready || info->MS_Status.Ready))) {
++	if (unlikely(!(info->SD_Status.Ready || info->MS_Status.Ready)))
+ 		result = ene_init(us);
+-	} else {
++	if (result == USB_STOR_XFER_GOOD) {
++		result = USB_STOR_TRANSPORT_ERROR;
+ 		if (info->SD_Status.Ready)
+ 			result = sd_scsi_irp(us, srb);
+ 
+ 		if (info->MS_Status.Ready)
+ 			result = ms_scsi_irp(us, srb);
+ 	}
+-	return 0;
++	return result;
+ }
+ 
+ static struct scsi_host_template ene_ub6250_host_template;

commit 63aea0dbab90a2461faaae357cbc8cfd6c8de9fe
+Author: Alan Stern 
+Date:   Wed May 17 18:32:03 2017 +0300
+
+    USB: xhci: fix lock-inversion problem
+    
+    With threaded interrupts, bottom-half handlers are called with
+    interrupts enabled.  Therefore they can't safely use spin_lock(); they
+    have to use spin_lock_irqsave().  Lockdep warns about a violation
+    occurring in xhci_irq():
+    
+    =========================================================
+    [ INFO: possible irq lock inversion dependency detected ]
+    4.11.0-rc8-dbg+ #1 Not tainted
+    ---------------------------------------------------------
+    swapper/7/0 just changed the state of lock:
+     (&(&ehci->lock)->rlock){-.-...}, at: []
+    ehci_hrtimer_func+0x29/0xc0 [ehci_hcd]
+    but this lock took another, HARDIRQ-unsafe lock in the past:
+     (hcd_urb_list_lock){+.....}
+    
+    and interrupts could create inverse lock ordering between them.
+    
+    other info that might help us debug this:
+     Possible interrupt unsafe locking scenario:
+    
+           CPU0                    CPU1
+           ----                    ----
+      lock(hcd_urb_list_lock);
+                                   local_irq_disable();
+                                   lock(&(&ehci->lock)->rlock);
+                                   lock(hcd_urb_list_lock);
+      
+        lock(&(&ehci->lock)->rlock);
+     *** DEADLOCK ***
+    
+    no locks held by swapper/7/0.
+    the shortest dependencies between 2nd lock and 1st lock:
+     -> (hcd_urb_list_lock){+.....} ops: 252 {
+        HARDIRQ-ON-W at:
+                          __lock_acquire+0x602/0x1280
+                          lock_acquire+0xd5/0x1c0
+                          _raw_spin_lock+0x2f/0x40
+                          usb_hcd_unlink_urb_from_ep+0x1b/0x60 [usbcore]
+                          xhci_giveback_urb_in_irq.isra.45+0x70/0x1b0 [xhci_hcd]
+                          finish_td.constprop.60+0x1d8/0x2e0 [xhci_hcd]
+                          xhci_irq+0xdd6/0x1fa0 [xhci_hcd]
+                          usb_hcd_irq+0x26/0x40 [usbcore]
+                          irq_forced_thread_fn+0x2f/0x70
+                          irq_thread+0x149/0x1d0
+                          kthread+0x113/0x150
+                          ret_from_fork+0x2e/0x40
+    
+    This patch fixes the problem.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Bart Van Assche 
+    CC: 
+    Signed-off-by: Mathias Nyman 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
+index 0830b25f9499..6d2492c1c643 100644
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -2677,11 +2677,12 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
+ 	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ 	union xhci_trb *event_ring_deq;
+ 	irqreturn_t ret = IRQ_NONE;
++	unsigned long flags;
+ 	dma_addr_t deq;
+ 	u64 temp_64;
+ 	u32 status;
+ 
+-	spin_lock(&xhci->lock);
++	spin_lock_irqsave(&xhci->lock, flags);
+ 	/* Check if the xHC generated the interrupt, or the irq is shared */
+ 	status = readl(&xhci->op_regs->status);
+ 	if (status == ~(u32)0) {
+@@ -2754,7 +2755,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
+ 	ret = IRQ_HANDLED;
+ 
+ out:
+-	spin_unlock(&xhci->lock);
++	spin_unlock_irqrestore(&xhci->lock, flags);
+ 
+ 	return ret;
+ }

commit 628c2893d44876ddd11602400c70606ade62e129
+Author: Alan Stern 
+Date:   Tue May 16 11:47:29 2017 -0400
+
+    USB: ene_usb6250: fix DMA to the stack
+    
+    The ene_usb6250 sub-driver in usb-storage does USB I/O to buffers on
+    the stack, which doesn't work with vmapped stacks.  This patch fixes
+    the problem by allocating a separate 512-byte buffer at probe time and
+    using it for all of the offending I/O operations.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Andreas Hartmann 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c
+index 369f3c24815a..44af719194b2 100644
+--- a/drivers/usb/storage/ene_ub6250.c
++++ b/drivers/usb/storage/ene_ub6250.c
+@@ -446,6 +446,10 @@ struct ms_lib_ctrl {
+ #define SD_BLOCK_LEN  9
+ 
+ struct ene_ub6250_info {
++
++	/* I/O bounce buffer */
++	u8		*bbuf;
++
+ 	/* for 6250 code */
+ 	struct SD_STATUS	SD_Status;
+ 	struct MS_STATUS	MS_Status;
+@@ -493,8 +497,11 @@ static int ene_load_bincode(struct us_data *us, unsigned char flag);
+ 
+ static void ene_ub6250_info_destructor(void *extra)
+ {
++	struct ene_ub6250_info *info = (struct ene_ub6250_info *) extra;
++
+ 	if (!extra)
+ 		return;
++	kfree(info->bbuf);
+ }
+ 
+ static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg)
+@@ -860,8 +867,9 @@ static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr,
+ 		u8 PageNum, u32 *PageBuf, struct ms_lib_type_extdat *ExtraDat)
+ {
+ 	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
++	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
++	u8 *bbuf = info->bbuf;
+ 	int result;
+-	u8 ExtBuf[4];
+ 	u32 bn = PhyBlockAddr * 0x20 + PageNum;
+ 
+ 	result = ene_load_bincode(us, MS_RW_PATTERN);
+@@ -901,7 +909,7 @@ static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr,
+ 	bcb->CDB[2]     = (unsigned char)(PhyBlockAddr>>16);
+ 	bcb->CDB[6]     = 0x01;
+ 
+-	result = ene_send_scsi_cmd(us, FDIR_READ, &ExtBuf, 0);
++	result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0);
+ 	if (result != USB_STOR_XFER_GOOD)
+ 		return USB_STOR_TRANSPORT_ERROR;
+ 
+@@ -910,9 +918,9 @@ static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr,
+ 	ExtraDat->status0  = 0x10;  /* Not yet,fireware support */
+ 
+ 	ExtraDat->status1  = 0x00;  /* Not yet,fireware support */
+-	ExtraDat->ovrflg   = ExtBuf[0];
+-	ExtraDat->mngflg   = ExtBuf[1];
+-	ExtraDat->logadr   = memstick_logaddr(ExtBuf[2], ExtBuf[3]);
++	ExtraDat->ovrflg   = bbuf[0];
++	ExtraDat->mngflg   = bbuf[1];
++	ExtraDat->logadr   = memstick_logaddr(bbuf[2], bbuf[3]);
+ 
+ 	return USB_STOR_TRANSPORT_GOOD;
+ }
+@@ -1332,8 +1340,9 @@ static int ms_lib_read_extra(struct us_data *us, u32 PhyBlock,
+ 				u8 PageNum, struct ms_lib_type_extdat *ExtraDat)
+ {
+ 	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
++	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
++	u8 *bbuf = info->bbuf;
+ 	int result;
+-	u8 ExtBuf[4];
+ 
+ 	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+ 	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+@@ -1347,7 +1356,7 @@ static int ms_lib_read_extra(struct us_data *us, u32 PhyBlock,
+ 	bcb->CDB[2]     = (unsigned char)(PhyBlock>>16);
+ 	bcb->CDB[6]     = 0x01;
+ 
+-	result = ene_send_scsi_cmd(us, FDIR_READ, &ExtBuf, 0);
++	result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0);
+ 	if (result != USB_STOR_XFER_GOOD)
+ 		return USB_STOR_TRANSPORT_ERROR;
+ 
+@@ -1355,9 +1364,9 @@ static int ms_lib_read_extra(struct us_data *us, u32 PhyBlock,
+ 	ExtraDat->intr     = 0x80;  /* Not yet, waiting for fireware support */
+ 	ExtraDat->status0  = 0x10;  /* Not yet, waiting for fireware support */
+ 	ExtraDat->status1  = 0x00;  /* Not yet, waiting for fireware support */
+-	ExtraDat->ovrflg   = ExtBuf[0];
+-	ExtraDat->mngflg   = ExtBuf[1];
+-	ExtraDat->logadr   = memstick_logaddr(ExtBuf[2], ExtBuf[3]);
++	ExtraDat->ovrflg   = bbuf[0];
++	ExtraDat->mngflg   = bbuf[1];
++	ExtraDat->logadr   = memstick_logaddr(bbuf[2], bbuf[3]);
+ 
+ 	return USB_STOR_TRANSPORT_GOOD;
+ }
+@@ -1556,9 +1565,9 @@ static int ms_lib_scan_logicalblocknumber(struct us_data *us, u16 btBlk1st)
+ 	u16 PhyBlock, newblk, i;
+ 	u16 LogStart, LogEnde;
+ 	struct ms_lib_type_extdat extdat;
+-	u8 buf[0x200];
+ 	u32 count = 0, index = 0;
+ 	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
++	u8 *bbuf = info->bbuf;
+ 
+ 	for (PhyBlock = 0; PhyBlock < info->MS_Lib.NumberOfPhyBlock;) {
+ 		ms_lib_phy_to_log_range(PhyBlock, &LogStart, &LogEnde);
+@@ -1572,14 +1581,16 @@ static int ms_lib_scan_logicalblocknumber(struct us_data *us, u16 btBlk1st)
+ 			}
+ 
+ 			if (count == PhyBlock) {
+-				ms_lib_read_extrablock(us, PhyBlock, 0, 0x80, &buf);
++				ms_lib_read_extrablock(us, PhyBlock, 0, 0x80,
++						bbuf);
+ 				count += 0x80;
+ 			}
+ 			index = (PhyBlock % 0x80) * 4;
+ 
+-			extdat.ovrflg = buf[index];
+-			extdat.mngflg = buf[index+1];
+-			extdat.logadr = memstick_logaddr(buf[index+2], buf[index+3]);
++			extdat.ovrflg = bbuf[index];
++			extdat.mngflg = bbuf[index+1];
++			extdat.logadr = memstick_logaddr(bbuf[index+2],
++					bbuf[index+3]);
+ 
+ 			if ((extdat.ovrflg & MS_REG_OVR_BKST) != MS_REG_OVR_BKST_OK) {
+ 				ms_lib_setacquired_errorblock(us, PhyBlock);
+@@ -2062,9 +2073,9 @@ static int ene_ms_init(struct us_data *us)
+ {
+ 	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+ 	int result;
+-	u8 buf[0x200];
+ 	u16 MSP_BlockSize, MSP_UserAreaBlocks;
+ 	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
++	u8 *bbuf = info->bbuf;
+ 
+ 	printk(KERN_INFO "transport --- ENE_MSInit\n");
+ 
+@@ -2083,13 +2094,13 @@ static int ene_ms_init(struct us_data *us)
+ 	bcb->CDB[0]     = 0xF1;
+ 	bcb->CDB[1]     = 0x01;
+ 
+-	result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0);
++	result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0);
+ 	if (result != USB_STOR_XFER_GOOD) {
+ 		printk(KERN_ERR "Execution MS Init Code Fail !!\n");
+ 		return USB_STOR_TRANSPORT_ERROR;
+ 	}
+ 	/* the same part to test ENE */
+-	info->MS_Status = *(struct MS_STATUS *)&buf[0];
++	info->MS_Status = *(struct MS_STATUS *) bbuf;
+ 
+ 	if (info->MS_Status.Insert && info->MS_Status.Ready) {
+ 		printk(KERN_INFO "Insert     = %x\n", info->MS_Status.Insert);
+@@ -2098,15 +2109,15 @@ static int ene_ms_init(struct us_data *us)
+ 		printk(KERN_INFO "IsMSPHG    = %x\n", info->MS_Status.IsMSPHG);
+ 		printk(KERN_INFO "WtP= %x\n", info->MS_Status.WtP);
+ 		if (info->MS_Status.IsMSPro) {
+-			MSP_BlockSize      = (buf[6] << 8) | buf[7];
+-			MSP_UserAreaBlocks = (buf[10] << 8) | buf[11];
++			MSP_BlockSize      = (bbuf[6] << 8) | bbuf[7];
++			MSP_UserAreaBlocks = (bbuf[10] << 8) | bbuf[11];
+ 			info->MSP_TotalBlock = MSP_BlockSize * MSP_UserAreaBlocks;
+ 		} else {
+ 			ms_card_init(us); /* Card is MS (to ms.c)*/
+ 		}
+ 		usb_stor_dbg(us, "MS Init Code OK !!\n");
+ 	} else {
+-		usb_stor_dbg(us, "MS Card Not Ready --- %x\n", buf[0]);
++		usb_stor_dbg(us, "MS Card Not Ready --- %x\n", bbuf[0]);
+ 		return USB_STOR_TRANSPORT_ERROR;
+ 	}
+ 
+@@ -2116,9 +2127,9 @@ static int ene_ms_init(struct us_data *us)
+ static int ene_sd_init(struct us_data *us)
+ {
+ 	int result;
+-	u8  buf[0x200];
+ 	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+ 	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
++	u8 *bbuf = info->bbuf;
+ 
+ 	usb_stor_dbg(us, "transport --- ENE_SDInit\n");
+ 	/* SD Init Part-1 */
+@@ -2152,17 +2163,17 @@ static int ene_sd_init(struct us_data *us)
+ 	bcb->Flags              = US_BULK_FLAG_IN;
+ 	bcb->CDB[0]             = 0xF1;
+ 
+-	result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0);
++	result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0);
+ 	if (result != USB_STOR_XFER_GOOD) {
+ 		usb_stor_dbg(us, "Execution SD Init Code Fail !!\n");
+ 		return USB_STOR_TRANSPORT_ERROR;
+ 	}
+ 
+-	info->SD_Status =  *(struct SD_STATUS *)&buf[0];
++	info->SD_Status =  *(struct SD_STATUS *) bbuf;
+ 	if (info->SD_Status.Insert && info->SD_Status.Ready) {
+ 		struct SD_STATUS *s = &info->SD_Status;
+ 
+-		ene_get_card_status(us, (unsigned char *)&buf);
++		ene_get_card_status(us, bbuf);
+ 		usb_stor_dbg(us, "Insert     = %x\n", s->Insert);
+ 		usb_stor_dbg(us, "Ready      = %x\n", s->Ready);
+ 		usb_stor_dbg(us, "IsMMC      = %x\n", s->IsMMC);
+@@ -2170,7 +2181,7 @@ static int ene_sd_init(struct us_data *us)
+ 		usb_stor_dbg(us, "HiSpeed    = %x\n", s->HiSpeed);
+ 		usb_stor_dbg(us, "WtP        = %x\n", s->WtP);
+ 	} else {
+-		usb_stor_dbg(us, "SD Card Not Ready --- %x\n", buf[0]);
++		usb_stor_dbg(us, "SD Card Not Ready --- %x\n", bbuf[0]);
+ 		return USB_STOR_TRANSPORT_ERROR;
+ 	}
+ 	return USB_STOR_TRANSPORT_GOOD;
+@@ -2180,13 +2191,15 @@ static int ene_sd_init(struct us_data *us)
+ static int ene_init(struct us_data *us)
+ {
+ 	int result;
+-	u8  misc_reg03 = 0;
++	u8  misc_reg03;
+ 	struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
++	u8 *bbuf = info->bbuf;
+ 
+-	result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03);
++	result = ene_get_card_type(us, REG_CARD_STATUS, bbuf);
+ 	if (result != USB_STOR_XFER_GOOD)
+ 		return USB_STOR_TRANSPORT_ERROR;
+ 
++	misc_reg03 = bbuf[0];
+ 	if (misc_reg03 & 0x01) {
+ 		if (!info->SD_Status.Ready) {
+ 			result = ene_sd_init(us);
+@@ -2303,8 +2316,9 @@ static int ene_ub6250_probe(struct usb_interface *intf,
+ 			 const struct usb_device_id *id)
+ {
+ 	int result;
+-	u8  misc_reg03 = 0;
++	u8  misc_reg03;
+ 	struct us_data *us;
++	struct ene_ub6250_info *info;
+ 
+ 	result = usb_stor_probe1(&us, intf, id,
+ 		   (id - ene_ub6250_usb_ids) + ene_ub6250_unusual_dev_list,
+@@ -2313,11 +2327,16 @@ static int ene_ub6250_probe(struct usb_interface *intf,
+ 		return result;
+ 
+ 	/* FIXME: where should the code alloc extra buf ? */
+-	if (!us->extra) {
+-		us->extra = kzalloc(sizeof(struct ene_ub6250_info), GFP_KERNEL);
+-		if (!us->extra)
+-			return -ENOMEM;
+-		us->extra_destructor = ene_ub6250_info_destructor;
++	us->extra = kzalloc(sizeof(struct ene_ub6250_info), GFP_KERNEL);
++	if (!us->extra)
++		return -ENOMEM;
++	us->extra_destructor = ene_ub6250_info_destructor;
++
++	info = (struct ene_ub6250_info *)(us->extra);
++	info->bbuf = kmalloc(512, GFP_KERNEL);
++	if (!info->bbuf) {
++		kfree(us->extra);
++		return -ENOMEM;
+ 	}
+ 
+ 	us->transport_name = "ene_ub6250";
+@@ -2329,12 +2348,13 @@ static int ene_ub6250_probe(struct usb_interface *intf,
+ 		return result;
+ 
+ 	/* probe card type */
+-	result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03);
++	result = ene_get_card_type(us, REG_CARD_STATUS, info->bbuf);
+ 	if (result != USB_STOR_XFER_GOOD) {
+ 		usb_stor_disconnect(intf);
+ 		return USB_STOR_TRANSPORT_ERROR;
+ 	}
+ 
++	misc_reg03 = info->bbuf[0];
+ 	if (!(misc_reg03 & 0x01)) {
+ 		pr_info("ums_eneub6250: This driver only supports SD/MS cards. "
+ 			"It does not support SM cards.\n");

commit 225785aec726f3edd5077be8f084b0b70ca197a8
+Author: Alan Stern 
+Date:   Thu Apr 13 16:37:01 2017 -0400
+
+    USB: f_mass_storage: improve memory barriers and synchronization
+    
+    This patch reworks the way f_mass_storage.c handles memory barriers
+    and synchronization:
+    
+            The driver now uses a wait_queue instead of doing its own
+            task-state manipulations (even though only one task will ever
+            use the wait_queue).
+    
+            The thread_wakeup_needed variable is removed.  It was only a
+            source of trouble; although it was what the driver tested to
+            see whether it should wake up, what we really wanted to see
+            was whether a USB transfer had completed.
+    
+            All the explicit memory barriers scattered throughout the
+            driver are replaced by a few calls to smp_load_acquire() and
+            smp_store_release().
+    
+            The inreq_busy and outreq_busy fields are removed.  In their
+            place, the driver keeps track of the current I/O direction by
+            splitting BUF_STATE_BUSY into two states: BUF_STATE_SENDING
+            and BUF_STATE_RECEIVING.
+    
+            The buffer states are no longer protected by a lock.  Mutual
+            exclusion isn't needed; the state is changed only by the
+            driver's main thread when it owns the buffer, and only by the
+            request completion routine when the gadget core owns the buffer.
+    
+            The do_write() and throw_away_data() routines were reorganized
+            to make efficient use of the new sleeping mechanism.  This
+            resulted in the removal of one indentation level in those
+            routines, making the patch appear to be more more complicated
+            than it really is.
+    
+            In a few places, the driver allowed itself to be frozen although
+            it really shouldn't have (in the middle of executing a SCSI
+            command).  Those places have been fixed.
+    
+            The logic in the exception handler for aborting transfers and
+            waiting for them to stop has been simplified.
+    
+    Tested-by: Thinh Nguyen 
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c
+index a0890a058f09..e80b9c123a9d 100644
+--- a/drivers/usb/gadget/function/f_mass_storage.c
++++ b/drivers/usb/gadget/function/f_mass_storage.c
+@@ -260,12 +260,13 @@ struct fsg_common {
+ 	struct usb_gadget	*gadget;
+ 	struct usb_composite_dev *cdev;
+ 	struct fsg_dev		*fsg, *new_fsg;
++	wait_queue_head_t	io_wait;
+ 	wait_queue_head_t	fsg_wait;
+ 
+ 	/* filesem protects: backing files in use */
+ 	struct rw_semaphore	filesem;
+ 
+-	/* lock protects: state, all the req_busy's */
++	/* lock protects: state and thread_task */
+ 	spinlock_t		lock;
+ 
+ 	struct usb_ep		*ep0;		/* Copy of gadget->ep0 */
+@@ -303,7 +304,6 @@ struct fsg_common {
+ 	unsigned int		running:1;
+ 	unsigned int		sysfs:1;
+ 
+-	int			thread_wakeup_needed;
+ 	struct completion	thread_notifier;
+ 	struct task_struct	*thread_task;
+ 
+@@ -393,16 +393,6 @@ static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
+ 
+ /* These routines may be called in process context or in_irq */
+ 
+-/* Caller must hold fsg->lock */
+-static void wakeup_thread(struct fsg_common *common)
+-{
+-	smp_wmb();	/* ensure the write of bh->state is complete */
+-	/* Tell the main thread that something has happened */
+-	common->thread_wakeup_needed = 1;
+-	if (common->thread_task)
+-		wake_up_process(common->thread_task);
+-}
+-
+ static void raise_exception(struct fsg_common *common, enum fsg_state new_state)
+ {
+ 	unsigned long		flags;
+@@ -456,13 +446,9 @@ static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)
+ 	if (req->status == -ECONNRESET)		/* Request was cancelled */
+ 		usb_ep_fifo_flush(ep);
+ 
+-	/* Hold the lock while we update the request and buffer states */
+-	smp_wmb();
+-	spin_lock(&common->lock);
+-	bh->inreq_busy = 0;
+-	bh->state = BUF_STATE_EMPTY;
+-	wakeup_thread(common);
+-	spin_unlock(&common->lock);
++	/* Synchronize with the smp_load_acquire() in sleep_thread() */
++	smp_store_release(&bh->state, BUF_STATE_EMPTY);
++	wake_up(&common->io_wait);
+ }
+ 
+ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
+@@ -477,13 +463,9 @@ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
+ 	if (req->status == -ECONNRESET)		/* Request was cancelled */
+ 		usb_ep_fifo_flush(ep);
+ 
+-	/* Hold the lock while we update the request and buffer states */
+-	smp_wmb();
+-	spin_lock(&common->lock);
+-	bh->outreq_busy = 0;
+-	bh->state = BUF_STATE_FULL;
+-	wakeup_thread(common);
+-	spin_unlock(&common->lock);
++	/* Synchronize with the smp_load_acquire() in sleep_thread() */
++	smp_store_release(&bh->state, BUF_STATE_FULL);
++	wake_up(&common->io_wait);
+ }
+ 
+ static int _fsg_common_get_max_lun(struct fsg_common *common)
+@@ -559,43 +541,39 @@ static int fsg_setup(struct usb_function *f,
+ /* All the following routines run in process context */
+ 
+ /* Use this for bulk or interrupt transfers, not ep0 */
+-static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
+-			   struct usb_request *req, int *pbusy,
+-			   enum fsg_buffer_state *state)
++static int start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
++			   struct usb_request *req)
+ {
+ 	int	rc;
+ 
+ 	if (ep == fsg->bulk_in)
+ 		dump_msg(fsg, "bulk-in", req->buf, req->length);
+ 
+-	spin_lock_irq(&fsg->common->lock);
+-	*pbusy = 1;
+-	*state = BUF_STATE_BUSY;
+-	spin_unlock_irq(&fsg->common->lock);
+-
+ 	rc = usb_ep_queue(ep, req, GFP_KERNEL);
+-	if (rc == 0)
+-		return;  /* All good, we're done */
+-
+-	*pbusy = 0;
+-	*state = BUF_STATE_EMPTY;
++	if (rc) {
+ 
+-	/* We can't do much more than wait for a reset */
++		/* We can't do much more than wait for a reset */
++		req->status = rc;
+ 
+-	/*
+-	 * Note: currently the net2280 driver fails zero-length
+-	 * submissions if DMA is enabled.
+-	 */
+-	if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP && req->length == 0))
+-		WARNING(fsg, "error in submission: %s --> %d\n", ep->name, rc);
++		/*
++		 * Note: currently the net2280 driver fails zero-length
++		 * submissions if DMA is enabled.
++		 */
++		if (rc != -ESHUTDOWN &&
++				!(rc == -EOPNOTSUPP && req->length == 0))
++			WARNING(fsg, "error in submission: %s --> %d\n",
++					ep->name, rc);
++	}
++	return rc;
+ }
+ 
+ static bool start_in_transfer(struct fsg_common *common, struct fsg_buffhd *bh)
+ {
+ 	if (!fsg_is_set(common))
+ 		return false;
+-	start_transfer(common->fsg, common->fsg->bulk_in,
+-		       bh->inreq, &bh->inreq_busy, &bh->state);
++	bh->state = BUF_STATE_SENDING;
++	if (start_transfer(common->fsg, common->fsg->bulk_in, bh->inreq))
++		bh->state = BUF_STATE_EMPTY;
+ 	return true;
+ }
+ 
+@@ -603,32 +581,31 @@ static bool start_out_transfer(struct fsg_common *common, struct fsg_buffhd *bh)
+ {
+ 	if (!fsg_is_set(common))
+ 		return false;
+-	start_transfer(common->fsg, common->fsg->bulk_out,
+-		       bh->outreq, &bh->outreq_busy, &bh->state);
++	bh->state = BUF_STATE_RECEIVING;
++	if (start_transfer(common->fsg, common->fsg->bulk_out, bh->outreq))
++		bh->state = BUF_STATE_FULL;
+ 	return true;
+ }
+ 
+-static int sleep_thread(struct fsg_common *common, bool can_freeze)
++static int sleep_thread(struct fsg_common *common, bool can_freeze,
++		struct fsg_buffhd *bh)
+ {
+-	int	rc = 0;
++	int	rc;
+ 
+-	/* Wait until a signal arrives or we are woken up */
+-	for (;;) {
+-		if (can_freeze)
+-			try_to_freeze();
+-		set_current_state(TASK_INTERRUPTIBLE);
+-		if (signal_pending(current)) {
+-			rc = -EINTR;
+-			break;
+-		}
+-		if (common->thread_wakeup_needed)
+-			break;
+-		schedule();
+-	}
+-	__set_current_state(TASK_RUNNING);
+-	common->thread_wakeup_needed = 0;
+-	smp_rmb();	/* ensure the latest bh->state is visible */
+-	return rc;
++	/* Wait until a signal arrives or bh is no longer busy */
++	if (can_freeze)
++		/*
++		 * synchronize with the smp_store_release(&bh->state) in
++		 * bulk_in_complete() or bulk_out_complete()
++		 */
++		rc = wait_event_freezable(common->io_wait,
++				bh && smp_load_acquire(&bh->state) >=
++					BUF_STATE_EMPTY);
++	else
++		rc = wait_event_interruptible(common->io_wait,
++				bh && smp_load_acquire(&bh->state) >=
++					BUF_STATE_EMPTY);
++	return rc ? -EINTR : 0;
+ }
+ 
+ 
+@@ -688,11 +665,9 @@ static int do_read(struct fsg_common *common)
+ 
+ 		/* Wait for the next buffer to become available */
+ 		bh = common->next_buffhd_to_fill;
+-		while (bh->state != BUF_STATE_EMPTY) {
+-			rc = sleep_thread(common, false);
+-			if (rc)
+-				return rc;
+-		}
++		rc = sleep_thread(common, false, bh);
++		if (rc)
++			return rc;
+ 
+ 		/*
+ 		 * If we were asked to read past the end of file,
+@@ -869,84 +844,80 @@ static int do_write(struct fsg_common *common)
+ 		bh = common->next_buffhd_to_drain;
+ 		if (bh->state == BUF_STATE_EMPTY && !get_some_more)
+ 			break;			/* We stopped early */
+-		if (bh->state == BUF_STATE_FULL) {
+-			smp_rmb();
+-			common->next_buffhd_to_drain = bh->next;
+-			bh->state = BUF_STATE_EMPTY;
+-
+-			/* Did something go wrong with the transfer? */
+-			if (bh->outreq->status != 0) {
+-				curlun->sense_data = SS_COMMUNICATION_FAILURE;
+-				curlun->sense_data_info =
++
++		/* Wait for the data to be received */
++		rc = sleep_thread(common, false, bh);
++		if (rc)
++			return rc;
++
++		common->next_buffhd_to_drain = bh->next;
++		bh->state = BUF_STATE_EMPTY;
++
++		/* Did something go wrong with the transfer? */
++		if (bh->outreq->status != 0) {
++			curlun->sense_data = SS_COMMUNICATION_FAILURE;
++			curlun->sense_data_info =
+ 					file_offset >> curlun->blkbits;
+-				curlun->info_valid = 1;
+-				break;
+-			}
++			curlun->info_valid = 1;
++			break;
++		}
+ 
+-			amount = bh->outreq->actual;
+-			if (curlun->file_length - file_offset < amount) {
+-				LERROR(curlun,
+-				       "write %u @ %llu beyond end %llu\n",
++		amount = bh->outreq->actual;
++		if (curlun->file_length - file_offset < amount) {
++			LERROR(curlun, "write %u @ %llu beyond end %llu\n",
+ 				       amount, (unsigned long long)file_offset,
+ 				       (unsigned long long)curlun->file_length);
+-				amount = curlun->file_length - file_offset;
+-			}
++			amount = curlun->file_length - file_offset;
++		}
+ 
+-			/* Don't accept excess data.  The spec doesn't say
+-			 * what to do in this case.  We'll ignore the error.
+-			 */
+-			amount = min(amount, bh->bulk_out_intended_length);
+-
+-			/* Don't write a partial block */
+-			amount = round_down(amount, curlun->blksize);
+-			if (amount == 0)
+-				goto empty_write;
+-
+-			/* Perform the write */
+-			file_offset_tmp = file_offset;
+-			nwritten = vfs_write(curlun->filp,
+-					     (char __user *)bh->buf,
+-					     amount, &file_offset_tmp);
+-			VLDBG(curlun, "file write %u @ %llu -> %d\n", amount,
+-			      (unsigned long long)file_offset, (int)nwritten);
+-			if (signal_pending(current))
+-				return -EINTR;		/* Interrupted! */
+-
+-			if (nwritten < 0) {
+-				LDBG(curlun, "error in file write: %d\n",
+-				     (int)nwritten);
+-				nwritten = 0;
+-			} else if (nwritten < amount) {
+-				LDBG(curlun, "partial file write: %d/%u\n",
+-				     (int)nwritten, amount);
+-				nwritten = round_down(nwritten, curlun->blksize);
+-			}
+-			file_offset += nwritten;
+-			amount_left_to_write -= nwritten;
+-			common->residue -= nwritten;
++		/*
++		 * Don't accept excess data.  The spec doesn't say
++		 * what to do in this case.  We'll ignore the error.
++		 */
++		amount = min(amount, bh->bulk_out_intended_length);
+ 
+-			/* If an error occurred, report it and its position */
+-			if (nwritten < amount) {
+-				curlun->sense_data = SS_WRITE_ERROR;
+-				curlun->sense_data_info =
++		/* Don't write a partial block */
++		amount = round_down(amount, curlun->blksize);
++		if (amount == 0)
++			goto empty_write;
++
++		/* Perform the write */
++		file_offset_tmp = file_offset;
++		nwritten = vfs_write(curlun->filp, (char __user *)bh->buf,
++				amount, &file_offset_tmp);
++		VLDBG(curlun, "file write %u @ %llu -> %d\n", amount,
++				(unsigned long long)file_offset, (int)nwritten);
++		if (signal_pending(current))
++			return -EINTR;		/* Interrupted! */
++
++		if (nwritten < 0) {
++			LDBG(curlun, "error in file write: %d\n",
++					(int) nwritten);
++			nwritten = 0;
++		} else if (nwritten < amount) {
++			LDBG(curlun, "partial file write: %d/%u\n",
++					(int) nwritten, amount);
++			nwritten = round_down(nwritten, curlun->blksize);
++		}
++		file_offset += nwritten;
++		amount_left_to_write -= nwritten;
++		common->residue -= nwritten;
++
++		/* If an error occurred, report it and its position */
++		if (nwritten < amount) {
++			curlun->sense_data = SS_WRITE_ERROR;
++			curlun->sense_data_info =
+ 					file_offset >> curlun->blkbits;
+-				curlun->info_valid = 1;
+-				break;
+-			}
++			curlun->info_valid = 1;
++			break;
++		}
+ 
+  empty_write:
+-			/* Did the host decide to stop early? */
+-			if (bh->outreq->actual < bh->bulk_out_intended_length) {
+-				common->short_packet_received = 1;
+-				break;
+-			}
+-			continue;
++		/* Did the host decide to stop early? */
++		if (bh->outreq->actual < bh->bulk_out_intended_length) {
++			common->short_packet_received = 1;
++			break;
+ 		}
+-
+-		/* Wait for something to happen */
+-		rc = sleep_thread(common, false);
+-		if (rc)
+-			return rc;
+ 	}
+ 
+ 	return -EIO;		/* No default reply */
+@@ -1471,7 +1442,7 @@ static int wedge_bulk_in_endpoint(struct fsg_dev *fsg)
+ 
+ static int throw_away_data(struct fsg_common *common)
+ {
+-	struct fsg_buffhd	*bh;
++	struct fsg_buffhd	*bh, *bh2;
+ 	u32			amount;
+ 	int			rc;
+ 
+@@ -1479,26 +1450,10 @@ static int throw_away_data(struct fsg_common *common)
+ 	     bh->state != BUF_STATE_EMPTY || common->usb_amount_left > 0;
+ 	     bh = common->next_buffhd_to_drain) {
+ 
+-		/* Throw away the data in a filled buffer */
+-		if (bh->state == BUF_STATE_FULL) {
+-			smp_rmb();
+-			bh->state = BUF_STATE_EMPTY;
+-			common->next_buffhd_to_drain = bh->next;
+-
+-			/* A short packet or an error ends everything */
+-			if (bh->outreq->actual < bh->bulk_out_intended_length ||
+-			    bh->outreq->status != 0) {
+-				raise_exception(common,
+-						FSG_STATE_ABORT_BULK_OUT);
+-				return -EINTR;
+-			}
+-			continue;
+-		}
+-
+ 		/* Try to submit another request if we need one */
+-		bh = common->next_buffhd_to_fill;
+-		if (bh->state == BUF_STATE_EMPTY
+-		 && common->usb_amount_left > 0) {
++		bh2 = common->next_buffhd_to_fill;
++		if (bh2->state == BUF_STATE_EMPTY &&
++				common->usb_amount_left > 0) {
+ 			amount = min(common->usb_amount_left, FSG_BUFLEN);
+ 
+ 			/*
+@@ -1506,19 +1461,30 @@ static int throw_away_data(struct fsg_common *common)
+ 			 * equal to the buffer size, which is divisible by
+ 			 * the bulk-out maxpacket size.
+ 			 */
+-			set_bulk_out_req_length(common, bh, amount);
+-			if (!start_out_transfer(common, bh))
++			set_bulk_out_req_length(common, bh2, amount);
++			if (!start_out_transfer(common, bh2))
+ 				/* Dunno what to do if common->fsg is NULL */
+ 				return -EIO;
+-			common->next_buffhd_to_fill = bh->next;
++			common->next_buffhd_to_fill = bh2->next;
+ 			common->usb_amount_left -= amount;
+ 			continue;
+ 		}
+ 
+-		/* Otherwise wait for something to happen */
+-		rc = sleep_thread(common, true);
++		/* Wait for the data to be received */
++		rc = sleep_thread(common, false, bh);
+ 		if (rc)
+ 			return rc;
++
++		/* Throw away the data in a filled buffer */
++		bh->state = BUF_STATE_EMPTY;
++		common->next_buffhd_to_drain = bh->next;
++
++		/* A short packet or an error ends everything */
++		if (bh->outreq->actual < bh->bulk_out_intended_length ||
++				bh->outreq->status != 0) {
++			raise_exception(common, FSG_STATE_ABORT_BULK_OUT);
++			return -EINTR;
++		}
+ 	}
+ 	return 0;
+ }
+@@ -1636,11 +1602,9 @@ static void send_status(struct fsg_common *common)
+ 
+ 	/* Wait for the next buffer to become available */
+ 	bh = common->next_buffhd_to_fill;
+-	while (bh->state != BUF_STATE_EMPTY) {
+-		rc = sleep_thread(common, true);
+-		if (rc)
+-			return;
+-	}
++	rc = sleep_thread(common, false, bh);
++	if (rc)
++		return;
+ 
+ 	if (curlun) {
+ 		sd = curlun->sense_data;
+@@ -1839,11 +1803,10 @@ static int do_scsi_command(struct fsg_common *common)
+ 	/* Wait for the next buffer to become available for data or status */
+ 	bh = common->next_buffhd_to_fill;
+ 	common->next_buffhd_to_drain = bh;
+-	while (bh->state != BUF_STATE_EMPTY) {
+-		rc = sleep_thread(common, true);
+-		if (rc)
+-			return rc;
+-	}
++	rc = sleep_thread(common, false, bh);
++	if (rc)
++		return rc;
++
+ 	common->phase_error = 0;
+ 	common->short_packet_received = 0;
+ 
+@@ -2186,11 +2149,9 @@ static int get_next_command(struct fsg_common *common)
+ 
+ 	/* Wait for the next buffer to become available */
+ 	bh = common->next_buffhd_to_fill;
+-	while (bh->state != BUF_STATE_EMPTY) {
+-		rc = sleep_thread(common, true);
+-		if (rc)
+-			return rc;
+-	}
++	rc = sleep_thread(common, true, bh);
++	if (rc)
++		return rc;
+ 
+ 	/* Queue a request to read a Bulk-only CBW */
+ 	set_bulk_out_req_length(common, bh, US_BULK_CB_WRAP_LEN);
+@@ -2205,12 +2166,10 @@ static int get_next_command(struct fsg_common *common)
+ 	 */
+ 
+ 	/* Wait for the CBW to arrive */
+-	while (bh->state != BUF_STATE_FULL) {
+-		rc = sleep_thread(common, true);
+-		if (rc)
+-			return rc;
+-	}
+-	smp_rmb();
++	rc = sleep_thread(common, true, bh);
++	if (rc)
++		return rc;
++
+ 	rc = fsg_is_set(common) ? received_cbw(common->fsg, bh) : -EIO;
+ 	bh->state = BUF_STATE_EMPTY;
+ 
+@@ -2374,23 +2333,14 @@ static void handle_exception(struct fsg_common *common)
+ 	if (likely(common->fsg)) {
+ 		for (i = 0; i < common->fsg_num_buffers; ++i) {
+ 			bh = &common->buffhds[i];
+-			if (bh->inreq_busy)
++			if (bh->state == BUF_STATE_SENDING)
+ 				usb_ep_dequeue(common->fsg->bulk_in, bh->inreq);
+-			if (bh->outreq_busy)
++			if (bh->state == BUF_STATE_RECEIVING)
+ 				usb_ep_dequeue(common->fsg->bulk_out,
+ 					       bh->outreq);
+-		}
+ 
+-		/* Wait until everything is idle */
+-		for (;;) {
+-			int num_active = 0;
+-			for (i = 0; i < common->fsg_num_buffers; ++i) {
+-				bh = &common->buffhds[i];
+-				num_active += bh->inreq_busy + bh->outreq_busy;
+-			}
+-			if (num_active == 0)
+-				break;
+-			if (sleep_thread(common, true))
++			/* Wait for a transfer to become idle */
++			if (sleep_thread(common, false, bh))
+ 				return;
+ 		}
+ 
+@@ -2518,7 +2468,7 @@ static int fsg_main_thread(void *common_)
+ 		}
+ 
+ 		if (!common->running) {
+-			sleep_thread(common, true);
++			sleep_thread(common, true, NULL);
+ 			continue;
+ 		}
+ 
+@@ -2648,6 +2598,7 @@ static struct fsg_common *fsg_common_setup(struct fsg_common *common)
+ 	spin_lock_init(&common->lock);
+ 	kref_init(&common->ref);
+ 	init_completion(&common->thread_notifier);
++	init_waitqueue_head(&common->io_wait);
+ 	init_waitqueue_head(&common->fsg_wait);
+ 	common->state = FSG_STATE_TERMINATED;
+ 	memset(common->luns, 0, sizeof(common->luns));
+diff --git a/drivers/usb/gadget/function/storage_common.h b/drivers/usb/gadget/function/storage_common.h
+index e6095dfbf1d5..e0814a960132 100644
+--- a/drivers/usb/gadget/function/storage_common.h
++++ b/drivers/usb/gadget/function/storage_common.h
+@@ -133,9 +133,10 @@ static inline bool fsg_lun_is_open(struct fsg_lun *curlun)
+ #define FSG_MAX_LUNS	16
+ 
+ enum fsg_buffer_state {
++	BUF_STATE_SENDING = -2,
++	BUF_STATE_RECEIVING,
+ 	BUF_STATE_EMPTY = 0,
+-	BUF_STATE_FULL,
+-	BUF_STATE_BUSY
++	BUF_STATE_FULL
+ };
+ 
+ struct fsg_buffhd {
+@@ -151,9 +152,7 @@ struct fsg_buffhd {
+ 	unsigned int			bulk_out_intended_length;
+ 
+ 	struct usb_request		*inreq;
+-	int				inreq_busy;
+ 	struct usb_request		*outreq;
+-	int				outreq_busy;
+ };
+ 
+ enum fsg_state {

commit 78db441d2ea0c804bc43a2bf3f894c4f7a6c7788
+Author: Alan Stern 
+Date:   Thu Apr 13 16:36:50 2017 -0400
+
+    USB: f_mass_storage: improve async notification handling
+    
+    This patch makes several adjustments to the way f_mass_storage.c
+    handles its internal state and asynchronous notifications (AKA
+    exceptions):
+    
+            A number of states weren't being used for anything.
+            They are removed.
+    
+            The FSG_STATE_IDLE state was renamed to FSG_STATE_NORMAL,
+            because it now applies whenever the gadget is operating
+            normally, not just when the gadget is idle.
+    
+            The FSG_STATE_RESET state was renamed to
+            FSG_STATE_PROTOCOL_RESET, indicating that it represents a
+            Bulk-Only Transport protocol reset and not a general USB
+            reset.
+    
+            When a signal arrives, it's silly for the signal handler to
+            send itself another signal!  Now it takes care of everything
+            inline.
+    
+    Along with an assortment of other minor changes in the same category.
+    
+    Tested-by: Thinh Nguyen 
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c
+index 4c8aacc232c0..a0890a058f09 100644
+--- a/drivers/usb/gadget/function/f_mass_storage.c
++++ b/drivers/usb/gadget/function/f_mass_storage.c
+@@ -355,7 +355,7 @@ typedef void (*fsg_routine_t)(struct fsg_dev *);
+ 
+ static int exception_in_progress(struct fsg_common *common)
+ {
+-	return common->state > FSG_STATE_IDLE;
++	return common->state > FSG_STATE_NORMAL;
+ }
+ 
+ /* Make bulk-out requests be divisible by the maxpacket size */
+@@ -528,7 +528,7 @@ static int fsg_setup(struct usb_function *f,
+ 		 * and reinitialize our state.
+ 		 */
+ 		DBG(fsg, "bulk reset request\n");
+-		raise_exception(fsg->common, FSG_STATE_RESET);
++		raise_exception(fsg->common, FSG_STATE_PROTOCOL_RESET);
+ 		return USB_GADGET_DELAYED_STATUS;
+ 
+ 	case US_BULK_GET_MAX_LUN:
+@@ -1625,7 +1625,7 @@ static int finish_reply(struct fsg_common *common)
+ 	return rc;
+ }
+ 
+-static int send_status(struct fsg_common *common)
++static void send_status(struct fsg_common *common)
+ {
+ 	struct fsg_lun		*curlun = common->curlun;
+ 	struct fsg_buffhd	*bh;
+@@ -1639,7 +1639,7 @@ static int send_status(struct fsg_common *common)
+ 	while (bh->state != BUF_STATE_EMPTY) {
+ 		rc = sleep_thread(common, true);
+ 		if (rc)
+-			return rc;
++			return;
+ 	}
+ 
+ 	if (curlun) {
+@@ -1674,10 +1674,10 @@ static int send_status(struct fsg_common *common)
+ 	bh->inreq->zero = 0;
+ 	if (!start_in_transfer(common, bh))
+ 		/* Don't know what to do if common->fsg is NULL */
+-		return -EIO;
++		return;
+ 
+ 	common->next_buffhd_to_fill = bh->next;
+-	return 0;
++	return;
+ }
+ 
+ 
+@@ -2362,9 +2362,11 @@ static void handle_exception(struct fsg_common *common)
+ 		if (!sig)
+ 			break;
+ 		if (sig != SIGUSR1) {
++			spin_lock_irq(&common->lock);
+ 			if (common->state < FSG_STATE_EXIT)
+ 				DBG(common, "Main thread exiting on signal\n");
+-			raise_exception(common, FSG_STATE_EXIT);
++			common->state = FSG_STATE_EXIT;
++			spin_unlock_irq(&common->lock);
+ 		}
+ 	}
+ 
+@@ -2413,10 +2415,9 @@ static void handle_exception(struct fsg_common *common)
+ 	common->next_buffhd_to_drain = &common->buffhds[0];
+ 	exception_req_tag = common->exception_req_tag;
+ 	old_state = common->state;
++	common->state = FSG_STATE_NORMAL;
+ 
+-	if (old_state == FSG_STATE_ABORT_BULK_OUT)
+-		common->state = FSG_STATE_STATUS_PHASE;
+-	else {
++	if (old_state != FSG_STATE_ABORT_BULK_OUT) {
+ 		for (i = 0; i < ARRAY_SIZE(common->luns); ++i) {
+ 			curlun = common->luns[i];
+ 			if (!curlun)
+@@ -2427,21 +2428,19 @@ static void handle_exception(struct fsg_common *common)
+ 			curlun->sense_data_info = 0;
+ 			curlun->info_valid = 0;
+ 		}
+-		common->state = FSG_STATE_IDLE;
+ 	}
+ 	spin_unlock_irq(&common->lock);
+ 
+ 	/* Carry out any extra actions required for the exception */
+ 	switch (old_state) {
++	case FSG_STATE_NORMAL:
++		break;
++
+ 	case FSG_STATE_ABORT_BULK_OUT:
+ 		send_status(common);
+-		spin_lock_irq(&common->lock);
+-		if (common->state == FSG_STATE_STATUS_PHASE)
+-			common->state = FSG_STATE_IDLE;
+-		spin_unlock_irq(&common->lock);
+ 		break;
+ 
+-	case FSG_STATE_RESET:
++	case FSG_STATE_PROTOCOL_RESET:
+ 		/*
+ 		 * In case we were forced against our will to halt a
+ 		 * bulk endpoint, clear the halt now.  (The SuperH UDC
+@@ -2474,19 +2473,13 @@ static void handle_exception(struct fsg_common *common)
+ 		break;
+ 
+ 	case FSG_STATE_EXIT:
+-	case FSG_STATE_TERMINATED:
+ 		do_set_interface(common, NULL);		/* Free resources */
+ 		spin_lock_irq(&common->lock);
+ 		common->state = FSG_STATE_TERMINATED;	/* Stop the thread */
+ 		spin_unlock_irq(&common->lock);
+ 		break;
+ 
+-	case FSG_STATE_INTERFACE_CHANGE:
+-	case FSG_STATE_DISCONNECT:
+-	case FSG_STATE_COMMAND_PHASE:
+-	case FSG_STATE_DATA_PHASE:
+-	case FSG_STATE_STATUS_PHASE:
+-	case FSG_STATE_IDLE:
++	case FSG_STATE_TERMINATED:
+ 		break;
+ 	}
+ }
+@@ -2529,29 +2522,13 @@ static int fsg_main_thread(void *common_)
+ 			continue;
+ 		}
+ 
+-		if (get_next_command(common))
++		if (get_next_command(common) || exception_in_progress(common))
+ 			continue;
+-
+-		spin_lock_irq(&common->lock);
+-		if (!exception_in_progress(common))
+-			common->state = FSG_STATE_DATA_PHASE;
+-		spin_unlock_irq(&common->lock);
+-
+-		if (do_scsi_command(common) || finish_reply(common))
++		if (do_scsi_command(common) || exception_in_progress(common))
+ 			continue;
+-
+-		spin_lock_irq(&common->lock);
+-		if (!exception_in_progress(common))
+-			common->state = FSG_STATE_STATUS_PHASE;
+-		spin_unlock_irq(&common->lock);
+-
+-		if (send_status(common))
++		if (finish_reply(common) || exception_in_progress(common))
+ 			continue;
+-
+-		spin_lock_irq(&common->lock);
+-		if (!exception_in_progress(common))
+-			common->state = FSG_STATE_IDLE;
+-		spin_unlock_irq(&common->lock);
++		send_status(common);
+ 	}
+ 
+ 	spin_lock_irq(&common->lock);
+@@ -2972,7 +2949,6 @@ static void fsg_common_release(struct kref *ref)
+ 	if (common->state != FSG_STATE_TERMINATED) {
+ 		raise_exception(common, FSG_STATE_EXIT);
+ 		wait_for_completion(&common->thread_notifier);
+-		common->thread_task = NULL;
+ 	}
+ 
+ 	for (i = 0; i < ARRAY_SIZE(common->luns); ++i) {
+@@ -3021,11 +2997,11 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
+ 	}
+ 
+ 	if (!common->thread_task) {
+-		common->state = FSG_STATE_IDLE;
++		common->state = FSG_STATE_NORMAL;
+ 		common->thread_task =
+ 			kthread_create(fsg_main_thread, common, "file-storage");
+ 		if (IS_ERR(common->thread_task)) {
+-			int ret = PTR_ERR(common->thread_task);
++			ret = PTR_ERR(common->thread_task);
+ 			common->thread_task = NULL;
+ 			common->state = FSG_STATE_TERMINATED;
+ 			return ret;
+diff --git a/drivers/usb/gadget/function/storage_common.h b/drivers/usb/gadget/function/storage_common.h
+index e69848994cb4..e6095dfbf1d5 100644
+--- a/drivers/usb/gadget/function/storage_common.h
++++ b/drivers/usb/gadget/function/storage_common.h
+@@ -157,17 +157,10 @@ struct fsg_buffhd {
+ };
+ 
+ enum fsg_state {
+-	/* This one isn't used anywhere */
+-	FSG_STATE_COMMAND_PHASE = -10,
+-	FSG_STATE_DATA_PHASE,
+-	FSG_STATE_STATUS_PHASE,
+-
+-	FSG_STATE_IDLE = 0,
++	FSG_STATE_NORMAL,
+ 	FSG_STATE_ABORT_BULK_OUT,
+-	FSG_STATE_RESET,
+-	FSG_STATE_INTERFACE_CHANGE,
++	FSG_STATE_PROTOCOL_RESET,
+ 	FSG_STATE_CONFIG_CHANGE,
+-	FSG_STATE_DISCONNECT,
+ 	FSG_STATE_EXIT,
+ 	FSG_STATE_TERMINATED
+ };

commit 1633682053a7ee8058e10c76722b9b28e97fb73f
+Author: Alan Stern 
+Date:   Fri Mar 24 13:38:28 2017 -0400
+
+    USB: fix linked-list corruption in rh_call_control()
+    
+    Using KASAN, Dmitry found a bug in the rh_call_control() routine: If
+    buffer allocation fails, the routine returns immediately without
+    unlinking its URB from the control endpoint, eventually leading to
+    linked-list corruption.
+    
+    This patch fixes the problem by jumping to the end of the routine
+    (where the URB is unlinked) when an allocation failure occurs.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Dmitry Vyukov 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 612fab6e54fb..79bdca5cb9c7 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -520,8 +520,10 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
+ 	 */
+ 	tbuf_size =  max_t(u16, sizeof(struct usb_hub_descriptor), wLength);
+ 	tbuf = kzalloc(tbuf_size, GFP_KERNEL);
+-	if (!tbuf)
+-		return -ENOMEM;
++	if (!tbuf) {
++		status = -ENOMEM;
++		goto err_alloc;
++	}
+ 
+ 	bufp = tbuf;
+ 
+@@ -734,6 +736,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
+ 	}
+ 
+ 	kfree(tbuf);
++ err_alloc:
+ 
+ 	/* any errors get returned through the urb completion */
+ 	spin_lock_irq(&hcd_root_hub_lock);

commit 0a8fd1346254974c3a852338508e4a4cddbb35f1
+Author: Alan Stern 
+Date:   Mon Dec 19 12:03:41 2016 -0500
+
+    USB: fix problems with duplicate endpoint addresses
+    
+    When checking a new device's descriptors, the USB core does not check
+    for duplicate endpoint addresses.  This can cause a problem when the
+    sysfs files for those endpoints are created; trying to create multiple
+    files with the same name will provoke a WARNING:
+    
+    WARNING: CPU: 2 PID: 865 at fs/sysfs/dir.c:31 sysfs_warn_dup+0x8a/0xa0
+    sysfs: cannot create duplicate filename
+    '/devices/platform/dummy_hcd.0/usb2/2-1/2-1:64.0/ep_05'
+    Kernel panic - not syncing: panic_on_warn set ...
+    
+    CPU: 2 PID: 865 Comm: kworker/2:1 Not tainted 4.9.0-rc7+ #34
+    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
+    Workqueue: usb_hub_wq hub_event
+     ffff88006bee64c8 ffffffff81f96b8a ffffffff00000001 1ffff1000d7dcc2c
+     ffffed000d7dcc24 0000000000000001 0000000041b58ab3 ffffffff8598b510
+     ffffffff81f968f8 ffffffff850fee20 ffffffff85cff020 dffffc0000000000
+    Call Trace:
+     [<     inline     >] __dump_stack lib/dump_stack.c:15
+     [] dump_stack+0x292/0x398 lib/dump_stack.c:51
+     [] panic+0x1cb/0x3a9 kernel/panic.c:179
+     [] __warn+0x1c4/0x1e0 kernel/panic.c:542
+     [] warn_slowpath_fmt+0xc5/0x110 kernel/panic.c:565
+     [] sysfs_warn_dup+0x8a/0xa0 fs/sysfs/dir.c:30
+     [] sysfs_create_dir_ns+0x178/0x1d0 fs/sysfs/dir.c:59
+     [<     inline     >] create_dir lib/kobject.c:71
+     [] kobject_add_internal+0x227/0xa60 lib/kobject.c:229
+     [<     inline     >] kobject_add_varg lib/kobject.c:366
+     [] kobject_add+0x139/0x220 lib/kobject.c:411
+     [] device_add+0x353/0x1660 drivers/base/core.c:1088
+     [] device_register+0x1d/0x20 drivers/base/core.c:1206
+     [] usb_create_ep_devs+0x163/0x260 drivers/usb/core/endpoint.c:195
+     [] create_intf_ep_devs+0x13b/0x200 drivers/usb/core/message.c:1030
+     [] usb_set_configuration+0x1083/0x18d0 drivers/usb/core/message.c:1937
+     [] generic_probe+0x6e/0xe0 drivers/usb/core/generic.c:172
+     [] usb_probe_device+0xaa/0xe0 drivers/usb/core/driver.c:263
+    
+    This patch prevents the problem by checking for duplicate endpoint
+    addresses during enumeration and skipping any duplicates.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Andrey Konovalov 
+    Tested-by: Andrey Konovalov 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
+index 0aa9e7d697a5..25dbd8c7aec7 100644
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -239,6 +239,16 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
+ 	if (ifp->desc.bNumEndpoints >= num_ep)
+ 		goto skip_to_next_endpoint_or_interface_descriptor;
+ 
++	/* Check for duplicate endpoint addresses */
++	for (i = 0; i < ifp->desc.bNumEndpoints; ++i) {
++		if (ifp->endpoint[i].desc.bEndpointAddress ==
++		    d->bEndpointAddress) {
++			dev_warn(ddev, "config %d interface %d altsetting %d has a duplicate endpoint with address 0x%X, skipping\n",
++			    cfgno, inum, asnum, d->bEndpointAddress);
++			goto skip_to_next_endpoint_or_interface_descriptor;
++		}
++	}
++
+ 	endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints];
+ 	++ifp->desc.bNumEndpoints;
+ 

commit 890e6c236dcda6d45c5f0bdd23665636376f6831
+Author: Alan Stern 
+Date:   Fri Dec 9 15:25:15 2016 -0500
+
+    USB: gadgetfs: remove unnecessary assignment
+    
+    The dev_config() routine in gadgetfs has a check that
+    dev->dev->bNumConfigurations is equal to 1, and then contains a
+    redundant line of code setting the value to 1.  This patch removes the
+    unnecessary assignment.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
+index 08e5ecc05079..6bde4396927c 100644
+--- a/drivers/usb/gadget/legacy/inode.c
++++ b/drivers/usb/gadget/legacy/inode.c
+@@ -1818,7 +1818,6 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
+ 			|| dev->dev->bDescriptorType != USB_DT_DEVICE
+ 			|| dev->dev->bNumConfigurations != 1)
+ 		goto fail;
+-	dev->dev->bNumConfigurations = 1;
+ 	dev->dev->bcdUSB = cpu_to_le16 (0x0200);
+ 
+ 	/* triggers gadgetfs_bind(); then we can enumerate. */

commit 1c069b057dcf64fada952eaa868d35f02bb0cfc2
+Author: Alan Stern 
+Date:   Fri Dec 9 15:24:24 2016 -0500
+
+    USB: gadgetfs: fix checks of wTotalLength in config descriptors
+    
+    Andrey Konovalov's fuzz testing of gadgetfs showed that we should
+    improve the driver's checks for valid configuration descriptors passed
+    in by the user.  In particular, the driver needs to verify that the
+    wTotalLength value in the descriptor is not too short (smaller
+    than USB_DT_CONFIG_SIZE).  And the check for whether wTotalLength is
+    too large has to be changed, because the driver assumes there is
+    always enough room remaining in the buffer to hold a device descriptor
+    (at least USB_DT_DEVICE_SIZE bytes).
+    
+    This patch adds the additional check and fixes the existing check.  It
+    may do a little more than strictly necessary, but one extra check
+    won't hurt.
+    
+    Signed-off-by: Alan Stern 
+    CC: Andrey Konovalov 
+    CC: 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
+index f1ca33942607..08e5ecc05079 100644
+--- a/drivers/usb/gadget/legacy/inode.c
++++ b/drivers/usb/gadget/legacy/inode.c
+@@ -1734,10 +1734,12 @@ static struct usb_gadget_driver gadgetfs_driver = {
+  * such as configuration notifications.
+  */
+ 
+-static int is_valid_config (struct usb_config_descriptor *config)
++static int is_valid_config(struct usb_config_descriptor *config,
++		unsigned int total)
+ {
+ 	return config->bDescriptorType == USB_DT_CONFIG
+ 		&& config->bLength == USB_DT_CONFIG_SIZE
++		&& total >= USB_DT_CONFIG_SIZE
+ 		&& config->bConfigurationValue != 0
+ 		&& (config->bmAttributes & USB_CONFIG_ATT_ONE) != 0
+ 		&& (config->bmAttributes & USB_CONFIG_ATT_WAKEUP) == 0;
+@@ -1787,7 +1789,8 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
+ 	/* full or low speed config */
+ 	dev->config = (void *) kbuf;
+ 	total = le16_to_cpu(dev->config->wTotalLength);
+-	if (!is_valid_config (dev->config) || total >= length)
++	if (!is_valid_config(dev->config, total) ||
++			total > length - USB_DT_DEVICE_SIZE)
+ 		goto fail;
+ 	kbuf += total;
+ 	length -= total;
+@@ -1796,7 +1799,8 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
+ 	if (kbuf [1] == USB_DT_CONFIG) {
+ 		dev->hs_config = (void *) kbuf;
+ 		total = le16_to_cpu(dev->hs_config->wTotalLength);
+-		if (!is_valid_config (dev->hs_config) || total >= length)
++		if (!is_valid_config(dev->hs_config, total) ||
++				total > length - USB_DT_DEVICE_SIZE)
+ 			goto fail;
+ 		kbuf += total;
+ 		length -= total;

commit add333a81a16abbd4f106266a2553677a165725f
+Author: Alan Stern 
+Date:   Fri Dec 9 15:18:43 2016 -0500
+
+    USB: gadgetfs: fix use-after-free bug
+    
+    Andrey Konovalov reports that fuzz testing with syzkaller causes a
+    KASAN use-after-free bug report in gadgetfs:
+    
+    BUG: KASAN: use-after-free in gadgetfs_setup+0x208a/0x20e0 at addr ffff88003dfe5bf2
+    Read of size 2 by task syz-executor0/22994
+    CPU: 3 PID: 22994 Comm: syz-executor0 Not tainted 4.9.0-rc7+ #16
+    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
+     ffff88006df06a18 ffffffff81f96aba ffffffffe0528500 1ffff1000dbe0cd6
+     ffffed000dbe0cce ffff88006df068f0 0000000041b58ab3 ffffffff8598b4c8
+     ffffffff81f96828 1ffff1000dbe0ccd ffff88006df06708 ffff88006df06748
+    Call Trace:
+      [  201.343209]  [<     inline     >] __dump_stack lib/dump_stack.c:15
+      [  201.343209]  [] dump_stack+0x292/0x398 lib/dump_stack.c:51
+     [] kasan_object_err+0x1c/0x70 mm/kasan/report.c:159
+     [<     inline     >] print_address_description mm/kasan/report.c:197
+     [] kasan_report_error+0x1f0/0x4e0 mm/kasan/report.c:286
+     [<     inline     >] kasan_report mm/kasan/report.c:306
+     [] __asan_report_load_n_noabort+0x3a/0x40 mm/kasan/report.c:337
+     [<     inline     >] config_buf drivers/usb/gadget/legacy/inode.c:1298
+     [] gadgetfs_setup+0x208a/0x20e0 drivers/usb/gadget/legacy/inode.c:1368
+     [] dummy_timer+0x11f0/0x36d0 drivers/usb/gadget/udc/dummy_hcd.c:1858
+     [] call_timer_fn+0x241/0x800 kernel/time/timer.c:1308
+     [<     inline     >] expire_timers kernel/time/timer.c:1348
+     [] __run_timers+0xa06/0xec0 kernel/time/timer.c:1641
+     [] run_timer_softirq+0x21/0x80 kernel/time/timer.c:1654
+     [] __do_softirq+0x2fb/0xb63 kernel/softirq.c:284
+    
+    The cause of the bug is subtle.  The dev_config() routine gets called
+    twice by the fuzzer.  The first time, the user data contains both a
+    full-speed configuration descriptor and a high-speed config
+    descriptor, causing dev->hs_config to be set.  But it also contains an
+    invalid device descriptor, so the buffer containing the descriptors is
+    deallocated and dev_config() returns an error.
+    
+    The second time dev_config() is called, the user data contains only a
+    full-speed config descriptor.  But dev->hs_config still has the stale
+    pointer remaining from the first call, causing the routine to think
+    that there is a valid high-speed config.  Later on, when the driver
+    dereferences the stale pointer to copy that descriptor, we get a
+    use-after-free access.
+    
+    The fix is simple: Clear dev->hs_config if the passed-in data does not
+    contain a high-speed config descriptor.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Andrey Konovalov 
+    Tested-by: Andrey Konovalov 
+    CC: 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
+index 01ed3bc0c3c8..f1ca33942607 100644
+--- a/drivers/usb/gadget/legacy/inode.c
++++ b/drivers/usb/gadget/legacy/inode.c
+@@ -1800,6 +1800,8 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
+ 			goto fail;
+ 		kbuf += total;
+ 		length -= total;
++	} else {
++		dev->hs_config = NULL;
+ 	}
+ 
+ 	/* could support multiple configs, using another encoding! */

commit faab50984fe6636e616c7cc3d30308ba391d36fd
+Author: Alan Stern 
+Date:   Fri Dec 9 15:17:46 2016 -0500
+
+    USB: gadgetfs: fix unbounded memory allocation bug
+    
+    Andrey Konovalov reports that fuzz testing with syzkaller causes a
+    KASAN warning in gadgetfs:
+    
+    BUG: KASAN: slab-out-of-bounds in dev_config+0x86f/0x1190 at addr ffff88003c47e160
+    Write of size 65537 by task syz-executor0/6356
+    CPU: 3 PID: 6356 Comm: syz-executor0 Not tainted 4.9.0-rc7+ #19
+    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
+     ffff88003c107ad8 ffffffff81f96aba ffffffff3dc11ef0 1ffff10007820eee
+     ffffed0007820ee6 ffff88003dc11f00 0000000041b58ab3 ffffffff8598b4c8
+     ffffffff81f96828 ffffffff813fb4a0 ffff88003b6eadc0 ffff88003c107738
+    Call Trace:
+     [<     inline     >] __dump_stack lib/dump_stack.c:15
+     [] dump_stack+0x292/0x398 lib/dump_stack.c:51
+     [] kasan_object_err+0x1c/0x70 mm/kasan/report.c:159
+     [<     inline     >] print_address_description mm/kasan/report.c:197
+     [] kasan_report_error+0x1f0/0x4e0 mm/kasan/report.c:286
+     [] kasan_report+0x35/0x40 mm/kasan/report.c:306
+     [<     inline     >] check_memory_region_inline mm/kasan/kasan.c:308
+     [] check_memory_region+0x139/0x190 mm/kasan/kasan.c:315
+     [] kasan_check_write+0x14/0x20 mm/kasan/kasan.c:326
+     [<     inline     >] copy_from_user arch/x86/include/asm/uaccess.h:689
+     [<     inline     >] ep0_write drivers/usb/gadget/legacy/inode.c:1135
+     [] dev_config+0x86f/0x1190 drivers/usb/gadget/legacy/inode.c:1759
+     [] __vfs_write+0x5d5/0x760 fs/read_write.c:510
+     [] vfs_write+0x170/0x4e0 fs/read_write.c:560
+     [<     inline     >] SYSC_write fs/read_write.c:607
+     [] SyS_write+0xfb/0x230 fs/read_write.c:599
+     [] entry_SYSCALL_64_fastpath+0x1f/0xc2
+    
+    Indeed, there is a comment saying that the value of len is restricted
+    to a 16-bit integer, but the code doesn't actually do this.
+    
+    This patch fixes the warning.  It replaces the comment with a
+    computation that forces the amount of data copied from the user in
+    ep0_write() to be no larger than the wLength size for the control
+    transfer, which is a 16-bit quantity.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Andrey Konovalov 
+    Tested-by: Andrey Konovalov 
+    CC: 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
+index 48f1409b438a..01ed3bc0c3c8 100644
+--- a/drivers/usb/gadget/legacy/inode.c
++++ b/drivers/usb/gadget/legacy/inode.c
+@@ -1126,7 +1126,7 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
+ 	/* data and/or status stage for control request */
+ 	} else if (dev->state == STATE_DEV_SETUP) {
+ 
+-		/* IN DATA+STATUS caller makes len <= wLength */
++		len = min_t(size_t, len, dev->setup_wLength);
+ 		if (dev->setup_in) {
+ 			retval = setup_req (dev->gadget->ep0, dev->req, len);
+ 			if (retval == 0) {

commit bcdbeb844773333d2d1c08004f3b3e25921040e5
+Author: Alan Stern 
+Date:   Wed Dec 14 14:55:56 2016 -0500
+
+    USB: dummy-hcd: fix bug in stop_activity (handle ep0)
+    
+    The stop_activity() routine in dummy-hcd is supposed to unlink all
+    active requests for every endpoint, among other things.  But it
+    doesn't handle ep0.  As a result, fuzz testing can generate a WARNING
+    like the following:
+    
+    WARNING: CPU: 0 PID: 4410 at drivers/usb/gadget/udc/dummy_hcd.c:672 dummy_free_request+0x153/0x170
+    Modules linked in:
+    CPU: 0 PID: 4410 Comm: syz-executor Not tainted 4.9.0-rc7+ #32
+    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
+     ffff88006a64ed10 ffffffff81f96b8a ffffffff41b58ab3 1ffff1000d4c9d35
+     ffffed000d4c9d2d ffff880065f8ac00 0000000041b58ab3 ffffffff8598b510
+     ffffffff81f968f8 0000000041b58ab3 ffffffff859410e0 ffffffff813f0590
+    Call Trace:
+     [<     inline     >] __dump_stack lib/dump_stack.c:15
+     [] dump_stack+0x292/0x398 lib/dump_stack.c:51
+     [] __warn+0x19f/0x1e0 kernel/panic.c:550
+     [] warn_slowpath_null+0x2c/0x40 kernel/panic.c:585
+     [] dummy_free_request+0x153/0x170 drivers/usb/gadget/udc/dummy_hcd.c:672
+     [] usb_ep_free_request+0xc0/0x420 drivers/usb/gadget/udc/core.c:195
+     [] gadgetfs_unbind+0x131/0x190 drivers/usb/gadget/legacy/inode.c:1612
+     [] usb_gadget_remove_driver+0x10f/0x2b0 drivers/usb/gadget/udc/core.c:1228
+     [] usb_gadget_unregister_driver+0x154/0x240 drivers/usb/gadget/udc/core.c:1357
+    
+    This patch fixes the problem by iterating over all the endpoints in
+    the driver's ep array instead of iterating over the gadget's ep_list,
+    which explicitly leaves out ep0.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Andrey Konovalov 
+    CC: 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
+index 02b14e91ae6c..c60abe3a68f9 100644
+--- a/drivers/usb/gadget/udc/dummy_hcd.c
++++ b/drivers/usb/gadget/udc/dummy_hcd.c
+@@ -330,7 +330,7 @@ static void nuke(struct dummy *dum, struct dummy_ep *ep)
+ /* caller must hold lock */
+ static void stop_activity(struct dummy *dum)
+ {
+-	struct dummy_ep	*ep;
++	int i;
+ 
+ 	/* prevent any more requests */
+ 	dum->address = 0;
+@@ -338,8 +338,8 @@ static void stop_activity(struct dummy *dum)
+ 	/* The timer is left running so that outstanding URBs can fail */
+ 
+ 	/* nuke any pending requests first, so driver i/o is quiesced */
+-	list_for_each_entry(ep, &dum->gadget.ep_list, ep.ep_list)
+-		nuke(dum, ep);
++	for (i = 0; i < DUMMY_ENDPOINTS; ++i)
++		nuke(dum, &dum->ep[i]);
+ 
+ 	/* driver now does any non-usb quiescing necessary */
+ }

commit ccdb6be9ec6580ef69f68949ebe26e0fb58a6fb0
+Author: Alan Stern 
+Date:   Fri Oct 21 16:49:07 2016 -0400
+
+    USB: UHCI: report non-PME wakeup signalling for Intel hardware
+    
+    The UHCI controllers in Intel chipsets rely on a platform-specific non-PME
+    mechanism for wakeup signalling.  They can generate wakeup signals even
+    though they don't support PME.
+    
+    We need to let the USB core know this so that it will enable runtime
+    suspend for UHCI controllers.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Bjorn Helgaas 
+    Acked-by: Greg Kroah-Hartman 
+    CC: stable@vger.kernel.org
+
+diff --git a/drivers/usb/host/uhci-pci.c b/drivers/usb/host/uhci-pci.c
+index 940304c33224..02260cfdedb1 100644
+--- a/drivers/usb/host/uhci-pci.c
++++ b/drivers/usb/host/uhci-pci.c
+@@ -129,6 +129,10 @@ static int uhci_pci_init(struct usb_hcd *hcd)
+ 	if (to_pci_dev(uhci_dev(uhci))->vendor == PCI_VENDOR_ID_HP)
+ 		uhci->wait_for_hp = 1;
+ 
++	/* Intel controllers use non-PME wakeup signalling */
++	if (to_pci_dev(uhci_dev(uhci))->vendor == PCI_VENDOR_ID_INTEL)
++		device_set_run_wake(uhci_dev(uhci), 1);
++
+ 	/* Set up pointers to PCI-specific functions */
+ 	uhci->reset_hc = uhci_pci_reset_hc;
+ 	uhci->check_and_reset_hc = uhci_pci_check_and_reset_hc;

commit 6496ebd7edf446fccf8266a1a70ffcb64252593e
+Author: Alan Stern 
+Date:   Fri Oct 21 16:45:38 2016 -0400
+
+    PCI: Check for PME in targeted sleep state
+    
+    One some systems, the firmware does not allow certain PCI devices to be put
+    in deep D-states.  This can cause problems for wakeup signalling, if the
+    device does not support PME# in the deepest allowed suspend state.  For
+    example, Pierre reports that on his system, ACPI does not permit his xHCI
+    host controller to go into D3 during runtime suspend -- but D3 is the only
+    state in which the controller can generate PME# signals.  As a result, the
+    controller goes into runtime suspend but never wakes up, so it doesn't work
+    properly.  USB devices plugged into the controller are never detected.
+    
+    If the device relies on PME# for wakeup signals but is not capable of
+    generating PME# in the target state, the PCI core should accurately report
+    that it cannot do wakeup from runtime suspend.  This patch modifies the
+    pci_dev_run_wake() routine to add this check.
+    
+    Reported-by: Pierre de Villemereuil 
+    Tested-by: Pierre de Villemereuil 
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Bjorn Helgaas 
+    Acked-by: Rafael J. Wysocki 
+    CC: stable@vger.kernel.org
+    CC: Lukas Wunner 
+
+diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
+index ba34907538f6..eda6a7cf0e54 100644
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -2106,6 +2106,10 @@ bool pci_dev_run_wake(struct pci_dev *dev)
+ 	if (!dev->pme_support)
+ 		return false;
+ 
++	/* PME-capable in principle, but not from the intended sleep state */
++	if (!pci_pme_capable(dev, pci_target_state(dev)))
++		return false;
++
+ 	while (bus->parent) {
+ 		struct pci_dev *bridge = bus->self;
+ 

commit 796aa46adf1d90eab36ae06a42e6d3f10b28a75c
+Author: Alan Stern 
+Date:   Mon Sep 26 15:45:41 2016 -0700
+
+    memstick: rtsx_usb_ms: Runtime resume the device when polling for cards
+    
+    Accesses to the rtsx usb device, which is the parent of the rtsx memstick
+    device, must not be done unless it's runtime resumed.
+    
+    Therefore when the rtsx_usb_ms driver polls for inserted memstick cards,
+    let's add pm_runtime_get|put*() to make sure accesses is done when the
+    rtsx usb device is runtime resumed.
+    
+    Reported-by: Ritesh Raj Sarraf 
+    Tested-by: Ritesh Raj Sarraf 
+    Signed-off-by: Alan Stern 
+    Cc: 
+    Signed-off-by: Ulf Hansson 
+
+diff --git a/drivers/memstick/host/rtsx_usb_ms.c b/drivers/memstick/host/rtsx_usb_ms.c
+index d34bc3530385..1b994897f0ff 100644
+--- a/drivers/memstick/host/rtsx_usb_ms.c
++++ b/drivers/memstick/host/rtsx_usb_ms.c
+@@ -681,6 +681,7 @@ static int rtsx_usb_detect_ms_card(void *__host)
+ 	int err;
+ 
+ 	for (;;) {
++		pm_runtime_get_sync(ms_dev(host));
+ 		mutex_lock(&ucr->dev_mutex);
+ 
+ 		/* Check pending MS card changes */
+@@ -703,6 +704,7 @@ static int rtsx_usb_detect_ms_card(void *__host)
+ 		}
+ 
+ poll_again:
++		pm_runtime_put(ms_dev(host));
+ 		if (host->eject)
+ 			break;
+ 

commit 08c5cd37480f59ea39682f4585d92269be6b1424
+Author: Alan Stern 
+Date:   Fri Sep 16 10:24:26 2016 -0400
+
+    USB: change bInterval default to 10 ms
+    
+    Some full-speed mceusb infrared transceivers contain invalid endpoint
+    descriptors for their interrupt endpoints, with bInterval set to 0.
+    In the past they have worked out okay with the mceusb driver, because
+    the driver sets the bInterval field in the descriptor to 1,
+    overwriting whatever value may have been there before.  However, this
+    approach was never sanctioned by the USB core, and in fact it does not
+    work with xHCI controllers, because they use the bInterval value that
+    was present when the configuration was installed.
+    
+    Currently usbcore uses 32 ms as the default interval if the value in
+    the endpoint descriptor is invalid.  It turns out that these IR
+    transceivers don't work properly unless the interval is set to 10 ms
+    or below.  To work around this mceusb problem, this patch changes the
+    endpoint-descriptor parsing routine, making the default interval value
+    be 10 ms rather than 32 ms.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Wade Berrier 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
+index 15ce4ab11688..a2d90aca779f 100644
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -240,8 +240,10 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
+ 	memcpy(&endpoint->desc, d, n);
+ 	INIT_LIST_HEAD(&endpoint->urb_list);
+ 
+-	/* Fix up bInterval values outside the legal range. Use 32 ms if no
+-	 * proper value can be guessed. */
++	/*
++	 * Fix up bInterval values outside the legal range.
++	 * Use 10 or 8 ms if no proper value can be guessed.
++	 */
+ 	i = 0;		/* i = min, j = max, n = default */
+ 	j = 255;
+ 	if (usb_endpoint_xfer_int(d)) {
+@@ -250,13 +252,15 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
+ 		case USB_SPEED_SUPER_PLUS:
+ 		case USB_SPEED_SUPER:
+ 		case USB_SPEED_HIGH:
+-			/* Many device manufacturers are using full-speed
++			/*
++			 * Many device manufacturers are using full-speed
+ 			 * bInterval values in high-speed interrupt endpoint
+-			 * descriptors. Try to fix those and fall back to a
+-			 * 32 ms default value otherwise. */
++			 * descriptors. Try to fix those and fall back to an
++			 * 8-ms default value otherwise.
++			 */
+ 			n = fls(d->bInterval*8);
+ 			if (n == 0)
+-				n = 9;	/* 32 ms = 2^(9-1) uframes */
++				n = 7;	/* 8 ms = 2^(7-1) uframes */
+ 			j = 16;
+ 
+ 			/*
+@@ -271,10 +275,12 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
+ 			}
+ 			break;
+ 		default:		/* USB_SPEED_FULL or _LOW */
+-			/* For low-speed, 10 ms is the official minimum.
++			/*
++			 * For low-speed, 10 ms is the official minimum.
+ 			 * But some "overclocked" devices might want faster
+-			 * polling so we'll allow it. */
+-			n = 32;
++			 * polling so we'll allow it.
++			 */
++			n = 10;
+ 			break;
+ 		}
+ 	} else if (usb_endpoint_xfer_isoc(d)) {
+@@ -282,10 +288,10 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
+ 		j = 16;
+ 		switch (to_usb_device(ddev)->speed) {
+ 		case USB_SPEED_HIGH:
+-			n = 9;		/* 32 ms = 2^(9-1) uframes */
++			n = 7;		/* 8 ms = 2^(7-1) uframes */
+ 			break;
+ 		default:		/* USB_SPEED_FULL */
+-			n = 6;		/* 32 ms = 2^(6-1) frames */
++			n = 4;		/* 8 ms = 2^(4-1) frames */
+ 			break;
+ 		}
+ 	}

commit fc8b690d5da86a4b309b74fb706cc1eb75d003e6
+Author: Alan Stern 
+Date:   Thu Aug 25 11:30:49 2016 -0400
+
+    usb-storage: MAINTAINERS: Alan Stern is the new maintainer
+    
+    At Matt Dharm's request, I am taking over maintainership of the
+    usb-storage driver.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Matthew Dharm 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 0bbe4b105c34..deff5cb58002 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -12163,7 +12163,7 @@ S:	Maintained
+ F:	drivers/net/usb/lan78xx.*
+ 
+ USB MASS STORAGE DRIVER
+-M:	Matthew Dharm 
++M:	Alan Stern 
+ L:	linux-usb@vger.kernel.org
+ L:	usb-storage@lists.one-eyed-alien.net
+ S:	Maintained

commit 53e5f36fbd2453ad69a3369a1db62dc06c30a4aa
+Author: Alan Stern 
+Date:   Tue Aug 23 15:32:51 2016 -0400
+
+    USB: avoid left shift by -1
+    
+    UBSAN complains about a left shift by -1 in proc_do_submiturb().  This
+    can occur when an URB is submitted for a bulk or control endpoint on
+    a high-speed device, since the code doesn't bother to check the
+    endpoint type; normally only interrupt or isochronous endpoints have
+    a nonzero bInterval value.
+    
+    Aside from the fact that the operation is illegal, it shouldn't matter
+    because the result isn't used.  Still, in theory it could cause a
+    hardware exception or other problem, so we should work around it.
+    This patch avoids doing the left shift unless the shift amount is >= 0.
+    
+    The same piece of code has another problem.  When checking the device
+    speed (the exponential encoding for interrupt endpoints is used only
+    by high-speed or faster devices), we need to look for speed >=
+    USB_SPEED_SUPER as well as speed == USB_SPEED HIGH.  The patch adds
+    this check.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Vittorio Zecca 
+    Tested-by: Vittorio Zecca 
+    Suggested-by: Bjørn Mork 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index e6a6d67c8705..09c8d9ca61ae 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -1709,11 +1709,17 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
+ 	as->urb->start_frame = uurb->start_frame;
+ 	as->urb->number_of_packets = number_of_packets;
+ 	as->urb->stream_id = stream_id;
+-	if (uurb->type == USBDEVFS_URB_TYPE_ISO ||
+-			ps->dev->speed == USB_SPEED_HIGH)
+-		as->urb->interval = 1 << min(15, ep->desc.bInterval - 1);
+-	else
+-		as->urb->interval = ep->desc.bInterval;
++
++	if (ep->desc.bInterval) {
++		if (uurb->type == USBDEVFS_URB_TYPE_ISO ||
++				ps->dev->speed == USB_SPEED_HIGH ||
++				ps->dev->speed >= USB_SPEED_SUPER)
++			as->urb->interval = 1 <<
++					min(15, ep->desc.bInterval - 1);
++		else
++			as->urb->interval = ep->desc.bInterval;
++	}
++
+ 	as->urb->context = as;
+ 	as->urb->complete = async_completed;
+ 	for (totlen = u = 0; u < number_of_packets; u++) {

commit 6c73358c83ce870c0cf32413e5cadb3b9a39c606
+Author: Alan Stern 
+Date:   Mon Aug 22 16:58:53 2016 -0400
+
+    USB: fix typo in wMaxPacketSize validation
+    
+    The maximum value allowed for wMaxPacketSize of a high-speed interrupt
+    endpoint is 1024 bytes, not 1023.
+    
+    Signed-off-by: Alan Stern 
+    Fixes: aed9d65ac327 ("USB: validate wMaxPacketValue entries in endpoint descriptors")
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
+index 051163189810..15ce4ab11688 100644
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -187,7 +187,7 @@ static const unsigned short high_speed_maxpacket_maxes[4] = {
+ 	[USB_ENDPOINT_XFER_CONTROL] = 64,
+ 	[USB_ENDPOINT_XFER_ISOC] = 1024,
+ 	[USB_ENDPOINT_XFER_BULK] = 512,
+-	[USB_ENDPOINT_XFER_INT] = 1023,
++	[USB_ENDPOINT_XFER_INT] = 1024,
+ };
+ static const unsigned short super_speed_maxpacket_maxes[4] = {
+ 	[USB_ENDPOINT_XFER_CONTROL] = 512,

commit 5cce438298a0d2a7a857a4a3c3e26aeb8f77b941
+Author: Alan Stern 
+Date:   Fri Jun 10 14:42:55 2016 -0400
+
+    USB: remove race condition in usbfs/libusb when using reap-after-disconnect
+    
+    Hans de Goede has reported a difficulty in the Linux port of libusb.
+    When a device is removed, the poll() system call in usbfs starts
+    returning POLLERR as soon as udev->state is set to
+    USB_STATE_NOTATTACHED, but the outstanding URBs are not available for
+    reaping until some time later (after usbdev_remove() has been called).
+    This is awkward for libusb or other usbfs clients, although not an
+    insuperable problem.
+    
+    At any rate, it's easy to change usbfs so that it returns POLLHUP as
+    soon as the state becomes USB_STATE_NOTATTACHED but it doesn't return
+    POLLERR until after the outstanding URBs have completed.  That's what
+    this patch does; it uses the fact that ps->list is always on the
+    dev->filelist list until usbdev_remove() takes it off, which happens
+    after all the outstanding URBs have been cancelled.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Hans de Goede 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 472cbcdf7456..e6a6d67c8705 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -2583,7 +2583,9 @@ static unsigned int usbdev_poll(struct file *file,
+ 	if (file->f_mode & FMODE_WRITE && !list_empty(&ps->async_completed))
+ 		mask |= POLLOUT | POLLWRNORM;
+ 	if (!connected(ps))
+-		mask |= POLLERR | POLLHUP;
++		mask |= POLLHUP;
++	if (list_empty(&ps->list))
++		mask |= POLLERR;
+ 	return mask;
+ }
+ 

commit aed9d65ac3278d4febd8665bd7db59ef53e825fe
+Author: Alan Stern 
+Date:   Mon Aug 1 15:25:56 2016 -0400
+
+    USB: validate wMaxPacketValue entries in endpoint descriptors
+    
+    Erroneous or malicious endpoint descriptors may have non-zero bits in
+    reserved positions, or out-of-bounds values.  This patch helps prevent
+    these from causing problems by bounds-checking the wMaxPacketValue
+    entries in endpoint descriptors and capping the values at the maximum
+    allowed.
+    
+    This issue was first discovered and tests were conducted by Jake Lamberson
+    , an intern working for Rosie Hall.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: roswest 
+    Tested-by: roswest 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
+index 31ccdccd7a04..051163189810 100644
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -171,6 +171,31 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
+ 							ep, buffer, size);
+ }
+ 
++static const unsigned short low_speed_maxpacket_maxes[4] = {
++	[USB_ENDPOINT_XFER_CONTROL] = 8,
++	[USB_ENDPOINT_XFER_ISOC] = 0,
++	[USB_ENDPOINT_XFER_BULK] = 0,
++	[USB_ENDPOINT_XFER_INT] = 8,
++};
++static const unsigned short full_speed_maxpacket_maxes[4] = {
++	[USB_ENDPOINT_XFER_CONTROL] = 64,
++	[USB_ENDPOINT_XFER_ISOC] = 1023,
++	[USB_ENDPOINT_XFER_BULK] = 64,
++	[USB_ENDPOINT_XFER_INT] = 64,
++};
++static const unsigned short high_speed_maxpacket_maxes[4] = {
++	[USB_ENDPOINT_XFER_CONTROL] = 64,
++	[USB_ENDPOINT_XFER_ISOC] = 1024,
++	[USB_ENDPOINT_XFER_BULK] = 512,
++	[USB_ENDPOINT_XFER_INT] = 1023,
++};
++static const unsigned short super_speed_maxpacket_maxes[4] = {
++	[USB_ENDPOINT_XFER_CONTROL] = 512,
++	[USB_ENDPOINT_XFER_ISOC] = 1024,
++	[USB_ENDPOINT_XFER_BULK] = 1024,
++	[USB_ENDPOINT_XFER_INT] = 1024,
++};
++
+ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
+     int asnum, struct usb_host_interface *ifp, int num_ep,
+     unsigned char *buffer, int size)
+@@ -179,6 +204,8 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
+ 	struct usb_endpoint_descriptor *d;
+ 	struct usb_host_endpoint *endpoint;
+ 	int n, i, j, retval;
++	unsigned int maxp;
++	const unsigned short *maxpacket_maxes;
+ 
+ 	d = (struct usb_endpoint_descriptor *) buffer;
+ 	buffer += d->bLength;
+@@ -286,6 +313,42 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
+ 			endpoint->desc.wMaxPacketSize = cpu_to_le16(8);
+ 	}
+ 
++	/* Validate the wMaxPacketSize field */
++	maxp = usb_endpoint_maxp(&endpoint->desc);
++
++	/* Find the highest legal maxpacket size for this endpoint */
++	i = 0;		/* additional transactions per microframe */
++	switch (to_usb_device(ddev)->speed) {
++	case USB_SPEED_LOW:
++		maxpacket_maxes = low_speed_maxpacket_maxes;
++		break;
++	case USB_SPEED_FULL:
++		maxpacket_maxes = full_speed_maxpacket_maxes;
++		break;
++	case USB_SPEED_HIGH:
++		/* Bits 12..11 are allowed only for HS periodic endpoints */
++		if (usb_endpoint_xfer_int(d) || usb_endpoint_xfer_isoc(d)) {
++			i = maxp & (BIT(12) | BIT(11));
++			maxp &= ~i;
++		}
++		/* fallthrough */
++	default:
++		maxpacket_maxes = high_speed_maxpacket_maxes;
++		break;
++	case USB_SPEED_SUPER:
++	case USB_SPEED_SUPER_PLUS:
++		maxpacket_maxes = super_speed_maxpacket_maxes;
++		break;
++	}
++	j = maxpacket_maxes[usb_endpoint_type(&endpoint->desc)];
++
++	if (maxp > j) {
++		dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has invalid maxpacket %d, setting to %d\n",
++		    cfgno, inum, asnum, d->bEndpointAddress, maxp, j);
++		maxp = j;
++		endpoint->desc.wMaxPacketSize = cpu_to_le16(i | maxp);
++	}
++
+ 	/*
+ 	 * Some buggy high speed devices have bulk endpoints using
+ 	 * maxpacket sizes other than 512.  High speed HCDs may not
+@@ -293,9 +356,6 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
+ 	 */
+ 	if (to_usb_device(ddev)->speed == USB_SPEED_HIGH
+ 			&& usb_endpoint_xfer_bulk(d)) {
+-		unsigned maxp;
+-
+-		maxp = usb_endpoint_maxp(&endpoint->desc) & 0x07ff;
+ 		if (maxp != 512)
+ 			dev_warn(ddev, "config %d interface %d altsetting %d "
+ 				"bulk endpoint 0x%X has invalid maxpacket %d\n",

commit 07d316a22e119fa301fd7dba7f1e1adfd4f72c05
+Author: Alan Stern 
+Date:   Fri Aug 5 11:51:30 2016 -0400
+
+    USB: hub: change the locking in hub_activate
+    
+    The locking in hub_activate() is not adequate to provide full mutual
+    exclusion with hub_quiesce().  The subroutine locks the hub's
+    usb_interface, but the callers of hub_quiesce() (such as
+    hub_pre_reset() and hub_event()) hold the lock to the hub's
+    usb_device.
+    
+    This patch changes hub_activate() to make it acquire the same lock as
+    those other routines.
+    
+    Signed-off-by: Alan Stern 
+    CC:  #4.4+
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index bb69d262b6f9..1d5fc32d06d0 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1052,7 +1052,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ 
+ 	/* Continue a partial initialization */
+ 	if (type == HUB_INIT2 || type == HUB_INIT3) {
+-		device_lock(hub->intfdev);
++		device_lock(&hdev->dev);
+ 
+ 		/* Was the hub disconnected while we were waiting? */
+ 		if (hub->disconnected)
+@@ -1259,7 +1259,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ 			queue_delayed_work(system_power_efficient_wq,
+ 					&hub->init_work,
+ 					msecs_to_jiffies(delay));
+-			device_unlock(hub->intfdev);
++			device_unlock(&hdev->dev);
+ 			return;		/* Continues at init3: below */
+ 		} else {
+ 			msleep(delay);
+@@ -1282,7 +1282,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ 		/* Allow autosuspend if it was suppressed */
+  disconnected:
+ 		usb_autopm_put_interface_async(to_usb_interface(hub->intfdev));
+-		device_unlock(hub->intfdev);
++		device_unlock(&hdev->dev);
+ 	}
+ 
+ 	kref_put(&hub->kref, hub_release);

commit ca5cbc8b02f9b21cc8cd1ab36668763ec34f9ee8
+Author: Alan Stern 
+Date:   Fri Aug 5 11:49:45 2016 -0400
+
+    USB: hub: fix up early-exit pathway in hub_activate
+    
+    The early-exit pathway in hub_activate, added by commit e50293ef9775
+    ("USB: fix invalid memory access in hub_activate()") needs
+    improvement.  It duplicates code that is already present at the end of
+    the subroutine, and it neglects to undo the effect of a
+    usb_autopm_get_interface_no_resume() call.
+    
+    This patch fixes both problems by making the early-exit pathway jump
+    directly to the end of the subroutine.  It simplifies the code at the
+    end by merging two conditionals that actually test the same condition
+    although they appear different: If type < HUB_INIT3 then type must be
+    either HUB_INIT2 or HUB_INIT, and it can't be HUB_INIT because in that
+    case the subroutine would have exited earlier.
+    
+    Signed-off-by: Alan Stern 
+    CC:  #4.4+
+    Reviewed-by: Viresh Kumar 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 3ccffac0f647..bb69d262b6f9 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1055,11 +1055,8 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ 		device_lock(hub->intfdev);
+ 
+ 		/* Was the hub disconnected while we were waiting? */
+-		if (hub->disconnected) {
+-			device_unlock(hub->intfdev);
+-			kref_put(&hub->kref, hub_release);
+-			return;
+-		}
++		if (hub->disconnected)
++			goto disconnected;
+ 		if (type == HUB_INIT2)
+ 			goto init2;
+ 		goto init3;
+@@ -1281,12 +1278,12 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ 	/* Scan all ports that need attention */
+ 	kick_hub_wq(hub);
+ 
+-	/* Allow autosuspend if it was suppressed */
+-	if (type <= HUB_INIT3)
++	if (type == HUB_INIT2 || type == HUB_INIT3) {
++		/* Allow autosuspend if it was suppressed */
++ disconnected:
+ 		usb_autopm_put_interface_async(to_usb_interface(hub->intfdev));
+-
+-	if (type == HUB_INIT2 || type == HUB_INIT3)
+ 		device_unlock(hub->intfdev);
++	}
+ 
+ 	kref_put(&hub->kref, hub_release);
+ }

commit 5e7ff2ca7f2da55fe777167849d0c93403bd0dc8
+Author: Alan Stern 
+Date:   Thu Jun 23 15:05:26 2016 -0400
+
+    SCSI: fix new bug in scsi_dev_info_list string matching
+    
+    Commit b704f70ce200 ("SCSI: fix bug in scsi_dev_info_list matching")
+    changed the way vendor- and model-string matching was carried out in the
+    routine that looks up entries in a SCSI devinfo list.  The new matching
+    code failed to take into account the case of a maximum-length string; in
+    such cases it could end up testing for a terminating '\0' byte beyond
+    the end of the memory allocated to the string.  This out-of-bounds bug
+    was detected by UBSAN.
+    
+    I don't know if anybody has actually encountered this bug.  The symptom
+    would be that a device entry in the blacklist might not be matched
+    properly if it contained an 8-character vendor name or a 16-character
+    model name.  Such entries certainly exist in scsi_static_device_list.
+    
+    This patch fixes the problem by adding a check for a maximum-length
+    string before the '\0' test.
+    
+    Signed-off-by: Alan Stern 
+    Fixes: b704f70ce200 ("SCSI: fix bug in scsi_dev_info_list matching")
+    Tested-by: Wilfried Klaebe 
+    CC:  # v4.4+
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
+index ff41c310c900..eaccd651ccda 100644
+--- a/drivers/scsi/scsi_devinfo.c
++++ b/drivers/scsi/scsi_devinfo.c
+@@ -429,7 +429,7 @@ static struct scsi_dev_info_list *scsi_dev_info_list_find(const char *vendor,
+ 	 * here, and we don't know what device it is
+ 	 * trying to work with, leave it as-is.
+ 	 */
+-	vmax = 8;	/* max length of vendor */
++	vmax = sizeof(devinfo->vendor);
+ 	vskip = vendor;
+ 	while (vmax > 0 && *vskip == ' ') {
+ 		vmax--;
+@@ -439,7 +439,7 @@ static struct scsi_dev_info_list *scsi_dev_info_list_find(const char *vendor,
+ 	while (vmax > 0 && vskip[vmax - 1] == ' ')
+ 		--vmax;
+ 
+-	mmax = 16;	/* max length of model */
++	mmax = sizeof(devinfo->model);
+ 	mskip = model;
+ 	while (mmax > 0 && *mskip == ' ') {
+ 		mmax--;
+@@ -455,10 +455,12 @@ static struct scsi_dev_info_list *scsi_dev_info_list_find(const char *vendor,
+ 			 * Behave like the older version of get_device_flags.
+ 			 */
+ 			if (memcmp(devinfo->vendor, vskip, vmax) ||
+-					devinfo->vendor[vmax])
++					(vmax < sizeof(devinfo->vendor) &&
++						devinfo->vendor[vmax]))
+ 				continue;
+ 			if (memcmp(devinfo->model, mskip, mmax) ||
+-					devinfo->model[mmax])
++					(mmax < sizeof(devinfo->model) &&
++						devinfo->model[mmax]))
+ 				continue;
+ 			return devinfo;
+ 		} else {

commit ab2a4bf83902c170d29ba130a8abb5f9d90559e1
+Author: Alan Stern 
+Date:   Mon Jun 27 10:23:10 2016 -0400
+
+    USB: don't free bandwidth_mutex too early
+    
+    The USB core contains a bug that can show up when a USB-3 host
+    controller is removed.  If the primary (USB-2) hcd structure is
+    released before the shared (USB-3) hcd, the core will try to do a
+    double-free of the common bandwidth_mutex.
+    
+    The problem was described in graphical form by Chung-Geol Kim, who
+    first reported it:
+    
+    =================================================
+         At *remove USB(3.0) Storage
+         sequence <1> --> <5> ((Problem Case))
+    =================================================
+                                      VOLD
+    ------------------------------------|------------
+                                     (uevent)
+                                ________|_________
+                               |<1>               |
+                               |dwc3_otg_sm_work  |
+                               |usb_put_hcd       |
+                               |peer_hcd(kref=2)|
+                               |__________________|
+                                ________|_________
+                               |<2>               |
+                               |New USB BUS #2    |
+                               |                  |
+                               |peer_hcd(kref=1)  |
+                               |                  |
+                             --(Link)-bandXX_mutex|
+                             | |__________________|
+                             |
+        ___________________  |
+       |<3>                | |
+       |dwc3_otg_sm_work   | |
+       |usb_put_hcd        | |
+       |primary_hcd(kref=1)| |
+       |___________________| |
+        _________|_________  |
+       |<4>                | |
+       |New USB BUS #1     | |
+       |hcd_release        | |
+       |primary_hcd(kref=0)| |
+       |                   | |
+       |bandXX_mutex(free) |<-
+       |___________________|
+                                   (( VOLD ))
+                                ______|___________
+                               |<5>               |
+                               |      SCSI        |
+                               |usb_put_hcd       |
+                               |peer_hcd(kref=0)  |
+                               |*hcd_release      |
+                               |bandXX_mutex(free*)|<- double free
+                               |__________________|
+    
+    =================================================
+    
+    This happens because hcd_release() frees the bandwidth_mutex whenever
+    it sees a primary hcd being released (which is not a very good idea
+    in any case), but in the course of releasing the primary hcd, it
+    changes the pointers in the shared hcd in such a way that the shared
+    hcd will appear to be primary when it gets released.
+    
+    This patch fixes the problem by changing hcd_release() so that it
+    deallocates the bandwidth_mutex only when the _last_ hcd structure
+    referencing it is released.  The patch also removes an unnecessary
+    test, so that when an hcd is released, both the shared_hcd and
+    primary_hcd pointers in the hcd's peer will be cleared.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Chung-Geol Kim 
+    Tested-by: Chung-Geol Kim 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 34b837ae1ed7..d2e3f655c26f 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -2598,26 +2598,23 @@ EXPORT_SYMBOL_GPL(usb_create_hcd);
+  * Don't deallocate the bandwidth_mutex until the last shared usb_hcd is
+  * deallocated.
+  *
+- * Make sure to only deallocate the bandwidth_mutex when the primary HCD is
+- * freed.  When hcd_release() is called for either hcd in a peer set
+- * invalidate the peer's ->shared_hcd and ->primary_hcd pointers to
+- * block new peering attempts
++ * Make sure to deallocate the bandwidth_mutex only when the last HCD is
++ * freed.  When hcd_release() is called for either hcd in a peer set,
++ * invalidate the peer's ->shared_hcd and ->primary_hcd pointers.
+  */
+ static void hcd_release(struct kref *kref)
+ {
+ 	struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref);
+ 
+ 	mutex_lock(&usb_port_peer_mutex);
+-	if (usb_hcd_is_primary_hcd(hcd)) {
+-		kfree(hcd->address0_mutex);
+-		kfree(hcd->bandwidth_mutex);
+-	}
+ 	if (hcd->shared_hcd) {
+ 		struct usb_hcd *peer = hcd->shared_hcd;
+ 
+ 		peer->shared_hcd = NULL;
+-		if (peer->primary_hcd == hcd)
+-			peer->primary_hcd = NULL;
++		peer->primary_hcd = NULL;
++	} else {
++		kfree(hcd->address0_mutex);
++		kfree(hcd->bandwidth_mutex);
+ 	}
+ 	mutex_unlock(&usb_port_peer_mutex);
+ 	kfree(hcd);

commit 7e8b3dfef16375dbfeb1f36a83eb9f27117c51fd
+Author: Alan Stern 
+Date:   Thu Jun 23 14:54:37 2016 -0400
+
+    USB: EHCI: declare hostpc register as zero-length array
+    
+    The HOSTPC extension registers found in some EHCI implementations form
+    a variable-length array, with one element for each port.  Therefore
+    the hostpc field in struct ehci_regs should be declared as a
+    zero-length array, not a single-element array.
+    
+    This fixes a problem reported by UBSAN.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Wilfried Klaebe 
+    Tested-by: Wilfried Klaebe 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/include/linux/usb/ehci_def.h b/include/linux/usb/ehci_def.h
+index 966889a20ea3..e479033bd782 100644
+--- a/include/linux/usb/ehci_def.h
++++ b/include/linux/usb/ehci_def.h
+@@ -180,11 +180,11 @@ struct ehci_regs {
+  * PORTSCx
+  */
+ 	/* HOSTPC: offset 0x84 */
+-	u32		hostpc[1];	/* HOSTPC extension */
++	u32		hostpc[0];	/* HOSTPC extension */
+ #define HOSTPC_PHCD	(1<<22)		/* Phy clock disable */
+ #define HOSTPC_PSPD	(3<<25)		/* Port speed detection */
+ 
+-	u32		reserved5[16];
++	u32		reserved5[17];
+ 
+ 	/* USBMODE_EX: offset 0xc8 */
+ 	u32		usbmode_ex;	/* USB Device mode extension */

commit 85e3990bea49a50cb389015fea564b58899ab7c1
+Author: Alan Stern 
+Date:   Thu May 19 16:29:50 2016 -0400
+
+    USB: EHCI: avoid undefined pointer arithmetic and placate UBSAN
+    
+    Several people have reported that UBSAN doesn't like the pointer
+    arithmetic in ehci_hub_control():
+    
+            u32 __iomem     *status_reg = &ehci->regs->port_status[
+                                    (wIndex & 0xff) - 1];
+            u32 __iomem     *hostpc_reg = &ehci->regs->hostpc[(wIndex & 0xff) - 1];
+    
+    If wIndex is 0 (and it often is), these calculations underflow and
+    UBSAN complains.
+    
+    According to the C standard, pointer computations leading to locations
+    outside the bounds of an array object (other than 1 position past the
+    end) are undefined.  In this case, the compiler would be justified in
+    concluding the wIndex can never be 0 and then optimizing away the
+    tests for !wIndex that occur later in the subroutine.  (Although,
+    since ehci->regs->port_status and ehci->regs->hostpc are both 0-length
+    arrays and are thus GCC extensions to the C standard, it's not clear
+    what the compiler is really allowed to do.)
+    
+    At any rate, we can avoid all these difficulties, at the cost of
+    making the code slightly longer, by not decrementing the index when it
+    is equal to 0.  The runtime effect is minimal, and anyway
+    ehci_hub_control() is not on a hot path.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Valdis Kletnieks 
+    Reported-by: Meelis Roos 
+    Reported-by: Martin_MOKREJÅ 
+    Reported-by: "Navin P.S" 
+    CC: Andrey Ryabinin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index ffc90295a95f..74f62d68f013 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -872,14 +872,22 @@ int ehci_hub_control(
+ ) {
+ 	struct ehci_hcd	*ehci = hcd_to_ehci (hcd);
+ 	int		ports = HCS_N_PORTS (ehci->hcs_params);
+-	u32 __iomem	*status_reg = &ehci->regs->port_status[
+-				(wIndex & 0xff) - 1];
+-	u32 __iomem	*hostpc_reg = &ehci->regs->hostpc[(wIndex & 0xff) - 1];
++	u32 __iomem	*status_reg, *hostpc_reg;
+ 	u32		temp, temp1, status;
+ 	unsigned long	flags;
+ 	int		retval = 0;
+ 	unsigned	selector;
+ 
++	/*
++	 * Avoid underflow while calculating (wIndex & 0xff) - 1.
++	 * The compiler might deduce that wIndex can never be 0 and then
++	 * optimize away the tests for !wIndex below.
++	 */
++	temp = wIndex & 0xff;
++	temp -= (temp > 0);
++	status_reg = &ehci->regs->port_status[temp];
++	hostpc_reg = &ehci->regs->hostpc[temp];
++
+ 	/*
+ 	 * FIXME:  support SetPortFeatures USB_PORT_FEAT_INDICATOR.
+ 	 * HCS_INDICATOR may say we can change LEDs to off/amber/green.

commit 6fb650d43da3e7054984dc548eaa88765a94d49f
+Author: Alan Stern 
+Date:   Fri Apr 29 15:25:17 2016 -0400
+
+    USB: leave LPM alone if possible when binding/unbinding interface drivers
+    
+    When a USB driver is bound to an interface (either through probing or
+    by claiming it) or is unbound from an interface, the USB core always
+    disables Link Power Management during the transition and then
+    re-enables it afterward.  The reason is because the driver might want
+    to prevent hub-initiated link power transitions, in which case the HCD
+    would have to recalculate the various LPM parameters.  This
+    recalculation takes place when LPM is re-enabled and the new
+    parameters are sent to the device and its parent hub.
+    
+    However, if the driver does not want to prevent hub-initiated link
+    power transitions then none of this work is necessary.  The parameters
+    don't need to be recalculated, and LPM doesn't need to be disabled and
+    re-enabled.
+    
+    It turns out that disabling and enabling LPM can be time-consuming,
+    enough so that it interferes with user programs that want to claim and
+    release interfaces rapidly via usbfs.  Since the usbfs kernel driver
+    doesn't set the disable_hub_initiated_lpm flag, we can speed things up
+    and get the user programs to work by leaving LPM alone whenever the
+    flag isn't set.
+    
+    And while we're improving the way disable_hub_initiated_lpm gets used,
+    let's also fix its kerneldoc.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Matthew Giassa 
+    CC: Mathias Nyman 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 2057d91d8336..dadd1e8dfe09 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -284,7 +284,7 @@ static int usb_probe_interface(struct device *dev)
+ 	struct usb_device *udev = interface_to_usbdev(intf);
+ 	const struct usb_device_id *id;
+ 	int error = -ENODEV;
+-	int lpm_disable_error;
++	int lpm_disable_error = -ENODEV;
+ 
+ 	dev_dbg(dev, "%s\n", __func__);
+ 
+@@ -336,12 +336,14 @@ static int usb_probe_interface(struct device *dev)
+ 	 * setting during probe, that should also be fine.  usb_set_interface()
+ 	 * will attempt to disable LPM, and fail if it can't disable it.
+ 	 */
+-	lpm_disable_error = usb_unlocked_disable_lpm(udev);
+-	if (lpm_disable_error && driver->disable_hub_initiated_lpm) {
+-		dev_err(&intf->dev, "%s Failed to disable LPM for driver %s\n.",
+-				__func__, driver->name);
+-		error = lpm_disable_error;
+-		goto err;
++	if (driver->disable_hub_initiated_lpm) {
++		lpm_disable_error = usb_unlocked_disable_lpm(udev);
++		if (lpm_disable_error) {
++			dev_err(&intf->dev, "%s Failed to disable LPM for driver %s\n.",
++					__func__, driver->name);
++			error = lpm_disable_error;
++			goto err;
++		}
+ 	}
+ 
+ 	/* Carry out a deferred switch to altsetting 0 */
+@@ -391,7 +393,8 @@ static int usb_unbind_interface(struct device *dev)
+ 	struct usb_interface *intf = to_usb_interface(dev);
+ 	struct usb_host_endpoint *ep, **eps = NULL;
+ 	struct usb_device *udev;
+-	int i, j, error, r, lpm_disable_error;
++	int i, j, error, r;
++	int lpm_disable_error = -ENODEV;
+ 
+ 	intf->condition = USB_INTERFACE_UNBINDING;
+ 
+@@ -399,12 +402,13 @@ static int usb_unbind_interface(struct device *dev)
+ 	udev = interface_to_usbdev(intf);
+ 	error = usb_autoresume_device(udev);
+ 
+-	/* Hub-initiated LPM policy may change, so attempt to disable LPM until
++	/* If hub-initiated LPM policy may change, attempt to disable LPM until
+ 	 * the driver is unbound.  If LPM isn't disabled, that's fine because it
+ 	 * wouldn't be enabled unless all the bound interfaces supported
+ 	 * hub-initiated LPM.
+ 	 */
+-	lpm_disable_error = usb_unlocked_disable_lpm(udev);
++	if (driver->disable_hub_initiated_lpm)
++		lpm_disable_error = usb_unlocked_disable_lpm(udev);
+ 
+ 	/*
+ 	 * Terminate all URBs for this interface unless the driver
+@@ -505,7 +509,7 @@ int usb_driver_claim_interface(struct usb_driver *driver,
+ 	struct device *dev;
+ 	struct usb_device *udev;
+ 	int retval = 0;
+-	int lpm_disable_error;
++	int lpm_disable_error = -ENODEV;
+ 
+ 	if (!iface)
+ 		return -ENODEV;
+@@ -526,12 +530,14 @@ int usb_driver_claim_interface(struct usb_driver *driver,
+ 
+ 	iface->condition = USB_INTERFACE_BOUND;
+ 
+-	/* Disable LPM until this driver is bound. */
+-	lpm_disable_error = usb_unlocked_disable_lpm(udev);
+-	if (lpm_disable_error && driver->disable_hub_initiated_lpm) {
+-		dev_err(&iface->dev, "%s Failed to disable LPM for driver %s\n.",
+-				__func__, driver->name);
+-		return -ENOMEM;
++	/* See the comment about disabling LPM in usb_probe_interface(). */
++	if (driver->disable_hub_initiated_lpm) {
++		lpm_disable_error = usb_unlocked_disable_lpm(udev);
++		if (lpm_disable_error) {
++			dev_err(&iface->dev, "%s Failed to disable LPM for driver %s\n.",
++					__func__, driver->name);
++			return -ENOMEM;
++		}
+ 	}
+ 
+ 	/* Claimed interfaces are initially inactive (suspended) and
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 01b6c61cf9bb..eba1f10e8cfd 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -1068,7 +1068,7 @@ struct usbdrv_wrap {
+  *	for interfaces bound to this driver.
+  * @soft_unbind: if set to 1, the USB core will not kill URBs and disable
+  *	endpoints before calling the driver's disconnect method.
+- * @disable_hub_initiated_lpm: if set to 0, the USB core will not allow hubs
++ * @disable_hub_initiated_lpm: if set to 1, the USB core will not allow hubs
+  *	to initiate lower power link state transitions when an idle timeout
+  *	occurs.  Device-initiated USB 3.0 link PM will still be allowed.
+  *

commit 128f8b3d77149e9f38fb6f52931cf791155d277a
+Author: Alan Stern 
+Date:   Fri Apr 29 15:19:56 2016 -0400
+
+    USB: EHCI: make all debugging depend on CONFIG_DYNAMIC_DEBUG
+    
+    The debugging facilities in ehci-dbg.c follow an uneven pattern.  Some
+    of them are protected by "#ifdef CONFIG_DYNAMIC_DEBUG" and some
+    aren't, presumably in the hope of having some of the debugging output
+    available in any configuration.
+    
+    This leads to build problems when dynamic debugging isn't configured.
+    Rather than try to keep this complicated state of affairs, let's just
+    make everything dependent on CONFIG_DYNAMIC_DEBUG.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Rafał Miłecki 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
+index 79d12b2ba3c4..1a2614aae42c 100644
+--- a/drivers/usb/host/ehci-dbg.c
++++ b/drivers/usb/host/ehci-dbg.c
+@@ -52,13 +52,6 @@ static void dbg_hcs_params(struct ehci_hcd *ehci, char *label)
+ 		ehci_dbg(ehci, "%s portroute %s\n", label, buf);
+ 	}
+ }
+-#else
+-
+-static inline void dbg_hcs_params(struct ehci_hcd *ehci, char *label) {}
+-
+-#endif
+-
+-#ifdef CONFIG_DYNAMIC_DEBUG
+ 
+ /*
+  * check the values in the HCCPARAMS register
+@@ -92,13 +85,6 @@ static void dbg_hcc_params(struct ehci_hcd *ehci, char *label)
+ 				" 32 periodic list" : "");
+ 	}
+ }
+-#else
+-
+-static inline void dbg_hcc_params(struct ehci_hcd *ehci, char *label) {}
+-
+-#endif
+-
+-#ifdef CONFIG_DYNAMIC_DEBUG
+ 
+ static void __maybe_unused
+ dbg_qtd(const char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd)
+@@ -281,37 +267,6 @@ dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status)
+ 		(status & PORT_CONNECT) ? " CONNECT" : "");
+ }
+ 
+-#else
+-static inline void __maybe_unused
+-dbg_qh(char *label, struct ehci_hcd *ehci, struct ehci_qh *qh)
+-{}
+-
+-static inline int __maybe_unused
+-dbg_status_buf(char *buf, unsigned len, const char *label, u32 status)
+-{
+-	return 0;
+-}
+-
+-static inline int __maybe_unused
+-dbg_command_buf(char *buf, unsigned len, const char *label, u32 command)
+-{
+-	return 0;
+-}
+-
+-static inline int __maybe_unused
+-dbg_intr_buf(char *buf, unsigned len, const char *label, u32 enable)
+-{
+-	return 0;
+-}
+-
+-static inline int __maybe_unused
+-dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status)
+-{
+-	return 0;
+-}
+-
+-#endif	/* CONFIG_DYNAMIC_DEBUG */
+-
+ static inline void
+ dbg_status(struct ehci_hcd *ehci, const char *label, u32 status)
+ {
+@@ -341,13 +296,6 @@ dbg_port(struct ehci_hcd *ehci, const char *label, int port, u32 status)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-#ifndef CONFIG_DYNAMIC_DEBUG
+-
+-static inline void create_debug_files(struct ehci_hcd *bus) { }
+-static inline void remove_debug_files(struct ehci_hcd *bus) { }
+-
+-#else
+-
+ /* troubleshooting help: expose state in debugfs */
+ 
+ static int debug_async_open(struct inode *, struct file *);
+@@ -1120,4 +1068,38 @@ static inline void remove_debug_files(struct ehci_hcd *ehci)
+ 	debugfs_remove_recursive(ehci->debug_dir);
+ }
+ 
++#else /* CONFIG_DYNAMIC_DEBUG */
++
++static inline void dbg_hcs_params(struct ehci_hcd *ehci, char *label) { }
++static inline void dbg_hcc_params(struct ehci_hcd *ehci, char *label) { }
++
++static inline void __maybe_unused dbg_qh(const char *label,
++		struct ehci_hcd *ehci, struct ehci_qh *qh) { }
++
++static inline int __maybe_unused dbg_status_buf(const char *buf,
++		unsigned int len, const char *label, u32 status)
++{ return 0; }
++
++static inline int __maybe_unused dbg_command_buf(const char *buf,
++		unsigned int len, const char *label, u32 command)
++{ return 0; }
++
++static inline int __maybe_unused dbg_intr_buf(const char *buf,
++		unsigned int len, const char *label, u32 enable)
++{ return 0; }
++
++static inline int __maybe_unused dbg_port_buf(char *buf,
++		unsigned int len, const char *label, int port, u32 status)
++{ return 0; }
++
++static inline void dbg_status(struct ehci_hcd *ehci, const char *label,
++		u32 status) { }
++static inline void dbg_cmd(struct ehci_hcd *ehci, const char *label,
++		u32 command) { }
++static inline void dbg_port(struct ehci_hcd *ehci, const char *label,
++		int port, u32 status) { }
++
++static inline void create_debug_files(struct ehci_hcd *bus) { }
++static inline void remove_debug_files(struct ehci_hcd *bus) { }
++
+ #endif /* CONFIG_DYNAMIC_DEBUG */

commit 972e6a993f278b416a8ee3ec65475724fc36feb2
+Author: Alan Stern 
+Date:   Wed Mar 23 12:17:09 2016 -0400
+
+    HID: usbhid: fix inconsistent reset/resume/reset-resume behavior
+    
+    The usbhid driver has inconsistently duplicated code in its post-reset,
+    resume, and reset-resume pathways.
+    
+            reset-resume doesn't check HID_STARTED before trying to
+            restart the I/O queues.
+    
+            resume fails to clear the HID_SUSPENDED flag if HID_STARTED
+            isn't set.
+    
+            resume calls usbhid_restart_queues() with usbhid->lock held
+            and the others call it without holding the lock.
+    
+    The first item in particular causes a problem following a reset-resume
+    if the driver hasn't started up its I/O.  URB submission fails because
+    usbhid->urbin is NULL, and this triggers an unending reset-retry loop.
+    
+    This patch fixes the problem by creating a new subroutine,
+    hid_restart_io(), to carry out all the common activities.  It also
+    adds some checks that were missing in the original code:
+    
+            After a reset, there's no need to clear any halted endpoints.
+    
+            After a resume, if a reset is pending there's no need to
+            restart any I/O until the reset is finished.
+    
+            After a resume, if the interrupt-IN endpoint is halted there's
+            no need to submit the input URB until the halt has been
+            cleared.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Daniel Fraga 
+    Tested-by: Daniel Fraga 
+    CC: 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index ad71160b9ea4..ae83af649a60 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -951,14 +951,6 @@ static int usbhid_output_report(struct hid_device *hid, __u8 *buf, size_t count)
+ 	return ret;
+ }
+ 
+-static void usbhid_restart_queues(struct usbhid_device *usbhid)
+-{
+-	if (usbhid->urbout && !test_bit(HID_OUT_RUNNING, &usbhid->iofl))
+-		usbhid_restart_out_queue(usbhid);
+-	if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl))
+-		usbhid_restart_ctrl_queue(usbhid);
+-}
+-
+ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
+ {
+ 	struct usbhid_device *usbhid = hid->driver_data;
+@@ -1404,6 +1396,37 @@ static void hid_cease_io(struct usbhid_device *usbhid)
+ 	usb_kill_urb(usbhid->urbout);
+ }
+ 
++static void hid_restart_io(struct hid_device *hid)
++{
++	struct usbhid_device *usbhid = hid->driver_data;
++	int clear_halt = test_bit(HID_CLEAR_HALT, &usbhid->iofl);
++	int reset_pending = test_bit(HID_RESET_PENDING, &usbhid->iofl);
++
++	spin_lock_irq(&usbhid->lock);
++	clear_bit(HID_SUSPENDED, &usbhid->iofl);
++	usbhid_mark_busy(usbhid);
++
++	if (clear_halt || reset_pending)
++		schedule_work(&usbhid->reset_work);
++	usbhid->retry_delay = 0;
++	spin_unlock_irq(&usbhid->lock);
++
++	if (reset_pending || !test_bit(HID_STARTED, &usbhid->iofl))
++		return;
++
++	if (!clear_halt) {
++		if (hid_start_in(hid) < 0)
++			hid_io_error(hid);
++	}
++
++	spin_lock_irq(&usbhid->lock);
++	if (usbhid->urbout && !test_bit(HID_OUT_RUNNING, &usbhid->iofl))
++		usbhid_restart_out_queue(usbhid);
++	if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl))
++		usbhid_restart_ctrl_queue(usbhid);
++	spin_unlock_irq(&usbhid->lock);
++}
++
+ /* Treat USB reset pretty much the same as suspend/resume */
+ static int hid_pre_reset(struct usb_interface *intf)
+ {
+@@ -1453,14 +1476,14 @@ static int hid_post_reset(struct usb_interface *intf)
+ 		return 1;
+ 	}
+ 
++	/* No need to do another reset or clear a halted endpoint */
+ 	spin_lock_irq(&usbhid->lock);
+ 	clear_bit(HID_RESET_PENDING, &usbhid->iofl);
++	clear_bit(HID_CLEAR_HALT, &usbhid->iofl);
+ 	spin_unlock_irq(&usbhid->lock);
+ 	hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0);
+-	status = hid_start_in(hid);
+-	if (status < 0)
+-		hid_io_error(hid);
+-	usbhid_restart_queues(usbhid);
++
++	hid_restart_io(hid);
+ 
+ 	return 0;
+ }
+@@ -1483,25 +1506,9 @@ void usbhid_put_power(struct hid_device *hid)
+ #ifdef CONFIG_PM
+ static int hid_resume_common(struct hid_device *hid, bool driver_suspended)
+ {
+-	struct usbhid_device *usbhid = hid->driver_data;
+-	int status;
+-
+-	spin_lock_irq(&usbhid->lock);
+-	clear_bit(HID_SUSPENDED, &usbhid->iofl);
+-	usbhid_mark_busy(usbhid);
+-
+-	if (test_bit(HID_CLEAR_HALT, &usbhid->iofl) ||
+-			test_bit(HID_RESET_PENDING, &usbhid->iofl))
+-		schedule_work(&usbhid->reset_work);
+-	usbhid->retry_delay = 0;
+-
+-	usbhid_restart_queues(usbhid);
+-	spin_unlock_irq(&usbhid->lock);
+-
+-	status = hid_start_in(hid);
+-	if (status < 0)
+-		hid_io_error(hid);
++	int status = 0;
+ 
++	hid_restart_io(hid);
+ 	if (driver_suspended && hid->driver && hid->driver->resume)
+ 		status = hid->driver->resume(hid);
+ 	return status;
+@@ -1570,12 +1577,8 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
+ static int hid_resume(struct usb_interface *intf)
+ {
+ 	struct hid_device *hid = usb_get_intfdata (intf);
+-	struct usbhid_device *usbhid = hid->driver_data;
+ 	int status;
+ 
+-	if (!test_bit(HID_STARTED, &usbhid->iofl))
+-		return 0;
+-
+ 	status = hid_resume_common(hid, true);
+ 	dev_dbg(&intf->dev, "resume status %d\n", status);
+ 	return 0;
+@@ -1584,10 +1587,8 @@ static int hid_resume(struct usb_interface *intf)
+ static int hid_reset_resume(struct usb_interface *intf)
+ {
+ 	struct hid_device *hid = usb_get_intfdata(intf);
+-	struct usbhid_device *usbhid = hid->driver_data;
+ 	int status;
+ 
+-	clear_bit(HID_SUSPENDED, &usbhid->iofl);
+ 	status = hid_post_reset(intf);
+ 	if (status >= 0 && hid->driver && hid->driver->reset_resume) {
+ 		int ret = hid->driver->reset_resume(hid);

commit 1586ba0c218b10cce1de57c45f599dd8831a2d12
+Author: Alan Stern 
+Date:   Thu Feb 4 11:17:36 2016 -0500
+
+    USB: EHCI: fix compiler warning introduced by commit 2a40f324541e
+    
+    Fix the following compiler warning (found by the kbuild test robot):
+    
+    drivers/usb/host/ehci-hcd.c:312:13: warning: 'unlink_empty_async_suspended' declared 'static' but never defined
+    
+    Commit 2a40f324541e ("USB: EHCI: fix regression during bus resume")
+    protected the function definition with a "#ifdef CONFIG_PM" block, so
+    now the declaration needs to be similarly protected.  This patch moves
+    it to a better location.
+    
+    Reported-by: kbuild test robot 
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index a93d445b63a4..ae1b6e69eb96 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -309,7 +309,6 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
+ static void end_iaa_cycle(struct ehci_hcd *ehci);
+ static void end_unlink_async(struct ehci_hcd *ehci);
+ static void unlink_empty_async(struct ehci_hcd *ehci);
+-static void unlink_empty_async_suspended(struct ehci_hcd *ehci);
+ static void ehci_work(struct ehci_hcd *ehci);
+ static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh);
+ static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh);
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 6333d3c2be9c..ffc90295a95f 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -33,6 +33,8 @@
+ 
+ #ifdef	CONFIG_PM
+ 
++static void unlink_empty_async_suspended(struct ehci_hcd *ehci);
++
+ static int persist_enabled_on_companion(struct usb_device *udev, void *unused)
+ {
+ 	return !udev->maxchild && udev->persist_enabled &&

commit 8df0d77d8ce065ef536676fb4e1f36bfbf1dd809
+Author: Alan Stern 
+Date:   Mon Jan 25 15:45:38 2016 -0500
+
+    USB: EHCI: improvements to unlink_empty_async_suspended()
+    
+    unlink_empty_async_suspended() is marked __maybe_unused.  This is
+    because its caller, ehci_bus_suspend(), is protected by "#ifdef
+    CONFIG_PM".  We should use the same protection here instead of
+    __maybe_unused.
+    
+    unlink_empty_async_suspended() gets called only when the root hub is
+    suspended.  It's silly for it to call start_iaa_cycle() at such a
+    time; the IAA mechanism doesn't work when the root hub isn't running.
+    It should call end_unlink_async() instead.  But even this isn't
+    necessary, since there already is a call to end_iaa_cycle() right
+    before the call to unlink_empty_async_suspended().  All we have to do
+    is interchange the two subroutine calls.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 6d84ce2edc27..6333d3c2be9c 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -347,9 +347,10 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 		goto done;
+ 	ehci->rh_state = EHCI_RH_SUSPENDED;
+ 
++	unlink_empty_async_suspended(ehci);
++
+ 	/* Any IAA cycle that started before the suspend is now invalid */
+ 	end_iaa_cycle(ehci);
+-	unlink_empty_async_suspended(ehci);
+ 	ehci_handle_start_intr_unlinks(ehci);
+ 	ehci_handle_intr_unlinks(ehci);
+ 	end_free_itds(ehci);
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index a24341ef863d..eca3710d8fc4 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -1459,8 +1459,10 @@ static void unlink_empty_async(struct ehci_hcd *ehci)
+ 	}
+ }
+ 
++#ifdef	CONFIG_PM
++
+ /* The root hub is suspended; unlink all the async QHs */
+-static void __maybe_unused unlink_empty_async_suspended(struct ehci_hcd *ehci)
++static void unlink_empty_async_suspended(struct ehci_hcd *ehci)
+ {
+ 	struct ehci_qh		*qh;
+ 
+@@ -1469,9 +1471,10 @@ static void __maybe_unused unlink_empty_async_suspended(struct ehci_hcd *ehci)
+ 		WARN_ON(!list_empty(&qh->qtd_list));
+ 		single_unlink_async(ehci, qh);
+ 	}
+-	start_iaa_cycle(ehci);
+ }
+ 
++#endif
++
+ /* makes sure the async qh will become idle */
+ /* caller must own ehci->lock */
+ 

commit 87d61912c23a746ee9a8a8d2fe17af217c87f761
+Author: Alan Stern 
+Date:   Mon Jan 25 15:45:25 2016 -0500
+
+    USB: EHCI: add a delay when unlinking an active QH
+    
+    Michael Reutman reports that an AMD/ATI EHCI host controller on one of
+    his computers does not stop transferring data when an active bulk QH
+    is unlinked from the async schedule.  Apparently that host controller
+    fails to implement the IAA mechanism correctly when an active QH is
+    unlinked.  This leads to data corruption, because the controller
+    continues to update the QH in memory when the driver doesn't expect
+    it.  As a result, the next URB submitted for that QH can hang, because
+    the link pointers for the TD queue have been messed up.  This
+    misbehavior is observed quite regularly.
+    
+    To be fair, the EHCI spec (section 4.8.2) says that active QHs should
+    not be unlinked.  It goes on to recommend a procedure that involves
+    waiting for the QH to go inactive before unlinking it.  In the real
+    world this is impractical, not least because the QH may _never_ go
+    inactive.  (What were they thinking?)  Sometimes we have no choice but
+    to unlink an active QH.
+    
+    In an attempt to avoid the problems that can ensue, this patch changes
+    how the driver decides when the unlink is complete.  In addition to
+    waiting through two IAA cycles, in cases where the QH was not known to
+    be inactive beforehand we now wait until a 2-ms period has elapsed
+    with the host controller making no change to the QH data structure
+    (the hw_current and hw_token fields in particular).  The intuition
+    here is that after such a long period, the endpoint must be NAKing and
+    hopefully the QH has been dropped from the host controller's internal
+    cache.  There's no way to know if this reasoning is really valid --
+    the spec is no help in this regard -- but at least this approach fixes
+    Michael's problem.
+    
+    The test for whether the QH is already known to be inactive involves
+    the reason for unlinking the QH originally.  If it was unlinked
+    because it had halted, or it stopped in response to a short read, or
+    it overlaid a dummy TD (a silicon bug), then it certainly is inactive.
+    If it was unlinked because the TD queue was empty and no TDs have been
+    added to the queue in the meantime, then it must be inactive.  Or if
+    the hardware status indicates that the QH is currently halted (even if
+    that wasn't the reason for unlinking it), then it is inactive.
+    Otherwise, if none of those checks apply, we go through the 2-ms
+    delay.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Michael Reutman 
+    Tested-by: Michael Reutman 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 84c41262109c..a93d445b63a4 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -566,6 +566,9 @@ static int ehci_init(struct usb_hcd *hcd)
+ 	/* Accept arbitrarily long scatter-gather lists */
+ 	if (!(hcd->driver->flags & HCD_LOCAL_MEM))
+ 		hcd->self.sg_tablesize = ~0;
++
++	/* Prepare for unlinking active QHs */
++	ehci->old_current = ~0;
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 15dcae8f0631..a24341ef863d 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -1341,14 +1341,60 @@ static void end_unlink_async(struct ehci_hcd *ehci)
+ 	 * after the IAA interrupt occurs.  In self-defense, always go
+ 	 * through two IAA cycles for each QH.
+ 	 */
+-	else if (qh->qh_state == QH_STATE_UNLINK_WAIT) {
++	else if (qh->qh_state == QH_STATE_UNLINK) {
++		/*
++		 * Second IAA cycle has finished.  Process only the first
++		 * waiting QH (NVIDIA (?) bug).
++		 */
++		list_move_tail(&qh->unlink_node, &ehci->async_idle);
++	}
++
++	/*
++	 * AMD/ATI (?) bug: The HC can continue to use an active QH long
++	 * after the IAA interrupt occurs.  To prevent problems, QHs that
++	 * may still be active will wait until 2 ms have passed with no
++	 * change to the hw_current and hw_token fields (this delay occurs
++	 * between the two IAA cycles).
++	 *
++	 * The EHCI spec (4.8.2) says that active QHs must not be removed
++	 * from the async schedule and recommends waiting until the QH
++	 * goes inactive.  This is ridiculous because the QH will _never_
++	 * become inactive if the endpoint NAKs indefinitely.
++	 */
++
++	/* Some reasons for unlinking guarantee the QH can't be active */
++	else if (qh->unlink_reason & (QH_UNLINK_HALTED |
++			QH_UNLINK_SHORT_READ | QH_UNLINK_DUMMY_OVERLAY))
++		goto DelayDone;
++
++	/* The QH can't be active if the queue was and still is empty... */
++	else if	((qh->unlink_reason & QH_UNLINK_QUEUE_EMPTY) &&
++			list_empty(&qh->qtd_list))
++		goto DelayDone;
++
++	/* ... or if the QH has halted */
++	else if	(qh->hw->hw_token & cpu_to_hc32(ehci, QTD_STS_HALT))
++		goto DelayDone;
++
++	/* Otherwise we have to wait until the QH stops changing */
++	else {
++		__hc32		qh_current, qh_token;
++
++		qh_current = qh->hw->hw_current;
++		qh_token = qh->hw->hw_token;
++		if (qh_current != ehci->old_current ||
++				qh_token != ehci->old_token) {
++			ehci->old_current = qh_current;
++			ehci->old_token = qh_token;
++			ehci_enable_event(ehci,
++					EHCI_HRTIMER_ACTIVE_UNLINK, true);
++			return;
++		}
++ DelayDone:
+ 		qh->qh_state = QH_STATE_UNLINK;
+ 		early_exit = true;
+ 	}
+-
+-	/* Otherwise process only the first waiting QH (NVIDIA bug?) */
+-	else
+-		list_move_tail(&qh->unlink_node, &ehci->async_idle);
++	ehci->old_current = ~0;		/* Prepare for next QH */
+ 
+ 	/* Start a new IAA cycle if any QHs are waiting for it */
+ 	if (!list_empty(&ehci->async_unlink))
+diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
+index 6bea4d553ec5..69f50e6533a6 100644
+--- a/drivers/usb/host/ehci-timer.c
++++ b/drivers/usb/host/ehci-timer.c
+@@ -72,6 +72,7 @@ static unsigned event_delays_ns[] = {
+ 	1 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_POLL_DEAD */
+ 	1125 * NSEC_PER_USEC,	/* EHCI_HRTIMER_UNLINK_INTR */
+ 	2 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_FREE_ITDS */
++	2 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_ACTIVE_UNLINK */
+ 	5 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_START_UNLINK_INTR */
+ 	6 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_ASYNC_UNLINKS */
+ 	10 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_IAA_WATCHDOG */
+@@ -395,6 +396,7 @@ static void (*event_handlers[])(struct ehci_hcd *) = {
+ 	ehci_handle_controller_death,	/* EHCI_HRTIMER_POLL_DEAD */
+ 	ehci_handle_intr_unlinks,	/* EHCI_HRTIMER_UNLINK_INTR */
+ 	end_free_itds,			/* EHCI_HRTIMER_FREE_ITDS */
++	end_unlink_async,		/* EHCI_HRTIMER_ACTIVE_UNLINK */
+ 	ehci_handle_start_intr_unlinks,	/* EHCI_HRTIMER_START_UNLINK_INTR */
+ 	unlink_empty_async,		/* EHCI_HRTIMER_ASYNC_UNLINKS */
+ 	ehci_iaa_watchdog,		/* EHCI_HRTIMER_IAA_WATCHDOG */
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index f11b9dc53981..b13894550139 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -110,6 +110,7 @@ enum ehci_hrtimer_event {
+ 	EHCI_HRTIMER_POLL_DEAD,		/* Wait for dead controller to stop */
+ 	EHCI_HRTIMER_UNLINK_INTR,	/* Wait for interrupt QH unlink */
+ 	EHCI_HRTIMER_FREE_ITDS,		/* Wait for unused iTDs and siTDs */
++	EHCI_HRTIMER_ACTIVE_UNLINK,	/* Wait while unlinking an active QH */
+ 	EHCI_HRTIMER_START_UNLINK_INTR, /* Unlink empty interrupt QHs */
+ 	EHCI_HRTIMER_ASYNC_UNLINKS,	/* Unlink empty async QHs */
+ 	EHCI_HRTIMER_IAA_WATCHDOG,	/* Handle lost IAA interrupts */
+@@ -156,6 +157,8 @@ struct ehci_hcd {			/* one per controller */
+ 	struct list_head	async_idle;
+ 	unsigned		async_unlink_cycle;
+ 	unsigned		async_count;	/* async activity count */
++	__hc32			old_current;	/* Test for QH becoming */
++	__hc32			old_token;	/*  inactive during unlink */
+ 
+ 	/* periodic schedule support */
+ #define	DEFAULT_I_TDPS		1024		/* some HCs can do less */

commit f96fba0dbf8f6b0eaa313b4c230f93c9bb0dd759
+Author: Alan Stern 
+Date:   Mon Jan 25 15:44:16 2016 -0500
+
+    USB: EHCI: improve handling of the ehci->iaa_in_progress flag
+    
+    This patch improves the way ehci-hcd handles the iaa_in_progress flag.
+    The current code is somewhat careless in this regard:
+    
+            The flag is meaningless when the root hub isn't running, most
+            particularly after the root hub has been suspended.  But in
+            start_iaa_cycle(), the driver checks the flag before checking
+            the root hub's state.  They should be checked in the opposite
+            order.
+    
+            That routine also sets the flag too early, before it has
+            definitely committed to starting an IAA cycle.
+    
+            The flag is turned off in end_unlink_async().  Upcoming
+            changes will call that routine at other times, not just at the
+            end of an IAA cycle.  The two actions are logically separate
+            (although related), so we separate out a new routine to be
+            called in place of end_unlink_async() whenever an IAA cycle
+            ends: end_iaa_cycle().
+    
+            iaa_in_progress should be turned off when the root hub is
+            suspended -- we certainly don't want it still to be set when
+            the root hub resumes.  Therefore the call to
+            end_unlink_async() in ehci_bus_suspend() should also be
+            replaced with a call to end_iaa_cycle().
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index c5465bf9a798..84c41262109c 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -306,6 +306,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++static void end_iaa_cycle(struct ehci_hcd *ehci);
+ static void end_unlink_async(struct ehci_hcd *ehci);
+ static void unlink_empty_async(struct ehci_hcd *ehci);
+ static void unlink_empty_async_suspended(struct ehci_hcd *ehci);
+@@ -758,7 +759,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 			ehci_dbg(ehci, "IAA with IAAD still set?\n");
+ 		if (ehci->iaa_in_progress)
+ 			COUNT(ehci->stats.iaa);
+-		end_unlink_async(ehci);
++		end_iaa_cycle(ehci);
+ 	}
+ 
+ 	/* remote wakeup [4.3.1] */
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 086a7115d263..6d84ce2edc27 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -347,7 +347,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 		goto done;
+ 	ehci->rh_state = EHCI_RH_SUSPENDED;
+ 
+-	end_unlink_async(ehci);
++	/* Any IAA cycle that started before the suspend is now invalid */
++	end_iaa_cycle(ehci);
+ 	unlink_empty_async_suspended(ehci);
+ 	ehci_handle_start_intr_unlinks(ehci);
+ 	ehci_handle_intr_unlinks(ehci);
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 1b42bcb59743..15dcae8f0631 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -1283,17 +1283,13 @@ static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 
+ static void start_iaa_cycle(struct ehci_hcd *ehci)
+ {
+-	/* Do nothing if an IAA cycle is already running */
+-	if (ehci->iaa_in_progress)
+-		return;
+-	ehci->iaa_in_progress = true;
+-
+ 	/* If the controller isn't running, we don't have to wait for it */
+ 	if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) {
+ 		end_unlink_async(ehci);
+ 
+-	/* Otherwise start a new IAA cycle */
+-	} else if (likely(ehci->rh_state == EHCI_RH_RUNNING)) {
++	/* Otherwise start a new IAA cycle if one isn't already running */
++	} else if (ehci->rh_state == EHCI_RH_RUNNING &&
++			!ehci->iaa_in_progress) {
+ 
+ 		/* Make sure the unlinks are all visible to the hardware */
+ 		wmb();
+@@ -1301,17 +1297,13 @@ static void start_iaa_cycle(struct ehci_hcd *ehci)
+ 		ehci_writel(ehci, ehci->command | CMD_IAAD,
+ 				&ehci->regs->command);
+ 		ehci_readl(ehci, &ehci->regs->command);
++		ehci->iaa_in_progress = true;
+ 		ehci_enable_event(ehci, EHCI_HRTIMER_IAA_WATCHDOG, true);
+ 	}
+ }
+ 
+-/* the async qh for the qtds being unlinked are now gone from the HC */
+-
+-static void end_unlink_async(struct ehci_hcd *ehci)
++static void end_iaa_cycle(struct ehci_hcd *ehci)
+ {
+-	struct ehci_qh		*qh;
+-	bool			early_exit;
+-
+ 	if (ehci->has_synopsys_hc_bug)
+ 		ehci_writel(ehci, (u32) ehci->async->qh_dma,
+ 			    &ehci->regs->async_next);
+@@ -1319,6 +1311,16 @@ static void end_unlink_async(struct ehci_hcd *ehci)
+ 	/* The current IAA cycle has ended */
+ 	ehci->iaa_in_progress = false;
+ 
++	end_unlink_async(ehci);
++}
++
++/* See if the async qh for the qtds being unlinked are now gone from the HC */
++
++static void end_unlink_async(struct ehci_hcd *ehci)
++{
++	struct ehci_qh		*qh;
++	bool			early_exit;
++
+ 	if (list_empty(&ehci->async_unlink))
+ 		return;
+ 	qh = list_first_entry(&ehci->async_unlink, struct ehci_qh,
+diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
+index 37a3e0dece84..6bea4d553ec5 100644
+--- a/drivers/usb/host/ehci-timer.c
++++ b/drivers/usb/host/ehci-timer.c
+@@ -361,7 +361,7 @@ static void ehci_iaa_watchdog(struct ehci_hcd *ehci)
+ 	}
+ 
+ 	ehci_dbg(ehci, "IAA watchdog: status %x cmd %x\n", status, cmd);
+-	end_unlink_async(ehci);
++	end_iaa_cycle(ehci);
+ }
+ 
+ 

commit fcc5184ec1521c7d85124421e593660c94e9a9fb
+Author: Alan Stern 
+Date:   Mon Jan 25 15:42:04 2016 -0500
+
+    USB: EHCI: store reason for unlinking a QH
+    
+    This patch replaces the "exception" bitflag in the ehci_qh structure
+    with a more explicit "unlink_reason" bitmask.  This is for use in the
+    following patch, where we will need to have a good idea of the
+    reason for unlinking a QH, not just "something exceptional happened".
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Michael Reutman 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 00e77cc91053..c5465bf9a798 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -911,7 +911,7 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ 		 */
+ 	} else {
+ 		qh = (struct ehci_qh *) urb->hcpriv;
+-		qh->exception = 1;
++		qh->unlink_reason |= QH_UNLINK_REQUESTED;
+ 		switch (qh->qh_state) {
+ 		case QH_STATE_LINKED:
+ 			if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)
+@@ -972,10 +972,13 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 		goto done;
+ 	}
+ 
+-	qh->exception = 1;
++	qh->unlink_reason |= QH_UNLINK_REQUESTED;
+ 	switch (qh->qh_state) {
+ 	case QH_STATE_LINKED:
+-		WARN_ON(!list_empty(&qh->qtd_list));
++		if (list_empty(&qh->qtd_list))
++			qh->unlink_reason |= QH_UNLINK_QUEUE_EMPTY;
++		else
++			WARN_ON(1);
+ 		if (usb_endpoint_type(&ep->desc) != USB_ENDPOINT_XFER_INT)
+ 			start_unlink_async(ehci, qh);
+ 		else
+@@ -1042,7 +1045,7 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 			 * re-linking will call qh_refresh().
+ 			 */
+ 			usb_settoggle(qh->ps.udev, epnum, is_out, 0);
+-			qh->exception = 1;
++			qh->unlink_reason |= QH_UNLINK_REQUESTED;
+ 			if (eptype == USB_ENDPOINT_XFER_BULK)
+ 				start_unlink_async(ehci, qh);
+ 			else
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index aad0777240d3..1b42bcb59743 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -394,6 +394,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 					goto retry_xacterr;
+ 				}
+ 				stopped = 1;
++				qh->unlink_reason |= QH_UNLINK_HALTED;
+ 
+ 			/* magic dummy for some short reads; qh won't advance.
+ 			 * that silicon quirk can kick in with this dummy too.
+@@ -408,6 +409,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 					&& !(qtd->hw_alt_next
+ 						& EHCI_LIST_END(ehci))) {
+ 				stopped = 1;
++				qh->unlink_reason |= QH_UNLINK_SHORT_READ;
+ 			}
+ 
+ 		/* stop scanning when we reach qtds the hc is using */
+@@ -420,8 +422,10 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 			stopped = 1;
+ 
+ 			/* cancel everything if we halt, suspend, etc */
+-			if (ehci->rh_state < EHCI_RH_RUNNING)
++			if (ehci->rh_state < EHCI_RH_RUNNING) {
+ 				last_status = -ESHUTDOWN;
++				qh->unlink_reason |= QH_UNLINK_SHUTDOWN;
++			}
+ 
+ 			/* this qtd is active; skip it unless a previous qtd
+ 			 * for its urb faulted, or its urb was canceled.
+@@ -538,10 +542,10 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	 * except maybe high bandwidth ...
+ 	 */
+ 	if (stopped != 0 || hw->hw_qtd_next == EHCI_LIST_END(ehci))
+-		qh->exception = 1;
++		qh->unlink_reason |= QH_UNLINK_DUMMY_OVERLAY;
+ 
+ 	/* Let the caller know if the QH needs to be unlinked. */
+-	return qh->exception;
++	return qh->unlink_reason;
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -1003,7 +1007,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 
+ 	qh->qh_state = QH_STATE_LINKED;
+ 	qh->xacterrs = 0;
+-	qh->exception = 0;
++	qh->unlink_reason = 0;
+ 	/* qtd completions reported later by interrupt */
+ 
+ 	enable_async(ehci);
+@@ -1395,6 +1399,7 @@ static void unlink_empty_async(struct ehci_hcd *ehci)
+ 
+ 	/* If nothing else is being unlinked, unlink the last empty QH */
+ 	if (list_empty(&ehci->async_unlink) && qh_to_unlink) {
++		qh_to_unlink->unlink_reason |= QH_UNLINK_QUEUE_EMPTY;
+ 		start_unlink_async(ehci, qh_to_unlink);
+ 		--count;
+ 	}
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index f9a332775c47..c1704a57e803 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -595,7 +595,7 @@ static void qh_link_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	}
+ 	qh->qh_state = QH_STATE_LINKED;
+ 	qh->xacterrs = 0;
+-	qh->exception = 0;
++	qh->unlink_reason = 0;
+ 
+ 	/* update per-qh bandwidth for debugfs */
+ 	ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->ps.bw_period
+diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
+index 424ac5d83714..37a3e0dece84 100644
+--- a/drivers/usb/host/ehci-timer.c
++++ b/drivers/usb/host/ehci-timer.c
+@@ -237,6 +237,7 @@ static void ehci_handle_start_intr_unlinks(struct ehci_hcd *ehci)
+ 				ehci->intr_unlink_wait_cycle))
+ 			break;
+ 		list_del_init(&qh->unlink_node);
++		qh->unlink_reason |= QH_UNLINK_QUEUE_EMPTY;
+ 		start_unlink_intr(ehci, qh);
+ 	}
+ 
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index ec61aedb0067..f11b9dc53981 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -432,13 +432,19 @@ struct ehci_qh {
+ 	u8			xacterrs;	/* XactErr retry counter */
+ #define	QH_XACTERR_MAX		32		/* XactErr retry limit */
+ 
++	u8			unlink_reason;
++#define QH_UNLINK_HALTED	0x01		/* Halt flag is set */
++#define QH_UNLINK_SHORT_READ	0x02		/* Recover from a short read */
++#define QH_UNLINK_DUMMY_OVERLAY	0x04		/* QH overlayed the dummy TD */
++#define QH_UNLINK_SHUTDOWN	0x08		/* The HC isn't running */
++#define QH_UNLINK_QUEUE_EMPTY	0x10		/* Reached end of the queue */
++#define QH_UNLINK_REQUESTED	0x20		/* Disable, reset, or dequeue */
++
+ 	u8			gap_uf;		/* uframes split/csplit gap */
+ 
+ 	unsigned		is_out:1;	/* bulk or intr OUT */
+ 	unsigned		clearing_tt:1;	/* Clear-TT-Buf in progress */
+ 	unsigned		dequeue_during_giveback:1;
+-	unsigned		exception:1;	/* got a fault, or an unlink
+-						   was requested */
+ 	unsigned		should_be_inactive:1;
+ };
+ 

commit 13b4389143413a1f18127c07f72c74cad5b563e8
+Author: Alan Stern 
+Date:   Wed Jan 20 11:26:01 2016 -0500
+
+    SCSI: fix crashes in sd and sr runtime PM
+    
+    Runtime suspend during driver probe and removal can cause problems.
+    The driver's runtime_suspend or runtime_resume callbacks may invoked
+    before the driver has finished binding to the device or after the
+    driver has unbound from the device.
+    
+    This problem shows up with the sd and sr drivers, and can cause disk
+    or CD/DVD drives to become unusable as a result.  The fix is simple.
+    The drivers store a pointer to the scsi_disk or scsi_cd structure as
+    their private device data when probing is finished, so we simply have
+    to be sure to clear the private data during removal and test it during
+    runtime suspend/resume.
+    
+    This fixes .
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Paul Menzel 
+    Reported-by: Erich Schubert 
+    Reported-by: Alexandre Rossi 
+    Tested-by: Paul Menzel 
+    Tested-by: Erich Schubert 
+    CC: 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+index 4e08d1cd704d..84fa4c46eaa6 100644
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -3268,8 +3268,8 @@ static int sd_suspend_common(struct device *dev, bool ignore_stop_errors)
+ 	struct scsi_disk *sdkp = dev_get_drvdata(dev);
+ 	int ret = 0;
+ 
+-	if (!sdkp)
+-		return 0;	/* this can happen */
++	if (!sdkp)	/* E.g.: runtime suspend following sd_remove() */
++		return 0;
+ 
+ 	if (sdkp->WCE && sdkp->media_present) {
+ 		sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
+@@ -3308,6 +3308,9 @@ static int sd_resume(struct device *dev)
+ {
+ 	struct scsi_disk *sdkp = dev_get_drvdata(dev);
+ 
++	if (!sdkp)	/* E.g.: runtime resume at the start of sd_probe() */
++		return 0;
++
+ 	if (!sdkp->device->manage_start_stop)
+ 		return 0;
+ 
+diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
+index 8bd54a64efd6..64c867405ad4 100644
+--- a/drivers/scsi/sr.c
++++ b/drivers/scsi/sr.c
+@@ -144,6 +144,9 @@ static int sr_runtime_suspend(struct device *dev)
+ {
+ 	struct scsi_cd *cd = dev_get_drvdata(dev);
+ 
++	if (!cd)	/* E.g.: runtime suspend following sr_remove() */
++		return 0;
++
+ 	if (cd->media_present)
+ 		return -EBUSY;
+ 	else
+@@ -985,6 +988,7 @@ static int sr_remove(struct device *dev)
+ 	scsi_autopm_get_device(cd->device);
+ 
+ 	del_gendisk(cd->disk);
++	dev_set_drvdata(dev, NULL);
+ 
+ 	mutex_lock(&sr_ref_mutex);
+ 	kref_put(&cd->kref, sr_kref_release);

commit e50293ef9775c5f1cf3fcc093037dd6a8c5684ea
+Author: Alan Stern 
+Date:   Wed Dec 16 13:32:38 2015 -0500
+
+    USB: fix invalid memory access in hub_activate()
+    
+    Commit 8520f38099cc ("USB: change hub initialization sleeps to
+    delayed_work") changed the hub_activate() routine to make part of it
+    run in a workqueue.  However, the commit failed to take a reference to
+    the usb_hub structure or to lock the hub interface while doing so.  As
+    a result, if a hub is plugged in and quickly unplugged before the work
+    routine can run, the routine will try to access memory that has been
+    deallocated.  Or, if the hub is unplugged while the routine is
+    running, the memory may be deallocated while it is in active use.
+    
+    This patch fixes the problem by taking a reference to the usb_hub at
+    the start of hub_activate() and releasing it at the end (when the work
+    is finished), and by locking the hub interface while the work routine
+    is running.  It also adds a check at the start of the routine to see
+    if the hub has already been disconnected, in which nothing should be
+    done.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Alexandru Cornea 
+    Tested-by: Alexandru Cornea 
+    Fixes: 8520f38099cc ("USB: change hub initialization sleeps to delayed_work")
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index a5cc032ef77a..ddbf32d599cb 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1035,10 +1035,20 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ 	unsigned delay;
+ 
+ 	/* Continue a partial initialization */
+-	if (type == HUB_INIT2)
+-		goto init2;
+-	if (type == HUB_INIT3)
++	if (type == HUB_INIT2 || type == HUB_INIT3) {
++		device_lock(hub->intfdev);
++
++		/* Was the hub disconnected while we were waiting? */
++		if (hub->disconnected) {
++			device_unlock(hub->intfdev);
++			kref_put(&hub->kref, hub_release);
++			return;
++		}
++		if (type == HUB_INIT2)
++			goto init2;
+ 		goto init3;
++	}
++	kref_get(&hub->kref);
+ 
+ 	/* The superspeed hub except for root hub has to use Hub Depth
+ 	 * value as an offset into the route string to locate the bits
+@@ -1236,6 +1246,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ 			queue_delayed_work(system_power_efficient_wq,
+ 					&hub->init_work,
+ 					msecs_to_jiffies(delay));
++			device_unlock(hub->intfdev);
+ 			return;		/* Continues at init3: below */
+ 		} else {
+ 			msleep(delay);
+@@ -1257,6 +1268,11 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ 	/* Allow autosuspend if it was suppressed */
+ 	if (type <= HUB_INIT3)
+ 		usb_autopm_put_interface_async(to_usb_interface(hub->intfdev));
++
++	if (type == HUB_INIT2 || type == HUB_INIT3)
++		device_unlock(hub->intfdev);
++
++	kref_put(&hub->kref, hub_release);
+ }
+ 
+ /* Implement the continuations for the delays above */

commit ad87e03213b552a5c33d5e1e7a19a73768397010
+Author: Alan Stern 
+Date:   Thu Dec 10 15:27:21 2015 -0500
+
+    USB: add quirk for devices with broken LPM
+    
+    Some USB device / host controller combinations seem to have problems
+    with Link Power Management.  For example, Steinar found that his xHCI
+    controller wouldn't handle bandwidth calculations correctly for two
+    video cards simultaneously when LPM was enabled, even though the bus
+    had plenty of bandwidth available.
+    
+    This patch introduces a new quirk flag for devices that should remain
+    disabled for LPM, and creates quirk entries for Steinar's devices.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Steinar H. Gunderson 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 585c3cb07da6..a5cc032ef77a 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -124,6 +124,10 @@ struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev)
+ 
+ int usb_device_supports_lpm(struct usb_device *udev)
+ {
++	/* Some devices have trouble with LPM */
++	if (udev->quirks & USB_QUIRK_NO_LPM)
++		return 0;
++
+ 	/* USB 2.1 (and greater) devices indicate LPM support through
+ 	 * their USB 2.0 Extended Capabilities BOS descriptor.
+ 	 */
+@@ -4512,6 +4516,8 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ 		goto fail;
+ 	}
+ 
++	usb_detect_quirks(udev);
++
+ 	if (udev->wusb == 0 && le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0201) {
+ 		retval = usb_get_bos_descriptor(udev);
+ 		if (!retval) {
+@@ -4710,7 +4716,6 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
+ 		if (status < 0)
+ 			goto loop;
+ 
+-		usb_detect_quirks(udev);
+ 		if (udev->quirks & USB_QUIRK_DELAY_INIT)
+ 			msleep(1000);
+ 
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index fcd6ac0c667f..6dc810bce295 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -202,6 +202,12 @@ static const struct usb_device_id usb_quirk_list[] = {
+ 	{ USB_DEVICE(0x1a0a, 0x0200), .driver_info =
+ 			USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL },
+ 
++	/* Blackmagic Design Intensity Shuttle */
++	{ USB_DEVICE(0x1edb, 0xbd3b), .driver_info = USB_QUIRK_NO_LPM },
++
++	/* Blackmagic Design UltraStudio SDI */
++	{ USB_DEVICE(0x1edb, 0xbd4f), .driver_info = USB_QUIRK_NO_LPM },
++
+ 	{ }  /* terminating entry must be last */
+ };
+ 
+diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h
+index 9948c874e3f1..1d0043dc34e4 100644
+--- a/include/linux/usb/quirks.h
++++ b/include/linux/usb/quirks.h
+@@ -47,4 +47,7 @@
+ /* device generates spurious wakeup, ignore remote wakeup capability */
+ #define USB_QUIRK_IGNORE_REMOTE_WAKEUP		BIT(9)
+ 
++/* device can't handle Link Power Management */
++#define USB_QUIRK_NO_LPM			BIT(10)
++
+ #endif /* __LINUX_USB_QUIRKS_H */

commit fc0855f2747a0e21d86b7e63c50bf234fa766184
+Author: Alan Stern 
+Date:   Fri Nov 20 13:53:58 2015 -0500
+
+    USB: EHCI: warn on unexpectedly active QH
+    
+    This patch adds a new warning message to ehci-hcd.  The warning is
+    triggered whenever the driver finds that the hardware has set the
+    Active bit in a QH at a time when the driver expects the QH to be
+    completely idle.  Such bugs have been observed by users in the past,
+    and since they can lead to serious problems (such as inability to
+    unlink an URB that never completes), it would be good to know about
+    them when they occur.
+    
+    This won't fix these bugs; that's a bigger job for a later patch.  But
+    success isn't guaranteed, since this depends on aspects of the
+    hardware which are not documented in the EHCI spec or for which the
+    spec's recommendations are clearly unworkable.  It therefore seems
+    worthwhile to check for these bugs proactively.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Michael Reutman 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 54f5332f814d..aad0777240d3 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -132,10 +132,14 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	 * qtd is updated in qh_completions(). Update the QH
+ 	 * overlay here.
+ 	 */
+-	if (qh->hw->hw_token & ACTIVE_BIT(ehci))
++	if (qh->hw->hw_token & ACTIVE_BIT(ehci)) {
+ 		qh->hw->hw_qtd_next = qtd->hw_next;
+-	else
++		if (qh->should_be_inactive)
++			ehci_warn(ehci, "qh %p should be inactive!\n", qh);
++	} else {
+ 		qh_update(ehci, qh, qtd);
++	}
++	qh->should_be_inactive = 0;
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -438,6 +442,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 					(hw->hw_token & ACTIVE_BIT(ehci))) {
+ 				token = hc32_to_cpu(ehci, hw->hw_token);
+ 				hw->hw_token &= ~ACTIVE_BIT(ehci);
++				qh->should_be_inactive = 1;
+ 
+ 				/* An unlink may leave an incomplete
+ 				 * async transaction in the TT buffer.
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 46f62e41bcde..ec61aedb0067 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -439,6 +439,7 @@ struct ehci_qh {
+ 	unsigned		dequeue_during_giveback:1;
+ 	unsigned		exception:1;	/* got a fault, or an unlink
+ 						   was requested */
++	unsigned		should_be_inactive:1;
+ };
+ 
+ /*-------------------------------------------------------------------------*/

commit 8ee10d6292cab0e425f93dbfa1f0e805c449dfc2
+Author: Alan Stern 
+Date:   Fri Nov 20 13:53:45 2015 -0500
+
+    USB: EHCI: enhance "async" debugfs output
+    
+    This patch enhances the "async" debugfs file in ehci-hcd by printing
+    out several additional fields in the hardware-accessible data
+    structures.  These fields are important for determining the hardware's
+    view of the async schedule, in particular, the addresses of the
+    current and next qTDs for each QH along with the start address of each
+    qTD's data buffer.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
+index b26b96e25a13..b7d623f1523c 100644
+--- a/drivers/usb/host/ehci-dbg.c
++++ b/drivers/usb/host/ehci-dbg.c
+@@ -436,7 +436,8 @@ static void qh_lines (
+ 	scratch = hc32_to_cpup(ehci, &hw->hw_info1);
+ 	hw_curr = (mark == '*') ? hc32_to_cpup(ehci, &hw->hw_current) : 0;
+ 	temp = scnprintf (next, size,
+-			"qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)",
++			"qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)"
++			" [cur %08x next %08x buf[0] %08x]",
+ 			qh, scratch & 0x007f,
+ 			speed_char (scratch),
+ 			(scratch >> 8) & 0x000f,
+@@ -444,7 +445,10 @@ static void qh_lines (
+ 			hc32_to_cpup(ehci, &hw->hw_token), mark,
+ 			(cpu_to_hc32(ehci, QTD_TOGGLE) & hw->hw_token)
+ 				? "data1" : "data0",
+-			(hc32_to_cpup(ehci, &hw->hw_alt_next) >> 1) & 0x0f);
++			(hc32_to_cpup(ehci, &hw->hw_alt_next) >> 1) & 0x0f,
++			hc32_to_cpup(ehci, &hw->hw_current),
++			hc32_to_cpup(ehci, &hw->hw_qtd_next),
++			hc32_to_cpup(ehci, &hw->hw_buf[0]));
+ 	size -= temp;
+ 	next += temp;
+ 
+@@ -464,7 +468,8 @@ static void qh_lines (
+ 				mark = '/';
+ 		}
+ 		temp = snprintf (next, size,
+-				"\n\t%p%c%s len=%d %08x urb %p",
++				"\n\t%p%c%s len=%d %08x urb %p"
++				" [td %08x buf[0] %08x]",
+ 				td, mark, ({ char *tmp;
+ 				 switch ((scratch>>8)&0x03) {
+ 				 case 0: tmp = "out"; break;
+@@ -474,7 +479,9 @@ static void qh_lines (
+ 				 } tmp;}),
+ 				(scratch >> 16) & 0x7fff,
+ 				scratch,
+-				td->urb);
++				td->urb,
++				(u32) td->qtd_dma,
++				hc32_to_cpup(ehci, &td->hw_buf[0]));
+ 		if (size < temp)
+ 			temp = size;
+ 		size -= temp;

commit a016a816bb96088ce4cd0ec890e256e4a63dfb47
+Author: Alan Stern 
+Date:   Fri Nov 20 13:53:35 2015 -0500
+
+    USB: add usbfs snooping for REAP and DISCARD
+    
+    This patch improves the usbfs_snoop debugging facility by adding
+    messages for a couple of significant events which, up to now, have not
+    been logged.  The events are reaping and discarding (i.e.,
+    cancelling) an URB.  The debugging messages include the userspace
+    address of the URB being reaped or discarded.
+    
+    The reaping messages have to be added in four places, in order to
+    handle blocking and non-blocking reaps in both normal and 32-bit
+    compatibility mode.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 3d41faf6e607..e9f0de3e06db 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -1716,8 +1716,12 @@ static struct async *reap_as(struct usb_dev_state *ps)
+ static int proc_reapurb(struct usb_dev_state *ps, void __user *arg)
+ {
+ 	struct async *as = reap_as(ps);
++
+ 	if (as) {
+-		int retval = processcompl(as, (void __user * __user *)arg);
++		int retval;
++
++		snoop(&ps->dev->dev, "reap %p\n", as->userurb);
++		retval = processcompl(as, (void __user * __user *)arg);
+ 		free_async(as);
+ 		return retval;
+ 	}
+@@ -1733,6 +1737,7 @@ static int proc_reapurbnonblock(struct usb_dev_state *ps, void __user *arg)
+ 
+ 	as = async_getcompleted(ps);
+ 	if (as) {
++		snoop(&ps->dev->dev, "reap %p\n", as->userurb);
+ 		retval = processcompl(as, (void __user * __user *)arg);
+ 		free_async(as);
+ 	} else {
+@@ -1859,8 +1864,12 @@ static int processcompl_compat(struct async *as, void __user * __user *arg)
+ static int proc_reapurb_compat(struct usb_dev_state *ps, void __user *arg)
+ {
+ 	struct async *as = reap_as(ps);
++
+ 	if (as) {
+-		int retval = processcompl_compat(as, (void __user * __user *)arg);
++		int retval;
++
++		snoop(&ps->dev->dev, "reap %p\n", as->userurb);
++		retval = processcompl_compat(as, (void __user * __user *)arg);
+ 		free_async(as);
+ 		return retval;
+ 	}
+@@ -1876,6 +1885,7 @@ static int proc_reapurbnonblock_compat(struct usb_dev_state *ps, void __user *ar
+ 
+ 	as = async_getcompleted(ps);
+ 	if (as) {
++		snoop(&ps->dev->dev, "reap %p\n", as->userurb);
+ 		retval = processcompl_compat(as, (void __user * __user *)arg);
+ 		free_async(as);
+ 	} else {
+@@ -2280,7 +2290,7 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
+ #endif
+ 
+ 	case USBDEVFS_DISCARDURB:
+-		snoop(&dev->dev, "%s: DISCARDURB\n", __func__);
++		snoop(&dev->dev, "%s: DISCARDURB %p\n", __func__, p);
+ 		ret = proc_unlinkurb(ps, p);
+ 		break;
+ 

commit 0290cc9f044a4d24d9a64e81761ac84498dc9d73
+Author: Alan Stern 
+Date:   Fri Nov 20 13:53:22 2015 -0500
+
+    USB: limit usbfs snooping of URB contents
+    
+    The usbfs_snoop facility can be very useful for debugging problems
+    involving usbfs.  However, it always prints out the entire contents of
+    every URB.  When dealing with large quantities of data, this can be
+    less than helpful.
+    
+    This patch ameliorates the situation by adding a module parameter to
+    usbcore for controlling the maximum number of bytes to print when
+    snooping an URB.  This makes debugging much easier.  For backward
+    compatibility, the default value is set unreasonably high.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
+index 742f69d18fc8..e6b6e056cc11 100644
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -3874,6 +3874,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
+ 	usbcore.usbfs_snoop=
+ 			[USB] Set to log all usbfs traffic (default 0 = off).
+ 
++	usbcore.usbfs_snoop_max=
++			[USB] Maximum number of bytes to snoop in each URB
++			(default = 65536).
++
+ 	usbcore.blinkenlights=
+ 			[USB] Set to cycle leds on hubs (default 0 = off).
+ 
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 38ae877c46e3..3d41faf6e607 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -100,6 +100,11 @@ static bool usbfs_snoop;
+ module_param(usbfs_snoop, bool, S_IRUGO | S_IWUSR);
+ MODULE_PARM_DESC(usbfs_snoop, "true to log all usbfs traffic");
+ 
++static unsigned usbfs_snoop_max = 65536;
++module_param(usbfs_snoop_max, uint, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(usbfs_snoop_max,
++		"maximum number of bytes to print while snooping");
++
+ #define snoop(dev, format, arg...)				\
+ 	do {							\
+ 		if (usbfs_snoop)				\
+@@ -392,6 +397,7 @@ static void snoop_urb(struct usb_device *udev,
+ 					ep, t, d, length, timeout_or_status);
+ 	}
+ 
++	data_len = min(data_len, usbfs_snoop_max);
+ 	if (data && data_len > 0) {
+ 		print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, 32, 1,
+ 			data, data_len, 1);
+@@ -402,7 +408,8 @@ static void snoop_urb_data(struct urb *urb, unsigned len)
+ {
+ 	int i, size;
+ 
+-	if (!usbfs_snoop)
++	len = min(len, usbfs_snoop_max);
++	if (!usbfs_snoop || len == 0)
+ 		return;
+ 
+ 	if (urb->num_sgs == 0) {

commit b704f70ce2003c8046d5c0128303aeeb0d93d890
+Author: Alan Stern 
+Date:   Mon Aug 3 11:57:29 2015 -0400
+
+    SCSI: fix bug in scsi_dev_info_list matching
+    
+    The "compatible" matching algorithm used for looking up old-style
+    blacklist entries in a scsi_dev_info_list is buggy.  The core of the
+    algorithm looks like this:
+    
+                    if (memcmp(devinfo->vendor, vendor,
+                                min(max, strlen(devinfo->vendor))))
+                            /* not a match */
+    
+    where max is the length of the device's vendor string after leading
+    spaces have been removed but trailing spaces have not.  Because of the
+    min() computation, either entry could be a proper substring of the
+    other and the code would still think that they match.
+    
+    In the case originally reported, the device's vendor and product
+    strings were "Inateck " and "                ".  These matched against
+    the following entry in the global device list:
+    
+            {"", "Scanner", "1.80", BLIST_NOLUN}
+    
+    because "" is a substring of "Inateck " and "" (the result of removing
+    leading spaces from the device's product string) is a substring of
+    "Scanner".  The mistaken match prevented the system from scanning and
+    finding the device's second Logical Unit.
+    
+    This patch fixes the problem by making two changes.  First, the code
+    for leading-space removal is hoisted out of the loop.  (This means it
+    will sometimes run unnecessarily, but since a large percentage of all
+    lookups involve the "compatible" entries in global device list, this
+    should be an overall improvement.)  Second and more importantly, the
+    patch removes trailing spaces and adds a check to verify that the two
+    resulting strings are exactly the same length.  This prevents matches
+    where one entry is a proper substring of the other.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Giulio Bernardi 
+    Tested-by: Giulio Bernardi 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
+index 2f49a224462d..2c1160c7ec92 100644
+--- a/drivers/scsi/scsi_devinfo.c
++++ b/drivers/scsi/scsi_devinfo.c
+@@ -407,51 +407,52 @@ static struct scsi_dev_info_list *scsi_dev_info_list_find(const char *vendor,
+ 	struct scsi_dev_info_list *devinfo;
+ 	struct scsi_dev_info_list_table *devinfo_table =
+ 		scsi_devinfo_lookup_by_key(key);
++	size_t vmax, mmax;
++	const char *vskip, *mskip;
+ 
+ 	if (IS_ERR(devinfo_table))
+ 		return (struct scsi_dev_info_list *) devinfo_table;
+ 
++	/* Prepare for "compatible" matches */
++
++	/*
++	 * XXX why skip leading spaces? If an odd INQUIRY
++	 * value, that should have been part of the
++	 * scsi_static_device_list[] entry, such as "  FOO"
++	 * rather than "FOO". Since this code is already
++	 * here, and we don't know what device it is
++	 * trying to work with, leave it as-is.
++	 */
++	vmax = 8;	/* max length of vendor */
++	vskip = vendor;
++	while (vmax > 0 && *vskip == ' ') {
++		vmax--;
++		vskip++;
++	}
++	/* Also skip trailing spaces */
++	while (vmax > 0 && vskip[vmax - 1] == ' ')
++		--vmax;
++
++	mmax = 16;	/* max length of model */
++	mskip = model;
++	while (mmax > 0 && *mskip == ' ') {
++		mmax--;
++		mskip++;
++	}
++	while (mmax > 0 && mskip[mmax - 1] == ' ')
++		--mmax;
++
+ 	list_for_each_entry(devinfo, &devinfo_table->scsi_dev_info_list,
+ 			    dev_info_list) {
+ 		if (devinfo->compatible) {
+ 			/*
+ 			 * Behave like the older version of get_device_flags.
+ 			 */
+-			size_t max;
+-			/*
+-			 * XXX why skip leading spaces? If an odd INQUIRY
+-			 * value, that should have been part of the
+-			 * scsi_static_device_list[] entry, such as "  FOO"
+-			 * rather than "FOO". Since this code is already
+-			 * here, and we don't know what device it is
+-			 * trying to work with, leave it as-is.
+-			 */
+-			max = 8;	/* max length of vendor */
+-			while ((max > 0) && *vendor == ' ') {
+-				max--;
+-				vendor++;
+-			}
+-			/*
+-			 * XXX removing the following strlen() would be
+-			 * good, using it means that for a an entry not in
+-			 * the list, we scan every byte of every vendor
+-			 * listed in scsi_static_device_list[], and never match
+-			 * a single one (and still have to compare at
+-			 * least the first byte of each vendor).
+-			 */
+-			if (memcmp(devinfo->vendor, vendor,
+-				    min(max, strlen(devinfo->vendor))))
++			if (memcmp(devinfo->vendor, vskip, vmax) ||
++					devinfo->vendor[vmax])
+ 				continue;
+-			/*
+-			 * Skip spaces again.
+-			 */
+-			max = 16;	/* max length of model */
+-			while ((max > 0) && *model == ' ') {
+-				max--;
+-				model++;
+-			}
+-			if (memcmp(devinfo->model, model,
+-				   min(max, strlen(devinfo->model))))
++			if (memcmp(devinfo->model, mskip, mmax) ||
++					devinfo->model[mmax])
+ 				continue;
+ 			return devinfo;
+ 		} else {

commit c42b3654f48bc06189a2d99629c9cf7bb79e8fe3
+Author: Alan Stern 
+Date:   Mon Aug 3 11:57:21 2015 -0400
+
+    SCSI: refactor device-matching code in scsi_devinfo.c
+    
+    In drivers/scsi/scsi_devinfo.c, the scsi_dev_info_list_del_keyed() and
+    scsi_get_device_flags_keyed() routines contain a large amount of
+    duplicate code for finding vendor/product matches in a
+    scsi_dev_info_list.  This patch factors out the duplicate code and
+    puts it in a separate function, scsi_dev_info_list_find().
+    
+    Signed-off-by: Alan Stern 
+    Suggested-by: Giulio Bernardi 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
+index 9f77d23239a2..2f49a224462d 100644
+--- a/drivers/scsi/scsi_devinfo.c
++++ b/drivers/scsi/scsi_devinfo.c
+@@ -390,25 +390,26 @@ int scsi_dev_info_list_add_keyed(int compatible, char *vendor, char *model,
+ EXPORT_SYMBOL(scsi_dev_info_list_add_keyed);
+ 
+ /**
+- * scsi_dev_info_list_del_keyed - remove one dev_info list entry.
++ * scsi_dev_info_list_find - find a matching dev_info list entry.
+  * @vendor:	vendor string
+  * @model:	model (product) string
+  * @key:	specify list to use
+  *
+  * Description:
+- * 	Remove and destroy one dev_info entry for @vendor, @model
++ *	Finds the first dev_info entry matching @vendor, @model
+  * 	in list specified by @key.
+  *
+- * Returns: 0 OK, -error on failure.
++ * Returns: pointer to matching entry, or ERR_PTR on failure.
+  **/
+-int scsi_dev_info_list_del_keyed(char *vendor, char *model, int key)
++static struct scsi_dev_info_list *scsi_dev_info_list_find(const char *vendor,
++		const char *model, int key)
+ {
+-	struct scsi_dev_info_list *devinfo, *found = NULL;
++	struct scsi_dev_info_list *devinfo;
+ 	struct scsi_dev_info_list_table *devinfo_table =
+ 		scsi_devinfo_lookup_by_key(key);
+ 
+ 	if (IS_ERR(devinfo_table))
+-		return PTR_ERR(devinfo_table);
++		return (struct scsi_dev_info_list *) devinfo_table;
+ 
+ 	list_for_each_entry(devinfo, &devinfo_table->scsi_dev_info_list,
+ 			    dev_info_list) {
+@@ -452,25 +453,42 @@ int scsi_dev_info_list_del_keyed(char *vendor, char *model, int key)
+ 			if (memcmp(devinfo->model, model,
+ 				   min(max, strlen(devinfo->model))))
+ 				continue;
+-			found = devinfo;
++			return devinfo;
+ 		} else {
+ 			if (!memcmp(devinfo->vendor, vendor,
+ 				     sizeof(devinfo->vendor)) &&
+ 			     !memcmp(devinfo->model, model,
+ 				      sizeof(devinfo->model)))
+-				found = devinfo;
++				return devinfo;
+ 		}
+-		if (found)
+-			break;
+ 	}
+ 
+-	if (found) {
+-		list_del(&found->dev_info_list);
+-		kfree(found);
+-		return 0;
+-	}
++	return ERR_PTR(-ENOENT);
++}
++
++/**
++ * scsi_dev_info_list_del_keyed - remove one dev_info list entry.
++ * @vendor:	vendor string
++ * @model:	model (product) string
++ * @key:	specify list to use
++ *
++ * Description:
++ *	Remove and destroy one dev_info entry for @vendor, @model
++ *	in list specified by @key.
++ *
++ * Returns: 0 OK, -error on failure.
++ **/
++int scsi_dev_info_list_del_keyed(char *vendor, char *model, int key)
++{
++	struct scsi_dev_info_list *found;
+ 
+-	return -ENOENT;
++	found = scsi_dev_info_list_find(vendor, model, key);
++	if (IS_ERR(found))
++		return PTR_ERR(found);
++
++	list_del(&found->dev_info_list);
++	kfree(found);
++	return 0;
+ }
+ EXPORT_SYMBOL(scsi_dev_info_list_del_keyed);
+ 
+@@ -565,64 +583,16 @@ int scsi_get_device_flags_keyed(struct scsi_device *sdev,
+ 				int key)
+ {
+ 	struct scsi_dev_info_list *devinfo;
+-	struct scsi_dev_info_list_table *devinfo_table;
++	int err;
+ 
+-	devinfo_table = scsi_devinfo_lookup_by_key(key);
++	devinfo = scsi_dev_info_list_find(vendor, model, key);
++	if (!IS_ERR(devinfo))
++		return devinfo->flags;
+ 
+-	if (IS_ERR(devinfo_table))
+-		return PTR_ERR(devinfo_table);
++	err = PTR_ERR(devinfo);
++	if (err != -ENOENT)
++		return err;
+ 
+-	list_for_each_entry(devinfo, &devinfo_table->scsi_dev_info_list,
+-			    dev_info_list) {
+-		if (devinfo->compatible) {
+-			/*
+-			 * Behave like the older version of get_device_flags.
+-			 */
+-			size_t max;
+-			/*
+-			 * XXX why skip leading spaces? If an odd INQUIRY
+-			 * value, that should have been part of the
+-			 * scsi_static_device_list[] entry, such as "  FOO"
+-			 * rather than "FOO". Since this code is already
+-			 * here, and we don't know what device it is
+-			 * trying to work with, leave it as-is.
+-			 */
+-			max = 8;	/* max length of vendor */
+-			while ((max > 0) && *vendor == ' ') {
+-				max--;
+-				vendor++;
+-			}
+-			/*
+-			 * XXX removing the following strlen() would be
+-			 * good, using it means that for a an entry not in
+-			 * the list, we scan every byte of every vendor
+-			 * listed in scsi_static_device_list[], and never match
+-			 * a single one (and still have to compare at
+-			 * least the first byte of each vendor).
+-			 */
+-			if (memcmp(devinfo->vendor, vendor,
+-				    min(max, strlen(devinfo->vendor))))
+-				continue;
+-			/*
+-			 * Skip spaces again.
+-			 */
+-			max = 16;	/* max length of model */
+-			while ((max > 0) && *model == ' ') {
+-				max--;
+-				model++;
+-			}
+-			if (memcmp(devinfo->model, model,
+-				   min(max, strlen(devinfo->model))))
+-				continue;
+-			return devinfo->flags;
+-		} else {
+-			if (!memcmp(devinfo->vendor, vendor,
+-				     sizeof(devinfo->vendor)) &&
+-			     !memcmp(devinfo->model, model,
+-				      sizeof(devinfo->model)))
+-				return devinfo->flags;
+-		}
+-	}
+ 	/* nothing found, return nothing */
+ 	if (key != SCSI_DEVINFO_GLOBAL)
+ 		return 0;

commit b9a6e8e1001e28fecbd74c073f5503dac2790563
+Author: Alan Stern 
+Date:   Tue Sep 1 09:48:01 2015 +0800
+
+    usb: misc: usbtest: format the data pattern according to max packet size
+    
+    With this change, the host and gadget doesn't need to agree with transfer
+    length for comparing the data, since they doesn't know each other's
+    transfer size, but know max packet size.
+    
+    Signed-off-by: Peter Chen 
+    Acked-by: Michal Nazarewicz 
+    (Fixed the 'line over 80 characters warning' by Peter Chen)
+    Tested-by: Peter Chen 
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
+index cac93b77f9a7..ad6dd4a1de6c 100644
+--- a/drivers/usb/misc/usbtest.c
++++ b/drivers/usb/misc/usbtest.c
+@@ -304,11 +304,20 @@ static unsigned mod_pattern;
+ module_param_named(pattern, mod_pattern, uint, S_IRUGO | S_IWUSR);
+ MODULE_PARM_DESC(mod_pattern, "i/o pattern (0 == zeroes)");
+ 
+-static inline void simple_fill_buf(struct urb *urb)
++static unsigned get_maxpacket(struct usb_device *udev, int pipe)
++{
++	struct usb_host_endpoint	*ep;
++
++	ep = usb_pipe_endpoint(udev, pipe);
++	return le16_to_cpup(&ep->desc.wMaxPacketSize);
++}
++
++static void simple_fill_buf(struct urb *urb)
+ {
+ 	unsigned	i;
+ 	u8		*buf = urb->transfer_buffer;
+ 	unsigned	len = urb->transfer_buffer_length;
++	unsigned	maxpacket;
+ 
+ 	switch (pattern) {
+ 	default:
+@@ -317,8 +326,9 @@ static inline void simple_fill_buf(struct urb *urb)
+ 		memset(buf, 0, len);
+ 		break;
+ 	case 1:			/* mod63 */
++		maxpacket = get_maxpacket(urb->dev, urb->pipe);
+ 		for (i = 0; i < len; i++)
+-			*buf++ = (u8) (i % 63);
++			*buf++ = (u8) ((i % maxpacket) % 63);
+ 		break;
+ 	}
+ }
+@@ -350,6 +360,7 @@ static int simple_check_buf(struct usbtest_dev *tdev, struct urb *urb)
+ 	u8		expected;
+ 	u8		*buf = urb->transfer_buffer;
+ 	unsigned	len = urb->actual_length;
++	unsigned	maxpacket = get_maxpacket(urb->dev, urb->pipe);
+ 
+ 	int ret = check_guard_bytes(tdev, urb);
+ 	if (ret)
+@@ -367,7 +378,7 @@ static int simple_check_buf(struct usbtest_dev *tdev, struct urb *urb)
+ 		 * with set_interface or set_config.
+ 		 */
+ 		case 1:			/* mod63 */
+-			expected = i % 63;
++			expected = (i % maxpacket) % 63;
+ 			break;
+ 		/* always fail unsupported patterns */
+ 		default:
+@@ -479,11 +490,13 @@ static void free_sglist(struct scatterlist *sg, int nents)
+ }
+ 
+ static struct scatterlist *
+-alloc_sglist(int nents, int max, int vary)
++alloc_sglist(int nents, int max, int vary, struct usbtest_dev *dev, int pipe)
+ {
+ 	struct scatterlist	*sg;
+ 	unsigned		i;
+ 	unsigned		size = max;
++	unsigned		maxpacket =
++		get_maxpacket(interface_to_usbdev(dev->intf), pipe);
+ 
+ 	if (max == 0)
+ 		return NULL;
+@@ -512,7 +525,7 @@ alloc_sglist(int nents, int max, int vary)
+ 			break;
+ 		case 1:
+ 			for (j = 0; j < size; j++)
+-				*buf++ = (u8) (j % 63);
++				*buf++ = (u8) ((j % maxpacket) % 63);
+ 			break;
+ 		}
+ 
+@@ -2176,7 +2189,8 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
+ 			"TEST 5:  write %d sglists %d entries of %d bytes\n",
+ 				param->iterations,
+ 				param->sglen, param->length);
+-		sg = alloc_sglist(param->sglen, param->length, 0);
++		sg = alloc_sglist(param->sglen, param->length,
++				0, dev, dev->out_pipe);
+ 		if (!sg) {
+ 			retval = -ENOMEM;
+ 			break;
+@@ -2194,7 +2208,8 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
+ 			"TEST 6:  read %d sglists %d entries of %d bytes\n",
+ 				param->iterations,
+ 				param->sglen, param->length);
+-		sg = alloc_sglist(param->sglen, param->length, 0);
++		sg = alloc_sglist(param->sglen, param->length,
++				0, dev, dev->in_pipe);
+ 		if (!sg) {
+ 			retval = -ENOMEM;
+ 			break;
+@@ -2211,7 +2226,8 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
+ 			"TEST 7:  write/%d %d sglists %d entries 0..%d bytes\n",
+ 				param->vary, param->iterations,
+ 				param->sglen, param->length);
+-		sg = alloc_sglist(param->sglen, param->length, param->vary);
++		sg = alloc_sglist(param->sglen, param->length,
++				param->vary, dev, dev->out_pipe);
+ 		if (!sg) {
+ 			retval = -ENOMEM;
+ 			break;
+@@ -2228,7 +2244,8 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
+ 			"TEST 8:  read/%d %d sglists %d entries 0..%d bytes\n",
+ 				param->vary, param->iterations,
+ 				param->sglen, param->length);
+-		sg = alloc_sglist(param->sglen, param->length, param->vary);
++		sg = alloc_sglist(param->sglen, param->length,
++				param->vary, dev, dev->in_pipe);
+ 		if (!sg) {
+ 			retval = -ENOMEM;
+ 			break;

commit 49718f0fb8c9af192b33d8af3a2826db04025371
+Author: Alan Stern 
+Date:   Mon Aug 17 11:02:42 2015 -0400
+
+    SCSI: Fix NULL pointer dereference in runtime PM
+    
+    The routines in scsi_rpm.c assume that if a runtime-PM callback is
+    invoked for a SCSI device, it can only mean that the device's driver
+    has asked the block layer to handle the runtime power management (by
+    calling blk_pm_runtime_init(), which among other things sets q->dev).
+    
+    However, this assumption turns out to be wrong for things like the ses
+    driver.  Normally ses devices are not allowed to do runtime PM, but
+    userspace can override this setting.  If this happens, the kernel gets
+    a NULL pointer dereference when blk_post_runtime_resume() tries to use
+    the uninitialized q->dev pointer.
+    
+    This patch fixes the problem by calling the block layer's runtime-PM
+    routines only if the device's driver really does have a runtime-PM
+    callback routine.  Since ses doesn't define any such callbacks, the
+    crash won't occur.
+    
+    This fixes Bugzilla #101371.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Stanisław Pitucha 
+    Reported-by: Ilan Cohen 
+    Tested-by: Ilan Cohen 
+    Reviewed-by: Johannes Thumshirn 
+    Cc: stable@vger.kernel.org
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
+index 9e43ae1d2163..e4b799837948 100644
+--- a/drivers/scsi/scsi_pm.c
++++ b/drivers/scsi/scsi_pm.c
+@@ -217,15 +217,15 @@ static int sdev_runtime_suspend(struct device *dev)
+ {
+ 	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+ 	struct scsi_device *sdev = to_scsi_device(dev);
+-	int err;
++	int err = 0;
+ 
+-	err = blk_pre_runtime_suspend(sdev->request_queue);
+-	if (err)
+-		return err;
+-	if (pm && pm->runtime_suspend)
++	if (pm && pm->runtime_suspend) {
++		err = blk_pre_runtime_suspend(sdev->request_queue);
++		if (err)
++			return err;
+ 		err = pm->runtime_suspend(dev);
+-	blk_post_runtime_suspend(sdev->request_queue, err);
+-
++		blk_post_runtime_suspend(sdev->request_queue, err);
++	}
+ 	return err;
+ }
+ 
+@@ -248,11 +248,11 @@ static int sdev_runtime_resume(struct device *dev)
+ 	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+ 	int err = 0;
+ 
+-	blk_pre_runtime_resume(sdev->request_queue);
+-	if (pm && pm->runtime_resume)
++	if (pm && pm->runtime_resume) {
++		blk_pre_runtime_resume(sdev->request_queue);
+ 		err = pm->runtime_resume(dev);
+-	blk_post_runtime_resume(sdev->request_queue, err);
+-
++		blk_post_runtime_resume(sdev->request_queue, err);
++	}
+ 	return err;
+ }
+ 

commit c93e64e91248becd0edb8f01723dff9da890e2ab
+Author: Alan Stern 
+Date:   Fri Jan 16 11:32:51 2015 -0500
+
+    usb: udc: core: add device_del() call to error pathway
+    
+    This patch fixes a bug in the error pathway of
+    usb_add_gadget_udc_release() in udc-core.c.  If the udc registration
+    fails, the gadget registration is not fully undone; there's a
+    put_device(&gadget->dev) call but no device_del().
+    
+    CC: 
+    Acked-by: Peter Chen 
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c
+index 362ee8af5fce..89ed5e71a199 100644
+--- a/drivers/usb/gadget/udc/udc-core.c
++++ b/drivers/usb/gadget/udc/udc-core.c
+@@ -323,6 +323,7 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
+ 
+ err3:
+ 	put_device(&udc->dev);
++	device_del(&gadget->dev);
+ 
+ err2:
+ 	put_device(&gadget->dev);

commit 1209544d8a2a6084f58625ca66f5cd77580df53f
+Author: Alan Stern 
+Date:   Wed Jul 8 12:14:56 2015 -0400
+
+    USB: OHCI: fix bad #define in ohci-tmio.c
+    
+    An incorrect definition of CCR_PM_USBPW3 in ohci-tmio.c is a perennial
+    source of invalid diagnoses from static scanners, such as in
+    .  This patch
+    fixes the definition.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: David Binderman 
+    CC: Dmitry Eremin-Solenikov 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c
+index e9a6eec39142..cfcfadfc94fc 100644
+--- a/drivers/usb/host/ohci-tmio.c
++++ b/drivers/usb/host/ohci-tmio.c
+@@ -58,7 +58,7 @@
+ #define CCR_PM_CKRNEN    0x0002
+ #define CCR_PM_USBPW1    0x0004
+ #define CCR_PM_USBPW2    0x0008
+-#define CCR_PM_USBPW3    0x0008
++#define CCR_PM_USBPW3    0x0010
+ #define CCR_PM_PMEE      0x0100
+ #define CCR_PM_PMES      0x8000
+ 

commit 7d8021c967648accd1b78e5e1ddaad655cd2c61f
+Author: Alan Stern 
+Date:   Tue Jun 30 11:25:54 2015 -0400
+
+    USB: OHCI: Fix race between ED unlink and URB submission
+    
+    This patch fixes a bug introduced by commit 977dcfdc6031 ("USB: OHCI:
+    don't lose track of EDs when a controller dies").  The commit changed
+    ed_state from ED_UNLINK to ED_IDLE too early, before finish_urb() had
+    been called.  The user-visible consequence is that the driver
+    occasionally crashes or locks up when an URB is submitted while
+    another URB for the same endpoint is being unlinked.
+    
+    This patch moves the ED state change later, to the right place.  The
+    drawback is that now we may unnecessarily execute some instructions
+    multiple times when a controller dies.  Since controllers dying is an
+    exceptional occurrence, a little wasted time won't matter.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Heiko Przybyl 
+    Tested-by: Heiko Przybyl 
+    Fixes: 977dcfdc60311e7aa571cabf6f39c36dde13339e
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
+index f7d561ed3c23..d029bbe9eb36 100644
+--- a/drivers/usb/host/ohci-q.c
++++ b/drivers/usb/host/ohci-q.c
+@@ -981,10 +981,6 @@ static void finish_unlinks(struct ohci_hcd *ohci)
+ 		int			completed, modified;
+ 		__hc32			*prev;
+ 
+-		/* Is this ED already invisible to the hardware? */
+-		if (ed->state == ED_IDLE)
+-			goto ed_idle;
+-
+ 		/* only take off EDs that the HC isn't using, accounting for
+ 		 * frame counter wraps and EDs with partially retired TDs
+ 		 */
+@@ -1012,12 +1008,10 @@ static void finish_unlinks(struct ohci_hcd *ohci)
+ 		}
+ 
+ 		/* ED's now officially unlinked, hc doesn't see */
+-		ed->state = ED_IDLE;
+ 		ed->hwHeadP &= ~cpu_to_hc32(ohci, ED_H);
+ 		ed->hwNextED = 0;
+ 		wmb();
+ 		ed->hwINFO &= ~cpu_to_hc32(ohci, ED_SKIP | ED_DEQUEUE);
+-ed_idle:
+ 
+ 		/* reentrancy:  if we drop the schedule lock, someone might
+ 		 * have modified this list.  normally it's just prepending
+@@ -1088,6 +1082,7 @@ static void finish_unlinks(struct ohci_hcd *ohci)
+ 		if (list_empty(&ed->td_list)) {
+ 			*last = ed->ed_next;
+ 			ed->ed_next = NULL;
++			ed->state = ED_IDLE;
+ 			list_del(&ed->in_use_list);
+ 		} else if (ohci->rh_state == OHCI_RH_RUNNING) {
+ 			*last = ed->ed_next;

commit 019d8817b1b064c2bacfbcf40fc68184438ad05a
+Author: Alan Stern 
+Date:   Wed Jul 15 14:40:06 2015 +0200
+
+    PM / sleep: Allow devices without runtime PM to do direct-complete
+    
+    Don't unset the direct_complete flag on devices that have runtime PM
+    disabled, if they are runtime suspended.
+    
+    This is needed because otherwise ancestor devices wouldn't be able to
+    do direct_complete without adding runtime PM support to all its
+    descendants.
+    
+    Also removes pm_runtime_suspended_if_enabled() because it's now unused.
+    
+    Signed-off-by: Tomeu Vizoso 
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt
+index d172bce0fd49..8ba6625fdd63 100644
+--- a/Documentation/power/devices.txt
++++ b/Documentation/power/devices.txt
+@@ -341,6 +341,13 @@ the phases are:
+ 	and is entirely responsible for bringing the device back to the
+ 	functional state as appropriate.
+ 
++	Note that this direct-complete procedure applies even if the device is
++	disabled for runtime PM; only the runtime-PM status matters.  It follows
++	that if a device has system-sleep callbacks but does not support runtime
++	PM, then its prepare callback must never return a positive value.  This
++	is because all devices are initially set to runtime-suspended with
++	runtime PM disabled.
++
+     2.	The suspend methods should quiesce the device to stop it from performing
+ 	I/O.  They also may save the device registers and put it into the
+ 	appropriate low-power state, depending on the bus type the device is on,
+diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt
+index e76dc0ad4d2b..0784bc3a2ab5 100644
+--- a/Documentation/power/runtime_pm.txt
++++ b/Documentation/power/runtime_pm.txt
+@@ -445,10 +445,6 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
+   bool pm_runtime_status_suspended(struct device *dev);
+     - return true if the device's runtime PM status is 'suspended'
+ 
+-  bool pm_runtime_suspended_if_enabled(struct device *dev);
+-    - return true if the device's runtime PM status is 'suspended' and its
+-      'power.disable_depth' field is equal to 1
+-
+   void pm_runtime_allow(struct device *dev);
+     - set the power.runtime_auto flag for the device and decrease its usage
+       counter (used by the /sys/devices/.../power/control interface to
+diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
+index 30b7bbfdc558..1710c26ba097 100644
+--- a/drivers/base/power/main.c
++++ b/drivers/base/power/main.c
+@@ -1377,7 +1377,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
+ 	if (dev->power.direct_complete) {
+ 		if (pm_runtime_status_suspended(dev)) {
+ 			pm_runtime_disable(dev);
+-			if (pm_runtime_suspended_if_enabled(dev))
++			if (pm_runtime_status_suspended(dev))
+ 				goto Complete;
+ 
+ 			pm_runtime_enable(dev);
+diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h
+index 30e84d48bfea..3bdbb4189780 100644
+--- a/include/linux/pm_runtime.h
++++ b/include/linux/pm_runtime.h
+@@ -98,11 +98,6 @@ static inline bool pm_runtime_status_suspended(struct device *dev)
+ 	return dev->power.runtime_status == RPM_SUSPENDED;
+ }
+ 
+-static inline bool pm_runtime_suspended_if_enabled(struct device *dev)
+-{
+-	return pm_runtime_status_suspended(dev) && dev->power.disable_depth == 1;
+-}
+-
+ static inline bool pm_runtime_enabled(struct device *dev)
+ {
+ 	return !dev->power.disable_depth;
+@@ -164,7 +159,6 @@ static inline void device_set_run_wake(struct device *dev, bool enable) {}
+ static inline bool pm_runtime_suspended(struct device *dev) { return false; }
+ static inline bool pm_runtime_active(struct device *dev) { return true; }
+ static inline bool pm_runtime_status_suspended(struct device *dev) { return false; }
+-static inline bool pm_runtime_suspended_if_enabled(struct device *dev) { return false; }
+ static inline bool pm_runtime_enabled(struct device *dev) { return false; }
+ 
+ static inline void pm_runtime_no_callbacks(struct device *dev) {}

commit 3091fa77ffb1b91f4ac3ae005efe6213508f7ec1
+Author: Alan Stern 
+Date:   Wed Apr 22 12:11:59 2015 -0400
+
+    USB: don't build PCI quirks if USB support isn't configured
+    
+    The USB PCI quirks code gets built into the kernel whenever CONFIG_PCI
+    is enabled, even if CONFIG_USB is not set.  This can cause unnecessary
+    messages to show up in the kernel log, such as "CONFIG_USB_XHCI_HCD is
+    turned off, defaulting to EHCI" (which makes no sense when the kernel
+    has been configured without host-side USB support).
+    
+    This patch addresses the problem by building pci-quirks.o only when
+    CONFIG_PCI and CONFIG_USB are both enabled.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Toralf Förster 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
+index 65b0b6a58599..972a74a6f428 100644
+--- a/drivers/usb/host/Makefile
++++ b/drivers/usb/host/Makefile
+@@ -24,7 +24,9 @@ endif
+ 
+ obj-$(CONFIG_USB_WHCI_HCD)	+= whci/
+ 
+-obj-$(CONFIG_PCI)		+= pci-quirks.o
++ifneq ($(CONFIG_USB), )
++	obj-$(CONFIG_PCI)	+= pci-quirks.o
++endif
+ 
+ obj-$(CONFIG_USB_XHCI_PCI)	+= xhci-pci.o
+ obj-$(CONFIG_USB_XHCI_PLATFORM) += xhci-plat-hcd.o

commit 96b62a57193494010eed66ca0739c93eb4653162
+Author: Alan Stern 
+Date:   Wed Mar 4 10:31:50 2015 -0500
+
+    gadgetfs: really get rid of switching ->f_op
+    
+    ... for ep0 as well
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Al Viro 
+
+diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
+index c0e25320a3c4..200f9a584064 100644
+--- a/drivers/usb/gadget/legacy/inode.c
++++ b/drivers/usb/gadget/legacy/inode.c
+@@ -909,6 +909,10 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
+ 	enum ep0_state			state;
+ 
+ 	spin_lock_irq (&dev->lock);
++	if (dev->state <= STATE_DEV_OPENED) {
++		retval = -EINVAL;
++		goto done;
++	}
+ 
+ 	/* report fd mode change before acting on it */
+ 	if (dev->setup_abort) {
+@@ -1107,8 +1111,6 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
+ 	struct dev_data		*dev = fd->private_data;
+ 	ssize_t			retval = -ESRCH;
+ 
+-	spin_lock_irq (&dev->lock);
+-
+ 	/* report fd mode change before acting on it */
+ 	if (dev->setup_abort) {
+ 		dev->setup_abort = 0;
+@@ -1154,7 +1156,6 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
+ 	} else
+ 		DBG (dev, "fail %s, state %d\n", __func__, dev->state);
+ 
+-	spin_unlock_irq (&dev->lock);
+ 	return retval;
+ }
+ 
+@@ -1201,6 +1202,9 @@ ep0_poll (struct file *fd, poll_table *wait)
+        struct dev_data         *dev = fd->private_data;
+        int                     mask = 0;
+ 
++	if (dev->state <= STATE_DEV_OPENED)
++		return DEFAULT_POLLMASK;
++
+        poll_wait(fd, &dev->wait, wait);
+ 
+        spin_lock_irq (&dev->lock);
+@@ -1236,19 +1240,6 @@ static long dev_ioctl (struct file *fd, unsigned code, unsigned long value)
+ 	return ret;
+ }
+ 
+-/* used after device configuration */
+-static const struct file_operations ep0_io_operations = {
+-	.owner =	THIS_MODULE,
+-	.llseek =	no_llseek,
+-
+-	.read =		ep0_read,
+-	.write =	ep0_write,
+-	.fasync =	ep0_fasync,
+-	.poll =		ep0_poll,
+-	.unlocked_ioctl =	dev_ioctl,
+-	.release =	dev_release,
+-};
+-
+ /*----------------------------------------------------------------------*/
+ 
+ /* The in-kernel gadget driver handles most ep0 issues, in particular
+@@ -1772,6 +1763,14 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
+ 	u32			tag;
+ 	char			*kbuf;
+ 
++	spin_lock_irq(&dev->lock);
++	if (dev->state > STATE_DEV_OPENED) {
++		value = ep0_write(fd, buf, len, ptr);
++		spin_unlock_irq(&dev->lock);
++		return value;
++	}
++	spin_unlock_irq(&dev->lock);
++
+ 	if (len < (USB_DT_CONFIG_SIZE + USB_DT_DEVICE_SIZE + 4))
+ 		return -EINVAL;
+ 
+@@ -1845,7 +1844,6 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
+ 		 * on, they can work ... except in cleanup paths that
+ 		 * kick in after the ep0 descriptor is closed.
+ 		 */
+-		fd->f_op = &ep0_io_operations;
+ 		value = len;
+ 	}
+ 	return value;
+@@ -1876,12 +1874,14 @@ dev_open (struct inode *inode, struct file *fd)
+ 	return value;
+ }
+ 
+-static const struct file_operations dev_init_operations = {
++static const struct file_operations ep0_operations = {
+ 	.llseek =	no_llseek,
+ 
+ 	.open =		dev_open,
++	.read =		ep0_read,
+ 	.write =	dev_config,
+ 	.fasync =	ep0_fasync,
++	.poll =		ep0_poll,
+ 	.unlocked_ioctl = dev_ioctl,
+ 	.release =	dev_release,
+ };
+@@ -1997,7 +1997,7 @@ gadgetfs_fill_super (struct super_block *sb, void *opts, int silent)
+ 		goto Enomem;
+ 
+ 	dev->sb = sb;
+-	dev->dentry = gadgetfs_create_file(sb, CHIP, dev, &dev_init_operations);
++	dev->dentry = gadgetfs_create_file(sb, CHIP, dev, &ep0_operations);
+ 	if (!dev->dentry) {
+ 		put_dev(dev);
+ 		goto Enomem;

commit f0c2b68198589249afd2b1f2c4e8de8c03e19c16
+Author: Alan Stern 
+Date:   Fri Feb 13 10:54:53 2015 -0500
+
+    USB: usbfs: don't leak kernel data in siginfo
+    
+    When a signal is delivered, the information in the siginfo structure
+    is copied to userspace.  Good security practice dicatates that the
+    unused fields in this structure should be initialized to 0 so that
+    random kernel stack data isn't exposed to the user.  This patch adds
+    such an initialization to the two places where usbfs raises signals.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Dave Mielke 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 66abdbcfbfa5..11635537c052 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -501,6 +501,7 @@ static void async_completed(struct urb *urb)
+ 	as->status = urb->status;
+ 	signr = as->signr;
+ 	if (signr) {
++		memset(&sinfo, 0, sizeof(sinfo));
+ 		sinfo.si_signo = as->signr;
+ 		sinfo.si_errno = as->status;
+ 		sinfo.si_code = SI_ASYNCIO;
+@@ -2382,6 +2383,7 @@ static void usbdev_remove(struct usb_device *udev)
+ 		wake_up_all(&ps->wait);
+ 		list_del_init(&ps->list);
+ 		if (ps->discsignr) {
++			memset(&sinfo, 0, sizeof(sinfo));
+ 			sinfo.si_signo = ps->discsignr;
+ 			sinfo.si_errno = EPIPE;
+ 			sinfo.si_code = SI_ASYNCIO;

commit c99197902da284b4b723451c1471c45b18537cde
+Author: Alan Stern 
+Date:   Fri Jan 30 12:58:26 2015 -0500
+
+    USB: fix use-after-free bug in usb_hcd_unlink_urb()
+    
+    The usb_hcd_unlink_urb() routine in hcd.c contains two possible
+    use-after-free errors.  The dev_dbg() statement at the end of the
+    routine dereferences urb and urb->dev even though both structures may
+    have been deallocated.
+    
+    This patch fixes the problem by storing urb->dev in a local variable
+    (avoiding the dereference of urb) and moving the dev_dbg() up before
+    the usb_put_dev() call.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Joe Lawrence 
+    Tested-by: Joe Lawrence 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 11cee55ae397..45a915ccd71c 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1618,6 +1618,7 @@ static int unlink1(struct usb_hcd *hcd, struct urb *urb, int status)
+ int usb_hcd_unlink_urb (struct urb *urb, int status)
+ {
+ 	struct usb_hcd		*hcd;
++	struct usb_device	*udev = urb->dev;
+ 	int			retval = -EIDRM;
+ 	unsigned long		flags;
+ 
+@@ -1629,20 +1630,19 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
+ 	spin_lock_irqsave(&hcd_urb_unlink_lock, flags);
+ 	if (atomic_read(&urb->use_count) > 0) {
+ 		retval = 0;
+-		usb_get_dev(urb->dev);
++		usb_get_dev(udev);
+ 	}
+ 	spin_unlock_irqrestore(&hcd_urb_unlink_lock, flags);
+ 	if (retval == 0) {
+ 		hcd = bus_to_hcd(urb->dev->bus);
+ 		retval = unlink1(hcd, urb, status);
+-		usb_put_dev(urb->dev);
++		if (retval == 0)
++			retval = -EINPROGRESS;
++		else if (retval != -EIDRM && retval != -EBUSY)
++			dev_dbg(&udev->dev, "hcd_unlink_urb %p fail %d\n",
++					urb, retval);
++		usb_put_dev(udev);
+ 	}
+-
+-	if (retval == 0)
+-		retval = -EINPROGRESS;
+-	else if (retval != -EIDRM && retval != -EBUSY)
+-		dev_dbg(&urb->dev->dev, "hcd_unlink_urb %p fail %d\n",
+-				urb, retval);
+ 	return retval;
+ }
+ 

commit 074f9dd55f9cab1b82690ed7e44bcf38b9616ce0
+Author: Alan Stern 
+Date:   Thu Jan 29 15:05:04 2015 -0500
+
+    USB: add flag for HCDs that can't receive wakeup requests (isp1760-hcd)
+    
+    Currently the USB stack assumes that all host controller drivers are
+    capable of receiving wakeup requests from downstream devices.
+    However, this isn't true for the isp1760-hcd driver, which means that
+    it isn't safe to do a runtime suspend of any device attached to a
+    root-hub port if the device requires wakeup.
+    
+    This patch adds a "cant_recv_wakeups" flag to the usb_hcd structure
+    and sets the flag in isp1760-hcd.  The core is modified to prevent a
+    direct child of the root hub from being put into runtime suspend with
+    wakeup enabled if the flag is set.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Nicolas Pitre 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index c76ec9758ce3..818369afff63 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1780,6 +1780,18 @@ static int autosuspend_check(struct usb_device *udev)
+ 		dev_dbg(&udev->dev, "remote wakeup needed for autosuspend\n");
+ 		return -EOPNOTSUPP;
+ 	}
++
++	/*
++	 * If the device is a direct child of the root hub and the HCD
++	 * doesn't handle wakeup requests, don't allow autosuspend when
++	 * wakeup is needed.
++	 */
++	if (w && udev->parent == udev->bus->root_hub &&
++			bus_to_hcd(udev->bus)->cant_recv_wakeups) {
++		dev_dbg(&udev->dev, "HCD doesn't handle wakeup requests\n");
++		return -EOPNOTSUPP;
++	}
++
+ 	udev->do_remote_wakeup = w;
+ 	return 0;
+ }
+diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c
+index dbba455884f4..cecf39a220e7 100644
+--- a/drivers/usb/host/isp1760-hcd.c
++++ b/drivers/usb/host/isp1760-hcd.c
+@@ -2245,6 +2245,9 @@ struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len,
+ 	hcd->rsrc_start = res_start;
+ 	hcd->rsrc_len = res_len;
+ 
++	/* This driver doesn't support wakeup requests */
++	hcd->cant_recv_wakeups = 1;
++
+ 	ret = usb_add_hcd(hcd, irq, irqflags);
+ 	if (ret)
+ 		goto err_unmap;
+diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
+index 8968f616e414..68b1e836dff1 100644
+--- a/include/linux/usb/hcd.h
++++ b/include/linux/usb/hcd.h
+@@ -146,6 +146,8 @@ struct usb_hcd {
+ 	unsigned		amd_resume_bug:1; /* AMD remote wakeup quirk */
+ 	unsigned		can_do_streams:1; /* HC supports streams */
+ 	unsigned		tpl_support:1; /* OTG & EH TPL support */
++	unsigned		cant_recv_wakeups:1;
++			/* wakeup requests from downstream aren't received */
+ 
+ 	unsigned int		irq;		/* irq allocated */
+ 	void __iomem		*regs;		/* device memory/io */

commit 3f2cee73b650921b2e214bf487b2061a1c266504
+Author: Alan Stern 
+Date:   Thu Jan 29 11:29:13 2015 -0500
+
+    USB: usbfs: allow URBs to be reaped after disconnection
+    
+    The usbfs API has a peculiar hole: Users are not allowed to reap their
+    URBs after the device has been disconnected.  There doesn't seem to be
+    any good reason for this; it is an ad-hoc inconsistency.
+    
+    The patch allows users to issue the USBDEVFS_REAPURB and
+    USBDEVFS_REAPURBNDELAY ioctls (together with their 32-bit counterparts
+    on 64-bit systems) even after the device is gone.  If no URBs are
+    pending for a disconnected device then the ioctls will return -ENODEV
+    rather than -EAGAIN, because obviously no new URBs will ever be able
+    to complete.
+    
+    The patch also adds a new capability flag for
+    USBDEVFS_GET_CAPABILITIES to indicate that the reap-after-disconnect
+    feature is supported.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Chris Dickens 
+    Acked-by: Hans de Goede 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 0b59731c3021..66abdbcfbfa5 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -1689,7 +1689,7 @@ static struct async *reap_as(struct usb_dev_state *ps)
+ 	for (;;) {
+ 		__set_current_state(TASK_INTERRUPTIBLE);
+ 		as = async_getcompleted(ps);
+-		if (as)
++		if (as || !connected(ps))
+ 			break;
+ 		if (signal_pending(current))
+ 			break;
+@@ -1712,7 +1712,7 @@ static int proc_reapurb(struct usb_dev_state *ps, void __user *arg)
+ 	}
+ 	if (signal_pending(current))
+ 		return -EINTR;
+-	return -EIO;
++	return -ENODEV;
+ }
+ 
+ static int proc_reapurbnonblock(struct usb_dev_state *ps, void __user *arg)
+@@ -1721,10 +1721,11 @@ static int proc_reapurbnonblock(struct usb_dev_state *ps, void __user *arg)
+ 	struct async *as;
+ 
+ 	as = async_getcompleted(ps);
+-	retval = -EAGAIN;
+ 	if (as) {
+ 		retval = processcompl(as, (void __user * __user *)arg);
+ 		free_async(as);
++	} else {
++		retval = (connected(ps) ? -EAGAIN : -ENODEV);
+ 	}
+ 	return retval;
+ }
+@@ -1854,7 +1855,7 @@ static int proc_reapurb_compat(struct usb_dev_state *ps, void __user *arg)
+ 	}
+ 	if (signal_pending(current))
+ 		return -EINTR;
+-	return -EIO;
++	return -ENODEV;
+ }
+ 
+ static int proc_reapurbnonblock_compat(struct usb_dev_state *ps, void __user *arg)
+@@ -1862,11 +1863,12 @@ static int proc_reapurbnonblock_compat(struct usb_dev_state *ps, void __user *ar
+ 	int retval;
+ 	struct async *as;
+ 
+-	retval = -EAGAIN;
+ 	as = async_getcompleted(ps);
+ 	if (as) {
+ 		retval = processcompl_compat(as, (void __user * __user *)arg);
+ 		free_async(as);
++	} else {
++		retval = (connected(ps) ? -EAGAIN : -ENODEV);
+ 	}
+ 	return retval;
+ }
+@@ -2038,7 +2040,8 @@ static int proc_get_capabilities(struct usb_dev_state *ps, void __user *arg)
+ {
+ 	__u32 caps;
+ 
+-	caps = USBDEVFS_CAP_ZERO_PACKET | USBDEVFS_CAP_NO_PACKET_SIZE_LIM;
++	caps = USBDEVFS_CAP_ZERO_PACKET | USBDEVFS_CAP_NO_PACKET_SIZE_LIM |
++			USBDEVFS_CAP_REAP_AFTER_DISCONNECT;
+ 	if (!ps->dev->bus->no_stop_on_short)
+ 		caps |= USBDEVFS_CAP_BULK_CONTINUATION;
+ 	if (ps->dev->bus->sg_tablesize)
+@@ -2138,6 +2141,32 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
+ 		return -EPERM;
+ 
+ 	usb_lock_device(dev);
++
++	/* Reap operations are allowed even after disconnection */
++	switch (cmd) {
++	case USBDEVFS_REAPURB:
++		snoop(&dev->dev, "%s: REAPURB\n", __func__);
++		ret = proc_reapurb(ps, p);
++		goto done;
++
++	case USBDEVFS_REAPURBNDELAY:
++		snoop(&dev->dev, "%s: REAPURBNDELAY\n", __func__);
++		ret = proc_reapurbnonblock(ps, p);
++		goto done;
++
++#ifdef CONFIG_COMPAT
++	case USBDEVFS_REAPURB32:
++		snoop(&dev->dev, "%s: REAPURB32\n", __func__);
++		ret = proc_reapurb_compat(ps, p);
++		goto done;
++
++	case USBDEVFS_REAPURBNDELAY32:
++		snoop(&dev->dev, "%s: REAPURBNDELAY32\n", __func__);
++		ret = proc_reapurbnonblock_compat(ps, p);
++		goto done;
++#endif
++	}
++
+ 	if (!connected(ps)) {
+ 		usb_unlock_device(dev);
+ 		return -ENODEV;
+@@ -2231,16 +2260,6 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
+ 			inode->i_mtime = CURRENT_TIME;
+ 		break;
+ 
+-	case USBDEVFS_REAPURB32:
+-		snoop(&dev->dev, "%s: REAPURB32\n", __func__);
+-		ret = proc_reapurb_compat(ps, p);
+-		break;
+-
+-	case USBDEVFS_REAPURBNDELAY32:
+-		snoop(&dev->dev, "%s: REAPURBNDELAY32\n", __func__);
+-		ret = proc_reapurbnonblock_compat(ps, p);
+-		break;
+-
+ 	case USBDEVFS_IOCTL32:
+ 		snoop(&dev->dev, "%s: IOCTL32\n", __func__);
+ 		ret = proc_ioctl_compat(ps, ptr_to_compat(p));
+@@ -2252,16 +2271,6 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
+ 		ret = proc_unlinkurb(ps, p);
+ 		break;
+ 
+-	case USBDEVFS_REAPURB:
+-		snoop(&dev->dev, "%s: REAPURB\n", __func__);
+-		ret = proc_reapurb(ps, p);
+-		break;
+-
+-	case USBDEVFS_REAPURBNDELAY:
+-		snoop(&dev->dev, "%s: REAPURBNDELAY\n", __func__);
+-		ret = proc_reapurbnonblock(ps, p);
+-		break;
+-
+ 	case USBDEVFS_DISCSIGNAL:
+ 		snoop(&dev->dev, "%s: DISCSIGNAL\n", __func__);
+ 		ret = proc_disconnectsignal(ps, p);
+@@ -2304,6 +2313,8 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
+ 		ret = proc_free_streams(ps, p);
+ 		break;
+ 	}
++
++ done:
+ 	usb_unlock_device(dev);
+ 	if (ret >= 0)
+ 		inode->i_atime = CURRENT_TIME;
+diff --git a/include/uapi/linux/usbdevice_fs.h b/include/uapi/linux/usbdevice_fs.h
+index abe5f4bd4d82..019ba1e0799a 100644
+--- a/include/uapi/linux/usbdevice_fs.h
++++ b/include/uapi/linux/usbdevice_fs.h
+@@ -128,11 +128,12 @@ struct usbdevfs_hub_portinfo {
+ 	char port [127];	/* e.g. port 3 connects to device 27 */
+ };
+ 
+-/* Device capability flags */
++/* System and bus capability flags */
+ #define USBDEVFS_CAP_ZERO_PACKET		0x01
+ #define USBDEVFS_CAP_BULK_CONTINUATION		0x02
+ #define USBDEVFS_CAP_NO_PACKET_SIZE_LIM		0x04
+ #define USBDEVFS_CAP_BULK_SCATTER_GATHER	0x08
++#define USBDEVFS_CAP_REAP_AFTER_DISCONNECT	0x10
+ 
+ /* USBDEVFS_DISCONNECT_CLAIM flags & struct */
+ 

commit 524134d422316a59d5464ccbc12036bbe90c5563
+Author: Alan Stern 
+Date:   Wed Jan 21 14:02:43 2015 -0500
+
+    USB: don't cancel queued resets when unbinding drivers
+    
+    The USB stack provides a mechanism for drivers to request an
+    asynchronous device reset (usb_queue_reset_device()).  The mechanism
+    uses a work item (reset_ws) embedded in the usb_interface structure
+    used by the driver, and the reset is carried out by a work queue
+    routine.
+    
+    The asynchronous reset can race with driver unbinding.  When this
+    happens, we try to cancel the queued reset before unbinding the
+    driver, on the theory that the driver won't care about any resets once
+    it is unbound.
+    
+    However, thanks to the fact that lockdep now tracks work queue
+    accesses, this can provoke a lockdep warning in situations where the
+    device reset causes another interface's driver to be unbound; see
+    
+            http://marc.info/?l=linux-usb&m=141893165203776&w=2
+    
+    for an example.  The reason is that the work routine for reset_ws in
+    one interface calls cancel_queued_work() for the reset_ws in another
+    interface.  Lockdep thinks this might lead to a work routine trying to
+    cancel itself.  The simplest solution is not to cancel queued resets
+    when unbinding drivers.
+    
+    This means we now need to acquire a reference to the usb_interface
+    when queuing a reset_ws work item and to drop the reference when the
+    work routine finishes.  We also need to make sure that the
+    usb_interface structure doesn't outlive its parent usb_device; this
+    means acquiring and dropping a reference when the interface is created
+    and destroyed.
+    
+    In addition, cancelling a queued reset can fail (if the device is in
+    the middle of an earlier reset), and this can cause usb_reset_device()
+    to try to rebind an interface that has been deallocated (see
+    http://marc.info/?l=linux-usb&m=142175717016628&w=2 for details).
+    Acquiring the extra references prevents this failure.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Russell King - ARM Linux 
+    Reported-by: Olivier Sobrie 
+    Tested-by: Olivier Sobrie 
+    Cc: stable  # 3.19
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 874dec31a111..c76ec9758ce3 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -275,21 +275,6 @@ static int usb_unbind_device(struct device *dev)
+ 	return 0;
+ }
+ 
+-/*
+- * Cancel any pending scheduled resets
+- *
+- * [see usb_queue_reset_device()]
+- *
+- * Called after unconfiguring / when releasing interfaces. See
+- * comments in __usb_queue_reset_device() regarding
+- * udev->reset_running.
+- */
+-static void usb_cancel_queued_reset(struct usb_interface *iface)
+-{
+-	if (iface->reset_running == 0)
+-		cancel_work_sync(&iface->reset_ws);
+-}
+-
+ /* called from driver core with dev locked */
+ static int usb_probe_interface(struct device *dev)
+ {
+@@ -380,7 +365,6 @@ static int usb_probe_interface(struct device *dev)
+ 	usb_set_intfdata(intf, NULL);
+ 	intf->needs_remote_wakeup = 0;
+ 	intf->condition = USB_INTERFACE_UNBOUND;
+-	usb_cancel_queued_reset(intf);
+ 
+ 	/* If the LPM disable succeeded, balance the ref counts. */
+ 	if (!lpm_disable_error)
+@@ -425,7 +409,6 @@ static int usb_unbind_interface(struct device *dev)
+ 		usb_disable_interface(udev, intf, false);
+ 
+ 	driver->disconnect(intf);
+-	usb_cancel_queued_reset(intf);
+ 
+ 	/* Free streams */
+ 	for (i = 0, j = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index aeb50bb6ba9c..b4bfa3ac4b12 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -5589,26 +5589,19 @@ EXPORT_SYMBOL_GPL(usb_reset_device);
+  *   possible; depending on how the driver attached to each interface
+  *   handles ->pre_reset(), the second reset might happen or not.
+  *
+- * - If a driver is unbound and it had a pending reset, the reset will
+- *   be cancelled.
++ * - If the reset is delayed so long that the interface is unbound from
++ *   its driver, the reset will be skipped.
+  *
+- * - This function can be called during .probe() or .disconnect()
+- *   times. On return from .disconnect(), any pending resets will be
+- *   cancelled.
+- *
+- * There is no no need to lock/unlock the @reset_ws as schedule_work()
+- * does its own.
+- *
+- * NOTE: We don't do any reference count tracking because it is not
+- *     needed. The lifecycle of the work_struct is tied to the
+- *     usb_interface. Before destroying the interface we cancel the
+- *     work_struct, so the fact that work_struct is queued and or
+- *     running means the interface (and thus, the device) exist and
+- *     are referenced.
++ * - This function can be called during .probe().  It can also be called
++ *   during .disconnect(), but doing so is pointless because the reset
++ *   will not occur.  If you really want to reset the device during
++ *   .disconnect(), call usb_reset_device() directly -- but watch out
++ *   for nested unbinding issues!
+  */
+ void usb_queue_reset_device(struct usb_interface *iface)
+ {
+-	schedule_work(&iface->reset_ws);
++	if (schedule_work(&iface->reset_ws))
++		usb_get_intf(iface);
+ }
+ EXPORT_SYMBOL_GPL(usb_queue_reset_device);
+ 
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index f7b7713cfb2a..f368d2053da5 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1551,6 +1551,7 @@ static void usb_release_interface(struct device *dev)
+ 			altsetting_to_usb_interface_cache(intf->altsetting);
+ 
+ 	kref_put(&intfc->ref, usb_release_interface_cache);
++	usb_put_dev(interface_to_usbdev(intf));
+ 	kfree(intf);
+ }
+ 
+@@ -1626,24 +1627,6 @@ static struct usb_interface_assoc_descriptor *find_iad(struct usb_device *dev,
+ 
+ /*
+  * Internal function to queue a device reset
+- *
+- * This is initialized into the workstruct in 'struct
+- * usb_device->reset_ws' that is launched by
+- * message.c:usb_set_configuration() when initializing each 'struct
+- * usb_interface'.
+- *
+- * It is safe to get the USB device without reference counts because
+- * the life cycle of @iface is bound to the life cycle of @udev. Then,
+- * this function will be ran only if @iface is alive (and before
+- * freeing it any scheduled instances of it will have been cancelled).
+- *
+- * We need to set a flag (usb_dev->reset_running) because when we call
+- * the reset, the interfaces might be unbound. The current interface
+- * cannot try to remove the queued work as it would cause a deadlock
+- * (you cannot remove your work from within your executing
+- * workqueue). This flag lets it know, so that
+- * usb_cancel_queued_reset() doesn't try to do it.
+- *
+  * See usb_queue_reset_device() for more details
+  */
+ static void __usb_queue_reset_device(struct work_struct *ws)
+@@ -1655,11 +1638,10 @@ static void __usb_queue_reset_device(struct work_struct *ws)
+ 
+ 	rc = usb_lock_device_for_reset(udev, iface);
+ 	if (rc >= 0) {
+-		iface->reset_running = 1;
+ 		usb_reset_device(udev);
+-		iface->reset_running = 0;
+ 		usb_unlock_device(udev);
+ 	}
++	usb_put_intf(iface);	/* Undo _get_ in usb_queue_reset_device() */
+ }
+ 
+ 
+@@ -1854,6 +1836,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 		dev_set_name(&intf->dev, "%d-%s:%d.%d",
+ 			dev->bus->busnum, dev->devpath,
+ 			configuration, alt->desc.bInterfaceNumber);
++		usb_get_dev(dev);
+ 	}
+ 	kfree(new_interfaces);
+ 
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 4add5661080a..7ee1b5c3b4cb 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -127,10 +127,6 @@ enum usb_interface_condition {
+  *	to the sysfs representation for that device.
+  * @pm_usage_cnt: PM usage counter for this interface
+  * @reset_ws: Used for scheduling resets from atomic context.
+- * @reset_running: set to 1 if the interface is currently running a
+- *      queued reset so that usb_cancel_queued_reset() doesn't try to
+- *      remove from the workqueue when running inside the worker
+- *      thread. See __usb_queue_reset_device().
+  * @resetting_device: USB core reset the device, so use alt setting 0 as
+  *	current; needs bandwidth alloc after reset.
+  *
+@@ -181,7 +177,6 @@ struct usb_interface {
+ 	unsigned needs_remote_wakeup:1;	/* driver requires remote wakeup */
+ 	unsigned needs_altsetting0:1;	/* switch to altsetting 0 is pending */
+ 	unsigned needs_binding:1;	/* needs delayed unbind/rebind */
+-	unsigned reset_running:1;
+ 	unsigned resetting_device:1;	/* true: bandwidth alloc after reset */
+ 
+ 	struct device dev;		/* interface specific device info */

commit c401e7b4a808d50ab53ef45cb8d0b99b238bf2c9
+Author: Alan Stern 
+Date:   Thu Dec 4 10:22:57 2014 -0500
+
+    USB: EHCI: adjust error return code
+    
+    The USB stack uses error code -ENOSPC to indicate that the periodic
+    schedule is too full, with insufficient bandwidth to accommodate a new
+    allocation.  It uses -EFBIG to indicate that an isochronous transfer
+    could not be linked into the schedule because it would exceed the
+    number of isochronous packets the host controller driver can handle
+    (generally because the new transfer would extend too far into the
+    future).
+    
+    ehci-hcd uses the wrong error code at one point.  This patch fixes it,
+    along with a misleading comment and debugging message.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index c399606f154e..f9a332775c47 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1604,11 +1604,11 @@ iso_stream_schedule (
+ 	 */
+ 	now2 = (now - base) & (mod - 1);
+ 
+-	/* Is the schedule already full? */
++	/* Is the schedule about to wrap around? */
+ 	if (unlikely(!empty && start < period)) {
+-		ehci_dbg(ehci, "iso sched full %p (%u-%u < %u mod %u)\n",
++		ehci_dbg(ehci, "request %p would overflow (%u-%u < %u mod %u)\n",
+ 				urb, stream->next_uframe, base, period, mod);
+-		status = -ENOSPC;
++		status = -EFBIG;
+ 		goto fail;
+ 	}
+ 

commit 6d89252a998a695ecb0348fc2d717dc33d90cae9
+Author: Alan Stern 
+Date:   Thu Dec 4 10:21:56 2014 -0500
+
+    USB: EHCI: fix initialization bug in iso_stream_schedule()
+    
+    Commit c3ee9b76aa93 (EHCI: improved logic for isochronous scheduling)
+    introduced the idea of using ehci->last_iso_frame as the origin (or
+    base) for the circular calculations involved in modifying the
+    isochronous schedule.  However, the new code it added used
+    ehci->last_iso_frame before the value was properly initialized.  This
+    patch rectifies the mistake by moving the initialization lines earlier
+    in iso_stream_schedule().
+    
+    This fixes Bugzilla #72891.
+    
+    Signed-off-by: Alan Stern 
+    Fixes: c3ee9b76aa93
+    Reported-by: Joe Bryant 
+    Tested-by: Joe Bryant 
+    Tested-by: Martin Long 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index e113fd73aeae..c399606f154e 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1581,6 +1581,10 @@ iso_stream_schedule (
+ 	else
+ 		next = (now + 2 + 7) & ~0x07;	/* full frame cache */
+ 
++	/* If needed, initialize last_iso_frame so that this URB will be seen */
++	if (ehci->isoc_count == 0)
++		ehci->last_iso_frame = now >> 3;
++
+ 	/*
+ 	 * Use ehci->last_iso_frame as the base.  There can't be any
+ 	 * TDs scheduled for earlier than that.
+@@ -1671,10 +1675,6 @@ iso_stream_schedule (
+ 	urb->start_frame = start & (mod - 1);
+ 	if (!stream->highspeed)
+ 		urb->start_frame >>= 3;
+-
+-	/* Make sure scan_isoc() sees these */
+-	if (ehci->isoc_count == 0)
+-		ehci->last_iso_frame = now >> 3;
+ 	return status;
+ 
+  fail:

commit 511833acfc06c013d453e288f483c682c60ffbff
+Author: Alan Stern 
+Date:   Fri Nov 21 10:44:49 2014 -0500
+
+    SCSI: fix regression in scsi_send_eh_cmnd()
+    
+    Commit ac61d1955934 (scsi: set correct completion code in
+    scsi_send_eh_cmnd()) introduced a bug.  It changed the stored return
+    value from a queuecommand call, but it didn't take into account that
+    the return value was used again later on.  This patch fixes the bug by
+    changing the later usage.
+    
+    There is a big comment in the middle of scsi_send_eh_cmnd() which
+    does a good job of explaining how the routine works.  But it mentions
+    a "rtn = FAILURE" value that doesn't exist in the code.  This patch
+    adjusts the code to match the comment (I assume the comment is right
+    and the code is wrong).
+    
+    This fixes Bugzilla #88341.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Андрей Аладьев 
+    Tested-by: Андрей Аладьев 
+    Fixes: ac61d19559349e205dad7b5122b281419aa74a82
+    Acked-by: Hannes Reinecke 
+    Cc: 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
+index e42fff6e8c10..8afb01604d51 100644
+--- a/drivers/scsi/scsi_error.c
++++ b/drivers/scsi/scsi_error.c
+@@ -1041,7 +1041,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
+ 		}
+ 		/* signal not to enter either branch of the if () below */
+ 		timeleft = 0;
+-		rtn = NEEDS_RETRY;
++		rtn = FAILED;
+ 	} else {
+ 		timeleft = wait_for_completion_timeout(&done, timeout);
+ 		rtn = SUCCESS;
+@@ -1081,7 +1081,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
+ 			rtn = FAILED;
+ 			break;
+ 		}
+-	} else if (!rtn) {
++	} else if (rtn != FAILED) {
+ 		scsi_abort_eh_cmnd(scmd);
+ 		rtn = FAILED;
+ 	}

commit 2193dda5eec60373c7a061c129c6ab9d658f78e9
+Author: Alan Stern 
+Date:   Tue Nov 25 12:28:46 2014 +0100
+
+    USB: host: Remove ehci-octeon and ohci-octeon drivers
+    
+    Remove special-purpose octeon drivers and instead use ehci-platform
+    and ohci-platform as suggested with
+    http://marc.info/?l=linux-mips&m=140139694721623&w=2
+    
+    [andreas.herrmann:
+        fixed compile error]
+    
+    Cc: David Daney 
+    Cc: Alex Smith 
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Andreas Herrmann 
+    Acked-by: Ralf Baechle 
+    Tested-by: Aaro Koskinen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c
+index 6df0f4d8f197..b67ddf0f8bcd 100644
+--- a/arch/mips/cavium-octeon/octeon-platform.c
++++ b/arch/mips/cavium-octeon/octeon-platform.c
+@@ -7,22 +7,27 @@
+  * Copyright (C) 2008 Wind River Systems
+  */
+ 
++#include 
+ #include 
+ #include 
+ #include 
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+ #include 
+ #include 
++#include 
++#include 
+ 
+ #include 
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ /* Octeon Random Number Generator.  */
+ static int __init octeon_rng_device_init(void)
+@@ -68,6 +73,229 @@ device_initcall(octeon_rng_device_init);
+ 
+ #ifdef CONFIG_USB
+ 
++static DEFINE_MUTEX(octeon2_usb_clocks_mutex);
++
++static int octeon2_usb_clock_start_cnt;
++
++static void octeon2_usb_clocks_start(void)
++{
++	u64 div;
++	union cvmx_uctlx_if_ena if_ena;
++	union cvmx_uctlx_clk_rst_ctl clk_rst_ctl;
++	union cvmx_uctlx_uphy_ctl_status uphy_ctl_status;
++	union cvmx_uctlx_uphy_portx_ctl_status port_ctl_status;
++	int i;
++	unsigned long io_clk_64_to_ns;
++
++
++	mutex_lock(&octeon2_usb_clocks_mutex);
++
++	octeon2_usb_clock_start_cnt++;
++	if (octeon2_usb_clock_start_cnt != 1)
++		goto exit;
++
++	io_clk_64_to_ns = 64000000000ull / octeon_get_io_clock_rate();
++
++	/*
++	 * Step 1: Wait for voltages stable.  That surely happened
++	 * before starting the kernel.
++	 *
++	 * Step 2: Enable  SCLK of UCTL by writing UCTL0_IF_ENA[EN] = 1
++	 */
++	if_ena.u64 = 0;
++	if_ena.s.en = 1;
++	cvmx_write_csr(CVMX_UCTLX_IF_ENA(0), if_ena.u64);
++
++	/* Step 3: Configure the reference clock, PHY, and HCLK */
++	clk_rst_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0));
++
++	/*
++	 * If the UCTL looks like it has already been started, skip
++	 * the initialization, otherwise bus errors are obtained.
++	 */
++	if (clk_rst_ctl.s.hrst)
++		goto end_clock;
++	/* 3a */
++	clk_rst_ctl.s.p_por = 1;
++	clk_rst_ctl.s.hrst = 0;
++	clk_rst_ctl.s.p_prst = 0;
++	clk_rst_ctl.s.h_clkdiv_rst = 0;
++	clk_rst_ctl.s.o_clkdiv_rst = 0;
++	clk_rst_ctl.s.h_clkdiv_en = 0;
++	clk_rst_ctl.s.o_clkdiv_en = 0;
++	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
++
++	/* 3b */
++	/* 12MHz crystal. */
++	clk_rst_ctl.s.p_refclk_sel = 0;
++	clk_rst_ctl.s.p_refclk_div = 0;
++	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
++
++	/* 3c */
++	div = octeon_get_io_clock_rate() / 130000000ull;
++
++	switch (div) {
++	case 0:
++		div = 1;
++		break;
++	case 1:
++	case 2:
++	case 3:
++	case 4:
++		break;
++	case 5:
++		div = 4;
++		break;
++	case 6:
++	case 7:
++		div = 6;
++		break;
++	case 8:
++	case 9:
++	case 10:
++	case 11:
++		div = 8;
++		break;
++	default:
++		div = 12;
++		break;
++	}
++	clk_rst_ctl.s.h_div = div;
++	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
++	/* Read it back, */
++	clk_rst_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0));
++	clk_rst_ctl.s.h_clkdiv_en = 1;
++	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
++	/* 3d */
++	clk_rst_ctl.s.h_clkdiv_rst = 1;
++	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
++
++	/* 3e: delay 64 io clocks */
++	ndelay(io_clk_64_to_ns);
++
++	/*
++	 * Step 4: Program the power-on reset field in the UCTL
++	 * clock-reset-control register.
++	 */
++	clk_rst_ctl.s.p_por = 0;
++	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
++
++	/* Step 5:    Wait 1 ms for the PHY clock to start. */
++	mdelay(1);
++
++	/*
++	 * Step 6: Program the reset input from automatic test
++	 * equipment field in the UPHY CSR
++	 */
++	uphy_ctl_status.u64 = cvmx_read_csr(CVMX_UCTLX_UPHY_CTL_STATUS(0));
++	uphy_ctl_status.s.ate_reset = 1;
++	cvmx_write_csr(CVMX_UCTLX_UPHY_CTL_STATUS(0), uphy_ctl_status.u64);
++
++	/* Step 7: Wait for at least 10ns. */
++	ndelay(10);
++
++	/* Step 8: Clear the ATE_RESET field in the UPHY CSR. */
++	uphy_ctl_status.s.ate_reset = 0;
++	cvmx_write_csr(CVMX_UCTLX_UPHY_CTL_STATUS(0), uphy_ctl_status.u64);
++
++	/*
++	 * Step 9: Wait for at least 20ns for UPHY to output PHY clock
++	 * signals and OHCI_CLK48
++	 */
++	ndelay(20);
++
++	/* Step 10: Configure the OHCI_CLK48 and OHCI_CLK12 clocks. */
++	/* 10a */
++	clk_rst_ctl.s.o_clkdiv_rst = 1;
++	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
++
++	/* 10b */
++	clk_rst_ctl.s.o_clkdiv_en = 1;
++	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
++
++	/* 10c */
++	ndelay(io_clk_64_to_ns);
++
++	/*
++	 * Step 11: Program the PHY reset field:
++	 * UCTL0_CLK_RST_CTL[P_PRST] = 1
++	 */
++	clk_rst_ctl.s.p_prst = 1;
++	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
++
++	/* Step 12: Wait 1 uS. */
++	udelay(1);
++
++	/* Step 13: Program the HRESET_N field: UCTL0_CLK_RST_CTL[HRST] = 1 */
++	clk_rst_ctl.s.hrst = 1;
++	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
++
++end_clock:
++	/* Now we can set some other registers.  */
++
++	for (i = 0; i <= 1; i++) {
++		port_ctl_status.u64 =
++			cvmx_read_csr(CVMX_UCTLX_UPHY_PORTX_CTL_STATUS(i, 0));
++		/* Set txvreftune to 15 to obtain compliant 'eye' diagram. */
++		port_ctl_status.s.txvreftune = 15;
++		port_ctl_status.s.txrisetune = 1;
++		port_ctl_status.s.txpreemphasistune = 1;
++		cvmx_write_csr(CVMX_UCTLX_UPHY_PORTX_CTL_STATUS(i, 0),
++			       port_ctl_status.u64);
++	}
++
++	/* Set uSOF cycle period to 60,000 bits. */
++	cvmx_write_csr(CVMX_UCTLX_EHCI_FLA(0), 0x20ull);
++exit:
++	mutex_unlock(&octeon2_usb_clocks_mutex);
++}
++
++static void octeon2_usb_clocks_stop(void)
++{
++	mutex_lock(&octeon2_usb_clocks_mutex);
++	octeon2_usb_clock_start_cnt--;
++	mutex_unlock(&octeon2_usb_clocks_mutex);
++}
++
++static int octeon_ehci_power_on(struct platform_device *pdev)
++{
++	octeon2_usb_clocks_start();
++	return 0;
++}
++
++static void octeon_ehci_power_off(struct platform_device *pdev)
++{
++	octeon2_usb_clocks_stop();
++}
++
++static struct usb_ehci_pdata octeon_ehci_pdata = {
++	/* Octeon EHCI matches CPU endianness. */
++#ifdef __BIG_ENDIAN
++	.big_endian_mmio	= 1,
++#endif
++	.power_on	= octeon_ehci_power_on,
++	.power_off	= octeon_ehci_power_off,
++};
++
++static void __init octeon_ehci_hw_start(void)
++{
++	union cvmx_uctlx_ehci_ctl ehci_ctl;
++
++	octeon2_usb_clocks_start();
++
++	ehci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_EHCI_CTL(0));
++	/* Use 64-bit addressing. */
++	ehci_ctl.s.ehci_64b_addr_en = 1;
++	ehci_ctl.s.l2c_addr_msb = 0;
++	ehci_ctl.s.l2c_buff_emod = 1; /* Byte swapped. */
++	ehci_ctl.s.l2c_desc_emod = 1; /* Byte swapped. */
++	cvmx_write_csr(CVMX_UCTLX_EHCI_CTL(0), ehci_ctl.u64);
++
++	octeon2_usb_clocks_stop();
++}
++
++static u64 octeon_ehci_dma_mask = DMA_BIT_MASK(64);
++
+ static int __init octeon_ehci_device_init(void)
+ {
+ 	struct platform_device *pd;
+@@ -88,7 +316,7 @@ static int __init octeon_ehci_device_init(void)
+ 	if (octeon_is_simulation() || usb_disabled())
+ 		return 0; /* No USB in the simulator. */
+ 
+-	pd = platform_device_alloc("octeon-ehci", 0);
++	pd = platform_device_alloc("ehci-platform", 0);
+ 	if (!pd) {
+ 		ret = -ENOMEM;
+ 		goto out;
+@@ -105,6 +333,10 @@ static int __init octeon_ehci_device_init(void)
+ 	if (ret)
+ 		goto fail;
+ 
++	pd->dev.dma_mask = &octeon_ehci_dma_mask;
++	pd->dev.platform_data = &octeon_ehci_pdata;
++	octeon_ehci_hw_start();
++
+ 	ret = platform_device_add(pd);
+ 	if (ret)
+ 		goto fail;
+@@ -117,6 +349,41 @@ static int __init octeon_ehci_device_init(void)
+ }
+ device_initcall(octeon_ehci_device_init);
+ 
++static int octeon_ohci_power_on(struct platform_device *pdev)
++{
++	octeon2_usb_clocks_start();
++	return 0;
++}
++
++static void octeon_ohci_power_off(struct platform_device *pdev)
++{
++	octeon2_usb_clocks_stop();
++}
++
++static struct usb_ohci_pdata octeon_ohci_pdata = {
++	/* Octeon OHCI matches CPU endianness. */
++#ifdef __BIG_ENDIAN
++	.big_endian_mmio	= 1,
++#endif
++	.power_on	= octeon_ohci_power_on,
++	.power_off	= octeon_ohci_power_off,
++};
++
++static void __init octeon_ohci_hw_start(void)
++{
++	union cvmx_uctlx_ohci_ctl ohci_ctl;
++
++	octeon2_usb_clocks_start();
++
++	ohci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_OHCI_CTL(0));
++	ohci_ctl.s.l2c_addr_msb = 0;
++	ohci_ctl.s.l2c_buff_emod = 1; /* Byte swapped. */
++	ohci_ctl.s.l2c_desc_emod = 1; /* Byte swapped. */
++	cvmx_write_csr(CVMX_UCTLX_OHCI_CTL(0), ohci_ctl.u64);
++
++	octeon2_usb_clocks_stop();
++}
++
+ static int __init octeon_ohci_device_init(void)
+ {
+ 	struct platform_device *pd;
+@@ -137,7 +404,7 @@ static int __init octeon_ohci_device_init(void)
+ 	if (octeon_is_simulation() || usb_disabled())
+ 		return 0; /* No USB in the simulator. */
+ 
+-	pd = platform_device_alloc("octeon-ohci", 0);
++	pd = platform_device_alloc("ohci-platform", 0);
+ 	if (!pd) {
+ 		ret = -ENOMEM;
+ 		goto out;
+@@ -154,6 +421,9 @@ static int __init octeon_ohci_device_init(void)
+ 	if (ret)
+ 		goto fail;
+ 
++	pd->dev.platform_data = &octeon_ohci_pdata;
++	octeon_ohci_hw_start();
++
+ 	ret = platform_device_add(pd);
+ 	if (ret)
+ 		goto fail;
+diff --git a/arch/mips/configs/cavium_octeon_defconfig b/arch/mips/configs/cavium_octeon_defconfig
+index b2476a1c4aaa..e57058d4ec22 100644
+--- a/arch/mips/configs/cavium_octeon_defconfig
++++ b/arch/mips/configs/cavium_octeon_defconfig
+@@ -120,6 +120,9 @@ CONFIG_SPI_OCTEON=y
+ # CONFIG_HWMON is not set
+ CONFIG_WATCHDOG=y
+ # CONFIG_USB_SUPPORT is not set
++CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y
++CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+ CONFIG_RTC_CLASS=y
+ CONFIG_RTC_DRV_DS1307=y
+ CONFIG_STAGING=y
+diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
+index a3ca1375dd52..fafc628480e0 100644
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -292,11 +292,15 @@ config USB_EHCI_HCD_PLATFORM
+ 	  If unsure, say N.
+ 
+ config USB_OCTEON_EHCI
+-	bool "Octeon on-chip EHCI support"
++	bool "Octeon on-chip EHCI support (DEPRECATED)"
+ 	depends on CAVIUM_OCTEON_SOC
+ 	default n
+ 	select USB_EHCI_BIG_ENDIAN_MMIO
++	select USB_EHCI_HCD_PLATFORM
+ 	help
++	  This option is deprecated now and the driver was removed, use
++	  USB_EHCI_HCD_PLATFORM instead.
++
+ 	  Enable support for the Octeon II SOC's on-chip EHCI
+ 	  controller.  It is needed for high-speed (480Mbit/sec)
+ 	  USB 2.0 device support.  All CN6XXX based chips with USB are
+@@ -575,12 +579,16 @@ config USB_OHCI_HCD_PLATFORM
+ 	  If unsure, say N.
+ 
+ config USB_OCTEON_OHCI
+-	bool "Octeon on-chip OHCI support"
++	bool "Octeon on-chip OHCI support (DEPRECATED)"
+ 	depends on CAVIUM_OCTEON_SOC
+ 	default USB_OCTEON_EHCI
+ 	select USB_OHCI_BIG_ENDIAN_MMIO
+ 	select USB_OHCI_LITTLE_ENDIAN
++	select USB_OHCI_HCD_PLATFORM
+ 	help
++	  This option is deprecated now and the driver was removed, use
++	  USB_OHCI_HCD_PLATFORM instead.
++
+ 	  Enable support for the Octeon II SOC's on-chip OHCI
+ 	  controller.  It is needed for low-speed USB 1.0 device
+ 	  support.  All CN6XXX based chips with USB are supported.
+@@ -754,12 +762,6 @@ config USB_IMX21_HCD
+          To compile this driver as a module, choose M here: the
+          module will be called "imx21-hcd".
+ 
+-
+-
+-config USB_OCTEON2_COMMON
+-	bool
+-	default y if USB_OCTEON_EHCI || USB_OCTEON_OHCI
+-
+ config USB_HCD_BCMA
+ 	tristate "BCMA usb host driver"
+ 	depends on BCMA
+diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
+index 348c24321562..d6216a493bab 100644
+--- a/drivers/usb/host/Makefile
++++ b/drivers/usb/host/Makefile
+@@ -73,7 +73,6 @@ obj-$(CONFIG_USB_ISP1760_HCD)	+= isp1760.o
+ obj-$(CONFIG_USB_HWA_HCD)	+= hwa-hc.o
+ obj-$(CONFIG_USB_IMX21_HCD)	+= imx21-hcd.o
+ obj-$(CONFIG_USB_FSL_MPH_DR_OF)	+= fsl-mph-dr-of.o
+-obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o
+ obj-$(CONFIG_USB_HCD_BCMA)	+= bcma-hcd.o
+ obj-$(CONFIG_USB_HCD_SSB)	+= ssb-hcd.o
+ obj-$(CONFIG_USB_FUSBH200_HCD)	+= fusbh200-hcd.o
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index df75b8e7d157..38bfeedae1d0 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1275,11 +1275,6 @@ MODULE_LICENSE ("GPL");
+ #define XILINX_OF_PLATFORM_DRIVER	ehci_hcd_xilinx_of_driver
+ #endif
+ 
+-#ifdef CONFIG_USB_OCTEON_EHCI
+-#include "ehci-octeon.c"
+-#define PLATFORM_DRIVER		ehci_octeon_driver
+-#endif
+-
+ #ifdef CONFIG_TILE_USB
+ #include "ehci-tilegx.c"
+ #define	PLATFORM_DRIVER		ehci_hcd_tilegx_driver
+diff --git a/drivers/usb/host/ehci-octeon.c b/drivers/usb/host/ehci-octeon.c
+deleted file mode 100644
+index 2d0c4bcba579..000000000000
+--- a/drivers/usb/host/ehci-octeon.c
++++ /dev/null
+@@ -1,182 +0,0 @@
+-/*
+- * EHCI HCD glue for Cavium Octeon II SOCs.
+- *
+- * Loosely based on ehci-au1xxx.c
+- *
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License.  See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (C) 2010 Cavium Networks
+- *
+- */
+-
+-#include 
+-
+-#include 
+-#include 
+-
+-#define OCTEON_EHCI_HCD_NAME "octeon-ehci"
+-
+-/* Common clock init code.  */
+-void octeon2_usb_clocks_start(void);
+-void octeon2_usb_clocks_stop(void);
+-
+-static void ehci_octeon_start(void)
+-{
+-	union cvmx_uctlx_ehci_ctl ehci_ctl;
+-
+-	octeon2_usb_clocks_start();
+-
+-	ehci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_EHCI_CTL(0));
+-	/* Use 64-bit addressing. */
+-	ehci_ctl.s.ehci_64b_addr_en = 1;
+-	ehci_ctl.s.l2c_addr_msb = 0;
+-	ehci_ctl.s.l2c_buff_emod = 1; /* Byte swapped. */
+-	ehci_ctl.s.l2c_desc_emod = 1; /* Byte swapped. */
+-	cvmx_write_csr(CVMX_UCTLX_EHCI_CTL(0), ehci_ctl.u64);
+-}
+-
+-static void ehci_octeon_stop(void)
+-{
+-	octeon2_usb_clocks_stop();
+-}
+-
+-static const struct hc_driver ehci_octeon_hc_driver = {
+-	.description		= hcd_name,
+-	.product_desc		= "Octeon EHCI",
+-	.hcd_priv_size		= sizeof(struct ehci_hcd),
+-
+-	/*
+-	 * generic hardware linkage
+-	 */
+-	.irq			= ehci_irq,
+-	.flags			= HCD_MEMORY | HCD_USB2 | HCD_BH,
+-
+-	/*
+-	 * basic lifecycle operations
+-	 */
+-	.reset			= ehci_setup,
+-	.start			= ehci_run,
+-	.stop			= ehci_stop,
+-	.shutdown		= ehci_shutdown,
+-
+-	/*
+-	 * managing i/o requests and associated device resources
+-	 */
+-	.urb_enqueue		= ehci_urb_enqueue,
+-	.urb_dequeue		= ehci_urb_dequeue,
+-	.endpoint_disable	= ehci_endpoint_disable,
+-	.endpoint_reset		= ehci_endpoint_reset,
+-
+-	/*
+-	 * scheduling support
+-	 */
+-	.get_frame_number	= ehci_get_frame,
+-
+-	/*
+-	 * root hub support
+-	 */
+-	.hub_status_data	= ehci_hub_status_data,
+-	.hub_control		= ehci_hub_control,
+-	.bus_suspend		= ehci_bus_suspend,
+-	.bus_resume		= ehci_bus_resume,
+-	.relinquish_port	= ehci_relinquish_port,
+-	.port_handed_over	= ehci_port_handed_over,
+-
+-	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
+-};
+-
+-static u64 ehci_octeon_dma_mask = DMA_BIT_MASK(64);
+-
+-static int ehci_octeon_drv_probe(struct platform_device *pdev)
+-{
+-	struct usb_hcd *hcd;
+-	struct ehci_hcd *ehci;
+-	struct resource *res_mem;
+-	int irq;
+-	int ret;
+-
+-	if (usb_disabled())
+-		return -ENODEV;
+-
+-	irq = platform_get_irq(pdev, 0);
+-	if (irq < 0) {
+-		dev_err(&pdev->dev, "No irq assigned\n");
+-		return -ENODEV;
+-	}
+-
+-	/*
+-	 * We can DMA from anywhere. But the descriptors must be in
+-	 * the lower 4GB.
+-	 */
+-	pdev->dev.dma_mask = &ehci_octeon_dma_mask;
+-	ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+-	if (ret)
+-		return ret;
+-
+-	hcd = usb_create_hcd(&ehci_octeon_hc_driver, &pdev->dev, "octeon");
+-	if (!hcd)
+-		return -ENOMEM;
+-
+-	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-	hcd->regs = devm_ioremap_resource(&pdev->dev, res_mem);
+-	if (IS_ERR(hcd->regs)) {
+-		ret = PTR_ERR(hcd->regs);
+-		goto err1;
+-	}
+-	hcd->rsrc_start = res_mem->start;
+-	hcd->rsrc_len = resource_size(res_mem);
+-
+-	ehci_octeon_start();
+-
+-	ehci = hcd_to_ehci(hcd);
+-
+-	/* Octeon EHCI matches CPU endianness. */
+-#ifdef __BIG_ENDIAN
+-	ehci->big_endian_mmio = 1;
+-#endif
+-
+-	ehci->caps = hcd->regs;
+-
+-	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
+-	if (ret) {
+-		dev_dbg(&pdev->dev, "failed to add hcd with err %d\n", ret);
+-		goto err2;
+-	}
+-	device_wakeup_enable(hcd->self.controller);
+-
+-	platform_set_drvdata(pdev, hcd);
+-
+-	return 0;
+-err2:
+-	ehci_octeon_stop();
+-
+-err1:
+-	usb_put_hcd(hcd);
+-	return ret;
+-}
+-
+-static int ehci_octeon_drv_remove(struct platform_device *pdev)
+-{
+-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+-
+-	usb_remove_hcd(hcd);
+-
+-	ehci_octeon_stop();
+-	usb_put_hcd(hcd);
+-
+-	return 0;
+-}
+-
+-static struct platform_driver ehci_octeon_driver = {
+-	.probe		= ehci_octeon_drv_probe,
+-	.remove		= ehci_octeon_drv_remove,
+-	.shutdown	= usb_hcd_platform_shutdown,
+-	.driver = {
+-		.name	= OCTEON_EHCI_HCD_NAME,
+-		.owner	= THIS_MODULE,
+-	}
+-};
+-
+-MODULE_ALIAS("platform:" OCTEON_EHCI_HCD_NAME);
+diff --git a/drivers/usb/host/octeon2-common.c b/drivers/usb/host/octeon2-common.c
+deleted file mode 100644
+index d9df423f3d12..000000000000
+--- a/drivers/usb/host/octeon2-common.c
++++ /dev/null
+@@ -1,200 +0,0 @@
+-/*
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License.  See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (C) 2010, 2011 Cavium Networks
+- */
+-
+-#include 
+-#include 
+-#include 
+-
+-#include 
+-#include 
+-
+-static DEFINE_MUTEX(octeon2_usb_clocks_mutex);
+-
+-static int octeon2_usb_clock_start_cnt;
+-
+-void octeon2_usb_clocks_start(void)
+-{
+-	u64 div;
+-	union cvmx_uctlx_if_ena if_ena;
+-	union cvmx_uctlx_clk_rst_ctl clk_rst_ctl;
+-	union cvmx_uctlx_uphy_ctl_status uphy_ctl_status;
+-	union cvmx_uctlx_uphy_portx_ctl_status port_ctl_status;
+-	int i;
+-	unsigned long io_clk_64_to_ns;
+-
+-
+-	mutex_lock(&octeon2_usb_clocks_mutex);
+-
+-	octeon2_usb_clock_start_cnt++;
+-	if (octeon2_usb_clock_start_cnt != 1)
+-		goto exit;
+-
+-	io_clk_64_to_ns = 64000000000ull / octeon_get_io_clock_rate();
+-
+-	/*
+-	 * Step 1: Wait for voltages stable.  That surely happened
+-	 * before starting the kernel.
+-	 *
+-	 * Step 2: Enable  SCLK of UCTL by writing UCTL0_IF_ENA[EN] = 1
+-	 */
+-	if_ena.u64 = 0;
+-	if_ena.s.en = 1;
+-	cvmx_write_csr(CVMX_UCTLX_IF_ENA(0), if_ena.u64);
+-
+-	/* Step 3: Configure the reference clock, PHY, and HCLK */
+-	clk_rst_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0));
+-
+-	/*
+-	 * If the UCTL looks like it has already been started, skip
+-	 * the initialization, otherwise bus errors are obtained.
+-	 */
+-	if (clk_rst_ctl.s.hrst)
+-		goto end_clock;
+-	/* 3a */
+-	clk_rst_ctl.s.p_por = 1;
+-	clk_rst_ctl.s.hrst = 0;
+-	clk_rst_ctl.s.p_prst = 0;
+-	clk_rst_ctl.s.h_clkdiv_rst = 0;
+-	clk_rst_ctl.s.o_clkdiv_rst = 0;
+-	clk_rst_ctl.s.h_clkdiv_en = 0;
+-	clk_rst_ctl.s.o_clkdiv_en = 0;
+-	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
+-
+-	/* 3b */
+-	/* 12MHz crystal. */
+-	clk_rst_ctl.s.p_refclk_sel = 0;
+-	clk_rst_ctl.s.p_refclk_div = 0;
+-	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
+-
+-	/* 3c */
+-	div = octeon_get_io_clock_rate() / 130000000ull;
+-
+-	switch (div) {
+-	case 0:
+-		div = 1;
+-		break;
+-	case 1:
+-	case 2:
+-	case 3:
+-	case 4:
+-		break;
+-	case 5:
+-		div = 4;
+-		break;
+-	case 6:
+-	case 7:
+-		div = 6;
+-		break;
+-	case 8:
+-	case 9:
+-	case 10:
+-	case 11:
+-		div = 8;
+-		break;
+-	default:
+-		div = 12;
+-		break;
+-	}
+-	clk_rst_ctl.s.h_div = div;
+-	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
+-	/* Read it back, */
+-	clk_rst_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0));
+-	clk_rst_ctl.s.h_clkdiv_en = 1;
+-	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
+-	/* 3d */
+-	clk_rst_ctl.s.h_clkdiv_rst = 1;
+-	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
+-
+-	/* 3e: delay 64 io clocks */
+-	ndelay(io_clk_64_to_ns);
+-
+-	/*
+-	 * Step 4: Program the power-on reset field in the UCTL
+-	 * clock-reset-control register.
+-	 */
+-	clk_rst_ctl.s.p_por = 0;
+-	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
+-
+-	/* Step 5:    Wait 1 ms for the PHY clock to start. */
+-	mdelay(1);
+-
+-	/*
+-	 * Step 6: Program the reset input from automatic test
+-	 * equipment field in the UPHY CSR
+-	 */
+-	uphy_ctl_status.u64 = cvmx_read_csr(CVMX_UCTLX_UPHY_CTL_STATUS(0));
+-	uphy_ctl_status.s.ate_reset = 1;
+-	cvmx_write_csr(CVMX_UCTLX_UPHY_CTL_STATUS(0), uphy_ctl_status.u64);
+-
+-	/* Step 7: Wait for at least 10ns. */
+-	ndelay(10);
+-
+-	/* Step 8: Clear the ATE_RESET field in the UPHY CSR. */
+-	uphy_ctl_status.s.ate_reset = 0;
+-	cvmx_write_csr(CVMX_UCTLX_UPHY_CTL_STATUS(0), uphy_ctl_status.u64);
+-
+-	/*
+-	 * Step 9: Wait for at least 20ns for UPHY to output PHY clock
+-	 * signals and OHCI_CLK48
+-	 */
+-	ndelay(20);
+-
+-	/* Step 10: Configure the OHCI_CLK48 and OHCI_CLK12 clocks. */
+-	/* 10a */
+-	clk_rst_ctl.s.o_clkdiv_rst = 1;
+-	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
+-
+-	/* 10b */
+-	clk_rst_ctl.s.o_clkdiv_en = 1;
+-	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
+-
+-	/* 10c */
+-	ndelay(io_clk_64_to_ns);
+-
+-	/*
+-	 * Step 11: Program the PHY reset field:
+-	 * UCTL0_CLK_RST_CTL[P_PRST] = 1
+-	 */
+-	clk_rst_ctl.s.p_prst = 1;
+-	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
+-
+-	/* Step 12: Wait 1 uS. */
+-	udelay(1);
+-
+-	/* Step 13: Program the HRESET_N field: UCTL0_CLK_RST_CTL[HRST] = 1 */
+-	clk_rst_ctl.s.hrst = 1;
+-	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
+-
+-end_clock:
+-	/* Now we can set some other registers.  */
+-
+-	for (i = 0; i <= 1; i++) {
+-		port_ctl_status.u64 =
+-			cvmx_read_csr(CVMX_UCTLX_UPHY_PORTX_CTL_STATUS(i, 0));
+-		/* Set txvreftune to 15 to obtain compliant 'eye' diagram. */
+-		port_ctl_status.s.txvreftune = 15;
+-		port_ctl_status.s.txrisetune = 1;
+-		port_ctl_status.s.txpreemphasistune = 1;
+-		cvmx_write_csr(CVMX_UCTLX_UPHY_PORTX_CTL_STATUS(i, 0),
+-			       port_ctl_status.u64);
+-	}
+-
+-	/* Set uSOF cycle period to 60,000 bits. */
+-	cvmx_write_csr(CVMX_UCTLX_EHCI_FLA(0), 0x20ull);
+-exit:
+-	mutex_unlock(&octeon2_usb_clocks_mutex);
+-}
+-EXPORT_SYMBOL(octeon2_usb_clocks_start);
+-
+-void octeon2_usb_clocks_stop(void)
+-{
+-	mutex_lock(&octeon2_usb_clocks_mutex);
+-	octeon2_usb_clock_start_cnt--;
+-	mutex_unlock(&octeon2_usb_clocks_mutex);
+-}
+-EXPORT_SYMBOL(octeon2_usb_clocks_stop);
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index d664edabf14e..1dab9dfbca6a 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -1249,11 +1249,6 @@ MODULE_LICENSE ("GPL");
+ #define PLATFORM_DRIVER	ohci_hcd_jz4740_driver
+ #endif
+ 
+-#ifdef CONFIG_USB_OCTEON_OHCI
+-#include "ohci-octeon.c"
+-#define PLATFORM_DRIVER		ohci_octeon_driver
+-#endif
+-
+ #ifdef CONFIG_TILE_USB
+ #include "ohci-tilegx.c"
+ #define PLATFORM_DRIVER		ohci_hcd_tilegx_driver
+diff --git a/drivers/usb/host/ohci-octeon.c b/drivers/usb/host/ohci-octeon.c
+deleted file mode 100644
+index 20d861b6192f..000000000000
+--- a/drivers/usb/host/ohci-octeon.c
++++ /dev/null
+@@ -1,196 +0,0 @@
+-/*
+- * EHCI HCD glue for Cavium Octeon II SOCs.
+- *
+- * Loosely based on ehci-au1xxx.c
+- *
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License.  See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (C) 2010 Cavium Networks
+- *
+- */
+-
+-#include 
+-
+-#include 
+-#include 
+-
+-#define OCTEON_OHCI_HCD_NAME "octeon-ohci"
+-
+-/* Common clock init code.  */
+-void octeon2_usb_clocks_start(void);
+-void octeon2_usb_clocks_stop(void);
+-
+-static void ohci_octeon_hw_start(void)
+-{
+-	union cvmx_uctlx_ohci_ctl ohci_ctl;
+-
+-	octeon2_usb_clocks_start();
+-
+-	ohci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_OHCI_CTL(0));
+-	ohci_ctl.s.l2c_addr_msb = 0;
+-	ohci_ctl.s.l2c_buff_emod = 1; /* Byte swapped. */
+-	ohci_ctl.s.l2c_desc_emod = 1; /* Byte swapped. */
+-	cvmx_write_csr(CVMX_UCTLX_OHCI_CTL(0), ohci_ctl.u64);
+-
+-}
+-
+-static void ohci_octeon_hw_stop(void)
+-{
+-	/* Undo ohci_octeon_start() */
+-	octeon2_usb_clocks_stop();
+-}
+-
+-static int ohci_octeon_start(struct usb_hcd *hcd)
+-{
+-	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+-	int ret;
+-
+-	ret = ohci_init(ohci);
+-
+-	if (ret < 0)
+-		return ret;
+-
+-	ret = ohci_run(ohci);
+-
+-	if (ret < 0) {
+-		ohci_err(ohci, "can't start %s", hcd->self.bus_name);
+-		ohci_stop(hcd);
+-		return ret;
+-	}
+-
+-	return 0;
+-}
+-
+-static const struct hc_driver ohci_octeon_hc_driver = {
+-	.description		= hcd_name,
+-	.product_desc		= "Octeon OHCI",
+-	.hcd_priv_size		= sizeof(struct ohci_hcd),
+-
+-	/*
+-	 * generic hardware linkage
+-	 */
+-	.irq =			ohci_irq,
+-	.flags =		HCD_USB11 | HCD_MEMORY,
+-
+-	/*
+-	 * basic lifecycle operations
+-	 */
+-	.start =		ohci_octeon_start,
+-	.stop =			ohci_stop,
+-	.shutdown =		ohci_shutdown,
+-
+-	/*
+-	 * managing i/o requests and associated device resources
+-	 */
+-	.urb_enqueue =		ohci_urb_enqueue,
+-	.urb_dequeue =		ohci_urb_dequeue,
+-	.endpoint_disable =	ohci_endpoint_disable,
+-
+-	/*
+-	 * scheduling support
+-	 */
+-	.get_frame_number =	ohci_get_frame,
+-
+-	/*
+-	 * root hub support
+-	 */
+-	.hub_status_data =	ohci_hub_status_data,
+-	.hub_control =		ohci_hub_control,
+-
+-	.start_port_reset =	ohci_start_port_reset,
+-};
+-
+-static int ohci_octeon_drv_probe(struct platform_device *pdev)
+-{
+-	struct usb_hcd *hcd;
+-	struct ohci_hcd *ohci;
+-	void *reg_base;
+-	struct resource *res_mem;
+-	int irq;
+-	int ret;
+-
+-	if (usb_disabled())
+-		return -ENODEV;
+-
+-	irq = platform_get_irq(pdev, 0);
+-	if (irq < 0) {
+-		dev_err(&pdev->dev, "No irq assigned\n");
+-		return -ENODEV;
+-	}
+-
+-	/* Ohci is a 32-bit device. */
+-	ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+-	if (ret)
+-		return ret;
+-
+-	hcd = usb_create_hcd(&ohci_octeon_hc_driver, &pdev->dev, "octeon");
+-	if (!hcd)
+-		return -ENOMEM;
+-
+-	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-	reg_base = devm_ioremap_resource(&pdev->dev, res_mem);
+-	if (IS_ERR(reg_base)) {
+-		ret = PTR_ERR(reg_base);
+-		goto err1;
+-	}
+-	hcd->rsrc_start = res_mem->start;
+-	hcd->rsrc_len = resource_size(res_mem);
+-
+-	ohci_octeon_hw_start();
+-
+-	hcd->regs = reg_base;
+-
+-	ohci = hcd_to_ohci(hcd);
+-
+-	/* Octeon OHCI matches CPU endianness. */
+-#ifdef __BIG_ENDIAN
+-	ohci->flags |= OHCI_QUIRK_BE_MMIO;
+-#endif
+-
+-	ohci_hcd_init(ohci);
+-
+-	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
+-	if (ret) {
+-		dev_dbg(&pdev->dev, "failed to add hcd with err %d\n", ret);
+-		goto err2;
+-	}
+-
+-	device_wakeup_enable(hcd->self.controller);
+-
+-	platform_set_drvdata(pdev, hcd);
+-
+-	return 0;
+-
+-err2:
+-	ohci_octeon_hw_stop();
+-
+-err1:
+-	usb_put_hcd(hcd);
+-	return ret;
+-}
+-
+-static int ohci_octeon_drv_remove(struct platform_device *pdev)
+-{
+-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+-
+-	usb_remove_hcd(hcd);
+-
+-	ohci_octeon_hw_stop();
+-	usb_put_hcd(hcd);
+-
+-	return 0;
+-}
+-
+-static struct platform_driver ohci_octeon_driver = {
+-	.probe		= ohci_octeon_drv_probe,
+-	.remove		= ohci_octeon_drv_remove,
+-	.shutdown	= usb_hcd_platform_shutdown,
+-	.driver = {
+-		.name	= OCTEON_OHCI_HCD_NAME,
+-		.owner	= THIS_MODULE,
+-	}
+-};
+-
+-MODULE_ALIAS("platform:" OCTEON_OHCI_HCD_NAME);

commit 5ca1ccdaa88ac15d1468c5e8bb40885dc6b8a364
+Author: Alan Stern 
+Date:   Thu Nov 6 14:27:57 2014 +0800
+
+    usb: gadget: net2272: use udc-core's reset notifier
+    
+    This patch adds support for the new udc-core reset notifier to the
+    net2272 driver.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Felipe Balbi 
+    Signed-off-by: Peter Chen 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c
+index ab3a73950d8f..3a90856625f2 100644
+--- a/drivers/usb/gadget/udc/net2272.c
++++ b/drivers/usb/gadget/udc/net2272.c
+@@ -1982,17 +1982,42 @@ net2272_handle_stat1_irqs(struct net2272 *dev, u8 stat)
+ 	mask = (1 << USB_HIGH_SPEED) | (1 << USB_FULL_SPEED);
+ 
+ 	if (stat & tmp) {
++		bool	reset = false;
++		bool	disconnect = false;
++
++		/*
++		 * Ignore disconnects and resets if the speed hasn't been set.
++		 * VBUS can bounce and there's always an initial reset.
++		 */
+ 		net2272_write(dev, IRQSTAT1, tmp);
+-		if ((((stat & (1 << ROOT_PORT_RESET_INTERRUPT)) &&
+-				((net2272_read(dev, USBCTL1) & mask) == 0))
+-			|| ((net2272_read(dev, USBCTL1) & (1 << VBUS_PIN))
+-				== 0))
+-				&& (dev->gadget.speed != USB_SPEED_UNKNOWN)) {
+-			dev_dbg(dev->dev, "disconnect %s\n",
+-				dev->driver->driver.name);
+-			stop_activity(dev, dev->driver);
+-			net2272_ep0_start(dev);
+-			return;
++		if (dev->gadget.speed != USB_SPEED_UNKNOWN) {
++			if ((stat & (1 << VBUS_INTERRUPT)) &&
++					(net2272_read(dev, USBCTL1) &
++						(1 << VBUS_PIN)) == 0) {
++				disconnect = true;
++				dev_dbg(dev->dev, "disconnect %s\n",
++					dev->driver->driver.name);
++			} else if ((stat & (1 << ROOT_PORT_RESET_INTERRUPT)) &&
++					(net2272_read(dev, USBCTL1) & mask)
++						== 0) {
++				reset = true;
++				dev_dbg(dev->dev, "reset %s\n",
++					dev->driver->driver.name);
++			}
++
++			if (disconnect || reset) {
++				stop_activity(dev, dev->driver);
++				net2272_ep0_start(dev);
++				spin_unlock(&dev->lock);
++				if (reset)
++					usb_gadget_udc_reset
++						(&dev->gadget, dev->driver);
++				else
++					(dev->driver->disconnect)
++						(&dev->gadget);
++				spin_lock(&dev->lock);
++				return;
++			}
+ 		}
+ 		stat &= ~tmp;
+ 

commit b611e424f1ad189409dde50fe950eb8c05f75cab
+Author: Alan Stern 
+Date:   Thu Nov 6 14:27:56 2014 +0800
+
+    usb: gadget: net2280: use udc-core's reset notifier
+    
+    This patch adds support for the new udc-core reset notifier to the
+    net2280 driver.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Felipe Balbi 
+    Signed-off-by: Peter Chen 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c
+index bd03a1b4192d..c49179493796 100644
+--- a/drivers/usb/gadget/udc/net2280.c
++++ b/drivers/usb/gadget/udc/net2280.c
+@@ -3308,17 +3308,42 @@ static void handle_stat1_irqs(struct net2280 *dev, u32 stat)
+ 	 * only indicates a change in the reset state).
+ 	 */
+ 	if (stat & tmp) {
++		bool	reset = false;
++		bool	disconnect = false;
++
++		/*
++		 * Ignore disconnects and resets if the speed hasn't been set.
++		 * VBUS can bounce and there's always an initial reset.
++		 */
+ 		writel(tmp, &dev->regs->irqstat1);
+-		if ((((stat & BIT(ROOT_PORT_RESET_INTERRUPT)) &&
+-				((readl(&dev->usb->usbstat) & mask) == 0)) ||
+-				((readl(&dev->usb->usbctl) &
+-					BIT(VBUS_PIN)) == 0)) &&
+-				(dev->gadget.speed != USB_SPEED_UNKNOWN)) {
+-			ep_dbg(dev, "disconnect %s\n",
+-					dev->driver->driver.name);
+-			stop_activity(dev, dev->driver);
+-			ep0_start(dev);
+-			return;
++		if (dev->gadget.speed != USB_SPEED_UNKNOWN) {
++			if ((stat & BIT(VBUS_INTERRUPT)) &&
++					(readl(&dev->usb->usbctl) &
++						BIT(VBUS_PIN)) == 0) {
++				disconnect = true;
++				ep_dbg(dev, "disconnect %s\n",
++						dev->driver->driver.name);
++			} else if ((stat & BIT(ROOT_PORT_RESET_INTERRUPT)) &&
++					(readl(&dev->usb->usbstat) & mask)
++						== 0) {
++				reset = true;
++				ep_dbg(dev, "reset %s\n",
++						dev->driver->driver.name);
++			}
++
++			if (disconnect || reset) {
++				stop_activity(dev, dev->driver);
++				ep0_start(dev);
++				spin_unlock(&dev->lock);
++				if (reset)
++					usb_gadget_udc_reset
++						(&dev->gadget, dev->driver);
++				else
++					(dev->driver->disconnect)
++						(&dev->gadget);
++				spin_lock(&dev->lock);
++				return;
++			}
+ 		}
+ 		stat &= ~tmp;
+ 

commit 8480484d6f4a5b7d50262702db082b0fd13e7df5
+Author: Alan Stern 
+Date:   Thu Nov 6 14:27:55 2014 +0800
+
+    usb: gadget: dummy-hcd: use udc-core's reset notifier
+    
+    Replace usb_gadget_driver's disconnect with udc-core's reset notifier at
+    bus reset handler.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Felipe Balbi 
+    Signed-off-by: Peter chen 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
+index 254b9e7659f3..1c69c760408e 100644
+--- a/drivers/usb/gadget/udc/dummy_hcd.c
++++ b/drivers/usb/gadget/udc/dummy_hcd.c
+@@ -367,19 +367,22 @@ static void set_link_state(struct dummy_hcd *dum_hcd)
+ 	     dum_hcd->active)
+ 		dum_hcd->resuming = 0;
+ 
+-	/* if !connected or reset */
++	/* Currently !connected or in reset */
+ 	if ((dum_hcd->port_status & USB_PORT_STAT_CONNECTION) == 0 ||
+ 			(dum_hcd->port_status & USB_PORT_STAT_RESET) != 0) {
+-		/*
+-		 * We're connected and not reset (reset occurred now),
+-		 * and driver attached - disconnect!
+-		 */
+-		if ((dum_hcd->old_status & USB_PORT_STAT_CONNECTION) != 0 &&
+-		    (dum_hcd->old_status & USB_PORT_STAT_RESET) == 0 &&
+-		    dum->driver) {
++		unsigned disconnect = USB_PORT_STAT_CONNECTION &
++				dum_hcd->old_status & (~dum_hcd->port_status);
++		unsigned reset = USB_PORT_STAT_RESET &
++				(~dum_hcd->old_status) & dum_hcd->port_status;
++
++		/* Report reset and disconnect events to the driver */
++		if (dum->driver && (disconnect || reset)) {
+ 			stop_activity(dum);
+ 			spin_unlock(&dum->lock);
+-			dum->driver->disconnect(&dum->gadget);
++			if (reset)
++				usb_gadget_udc_reset(&dum->gadget, dum->driver);
++			else
++				dum->driver->disconnect(&dum->gadget);
+ 			spin_lock(&dum->lock);
+ 		}
+ 	} else if (dum_hcd->active != dum_hcd->old_active) {

commit 93c9bf4d1838d5851a18ca398b0ad66397f05056
+Author: Alan Stern 
+Date:   Fri Oct 31 14:49:47 2014 -0400
+
+    usb-storage: handle a skipped data phase
+    
+    Sometimes mass-storage devices using the Bulk-only transport will
+    mistakenly skip the data phase of a command.  Rather than sending the
+    data expected by the host or sending a zero-length packet, they go
+    directly to the status phase and send the CSW.
+    
+    This causes problems for usb-storage, for obvious reasons.  The driver
+    will interpret the CSW as a short data transfer and will wait to
+    receive a CSW.  The device won't have anything left to send, so the
+    command eventually times out.
+    
+    The SCSI layer doesn't retry commands after they time out (this is a
+    relatively recent change).  Therefore we should do our best to detect
+    a skipped data phase and handle it promptly.
+    
+    This patch adds code to do that.  If usb-storage receives a short
+    13-byte data transfer from the device, and if the first four bytes of
+    the data match the CSW signature, the driver will set the residue to
+    the full transfer length and interpret the data as a CSW.
+    
+    This fixes Bugzilla #86611.
+    
+    Signed-off-by: Alan Stern 
+    CC: Matthew Dharm 
+    Tested-by: Paul Osmialowski 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+index 22c7d4360fa2..b1d815eb6d0b 100644
+--- a/drivers/usb/storage/transport.c
++++ b/drivers/usb/storage/transport.c
+@@ -1118,6 +1118,31 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 		 */
+ 		if (result == USB_STOR_XFER_LONG)
+ 			fake_sense = 1;
++
++		/*
++		 * Sometimes a device will mistakenly skip the data phase
++		 * and go directly to the status phase without sending a
++		 * zero-length packet.  If we get a 13-byte response here,
++		 * check whether it really is a CSW.
++		 */
++		if (result == USB_STOR_XFER_SHORT &&
++				srb->sc_data_direction == DMA_FROM_DEVICE &&
++				transfer_length - scsi_get_resid(srb) ==
++					US_BULK_CS_WRAP_LEN) {
++			struct scatterlist *sg = NULL;
++			unsigned int offset = 0;
++
++			if (usb_stor_access_xfer_buf((unsigned char *) bcs,
++					US_BULK_CS_WRAP_LEN, srb, &sg,
++					&offset, FROM_XFER_BUF) ==
++						US_BULK_CS_WRAP_LEN &&
++					bcs->Signature ==
++						cpu_to_le32(US_BULK_CS_SIGN)) {
++				usb_stor_dbg(us, "Device skipped data phase\n");
++				scsi_set_resid(srb, transfer_length);
++				goto skipped_data_phase;
++			}
++		}
+ 	}
+ 
+ 	/* See flow chart on pg 15 of the Bulk Only Transport spec for
+@@ -1153,6 +1178,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 	if (result != USB_STOR_XFER_GOOD)
+ 		return USB_STOR_TRANSPORT_ERROR;
+ 
++ skipped_data_phase:
+ 	/* check bulk status */
+ 	residue = le32_to_cpu(bcs->Residue);
+ 	usb_stor_dbg(us, "Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",

commit 7312b5ddd47fee2356baa78c5516ef8e04eed452
+Author: Alan Stern 
+Date:   Wed Sep 17 11:23:54 2014 -0400
+
+    USB: EHCI: unlink QHs even after the controller has stopped
+    
+    Old code in ehci-hcd tries to expedite disabling endpoints after the
+    controller has stopped, by destroying the endpoint's associated QH
+    without first unlinking the QH.  This was necessary back when the
+    driver wasn't so careful about keeping track of the controller's
+    state.
+    
+    But now we are careful about it, and the driver knows that when the
+    controller isn't running, no unlinking delay is needed.  Furthermore,
+    skipping the unlink step will trigger a BUG() in qh_destroy() when the
+    preceding QH is released, because the link pointer will be non-NULL.
+    
+    Removing the lines that skip the unlinking step and go directly to
+    QH_STATE_IDLE fixes the problem.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Joe Lawrence 
+    Tested-by: Joe Lawrence 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 81cda09b47e3..488a30836c36 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -965,8 +965,6 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 	}
+ 
+ 	qh->exception = 1;
+-	if (ehci->rh_state < EHCI_RH_RUNNING)
+-		qh->qh_state = QH_STATE_IDLE;
+ 	switch (qh->qh_state) {
+ 	case QH_STATE_LINKED:
+ 		WARN_ON(!list_empty(&qh->qtd_list));

commit 50c4e96411a6cd728f04cf70d8d6def57828b320
+Author: Alan Stern 
+Date:   Tue Sep 2 11:35:50 2014 -0400
+
+    scsi: don't store LUN bits in CDB[1] for USB mass-storage devices
+    
+    The SCSI specification requires that the second Command Data Byte
+    should contain the LUN value in its high-order bits if the recipient
+    device reports SCSI level 2 or below.  Nevertheless, some USB
+    mass-storage devices use those bits for other purposes in
+    vendor-specific commands.  Currently Linux has no way to send such
+    commands, because the SCSI stack always overwrites the LUN bits.
+    
+    Testing shows that Windows 7 and XP do not store the LUN bits in the
+    CDB when sending commands to a USB device.  This doesn't matter if the
+    device uses the Bulk-Only or UAS transports (which virtually all
+    modern USB mass-storage devices do), as these have a separate
+    mechanism for sending the LUN value.
+    
+    Therefore this patch introduces a flag in the Scsi_Host structure to
+    inform the SCSI midlayer that a transport does not require the LUN
+    bits to be stored in the CDB, and it makes usb-storage set this flag
+    for all devices using the Bulk-Only transport.  (UAS is handled by a
+    separate driver, but it doesn't really matter because no SCSI-2 or
+    lower device is at all likely to use UAS.)
+    
+    The patch also cleans up the code responsible for storing the LUN
+    value by adding a bitflag to the scsi_device structure.  The test for
+    whether to stick the LUN value in the CDB can be made when the device
+    is probed, and stored for future use rather than being made over and
+    over in the fast path.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Tiziano Bacocco 
+    Acked-by: Martin K. Petersen 
+    Acked-by: James Bottomley 
+    Signed-off-by: Christoph Hellwig 
+
+diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
+index d81f3cc43ff1..1423cb17fbfd 100644
+--- a/drivers/scsi/scsi.c
++++ b/drivers/scsi/scsi.c
+@@ -670,14 +670,10 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
+ 		return SCSI_MLQUEUE_DEVICE_BUSY;
+ 	}
+ 
+-	/*
+-	 * If SCSI-2 or lower, store the LUN value in cmnd.
+-	 */
+-	if (cmd->device->scsi_level <= SCSI_2 &&
+-	    cmd->device->scsi_level != SCSI_UNKNOWN) {
++	/* Store the LUN value in cmnd, if needed. */
++	if (cmd->device->lun_in_cdb)
+ 		cmd->cmnd[1] = (cmd->cmnd[1] & 0x1f) |
+ 			       (cmd->device->lun << 5 & 0xe0);
+-	}
+ 
+ 	scsi_log_send(cmd);
+ 
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+index 56675dbbf681..f84c40188478 100644
+--- a/drivers/scsi/scsi_scan.c
++++ b/drivers/scsi/scsi_scan.c
+@@ -736,6 +736,16 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result,
+ 		sdev->scsi_level++;
+ 	sdev->sdev_target->scsi_level = sdev->scsi_level;
+ 
++	/*
++	 * If SCSI-2 or lower, and if the transport requires it,
++	 * store the LUN value in CDB[1].
++	 */
++	sdev->lun_in_cdb = 0;
++	if (sdev->scsi_level <= SCSI_2 &&
++	    sdev->scsi_level != SCSI_UNKNOWN &&
++	    !sdev->host->no_scsi2_lun_in_cdb)
++		sdev->lun_in_cdb = 1;
++
+ 	return 0;
+ }
+ 
+diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
+index 8b4105a22ac2..85e36f3a5585 100644
+--- a/drivers/scsi/scsi_sysfs.c
++++ b/drivers/scsi/scsi_sysfs.c
+@@ -1263,7 +1263,19 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev)
+ 	sdev->sdev_dev.class = &sdev_class;
+ 	dev_set_name(&sdev->sdev_dev, "%d:%d:%d:%llu",
+ 		     sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
++	/*
++	 * Get a default scsi_level from the target (derived from sibling
++	 * devices).  This is the best we can do for guessing how to set
++	 * sdev->lun_in_cdb for the initial INQUIRY command.  For LUN 0 the
++	 * setting doesn't matter, because all the bits are zero anyway.
++	 * But it does matter for higher LUNs.
++	 */
+ 	sdev->scsi_level = starget->scsi_level;
++	if (sdev->scsi_level <= SCSI_2 &&
++			sdev->scsi_level != SCSI_UNKNOWN &&
++			!shost->no_scsi2_lun_in_cdb)
++		sdev->lun_in_cdb = 1;
++
+ 	transport_setup_device(&sdev->sdev_gendev);
+ 	spin_lock_irqsave(shost->host_lock, flags);
+ 	list_add_tail(&sdev->same_target_siblings, &starget->devices);
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index cedb29252a92..bf3f8e2de046 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -983,6 +983,14 @@ int usb_stor_probe2(struct us_data *us)
+ 	if (!(us->fflags & US_FL_SCM_MULT_TARG))
+ 		us_to_host(us)->max_id = 1;
+ 
++	/*
++	 * Like Windows, we won't store the LUN bits in CDB[1] for SCSI-2
++	 * devices using the Bulk-Only transport (even though this violates
++	 * the SCSI spec).
++	 */
++	if (us->transport == usb_stor_Bulk_transport)
++		us_to_host(us)->no_scsi2_lun_in_cdb = 1;
++
+ 	/* Find the endpoints and calculate pipe values */
+ 	result = get_pipes(us);
+ 	if (result)
+diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
+index 1a0d1842962e..27ecee73bd72 100644
+--- a/include/scsi/scsi_device.h
++++ b/include/scsi/scsi_device.h
+@@ -174,6 +174,7 @@ struct scsi_device {
+ 	unsigned wce_default_on:1;	/* Cache is ON by default */
+ 	unsigned no_dif:1;	/* T10 PI (DIF) should be disabled */
+ 	unsigned broken_fua:1;		/* Don't set FUA bit */
++	unsigned lun_in_cdb:1;		/* Store LUN bits in CDB[1] */
+ 
+ 	atomic_t disk_events_disable_depth; /* disable depth for disk events */
+ 
+diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
+index cafb260ef2d3..d0f69a3210df 100644
+--- a/include/scsi/scsi_host.h
++++ b/include/scsi/scsi_host.h
+@@ -693,6 +693,9 @@ struct Scsi_Host {
+ 	 */
+ 	struct workqueue_struct *tmf_work_q;
+ 
++	/* The transport requires the LUN bits NOT to be stored in CDB[1] */
++	unsigned no_scsi2_lun_in_cdb:1;
++
+ 	/*
+ 	 * Value host_blocked counts down from
+ 	 */

commit df35c7c912fe668797681842b3b74c61b0664050
+Author: Alan Stern 
+Date:   Tue Sep 9 11:50:58 2014 -0400
+
+    Block: fix unbalanced bypass-disable in blk_register_queue
+    
+    When a queue is registered, the block layer turns off the bypass
+    setting (because bypass is enabled when the queue is created).  This
+    doesn't work well for queues that are unregistered and then registered
+    again; we get a WARNING because of the unbalanced calls to
+    blk_queue_bypass_end().
+    
+    This patch fixes the problem by making blk_register_queue() call
+    blk_queue_bypass_end() only the first time the queue is registered.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Tejun Heo 
+    CC: James Bottomley 
+    CC: Jens Axboe 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
+index 4db5abf96b9e..17f5c84ce7bf 100644
+--- a/block/blk-sysfs.c
++++ b/block/blk-sysfs.c
+@@ -554,8 +554,10 @@ int blk_register_queue(struct gendisk *disk)
+ 	 * Initialization must be complete by now.  Finish the initial
+ 	 * bypass from queue allocation.
+ 	 */
+-	queue_flag_set_unlocked(QUEUE_FLAG_INIT_DONE, q);
+-	blk_queue_bypass_end(q);
++	if (!blk_queue_init_done(q)) {
++		queue_flag_set_unlocked(QUEUE_FLAG_INIT_DONE, q);
++		blk_queue_bypass_end(q);
++	}
+ 
+ 	ret = blk_trace_init_sysfs(dev);
+ 	if (ret)

commit b6089f19fe0cec625b5963a851a07c3e412c27c8
+Author: Alan Stern 
+Date:   Tue Sep 2 15:42:18 2014 -0400
+
+    USB: document the 'u' flag for usb-storage quirks parameter
+    
+    Commit d24d481b7d36 (usb-storage: Modify and export adjust_quirks so
+    that it can be used by uas) added the 'u' flag to the quirks module
+    parameter for usb-storage, but neglected to update the
+    documentation.  This patch adds the documentation.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable   # 3.15+
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
+index 5ae8608ca9f5..10d51c2f10d7 100644
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -3541,6 +3541,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
+ 					bogus residue values);
+ 				s = SINGLE_LUN (the device has only one
+ 					Logical Unit);
++				u = IGNORE_UAS (don't bind to the uas driver);
+ 				w = NO_WP_DETECT (don't test whether the
+ 					medium is write-protected).
+ 			Example: quirks=0419:aaf5:rl,0421:0433:rc

commit 8f507ef522d55a6e2f9e11a1c1163a92756da044
+Author: Alan Stern 
+Date:   Tue Sep 2 11:39:15 2014 -0400
+
+    HID: usbhid: improve handling of Clear-Halt and reset
+    
+    This patch changes the way usbhid carries out Clear-Halt and reset.
+    
+    Currently, after a Clear-Halt on the interrupt-IN endpoint, the driver
+    immediately restarts the interrupt URB, even if the Clear-Halt failed.
+    This doesn't work out well when the reason for the failure was that
+    the device was disconnected (when a low- or full-speed device is
+    connected through a hub to an EHCI controller, transfer errors caused
+    by disconnection are reported as stalls by the hub).  Instead now the
+    driver will attempt a reset after a failed Clear-Halt.
+    
+    The way resets are carried out is also changed.  Now the driver will
+    call usb_queue_reset_device() instead of calling usb_reset_device()
+    directly.  This avoids a deadlock that would arise when a device is
+    unplugged: The hid_reset() routine runs as a workqueue item, a reset
+    attempt after the device has been unplugged will fail, failure will
+    cause usbhid to be unbound, and the disconnect routine will try to do
+    cancel_work_sync().  The usb_queue_reset_device() implementation is
+    carefully written to handle scenarios like this one properly.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index 79cf503e37bf..80c50763b3f8 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -116,40 +116,24 @@ static void hid_reset(struct work_struct *work)
+ 	struct usbhid_device *usbhid =
+ 		container_of(work, struct usbhid_device, reset_work);
+ 	struct hid_device *hid = usbhid->hid;
+-	int rc = 0;
++	int rc;
+ 
+ 	if (test_bit(HID_CLEAR_HALT, &usbhid->iofl)) {
+ 		dev_dbg(&usbhid->intf->dev, "clear halt\n");
+ 		rc = usb_clear_halt(hid_to_usb_dev(hid), usbhid->urbin->pipe);
+ 		clear_bit(HID_CLEAR_HALT, &usbhid->iofl);
+-		hid_start_in(hid);
+-	}
+-
+-	else if (test_bit(HID_RESET_PENDING, &usbhid->iofl)) {
+-		dev_dbg(&usbhid->intf->dev, "resetting device\n");
+-		rc = usb_lock_device_for_reset(hid_to_usb_dev(hid), usbhid->intf);
+ 		if (rc == 0) {
+-			rc = usb_reset_device(hid_to_usb_dev(hid));
+-			usb_unlock_device(hid_to_usb_dev(hid));
++			hid_start_in(hid);
++		} else {
++			dev_dbg(&usbhid->intf->dev,
++					"clear-halt failed: %d\n", rc);
++			set_bit(HID_RESET_PENDING, &usbhid->iofl);
+ 		}
+-		clear_bit(HID_RESET_PENDING, &usbhid->iofl);
+ 	}
+ 
+-	switch (rc) {
+-	case 0:
+-		if (!test_bit(HID_IN_RUNNING, &usbhid->iofl))
+-			hid_io_error(hid);
+-		break;
+-	default:
+-		hid_err(hid, "can't reset device, %s-%s/input%d, status %d\n",
+-			hid_to_usb_dev(hid)->bus->bus_name,
+-			hid_to_usb_dev(hid)->devpath,
+-			usbhid->ifnum, rc);
+-		/* FALLTHROUGH */
+-	case -EHOSTUNREACH:
+-	case -ENODEV:
+-	case -EINTR:
+-		break;
++	if (test_bit(HID_RESET_PENDING, &usbhid->iofl)) {
++		dev_dbg(&usbhid->intf->dev, "resetting device\n");
++		usb_queue_reset_device(usbhid->intf);
+ 	}
+ }
+ 

commit 499b3803d3e2f062f73bf22372b38393369ffcbf
+Author: Alan Stern 
+Date:   Fri Jul 18 16:26:17 2014 -0400
+
+    USB: OHCI: add check for stopped frame counter
+    
+    This patch adds an extra check to ohci-hcd's I/O watchdog routine.  If
+    the controller stops updating the frame counter, we will assume it is
+    dead.  But there has to be an exception: Some controllers stop the
+    frame counter when no ports are connected.  Check to make sure there
+    is at least one active port before deciding the controller is dead.
+    
+    (This test may appear racy, but it isn't.  Enabling a newly connected
+    port takes several milliseconds, during which time the frame counter
+    must advance.)
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Dennis New 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index aba8f19eae4d..46987735a2e3 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -72,7 +72,7 @@
+ static const char	hcd_name [] = "ohci_hcd";
+ 
+ #define	STATECHANGE_DELAY	msecs_to_jiffies(300)
+-#define IO_WATCHDOG_DELAY	msecs_to_jiffies(250)
++#define	IO_WATCHDOG_DELAY	msecs_to_jiffies(250)
+ 
+ #include "ohci.h"
+ #include "pci-quirks.h"
+@@ -230,9 +230,11 @@ static int ohci_urb_enqueue (
+ 
+ 		/* Start up the I/O watchdog timer, if it's not running */
+ 		if (!timer_pending(&ohci->io_watchdog) &&
+-				list_empty(&ohci->eds_in_use))
++				list_empty(&ohci->eds_in_use)) {
++			ohci->prev_frame_no = ohci_frame_no(ohci);
+ 			mod_timer(&ohci->io_watchdog,
+ 					jiffies + IO_WATCHDOG_DELAY);
++		}
+ 		list_add(&ed->in_use_list, &ohci->eds_in_use);
+ 
+ 		if (ed->type == PIPE_ISOCHRONOUS) {
+@@ -727,6 +729,7 @@ static void io_watchdog_func(unsigned long _ohci)
+ 	u32		head;
+ 	struct ed	*ed;
+ 	struct td	*td, *td_start, *td_next;
++	unsigned	frame_no;
+ 	unsigned long	flags;
+ 
+ 	spin_lock_irqsave(&ohci->lock, flags);
+@@ -742,6 +745,7 @@ static void io_watchdog_func(unsigned long _ohci)
+ 	if (!(status & OHCI_INTR_WDH) && ohci->wdh_cnt == ohci->prev_wdh_cnt) {
+ 		if (ohci->prev_donehead) {
+ 			ohci_err(ohci, "HcDoneHead not written back; disabled\n");
++ died:
+ 			usb_hc_died(ohci_to_hcd(ohci));
+ 			ohci_dump(ohci);
+ 			ohci_shutdown(ohci_to_hcd(ohci));
+@@ -802,7 +806,35 @@ static void io_watchdog_func(unsigned long _ohci)
+ 	ohci_work(ohci);
+ 
+ 	if (ohci->rh_state == OHCI_RH_RUNNING) {
++
++		/*
++		 * Sometimes a controller just stops working.  We can tell
++		 * by checking that the frame counter has advanced since
++		 * the last time we ran.
++		 *
++		 * But be careful: Some controllers violate the spec by
++		 * stopping their frame counter when no ports are active.
++		 */
++		frame_no = ohci_frame_no(ohci);
++		if (frame_no == ohci->prev_frame_no) {
++			int		active_cnt = 0;
++			int		i;
++			unsigned	tmp;
++
++			for (i = 0; i < ohci->num_ports; ++i) {
++				tmp = roothub_portstatus(ohci, i);
++				/* Enabled and not suspended? */
++				if ((tmp & RH_PS_PES) && !(tmp & RH_PS_PSS))
++					++active_cnt;
++			}
++
++			if (active_cnt > 0) {
++				ohci_err(ohci, "frame counter not updating; disabled\n");
++				goto died;
++			}
++		}
+ 		if (!list_empty(&ohci->eds_in_use)) {
++			ohci->prev_frame_no = frame_no;
+ 			ohci->prev_wdh_cnt = ohci->wdh_cnt;
+ 			ohci->prev_donehead = ohci_readl(ohci,
+ 					&ohci->regs->donehead);
+diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
+index 0548f5ca18e2..59f424567a8d 100644
+--- a/drivers/usb/host/ohci.h
++++ b/drivers/usb/host/ohci.h
+@@ -421,6 +421,7 @@ struct ohci_hcd {
+ 
+ 	// there are also chip quirks/bugs in init logic
+ 
++	unsigned		prev_frame_no;
+ 	unsigned		wdh_cnt, prev_wdh_cnt;
+ 	u32			prev_donehead;
+ 	struct timer_list	io_watchdog;

commit 81e38333513cec155c720432226dabe9f9f76a77
+Author: Alan Stern 
+Date:   Fri Jul 18 16:26:12 2014 -0400
+
+    USB: OHCI: add I/O watchdog for orphan TDs
+    
+    Some OHCI controllers have a bug: They fail to add completed TDs to
+    the done queue.  Examining this queue is the only method ohci-hcd has
+    for telling when a transfer is complete; failure to add a TD can
+    result in an URB that never completes and cannot be unlinked.
+    
+    This patch adds a watchdog routine to ohci-hcd.  The routine
+    periodically scans the active ED and TD lists, looking for TDs which
+    are finished but not on the done queue.  When one is found, and it is
+    certain that the controller hardware will never add the TD to the done
+    queue, the watchdog routine manually puts the TD on the done list so
+    that it can be handled normally.
+    
+    The watchdog routine also checks for a condition indicating the
+    controller has died.  If the done queue is non-empty but the
+    HccaDoneHead pointer hasn't been updated for a few hundred
+    milliseconds, we assume the controller will never update it and
+    therefore is dead.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index ad588538e2e7..aba8f19eae4d 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -72,12 +72,14 @@
+ static const char	hcd_name [] = "ohci_hcd";
+ 
+ #define	STATECHANGE_DELAY	msecs_to_jiffies(300)
++#define IO_WATCHDOG_DELAY	msecs_to_jiffies(250)
+ 
+ #include "ohci.h"
+ #include "pci-quirks.h"
+ 
+ static void ohci_dump(struct ohci_hcd *ohci);
+ static void ohci_stop(struct usb_hcd *hcd);
++static void io_watchdog_func(unsigned long _ohci);
+ 
+ #include "ohci-hub.c"
+ #include "ohci-dbg.c"
+@@ -225,6 +227,14 @@ static int ohci_urb_enqueue (
+ 			usb_hcd_unlink_urb_from_ep(hcd, urb);
+ 			goto fail;
+ 		}
++
++		/* Start up the I/O watchdog timer, if it's not running */
++		if (!timer_pending(&ohci->io_watchdog) &&
++				list_empty(&ohci->eds_in_use))
++			mod_timer(&ohci->io_watchdog,
++					jiffies + IO_WATCHDOG_DELAY);
++		list_add(&ed->in_use_list, &ohci->eds_in_use);
++
+ 		if (ed->type == PIPE_ISOCHRONOUS) {
+ 			u16	frame = ohci_frame_no(ohci);
+ 
+@@ -416,6 +426,7 @@ ohci_shutdown (struct usb_hcd *hcd)
+ 	udelay(10);
+ 
+ 	ohci_writel(ohci, ohci->fminterval, &ohci->regs->fminterval);
++	ohci->rh_state = OHCI_RH_HALTED;
+ }
+ 
+ /*-------------------------------------------------------------------------*
+@@ -484,6 +495,10 @@ static int ohci_init (struct ohci_hcd *ohci)
+ 	if (ohci->hcca)
+ 		return 0;
+ 
++	setup_timer(&ohci->io_watchdog, io_watchdog_func,
++			(unsigned long) ohci);
++	set_timer_slack(&ohci->io_watchdog, msecs_to_jiffies(20));
++
+ 	ohci->hcca = dma_alloc_coherent (hcd->self.controller,
+ 			sizeof(*ohci->hcca), &ohci->hcca_dma, GFP_KERNEL);
+ 	if (!ohci->hcca)
+@@ -694,6 +709,112 @@ static int ohci_start(struct usb_hcd *hcd)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++/*
++ * Some OHCI controllers are known to lose track of completed TDs.  They
++ * don't add the TDs to the hardware done queue, which means we never see
++ * them as being completed.
++ *
++ * This watchdog routine checks for such problems.  Without some way to
++ * tell when those TDs have completed, we would never take their EDs off
++ * the unlink list.  As a result, URBs could never be dequeued and
++ * endpoints could never be released.
++ */
++static void io_watchdog_func(unsigned long _ohci)
++{
++	struct ohci_hcd	*ohci = (struct ohci_hcd *) _ohci;
++	bool		takeback_all_pending = false;
++	u32		status;
++	u32		head;
++	struct ed	*ed;
++	struct td	*td, *td_start, *td_next;
++	unsigned long	flags;
++
++	spin_lock_irqsave(&ohci->lock, flags);
++
++	/*
++	 * One way to lose track of completed TDs is if the controller
++	 * never writes back the done queue head.  If it hasn't been
++	 * written back since the last time this function ran and if it
++	 * was non-empty at that time, something is badly wrong with the
++	 * hardware.
++	 */
++	status = ohci_readl(ohci, &ohci->regs->intrstatus);
++	if (!(status & OHCI_INTR_WDH) && ohci->wdh_cnt == ohci->prev_wdh_cnt) {
++		if (ohci->prev_donehead) {
++			ohci_err(ohci, "HcDoneHead not written back; disabled\n");
++			usb_hc_died(ohci_to_hcd(ohci));
++			ohci_dump(ohci);
++			ohci_shutdown(ohci_to_hcd(ohci));
++			goto done;
++		} else {
++			/* No write back because the done queue was empty */
++			takeback_all_pending = true;
++		}
++	}
++
++	/* Check every ED which might have pending TDs */
++	list_for_each_entry(ed, &ohci->eds_in_use, in_use_list) {
++		if (ed->pending_td) {
++			if (takeback_all_pending ||
++					OKAY_TO_TAKEBACK(ohci, ed)) {
++				unsigned tmp = hc32_to_cpu(ohci, ed->hwINFO);
++
++				ohci_dbg(ohci, "takeback pending TD for dev %d ep 0x%x\n",
++						0x007f & tmp,
++						(0x000f & (tmp >> 7)) +
++							((tmp & ED_IN) >> 5));
++				add_to_done_list(ohci, ed->pending_td);
++			}
++		}
++
++		/* Starting from the latest pending TD, */
++		td = ed->pending_td;
++
++		/* or the last TD on the done list, */
++		if (!td) {
++			list_for_each_entry(td_next, &ed->td_list, td_list) {
++				if (!td_next->next_dl_td)
++					break;
++				td = td_next;
++			}
++		}
++
++		/* find the last TD processed by the controller. */
++		head = hc32_to_cpu(ohci, ACCESS_ONCE(ed->hwHeadP)) & TD_MASK;
++		td_start = td;
++		td_next = list_prepare_entry(td, &ed->td_list, td_list);
++		list_for_each_entry_continue(td_next, &ed->td_list, td_list) {
++			if (head == (u32) td_next->td_dma)
++				break;
++			td = td_next;	/* head pointer has passed this TD */
++		}
++		if (td != td_start) {
++			/*
++			 * In case a WDH cycle is in progress, we will wait
++			 * for the next two cycles to complete before assuming
++			 * this TD will never get on the done queue.
++			 */
++			ed->takeback_wdh_cnt = ohci->wdh_cnt + 2;
++			ed->pending_td = td;
++		}
++	}
++
++	ohci_work(ohci);
++
++	if (ohci->rh_state == OHCI_RH_RUNNING) {
++		if (!list_empty(&ohci->eds_in_use)) {
++			ohci->prev_wdh_cnt = ohci->wdh_cnt;
++			ohci->prev_donehead = ohci_readl(ohci,
++					&ohci->regs->donehead);
++			mod_timer(&ohci->io_watchdog,
++					jiffies + IO_WATCHDOG_DELAY);
++		}
++	}
++
++ done:
++	spin_unlock_irqrestore(&ohci->lock, flags);
++}
++
+ /* an interrupt happens */
+ 
+ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
+@@ -796,6 +917,9 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
+ 
+ 	if (ohci->rh_state == OHCI_RH_RUNNING) {
+ 		ohci_writel (ohci, ints, ®s->intrstatus);
++		if (ints & OHCI_INTR_WDH)
++			++ohci->wdh_cnt;
++
+ 		ohci_writel (ohci, OHCI_INTR_MIE, ®s->intrenable);
+ 		// flush those writes
+ 		(void) ohci_readl (ohci, &ohci->regs->control);
+@@ -815,6 +939,7 @@ static void ohci_stop (struct usb_hcd *hcd)
+ 
+ 	if (quirk_nec(ohci))
+ 		flush_work(&ohci->nec_work);
++	del_timer_sync(&ohci->io_watchdog);
+ 
+ 	ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
+ 	ohci_usb_reset(ohci);
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index 8991692bcfb8..17d32b0ea565 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -309,6 +309,9 @@ static int ohci_bus_suspend (struct usb_hcd *hcd)
+ 	else
+ 		rc = ohci_rh_suspend (ohci, 0);
+ 	spin_unlock_irq (&ohci->lock);
++
++	if (rc == 0)
++		del_timer_sync(&ohci->io_watchdog);
+ 	return rc;
+ }
+ 
+diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c
+index 2f20d3dc895b..c9e315c6808a 100644
+--- a/drivers/usb/host/ohci-mem.c
++++ b/drivers/usb/host/ohci-mem.c
+@@ -28,6 +28,7 @@ static void ohci_hcd_init (struct ohci_hcd *ohci)
+ 	ohci->next_statechange = jiffies;
+ 	spin_lock_init (&ohci->lock);
+ 	INIT_LIST_HEAD (&ohci->pending);
++	INIT_LIST_HEAD(&ohci->eds_in_use);
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
+index 1974ddc68e45..1463c398d322 100644
+--- a/drivers/usb/host/ohci-q.c
++++ b/drivers/usb/host/ohci-q.c
+@@ -921,6 +921,11 @@ static void add_to_done_list(struct ohci_hcd *ohci, struct td *td)
+ 	 * that td is on the done list.
+ 	 */
+ 	ohci->dl_end = td->next_dl_td = td;
++
++	/* Did we just add the latest pending TD? */
++	td2 = ed->pending_td;
++	if (td2 && td2->next_dl_td)
++		ed->pending_td = NULL;
+ }
+ 
+ /* Get the entries on the hardware done queue and put them on our list */
+@@ -1082,6 +1087,7 @@ static void finish_unlinks(struct ohci_hcd *ohci)
+ 		if (list_empty(&ed->td_list)) {
+ 			*last = ed->ed_next;
+ 			ed->ed_next = NULL;
++			list_del(&ed->in_use_list);
+ 		} else if (ohci->rh_state == OHCI_RH_RUNNING) {
+ 			*last = ed->ed_next;
+ 			ed->ed_next = NULL;
+diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
+index ef348c2e1e4b..0548f5ca18e2 100644
+--- a/drivers/usb/host/ohci.h
++++ b/drivers/usb/host/ohci.h
+@@ -47,6 +47,7 @@ struct ed {
+ 	struct ed		*ed_next;	/* on schedule or rm_list */
+ 	struct ed		*ed_prev;	/* for non-interrupt EDs */
+ 	struct list_head	td_list;	/* "shadow list" of our TDs */
++	struct list_head	in_use_list;
+ 
+ 	/* create --> IDLE --> OPER --> ... --> IDLE --> destroy
+ 	 * usually:  OPER --> UNLINK --> (IDLE | OPER) --> ...
+@@ -66,6 +67,13 @@ struct ed {
+ 
+ 	/* HC may see EDs on rm_list until next frame (frame_no == tick) */
+ 	u16			tick;
++
++	/* Detect TDs not added to the done queue */
++	unsigned		takeback_wdh_cnt;
++	struct td		*pending_td;
++#define	OKAY_TO_TAKEBACK(ohci, ed)			\
++		((int) (ohci->wdh_cnt - ed->takeback_wdh_cnt) >= 0)
++
+ } __attribute__ ((aligned(16)));
+ 
+ #define ED_MASK	((u32)~0x0f)		/* strip hw status in low addr bits */
+@@ -382,6 +390,7 @@ struct ohci_hcd {
+ 	struct td		*td_hash [TD_HASH_SIZE];
+ 	struct td		*dl_start, *dl_end;	/* the done list */
+ 	struct list_head	pending;
++	struct list_head	eds_in_use;	/* all EDs with at least 1 TD */
+ 
+ 	/*
+ 	 * driver state
+@@ -412,6 +421,10 @@ struct ohci_hcd {
+ 
+ 	// there are also chip quirks/bugs in init logic
+ 
++	unsigned		wdh_cnt, prev_wdh_cnt;
++	u32			prev_donehead;
++	struct timer_list	io_watchdog;
++
+ 	struct work_struct	nec_work;	/* Worker for NEC quirk */
+ 
+ 	struct dentry		*debug_dir;

commit cdb4dd15e62eb984d9461b520d15d00ff2b88d9d
+Author: Alan Stern 
+Date:   Fri Jul 18 16:26:07 2014 -0400
+
+    USB: OHCI: make URB completions single-threaded
+    
+    URBs for a particular endpoint should complete sequentially.  That is,
+    we shouldn't call the completion handler for one URB until the handler
+    for the previous URB has returned.
+    
+    When the OHCI watchdog routine is added, there will be two paths for
+    completing URBs: interrupt handler and watchdog routine.  Their
+    activities have to be synchronized so that completions don't occur in
+    multiple threads concurrently.
+    
+    For that purpose, this patch creates an ohci_work() routine which will
+    be responsible for calling process_done_list() and finish_unlinks(),
+    the two routines that detect when an URB is complete.  Everything will
+    funnel through ohci_work(), and it will be careful not to run in more
+    than one thread at a time.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index 3112799bba7f..ad588538e2e7 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -316,7 +316,7 @@ static int ohci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ 
+ 		if (ohci->rh_state != OHCI_RH_RUNNING) {
+ 			/* With HC dead, we can clean up right away */
+-			finish_unlinks(ohci, 0);
++			ohci_work(ohci);
+ 		}
+ 	}
+ 	spin_unlock_irqrestore (&ohci->lock, flags);
+@@ -349,7 +349,7 @@ ohci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 	if (ohci->rh_state != OHCI_RH_RUNNING) {
+ sanitize:
+ 		ed->state = ED_IDLE;
+-		finish_unlinks (ohci, 0);
++		ohci_work(ohci);
+ 	}
+ 
+ 	switch (ed->state) {
+@@ -789,9 +789,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
+ 	/* handle any pending URB/ED unlinks, leaving INTR_SF enabled
+ 	 * when there's still unlinking to be done (next frame).
+ 	 */
+-	process_done_list(ohci);
+-	if (ohci->ed_rm_list)
+-		finish_unlinks (ohci, ohci_frame_no(ohci));
++	ohci_work(ohci);
+ 	if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list
+ 			&& ohci->rh_state == OHCI_RH_RUNNING)
+ 		ohci_writel (ohci, OHCI_INTR_SF, ®s->intrdisable);
+@@ -879,7 +877,7 @@ int ohci_restart(struct ohci_hcd *ohci)
+ 		if (!urb->unlinked)
+ 			urb->unlinked = -ESHUTDOWN;
+ 	}
+-	finish_unlinks (ohci, 0);
++	ohci_work(ohci);
+ 	spin_unlock_irq(&ohci->lock);
+ 
+ 	/* paranoia, in case that didn't work: */
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index dccb90edd66e..8991692bcfb8 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -40,8 +40,7 @@
+ 	(OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
+ 
+ static void update_done_list(struct ohci_hcd *);
+-static void process_done_list(struct ohci_hcd *);
+-static void finish_unlinks (struct ohci_hcd *, u16);
++static void ohci_work(struct ohci_hcd *);
+ 
+ #ifdef	CONFIG_PM
+ static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop)
+@@ -89,8 +88,7 @@ __acquires(ohci->lock)
+ 		spin_lock_irq (&ohci->lock);
+ 	}
+ 	update_done_list(ohci);
+-	process_done_list(ohci);
+-	finish_unlinks (ohci, ohci_frame_no(ohci));
++	ohci_work(ohci);
+ 
+ 	/*
+ 	 * Some controllers don't handle "global" suspend properly if
+diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
+index f36b2fa0ee2f..1974ddc68e45 100644
+--- a/drivers/usb/host/ohci-q.c
++++ b/drivers/usb/host/ohci-q.c
+@@ -964,9 +964,9 @@ static void update_done_list(struct ohci_hcd *ohci)
+ /*-------------------------------------------------------------------------*/
+ 
+ /* there are some urbs/eds to unlink; called in_irq(), with HCD locked */
+-static void
+-finish_unlinks (struct ohci_hcd *ohci, u16 tick)
++static void finish_unlinks(struct ohci_hcd *ohci)
+ {
++	unsigned	tick = ohci_frame_no(ohci);
+ 	struct ed	*ed, **last;
+ 
+ rescan_all:
+@@ -1202,3 +1202,27 @@ static void process_done_list(struct ohci_hcd *ohci)
+ 		takeback_td(ohci, td);
+ 	}
+ }
++
++/*
++ * TD takeback and URB giveback must be single-threaded.
++ * This routine takes care of it all.
++ */
++static void ohci_work(struct ohci_hcd *ohci)
++{
++	if (ohci->working) {
++		ohci->restart_work = 1;
++		return;
++	}
++	ohci->working = 1;
++
++ restart:
++	process_done_list(ohci);
++	if (ohci->ed_rm_list)
++		finish_unlinks(ohci);
++
++	if (ohci->restart_work) {
++		ohci->restart_work = 0;
++		goto restart;
++	}
++	ohci->working = 0;
++}
+diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
+index a8259bc6fd8b..ef348c2e1e4b 100644
+--- a/drivers/usb/host/ohci.h
++++ b/drivers/usb/host/ohci.h
+@@ -393,6 +393,8 @@ struct ohci_hcd {
+ 	unsigned long		next_statechange;	/* suspend/resume */
+ 	u32			fminterval;		/* saved register */
+ 	unsigned		autostop:1;	/* rh auto stopping/stopped */
++	unsigned		working:1;
++	unsigned		restart_work:1;
+ 
+ 	unsigned long		flags;		/* for HC bugs */
+ #define	OHCI_QUIRK_AMD756	0x01			/* erratum #4 */

commit c6fcb85ea22889527ee44aba42c3e3b479fd2d92
+Author: Alan Stern 
+Date:   Fri Jul 18 16:25:59 2014 -0400
+
+    USB: OHCI: redesign the TD done list
+    
+    This patch changes the way ohci-hcd handles the TD done list.  In
+    addition to relying on the TD pointers stored by the controller
+    hardware, we need to handle TDs that the hardware has forgotten about.
+    
+    This means the list has to exist even while the dl_done_list() routine
+    isn't running.  That function essentially gets split in two:
+    update_done_list() reads the TD pointers stored by the hardware and
+    adds the TDs to the done list, and process_done_list() scans through
+    the list to handle URB completions.  When we detect a TD that the
+    hardware forgot about, we will be able to add it to the done list
+    manually and then process it normally.
+    
+    Since the list is really a queue, and because there can be a lot of
+    TDs, keep the existing singly linked implementation.  To insure that
+    URBs are given back in order of submission, whenever a TD is added to
+    the done list, all the preceding TDs for the same endpoint must be
+    added as well (going back to the first one that isn't already on the
+    done list).
+    
+    The done list manipulations must all be protected by the private
+    lock.  The scope of the lock is expanded in preparation for the
+    watchdog routine to be added in a later patch.
+    
+    We have to be more careful about giving back unlinked URBs.  Since TDs
+    may be added to the done list by the watchdog routine and not in
+    response to a controller interrupt, we have to check explicitly to
+    make sure all the URB's TDs that were added to the done list have been
+    processed before giving back the URB.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index 52829276a44e..3112799bba7f 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -780,24 +780,21 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
+ 			usb_hcd_resume_root_hub(hcd);
+ 	}
+ 
+-	if (ints & OHCI_INTR_WDH) {
+-		spin_lock (&ohci->lock);
+-		dl_done_list (ohci);
+-		spin_unlock (&ohci->lock);
+-	}
++	spin_lock(&ohci->lock);
++	if (ints & OHCI_INTR_WDH)
++		update_done_list(ohci);
+ 
+ 	/* could track INTR_SO to reduce available PCI/... bandwidth */
+ 
+ 	/* handle any pending URB/ED unlinks, leaving INTR_SF enabled
+ 	 * when there's still unlinking to be done (next frame).
+ 	 */
+-	spin_lock (&ohci->lock);
++	process_done_list(ohci);
+ 	if (ohci->ed_rm_list)
+ 		finish_unlinks (ohci, ohci_frame_no(ohci));
+ 	if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list
+ 			&& ohci->rh_state == OHCI_RH_RUNNING)
+ 		ohci_writel (ohci, OHCI_INTR_SF, ®s->intrdisable);
+-	spin_unlock (&ohci->lock);
+ 
+ 	if (ohci->rh_state == OHCI_RH_RUNNING) {
+ 		ohci_writel (ohci, ints, ®s->intrstatus);
+@@ -805,6 +802,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
+ 		// flush those writes
+ 		(void) ohci_readl (ohci, &ohci->regs->control);
+ 	}
++	spin_unlock(&ohci->lock);
+ 
+ 	return IRQ_HANDLED;
+ }
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index b4940de1eba3..dccb90edd66e 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -39,7 +39,8 @@
+ #define OHCI_SCHED_ENABLES \
+ 	(OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
+ 
+-static void dl_done_list (struct ohci_hcd *);
++static void update_done_list(struct ohci_hcd *);
++static void process_done_list(struct ohci_hcd *);
+ static void finish_unlinks (struct ohci_hcd *, u16);
+ 
+ #ifdef	CONFIG_PM
+@@ -87,7 +88,8 @@ __acquires(ohci->lock)
+ 		msleep (8);
+ 		spin_lock_irq (&ohci->lock);
+ 	}
+-	dl_done_list (ohci);
++	update_done_list(ohci);
++	process_done_list(ohci);
+ 	finish_unlinks (ohci, ohci_frame_no(ohci));
+ 
+ 	/*
+diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
+index a9f4f04c3fad..f36b2fa0ee2f 100644
+--- a/drivers/usb/host/ohci-q.c
++++ b/drivers/usb/host/ohci-q.c
+@@ -892,13 +892,41 @@ static void ed_halted(struct ohci_hcd *ohci, struct td *td, int cc)
+ 	}
+ }
+ 
+-/* replies to the request have to be on a FIFO basis so
+- * we unreverse the hc-reversed done-list
+- */
+-static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
++/* Add a TD to the done list */
++static void add_to_done_list(struct ohci_hcd *ohci, struct td *td)
++{
++	struct td	*td2, *td_prev;
++	struct ed	*ed;
++
++	if (td->next_dl_td)
++		return;		/* Already on the list */
++
++	/* Add all the TDs going back until we reach one that's on the list */
++	ed = td->ed;
++	td2 = td_prev = td;
++	list_for_each_entry_continue_reverse(td2, &ed->td_list, td_list) {
++		if (td2->next_dl_td)
++			break;
++		td2->next_dl_td = td_prev;
++		td_prev = td2;
++	}
++
++	if (ohci->dl_end)
++		ohci->dl_end->next_dl_td = td_prev;
++	else
++		ohci->dl_start = td_prev;
++
++	/*
++	 * Make td->next_dl_td point to td itself, to mark the fact
++	 * that td is on the done list.
++	 */
++	ohci->dl_end = td->next_dl_td = td;
++}
++
++/* Get the entries on the hardware done queue and put them on our list */
++static void update_done_list(struct ohci_hcd *ohci)
+ {
+ 	u32		td_dma;
+-	struct td	*td_rev = NULL;
+ 	struct td	*td = NULL;
+ 
+ 	td_dma = hc32_to_cpup (ohci, &ohci->hcca->done_head);
+@@ -906,7 +934,7 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
+ 	wmb();
+ 
+ 	/* get TD from hc's singly linked list, and
+-	 * prepend to ours.  ed->td_list changes later.
++	 * add to ours.  ed->td_list changes later.
+ 	 */
+ 	while (td_dma) {
+ 		int		cc;
+@@ -928,11 +956,9 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
+ 				&& (td->ed->hwHeadP & cpu_to_hc32 (ohci, ED_H)))
+ 			ed_halted(ohci, td, cc);
+ 
+-		td->next_dl_td = td_rev;
+-		td_rev = td;
+ 		td_dma = hc32_to_cpup (ohci, &td->hwNextTD);
++		add_to_done_list(ohci, td);
+ 	}
+-	return td_rev;
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -956,26 +982,27 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick)
+ 		/* only take off EDs that the HC isn't using, accounting for
+ 		 * frame counter wraps and EDs with partially retired TDs
+ 		 */
+-		if (likely(ohci->rh_state == OHCI_RH_RUNNING)) {
+-			if (tick_before (tick, ed->tick)) {
++		if (likely(ohci->rh_state == OHCI_RH_RUNNING) &&
++				tick_before(tick, ed->tick)) {
+ skip_ed:
+-				last = &ed->ed_next;
+-				continue;
+-			}
++			last = &ed->ed_next;
++			continue;
++		}
++		if (!list_empty(&ed->td_list)) {
++			struct td	*td;
++			u32		head;
+ 
+-			if (!list_empty (&ed->td_list)) {
+-				struct td	*td;
+-				u32		head;
++			td = list_first_entry(&ed->td_list, struct td, td_list);
+ 
+-				td = list_entry (ed->td_list.next, struct td,
+-							td_list);
+-				head = hc32_to_cpu (ohci, ed->hwHeadP) &
+-								TD_MASK;
++			/* INTR_WDH may need to clean up first */
++			head = hc32_to_cpu(ohci, ed->hwHeadP) & TD_MASK;
++			if (td->td_dma != head &&
++					ohci->rh_state == OHCI_RH_RUNNING)
++				goto skip_ed;
+ 
+-				/* INTR_WDH may need to clean up first */
+-				if (td->td_dma != head)
+-					goto skip_ed;
+-			}
++			/* Don't mess up anything already on the done list */
++			if (td->next_dl_td)
++				goto skip_ed;
+ 		}
+ 
+ 		/* ED's now officially unlinked, hc doesn't see */
+@@ -1161,33 +1188,17 @@ static void takeback_td(struct ohci_hcd *ohci, struct td *td)
+  * normal path is finish_unlinks(), which unlinks URBs using ed_rm_list,
+  * instead of scanning the (re-reversed) donelist as this does.
+  */
+-static void
+-dl_done_list (struct ohci_hcd *ohci)
++static void process_done_list(struct ohci_hcd *ohci)
+ {
+-	struct td	*td = dl_reverse_done_list (ohci);
+-
+-	while (td) {
+-		struct td	*td_next = td->next_dl_td;
+-		struct ed	*ed = td->ed;
++	struct td	*td;
+ 
+-		/*
+-		 * Some OHCI controllers (NVIDIA for sure, maybe others)
+-		 * occasionally forget to add TDs to the done queue.  Since
+-		 * TDs for a given endpoint are always processed in order,
+-		 * if we find a TD on the donelist then all of its
+-		 * predecessors must be finished as well.
+-		 */
+-		for (;;) {
+-			struct td	*td2;
+-
+-			td2 = list_first_entry(&ed->td_list, struct td,
+-					td_list);
+-			if (td2 == td)
+-				break;
+-			takeback_td(ohci, td2);
+-		}
++	while (ohci->dl_start) {
++		td = ohci->dl_start;
++		if (td == ohci->dl_end)
++			ohci->dl_start = ohci->dl_end = NULL;
++		else
++			ohci->dl_start = td->next_dl_td;
+ 
+ 		takeback_td(ohci, td);
+-		td = td_next;
+ 	}
+ }
+diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
+index 392932dd6318..a8259bc6fd8b 100644
+--- a/drivers/usb/host/ohci.h
++++ b/drivers/usb/host/ohci.h
+@@ -380,6 +380,7 @@ struct ohci_hcd {
+ 	struct dma_pool		*td_cache;
+ 	struct dma_pool		*ed_cache;
+ 	struct td		*td_hash [TD_HASH_SIZE];
++	struct td		*dl_start, *dl_end;	/* the done list */
+ 	struct list_head	pending;
+ 
+ 	/*

commit 8b3ab0edaf6acd281243bf974fac7e01c9574d08
+Author: Alan Stern 
+Date:   Fri Jul 18 16:25:49 2014 -0400
+
+    USB: OHCI: no shortcut for unlinking URBS from a dead controller
+    
+    When an URB is unlinked from a dead controller, ohci-hcd gives back
+    the URB with no regard for cleaning up the internal data structures.
+    This won't play nicely with the upcoming changes to the TD done
+    list.
+    
+    Therefore make ohci_urb_dequeue() call finish_unlinks(), which uses
+    td_done() to do a proper cleanup, rather than calling finish_urb()
+    directly.  Also, remove the checks that urb_priv is non-NULL; the
+    driver guarantees that urb_priv will never be NULL for a valid URB.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index a8f0e1b00e7d..52829276a44e 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -300,30 +300,24 @@ static int ohci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+ 	unsigned long		flags;
+ 	int			rc;
++	urb_priv_t		*urb_priv;
+ 
+ 	spin_lock_irqsave (&ohci->lock, flags);
+ 	rc = usb_hcd_check_unlink_urb(hcd, urb, status);
+-	if (rc) {
+-		;	/* Do nothing */
+-	} else if (ohci->rh_state == OHCI_RH_RUNNING) {
+-		urb_priv_t  *urb_priv;
++	if (rc == 0) {
+ 
+ 		/* Unless an IRQ completed the unlink while it was being
+ 		 * handed to us, flag it for unlink and giveback, and force
+ 		 * some upcoming INTR_SF to call finish_unlinks()
+ 		 */
+ 		urb_priv = urb->hcpriv;
+-		if (urb_priv) {
+-			if (urb_priv->ed->state == ED_OPER)
+-				start_ed_unlink (ohci, urb_priv->ed);
++		if (urb_priv->ed->state == ED_OPER)
++			start_ed_unlink(ohci, urb_priv->ed);
++
++		if (ohci->rh_state != OHCI_RH_RUNNING) {
++			/* With HC dead, we can clean up right away */
++			finish_unlinks(ohci, 0);
+ 		}
+-	} else {
+-		/*
+-		 * with HC dead, we won't respect hc queue pointers
+-		 * any more ... just clean up every urb's memory.
+-		 */
+-		if (urb->hcpriv)
+-			finish_urb(ohci, urb, status);
+ 	}
+ 	spin_unlock_irqrestore (&ohci->lock, flags);
+ 	return rc;

commit 95d9a01d727fdb6d2b667ac374341c48777cc41e
+Author: Alan Stern 
+Date:   Fri Jul 18 16:25:36 2014 -0400
+
+    USB: OHCI: revert the ZF Micro orphan-TD quirk
+    
+    This patch reverts the important parts of commit 89a0fd18a96e (USB:
+    OHCI handles more ZFMicro quirks), namely, the parts related to
+    handling orphan TDs for interrupt endpoints.  A later patch in this
+    series will introduce a more general mechanism that applies to all
+    endpoint types and all controllers.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index 7570098b1cfa..a8f0e1b00e7d 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -355,8 +355,6 @@ ohci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 	if (ohci->rh_state != OHCI_RH_RUNNING) {
+ sanitize:
+ 		ed->state = ED_IDLE;
+-		if (quirk_zfmicro(ohci) && ed->type == PIPE_INTERRUPT)
+-			ohci->eds_scheduled--;
+ 		finish_unlinks (ohci, 0);
+ 	}
+ 
+@@ -365,11 +363,6 @@ ohci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 		/* major IRQ delivery trouble loses INTR_SF too... */
+ 		if (limit-- == 0) {
+ 			ohci_warn(ohci, "ED unlink timeout\n");
+-			if (quirk_zfmicro(ohci)) {
+-				ohci_warn(ohci, "Attempting ZF TD recovery\n");
+-				ohci->ed_to_check = ed;
+-				ohci->zf_delay = 2;
+-			}
+ 			goto sanitize;
+ 		}
+ 		spin_unlock_irqrestore (&ohci->lock, flags);
+@@ -431,93 +424,6 @@ ohci_shutdown (struct usb_hcd *hcd)
+ 	ohci_writel(ohci, ohci->fminterval, &ohci->regs->fminterval);
+ }
+ 
+-static int check_ed(struct ohci_hcd *ohci, struct ed *ed)
+-{
+-	return (hc32_to_cpu(ohci, ed->hwINFO) & ED_IN) != 0
+-		&& (hc32_to_cpu(ohci, ed->hwHeadP) & TD_MASK)
+-			== (hc32_to_cpu(ohci, ed->hwTailP) & TD_MASK)
+-		&& !list_empty(&ed->td_list);
+-}
+-
+-/* ZF Micro watchdog timer callback. The ZF Micro chipset sometimes completes
+- * an interrupt TD but neglects to add it to the donelist.  On systems with
+- * this chipset, we need to periodically check the state of the queues to look
+- * for such "lost" TDs.
+- */
+-static void unlink_watchdog_func(unsigned long _ohci)
+-{
+-	unsigned long	flags;
+-	unsigned	max;
+-	unsigned	seen_count = 0;
+-	unsigned	i;
+-	struct ed	**seen = NULL;
+-	struct ohci_hcd	*ohci = (struct ohci_hcd *) _ohci;
+-
+-	spin_lock_irqsave(&ohci->lock, flags);
+-	max = ohci->eds_scheduled;
+-	if (!max)
+-		goto done;
+-
+-	if (ohci->ed_to_check)
+-		goto out;
+-
+-	seen = kcalloc(max, sizeof *seen, GFP_ATOMIC);
+-	if (!seen)
+-		goto out;
+-
+-	for (i = 0; i < NUM_INTS; i++) {
+-		struct ed	*ed = ohci->periodic[i];
+-
+-		while (ed) {
+-			unsigned	temp;
+-
+-			/* scan this branch of the periodic schedule tree */
+-			for (temp = 0; temp < seen_count; temp++) {
+-				if (seen[temp] == ed) {
+-					/* we've checked it and what's after */
+-					ed = NULL;
+-					break;
+-				}
+-			}
+-			if (!ed)
+-				break;
+-			seen[seen_count++] = ed;
+-			if (!check_ed(ohci, ed)) {
+-				ed = ed->ed_next;
+-				continue;
+-			}
+-
+-			/* HC's TD list is empty, but HCD sees at least one
+-			 * TD that's not been sent through the donelist.
+-			 */
+-			ohci->ed_to_check = ed;
+-			ohci->zf_delay = 2;
+-
+-			/* The HC may wait until the next frame to report the
+-			 * TD as done through the donelist and INTR_WDH.  (We
+-			 * just *assume* it's not a multi-TD interrupt URB;
+-			 * those could defer the IRQ more than one frame, using
+-			 * DI...)  Check again after the next INTR_SF.
+-			 */
+-			ohci_writel(ohci, OHCI_INTR_SF,
+-					&ohci->regs->intrstatus);
+-			ohci_writel(ohci, OHCI_INTR_SF,
+-					&ohci->regs->intrenable);
+-
+-			/* flush those writes */
+-			(void) ohci_readl(ohci, &ohci->regs->control);
+-
+-			goto out;
+-		}
+-	}
+-out:
+-	kfree(seen);
+-	if (ohci->eds_scheduled)
+-		mod_timer(&ohci->unlink_watchdog, round_jiffies(jiffies + HZ));
+-done:
+-	spin_unlock_irqrestore(&ohci->lock, flags);
+-}
+-
+ /*-------------------------------------------------------------------------*
+  * HC functions
+  *-------------------------------------------------------------------------*/
+@@ -761,15 +667,6 @@ static int ohci_run (struct ohci_hcd *ohci)
+ 	// POTPGT delay is bits 24-31, in 2 ms units.
+ 	mdelay ((val >> 23) & 0x1fe);
+ 
+-	if (quirk_zfmicro(ohci)) {
+-		/* Create timer to watch for bad queue state on ZF Micro */
+-		setup_timer(&ohci->unlink_watchdog, unlink_watchdog_func,
+-				(unsigned long) ohci);
+-
+-		ohci->eds_scheduled = 0;
+-		ohci->ed_to_check = NULL;
+-	}
+-
+ 	ohci_dump(ohci);
+ 
+ 	return 0;
+@@ -895,31 +792,6 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
+ 		spin_unlock (&ohci->lock);
+ 	}
+ 
+-	if (quirk_zfmicro(ohci) && (ints & OHCI_INTR_SF)) {
+-		spin_lock(&ohci->lock);
+-		if (ohci->ed_to_check) {
+-			struct ed *ed = ohci->ed_to_check;
+-
+-			if (check_ed(ohci, ed)) {
+-				/* HC thinks the TD list is empty; HCD knows
+-				 * at least one TD is outstanding
+-				 */
+-				if (--ohci->zf_delay == 0) {
+-					struct td *td = list_entry(
+-						ed->td_list.next,
+-						struct td, td_list);
+-					ohci_warn(ohci,
+-						  "Reclaiming orphan TD %p\n",
+-						  td);
+-					takeback_td(ohci, td);
+-					ohci->ed_to_check = NULL;
+-				}
+-			} else
+-				ohci->ed_to_check = NULL;
+-		}
+-		spin_unlock(&ohci->lock);
+-	}
+-
+ 	/* could track INTR_SO to reduce available PCI/... bandwidth */
+ 
+ 	/* handle any pending URB/ED unlinks, leaving INTR_SF enabled
+@@ -928,9 +800,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
+ 	spin_lock (&ohci->lock);
+ 	if (ohci->ed_rm_list)
+ 		finish_unlinks (ohci, ohci_frame_no(ohci));
+-	if ((ints & OHCI_INTR_SF) != 0
+-			&& !ohci->ed_rm_list
+-			&& !ohci->ed_to_check
++	if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list
+ 			&& ohci->rh_state == OHCI_RH_RUNNING)
+ 		ohci_writel (ohci, OHCI_INTR_SF, ®s->intrdisable);
+ 	spin_unlock (&ohci->lock);
+@@ -961,8 +831,6 @@ static void ohci_stop (struct usb_hcd *hcd)
+ 	free_irq(hcd->irq, hcd);
+ 	hcd->irq = 0;
+ 
+-	if (quirk_zfmicro(ohci))
+-		del_timer(&ohci->unlink_watchdog);
+ 	if (quirk_amdiso(ohci))
+ 		usb_amd_dev_put();
+ 
+diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
+index a6376f3e55cb..a9f4f04c3fad 100644
+--- a/drivers/usb/host/ohci-q.c
++++ b/drivers/usb/host/ohci-q.c
+@@ -187,10 +187,6 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed)
+ 	ed->ed_prev = NULL;
+ 	ed->ed_next = NULL;
+ 	ed->hwNextED = 0;
+-	if (quirk_zfmicro(ohci)
+-			&& (ed->type == PIPE_INTERRUPT)
+-			&& !(ohci->eds_scheduled++))
+-		mod_timer(&ohci->unlink_watchdog, round_jiffies(jiffies + HZ));
+ 	wmb ();
+ 
+ 	/* we care about rm_list when setting CLE/BLE in case the HC was at
+@@ -977,19 +973,13 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick)
+ 								TD_MASK;
+ 
+ 				/* INTR_WDH may need to clean up first */
+-				if (td->td_dma != head) {
+-					if (ed == ohci->ed_to_check)
+-						ohci->ed_to_check = NULL;
+-					else
+-						goto skip_ed;
+-				}
++				if (td->td_dma != head)
++					goto skip_ed;
+ 			}
+ 		}
+ 
+ 		/* ED's now officially unlinked, hc doesn't see */
+ 		ed->state = ED_IDLE;
+-		if (quirk_zfmicro(ohci) && ed->type == PIPE_INTERRUPT)
+-			ohci->eds_scheduled--;
+ 		ed->hwHeadP &= ~cpu_to_hc32(ohci, ED_H);
+ 		ed->hwNextED = 0;
+ 		wmb();
+@@ -1122,12 +1112,7 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-/*
+- * Used to take back a TD from the host controller. This would normally be
+- * called from within dl_done_list, however it may be called directly if the
+- * HC no longer sees the TD and it has not appeared on the donelist (after
+- * two frames).  This bug has been observed on ZF Micro systems.
+- */
++/* Take back a TD from the host controller */
+ static void takeback_td(struct ohci_hcd *ohci, struct td *td)
+ {
+ 	struct urb	*urb = td->urb;
+@@ -1174,9 +1159,7 @@ static void takeback_td(struct ohci_hcd *ohci, struct td *td)
+  *
+  * This is the main path for handing urbs back to drivers.  The only other
+  * normal path is finish_unlinks(), which unlinks URBs using ed_rm_list,
+- * instead of scanning the (re-reversed) donelist as this does.  There's
+- * an abnormal path too, handling a quirk in some Compaq silicon:  URBs
+- * with TDs that appear to be orphaned are directly reclaimed.
++ * instead of scanning the (re-reversed) donelist as this does.
+  */
+ static void
+ dl_done_list (struct ohci_hcd *ohci)
+diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
+index 05e02a709d4f..392932dd6318 100644
+--- a/drivers/usb/host/ohci.h
++++ b/drivers/usb/host/ohci.h
+@@ -411,12 +411,6 @@ struct ohci_hcd {
+ 
+ 	struct work_struct	nec_work;	/* Worker for NEC quirk */
+ 
+-	/* Needed for ZF Micro quirk */
+-	struct timer_list	unlink_watchdog;
+-	unsigned		eds_scheduled;
+-	struct ed		*ed_to_check;
+-	unsigned		zf_delay;
+-
+ 	struct dentry		*debug_dir;
+ 	struct dentry		*debug_async;
+ 	struct dentry		*debug_periodic;

commit 977dcfdc60311e7aa571cabf6f39c36dde13339e
+Author: Alan Stern 
+Date:   Thu Jul 17 16:34:29 2014 -0400
+
+    USB: OHCI: don't lose track of EDs when a controller dies
+    
+    This patch fixes a bug in ohci-hcd.  When an URB is unlinked, the
+    corresponding Endpoint Descriptor is added to the ed_rm_list and taken
+    off the hardware schedule.  Once the ED is no longer visible to the
+    hardware, finish_unlinks() handles the URBs that were unlinked or have
+    completed.  If any URBs remain attached to the ED, the ED is added
+    back to the hardware schedule -- but only if the controller is
+    running.
+    
+    This fails when a controller dies.  A non-empty ED does not get added
+    back to the hardware schedule and does not remain on the ed_rm_list;
+    ohci-hcd loses track of it.  The remaining URBs cannot be unlinked,
+    which causes the USB stack to hang.
+    
+    The patch changes finish_unlinks() so that non-empty EDs remain on
+    the ed_rm_list if the controller isn't running.  This requires moving
+    some of the existing code around, to avoid modifying the ED's hardware
+    fields more than once.
+    
+    Signed-off-by: Alan Stern 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
+index 517d04d5c150..a6376f3e55cb 100644
+--- a/drivers/usb/host/ohci-q.c
++++ b/drivers/usb/host/ohci-q.c
+@@ -311,8 +311,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed)
+  *  - ED_OPER: when there's any request queued, the ED gets rescheduled
+  *    immediately.  HC should be working on them.
+  *
+- *  - ED_IDLE:  when there's no TD queue. there's no reason for the HC
+- *    to care about this ED; safe to disable the endpoint.
++ *  - ED_IDLE: when there's no TD queue or the HC isn't running.
+  *
+  * When finish_unlinks() runs later, after SOF interrupt, it will often
+  * complete one or more URB unlinks before making that state change.
+@@ -954,6 +953,10 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick)
+ 		int			completed, modified;
+ 		__hc32			*prev;
+ 
++		/* Is this ED already invisible to the hardware? */
++		if (ed->state == ED_IDLE)
++			goto ed_idle;
++
+ 		/* only take off EDs that the HC isn't using, accounting for
+ 		 * frame counter wraps and EDs with partially retired TDs
+ 		 */
+@@ -983,12 +986,20 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick)
+ 			}
+ 		}
+ 
++		/* ED's now officially unlinked, hc doesn't see */
++		ed->state = ED_IDLE;
++		if (quirk_zfmicro(ohci) && ed->type == PIPE_INTERRUPT)
++			ohci->eds_scheduled--;
++		ed->hwHeadP &= ~cpu_to_hc32(ohci, ED_H);
++		ed->hwNextED = 0;
++		wmb();
++		ed->hwINFO &= ~cpu_to_hc32(ohci, ED_SKIP | ED_DEQUEUE);
++ed_idle:
++
+ 		/* reentrancy:  if we drop the schedule lock, someone might
+ 		 * have modified this list.  normally it's just prepending
+ 		 * entries (which we'd ignore), but paranoia won't hurt.
+ 		 */
+-		*last = ed->ed_next;
+-		ed->ed_next = NULL;
+ 		modified = 0;
+ 
+ 		/* unlink urbs as requested, but rescan the list after
+@@ -1046,19 +1057,20 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick)
+ 		if (completed && !list_empty (&ed->td_list))
+ 			goto rescan_this;
+ 
+-		/* ED's now officially unlinked, hc doesn't see */
+-		ed->state = ED_IDLE;
+-		if (quirk_zfmicro(ohci) && ed->type == PIPE_INTERRUPT)
+-			ohci->eds_scheduled--;
+-		ed->hwHeadP &= ~cpu_to_hc32(ohci, ED_H);
+-		ed->hwNextED = 0;
+-		wmb ();
+-		ed->hwINFO &= ~cpu_to_hc32 (ohci, ED_SKIP | ED_DEQUEUE);
+-
+-		/* but if there's work queued, reschedule */
+-		if (!list_empty (&ed->td_list)) {
+-			if (ohci->rh_state == OHCI_RH_RUNNING)
+-				ed_schedule (ohci, ed);
++		/*
++		 * If no TDs are queued, take ED off the ed_rm_list.
++		 * Otherwise, if the HC is running, reschedule.
++		 * If not, leave it on the list for further dequeues.
++		 */
++		if (list_empty(&ed->td_list)) {
++			*last = ed->ed_next;
++			ed->ed_next = NULL;
++		} else if (ohci->rh_state == OHCI_RH_RUNNING) {
++			*last = ed->ed_next;
++			ed->ed_next = NULL;
++			ed_schedule(ohci, ed);
++		} else {
++			last = &ed->ed_next;
+ 		}
+ 
+ 		if (modified)

commit 256dbcd80f1ccf8abf421c1d72ba79a4e29941dd
+Author: Alan Stern 
+Date:   Thu Jul 17 16:32:26 2014 -0400
+
+    USB: OHCI: fix bugs in debug routines
+    
+    The debug routine fill_async_buffer() in ohci-hcd is buggy: It never
+    produces any output because it forgets to initialize the output buffer
+    size.  Also, the debug routine ohci_dump() has an unused argument.
+    
+    This patch adds the correct initialization and removes the unused
+    argument.
+    
+    Signed-off-by: Alan Stern 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
+index 45032e933e18..04f2186939d2 100644
+--- a/drivers/usb/host/ohci-dbg.c
++++ b/drivers/usb/host/ohci-dbg.c
+@@ -236,7 +236,7 @@ ohci_dump_roothub (
+ 	}
+ }
+ 
+-static void ohci_dump (struct ohci_hcd *controller, int verbose)
++static void ohci_dump(struct ohci_hcd *controller)
+ {
+ 	ohci_dbg (controller, "OHCI controller state\n");
+ 
+@@ -464,15 +464,16 @@ show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed)
+ static ssize_t fill_async_buffer(struct debug_buffer *buf)
+ {
+ 	struct ohci_hcd		*ohci;
+-	size_t			temp;
++	size_t			temp, size;
+ 	unsigned long		flags;
+ 
+ 	ohci = buf->ohci;
++	size = PAGE_SIZE;
+ 
+ 	/* display control and bulk lists together, for simplicity */
+ 	spin_lock_irqsave (&ohci->lock, flags);
+-	temp = show_list(ohci, buf->page, buf->count, ohci->ed_controltail);
+-	temp += show_list(ohci, buf->page + temp, buf->count - temp,
++	temp = show_list(ohci, buf->page, size, ohci->ed_controltail);
++	temp += show_list(ohci, buf->page + temp, size - temp,
+ 			  ohci->ed_bulktail);
+ 	spin_unlock_irqrestore (&ohci->lock, flags);
+ 
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index 7f94c586c5dc..7570098b1cfa 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -76,8 +76,8 @@ static const char	hcd_name [] = "ohci_hcd";
+ #include "ohci.h"
+ #include "pci-quirks.h"
+ 
+-static void ohci_dump (struct ohci_hcd *ohci, int verbose);
+-static void ohci_stop (struct usb_hcd *hcd);
++static void ohci_dump(struct ohci_hcd *ohci);
++static void ohci_stop(struct usb_hcd *hcd);
+ 
+ #include "ohci-hub.c"
+ #include "ohci-dbg.c"
+@@ -770,7 +770,7 @@ static int ohci_run (struct ohci_hcd *ohci)
+ 		ohci->ed_to_check = NULL;
+ 	}
+ 
+-	ohci_dump (ohci, 1);
++	ohci_dump(ohci);
+ 
+ 	return 0;
+ }
+@@ -851,7 +851,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
+ 			usb_hc_died(hcd);
+ 		}
+ 
+-		ohci_dump (ohci, 1);
++		ohci_dump(ohci);
+ 		ohci_usb_reset (ohci);
+ 	}
+ 
+@@ -951,7 +951,7 @@ static void ohci_stop (struct usb_hcd *hcd)
+ {
+ 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+ 
+-	ohci_dump (ohci, 1);
++	ohci_dump(ohci);
+ 
+ 	if (quirk_nec(ohci))
+ 		flush_work(&ohci->nec_work);

commit 6f65126c76e38e671c64ec171acff8a99c4de749
+Author: Alan Stern 
+Date:   Thu Jul 17 16:30:01 2014 -0400
+
+    USB: OHCI: add SG support
+    
+    Apparently nobody ever remembered to add Scatter-Gather support to
+    ohci-hcd.  This patch adds it.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index 6f8ec52c7e0c..7f94c586c5dc 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -109,6 +109,33 @@ MODULE_PARM_DESC (no_handshake, "true (not default) disables BIOS handshake");
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++static int number_of_tds(struct urb *urb)
++{
++	int			len, i, num, this_sg_len;
++	struct scatterlist	*sg;
++
++	len = urb->transfer_buffer_length;
++	i = urb->num_mapped_sgs;
++
++	if (len > 0 && i > 0) {		/* Scatter-gather transfer */
++		num = 0;
++		sg = urb->sg;
++		for (;;) {
++			this_sg_len = min_t(int, sg_dma_len(sg), len);
++			num += DIV_ROUND_UP(this_sg_len, 4096);
++			len -= this_sg_len;
++			if (--i <= 0 || len <= 0)
++				break;
++			sg = sg_next(sg);
++		}
++
++	} else {			/* Non-SG transfer */
++		/* one TD for every 4096 Bytes (could be up to 8K) */
++		num = DIV_ROUND_UP(len, 4096);
++	}
++	return num;
++}
++
+ /*
+  * queue up an urb for anything except the root hub
+  */
+@@ -142,12 +169,8 @@ static int ohci_urb_enqueue (
+ 		// case PIPE_INTERRUPT:
+ 		// case PIPE_BULK:
+ 		default:
+-			/* one TD for every 4096 Bytes (can be up to 8K) */
+-			size += urb->transfer_buffer_length / 4096;
+-			/* ... and for any remaining bytes ... */
+-			if ((urb->transfer_buffer_length % 4096) != 0)
+-				size++;
+-			/* ... and maybe a zero length packet to wrap it up */
++			size += number_of_tds(urb);
++			/* maybe a zero-length packet to wrap it up */
+ 			if (size == 0)
+ 				size++;
+ 			else if ((urb->transfer_flags & URB_ZERO_PACKET) != 0
+@@ -506,6 +529,9 @@ static int ohci_init (struct ohci_hcd *ohci)
+ 	int ret;
+ 	struct usb_hcd *hcd = ohci_to_hcd(ohci);
+ 
++	/* Accept arbitrarily long scatter-gather lists */
++	hcd->self.sg_tablesize = ~0;
++
+ 	if (distrust_firmware)
+ 		ohci->flags |= OHCI_QUIRK_HUB_POWER;
+ 
+diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
+index d4253e319428..517d04d5c150 100644
+--- a/drivers/usb/host/ohci-q.c
++++ b/drivers/usb/host/ohci-q.c
+@@ -602,6 +602,8 @@ static void td_submit_urb (
+ 	u32		info = 0;
+ 	int		is_out = usb_pipeout (urb->pipe);
+ 	int		periodic = 0;
++	int		i, this_sg_len, n;
++	struct scatterlist	*sg;
+ 
+ 	/* OHCI handles the bulk/interrupt data toggles itself.  We just
+ 	 * use the device toggle bits for resetting, and rely on the fact
+@@ -615,10 +617,24 @@ static void td_submit_urb (
+ 
+ 	list_add (&urb_priv->pending, &ohci->pending);
+ 
+-	if (data_len)
+-		data = urb->transfer_dma;
+-	else
+-		data = 0;
++	i = urb->num_mapped_sgs;
++	if (data_len > 0 && i > 0) {
++		sg = urb->sg;
++		data = sg_dma_address(sg);
++
++		/*
++		 * urb->transfer_buffer_length may be smaller than the
++		 * size of the scatterlist (or vice versa)
++		 */
++		this_sg_len = min_t(int, sg_dma_len(sg), data_len);
++	} else {
++		sg = NULL;
++		if (data_len)
++			data = urb->transfer_dma;
++		else
++			data = 0;
++		this_sg_len = data_len;
++	}
+ 
+ 	/* NOTE:  TD_CC is set so we can tell which TDs the HC processed by
+ 	 * using TD_CC_GET, as well as by seeing them on the done list.
+@@ -639,17 +655,29 @@ static void td_submit_urb (
+ 			? TD_T_TOGGLE | TD_CC | TD_DP_OUT
+ 			: TD_T_TOGGLE | TD_CC | TD_DP_IN;
+ 		/* TDs _could_ transfer up to 8K each */
+-		while (data_len > 4096) {
+-			td_fill (ohci, info, data, 4096, urb, cnt);
+-			data += 4096;
+-			data_len -= 4096;
++		for (;;) {
++			n = min(this_sg_len, 4096);
++
++			/* maybe avoid ED halt on final TD short read */
++			if (n >= data_len || (i == 1 && n >= this_sg_len)) {
++				if (!(urb->transfer_flags & URB_SHORT_NOT_OK))
++					info |= TD_R;
++			}
++			td_fill(ohci, info, data, n, urb, cnt);
++			this_sg_len -= n;
++			data_len -= n;
++			data += n;
+ 			cnt++;
++
++			if (this_sg_len <= 0) {
++				if (--i <= 0 || data_len <= 0)
++					break;
++				sg = sg_next(sg);
++				data = sg_dma_address(sg);
++				this_sg_len = min_t(int, sg_dma_len(sg),
++						data_len);
++			}
+ 		}
+-		/* maybe avoid ED halt on final TD short read */
+-		if (!(urb->transfer_flags & URB_SHORT_NOT_OK))
+-			info |= TD_R;
+-		td_fill (ohci, info, data, data_len, urb, cnt);
+-		cnt++;
+ 		if ((urb->transfer_flags & URB_ZERO_PACKET)
+ 				&& cnt < urb_priv->length) {
+ 			td_fill (ohci, info, 0, 0, urb, cnt);

commit 1299cff9fa39811cd1b3f1731527b062425f0541
+Author: Alan Stern 
+Date:   Thu Jul 17 15:40:57 2014 -0400
+
+    USB: shutdown all URBs after controller death
+    
+    When a host controller dies, we don't need to wait for a driver to
+    time out.  We can shut down its URBs immediately.  Without this
+    change, we can end up waiting 30 seconds for a mass-storage transfer
+    to time out.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 4aeb10034de7..9bffd26cea05 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -417,10 +417,11 @@ static int usb_unbind_interface(struct device *dev)
+ 	 */
+ 	lpm_disable_error = usb_unlocked_disable_lpm(udev);
+ 
+-	/* Terminate all URBs for this interface unless the driver
+-	 * supports "soft" unbinding.
++	/*
++	 * Terminate all URBs for this interface unless the driver
++	 * supports "soft" unbinding and the device is still present.
+ 	 */
+-	if (!driver->soft_unbind)
++	if (!driver->soft_unbind || udev->state == USB_STATE_NOTATTACHED)
+ 		usb_disable_interface(udev, intf, false);
+ 
+ 	driver->disconnect(intf);

commit b14bf2d0c0358140041d1c1805a674376964d0e0
+Author: Alan Stern 
+Date:   Mon Jun 30 11:04:21 2014 -0400
+
+    usb-storage/SCSI: Add broken_fua blacklist flag
+    
+    Some buggy JMicron USB-ATA bridges don't know how to translate the FUA
+    bit in READs or WRITEs.  This patch adds an entry in unusual_devs.h
+    and a blacklist flag to tell the sd driver not to use FUA.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Michael Büsch 
+    Tested-by: Michael Büsch 
+    Acked-by: James Bottomley 
+    CC: Matthew Dharm 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+index e9689d57ccb6..6825eda1114a 100644
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -2441,7 +2441,10 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
+ 		}
+ 
+ 		sdkp->DPOFUA = (data.device_specific & 0x10) != 0;
+-		if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw) {
++		if (sdp->broken_fua) {
++			sd_first_printk(KERN_NOTICE, sdkp, "Disabling FUA\n");
++			sdkp->DPOFUA = 0;
++		} else if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw) {
+ 			sd_first_printk(KERN_NOTICE, sdkp,
+ 				  "Uses READ/WRITE(6), disabling FUA\n");
+ 			sdkp->DPOFUA = 0;
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index 9d38ddc8da49..866b5df36ed1 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -256,6 +256,10 @@ static int slave_configure(struct scsi_device *sdev)
+ 		if (us->fflags & US_FL_WRITE_CACHE)
+ 			sdev->wce_default_on = 1;
+ 
++		/* A few buggy USB-ATA bridges don't understand FUA */
++		if (us->fflags & US_FL_BROKEN_FUA)
++			sdev->broken_fua = 1;
++
+ 	} else {
+ 
+ 		/* Non-disk-type devices don't need to blacklist any pages
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 174a447868cd..80a5b366255f 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -1936,6 +1936,13 @@ UNUSUAL_DEV(  0x14cd, 0x6600, 0x0201, 0x0201,
+ 		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ 		US_FL_IGNORE_RESIDUE ),
+ 
++/* Reported by Michael Büsch  */
++UNUSUAL_DEV(  0x152d, 0x0567, 0x0114, 0x0114,
++		"JMicron",
++		"USB to ATA/ATAPI Bridge",
++		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
++		US_FL_BROKEN_FUA ),
++
+ /* Reported by Alexandre Oliva 
+  * JMicron responds to USN and several other SCSI ioctls with a
+  * residue that causes subsequent I/O requests to fail.  */
+diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
+index 1a64b26046ed..9b7de1b46437 100644
+--- a/include/linux/usb_usual.h
++++ b/include/linux/usb_usual.h
+@@ -70,7 +70,9 @@
+ 	US_FLAG(NEEDS_CAP16,	0x00400000)			\
+ 		/* cannot handle READ_CAPACITY_10 */		\
+ 	US_FLAG(IGNORE_UAS,	0x00800000)			\
+-		/* Device advertises UAS but it is broken */
++		/* Device advertises UAS but it is broken */	\
++	US_FLAG(BROKEN_FUA,	0x01000000)			\
++		/* Cannot handle FUA in WRITE or READ CDBs */	\
+ 
+ #define US_FLAG(name, value)	US_FL_##name = value ,
+ enum { US_DO_ALL_FLAGS };
+diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
+index 5853c913d2b0..27ab31017f09 100644
+--- a/include/scsi/scsi_device.h
++++ b/include/scsi/scsi_device.h
+@@ -173,6 +173,7 @@ struct scsi_device {
+ 	unsigned is_visible:1;	/* is the device visible in sysfs */
+ 	unsigned wce_default_on:1;	/* Cache is ON by default */
+ 	unsigned no_dif:1;	/* T10 PI (DIF) should be disabled */
++	unsigned broken_fua:1;		/* Don't set FUA bit */
+ 
+ 	atomic_t disk_events_disable_depth; /* disable depth for disk events */
+ 

commit 32b36eeae6a859670d2939a7d6136cb5e9ed64f8
+Author: Alan Stern 
+Date:   Tue Jun 3 11:11:34 2014 -0400
+
+    USB: usbtest: add a timeout for scatter-gather tests
+    
+    In usbtest, tests 5 - 8 use the scatter-gather library in usbcore
+    without any sort of timeout.  If there's a problem in the gadget or
+    host controller being tested, the test can hang.
+    
+    This patch adds a 10-second timeout to the tests, so that they will
+    fail gracefully with an ETIMEDOUT error instead of hanging.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Huang Rui 
+    Tested-by: Huang Rui 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
+index 51a6da256772..829f446064ea 100644
+--- a/drivers/usb/misc/usbtest.c
++++ b/drivers/usb/misc/usbtest.c
+@@ -7,7 +7,7 @@
+ #include 
+ #include 
+ #include 
+-
++#include 
+ #include 
+ 
+ #define SIMPLE_IO_TIMEOUT	10000	/* in milliseconds */
+@@ -484,6 +484,14 @@ alloc_sglist(int nents, int max, int vary)
+ 	return sg;
+ }
+ 
++static void sg_timeout(unsigned long _req)
++{
++	struct usb_sg_request	*req = (struct usb_sg_request *) _req;
++
++	req->status = -ETIMEDOUT;
++	usb_sg_cancel(req);
++}
++
+ static int perform_sglist(
+ 	struct usbtest_dev	*tdev,
+ 	unsigned		iterations,
+@@ -495,6 +503,9 @@ static int perform_sglist(
+ {
+ 	struct usb_device	*udev = testdev_to_usbdev(tdev);
+ 	int			retval = 0;
++	struct timer_list	sg_timer;
++
++	setup_timer_on_stack(&sg_timer, sg_timeout, (unsigned long) req);
+ 
+ 	while (retval == 0 && iterations-- > 0) {
+ 		retval = usb_sg_init(req, udev, pipe,
+@@ -505,7 +516,10 @@ static int perform_sglist(
+ 
+ 		if (retval)
+ 			break;
++		mod_timer(&sg_timer, jiffies +
++				msecs_to_jiffies(SIMPLE_IO_TIMEOUT));
+ 		usb_sg_wait(req);
++		del_timer_sync(&sg_timer);
+ 		retval = req->status;
+ 
+ 		/* FIXME check resulting data pattern */

commit b0a50e92bda3c4aeb8017d4e6c6e92146ebd5c9b
+Author: Alan Stern 
+Date:   Tue Jun 3 11:00:27 2014 -0400
+
+    USB: EHCI: avoid BIOS handover on the HASEE E200
+    
+    Leandro Liptak reports that his HASEE E200 computer hangs when we ask
+    the BIOS to hand over control of the EHCI host controller.  This
+    definitely sounds like a bug in the BIOS, but at the moment there is
+    no way to fix it.
+    
+    This patch works around the problem by avoiding the handoff whenever
+    the motherboard and BIOS version match those of Leandro's computer.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Leandro Liptak 
+    Tested-by: Leandro Liptak 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
+index 4a6d3dd68572..2f3acebb577a 100644
+--- a/drivers/usb/host/pci-quirks.c
++++ b/drivers/usb/host/pci-quirks.c
+@@ -656,6 +656,14 @@ static const struct dmi_system_id ehci_dmi_nohandoff_table[] = {
+ 			DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"),
+ 		},
+ 	},
++	{
++		/* HASEE E200 */
++		.matches = {
++			DMI_MATCH(DMI_BOARD_VENDOR, "HASEE"),
++			DMI_MATCH(DMI_BOARD_NAME, "E210"),
++			DMI_MATCH(DMI_BIOS_VERSION, "6.00"),
++		},
++	},
+ 	{ }
+ };
+ 
+@@ -665,9 +673,14 @@ static void ehci_bios_handoff(struct pci_dev *pdev,
+ {
+ 	int try_handoff = 1, tried_handoff = 0;
+ 
+-	/* The Pegatron Lucid tablet sporadically waits for 98 seconds trying
+-	 * the handoff on its unused controller.  Skip it. */
+-	if (pdev->vendor == 0x8086 && pdev->device == 0x283a) {
++	/*
++	 * The Pegatron Lucid tablet sporadically waits for 98 seconds trying
++	 * the handoff on its unused controller.  Skip it.
++	 *
++	 * The HASEE E200 hangs when the semaphore is set (bugzilla #77021).
++	 */
++	if (pdev->vendor == 0x8086 && (pdev->device == 0x283a ||
++			pdev->device == 0x27cc)) {
+ 		if (dmi_check_system(ehci_dmi_nohandoff_table))
+ 			try_handoff = 0;
+ 	}

commit 600856c231ccb0cbf8afcf09066a8ab2a93ab03d
+Author: Alan Stern 
+Date:   Tue May 20 18:08:07 2014 -0700
+
+    USB: mutual exclusion for resetting a hub and power-managing a port
+    
+    The USB core doesn't properly handle mutual exclusion between
+    resetting a hub and changing the power states of the hub's ports.  We
+    need to avoid sending port-power requests to the hub while it is being
+    reset, because such requests cannot succeed.
+    
+    This patch fixes the problem by keeping track of when a reset is in
+    progress.  At such times, attempts to suspend (power-off) a port will
+    fail immediately with -EBUSY, and calls to usb_port_runtime_resume()
+    will update the power_is_on flag and return immediately.  When the
+    reset is complete, hub_activate() will automatically restore each port
+    to the proper power state.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Dan Williams 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 726fa072c3fe..5f43c22ba787 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1276,12 +1276,22 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
+ 		flush_work(&hub->tt.clear_work);
+ }
+ 
++static void hub_pm_barrier_for_all_ports(struct usb_hub *hub)
++{
++	int i;
++
++	for (i = 0; i < hub->hdev->maxchild; ++i)
++		pm_runtime_barrier(&hub->ports[i]->dev);
++}
++
+ /* caller has locked the hub device */
+ static int hub_pre_reset(struct usb_interface *intf)
+ {
+ 	struct usb_hub *hub = usb_get_intfdata(intf);
+ 
+ 	hub_quiesce(hub, HUB_PRE_RESET);
++	hub->in_reset = 1;
++	hub_pm_barrier_for_all_ports(hub);
+ 	return 0;
+ }
+ 
+@@ -1290,6 +1300,8 @@ static int hub_post_reset(struct usb_interface *intf)
+ {
+ 	struct usb_hub *hub = usb_get_intfdata(intf);
+ 
++	hub->in_reset = 0;
++	hub_pm_barrier_for_all_ports(hub);
+ 	hub_activate(hub, HUB_POST_RESET);
+ 	return 0;
+ }
+diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
+index 33bcb2c6f90a..f9b521e60128 100644
+--- a/drivers/usb/core/hub.h
++++ b/drivers/usb/core/hub.h
+@@ -66,6 +66,7 @@ struct usb_hub {
+ 	unsigned		limited_power:1;
+ 	unsigned		quiescing:1;
+ 	unsigned		disconnected:1;
++	unsigned		in_reset:1;
+ 
+ 	unsigned		quirk_check_port_auto_suspend:1;
+ 
+diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
+index 51542f852393..37647e080599 100644
+--- a/drivers/usb/core/port.c
++++ b/drivers/usb/core/port.c
+@@ -81,6 +81,10 @@ static int usb_port_runtime_resume(struct device *dev)
+ 
+ 	if (!hub)
+ 		return -EINVAL;
++	if (hub->in_reset) {
++		port_dev->power_is_on = 1;
++		return 0;
++	}
+ 
+ 	usb_autopm_get_interface(intf);
+ 	set_bit(port1, hub->busy_bits);
+@@ -117,6 +121,8 @@ static int usb_port_runtime_suspend(struct device *dev)
+ 
+ 	if (!hub)
+ 		return -EINVAL;
++	if (hub->in_reset)
++		return -EBUSY;
+ 
+ 	if (dev_pm_qos_flags(&port_dev->dev, PM_QOS_FLAG_NO_POWER_OFF)
+ 			== PM_QOS_FLAGS_ALL)

commit 8ef42ddd9a53b73e6fc3934278710c27f80f324f
+Author: Alan Stern 
+Date:   Fri May 23 10:45:54 2014 -0400
+
+    USB: Avoid runtime suspend loops for HCDs that can't handle suspend/resume
+    
+    Not all host controller drivers have bus-suspend and bus-resume
+    methods.  When one doesn't, it will cause problems if runtime PM is
+    enabled in the kernel.  The PM core will attempt to suspend the
+    controller's root hub, the suspend will fail because there is no
+    bus-suspend routine, and a -EBUSY error code will be returned to the
+    PM core.  This will cause the suspend attempt to be repeated shortly
+    thereafter, in a never-ending loop.
+    
+    Part of the problem is that the original error code -ENOENT gets
+    changed to -EBUSY in usb_runtime_suspend(), on the grounds that the PM
+    core will interpret -ENOENT as meaning that the root hub has gotten
+    into a runtime-PM error state.  While this change is appropriate for
+    real USB devices, it's not such a good idea for a root hub.  In fact,
+    considering the root hub to be in a runtime-PM error state would not
+    be far from the truth.  Therefore this patch updates
+    usb_runtime_suspend() so that it adjusts error codes only for
+    non-root-hub devices.
+    
+    Furthermore, the patch attempts to prevent the problem from occurring
+    in the first place by not enabling runtime PM by default for root hubs
+    whose host controller driver doesn't have bus_suspend and bus_resume
+    methods.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Will Deacon 
+    Tested-by: Will Deacon 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 888881e5f292..4aeb10034de7 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1822,10 +1822,13 @@ int usb_runtime_suspend(struct device *dev)
+ 	if (status == -EAGAIN || status == -EBUSY)
+ 		usb_mark_last_busy(udev);
+ 
+-	/* The PM core reacts badly unless the return code is 0,
+-	 * -EAGAIN, or -EBUSY, so always return -EBUSY on an error.
++	/*
++	 * The PM core reacts badly unless the return code is 0,
++	 * -EAGAIN, or -EBUSY, so always return -EBUSY on an error
++	 * (except for root hubs, because they don't suspend through
++	 * an upstream port like other USB devices).
+ 	 */
+-	if (status != 0)
++	if (status != 0 && udev->parent)
+ 		return -EBUSY;
+ 	return status;
+ }
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 090469ebfcff..229a73f64304 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1691,8 +1691,19 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
+ 	 */
+ 	pm_runtime_set_autosuspend_delay(&hdev->dev, 0);
+ 
+-	/* Hubs have proper suspend/resume support. */
+-	usb_enable_autosuspend(hdev);
++	/*
++	 * Hubs have proper suspend/resume support, except for root hubs
++	 * where the controller driver doesn't have bus_suspend and
++	 * bus_resume methods.
++	 */
++	if (hdev->parent) {		/* normal device */
++		usb_enable_autosuspend(hdev);
++	} else {			/* root hub */
++		const struct hc_driver *drv = bus_to_hcd(hdev->bus)->driver;
++
++		if (drv->bus_suspend && drv->bus_resume)
++			usb_enable_autosuspend(hdev);
++	}
+ 
+ 	if (hdev->level == MAX_TOPO_LEVEL) {
+ 		dev_err(&intf->dev,

commit c1db30a2a79eb59997b13b8cabf2a50bea9f04e1
+Author: Alan Stern 
+Date:   Thu May 1 15:21:42 2014 -0400
+
+    USB: OHCI: fix problem with global suspend on ATI controllers
+    
+    Some OHCI controllers from ATI/AMD seem to have difficulty with
+    "global" USB suspend, that is, suspending an entire USB bus without
+    setting the suspend feature for each port connected to a device.  When
+    we try to resume the child devices, the controller gives timeout
+    errors on the unsuspended ports, requiring resets, and can even cause
+    ohci-hcd to hang; see
+    
+            http://marc.info/?l=linux-usb&m=139514332820398&w=2
+    
+    and the following messages.
+    
+    This patch fixes the problem by adding a new quirk flag to ohci-hcd.
+    The flag causes the ohci_rh_suspend() routine to suspend each
+    unsuspended, enabled port before suspending the root hub.  This
+    effectively converts the "global" suspend to an ordinary root-hub
+    suspend.  There is no need to unsuspend these ports when the root hub
+    is resumed, because the child devices will be resumed anyway in the
+    course of a normal system resume ("global" suspend is never used for
+    runtime PM).
+    
+    This patch should be applied to all stable kernels which include
+    commit 0aa2832dd0d9 (USB: use "global suspend" for system sleep on
+    USB-2 buses) or a backported version thereof.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Peter Münster 
+    Tested-by: Peter Münster 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index c81c8721cc5a..cd871b895013 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -90,6 +90,24 @@ __acquires(ohci->lock)
+ 	dl_done_list (ohci);
+ 	finish_unlinks (ohci, ohci_frame_no(ohci));
+ 
++	/*
++	 * Some controllers don't handle "global" suspend properly if
++	 * there are unsuspended ports.  For these controllers, put all
++	 * the enabled ports into suspend before suspending the root hub.
++	 */
++	if (ohci->flags & OHCI_QUIRK_GLOBAL_SUSPEND) {
++		__hc32 __iomem	*portstat = ohci->regs->roothub.portstatus;
++		int		i;
++		unsigned	temp;
++
++		for (i = 0; i < ohci->num_ports; (++i, ++portstat)) {
++			temp = ohci_readl(ohci, portstat);
++			if ((temp & (RH_PS_PES | RH_PS_PSS)) ==
++					RH_PS_PES)
++				ohci_writel(ohci, RH_PS_PSS, portstat);
++		}
++	}
++
+ 	/* maybe resume can wake root hub */
+ 	if (ohci_to_hcd(ohci)->self.root_hub->do_remote_wakeup || autostop) {
+ 		ohci->hc_control |= OHCI_CTRL_RWE;
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index 90879e9ccbec..bb1509675727 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -160,6 +160,7 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd)
+ 		ohci_dbg(ohci, "enabled AMD prefetch quirk\n");
+ 	}
+ 
++	ohci->flags |= OHCI_QUIRK_GLOBAL_SUSPEND;
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
+index 9250cada13f0..4550ce05af7f 100644
+--- a/drivers/usb/host/ohci.h
++++ b/drivers/usb/host/ohci.h
+@@ -405,6 +405,8 @@ struct ohci_hcd {
+ #define	OHCI_QUIRK_HUB_POWER	0x100			/* distrust firmware power/oc setup */
+ #define	OHCI_QUIRK_AMD_PLL	0x200			/* AMD PLL quirk*/
+ #define	OHCI_QUIRK_AMD_PREFETCH	0x400			/* pre-fetch for ISO transfer */
++#define	OHCI_QUIRK_GLOBAL_SUSPEND	0x800		/* must suspend ports */
++
+ 	// there are also chip quirks/bugs in init logic
+ 
+ 	struct work_struct	nec_work;	/* Worker for NEC quirk */

commit 644373a4219add42123df69c8b7ce6a918475ccd
+Author: Alan Stern 
+Date:   Fri Mar 28 10:51:15 2014 -0700
+
+    [SCSI] Fix command result state propagation
+    
+    We're seeing a case where the contents of scmd->result isn't being reset after
+    a SCSI command encounters an error, is resubmitted, times out and then gets
+    handled.  The error handler acts on the stale result of the previous error
+    instead of the timeout.  Fix this by properly zeroing the scmd->status before
+    the command is resubmitted.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
+index d020149ea8d4..2953bfa92da7 100644
+--- a/drivers/scsi/scsi_error.c
++++ b/drivers/scsi/scsi_error.c
+@@ -924,6 +924,7 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
+ 	memset(scmd->cmnd, 0, BLK_MAX_CDB);
+ 	memset(&scmd->sdb, 0, sizeof(scmd->sdb));
+ 	scmd->request->next_rq = NULL;
++	scmd->result = 0;
+ 
+ 	if (sense_bytes) {
+ 		scmd->sdb.length = min_t(unsigned, SCSI_SENSE_BUFFERSIZE,
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index 7fa54fe51f63..9db097a28a74 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -137,6 +137,7 @@ static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, int unbusy)
+ 	 * lock such that the kblockd_schedule_work() call happens
+ 	 * before blk_cleanup_queue() finishes.
+ 	 */
++	cmd->result = 0;
+ 	spin_lock_irqsave(q->queue_lock, flags);
+ 	blk_requeue_request(q, cmd->request);
+ 	kblockd_schedule_work(q, &device->requeue_work);

commit a2ff864b53eac9a0e9b05bfe9d1781ccd6c2af71
+Author: Alan Stern 
+Date:   Mon Apr 14 13:48:47 2014 -0400
+
+    USB: fix crash during hotplug of PCI USB controller card
+    
+    The code in hcd-pci.c that matches up EHCI controllers with their
+    companion UHCI or OHCI controllers assumes that the private drvdata
+    fields don't get set too early.  However, it turns out that this field
+    gets set by usb_create_hcd(), before hcd-pci expects it, and this can
+    result in a crash when two controllers are probed in parallel (as can
+    happen when a new controller card is hotplugged).
+    
+    The companions_rwsem lock was supposed to prevent this sort of thing,
+    but usb_create_hcd() is called outside the scope of the rwsem.
+    
+    A simple solution is to check that the root-hub pointer has been
+    initialized as well as the drvdata field.  This doesn't happen until
+    usb_add_hcd() is called; that call and the check are both protected by
+    the rwsem.
+    
+    This patch should be applied to stable kernels from 3.10 onward.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Stefani Seibold 
+    Tested-by: Stefani Seibold 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index d59d99347d54..1f02e65fe305 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -75,7 +75,7 @@ static void for_each_companion(struct pci_dev *pdev, struct usb_hcd *hcd,
+ 				PCI_SLOT(companion->devfn) != slot)
+ 			continue;
+ 		companion_hcd = pci_get_drvdata(companion);
+-		if (!companion_hcd)
++		if (!companion_hcd || !companion_hcd->self.root_hub)
+ 			continue;
+ 		fn(pdev, hcd, companion, companion_hcd);
+ 	}

commit 1d10255c1c496557a5674e651c4ebbe0f61279f2
+Author: Alan Stern 
+Date:   Tue Mar 18 10:39:05 2014 -0400
+
+    USB: disable reset-resume when USB_QUIRK_RESET is set
+    
+    The USB_QUIRK_RESET flag indicates that a USB device changes its
+    identity in some way when it is reset.  It may lose its firmware, its
+    descriptors may change, or it may switch back to a default mode of
+    operation.
+    
+    If a device does this, the kernel needs to avoid resetting it.  Resets
+    are likely to fail, or worse, succeed while changing the device's
+    state in a way the system can't detect.
+    
+    This means we should disable the reset-resume mechanism whenever this
+    quirk flag is present.  An attempted reset-resume will fail, the
+    device will be logically disconnected, and later on the hub driver
+    will rediscover and re-enumerate the device.  This will cause the
+    appropriate udev events to be generated, so that userspace will have a
+    chance to switch the device into its normal operating mode, if
+    necessary.
+    
+    Signed-off-by: Alan Stern 
+    CC: Oliver Neukum 
+    Reviewed-by: Hans de Goede 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 2d74dfb9c989..d670aaf13a3d 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -3105,9 +3105,19 @@ static int finish_port_resume(struct usb_device *udev)
+ 	 * operation is carried out here, after the port has been
+ 	 * resumed.
+ 	 */
+-	if (udev->reset_resume)
++	if (udev->reset_resume) {
++		/*
++		 * If the device morphs or switches modes when it is reset,
++		 * we don't want to perform a reset-resume.  We'll fail the
++		 * resume, which will cause a logical disconnect, and then
++		 * the device will be rediscovered.
++		 */
+  retry_reset_resume:
+-		status = usb_reset_and_verify_device(udev);
++		if (udev->quirks & USB_QUIRK_RESET)
++			status = -ENODEV;
++		else
++			status = usb_reset_and_verify_device(udev);
++	}
+ 
+ 	/* 10.5.4.5 says be sure devices in the tree are still there.
+ 	 * For now let's assume the device didn't go crazy on resume,

commit 6aec044cc2f5670cf3b143c151c8be846499bd15
+Author: Alan Stern 
+Date:   Wed Mar 12 11:30:38 2014 -0400
+
+    USB: unbind all interfaces before rebinding any
+    
+    When a driver doesn't have pre_reset, post_reset, or reset_resume
+    methods, the USB core unbinds that driver when its device undergoes a
+    reset or a reset-resume, and then rebinds it afterward.
+    
+    The existing straightforward implementation can lead to problems,
+    because each interface gets unbound and rebound before the next
+    interface is handled.  If a driver claims additional interfaces, the
+    claim may fail because the old binding instance may still own the
+    additional interface when the new instance tries to claim it.
+    
+    This patch fixes the problem by first unbinding all the interfaces
+    that are marked (i.e., their needs_binding flag is set) and then
+    rebinding all of them.
+    
+    The patch also makes the helper functions in driver.c a little more
+    uniform and adjusts some out-of-date comments.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: "Poulain, Loic" 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 08283d40616c..888881e5f292 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1011,8 +1011,7 @@ EXPORT_SYMBOL_GPL(usb_deregister);
+  * it doesn't support pre_reset/post_reset/reset_resume or
+  * because it doesn't support suspend/resume.
+  *
+- * The caller must hold @intf's device's lock, but not its pm_mutex
+- * and not @intf->dev.sem.
++ * The caller must hold @intf's device's lock, but not @intf's lock.
+  */
+ void usb_forced_unbind_intf(struct usb_interface *intf)
+ {
+@@ -1025,16 +1024,37 @@ void usb_forced_unbind_intf(struct usb_interface *intf)
+ 	intf->needs_binding = 1;
+ }
+ 
++/*
++ * Unbind drivers for @udev's marked interfaces.  These interfaces have
++ * the needs_binding flag set, for example by usb_resume_interface().
++ *
++ * The caller must hold @udev's device lock.
++ */
++static void unbind_marked_interfaces(struct usb_device *udev)
++{
++	struct usb_host_config	*config;
++	int			i;
++	struct usb_interface	*intf;
++
++	config = udev->actconfig;
++	if (config) {
++		for (i = 0; i < config->desc.bNumInterfaces; ++i) {
++			intf = config->interface[i];
++			if (intf->dev.driver && intf->needs_binding)
++				usb_forced_unbind_intf(intf);
++		}
++	}
++}
++
+ /* Delayed forced unbinding of a USB interface driver and scan
+  * for rebinding.
+  *
+- * The caller must hold @intf's device's lock, but not its pm_mutex
+- * and not @intf->dev.sem.
++ * The caller must hold @intf's device's lock, but not @intf's lock.
+  *
+  * Note: Rebinds will be skipped if a system sleep transition is in
+  * progress and the PM "complete" callback hasn't occurred yet.
+  */
+-void usb_rebind_intf(struct usb_interface *intf)
++static void usb_rebind_intf(struct usb_interface *intf)
+ {
+ 	int rc;
+ 
+@@ -1051,68 +1071,66 @@ void usb_rebind_intf(struct usb_interface *intf)
+ 	}
+ }
+ 
+-#ifdef CONFIG_PM
+-
+-/* Unbind drivers for @udev's interfaces that don't support suspend/resume
+- * There is no check for reset_resume here because it can be determined
+- * only during resume whether reset_resume is needed.
++/*
++ * Rebind drivers to @udev's marked interfaces.  These interfaces have
++ * the needs_binding flag set.
+  *
+  * The caller must hold @udev's device lock.
+  */
+-static void unbind_no_pm_drivers_interfaces(struct usb_device *udev)
++static void rebind_marked_interfaces(struct usb_device *udev)
+ {
+ 	struct usb_host_config	*config;
+ 	int			i;
+ 	struct usb_interface	*intf;
+-	struct usb_driver	*drv;
+ 
+ 	config = udev->actconfig;
+ 	if (config) {
+ 		for (i = 0; i < config->desc.bNumInterfaces; ++i) {
+ 			intf = config->interface[i];
+-
+-			if (intf->dev.driver) {
+-				drv = to_usb_driver(intf->dev.driver);
+-				if (!drv->suspend || !drv->resume)
+-					usb_forced_unbind_intf(intf);
+-			}
++			if (intf->needs_binding)
++				usb_rebind_intf(intf);
+ 		}
+ 	}
+ }
+ 
+-/* Unbind drivers for @udev's interfaces that failed to support reset-resume.
+- * These interfaces have the needs_binding flag set by usb_resume_interface().
++/*
++ * Unbind all of @udev's marked interfaces and then rebind all of them.
++ * This ordering is necessary because some drivers claim several interfaces
++ * when they are first probed.
+  *
+  * The caller must hold @udev's device lock.
+  */
+-static void unbind_no_reset_resume_drivers_interfaces(struct usb_device *udev)
++void usb_unbind_and_rebind_marked_interfaces(struct usb_device *udev)
+ {
+-	struct usb_host_config	*config;
+-	int			i;
+-	struct usb_interface	*intf;
+-
+-	config = udev->actconfig;
+-	if (config) {
+-		for (i = 0; i < config->desc.bNumInterfaces; ++i) {
+-			intf = config->interface[i];
+-			if (intf->dev.driver && intf->needs_binding)
+-				usb_forced_unbind_intf(intf);
+-		}
+-	}
++	unbind_marked_interfaces(udev);
++	rebind_marked_interfaces(udev);
+ }
+ 
+-static void do_rebind_interfaces(struct usb_device *udev)
++#ifdef CONFIG_PM
++
++/* Unbind drivers for @udev's interfaces that don't support suspend/resume
++ * There is no check for reset_resume here because it can be determined
++ * only during resume whether reset_resume is needed.
++ *
++ * The caller must hold @udev's device lock.
++ */
++static void unbind_no_pm_drivers_interfaces(struct usb_device *udev)
+ {
+ 	struct usb_host_config	*config;
+ 	int			i;
+ 	struct usb_interface	*intf;
++	struct usb_driver	*drv;
+ 
+ 	config = udev->actconfig;
+ 	if (config) {
+ 		for (i = 0; i < config->desc.bNumInterfaces; ++i) {
+ 			intf = config->interface[i];
+-			if (intf->needs_binding)
+-				usb_rebind_intf(intf);
++
++			if (intf->dev.driver) {
++				drv = to_usb_driver(intf->dev.driver);
++				if (!drv->suspend || !drv->resume)
++					usb_forced_unbind_intf(intf);
++			}
+ 		}
+ 	}
+ }
+@@ -1441,7 +1459,7 @@ int usb_resume_complete(struct device *dev)
+ 	 * whose needs_binding flag is set
+ 	 */
+ 	if (udev->state != USB_STATE_NOTATTACHED)
+-		do_rebind_interfaces(udev);
++		rebind_marked_interfaces(udev);
+ 	return 0;
+ }
+ 
+@@ -1463,7 +1481,7 @@ int usb_resume(struct device *dev, pm_message_t msg)
+ 		pm_runtime_disable(dev);
+ 		pm_runtime_set_active(dev);
+ 		pm_runtime_enable(dev);
+-		unbind_no_reset_resume_drivers_interfaces(udev);
++		unbind_marked_interfaces(udev);
+ 	}
+ 
+ 	/* Avoid PM error messages for devices disconnected while suspended
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 5da5394127e9..2d74dfb9c989 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -5380,10 +5380,11 @@ int usb_reset_device(struct usb_device *udev)
+ 				else if (cintf->condition ==
+ 						USB_INTERFACE_BOUND)
+ 					rebind = 1;
++				if (rebind)
++					cintf->needs_binding = 1;
+ 			}
+-			if (ret == 0 && rebind)
+-				usb_rebind_intf(cintf);
+ 		}
++		usb_unbind_and_rebind_marked_interfaces(udev);
+ 	}
+ 
+ 	usb_autosuspend_device(udev);
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 823857767a16..0923add72b59 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -55,7 +55,7 @@ extern int usb_match_one_id_intf(struct usb_device *dev,
+ extern int usb_match_device(struct usb_device *dev,
+ 			    const struct usb_device_id *id);
+ extern void usb_forced_unbind_intf(struct usb_interface *intf);
+-extern void usb_rebind_intf(struct usb_interface *intf);
++extern void usb_unbind_and_rebind_marked_interfaces(struct usb_device *udev);
+ 
+ extern int usb_hub_claim_port(struct usb_device *hdev, unsigned port,
+ 		struct dev_state *owner);

commit 7aae51347b21eb738dc1981df1365b57a6c5ee4e
+Author: Alan Stern 
+Date:   Wed Jan 15 15:37:04 2014 -0500
+
+    [SCSI] sd: don't fail if the device doesn't recognize SYNCHRONIZE CACHE
+    
+    Evidently some wacky USB-ATA bridges don't recognize the SYNCHRONIZE
+    CACHE command, as shown in this email thread:
+    
+            http://marc.info/?t=138978356200002&r=1&w=2
+    
+    The fact that we can't tell them to drain their caches shouldn't
+    prevent the system from going into suspend.  Therefore sd_sync_cache()
+    shouldn't return an error if the device replies with an Invalid
+    Command ASC.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Sven Neumann 
+    Tested-by: Daniel Mack 
+    CC: 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+index 470954aba728..36d1a23f14be 100644
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -1463,8 +1463,8 @@ static int sd_sync_cache(struct scsi_disk *sdkp)
+ 			sd_print_sense_hdr(sdkp, &sshdr);
+ 		/* we need to evaluate the error return  */
+ 		if (scsi_sense_valid(&sshdr) &&
+-			/* 0x3a is medium not present */
+-			sshdr.asc == 0x3a)
++			(sshdr.asc == 0x3a ||	/* medium not present */
++			 sshdr.asc == 0x20))	/* invalid command */
+ 				/* this is no error here */
+ 				return 0;
+ 

commit f080a51bef2caa9b0f647dc430bc608d5723ac29
+Author: Alan Stern 
+Date:   Thu Feb 20 10:49:30 2014 -0500
+
+    USB: complain if userspace resets an active endpoint
+    
+    It is an error for a driver to call usb_clear_halt() or
+    usb_reset_endpoint() while there are URBs queued for the endpoint,
+    because the end result is not well defined.  At the time the endpoint
+    gets reset, it may or may not be actively running.
+    
+    As far as I know, no kernel drivers do this.  But some userspace
+    drivers do, and it seems like a good idea to bring this error to their
+    attention.
+    
+    This patch adds a warning to the kernel log whenever a program invokes
+    the USBDEVFS_CLEAR_HALT or USBDEVFS_RESETEP ioctls at an inappropriate
+    time, and includes the name of the program.  This will make it clear
+    that any subsequent errors are not due to the misbehavior of a kernel
+    driver.
+    
+    Signed-off-by: Alan Stern 
+    Suggested-by: Bjørn Mork 
+    CC: Stanislaw Gruszka 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 90e18f6fa2bb..f3ba2e076ee3 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -1043,6 +1043,20 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
+ 	return ret;
+ }
+ 
++static void check_reset_of_active_ep(struct usb_device *udev,
++		unsigned int epnum, char *ioctl_name)
++{
++	struct usb_host_endpoint **eps;
++	struct usb_host_endpoint *ep;
++
++	eps = (epnum & USB_DIR_IN) ? udev->ep_in : udev->ep_out;
++	ep = eps[epnum & 0x0f];
++	if (ep && !list_empty(&ep->urb_list))
++		dev_warn(&udev->dev, "Process %d (%s) called USBDEVFS_%s for active endpoint 0x%02x\n",
++				task_pid_nr(current), current->comm,
++				ioctl_name, epnum);
++}
++
+ static int proc_resetep(struct dev_state *ps, void __user *arg)
+ {
+ 	unsigned int ep;
+@@ -1056,6 +1070,7 @@ static int proc_resetep(struct dev_state *ps, void __user *arg)
+ 	ret = checkintf(ps, ret);
+ 	if (ret)
+ 		return ret;
++	check_reset_of_active_ep(ps->dev, ep, "RESETEP");
+ 	usb_reset_endpoint(ps->dev, ep);
+ 	return 0;
+ }
+@@ -1074,6 +1089,7 @@ static int proc_clearhalt(struct dev_state *ps, void __user *arg)
+ 	ret = checkintf(ps, ret);
+ 	if (ret)
+ 		return ret;
++	check_reset_of_active_ep(ps->dev, ep, "CLEAR_HALT");
+ 	if (ep & USB_DIR_IN)
+ 		pipe = usb_rcvbulkpipe(ps->dev, ep & 0x7f);
+ 	else

commit 3e8d6d85adedc59115a564c0a54b36e42087c4d9
+Author: Alan Stern 
+Date:   Thu Feb 13 15:49:17 2014 -0500
+
+    USB: EHCI: add delay during suspend to prevent erroneous wakeups
+    
+    High-speed USB connections revert back to full-speed signalling when
+    the device goes into suspend.  This takes several milliseconds, and
+    during that time it's not possible to tell reliably whether the device
+    has been disconnected.
+    
+    On some platforms, the Wake-On-Disconnect circuitry gets confused
+    during this intermediate state.  It generates a false wakeup signal,
+    which can prevent the controller from going to sleep.
+    
+    To avoid this problem, this patch adds a 5-ms delay to the
+    ehci_bus_suspend() routine if any ports have to switch over to
+    full-speed signalling.  (Actually, the delay was already present for
+    devices using a particular kind of PHY power management; the patch
+    merely causes the delay to be used more widely.)
+    
+    Signed-off-by: Alan Stern 
+    Reviewed-by: Peter Chen 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 47b858fc50b2..7ae0c4d51741 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -238,6 +238,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 	int			port;
+ 	int			mask;
+ 	int			changed;
++	bool			fs_idle_delay;
+ 
+ 	ehci_dbg(ehci, "suspend root hub\n");
+ 
+@@ -272,6 +273,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 	ehci->bus_suspended = 0;
+ 	ehci->owned_ports = 0;
+ 	changed = 0;
++	fs_idle_delay = false;
+ 	port = HCS_N_PORTS(ehci->hcs_params);
+ 	while (port--) {
+ 		u32 __iomem	*reg = &ehci->regs->port_status [port];
+@@ -300,16 +302,32 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 		}
+ 
+ 		if (t1 != t2) {
++			/*
++			 * On some controllers, Wake-On-Disconnect will
++			 * generate false wakeup signals until the bus
++			 * switches over to full-speed idle.  For their
++			 * sake, add a delay if we need one.
++			 */
++			if ((t2 & PORT_WKDISC_E) &&
++					ehci_port_speed(ehci, t2) ==
++						USB_PORT_STAT_HIGH_SPEED)
++				fs_idle_delay = true;
+ 			ehci_writel(ehci, t2, reg);
+ 			changed = 1;
+ 		}
+ 	}
++	spin_unlock_irq(&ehci->lock);
++
++	if ((changed && ehci->has_tdi_phy_lpm) || fs_idle_delay) {
++		/*
++		 * Wait for HCD to enter low-power mode or for the bus
++		 * to switch to full-speed idle.
++		 */
++		usleep_range(5000, 5500);
++	}
+ 
+ 	if (changed && ehci->has_tdi_phy_lpm) {
+-		spin_unlock_irq(&ehci->lock);
+-		msleep(5);	/* 5 ms for HCD to enter low-power mode */
+ 		spin_lock_irq(&ehci->lock);
+-
+ 		port = HCS_N_PORTS(ehci->hcs_params);
+ 		while (port--) {
+ 			u32 __iomem	*hostpc_reg = &ehci->regs->hostpc[port];
+@@ -322,8 +340,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 					port, (t3 & HOSTPC_PHCD) ?
+ 					"succeeded" : "failed");
+ 		}
++		spin_unlock_irq(&ehci->lock);
+ 	}
+-	spin_unlock_irq(&ehci->lock);
+ 
+ 	/* Apparently some devices need a >= 1-uframe delay here */
+ 	if (ehci->bus_suspended)

commit adff52952ef52c4dbfb930727f6f8cfe14d9967c
+Author: Alan Stern 
+Date:   Tue Feb 11 11:26:00 2014 -0500
+
+    USB: ohci-platform: check for platform data misconfiguration
+    
+    The ohci-platform driver checks for misconfigurations in cases where
+    the Device Tree data specifies big-endian registers or descriptors but
+    the corresponding driver config settings have not been enabled.  As
+    Jonas Gorski suggested, we may as well apply the same check to general
+    platform data too.
+    
+    This requires moving the code that sets the big-endian quirk flags
+    from the ohci_platform_reset() routine into ohci_platform_probe(), and
+    moving the checks out of the DT-specific "if" statement clause.
+    
+    The patch also changes the text of the error messages in an attempt to
+    make the nature of the error more clear.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Jonas Gorski 
+    Acked-by: Hans de Goede 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
+index b6ca0b25259a..b6002c951c5c 100644
+--- a/drivers/usb/host/ohci-platform.c
++++ b/drivers/usb/host/ohci-platform.c
+@@ -47,10 +47,6 @@ static int ohci_platform_reset(struct usb_hcd *hcd)
+ 	struct usb_ohci_pdata *pdata = dev_get_platdata(&pdev->dev);
+ 	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+ 
+-	if (pdata->big_endian_desc)
+-		ohci->flags |= OHCI_QUIRK_BE_DESC;
+-	if (pdata->big_endian_mmio)
+-		ohci->flags |= OHCI_QUIRK_BE_MMIO;
+ 	if (pdata->no_big_frame_no)
+ 		ohci->flags |= OHCI_QUIRK_FRAME_NO;
+ 	if (pdata->num_ports)
+@@ -177,22 +173,6 @@ static int ohci_platform_probe(struct platform_device *dev)
+ 		if (of_property_read_bool(dev->dev.of_node, "big-endian"))
+ 			ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC;
+ 
+-#ifndef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO
+-		if (ohci->flags & OHCI_QUIRK_BE_MMIO) {
+-			dev_err(&dev->dev,
+-				"Error big-endian-regs not compiled in\n");
+-			err = -EINVAL;
+-			goto err_put_hcd;
+-		}
+-#endif
+-#ifndef CONFIG_USB_OHCI_BIG_ENDIAN_DESC
+-		if (ohci->flags & OHCI_QUIRK_BE_DESC) {
+-			dev_err(&dev->dev,
+-				"Error big-endian-desc not compiled in\n");
+-			err = -EINVAL;
+-			goto err_put_hcd;
+-		}
+-#endif
+ 		priv->phy = devm_phy_get(&dev->dev, "usb");
+ 		if (IS_ERR(priv->phy)) {
+ 			err = PTR_ERR(priv->phy);
+@@ -213,6 +193,28 @@ static int ohci_platform_probe(struct platform_device *dev)
+ 		}
+ 	}
+ 
++	if (pdata->big_endian_desc)
++		ohci->flags |= OHCI_QUIRK_BE_DESC;
++	if (pdata->big_endian_mmio)
++		ohci->flags |= OHCI_QUIRK_BE_MMIO;
++
++#ifndef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO
++	if (ohci->flags & OHCI_QUIRK_BE_MMIO) {
++		dev_err(&dev->dev,
++			"Error: CONFIG_USB_OHCI_BIG_ENDIAN_MMIO not set\n");
++		err = -EINVAL;
++		goto err_put_clks;
++	}
++#endif
++#ifndef CONFIG_USB_OHCI_BIG_ENDIAN_DESC
++	if (ohci->flags & OHCI_QUIRK_BE_DESC) {
++		dev_err(&dev->dev,
++			"Error: CONFIG_USB_OHCI_BIG_ENDIAN_DESC not set\n");
++		err = -EINVAL;
++		goto err_put_clks;
++	}
++#endif
++
+ 	if (pdata->power_on) {
+ 		err = pdata->power_on(dev);
+ 		if (err < 0)

commit 843d5e036419bddb4aaf21d60c7ffe437e963166
+Author: Alan Stern 
+Date:   Tue Feb 11 11:26:10 2014 -0500
+
+    USB: ehci-platform: check for platform data misconfiguration
+    
+    The ehci-platform driver checks for misconfigurations in cases where
+    the Device Tree data specifies big-endian registers or descriptors but
+    the corresponding driver config settings have not been enabled.  As
+    Jonas Gorski suggested, we may as well apply the same check to general
+    platform data too.
+    
+    This requires moving the code that sets the big-endian quirk flags
+    from the ehci_platform_reset() routine into ehci_platform_probe(), and
+    moving the checks out of the DT-specific "if" statement clause.
+    
+    The patch also changes the text of the error messages in an attempt to
+    make the nature of the error more clear.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Jonas Gorski 
+    Acked-by: Hans de Goede 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
+index 117873033d00..b3a0e11073aa 100644
+--- a/drivers/usb/host/ehci-platform.c
++++ b/drivers/usb/host/ehci-platform.c
+@@ -55,10 +55,6 @@ static int ehci_platform_reset(struct usb_hcd *hcd)
+ 
+ 	hcd->has_tt = pdata->has_tt;
+ 	ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug;
+-	if (pdata->big_endian_desc)
+-		ehci->big_endian_desc = 1;
+-	if (pdata->big_endian_mmio)
+-		ehci->big_endian_mmio = 1;
+ 
+ 	if (pdata->pre_setup) {
+ 		retval = pdata->pre_setup(hcd);
+@@ -192,22 +188,6 @@ static int ehci_platform_probe(struct platform_device *dev)
+ 		if (of_property_read_bool(dev->dev.of_node, "big-endian"))
+ 			ehci->big_endian_mmio = ehci->big_endian_desc = 1;
+ 
+-#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
+-		if (ehci->big_endian_mmio) {
+-			dev_err(&dev->dev,
+-				"Error big-endian-regs not compiled in\n");
+-			err = -EINVAL;
+-			goto err_put_hcd;
+-		}
+-#endif
+-#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_DESC
+-		if (ehci->big_endian_desc) {
+-			dev_err(&dev->dev,
+-				"Error big-endian-desc not compiled in\n");
+-			err = -EINVAL;
+-			goto err_put_hcd;
+-		}
+-#endif
+ 		priv->phy = devm_phy_get(&dev->dev, "usb");
+ 		if (IS_ERR(priv->phy)) {
+ 			err = PTR_ERR(priv->phy);
+@@ -228,6 +208,28 @@ static int ehci_platform_probe(struct platform_device *dev)
+ 		}
+ 	}
+ 
++	if (pdata->big_endian_desc)
++		ehci->big_endian_desc = 1;
++	if (pdata->big_endian_mmio)
++		ehci->big_endian_mmio = 1;
++
++#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
++	if (ehci->big_endian_mmio) {
++		dev_err(&dev->dev,
++			"Error: CONFIG_USB_EHCI_BIG_ENDIAN_MMIO not set\n");
++		err = -EINVAL;
++		goto err_put_clks;
++	}
++#endif
++#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_DESC
++	if (ehci->big_endian_desc) {
++		dev_err(&dev->dev,
++			"Error: CONFIG_USB_EHCI_BIG_ENDIAN_DESC not set\n");
++		err = -EINVAL;
++		goto err_put_clks;
++	}
++#endif
++
+ 	if (pdata->power_on) {
+ 		err = pdata->power_on(dev);
+ 		if (err < 0)

commit 823d12c95c666fa7ab7dad208d735f6bc6afabdc
+Author: Alan Stern 
+Date:   Thu Jan 30 10:43:22 2014 -0500
+
+    usb-storage: enable multi-LUN scanning when needed
+    
+    People sometimes create their own custom-configured kernels and forget
+    to enable CONFIG_SCSI_MULTI_LUN.  This causes problems when they plug
+    in a USB storage device (such as a card reader) with more than one
+    LUN.
+    
+    Fortunately, we can tell fairly easily when a storage device claims to
+    have more than one LUN.  When that happens, this patch asks the SCSI
+    layer to probe all the LUNs automatically, regardless of the config
+    setting.
+    
+    The patch also updates the Kconfig help text for usb-storage,
+    explaining that CONFIG_SCSI_MULTI_LUN may be necessary.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Thomas Raschbacher 
+    CC: Matthew Dharm 
+    CC: James Bottomley 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
+index 8470e1b114f2..1dd0604d1911 100644
+--- a/drivers/usb/storage/Kconfig
++++ b/drivers/usb/storage/Kconfig
+@@ -18,7 +18,9 @@ config USB_STORAGE
+ 
+ 	  This option depends on 'SCSI' support being enabled, but you
+ 	  probably also need 'SCSI device support: SCSI disk support'
+-	  (BLK_DEV_SD) for most USB storage devices.
++	  (BLK_DEV_SD) for most USB storage devices.  Some devices also
++	  will require 'Probe all LUNs on each SCSI device'
++	  (SCSI_MULTI_LUN).
+ 
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called usb-storage.
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index 18509e6c21ab..9d38ddc8da49 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -78,6 +78,8 @@ static const char* host_info(struct Scsi_Host *host)
+ 
+ static int slave_alloc (struct scsi_device *sdev)
+ {
++	struct us_data *us = host_to_us(sdev->host);
++
+ 	/*
+ 	 * Set the INQUIRY transfer length to 36.  We don't use any of
+ 	 * the extra data and many devices choke if asked for more or
+@@ -102,6 +104,10 @@ static int slave_alloc (struct scsi_device *sdev)
+ 	 */
+ 	blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
+ 
++	/* Tell the SCSI layer if we know there is more than one LUN */
++	if (us->protocol == USB_PR_BULK && us->max_lun > 0)
++		sdev->sdev_bflags |= BLIST_FORCELUN;
++
+ 	return 0;
+ }
+ 

commit c5637e5119c43452a00e27c274356b072263ecbb
+Author: Alan Stern 
+Date:   Tue Jan 21 10:38:45 2014 -0500
+
+    usb-storage: add unusual-devs entry for BlackBerry 9000
+    
+    This patch adds an unusual-devs entry for the BlackBerry 9000.  This
+    fixes Bugzilla #22442.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Moritz Moeller-Herrmann 
+    Tested-by: Moritz Moeller-Herrmann 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index ad06255c2ade..adbeb255616a 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -1455,6 +1455,13 @@ UNUSUAL_DEV( 0x0f88, 0x042e, 0x0100, 0x0100,
+ 		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ 		US_FL_FIX_CAPACITY ),
+ 
++/* Reported by Moritz Moeller-Herrmann  */
++UNUSUAL_DEV(  0x0fca, 0x8004, 0x0201, 0x0201,
++		"Research In Motion",
++		"BlackBerry Bold 9000",
++		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
++		US_FL_MAX_SECTORS_64 ),
++
+ /* Reported by Michael Stattmann  */
+ UNUSUAL_DEV(  0x0fce, 0xd008, 0x0000, 0x0000,
+ 		"Sony Ericsson",

commit a9c143c82608bee2a36410caa56d82cd86bdc7fa
+Author: Alan Stern 
+Date:   Thu Jan 30 10:20:29 2014 -0500
+
+    usb-storage: restrict bcdDevice range for Super Top in Cypress ATACB
+    
+    The Cypress ATACB unusual-devs entry for the Super Top SATA bridge
+    causes problems.  Although it was originally reported only for
+    bcdDevice = 0x160, its range was much larger.  This resulted in a bug
+    report for bcdDevice 0x220, so the range was capped at 0x219.  Now
+    Milan reports errors with bcdDevice 0x150.
+    
+    Therefore this patch restricts the range to just 0x160.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Milan Svoboda 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_cypress.h b/drivers/usb/storage/unusual_cypress.h
+index 65a6a75066a8..82e8ed0324e3 100644
+--- a/drivers/usb/storage/unusual_cypress.h
++++ b/drivers/usb/storage/unusual_cypress.h
+@@ -31,7 +31,7 @@ UNUSUAL_DEV(  0x04b4, 0x6831, 0x0000, 0x9999,
+ 		"Cypress ISD-300LP",
+ 		USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0),
+ 
+-UNUSUAL_DEV( 0x14cd, 0x6116, 0x0000, 0x0219,
++UNUSUAL_DEV( 0x14cd, 0x6116, 0x0160, 0x0160,
+ 		"Super Top",
+ 		"USB 2.0  SATA BRIDGE",
+ 		USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0),

commit 543d7784b07ffd16cc82a9cb4e1e0323fd0040f1
+Author: Alan Stern 
+Date:   Tue Jan 7 10:43:02 2014 -0500
+
+    USB: fix race between hub_disconnect and recursively_mark_NOTATTACHED
+    
+    There is a race in the hub driver between hub_disconnect() and
+    recursively_mark_NOTATTACHED().  This race can be triggered if the
+    driver is unbound from a device at the same time as the bus's root hub
+    is removed.  When the race occurs, it can cause an oops:
+    
+    BUG: unable to handle kernel NULL pointer dereference at 0000015c
+    IP: [] recursively_mark_NOTATTACHED+0x20/0x60
+    Call Trace:
+     [] recursively_mark_NOTATTACHED+0x34/0x60
+     [] recursively_mark_NOTATTACHED+0x34/0x60
+     [] recursively_mark_NOTATTACHED+0x34/0x60
+     [] recursively_mark_NOTATTACHED+0x34/0x60
+     [] usb_set_device_state+0x92/0x120
+     [] usb_disconnect+0x2b/0x1a0
+     [] usb_remove_hcd+0xb0/0x160
+     [] ? _raw_spin_unlock_irqrestore+0x26/0x50
+     [] ehci_mid_remove+0x1c/0x30
+     [] ehci_mid_stop_host+0x16/0x30
+     [] penwell_otg_work+0xd28/0x3520
+     [] ? __schedule+0x39b/0x7f0
+     [] ? sub_preempt_count+0x3d/0x50
+     [] process_one_work+0x11d/0x3d0
+     [] ? mutex_unlock+0xd/0x10
+     [] ? manage_workers.isra.24+0x1b5/0x270
+     [] worker_thread+0xf9/0x320
+     [] ? _raw_spin_unlock_irqrestore+0x26/0x50
+     [] ? rescuer_thread+0x2b0/0x2b0
+     [] kthread+0x94/0xa0
+     [] ret_from_kernel_thread+0x1b/0x28
+     [] ? kthread_create_on_node+0xc0/0xc0
+    
+    One problem is that recursively_mark_NOTATTACHED() uses the intfdata
+    value and hub->hdev->maxchild while hub_disconnect() is clearing them.
+    Another problem is that it uses hub->ports[i] while the port device is
+    being released.
+    
+    To fix this race, we need to hold the device_state_lock while
+    hub_disconnect() changes the values.  (Note that usb_disconnect()
+    and hub_port_connect_change() already acquire this lock at similar
+    critical times during a USB device's life cycle.)  We also need to
+    remove the port devices after maxchild has been set to 0, instead of
+    before.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: "Du, Changbin" 
+    Tested-by: "Du, Changbin" 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 92e052db27ac..9e49c6d6e4a2 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1600,7 +1600,7 @@ static void hub_disconnect(struct usb_interface *intf)
+ {
+ 	struct usb_hub *hub = usb_get_intfdata(intf);
+ 	struct usb_device *hdev = interface_to_usbdev(intf);
+-	int i;
++	int port1;
+ 
+ 	/* Take the hub off the event list and don't let it be added again */
+ 	spin_lock_irq(&hub_event_lock);
+@@ -1615,11 +1615,15 @@ static void hub_disconnect(struct usb_interface *intf)
+ 	hub->error = 0;
+ 	hub_quiesce(hub, HUB_DISCONNECT);
+ 
+-	usb_set_intfdata (intf, NULL);
++	/* Avoid races with recursively_mark_NOTATTACHED() */
++	spin_lock_irq(&device_state_lock);
++	port1 = hdev->maxchild;
++	hdev->maxchild = 0;
++	usb_set_intfdata(intf, NULL);
++	spin_unlock_irq(&device_state_lock);
+ 
+-	for (i = 0; i < hdev->maxchild; i++)
+-		usb_hub_remove_port_device(hub, i + 1);
+-	hub->hdev->maxchild = 0;
++	for (; port1 > 0; --port1)
++		usb_hub_remove_port_device(hub, port1);
+ 
+ 	if (hub->hdev->speed == USB_SPEED_HIGH)
+ 		highspeed_hubs--;

commit a535d81c92615b8ffb99b7e1fd1fb01effaed1af
+Author: Alan Stern 
+Date:   Fri Nov 1 12:05:12 2013 -0400
+
+    usb: dwc3: fix implementation of endpoint wedge
+    
+    The dwc3 UDC driver doesn't implement endpoint wedging correctly.
+    When an endpoint is wedged, the gadget driver should be allowed to
+    clear the wedge by calling usb_ep_clear_halt().  Only the host is
+    prevented from resetting the endpoint.
+    
+    This patch fixes the implementation.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Pratyush Anand 
+    Cc: 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
+index 95f7649c71a7..21a352079bc2 100644
+--- a/drivers/usb/dwc3/ep0.c
++++ b/drivers/usb/dwc3/ep0.c
+@@ -459,6 +459,8 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
+ 			dep = dwc3_wIndex_to_dep(dwc, wIndex);
+ 			if (!dep)
+ 				return -EINVAL;
++			if (set == 0 && (dep->flags & DWC3_EP_WEDGE))
++				break;
+ 			ret = __dwc3_gadget_ep_set_halt(dep, set);
+ 			if (ret)
+ 				return -EINVAL;
+diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
+index 5452c0fce360..02e44fcaf205 100644
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -1200,9 +1200,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value)
+ 		else
+ 			dep->flags |= DWC3_EP_STALL;
+ 	} else {
+-		if (dep->flags & DWC3_EP_WEDGE)
+-			return 0;
+-
+ 		ret = dwc3_send_gadget_ep_cmd(dwc, dep->number,
+ 			DWC3_DEPCMD_CLEARSTALL, ¶ms);
+ 		if (ret)
+@@ -1210,7 +1207,7 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value)
+ 					value ? "set" : "clear",
+ 					dep->name);
+ 		else
+-			dep->flags &= ~DWC3_EP_STALL;
++			dep->flags &= ~(DWC3_EP_STALL | DWC3_EP_WEDGE);
+ 	}
+ 
+ 	return ret;

commit 1c124c9962b4ee6555fd6179ca318c2ad3a30354
+Author: Alan Stern 
+Date:   Fri Oct 18 11:19:18 2013 -0400
+
+    USB: UHCI: check for wakeup/suspend race
+    
+    hcd-pci.c in usbcore contains a check for wakeup requests racing with
+    controller suspend.  This check is going to be moved out of usbcore
+    and into the individual controller drivers, where it can apply to all
+    platforms, not just PCI.
+    
+    This patch adds the check to uhci-hcd.  Ironically, none of the
+    non-PCI platform drivers for uhci-hcd implement suspend/resume.
+    Nevertheless, this change is needed to accomodate the upcoming change
+    to usbcore.
+    
+    The patch also removes an outdated check of the root hub state.  For
+    one thing, the PM layer has long been quite reliable about suspending
+    root hubs before controllers.  For another, virtually the same check
+    is also made in hcd-pci.c; there's no point in repeating it.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-pci.c b/drivers/usb/host/uhci-pci.c
+index 8de0da0e6dfc..4cd79888804b 100644
+--- a/drivers/usb/host/uhci-pci.c
++++ b/drivers/usb/host/uhci-pci.c
+@@ -162,6 +162,8 @@ static void uhci_shutdown(struct pci_dev *pdev)
+ 
+ #ifdef CONFIG_PM
+ 
++static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated);
++
+ static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+@@ -174,12 +176,6 @@ static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+ 	if (!HCD_HW_ACCESSIBLE(hcd) || uhci->dead)
+ 		goto done_okay;		/* Already suspended or dead */
+ 
+-	if (uhci->rh_state > UHCI_RH_SUSPENDED) {
+-		dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n");
+-		rc = -EBUSY;
+-		goto done;
+-	}
+-
+ 	/* All PCI host controllers are required to disable IRQ generation
+ 	 * at the source, so we must turn off PIRQ.
+ 	 */
+@@ -195,8 +191,15 @@ static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+ 
+ done_okay:
+ 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+-done:
+ 	spin_unlock_irq(&uhci->lock);
++
++	synchronize_irq(hcd->irq);
++
++	/* Check for race with a wakeup request */
++	if (do_wakeup && HCD_WAKEUP_PENDING(hcd)) {
++		uhci_pci_resume(hcd, false);
++		rc = -EBUSY;
++	}
+ 	return rc;
+ }
+ 

commit b8efdafb4005a79ab2305f8af31025d49292d4cf
+Author: Alan Stern 
+Date:   Fri Oct 18 11:18:21 2013 -0400
+
+    USB: EHCI: add check for wakeup/suspend race
+    
+    hcd-pci.c in usbcore contains a check for wakeup requests racing with
+    controller suspend.  This check is going to be moved out of usbcore
+    and into the individual controller drivers, where it can apply to all
+    platforms, not just PCI.
+    
+    This patch adds the check to ehci-hcd.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index e66706aa9f0c..e8ba4c44223a 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1095,6 +1095,14 @@ int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+ 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ 	spin_unlock_irq(&ehci->lock);
+ 
++	synchronize_irq(hcd->irq);
++
++	/* Check for race with a wakeup request */
++	if (do_wakeup && HCD_WAKEUP_PENDING(hcd)) {
++		ehci_resume(hcd, false);
++		return -EBUSY;
++	}
++
+ 	return 0;
+ }
+ EXPORT_SYMBOL_GPL(ehci_suspend);

commit 0a56b4fa6844f74976d4bfa4956fa6d606b392ea
+Author: Alan Stern 
+Date:   Fri Oct 18 11:17:21 2013 -0400
+
+    USB: change dev_warn about missing reset-resume to dev_dbg
+    
+    This patch changes a dev_warn() call in usbcore to dev_dbg().  It's
+    not necessary to warn about drivers missing a reset-resume callback,
+    since the reset-resume method is optional.
+    
+    Signed-off-by: Alan Stern 
+    CC: Clemens Ladisch 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 689433cdef25..47aade2a5e74 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1179,8 +1179,8 @@ static int usb_resume_interface(struct usb_device *udev,
+ 						"reset_resume", status);
+ 		} else {
+ 			intf->needs_binding = 1;
+-			dev_warn(&intf->dev, "no %s for driver %s?\n",
+-					"reset_resume", driver->name);
++			dev_dbg(&intf->dev, "no reset_resume for driver %s?\n",
++					driver->name);
+ 		}
+ 	} else {
+ 		status = driver->resume(intf);

commit 7c71c6e6befd4b234e166f2f40d4430bacc779e6
+Author: Alan Stern 
+Date:   Fri Oct 18 11:16:07 2013 -0400
+
+    USB: OHCI: fix and explain sparse errors
+    
+    This patch fixes an endian-related error in ohci-hcd (detected by
+    sparse) and clarifies a comment explaining a peculiar locking
+    arrangement that sparse warns about.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index 2347ab83f046..61705a760e7d 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -212,10 +212,11 @@ __acquires(ohci->lock)
+ 	/* Sometimes PCI D3 suspend trashes frame timings ... */
+ 	periodic_reinit (ohci);
+ 
+-	/* the following code is executed with ohci->lock held and
+-	 * irqs disabled if and only if autostopped is true
++	/*
++	 * The following code is executed with ohci->lock held and
++	 * irqs disabled if and only if autostopped is true.  This
++	 * will cause sparse to warn about a "context imbalance".
+ 	 */
+-
+ skip_resume:
+ 	/* interrupts might have been disabled */
+ 	ohci_writel (ohci, OHCI_INTR_INIT, &ohci->regs->intrenable);
+@@ -531,7 +532,7 @@ ohci_hub_descriptor (
+ 	    temp |= 0x0010;
+ 	else if (rh & RH_A_OCPM)	/* per-port overcurrent reporting? */
+ 	    temp |= 0x0008;
+-	desc->wHubCharacteristics = (__force __u16)cpu_to_hc16(ohci, temp);
++	desc->wHubCharacteristics = cpu_to_le16(temp);
+ 
+ 	/* ports removable, and usb 1.0 legacy PortPwrCtrlMask */
+ 	rh = roothub_b (ohci);

commit 4a71f242e51767e75c7ecdba890debab2c0dceaf
+Author: Alan Stern 
+Date:   Fri Oct 18 11:15:14 2013 -0400
+
+    USB: EHCI: fix sparse errors
+    
+    This patch fixes several sparse errors in ehci-hcd introduced by
+    commit 3d091a6f7039 (USB: EHCI: AMD periodic frame list table quirk).
+    Although the problem fixed by that commit affects only little-endian
+    systems, the source code has to use types appropriate for big-endian
+    too.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
+index 52a77734a225..c0fb6a8ae6a3 100644
+--- a/drivers/usb/host/ehci-mem.c
++++ b/drivers/usb/host/ehci-mem.c
+@@ -224,11 +224,11 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
+ 		hw->hw_next = EHCI_LIST_END(ehci);
+ 		hw->hw_qtd_next = EHCI_LIST_END(ehci);
+ 		hw->hw_alt_next = EHCI_LIST_END(ehci);
+-		hw->hw_token &= ~QTD_STS_ACTIVE;
+ 		ehci->dummy->hw = hw;
+ 
+ 		for (i = 0; i < ehci->periodic_size; i++)
+-			ehci->periodic[i] = ehci->dummy->qh_dma;
++			ehci->periodic[i] = cpu_to_hc32(ehci,
++					ehci->dummy->qh_dma);
+ 	} else {
+ 		for (i = 0; i < ehci->periodic_size; i++)
+ 			ehci->periodic[i] = EHCI_LIST_END(ehci);
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index fbeb82e552b8..e113fd73aeae 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -103,7 +103,7 @@ static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
+ 		*hw_p = *shadow_next_periodic(ehci, &here,
+ 				Q_NEXT_TYPE(ehci, *hw_p));
+ 	else
+-		*hw_p = ehci->dummy->qh_dma;
++		*hw_p = cpu_to_hc32(ehci, ehci->dummy->qh_dma);
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -2446,7 +2446,8 @@ static void scan_isoc(struct ehci_hcd *ehci)
+ 				    q.itd->hw_next != EHCI_LIST_END(ehci))
+ 					*hw_p = q.itd->hw_next;
+ 				else
+-					*hw_p = ehci->dummy->qh_dma;
++					*hw_p = cpu_to_hc32(ehci,
++							ehci->dummy->qh_dma);
+ 				type = Q_NEXT_TYPE(ehci, q.itd->hw_next);
+ 				wmb();
+ 				modified = itd_complete (ehci, q.itd);
+@@ -2481,7 +2482,8 @@ static void scan_isoc(struct ehci_hcd *ehci)
+ 				    q.sitd->hw_next != EHCI_LIST_END(ehci))
+ 					*hw_p = q.sitd->hw_next;
+ 				else
+-					*hw_p = ehci->dummy->qh_dma;
++					*hw_p = cpu_to_hc32(ehci,
++							ehci->dummy->qh_dma);
+ 				type = Q_NEXT_TYPE(ehci, q.sitd->hw_next);
+ 				wmb();
+ 				modified = sitd_complete (ehci, q.sitd);

commit 5d8f681f3d14880d5b509eb32a910ba90ef28c36
+Author: Alan Stern 
+Date:   Fri Oct 18 11:13:08 2013 -0400
+
+    USB: EHCI: fix type mismatch in check_intr_schedule
+    
+    This patch fixes a type mismatch in ehci-hcd caused by commit
+    b35c5009bbf6 (USB: EHCI: create per-TT bandwidth tables).  The c_maskp
+    parameter in check_intr_schedule() was changed to point to unsigned
+    int rather than __hc32, but the prototype declaration wasn't adjusted
+    accordingly.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: kbuild test robot 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 7ce5c2a2fe31..fbeb82e552b8 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -794,7 +794,7 @@ static int check_intr_schedule (
+ 	unsigned		frame,
+ 	unsigned		uframe,
+ 	struct ehci_qh		*qh,
+-	__hc32			*c_maskp,
++	unsigned		*c_maskp,
+ 	struct ehci_tt		*tt
+ )
+ {

commit a393a807d0c805e7c723315ff0e88a857055e9c6
+Author: Alan Stern 
+Date:   Fri Oct 11 11:29:36 2013 -0400
+
+    USB: EHCI: start new isochronous streams ASAP
+    
+    This patch changes the initial delay before the startup of a newly
+    scheduled isochronous stream.  Currently the stream doesn't start
+    for at least 5 ms (40 microframes).  This value is just an estimate;
+    it has no real justification.
+    
+    Instead, we can start the stream as soon as possible after the
+    scheduling computations are complete.  Essentially this requires
+    nothing more than reading the frame counter after the stream is
+    scheduled, instead of before.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index b5f957d322e3..7ce5c2a2fe31 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1491,8 +1491,6 @@ sitd_slot_ok (
+  * given EHCI_TUNE_FLS and the slop).  Or, write a smarter scheduler!
+  */
+ 
+-#define SCHEDULING_DELAY	40	/* microframes */
+-
+ static int
+ iso_stream_schedule (
+ 	struct ehci_hcd		*ehci,
+@@ -1506,27 +1504,13 @@ iso_stream_schedule (
+ 	unsigned		mod = ehci->periodic_size << 3;
+ 	struct ehci_iso_sched	*sched = urb->hcpriv;
+ 	bool			empty = list_empty(&stream->td_list);
++	bool			new_stream = false;
+ 
+ 	period = stream->uperiod;
+ 	span = sched->span;
+ 	if (!stream->highspeed)
+ 		span <<= 3;
+ 
+-	now = ehci_read_frame_index(ehci) & (mod - 1);
+-
+-	/* Take the isochronous scheduling threshold into account */
+-	if (ehci->i_thresh)
+-		next = now + ehci->i_thresh;	/* uframe cache */
+-	else
+-		next = (now + 2 + 7) & ~0x07;	/* full frame cache */
+-
+-	/*
+-	 * Use ehci->last_iso_frame as the base.  There can't be any
+-	 * TDs scheduled for earlier than that.
+-	 */
+-	base = ehci->last_iso_frame << 3;
+-	next = (next - base) & (mod - 1);
+-
+ 	/* Start a new isochronous stream? */
+ 	if (unlikely(empty && !hcd_periodic_completion_in_progress(
+ 			ehci_to_hcd(ehci), urb->ep))) {
+@@ -1542,7 +1526,7 @@ iso_stream_schedule (
+ 			}
+ 			compute_tt_budget(ehci->tt_budget, tt);
+ 
+-			start = (now & ~0x07) + SCHEDULING_DELAY;
++			start = ((-(++ehci->random_frame)) << 3) & (period - 1);
+ 
+ 			/* find a uframe slot with enough bandwidth.
+ 			 * Early uframes are more precious because full-speed
+@@ -1585,17 +1569,35 @@ iso_stream_schedule (
+ 			start = (stream->ps.phase << 3) + stream->ps.phase_uf;
+ 		}
+ 
+-		start = (start - base) & (mod - 1);
+-		goto use_start;
++		stream->next_uframe = start;
++		new_stream = true;
+ 	}
+ 
++	now = ehci_read_frame_index(ehci) & (mod - 1);
++
++	/* Take the isochronous scheduling threshold into account */
++	if (ehci->i_thresh)
++		next = now + ehci->i_thresh;	/* uframe cache */
++	else
++		next = (now + 2 + 7) & ~0x07;	/* full frame cache */
++
++	/*
++	 * Use ehci->last_iso_frame as the base.  There can't be any
++	 * TDs scheduled for earlier than that.
++	 */
++	base = ehci->last_iso_frame << 3;
++	next = (next - base) & (mod - 1);
++	start = (stream->next_uframe - base) & (mod - 1);
++
++	if (unlikely(new_stream))
++		goto do_ASAP;
++
+ 	/*
+ 	 * Typical case: reuse current schedule, stream may still be active.
+ 	 * Hopefully there are no gaps from the host falling behind
+ 	 * (irq delays etc).  If there are, the behavior depends on
+ 	 * whether URB_ISO_ASAP is set.
+ 	 */
+-	start = (stream->next_uframe - base) & (mod - 1);
+ 	now2 = (now - base) & (mod - 1);
+ 
+ 	/* Is the schedule already full? */

commit b35c5009bbf619d8885b4b3c8b102d09002acfe5
+Author: Alan Stern 
+Date:   Fri Oct 11 22:16:21 2013 -0400
+
+    USB: EHCI: create per-TT bandwidth tables
+    
+    This patch continues the scheduling changes in ehci-hcd by adding a
+    table to store the bandwidth allocation below each TT.  This will
+    speed up the scheduling code, as it will no longer need to read
+    through the entire schedule to compute the bandwidth currently in use.
+    
+    Properly speaking, the FS/LS budget calculations should be done in
+    terms of full-speed bytes per microframe, as described in the USB-2
+    spec.  However the driver currently uses microseconds per microframe,
+    and the scheduling code isn't robust enough at this point to change
+    over.  For the time being, we leave the calculations as they are.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
+index 5bbfb1f9929c..4a9c2edbcb2b 100644
+--- a/drivers/usb/host/ehci-dbg.c
++++ b/drivers/usb/host/ehci-dbg.c
+@@ -536,10 +536,14 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf)
+ static ssize_t fill_bandwidth_buffer(struct debug_buffer *buf)
+ {
+ 	struct ehci_hcd		*ehci;
++	struct ehci_tt		*tt;
++	struct ehci_per_sched	*ps;
+ 	unsigned		temp, size;
+ 	char			*next;
+ 	unsigned		i;
+ 	u8			*bw;
++	u16			*bf;
++	u8			budget[EHCI_BANDWIDTH_SIZE];
+ 
+ 	ehci = hcd_to_ehci(bus_to_hcd(buf->bus));
+ 	next = buf->output_buf;
+@@ -563,6 +567,50 @@ static ssize_t fill_bandwidth_buffer(struct debug_buffer *buf)
+ 		size -= temp;
+ 		next += temp;
+ 	}
++
++	/* Dump all the FS/LS tables */
++	list_for_each_entry(tt, &ehci->tt_list, tt_list) {
++		temp = scnprintf(next, size,
++				"\nTT %s port %d  FS/LS bandwidth allocation (us per frame)\n",
++				dev_name(&tt->usb_tt->hub->dev),
++				tt->tt_port + !!tt->usb_tt->multi);
++		size -= temp;
++		next += temp;
++
++		bf = tt->bandwidth;
++		temp = scnprintf(next, size,
++				"  %5u%5u%5u%5u%5u%5u%5u%5u\n",
++				bf[0], bf[1], bf[2], bf[3],
++					bf[4], bf[5], bf[6], bf[7]);
++		size -= temp;
++		next += temp;
++
++		temp = scnprintf(next, size,
++				"FS/LS budget (us per microframe)\n");
++		size -= temp;
++		next += temp;
++		compute_tt_budget(budget, tt);
++		for (i = 0; i < EHCI_BANDWIDTH_SIZE; i += 8) {
++			bw = &budget[i];
++			temp = scnprintf(next, size,
++					"%2u: %4u%4u%4u%4u%4u%4u%4u%4u\n",
++					i, bw[0], bw[1], bw[2], bw[3],
++						bw[4], bw[5], bw[6], bw[7]);
++			size -= temp;
++			next += temp;
++		}
++		list_for_each_entry(ps, &tt->ps_list, ps_list) {
++			temp = scnprintf(next, size,
++					"%s ep %02x:  %4u @ %2u.%u+%u mask %04x\n",
++					dev_name(&ps->udev->dev),
++					ps->ep->desc.bEndpointAddress,
++					ps->tt_usecs,
++					ps->bw_phase, ps->phase_uf,
++					ps->bw_period, ps->cs_mask);
++			size -= temp;
++			next += temp;
++		}
++	}
+ 	spin_unlock_irq(&ehci->lock);
+ 
+ 	return next - buf->output_buf;
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 398e8fa3032f..e66706aa9f0c 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -110,6 +110,9 @@ MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications");
+ #include "ehci.h"
+ #include "pci-quirks.h"
+ 
++static void compute_tt_budget(u8 budget_table[EHCI_BANDWIDTH_SIZE],
++		struct ehci_tt *tt);
++
+ /*
+  * The MosChip MCS9990 controller updates its microframe counter
+  * a little before the frame counter, and occasionally we will read
+@@ -484,6 +487,7 @@ static int ehci_init(struct usb_hcd *hcd)
+ 	INIT_LIST_HEAD(&ehci->intr_qh_list);
+ 	INIT_LIST_HEAD(&ehci->cached_itd_list);
+ 	INIT_LIST_HEAD(&ehci->cached_sitd_list);
++	INIT_LIST_HEAD(&ehci->tt_list);
+ 
+ 	if (HCC_PGM_FRAMELISTLEN(hcc_params)) {
+ 		/* periodic schedule size can be smaller than default */
+@@ -1051,6 +1055,19 @@ static int ehci_get_frame (struct usb_hcd *hcd)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++/* Device addition and removal */
++
++static void ehci_remove_device(struct usb_hcd *hcd, struct usb_device *udev)
++{
++	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
++
++	spin_lock_irq(&ehci->lock);
++	drop_tt(udev);
++	spin_unlock_irq(&ehci->lock);
++}
++
++/*-------------------------------------------------------------------------*/
++
+ #ifdef	CONFIG_PM
+ 
+ /* suspend/resume, section 4.3 */
+@@ -1194,6 +1211,11 @@ static const struct hc_driver ehci_hc_driver = {
+ 	.bus_resume =		ehci_bus_resume,
+ 	.relinquish_port =	ehci_relinquish_port,
+ 	.port_handed_over =	ehci_port_handed_over,
++
++	/*
++	 * device support
++	 */
++	.free_dev =		ehci_remove_device,
+ };
+ 
+ void ehci_init_driver(struct hc_driver *drv,
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 790a64c0da5c..b5f957d322e3 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -106,6 +106,103 @@ static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
+ 		*hw_p = ehci->dummy->qh_dma;
+ }
+ 
++/*-------------------------------------------------------------------------*/
++
++/* Bandwidth and TT management */
++
++/* Find the TT data structure for this device; create it if necessary */
++static struct ehci_tt *find_tt(struct usb_device *udev)
++{
++	struct usb_tt		*utt = udev->tt;
++	struct ehci_tt		*tt, **tt_index, **ptt;
++	unsigned		port;
++	bool			allocated_index = false;
++
++	if (!utt)
++		return NULL;		/* Not below a TT */
++
++	/*
++	 * Find/create our data structure.
++	 * For hubs with a single TT, we get it directly.
++	 * For hubs with multiple TTs, there's an extra level of pointers.
++	 */
++	tt_index = NULL;
++	if (utt->multi) {
++		tt_index = utt->hcpriv;
++		if (!tt_index) {		/* Create the index array */
++			tt_index = kzalloc(utt->hub->maxchild *
++					sizeof(*tt_index), GFP_ATOMIC);
++			if (!tt_index)
++				return ERR_PTR(-ENOMEM);
++			utt->hcpriv = tt_index;
++			allocated_index = true;
++		}
++		port = udev->ttport - 1;
++		ptt = &tt_index[port];
++	} else {
++		port = 0;
++		ptt = (struct ehci_tt **) &utt->hcpriv;
++	}
++
++	tt = *ptt;
++	if (!tt) {				/* Create the ehci_tt */
++		struct ehci_hcd		*ehci =
++				hcd_to_ehci(bus_to_hcd(udev->bus));
++
++		tt = kzalloc(sizeof(*tt), GFP_ATOMIC);
++		if (!tt) {
++			if (allocated_index) {
++				utt->hcpriv = NULL;
++				kfree(tt_index);
++			}
++			return ERR_PTR(-ENOMEM);
++		}
++		list_add_tail(&tt->tt_list, &ehci->tt_list);
++		INIT_LIST_HEAD(&tt->ps_list);
++		tt->usb_tt = utt;
++		tt->tt_port = port;
++		*ptt = tt;
++	}
++
++	return tt;
++}
++
++/* Release the TT above udev, if it's not in use */
++static void drop_tt(struct usb_device *udev)
++{
++	struct usb_tt		*utt = udev->tt;
++	struct ehci_tt		*tt, **tt_index, **ptt;
++	int			cnt, i;
++
++	if (!utt || !utt->hcpriv)
++		return;		/* Not below a TT, or never allocated */
++
++	cnt = 0;
++	if (utt->multi) {
++		tt_index = utt->hcpriv;
++		ptt = &tt_index[udev->ttport - 1];
++
++		/* How many entries are left in tt_index? */
++		for (i = 0; i < utt->hub->maxchild; ++i)
++			cnt += !!tt_index[i];
++	} else {
++		tt_index = NULL;
++		ptt = (struct ehci_tt **) &utt->hcpriv;
++	}
++
++	tt = *ptt;
++	if (!tt || !list_empty(&tt->ps_list))
++		return;		/* never allocated, or still in use */
++
++	list_del(&tt->tt_list);
++	*ptt = NULL;
++	kfree(tt);
++	if (cnt == 1) {
++		utt->hcpriv = NULL;
++		kfree(tt_index);
++	}
++}
++
+ static void bandwidth_dbg(struct ehci_hcd *ehci, int sign, char *type,
+ 		struct ehci_per_sched *ps)
+ {
+@@ -125,6 +222,8 @@ static void reserve_release_intr_bandwidth(struct ehci_hcd *ehci,
+ 	unsigned		i, j, m;
+ 	int			usecs = qh->ps.usecs;
+ 	int			c_usecs = qh->ps.c_usecs;
++	int			tt_usecs = qh->ps.tt_usecs;
++	struct ehci_tt		*tt;
+ 
+ 	if (qh->ps.phase == NO_FRAME)	/* Bandwidth wasn't reserved */
+ 		return;
+@@ -135,6 +234,7 @@ static void reserve_release_intr_bandwidth(struct ehci_hcd *ehci,
+ 	if (sign < 0) {		/* Release bandwidth */
+ 		usecs = -usecs;
+ 		c_usecs = -c_usecs;
++		tt_usecs = -tt_usecs;
+ 	}
+ 
+ 	/* Entire transaction (high speed) or start-split (full/low speed) */
+@@ -153,11 +253,60 @@ static void reserve_release_intr_bandwidth(struct ehci_hcd *ehci,
+ 			}
+ 		}
+ 	}
++
++	/* FS/LS bus bandwidth */
++	if (tt_usecs) {
++		tt = find_tt(qh->ps.udev);
++		if (sign > 0)
++			list_add_tail(&qh->ps.ps_list, &tt->ps_list);
++		else
++			list_del(&qh->ps.ps_list);
++
++		for (i = start_uf >> 3; i < EHCI_BANDWIDTH_FRAMES;
++				i += qh->ps.bw_period)
++			tt->bandwidth[i] += tt_usecs;
++	}
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-static int same_tt (struct usb_device *dev1, struct usb_device *dev2)
++static void compute_tt_budget(u8 budget_table[EHCI_BANDWIDTH_SIZE],
++		struct ehci_tt *tt)
++{
++	struct ehci_per_sched	*ps;
++	unsigned		uframe, uf, x;
++	u8			*budget_line;
++
++	if (!tt)
++		return;
++	memset(budget_table, 0, EHCI_BANDWIDTH_SIZE);
++
++	/* Add up the contributions from all the endpoints using this TT */
++	list_for_each_entry(ps, &tt->ps_list, ps_list) {
++		for (uframe = ps->bw_phase << 3; uframe < EHCI_BANDWIDTH_SIZE;
++				uframe += ps->bw_uperiod) {
++			budget_line = &budget_table[uframe];
++			x = ps->tt_usecs;
++
++			/* propagate the time forward */
++			for (uf = ps->phase_uf; uf < 8; ++uf) {
++				x += budget_line[uf];
++
++				/* Each microframe lasts 125 us */
++				if (x <= 125) {
++					budget_line[uf] = x;
++					break;
++				} else {
++					budget_line[uf] = 125;
++					x -= 125;
++				}
++			}
++		}
++	}
++}
++
++static int __maybe_unused same_tt(struct usb_device *dev1,
++		struct usb_device *dev2)
+ {
+ 	if (!dev1->tt || !dev2->tt)
+ 		return 0;
+@@ -205,68 +354,6 @@ static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8])
+ 	}
+ }
+ 
+-/* How many of the tt's periodic downstream 1000 usecs are allocated?
+- *
+- * While this measures the bandwidth in terms of usecs/uframe,
+- * the low/fullspeed bus has no notion of uframes, so any particular
+- * low/fullspeed transfer can "carry over" from one uframe to the next,
+- * since the TT just performs downstream transfers in sequence.
+- *
+- * For example two separate 100 usec transfers can start in the same uframe,
+- * and the second one would "carry over" 75 usecs into the next uframe.
+- */
+-static void
+-periodic_tt_usecs (
+-	struct ehci_hcd *ehci,
+-	struct usb_device *dev,
+-	unsigned frame,
+-	unsigned short tt_usecs[8]
+-)
+-{
+-	__hc32			*hw_p = &ehci->periodic [frame];
+-	union ehci_shadow	*q = &ehci->pshadow [frame];
+-	unsigned char		uf;
+-
+-	memset(tt_usecs, 0, 16);
+-
+-	while (q->ptr) {
+-		switch (hc32_to_cpu(ehci, Q_NEXT_TYPE(ehci, *hw_p))) {
+-		case Q_TYPE_ITD:
+-			hw_p = &q->itd->hw_next;
+-			q = &q->itd->itd_next;
+-			continue;
+-		case Q_TYPE_QH:
+-			if (same_tt(dev, q->qh->ps.udev)) {
+-				uf = tt_start_uframe(ehci, q->qh->hw->hw_info2);
+-				tt_usecs[uf] += q->qh->ps.tt_usecs;
+-			}
+-			hw_p = &q->qh->hw->hw_next;
+-			q = &q->qh->qh_next;
+-			continue;
+-		case Q_TYPE_SITD:
+-			if (same_tt(dev, q->sitd->urb->dev)) {
+-				uf = tt_start_uframe(ehci, q->sitd->hw_uframe);
+-				tt_usecs[uf] += q->sitd->stream->ps.tt_usecs;
+-			}
+-			hw_p = &q->sitd->hw_next;
+-			q = &q->sitd->sitd_next;
+-			continue;
+-		// case Q_TYPE_FSTN:
+-		default:
+-			ehci_dbg(ehci, "ignoring periodic frame %d FSTN\n",
+-					frame);
+-			hw_p = &q->fstn->hw_next;
+-			q = &q->fstn->fstn_next;
+-		}
+-	}
+-
+-	carryover_tt_bandwidth(tt_usecs);
+-
+-	if (max_tt_usecs[7] < tt_usecs[7])
+-		ehci_err(ehci, "frame %d tt sched overrun: %d usecs\n",
+-			frame, tt_usecs[7] - max_tt_usecs[7]);
+-}
+-
+ /*
+  * Return true if the device's tt's downstream bus is available for a
+  * periodic transfer of the specified length (usecs), starting at the
+@@ -290,20 +377,29 @@ periodic_tt_usecs (
+  */
+ static int tt_available (
+ 	struct ehci_hcd		*ehci,
+-	unsigned		period,
+-	struct usb_device	*dev,
++	struct ehci_per_sched	*ps,
++	struct ehci_tt		*tt,
+ 	unsigned		frame,
+-	unsigned		uframe,
+-	u16			usecs
++	unsigned		uframe
+ )
+ {
++	unsigned		period = ps->bw_period;
++	unsigned		usecs = ps->tt_usecs;
++
+ 	if ((period == 0) || (uframe >= 7))	/* error */
+ 		return 0;
+ 
+-	for (; frame < ehci->periodic_size; frame += period) {
+-		unsigned short tt_usecs[8];
++	for (frame &= period - 1; frame < EHCI_BANDWIDTH_FRAMES;
++			frame += period) {
++		unsigned	i, uf;
++		unsigned short	tt_usecs[8];
++
++		if (tt->bandwidth[frame] + usecs > 900)
++			return 0;
+ 
+-		periodic_tt_usecs (ehci, dev, frame, tt_usecs);
++		uf = frame << 3;
++		for (i = 0; i < 8; (++i, ++uf))
++			tt_usecs[i] = ehci->tt_budget[uf];
+ 
+ 		if (max_tt_usecs[uframe] <= tt_usecs[uframe])
+ 			return 0;
+@@ -315,7 +411,7 @@ static int tt_available (
+ 		 */
+ 		if (125 < usecs) {
+ 			int ufs = (usecs / 125);
+-			int i;
++
+ 			for (i = uframe; i < (uframe + ufs) && i < 8; i++)
+ 				if (0 < tt_usecs[i])
+ 					return 0;
+@@ -697,8 +793,9 @@ static int check_intr_schedule (
+ 	struct ehci_hcd		*ehci,
+ 	unsigned		frame,
+ 	unsigned		uframe,
+-	const struct ehci_qh	*qh,
+-	__hc32			*c_maskp
++	struct ehci_qh		*qh,
++	__hc32			*c_maskp,
++	struct ehci_tt		*tt
+ )
+ {
+ 	int		retval = -ENOSPC;
+@@ -716,8 +813,7 @@ static int check_intr_schedule (
+ 	}
+ 
+ #ifdef CONFIG_USB_EHCI_TT_NEWSCHED
+-	if (tt_available(ehci, qh->ps.bw_period, qh->ps.udev, frame, uframe,
+-				qh->ps.tt_usecs)) {
++	if (tt_available(ehci, &qh->ps, tt, frame, uframe)) {
+ 		unsigned i;
+ 
+ 		/* TODO : this may need FSTN for SSPLIT in uframe 5. */
+@@ -763,10 +859,11 @@ static int check_intr_schedule (
+  */
+ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ {
+-	int		status;
++	int		status = 0;
+ 	unsigned	uframe;
+ 	unsigned	c_mask;
+ 	struct ehci_qh_hw	*hw = qh->hw;
++	struct ehci_tt		*tt;
+ 
+ 	hw->hw_next = EHCI_LIST_END(ehci);
+ 
+@@ -778,7 +875,12 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 
+ 	uframe = 0;
+ 	c_mask = 0;
+-	status = -ENOSPC;
++	tt = find_tt(qh->ps.udev);
++	if (IS_ERR(tt)) {
++		status = PTR_ERR(tt);
++		goto done;
++	}
++	compute_tt_budget(ehci->tt_budget, tt);
+ 
+ 	/* else scan the schedule to find a group of slots such that all
+ 	 * uframes have enough periodic bandwidth available.
+@@ -788,22 +890,24 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		int		i;
+ 		unsigned	frame;
+ 
+-		for (i = qh->ps.bw_period; status && i > 0; --i) {
++		for (i = qh->ps.bw_period; i > 0; --i) {
+ 			frame = ++ehci->random_frame & (qh->ps.bw_period - 1);
+ 			for (uframe = 0; uframe < 8; uframe++) {
+ 				status = check_intr_schedule(ehci,
+-						frame, uframe, qh, &c_mask);
++						frame, uframe, qh, &c_mask, tt);
+ 				if (status == 0)
+-					break;
++					goto got_it;
+ 			}
+ 		}
+ 
+ 	/* qh->ps.bw_period == 0 means every uframe */
+ 	} else {
+-		status = check_intr_schedule(ehci, 0, 0, qh, &c_mask);
++		status = check_intr_schedule(ehci, 0, 0, qh, &c_mask, tt);
+ 	}
+ 	if (status)
+ 		goto done;
++
++ got_it:
+ 	qh->ps.phase = (qh->ps.period ? ehci->random_frame &
+ 			(qh->ps.period - 1) : 0);
+ 	qh->ps.bw_phase = qh->ps.phase & (qh->ps.bw_period - 1);
+@@ -1232,6 +1336,8 @@ static void reserve_release_iso_bandwidth(struct ehci_hcd *ehci,
+ 	unsigned		s_mask, c_mask, m;
+ 	int			usecs = stream->ps.usecs;
+ 	int			c_usecs = stream->ps.c_usecs;
++	int			tt_usecs = stream->ps.tt_usecs;
++	struct ehci_tt		*tt;
+ 
+ 	if (stream->ps.phase == NO_FRAME)	/* Bandwidth wasn't reserved */
+ 		return;
+@@ -1242,6 +1348,7 @@ static void reserve_release_iso_bandwidth(struct ehci_hcd *ehci,
+ 	if (sign < 0) {		/* Release bandwidth */
+ 		usecs = -usecs;
+ 		c_usecs = -c_usecs;
++		tt_usecs = -tt_usecs;
+ 	}
+ 
+ 	if (!stream->splits) {		/* High speed */
+@@ -1264,6 +1371,16 @@ static void reserve_release_iso_bandwidth(struct ehci_hcd *ehci,
+ 					ehci->bandwidth[i+j] += c_usecs;
+ 			}
+ 		}
++
++		tt = find_tt(stream->ps.udev);
++		if (sign > 0)
++			list_add_tail(&stream->ps.ps_list, &tt->ps_list);
++		else
++			list_del(&stream->ps.ps_list);
++
++		for (i = uframe >> 3; i < EHCI_BANDWIDTH_FRAMES;
++				i += stream->ps.bw_period)
++			tt->bandwidth[i] += tt_usecs;
+ 	}
+ }
+ 
+@@ -1292,7 +1409,8 @@ sitd_slot_ok (
+ 	struct ehci_hcd		*ehci,
+ 	struct ehci_iso_stream	*stream,
+ 	unsigned		uframe,
+-	struct ehci_iso_sched	*sched
++	struct ehci_iso_sched	*sched,
++	struct ehci_tt		*tt
+ )
+ {
+ 	unsigned		mask, tmp;
+@@ -1317,8 +1435,7 @@ sitd_slot_ok (
+ 	 * tt_available scheduling guarantees 10+% for control/bulk.
+ 	 */
+ 	uf = uframe & 7;
+-	if (!tt_available(ehci, stream->ps.bw_period,
+-			stream->ps.udev, frame, uf, stream->ps.tt_usecs))
++	if (!tt_available(ehci, &stream->ps, tt, frame, uf))
+ 		return 0;
+ #else
+ 	/* tt must be idle for start(s), any gap, and csplit.
+@@ -1417,6 +1534,13 @@ iso_stream_schedule (
+ 		/* Schedule the endpoint */
+ 		if (stream->ps.phase == NO_FRAME) {
+ 			int		done = 0;
++			struct ehci_tt	*tt = find_tt(stream->ps.udev);
++
++			if (IS_ERR(tt)) {
++				status = PTR_ERR(tt);
++				goto fail;
++			}
++			compute_tt_budget(ehci->tt_budget, tt);
+ 
+ 			start = (now & ~0x07) + SCHEDULING_DELAY;
+ 
+@@ -1437,7 +1561,7 @@ iso_stream_schedule (
+ 					if ((start % 8) >= 6)
+ 						continue;
+ 					if (sitd_slot_ok(ehci, stream, start,
+-							sched))
++							sched, tt))
+ 						done = 1;
+ 				}
+ 			} while (start > next && !done);
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 12504fbded56..e8f41c5e771b 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -61,6 +61,7 @@ struct ehci_stats {
+ struct ehci_per_sched {
+ 	struct usb_device	*udev;		/* access to the TT */
+ 	struct usb_host_endpoint *ep;
++	struct list_head	ps_list;	/* node on ehci_tt's ps_list */
+ 	u16			tt_usecs;	/* time on the FS/LS bus */
+ 	u16			cs_mask;	/* C-mask and S-mask bytes */
+ 	u16			period;		/* actual period in frames */
+@@ -256,6 +257,9 @@ struct ehci_hcd {			/* one per controller */
+ #define EHCI_BANDWIDTH_FRAMES	(EHCI_BANDWIDTH_SIZE >> 3)
+ 	u8			bandwidth[EHCI_BANDWIDTH_SIZE];
+ 						/* us allocated per uframe */
++	u8			tt_budget[EHCI_BANDWIDTH_SIZE];
++						/* us budgeted per uframe */
++	struct list_head	tt_list;
+ 
+ 	/* platform-specific data -- must come last */
+ 	unsigned long		priv[0] __aligned(sizeof(s64));
+@@ -595,6 +599,35 @@ struct ehci_fstn {
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++/*
++ * USB-2.0 Specification Sections 11.14 and 11.18
++ * Scheduling and budgeting split transactions using TTs
++ *
++ * A hub can have a single TT for all its ports, or multiple TTs (one for each
++ * port).  The bandwidth and budgeting information for the full/low-speed bus
++ * below each TT is self-contained and independent of the other TTs or the
++ * high-speed bus.
++ *
++ * "Bandwidth" refers to the number of microseconds on the FS/LS bus allocated
++ * to an interrupt or isochronous endpoint for each frame.  "Budget" refers to
++ * the best-case estimate of the number of full-speed bytes allocated to an
++ * endpoint for each microframe within an allocated frame.
++ *
++ * Removal of an endpoint invalidates a TT's budget.  Instead of trying to
++ * keep an up-to-date record, we recompute the budget when it is needed.
++ */
++
++struct ehci_tt {
++	u16			bandwidth[EHCI_BANDWIDTH_FRAMES];
++
++	struct list_head	tt_list;	/* List of all ehci_tt's */
++	struct list_head	ps_list;	/* Items using this TT */
++	struct usb_tt		*usb_tt;
++	int			tt_port;	/* TT port number */
++};
++
++/*-------------------------------------------------------------------------*/
++
+ /* Prepare the PORTSC wakeup flags during controller suspend/resume */
+ 
+ #define ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup)	\

commit 7c4bb942986fc2aa7ca4fccfed665d24525a0e21
+Author: Alan Stern 
+Date:   Fri Oct 11 11:29:22 2013 -0400
+
+    USB: add a private-data pointer to struct usb_tt
+    
+    For improved scheduling of transfers through a Transaction Translator,
+    ehci-hcd will need to store a bunch of information associated with the
+    FS/LS bus on the downstream side of the TT.  This patch adds a pointer
+    for such HCD-private data to the usb_tt structure.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
+index dbe3cd19ffd8..b8aba196f7f1 100644
+--- a/include/linux/usb/hcd.h
++++ b/include/linux/usb/hcd.h
+@@ -506,6 +506,7 @@ struct usb_tt {
+ 	struct usb_device	*hub;	/* upstream highspeed hub */
+ 	int			multi;	/* true means one TT per port */
+ 	unsigned		think_time;	/* think time in ns */
++	void			*hcpriv;	/* HCD private data */
+ 
+ 	/* for control/bulk error recovery (CLEAR_TT_BUFFER) */
+ 	spinlock_t		lock;

commit d0ce5c6b9208c79fc725c578eebdeb5724faf17d
+Author: Alan Stern 
+Date:   Fri Oct 11 11:29:13 2013 -0400
+
+    USB: EHCI: use a bandwidth-allocation table
+    
+    This patch significantly changes the scheduling code in ehci-hcd.
+    Instead of calculating the current bandwidth utilization by trudging
+    through the schedule and adding up the times used by the existing
+    transfers, we will now maintain a table holding the time used for each
+    of 64 microframes.  This will drastically speed up the bandwidth
+    computations.
+    
+    In addition, it eliminates a theoretical bug.  An isochronous endpoint
+    may have bandwidth reserved even at times when it has no transfers
+    listed in the schedule.  The table will keep track of the reserved
+    bandwidth, whereas adding up entries in the schedule would miss it.
+    
+    As a corollary, we can keep bandwidth reserved for endpoints even
+    when they aren't in active use.  Eventually the bandwidth will be
+    reserved when a new alternate setting is installed; for now the
+    endpoint's reservation takes place when its first URB is submitted.
+    
+    A drawback of this approach is that transfers with an interval larger
+    than 64 microframes will have to be charged for bandwidth as though
+    the interval was 64.  In practice this shouldn't matter much;
+    transfers with longer intervals tend to be rather short anyway (things
+    like hubs or HID devices).
+    
+    Another minor drawback is that we will keep track of two different
+    period and phase values: the actual ones and the ones used for
+    bandwidth allocation (which are limited to 64).  This adds only a
+    small amount of overhead: 3 bytes for each endpoint.
+    
+    The patch also adds a new debugfs file named "bandwidth" to display
+    the information stored in the new table.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
+index 09e5bc8e2b98..5bbfb1f9929c 100644
+--- a/drivers/usb/host/ehci-dbg.c
++++ b/drivers/usb/host/ehci-dbg.c
+@@ -334,6 +334,7 @@ static inline void remove_debug_files (struct ehci_hcd *bus) { }
+ /* troubleshooting help: expose state in debugfs */
+ 
+ static int debug_async_open(struct inode *, struct file *);
++static int debug_bandwidth_open(struct inode *, struct file *);
+ static int debug_periodic_open(struct inode *, struct file *);
+ static int debug_registers_open(struct inode *, struct file *);
+ 
+@@ -347,6 +348,13 @@ static const struct file_operations debug_async_fops = {
+ 	.release	= debug_close,
+ 	.llseek		= default_llseek,
+ };
++static const struct file_operations debug_bandwidth_fops = {
++	.owner		= THIS_MODULE,
++	.open		= debug_bandwidth_open,
++	.read		= debug_output,
++	.release	= debug_close,
++	.llseek		= default_llseek,
++};
+ static const struct file_operations debug_periodic_fops = {
+ 	.owner		= THIS_MODULE,
+ 	.open		= debug_periodic_open,
+@@ -525,6 +533,41 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf)
+ 	return strlen(buf->output_buf);
+ }
+ 
++static ssize_t fill_bandwidth_buffer(struct debug_buffer *buf)
++{
++	struct ehci_hcd		*ehci;
++	unsigned		temp, size;
++	char			*next;
++	unsigned		i;
++	u8			*bw;
++
++	ehci = hcd_to_ehci(bus_to_hcd(buf->bus));
++	next = buf->output_buf;
++	size = buf->alloc_size;
++
++	*next = 0;
++
++	spin_lock_irq(&ehci->lock);
++
++	/* Dump the HS bandwidth table */
++	temp = scnprintf(next, size,
++			"HS bandwidth allocation (us per microframe)\n");
++	size -= temp;
++	next += temp;
++	for (i = 0; i < EHCI_BANDWIDTH_SIZE; i += 8) {
++		bw = &ehci->bandwidth[i];
++		temp = scnprintf(next, size,
++				"%2u: %4u%4u%4u%4u%4u%4u%4u%4u\n",
++				i, bw[0], bw[1], bw[2], bw[3],
++					bw[4], bw[5], bw[6], bw[7]);
++		size -= temp;
++		next += temp;
++	}
++	spin_unlock_irq(&ehci->lock);
++
++	return next - buf->output_buf;
++}
++
+ #define DBG_SCHED_LIMIT 64
+ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
+ {
+@@ -919,6 +962,7 @@ static int debug_close(struct inode *inode, struct file *file)
+ 
+ 	return 0;
+ }
++
+ static int debug_async_open(struct inode *inode, struct file *file)
+ {
+ 	file->private_data = alloc_buffer(inode->i_private, fill_async_buffer);
+@@ -926,6 +970,14 @@ static int debug_async_open(struct inode *inode, struct file *file)
+ 	return file->private_data ? 0 : -ENOMEM;
+ }
+ 
++static int debug_bandwidth_open(struct inode *inode, struct file *file)
++{
++	file->private_data = alloc_buffer(inode->i_private,
++			fill_bandwidth_buffer);
++
++	return file->private_data ? 0 : -ENOMEM;
++}
++
+ static int debug_periodic_open(struct inode *inode, struct file *file)
+ {
+ 	struct debug_buffer *buf;
+@@ -958,6 +1010,10 @@ static inline void create_debug_files (struct ehci_hcd *ehci)
+ 						&debug_async_fops))
+ 		goto file_error;
+ 
++	if (!debugfs_create_file("bandwidth", S_IRUGO, ehci->debug_dir, bus,
++						&debug_bandwidth_fops))
++		goto file_error;
++
+ 	if (!debugfs_create_file("periodic", S_IRUGO, ehci->debug_dir, bus,
+ 						&debug_periodic_fops))
+ 		goto file_error;
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index b2e4e4b3cfae..398e8fa3032f 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -956,6 +956,7 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 			goto idle_timeout;
+ 
+ 		/* BUG_ON(!list_empty(&stream->free_list)); */
++		reserve_release_iso_bandwidth(ehci, stream, -1);
+ 		kfree(stream);
+ 		goto done;
+ 	}
+@@ -982,6 +983,8 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 		if (qh->clearing_tt)
+ 			goto idle_timeout;
+ 		if (list_empty (&qh->qtd_list)) {
++			if (qh->ps.bw_uperiod)
++				reserve_release_intr_bandwidth(ehci, qh, -1);
+ 			qh_destroy(ehci, qh);
+ 			break;
+ 		}
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 9bfaa21707bd..db05bd8ee9d5 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -797,6 +797,8 @@ qh_make (
+ 	 * For control/bulk requests, the HC or TT handles these.
+ 	 */
+ 	if (type == PIPE_INTERRUPT) {
++		unsigned	tmp;
++
+ 		qh->ps.usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH,
+ 				is_input, 0,
+ 				hb_mult(maxp) * max_packet(maxp)));
+@@ -816,6 +818,14 @@ qh_make (
+ 				urb->interval = ehci->periodic_size << 3;
+ 			}
+ 			qh->ps.period = urb->interval >> 3;
++
++			/* period for bandwidth allocation */
++			tmp = min_t(unsigned, EHCI_BANDWIDTH_SIZE,
++					1 << (urb->ep->desc.bInterval - 1));
++
++			/* Allow urb->interval to override */
++			qh->ps.bw_uperiod = min_t(unsigned, tmp, urb->interval);
++			qh->ps.bw_period = qh->ps.bw_uperiod >> 3;
+ 		} else {
+ 			int		think_time;
+ 
+@@ -839,6 +849,15 @@ qh_make (
+ 			if (urb->interval > ehci->periodic_size)
+ 				urb->interval = ehci->periodic_size;
+ 			qh->ps.period = urb->interval;
++
++			/* period for bandwidth allocation */
++			tmp = min_t(unsigned, EHCI_BANDWIDTH_FRAMES,
++					urb->ep->desc.bInterval);
++			tmp = rounddown_pow_of_two(tmp);
++
++			/* Allow urb->interval to override */
++			qh->ps.bw_period = min_t(unsigned, tmp, urb->interval);
++			qh->ps.bw_uperiod = qh->ps.bw_period << 3;
+ 		}
+ 	}
+ 
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 1fafcda0ae81..790a64c0da5c 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -106,75 +106,53 @@ static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
+ 		*hw_p = ehci->dummy->qh_dma;
+ }
+ 
+-/* how many of the uframe's 125 usecs are allocated? */
+-static unsigned short
+-periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
++static void bandwidth_dbg(struct ehci_hcd *ehci, int sign, char *type,
++		struct ehci_per_sched *ps)
+ {
+-	__hc32			*hw_p = &ehci->periodic [frame];
+-	union ehci_shadow	*q = &ehci->pshadow [frame];
+-	unsigned		usecs = 0;
+-	struct ehci_qh_hw	*hw;
++	dev_dbg(&ps->udev->dev,
++			"ep %02x: %s %s @ %u+%u (%u.%u+%u) [%u/%u us] mask %04x\n",
++			ps->ep->desc.bEndpointAddress,
++			(sign >= 0 ? "reserve" : "release"), type,
++			(ps->bw_phase << 3) + ps->phase_uf, ps->bw_uperiod,
++			ps->phase, ps->phase_uf, ps->period,
++			ps->usecs, ps->c_usecs, ps->cs_mask);
++}
+ 
+-	while (q->ptr) {
+-		switch (hc32_to_cpu(ehci, Q_NEXT_TYPE(ehci, *hw_p))) {
+-		case Q_TYPE_QH:
+-			hw = q->qh->hw;
+-			/* is it in the S-mask? */
+-			if (hw->hw_info2 & cpu_to_hc32(ehci, 1 << uframe))
+-				usecs += q->qh->ps.usecs;
+-			/* ... or C-mask? */
+-			if (hw->hw_info2 & cpu_to_hc32(ehci,
+-					1 << (8 + uframe)))
+-				usecs += q->qh->ps.c_usecs;
+-			hw_p = &hw->hw_next;
+-			q = &q->qh->qh_next;
+-			break;
+-		// case Q_TYPE_FSTN:
+-		default:
+-			/* for "save place" FSTNs, count the relevant INTR
+-			 * bandwidth from the previous frame
+-			 */
+-			if (q->fstn->hw_prev != EHCI_LIST_END(ehci)) {
+-				ehci_dbg (ehci, "ignoring FSTN cost ...\n");
+-			}
+-			hw_p = &q->fstn->hw_next;
+-			q = &q->fstn->fstn_next;
+-			break;
+-		case Q_TYPE_ITD:
+-			if (q->itd->hw_transaction[uframe])
+-				usecs += q->itd->stream->ps.usecs;
+-			hw_p = &q->itd->hw_next;
+-			q = &q->itd->itd_next;
+-			break;
+-		case Q_TYPE_SITD:
+-			/* is it in the S-mask?  (count SPLIT, DATA) */
+-			if (q->sitd->hw_uframe & cpu_to_hc32(ehci,
+-					1 << uframe)) {
+-				if (q->sitd->hw_fullspeed_ep &
+-						cpu_to_hc32(ehci, 1<<31))
+-					usecs += q->sitd->stream->ps.usecs;
+-				else	/* worst case for OUT start-split */
+-					usecs += HS_USECS_ISO (188);
+-			}
++static void reserve_release_intr_bandwidth(struct ehci_hcd *ehci,
++		struct ehci_qh *qh, int sign)
++{
++	unsigned		start_uf;
++	unsigned		i, j, m;
++	int			usecs = qh->ps.usecs;
++	int			c_usecs = qh->ps.c_usecs;
+ 
+-			/* ... C-mask?  (count CSPLIT, DATA) */
+-			if (q->sitd->hw_uframe &
+-					cpu_to_hc32(ehci, 1 << (8 + uframe))) {
+-				/* worst case for IN complete-split */
+-				usecs += q->sitd->stream->ps.c_usecs;
+-			}
++	if (qh->ps.phase == NO_FRAME)	/* Bandwidth wasn't reserved */
++		return;
++	start_uf = qh->ps.bw_phase << 3;
+ 
+-			hw_p = &q->sitd->hw_next;
+-			q = &q->sitd->sitd_next;
+-			break;
++	bandwidth_dbg(ehci, sign, "intr", &qh->ps);
++
++	if (sign < 0) {		/* Release bandwidth */
++		usecs = -usecs;
++		c_usecs = -c_usecs;
++	}
++
++	/* Entire transaction (high speed) or start-split (full/low speed) */
++	for (i = start_uf + qh->ps.phase_uf; i < EHCI_BANDWIDTH_SIZE;
++			i += qh->ps.bw_uperiod)
++		ehci->bandwidth[i] += usecs;
++
++	/* Complete-split (full/low speed) */
++	if (qh->ps.c_usecs) {
++		/* NOTE: adjustments needed for FSTN */
++		for (i = start_uf; i < EHCI_BANDWIDTH_SIZE;
++				i += qh->ps.bw_uperiod) {
++			for ((j = 2, m = 1 << (j+8)); j < 8; (++j, m <<= 1)) {
++				if (qh->ps.cs_mask & m)
++					ehci->bandwidth[i+j] += c_usecs;
++			}
+ 		}
+ 	}
+-#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
+-	if (usecs > ehci->uframe_periodic_max)
+-		ehci_err (ehci, "uframe %d sched overrun: %d usecs\n",
+-			frame * 8 + uframe, usecs);
+-#endif
+-	return usecs;
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -524,8 +502,8 @@ static void qh_link_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	qh->exception = 0;
+ 
+ 	/* update per-qh bandwidth for debugfs */
+-	ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->ps.period
+-		? ((qh->ps.usecs + qh->ps.c_usecs) / qh->ps.period)
++	ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->ps.bw_period
++		? ((qh->ps.usecs + qh->ps.c_usecs) / qh->ps.bw_period)
+ 		: (qh->ps.usecs * 8);
+ 
+ 	list_add(&qh->intr_node, &ehci->intr_qh_list);
+@@ -562,8 +540,8 @@ static void qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		periodic_unlink (ehci, i, qh);
+ 
+ 	/* update per-qh bandwidth for debugfs */
+-	ehci_to_hcd(ehci)->self.bandwidth_allocated -= qh->ps.period
+-		? ((qh->ps.usecs + qh->ps.c_usecs) / qh->ps.period)
++	ehci_to_hcd(ehci)->self.bandwidth_allocated -= qh->ps.bw_period
++		? ((qh->ps.usecs + qh->ps.c_usecs) / qh->ps.bw_period)
+ 		: (qh->ps.usecs * 8);
+ 
+ 	dev_dbg(&qh->ps.udev->dev,
+@@ -693,11 +671,9 @@ static int check_period (
+ 	struct ehci_hcd *ehci,
+ 	unsigned	frame,
+ 	unsigned	uframe,
+-	unsigned	period,
++	unsigned	uperiod,
+ 	unsigned	usecs
+ ) {
+-	int		claimed;
+-
+ 	/* complete split running into next frame?
+ 	 * given FSTN support, we could sometimes check...
+ 	 */
+@@ -707,25 +683,10 @@ static int check_period (
+ 	/* convert "usecs we need" to "max already claimed" */
+ 	usecs = ehci->uframe_periodic_max - usecs;
+ 
+-	/* we "know" 2 and 4 uframe intervals were rejected; so
+-	 * for period 0, check _every_ microframe in the schedule.
+-	 */
+-	if (unlikely (period == 0)) {
+-		do {
+-			for (uframe = 0; uframe < 7; uframe++) {
+-				claimed = periodic_usecs (ehci, frame, uframe);
+-				if (claimed > usecs)
+-					return 0;
+-			}
+-		} while ((frame += 1) < ehci->periodic_size);
+-
+-	/* just check the specified uframe, at that period */
+-	} else {
+-		do {
+-			claimed = periodic_usecs (ehci, frame, uframe);
+-			if (claimed > usecs)
+-				return 0;
+-		} while ((frame += period) < ehci->periodic_size);
++	for (uframe += frame << 3; uframe < EHCI_BANDWIDTH_SIZE;
++			uframe += uperiod) {
++		if (ehci->bandwidth[uframe] > usecs)
++			return 0;
+ 	}
+ 
+ 	// success!
+@@ -746,7 +707,7 @@ static int check_intr_schedule (
+ 	if (qh->ps.c_usecs && uframe >= 6)	/* FSTN territory? */
+ 		goto done;
+ 
+-	if (!check_period(ehci, frame, uframe, qh->ps.period, qh->ps.usecs))
++	if (!check_period(ehci, frame, uframe, qh->ps.bw_uperiod, qh->ps.usecs))
+ 		goto done;
+ 	if (!qh->ps.c_usecs) {
+ 		retval = 0;
+@@ -755,21 +716,21 @@ static int check_intr_schedule (
+ 	}
+ 
+ #ifdef CONFIG_USB_EHCI_TT_NEWSCHED
+-	if (tt_available(ehci, qh->ps.period, qh->ps.udev, frame, uframe,
++	if (tt_available(ehci, qh->ps.bw_period, qh->ps.udev, frame, uframe,
+ 				qh->ps.tt_usecs)) {
+ 		unsigned i;
+ 
+ 		/* TODO : this may need FSTN for SSPLIT in uframe 5. */
+ 		for (i = uframe+2; i < 8 && i <= uframe+4; i++)
+ 			if (!check_period(ehci, frame, i,
+-					qh->ps.period, qh->ps.c_usecs))
++					qh->ps.bw_uperiod, qh->ps.c_usecs))
+ 				goto done;
+ 			else
+ 				mask |= 1 << i;
+ 
+ 		retval = 0;
+ 
+-		*c_maskp = cpu_to_hc32(ehci, mask << 8);
++		*c_maskp = mask;
+ 	}
+ #else
+ 	/* Make sure this tt's buffer is also available for CSPLITs.
+@@ -780,15 +741,15 @@ static int check_intr_schedule (
+ 	 * one smart pass...
+ 	 */
+ 	mask = 0x03 << (uframe + qh->gap_uf);
+-	*c_maskp = cpu_to_hc32(ehci, mask << 8);
++	*c_maskp = mask;
+ 
+ 	mask |= 1 << uframe;
+-	if (tt_no_collision(ehci, qh->ps.period, qh->ps.udev, frame, mask)) {
++	if (tt_no_collision(ehci, qh->ps.bw_period, qh->ps.udev, frame, mask)) {
+ 		if (!check_period(ehci, frame, uframe + qh->gap_uf + 1,
+-				qh->ps.period, qh->ps.c_usecs))
++				qh->ps.bw_uperiod, qh->ps.c_usecs))
+ 			goto done;
+ 		if (!check_period(ehci, frame, uframe + qh->gap_uf,
+-				qh->ps.period, qh->ps.c_usecs))
++				qh->ps.bw_uperiod, qh->ps.c_usecs))
+ 			goto done;
+ 		retval = 0;
+ 	}
+@@ -804,60 +765,57 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ {
+ 	int		status;
+ 	unsigned	uframe;
+-	__hc32		c_mask;
+-	unsigned	frame;		/* 0..(qh->period - 1), or NO_FRAME */
++	unsigned	c_mask;
+ 	struct ehci_qh_hw	*hw = qh->hw;
+ 
+ 	hw->hw_next = EHCI_LIST_END(ehci);
+-	frame = qh->ps.phase;
+ 
+ 	/* reuse the previous schedule slots, if we can */
+-	if (frame != NO_FRAME) {
+-		uframe = ffs(hc32_to_cpup(ehci, &hw->hw_info2) & QH_SMASK);
+-		status = check_intr_schedule (ehci, frame, --uframe,
+-				qh, &c_mask);
+-	} else {
+-		uframe = 0;
+-		c_mask = 0;
+-		status = -ENOSPC;
++	if (qh->ps.phase != NO_FRAME) {
++		ehci_dbg(ehci, "reused qh %p schedule\n", qh);
++		return 0;
+ 	}
+ 
++	uframe = 0;
++	c_mask = 0;
++	status = -ENOSPC;
++
+ 	/* else scan the schedule to find a group of slots such that all
+ 	 * uframes have enough periodic bandwidth available.
+ 	 */
+-	if (status) {
+-		/* "normal" case, uframing flexible except with splits */
+-		if (qh->ps.period) {
+-			int		i;
+-
+-			for (i = qh->ps.period; status && i > 0; --i) {
+-				frame = ++ehci->random_frame % qh->ps.period;
+-				for (uframe = 0; uframe < 8; uframe++) {
+-					status = check_intr_schedule (ehci,
+-							frame, uframe, qh,
+-							&c_mask);
+-					if (status == 0)
+-						break;
+-				}
++	/* "normal" case, uframing flexible except with splits */
++	if (qh->ps.bw_period) {
++		int		i;
++		unsigned	frame;
++
++		for (i = qh->ps.bw_period; status && i > 0; --i) {
++			frame = ++ehci->random_frame & (qh->ps.bw_period - 1);
++			for (uframe = 0; uframe < 8; uframe++) {
++				status = check_intr_schedule(ehci,
++						frame, uframe, qh, &c_mask);
++				if (status == 0)
++					break;
+ 			}
+-
+-		/* qh->ps.period == 0 means every uframe */
+-		} else {
+-			frame = 0;
+-			status = check_intr_schedule (ehci, 0, 0, qh, &c_mask);
+ 		}
+-		if (status)
+-			goto done;
+-		qh->ps.phase = frame;
+ 
+-		/* reset S-frame and (maybe) C-frame masks */
+-		hw->hw_info2 &= cpu_to_hc32(ehci, ~(QH_CMASK | QH_SMASK));
+-		hw->hw_info2 |= qh->ps.period
+-			? cpu_to_hc32(ehci, 1 << uframe)
+-			: cpu_to_hc32(ehci, QH_SMASK);
+-		hw->hw_info2 |= c_mask;
+-	} else
+-		ehci_dbg (ehci, "reused qh %p schedule\n", qh);
++	/* qh->ps.bw_period == 0 means every uframe */
++	} else {
++		status = check_intr_schedule(ehci, 0, 0, qh, &c_mask);
++	}
++	if (status)
++		goto done;
++	qh->ps.phase = (qh->ps.period ? ehci->random_frame &
++			(qh->ps.period - 1) : 0);
++	qh->ps.bw_phase = qh->ps.phase & (qh->ps.bw_period - 1);
++	qh->ps.phase_uf = uframe;
++	qh->ps.cs_mask = qh->ps.period ?
++			(c_mask << 8) | (1 << uframe) :
++			QH_SMASK;
++
++	/* reset S-frame and (maybe) C-frame masks */
++	hw->hw_info2 &= cpu_to_hc32(ehci, ~(QH_CMASK | QH_SMASK));
++	hw->hw_info2 |= cpu_to_hc32(ehci, qh->ps.cs_mask);
++	reserve_release_intr_bandwidth(ehci, qh, 1);
+ 
+ done:
+ 	return status;
+@@ -969,6 +927,7 @@ iso_stream_alloc (gfp_t mem_flags)
+ 		INIT_LIST_HEAD(&stream->td_list);
+ 		INIT_LIST_HEAD(&stream->free_list);
+ 		stream->next_uframe = NO_FRAME;
++		stream->ps.phase = NO_FRAME;
+ 	}
+ 	return stream;
+ }
+@@ -983,10 +942,10 @@ iso_stream_init (
+ 	static const u8 smask_out [] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f };
+ 
+ 	struct usb_device	*dev = urb->dev;
+-	unsigned		interval = urb->interval;
+ 	u32			buf1;
+ 	unsigned		epnum, maxp;
+ 	int			is_input;
++	unsigned		tmp;
+ 
+ 	/*
+ 	 * this might be a "high bandwidth" highspeed endpoint,
+@@ -1020,9 +979,17 @@ iso_stream_init (
+ 		 */
+ 		stream->ps.usecs = HS_USECS_ISO(maxp);
+ 
+-		stream->bandwidth = stream->ps.usecs * 8 / interval;
+-		stream->uperiod = interval;
+-		stream->ps.period = interval >> 3;
++		/* period for bandwidth allocation */
++		tmp = min_t(unsigned, EHCI_BANDWIDTH_SIZE,
++				1 << (urb->ep->desc.bInterval - 1));
++
++		/* Allow urb->interval to override */
++		stream->ps.bw_uperiod = min_t(unsigned, tmp, urb->interval);
++
++		stream->uperiod = urb->interval;
++		stream->ps.period = urb->interval >> 3;
++		stream->bandwidth = stream->ps.usecs * 8 /
++				stream->ps.bw_uperiod;
+ 
+ 	} else {
+ 		u32		addr;
+@@ -1047,20 +1014,28 @@ iso_stream_init (
+ 			addr |= 1 << 31;
+ 			stream->ps.c_usecs = stream->ps.usecs;
+ 			stream->ps.usecs = HS_USECS_ISO(1);
+-			stream->raw_mask = 1;
++			stream->ps.cs_mask = 1;
+ 
+ 			/* c-mask as specified in USB 2.0 11.18.4 3.c */
+ 			tmp = (1 << (hs_transfers + 2)) - 1;
+-			stream->raw_mask |= tmp << (8 + 2);
++			stream->ps.cs_mask |= tmp << (8 + 2);
+ 		} else
+-			stream->raw_mask = smask_out [hs_transfers - 1];
++			stream->ps.cs_mask = smask_out[hs_transfers - 1];
++
++		/* period for bandwidth allocation */
++		tmp = min_t(unsigned, EHCI_BANDWIDTH_FRAMES,
++				1 << (urb->ep->desc.bInterval - 1));
+ 
++		/* Allow urb->interval to override */
++		stream->ps.bw_period = min_t(unsigned, tmp, urb->interval);
++		stream->ps.bw_uperiod = stream->ps.bw_period << 3;
++
++		stream->ps.period = urb->interval;
++		stream->uperiod = urb->interval << 3;
+ 		stream->bandwidth = (stream->ps.usecs + stream->ps.c_usecs) /
+-				interval;
+-		stream->uperiod = interval << 3;
+-		stream->ps.period = interval;
++				stream->ps.bw_period;
+ 
+-		/* stream->splits gets created from raw_mask later */
++		/* stream->splits gets created from cs_mask later */
+ 		stream->address = cpu_to_hc32(ehci, addr);
+ 	}
+ 
+@@ -1249,45 +1224,84 @@ itd_urb_transaction (
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++static void reserve_release_iso_bandwidth(struct ehci_hcd *ehci,
++		struct ehci_iso_stream *stream, int sign)
++{
++	unsigned		uframe;
++	unsigned		i, j;
++	unsigned		s_mask, c_mask, m;
++	int			usecs = stream->ps.usecs;
++	int			c_usecs = stream->ps.c_usecs;
++
++	if (stream->ps.phase == NO_FRAME)	/* Bandwidth wasn't reserved */
++		return;
++	uframe = stream->ps.bw_phase << 3;
++
++	bandwidth_dbg(ehci, sign, "iso", &stream->ps);
++
++	if (sign < 0) {		/* Release bandwidth */
++		usecs = -usecs;
++		c_usecs = -c_usecs;
++	}
++
++	if (!stream->splits) {		/* High speed */
++		for (i = uframe + stream->ps.phase_uf; i < EHCI_BANDWIDTH_SIZE;
++				i += stream->ps.bw_uperiod)
++			ehci->bandwidth[i] += usecs;
++
++	} else {			/* Full speed */
++		s_mask = stream->ps.cs_mask;
++		c_mask = s_mask >> 8;
++
++		/* NOTE: adjustment needed for frame overflow */
++		for (i = uframe; i < EHCI_BANDWIDTH_SIZE;
++				i += stream->ps.bw_uperiod) {
++			for ((j = stream->ps.phase_uf, m = 1 << j); j < 8;
++					(++j, m <<= 1)) {
++				if (s_mask & m)
++					ehci->bandwidth[i+j] += usecs;
++				else if (c_mask & m)
++					ehci->bandwidth[i+j] += c_usecs;
++			}
++		}
++	}
++}
++
+ static inline int
+ itd_slot_ok (
+ 	struct ehci_hcd		*ehci,
+-	u32			mod,
+-	u32			uframe,
+-	u8			usecs,
+-	u32			period
++	struct ehci_iso_stream	*stream,
++	unsigned		uframe
+ )
+ {
+-	uframe %= period;
+-	do {
+-		/* can't commit more than uframe_periodic_max usec */
+-		if (periodic_usecs (ehci, uframe >> 3, uframe & 0x7)
+-				> (ehci->uframe_periodic_max - usecs))
+-			return 0;
++	unsigned		usecs;
++
++	/* convert "usecs we need" to "max already claimed" */
++	usecs = ehci->uframe_periodic_max - stream->ps.usecs;
+ 
+-		/* we know urb->interval is 2^N uframes */
+-		uframe += period;
+-	} while (uframe < mod);
++	for (uframe &= stream->ps.bw_uperiod - 1; uframe < EHCI_BANDWIDTH_SIZE;
++			uframe += stream->ps.bw_uperiod) {
++		if (ehci->bandwidth[uframe] > usecs)
++			return 0;
++	}
+ 	return 1;
+ }
+ 
+ static inline int
+ sitd_slot_ok (
+ 	struct ehci_hcd		*ehci,
+-	u32			mod,
+ 	struct ehci_iso_stream	*stream,
+-	u32			uframe,
+-	struct ehci_iso_sched	*sched,
+-	u32			period_uframes
++	unsigned		uframe,
++	struct ehci_iso_sched	*sched
+ )
+ {
+-	u32			mask, tmp;
+-	u32			frame, uf;
++	unsigned		mask, tmp;
++	unsigned		frame, uf;
+ 
+-	mask = stream->raw_mask << (uframe & 7);
++	mask = stream->ps.cs_mask << (uframe & 7);
+ 
+ 	/* for OUT, don't wrap SSPLIT into H-microframe 7 */
+-	if (((stream->raw_mask & 0xff) << (uframe & 7)) >= (1 << 7))
++	if (((stream->ps.cs_mask & 0xff) << (uframe & 7)) >= (1 << 7))
+ 		return 0;
+ 
+ 	/* for IN, don't wrap CSPLIT into the next frame */
+@@ -1295,7 +1309,7 @@ sitd_slot_ok (
+ 		return 0;
+ 
+ 	/* check bandwidth */
+-	uframe %= period_uframes;
++	uframe &= stream->ps.bw_uperiod - 1;
+ 	frame = uframe >> 3;
+ 
+ #ifdef CONFIG_USB_EHCI_TT_NEWSCHED
+@@ -1303,55 +1317,49 @@ sitd_slot_ok (
+ 	 * tt_available scheduling guarantees 10+% for control/bulk.
+ 	 */
+ 	uf = uframe & 7;
+-	if (!tt_available(ehci, period_uframes >> 3,
++	if (!tt_available(ehci, stream->ps.bw_period,
+ 			stream->ps.udev, frame, uf, stream->ps.tt_usecs))
+ 		return 0;
+ #else
+ 	/* tt must be idle for start(s), any gap, and csplit.
+ 	 * assume scheduling slop leaves 10+% for control/bulk.
+ 	 */
+-	if (!tt_no_collision(ehci, period_uframes >> 3,
++	if (!tt_no_collision(ehci, stream->ps.bw_period,
+ 			stream->ps.udev, frame, mask))
+ 		return 0;
+ #endif
+ 
+-	/* this multi-pass logic is simple, but performance may
+-	 * suffer when the schedule data isn't cached.
+-	 */
+ 	do {
+-		u32		max_used;
+-
+-		frame = uframe >> 3;
+-		uf = uframe & 7;
++		unsigned	max_used;
++		unsigned	i;
+ 
+ 		/* check starts (OUT uses more than one) */
++		uf = uframe;
+ 		max_used = ehci->uframe_periodic_max - stream->ps.usecs;
+-		for (tmp = stream->raw_mask & 0xff; tmp; tmp >>= 1, uf++) {
+-			if (periodic_usecs (ehci, frame, uf) > max_used)
++		for (tmp = stream->ps.cs_mask & 0xff; tmp; tmp >>= 1, uf++) {
++			if (ehci->bandwidth[uf] > max_used)
+ 				return 0;
+ 		}
+ 
+ 		/* for IN, check CSPLIT */
+ 		if (stream->ps.c_usecs) {
+-			uf = uframe & 7;
+ 			max_used = ehci->uframe_periodic_max -
+ 					stream->ps.c_usecs;
+-			do {
+-				tmp = 1 << uf;
+-				tmp <<= 8;
+-				if ((stream->raw_mask & tmp) == 0)
++			uf = uframe & ~7;
++			tmp = 1 << (2+8);
++			for (i = (uframe & 7) + 2; i < 8; (++i, tmp <<= 1)) {
++				if ((stream->ps.cs_mask & tmp) == 0)
+ 					continue;
+-				if (periodic_usecs (ehci, frame, uf)
+-						> max_used)
++				if (ehci->bandwidth[uf+i] > max_used)
+ 					return 0;
+-			} while (++uf < 8);
++			}
+ 		}
+ 
+-		/* we know urb->interval is 2^N uframes */
+-		uframe += period_uframes;
+-	} while (uframe < mod);
++		uframe += stream->ps.bw_uperiod;
++	} while (uframe < EHCI_BANDWIDTH_SIZE);
+ 
+-	stream->splits = cpu_to_hc32(ehci, stream->raw_mask << (uframe & 7));
++	stream->ps.cs_mask <<= uframe & 7;
++	stream->splits = cpu_to_hc32(ehci, stream->ps.cs_mask);
+ 	return 1;
+ }
+ 
+@@ -1382,12 +1390,10 @@ iso_stream_schedule (
+ 	struct ehci_iso_sched	*sched = urb->hcpriv;
+ 	bool			empty = list_empty(&stream->td_list);
+ 
+-	period = urb->interval;
++	period = stream->uperiod;
+ 	span = sched->span;
+-	if (!stream->highspeed) {
+-		period <<= 3;
++	if (!stream->highspeed)
+ 		span <<= 3;
+-	}
+ 
+ 	now = ehci_read_frame_index(ehci) & (mod - 1);
+ 
+@@ -1404,47 +1410,55 @@ iso_stream_schedule (
+ 	base = ehci->last_iso_frame << 3;
+ 	next = (next - base) & (mod - 1);
+ 
+-	/*
+-	 * Need to schedule; when's the next (u)frame we could start?
+-	 * This is bigger than ehci->i_thresh allows; scheduling itself
+-	 * isn't free, the delay should handle reasonably slow cpus.  It
+-	 * can also help high bandwidth if the dma and irq loads don't
+-	 * jump until after the queue is primed.
+-	 */
++	/* Start a new isochronous stream? */
+ 	if (unlikely(empty && !hcd_periodic_completion_in_progress(
+ 			ehci_to_hcd(ehci), urb->ep))) {
+-		int done = 0;
+ 
+-		start = (now & ~0x07) + SCHEDULING_DELAY;
++		/* Schedule the endpoint */
++		if (stream->ps.phase == NO_FRAME) {
++			int		done = 0;
+ 
+-		/* find a uframe slot with enough bandwidth.
+-		 * Early uframes are more precious because full-speed
+-		 * iso IN transfers can't use late uframes,
+-		 * and therefore they should be allocated last.
+-		 */
+-		next = start;
+-		start += period;
+-		do {
+-			start--;
+-			/* check schedule: enough space? */
+-			if (stream->highspeed) {
+-				if (itd_slot_ok(ehci, mod, start,
+-						stream->ps.usecs, period))
+-					done = 1;
+-			} else {
+-				if ((start % 8) >= 6)
+-					continue;
+-				if (sitd_slot_ok(ehci, mod, stream,
+-						start, sched, period))
+-					done = 1;
++			start = (now & ~0x07) + SCHEDULING_DELAY;
++
++			/* find a uframe slot with enough bandwidth.
++			 * Early uframes are more precious because full-speed
++			 * iso IN transfers can't use late uframes,
++			 * and therefore they should be allocated last.
++			 */
++			next = start;
++			start += period;
++			do {
++				start--;
++				/* check schedule: enough space? */
++				if (stream->highspeed) {
++					if (itd_slot_ok(ehci, stream, start))
++						done = 1;
++				} else {
++					if ((start % 8) >= 6)
++						continue;
++					if (sitd_slot_ok(ehci, stream, start,
++							sched))
++						done = 1;
++				}
++			} while (start > next && !done);
++
++			/* no room in the schedule */
++			if (!done) {
++				ehci_dbg(ehci, "iso sched full %p", urb);
++				status = -ENOSPC;
++				goto fail;
+ 			}
+-		} while (start > next && !done);
++			stream->ps.phase = (start >> 3) &
++					(stream->ps.period - 1);
++			stream->ps.bw_phase = stream->ps.phase &
++					(stream->ps.bw_period - 1);
++			stream->ps.phase_uf = start & 7;
++			reserve_release_iso_bandwidth(ehci, stream, 1);
++		}
+ 
+-		/* no room in the schedule */
+-		if (!done) {
+-			ehci_dbg(ehci, "iso sched full %p", urb);
+-			status = -ENOSPC;
+-			goto fail;
++		/* New stream is already scheduled; use the upcoming slot */
++		else {
++			start = (stream->ps.phase << 3) + stream->ps.phase_uf;
+ 		}
+ 
+ 		start = (start - base) & (mod - 1);
+@@ -1452,7 +1466,7 @@ iso_stream_schedule (
+ 	}
+ 
+ 	/*
+-	 * Typical case: reuse current schedule, stream is still active.
++	 * Typical case: reuse current schedule, stream may still be active.
+ 	 * Hopefully there are no gaps from the host falling behind
+ 	 * (irq delays etc).  If there are, the behavior depends on
+ 	 * whether URB_ISO_ASAP is set.
+diff --git a/drivers/usb/host/ehci-sysfs.c b/drivers/usb/host/ehci-sysfs.c
+index 14ced00ba220..f6459dfb6f54 100644
+--- a/drivers/usb/host/ehci-sysfs.c
++++ b/drivers/usb/host/ehci-sysfs.c
+@@ -97,8 +97,7 @@ static ssize_t store_uframe_periodic_max(struct device *dev,
+ {
+ 	struct ehci_hcd		*ehci;
+ 	unsigned		uframe_periodic_max;
+-	unsigned		frame, uframe;
+-	unsigned short		allocated_max;
++	unsigned		uframe;
+ 	unsigned long		flags;
+ 	ssize_t			ret;
+ 
+@@ -122,16 +121,14 @@ static ssize_t store_uframe_periodic_max(struct device *dev,
+ 
+ 	/*
+ 	 * for request to decrease max periodic bandwidth, we have to check
+-	 * every microframe in the schedule to see whether the decrease is
+-	 * possible.
++	 * to see whether the decrease is possible.
+ 	 */
+ 	if (uframe_periodic_max < ehci->uframe_periodic_max) {
+-		allocated_max = 0;
++		u8		allocated_max = 0;
+ 
+-		for (frame = 0; frame < ehci->periodic_size; ++frame)
+-			for (uframe = 0; uframe < 7; ++uframe)
+-				allocated_max = max(allocated_max,
+-						    periodic_usecs (ehci, frame, uframe));
++		for (uframe = 0; uframe < EHCI_BANDWIDTH_SIZE; ++uframe)
++			allocated_max = max(allocated_max,
++					ehci->bandwidth[uframe]);
+ 
+ 		if (allocated_max > uframe_periodic_max) {
+ 			ehci_info(ehci,
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index e2b64c40d94f..12504fbded56 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -62,10 +62,16 @@ struct ehci_per_sched {
+ 	struct usb_device	*udev;		/* access to the TT */
+ 	struct usb_host_endpoint *ep;
+ 	u16			tt_usecs;	/* time on the FS/LS bus */
++	u16			cs_mask;	/* C-mask and S-mask bytes */
+ 	u16			period;		/* actual period in frames */
+ 	u16			phase;		/* actual phase, frame part */
++	u8			bw_phase;	/* same, for bandwidth
++						   reservation */
+ 	u8			phase_uf;	/* uframe part of the phase */
+ 	u8			usecs, c_usecs;	/* times on the HS bus */
++	u8			bw_uperiod;	/* period in microframes, for
++						   bandwidth reservation */
++	u8			bw_period;	/* same, in frames */
+ };
+ #define NO_FRAME	29999			/* frame not assigned yet */
+ 
+@@ -245,6 +251,12 @@ struct ehci_hcd {			/* one per controller */
+ 	struct dentry		*debug_dir;
+ #endif
+ 
++	/* bandwidth usage */
++#define EHCI_BANDWIDTH_SIZE	64
++#define EHCI_BANDWIDTH_FRAMES	(EHCI_BANDWIDTH_SIZE >> 3)
++	u8			bandwidth[EHCI_BANDWIDTH_SIZE];
++						/* us allocated per uframe */
++
+ 	/* platform-specific data -- must come last */
+ 	unsigned long		priv[0] __aligned(sizeof(s64));
+ };
+@@ -469,7 +481,6 @@ struct ehci_iso_stream {
+ 	 */
+ 	u16			uperiod;	/* period in uframes */
+ 	u16			maxp;
+-	u16			raw_mask;
+ 	unsigned		bandwidth;
+ 
+ 	/* This is used to initialize iTD's hw_bufp fields */

commit ffa0248e643175cea3887c7058916af53104d8e5
+Author: Alan Stern 
+Date:   Fri Oct 11 11:29:03 2013 -0400
+
+    USB: EHCI: create a "periodic schedule info" struct
+    
+    This patch begins the process of unifying the scheduling parameters
+    that ehci-hcd uses for interrupt and isochronous transfers.  It
+    creates an ehci_per_sched structure, which will be stored in both
+    ehci_qh and ehci_iso_stream structures, and will contain the common
+    scheduling information needed for both.
+    
+    Initially we merely create the new structure and move some existing
+    fields into it.  Later patches will add more fields and utilize these
+    structures in improved scheduling algorithms.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
+index da7d7fcccb8a..09e5bc8e2b98 100644
+--- a/drivers/usb/host/ehci-dbg.c
++++ b/drivers/usb/host/ehci-dbg.c
+@@ -571,7 +571,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
+ 			case Q_TYPE_QH:
+ 				hw = p.qh->hw;
+ 				temp = scnprintf (next, size, " qh%d-%04x/%p",
+-						p.qh->period,
++						p.qh->ps.period,
+ 						hc32_to_cpup(ehci,
+ 							&hw->hw_info2)
+ 							/* uframe masks */
+@@ -618,7 +618,8 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
+ 						speed_char (scratch),
+ 						scratch & 0x007f,
+ 						(scratch >> 8) & 0x000f, type,
+-						p.qh->usecs, p.qh->c_usecs,
++						p.qh->ps.usecs,
++						p.qh->ps.c_usecs,
+ 						temp,
+ 						0x7ff & (scratch >> 16));
+ 
+@@ -645,7 +646,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
+ 			case Q_TYPE_SITD:
+ 				temp = scnprintf (next, size,
+ 					" sitd%d-%04x/%p",
+-					p.sitd->stream->interval,
++					p.sitd->stream->ps.period,
+ 					hc32_to_cpup(ehci, &p.sitd->hw_uframe)
+ 						& 0x0000ffff,
+ 					p.sitd);
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 652018f93632..b2e4e4b3cfae 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1029,7 +1029,7 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 			 * while the QH is active.  Unlink it now;
+ 			 * re-linking will call qh_refresh().
+ 			 */
+-			usb_settoggle(qh->dev, epnum, is_out, 0);
++			usb_settoggle(qh->ps.udev, epnum, is_out, 0);
+ 			qh->exception = 1;
+ 			if (eptype == USB_ENDPOINT_XFER_BULK)
+ 				start_unlink_async(ehci, qh);
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index e321804c3475..9bfaa21707bd 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -105,9 +105,9 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
+ 
+ 		is_out = qh->is_out;
+ 		epnum = (hc32_to_cpup(ehci, &hw->hw_info1) >> 8) & 0x0f;
+-		if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) {
++		if (unlikely(!usb_gettoggle(qh->ps.udev, epnum, is_out))) {
+ 			hw->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
+-			usb_settoggle (qh->dev, epnum, is_out, 1);
++			usb_settoggle(qh->ps.udev, epnum, is_out, 1);
+ 		}
+ 	}
+ 
+@@ -797,26 +797,25 @@ qh_make (
+ 	 * For control/bulk requests, the HC or TT handles these.
+ 	 */
+ 	if (type == PIPE_INTERRUPT) {
+-		qh->usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH,
++		qh->ps.usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH,
+ 				is_input, 0,
+ 				hb_mult(maxp) * max_packet(maxp)));
+-		qh->start = NO_FRAME;
++		qh->ps.phase = NO_FRAME;
+ 
+ 		if (urb->dev->speed == USB_SPEED_HIGH) {
+-			qh->c_usecs = 0;
++			qh->ps.c_usecs = 0;
+ 			qh->gap_uf = 0;
+ 
+-			qh->period = urb->interval >> 3;
+-			if (qh->period == 0 && urb->interval != 1) {
++			if (urb->interval > 1 && urb->interval < 8) {
+ 				/* NOTE interval 2 or 4 uframes could work.
+ 				 * But interval 1 scheduling is simpler, and
+ 				 * includes high bandwidth.
+ 				 */
+ 				urb->interval = 1;
+-			} else if (qh->period > ehci->periodic_size) {
+-				qh->period = ehci->periodic_size;
+-				urb->interval = qh->period << 3;
++			} else if (urb->interval > ehci->periodic_size << 3) {
++				urb->interval = ehci->periodic_size << 3;
+ 			}
++			qh->ps.period = urb->interval >> 3;
+ 		} else {
+ 			int		think_time;
+ 
+@@ -826,27 +825,26 @@ qh_make (
+ 
+ 			/* FIXME this just approximates SPLIT/CSPLIT times */
+ 			if (is_input) {		// SPLIT, gap, CSPLIT+DATA
+-				qh->c_usecs = qh->usecs + HS_USECS (0);
+-				qh->usecs = HS_USECS (1);
++				qh->ps.c_usecs = qh->ps.usecs + HS_USECS(0);
++				qh->ps.usecs = HS_USECS(1);
+ 			} else {		// SPLIT+DATA, gap, CSPLIT
+-				qh->usecs += HS_USECS (1);
+-				qh->c_usecs = HS_USECS (0);
++				qh->ps.usecs += HS_USECS(1);
++				qh->ps.c_usecs = HS_USECS(0);
+ 			}
+ 
+ 			think_time = tt ? tt->think_time : 0;
+-			qh->tt_usecs = NS_TO_US (think_time +
++			qh->ps.tt_usecs = NS_TO_US(think_time +
+ 					usb_calc_bus_time (urb->dev->speed,
+ 					is_input, 0, max_packet (maxp)));
+-			qh->period = urb->interval;
+-			if (qh->period > ehci->periodic_size) {
+-				qh->period = ehci->periodic_size;
+-				urb->interval = qh->period;
+-			}
++			if (urb->interval > ehci->periodic_size)
++				urb->interval = ehci->periodic_size;
++			qh->ps.period = urb->interval;
+ 		}
+ 	}
+ 
+ 	/* support for tt scheduling, and access to toggles */
+-	qh->dev = urb->dev;
++	qh->ps.udev = urb->dev;
++	qh->ps.ep = urb->ep;
+ 
+ 	/* using TT? */
+ 	switch (urb->dev->speed) {
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 37e97a70894a..1fafcda0ae81 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -121,11 +121,11 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
+ 			hw = q->qh->hw;
+ 			/* is it in the S-mask? */
+ 			if (hw->hw_info2 & cpu_to_hc32(ehci, 1 << uframe))
+-				usecs += q->qh->usecs;
++				usecs += q->qh->ps.usecs;
+ 			/* ... or C-mask? */
+ 			if (hw->hw_info2 & cpu_to_hc32(ehci,
+ 					1 << (8 + uframe)))
+-				usecs += q->qh->c_usecs;
++				usecs += q->qh->ps.c_usecs;
+ 			hw_p = &hw->hw_next;
+ 			q = &q->qh->qh_next;
+ 			break;
+@@ -142,7 +142,7 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
+ 			break;
+ 		case Q_TYPE_ITD:
+ 			if (q->itd->hw_transaction[uframe])
+-				usecs += q->itd->stream->usecs;
++				usecs += q->itd->stream->ps.usecs;
+ 			hw_p = &q->itd->hw_next;
+ 			q = &q->itd->itd_next;
+ 			break;
+@@ -152,7 +152,7 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
+ 					1 << uframe)) {
+ 				if (q->sitd->hw_fullspeed_ep &
+ 						cpu_to_hc32(ehci, 1<<31))
+-					usecs += q->sitd->stream->usecs;
++					usecs += q->sitd->stream->ps.usecs;
+ 				else	/* worst case for OUT start-split */
+ 					usecs += HS_USECS_ISO (188);
+ 			}
+@@ -161,7 +161,7 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
+ 			if (q->sitd->hw_uframe &
+ 					cpu_to_hc32(ehci, 1 << (8 + uframe))) {
+ 				/* worst case for IN complete-split */
+-				usecs += q->sitd->stream->c_usecs;
++				usecs += q->sitd->stream->ps.c_usecs;
+ 			}
+ 
+ 			hw_p = &q->sitd->hw_next;
+@@ -258,9 +258,9 @@ periodic_tt_usecs (
+ 			q = &q->itd->itd_next;
+ 			continue;
+ 		case Q_TYPE_QH:
+-			if (same_tt(dev, q->qh->dev)) {
++			if (same_tt(dev, q->qh->ps.udev)) {
+ 				uf = tt_start_uframe(ehci, q->qh->hw->hw_info2);
+-				tt_usecs[uf] += q->qh->tt_usecs;
++				tt_usecs[uf] += q->qh->ps.tt_usecs;
+ 			}
+ 			hw_p = &q->qh->hw->hw_next;
+ 			q = &q->qh->qh_next;
+@@ -268,7 +268,7 @@ periodic_tt_usecs (
+ 		case Q_TYPE_SITD:
+ 			if (same_tt(dev, q->sitd->urb->dev)) {
+ 				uf = tt_start_uframe(ehci, q->sitd->hw_uframe);
+-				tt_usecs[uf] += q->sitd->stream->tt_usecs;
++				tt_usecs[uf] += q->sitd->stream->ps.tt_usecs;
+ 			}
+ 			hw_p = &q->sitd->hw_next;
+ 			q = &q->sitd->sitd_next;
+@@ -391,7 +391,7 @@ static int tt_no_collision (
+ 				continue;
+ 			case Q_TYPE_QH:
+ 				hw = here.qh->hw;
+-				if (same_tt (dev, here.qh->dev)) {
++				if (same_tt(dev, here.qh->ps.udev)) {
+ 					u32		mask;
+ 
+ 					mask = hc32_to_cpu(ehci,
+@@ -471,19 +471,19 @@ static void disable_periodic(struct ehci_hcd *ehci)
+ static void qh_link_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ {
+ 	unsigned	i;
+-	unsigned	period = qh->period;
++	unsigned	period = qh->ps.period;
+ 
+-	dev_dbg (&qh->dev->dev,
++	dev_dbg(&qh->ps.udev->dev,
+ 		"link qh%d-%04x/%p start %d [%d/%d us]\n",
+ 		period, hc32_to_cpup(ehci, &qh->hw->hw_info2)
+ 			& (QH_CMASK | QH_SMASK),
+-		qh, qh->start, qh->usecs, qh->c_usecs);
++		qh, qh->ps.phase, qh->ps.usecs, qh->ps.c_usecs);
+ 
+ 	/* high bandwidth, or otherwise every microframe */
+ 	if (period == 0)
+ 		period = 1;
+ 
+-	for (i = qh->start; i < ehci->periodic_size; i += period) {
++	for (i = qh->ps.phase; i < ehci->periodic_size; i += period) {
+ 		union ehci_shadow	*prev = &ehci->pshadow[i];
+ 		__hc32			*hw_p = &ehci->periodic[i];
+ 		union ehci_shadow	here = *prev;
+@@ -503,7 +503,7 @@ static void qh_link_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		 * enables sharing interior tree nodes
+ 		 */
+ 		while (here.ptr && qh != here.qh) {
+-			if (qh->period > here.qh->period)
++			if (qh->ps.period > here.qh->ps.period)
+ 				break;
+ 			prev = &here.qh->qh_next;
+ 			hw_p = &here.qh->hw->hw_next;
+@@ -523,10 +523,10 @@ static void qh_link_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	qh->xacterrs = 0;
+ 	qh->exception = 0;
+ 
+-	/* update per-qh bandwidth for usbfs */
+-	ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->period
+-		? ((qh->usecs + qh->c_usecs) / qh->period)
+-		: (qh->usecs * 8);
++	/* update per-qh bandwidth for debugfs */
++	ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->ps.period
++		? ((qh->ps.usecs + qh->ps.c_usecs) / qh->ps.period)
++		: (qh->ps.usecs * 8);
+ 
+ 	list_add(&qh->intr_node, &ehci->intr_qh_list);
+ 
+@@ -556,22 +556,21 @@ static void qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	 */
+ 
+ 	/* high bandwidth, or otherwise part of every microframe */
+-	if ((period = qh->period) == 0)
+-		period = 1;
++	period = qh->ps.period ? : 1;
+ 
+-	for (i = qh->start; i < ehci->periodic_size; i += period)
++	for (i = qh->ps.phase; i < ehci->periodic_size; i += period)
+ 		periodic_unlink (ehci, i, qh);
+ 
+-	/* update per-qh bandwidth for usbfs */
+-	ehci_to_hcd(ehci)->self.bandwidth_allocated -= qh->period
+-		? ((qh->usecs + qh->c_usecs) / qh->period)
+-		: (qh->usecs * 8);
++	/* update per-qh bandwidth for debugfs */
++	ehci_to_hcd(ehci)->self.bandwidth_allocated -= qh->ps.period
++		? ((qh->ps.usecs + qh->ps.c_usecs) / qh->ps.period)
++		: (qh->ps.usecs * 8);
+ 
+-	dev_dbg (&qh->dev->dev,
++	dev_dbg(&qh->ps.udev->dev,
+ 		"unlink qh%d-%04x/%p start %d [%d/%d us]\n",
+-		qh->period,
++		qh->ps.period,
+ 		hc32_to_cpup(ehci, &qh->hw->hw_info2) & (QH_CMASK | QH_SMASK),
+-		qh, qh->start, qh->usecs, qh->c_usecs);
++		qh, qh->ps.phase, qh->ps.usecs, qh->ps.c_usecs);
+ 
+ 	/* qh->qh_next still "live" to HC */
+ 	qh->qh_state = QH_STATE_UNLINK;
+@@ -744,26 +743,26 @@ static int check_intr_schedule (
+ 	int		retval = -ENOSPC;
+ 	u8		mask = 0;
+ 
+-	if (qh->c_usecs && uframe >= 6)		/* FSTN territory? */
++	if (qh->ps.c_usecs && uframe >= 6)	/* FSTN territory? */
+ 		goto done;
+ 
+-	if (!check_period (ehci, frame, uframe, qh->period, qh->usecs))
++	if (!check_period(ehci, frame, uframe, qh->ps.period, qh->ps.usecs))
+ 		goto done;
+-	if (!qh->c_usecs) {
++	if (!qh->ps.c_usecs) {
+ 		retval = 0;
+ 		*c_maskp = 0;
+ 		goto done;
+ 	}
+ 
+ #ifdef CONFIG_USB_EHCI_TT_NEWSCHED
+-	if (tt_available (ehci, qh->period, qh->dev, frame, uframe,
+-				qh->tt_usecs)) {
++	if (tt_available(ehci, qh->ps.period, qh->ps.udev, frame, uframe,
++				qh->ps.tt_usecs)) {
+ 		unsigned i;
+ 
+ 		/* TODO : this may need FSTN for SSPLIT in uframe 5. */
+ 		for (i = uframe+2; i < 8 && i <= uframe+4; i++)
+-			if (!check_period (ehci, frame, i,
+-						qh->period, qh->c_usecs))
++			if (!check_period(ehci, frame, i,
++					qh->ps.period, qh->ps.c_usecs))
+ 				goto done;
+ 			else
+ 				mask |= 1 << i;
+@@ -784,12 +783,12 @@ static int check_intr_schedule (
+ 	*c_maskp = cpu_to_hc32(ehci, mask << 8);
+ 
+ 	mask |= 1 << uframe;
+-	if (tt_no_collision (ehci, qh->period, qh->dev, frame, mask)) {
+-		if (!check_period (ehci, frame, uframe + qh->gap_uf + 1,
+-					qh->period, qh->c_usecs))
++	if (tt_no_collision(ehci, qh->ps.period, qh->ps.udev, frame, mask)) {
++		if (!check_period(ehci, frame, uframe + qh->gap_uf + 1,
++				qh->ps.period, qh->ps.c_usecs))
+ 			goto done;
+-		if (!check_period (ehci, frame, uframe + qh->gap_uf,
+-					qh->period, qh->c_usecs))
++		if (!check_period(ehci, frame, uframe + qh->gap_uf,
++				qh->ps.period, qh->ps.c_usecs))
+ 			goto done;
+ 		retval = 0;
+ 	}
+@@ -810,7 +809,7 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	struct ehci_qh_hw	*hw = qh->hw;
+ 
+ 	hw->hw_next = EHCI_LIST_END(ehci);
+-	frame = qh->start;
++	frame = qh->ps.phase;
+ 
+ 	/* reuse the previous schedule slots, if we can */
+ 	if (frame != NO_FRAME) {
+@@ -828,11 +827,11 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	 */
+ 	if (status) {
+ 		/* "normal" case, uframing flexible except with splits */
+-		if (qh->period) {
++		if (qh->ps.period) {
+ 			int		i;
+ 
+-			for (i = qh->period; status && i > 0; --i) {
+-				frame = ++ehci->random_frame % qh->period;
++			for (i = qh->ps.period; status && i > 0; --i) {
++				frame = ++ehci->random_frame % qh->ps.period;
+ 				for (uframe = 0; uframe < 8; uframe++) {
+ 					status = check_intr_schedule (ehci,
+ 							frame, uframe, qh,
+@@ -842,18 +841,18 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 				}
+ 			}
+ 
+-		/* qh->period == 0 means every uframe */
++		/* qh->ps.period == 0 means every uframe */
+ 		} else {
+ 			frame = 0;
+ 			status = check_intr_schedule (ehci, 0, 0, qh, &c_mask);
+ 		}
+ 		if (status)
+ 			goto done;
+-		qh->start = frame;
++		qh->ps.phase = frame;
+ 
+ 		/* reset S-frame and (maybe) C-frame masks */
+ 		hw->hw_info2 &= cpu_to_hc32(ehci, ~(QH_CMASK | QH_SMASK));
+-		hw->hw_info2 |= qh->period
++		hw->hw_info2 |= qh->ps.period
+ 			? cpu_to_hc32(ehci, 1 << uframe)
+ 			: cpu_to_hc32(ehci, QH_SMASK);
+ 		hw->hw_info2 |= c_mask;
+@@ -978,25 +977,24 @@ static void
+ iso_stream_init (
+ 	struct ehci_hcd		*ehci,
+ 	struct ehci_iso_stream	*stream,
+-	struct usb_device	*dev,
+-	int			pipe,
+-	unsigned		interval
++	struct urb		*urb
+ )
+ {
+ 	static const u8 smask_out [] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f };
+ 
++	struct usb_device	*dev = urb->dev;
++	unsigned		interval = urb->interval;
+ 	u32			buf1;
+ 	unsigned		epnum, maxp;
+ 	int			is_input;
+-	long			bandwidth;
+ 
+ 	/*
+ 	 * this might be a "high bandwidth" highspeed endpoint,
+ 	 * as encoded in the ep descriptor's wMaxPacket field
+ 	 */
+-	epnum = usb_pipeendpoint (pipe);
+-	is_input = usb_pipein (pipe) ? USB_DIR_IN : 0;
+-	maxp = usb_maxpacket(dev, pipe, !is_input);
++	epnum = usb_pipeendpoint(urb->pipe);
++	is_input = usb_pipein(urb->pipe) ? USB_DIR_IN : 0;
++	maxp = usb_endpoint_maxp(&urb->ep->desc);
+ 	if (is_input) {
+ 		buf1 = (1 << 11);
+ 	} else {
+@@ -1020,9 +1018,11 @@ iso_stream_init (
+ 		/* usbfs wants to report the average usecs per frame tied up
+ 		 * when transfers on this endpoint are scheduled ...
+ 		 */
+-		stream->usecs = HS_USECS_ISO (maxp);
+-		bandwidth = stream->usecs * 8;
+-		bandwidth /= interval;
++		stream->ps.usecs = HS_USECS_ISO(maxp);
++
++		stream->bandwidth = stream->ps.usecs * 8 / interval;
++		stream->uperiod = interval;
++		stream->ps.period = interval >> 3;
+ 
+ 	} else {
+ 		u32		addr;
+@@ -1036,17 +1036,17 @@ iso_stream_init (
+ 			addr |= dev->tt->hub->devnum << 16;
+ 		addr |= epnum << 8;
+ 		addr |= dev->devnum;
+-		stream->usecs = HS_USECS_ISO (maxp);
++		stream->ps.usecs = HS_USECS_ISO(maxp);
+ 		think_time = dev->tt ? dev->tt->think_time : 0;
+-		stream->tt_usecs = NS_TO_US (think_time + usb_calc_bus_time (
++		stream->ps.tt_usecs = NS_TO_US(think_time + usb_calc_bus_time(
+ 				dev->speed, is_input, 1, maxp));
+ 		hs_transfers = max (1u, (maxp + 187) / 188);
+ 		if (is_input) {
+ 			u32	tmp;
+ 
+ 			addr |= 1 << 31;
+-			stream->c_usecs = stream->usecs;
+-			stream->usecs = HS_USECS_ISO (1);
++			stream->ps.c_usecs = stream->ps.usecs;
++			stream->ps.usecs = HS_USECS_ISO(1);
+ 			stream->raw_mask = 1;
+ 
+ 			/* c-mask as specified in USB 2.0 11.18.4 3.c */
+@@ -1054,18 +1054,20 @@ iso_stream_init (
+ 			stream->raw_mask |= tmp << (8 + 2);
+ 		} else
+ 			stream->raw_mask = smask_out [hs_transfers - 1];
+-		bandwidth = stream->usecs + stream->c_usecs;
+-		bandwidth /= interval;
++
++		stream->bandwidth = (stream->ps.usecs + stream->ps.c_usecs) /
++				interval;
++		stream->uperiod = interval << 3;
++		stream->ps.period = interval;
+ 
+ 		/* stream->splits gets created from raw_mask later */
+ 		stream->address = cpu_to_hc32(ehci, addr);
+ 	}
+-	stream->bandwidth = bandwidth;
+ 
+-	stream->udev = dev;
++	stream->ps.udev = dev;
++	stream->ps.ep = urb->ep;
+ 
+ 	stream->bEndpointAddress = is_input | epnum;
+-	stream->interval = interval;
+ 	stream->maxp = maxp;
+ }
+ 
+@@ -1090,9 +1092,7 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb)
+ 		stream = iso_stream_alloc(GFP_ATOMIC);
+ 		if (likely (stream != NULL)) {
+ 			ep->hcpriv = stream;
+-			stream->ep = ep;
+-			iso_stream_init(ehci, stream, urb->dev, urb->pipe,
+-					urb->interval);
++			iso_stream_init(ehci, stream, urb);
+ 		}
+ 
+ 	/* if dev->ep [epnum] is a QH, hw is set */
+@@ -1137,7 +1137,7 @@ itd_sched_init(
+ 	dma_addr_t	dma = urb->transfer_dma;
+ 
+ 	/* how many uframes are needed for these transfers */
+-	iso_sched->span = urb->number_of_packets * stream->interval;
++	iso_sched->span = urb->number_of_packets * stream->uperiod;
+ 
+ 	/* figure out per-uframe itd fields that we'll need later
+ 	 * when we fit new itds into the schedule.
+@@ -1304,14 +1304,14 @@ sitd_slot_ok (
+ 	 */
+ 	uf = uframe & 7;
+ 	if (!tt_available(ehci, period_uframes >> 3,
+-			stream->udev, frame, uf, stream->tt_usecs))
++			stream->ps.udev, frame, uf, stream->ps.tt_usecs))
+ 		return 0;
+ #else
+ 	/* tt must be idle for start(s), any gap, and csplit.
+ 	 * assume scheduling slop leaves 10+% for control/bulk.
+ 	 */
+ 	if (!tt_no_collision(ehci, period_uframes >> 3,
+-			stream->udev, frame, mask))
++			stream->ps.udev, frame, mask))
+ 		return 0;
+ #endif
+ 
+@@ -1325,16 +1325,17 @@ sitd_slot_ok (
+ 		uf = uframe & 7;
+ 
+ 		/* check starts (OUT uses more than one) */
+-		max_used = ehci->uframe_periodic_max - stream->usecs;
++		max_used = ehci->uframe_periodic_max - stream->ps.usecs;
+ 		for (tmp = stream->raw_mask & 0xff; tmp; tmp >>= 1, uf++) {
+ 			if (periodic_usecs (ehci, frame, uf) > max_used)
+ 				return 0;
+ 		}
+ 
+ 		/* for IN, check CSPLIT */
+-		if (stream->c_usecs) {
++		if (stream->ps.c_usecs) {
+ 			uf = uframe & 7;
+-			max_used = ehci->uframe_periodic_max - stream->c_usecs;
++			max_used = ehci->uframe_periodic_max -
++					stream->ps.c_usecs;
+ 			do {
+ 				tmp = 1 << uf;
+ 				tmp <<= 8;
+@@ -1428,7 +1429,7 @@ iso_stream_schedule (
+ 			/* check schedule: enough space? */
+ 			if (stream->highspeed) {
+ 				if (itd_slot_ok(ehci, mod, start,
+-						stream->usecs, period))
++						stream->ps.usecs, period))
+ 					done = 1;
+ 			} else {
+ 				if ((start % 8) >= 6)
+@@ -1668,7 +1669,7 @@ static void itd_link_urb(
+ 
+ 		itd_patch(ehci, itd, iso_sched, packet, uframe);
+ 
+-		next_uframe += stream->interval;
++		next_uframe += stream->uperiod;
+ 		next_uframe &= mod - 1;
+ 		packet++;
+ 
+@@ -1808,9 +1809,9 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb,
+ 		ehci_dbg (ehci, "can't get iso stream\n");
+ 		return -ENOMEM;
+ 	}
+-	if (unlikely (urb->interval != stream->interval)) {
++	if (unlikely(urb->interval != stream->uperiod)) {
+ 		ehci_dbg (ehci, "can't change iso interval %d --> %d\n",
+-			stream->interval, urb->interval);
++			stream->uperiod, urb->interval);
+ 		goto done;
+ 	}
+ 
+@@ -1875,7 +1876,7 @@ sitd_sched_init(
+ 	dma_addr_t	dma = urb->transfer_dma;
+ 
+ 	/* how many frames are needed for these transfers */
+-	iso_sched->span = urb->number_of_packets * stream->interval;
++	iso_sched->span = urb->number_of_packets * stream->ps.period;
+ 
+ 	/* figure out per-frame sitd fields that we'll need later
+ 	 * when we fit new sitds into the schedule.
+@@ -2069,7 +2070,7 @@ static void sitd_link_urb(
+ 		sitd_link(ehci, (next_uframe >> 3) & (ehci->periodic_size - 1),
+ 				sitd);
+ 
+-		next_uframe += stream->interval << 3;
++		next_uframe += stream->uperiod;
+ 	}
+ 	stream->next_uframe = next_uframe & (mod - 1);
+ 
+@@ -2188,9 +2189,9 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
+ 		ehci_dbg (ehci, "can't get iso stream\n");
+ 		return -ENOMEM;
+ 	}
+-	if (urb->interval != stream->interval) {
++	if (urb->interval != stream->ps.period) {
+ 		ehci_dbg (ehci, "can't change iso interval %d --> %d\n",
+-			stream->interval, urb->interval);
++			stream->ps.period, urb->interval);
+ 		goto done;
+ 	}
+ 
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index b93eb59bb529..e2b64c40d94f 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -54,6 +54,19 @@ struct ehci_stats {
+ 	unsigned long		unlink;
+ };
+ 
++/*
++ * Scheduling and budgeting information for periodic transfers, for both
++ * high-speed devices and full/low-speed devices lying behind a TT.
++ */
++struct ehci_per_sched {
++	struct usb_device	*udev;		/* access to the TT */
++	struct usb_host_endpoint *ep;
++	u16			tt_usecs;	/* time on the FS/LS bus */
++	u16			period;		/* actual period in frames */
++	u16			phase;		/* actual phase, frame part */
++	u8			phase_uf;	/* uframe part of the phase */
++	u8			usecs, c_usecs;	/* times on the HS bus */
++};
+ #define NO_FRAME	29999			/* frame not assigned yet */
+ 
+ /* ehci_hcd->lock guards shared data against other CPUs:
+@@ -387,6 +400,7 @@ struct ehci_qh {
+ 	struct list_head	intr_node;	/* list of intr QHs */
+ 	struct ehci_qtd		*dummy;
+ 	struct list_head	unlink_node;
++	struct ehci_per_sched	ps;		/* scheduling info */
+ 
+ 	unsigned		unlink_cycle;
+ 
+@@ -400,15 +414,8 @@ struct ehci_qh {
+ 	u8			xacterrs;	/* XactErr retry counter */
+ #define	QH_XACTERR_MAX		32		/* XactErr retry limit */
+ 
+-	/* periodic schedule info */
+-	u8			usecs;		/* intr bandwidth */
+ 	u8			gap_uf;		/* uframes split/csplit gap */
+-	u8			c_usecs;	/* ... split completion bw */
+-	u16			tt_usecs;	/* tt downstream bandwidth */
+-	unsigned short		period;		/* polling interval */
+-	unsigned short		start;		/* where polling starts */
+ 
+-	struct usb_device	*dev;		/* access to TT */
+ 	unsigned		is_out:1;	/* bulk or intr OUT */
+ 	unsigned		clearing_tt:1;	/* Clear-TT-Buf in progress */
+ 	unsigned		dequeue_during_giveback:1;
+@@ -451,20 +458,16 @@ struct ehci_iso_stream {
+ 	u8			highspeed;
+ 	struct list_head	td_list;	/* queued itds/sitds */
+ 	struct list_head	free_list;	/* list of unused itds/sitds */
+-	struct usb_device	*udev;
+-	struct usb_host_endpoint *ep;
+ 
+ 	/* output of (re)scheduling */
++	struct ehci_per_sched	ps;		/* scheduling info */
+ 	unsigned		next_uframe;
+ 	__hc32			splits;
+ 
+ 	/* the rest is derived from the endpoint descriptor,
+-	 * trusting urb->interval == f(epdesc->bInterval) and
+ 	 * including the extra info for hw_bufp[0..2]
+ 	 */
+-	u8			usecs, c_usecs;
+-	u16			interval;
+-	u16			tt_usecs;
++	u16			uperiod;	/* period in uframes */
+ 	u16			maxp;
+ 	u16			raw_mask;
+ 	unsigned		bandwidth;

commit 91a99b5e78849db90dc2f5e8dfa034af43bdb760
+Author: Alan Stern 
+Date:   Fri Oct 11 11:28:52 2013 -0400
+
+    USB: EHCI: use consistent NO_FRAME value
+    
+    ehci-hcd is inconsistent in the sentinel values it uses to indicate
+    that no frame number has been assigned for a periodic transfer.  Some
+    places it uses NO_FRAME (defined as 65535), other places it uses -1,
+    and elsewhere it uses 9999.
+    
+    This patch defines a value for NO_FRAME which can fit in a 16-bit
+    signed integer, and changes the code to use it everywhere.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 1fc2befc4fdc..37e97a70894a 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -813,7 +813,7 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	frame = qh->start;
+ 
+ 	/* reuse the previous schedule slots, if we can */
+-	if (frame < qh->period) {
++	if (frame != NO_FRAME) {
+ 		uframe = ffs(hc32_to_cpup(ehci, &hw->hw_info2) & QH_SMASK);
+ 		status = check_intr_schedule (ehci, frame, --uframe,
+ 				qh, &c_mask);
+@@ -969,7 +969,7 @@ iso_stream_alloc (gfp_t mem_flags)
+ 	if (likely (stream != NULL)) {
+ 		INIT_LIST_HEAD(&stream->td_list);
+ 		INIT_LIST_HEAD(&stream->free_list);
+-		stream->next_uframe = -1;
++		stream->next_uframe = NO_FRAME;
+ 	}
+ 	return stream;
+ }
+@@ -1236,7 +1236,7 @@ itd_urb_transaction (
+ 
+ 		memset (itd, 0, sizeof *itd);
+ 		itd->itd_dma = itd_dma;
+-		itd->frame = 9999;		/* an invalid value */
++		itd->frame = NO_FRAME;
+ 		list_add (&itd->itd_list, &sched->td_list);
+ 	}
+ 	spin_unlock_irqrestore (&ehci->lock, flags);
+@@ -1967,7 +1967,7 @@ sitd_urb_transaction (
+ 
+ 		memset (sitd, 0, sizeof *sitd);
+ 		sitd->sitd_dma = sitd_dma;
+-		sitd->frame = 9999;		/* an invalid value */
++		sitd->frame = NO_FRAME;
+ 		list_add (&sitd->sitd_list, &iso_sched->td_list);
+ 	}
+ 
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 2d401927e143..b93eb59bb529 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -54,6 +54,8 @@ struct ehci_stats {
+ 	unsigned long		unlink;
+ };
+ 
++#define NO_FRAME	29999			/* frame not assigned yet */
++
+ /* ehci_hcd->lock guards shared data against other CPUs:
+  *   ehci_hcd:	async, unlink, periodic (and shadow), ...
+  *   usb_host_endpoint: hcpriv
+@@ -405,7 +407,6 @@ struct ehci_qh {
+ 	u16			tt_usecs;	/* tt downstream bandwidth */
+ 	unsigned short		period;		/* polling interval */
+ 	unsigned short		start;		/* where polling starts */
+-#define NO_FRAME ((unsigned short)~0)			/* pick new start */
+ 
+ 	struct usb_device	*dev;		/* access to TT */
+ 	unsigned		is_out:1;	/* bulk or intr OUT */
+@@ -454,7 +455,7 @@ struct ehci_iso_stream {
+ 	struct usb_host_endpoint *ep;
+ 
+ 	/* output of (re)scheduling */
+-	int			next_uframe;
++	unsigned		next_uframe;
+ 	__hc32			splits;
+ 
+ 	/* the rest is derived from the endpoint descriptor,

commit 27c4a31d6739095d613c6e72fb44867bc28c699f
+Author: Alan Stern 
+Date:   Fri Oct 11 11:28:44 2013 -0400
+
+    USB: EHCI: change toggle only upon successful reset
+    
+    ehci-hcd uses a value of 0 in an endpoint's toggle flag to indicate
+    that the endpoint has been reset (and therefore the Data Toggle bit
+    needs to be cleared in the endpoint's QH overlay region).
+    
+    The toggle flag should be set to 0 only when ehci_endpoint_reset()
+    succeeds.  This patch moves the usb_settoggle() call into the
+    appropriate branch of the "if" statement.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 3e3ca839e6ce..652018f93632 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1022,7 +1022,6 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 	 * the toggle bit in the QH.
+ 	 */
+ 	if (qh) {
+-		usb_settoggle(qh->dev, epnum, is_out, 0);
+ 		if (!list_empty(&qh->qtd_list)) {
+ 			WARN_ONCE(1, "clear_halt for a busy endpoint\n");
+ 		} else {
+@@ -1030,6 +1029,7 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 			 * while the QH is active.  Unlink it now;
+ 			 * re-linking will call qh_refresh().
+ 			 */
++			usb_settoggle(qh->dev, epnum, is_out, 0);
+ 			qh->exception = 1;
+ 			if (eptype == USB_ENDPOINT_XFER_BULK)
+ 				start_unlink_async(ehci, qh);

commit 8c05dc598e5bc0eb33791de23157cf1e47cb580e
+Author: Alan Stern 
+Date:   Fri Oct 11 11:28:31 2013 -0400
+
+    USB: EHCI: No SSPLIT allowed in uframe 7
+    
+    The scheduling code in ehci-hcd contains an error.  For full-speed
+    isochronous-OUT transfers, the EHCI spec forbids scheduling
+    Start-Split transactions in H-microframe 7, but the driver allows it
+    anyway.  This patch adds a check to prevent it.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 4b0903c6c616..1fc2befc4fdc 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1286,6 +1286,10 @@ sitd_slot_ok (
+ 
+ 	mask = stream->raw_mask << (uframe & 7);
+ 
++	/* for OUT, don't wrap SSPLIT into H-microframe 7 */
++	if (((stream->raw_mask & 0xff) << (uframe & 7)) >= (1 << 7))
++		return 0;
++
+ 	/* for IN, don't wrap CSPLIT into the next frame */
+ 	if (mask & ~0xffff)
+ 		return 0;

commit 2b90f01b219e390e1f1bf68dd7a2333efb3e3eff
+Author: Alan Stern 
+Date:   Fri Oct 11 11:28:21 2013 -0400
+
+    USB: EHCI: compute full-speed bandwidth usage correctly
+    
+    Although the bandwidth statistics maintained by ehci-hcd show up only
+    in the /sys/kernel/debug/usb/devices file, they ought to be calculated
+    correctly.  The calculation for full-speed isochronous endpoints is
+    wrong; it mistakenly yields bytes per microframe instead of bytes per
+    frame.  The "interval" value, which is in frames, should not be
+    converted to microframes.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 34b5945fafa5..4b0903c6c616 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1055,7 +1055,7 @@ iso_stream_init (
+ 		} else
+ 			stream->raw_mask = smask_out [hs_transfers - 1];
+ 		bandwidth = stream->usecs + stream->c_usecs;
+-		bandwidth /= interval << 3;
++		bandwidth /= interval;
+ 
+ 		/* stream->splits gets created from raw_mask later */
+ 		stream->address = cpu_to_hc32(ehci, addr);

commit e24371a6be9c5c00b56607bd425cc409cba75d88
+Author: Alan Stern 
+Date:   Fri Oct 11 11:28:12 2013 -0400
+
+    USB: EHCI: check the right uframes for CSPLIT
+    
+    The check_intr_schedule() routine in ehci-hcd looks at the wrong
+    microframes when checking to see if a full-speed or low-speed
+    interrupt endpoint will fit in the periodic schedule.  If the
+    Start-Split transaction is scheduled for microframe N then the
+    Complete-Split transactions get scheduled for microframes N+2, N+3, and
+    N+4.  However the code considers N+1, N+2, and N+3 instead.
+    
+    This patch fixes the limits on the "for" loop and also improves the
+    use of whitespace.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index dcbaad94d607..34b5945fafa5 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -761,7 +761,7 @@ static int check_intr_schedule (
+ 		unsigned i;
+ 
+ 		/* TODO : this may need FSTN for SSPLIT in uframe 5. */
+-		for (i=uframe+1; i<8 && iperiod, qh->c_usecs))
+ 				goto done;

commit 63fb3a280061c5a1d9190015e5a074213f9d23c0
+Author: Alan Stern 
+Date:   Fri Oct 11 11:28:02 2013 -0400
+
+    USB: NS_TO_US should round up
+    
+    Host controller drivers use the NS_TO_US macro to convert transaction
+    times, which are computed in nanoseconds, to microseconds for
+    scheduling.  Periodic scheduling requires worst-case estimates, but
+    the macro does its conversion using round-to-nearest.  This patch
+    changes it to use round-up, giving a correct worst-case value.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
+index fc64b6825f5e..dbe3cd19ffd8 100644
+--- a/include/linux/usb/hcd.h
++++ b/include/linux/usb/hcd.h
+@@ -564,9 +564,8 @@ extern void usb_ep0_reinit(struct usb_device *);
+ 		 * of (7/6 * 8 * bytecount) = 9.33 * bytecount */
+ 		/* bytecount = data payload byte count */
+ 
+-#define NS_TO_US(ns)	((ns + 500L) / 1000L)
+-			/* convert & round nanoseconds to microseconds */
+-
++#define NS_TO_US(ns)	DIV_ROUND_UP(ns, 1000L)
++			/* convert nanoseconds to microseconds, rounding up */
+ 
+ /*
+  * Full/low speed bandwidth allocation constants/support.

commit 976b6c064a957445eb0573b270f2d0282630e9b9
+Author: Alan Stern 
+Date:   Tue Sep 24 15:51:58 2013 -0400
+
+    ALSA: improve buffer size computations for USB PCM audio
+    
+    This patch changes the way URBs are allocated and their sizes are
+    determined for PCM playback in the snd-usb-audio driver.  Currently
+    the driver allocates too few URBs for endpoints that don't use
+    implicit sync, making underruns more likely to occur.  This may be a
+    holdover from before I/O delays could be measured accurately; in any
+    case, it is no longer necessary.
+    
+    The patch allocates as many URBs as possible, subject to four
+    limitations:
+    
+            The total number of URBs for the endpoint is not allowed to
+            exceed MAX_URBS (which the patch increases from 8 to 12).
+    
+            The total number of packets per URB is not allowed to exceed
+            MAX_PACKS (or MAX_PACKS_HS for high-speed devices), which is
+            decreased from 20 to 6.
+    
+            The total duration of queued data is not allowed to exceed
+            MAX_QUEUE, which is decreased from 24 ms to 18 ms.
+    
+            The total number of ALSA frames in the output queue is not
+            allowed to exceed the ALSA buffer size.
+    
+    The last requirement is the hardest to implement.  Currently the
+    number of URBs needed to fill a buffer cannot be determined in
+    advance, because a buffer contains a fixed number of frames whereas
+    the number of frames in an URB varies to match shifts in the device's
+    clock rate.  To solve this problem, the patch changes the logic for
+    deciding how many packets an URB should contain.  Rather than using as
+    many as possible without exceeding an ALSA period boundary, now the
+    driver uses only as many packets as needed to transfer a predetermined
+    number of frames.  As a result, unless the device's clock has an
+    exceedingly variable rate, the number of URBs making up each period
+    (and hence each buffer) will remain constant.
+    
+    The overall effect of the patch is that playback works better in
+    low-latency settings.  The user can still specify values for
+    frames/period and periods/buffer that exceed the capabilities of the
+    hardware, of course.  But for values that are within those
+    capabilities, the performance will be improved.  For example, testing
+    shows that a high-speed device can handle 32 frames/period and 3
+    periods/buffer at 48 KHz, whereas the current driver starts to get
+    glitchy at 64 frames/period and 2 periods/buffer.
+    
+    A side effect of these changes is that the "nrpacks" module parameter
+    is no longer used.  The patch removes it.
+    
+    Signed-off-by: Alan Stern 
+    CC: Clemens Ladisch 
+    Tested-by: Daniel Mack 
+    Tested-by: Eldad Zack 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/usb/card.c b/sound/usb/card.c
+index 64952e2d3ed1..d1f54dfe41d5 100644
+--- a/sound/usb/card.c
++++ b/sound/usb/card.c
+@@ -79,7 +79,6 @@ static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card *
+ /* Vendor/product IDs for this card */
+ static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
+ static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
+-static int nrpacks = 8;		/* max. number of packets per urb */
+ static int device_setup[SNDRV_CARDS]; /* device parameter for this card */
+ static bool ignore_ctl_error;
+ static bool autoclock = true;
+@@ -94,8 +93,6 @@ module_param_array(vid, int, NULL, 0444);
+ MODULE_PARM_DESC(vid, "Vendor ID for the USB audio device.");
+ module_param_array(pid, int, NULL, 0444);
+ MODULE_PARM_DESC(pid, "Product ID for the USB audio device.");
+-module_param(nrpacks, int, 0644);
+-MODULE_PARM_DESC(nrpacks, "Max. number of packets per URB.");
+ module_param_array(device_setup, int, NULL, 0444);
+ MODULE_PARM_DESC(device_setup, "Specific device setup (if needed).");
+ module_param(ignore_ctl_error, bool, 0444);
+@@ -374,7 +371,6 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
+ 	chip->dev = dev;
+ 	chip->card = card;
+ 	chip->setup = device_setup[idx];
+-	chip->nrpacks = nrpacks;
+ 	chip->autoclock = autoclock;
+ 	chip->probing = 1;
+ 
+@@ -756,10 +752,6 @@ static struct usb_driver usb_audio_driver = {
+ 
+ static int __init snd_usb_audio_init(void)
+ {
+-	if (nrpacks < 1 || nrpacks > MAX_PACKS) {
+-		printk(KERN_WARNING "invalid nrpacks value.\n");
+-		return -EINVAL;
+-	}
+ 	return usb_register(&usb_audio_driver);
+ }
+ 
+diff --git a/sound/usb/card.h b/sound/usb/card.h
+index 5ecacaa90b53..ca98a9b915c9 100644
+--- a/sound/usb/card.h
++++ b/sound/usb/card.h
+@@ -2,11 +2,11 @@
+ #define __USBAUDIO_CARD_H
+ 
+ #define MAX_NR_RATES	1024
+-#define MAX_PACKS	20
++#define MAX_PACKS	6		/* per URB */
+ #define MAX_PACKS_HS	(MAX_PACKS * 8)	/* in high speed mode */
+-#define MAX_URBS	8
++#define MAX_URBS	12
+ #define SYNC_URBS	4	/* always four urbs for sync */
+-#define MAX_QUEUE	24	/* try not to exceed this queue length, in ms */
++#define MAX_QUEUE	18	/* try not to exceed this queue length, in ms */
+ 
+ struct audioformat {
+ 	struct list_head list;
+@@ -87,6 +87,7 @@ struct snd_usb_endpoint {
+ 	unsigned int phase;		/* phase accumulator */
+ 	unsigned int maxpacksize;	/* max packet size in bytes */
+ 	unsigned int maxframesize;      /* max packet size in frames */
++	unsigned int max_urb_frames;	/* max URB size in frames */
+ 	unsigned int curpacksize;	/* current packet size in bytes (for capture) */
+ 	unsigned int curframesize;      /* current packet size in frames (for capture) */
+ 	unsigned int syncmaxsize;	/* sync endpoint packet size */
+@@ -116,6 +117,8 @@ struct snd_usb_substream {
+ 	unsigned int channels_max;	/* max channels in the all audiofmts */
+ 	unsigned int cur_rate;		/* current rate (for hw_params callback) */
+ 	unsigned int period_bytes;	/* current period bytes (for hw_params callback) */
++	unsigned int period_frames;	/* current frames per period */
++	unsigned int buffer_periods;	/* current periods per buffer */
+ 	unsigned int altset_idx;     /* USB data format: index of alternate setting */
+ 	unsigned int txfr_quirk:1;	/* allow sub-frame alignment */
+ 	unsigned int fmt_type;		/* USB audio format type (1-3) */
+@@ -125,6 +128,7 @@ struct snd_usb_substream {
+ 
+ 	unsigned int hwptr_done;	/* processed byte position in the buffer */
+ 	unsigned int transfer_done;		/* processed frames since last period update */
++	unsigned int frame_limit;	/* limits number of packets in URB */
+ 
+ 	/* data and sync endpoints for this stream */
+ 	unsigned int ep_num;		/* the endpoint number */
+diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
+index 93e970f2b3c0..21dc6422d747 100644
+--- a/sound/usb/endpoint.c
++++ b/sound/usb/endpoint.c
+@@ -574,11 +574,14 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
+ 			      snd_pcm_format_t pcm_format,
+ 			      unsigned int channels,
+ 			      unsigned int period_bytes,
++			      unsigned int frames_per_period,
++			      unsigned int periods_per_buffer,
+ 			      struct audioformat *fmt,
+ 			      struct snd_usb_endpoint *sync_ep)
+ {
+-	unsigned int maxsize, i, urb_packs, total_packs, packs_per_ms;
+-	int is_playback = usb_pipeout(ep->pipe);
++	unsigned int maxsize, minsize, packs_per_ms, max_packs_per_urb;
++	unsigned int max_packs_per_period, urbs_per_period, urb_packs;
++	unsigned int max_urbs, i;
+ 	int frame_bits = snd_pcm_format_physical_width(pcm_format) * channels;
+ 
+ 	if (pcm_format == SNDRV_PCM_FORMAT_DSD_U16_LE && fmt->dsd_dop) {
+@@ -611,58 +614,67 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
+ 	else
+ 		ep->curpacksize = maxsize;
+ 
+-	if (snd_usb_get_speed(ep->chip->dev) != USB_SPEED_FULL)
++	if (snd_usb_get_speed(ep->chip->dev) != USB_SPEED_FULL) {
+ 		packs_per_ms = 8 >> ep->datainterval;
+-	else
+-		packs_per_ms = 1;
+-
+-	if (is_playback && !snd_usb_endpoint_implicit_feedback_sink(ep)) {
+-		urb_packs = max(ep->chip->nrpacks, 1);
+-		urb_packs = min(urb_packs, (unsigned int) MAX_PACKS);
++		max_packs_per_urb = MAX_PACKS_HS;
+ 	} else {
+-		urb_packs = 1;
++		packs_per_ms = 1;
++		max_packs_per_urb = MAX_PACKS;
+ 	}
++	if (sync_ep && !snd_usb_endpoint_implicit_feedback_sink(ep))
++		max_packs_per_urb = min(max_packs_per_urb,
++					1U << sync_ep->syncinterval);
++	max_packs_per_urb = max(1u, max_packs_per_urb >> ep->datainterval);
+ 
+-	urb_packs *= packs_per_ms;
++	/*
++	 * Capture endpoints need to use small URBs because there's no way
++	 * to tell in advance where the next period will end, and we don't
++	 * want the next URB to complete much after the period ends.
++	 *
++	 * Playback endpoints with implicit sync much use the same parameters
++	 * as their corresponding capture endpoint.
++	 */
++	if (usb_pipein(ep->pipe) ||
++			snd_usb_endpoint_implicit_feedback_sink(ep)) {
+ 
+-	if (sync_ep && !snd_usb_endpoint_implicit_feedback_sink(ep))
+-		urb_packs = min(urb_packs, 1U << sync_ep->syncinterval);
++		/* make capture URBs <= 1 ms and smaller than a period */
++		urb_packs = min(max_packs_per_urb, packs_per_ms);
++		while (urb_packs > 1 && urb_packs * maxsize >= period_bytes)
++			urb_packs >>= 1;
++		ep->nurbs = MAX_URBS;
+ 
+-	/* decide how many packets to be used */
+-	if (is_playback && !snd_usb_endpoint_implicit_feedback_sink(ep)) {
+-		unsigned int minsize, maxpacks;
++	/*
++	 * Playback endpoints without implicit sync are adjusted so that
++	 * a period fits as evenly as possible in the smallest number of
++	 * URBs.  The total number of URBs is adjusted to the size of the
++	 * ALSA buffer, subject to the MAX_URBS and MAX_QUEUE limits.
++	 */
++	} else {
+ 		/* determine how small a packet can be */
+-		minsize = (ep->freqn >> (16 - ep->datainterval))
+-			  * (frame_bits >> 3);
++		minsize = (ep->freqn >> (16 - ep->datainterval)) *
++				(frame_bits >> 3);
+ 		/* with sync from device, assume it can be 12% lower */
+ 		if (sync_ep)
+ 			minsize -= minsize >> 3;
+ 		minsize = max(minsize, 1u);
+-		total_packs = (period_bytes + minsize - 1) / minsize;
+-		/* we need at least two URBs for queueing */
+-		if (total_packs < 2) {
+-			total_packs = 2;
+-		} else {
+-			/* and we don't want too long a queue either */
+-			maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2);
+-			total_packs = min(total_packs, maxpacks);
+-		}
+-	} else {
+-		while (urb_packs > 1 && urb_packs * maxsize >= period_bytes)
+-			urb_packs >>= 1;
+-		total_packs = MAX_URBS * urb_packs;
+-	}
+ 
+-	ep->nurbs = (total_packs + urb_packs - 1) / urb_packs;
+-	if (ep->nurbs > MAX_URBS) {
+-		/* too much... */
+-		ep->nurbs = MAX_URBS;
+-		total_packs = MAX_URBS * urb_packs;
+-	} else if (ep->nurbs < 2) {
+-		/* too little - we need at least two packets
+-		 * to ensure contiguous playback/capture
+-		 */
+-		ep->nurbs = 2;
++		/* how many packets will contain an entire ALSA period? */
++		max_packs_per_period = DIV_ROUND_UP(period_bytes, minsize);
++
++		/* how many URBs will contain a period? */
++		urbs_per_period = DIV_ROUND_UP(max_packs_per_period,
++				max_packs_per_urb);
++		/* how many packets are needed in each URB? */
++		urb_packs = DIV_ROUND_UP(max_packs_per_period, urbs_per_period);
++
++		/* limit the number of frames in a single URB */
++		ep->max_urb_frames = DIV_ROUND_UP(frames_per_period,
++					urbs_per_period);
++
++		/* try to use enough URBs to contain an entire ALSA buffer */
++		max_urbs = min((unsigned) MAX_URBS,
++				MAX_QUEUE * packs_per_ms / urb_packs);
++		ep->nurbs = min(max_urbs, urbs_per_period * periods_per_buffer);
+ 	}
+ 
+ 	/* allocate and initialize data urbs */
+@@ -670,8 +682,7 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
+ 		struct snd_urb_ctx *u = &ep->urb[i];
+ 		u->index = i;
+ 		u->ep = ep;
+-		u->packets = (i + 1) * total_packs / ep->nurbs
+-			- i * total_packs / ep->nurbs;
++		u->packets = urb_packs;
+ 		u->buffer_size = maxsize * u->packets;
+ 
+ 		if (fmt->fmt_type == UAC_FORMAT_TYPE_II)
+@@ -748,6 +759,8 @@ static int sync_ep_set_params(struct snd_usb_endpoint *ep,
+  * @pcm_format: the audio fomat.
+  * @channels: the number of audio channels.
+  * @period_bytes: the number of bytes in one alsa period.
++ * @period_frames: the number of frames in one alsa period.
++ * @buffer_periods: the number of periods in one alsa buffer.
+  * @rate: the frame rate.
+  * @fmt: the USB audio format information
+  * @sync_ep: the sync endpoint to use, if any
+@@ -760,6 +773,8 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
+ 				snd_pcm_format_t pcm_format,
+ 				unsigned int channels,
+ 				unsigned int period_bytes,
++				unsigned int period_frames,
++				unsigned int buffer_periods,
+ 				unsigned int rate,
+ 				struct audioformat *fmt,
+ 				struct snd_usb_endpoint *sync_ep)
+@@ -793,7 +808,8 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
+ 	switch (ep->type) {
+ 	case  SND_USB_ENDPOINT_TYPE_DATA:
+ 		err = data_ep_set_params(ep, pcm_format, channels,
+-					 period_bytes, fmt, sync_ep);
++					 period_bytes, period_frames,
++					 buffer_periods, fmt, sync_ep);
+ 		break;
+ 	case  SND_USB_ENDPOINT_TYPE_SYNC:
+ 		err = sync_ep_set_params(ep, fmt);
+diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
+index 2287adf5ca59..3bd02f0d226c 100644
+--- a/sound/usb/endpoint.h
++++ b/sound/usb/endpoint.h
+@@ -12,6 +12,8 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
+ 				snd_pcm_format_t pcm_format,
+ 				unsigned int channels,
+ 				unsigned int period_bytes,
++				unsigned int period_frames,
++				unsigned int buffer_periods,
+ 				unsigned int rate,
+ 				struct audioformat *fmt,
+ 				struct snd_usb_endpoint *sync_ep);
+diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
+index b375d58871e7..19e79953f2e3 100644
+--- a/sound/usb/pcm.c
++++ b/sound/usb/pcm.c
+@@ -595,6 +595,7 @@ static int configure_sync_endpoint(struct snd_usb_substream *subs)
+ 						   subs->pcm_format,
+ 						   subs->channels,
+ 						   subs->period_bytes,
++						   0, 0,
+ 						   subs->cur_rate,
+ 						   subs->cur_audiofmt,
+ 						   NULL);
+@@ -631,6 +632,7 @@ static int configure_sync_endpoint(struct snd_usb_substream *subs)
+ 					  subs->pcm_format,
+ 					  sync_fp->channels,
+ 					  sync_period_bytes,
++					  0, 0,
+ 					  subs->cur_rate,
+ 					  sync_fp,
+ 					  NULL);
+@@ -653,6 +655,8 @@ static int configure_endpoint(struct snd_usb_substream *subs)
+ 					  subs->pcm_format,
+ 					  subs->channels,
+ 					  subs->period_bytes,
++					  subs->period_frames,
++					  subs->buffer_periods,
+ 					  subs->cur_rate,
+ 					  subs->cur_audiofmt,
+ 					  subs->sync_endpoint);
+@@ -689,6 +693,8 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
+ 
+ 	subs->pcm_format = params_format(hw_params);
+ 	subs->period_bytes = params_period_bytes(hw_params);
++	subs->period_frames = params_period_size(hw_params);
++	subs->buffer_periods = params_periods(hw_params);
+ 	subs->channels = params_channels(hw_params);
+ 	subs->cur_rate = params_rate(hw_params);
+ 
+@@ -1363,6 +1369,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
+ 	frames = 0;
+ 	urb->number_of_packets = 0;
+ 	spin_lock_irqsave(&subs->lock, flags);
++	subs->frame_limit += ep->max_urb_frames;
+ 	for (i = 0; i < ctx->packets; i++) {
+ 		if (ctx->packet_size[i])
+ 			counts = ctx->packet_size[i];
+@@ -1377,6 +1384,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
+ 		subs->transfer_done += counts;
+ 		if (subs->transfer_done >= runtime->period_size) {
+ 			subs->transfer_done -= runtime->period_size;
++			subs->frame_limit = 0;
+ 			period_elapsed = 1;
+ 			if (subs->fmt_type == UAC_FORMAT_TYPE_II) {
+ 				if (subs->transfer_done > 0) {
+@@ -1399,8 +1407,10 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
+ 				break;
+ 			}
+ 		}
+-		if (period_elapsed &&
+-		    !snd_usb_endpoint_implicit_feedback_sink(subs->data_endpoint)) /* finish at the period boundary */
++		/* finish at the period boundary or after enough frames */
++		if ((period_elapsed ||
++				subs->transfer_done >= subs->frame_limit) &&
++		    !snd_usb_endpoint_implicit_feedback_sink(ep))
+ 			break;
+ 	}
+ 	bytes = frames * ep->stride;
+diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
+index caabe9b3af49..5d2fe0530745 100644
+--- a/sound/usb/usbaudio.h
++++ b/sound/usb/usbaudio.h
+@@ -55,7 +55,6 @@ struct snd_usb_audio {
+ 	struct list_head mixer_list;	/* list of mixer interfaces */
+ 
+ 	int setup;			/* from the 'device_setup' module param */
+-	int nrpacks;			/* from the 'nrpacks' module param */
+ 	bool autoclock;			/* from the 'autoclock' module param */
+ 
+ 	struct usb_host_interface *ctrl_intf;	/* the audio control interface */

commit 232275a089dfd2e77377a85f11d0a4e3ca60e612
+Author: Alan Stern 
+Date:   Tue Sep 24 15:43:39 2013 -0400
+
+    USB: fix substandard locking for the sysfs files
+    
+    This patch straightens out some locking issues in the USB sysfs
+    interface:
+    
+            Deauthorization will destroy existing configurations.
+            Attributes that read from udev->actconfig need to lock the
+            device to prevent races.  Likewise for the rawdescriptor
+            values.
+    
+            Attributes that access an interface's current alternate
+            setting should use ACCESS_ONCE() to obtain the cur_altsetting
+            pointer, to protect against concurrent altsetting changes.
+    
+            The supports_autosuspend() attribute routine accesses values
+            from an interface's driver, so it should lock the interface
+            (rather than the usb_device) to protect against concurrent
+            unbinds.  Once this is done, the routine can be simplified
+            considerably.
+    
+    Scalar values that are stored directly in the usb_device structure are
+    always available.  They do not require any locking.  The same is true
+    of the cached interface string descriptor, because it is not
+    deallocated until the usb_host_interface structure is destroyed.
+    
+    Signed-off-by: Alan Stern 
+    CC: Hans de Goede 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 6d2c8edb1ffe..59cb5f99467a 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -23,14 +23,16 @@ static ssize_t field##_show(struct device *dev,				\
+ {									\
+ 	struct usb_device *udev;					\
+ 	struct usb_host_config *actconfig;				\
++	ssize_t rc = 0;							\
+ 									\
+ 	udev = to_usb_device(dev);					\
++	usb_lock_device(udev);						\
+ 	actconfig = udev->actconfig;					\
+ 	if (actconfig)							\
+-		return sprintf(buf, format_string,			\
++		rc = sprintf(buf, format_string,			\
+ 				actconfig->desc.field);			\
+-	else								\
+-		return 0;						\
++	usb_unlock_device(udev);					\
++	return rc;							\
+ }									\
+ 
+ #define usb_actconfig_attr(field, format_string)		\
+@@ -45,12 +47,15 @@ static ssize_t bMaxPower_show(struct device *dev,
+ {
+ 	struct usb_device *udev;
+ 	struct usb_host_config *actconfig;
++	ssize_t rc = 0;
+ 
+ 	udev = to_usb_device(dev);
++	usb_lock_device(udev);
+ 	actconfig = udev->actconfig;
+-	if (!actconfig)
+-		return 0;
+-	return sprintf(buf, "%dmA\n", usb_get_max_power(udev, actconfig));
++	if (actconfig)
++		rc = sprintf(buf, "%dmA\n", usb_get_max_power(udev, actconfig));
++	usb_unlock_device(udev);
++	return rc;
+ }
+ static DEVICE_ATTR_RO(bMaxPower);
+ 
+@@ -59,12 +64,15 @@ static ssize_t configuration_show(struct device *dev,
+ {
+ 	struct usb_device *udev;
+ 	struct usb_host_config *actconfig;
++	ssize_t rc = 0;
+ 
+ 	udev = to_usb_device(dev);
++	usb_lock_device(udev);
+ 	actconfig = udev->actconfig;
+-	if ((!actconfig) || (!actconfig->string))
+-		return 0;
+-	return sprintf(buf, "%s\n", actconfig->string);
++	if (actconfig && actconfig->string)
++		rc = sprintf(buf, "%s\n", actconfig->string);
++	usb_unlock_device(udev);
++	return rc;
+ }
+ static DEVICE_ATTR_RO(configuration);
+ 
+@@ -764,6 +772,7 @@ read_descriptors(struct file *filp, struct kobject *kobj,
+ 	 * Following that are the raw descriptor entries for all the
+ 	 * configurations (config plus subsidiary descriptors).
+ 	 */
++	usb_lock_device(udev);
+ 	for (cfgno = -1; cfgno < udev->descriptor.bNumConfigurations &&
+ 			nleft > 0; ++cfgno) {
+ 		if (cfgno < 0) {
+@@ -784,6 +793,7 @@ read_descriptors(struct file *filp, struct kobject *kobj,
+ 			off -= srclen;
+ 		}
+ 	}
++	usb_unlock_device(udev);
+ 	return count - nleft;
+ }
+ 
+@@ -870,9 +880,7 @@ static ssize_t interface_show(struct device *dev, struct device_attribute *attr,
+ 	char *string;
+ 
+ 	intf = to_usb_interface(dev);
+-	string = intf->cur_altsetting->string;
+-	barrier();		/* The altsetting might change! */
+-
++	string = ACCESS_ONCE(intf->cur_altsetting->string);
+ 	if (!string)
+ 		return 0;
+ 	return sprintf(buf, "%s\n", string);
+@@ -888,7 +896,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
+ 
+ 	intf = to_usb_interface(dev);
+ 	udev = interface_to_usbdev(intf);
+-	alt = intf->cur_altsetting;
++	alt = ACCESS_ONCE(intf->cur_altsetting);
+ 
+ 	return sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02X"
+ 			"ic%02Xisc%02Xip%02Xin%02X\n",
+@@ -909,23 +917,14 @@ static ssize_t supports_autosuspend_show(struct device *dev,
+ 					 struct device_attribute *attr,
+ 					 char *buf)
+ {
+-	struct usb_interface *intf;
+-	struct usb_device *udev;
+-	int ret;
++	int s;
+ 
+-	intf = to_usb_interface(dev);
+-	udev = interface_to_usbdev(intf);
+-
+-	usb_lock_device(udev);
++	device_lock(dev);
+ 	/* Devices will be autosuspended even when an interface isn't claimed */
+-	if (!intf->dev.driver ||
+-			to_usb_driver(intf->dev.driver)->supports_autosuspend)
+-		ret = sprintf(buf, "%u\n", 1);
+-	else
+-		ret = sprintf(buf, "%u\n", 0);
+-	usb_unlock_device(udev);
++	s = (!dev->driver || to_usb_driver(dev->driver)->supports_autosuspend);
++	device_unlock(dev);
+ 
+-	return ret;
++	return sprintf(buf, "%u\n", s);
+ }
+ static DEVICE_ATTR_RO(supports_autosuspend);
+ 

commit f875fdbf344b9fde207f66b392c40845dd7e5aa6
+Author: Alan Stern 
+Date:   Tue Sep 24 15:45:25 2013 -0400
+
+    USB: fix PM config symbol in uhci-hcd, ehci-hcd, and xhci-hcd
+    
+    Since uhci-hcd, ehci-hcd, and xhci-hcd support runtime PM, the .pm
+    field in their pci_driver structures should be protected by CONFIG_PM
+    rather than CONFIG_PM_SLEEP.  The corresponding change has already
+    been made for ohci-hcd.
+    
+    Without this change, controllers won't do runtime suspend if system
+    suspend or hibernation isn't enabled.
+    
+    Signed-off-by: Alan Stern 
+    CC: Sarah Sharp 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index 6bd299e61f58..854c2ec7b699 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -361,7 +361,7 @@ static struct pci_driver ehci_pci_driver = {
+ 	.remove =	usb_hcd_pci_remove,
+ 	.shutdown = 	usb_hcd_pci_shutdown,
+ 
+-#ifdef CONFIG_PM_SLEEP
++#ifdef CONFIG_PM
+ 	.driver =	{
+ 		.pm =	&usb_hcd_pci_pm_ops
+ 	},
+diff --git a/drivers/usb/host/uhci-pci.c b/drivers/usb/host/uhci-pci.c
+index c300bd2f7d1c..0f228c46eeda 100644
+--- a/drivers/usb/host/uhci-pci.c
++++ b/drivers/usb/host/uhci-pci.c
+@@ -293,7 +293,7 @@ static struct pci_driver uhci_pci_driver = {
+ 	.remove =	usb_hcd_pci_remove,
+ 	.shutdown =	uhci_shutdown,
+ 
+-#ifdef CONFIG_PM_SLEEP
++#ifdef CONFIG_PM
+ 	.driver =	{
+ 		.pm =	&usb_hcd_pci_pm_ops
+ 	},
+diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
+index c2d495057eb5..236c3aabe940 100644
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -351,7 +351,7 @@ static struct pci_driver xhci_pci_driver = {
+ 	/* suspend and resume implemented later */
+ 
+ 	.shutdown = 	usb_hcd_pci_shutdown,
+-#ifdef CONFIG_PM_SLEEP
++#ifdef CONFIG_PM
+ 	.driver = {
+ 		.pm = &usb_hcd_pci_pm_ops
+ 	},

commit a8693424c751b8247ee19bd8b857f1d4f432b972
+Author: Alan Stern 
+Date:   Tue Sep 24 15:46:45 2013 -0400
+
+    USB: OHCI: accept very late isochronous URBs
+    
+    Commit 24f531371de1 (USB: EHCI: accept very late isochronous URBs)
+    changed the isochronous API provided by ehci-hcd.  URBs submitted too
+    late, so that the time slots for all their packets have already
+    expired, are no longer rejected outright.  Instead the submission is
+    accepted, and the URB completes normally with a -EXDEV error for each
+    packet.  This is what client drivers expect.
+    
+    This patch implements the same policy in ohci-hcd.  The change is more
+    complicated than it was in ehci-hcd, because ohci-hcd doesn't scan for
+    isochronous completions in the same way as ehci-hcd does.  Rather, it
+    depends on the hardware adding completed TDs to a "done queue".  Some
+    OHCI controller don't handle this properly when a TD's time slot has
+    already expired, so we have to avoid adding such TDs to the schedule
+    in the first place.  As a result, if the URB was submitted too late
+    then none of its TDs will get put on the schedule, so none of them
+    will end up on the done queue, so the driver will never realize that
+    the URB should be completed.
+    
+    To solve this problem, the patch adds one to urb_priv->td_cnt for such
+    URBs, making it larger than urb_priv->length (td_cnt already gets set
+    to the number of TD's that had to be skipped because their slots have
+    expired).  Each time an URB is given back, the finish_urb() routine
+    looks to see if urb_priv->td_cnt for the next URB on the same endpoint
+    is marked in this way.  If so, it gives back the next URB right away.
+    
+    This should be applied to all kernels containing commit 815fa7b91761
+    (USB: OHCI: fix logic for scheduling isochronous URBs).
+    
+    Signed-off-by: Alan Stern 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index 8f6b695af6a4..604cad1bcf9c 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -216,31 +216,26 @@ static int ohci_urb_enqueue (
+ 			frame &= ~(ed->interval - 1);
+ 			frame |= ed->branch;
+ 			urb->start_frame = frame;
++			ed->last_iso = frame + ed->interval * (size - 1);
+ 		}
+ 	} else if (ed->type == PIPE_ISOCHRONOUS) {
+ 		u16	next = ohci_frame_no(ohci) + 1;
+ 		u16	frame = ed->last_iso + ed->interval;
++		u16	length = ed->interval * (size - 1);
+ 
+ 		/* Behind the scheduling threshold? */
+ 		if (unlikely(tick_before(frame, next))) {
+ 
+-			/* USB_ISO_ASAP: Round up to the first available slot */
++			/* URB_ISO_ASAP: Round up to the first available slot */
+ 			if (urb->transfer_flags & URB_ISO_ASAP) {
+ 				frame += (next - frame + ed->interval - 1) &
+ 						-ed->interval;
+ 
+ 			/*
+-			 * Not ASAP: Use the next slot in the stream.  If
+-			 * the entire URB falls before the threshold, fail.
++			 * Not ASAP: Use the next slot in the stream,
++			 * no matter what.
+ 			 */
+ 			} else {
+-				if (tick_before(frame + ed->interval *
+-					(urb->number_of_packets - 1), next)) {
+-					retval = -EXDEV;
+-					usb_hcd_unlink_urb_from_ep(hcd, urb);
+-					goto fail;
+-				}
+-
+ 				/*
+ 				 * Some OHCI hardware doesn't handle late TDs
+ 				 * correctly.  After retiring them it proceeds
+@@ -251,9 +246,16 @@ static int ohci_urb_enqueue (
+ 				urb_priv->td_cnt = DIV_ROUND_UP(
+ 						(u16) (next - frame),
+ 						ed->interval);
++				if (urb_priv->td_cnt >= urb_priv->length) {
++					++urb_priv->td_cnt;	/* Mark it */
++					ohci_dbg(ohci, "iso underrun %p (%u+%u < %u)\n",
++							urb, frame, length,
++							next);
++				}
+ 			}
+ 		}
+ 		urb->start_frame = frame;
++		ed->last_iso = frame + length;
+ 	}
+ 
+ 	/* fill the TDs and link them to the ed; and
+diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
+index df4a6707322d..e7f577e63624 100644
+--- a/drivers/usb/host/ohci-q.c
++++ b/drivers/usb/host/ohci-q.c
+@@ -41,9 +41,13 @@ finish_urb(struct ohci_hcd *ohci, struct urb *urb, int status)
+ __releases(ohci->lock)
+ __acquires(ohci->lock)
+ {
+-	 struct device *dev = ohci_to_hcd(ohci)->self.controller;
++	struct device *dev = ohci_to_hcd(ohci)->self.controller;
++	struct usb_host_endpoint *ep = urb->ep;
++	struct urb_priv *urb_priv;
++
+ 	// ASSERT (urb->hcpriv != 0);
+ 
++ restart:
+ 	urb_free_priv (ohci, urb->hcpriv);
+ 	urb->hcpriv = NULL;
+ 	if (likely(status == -EINPROGRESS))
+@@ -80,6 +84,21 @@ __acquires(ohci->lock)
+ 		ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_IE);
+ 		ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
+ 	}
++
++	/*
++	 * An isochronous URB that is sumitted too late won't have any TDs
++	 * (marked by the fact that the td_cnt value is larger than the
++	 * actual number of TDs).  If the next URB on this endpoint is like
++	 * that, give it back now.
++	 */
++	if (!list_empty(&ep->urb_list)) {
++		urb = list_first_entry(&ep->urb_list, struct urb, urb_list);
++		urb_priv = urb->hcpriv;
++		if (urb_priv->td_cnt > urb_priv->length) {
++			status = 0;
++			goto restart;
++		}
++	}
+ }
+ 
+ 
+@@ -546,7 +565,6 @@ td_fill (struct ohci_hcd *ohci, u32 info,
+ 		td->hwCBP = cpu_to_hc32 (ohci, data & 0xFFFFF000);
+ 		*ohci_hwPSWp(ohci, td, 0) = cpu_to_hc16 (ohci,
+ 						(data & 0x0FFF) | 0xE000);
+-		td->ed->last_iso = info & 0xffff;
+ 	} else {
+ 		td->hwCBP = cpu_to_hc32 (ohci, data);
+ 	}
+@@ -996,7 +1014,7 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick)
+ 			urb_priv->td_cnt++;
+ 
+ 			/* if URB is done, clean up */
+-			if (urb_priv->td_cnt == urb_priv->length) {
++			if (urb_priv->td_cnt >= urb_priv->length) {
+ 				modified = completed = 1;
+ 				finish_urb(ohci, urb, 0);
+ 			}
+@@ -1086,7 +1104,7 @@ static void takeback_td(struct ohci_hcd *ohci, struct td *td)
+ 	urb_priv->td_cnt++;
+ 
+ 	/* If all this urb's TDs are done, call complete() */
+-	if (urb_priv->td_cnt == urb_priv->length)
++	if (urb_priv->td_cnt >= urb_priv->length)
+ 		finish_urb(ohci, urb, status);
+ 
+ 	/* clean schedule:  unlink EDs that are no longer busy */

commit bef073b067a7b1874a6b381e0035bb0516d71a77
+Author: Alan Stern 
+Date:   Tue Sep 24 15:47:20 2013 -0400
+
+    USB: UHCI: accept very late isochronous URBs
+    
+    Commit 24f531371de1 (USB: EHCI: accept very late isochronous URBs)
+    changed the isochronous API provided by ehci-hcd.  URBs submitted too
+    late, so that the time slots for all their packets have already
+    expired, are no longer rejected outright.  Instead the submission is
+    accepted, and the URB completes normally with a -EXDEV error for each
+    packet.  This is what client drivers expect.
+    
+    This patch implements the same policy in uhci-hcd.  It should be
+    applied to all kernels containing commit c44b225077bb (UHCI: implement
+    new semantics for URB_ISO_ASAP).
+    
+    Signed-off-by: Alan Stern 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 041c6ddb695c..da6f56d996ce 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -1303,7 +1303,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
+ 		}
+ 
+ 		/* Fell behind? */
+-		if (uhci_frame_before_eq(frame, next)) {
++		if (!uhci_frame_before_eq(next, frame)) {
+ 
+ 			/* USB_ISO_ASAP: Round up to the first available slot */
+ 			if (urb->transfer_flags & URB_ISO_ASAP)
+@@ -1311,13 +1311,17 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
+ 						-qh->period;
+ 
+ 			/*
+-			 * Not ASAP: Use the next slot in the stream.  If
+-			 * the entire URB falls before the threshold, fail.
++			 * Not ASAP: Use the next slot in the stream,
++			 * no matter what.
+ 			 */
+ 			else if (!uhci_frame_before_eq(next,
+ 					frame + (urb->number_of_packets - 1) *
+ 						qh->period))
+-				return -EXDEV;
++				dev_dbg(uhci_dev(uhci), "iso underrun %p (%u+%u < %u)\n",
++						urb, frame,
++						(urb->number_of_packets - 1) *
++							qh->period,
++						next);
+ 		}
+ 	}
+ 

commit 8937669fd637e2edff05973cb1fdee5f910cbcc7
+Author: Alan Stern 
+Date:   Tue Sep 24 15:48:05 2013 -0400
+
+    USB: iMX21: accept very late isochronous URBs
+    
+    Commit 24f531371de1 (USB: EHCI: accept very late isochronous URBs)
+    changed the isochronous API provided by ehci-hcd.  URBs submitted too
+    late, so that the time slots for all their packets have already
+    expired, are no longer rejected outright.  Instead the submission is
+    accepted, and the URB completes normally with a -EXDEV error for each
+    packet.  This is what client drivers expect.
+    
+    The same policy should be implemented in imx21-hcd, but I don't know
+    enough about the hardware to do it.  As a second-best substitute, this
+    patch treats very late isochronous submissions as though the
+    URB_ISO_ASAP flag were set.  I don't have any way to test this change,
+    unfortunately.
+    
+    Signed-off-by: Alan Stern 
+    CC: Sascha Hauer 
+    CC: Martin Fuzzey 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c
+index 60a5de505ca1..adb01d950a16 100644
+--- a/drivers/usb/host/imx21-hcd.c
++++ b/drivers/usb/host/imx21-hcd.c
+@@ -824,13 +824,13 @@ static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd,
+ 			i = DIV_ROUND_UP(wrap_frame(
+ 					cur_frame - urb->start_frame),
+ 					urb->interval);
+-			if (urb->transfer_flags & URB_ISO_ASAP) {
++
++			/* Treat underruns as if URB_ISO_ASAP was set */
++			if ((urb->transfer_flags & URB_ISO_ASAP) ||
++					i >= urb->number_of_packets) {
+ 				urb->start_frame = wrap_frame(urb->start_frame
+ 						+ i * urb->interval);
+ 				i = 0;
+-			} else if (i >= urb->number_of_packets) {
+-				ret = -EXDEV;
+-				goto alloc_dmem_failed;
+ 			}
+ 		}
+ 	}

commit 46c73d1d3ebc38feed1d97c6980252a0a01f6a5b
+Author: Alan Stern 
+Date:   Tue Sep 3 13:59:03 2013 -0400
+
+    USB: EHCI: handle isochronous underruns with tasklets
+    
+    This patch updates the iso_stream_schedule() routine in ehci-sched.c
+    to handle cases where an underrun causes an isochronous endpoint's
+    queue to empty out, but the client driver wants to maintain
+    synchronization with the device (i.e., the URB_ISO_ASAP flag is not
+    set).  This could not happen until recently, when ehci-hcd switched
+    over to completing URBs in a tasklet.
+    
+    (This may seem like an unlikely case to worry about, but underruns are
+    all too common with the snd-usb-audio driver, which doesn't use
+    URB_ISO_ASAP.)
+    
+    As part of the fix, some URBs may need to be given back when they are
+    submitted.  This is necessary when the URB's scheduled slots all fall
+    before the current value of ehci->last_iso_frame, and as an
+    optimization we do it also when the slots all fall before the current
+    frame number.
+    
+    As a second part of the fix, we may need to skip some but not all of
+    an URB's packets.  This is necessary when some of the URB's scheduled
+    slots fall before the current value of ehci->last_iso_frame and some
+    of them fall after the current frame number.  A new field
+    (first_packet) is added to struct ehci_iso_sched, to indicate how many
+    packets should be skipped.
+    
+    Signed-off-by: Alan Stern 
+    CC: Ming Lei 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 208518bc6e36..dcbaad94d607 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1370,10 +1370,12 @@ iso_stream_schedule (
+ 	struct ehci_iso_stream	*stream
+ )
+ {
+-	u32			now, base, next, start, period, span;
+-	int			status;
++	u32			now, base, next, start, period, span, now2;
++	u32			wrap = 0, skip = 0;
++	int			status = 0;
+ 	unsigned		mod = ehci->periodic_size << 3;
+ 	struct ehci_iso_sched	*sched = urb->hcpriv;
++	bool			empty = list_empty(&stream->td_list);
+ 
+ 	period = urb->interval;
+ 	span = sched->span;
+@@ -1384,6 +1386,19 @@ iso_stream_schedule (
+ 
+ 	now = ehci_read_frame_index(ehci) & (mod - 1);
+ 
++	/* Take the isochronous scheduling threshold into account */
++	if (ehci->i_thresh)
++		next = now + ehci->i_thresh;	/* uframe cache */
++	else
++		next = (now + 2 + 7) & ~0x07;	/* full frame cache */
++
++	/*
++	 * Use ehci->last_iso_frame as the base.  There can't be any
++	 * TDs scheduled for earlier than that.
++	 */
++	base = ehci->last_iso_frame << 3;
++	next = (next - base) & (mod - 1);
++
+ 	/*
+ 	 * Need to schedule; when's the next (u)frame we could start?
+ 	 * This is bigger than ehci->i_thresh allows; scheduling itself
+@@ -1391,11 +1406,11 @@ iso_stream_schedule (
+ 	 * can also help high bandwidth if the dma and irq loads don't
+ 	 * jump until after the queue is primed.
+ 	 */
+-	if (unlikely(list_empty(&stream->td_list))) {
++	if (unlikely(empty && !hcd_periodic_completion_in_progress(
++			ehci_to_hcd(ehci), urb->ep))) {
+ 		int done = 0;
+ 
+-		base = now & ~0x07;
+-		start = base + SCHEDULING_DELAY;
++		start = (now & ~0x07) + SCHEDULING_DELAY;
+ 
+ 		/* find a uframe slot with enough bandwidth.
+ 		 * Early uframes are more precious because full-speed
+@@ -1426,6 +1441,9 @@ iso_stream_schedule (
+ 			status = -ENOSPC;
+ 			goto fail;
+ 		}
++
++		start = (start - base) & (mod - 1);
++		goto use_start;
+ 	}
+ 
+ 	/*
+@@ -1434,72 +1452,85 @@ iso_stream_schedule (
+ 	 * (irq delays etc).  If there are, the behavior depends on
+ 	 * whether URB_ISO_ASAP is set.
+ 	 */
+-	else {
++	start = (stream->next_uframe - base) & (mod - 1);
++	now2 = (now - base) & (mod - 1);
+ 
+-		/* Take the isochronous scheduling threshold into account */
+-		if (ehci->i_thresh)
+-			next = now + ehci->i_thresh;	/* uframe cache */
+-		else
+-			next = (now + 2 + 7) & ~0x07;	/* full frame cache */
++	/* Is the schedule already full? */
++	if (unlikely(!empty && start < period)) {
++		ehci_dbg(ehci, "iso sched full %p (%u-%u < %u mod %u)\n",
++				urb, stream->next_uframe, base, period, mod);
++		status = -ENOSPC;
++		goto fail;
++	}
+ 
+-		/*
+-		 * Use ehci->last_iso_frame as the base.  There can't be any
+-		 * TDs scheduled for earlier than that.
+-		 */
+-		base = ehci->last_iso_frame << 3;
+-		next = (next - base) & (mod - 1);
+-		start = (stream->next_uframe - base) & (mod - 1);
+-
+-		/* Is the schedule already full? */
+-		if (unlikely(start < period)) {
+-			ehci_dbg(ehci, "iso sched full %p (%u-%u < %u mod %u)\n",
+-					urb, stream->next_uframe, base,
+-					period, mod);
+-			status = -ENOSPC;
+-			goto fail;
+-		}
++	/* Is the next packet scheduled after the base time? */
++	if (likely(!empty || start <= now2 + period)) {
+ 
+-		/* Behind the scheduling threshold? */
+-		if (unlikely(start < next)) {
+-			unsigned now2 = (now - base) & (mod - 1);
++		/* URB_ISO_ASAP: make sure that start >= next */
++		if (unlikely(start < next &&
++				(urb->transfer_flags & URB_ISO_ASAP)))
++			goto do_ASAP;
+ 
+-			/* USB_ISO_ASAP: Round up to the first available slot */
+-			if (urb->transfer_flags & URB_ISO_ASAP)
+-				start += (next - start + period - 1) & -period;
++		/* Otherwise use start, if it's not in the past */
++		if (likely(start >= now2))
++			goto use_start;
+ 
+-			/*
+-			 * Not ASAP: Use the next slot in the stream,
+-			 * no matter what.
+-			 */
+-			else if (start + span - period < now2) {
+-				ehci_dbg(ehci, "iso underrun %p (%u+%u < %u)\n",
+-						urb, start + base,
+-						span - period, now2 + base);
+-			}
+-		}
++	/* Otherwise we got an underrun while the queue was empty */
++	} else {
++		if (urb->transfer_flags & URB_ISO_ASAP)
++			goto do_ASAP;
++		wrap = mod;
++		now2 += mod;
++	}
+ 
+-		start += base;
++	/* How many uframes and packets do we need to skip? */
++	skip = (now2 - start + period - 1) & -period;
++	if (skip >= span) {		/* Entirely in the past? */
++		ehci_dbg(ehci, "iso underrun %p (%u+%u < %u) [%u]\n",
++				urb, start + base, span - period, now2 + base,
++				base);
++
++		/* Try to keep the last TD intact for scanning later */
++		skip = span - period;
++
++		/* Will it come before the current scan position? */
++		if (empty) {
++			skip = span;	/* Skip the entire URB */
++			status = 1;	/* and give it back immediately */
++			iso_sched_free(stream, sched);
++			sched = NULL;
++		}
+ 	}
++	urb->error_count = skip / period;
++	if (sched)
++		sched->first_packet = urb->error_count;
++	goto use_start;
+ 
++ do_ASAP:
++	/* Use the first slot after "next" */
++	start = next + ((start - next) & (period - 1));
++
++ use_start:
+ 	/* Tried to schedule too far into the future? */
+-	if (unlikely(start - base + span - period >= mod)) {
++	if (unlikely(start + span - period >= mod + wrap)) {
+ 		ehci_dbg(ehci, "request %p would overflow (%u+%u >= %u)\n",
+-				urb, start - base, span - period, mod);
++				urb, start, span - period, mod + wrap);
+ 		status = -EFBIG;
+ 		goto fail;
+ 	}
+ 
+-	stream->next_uframe = start & (mod - 1);
++	start += base;
++	stream->next_uframe = (start + skip) & (mod - 1);
+ 
+ 	/* report high speed start in uframes; full speed, in frames */
+-	urb->start_frame = stream->next_uframe;
++	urb->start_frame = start & (mod - 1);
+ 	if (!stream->highspeed)
+ 		urb->start_frame >>= 3;
+ 
+ 	/* Make sure scan_isoc() sees these */
+ 	if (ehci->isoc_count == 0)
+ 		ehci->last_iso_frame = now >> 3;
+-	return 0;
++	return status;
+ 
+  fail:
+ 	iso_sched_free(stream, sched);
+@@ -1612,7 +1643,8 @@ static void itd_link_urb(
+ 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
+ 
+ 	/* fill iTDs uframe by uframe */
+-	for (packet = 0, itd = NULL; packet < urb->number_of_packets; ) {
++	for (packet = iso_sched->first_packet, itd = NULL;
++			packet < urb->number_of_packets;) {
+ 		if (itd == NULL) {
+ 			/* ASSERT:  we have all necessary itds */
+ 			// BUG_ON (list_empty (&iso_sched->td_list));
+@@ -1806,10 +1838,14 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb,
+ 	if (unlikely(status))
+ 		goto done_not_linked;
+ 	status = iso_stream_schedule(ehci, urb, stream);
+-	if (likely (status == 0))
++	if (likely(status == 0)) {
+ 		itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
+-	else
++	} else if (status > 0) {
++		status = 0;
++		ehci_urb_done(ehci, urb, 0);
++	} else {
+ 		usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
++	}
+  done_not_linked:
+ 	spin_unlock_irqrestore (&ehci->lock, flags);
+  done:
+@@ -2010,7 +2046,7 @@ static void sitd_link_urb(
+ 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
+ 
+ 	/* fill sITDs frame by frame */
+-	for (packet = 0, sitd = NULL;
++	for (packet = sched->first_packet, sitd = NULL;
+ 			packet < urb->number_of_packets;
+ 			packet++) {
+ 
+@@ -2180,10 +2216,14 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
+ 	if (unlikely(status))
+ 		goto done_not_linked;
+ 	status = iso_stream_schedule(ehci, urb, stream);
+-	if (status == 0)
++	if (likely(status == 0)) {
+ 		sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
+-	else
++	} else if (status > 0) {
++		status = 0;
++		ehci_urb_done(ehci, urb, 0);
++	} else {
+ 		usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
++	}
+  done_not_linked:
+ 	spin_unlock_irqrestore (&ehci->lock, flags);
+  done:
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 291db7d09f22..2d401927e143 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -434,6 +434,7 @@ struct ehci_iso_packet {
+ struct ehci_iso_sched {
+ 	struct list_head	td_list;
+ 	unsigned		span;
++	unsigned		first_packet;
+ 	struct ehci_iso_packet	packet [0];
+ };
+ 

commit e4e18cbd52c8efb0d73a66d0598dc887c0feefb7
+Author: Alan Stern 
+Date:   Tue Sep 3 13:58:59 2013 -0400
+
+    USB: EHCI: code rearrangement in iso_stream_schedule()
+    
+    This patch interchanges the "if" and "else" branches of the big "if"
+    statement in iso_stream_schedule(), in preparation for the next patch
+    in this series.  That is, it changes
+    
+            if (likely(!...)) {
+                    A
+            } else {
+                    B
+            }
+    
+    to
+    
+            if (unlikely(...)) {
+                    B
+            } else {
+                    A
+            }
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 85dd24ed97a6..208518bc6e36 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1384,12 +1384,57 @@ iso_stream_schedule (
+ 
+ 	now = ehci_read_frame_index(ehci) & (mod - 1);
+ 
+-	/* Typical case: reuse current schedule, stream is still active.
++	/*
++	 * Need to schedule; when's the next (u)frame we could start?
++	 * This is bigger than ehci->i_thresh allows; scheduling itself
++	 * isn't free, the delay should handle reasonably slow cpus.  It
++	 * can also help high bandwidth if the dma and irq loads don't
++	 * jump until after the queue is primed.
++	 */
++	if (unlikely(list_empty(&stream->td_list))) {
++		int done = 0;
++
++		base = now & ~0x07;
++		start = base + SCHEDULING_DELAY;
++
++		/* find a uframe slot with enough bandwidth.
++		 * Early uframes are more precious because full-speed
++		 * iso IN transfers can't use late uframes,
++		 * and therefore they should be allocated last.
++		 */
++		next = start;
++		start += period;
++		do {
++			start--;
++			/* check schedule: enough space? */
++			if (stream->highspeed) {
++				if (itd_slot_ok(ehci, mod, start,
++						stream->usecs, period))
++					done = 1;
++			} else {
++				if ((start % 8) >= 6)
++					continue;
++				if (sitd_slot_ok(ehci, mod, stream,
++						start, sched, period))
++					done = 1;
++			}
++		} while (start > next && !done);
++
++		/* no room in the schedule */
++		if (!done) {
++			ehci_dbg(ehci, "iso sched full %p", urb);
++			status = -ENOSPC;
++			goto fail;
++		}
++	}
++
++	/*
++	 * Typical case: reuse current schedule, stream is still active.
+ 	 * Hopefully there are no gaps from the host falling behind
+ 	 * (irq delays etc).  If there are, the behavior depends on
+ 	 * whether URB_ISO_ASAP is set.
+ 	 */
+-	if (likely (!list_empty (&stream->td_list))) {
++	else {
+ 
+ 		/* Take the isochronous scheduling threshold into account */
+ 		if (ehci->i_thresh)
+@@ -1436,49 +1481,6 @@ iso_stream_schedule (
+ 		start += base;
+ 	}
+ 
+-	/* need to schedule; when's the next (u)frame we could start?
+-	 * this is bigger than ehci->i_thresh allows; scheduling itself
+-	 * isn't free, the delay should handle reasonably slow cpus.  it
+-	 * can also help high bandwidth if the dma and irq loads don't
+-	 * jump until after the queue is primed.
+-	 */
+-	else {
+-		int done = 0;
+-
+-		base = now & ~0x07;
+-		start = base + SCHEDULING_DELAY;
+-
+-		/* find a uframe slot with enough bandwidth.
+-		 * Early uframes are more precious because full-speed
+-		 * iso IN transfers can't use late uframes,
+-		 * and therefore they should be allocated last.
+-		 */
+-		next = start;
+-		start += period;
+-		do {
+-			start--;
+-			/* check schedule: enough space? */
+-			if (stream->highspeed) {
+-				if (itd_slot_ok(ehci, mod, start,
+-						stream->usecs, period))
+-					done = 1;
+-			} else {
+-				if ((start % 8) >= 6)
+-					continue;
+-				if (sitd_slot_ok(ehci, mod, stream,
+-						start, sched, period))
+-					done = 1;
+-			}
+-		} while (start > next && !done);
+-
+-		/* no room in the schedule */
+-		if (!done) {
+-			ehci_dbg(ehci, "iso sched full %p", urb);
+-			status = -ENOSPC;
+-			goto fail;
+-		}
+-	}
+-
+ 	/* Tried to schedule too far into the future? */
+ 	if (unlikely(start - base + span - period >= mod)) {
+ 		ehci_dbg(ehci, "request %p would overflow (%u+%u >= %u)\n",

commit c7ccde6eac6d3c4bc6110cc3fd76ef3823bc0831
+Author: Alan Stern 
+Date:   Tue Sep 3 13:58:43 2013 -0400
+
+    USB: see if URB comes from a completion handler
+    
+    Now that URBs can be completed inside tasklets, we need a way of
+    determining whether a completion handler for a given endpoint is
+    currently running.  Otherwise it's not possible to maintain the API
+    guarantee about keeping isochronous streams synchronous when an
+    underrun occurs.
+    
+    This patch adds a field and a routine to check whether a completion
+    handler for a periodic endpoint is running.  At the moment no
+    analogous routine appears to be necessary for async endpoints, but one
+    can always be added.
+    
+    Signed-off-by: Alan Stern 
+    CC: Ming Lei 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index d6a8d23f047b..3a2e82a9c115 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1703,7 +1703,9 @@ static void usb_giveback_urb_bh(unsigned long param)
+ 
+ 		urb = list_entry(local_list.next, struct urb, urb_list);
+ 		list_del_init(&urb->urb_list);
++		bh->completing_ep = urb->ep;
+ 		__usb_hcd_giveback_urb(urb);
++		bh->completing_ep = NULL;
+ 	}
+ 
+ 	/* check if there are new URBs to giveback */
+diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
+index 75efc45eaa2f..8c865134c881 100644
+--- a/include/linux/usb/hcd.h
++++ b/include/linux/usb/hcd.h
+@@ -73,6 +73,7 @@ struct giveback_urb_bh {
+ 	spinlock_t lock;
+ 	struct list_head  head;
+ 	struct tasklet_struct bh;
++	struct usb_host_endpoint *completing_ep;
+ };
+ 
+ struct usb_hcd {
+@@ -378,6 +379,12 @@ static inline int hcd_giveback_urb_in_bh(struct usb_hcd *hcd)
+ 	return hcd->driver->flags & HCD_BH;
+ }
+ 
++static inline bool hcd_periodic_completion_in_progress(struct usb_hcd *hcd,
++		struct usb_host_endpoint *ep)
++{
++	return hcd->high_prio_bh.completing_ep == ep;
++}
++
+ extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
+ extern int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
+ 		int status);

commit 5f5610f69be3a925b1f79af27150bb7377bc9ad6
+Author: Alan Stern 
+Date:   Tue Jul 30 15:18:15 2013 -0400
+
+    usb: gadget: fix a bug and a WARN_ON in dummy-hcd
+    
+    This patch fixes a NULL pointer dereference and a WARN_ON in
+    dummy-hcd.  These things were the result of moving to the UDC core
+    framework, and possibly of changes to that framework.
+    
+    Now unloading a gadget driver causes the UDC to be stopped after the
+    gadget driver is unbound, not before.  Therefore the "driver" argument
+    to dummy_udc_stop() can be NULL, so we must not try to print the
+    driver's name without checking first.
+    
+    Also, the UDC framework automatically unregisters the gadget when the
+    UDC is deleted.  Therefore a sysfs attribute file attached to the
+    gadget must be removed before the UDC is deleted, not after.
+    
+    Signed-off-by: Alan Stern 
+    CC: 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index 06ecd08fd57a..b8a2376971a4 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -923,8 +923,9 @@ static int dummy_udc_stop(struct usb_gadget *g,
+ 	struct dummy_hcd	*dum_hcd = gadget_to_dummy_hcd(g);
+ 	struct dummy		*dum = dum_hcd->dum;
+ 
+-	dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n",
+-			driver->driver.name);
++	if (driver)
++		dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n",
++				driver->driver.name);
+ 
+ 	dum->driver = NULL;
+ 
+@@ -1000,8 +1001,8 @@ static int dummy_udc_remove(struct platform_device *pdev)
+ {
+ 	struct dummy	*dum = platform_get_drvdata(pdev);
+ 
+-	usb_del_gadget_udc(&dum->gadget);
+ 	device_remove_file(&dum->gadget.dev, &dev_attr_function);
++	usb_del_gadget_udc(&dum->gadget);
+ 	return 0;
+ }
+ 

commit 984f1733fcee3fbc78d47e26c5096921c5d9946a
+Author: Alan Stern 
+Date:   Fri Sep 6 11:49:51 2013 -0400
+
+    [SCSI] sd: Fix potential out-of-bounds access
+    
+    This patch fixes an out-of-bounds error in sd_read_cache_type(), found
+    by Google's AddressSanitizer tool.  When the loop ends, we know that
+    "offset" lies beyond the end of the data in the buffer, so no Caching
+    mode page was found.  In theory it may be present, but the buffer size
+    is limited to 512 bytes.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Dmitry Vyukov 
+    CC: 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+index b58e8f815a00..e62d17d41d4e 100644
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -2420,14 +2420,9 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
+ 			}
+ 		}
+ 
+-		if (modepage == 0x3F) {
+-			sd_printk(KERN_ERR, sdkp, "No Caching mode page "
+-				  "present\n");
+-			goto defaults;
+-		} else if ((buffer[offset] & 0x3f) != modepage) {
+-			sd_printk(KERN_ERR, sdkp, "Got wrong page\n");
+-			goto defaults;
+-		}
++		sd_printk(KERN_ERR, sdkp, "No Caching mode page found\n");
++		goto defaults;
++
+ 	Page_found:
+ 		if (modepage == 8) {
+ 			sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0);

commit 9d8924297cd9c256c23c02abae40202563452453
+Author: Alan Stern 
+Date:   Fri Aug 30 10:46:00 2013 -0400
+
+    USB: fix build error when CONFIG_PM_SLEEP isn't enabled
+    
+    This patch fixes a build error that occurs when CONFIG_PM is enabled
+    and CONFIG_PM_SLEEP isn't:
+    
+    >> drivers/usb/host/ohci-pci.c:294:10: error: 'usb_hcd_pci_pm_ops' undeclared here (not in a function)
+          .pm = &usb_hcd_pci_pm_ops
+    
+    Since the usb_hcd_pci_pm_ops structure is defined and used when
+    CONFIG_PM is enabled, its declaration should not be protected by
+    CONFIG_PM_SLEEP.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: kbuild test robot 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
+index a9c7d44bd2ed..75efc45eaa2f 100644
+--- a/include/linux/usb/hcd.h
++++ b/include/linux/usb/hcd.h
+@@ -428,7 +428,7 @@ extern int usb_hcd_pci_probe(struct pci_dev *dev,
+ extern void usb_hcd_pci_remove(struct pci_dev *dev);
+ extern void usb_hcd_pci_shutdown(struct pci_dev *dev);
+ 
+-#ifdef CONFIG_PM_SLEEP
++#ifdef CONFIG_PM
+ extern const struct dev_pm_ops usb_hcd_pci_pm_ops;
+ #endif
+ #endif /* CONFIG_PCI */

commit 69820e01aa756b8d228143d997f71523c1e97984
+Author: Alan Stern 
+Date:   Mon Aug 26 15:01:40 2013 -0400
+
+    USB: OHCI: Allow runtime PM without system sleep
+    
+    Since ohci-hcd supports runtime PM, the .pm field in its pci_driver
+    structure should be protected by CONFIG_PM rather than
+    CONFIG_PM_SLEEP.
+    
+    Without this change, OHCI controllers won't do runtime suspend if
+    system suspend or hibernation isn't enabled.
+    
+    Signed-off-by: Alan Stern 
+    cc: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index 08613e241894..767a5eeff848 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -289,7 +289,7 @@ static struct pci_driver ohci_pci_driver = {
+ 	.remove =	usb_hcd_pci_remove,
+ 	.shutdown =	usb_hcd_pci_shutdown,
+ 
+-#ifdef CONFIG_PM_SLEEP
++#ifdef CONFIG_PM
+ 	.driver =	{
+ 		.pm =	&usb_hcd_pci_pm_ops
+ 	},

commit d3474049ab6cfcf14274f5ab9f20c8f50b083eab
+Author: Alan Stern 
+Date:   Mon Aug 26 10:53:53 2013 -0400
+
+    USB: OHCI: fix build error related to ohci_suspend/resume
+    
+    Commit 9a11899c5e69 (USB: OHCI: add missing PCI PM callbacks to
+    ohci-pci.c) added missing ohci_suspend and ohci_resume callback
+    pointers, but forgot that these callbacks are declared and defined
+    only when CONFIG_PM is enabled.
+    
+    This patch adds a preprocessor conditional to avoid build errors when
+    PM is disabled.
+    
+    Reported-by: Guenter Roeck 
+    Tested-by: Guenter Roeck 
+    Reported-by: Meelis Roos ,
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index 0f1d193fef02..279b04910f00 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -305,9 +305,11 @@ static int __init ohci_pci_init(void)
+ 
+ 	ohci_init_driver(&ohci_pci_hc_driver, &pci_overrides);
+ 
++#ifdef	CONFIG_PM
+ 	/* Entries for the PCI suspend/resume callbacks are special */
+ 	ohci_pci_hc_driver.pci_suspend = ohci_suspend;
+ 	ohci_pci_hc_driver.pci_resume = ohci_resume;
++#endif
+ 
+ 	return pci_register_driver(&ohci_pci_driver);
+ }

commit 9a11899c5e699a8d2551692dfcd4372e39dcbdf6
+Author: Alan Stern 
+Date:   Wed Aug 21 10:33:17 2013 -0400
+
+    USB: OHCI: add missing PCI PM callbacks to ohci-pci.c
+    
+    Commit c1117afb8589 (USB: OHCI: make ohci-pci a separate driver)
+    neglected to preserve the entries for the pci_suspend and pci_resume
+    driver callbacks.  As a result, OHCI controllers don't work properly
+    during suspend and after hibernation.
+    
+    This patch adds the missing callbacks to the driver.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Steve Cotton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index 08613e241894..0f1d193fef02 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -304,6 +304,11 @@ static int __init ohci_pci_init(void)
+ 	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+ 
+ 	ohci_init_driver(&ohci_pci_hc_driver, &pci_overrides);
++
++	/* Entries for the PCI suspend/resume callbacks are special */
++	ohci_pci_hc_driver.pci_suspend = ohci_suspend;
++	ohci_pci_hc_driver.pci_resume = ohci_resume;
++
+ 	return pci_register_driver(&ohci_pci_driver);
+ }
+ module_init(ohci_pci_init);

commit aa5ceae24bf8dff1d6fe87c6c4b08e69c6d33550
+Author: Alan Stern 
+Date:   Tue Jul 30 15:39:02 2013 -0400
+
+    USB: handle LPM errors during device suspend correctly
+    
+    The hub driver's usb_port_suspend() routine doesn't handle errors
+    related to Link Power Management properly.  It always returns failure,
+    it doesn't try to clean up the wakeup setting, (in the case of system
+    sleep) it doesn't try to go ahead with the port suspend regardless,
+    and it doesn't try to apply the new power-off mechanism.
+    
+    This patch fixes these problems.
+    
+    Note: Sarah fixed this patch to apply against 3.11, since the original
+    commit (4fae6f0fa86f92e6bc7429371b1e177ad0aaac66 "USB: handle LPM errors
+    during device suspend correctly") called usb_disable_remote_wakeup,
+    which won't be added until 3.12.
+    
+    This patch should be backported to kernels as old as 3.5, that
+    contain the commit 8306095fd2c1100e8244c09bf560f97aca5a311d "USB:
+    Disable USB 3.0 LPM in critical sections.".  There will be merge
+    conflicts, since LTM wasn't added until 3.6.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Sarah Sharp 
+    Cc: stable@vger.kernel.org
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 558313de4911..8287953e066c 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2918,7 +2918,6 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ {
+ 	struct usb_hub	*hub = usb_hub_to_struct_hub(udev->parent);
+ 	struct usb_port *port_dev = hub->ports[udev->portnum - 1];
+-	enum pm_qos_flags_status pm_qos_stat;
+ 	int		port1 = udev->portnum;
+ 	int		status;
+ 	bool		really_suspend = true;
+@@ -2956,7 +2955,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ 					status);
+ 			/* bail if autosuspend is requested */
+ 			if (PMSG_IS_AUTO(msg))
+-				return status;
++				goto err_wakeup;
+ 		}
+ 	}
+ 
+@@ -2965,14 +2964,16 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ 		usb_set_usb2_hardware_lpm(udev, 0);
+ 
+ 	if (usb_disable_ltm(udev)) {
+-		dev_err(&udev->dev, "%s Failed to disable LTM before suspend\n.",
+-				__func__);
+-		return -ENOMEM;
++		dev_err(&udev->dev, "Failed to disable LTM before suspend\n.");
++		status = -ENOMEM;
++		if (PMSG_IS_AUTO(msg))
++			goto err_ltm;
+ 	}
+ 	if (usb_unlocked_disable_lpm(udev)) {
+-		dev_err(&udev->dev, "%s Failed to disable LPM before suspend\n.",
+-				__func__);
+-		return -ENOMEM;
++		dev_err(&udev->dev, "Failed to disable LPM before suspend\n.");
++		status = -ENOMEM;
++		if (PMSG_IS_AUTO(msg))
++			goto err_lpm3;
+ 	}
+ 
+ 	/* see 7.1.7.6 */
+@@ -3000,28 +3001,31 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ 	if (status) {
+ 		dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",
+ 				port1, status);
+-		/* paranoia:  "should not happen" */
+-		if (udev->do_remote_wakeup) {
+-			if (!hub_is_superspeed(hub->hdev)) {
+-				(void) usb_control_msg(udev,
+-						usb_sndctrlpipe(udev, 0),
+-						USB_REQ_CLEAR_FEATURE,
+-						USB_RECIP_DEVICE,
+-						USB_DEVICE_REMOTE_WAKEUP, 0,
+-						NULL, 0,
+-						USB_CTRL_SET_TIMEOUT);
+-			} else
+-				(void) usb_disable_function_remotewakeup(udev);
+-
+-		}
+ 
++		/* Try to enable USB3 LPM and LTM again */
++		usb_unlocked_enable_lpm(udev);
++ err_lpm3:
++		usb_enable_ltm(udev);
++ err_ltm:
+ 		/* Try to enable USB2 hardware LPM again */
+ 		if (udev->usb2_hw_lpm_capable == 1)
+ 			usb_set_usb2_hardware_lpm(udev, 1);
+ 
+-		/* Try to enable USB3 LTM and LPM again */
+-		usb_enable_ltm(udev);
+-		usb_unlocked_enable_lpm(udev);
++		if (udev->do_remote_wakeup) {
++			if (udev->speed < USB_SPEED_SUPER)
++				usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
++						USB_REQ_CLEAR_FEATURE,
++						USB_RECIP_DEVICE,
++						USB_DEVICE_REMOTE_WAKEUP, 0,
++						NULL, 0, USB_CTRL_SET_TIMEOUT);
++			else
++				usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
++						USB_REQ_CLEAR_FEATURE,
++						USB_RECIP_INTERFACE,
++						USB_INTRF_FUNC_SUSPEND, 0,
++						NULL, 0, USB_CTRL_SET_TIMEOUT);
++		}
++ err_wakeup:
+ 
+ 		/* System sleep transitions should never fail */
+ 		if (!PMSG_IS_AUTO(msg))
+@@ -3043,14 +3047,15 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ 	 * Check whether current status meets the requirement of
+ 	 * usb port power off mechanism
+ 	 */
+-	pm_qos_stat = dev_pm_qos_flags(&port_dev->dev,
+-			PM_QOS_FLAG_NO_POWER_OFF);
+-	if (!udev->do_remote_wakeup
+-			&& pm_qos_stat != PM_QOS_FLAGS_ALL
+-			&& udev->persist_enabled
+-			&& !status) {
+-		pm_runtime_put_sync(&port_dev->dev);
+-		port_dev->did_runtime_put = true;
++	if (status == 0 && !udev->do_remote_wakeup && udev->persist_enabled) {
++		enum pm_qos_flags_status pm_qos_stat;
++
++		pm_qos_stat = dev_pm_qos_flags(&port_dev->dev,
++				PM_QOS_FLAG_NO_POWER_OFF);
++		if (pm_qos_stat != PM_QOS_FLAGS_ALL) {
++			pm_runtime_put_sync(&port_dev->dev);
++			port_dev->did_runtime_put = true;
++		}
+ 	}
+ 
+ 	usb_mark_last_busy(hub->hdev);

commit 24f531371de17010f2b1b57d90e42240032e7733
+Author: Alan Stern 
+Date:   Wed Aug 7 10:58:05 2013 -0400
+
+    USB: EHCI: accept very late isochronous URBs
+    
+    Since commits 4005ad4390bf (EHCI: implement new semantics for
+    URB_ISO_ASAP) and c75c5ab575af (ALSA: USB: adjust for changed 3.8 USB
+    API) became widely distributed, people have been experiencing problems
+    with audio transfers.  The slightest underrun causes complete failure,
+    requiring the audio stream to be restarted.
+    
+    It turns out that the current isochronous API doesn't handle underruns
+    in the best way.  The ALSA developers would much rather have transfers
+    that are submitted too late be accepted and complete in the normal
+    fashion, rather than being refused outright.
+    
+    This patch implements the requested approach.  When an isochronous URB
+    submission is so late that all its scheduled slots have already
+    expired, a debugging message will be printed in the log and the URB
+    will be accepted as usual.  Assuming it was submitted by a completion
+    handler (which is normally the case), it will complete shortly
+    thereafter with all the usb_iso_packet_descriptor status fields marked
+    -EXDEV.
+    
+    This fixes (for ehci-hcd)
+    
+            https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1191603
+    
+    It should be applied to all kernels that include commit 4005ad4390bf.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Maksim Boyko 
+    CC: Clemens Ladisch 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index f80d0330d548..8e3c878f38cf 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1391,21 +1391,20 @@ iso_stream_schedule (
+ 
+ 		/* Behind the scheduling threshold? */
+ 		if (unlikely(start < next)) {
++			unsigned now2 = (now - base) & (mod - 1);
+ 
+ 			/* USB_ISO_ASAP: Round up to the first available slot */
+ 			if (urb->transfer_flags & URB_ISO_ASAP)
+ 				start += (next - start + period - 1) & -period;
+ 
+ 			/*
+-			 * Not ASAP: Use the next slot in the stream.  If
+-			 * the entire URB falls before the threshold, fail.
++			 * Not ASAP: Use the next slot in the stream,
++			 * no matter what.
+ 			 */
+-			else if (start + span - period < next) {
+-				ehci_dbg(ehci, "iso urb late %p (%u+%u < %u)\n",
++			else if (start + span - period < now2) {
++				ehci_dbg(ehci, "iso underrun %p (%u+%u < %u)\n",
+ 						urb, start + base,
+-						span - period, next + base);
+-				status = -EXDEV;
+-				goto fail;
++						span - period, now2 + base);
+ 			}
+ 		}
+ 

commit 6753f4cf29046f4a2ae68c3a93bf6e6e6dce9fb7
+Author: Alan Stern 
+Date:   Thu Aug 1 17:09:28 2013 -0400
+
+    USB: EHCI: don't depend on hardware for tracking port resets and resumes
+    
+    In theory, an EHCI controller can turn off the PORT_RESUME or
+    PORT_RESET bits in a port status register all by itself (and some
+    controllers actually do this).  We shouldn't depend on these bits
+    being set correctly.
+    
+    This patch rearranges the code in ehci-hcd that handles completion of
+    port resets and resumes.  We guarantee that ehci->reset_done[portnum]
+    is nonzero if a reset or resume is in progress, and that the portnum
+    bit is set in ehci->resuming_ports if the operation is a resume.  (To
+    help enforce this guarantee, the patch prevents suspended ports from
+    being reset.)  Therefore it's not necessary to look at the port status
+    bits to learn what's going on.
+    
+    The patch looks bigger than it really is, because it changes the
+    indentation level of a sizeable region of code.  Most of what it
+    actually does is interchange some tests.  The only functional changes
+    are testing reset_done and resuming_ports rather than PORT_RESUME and
+    PORT_RESET, removing a now-unnecessary check for spontaneous
+    resets of the PORT_RESUME and PORT_RESET bits, and preventing a
+    suspended or resuming port from being reset.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 6d0e59306ed9..6e69ee1a3371 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -867,11 +867,11 @@ static int ehci_hub_control (
+ 			}
+ 		}
+ 
+-		/* whoever resumes must GetPortStatus to complete it!! */
+-		if (temp & PORT_RESUME) {
++		/* no reset or resume pending */
++		if (!ehci->reset_done[wIndex]) {
+ 
+ 			/* Remote Wakeup received? */
+-			if (!ehci->reset_done[wIndex]) {
++			if (temp & PORT_RESUME) {
+ 				/* resume signaling for 20 msec */
+ 				ehci->reset_done[wIndex] = jiffies
+ 						+ msecs_to_jiffies(20);
+@@ -882,35 +882,32 @@ static int ehci_hub_control (
+ 						ehci->reset_done[wIndex]);
+ 			}
+ 
+-			/* resume completed? */
+-			else if (time_after_eq(jiffies,
+-					ehci->reset_done[wIndex])) {
+-				clear_bit(wIndex, &ehci->suspended_ports);
+-				set_bit(wIndex, &ehci->port_c_suspend);
+-				ehci->reset_done[wIndex] = 0;
+-				usb_hcd_end_port_resume(&hcd->self, wIndex);
+-
+-				/* stop resume signaling */
+-				temp &= ~(PORT_RWC_BITS |
+-						PORT_SUSPEND | PORT_RESUME);
+-				ehci_writel(ehci, temp, status_reg);
+-				clear_bit(wIndex, &ehci->resuming_ports);
+-				retval = ehci_handshake(ehci, status_reg,
+-					   PORT_RESUME, 0, 2000 /* 2msec */);
+-				if (retval != 0) {
+-					ehci_err(ehci,
+-						"port %d resume error %d\n",
++		/* reset or resume not yet complete */
++		} else if (!time_after_eq(jiffies, ehci->reset_done[wIndex])) {
++			;	/* wait until it is complete */
++
++		/* resume completed */
++		} else if (test_bit(wIndex, &ehci->resuming_ports)) {
++			clear_bit(wIndex, &ehci->suspended_ports);
++			set_bit(wIndex, &ehci->port_c_suspend);
++			ehci->reset_done[wIndex] = 0;
++			usb_hcd_end_port_resume(&hcd->self, wIndex);
++
++			/* stop resume signaling */
++			temp &= ~(PORT_RWC_BITS | PORT_SUSPEND | PORT_RESUME);
++			ehci_writel(ehci, temp, status_reg);
++			clear_bit(wIndex, &ehci->resuming_ports);
++			retval = ehci_handshake(ehci, status_reg,
++					PORT_RESUME, 0, 2000 /* 2msec */);
++			if (retval != 0) {
++				ehci_err(ehci, "port %d resume error %d\n",
+ 						wIndex + 1, retval);
+-					goto error;
+-				}
+-				temp = ehci_readl(ehci, status_reg);
++				goto error;
+ 			}
+-		}
++			temp = ehci_readl(ehci, status_reg);
+ 
+ 		/* whoever resets must GetPortStatus to complete it!! */
+-		if ((temp & PORT_RESET)
+-				&& time_after_eq(jiffies,
+-					ehci->reset_done[wIndex])) {
++		} else {
+ 			status |= USB_PORT_STAT_C_RESET << 16;
+ 			ehci->reset_done [wIndex] = 0;
+ 
+@@ -933,11 +930,6 @@ static int ehci_hub_control (
+ 					ehci_readl(ehci, status_reg));
+ 		}
+ 
+-		if (!(temp & (PORT_RESUME|PORT_RESET))) {
+-			ehci->reset_done[wIndex] = 0;
+-			clear_bit(wIndex, &ehci->resuming_ports);
+-		}
+-
+ 		/* transfer dedicated ports to the companion hc */
+ 		if ((temp & PORT_CONNECT) &&
+ 				test_bit(wIndex, &ehci->companion_ports)) {
+@@ -1058,7 +1050,7 @@ static int ehci_hub_control (
+ 						status_reg);
+ 			break;
+ 		case USB_PORT_FEAT_RESET:
+-			if (temp & PORT_RESUME)
++			if (temp & (PORT_SUSPEND|PORT_RESUME))
+ 				goto error;
+ 			/* line status bits may report this as low speed,
+ 			 * which can be fine if this root hub has a

commit 3a20446f02bfb71d68ae9ec673268bb7823f878c
+Author: Alan Stern 
+Date:   Thu Aug 1 17:09:23 2013 -0400
+
+    USB: EHCI: keep better track of resuming ports
+    
+    The ehci-hcd driver isn't as careful as it should be about the way it
+    uses ehci->resuming_ports.  One of the omissions was fixed recently by
+    commit 47a64a13d54 (USB: EHCI: Fix resume signalling on remote
+    wakeup), but there are other places that need attention:
+    
+            When a port's suspend feature is explicitly cleared, the
+            corresponding bit in resuming_ports should be set and the core
+            should be notified about the port resume.
+    
+            We don't need to clear a resuming_ports bit when a reset
+            completes.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 6dce37555c4f..6d0e59306ed9 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -801,6 +801,8 @@ static int ehci_hub_control (
+ 			ehci_writel(ehci, temp | PORT_RESUME, status_reg);
+ 			ehci->reset_done[wIndex] = jiffies
+ 					+ msecs_to_jiffies(20);
++			set_bit(wIndex, &ehci->resuming_ports);
++			usb_hcd_start_port_resume(&hcd->self, wIndex);
+ 			break;
+ 		case USB_PORT_FEAT_C_SUSPEND:
+ 			clear_bit(wIndex, &ehci->port_c_suspend);
+@@ -911,7 +913,6 @@ static int ehci_hub_control (
+ 					ehci->reset_done[wIndex])) {
+ 			status |= USB_PORT_STAT_C_RESET << 16;
+ 			ehci->reset_done [wIndex] = 0;
+-			clear_bit(wIndex, &ehci->resuming_ports);
+ 
+ 			/* force reset to complete */
+ 			ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_RESET),

commit 4fae6f0fa86f92e6bc7429371b1e177ad0aaac66
+Author: Alan Stern 
+Date:   Tue Jul 30 15:39:02 2013 -0400
+
+    USB: handle LPM errors during device suspend correctly
+    
+    The hub driver's usb_port_suspend() routine doesn't handle errors
+    related to Link Power Management properly.  It always returns failure,
+    it doesn't try to clean up the wakeup setting, (in the case of system
+    sleep) it doesn't try to go ahead with the port suspend regardless,
+    and it doesn't try to apply the new power-off mechanism.
+    
+    This patch fixes these problems.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Sarah Sharp 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index c376c8bad40c..0416f835cfee 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2948,7 +2948,6 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ {
+ 	struct usb_hub	*hub = usb_hub_to_struct_hub(udev->parent);
+ 	struct usb_port *port_dev = hub->ports[udev->portnum - 1];
+-	enum pm_qos_flags_status pm_qos_stat;
+ 	int		port1 = udev->portnum;
+ 	int		status;
+ 	bool		really_suspend = true;
+@@ -2966,7 +2965,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ 					status);
+ 			/* bail if autosuspend is requested */
+ 			if (PMSG_IS_AUTO(msg))
+-				return status;
++				goto err_wakeup;
+ 		}
+ 	}
+ 
+@@ -2975,14 +2974,16 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ 		usb_set_usb2_hardware_lpm(udev, 0);
+ 
+ 	if (usb_disable_ltm(udev)) {
+-		dev_err(&udev->dev, "%s Failed to disable LTM before suspend\n.",
+-				__func__);
+-		return -ENOMEM;
++		dev_err(&udev->dev, "Failed to disable LTM before suspend\n.");
++		status = -ENOMEM;
++		if (PMSG_IS_AUTO(msg))
++			goto err_ltm;
+ 	}
+ 	if (usb_unlocked_disable_lpm(udev)) {
+-		dev_err(&udev->dev, "%s Failed to disable LPM before suspend\n.",
+-				__func__);
+-		return -ENOMEM;
++		dev_err(&udev->dev, "Failed to disable LPM before suspend\n.");
++		status = -ENOMEM;
++		if (PMSG_IS_AUTO(msg))
++			goto err_lpm3;
+ 	}
+ 
+ 	/* see 7.1.7.6 */
+@@ -3010,17 +3011,19 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ 	if (status) {
+ 		dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",
+ 				port1, status);
+-		/* paranoia:  "should not happen" */
+-		if (udev->do_remote_wakeup)
+-			(void) usb_disable_remote_wakeup(udev);
+ 
++		/* Try to enable USB3 LPM and LTM again */
++		usb_unlocked_enable_lpm(udev);
++ err_lpm3:
++		usb_enable_ltm(udev);
++ err_ltm:
+ 		/* Try to enable USB2 hardware LPM again */
+ 		if (udev->usb2_hw_lpm_capable == 1)
+ 			usb_set_usb2_hardware_lpm(udev, 1);
+ 
+-		/* Try to enable USB3 LTM and LPM again */
+-		usb_enable_ltm(udev);
+-		usb_unlocked_enable_lpm(udev);
++		if (udev->do_remote_wakeup)
++			(void) usb_disable_remote_wakeup(udev);
++ err_wakeup:
+ 
+ 		/* System sleep transitions should never fail */
+ 		if (!PMSG_IS_AUTO(msg))
+@@ -3042,14 +3045,15 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ 	 * Check whether current status meets the requirement of
+ 	 * usb port power off mechanism
+ 	 */
+-	pm_qos_stat = dev_pm_qos_flags(&port_dev->dev,
+-			PM_QOS_FLAG_NO_POWER_OFF);
+-	if (!udev->do_remote_wakeup
+-			&& pm_qos_stat != PM_QOS_FLAGS_ALL
+-			&& udev->persist_enabled
+-			&& !status) {
+-		pm_runtime_put_sync(&port_dev->dev);
+-		port_dev->did_runtime_put = true;
++	if (status == 0 && !udev->do_remote_wakeup && udev->persist_enabled) {
++		enum pm_qos_flags_status pm_qos_stat;
++
++		pm_qos_stat = dev_pm_qos_flags(&port_dev->dev,
++				PM_QOS_FLAG_NO_POWER_OFF);
++		if (pm_qos_stat != PM_QOS_FLAGS_ALL) {
++			pm_runtime_put_sync(&port_dev->dev);
++			port_dev->did_runtime_put = true;
++		}
+ 	}
+ 
+ 	usb_mark_last_busy(hub->hdev);

commit 28e861658e23ca94692f98e245d254c75c8088a7
+Author: Alan Stern 
+Date:   Tue Jul 30 15:37:33 2013 -0400
+
+    USB: refactor code for enabling/disabling remote wakeup
+    
+    The hub driver is inconsistent in its organization of code for
+    enabling and disabling remote wakeup.  There is a special routine to
+    disable wakeup for SuperSpeed devices but not for slower devices, and
+    there is no special routine to enable wakeup.
+    
+    This patch refactors the code.  It renames and changes the existing
+    function to make it handle both SuperSpeed and non-SuperSpeed devices,
+    and it adds a corresponding routine to enable remote wakeup.  It also
+    changes the speed determination to look at the device's speed rather
+    than the speed of the parent hub -- this shouldn't make any difference
+    because a SuperSpeed device always has to be attached to a SuperSpeed
+    hub and conversely.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 11a92198bfc7..c376c8bad40c 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2838,18 +2838,50 @@ void usb_enable_ltm(struct usb_device *udev)
+ EXPORT_SYMBOL_GPL(usb_enable_ltm);
+ 
+ /*
+- * usb_disable_function_remotewakeup - disable usb3.0
+- * device's function remote wakeup
++ * usb_enable_remote_wakeup - enable remote wakeup for a device
+  * @udev: target device
+  *
+- * Assume there's only one function on the USB 3.0
+- * device and disable remote wake for the first
+- * interface. FIXME if the interface association
+- * descriptor shows there's more than one function.
++ * For USB-2 devices: Set the device's remote wakeup feature.
++ *
++ * For USB-3 devices: Assume there's only one function on the device and
++ * enable remote wake for the first interface.  FIXME if the interface
++ * association descriptor shows there's more than one function.
+  */
+-static int usb_disable_function_remotewakeup(struct usb_device *udev)
++static int usb_enable_remote_wakeup(struct usb_device *udev)
+ {
+-	return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
++	if (udev->speed < USB_SPEED_SUPER)
++		return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
++				USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
++				USB_DEVICE_REMOTE_WAKEUP, 0, NULL, 0,
++				USB_CTRL_SET_TIMEOUT);
++	else
++		return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
++				USB_REQ_SET_FEATURE, USB_RECIP_INTERFACE,
++				USB_INTRF_FUNC_SUSPEND,
++				USB_INTRF_FUNC_SUSPEND_RW |
++					USB_INTRF_FUNC_SUSPEND_LP,
++				NULL, 0, USB_CTRL_SET_TIMEOUT);
++}
++
++/*
++ * usb_disable_remote_wakeup - disable remote wakeup for a device
++ * @udev: target device
++ *
++ * For USB-2 devices: Clear the device's remote wakeup feature.
++ *
++ * For USB-3 devices: Assume there's only one function on the device and
++ * disable remote wake for the first interface.  FIXME if the interface
++ * association descriptor shows there's more than one function.
++ */
++static int usb_disable_remote_wakeup(struct usb_device *udev)
++{
++	if (udev->speed < USB_SPEED_SUPER)
++		return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
++				USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE,
++				USB_DEVICE_REMOTE_WAKEUP, 0, NULL, 0,
++				USB_CTRL_SET_TIMEOUT);
++	else
++		return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ 				USB_REQ_CLEAR_FEATURE, USB_RECIP_INTERFACE,
+ 				USB_INTRF_FUNC_SUSPEND,	0, NULL, 0,
+ 				USB_CTRL_SET_TIMEOUT);
+@@ -2928,27 +2960,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ 	 * we don't explicitly enable it here.
+ 	 */
+ 	if (udev->do_remote_wakeup) {
+-		if (!hub_is_superspeed(hub->hdev)) {
+-			status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+-					USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
+-					USB_DEVICE_REMOTE_WAKEUP, 0,
+-					NULL, 0,
+-					USB_CTRL_SET_TIMEOUT);
+-		} else {
+-			/* Assume there's only one function on the USB 3.0
+-			 * device and enable remote wake for the first
+-			 * interface. FIXME if the interface association
+-			 * descriptor shows there's more than one function.
+-			 */
+-			status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+-					USB_REQ_SET_FEATURE,
+-					USB_RECIP_INTERFACE,
+-					USB_INTRF_FUNC_SUSPEND,
+-					USB_INTRF_FUNC_SUSPEND_RW |
+-					USB_INTRF_FUNC_SUSPEND_LP,
+-					NULL, 0,
+-					USB_CTRL_SET_TIMEOUT);
+-		}
++		status = usb_enable_remote_wakeup(udev);
+ 		if (status) {
+ 			dev_dbg(&udev->dev, "won't remote wakeup, status %d\n",
+ 					status);
+@@ -2999,19 +3011,8 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ 		dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",
+ 				port1, status);
+ 		/* paranoia:  "should not happen" */
+-		if (udev->do_remote_wakeup) {
+-			if (!hub_is_superspeed(hub->hdev)) {
+-				(void) usb_control_msg(udev,
+-						usb_sndctrlpipe(udev, 0),
+-						USB_REQ_CLEAR_FEATURE,
+-						USB_RECIP_DEVICE,
+-						USB_DEVICE_REMOTE_WAKEUP, 0,
+-						NULL, 0,
+-						USB_CTRL_SET_TIMEOUT);
+-			} else
+-				(void) usb_disable_function_remotewakeup(udev);
+-
+-		}
++		if (udev->do_remote_wakeup)
++			(void) usb_disable_remote_wakeup(udev);
+ 
+ 		/* Try to enable USB2 hardware LPM again */
+ 		if (udev->usb2_hw_lpm_capable == 1)
+@@ -3119,22 +3120,15 @@ static int finish_port_resume(struct usb_device *udev)
+ 	 * udev->reset_resume
+ 	 */
+ 	} else if (udev->actconfig && !udev->reset_resume) {
+-		if (!hub_is_superspeed(udev->parent)) {
++		if (udev->speed < USB_SPEED_SUPER) {
+ 			if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP))
+-				status = usb_control_msg(udev,
+-						usb_sndctrlpipe(udev, 0),
+-						USB_REQ_CLEAR_FEATURE,
+-						USB_RECIP_DEVICE,
+-						USB_DEVICE_REMOTE_WAKEUP, 0,
+-						NULL, 0,
+-						USB_CTRL_SET_TIMEOUT);
++				status = usb_disable_remote_wakeup(udev);
+ 		} else {
+ 			status = usb_get_status(udev, USB_RECIP_INTERFACE, 0,
+ 					&devstatus);
+ 			if (!status && devstatus & (USB_INTRF_STAT_FUNC_RW_CAP
+ 					| USB_INTRF_STAT_FUNC_RW))
+-				status =
+-					usb_disable_function_remotewakeup(udev);
++				status = usb_disable_remote_wakeup(udev);
+ 		}
+ 
+ 		if (status)

commit 15b7336e02d998720c5ace47036f7e539365bb05
+Author: Alan Stern 
+Date:   Tue Jul 30 15:35:40 2013 -0400
+
+    USB: simplify the interface of usb_get_status()
+    
+    This patch simplifies the interface presented by usb_get_status().
+    Instead of forcing callers to check for the proper data length and
+    convert the status value to host byte order, the function will now
+    do these things itself.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index c881830af55f..11a92198bfc7 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1464,11 +1464,10 @@ static int hub_configure(struct usb_hub *hub,
+ 	 * and battery-powered root hubs (may provide just 8 mA).
+ 	 */
+ 	ret = usb_get_status(hdev, USB_RECIP_DEVICE, 0, &hubstatus);
+-	if (ret < 2) {
++	if (ret) {
+ 		message = "can't get hub status";
+ 		goto fail;
+ 	}
+-	le16_to_cpus(&hubstatus);
+ 	hcd = bus_to_hcd(hdev->bus);
+ 	if (hdev == hdev->bus->root_hub) {
+ 		if (hcd->power_budget > 0)
+@@ -3101,8 +3100,6 @@ static int finish_port_resume(struct usb_device *udev)
+ 	if (status == 0) {
+ 		devstatus = 0;
+ 		status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
+-		if (status >= 0)
+-			status = (status > 0 ? 0 : -ENODEV);
+ 
+ 		/* If a normal resume failed, try doing a reset-resume */
+ 		if (status && !udev->reset_resume && udev->persist_enabled) {
+@@ -3123,7 +3120,6 @@ static int finish_port_resume(struct usb_device *udev)
+ 	 */
+ 	} else if (udev->actconfig && !udev->reset_resume) {
+ 		if (!hub_is_superspeed(udev->parent)) {
+-			le16_to_cpus(&devstatus);
+ 			if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP))
+ 				status = usb_control_msg(udev,
+ 						usb_sndctrlpipe(udev, 0),
+@@ -3135,7 +3131,6 @@ static int finish_port_resume(struct usb_device *udev)
+ 		} else {
+ 			status = usb_get_status(udev, USB_RECIP_INTERFACE, 0,
+ 					&devstatus);
+-			le16_to_cpus(&devstatus);
+ 			if (!status && devstatus & (USB_INTRF_STAT_FUNC_RW_CAP
+ 					| USB_INTRF_STAT_FUNC_RW))
+ 				status =
+@@ -4481,11 +4476,10 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 
+ 			status = usb_get_status(udev, USB_RECIP_DEVICE, 0,
+ 					&devstat);
+-			if (status < 2) {
++			if (status) {
+ 				dev_dbg(&udev->dev, "get status %d ?\n", status);
+ 				goto loop_disable;
+ 			}
+-			le16_to_cpus(&devstat);
+ 			if ((devstat & (1 << USB_DEVICE_SELF_POWERED)) == 0) {
+ 				dev_err(&udev->dev,
+ 					"can't connect bus-powered hub "
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index e7ee1e451660..6549a975b0c5 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -934,13 +934,13 @@ int usb_get_device_descriptor(struct usb_device *dev, unsigned int size)
+  *
+  * This call is synchronous, and may not be used in an interrupt context.
+  *
+- * Returns the number of bytes received on success, or else the status code
+- * returned by the underlying usb_control_msg() call.
++ * Returns 0 and the status value in *@data (in host byte order) on success,
++ * or else the status code from the underlying usb_control_msg() call.
+  */
+ int usb_get_status(struct usb_device *dev, int type, int target, void *data)
+ {
+ 	int ret;
+-	u16 *status = kmalloc(sizeof(*status), GFP_KERNEL);
++	__le16 *status = kmalloc(sizeof(*status), GFP_KERNEL);
+ 
+ 	if (!status)
+ 		return -ENOMEM;
+@@ -949,7 +949,12 @@ int usb_get_status(struct usb_device *dev, int type, int target, void *data)
+ 		USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, status,
+ 		sizeof(*status), USB_CTRL_GET_TIMEOUT);
+ 
+-	*(u16 *)data = *status;
++	if (ret == 2) {
++		*(u16 *) data = le16_to_cpu(*status);
++		ret = 0;
++	} else if (ret >= 0) {
++		ret = -EIO;
++	}
+ 	kfree(status);
+ 	return ret;
+ }
+diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
+index 8b4ca1cb450a..aa28ac8c7607 100644
+--- a/drivers/usb/misc/usbtest.c
++++ b/drivers/usb/misc/usbtest.c
+@@ -747,9 +747,9 @@ static int ch9_postconfig(struct usbtest_dev *dev)
+ 
+ 	/* [9.4.5] get_status always works */
+ 	retval = usb_get_status(udev, USB_RECIP_DEVICE, 0, dev->buf);
+-	if (retval != 2) {
++	if (retval) {
+ 		dev_err(&iface->dev, "get dev status --> %d\n", retval);
+-		return (retval < 0) ? retval : -EDOM;
++		return retval;
+ 	}
+ 
+ 	/* FIXME configuration.bmAttributes says if we could try to set/clear
+@@ -758,9 +758,9 @@ static int ch9_postconfig(struct usbtest_dev *dev)
+ 
+ 	retval = usb_get_status(udev, USB_RECIP_INTERFACE,
+ 			iface->altsetting[0].desc.bInterfaceNumber, dev->buf);
+-	if (retval != 2) {
++	if (retval) {
+ 		dev_err(&iface->dev, "get interface status --> %d\n", retval);
+-		return (retval < 0) ? retval : -EDOM;
++		return retval;
+ 	}
+ 	/* FIXME get status for each endpoint in the interface */
+ 
+@@ -1351,7 +1351,6 @@ static int verify_halted(struct usbtest_dev *tdev, int ep, struct urb *urb)
+ 				ep, retval);
+ 		return retval;
+ 	}
+-	le16_to_cpus(&status);
+ 	if (status != 1) {
+ 		ERROR(tdev, "ep %02x bogus status: %04x != 1\n", ep, status);
+ 		return -EINVAL;

commit c4b51a431561f0bacc1740aa27f080bf95c4d6c7
+Author: Alan Stern 
+Date:   Thu Jul 11 14:58:23 2013 -0400
+
+    USB: remove redundant "#if"
+    
+    This patch removes a redundant nested "#ifdef CONFIG_PM" from the hub
+    driver.  It also adds a label to the "#endif" line corresponding to
+    the outer "#ifdef CONFIG_PM".
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 4191db32f12c..f735f6bc929c 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2829,7 +2829,6 @@ void usb_enable_ltm(struct usb_device *udev)
+ }
+ EXPORT_SYMBOL_GPL(usb_enable_ltm);
+ 
+-#ifdef	CONFIG_PM
+ /*
+  * usb_disable_function_remotewakeup - disable usb3.0
+  * device's function remote wakeup
+@@ -3249,8 +3248,6 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
+ 	return status;
+ }
+ 
+-#endif	/* CONFIG_PM */
+-
+ #ifdef	CONFIG_PM_RUNTIME
+ 
+ /* caller has locked udev */
+@@ -3811,7 +3808,8 @@ EXPORT_SYMBOL_GPL(usb_disable_ltm);
+ 
+ void usb_enable_ltm(struct usb_device *udev) { }
+ EXPORT_SYMBOL_GPL(usb_enable_ltm);
+-#endif
++
++#endif	/* CONFIG_PM */
+ 
+ 
+ /* USB 2.0 spec, 7.1.7.3 / fig 7-29:

commit e583d9db9960cf40e0bc8afee4946baa9d71596e
+Author: Alan Stern 
+Date:   Thu Jul 11 14:58:04 2013 -0400
+
+    USB: global suspend and remote wakeup don't mix
+    
+    The hub driver was recently changed to use "global" suspend for system
+    suspend transitions on non-SuperSpeed buses.  This means that we don't
+    suspend devices individually by setting the suspend feature on the
+    upstream hub port; instead devices all go into suspend automatically
+    when the root hub stops transmitting packets.  The idea was to save
+    time and to avoid certain kinds of wakeup races.
+    
+    Now it turns out that many hubs are buggy; they don't relay wakeup
+    requests from a downstream port to their upstream port if the
+    downstream port's suspend feature is not set (depending on the speed
+    of the downstream port, whether or not the hub is enabled for remote
+    wakeup, and possibly other factors).
+    
+    We can't have hubs dropping wakeup requests.  Therefore this patch
+    goes partway back to the old policy: It sets the suspend feature for a
+    port if the device attached to that port or any of its descendants is
+    enabled for wakeup.  People will still be able to benefit from the
+    time savings if they don't care about wakeup and leave it disabled on
+    all their devices.
+    
+    In order to accomplish this, the patch adds a new field to the usb_hub
+    structure: wakeup_enabled_descendants is a count of how many devices
+    below a suspended hub are enabled for remote wakeup.  A corresponding
+    new subroutine determines the number of wakeup-enabled devices at or
+    below an arbitrary suspended USB device.
+    
+    This should be applied to the 3.10 stable kernel.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Toralf Förster 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 4191db32f12c..c857471519e3 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2848,6 +2848,15 @@ static int usb_disable_function_remotewakeup(struct usb_device *udev)
+ 				USB_CTRL_SET_TIMEOUT);
+ }
+ 
++/* Count of wakeup-enabled devices at or below udev */
++static unsigned wakeup_enabled_descendants(struct usb_device *udev)
++{
++	struct usb_hub *hub = usb_hub_to_struct_hub(udev);
++
++	return udev->do_remote_wakeup +
++			(hub ? hub->wakeup_enabled_descendants : 0);
++}
++
+ /*
+  * usb_port_suspend - suspend a usb device's upstream port
+  * @udev: device that's no longer in active use, not a root hub
+@@ -2888,8 +2897,8 @@ static int usb_disable_function_remotewakeup(struct usb_device *udev)
+  * Linux (2.6) currently has NO mechanisms to initiate that:  no khubd
+  * timer, no SRP, no requests through sysfs.
+  *
+- * If Runtime PM isn't enabled or used, non-SuperSpeed devices really get
+- * suspended only when their bus goes into global suspend (i.e., the root
++ * If Runtime PM isn't enabled or used, non-SuperSpeed devices may not get
++ * suspended until their bus goes into global suspend (i.e., the root
+  * hub is suspended).  Nevertheless, we change @udev->state to
+  * USB_STATE_SUSPENDED as this is the device's "logical" state.  The actual
+  * upstream port setting is stored in @udev->port_is_suspended.
+@@ -2960,15 +2969,21 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ 	/* see 7.1.7.6 */
+ 	if (hub_is_superspeed(hub->hdev))
+ 		status = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_U3);
+-	else if (PMSG_IS_AUTO(msg))
+-		status = set_port_feature(hub->hdev, port1,
+-						USB_PORT_FEAT_SUSPEND);
++
+ 	/*
+ 	 * For system suspend, we do not need to enable the suspend feature
+ 	 * on individual USB-2 ports.  The devices will automatically go
+ 	 * into suspend a few ms after the root hub stops sending packets.
+ 	 * The USB 2.0 spec calls this "global suspend".
++	 *
++	 * However, many USB hubs have a bug: They don't relay wakeup requests
++	 * from a downstream port if the port's suspend feature isn't on.
++	 * Therefore we will turn on the suspend feature if udev or any of its
++	 * descendants is enabled for remote wakeup.
+ 	 */
++	else if (PMSG_IS_AUTO(msg) || wakeup_enabled_descendants(udev) > 0)
++		status = set_port_feature(hub->hdev, port1,
++				USB_PORT_FEAT_SUSPEND);
+ 	else {
+ 		really_suspend = false;
+ 		status = 0;
+@@ -3003,15 +3018,16 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ 		if (!PMSG_IS_AUTO(msg))
+ 			status = 0;
+ 	} else {
+-		/* device has up to 10 msec to fully suspend */
+ 		dev_dbg(&udev->dev, "usb %ssuspend, wakeup %d\n",
+ 				(PMSG_IS_AUTO(msg) ? "auto-" : ""),
+ 				udev->do_remote_wakeup);
+-		usb_set_device_state(udev, USB_STATE_SUSPENDED);
+ 		if (really_suspend) {
+ 			udev->port_is_suspended = 1;
++
++			/* device has up to 10 msec to fully suspend */
+ 			msleep(10);
+ 		}
++		usb_set_device_state(udev, USB_STATE_SUSPENDED);
+ 	}
+ 
+ 	/*
+@@ -3293,7 +3309,11 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+ 	unsigned		port1;
+ 	int			status;
+ 
+-	/* Warn if children aren't already suspended */
++	/*
++	 * Warn if children aren't already suspended.
++	 * Also, add up the number of wakeup-enabled descendants.
++	 */
++	hub->wakeup_enabled_descendants = 0;
+ 	for (port1 = 1; port1 <= hdev->maxchild; port1++) {
+ 		struct usb_device	*udev;
+ 
+@@ -3303,6 +3323,9 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+ 			if (PMSG_IS_AUTO(msg))
+ 				return -EBUSY;
+ 		}
++		if (udev)
++			hub->wakeup_enabled_descendants +=
++					wakeup_enabled_descendants(udev);
+ 	}
+ 
+ 	if (hdev->do_remote_wakeup && hub->quirk_check_port_auto_suspend) {
+diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
+index 6508e02b3dac..4e4790dea343 100644
+--- a/drivers/usb/core/hub.h
++++ b/drivers/usb/core/hub.h
+@@ -59,6 +59,9 @@ struct usb_hub {
+ 	struct usb_tt		tt;		/* Transaction Translator */
+ 
+ 	unsigned		mA_per_port;	/* current for each child */
++#ifdef	CONFIG_PM
++	unsigned		wakeup_enabled_descendants;
++#endif
+ 
+ 	unsigned		limited_power:1;
+ 	unsigned		quiescing:1;

commit 36ff66db3fb5642906e46e73ca9cf92f1c5974ff
+Author: Alan Stern 
+Date:   Thu Jun 27 15:27:07 2013 -0400
+
+    USB: move the definition of USB_MAXCHILDREN
+    
+    The USB_MAXCHILDREN symbol is used in include/uapi/linux/usb/ch11.h, a
+    user-mode header, even though it is defined in include/linux/usb.h,
+    which is kernel-only.  This causes compile-time errors when user
+    programs try to #include linux/usb/ch11.h.
+    
+    This patch fixes the problem by moving the definition of USB_MAXCHILDREN
+    into ch11.h.  It also gets rid of unneeded parentheses.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index a232b7ece1f6..0eec2689b955 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -367,17 +367,6 @@ struct usb_bus {
+ 
+ /* ----------------------------------------------------------------------- */
+ 
+-/* This is arbitrary.
+- * From USB 2.0 spec Table 11-13, offset 7, a hub can
+- * have up to 255 ports. The most yet reported is 10.
+- *
+- * Current Wireless USB host hardware (Intel i1480 for example) allows
+- * up to 22 devices to connect. Upcoming hardware might raise that
+- * limit. Because the arrays need to add a bit for hub status data, we
+- * do 31, so plus one evens out to four bytes.
+- */
+-#define USB_MAXCHILDREN		(31)
+-
+ struct usb_tt;
+ 
+ enum usb_device_removable {
+diff --git a/include/uapi/linux/usb/ch11.h b/include/uapi/linux/usb/ch11.h
+index 7692dc69ccf7..331499d597fa 100644
+--- a/include/uapi/linux/usb/ch11.h
++++ b/include/uapi/linux/usb/ch11.h
+@@ -11,6 +11,17 @@
+ 
+ #include 	/* __u8 etc */
+ 
++/* This is arbitrary.
++ * From USB 2.0 spec Table 11-13, offset 7, a hub can
++ * have up to 255 ports. The most yet reported is 10.
++ *
++ * Current Wireless USB host hardware (Intel i1480 for example) allows
++ * up to 22 devices to connect. Upcoming hardware might raise that
++ * limit. Because the arrays need to add a bit for hub status data, we
++ * use 31, so plus one evens out to four bytes.
++ */
++#define USB_MAXCHILDREN		31
++
+ /*
+  * Hub request types
+  */

commit 908b961326b2ecfbf494c9b2f206847d925f269d
+Author: Alan Stern 
+Date:   Fri Jul 12 11:06:21 2013 -0400
+
+    usb: gadget: don't fail when DMA isn't present
+    
+    When CONFIG_HAS_DMA isn't enabled, the UDC core gets build errors:
+    
+    drivers/built-in.o: In function `dma_set_coherent_mask':
+    include/linux/dma-mapping.h:93: undefined reference to `dma_supported'
+    include/linux/dma-mapping.h:93: undefined reference to `dma_supported'
+    drivers/built-in.o: In function `usb_gadget_unmap_request':
+    drivers/usb/gadget/udc-core.c:91: undefined reference to `dma_unmap_sg'
+    drivers/usb/gadget/udc-core.c:96: undefined reference to `dma_unmap_single'
+    drivers/built-in.o: In function `usb_gadget_map_request':
+    drivers/usb/gadget/udc-core.c:62: undefined reference to `dma_map_sg'
+    drivers/usb/gadget/udc-core.c:71: undefined reference to `dma_map_single'
+    drivers/usb/gadget/udc-core.c:74: undefined reference to `dma_mapping_error'
+    
+    Prevent this by protecting the DMA API routines with preprocessor tests.
+    
+    Signed-off-by: Alan Stern 
+    CC: Geert Uytterhoeven 
+    Acked-by: Alexander Shishkin 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c
+index ffd8fa541101..c28ac9872030 100644
+--- a/drivers/usb/gadget/udc-core.c
++++ b/drivers/usb/gadget/udc-core.c
+@@ -50,6 +50,8 @@ static DEFINE_MUTEX(udc_lock);
+ 
+ /* ------------------------------------------------------------------------- */
+ 
++#ifdef	CONFIG_HAS_DMA
++
+ int usb_gadget_map_request(struct usb_gadget *gadget,
+ 		struct usb_request *req, int is_in)
+ {
+@@ -99,6 +101,8 @@ void usb_gadget_unmap_request(struct usb_gadget *gadget,
+ }
+ EXPORT_SYMBOL_GPL(usb_gadget_unmap_request);
+ 
++#endif	/* CONFIG_HAS_DMA */
++
+ /* ------------------------------------------------------------------------- */
+ 
+ void usb_gadget_set_state(struct usb_gadget *gadget,
+@@ -194,9 +198,11 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
+ 	dev_set_name(&gadget->dev, "gadget");
+ 	gadget->dev.parent = parent;
+ 
++#ifdef	CONFIG_HAS_DMA
+ 	dma_set_coherent_mask(&gadget->dev, parent->coherent_dma_mask);
+ 	gadget->dev.dma_parms = parent->dma_parms;
+ 	gadget->dev.dma_mask = parent->dma_mask;
++#endif
+ 
+ 	if (release)
+ 		gadget->dev.release = release;

commit 43d51af489126305dbacc1b8ebd1ce4797d277ea
+Author: Alan Stern 
+Date:   Mon Jun 3 21:49:59 2013 +0200
+
+    PM / Runtime: Update .runtime_idle() callback documentation
+    
+    Runtime PM documentation needs to be updated after the previous
+    change of the rpm_idle() behavior, so modify it as appropriate.
+    
+    [rjw: Subject and changelog]
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt
+index 6c470c71ba27..71d8fe4e75d3 100644
+--- a/Documentation/power/runtime_pm.txt
++++ b/Documentation/power/runtime_pm.txt
+@@ -144,8 +144,12 @@ The action performed by the idle callback is totally dependent on the subsystem
+ (or driver) in question, but the expected and recommended action is to check
+ if the device can be suspended (i.e. if all of the conditions necessary for
+ suspending the device are satisfied) and to queue up a suspend request for the
+-device in that case.  The value returned by this callback is ignored by the PM
+-core.
++device in that case.  If there is no idle callback, or if the callback returns
++0, then the PM core will attempt to carry out a runtime suspend of the device;
++in essence, it will call pm_runtime_suspend() directly.  To prevent this (for
++example, if the callback routine has started a delayed suspend), the routine
++should return a non-zero value.  Negative error return codes are ignored by the
++PM core.
+ 
+ The helper functions provided by the PM core, described in Section 4, guarantee
+ that the following constraints are met with respect to runtime PM callbacks for
+@@ -301,9 +305,10 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
+       removing the device from device hierarchy
+ 
+   int pm_runtime_idle(struct device *dev);
+-    - execute the subsystem-level idle callback for the device; returns 0 on
+-      success or error code on failure, where -EINPROGRESS means that
+-      ->runtime_idle() is already being executed
++    - execute the subsystem-level idle callback for the device; returns an
++      error code on failure, where -EINPROGRESS means that ->runtime_idle() is
++      already being executed; if there is no callback or the callback returns 0
++      then run pm_runtime_suspend(dev) and return its result
+ 
+   int pm_runtime_suspend(struct device *dev);
+     - execute the subsystem-level suspend callback for the device; returns 0 on

commit f467ff4c7dd736b4a3c7e715efed763c0b021838
+Author: Alan Stern 
+Date:   Wed May 29 13:19:10 2013 -0400
+
+    USB: FHCI: upgrade the isochronous API
+    
+    This patch attempts to fix the isochronous API in the fhci-hcd
+    driver.  There are two problems with the current code:
+    
+            ed->last_iso is used but not set anywhere.  The patch changes
+            its name to ed->next_iso and uses it to store the frame number
+            of the next available slot in the isochronous stream.
+    
+            urb->start_frame isn't set when the URB_ISO_ASAP flag is off.
+            The patch sets it to the next available slot if the stream is
+            in use, or the current frame otherwise.
+    
+    This won't give the right behavior when an underrun occurs, but I
+    don't know enough about the driver to handle that case.
+    
+    Unfortunately, I don't have any way to test these changes.
+    
+    Signed-off-by: Alan Stern 
+    CC: Anton Vorontsov 
+    CC: Li Yang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/fhci-sched.c b/drivers/usb/host/fhci-sched.c
+index 8f18538e0ff7..95ca5986e672 100644
+--- a/drivers/usb/host/fhci-sched.c
++++ b/drivers/usb/host/fhci-sched.c
+@@ -739,9 +739,13 @@ void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb)
+ 	}
+ 
+ 	/* for ISO transfer calculate start frame index */
+-	if (ed->mode == FHCI_TF_ISO && urb->transfer_flags & URB_ISO_ASAP)
+-		urb->start_frame = ed->td_head ? ed->last_iso + 1 :
++	if (ed->mode == FHCI_TF_ISO) {
++		/* Ignore the possibility of underruns */
++		urb->start_frame = ed->td_head ? ed->next_iso :
+ 						 get_frame_num(fhci);
++		ed->next_iso = (urb->start_frame + urb->interval *
++				urb->number_of_packets) & 0x07ff;
++	}
+ 
+ 	/*
+ 	 * OHCI handles the DATA toggle itself,we just use the USB
+diff --git a/drivers/usb/host/fhci.h b/drivers/usb/host/fhci.h
+index 7cc1c32dc36c..154e6a007727 100644
+--- a/drivers/usb/host/fhci.h
++++ b/drivers/usb/host/fhci.h
+@@ -338,7 +338,7 @@ struct ed {
+ 
+ 	/* read only parameters, should be cleared upon initialization */
+ 	u8 toggle_carry;	/* toggle carry from the last TD submitted */
+-	u32 last_iso;		/* time stamp of last queued ISO transfer */
++	u16 next_iso;		/* time stamp of next queued ISO transfer */
+ 	struct td *td_head;	/* a pointer to the current TD handled */
+ };
+ 

commit 9db33f317432d1a9e22116092c6455ae71bf73fc
+Author: Alan Stern 
+Date:   Wed May 29 13:20:00 2013 -0400
+
+    USB: IMX21: upgrade the isochronous API
+    
+    This patch attempts to update the imx21-hcd driver to the current
+    standard for the isochronous API.  Firstly, urb->start_frame should
+    always be set by the driver; it is not an input parameter.  Secondly,
+    the URB_ISO_ASAP flag matters only when an URB is submitted to a
+    stream that has gotten an underrun.  It causes the URB to be scheduled
+    for the next available slot in the future, rather than the earliest
+    unused (and expired) slot.
+    
+    Unfortunately, I don't have any way to test these changes.
+    
+    Signed-off-by: Alan Stern 
+    CC: Sascha Hauer 
+    CC: Martin Fuzzey 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c
+index f0ebe8e7c58b..03dc4d9cbeca 100644
+--- a/drivers/usb/host/imx21-hcd.c
++++ b/drivers/usb/host/imx21-hcd.c
+@@ -809,26 +809,36 @@ static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd,
+ 
+ 	/* calculate frame */
+ 	cur_frame = imx21_hc_get_frame(hcd);
+-	if (urb->transfer_flags & URB_ISO_ASAP) {
+-		if (list_empty(&ep_priv->td_list))
+-			urb->start_frame = cur_frame + 5;
+-		else
+-			urb->start_frame = list_entry(
+-				ep_priv->td_list.prev,
+-				struct td, list)->frame + urb->interval;
+-	}
+-	urb->start_frame = wrap_frame(urb->start_frame);
+-	if (frame_after(cur_frame, urb->start_frame)) {
+-		dev_dbg(imx21->dev,
+-			"enqueue: adjusting iso start %d (cur=%d) asap=%d\n",
+-			urb->start_frame, cur_frame,
+-			(urb->transfer_flags & URB_ISO_ASAP) != 0);
+-		urb->start_frame = wrap_frame(cur_frame + 1);
++	i = 0;
++	if (list_empty(&ep_priv->td_list)) {
++		urb->start_frame = wrap_frame(cur_frame + 5);
++	} else {
++		urb->start_frame = wrap_frame(list_entry(ep_priv->td_list.prev,
++				struct td, list)->frame + urb->interval);
++
++		if (frame_after(cur_frame, urb->start_frame)) {
++			dev_dbg(imx21->dev,
++				"enqueue: adjusting iso start %d (cur=%d) asap=%d\n",
++				urb->start_frame, cur_frame,
++				(urb->transfer_flags & URB_ISO_ASAP) != 0);
++			i = DIV_ROUND_UP(wrap_frame(
++					cur_frame - urb->start_frame),
++					urb->interval);
++			if (urb->transfer_flags & URB_ISO_ASAP) {
++				urb->start_frame = wrap_frame(urb->start_frame
++						+ i * urb->interval);
++				i = 0;
++			} else if (i >= urb->number_of_packets) {
++				ret = -EXDEV;
++				goto alloc_dmem_failed;
++			}
++		}
+ 	}
+ 
+ 	/* set up transfers */
++	urb_priv->isoc_remaining = urb->number_of_packets - i;
+ 	td = urb_priv->isoc_td;
+-	for (i = 0; i < urb->number_of_packets; i++, td++) {
++	for (; i < urb->number_of_packets; i++, td++) {
+ 		unsigned int offset = urb->iso_frame_desc[i].offset;
+ 		td->ep = ep;
+ 		td->urb = urb;
+@@ -840,7 +850,6 @@ static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd,
+ 		list_add_tail(&td->list, &ep_priv->td_list);
+ 	}
+ 
+-	urb_priv->isoc_remaining = urb->number_of_packets;
+ 	dev_vdbg(imx21->dev, "setup %d packets for iso frame %d->%d\n",
+ 		urb->number_of_packets, urb->start_frame, td->frame);
+ 

commit 8a1ea51f87a6149c3263a63e9c60d852bedbecd7
+Author: Alan Stern 
+Date:   Wed May 29 13:21:01 2013 -0400
+
+    USB: MUSB: upgrade the isochronous API
+    
+    This patch attempts to fix the isochonour API in the musb host
+    driver.  In particular, the urb->start_frame field should always be
+    set by the driver; it isn't an input parameter.
+    
+    The simplest way to accomplish this is to treat all URBs as though the
+    URB_ISO_ASAP flag was set.  This won't give the right behavior when an
+    underrun occurs, but I don't know enough about the musb driver to
+    handle that case.
+    
+    Unfortunately, I have no way to test this change.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
+index 8914dec49f01..85ed11e04f35 100644
+--- a/drivers/usb/musb/musb_host.c
++++ b/drivers/usb/musb/musb_host.c
+@@ -269,8 +269,7 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
+ 		/* FIXME this doesn't implement that scheduling policy ...
+ 		 * or handle framecounter wrapping
+ 		 */
+-		if ((urb->transfer_flags & URB_ISO_ASAP)
+-				|| (frame >= urb->start_frame)) {
++		if (1) {	/* Always assume URB_ISO_ASAP */
+ 			/* REVISIT the SOF irq handler shouldn't duplicate
+ 			 * this code; and we don't init urb->start_frame...
+ 			 */

commit 077f5f1c23b3cf1134c031677497dfb6077e6bdd
+Author: Alan Stern 
+Date:   Wed May 29 11:33:52 2013 -0400
+
+    USB: EHCI: fix regression related to qh_refresh()
+    
+    This patch adds some code that inadvertently got left out of commit
+    c1fdb68e3d73741630ca16695cf9176c233be7ed (USB: EHCI: changes related
+    to qh_refresh()).  The calls to qh_refresh() and qh_link_periodic()
+    were taken out of qh_schedule(); therefore it is necessary to call
+    these routines manually after calling qh_schedule().
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Oleksij Rempel 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index f3c1028a54fc..f80d0330d548 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -646,6 +646,10 @@ static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	/* reschedule QH iff another request is queued */
+ 	if (!list_empty(&qh->qtd_list) && ehci->rh_state == EHCI_RH_RUNNING) {
+ 		rc = qh_schedule(ehci, qh);
++		if (rc == 0) {
++			qh_refresh(ehci, qh);
++			qh_link_periodic(ehci, qh);
++		}
+ 
+ 		/* An error here likely indicates handshake failure
+ 		 * or no space left in the schedule.  Neither fault
+@@ -653,9 +657,10 @@ static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		 *
+ 		 * FIXME kill the now-dysfunctional queued urbs
+ 		 */
+-		if (rc != 0)
++		else {
+ 			ehci_err(ehci, "can't reschedule qh %p, err %d\n",
+ 					qh, rc);
++		}
+ 	}
+ 
+ 	/* maybe turn off periodic schedule */

commit fdc03438f53a00294ed9939eb3a1f6db6f3d8963
+Author: Alan Stern 
+Date:   Tue May 28 14:03:10 2013 -0400
+
+    USB: revert periodic scheduling bugfix
+    
+    This patch reverts commit 3e619d04159be54b3daa0b7036b0ce9e067f4b5d
+    (USB: EHCI: fix bug in scheduling periodic split transfers).  The
+    commit was valid -- it fixed a real bug -- but the periodic scheduler
+    in ehci-hcd is in such bad shape (especially the part that handles
+    split transactions) that fixing one bug is very likely to cause
+    another to surface.  That's what happened in this case; the result was
+    choppy and noisy playback on certain 24-bit audio devices.
+    
+    The only real fix will be to rewrite this entire section of code.  My
+    next project...
+    
+    This fixes https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1136110.
+    
+    Thanks to Tim Richardson for extra testing and feedback, and to Joseph
+    Salisbury and Tyson Tan for tracking down the original source of the
+    problem.
+    
+    Signed-off-by: Alan Stern 
+    CC: Joseph Salisbury 
+    CC: Tim Richardson 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index acff5b8f6e89..f3c1028a54fc 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -213,7 +213,7 @@ static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask)
+ }
+ 
+ static const unsigned char
+-max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 125, 25 };
++max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 };
+ 
+ /* carryover low/fullspeed bandwidth that crosses uframe boundries */
+ static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8])

commit 98f541c6e390d48643047e0924da8ccc10bb1598
+Author: Alan Stern 
+Date:   Wed May 1 12:13:54 2013 -0400
+
+    USB: remove remaining instances of USB_SUSPEND
+    
+    Commit 84ebc10294a3d7be4c66f51070b7aedbaa24de9b (USB: remove
+    CONFIG_USB_SUSPEND option) failed to remove all of the usages of
+    USB_SUSPEND throughout the kernel.  This patch (as1677) removes the
+    remaining instances of that symbol.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/arm/configs/omap1_defconfig b/arch/arm/configs/omap1_defconfig
+index 7e0ebb64a7f9..9940f7b4e438 100644
+--- a/arch/arm/configs/omap1_defconfig
++++ b/arch/arm/configs/omap1_defconfig
+@@ -199,7 +199,6 @@ CONFIG_USB_PHY=y
+ CONFIG_USB_DEBUG=y
+ CONFIG_USB_DEVICEFS=y
+ # CONFIG_USB_DEVICE_CLASS is not set
+-CONFIG_USB_SUSPEND=y
+ CONFIG_USB_MON=y
+ CONFIG_USB_OHCI_HCD=y
+ CONFIG_USB_STORAGE=y
+diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
+index c1ef64bc5abd..435d69b83e32 100644
+--- a/arch/arm/configs/omap2plus_defconfig
++++ b/arch/arm/configs/omap2plus_defconfig
+@@ -204,7 +204,6 @@ CONFIG_USB=y
+ CONFIG_USB_DEBUG=y
+ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+ CONFIG_USB_DEVICEFS=y
+-CONFIG_USB_SUSPEND=y
+ CONFIG_USB_MON=y
+ CONFIG_USB_WDM=y
+ CONFIG_USB_STORAGE=y
+diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig
+index face9d26e6d5..bac26b971c5e 100644
+--- a/arch/mips/configs/db1000_defconfig
++++ b/arch/mips/configs/db1000_defconfig
+@@ -228,7 +228,6 @@ CONFIG_HIDRAW=y
+ CONFIG_USB_HID=y
+ CONFIG_USB_SUPPORT=y
+ CONFIG_USB=y
+-CONFIG_USB_SUSPEND=y
+ CONFIG_USB_EHCI_HCD=y
+ CONFIG_USB_EHCI_ROOT_HUB_TT=y
+ CONFIG_USB_EHCI_TT_NEWSCHED=y
+diff --git a/arch/mips/configs/db1235_defconfig b/arch/mips/configs/db1235_defconfig
+index 14752dde7540..e2b4ad55462f 100644
+--- a/arch/mips/configs/db1235_defconfig
++++ b/arch/mips/configs/db1235_defconfig
+@@ -344,7 +344,6 @@ CONFIG_UHID=y
+ CONFIG_USB_HIDDEV=y
+ CONFIG_USB=y
+ CONFIG_USB_DYNAMIC_MINORS=y
+-CONFIG_USB_SUSPEND=y
+ CONFIG_USB_EHCI_HCD=y
+ CONFIG_USB_EHCI_HCD_PLATFORM=y
+ CONFIG_USB_EHCI_ROOT_HUB_TT=y
+diff --git a/arch/mips/configs/lemote2f_defconfig b/arch/mips/configs/lemote2f_defconfig
+index b6acd2f256b6..343bebc4b63b 100644
+--- a/arch/mips/configs/lemote2f_defconfig
++++ b/arch/mips/configs/lemote2f_defconfig
+@@ -300,7 +300,6 @@ CONFIG_USB=y
+ CONFIG_USB_DEVICEFS=y
+ # CONFIG_USB_DEVICE_CLASS is not set
+ CONFIG_USB_DYNAMIC_MINORS=y
+-CONFIG_USB_SUSPEND=y
+ CONFIG_USB_OTG_WHITELIST=y
+ CONFIG_USB_MON=y
+ CONFIG_USB_EHCI_HCD=y
+diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig
+index f79196232917..139a8308070c 100644
+--- a/arch/powerpc/configs/ps3_defconfig
++++ b/arch/powerpc/configs/ps3_defconfig
+@@ -136,7 +136,6 @@ CONFIG_HID_SMARTJOYPLUS=m
+ CONFIG_USB_HIDDEV=y
+ CONFIG_USB=m
+ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+-CONFIG_USB_SUSPEND=y
+ CONFIG_USB_MON=m
+ CONFIG_USB_EHCI_HCD=m
+ # CONFIG_USB_EHCI_HCD_PPC_OF is not set
+diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
+index f95cb032394b..06ee82f557d4 100644
+--- a/drivers/net/usb/usbnet.c
++++ b/drivers/net/usb/usbnet.c
+@@ -1477,7 +1477,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
+ 
+ 	/* usbnet already took usb runtime pm, so have to enable the feature
+ 	 * for usb interface, otherwise usb_autopm_get_interface may return
+-	 * failure if USB_SUSPEND(RUNTIME_PM) is enabled.
++	 * failure if RUNTIME_PM is enabled.
+ 	 */
+ 	if (!driver->supports_autosuspend) {
+ 		driver->supports_autosuspend = 1;
+diff --git a/drivers/staging/gdm72xx/Kconfig b/drivers/staging/gdm72xx/Kconfig
+index 3c18efe31365..69059138de4a 100644
+--- a/drivers/staging/gdm72xx/Kconfig
++++ b/drivers/staging/gdm72xx/Kconfig
+@@ -39,7 +39,7 @@ if WIMAX_GDM72XX_USB
+ 
+ config WIMAX_GDM72XX_USB_PM
+ 	bool "Enable power managerment support"
+-	depends on USB_SUSPEND
++	depends on PM_RUNTIME
+ 
+ endif # WIMAX_GDM72XX_USB
+ 
+diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
+index 8772b3659296..db535b0aa172 100644
+--- a/drivers/usb/core/Kconfig
++++ b/drivers/usb/core/Kconfig
+@@ -51,7 +51,7 @@ config USB_DYNAMIC_MINORS
+ 
+ config USB_OTG
+ 	bool "OTG support"
+-	depends on USB_SUSPEND
++	depends on PM_RUNTIME
+ 	default n
+ 	help
+ 	  The most notable feature of USB OTG is support for a
+diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c
+index 125e261f5bfc..2facee53eab1 100644
+--- a/drivers/usb/host/isp1760-hcd.c
++++ b/drivers/usb/host/isp1760-hcd.c
+@@ -1739,7 +1739,7 @@ static int isp1760_hub_status_data(struct usb_hcd *hcd, char *buf)
+ 	int retval = 1;
+ 	unsigned long flags;
+ 
+-	/* if !USB_SUSPEND, root hub timers won't get shut down ... */
++	/* if !PM_RUNTIME, root hub timers won't get shut down ... */
+ 	if (!HC_IS_RUNNING(hcd->state))
+ 		return 0;
+ 
+diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
+index 4f0f0339532f..0f401dbfaf07 100644
+--- a/drivers/usb/host/oxu210hp-hcd.c
++++ b/drivers/usb/host/oxu210hp-hcd.c
+@@ -3084,7 +3084,7 @@ static int oxu_hub_status_data(struct usb_hcd *hcd, char *buf)
+ 	int ports, i, retval = 1;
+ 	unsigned long flags;
+ 
+-	/* if !USB_SUSPEND, root hub timers won't get shut down ... */
++	/* if !PM_RUNTIME, root hub timers won't get shut down ... */
+ 	if (!HC_IS_RUNNING(hcd->state))
+ 		return 0;
+ 
+diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
+index ad4483efb6d6..b2ec7fe758dd 100644
+--- a/drivers/usb/host/sl811-hcd.c
++++ b/drivers/usb/host/sl811-hcd.c
+@@ -22,7 +22,7 @@
+  * and usb-storage.
+  *
+  * TODO:
+- * - usb suspend/resume triggered by sl811 (with USB_SUSPEND)
++ * - usb suspend/resume triggered by sl811 (with PM_RUNTIME)
+  * - various issues noted in the code
+  * - performance work; use both register banks; ...
+  * - use urb->iso_frame_desc[] with ISO transfers
+diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
+index 5053cea0ad89..7ef3eb8617a6 100644
+--- a/drivers/usb/phy/Kconfig
++++ b/drivers/usb/phy/Kconfig
+@@ -25,7 +25,7 @@ config AB8500_USB
+ 
+ config FSL_USB2_OTG
+ 	bool "Freescale USB OTG Transceiver Driver"
+-	depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_SUSPEND
++	depends on USB_EHCI_FSL && USB_FSL_USB2 && PM_RUNTIME
+ 	select USB_OTG
+ 	help
+ 	  Enable this to support Freescale USB OTG transceiver.
+@@ -161,7 +161,7 @@ config USB_MSM_OTG
+ 
+ config USB_MV_OTG
+ 	tristate "Marvell USB OTG support"
+-	depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND
++	depends on USB_EHCI_MV && USB_MV_UDC && PM_RUNTIME
+ 	select USB_OTG
+ 	help
+ 	  Say Y here if you want to build Marvell USB OTG transciever

commit 815fa7b917614261748d1ecd9600ff27f99508e5
+Author: Alan Stern 
+Date:   Tue May 14 13:57:51 2013 -0400
+
+    USB: OHCI: fix logic for scheduling isochronous URBs
+    
+    The isochronous scheduling logic in ohci-hcd has a bug.  The
+    calculation for skipping TDs that are too late should be carried out
+    only in the !URB_ISO_ASAP case.  When URB_ISO_ASAP is set, the URB is
+    pushed back so that none of the TDs are too late, which would cause
+    the calculation to overflow.
+    
+    The patch also fixes the calculation to avoid overflow in the case
+    where the frame value wraps around.
+    
+    This should be applied to -stable kernels going back to 3.8.
+    
+    Signed-off-by: Alan Stern 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index df1af0bcfe99..fc627fd54116 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -240,7 +240,7 @@ static int ohci_urb_enqueue (
+ 		if (unlikely(tick_before(frame, next))) {
+ 
+ 			/* USB_ISO_ASAP: Round up to the first available slot */
+-			if (urb->transfer_flags & URB_ISO_ASAP)
++			if (urb->transfer_flags & URB_ISO_ASAP) {
+ 				frame += (next - frame + ed->interval - 1) &
+ 						-ed->interval;
+ 
+@@ -248,21 +248,25 @@ static int ohci_urb_enqueue (
+ 			 * Not ASAP: Use the next slot in the stream.  If
+ 			 * the entire URB falls before the threshold, fail.
+ 			 */
+-			else if (tick_before(frame + ed->interval *
++			} else {
++				if (tick_before(frame + ed->interval *
+ 					(urb->number_of_packets - 1), next)) {
+-				retval = -EXDEV;
+-				usb_hcd_unlink_urb_from_ep(hcd, urb);
+-				goto fail;
+-			}
++					retval = -EXDEV;
++					usb_hcd_unlink_urb_from_ep(hcd, urb);
++					goto fail;
++				}
+ 
+-			/*
+-			 * Some OHCI hardware doesn't handle late TDs
+-			 * correctly.  After retiring them it proceeds to
+-			 * the next ED instead of the next TD.  Therefore
+-			 * we have to omit the late TDs entirely.
+-			 */
+-			urb_priv->td_cnt = DIV_ROUND_UP(next - frame,
+-					ed->interval);
++				/*
++				 * Some OHCI hardware doesn't handle late TDs
++				 * correctly.  After retiring them it proceeds
++				 * to the next ED instead of the next TD.
++				 * Therefore we have to omit the late TDs
++				 * entirely.
++				 */
++				urb_priv->td_cnt = DIV_ROUND_UP(
++						(u16) (next - frame),
++						ed->interval);
++			}
+ 		}
+ 		urb->start_frame = frame;
+ 	}

commit e1944017839d7dfbf7329fac4bdec8b4050edf5e
+Author: Alan Stern 
+Date:   Tue May 14 13:57:19 2013 -0400
+
+    USB: fix latency in uhci-hcd and ohci-hcd
+    
+    Commits c44b225077bb1fb25ed5cd5c4f226897b91bedd4 (UHCI: implement new
+    semantics for URB_ISO_ASAP) and
+    6a41b4d3fe8cd4cc95181516fc6fba7b1747a27c (OHCI: implement new
+    semantics for URB_ISO_ASAP) increased the latency for isochronous URBs
+    in uhci-hcd and ohci-hcd respectively to 2 milliseconds, in an
+    attempt to avoid underruns.  It turns out that not only was this
+    unnecessary -- 1-ms latency works okay -- it also causes problems with
+    certain application loads such as real-time audio.
+    
+    This patch changes the latency for both drivers back to 1 ms.
+    
+    This should be applied to -stable kernels going back to 3.8.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Joe Rayhawk 
+    CC: Clemens Ladisch 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index 9e6de9586ae4..df1af0bcfe99 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -233,7 +233,7 @@ static int ohci_urb_enqueue (
+ 			urb->start_frame = frame;
+ 		}
+ 	} else if (ed->type == PIPE_ISOCHRONOUS) {
+-		u16	next = ohci_frame_no(ohci) + 2;
++		u16	next = ohci_frame_no(ohci) + 1;
+ 		u16	frame = ed->last_iso + ed->interval;
+ 
+ 		/* Behind the scheduling threshold? */
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index f0976d8190bc..041c6ddb695c 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -1287,7 +1287,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
+ 		return -EINVAL;		/* Can't change the period */
+ 
+ 	} else {
+-		next = uhci->frame_number + 2;
++		next = uhci->frame_number + 1;
+ 
+ 		/* Find the next unused frame */
+ 		if (list_empty(&qh->queue)) {

commit 997ff893603c6455da4c5e26ba1d0f81adfecdfc
+Author: Alan Stern 
+Date:   Tue May 14 13:55:29 2013 -0400
+
+    USB: UHCI: fix for suspend of virtual HP controller
+    
+    HP's virtual UHCI host controller takes a long time to suspend
+    (several hundred microseconds), even when no devices are attached.
+    This provokes a warning message from uhci-hcd in the auto-stop case.
+    
+    To prevent this from happening, this patch adds a test to avoid
+    performing an auto-stop when the wait_for_hp quirk flag is set.  The
+    controller will still suspend through the normal runtime PM mechanism.
+    And since that pathway includes a 1-ms delay, the slowness of the
+    virtual hardware won't matter.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: ZhenHua 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
+index f87bee6d2789..9189bc984c98 100644
+--- a/drivers/usb/host/uhci-hub.c
++++ b/drivers/usb/host/uhci-hub.c
+@@ -225,7 +225,8 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
+ 		/* auto-stop if nothing connected for 1 second */
+ 		if (any_ports_active(uhci))
+ 			uhci->rh_state = UHCI_RH_RUNNING;
+-		else if (time_after_eq(jiffies, uhci->auto_stop_time))
++		else if (time_after_eq(jiffies, uhci->auto_stop_time) &&
++				!uhci->wait_for_hp)
+ 			suspend_rh(uhci, UHCI_RH_AUTO_STOPPED);
+ 		break;
+ 

commit ccd9509a0b942f7a139f1adb741a746ef0220911
+Author: Alan Stern 
+Date:   Tue May 14 13:54:12 2013 -0400
+
+    USB: fix Kconfig logic for USB_UHCI_HCD
+    
+    The Kconfig settings for uhci-hcd are too permissive; they allow the
+    driver to be built without any bus-glue modules configured
+    (USB_UHCI_HCD enabled, PCI disabled, SPARC_LEON disabled, ARCH_VT8500
+    enabled, and USB_UHCI_PLATFORM disabled).
+    
+    This patch fixes the problem by rearranging the dependencies.  Now the
+    platform-dependent config options don't depend on USB_UHCI_HCD;
+    instead it depends on them.  Furthermore, there is no user-selectable
+    choice as to which glue modules will be built.  If USB_UHCI_HCD is
+    enabled then all applicable bus glues will be built.
+    
+    Signed-off-by: Alan Stern 
+    CC: Arnd Bergmann 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
+index de94f2699063..344d5e2f87d7 100644
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -507,7 +507,7 @@ endif # USB_OHCI_HCD
+ 
+ config USB_UHCI_HCD
+ 	tristate "UHCI HCD (most Intel and VIA) support"
+-	depends on PCI || SPARC_LEON || ARCH_VT8500
++	depends on PCI || USB_UHCI_SUPPORT_NON_PCI_HC
+ 	---help---
+ 	  The Universal Host Controller Interface is a standard by Intel for
+ 	  accessing the USB hardware in the PC (which is also called the USB
+@@ -524,26 +524,19 @@ config USB_UHCI_HCD
+ 
+ config USB_UHCI_SUPPORT_NON_PCI_HC
+ 	bool
+-	depends on USB_UHCI_HCD
+-	default y if (SPARC_LEON || ARCH_VT8500)
++	default y if (SPARC_LEON || USB_UHCI_PLATFORM)
+ 
+ config USB_UHCI_PLATFORM
+-	bool "Generic UHCI Platform Driver support"
+-	depends on USB_UHCI_SUPPORT_NON_PCI_HC
++	bool
+ 	default y if ARCH_VT8500
+-	---help---
+-	  Enable support for generic UHCI platform devices that require no
+-	  additional configuration.
+ 
+ config USB_UHCI_BIG_ENDIAN_MMIO
+ 	bool
+-	depends on USB_UHCI_SUPPORT_NON_PCI_HC && SPARC_LEON
+-	default y
++	default y if SPARC_LEON
+ 
+ config USB_UHCI_BIG_ENDIAN_DESC
+ 	bool
+-	depends on USB_UHCI_SUPPORT_NON_PCI_HC && SPARC_LEON
+-	default y
++	default y if SPARC_LEON
+ 
+ config USB_FHCI_HCD
+ 	tristate "Freescale QE USB Host Controller support"

commit e4f47e3675e6f1f40906b785b934ce963e9f2eb3
+Author: Alan Stern 
+Date:   Wed May 8 11:18:05 2013 -0400
+
+    USB: xHCI: override bogus bulk wMaxPacketSize values
+    
+    This patch shortens the logic in xhci_endpoint_init() by moving common
+    calculations involving max_packet and max_burst outside the switch
+    statement, rather than repeating the same code in multiple
+    case-specific statements.  It also replaces two usages of max_packet
+    which were clearly intended to be max_burst all along.
+    
+    More importantly, it compensates for a common bug in high-speed bulk
+    endpoint descriptors.  In many devices there is a bulk endpoint having
+    a wMaxPacketSize value smaller than 512, which is forbidden by the USB
+    spec.  Some xHCI controllers can't handle this and refuse to accept
+    the endpoint.  This patch changes the max_packet value to 512, which
+    allows the controller to use the endpoint properly.
+    
+    In practice the bogus maxpacket size doesn't matter, because none of
+    the transfers sent via these endpoints are longer than the maxpacket
+    value anyway.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: "Aurélien Leblond" 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
+index 965b539bc474..2cfc465925bd 100644
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -1423,15 +1423,17 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
+ 	ep_ctx->ep_info2 |= cpu_to_le32(xhci_get_endpoint_type(udev, ep));
+ 
+ 	/* Set the max packet size and max burst */
++	max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc));
++	max_burst = 0;
+ 	switch (udev->speed) {
+ 	case USB_SPEED_SUPER:
+-		max_packet = usb_endpoint_maxp(&ep->desc);
+-		ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet));
+ 		/* dig out max burst from ep companion desc */
+-		max_packet = ep->ss_ep_comp.bMaxBurst;
+-		ep_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(max_packet));
++		max_burst = ep->ss_ep_comp.bMaxBurst;
+ 		break;
+ 	case USB_SPEED_HIGH:
++		/* Some devices get this wrong */
++		if (usb_endpoint_xfer_bulk(&ep->desc))
++			max_packet = 512;
+ 		/* bits 11:12 specify the number of additional transaction
+ 		 * opportunities per microframe (USB 2.0, section 9.6.6)
+ 		 */
+@@ -1439,17 +1441,16 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
+ 				usb_endpoint_xfer_int(&ep->desc)) {
+ 			max_burst = (usb_endpoint_maxp(&ep->desc)
+ 				     & 0x1800) >> 11;
+-			ep_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(max_burst));
+ 		}
+-		/* Fall through */
++		break;
+ 	case USB_SPEED_FULL:
+ 	case USB_SPEED_LOW:
+-		max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc));
+-		ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet));
+ 		break;
+ 	default:
+ 		BUG();
+ 	}
++	ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet) |
++			MAX_BURST(max_burst));
+ 	max_esit_payload = xhci_get_max_esit_payload(xhci, udev, ep);
+ 	ep_ctx->tx_info = cpu_to_le32(MAX_ESIT_PAYLOAD_FOR_EP(max_esit_payload));
+ 

commit 05768918b9a122ce21bd55950df5054ff6c57f28
+Author: Alan Stern 
+Date:   Thu Mar 28 15:04:45 2013 -0400
+
+    USB: improve port transitions when EHCI starts up
+    
+    It seems to be getting more common recently for EHCI host controllers
+    to be probed after their companion UHCI or OHCI controllers.  This may
+    be caused partly by splitting the ehci-pci driver out from ehci-hcd,
+    or it may be caused by changes in the way the kernel does driver
+    probing.
+    
+    Regardless, it has a tendency to cause problems.  When an EHCI
+    controller is initialized, it takes ownership of all the ports away
+    from the companions.  In effect, it forcefully disconnects all the USB
+    devices that may already be using a companion controller.
+    
+    This patch (as1672b) tries to make the transition more orderly by
+    deconfiguring the root hubs for all the companion controllers before
+    initializing the EHCI controller, and reconfiguring them afterward.
+    The result is a soft disconnect rather than a hard one.
+    
+    Internally, the patch refactors the code involved in associating EHCI
+    controllers with their companions.  The old approach, in which a
+    single function is called with an argument telling it what to do (the
+    companion_action enum), has been replaced with a scheme using multiple
+    callback functions, each performing a single task.
+    
+    This patch won't solve all the problems people encounter when their
+    EHCI controllers start up, but it will at least reduce the number of
+    error messages generated by the unexpected disconnections.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Jenya Y 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index 2b487d4797bd..caeb8d6d39fb 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -37,119 +37,123 @@
+ 
+ /* PCI-based HCs are common, but plenty of non-PCI HCs are used too */
+ 
+-#ifdef CONFIG_PM_SLEEP
+-
+-/* Coordinate handoffs between EHCI and companion controllers
+- * during system resume
++/*
++ * Coordinate handoffs between EHCI and companion controllers
++ * during EHCI probing and system resume.
+  */
+ 
+-static DEFINE_MUTEX(companions_mutex);
++static DECLARE_RWSEM(companions_rwsem);
+ 
+ #define CL_UHCI		PCI_CLASS_SERIAL_USB_UHCI
+ #define CL_OHCI		PCI_CLASS_SERIAL_USB_OHCI
+ #define CL_EHCI		PCI_CLASS_SERIAL_USB_EHCI
+ 
+-enum companion_action {
+-	SET_HS_COMPANION, CLEAR_HS_COMPANION, WAIT_FOR_COMPANIONS
+-};
++static inline int is_ohci_or_uhci(struct pci_dev *pdev)
++{
++	return pdev->class == CL_OHCI || pdev->class == CL_UHCI;
++}
++
++typedef void (*companion_fn)(struct pci_dev *pdev, struct usb_hcd *hcd,
++		struct pci_dev *companion, struct usb_hcd *companion_hcd);
+ 
+-static void companion_common(struct pci_dev *pdev, struct usb_hcd *hcd,
+-		enum companion_action action)
++/* Iterate over PCI devices in the same slot as pdev and call fn for each */
++static void for_each_companion(struct pci_dev *pdev, struct usb_hcd *hcd,
++		companion_fn fn)
+ {
+ 	struct pci_dev		*companion;
+ 	struct usb_hcd		*companion_hcd;
+ 	unsigned int		slot = PCI_SLOT(pdev->devfn);
+ 
+-	/* Iterate through other PCI functions in the same slot.
+-	 * If pdev is OHCI or UHCI then we are looking for EHCI, and
+-	 * vice versa.
++	/*
++	 * Iterate through other PCI functions in the same slot.
++	 * If the function's drvdata isn't set then it isn't bound to
++	 * a USB host controller driver, so skip it.
+ 	 */
+ 	companion = NULL;
+ 	for_each_pci_dev(companion) {
+ 		if (companion->bus != pdev->bus ||
+ 				PCI_SLOT(companion->devfn) != slot)
+ 			continue;
+-
+ 		companion_hcd = pci_get_drvdata(companion);
+ 		if (!companion_hcd)
+ 			continue;
+-
+-		/* For SET_HS_COMPANION, store a pointer to the EHCI bus in
+-		 * the OHCI/UHCI companion bus structure.
+-		 * For CLEAR_HS_COMPANION, clear the pointer to the EHCI bus
+-		 * in the OHCI/UHCI companion bus structure.
+-		 * For WAIT_FOR_COMPANIONS, wait until the OHCI/UHCI
+-		 * companion controllers have fully resumed.
+-		 */
+-
+-		if ((pdev->class == CL_OHCI || pdev->class == CL_UHCI) &&
+-				companion->class == CL_EHCI) {
+-			/* action must be SET_HS_COMPANION */
+-			dev_dbg(&companion->dev, "HS companion for %s\n",
+-					dev_name(&pdev->dev));
+-			hcd->self.hs_companion = &companion_hcd->self;
+-
+-		} else if (pdev->class == CL_EHCI &&
+-				(companion->class == CL_OHCI ||
+-				companion->class == CL_UHCI)) {
+-			switch (action) {
+-			case SET_HS_COMPANION:
+-				dev_dbg(&pdev->dev, "HS companion for %s\n",
+-						dev_name(&companion->dev));
+-				companion_hcd->self.hs_companion = &hcd->self;
+-				break;
+-			case CLEAR_HS_COMPANION:
+-				companion_hcd->self.hs_companion = NULL;
+-				break;
+-			case WAIT_FOR_COMPANIONS:
+-				device_pm_wait_for_dev(&pdev->dev,
+-						&companion->dev);
+-				break;
+-			}
+-		}
++		fn(pdev, hcd, companion, companion_hcd);
+ 	}
+ }
+ 
+-static void set_hs_companion(struct pci_dev *pdev, struct usb_hcd *hcd)
++/*
++ * We're about to add an EHCI controller, which will unceremoniously grab
++ * all the port connections away from its companions.  To prevent annoying
++ * error messages, lock the companion's root hub and gracefully unconfigure
++ * it beforehand.  Leave it locked until the EHCI controller is all set.
++ */
++static void ehci_pre_add(struct pci_dev *pdev, struct usb_hcd *hcd,
++		struct pci_dev *companion, struct usb_hcd *companion_hcd)
+ {
+-	mutex_lock(&companions_mutex);
+-	dev_set_drvdata(&pdev->dev, hcd);
+-	companion_common(pdev, hcd, SET_HS_COMPANION);
+-	mutex_unlock(&companions_mutex);
++	struct usb_device *udev;
++
++	if (is_ohci_or_uhci(companion)) {
++		udev = companion_hcd->self.root_hub;
++		usb_lock_device(udev);
++		usb_set_configuration(udev, 0);
++	}
+ }
+ 
+-static void clear_hs_companion(struct pci_dev *pdev, struct usb_hcd *hcd)
++/*
++ * Adding the EHCI controller has either succeeded or failed.  Set the
++ * companion pointer accordingly, and in either case, reconfigure and
++ * unlock the root hub.
++ */
++static void ehci_post_add(struct pci_dev *pdev, struct usb_hcd *hcd,
++		struct pci_dev *companion, struct usb_hcd *companion_hcd)
+ {
+-	mutex_lock(&companions_mutex);
+-	dev_set_drvdata(&pdev->dev, NULL);
++	struct usb_device *udev;
+ 
+-	/* If pdev is OHCI or UHCI, just clear its hs_companion pointer */
+-	if (pdev->class == CL_OHCI || pdev->class == CL_UHCI)
+-		hcd->self.hs_companion = NULL;
++	if (is_ohci_or_uhci(companion)) {
++		if (dev_get_drvdata(&pdev->dev)) {	/* Succeeded */
++			dev_dbg(&pdev->dev, "HS companion for %s\n",
++					dev_name(&companion->dev));
++			companion_hcd->self.hs_companion = &hcd->self;
++		}
++		udev = companion_hcd->self.root_hub;
++		usb_set_configuration(udev, 1);
++		usb_unlock_device(udev);
++	}
++}
+ 
+-	/* Otherwise search for companion buses and clear their pointers */
+-	else
+-		companion_common(pdev, hcd, CLEAR_HS_COMPANION);
+-	mutex_unlock(&companions_mutex);
++/*
++ * We just added a non-EHCI controller.  Find the EHCI controller to
++ * which it is a companion, and store a pointer to the bus structure.
++ */
++static void non_ehci_add(struct pci_dev *pdev, struct usb_hcd *hcd,
++		struct pci_dev *companion, struct usb_hcd *companion_hcd)
++{
++	if (is_ohci_or_uhci(pdev) && companion->class == CL_EHCI) {
++		dev_dbg(&pdev->dev, "FS/LS companion for %s\n",
++				dev_name(&companion->dev));
++		hcd->self.hs_companion = &companion_hcd->self;
++	}
+ }
+ 
+-static void wait_for_companions(struct pci_dev *pdev, struct usb_hcd *hcd)
++/* We are removing an EHCI controller.  Clear the companions' pointers. */
++static void ehci_remove(struct pci_dev *pdev, struct usb_hcd *hcd,
++		struct pci_dev *companion, struct usb_hcd *companion_hcd)
+ {
+-	/* Only EHCI controllers need to wait.
+-	 * No locking is needed because a controller cannot be resumed
+-	 * while one of its companions is getting unbound.
+-	 */
+-	if (pdev->class == CL_EHCI)
+-		companion_common(pdev, hcd, WAIT_FOR_COMPANIONS);
++	if (is_ohci_or_uhci(companion))
++		companion_hcd->self.hs_companion = NULL;
+ }
+ 
+-#else /* !CONFIG_PM_SLEEP */
++#ifdef	CONFIG_PM
+ 
+-static inline void set_hs_companion(struct pci_dev *d, struct usb_hcd *h) {}
+-static inline void clear_hs_companion(struct pci_dev *d, struct usb_hcd *h) {}
+-static inline void wait_for_companions(struct pci_dev *d, struct usb_hcd *h) {}
++/* An EHCI controller must wait for its companions before resuming. */
++static void ehci_wait_for_companions(struct pci_dev *pdev, struct usb_hcd *hcd,
++		struct pci_dev *companion, struct usb_hcd *companion_hcd)
++{
++	if (is_ohci_or_uhci(companion))
++		device_pm_wait_for_dev(&pdev->dev, &companion->dev);
++}
+ 
+-#endif /* !CONFIG_PM_SLEEP */
++#endif	/* CONFIG_PM */
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+@@ -217,7 +221,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ 				driver->description)) {
+ 			dev_dbg(&dev->dev, "controller already in use\n");
+ 			retval = -EBUSY;
+-			goto clear_companion;
++			goto put_hcd;
+ 		}
+ 		hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
+ 		if (hcd->regs == NULL) {
+@@ -244,16 +248,35 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ 		if (region == PCI_ROM_RESOURCE) {
+ 			dev_dbg(&dev->dev, "no i/o regions available\n");
+ 			retval = -EBUSY;
+-			goto clear_companion;
++			goto put_hcd;
+ 		}
+ 	}
+ 
+ 	pci_set_master(dev);
+ 
+-	retval = usb_add_hcd(hcd, hcd_irq, IRQF_SHARED);
++	/* Note: dev_set_drvdata must be called while holding the rwsem */
++	if (dev->class == CL_EHCI) {
++		down_write(&companions_rwsem);
++		dev_set_drvdata(&dev->dev, hcd);
++		for_each_companion(dev, hcd, ehci_pre_add);
++		retval = usb_add_hcd(hcd, hcd_irq, IRQF_SHARED);
++		if (retval != 0)
++			dev_set_drvdata(&dev->dev, NULL);
++		for_each_companion(dev, hcd, ehci_post_add);
++		up_write(&companions_rwsem);
++	} else {
++		down_read(&companions_rwsem);
++		dev_set_drvdata(&dev->dev, hcd);
++		retval = usb_add_hcd(hcd, hcd_irq, IRQF_SHARED);
++		if (retval != 0)
++			dev_set_drvdata(&dev->dev, NULL);
++		else
++			for_each_companion(dev, hcd, non_ehci_add);
++		up_read(&companions_rwsem);
++	}
++
+ 	if (retval != 0)
+ 		goto unmap_registers;
+-	set_hs_companion(dev, hcd);
+ 
+ 	if (pci_dev_run_wake(dev))
+ 		pm_runtime_put_noidle(&dev->dev);
+@@ -266,8 +289,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ 		release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ 	} else
+ 		release_region(hcd->rsrc_start, hcd->rsrc_len);
+-clear_companion:
+-	clear_hs_companion(dev, hcd);
++put_hcd:
+ 	usb_put_hcd(hcd);
+ disable_pci:
+ 	pci_disable_device(dev);
+@@ -310,14 +332,29 @@ void usb_hcd_pci_remove(struct pci_dev *dev)
+ 	usb_hcd_irq(0, hcd);
+ 	local_irq_enable();
+ 
+-	usb_remove_hcd(hcd);
++	/* Note: dev_set_drvdata must be called while holding the rwsem */
++	if (dev->class == CL_EHCI) {
++		down_write(&companions_rwsem);
++		for_each_companion(dev, hcd, ehci_remove);
++		usb_remove_hcd(hcd);
++		dev_set_drvdata(&dev->dev, NULL);
++		up_write(&companions_rwsem);
++	} else {
++		/* Not EHCI; just clear the companion pointer */
++		down_read(&companions_rwsem);
++		hcd->self.hs_companion = NULL;
++		usb_remove_hcd(hcd);
++		dev_set_drvdata(&dev->dev, NULL);
++		up_read(&companions_rwsem);
++	}
++
+ 	if (hcd->driver->flags & HCD_MEMORY) {
+ 		iounmap(hcd->regs);
+ 		release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ 	} else {
+ 		release_region(hcd->rsrc_start, hcd->rsrc_len);
+ 	}
+-	clear_hs_companion(dev, hcd);
++
+ 	usb_put_hcd(hcd);
+ 	pci_disable_device(dev);
+ }
+@@ -463,8 +500,15 @@ static int resume_common(struct device *dev, int event)
+ 	pci_set_master(pci_dev);
+ 
+ 	if (hcd->driver->pci_resume && !HCD_DEAD(hcd)) {
+-		if (event != PM_EVENT_AUTO_RESUME)
+-			wait_for_companions(pci_dev, hcd);
++
++		/*
++		 * Only EHCI controllers have to wait for their companions.
++		 * No locking is needed because PCI controller drivers do not
++		 * get unbound during system resume.
++		 */
++		if (pci_dev->class == CL_EHCI && event != PM_EVENT_AUTO_RESUME)
++			for_each_companion(pci_dev, hcd,
++					ehci_wait_for_companions);
+ 
+ 		retval = hcd->driver->pci_resume(hcd,
+ 				event == PM_EVENT_RESTORE);

commit 4e9c8e5c5883c910926296e699c2f4e4d9f847cb
+Author: Alan Stern 
+Date:   Thu Mar 28 15:31:13 2013 -0400
+
+    USB: remove CONFIG_USB_SUSPEND from Documentation
+    
+    An earlier patch removed the CONFIG_USB_SUSPEND symbol but forgot to
+    update the Documentation files.  This patch (as1676) rectifies that
+    omission.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb
+index c8baaf53594a..f093e59cbe5f 100644
+--- a/Documentation/ABI/testing/sysfs-bus-usb
++++ b/Documentation/ABI/testing/sysfs-bus-usb
+@@ -32,7 +32,7 @@ Date:		January 2008
+ KernelVersion:	2.6.25
+ Contact:	Sarah Sharp 
+ Description:
+-		If CONFIG_PM and CONFIG_USB_SUSPEND are enabled, then this file
++		If CONFIG_PM_RUNTIME is enabled then this file
+ 		is present.  When read, it returns the total time (in msec)
+ 		that the USB device has been connected to the machine.  This
+ 		file is read-only.
+@@ -45,7 +45,7 @@ Date:		January 2008
+ KernelVersion:	2.6.25
+ Contact:	Sarah Sharp 
+ Description:
+-		If CONFIG_PM and CONFIG_USB_SUSPEND are enabled, then this file
++		If CONFIG_PM_RUNTIME is enabled then this file
+ 		is present.  When read, it returns the total time (in msec)
+ 		that the USB device has been active, i.e. not in a suspended
+ 		state.  This file is read-only.
+@@ -187,7 +187,7 @@ What:		/sys/bus/usb/devices/.../power/usb2_hardware_lpm
+ Date:		September 2011
+ Contact:	Andiry Xu 
+ Description:
+-		If CONFIG_USB_SUSPEND is set and a USB 2.0 lpm-capable device
++		If CONFIG_PM_RUNTIME is set and a USB 2.0 lpm-capable device
+ 		is plugged in to a xHCI host which support link PM, it will
+ 		perform a LPM test; if the test is passed and host supports
+ 		USB2 hardware LPM (xHCI 1.0 feature), USB2 hardware LPM will
+diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt
+index 4204eb01fd38..1392b61d6ebe 100644
+--- a/Documentation/usb/power-management.txt
++++ b/Documentation/usb/power-management.txt
+@@ -33,6 +33,10 @@ built with CONFIG_USB_SUSPEND enabled (which depends on
+ CONFIG_PM_RUNTIME).  System PM support is present only if the kernel
+ was built with CONFIG_SUSPEND or CONFIG_HIBERNATION enabled.
+ 
++(Starting with the 3.10 kernel release, dynamic PM support for USB is
++present whenever the kernel was built with CONFIG_PM_RUNTIME enabled.
++The CONFIG_USB_SUSPEND option has been eliminated.)
++
+ 
+ 	What is Remote Wakeup?
+ 	----------------------
+@@ -206,10 +210,8 @@ initialized to 5.  (The idle-delay values for already existing devices
+ will not be affected.)
+ 
+ Setting the initial default idle-delay to -1 will prevent any
+-autosuspend of any USB device.  This is a simple alternative to
+-disabling CONFIG_USB_SUSPEND and rebuilding the kernel, and it has the
+-added benefit of allowing you to enable autosuspend for selected
+-devices.
++autosuspend of any USB device.  This has the benefit of allowing you
++then to enable autosuspend for selected devices.
+ 
+ 
+ 	Warnings

commit 84ebc10294a3d7be4c66f51070b7aedbaa24de9b
+Author: Alan Stern 
+Date:   Wed Mar 27 16:14:46 2013 -0400
+
+    USB: remove CONFIG_USB_SUSPEND option
+    
+    This patch (as1675) removes the CONFIG_USB_SUSPEND option, essentially
+    replacing it everywhere with CONFIG_PM_RUNTIME (except for one place
+    in hub.c, where it is replaced with CONFIG_PM because the code needs
+    to be used in both runtime and system PM).  The net result is code
+    shrinkage and simplification.
+    
+    There's very little point in keeping CONFIG_USB_SUSPEND because almost
+    everybody enables it.  The few that don't will find that the usbcore
+    module has gotten somewhat bigger and they will have to take active
+    measures if they want to prevent hubs from being runtime suspended.
+    
+    Signed-off-by: Alan Stern 
+    CC: Peter Chen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
+index f70c1a1694ad..175701a2dae4 100644
+--- a/drivers/usb/core/Kconfig
++++ b/drivers/usb/core/Kconfig
+@@ -38,22 +38,6 @@ config USB_DYNAMIC_MINORS
+ 
+ 	  If you are unsure about this, say N here.
+ 
+-config USB_SUSPEND
+-	bool "USB runtime power management (autosuspend) and wakeup"
+-	depends on USB && PM_RUNTIME
+-	help
+-	  If you say Y here, you can use driver calls or the sysfs
+-	  "power/control" file to enable or disable autosuspend for
+-	  individual USB peripherals (see
+-	  Documentation/usb/power-management.txt for more details).
+-
+-	  Also, USB "remote wakeup" signaling is supported, whereby some
+-	  USB devices (like keyboards and network adapters) can wake up
+-	  their parent hub.  That wakeup cascades up the USB tree, and
+-	  could wake the system from states like suspend-to-RAM.
+-
+-	  If you are unsure about this, say N here.
+-
+ config USB_OTG
+ 	bool "OTG support"
+ 	depends on USB
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index eb1d00a3543a..84d2b0585810 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1412,7 +1412,7 @@ int usb_resume(struct device *dev, pm_message_t msg)
+ 
+ #endif /* CONFIG_PM */
+ 
+-#ifdef CONFIG_USB_SUSPEND
++#ifdef CONFIG_PM_RUNTIME
+ 
+ /**
+  * usb_enable_autosuspend - allow a USB device to be autosuspended
+@@ -1780,7 +1780,7 @@ int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)
+ 	return ret;
+ }
+ 
+-#endif /* CONFIG_USB_SUSPEND */
++#endif /* CONFIG_PM_RUNTIME */
+ 
+ struct bus_type usb_bus_type = {
+ 	.name =		"usb",
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index f9ec44cbb82f..d53547d2e4c7 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -2125,7 +2125,7 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
+ 
+ #endif	/* CONFIG_PM */
+ 
+-#ifdef	CONFIG_USB_SUSPEND
++#ifdef	CONFIG_PM_RUNTIME
+ 
+ /* Workqueue routine for root-hub remote wakeup */
+ static void hcd_resume_work(struct work_struct *work)
+@@ -2160,7 +2160,7 @@ void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
+ }
+ EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub);
+ 
+-#endif	/* CONFIG_USB_SUSPEND */
++#endif	/* CONFIG_PM_RUNTIME */
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+@@ -2336,7 +2336,7 @@ struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver,
+ 	init_timer(&hcd->rh_timer);
+ 	hcd->rh_timer.function = rh_timer_func;
+ 	hcd->rh_timer.data = (unsigned long) hcd;
+-#ifdef CONFIG_USB_SUSPEND
++#ifdef CONFIG_PM_RUNTIME
+ 	INIT_WORK(&hcd->wakeup_work, hcd_resume_work);
+ #endif
+ 
+@@ -2590,7 +2590,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ 	hcd->rh_registered = 0;
+ 	spin_unlock_irq(&hcd_root_hub_lock);
+ 
+-#ifdef CONFIG_USB_SUSPEND
++#ifdef CONFIG_PM_RUNTIME
+ 	cancel_work_sync(&hcd->wakeup_work);
+ #endif
+ 	mutex_lock(&usb_bus_list_lock);
+@@ -2645,7 +2645,7 @@ void usb_remove_hcd(struct usb_hcd *hcd)
+ 	hcd->rh_registered = 0;
+ 	spin_unlock_irq (&hcd_root_hub_lock);
+ 
+-#ifdef CONFIG_USB_SUSPEND
++#ifdef CONFIG_PM_RUNTIME
+ 	cancel_work_sync(&hcd->wakeup_work);
+ #endif
+ 
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 443d5cc9330b..feef9351463d 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2827,7 +2827,7 @@ void usb_enable_ltm(struct usb_device *udev)
+ }
+ EXPORT_SYMBOL_GPL(usb_enable_ltm);
+ 
+-#ifdef	CONFIG_USB_SUSPEND
++#ifdef	CONFIG_PM
+ /*
+  * usb_disable_function_remotewakeup - disable usb3.0
+  * device's function remote wakeup
+@@ -2886,7 +2886,7 @@ static int usb_disable_function_remotewakeup(struct usb_device *udev)
+  * Linux (2.6) currently has NO mechanisms to initiate that:  no khubd
+  * timer, no SRP, no requests through sysfs.
+  *
+- * If CONFIG_USB_SUSPEND isn't enabled, non-SuperSpeed devices really get
++ * If Runtime PM isn't enabled or used, non-SuperSpeed devices really get
+  * suspended only when their bus goes into global suspend (i.e., the root
+  * hub is suspended).  Nevertheless, we change @udev->state to
+  * USB_STATE_SUSPENDED as this is the device's "logical" state.  The actual
+@@ -3247,6 +3247,10 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
+ 	return status;
+ }
+ 
++#endif	/* CONFIG_PM */
++
++#ifdef	CONFIG_PM_RUNTIME
++
+ /* caller has locked udev */
+ int usb_remote_wakeup(struct usb_device *udev)
+ {
+@@ -3263,38 +3267,6 @@ int usb_remote_wakeup(struct usb_device *udev)
+ 	return status;
+ }
+ 
+-#else	/* CONFIG_USB_SUSPEND */
+-
+-/* When CONFIG_USB_SUSPEND isn't set, we never suspend or resume any ports. */
+-
+-int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+-{
+-	return 0;
+-}
+-
+-/* However we may need to do a reset-resume */
+-
+-int usb_port_resume(struct usb_device *udev, pm_message_t msg)
+-{
+-	struct usb_hub	*hub = usb_hub_to_struct_hub(udev->parent);
+-	int		port1 = udev->portnum;
+-	int		status;
+-	u16		portchange, portstatus;
+-
+-	status = hub_port_status(hub, port1, &portstatus, &portchange);
+-	status = check_port_resume_type(udev,
+-			hub, port1, status, portchange, portstatus);
+-
+-	if (status) {
+-		dev_dbg(&udev->dev, "can't resume, status %d\n", status);
+-		hub_port_logical_disconnect(hub, port1);
+-	} else if (udev->reset_resume) {
+-		dev_dbg(&udev->dev, "reset-resume\n");
+-		status = usb_reset_and_verify_device(udev);
+-	}
+-	return status;
+-}
+-
+ #endif
+ 
+ static int check_ports_changed(struct usb_hub *hub)
+@@ -4356,7 +4328,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 		if (portstatus & USB_PORT_STAT_ENABLE) {
+ 			status = 0;		/* Nothing to do */
+ 
+-#ifdef CONFIG_USB_SUSPEND
++#ifdef CONFIG_PM_RUNTIME
+ 		} else if (udev->state == USB_STATE_SUSPENDED &&
+ 				udev->persist_enabled) {
+ 			/* For a suspended device, treat this as a
+diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
+index 797f9d514732..06c4894bf181 100644
+--- a/drivers/usb/core/port.c
++++ b/drivers/usb/core/port.c
+@@ -71,7 +71,7 @@ static void usb_port_device_release(struct device *dev)
+ 	kfree(port_dev);
+ }
+ 
+-#ifdef CONFIG_USB_SUSPEND
++#ifdef CONFIG_PM_RUNTIME
+ static int usb_port_runtime_resume(struct device *dev)
+ {
+ 	struct usb_port *port_dev = to_usb_port(dev);
+@@ -139,7 +139,7 @@ static int usb_port_runtime_suspend(struct device *dev)
+ #endif
+ 
+ static const struct dev_pm_ops usb_port_pm_ops = {
+-#ifdef CONFIG_USB_SUSPEND
++#ifdef CONFIG_PM_RUNTIME
+ 	.runtime_suspend =	usb_port_runtime_suspend,
+ 	.runtime_resume =	usb_port_runtime_resume,
+ 	.runtime_idle =		pm_generic_runtime_idle,
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 3f81a3dc6867..aa38db44818a 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -338,7 +338,7 @@ static void remove_persist_attributes(struct device *dev)
+ 
+ #endif	/* CONFIG_PM */
+ 
+-#ifdef	CONFIG_USB_SUSPEND
++#ifdef	CONFIG_PM_RUNTIME
+ 
+ static ssize_t
+ show_connected_duration(struct device *dev, struct device_attribute *attr,
+@@ -544,7 +544,7 @@ static void remove_power_attributes(struct device *dev)
+ #define add_power_attributes(dev)	0
+ #define remove_power_attributes(dev)	do {} while (0)
+ 
+-#endif	/* CONFIG_USB_SUSPEND */
++#endif	/* CONFIG_PM_RUNTIME */
+ 
+ 
+ /* Descriptor fields */
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index f81b92572735..03eb7ae8fc1a 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -49,7 +49,7 @@ const char *usbcore_name = "usbcore";
+ 
+ static bool nousb;	/* Disable USB when built into kernel image */
+ 
+-#ifdef	CONFIG_USB_SUSPEND
++#ifdef	CONFIG_PM_RUNTIME
+ static int usb_autosuspend_delay = 2;		/* Default delay value,
+ 						 * in seconds */
+ module_param_named(autosuspend, usb_autosuspend_delay, int, 0644);
+@@ -307,7 +307,7 @@ static const struct dev_pm_ops usb_device_pm_ops = {
+ 	.thaw =		usb_dev_thaw,
+ 	.poweroff =	usb_dev_poweroff,
+ 	.restore =	usb_dev_restore,
+-#ifdef CONFIG_USB_SUSPEND
++#ifdef CONFIG_PM_RUNTIME
+ 	.runtime_suspend =	usb_runtime_suspend,
+ 	.runtime_resume =	usb_runtime_resume,
+ 	.runtime_idle =		usb_runtime_idle,
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index a7f20bde0e5e..823857767a16 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -93,7 +93,7 @@ static inline int usb_port_resume(struct usb_device *udev, pm_message_t msg)
+ 
+ #endif
+ 
+-#ifdef CONFIG_USB_SUSPEND
++#ifdef CONFIG_PM_RUNTIME
+ 
+ extern void usb_autosuspend_device(struct usb_device *udev);
+ extern int usb_autoresume_device(struct usb_device *udev);
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index 170b9399e09f..a573d5ff9adc 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -292,17 +292,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 		}
+ 	}
+ 
+-#ifdef	CONFIG_USB_SUSPEND
+-	/* REVISIT: the controller works fine for wakeup iff the root hub
+-	 * itself is "globally" suspended, but usbcore currently doesn't
+-	 * understand such things.
+-	 *
+-	 * System suspend currently expects to be able to suspend the entire
+-	 * device tree, device-at-a-time.  If we failed selective suspend
+-	 * reports, system suspend would fail; so the root hub code must claim
+-	 * success.  That's lying to usbcore, and it matters for runtime
+-	 * PM scenarios with selective suspend and remote wakeup...
+-	 */
++#ifdef	CONFIG_PM_RUNTIME
+ 	if (ehci->no_selective_suspend && device_can_wakeup(&pdev->dev))
+ 		ehci_warn(ehci, "selective suspend/wakeup unavailable\n");
+ #endif
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index db09dae7b557..60ff4220e8b4 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -580,14 +580,8 @@ static int ohci_start_port_reset (struct usb_hcd *hcd, unsigned port)
+ 
+ /* See usb 7.1.7.5:  root hubs must issue at least 50 msec reset signaling,
+  * not necessarily continuous ... to guard against resume signaling.
+- * The short timeout is safe for non-root hubs, and is backward-compatible
+- * with earlier Linux hosts.
+  */
+-#ifdef	CONFIG_USB_SUSPEND
+ #define	PORT_RESET_MSEC		50
+-#else
+-#define	PORT_RESET_MSEC		10
+-#endif
+ 
+ /* this timer value might be vendor-specific ... */
+ #define	PORT_RESET_HW_MSEC	10
+diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
+index d62f0404baaa..15ed7e8d887f 100644
+--- a/drivers/usb/host/sl811-hcd.c
++++ b/drivers/usb/host/sl811-hcd.c
+@@ -1755,7 +1755,7 @@ sl811h_probe(struct platform_device *dev)
+ 
+ /* for this device there's no useful distinction between the controller
+  * and its root hub, except that the root hub only gets direct PM calls
+- * when CONFIG_USB_SUSPEND is enabled.
++ * when CONFIG_PM_RUNTIME is enabled.
+  */
+ 
+ static int
+diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
+index 5efdffe32365..5c124bf5d018 100644
+--- a/drivers/usb/host/u132-hcd.c
++++ b/drivers/usb/host/u132-hcd.c
+@@ -3141,10 +3141,11 @@ static int u132_probe(struct platform_device *pdev)
+ 
+ 
+ #ifdef CONFIG_PM
+-/* for this device there's no useful distinction between the controller
+-* and its root hub, except that the root hub only gets direct PM calls
+-* when CONFIG_USB_SUSPEND is enabled.
+-*/
++/*
++ * for this device there's no useful distinction between the controller
++ * and its root hub, except that the root hub only gets direct PM calls
++ * when CONFIG_PM_RUNTIME is enabled.
++ */
+ static int u132_suspend(struct platform_device *pdev, pm_message_t state)
+ {
+ 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
+index 68914429482f..187a3ec1069a 100644
+--- a/drivers/usb/host/xhci-hub.c
++++ b/drivers/usb/host/xhci-hub.c
+@@ -1075,7 +1075,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
+ 			set_bit(port_index, &bus_state->bus_suspended);
+ 		}
+ 		/* USB core sets remote wake mask for USB 3.0 hubs,
+-		 * including the USB 3.0 roothub, but only if CONFIG_USB_SUSPEND
++		 * including the USB 3.0 roothub, but only if CONFIG_PM_RUNTIME
+ 		 * is enabled, so also enable remote wake here.
+ 		 */
+ 		if (hcd->self.root_hub->do_remote_wakeup) {
+diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
+index 53b8f89a0b1c..5156b720a53a 100644
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -3801,7 +3801,7 @@ int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1)
+ 	return raw_port;
+ }
+ 
+-#ifdef CONFIG_USB_SUSPEND
++#ifdef CONFIG_PM_RUNTIME
+ 
+ /* BESL to HIRD Encoding array for USB2 LPM */
+ static int xhci_besl_encoding[16] = {125, 150, 200, 300, 400, 500, 1000, 2000,
+@@ -4051,7 +4051,7 @@ int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
+ 	return 0;
+ }
+ 
+-#endif /* CONFIG_USB_SUSPEND */
++#endif /* CONFIG_PM_RUNTIME */
+ 
+ /*---------------------- USB 3.0 Link PM functions ------------------------*/
+ 
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 8d4bc173d66a..a0bee5a28d1a 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -617,7 +617,7 @@ static inline bool usb_acpi_power_manageable(struct usb_device *hdev, int index)
+ #endif
+ 
+ /* USB autosuspend and autoresume */
+-#ifdef CONFIG_USB_SUSPEND
++#ifdef CONFIG_PM_RUNTIME
+ extern void usb_enable_autosuspend(struct usb_device *udev);
+ extern void usb_disable_autosuspend(struct usb_device *udev);
+ 
+diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
+index 59694b5e5e90..f5f5c7dfda90 100644
+--- a/include/linux/usb/hcd.h
++++ b/include/linux/usb/hcd.h
+@@ -84,7 +84,7 @@ struct usb_hcd {
+ 
+ 	struct timer_list	rh_timer;	/* drives root-hub polling */
+ 	struct urb		*status_urb;	/* the current status urb */
+-#ifdef CONFIG_USB_SUSPEND
++#ifdef CONFIG_PM_RUNTIME
+ 	struct work_struct	wakeup_work;	/* for remote wakeup */
+ #endif
+ 
+@@ -593,14 +593,14 @@ extern int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg);
+ extern int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg);
+ #endif /* CONFIG_PM */
+ 
+-#ifdef CONFIG_USB_SUSPEND
++#ifdef CONFIG_PM_RUNTIME
+ extern void usb_hcd_resume_root_hub(struct usb_hcd *hcd);
+ #else
+ static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
+ {
+ 	return;
+ }
+-#endif /* CONFIG_USB_SUSPEND */
++#endif /* CONFIG_PM_RUNTIME */
+ 
+ /*-------------------------------------------------------------------------*/
+ 

commit 0aa2832dd0d9d8609fd8f15139bc7572541a1215
+Author: Alan Stern 
+Date:   Wed Mar 27 16:14:19 2013 -0400
+
+    USB: use "global suspend" for system sleep on USB-2 buses
+    
+    This patch (as1674) speeds up system sleep transitions by not
+    suspending each individual device on a USB-1.1 or USB-2 bus.  The
+    devices will automatically go into suspend when their root hubs are
+    suspended (i.e., stop sending out Start-Of-Frame packets) -- this is
+    what the USB spec calls "global suspend".
+    
+    Since this is what we do already when CONFIG_USB_SUSPEND isn't
+    enabled, it shouldn't cause any problems.
+    
+    Signed-off-by: Alan Stern 
+    CC: Peter Chen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 669da9ef714d..443d5cc9330b 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2886,9 +2886,11 @@ static int usb_disable_function_remotewakeup(struct usb_device *udev)
+  * Linux (2.6) currently has NO mechanisms to initiate that:  no khubd
+  * timer, no SRP, no requests through sysfs.
+  *
+- * If CONFIG_USB_SUSPEND isn't enabled, devices only really suspend when
+- * the root hub for their bus goes into global suspend ... so we don't
+- * (falsely) update the device power state to say it suspended.
++ * If CONFIG_USB_SUSPEND isn't enabled, non-SuperSpeed devices really get
++ * suspended only when their bus goes into global suspend (i.e., the root
++ * hub is suspended).  Nevertheless, we change @udev->state to
++ * USB_STATE_SUSPENDED as this is the device's "logical" state.  The actual
++ * upstream port setting is stored in @udev->port_is_suspended.
+  *
+  * Returns 0 on success, else negative errno.
+  */
+@@ -2899,6 +2901,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ 	enum pm_qos_flags_status pm_qos_stat;
+ 	int		port1 = udev->portnum;
+ 	int		status;
++	bool		really_suspend = true;
+ 
+ 	/* enable remote wakeup when appropriate; this lets the device
+ 	 * wake up the upstream hub (including maybe the root hub).
+@@ -2955,9 +2958,19 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ 	/* see 7.1.7.6 */
+ 	if (hub_is_superspeed(hub->hdev))
+ 		status = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_U3);
+-	else
++	else if (PMSG_IS_AUTO(msg))
+ 		status = set_port_feature(hub->hdev, port1,
+ 						USB_PORT_FEAT_SUSPEND);
++	/*
++	 * For system suspend, we do not need to enable the suspend feature
++	 * on individual USB-2 ports.  The devices will automatically go
++	 * into suspend a few ms after the root hub stops sending packets.
++	 * The USB 2.0 spec calls this "global suspend".
++	 */
++	else {
++		really_suspend = false;
++		status = 0;
++	}
+ 	if (status) {
+ 		dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",
+ 				port1, status);
+@@ -2993,8 +3006,10 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ 				(PMSG_IS_AUTO(msg) ? "auto-" : ""),
+ 				udev->do_remote_wakeup);
+ 		usb_set_device_state(udev, USB_STATE_SUSPENDED);
+-		udev->port_is_suspended = 1;
+-		msleep(10);
++		if (really_suspend) {
++			udev->port_is_suspended = 1;
++			msleep(10);
++		}
+ 	}
+ 
+ 	/*

commit e9e88fb7bca9f527ccdf4166a240a9023ba6ee73
+Author: Alan Stern 
+Date:   Wed Mar 27 16:14:01 2013 -0400
+
+    USB: avoid error messages when a device is disconnected
+    
+    This patch (as1673) reduces the amount of log spew from the hub driver
+    by removing a bunch of error messages in the case where the device in
+    question is already known to have been disconnected.  Since the
+    disconnect event itself appears in the log, there's no need for other
+    error messages.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Jenya Y 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
+index 271e761f563e..acbfeb0a0119 100644
+--- a/drivers/usb/core/generic.c
++++ b/drivers/usb/core/generic.c
+@@ -169,7 +169,7 @@ static int generic_probe(struct usb_device *udev)
+ 		c = usb_choose_configuration(udev);
+ 		if (c >= 0) {
+ 			err = usb_set_configuration(udev, c);
+-			if (err) {
++			if (err && err != -ENODEV) {
+ 				dev_err(&udev->dev, "can't set config #%d, error %d\n",
+ 					c, err);
+ 				/* This need not be fatal.  The user can try to
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 781546269d26..669da9ef714d 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -555,8 +555,9 @@ static int hub_port_status(struct usb_hub *hub, int port1,
+ 	mutex_lock(&hub->status_mutex);
+ 	ret = get_port_status(hub->hdev, port1, &hub->status->port);
+ 	if (ret < 4) {
+-		dev_err(hub->intfdev,
+-			"%s failed (err = %d)\n", __func__, ret);
++		if (ret != -ENODEV)
++			dev_err(hub->intfdev,
++				"%s failed (err = %d)\n", __func__, ret);
+ 		if (ret >= 0)
+ 			ret = -EIO;
+ 	} else {
+@@ -699,7 +700,7 @@ static void hub_tt_work(struct work_struct *work)
+ 		/* drop lock so HCD can concurrently report other TT errors */
+ 		spin_unlock_irqrestore (&hub->tt.lock, flags);
+ 		status = hub_clear_tt_buffer (hdev, clear->devinfo, clear->tt);
+-		if (status)
++		if (status && status != -ENODEV)
+ 			dev_err (&hdev->dev,
+ 				"clear tt %d (%04x) error %d\n",
+ 				clear->tt, clear->devinfo, status);
+@@ -837,10 +838,11 @@ static int hub_hub_status(struct usb_hub *hub,
+ 
+ 	mutex_lock(&hub->status_mutex);
+ 	ret = get_hub_status(hub->hdev, &hub->status->hub);
+-	if (ret < 0)
+-		dev_err (hub->intfdev,
+-			"%s failed (err = %d)\n", __func__, ret);
+-	else {
++	if (ret < 0) {
++		if (ret != -ENODEV)
++			dev_err(hub->intfdev,
++				"%s failed (err = %d)\n", __func__, ret);
++	} else {
+ 		*status = le16_to_cpu(hub->status->hub.wHubStatus);
+ 		*change = le16_to_cpu(hub->status->hub.wHubChange); 
+ 		ret = 0;
+@@ -877,11 +879,8 @@ static int hub_usb3_port_disable(struct usb_hub *hub, int port1)
+ 		return -EINVAL;
+ 
+ 	ret = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_SS_DISABLED);
+-	if (ret) {
+-		dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
+-				port1, ret);
++	if (ret)
+ 		return ret;
+-	}
+ 
+ 	/* Wait for the link to enter the disabled state. */
+ 	for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) {
+@@ -918,7 +917,7 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
+ 			ret = usb_clear_port_feature(hdev, port1,
+ 					USB_PORT_FEAT_ENABLE);
+ 	}
+-	if (ret)
++	if (ret && ret != -ENODEV)
+ 		dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
+ 				port1, ret);
+ 	return ret;
+@@ -2196,8 +2195,9 @@ static int usb_enumerate_device(struct usb_device *udev)
+ 	if (udev->config == NULL) {
+ 		err = usb_get_configuration(udev);
+ 		if (err < 0) {
+-			dev_err(&udev->dev, "can't read configurations, error %d\n",
+-				err);
++			if (err != -ENODEV)
++				dev_err(&udev->dev, "can't read configurations, error %d\n",
++						err);
+ 			return err;
+ 		}
+ 	}
+@@ -2644,14 +2644,16 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
+ 		status = set_port_feature(hub->hdev, port1, (warm ?
+ 					USB_PORT_FEAT_BH_PORT_RESET :
+ 					USB_PORT_FEAT_RESET));
+-		if (status) {
++		if (status == -ENODEV) {
++			;	/* The hub is gone */
++		} else if (status) {
+ 			dev_err(hub->intfdev,
+ 					"cannot %sreset port %d (err = %d)\n",
+ 					warm ? "warm " : "", port1, status);
+ 		} else {
+ 			status = hub_port_wait_reset(hub, port1, udev, delay,
+ 								warm);
+-			if (status && status != -ENOTCONN)
++			if (status && status != -ENOTCONN && status != -ENODEV)
+ 				dev_dbg(hub->intfdev,
+ 						"port_wait_reset: err = %d\n",
+ 						status);
+@@ -4094,9 +4096,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ 				goto fail;
+ 			}
+ 			if (r) {
+-				dev_err(&udev->dev,
+-					"device descriptor read/64, error %d\n",
+-					r);
++				if (r != -ENODEV)
++					dev_err(&udev->dev, "device descriptor read/64, error %d\n",
++							r);
+ 				retval = -EMSGSIZE;
+ 				continue;
+ 			}
+@@ -4116,9 +4118,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ 				msleep(200);
+ 			}
+ 			if (retval < 0) {
+-				dev_err(&udev->dev,
+-					"device not accepting address %d, error %d\n",
+-					devnum, retval);
++				if (retval != -ENODEV)
++					dev_err(&udev->dev, "device not accepting address %d, error %d\n",
++							devnum, retval);
+ 				goto fail;
+ 			}
+ 			if (udev->speed == USB_SPEED_SUPER) {
+@@ -4140,7 +4142,8 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ 
+ 		retval = usb_get_device_descriptor(udev, 8);
+ 		if (retval < 8) {
+-			dev_err(&udev->dev,
++			if (retval != -ENODEV)
++				dev_err(&udev->dev,
+ 					"device descriptor read/8, error %d\n",
+ 					retval);
+ 			if (retval >= 0)
+@@ -4194,8 +4197,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+   
+ 	retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);
+ 	if (retval < (signed)sizeof(udev->descriptor)) {
+-		dev_err(&udev->dev, "device descriptor read/all, error %d\n",
+-			retval);
++		if (retval != -ENODEV)
++			dev_err(&udev->dev, "device descriptor read/all, error %d\n",
++					retval);
+ 		if (retval >= 0)
+ 			retval = -ENOMSG;
+ 		goto fail;
+@@ -4377,7 +4381,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 				USB_PORT_STAT_C_ENABLE)) {
+ 		status = hub_port_debounce_be_stable(hub, port1);
+ 		if (status < 0) {
+-			if (printk_ratelimit())
++			if (status != -ENODEV && printk_ratelimit())
+ 				dev_err(hub_dev, "connect-debounce failed, "
+ 						"port %d disabled\n", port1);
+ 			portstatus &= ~USB_PORT_STAT_CONNECTION;
+@@ -4406,6 +4410,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 	else
+ 		unit_load = 100;
+ 
++	status = 0;
+ 	for (i = 0; i < SET_CONFIG_TRIES; i++) {
+ 
+ 		/* reallocate for each attempt, since references
+@@ -4530,9 +4535,11 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 	}
+ 	if (hub->hdev->parent ||
+ 			!hcd->driver->port_handed_over ||
+-			!(hcd->driver->port_handed_over)(hcd, port1))
+-		dev_err(hub_dev, "unable to enumerate USB device on port %d\n",
+-				port1);
++			!(hcd->driver->port_handed_over)(hcd, port1)) {
++		if (status != -ENOTCONN && status != -ENODEV)
++			dev_err(hub_dev, "unable to enumerate USB device on port %d\n",
++					port1);
++	}
+  
+ done:
+ 	hub_port_disable(hub, port1, 1);

commit afc2c9a2c359c850cea097c60a5f2b596efbbd88
+Author: Alan Stern 
+Date:   Fri Mar 22 13:32:10 2013 -0400
+
+    USB: EHCI: remove unused variable in unlink_empty_async()
+    
+    This patch (as1669) removes the check_unlinks_later flag in ehci-hcd's
+    unlink_empty_async().  It wasn't being used for anything and should
+    have been removed in an earlier patch, but I forgot about it.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 820583bfb5ee..50787a389fa8 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -1268,7 +1268,6 @@ static void unlink_empty_async(struct ehci_hcd *ehci)
+ {
+ 	struct ehci_qh		*qh;
+ 	struct ehci_qh		*qh_to_unlink = NULL;
+-	bool			check_unlinks_later = false;
+ 	int			count = 0;
+ 
+ 	/* Find the last async QH which has been empty for a timer cycle */
+@@ -1276,9 +1275,7 @@ static void unlink_empty_async(struct ehci_hcd *ehci)
+ 		if (list_empty(&qh->qtd_list) &&
+ 				qh->qh_state == QH_STATE_LINKED) {
+ 			++count;
+-			if (qh->unlink_cycle == ehci->async_unlink_cycle)
+-				check_unlinks_later = true;
+-			else
++			if (qh->unlink_cycle != ehci->async_unlink_cycle)
+ 				qh_to_unlink = qh;
+ 		}
+ 	}

commit 214ac7a0771d95d2f66d01bca5afeb2c9e8ac3c8
+Author: Alan Stern 
+Date:   Fri Mar 22 13:31:58 2013 -0400
+
+    USB: EHCI: improve end_unlink_async()
+    
+    This patch (as1665) changes the way ehci-hcd's end_unlink_async()
+    routine works in order to avoid recursive execution and to be more
+    efficient:
+    
+            Now when an IAA cycle ends, a new one gets started up right
+            away (if it is needed) instead of waiting until the
+            just-unlinked QH has been processed.
+    
+            The async_iaa list is renamed to async_idle, which better
+            expresses its new purpose: It is now the list of QHs which are
+            now completely idle and are waiting to be processed by
+            end_unlink_async().
+    
+            A new flag is added to track whether an IAA cycle is in
+            progress, because the list formerly known as async_iaa no
+            longer stores the QHs waiting for the IAA to finish.
+    
+            The decision about how many QHs to process when an IAA cycle
+            ends is now made at the end of the cycle, when we know the
+            current state of the hardware, rather than at the beginning.
+            This means a bunch of logic got moved from start_iaa_cycle()
+            to end_unlink_async().
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index b32323ca07d3..037a4729d549 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -483,7 +483,7 @@ static int ehci_init(struct usb_hcd *hcd)
+ 	 */
+ 	ehci->periodic_size = DEFAULT_I_TDPS;
+ 	INIT_LIST_HEAD(&ehci->async_unlink);
+-	INIT_LIST_HEAD(&ehci->async_iaa);
++	INIT_LIST_HEAD(&ehci->async_idle);
+ 	INIT_LIST_HEAD(&ehci->intr_unlink);
+ 	INIT_LIST_HEAD(&ehci->intr_qh_list);
+ 	INIT_LIST_HEAD(&ehci->cached_itd_list);
+@@ -752,7 +752,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 		/* guard against (alleged) silicon errata */
+ 		if (cmd & CMD_IAAD)
+ 			ehci_dbg(ehci, "IAA with IAAD still set?\n");
+-		if (!list_empty(&ehci->async_iaa))
++		if (ehci->iaa_in_progress)
+ 			COUNT(ehci->stats.iaa);
+ 		end_unlink_async(ehci);
+ 	}
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 4a01367bb2a0..820583bfb5ee 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -960,7 +960,7 @@ static void disable_async(struct ehci_hcd *ehci)
+ 
+ 	/* The async schedule and unlink lists are supposed to be empty */
+ 	WARN_ON(ehci->async->qh_next.qh || !list_empty(&ehci->async_unlink) ||
+-			!list_empty(&ehci->async_iaa));
++			!list_empty(&ehci->async_idle));
+ 
+ 	/* Don't turn off the schedule until ASS is 1 */
+ 	ehci_poll_ASS(ehci);
+@@ -1164,41 +1164,19 @@ static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		ehci->qh_scan_next = qh->qh_next.qh;
+ }
+ 
+-static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested)
++static void start_iaa_cycle(struct ehci_hcd *ehci)
+ {
+-	/*
+-	 * Do nothing if an IAA cycle is already running or
+-	 * if one will be started shortly.
+-	 */
+-	if (!list_empty(&ehci->async_iaa) || ehci->async_unlinking)
++	/* Do nothing if an IAA cycle is already running */
++	if (ehci->iaa_in_progress)
+ 		return;
++	ehci->iaa_in_progress = true;
+ 
+ 	/* If the controller isn't running, we don't have to wait for it */
+ 	if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) {
+-
+-		/* Do all the waiting QHs */
+-		list_splice_tail_init(&ehci->async_unlink, &ehci->async_iaa);
+-
+-		if (!nested)		/* Avoid recursion */
+-			end_unlink_async(ehci);
++		end_unlink_async(ehci);
+ 
+ 	/* Otherwise start a new IAA cycle */
+ 	} else if (likely(ehci->rh_state == EHCI_RH_RUNNING)) {
+-		struct ehci_qh		*qh;
+-
+-		/* Do only the first waiting QH (nVidia bug?) */
+-		qh = list_first_entry(&ehci->async_unlink, struct ehci_qh,
+-				unlink_node);
+-
+-		/*
+-		 * Intel (?) bug: The HC can write back the overlay region
+-		 * even after the IAA interrupt occurs.  In self-defense,
+-		 * always go through two IAA cycles for each QH.
+-		 */
+-		if (qh->qh_state == QH_STATE_UNLINK_WAIT)
+-			qh->qh_state = QH_STATE_UNLINK;
+-		else
+-			list_move_tail(&qh->unlink_node, &ehci->async_iaa);
+ 
+ 		/* Make sure the unlinks are all visible to the hardware */
+ 		wmb();
+@@ -1215,16 +1193,59 @@ static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested)
+ static void end_unlink_async(struct ehci_hcd *ehci)
+ {
+ 	struct ehci_qh		*qh;
++	bool			early_exit;
+ 
+ 	if (ehci->has_synopsys_hc_bug)
+ 		ehci_writel(ehci, (u32) ehci->async->qh_dma,
+ 			    &ehci->regs->async_next);
+ 
++	/* The current IAA cycle has ended */
++	ehci->iaa_in_progress = false;
++
++	if (list_empty(&ehci->async_unlink))
++		return;
++	qh = list_first_entry(&ehci->async_unlink, struct ehci_qh,
++			unlink_node);	/* QH whose IAA cycle just ended */
++
++	/*
++	 * If async_unlinking is set then this routine is already running,
++	 * either on the stack or on another CPU.
++	 */
++	early_exit = ehci->async_unlinking;
++
++	/* If the controller isn't running, process all the waiting QHs */
++	if (ehci->rh_state < EHCI_RH_RUNNING)
++		list_splice_tail_init(&ehci->async_unlink, &ehci->async_idle);
++
++	/*
++	 * Intel (?) bug: The HC can write back the overlay region even
++	 * after the IAA interrupt occurs.  In self-defense, always go
++	 * through two IAA cycles for each QH.
++	 */
++	else if (qh->qh_state == QH_STATE_UNLINK_WAIT) {
++		qh->qh_state = QH_STATE_UNLINK;
++		early_exit = true;
++	}
++
++	/* Otherwise process only the first waiting QH (NVIDIA bug?) */
++	else
++		list_move_tail(&qh->unlink_node, &ehci->async_idle);
++
++	/* Start a new IAA cycle if any QHs are waiting for it */
++	if (!list_empty(&ehci->async_unlink))
++		start_iaa_cycle(ehci);
++
++	/*
++	 * Don't allow nesting or concurrent calls,
++	 * or wait for the second IAA cycle for the next QH.
++	 */
++	if (early_exit)
++		return;
++
+ 	/* Process the idle QHs */
+- restart:
+ 	ehci->async_unlinking = true;
+-	while (!list_empty(&ehci->async_iaa)) {
+-		qh = list_first_entry(&ehci->async_iaa, struct ehci_qh,
++	while (!list_empty(&ehci->async_idle)) {
++		qh = list_first_entry(&ehci->async_idle, struct ehci_qh,
+ 				unlink_node);
+ 		list_del(&qh->unlink_node);
+ 
+@@ -1239,13 +1260,6 @@ static void end_unlink_async(struct ehci_hcd *ehci)
+ 		disable_async(ehci);
+ 	}
+ 	ehci->async_unlinking = false;
+-
+-	/* Start a new IAA cycle if any QHs are waiting for it */
+-	if (!list_empty(&ehci->async_unlink)) {
+-		start_iaa_cycle(ehci, true);
+-		if (unlikely(ehci->rh_state < EHCI_RH_RUNNING))
+-			goto restart;
+-	}
+ }
+ 
+ static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh);
+@@ -1270,8 +1284,7 @@ static void unlink_empty_async(struct ehci_hcd *ehci)
+ 	}
+ 
+ 	/* If nothing else is being unlinked, unlink the last empty QH */
+-	if (list_empty(&ehci->async_iaa) && list_empty(&ehci->async_unlink) &&
+-			qh_to_unlink) {
++	if (list_empty(&ehci->async_unlink) && qh_to_unlink) {
+ 		start_unlink_async(ehci, qh_to_unlink);
+ 		--count;
+ 	}
+@@ -1293,7 +1306,7 @@ static void unlink_empty_async_suspended(struct ehci_hcd *ehci)
+ 		WARN_ON(!list_empty(&qh->qtd_list));
+ 		single_unlink_async(ehci, qh);
+ 	}
+-	start_iaa_cycle(ehci, false);
++	start_iaa_cycle(ehci);
+ }
+ 
+ /* makes sure the async qh will become idle */
+@@ -1306,7 +1319,7 @@ static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		return;
+ 
+ 	single_unlink_async(ehci, qh);
+-	start_iaa_cycle(ehci, false);
++	start_iaa_cycle(ehci);
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
+index f63a98353efd..11e5b32f73e9 100644
+--- a/drivers/usb/host/ehci-timer.c
++++ b/drivers/usb/host/ehci-timer.c
+@@ -304,7 +304,7 @@ static void ehci_iaa_watchdog(struct ehci_hcd *ehci)
+ 	 * (a) SMP races against real IAA firing and retriggering, and
+ 	 * (b) clean HC shutdown, when IAA watchdog was pending.
+ 	 */
+-	if (ehci->rh_state != EHCI_RH_RUNNING)
++	if (!ehci->iaa_in_progress || ehci->rh_state != EHCI_RH_RUNNING)
+ 		return;
+ 
+ 	/* If we get here, IAA is *REALLY* late.  It's barely
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 13f67041502e..e66699950997 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -121,6 +121,7 @@ struct ehci_hcd {			/* one per controller */
+ 	bool			scanning:1;
+ 	bool			need_rescan:1;
+ 	bool			intr_unlinking:1;
++	bool			iaa_in_progress:1;
+ 	bool			async_unlinking:1;
+ 	bool			shutdown:1;
+ 	struct ehci_qh		*qh_scan_next;
+@@ -129,7 +130,7 @@ struct ehci_hcd {			/* one per controller */
+ 	struct ehci_qh		*async;
+ 	struct ehci_qh		*dummy;		/* For AMD quirk use */
+ 	struct list_head	async_unlink;
+-	struct list_head	async_iaa;
++	struct list_head	async_idle;
+ 	unsigned		async_unlink_cycle;
+ 	unsigned		async_count;	/* async activity count */
+ 

commit 6e018751a35f6ef7ad04eb8006b5886b6a7c47f5
+Author: Alan Stern 
+Date:   Fri Mar 22 13:31:45 2013 -0400
+
+    USB: EHCI: convert singly-linked lists to list_heads
+    
+    This patch (as1664) converts ehci-hcd's async_unlink, async_iaa, and
+    intr_unlink from singly-linked lists to standard doubly-linked
+    list_heads.  Originally it didn't seem necessary to use list_heads,
+    because items are always added to and removed from these lists in FIFO
+    order.  But now with more list processing going on, it's easier to use
+    the standard routines than continue with a roll-your-own approach.
+    
+    I don't know if the code ends up being notably shorter, but the
+    patterns will be more familiar to any kernel hacker.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
+index 70b496dc18a0..5429d2645bbc 100644
+--- a/drivers/usb/host/ehci-dbg.c
++++ b/drivers/usb/host/ehci-dbg.c
+@@ -510,14 +510,16 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf)
+ 	spin_lock_irqsave (&ehci->lock, flags);
+ 	for (qh = ehci->async->qh_next.qh; size > 0 && qh; qh = qh->qh_next.qh)
+ 		qh_lines (ehci, qh, &next, &size);
+-	if (ehci->async_unlink && size > 0) {
++	if (!list_empty(&ehci->async_unlink) && size > 0) {
+ 		temp = scnprintf(next, size, "\nunlink =\n");
+ 		size -= temp;
+ 		next += temp;
+ 
+-		for (qh = ehci->async_unlink; size > 0 && qh;
+-				qh = qh->unlink_next)
+-			qh_lines (ehci, qh, &next, &size);
++		list_for_each_entry(qh, &ehci->async_unlink, unlink_node) {
++			if (size <= 0)
++				break;
++			qh_lines(ehci, qh, &next, &size);
++		}
+ 	}
+ 	spin_unlock_irqrestore (&ehci->lock, flags);
+ 
+@@ -814,9 +816,10 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
+ 		}
+ 	}
+ 
+-	if (ehci->async_unlink) {
++	if (!list_empty(&ehci->async_unlink)) {
+ 		temp = scnprintf(next, size, "async unlink qh %p\n",
+-				ehci->async_unlink);
++				list_first_entry(&ehci->async_unlink,
++						struct ehci_qh, unlink_node));
+ 		size -= temp;
+ 		next += temp;
+ 	}
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 87fe3daaa092..b32323ca07d3 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -482,6 +482,9 @@ static int ehci_init(struct usb_hcd *hcd)
+ 	 * periodic_size can shrink by USBCMD update if hcc_params allows.
+ 	 */
+ 	ehci->periodic_size = DEFAULT_I_TDPS;
++	INIT_LIST_HEAD(&ehci->async_unlink);
++	INIT_LIST_HEAD(&ehci->async_iaa);
++	INIT_LIST_HEAD(&ehci->intr_unlink);
+ 	INIT_LIST_HEAD(&ehci->intr_qh_list);
+ 	INIT_LIST_HEAD(&ehci->cached_itd_list);
+ 	INIT_LIST_HEAD(&ehci->cached_sitd_list);
+@@ -749,7 +752,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 		/* guard against (alleged) silicon errata */
+ 		if (cmd & CMD_IAAD)
+ 			ehci_dbg(ehci, "IAA with IAAD still set?\n");
+-		if (ehci->async_iaa)
++		if (!list_empty(&ehci->async_iaa))
+ 			COUNT(ehci->stats.iaa);
+ 		end_unlink_async(ehci);
+ 	}
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index fca741dbf9df..4a01367bb2a0 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -958,8 +958,9 @@ static void disable_async(struct ehci_hcd *ehci)
+ 	if (--ehci->async_count)
+ 		return;
+ 
+-	/* The async schedule and async_unlink list are supposed to be empty */
+-	WARN_ON(ehci->async->qh_next.qh || ehci->async_unlink);
++	/* The async schedule and unlink lists are supposed to be empty */
++	WARN_ON(ehci->async->qh_next.qh || !list_empty(&ehci->async_unlink) ||
++			!list_empty(&ehci->async_iaa));
+ 
+ 	/* Don't turn off the schedule until ASS is 1 */
+ 	ehci_poll_ASS(ehci);
+@@ -1150,11 +1151,7 @@ static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 
+ 	/* Add to the end of the list of QHs waiting for the next IAAD */
+ 	qh->qh_state = QH_STATE_UNLINK_WAIT;
+-	if (ehci->async_unlink)
+-		ehci->async_unlink_last->unlink_next = qh;
+-	else
+-		ehci->async_unlink = qh;
+-	ehci->async_unlink_last = qh;
++	list_add_tail(&qh->unlink_node, &ehci->async_unlink);
+ 
+ 	/* Unlink it from the schedule */
+ 	prev = ehci->async;
+@@ -1173,15 +1170,14 @@ static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested)
+ 	 * Do nothing if an IAA cycle is already running or
+ 	 * if one will be started shortly.
+ 	 */
+-	if (ehci->async_iaa || ehci->async_unlinking)
++	if (!list_empty(&ehci->async_iaa) || ehci->async_unlinking)
+ 		return;
+ 
+ 	/* If the controller isn't running, we don't have to wait for it */
+ 	if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) {
+ 
+ 		/* Do all the waiting QHs */
+-		ehci->async_iaa = ehci->async_unlink;
+-		ehci->async_unlink = NULL;
++		list_splice_tail_init(&ehci->async_unlink, &ehci->async_iaa);
+ 
+ 		if (!nested)		/* Avoid recursion */
+ 			end_unlink_async(ehci);
+@@ -1191,20 +1187,18 @@ static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested)
+ 		struct ehci_qh		*qh;
+ 
+ 		/* Do only the first waiting QH (nVidia bug?) */
+-		qh = ehci->async_unlink;
++		qh = list_first_entry(&ehci->async_unlink, struct ehci_qh,
++				unlink_node);
+ 
+ 		/*
+ 		 * Intel (?) bug: The HC can write back the overlay region
+ 		 * even after the IAA interrupt occurs.  In self-defense,
+ 		 * always go through two IAA cycles for each QH.
+ 		 */
+-		if (qh->qh_state == QH_STATE_UNLINK_WAIT) {
++		if (qh->qh_state == QH_STATE_UNLINK_WAIT)
+ 			qh->qh_state = QH_STATE_UNLINK;
+-		} else {
+-			ehci->async_iaa = qh;
+-			ehci->async_unlink = qh->unlink_next;
+-			qh->unlink_next = NULL;
+-		}
++		else
++			list_move_tail(&qh->unlink_node, &ehci->async_iaa);
+ 
+ 		/* Make sure the unlinks are all visible to the hardware */
+ 		wmb();
+@@ -1229,10 +1223,10 @@ static void end_unlink_async(struct ehci_hcd *ehci)
+ 	/* Process the idle QHs */
+  restart:
+ 	ehci->async_unlinking = true;
+-	while (ehci->async_iaa) {
+-		qh = ehci->async_iaa;
+-		ehci->async_iaa = qh->unlink_next;
+-		qh->unlink_next = NULL;
++	while (!list_empty(&ehci->async_iaa)) {
++		qh = list_first_entry(&ehci->async_iaa, struct ehci_qh,
++				unlink_node);
++		list_del(&qh->unlink_node);
+ 
+ 		qh->qh_state = QH_STATE_IDLE;
+ 		qh->qh_next.qh = NULL;
+@@ -1247,7 +1241,7 @@ static void end_unlink_async(struct ehci_hcd *ehci)
+ 	ehci->async_unlinking = false;
+ 
+ 	/* Start a new IAA cycle if any QHs are waiting for it */
+-	if (ehci->async_unlink) {
++	if (!list_empty(&ehci->async_unlink)) {
+ 		start_iaa_cycle(ehci, true);
+ 		if (unlikely(ehci->rh_state < EHCI_RH_RUNNING))
+ 			goto restart;
+@@ -1276,7 +1270,8 @@ static void unlink_empty_async(struct ehci_hcd *ehci)
+ 	}
+ 
+ 	/* If nothing else is being unlinked, unlink the last empty QH */
+-	if (!ehci->async_iaa && !ehci->async_unlink && qh_to_unlink) {
++	if (list_empty(&ehci->async_iaa) && list_empty(&ehci->async_unlink) &&
++			qh_to_unlink) {
+ 		start_unlink_async(ehci, qh_to_unlink);
+ 		--count;
+ 	}
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index e7a2dbd27b1e..c833febf8df0 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -620,17 +620,13 @@ static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	qh->unlink_cycle = ehci->intr_unlink_cycle;
+ 
+ 	/* New entries go at the end of the intr_unlink list */
+-	if (ehci->intr_unlink)
+-		ehci->intr_unlink_last->unlink_next = qh;
+-	else
+-		ehci->intr_unlink = qh;
+-	ehci->intr_unlink_last = qh;
++	list_add_tail(&qh->unlink_node, &ehci->intr_unlink);
+ 
+ 	if (ehci->intr_unlinking)
+ 		;	/* Avoid recursive calls */
+ 	else if (ehci->rh_state < EHCI_RH_RUNNING)
+ 		ehci_handle_intr_unlinks(ehci);
+-	else if (ehci->intr_unlink == qh) {
++	else if (ehci->intr_unlink.next == &qh->unlink_node) {
+ 		ehci_enable_event(ehci, EHCI_HRTIMER_UNLINK_INTR, true);
+ 		++ehci->intr_unlink_cycle;
+ 	}
+diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
+index e7363332887e..f63a98353efd 100644
+--- a/drivers/usb/host/ehci-timer.c
++++ b/drivers/usb/host/ehci-timer.c
+@@ -229,18 +229,19 @@ static void ehci_handle_intr_unlinks(struct ehci_hcd *ehci)
+ 	 * process all the QHs on the list.
+ 	 */
+ 	ehci->intr_unlinking = true;
+-	while (ehci->intr_unlink) {
+-		struct ehci_qh	*qh = ehci->intr_unlink;
++	while (!list_empty(&ehci->intr_unlink)) {
++		struct ehci_qh	*qh;
+ 
++		qh = list_first_entry(&ehci->intr_unlink, struct ehci_qh,
++				unlink_node);
+ 		if (!stopped && qh->unlink_cycle == ehci->intr_unlink_cycle)
+ 			break;
+-		ehci->intr_unlink = qh->unlink_next;
+-		qh->unlink_next = NULL;
++		list_del(&qh->unlink_node);
+ 		end_unlink_intr(ehci, qh);
+ 	}
+ 
+ 	/* Handle remaining entries later */
+-	if (ehci->intr_unlink) {
++	if (!list_empty(&ehci->intr_unlink)) {
+ 		ehci_enable_event(ehci, EHCI_HRTIMER_UNLINK_INTR, true);
+ 		++ehci->intr_unlink_cycle;
+ 	}
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 6815209511aa..13f67041502e 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -128,9 +128,8 @@ struct ehci_hcd {			/* one per controller */
+ 	/* async schedule support */
+ 	struct ehci_qh		*async;
+ 	struct ehci_qh		*dummy;		/* For AMD quirk use */
+-	struct ehci_qh		*async_unlink;
+-	struct ehci_qh		*async_unlink_last;
+-	struct ehci_qh		*async_iaa;
++	struct list_head	async_unlink;
++	struct list_head	async_iaa;
+ 	unsigned		async_unlink_cycle;
+ 	unsigned		async_count;	/* async activity count */
+ 
+@@ -143,8 +142,7 @@ struct ehci_hcd {			/* one per controller */
+ 	unsigned		i_thresh;	/* uframes HC might cache */
+ 
+ 	union ehci_shadow	*pshadow;	/* mirror hw periodic table */
+-	struct ehci_qh		*intr_unlink;
+-	struct ehci_qh		*intr_unlink_last;
++	struct list_head	intr_unlink;
+ 	unsigned		intr_unlink_cycle;
+ 	unsigned		now_frame;	/* frame from HC hardware */
+ 	unsigned		last_iso_frame;	/* last frame scanned for iso */
+@@ -380,7 +378,7 @@ struct ehci_qh {
+ 	struct list_head	qtd_list;	/* sw qtd list */
+ 	struct list_head	intr_node;	/* list of intr QHs */
+ 	struct ehci_qtd		*dummy;
+-	struct ehci_qh		*unlink_next;	/* next on unlink list */
++	struct list_head	unlink_node;
+ 
+ 	unsigned		unlink_cycle;
+ 

commit 7655e3160c78a18c2ecf7bf4dee0bbfe58575c7f
+Author: Alan Stern 
+Date:   Fri Mar 22 13:31:29 2013 -0400
+
+    USB: EHCI: consolidate code in ehci_urb_dequeue()
+    
+    This patch (as1668) consolidates two nearly identical code paths in
+    ehci_urb_dequeue().  The test for !qh can be removed because it will
+    never succeed; the fact that usb_hcd_check_unlink_urb() returned 0
+    means that urb must be queued and therefore urb->hcpriv must point to
+    a QH.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 93f4cd75845e..87fe3daaa092 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -896,17 +896,21 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ 	if (rc)
+ 		goto done;
+ 
+-	switch (usb_pipetype (urb->pipe)) {
+-	// case PIPE_CONTROL:
+-	// case PIPE_BULK:
+-	default:
++	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
++		/*
++		 * We don't expedite dequeue for isochronous URBs.
++		 * Just wait until they complete normally or their
++		 * time slot expires.
++		 */
++	} else {
+ 		qh = (struct ehci_qh *) urb->hcpriv;
+-		if (!qh)
+-			break;
+ 		qh->exception = 1;
+ 		switch (qh->qh_state) {
+ 		case QH_STATE_LINKED:
+-			start_unlink_async(ehci, qh);
++			if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)
++				start_unlink_intr(ehci, qh);
++			else
++				start_unlink_async(ehci, qh);
+ 			break;
+ 		case QH_STATE_COMPLETING:
+ 			qh->dequeue_during_giveback = 1;
+@@ -920,36 +924,6 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ 			qh_completions(ehci, qh);
+ 			break;
+ 		}
+-		break;
+-
+-	case PIPE_INTERRUPT:
+-		qh = (struct ehci_qh *) urb->hcpriv;
+-		if (!qh)
+-			break;
+-		qh->exception = 1;
+-		switch (qh->qh_state) {
+-		case QH_STATE_LINKED:
+-			start_unlink_intr(ehci, qh);
+-			break;
+-		case QH_STATE_COMPLETING:
+-			qh->dequeue_during_giveback = 1;
+-			break;
+-		case QH_STATE_IDLE:
+-			qh_completions (ehci, qh);
+-			break;
+-		default:
+-			ehci_dbg (ehci, "bogus qh %p state %d\n",
+-					qh, qh->qh_state);
+-			goto done;
+-		}
+-		break;
+-
+-	case PIPE_ISOCHRONOUS:
+-		// itd or sitd ...
+-
+-		// wait till next completion, do it then.
+-		// completion irqs can wait up to 1024 msec,
+-		break;
+ 	}
+ done:
+ 	spin_unlock_irqrestore (&ehci->lock, flags);

commit 7bc782d73c7db042ecc965866b8c1c2b7d6e93d6
+Author: Alan Stern 
+Date:   Fri Mar 22 13:31:11 2013 -0400
+
+    USB: EHCI: split needs_rescan into two flags
+    
+    This patch (as1662) does some more QH-related cleanup in ehci-hcd.
+    The qh->needs_rescan flag is currently used for two different
+    purposes; the patch replaces it with two separate flags for greater
+    clarity: qh->dequeue_during_giveback indicates that a completion
+    handler dequeued an URB (implying that a rescan is needed), and
+    qh->exception indicates that the QH is in an exceptional state
+    requiring an unlink (either it encountered an I/O error or an unlink
+    was requested).
+    
+    The new flags get set where the dequeue, exception, or unlink request
+    occurred, rather than where the unlink is started.  This is so that in
+    the future, if we need to, we will be able to tell apart unlinks that
+    truly were required from those that were carried out merely because
+    the QH wasn't being used.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 0c3314c41363..93f4cd75845e 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -903,11 +903,14 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ 		qh = (struct ehci_qh *) urb->hcpriv;
+ 		if (!qh)
+ 			break;
++		qh->exception = 1;
+ 		switch (qh->qh_state) {
+ 		case QH_STATE_LINKED:
+-		case QH_STATE_COMPLETING:
+ 			start_unlink_async(ehci, qh);
+ 			break;
++		case QH_STATE_COMPLETING:
++			qh->dequeue_during_giveback = 1;
++			break;
+ 		case QH_STATE_UNLINK:
+ 		case QH_STATE_UNLINK_WAIT:
+ 			/* already started */
+@@ -923,11 +926,14 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ 		qh = (struct ehci_qh *) urb->hcpriv;
+ 		if (!qh)
+ 			break;
++		qh->exception = 1;
+ 		switch (qh->qh_state) {
+ 		case QH_STATE_LINKED:
+-		case QH_STATE_COMPLETING:
+ 			start_unlink_intr(ehci, qh);
+ 			break;
++		case QH_STATE_COMPLETING:
++			qh->dequeue_during_giveback = 1;
++			break;
+ 		case QH_STATE_IDLE:
+ 			qh_completions (ehci, qh);
+ 			break;
+@@ -984,6 +990,7 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 		goto done;
+ 	}
+ 
++	qh->exception = 1;
+ 	if (ehci->rh_state < EHCI_RH_RUNNING)
+ 		qh->qh_state = QH_STATE_IDLE;
+ 	switch (qh->qh_state) {
+@@ -1052,13 +1059,12 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 		usb_settoggle(qh->dev, epnum, is_out, 0);
+ 		if (!list_empty(&qh->qtd_list)) {
+ 			WARN_ONCE(1, "clear_halt for a busy endpoint\n");
+-		} else if (qh->qh_state == QH_STATE_LINKED ||
+-				qh->qh_state == QH_STATE_COMPLETING) {
+-
++		} else {
+ 			/* The toggle value in the QH can't be updated
+ 			 * while the QH is active.  Unlink it now;
+ 			 * re-linking will call qh_refresh().
+ 			 */
++			qh->exception = 1;
+ 			if (eptype == USB_ENDPOINT_XFER_BULK)
+ 				start_unlink_async(ehci, qh);
+ 			else
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index c95f60d43b1a..fca741dbf9df 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -322,7 +322,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+  rescan:
+ 	last = NULL;
+ 	last_status = -EINPROGRESS;
+-	qh->needs_rescan = 0;
++	qh->dequeue_during_giveback = 0;
+ 
+ 	/* remove de-activated QTDs from front of queue.
+ 	 * after faults (including short reads), cleanup this urb
+@@ -518,18 +518,12 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	}
+ 
+ 	/* Do we need to rescan for URBs dequeued during a giveback? */
+-	if (unlikely(qh->needs_rescan)) {
++	if (unlikely(qh->dequeue_during_giveback)) {
+ 		/* If the QH is already unlinked, do the rescan now. */
+ 		if (state == QH_STATE_IDLE)
+ 			goto rescan;
+ 
+-		/* Otherwise we have to wait until the QH is fully unlinked.
+-		 * Our caller will start an unlink if qh->needs_rescan is
+-		 * set.  But if an unlink has already started, nothing needs
+-		 * to be done.
+-		 */
+-		if (state != QH_STATE_LINKED)
+-			qh->needs_rescan = 0;
++		/* Otherwise the caller must unlink the QH. */
+ 	}
+ 
+ 	/* restore original state; caller must unlink or relink */
+@@ -538,29 +532,23 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	/* be sure the hardware's done with the qh before refreshing
+ 	 * it after fault cleanup, or recovering from silicon wrongly
+ 	 * overlaying the dummy qtd (which reduces DMA chatter).
++	 *
++	 * We won't refresh a QH that's linked (after the HC
++	 * stopped the queue).  That avoids a race:
++	 *  - HC reads first part of QH;
++	 *  - CPU updates that first part and the token;
++	 *  - HC reads rest of that QH, including token
++	 * Result:  HC gets an inconsistent image, and then
++	 * DMAs to/from the wrong memory (corrupting it).
++	 *
++	 * That should be rare for interrupt transfers,
++	 * except maybe high bandwidth ...
+ 	 */
+-	if (stopped != 0 || hw->hw_qtd_next == EHCI_LIST_END(ehci)) {
+-		if (state == QH_STATE_LINKED) {
+-			/*
+-			 * We won't refresh a QH that's linked (after the HC
+-			 * stopped the queue).  That avoids a race:
+-			 *  - HC reads first part of QH;
+-			 *  - CPU updates that first part and the token;
+-			 *  - HC reads rest of that QH, including token
+-			 * Result:  HC gets an inconsistent image, and then
+-			 * DMAs to/from the wrong memory (corrupting it).
+-			 *
+-			 * That should be rare for interrupt transfers,
+-			 * except maybe high bandwidth ...
+-			 *
+-			 * Therefore tell the caller to start an unlink.
+-			 */
+-			qh->needs_rescan = 1;
+-		}
+-		/* otherwise, unlink already started */
+-	}
++	if (stopped != 0 || hw->hw_qtd_next == EHCI_LIST_END(ehci))
++		qh->exception = 1;
+ 
+-	return qh->needs_rescan;
++	/* Let the caller know if the QH needs to be unlinked. */
++	return qh->exception;
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -1002,8 +990,9 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	head->qh_next.qh = qh;
+ 	head->hw->hw_next = dma;
+ 
+-	qh->xacterrs = 0;
+ 	qh->qh_state = QH_STATE_LINKED;
++	qh->xacterrs = 0;
++	qh->exception = 0;
+ 	/* qtd completions reported later by interrupt */
+ 
+ 	enable_async(ehci);
+@@ -1317,16 +1306,9 @@ static void unlink_empty_async_suspended(struct ehci_hcd *ehci)
+ 
+ static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ {
+-	/*
+-	 * If the QH isn't linked then there's nothing we can do
+-	 * unless we were called during a giveback, in which case
+-	 * qh_completions() has to deal with it.
+-	 */
+-	if (qh->qh_state != QH_STATE_LINKED) {
+-		if (qh->qh_state == QH_STATE_COMPLETING)
+-			qh->needs_rescan = 1;
++	/* If the QH isn't linked then there's nothing we can do. */
++	if (qh->qh_state != QH_STATE_LINKED)
+ 		return;
+-	}
+ 
+ 	single_unlink_async(ehci, qh);
+ 	start_iaa_cycle(ehci, false);
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 5c82bbab9a48..e7a2dbd27b1e 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -539,6 +539,7 @@ static void qh_link_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	}
+ 	qh->qh_state = QH_STATE_LINKED;
+ 	qh->xacterrs = 0;
++	qh->exception = 0;
+ 
+ 	/* update per-qh bandwidth for usbfs */
+ 	ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->period
+@@ -602,15 +603,9 @@ static void qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 
+ static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ {
+-	/* If the QH isn't linked then there's nothing we can do
+-	 * unless we were called during a giveback, in which case
+-	 * qh_completions() has to deal with it.
+-	 */
+-	if (qh->qh_state != QH_STATE_LINKED) {
+-		if (qh->qh_state == QH_STATE_COMPLETING)
+-			qh->needs_rescan = 1;
++	/* If the QH isn't linked then there's nothing we can do. */
++	if (qh->qh_state != QH_STATE_LINKED)
+ 		return;
+-	}
+ 
+ 	qh_unlink_periodic (ehci, qh);
+ 
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 36c3a8210595..6815209511aa 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -384,7 +384,6 @@ struct ehci_qh {
+ 
+ 	unsigned		unlink_cycle;
+ 
+-	u8			needs_rescan;	/* Dequeue during giveback */
+ 	u8			qh_state;
+ #define	QH_STATE_LINKED		1		/* HC sees this */
+ #define	QH_STATE_UNLINK		2		/* HC may still see this */
+@@ -407,6 +406,9 @@ struct ehci_qh {
+ 	struct usb_device	*dev;		/* access to TT */
+ 	unsigned		is_out:1;	/* bulk or intr OUT */
+ 	unsigned		clearing_tt:1;	/* Clear-TT-Buf in progress */
++	unsigned		dequeue_during_giveback:1;
++	unsigned		exception:1;	/* got a fault, or an unlink
++						   was requested */
+ };
+ 
+ /*-------------------------------------------------------------------------*/

commit 79bcf7b02ba3d45bafe81a2753cedb8ef49548e3
+Author: Alan Stern 
+Date:   Fri Mar 22 13:30:56 2013 -0400
+
+    USB: EHCI: change return value of qh_completions()
+    
+    This patch (as1658) cleans up the usage of qh_completions() in
+    ehci-hcd.  Currently the function's return value indicates whether any
+    URBs were given back; the idea was that the caller can scan the QH
+    over again to handle any URBs that were dequeued by a completion
+    handler.  This is not necessary; when qh_completions() is ready to
+    give back dequeued URBs, it does its own rescanning.
+    
+    Therefore the new return value will be a flag indicating whether the
+    caller needs to unlink the QH.  This is more convenient than forcing
+    the caller to check qh->needs_rescan, and it makes a lot more sense --
+    why should "needs_rescan" imply that an unlink is needed?  The callers
+    are also changed to remove the unneeded rescans.
+    
+    Lastly, the check for whether qh->qtd_list is non-empty is removed
+    from the start of qh_completions().  Two of the callers have to make
+    this test anyway, so the same test can simply be added to the other
+    two callers.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index b824cb674898..c95f60d43b1a 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -292,8 +292,8 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh);
+ 
+ /*
+  * Process and free completed qtds for a qh, returning URBs to drivers.
+- * Chases up to qh->hw_current.  Returns number of completions called,
+- * indicating how much "real" work we did.
++ * Chases up to qh->hw_current.  Returns nonzero if the caller should
++ * unlink qh.
+  */
+ static unsigned
+ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+@@ -302,13 +302,9 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	struct list_head	*entry, *tmp;
+ 	int			last_status;
+ 	int			stopped;
+-	unsigned		count = 0;
+ 	u8			state;
+ 	struct ehci_qh_hw	*hw = qh->hw;
+ 
+-	if (unlikely (list_empty (&qh->qtd_list)))
+-		return count;
+-
+ 	/* completions (or tasks on other cpus) must never clobber HALT
+ 	 * till we've gone through and cleaned everything up, even when
+ 	 * they add urbs to this qh's queue or mark them for unlinking.
+@@ -345,7 +341,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		if (last) {
+ 			if (likely (last->urb != urb)) {
+ 				ehci_urb_done(ehci, last->urb, last_status);
+-				count++;
+ 				last_status = -EINPROGRESS;
+ 			}
+ 			ehci_qtd_free (ehci, last);
+@@ -519,7 +514,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	/* last urb's completion might still need calling */
+ 	if (likely (last != NULL)) {
+ 		ehci_urb_done(ehci, last->urb, last_status);
+-		count++;
+ 		ehci_qtd_free (ehci, last);
+ 	}
+ 
+@@ -566,7 +560,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		/* otherwise, unlink already started */
+ 	}
+ 
+-	return count;
++	return qh->needs_rescan;
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -1254,7 +1248,8 @@ static void end_unlink_async(struct ehci_hcd *ehci)
+ 		qh->qh_state = QH_STATE_IDLE;
+ 		qh->qh_next.qh = NULL;
+ 
+-		qh_completions(ehci, qh);
++		if (!list_empty(&qh->qtd_list))
++			qh_completions(ehci, qh);
+ 		if (!list_empty(&qh->qtd_list) &&
+ 				ehci->rh_state == EHCI_RH_RUNNING)
+ 			qh_link_async(ehci, qh);
+@@ -1348,7 +1343,7 @@ static void scan_async (struct ehci_hcd *ehci)
+ 	while (ehci->qh_scan_next) {
+ 		qh = ehci->qh_scan_next;
+ 		ehci->qh_scan_next = qh->qh_next.qh;
+- rescan:
++
+ 		/* clean any finished work for this qh */
+ 		if (!list_empty(&qh->qtd_list)) {
+ 			int temp;
+@@ -1361,14 +1356,13 @@ static void scan_async (struct ehci_hcd *ehci)
+ 			 * in single_unlink_async().
+ 			 */
+ 			temp = qh_completions(ehci, qh);
+-			if (qh->needs_rescan) {
++			if (unlikely(temp)) {
+ 				start_unlink_async(ehci, qh);
+ 			} else if (list_empty(&qh->qtd_list)
+ 					&& qh->qh_state == QH_STATE_LINKED) {
+ 				qh->unlink_cycle = ehci->async_unlink_cycle;
+ 				check_unlinks_later = true;
+-			} else if (temp != 0)
+-				goto rescan;
++			}
+ 		}
+ 	}
+ 
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 66259dc7822e..5c82bbab9a48 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -649,7 +649,8 @@ static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	qh->qh_state = QH_STATE_IDLE;
+ 	hw->hw_next = EHCI_LIST_END(ehci);
+ 
+-	qh_completions(ehci, qh);
++	if (!list_empty(&qh->qtd_list))
++		qh_completions(ehci, qh);
+ 
+ 	/* reschedule QH iff another request is queued */
+ 	if (!list_empty(&qh->qtd_list) && ehci->rh_state == EHCI_RH_RUNNING) {
+@@ -914,7 +915,7 @@ static void scan_intr(struct ehci_hcd *ehci)
+ 
+ 	list_for_each_entry_safe(qh, ehci->qh_scan_next, &ehci->intr_qh_list,
+ 			intr_node) {
+- rescan:
++
+ 		/* clean any finished work for this qh */
+ 		if (!list_empty(&qh->qtd_list)) {
+ 			int temp;
+@@ -927,12 +928,9 @@ static void scan_intr(struct ehci_hcd *ehci)
+ 			 * in qh_unlink_periodic().
+ 			 */
+ 			temp = qh_completions(ehci, qh);
+-			if (unlikely(qh->needs_rescan ||
+-					(list_empty(&qh->qtd_list) &&
+-						qh->qh_state == QH_STATE_LINKED)))
++			if (unlikely(temp || (list_empty(&qh->qtd_list) &&
++					qh->qh_state == QH_STATE_LINKED)))
+ 				start_unlink_intr(ehci, qh);
+-			else if (temp != 0)
+-				goto rescan;
+ 		}
+ 	}
+ }

commit c1fdb68e3d73741630ca16695cf9176c233be7ed
+Author: Alan Stern 
+Date:   Fri Mar 22 13:30:43 2013 -0400
+
+    USB: EHCI: changes related to qh_refresh()
+    
+    This patch (as1638) makes several changes to the ehci-hcd driver, all
+    related to the qh_refresh() function.  This function must be called
+    whenever an idle QH gets linked back into either the async or the
+    periodic schedule.
+    
+            Change a BUG_ON() in the qh_update routine to a WARN_ON().
+            Since this code runs in atomic context, a BUG_ON() would
+            immediately freeze the whole system.
+    
+            Remove two unneeded calls to qh_refresh(), one when a QH is
+            initialized and one when a QH becomes idle.  Adjust the
+            adjacent comments accordingly.
+    
+            Move the qh_refresh() and qh_link_periodic() calls for new
+            interrupt URBs to after the new TDs have been added.
+    
+            As a result of the previous two changes, qh_refresh() is never
+            called when the qtd_list is empty.  The corresponding check in
+            qh_refresh() can be removed, along with an indentation level.
+    
+    These changes should not cause any alteration of behavior.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 23d136904285..b824cb674898 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -90,7 +90,7 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
+ 	struct ehci_qh_hw *hw = qh->hw;
+ 
+ 	/* writes to an active overlay are unsafe */
+-	BUG_ON(qh->qh_state != QH_STATE_IDLE);
++	WARN_ON(qh->qh_state != QH_STATE_IDLE);
+ 
+ 	hw->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma);
+ 	hw->hw_alt_next = EHCI_LIST_END(ehci);
+@@ -123,26 +123,19 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ {
+ 	struct ehci_qtd *qtd;
+ 
+-	if (list_empty (&qh->qtd_list))
+-		qtd = qh->dummy;
+-	else {
+-		qtd = list_entry (qh->qtd_list.next,
+-				struct ehci_qtd, qtd_list);
+-		/*
+-		 * first qtd may already be partially processed.
+-		 * If we come here during unlink, the QH overlay region
+-		 * might have reference to the just unlinked qtd. The
+-		 * qtd is updated in qh_completions(). Update the QH
+-		 * overlay here.
+-		 */
+-		if (qh->hw->hw_token & ACTIVE_BIT(ehci)) {
+-			qh->hw->hw_qtd_next = qtd->hw_next;
+-			qtd = NULL;
+-		}
+-	}
++	qtd = list_entry(qh->qtd_list.next, struct ehci_qtd, qtd_list);
+ 
+-	if (qtd)
+-		qh_update (ehci, qh, qtd);
++	/*
++	 * first qtd may already be partially processed.
++	 * If we come here during unlink, the QH overlay region
++	 * might have reference to the just unlinked qtd. The
++	 * qtd is updated in qh_completions(). Update the QH
++	 * overlay here.
++	 */
++	if (qh->hw->hw_token & ACTIVE_BIT(ehci))
++		qh->hw->hw_qtd_next = qtd->hw_next;
++	else
++		qh_update(ehci, qh, qtd);
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -553,12 +546,9 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	 * overlaying the dummy qtd (which reduces DMA chatter).
+ 	 */
+ 	if (stopped != 0 || hw->hw_qtd_next == EHCI_LIST_END(ehci)) {
+-		switch (state) {
+-		case QH_STATE_IDLE:
+-			qh_refresh(ehci, qh);
+-			break;
+-		case QH_STATE_LINKED:
+-			/* We won't refresh a QH that's linked (after the HC
++		if (state == QH_STATE_LINKED) {
++			/*
++			 * We won't refresh a QH that's linked (after the HC
+ 			 * stopped the queue).  That avoids a race:
+ 			 *  - HC reads first part of QH;
+ 			 *  - CPU updates that first part and the token;
+@@ -568,13 +558,12 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 			 *
+ 			 * That should be rare for interrupt transfers,
+ 			 * except maybe high bandwidth ...
++			 *
++			 * Therefore tell the caller to start an unlink.
+ 			 */
+-
+-			/* Tell the caller to start an unlink */
+ 			qh->needs_rescan = 1;
+-			break;
+-		/* otherwise, unlink already started */
+ 		}
++		/* otherwise, unlink already started */
+ 	}
+ 
+ 	return count;
+@@ -957,14 +946,13 @@ qh_make (
+ 
+ 	/* NOTE:  if (PIPE_INTERRUPT) { scheduler sets s-mask } */
+ 
+-	/* init as live, toggle clear, advance to dummy */
++	/* init as live, toggle clear */
+ 	qh->qh_state = QH_STATE_IDLE;
+ 	hw = qh->hw;
+ 	hw->hw_info1 = cpu_to_hc32(ehci, info1);
+ 	hw->hw_info2 = cpu_to_hc32(ehci, info2);
+ 	qh->is_out = !is_input;
+ 	usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1);
+-	qh_refresh (ehci, qh);
+ 	return qh;
+ }
+ 
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index b476daf49f6f..66259dc7822e 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -792,7 +792,6 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	unsigned	frame;		/* 0..(qh->period - 1), or NO_FRAME */
+ 	struct ehci_qh_hw	*hw = qh->hw;
+ 
+-	qh_refresh(ehci, qh);
+ 	hw->hw_next = EHCI_LIST_END(ehci);
+ 	frame = qh->start;
+ 
+@@ -844,8 +843,6 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	} else
+ 		ehci_dbg (ehci, "reused qh %p schedule\n", qh);
+ 
+-	/* stuff into the periodic schedule */
+-	qh_link_periodic(ehci, qh);
+ done:
+ 	return status;
+ }
+@@ -891,6 +888,12 @@ static int intr_submit (
+ 	qh = qh_append_tds(ehci, urb, qtd_list, epnum, &urb->ep->hcpriv);
+ 	BUG_ON (qh == NULL);
+ 
++	/* stuff into the periodic schedule */
++	if (qh->qh_state == QH_STATE_IDLE) {
++		qh_refresh(ehci, qh);
++		qh_link_periodic(ehci, qh);
++	}
++
+ 	/* ... update usbfs periodic stats */
+ 	ehci_to_hcd(ehci)->self.bandwidth_int_reqs++;
+ 

commit 417c765af914106f5e76c4e0181dd555fe6a89a0
+Author: Alan Stern 
+Date:   Thu Mar 21 12:48:42 2013 -0400
+
+    USB: EHCI: fix up incorrect merge resolution
+    
+    This patch (as1671) fixes up an incorrect resolution of a merge
+    conflict between Greg KH's usb-linus branch and his usb-next branch.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
+index dca8fc42b8d7..e7363332887e 100644
+--- a/drivers/usb/host/ehci-timer.c
++++ b/drivers/usb/host/ehci-timer.c
+@@ -297,6 +297,15 @@ static void ehci_iaa_watchdog(struct ehci_hcd *ehci)
+ {
+ 	u32 cmd, status;
+ 
++	/*
++	 * Lost IAA irqs wedge things badly; seen first with a vt8235.
++	 * So we need this watchdog, but must protect it against both
++	 * (a) SMP races against real IAA firing and retriggering, and
++	 * (b) clean HC shutdown, when IAA watchdog was pending.
++	 */
++	if (ehci->rh_state != EHCI_RH_RUNNING)
++		return;
++
+ 	/* If we get here, IAA is *REALLY* late.  It's barely
+ 	 * conceivable that the system is so busy that CMD_IAAD
+ 	 * is still legitimately set, so let's be sure it's

commit d714aaf649460cbfd5e82e75520baa856b4fa0a0
+Author: Alan Stern 
+Date:   Wed Mar 20 15:07:26 2013 -0400
+
+    USB: EHCI: fix regression in QH unlinking
+    
+    This patch (as1670) fixes a regression caused by commit
+    6402c796d3b4205d3d7296157956c5100a05d7d6 (USB: EHCI: work around
+    silicon bug in Intel's EHCI controllers).  The workaround goes through
+    two IAA cycles for each QH being unlinked.  During the first cycle,
+    the QH is not added to the async_iaa list (because it isn't fully gone
+    from the hardware yet), which means that list will be empty.
+    
+    Unfortunately, I forgot to update the IAA watchdog timer routine.  It
+    thinks that an empty async_iaa list means the timer expiration was an
+    error, which isn't true any more.  This problem didn't show up during
+    initial testing because the controllers being tested all had working
+    IAA interrupts.  But not all controllers do, and when the watchdog
+    timer expires, the empty-list check prevents the second IAA cycle from
+    starting.  As a result, URB unlinks never complete.  The check needs
+    to be removed.
+    
+    Among the symptoms of the regression are processes stuck in D wait
+    states and hangs during system shutdown.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Stephen Warren 
+    Reported-and-tested-by: Sven Joachim 
+    Reported-by: Andreas Bombe 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
+index 20dbdcbe9b0f..c3fa1305f830 100644
+--- a/drivers/usb/host/ehci-timer.c
++++ b/drivers/usb/host/ehci-timer.c
+@@ -304,7 +304,7 @@ static void ehci_iaa_watchdog(struct ehci_hcd *ehci)
+ 	 * (a) SMP races against real IAA firing and retriggering, and
+ 	 * (b) clean HC shutdown, when IAA watchdog was pending.
+ 	 */
+-	if (ehci->async_iaa) {
++	if (1) {
+ 		u32 cmd, status;
+ 
+ 		/* If we get here, IAA is *REALLY* late.  It's barely

commit 8119b55aed818e590c26cb97706c914e3d660fd8
+Author: Alan Stern 
+Date:   Fri Mar 15 14:03:17 2013 -0400
+
+    USB: gadget: net2280: remove leftover driver->unbind call in error pathway
+    
+    This patch (as1667) removes an incorrect driver->unbind() call from
+    the net2280 driver.  If startup fails, the UDC core takes care of
+    unbinding the gadget driver automatically; the controller driver
+    shouldn't do it too.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
+index 3105a4d601c8..3bd0f992fb49 100644
+--- a/drivers/usb/gadget/net2280.c
++++ b/drivers/usb/gadget/net2280.c
+@@ -1924,7 +1924,6 @@ static int net2280_start(struct usb_gadget *_gadget,
+ err_func:
+ 	device_remove_file (&dev->pdev->dev, &dev_attr_function);
+ err_unbind:
+-	driver->unbind (&dev->gadget);
+ 	dev->gadget.dev.driver = NULL;
+ 	dev->driver = NULL;
+ 	return retval;

commit 511f3c5326eabe1ece35202a404c24c0aeacc246
+Author: Alan Stern 
+Date:   Fri Mar 15 14:02:14 2013 -0400
+
+    usb: gadget: udc-core: fix a regression during gadget driver unbinding
+    
+    This patch (as1666) fixes a regression in the UDC core.  The core
+    takes care of unbinding gadget drivers, and it does the unbinding
+    before telling the UDC driver to turn off the controller hardware.
+    When the call to the udc_stop callback is made, the gadget no longer
+    has a driver.  The callback routine should not be invoked with a
+    pointer to the old driver; doing so can cause problems (such as
+    use-after-free accesses in net2280).
+    
+    This patch should be applied, with appropriate context changes, to all
+    the stable kernels going back to 3.1.
+    
+    Signed-off-by: Alan Stern 
+    CC: 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c
+index 2a9cd369f71c..f8f62c3ed65e 100644
+--- a/drivers/usb/gadget/udc-core.c
++++ b/drivers/usb/gadget/udc-core.c
+@@ -216,7 +216,7 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
+ 	usb_gadget_disconnect(udc->gadget);
+ 	udc->driver->disconnect(udc->gadget);
+ 	udc->driver->unbind(udc->gadget);
+-	usb_gadget_udc_stop(udc->gadget, udc->driver);
++	usb_gadget_udc_stop(udc->gadget, NULL);
+ 
+ 	udc->driver = NULL;
+ 	udc->dev.driver = NULL;

commit 24b90814fb133bb7971aef8ea5e642d9f9bc4b0b
+Author: Alan Stern 
+Date:   Mon Mar 18 12:05:42 2013 -0400
+
+    USB: EHCI: don't turn on PORT_SUSPEND during port resume
+    
+    This patch (as1637) cleans up the way ehci-hcd handles end-of-resume
+    port signalling.  When the PORT_RESUME bit in the port's status and
+    control register is cleared, we shouldn't be setting the PORT_SUSPEND
+    bit at the same time.  Not doing this doesn't seem to have hurt so
+    far, but we might as well do the right thing.
+    
+    Also, the patch replaces an estimated value for what the port status
+    should be following a resume with the actual register value.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 576b735f49b6..0df45d933a10 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -464,7 +464,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 	while (i--) {
+ 		temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
+ 		if (test_bit(i, &resume_needed)) {
+-			temp &= ~(PORT_RWC_BITS | PORT_RESUME);
++			temp &= ~(PORT_RWC_BITS | PORT_SUSPEND | PORT_RESUME);
+ 			ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
+ 			ehci_vdbg (ehci, "resumed port %d\n", i + 1);
+ 		}
+@@ -871,10 +871,9 @@ static int ehci_hub_control (
+ 				usb_hcd_end_port_resume(&hcd->self, wIndex);
+ 
+ 				/* stop resume signaling */
+-				temp = ehci_readl(ehci, status_reg);
+-				ehci_writel(ehci,
+-					temp & ~(PORT_RWC_BITS | PORT_RESUME),
+-					status_reg);
++				temp &= ~(PORT_RWC_BITS |
++						PORT_SUSPEND | PORT_RESUME);
++				ehci_writel(ehci, temp, status_reg);
+ 				clear_bit(wIndex, &ehci->resuming_ports);
+ 				retval = handshake(ehci, status_reg,
+ 					   PORT_RESUME, 0, 2000 /* 2msec */);
+@@ -884,7 +883,7 @@ static int ehci_hub_control (
+ 						wIndex + 1, retval);
+ 					goto error;
+ 				}
+-				temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10));
++				temp = ehci_readl(ehci, status_reg);
+ 			}
+ 		}
+ 

commit 60fd4aa742a0c4f01dafeb0d125fed54e91e3657
+Author: Alan Stern 
+Date:   Mon Mar 18 12:05:19 2013 -0400
+
+    USB: EHCI: reorganize ehci_iaa_watchdog()
+    
+    This patch (as1635) rearranges the control-flow logic in
+    ehci_iaa_watchdog() slightly to agree better with the comments.  It
+    also changes a verbose-debug message to a regular debug message.
+    Expiration of the IAA watchdog is an unusual event and can lead to
+    problems; we need to know about it if it happens during debugging.  It
+    should not be necessary to set a "verbose" compilation option.
+    
+    No behavioral changes other than the debug message.  Lots of apparent
+    changes to the source text, though, because the indentation level was
+    decreased.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
+index cc9ad5892d19..97815d0fc97c 100644
+--- a/drivers/usb/host/ehci-timer.c
++++ b/drivers/usb/host/ehci-timer.c
+@@ -295,8 +295,7 @@ static void end_free_itds(struct ehci_hcd *ehci)
+ /* Handle lost (or very late) IAA interrupts */
+ static void ehci_iaa_watchdog(struct ehci_hcd *ehci)
+ {
+-	if (ehci->rh_state != EHCI_RH_RUNNING)
+-		return;
++	u32 cmd, status;
+ 
+ 	/*
+ 	 * Lost IAA irqs wedge things badly; seen first with a vt8235.
+@@ -304,34 +303,32 @@ static void ehci_iaa_watchdog(struct ehci_hcd *ehci)
+ 	 * (a) SMP races against real IAA firing and retriggering, and
+ 	 * (b) clean HC shutdown, when IAA watchdog was pending.
+ 	 */
+-	if (ehci->async_iaa) {
+-		u32 cmd, status;
+-
+-		/* If we get here, IAA is *REALLY* late.  It's barely
+-		 * conceivable that the system is so busy that CMD_IAAD
+-		 * is still legitimately set, so let's be sure it's
+-		 * clear before we read STS_IAA.  (The HC should clear
+-		 * CMD_IAAD when it sets STS_IAA.)
+-		 */
+-		cmd = ehci_readl(ehci, &ehci->regs->command);
+-
+-		/*
+-		 * If IAA is set here it either legitimately triggered
+-		 * after the watchdog timer expired (_way_ late, so we'll
+-		 * still count it as lost) ... or a silicon erratum:
+-		 * - VIA seems to set IAA without triggering the IRQ;
+-		 * - IAAD potentially cleared without setting IAA.
+-		 */
+-		status = ehci_readl(ehci, &ehci->regs->status);
+-		if ((status & STS_IAA) || !(cmd & CMD_IAAD)) {
+-			COUNT(ehci->stats.lost_iaa);
+-			ehci_writel(ehci, STS_IAA, &ehci->regs->status);
+-		}
++	if (!ehci->async_iaa || ehci->rh_state != EHCI_RH_RUNNING)
++		return;
++
++	/* If we get here, IAA is *REALLY* late.  It's barely
++	 * conceivable that the system is so busy that CMD_IAAD
++	 * is still legitimately set, so let's be sure it's
++	 * clear before we read STS_IAA.  (The HC should clear
++	 * CMD_IAAD when it sets STS_IAA.)
++	 */
++	cmd = ehci_readl(ehci, &ehci->regs->command);
+ 
+-		ehci_vdbg(ehci, "IAA watchdog: status %x cmd %x\n",
+-				status, cmd);
+-		end_unlink_async(ehci);
++	/*
++	 * If IAA is set here it either legitimately triggered
++	 * after the watchdog timer expired (_way_ late, so we'll
++	 * still count it as lost) ... or a silicon erratum:
++	 * - VIA seems to set IAA without triggering the IRQ;
++	 * - IAAD potentially cleared without setting IAA.
++	 */
++	status = ehci_readl(ehci, &ehci->regs->status);
++	if ((status & STS_IAA) || !(cmd & CMD_IAAD)) {
++		COUNT(ehci->stats.lost_iaa);
++		ehci_writel(ehci, STS_IAA, &ehci->regs->status);
+ 	}
++
++	ehci_dbg(ehci, "IAA watchdog: status %x cmd %x\n", status, cmd);
++	end_unlink_async(ehci);
+ }
+ 
+ 

commit 4dd405a4b0969bfec4dc9959050b46d818b6549b
+Author: Alan Stern 
+Date:   Mon Mar 18 12:05:08 2013 -0400
+
+    USB: EHCI: improve use of per-port status-change bits
+    
+    This patch (as1634) simplifies some of the code associated with the
+    per-port change bits added in EHCI-1.1, and in particular it fixes a
+    bug in the logic of ehci_hub_status_data().  Even if the change bit
+    doesn't indicate anything happened on a particular port, we still have
+    to notify the core about changes to the suspend or reset status.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 303b0222cd6d..fcf8b940e867 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -758,7 +758,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 	/* remote wakeup [4.3.1] */
+ 	if (status & STS_PCD) {
+ 		unsigned	i = HCS_N_PORTS (ehci->hcs_params);
+-		u32		ppcd = 0;
++		u32		ppcd = ~0;
+ 
+ 		/* kick root hub later */
+ 		pcd_status = status;
+@@ -775,7 +775,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 			int pstatus;
+ 
+ 			/* leverage per-port change bits feature */
+-			if (ehci->has_ppcd && !(ppcd & (1 << i)))
++			if (!(ppcd & (1 << i)))
+ 				continue;
+ 			pstatus = ehci_readl(ehci,
+ 					 &ehci->regs->port_status[i]);
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 4d3b294f203e..576b735f49b6 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -590,7 +590,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ 	u32		mask;
+ 	int		ports, i, retval = 1;
+ 	unsigned long	flags;
+-	u32		ppcd = 0;
++	u32		ppcd = ~0;
+ 
+ 	/* init status to no-changes */
+ 	buf [0] = 0;
+@@ -628,9 +628,10 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ 
+ 	for (i = 0; i < ports; i++) {
+ 		/* leverage per-port change bits feature */
+-		if (ehci->has_ppcd && !(ppcd & (1 << i)))
+-			continue;
+-		temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
++		if (ppcd & (1 << i))
++			temp = ehci_readl(ehci, &ehci->regs->port_status[i]);
++		else
++			temp = 0;
+ 
+ 		/*
+ 		 * Return status information even for ports with OWNER set.

commit 6d5df8976266d8e40603601f7695537f9f3dc9e2
+Author: Alan Stern 
+Date:   Mon Mar 18 12:04:54 2013 -0400
+
+    USB: EHCI: decrease schedule-status poll timeout
+    
+    This patch (as1657) decreases the timeout used by ehci-hcd for polling
+    the async and periodic schedule statuses.  The timeout is currently
+    set to 20 ms, which is much too high.  Controllers should always
+    update the schedule status within one or two ms of being told to do
+    so; if they don't then something is wrong.
+    
+    Furthermore, bug reports have shown that sometimes controllers
+    (particularly those made by VIA) don't update the status bit at all,
+    even when the schedule does change state.  When this happens, polling
+    for 20 ms would cause an unnecessarily long delay.
+    
+    The delay is reduced to somewhere between 2 and 4 ms, depending on the
+    slop allowed by the kernel's high-res timers.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
+index 20dbdcbe9b0f..cc9ad5892d19 100644
+--- a/drivers/usb/host/ehci-timer.c
++++ b/drivers/usb/host/ehci-timer.c
+@@ -113,8 +113,8 @@ static void ehci_poll_ASS(struct ehci_hcd *ehci)
+ 
+ 	if (want != actual) {
+ 
+-		/* Poll again later, but give up after about 20 ms */
+-		if (ehci->ASS_poll_count++ < 20) {
++		/* Poll again later, but give up after about 2-4 ms */
++		if (ehci->ASS_poll_count++ < 2) {
+ 			ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true);
+ 			return;
+ 		}
+@@ -159,8 +159,8 @@ static void ehci_poll_PSS(struct ehci_hcd *ehci)
+ 
+ 	if (want != actual) {
+ 
+-		/* Poll again later, but give up after about 20 ms */
+-		if (ehci->PSS_poll_count++ < 20) {
++		/* Poll again later, but give up after about 2-4 ms */
++		if (ehci->PSS_poll_count++ < 2) {
+ 			ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);
+ 			return;
+ 		}

commit 2a40f324541ee61c22146214349c2ce9f5c30bcf
+Author: Alan Stern 
+Date:   Fri Mar 15 14:40:26 2013 -0400
+
+    USB: EHCI: fix regression during bus resume
+    
+    This patch (as1663) fixes a regression caused by commit
+    6e0c3339a6f19d748f16091d0a05adeb1e1f822b (USB: EHCI: unlink one async
+    QH at a time).  In order to avoid keeping multiple QHs in an unusable
+    intermediate state, that commit changed unlink_empty_async() so that
+    it unlinks only one empty QH at a time.
+    
+    However, when the EHCI root hub is suspended, _all_ async QHs need to
+    be unlinked.  ehci_bus_suspend() used to do this by calling
+    unlink_empty_async(), but now this only unlinks one of the QHs, not
+    all of them.
+    
+    The symptom is that when the root hub is resumed, USB communications
+    don't work for some period of time.  This is because ehci-hcd doesn't
+    realize it needs to restart the async schedule; it assumes that
+    because some QHs are already on the schedule, the schedule must be
+    running.
+    
+    The easiest way to fix the problem is add a new function that unlinks
+    all the async QHs when the root hub is suspended.
+    
+    This patch should be applied to all kernels that have the 6e0c3339a6f1
+    commit.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Adrian Bassett 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 5726cb144abf..416a6dce5e11 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -302,6 +302,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
+ 
+ static void end_unlink_async(struct ehci_hcd *ehci);
+ static void unlink_empty_async(struct ehci_hcd *ehci);
++static void unlink_empty_async_suspended(struct ehci_hcd *ehci);
+ static void ehci_work(struct ehci_hcd *ehci);
+ static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh);
+ static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh);
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 4d3b294f203e..7d06e77f6c4f 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -328,7 +328,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 	ehci->rh_state = EHCI_RH_SUSPENDED;
+ 
+ 	end_unlink_async(ehci);
+-	unlink_empty_async(ehci);
++	unlink_empty_async_suspended(ehci);
+ 	ehci_handle_intr_unlinks(ehci);
+ 	end_free_itds(ehci);
+ 
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 5464665f0b6a..23d136904285 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -1316,6 +1316,19 @@ static void unlink_empty_async(struct ehci_hcd *ehci)
+ 	}
+ }
+ 
++/* The root hub is suspended; unlink all the async QHs */
++static void unlink_empty_async_suspended(struct ehci_hcd *ehci)
++{
++	struct ehci_qh		*qh;
++
++	while (ehci->async->qh_next.qh) {
++		qh = ehci->async->qh_next.qh;
++		WARN_ON(!list_empty(&qh->qtd_list));
++		single_unlink_async(ehci, qh);
++	}
++	start_iaa_cycle(ehci, false);
++}
++
+ /* makes sure the async qh will become idle */
+ /* caller must own ehci->lock */
+ 

commit 54a419668b0f27b7982807fb2376d237e0a0ce05
+Author: Alan Stern 
+Date:   Tue Mar 12 12:44:39 2013 +0200
+
+    USB: EHCI: split ehci-omap out to a separate driver
+    
+    This patch (as1645) converts ehci-omap over to the new "ehci-hcd is a
+    library" approach, so that it can coexist peacefully with other EHCI
+    platform drivers and can make use of the private area allocated at
+    the end of struct ehci_hcd.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
+index c59a1126926f..62f4e9a38557 100644
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -155,7 +155,7 @@ config USB_EHCI_MXC
+ 	  Variation of ARC USB block used in some Freescale chips.
+ 
+ config USB_EHCI_HCD_OMAP
+-	bool "EHCI support for OMAP3 and later chips"
++	tristate "EHCI support for OMAP3 and later chips"
+ 	depends on USB_EHCI_HCD && ARCH_OMAP
+ 	default y
+ 	---help---
+diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
+index 001fbff2fdef..56de4106c8b3 100644
+--- a/drivers/usb/host/Makefile
++++ b/drivers/usb/host/Makefile
+@@ -27,6 +27,7 @@ obj-$(CONFIG_USB_EHCI_HCD)	+= ehci-hcd.o
+ obj-$(CONFIG_USB_EHCI_PCI)	+= ehci-pci.o
+ obj-$(CONFIG_USB_EHCI_HCD_PLATFORM)	+= ehci-platform.o
+ obj-$(CONFIG_USB_EHCI_MXC)	+= ehci-mxc.o
++obj-$(CONFIG_USB_EHCI_HCD_OMAP)	+= ehci-omap.o
+ 
+ obj-$(CONFIG_USB_OXU210HP_HCD)	+= oxu210hp-hcd.o
+ obj-$(CONFIG_USB_ISP116X_HCD)	+= isp116x-hcd.o
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index b416a3fc9959..303b0222cd6d 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1252,11 +1252,6 @@ MODULE_LICENSE ("GPL");
+ #define PLATFORM_DRIVER		ehci_hcd_sh_driver
+ #endif
+ 
+-#ifdef CONFIG_USB_EHCI_HCD_OMAP
+-#include "ehci-omap.c"
+-#define        PLATFORM_DRIVER         ehci_hcd_omap_driver
+-#endif
+-
+ #ifdef CONFIG_PPC_PS3
+ #include "ehci-ps3.c"
+ #define	PS3_SYSTEM_BUS_DRIVER	ps3_ehci_driver
+@@ -1346,6 +1341,7 @@ MODULE_LICENSE ("GPL");
+ 	!IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \
+ 	!IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \
+ 	!IS_ENABLED(CONFIG_USB_EHCI_MXC) && \
++	!IS_ENABLED(CONFIG_USB_EHCI_HCD_OMAP) && \
+ 	!defined(PLATFORM_DRIVER) && \
+ 	!defined(PS3_SYSTEM_BUS_DRIVER) && \
+ 	!defined(OF_PLATFORM_DRIVER) && \
+diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
+index 0555ee42d7cb..fa667577d9b9 100644
+--- a/drivers/usb/host/ehci-omap.c
++++ b/drivers/usb/host/ehci-omap.c
+@@ -36,6 +36,9 @@
+  *	- convert to use hwmod and runtime PM
+  */
+ 
++#include 
++#include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -43,6 +46,10 @@
+ #include 
+ #include 
+ #include 
++#include 
++#include 
++
++#include "ehci.h"
+ 
+ #include 
+ 
+@@ -57,9 +64,11 @@
+ #define	EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT		8
+ #define	EHCI_INSNREG05_ULPI_WRDATA_SHIFT		0
+ 
+-/*-------------------------------------------------------------------------*/
++#define DRIVER_DESC "OMAP-EHCI Host Controller driver"
+ 
+-static const struct hc_driver ehci_omap_hc_driver;
++static const char hcd_name[] = "ehci-omap";
++
++/*-------------------------------------------------------------------------*/
+ 
+ 
+ static inline void ehci_write(void __iomem *base, u32 reg, u32 val)
+@@ -166,6 +175,12 @@ static void disable_put_regulator(
+ /* configure so an HC device and id are always provided */
+ /* always called with process context; sleeping is OK */
+ 
++static struct hc_driver __read_mostly ehci_omap_hc_driver;
++
++static const struct ehci_driver_overrides ehci_omap_overrides __initdata = {
++	.reset =		omap_ehci_init,
++};
++
+ /**
+  * ehci_hcd_omap_probe - initialize TI-based HCDs
+  *
+@@ -315,56 +330,33 @@ static struct platform_driver ehci_hcd_omap_driver = {
+ 	/*.suspend		= ehci_hcd_omap_suspend, */
+ 	/*.resume		= ehci_hcd_omap_resume, */
+ 	.driver = {
+-		.name		= "ehci-omap",
++		.name		= hcd_name,
+ 	}
+ };
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-static const struct hc_driver ehci_omap_hc_driver = {
+-	.description		= hcd_name,
+-	.product_desc		= "OMAP-EHCI Host Controller",
+-	.hcd_priv_size		= sizeof(struct ehci_hcd),
+-
+-	/*
+-	 * generic hardware linkage
+-	 */
+-	.irq			= ehci_irq,
+-	.flags			= HCD_MEMORY | HCD_USB2,
+-
+-	/*
+-	 * basic lifecycle operations
+-	 */
+-	.reset			= omap_ehci_init,
+-	.start			= ehci_run,
+-	.stop			= ehci_stop,
+-	.shutdown		= ehci_shutdown,
+-
+-	/*
+-	 * managing i/o requests and associated device resources
+-	 */
+-	.urb_enqueue		= ehci_urb_enqueue,
+-	.urb_dequeue		= ehci_urb_dequeue,
+-	.endpoint_disable	= ehci_endpoint_disable,
+-	.endpoint_reset		= ehci_endpoint_reset,
++static int __init ehci_omap_init(void)
++{
++	if (usb_disabled())
++		return -ENODEV;
+ 
+-	/*
+-	 * scheduling support
+-	 */
+-	.get_frame_number	= ehci_get_frame,
++	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+ 
+-	/*
+-	 * root hub support
+-	 */
+-	.hub_status_data	= ehci_hub_status_data,
+-	.hub_control		= ehci_hub_control,
+-	.bus_suspend		= ehci_bus_suspend,
+-	.bus_resume		= ehci_bus_resume,
++	ehci_init_driver(&ehci_omap_hc_driver, &ehci_omap_overrides);
++	return platform_driver_register(&ehci_hcd_omap_driver);
++}
++module_init(ehci_omap_init);
+ 
+-	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+-};
++static void __exit ehci_omap_cleanup(void)
++{
++	platform_driver_unregister(&ehci_hcd_omap_driver);
++}
++module_exit(ehci_omap_cleanup);
+ 
+ MODULE_ALIAS("platform:ehci-omap");
+ MODULE_AUTHOR("Texas Instruments, Inc.");
+ MODULE_AUTHOR("Felipe Balbi ");
+ 
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_LICENSE("GPL");

commit feca7746d5d9e84b105a613b7f3b6ad00d327372
+Author: Alan Stern 
+Date:   Fri Mar 1 10:51:15 2013 -0500
+
+    USB: EHCI: don't check DMA values in QH overlays
+    
+    This patch (as1661) fixes a rather obscure bug in ehci-hcd.  In a
+    couple of places, the driver compares the DMA address stored in a QH's
+    overlay region with the address of a particular qTD, in order to see
+    whether that qTD is the one currently being processed by the hardware.
+    (If it is then the status in the QH's overlay region is more
+    up-to-date than the status in the qTD, and if it isn't then the
+    overlay's value needs to be adjusted when the QH is added back to the
+    active schedule.)
+    
+    However, DMA address in the overlay region isn't always valid.  It
+    sometimes will contain a stale value, which may happen by coincidence
+    to be equal to a qTD's DMA address.  Instead of checking the DMA
+    address, we should check whether the overlay region is active and
+    valid.  The patch tests the ACTIVE bit in the overlay, and clears this
+    bit when the overlay becomes invalid (which happens when the
+    currently-executing URB is unlinked).
+    
+    This is the second part of a fix for the regression reported at:
+    
+            https://bugs.launchpad.net/bugs/1088733
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Joseph Salisbury 
+    Reported-and-tested-by: Stephen Thirlwall 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 7bf2b4eeb9ce..5464665f0b6a 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -135,7 +135,7 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		 * qtd is updated in qh_completions(). Update the QH
+ 		 * overlay here.
+ 		 */
+-		if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) {
++		if (qh->hw->hw_token & ACTIVE_BIT(ehci)) {
+ 			qh->hw->hw_qtd_next = qtd->hw_next;
+ 			qtd = NULL;
+ 		}
+@@ -449,11 +449,19 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 			else if (last_status == -EINPROGRESS && !urb->unlinked)
+ 				continue;
+ 
+-			/* qh unlinked; token in overlay may be most current */
+-			if (state == QH_STATE_IDLE
+-					&& cpu_to_hc32(ehci, qtd->qtd_dma)
+-						== hw->hw_current) {
++			/*
++			 * If this was the active qtd when the qh was unlinked
++			 * and the overlay's token is active, then the overlay
++			 * hasn't been written back to the qtd yet so use its
++			 * token instead of the qtd's.  After the qtd is
++			 * processed and removed, the overlay won't be valid
++			 * any more.
++			 */
++			if (state == QH_STATE_IDLE &&
++					qh->qtd_list.next == &qtd->qtd_list &&
++					(hw->hw_token & ACTIVE_BIT(ehci))) {
+ 				token = hc32_to_cpu(ehci, hw->hw_token);
++				hw->hw_token &= ~ACTIVE_BIT(ehci);
+ 
+ 				/* An unlink may leave an incomplete
+ 				 * async transaction in the TT buffer.

commit 6402c796d3b4205d3d7296157956c5100a05d7d6
+Author: Alan Stern 
+Date:   Fri Mar 1 10:50:08 2013 -0500
+
+    USB: EHCI: work around silicon bug in Intel's EHCI controllers
+    
+    This patch (as1660) works around a hardware problem present in some
+    (if not all) Intel EHCI controllers.  After a QH has been unlinked
+    from the async schedule and the corresponding IAA interrupt has
+    occurred, the controller is not supposed access the QH and its qTDs.
+    There certainly shouldn't be any more DMA writes to those structures.
+    Nevertheless, Intel's controllers have been observed to perform a
+    final writeback to the QH's overlay region and to the most recent qTD.
+    For more information and a test program to determine whether this
+    problem is present in a particular controller, see
+    
+            http://marc.info/?l=linux-usb&m=135492071812265&w=2
+            http://marc.info/?l=linux-usb&m=136182570800963&w=2
+    
+    This patch works around the problem by always waiting for two IAA
+    cycles when unlinking an async QH.  The extra IAA delay gives the
+    controller time to perform its final writeback.
+    
+    Surprisingly enough, the effects of this silicon bug have gone
+    undetected until quite recently.  More through luck than anything
+    else, it hasn't caused any apparent problems.  However, it does
+    interact badly with the path that follows this one, so it needs to be
+    addressed.
+    
+    This is the first part of a fix for the regression reported at:
+    
+            https://bugs.launchpad.net/bugs/1088733
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Stephen Thirlwall 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index b416a3fc9959..5726cb144abf 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -748,11 +748,9 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 		/* guard against (alleged) silicon errata */
+ 		if (cmd & CMD_IAAD)
+ 			ehci_dbg(ehci, "IAA with IAAD still set?\n");
+-		if (ehci->async_iaa) {
++		if (ehci->async_iaa)
+ 			COUNT(ehci->stats.iaa);
+-			end_unlink_async(ehci);
+-		} else
+-			ehci_dbg(ehci, "IAA with nothing unlinked?\n");
++		end_unlink_async(ehci);
+ 	}
+ 
+ 	/* remote wakeup [4.3.1] */
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index fd252f0cfb3a..7bf2b4eeb9ce 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -1170,7 +1170,7 @@ static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	struct ehci_qh		*prev;
+ 
+ 	/* Add to the end of the list of QHs waiting for the next IAAD */
+-	qh->qh_state = QH_STATE_UNLINK;
++	qh->qh_state = QH_STATE_UNLINK_WAIT;
+ 	if (ehci->async_unlink)
+ 		ehci->async_unlink_last->unlink_next = qh;
+ 	else
+@@ -1213,9 +1213,19 @@ static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested)
+ 
+ 		/* Do only the first waiting QH (nVidia bug?) */
+ 		qh = ehci->async_unlink;
+-		ehci->async_iaa = qh;
+-		ehci->async_unlink = qh->unlink_next;
+-		qh->unlink_next = NULL;
++
++		/*
++		 * Intel (?) bug: The HC can write back the overlay region
++		 * even after the IAA interrupt occurs.  In self-defense,
++		 * always go through two IAA cycles for each QH.
++		 */
++		if (qh->qh_state == QH_STATE_UNLINK_WAIT) {
++			qh->qh_state = QH_STATE_UNLINK;
++		} else {
++			ehci->async_iaa = qh;
++			ehci->async_unlink = qh->unlink_next;
++			qh->unlink_next = NULL;
++		}
+ 
+ 		/* Make sure the unlinks are all visible to the hardware */
+ 		wmb();

commit 221f8dfca89276d8aec54c6d07fbe20c281668f0
+Author: Alan Stern 
+Date:   Tue Feb 26 13:43:41 2013 -0500
+
+    USB: EHCI: revert "remove ASS/PSS polling timeout"
+    
+    This patch (as1649) reverts commit
+    55bcdce8a8228223ec4d17d8ded8134ed265d2c5 (USB: EHCI: remove ASS/PSS
+    polling timeout).  That commit was written under the assumption that
+    some controllers may take a very long time to turn off their async and
+    periodic schedules.  It now appears that in fact the schedules do get
+    turned off reasonably quickly, but some controllers occasionally leave
+    the schedules' status bits turned on and consequently ehci-hcd can't
+    tell that the schedules are off.
+    
+    VIA controllers in particular have this problem.  ehci-hcd tells the
+    hardware to turn off the async schedule, the schedule does get turned
+    off, but the status bit remains on.  Since the EHCI spec requires that
+    the schedules not be re-enabled until the previous disable has taken
+    effect, with an unlimited timeout the async schedule never gets turned
+    back on.  The resulting symptom is that the system is unable to
+    communicate with USB devices.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Ronald 
+    Reported-and-tested-by: Paul Hartman 
+    Reported-and-tested-by: Dieter Nützel 
+    Reported-and-tested-by: Jean Delvare 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
+index f904071d70df..20dbdcbe9b0f 100644
+--- a/drivers/usb/host/ehci-timer.c
++++ b/drivers/usb/host/ehci-timer.c
+@@ -113,15 +113,14 @@ static void ehci_poll_ASS(struct ehci_hcd *ehci)
+ 
+ 	if (want != actual) {
+ 
+-		/* Poll again later */
+-		ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true);
+-		++ehci->ASS_poll_count;
+-		return;
++		/* Poll again later, but give up after about 20 ms */
++		if (ehci->ASS_poll_count++ < 20) {
++			ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true);
++			return;
++		}
++		ehci_dbg(ehci, "Waited too long for the async schedule status (%x/%x), giving up\n",
++				want, actual);
+ 	}
+-
+-	if (ehci->ASS_poll_count > 20)
+-		ehci_dbg(ehci, "ASS poll count reached %d\n",
+-				ehci->ASS_poll_count);
+ 	ehci->ASS_poll_count = 0;
+ 
+ 	/* The status is up-to-date; restart or stop the schedule as needed */
+@@ -160,14 +159,14 @@ static void ehci_poll_PSS(struct ehci_hcd *ehci)
+ 
+ 	if (want != actual) {
+ 
+-		/* Poll again later */
+-		ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);
+-		return;
++		/* Poll again later, but give up after about 20 ms */
++		if (ehci->PSS_poll_count++ < 20) {
++			ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);
++			return;
++		}
++		ehci_dbg(ehci, "Waited too long for the periodic schedule status (%x/%x), giving up\n",
++				want, actual);
+ 	}
+-
+-	if (ehci->PSS_poll_count > 20)
+-		ehci_dbg(ehci, "PSS poll count reached %d\n",
+-				ehci->PSS_poll_count);
+ 	ehci->PSS_poll_count = 0;
+ 
+ 	/* The status is up-to-date; restart or stop the schedule as needed */

commit 3e619d04159be54b3daa0b7036b0ce9e067f4b5d
+Author: Alan Stern 
+Date:   Wed Jan 30 16:36:40 2013 -0500
+
+    USB: EHCI: fix bug in scheduling periodic split transfers
+    
+    This patch (as1654) fixes a very old bug in ehci-hcd, connected with
+    scheduling of periodic split transfers.  The calculations for
+    full/low-speed bus usage are all carried out after the correction for
+    bit-stuffing has been applied, but the values in the max_tt_usecs
+    array assume it hasn't been.  The array should allow for allocation of
+    up to 90% of the bus capacity, which is 900 us, not 780 us.
+    
+    The symptom caused by this bug is that any isochronous transfer to a
+    full-speed device with a maxpacket size larger than about 980 bytes is
+    always rejected with a -ENOSPC error.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 2b6917dc3996..b476daf49f6f 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -213,7 +213,7 @@ static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask)
+ }
+ 
+ static const unsigned char
+-max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 };
++max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 125, 25 };
+ 
+ /* carryover low/fullspeed bandwidth that crosses uframe boundries */
+ static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8])

commit b09a61cc0bc2a7151f4ab652489e85253d5d0175
+Author: Alan Stern 
+Date:   Wed Jan 30 16:35:02 2013 -0500
+
+    USB: EHCI: fix for leaking isochronous data
+    
+    This patch (as1653) fixes a bug in ehci-hcd.  Unlike iTD entries, an
+    siTD entry in the periodic schedule may not complete until the frame
+    after the one it belongs to.  Consequently, when scanning the periodic
+    schedule it is necessary to start with the frame _preceding_ the one
+    where the previous scan ended.
+    
+    Not doing this properly can result in memory leaks and failures to
+    complete isochronous URBs.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Andy Leiserson 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 69ebee73c0c1..2b6917dc3996 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -2212,11 +2212,11 @@ static void scan_isoc(struct ehci_hcd *ehci)
+ 	}
+ 	ehci->now_frame = now_frame;
+ 
++	frame = ehci->last_iso_frame;
+ 	for (;;) {
+ 		union ehci_shadow	q, *q_p;
+ 		__hc32			type, *hw_p;
+ 
+-		frame = ehci->last_iso_frame;
+ restart:
+ 		/* scan each element in frame's queue for completions */
+ 		q_p = &ehci->pshadow [frame];
+@@ -2321,6 +2321,9 @@ static void scan_isoc(struct ehci_hcd *ehci)
+ 		/* Stop when we have reached the current frame */
+ 		if (frame == now_frame)
+ 			break;
+-		ehci->last_iso_frame = (frame + 1) & fmask;
++
++		/* The last frame may still have active siTDs */
++		ehci->last_iso_frame = frame;
++		frame = (frame + 1) & fmask;
+ 	}
+ }

commit 2f0760774711c957c395b31131b848043af98edf
+Author: Alan Stern 
+Date:   Wed Jan 30 16:40:14 2013 -0500
+
+    USB: GADGET: optionally force full-speed for net2280 UDC
+    
+    This patch (as1656) adds a module parameter to the net2280 UDC driver
+    to force full-speed operation.  It is intended for testing purposes,
+    where one wants to check how well a full-speed device performs when
+    attached to a high-speed bus.  Without this parameter it would be
+    necessary to interpose a full-speed hub; otherwise the net2280 would
+    connect at high speed.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Felipe Balbi 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
+index 708c0b55dcc8..a1b650e11339 100644
+--- a/drivers/usb/gadget/net2280.c
++++ b/drivers/usb/gadget/net2280.c
+@@ -116,6 +116,10 @@ static bool enable_suspend = 0;
+ /* "modprobe net2280 enable_suspend=1" etc */
+ module_param (enable_suspend, bool, S_IRUGO);
+ 
++/* force full-speed operation */
++static bool full_speed;
++module_param(full_speed, bool, 0444);
++MODULE_PARM_DESC(full_speed, "force full-speed mode -- for testing only!");
+ 
+ #define	DIR_STRING(bAddress) (((bAddress) & USB_DIR_IN) ? "in" : "out")
+ 
+@@ -1899,6 +1903,10 @@ static int net2280_start(struct usb_gadget *_gadget,
+ 	retval = device_create_file (&dev->pdev->dev, &dev_attr_queues);
+ 	if (retval) goto err_func;
+ 
++	/* Enable force-full-speed testing mode, if desired */
++	if (full_speed)
++		writel(1 << FORCE_FULL_SPEED_MODE, &dev->usb->xcvrdiag);
++
+ 	/* ... then enable host detection and ep0; and we're ready
+ 	 * for set_configuration as well as eventual disconnect.
+ 	 */
+@@ -1957,6 +1965,10 @@ static int net2280_stop(struct usb_gadget *_gadget,
+ 	dev->driver = NULL;
+ 
+ 	net2280_led_active (dev, 0);
++
++	/* Disable full-speed test mode */
++	writel(0, &dev->usb->xcvrdiag);
++
+ 	device_remove_file (&dev->pdev->dev, &dev_attr_function);
+ 	device_remove_file (&dev->pdev->dev, &dev_attr_queues);
+ 
+@@ -2841,6 +2853,9 @@ static void net2280_shutdown (struct pci_dev *pdev)
+ 
+ 	/* disable the pullup so the host will think we're gone */
+ 	writel (0, &dev->usb->usbctl);
++
++	/* Disable full-speed test mode */
++	writel(0, &dev->usb->xcvrdiag);
+ }
+ 
+ 

commit d0b4652f80c3276a57ede3b6b6d8159fa26c091f
+Author: Alan Stern 
+Date:   Wed Jan 30 16:38:11 2013 -0500
+
+    USB: altsetting overrides for usbtest
+    
+    The usbtest driver includes some rather simple-minded logic for
+    selecting an altsetting to test.  It doesn't work well for the g_zero
+    gadget, because it selects altsetting 0 (which doesn't have
+    isochronous endpoints) rather than altsetting 1 (which does have them,
+    if the gadget's hardware supports them).  This prevents usbtest's
+    isochronous tests (15, 16, 22, and 23) from working with g_zero.
+    
+    Since g_zero is one of the most common gadget drivers used for USB
+    testing, usbtest should do a better job of supporting it.  But since
+    some programs may rely on the current scheme for selecting
+    altsettings, I didn't want to change it.
+    
+    Instead, this patch (as1655) adds a module parameter to usbtest, which
+    can be used to override the default altsetting.  Since usbtest is
+    never used by normal users (most distributions probably don't even
+    build it), the new module parameter won't inconvenience anybody.  In
+    any case, it is entirely optional -- leaving it unset preserves the
+    existing behavior.
+    
+    The patch also fixes a related bug in usbtest: After selecting an
+    altsetting, the driver neglects to store its selection.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
+index 268148de9714..8b4ca1cb450a 100644
+--- a/drivers/usb/misc/usbtest.c
++++ b/drivers/usb/misc/usbtest.c
+@@ -11,6 +11,12 @@
+ #include 
+ 
+ 
++/*-------------------------------------------------------------------------*/
++
++static int override_alt = -1;
++module_param_named(alt, override_alt, int, 0644);
++MODULE_PARM_DESC(alt, ">= 0 to override altsetting selection");
++
+ /*-------------------------------------------------------------------------*/
+ 
+ /* FIXME make these public somewhere; usbdevfs.h? */
+@@ -103,6 +109,10 @@ get_endpoints(struct usbtest_dev *dev, struct usb_interface *intf)
+ 		iso_in = iso_out = NULL;
+ 		alt = intf->altsetting + tmp;
+ 
++		if (override_alt >= 0 &&
++				override_alt != alt->desc.bAlternateSetting)
++			continue;
++
+ 		/* take the first altsetting with in-bulk + out-bulk;
+ 		 * ignore other endpoints and altsettings.
+ 		 */
+@@ -144,6 +154,7 @@ get_endpoints(struct usbtest_dev *dev, struct usb_interface *intf)
+ 
+ found:
+ 	udev = testdev_to_usbdev(dev);
++	dev->info->alt = alt->desc.bAlternateSetting;
+ 	if (alt->desc.bAlternateSetting != 0) {
+ 		tmp = usb_set_interface(udev,
+ 				alt->desc.bInterfaceNumber,
+@@ -2280,7 +2291,7 @@ usbtest_probe(struct usb_interface *intf, const struct usb_device_id *id)
+ 			wtest = " intr-out";
+ 		}
+ 	} else {
+-		if (info->autoconf) {
++		if (override_alt >= 0 || info->autoconf) {
+ 			int status;
+ 
+ 			status = get_endpoints(dev, intf);

commit ee74290b7853db9d5fd64db70e5c175241c59fba
+Author: Alan Stern 
+Date:   Fri Jan 25 17:17:43 2013 -0500
+
+    USB: EHCI: fix timer bug affecting port resume
+    
+    This patch (as1652) fixes a long-standing bug in ehci-hcd.  The driver
+    relies on status polls to know when to stop port-resume signalling.
+    It uses the root-hub status timer to schedule these status polls.  But
+    when the driver for the root hub is resumed, the timer is rescheduled
+    to go off immediately -- before the port is ready.  When this happens
+    the timer does not get re-enabled, which prevents the port resume from
+    finishing until some other event occurs.
+    
+    The symptom is that when a new device is plugged in, it doesn't get
+    recognized or enumerated until lsusb is run or something else happens.
+    
+    The solution is to re-enable the root-hub status timer after every
+    status poll while a port resume is in progress.
+    
+    This bug hasn't surfaced before now because we never used to try to
+    suspend the root hub in the middle of a port resume (except by
+    coincidence).
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Norbert Preining 
+    Tested-by: Ming Lei 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index f88be801d60c..4d3b294f203e 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -649,7 +649,11 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ 			status = STS_PCD;
+ 		}
+ 	}
+-	/* FIXME autosuspend idle root hubs */
++
++	/* If a resume is in progress, make sure it can finish */
++	if (ehci->resuming_ports)
++		mod_timer(&hcd->rh_timer, jiffies + msecs_to_jiffies(25));
++
+ 	spin_unlock_irqrestore (&ehci->lock, flags);
+ 	return status ? retval : 0;
+ }

commit 840008bb5162f029d5bc05959c7f51a3e8f9e0ff
+Author: Alan Stern 
+Date:   Fri Jan 25 17:09:55 2013 -0500
+
+    USB: UHCI: notify usbcore about port resumes
+    
+    This patch (as1651) adds calls to the new
+    usb_hcd_{start,end}_port_resume() functions to uhci-hcd.  Now UHCI
+    root hubs won't be runtime suspended while they are sending a resume
+    signal to one of their ports.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
+index 768d54295a20..15d13229ddbb 100644
+--- a/drivers/usb/host/uhci-hub.c
++++ b/drivers/usb/host/uhci-hub.c
+@@ -116,6 +116,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
+ 		}
+ 	}
+ 	clear_bit(port, &uhci->resuming_ports);
++	usb_hcd_end_port_resume(&uhci_to_hcd(uhci)->self, port);
+ }
+ 
+ /* Wait for the UHCI controller in HP's iLO2 server management chip.
+@@ -167,6 +168,8 @@ static void uhci_check_ports(struct uhci_hcd *uhci)
+ 				set_bit(port, &uhci->resuming_ports);
+ 				uhci->ports_timeout = jiffies +
+ 						msecs_to_jiffies(25);
++				usb_hcd_start_port_resume(
++						&uhci_to_hcd(uhci)->self, port);
+ 
+ 				/* Make sure we see the port again
+ 				 * after the resuming period is over. */

commit f292e7f9fb0e4bec68bbd83443407d6bb7922d36
+Author: Alan Stern 
+Date:   Fri Jan 25 17:09:49 2013 -0500
+
+    USB: EHCI: notify usbcore about port resumes
+    
+    This patch (as1650) adds calls to the new
+    usb_hcd_{start,end}_port_resume() functions to ehci-hcd.  Now EHCI
+    root hubs won't be runtime suspended while they are sending a resume
+    signal to one of their ports.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Ming Lei 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 09537b2f1002..b416a3fc9959 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -797,6 +797,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 			ehci->reset_done[i] = jiffies + msecs_to_jiffies(25);
+ 			set_bit(i, &ehci->resuming_ports);
+ 			ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
++			usb_hcd_start_port_resume(&hcd->self, i);
+ 			mod_timer(&hcd->rh_timer, ehci->reset_done[i]);
+ 		}
+ 	}
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 4ccb97c0678f..f88be801d60c 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -851,6 +851,7 @@ static int ehci_hub_control (
+ 				/* resume signaling for 20 msec */
+ 				ehci->reset_done[wIndex] = jiffies
+ 						+ msecs_to_jiffies(20);
++				usb_hcd_start_port_resume(&hcd->self, wIndex);
+ 				/* check the port again */
+ 				mod_timer(&ehci_to_hcd(ehci)->rh_timer,
+ 						ehci->reset_done[wIndex]);
+@@ -862,6 +863,7 @@ static int ehci_hub_control (
+ 				clear_bit(wIndex, &ehci->suspended_ports);
+ 				set_bit(wIndex, &ehci->port_c_suspend);
+ 				ehci->reset_done[wIndex] = 0;
++				usb_hcd_end_port_resume(&hcd->self, wIndex);
+ 
+ 				/* stop resume signaling */
+ 				temp = ehci_readl(ehci, status_reg);
+@@ -950,6 +952,7 @@ static int ehci_hub_control (
+ 			ehci->reset_done[wIndex] = 0;
+ 			if (temp & PORT_PE)
+ 				set_bit(wIndex, &ehci->port_c_suspend);
++			usb_hcd_end_port_resume(&hcd->self, wIndex);
+ 		}
+ 
+ 		if (temp & PORT_OC)

commit da0aa7169b97d90f4af39a9dc84d58bbe19d7e78
+Author: Alan Stern 
+Date:   Fri Jan 25 17:09:42 2013 -0500
+
+    USB: add usb_hcd_{start,end}_port_resume
+    
+    This patch (as1649) adds a mechanism for host controller drivers to
+    inform usbcore when they have begun or ended resume signalling on a
+    particular root-hub port.  The core will then make sure that the root
+    hub does not get runtime-suspended while the port resume is going on.
+    
+    Since commit 596d789a211d134dc5f94d1e5957248c204ef850 (USB: set hub's
+    default autosuspend delay as 0), the system tries to suspend hubs
+    whenever they aren't in use.  While a root-hub port is being resumed,
+    the root hub does not appear to be in use.  Attempted runtime suspends
+    fail because of the ongoing port resume, but the PM core just keeps on
+    trying over and over again.  We want to prevent this wasteful effort.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Ming Lei 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 4225d5e72131..8e64adf8e4d5 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -39,6 +39,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ #include 
+@@ -1025,6 +1026,49 @@ static int register_root_hub(struct usb_hcd *hcd)
+ 	return retval;
+ }
+ 
++/*
++ * usb_hcd_start_port_resume - a root-hub port is sending a resume signal
++ * @bus: the bus which the root hub belongs to
++ * @portnum: the port which is being resumed
++ *
++ * HCDs should call this function when they know that a resume signal is
++ * being sent to a root-hub port.  The root hub will be prevented from
++ * going into autosuspend until usb_hcd_end_port_resume() is called.
++ *
++ * The bus's private lock must be held by the caller.
++ */
++void usb_hcd_start_port_resume(struct usb_bus *bus, int portnum)
++{
++	unsigned bit = 1 << portnum;
++
++	if (!(bus->resuming_ports & bit)) {
++		bus->resuming_ports |= bit;
++		pm_runtime_get_noresume(&bus->root_hub->dev);
++	}
++}
++EXPORT_SYMBOL_GPL(usb_hcd_start_port_resume);
++
++/*
++ * usb_hcd_end_port_resume - a root-hub port has stopped sending a resume signal
++ * @bus: the bus which the root hub belongs to
++ * @portnum: the port which is being resumed
++ *
++ * HCDs should call this function when they know that a resume signal has
++ * stopped being sent to a root-hub port.  The root hub will be allowed to
++ * autosuspend again.
++ *
++ * The bus's private lock must be held by the caller.
++ */
++void usb_hcd_end_port_resume(struct usb_bus *bus, int portnum)
++{
++	unsigned bit = 1 << portnum;
++
++	if (bus->resuming_ports & bit) {
++		bus->resuming_ports &= ~bit;
++		pm_runtime_put_noidle(&bus->root_hub->dev);
++	}
++}
++EXPORT_SYMBOL_GPL(usb_hcd_end_port_resume);
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 689b14b26c8d..4d22d0f6167a 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -357,6 +357,8 @@ struct usb_bus {
+ 	int bandwidth_int_reqs;		/* number of Interrupt requests */
+ 	int bandwidth_isoc_reqs;	/* number of Isoc. requests */
+ 
++	unsigned resuming_ports;	/* bit array: resuming root-hub ports */
++
+ #if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)
+ 	struct mon_bus *mon_bus;	/* non-null when associated */
+ 	int monitored;			/* non-zero when monitored */
+diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
+index 608050b2545f..0a78df5f6cfd 100644
+--- a/include/linux/usb/hcd.h
++++ b/include/linux/usb/hcd.h
+@@ -430,6 +430,9 @@ extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd);
+ extern void usb_wakeup_notification(struct usb_device *hdev,
+ 		unsigned int portnum);
+ 
++extern void usb_hcd_start_port_resume(struct usb_bus *bus, int portnum);
++extern void usb_hcd_end_port_resume(struct usb_bus *bus, int portnum);
++
+ /* The D0/D1 toggle bits ... USE WITH CAUTION (they're almost hcd-internal) */
+ #define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1)
+ #define	usb_dotoggle(dev, ep, out)  ((dev)->toggle[out] ^= (1 << (ep)))

commit 6e0c3339a6f19d748f16091d0a05adeb1e1f822b
+Author: Alan Stern 
+Date:   Fri Jan 25 16:54:22 2013 -0500
+
+    USB: EHCI: unlink one async QH at a time
+    
+    This patch (as1648) fixes a regression affecting nVidia EHCI
+    controllers.  Evidently they don't like to have more than one async QH
+    unlinked at a time.  I can't imagine how they manage to mess it up,
+    but at least one of them does.
+    
+    The patch changes the async unlink logic in two ways:
+    
+            Each time an IAA cycle is started, only the first QH on the
+            async unlink list is handled (rather than all of them).
+    
+            Async QHs do not all get unlinked as soon as they have been
+            empty for long enough.  Instead, only the last one (i.e., the
+            one that has been on the schedule the longest) is unlinked,
+            and then only if no other unlinks are in progress at the time.
+    
+    This means that when multiple QHs are empty, they won't be unlinked as
+    quickly as before.  That's okay; it won't affect correct operation of
+    the driver or add an excessive load.  Multiple unlinks tend to be
+    relatively rare in any case.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Piergiorgio Sartor 
+    Cc: stable  # 3.6
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 3d989028c836..fd252f0cfb3a 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -1197,17 +1197,26 @@ static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested)
+ 	if (ehci->async_iaa || ehci->async_unlinking)
+ 		return;
+ 
+-	/* Do all the waiting QHs at once */
+-	ehci->async_iaa = ehci->async_unlink;
+-	ehci->async_unlink = NULL;
+-
+ 	/* If the controller isn't running, we don't have to wait for it */
+ 	if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) {
++
++		/* Do all the waiting QHs */
++		ehci->async_iaa = ehci->async_unlink;
++		ehci->async_unlink = NULL;
++
+ 		if (!nested)		/* Avoid recursion */
+ 			end_unlink_async(ehci);
+ 
+ 	/* Otherwise start a new IAA cycle */
+ 	} else if (likely(ehci->rh_state == EHCI_RH_RUNNING)) {
++		struct ehci_qh		*qh;
++
++		/* Do only the first waiting QH (nVidia bug?) */
++		qh = ehci->async_unlink;
++		ehci->async_iaa = qh;
++		ehci->async_unlink = qh->unlink_next;
++		qh->unlink_next = NULL;
++
+ 		/* Make sure the unlinks are all visible to the hardware */
+ 		wmb();
+ 
+@@ -1255,34 +1264,35 @@ static void end_unlink_async(struct ehci_hcd *ehci)
+ 	}
+ }
+ 
++static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh);
++
+ static void unlink_empty_async(struct ehci_hcd *ehci)
+ {
+-	struct ehci_qh		*qh, *next;
+-	bool			stopped = (ehci->rh_state < EHCI_RH_RUNNING);
++	struct ehci_qh		*qh;
++	struct ehci_qh		*qh_to_unlink = NULL;
+ 	bool			check_unlinks_later = false;
++	int			count = 0;
+ 
+-	/* Unlink all the async QHs that have been empty for a timer cycle */
+-	next = ehci->async->qh_next.qh;
+-	while (next) {
+-		qh = next;
+-		next = qh->qh_next.qh;
+-
++	/* Find the last async QH which has been empty for a timer cycle */
++	for (qh = ehci->async->qh_next.qh; qh; qh = qh->qh_next.qh) {
+ 		if (list_empty(&qh->qtd_list) &&
+ 				qh->qh_state == QH_STATE_LINKED) {
+-			if (!stopped && qh->unlink_cycle ==
+-					ehci->async_unlink_cycle)
++			++count;
++			if (qh->unlink_cycle == ehci->async_unlink_cycle)
+ 				check_unlinks_later = true;
+ 			else
+-				single_unlink_async(ehci, qh);
++				qh_to_unlink = qh;
+ 		}
+ 	}
+ 
+-	/* Start a new IAA cycle if any QHs are waiting for it */
+-	if (ehci->async_unlink)
+-		start_iaa_cycle(ehci, false);
++	/* If nothing else is being unlinked, unlink the last empty QH */
++	if (!ehci->async_iaa && !ehci->async_unlink && qh_to_unlink) {
++		start_unlink_async(ehci, qh_to_unlink);
++		--count;
++	}
+ 
+-	/* QHs that haven't been empty for long enough will be handled later */
+-	if (check_unlinks_later) {
++	/* Other QHs will be handled later */
++	if (count > 0) {
+ 		ehci_enable_event(ehci, EHCI_HRTIMER_ASYNC_UNLINKS, true);
+ 		++ehci->async_unlink_cycle;
+ 	}

commit 55bcdce8a8228223ec4d17d8ded8134ed265d2c5
+Author: Alan Stern 
+Date:   Fri Jan 25 16:52:45 2013 -0500
+
+    USB: EHCI: remove ASS/PSS polling timeout
+    
+    This patch (as1647) attempts to work around a problem that seems to
+    affect some nVidia EHCI controllers.  They sometimes take a very long
+    time to turn off their async or periodic schedules.  I don't know if
+    this is a result of other problems, but in any case it seems wise not
+    to depend on schedule enables or disables taking effect in any
+    specific length of time.
+    
+    The patch removes the existing 20-ms timeout for enabling and
+    disabling the schedules.  The driver will now continue to poll the
+    schedule state at 1-ms intervals until the controller finally decides
+    to obey the most recent command issued by the driver.  Just in case
+    this hides a problem, a debugging message will be logged if the
+    controller takes longer than 20 polls.
+    
+    I don't know if this will actually fix anything, but it can't hurt.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Piergiorgio Sartor 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
+index 20dbdcbe9b0f..f904071d70df 100644
+--- a/drivers/usb/host/ehci-timer.c
++++ b/drivers/usb/host/ehci-timer.c
+@@ -113,14 +113,15 @@ static void ehci_poll_ASS(struct ehci_hcd *ehci)
+ 
+ 	if (want != actual) {
+ 
+-		/* Poll again later, but give up after about 20 ms */
+-		if (ehci->ASS_poll_count++ < 20) {
+-			ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true);
+-			return;
+-		}
+-		ehci_dbg(ehci, "Waited too long for the async schedule status (%x/%x), giving up\n",
+-				want, actual);
++		/* Poll again later */
++		ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true);
++		++ehci->ASS_poll_count;
++		return;
+ 	}
++
++	if (ehci->ASS_poll_count > 20)
++		ehci_dbg(ehci, "ASS poll count reached %d\n",
++				ehci->ASS_poll_count);
+ 	ehci->ASS_poll_count = 0;
+ 
+ 	/* The status is up-to-date; restart or stop the schedule as needed */
+@@ -159,14 +160,14 @@ static void ehci_poll_PSS(struct ehci_hcd *ehci)
+ 
+ 	if (want != actual) {
+ 
+-		/* Poll again later, but give up after about 20 ms */
+-		if (ehci->PSS_poll_count++ < 20) {
+-			ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);
+-			return;
+-		}
+-		ehci_dbg(ehci, "Waited too long for the periodic schedule status (%x/%x), giving up\n",
+-				want, actual);
++		/* Poll again later */
++		ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);
++		return;
+ 	}
++
++	if (ehci->PSS_poll_count > 20)
++		ehci_dbg(ehci, "PSS poll count reached %d\n",
++				ehci->PSS_poll_count);
+ 	ehci->PSS_poll_count = 0;
+ 
+ 	/* The status is up-to-date; restart or stop the schedule as needed */

commit bdb6bc06f7d694652c12fb8779bb031c2f220823
+Author: Alan Stern 
+Date:   Thu Jan 24 15:04:13 2013 -0500
+
+    USB: fix sign-extension bug in the hub driver
+    
+    This patch (as1646) fixes a long-standing bug in the USB hub driver.
+    Upon conversion from char to unsigned long, the bytes in the status
+    buffer are subject to unwanted sign extension.  The bytes should be
+    declared as u8 rather than char, to prevent this.
+    
+    This effects of this bug are minimal.  The hub driver may end up doing
+    a little unnecessary extra work because it thinks events have occurred
+    on some ports when they really haven't.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
+index d16a7c98aea9..c472058f8f27 100644
+--- a/drivers/usb/core/hub.h
++++ b/drivers/usb/core/hub.h
+@@ -31,7 +31,7 @@ struct usb_hub {
+ 	struct urb		*urb;		/* for interrupt polling pipe */
+ 
+ 	/* buffer for urb ... with extra space in case of babble */
+-	char			(*buffer)[8];
++	u8			(*buffer)[8];
+ 	union {
+ 		struct usb_hub_status	hub;
+ 		struct usb_port_status	port;

commit 48c3375c5f69b1c2ef3d1051a0009cb9bce0ce24
+Author: Alan Stern 
+Date:   Thu Jan 17 10:32:16 2013 -0500
+
+    USB: XHCI: fix memory leak of URB-private data
+    
+    This patch (as1640) fixes a memory leak in xhci-hcd.  The urb_priv
+    data structure isn't always deallocated in the handle_tx_event()
+    routine for non-control transfers.  The patch adds a kfree() call so
+    that all paths end up freeing the memory properly.
+    
+    This patch should be backported to kernels as old as 2.6.36, that
+    contain the commit 8e51adccd4c4b9ffcd509d7f2afce0a906139f75 "USB: xHCI:
+    Introduce urb_priv structure"
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Sarah Sharp 
+    Reported-and-tested-by: Martin Mokrejs 
+    CC: 
+
+diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
+index 151204642a6e..7f76a49e90d3 100644
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -2589,6 +2589,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,
+ 				(trb_comp_code != COMP_STALL &&
+ 					trb_comp_code != COMP_BABBLE))
+ 				xhci_urb_free_priv(xhci, urb_priv);
++			else
++				kfree(urb_priv);
+ 
+ 			usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb);
+ 			if ((urb->actual_length != urb->transfer_buffer_length &&

commit dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7f
+Author: Alan Stern 
+Date:   Wed Jan 23 13:26:15 2013 -0500
+
+    USB: EHCI: fix build error in ehci-mxc
+    
+    This patch (as1643b) fixes a build error in ehci-hcd when compiling for
+    ARM with allmodconfig:
+    
+    drivers/usb/host/ehci-hcd.c:1285:0: warning: "PLATFORM_DRIVER" redefined [enabled by default]
+    drivers/usb/host/ehci-hcd.c:1255:0: note: this is the location of the previous definition
+    drivers/usb/host/ehci-mxc.c:280:31: warning: 'ehci_mxc_driver' defined but not used [-Wunused-variable]
+    drivers/usb/host/ehci-hcd.c:1285:0: warning: "PLATFORM_DRIVER" redefined [enabled by default]
+    drivers/usb/host/ehci-hcd.c:1255:0: note: this is the location of the previous definition
+    
+    The fix is to convert ehci-mxc over to the new "ehci-hcd is a library"
+    scheme so that it can coexist peacefully with the ehci-platform
+    driver.  As part of the conversion the ehci_mxc_priv data structure,
+    which was allocated dynamically, is now placed where it belongs: in
+    the private area at the end of struct ehci_hcd.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Shawn Guo 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
+index d6bb128ce21e..3a21c5d683c0 100644
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -148,7 +148,7 @@ config USB_EHCI_FSL
+ 	  Variation of ARC USB block used in some Freescale chips.
+ 
+ config USB_EHCI_MXC
+-	bool "Support for Freescale i.MX on-chip EHCI USB controller"
++	tristate "Support for Freescale i.MX on-chip EHCI USB controller"
+ 	depends on USB_EHCI_HCD && ARCH_MXC
+ 	select USB_EHCI_ROOT_HUB_TT
+ 	---help---
+diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
+index 1eb4c3006e9e..001fbff2fdef 100644
+--- a/drivers/usb/host/Makefile
++++ b/drivers/usb/host/Makefile
+@@ -26,6 +26,7 @@ obj-$(CONFIG_PCI)		+= pci-quirks.o
+ obj-$(CONFIG_USB_EHCI_HCD)	+= ehci-hcd.o
+ obj-$(CONFIG_USB_EHCI_PCI)	+= ehci-pci.o
+ obj-$(CONFIG_USB_EHCI_HCD_PLATFORM)	+= ehci-platform.o
++obj-$(CONFIG_USB_EHCI_MXC)	+= ehci-mxc.o
+ 
+ obj-$(CONFIG_USB_OXU210HP_HCD)	+= oxu210hp-hcd.o
+ obj-$(CONFIG_USB_ISP116X_HCD)	+= isp116x-hcd.o
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index d09ff8f294fe..09537b2f1002 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1246,11 +1246,6 @@ MODULE_LICENSE ("GPL");
+ #define	PLATFORM_DRIVER		ehci_fsl_driver
+ #endif
+ 
+-#ifdef CONFIG_USB_EHCI_MXC
+-#include "ehci-mxc.c"
+-#define PLATFORM_DRIVER		ehci_mxc_driver
+-#endif
+-
+ #ifdef CONFIG_USB_EHCI_SH
+ #include "ehci-sh.c"
+ #define PLATFORM_DRIVER		ehci_hcd_sh_driver
+@@ -1349,6 +1344,7 @@ MODULE_LICENSE ("GPL");
+ #if !IS_ENABLED(CONFIG_USB_EHCI_PCI) && \
+ 	!IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \
+ 	!IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \
++	!IS_ENABLED(CONFIG_USB_EHCI_MXC) && \
+ 	!defined(PLATFORM_DRIVER) && \
+ 	!defined(PS3_SYSTEM_BUS_DRIVER) && \
+ 	!defined(OF_PLATFORM_DRIVER) && \
+diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
+index ec7f5d2c90de..dedb80bb8d40 100644
+--- a/drivers/usb/host/ehci-mxc.c
++++ b/drivers/usb/host/ehci-mxc.c
+@@ -17,75 +17,38 @@
+  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+  */
+ 
++#include 
++#include 
++#include 
+ #include 
+ #include 
+ #include 
+ #include 
+ #include 
+ #include 
++#include 
++#include 
+ 
+ #include 
+ 
+ #include 
+ 
++#include "ehci.h"
++
++#define DRIVER_DESC "Freescale On-Chip EHCI Host driver"
++
++static const char hcd_name[] = "ehci-mxc";
++
+ #define ULPI_VIEWPORT_OFFSET	0x170
+ 
+ struct ehci_mxc_priv {
+ 	struct clk *usbclk, *ahbclk, *phyclk;
+-	struct usb_hcd *hcd;
+ };
+ 
+-/* called during probe() after chip reset completes */
+-static int ehci_mxc_setup(struct usb_hcd *hcd)
+-{
+-	hcd->has_tt = 1;
+-
+-	return ehci_setup(hcd);
+-}
++static struct hc_driver __read_mostly ehci_mxc_hc_driver;
+ 
+-static const struct hc_driver ehci_mxc_hc_driver = {
+-	.description = hcd_name,
+-	.product_desc = "Freescale On-Chip EHCI Host Controller",
+-	.hcd_priv_size = sizeof(struct ehci_hcd),
+-
+-	/*
+-	 * generic hardware linkage
+-	 */
+-	.irq = ehci_irq,
+-	.flags = HCD_USB2 | HCD_MEMORY,
+-
+-	/*
+-	 * basic lifecycle operations
+-	 */
+-	.reset = ehci_mxc_setup,
+-	.start = ehci_run,
+-	.stop = ehci_stop,
+-	.shutdown = ehci_shutdown,
+-
+-	/*
+-	 * managing i/o requests and associated device resources
+-	 */
+-	.urb_enqueue = ehci_urb_enqueue,
+-	.urb_dequeue = ehci_urb_dequeue,
+-	.endpoint_disable = ehci_endpoint_disable,
+-	.endpoint_reset = ehci_endpoint_reset,
+-
+-	/*
+-	 * scheduling support
+-	 */
+-	.get_frame_number = ehci_get_frame,
+-
+-	/*
+-	 * root hub support
+-	 */
+-	.hub_status_data = ehci_hub_status_data,
+-	.hub_control = ehci_hub_control,
+-	.bus_suspend = ehci_bus_suspend,
+-	.bus_resume = ehci_bus_resume,
+-	.relinquish_port = ehci_relinquish_port,
+-	.port_handed_over = ehci_port_handed_over,
+-
+-	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
++static const struct ehci_driver_overrides ehci_mxc_overrides __initdata = {
++	.extra_priv_size =	sizeof(struct ehci_mxc_priv),
+ };
+ 
+ static int ehci_mxc_drv_probe(struct platform_device *pdev)
+@@ -112,12 +75,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
+ 	if (!hcd)
+ 		return -ENOMEM;
+ 
+-	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+-	if (!priv) {
+-		ret = -ENOMEM;
+-		goto err_alloc;
+-	}
+-
+ 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ 	if (!res) {
+ 		dev_err(dev, "Found HC with no register addr. Check setup!\n");
+@@ -135,6 +92,10 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
+ 		goto err_alloc;
+ 	}
+ 
++	hcd->has_tt = 1;
++	ehci = hcd_to_ehci(hcd);
++	priv = (struct ehci_mxc_priv *) ehci->priv;
++
+ 	/* enable clocks */
+ 	priv->usbclk = devm_clk_get(&pdev->dev, "ipg");
+ 	if (IS_ERR(priv->usbclk)) {
+@@ -169,8 +130,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
+ 		mdelay(10);
+ 	}
+ 
+-	ehci = hcd_to_ehci(hcd);
+-
+ 	/* EHCI registers start at offset 0x100 */
+ 	ehci->caps = hcd->regs + 0x100;
+ 	ehci->regs = hcd->regs + 0x100 +
+@@ -198,8 +157,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
+ 		}
+ 	}
+ 
+-	priv->hcd = hcd;
+-	platform_set_drvdata(pdev, priv);
++	platform_set_drvdata(pdev, hcd);
+ 
+ 	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
+ 	if (ret)
+@@ -244,8 +202,11 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
+ static int __exit ehci_mxc_drv_remove(struct platform_device *pdev)
+ {
+ 	struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data;
+-	struct ehci_mxc_priv *priv = platform_get_drvdata(pdev);
+-	struct usb_hcd *hcd = priv->hcd;
++	struct usb_hcd *hcd = platform_get_drvdata(pdev);
++	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
++	struct ehci_mxc_priv *priv = (struct ehci_mxc_priv *) ehci->priv;
++
++	usb_remove_hcd(hcd);
+ 
+ 	if (pdata && pdata->exit)
+ 		pdata->exit(pdev);
+@@ -253,23 +214,20 @@ static int __exit ehci_mxc_drv_remove(struct platform_device *pdev)
+ 	if (pdata->otg)
+ 		usb_phy_shutdown(pdata->otg);
+ 
+-	usb_remove_hcd(hcd);
+-	usb_put_hcd(hcd);
+-	platform_set_drvdata(pdev, NULL);
+-
+ 	clk_disable_unprepare(priv->usbclk);
+ 	clk_disable_unprepare(priv->ahbclk);
+ 
+ 	if (priv->phyclk)
+ 		clk_disable_unprepare(priv->phyclk);
+ 
++	usb_put_hcd(hcd);
++	platform_set_drvdata(pdev, NULL);
+ 	return 0;
+ }
+ 
+ static void ehci_mxc_drv_shutdown(struct platform_device *pdev)
+ {
+-	struct ehci_mxc_priv *priv = platform_get_drvdata(pdev);
+-	struct usb_hcd *hcd = priv->hcd;
++	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ 
+ 	if (hcd->driver->shutdown)
+ 		hcd->driver->shutdown(hcd);
+@@ -279,9 +237,31 @@ MODULE_ALIAS("platform:mxc-ehci");
+ 
+ static struct platform_driver ehci_mxc_driver = {
+ 	.probe = ehci_mxc_drv_probe,
+-	.remove = __exit_p(ehci_mxc_drv_remove),
++	.remove = ehci_mxc_drv_remove,
+ 	.shutdown = ehci_mxc_drv_shutdown,
+ 	.driver = {
+ 		   .name = "mxc-ehci",
+ 	},
+ };
++
++static int __init ehci_mxc_init(void)
++{
++	if (usb_disabled())
++		return -ENODEV;
++
++	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
++
++	ehci_init_driver(&ehci_mxc_hc_driver, &ehci_mxc_overrides);
++	return platform_driver_register(&ehci_mxc_driver);
++}
++module_init(ehci_mxc_init);
++
++static void __exit ehci_mxc_cleanup(void)
++{
++	platform_driver_unregister(&ehci_mxc_driver);
++}
++module_exit(ehci_mxc_cleanup);
++
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_AUTHOR("Sascha Hauer");
++MODULE_LICENSE("GPL");

commit 9debc1793b36124b9304255d2e8b5b6d8b491793
+Author: Alan Stern 
+Date:   Tue Jan 22 12:00:26 2013 -0500
+
+    USB: EHCI: add a name for the platform-private field
+    
+    This patch (as1642) adds an ehci->priv field for private use by EHCI
+    platform drivers.  The space was provided some time ago, but it didn't
+    have a name.
+    
+    Until now none of the platform drivers has used this private space,
+    but that's about to change in the next patch of this series.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 88f0142aea0c..36c3a8210595 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -225,6 +225,9 @@ struct ehci_hcd {			/* one per controller */
+ #ifdef DEBUG
+ 	struct dentry		*debug_dir;
+ #endif
++
++	/* platform-specific data -- must come last */
++	unsigned long		priv[0] __aligned(sizeof(s64));
+ };
+ 
+ /* convert between an HCD pointer and the corresponding EHCI_HCD */

commit 9ce45ef86c4c861841ba68b24341dbd9d6834c98
+Author: Alan Stern 
+Date:   Tue Jan 22 12:00:12 2013 -0500
+
+    USB: EHCI: fix incorrect configuration test
+    
+    This patch (as1641) fixes a minor bug in ehci-hcd left over from when
+    the Chipidea driver was converted to the "ehci-hcd is a library"
+    scheme.  The test for whether the Chipidea platform driver is active
+    should be IS_ENABLED(), not defined().
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 104d6348377e..d09ff8f294fe 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1348,7 +1348,7 @@ MODULE_LICENSE ("GPL");
+ 
+ #if !IS_ENABLED(CONFIG_USB_EHCI_PCI) && \
+ 	!IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \
+-	!defined(CONFIG_USB_CHIPIDEA_HOST) && \
++	!IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \
+ 	!defined(PLATFORM_DRIVER) && \
+ 	!defined(PS3_SYSTEM_BUS_DRIVER) && \
+ 	!defined(OF_PLATFORM_DRIVER) && \

commit 0f815a0a700bc10547449bde6c106051a035a1b9
+Author: Alan Stern 
+Date:   Tue Jan 22 11:37:35 2013 -0500
+
+    USB: UHCI: fix IRQ race during initialization
+    
+    This patch (as1644) fixes a race that occurs during startup in
+    uhci-hcd.  If the IRQ line is shared with other devices, it's possible
+    for the handler routine to be called before the data structures are
+    fully initialized.
+    
+    The problem is fixed by adding a check to the IRQ handler routine.  If
+    the initialization hasn't finished yet, the routine will return
+    immediately.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Don Zickus 
+    Tested-by: "Huang, Adrian (ISS Linux TW)" 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 4b9e9aba2665..4f64d24eebc8 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -447,6 +447,10 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd)
+ 		return IRQ_NONE;
+ 	uhci_writew(uhci, status, USBSTS);		/* Clear it */
+ 
++	spin_lock(&uhci->lock);
++	if (unlikely(!uhci->is_initialized))	/* not yet configured */
++		goto done;
++
+ 	if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) {
+ 		if (status & USBSTS_HSE)
+ 			dev_err(uhci_dev(uhci), "host system error, "
+@@ -455,7 +459,6 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd)
+ 			dev_err(uhci_dev(uhci), "host controller process "
+ 					"error, something bad happened!\n");
+ 		if (status & USBSTS_HCH) {
+-			spin_lock(&uhci->lock);
+ 			if (uhci->rh_state >= UHCI_RH_RUNNING) {
+ 				dev_err(uhci_dev(uhci),
+ 					"host controller halted, "
+@@ -473,15 +476,15 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd)
+ 				 * pending unlinks */
+ 				mod_timer(&hcd->rh_timer, jiffies);
+ 			}
+-			spin_unlock(&uhci->lock);
+ 		}
+ 	}
+ 
+-	if (status & USBSTS_RD)
++	if (status & USBSTS_RD) {
++		spin_unlock(&uhci->lock);
+ 		usb_hcd_poll_rh_status(hcd);
+-	else {
+-		spin_lock(&uhci->lock);
++	} else {
+ 		uhci_scan_schedule(uhci);
++ done:
+ 		spin_unlock(&uhci->lock);
+ 	}
+ 
+@@ -662,9 +665,9 @@ static int uhci_start(struct usb_hcd *hcd)
+ 	 */
+ 	mb();
+ 
++	spin_lock_irq(&uhci->lock);
+ 	configure_hc(uhci);
+ 	uhci->is_initialized = 1;
+-	spin_lock_irq(&uhci->lock);
+ 	start_rh(uhci);
+ 	spin_unlock_irq(&uhci->lock);
+ 	return 0;

commit 2cb5000057fbd2237c19b8b8bd4f6948fd11f5f8
+Author: Alan Stern 
+Date:   Wed Jan 2 13:58:18 2013 -0500
+
+    USB: usbtest: fix test number in log message
+    
+    This patch (as1639) fixes a minor bug in the usbtest driver.  Due to
+    concurrent changes, a test originally written as number 17 got changed
+    to number 24, but the corresponding change was not made in the log
+    message.  This updates the log message.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
+index 7667b12f2ff5..268148de9714 100644
+--- a/drivers/usb/misc/usbtest.c
++++ b/drivers/usb/misc/usbtest.c
+@@ -2179,7 +2179,7 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
+ 		if (dev->out_pipe == 0 || !param->length || param->sglen < 4)
+ 			break;
+ 		retval = 0;
+-		dev_info(&intf->dev, "TEST 17:  unlink from %d queues of "
++		dev_info(&intf->dev, "TEST 24:  unlink from %d queues of "
+ 				"%d %d-byte writes\n",
+ 				param->iterations, param->sglen, param->length);
+ 		for (i = param->iterations; retval == 0 && i > 0; --i) {

commit 50ce5c0683aa83eb161624ea89daa5a9eee0c2ce
+Author: Alan Stern 
+Date:   Mon Nov 26 12:36:21 2012 -0500
+
+    USB: OHCI: workaround for hardware bug: retired TDs not added to the Done Queue
+    
+    This patch (as1636) is a partial workaround for a hardware bug
+    affecting OHCI controllers by NVIDIA at least, maybe others too.  When
+    the controller retires a Transfer Descriptor, it is supposed to add
+    the TD onto the Done Queue.  But sometimes this doesn't happen, with
+    the result that ohci-hcd never realizes the corresponding transfer has
+    finished.  Symptoms can vary; a typical result is that USB audio stops
+    working after a while.
+    
+    The patch works around the problem by recognizing that TDs are always
+    processed in order.  Therefore, if a later TD is found on the Done
+    Queue than all the earlier TDs for the same endpoint must be finished
+    as well.
+    
+    Unfortunately this won't solve the problem in cases where the missing
+    TD is the last one in the endpoint's queue.  A complete fix would
+    require a signficant amount of change to the driver.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Oliver Neukum 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
+index 177a213790d4..7482cfbe8c5e 100644
+--- a/drivers/usb/host/ohci-q.c
++++ b/drivers/usb/host/ohci-q.c
+@@ -1128,6 +1128,25 @@ dl_done_list (struct ohci_hcd *ohci)
+ 
+ 	while (td) {
+ 		struct td	*td_next = td->next_dl_td;
++		struct ed	*ed = td->ed;
++
++		/*
++		 * Some OHCI controllers (NVIDIA for sure, maybe others)
++		 * occasionally forget to add TDs to the done queue.  Since
++		 * TDs for a given endpoint are always processed in order,
++		 * if we find a TD on the donelist then all of its
++		 * predecessors must be finished as well.
++		 */
++		for (;;) {
++			struct td	*td2;
++
++			td2 = list_first_entry(&ed->td_list, struct td,
++					td_list);
++			if (td2 == td)
++				break;
++			takeback_td(ohci, td2);
++		}
++
+ 		takeback_td(ohci, td);
+ 		td = td_next;
+ 	}

commit 2f02bc8af3abb846823811af65ec6cc46a4d525d
+Author: Alan Stern 
+Date:   Wed Nov 7 16:35:00 2012 -0500
+
+    USB: report submission of active URBs
+    
+    This patch (as1633) changes slightly the way usbcore handled
+    submissions of URBs that are already active.  It will now return
+    -EBUSY rather than -EINVAL, and it will call WARN_ONCE to draw
+    people's attention to the bug.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/usb/error-codes.txt b/Documentation/usb/error-codes.txt
+index 8d1e2a9ebbba..9c3eb845ebe5 100644
+--- a/Documentation/usb/error-codes.txt
++++ b/Documentation/usb/error-codes.txt
+@@ -21,6 +21,8 @@ Non-USB-specific:
+ 
+ USB-specific:
+ 
++-EBUSY		The URB is already active.
++
+ -ENODEV		specified USB-device or bus doesn't exist
+ 
+ -ENOENT		specified interface or endpoint does not exist or
+diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
+index 3662287e2f4f..e0d9d948218c 100644
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -321,8 +321,13 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 	struct usb_host_endpoint	*ep;
+ 	int				is_out;
+ 
+-	if (!urb || urb->hcpriv || !urb->complete)
++	if (!urb || !urb->complete)
+ 		return -EINVAL;
++	if (urb->hcpriv) {
++		WARN_ONCE(1, "URB %p submitted while active\n", urb);
++		return -EBUSY;
++	}
++
+ 	dev = urb->dev;
+ 	if ((!dev) || (dev->state < USB_STATE_UNAUTHENTICATED))
+ 		return -ENODEV;

commit 2656a9abcf1ec8dd5fee6a75d6997a0f2fa0094e
+Author: Alan Stern 
+Date:   Thu Nov 8 10:17:01 2012 -0500
+
+    USB: EHCI: bugfix: urb->hcpriv should not be NULL
+    
+    This patch (as1632b) fixes a bug in ehci-hcd.  The USB core uses
+    urb->hcpriv to determine whether or not an URB is active; host
+    controller drivers are supposed to set this pointer to a non-NULL
+    value when an URB is queued.  However ehci-hcd sets it to NULL for
+    isochronous URBs, which defeats the check in usbcore.
+    
+    In itself this isn't a big deal.  But people have recently found that
+    certain sequences of actions will cause the snd-usb-audio driver to
+    reuse URBs without waiting for them to complete.  In the absence of
+    proper checking by usbcore, the URBs get added to their endpoint list
+    twice.  This leads to list corruption and a system freeze.
+    
+    The patch makes ehci-hcd assign a meaningful value to urb->hcpriv for
+    isochronous URBs.  Improving robustness always helps.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Artem S. Tashkinov 
+    Reported-by: Christof Meerwald 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 4b66374bdc8e..3d989028c836 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -264,15 +264,9 @@ ehci_urb_done(struct ehci_hcd *ehci, struct urb *urb, int status)
+ __releases(ehci->lock)
+ __acquires(ehci->lock)
+ {
+-	if (likely (urb->hcpriv != NULL)) {
+-		struct ehci_qh	*qh = (struct ehci_qh *) urb->hcpriv;
+-
+-		/* S-mask in a QH means it's an interrupt urb */
+-		if ((qh->hw->hw_info2 & cpu_to_hc32(ehci, QH_SMASK)) != 0) {
+-
+-			/* ... update hc-wide periodic stats (for usbfs) */
+-			ehci_to_hcd(ehci)->self.bandwidth_int_reqs--;
+-		}
++	if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
++		/* ... update hc-wide periodic stats */
++		ehci_to_hcd(ehci)->self.bandwidth_int_reqs--;
+ 	}
+ 
+ 	if (unlikely(urb->unlinked)) {
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 2e14714b359f..69ebee73c0c1 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1630,7 +1630,7 @@ static void itd_link_urb(
+ 
+ 	/* don't need that schedule data any more */
+ 	iso_sched_free (stream, iso_sched);
+-	urb->hcpriv = NULL;
++	urb->hcpriv = stream;
+ 
+ 	++ehci->isoc_count;
+ 	enable_periodic(ehci);
+@@ -2029,7 +2029,7 @@ static void sitd_link_urb(
+ 
+ 	/* don't need that schedule data any more */
+ 	iso_sched_free (stream, sched);
+-	urb->hcpriv = NULL;
++	urb->hcpriv = stream;
+ 
+ 	++ehci->isoc_count;
+ 	enable_periodic(ehci);

commit 1b36810e27a9791878e4694357ab6d4c06acc22d
+Author: Alan Stern 
+Date:   Wed Nov 7 16:12:47 2012 -0500
+
+    USB: EHCI: miscellaneous cleanups for the library conversion
+    
+    This patch (as1630) cleans up a few minor items resulting from the
+    split-up of the ehci-hcd driver:
+    
+            Remove the product_desc string from the ehci_driver_overrides
+            structure.  All drivers will use the generic "EHCI Host
+            Controller" string.  (This was requested by Felipe Balbi.)
+    
+            Allow drivers to pass a NULL pointer to ehci_init_driver()
+            if they don't have to override any settings.
+    
+            Remove a #define symbol that is no longer used from the
+            ChipIdea host driver.
+    
+            Rename overrides to pci_overrides in ehci-pci.c, for
+            consistency with ehci-platform.c.
+    
+            Mark the *_overrides structures as __initdata.
+    
+    Signed-off-by: Alan Stern 
+    Reviewed-by: Felipe Balbi 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
+index fed97d323899..caecad9213f5 100644
+--- a/drivers/usb/chipidea/host.c
++++ b/drivers/usb/chipidea/host.c
+@@ -25,17 +25,12 @@
+ #include 
+ #include 
+ 
+-#define CHIPIDEA_EHCI
+ #include "../host/ehci.h"
+ 
+ #include "ci.h"
+ #include "bits.h"
+ #include "host.h"
+ 
+-static const struct ehci_driver_overrides ci_overrides = {
+-	.product_desc =		"ChipIdea HDRC EHCI host controller",
+-};
+-
+ static struct hc_driver __read_mostly ci_ehci_hc_driver;
+ 
+ static irqreturn_t host_irq(struct ci13xxx *ci)
+@@ -103,7 +98,7 @@ int ci_hdrc_host_init(struct ci13xxx *ci)
+ 	rdrv->name	= "host";
+ 	ci->roles[CI_ROLE_HOST] = rdrv;
+ 
+-	ehci_init_driver(&ci_ehci_hc_driver, &ci_overrides);
++	ehci_init_driver(&ci_ehci_hc_driver, NULL);
+ 
+ 	return 0;
+ }
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 28f694eb624b..c97503bb0b0e 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1231,10 +1231,11 @@ void ehci_init_driver(struct hc_driver *drv,
+ 	/* Copy the generic table to drv and then apply the overrides */
+ 	*drv = ehci_hc_driver;
+ 
+-	drv->product_desc = over->product_desc;
+-	drv->hcd_priv_size += over->extra_priv_size;
+-	if (over->reset)
+-		drv->reset = over->reset;
++	if (over) {
++		drv->hcd_priv_size += over->extra_priv_size;
++		if (over->reset)
++			drv->reset = over->reset;
++	}
+ }
+ EXPORT_SYMBOL_GPL(ehci_init_driver);
+ 
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index 46018e975244..3fb76ca61848 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -383,8 +383,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)
+ 
+ static struct hc_driver __read_mostly ehci_pci_hc_driver;
+ 
+-static const struct ehci_driver_overrides overrides = {
+-	.product_desc =		"EHCI PCI host controller",
++static const struct ehci_driver_overrides pci_overrides __initdata = {
+ 	.reset =		ehci_pci_setup,
+ };
+ 
+@@ -426,7 +425,7 @@ static int __init ehci_pci_init(void)
+ 
+ 	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+ 
+-	ehci_init_driver(&ehci_pci_hc_driver, &overrides);
++	ehci_init_driver(&ehci_pci_hc_driver, &pci_overrides);
+ 
+ 	/* Entries for the PCI suspend/resume callbacks are special */
+ 	ehci_pci_hc_driver.pci_suspend = ehci_suspend;
+diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
+index feeedf840117..f14c542b142f 100644
+--- a/drivers/usb/host/ehci-platform.c
++++ b/drivers/usb/host/ehci-platform.c
+@@ -57,8 +57,7 @@ static int ehci_platform_reset(struct usb_hcd *hcd)
+ 
+ static struct hc_driver __read_mostly ehci_platform_hc_driver;
+ 
+-static const struct ehci_driver_overrides platform_overrides = {
+-	.product_desc =	"Generic Platform EHCI controller",
++static const struct ehci_driver_overrides platform_overrides __initdata = {
+ 	.reset =	ehci_platform_reset,
+ };
+ 
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 24a8ada4701c..9dadc7118d68 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -784,7 +784,6 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x)
+ /* Declarations of things exported for use by ehci platform drivers */
+ 
+ struct ehci_driver_overrides {
+-	const char	*product_desc;
+ 	size_t		extra_priv_size;
+ 	int		(*reset)(struct usb_hcd *hcd);
+ };

commit 36caff5d795429c572443894e8789c2150dd796b
+Author: Alan Stern 
+Date:   Wed Nov 7 10:31:30 2012 -0500
+
+    USB: fix endpoint-disabling for failed config changes
+    
+    This patch (as1631) fixes a bug that shows up when a config change
+    fails for a device under an xHCI controller.  The controller needs to
+    be told to disable the endpoints that have been enabled for the new
+    config.  The existing code does this, but before storing the
+    information about which endpoints were enabled!  As a result, any
+    second attempt to install the new config is doomed to fail because
+    xhci-hcd will refuse to enable an endpoint that is already enabled.
+    
+    The patch optimistically initializes the new endpoints' device
+    structures before asking the device to switch to the new config.  If
+    the request fails then the endpoint information is already stored, so
+    we can use usb_hcd_alloc_bandwidth() to disable the endpoints with no
+    trouble.  The rest of the error path is slightly more complex now; we
+    have to disable the new interfaces and call put_device() rather than
+    simply deallocating them.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Matthias Schniedermeyer 
+    CC: Sarah Sharp 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 1ed5afd91e6d..a557658f3223 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1806,29 +1806,8 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 		goto free_interfaces;
+ 	}
+ 
+-	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+-			      USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
+-			      NULL, 0, USB_CTRL_SET_TIMEOUT);
+-	if (ret < 0) {
+-		/* All the old state is gone, so what else can we do?
+-		 * The device is probably useless now anyway.
+-		 */
+-		cp = NULL;
+-	}
+-
+-	dev->actconfig = cp;
+-	if (!cp) {
+-		usb_set_device_state(dev, USB_STATE_ADDRESS);
+-		usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
+-		/* Leave LPM disabled while the device is unconfigured. */
+-		mutex_unlock(hcd->bandwidth_mutex);
+-		usb_autosuspend_device(dev);
+-		goto free_interfaces;
+-	}
+-	mutex_unlock(hcd->bandwidth_mutex);
+-	usb_set_device_state(dev, USB_STATE_CONFIGURED);
+-
+-	/* Initialize the new interface structures and the
++	/*
++	 * Initialize the new interface structures and the
+ 	 * hc/hcd/usbcore interface/endpoint state.
+ 	 */
+ 	for (i = 0; i < nintf; ++i) {
+@@ -1872,6 +1851,35 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 	}
+ 	kfree(new_interfaces);
+ 
++	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
++			      USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
++			      NULL, 0, USB_CTRL_SET_TIMEOUT);
++	if (ret < 0 && cp) {
++		/*
++		 * All the old state is gone, so what else can we do?
++		 * The device is probably useless now anyway.
++		 */
++		usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
++		for (i = 0; i < nintf; ++i) {
++			usb_disable_interface(dev, cp->interface[i], true);
++			put_device(&cp->interface[i]->dev);
++			cp->interface[i] = NULL;
++		}
++		cp = NULL;
++	}
++
++	dev->actconfig = cp;
++	mutex_unlock(hcd->bandwidth_mutex);
++
++	if (!cp) {
++		usb_set_device_state(dev, USB_STATE_ADDRESS);
++
++		/* Leave LPM disabled while the device is unconfigured. */
++		usb_autosuspend_device(dev);
++		return ret;
++	}
++	usb_set_device_state(dev, USB_STATE_CONFIGURED);
++
+ 	if (cp->string == NULL &&
+ 			!(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
+ 		cp->string = usb_cache_string(dev, cp->desc.iConfiguration);

commit cdb2fac78321a8d621b5612c7ddfe96bdbe7d267
+Author: Alan Stern 
+Date:   Sat Nov 3 12:39:27 2012 -0400
+
+    USB: EHCI: fix build error in ChipIdea host driver
+    
+    This patch (as1629) fixes a build error in the ChipIdea host driver
+    when compiled for the ARM architecture.  The error was introduced
+    by commit 99f91934a907df31ba878dfdd090002049dc476a (USB: EHCI: make
+    ehci-platform a separate driver).
+    
+    The fix is simple; an additional header-file #include is needed.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Fengguang Wu 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
+index 30b17ae5aa22..fed97d323899 100644
+--- a/drivers/usb/chipidea/host.c
++++ b/drivers/usb/chipidea/host.c
+@@ -20,6 +20,7 @@
+  */
+ 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 

commit 09f6ffde2ecef4cc4e2a5edaa303210cabd96f57
+Author: Alan Stern 
+Date:   Fri Nov 2 12:34:41 2012 -0400
+
+    USB: EHCI: fix build error by making ChipIdea host a normal EHCI driver
+    
+    This patch (as1627) splits the ehci-hcd core code, which has become a
+    separate library module, out from the ChipIdea host driver.  Instead
+    of #include-ing ehci-hcd.c directly, the ChipIdea module will now use
+    the ehci-hcd library in a normal fashion.
+    
+    This fixes a build error caused by commit
+    3e0232039967d7a1a06c013d097458b4d5892af1 (USB: EHCI: prepare to make
+    ehci-hcd a library module); I had forgotten about the unorthodox way
+    the ChipIdea driver uses the ehci-hcd code.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Alexander Shishkin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig
+index 1ea932a13685..608a2aeb400c 100644
+--- a/drivers/usb/chipidea/Kconfig
++++ b/drivers/usb/chipidea/Kconfig
+@@ -20,6 +20,7 @@ config USB_CHIPIDEA_UDC
+ config USB_CHIPIDEA_HOST
+ 	bool "ChipIdea host controller"
+ 	depends on USB=y || USB=USB_CHIPIDEA
++	depends on USB_EHCI_HCD
+ 	select USB_EHCI_ROOT_HUB_TT
+ 	help
+ 	  Say Y here to enable host controller functionality of the
+diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
+index ebc041ff9cd5..30b17ae5aa22 100644
+--- a/drivers/usb/chipidea/host.c
++++ b/drivers/usb/chipidea/host.c
+@@ -25,57 +25,18 @@
+ #include 
+ 
+ #define CHIPIDEA_EHCI
+-#include "../host/ehci-hcd.c"
++#include "../host/ehci.h"
+ 
+ #include "ci.h"
+ #include "bits.h"
+ #include "host.h"
+ 
+-static const struct hc_driver ci_ehci_hc_driver = {
+-	.description	= "ehci_hcd",
+-	.product_desc	= "ChipIdea HDRC EHCI",
+-	.hcd_priv_size	= sizeof(struct ehci_hcd),
+-
+-	/*
+-	 * generic hardware linkage
+-	 */
+-	.irq	= ehci_irq,
+-	.flags	= HCD_MEMORY | HCD_USB2,
+-
+-	/*
+-	 * basic lifecycle operations
+-	 */
+-	.reset		= ehci_setup,
+-	.start		= ehci_run,
+-	.stop		= ehci_stop,
+-	.shutdown	= ehci_shutdown,
+-
+-	/*
+-	 * managing i/o requests and associated device resources
+-	 */
+-	.urb_enqueue		= ehci_urb_enqueue,
+-	.urb_dequeue		= ehci_urb_dequeue,
+-	.endpoint_disable	= ehci_endpoint_disable,
+-	.endpoint_reset		= ehci_endpoint_reset,
+-
+-	/*
+-	 * scheduling support
+-	 */
+-	.get_frame_number = ehci_get_frame,
+-
+-	/*
+-	 * root hub support
+-	 */
+-	.hub_status_data	= ehci_hub_status_data,
+-	.hub_control		= ehci_hub_control,
+-	.bus_suspend		= ehci_bus_suspend,
+-	.bus_resume		= ehci_bus_resume,
+-	.relinquish_port	= ehci_relinquish_port,
+-	.port_handed_over	= ehci_port_handed_over,
+-
+-	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
++static const struct ehci_driver_overrides ci_overrides = {
++	.product_desc =		"ChipIdea HDRC EHCI host controller",
+ };
+ 
++static struct hc_driver __read_mostly ci_ehci_hc_driver;
++
+ static irqreturn_t host_irq(struct ci13xxx *ci)
+ {
+ 	return usb_hcd_irq(ci->irq, ci->hcd);
+@@ -141,5 +102,7 @@ int ci_hdrc_host_init(struct ci13xxx *ci)
+ 	rdrv->name	= "host";
+ 	ci->roles[CI_ROLE_HOST] = rdrv;
+ 
++	ehci_init_driver(&ci_ehci_hc_driver, &ci_overrides);
++
+ 	return 0;
+ }
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 4a466d7730c5..28f694eb624b 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1240,14 +1240,6 @@ EXPORT_SYMBOL_GPL(ehci_init_driver);
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-/*
+- * The EHCI in ChipIdea HDRC cannot be a separate module or device,
+- * because its registers (and irq) are shared between host/gadget/otg
+- * functions  and in order to facilitate role switching we cannot
+- * give the ehci driver exclusive access to those.
+- */
+-#ifndef CHIPIDEA_EHCI
+-
+ MODULE_DESCRIPTION(DRIVER_DESC);
+ MODULE_AUTHOR (DRIVER_AUTHOR);
+ MODULE_LICENSE ("GPL");
+@@ -1359,6 +1351,7 @@ MODULE_LICENSE ("GPL");
+ 
+ #if !IS_ENABLED(CONFIG_USB_EHCI_PCI) && \
+ 	!IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \
++	!defined(CONFIG_USB_CHIPIDEA_HOST) && \
+ 	!defined(PLATFORM_DRIVER) && \
+ 	!defined(PS3_SYSTEM_BUS_DRIVER) && \
+ 	!defined(OF_PLATFORM_DRIVER) && \
+@@ -1464,5 +1457,3 @@ static void __exit ehci_hcd_cleanup(void)
+ 	clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
+ }
+ module_exit(ehci_hcd_cleanup);
+-
+-#endif /* CHIPIDEA_EHCI */

commit d1bb67a7a2a5a5ff49b0ef4d191725769243e639
+Author: Alan Stern 
+Date:   Fri Nov 2 10:13:24 2012 -0400
+
+    USB: EHCI: fix build error in ehci-platform.c under PowerPC
+    
+    This patch (as1628) fixes a build error in the ehci-platform driver
+    when compiled for the PowerPC architecture.  The error was introduced
+    by commit 99f91934a907df31ba878dfdd090002049dc476a (USB: EHCI: make
+    ehci-platform a separate driver).
+    
+    The fix is simple; a few additional header-file #includes are needed.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
+index f97fe3a4d81c..feeedf840117 100644
+--- a/drivers/usb/host/ehci-platform.c
++++ b/drivers/usb/host/ehci-platform.c
+@@ -19,6 +19,8 @@
+  * Licensed under the GNU/GPL. See COPYING for details.
+  */
+ #include 
++#include 
++#include 
+ #include 
+ #include 
+ #include 

commit 99f91934a907df31ba878dfdd090002049dc476a
+Author: Alan Stern 
+Date:   Thu Nov 1 11:13:08 2012 -0400
+
+    USB: EHCI: make ehci-platform a separate driver
+    
+    This patch (as1626) splits the ehci-platform code from ehci-hcd out
+    into its own separate driver module.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
+index 10130f47fc78..d6bb128ce21e 100644
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -430,7 +430,7 @@ config USB_OHCI_HCD_PLATFORM
+ 	  If unsure, say N.
+ 
+ config USB_EHCI_HCD_PLATFORM
+-	bool "Generic EHCI driver for a platform device"
++	tristate "Generic EHCI driver for a platform device"
+ 	depends on USB_EHCI_HCD
+ 	default n
+ 	---help---
+diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
+index a8390b091c4d..1eb4c3006e9e 100644
+--- a/drivers/usb/host/Makefile
++++ b/drivers/usb/host/Makefile
+@@ -25,6 +25,7 @@ obj-$(CONFIG_PCI)		+= pci-quirks.o
+ 
+ obj-$(CONFIG_USB_EHCI_HCD)	+= ehci-hcd.o
+ obj-$(CONFIG_USB_EHCI_PCI)	+= ehci-pci.o
++obj-$(CONFIG_USB_EHCI_HCD_PLATFORM)	+= ehci-platform.o
+ 
+ obj-$(CONFIG_USB_OXU210HP_HCD)	+= oxu210hp-hcd.o
+ obj-$(CONFIG_USB_ISP116X_HCD)	+= isp116x-hcd.o
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 7113d6ad24f7..4a466d7730c5 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1357,12 +1357,8 @@ MODULE_LICENSE ("GPL");
+ #define	PLATFORM_DRIVER		ehci_hcd_sead3_driver
+ #endif
+ 
+-#ifdef CONFIG_USB_EHCI_HCD_PLATFORM
+-#include "ehci-platform.c"
+-#define PLATFORM_DRIVER		ehci_platform_driver
+-#endif
+-
+ #if !IS_ENABLED(CONFIG_USB_EHCI_PCI) && \
++	!IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \
+ 	!defined(PLATFORM_DRIVER) && \
+ 	!defined(PS3_SYSTEM_BUS_DRIVER) && \
+ 	!defined(OF_PLATFORM_DRIVER) && \
+diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
+index 6e6c23bdb484..f97fe3a4d81c 100644
+--- a/drivers/usb/host/ehci-platform.c
++++ b/drivers/usb/host/ehci-platform.c
+@@ -18,9 +18,19 @@
+  *
+  * Licensed under the GNU/GPL. See COPYING for details.
+  */
++#include 
++#include 
+ #include 
++#include 
++#include 
+ #include 
+ 
++#include "ehci.h"
++
++#define DRIVER_DESC "EHCI generic platform driver"
++
++static const char hcd_name[] = "ehci-platform";
++
+ static int ehci_platform_reset(struct usb_hcd *hcd)
+ {
+ 	struct platform_device *pdev = to_platform_device(hcd->self.controller);
+@@ -43,36 +53,11 @@ static int ehci_platform_reset(struct usb_hcd *hcd)
+ 	return 0;
+ }
+ 
+-static const struct hc_driver ehci_platform_hc_driver = {
+-	.description		= hcd_name,
+-	.product_desc		= "Generic Platform EHCI Controller",
+-	.hcd_priv_size		= sizeof(struct ehci_hcd),
+-
+-	.irq			= ehci_irq,
+-	.flags			= HCD_MEMORY | HCD_USB2,
+-
+-	.reset			= ehci_platform_reset,
+-	.start			= ehci_run,
+-	.stop			= ehci_stop,
+-	.shutdown		= ehci_shutdown,
++static struct hc_driver __read_mostly ehci_platform_hc_driver;
+ 
+-	.urb_enqueue		= ehci_urb_enqueue,
+-	.urb_dequeue		= ehci_urb_dequeue,
+-	.endpoint_disable	= ehci_endpoint_disable,
+-	.endpoint_reset		= ehci_endpoint_reset,
+-
+-	.get_frame_number	= ehci_get_frame,
+-
+-	.hub_status_data	= ehci_hub_status_data,
+-	.hub_control		= ehci_hub_control,
+-#if defined(CONFIG_PM)
+-	.bus_suspend		= ehci_bus_suspend,
+-	.bus_resume		= ehci_bus_resume,
+-#endif
+-	.relinquish_port	= ehci_relinquish_port,
+-	.port_handed_over	= ehci_port_handed_over,
+-
+-	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
++static const struct ehci_driver_overrides platform_overrides = {
++	.product_desc =	"Generic Platform EHCI controller",
++	.reset =	ehci_platform_reset,
+ };
+ 
+ static int __devinit ehci_platform_probe(struct platform_device *dev)
+@@ -218,3 +203,26 @@ static struct platform_driver ehci_platform_driver = {
+ 		.pm	= &ehci_platform_pm_ops,
+ 	}
+ };
++
++static int __init ehci_platform_init(void)
++{
++	if (usb_disabled())
++		return -ENODEV;
++
++	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
++
++	ehci_init_driver(&ehci_platform_hc_driver, &platform_overrides);
++	return platform_driver_register(&ehci_platform_driver);
++}
++module_init(ehci_platform_init);
++
++static void __exit ehci_platform_cleanup(void)
++{
++	platform_driver_unregister(&ehci_platform_driver);
++}
++module_exit(ehci_platform_cleanup);
++
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_AUTHOR("Hauke Mehrtens");
++MODULE_AUTHOR("Alan Stern");
++MODULE_LICENSE("GPL");

commit adfa79d1c06a32650332930ca4c488ca570b3407
+Author: Alan Stern 
+Date:   Thu Nov 1 11:13:04 2012 -0400
+
+    USB: EHCI: make ehci-pci a separate driver
+    
+    This patch (as1625) splits the PCI portion of ehci-hcd out into its
+    own separate driver module, called ehci-pci.  Consistently with the
+    current practice, the decision whether to build this module is not
+    user-configurable.  If EHCI and PCI are enabled then the module will
+    be built, always.
+    
+    Signed-off-by: Alan Stern 
+    CC: Felipe Balbi 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
+index 8cc06f054c6a..10130f47fc78 100644
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -95,6 +95,11 @@ config USB_EHCI_TT_NEWSCHED
+ 
+ 	  If unsure, say Y.
+ 
++config USB_EHCI_PCI
++	tristate
++	depends on USB_EHCI_HCD && PCI
++	default y
++
+ config USB_EHCI_HCD_PMC_MSP
+ 	tristate "EHCI support for on-chip PMC MSP71xx USB controller"
+ 	depends on USB_EHCI_HCD && MSP_HAS_USB
+diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
+index 332ed897a6fb..a8390b091c4d 100644
+--- a/drivers/usb/host/Makefile
++++ b/drivers/usb/host/Makefile
+@@ -24,6 +24,8 @@ obj-$(CONFIG_USB_WHCI_HCD)	+= whci/
+ obj-$(CONFIG_PCI)		+= pci-quirks.o
+ 
+ obj-$(CONFIG_USB_EHCI_HCD)	+= ehci-hcd.o
++obj-$(CONFIG_USB_EHCI_PCI)	+= ehci-pci.o
++
+ obj-$(CONFIG_USB_OXU210HP_HCD)	+= oxu210hp-hcd.o
+ obj-$(CONFIG_USB_ISP116X_HCD)	+= isp116x-hcd.o
+ obj-$(CONFIG_USB_ISP1362_HCD)	+= isp1362-hcd.o
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index dee3541bfae8..7113d6ad24f7 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1252,11 +1252,6 @@ MODULE_DESCRIPTION(DRIVER_DESC);
+ MODULE_AUTHOR (DRIVER_AUTHOR);
+ MODULE_LICENSE ("GPL");
+ 
+-#ifdef CONFIG_PCI
+-#include "ehci-pci.c"
+-#define	PCI_DRIVER		ehci_pci_driver
+-#endif
+-
+ #ifdef CONFIG_USB_EHCI_FSL
+ #include "ehci-fsl.c"
+ #define	PLATFORM_DRIVER		ehci_fsl_driver
+@@ -1367,9 +1362,11 @@ MODULE_LICENSE ("GPL");
+ #define PLATFORM_DRIVER		ehci_platform_driver
+ #endif
+ 
+-#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
+-    !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
+-    !defined(XILINX_OF_PLATFORM_DRIVER)
++#if !IS_ENABLED(CONFIG_USB_EHCI_PCI) && \
++	!defined(PLATFORM_DRIVER) && \
++	!defined(PS3_SYSTEM_BUS_DRIVER) && \
++	!defined(OF_PLATFORM_DRIVER) && \
++	!defined(XILINX_OF_PLATFORM_DRIVER)
+ #error "missing bus glue for ehci-hcd"
+ #endif
+ 
+@@ -1406,12 +1403,6 @@ static int __init ehci_hcd_init(void)
+ 		goto clean0;
+ #endif
+ 
+-#ifdef PCI_DRIVER
+-	retval = pci_register_driver(&PCI_DRIVER);
+-	if (retval < 0)
+-		goto clean1;
+-#endif
+-
+ #ifdef PS3_SYSTEM_BUS_DRIVER
+ 	retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER);
+ 	if (retval < 0)
+@@ -1443,10 +1434,6 @@ static int __init ehci_hcd_init(void)
+ 	ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+ clean2:
+ #endif
+-#ifdef PCI_DRIVER
+-	pci_unregister_driver(&PCI_DRIVER);
+-clean1:
+-#endif
+ #ifdef PLATFORM_DRIVER
+ 	platform_driver_unregister(&PLATFORM_DRIVER);
+ clean0:
+@@ -1472,9 +1459,6 @@ static void __exit ehci_hcd_cleanup(void)
+ #ifdef PLATFORM_DRIVER
+ 	platform_driver_unregister(&PLATFORM_DRIVER);
+ #endif
+-#ifdef PCI_DRIVER
+-	pci_unregister_driver(&PCI_DRIVER);
+-#endif
+ #ifdef PS3_SYSTEM_BUS_DRIVER
+ 	ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+ #endif
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index c92dcaee0d4d..46018e975244 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -18,9 +18,18 @@
+  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+  */
+ 
+-#ifndef CONFIG_PCI
+-#error "This file is PCI bus glue.  CONFIG_PCI must be defined."
+-#endif
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include "ehci.h"
++#include "pci-quirks.h"
++
++#define DRIVER_DESC "EHCI PCI platform driver"
++
++static const char hcd_name[] = "ehci-pci";
+ 
+ /* defined here to avoid adding to pci_ids.h for single instance use */
+ #define PCI_DEVICE_ID_INTEL_CE4100_USB	0x2e70
+@@ -315,11 +324,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+  * Also they depend on separate root hub suspend/resume.
+  */
+ 
+-static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+-{
+-	return ehci_suspend(hcd, do_wakeup);
+-}
+-
+ static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev)
+ {
+ 	return pdev->class == PCI_CLASS_SERIAL_USB_EHCI &&
+@@ -370,55 +374,18 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)
+ 		(void) ehci_pci_reinit(ehci, pdev);
+ 	return 0;
+ }
+-#endif
+-
+-static const struct hc_driver ehci_pci_hc_driver = {
+-	.description =		hcd_name,
+-	.product_desc =		"EHCI Host Controller",
+-	.hcd_priv_size =	sizeof(struct ehci_hcd),
+ 
+-	/*
+-	 * generic hardware linkage
+-	 */
+-	.irq =			ehci_irq,
+-	.flags =		HCD_MEMORY | HCD_USB2,
+-
+-	/*
+-	 * basic lifecycle operations
+-	 */
+-	.reset =		ehci_pci_setup,
+-	.start =		ehci_run,
+-#ifdef	CONFIG_PM
+-	.pci_suspend =		ehci_pci_suspend,
+-	.pci_resume =		ehci_pci_resume,
+-#endif
+-	.stop =			ehci_stop,
+-	.shutdown =		ehci_shutdown,
++#else
+ 
+-	/*
+-	 * managing i/o requests and associated device resources
+-	 */
+-	.urb_enqueue =		ehci_urb_enqueue,
+-	.urb_dequeue =		ehci_urb_dequeue,
+-	.endpoint_disable =	ehci_endpoint_disable,
+-	.endpoint_reset =	ehci_endpoint_reset,
++#define ehci_suspend		NULL
++#define ehci_pci_resume		NULL
++#endif	/* CONFIG_PM */
+ 
+-	/*
+-	 * scheduling support
+-	 */
+-	.get_frame_number =	ehci_get_frame,
++static struct hc_driver __read_mostly ehci_pci_hc_driver;
+ 
+-	/*
+-	 * root hub support
+-	 */
+-	.hub_status_data =	ehci_hub_status_data,
+-	.hub_control =		ehci_hub_control,
+-	.bus_suspend =		ehci_bus_suspend,
+-	.bus_resume =		ehci_bus_resume,
+-	.relinquish_port =	ehci_relinquish_port,
+-	.port_handed_over =	ehci_port_handed_over,
+-
+-	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
++static const struct ehci_driver_overrides overrides = {
++	.product_desc =		"EHCI PCI host controller",
++	.reset =		ehci_pci_setup,
+ };
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -451,3 +418,31 @@ static struct pci_driver ehci_pci_driver = {
+ 	},
+ #endif
+ };
++
++static int __init ehci_pci_init(void)
++{
++	if (usb_disabled())
++		return -ENODEV;
++
++	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
++
++	ehci_init_driver(&ehci_pci_hc_driver, &overrides);
++
++	/* Entries for the PCI suspend/resume callbacks are special */
++	ehci_pci_hc_driver.pci_suspend = ehci_suspend;
++	ehci_pci_hc_driver.pci_resume = ehci_pci_resume;
++
++	return pci_register_driver(&ehci_pci_driver);
++}
++module_init(ehci_pci_init);
++
++static void __exit ehci_pci_cleanup(void)
++{
++	pci_unregister_driver(&ehci_pci_driver);
++}
++module_exit(ehci_pci_cleanup);
++
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_AUTHOR("David Brownell");
++MODULE_AUTHOR("Alan Stern");
++MODULE_LICENSE("GPL");

commit 3e0232039967d7a1a06c013d097458b4d5892af1
+Author: Alan Stern 
+Date:   Thu Nov 1 11:12:58 2012 -0400
+
+    USB: EHCI: prepare to make ehci-hcd a library module
+    
+    This patch (as1624) prepares ehci-hcd for being split up into a core
+    library and separate platform driver modules.  A generic
+    ehci_hc_driver structure is created, containing all the "standard"
+    values, and a new mechanism is added whereby a driver module can
+    specify a set of overrides to those values.  In addition the
+    ehci_setup(), ehci_suspend(), and ehci_resume() routines need to be
+    EXPORTed for use by the drivers.
+    
+    As a side effect of this change, a few routines no longer need to be
+    marked __maybe_unused.
+    
+    Signed-off-by: Alan Stern 
+    CC: Felipe Balbi 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index ab4a769a4104..dee3541bfae8 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -649,7 +649,7 @@ static int ehci_run (struct usb_hcd *hcd)
+ 	return 0;
+ }
+ 
+-static int ehci_setup(struct usb_hcd *hcd)
++int ehci_setup(struct usb_hcd *hcd)
+ {
+ 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ 	int retval;
+@@ -680,6 +680,7 @@ static int ehci_setup(struct usb_hcd *hcd)
+ 
+ 	return 0;
+ }
++EXPORT_SYMBOL_GPL(ehci_setup);
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+@@ -1085,7 +1086,7 @@ static int ehci_get_frame (struct usb_hcd *hcd)
+ 
+ /* These routines handle the generic parts of controller suspend/resume */
+ 
+-static int __maybe_unused ehci_suspend(struct usb_hcd *hcd, bool do_wakeup)
++int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+ {
+ 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
+ 
+@@ -1108,9 +1109,10 @@ static int __maybe_unused ehci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+ 
+ 	return 0;
+ }
++EXPORT_SYMBOL_GPL(ehci_suspend);
+ 
+ /* Returns 0 if power was preserved, 1 if power was lost */
+-static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated)
++int ehci_resume(struct usb_hcd *hcd, bool hibernated)
+ {
+ 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
+ 
+@@ -1168,11 +1170,76 @@ static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated)
+ 
+ 	return 1;
+ }
++EXPORT_SYMBOL_GPL(ehci_resume);
+ 
+ #endif
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++/*
++ * Generic structure: This gets copied for platform drivers so that
++ * individual entries can be overridden as needed.
++ */
++
++static const struct hc_driver ehci_hc_driver = {
++	.description =		hcd_name,
++	.product_desc =		"EHCI Host Controller",
++	.hcd_priv_size =	sizeof(struct ehci_hcd),
++
++	/*
++	 * generic hardware linkage
++	 */
++	.irq =			ehci_irq,
++	.flags =		HCD_MEMORY | HCD_USB2,
++
++	/*
++	 * basic lifecycle operations
++	 */
++	.reset =		ehci_setup,
++	.start =		ehci_run,
++	.stop =			ehci_stop,
++	.shutdown =		ehci_shutdown,
++
++	/*
++	 * managing i/o requests and associated device resources
++	 */
++	.urb_enqueue =		ehci_urb_enqueue,
++	.urb_dequeue =		ehci_urb_dequeue,
++	.endpoint_disable =	ehci_endpoint_disable,
++	.endpoint_reset =	ehci_endpoint_reset,
++	.clear_tt_buffer_complete =	ehci_clear_tt_buffer_complete,
++
++	/*
++	 * scheduling support
++	 */
++	.get_frame_number =	ehci_get_frame,
++
++	/*
++	 * root hub support
++	 */
++	.hub_status_data =	ehci_hub_status_data,
++	.hub_control =		ehci_hub_control,
++	.bus_suspend =		ehci_bus_suspend,
++	.bus_resume =		ehci_bus_resume,
++	.relinquish_port =	ehci_relinquish_port,
++	.port_handed_over =	ehci_port_handed_over,
++};
++
++void ehci_init_driver(struct hc_driver *drv,
++		const struct ehci_driver_overrides *over)
++{
++	/* Copy the generic table to drv and then apply the overrides */
++	*drv = ehci_hc_driver;
++
++	drv->product_desc = over->product_desc;
++	drv->hcd_priv_size += over->extra_priv_size;
++	if (over->reset)
++		drv->reset = over->reset;
++}
++EXPORT_SYMBOL_GPL(ehci_init_driver);
++
++/*-------------------------------------------------------------------------*/
++
+ /*
+  * The EHCI in ChipIdea HDRC cannot be a separate module or device,
+  * because its registers (and irq) are shared between host/gadget/otg
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index a59c61fea09f..4ccb97c0678f 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -1109,8 +1109,7 @@ static int ehci_hub_control (
+ 	return retval;
+ }
+ 
+-static void __maybe_unused ehci_relinquish_port(struct usb_hcd *hcd,
+-		int portnum)
++static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum)
+ {
+ 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
+ 
+@@ -1119,8 +1118,7 @@ static void __maybe_unused ehci_relinquish_port(struct usb_hcd *hcd,
+ 	set_owner(ehci, --portnum, PORT_OWNER);
+ }
+ 
+-static int __maybe_unused ehci_port_handed_over(struct usb_hcd *hcd,
+-		int portnum)
++static int ehci_port_handed_over(struct usb_hcd *hcd, int portnum)
+ {
+ 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
+ 	u32 __iomem		*reg;
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 2262dcdaa3c1..24a8ada4701c 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -781,4 +781,21 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++/* Declarations of things exported for use by ehci platform drivers */
++
++struct ehci_driver_overrides {
++	const char	*product_desc;
++	size_t		extra_priv_size;
++	int		(*reset)(struct usb_hcd *hcd);
++};
++
++extern void	ehci_init_driver(struct hc_driver *drv,
++				const struct ehci_driver_overrides *over);
++extern int	ehci_setup(struct usb_hcd *hcd);
++
++#ifdef CONFIG_PM
++extern int	ehci_suspend(struct usb_hcd *hcd, bool do_wakeup);
++extern int	ehci_resume(struct usb_hcd *hcd, bool hibernated);
++#endif	/* CONFIG_PM */
++
+ #endif /* __LINUX_EHCI_HCD_H */

commit c73cee717e7d5da0698acb720ad1219646fe4f46
+Author: Alan Stern 
+Date:   Wed Oct 31 13:21:06 2012 -0400
+
+    USB: EHCI: remove ehci_port_power() routine
+    
+    This patch (as1623) removes the ehci_port_power() routine and all the
+    places that call it.  There's no reason for ehci-hcd to change the
+    port power settings; the hub driver takes care of all that stuff.
+    
+    There is one exception: When the controller is resumed from
+    hibernation or following a loss of power, the ports that are supposed
+    to be handed over to a companion controller must be powered on first.
+    Otherwise the handover won't work.  This process is not visible to the
+    hub driver, so it has to be handled in ehci-hcd.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/arm/mach-cns3xxx/cns3420vb.c b/arch/arm/mach-cns3xxx/cns3420vb.c
+index 8a00cee82228..ae305397003c 100644
+--- a/arch/arm/mach-cns3xxx/cns3420vb.c
++++ b/arch/arm/mach-cns3xxx/cns3420vb.c
+@@ -162,7 +162,6 @@ static void csn3xxx_usb_power_off(struct platform_device *pdev)
+ }
+ 
+ static struct usb_ehci_pdata cns3xxx_usb_ehci_pdata = {
+-	.port_power_off	= 1,
+ 	.power_on	= csn3xxx_usb_power_on,
+ 	.power_off	= csn3xxx_usb_power_off,
+ };
+diff --git a/arch/mips/ath79/dev-usb.c b/arch/mips/ath79/dev-usb.c
+index 072bb9be2304..bd2bc108e1b5 100644
+--- a/arch/mips/ath79/dev-usb.c
++++ b/arch/mips/ath79/dev-usb.c
+@@ -50,13 +50,11 @@ static u64 ath79_ehci_dmamask = DMA_BIT_MASK(32);
+ 
+ static struct usb_ehci_pdata ath79_ehci_pdata_v1 = {
+ 	.has_synopsys_hc_bug	= 1,
+-	.port_power_off		= 1,
+ };
+ 
+ static struct usb_ehci_pdata ath79_ehci_pdata_v2 = {
+ 	.caps_offset		= 0x100,
+ 	.has_tt			= 1,
+-	.port_power_off		= 1,
+ };
+ 
+ static struct platform_device ath79_ehci_device = {
+diff --git a/arch/mips/loongson1/common/platform.c b/arch/mips/loongson1/common/platform.c
+index 2874bf224418..0412ad61e290 100644
+--- a/arch/mips/loongson1/common/platform.c
++++ b/arch/mips/loongson1/common/platform.c
+@@ -109,7 +109,6 @@ static struct resource ls1x_ehci_resources[] = {
+ };
+ 
+ static struct usb_ehci_pdata ls1x_ehci_pdata = {
+-	.port_power_off	= 1,
+ };
+ 
+ struct platform_device ls1x_ehci_device = {
+diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
+index ebff9f4f56ec..ebc041ff9cd5 100644
+--- a/drivers/usb/chipidea/host.c
++++ b/drivers/usb/chipidea/host.c
+@@ -31,22 +31,6 @@
+ #include "bits.h"
+ #include "host.h"
+ 
+-static int ci_ehci_setup(struct usb_hcd *hcd)
+-{
+-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+-	int ret;
+-
+-	hcd->has_tt = 1;
+-
+-	ret = ehci_setup(hcd);
+-	if (ret)
+-		return ret;
+-
+-	ehci_port_power(ehci, 0);
+-
+-	return ret;
+-}
+-
+ static const struct hc_driver ci_ehci_hc_driver = {
+ 	.description	= "ehci_hcd",
+ 	.product_desc	= "ChipIdea HDRC EHCI",
+@@ -61,7 +45,7 @@ static const struct hc_driver ci_ehci_hc_driver = {
+ 	/*
+ 	 * basic lifecycle operations
+ 	 */
+-	.reset		= ci_ehci_setup,
++	.reset		= ehci_setup,
+ 	.start		= ehci_run,
+ 	.stop		= ehci_stop,
+ 	.shutdown	= ehci_shutdown,
+diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
+index 411bb74152eb..d23321ec0e46 100644
+--- a/drivers/usb/host/ehci-atmel.c
++++ b/drivers/usb/host/ehci-atmel.c
+@@ -53,18 +53,11 @@ static void atmel_stop_ehci(struct platform_device *pdev)
+ static int ehci_atmel_setup(struct usb_hcd *hcd)
+ {
+ 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+-	int retval;
+ 
+ 	/* registers start at offset 0x0 */
+ 	ehci->caps = hcd->regs;
+ 
+-	retval = ehci_setup(hcd);
+-	if (retval)
+-		return retval;
+-
+-	ehci_port_power(ehci, 0);
+-
+-	return retval;
++	return ehci_setup(hcd);
+ }
+ 
+ static const struct hc_driver ehci_atmel_hc_driver = {
+diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
+index 0d2f35ca93f1..fd9b5424b860 100644
+--- a/drivers/usb/host/ehci-fsl.c
++++ b/drivers/usb/host/ehci-fsl.c
+@@ -349,7 +349,6 @@ static int ehci_fsl_reinit(struct ehci_hcd *ehci)
+ {
+ 	if (ehci_fsl_usb_setup(ehci))
+ 		return -EINVAL;
+-	ehci_port_power(ehci, 0);
+ 
+ 	return 0;
+ }
+diff --git a/drivers/usb/host/ehci-grlib.c b/drivers/usb/host/ehci-grlib.c
+index 3180cb3624d9..da4269550fba 100644
+--- a/drivers/usb/host/ehci-grlib.c
++++ b/drivers/usb/host/ehci-grlib.c
+@@ -34,22 +34,6 @@
+ 
+ #define GRUSBHC_HCIVERSION 0x0100 /* Known value of cap. reg. HCIVERSION */
+ 
+-/* called during probe() after chip reset completes */
+-static int ehci_grlib_setup(struct usb_hcd *hcd)
+-{
+-	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
+-	int		retval;
+-
+-	retval = ehci_setup(hcd);
+-	if (retval)
+-		return retval;
+-
+-	ehci_port_power(ehci, 1);
+-
+-	return retval;
+-}
+-
+-
+ static const struct hc_driver ehci_grlib_hc_driver = {
+ 	.description		= hcd_name,
+ 	.product_desc		= "GRLIB GRUSBHC EHCI",
+@@ -64,7 +48,7 @@ static const struct hc_driver ehci_grlib_hc_driver = {
+ 	/*
+ 	 * basic lifecycle operations
+ 	 */
+-	.reset			= ehci_grlib_setup,
++	.reset			= ehci_setup,
+ 	.start			= ehci_run,
+ 	.stop			= ehci_stop,
+ 	.shutdown		= ehci_shutdown,
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 68dd1c99b1f5..ab4a769a4104 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -371,24 +371,6 @@ static void ehci_shutdown(struct usb_hcd *hcd)
+ 	hrtimer_cancel(&ehci->hrtimer);
+ }
+ 
+-static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
+-{
+-	unsigned port;
+-
+-	if (!HCS_PPC (ehci->hcs_params))
+-		return;
+-
+-	ehci_dbg (ehci, "...power%s ports...\n", is_on ? "up" : "down");
+-	for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; )
+-		(void) ehci_hub_control(ehci_to_hcd(ehci),
+-				is_on ? SetPortFeature : ClearPortFeature,
+-				USB_PORT_FEAT_POWER,
+-				port--, NULL, 0);
+-	/* Flush those writes */
+-	ehci_readl(ehci, &ehci->regs->command);
+-	msleep(20);
+-}
+-
+ /*-------------------------------------------------------------------------*/
+ 
+ /*
+@@ -1184,9 +1166,6 @@ static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated)
+ 	ehci->rh_state = EHCI_RH_SUSPENDED;
+ 	spin_unlock_irq(&ehci->lock);
+ 
+-	/* here we "know" root ports should always stay powered */
+-	ehci_port_power(ehci, 1);
+-
+ 	return 1;
+ }
+ 
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index a2c56cdd2c3a..a59c61fea09f 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -56,6 +56,19 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
+ 	if (!ehci->owned_ports)
+ 		return;
+ 
++	/* Make sure the ports are powered */
++	port = HCS_N_PORTS(ehci->hcs_params);
++	while (port--) {
++		if (test_bit(port, &ehci->owned_ports)) {
++			reg = &ehci->regs->port_status[port];
++			status = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
++			if (!(status & PORT_POWER)) {
++				status |= PORT_POWER;
++				ehci_writel(ehci, status, reg);
++			}
++		}
++	}
++
+ 	/* Give the connections some time to appear */
+ 	msleep(20);
+ 
+diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
+index 4af4dc5b618c..7fa1ba4de789 100644
+--- a/drivers/usb/host/ehci-msm.c
++++ b/drivers/usb/host/ehci-msm.c
+@@ -53,7 +53,6 @@ static int ehci_msm_reset(struct usb_hcd *hcd)
+ 	/* Disable streaming mode and select host mode */
+ 	writel(0x13, USB_USBMODE);
+ 
+-	ehci_port_power(ehci, 1);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
+index 4a08fc0b27c9..a37224a4a49b 100644
+--- a/drivers/usb/host/ehci-mxc.c
++++ b/drivers/usb/host/ehci-mxc.c
+@@ -40,16 +40,10 @@ struct ehci_mxc_priv {
+ static int ehci_mxc_setup(struct usb_hcd *hcd)
+ {
+ 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+-	int retval;
+ 
+ 	hcd->has_tt = 1;
+ 
+-	retval = ehci_setup(hcd);
+-	if (retval)
+-		return retval;
+-
+-	ehci_port_power(ehci, 0);
+-	return 0;
++	return ehci_setup(hcd);
+ }
+ 
+ static const struct hc_driver ehci_mxc_hc_driver = {
+diff --git a/drivers/usb/host/ehci-octeon.c b/drivers/usb/host/ehci-octeon.c
+index ba26957abf46..a89750fff4ff 100644
+--- a/drivers/usb/host/ehci-octeon.c
++++ b/drivers/usb/host/ehci-octeon.c
+@@ -159,9 +159,6 @@ static int ehci_octeon_drv_probe(struct platform_device *pdev)
+ 
+ 	platform_set_drvdata(pdev, hcd);
+ 
+-	/* root ports should always stay powered */
+-	ehci_port_power(ehci, 1);
+-
+ 	return 0;
+ err3:
+ 	ehci_octeon_stop();
+diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
+index d7fe287d0678..44e7d0f638e8 100644
+--- a/drivers/usb/host/ehci-omap.c
++++ b/drivers/usb/host/ehci-omap.c
+@@ -146,9 +146,6 @@ static int omap_ehci_init(struct usb_hcd *hcd)
+ 			gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1);
+ 	}
+ 
+-	/* root ports should always stay powered */
+-	ehci_port_power(ehci, 1);
+-
+ 	return rc;
+ }
+ 
+diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
+index 9c2717d66730..96da679becef 100644
+--- a/drivers/usb/host/ehci-orion.c
++++ b/drivers/usb/host/ehci-orion.c
+@@ -101,20 +101,6 @@ static void orion_usb_phy_v1_setup(struct usb_hcd *hcd)
+ 	wrl(USB_MODE, 0x13);
+ }
+ 
+-static int ehci_orion_setup(struct usb_hcd *hcd)
+-{
+-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+-	int retval;
+-
+-	retval = ehci_setup(hcd);
+-	if (retval)
+-		return retval;
+-
+-	ehci_port_power(ehci, 0);
+-
+-	return retval;
+-}
+-
+ static const struct hc_driver ehci_orion_hc_driver = {
+ 	.description = hcd_name,
+ 	.product_desc = "Marvell Orion EHCI",
+@@ -129,7 +115,7 @@ static const struct hc_driver ehci_orion_hc_driver = {
+ 	/*
+ 	 * basic lifecycle operations
+ 	 */
+-	.reset = ehci_orion_setup,
++	.reset = ehci_setup,
+ 	.start = ehci_run,
+ 	.stop = ehci_stop,
+ 	.shutdown = ehci_shutdown,
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index e17330ae0aee..c92dcaee0d4d 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -297,7 +297,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 		ehci_warn(ehci, "selective suspend/wakeup unavailable\n");
+ #endif
+ 
+-	ehci_port_power(ehci, 1);
+ 	retval = ehci_pci_reinit(ehci, pdev);
+ done:
+ 	return retval;
+diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
+index 272728c48c9e..6e6c23bdb484 100644
+--- a/drivers/usb/host/ehci-platform.c
++++ b/drivers/usb/host/ehci-platform.c
+@@ -40,11 +40,6 @@ static int ehci_platform_reset(struct usb_hcd *hcd)
+ 
+ 	if (pdata->no_io_watchdog)
+ 		ehci->need_io_watchdog = 0;
+-	if (pdata->port_power_on)
+-		ehci_port_power(ehci, 1);
+-	if (pdata->port_power_off)
+-		ehci_port_power(ehci, 0);
+-
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/host/ehci-pmcmsp.c b/drivers/usb/host/ehci-pmcmsp.c
+index 087aee2a904f..363890ee41d2 100644
+--- a/drivers/usb/host/ehci-pmcmsp.c
++++ b/drivers/usb/host/ehci-pmcmsp.c
+@@ -90,7 +90,6 @@ static int ehci_msp_setup(struct usb_hcd *hcd)
+ 		return retval;
+ 
+ 	usb_hcd_tdi_set_mode(ehci);
+-	ehci_port_power(ehci, 0);
+ 
+ 	return retval;
+ }
+diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c
+index 6081e1ed3ac9..0c90a24fa989 100644
+--- a/drivers/usb/host/ehci-sh.c
++++ b/drivers/usb/host/ehci-sh.c
+@@ -21,17 +21,10 @@ struct ehci_sh_priv {
+ static int ehci_sh_reset(struct usb_hcd *hcd)
+ {
+ 	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
+-	int ret;
+ 
+ 	ehci->caps = hcd->regs;
+ 
+-	ret = ehci_setup(hcd);
+-	if (unlikely(ret))
+-		return ret;
+-
+-	ehci_port_power(ehci, 0);
+-
+-	return ret;
++	return ehci_setup(hcd);
+ }
+ 
+ static const struct hc_driver ehci_sh_hc_driver = {
+diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c
+index c718a065e154..719ca48a471a 100644
+--- a/drivers/usb/host/ehci-spear.c
++++ b/drivers/usb/host/ehci-spear.c
+@@ -37,18 +37,11 @@ static void spear_stop_ehci(struct spear_ehci *ehci)
+ static int ehci_spear_setup(struct usb_hcd *hcd)
+ {
+ 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+-	int retval = 0;
+ 
+ 	/* registers start at offset 0x0 */
+ 	ehci->caps = hcd->regs;
+ 
+-	retval = ehci_setup(hcd);
+-	if (retval)
+-		return retval;
+-
+-	ehci_port_power(ehci, 0);
+-
+-	return retval;
++	return ehci_setup(hcd);
+ }
+ 
+ static const struct hc_driver ehci_spear_hc_driver = {
+diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
+index 2de089001ae9..94ee3212094e 100644
+--- a/drivers/usb/host/ehci-tegra.c
++++ b/drivers/usb/host/ehci-tegra.c
+@@ -280,7 +280,6 @@ static void tegra_ehci_shutdown(struct usb_hcd *hcd)
+ static int tegra_ehci_setup(struct usb_hcd *hcd)
+ {
+ 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+-	int retval;
+ 
+ 	/* EHCI registers start at offset 0x100 */
+ 	ehci->caps = hcd->regs + 0x100;
+@@ -288,12 +287,7 @@ static int tegra_ehci_setup(struct usb_hcd *hcd)
+ 	/* switch to host mode */
+ 	hcd->has_tt = 1;
+ 
+-	retval = ehci_setup(hcd);
+-	if (retval)
+-		return retval;
+-
+-	ehci_port_power(ehci, 1);
+-	return retval;
++	return ehci_setup(hcd);
+ }
+ 
+ struct dma_aligned_buffer {
+diff --git a/include/linux/usb/ehci_pdriver.h b/include/linux/usb/ehci_pdriver.h
+index 67ac74bde6d0..99238b096f7e 100644
+--- a/include/linux/usb/ehci_pdriver.h
++++ b/include/linux/usb/ehci_pdriver.h
+@@ -41,8 +41,6 @@ struct usb_ehci_pdata {
+ 	unsigned	has_synopsys_hc_bug:1;
+ 	unsigned	big_endian_desc:1;
+ 	unsigned	big_endian_mmio:1;
+-	unsigned	port_power_on:1;
+-	unsigned	port_power_off:1;
+ 	unsigned	no_io_watchdog:1;
+ 
+ 	/* Turn on all power and clocks */

commit 4968f951913997adc8c68c4e986e8168ee1d2998
+Author: Alan Stern 
+Date:   Wed Oct 31 13:12:11 2012 -0400
+
+    USB: EHCI: remove unused Link Power Management code
+    
+    This patch (as1622) removes the USB-2.1 Link Power Management code
+    from the ehci-hcd driver.  This code was never integrated with
+    usbcore, it is full of bugs, and it was not getting used by anybody.
+    
+    However, the debugging code for dumping the LPM-related fields in the
+    EHCI registers is left in place.  In theory it might be useful to see
+    these values, even though we don't use them.
+    
+    This essentially amounts to a partial revert of commit
+    aa4d8342988d0c1a79ff19b2ede1e81dfbb16ea5 (USB: EHCI: EHCI 1.1
+    addendum: preparation) and an almost full revert of commit
+    48f24970144479c29b8cee6d2e1dbedf6dcf9cfb (USB: EHCI: EHCI 1.1
+    addendum: Basic LPM feature support) plus its follow-ons.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
+index dfd3bf3aa4de..70b496dc18a0 100644
+--- a/drivers/usb/host/ehci-dbg.c
++++ b/drivers/usb/host/ehci-dbg.c
+@@ -337,11 +337,6 @@ static int debug_async_open(struct inode *, struct file *);
+ static int debug_periodic_open(struct inode *, struct file *);
+ static int debug_registers_open(struct inode *, struct file *);
+ static int debug_async_open(struct inode *, struct file *);
+-static ssize_t debug_lpm_read(struct file *file, char __user *user_buf,
+-				   size_t count, loff_t *ppos);
+-static ssize_t debug_lpm_write(struct file *file, const char __user *buffer,
+-			      size_t count, loff_t *ppos);
+-static int debug_lpm_close(struct inode *inode, struct file *file);
+ 
+ static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*);
+ static int debug_close(struct inode *, struct file *);
+@@ -367,14 +362,6 @@ static const struct file_operations debug_registers_fops = {
+ 	.release	= debug_close,
+ 	.llseek		= default_llseek,
+ };
+-static const struct file_operations debug_lpm_fops = {
+-	.owner		= THIS_MODULE,
+-	.open		= simple_open,
+-	.read		= debug_lpm_read,
+-	.write		= debug_lpm_write,
+-	.release	= debug_lpm_close,
+-	.llseek		= noop_llseek,
+-};
+ 
+ static struct dentry *ehci_debug_root;
+ 
+@@ -956,86 +943,6 @@ static int debug_registers_open(struct inode *inode, struct file *file)
+ 	return file->private_data ? 0 : -ENOMEM;
+ }
+ 
+-static int debug_lpm_close(struct inode *inode, struct file *file)
+-{
+-	return 0;
+-}
+-
+-static ssize_t debug_lpm_read(struct file *file, char __user *user_buf,
+-				   size_t count, loff_t *ppos)
+-{
+-	/* TODO: show lpm stats */
+-	return 0;
+-}
+-
+-static ssize_t debug_lpm_write(struct file *file, const char __user *user_buf,
+-			      size_t count, loff_t *ppos)
+-{
+-	struct usb_hcd		*hcd;
+-	struct ehci_hcd		*ehci;
+-	char buf[50];
+-	size_t len;
+-	u32 temp;
+-	unsigned long port;
+-	u32 __iomem	*portsc ;
+-	u32 params;
+-
+-	hcd = bus_to_hcd(file->private_data);
+-	ehci = hcd_to_ehci(hcd);
+-
+-	len = min(count, sizeof(buf) - 1);
+-	if (copy_from_user(buf, user_buf, len))
+-		return -EFAULT;
+-	buf[len] = '\0';
+-	if (len > 0 && buf[len - 1] == '\n')
+-		buf[len - 1] = '\0';
+-
+-	if (strncmp(buf, "enable", 5) == 0) {
+-		if (strict_strtoul(buf + 7, 10, &port))
+-			return -EINVAL;
+-		params = ehci_readl(ehci, &ehci->caps->hcs_params);
+-		if (port > HCS_N_PORTS(params)) {
+-			ehci_dbg(ehci, "ERR: LPM on bad port %lu\n", port);
+-			return -ENODEV;
+-		}
+-		portsc = &ehci->regs->port_status[port-1];
+-		temp = ehci_readl(ehci, portsc);
+-		if (!(temp & PORT_DEV_ADDR)) {
+-			ehci_dbg(ehci, "LPM: no device attached\n");
+-			return -ENODEV;
+-		}
+-		temp |= PORT_LPM;
+-		ehci_writel(ehci, temp, portsc);
+-		printk(KERN_INFO "force enable LPM for port %lu\n", port);
+-	} else if (strncmp(buf, "hird=", 5) == 0) {
+-		unsigned long hird;
+-		if (strict_strtoul(buf + 5, 16, &hird))
+-			return -EINVAL;
+-		printk(KERN_INFO "setting hird %s %lu\n", buf + 6, hird);
+-		ehci->command = (ehci->command & ~CMD_HIRD) | (hird << 24);
+-		ehci_writel(ehci, ehci->command, &ehci->regs->command);
+-	} else if (strncmp(buf, "disable", 7) == 0) {
+-		if (strict_strtoul(buf + 8, 10, &port))
+-			return -EINVAL;
+-		params = ehci_readl(ehci, &ehci->caps->hcs_params);
+-		if (port > HCS_N_PORTS(params)) {
+-			ehci_dbg(ehci, "ERR: LPM off bad port %lu\n", port);
+-			return -ENODEV;
+-		}
+-		portsc = &ehci->regs->port_status[port-1];
+-		temp = ehci_readl(ehci, portsc);
+-		if (!(temp & PORT_DEV_ADDR)) {
+-			ehci_dbg(ehci, "ERR: no device attached\n");
+-			return -ENODEV;
+-		}
+-		temp &= ~PORT_LPM;
+-		ehci_writel(ehci, temp, portsc);
+-		printk(KERN_INFO "disabled LPM for port %lu\n", port);
+-	} else
+-		return -EOPNOTSUPP;
+-	return count;
+-}
+-
+ static inline void create_debug_files (struct ehci_hcd *ehci)
+ {
+ 	struct usb_bus *bus = &ehci_to_hcd(ehci)->self;
+@@ -1056,10 +963,6 @@ static inline void create_debug_files (struct ehci_hcd *ehci)
+ 						    &debug_registers_fops))
+ 		goto file_error;
+ 
+-	if (!debugfs_create_file("lpm", S_IRUGO|S_IWUSR, ehci->debug_dir, bus,
+-						    &debug_lpm_fops))
+-		goto file_error;
+-
+ 	return;
+ 
+ file_error:
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 9c2afb516fe5..68dd1c99b1f5 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -39,7 +39,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ 
+ #include 
+ #include 
+@@ -108,11 +107,6 @@ static bool ignore_oc = 0;
+ module_param (ignore_oc, bool, S_IRUGO);
+ MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications");
+ 
+-/* for link power management(LPM) feature */
+-static unsigned int hird;
+-module_param(hird, int, S_IRUGO);
+-MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us");
+-
+ #define	INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -318,7 +312,6 @@ static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh);
+ 
+ #include "ehci-timer.c"
+ #include "ehci-hub.c"
+-#include "ehci-lpm.c"
+ #include "ehci-mem.c"
+ #include "ehci-q.c"
+ #include "ehci-sched.c"
+@@ -580,17 +573,6 @@ static int ehci_init(struct usb_hcd *hcd)
+ 		temp &= ~(3 << 2);
+ 		temp |= (EHCI_TUNE_FLS << 2);
+ 	}
+-	if (HCC_LPM(hcc_params)) {
+-		/* support link power management EHCI 1.1 addendum */
+-		ehci_dbg(ehci, "support lpm\n");
+-		ehci->has_lpm = 1;
+-		if (hird > 0xf) {
+-			ehci_dbg(ehci, "hird %d invalid, use default 0",
+-			hird);
+-			hird = 0;
+-		}
+-		temp |= hird << 24;
+-	}
+ 	ehci->command = temp;
+ 
+ 	/* Accept arbitrarily long scatter-gather lists */
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index a7ec827ca2ca..a2c56cdd2c3a 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -777,11 +777,6 @@ static int ehci_hub_control (
+ 						status_reg);
+ 			break;
+ 		case USB_PORT_FEAT_C_CONNECTION:
+-			if (ehci->has_lpm) {
+-				/* clear PORTSC bits on disconnect */
+-				temp &= ~PORT_LPM;
+-				temp &= ~PORT_DEV_ADDR;
+-			}
+ 			ehci_writel(ehci, temp | PORT_CSC, status_reg);
+ 			break;
+ 		case USB_PORT_FEAT_C_OVER_CURRENT:
+diff --git a/drivers/usb/host/ehci-lpm.c b/drivers/usb/host/ehci-lpm.c
+deleted file mode 100644
+index 6b092c1dff64..000000000000
+--- a/drivers/usb/host/ehci-lpm.c
++++ /dev/null
+@@ -1,101 +0,0 @@
+-/* ehci-lpm.c EHCI HCD LPM support code
+- * Copyright (c) 2008 - 2010,  Intel Corporation.
+- * Author: Jacob Pan 
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-*/
+-
+-/* this file is part of ehci-hcd.c */
+-
+-static int ehci_lpm_set_da(struct ehci_hcd *ehci, int dev_addr, int port_num)
+-{
+-	u32 __iomem portsc;
+-
+-	ehci_dbg(ehci, "set dev address %d for port %d\n", dev_addr, port_num);
+-	if (port_num > HCS_N_PORTS(ehci->hcs_params)) {
+-		ehci_dbg(ehci, "invalid port number %d\n", port_num);
+-		return -ENODEV;
+-	}
+-	portsc = ehci_readl(ehci, &ehci->regs->port_status[port_num-1]);
+-	portsc &= ~PORT_DEV_ADDR;
+-	portsc |= dev_addr<<25;
+-	ehci_writel(ehci, portsc, &ehci->regs->port_status[port_num-1]);
+-	return 0;
+-}
+-
+-/*
+- * this function is used to check if the device support LPM
+- * if yes, mark the PORTSC register with PORT_LPM bit
+- */
+-static int ehci_lpm_check(struct ehci_hcd *ehci, int port)
+-{
+-	u32 __iomem	*portsc ;
+-	u32 val32;
+-	int retval;
+-
+-	portsc = &ehci->regs->port_status[port-1];
+-	val32 = ehci_readl(ehci, portsc);
+-	if (!(val32 & PORT_DEV_ADDR)) {
+-		ehci_dbg(ehci, "LPM: no device attached\n");
+-		return -ENODEV;
+-	}
+-	val32 |= PORT_LPM;
+-	ehci_writel(ehci, val32, portsc);
+-	msleep(5);
+-	val32 |= PORT_SUSPEND;
+-	ehci_dbg(ehci, "Sending LPM 0x%08x to port %d\n", val32, port);
+-	ehci_writel(ehci, val32, portsc);
+-	/* wait for ACK */
+-	msleep(10);
+-	retval = handshake(ehci, &ehci->regs->port_status[port-1], PORT_SSTS,
+-			PORTSC_SUSPEND_STS_ACK, 125);
+-	dbg_port(ehci, "LPM", port, val32);
+-	if (retval != -ETIMEDOUT) {
+-		ehci_dbg(ehci, "LPM: device ACK for LPM\n");
+-		val32 |= PORT_LPM;
+-		/*
+-		 * now device should be in L1 sleep, let's wake up the device
+-		 * so that we can complete enumeration.
+-		 */
+-		ehci_writel(ehci, val32, portsc);
+-		msleep(10);
+-		val32 |= PORT_RESUME;
+-		ehci_writel(ehci, val32, portsc);
+-	} else {
+-		ehci_dbg(ehci, "LPM: device does not ACK, disable LPM %d\n",
+-			retval);
+-		val32 &= ~PORT_LPM;
+-		retval = -ETIMEDOUT;
+-		ehci_writel(ehci, val32, portsc);
+-	}
+-
+-	return retval;
+-}
+-
+-static int __maybe_unused ehci_update_device(struct usb_hcd *hcd,
+-		struct usb_device *udev)
+-{
+-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+-	int rc = 0;
+-
+-	if (!udev->parent) /* udev is root hub itself, impossible */
+-		rc = -1;
+-	/* we only support lpm device connected to root hub yet */
+-	if (ehci->has_lpm && !udev->parent->parent) {
+-		rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum);
+-		if (!rc)
+-			rc = ehci_lpm_check(ehci, udev->portnum);
+-	}
+-	return rc;
+-}
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index 7880ba621f89..e17330ae0aee 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -202,11 +202,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 		break;
+ 	case PCI_VENDOR_ID_INTEL:
+ 		ehci->need_io_watchdog = 0;
+-		if (pdev->device == 0x0806 || pdev->device == 0x0811
+-				|| pdev->device == 0x0829) {
+-			ehci_info(ehci, "disable lpm for langwell/penwell\n");
+-			ehci->has_lpm = 0;
+-		}
+ 		break;
+ 	case PCI_VENDOR_ID_NVIDIA:
+ 		switch (pdev->device) {
+@@ -216,8 +211,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 		 * devices with PPCD enabled.
+ 		 */
+ 		case 0x0d9d:
+-			ehci_info(ehci, "disable lpm/ppcd for nvidia mcp89");
+-			ehci->has_lpm = 0;
++			ehci_info(ehci, "disable ppcd for nvidia mcp89\n");
+ 			ehci->has_ppcd = 0;
+ 			ehci->command &= ~CMD_PPCEE;
+ 			break;
+@@ -425,11 +419,6 @@ static const struct hc_driver ehci_pci_hc_driver = {
+ 	.relinquish_port =	ehci_relinquish_port,
+ 	.port_handed_over =	ehci_port_handed_over,
+ 
+-	/*
+-	 * call back when device connected and addressed
+-	 */
+-	.update_device =	ehci_update_device,
+-
+ 	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
+ };
+ 
+diff --git a/drivers/usb/host/ehci-vt8500.c b/drivers/usb/host/ehci-vt8500.c
+index c6fe0bb619cb..11695d5b9d86 100644
+--- a/drivers/usb/host/ehci-vt8500.c
++++ b/drivers/usb/host/ehci-vt8500.c
+@@ -61,11 +61,6 @@ static const struct hc_driver vt8500_ehci_hc_driver = {
+ 	.relinquish_port	= ehci_relinquish_port,
+ 	.port_handed_over	= ehci_port_handed_over,
+ 
+-	/*
+-	 * call back when device connected and addressed
+-	 */
+-	.update_device =	ehci_update_device,
+-
+ 	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
+ };
+ 
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index ec948c3b1cea..2262dcdaa3c1 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -206,7 +206,6 @@ struct ehci_hcd {			/* one per controller */
+ 	#define OHCI_HCCTRL_LEN         0x4
+ 	__hc32			*ohci_hcctrl_reg;
+ 	unsigned		has_hostpc:1;
+-	unsigned		has_lpm:1;  /* support link power management */
+ 	unsigned		has_ppcd:1; /* support per-port change bits */
+ 	u8			sbrn;		/* packed release number */
+ 

commit 571e41214e988bc38c99d804e6d8e1ea1d016342
+Author: Alan Stern 
+Date:   Wed Oct 31 13:09:07 2012 -0400
+
+    USB: remove iteration limit in hub_tt_work()
+    
+    This patch (as1621) removes the limit on the number of loops allowed
+    in hub_tt_work().  The value is arbitrary, and it's silly to have a
+    limit in the first place -- anything beyond the limit would not get
+    handled.
+    
+    Besides, it's most unlikely that we'll ever need to clear more than a
+    couple of TT buffers at any time.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index fbaf3c3dbf07..90accdefdc7d 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -741,7 +741,6 @@ static void hub_tt_work(struct work_struct *work)
+ 	struct usb_hub		*hub =
+ 		container_of(work, struct usb_hub, tt.clear_work);
+ 	unsigned long		flags;
+-	int			limit = 100;
+ 
+ 	spin_lock_irqsave (&hub->tt.lock, flags);
+ 	while (!list_empty(&hub->tt.clear_list)) {
+@@ -751,9 +750,6 @@ static void hub_tt_work(struct work_struct *work)
+ 		const struct hc_driver	*drv;
+ 		int			status;
+ 
+-		if (!hub->quiescing && --limit < 0)
+-			break;
+-
+ 		next = hub->tt.clear_list.next;
+ 		clear = list_entry (next, struct usb_tt_clear, clear_list);
+ 		list_del (&clear->clear_list);

commit bfd1e910139be73fb0783a0b3171fc79e6afa031
+Author: Alan Stern 
+Date:   Fri Oct 19 11:03:39 2012 -0400
+
+    USB: speed up usb_bus_resume()
+    
+    This patch (as1620) speeds up USB root-hub resumes in the common case
+    where every enabled port has its suspend feature set (which currently
+    will be true for every runtime resume of the root hub).  If all the
+    enabled ports are suspended then resuming the root hub won't resume
+    any of the downstream devices.  In this case there's no need for a
+    Resume Recovery delay, because that delay is meant to give devices a
+    chance to get ready for active use.
+    
+    To keep track of the port suspend features, the patch adds a
+    "port_is_suspended" flag to struct usb_device.  This has to be tracked
+    separately from the device's state; it's entirely possible for a USB-2
+    device to be suspended while the suspend feature on its parent port is
+    clear.  The reason is that devices will go into suspend whenever their
+    parent hub does.
+    
+    Signed-off-by: Alan Stern 
+    Reviewed-by: Peter Chen 
+    Tested-by: Peter Chen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 1e741bca0265..eaa14514e173 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -2039,8 +2039,9 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
+ 	status = hcd->driver->bus_resume(hcd);
+ 	clear_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags);
+ 	if (status == 0) {
+-		/* TRSMRCY = 10 msec */
+-		msleep(10);
++		struct usb_device *udev;
++		int port1;
++
+ 		spin_lock_irq(&hcd_root_hub_lock);
+ 		if (!HCD_DEAD(hcd)) {
+ 			usb_set_device_state(rhdev, rhdev->actconfig
+@@ -2050,6 +2051,20 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
+ 			hcd->state = HC_STATE_RUNNING;
+ 		}
+ 		spin_unlock_irq(&hcd_root_hub_lock);
++
++		/*
++		 * Check whether any of the enabled ports on the root hub are
++		 * unsuspended.  If they are then a TRSMRCY delay is needed
++		 * (this is what the USB-2 spec calls a "global resume").
++		 * Otherwise we can skip the delay.
++		 */
++		usb_hub_for_each_child(rhdev, port1, udev) {
++			if (udev->state != USB_STATE_NOTATTACHED &&
++					!udev->port_is_suspended) {
++				usleep_range(10000, 11000);	/* TRSMRCY */
++				break;
++			}
++		}
+ 	} else {
+ 		hcd->state = old_state;
+ 		dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 64854d76f529..e729e94cb751 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2876,6 +2876,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ 				(PMSG_IS_AUTO(msg) ? "auto-" : ""),
+ 				udev->do_remote_wakeup);
+ 		usb_set_device_state(udev, USB_STATE_SUSPENDED);
++		udev->port_is_suspended = 1;
+ 		msleep(10);
+ 	}
+ 	usb_mark_last_busy(hub->hdev);
+@@ -3040,6 +3041,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
+ 
+  SuspendCleared:
+ 	if (status == 0) {
++		udev->port_is_suspended = 0;
+ 		if (hub_is_superspeed(hub->hdev)) {
+ 			if (portchange & USB_PORT_STAT_C_LINK_STATE)
+ 				clear_port_feature(hub->hdev, port1,
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 5df7c87b277f..f51f9981de1e 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -482,6 +482,7 @@ struct usb3_lpm_parameters {
+  * @connect_time: time device was first connected
+  * @do_remote_wakeup:  remote wakeup should be enabled
+  * @reset_resume: needs reset instead of resume
++ * @port_is_suspended: the upstream port is suspended (L2 or U3)
+  * @wusb_dev: if this is a Wireless USB device, link to the WUSB
+  *	specific data for the device.
+  * @slot_id: Slot ID assigned by xHCI
+@@ -560,6 +561,7 @@ struct usb_device {
+ 
+ 	unsigned do_remote_wakeup:1;
+ 	unsigned reset_resume:1;
++	unsigned port_is_suspended:1;
+ #endif
+ 	struct wusb_dev *wusb_dev;
+ 	int slot_id;

commit 969ddcfc95c9a1849114fb72466d2fdea70f1d48
+Author: Alan Stern 
+Date:   Fri Oct 19 11:03:02 2012 -0400
+
+    USB: hub_for_each_child should skip unconnected ports
+    
+    This patch (as1619) improves the interface to the "hub_for_each_child"
+    macro.  The name clearly suggests that the macro iterates over child
+    devices; it does not suggest that the loop will also iterate over
+    unnconnected ports.
+    
+    The patch changes the macro so that it will skip over unconnected
+    ports and iterate only the actual child devices.  The two existing
+    call sites are updated to avoid testing for a NULL child pointer,
+    which is now unnecessary.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
+index f460de31acee..cbacea933b18 100644
+--- a/drivers/usb/core/devices.c
++++ b/drivers/usb/core/devices.c
+@@ -591,16 +591,14 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,
+ 
+ 	/* Now look at all of this device's children. */
+ 	usb_hub_for_each_child(usbdev, chix, childdev) {
+-		if (childdev) {
+-			usb_lock_device(childdev);
+-			ret = usb_device_dump(buffer, nbytes, skip_bytes,
+-					      file_offset, childdev, bus,
+-					      level + 1, chix - 1, ++cnt);
+-			usb_unlock_device(childdev);
+-			if (ret == -EFAULT)
+-				return total_written;
+-			total_written += ret;
+-		}
++		usb_lock_device(childdev);
++		ret = usb_device_dump(buffer, nbytes, skip_bytes,
++				      file_offset, childdev, bus,
++				      level + 1, chix - 1, ++cnt);
++		usb_unlock_device(childdev);
++		if (ret == -EFAULT)
++			return total_written;
++		total_written += ret;
+ 	}
+ 	return total_written;
+ }
+diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
+index fcc09e5ec0ad..b3eea0ba97a9 100644
+--- a/drivers/usb/host/r8a66597-hcd.c
++++ b/drivers/usb/host/r8a66597-hcd.c
+@@ -2036,10 +2036,8 @@ static void collect_usb_address_map(struct usb_device *udev, unsigned long *map)
+ 	    udev->parent->descriptor.bDeviceClass == USB_CLASS_HUB)
+ 		map[udev->devnum/32] |= (1 << (udev->devnum % 32));
+ 
+-	usb_hub_for_each_child(udev, chix, childdev) {
+-		if (childdev)
+-			collect_usb_address_map(childdev, map);
+-	}
++	usb_hub_for_each_child(udev, chix, childdev)
++		collect_usb_address_map(childdev, map);
+ }
+ 
+ /* this function must be called with interrupt disabled */
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index f92cdf0c1457..5df7c87b277f 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -588,8 +588,9 @@ extern struct usb_device *usb_hub_find_child(struct usb_device *hdev,
+  */
+ #define usb_hub_for_each_child(hdev, port1, child) \
+ 	for (port1 = 1,	child =	usb_hub_find_child(hdev, port1); \
+-		port1 <= hdev->maxchild; \
+-		child = usb_hub_find_child(hdev, ++port1))
++			port1 <= hdev->maxchild; \
++			child = usb_hub_find_child(hdev, ++port1)) \
++		if (!child) continue; else
+ 
+ /* USB device locking */
+ #define usb_lock_device(udev)		device_lock(&(udev)->dev)

commit d39dbc8918be0e6bb850592e334203c9114c0e77
+Author: Alan Stern 
+Date:   Wed Oct 10 15:07:46 2012 -0400
+
+    USB: EHCI: move ehci_update_device() to ehci-lpm.c
+    
+    In preparation for splitting the ehci-hcd driver into a core library
+    and separate platform-specific driver modules, this patch (as1618)
+    moves ehci_update_device() from a couple of platform-specific source
+    files into ehci-lpm.c.  This is where it should have been all along,
+    since all it does is call a couple of other functions that are already
+    in ehci-lpm.c.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Felipe Balbi 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-lpm.c b/drivers/usb/host/ehci-lpm.c
+index 2111627a19de..6b092c1dff64 100644
+--- a/drivers/usb/host/ehci-lpm.c
++++ b/drivers/usb/host/ehci-lpm.c
+@@ -17,8 +17,8 @@
+ */
+ 
+ /* this file is part of ehci-hcd.c */
+-static int __maybe_unused ehci_lpm_set_da(struct ehci_hcd *ehci,
+-	int dev_addr, int port_num)
++
++static int ehci_lpm_set_da(struct ehci_hcd *ehci, int dev_addr, int port_num)
+ {
+ 	u32 __iomem portsc;
+ 
+@@ -38,7 +38,7 @@ static int __maybe_unused ehci_lpm_set_da(struct ehci_hcd *ehci,
+  * this function is used to check if the device support LPM
+  * if yes, mark the PORTSC register with PORT_LPM bit
+  */
+-static int __maybe_unused ehci_lpm_check(struct ehci_hcd *ehci, int port)
++static int ehci_lpm_check(struct ehci_hcd *ehci, int port)
+ {
+ 	u32 __iomem	*portsc ;
+ 	u32 val32;
+@@ -82,3 +82,20 @@ static int __maybe_unused ehci_lpm_check(struct ehci_hcd *ehci, int port)
+ 
+ 	return retval;
+ }
++
++static int __maybe_unused ehci_update_device(struct usb_hcd *hcd,
++		struct usb_device *udev)
++{
++	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
++	int rc = 0;
++
++	if (!udev->parent) /* udev is root hub itself, impossible */
++		rc = -1;
++	/* we only support lpm device connected to root hub yet */
++	if (ehci->has_lpm && !udev->parent->parent) {
++		rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum);
++		if (!rc)
++			rc = ehci_lpm_check(ehci, udev->portnum);
++	}
++	return rc;
++}
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index d1407f8d42b1..7880ba621f89 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -379,22 +379,6 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)
+ }
+ #endif
+ 
+-static int ehci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
+-{
+-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+-	int rc = 0;
+-
+-	if (!udev->parent) /* udev is root hub itself, impossible */
+-		rc = -1;
+-	/* we only support lpm device connected to root hub yet */
+-	if (ehci->has_lpm && !udev->parent->parent) {
+-		rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum);
+-		if (!rc)
+-			rc = ehci_lpm_check(ehci, udev->portnum);
+-	}
+-	return rc;
+-}
+-
+ static const struct hc_driver ehci_pci_hc_driver = {
+ 	.description =		hcd_name,
+ 	.product_desc =		"EHCI Host Controller",
+diff --git a/drivers/usb/host/ehci-vt8500.c b/drivers/usb/host/ehci-vt8500.c
+index d3c9a3e397b9..c6fe0bb619cb 100644
+--- a/drivers/usb/host/ehci-vt8500.c
++++ b/drivers/usb/host/ehci-vt8500.c
+@@ -19,22 +19,6 @@
+ #include 
+ #include 
+ 
+-static int ehci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
+-{
+-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+-	int rc = 0;
+-
+-	if (!udev->parent) /* udev is root hub itself, impossible */
+-		rc = -1;
+-	/* we only support lpm device connected to root hub yet */
+-	if (ehci->has_lpm && !udev->parent->parent) {
+-		rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum);
+-		if (!rc)
+-			rc = ehci_lpm_check(ehci, udev->portnum);
+-	}
+-	return rc;
+-}
+-
+ static const struct hc_driver vt8500_ehci_hc_driver = {
+ 	.description		= hcd_name,
+ 	.product_desc		= "VT8500 EHCI",

commit acc08503406f97ce6582c92fd8c8139f1e871a96
+Author: Alan Stern 
+Date:   Wed Oct 10 15:07:39 2012 -0400
+
+    USB: EHCI: make ehci_read_frame_index platform independent
+    
+    In preparation for splitting the ehci-hcd driver into a core library
+    and separate platform-specific driver modules, this patch (as1617)
+    changes the way ehci_read_frame_index() is handled.
+    
+    Since the same core library will have to work with both PCI and
+    non-PCI platforms, the quirk handler routine will be compiled
+    unconditionally.  The decision about whether to call it or simply to
+    read the frame index register is made at run time, based on whether
+    the frame_index_bug quirk flag is set.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Felipe Balbi 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 28fb5ddaf786..9c2afb516fe5 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -118,9 +118,34 @@ MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us");
+ /*-------------------------------------------------------------------------*/
+ 
+ #include "ehci.h"
+-#include "ehci-dbg.c"
+ #include "pci-quirks.h"
+ 
++/*
++ * The MosChip MCS9990 controller updates its microframe counter
++ * a little before the frame counter, and occasionally we will read
++ * the invalid intermediate value.  Avoid problems by checking the
++ * microframe number (the low-order 3 bits); if they are 0 then
++ * re-read the register to get the correct value.
++ */
++static unsigned ehci_moschip_read_frame_index(struct ehci_hcd *ehci)
++{
++	unsigned uf;
++
++	uf = ehci_readl(ehci, &ehci->regs->frame_index);
++	if (unlikely((uf & 7) == 0))
++		uf = ehci_readl(ehci, &ehci->regs->frame_index);
++	return uf;
++}
++
++static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
++{
++	if (ehci->frame_index_bug)
++		return ehci_moschip_read_frame_index(ehci);
++	return ehci_readl(ehci, &ehci->regs->frame_index);
++}
++
++#include "ehci-dbg.c"
++
+ /*-------------------------------------------------------------------------*/
+ 
+ /*
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index b538a4d62d5e..2e14714b359f 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -36,29 +36,6 @@
+ 
+ static int ehci_get_frame (struct usb_hcd *hcd);
+ 
+-#ifdef CONFIG_PCI
+-
+-static unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
+-{
+-	unsigned uf;
+-
+-	/*
+-	 * The MosChip MCS9990 controller updates its microframe counter
+-	 * a little before the frame counter, and occasionally we will read
+-	 * the invalid intermediate value.  Avoid problems by checking the
+-	 * microframe number (the low-order 3 bits); if they are 0 then
+-	 * re-read the register to get the correct value.
+-	 */
+-	uf = ehci_readl(ehci, &ehci->regs->frame_index);
+-	if (unlikely(ehci->frame_index_bug && ((uf & 7) == 0)))
+-		uf = ehci_readl(ehci, &ehci->regs->frame_index);
+-	return uf;
+-}
+-
+-#endif
+-
+-/*-------------------------------------------------------------------------*/
+-
+ /*
+  * periodic_next_shadow - return "next" pointer on shadow list
+  * @periodic: host pointer to qh/itd/sitd
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 9b8cbb4b3e2c..ec948c3b1cea 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -776,22 +776,6 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x)
+ 	static inline void ehci_vdbg(struct ehci_hcd *ehci, ...) {}
+ #endif
+ 
+-#ifdef CONFIG_PCI
+-
+-/* For working around the MosChip frame-index-register bug */
+-static unsigned ehci_read_frame_index(struct ehci_hcd *ehci);
+-
+-#else
+-
+-static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
+-{
+-	return ehci_readl(ehci, &ehci->regs->frame_index);
+-}
+-
+-#endif
+-
+-/*-------------------------------------------------------------------------*/
+-
+ #ifndef DEBUG
+ #define STUB_DEBUG_FILES
+ #endif	/* DEBUG */

commit d6064aca824b81fbb788fd230c88976d84b651b1
+Author: Alan Stern 
+Date:   Wed Oct 10 15:07:30 2012 -0400
+
+    USB: EHCI: move logging macros to ehci.h
+    
+    In preparation for splitting the ehci-hcd driver into a core library
+    and separate platform-specific driver modules, this patch (as1616)
+    moves the console logging macros from ehci-dbg.c to ehci.h, where they
+    will be available to the platform drivers.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Felipe Balbi 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
+index 1599806e3d47..dfd3bf3aa4de 100644
+--- a/drivers/usb/host/ehci-dbg.c
++++ b/drivers/usb/host/ehci-dbg.c
+@@ -18,21 +18,6 @@
+ 
+ /* this file is part of ehci-hcd.c */
+ 
+-#define ehci_dbg(ehci, fmt, args...) \
+-	dev_dbg (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
+-#define ehci_err(ehci, fmt, args...) \
+-	dev_err (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
+-#define ehci_info(ehci, fmt, args...) \
+-	dev_info (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
+-#define ehci_warn(ehci, fmt, args...) \
+-	dev_warn (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
+-
+-#ifdef VERBOSE_DEBUG
+-#	define ehci_vdbg ehci_dbg
+-#else
+-	static inline void ehci_vdbg(struct ehci_hcd *ehci, ...) {}
+-#endif
+-
+ #ifdef	DEBUG
+ 
+ /* check the values in the HCSPARAMS register
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 4ddf7c51616b..9b8cbb4b3e2c 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -761,6 +761,21 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++#define ehci_dbg(ehci, fmt, args...) \
++	dev_dbg(ehci_to_hcd(ehci)->self.controller , fmt , ## args)
++#define ehci_err(ehci, fmt, args...) \
++	dev_err(ehci_to_hcd(ehci)->self.controller , fmt , ## args)
++#define ehci_info(ehci, fmt, args...) \
++	dev_info(ehci_to_hcd(ehci)->self.controller , fmt , ## args)
++#define ehci_warn(ehci, fmt, args...) \
++	dev_warn(ehci_to_hcd(ehci)->self.controller , fmt , ## args)
++
++#ifdef VERBOSE_DEBUG
++#	define ehci_vdbg ehci_dbg
++#else
++	static inline void ehci_vdbg(struct ehci_hcd *ehci, ...) {}
++#endif
++
+ #ifdef CONFIG_PCI
+ 
+ /* For working around the MosChip frame-index-register bug */

commit 6a41b4d3fe8cd4cc95181516fc6fba7b1747a27c
+Author: Alan Stern 
+Date:   Mon Oct 1 10:32:15 2012 -0400
+
+    OHCI: implement new semantics for URB_ISO_ASAP
+    
+    This patch (as1614) updates the isochronous scheduling in ohci-hcd to
+    match the new semantics for URB_ISO_ASAP.  Testing revealed a hardware
+    bug in the way my OHCI controller handles expired isochronous TDs;
+    consequently the patch tries hard to avoid creating them (unlike the
+    ehci-hcd and uhci-hcd drivers).
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index 4a1d64d92338..cfc1da30667c 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -231,13 +231,41 @@ static int ohci_urb_enqueue (
+ 			frame &= ~(ed->interval - 1);
+ 			frame |= ed->branch;
+ 			urb->start_frame = frame;
++		}
++	} else if (ed->type == PIPE_ISOCHRONOUS) {
++		u16	next = ohci_frame_no(ohci) + 2;
++		u16	frame = ed->last_iso + ed->interval;
++
++		/* Behind the scheduling threshold? */
++		if (unlikely(tick_before(frame, next))) {
+ 
+-			/* yes, only URB_ISO_ASAP is supported, and
+-			 * urb->start_frame is never used as input.
++			/* USB_ISO_ASAP: Round up to the first available slot */
++			if (urb->transfer_flags & URB_ISO_ASAP)
++				frame += (next - frame + ed->interval - 1) &
++						-ed->interval;
++
++			/*
++			 * Not ASAP: Use the next slot in the stream.  If
++			 * the entire URB falls before the threshold, fail.
+ 			 */
++			else if (tick_before(frame + ed->interval *
++					(urb->number_of_packets - 1), next)) {
++				retval = -EXDEV;
++				usb_hcd_unlink_urb_from_ep(hcd, urb);
++				goto fail;
++			}
++
++			/*
++			 * Some OHCI hardware doesn't handle late TDs
++			 * correctly.  After retiring them it proceeds to
++			 * the next ED instead of the next TD.  Therefore
++			 * we have to omit the late TDs entirely.
++			 */
++			urb_priv->td_cnt = DIV_ROUND_UP(next - frame,
++					ed->interval);
+ 		}
+-	} else if (ed->type == PIPE_ISOCHRONOUS)
+-		urb->start_frame = ed->last_iso + ed->interval;
++		urb->start_frame = frame;
++	}
+ 
+ 	/* fill the TDs and link them to the ed; and
+ 	 * enable that part of the schedule, if needed
+diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
+index c5a1ea9145fa..177a213790d4 100644
+--- a/drivers/usb/host/ohci-q.c
++++ b/drivers/usb/host/ohci-q.c
+@@ -596,7 +596,6 @@ static void td_submit_urb (
+ 		urb_priv->ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_C);
+ 	}
+ 
+-	urb_priv->td_cnt = 0;
+ 	list_add (&urb_priv->pending, &ohci->pending);
+ 
+ 	if (data_len)
+@@ -672,7 +671,8 @@ static void td_submit_urb (
+ 	 * we could often reduce the number of TDs here.
+ 	 */
+ 	case PIPE_ISOCHRONOUS:
+-		for (cnt = 0; cnt < urb->number_of_packets; cnt++) {
++		for (cnt = urb_priv->td_cnt; cnt < urb->number_of_packets;
++				cnt++) {
+ 			int	frame = urb->start_frame;
+ 
+ 			// FIXME scheduling should handle frame counter

commit c44b225077bb1fb25ed5cd5c4f226897b91bedd4
+Author: Alan Stern 
+Date:   Mon Oct 1 10:32:09 2012 -0400
+
+    UHCI: implement new semantics for URB_ISO_ASAP
+    
+    This patch (as1613) updates the isochronous scheduling in uhci-hcd to
+    match the new semantics for URB_ISO_ASAP.  The amount of code
+    alteration is smaller than it looks because of a change in the
+    indentation level.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index d2c6f5ac4626..15921fd55048 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -1256,7 +1256,8 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
+ 		struct uhci_qh *qh)
+ {
+ 	struct uhci_td *td = NULL;	/* Since urb->number_of_packets > 0 */
+-	int i, frame;
++	int i;
++	unsigned frame, next;
+ 	unsigned long destination, status;
+ 	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
+ 
+@@ -1265,37 +1266,29 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
+ 			urb->number_of_packets >= UHCI_NUMFRAMES)
+ 		return -EFBIG;
+ 
++	uhci_get_current_frame_number(uhci);
++
+ 	/* Check the period and figure out the starting frame number */
+ 	if (!qh->bandwidth_reserved) {
+ 		qh->period = urb->interval;
+-		if (urb->transfer_flags & URB_ISO_ASAP) {
+-			qh->phase = -1;		/* Find the best phase */
+-			i = uhci_check_bandwidth(uhci, qh);
+-			if (i)
+-				return i;
+-
+-			/* Allow a little time to allocate the TDs */
+-			uhci_get_current_frame_number(uhci);
+-			frame = uhci->frame_number + 10;
+-
+-			/* Move forward to the first frame having the
+-			 * correct phase */
+-			urb->start_frame = frame + ((qh->phase - frame) &
+-					(qh->period - 1));
+-		} else {
+-			i = urb->start_frame - uhci->last_iso_frame;
+-			if (i <= 0 || i >= UHCI_NUMFRAMES)
+-				return -EINVAL;
+-			qh->phase = urb->start_frame & (qh->period - 1);
+-			i = uhci_check_bandwidth(uhci, qh);
+-			if (i)
+-				return i;
+-		}
++		qh->phase = -1;		/* Find the best phase */
++		i = uhci_check_bandwidth(uhci, qh);
++		if (i)
++			return i;
++
++		/* Allow a little time to allocate the TDs */
++		next = uhci->frame_number + 10;
++		frame = qh->phase;
++
++		/* Round up to the first available slot */
++		frame += (next - frame + qh->period - 1) & -qh->period;
+ 
+ 	} else if (qh->period != urb->interval) {
+ 		return -EINVAL;		/* Can't change the period */
+ 
+ 	} else {
++		next = uhci->frame_number + 2;
++
+ 		/* Find the next unused frame */
+ 		if (list_empty(&qh->queue)) {
+ 			frame = qh->iso_frame;
+@@ -1308,25 +1301,31 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
+ 					lurb->number_of_packets *
+ 					lurb->interval;
+ 		}
+-		if (urb->transfer_flags & URB_ISO_ASAP) {
+-			/* Skip some frames if necessary to insure
+-			 * the start frame is in the future.
++
++		/* Fell behind? */
++		if (uhci_frame_before_eq(frame, next)) {
++
++			/* USB_ISO_ASAP: Round up to the first available slot */
++			if (urb->transfer_flags & URB_ISO_ASAP)
++				frame += (next - frame + qh->period - 1) &
++						-qh->period;
++
++			/*
++			 * Not ASAP: Use the next slot in the stream.  If
++			 * the entire URB falls before the threshold, fail.
+ 			 */
+-			uhci_get_current_frame_number(uhci);
+-			if (uhci_frame_before_eq(frame, uhci->frame_number)) {
+-				frame = uhci->frame_number + 1;
+-				frame += ((qh->phase - frame) &
+-					(qh->period - 1));
+-			}
+-		}	/* Otherwise pick up where the last URB leaves off */
+-		urb->start_frame = frame;
++			else if (!uhci_frame_before_eq(next,
++					frame + (urb->number_of_packets - 1) *
++						qh->period))
++				return -EXDEV;
++		}
+ 	}
+ 
+ 	/* Make sure we won't have to go too far into the future */
+ 	if (uhci_frame_before_eq(uhci->last_iso_frame + UHCI_NUMFRAMES,
+-			urb->start_frame + urb->number_of_packets *
+-				urb->interval))
++			frame + urb->number_of_packets * urb->interval))
+ 		return -EFBIG;
++	urb->start_frame = frame;
+ 
+ 	status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
+ 	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);

commit 4005ad4390bf698e3bdae9567e79242ec0584097
+Author: Alan Stern 
+Date:   Mon Oct 1 10:32:01 2012 -0400
+
+    EHCI: implement new semantics for URB_ISO_ASAP
+    
+    This patch (as1612) updates the isochronous scheduling and processing
+    in ehci-hcd to match the new semantics for URB_ISO_ASAP.  It also adds
+    a missing "unlikely" in sitd_complete() to match the corresponding
+    statement in itd_complete(), and it increments urb->error_count in a
+    couple of places that had been overlooked.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index e08e65d8e004..b538a4d62d5e 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1386,8 +1386,8 @@ iso_stream_schedule (
+ 
+ 	/* Typical case: reuse current schedule, stream is still active.
+ 	 * Hopefully there are no gaps from the host falling behind
+-	 * (irq delays etc), but if there are we'll take the next
+-	 * slot in the schedule, implicitly assuming URB_ISO_ASAP.
++	 * (irq delays etc).  If there are, the behavior depends on
++	 * whether URB_ISO_ASAP is set.
+ 	 */
+ 	if (likely (!list_empty (&stream->td_list))) {
+ 
+@@ -1414,9 +1414,25 @@ iso_stream_schedule (
+ 			goto fail;
+ 		}
+ 
+-		/* Behind the scheduling threshold?  Assume URB_ISO_ASAP. */
+-		if (unlikely(start < next))
+-			start += (next - start + period - 1) & (- period);
++		/* Behind the scheduling threshold? */
++		if (unlikely(start < next)) {
++
++			/* USB_ISO_ASAP: Round up to the first available slot */
++			if (urb->transfer_flags & URB_ISO_ASAP)
++				start += (next - start + period - 1) & -period;
++
++			/*
++			 * Not ASAP: Use the next slot in the stream.  If
++			 * the entire URB falls before the threshold, fail.
++			 */
++			else if (start + span - period < next) {
++				ehci_dbg(ehci, "iso urb late %p (%u+%u < %u)\n",
++						urb, start + base,
++						span - period, next + base);
++				status = -EXDEV;
++				goto fail;
++			}
++		}
+ 
+ 		start += base;
+ 	}
+@@ -1699,7 +1715,7 @@ static bool itd_complete(struct ehci_hcd *ehci, struct ehci_itd *itd)
+ 			urb->actual_length += desc->actual_length;
+ 		} else {
+ 			/* URB was too late */
+-			desc->status = -EXDEV;
++			urb->error_count++;
+ 		}
+ 	}
+ 
+@@ -2072,7 +2088,7 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd)
+ 	t = hc32_to_cpup(ehci, &sitd->hw_results);
+ 
+ 	/* report transfer status */
+-	if (t & SITD_ERRS) {
++	if (unlikely(t & SITD_ERRS)) {
+ 		urb->error_count++;
+ 		if (t & SITD_STS_DBE)
+ 			desc->status = usb_pipein (urb->pipe)
+@@ -2082,6 +2098,9 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd)
+ 			desc->status = -EOVERFLOW;
+ 		else /* XACT, MMF, etc */
+ 			desc->status = -EPROTO;
++	} else if (unlikely(t & SITD_STS_ACTIVE)) {
++		/* URB was too late */
++		urb->error_count++;
+ 	} else {
+ 		desc->status = 0;
+ 		desc->actual_length = desc->length - SITD_LENGTH(t);

commit a03bede5c73a6876fa891cfe82a65460dc9f4698
+Author: Alan Stern 
+Date:   Mon Oct 1 10:31:53 2012 -0400
+
+    USB: update documentation for URB_ISO_ASAP
+    
+    This patch (as1611) updates the USB documentation and kerneldoc to
+    give a more precise meaning for the URB_ISO_ASAP flag and to explain
+    more of the details of scheduling for isochronous URBs.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/usb/error-codes.txt b/Documentation/usb/error-codes.txt
+index b3f606b81a03..8d1e2a9ebbba 100644
+--- a/Documentation/usb/error-codes.txt
++++ b/Documentation/usb/error-codes.txt
+@@ -35,9 +35,8 @@ USB-specific:
+ 		d) ISO: number_of_packets is < 0
+ 		e) various other cases
+ 
+--EAGAIN		a) specified ISO start frame too early
+-		b) (using ISO-ASAP) too much scheduled for the future
+-		   wait some time and try again.
++-EXDEV		ISO: URB_ISO_ASAP wasn't specified and all the frames
++		the URB would be scheduled in have already expired.
+ 
+ -EFBIG		Host controller driver can't schedule that many ISO frames.
+ 
+diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
+index 9d912bfdcffe..3662287e2f4f 100644
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -214,9 +214,25 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
+  * urb->interval is modified to reflect the actual transfer period used
+  * (normally some power of two units).  And for isochronous urbs,
+  * urb->start_frame is modified to reflect when the URB's transfers were
+- * scheduled to start.  Not all isochronous transfer scheduling policies
+- * will work, but most host controller drivers should easily handle ISO
+- * queues going from now until 10-200 msec into the future.
++ * scheduled to start.
++ *
++ * Not all isochronous transfer scheduling policies will work, but most
++ * host controller drivers should easily handle ISO queues going from now
++ * until 10-200 msec into the future.  Drivers should try to keep at
++ * least one or two msec of data in the queue; many controllers require
++ * that new transfers start at least 1 msec in the future when they are
++ * added.  If the driver is unable to keep up and the queue empties out,
++ * the behavior for new submissions is governed by the URB_ISO_ASAP flag.
++ * If the flag is set, or if the queue is idle, then the URB is always
++ * assigned to the first available (and not yet expired) slot in the
++ * endpoint's schedule.  If the flag is not set and the queue is active
++ * then the URB is always assigned to the next slot in the schedule
++ * following the end of the endpoint's previous URB, even if that slot is
++ * in the past.  When a packet is assigned in this way to a slot that has
++ * already expired, the packet is not transmitted and the corresponding
++ * usb_iso_packet_descriptor's status field will return -EXDEV.  If this
++ * would happen to all the packets in the URB, submission fails with a
++ * -EXDEV error code.
+  *
+  * For control endpoints, the synchronous usb_control_msg() call is
+  * often used (in non-interrupt context) instead of this call.
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 10278d18709c..f92cdf0c1457 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -1129,8 +1129,8 @@ extern int usb_disabled(void);
+  * Note: URB_DIR_IN/OUT is automatically set in usb_submit_urb().
+  */
+ #define URB_SHORT_NOT_OK	0x0001	/* report short reads as errors */
+-#define URB_ISO_ASAP		0x0002	/* iso-only, urb->start_frame
+-					 * ignored */
++#define URB_ISO_ASAP		0x0002	/* iso-only; use the first unexpired
++					 * slot in the schedule */
+ #define URB_NO_TRANSFER_DMA_MAP	0x0004	/* urb->transfer_dma valid on submit */
+ #define URB_NO_FSBR		0x0020	/* UHCI-specific */
+ #define URB_ZERO_PACKET		0x0040	/* Finish bulk OUT with short packet */
+@@ -1309,15 +1309,20 @@ typedef void (*usb_complete_t)(struct urb *);
+  * the transfer interval in the endpoint descriptor is logarithmic.
+  * Device drivers must convert that value to linear units themselves.)
+  *
+- * Isochronous URBs normally use the URB_ISO_ASAP transfer flag, telling
+- * the host controller to schedule the transfer as soon as bandwidth
+- * utilization allows, and then set start_frame to reflect the actual frame
+- * selected during submission.  Otherwise drivers must specify the start_frame
+- * and handle the case where the transfer can't begin then.  However, drivers
+- * won't know how bandwidth is currently allocated, and while they can
+- * find the current frame using usb_get_current_frame_number () they can't
+- * know the range for that frame number.  (Ranges for frame counter values
+- * are HC-specific, and can go from 256 to 65536 frames from "now".)
++ * If an isochronous endpoint queue isn't already running, the host
++ * controller will schedule a new URB to start as soon as bandwidth
++ * utilization allows.  If the queue is running then a new URB will be
++ * scheduled to start in the first transfer slot following the end of the
++ * preceding URB, if that slot has not already expired.  If the slot has
++ * expired (which can happen when IRQ delivery is delayed for a long time),
++ * the scheduling behavior depends on the URB_ISO_ASAP flag.  If the flag
++ * is clear then the URB will be scheduled to start in the expired slot,
++ * implying that some of its packets will not be transferred; if the flag
++ * is set then the URB will be scheduled in the first unexpired slot,
++ * breaking the queue's synchronization.  Upon URB completion, the
++ * start_frame field will be set to the (micro)frame number in which the
++ * transfer was scheduled.  Ranges for frame counter values are HC-specific
++ * and can go from as low as 256 to as high as 65536 frames.
+  *
+  * Isochronous URBs have a different data transfer model, in part because
+  * the quality of service is only "best effort".  Callers provide specially

commit 72675479925f53af051ae8a78bcfafeaa47b3eef
+Author: Alan Stern 
+Date:   Fri Sep 28 16:01:40 2012 -0400
+
+    EHCI: replace mult/div with bit-mask operation
+    
+    This patch (as1610) replaces multiplication and divison operations in
+    ehci-hcd's isochronous scheduling code with a bit-mask operation,
+    taking advantage of the fact that isochronous periods are always
+    powers of 2.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index b764cab2ab9a..e08e65d8e004 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1416,7 +1416,7 @@ iso_stream_schedule (
+ 
+ 		/* Behind the scheduling threshold?  Assume URB_ISO_ASAP. */
+ 		if (unlikely(start < next))
+-			start += period * DIV_ROUND_UP(next - start, period);
++			start += (next - start + period - 1) & (- period);
+ 
+ 		start += base;
+ 	}

commit 98cae42d82fe9c9e2b5dacdf391edaa007e147e5
+Author: Alan Stern 
+Date:   Fri Sep 28 16:01:34 2012 -0400
+
+    EHCI: use the isochronous scheduling threshold
+    
+    This patch (as1609) changes the way ehci-hcd uses the "Isochronous
+    Scheduling Threshold" in its calculations.  Until now the code has
+    ignored the threshold except for certain Intel PCI-based controllers.
+    This violates the EHCI spec.
+    
+    The new code takes the threshold into account always, removing the
+    need for the fs_i_thresh quirk flag.  In addition it implements the
+    "full frame cache" setting more efficiently, moving forward only as
+    far as the next frame boundary instead of always moving forward 8
+    microframes.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 6bf6c42481e8..61eac96441de 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -503,7 +503,7 @@ static int ehci_init(struct usb_hcd *hcd)
+ 
+ 	/* controllers may cache some of the periodic schedule ... */
+ 	if (HCC_ISOC_CACHE(hcc_params))		// full frame cache
+-		ehci->i_thresh = 2 + 8;
++		ehci->i_thresh = 0;
+ 	else					// N microframes cached
+ 		ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params);
+ 
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index 2cb7d370c4ef..d1407f8d42b1 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -103,7 +103,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 		}
+ 		break;
+ 	case PCI_VENDOR_ID_INTEL:
+-		ehci->fs_i_thresh = 1;
+ 		if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB)
+ 			hcd->has_tt = 1;
+ 		break;
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 7eb242f27c00..b764cab2ab9a 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1391,15 +1391,11 @@ iso_stream_schedule (
+ 	 */
+ 	if (likely (!list_empty (&stream->td_list))) {
+ 
+-		/* For high speed devices, allow scheduling within the
+-		 * isochronous scheduling threshold.  For full speed devices
+-		 * and Intel PCI-based controllers, don't (work around for
+-		 * Intel ICH9 bug).
+-		 */
+-		if (!stream->highspeed && ehci->fs_i_thresh)
+-			next = now + ehci->i_thresh;
++		/* Take the isochronous scheduling threshold into account */
++		if (ehci->i_thresh)
++			next = now + ehci->i_thresh;	/* uframe cache */
+ 		else
+-			next = now;
++			next = (now + 2 + 7) & ~0x07;	/* full frame cache */
+ 
+ 		/*
+ 		 * Use ehci->last_iso_frame as the base.  There can't be any
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 0564a63f5eb3..4ddf7c51616b 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -193,7 +193,6 @@ struct ehci_hcd {			/* one per controller */
+ 	unsigned		has_amcc_usb23:1;
+ 	unsigned		need_io_watchdog:1;
+ 	unsigned		amd_pll_fix:1;
+-	unsigned		fs_i_thresh:1;	/* Intel iso scheduling */
+ 	unsigned		use_dummy_qh:1;	/* AMD Frame List table quirk*/
+ 	unsigned		has_synopsys_hc_bug:1; /* Synopsys HC */
+ 	unsigned		frame_index_bug:1; /* MosChip (AKA NetMos) */

commit c3ee9b76aa93fbf59727e02fac9914c7355108f3
+Author: Alan Stern 
+Date:   Fri Sep 28 16:01:23 2012 -0400
+
+    EHCI: improved logic for isochronous scheduling
+    
+    This patch (as1608) reworks the logic used by ehci-hcd for scheduling
+    isochronous transfers.  Now the modular calculations are all based on
+    a window that starts at the last frame scanned for isochronous
+    completions.  No transfer descriptors for any earlier frames can
+    possibly remain on the schedule, so there can be no confusion from
+    schedule wrap-around.  This removes the need for a "slop" region of
+    arbitrary size.
+    
+    There's no need to check for URBs that are longer than the schedule
+    length.  With the old code they could throw things off by wrapping
+    around and appearing to end in the near future rather than the distant
+    future.  Now such confusion isn't possible, and the existing test for
+    submissions that extend too far into the future will also catch those
+    that exceed the schedule length.  (But there still has to be an
+    initial test to handle the case where the schedule already extends as
+    far into the future as possible.)
+    
+    Delays caused by IRQ latency won't confuse the algorithm unless they
+    are ridiculously long (over 250 ms); they will merely reduce how far
+    into the future new transfers can be scheduled.  A few people have
+    reported problems caused by delays of 50 ms or so.  Now instead of
+    failing completely, isochronous transfers will experience a brief
+    glitch and then continue normally.
+    
+    (Whether this is truly a good thing is debatable.  A latency as large
+    as 50 ms generally indicates a bug is present, and complete failure of
+    audio or video transfers draws people's attention pretty vividly.
+    Making the transfers more robust also makes it easier for such bugs to
+    remain undetected.)
+    
+    Finally, ehci->next_frame is renamed to ehci->last_iso_frame, because
+    that better describes what it is: the last frame to have been scanned
+    for isochronous completions.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 7cf3da7babf0..7eb242f27c00 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1361,7 +1361,7 @@ sitd_slot_ok (
+  * given EHCI_TUNE_FLS and the slop).  Or, write a smarter scheduler!
+  */
+ 
+-#define SCHEDULE_SLOP	80	/* microframes */
++#define SCHEDULING_DELAY	40	/* microframes */
+ 
+ static int
+ iso_stream_schedule (
+@@ -1370,7 +1370,7 @@ iso_stream_schedule (
+ 	struct ehci_iso_stream	*stream
+ )
+ {
+-	u32			now, next, start, period, span;
++	u32			now, base, next, start, period, span;
+ 	int			status;
+ 	unsigned		mod = ehci->periodic_size << 3;
+ 	struct ehci_iso_sched	*sched = urb->hcpriv;
+@@ -1382,12 +1382,6 @@ iso_stream_schedule (
+ 		span <<= 3;
+ 	}
+ 
+-	if (span > mod - SCHEDULE_SLOP) {
+-		ehci_dbg (ehci, "iso request %p too long\n", urb);
+-		status = -EFBIG;
+-		goto fail;
+-	}
+-
+ 	now = ehci_read_frame_index(ehci) & (mod - 1);
+ 
+ 	/* Typical case: reuse current schedule, stream is still active.
+@@ -1396,7 +1390,6 @@ iso_stream_schedule (
+ 	 * slot in the schedule, implicitly assuming URB_ISO_ASAP.
+ 	 */
+ 	if (likely (!list_empty (&stream->td_list))) {
+-		u32	excess;
+ 
+ 		/* For high speed devices, allow scheduling within the
+ 		 * isochronous scheduling threshold.  For full speed devices
+@@ -1408,36 +1401,41 @@ iso_stream_schedule (
+ 		else
+ 			next = now;
+ 
+-		/* Fell behind (by up to twice the slop amount)?
+-		 * We decide based on the time of the last currently-scheduled
+-		 * slot, not the time of the next available slot.
++		/*
++		 * Use ehci->last_iso_frame as the base.  There can't be any
++		 * TDs scheduled for earlier than that.
+ 		 */
+-		excess = (stream->next_uframe - period - next) & (mod - 1);
+-		if (excess >= mod - 2 * SCHEDULE_SLOP)
+-			start = next + excess - mod + period *
+-					DIV_ROUND_UP(mod - excess, period);
+-		else
+-			start = next + excess + period;
+-		if (start - now >= mod) {
+-			ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n",
+-					urb, start - now - period, period,
+-					mod);
+-			status = -EFBIG;
++		base = ehci->last_iso_frame << 3;
++		next = (next - base) & (mod - 1);
++		start = (stream->next_uframe - base) & (mod - 1);
++
++		/* Is the schedule already full? */
++		if (unlikely(start < period)) {
++			ehci_dbg(ehci, "iso sched full %p (%u-%u < %u mod %u)\n",
++					urb, stream->next_uframe, base,
++					period, mod);
++			status = -ENOSPC;
+ 			goto fail;
+ 		}
++
++		/* Behind the scheduling threshold?  Assume URB_ISO_ASAP. */
++		if (unlikely(start < next))
++			start += period * DIV_ROUND_UP(next - start, period);
++
++		start += base;
+ 	}
+ 
+ 	/* need to schedule; when's the next (u)frame we could start?
+ 	 * this is bigger than ehci->i_thresh allows; scheduling itself
+-	 * isn't free, the slop should handle reasonably slow cpus.  it
++	 * isn't free, the delay should handle reasonably slow cpus.  it
+ 	 * can also help high bandwidth if the dma and irq loads don't
+ 	 * jump until after the queue is primed.
+ 	 */
+ 	else {
+ 		int done = 0;
+-		start = SCHEDULE_SLOP + (now & ~0x07);
+ 
+-		/* NOTE:  assumes URB_ISO_ASAP, to limit complexity/bugs */
++		base = now & ~0x07;
++		start = base + SCHEDULING_DELAY;
+ 
+ 		/* find a uframe slot with enough bandwidth.
+ 		 * Early uframes are more precious because full-speed
+@@ -1464,19 +1462,16 @@ iso_stream_schedule (
+ 
+ 		/* no room in the schedule */
+ 		if (!done) {
+-			ehci_dbg(ehci, "iso resched full %p (now %d max %d)\n",
+-				urb, now, now + mod);
++			ehci_dbg(ehci, "iso sched full %p", urb);
+ 			status = -ENOSPC;
+ 			goto fail;
+ 		}
+ 	}
+ 
+ 	/* Tried to schedule too far into the future? */
+-	if (unlikely(start - now + span - period
+-				>= mod - 2 * SCHEDULE_SLOP)) {
+-		ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n",
+-				urb, start - now, span - period,
+-				mod - 2 * SCHEDULE_SLOP);
++	if (unlikely(start - base + span - period >= mod)) {
++		ehci_dbg(ehci, "request %p would overflow (%u+%u >= %u)\n",
++				urb, start - base, span - period, mod);
+ 		status = -EFBIG;
+ 		goto fail;
+ 	}
+@@ -1490,7 +1485,7 @@ iso_stream_schedule (
+ 
+ 	/* Make sure scan_isoc() sees these */
+ 	if (ehci->isoc_count == 0)
+-		ehci->next_frame = now >> 3;
++		ehci->last_iso_frame = now >> 3;
+ 	return 0;
+ 
+  fail:
+@@ -2220,16 +2215,16 @@ static void scan_isoc(struct ehci_hcd *ehci)
+ 		now_frame = (uf >> 3) & fmask;
+ 		live = true;
+ 	} else  {
+-		now_frame = (ehci->next_frame - 1) & fmask;
++		now_frame = (ehci->last_iso_frame - 1) & fmask;
+ 		live = false;
+ 	}
+ 	ehci->now_frame = now_frame;
+ 
+-	frame = ehci->next_frame;
+ 	for (;;) {
+ 		union ehci_shadow	q, *q_p;
+ 		__hc32			type, *hw_p;
+ 
++		frame = ehci->last_iso_frame;
+ restart:
+ 		/* scan each element in frame's queue for completions */
+ 		q_p = &ehci->pshadow [frame];
+@@ -2334,7 +2329,6 @@ static void scan_isoc(struct ehci_hcd *ehci)
+ 		/* Stop when we have reached the current frame */
+ 		if (frame == now_frame)
+ 			break;
+-		frame = (frame + 1) & fmask;
++		ehci->last_iso_frame = (frame + 1) & fmask;
+ 	}
+-	ehci->next_frame = now_frame;
+ }
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index da07d98f7d1d..0564a63f5eb3 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -143,7 +143,7 @@ struct ehci_hcd {			/* one per controller */
+ 	struct ehci_qh		*intr_unlink_last;
+ 	unsigned		intr_unlink_cycle;
+ 	unsigned		now_frame;	/* frame from HC hardware */
+-	unsigned		next_frame;	/* scan periodic, start here */
++	unsigned		last_iso_frame;	/* last frame scanned for iso */
+ 	unsigned		intr_count;	/* intr activity count */
+ 	unsigned		isoc_count;	/* isoc activity count */
+ 	unsigned		periodic_count;	/* periodic activity count */

commit db5c8b524444d4fc6b1f32d368a50a3729e50002
+Author: Alan Stern 
+Date:   Wed Oct 10 14:10:21 2012 -0400
+
+    USB: fix port probing and removal in garmin_gps
+    
+    This patch (as1615) fixes a bug in the Garmin USB serial driver.  It
+    uses attach, disconnect, and release routines to carry out actions
+    that should be handled by port_probe and port_remove routines, because
+    they access port-specific data.
+    
+    The bug causes an oops when the device in unplugged, because the
+    private data for each port structure now gets erased when the port is
+    unbound from the driver, resulting in a null-pointer dereference.
+    
+    Signed-off-by: Alan Stern 
+    Reported--by: Markus Schauler 
+    Tested-by: Markus Schauler 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
+index 3ee92648c02d..203358d7e7bc 100644
+--- a/drivers/usb/serial/garmin_gps.c
++++ b/drivers/usb/serial/garmin_gps.c
+@@ -1405,11 +1405,10 @@ static void timeout_handler(unsigned long data)
+ 
+ 
+ 
+-static int garmin_attach(struct usb_serial *serial)
++static int garmin_port_probe(struct usb_serial_port *port)
+ {
+-	int status = 0;
+-	struct usb_serial_port *port = serial->port[0];
+-	struct garmin_data *garmin_data_p = NULL;
++	int status;
++	struct garmin_data *garmin_data_p;
+ 
+ 	garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL);
+ 	if (garmin_data_p == NULL) {
+@@ -1434,22 +1433,14 @@ static int garmin_attach(struct usb_serial *serial)
+ }
+ 
+ 
+-static void garmin_disconnect(struct usb_serial *serial)
++static int garmin_port_remove(struct usb_serial_port *port)
+ {
+-	struct usb_serial_port *port = serial->port[0];
+ 	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
+ 
+ 	usb_kill_urb(port->interrupt_in_urb);
+ 	del_timer_sync(&garmin_data_p->timer);
+-}
+-
+-
+-static void garmin_release(struct usb_serial *serial)
+-{
+-	struct usb_serial_port *port = serial->port[0];
+-	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
+-
+ 	kfree(garmin_data_p);
++	return 0;
+ }
+ 
+ 
+@@ -1466,9 +1457,8 @@ static struct usb_serial_driver garmin_device = {
+ 	.close               = garmin_close,
+ 	.throttle            = garmin_throttle,
+ 	.unthrottle          = garmin_unthrottle,
+-	.attach              = garmin_attach,
+-	.disconnect          = garmin_disconnect,
+-	.release             = garmin_release,
++	.port_probe		= garmin_port_probe,
++	.port_remove		= garmin_port_remove,
+ 	.write               = garmin_write,
+ 	.write_room          = garmin_write_room,
+ 	.write_bulk_callback = garmin_write_bulk_callback,

commit 0d00dc2611abbe6ad244d50569c2ee82ce42846c
+Author: Alan Stern 
+Date:   Wed Sep 26 13:09:53 2012 -0400
+
+    USB: Fix race condition when removing host controllers
+    
+    This patch (as1607) fixes a race that can occur if a USB host
+    controller is removed while a process is reading the
+    /sys/kernel/debug/usb/devices file.
+    
+    The usb_device_read() routine uses the bus->root_hub pointer to
+    determine whether or not the root hub is registered.  The is not a
+    valid test, because the pointer is set before the root hub gets
+    registered and remains set even after the root hub is unregistered and
+    deallocated.  As a result, usb_device_read() or usb_device_dump() can
+    access freed memory, causing an oops.
+    
+    The patch changes the test to use the hcd->rh_registered flag, which
+    does get set and cleared at the appropriate times.  It also makes sure
+    to hold the usb_bus_list_lock mutex while setting the flag, so that
+    usb_device_read() will become aware of new root hubs as soon as they
+    are registered.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Don Zickus 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
+index d95696584762..3440812b4a84 100644
+--- a/drivers/usb/core/devices.c
++++ b/drivers/usb/core/devices.c
+@@ -624,7 +624,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf,
+ 	/* print devices for all busses */
+ 	list_for_each_entry(bus, &usb_bus_list, bus_list) {
+ 		/* recurse through all children of the root hub */
+-		if (!bus->root_hub)
++		if (!bus_to_hcd(bus)->rh_registered)
+ 			continue;
+ 		usb_lock_device(bus->root_hub);
+ 		ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos,
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index bc84106ac057..75ba2091f9b4 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1011,10 +1011,7 @@ static int register_root_hub(struct usb_hcd *hcd)
+ 	if (retval) {
+ 		dev_err (parent_dev, "can't register root hub for %s, %d\n",
+ 				dev_name(&usb_dev->dev), retval);
+-	}
+-	mutex_unlock(&usb_bus_list_lock);
+-
+-	if (retval == 0) {
++	} else {
+ 		spin_lock_irq (&hcd_root_hub_lock);
+ 		hcd->rh_registered = 1;
+ 		spin_unlock_irq (&hcd_root_hub_lock);
+@@ -1023,6 +1020,7 @@ static int register_root_hub(struct usb_hcd *hcd)
+ 		if (HCD_DEAD(hcd))
+ 			usb_hc_died (hcd);	/* This time clean up */
+ 	}
++	mutex_unlock(&usb_bus_list_lock);
+ 
+ 	return retval;
+ }

commit 0a2314035cab62cafc38ea11ec5b6f95cf347b38
+Author: Alan Stern 
+Date:   Wed Sep 26 13:09:53 2012 -0400
+
+    USB: Fix race condition when removing host controllers
+    
+    This patch (as1607) fixes a race that can occur if a USB host
+    controller is removed while a process is reading the
+    /sys/kernel/debug/usb/devices file.
+    
+    The usb_device_read() routine uses the bus->root_hub pointer to
+    determine whether or not the root hub is registered.  The is not a
+    valid test, because the pointer is set before the root hub gets
+    registered and remains set even after the root hub is unregistered and
+    deallocated.  As a result, usb_device_read() or usb_device_dump() can
+    access freed memory, causing an oops.
+    
+    The patch changes the test to use the hcd->rh_registered flag, which
+    does get set and cleared at the appropriate times.  It also makes sure
+    to hold the usb_bus_list_lock mutex while setting the flag, so that
+    usb_device_read() will become aware of new root hubs as soon as they
+    are registered.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Don Zickus 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
+index f4ead1296820..f460de31acee 100644
+--- a/drivers/usb/core/devices.c
++++ b/drivers/usb/core/devices.c
+@@ -623,7 +623,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf,
+ 	/* print devices for all busses */
+ 	list_for_each_entry(bus, &usb_bus_list, bus_list) {
+ 		/* recurse through all children of the root hub */
+-		if (!bus->root_hub)
++		if (!bus_to_hcd(bus)->rh_registered)
+ 			continue;
+ 		usb_lock_device(bus->root_hub);
+ 		ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos,
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 35b52f6e1c5e..1e741bca0265 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1011,10 +1011,7 @@ static int register_root_hub(struct usb_hcd *hcd)
+ 	if (retval) {
+ 		dev_err (parent_dev, "can't register root hub for %s, %d\n",
+ 				dev_name(&usb_dev->dev), retval);
+-	}
+-	mutex_unlock(&usb_bus_list_lock);
+-
+-	if (retval == 0) {
++	} else {
+ 		spin_lock_irq (&hcd_root_hub_lock);
+ 		hcd->rh_registered = 1;
+ 		spin_unlock_irq (&hcd_root_hub_lock);
+@@ -1023,6 +1020,7 @@ static int register_root_hub(struct usb_hcd *hcd)
+ 		if (HCD_DEAD(hcd))
+ 			usb_hc_died (hcd);	/* This time clean up */
+ 	}
++	mutex_unlock(&usb_bus_list_lock);
+ 
+ 	return retval;
+ }

commit d16ba48774913d244c7eb894d28d8ae2c019a827
+Author: Alan Stern 
+Date:   Wed Sep 19 17:02:29 2012 -0400
+
+    USB: EHCI: convert warning messages to debug-level
+    
+    This patch (as1606) converts two warning messages in the ehci-hcd
+    driver to debug messages, and adds a little extra information to each.
+    
+    The log messages occur when an EHCI controller takes too long (more
+    than 20 ms) to turn its async or periodic schedule on or off.  If this
+    happens at all, it's liable to happen quite often and there's no point
+    spamming the system log with these warnings.  Furthermore, there's
+    nothing much we can do about it when the problem happens.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Thomas Voegtle 
+    Cc: stable  # [3.6]
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
+index eb896a2c8f2e..20dbdcbe9b0f 100644
+--- a/drivers/usb/host/ehci-timer.c
++++ b/drivers/usb/host/ehci-timer.c
+@@ -118,7 +118,8 @@ static void ehci_poll_ASS(struct ehci_hcd *ehci)
+ 			ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true);
+ 			return;
+ 		}
+-		ehci_warn(ehci, "Waited too long for the async schedule status, giving up\n");
++		ehci_dbg(ehci, "Waited too long for the async schedule status (%x/%x), giving up\n",
++				want, actual);
+ 	}
+ 	ehci->ASS_poll_count = 0;
+ 
+@@ -163,7 +164,8 @@ static void ehci_poll_PSS(struct ehci_hcd *ehci)
+ 			ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);
+ 			return;
+ 		}
+-		ehci_warn(ehci, "Waited too long for the periodic schedule status, giving up\n");
++		ehci_dbg(ehci, "Waited too long for the periodic schedule status (%x/%x), giving up\n",
++				want, actual);
+ 	}
+ 	ehci->PSS_poll_count = 0;
+ 

commit 17dcfc9bd3dfb699e00205ec9d431b5a5cb00b34
+Author: Alan Stern 
+Date:   Wed Sep 19 17:00:55 2012 -0400
+
+    USB: EHCI: remove useless test
+    
+    This patch (as1605) removes a useless test from the EHCI debugfs
+    code.  There's no point checking whether p.qh is non-NULL; we already
+    know it is and in any case it gets dereferenced aerlier in the
+    function.
+    
+    The useless test was identified by smatch.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Fengguang Wu 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
+index f0c00de035ef..1599806e3d47 100644
+--- a/drivers/usb/host/ehci-dbg.c
++++ b/drivers/usb/host/ehci-dbg.c
+@@ -653,10 +653,8 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
+ 						seen [seen_count++].qh = p.qh;
+ 				} else
+ 					temp = 0;
+-				if (p.qh) {
+-					tag = Q_NEXT_TYPE(ehci, hw->hw_next);
+-					p = p.qh->qh_next;
+-				}
++				tag = Q_NEXT_TYPE(ehci, hw->hw_next);
++				p = p.qh->qh_next;
+ 				break;
+ 			case Q_TYPE_FSTN:
+ 				temp = scnprintf (next, size,

commit 88d26136a256576e444db312179e17af6dd0ea87
+Author: Alan Stern 
+Date:   Wed Sep 19 21:59:02 2012 +0200
+
+    PM: Prevent runtime suspend during system resume
+    
+    This patch (as1591) moves the pm_runtime_get_noresume() and
+    pm_runtime_put_sync() calls from __device_suspend() and
+    device_resume() to device_prepare() and device_complete() in the PM
+    core.
+    
+    The reason for doing this is to make sure that parent devices remain
+    at full power (i.e., don't go into runtime suspend) while their
+    children are being resumed from a system sleep.
+    
+    The PCI core already contained equivalent code to serve the same
+    purpose.  The patch removes the duplicated code, since it is no longer
+    needed.  One of the comments from the PCI core gets moved into the PM
+    core, and a second comment is added to explain whe the _get_noresume
+    and _put_sync calls are present.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
+index 2700f2e4066f..077b9756fd8f 100644
+--- a/drivers/base/power/main.c
++++ b/drivers/base/power/main.c
+@@ -565,7 +565,6 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
+ 	pm_callback_t callback = NULL;
+ 	char *info = NULL;
+ 	int error = 0;
+-	bool put = false;
+ 
+ 	TRACE_DEVICE(dev);
+ 	TRACE_RESUME(0);
+@@ -583,7 +582,6 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
+ 		goto Unlock;
+ 
+ 	pm_runtime_enable(dev);
+-	put = true;
+ 
+ 	if (dev->pm_domain) {
+ 		info = "power domain ";
+@@ -636,9 +634,6 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
+ 
+ 	TRACE_RESUME(error);
+ 
+-	if (put)
+-		pm_runtime_put_sync(dev);
+-
+ 	return error;
+ }
+ 
+@@ -749,6 +744,8 @@ static void device_complete(struct device *dev, pm_message_t state)
+ 	}
+ 
+ 	device_unlock(dev);
++
++	pm_runtime_put_sync(dev);
+ }
+ 
+ /**
+@@ -1043,12 +1040,16 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
+ 	if (async_error)
+ 		goto Complete;
+ 
+-	pm_runtime_get_noresume(dev);
++	/*
++	 * If a device configured to wake up the system from sleep states
++	 * has been suspended at run time and there's a resume request pending
++	 * for it, this is equivalent to the device signaling wakeup, so the
++	 * system suspend operation should be aborted.
++	 */
+ 	if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
+ 		pm_wakeup_event(dev, 0);
+ 
+ 	if (pm_wakeup_pending()) {
+-		pm_runtime_put_sync(dev);
+ 		async_error = -EBUSY;
+ 		goto Complete;
+ 	}
+@@ -1111,12 +1112,10 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
+  Complete:
+ 	complete_all(&dev->power.completion);
+ 
+-	if (error) {
+-		pm_runtime_put_sync(dev);
++	if (error)
+ 		async_error = error;
+-	} else if (dev->power.is_suspended) {
++	else if (dev->power.is_suspended)
+ 		__pm_runtime_disable(dev, false);
+-	}
+ 
+ 	return error;
+ }
+@@ -1209,6 +1208,14 @@ static int device_prepare(struct device *dev, pm_message_t state)
+ 	char *info = NULL;
+ 	int error = 0;
+ 
++	/*
++	 * If a device's parent goes into runtime suspend at the wrong time,
++	 * it won't be possible to resume the device.  To prevent this we
++	 * block runtime suspend here, during the prepare phase, and allow
++	 * it again during the complete phase.
++	 */
++	pm_runtime_get_noresume(dev);
++
+ 	device_lock(dev);
+ 
+ 	dev->power.wakeup_path = device_may_wakeup(dev);
+diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
+index 185be3703343..51cd90bcdd4c 100644
+--- a/drivers/pci/pci-driver.c
++++ b/drivers/pci/pci-driver.c
+@@ -623,21 +623,6 @@ static int pci_pm_prepare(struct device *dev)
+ 	struct device_driver *drv = dev->driver;
+ 	int error = 0;
+ 
+-	/*
+-	 * If a PCI device configured to wake up the system from sleep states
+-	 * has been suspended at run time and there's a resume request pending
+-	 * for it, this is equivalent to the device signaling wakeup, so the
+-	 * system suspend operation should be aborted.
+-	 */
+-	pm_runtime_get_noresume(dev);
+-	if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
+-		pm_wakeup_event(dev, 0);
+-
+-	if (pm_wakeup_pending()) {
+-		pm_runtime_put_sync(dev);
+-		return -EBUSY;
+-	}
+-
+ 	/*
+ 	 * PCI devices suspended at run time need to be resumed at this
+ 	 * point, because in general it is necessary to reconfigure them for
+@@ -661,8 +646,6 @@ static void pci_pm_complete(struct device *dev)
+ 
+ 	if (drv && drv->pm && drv->pm->complete)
+ 		drv->pm->complete(dev);
+-
+-	pm_runtime_put_sync(dev);
+ }
+ 
+ #else /* !CONFIG_PM_SLEEP */

commit 92fc7a8b0f20bdb243c706daf42658e8e0cd2ef0
+Author: Alan Stern 
+Date:   Tue Sep 4 10:41:02 2012 -0400
+
+    USB: add device quirk for Joss Optical touchboard
+    
+    This patch (as1604) adds a CONFIG_INTF_STRINGS quirk for the Joss
+    infrared touchboard device.  The device doesn't like to be asked for
+    its interface strings.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: adam ? 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index f15501f4c585..e77a8e8eaa23 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -71,6 +71,10 @@ static const struct usb_device_id usb_quirk_list[] = {
+ 	{ USB_DEVICE(0x04b4, 0x0526), .driver_info =
+ 			USB_QUIRK_CONFIG_INTF_STRINGS },
+ 
++	/* Microchip Joss Optical infrared touchboard device */
++	{ USB_DEVICE(0x04d8, 0x000c), .driver_info =
++			USB_QUIRK_CONFIG_INTF_STRINGS },
++
+ 	/* Samsung Android phone modem - ID conflict with SPH-I500 */
+ 	{ USB_DEVICE(0x04e8, 0x6601), .driver_info =
+ 			USB_QUIRK_CONFIG_INTF_STRINGS },

commit d0d860758bd350206242962a223858bd01cd8a93
+Author: Alan Stern 
+Date:   Mon Aug 20 16:12:47 2012 -0400
+
+    usb: gadget: dummy-hcd: remember to update driver pointer
+    
+    This patch (as1599) fixes dummy-hcd to make it update the appropriate
+    driver pointer when a new gadget driver is bound or unbound.  Without
+    this change, the gadget driver's name doesn't appear in dev_printk
+    output.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index b799106027ad..91916f693ff7 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -909,6 +909,7 @@ static int dummy_udc_start(struct usb_gadget *g,
+ 	dum->devstatus = 0;
+ 
+ 	dum->driver = driver;
++	dum->gadget.dev.driver = &driver->driver;
+ 	dev_dbg(udc_dev(dum), "binding gadget driver '%s'\n",
+ 			driver->driver.name);
+ 	return 0;
+@@ -923,6 +924,7 @@ static int dummy_udc_stop(struct usb_gadget *g,
+ 	dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n",
+ 			driver->driver.name);
+ 
++	dum->gadget.dev.driver = NULL;
+ 	dum->driver = NULL;
+ 
+ 	return 0;

commit 67ddbb3e6568fb1820b2cc45b00c50702b114801
+Author: Alan Stern 
+Date:   Thu Aug 23 10:51:55 2012 -0400
+
+    HID: add NOGET quirk for Eaton Ellipse MAX UPS
+    
+    This patch (as1603) adds a NOGET quirk for the Eaton Ellipse MAX UPS
+    device.  (The USB IDs were already present in hid-ids.h, apparently
+    under a different name.)
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Laurent Bigonville 
+    CC: 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
+index 903eef3d3e10..991e85c7325c 100644
+--- a/drivers/hid/usbhid/hid-quirks.c
++++ b/drivers/hid/usbhid/hid-quirks.c
+@@ -70,6 +70,7 @@ static const struct hid_blacklist {
+ 	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
++	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS },
+ 	{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS },
+ 	{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2, HID_QUIRK_NO_INIT_REPORTS },

commit eb055fd0560b9835e9e1a956aa6a83c51a735801
+Author: Alan Stern 
+Date:   Thu Jul 19 16:09:01 2012 -0400
+
+    HID: usbhid: fix error paths in suspend
+    
+    This patch (as1597) fixes some of the error paths in usbhid's suspend
+    routine.  The driver was not careful to restart everything that might
+    have been stopped, in cases where a suspend failed.
+    
+    For example, once the HID_SUSPENDED flag is set, an output report
+    submission would not restart the corresponding URB queue.  If a
+    suspend fails, it's therefore necessary to check whether the queues
+    need to be restarted.
+    
+    Signed-off-by: Alan Stern 
+    CC: Oliver Neukum 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index 4309c03038f6..dedd8e4e5c6d 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -993,9 +993,10 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co
+ 
+ static void usbhid_restart_queues(struct usbhid_device *usbhid)
+ {
+-	if (usbhid->urbout)
++	if (usbhid->urbout && !test_bit(HID_OUT_RUNNING, &usbhid->iofl))
+ 		usbhid_restart_out_queue(usbhid);
+-	usbhid_restart_ctrl_queue(usbhid);
++	if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl))
++		usbhid_restart_ctrl_queue(usbhid);
+ }
+ 
+ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
+@@ -1462,11 +1463,38 @@ void usbhid_put_power(struct hid_device *hid)
+ 
+ 
+ #ifdef CONFIG_PM
++static int hid_resume_common(struct hid_device *hid, bool driver_suspended)
++{
++	struct usbhid_device *usbhid = hid->driver_data;
++	int status;
++
++	spin_lock_irq(&usbhid->lock);
++	clear_bit(HID_SUSPENDED, &usbhid->iofl);
++	usbhid_mark_busy(usbhid);
++
++	if (test_bit(HID_CLEAR_HALT, &usbhid->iofl) ||
++			test_bit(HID_RESET_PENDING, &usbhid->iofl))
++		schedule_work(&usbhid->reset_work);
++	usbhid->retry_delay = 0;
++
++	usbhid_restart_queues(usbhid);
++	spin_unlock_irq(&usbhid->lock);
++
++	status = hid_start_in(hid);
++	if (status < 0)
++		hid_io_error(hid);
++
++	if (driver_suspended && hid->driver && hid->driver->resume)
++		status = hid->driver->resume(hid);
++	return status;
++}
++
+ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
+ {
+ 	struct hid_device *hid = usb_get_intfdata(intf);
+ 	struct usbhid_device *usbhid = hid->driver_data;
+ 	int status;
++	bool driver_suspended = false;
+ 
+ 	if (PMSG_IS_AUTO(message)) {
+ 		spin_lock_irq(&usbhid->lock);	/* Sync with error handler */
+@@ -1482,8 +1510,9 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
+ 			if (hid->driver && hid->driver->suspend) {
+ 				status = hid->driver->suspend(hid, message);
+ 				if (status < 0)
+-					return status;
++					goto failed;
+ 			}
++			driver_suspended = true;
+ 		} else {
+ 			usbhid_mark_busy(usbhid);
+ 			spin_unlock_irq(&usbhid->lock);
+@@ -1496,11 +1525,14 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
+ 			if (status < 0)
+ 				return status;
+ 		}
++		driver_suspended = true;
+ 		spin_lock_irq(&usbhid->lock);
+ 		set_bit(HID_SUSPENDED, &usbhid->iofl);
+ 		spin_unlock_irq(&usbhid->lock);
+-		if (usbhid_wait_io(hid) < 0)
+-			return -EIO;
++		if (usbhid_wait_io(hid) < 0) {
++			status = -EIO;
++			goto failed;
++		}
+ 	}
+ 
+ 	hid_cancel_delayed_stuff(usbhid);
+@@ -1508,14 +1540,15 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
+ 
+ 	if (PMSG_IS_AUTO(message) && test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) {
+ 		/* lost race against keypresses */
+-		status = hid_start_in(hid);
+-		if (status < 0)
+-			hid_io_error(hid);
+-		usbhid_mark_busy(usbhid);
+-		return -EBUSY;
++		status = -EBUSY;
++		goto failed;
+ 	}
+ 	dev_dbg(&intf->dev, "suspend\n");
+ 	return 0;
++
++ failed:
++	hid_resume_common(hid, driver_suspended);
++	return status;
+ }
+ 
+ static int hid_resume(struct usb_interface *intf)
+@@ -1527,23 +1560,7 @@ static int hid_resume(struct usb_interface *intf)
+ 	if (!test_bit(HID_STARTED, &usbhid->iofl))
+ 		return 0;
+ 
+-	clear_bit(HID_SUSPENDED, &usbhid->iofl);
+-	usbhid_mark_busy(usbhid);
+-
+-	if (test_bit(HID_CLEAR_HALT, &usbhid->iofl) ||
+-	    test_bit(HID_RESET_PENDING, &usbhid->iofl))
+-		schedule_work(&usbhid->reset_work);
+-	usbhid->retry_delay = 0;
+-	status = hid_start_in(hid);
+-	if (status < 0)
+-		hid_io_error(hid);
+-	usbhid_restart_queues(usbhid);
+-
+-	if (status >= 0 && hid->driver && hid->driver->resume) {
+-		int ret = hid->driver->resume(hid);
+-		if (ret < 0)
+-			status = ret;
+-	}
++	status = hid_resume_common(hid, true);
+ 	dev_dbg(&intf->dev, "resume status %d\n", status);
+ 	return 0;
+ }

commit d4150c8f3d80b4a9387083478a86da8b3390dd83
+Author: Alan Stern 
+Date:   Thu Jul 19 16:08:54 2012 -0400
+
+    HID: usbhid: check for suspend or reset before restarting
+    
+    This patch (as1596) improves the queue-restart logic in usbhid by
+    checking to see if the device is suspended or a reset is about to
+    occur.  There's no point submitting an URB if either of those is
+    true.
+    
+    Signed-off-by: Alan Stern 
+    CC: Oliver Neukum 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index 271578b85d91..4309c03038f6 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -207,7 +207,8 @@ static int usbhid_restart_out_queue(struct usbhid_device *usbhid)
+ 	int kicked;
+ 	int r;
+ 
+-	if (!hid)
++	if (!hid || test_bit(HID_RESET_PENDING, &usbhid->iofl) ||
++			test_bit(HID_SUSPENDED, &usbhid->iofl))
+ 		return 0;
+ 
+ 	if ((kicked = (usbhid->outhead != usbhid->outtail))) {
+@@ -245,7 +246,8 @@ static int usbhid_restart_ctrl_queue(struct usbhid_device *usbhid)
+ 	int r;
+ 
+ 	WARN_ON(hid == NULL);
+-	if (!hid)
++	if (!hid || test_bit(HID_RESET_PENDING, &usbhid->iofl) ||
++			test_bit(HID_SUSPENDED, &usbhid->iofl))
+ 		return 0;
+ 
+ 	if ((kicked = (usbhid->ctrlhead != usbhid->ctrltail))) {

commit f2b5264d4f77328e45d73cd135772b6e88a4951a
+Author: Alan Stern 
+Date:   Thu Jul 19 16:08:45 2012 -0400
+
+    HID: usbhid: replace HID_REPORTED_IDLE with HID_SUSPENDED
+    
+    This patch (as1595) improves the usbhid driver by using the
+    HID_SUSPENDED bitflag to indicate that the device is suspended rather
+    than using HID_REPORTED_IDLE, which the patch removes.
+    
+    Since HID_SUSPENDED was not being used for anything, and since the
+    name "HID_REPORTED_IDLE" doesn't convey much meaning, the end result
+    is easier to read and understand.
+    
+    Signed-off-by: Alan Stern 
+    CC: Oliver Neukum 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index 0fa07d95202d..271578b85d91 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -84,7 +84,7 @@ static int hid_start_in(struct hid_device *hid)
+ 	spin_lock_irqsave(&usbhid->lock, flags);
+ 	if (hid->open > 0 &&
+ 			!test_bit(HID_DISCONNECTED, &usbhid->iofl) &&
+-			!test_bit(HID_REPORTED_IDLE, &usbhid->iofl) &&
++			!test_bit(HID_SUSPENDED, &usbhid->iofl) &&
+ 			!test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) {
+ 		rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC);
+ 		if (rc != 0) {
+@@ -222,7 +222,7 @@ static int usbhid_restart_out_queue(struct usbhid_device *usbhid)
+ 		 * If still suspended, don't submit.  Submission will
+ 		 * occur if/when resume drains the queue.
+ 		 */
+-		if (test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) {
++		if (test_bit(HID_SUSPENDED, &usbhid->iofl)) {
+ 			usb_autopm_put_interface_no_suspend(usbhid->intf);
+ 			return r;
+ 		}
+@@ -260,7 +260,7 @@ static int usbhid_restart_ctrl_queue(struct usbhid_device *usbhid)
+ 		 * If still suspended, don't submit.  Submission will
+ 		 * occur if/when resume drains the queue.
+ 		 */
+-		if (test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) {
++		if (test_bit(HID_SUSPENDED, &usbhid->iofl)) {
+ 			usb_autopm_put_interface_no_suspend(usbhid->intf);
+ 			return r;
+ 		}
+@@ -1475,7 +1475,7 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
+ 		    && !test_bit(HID_KEYS_PRESSED, &usbhid->iofl)
+ 		    && (!usbhid->ledcount || ignoreled))
+ 		{
+-			set_bit(HID_REPORTED_IDLE, &usbhid->iofl);
++			set_bit(HID_SUSPENDED, &usbhid->iofl);
+ 			spin_unlock_irq(&usbhid->lock);
+ 			if (hid->driver && hid->driver->suspend) {
+ 				status = hid->driver->suspend(hid, message);
+@@ -1495,7 +1495,7 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
+ 				return status;
+ 		}
+ 		spin_lock_irq(&usbhid->lock);
+-		set_bit(HID_REPORTED_IDLE, &usbhid->iofl);
++		set_bit(HID_SUSPENDED, &usbhid->iofl);
+ 		spin_unlock_irq(&usbhid->lock);
+ 		if (usbhid_wait_io(hid) < 0)
+ 			return -EIO;
+@@ -1525,7 +1525,7 @@ static int hid_resume(struct usb_interface *intf)
+ 	if (!test_bit(HID_STARTED, &usbhid->iofl))
+ 		return 0;
+ 
+-	clear_bit(HID_REPORTED_IDLE, &usbhid->iofl);
++	clear_bit(HID_SUSPENDED, &usbhid->iofl);
+ 	usbhid_mark_busy(usbhid);
+ 
+ 	if (test_bit(HID_CLEAR_HALT, &usbhid->iofl) ||
+@@ -1552,7 +1552,7 @@ static int hid_reset_resume(struct usb_interface *intf)
+ 	struct usbhid_device *usbhid = hid->driver_data;
+ 	int status;
+ 
+-	clear_bit(HID_REPORTED_IDLE, &usbhid->iofl);
++	clear_bit(HID_SUSPENDED, &usbhid->iofl);
+ 	status = hid_post_reset(intf);
+ 	if (status >= 0 && hid->driver && hid->driver->reset_resume) {
+ 		int ret = hid->driver->reset_resume(hid);
+diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h
+index 1883d7b94870..bd87a61e5303 100644
+--- a/drivers/hid/usbhid/usbhid.h
++++ b/drivers/hid/usbhid/usbhid.h
+@@ -53,7 +53,6 @@ struct usb_interface *usbhid_find_interface(int minor);
+ #define HID_CLEAR_HALT		6
+ #define HID_DISCONNECTED	7
+ #define HID_STARTED		8
+-#define HID_REPORTED_IDLE	9
+ #define HID_KEYS_PRESSED	10
+ #define HID_NO_BANDWIDTH	11
+ 

commit 93101af31bc5df4486103f6b3ef212aaa5341b09
+Author: Alan Stern 
+Date:   Thu Jul 19 16:08:39 2012 -0400
+
+    HID: usbhid: inline some simple routines
+    
+    This patch (as1594) simplifies the usbhid driver by inlining a couple
+    of routines.  As a result of an earlier patch, irq_out_pump_restart()
+    and ctrl_pump_restart() are each used in only one place.  Since they
+    don't really do what their names say, and since they each involve only
+    about two lines of actual code, there's no reason to keep them as
+    separate functions.
+    
+    Signed-off-by: Alan Stern 
+    CC: Oliver Neukum 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index 213b3f39753c..0fa07d95202d 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -435,16 +435,6 @@ static int hid_submit_ctrl(struct hid_device *hid)
+  * Output interrupt completion handler.
+  */
+ 
+-static int irq_out_pump_restart(struct hid_device *hid)
+-{
+-	struct usbhid_device *usbhid = hid->driver_data;
+-
+-	if (usbhid->outhead != usbhid->outtail)
+-		return hid_submit_out(hid);
+-	else
+-		return -1;
+-}
+-
+ static void hid_irq_out(struct urb *urb)
+ {
+ 	struct hid_device *hid = urb->context;
+@@ -469,15 +459,17 @@ static void hid_irq_out(struct urb *urb)
+ 
+ 	spin_lock_irqsave(&usbhid->lock, flags);
+ 
+-	if (unplug)
++	if (unplug) {
+ 		usbhid->outtail = usbhid->outhead;
+-	else
++	} else {
+ 		usbhid->outtail = (usbhid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1);
+ 
+-	if (!irq_out_pump_restart(hid)) {
+-		/* Successfully submitted next urb in queue */
+-		spin_unlock_irqrestore(&usbhid->lock, flags);
+-		return;
++		if (usbhid->outhead != usbhid->outtail &&
++				hid_submit_out(hid) == 0) {
++			/* Successfully submitted next urb in queue */
++			spin_unlock_irqrestore(&usbhid->lock, flags);
++			return;
++		}
+ 	}
+ 
+ 	clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
+@@ -489,15 +481,6 @@ static void hid_irq_out(struct urb *urb)
+ /*
+  * Control pipe completion handler.
+  */
+-static int ctrl_pump_restart(struct hid_device *hid)
+-{
+-	struct usbhid_device *usbhid = hid->driver_data;
+-
+-	if (usbhid->ctrlhead != usbhid->ctrltail)
+-		return hid_submit_ctrl(hid);
+-	else
+-		return -1;
+-}
+ 
+ static void hid_ctrl(struct urb *urb)
+ {
+@@ -526,15 +509,17 @@ static void hid_ctrl(struct urb *urb)
+ 		hid_warn(urb->dev, "ctrl urb status %d received\n", status);
+ 	}
+ 
+-	if (unplug)
++	if (unplug) {
+ 		usbhid->ctrltail = usbhid->ctrlhead;
+-	else
++	} else {
+ 		usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
+ 
+-	if (!ctrl_pump_restart(hid)) {
+-		/* Successfully submitted next urb in queue */
+-		spin_unlock(&usbhid->lock);
+-		return;
++		if (usbhid->ctrlhead != usbhid->ctrltail &&
++				hid_submit_ctrl(hid) == 0) {
++			/* Successfully submitted next urb in queue */
++			spin_unlock(&usbhid->lock);
++			return;
++		}
+ 	}
+ 
+ 	clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);

commit 01a7c984e86fd45b760bb0da8b635059dff602e1
+Author: Alan Stern 
+Date:   Thu Jul 19 16:08:31 2012 -0400
+
+    HID: usbhid: fix autosuspend calls
+    
+    This patch (as1593) fixes some logic errors in the usbhid driver
+    relating to runtime PM.  The driver does not balance its calls to
+    usb_autopm_get_interface_async() and usb_autopm_put_interface_async().
+    
+    For example, when the control queue is restarted the driver does a
+    _get.  But the resume won't happen immediately, so the driver leaves
+    the queue stopped.  When the resume does occur, the queue is restarted
+    and a second _get occurs, with no balancing _put.
+    
+    The patch fixes the problem by rearranging the logic for restarting
+    the queues.  All the _get/_put calls and bitflag settings in
+    __usbhid_submit_report() are moved into the queue-restart routines.  A
+    balancing _put call is added for the case where the queue is still
+    suspended.  A call to irq_out_pump_restart(), which doesn't take all
+    the right actions for restarting the irq-OUT queue, is replaced by a
+    call to usbhid_restart_out_queue(), which does.  Similarly for
+    ctrl_pump_restart().
+    
+    Finally, new code is added to prevent an autosuspend from happening
+    every time an URB is cancelled, and the comments explaining what
+    happens when an URB needs to be cancelled are expanded and clarified.
+    
+    Signed-off-by: Alan Stern 
+    CC: Oliver Neukum 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index 6b9bad540702..213b3f39753c 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -213,9 +213,20 @@ static int usbhid_restart_out_queue(struct usbhid_device *usbhid)
+ 	if ((kicked = (usbhid->outhead != usbhid->outtail))) {
+ 		hid_dbg(hid, "Kicking head %d tail %d", usbhid->outhead, usbhid->outtail);
+ 
++		/* Try to wake up from autosuspend... */
+ 		r = usb_autopm_get_interface_async(usbhid->intf);
+ 		if (r < 0)
+ 			return r;
++
++		/*
++		 * If still suspended, don't submit.  Submission will
++		 * occur if/when resume drains the queue.
++		 */
++		if (test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) {
++			usb_autopm_put_interface_no_suspend(usbhid->intf);
++			return r;
++		}
++
+ 		/* Asynchronously flush queue. */
+ 		set_bit(HID_OUT_RUNNING, &usbhid->iofl);
+ 		if (hid_submit_out(hid)) {
+@@ -240,9 +251,20 @@ static int usbhid_restart_ctrl_queue(struct usbhid_device *usbhid)
+ 	if ((kicked = (usbhid->ctrlhead != usbhid->ctrltail))) {
+ 		hid_dbg(hid, "Kicking head %d tail %d", usbhid->ctrlhead, usbhid->ctrltail);
+ 
++		/* Try to wake up from autosuspend... */
+ 		r = usb_autopm_get_interface_async(usbhid->intf);
+ 		if (r < 0)
+ 			return r;
++
++		/*
++		 * If still suspended, don't submit.  Submission will
++		 * occur if/when resume drains the queue.
++		 */
++		if (test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) {
++			usb_autopm_put_interface_no_suspend(usbhid->intf);
++			return r;
++		}
++
+ 		/* Asynchronously flush queue. */
+ 		set_bit(HID_CTRL_RUNNING, &usbhid->iofl);
+ 		if (hid_submit_ctrl(hid)) {
+@@ -546,49 +568,36 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
+ 		usbhid->out[usbhid->outhead].report = report;
+ 		usbhid->outhead = head;
+ 
+-		/* Try to awake from autosuspend... */
+-		if (usb_autopm_get_interface_async(usbhid->intf) < 0)
+-			return;
++		/* If the queue isn't running, restart it */
++		if (!test_bit(HID_OUT_RUNNING, &usbhid->iofl)) {
++			usbhid_restart_out_queue(usbhid);
+ 
+-		/*
+-		 * But if still suspended, leave urb enqueued, don't submit.
+-		 * Submission will occur if/when resume() drains the queue.
+-		 */
+-		if (test_bit(HID_REPORTED_IDLE, &usbhid->iofl))
+-			return;
++		/* Otherwise see if an earlier request has timed out */
++		} else if (time_after(jiffies, usbhid->last_out + HZ * 5)) {
++
++			/* Prevent autosuspend following the unlink */
++			usb_autopm_get_interface_no_resume(usbhid->intf);
+ 
+-		if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl)) {
+-			if (hid_submit_out(hid)) {
+-				clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
+-				usb_autopm_put_interface_async(usbhid->intf);
+-			}
+-			wake_up(&usbhid->wait);
+-		} else {
+ 			/*
+-			 * the queue is known to run
+-			 * but an earlier request may be stuck
+-			 * we may need to time out
+-			 * no race because the URB is blocked under
+-			 * spinlock
++			 * Prevent resubmission in case the URB completes
++			 * before we can unlink it.  We don't want to cancel
++			 * the wrong transfer!
+ 			 */
+-			if (time_after(jiffies, usbhid->last_out + HZ * 5)) {
+-				usb_block_urb(usbhid->urbout);
+-				/* drop lock to not deadlock if the callback is called */
+-				spin_unlock(&usbhid->lock);
+-				usb_unlink_urb(usbhid->urbout);
+-				spin_lock(&usbhid->lock);
+-				usb_unblock_urb(usbhid->urbout);
+-				/*
+-				 * if the unlinking has already completed
+-				 * the pump will have been stopped
+-				 * it must be restarted now
+-				 */
+-				if (!test_bit(HID_OUT_RUNNING, &usbhid->iofl))
+-					if (!irq_out_pump_restart(hid))
+-						set_bit(HID_OUT_RUNNING, &usbhid->iofl);
++			usb_block_urb(usbhid->urbout);
+ 
++			/* Drop lock to avoid deadlock if the callback runs */
++			spin_unlock(&usbhid->lock);
+ 
+-			}
++			usb_unlink_urb(usbhid->urbout);
++			spin_lock(&usbhid->lock);
++			usb_unblock_urb(usbhid->urbout);
++
++			/* Unlink might have stopped the queue */
++			if (!test_bit(HID_OUT_RUNNING, &usbhid->iofl))
++				usbhid_restart_out_queue(usbhid);
++
++			/* Now we can allow autosuspend again */
++			usb_autopm_put_interface_async(usbhid->intf);
+ 		}
+ 		return;
+ 	}
+@@ -610,47 +619,36 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
+ 	usbhid->ctrl[usbhid->ctrlhead].dir = dir;
+ 	usbhid->ctrlhead = head;
+ 
+-	/* Try to awake from autosuspend... */
+-	if (usb_autopm_get_interface_async(usbhid->intf) < 0)
+-		return;
++	/* If the queue isn't running, restart it */
++	if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl)) {
++		usbhid_restart_ctrl_queue(usbhid);
+ 
+-	/*
+-	 * If already suspended, leave urb enqueued, but don't submit.
+-	 * Submission will occur if/when resume() drains the queue.
+-	 */
+-	if (test_bit(HID_REPORTED_IDLE, &usbhid->iofl))
+-		return;
++	/* Otherwise see if an earlier request has timed out */
++	} else if (time_after(jiffies, usbhid->last_ctrl + HZ * 5)) {
++
++		/* Prevent autosuspend following the unlink */
++		usb_autopm_get_interface_no_resume(usbhid->intf);
+ 
+-	if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl)) {
+-		if (hid_submit_ctrl(hid)) {
+-			clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
+-			usb_autopm_put_interface_async(usbhid->intf);
+-		}
+-		wake_up(&usbhid->wait);
+-	} else {
+ 		/*
+-		 * the queue is known to run
+-		 * but an earlier request may be stuck
+-		 * we may need to time out
+-		 * no race because the URB is blocked under
+-		 * spinlock
++		 * Prevent resubmission in case the URB completes
++		 * before we can unlink it.  We don't want to cancel
++		 * the wrong transfer!
+ 		 */
+-		if (time_after(jiffies, usbhid->last_ctrl + HZ * 5)) {
+-			usb_block_urb(usbhid->urbctrl);
+-			/* drop lock to not deadlock if the callback is called */
+-			spin_unlock(&usbhid->lock);
+-			usb_unlink_urb(usbhid->urbctrl);
+-			spin_lock(&usbhid->lock);
+-			usb_unblock_urb(usbhid->urbctrl);
+-			/*
+-			 * if the unlinking has already completed
+-			 * the pump will have been stopped
+-			 * it must be restarted now
+-			 */
+-			if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl))
+-				if (!ctrl_pump_restart(hid))
+-					set_bit(HID_CTRL_RUNNING, &usbhid->iofl);
+-		}
++		usb_block_urb(usbhid->urbctrl);
++
++		/* Drop lock to avoid deadlock if the callback runs */
++		spin_unlock(&usbhid->lock);
++
++		usb_unlink_urb(usbhid->urbctrl);
++		spin_lock(&usbhid->lock);
++		usb_unblock_urb(usbhid->urbctrl);
++
++		/* Unlink might have stopped the queue */
++		if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl))
++			usbhid_restart_ctrl_queue(usbhid);
++
++		/* Now we can allow autosuspend again */
++		usb_autopm_put_interface_async(usbhid->intf);
+ 	}
+ }
+ 

commit 668160e5a80536251b4931a332dfe34d6ec2aeb7
+Author: Alan Stern 
+Date:   Thu Jul 19 16:08:21 2012 -0400
+
+    HID: usbhid: fix use-after-free bug
+    
+    This patch (as1592) fixes an obscure problem in the usbhid driver.
+    Under some circumstances, a control or interrupt-OUT URB can be
+    submitted twice.  This will happen if the first submission fails; the
+    queue pointers aren't updated, so the next time the queue is restarted
+    the same URB will be submitted again.
+    
+    The problem is that raw_report gets deallocated during the first
+    submission.  The second submission will then dereference and try to
+    free an already-freed region of memory.  The patch fixes the problem
+    by setting raw_report to NULL when it is deallocated and checking for
+    NULL before dereferencing it.
+    
+    Signed-off-by: Alan Stern 
+    CC: Oliver Neukum 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index 482f936fc29b..6b9bad540702 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -331,9 +331,12 @@ static int hid_submit_out(struct hid_device *hid)
+ 	usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) +
+ 						 1 + (report->id > 0);
+ 	usbhid->urbout->dev = hid_to_usb_dev(hid);
+-	memcpy(usbhid->outbuf, raw_report,
+-	       usbhid->urbout->transfer_buffer_length);
+-	kfree(raw_report);
++	if (raw_report) {
++		memcpy(usbhid->outbuf, raw_report,
++				usbhid->urbout->transfer_buffer_length);
++		kfree(raw_report);
++		usbhid->out[usbhid->outtail].raw_report = NULL;
++	}
+ 
+ 	dbg_hid("submitting out urb\n");
+ 
+@@ -362,8 +365,11 @@ static int hid_submit_ctrl(struct hid_device *hid)
+ 	if (dir == USB_DIR_OUT) {
+ 		usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0);
+ 		usbhid->urbctrl->transfer_buffer_length = len;
+-		memcpy(usbhid->ctrlbuf, raw_report, len);
+-		kfree(raw_report);
++		if (raw_report) {
++			memcpy(usbhid->ctrlbuf, raw_report, len);
++			kfree(raw_report);
++			usbhid->ctrl[usbhid->ctrltail].raw_report = NULL;
++		}
+ 	} else {
+ 		int maxpacket, padlen;
+ 

commit 43fe3a99d9caf10b25f9c596e9854cdae30db418
+Author: Alan Stern 
+Date:   Wed Jul 11 11:23:16 2012 -0400
+
+    USB: EHCI: resolve some unlikely races
+    
+    This patch (as1589) resolves some unlikely races involving system
+    shutdown or controller death in ehci-hcd:
+    
+            Shutdown races with both root-hub resume and controller
+            resume.
+    
+            Controller death races with root-hub suspend.
+    
+    A new bitflag is added to indicate that the controller has been shut
+    down (whether for system shutdown or because it died).  Tests are
+    added in the suspend and resume pathways to avoid reactivating the
+    controller after any sort of shutdown.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index ac4c8ddde20a..e44ca5453aa2 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -343,6 +343,7 @@ static void ehci_shutdown(struct usb_hcd *hcd)
+ 	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
+ 
+ 	spin_lock_irq(&ehci->lock);
++	ehci->shutdown = true;
+ 	ehci->rh_state = EHCI_RH_STOPPING;
+ 	ehci->enabled_hrtimer_events = 0;
+ 	spin_unlock_irq(&ehci->lock);
+@@ -823,6 +824,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 		usb_hc_died(hcd);
+ 
+ 		/* Don't let the controller do anything more */
++		ehci->shutdown = true;
+ 		ehci->rh_state = EHCI_RH_STOPPING;
+ 		ehci->command &= ~(CMD_RUN | CMD_ASE | CMD_PSE);
+ 		ehci_writel(ehci, ehci->command, &ehci->regs->command);
+@@ -1129,6 +1131,9 @@ static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated)
+ 	/* Mark hardware accessible again as we are back to full power by now */
+ 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ 
++	if (ehci->shutdown)
++		return 0;		/* Controller is dead */
++
+ 	/*
+ 	 * If CF is still set and we aren't resuming from hibernation
+ 	 * then we maintained suspend power.
+@@ -1139,10 +1144,17 @@ static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated)
+ 		int	mask = INTR_MASK;
+ 
+ 		ehci_prepare_ports_for_controller_resume(ehci);
++
++		spin_lock_irq(&ehci->lock);
++		if (ehci->shutdown)
++			goto skip;
++
+ 		if (!hcd->self.root_hub->do_remote_wakeup)
+ 			mask &= ~STS_PCD;
+ 		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+ 		ehci_readl(ehci, &ehci->regs->intr_enable);
++ skip:
++		spin_unlock_irq(&ehci->lock);
+ 		return 0;
+ 	}
+ 
+@@ -1154,14 +1166,20 @@ static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated)
+ 	(void) ehci_halt(ehci);
+ 	(void) ehci_reset(ehci);
+ 
++	spin_lock_irq(&ehci->lock);
++	if (ehci->shutdown)
++		goto skip;
++
+ 	ehci_writel(ehci, ehci->command, &ehci->regs->command);
+ 	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
+ 	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
+ 
++	ehci->rh_state = EHCI_RH_SUSPENDED;
++	spin_unlock_irq(&ehci->lock);
++
+ 	/* here we "know" root ports should always stay powered */
+ 	ehci_port_power(ehci, 1);
+ 
+-	ehci->rh_state = EHCI_RH_SUSPENDED;
+ 	return 1;
+ }
+ 
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index ffc5f27df725..c7880223738a 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -221,6 +221,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 	ehci_quiesce(ehci);
+ 
+ 	spin_lock_irq (&ehci->lock);
++	if (ehci->rh_state < EHCI_RH_RUNNING)
++		goto done;
+ 
+ 	/* Once the controller is stopped, port resumes that are already
+ 	 * in progress won't complete.  Hence if remote wakeup is enabled
+@@ -306,6 +308,10 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 	ehci_halt (ehci);
+ 
+ 	spin_lock_irq(&ehci->lock);
++	if (ehci->enabled_hrtimer_events & BIT(EHCI_HRTIMER_POLL_DEAD))
++		ehci_handle_controller_death(ehci);
++	if (ehci->rh_state != EHCI_RH_RUNNING)
++		goto done;
+ 	ehci->rh_state = EHCI_RH_SUSPENDED;
+ 
+ 	end_unlink_async(ehci);
+@@ -320,6 +326,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 	ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+ 	ehci_readl(ehci, &ehci->regs->intr_enable);
+ 
++ done:
+ 	ehci->next_statechange = jiffies + msecs_to_jiffies(10);
+ 	ehci->enabled_hrtimer_events = 0;
+ 	ehci->next_hrtimer_event = EHCI_HRTIMER_NO_EVENT;
+@@ -342,10 +349,8 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 	if (time_before (jiffies, ehci->next_statechange))
+ 		msleep(5);
+ 	spin_lock_irq (&ehci->lock);
+-	if (!HCD_HW_ACCESSIBLE(hcd)) {
+-		spin_unlock_irq(&ehci->lock);
+-		return -ESHUTDOWN;
+-	}
++	if (!HCD_HW_ACCESSIBLE(hcd) || ehci->shutdown)
++		goto shutdown;
+ 
+ 	if (unlikely(ehci->debug)) {
+ 		if (!dbgp_reset_prep())
+@@ -384,6 +389,8 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 	spin_unlock_irq(&ehci->lock);
+ 	msleep(8);
+ 	spin_lock_irq(&ehci->lock);
++	if (ehci->shutdown)
++		goto shutdown;
+ 
+ 	/* clear phy low-power mode before resume */
+ 	if (ehci->bus_suspended && ehci->has_hostpc) {
+@@ -401,6 +408,8 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 		spin_unlock_irq(&ehci->lock);
+ 		msleep(5);
+ 		spin_lock_irq(&ehci->lock);
++		if (ehci->shutdown)
++			goto shutdown;
+ 	}
+ 
+ 	/* manually resume the ports we suspended during bus_suspend() */
+@@ -421,6 +430,8 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 		spin_unlock_irq(&ehci->lock);
+ 		msleep(20);
+ 		spin_lock_irq(&ehci->lock);
++		if (ehci->shutdown)
++			goto shutdown;
+ 	}
+ 
+ 	i = HCS_N_PORTS (ehci->hcs_params);
+@@ -439,10 +450,18 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 	ehci_handover_companion_ports(ehci);
+ 
+ 	/* Now we can safely re-enable irqs */
++	spin_lock_irq(&ehci->lock);
++	if (ehci->shutdown)
++		goto shutdown;
+ 	ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
+ 	(void) ehci_readl(ehci, &ehci->regs->intr_enable);
++	spin_unlock_irq(&ehci->lock);
+ 
+ 	return 0;
++
++ shutdown:
++	spin_unlock_irq(&ehci->lock);
++	return -ESHUTDOWN;
+ }
+ 
+ #else
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 7de58fe52d51..da07d98f7d1d 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -118,6 +118,7 @@ struct ehci_hcd {			/* one per controller */
+ 	bool			need_rescan:1;
+ 	bool			intr_unlinking:1;
+ 	bool			async_unlinking:1;
++	bool			shutdown:1;
+ 	struct ehci_qh		*qh_scan_next;
+ 
+ 	/* async schedule support */

commit c4f3476436f7452b97c8accb5dd7d53219a11a3f
+Author: Alan Stern 
+Date:   Wed Jul 11 11:23:10 2012 -0400
+
+    USB: EHCI: fix up locking
+    
+    This patch (as1588) adjusts the locking in ehci-hcd's various halt,
+    shutdown, and suspend/resume pathways.  We want to hold the spinlock
+    while writing device registers and accessing shared variables, but not
+    while polling in a loop.
+    
+    In addition, there's no need to call ehci_work() at times when no URBs
+    can be active, i.e., in ehci_stop() and ehci_bus_suspend().
+    
+    Finally, ehci_adjust_port_wakeup_flags() is called only in situations
+    where interrupts are enabled; therefore it can use spin_lock_irq
+    rather than spin_lock_irqsave.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 340c9c4894bf..ac4c8ddde20a 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -167,21 +167,24 @@ static int tdi_in_host_mode (struct ehci_hcd *ehci)
+ 	return (tmp & 3) == USBMODE_CM_HC;
+ }
+ 
+-/* force HC to halt state from unknown (EHCI spec section 2.3) */
++/*
++ * Force HC to halt state from unknown (EHCI spec section 2.3).
++ * Must be called with interrupts enabled and the lock not held.
++ */
+ static int ehci_halt (struct ehci_hcd *ehci)
+ {
+-	u32	temp = ehci_readl(ehci, &ehci->regs->status);
++	u32	temp;
++
++	spin_lock_irq(&ehci->lock);
+ 
+ 	/* disable any irqs left enabled by previous code */
+ 	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+ 
+-	if (ehci_is_TDI(ehci) && tdi_in_host_mode(ehci) == 0) {
++	if (ehci_is_TDI(ehci) && !tdi_in_host_mode(ehci)) {
++		spin_unlock_irq(&ehci->lock);
+ 		return 0;
+ 	}
+ 
+-	if ((temp & STS_HALT) != 0)
+-		return 0;
+-
+ 	/*
+ 	 * This routine gets called during probe before ehci->command
+ 	 * has been initialized, so we can't rely on its value.
+@@ -190,7 +193,11 @@ static int ehci_halt (struct ehci_hcd *ehci)
+ 	temp = ehci_readl(ehci, &ehci->regs->command);
+ 	temp &= ~(CMD_RUN | CMD_IAAD);
+ 	ehci_writel(ehci, temp, &ehci->regs->command);
+-	return handshake (ehci, &ehci->regs->status,
++
++	spin_unlock_irq(&ehci->lock);
++	synchronize_irq(ehci_to_hcd(ehci)->irq);
++
++	return handshake(ehci, &ehci->regs->status,
+ 			  STS_HALT, STS_HALT, 16 * 125);
+ }
+ 
+@@ -210,7 +217,10 @@ static void tdi_reset (struct ehci_hcd *ehci)
+ 	ehci_writel(ehci, tmp, &ehci->regs->usbmode);
+ }
+ 
+-/* reset a non-running (STS_HALT == 1) controller */
++/*
++ * Reset a non-running (STS_HALT == 1) controller.
++ * Must be called with interrupts enabled and the lock not held.
++ */
+ static int ehci_reset (struct ehci_hcd *ehci)
+ {
+ 	int	retval;
+@@ -248,7 +258,10 @@ static int ehci_reset (struct ehci_hcd *ehci)
+ 	return retval;
+ }
+ 
+-/* idle the controller (from running) */
++/*
++ * Idle the controller (turn off the schedules).
++ * Must be called with interrupts enabled and the lock not held.
++ */
+ static void ehci_quiesce (struct ehci_hcd *ehci)
+ {
+ 	u32	temp;
+@@ -261,8 +274,10 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
+ 	handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, temp, 16 * 125);
+ 
+ 	/* then disable anything that's still active */
++	spin_lock_irq(&ehci->lock);
+ 	ehci->command &= ~(CMD_ASE | CMD_PSE);
+ 	ehci_writel(ehci, ehci->command, &ehci->regs->command);
++	spin_unlock_irq(&ehci->lock);
+ 
+ 	/* hardware can take 16 microframes to turn off ... */
+ 	handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, 0, 16 * 125);
+@@ -301,11 +316,14 @@ static void ehci_turn_off_all_ports(struct ehci_hcd *ehci)
+ 
+ /*
+  * Halt HC, turn off all ports, and let the BIOS use the companion controllers.
+- * Should be called with ehci->lock held.
++ * Must be called with interrupts enabled and the lock not held.
+  */
+ static void ehci_silence_controller(struct ehci_hcd *ehci)
+ {
+ 	ehci_halt(ehci);
++
++	spin_lock_irq(&ehci->lock);
++	ehci->rh_state = EHCI_RH_HALTED;
+ 	ehci_turn_off_all_ports(ehci);
+ 
+ 	/* make BIOS/etc use companion controller during reboot */
+@@ -313,6 +331,7 @@ static void ehci_silence_controller(struct ehci_hcd *ehci)
+ 
+ 	/* unblock posted writes */
+ 	ehci_readl(ehci, &ehci->regs->configured_flag);
++	spin_unlock_irq(&ehci->lock);
+ }
+ 
+ /* ehci_shutdown kick in for silicon on any bus (not just pci, etc).
+@@ -325,10 +344,11 @@ static void ehci_shutdown(struct usb_hcd *hcd)
+ 
+ 	spin_lock_irq(&ehci->lock);
+ 	ehci->rh_state = EHCI_RH_STOPPING;
+-	ehci_silence_controller(ehci);
+ 	ehci->enabled_hrtimer_events = 0;
+ 	spin_unlock_irq(&ehci->lock);
+ 
++	ehci_silence_controller(ehci);
++
+ 	hrtimer_cancel(&ehci->hrtimer);
+ }
+ 
+@@ -400,11 +420,11 @@ static void ehci_stop (struct usb_hcd *hcd)
+ 
+ 	spin_lock_irq(&ehci->lock);
+ 	ehci->enabled_hrtimer_events = 0;
+-	ehci_quiesce(ehci);
++	spin_unlock_irq(&ehci->lock);
+ 
++	ehci_quiesce(ehci);
+ 	ehci_silence_controller(ehci);
+ 	ehci_reset (ehci);
+-	spin_unlock_irq(&ehci->lock);
+ 
+ 	hrtimer_cancel(&ehci->hrtimer);
+ 	remove_sysfs_files(ehci);
+@@ -412,8 +432,6 @@ static void ehci_stop (struct usb_hcd *hcd)
+ 
+ 	/* root hub is shut down separately (first, when possible) */
+ 	spin_lock_irq (&ehci->lock);
+-	if (ehci->async)
+-		ehci_work (ehci);
+ 	end_free_itds(ehci);
+ 	spin_unlock_irq (&ehci->lock);
+ 	ehci_mem_cleanup (ehci);
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 05490d387fd2..ffc5f27df725 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -59,6 +59,7 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
+ 	/* Give the connections some time to appear */
+ 	msleep(20);
+ 
++	spin_lock_irq(&ehci->lock);
+ 	port = HCS_N_PORTS(ehci->hcs_params);
+ 	while (port--) {
+ 		if (test_bit(port, &ehci->owned_ports)) {
+@@ -70,23 +71,30 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
+ 				clear_bit(port, &ehci->owned_ports);
+ 			else if (test_bit(port, &ehci->companion_ports))
+ 				ehci_writel(ehci, status & ~PORT_PE, reg);
+-			else
++			else {
++				spin_unlock_irq(&ehci->lock);
+ 				ehci_hub_control(hcd, SetPortFeature,
+ 						USB_PORT_FEAT_RESET, port + 1,
+ 						NULL, 0);
++				spin_lock_irq(&ehci->lock);
++			}
+ 		}
+ 	}
++	spin_unlock_irq(&ehci->lock);
+ 
+ 	if (!ehci->owned_ports)
+ 		return;
+ 	msleep(90);		/* Wait for resets to complete */
+ 
++	spin_lock_irq(&ehci->lock);
+ 	port = HCS_N_PORTS(ehci->hcs_params);
+ 	while (port--) {
+ 		if (test_bit(port, &ehci->owned_ports)) {
++			spin_unlock_irq(&ehci->lock);
+ 			ehci_hub_control(hcd, GetPortStatus,
+ 					0, port + 1,
+ 					(char *) &buf, sizeof(buf));
++			spin_lock_irq(&ehci->lock);
+ 
+ 			/* The companion should now own the port,
+ 			 * but if something went wrong the port must not
+@@ -105,6 +113,7 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
+ 	}
+ 
+ 	ehci->owned_ports = 0;
++	spin_unlock_irq(&ehci->lock);
+ }
+ 
+ static int ehci_port_change(struct ehci_hcd *ehci)
+@@ -133,7 +142,6 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
+ {
+ 	int		port;
+ 	u32		temp;
+-	unsigned long	flags;
+ 
+ 	/* If remote wakeup is enabled for the root hub but disabled
+ 	 * for the controller, we must adjust all the port wakeup flags
+@@ -143,7 +151,7 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
+ 	if (!ehci_to_hcd(ehci)->self.root_hub->do_remote_wakeup || do_wakeup)
+ 		return;
+ 
+-	spin_lock_irqsave(&ehci->lock, flags);
++	spin_lock_irq(&ehci->lock);
+ 
+ 	/* clear phy low-power mode before changing wakeup flags */
+ 	if (ehci->has_hostpc) {
+@@ -154,9 +162,9 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
+ 			temp = ehci_readl(ehci, hostpc_reg);
+ 			ehci_writel(ehci, temp & ~HOSTPC_PHCD, hostpc_reg);
+ 		}
+-		spin_unlock_irqrestore(&ehci->lock, flags);
++		spin_unlock_irq(&ehci->lock);
+ 		msleep(5);
+-		spin_lock_irqsave(&ehci->lock, flags);
++		spin_lock_irq(&ehci->lock);
+ 	}
+ 
+ 	port = HCS_N_PORTS(ehci->hcs_params);
+@@ -194,7 +202,7 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
+ 	if (!suspending && ehci_port_change(ehci))
+ 		usb_hcd_resume_root_hub(ehci_to_hcd(ehci));
+ 
+-	spin_unlock_irqrestore(&ehci->lock, flags);
++	spin_unlock_irq(&ehci->lock);
+ }
+ 
+ static int ehci_bus_suspend (struct usb_hcd *hcd)
+@@ -209,6 +217,9 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 	if (time_before (jiffies, ehci->next_statechange))
+ 		msleep(5);
+ 
++	/* stop the schedules */
++	ehci_quiesce(ehci);
++
+ 	spin_lock_irq (&ehci->lock);
+ 
+ 	/* Once the controller is stopped, port resumes that are already
+@@ -224,10 +235,6 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 		}
+ 	}
+ 
+-	/* stop schedules, clean any completed work */
+-	ehci_quiesce(ehci);
+-	ehci_work(ehci);
+-
+ 	/* Unlike other USB host controller types, EHCI doesn't have
+ 	 * any notion of "global" or bus-wide suspend.  The driver has
+ 	 * to manually suspend all the active unsuspended ports, and
+@@ -289,6 +296,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 					"succeeded" : "failed");
+ 		}
+ 	}
++	spin_unlock_irq(&ehci->lock);
+ 
+ 	/* Apparently some devices need a >= 1-uframe delay here */
+ 	if (ehci->bus_suspended)
+@@ -296,6 +304,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 
+ 	/* turn off now-idle HC */
+ 	ehci_halt (ehci);
++
++	spin_lock_irq(&ehci->lock);
+ 	ehci->rh_state = EHCI_RH_SUSPENDED;
+ 
+ 	end_unlink_async(ehci);
+@@ -424,13 +434,14 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 	}
+ 
+ 	ehci->next_statechange = jiffies + msecs_to_jiffies(5);
++	spin_unlock_irq(&ehci->lock);
++
++	ehci_handover_companion_ports(ehci);
+ 
+ 	/* Now we can safely re-enable irqs */
+ 	ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
+ 	(void) ehci_readl(ehci, &ehci->regs->intr_enable);
+ 
+-	spin_unlock_irq (&ehci->lock);
+-	ehci_handover_companion_ports(ehci);
+ 	return 0;
+ }
+ 
+@@ -1018,7 +1029,9 @@ static int ehci_hub_control (
+ 		case USB_PORT_FEAT_TEST:
+ 			if (!selector || selector > 5)
+ 				goto error;
++			spin_unlock_irqrestore(&ehci->lock, flags);
+ 			ehci_quiesce(ehci);
++			spin_lock_irqsave(&ehci->lock, flags);
+ 
+ 			/* Put all enabled ports into suspend */
+ 			while (ports--) {
+@@ -1030,7 +1043,11 @@ static int ehci_hub_control (
+ 					ehci_writel(ehci, temp | PORT_SUSPEND,
+ 							sreg);
+ 			}
++
++			spin_unlock_irqrestore(&ehci->lock, flags);
+ 			ehci_halt(ehci);
++			spin_lock_irqsave(&ehci->lock, flags);
++
+ 			temp = ehci_readl(ehci, status_reg);
+ 			temp |= selector << 16;
+ 			ehci_writel(ehci, temp, status_reg);
+diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
+index f7f3ce3275b8..65360945df78 100644
+--- a/drivers/usb/host/ehci-tegra.c
++++ b/drivers/usb/host/ehci-tegra.c
+@@ -445,12 +445,11 @@ static int controller_suspend(struct device *dev)
+ 	if (time_before(jiffies, ehci->next_statechange))
+ 		msleep(10);
+ 
+-	spin_lock_irqsave(&ehci->lock, flags);
++	ehci_halt(ehci);
+ 
++	spin_lock_irqsave(&ehci->lock, flags);
+ 	tegra->port_speed = (readl(&hw->port_status[0]) >> 26) & 0x3;
+-	ehci_halt(ehci);
+ 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+-
+ 	spin_unlock_irqrestore(&ehci->lock, flags);
+ 
+ 	tegra_ehci_power_down(hcd);

commit f42890782241a60d107f23d08089a4a12b507a11
+Author: Alan Stern 
+Date:   Wed Jul 11 11:23:07 2012 -0400
+
+    USB: EHCI: simplify isochronous scanning
+    
+    This patch (as1587) simplifies ehci-hcd's scan_isoc() routine by
+    eliminating some local variables, declaring boolean-valued values as
+    bool rather than unsigned, changing variable names to make more sense,
+    and so on.
+    
+    The logic at the end of the routine is cut down significantly.  The
+    scanning doesn't have to catch up all the way to where the hardware
+    is; it merely has to catch up to where the hardware was when the last
+    interrupt occurred.  If the hardware has made more progress since then
+    and issued another interrupt, a rescan will catch up to it.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 9f26080889f5..340c9c4894bf 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -488,9 +488,6 @@ static int ehci_init(struct usb_hcd *hcd)
+ 	else					// N microframes cached
+ 		ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params);
+ 
+-	ehci->next_uframe = -1;
+-	ehci->clock_frame = -1;
+-
+ 	/*
+ 	 * dedicate a qh for the async ring head, since we couldn't unlink
+ 	 * a 'real' qh without stopping the async schedule [4.8].  use it
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 26ce8fef0e5b..7cf3da7babf0 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -497,8 +497,6 @@ static void disable_periodic(struct ehci_hcd *ehci)
+ 	if (--ehci->periodic_count)
+ 		return;
+ 
+-	ehci->next_uframe = -1;		/* the periodic schedule is empty */
+-
+ 	/* Don't turn off the schedule until PSS is 1 */
+ 	ehci_poll_PSS(ehci);
+ }
+@@ -1220,7 +1218,7 @@ itd_urb_transaction (
+ 		if (likely(!list_empty(&stream->free_list))) {
+ 			itd = list_first_entry(&stream->free_list,
+ 					struct ehci_itd, itd_list);
+-			if (itd->frame == ehci->clock_frame)
++			if (itd->frame == ehci->now_frame)
+ 				goto alloc_itd;
+ 			list_del (&itd->itd_list);
+ 			itd_dma = itd->itd_dma;
+@@ -1492,7 +1490,7 @@ iso_stream_schedule (
+ 
+ 	/* Make sure scan_isoc() sees these */
+ 	if (ehci->isoc_count == 0)
+-		ehci->next_uframe = now;
++		ehci->next_frame = now >> 3;
+ 	return 0;
+ 
+  fail:
+@@ -1666,11 +1664,8 @@ static void itd_link_urb(
+  * (b) only this endpoint's completions submit URBs.  It seems some silicon
+  * corrupts things if you reuse completed descriptors very quickly...
+  */
+-static unsigned
+-itd_complete (
+-	struct ehci_hcd	*ehci,
+-	struct ehci_itd	*itd
+-) {
++static bool itd_complete(struct ehci_hcd *ehci, struct ehci_itd *itd)
++{
+ 	struct urb				*urb = itd->urb;
+ 	struct usb_iso_packet_descriptor	*desc;
+ 	u32					t;
+@@ -1678,7 +1673,7 @@ itd_complete (
+ 	int					urb_index = -1;
+ 	struct ehci_iso_stream			*stream = itd->stream;
+ 	struct usb_device			*dev;
+-	unsigned				retval = false;
++	bool					retval = false;
+ 
+ 	/* for each uframe with a packet */
+ 	for (uframe = 0; uframe < 8; uframe++) {
+@@ -1917,7 +1912,7 @@ sitd_urb_transaction (
+ 		if (likely(!list_empty(&stream->free_list))) {
+ 			sitd = list_first_entry(&stream->free_list,
+ 					 struct ehci_sitd, sitd_list);
+-			if (sitd->frame == ehci->clock_frame)
++			if (sitd->frame == ehci->now_frame)
+ 				goto alloc_sitd;
+ 			list_del (&sitd->sitd_list);
+ 			sitd_dma = sitd->sitd_dma;
+@@ -2071,18 +2066,15 @@ static void sitd_link_urb(
+  * (b) only this endpoint's completions submit URBs.  It seems some silicon
+  * corrupts things if you reuse completed descriptors very quickly...
+  */
+-static unsigned
+-sitd_complete (
+-	struct ehci_hcd		*ehci,
+-	struct ehci_sitd	*sitd
+-) {
++static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd)
++{
+ 	struct urb				*urb = sitd->urb;
+ 	struct usb_iso_packet_descriptor	*desc;
+ 	u32					t;
+ 	int					urb_index = -1;
+ 	struct ehci_iso_stream			*stream = sitd->stream;
+ 	struct usb_device			*dev;
+-	unsigned				retval = false;
++	bool					retval = false;
+ 
+ 	urb_index = sitd->index;
+ 	desc = &urb->iso_frame_desc [urb_index];
+@@ -2214,34 +2206,29 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
+ 
+ static void scan_isoc(struct ehci_hcd *ehci)
+ {
+-	unsigned	now_uframe, frame, clock, clock_frame, mod;
+-	unsigned	modified;
+-
+-	mod = ehci->periodic_size << 3;
++	unsigned	uf, now_frame, frame;
++	unsigned	fmask = ehci->periodic_size - 1;
++	bool		modified, live;
+ 
+ 	/*
+ 	 * When running, scan from last scan point up to "now"
+ 	 * else clean up by scanning everything that's left.
+ 	 * Touches as few pages as possible:  cache-friendly.
+ 	 */
+-	now_uframe = ehci->next_uframe;
+ 	if (ehci->rh_state >= EHCI_RH_RUNNING) {
+-		clock = ehci_read_frame_index(ehci);
+-		clock_frame = (clock >> 3) & (ehci->periodic_size - 1);
++		uf = ehci_read_frame_index(ehci);
++		now_frame = (uf >> 3) & fmask;
++		live = true;
+ 	} else  {
+-		clock = now_uframe + mod - 1;
+-		clock_frame = -1;
++		now_frame = (ehci->next_frame - 1) & fmask;
++		live = false;
+ 	}
+-	ehci->clock_frame = clock_frame;
+-	clock &= mod - 1;
+-	clock_frame = clock >> 3;
++	ehci->now_frame = now_frame;
+ 
++	frame = ehci->next_frame;
+ 	for (;;) {
+ 		union ehci_shadow	q, *q_p;
+ 		__hc32			type, *hw_p;
+-		unsigned		incomplete = false;
+-
+-		frame = now_uframe >> 3;
+ 
+ restart:
+ 		/* scan each element in frame's queue for completions */
+@@ -2249,13 +2236,9 @@ static void scan_isoc(struct ehci_hcd *ehci)
+ 		hw_p = &ehci->periodic [frame];
+ 		q.ptr = q_p->ptr;
+ 		type = Q_NEXT_TYPE(ehci, *hw_p);
+-		modified = 0;
++		modified = false;
+ 
+ 		while (q.ptr != NULL) {
+-			unsigned		uf;
+-			int			live;
+-
+-			live = (ehci->rh_state >= EHCI_RH_RUNNING);
+ 			switch (hc32_to_cpu(ehci, type)) {
+ 			case Q_TYPE_ITD:
+ 				/* If this ITD is still active, leave it for
+@@ -2263,7 +2246,7 @@ static void scan_isoc(struct ehci_hcd *ehci)
+ 				 * No need to check for activity unless the
+ 				 * frame is current.
+ 				 */
+-				if (frame == clock_frame && live) {
++				if (frame == now_frame && live) {
+ 					rmb();
+ 					for (uf = 0; uf < 8; uf++) {
+ 						if (q.itd->hw_transaction[uf] &
+@@ -2271,7 +2254,6 @@ static void scan_isoc(struct ehci_hcd *ehci)
+ 							break;
+ 					}
+ 					if (uf < 8) {
+-						incomplete = true;
+ 						q_p = &q.itd->itd_next;
+ 						hw_p = &q.itd->hw_next;
+ 						type = Q_NEXT_TYPE(ehci,
+@@ -2303,14 +2285,12 @@ static void scan_isoc(struct ehci_hcd *ehci)
+ 				 * No need to check for activity unless the
+ 				 * frame is current.
+ 				 */
+-				if (((frame == clock_frame) ||
+-				     (((frame + 1) & (ehci->periodic_size - 1))
+-				      == clock_frame))
++				if (((frame == now_frame) ||
++				     (((frame + 1) & fmask) == now_frame))
+ 				    && live
+ 				    && (q.sitd->hw_results &
+ 					SITD_ACTIVE(ehci))) {
+ 
+-					incomplete = true;
+ 					q_p = &q.sitd->sitd_next;
+ 					hw_p = &q.sitd->hw_next;
+ 					type = Q_NEXT_TYPE(ehci,
+@@ -2347,50 +2327,14 @@ static void scan_isoc(struct ehci_hcd *ehci)
+ 			}
+ 
+ 			/* assume completion callbacks modify the queue */
+-			if (unlikely (modified)) {
+-				if (likely(ehci->isoc_count > 0))
+-					goto restart;
+-				/* short-circuit this scan */
+-				now_uframe = clock;
+-				break;
+-			}
++			if (unlikely(modified && ehci->isoc_count > 0))
++				goto restart;
+ 		}
+ 
+-		/* If we can tell we caught up to the hardware, stop now.
+-		 * We can't advance our scan without collecting the ISO
+-		 * transfers that are still pending in this frame.
+-		 */
+-		if (incomplete && ehci->rh_state >= EHCI_RH_RUNNING) {
+-			ehci->next_uframe = now_uframe;
++		/* Stop when we have reached the current frame */
++		if (frame == now_frame)
+ 			break;
+-		}
+-
+-		// FIXME:  this assumes we won't get lapped when
+-		// latencies climb; that should be rare, but...
+-		// detect it, and just go all the way around.
+-		// FLR might help detect this case, so long as latencies
+-		// don't exceed periodic_size msec (default 1.024 sec).
+-
+-		// FIXME:  likewise assumes HC doesn't halt mid-scan
+-
+-		if (now_uframe == clock) {
+-			unsigned	now;
+-
+-			if (ehci->rh_state < EHCI_RH_RUNNING
+-					|| ehci->isoc_count == 0)
+-				break;
+-			ehci->next_uframe = now_uframe;
+-			now = ehci_read_frame_index(ehci) & (mod - 1);
+-			if (now_uframe == now)
+-				break;
+-
+-			/* rescan the rest of this frame, then ... */
+-			clock = now;
+-			clock_frame = clock >> 3;
+-			ehci->clock_frame = clock_frame;
+-		} else {
+-			now_uframe++;
+-			now_uframe &= mod - 1;
+-		}
++		frame = (frame + 1) & fmask;
+ 	}
++	ehci->next_frame = now_frame;
+ }
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 254f414bd0bd..7de58fe52d51 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -141,19 +141,19 @@ struct ehci_hcd {			/* one per controller */
+ 	struct ehci_qh		*intr_unlink;
+ 	struct ehci_qh		*intr_unlink_last;
+ 	unsigned		intr_unlink_cycle;
+-	int			next_uframe;	/* scan periodic, start here */
++	unsigned		now_frame;	/* frame from HC hardware */
++	unsigned		next_frame;	/* scan periodic, start here */
+ 	unsigned		intr_count;	/* intr activity count */
+ 	unsigned		isoc_count;	/* isoc activity count */
+ 	unsigned		periodic_count;	/* periodic activity count */
+ 	unsigned		uframe_periodic_max; /* max periodic time per uframe */
+ 
+ 
+-	/* list of itds & sitds completed while clock_frame was still active */
++	/* list of itds & sitds completed while now_frame was still active */
+ 	struct list_head	cached_itd_list;
+ 	struct ehci_itd		*last_itd_to_free;
+ 	struct list_head	cached_sitd_list;
+ 	struct ehci_sitd	*last_sitd_to_free;
+-	unsigned		clock_frame;
+ 
+ 	/* per root hub port */
+ 	unsigned long		reset_done [EHCI_MAX_ROOT_PORTS];

commit 18aafe64d75d0e27dae206cacf4171e4e485d285
+Author: Alan Stern 
+Date:   Wed Jul 11 11:23:04 2012 -0400
+
+    USB: EHCI: use hrtimer for the I/O watchdog
+    
+    This patch (as1586) replaces the kernel timer used by ehci-hcd as an
+    I/O watchdog with an hrtimer event.
+    
+    Unlike in the current code, the watchdog event is now always enabled
+    whenever any isochronous URBs are active.  This will prevent bugs
+    caused by the periodic schedule wrapping around with no completion
+    interrupts; the watchdog handler is guaranteed to scan the isochronous
+    transfers at least once during each iteration of the schedule.  The
+    extra overhead will be negligible: one timer interrupt every 100 ms.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index c13dad8a8503..9f26080889f5 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -93,8 +93,6 @@ static const char	hcd_name [] = "ehci_hcd";
+  */
+ #define	EHCI_TUNE_FLS		1	/* (medium) 512-frame schedule */
+ 
+-#define EHCI_IO_JIFFIES		(HZ/10)		/* io watchdog > irq_thresh */
+-
+ /* Initial IRQ latency:  faster than hw default */
+ static int log2_irq_thresh = 0;		// 0 to 6
+ module_param (log2_irq_thresh, int, S_IRUGO);
+@@ -125,25 +123,6 @@ MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us");
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-static void
+-timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action)
+-{
+-	if (!test_and_set_bit(action, &ehci->actions)) {
+-		unsigned long t;
+-
+-		switch (action) {
+-		case TIMER_IO_WATCHDOG:
+-			if (!ehci->need_io_watchdog)
+-				return;
+-			t = EHCI_IO_JIFFIES;
+-			break;
+-		}
+-		mod_timer(&ehci->watchdog, t + jiffies);
+-	}
+-}
+-
+-/*-------------------------------------------------------------------------*/
+-
+ /*
+  * handshake - spin reading hc until handshake completes or fails
+  * @ptr: address of hc register to be read
+@@ -307,19 +286,6 @@ static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh);
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-static void ehci_watchdog(unsigned long param)
+-{
+-	struct ehci_hcd		*ehci = (struct ehci_hcd *) param;
+-	unsigned long		flags;
+-
+-	spin_lock_irqsave(&ehci->lock, flags);
+-
+-	/* ehci could run by timer, without IRQs ... */
+-	ehci_work (ehci);
+-
+-	spin_unlock_irqrestore (&ehci->lock, flags);
+-}
+-
+ /* On some systems, leaving remote wakeup enabled prevents system shutdown.
+  * The firmware seems to think that powering off is a wakeup event!
+  * This routine turns off remote wakeup and everything else, on all ports.
+@@ -357,8 +323,6 @@ static void ehci_shutdown(struct usb_hcd *hcd)
+ {
+ 	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
+ 
+-	del_timer_sync(&ehci->watchdog);
+-
+ 	spin_lock_irq(&ehci->lock);
+ 	ehci->rh_state = EHCI_RH_STOPPING;
+ 	ehci_silence_controller(ehci);
+@@ -394,8 +358,6 @@ static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
+  */
+ static void ehci_work (struct ehci_hcd *ehci)
+ {
+-	timer_action_done (ehci, TIMER_IO_WATCHDOG);
+-
+ 	/* another CPU may drop ehci->lock during a schedule scan while
+ 	 * it reports urb completions.  this flag guards against bogus
+ 	 * attempts at re-entrant schedule scanning.
+@@ -422,10 +384,7 @@ static void ehci_work (struct ehci_hcd *ehci)
+ 	 * misplace IRQs, and should let us run completely without IRQs.
+ 	 * such lossage has been observed on both VT6202 and VT8235.
+ 	 */
+-	if (ehci->rh_state == EHCI_RH_RUNNING &&
+-			(ehci->async->qh_next.ptr != NULL ||
+-			 ehci->periodic_count != 0))
+-		timer_action (ehci, TIMER_IO_WATCHDOG);
++	turn_on_io_watchdog(ehci);
+ }
+ 
+ /*
+@@ -438,7 +397,6 @@ static void ehci_stop (struct usb_hcd *hcd)
+ 	ehci_dbg (ehci, "stop\n");
+ 
+ 	/* no more interrupts ... */
+-	del_timer_sync (&ehci->watchdog);
+ 
+ 	spin_lock_irq(&ehci->lock);
+ 	ehci->enabled_hrtimer_events = 0;
+@@ -490,9 +448,6 @@ static int ehci_init(struct usb_hcd *hcd)
+ 	 * keep io watchdog by default, those good HCDs could turn off it later
+ 	 */
+ 	ehci->need_io_watchdog = 1;
+-	init_timer(&ehci->watchdog);
+-	ehci->watchdog.function = ehci_watchdog;
+-	ehci->watchdog.data = (unsigned long) ehci;
+ 
+ 	hrtimer_init(&ehci->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+ 	ehci->hrtimer.function = ehci_hrtimer_func;
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 5d84562e2716..05490d387fd2 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -208,7 +208,6 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 
+ 	if (time_before (jiffies, ehci->next_statechange))
+ 		msleep(5);
+-	del_timer_sync(&ehci->watchdog);
+ 
+ 	spin_lock_irq (&ehci->lock);
+ 
+@@ -316,10 +315,6 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 	ehci->next_hrtimer_event = EHCI_HRTIMER_NO_EVENT;
+ 	spin_unlock_irq (&ehci->lock);
+ 
+-	/* ehci_work() may have re-enabled the watchdog timer, which we do not
+-	 * want, and so we must delete any pending watchdog timer events.
+-	 */
+-	del_timer_sync(&ehci->watchdog);
+ 	hrtimer_cancel(&ehci->hrtimer);
+ 	return 0;
+ }
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index c9c7f7b3b7db..9bc39ca460c8 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -970,6 +970,7 @@ static void enable_async(struct ehci_hcd *ehci)
+ 
+ 	/* Don't start the schedule until ASS is 0 */
+ 	ehci_poll_ASS(ehci);
++	turn_on_io_watchdog(ehci);
+ }
+ 
+ static void disable_async(struct ehci_hcd *ehci)
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 263b542985c0..26ce8fef0e5b 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -489,6 +489,7 @@ static void enable_periodic(struct ehci_hcd *ehci)
+ 
+ 	/* Don't start the schedule until PSS is 0 */
+ 	ehci_poll_PSS(ehci);
++	turn_on_io_watchdog(ehci);
+ }
+ 
+ static void disable_periodic(struct ehci_hcd *ehci)
+@@ -1649,7 +1650,6 @@ static void itd_link_urb(
+ 	iso_sched_free (stream, iso_sched);
+ 	urb->hcpriv = NULL;
+ 
+-	timer_action (ehci, TIMER_IO_WATCHDOG);
+ 	++ehci->isoc_count;
+ 	enable_periodic(ehci);
+ }
+@@ -2052,7 +2052,6 @@ static void sitd_link_urb(
+ 	iso_sched_free (stream, sched);
+ 	urb->hcpriv = NULL;
+ 
+-	timer_action (ehci, TIMER_IO_WATCHDOG);
+ 	++ehci->isoc_count;
+ 	enable_periodic(ehci);
+ }
+diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
+index 0e28bae78d18..eb896a2c8f2e 100644
+--- a/drivers/usb/host/ehci-timer.c
++++ b/drivers/usb/host/ehci-timer.c
+@@ -76,6 +76,7 @@ static unsigned event_delays_ns[] = {
+ 	10 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_IAA_WATCHDOG */
+ 	10 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_DISABLE_PERIODIC */
+ 	15 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_DISABLE_ASYNC */
++	100 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_IO_WATCHDOG */
+ };
+ 
+ /* Enable a pending hrtimer event */
+@@ -332,6 +333,25 @@ static void ehci_iaa_watchdog(struct ehci_hcd *ehci)
+ }
+ 
+ 
++/* Enable the I/O watchdog, if appropriate */
++static void turn_on_io_watchdog(struct ehci_hcd *ehci)
++{
++	/* Not needed if the controller isn't running or it's already enabled */
++	if (ehci->rh_state != EHCI_RH_RUNNING ||
++			(ehci->enabled_hrtimer_events &
++				BIT(EHCI_HRTIMER_IO_WATCHDOG)))
++		return;
++
++	/*
++	 * Isochronous transfers always need the watchdog.
++	 * For other sorts we use it only if the flag is set.
++	 */
++	if (ehci->isoc_count > 0 || (ehci->need_io_watchdog &&
++			ehci->async_count + ehci->intr_count > 0))
++		ehci_enable_event(ehci, EHCI_HRTIMER_IO_WATCHDOG, true);
++}
++
++
+ /*
+  * Handler functions for the hrtimer event types.
+  * Keep this array in the same order as the event types indexed by
+@@ -347,6 +367,7 @@ static void (*event_handlers[])(struct ehci_hcd *) = {
+ 	ehci_iaa_watchdog,		/* EHCI_HRTIMER_IAA_WATCHDOG */
+ 	ehci_disable_PSE,		/* EHCI_HRTIMER_DISABLE_PERIODIC */
+ 	ehci_disable_ASE,		/* EHCI_HRTIMER_DISABLE_ASYNC */
++	ehci_work,			/* EHCI_HRTIMER_IO_WATCHDOG */
+ };
+ 
+ static enum hrtimer_restart ehci_hrtimer_func(struct hrtimer *t)
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 08637183aad0..254f414bd0bd 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -88,6 +88,7 @@ enum ehci_hrtimer_event {
+ 	EHCI_HRTIMER_IAA_WATCHDOG,	/* Handle lost IAA interrupts */
+ 	EHCI_HRTIMER_DISABLE_PERIODIC,	/* Wait to disable periodic sched */
+ 	EHCI_HRTIMER_DISABLE_ASYNC,	/* Wait to disable async sched */
++	EHCI_HRTIMER_IO_WATCHDOG,	/* Check for missing IRQs */
+ 	EHCI_HRTIMER_NUM_EVENTS		/* Must come last */
+ };
+ #define EHCI_HRTIMER_NO_EVENT	99
+@@ -177,8 +178,6 @@ struct ehci_hcd {			/* one per controller */
+ 	struct dma_pool		*itd_pool;	/* itd per iso urb */
+ 	struct dma_pool		*sitd_pool;	/* sitd per split iso urb */
+ 
+-	struct timer_list	watchdog;
+-	unsigned long		actions;
+ 	unsigned		random_frame;
+ 	unsigned long		next_statechange;
+ 	ktime_t			last_periodic_enable;
+@@ -235,16 +234,6 @@ static inline struct usb_hcd *ehci_to_hcd (struct ehci_hcd *ehci)
+ 	return container_of ((void *) ehci, struct usb_hcd, hcd_priv);
+ }
+ 
+-enum ehci_timer_action {
+-	TIMER_IO_WATCHDOG,
+-};
+-
+-static inline void
+-timer_action_done (struct ehci_hcd *ehci, enum ehci_timer_action action)
+-{
+-	clear_bit (action, &ehci->actions);
+-}
+-
+ /*-------------------------------------------------------------------------*/
+ 
+ #include 

commit 569b394f53f0abd177cc665c9b4ace89e3f4c7fb
+Author: Alan Stern 
+Date:   Wed Jul 11 11:23:00 2012 -0400
+
+    USB: EHCI: always scan each interrupt QH
+    
+    This patch (as1585) fixes a bug in ehci-hcd's scheme for scanning
+    interrupt QHs.
+    
+    Currently a single routine takes care of scanning everything on the
+    periodic schedule.  Whenever an interrupt occurs, it scans all
+    isochronous and interrupt URBs scheduled for frames that have elapsed
+    since the last scan.
+    
+    This has two disadvantages.  The first is relatively minor: An
+    interrupt QH is likely to end up getting scanned multiple times,
+    particularly if the last scan was not fairly recent.  (The current
+    code avoids this by maintaining a periodic_stamp in each interrupt
+    QH.)
+    
+    The second is more serious.  The periodic schedule wraps around.  If
+    the last scan occurred during frame N, and the next scan occurs when
+    the schedule has gone through an entire cycle and is back at frame N,
+    the scanning code won't look at any frames other than N.  Consequently
+    it won't see any QHs that completed during frame N-1 or earlier.
+    
+    The patch replaces the entire frame-based approach for scanning
+    interrupt QHs with a new routine using a list-based approach, the same
+    as for async QHs.  This has a slight disadvantage, because it means
+    that all interrupt QHs have to be scanned every time.  But it is more
+    robust than the current approach.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index f6cf1d178107..c13dad8a8503 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -410,8 +410,10 @@ static void ehci_work (struct ehci_hcd *ehci)
+ 	ehci->need_rescan = false;
+ 	if (ehci->async_count)
+ 		scan_async(ehci);
+-	if (ehci->next_uframe != -1)
+-		scan_periodic (ehci);
++	if (ehci->intr_count > 0)
++		scan_intr(ehci);
++	if (ehci->isoc_count > 0)
++		scan_isoc(ehci);
+ 	if (ehci->need_rescan)
+ 		goto rescan;
+ 	ehci->scanning = false;
+@@ -509,6 +511,7 @@ static int ehci_init(struct usb_hcd *hcd)
+ 	 * periodic_size can shrink by USBCMD update if hcc_params allows.
+ 	 */
+ 	ehci->periodic_size = DEFAULT_I_TDPS;
++	INIT_LIST_HEAD(&ehci->intr_qh_list);
+ 	INIT_LIST_HEAD(&ehci->cached_itd_list);
+ 	INIT_LIST_HEAD(&ehci->cached_sitd_list);
+ 
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index bae931767825..c9c7f7b3b7db 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -322,7 +322,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	 *
+ 	 * It's a bug for qh->qh_state to be anything other than
+ 	 * QH_STATE_IDLE, unless our caller is scan_async() or
+-	 * scan_periodic().
++	 * scan_intr().
+ 	 */
+ 	state = qh->qh_state;
+ 	qh->qh_state = QH_STATE_COMPLETING;
+@@ -832,7 +832,6 @@ qh_make (
+ 				is_input, 0,
+ 				hb_mult(maxp) * max_packet(maxp)));
+ 		qh->start = NO_FRAME;
+-		qh->stamp = ehci->periodic_stamp;
+ 
+ 		if (urb->dev->speed == USB_SPEED_HIGH) {
+ 			qh->c_usecs = 0;
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 11b2f21d7ac1..263b542985c0 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -569,7 +569,10 @@ static void qh_link_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		? ((qh->usecs + qh->c_usecs) / qh->period)
+ 		: (qh->usecs * 8);
+ 
++	list_add(&qh->intr_node, &ehci->intr_qh_list);
++
+ 	/* maybe enable periodic schedule processing */
++	++ehci->intr_count;
+ 	enable_periodic(ehci);
+ }
+ 
+@@ -614,6 +617,11 @@ static void qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	/* qh->qh_next still "live" to HC */
+ 	qh->qh_state = QH_STATE_UNLINK;
+ 	qh->qh_next.ptr = NULL;
++
++	if (ehci->qh_scan_next == qh)
++		ehci->qh_scan_next = list_entry(qh->intr_node.next,
++				struct ehci_qh, intr_node);
++	list_del(&qh->intr_node);
+ }
+ 
+ static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)
+@@ -683,6 +691,7 @@ static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	}
+ 
+ 	/* maybe turn off periodic schedule */
++	--ehci->intr_count;
+ 	disable_periodic(ehci);
+ }
+ 
+@@ -920,6 +929,35 @@ static int intr_submit (
+ 	return status;
+ }
+ 
++static void scan_intr(struct ehci_hcd *ehci)
++{
++	struct ehci_qh		*qh;
++
++	list_for_each_entry_safe(qh, ehci->qh_scan_next, &ehci->intr_qh_list,
++			intr_node) {
++ rescan:
++		/* clean any finished work for this qh */
++		if (!list_empty(&qh->qtd_list)) {
++			int temp;
++
++			/*
++			 * Unlinks could happen here; completion reporting
++			 * drops the lock.  That's why ehci->qh_scan_next
++			 * always holds the next qh to scan; if the next qh
++			 * gets unlinked then ehci->qh_scan_next is adjusted
++			 * in qh_unlink_periodic().
++			 */
++			temp = qh_completions(ehci, qh);
++			if (unlikely(qh->needs_rescan ||
++					(list_empty(&qh->qtd_list) &&
++						qh->qh_state == QH_STATE_LINKED)))
++				start_unlink_intr(ehci, qh);
++			else if (temp != 0)
++				goto rescan;
++		}
++	}
++}
++
+ /*-------------------------------------------------------------------------*/
+ 
+ /* ehci_iso_stream ops work with both ITD and SITD */
+@@ -1450,6 +1488,10 @@ iso_stream_schedule (
+ 	urb->start_frame = stream->next_uframe;
+ 	if (!stream->highspeed)
+ 		urb->start_frame >>= 3;
++
++	/* Make sure scan_isoc() sees these */
++	if (ehci->isoc_count == 0)
++		ehci->next_uframe = now;
+ 	return 0;
+ 
+  fail:
+@@ -1608,6 +1650,7 @@ static void itd_link_urb(
+ 	urb->hcpriv = NULL;
+ 
+ 	timer_action (ehci, TIMER_IO_WATCHDOG);
++	++ehci->isoc_count;
+ 	enable_periodic(ehci);
+ }
+ 
+@@ -1688,9 +1731,11 @@ itd_complete (
+ 	ehci_urb_done(ehci, urb, 0);
+ 	retval = true;
+ 	urb = NULL;
++
++	--ehci->isoc_count;
+ 	disable_periodic(ehci);
+-	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
+ 
++	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
+ 	if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
+ 		if (ehci->amd_pll_fix == 1)
+ 			usb_amd_quirk_pll_enable();
+@@ -2008,6 +2053,7 @@ static void sitd_link_urb(
+ 	urb->hcpriv = NULL;
+ 
+ 	timer_action (ehci, TIMER_IO_WATCHDOG);
++	++ehci->isoc_count;
+ 	enable_periodic(ehci);
+ }
+ 
+@@ -2074,9 +2120,11 @@ sitd_complete (
+ 	ehci_urb_done(ehci, urb, 0);
+ 	retval = true;
+ 	urb = NULL;
++
++	--ehci->isoc_count;
+ 	disable_periodic(ehci);
+-	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
+ 
++	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
+ 	if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
+ 		if (ehci->amd_pll_fix == 1)
+ 			usb_amd_quirk_pll_enable();
+@@ -2165,8 +2213,7 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-static void
+-scan_periodic (struct ehci_hcd *ehci)
++static void scan_isoc(struct ehci_hcd *ehci)
+ {
+ 	unsigned	now_uframe, frame, clock, clock_frame, mod;
+ 	unsigned	modified;
+@@ -2189,7 +2236,6 @@ scan_periodic (struct ehci_hcd *ehci)
+ 	ehci->clock_frame = clock_frame;
+ 	clock &= mod - 1;
+ 	clock_frame = clock >> 3;
+-	++ehci->periodic_stamp;
+ 
+ 	for (;;) {
+ 		union ehci_shadow	q, *q_p;
+@@ -2208,36 +2254,10 @@ scan_periodic (struct ehci_hcd *ehci)
+ 
+ 		while (q.ptr != NULL) {
+ 			unsigned		uf;
+-			union ehci_shadow	temp;
+ 			int			live;
+ 
+ 			live = (ehci->rh_state >= EHCI_RH_RUNNING);
+ 			switch (hc32_to_cpu(ehci, type)) {
+-			case Q_TYPE_QH:
+-				/* handle any completions */
+-				temp.qh = q.qh;
+-				type = Q_NEXT_TYPE(ehci, q.qh->hw->hw_next);
+-				q = q.qh->qh_next;
+-				if (temp.qh->stamp != ehci->periodic_stamp) {
+-					modified = qh_completions(ehci, temp.qh);
+-					if (!modified)
+-						temp.qh->stamp = ehci->periodic_stamp;
+-					if (unlikely(list_empty(&temp.qh->qtd_list) ||
+-							temp.qh->needs_rescan))
+-						start_unlink_intr(ehci, temp.qh);
+-				}
+-				break;
+-			case Q_TYPE_FSTN:
+-				/* for "save place" FSTNs, look at QH entries
+-				 * in the previous frame for completions.
+-				 */
+-				if (q.fstn->hw_prev != EHCI_LIST_END(ehci)) {
+-					ehci_dbg(ehci,
+-						"ignoring completions from FSTNs\n");
+-				}
+-				type = Q_NEXT_TYPE(ehci, q.fstn->hw_next);
+-				q = q.fstn->fstn_next;
+-				break;
+ 			case Q_TYPE_ITD:
+ 				/* If this ITD is still active, leave it for
+ 				 * later processing ... check the next entry.
+@@ -2319,12 +2339,17 @@ scan_periodic (struct ehci_hcd *ehci)
+ 				ehci_dbg(ehci, "corrupt type %d frame %d shadow %p\n",
+ 					type, frame, q.ptr);
+ 				// BUG ();
++				/* FALL THROUGH */
++			case Q_TYPE_QH:
++			case Q_TYPE_FSTN:
++				/* End of the iTDs and siTDs */
+ 				q.ptr = NULL;
++				break;
+ 			}
+ 
+ 			/* assume completion callbacks modify the queue */
+ 			if (unlikely (modified)) {
+-				if (likely(ehci->periodic_count > 0))
++				if (likely(ehci->isoc_count > 0))
+ 					goto restart;
+ 				/* short-circuit this scan */
+ 				now_uframe = clock;
+@@ -2353,7 +2378,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 			unsigned	now;
+ 
+ 			if (ehci->rh_state < EHCI_RH_RUNNING
+-					|| ehci->periodic_count == 0)
++					|| ehci->isoc_count == 0)
+ 				break;
+ 			ehci->next_uframe = now_uframe;
+ 			now = ehci_read_frame_index(ehci) & (mod - 1);
+@@ -2363,10 +2388,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 			/* rescan the rest of this frame, then ... */
+ 			clock = now;
+ 			clock_frame = clock >> 3;
+-			if (ehci->clock_frame != clock_frame) {
+-				ehci->clock_frame = clock_frame;
+-				++ehci->periodic_stamp;
+-			}
++			ehci->clock_frame = clock_frame;
+ 		} else {
+ 			now_uframe++;
+ 			now_uframe &= mod - 1;
+diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
+index a823290b5139..0e28bae78d18 100644
+--- a/drivers/usb/host/ehci-timer.c
++++ b/drivers/usb/host/ehci-timer.c
+@@ -168,13 +168,8 @@ static void ehci_poll_PSS(struct ehci_hcd *ehci)
+ 
+ 	/* The status is up-to-date; restart or stop the schedule as needed */
+ 	if (want == 0) {	/* Stopped */
+-		if (ehci->periodic_count > 0) {
+-
+-			/* make sure ehci_work scans these */
+-			ehci->next_uframe = ehci_read_frame_index(ehci)
+-					& ((ehci->periodic_size << 3) - 1);
++		if (ehci->periodic_count > 0)
+ 			ehci_set_command_bit(ehci, CMD_PSE);
+-		}
+ 
+ 	} else {		/* Running */
+ 		if (ehci->periodic_count == 0) {
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index c462d52ac575..08637183aad0 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -117,6 +117,7 @@ struct ehci_hcd {			/* one per controller */
+ 	bool			need_rescan:1;
+ 	bool			intr_unlinking:1;
+ 	bool			async_unlinking:1;
++	struct ehci_qh		*qh_scan_next;
+ 
+ 	/* async schedule support */
+ 	struct ehci_qh		*async;
+@@ -124,7 +125,6 @@ struct ehci_hcd {			/* one per controller */
+ 	struct ehci_qh		*async_unlink;
+ 	struct ehci_qh		*async_unlink_last;
+ 	struct ehci_qh		*async_iaa;
+-	struct ehci_qh		*qh_scan_next;
+ 	unsigned		async_unlink_cycle;
+ 	unsigned		async_count;	/* async activity count */
+ 
+@@ -133,6 +133,7 @@ struct ehci_hcd {			/* one per controller */
+ 	unsigned		periodic_size;
+ 	__hc32			*periodic;	/* hw periodic table */
+ 	dma_addr_t		periodic_dma;
++	struct list_head	intr_qh_list;
+ 	unsigned		i_thresh;	/* uframes HC might cache */
+ 
+ 	union ehci_shadow	*pshadow;	/* mirror hw periodic table */
+@@ -140,6 +141,8 @@ struct ehci_hcd {			/* one per controller */
+ 	struct ehci_qh		*intr_unlink_last;
+ 	unsigned		intr_unlink_cycle;
+ 	int			next_uframe;	/* scan periodic, start here */
++	unsigned		intr_count;	/* intr activity count */
++	unsigned		isoc_count;	/* isoc activity count */
+ 	unsigned		periodic_count;	/* periodic activity count */
+ 	unsigned		uframe_periodic_max; /* max periodic time per uframe */
+ 
+@@ -176,7 +179,6 @@ struct ehci_hcd {			/* one per controller */
+ 
+ 	struct timer_list	watchdog;
+ 	unsigned long		actions;
+-	unsigned		periodic_stamp;
+ 	unsigned		random_frame;
+ 	unsigned long		next_statechange;
+ 	ktime_t			last_periodic_enable;
+@@ -381,11 +383,11 @@ struct ehci_qh {
+ 	dma_addr_t		qh_dma;		/* address of qh */
+ 	union ehci_shadow	qh_next;	/* ptr to qh; or periodic */
+ 	struct list_head	qtd_list;	/* sw qtd list */
++	struct list_head	intr_node;	/* list of intr QHs */
+ 	struct ehci_qtd		*dummy;
+ 	struct ehci_qh		*unlink_next;	/* next on unlink list */
+ 
+ 	unsigned		unlink_cycle;
+-	unsigned		stamp;
+ 
+ 	u8			needs_rescan;	/* Dequeue during giveback */
+ 	u8			qh_state;

commit 361aabf395e4a23cf554cf4ec0c0c6963b8beb01
+Author: Alan Stern 
+Date:   Wed Jul 11 11:22:57 2012 -0400
+
+    USB: EHCI: don't lose events during a scan
+    
+    This patch (as1584) fixes a minor bug that has been present in
+    ehci-hcd since the beginning.
+    
+    Scanning the schedules for URB completions is single-threaded.  If a
+    completion interrupt occurs while an URB is being given back, the
+    interrupt handler realizes that a scan is in progress on another CPU
+    and avoids starting a new one.
+    
+    This means that completion events can be lost.  If an URB completes
+    after it has been scanned but while a scan is still in progress, the
+    driver won't notice and won't rescan the completed URB.
+    
+    The patch fixes the problem by adding a new flag to indicate that
+    another scan is needed after the current scan is done.  The flag gets
+    set whenever a completion interrupt occurs while a scan is in
+    progress.  The rescan will see the completion, thus preventing it from
+    getting lost.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 74ffd20edff8..f6cf1d178107 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -400,14 +400,21 @@ static void ehci_work (struct ehci_hcd *ehci)
+ 	 * it reports urb completions.  this flag guards against bogus
+ 	 * attempts at re-entrant schedule scanning.
+ 	 */
+-	if (ehci->scanning)
++	if (ehci->scanning) {
++		ehci->need_rescan = true;
+ 		return;
+-	ehci->scanning = 1;
++	}
++	ehci->scanning = true;
++
++ rescan:
++	ehci->need_rescan = false;
+ 	if (ehci->async_count)
+ 		scan_async(ehci);
+ 	if (ehci->next_uframe != -1)
+ 		scan_periodic (ehci);
+-	ehci->scanning = 0;
++	if (ehci->need_rescan)
++		goto rescan;
++	ehci->scanning = false;
+ 
+ 	/* the IO watchdog guards against hardware or driver bugs that
+ 	 * misplace IRQs, and should let us run completely without IRQs.
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 303c36cc99c9..c462d52ac575 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -113,7 +113,8 @@ struct ehci_hcd {			/* one per controller */
+ 	enum ehci_rh_state	rh_state;
+ 
+ 	/* general schedule support */
+-	unsigned		scanning:1;
++	bool			scanning:1;
++	bool			need_rescan:1;
+ 	bool			intr_unlinking:1;
+ 	bool			async_unlinking:1;
+ 

commit 32830f207691176234b4c4dd17f0d7ab6d87d94b
+Author: Alan Stern 
+Date:   Wed Jul 11 11:22:53 2012 -0400
+
+    USB: EHCI: use hrtimer for unlinking empty async QHs
+    
+    This patch (as1583) changes ehci-hcd to use an hrtimer event for
+    unlinking empty (unused) async QHs instead of using a kernel timer.
+    
+    The check for empty QHs is moved to a new routine, where it doesn't
+    require going through an entire scan of both the async and periodic
+    schedules.  And it can unlink multiple QHs at once, unlike the current
+    code.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 86e8ee169c67..74ffd20edff8 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -94,8 +94,6 @@ static const char	hcd_name [] = "ehci_hcd";
+ #define	EHCI_TUNE_FLS		1	/* (medium) 512-frame schedule */
+ 
+ #define EHCI_IO_JIFFIES		(HZ/10)		/* io watchdog > irq_thresh */
+-#define EHCI_SHRINK_JIFFIES	(DIV_ROUND_UP(HZ, 200) + 1)
+-						/* 5-ms async qh unlink delay */
+ 
+ /* Initial IRQ latency:  faster than hw default */
+ static int log2_irq_thresh = 0;		// 0 to 6
+@@ -130,15 +128,6 @@ MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us");
+ static void
+ timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action)
+ {
+-	/* Don't override timeouts which shrink or (later) disable
+-	 * the async ring; just the I/O watchdog.  Note that if a
+-	 * SHRINK were pending, OFF would never be requested.
+-	 */
+-	if (timer_pending(&ehci->watchdog)
+-			&& (BIT(TIMER_ASYNC_SHRINK)
+-				& ehci->actions))
+-		return;
+-
+ 	if (!test_and_set_bit(action, &ehci->actions)) {
+ 		unsigned long t;
+ 
+@@ -148,10 +137,6 @@ timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action)
+ 				return;
+ 			t = EHCI_IO_JIFFIES;
+ 			break;
+-		/* case TIMER_ASYNC_SHRINK: */
+-		default:
+-			t = EHCI_SHRINK_JIFFIES;
+-			break;
+ 		}
+ 		mod_timer(&ehci->watchdog, t + jiffies);
+ 	}
+@@ -307,6 +292,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
+ /*-------------------------------------------------------------------------*/
+ 
+ static void end_unlink_async(struct ehci_hcd *ehci);
++static void unlink_empty_async(struct ehci_hcd *ehci);
+ static void ehci_work(struct ehci_hcd *ehci);
+ static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh);
+ static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh);
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index a3822700e496..5d84562e2716 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -300,6 +300,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 	ehci->rh_state = EHCI_RH_SUSPENDED;
+ 
+ 	end_unlink_async(ehci);
++	unlink_empty_async(ehci);
+ 	ehci_handle_intr_unlinks(ehci);
+ 	end_free_itds(ehci);
+ 
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 181832921c53..bae931767825 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -1205,7 +1205,7 @@ static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested)
+ 			end_unlink_async(ehci);
+ 
+ 	/* Otherwise start a new IAA cycle */
+-	} else {
++	} else if (likely(ehci->rh_state == EHCI_RH_RUNNING)) {
+ 		/* Make sure the unlinks are all visible to the hardware */
+ 		wmb();
+ 
+@@ -1253,6 +1253,39 @@ static void end_unlink_async(struct ehci_hcd *ehci)
+ 	}
+ }
+ 
++static void unlink_empty_async(struct ehci_hcd *ehci)
++{
++	struct ehci_qh		*qh, *next;
++	bool			stopped = (ehci->rh_state < EHCI_RH_RUNNING);
++	bool			check_unlinks_later = false;
++
++	/* Unlink all the async QHs that have been empty for a timer cycle */
++	next = ehci->async->qh_next.qh;
++	while (next) {
++		qh = next;
++		next = qh->qh_next.qh;
++
++		if (list_empty(&qh->qtd_list) &&
++				qh->qh_state == QH_STATE_LINKED) {
++			if (!stopped && qh->unlink_cycle ==
++					ehci->async_unlink_cycle)
++				check_unlinks_later = true;
++			else
++				single_unlink_async(ehci, qh);
++		}
++	}
++
++	/* Start a new IAA cycle if any QHs are waiting for it */
++	if (ehci->async_unlink)
++		start_iaa_cycle(ehci, false);
++
++	/* QHs that haven't been empty for long enough will be handled later */
++	if (check_unlinks_later) {
++		ehci_enable_event(ehci, EHCI_HRTIMER_ASYNC_UNLINKS, true);
++		++ehci->async_unlink_cycle;
++	}
++}
++
+ /* makes sure the async qh will become idle */
+ /* caller must own ehci->lock */
+ 
+@@ -1277,12 +1310,8 @@ static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 
+ static void scan_async (struct ehci_hcd *ehci)
+ {
+-	bool			stopped;
+ 	struct ehci_qh		*qh;
+-	enum ehci_timer_action	action = TIMER_IO_WATCHDOG;
+-
+-	timer_action_done (ehci, TIMER_ASYNC_SHRINK);
+-	stopped = (ehci->rh_state < EHCI_RH_RUNNING);
++	bool			check_unlinks_later = false;
+ 
+ 	ehci->qh_scan_next = ehci->async->qh_next.qh;
+ 	while (ehci->qh_scan_next) {
+@@ -1301,28 +1330,27 @@ static void scan_async (struct ehci_hcd *ehci)
+ 			 * in single_unlink_async().
+ 			 */
+ 			temp = qh_completions(ehci, qh);
+-			if (qh->needs_rescan)
++			if (qh->needs_rescan) {
+ 				start_unlink_async(ehci, qh);
+-			qh->unlink_time = jiffies + EHCI_SHRINK_JIFFIES;
+-			if (temp != 0)
++			} else if (list_empty(&qh->qtd_list)
++					&& qh->qh_state == QH_STATE_LINKED) {
++				qh->unlink_cycle = ehci->async_unlink_cycle;
++				check_unlinks_later = true;
++			} else if (temp != 0)
+ 				goto rescan;
+ 		}
++	}
+ 
+-		/* unlink idle entries, reducing DMA usage as well
+-		 * as HCD schedule-scanning costs.  delay for any qh
+-		 * we just scanned, there's a not-unusual case that it
+-		 * doesn't stay idle for long.
+-		 * (plus, avoids some kind of re-activation race.)
+-		 */
+-		if (list_empty(&qh->qtd_list)
+-				&& qh->qh_state == QH_STATE_LINKED) {
+-			if (!ehci->async_unlink && (stopped ||
+-					time_after_eq(jiffies, qh->unlink_time)))
+-				start_unlink_async(ehci, qh);
+-			else
+-				action = TIMER_ASYNC_SHRINK;
+-		}
++	/*
++	 * Unlink empty entries, reducing DMA usage as well
++	 * as HCD schedule-scanning costs.  Delay for any qh
++	 * we just scanned, there's a not-unusual case that it
++	 * doesn't stay idle for long.
++	 */
++	if (check_unlinks_later && ehci->rh_state == EHCI_RH_RUNNING &&
++			!(ehci->enabled_hrtimer_events &
++				BIT(EHCI_HRTIMER_ASYNC_UNLINKS))) {
++		ehci_enable_event(ehci, EHCI_HRTIMER_ASYNC_UNLINKS, true);
++		++ehci->async_unlink_cycle;
+ 	}
+-	if (action == TIMER_ASYNC_SHRINK)
+-		timer_action (ehci, TIMER_ASYNC_SHRINK);
+ }
+diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
+index 8ca5f152f5bd..a823290b5139 100644
+--- a/drivers/usb/host/ehci-timer.c
++++ b/drivers/usb/host/ehci-timer.c
+@@ -72,6 +72,7 @@ static unsigned event_delays_ns[] = {
+ 	1 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_POLL_DEAD */
+ 	1125 * NSEC_PER_USEC,	/* EHCI_HRTIMER_UNLINK_INTR */
+ 	2 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_FREE_ITDS */
++	6 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_ASYNC_UNLINKS */
+ 	10 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_IAA_WATCHDOG */
+ 	10 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_DISABLE_PERIODIC */
+ 	15 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_DISABLE_ASYNC */
+@@ -347,6 +348,7 @@ static void (*event_handlers[])(struct ehci_hcd *) = {
+ 	ehci_handle_controller_death,	/* EHCI_HRTIMER_POLL_DEAD */
+ 	ehci_handle_intr_unlinks,	/* EHCI_HRTIMER_UNLINK_INTR */
+ 	end_free_itds,			/* EHCI_HRTIMER_FREE_ITDS */
++	unlink_empty_async,		/* EHCI_HRTIMER_ASYNC_UNLINKS */
+ 	ehci_iaa_watchdog,		/* EHCI_HRTIMER_IAA_WATCHDOG */
+ 	ehci_disable_PSE,		/* EHCI_HRTIMER_DISABLE_PERIODIC */
+ 	ehci_disable_ASE,		/* EHCI_HRTIMER_DISABLE_ASYNC */
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 1a782775881b..303c36cc99c9 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -84,6 +84,7 @@ enum ehci_hrtimer_event {
+ 	EHCI_HRTIMER_POLL_DEAD,		/* Wait for dead controller to stop */
+ 	EHCI_HRTIMER_UNLINK_INTR,	/* Wait for interrupt QH unlink */
+ 	EHCI_HRTIMER_FREE_ITDS,		/* Wait for unused iTDs and siTDs */
++	EHCI_HRTIMER_ASYNC_UNLINKS,	/* Unlink empty async QHs */
+ 	EHCI_HRTIMER_IAA_WATCHDOG,	/* Handle lost IAA interrupts */
+ 	EHCI_HRTIMER_DISABLE_PERIODIC,	/* Wait to disable periodic sched */
+ 	EHCI_HRTIMER_DISABLE_ASYNC,	/* Wait to disable async sched */
+@@ -123,6 +124,7 @@ struct ehci_hcd {			/* one per controller */
+ 	struct ehci_qh		*async_unlink_last;
+ 	struct ehci_qh		*async_iaa;
+ 	struct ehci_qh		*qh_scan_next;
++	unsigned		async_unlink_cycle;
+ 	unsigned		async_count;	/* async activity count */
+ 
+ 	/* periodic schedule support */
+@@ -232,7 +234,6 @@ static inline struct usb_hcd *ehci_to_hcd (struct ehci_hcd *ehci)
+ 
+ enum ehci_timer_action {
+ 	TIMER_IO_WATCHDOG,
+-	TIMER_ASYNC_SHRINK,
+ };
+ 
+ static inline void
+@@ -382,7 +383,6 @@ struct ehci_qh {
+ 	struct ehci_qtd		*dummy;
+ 	struct ehci_qh		*unlink_next;	/* next on unlink list */
+ 
+-	unsigned long		unlink_time;
+ 	unsigned		unlink_cycle;
+ 	unsigned		stamp;
+ 

commit 3c273a056bf46167f0a1309c2ba72282a17d2541
+Author: Alan Stern 
+Date:   Wed Jul 11 11:22:49 2012 -0400
+
+    USB: EHCI: unlink multiple async QHs together
+    
+    This patch (as1582) changes ehci-hcd's strategy for unlinking async
+    QHs.  Currently the driver never unlinks more than one QH at a time.
+    This can be inefficient and cause unnecessary delays, since a QH
+    cannot be reused while it is waiting to be unlinked.
+    
+    The new strategy unlinks all the waiting QHs at once.  In practice the
+    improvement won't be very big, because it's somewhat uncommon to have
+    two or more QHs waiting to be unlinked at any time.  But it does
+    happen, and in any case, doing things this way makes more sense IMO.
+    
+    The change requires the async unlinking code to be refactored
+    slightly.  Now in addition to the routines for starting and ending an
+    unlink, there are new routines for unlinking a single QH and starting
+    an IAA cycle.  This approach is needed because there are two separate
+    paths for unlinking async QHs:
+    
+            When a transfer error occurs or an URB is cancelled, the QH
+            must be unlinked right away;
+    
+            When a QH has been idle sufficiently long, it is unlinked
+            to avoid consuming DMA bandwidth uselessly.
+    
+    In the first case we want the unlink to proceed as quickly as
+    possible, whereas in the second case we can afford to batch several
+    QHs together and unlink them all at once.  Hence the division of
+    labor.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index f74ba277c22d..86e8ee169c67 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -795,7 +795,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 		/* guard against (alleged) silicon errata */
+ 		if (cmd & CMD_IAAD)
+ 			ehci_dbg(ehci, "IAA with IAAD still set?\n");
+-		if (ehci->async_unlink) {
++		if (ehci->async_iaa) {
+ 			COUNT(ehci->stats.iaa);
+ 			end_unlink_async(ehci);
+ 		} else
+@@ -926,33 +926,6 @@ static int ehci_urb_enqueue (
+ 	}
+ }
+ 
+-static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+-{
+-	/* failfast */
+-	if (ehci->rh_state < EHCI_RH_RUNNING && ehci->async_unlink)
+-		end_unlink_async(ehci);
+-
+-	/* If the QH isn't linked then there's nothing we can do
+-	 * unless we were called during a giveback, in which case
+-	 * qh_completions() has to deal with it.
+-	 */
+-	if (qh->qh_state != QH_STATE_LINKED) {
+-		if (qh->qh_state == QH_STATE_COMPLETING)
+-			qh->needs_rescan = 1;
+-		return;
+-	}
+-
+-	/* defer till later if busy */
+-	if (ehci->async_unlink) {
+-		qh->qh_state = QH_STATE_UNLINK_WAIT;
+-		ehci->async_unlink_last->unlink_next = qh;
+-		ehci->async_unlink_last = qh;
+-
+-	/* start IAA cycle */
+-	} else
+-		start_unlink_async (ehci, qh);
+-}
+-
+ /* remove from hardware lists
+  * completions normally happen asynchronously
+  */
+@@ -979,7 +952,7 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ 		switch (qh->qh_state) {
+ 		case QH_STATE_LINKED:
+ 		case QH_STATE_COMPLETING:
+-			unlink_async(ehci, qh);
++			start_unlink_async(ehci, qh);
+ 			break;
+ 		case QH_STATE_UNLINK:
+ 		case QH_STATE_UNLINK_WAIT:
+@@ -1070,7 +1043,7 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 		 * may already be unlinked.
+ 		 */
+ 		if (tmp)
+-			unlink_async(ehci, qh);
++			start_unlink_async(ehci, qh);
+ 		/* FALL THROUGH */
+ 	case QH_STATE_UNLINK:		/* wait for hw to finish? */
+ 	case QH_STATE_UNLINK_WAIT:
+@@ -1133,7 +1106,7 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 			 * re-linking will call qh_refresh().
+ 			 */
+ 			if (eptype == USB_ENDPOINT_XFER_BULK)
+-				unlink_async(ehci, qh);
++				start_unlink_async(ehci, qh);
+ 			else
+ 				start_unlink_intr(ehci, qh);
+ 		}
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 3097872b1e74..a3822700e496 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -299,8 +299,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 	ehci_halt (ehci);
+ 	ehci->rh_state = EHCI_RH_SUSPENDED;
+ 
+-	if (ehci->async_unlink)
+-		end_unlink_async(ehci);
++	end_unlink_async(ehci);
+ 	ehci_handle_intr_unlinks(ehci);
+ 	end_free_itds(ehci);
+ 
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 7b35933d91a6..181832921c53 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -293,9 +293,6 @@ __acquires(ehci->lock)
+ 	spin_lock (&ehci->lock);
+ }
+ 
+-static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh);
+-static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh);
+-
+ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh);
+ 
+ /*
+@@ -1166,82 +1163,114 @@ submit_async (
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-/* the async qh for the qtds being unlinked are now gone from the HC */
+-
+-static void end_unlink_async (struct ehci_hcd *ehci)
++static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ {
+-	struct ehci_qh		*qh = ehci->async_unlink;
+-	struct ehci_qh		*next;
++	struct ehci_qh		*prev;
+ 
+-	// qh->hw_next = cpu_to_hc32(qh->qh_dma);
+-	qh->qh_state = QH_STATE_IDLE;
+-	qh->qh_next.qh = NULL;
++	/* Add to the end of the list of QHs waiting for the next IAAD */
++	qh->qh_state = QH_STATE_UNLINK;
++	if (ehci->async_unlink)
++		ehci->async_unlink_last->unlink_next = qh;
++	else
++		ehci->async_unlink = qh;
++	ehci->async_unlink_last = qh;
++
++	/* Unlink it from the schedule */
++	prev = ehci->async;
++	while (prev->qh_next.qh != qh)
++		prev = prev->qh_next.qh;
++
++	prev->hw->hw_next = qh->hw->hw_next;
++	prev->qh_next = qh->qh_next;
++	if (ehci->qh_scan_next == qh)
++		ehci->qh_scan_next = qh->qh_next.qh;
++}
+ 
+-	/* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */
+-	next = qh->unlink_next;
+-	ehci->async_unlink = next;
+-	qh->unlink_next = NULL;
++static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested)
++{
++	/*
++	 * Do nothing if an IAA cycle is already running or
++	 * if one will be started shortly.
++	 */
++	if (ehci->async_iaa || ehci->async_unlinking)
++		return;
+ 
+-	qh_completions (ehci, qh);
++	/* Do all the waiting QHs at once */
++	ehci->async_iaa = ehci->async_unlink;
++	ehci->async_unlink = NULL;
+ 
+-	if (!list_empty(&qh->qtd_list) && ehci->rh_state == EHCI_RH_RUNNING)
+-		qh_link_async (ehci, qh);
++	/* If the controller isn't running, we don't have to wait for it */
++	if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) {
++		if (!nested)		/* Avoid recursion */
++			end_unlink_async(ehci);
+ 
+-	disable_async(ehci);
++	/* Otherwise start a new IAA cycle */
++	} else {
++		/* Make sure the unlinks are all visible to the hardware */
++		wmb();
+ 
+-	if (next) {
+-		ehci->async_unlink = NULL;
+-		start_unlink_async (ehci, next);
++		ehci_writel(ehci, ehci->command | CMD_IAAD,
++				&ehci->regs->command);
++		ehci_readl(ehci, &ehci->regs->command);
++		ehci_enable_event(ehci, EHCI_HRTIMER_IAA_WATCHDOG, true);
+ 	}
++}
++
++/* the async qh for the qtds being unlinked are now gone from the HC */
++
++static void end_unlink_async(struct ehci_hcd *ehci)
++{
++	struct ehci_qh		*qh;
+ 
+ 	if (ehci->has_synopsys_hc_bug)
+ 		ehci_writel(ehci, (u32) ehci->async->qh_dma,
+ 			    &ehci->regs->async_next);
++
++	/* Process the idle QHs */
++ restart:
++	ehci->async_unlinking = true;
++	while (ehci->async_iaa) {
++		qh = ehci->async_iaa;
++		ehci->async_iaa = qh->unlink_next;
++		qh->unlink_next = NULL;
++
++		qh->qh_state = QH_STATE_IDLE;
++		qh->qh_next.qh = NULL;
++
++		qh_completions(ehci, qh);
++		if (!list_empty(&qh->qtd_list) &&
++				ehci->rh_state == EHCI_RH_RUNNING)
++			qh_link_async(ehci, qh);
++		disable_async(ehci);
++	}
++	ehci->async_unlinking = false;
++
++	/* Start a new IAA cycle if any QHs are waiting for it */
++	if (ehci->async_unlink) {
++		start_iaa_cycle(ehci, true);
++		if (unlikely(ehci->rh_state < EHCI_RH_RUNNING))
++			goto restart;
++	}
+ }
+ 
+ /* makes sure the async qh will become idle */
+ /* caller must own ehci->lock */
+ 
+-static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
++static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ {
+-	struct ehci_qh	*prev;
+-
+-#ifdef DEBUG
+-	assert_spin_locked(&ehci->lock);
+-	if (ehci->async_unlink
+-			|| (qh->qh_state != QH_STATE_LINKED
+-				&& qh->qh_state != QH_STATE_UNLINK_WAIT)
+-			)
+-		BUG ();
+-#endif
+-
+-	qh->qh_state = QH_STATE_UNLINK;
+-	ehci->async_unlink = qh;
+-	if (!qh->unlink_next)
+-		ehci->async_unlink_last = qh;
+-
+-	prev = ehci->async;
+-	while (prev->qh_next.qh != qh)
+-		prev = prev->qh_next.qh;
+-
+-	prev->hw->hw_next = qh->hw->hw_next;
+-	prev->qh_next = qh->qh_next;
+-	if (ehci->qh_scan_next == qh)
+-		ehci->qh_scan_next = qh->qh_next.qh;
+-	wmb ();
+-
+-	/* If the controller isn't running, we don't have to wait for it */
+-	if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) {
+-		/* if (unlikely (qh->unlink_next != 0))
+-		 *	this will recurse, probably not much
+-		 */
+-		end_unlink_async (ehci);
++	/*
++	 * If the QH isn't linked then there's nothing we can do
++	 * unless we were called during a giveback, in which case
++	 * qh_completions() has to deal with it.
++	 */
++	if (qh->qh_state != QH_STATE_LINKED) {
++		if (qh->qh_state == QH_STATE_COMPLETING)
++			qh->needs_rescan = 1;
+ 		return;
+ 	}
+ 
+-	ehci_writel(ehci, ehci->command | CMD_IAAD, &ehci->regs->command);
+-	(void)ehci_readl(ehci, &ehci->regs->command);
+-	ehci_enable_event(ehci, EHCI_HRTIMER_IAA_WATCHDOG, true);
++	single_unlink_async(ehci, qh);
++	start_iaa_cycle(ehci, false);
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -1269,11 +1298,11 @@ static void scan_async (struct ehci_hcd *ehci)
+ 			 * drops the lock.  That's why ehci->qh_scan_next
+ 			 * always holds the next qh to scan; if the next qh
+ 			 * gets unlinked then ehci->qh_scan_next is adjusted
+-			 * in start_unlink_async().
++			 * in single_unlink_async().
+ 			 */
+ 			temp = qh_completions(ehci, qh);
+ 			if (qh->needs_rescan)
+-				unlink_async(ehci, qh);
++				start_unlink_async(ehci, qh);
+ 			qh->unlink_time = jiffies + EHCI_SHRINK_JIFFIES;
+ 			if (temp != 0)
+ 				goto rescan;
+diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
+index aab042064226..8ca5f152f5bd 100644
+--- a/drivers/usb/host/ehci-timer.c
++++ b/drivers/usb/host/ehci-timer.c
+@@ -211,6 +211,7 @@ static void ehci_handle_controller_death(struct ehci_hcd *ehci)
+ 	ehci_writel(ehci, 0, &ehci->regs->configured_flag);
+ 	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+ 	ehci_work(ehci);
++	end_unlink_async(ehci);
+ 
+ 	/* Not in process context, so don't try to reset the controller */
+ }
+@@ -304,7 +305,7 @@ static void ehci_iaa_watchdog(struct ehci_hcd *ehci)
+ 	 * (a) SMP races against real IAA firing and retriggering, and
+ 	 * (b) clean HC shutdown, when IAA watchdog was pending.
+ 	 */
+-	if (ehci->async_unlink) {
++	if (ehci->async_iaa) {
+ 		u32 cmd, status;
+ 
+ 		/* If we get here, IAA is *REALLY* late.  It's barely
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index d9414aae610f..1a782775881b 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -114,12 +114,14 @@ struct ehci_hcd {			/* one per controller */
+ 	/* general schedule support */
+ 	unsigned		scanning:1;
+ 	bool			intr_unlinking:1;
++	bool			async_unlinking:1;
+ 
+ 	/* async schedule support */
+ 	struct ehci_qh		*async;
+ 	struct ehci_qh		*dummy;		/* For AMD quirk use */
+ 	struct ehci_qh		*async_unlink;
+ 	struct ehci_qh		*async_unlink_last;
++	struct ehci_qh		*async_iaa;
+ 	struct ehci_qh		*qh_scan_next;
+ 	unsigned		async_count;	/* async activity count */
+ 

commit 9d9387475af261949f61a5ec465e1f762d7be08a
+Author: Alan Stern 
+Date:   Wed Jul 11 11:22:44 2012 -0400
+
+    USB: EHCI: use hrtimer for the IAA watchdog
+    
+    This patch (as1581) replaces the iaa_watchdog kernel timer used by
+    ehci-hcd with an hrtimer event, in keeping with the general conversion
+    to high-res timers.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index fb1966cf5649..f74ba277c22d 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -93,7 +93,6 @@ static const char	hcd_name [] = "ehci_hcd";
+  */
+ #define	EHCI_TUNE_FLS		1	/* (medium) 512-frame schedule */
+ 
+-#define EHCI_IAA_MSECS		10		/* arbitrary */
+ #define EHCI_IO_JIFFIES		(HZ/10)		/* io watchdog > irq_thresh */
+ #define EHCI_SHRINK_JIFFIES	(DIV_ROUND_UP(HZ, 200) + 1)
+ 						/* 5-ms async qh unlink delay */
+@@ -322,51 +321,6 @@ static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh);
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-static void ehci_iaa_watchdog(unsigned long param)
+-{
+-	struct ehci_hcd		*ehci = (struct ehci_hcd *) param;
+-	unsigned long		flags;
+-
+-	spin_lock_irqsave (&ehci->lock, flags);
+-
+-	/* Lost IAA irqs wedge things badly; seen first with a vt8235.
+-	 * So we need this watchdog, but must protect it against both
+-	 * (a) SMP races against real IAA firing and retriggering, and
+-	 * (b) clean HC shutdown, when IAA watchdog was pending.
+-	 */
+-	if (ehci->async_unlink
+-			&& !timer_pending(&ehci->iaa_watchdog)
+-			&& ehci->rh_state == EHCI_RH_RUNNING) {
+-		u32 cmd, status;
+-
+-		/* If we get here, IAA is *REALLY* late.  It's barely
+-		 * conceivable that the system is so busy that CMD_IAAD
+-		 * is still legitimately set, so let's be sure it's
+-		 * clear before we read STS_IAA.  (The HC should clear
+-		 * CMD_IAAD when it sets STS_IAA.)
+-		 */
+-		cmd = ehci_readl(ehci, &ehci->regs->command);
+-
+-		/* If IAA is set here it either legitimately triggered
+-		 * before we cleared IAAD above (but _way_ late, so we'll
+-		 * still count it as lost) ... or a silicon erratum:
+-		 * - VIA seems to set IAA without triggering the IRQ;
+-		 * - IAAD potentially cleared without setting IAA.
+-		 */
+-		status = ehci_readl(ehci, &ehci->regs->status);
+-		if ((status & STS_IAA) || !(cmd & CMD_IAAD)) {
+-			COUNT (ehci->stats.lost_iaa);
+-			ehci_writel(ehci, STS_IAA, &ehci->regs->status);
+-		}
+-
+-		ehci_vdbg(ehci, "IAA watchdog: status %x cmd %x\n",
+-				status, cmd);
+-		end_unlink_async(ehci);
+-	}
+-
+-	spin_unlock_irqrestore(&ehci->lock, flags);
+-}
+-
+ static void ehci_watchdog(unsigned long param)
+ {
+ 	struct ehci_hcd		*ehci = (struct ehci_hcd *) param;
+@@ -418,7 +372,6 @@ static void ehci_shutdown(struct usb_hcd *hcd)
+ 	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
+ 
+ 	del_timer_sync(&ehci->watchdog);
+-	del_timer_sync(&ehci->iaa_watchdog);
+ 
+ 	spin_lock_irq(&ehci->lock);
+ 	ehci->rh_state = EHCI_RH_STOPPING;
+@@ -491,7 +444,6 @@ static void ehci_stop (struct usb_hcd *hcd)
+ 
+ 	/* no more interrupts ... */
+ 	del_timer_sync (&ehci->watchdog);
+-	del_timer_sync(&ehci->iaa_watchdog);
+ 
+ 	spin_lock_irq(&ehci->lock);
+ 	ehci->enabled_hrtimer_events = 0;
+@@ -547,10 +499,6 @@ static int ehci_init(struct usb_hcd *hcd)
+ 	ehci->watchdog.function = ehci_watchdog;
+ 	ehci->watchdog.data = (unsigned long) ehci;
+ 
+-	init_timer(&ehci->iaa_watchdog);
+-	ehci->iaa_watchdog.function = ehci_iaa_watchdog;
+-	ehci->iaa_watchdog.data = (unsigned long) ehci;
+-
+ 	hrtimer_init(&ehci->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+ 	ehci->hrtimer.function = ehci_hrtimer_func;
+ 	ehci->next_hrtimer_event = EHCI_HRTIMER_NO_EVENT;
+@@ -830,6 +778,20 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 
+ 	/* complete the unlinking of some qh [4.15.2.3] */
+ 	if (status & STS_IAA) {
++
++		/* Turn off the IAA watchdog */
++		ehci->enabled_hrtimer_events &= ~BIT(EHCI_HRTIMER_IAA_WATCHDOG);
++
++		/*
++		 * Mild optimization: Allow another IAAD to reset the
++		 * hrtimer, if one occurs before the next expiration.
++		 * In theory we could always cancel the hrtimer, but
++		 * tests show that about half the time it will be reset
++		 * for some other event anyway.
++		 */
++		if (ehci->next_hrtimer_event == EHCI_HRTIMER_IAA_WATCHDOG)
++			++ehci->next_hrtimer_event;
++
+ 		/* guard against (alleged) silicon errata */
+ 		if (cmd & CMD_IAAD)
+ 			ehci_dbg(ehci, "IAA with IAAD still set?\n");
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 6ad806bbe468..3097872b1e74 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -209,7 +209,6 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 	if (time_before (jiffies, ehci->next_statechange))
+ 		msleep(5);
+ 	del_timer_sync(&ehci->watchdog);
+-	del_timer_sync(&ehci->iaa_watchdog);
+ 
+ 	spin_lock_irq (&ehci->lock);
+ 
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index d68764ef4476..7b35933d91a6 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -1173,8 +1173,6 @@ static void end_unlink_async (struct ehci_hcd *ehci)
+ 	struct ehci_qh		*qh = ehci->async_unlink;
+ 	struct ehci_qh		*next;
+ 
+-	iaa_watchdog_done(ehci);
+-
+ 	// qh->hw_next = cpu_to_hc32(qh->qh_dma);
+ 	qh->qh_state = QH_STATE_IDLE;
+ 	qh->qh_next.qh = NULL;
+@@ -1243,7 +1241,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 
+ 	ehci_writel(ehci, ehci->command | CMD_IAAD, &ehci->regs->command);
+ 	(void)ehci_readl(ehci, &ehci->regs->command);
+-	iaa_watchdog_start(ehci);
++	ehci_enable_event(ehci, EHCI_HRTIMER_IAA_WATCHDOG, true);
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
+index 8feb60ff4228..aab042064226 100644
+--- a/drivers/usb/host/ehci-timer.c
++++ b/drivers/usb/host/ehci-timer.c
+@@ -72,6 +72,7 @@ static unsigned event_delays_ns[] = {
+ 	1 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_POLL_DEAD */
+ 	1125 * NSEC_PER_USEC,	/* EHCI_HRTIMER_UNLINK_INTR */
+ 	2 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_FREE_ITDS */
++	10 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_IAA_WATCHDOG */
+ 	10 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_DISABLE_PERIODIC */
+ 	15 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_DISABLE_ASYNC */
+ };
+@@ -291,6 +292,49 @@ static void end_free_itds(struct ehci_hcd *ehci)
+ }
+ 
+ 
++/* Handle lost (or very late) IAA interrupts */
++static void ehci_iaa_watchdog(struct ehci_hcd *ehci)
++{
++	if (ehci->rh_state != EHCI_RH_RUNNING)
++		return;
++
++	/*
++	 * Lost IAA irqs wedge things badly; seen first with a vt8235.
++	 * So we need this watchdog, but must protect it against both
++	 * (a) SMP races against real IAA firing and retriggering, and
++	 * (b) clean HC shutdown, when IAA watchdog was pending.
++	 */
++	if (ehci->async_unlink) {
++		u32 cmd, status;
++
++		/* If we get here, IAA is *REALLY* late.  It's barely
++		 * conceivable that the system is so busy that CMD_IAAD
++		 * is still legitimately set, so let's be sure it's
++		 * clear before we read STS_IAA.  (The HC should clear
++		 * CMD_IAAD when it sets STS_IAA.)
++		 */
++		cmd = ehci_readl(ehci, &ehci->regs->command);
++
++		/*
++		 * If IAA is set here it either legitimately triggered
++		 * after the watchdog timer expired (_way_ late, so we'll
++		 * still count it as lost) ... or a silicon erratum:
++		 * - VIA seems to set IAA without triggering the IRQ;
++		 * - IAAD potentially cleared without setting IAA.
++		 */
++		status = ehci_readl(ehci, &ehci->regs->status);
++		if ((status & STS_IAA) || !(cmd & CMD_IAAD)) {
++			COUNT(ehci->stats.lost_iaa);
++			ehci_writel(ehci, STS_IAA, &ehci->regs->status);
++		}
++
++		ehci_vdbg(ehci, "IAA watchdog: status %x cmd %x\n",
++				status, cmd);
++		end_unlink_async(ehci);
++	}
++}
++
++
+ /*
+  * Handler functions for the hrtimer event types.
+  * Keep this array in the same order as the event types indexed by
+@@ -302,6 +346,7 @@ static void (*event_handlers[])(struct ehci_hcd *) = {
+ 	ehci_handle_controller_death,	/* EHCI_HRTIMER_POLL_DEAD */
+ 	ehci_handle_intr_unlinks,	/* EHCI_HRTIMER_UNLINK_INTR */
+ 	end_free_itds,			/* EHCI_HRTIMER_FREE_ITDS */
++	ehci_iaa_watchdog,		/* EHCI_HRTIMER_IAA_WATCHDOG */
+ 	ehci_disable_PSE,		/* EHCI_HRTIMER_DISABLE_PERIODIC */
+ 	ehci_disable_ASE,		/* EHCI_HRTIMER_DISABLE_ASYNC */
+ };
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 755e30b0000b..d9414aae610f 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -84,6 +84,7 @@ enum ehci_hrtimer_event {
+ 	EHCI_HRTIMER_POLL_DEAD,		/* Wait for dead controller to stop */
+ 	EHCI_HRTIMER_UNLINK_INTR,	/* Wait for interrupt QH unlink */
+ 	EHCI_HRTIMER_FREE_ITDS,		/* Wait for unused iTDs and siTDs */
++	EHCI_HRTIMER_IAA_WATCHDOG,	/* Handle lost IAA interrupts */
+ 	EHCI_HRTIMER_DISABLE_PERIODIC,	/* Wait to disable periodic sched */
+ 	EHCI_HRTIMER_DISABLE_ASYNC,	/* Wait to disable async sched */
+ 	EHCI_HRTIMER_NUM_EVENTS		/* Must come last */
+@@ -168,7 +169,6 @@ struct ehci_hcd {			/* one per controller */
+ 	struct dma_pool		*itd_pool;	/* itd per iso urb */
+ 	struct dma_pool		*sitd_pool;	/* sitd per split iso urb */
+ 
+-	struct timer_list	iaa_watchdog;
+ 	struct timer_list	watchdog;
+ 	unsigned long		actions;
+ 	unsigned		periodic_stamp;
+@@ -228,20 +228,6 @@ static inline struct usb_hcd *ehci_to_hcd (struct ehci_hcd *ehci)
+ 	return container_of ((void *) ehci, struct usb_hcd, hcd_priv);
+ }
+ 
+-
+-static inline void
+-iaa_watchdog_start(struct ehci_hcd *ehci)
+-{
+-	WARN_ON(timer_pending(&ehci->iaa_watchdog));
+-	mod_timer(&ehci->iaa_watchdog,
+-			jiffies + msecs_to_jiffies(EHCI_IAA_MSECS));
+-}
+-
+-static inline void iaa_watchdog_done(struct ehci_hcd *ehci)
+-{
+-	del_timer(&ehci->iaa_watchdog);
+-}
+-
+ enum ehci_timer_action {
+ 	TIMER_IO_WATCHDOG,
+ 	TIMER_ASYNC_SHRINK,

commit 8c5bf7be56f1a8aecc1f802f132d53f556a9bc45
+Author: Alan Stern 
+Date:   Wed Jul 11 11:22:39 2012 -0400
+
+    USB: EHCI: don't refcount iso_stream structures
+    
+    This patch (as1580) makes ehci_iso_stream structures behave more like
+    QHs, in that they will remain allocated until their isochronous
+    endpoint is disabled.  This will come in useful in the future, when
+    periodic bandwidth gets allocated as an altsetting is installed rather
+    than on-the-fly.
+    
+    For now, the change to the ehci_iso_stream lifetimes means that each
+    structure is always deallocated at exactly one spot in
+    ehci_endpoint_disable() and never used again.  As a result, it is no
+    longer necessary to use reference counting on these things, and the
+    patch removes it.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 98b945840c9e..fb1966cf5649 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1085,8 +1085,14 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 	 * accelerate iso completions ... so spin a while.
+ 	 */
+ 	if (qh->hw == NULL) {
+-		ehci_vdbg (ehci, "iso delay\n");
+-		goto idle_timeout;
++		struct ehci_iso_stream	*stream = ep->hcpriv;
++
++		if (!list_empty(&stream->td_list))
++			goto idle_timeout;
++
++		/* BUG_ON(!list_empty(&stream->free_list)); */
++		kfree(stream);
++		goto done;
+ 	}
+ 
+ 	if (ehci->rh_state < EHCI_RH_RUNNING)
+@@ -1127,8 +1133,8 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 			list_empty (&qh->qtd_list) ? "" : "(has tds)");
+ 		break;
+ 	}
++ done:
+ 	ep->hcpriv = NULL;
+-done:
+ 	spin_unlock_irqrestore (&ehci->lock, flags);
+ }
+ 
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 1e4f13c11b6a..11b2f21d7ac1 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -934,7 +934,6 @@ iso_stream_alloc (gfp_t mem_flags)
+ 		INIT_LIST_HEAD(&stream->td_list);
+ 		INIT_LIST_HEAD(&stream->free_list);
+ 		stream->next_uframe = -1;
+-		stream->refcount = 1;
+ 	}
+ 	return stream;
+ }
+@@ -1034,32 +1033,6 @@ iso_stream_init (
+ 	stream->maxp = maxp;
+ }
+ 
+-static void
+-iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream)
+-{
+-	stream->refcount--;
+-
+-	/* free whenever just a dev->ep reference remains.
+-	 * not like a QH -- no persistent state (toggle, halt)
+-	 */
+-	if (stream->refcount == 1) {
+-		// BUG_ON (!list_empty(&stream->td_list));
+-
+-		if (stream->ep)
+-			stream->ep->hcpriv = NULL;
+-
+-		kfree(stream);
+-	}
+-}
+-
+-static inline struct ehci_iso_stream *
+-iso_stream_get (struct ehci_iso_stream *stream)
+-{
+-	if (likely (stream != NULL))
+-		stream->refcount++;
+-	return stream;
+-}
+-
+ static struct ehci_iso_stream *
+ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb)
+ {
+@@ -1080,7 +1053,6 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb)
+ 	if (unlikely (stream == NULL)) {
+ 		stream = iso_stream_alloc(GFP_ATOMIC);
+ 		if (likely (stream != NULL)) {
+-			/* dev->ep owns the initial refcount */
+ 			ep->hcpriv = stream;
+ 			stream->ep = ep;
+ 			iso_stream_init(ehci, stream, urb->dev, urb->pipe,
+@@ -1095,9 +1067,6 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb)
+ 		stream = NULL;
+ 	}
+ 
+-	/* caller guarantees an eventual matching iso_stream_put */
+-	stream = iso_stream_get (stream);
+-
+ 	spin_unlock_irqrestore (&ehci->lock, flags);
+ 	return stream;
+ }
+@@ -1611,7 +1580,7 @@ static void itd_link_urb(
+ 			itd = list_entry (iso_sched->td_list.next,
+ 					struct ehci_itd, itd_list);
+ 			list_move_tail (&itd->itd_list, &stream->td_list);
+-			itd->stream = iso_stream_get (stream);
++			itd->stream = stream;
+ 			itd->urb = urb;
+ 			itd_init (ehci, stream, itd);
+ 		}
+@@ -1735,7 +1704,6 @@ itd_complete (
+ 			dev->devpath, stream->bEndpointAddress & 0x0f,
+ 			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
+ 	}
+-	iso_stream_put (ehci, stream);
+ 
+ done:
+ 	itd->urb = NULL;
+@@ -1750,7 +1718,6 @@ itd_complete (
+ 		start_free_itds(ehci);
+ 	}
+ 
+-	iso_stream_put(ehci, stream);
+ 	return retval;
+ }
+ 
+@@ -1807,12 +1774,9 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb,
+ 		itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
+ 	else
+ 		usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
+-done_not_linked:
++ done_not_linked:
+ 	spin_unlock_irqrestore (&ehci->lock, flags);
+-
+-done:
+-	if (unlikely (status < 0))
+-		iso_stream_put (ehci, stream);
++ done:
+ 	return status;
+ }
+ 
+@@ -2028,7 +1992,7 @@ static void sitd_link_urb(
+ 		sitd = list_entry (sched->td_list.next,
+ 				struct ehci_sitd, sitd_list);
+ 		list_move_tail (&sitd->sitd_list, &stream->td_list);
+-		sitd->stream = iso_stream_get (stream);
++		sitd->stream = stream;
+ 		sitd->urb = urb;
+ 
+ 		sitd_patch(ehci, stream, sitd, sched, packet);
+@@ -2126,7 +2090,6 @@ sitd_complete (
+ 			dev->devpath, stream->bEndpointAddress & 0x0f,
+ 			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
+ 	}
+-	iso_stream_put (ehci, stream);
+ 
+ done:
+ 	sitd->urb = NULL;
+@@ -2141,7 +2104,6 @@ sitd_complete (
+ 		start_free_itds(ehci);
+ 	}
+ 
+-	iso_stream_put(ehci, stream);
+ 	return retval;
+ }
+ 
+@@ -2195,12 +2157,9 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
+ 		sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
+ 	else
+ 		usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
+-done_not_linked:
++ done_not_linked:
+ 	spin_unlock_irqrestore (&ehci->lock, flags);
+-
+-done:
+-	if (status < 0)
+-		iso_stream_put (ehci, stream);
++ done:
+ 	return status;
+ }
+ 
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index bcfbb175e2b4..755e30b0000b 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -386,7 +386,7 @@ struct ehci_qh_hw {
+ } __attribute__ ((aligned(32)));
+ 
+ struct ehci_qh {
+-	struct ehci_qh_hw	*hw;
++	struct ehci_qh_hw	*hw;		/* Must come first */
+ 	/* the rest is HCD-private */
+ 	dma_addr_t		qh_dma;		/* address of qh */
+ 	union ehci_shadow	qh_next;	/* ptr to qh; or periodic */
+@@ -453,7 +453,6 @@ struct ehci_iso_stream {
+ 	/* first field matches ehci_hq, but is NULL */
+ 	struct ehci_qh_hw	*hw;
+ 
+-	u32			refcount;
+ 	u8			bEndpointAddress;
+ 	u8			highspeed;
+ 	struct list_head	td_list;	/* queued itds/sitds */

commit 55934eb3b9fa52eb53b9d7342267fc73c38206aa
+Author: Alan Stern 
+Date:   Wed Jul 11 11:22:35 2012 -0400
+
+    USB: EHCI: use hrtimer for (s)iTD deallocation
+    
+    This patch (as1579) adds an hrtimer event to handle deallocation of
+    iTDs and siTDs in ehci-hcd.
+    
+    Because of the frame-oriented approach used by the EHCI periodic
+    schedule, the hardware can continue to access the Transfer Descriptor
+    for isochronous (or split-isochronous) transactions for up to a
+    millisecond after the transaction completes.  The iTD (or siTD) must
+    not be reused before then.
+    
+    The strategy currently used involves putting completed iTDs on a list
+    of cached entries and every so often returning them to the endpoint's
+    free list.  The new strategy reduces overhead by putting completed
+    iTDs back on the free list immediately, although they are not reused
+    until it is safe to do so.
+    
+    When the isochronous endpoint stops (its queue becomes empty), the
+    iTDs on its free list get moved to a global list, from which they will
+    be deallocated after a minimum of 2 ms.  This delay is what the new
+    hrtimer event is for.
+    
+    Overall this may not be a tremendous improvement over the current
+    code, but to me it seems a lot more clear and logical.  In addition,
+    it removes the need for each iTD to keep a reference to the
+    ehci_iso_stream it belongs to, since the iTD never needs to be moved
+    back to the stream's free list from the global list.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 1676c66b8530..98b945840c9e 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -509,6 +509,7 @@ static void ehci_stop (struct usb_hcd *hcd)
+ 	spin_lock_irq (&ehci->lock);
+ 	if (ehci->async)
+ 		ehci_work (ehci);
++	end_free_itds(ehci);
+ 	spin_unlock_irq (&ehci->lock);
+ 	ehci_mem_cleanup (ehci);
+ 
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 8aa740dc510d..6ad806bbe468 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -303,6 +303,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 	if (ehci->async_unlink)
+ 		end_unlink_async(ehci);
+ 	ehci_handle_intr_unlinks(ehci);
++	end_free_itds(ehci);
+ 
+ 	/* allow remote wakeup */
+ 	mask = INTR_MASK;
+diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
+index 93132d8ad360..ef2c3a1eca4b 100644
+--- a/drivers/usb/host/ehci-mem.c
++++ b/drivers/usb/host/ehci-mem.c
+@@ -118,7 +118,6 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags)
+ 
+ static void ehci_mem_cleanup (struct ehci_hcd *ehci)
+ {
+-	free_cached_lists(ehci);
+ 	if (ehci->async)
+ 		qh_destroy(ehci, ehci->async);
+ 	ehci->async = NULL;
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index eec8446f8ded..1e4f13c11b6a 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1045,31 +1045,6 @@ iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream)
+ 	if (stream->refcount == 1) {
+ 		// BUG_ON (!list_empty(&stream->td_list));
+ 
+-		while (!list_empty (&stream->free_list)) {
+-			struct list_head	*entry;
+-
+-			entry = stream->free_list.next;
+-			list_del (entry);
+-
+-			/* knows about ITD vs SITD */
+-			if (stream->highspeed) {
+-				struct ehci_itd		*itd;
+-
+-				itd = list_entry (entry, struct ehci_itd,
+-						itd_list);
+-				dma_pool_free (ehci->itd_pool, itd,
+-						itd->itd_dma);
+-			} else {
+-				struct ehci_sitd	*sitd;
+-
+-				sitd = list_entry (entry, struct ehci_sitd,
+-						sitd_list);
+-				dma_pool_free (ehci->sitd_pool, sitd,
+-						sitd->sitd_dma);
+-			}
+-		}
+-
+-		stream->bEndpointAddress &= 0x0f;
+ 		if (stream->ep)
+ 			stream->ep->hcpriv = NULL;
+ 
+@@ -1230,17 +1205,19 @@ itd_urb_transaction (
+ 	spin_lock_irqsave (&ehci->lock, flags);
+ 	for (i = 0; i < num_itds; i++) {
+ 
+-		/* free_list.next might be cache-hot ... but maybe
+-		 * the HC caches it too. avoid that issue for now.
++		/*
++		 * Use iTDs from the free list, but not iTDs that may
++		 * still be in use by the hardware.
+ 		 */
+-
+-		/* prefer previously-allocated itds */
+-		if (likely (!list_empty(&stream->free_list))) {
+-			itd = list_entry (stream->free_list.prev,
++		if (likely(!list_empty(&stream->free_list))) {
++			itd = list_first_entry(&stream->free_list,
+ 					struct ehci_itd, itd_list);
++			if (itd->frame == ehci->clock_frame)
++				goto alloc_itd;
+ 			list_del (&itd->itd_list);
+ 			itd_dma = itd->itd_dma;
+ 		} else {
++ alloc_itd:
+ 			spin_unlock_irqrestore (&ehci->lock, flags);
+ 			itd = dma_pool_alloc (ehci->itd_pool, mem_flags,
+ 					&itd_dma);
+@@ -1762,24 +1739,18 @@ itd_complete (
+ 
+ done:
+ 	itd->urb = NULL;
+-	if (ehci->clock_frame != itd->frame || itd->index[7] != -1) {
+-		/* OK to recycle this ITD now. */
+-		itd->stream = NULL;
+-		list_move(&itd->itd_list, &stream->free_list);
+-		iso_stream_put(ehci, stream);
+-	} else {
+-		/* HW might remember this ITD, so we can't recycle it yet.
+-		 * Move it to a safe place until a new frame starts.
+-		 */
+-		list_move(&itd->itd_list, &ehci->cached_itd_list);
+-		if (stream->refcount == 2) {
+-			/* If iso_stream_put() were called here, stream
+-			 * would be freed.  Instead, just prevent reuse.
+-			 */
+-			stream->ep->hcpriv = NULL;
+-			stream->ep = NULL;
+-		}
++
++	/* Add to the end of the free list for later reuse */
++	list_move_tail(&itd->itd_list, &stream->free_list);
++
++	/* Recycle the iTDs when the pipeline is empty (ep no longer in use) */
++	if (list_empty(&stream->td_list)) {
++		list_splice_tail_init(&stream->free_list,
++				&ehci->cached_itd_list);
++		start_free_itds(ehci);
+ 	}
++
++	iso_stream_put(ehci, stream);
+ 	return retval;
+ }
+ 
+@@ -1930,17 +1901,19 @@ sitd_urb_transaction (
+ 		 * means we never need two sitds for full speed packets.
+ 		 */
+ 
+-		/* free_list.next might be cache-hot ... but maybe
+-		 * the HC caches it too. avoid that issue for now.
++		/*
++		 * Use siTDs from the free list, but not siTDs that may
++		 * still be in use by the hardware.
+ 		 */
+-
+-		/* prefer previously-allocated sitds */
+-		if (!list_empty(&stream->free_list)) {
+-			sitd = list_entry (stream->free_list.prev,
++		if (likely(!list_empty(&stream->free_list))) {
++			sitd = list_first_entry(&stream->free_list,
+ 					 struct ehci_sitd, sitd_list);
++			if (sitd->frame == ehci->clock_frame)
++				goto alloc_sitd;
+ 			list_del (&sitd->sitd_list);
+ 			sitd_dma = sitd->sitd_dma;
+ 		} else {
++ alloc_sitd:
+ 			spin_unlock_irqrestore (&ehci->lock, flags);
+ 			sitd = dma_pool_alloc (ehci->sitd_pool, mem_flags,
+ 					&sitd_dma);
+@@ -2157,24 +2130,18 @@ sitd_complete (
+ 
+ done:
+ 	sitd->urb = NULL;
+-	if (ehci->clock_frame != sitd->frame) {
+-		/* OK to recycle this SITD now. */
+-		sitd->stream = NULL;
+-		list_move(&sitd->sitd_list, &stream->free_list);
+-		iso_stream_put(ehci, stream);
+-	} else {
+-		/* HW might remember this SITD, so we can't recycle it yet.
+-		 * Move it to a safe place until a new frame starts.
+-		 */
+-		list_move(&sitd->sitd_list, &ehci->cached_sitd_list);
+-		if (stream->refcount == 2) {
+-			/* If iso_stream_put() were called here, stream
+-			 * would be freed.  Instead, just prevent reuse.
+-			 */
+-			stream->ep->hcpriv = NULL;
+-			stream->ep = NULL;
+-		}
++
++	/* Add to the end of the free list for later reuse */
++	list_move_tail(&sitd->sitd_list, &stream->free_list);
++
++	/* Recycle the siTDs when the pipeline is empty (ep no longer in use) */
++	if (list_empty(&stream->td_list)) {
++		list_splice_tail_init(&stream->free_list,
++				&ehci->cached_sitd_list);
++		start_free_itds(ehci);
+ 	}
++
++	iso_stream_put(ehci, stream);
+ 	return retval;
+ }
+ 
+@@ -2239,28 +2206,6 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-static void free_cached_lists(struct ehci_hcd *ehci)
+-{
+-	struct ehci_itd *itd, *n;
+-	struct ehci_sitd *sitd, *sn;
+-
+-	list_for_each_entry_safe(itd, n, &ehci->cached_itd_list, itd_list) {
+-		struct ehci_iso_stream	*stream = itd->stream;
+-		itd->stream = NULL;
+-		list_move(&itd->itd_list, &stream->free_list);
+-		iso_stream_put(ehci, stream);
+-	}
+-
+-	list_for_each_entry_safe(sitd, sn, &ehci->cached_sitd_list, sitd_list) {
+-		struct ehci_iso_stream	*stream = sitd->stream;
+-		sitd->stream = NULL;
+-		list_move(&sitd->sitd_list, &stream->free_list);
+-		iso_stream_put(ehci, stream);
+-	}
+-}
+-
+-/*-------------------------------------------------------------------------*/
+-
+ static void
+ scan_periodic (struct ehci_hcd *ehci)
+ {
+@@ -2282,10 +2227,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 		clock = now_uframe + mod - 1;
+ 		clock_frame = -1;
+ 	}
+-	if (ehci->clock_frame != clock_frame) {
+-		free_cached_lists(ehci);
+-		ehci->clock_frame = clock_frame;
+-	}
++	ehci->clock_frame = clock_frame;
+ 	clock &= mod - 1;
+ 	clock_frame = clock >> 3;
+ 	++ehci->periodic_stamp;
+@@ -2463,7 +2405,6 @@ scan_periodic (struct ehci_hcd *ehci)
+ 			clock = now;
+ 			clock_frame = clock >> 3;
+ 			if (ehci->clock_frame != clock_frame) {
+-				free_cached_lists(ehci);
+ 				ehci->clock_frame = clock_frame;
+ 				++ehci->periodic_stamp;
+ 			}
+diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
+index 0c5326a8883c..8feb60ff4228 100644
+--- a/drivers/usb/host/ehci-timer.c
++++ b/drivers/usb/host/ehci-timer.c
+@@ -71,6 +71,7 @@ static unsigned event_delays_ns[] = {
+ 	1 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_POLL_PSS */
+ 	1 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_POLL_DEAD */
+ 	1125 * NSEC_PER_USEC,	/* EHCI_HRTIMER_UNLINK_INTR */
++	2 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_FREE_ITDS */
+ 	10 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_DISABLE_PERIODIC */
+ 	15 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_DISABLE_ASYNC */
+ };
+@@ -165,7 +166,6 @@ static void ehci_poll_PSS(struct ehci_hcd *ehci)
+ 
+ 	/* The status is up-to-date; restart or stop the schedule as needed */
+ 	if (want == 0) {	/* Stopped */
+-		free_cached_lists(ehci);
+ 		if (ehci->periodic_count > 0) {
+ 
+ 			/* make sure ehci_work scans these */
+@@ -188,9 +188,6 @@ static void ehci_poll_PSS(struct ehci_hcd *ehci)
+ static void ehci_disable_PSE(struct ehci_hcd *ehci)
+ {
+ 	ehci_clear_command_bit(ehci, CMD_PSE);
+-
+-	/* Poll to see when it actually stops */
+-	ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);
+ }
+ 
+ 
+@@ -250,6 +247,50 @@ static void ehci_handle_intr_unlinks(struct ehci_hcd *ehci)
+ }
+ 
+ 
++/* Start another free-iTDs/siTDs cycle */
++static void start_free_itds(struct ehci_hcd *ehci)
++{
++	if (!(ehci->enabled_hrtimer_events & BIT(EHCI_HRTIMER_FREE_ITDS))) {
++		ehci->last_itd_to_free = list_entry(
++				ehci->cached_itd_list.prev,
++				struct ehci_itd, itd_list);
++		ehci->last_sitd_to_free = list_entry(
++				ehci->cached_sitd_list.prev,
++				struct ehci_sitd, sitd_list);
++		ehci_enable_event(ehci, EHCI_HRTIMER_FREE_ITDS, true);
++	}
++}
++
++/* Wait for controller to stop using old iTDs and siTDs */
++static void end_free_itds(struct ehci_hcd *ehci)
++{
++	struct ehci_itd		*itd, *n;
++	struct ehci_sitd	*sitd, *sn;
++
++	if (ehci->rh_state < EHCI_RH_RUNNING) {
++		ehci->last_itd_to_free = NULL;
++		ehci->last_sitd_to_free = NULL;
++	}
++
++	list_for_each_entry_safe(itd, n, &ehci->cached_itd_list, itd_list) {
++		list_del(&itd->itd_list);
++		dma_pool_free(ehci->itd_pool, itd, itd->itd_dma);
++		if (itd == ehci->last_itd_to_free)
++			break;
++	}
++	list_for_each_entry_safe(sitd, sn, &ehci->cached_sitd_list, sitd_list) {
++		list_del(&sitd->sitd_list);
++		dma_pool_free(ehci->sitd_pool, sitd, sitd->sitd_dma);
++		if (sitd == ehci->last_sitd_to_free)
++			break;
++	}
++
++	if (!list_empty(&ehci->cached_itd_list) ||
++			!list_empty(&ehci->cached_sitd_list))
++		start_free_itds(ehci);
++}
++
++
+ /*
+  * Handler functions for the hrtimer event types.
+  * Keep this array in the same order as the event types indexed by
+@@ -260,6 +301,7 @@ static void (*event_handlers[])(struct ehci_hcd *) = {
+ 	ehci_poll_PSS,			/* EHCI_HRTIMER_POLL_PSS */
+ 	ehci_handle_controller_death,	/* EHCI_HRTIMER_POLL_DEAD */
+ 	ehci_handle_intr_unlinks,	/* EHCI_HRTIMER_UNLINK_INTR */
++	end_free_itds,			/* EHCI_HRTIMER_FREE_ITDS */
+ 	ehci_disable_PSE,		/* EHCI_HRTIMER_DISABLE_PERIODIC */
+ 	ehci_disable_ASE,		/* EHCI_HRTIMER_DISABLE_ASYNC */
+ };
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 6874d89b0b64..bcfbb175e2b4 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -83,6 +83,7 @@ enum ehci_hrtimer_event {
+ 	EHCI_HRTIMER_POLL_PSS,		/* Poll for periodic schedule off */
+ 	EHCI_HRTIMER_POLL_DEAD,		/* Wait for dead controller to stop */
+ 	EHCI_HRTIMER_UNLINK_INTR,	/* Wait for interrupt QH unlink */
++	EHCI_HRTIMER_FREE_ITDS,		/* Wait for unused iTDs and siTDs */
+ 	EHCI_HRTIMER_DISABLE_PERIODIC,	/* Wait to disable periodic sched */
+ 	EHCI_HRTIMER_DISABLE_ASYNC,	/* Wait to disable async sched */
+ 	EHCI_HRTIMER_NUM_EVENTS		/* Must come last */
+@@ -139,7 +140,9 @@ struct ehci_hcd {			/* one per controller */
+ 
+ 	/* list of itds & sitds completed while clock_frame was still active */
+ 	struct list_head	cached_itd_list;
++	struct ehci_itd		*last_itd_to_free;
+ 	struct list_head	cached_sitd_list;
++	struct ehci_sitd	*last_sitd_to_free;
+ 	unsigned		clock_frame;
+ 
+ 	/* per root hub port */
+@@ -250,8 +253,6 @@ timer_action_done (struct ehci_hcd *ehci, enum ehci_timer_action action)
+ 	clear_bit (action, &ehci->actions);
+ }
+ 
+-static void free_cached_lists(struct ehci_hcd *ehci);
+-
+ /*-------------------------------------------------------------------------*/
+ 
+ #include 

commit bf6387bcd16975ba8952b094f262a359d74e1c8a
+Author: Alan Stern 
+Date:   Wed Jul 11 11:22:31 2012 -0400
+
+    USB: EHCI: use hrtimer for controller death
+    
+    This patch (as1578) adds an hrtimer event to handle the death of an
+    EHCI controller.  When a controller dies, it doesn't necessarily stop
+    running right away.  The new event polls at 1-ms intervals to see when
+    all activity has safely stopped.  This replaces a busy-wait polling
+    loop in the current code.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index edcfd2c4295e..1676c66b8530 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -888,20 +888,20 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 	/* PCI errors [4.15.2.4] */
+ 	if (unlikely ((status & STS_FATAL) != 0)) {
+ 		ehci_err(ehci, "fatal error\n");
+-		ehci->rh_state = EHCI_RH_STOPPING;
+ 		dbg_cmd(ehci, "fatal", cmd);
+ 		dbg_status(ehci, "fatal", status);
+-		ehci_halt(ehci);
+ dead:
+-		ehci->enabled_hrtimer_events = 0;
+-		hrtimer_try_to_cancel(&ehci->hrtimer);
+-		ehci_reset(ehci);
+-		ehci_writel(ehci, 0, &ehci->regs->configured_flag);
+ 		usb_hc_died(hcd);
+-		/* generic layer kills/unlinks all urbs, then
+-		 * uses ehci_stop to clean up the rest
+-		 */
+-		bh = 1;
++
++		/* Don't let the controller do anything more */
++		ehci->rh_state = EHCI_RH_STOPPING;
++		ehci->command &= ~(CMD_RUN | CMD_ASE | CMD_PSE);
++		ehci_writel(ehci, ehci->command, &ehci->regs->command);
++		ehci_writel(ehci, 0, &ehci->regs->intr_enable);
++		ehci_handle_controller_death(ehci);
++
++		/* Handle completions when the controller stops */
++		bh = 0;
+ 	}
+ 
+ 	if (bh)
+diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
+index bd8b591771b0..0c5326a8883c 100644
+--- a/drivers/usb/host/ehci-timer.c
++++ b/drivers/usb/host/ehci-timer.c
+@@ -69,6 +69,7 @@ static void ehci_clear_command_bit(struct ehci_hcd *ehci, u32 bit)
+ static unsigned event_delays_ns[] = {
+ 	1 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_POLL_ASS */
+ 	1 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_POLL_PSS */
++	1 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_POLL_DEAD */
+ 	1125 * NSEC_PER_USEC,	/* EHCI_HRTIMER_UNLINK_INTR */
+ 	10 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_DISABLE_PERIODIC */
+ 	15 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_DISABLE_ASYNC */
+@@ -193,6 +194,30 @@ static void ehci_disable_PSE(struct ehci_hcd *ehci)
+ }
+ 
+ 
++/* Poll the STS_HALT status bit; see when a dead controller stops */
++static void ehci_handle_controller_death(struct ehci_hcd *ehci)
++{
++	if (!(ehci_readl(ehci, &ehci->regs->status) & STS_HALT)) {
++
++		/* Give up after a few milliseconds */
++		if (ehci->died_poll_count++ < 5) {
++			/* Try again later */
++			ehci_enable_event(ehci, EHCI_HRTIMER_POLL_DEAD, true);
++			return;
++		}
++		ehci_warn(ehci, "Waited too long for the controller to stop, giving up\n");
++	}
++
++	/* Clean up the mess */
++	ehci->rh_state = EHCI_RH_HALTED;
++	ehci_writel(ehci, 0, &ehci->regs->configured_flag);
++	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
++	ehci_work(ehci);
++
++	/* Not in process context, so don't try to reset the controller */
++}
++
++
+ /* Handle unlinked interrupt QHs once they are gone from the hardware */
+ static void ehci_handle_intr_unlinks(struct ehci_hcd *ehci)
+ {
+@@ -233,6 +258,7 @@ static void ehci_handle_intr_unlinks(struct ehci_hcd *ehci)
+ static void (*event_handlers[])(struct ehci_hcd *) = {
+ 	ehci_poll_ASS,			/* EHCI_HRTIMER_POLL_ASS */
+ 	ehci_poll_PSS,			/* EHCI_HRTIMER_POLL_PSS */
++	ehci_handle_controller_death,	/* EHCI_HRTIMER_POLL_DEAD */
+ 	ehci_handle_intr_unlinks,	/* EHCI_HRTIMER_UNLINK_INTR */
+ 	ehci_disable_PSE,		/* EHCI_HRTIMER_DISABLE_PERIODIC */
+ 	ehci_disable_ASE,		/* EHCI_HRTIMER_DISABLE_ASYNC */
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index f36f1f85d7fd..6874d89b0b64 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -81,6 +81,7 @@ enum ehci_rh_state {
+ enum ehci_hrtimer_event {
+ 	EHCI_HRTIMER_POLL_ASS,		/* Poll for async schedule off */
+ 	EHCI_HRTIMER_POLL_PSS,		/* Poll for periodic schedule off */
++	EHCI_HRTIMER_POLL_DEAD,		/* Wait for dead controller to stop */
+ 	EHCI_HRTIMER_UNLINK_INTR,	/* Wait for interrupt QH unlink */
+ 	EHCI_HRTIMER_DISABLE_PERIODIC,	/* Wait to disable periodic sched */
+ 	EHCI_HRTIMER_DISABLE_ASYNC,	/* Wait to disable async sched */
+@@ -97,6 +98,7 @@ struct ehci_hcd {			/* one per controller */
+ 
+ 	int			PSS_poll_count;
+ 	int			ASS_poll_count;
++	int			died_poll_count;
+ 
+ 	/* glue to PCI and HCD framework */
+ 	struct ehci_caps __iomem *caps;

commit df2022553dd8d34d49e16c19d851ea619438f0ef
+Author: Alan Stern 
+Date:   Wed Jul 11 11:22:26 2012 -0400
+
+    USB: EHCI: use hrtimer for interrupt QH unlink
+    
+    This patch (as1577) adds hrtimer support for unlinking interrupt QHs
+    in ehci-hcd.  The current code relies on a fixed delay of either 2 or
+    55 us, which is not always adequate and in any case is totally bogus.
+    Thanks to internal caching, the EHCI hardware may continue to access
+    an interrupt QH for more than a millisecond after it has been unlinked.
+    
+    In fact, the EHCI spec doesn't say how long to wait before using an
+    unlinked interrupt QH.  The patch sets the delay to 9 microframes
+    minimum, which ought to be adequate.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 21d6fbc0a327..edcfd2c4295e 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -309,6 +309,8 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
+ 
+ static void end_unlink_async(struct ehci_hcd *ehci);
+ static void ehci_work(struct ehci_hcd *ehci);
++static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh);
++static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh);
+ 
+ #include "ehci-timer.c"
+ #include "ehci-hub.c"
+@@ -1034,7 +1036,7 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ 		switch (qh->qh_state) {
+ 		case QH_STATE_LINKED:
+ 		case QH_STATE_COMPLETING:
+-			intr_deschedule (ehci, qh);
++			start_unlink_intr(ehci, qh);
+ 			break;
+ 		case QH_STATE_IDLE:
+ 			qh_completions (ehci, qh);
+@@ -1164,7 +1166,7 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 			if (eptype == USB_ENDPOINT_XFER_BULK)
+ 				unlink_async(ehci, qh);
+ 			else
+-				intr_deschedule(ehci, qh);
++				start_unlink_intr(ehci, qh);
+ 		}
+ 	}
+ 	spin_unlock_irqrestore(&ehci->lock, flags);
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 25329e4b844f..8aa740dc510d 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -302,6 +302,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 
+ 	if (ehci->async_unlink)
+ 		end_unlink_async(ehci);
++	ehci_handle_intr_unlinks(ehci);
+ 
+ 	/* allow remote wakeup */
+ 	mask = INTR_MASK;
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 69b1861e4325..eec8446f8ded 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -578,12 +578,20 @@ static void qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	unsigned	i;
+ 	unsigned	period;
+ 
+-	// FIXME:
+-	// IF this isn't high speed
+-	//   and this qh is active in the current uframe
+-	//   (and overlay token SplitXstate is false?)
+-	// THEN
+-	//   qh->hw_info1 |= cpu_to_hc32(1 << 7 /* "ignore" */);
++	/*
++	 * If qh is for a low/full-speed device, simply unlinking it
++	 * could interfere with an ongoing split transaction.  To unlink
++	 * it safely would require setting the QH_INACTIVATE bit and
++	 * waiting at least one frame, as described in EHCI 4.12.2.5.
++	 *
++	 * We won't bother with any of this.  Instead, we assume that the
++	 * only reason for unlinking an interrupt QH while the current URB
++	 * is still active is to dequeue all the URBs (flush the whole
++	 * endpoint queue).
++	 *
++	 * If rebalancing the periodic schedule is ever implemented, this
++	 * approach will no longer be valid.
++	 */
+ 
+ 	/* high bandwidth, or otherwise part of every microframe */
+ 	if ((period = qh->period) == 0)
+@@ -608,12 +616,8 @@ static void qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	qh->qh_next.ptr = NULL;
+ }
+ 
+-static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
++static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ {
+-	unsigned		wait;
+-	struct ehci_qh_hw	*hw = qh->hw;
+-	int			rc;
+-
+ 	/* If the QH isn't linked then there's nothing we can do
+ 	 * unless we were called during a giveback, in which case
+ 	 * qh_completions() has to deal with it.
+@@ -626,28 +630,45 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 
+ 	qh_unlink_periodic (ehci, qh);
+ 
+-	/* simple/paranoid:  always delay, expecting the HC needs to read
+-	 * qh->hw_next or finish a writeback after SPLIT/CSPLIT ... and
+-	 * expect khubd to clean up after any CSPLITs we won't issue.
+-	 * active high speed queues may need bigger delays...
++	/* Make sure the unlinks are visible before starting the timer */
++	wmb();
++
++	/*
++	 * The EHCI spec doesn't say how long it takes the controller to
++	 * stop accessing an unlinked interrupt QH.  The timer delay is
++	 * 9 uframes; presumably that will be long enough.
+ 	 */
+-	if (list_empty (&qh->qtd_list)
+-			|| (cpu_to_hc32(ehci, QH_CMASK)
+-					& hw->hw_info2) != 0)
+-		wait = 2;
++	qh->unlink_cycle = ehci->intr_unlink_cycle;
++
++	/* New entries go at the end of the intr_unlink list */
++	if (ehci->intr_unlink)
++		ehci->intr_unlink_last->unlink_next = qh;
+ 	else
+-		wait = 55;	/* worst case: 3 * 1024 */
++		ehci->intr_unlink = qh;
++	ehci->intr_unlink_last = qh;
++
++	if (ehci->intr_unlinking)
++		;	/* Avoid recursive calls */
++	else if (ehci->rh_state < EHCI_RH_RUNNING)
++		ehci_handle_intr_unlinks(ehci);
++	else if (ehci->intr_unlink == qh) {
++		ehci_enable_event(ehci, EHCI_HRTIMER_UNLINK_INTR, true);
++		++ehci->intr_unlink_cycle;
++	}
++}
++
++static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)
++{
++	struct ehci_qh_hw	*hw = qh->hw;
++	int			rc;
+ 
+-	udelay (wait);
+ 	qh->qh_state = QH_STATE_IDLE;
+ 	hw->hw_next = EHCI_LIST_END(ehci);
+-	wmb ();
+ 
+ 	qh_completions(ehci, qh);
+ 
+ 	/* reschedule QH iff another request is queued */
+-	if (!list_empty(&qh->qtd_list) &&
+-			ehci->rh_state == EHCI_RH_RUNNING) {
++	if (!list_empty(&qh->qtd_list) && ehci->rh_state == EHCI_RH_RUNNING) {
+ 		rc = qh_schedule(ehci, qh);
+ 
+ 		/* An error here likely indicates handshake failure
+@@ -2302,7 +2323,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 						temp.qh->stamp = ehci->periodic_stamp;
+ 					if (unlikely(list_empty(&temp.qh->qtd_list) ||
+ 							temp.qh->needs_rescan))
+-						intr_deschedule(ehci, temp.qh);
++						start_unlink_intr(ehci, temp.qh);
+ 				}
+ 				break;
+ 			case Q_TYPE_FSTN:
+diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
+index 1e907dd3bb1b..bd8b591771b0 100644
+--- a/drivers/usb/host/ehci-timer.c
++++ b/drivers/usb/host/ehci-timer.c
+@@ -69,6 +69,7 @@ static void ehci_clear_command_bit(struct ehci_hcd *ehci, u32 bit)
+ static unsigned event_delays_ns[] = {
+ 	1 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_POLL_ASS */
+ 	1 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_POLL_PSS */
++	1125 * NSEC_PER_USEC,	/* EHCI_HRTIMER_UNLINK_INTR */
+ 	10 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_DISABLE_PERIODIC */
+ 	15 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_DISABLE_ASYNC */
+ };
+@@ -192,6 +193,38 @@ static void ehci_disable_PSE(struct ehci_hcd *ehci)
+ }
+ 
+ 
++/* Handle unlinked interrupt QHs once they are gone from the hardware */
++static void ehci_handle_intr_unlinks(struct ehci_hcd *ehci)
++{
++	bool		stopped = (ehci->rh_state < EHCI_RH_RUNNING);
++
++	/*
++	 * Process all the QHs on the intr_unlink list that were added
++	 * before the current unlink cycle began.  The list is in
++	 * temporal order, so stop when we reach the first entry in the
++	 * current cycle.  But if the root hub isn't running then
++	 * process all the QHs on the list.
++	 */
++	ehci->intr_unlinking = true;
++	while (ehci->intr_unlink) {
++		struct ehci_qh	*qh = ehci->intr_unlink;
++
++		if (!stopped && qh->unlink_cycle == ehci->intr_unlink_cycle)
++			break;
++		ehci->intr_unlink = qh->unlink_next;
++		qh->unlink_next = NULL;
++		end_unlink_intr(ehci, qh);
++	}
++
++	/* Handle remaining entries later */
++	if (ehci->intr_unlink) {
++		ehci_enable_event(ehci, EHCI_HRTIMER_UNLINK_INTR, true);
++		++ehci->intr_unlink_cycle;
++	}
++	ehci->intr_unlinking = false;
++}
++
++
+ /*
+  * Handler functions for the hrtimer event types.
+  * Keep this array in the same order as the event types indexed by
+@@ -200,6 +233,7 @@ static void ehci_disable_PSE(struct ehci_hcd *ehci)
+ static void (*event_handlers[])(struct ehci_hcd *) = {
+ 	ehci_poll_ASS,			/* EHCI_HRTIMER_POLL_ASS */
+ 	ehci_poll_PSS,			/* EHCI_HRTIMER_POLL_PSS */
++	ehci_handle_intr_unlinks,	/* EHCI_HRTIMER_UNLINK_INTR */
+ 	ehci_disable_PSE,		/* EHCI_HRTIMER_DISABLE_PERIODIC */
+ 	ehci_disable_ASE,		/* EHCI_HRTIMER_DISABLE_ASYNC */
+ };
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index bf06bbb77ba4..f36f1f85d7fd 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -81,6 +81,7 @@ enum ehci_rh_state {
+ enum ehci_hrtimer_event {
+ 	EHCI_HRTIMER_POLL_ASS,		/* Poll for async schedule off */
+ 	EHCI_HRTIMER_POLL_PSS,		/* Poll for periodic schedule off */
++	EHCI_HRTIMER_UNLINK_INTR,	/* Wait for interrupt QH unlink */
+ 	EHCI_HRTIMER_DISABLE_PERIODIC,	/* Wait to disable periodic sched */
+ 	EHCI_HRTIMER_DISABLE_ASYNC,	/* Wait to disable async sched */
+ 	EHCI_HRTIMER_NUM_EVENTS		/* Must come last */
+@@ -106,13 +107,16 @@ struct ehci_hcd {			/* one per controller */
+ 	spinlock_t		lock;
+ 	enum ehci_rh_state	rh_state;
+ 
++	/* general schedule support */
++	unsigned		scanning:1;
++	bool			intr_unlinking:1;
++
+ 	/* async schedule support */
+ 	struct ehci_qh		*async;
+ 	struct ehci_qh		*dummy;		/* For AMD quirk use */
+ 	struct ehci_qh		*async_unlink;
+ 	struct ehci_qh		*async_unlink_last;
+ 	struct ehci_qh		*qh_scan_next;
+-	unsigned		scanning : 1;
+ 	unsigned		async_count;	/* async activity count */
+ 
+ 	/* periodic schedule support */
+@@ -123,6 +127,9 @@ struct ehci_hcd {			/* one per controller */
+ 	unsigned		i_thresh;	/* uframes HC might cache */
+ 
+ 	union ehci_shadow	*pshadow;	/* mirror hw periodic table */
++	struct ehci_qh		*intr_unlink;
++	struct ehci_qh		*intr_unlink_last;
++	unsigned		intr_unlink_cycle;
+ 	int			next_uframe;	/* scan periodic, start here */
+ 	unsigned		periodic_count;	/* periodic activity count */
+ 	unsigned		uframe_periodic_max; /* max periodic time per uframe */
+@@ -385,6 +392,7 @@ struct ehci_qh {
+ 	struct ehci_qh		*unlink_next;	/* next on unlink list */
+ 
+ 	unsigned long		unlink_time;
++	unsigned		unlink_cycle;
+ 	unsigned		stamp;
+ 
+ 	u8			needs_rescan;	/* Dequeue during giveback */

commit 314466101c6ae14f6f5db8a86eda1509ba2c02a8
+Author: Alan Stern 
+Date:   Wed Jul 11 11:22:21 2012 -0400
+
+    USB: EHCI: use hrtimer for async schedule
+    
+    This patch (as1576) adds hrtimer support for managing ehci-hcd's
+    async schedule.  Just as with the earlier change to the periodic
+    schedule management, two new hrtimer events take care of everything.
+    
+    One event polls at 1-ms intervals to see when the Asynchronous
+    Schedule Status (ASS) flag matches the Asynchronous Schedule Enable
+    (ASE) value; the schedule's state must not be changed until it does.
+    The other event delays for 15 ms after the async schedule becomes
+    empty before turning it off.
+    
+    The new events replace a busy-wait poll and a kernel timer usage.
+    They also replace the rather illogical method currently used for
+    indicating the async schedule should be turned off: attempting to
+    unlink the dedicated QH at the head of the async list.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index fd7ae16f77be..21d6fbc0a327 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -95,7 +95,6 @@ static const char	hcd_name [] = "ehci_hcd";
+ 
+ #define EHCI_IAA_MSECS		10		/* arbitrary */
+ #define EHCI_IO_JIFFIES		(HZ/10)		/* io watchdog > irq_thresh */
+-#define EHCI_ASYNC_JIFFIES	(HZ/20)		/* async idle timeout */
+ #define EHCI_SHRINK_JIFFIES	(DIV_ROUND_UP(HZ, 200) + 1)
+ 						/* 5-ms async qh unlink delay */
+ 
+@@ -137,7 +136,7 @@ timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action)
+ 	 * SHRINK were pending, OFF would never be requested.
+ 	 */
+ 	if (timer_pending(&ehci->watchdog)
+-			&& ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF))
++			&& (BIT(TIMER_ASYNC_SHRINK)
+ 				& ehci->actions))
+ 		return;
+ 
+@@ -150,9 +149,6 @@ timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action)
+ 				return;
+ 			t = EHCI_IO_JIFFIES;
+ 			break;
+-		case TIMER_ASYNC_OFF:
+-			t = EHCI_ASYNC_JIFFIES;
+-			break;
+ 		/* case TIMER_ASYNC_SHRINK: */
+ 		default:
+ 			t = EHCI_SHRINK_JIFFIES;
+@@ -376,10 +372,6 @@ static void ehci_watchdog(unsigned long param)
+ 
+ 	spin_lock_irqsave(&ehci->lock, flags);
+ 
+-	/* stop async processing after it's idled a bit */
+-	if (test_bit (TIMER_ASYNC_OFF, &ehci->actions))
+-		start_unlink_async (ehci, ehci->async);
+-
+ 	/* ehci could run by timer, without IRQs ... */
+ 	ehci_work (ehci);
+ 
+@@ -470,7 +462,8 @@ static void ehci_work (struct ehci_hcd *ehci)
+ 	if (ehci->scanning)
+ 		return;
+ 	ehci->scanning = 1;
+-	scan_async (ehci);
++	if (ehci->async_count)
++		scan_async(ehci);
+ 	if (ehci->next_uframe != -1)
+ 		scan_periodic (ehci);
+ 	ehci->scanning = 0;
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 285d5a0f3f70..d68764ef4476 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -964,6 +964,30 @@ qh_make (
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++static void enable_async(struct ehci_hcd *ehci)
++{
++	if (ehci->async_count++)
++		return;
++
++	/* Stop waiting to turn off the async schedule */
++	ehci->enabled_hrtimer_events &= ~BIT(EHCI_HRTIMER_DISABLE_ASYNC);
++
++	/* Don't start the schedule until ASS is 0 */
++	ehci_poll_ASS(ehci);
++}
++
++static void disable_async(struct ehci_hcd *ehci)
++{
++	if (--ehci->async_count)
++		return;
++
++	/* The async schedule and async_unlink list are supposed to be empty */
++	WARN_ON(ehci->async->qh_next.qh || ehci->async_unlink);
++
++	/* Don't turn off the schedule until ASS is 1 */
++	ehci_poll_ASS(ehci);
++}
++
+ /* move qh (and its qtds) onto async queue; maybe enable queue.  */
+ 
+ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+@@ -977,24 +1001,11 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 
+ 	WARN_ON(qh->qh_state != QH_STATE_IDLE);
+ 
+-	/* (re)start the async schedule? */
+-	head = ehci->async;
+-	timer_action_done (ehci, TIMER_ASYNC_OFF);
+-	if (!head->qh_next.qh) {
+-		if (!(ehci->command & CMD_ASE)) {
+-			/* in case a clear of CMD_ASE didn't take yet */
+-			(void)handshake(ehci, &ehci->regs->status,
+-					STS_ASS, 0, 150);
+-			ehci->command |= CMD_ASE;
+-			ehci_writel(ehci, ehci->command, &ehci->regs->command);
+-			/* posted write need not be known to HC yet ... */
+-		}
+-	}
+-
+ 	/* clear halt and/or toggle; and maybe recover from silicon quirk */
+ 	qh_refresh(ehci, qh);
+ 
+ 	/* splice right after start */
++	head = ehci->async;
+ 	qh->qh_next = head->qh_next;
+ 	qh->hw->hw_next = head->hw->hw_next;
+ 	wmb ();
+@@ -1005,6 +1016,8 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	qh->xacterrs = 0;
+ 	qh->qh_state = QH_STATE_LINKED;
+ 	/* qtd completions reported later by interrupt */
++
++	enable_async(ehci);
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -1173,16 +1186,10 @@ static void end_unlink_async (struct ehci_hcd *ehci)
+ 
+ 	qh_completions (ehci, qh);
+ 
+-	if (!list_empty(&qh->qtd_list) && ehci->rh_state == EHCI_RH_RUNNING) {
++	if (!list_empty(&qh->qtd_list) && ehci->rh_state == EHCI_RH_RUNNING)
+ 		qh_link_async (ehci, qh);
+-	} else {
+-		/* it's not free to turn the async schedule on/off; leave it
+-		 * active but idle for a while once it empties.
+-		 */
+-		if (ehci->rh_state == EHCI_RH_RUNNING
+-				&& ehci->async->qh_next.qh == NULL)
+-			timer_action (ehci, TIMER_ASYNC_OFF);
+-	}
++
++	disable_async(ehci);
+ 
+ 	if (next) {
+ 		ehci->async_unlink = NULL;
+@@ -1210,21 +1217,6 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		BUG ();
+ #endif
+ 
+-	/* stop async schedule right now? */
+-	if (unlikely (qh == ehci->async)) {
+-		/* can't get here without STS_ASS set */
+-		if (ehci->rh_state != EHCI_RH_HALTED
+-				&& !ehci->async_unlink) {
+-			/* ... and CMD_IAAD clear */
+-			ehci->command &= ~CMD_ASE;
+-			ehci_writel(ehci, ehci->command, &ehci->regs->command);
+-			wmb ();
+-			// handshake later, if we need to
+-			timer_action_done (ehci, TIMER_ASYNC_OFF);
+-		}
+-		return;
+-	}
+-
+ 	qh->qh_state = QH_STATE_UNLINK;
+ 	ehci->async_unlink = qh;
+ 	if (!qh->unlink_next)
+diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
+index ecd3296157c6..1e907dd3bb1b 100644
+--- a/drivers/usb/host/ehci-timer.c
++++ b/drivers/usb/host/ehci-timer.c
+@@ -67,8 +67,10 @@ static void ehci_clear_command_bit(struct ehci_hcd *ehci, u32 bit)
+  * the event types indexed by enum ehci_hrtimer_event in ehci.h.
+  */
+ static unsigned event_delays_ns[] = {
++	1 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_POLL_ASS */
+ 	1 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_POLL_PSS */
+ 	10 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_DISABLE_PERIODIC */
++	15 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_DISABLE_ASYNC */
+ };
+ 
+ /* Enable a pending hrtimer event */
+@@ -91,6 +93,51 @@ static void ehci_enable_event(struct ehci_hcd *ehci, unsigned event,
+ }
+ 
+ 
++/* Poll the STS_ASS status bit; see when it agrees with CMD_ASE */
++static void ehci_poll_ASS(struct ehci_hcd *ehci)
++{
++	unsigned	actual, want;
++
++	/* Don't enable anything if the controller isn't running (e.g., died) */
++	if (ehci->rh_state != EHCI_RH_RUNNING)
++		return;
++
++	want = (ehci->command & CMD_ASE) ? STS_ASS : 0;
++	actual = ehci_readl(ehci, &ehci->regs->status) & STS_ASS;
++
++	if (want != actual) {
++
++		/* Poll again later, but give up after about 20 ms */
++		if (ehci->ASS_poll_count++ < 20) {
++			ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true);
++			return;
++		}
++		ehci_warn(ehci, "Waited too long for the async schedule status, giving up\n");
++	}
++	ehci->ASS_poll_count = 0;
++
++	/* The status is up-to-date; restart or stop the schedule as needed */
++	if (want == 0) {	/* Stopped */
++		if (ehci->async_count > 0)
++			ehci_set_command_bit(ehci, CMD_ASE);
++
++	} else {		/* Running */
++		if (ehci->async_count == 0) {
++
++			/* Turn off the schedule after a while */
++			ehci_enable_event(ehci, EHCI_HRTIMER_DISABLE_ASYNC,
++					true);
++		}
++	}
++}
++
++/* Turn off the async schedule after a brief delay */
++static void ehci_disable_ASE(struct ehci_hcd *ehci)
++{
++	ehci_clear_command_bit(ehci, CMD_ASE);
++}
++
++
+ /* Poll the STS_PSS status bit; see when it agrees with CMD_PSE */
+ static void ehci_poll_PSS(struct ehci_hcd *ehci)
+ {
+@@ -151,8 +198,10 @@ static void ehci_disable_PSE(struct ehci_hcd *ehci)
+  * enum ehci_hrtimer_event in ehci.h.
+  */
+ static void (*event_handlers[])(struct ehci_hcd *) = {
++	ehci_poll_ASS,			/* EHCI_HRTIMER_POLL_ASS */
+ 	ehci_poll_PSS,			/* EHCI_HRTIMER_POLL_PSS */
+ 	ehci_disable_PSE,		/* EHCI_HRTIMER_DISABLE_PERIODIC */
++	ehci_disable_ASE,		/* EHCI_HRTIMER_DISABLE_ASYNC */
+ };
+ 
+ static enum hrtimer_restart ehci_hrtimer_func(struct hrtimer *t)
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index da2e0ab23850..bf06bbb77ba4 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -79,8 +79,10 @@ enum ehci_rh_state {
+  * ehci-timer.c) in parallel with this list.
+  */
+ enum ehci_hrtimer_event {
++	EHCI_HRTIMER_POLL_ASS,		/* Poll for async schedule off */
+ 	EHCI_HRTIMER_POLL_PSS,		/* Poll for periodic schedule off */
+ 	EHCI_HRTIMER_DISABLE_PERIODIC,	/* Wait to disable periodic sched */
++	EHCI_HRTIMER_DISABLE_ASYNC,	/* Wait to disable async sched */
+ 	EHCI_HRTIMER_NUM_EVENTS		/* Must come last */
+ };
+ #define EHCI_HRTIMER_NO_EVENT	99
+@@ -93,6 +95,7 @@ struct ehci_hcd {			/* one per controller */
+ 	struct hrtimer		hrtimer;
+ 
+ 	int			PSS_poll_count;
++	int			ASS_poll_count;
+ 
+ 	/* glue to PCI and HCD framework */
+ 	struct ehci_caps __iomem *caps;
+@@ -110,6 +113,7 @@ struct ehci_hcd {			/* one per controller */
+ 	struct ehci_qh		*async_unlink_last;
+ 	struct ehci_qh		*qh_scan_next;
+ 	unsigned		scanning : 1;
++	unsigned		async_count;	/* async activity count */
+ 
+ 	/* periodic schedule support */
+ #define	DEFAULT_I_TDPS		1024		/* some HCs can do less */
+@@ -229,7 +233,6 @@ static inline void iaa_watchdog_done(struct ehci_hcd *ehci)
+ enum ehci_timer_action {
+ 	TIMER_IO_WATCHDOG,
+ 	TIMER_ASYNC_SHRINK,
+-	TIMER_ASYNC_OFF,
+ };
+ 
+ static inline void

commit 9671cd7a91059bcd27665a884ee6568d31ef6857
+Author: Alan Stern 
+Date:   Wed Jul 11 11:22:16 2012 -0400
+
+    USB: EHCI: remove PS3 status polling
+    
+    This patch (as1575) removes special code added for status polling of
+    the EHCI controller in PS3 systems.  While the controller is running,
+    the polling is now carried out by an hrtimer handler.  When the
+    controller is suspending or stopping, we use the same polling routine
+    as the old code -- but in neither case do we need to conclude that the
+    controller has died if the polling goes on for too long.
+    
+    As a result the entire handshake_on_error_set_halt() routine is now
+    unused, so it is removed from the driver.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 7e00ca095cea..fd7ae16f77be 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -235,68 +235,6 @@ static int ehci_halt (struct ehci_hcd *ehci)
+ 			  STS_HALT, STS_HALT, 16 * 125);
+ }
+ 
+-#if defined(CONFIG_USB_SUSPEND) && defined(CONFIG_PPC_PS3)
+-
+-/*
+- * The EHCI controller of the Cell Super Companion Chip used in the
+- * PS3 will stop the root hub after all root hub ports are suspended.
+- * When in this condition handshake will return -ETIMEDOUT.  The
+- * STS_HLT bit will not be set, so inspection of the frame index is
+- * used here to test for the condition.  If the condition is found
+- * return success to allow the USB suspend to complete.
+- */
+-
+-static int handshake_for_broken_root_hub(struct ehci_hcd *ehci,
+-					 void __iomem *ptr, u32 mask, u32 done,
+-					 int usec)
+-{
+-	unsigned int old_index;
+-	int error;
+-
+-	if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
+-		return -ETIMEDOUT;
+-
+-	old_index = ehci_read_frame_index(ehci);
+-
+-	error = handshake(ehci, ptr, mask, done, usec);
+-
+-	if (error == -ETIMEDOUT && ehci_read_frame_index(ehci) == old_index)
+-		return 0;
+-
+-	return error;
+-}
+-
+-#else
+-
+-static int handshake_for_broken_root_hub(struct ehci_hcd *ehci,
+-					 void __iomem *ptr, u32 mask, u32 done,
+-					 int usec)
+-{
+-	return -ETIMEDOUT;
+-}
+-
+-#endif
+-
+-static int handshake_on_error_set_halt(struct ehci_hcd *ehci, void __iomem *ptr,
+-				       u32 mask, u32 done, int usec)
+-{
+-	int error;
+-
+-	error = handshake(ehci, ptr, mask, done, usec);
+-	if (error == -ETIMEDOUT)
+-		error = handshake_for_broken_root_hub(ehci, ptr, mask, done,
+-						      usec);
+-
+-	if (error) {
+-		ehci_halt(ehci);
+-		ehci->rh_state = EHCI_RH_HALTED;
+-		ehci_err(ehci, "force halt; handshake %p %08x %08x -> %d\n",
+-			ptr, mask, done, error);
+-	}
+-
+-	return error;
+-}
+-
+ /* put TDI/ARC silicon into EHCI mode */
+ static void tdi_reset (struct ehci_hcd *ehci)
+ {
+@@ -361,17 +299,14 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
+ 
+ 	/* wait for any schedule enables/disables to take effect */
+ 	temp = (ehci->command << 10) & (STS_ASS | STS_PSS);
+-	if (handshake_on_error_set_halt(ehci, &ehci->regs->status,
+-					STS_ASS | STS_PSS, temp, 16 * 125))
+-		return;
++	handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, temp, 16 * 125);
+ 
+ 	/* then disable anything that's still active */
+ 	ehci->command &= ~(CMD_ASE | CMD_PSE);
+ 	ehci_writel(ehci, ehci->command, &ehci->regs->command);
+ 
+ 	/* hardware can take 16 microframes to turn off ... */
+-	handshake_on_error_set_halt(ehci, &ehci->regs->status,
+-				    STS_ASS | STS_PSS, 0, 16 * 125);
++	handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, 0, 16 * 125);
+ }
+ 
+ /*-------------------------------------------------------------------------*/

commit b015cb79ce84944076a8a849055f898f2a4d6be8
+Author: Alan Stern 
+Date:   Wed Jul 11 11:22:10 2012 -0400
+
+    USB: EHCI: return void instead of 0
+    
+    This patch (as1574) changes the return type of multiple functions in
+    ehci-sched.c from int to void.  The values they return are now always
+    0, so there's no reason for them to return any value at all.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index f5c15880c65a..69b1861e4325 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -479,29 +479,27 @@ static int tt_no_collision (
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-static int enable_periodic (struct ehci_hcd *ehci)
++static void enable_periodic(struct ehci_hcd *ehci)
+ {
+ 	if (ehci->periodic_count++)
+-		return 0;
++		return;
+ 
+ 	/* Stop waiting to turn off the periodic schedule */
+ 	ehci->enabled_hrtimer_events &= ~BIT(EHCI_HRTIMER_DISABLE_PERIODIC);
+ 
+ 	/* Don't start the schedule until PSS is 0 */
+ 	ehci_poll_PSS(ehci);
+-	return 0;
+ }
+ 
+-static int disable_periodic (struct ehci_hcd *ehci)
++static void disable_periodic(struct ehci_hcd *ehci)
+ {
+ 	if (--ehci->periodic_count)
+-		return 0;
++		return;
+ 
+ 	ehci->next_uframe = -1;		/* the periodic schedule is empty */
+ 
+ 	/* Don't turn off the schedule until PSS is 1 */
+ 	ehci_poll_PSS(ehci);
+-	return 0;
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -512,7 +510,7 @@ static int disable_periodic (struct ehci_hcd *ehci)
+  * this just links in a qh; caller guarantees uframe masks are set right.
+  * no FSTN support (yet; ehci 0.96+)
+  */
+-static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
++static void qh_link_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ {
+ 	unsigned	i;
+ 	unsigned	period = qh->period;
+@@ -572,10 +570,10 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		: (qh->usecs * 8);
+ 
+ 	/* maybe enable periodic schedule processing */
+-	return enable_periodic(ehci);
++	enable_periodic(ehci);
+ }
+ 
+-static int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
++static void qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ {
+ 	unsigned	i;
+ 	unsigned	period;
+@@ -608,8 +606,6 @@ static int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	/* qh->qh_next still "live" to HC */
+ 	qh->qh_state = QH_STATE_UNLINK;
+ 	qh->qh_next.ptr = NULL;
+-
+-	return 0;
+ }
+ 
+ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
+@@ -843,7 +839,7 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		ehci_dbg (ehci, "reused qh %p schedule\n", qh);
+ 
+ 	/* stuff into the periodic schedule */
+-	status = qh_link_periodic (ehci, qh);
++	qh_link_periodic(ehci, qh);
+ done:
+ 	return status;
+ }
+@@ -1574,8 +1570,7 @@ itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd)
+ }
+ 
+ /* fit urb's itds into the selected schedule slot; activate as needed */
+-static int
+-itd_link_urb (
++static void itd_link_urb(
+ 	struct ehci_hcd		*ehci,
+ 	struct urb		*urb,
+ 	unsigned		mod,
+@@ -1646,7 +1641,7 @@ itd_link_urb (
+ 	urb->hcpriv = NULL;
+ 
+ 	timer_action (ehci, TIMER_IO_WATCHDOG);
+-	return enable_periodic(ehci);
++	enable_periodic(ehci);
+ }
+ 
+ #define	ISO_ERRS (EHCI_ISOC_BUF_ERR | EHCI_ISOC_BABBLE | EHCI_ISOC_XACTERR)
+@@ -1726,7 +1721,7 @@ itd_complete (
+ 	ehci_urb_done(ehci, urb, 0);
+ 	retval = true;
+ 	urb = NULL;
+-	(void) disable_periodic(ehci);
++	disable_periodic(ehci);
+ 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
+ 
+ 	if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
+@@ -1993,8 +1988,7 @@ sitd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_sitd *sitd)
+ }
+ 
+ /* fit urb's sitds into the selected schedule slot; activate as needed */
+-static int
+-sitd_link_urb (
++static void sitd_link_urb(
+ 	struct ehci_hcd		*ehci,
+ 	struct urb		*urb,
+ 	unsigned		mod,
+@@ -2056,7 +2050,7 @@ sitd_link_urb (
+ 	urb->hcpriv = NULL;
+ 
+ 	timer_action (ehci, TIMER_IO_WATCHDOG);
+-	return enable_periodic(ehci);
++	enable_periodic(ehci);
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -2122,7 +2116,7 @@ sitd_complete (
+ 	ehci_urb_done(ehci, urb, 0);
+ 	retval = true;
+ 	urb = NULL;
+-	(void) disable_periodic(ehci);
++	disable_periodic(ehci);
+ 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
+ 
+ 	if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {

commit 3ca9aebac2ebb8f56d2d097636b8c568320a9f87
+Author: Alan Stern 
+Date:   Wed Jul 11 11:22:05 2012 -0400
+
+    USB: EHCI: use hrtimer for the periodic schedule
+    
+    This patch (as1573) adds hrtimer support for managing ehci-hcd's
+    periodic schedule.  There are two issues to deal with.
+    
+    First, the schedule's state (on or off) must not be changed until the
+    hardware status has caught up with the current command.  This is
+    handled by an hrtimer event that polls at 1-ms intervals to see when
+    the Periodic Schedule Status (PSS) flag matches the Periodic Schedule
+    Enable (PSE) value.
+    
+    Second, the schedule should not be turned off as soon as it becomes
+    empty.  Turning the schedule on and off takes time, so we want to wait
+    until the schedule has been empty for a suitable period before turning
+    it off.  This is handled by an hrtimer event that gets set to expire
+    10 ms after the periodic schedule becomes empty.
+    
+    The existing code polls (for up to 1125 us and with interrupts
+    disabled!) to check the status, and doesn't implement a delay before
+    turning off the schedule.  Furthermore, if the polling fails then the
+    driver decides that the controller has died.  This has caused problems
+    for several people; some controllers can take 10 ms or more to turn
+    off their periodic schedules.
+    
+    This patch fixes these issues.  It also makes the "broken_periodic"
+    workaround unnecessary; there is no longer any danger of turning off
+    the periodic schedule after it has been on for less than 1 ms.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index f8fed163a23a..7e00ca095cea 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -546,7 +546,7 @@ static void ehci_work (struct ehci_hcd *ehci)
+ 	 */
+ 	if (ehci->rh_state == EHCI_RH_RUNNING &&
+ 			(ehci->async->qh_next.ptr != NULL ||
+-			 ehci->periodic_sched != 0))
++			 ehci->periodic_count != 0))
+ 		timer_action (ehci, TIMER_IO_WATCHDOG);
+ }
+ 
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index 21e5f963f331..2cb7d370c4ef 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -104,10 +104,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 		break;
+ 	case PCI_VENDOR_ID_INTEL:
+ 		ehci->fs_i_thresh = 1;
+-		if (pdev->device == 0x27cc) {
+-			ehci->broken_periodic = 1;
+-			ehci_info(ehci, "using broken periodic workaround\n");
+-		}
+ 		if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB)
+ 			hcd->has_tt = 1;
+ 		break;
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 3429b8a33c58..f5c15880c65a 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -481,67 +481,26 @@ static int tt_no_collision (
+ 
+ static int enable_periodic (struct ehci_hcd *ehci)
+ {
+-	int	status;
+-
+-	if (ehci->periodic_sched++)
++	if (ehci->periodic_count++)
+ 		return 0;
+ 
+-	/* did clearing PSE did take effect yet?
+-	 * takes effect only at frame boundaries...
+-	 */
+-	status = handshake_on_error_set_halt(ehci, &ehci->regs->status,
+-					     STS_PSS, 0, 9 * 125);
+-	if (status) {
+-		usb_hc_died(ehci_to_hcd(ehci));
+-		return status;
+-	}
+-
+-	ehci->command |= CMD_PSE;
+-	ehci_writel(ehci, ehci->command, &ehci->regs->command);
+-	/* posted write ... PSS happens later */
++	/* Stop waiting to turn off the periodic schedule */
++	ehci->enabled_hrtimer_events &= ~BIT(EHCI_HRTIMER_DISABLE_PERIODIC);
+ 
+-	/* make sure ehci_work scans these */
+-	ehci->next_uframe = ehci_read_frame_index(ehci)
+-		% (ehci->periodic_size << 3);
+-	if (unlikely(ehci->broken_periodic))
+-		ehci->last_periodic_enable = ktime_get_real();
++	/* Don't start the schedule until PSS is 0 */
++	ehci_poll_PSS(ehci);
+ 	return 0;
+ }
+ 
+ static int disable_periodic (struct ehci_hcd *ehci)
+ {
+-	int	status;
+-
+-	if (--ehci->periodic_sched)
++	if (--ehci->periodic_count)
+ 		return 0;
+ 
+-	if (unlikely(ehci->broken_periodic)) {
+-		/* delay experimentally determined */
+-		ktime_t safe = ktime_add_us(ehci->last_periodic_enable, 1000);
+-		ktime_t now = ktime_get_real();
+-		s64 delay = ktime_us_delta(safe, now);
+-
+-		if (unlikely(delay > 0))
+-			udelay(delay);
+-	}
+-
+-	/* did setting PSE not take effect yet?
+-	 * takes effect only at frame boundaries...
+-	 */
+-	status = handshake_on_error_set_halt(ehci, &ehci->regs->status,
+-					     STS_PSS, STS_PSS, 9 * 125);
+-	if (status) {
+-		usb_hc_died(ehci_to_hcd(ehci));
+-		return status;
+-	}
+-
+-	ehci->command &= ~CMD_PSE;
+-	ehci_writel(ehci, ehci->command, &ehci->regs->command);
+-	/* posted write ... */
+-
+-	free_cached_lists(ehci);
++	ehci->next_uframe = -1;		/* the periodic schedule is empty */
+ 
+-	ehci->next_uframe = -1;
++	/* Don't turn off the schedule until PSS is 1 */
++	ehci_poll_PSS(ehci);
+ 	return 0;
+ }
+ 
+@@ -650,8 +609,7 @@ static int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	qh->qh_state = QH_STATE_UNLINK;
+ 	qh->qh_next.ptr = NULL;
+ 
+-	/* maybe turn off periodic schedule */
+-	return disable_periodic(ehci);
++	return 0;
+ }
+ 
+ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
+@@ -706,6 +664,9 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 			ehci_err(ehci, "can't reschedule qh %p, err %d\n",
+ 					qh, rc);
+ 	}
++
++	/* maybe turn off periodic schedule */
++	disable_periodic(ehci);
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -2447,7 +2408,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 
+ 			/* assume completion callbacks modify the queue */
+ 			if (unlikely (modified)) {
+-				if (likely(ehci->periodic_sched > 0))
++				if (likely(ehci->periodic_count > 0))
+ 					goto restart;
+ 				/* short-circuit this scan */
+ 				now_uframe = clock;
+@@ -2476,7 +2437,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 			unsigned	now;
+ 
+ 			if (ehci->rh_state < EHCI_RH_RUNNING
+-					|| ehci->periodic_sched == 0)
++					|| ehci->periodic_count == 0)
+ 				break;
+ 			ehci->next_uframe = now_uframe;
+ 			now = ehci_read_frame_index(ehci) & (mod - 1);
+diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
+index f6279e2883a8..ecd3296157c6 100644
+--- a/drivers/usb/host/ehci-timer.c
++++ b/drivers/usb/host/ehci-timer.c
+@@ -16,6 +16,28 @@
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++/* Set a bit in the USBCMD register */
++static void ehci_set_command_bit(struct ehci_hcd *ehci, u32 bit)
++{
++	ehci->command |= bit;
++	ehci_writel(ehci, ehci->command, &ehci->regs->command);
++
++	/* unblock posted write */
++	ehci_readl(ehci, &ehci->regs->command);
++}
++
++/* Clear a bit in the USBCMD register */
++static void ehci_clear_command_bit(struct ehci_hcd *ehci, u32 bit)
++{
++	ehci->command &= ~bit;
++	ehci_writel(ehci, ehci->command, &ehci->regs->command);
++
++	/* unblock posted write */
++	ehci_readl(ehci, &ehci->regs->command);
++}
++
++/*-------------------------------------------------------------------------*/
++
+ /*
+  * EHCI timer support...  Now using hrtimers.
+  *
+@@ -45,6 +67,8 @@
+  * the event types indexed by enum ehci_hrtimer_event in ehci.h.
+  */
+ static unsigned event_delays_ns[] = {
++	1 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_POLL_PSS */
++	10 * NSEC_PER_MSEC,	/* EHCI_HRTIMER_DISABLE_PERIODIC */
+ };
+ 
+ /* Enable a pending hrtimer event */
+@@ -67,12 +91,68 @@ static void ehci_enable_event(struct ehci_hcd *ehci, unsigned event,
+ }
+ 
+ 
++/* Poll the STS_PSS status bit; see when it agrees with CMD_PSE */
++static void ehci_poll_PSS(struct ehci_hcd *ehci)
++{
++	unsigned	actual, want;
++
++	/* Don't do anything if the controller isn't running (e.g., died) */
++	if (ehci->rh_state != EHCI_RH_RUNNING)
++		return;
++
++	want = (ehci->command & CMD_PSE) ? STS_PSS : 0;
++	actual = ehci_readl(ehci, &ehci->regs->status) & STS_PSS;
++
++	if (want != actual) {
++
++		/* Poll again later, but give up after about 20 ms */
++		if (ehci->PSS_poll_count++ < 20) {
++			ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);
++			return;
++		}
++		ehci_warn(ehci, "Waited too long for the periodic schedule status, giving up\n");
++	}
++	ehci->PSS_poll_count = 0;
++
++	/* The status is up-to-date; restart or stop the schedule as needed */
++	if (want == 0) {	/* Stopped */
++		free_cached_lists(ehci);
++		if (ehci->periodic_count > 0) {
++
++			/* make sure ehci_work scans these */
++			ehci->next_uframe = ehci_read_frame_index(ehci)
++					& ((ehci->periodic_size << 3) - 1);
++			ehci_set_command_bit(ehci, CMD_PSE);
++		}
++
++	} else {		/* Running */
++		if (ehci->periodic_count == 0) {
++
++			/* Turn off the schedule after a while */
++			ehci_enable_event(ehci, EHCI_HRTIMER_DISABLE_PERIODIC,
++					true);
++		}
++	}
++}
++
++/* Turn off the periodic schedule after a brief delay */
++static void ehci_disable_PSE(struct ehci_hcd *ehci)
++{
++	ehci_clear_command_bit(ehci, CMD_PSE);
++
++	/* Poll to see when it actually stops */
++	ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);
++}
++
++
+ /*
+  * Handler functions for the hrtimer event types.
+  * Keep this array in the same order as the event types indexed by
+  * enum ehci_hrtimer_event in ehci.h.
+  */
+ static void (*event_handlers[])(struct ehci_hcd *) = {
++	ehci_poll_PSS,			/* EHCI_HRTIMER_POLL_PSS */
++	ehci_disable_PSE,		/* EHCI_HRTIMER_DISABLE_PERIODIC */
+ };
+ 
+ static enum hrtimer_restart ehci_hrtimer_func(struct hrtimer *t)
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 070be83028d5..da2e0ab23850 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -79,6 +79,8 @@ enum ehci_rh_state {
+  * ehci-timer.c) in parallel with this list.
+  */
+ enum ehci_hrtimer_event {
++	EHCI_HRTIMER_POLL_PSS,		/* Poll for periodic schedule off */
++	EHCI_HRTIMER_DISABLE_PERIODIC,	/* Wait to disable periodic sched */
+ 	EHCI_HRTIMER_NUM_EVENTS		/* Must come last */
+ };
+ #define EHCI_HRTIMER_NO_EVENT	99
+@@ -90,6 +92,8 @@ struct ehci_hcd {			/* one per controller */
+ 	ktime_t			hr_timeouts[EHCI_HRTIMER_NUM_EVENTS];
+ 	struct hrtimer		hrtimer;
+ 
++	int			PSS_poll_count;
++
+ 	/* glue to PCI and HCD framework */
+ 	struct ehci_caps __iomem *caps;
+ 	struct ehci_regs __iomem *regs;
+@@ -116,7 +120,7 @@ struct ehci_hcd {			/* one per controller */
+ 
+ 	union ehci_shadow	*pshadow;	/* mirror hw periodic table */
+ 	int			next_uframe;	/* scan periodic, start here */
+-	unsigned		periodic_sched;	/* periodic activity count */
++	unsigned		periodic_count;	/* periodic activity count */
+ 	unsigned		uframe_periodic_max; /* max periodic time per uframe */
+ 
+ 
+@@ -165,7 +169,6 @@ struct ehci_hcd {			/* one per controller */
+ 	unsigned		big_endian_capbase:1;
+ 	unsigned		has_amcc_usb23:1;
+ 	unsigned		need_io_watchdog:1;
+-	unsigned		broken_periodic:1;
+ 	unsigned		amd_pll_fix:1;
+ 	unsigned		fs_i_thresh:1;	/* Intel iso scheduling */
+ 	unsigned		use_dummy_qh:1;	/* AMD Frame List table quirk*/

commit d58b4bcc6df8046cf9c3c59f9ff84d2cd86b93eb
+Author: Alan Stern 
+Date:   Wed Jul 11 11:21:54 2012 -0400
+
+    USB: EHCI: introduce high-res timer
+    
+    This patch (as1572) begins the conversion of ehci-hcd over to using
+    high-resolution timers rather than old-fashioned low-resolution kernel
+    timers.  This reduces overhead caused by timer roundoff on systems
+    where HZ is smaller than 1000.  Also, the new timer framework
+    introduced here is much more logical and easily extended than the
+    ad-hoc approach ehci-hcd currently uses for timers.
+    
+    An hrtimer structure is added to ehci_hcd, along with a bitflag array
+    and an array of ktime_t values, to keep track of which timing events
+    are pending and what their expiration times are.
+    
+    Only the infrastructure for the timing operations is added in this
+    patch.  Later patches will add routines for handling each of the
+    various timing events the driver needs.  In some cases the new hrtimer
+    handlers will replace the existing handlers for ehci-hcd's kernel
+    timers; as this happens the old timers will be removed.  In other
+    cases the new timing events will replace busy-wait loops.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index bc94822f4c5d..f8fed163a23a 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -30,8 +30,7 @@
+ #include 
+ #include 
+ #include 
+-#include 
+-#include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -380,6 +379,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
+ static void end_unlink_async(struct ehci_hcd *ehci);
+ static void ehci_work(struct ehci_hcd *ehci);
+ 
++#include "ehci-timer.c"
+ #include "ehci-hub.c"
+ #include "ehci-lpm.c"
+ #include "ehci-mem.c"
+@@ -494,7 +494,10 @@ static void ehci_shutdown(struct usb_hcd *hcd)
+ 	spin_lock_irq(&ehci->lock);
+ 	ehci->rh_state = EHCI_RH_STOPPING;
+ 	ehci_silence_controller(ehci);
++	ehci->enabled_hrtimer_events = 0;
+ 	spin_unlock_irq(&ehci->lock);
++
++	hrtimer_cancel(&ehci->hrtimer);
+ }
+ 
+ static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
+@@ -561,12 +564,14 @@ static void ehci_stop (struct usb_hcd *hcd)
+ 	del_timer_sync(&ehci->iaa_watchdog);
+ 
+ 	spin_lock_irq(&ehci->lock);
++	ehci->enabled_hrtimer_events = 0;
+ 	ehci_quiesce(ehci);
+ 
+ 	ehci_silence_controller(ehci);
+ 	ehci_reset (ehci);
+ 	spin_unlock_irq(&ehci->lock);
+ 
++	hrtimer_cancel(&ehci->hrtimer);
+ 	remove_sysfs_files(ehci);
+ 	remove_debug_files (ehci);
+ 
+@@ -615,6 +620,10 @@ static int ehci_init(struct usb_hcd *hcd)
+ 	ehci->iaa_watchdog.function = ehci_iaa_watchdog;
+ 	ehci->iaa_watchdog.data = (unsigned long) ehci;
+ 
++	hrtimer_init(&ehci->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
++	ehci->hrtimer.function = ehci_hrtimer_func;
++	ehci->next_hrtimer_event = EHCI_HRTIMER_NO_EVENT;
++
+ 	hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params);
+ 
+ 	/*
+@@ -954,6 +963,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 		dbg_status(ehci, "fatal", status);
+ 		ehci_halt(ehci);
+ dead:
++		ehci->enabled_hrtimer_events = 0;
++		hrtimer_try_to_cancel(&ehci->hrtimer);
+ 		ehci_reset(ehci);
+ 		ehci_writel(ehci, 0, &ehci->regs->configured_flag);
+ 		usb_hc_died(hcd);
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index fb1b99e74937..25329e4b844f 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -311,12 +311,15 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 	ehci_readl(ehci, &ehci->regs->intr_enable);
+ 
+ 	ehci->next_statechange = jiffies + msecs_to_jiffies(10);
++	ehci->enabled_hrtimer_events = 0;
++	ehci->next_hrtimer_event = EHCI_HRTIMER_NO_EVENT;
+ 	spin_unlock_irq (&ehci->lock);
+ 
+ 	/* ehci_work() may have re-enabled the watchdog timer, which we do not
+ 	 * want, and so we must delete any pending watchdog timer events.
+ 	 */
+ 	del_timer_sync(&ehci->watchdog);
++	hrtimer_cancel(&ehci->hrtimer);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
+new file mode 100644
+index 000000000000..f6279e2883a8
+--- /dev/null
++++ b/drivers/usb/host/ehci-timer.c
+@@ -0,0 +1,106 @@
++/*
++ * Copyright (C) 2012 by Alan Stern
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ */
++
++/* This file is part of ehci-hcd.c */
++
++/*-------------------------------------------------------------------------*/
++
++/*
++ * EHCI timer support...  Now using hrtimers.
++ *
++ * Lots of different events are triggered from ehci->hrtimer.  Whenever
++ * the timer routine runs, it checks each possible event; events that are
++ * currently enabled and whose expiration time has passed get handled.
++ * The set of enabled events is stored as a collection of bitflags in
++ * ehci->enabled_hrtimer_events, and they are numbered in order of
++ * increasing delay values (ranging between 1 ms and 100 ms).
++ *
++ * Rather than implementing a sorted list or tree of all pending events,
++ * we keep track only of the lowest-numbered pending event, in
++ * ehci->next_hrtimer_event.  Whenever ehci->hrtimer gets restarted, its
++ * expiration time is set to the timeout value for this event.
++ *
++ * As a result, events might not get handled right away; the actual delay
++ * could be anywhere up to twice the requested delay.  This doesn't
++ * matter, because none of the events are especially time-critical.  The
++ * ones that matter most all have a delay of 1 ms, so they will be
++ * handled after 2 ms at most, which is okay.  In addition to this, we
++ * allow for an expiration range of 1 ms.
++ */
++
++/*
++ * Delay lengths for the hrtimer event types.
++ * Keep this list sorted by delay length, in the same order as
++ * the event types indexed by enum ehci_hrtimer_event in ehci.h.
++ */
++static unsigned event_delays_ns[] = {
++};
++
++/* Enable a pending hrtimer event */
++static void ehci_enable_event(struct ehci_hcd *ehci, unsigned event,
++		bool resched)
++{
++	ktime_t		*timeout = &ehci->hr_timeouts[event];
++
++	if (resched)
++		*timeout = ktime_add(ktime_get(),
++				ktime_set(0, event_delays_ns[event]));
++	ehci->enabled_hrtimer_events |= (1 << event);
++
++	/* Track only the lowest-numbered pending event */
++	if (event < ehci->next_hrtimer_event) {
++		ehci->next_hrtimer_event = event;
++		hrtimer_start_range_ns(&ehci->hrtimer, *timeout,
++				NSEC_PER_MSEC, HRTIMER_MODE_ABS);
++	}
++}
++
++
++/*
++ * Handler functions for the hrtimer event types.
++ * Keep this array in the same order as the event types indexed by
++ * enum ehci_hrtimer_event in ehci.h.
++ */
++static void (*event_handlers[])(struct ehci_hcd *) = {
++};
++
++static enum hrtimer_restart ehci_hrtimer_func(struct hrtimer *t)
++{
++	struct ehci_hcd	*ehci = container_of(t, struct ehci_hcd, hrtimer);
++	ktime_t		now;
++	unsigned long	events;
++	unsigned long	flags;
++	unsigned	e;
++
++	spin_lock_irqsave(&ehci->lock, flags);
++
++	events = ehci->enabled_hrtimer_events;
++	ehci->enabled_hrtimer_events = 0;
++	ehci->next_hrtimer_event = EHCI_HRTIMER_NO_EVENT;
++
++	/*
++	 * Check each pending event.  If its time has expired, handle
++	 * the event; otherwise re-enable it.
++	 */
++	now = ktime_get();
++	for_each_set_bit(e, &events, EHCI_HRTIMER_NUM_EVENTS) {
++		if (now.tv64 >= ehci->hr_timeouts[e].tv64)
++			event_handlers[e](ehci);
++		else
++			ehci_enable_event(ehci, e, false);
++	}
++
++	spin_unlock_irqrestore(&ehci->lock, flags);
++	return HRTIMER_NORESTART;
++}
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 9e8e82ecce58..070be83028d5 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -73,7 +73,23 @@ enum ehci_rh_state {
+ 	EHCI_RH_STOPPING
+ };
+ 
++/*
++ * Timer events, ordered by increasing delay length.
++ * Always update event_delays_ns[] and event_handlers[] (defined in
++ * ehci-timer.c) in parallel with this list.
++ */
++enum ehci_hrtimer_event {
++	EHCI_HRTIMER_NUM_EVENTS		/* Must come last */
++};
++#define EHCI_HRTIMER_NO_EVENT	99
++
+ struct ehci_hcd {			/* one per controller */
++	/* timing support */
++	enum ehci_hrtimer_event	next_hrtimer_event;
++	unsigned		enabled_hrtimer_events;
++	ktime_t			hr_timeouts[EHCI_HRTIMER_NUM_EVENTS];
++	struct hrtimer		hrtimer;
++
+ 	/* glue to PCI and HCD framework */
+ 	struct ehci_caps __iomem *caps;
+ 	struct ehci_regs __iomem *regs;

commit c0c53dbc32ea05a1e1dd9dba4772327da9a11750
+Author: Alan Stern 
+Date:   Wed Jul 11 11:21:48 2012 -0400
+
+    USB: EHCI: add new root-hub state: STOPPING
+    
+    This patch (as1571) adds a new state for ehci-hcd's root hubs:
+    EHCI_RH_STOPPING.  This value is used at times when the root hub is
+    being stopped and we don't know whether or not the hardware has
+    finished all its DMA yet.
+    
+    Although the purpose may not be apparent, this distinction will come
+    in useful later on.  Future patches will avoid actions that depend on
+    the root hub being operational (like turning on the async or periodic
+    schedules) when they see the state is EHCI_RH_STOPPING.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
+index 76120957d60a..f0c00de035ef 100644
+--- a/drivers/usb/host/ehci-dbg.c
++++ b/drivers/usb/host/ehci-dbg.c
+@@ -706,6 +706,8 @@ static const char *rh_state_string(struct ehci_hcd *ehci)
+ 		return "suspended";
+ 	case EHCI_RH_RUNNING:
+ 		return "running";
++	case EHCI_RH_STOPPING:
++		return "stopping";
+ 	}
+ 	return "?";
+ }
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 8b75e4279a47..bc94822f4c5d 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -357,10 +357,8 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
+ {
+ 	u32	temp;
+ 
+-#ifdef DEBUG
+ 	if (ehci->rh_state != EHCI_RH_RUNNING)
+-		BUG ();
+-#endif
++		return;
+ 
+ 	/* wait for any schedule enables/disables to take effect */
+ 	temp = (ehci->command << 10) & (STS_ASS | STS_PSS);
+@@ -494,6 +492,7 @@ static void ehci_shutdown(struct usb_hcd *hcd)
+ 	del_timer_sync(&ehci->iaa_watchdog);
+ 
+ 	spin_lock_irq(&ehci->lock);
++	ehci->rh_state = EHCI_RH_STOPPING;
+ 	ehci_silence_controller(ehci);
+ 	spin_unlock_irq(&ehci->lock);
+ }
+@@ -562,8 +561,7 @@ static void ehci_stop (struct usb_hcd *hcd)
+ 	del_timer_sync(&ehci->iaa_watchdog);
+ 
+ 	spin_lock_irq(&ehci->lock);
+-	if (ehci->rh_state == EHCI_RH_RUNNING)
+-		ehci_quiesce (ehci);
++	ehci_quiesce(ehci);
+ 
+ 	ehci_silence_controller(ehci);
+ 	ehci_reset (ehci);
+@@ -951,6 +949,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 	/* PCI errors [4.15.2.4] */
+ 	if (unlikely ((status & STS_FATAL) != 0)) {
+ 		ehci_err(ehci, "fatal error\n");
++		ehci->rh_state = EHCI_RH_STOPPING;
+ 		dbg_cmd(ehci, "fatal", cmd);
+ 		dbg_status(ehci, "fatal", status);
+ 		ehci_halt(ehci);
+@@ -1026,7 +1025,7 @@ static int ehci_urb_enqueue (
+ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ {
+ 	/* failfast */
+-	if (ehci->rh_state != EHCI_RH_RUNNING && ehci->async_unlink)
++	if (ehci->rh_state < EHCI_RH_RUNNING && ehci->async_unlink)
+ 		end_unlink_async(ehci);
+ 
+ 	/* If the QH isn't linked then there's nothing we can do
+@@ -1148,7 +1147,7 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 		goto idle_timeout;
+ 	}
+ 
+-	if (ehci->rh_state != EHCI_RH_RUNNING)
++	if (ehci->rh_state < EHCI_RH_RUNNING)
+ 		qh->qh_state = QH_STATE_IDLE;
+ 	switch (qh->qh_state) {
+ 	case QH_STATE_LINKED:
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 77d3324b4b28..fb1b99e74937 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -227,8 +227,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 	}
+ 
+ 	/* stop schedules, clean any completed work */
+-	if (ehci->rh_state == EHCI_RH_RUNNING)
+-		ehci_quiesce (ehci);
++	ehci_quiesce(ehci);
+ 	ehci_work(ehci);
+ 
+ 	/* Unlike other USB host controller types, EHCI doesn't have
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 5193612c96ea..285d5a0f3f70 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -433,7 +433,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 
+ 		/* stop scanning when we reach qtds the hc is using */
+ 		} else if (likely (!stopped
+-				&& ehci->rh_state == EHCI_RH_RUNNING)) {
++				&& ehci->rh_state >= EHCI_RH_RUNNING)) {
+ 			break;
+ 
+ 		/* scan the whole queue for unlinks whenever it stops */
+@@ -441,7 +441,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 			stopped = 1;
+ 
+ 			/* cancel everything if we halt, suspend, etc */
+-			if (ehci->rh_state != EHCI_RH_RUNNING)
++			if (ehci->rh_state < EHCI_RH_RUNNING)
+ 				last_status = -ESHUTDOWN;
+ 
+ 			/* this qtd is active; skip it unless a previous qtd
+@@ -1241,7 +1241,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	wmb ();
+ 
+ 	/* If the controller isn't running, we don't have to wait for it */
+-	if (unlikely(ehci->rh_state != EHCI_RH_RUNNING)) {
++	if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) {
+ 		/* if (unlikely (qh->unlink_next != 0))
+ 		 *	this will recurse, probably not much
+ 		 */
+@@ -1263,7 +1263,7 @@ static void scan_async (struct ehci_hcd *ehci)
+ 	enum ehci_timer_action	action = TIMER_IO_WATCHDOG;
+ 
+ 	timer_action_done (ehci, TIMER_ASYNC_SHRINK);
+-	stopped = (ehci->rh_state != EHCI_RH_RUNNING);
++	stopped = (ehci->rh_state < EHCI_RH_RUNNING);
+ 
+ 	ehci->qh_scan_next = ehci->async->qh_next.qh;
+ 	while (ehci->qh_scan_next) {
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 027df3de2dc9..3429b8a33c58 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -2299,7 +2299,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 	 * Touches as few pages as possible:  cache-friendly.
+ 	 */
+ 	now_uframe = ehci->next_uframe;
+-	if (ehci->rh_state == EHCI_RH_RUNNING) {
++	if (ehci->rh_state >= EHCI_RH_RUNNING) {
+ 		clock = ehci_read_frame_index(ehci);
+ 		clock_frame = (clock >> 3) & (ehci->periodic_size - 1);
+ 	} else  {
+@@ -2334,7 +2334,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 			union ehci_shadow	temp;
+ 			int			live;
+ 
+-			live = (ehci->rh_state == EHCI_RH_RUNNING);
++			live = (ehci->rh_state >= EHCI_RH_RUNNING);
+ 			switch (hc32_to_cpu(ehci, type)) {
+ 			case Q_TYPE_QH:
+ 				/* handle any completions */
+@@ -2459,7 +2459,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 		 * We can't advance our scan without collecting the ISO
+ 		 * transfers that are still pending in this frame.
+ 		 */
+-		if (incomplete && ehci->rh_state == EHCI_RH_RUNNING) {
++		if (incomplete && ehci->rh_state >= EHCI_RH_RUNNING) {
+ 			ehci->next_uframe = now_uframe;
+ 			break;
+ 		}
+@@ -2475,7 +2475,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 		if (now_uframe == clock) {
+ 			unsigned	now;
+ 
+-			if (ehci->rh_state != EHCI_RH_RUNNING
++			if (ehci->rh_state < EHCI_RH_RUNNING
+ 					|| ehci->periodic_sched == 0)
+ 				break;
+ 			ehci->next_uframe = now_uframe;
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 475f23e10bbf..9e8e82ecce58 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -62,10 +62,15 @@ struct ehci_stats {
+ 
+ #define	EHCI_MAX_ROOT_PORTS	15		/* see HCS_N_PORTS */
+ 
++/*
++ * ehci_rh_state values of EHCI_RH_RUNNING or above mean that the
++ * controller may be doing DMA.  Lower values mean there's no DMA.
++ */
+ enum ehci_rh_state {
+ 	EHCI_RH_HALTED,
+ 	EHCI_RH_SUSPENDED,
+-	EHCI_RH_RUNNING
++	EHCI_RH_RUNNING,
++	EHCI_RH_STOPPING
+ };
+ 
+ struct ehci_hcd {			/* one per controller */

commit 2f5bb665ba7a14c5842fa2e1cde2be039843a2a2
+Author: Alan Stern 
+Date:   Wed Jul 11 11:21:43 2012 -0400
+
+    USB: EHCI: add pointer to end of async-unlink list
+    
+    This patch (as1570) adds a pointer for the end of ehci-hcd's
+    async-unlink list.  The list (which is actually a queue) is singly
+    linked, so having a pointer to its end makes adding new entries easier
+    -- there's no longer any need to scan through the whole list.
+    
+    In principle it could be changed to a standard doubly-linked list.  It
+    turns out that doing so actually makes the code less clear, so I'm
+    leaving it as is.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index efee426a2465..8b75e4279a47 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1041,14 +1041,9 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 
+ 	/* defer till later if busy */
+ 	if (ehci->async_unlink) {
+-		struct ehci_qh		*last;
+-
+-		for (last = ehci->async_unlink;
+-				last->unlink_next;
+-				last = last->unlink_next)
+-			continue;
+ 		qh->qh_state = QH_STATE_UNLINK_WAIT;
+-		last->unlink_next = qh;
++		ehci->async_unlink_last->unlink_next = qh;
++		ehci->async_unlink_last = qh;
+ 
+ 	/* start IAA cycle */
+ 	} else
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 8e80cde8c35e..5193612c96ea 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -1227,6 +1227,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 
+ 	qh->qh_state = QH_STATE_UNLINK;
+ 	ehci->async_unlink = qh;
++	if (!qh->unlink_next)
++		ehci->async_unlink_last = qh;
+ 
+ 	prev = ehci->async;
+ 	while (prev->qh_next.qh != qh)
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 3c6c07c0956a..475f23e10bbf 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -82,6 +82,7 @@ struct ehci_hcd {			/* one per controller */
+ 	struct ehci_qh		*async;
+ 	struct ehci_qh		*dummy;		/* For AMD quirk use */
+ 	struct ehci_qh		*async_unlink;
++	struct ehci_qh		*async_unlink_last;
+ 	struct ehci_qh		*qh_scan_next;
+ 	unsigned		scanning : 1;
+ 

commit 99ac5b1e9536f142461681fa6143a947d66b4279
+Author: Alan Stern 
+Date:   Wed Jul 11 11:21:38 2012 -0400
+
+    USB: EHCI: rename "reclaim"
+    
+    This patch (as1569) renames the ehci->reclaim list in ehci-hcd.  The
+    word "reclaim" is used in the EHCI specification to mean something
+    quite different, and "unlink_next" is more descriptive of the list's
+    purpose anyway.
+    
+    Similarly, the "reclaim" field in the ehci_stats structure is renamed
+    "iaa", which is more meaningful (to experts, anyway) and is a better
+    match for the "lost_iaa" field.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
+index 97338abff296..76120957d60a 100644
+--- a/drivers/usb/host/ehci-dbg.c
++++ b/drivers/usb/host/ehci-dbg.c
+@@ -538,12 +538,13 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf)
+ 	spin_lock_irqsave (&ehci->lock, flags);
+ 	for (qh = ehci->async->qh_next.qh; size > 0 && qh; qh = qh->qh_next.qh)
+ 		qh_lines (ehci, qh, &next, &size);
+-	if (ehci->reclaim && size > 0) {
+-		temp = scnprintf (next, size, "\nreclaim =\n");
++	if (ehci->async_unlink && size > 0) {
++		temp = scnprintf(next, size, "\nunlink =\n");
+ 		size -= temp;
+ 		next += temp;
+ 
+-		for (qh = ehci->reclaim; size > 0 && qh; qh = qh->reclaim)
++		for (qh = ehci->async_unlink; size > 0 && qh;
++				qh = qh->unlink_next)
+ 			qh_lines (ehci, qh, &next, &size);
+ 	}
+ 	spin_unlock_irqrestore (&ehci->lock, flags);
+@@ -841,16 +842,17 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
+ 		}
+ 	}
+ 
+-	if (ehci->reclaim) {
+-		temp = scnprintf(next, size, "reclaim qh %p\n", ehci->reclaim);
++	if (ehci->async_unlink) {
++		temp = scnprintf(next, size, "async unlink qh %p\n",
++				ehci->async_unlink);
+ 		size -= temp;
+ 		next += temp;
+ 	}
+ 
+ #ifdef EHCI_STATS
+ 	temp = scnprintf (next, size,
+-		"irq normal %ld err %ld reclaim %ld (lost %ld)\n",
+-		ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim,
++		"irq normal %ld err %ld iaa %ld (lost %ld)\n",
++		ehci->stats.normal, ehci->stats.error, ehci->stats.iaa,
+ 		ehci->stats.lost_iaa);
+ 	size -= temp;
+ 	next += temp;
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index cdb15769468a..efee426a2465 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -403,7 +403,7 @@ static void ehci_iaa_watchdog(unsigned long param)
+ 	 * (a) SMP races against real IAA firing and retriggering, and
+ 	 * (b) clean HC shutdown, when IAA watchdog was pending.
+ 	 */
+-	if (ehci->reclaim
++	if (ehci->async_unlink
+ 			&& !timer_pending(&ehci->iaa_watchdog)
+ 			&& ehci->rh_state == EHCI_RH_RUNNING) {
+ 		u32 cmd, status;
+@@ -583,8 +583,8 @@ static void ehci_stop (struct usb_hcd *hcd)
+ 		usb_amd_dev_put();
+ 
+ #ifdef	EHCI_STATS
+-	ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n",
+-		ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim,
++	ehci_dbg(ehci, "irq normal %ld err %ld iaa %ld (lost %ld)\n",
++		ehci->stats.normal, ehci->stats.error, ehci->stats.iaa,
+ 		ehci->stats.lost_iaa);
+ 	ehci_dbg (ehci, "complete %ld unlink %ld\n",
+ 		ehci->stats.complete, ehci->stats.unlink);
+@@ -651,7 +651,6 @@ static int ehci_init(struct usb_hcd *hcd)
+ 	else					// N microframes cached
+ 		ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params);
+ 
+-	ehci->reclaim = NULL;
+ 	ehci->next_uframe = -1;
+ 	ehci->clock_frame = -1;
+ 
+@@ -896,11 +895,11 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 		/* guard against (alleged) silicon errata */
+ 		if (cmd & CMD_IAAD)
+ 			ehci_dbg(ehci, "IAA with IAAD still set?\n");
+-		if (ehci->reclaim) {
+-			COUNT(ehci->stats.reclaim);
++		if (ehci->async_unlink) {
++			COUNT(ehci->stats.iaa);
+ 			end_unlink_async(ehci);
+ 		} else
+-			ehci_dbg(ehci, "IAA with nothing to reclaim?\n");
++			ehci_dbg(ehci, "IAA with nothing unlinked?\n");
+ 	}
+ 
+ 	/* remote wakeup [4.3.1] */
+@@ -1027,7 +1026,7 @@ static int ehci_urb_enqueue (
+ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ {
+ 	/* failfast */
+-	if (ehci->rh_state != EHCI_RH_RUNNING && ehci->reclaim)
++	if (ehci->rh_state != EHCI_RH_RUNNING && ehci->async_unlink)
+ 		end_unlink_async(ehci);
+ 
+ 	/* If the QH isn't linked then there's nothing we can do
+@@ -1041,15 +1040,15 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	}
+ 
+ 	/* defer till later if busy */
+-	if (ehci->reclaim) {
++	if (ehci->async_unlink) {
+ 		struct ehci_qh		*last;
+ 
+-		for (last = ehci->reclaim;
+-				last->reclaim;
+-				last = last->reclaim)
++		for (last = ehci->async_unlink;
++				last->unlink_next;
++				last = last->unlink_next)
+ 			continue;
+ 		qh->qh_state = QH_STATE_UNLINK_WAIT;
+-		last->reclaim = qh;
++		last->unlink_next = qh;
+ 
+ 	/* start IAA cycle */
+ 	} else
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 1daaa96f527d..77d3324b4b28 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -301,7 +301,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 	ehci_halt (ehci);
+ 	ehci->rh_state = EHCI_RH_SUSPENDED;
+ 
+-	if (ehci->reclaim)
++	if (ehci->async_unlink)
+ 		end_unlink_async(ehci);
+ 
+ 	/* allow remote wakeup */
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 156504787711..8e80cde8c35e 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -1153,11 +1153,11 @@ submit_async (
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-/* the async qh for the qtds being reclaimed are now unlinked from the HC */
++/* the async qh for the qtds being unlinked are now gone from the HC */
+ 
+ static void end_unlink_async (struct ehci_hcd *ehci)
+ {
+-	struct ehci_qh		*qh = ehci->reclaim;
++	struct ehci_qh		*qh = ehci->async_unlink;
+ 	struct ehci_qh		*next;
+ 
+ 	iaa_watchdog_done(ehci);
+@@ -1167,9 +1167,9 @@ static void end_unlink_async (struct ehci_hcd *ehci)
+ 	qh->qh_next.qh = NULL;
+ 
+ 	/* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */
+-	next = qh->reclaim;
+-	ehci->reclaim = next;
+-	qh->reclaim = NULL;
++	next = qh->unlink_next;
++	ehci->async_unlink = next;
++	qh->unlink_next = NULL;
+ 
+ 	qh_completions (ehci, qh);
+ 
+@@ -1185,7 +1185,7 @@ static void end_unlink_async (struct ehci_hcd *ehci)
+ 	}
+ 
+ 	if (next) {
+-		ehci->reclaim = NULL;
++		ehci->async_unlink = NULL;
+ 		start_unlink_async (ehci, next);
+ 	}
+ 
+@@ -1203,7 +1203,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 
+ #ifdef DEBUG
+ 	assert_spin_locked(&ehci->lock);
+-	if (ehci->reclaim
++	if (ehci->async_unlink
+ 			|| (qh->qh_state != QH_STATE_LINKED
+ 				&& qh->qh_state != QH_STATE_UNLINK_WAIT)
+ 			)
+@@ -1214,7 +1214,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	if (unlikely (qh == ehci->async)) {
+ 		/* can't get here without STS_ASS set */
+ 		if (ehci->rh_state != EHCI_RH_HALTED
+-				&& !ehci->reclaim) {
++				&& !ehci->async_unlink) {
+ 			/* ... and CMD_IAAD clear */
+ 			ehci->command &= ~CMD_ASE;
+ 			ehci_writel(ehci, ehci->command, &ehci->regs->command);
+@@ -1226,7 +1226,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	}
+ 
+ 	qh->qh_state = QH_STATE_UNLINK;
+-	ehci->reclaim = qh;
++	ehci->async_unlink = qh;
+ 
+ 	prev = ehci->async;
+ 	while (prev->qh_next.qh != qh)
+@@ -1240,7 +1240,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 
+ 	/* If the controller isn't running, we don't have to wait for it */
+ 	if (unlikely(ehci->rh_state != EHCI_RH_RUNNING)) {
+-		/* if (unlikely (qh->reclaim != 0))
++		/* if (unlikely (qh->unlink_next != 0))
+ 		 *	this will recurse, probably not much
+ 		 */
+ 		end_unlink_async (ehci);
+@@ -1295,7 +1295,7 @@ static void scan_async (struct ehci_hcd *ehci)
+ 		 */
+ 		if (list_empty(&qh->qtd_list)
+ 				&& qh->qh_state == QH_STATE_LINKED) {
+-			if (!ehci->reclaim && (stopped ||
++			if (!ehci->async_unlink && (stopped ||
+ 					time_after_eq(jiffies, qh->unlink_time)))
+ 				start_unlink_async(ehci, qh);
+ 			else
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 195449db1b18..3c6c07c0956a 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -42,7 +42,7 @@ struct ehci_stats {
+ 	/* irq usage */
+ 	unsigned long		normal;
+ 	unsigned long		error;
+-	unsigned long		reclaim;
++	unsigned long		iaa;
+ 	unsigned long		lost_iaa;
+ 
+ 	/* termination of urbs from core */
+@@ -51,7 +51,7 @@ struct ehci_stats {
+ };
+ 
+ /* ehci_hcd->lock guards shared data against other CPUs:
+- *   ehci_hcd:	async, reclaim, periodic (and shadow), ...
++ *   ehci_hcd:	async, unlink, periodic (and shadow), ...
+  *   usb_host_endpoint: hcpriv
+  *   ehci_qh:	qh_next, qtd_list
+  *   ehci_qtd:	qtd_list
+@@ -81,7 +81,7 @@ struct ehci_hcd {			/* one per controller */
+ 	/* async schedule support */
+ 	struct ehci_qh		*async;
+ 	struct ehci_qh		*dummy;		/* For AMD quirk use */
+-	struct ehci_qh		*reclaim;
++	struct ehci_qh		*async_unlink;
+ 	struct ehci_qh		*qh_scan_next;
+ 	unsigned		scanning : 1;
+ 
+@@ -354,7 +354,7 @@ struct ehci_qh {
+ 	union ehci_shadow	qh_next;	/* ptr to qh; or periodic */
+ 	struct list_head	qtd_list;	/* sw qtd list */
+ 	struct ehci_qtd		*dummy;
+-	struct ehci_qh		*reclaim;	/* next to reclaim */
++	struct ehci_qh		*unlink_next;	/* next on unlink list */
+ 
+ 	unsigned long		unlink_time;
+ 	unsigned		stamp;
+@@ -364,7 +364,7 @@ struct ehci_qh {
+ #define	QH_STATE_LINKED		1		/* HC sees this */
+ #define	QH_STATE_UNLINK		2		/* HC may still see this */
+ #define	QH_STATE_IDLE		3		/* HC doesn't see this */
+-#define	QH_STATE_UNLINK_WAIT	4		/* LINKED and on reclaim q */
++#define	QH_STATE_UNLINK_WAIT	4		/* LINKED and on unlink q */
+ #define	QH_STATE_COMPLETING	5		/* don't touch token.HALT */
+ 
+ 	u8			xacterrs;	/* XactErr retry counter */

commit 4c53de72109759c931744734ca75f9cecb3baef1
+Author: Alan Stern 
+Date:   Wed Jul 11 11:21:32 2012 -0400
+
+    USB: EHCI: add symbolic constants for QHs
+    
+    This patch (as1568) introduces symbolic constants for some of the
+    less-frequently used bitfields in the QH structure.  This makes the
+    code a little easier to read and understand.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
+index 7561966fbdc4..97338abff296 100644
+--- a/drivers/usb/host/ehci-dbg.c
++++ b/drivers/usb/host/ehci-dbg.c
+@@ -404,9 +404,9 @@ struct debug_buffer {
+ 
+ #define speed_char(info1) ({ char tmp; \
+ 		switch (info1 & (3 << 12)) { \
+-		case 0 << 12: tmp = 'f'; break; \
+-		case 1 << 12: tmp = 'l'; break; \
+-		case 2 << 12: tmp = 'h'; break; \
++		case QH_FULL_SPEED: tmp = 'f'; break; \
++		case QH_LOW_SPEED:  tmp = 'l'; break; \
++		case QH_HIGH_SPEED: tmp = 'h'; break; \
+ 		default: tmp = '?'; break; \
+ 		}; tmp; })
+ 
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 1f8f792eec86..cdb15769468a 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -667,7 +667,7 @@ static int ehci_init(struct usb_hcd *hcd)
+ 	hw->hw_next = QH_NEXT(ehci, ehci->async->qh_dma);
+ 	hw->hw_info1 = cpu_to_hc32(ehci, QH_HEAD);
+ #if defined(CONFIG_PPC_PS3)
+-	hw->hw_info1 |= cpu_to_hc32(ehci, (1 << 7));	/* I = 1 */
++	hw->hw_info1 |= cpu_to_hc32(ehci, QH_INACTIVATE);
+ #endif
+ 	hw->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT);
+ 	hw->hw_qtd_next = EHCI_LIST_END(ehci);
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 7d117bbffac1..156504787711 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -100,7 +100,7 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
+ 	 * and set the pseudo-toggle in udev. Only usb_clear_halt() will
+ 	 * ever clear it.
+ 	 */
+-	if (!(hw->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) {
++	if (!(hw->hw_info1 & cpu_to_hc32(ehci, QH_TOGGLE_CTL))) {
+ 		unsigned	is_out, epnum;
+ 
+ 		is_out = qh->is_out;
+@@ -886,7 +886,7 @@ qh_make (
+ 	/* using TT? */
+ 	switch (urb->dev->speed) {
+ 	case USB_SPEED_LOW:
+-		info1 |= (1 << 12);	/* EPS "low" */
++		info1 |= QH_LOW_SPEED;
+ 		/* FALL THROUGH */
+ 
+ 	case USB_SPEED_FULL:
+@@ -894,8 +894,8 @@ qh_make (
+ 		if (type != PIPE_INTERRUPT)
+ 			info1 |= (EHCI_TUNE_RL_TT << 28);
+ 		if (type == PIPE_CONTROL) {
+-			info1 |= (1 << 27);	/* for TT */
+-			info1 |= 1 << 14;	/* toggle from qtd */
++			info1 |= QH_CONTROL_EP;		/* for TT */
++			info1 |= QH_TOGGLE_CTL;		/* toggle from qtd */
+ 		}
+ 		info1 |= maxp << 16;
+ 
+@@ -920,11 +920,11 @@ qh_make (
+ 		break;
+ 
+ 	case USB_SPEED_HIGH:		/* no TT involved */
+-		info1 |= (2 << 12);	/* EPS "high" */
++		info1 |= QH_HIGH_SPEED;
+ 		if (type == PIPE_CONTROL) {
+ 			info1 |= (EHCI_TUNE_RL_HS << 28);
+ 			info1 |= 64 << 16;	/* usb2 fixed maxpacket */
+-			info1 |= 1 << 14;	/* toggle from qtd */
++			info1 |= QH_TOGGLE_CTL;	/* toggle from qtd */
+ 			info2 |= (EHCI_TUNE_MULT_HS << 30);
+ 		} else if (type == PIPE_BULK) {
+ 			info1 |= (EHCI_TUNE_RL_HS << 28);
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index f7a59f5d70c6..195449db1b18 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -324,7 +324,13 @@ union ehci_shadow {
+ struct ehci_qh_hw {
+ 	__hc32			hw_next;	/* see EHCI 3.6.1 */
+ 	__hc32			hw_info1;       /* see EHCI 3.6.2 */
+-#define	QH_HEAD		0x00008000
++#define	QH_CONTROL_EP	(1 << 27)	/* FS/LS control endpoint */
++#define	QH_HEAD		(1 << 15)	/* Head of async reclamation list */
++#define	QH_TOGGLE_CTL	(1 << 14)	/* Data toggle control */
++#define	QH_HIGH_SPEED	(2 << 12)	/* Endpoint speed */
++#define	QH_LOW_SPEED	(1 << 12)
++#define	QH_FULL_SPEED	(0 << 12)
++#define	QH_INACTIVATE	(1 << 7)	/* Inactivate on next transaction */
+ 	__hc32			hw_info2;        /* see EHCI 3.6.2 */
+ #define	QH_SMASK	0x000000ff
+ #define	QH_CMASK	0x0000ff00

commit c83e1a9ff68a6535b81c40dc8fda99348ab480fb
+Author: Alan Stern 
+Date:   Wed Jul 11 11:21:25 2012 -0400
+
+    USB: EHCI: don't refcount QHs
+    
+    This patch (as1567) removes ehci-hcd's reference counting of QH
+    structures.  It's not necessary to refcount these things because they
+    always get deallocated at exactly one spot in ehci_endpoint_disable()
+    (except for two special QHs, ehci->async and ehci->dummy) and are
+    never used again.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index ab7306de8d16..1f8f792eec86 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1179,7 +1179,7 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 		if (qh->clearing_tt)
+ 			goto idle_timeout;
+ 		if (list_empty (&qh->qtd_list)) {
+-			qh_put (qh);
++			qh_destroy(ehci, qh);
+ 			break;
+ 		}
+ 		/* else FALL THROUGH */
+diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
+index 12f70c302b0b..93132d8ad360 100644
+--- a/drivers/usb/host/ehci-mem.c
++++ b/drivers/usb/host/ehci-mem.c
+@@ -64,10 +64,8 @@ static inline void ehci_qtd_free (struct ehci_hcd *ehci, struct ehci_qtd *qtd)
+ }
+ 
+ 
+-static void qh_destroy(struct ehci_qh *qh)
++static void qh_destroy(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ {
+-	struct ehci_hcd *ehci = qh->ehci;
+-
+ 	/* clean qtds first, and know this is not linked */
+ 	if (!list_empty (&qh->qtd_list) || qh->qh_next.ptr) {
+ 		ehci_dbg (ehci, "unused qh not empty!\n");
+@@ -92,8 +90,6 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags)
+ 	if (!qh->hw)
+ 		goto fail;
+ 	memset(qh->hw, 0, sizeof *qh->hw);
+-	qh->refcount = 1;
+-	qh->ehci = ehci;
+ 	qh->qh_dma = dma;
+ 	// INIT_LIST_HEAD (&qh->qh_list);
+ 	INIT_LIST_HEAD (&qh->qtd_list);
+@@ -113,20 +109,6 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags)
+ 	return NULL;
+ }
+ 
+-/* to share a qh (cpu threads, or hc) */
+-static inline struct ehci_qh *qh_get (struct ehci_qh *qh)
+-{
+-	WARN_ON(!qh->refcount);
+-	qh->refcount++;
+-	return qh;
+-}
+-
+-static inline void qh_put (struct ehci_qh *qh)
+-{
+-	if (!--qh->refcount)
+-		qh_destroy(qh);
+-}
+-
+ /*-------------------------------------------------------------------------*/
+ 
+ /* The queue heads and transfer descriptors are managed from pools tied
+@@ -138,11 +120,11 @@ static void ehci_mem_cleanup (struct ehci_hcd *ehci)
+ {
+ 	free_cached_lists(ehci);
+ 	if (ehci->async)
+-		qh_put (ehci->async);
++		qh_destroy(ehci, ehci->async);
+ 	ehci->async = NULL;
+ 
+ 	if (ehci->dummy)
+-		qh_put(ehci->dummy);
++		qh_destroy(ehci, ehci->dummy);
+ 	ehci->dummy = NULL;
+ 
+ 	/* DMA consistent memory and pools */
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 4378bf72bbac..7d117bbffac1 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -265,7 +265,6 @@ __acquires(ehci->lock)
+ 			/* ... update hc-wide periodic stats (for usbfs) */
+ 			ehci_to_hcd(ehci)->self.bandwidth_int_reqs--;
+ 		}
+-		qh_put (qh);
+ 	}
+ 
+ 	if (unlikely(urb->unlinked)) {
+@@ -946,7 +945,7 @@ qh_make (
+ 		ehci_dbg(ehci, "bogus dev %p speed %d\n", urb->dev,
+ 			urb->dev->speed);
+ done:
+-		qh_put (qh);
++		qh_destroy(ehci, qh);
+ 		return NULL;
+ 	}
+ 
+@@ -1003,7 +1002,6 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	head->qh_next.qh = qh;
+ 	head->hw->hw_next = dma;
+ 
+-	qh_get(qh);
+ 	qh->xacterrs = 0;
+ 	qh->qh_state = QH_STATE_LINKED;
+ 	/* qtd completions reported later by interrupt */
+@@ -1090,7 +1088,7 @@ static struct ehci_qh *qh_append_tds (
+ 			wmb ();
+ 			dummy->hw_token = token;
+ 
+-			urb->hcpriv = qh_get (qh);
++			urb->hcpriv = qh;
+ 		}
+ 	}
+ 	return qh;
+@@ -1167,7 +1165,6 @@ static void end_unlink_async (struct ehci_hcd *ehci)
+ 	// qh->hw_next = cpu_to_hc32(qh->qh_dma);
+ 	qh->qh_state = QH_STATE_IDLE;
+ 	qh->qh_next.qh = NULL;
+-	qh_put (qh);			// refcount from reclaim
+ 
+ 	/* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */
+ 	next = qh->reclaim;
+@@ -1186,7 +1183,6 @@ static void end_unlink_async (struct ehci_hcd *ehci)
+ 				&& ehci->async->qh_next.qh == NULL)
+ 			timer_action (ehci, TIMER_ASYNC_OFF);
+ 	}
+-	qh_put(qh);			/* refcount from async list */
+ 
+ 	if (next) {
+ 		ehci->reclaim = NULL;
+@@ -1230,7 +1226,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	}
+ 
+ 	qh->qh_state = QH_STATE_UNLINK;
+-	ehci->reclaim = qh = qh_get (qh);
++	ehci->reclaim = qh;
+ 
+ 	prev = ehci->async;
+ 	while (prev->qh_next.qh != qh)
+@@ -1283,12 +1279,10 @@ static void scan_async (struct ehci_hcd *ehci)
+ 			 * gets unlinked then ehci->qh_scan_next is adjusted
+ 			 * in start_unlink_async().
+ 			 */
+-			qh = qh_get(qh);
+ 			temp = qh_completions(ehci, qh);
+ 			if (qh->needs_rescan)
+ 				unlink_async(ehci, qh);
+ 			qh->unlink_time = jiffies + EHCI_SHRINK_JIFFIES;
+-			qh_put(qh);
+ 			if (temp != 0)
+ 				goto rescan;
+ 		}
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 33182c6d1ff9..027df3de2dc9 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -606,7 +606,6 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	}
+ 	qh->qh_state = QH_STATE_LINKED;
+ 	qh->xacterrs = 0;
+-	qh_get (qh);
+ 
+ 	/* update per-qh bandwidth for usbfs */
+ 	ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->period
+@@ -650,7 +649,6 @@ static int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	/* qh->qh_next still "live" to HC */
+ 	qh->qh_state = QH_STATE_UNLINK;
+ 	qh->qh_next.ptr = NULL;
+-	qh_put (qh);
+ 
+ 	/* maybe turn off periodic schedule */
+ 	return disable_periodic(ehci);
+@@ -2340,7 +2338,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 			switch (hc32_to_cpu(ehci, type)) {
+ 			case Q_TYPE_QH:
+ 				/* handle any completions */
+-				temp.qh = qh_get (q.qh);
++				temp.qh = q.qh;
+ 				type = Q_NEXT_TYPE(ehci, q.qh->hw->hw_next);
+ 				q = q.qh->qh_next;
+ 				if (temp.qh->stamp != ehci->periodic_stamp) {
+@@ -2351,7 +2349,6 @@ scan_periodic (struct ehci_hcd *ehci)
+ 							temp.qh->needs_rescan))
+ 						intr_deschedule(ehci, temp.qh);
+ 				}
+-				qh_put (temp.qh);
+ 				break;
+ 			case Q_TYPE_FSTN:
+ 				/* for "save place" FSTNs, look at QH entries
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 85c3572155d1..f7a59f5d70c6 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -350,16 +350,7 @@ struct ehci_qh {
+ 	struct ehci_qtd		*dummy;
+ 	struct ehci_qh		*reclaim;	/* next to reclaim */
+ 
+-	struct ehci_hcd		*ehci;
+ 	unsigned long		unlink_time;
+-
+-	/*
+-	 * Do NOT use atomic operations for QH refcounting. On some CPUs
+-	 * (PPC7448 for example), atomic operations cannot be performed on
+-	 * memory that is cache-inhibited (i.e. being used for DMA).
+-	 * Spinlocks are used to protect all QH fields.
+-	 */
+-	u32			refcount;
+ 	unsigned		stamp;
+ 
+ 	u8			needs_rescan;	/* Dequeue during giveback */

commit 15be105b4a18c461b95fa683907f6da6deae1b75
+Author: Alan Stern 
+Date:   Wed Jul 11 11:21:17 2012 -0400
+
+    USB: EHCI: remove unneeded suspend/resume code
+    
+    This patch (as1566) removes the code in ehci-hcd's resume routines
+    which tries to restart or cancel any transfers left active while the
+    root hub or controller was asleep.  This code isn't necessary, because
+    all URBs are terminated before the root hub is suspended.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 8727f4ea343f..ab7306de8d16 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1312,13 +1312,6 @@ static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated)
+ 	(void) ehci_halt(ehci);
+ 	(void) ehci_reset(ehci);
+ 
+-	/* emptying the schedule aborts any urbs */
+-	spin_lock_irq(&ehci->lock);
+-	if (ehci->reclaim)
+-		end_unlink_async(ehci);
+-	ehci_work(ehci);
+-	spin_unlock_irq(&ehci->lock);
+-
+ 	ehci_writel(ehci, ehci->command, &ehci->regs->command);
+ 	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
+ 	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index b3e2d66e95bb..1daaa96f527d 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -424,23 +424,12 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 			ehci_vdbg (ehci, "resumed port %d\n", i + 1);
+ 		}
+ 	}
+-	(void) ehci_readl(ehci, &ehci->regs->command);
+-
+-	/* maybe re-activate the schedule(s) */
+-	temp = 0;
+-	if (ehci->async->qh_next.qh)
+-		temp |= CMD_ASE;
+-	if (ehci->periodic_sched)
+-		temp |= CMD_PSE;
+-	if (temp) {
+-		ehci->command |= temp;
+-		ehci_writel(ehci, ehci->command, &ehci->regs->command);
+-	}
+ 
+ 	ehci->next_statechange = jiffies + msecs_to_jiffies(5);
+ 
+ 	/* Now we can safely re-enable irqs */
+ 	ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
++	(void) ehci_readl(ehci, &ehci->regs->intr_enable);
+ 
+ 	spin_unlock_irq (&ehci->lock);
+ 	ehci_handover_companion_ports(ehci);

commit 631fe9d9d20e28fffdf750d12dd2cd275bd654e9
+Author: Alan Stern 
+Date:   Wed Jul 11 11:21:09 2012 -0400
+
+    USB: EHCI: initialize data before resetting hardware
+    
+    Currently, EHCI initialization turns off the controller (in case it
+    was left running by the firmware) before setting up the ehci_hcd data
+    structure.  This patch (as1565) reverses that order.
+    
+    Although it doesn't matter now, it will matter later on when future
+    additions to ehci_halt() will want to acquire a spinlock that gets
+    initialized by ehci_init().
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index f9a783bfa1fe..8727f4ea343f 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -823,12 +823,12 @@ static int ehci_setup(struct usb_hcd *hcd)
+ 
+ 	ehci->sbrn = HCD_USB2;
+ 
+-	retval = ehci_halt(ehci);
++	/* data structure init */
++	retval = ehci_init(hcd);
+ 	if (retval)
+ 		return retval;
+ 
+-	/* data structure init */
+-	retval = ehci_init(hcd);
++	retval = ehci_halt(ehci);
+ 	if (retval)
+ 		return retval;
+ 

commit dbf0e4c7257f8d684ec1a3c919853464293de66e
+Author: Alan Stern 
+Date:   Mon Jul 9 11:09:21 2012 -0400
+
+    PCI: EHCI: fix crash during suspend on ASUS computers
+    
+    Quite a few ASUS computers experience a nasty problem, related to the
+    EHCI controllers, when going into system suspend.  It was observed
+    that the problem didn't occur if the controllers were not put into the
+    D3 power state before starting the suspend, and commit
+    151b61284776be2d6f02d48c23c3625678960b97 (USB: EHCI: fix crash during
+    suspend on ASUS computers) was created to do this.
+    
+    It turned out this approach messed up other computers that didn't have
+    the problem -- it prevented USB wakeup from working.  Consequently
+    commit c2fb8a3fa25513de8fedb38509b1f15a5bbee47b (USB: add
+    NO_D3_DURING_SLEEP flag and revert 151b61284776be2) was merged; it
+    reverted the earlier commit and added a whitelist of known good board
+    names.
+    
+    Now we know the actual cause of the problem.  Thanks to AceLan Kao for
+    tracking it down.
+    
+    According to him, an engineer at ASUS explained that some of their
+    BIOSes contain a bug that was added in an attempt to work around a
+    problem in early versions of Windows.  When the computer goes into S3
+    suspend, the BIOS tries to verify that the EHCI controllers were first
+    quiesced by the OS.  Nothing's wrong with this, but the BIOS does it
+    by checking that the PCI COMMAND registers contain 0 without checking
+    the controllers' power state.  If the register isn't 0, the BIOS
+    assumes the controller needs to be quiesced and tries to do so.  This
+    involves making various MMIO accesses to the controller, which don't
+    work very well if the controller is already in D3.  The end result is
+    a system hang or memory corruption.
+    
+    Since the value in the PCI COMMAND register doesn't matter once the
+    controller has been suspended, and since the value will be restored
+    anyway when the controller is resumed, we can work around the BIOS bug
+    simply by setting the register to 0 during system suspend.  This patch
+    (as1590) does so and also reverts the second commit mentioned above,
+    which is now unnecessary.
+    
+    In theory we could do this for every PCI device.  However to avoid
+    introducing new problems, the patch restricts itself to EHCI host
+    controllers.
+    
+    Finally the affected systems can suspend with USB wakeup working
+    properly.
+    
+    Reference: https://bugzilla.kernel.org/show_bug.cgi?id=37632
+    Reference: https://bugzilla.kernel.org/show_bug.cgi?id=42728
+    Based-on-patch-by: AceLan Kao 
+    Signed-off-by: Alan Stern 
+    Tested-by: Dâniel Fraga 
+    Tested-by: Javier Marcet 
+    Tested-by: Andrey Rahmatullin 
+    Tested-by: Oleksij Rempel 
+    Tested-by: Pavel Pisa 
+    Cc: stable 
+    Acked-by: Bjorn Helgaas 
+    Acked-by: Rafael J. Wysocki 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
+index bf0cee629b60..099f46cd8e87 100644
+--- a/drivers/pci/pci-driver.c
++++ b/drivers/pci/pci-driver.c
+@@ -748,6 +748,18 @@ static int pci_pm_suspend_noirq(struct device *dev)
+ 
+ 	pci_pm_set_unknown_state(pci_dev);
+ 
++	/*
++	 * Some BIOSes from ASUS have a bug: If a USB EHCI host controller's
++	 * PCI COMMAND register isn't 0, the BIOS assumes that the controller
++	 * hasn't been quiesced and tries to turn it off.  If the controller
++	 * is already in D3, this can hang or cause memory corruption.
++	 *
++	 * Since the value of the COMMAND register doesn't matter once the
++	 * device has been suspended, we can safely set it to 0 here.
++	 */
++	if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI)
++		pci_write_config_word(pci_dev, PCI_COMMAND, 0);
++
+ 	return 0;
+ }
+ 
+diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
+index 77cb54a65cde..447e83472c01 100644
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -1744,11 +1744,6 @@ int pci_prepare_to_sleep(struct pci_dev *dev)
+ 	if (target_state == PCI_POWER_ERROR)
+ 		return -EIO;
+ 
+-	/* Some devices mustn't be in D3 during system sleep */
+-	if (target_state == PCI_D3hot &&
+-			(dev->dev_flags & PCI_DEV_FLAGS_NO_D3_DURING_SLEEP))
+-		return 0;
+-
+ 	pci_enable_wake(dev, target_state, device_may_wakeup(&dev->dev));
+ 
+ 	error = pci_set_power_state(dev, target_state);
+diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
+index 194b243a2817..2a7521677541 100644
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -2929,32 +2929,6 @@ static void __devinit disable_igfx_irq(struct pci_dev *dev)
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0102, disable_igfx_irq);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq);
+ 
+-/*
+- * The Intel 6 Series/C200 Series chipset's EHCI controllers on many
+- * ASUS motherboards will cause memory corruption or a system crash
+- * if they are in D3 while the system is put into S3 sleep.
+- */
+-static void __devinit asus_ehci_no_d3(struct pci_dev *dev)
+-{
+-	const char *sys_info;
+-	static const char good_Asus_board[] = "P8Z68-V";
+-
+-	if (dev->dev_flags & PCI_DEV_FLAGS_NO_D3_DURING_SLEEP)
+-		return;
+-	if (dev->subsystem_vendor != PCI_VENDOR_ID_ASUSTEK)
+-		return;
+-	sys_info = dmi_get_system_info(DMI_BOARD_NAME);
+-	if (sys_info && memcmp(sys_info, good_Asus_board,
+-			sizeof(good_Asus_board) - 1) == 0)
+-		return;
+-
+-	dev_info(&dev->dev, "broken D3 during system sleep on ASUS\n");
+-	dev->dev_flags |= PCI_DEV_FLAGS_NO_D3_DURING_SLEEP;
+-	device_set_wakeup_capable(&dev->dev, false);
+-}
+-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1c26, asus_ehci_no_d3);
+-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1c2d, asus_ehci_no_d3);
+-
+ static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
+ 			  struct pci_fixup *end)
+ {
+diff --git a/include/linux/pci.h b/include/linux/pci.h
+index fefb4e19bf6a..d8c379dba6ad 100644
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -176,8 +176,6 @@ enum pci_dev_flags {
+ 	PCI_DEV_FLAGS_NO_D3 = (__force pci_dev_flags_t) 2,
+ 	/* Provide indication device is assigned by a Virtual Machine Manager */
+ 	PCI_DEV_FLAGS_ASSIGNED = (__force pci_dev_flags_t) 4,
+-	/* Device causes system crash if in D3 during S3 sleep */
+-	PCI_DEV_FLAGS_NO_D3_DURING_SLEEP = (__force pci_dev_flags_t) 8,
+ };
+ 
+ enum pci_irq_reroute_variant {

commit 1a49e2ac9651df7349867a5cf44e2c83de1046af
+Author: Alan Stern 
+Date:   Mon Jul 9 15:55:14 2012 -0400
+
+    EHCI: centralize controller initialization
+    
+    This patch (as1564c) converts the EHCI platform drivers to use the
+    central ehci_setup() routine for generic controller initialization
+    rather than each having its own idiosyncratic approach.
+    
+    The major point of difficulty lies in ehci-pci's many vendor- and
+    device-specific workarounds.  Some of them have to be applied before
+    calling ehci_setup() and some after, which necessitates a fair amount
+    of code motion.  The other platform drivers require much smaller
+    changes.
+    
+    One point not addressed by the patch is whether ports should be
+    powered on or off following initialization.  The different drivers
+    appear to handle this pretty much at random.  In fact it shouldn't
+    matter, because the hub driver turns on power to all ports when it
+    binds to the root hub.  Straightening that out will be left for
+    another day.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
+index cf14c95a6700..a47e2cffaaf8 100644
+--- a/drivers/usb/host/ehci-atmel.c
++++ b/drivers/usb/host/ehci-atmel.c
+@@ -53,30 +53,15 @@ static void atmel_stop_ehci(struct platform_device *pdev)
+ static int ehci_atmel_setup(struct usb_hcd *hcd)
+ {
+ 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+-	int retval = 0;
++	int retval;
+ 
+ 	/* registers start at offset 0x0 */
+ 	ehci->caps = hcd->regs;
+-	ehci->regs = hcd->regs +
+-		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
+-	dbg_hcs_params(ehci, "reset");
+-	dbg_hcc_params(ehci, "reset");
+-
+-	/* cache this readonly data; minimize chip reads */
+-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+-
+-	retval = ehci_halt(ehci);
+-	if (retval)
+-		return retval;
+ 
+-	/* data structure init */
+-	retval = ehci_init(hcd);
++	retval = ehci_setup(hcd);
+ 	if (retval)
+ 		return retval;
+ 
+-	ehci->sbrn = 0x20;
+-
+-	ehci_reset(ehci);
+ 	ehci_port_power(ehci, 0);
+ 
+ 	return retval;
+diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
+index 182d39565906..cba10d625a5d 100644
+--- a/drivers/usb/host/ehci-au1xxx.c
++++ b/drivers/usb/host/ehci-au1xxx.c
+@@ -20,10 +20,12 @@ extern int usb_disabled(void);
+ static int au1xxx_ehci_setup(struct usb_hcd *hcd)
+ {
+ 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+-	int ret = ehci_init(hcd);
++	int ret;
++
++	ehci->caps = hcd->regs;
++	ret = ehci_setup(hcd);
+ 
+ 	ehci->need_io_watchdog = 0;
+-	ehci_reset(ehci);
+ 	return ret;
+ }
+ 
+@@ -78,7 +80,6 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
+ static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
+ {
+ 	struct usb_hcd *hcd;
+-	struct ehci_hcd *ehci;
+ 	struct resource *res;
+ 	int ret;
+ 
+@@ -116,13 +117,6 @@ static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
+ 		goto err3;
+ 	}
+ 
+-	ehci = hcd_to_ehci(hcd);
+-	ehci->caps = hcd->regs;
+-	ehci->regs = hcd->regs +
+-		HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
+-	/* cache this readonly data; minimize chip reads */
+-	ehci->hcs_params = readl(&ehci->caps->hcs_params);
+-
+ 	ret = usb_add_hcd(hcd, pdev->resource[1].start,
+ 			  IRQF_SHARED);
+ 	if (ret == 0) {
+diff --git a/drivers/usb/host/ehci-cns3xxx.c b/drivers/usb/host/ehci-cns3xxx.c
+index 6536abdea6e6..caaa3e5be334 100644
+--- a/drivers/usb/host/ehci-cns3xxx.c
++++ b/drivers/usb/host/ehci-cns3xxx.c
+@@ -33,14 +33,10 @@ static int cns3xxx_ehci_init(struct usb_hcd *hcd)
+ 	}
+ 
+ 	ehci->caps = hcd->regs;
+-	ehci->regs = hcd->regs
+-		+ HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
+-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+ 
+ 	hcd->has_tt = 0;
+-	ehci_reset(ehci);
+ 
+-	retval = ehci_init(hcd);
++	retval = ehci_setup(hcd);
+ 	if (retval)
+ 		return retval;
+ 
+diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
+index 74914de8b9bf..ab52db684b63 100644
+--- a/drivers/usb/host/ehci-fsl.c
++++ b/drivers/usb/host/ehci-fsl.c
+@@ -348,29 +348,13 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
+ 
+ 	/* EHCI registers start at offset 0x100 */
+ 	ehci->caps = hcd->regs + 0x100;
+-	ehci->regs = hcd->regs + 0x100 +
+-		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
+-	dbg_hcs_params(ehci, "reset");
+-	dbg_hcc_params(ehci, "reset");
+-
+-	/* cache this readonly data; minimize chip reads */
+-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+ 
+ 	hcd->has_tt = 1;
+ 
+-	retval = ehci_halt(ehci);
+-	if (retval)
+-		return retval;
+-
+-	/* data structure init */
+-	retval = ehci_init(hcd);
++	retval = ehci_setup(hcd);
+ 	if (retval)
+ 		return retval;
+ 
+-	ehci->sbrn = 0x20;
+-
+-	ehci_reset(ehci);
+-
+ 	if (of_device_is_compatible(dev->parent->of_node,
+ 				    "fsl,mpc5121-usb2-dr")) {
+ 		/*
+diff --git a/drivers/usb/host/ehci-grlib.c b/drivers/usb/host/ehci-grlib.c
+index fdfd8c5b639b..22ca45c079a4 100644
+--- a/drivers/usb/host/ehci-grlib.c
++++ b/drivers/usb/host/ehci-grlib.c
+@@ -40,18 +40,13 @@ static int ehci_grlib_setup(struct usb_hcd *hcd)
+ 	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
+ 	int		retval;
+ 
+-	retval = ehci_halt(ehci);
++	retval = ehci_setup(hcd);
+ 	if (retval)
+ 		return retval;
+ 
+-	retval = ehci_init(hcd);
+-	if (retval)
+-		return retval;
+-
+-	ehci->sbrn = 0x20;
+ 	ehci_port_power(ehci, 1);
+ 
+-	return ehci_reset(ehci);
++	return retval;
+ }
+ 
+ 
+@@ -164,12 +159,6 @@ static int __devinit ehci_hcd_grlib_probe(struct platform_device *op)
+ 		ehci->big_endian_capbase = 1;
+ 	}
+ 
+-	ehci->regs = hcd->regs +
+-		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
+-
+-	/* cache this readonly data; minimize chip reads */
+-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+-
+ 	rv = usb_add_hcd(hcd, irq, 0);
+ 	if (rv)
+ 		goto err_ehci;
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index e6823a0cf642..f9a783bfa1fe 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -808,7 +808,7 @@ static int ehci_run (struct usb_hcd *hcd)
+ 	return 0;
+ }
+ 
+-static int __maybe_unused ehci_setup (struct usb_hcd *hcd)
++static int ehci_setup(struct usb_hcd *hcd)
+ {
+ 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ 	int retval;
+@@ -832,6 +832,9 @@ static int __maybe_unused ehci_setup (struct usb_hcd *hcd)
+ 	if (retval)
+ 		return retval;
+ 
++	if (ehci_is_TDI(ehci))
++		tdi_reset(ehci);
++
+ 	ehci_reset(ehci);
+ 
+ 	return 0;
+diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c
+index c4460f3d009f..488d401942e9 100644
+--- a/drivers/usb/host/ehci-ixp4xx.c
++++ b/drivers/usb/host/ehci-ixp4xx.c
+@@ -22,14 +22,10 @@ static int ixp4xx_ehci_init(struct usb_hcd *hcd)
+ 	ehci->big_endian_mmio = 1;
+ 
+ 	ehci->caps = hcd->regs + 0x100;
+-	ehci->regs = hcd->regs + 0x100
+-		+ HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
+-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+ 
+ 	hcd->has_tt = 1;
+-	ehci_reset(ehci);
+ 
+-	retval = ehci_init(hcd);
++	retval = ehci_setup(hcd);
+ 	if (retval)
+ 		return retval;
+ 
+diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c
+index 0e8c168ca24c..f6df1ccc9617 100644
+--- a/drivers/usb/host/ehci-mv.c
++++ b/drivers/usb/host/ehci-mv.c
+@@ -77,7 +77,6 @@ static void mv_ehci_disable(struct ehci_hcd_mv *ehci_mv)
+ 
+ static int mv_ehci_reset(struct usb_hcd *hcd)
+ {
+-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ 	struct device *dev = hcd->self.controller;
+ 	struct ehci_hcd_mv *ehci_mv = dev_get_drvdata(dev);
+ 	int retval;
+@@ -87,25 +86,13 @@ static int mv_ehci_reset(struct usb_hcd *hcd)
+ 		return -ENODEV;
+ 	}
+ 
+-	/*
+-	 * data structure init
+-	 */
+-	retval = ehci_init(hcd);
+-	if (retval) {
+-		dev_err(dev, "ehci_init failed %d\n", retval);
+-		return retval;
+-	}
+-
+ 	hcd->has_tt = 1;
+-	ehci->sbrn = 0x20;
+ 
+-	retval = ehci_reset(ehci);
+-	if (retval) {
+-		dev_err(dev, "ehci_reset failed %d\n", retval);
+-		return retval;
+-	}
++	retval = ehci_setup(hcd);
++	if (retval)
++		dev_err(dev, "ehci_setup failed %d\n", retval);
+ 
+-	return 0;
++	return retval;
+ }
+ 
+ static const struct hc_driver mv_ehci_hc_driver = {
+@@ -248,8 +235,6 @@ static int mv_ehci_probe(struct platform_device *pdev)
+ 
+ 	ehci = hcd_to_ehci(hcd);
+ 	ehci->caps = (struct ehci_caps *) ehci_mv->cap_regs;
+-	ehci->regs = (struct ehci_regs *) ehci_mv->op_regs;
+-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+ 
+ 	ehci_mv->mode = pdata->mode;
+ 	if (ehci_mv->mode == MV_USB_MODE_OTG) {
+diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
+index c778ffe4e4e5..34201372c85f 100644
+--- a/drivers/usb/host/ehci-mxc.c
++++ b/drivers/usb/host/ehci-mxc.c
+@@ -42,27 +42,12 @@ static int ehci_mxc_setup(struct usb_hcd *hcd)
+ 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ 	int retval;
+ 
+-	dbg_hcs_params(ehci, "reset");
+-	dbg_hcc_params(ehci, "reset");
+-
+-	/* cache this readonly data; minimize chip reads */
+-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+-
+ 	hcd->has_tt = 1;
+ 
+-	retval = ehci_halt(ehci);
++	retval = ehci_setup(hcd);
+ 	if (retval)
+ 		return retval;
+ 
+-	/* data structure init */
+-	retval = ehci_init(hcd);
+-	if (retval)
+-		return retval;
+-
+-	ehci->sbrn = 0x20;
+-
+-	ehci_reset(ehci);
+-
+ 	ehci_port_power(ehci, 0);
+ 	return 0;
+ }
+diff --git a/drivers/usb/host/ehci-octeon.c b/drivers/usb/host/ehci-octeon.c
+index c0104882c72d..ba26957abf46 100644
+--- a/drivers/usb/host/ehci-octeon.c
++++ b/drivers/usb/host/ehci-octeon.c
+@@ -56,7 +56,7 @@ static const struct hc_driver ehci_octeon_hc_driver = {
+ 	/*
+ 	 * basic lifecycle operations
+ 	 */
+-	.reset			= ehci_init,
++	.reset			= ehci_setup,
+ 	.start			= ehci_run,
+ 	.stop			= ehci_stop,
+ 	.shutdown		= ehci_shutdown,
+@@ -150,12 +150,6 @@ static int ehci_octeon_drv_probe(struct platform_device *pdev)
+ #endif
+ 
+ 	ehci->caps = hcd->regs;
+-	ehci->regs = hcd->regs +
+-		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
+-	/* cache this readonly data; minimize chip reads */
+-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+-
+-	ehci_reset(ehci);
+ 
+ 	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
+ 	if (ret) {
+diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
+index 6e15fc87cf60..6133d93808dc 100644
+--- a/drivers/usb/host/ehci-omap.c
++++ b/drivers/usb/host/ehci-omap.c
+@@ -145,6 +145,56 @@ static void omap_ehci_soft_phy_reset(struct platform_device *pdev, u8 port)
+ 	}
+ }
+ 
++static int omap_ehci_init(struct usb_hcd *hcd)
++{
++	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
++	int			rc;
++	struct ehci_hcd_omap_platform_data	*pdata;
++
++	pdata = hcd->self.controller->platform_data;
++	if (pdata->phy_reset) {
++		if (gpio_is_valid(pdata->reset_gpio_port[0]))
++			gpio_request_one(pdata->reset_gpio_port[0],
++					 GPIOF_OUT_INIT_LOW, "USB1 PHY reset");
++
++		if (gpio_is_valid(pdata->reset_gpio_port[1]))
++			gpio_request_one(pdata->reset_gpio_port[1],
++					 GPIOF_OUT_INIT_LOW, "USB2 PHY reset");
++
++		/* Hold the PHY in RESET for enough time till DIR is high */
++		udelay(10);
++	}
++
++	/* Soft reset the PHY using PHY reset command over ULPI */
++	if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY)
++		omap_ehci_soft_phy_reset(pdev, 0);
++	if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY)
++		omap_ehci_soft_phy_reset(pdev, 1);
++
++	/* we know this is the memory we want, no need to ioremap again */
++	ehci->caps = hcd->regs;
++
++	rc = ehci_setup(hcd);
++
++	if (pdata->phy_reset) {
++		/* Hold the PHY in RESET for enough time till
++		 * PHY is settled and ready
++		 */
++		udelay(10);
++
++		if (gpio_is_valid(pdata->reset_gpio_port[0]))
++			gpio_set_value_cansleep(pdata->reset_gpio_port[0], 1);
++
++		if (gpio_is_valid(pdata->reset_gpio_port[1]))
++			gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1);
++	}
++
++	/* root ports should always stay powered */
++	ehci_port_power(ehci, 1);
++
++	return rc;
++}
++
+ static int omap_ehci_hub_control(
+ 	struct usb_hcd	*hcd,
+ 	u16		typeReq,
+@@ -219,7 +269,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
+ 	struct resource				*res;
+ 	struct usb_hcd				*hcd;
+ 	void __iomem				*regs;
+-	struct ehci_hcd				*omap_ehci;
+ 	int					ret = -ENODEV;
+ 	int					irq;
+ 	int					i;
+@@ -281,19 +330,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
+ 		}
+ 	}
+ 
+-	if (pdata->phy_reset) {
+-		if (gpio_is_valid(pdata->reset_gpio_port[0]))
+-			gpio_request_one(pdata->reset_gpio_port[0],
+-					 GPIOF_OUT_INIT_LOW, "USB1 PHY reset");
+-
+-		if (gpio_is_valid(pdata->reset_gpio_port[1]))
+-			gpio_request_one(pdata->reset_gpio_port[1],
+-					 GPIOF_OUT_INIT_LOW, "USB2 PHY reset");
+-
+-		/* Hold the PHY in RESET for enough time till DIR is high */
+-		udelay(10);
+-	}
+-
+ 	pm_runtime_enable(dev);
+ 	pm_runtime_get_sync(dev);
+ 
+@@ -309,50 +345,12 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
+ 	ehci_write(regs, EHCI_INSNREG04,
+ 				EHCI_INSNREG04_DISABLE_UNSUSPEND);
+ 
+-	/* Soft reset the PHY using PHY reset command over ULPI */
+-	if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY)
+-		omap_ehci_soft_phy_reset(pdev, 0);
+-	if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY)
+-		omap_ehci_soft_phy_reset(pdev, 1);
+-
+-	omap_ehci = hcd_to_ehci(hcd);
+-	omap_ehci->sbrn = 0x20;
+-
+-	/* we know this is the memory we want, no need to ioremap again */
+-	omap_ehci->caps = hcd->regs;
+-	omap_ehci->regs = hcd->regs
+-		+ HC_LENGTH(ehci, readl(&omap_ehci->caps->hc_capbase));
+-
+-	dbg_hcs_params(omap_ehci, "reset");
+-	dbg_hcc_params(omap_ehci, "reset");
+-
+-	/* cache this readonly data; minimize chip reads */
+-	omap_ehci->hcs_params = readl(&omap_ehci->caps->hcs_params);
+-
+-	ehci_reset(omap_ehci);
+-
+-	if (pdata->phy_reset) {
+-		/* Hold the PHY in RESET for enough time till
+-		 * PHY is settled and ready
+-		 */
+-		udelay(10);
+-
+-		if (gpio_is_valid(pdata->reset_gpio_port[0]))
+-			gpio_set_value_cansleep(pdata->reset_gpio_port[0], 1);
+-
+-		if (gpio_is_valid(pdata->reset_gpio_port[1]))
+-			gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1);
+-	}
+-
+ 	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
+ 	if (ret) {
+ 		dev_err(dev, "failed to add hcd with err %d\n", ret);
+ 		goto err_pm_runtime;
+ 	}
+ 
+-	/* root ports should always stay powered */
+-	ehci_port_power(omap_ehci, 1);
+-
+ 	/* get clocks */
+ 	utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk");
+ 	if (IS_ERR(utmi_p1_fck)) {
+@@ -512,7 +510,7 @@ static const struct hc_driver ehci_omap_hc_driver = {
+ 	/*
+ 	 * basic lifecycle operations
+ 	 */
+-	.reset			= ehci_init,
++	.reset			= omap_ehci_init,
+ 	.start			= ehci_run,
+ 	.stop			= ehci_stop,
+ 	.shutdown		= ehci_shutdown,
+diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
+index 82de1073aa52..3e411230953b 100644
+--- a/drivers/usb/host/ehci-orion.c
++++ b/drivers/usb/host/ehci-orion.c
+@@ -106,21 +106,10 @@ static int ehci_orion_setup(struct usb_hcd *hcd)
+ 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ 	int retval;
+ 
+-	hcd->has_tt = 1;
+-
+-	retval = ehci_halt(ehci);
+-	if (retval)
+-		return retval;
+-
+-	/*
+-	 * data structure init
+-	 */
+-	retval = ehci_init(hcd);
++	retval = ehci_setup(ehci);
+ 	if (retval)
+ 		return retval;
+ 
+-	ehci_reset(ehci);
+-
+ 	ehci_port_power(ehci, 0);
+ 
+ 	return retval;
+@@ -261,11 +250,7 @@ static int __devinit ehci_orion_drv_probe(struct platform_device *pdev)
+ 
+ 	ehci = hcd_to_ehci(hcd);
+ 	ehci->caps = hcd->regs + 0x100;
+-	ehci->regs = hcd->regs + 0x100 +
+-		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
+-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+ 	hcd->has_tt = 1;
+-	ehci->sbrn = 0x20;
+ 
+ 	/*
+ 	 * (Re-)program MBUS remapping windows if we are asked to.
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index 6e767bce0605..21e5f963f331 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -54,6 +54,17 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 	u32			temp;
+ 	int			retval;
+ 
++	ehci->caps = hcd->regs;
++
++	/*
++	 * ehci_init() causes memory for DMA transfers to be
++	 * allocated.  Thus, any vendor-specific workarounds based on
++	 * limiting the type of memory used for DMA transfers must
++	 * happen before ehci_setup() is called.
++	 *
++	 * Most other workarounds can be done either before or after
++	 * init and reset; they are located here too.
++	 */
+ 	switch (pdev->vendor) {
+ 	case PCI_VENDOR_ID_TOSHIBA_2:
+ 		/* celleb's companion chip */
+@@ -66,20 +77,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ #endif
+ 		}
+ 		break;
+-	}
+-
+-	ehci->caps = hcd->regs;
+-	ehci->regs = hcd->regs +
+-		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
+-
+-	dbg_hcs_params(ehci, "reset");
+-	dbg_hcc_params(ehci, "reset");
+-
+-        /* ehci_init() causes memory for DMA transfers to be
+-         * allocated.  Thus, any vendor-specific workarounds based on
+-         * limiting the type of memory used for DMA transfers must
+-         * happen before ehci_init() is called. */
+-	switch (pdev->vendor) {
+ 	case PCI_VENDOR_ID_NVIDIA:
+ 		/* NVidia reports that certain chips don't handle
+ 		 * QH, ITD, or SITD addresses above 2GB.  (But TD,
+@@ -95,61 +92,28 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 				ehci_warn(ehci, "can't enable NVidia "
+ 					"workaround for >2GB RAM\n");
+ 			break;
+-		}
+-		break;
+-	}
+ 
+-	/* cache this readonly data; minimize chip reads */
+-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+-
+-	retval = ehci_halt(ehci);
+-	if (retval)
+-		return retval;
+-
+-	if ((pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == 0x7808) ||
+-	    (pdev->vendor == PCI_VENDOR_ID_ATI && pdev->device == 0x4396)) {
+-		/* EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may
+-		 * read/write memory space which does not belong to it when
+-		 * there is NULL pointer with T-bit set to 1 in the frame list
+-		 * table. To avoid the issue, the frame list link pointer
+-		 * should always contain a valid pointer to a inactive qh.
++		/* Some NForce2 chips have problems with selective suspend;
++		 * fixed in newer silicon.
+ 		 */
+-		ehci->use_dummy_qh = 1;
+-		ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI "
+-				"dummy qh workaround\n");
+-	}
+-
+-	/* data structure init */
+-	retval = ehci_init(hcd);
+-	if (retval)
+-		return retval;
+-
+-	switch (pdev->vendor) {
+-	case PCI_VENDOR_ID_NEC:
+-		ehci->need_io_watchdog = 0;
++		case 0x0068:
++			if (pdev->revision < 0xa4)
++				ehci->no_selective_suspend = 1;
++			break;
++		}
+ 		break;
+ 	case PCI_VENDOR_ID_INTEL:
+-		ehci->need_io_watchdog = 0;
+ 		ehci->fs_i_thresh = 1;
+ 		if (pdev->device == 0x27cc) {
+ 			ehci->broken_periodic = 1;
+ 			ehci_info(ehci, "using broken periodic workaround\n");
+ 		}
+-		if (pdev->device == 0x0806 || pdev->device == 0x0811
+-				|| pdev->device == 0x0829) {
+-			ehci_info(ehci, "disable lpm for langwell/penwell\n");
+-			ehci->has_lpm = 0;
+-		}
+-		if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB) {
++		if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB)
+ 			hcd->has_tt = 1;
+-			tdi_reset(ehci);
+-		}
+ 		break;
+ 	case PCI_VENDOR_ID_TDI:
+-		if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
++		if (pdev->device == PCI_DEVICE_ID_TDI_EHCI)
+ 			hcd->has_tt = 1;
+-			tdi_reset(ehci);
+-		}
+ 		break;
+ 	case PCI_VENDOR_ID_AMD:
+ 		/* AMD PLL quirk */
+@@ -161,28 +125,17 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 			retval = -EIO;
+ 			goto done;
+ 		}
+-		break;
+-	case PCI_VENDOR_ID_NVIDIA:
+-		switch (pdev->device) {
+-		/* Some NForce2 chips have problems with selective suspend;
+-		 * fixed in newer silicon.
+-		 */
+-		case 0x0068:
+-			if (pdev->revision < 0xa4)
+-				ehci->no_selective_suspend = 1;
+-			break;
+ 
+-		/* MCP89 chips on the MacBookAir3,1 give EPROTO when
+-		 * fetching device descriptors unless LPM is disabled.
+-		 * There are also intermittent problems enumerating
+-		 * devices with PPCD enabled.
++		/*
++		 * EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may
++		 * read/write memory space which does not belong to it when
++		 * there is NULL pointer with T-bit set to 1 in the frame list
++		 * table. To avoid the issue, the frame list link pointer
++		 * should always contain a valid pointer to a inactive qh.
+ 		 */
+-		case 0x0d9d:
+-			ehci_info(ehci, "disable lpm/ppcd for nvidia mcp89");
+-			ehci->has_lpm = 0;
+-			ehci->has_ppcd = 0;
+-			ehci->command &= ~CMD_PPCEE;
+-			break;
++		if (pdev->device == 0x7808) {
++			ehci->use_dummy_qh = 1;
++			ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI dummy qh workaround\n");
+ 		}
+ 		break;
+ 	case PCI_VENDOR_ID_VIA:
+@@ -203,6 +156,18 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 		/* AMD PLL quirk */
+ 		if (usb_amd_find_chipset_info())
+ 			ehci->amd_pll_fix = 1;
++
++		/*
++		 * EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may
++		 * read/write memory space which does not belong to it when
++		 * there is NULL pointer with T-bit set to 1 in the frame list
++		 * table. To avoid the issue, the frame list link pointer
++		 * should always contain a valid pointer to a inactive qh.
++		 */
++		if (pdev->device == 0x4396) {
++			ehci->use_dummy_qh = 1;
++			ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI dummy qh workaround\n");
++		}
+ 		/* SB600 and old version of SB700 have a bug in EHCI controller,
+ 		 * which causes usb devices lose response in some cases.
+ 		 */
+@@ -231,6 +196,40 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 		break;
+ 	}
+ 
++	retval = ehci_setup(hcd);
++	if (retval)
++		return retval;
++
++	/* These workarounds need to be applied after ehci_setup() */
++	switch (pdev->vendor) {
++	case PCI_VENDOR_ID_NEC:
++		ehci->need_io_watchdog = 0;
++		break;
++	case PCI_VENDOR_ID_INTEL:
++		ehci->need_io_watchdog = 0;
++		if (pdev->device == 0x0806 || pdev->device == 0x0811
++				|| pdev->device == 0x0829) {
++			ehci_info(ehci, "disable lpm for langwell/penwell\n");
++			ehci->has_lpm = 0;
++		}
++		break;
++	case PCI_VENDOR_ID_NVIDIA:
++		switch (pdev->device) {
++		/* MCP89 chips on the MacBookAir3,1 give EPROTO when
++		 * fetching device descriptors unless LPM is disabled.
++		 * There are also intermittent problems enumerating
++		 * devices with PPCD enabled.
++		 */
++		case 0x0d9d:
++			ehci_info(ehci, "disable lpm/ppcd for nvidia mcp89");
++			ehci->has_lpm = 0;
++			ehci->has_ppcd = 0;
++			ehci->command &= ~CMD_PPCEE;
++			break;
++		}
++		break;
++	}
++
+ 	/* optional debug port, normally in the first BAR */
+ 	temp = pci_find_capability(pdev, 0x0a);
+ 	if (temp) {
+@@ -238,7 +237,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 		temp >>= 16;
+ 		if ((temp & (3 << 13)) == (1 << 13)) {
+ 			temp &= 0x1fff;
+-			ehci->debug = ehci_to_hcd(ehci)->regs + temp;
++			ehci->debug = hcd->regs + temp;
+ 			temp = ehci_readl(ehci, &ehci->debug->control);
+ 			ehci_info(ehci, "debug port %d%s\n",
+ 				HCS_DEBUG_PORT(ehci->hcs_params),
+@@ -250,8 +249,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 		}
+ 	}
+ 
+-	ehci_reset(ehci);
+-
+ 	/* at least the Genesys GL880S needs fixup here */
+ 	temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params);
+ 	temp &= 0x0f;
+@@ -275,10 +272,11 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 	}
+ 
+ 	/* Serial Bus Release Number is at PCI 0x60 offset */
+-	pci_read_config_byte(pdev, 0x60, &ehci->sbrn);
+ 	if (pdev->vendor == PCI_VENDOR_ID_STMICRO
+ 	    && pdev->device == PCI_DEVICE_ID_STMICRO_USB_HOST)
+-		ehci->sbrn = 0x20; /* ConneXT has no sbrn register */
++		;	/* ConneXT has no sbrn register */
++	else
++		pci_read_config_byte(pdev, 0x60, &ehci->sbrn);
+ 
+ 	/* Keep this around for a while just in case some EHCI
+ 	 * implementation uses legacy PCI PM support.  This test
+diff --git a/drivers/usb/host/ehci-pmcmsp.c b/drivers/usb/host/ehci-pmcmsp.c
+index e8d54de44acc..087aee2a904f 100644
+--- a/drivers/usb/host/ehci-pmcmsp.c
++++ b/drivers/usb/host/ehci-pmcmsp.c
+@@ -78,27 +78,14 @@ static int ehci_msp_setup(struct usb_hcd *hcd)
+ {
+ 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
+ 	int			retval;
++
+ 	ehci->big_endian_mmio = 1;
+ 	ehci->big_endian_desc = 1;
+ 
+ 	ehci->caps = hcd->regs;
+-	ehci->regs = hcd->regs +
+-		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
+-	dbg_hcs_params(ehci, "reset");
+-	dbg_hcc_params(ehci, "reset");
+-
+-	/* cache this readonly data; minimize chip reads */
+-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+ 	hcd->has_tt = 1;
+ 
+-	retval = ehci_halt(ehci);
+-	if (retval)
+-		return retval;
+-
+-	ehci_reset(ehci);
+-
+-	/* data structure init */
+-	retval = ehci_init(hcd);
++	retval = ehci_setup(hcd);
+ 	if (retval)
+ 		return retval;
+ 
+diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c
+index 41d11fe14252..bbbe89dfd886 100644
+--- a/drivers/usb/host/ehci-ppc-of.c
++++ b/drivers/usb/host/ehci-ppc-of.c
+@@ -17,24 +17,6 @@
+ #include 
+ #include 
+ 
+-/* called during probe() after chip reset completes */
+-static int ehci_ppc_of_setup(struct usb_hcd *hcd)
+-{
+-	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
+-	int		retval;
+-
+-	retval = ehci_halt(ehci);
+-	if (retval)
+-		return retval;
+-
+-	retval = ehci_init(hcd);
+-	if (retval)
+-		return retval;
+-
+-	ehci->sbrn = 0x20;
+-	return ehci_reset(ehci);
+-}
+-
+ 
+ static const struct hc_driver ehci_ppc_of_hc_driver = {
+ 	.description		= hcd_name,
+@@ -50,7 +32,7 @@ static const struct hc_driver ehci_ppc_of_hc_driver = {
+ 	/*
+ 	 * basic lifecycle operations
+ 	 */
+-	.reset			= ehci_ppc_of_setup,
++	.reset			= ehci_setup,
+ 	.start			= ehci_run,
+ 	.stop			= ehci_stop,
+ 	.shutdown		= ehci_shutdown,
+@@ -178,11 +160,6 @@ static int __devinit ehci_hcd_ppc_of_probe(struct platform_device *op)
+ 		ehci->big_endian_desc = 1;
+ 
+ 	ehci->caps = hcd->regs;
+-	ehci->regs = hcd->regs +
+-		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
+-
+-	/* cache this readonly data; minimize chip reads */
+-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+ 
+ 	if (of_device_is_compatible(dn, "ibm,usb-ehci-440epx")) {
+ 		rv = ppc44x_enable_bmt(dn);
+diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
+index a20e496eb479..45a356e9f138 100644
+--- a/drivers/usb/host/ehci-ps3.c
++++ b/drivers/usb/host/ehci-ps3.c
+@@ -55,28 +55,12 @@ static int ps3_ehci_hc_reset(struct usb_hcd *hcd)
+ 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ 
+ 	ehci->big_endian_mmio = 1;
+-
+ 	ehci->caps = hcd->regs;
+-	ehci->regs = hcd->regs + HC_LENGTH(ehci, ehci_readl(ehci,
+-		&ehci->caps->hc_capbase));
+-
+-	dbg_hcs_params(ehci, "reset");
+-	dbg_hcc_params(ehci, "reset");
+-
+-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+-
+-	result = ehci_halt(ehci);
+ 
++	result = ehci_setup(hcd);
+ 	if (result)
+ 		return result;
+ 
+-	result = ehci_init(hcd);
+-
+-	if (result)
+-		return result;
+-
+-	ehci_reset(ehci);
+-
+ 	ps3_ehci_setup_insnreg(ehci);
+ 
+ 	return result;
+diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c
+index c7e0936d4a7c..13c179fb2ee2 100644
+--- a/drivers/usb/host/ehci-s5p.c
++++ b/drivers/usb/host/ehci-s5p.c
+@@ -40,7 +40,7 @@ static const struct hc_driver s5p_ehci_hc_driver = {
+ 	.irq			= ehci_irq,
+ 	.flags			= HCD_MEMORY | HCD_USB2,
+ 
+-	.reset			= ehci_init,
++	.reset			= ehci_setup,
+ 	.start			= ehci_run,
+ 	.stop			= ehci_stop,
+ 	.shutdown		= ehci_shutdown,
+@@ -134,20 +134,10 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev)
+ 
+ 	ehci = hcd_to_ehci(hcd);
+ 	ehci->caps = hcd->regs;
+-	ehci->regs = hcd->regs +
+-		HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
+ 
+ 	/* DMA burst Enable */
+ 	writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs));
+ 
+-	dbg_hcs_params(ehci, "reset");
+-	dbg_hcc_params(ehci, "reset");
+-
+-	/* cache this readonly data; minimize chip reads */
+-	ehci->hcs_params = readl(&ehci->caps->hcs_params);
+-
+-	ehci_reset(ehci);
+-
+ 	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
+ 	if (err) {
+ 		dev_err(&pdev->dev, "Failed to add USB HCD\n");
+diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c
+index e7cb3925abf8..b3f1e3650da0 100644
+--- a/drivers/usb/host/ehci-sh.c
++++ b/drivers/usb/host/ehci-sh.c
+@@ -24,25 +24,11 @@ static int ehci_sh_reset(struct usb_hcd *hcd)
+ 	int ret;
+ 
+ 	ehci->caps = hcd->regs;
+-	ehci->regs = hcd->regs + HC_LENGTH(ehci, ehci_readl(ehci,
+-		&ehci->caps->hc_capbase));
+ 
+-	dbg_hcs_params(ehci, "reset");
+-	dbg_hcc_params(ehci, "reset");
+-
+-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+-
+-	ret = ehci_halt(ehci);
+-	if (unlikely(ret))
+-		return ret;
+-
+-	ret = ehci_init(hcd);
++	ret = ehci_setup(hcd);
+ 	if (unlikely(ret))
+ 		return ret;
+ 
+-	ehci->sbrn = 0x20;
+-
+-	ehci_reset(ehci);
+ 	ehci_port_power(ehci, 0);
+ 
+ 	return ret;
+diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c
+index 7ed533e6cca8..c718a065e154 100644
+--- a/drivers/usb/host/ehci-spear.c
++++ b/drivers/usb/host/ehci-spear.c
+@@ -41,19 +41,11 @@ static int ehci_spear_setup(struct usb_hcd *hcd)
+ 
+ 	/* registers start at offset 0x0 */
+ 	ehci->caps = hcd->regs;
+-	ehci->regs = hcd->regs + HC_LENGTH(ehci, ehci_readl(ehci,
+-				&ehci->caps->hc_capbase));
+-	/* cache this readonly data; minimize chip reads */
+-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+-	retval = ehci_halt(ehci);
+-	if (retval)
+-		return retval;
+ 
+-	retval = ehci_init(hcd);
++	retval = ehci_setup(hcd);
+ 	if (retval)
+ 		return retval;
+ 
+-	ehci_reset(ehci);
+ 	ehci_port_power(ehci, 0);
+ 
+ 	return retval;
+diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
+index 477ecfa05154..f7f3ce3275b8 100644
+--- a/drivers/usb/host/ehci-tegra.c
++++ b/drivers/usb/host/ehci-tegra.c
+@@ -281,30 +281,14 @@ static int tegra_ehci_setup(struct usb_hcd *hcd)
+ 
+ 	/* EHCI registers start at offset 0x100 */
+ 	ehci->caps = hcd->regs + 0x100;
+-	ehci->regs = hcd->regs + 0x100 +
+-		HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
+-
+-	dbg_hcs_params(ehci, "reset");
+-	dbg_hcc_params(ehci, "reset");
+-
+-	/* cache this readonly data; minimize chip reads */
+-	ehci->hcs_params = readl(&ehci->caps->hcs_params);
+ 
+ 	/* switch to host mode */
+ 	hcd->has_tt = 1;
+-	ehci_reset(ehci);
+ 
+-	retval = ehci_halt(ehci);
++	retval = ehci_setup(ehci);
+ 	if (retval)
+ 		return retval;
+ 
+-	/* data structure init */
+-	retval = ehci_init(hcd);
+-	if (retval)
+-		return retval;
+-
+-	ehci->sbrn = 0x20;
+-
+ 	ehci_port_power(ehci, 1);
+ 	return retval;
+ }
+diff --git a/drivers/usb/host/ehci-vt8500.c b/drivers/usb/host/ehci-vt8500.c
+index c1eda73916cd..4d147c4e33f5 100644
+--- a/drivers/usb/host/ehci-vt8500.c
++++ b/drivers/usb/host/ehci-vt8500.c
+@@ -48,7 +48,7 @@ static const struct hc_driver vt8500_ehci_hc_driver = {
+ 	/*
+ 	 * basic lifecycle operations
+ 	 */
+-	.reset			= ehci_init,
++	.reset			= ehci_setup,
+ 	.start			= ehci_run,
+ 	.stop			= ehci_stop,
+ 	.shutdown		= ehci_shutdown,
+@@ -121,18 +121,6 @@ static int vt8500_ehci_drv_probe(struct platform_device *pdev)
+ 
+ 	ehci = hcd_to_ehci(hcd);
+ 	ehci->caps = hcd->regs;
+-	ehci->regs = hcd->regs +
+-		HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
+-
+-	dbg_hcs_params(ehci, "reset");
+-	dbg_hcc_params(ehci, "reset");
+-
+-	/* cache this readonly data; minimize chip reads */
+-	ehci->hcs_params = readl(&ehci->caps->hcs_params);
+-
+-	ehci_port_power(ehci, 1);
+-
+-	ehci_reset(ehci);
+ 
+ 	ret = usb_add_hcd(hcd, pdev->resource[1].start,
+ 			  IRQF_SHARED);
+diff --git a/drivers/usb/host/ehci-w90x900.c b/drivers/usb/host/ehci-w90x900.c
+index 3d2e26cbb34c..ec598082c14b 100644
+--- a/drivers/usb/host/ehci-w90x900.c
++++ b/drivers/usb/host/ehci-w90x900.c
+@@ -71,21 +71,14 @@ static int __devinit usb_w90x900_probe(const struct hc_driver *driver,
+ 	val |= ENPHY;
+ 	__raw_writel(val, ehci->regs+PHY1_CTR);
+ 
+-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+-	ehci->sbrn = 0x20;
+-
+ 	irq = platform_get_irq(pdev, 0);
+ 	if (irq < 0)
+ 		goto err4;
+ 
+-	ehci_reset(ehci);
+-
+ 	retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
+ 	if (retval != 0)
+ 		goto err4;
+ 
+-	ehci_writel(ehci, 1, &ehci->regs->configured_flag);
+-
+ 	return retval;
+ err4:
+ 	iounmap(hcd->regs);
+@@ -120,7 +113,7 @@ static const struct hc_driver ehci_w90x900_hc_driver = {
+ 	/*
+ 	 * basic lifecycle operations
+ 	 */
+-	.reset = ehci_init,
++	.reset = ehci_setup,
+ 	.start = ehci_run,
+ 
+ 	.stop = ehci_stop,
+diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c
+index e9713d589e30..39f24fa37ebe 100644
+--- a/drivers/usb/host/ehci-xilinx-of.c
++++ b/drivers/usb/host/ehci-xilinx-of.c
+@@ -31,30 +31,6 @@
+ #include 
+ #include 
+ 
+-/**
+- * ehci_xilinx_of_setup - Initialize the device for ehci_reset()
+- * @hcd:	Pointer to the usb_hcd device to which the host controller bound
+- *
+- * called during probe() after chip reset completes.
+- */
+-static int ehci_xilinx_of_setup(struct usb_hcd *hcd)
+-{
+-	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
+-	int		retval;
+-
+-	retval = ehci_halt(ehci);
+-	if (retval)
+-		return retval;
+-
+-	retval = ehci_init(hcd);
+-	if (retval)
+-		return retval;
+-
+-	ehci->sbrn = 0x20;
+-
+-	return ehci_reset(ehci);
+-}
+-
+ /**
+  * ehci_xilinx_port_handed_over - hand the port out if failed to enable it
+  * @hcd:	Pointer to the usb_hcd device to which the host controller bound
+@@ -107,7 +83,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = {
+ 	/*
+ 	 * basic lifecycle operations
+ 	 */
+-	.reset			= ehci_xilinx_of_setup,
++	.reset			= ehci_setup,
+ 	.start			= ehci_run,
+ 	.stop			= ehci_stop,
+ 	.shutdown		= ehci_shutdown,
+@@ -219,11 +195,6 @@ static int __devinit ehci_hcd_xilinx_of_probe(struct platform_device *op)
+ 	/* Debug registers are at the first 0x100 region
+ 	 */
+ 	ehci->caps = hcd->regs + 0x100;
+-	ehci->regs = hcd->regs + 0x100 +
+-		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
+-
+-	/* cache this readonly data; minimize chip reads */
+-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+ 
+ 	rv = usb_add_hcd(hcd, irq, 0);
+ 	if (rv == 0)
+diff --git a/drivers/usb/host/ehci-xls.c b/drivers/usb/host/ehci-xls.c
+index 72f08196f8cd..99c353a85ae4 100644
+--- a/drivers/usb/host/ehci-xls.c
++++ b/drivers/usb/host/ehci-xls.c
+@@ -14,30 +14,11 @@
+ 
+ static int ehci_xls_setup(struct usb_hcd *hcd)
+ {
+-	int	retval;
+ 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ 
+ 	ehci->caps = hcd->regs;
+-	ehci->regs = hcd->regs +
+-		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
+-	dbg_hcs_params(ehci, "reset");
+-	dbg_hcc_params(ehci, "reset");
+ 
+-	/* cache this readonly data; minimize chip reads */
+-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+-
+-	retval = ehci_halt(ehci);
+-	if (retval)
+-		return retval;
+-
+-	/* data structure init */
+-	retval = ehci_init(hcd);
+-	if (retval)
+-		return retval;
+-
+-	ehci_reset(ehci);
+-
+-	return retval;
++	return ehci_setup(ehci);
+ }
+ 
+ int ehci_xls_probe_internal(const struct hc_driver *driver,

commit c5cf9212a368d88fe1e25797699b167f6daa64a5
+Author: Alan Stern 
+Date:   Thu Jun 28 11:19:02 2012 -0400
+
+    EHCI: centralize controller suspend/resume
+    
+    This patch (as1563) removes a lot of duplicated code by moving the
+    EHCI controller suspend/resume routines into the core driver, where
+    the various platform drivers can invoke them as needed.
+    
+    Not only does this simplify these platform drivers, this also makes it
+    easier for other platform drivers to add suspend/resume support in the
+    future.
+    
+    Note: The patch does not touch the ehci-fsl.c file, because its
+    approach to suspend and resume is so different from all the others.
+    It will have to be handled specially by its maintainer.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
+index bf7441afed16..182d39565906 100644
+--- a/drivers/usb/host/ehci-au1xxx.c
++++ b/drivers/usb/host/ehci-au1xxx.c
+@@ -158,28 +158,10 @@ static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
+ static int ehci_hcd_au1xxx_drv_suspend(struct device *dev)
+ {
+ 	struct usb_hcd *hcd = dev_get_drvdata(dev);
+-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+-	unsigned long flags;
+-	int rc = 0;
+-
+-	if (time_before(jiffies, ehci->next_statechange))
+-		msleep(10);
+-
+-	/* Root hub was already suspended. Disable irq emission and
+-	 * mark HW unaccessible.  The PM and USB cores make sure that
+-	 * the root hub is either suspended or stopped.
+-	 */
+-	ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev));
+-	spin_lock_irqsave(&ehci->lock, flags);
+-	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+-	(void)ehci_readl(ehci, &ehci->regs->intr_enable);
+-
+-	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+-	spin_unlock_irqrestore(&ehci->lock, flags);
+-
+-	// could save FLADJ in case of Vaux power loss
+-	// ... we'd only use it to handle clock skew
++	bool do_wakeup = device_may_wakeup(dev);
++	int rc;
+ 
++	rc = ehci_suspend(hcd, do_wakeup);
+ 	alchemy_usb_control(ALCHEMY_USB_EHCI0, 0);
+ 
+ 	return rc;
+@@ -188,56 +170,9 @@ static int ehci_hcd_au1xxx_drv_suspend(struct device *dev)
+ static int ehci_hcd_au1xxx_drv_resume(struct device *dev)
+ {
+ 	struct usb_hcd *hcd = dev_get_drvdata(dev);
+-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ 
+ 	alchemy_usb_control(ALCHEMY_USB_EHCI0, 1);
+-
+-	// maybe restore FLADJ
+-
+-	if (time_before(jiffies, ehci->next_statechange))
+-		msleep(100);
+-
+-	/* Mark hardware accessible again as we are out of D3 state by now */
+-	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+-
+-	/* If CF is still set, we maintained PCI Vaux power.
+-	 * Just undo the effect of ehci_pci_suspend().
+-	 */
+-	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
+-		int	mask = INTR_MASK;
+-
+-		ehci_prepare_ports_for_controller_resume(ehci);
+-		if (!hcd->self.root_hub->do_remote_wakeup)
+-			mask &= ~STS_PCD;
+-		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+-		ehci_readl(ehci, &ehci->regs->intr_enable);
+-		return 0;
+-	}
+-
+-	ehci_dbg(ehci, "lost power, restarting\n");
+-	usb_root_hub_lost_power(hcd->self.root_hub);
+-
+-	/* Else reset, to cope with power loss or flush-to-storage
+-	 * style "resume" having let BIOS kick in during reboot.
+-	 */
+-	(void) ehci_halt(ehci);
+-	(void) ehci_reset(ehci);
+-
+-	/* emptying the schedule aborts any urbs */
+-	spin_lock_irq(&ehci->lock);
+-	if (ehci->reclaim)
+-		end_unlink_async(ehci);
+-	ehci_work(ehci);
+-	spin_unlock_irq(&ehci->lock);
+-
+-	ehci_writel(ehci, ehci->command, &ehci->regs->command);
+-	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
+-	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
+-
+-	/* here we "know" root ports should always stay powered */
+-	ehci_port_power(ehci, 1);
+-
+-	ehci->rh_state = EHCI_RH_SUSPENDED;
++	ehci_resume(hcd, false);
+ 
+ 	return 0;
+ }
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index c49fc1e7895d..e6823a0cf642 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1242,6 +1242,95 @@ static int ehci_get_frame (struct usb_hcd *hcd)
+ }
+ 
+ /*-------------------------------------------------------------------------*/
++
++#ifdef	CONFIG_PM
++
++/* suspend/resume, section 4.3 */
++
++/* These routines handle the generic parts of controller suspend/resume */
++
++static int __maybe_unused ehci_suspend(struct usb_hcd *hcd, bool do_wakeup)
++{
++	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
++
++	if (time_before(jiffies, ehci->next_statechange))
++		msleep(10);
++
++	/*
++	 * Root hub was already suspended.  Disable IRQ emission and
++	 * mark HW unaccessible.  The PM and USB cores make sure that
++	 * the root hub is either suspended or stopped.
++	 */
++	ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup);
++
++	spin_lock_irq(&ehci->lock);
++	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
++	(void) ehci_readl(ehci, &ehci->regs->intr_enable);
++
++	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
++	spin_unlock_irq(&ehci->lock);
++
++	return 0;
++}
++
++/* Returns 0 if power was preserved, 1 if power was lost */
++static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated)
++{
++	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
++
++	if (time_before(jiffies, ehci->next_statechange))
++		msleep(100);
++
++	/* Mark hardware accessible again as we are back to full power by now */
++	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
++
++	/*
++	 * If CF is still set and we aren't resuming from hibernation
++	 * then we maintained suspend power.
++	 * Just undo the effect of ehci_suspend().
++	 */
++	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF &&
++			!hibernated) {
++		int	mask = INTR_MASK;
++
++		ehci_prepare_ports_for_controller_resume(ehci);
++		if (!hcd->self.root_hub->do_remote_wakeup)
++			mask &= ~STS_PCD;
++		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
++		ehci_readl(ehci, &ehci->regs->intr_enable);
++		return 0;
++	}
++
++	/*
++	 * Else reset, to cope with power loss or resume from hibernation
++	 * having let the firmware kick in during reboot.
++	 */
++	usb_root_hub_lost_power(hcd->self.root_hub);
++	(void) ehci_halt(ehci);
++	(void) ehci_reset(ehci);
++
++	/* emptying the schedule aborts any urbs */
++	spin_lock_irq(&ehci->lock);
++	if (ehci->reclaim)
++		end_unlink_async(ehci);
++	ehci_work(ehci);
++	spin_unlock_irq(&ehci->lock);
++
++	ehci_writel(ehci, ehci->command, &ehci->regs->command);
++	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
++	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
++
++	/* here we "know" root ports should always stay powered */
++	ehci_port_power(ehci, 1);
++
++	ehci->rh_state = EHCI_RH_SUSPENDED;
++	return 1;
++}
++
++#endif
++
++/*-------------------------------------------------------------------------*/
++
+ /*
+  * The EHCI in ChipIdea HDRC cannot be a separate module or device,
+  * because its registers (and irq) are shared between host/gadget/otg
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index db05e358677a..b3e2d66e95bb 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -107,7 +107,7 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
+ 	ehci->owned_ports = 0;
+ }
+ 
+-static int __maybe_unused ehci_port_change(struct ehci_hcd *ehci)
++static int ehci_port_change(struct ehci_hcd *ehci)
+ {
+ 	int i = HCS_N_PORTS(ehci->hcs_params);
+ 
+@@ -128,7 +128,7 @@ static int __maybe_unused ehci_port_change(struct ehci_hcd *ehci)
+ 	return 0;
+ }
+ 
+-static __maybe_unused void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
++static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
+ 		bool suspending, bool do_wakeup)
+ {
+ 	int		port;
+diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
+index 6b4ffb598db1..17dd9e94001e 100644
+--- a/drivers/usb/host/ehci-msm.c
++++ b/drivers/usb/host/ehci-msm.c
+@@ -198,24 +198,11 @@ static int __devexit ehci_msm_remove(struct platform_device *pdev)
+ static int ehci_msm_pm_suspend(struct device *dev)
+ {
+ 	struct usb_hcd *hcd = dev_get_drvdata(dev);
+-	bool wakeup = device_may_wakeup(dev);
++	bool do_wakeup = device_may_wakeup(dev);
+ 
+ 	dev_dbg(dev, "ehci-msm PM suspend\n");
+ 
+-	/*
+-	 * EHCI helper function has also the same check before manipulating
+-	 * port wakeup flags.  We do check here the same condition before
+-	 * calling the same helper function to avoid bringing hardware
+-	 * from Low power mode when there is no need for adjusting port
+-	 * wakeup flags.
+-	 */
+-	if (hcd->self.root_hub->do_remote_wakeup && !wakeup) {
+-		pm_runtime_resume(dev);
+-		ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd),
+-				wakeup);
+-	}
+-
+-	return 0;
++	return ehci_suspend(hcd, do_wakeup);
+ }
+ 
+ static int ehci_msm_pm_resume(struct device *dev)
+@@ -223,7 +210,7 @@ static int ehci_msm_pm_resume(struct device *dev)
+ 	struct usb_hcd *hcd = dev_get_drvdata(dev);
+ 
+ 	dev_dbg(dev, "ehci-msm PM resume\n");
+-	ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd));
++	ehci_resume(hcd, false);
+ 
+ 	return 0;
+ }
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index 123481793a47..6e767bce0605 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -331,29 +331,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 
+ static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+ {
+-	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
+-	unsigned long		flags;
+-	int			rc = 0;
+-
+-	if (time_before(jiffies, ehci->next_statechange))
+-		msleep(10);
+-
+-	/* Root hub was already suspended. Disable irq emission and
+-	 * mark HW unaccessible.  The PM and USB cores make sure that
+-	 * the root hub is either suspended or stopped.
+-	 */
+-	ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup);
+-	spin_lock_irqsave (&ehci->lock, flags);
+-	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+-	(void)ehci_readl(ehci, &ehci->regs->intr_enable);
+-
+-	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+-	spin_unlock_irqrestore (&ehci->lock, flags);
+-
+-	// could save FLADJ in case of Vaux power loss
+-	// ... we'd only use it to handle clock skew
+-
+-	return rc;
++	return ehci_suspend(hcd, do_wakeup);
+ }
+ 
+ static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev)
+@@ -402,54 +380,8 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)
+ 	if (usb_is_intel_switchable_ehci(pdev))
+ 		ehci_enable_xhci_companion();
+ 
+-	// maybe restore FLADJ
+-
+-	if (time_before(jiffies, ehci->next_statechange))
+-		msleep(100);
+-
+-	/* Mark hardware accessible again as we are out of D3 state by now */
+-	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+-
+-	/* If CF is still set and we aren't resuming from hibernation
+-	 * then we maintained PCI Vaux power.
+-	 * Just undo the effect of ehci_pci_suspend().
+-	 */
+-	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF &&
+-				!hibernated) {
+-		int	mask = INTR_MASK;
+-
+-		ehci_prepare_ports_for_controller_resume(ehci);
+-		if (!hcd->self.root_hub->do_remote_wakeup)
+-			mask &= ~STS_PCD;
+-		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+-		ehci_readl(ehci, &ehci->regs->intr_enable);
+-		return 0;
+-	}
+-
+-	usb_root_hub_lost_power(hcd->self.root_hub);
+-
+-	/* Else reset, to cope with power loss or flush-to-storage
+-	 * style "resume" having let BIOS kick in during reboot.
+-	 */
+-	(void) ehci_halt(ehci);
+-	(void) ehci_reset(ehci);
+-	(void) ehci_pci_reinit(ehci, pdev);
+-
+-	/* emptying the schedule aborts any urbs */
+-	spin_lock_irq(&ehci->lock);
+-	if (ehci->reclaim)
+-		end_unlink_async(ehci);
+-	ehci_work(ehci);
+-	spin_unlock_irq(&ehci->lock);
+-
+-	ehci_writel(ehci, ehci->command, &ehci->regs->command);
+-	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
+-	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
+-
+-	/* here we "know" root ports should always stay powered */
+-	ehci_port_power(ehci, 1);
+-
+-	ehci->rh_state = EHCI_RH_SUSPENDED;
++	if (ehci_resume(hcd, hibernated) != 0)
++		(void) ehci_pci_reinit(ehci, pdev);
+ 	return 0;
+ }
+ #endif
+diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
+index dfe881a34ae2..4b1d896d5a22 100644
+--- a/drivers/usb/host/ehci-platform.c
++++ b/drivers/usb/host/ehci-platform.c
+@@ -153,17 +153,16 @@ static int __devexit ehci_platform_remove(struct platform_device *dev)
+ static int ehci_platform_suspend(struct device *dev)
+ {
+ 	struct usb_hcd *hcd = dev_get_drvdata(dev);
+-	bool wakeup = device_may_wakeup(dev);
++	bool do_wakeup = device_may_wakeup(dev);
+ 
+-	ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd), wakeup);
+-	return 0;
++	return ehci_suspend(hcd, do_wakeup);
+ }
+ 
+ static int ehci_platform_resume(struct device *dev)
+ {
+ 	struct usb_hcd *hcd = dev_get_drvdata(dev);
+ 
+-	ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd));
++	ehci_resume(hcd, false);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c
+index 1e483f052ff7..c7e0936d4a7c 100644
+--- a/drivers/usb/host/ehci-s5p.c
++++ b/drivers/usb/host/ehci-s5p.c
+@@ -200,27 +200,12 @@ static int s5p_ehci_suspend(struct device *dev)
+ {
+ 	struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev);
+ 	struct usb_hcd *hcd = s5p_ehci->hcd;
+-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
++	bool do_wakeup = device_may_wakeup(dev);
+ 	struct platform_device *pdev = to_platform_device(dev);
+ 	struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
+-	unsigned long flags;
+-	int rc = 0;
++	int rc;
+ 
+-	if (time_before(jiffies, ehci->next_statechange))
+-		msleep(20);
+-
+-	/*
+-	 * Root hub was already suspended. Disable irq emission and
+-	 * mark HW unaccessible.  The PM and USB cores make sure that
+-	 * the root hub is either suspended or stopped.
+-	 */
+-	ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev));
+-	spin_lock_irqsave(&ehci->lock, flags);
+-	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+-	(void)ehci_readl(ehci, &ehci->regs->intr_enable);
+-
+-	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+-	spin_unlock_irqrestore(&ehci->lock, flags);
++	rc = ehci_suspend(hcd, do_wakeup);
+ 
+ 	if (pdata && pdata->phy_exit)
+ 		pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
+@@ -234,7 +219,6 @@ static int s5p_ehci_resume(struct device *dev)
+ {
+ 	struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev);
+ 	struct usb_hcd *hcd = s5p_ehci->hcd;
+-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ 	struct platform_device *pdev = to_platform_device(dev);
+ 	struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
+ 
+@@ -246,44 +230,7 @@ static int s5p_ehci_resume(struct device *dev)
+ 	/* DMA burst Enable */
+ 	writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs));
+ 
+-	if (time_before(jiffies, ehci->next_statechange))
+-		msleep(100);
+-
+-	/* Mark hardware accessible again as we are out of D3 state by now */
+-	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+-
+-	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
+-		int	mask = INTR_MASK;
+-
+-		ehci_prepare_ports_for_controller_resume(ehci);
+-		if (!hcd->self.root_hub->do_remote_wakeup)
+-			mask &= ~STS_PCD;
+-		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+-		ehci_readl(ehci, &ehci->regs->intr_enable);
+-		return 0;
+-	}
+-
+-	usb_root_hub_lost_power(hcd->self.root_hub);
+-
+-	(void) ehci_halt(ehci);
+-	(void) ehci_reset(ehci);
+-
+-	/* emptying the schedule aborts any urbs */
+-	spin_lock_irq(&ehci->lock);
+-	if (ehci->reclaim)
+-		end_unlink_async(ehci);
+-	ehci_work(ehci);
+-	spin_unlock_irq(&ehci->lock);
+-
+-	ehci_writel(ehci, ehci->command, &ehci->regs->command);
+-	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
+-	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
+-
+-	/* here we "know" root ports should always stay powered */
+-	ehci_port_power(ehci, 1);
+-
+-	ehci->rh_state = EHCI_RH_SUSPENDED;
+-
++	ehci_resume(hcd, false);
+ 	return 0;
+ }
+ #else
+diff --git a/drivers/usb/host/ehci-sead3.c b/drivers/usb/host/ehci-sead3.c
+index cc199e87a7a9..58c96bd50d22 100644
+--- a/drivers/usb/host/ehci-sead3.c
++++ b/drivers/usb/host/ehci-sead3.c
+@@ -160,84 +160,16 @@ static int ehci_hcd_sead3_drv_remove(struct platform_device *pdev)
+ static int ehci_hcd_sead3_drv_suspend(struct device *dev)
+ {
+ 	struct usb_hcd *hcd = dev_get_drvdata(dev);
+-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+-	unsigned long flags;
+-	int rc = 0;
+-
+-	if (time_before(jiffies, ehci->next_statechange))
+-		msleep(20);
+-
+-	/* Root hub was already suspended. Disable irq emission and
+-	 * mark HW unaccessible.  The PM and USB cores make sure that
+-	 * the root hub is either suspended or stopped.
+-	 */
+-	ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev));
+-	spin_lock_irqsave(&ehci->lock, flags);
+-	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+-	(void)ehci_readl(ehci, &ehci->regs->intr_enable);
+-
+-	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+-	spin_unlock_irqrestore(&ehci->lock, flags);
++	bool do_wakeup = device_may_wakeup(dev);
+ 
+-	/* could save FLADJ in case of Vaux power loss
+-	 * ... we'd only use it to handle clock skew
+-	 */
+-
+-	return rc;
++	return ehci_suspend(hcd, do_wakeup);
+ }
+ 
+ static int ehci_hcd_sead3_drv_resume(struct device *dev)
+ {
+ 	struct usb_hcd *hcd = dev_get_drvdata(dev);
+-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+-
+-	/* maybe restore FLADJ. */
+-
+-	if (time_before(jiffies, ehci->next_statechange))
+-		msleep(100);
+-
+-	/* Mark hardware accessible again as we are out of D3 state by now */
+-	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+-
+-	/* If CF is still set, we maintained PCI Vaux power.
+-	 * Just undo the effect of ehci_pci_suspend().
+-	 */
+-	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
+-		int	mask = INTR_MASK;
+-
+-		ehci_prepare_ports_for_controller_resume(ehci);
+-		if (!hcd->self.root_hub->do_remote_wakeup)
+-			mask &= ~STS_PCD;
+-		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+-		ehci_readl(ehci, &ehci->regs->intr_enable);
+-		return 0;
+-	}
+-
+-	ehci_dbg(ehci, "lost power, restarting\n");
+-	usb_root_hub_lost_power(hcd->self.root_hub);
+-
+-	/* Else reset, to cope with power loss or flush-to-storage
+-	 * style "resume" having let BIOS kick in during reboot.
+-	 */
+-	(void) ehci_halt(ehci);
+-	(void) ehci_reset(ehci);
+-
+-	/* emptying the schedule aborts any urbs */
+-	spin_lock_irq(&ehci->lock);
+-	if (ehci->reclaim)
+-		end_unlink_async(ehci);
+-	ehci_work(ehci);
+-	spin_unlock_irq(&ehci->lock);
+-
+-	ehci_writel(ehci, ehci->command, &ehci->regs->command);
+-	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
+-	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
+-
+-	/* here we "know" root ports should always stay powered */
+-	ehci_port_power(ehci, 1);
+-
+-	ehci->rh_state = EHCI_RH_SUSPENDED;
+ 
++	ehci_resume(hcd, false);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c
+index 37ba8c8d2fd0..7ed533e6cca8 100644
+--- a/drivers/usb/host/ehci-spear.c
++++ b/drivers/usb/host/ehci-spear.c
+@@ -97,71 +97,16 @@ static const struct hc_driver ehci_spear_hc_driver = {
+ static int ehci_spear_drv_suspend(struct device *dev)
+ {
+ 	struct usb_hcd *hcd = dev_get_drvdata(dev);
+-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+-	unsigned long flags;
+-	int rc = 0;
+-
+-	if (time_before(jiffies, ehci->next_statechange))
+-		msleep(10);
+-
+-	/*
+-	 * Root hub was already suspended. Disable irq emission and mark HW
+-	 * unaccessible. The PM and USB cores make sure that the root hub is
+-	 * either suspended or stopped.
+-	 */
+-	spin_lock_irqsave(&ehci->lock, flags);
+-	ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev));
+-	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+-	ehci_readl(ehci, &ehci->regs->intr_enable);
+-	spin_unlock_irqrestore(&ehci->lock, flags);
++	bool do_wakeup = device_may_wakeup(dev);
+ 
+-	return rc;
++	return ehci_suspend(hcd, do_wakeup);
+ }
+ 
+ static int ehci_spear_drv_resume(struct device *dev)
+ {
+ 	struct usb_hcd *hcd = dev_get_drvdata(dev);
+-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+-
+-	if (time_before(jiffies, ehci->next_statechange))
+-		msleep(100);
+-
+-	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
+-		int mask = INTR_MASK;
+-
+-		ehci_prepare_ports_for_controller_resume(ehci);
+-
+-		if (!hcd->self.root_hub->do_remote_wakeup)
+-			mask &= ~STS_PCD;
+-
+-		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+-		ehci_readl(ehci, &ehci->regs->intr_enable);
+-		return 0;
+-	}
+-
+-	usb_root_hub_lost_power(hcd->self.root_hub);
+-
+-	/*
+-	 * Else reset, to cope with power loss or flush-to-storage style
+-	 * "resume" having let BIOS kick in during reboot.
+-	 */
+-	ehci_halt(ehci);
+-	ehci_reset(ehci);
+-
+-	/* emptying the schedule aborts any urbs */
+-	spin_lock_irq(&ehci->lock);
+-	if (ehci->reclaim)
+-		end_unlink_async(ehci);
+-
+-	ehci_work(ehci);
+-	spin_unlock_irq(&ehci->lock);
+-
+-	ehci_writel(ehci, ehci->command, &ehci->regs->command);
+-	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
+-	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
+ 
+-	/* here we "know" root ports should always stay powered */
+-	ehci_port_power(ehci, 1);
++	ehci_resume(hcd, false);
+ 	return 0;
+ }
+ #endif /* CONFIG_PM */

commit a46af4ebf9ffec35eea0390e89935197b833dc61
+Author: Alan Stern 
+Date:   Mon Jun 25 12:19:03 2012 -0400
+
+    USB: EHCI: define extension registers like normal ones
+    
+    This patch (as1562) cleans up the definitions of the EHCI extended
+    registers to be consistent with the definitions of the standard
+    registers.  This makes the code look a lot nicer, with no functional
+    change.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 800be38c78b4..c49fc1e7895d 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -203,11 +203,9 @@ static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
+ /* check TDI/ARC silicon is in host mode */
+ static int tdi_in_host_mode (struct ehci_hcd *ehci)
+ {
+-	u32 __iomem	*reg_ptr;
+ 	u32		tmp;
+ 
+-	reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE);
+-	tmp = ehci_readl(ehci, reg_ptr);
++	tmp = ehci_readl(ehci, &ehci->regs->usbmode);
+ 	return (tmp & 3) == USBMODE_CM_HC;
+ }
+ 
+@@ -303,11 +301,9 @@ static int handshake_on_error_set_halt(struct ehci_hcd *ehci, void __iomem *ptr,
+ /* put TDI/ARC silicon into EHCI mode */
+ static void tdi_reset (struct ehci_hcd *ehci)
+ {
+-	u32 __iomem	*reg_ptr;
+ 	u32		tmp;
+ 
+-	reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE);
+-	tmp = ehci_readl(ehci, reg_ptr);
++	tmp = ehci_readl(ehci, &ehci->regs->usbmode);
+ 	tmp |= USBMODE_CM_HC;
+ 	/* The default byte access to MMR space is LE after
+ 	 * controller reset. Set the required endian mode
+@@ -315,7 +311,7 @@ static void tdi_reset (struct ehci_hcd *ehci)
+ 	 */
+ 	if (ehci_big_endian_mmio(ehci))
+ 		tmp |= USBMODE_BE;
+-	ehci_writel(ehci, tmp, reg_ptr);
++	ehci_writel(ehci, tmp, &ehci->regs->usbmode);
+ }
+ 
+ /* reset a non-running (STS_HALT == 1) controller */
+@@ -339,9 +335,8 @@ static int ehci_reset (struct ehci_hcd *ehci)
+ 
+ 	if (ehci->has_hostpc) {
+ 		ehci_writel(ehci, USBMODE_EX_HC | USBMODE_EX_VBPS,
+-			(u32 __iomem *)(((u8 *)ehci->regs) + USBMODE_EX));
+-		ehci_writel(ehci, TXFIFO_DEFAULT,
+-			(u32 __iomem *)(((u8 *)ehci->regs) + TXFILLTUNING));
++				&ehci->regs->usbmode_ex);
++		ehci_writel(ehci, TXFIFO_DEFAULT, &ehci->regs->txfill_tuning);
+ 	}
+ 	if (retval)
+ 		return retval;
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index dd5eef6af6df..db05e358677a 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -149,10 +149,8 @@ static __maybe_unused void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
+ 	if (ehci->has_hostpc) {
+ 		port = HCS_N_PORTS(ehci->hcs_params);
+ 		while (port--) {
+-			u32 __iomem	*hostpc_reg;
++			u32 __iomem	*hostpc_reg = &ehci->regs->hostpc[port];
+ 
+-			hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs
+-					+ HOSTPC0 + 4 * port);
+ 			temp = ehci_readl(ehci, hostpc_reg);
+ 			ehci_writel(ehci, temp & ~HOSTPC_PHCD, hostpc_reg);
+ 		}
+@@ -185,10 +183,8 @@ static __maybe_unused void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
+ 	if (ehci->has_hostpc) {
+ 		port = HCS_N_PORTS(ehci->hcs_params);
+ 		while (port--) {
+-			u32 __iomem	*hostpc_reg;
++			u32 __iomem	*hostpc_reg = &ehci->regs->hostpc[port];
+ 
+-			hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs
+-					+ HOSTPC0 + 4 * port);
+ 			temp = ehci_readl(ehci, hostpc_reg);
+ 			ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg);
+ 		}
+@@ -285,11 +281,9 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 
+ 		port = HCS_N_PORTS(ehci->hcs_params);
+ 		while (port--) {
+-			u32 __iomem	*hostpc_reg;
++			u32 __iomem	*hostpc_reg = &ehci->regs->hostpc[port];
+ 			u32		t3;
+ 
+-			hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs
+-					+ HOSTPC0 + 4 * port);
+ 			t3 = ehci_readl(ehci, hostpc_reg);
+ 			ehci_writel(ehci, t3 | HOSTPC_PHCD, hostpc_reg);
+ 			t3 = ehci_readl(ehci, hostpc_reg);
+@@ -388,10 +382,9 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 		i = HCS_N_PORTS(ehci->hcs_params);
+ 		while (i--) {
+ 			if (test_bit(i, &ehci->bus_suspended)) {
+-				u32 __iomem	*hostpc_reg;
++				u32 __iomem	*hostpc_reg =
++							&ehci->regs->hostpc[i];
+ 
+-				hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs
+-						+ HOSTPC0 + 4 * i);
+ 				temp = ehci_readl(ehci, hostpc_reg);
+ 				ehci_writel(ehci, temp & ~HOSTPC_PHCD,
+ 						hostpc_reg);
+@@ -667,7 +660,7 @@ static int ehci_hub_control (
+ 	int		ports = HCS_N_PORTS (ehci->hcs_params);
+ 	u32 __iomem	*status_reg = &ehci->regs->port_status[
+ 				(wIndex & 0xff) - 1];
+-	u32 __iomem	*hostpc_reg = NULL;
++	u32 __iomem	*hostpc_reg = &ehci->regs->hostpc[(wIndex & 0xff) - 1];
+ 	u32		temp, temp1, status;
+ 	unsigned long	flags;
+ 	int		retval = 0;
+@@ -680,9 +673,6 @@ static int ehci_hub_control (
+ 	 * power, "this is the one", etc.  EHCI spec supports this.
+ 	 */
+ 
+-	if (ehci->has_hostpc)
+-		hostpc_reg = (u32 __iomem *)((u8 *)ehci->regs
+-				+ HOSTPC0 + 4 * ((wIndex & 0xff) - 1));
+ 	spin_lock_irqsave (&ehci->lock, flags);
+ 	switch (typeReq) {
+ 	case ClearHubFeature:
+@@ -734,7 +724,7 @@ static int ehci_hub_control (
+ 				goto error;
+ 
+ 			/* clear phy low-power mode before resume */
+-			if (hostpc_reg) {
++			if (ehci->has_hostpc) {
+ 				temp1 = ehci_readl(ehci, hostpc_reg);
+ 				ehci_writel(ehci, temp1 & ~HOSTPC_PHCD,
+ 						hostpc_reg);
+@@ -984,7 +974,7 @@ static int ehci_hub_control (
+ 			temp &= ~PORT_WKCONN_E;
+ 			temp |= PORT_WKDISC_E | PORT_WKOC_E;
+ 			ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
+-			if (hostpc_reg) {
++			if (ehci->has_hostpc) {
+ 				spin_unlock_irqrestore(&ehci->lock, flags);
+ 				msleep(5);/* 5ms for HCD enter low pwr mode */
+ 				spin_lock_irqsave(&ehci->lock, flags);
+diff --git a/include/linux/usb/ehci_def.h b/include/linux/usb/ehci_def.h
+index 7cc95ee3606b..de4b9ed5d5dd 100644
+--- a/include/linux/usb/ehci_def.h
++++ b/include/linux/usb/ehci_def.h
+@@ -111,7 +111,13 @@ struct ehci_regs {
+ 	/* ASYNCLISTADDR: offset 0x18 */
+ 	u32		async_next;	/* address of next async queue head */
+ 
+-	u32		reserved[9];
++	u32		reserved1[2];
++
++	/* TXFILLTUNING: offset 0x24 */
++	u32		txfill_tuning;	/* TX FIFO Tuning register */
++#define TXFIFO_DEFAULT	(8<<16)		/* FIFO burst threshold 8 */
++
++	u32		reserved2[6];
+ 
+ 	/* CONFIGFLAG: offset 0x40 */
+ 	u32		configured_flag;
+@@ -155,26 +161,34 @@ struct ehci_regs {
+ #define PORT_CSC	(1<<1)		/* connect status change */
+ #define PORT_CONNECT	(1<<0)		/* device connected */
+ #define PORT_RWC_BITS   (PORT_CSC | PORT_PEC | PORT_OCC)
+-};
+ 
+-#define USBMODE		0x68		/* USB Device mode */
++	u32		reserved3[9];
++
++	/* USBMODE: offset 0x68 */
++	u32		usbmode;	/* USB Device mode */
+ #define USBMODE_SDIS	(1<<3)		/* Stream disable */
+ #define USBMODE_BE	(1<<2)		/* BE/LE endianness select */
+ #define USBMODE_CM_HC	(3<<0)		/* host controller mode */
+ #define USBMODE_CM_IDLE	(0<<0)		/* idle state */
+ 
++	u32		reserved4[7];
++
+ /* Moorestown has some non-standard registers, partially due to the fact that
+  * its EHCI controller has both TT and LPM support. HOSTPCx are extensions to
+  * PORTSCx
+  */
+-#define HOSTPC0		0x84		/* HOSTPC extension */
++	/* HOSTPC: offset 0x84 */
++	u32		hostpc[0];	/* HOSTPC extension */
+ #define HOSTPC_PHCD	(1<<22)		/* Phy clock disable */
+ #define HOSTPC_PSPD	(3<<25)		/* Port speed detection */
+-#define USBMODE_EX	0xc8		/* USB Device mode extension */
++
++	u32		reserved5[17];
++
++	/* USBMODE_EX: offset 0xc8 */
++	u32		usbmode_ex;	/* USB Device mode extension */
+ #define USBMODE_EX_VBPS	(1<<5)		/* VBus Power Select On */
+ #define USBMODE_EX_HC	(3<<0)		/* host controller mode */
+-#define TXFILLTUNING	0x24		/* TX FIFO Tuning register */
+-#define TXFIFO_DEFAULT	(8<<16)		/* FIFO burst threshold 8 */
++};
+ 
+ /* Appendix C, Debug port ... intended for use with special "debug devices"
+  * that can help if there's no serial console.  (nonstandard enumeration.)

commit 4661e3568a7d14a93d4e428d246cdb86f4bac6e7
+Author: Alan Stern 
+Date:   Fri Jun 22 17:12:19 2012 -0400
+
+    printk: fix regression in SYSLOG_ACTION_CLEAR
+    
+    Commit 7ff9554bb578ba02166071d2d487b7fc7d860d62 (printk: convert
+    byte-buffer to variable-length record buffer) introduced a regression
+    by accidentally removing a "break" statement from inside the big
+    switch in printk's do_syslog().  The symptom of this bug is that the
+    "dmesg -C" command doesn't only clear the kernel's log buffer; it also
+    disables console logging.
+    
+    This patch (as1561) fixes the regression by adding the missing
+    "break".
+    
+    Signed-off-by: Alan Stern 
+    CC: Kay Sievers 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/kernel/printk.c b/kernel/printk.c
+index a2276b916769..d6a1412f6b09 100644
+--- a/kernel/printk.c
++++ b/kernel/printk.c
+@@ -1040,6 +1040,7 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
+ 	/* Clear ring buffer */
+ 	case SYSLOG_ACTION_CLEAR:
+ 		syslog_print_all(NULL, 0, true);
++		break;
+ 	/* Disable logging to console */
+ 	case SYSLOG_ACTION_CONSOLE_OFF:
+ 		if (saved_console_loglevel == -1)

commit 0070513b5e005161a7a7fd9a3f48f982b41eb094
+Author: Alan Stern 
+Date:   Wed Jun 20 16:04:30 2012 -0400
+
+    usb-storage: revert commit afff07e61a52 (Add 090c:1000 to unusal-devs)
+    
+    This patch (as1560) reverts commit
+    afff07e61a5243e14ee3f0a272a0380cd744a8a3 (usb-storage: Add 090c:1000
+    to unusal-devs).  It is no longer needed, because usb-storage now
+    tells the sd driver to try READ CAPACITY(10) before READ CAPACITY(16)
+    for every USB mass-storage device.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Hans de Goede 
+    CC: Matthew Dharm 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index caf22bf5f822..1719886bb9be 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -1107,13 +1107,6 @@ UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999,
+ 		USB_SC_RBC, USB_PR_BULK, NULL,
+ 		0 ),
+ 
+-/* Feiya QDI U2 DISK, reported by Hans de Goede  */
+-UNUSUAL_DEV( 0x090c, 0x1000, 0x0000, 0xffff,
+-		"Feiya",
+-		"QDI U2 DISK",
+-		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+-		US_FL_NO_READ_CAPACITY_16 ),
+-
+ /* aeb */
+ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
+ 		"Feiya",

commit 6a0bdffa0073857870a4ed1b4489762146359eb4
+Author: Alan Stern 
+Date:   Wed Jun 20 16:04:19 2012 -0400
+
+    SCSI & usb-storage: add try_rc_10_first flag
+    
+    Several bug reports have been received recently for USB mass-storage
+    devices that don't handle READ CAPACITY(16) commands properly.  They
+    report bogus sizes, in some cases becoming unusable as a result.
+    
+    The bugs were triggered by commit
+    09b6b51b0b6c1b9bb61815baf205e4d74c89ff04 (SCSI & usb-storage: add
+    flags for VPD pages and REPORT LUNS), which caused usb-storage to stop
+    overriding the SCSI level reported by devices.  By default, the sd
+    driver will try READ CAPACITY(16) first for any device whose level is
+    above SCSI_SPC_2.
+    
+    It seems likely that any device large enough to require the use of
+    READ CAPACITY(16) (i.e., 2 TB or more) would be able to handle READ
+    CAPACITY(10) commands properly.  Indeed, I don't know of any devices
+    that don't handle READ CAPACITY(10) properly.
+    
+    Therefore this patch (as1559) adds a new flag telling the sd driver
+    to try READ CAPACITY(10) before READ CAPACITY(16), and sets this flag
+    for every USB mass-storage device.  If a device really is larger than
+    2 TB, sd will fall back to READ CAPACITY(16) just as it used to.
+    
+    This fixes Bugzilla #43391.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Hans de Goede 
+    CC: "James E.J. Bottomley" 
+    CC: Matthew Dharm 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+index 6f0a4c612b3b..6f72b80121a0 100644
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -1899,6 +1899,8 @@ static int sd_try_rc16_first(struct scsi_device *sdp)
+ {
+ 	if (sdp->host->max_cmd_len < 16)
+ 		return 0;
++	if (sdp->try_rc_10_first)
++		return 0;
+ 	if (sdp->scsi_level > SCSI_SPC_2)
+ 		return 1;
+ 	if (scsi_device_protection(sdp))
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index a324a5d21e99..11418da9bc09 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -202,6 +202,12 @@ static int slave_configure(struct scsi_device *sdev)
+ 		if (us->fflags & US_FL_NO_READ_CAPACITY_16)
+ 			sdev->no_read_capacity_16 = 1;
+ 
++		/*
++		 * Many devices do not respond properly to READ_CAPACITY_16.
++		 * Tell the SCSI layer to try READ_CAPACITY_10 first.
++		 */
++		sdev->try_rc_10_first = 1;
++
+ 		/* assume SPC3 or latter devices support sense size > 18 */
+ 		if (sdev->scsi_level > SCSI_SPC_2)
+ 			us->fflags |= US_FL_SANE_SENSE;
+diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
+index 6efb2e1416e0..ba9698852321 100644
+--- a/include/scsi/scsi_device.h
++++ b/include/scsi/scsi_device.h
+@@ -151,6 +151,7 @@ struct scsi_device {
+ 					   SD_LAST_BUGGY_SECTORS */
+ 	unsigned no_read_disc_info:1;	/* Avoid READ_DISC_INFO cmds */
+ 	unsigned no_read_capacity_16:1; /* Avoid READ_CAPACITY_16 cmds */
++	unsigned try_rc_10_first:1;	/* Try READ_CAPACACITY_10 first */
+ 	unsigned is_visible:1;	/* is the device visible in sysfs */
+ 
+ 	DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */

commit 0b84704a2d6fdf55a3dcdd2a1f2ac8b48913c84b
+Author: Alan Stern 
+Date:   Thu May 31 17:03:52 2012 -0400
+
+    USB: serial-generic: use a single set of device IDs
+    
+    The usb-serial-generic driver uses different device IDs for its USB
+    matching and its serial matching.  This can lead to problems: The
+    driver can end up getting bound to a USB interface without being
+    allowed to bind to the corresponding serial port.
+    
+    This patch (as1557) fixes the problem by using the same device ID
+    table (the one that can be altered by the "vendor=" and "product="
+    module parameters) for both purposes.  The unused table is removed.
+    Now the driver will bind only to the intended devices.
+    
+    Signed-off-by: Alan Stern 
+    CC: Bjørn Mork 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
+index 105a6d898ca4..9b026bf7afef 100644
+--- a/drivers/usb/serial/generic.c
++++ b/drivers/usb/serial/generic.c
+@@ -39,13 +39,6 @@ MODULE_PARM_DESC(product, "User specified USB idProduct");
+ 
+ static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */
+ 
+-/* we want to look at all devices, as the vendor/product id can change
+- * depending on the command line argument */
+-static const struct usb_device_id generic_serial_ids[] = {
+-	{.driver_info = 42},
+-	{}
+-};
+-
+ /* All of the device info needed for the Generic Serial Converter */
+ struct usb_serial_driver usb_serial_generic_device = {
+ 	.driver = {
+@@ -79,7 +72,8 @@ int usb_serial_generic_register(int _debug)
+ 		USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT;
+ 
+ 	/* register our generic driver with ourselves */
+-	retval = usb_serial_register_drivers(serial_drivers, "usbserial_generic", generic_serial_ids);
++	retval = usb_serial_register_drivers(serial_drivers,
++			"usbserial_generic", generic_device_ids);
+ #endif
+ 	return retval;
+ }

commit c2fb8a3fa25513de8fedb38509b1f15a5bbee47b
+Author: Alan Stern 
+Date:   Wed Jun 13 11:20:19 2012 -0400
+
+    USB: add NO_D3_DURING_SLEEP flag and revert 151b61284776be2
+    
+    This patch (as1558) fixes a problem affecting several ASUS computers:
+    The machine crashes or corrupts memory when going into suspend if the
+    ehci-hcd driver is bound to any controllers.  Users have been forced
+    to unbind or unload ehci-hcd before putting their systems to sleep.
+    
+    After extensive testing, it was determined that the machines don't
+    like going into suspend when any EHCI controllers are in the PCI D3
+    power state.  Presumably this is a firmware bug, but there's nothing
+    we can do about it except to avoid putting the controllers in D3
+    during system sleep.
+    
+    The patch adds a new flag to indicate whether the problem is present,
+    and avoids changing the controller's power state if the flag is set.
+    Runtime suspend is unaffected; this matters only for system suspend.
+    However as a side effect, the controller will not respond to remote
+    wakeup requests while the system is asleep.  Hence USB wakeup is not
+    functional -- but of course, this is already true in the current state
+    of affairs.
+    
+    A similar patch has already been applied as commit
+    151b61284776be2d6f02d48c23c3625678960b97 (USB: EHCI: fix crash during
+    suspend on ASUS computers).  The patch supersedes that one and reverts
+    it.  There are two differences:
+    
+            The old patch added the flag at the USB level; this patch
+            adds it at the PCI level.
+    
+            The old patch applied to all chipsets with the same vendor,
+            subsystem vendor, and product IDs; this patch makes an
+            exception for a known-good system (based on DMI information).
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Dâniel Fraga 
+    Tested-by: Andrey Rahmatullin 
+    Tested-by: Steven Rostedt 
+    Cc: stable 
+    Reviewed-by: Rafael J. Wysocki 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
+index 447e83472c01..77cb54a65cde 100644
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -1744,6 +1744,11 @@ int pci_prepare_to_sleep(struct pci_dev *dev)
+ 	if (target_state == PCI_POWER_ERROR)
+ 		return -EIO;
+ 
++	/* Some devices mustn't be in D3 during system sleep */
++	if (target_state == PCI_D3hot &&
++			(dev->dev_flags & PCI_DEV_FLAGS_NO_D3_DURING_SLEEP))
++		return 0;
++
+ 	pci_enable_wake(dev, target_state, device_may_wakeup(&dev->dev));
+ 
+ 	error = pci_set_power_state(dev, target_state);
+diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
+index 2a7521677541..194b243a2817 100644
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -2929,6 +2929,32 @@ static void __devinit disable_igfx_irq(struct pci_dev *dev)
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0102, disable_igfx_irq);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq);
+ 
++/*
++ * The Intel 6 Series/C200 Series chipset's EHCI controllers on many
++ * ASUS motherboards will cause memory corruption or a system crash
++ * if they are in D3 while the system is put into S3 sleep.
++ */
++static void __devinit asus_ehci_no_d3(struct pci_dev *dev)
++{
++	const char *sys_info;
++	static const char good_Asus_board[] = "P8Z68-V";
++
++	if (dev->dev_flags & PCI_DEV_FLAGS_NO_D3_DURING_SLEEP)
++		return;
++	if (dev->subsystem_vendor != PCI_VENDOR_ID_ASUSTEK)
++		return;
++	sys_info = dmi_get_system_info(DMI_BOARD_NAME);
++	if (sys_info && memcmp(sys_info, good_Asus_board,
++			sizeof(good_Asus_board) - 1) == 0)
++		return;
++
++	dev_info(&dev->dev, "broken D3 during system sleep on ASUS\n");
++	dev->dev_flags |= PCI_DEV_FLAGS_NO_D3_DURING_SLEEP;
++	device_set_wakeup_capable(&dev->dev, false);
++}
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1c26, asus_ehci_no_d3);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1c2d, asus_ehci_no_d3);
++
+ static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
+ 			  struct pci_fixup *end)
+ {
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index 57ed9e400c06..622b4a48e732 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -493,15 +493,6 @@ static int hcd_pci_suspend_noirq(struct device *dev)
+ 
+ 	pci_save_state(pci_dev);
+ 
+-	/*
+-	 * Some systems crash if an EHCI controller is in D3 during
+-	 * a sleep transition.  We have to leave such controllers in D0.
+-	 */
+-	if (hcd->broken_pci_sleep) {
+-		dev_dbg(dev, "Staying in PCI D0\n");
+-		return retval;
+-	}
+-
+ 	/* If the root hub is dead rather than suspended, disallow remote
+ 	 * wakeup.  usb_hc_died() should ensure that both hosts are marked as
+ 	 * dying, so we only need to check the primary roothub.
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index bc94d7bf072d..123481793a47 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -144,14 +144,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 			hcd->has_tt = 1;
+ 			tdi_reset(ehci);
+ 		}
+-		if (pdev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK) {
+-			/* EHCI #1 or #2 on 6 Series/C200 Series chipset */
+-			if (pdev->device == 0x1c26 || pdev->device == 0x1c2d) {
+-				ehci_info(ehci, "broken D3 during system sleep on ASUS\n");
+-				hcd->broken_pci_sleep = 1;
+-				device_set_wakeup_capable(&pdev->dev, false);
+-			}
+-		}
+ 		break;
+ 	case PCI_VENDOR_ID_TDI:
+ 		if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
+diff --git a/include/linux/pci.h b/include/linux/pci.h
+index d8c379dba6ad..fefb4e19bf6a 100644
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -176,6 +176,8 @@ enum pci_dev_flags {
+ 	PCI_DEV_FLAGS_NO_D3 = (__force pci_dev_flags_t) 2,
+ 	/* Provide indication device is assigned by a Virtual Machine Manager */
+ 	PCI_DEV_FLAGS_ASSIGNED = (__force pci_dev_flags_t) 4,
++	/* Device causes system crash if in D3 during S3 sleep */
++	PCI_DEV_FLAGS_NO_D3_DURING_SLEEP = (__force pci_dev_flags_t) 8,
+ };
+ 
+ enum pci_irq_reroute_variant {
+diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
+index 7f855d50cdf5..49b3ac29726a 100644
+--- a/include/linux/usb/hcd.h
++++ b/include/linux/usb/hcd.h
+@@ -126,8 +126,6 @@ struct usb_hcd {
+ 	unsigned		wireless:1;	/* Wireless USB HCD */
+ 	unsigned		authorized_default:1;
+ 	unsigned		has_tt:1;	/* Integrated TT in root hub */
+-	unsigned		broken_pci_sleep:1;	/* Don't put the
+-			controller in PCI-D3 for system sleep */
+ 
+ 	unsigned int		irq;		/* irq allocated */
+ 	void __iomem		*regs;		/* device memory/io */

commit 1996e6c572969a8cf6d7fa97eef621219acd94a9
+Author: Alan Stern 
+Date:   Mon May 14 13:48:16 2012 -0400
+
+    USB: EHCI: work around bug in the Philips ISP1562 controller
+    
+    This patch (as1556) works around a bug in the Philips ISP1562 EHCI
+    controller.  Although the controller claims to support frame-list
+    lengths smaller than the default of 1024 for its periodic schedule, in
+    fact smaller values don't work.  A new quirk flag is added to indicate
+    when the bug is present, and if it is then the schedule size is left
+    at the default value.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 5cb775b1802d..f644ba9529ed 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -639,7 +639,7 @@ static int ehci_init(struct usb_hcd *hcd)
+ 	INIT_LIST_HEAD(&ehci->cached_itd_list);
+ 	INIT_LIST_HEAD(&ehci->cached_sitd_list);
+ 
+-	if (HCC_PGM_FRAMELISTLEN(hcc_params)) {
++	if (HCC_PGM_FRAMELISTLEN(hcc_params) && !ehci->sched_size_bug) {
+ 		/* periodic schedule size can be smaller than default */
+ 		switch (EHCI_TUNE_FLS) {
+ 		case 0: ehci->periodic_size = 1024; break;
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index bc94d7bf072d..4baafa3e80b2 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -97,6 +97,13 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 			break;
+ 		}
+ 		break;
++
++	case PCI_VENDOR_ID_PHILIPS:
++		/*
++		 * Philips controllers set HCC_PGM_FRAMELISTLEN, but
++		 * they don't implement schedule sizes shorter than 1024.
++		 */
++		ehci->sched_size_bug = 1;
+ 	}
+ 
+ 	/* cache this readonly data; minimize chip reads */
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 2694ed6558d2..2a6652fd5400 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -149,6 +149,7 @@ struct ehci_hcd {			/* one per controller */
+ 	unsigned		use_dummy_qh:1;	/* AMD Frame List table quirk*/
+ 	unsigned		has_synopsys_hc_bug:1; /* Synopsys HC */
+ 	unsigned		frame_index_bug:1; /* MosChip (AKA NetMos) */
++	unsigned		sched_size_bug:1; /* Philips */
+ 
+ 	/* required for usb32 quirk */
+ 	#define OHCI_CTRL_HCFS          (3 << 6)

commit 65b8e5cbdddc86474372bdb48dc233b06710a576
+Author: Alan Stern 
+Date:   Mon May 14 13:47:20 2012 -0400
+
+    USB: EHCI: improve full-speed isochronous scheduling routine
+    
+    This patch (as1555) improves the code ehci-hcd uses while checking the
+    periodic schedule for isochronous transfers to full-speed devices.  In
+    addition to making sure that a new transfer does not violate the
+    restrictions on the high-speed schedule, it also has to check the
+    restrictions on the full-speed part of the bus, i.e., the part beyond
+    the Transaction Translator (TT).
+    
+    It does this by calling tt_available() (or tt_no_collision() if
+    CONFIG_USB_EHCI_TT_NEWSCHED isn't enabled).  However it calls that
+    routine on each pass through a loop over the frames being modified,
+    which is an unnecessary expense because tt_available() (or
+    tt_no_collision) already does its own loop over frames.  It is
+    sufficient to do the check just once, before starting the loop.
+    
+    In addition, the function calls incorrectly converted the transfer's
+    period from microframes to frames by doing a left shift instead of a
+    right shift.  The patch fixes this while moving the calls.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index cb7667967e5a..33182c6d1ff9 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1331,34 +1331,36 @@ sitd_slot_ok (
+ 	if (mask & ~0xffff)
+ 		return 0;
+ 
++	/* check bandwidth */
++	uframe %= period_uframes;
++	frame = uframe >> 3;
++
++#ifdef CONFIG_USB_EHCI_TT_NEWSCHED
++	/* The tt's fullspeed bus bandwidth must be available.
++	 * tt_available scheduling guarantees 10+% for control/bulk.
++	 */
++	uf = uframe & 7;
++	if (!tt_available(ehci, period_uframes >> 3,
++			stream->udev, frame, uf, stream->tt_usecs))
++		return 0;
++#else
++	/* tt must be idle for start(s), any gap, and csplit.
++	 * assume scheduling slop leaves 10+% for control/bulk.
++	 */
++	if (!tt_no_collision(ehci, period_uframes >> 3,
++			stream->udev, frame, mask))
++		return 0;
++#endif
++
+ 	/* this multi-pass logic is simple, but performance may
+ 	 * suffer when the schedule data isn't cached.
+ 	 */
+-
+-	/* check bandwidth */
+-	uframe %= period_uframes;
+ 	do {
+ 		u32		max_used;
+ 
+ 		frame = uframe >> 3;
+ 		uf = uframe & 7;
+ 
+-#ifdef CONFIG_USB_EHCI_TT_NEWSCHED
+-		/* The tt's fullspeed bus bandwidth must be available.
+-		 * tt_available scheduling guarantees 10+% for control/bulk.
+-		 */
+-		if (!tt_available (ehci, period_uframes << 3,
+-				stream->udev, frame, uf, stream->tt_usecs))
+-			return 0;
+-#else
+-		/* tt must be idle for start(s), any gap, and csplit.
+-		 * assume scheduling slop leaves 10+% for control/bulk.
+-		 */
+-		if (!tt_no_collision (ehci, period_uframes << 3,
+-				stream->udev, frame, mask))
+-			return 0;
+-#endif
+-
+ 		/* check starts (OUT uses more than one) */
+ 		max_used = ehci->uframe_periodic_max - stream->usecs;
+ 		for (tmp = stream->raw_mask & 0xff; tmp; tmp >>= 1, uf++) {

commit 356c05d58af05d582e634b54b40050c73609617b
+Author: Alan Stern 
+Date:   Mon May 14 13:30:03 2012 -0400
+
+    sysfs: get rid of some lockdep false positives
+    
+    This patch (as1554) fixes a lockdep false-positive report.  The
+    problem arises because lockdep is unable to deal with the
+    tree-structured locks created by the device core and sysfs.
+    
+    This particular problem involves a sysfs attribute method that
+    unregisters itself, not from the device it was called for, but from a
+    descendant device.  Lockdep doesn't understand the distinction and
+    reports a possible deadlock, even though the operation is safe.
+    
+    This is the sort of thing that would normally be handled by using a
+    nested lock annotation; unfortunately it's not feasible to do that
+    here.  There's no sensible way to tell sysfs when attribute removal
+    occurs in the context of a parent attribute method.
+    
+    As a workaround, the patch adds a new flag to struct attribute
+    telling sysfs not to inform lockdep when it acquires a readlock on a
+    sysfs_dirent instance for the attribute.  The readlock is still
+    acquired, but lockdep doesn't know about it and hence does not
+    complain about impossible deadlock scenarios.
+    
+    Also added are macros for static initialization of attribute
+    structures with the ignore_lockdep flag set.  The three offending
+    attributes in the USB subsystem are converted to use the new macros.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Tejun Heo 
+    CC: Eric W. Biederman 
+    CC: Peter Zijlstra 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 566d9f94f735..9a56e3adf476 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -73,7 +73,7 @@ set_bConfigurationValue(struct device *dev, struct device_attribute *attr,
+ 	return (value < 0) ? value : count;
+ }
+ 
+-static DEVICE_ATTR(bConfigurationValue, S_IRUGO | S_IWUSR,
++static DEVICE_ATTR_IGNORE_LOCKDEP(bConfigurationValue, S_IRUGO | S_IWUSR,
+ 		show_bConfigurationValue, set_bConfigurationValue);
+ 
+ /* String fields */
+@@ -595,7 +595,7 @@ static ssize_t usb_dev_authorized_store(struct device *dev,
+ 	return result < 0? result : size;
+ }
+ 
+-static DEVICE_ATTR(authorized, 0644,
++static DEVICE_ATTR_IGNORE_LOCKDEP(authorized, 0644,
+ 	    usb_dev_authorized_show, usb_dev_authorized_store);
+ 
+ /* "Safely remove a device" */
+@@ -618,7 +618,7 @@ static ssize_t usb_remove_store(struct device *dev,
+ 	usb_unlock_device(udev);
+ 	return rc;
+ }
+-static DEVICE_ATTR(remove, 0200, NULL, usb_remove_store);
++static DEVICE_ATTR_IGNORE_LOCKDEP(remove, 0200, NULL, usb_remove_store);
+ 
+ 
+ static struct attribute *dev_attrs[] = {
+diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
+index 24fa995f0312..e6bb9b2a4cbe 100644
+--- a/fs/sysfs/dir.c
++++ b/fs/sysfs/dir.c
+@@ -132,6 +132,24 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd)
+ 	rb_erase(&sd->s_rb, &sd->s_parent->s_dir.children);
+ }
+ 
++#ifdef CONFIG_DEBUG_LOCK_ALLOC
++
++/* Test for attributes that want to ignore lockdep for read-locking */
++static bool ignore_lockdep(struct sysfs_dirent *sd)
++{
++	return sysfs_type(sd) == SYSFS_KOBJ_ATTR &&
++			sd->s_attr.attr->ignore_lockdep;
++}
++
++#else
++
++static inline bool ignore_lockdep(struct sysfs_dirent *sd)
++{
++	return true;
++}
++
++#endif
++
+ /**
+  *	sysfs_get_active - get an active reference to sysfs_dirent
+  *	@sd: sysfs_dirent to get an active reference to
+@@ -155,15 +173,17 @@ struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
+ 			return NULL;
+ 
+ 		t = atomic_cmpxchg(&sd->s_active, v, v + 1);
+-		if (likely(t == v)) {
+-			rwsem_acquire_read(&sd->dep_map, 0, 1, _RET_IP_);
+-			return sd;
+-		}
++		if (likely(t == v))
++			break;
+ 		if (t < 0)
+ 			return NULL;
+ 
+ 		cpu_relax();
+ 	}
++
++	if (likely(!ignore_lockdep(sd)))
++		rwsem_acquire_read(&sd->dep_map, 0, 1, _RET_IP_);
++	return sd;
+ }
+ 
+ /**
+@@ -180,7 +200,8 @@ void sysfs_put_active(struct sysfs_dirent *sd)
+ 	if (unlikely(!sd))
+ 		return;
+ 
+-	rwsem_release(&sd->dep_map, 1, _RET_IP_);
++	if (likely(!ignore_lockdep(sd)))
++		rwsem_release(&sd->dep_map, 1, _RET_IP_);
+ 	v = atomic_dec_return(&sd->s_active);
+ 	if (likely(v != SD_DEACTIVATED_BIAS))
+ 		return;
+diff --git a/include/linux/device.h b/include/linux/device.h
+index a8db2cfa2c81..e04f5776f6d0 100644
+--- a/include/linux/device.h
++++ b/include/linux/device.h
+@@ -504,6 +504,9 @@ ssize_t device_store_int(struct device *dev, struct device_attribute *attr,
+ #define DEVICE_INT_ATTR(_name, _mode, _var) \
+ 	struct dev_ext_attribute dev_attr_##_name = \
+ 		{ __ATTR(_name, _mode, device_show_int, device_store_int), &(_var) }
++#define DEVICE_ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store) \
++	struct device_attribute dev_attr_##_name =		\
++		__ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store)
+ 
+ extern int device_create_file(struct device *device,
+ 			      const struct device_attribute *entry);
+diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
+index 0010009b2f00..381f06db2fe5 100644
+--- a/include/linux/sysfs.h
++++ b/include/linux/sysfs.h
+@@ -27,6 +27,7 @@ struct attribute {
+ 	const char		*name;
+ 	umode_t			mode;
+ #ifdef CONFIG_DEBUG_LOCK_ALLOC
++	bool			ignore_lockdep:1;
+ 	struct lock_class_key	*key;
+ 	struct lock_class_key	skey;
+ #endif
+@@ -80,6 +81,17 @@ struct attribute_group {
+ 
+ #define __ATTR_NULL { .attr = { .name = NULL } }
+ 
++#ifdef CONFIG_DEBUG_LOCK_ALLOC
++#define __ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store) {	\
++	.attr = {.name = __stringify(_name), .mode = _mode,	\
++			.ignore_lockdep = true },		\
++	.show		= _show,				\
++	.store		= _store,				\
++}
++#else
++#define __ATTR_IGNORE_LOCKDEP	__ATTR
++#endif
++
+ #define attr_name(_attr) (_attr).attr.name
+ 
+ struct file;

commit df767b71e5816692134d59c0c17e0f77cd73333d
+Author: Alan Stern 
+Date:   Tue May 8 15:15:25 2012 -0400
+
+    usb-storage: unusual_devs entry for Yarvik PMP400 MP4 player
+    
+    This patch (as1553) adds an unusual_dev entrie for the Yarvik PMP400
+    MP4 music player.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Jesse Feddema 
+    Tested-by: Jesse Feddema 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 856ad92c40de..8f3cbb8dc81b 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -1885,6 +1885,13 @@ UNUSUAL_DEV(  0x1652, 0x6600, 0x0201, 0x0201,
+ 		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ 		US_FL_IGNORE_RESIDUE ),
+ 
++/* Reported by Jesse Feddema  */
++UNUSUAL_DEV(  0x177f, 0x0400, 0x0000, 0x0000,
++		"Yarvik",
++		"PMP400",
++		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
++		US_FL_BULK_IGNORE_TAG | US_FL_MAX_SECTORS_64 ),
++
+ /* Reported by Hans de Goede 
+  * These Appotech controllers are found in Picture Frames, they provide a
+  * (buggy) emulation of a cdrom drive which contains the windows software

commit 1949f9e2435cc2e87c63da167af63faafc49b388
+Author: Alan Stern 
+Date:   Mon May 7 13:22:52 2012 -0400
+
+    USB: xhci-hcd: print URB's expected length in decimal, not hex
+    
+    This patch changes the output format specifier of a debugging line in
+    the xhci-hcd driver.  An URB's transfer_buffer_length should be
+    printed in decimal; there's no reason to print it in hex.  Especially
+    since the actual_length value, printed earlier on the same line, is
+    already in decimal.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Sarah Sharp 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
+index d40194c8ca60..329fd2a98dd6 100644
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -2272,7 +2272,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
+ 					(status != 0 &&
+ 					 !usb_endpoint_xfer_isoc(&urb->ep->desc)))
+ 				xhci_dbg(xhci, "Giveback URB %p, len = %d, "
+-						"expected = %x, status = %d\n",
++						"expected = %d, status = %d\n",
+ 						urb, urb->actual_length,
+ 						urb->transfer_buffer_length,
+ 						status);

commit c7f3619b90fc4c43ed326ec8b3f0299374763c92
+Author: Alan Stern 
+Date:   Mon May 7 11:24:05 2012 -0400
+
+    usb-serial: clean up unneeded PM-related fields
+    
+    This patch (as1551) cleans up the PM-related entries in the usb_driver
+    structures of the various USB serial driver modules.  Those entries
+    are now filled in by the usb-serial core during driver registration,
+    so they don't need to be initialized explicitly in the source code.
+    
+    The same is true of the one remaining no_dynamic_id entry.
+    
+    reset_resume remains a small problem, because the serial core doesn't
+    support it.  The patch ignores these entries.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
+index 70c46b0426ff..ba4f067cf277 100644
+--- a/drivers/usb/serial/ch341.c
++++ b/drivers/usb/serial/ch341.c
+@@ -599,11 +599,8 @@ static struct usb_driver ch341_driver = {
+ 	.name		= "ch341",
+ 	.probe		= usb_serial_probe,
+ 	.disconnect	= usb_serial_disconnect,
+-	.suspend	= usb_serial_suspend,
+-	.resume		= usb_serial_resume,
+ 	.reset_resume	= ch341_reset_resume,
+ 	.id_table	= id_table,
+-	.supports_autosuspend =	1,
+ };
+ 
+ static struct usb_serial_driver ch341_device = {
+diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c
+index 46aee85210e2..c32486d73a76 100644
+--- a/drivers/usb/serial/f81232.c
++++ b/drivers/usb/serial/f81232.c
+@@ -355,10 +355,6 @@ static struct usb_driver f81232_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table,
+-	.suspend =      usb_serial_suspend,
+-	.resume =       usb_serial_resume,
+-	.no_dynamic_id = 	1,
+-	.supports_autosuspend =	1,
+ };
+ 
+ static struct usb_serial_driver f81232_device = {
+diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
+index ae0b4aa9aa59..d1674bc3d4fa 100644
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -1224,11 +1224,6 @@ static struct usb_driver option_driver = {
+ 	.name       = "option",
+ 	.probe      = usb_serial_probe,
+ 	.disconnect = usb_serial_disconnect,
+-#ifdef CONFIG_PM
+-	.suspend    = usb_serial_suspend,
+-	.resume     = usb_serial_resume,
+-	.supports_autosuspend =	1,
+-#endif
+ 	.id_table   = option_ids,
+ };
+ 
+diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
+index 9eec2c3574d8..34e51a04dde0 100644
+--- a/drivers/usb/serial/pl2303.c
++++ b/drivers/usb/serial/pl2303.c
+@@ -100,9 +100,6 @@ static struct usb_driver pl2303_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table,
+-	.suspend =      usb_serial_suspend,
+-	.resume =       usb_serial_resume,
+-	.supports_autosuspend =	1,
+ };
+ 
+ #define SET_LINE_REQUEST_TYPE		0x21
+diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
+index 201f2810d503..3696924c1eb3 100644
+--- a/drivers/usb/serial/qcserial.c
++++ b/drivers/usb/serial/qcserial.c
+@@ -117,9 +117,6 @@ static struct usb_driver qcdriver = {
+ 	.probe			= usb_serial_probe,
+ 	.disconnect		= usb_serial_disconnect,
+ 	.id_table		= id_table,
+-	.suspend		= usb_serial_suspend,
+-	.resume			= usb_serial_resume,
+-	.supports_autosuspend	= true,
+ };
+ 
+ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
+diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
+index f298ddaac684..7b7771491a64 100644
+--- a/drivers/usb/serial/sierra.c
++++ b/drivers/usb/serial/sierra.c
+@@ -1055,11 +1055,8 @@ static struct usb_driver sierra_driver = {
+ 	.name       = "sierra",
+ 	.probe      = usb_serial_probe,
+ 	.disconnect = usb_serial_disconnect,
+-	.suspend    = usb_serial_suspend,
+-	.resume     = usb_serial_resume,
+ 	.reset_resume = sierra_reset_resume,
+ 	.id_table   = id_table,
+-	.supports_autosuspend =	1,
+ };
+ 
+ static struct usb_serial_driver sierra_device = {
+diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
+index cda513bb01c7..9820492cf885 100644
+--- a/drivers/usb/serial/ssu100.c
++++ b/drivers/usb/serial/ssu100.c
+@@ -68,9 +68,6 @@ static struct usb_driver ssu100_driver = {
+ 	.probe			       = usb_serial_probe,
+ 	.disconnect		       = usb_serial_disconnect,
+ 	.id_table		       = id_table,
+-	.suspend		       = usb_serial_suspend,
+-	.resume			       = usb_serial_resume,
+-	.supports_autosuspend	       = 1,
+ };
+ 
+ struct ssu100_port_private {

commit 5cbe61c5aff0a8ada691eb8b07dbfb55c303f640
+Author: Alan Stern 
+Date:   Mon May 7 11:20:06 2012 -0400
+
+    usb-serial: ftdi_sio: fix oops during autosuspend
+    
+    This patch (as1550) fixes a bug in the usb-serial core that affects
+    the ftdi_sio driver and most likely others as well.  The core
+    implements suspend and resume routines, but it doesn't store pointers
+    to those routines in the usb_driver structures that it registers,
+    even though it does set those drivers' supports_autosuspend flag.  The
+    end result is that when one of these devices is autosuspended, we try
+    to call through a NULL pointer.
+    
+    The patch fixes the problem by setting the suspend and resume method
+    pointers to the appropriate routines in the USB serial core, along
+    with the supports_autosuspend field, in each driver as it is
+    registered.
+    
+    This should be back-ported to all the stable kernels that have the new
+    usb_serial_register_drivers() interface.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Frank Schäfer 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
+index 906f06e97fde..f7b263e237ef 100644
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -1336,7 +1336,6 @@ static int usb_serial_register(struct usb_serial_driver *driver)
+ 				driver->description);
+ 		return -EINVAL;
+ 	}
+-	driver->usb_driver->supports_autosuspend = 1;
+ 
+ 	/* Add this device to our list of devices */
+ 	mutex_lock(&table_lock);
+@@ -1371,7 +1370,7 @@ static void usb_serial_deregister(struct usb_serial_driver *device)
+  * @serial_drivers: NULL-terminated array of pointers to drivers to be registered
+  *
+  * Registers @udriver and all the drivers in the @serial_drivers array.
+- * Automatically fills in the .no_dynamic_id field in @udriver and
++ * Automatically fills in the .no_dynamic_id and PM fields in @udriver and
+  * the .usb_driver field in each serial driver.
+  */
+ int usb_serial_register_drivers(struct usb_driver *udriver,
+@@ -1390,11 +1389,17 @@ int usb_serial_register_drivers(struct usb_driver *udriver,
+ 	 * the serial drivers are registered, because the probe would
+ 	 * simply fail for lack of a matching serial driver.
+ 	 * Therefore save off udriver's id_table until we are all set.
++	 *
++	 * Suspend/resume support is implemented in the usb-serial core,
++	 * so fill in the PM-related fields in udriver.
+ 	 */
+ 	saved_id_table = udriver->id_table;
+ 	udriver->id_table = NULL;
+ 
+ 	udriver->no_dynamic_id = 1;
++	udriver->supports_autosuspend = 1;
++	udriver->suspend = usb_serial_suspend;
++	udriver->resume = usb_serial_resume;
+ 	rc = usb_register(udriver);
+ 	if (rc)
+ 		return rc;

commit ebf20de453042c066a289b90dd14d59de03dba2f
+Author: Alan Stern 
+Date:   Tue May 1 11:28:49 2012 -0400
+
+    EHCI: update PM methods in ehci-tegra.c
+    
+    This patch (as1547) rearranges the Power Management parts of the
+    ehci-tegra driver to match the conventions used in other EHCI platform
+    drivers.  In particular, the controller should not be powered down by
+    the root hub's suspend routine; the controller's power level should be
+    managed by the controller's own PM methods.
+    
+    The end result of the patch is that the standard ehci_bus_suspend()
+    and ehci_bus_resume() methods can be used instead of special-purpose
+    routines.  The driver now uses the standard dev_pm_ops methods instead
+    of legacy power management.  Since there is no supported wakeup
+    mechanism for the controller, runtime suspend is forbidden by default
+    (this can be overridden via sysfs, if desired).
+    
+    These adjustments are needed in order to make ehci-tegra compatible
+    with recent changes to the USB core.  The core now checks the root
+    hub's status following bus suspend; if the controller is automatically
+    powered down during bus suspend then the check will fail and the root
+    hub will be resumed immediately.  Doing the controller power-down in a
+    separate method avoids this problem.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Stephen Warren 
+    Tested-by: Stephen Warren 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
+index 86183366647f..73f3525e6921 100644
+--- a/drivers/usb/host/ehci-tegra.c
++++ b/drivers/usb/host/ehci-tegra.c
+@@ -24,6 +24,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ #include 
+@@ -37,9 +38,7 @@ struct tegra_ehci_hcd {
+ 	struct clk *emc_clk;
+ 	struct usb_phy *transceiver;
+ 	int host_resumed;
+-	int bus_suspended;
+ 	int port_resuming;
+-	int power_down_on_bus_suspend;
+ 	enum tegra_usb_phy_port_speed port_speed;
+ };
+ 
+@@ -273,120 +272,6 @@ static void tegra_ehci_restart(struct usb_hcd *hcd)
+ 	up_write(&ehci_cf_port_reset_rwsem);
+ }
+ 
+-static int tegra_usb_suspend(struct usb_hcd *hcd)
+-{
+-	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
+-	struct ehci_regs __iomem *hw = tegra->ehci->regs;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&tegra->ehci->lock, flags);
+-
+-	tegra->port_speed = (readl(&hw->port_status[0]) >> 26) & 0x3;
+-	ehci_halt(tegra->ehci);
+-	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+-
+-	spin_unlock_irqrestore(&tegra->ehci->lock, flags);
+-
+-	tegra_ehci_power_down(hcd);
+-	return 0;
+-}
+-
+-static int tegra_usb_resume(struct usb_hcd *hcd)
+-{
+-	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
+-	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
+-	struct ehci_regs __iomem *hw = ehci->regs;
+-	unsigned long val;
+-
+-	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+-	tegra_ehci_power_up(hcd);
+-
+-	if (tegra->port_speed > TEGRA_USB_PHY_PORT_SPEED_HIGH) {
+-		/* Wait for the phy to detect new devices
+-		 * before we restart the controller */
+-		msleep(10);
+-		goto restart;
+-	}
+-
+-	/* Force the phy to keep data lines in suspend state */
+-	tegra_ehci_phy_restore_start(tegra->phy, tegra->port_speed);
+-
+-	/* Enable host mode */
+-	tdi_reset(ehci);
+-
+-	/* Enable Port Power */
+-	val = readl(&hw->port_status[0]);
+-	val |= PORT_POWER;
+-	writel(val, &hw->port_status[0]);
+-	udelay(10);
+-
+-	/* Check if the phy resume from LP0. When the phy resume from LP0
+-	 * USB register will be reset. */
+-	if (!readl(&hw->async_next)) {
+-		/* Program the field PTC based on the saved speed mode */
+-		val = readl(&hw->port_status[0]);
+-		val &= ~PORT_TEST(~0);
+-		if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_HIGH)
+-			val |= PORT_TEST_FORCE;
+-		else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_FULL)
+-			val |= PORT_TEST(6);
+-		else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW)
+-			val |= PORT_TEST(7);
+-		writel(val, &hw->port_status[0]);
+-		udelay(10);
+-
+-		/* Disable test mode by setting PTC field to NORMAL_OP */
+-		val = readl(&hw->port_status[0]);
+-		val &= ~PORT_TEST(~0);
+-		writel(val, &hw->port_status[0]);
+-		udelay(10);
+-	}
+-
+-	/* Poll until CCS is enabled */
+-	if (handshake(ehci, &hw->port_status[0], PORT_CONNECT,
+-						 PORT_CONNECT, 2000)) {
+-		pr_err("%s: timeout waiting for PORT_CONNECT\n", __func__);
+-		goto restart;
+-	}
+-
+-	/* Poll until PE is enabled */
+-	if (handshake(ehci, &hw->port_status[0], PORT_PE,
+-						 PORT_PE, 2000)) {
+-		pr_err("%s: timeout waiting for USB_PORTSC1_PE\n", __func__);
+-		goto restart;
+-	}
+-
+-	/* Clear the PCI status, to avoid an interrupt taken upon resume */
+-	val = readl(&hw->status);
+-	val |= STS_PCD;
+-	writel(val, &hw->status);
+-
+-	/* Put controller in suspend mode by writing 1 to SUSP bit of PORTSC */
+-	val = readl(&hw->port_status[0]);
+-	if ((val & PORT_POWER) && (val & PORT_PE)) {
+-		val |= PORT_SUSPEND;
+-		writel(val, &hw->port_status[0]);
+-
+-		/* Wait until port suspend completes */
+-		if (handshake(ehci, &hw->port_status[0], PORT_SUSPEND,
+-							 PORT_SUSPEND, 1000)) {
+-			pr_err("%s: timeout waiting for PORT_SUSPEND\n",
+-								__func__);
+-			goto restart;
+-		}
+-	}
+-
+-	tegra_ehci_phy_restore_end(tegra->phy);
+-	return 0;
+-
+-restart:
+-	if (tegra->port_speed <= TEGRA_USB_PHY_PORT_SPEED_HIGH)
+-		tegra_ehci_phy_restore_end(tegra->phy);
+-
+-	tegra_ehci_restart(hcd);
+-	return 0;
+-}
+-
+ static void tegra_ehci_shutdown(struct usb_hcd *hcd)
+ {
+ 	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
+@@ -434,36 +319,6 @@ static int tegra_ehci_setup(struct usb_hcd *hcd)
+ 	return retval;
+ }
+ 
+-#ifdef CONFIG_PM
+-static int tegra_ehci_bus_suspend(struct usb_hcd *hcd)
+-{
+-	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
+-	int error_status = 0;
+-
+-	error_status = ehci_bus_suspend(hcd);
+-	if (!error_status && tegra->power_down_on_bus_suspend) {
+-		tegra_usb_suspend(hcd);
+-		tegra->bus_suspended = 1;
+-	}
+-
+-	return error_status;
+-}
+-
+-static int tegra_ehci_bus_resume(struct usb_hcd *hcd)
+-{
+-	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
+-
+-	if (tegra->bus_suspended && tegra->power_down_on_bus_suspend) {
+-		tegra_usb_resume(hcd);
+-		tegra->bus_suspended = 0;
+-	}
+-
+-	tegra_usb_phy_preresume(tegra->phy);
+-	tegra->port_resuming = 1;
+-	return ehci_bus_resume(hcd);
+-}
+-#endif
+-
+ struct temp_buffer {
+ 	void *kmalloc_ptr;
+ 	void *old_xfer_buffer;
+@@ -574,8 +429,8 @@ static const struct hc_driver tegra_ehci_hc_driver = {
+ 	.hub_control		= tegra_ehci_hub_control,
+ 	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+ #ifdef CONFIG_PM
+-	.bus_suspend		= tegra_ehci_bus_suspend,
+-	.bus_resume		= tegra_ehci_bus_resume,
++	.bus_suspend		= ehci_bus_suspend,
++	.bus_resume		= ehci_bus_resume,
+ #endif
+ 	.relinquish_port	= ehci_relinquish_port,
+ 	.port_handed_over	= ehci_port_handed_over,
+@@ -608,6 +463,183 @@ static int setup_vbus_gpio(struct platform_device *pdev)
+ 	return err;
+ }
+ 
++#ifdef CONFIG_PM
++
++static int controller_suspend(struct device *dev)
++{
++	struct tegra_ehci_hcd *tegra =
++			platform_get_drvdata(to_platform_device(dev));
++	struct ehci_hcd	*ehci = tegra->ehci;
++	struct usb_hcd *hcd = ehci_to_hcd(ehci);
++	struct ehci_regs __iomem *hw = ehci->regs;
++	unsigned long flags;
++
++	if (time_before(jiffies, ehci->next_statechange))
++		msleep(10);
++
++	spin_lock_irqsave(&ehci->lock, flags);
++
++	tegra->port_speed = (readl(&hw->port_status[0]) >> 26) & 0x3;
++	ehci_halt(ehci);
++	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
++
++	spin_unlock_irqrestore(&ehci->lock, flags);
++
++	tegra_ehci_power_down(hcd);
++	return 0;
++}
++
++static int controller_resume(struct device *dev)
++{
++	struct tegra_ehci_hcd *tegra =
++			platform_get_drvdata(to_platform_device(dev));
++	struct ehci_hcd	*ehci = tegra->ehci;
++	struct usb_hcd *hcd = ehci_to_hcd(ehci);
++	struct ehci_regs __iomem *hw = ehci->regs;
++	unsigned long val;
++
++	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
++	tegra_ehci_power_up(hcd);
++
++	if (tegra->port_speed > TEGRA_USB_PHY_PORT_SPEED_HIGH) {
++		/* Wait for the phy to detect new devices
++		 * before we restart the controller */
++		msleep(10);
++		goto restart;
++	}
++
++	/* Force the phy to keep data lines in suspend state */
++	tegra_ehci_phy_restore_start(tegra->phy, tegra->port_speed);
++
++	/* Enable host mode */
++	tdi_reset(ehci);
++
++	/* Enable Port Power */
++	val = readl(&hw->port_status[0]);
++	val |= PORT_POWER;
++	writel(val, &hw->port_status[0]);
++	udelay(10);
++
++	/* Check if the phy resume from LP0. When the phy resume from LP0
++	 * USB register will be reset. */
++	if (!readl(&hw->async_next)) {
++		/* Program the field PTC based on the saved speed mode */
++		val = readl(&hw->port_status[0]);
++		val &= ~PORT_TEST(~0);
++		if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_HIGH)
++			val |= PORT_TEST_FORCE;
++		else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_FULL)
++			val |= PORT_TEST(6);
++		else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW)
++			val |= PORT_TEST(7);
++		writel(val, &hw->port_status[0]);
++		udelay(10);
++
++		/* Disable test mode by setting PTC field to NORMAL_OP */
++		val = readl(&hw->port_status[0]);
++		val &= ~PORT_TEST(~0);
++		writel(val, &hw->port_status[0]);
++		udelay(10);
++	}
++
++	/* Poll until CCS is enabled */
++	if (handshake(ehci, &hw->port_status[0], PORT_CONNECT,
++						 PORT_CONNECT, 2000)) {
++		pr_err("%s: timeout waiting for PORT_CONNECT\n", __func__);
++		goto restart;
++	}
++
++	/* Poll until PE is enabled */
++	if (handshake(ehci, &hw->port_status[0], PORT_PE,
++						 PORT_PE, 2000)) {
++		pr_err("%s: timeout waiting for USB_PORTSC1_PE\n", __func__);
++		goto restart;
++	}
++
++	/* Clear the PCI status, to avoid an interrupt taken upon resume */
++	val = readl(&hw->status);
++	val |= STS_PCD;
++	writel(val, &hw->status);
++
++	/* Put controller in suspend mode by writing 1 to SUSP bit of PORTSC */
++	val = readl(&hw->port_status[0]);
++	if ((val & PORT_POWER) && (val & PORT_PE)) {
++		val |= PORT_SUSPEND;
++		writel(val, &hw->port_status[0]);
++
++		/* Wait until port suspend completes */
++		if (handshake(ehci, &hw->port_status[0], PORT_SUSPEND,
++							 PORT_SUSPEND, 1000)) {
++			pr_err("%s: timeout waiting for PORT_SUSPEND\n",
++								__func__);
++			goto restart;
++		}
++	}
++
++	tegra_ehci_phy_restore_end(tegra->phy);
++	goto done;
++
++ restart:
++	if (tegra->port_speed <= TEGRA_USB_PHY_PORT_SPEED_HIGH)
++		tegra_ehci_phy_restore_end(tegra->phy);
++
++	tegra_ehci_restart(hcd);
++
++ done:
++	tegra_usb_phy_preresume(tegra->phy);
++	tegra->port_resuming = 1;
++	return 0;
++}
++
++static int tegra_ehci_suspend(struct device *dev)
++{
++	struct tegra_ehci_hcd *tegra =
++			platform_get_drvdata(to_platform_device(dev));
++	struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
++	int rc = 0;
++
++	/*
++	 * When system sleep is supported and USB controller wakeup is
++	 * implemented: If the controller is runtime-suspended and the
++	 * wakeup setting needs to be changed, call pm_runtime_resume().
++	 */
++	if (HCD_HW_ACCESSIBLE(hcd))
++		rc = controller_suspend(dev);
++	return rc;
++}
++
++static int tegra_ehci_resume(struct device *dev)
++{
++	int rc;
++
++	rc = controller_resume(dev);
++	if (rc == 0) {
++		pm_runtime_disable(dev);
++		pm_runtime_set_active(dev);
++		pm_runtime_enable(dev);
++	}
++	return rc;
++}
++
++static int tegra_ehci_runtime_suspend(struct device *dev)
++{
++	return controller_suspend(dev);
++}
++
++static int tegra_ehci_runtime_resume(struct device *dev)
++{
++	return controller_resume(dev);
++}
++
++static const struct dev_pm_ops tegra_ehci_pm_ops = {
++	.suspend	= tegra_ehci_suspend,
++	.resume		= tegra_ehci_resume,
++	.runtime_suspend = tegra_ehci_runtime_suspend,
++	.runtime_resume	= tegra_ehci_runtime_resume,
++};
++
++#endif
++
+ static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32);
+ 
+ static int tegra_ehci_probe(struct platform_device *pdev)
+@@ -722,7 +754,6 @@ static int tegra_ehci_probe(struct platform_device *pdev)
+ 	}
+ 
+ 	tegra->host_resumed = 1;
+-	tegra->power_down_on_bus_suspend = pdata->power_down_on_bus_suspend;
+ 	tegra->ehci = hcd_to_ehci(hcd);
+ 
+ 	irq = platform_get_irq(pdev, 0);
+@@ -746,6 +777,14 @@ static int tegra_ehci_probe(struct platform_device *pdev)
+ 		goto fail;
+ 	}
+ 
++	pm_runtime_set_active(&pdev->dev);
++	pm_runtime_get_noresume(&pdev->dev);
++
++	/* Don't skip the pm_runtime_forbid call if wakeup isn't working */
++	/* if (!pdata->power_down_on_bus_suspend) */
++		pm_runtime_forbid(&pdev->dev);
++	pm_runtime_enable(&pdev->dev);
++	pm_runtime_put_sync(&pdev->dev);
+ 	return err;
+ 
+ fail:
+@@ -772,33 +811,6 @@ static int tegra_ehci_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-#ifdef CONFIG_PM
+-static int tegra_ehci_resume(struct platform_device *pdev)
+-{
+-	struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
+-	struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
+-
+-	if (tegra->bus_suspended)
+-		return 0;
+-
+-	return tegra_usb_resume(hcd);
+-}
+-
+-static int tegra_ehci_suspend(struct platform_device *pdev, pm_message_t state)
+-{
+-	struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
+-	struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
+-
+-	if (tegra->bus_suspended)
+-		return 0;
+-
+-	if (time_before(jiffies, tegra->ehci->next_statechange))
+-		msleep(10);
+-
+-	return tegra_usb_suspend(hcd);
+-}
+-#endif
+-
+ static int tegra_ehci_remove(struct platform_device *pdev)
+ {
+ 	struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
+@@ -807,6 +819,10 @@ static int tegra_ehci_remove(struct platform_device *pdev)
+ 	if (tegra == NULL || hcd == NULL)
+ 		return -EINVAL;
+ 
++	pm_runtime_get_sync(&pdev->dev);
++	pm_runtime_disable(&pdev->dev);
++	pm_runtime_put_noidle(&pdev->dev);
++
+ #ifdef CONFIG_USB_OTG_UTILS
+ 	if (tegra->transceiver) {
+ 		otg_set_host(tegra->transceiver->otg, NULL);
+@@ -847,13 +863,12 @@ static struct of_device_id tegra_ehci_of_match[] __devinitdata = {
+ static struct platform_driver tegra_ehci_driver = {
+ 	.probe		= tegra_ehci_probe,
+ 	.remove		= tegra_ehci_remove,
+-#ifdef CONFIG_PM
+-	.suspend	= tegra_ehci_suspend,
+-	.resume		= tegra_ehci_resume,
+-#endif
+ 	.shutdown	= tegra_ehci_hcd_shutdown,
+ 	.driver		= {
+ 		.name	= "tegra-ehci",
+ 		.of_match_table = tegra_ehci_of_match,
++#ifdef CONFIG_PM
++		.pm	= &tegra_ehci_pm_ops,
++#endif
+ 	}
+ };

commit 320cd1e750f1bf3e47eb41209dcb2be07264cb76
+Author: Alan Stern 
+Date:   Thu Apr 26 11:31:57 2012 -0400
+
+    usb: gadget: udc-core: fix incompatibility with dummy-hcd
+    
+    This patch (as1548) fixes a recently-introduced incompatibility
+    between the UDC core and the dummy-hcd driver.  Commit
+    8ae8090c82eb407267001f75b3d256b3bd4ae691 (usb: gadget: udc-core: fix
+    asymmetric calls in remove_driver) moved the usb_gadget_udc_stop()
+    call in usb_gadget_remove_driver() below the usb_gadget_disconnect()
+    call.
+    
+    As a result, usb_gadget_disconnect() gets called at a time when the
+    gadget driver believes it has been unbound but dummy-hcd believes
+    it has not.  A nasty error ensues when dummy-hcd calls the gadget
+    driver's disconnect method a second time.
+    
+    To fix the problem, this patch moves the gadget driver's unbind
+    notification after the usb_gadget_disconnect() call.  Now nothing
+    happens between the two unbind notifications, so nothing goes wrong.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Alexander Shishkin 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c
+index df1bd87232dd..e5e44f8cde9a 100644
+--- a/drivers/usb/gadget/udc-core.c
++++ b/drivers/usb/gadget/udc-core.c
+@@ -263,8 +263,8 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
+ 
+ 	if (udc_is_newstyle(udc)) {
+ 		udc->driver->disconnect(udc->gadget);
+-		udc->driver->unbind(udc->gadget);
+ 		usb_gadget_disconnect(udc->gadget);
++		udc->driver->unbind(udc->gadget);
+ 		usb_gadget_udc_stop(udc->gadget, udc->driver);
+ 	} else {
+ 		usb_gadget_stop(udc->gadget, udc->driver);

commit 151b61284776be2d6f02d48c23c3625678960b97
+Author: Alan Stern 
+Date:   Tue Apr 24 14:07:22 2012 -0400
+
+    USB: EHCI: fix crash during suspend on ASUS computers
+    
+    This patch (as1545) fixes a problem affecting several ASUS computers:
+    The machine crashes or corrupts memory when going into suspend if the
+    ehci-hcd driver is bound to any controllers.  Users have been forced
+    to unbind or unload ehci-hcd before putting their systems to sleep.
+    
+    After extensive testing, it was determined that the machines don't
+    like going into suspend when any EHCI controllers are in the PCI D3
+    power state.  Presumably this is a firmware bug, but there's nothing
+    we can do about it except to avoid putting the controllers in D3
+    during system sleep.
+    
+    The patch adds a new flag to indicate whether the problem is present,
+    and avoids changing the controller's power state if the flag is set.
+    Runtime suspend is unaffected; this matters only for system suspend.
+    However as a side effect, the controller will not respond to remote
+    wakeup requests while the system is asleep.  Hence USB wakeup is not
+    functional -- but of course, this is already true in the current state
+    of affairs.
+    
+    This fixes Bugzilla #42728.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Steven Rostedt 
+    Tested-by: Andrey Rahmatullin 
+    Tested-by: Oleksij Rempel (fishor) 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index 622b4a48e732..57ed9e400c06 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -493,6 +493,15 @@ static int hcd_pci_suspend_noirq(struct device *dev)
+ 
+ 	pci_save_state(pci_dev);
+ 
++	/*
++	 * Some systems crash if an EHCI controller is in D3 during
++	 * a sleep transition.  We have to leave such controllers in D0.
++	 */
++	if (hcd->broken_pci_sleep) {
++		dev_dbg(dev, "Staying in PCI D0\n");
++		return retval;
++	}
++
+ 	/* If the root hub is dead rather than suspended, disallow remote
+ 	 * wakeup.  usb_hc_died() should ensure that both hosts are marked as
+ 	 * dying, so we only need to check the primary roothub.
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index 01bb7241d6ef..fe8dc069164e 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -144,6 +144,14 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 			hcd->has_tt = 1;
+ 			tdi_reset(ehci);
+ 		}
++		if (pdev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK) {
++			/* EHCI #1 or #2 on 6 Series/C200 Series chipset */
++			if (pdev->device == 0x1c26 || pdev->device == 0x1c2d) {
++				ehci_info(ehci, "broken D3 during system sleep on ASUS\n");
++				hcd->broken_pci_sleep = 1;
++				device_set_wakeup_capable(&pdev->dev, false);
++			}
++		}
+ 		break;
+ 	case PCI_VENDOR_ID_TDI:
+ 		if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
+diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
+index 5de415707c23..d28cc78a38e4 100644
+--- a/include/linux/usb/hcd.h
++++ b/include/linux/usb/hcd.h
+@@ -126,6 +126,8 @@ struct usb_hcd {
+ 	unsigned		wireless:1;	/* Wireless USB HCD */
+ 	unsigned		authorized_default:1;
+ 	unsigned		has_tt:1;	/* Integrated TT in root hub */
++	unsigned		broken_pci_sleep:1;	/* Don't put the
++			controller in PCI-D3 for system sleep */
+ 
+ 	unsigned int		irq;		/* irq allocated */
+ 	void __iomem		*regs;		/* device memory/io */

commit 3d9545cc375d117554a9b35dfddadf9189c62775
+Author: Alan Stern 
+Date:   Mon Apr 23 13:54:36 2012 -0400
+
+    EHCI: maintain the ehci->command value properly
+    
+    The ehci-hcd driver is a little haphazard about keeping track of the
+    state of the USBCMD register.  The ehci->command field is supposed to
+    hold the register's value (apart from a few special bits) at all
+    times, but it isn't maintained properly.
+    
+    This patch (as1543) cleans up the situation.  It keeps ehci->command
+    up-to-date, and uses that value rather than reading the register from
+    the hardware whenever possible.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
+index 680e1a31fb87..7561966fbdc4 100644
+--- a/drivers/usb/host/ehci-dbg.c
++++ b/drivers/usb/host/ehci-dbg.c
+@@ -1025,10 +1025,8 @@ static ssize_t debug_lpm_write(struct file *file, const char __user *user_buf,
+ 		if (strict_strtoul(buf + 5, 16, &hird))
+ 			return -EINVAL;
+ 		printk(KERN_INFO "setting hird %s %lu\n", buf + 6, hird);
+-		temp = ehci_readl(ehci, &ehci->regs->command);
+-		temp &= ~CMD_HIRD;
+-		temp |= hird << 24;
+-		ehci_writel(ehci, temp, &ehci->regs->command);
++		ehci->command = (ehci->command & ~CMD_HIRD) | (hird << 24);
++		ehci_writel(ehci, ehci->command, &ehci->regs->command);
+ 	} else if (strncmp(buf, "disable", 7) == 0) {
+ 		if (strict_strtoul(buf + 8, 10, &port))
+ 			return -EINVAL;
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index a87c0573c860..de1e689d3df0 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -226,8 +226,13 @@ static int ehci_halt (struct ehci_hcd *ehci)
+ 	if ((temp & STS_HALT) != 0)
+ 		return 0;
+ 
++	/*
++	 * This routine gets called during probe before ehci->command
++	 * has been initialized, so we can't rely on its value.
++	 */
++	ehci->command &= ~CMD_RUN;
+ 	temp = ehci_readl(ehci, &ehci->regs->command);
+-	temp &= ~CMD_RUN;
++	temp &= ~(CMD_RUN | CMD_IAAD);
+ 	ehci_writel(ehci, temp, &ehci->regs->command);
+ 	return handshake (ehci, &ehci->regs->status,
+ 			  STS_HALT, STS_HALT, 16 * 125);
+@@ -347,6 +352,7 @@ static int ehci_reset (struct ehci_hcd *ehci)
+ 	if (ehci->debug)
+ 		dbgp_external_startup();
+ 
++	ehci->command = ehci_readl(ehci, &ehci->regs->command);
+ 	ehci->port_c_suspend = ehci->suspended_ports =
+ 			ehci->resuming_ports = 0;
+ 	return retval;
+@@ -363,16 +369,14 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
+ #endif
+ 
+ 	/* wait for any schedule enables/disables to take effect */
+-	temp = ehci_readl(ehci, &ehci->regs->command) << 10;
+-	temp &= STS_ASS | STS_PSS;
++	temp = (ehci->command << 10) & (STS_ASS | STS_PSS);
+ 	if (handshake_on_error_set_halt(ehci, &ehci->regs->status,
+ 					STS_ASS | STS_PSS, temp, 16 * 125))
+ 		return;
+ 
+ 	/* then disable anything that's still active */
+-	temp = ehci_readl(ehci, &ehci->regs->command);
+-	temp &= ~(CMD_ASE | CMD_IAAD | CMD_PSE);
+-	ehci_writel(ehci, temp, &ehci->regs->command);
++	ehci->command &= ~(CMD_ASE | CMD_PSE);
++	ehci_writel(ehci, ehci->command, &ehci->regs->command);
+ 
+ 	/* hardware can take 16 microframes to turn off ... */
+ 	handshake_on_error_set_halt(ehci, &ehci->regs->status,
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 402e766df2fe..fc9e7cc6ac9b 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -233,7 +233,6 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 	/* stop schedules, clean any completed work */
+ 	if (ehci->rh_state == EHCI_RH_RUNNING)
+ 		ehci_quiesce (ehci);
+-	ehci->command = ehci_readl(ehci, &ehci->regs->command);
+ 	ehci_work(ehci);
+ 
+ 	/* Unlike other USB host controller types, EHCI doesn't have
+@@ -374,6 +373,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 	ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next);
+ 
+ 	/* restore CMD_RUN, framelist size, and irq threshold */
++	ehci->command |= CMD_RUN;
+ 	ehci_writel(ehci, ehci->command, &ehci->regs->command);
+ 	ehci->rh_state = EHCI_RH_RUNNING;
+ 
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 36ca5077cdf7..13f4f980841a 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -981,14 +981,12 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	head = ehci->async;
+ 	timer_action_done (ehci, TIMER_ASYNC_OFF);
+ 	if (!head->qh_next.qh) {
+-		u32	cmd = ehci_readl(ehci, &ehci->regs->command);
+-
+-		if (!(cmd & CMD_ASE)) {
++		if (!(ehci->command & CMD_ASE)) {
+ 			/* in case a clear of CMD_ASE didn't take yet */
+ 			(void)handshake(ehci, &ehci->regs->status,
+ 					STS_ASS, 0, 150);
+-			cmd |= CMD_ASE;
+-			ehci_writel(ehci, cmd, &ehci->regs->command);
++			ehci->command |= CMD_ASE;
++			ehci_writel(ehci, ehci->command, &ehci->regs->command);
+ 			/* posted write need not be known to HC yet ... */
+ 		}
+ 	}
+@@ -1204,7 +1202,6 @@ static void end_unlink_async (struct ehci_hcd *ehci)
+ 
+ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ {
+-	int		cmd = ehci_readl(ehci, &ehci->regs->command);
+ 	struct ehci_qh	*prev;
+ 
+ #ifdef DEBUG
+@@ -1222,8 +1219,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		if (ehci->rh_state != EHCI_RH_HALTED
+ 				&& !ehci->reclaim) {
+ 			/* ... and CMD_IAAD clear */
+-			ehci_writel(ehci, cmd & ~CMD_ASE,
+-				    &ehci->regs->command);
++			ehci->command &= ~CMD_ASE;
++			ehci_writel(ehci, ehci->command, &ehci->regs->command);
+ 			wmb ();
+ 			// handshake later, if we need to
+ 			timer_action_done (ehci, TIMER_ASYNC_OFF);
+@@ -1253,8 +1250,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		return;
+ 	}
+ 
+-	cmd |= CMD_IAAD;
+-	ehci_writel(ehci, cmd, &ehci->regs->command);
++	ehci_writel(ehci, ehci->command | CMD_IAAD, &ehci->regs->command);
+ 	(void)ehci_readl(ehci, &ehci->regs->command);
+ 	iaa_watchdog_start(ehci);
+ }
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index a60679cbbf85..ffe8fc3bc7ef 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -481,7 +481,6 @@ static int tt_no_collision (
+ 
+ static int enable_periodic (struct ehci_hcd *ehci)
+ {
+-	u32	cmd;
+ 	int	status;
+ 
+ 	if (ehci->periodic_sched++)
+@@ -497,8 +496,8 @@ static int enable_periodic (struct ehci_hcd *ehci)
+ 		return status;
+ 	}
+ 
+-	cmd = ehci_readl(ehci, &ehci->regs->command) | CMD_PSE;
+-	ehci_writel(ehci, cmd, &ehci->regs->command);
++	ehci->command |= CMD_PSE;
++	ehci_writel(ehci, ehci->command, &ehci->regs->command);
+ 	/* posted write ... PSS happens later */
+ 
+ 	/* make sure ehci_work scans these */
+@@ -511,7 +510,6 @@ static int enable_periodic (struct ehci_hcd *ehci)
+ 
+ static int disable_periodic (struct ehci_hcd *ehci)
+ {
+-	u32	cmd;
+ 	int	status;
+ 
+ 	if (--ehci->periodic_sched)
+@@ -537,8 +535,8 @@ static int disable_periodic (struct ehci_hcd *ehci)
+ 		return status;
+ 	}
+ 
+-	cmd = ehci_readl(ehci, &ehci->regs->command) & ~CMD_PSE;
+-	ehci_writel(ehci, cmd, &ehci->regs->command);
++	ehci->command &= ~CMD_PSE;
++	ehci_writel(ehci, ehci->command, &ehci->regs->command);
+ 	/* posted write ... */
+ 
+ 	free_cached_lists(ehci);

commit 6feff1b92bedab133c5835e510d11f62e843b257
+Author: Alan Stern 
+Date:   Tue Apr 17 15:23:25 2012 -0400
+
+    EHCI: don't try to clear the IAAD bit
+    
+    This patch (as1541) corrects a small mistake in ehci-hcd.  The IAAD
+    (Interrupt on Async Advance Doorbell) bit in the USBCMD register is
+    designed, as its name says, to act as a "doorbell".  That is, the
+    driver activates the bit by setting it to 1, and the hardware
+    deactivates it later by setting it back to 0.  The driver cannot clear
+    the bit by writing a 0 to it; such writes are simply ignored.
+    
+    Therefore there is no reason for ehci-hcd to try to clear the bit.
+    The patch removes the two instances where such attempts occur.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 057cdda7a489..343f40c23b5f 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -415,9 +415,6 @@ static void ehci_iaa_watchdog(unsigned long param)
+ 		 * CMD_IAAD when it sets STS_IAA.)
+ 		 */
+ 		cmd = ehci_readl(ehci, &ehci->regs->command);
+-		if (cmd & CMD_IAAD)
+-			ehci_writel(ehci, cmd & ~CMD_IAAD,
+-					&ehci->regs->command);
+ 
+ 		/* If IAA is set here it either legitimately triggered
+ 		 * before we cleared IAAD above (but _way_ late, so we'll
+@@ -887,11 +884,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 	/* complete the unlinking of some qh [4.15.2.3] */
+ 	if (status & STS_IAA) {
+ 		/* guard against (alleged) silicon errata */
+-		if (cmd & CMD_IAAD) {
+-			ehci_writel(ehci, cmd & ~CMD_IAAD,
+-					&ehci->regs->command);
++		if (cmd & CMD_IAAD)
+ 			ehci_dbg(ehci, "IAA with IAAD still set?\n");
+-		}
+ 		if (ehci->reclaim) {
+ 			COUNT(ehci->stats.reclaim);
+ 			end_unlink_async(ehci);

commit 2fbe2bf1fd37f9d99950bd8d8093623cf22cf08b
+Author: Alan Stern 
+Date:   Wed Apr 18 11:33:00 2012 -0400
+
+    EHCI: always clear the STS_FLR status bit
+    
+    This patch (as1544) fixes a problem affecting some EHCI controllers.
+    They can generate interrupts whenever the STS_FLR status bit is turned
+    on, even though that bit is masked out in the Interrupt Enable
+    register.
+    
+    Since the driver doesn't use STS_FLR anyway, the patch changes the
+    interrupt routine to clear that bit whenever it is set, rather than
+    leaving it alone.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Tomoya MORINAGA 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 95ca07a8e1b5..4a3bc5b7a06f 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -858,8 +858,13 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 		goto dead;
+ 	}
+ 
++	/*
++	 * We don't use STS_FLR, but some controllers don't like it to
++	 * remain on, so mask it out along with the other status bits.
++	 */
++	masked_status = status & (INTR_MASK | STS_FLR);
++
+ 	/* Shared IRQ? */
+-	masked_status = status & INTR_MASK;
+ 	if (!masked_status || unlikely(ehci->rh_state == EHCI_RH_HALTED)) {
+ 		spin_unlock(&ehci->lock);
+ 		return IRQ_NONE;

commit dc75ce9d929aabeb0843a6b1a4ab320e58ba1597
+Author: Alan Stern 
+Date:   Tue Apr 17 15:24:15 2012 -0400
+
+    EHCI: fix criterion for resuming the root hub
+    
+    This patch (as1542) changes the criterion ehci-hcd uses to tell when
+    it needs to resume the controller's root hub.  A resume is needed when
+    a port status change is detected, obviously, but only if the root hub
+    is currently suspended.
+    
+    Right now the driver tests whether the root hub is running, and that
+    is not the correct test.  In particular, if the controller has died
+    then the root hub should not be restarted.  In addition, some buggy
+    hardware occasionally requires the root hub to be running and
+    sending out SOF packets even while it is nominally supposed to be
+    suspended.
+    
+    In the end, the test needs to be changed.  Rather than checking whether
+    the root hub is currently running, the driver will now check whether
+    the root hub is currently suspended.  This will yield the correct
+    behavior in all cases.
+    
+    Signed-off-by: Alan Stern 
+    CC: Peter Chen 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 806cc95317aa..95ca07a8e1b5 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -910,7 +910,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 		pcd_status = status;
+ 
+ 		/* resume root hub? */
+-		if (!(cmd & CMD_RUN))
++		if (ehci->rh_state == EHCI_RH_SUSPENDED)
+ 			usb_hcd_resume_root_hub(hcd);
+ 
+ 		/* get per-port change detect bits */

commit 8963c487a80b4688c9e68dcc504a90074aacc145
+Author: Alan Stern 
+Date:   Tue Apr 17 15:22:39 2012 -0400
+
+    USB: fix deadlock in bConfigurationValue attribute method
+    
+    This patch (as154) fixes a self-deadlock that occurs when userspace
+    writes to the bConfigurationValue sysfs attribute for a hub with
+    children.  The task tries to lock the bandwidth_mutex at a time when
+    it already owns the lock:
+    
+            The attribute's method calls usb_set_configuration(),
+            which calls usb_disable_device() with the bandwidth_mutex
+            held.
+    
+            usb_disable_device() unregisters the existing interfaces,
+            which causes the hub driver to be unbound.
+    
+            The hub_disconnect() routine calls hub_quiesce(), which
+            calls usb_disconnect() for each of the hub's children.
+    
+            usb_disconnect() attempts to acquire the bandwidth_mutex
+            around a call to usb_disable_device().
+    
+    The solution is to make usb_disable_device() acquire the mutex for
+    itself instead of requiring the caller to hold it.  Then the mutex can
+    cover only the bandwidth deallocation operation and not the region
+    where the interfaces are unregistered.
+    
+    This has the potential to change system behavior slightly when a
+    config change races with another config or altsetting change.  Some of
+    the bandwidth released from the old config might get claimed by the
+    other config or altsetting, make it impossible to restore the old
+    config in case of a failure.  But since we don't try to recover from
+    config-change failures anyway, this doesn't matter.
+    
+    [This should be marked for stable kernels that contain the commit
+    fccf4e86200b8f5edd9a65da26f150e32ba79808 "USB: Free bandwidth when
+    usb_disable_device is called."
+    That commit was marked for stable kernels as old as 2.6.32.]
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Sarah Sharp 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index a2aa9d652c67..ec6c97dadbe4 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1667,7 +1667,6 @@ void usb_disconnect(struct usb_device **pdev)
+ {
+ 	struct usb_device	*udev = *pdev;
+ 	int			i;
+-	struct usb_hcd		*hcd = bus_to_hcd(udev->bus);
+ 
+ 	/* mark the device as inactive, so any further urb submissions for
+ 	 * this device (and any of its children) will fail immediately.
+@@ -1690,9 +1689,7 @@ void usb_disconnect(struct usb_device **pdev)
+ 	 * so that the hardware is now fully quiesced.
+ 	 */
+ 	dev_dbg (&udev->dev, "unregistering device\n");
+-	mutex_lock(hcd->bandwidth_mutex);
+ 	usb_disable_device(udev, 0);
+-	mutex_unlock(hcd->bandwidth_mutex);
+ 	usb_hcd_synchronize_unlinks(udev);
+ 
+ 	usb_remove_ep_devs(&udev->ep0);
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index aed3e07942d4..ca717da3be95 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1136,8 +1136,6 @@ void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf,
+  * Deallocates hcd/hardware state for the endpoints (nuking all or most
+  * pending urbs) and usbcore state for the interfaces, so that usbcore
+  * must usb_set_configuration() before any interfaces could be used.
+- *
+- * Must be called with hcd->bandwidth_mutex held.
+  */
+ void usb_disable_device(struct usb_device *dev, int skip_ep0)
+ {
+@@ -1190,7 +1188,9 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
+ 			usb_disable_endpoint(dev, i + USB_DIR_IN, false);
+ 		}
+ 		/* Remove endpoints from the host controller internal state */
++		mutex_lock(hcd->bandwidth_mutex);
+ 		usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
++		mutex_unlock(hcd->bandwidth_mutex);
+ 		/* Second pass: remove endpoint pointers */
+ 	}
+ 	for (i = skip_ep0; i < 16; ++i) {
+@@ -1750,7 +1750,6 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 	/* if it's already configured, clear out old state first.
+ 	 * getting rid of old interfaces means unbinding their drivers.
+ 	 */
+-	mutex_lock(hcd->bandwidth_mutex);
+ 	if (dev->state != USB_STATE_ADDRESS)
+ 		usb_disable_device(dev, 1);	/* Skip ep0 */
+ 
+@@ -1763,6 +1762,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 	 * host controller will not allow submissions to dropped endpoints.  If
+ 	 * this call fails, the device state is unchanged.
+ 	 */
++	mutex_lock(hcd->bandwidth_mutex);
+ 	ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL);
+ 	if (ret < 0) {
+ 		mutex_unlock(hcd->bandwidth_mutex);

commit c85dcdac5852295cf6822f5c4331a6ddab72581f
+Author: Alan Stern 
+Date:   Wed Apr 11 16:09:10 2012 -0400
+
+    USB: gadget: storage gadgets send wrong error code for unknown commands
+    
+    This patch (as1539) fixes a minor bug in the mass-storage gadget
+    drivers.  When an unknown command is received, the error code sent
+    back is "Invalid Field in CDB" rather than "Invalid Command".  This is
+    because the bitmask of CDB bytes allowed to be nonzero is incorrect.
+    
+    When handling an unknown command, we don't care which command bytes
+    are nonzero.  All the bits in the mask should be set, not just eight
+    of them.
+    
+    Signed-off-by: Alan Stern 
+    CC: 
+    CC: 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
+index a371e966425f..cb8c162cae5a 100644
+--- a/drivers/usb/gadget/f_mass_storage.c
++++ b/drivers/usb/gadget/f_mass_storage.c
+@@ -2189,7 +2189,7 @@ static int do_scsi_command(struct fsg_common *common)
+ 		common->data_size_from_cmnd = 0;
+ 		sprintf(unknown, "Unknown x%02x", common->cmnd[0]);
+ 		reply = check_command(common, common->cmnd_size,
+-				      DATA_DIR_UNKNOWN, 0xff, 0, unknown);
++				      DATA_DIR_UNKNOWN, ~0, 0, unknown);
+ 		if (reply == 0) {
+ 			common->curlun->sense_data = SS_INVALID_COMMAND;
+ 			reply = -EINVAL;
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index 4fac56927741..a896d73f7a93 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -2579,7 +2579,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
+ 		fsg->data_size_from_cmnd = 0;
+ 		sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]);
+ 		if ((reply = check_command(fsg, fsg->cmnd_size,
+-				DATA_DIR_UNKNOWN, 0xff, 0, unknown)) == 0) {
++				DATA_DIR_UNKNOWN, ~0, 0, unknown)) == 0) {
+ 			fsg->curlun->sense_data = SS_INVALID_COMMAND;
+ 			reply = -EINVAL;
+ 		}

commit b446b96fd11b69b7c4ecd47d869cff9094fd8802
+Author: Alan Stern 
+Date:   Tue Apr 3 15:24:43 2012 -0400
+
+    UHCI: hub_status_data should indicate if ports are resuming
+    
+    This patch (as1538) causes uhci_hub_status_data() to return a nonzero
+    value when any port is undergoing a resume transition while the root
+    hub is suspended.  This will allow usbcore to handle races between
+    root-hub suspend and port wakeup.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
+index 045cde4cbc3d..768d54295a20 100644
+--- a/drivers/usb/host/uhci-hub.c
++++ b/drivers/usb/host/uhci-hub.c
+@@ -196,11 +196,12 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
+ 	status = get_hub_status_data(uhci, buf);
+ 
+ 	switch (uhci->rh_state) {
+-	    case UHCI_RH_SUSPENDING:
+ 	    case UHCI_RH_SUSPENDED:
+ 		/* if port change, ask to be resumed */
+-		if (status || uhci->resuming_ports)
++		if (status || uhci->resuming_ports) {
++			status = 1;
+ 			usb_hcd_resume_root_hub(hcd);
++		}
+ 		break;
+ 
+ 	    case UHCI_RH_AUTO_STOPPED:

commit a448e4dc25303fe551e4dafe16c8c7c34f1b9d82
+Author: Alan Stern 
+Date:   Tue Apr 3 15:24:30 2012 -0400
+
+    EHCI: keep track of ports being resumed and indicate in hub_status_data
+    
+    This patch (as1537) adds a bit-array to ehci-hcd for keeping track of
+    which ports are undergoing a resume transition.  If any of the bits
+    are set when ehci_hub_status_data() is called, the routine will return
+    a nonzero value even if no ports have any status changes pending.
+    This will allow usbcore to handle races between root-hub suspend and
+    port wakeup.
+    
+    Signed-off-by: Alan Stern 
+    CC: Sarah Sharp 
+    CC: Chen Peter-B29397 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 057cdda7a489..806cc95317aa 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -347,6 +347,8 @@ static int ehci_reset (struct ehci_hcd *ehci)
+ 	if (ehci->debug)
+ 		dbgp_external_startup();
+ 
++	ehci->port_c_suspend = ehci->suspended_ports =
++			ehci->resuming_ports = 0;
+ 	return retval;
+ }
+ 
+@@ -939,6 +941,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 			 * like usb_port_resume() does.
+ 			 */
+ 			ehci->reset_done[i] = jiffies + msecs_to_jiffies(25);
++			set_bit(i, &ehci->resuming_ports);
+ 			ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
+ 			mod_timer(&hcd->rh_timer, ehci->reset_done[i]);
+ 		}
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 256fbd42e48c..38fe07623152 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -223,15 +223,10 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 	 * remote wakeup, we must fail the suspend.
+ 	 */
+ 	if (hcd->self.root_hub->do_remote_wakeup) {
+-		port = HCS_N_PORTS(ehci->hcs_params);
+-		while (port--) {
+-			if (ehci->reset_done[port] != 0) {
+-				spin_unlock_irq(&ehci->lock);
+-				ehci_dbg(ehci, "suspend failed because "
+-						"port %d is resuming\n",
+-						port + 1);
+-				return -EBUSY;
+-			}
++		if (ehci->resuming_ports) {
++			spin_unlock_irq(&ehci->lock);
++			ehci_dbg(ehci, "suspend failed because a port is resuming\n");
++			return -EBUSY;
+ 		}
+ 	}
+ 
+@@ -554,16 +549,12 @@ static int
+ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ {
+ 	struct ehci_hcd	*ehci = hcd_to_ehci (hcd);
+-	u32		temp, status = 0;
++	u32		temp, status;
+ 	u32		mask;
+ 	int		ports, i, retval = 1;
+ 	unsigned long	flags;
+ 	u32		ppcd = 0;
+ 
+-	/* if !USB_SUSPEND, root hub timers won't get shut down ... */
+-	if (ehci->rh_state != EHCI_RH_RUNNING)
+-		return 0;
+-
+ 	/* init status to no-changes */
+ 	buf [0] = 0;
+ 	ports = HCS_N_PORTS (ehci->hcs_params);
+@@ -572,6 +563,11 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ 		retval++;
+ 	}
+ 
++	/* Inform the core about resumes-in-progress by returning
++	 * a non-zero value even if there are no status changes.
++	 */
++	status = ehci->resuming_ports;
++
+ 	/* Some boards (mostly VIA?) report bogus overcurrent indications,
+ 	 * causing massive log spam unless we completely ignore them.  It
+ 	 * may be relevant that VIA VT8235 controllers, where PORT_POWER is
+@@ -846,6 +842,7 @@ static int ehci_hub_control (
+ 				ehci_writel(ehci,
+ 					temp & ~(PORT_RWC_BITS | PORT_RESUME),
+ 					status_reg);
++				clear_bit(wIndex, &ehci->resuming_ports);
+ 				retval = handshake(ehci, status_reg,
+ 					   PORT_RESUME, 0, 2000 /* 2msec */);
+ 				if (retval != 0) {
+@@ -864,6 +861,7 @@ static int ehci_hub_control (
+ 					ehci->reset_done[wIndex])) {
+ 			status |= USB_PORT_STAT_C_RESET << 16;
+ 			ehci->reset_done [wIndex] = 0;
++			clear_bit(wIndex, &ehci->resuming_ports);
+ 
+ 			/* force reset to complete */
+ 			ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_RESET),
+@@ -884,8 +882,10 @@ static int ehci_hub_control (
+ 					ehci_readl(ehci, status_reg));
+ 		}
+ 
+-		if (!(temp & (PORT_RESUME|PORT_RESET)))
++		if (!(temp & (PORT_RESUME|PORT_RESET))) {
+ 			ehci->reset_done[wIndex] = 0;
++			clear_bit(wIndex, &ehci->resuming_ports);
++		}
+ 
+ 		/* transfer dedicated ports to the companion hc */
+ 		if ((temp & PORT_CONNECT) &&
+@@ -920,6 +920,7 @@ static int ehci_hub_control (
+ 			status |= USB_PORT_STAT_SUSPEND;
+ 		} else if (test_bit(wIndex, &ehci->suspended_ports)) {
+ 			clear_bit(wIndex, &ehci->suspended_ports);
++			clear_bit(wIndex, &ehci->resuming_ports);
+ 			ehci->reset_done[wIndex] = 0;
+ 			if (temp & PORT_PE)
+ 				set_bit(wIndex, &ehci->port_c_suspend);
+diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
+index 3de48a2d7955..73544bd440bd 100644
+--- a/drivers/usb/host/ehci-tegra.c
++++ b/drivers/usb/host/ehci-tegra.c
+@@ -224,6 +224,7 @@ static int tegra_ehci_hub_control(
+ 		temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
+ 		/* start resume signalling */
+ 		ehci_writel(ehci, temp | PORT_RESUME, status_reg);
++		set_bit(wIndex-1, &ehci->resuming_ports);
+ 
+ 		spin_unlock_irqrestore(&ehci->lock, flags);
+ 		msleep(20);
+@@ -236,6 +237,7 @@ static int tegra_ehci_hub_control(
+ 			pr_err("%s: timeout waiting for SUSPEND\n", __func__);
+ 
+ 		ehci->reset_done[wIndex-1] = 0;
++		clear_bit(wIndex-1, &ehci->resuming_ports);
+ 
+ 		tegra->port_resuming = 1;
+ 		goto done;
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 8f9acbc96fde..2694ed6558d2 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -117,6 +117,8 @@ struct ehci_hcd {			/* one per controller */
+ 			the change-suspend feature turned on */
+ 	unsigned long		suspended_ports;	/* which ports are
+ 			suspended */
++	unsigned long		resuming_ports;		/* which ports have
++			started to resume */
+ 
+ 	/* per-HC memory pools (could be per-bus, but ...) */
+ 	struct dma_pool		*qh_pool;	/* qh per active urb */

commit 879d38e6bc36d73b0ac40ec9b0d839fda9fa8b1a
+Author: Alan Stern 
+Date:   Tue Apr 3 15:24:18 2012 -0400
+
+    USB: fix race between root-hub suspend and remote wakeup
+    
+    This patch (as1533) fixes a race between root-hub suspend and remote
+    wakeup.  If a wakeup event occurs while a root hub is suspending, it
+    might not cause the suspend to fail.  Although the host controller
+    drivers check for pending wakeup events at the start of their
+    bus_suspend routines, they generally do not check for wakeup events
+    while the routines are running.
+    
+    In addition, if a wakeup event occurs any time after khubd is frozen
+    and before the root hub is fully suspended, it might not cause a
+    system sleep transition to fail.  For example, the host controller
+    drivers do not fail root-hub suspends when a connect-change event is
+    pending.
+    
+    To fix both these issues, this patch causes hcd_bus_suspend() to query
+    the controller driver's hub_status_data method after a root hub is
+    suspended, if the root hub is enabled for wakeup.  Any pending status
+    changes will count as wakeup events, causing the root hub to be
+    resumed and the overall suspend to fail with -EBUSY.
+    
+    A significant point is that not all events are reflected immediately
+    in the status bits.  Both EHCI and UHCI controllers notify the CPU
+    when remote wakeup begins on a port, but the port's suspend-change
+    status bit doesn't get set until after the port has completed the
+    transition out of the suspend state, some 25 milliseconds later.
+    Consequently, the patch will interpret any nonzero return value from
+    hub_status_data as indicating a pending event, even if none of the
+    status bits are set in the data buffer.  Follow-up patches make the
+    necessary changes to ehci-hcd and uhci-hcd.
+    
+    Signed-off-by: Alan Stern 
+    CC: Sarah Sharp 
+    CC: Chen Peter-B29397 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 9d7fc9a39933..140d3e11f212 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1978,6 +1978,18 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg)
+ 	if (status == 0) {
+ 		usb_set_device_state(rhdev, USB_STATE_SUSPENDED);
+ 		hcd->state = HC_STATE_SUSPENDED;
++
++		/* Did we race with a root-hub wakeup event? */
++		if (rhdev->do_remote_wakeup) {
++			char	buffer[6];
++
++			status = hcd->driver->hub_status_data(hcd, buffer);
++			if (status != 0) {
++				dev_dbg(&rhdev->dev, "suspend raced with wakeup event\n");
++				hcd_bus_resume(rhdev, PMSG_AUTO_RESUME);
++				status = -EBUSY;
++			}
++		}
+ 	} else {
+ 		spin_lock_irq(&hcd_root_hub_lock);
+ 		if (!HCD_DEAD(hcd)) {

commit cd4376e23a59a2adf3084cb5f4a523e6d5fd4e49
+Author: Alan Stern 
+Date:   Wed Mar 28 15:56:17 2012 -0400
+
+    USB: don't ignore suspend errors for root hubs
+    
+    This patch (as1532) fixes a mistake in the USB suspend code.  When the
+    system is going to sleep, we should ignore errors in powering down USB
+    devices, because they don't really matter.  The devices will go to low
+    power anyway when the entire USB bus gets suspended (except for
+    SuperSpeed devices; maybe they will need special treatment later).
+    
+    However we should not ignore errors in suspending root hubs,
+    especially if the error indicates that the suspend raced with a wakeup
+    request.  Doing so might leave the bus powered on while the system was
+    supposed to be asleep, or it might cause the suspend of the root hub's
+    parent controller device to fail, or it might cause a wakeup request
+    to be ignored.
+    
+    The patch fixes the problem by ignoring errors only when the device in
+    question is not a root hub.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Chen Peter 
+    CC: 
+    Tested-by: Chen Peter 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index f8e2d6d52e5c..9a56635dc19c 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1189,8 +1189,13 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 	if (status == 0) {
+ 		status = usb_suspend_device(udev, msg);
+ 
+-		/* Again, ignore errors during system sleep transitions */
+-		if (!PMSG_IS_AUTO(msg))
++		/*
++		 * Ignore errors from non-root-hub devices during
++		 * system sleep transitions.  For the most part,
++		 * these devices should go to low power anyway when
++		 * the entire bus is suspended.
++		 */
++		if (udev->parent && !PMSG_IS_AUTO(msg))
+ 			status = 0;
+ 	}
+ 

commit 891a3b1fddb24b4b53426685bd0390bb74c9b5b3
+Author: Alan Stern 
+Date:   Wed Mar 28 16:10:49 2012 -0400
+
+    USB: fix bug in serial driver unregistration
+    
+    This patch (as1536) fixes a bug in the USB serial core.  Unloading and
+    reloading a serial driver while a serial device is plugged in causes
+    errors because of the code in usb_serial_disconnect() that tries to
+    make sure the port_remove method is called.  With the new order of
+    driver registration introduced in the 3.4 kernel, this is definitely
+    not the right thing to do (if indeed it ever was).
+    
+    The patch removes that whole section code, along with the mechanism
+    for keeping track of each port's registration state, which is no
+    longer needed.  The driver core can handle all that stuff for us.
+    
+    Note: This has been tested only with one or two USB serial drivers.
+    In theory, other drivers might still run into trouble.  But if they
+    do, it will be the fault of the drivers, not of this patch -- that is,
+    the drivers will need to be fixed.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Johan Hovold 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
+index 7f547dc3a590..ed8adb052ca7 100644
+--- a/drivers/usb/serial/bus.c
++++ b/drivers/usb/serial/bus.c
+@@ -60,8 +60,6 @@ static int usb_serial_device_probe(struct device *dev)
+ 		retval = -ENODEV;
+ 		goto exit;
+ 	}
+-	if (port->dev_state != PORT_REGISTERING)
+-		goto exit;
+ 
+ 	driver = port->serial->type;
+ 	if (driver->port_probe) {
+@@ -98,9 +96,6 @@ static int usb_serial_device_remove(struct device *dev)
+ 	if (!port)
+ 		return -ENODEV;
+ 
+-	if (port->dev_state != PORT_UNREGISTERING)
+-		return retval;
+-
+ 	device_remove_file(&port->dev, &dev_attr_port_number);
+ 
+ 	driver = port->serial->type;
+diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
+index 69230f01056a..5413bd500781 100644
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -1070,17 +1070,12 @@ int usb_serial_probe(struct usb_interface *interface,
+ 		port = serial->port[i];
+ 		dev_set_name(&port->dev, "ttyUSB%d", port->number);
+ 		dbg ("%s - registering %s", __func__, dev_name(&port->dev));
+-		port->dev_state = PORT_REGISTERING;
+ 		device_enable_async_suspend(&port->dev);
+ 
+ 		retval = device_add(&port->dev);
+-		if (retval) {
++		if (retval)
+ 			dev_err(&port->dev, "Error registering port device, "
+ 				"continuing\n");
+-			port->dev_state = PORT_UNREGISTERED;
+-		} else {
+-			port->dev_state = PORT_REGISTERED;
+-		}
+ 	}
+ 
+ 	usb_serial_console_init(debug, minor);
+@@ -1124,22 +1119,8 @@ void usb_serial_disconnect(struct usb_interface *interface)
+ 			}
+ 			kill_traffic(port);
+ 			cancel_work_sync(&port->work);
+-			if (port->dev_state == PORT_REGISTERED) {
+-
+-				/* Make sure the port is bound so that the
+-				 * driver's port_remove method is called.
+-				 */
+-				if (!port->dev.driver) {
+-					int rc;
+-
+-					port->dev.driver =
+-							&serial->type->driver;
+-					rc = device_bind_driver(&port->dev);
+-				}
+-				port->dev_state = PORT_UNREGISTERING;
++			if (device_is_registered(&port->dev))
+ 				device_del(&port->dev);
+-				port->dev_state = PORT_UNREGISTERED;
+-			}
+ 		}
+ 	}
+ 	serial->type->disconnect(serial);
+diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
+index fbb666b1b670..474283888233 100644
+--- a/include/linux/usb/serial.h
++++ b/include/linux/usb/serial.h
+@@ -28,13 +28,6 @@
+ /* parity check flag */
+ #define RELEVANT_IFLAG(iflag)	(iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
+ 
+-enum port_dev_state {
+-	PORT_UNREGISTERED,
+-	PORT_REGISTERING,
+-	PORT_REGISTERED,
+-	PORT_UNREGISTERING,
+-};
+-
+ /* USB serial flags */
+ #define USB_SERIAL_WRITE_BUSY	0
+ 
+@@ -124,7 +117,6 @@ struct usb_serial_port {
+ 	char			throttle_req;
+ 	unsigned long		sysrq; /* sysrq timeout */
+ 	struct device		dev;
+-	enum port_dev_state	dev_state;
+ };
+ #define to_usb_serial_port(d) container_of(d, struct usb_serial_port, dev)
+ 

commit da8bfb090c2b30af9f3879443355f7eb1d0fe10a
+Author: Alan Stern 
+Date:   Wed Mar 28 16:13:28 2012 -0400
+
+    USB documentation: explain lifetime rules for unlinking URBs
+    
+    This patch (as1534c) updates the documentation for usb_unlink_urb and
+    related functions.  It explains that the caller must prevent the URB
+    being unlinked from getting deallocated while the unlink is taking
+    place.
+    
+    Signed-off-by: Alan Stern 
+    CC: Ming Lei 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/usb/URB.txt b/Documentation/usb/URB.txt
+index 8ffce746d496..00d2c644068e 100644
+--- a/Documentation/usb/URB.txt
++++ b/Documentation/usb/URB.txt
+@@ -168,6 +168,28 @@ that if the completion handler or anyone else tries to resubmit it
+ they will get a -EPERM error.  Thus you can be sure that when
+ usb_kill_urb() returns, the URB is totally idle.
+ 
++There is a lifetime issue to consider.  An URB may complete at any
++time, and the completion handler may free the URB.  If this happens
++while usb_unlink_urb or usb_kill_urb is running, it will cause a
++memory-access violation.  The driver is responsible for avoiding this,
++which often means some sort of lock will be needed to prevent the URB
++from being deallocated while it is still in use.
++
++On the other hand, since usb_unlink_urb may end up calling the
++completion handler, the handler must not take any lock that is held
++when usb_unlink_urb is invoked.  The general solution to this problem
++is to increment the URB's reference count while holding the lock, then
++drop the lock and call usb_unlink_urb or usb_kill_urb, and then
++decrement the URB's reference count.  You increment the reference
++count by calling
++
++	struct urb *usb_get_urb(struct urb *urb)
++
++(ignore the return value; it is the same as the argument) and
++decrement the reference count by calling usb_free_urb.  Of course,
++none of this is necessary if there's no danger of the URB being freed
++by the completion handler.
++
+ 
+ 1.7. What about the completion handler?
+ 
+diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
+index 7239a73c1b8c..cd9b3a2cd8a7 100644
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -539,6 +539,10 @@ EXPORT_SYMBOL_GPL(usb_submit_urb);
+  * never submitted, or it was unlinked before, or the hardware is already
+  * finished with it), even if the completion handler has not yet run.
+  *
++ * The URB must not be deallocated while this routine is running.  In
++ * particular, when a driver calls this routine, it must insure that the
++ * completion handler cannot deallocate the URB.
++ *
+  * Unlinking and Endpoint Queues:
+  *
+  * [The behaviors and guarantees described below do not apply to virtual
+@@ -603,6 +607,10 @@ EXPORT_SYMBOL_GPL(usb_unlink_urb);
+  * with error -EPERM.  Thus even if the URB's completion handler always
+  * tries to resubmit, it will not succeed and the URB will become idle.
+  *
++ * The URB must not be deallocated while this routine is running.  In
++ * particular, when a driver calls this routine, it must insure that the
++ * completion handler cannot deallocate the URB.
++ *
+  * This routine may not be used in an interrupt context (such as a bottom
+  * half or a completion handler), or when holding a spinlock, or in other
+  * situations where the caller can't schedule().
+@@ -640,6 +648,10 @@ EXPORT_SYMBOL_GPL(usb_kill_urb);
+  * with error -EPERM.  Thus even if the URB's completion handler always
+  * tries to resubmit, it will not succeed and the URB will become idle.
+  *
++ * The URB must not be deallocated while this routine is running.  In
++ * particular, when a driver calls this routine, it must insure that the
++ * completion handler cannot deallocate the URB.
++ *
+  * This routine may not be used in an interrupt context (such as a bottom
+  * half or a completion handler), or when holding a spinlock, or in other
+  * situations where the caller can't schedule().

commit bcf398537630bf20b4dbe59ba855b69f404c93cf
+Author: Alan Stern 
+Date:   Thu Mar 22 11:00:21 2012 -0400
+
+    USB: don't clear urb->dev in scatter-gather library
+    
+    This patch (as1517b) fixes an error in the USB scatter-gather library.
+    The library code uses urb->dev to determine whether or nor an URB is
+    currently active; the completion handler sets urb->dev to NULL.
+    However the core unlinking routines need to use urb->dev.  Since
+    unlinking always racing with completion, the completion handler must
+    not clear urb->dev -- it can lead to invalid memory accesses when a
+    transfer has to be cancelled.
+    
+    This patch fixes the problem by getting rid of the lines that clear
+    urb->dev after urb has been submitted.  As a result we may end up
+    trying to unlink an URB that failed in submission or that has already
+    completed, so an extra check is added after each unlink to avoid
+    printing an error message when this happens.  The checks are updated
+    in both sg_complete() and sg_cancel(), and the second is updated to
+    match the first (currently it prints out unnecessary warning messages
+    if a device is unplugged while a transfer is in progress).
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Illia Zaitsev 
+    CC: Ming Lei 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index b3bdfede45e6..aed3e07942d4 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -308,7 +308,8 @@ static void sg_complete(struct urb *urb)
+ 				retval = usb_unlink_urb(io->urbs [i]);
+ 				if (retval != -EINPROGRESS &&
+ 				    retval != -ENODEV &&
+-				    retval != -EBUSY)
++				    retval != -EBUSY &&
++				    retval != -EIDRM)
+ 					dev_err(&io->dev->dev,
+ 						"%s, unlink --> %d\n",
+ 						__func__, retval);
+@@ -317,7 +318,6 @@ static void sg_complete(struct urb *urb)
+ 		}
+ 		spin_lock(&io->lock);
+ 	}
+-	urb->dev = NULL;
+ 
+ 	/* on the last completion, signal usb_sg_wait() */
+ 	io->bytes += urb->actual_length;
+@@ -524,7 +524,6 @@ void usb_sg_wait(struct usb_sg_request *io)
+ 		case -ENXIO:	/* hc didn't queue this one */
+ 		case -EAGAIN:
+ 		case -ENOMEM:
+-			io->urbs[i]->dev = NULL;
+ 			retval = 0;
+ 			yield();
+ 			break;
+@@ -542,7 +541,6 @@ void usb_sg_wait(struct usb_sg_request *io)
+ 
+ 			/* fail any uncompleted urbs */
+ 		default:
+-			io->urbs[i]->dev = NULL;
+ 			io->urbs[i]->status = retval;
+ 			dev_dbg(&io->dev->dev, "%s, submit --> %d\n",
+ 				__func__, retval);
+@@ -593,7 +591,10 @@ void usb_sg_cancel(struct usb_sg_request *io)
+ 			if (!io->urbs [i]->dev)
+ 				continue;
+ 			retval = usb_unlink_urb(io->urbs [i]);
+-			if (retval != -EINPROGRESS && retval != -EBUSY)
++			if (retval != -EINPROGRESS
++					&& retval != -ENODEV
++					&& retval != -EBUSY
++					&& retval != -EIDRM)
+ 				dev_warn(&io->dev->dev, "%s, unlink --> %d\n",
+ 					__func__, retval);
+ 		}

commit f2791d733a2f06997b573d1a3cfde21e6f529826
+Author: Alan Stern 
+Date:   Mon Mar 26 22:46:52 2012 +0200
+
+    PM / Runtime: don't forget to wake up waitqueue on failure
+    
+    This patch (as1535) fixes a bug in the runtime PM core.  When a
+    runtime suspend attempt completes, whether successfully or not, the
+    device's power.wait_queue is supposed to be signalled.  But this
+    doesn't happen in the failure pathway of rpm_suspend() when another
+    autosuspend attempt is rescheduled.  As a result, a task can get stuck
+    indefinitely on the wait queue (I have seen this happen in testing).
+    
+    The patch fixes the problem by moving the wake_up_all() call up near
+    the start of the failure code.
+    
+    Signed-off-by: Alan Stern 
+    CC: 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
+index 541f821d4ea6..bd0f3949bcf9 100644
+--- a/drivers/base/power/runtime.c
++++ b/drivers/base/power/runtime.c
+@@ -532,6 +532,8 @@ static int rpm_suspend(struct device *dev, int rpmflags)
+ 	dev->power.suspend_time = ktime_set(0, 0);
+ 	dev->power.max_time_suspended_ns = -1;
+ 	dev->power.deferred_resume = false;
++	wake_up_all(&dev->power.wait_queue);
++
+ 	if (retval == -EAGAIN || retval == -EBUSY) {
+ 		dev->power.runtime_error = 0;
+ 
+@@ -547,7 +549,6 @@ static int rpm_suspend(struct device *dev, int rpmflags)
+ 	} else {
+ 		pm_runtime_cancel_pending(dev);
+ 	}
+-	wake_up_all(&dev->power.wait_queue);
+ 	goto out;
+ }
+ 

commit 62d3c5439c534b0e6c653fc63e6d8c67be3a57b1
+Author: Alan Stern 
+Date:   Fri Mar 2 10:51:00 2012 +0100
+
+    Block: use a freezable workqueue for disk-event polling
+    
+    This patch (as1519) fixes a bug in the block layer's disk-events
+    polling.  The polling is done by a work routine queued on the
+    system_nrt_wq workqueue.  Since that workqueue isn't freezable, the
+    polling continues even in the middle of a system sleep transition.
+    
+    Obviously, polling a suspended drive for media changes and such isn't
+    a good thing to do; in the case of USB mass-storage devices it can
+    lead to real problems requiring device resets and even re-enumeration.
+    
+    The patch fixes things by creating a new system-wide, non-reentrant,
+    freezable workqueue and using it for disk-events polling.
+    
+    Signed-off-by: Alan Stern 
+    CC: 
+    Acked-by: Tejun Heo 
+    Acked-by: Rafael J. Wysocki 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/genhd.c b/block/genhd.c
+index b26c4085590d..df9816ede75b 100644
+--- a/block/genhd.c
++++ b/block/genhd.c
+@@ -1478,9 +1478,9 @@ static void __disk_unblock_events(struct gendisk *disk, bool check_now)
+ 	intv = disk_events_poll_jiffies(disk);
+ 	set_timer_slack(&ev->dwork.timer, intv / 4);
+ 	if (check_now)
+-		queue_delayed_work(system_nrt_wq, &ev->dwork, 0);
++		queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, 0);
+ 	else if (intv)
+-		queue_delayed_work(system_nrt_wq, &ev->dwork, intv);
++		queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, intv);
+ out_unlock:
+ 	spin_unlock_irqrestore(&ev->lock, flags);
+ }
+@@ -1524,7 +1524,7 @@ void disk_flush_events(struct gendisk *disk, unsigned int mask)
+ 	ev->clearing |= mask;
+ 	if (!ev->block) {
+ 		cancel_delayed_work(&ev->dwork);
+-		queue_delayed_work(system_nrt_wq, &ev->dwork, 0);
++		queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, 0);
+ 	}
+ 	spin_unlock_irq(&ev->lock);
+ }
+@@ -1561,7 +1561,7 @@ unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask)
+ 
+ 	/* uncondtionally schedule event check and wait for it to finish */
+ 	disk_block_events(disk);
+-	queue_delayed_work(system_nrt_wq, &ev->dwork, 0);
++	queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, 0);
+ 	flush_delayed_work(&ev->dwork);
+ 	__disk_unblock_events(disk, false);
+ 
+@@ -1598,7 +1598,7 @@ static void disk_events_workfn(struct work_struct *work)
+ 
+ 	intv = disk_events_poll_jiffies(disk);
+ 	if (!ev->block && intv)
+-		queue_delayed_work(system_nrt_wq, &ev->dwork, intv);
++		queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, intv);
+ 
+ 	spin_unlock_irq(&ev->lock);
+ 
+diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
+index eb8b9f15f2e0..af155450cabb 100644
+--- a/include/linux/workqueue.h
++++ b/include/linux/workqueue.h
+@@ -289,12 +289,16 @@ enum {
+  *
+  * system_freezable_wq is equivalent to system_wq except that it's
+  * freezable.
++ *
++ * system_nrt_freezable_wq is equivalent to system_nrt_wq except that
++ * it's freezable.
+  */
+ extern struct workqueue_struct *system_wq;
+ extern struct workqueue_struct *system_long_wq;
+ extern struct workqueue_struct *system_nrt_wq;
+ extern struct workqueue_struct *system_unbound_wq;
+ extern struct workqueue_struct *system_freezable_wq;
++extern struct workqueue_struct *system_nrt_freezable_wq;
+ 
+ extern struct workqueue_struct *
+ __alloc_workqueue_key(const char *fmt, unsigned int flags, int max_active,
+diff --git a/kernel/workqueue.c b/kernel/workqueue.c
+index bec7b5b53e03..f2c5638bb5ab 100644
+--- a/kernel/workqueue.c
++++ b/kernel/workqueue.c
+@@ -253,11 +253,13 @@ struct workqueue_struct *system_long_wq __read_mostly;
+ struct workqueue_struct *system_nrt_wq __read_mostly;
+ struct workqueue_struct *system_unbound_wq __read_mostly;
+ struct workqueue_struct *system_freezable_wq __read_mostly;
++struct workqueue_struct *system_nrt_freezable_wq __read_mostly;
+ EXPORT_SYMBOL_GPL(system_wq);
+ EXPORT_SYMBOL_GPL(system_long_wq);
+ EXPORT_SYMBOL_GPL(system_nrt_wq);
+ EXPORT_SYMBOL_GPL(system_unbound_wq);
+ EXPORT_SYMBOL_GPL(system_freezable_wq);
++EXPORT_SYMBOL_GPL(system_nrt_freezable_wq);
+ 
+ #define CREATE_TRACE_POINTS
+ #include 
+@@ -3833,8 +3835,11 @@ static int __init init_workqueues(void)
+ 					    WQ_UNBOUND_MAX_ACTIVE);
+ 	system_freezable_wq = alloc_workqueue("events_freezable",
+ 					      WQ_FREEZABLE, 0);
++	system_nrt_freezable_wq = alloc_workqueue("events_nrt_freezable",
++			WQ_NON_REENTRANT | WQ_FREEZABLE, 0);
+ 	BUG_ON(!system_wq || !system_long_wq || !system_nrt_wq ||
+-	       !system_unbound_wq || !system_freezable_wq);
++	       !system_unbound_wq || !system_freezable_wq ||
++		!system_nrt_freezable_wq);
+ 	return 0;
+ }
+ early_initcall(init_workqueues);

commit 37891abc8464637964a26ae4b61d307fef831f80
+Author: Alan Stern 
+Date:   Mon Feb 27 11:23:45 2012 -0500
+
+    HID: usbhid: Add NOGET quirk for the AIREN Slim+ keyboard
+    
+    This patch (as1531) adds a NOGET quirk for the Slim+ keyboard marketed
+    by AIREN.  This keyboard seems to have a lot of bugs; NOGET works
+    around only one of them.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: okias 
+    CC: 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
+index b8574cddd953..63552e30d0c3 100644
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -59,6 +59,9 @@
+ #define USB_VENDOR_ID_AIRCABLE		0x16CA
+ #define USB_DEVICE_ID_AIRCABLE1		0x1502
+ 
++#define USB_VENDOR_ID_AIREN		0x1a2c
++#define USB_DEVICE_ID_AIREN_SLIMPLUS	0x0002
++
+ #define USB_VENDOR_ID_ALCOR		0x058f
+ #define USB_DEVICE_ID_ALCOR_USBRS232	0x9720
+ 
+diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
+index c831af937481..57d4e1e1df48 100644
+--- a/drivers/hid/usbhid/hid-quirks.c
++++ b/drivers/hid/usbhid/hid-quirks.c
+@@ -54,6 +54,7 @@ static const struct hid_blacklist {
+ 	{ USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII, HID_QUIRK_MULTI_INPUT },
+ 	{ USB_VENDOR_ID_TOUCHPACK, USB_DEVICE_ID_TOUCHPACK_RTS, HID_QUIRK_MULTI_INPUT },
+ 
++	{ USB_VENDOR_ID_AIREN, USB_DEVICE_ID_AIREN_SLIMPLUS, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },

commit 69276a33bd1d272dc9c3bd577038954811bd1831
+Author: Alan Stern 
+Date:   Thu Feb 23 14:57:37 2012 -0500
+
+    usb-serial: use new registration API in staging drivers
+    
+    This patch (as1530) modifies the following usb-serial drivers from
+    drivers/staging to utilize the new usb_serial_{de}register_drivers()
+    routines:
+    
+            quatech_usb2 and serqt_usb2.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/quatech_usb2/quatech_usb2.c b/drivers/staging/quatech_usb2/quatech_usb2.c
+index 897a3a99c794..b8a078abd6c7 100644
+--- a/drivers/staging/quatech_usb2/quatech_usb2.c
++++ b/drivers/staging/quatech_usb2/quatech_usb2.c
+@@ -135,7 +135,6 @@ static struct usb_driver quausb2_usb_driver = {
+ 	.probe = usb_serial_probe,
+ 	.disconnect = usb_serial_disconnect,
+ 	.id_table = quausb2_id_table,
+-	.no_dynamic_id = 1,
+ };
+ 
+ /**
+@@ -1942,7 +1941,6 @@ static struct usb_serial_driver quatech2_device = {
+ 		.name = "quatech_usb2",
+ 	},
+ 	.description = DRIVER_DESC,
+-	.usb_driver = &quausb2_usb_driver,
+ 	.id_table = quausb2_id_table,
+ 	.num_ports = 8,
+ 	.open = qt2_open,
+@@ -1964,37 +1962,27 @@ static struct usb_serial_driver quatech2_device = {
+ 	.write_bulk_callback = qt2_write_bulk_callback,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&quatech2_device, NULL
++};
++
+ static int __init quausb2_usb_init(void)
+ {
+ 	int retval;
+ 
+ 	dbg("%s\n", __func__);
+ 
+-	/* register with usb-serial */
+-	retval = usb_serial_register(&quatech2_device);
+-
+-	if (retval)
+-		goto failed_usb_serial_register;
+-
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-			DRIVER_DESC "\n");
+-
+-	/* register with usb */
+-
+-	retval = usb_register(&quausb2_usb_driver);
++	retval = usb_serial_register_drivers(&quausb2_usb_driver,
++			serial_drivers);
+ 	if (retval == 0)
+-		return 0;
+-
+-	/* if we're here, usb_register() failed */
+-	usb_serial_deregister(&quatech2_device);
+-failed_usb_serial_register:
+-		return retval;
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++				DRIVER_DESC "\n");
++	return retval;
+ }
+ 
+ static void __exit quausb2_usb_exit(void)
+ {
+-	usb_deregister(&quausb2_usb_driver);
+-	usb_serial_deregister(&quatech2_device);
++	usb_serial_deregister_drivers(&quausb2_usb_driver, serial_drivers);
+ }
+ 
+ module_init(quausb2_usb_init);
+diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c
+index 1c5780f1571b..04b6be86df1a 100644
+--- a/drivers/staging/serqt_usb2/serqt_usb2.c
++++ b/drivers/staging/serqt_usb2/serqt_usb2.c
+@@ -200,7 +200,6 @@ static struct usb_driver serqt_usb_driver = {
+ 	.probe = usb_serial_probe,
+ 	.disconnect = usb_serial_disconnect,
+ 	.id_table = serqt_id_table,
+-	.no_dynamic_id = 1,
+ };
+ 
+ static int port_paranoia_check(struct usb_serial_port *port,
+@@ -1590,7 +1589,6 @@ static struct usb_serial_driver quatech_device = {
+ 		   .name = "serqt",
+ 		   },
+ 	.description = DRIVER_DESC,
+-	.usb_driver = &serqt_usb_driver,
+ 	.id_table = serqt_id_table,
+ 	.num_ports = 8,
+ 	.open = qt_open,
+@@ -1610,37 +1608,27 @@ static struct usb_serial_driver quatech_device = {
+ 	.release = qt_release,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&quatech_device, NULL
++};
++
+ static int __init serqt_usb_init(void)
+ {
+ 	int retval;
+ 
+ 	dbg("%s\n", __func__);
+ 
+-	/* register with usb-serial */
+-	retval = usb_serial_register(&quatech_device);
+-
+-	if (retval)
+-		goto failed_usb_serial_register;
+-
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
+-
+-	/* register with usb */
+-
+-	retval = usb_register(&serqt_usb_driver);
++	retval = usb_serial_register_drivers(&serqt_usb_driver,
++			serial_drivers);
+ 	if (retval == 0)
+-		return 0;
+-
+-	/* if we're here, usb_register() failed */
+-	usb_serial_deregister(&quatech_device);
+-failed_usb_serial_register:
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++				DRIVER_DESC "\n");
+ 	return retval;
+ }
+ 
+ static void __exit serqt_usb_exit(void)
+ {
+-	usb_deregister(&serqt_usb_driver);
+-	usb_serial_deregister(&quatech_device);
++	usb_serial_deregister_drivers(&serqt_usb_driver, serial_drivers);
+ }
+ 
+ module_init(serqt_usb_init);

commit 29618e9fb5507b9fcf07f739a8506a3640495945
+Author: Alan Stern 
+Date:   Thu Feb 23 14:57:32 2012 -0500
+
+    usb-serial: use new registration API in [t-z]* drivers
+    
+    This patch (as1529) modifies the following usb-serial drivers to
+    utilize the new usb_serial_{de}register_drivers() routines:
+    
+            ti_usb_3410_5052, usb_debug, visor, vivopay-serial,
+            whiteheat, and zio.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
+index 74f2c7746cc4..ab74123d658e 100644
+--- a/drivers/usb/serial/ti_usb_3410_5052.c
++++ b/drivers/usb/serial/ti_usb_3410_5052.c
+@@ -216,7 +216,6 @@ static struct usb_driver ti_usb_driver = {
+ 	.probe			= usb_serial_probe,
+ 	.disconnect		= usb_serial_disconnect,
+ 	.id_table		= ti_id_table_combined,
+-	.no_dynamic_id = 	1,
+ };
+ 
+ static struct usb_serial_driver ti_1port_device = {
+@@ -225,7 +224,6 @@ static struct usb_serial_driver ti_1port_device = {
+ 		.name		= "ti_usb_3410_5052_1",
+ 	},
+ 	.description		= "TI USB 3410 1 port adapter",
+-	.usb_driver		= &ti_usb_driver,
+ 	.id_table		= ti_id_table_3410,
+ 	.num_ports		= 1,
+ 	.attach			= ti_startup,
+@@ -254,7 +252,6 @@ static struct usb_serial_driver ti_2port_device = {
+ 		.name		= "ti_usb_3410_5052_2",
+ 	},
+ 	.description		= "TI USB 5052 2 port adapter",
+-	.usb_driver		= &ti_usb_driver,
+ 	.id_table		= ti_id_table_5052,
+ 	.num_ports		= 2,
+ 	.attach			= ti_startup,
+@@ -277,6 +274,9 @@ static struct usb_serial_driver ti_2port_device = {
+ 	.write_bulk_callback	= ti_bulk_out_callback,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&ti_1port_device, &ti_2port_device, NULL
++};
+ 
+ /* Module */
+ 
+@@ -344,36 +344,17 @@ static int __init ti_init(void)
+ 		ti_id_table_combined[c].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
+ 	}
+ 
+-	ret = usb_serial_register(&ti_1port_device);
+-	if (ret)
+-		goto failed_1port;
+-	ret = usb_serial_register(&ti_2port_device);
+-	if (ret)
+-		goto failed_2port;
+-
+-	ret = usb_register(&ti_usb_driver);
+-	if (ret)
+-		goto failed_usb;
+-
+-	printk(KERN_INFO KBUILD_MODNAME ": " TI_DRIVER_VERSION ":"
+-	       TI_DRIVER_DESC "\n");
+-
+-	return 0;
+-
+-failed_usb:
+-	usb_serial_deregister(&ti_2port_device);
+-failed_2port:
+-	usb_serial_deregister(&ti_1port_device);
+-failed_1port:
++	ret = usb_serial_register_drivers(&ti_usb_driver, serial_drivers);
++	if (ret == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " TI_DRIVER_VERSION ":"
++			       TI_DRIVER_DESC "\n");
+ 	return ret;
+ }
+ 
+ 
+ static void __exit ti_exit(void)
+ {
+-	usb_deregister(&ti_usb_driver);
+-	usb_serial_deregister(&ti_1port_device);
+-	usb_serial_deregister(&ti_2port_device);
++	usb_serial_deregister_drivers(&ti_usb_driver, serial_drivers);
+ }
+ 
+ 
+diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c
+index 9b632e753210..5b29b4a2ebc7 100644
+--- a/drivers/usb/serial/usb_debug.c
++++ b/drivers/usb/serial/usb_debug.c
+@@ -40,7 +40,6 @@ static struct usb_driver debug_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table,
+-	.no_dynamic_id =	1,
+ };
+ 
+ /* This HW really does not support a serial break, so one will be
+@@ -74,30 +73,24 @@ static struct usb_serial_driver debug_device = {
+ 		.name =		"debug",
+ 	},
+ 	.id_table =		id_table,
+-	.usb_driver =		&debug_driver,
+ 	.num_ports =		1,
+ 	.bulk_out_size =	USB_DEBUG_MAX_PACKET_SIZE,
+ 	.break_ctl =		usb_debug_break_ctl,
+ 	.process_read_urb =	usb_debug_process_read_urb,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&debug_device, NULL
++};
++
+ static int __init debug_init(void)
+ {
+-	int retval;
+-
+-	retval = usb_serial_register(&debug_device);
+-	if (retval)
+-		return retval;
+-	retval = usb_register(&debug_driver);
+-	if (retval)
+-		usb_serial_deregister(&debug_device);
+-	return retval;
++	return usb_serial_register_drivers(&debug_driver, serial_drivers);
+ }
+ 
+ static void __exit debug_exit(void)
+ {
+-	usb_deregister(&debug_driver);
+-	usb_serial_deregister(&debug_device);
++	usb_serial_deregister_drivers(&debug_driver, serial_drivers);
+ }
+ 
+ module_init(debug_init);
+diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
+index 210e4b10dc11..71d696474f24 100644
+--- a/drivers/usb/serial/visor.c
++++ b/drivers/usb/serial/visor.c
+@@ -173,7 +173,6 @@ static struct usb_driver visor_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table_combined,
+-	.no_dynamic_id = 	1,
+ };
+ 
+ /* All of the device info needed for the Handspring Visor,
+@@ -184,7 +183,6 @@ static struct usb_serial_driver handspring_device = {
+ 		.name =		"visor",
+ 	},
+ 	.description =		"Handspring Visor / Palm OS",
+-	.usb_driver =		&visor_driver,
+ 	.id_table =		id_table,
+ 	.num_ports =		2,
+ 	.bulk_out_size =	256,
+@@ -205,7 +203,6 @@ static struct usb_serial_driver clie_5_device = {
+ 		.name =		"clie_5",
+ 	},
+ 	.description =		"Sony Clie 5.0",
+-	.usb_driver =		&visor_driver,
+ 	.id_table =		clie_id_5_table,
+ 	.num_ports =		2,
+ 	.bulk_out_size =	256,
+@@ -226,7 +223,6 @@ static struct usb_serial_driver clie_3_5_device = {
+ 		.name =		"clie_3.5",
+ 	},
+ 	.description =		"Sony Clie 3.5",
+-	.usb_driver =		&visor_driver,
+ 	.id_table =		clie_id_3_5_table,
+ 	.num_ports =		1,
+ 	.bulk_out_size =	256,
+@@ -237,6 +233,10 @@ static struct usb_serial_driver clie_3_5_device = {
+ 	.attach =		clie_3_5_startup,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&handspring_device, &clie_5_device, &clie_3_5_device, NULL
++};
++
+ /******************************************************************************
+  * Handspring Visor specific driver functions
+  ******************************************************************************/
+@@ -685,38 +685,17 @@ static int __init visor_init(void)
+ 		       ": Adding Palm OS protocol 4.x support for unknown device: 0x%x/0x%x\n",
+ 			vendor, product);
+ 	}
+-	retval = usb_serial_register(&handspring_device);
+-	if (retval)
+-		goto failed_handspring_register;
+-	retval = usb_serial_register(&clie_3_5_device);
+-	if (retval)
+-		goto failed_clie_3_5_register;
+-	retval = usb_serial_register(&clie_5_device);
+-	if (retval)
+-		goto failed_clie_5_register;
+-	retval = usb_register(&visor_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
+ 
+-	return 0;
+-failed_usb_register:
+-	usb_serial_deregister(&clie_5_device);
+-failed_clie_5_register:
+-	usb_serial_deregister(&clie_3_5_device);
+-failed_clie_3_5_register:
+-	usb_serial_deregister(&handspring_device);
+-failed_handspring_register:
++	retval = usb_serial_register_drivers(&visor_driver, serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
+ 	return retval;
+ }
+ 
+ 
+ static void __exit visor_exit (void)
+ {
+-	usb_deregister(&visor_driver);
+-	usb_serial_deregister(&handspring_device);
+-	usb_serial_deregister(&clie_3_5_device);
+-	usb_serial_deregister(&clie_5_device);
++	usb_serial_deregister_drivers(&visor_driver, serial_drivers);
+ }
+ 
+ 
+diff --git a/drivers/usb/serial/vivopay-serial.c b/drivers/usb/serial/vivopay-serial.c
+index f719d00972fc..a6f113bd4fae 100644
+--- a/drivers/usb/serial/vivopay-serial.c
++++ b/drivers/usb/serial/vivopay-serial.c
+@@ -30,7 +30,6 @@ static struct usb_driver vivopay_serial_driver = {
+ 	.probe =		usb_serial_probe,
+ 	.disconnect =		usb_serial_disconnect,
+ 	.id_table =		id_table,
+-	.no_dynamic_id =	1,
+ };
+ 
+ static struct usb_serial_driver vivopay_serial_device = {
+@@ -39,32 +38,28 @@ static struct usb_serial_driver vivopay_serial_device = {
+ 		.name =		"vivopay-serial",
+ 	},
+ 	.id_table =		id_table,
+-	.usb_driver =		&vivopay_serial_driver,
+ 	.num_ports =		1,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&vivopay_serial_device, NULL
++};
++
+ static int __init vivopay_serial_init(void)
+ {
+ 	int retval;
+-	retval = usb_serial_register(&vivopay_serial_device);
+-	if (retval)
+-		goto failed_usb_serial_register;
+-	retval = usb_register(&vivopay_serial_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	    DRIVER_DESC "\n");
+-	return 0;
+-failed_usb_register:
+-	usb_serial_deregister(&vivopay_serial_device);
+-failed_usb_serial_register:
++
++	retval = usb_serial_register_drivers(&vivopay_serial_driver,
++			serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++				DRIVER_DESC "\n");
+ 	return retval;
+ }
+ 
+ static void __exit vivopay_serial_exit(void)
+ {
+-	usb_deregister(&vivopay_serial_driver);
+-	usb_serial_deregister(&vivopay_serial_device);
++	usb_serial_deregister_drivers(&vivopay_serial_driver, serial_drivers);
+ }
+ 
+ module_init(vivopay_serial_init);
+diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
+index 007cf3a2481a..a29be37a3a67 100644
+--- a/drivers/usb/serial/whiteheat.c
++++ b/drivers/usb/serial/whiteheat.c
+@@ -83,7 +83,6 @@ static struct usb_driver whiteheat_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table_combined,
+-	.no_dynamic_id = 	1,
+ };
+ 
+ /* function prototypes for the Connect Tech WhiteHEAT prerenumeration device */
+@@ -121,7 +120,6 @@ static struct usb_serial_driver whiteheat_fake_device = {
+ 		.name =		"whiteheatnofirm",
+ 	},
+ 	.description =		"Connect Tech - WhiteHEAT - (prerenumeration)",
+-	.usb_driver =		&whiteheat_driver,
+ 	.id_table =		id_table_prerenumeration,
+ 	.num_ports =		1,
+ 	.probe =		whiteheat_firmware_download,
+@@ -134,7 +132,6 @@ static struct usb_serial_driver whiteheat_device = {
+ 		.name =		"whiteheat",
+ 	},
+ 	.description =		"Connect Tech - WhiteHEAT",
+-	.usb_driver =		&whiteheat_driver,
+ 	.id_table =		id_table_std,
+ 	.num_ports =		4,
+ 	.attach =		whiteheat_attach,
+@@ -155,6 +152,9 @@ static struct usb_serial_driver whiteheat_device = {
+ 	.write_bulk_callback =	whiteheat_write_callback,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&whiteheat_fake_device, &whiteheat_device, NULL
++};
+ 
+ struct whiteheat_command_private {
+ 	struct mutex		mutex;
+@@ -1461,32 +1461,18 @@ static void rx_data_softint(struct work_struct *work)
+ static int __init whiteheat_init(void)
+ {
+ 	int retval;
+-	retval = usb_serial_register(&whiteheat_fake_device);
+-	if (retval)
+-		goto failed_fake_register;
+-	retval = usb_serial_register(&whiteheat_device);
+-	if (retval)
+-		goto failed_device_register;
+-	retval = usb_register(&whiteheat_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
+-	return 0;
+-failed_usb_register:
+-	usb_serial_deregister(&whiteheat_device);
+-failed_device_register:
+-	usb_serial_deregister(&whiteheat_fake_device);
+-failed_fake_register:
++
++	retval = usb_serial_register_drivers(&whiteheat_driver, serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++				DRIVER_DESC "\n");
+ 	return retval;
+ }
+ 
+ 
+ static void __exit whiteheat_exit(void)
+ {
+-	usb_deregister(&whiteheat_driver);
+-	usb_serial_deregister(&whiteheat_fake_device);
+-	usb_serial_deregister(&whiteheat_device);
++	usb_serial_deregister_drivers(&whiteheat_driver, serial_drivers);
+ }
+ 
+ 
+diff --git a/drivers/usb/serial/zio.c b/drivers/usb/serial/zio.c
+index f57967278833..ae8115aab77d 100644
+--- a/drivers/usb/serial/zio.c
++++ b/drivers/usb/serial/zio.c
+@@ -27,7 +27,6 @@ static struct usb_driver zio_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table,
+-	.no_dynamic_id =	1,
+ };
+ 
+ static struct usb_serial_driver zio_device = {
+@@ -36,27 +35,21 @@ static struct usb_serial_driver zio_device = {
+ 		.name =		"zio",
+ 	},
+ 	.id_table =		id_table,
+-	.usb_driver =		&zio_driver,
+ 	.num_ports =		1,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&zio_device, NULL
++};
++
+ static int __init zio_init(void)
+ {
+-	int retval;
+-
+-	retval = usb_serial_register(&zio_device);
+-	if (retval)
+-		return retval;
+-	retval = usb_register(&zio_driver);
+-	if (retval)
+-		usb_serial_deregister(&zio_device);
+-	return retval;
++	return usb_serial_register_drivers(&zio_driver, serial_drivers);
+ }
+ 
+ static void __exit zio_exit(void)
+ {
+-	usb_deregister(&zio_driver);
+-	usb_serial_deregister(&zio_device);
++	usb_serial_deregister_drivers(&zio_driver, serial_drivers);
+ }
+ 
+ module_init(zio_init);

commit d860322f34e4a53f347b1aeae23d5b72f1e91b8c
+Author: Alan Stern 
+Date:   Thu Feb 23 14:57:25 2012 -0500
+
+    usb-serial: use new registration API in [q-s]* drivers
+    
+    This patch (as1528) modifies the following usb-serial drivers to
+    utilize the new usb_serial_{de}register_drivers() routines:
+    
+            qcaux, qcserial, safe_serial, siemens_mpi, sierra,
+            spcp8x5, ssu100, and symbolserial.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c
+index a34819884c1a..a2ce274b3f28 100644
+--- a/drivers/usb/serial/qcaux.c
++++ b/drivers/usb/serial/qcaux.c
+@@ -82,7 +82,6 @@ static struct usb_driver qcaux_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table,
+-	.no_dynamic_id = 	1,
+ };
+ 
+ static struct usb_serial_driver qcaux_device = {
+@@ -91,27 +90,21 @@ static struct usb_serial_driver qcaux_device = {
+ 		.name =		"qcaux",
+ 	},
+ 	.id_table =		id_table,
+-	.usb_driver =		&qcaux_driver,
+ 	.num_ports =		1,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&qcaux_device, NULL
++};
++
+ static int __init qcaux_init(void)
+ {
+-	int retval;
+-
+-	retval = usb_serial_register(&qcaux_device);
+-	if (retval)
+-		return retval;
+-	retval = usb_register(&qcaux_driver);
+-	if (retval)
+-		usb_serial_deregister(&qcaux_device);
+-	return retval;
++	return usb_serial_register_drivers(&qcaux_driver, serial_drivers);
+ }
+ 
+ static void __exit qcaux_exit(void)
+ {
+-	usb_deregister(&qcaux_driver);
+-	usb_serial_deregister(&qcaux_device);
++	usb_serial_deregister_drivers(&qcaux_driver, serial_drivers);
+ }
+ 
+ module_init(qcaux_init);
+diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
+index f98800f2324c..70e9f1abdad1 100644
+--- a/drivers/usb/serial/qcserial.c
++++ b/drivers/usb/serial/qcserial.c
+@@ -246,7 +246,6 @@ static struct usb_serial_driver qcdevice = {
+ 	},
+ 	.description         = "Qualcomm USB modem",
+ 	.id_table            = id_table,
+-	.usb_driver          = &qcdriver,
+ 	.num_ports           = 1,
+ 	.probe               = qcprobe,
+ 	.open		     = usb_wwan_open,
+@@ -263,27 +262,18 @@ static struct usb_serial_driver qcdevice = {
+ #endif
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&qcdevice, NULL
++};
++
+ static int __init qcinit(void)
+ {
+-	int retval;
+-
+-	retval = usb_serial_register(&qcdevice);
+-	if (retval)
+-		return retval;
+-
+-	retval = usb_register(&qcdriver);
+-	if (retval) {
+-		usb_serial_deregister(&qcdevice);
+-		return retval;
+-	}
+-
+-	return 0;
++	return usb_serial_register_drivers(&qcdriver, serial_drivers);
+ }
+ 
+ static void __exit qcexit(void)
+ {
+-	usb_deregister(&qcdriver);
+-	usb_serial_deregister(&qcdevice);
++	usb_serial_deregister_drivers(&qcdriver, serial_drivers);
+ }
+ 
+ module_init(qcinit);
+diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
+index d074b3740dcb..ae4ee30c7411 100644
+--- a/drivers/usb/serial/safe_serial.c
++++ b/drivers/usb/serial/safe_serial.c
+@@ -156,7 +156,6 @@ static struct usb_driver safe_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table,
+-	.no_dynamic_id = 	1,
+ };
+ 
+ static const __u16 crc10_table[256] = {
+@@ -309,16 +308,19 @@ static struct usb_serial_driver safe_device = {
+ 		.name =		"safe_serial",
+ 	},
+ 	.id_table =		id_table,
+-	.usb_driver =		&safe_driver,
+ 	.num_ports =		1,
+ 	.process_read_urb =	safe_process_read_urb,
+ 	.prepare_write_buffer =	safe_prepare_write_buffer,
+ 	.attach =		safe_startup,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&safe_device, NULL
++};
++
+ static int __init safe_init(void)
+ {
+-	int i, retval;
++	int i;
+ 
+ 	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ 	       DRIVER_DESC "\n");
+@@ -337,24 +339,12 @@ static int __init safe_init(void)
+ 		}
+ 	}
+ 
+-	retval = usb_serial_register(&safe_device);
+-	if (retval)
+-		goto failed_usb_serial_register;
+-	retval = usb_register(&safe_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-
+-	return 0;
+-failed_usb_register:
+-	usb_serial_deregister(&safe_device);
+-failed_usb_serial_register:
+-	return retval;
++	return usb_serial_register_drivers(&safe_driver, serial_drivers);
+ }
+ 
+ static void __exit safe_exit(void)
+ {
+-	usb_deregister(&safe_driver);
+-	usb_serial_deregister(&safe_device);
++	usb_serial_deregister_drivers(&safe_driver, serial_drivers);
+ }
+ 
+ module_init(safe_init);
+diff --git a/drivers/usb/serial/siemens_mpi.c b/drivers/usb/serial/siemens_mpi.c
+index 74cd4ccdb3fc..8aa4c1aef6d1 100644
+--- a/drivers/usb/serial/siemens_mpi.c
++++ b/drivers/usb/serial/siemens_mpi.c
+@@ -42,33 +42,29 @@ static struct usb_serial_driver siemens_usb_mpi_device = {
+ 		.name =		"siemens_mpi",
+ 	},
+ 	.id_table =		id_table,
+-	.usb_driver =		&siemens_usb_mpi_driver,
+ 	.num_ports =		1,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&siemens_usb_mpi_device, NULL
++};
++
+ static int __init siemens_usb_mpi_init(void)
+ {
+ 	int retval;
+ 
+-	retval = usb_serial_register(&siemens_usb_mpi_device);
+-	if (retval)
+-		goto failed_usb_serial_register;
+-	retval = usb_register(&siemens_usb_mpi_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-	printk(KERN_INFO DRIVER_DESC "\n");
+-	printk(KERN_INFO DRIVER_VERSION " " DRIVER_AUTHOR "\n");
+-	return retval;
+-failed_usb_register:
+-	usb_serial_deregister(&siemens_usb_mpi_device);
+-failed_usb_serial_register:
++	retval = usb_serial_register_drivers(&siemens_usb_mpi_driver,
++			serial_drivers);
++	if (retval == 0) {
++		printk(KERN_INFO DRIVER_DESC "\n");
++		printk(KERN_INFO DRIVER_VERSION " " DRIVER_AUTHOR "\n");
++	}
+ 	return retval;
+ }
+ 
+ static void __exit siemens_usb_mpi_exit(void)
+ {
+-	usb_deregister(&siemens_usb_mpi_driver);
+-	usb_serial_deregister(&siemens_usb_mpi_device);
++	usb_serial_deregister_drivers(&siemens_usb_mpi_driver, serial_drivers);
+ }
+ 
+ module_init(siemens_usb_mpi_init);
+diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
+index fdae0a4407cb..d75a75b83e9f 100644
+--- a/drivers/usb/serial/sierra.c
++++ b/drivers/usb/serial/sierra.c
+@@ -1084,7 +1084,6 @@ static struct usb_driver sierra_driver = {
+ 	.resume     = usb_serial_resume,
+ 	.reset_resume = sierra_reset_resume,
+ 	.id_table   = id_table,
+-	.no_dynamic_id = 	1,
+ 	.supports_autosuspend =	1,
+ };
+ 
+@@ -1095,7 +1094,6 @@ static struct usb_serial_driver sierra_device = {
+ 	},
+ 	.description       = "Sierra USB modem",
+ 	.id_table          = id_table,
+-	.usb_driver        = &sierra_driver,
+ 	.calc_num_ports	   = sierra_calc_num_ports,
+ 	.probe		   = sierra_probe,
+ 	.open              = sierra_open,
+@@ -1113,34 +1111,25 @@ static struct usb_serial_driver sierra_device = {
+ 	.read_int_callback = sierra_instat_callback,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&sierra_device, NULL
++};
++
+ /* Functions used by new usb-serial code. */
+ static int __init sierra_init(void)
+ {
+ 	int retval;
+-	retval = usb_serial_register(&sierra_device);
+-	if (retval)
+-		goto failed_device_register;
+-
+-
+-	retval = usb_register(&sierra_driver);
+-	if (retval)
+-		goto failed_driver_register;
+-
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
+-
+-	return 0;
+ 
+-failed_driver_register:
+-	usb_serial_deregister(&sierra_device);
+-failed_device_register:
++	retval = usb_serial_register_drivers(&sierra_driver, serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++			       DRIVER_DESC "\n");
+ 	return retval;
+ }
+ 
+ static void __exit sierra_exit(void)
+ {
+-	usb_deregister(&sierra_driver);
+-	usb_serial_deregister(&sierra_device);
++	usb_serial_deregister_drivers(&sierra_driver, serial_drivers);
+ }
+ 
+ module_init(sierra_init);
+diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
+index d7f5eee18f00..af898937d4b1 100644
+--- a/drivers/usb/serial/spcp8x5.c
++++ b/drivers/usb/serial/spcp8x5.c
+@@ -156,7 +156,6 @@ static struct usb_driver spcp8x5_driver = {
+ 	.probe =		usb_serial_probe,
+ 	.disconnect =		usb_serial_disconnect,
+ 	.id_table =		id_table,
+-	.no_dynamic_id =	1,
+ };
+ 
+ 
+@@ -649,7 +648,6 @@ static struct usb_serial_driver spcp8x5_device = {
+ 		.name =		"SPCP8x5",
+ 	},
+ 	.id_table		= id_table,
+-	.usb_driver		= &spcp8x5_driver,
+ 	.num_ports		= 1,
+ 	.open 			= spcp8x5_open,
+ 	.dtr_rts		= spcp8x5_dtr_rts,
+@@ -664,28 +662,24 @@ static struct usb_serial_driver spcp8x5_device = {
+ 	.process_read_urb	= spcp8x5_process_read_urb,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&spcp8x5_device, NULL
++};
++
+ static int __init spcp8x5_init(void)
+ {
+ 	int retval;
+-	retval = usb_serial_register(&spcp8x5_device);
+-	if (retval)
+-		goto failed_usb_serial_register;
+-	retval = usb_register(&spcp8x5_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
+-	return 0;
+-failed_usb_register:
+-	usb_serial_deregister(&spcp8x5_device);
+-failed_usb_serial_register:
++
++	retval = usb_serial_register_drivers(&spcp8x5_driver, serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++			       DRIVER_DESC "\n");
+ 	return retval;
+ }
+ 
+ static void __exit spcp8x5_exit(void)
+ {
+-	usb_deregister(&spcp8x5_driver);
+-	usb_serial_deregister(&spcp8x5_device);
++	usb_serial_deregister_drivers(&spcp8x5_driver, serial_drivers);
+ }
+ 
+ module_init(spcp8x5_init);
+diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
+index 7697858d8858..ab8842107a8b 100644
+--- a/drivers/usb/serial/ssu100.c
++++ b/drivers/usb/serial/ssu100.c
+@@ -70,7 +70,6 @@ static struct usb_driver ssu100_driver = {
+ 	.id_table		       = id_table,
+ 	.suspend		       = usb_serial_suspend,
+ 	.resume			       = usb_serial_resume,
+-	.no_dynamic_id		       = 1,
+ 	.supports_autosuspend	       = 1,
+ };
+ 
+@@ -677,7 +676,6 @@ static struct usb_serial_driver ssu100_device = {
+ 	},
+ 	.description	     = DRIVER_DESC,
+ 	.id_table	     = id_table,
+-	.usb_driver	     = &ssu100_driver,
+ 	.num_ports	     = 1,
+ 	.open		     = ssu100_open,
+ 	.close		     = ssu100_close,
+@@ -693,37 +691,26 @@ static struct usb_serial_driver ssu100_device = {
+ 	.disconnect          = usb_serial_generic_disconnect,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&ssu100_device, NULL
++};
++
+ static int __init ssu100_init(void)
+ {
+ 	int retval;
+ 
+ 	dbg("%s", __func__);
+ 
+-	/* register with usb-serial */
+-	retval = usb_serial_register(&ssu100_device);
+-
+-	if (retval)
+-		goto failed_usb_sio_register;
+-
+-	retval = usb_register(&ssu100_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
+-
+-	return 0;
+-
+-failed_usb_register:
+-	usb_serial_deregister(&ssu100_device);
+-failed_usb_sio_register:
++	retval = usb_serial_register_drivers(&ssu100_driver, serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++			       DRIVER_DESC "\n");
+ 	return retval;
+ }
+ 
+ static void __exit ssu100_exit(void)
+ {
+-	usb_deregister(&ssu100_driver);
+-	usb_serial_deregister(&ssu100_device);
++	usb_serial_deregister_drivers(&ssu100_driver, serial_drivers);
+ }
+ 
+ module_init(ssu100_init);
+diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c
+index 50651cf4fc61..76cd9f2a08c0 100644
+--- a/drivers/usb/serial/symbolserial.c
++++ b/drivers/usb/serial/symbolserial.c
+@@ -287,7 +287,6 @@ static struct usb_driver symbol_driver = {
+ 	.probe =		usb_serial_probe,
+ 	.disconnect =		usb_serial_disconnect,
+ 	.id_table =		id_table,
+-	.no_dynamic_id = 	1,
+ };
+ 
+ static struct usb_serial_driver symbol_device = {
+@@ -296,7 +295,6 @@ static struct usb_serial_driver symbol_device = {
+ 		.name =		"symbol",
+ 	},
+ 	.id_table =		id_table,
+-	.usb_driver = 		&symbol_driver,
+ 	.num_ports =		1,
+ 	.attach =		symbol_startup,
+ 	.open =			symbol_open,
+@@ -307,23 +305,18 @@ static struct usb_serial_driver symbol_device = {
+ 	.unthrottle =		symbol_unthrottle,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&symbol_device, NULL
++};
++
+ static int __init symbol_init(void)
+ {
+-	int retval;
+-
+-	retval = usb_serial_register(&symbol_device);
+-	if (retval)
+-		return retval;
+-	retval = usb_register(&symbol_driver);
+-	if (retval)
+-		usb_serial_deregister(&symbol_device);
+-	return retval;
++	return usb_serial_register_drivers(&symbol_driver, serial_drivers);
+ }
+ 
+ static void __exit symbol_exit(void)
+ {
+-	usb_deregister(&symbol_driver);
+-	usb_serial_deregister(&symbol_device);
++	usb_serial_deregister_drivers(&symbol_driver, serial_drivers);
+ }
+ 
+ module_init(symbol_init);

commit f667ddad41e303ebc2c6d5bf3105dffe2fbdd717
+Author: Alan Stern 
+Date:   Thu Feb 23 14:57:18 2012 -0500
+
+    usb-serial: use new registration API in [n-p]* drivers
+    
+    This patch (as1527) modifies the following usb-serial drivers to
+    utilize the new usb_serial_{de}register_drivers() routines:
+    
+            navman, omninet, opticon, option, oti6858, and pl2303.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c
+index b28f1db0195f..fd4b2c833c0b 100644
+--- a/drivers/usb/serial/navman.c
++++ b/drivers/usb/serial/navman.c
+@@ -35,7 +35,6 @@ static struct usb_driver navman_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table,
+-	.no_dynamic_id = 	1,
+ };
+ 
+ static void navman_read_int_callback(struct urb *urb)
+@@ -122,7 +121,6 @@ static struct usb_serial_driver navman_device = {
+ 		.name =		"navman",
+ 	},
+ 	.id_table =		id_table,
+-	.usb_driver =		&navman_driver,
+ 	.num_ports =		1,
+ 	.open =			navman_open,
+ 	.close = 		navman_close,
+@@ -130,23 +128,18 @@ static struct usb_serial_driver navman_device = {
+ 	.read_int_callback =	navman_read_int_callback,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&navman_device, NULL
++};
++
+ static int __init navman_init(void)
+ {
+-	int retval;
+-
+-	retval = usb_serial_register(&navman_device);
+-	if (retval)
+-		return retval;
+-	retval = usb_register(&navman_driver);
+-	if (retval)
+-		usb_serial_deregister(&navman_device);
+-	return retval;
++	return usb_serial_register_drivers(&navman_driver, serial_drivers);
+ }
+ 
+ static void __exit navman_exit(void)
+ {
+-	usb_deregister(&navman_driver);
+-	usb_serial_deregister(&navman_device);
++	usb_serial_deregister_drivers(&navman_driver, serial_drivers);
+ }
+ 
+ module_init(navman_init);
+diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
+index 033e8afa6c77..975d5c559ccb 100644
+--- a/drivers/usb/serial/omninet.c
++++ b/drivers/usb/serial/omninet.c
+@@ -62,7 +62,6 @@ static struct usb_driver omninet_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table,
+-	.no_dynamic_id = 	1,
+ };
+ 
+ 
+@@ -72,7 +71,6 @@ static struct usb_serial_driver zyxel_omninet_device = {
+ 		.name =		"omninet",
+ 	},
+ 	.description =		"ZyXEL - omni.net lcd plus usb",
+-	.usb_driver =		&omninet_driver,
+ 	.id_table =		id_table,
+ 	.num_ports =		1,
+ 	.attach =		omninet_attach,
+@@ -86,6 +84,10 @@ static struct usb_serial_driver zyxel_omninet_device = {
+ 	.release =		omninet_release,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&zyxel_omninet_device, NULL
++};
++
+ 
+ /* The protocol.
+  *
+@@ -323,26 +325,18 @@ static void omninet_release(struct usb_serial *serial)
+ static int __init omninet_init(void)
+ {
+ 	int retval;
+-	retval = usb_serial_register(&zyxel_omninet_device);
+-	if (retval)
+-		goto failed_usb_serial_register;
+-	retval = usb_register(&omninet_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
+-	return 0;
+-failed_usb_register:
+-	usb_serial_deregister(&zyxel_omninet_device);
+-failed_usb_serial_register:
++
++	retval = usb_serial_register_drivers(&omninet_driver, serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++			       DRIVER_DESC "\n");
+ 	return retval;
+ }
+ 
+ 
+ static void __exit omninet_exit(void)
+ {
+-	usb_deregister(&omninet_driver);
+-	usb_serial_deregister(&zyxel_omninet_device);
++	usb_serial_deregister_drivers(&omninet_driver, serial_drivers);
+ }
+ 
+ 
+diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c
+index 262ded9e076b..7001ad779b94 100644
+--- a/drivers/usb/serial/opticon.c
++++ b/drivers/usb/serial/opticon.c
+@@ -604,7 +604,6 @@ static struct usb_driver opticon_driver = {
+ 	.suspend =	opticon_suspend,
+ 	.resume =	opticon_resume,
+ 	.id_table =	id_table,
+-	.no_dynamic_id = 	1,
+ };
+ 
+ static struct usb_serial_driver opticon_device = {
+@@ -613,7 +612,6 @@ static struct usb_serial_driver opticon_device = {
+ 		.name =		"opticon",
+ 	},
+ 	.id_table =		id_table,
+-	.usb_driver = 		&opticon_driver,
+ 	.num_ports =		1,
+ 	.attach =		opticon_startup,
+ 	.open =			opticon_open,
+@@ -629,23 +627,18 @@ static struct usb_serial_driver opticon_device = {
+ 	.tiocmset =		opticon_tiocmset,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&opticon_device, NULL
++};
++
+ static int __init opticon_init(void)
+ {
+-	int retval;
+-
+-	retval = usb_serial_register(&opticon_device);
+-	if (retval)
+-		return retval;
+-	retval = usb_register(&opticon_driver);
+-	if (retval)
+-		usb_serial_deregister(&opticon_device);
+-	return retval;
++	return usb_serial_register_drivers(&opticon_driver, serial_drivers);
+ }
+ 
+ static void __exit opticon_exit(void)
+ {
+-	usb_deregister(&opticon_driver);
+-	usb_serial_deregister(&opticon_device);
++	usb_serial_deregister_drivers(&opticon_driver, serial_drivers);
+ }
+ 
+ module_init(opticon_init);
+diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
+index b54afceb9611..138a7b98cda4 100644
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -1212,7 +1212,6 @@ static struct usb_driver option_driver = {
+ 	.supports_autosuspend =	1,
+ #endif
+ 	.id_table   = option_ids,
+-	.no_dynamic_id = 	1,
+ };
+ 
+ /* The card has three separate interfaces, which the serial driver
+@@ -1225,7 +1224,6 @@ static struct usb_serial_driver option_1port_device = {
+ 		.name =		"option1",
+ 	},
+ 	.description       = "GSM modem (1-port)",
+-	.usb_driver        = &option_driver,
+ 	.id_table          = option_ids,
+ 	.num_ports         = 1,
+ 	.probe             = option_probe,
+@@ -1249,6 +1247,10 @@ static struct usb_serial_driver option_1port_device = {
+ #endif
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&option_1port_device, NULL
++};
++
+ static bool debug;
+ 
+ /* per port private data */
+@@ -1284,28 +1286,17 @@ struct option_port_private {
+ static int __init option_init(void)
+ {
+ 	int retval;
+-	retval = usb_serial_register(&option_1port_device);
+-	if (retval)
+-		goto failed_1port_device_register;
+-	retval = usb_register(&option_driver);
+-	if (retval)
+-		goto failed_driver_register;
+-
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
+-
+-	return 0;
+ 
+-failed_driver_register:
+-	usb_serial_deregister(&option_1port_device);
+-failed_1port_device_register:
++	retval = usb_serial_register_drivers(&option_driver, serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++			       DRIVER_DESC "\n");
+ 	return retval;
+ }
+ 
+ static void __exit option_exit(void)
+ {
+-	usb_deregister(&option_driver);
+-	usb_serial_deregister(&option_1port_device);
++	usb_serial_deregister_drivers(&option_driver, serial_drivers);
+ }
+ 
+ module_init(option_init);
+diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
+index 343e626a06f8..53f2768c9a36 100644
+--- a/drivers/usb/serial/oti6858.c
++++ b/drivers/usb/serial/oti6858.c
+@@ -71,7 +71,6 @@ static struct usb_driver oti6858_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table,
+-	.no_dynamic_id = 	1,
+ };
+ 
+ static bool debug;
+@@ -157,7 +156,6 @@ static struct usb_serial_driver oti6858_device = {
+ 		.name =		"oti6858",
+ 	},
+ 	.id_table =		id_table,
+-	.usb_driver =		&oti6858_driver,
+ 	.num_ports =		1,
+ 	.open =			oti6858_open,
+ 	.close =		oti6858_close,
+@@ -176,6 +174,10 @@ static struct usb_serial_driver oti6858_device = {
+ 	.release =		oti6858_release,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&oti6858_device, NULL
++};
++
+ struct oti6858_private {
+ 	spinlock_t lock;
+ 
+@@ -960,21 +962,12 @@ static void oti6858_write_bulk_callback(struct urb *urb)
+ 
+ static int __init oti6858_init(void)
+ {
+-	int retval;
+-
+-	retval = usb_serial_register(&oti6858_device);
+-	if (retval == 0) {
+-		retval = usb_register(&oti6858_driver);
+-		if (retval)
+-			usb_serial_deregister(&oti6858_device);
+-	}
+-	return retval;
++	return usb_serial_register_drivers(&oti6858_driver, serial_drivers);
+ }
+ 
+ static void __exit oti6858_exit(void)
+ {
+-	usb_deregister(&oti6858_driver);
+-	usb_serial_deregister(&oti6858_device);
++	usb_serial_deregister_drivers(&oti6858_driver, serial_drivers);
+ }
+ 
+ module_init(oti6858_init);
+diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
+index 3d8cda57ce7a..cc65d810c8f5 100644
+--- a/drivers/usb/serial/pl2303.c
++++ b/drivers/usb/serial/pl2303.c
+@@ -104,7 +104,6 @@ static struct usb_driver pl2303_driver = {
+ 	.id_table =	id_table,
+ 	.suspend =      usb_serial_suspend,
+ 	.resume =       usb_serial_resume,
+-	.no_dynamic_id = 	1,
+ 	.supports_autosuspend =	1,
+ };
+ 
+@@ -834,7 +833,6 @@ static struct usb_serial_driver pl2303_device = {
+ 		.name =		"pl2303",
+ 	},
+ 	.id_table =		id_table,
+-	.usb_driver = 		&pl2303_driver,
+ 	.num_ports =		1,
+ 	.bulk_in_size =		256,
+ 	.bulk_out_size =	256,
+@@ -853,28 +851,23 @@ static struct usb_serial_driver pl2303_device = {
+ 	.release =		pl2303_release,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&pl2303_device, NULL
++};
++
+ static int __init pl2303_init(void)
+ {
+ 	int retval;
+ 
+-	retval = usb_serial_register(&pl2303_device);
+-	if (retval)
+-		goto failed_usb_serial_register;
+-	retval = usb_register(&pl2303_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
+-	return 0;
+-failed_usb_register:
+-	usb_serial_deregister(&pl2303_device);
+-failed_usb_serial_register:
++	retval = usb_serial_register_drivers(&pl2303_driver, serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
+ 	return retval;
+ }
+ 
+ static void __exit pl2303_exit(void)
+ {
+-	usb_deregister(&pl2303_driver);
+-	usb_serial_deregister(&pl2303_device);
++	usb_serial_deregister_drivers(&pl2303_driver, serial_drivers);
+ }
+ 
+ module_init(pl2303_init);

commit 4d2a7aff1062048ea59214b49ca1d915586d6d6d
+Author: Alan Stern 
+Date:   Thu Feb 23 14:57:09 2012 -0500
+
+    usb-serial: use new registration API in [k-m]* drivers
+    
+    This patch (as1526) modifies the following usb-serial drivers to
+    utilize the new usb_serial_{de}register_drivers() routines:
+    
+            keyspan, kl5kusb105, kobil_sct, mct_u232, mos7720,
+            mos7840, and moto_modem.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
+index 4cc36c761801..0d5d3025a663 100644
+--- a/drivers/usb/serial/keyspan.c
++++ b/drivers/usb/serial/keyspan.c
+@@ -134,45 +134,17 @@ struct keyspan_port_private {
+ static int __init keyspan_init(void)
+ {
+ 	int retval;
+-	retval = usb_serial_register(&keyspan_pre_device);
+-	if (retval)
+-		goto failed_pre_device_register;
+-	retval = usb_serial_register(&keyspan_1port_device);
+-	if (retval)
+-		goto failed_1port_device_register;
+-	retval = usb_serial_register(&keyspan_2port_device);
+-	if (retval)
+-		goto failed_2port_device_register;
+-	retval = usb_serial_register(&keyspan_4port_device);
+-	if (retval)
+-		goto failed_4port_device_register;
+-	retval = usb_register(&keyspan_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
+ 
+-	return 0;
+-failed_usb_register:
+-	usb_serial_deregister(&keyspan_4port_device);
+-failed_4port_device_register:
+-	usb_serial_deregister(&keyspan_2port_device);
+-failed_2port_device_register:
+-	usb_serial_deregister(&keyspan_1port_device);
+-failed_1port_device_register:
+-	usb_serial_deregister(&keyspan_pre_device);
+-failed_pre_device_register:
++	retval = usb_serial_register_drivers(&keyspan_driver, serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++			       DRIVER_DESC "\n");
+ 	return retval;
+ }
+ 
+ static void __exit keyspan_exit(void)
+ {
+-	usb_deregister(&keyspan_driver);
+-	usb_serial_deregister(&keyspan_pre_device);
+-	usb_serial_deregister(&keyspan_1port_device);
+-	usb_serial_deregister(&keyspan_2port_device);
+-	usb_serial_deregister(&keyspan_4port_device);
++	usb_serial_deregister_drivers(&keyspan_driver, serial_drivers);
+ }
+ 
+ module_init(keyspan_init);
+diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
+index 13fa1d1cc900..622853c9e384 100644
+--- a/drivers/usb/serial/keyspan.h
++++ b/drivers/usb/serial/keyspan.h
+@@ -492,7 +492,6 @@ static struct usb_driver keyspan_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	keyspan_ids_combined,
+-	.no_dynamic_id = 	1,
+ };
+ 
+ /* usb_device_id table for the pre-firmware download keyspan devices */
+@@ -545,7 +544,6 @@ static struct usb_serial_driver keyspan_pre_device = {
+ 		.name		= "keyspan_no_firm",
+ 	},
+ 	.description		= "Keyspan - (without firmware)",
+-	.usb_driver		= &keyspan_driver,
+ 	.id_table		= keyspan_pre_ids,
+ 	.num_ports		= 1,
+ 	.attach			= keyspan_fake_startup,
+@@ -557,7 +555,6 @@ static struct usb_serial_driver keyspan_1port_device = {
+ 		.name		= "keyspan_1",
+ 	},
+ 	.description		= "Keyspan 1 port adapter",
+-	.usb_driver		= &keyspan_driver,
+ 	.id_table		= keyspan_1port_ids,
+ 	.num_ports		= 1,
+ 	.open			= keyspan_open,
+@@ -580,7 +577,6 @@ static struct usb_serial_driver keyspan_2port_device = {
+ 		.name		= "keyspan_2",
+ 	},
+ 	.description		= "Keyspan 2 port adapter",
+-	.usb_driver		= &keyspan_driver,
+ 	.id_table		= keyspan_2port_ids,
+ 	.num_ports		= 2,
+ 	.open			= keyspan_open,
+@@ -603,7 +599,6 @@ static struct usb_serial_driver keyspan_4port_device = {
+ 		.name		= "keyspan_4",
+ 	},
+ 	.description		= "Keyspan 4 port adapter",
+-	.usb_driver		= &keyspan_driver,
+ 	.id_table		= keyspan_4port_ids,
+ 	.num_ports		= 4,
+ 	.open			= keyspan_open,
+@@ -620,4 +615,9 @@ static struct usb_serial_driver keyspan_4port_device = {
+ 	.release		= keyspan_release,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&keyspan_pre_device, &keyspan_1port_device,
++	&keyspan_2port_device, &keyspan_4port_device, NULL
++};
++
+ #endif
+diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
+index fc064e1442ca..0e65e50edd50 100644
+--- a/drivers/usb/serial/kl5kusb105.c
++++ b/drivers/usb/serial/kl5kusb105.c
+@@ -91,7 +91,6 @@ static struct usb_driver kl5kusb105d_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table,
+-	.no_dynamic_id =	1,
+ };
+ 
+ static struct usb_serial_driver kl5kusb105d_device = {
+@@ -100,7 +99,6 @@ static struct usb_serial_driver kl5kusb105d_device = {
+ 		.name =		"kl5kusb105d",
+ 	},
+ 	.description =		"KL5KUSB105D / PalmConnect",
+-	.usb_driver =		&kl5kusb105d_driver,
+ 	.id_table =		id_table,
+ 	.num_ports =		1,
+ 	.bulk_out_size =	64,
+@@ -118,6 +116,10 @@ static struct usb_serial_driver kl5kusb105d_device = {
+ 	.prepare_write_buffer =	klsi_105_prepare_write_buffer,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&kl5kusb105d_device, NULL
++};
++
+ struct klsi_105_port_settings {
+ 	__u8	pktlen;		/* always 5, it seems */
+ 	__u8	baudrate;
+@@ -694,26 +696,18 @@ static int klsi_105_tiocmset(struct tty_struct *tty,
+ static int __init klsi_105_init(void)
+ {
+ 	int retval;
+-	retval = usb_serial_register(&kl5kusb105d_device);
+-	if (retval)
+-		goto failed_usb_serial_register;
+-	retval = usb_register(&kl5kusb105d_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
+-	return 0;
+-failed_usb_register:
+-	usb_serial_deregister(&kl5kusb105d_device);
+-failed_usb_serial_register:
++
++	retval = usb_serial_register_drivers(&kl5kusb105d_driver,
++			serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++			       DRIVER_DESC "\n");
+ 	return retval;
+ }
+ 
+ static void __exit klsi_105_exit(void)
+ {
+-	usb_deregister(&kl5kusb105d_driver);
+-	usb_serial_deregister(&kl5kusb105d_device);
++	usb_serial_deregister_drivers(&kl5kusb105d_driver, serial_drivers);
+ }
+ 
+ 
+diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
+index a92a3efb507b..a033dd7dc265 100644
+--- a/drivers/usb/serial/kobil_sct.c
++++ b/drivers/usb/serial/kobil_sct.c
+@@ -90,7 +90,6 @@ static struct usb_driver kobil_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table,
+-	.no_dynamic_id = 	1,
+ };
+ 
+ 
+@@ -100,7 +99,6 @@ static struct usb_serial_driver kobil_device = {
+ 		.name =		"kobil",
+ 	},
+ 	.description =		"KOBIL USB smart card terminal",
+-	.usb_driver = 		&kobil_driver,
+ 	.id_table =		id_table,
+ 	.num_ports =		1,
+ 	.attach =		kobil_startup,
+@@ -117,6 +115,9 @@ static struct usb_serial_driver kobil_device = {
+ 	.read_int_callback =	kobil_read_int_callback,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&kobil_device, NULL
++};
+ 
+ struct kobil_private {
+ 	int write_int_endpoint_address;
+@@ -685,28 +686,18 @@ static int kobil_ioctl(struct tty_struct *tty,
+ static int __init kobil_init(void)
+ {
+ 	int retval;
+-	retval = usb_serial_register(&kobil_device);
+-	if (retval)
+-		goto failed_usb_serial_register;
+-	retval = usb_register(&kobil_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
+ 
+-	return 0;
+-failed_usb_register:
+-	usb_serial_deregister(&kobil_device);
+-failed_usb_serial_register:
++	retval = usb_serial_register_drivers(&kobil_driver, serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++			       DRIVER_DESC "\n");
+ 	return retval;
+ }
+ 
+ 
+ static void __exit kobil_exit(void)
+ {
+-	usb_deregister(&kobil_driver);
+-	usb_serial_deregister(&kobil_device);
++	usb_serial_deregister_drivers(&kobil_driver, serial_drivers);
+ }
+ 
+ module_init(kobil_init);
+diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
+index 27fa9c8a77b0..6d9a7f8b13db 100644
+--- a/drivers/usb/serial/mct_u232.c
++++ b/drivers/usb/serial/mct_u232.c
+@@ -88,7 +88,6 @@ static struct usb_driver mct_u232_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table_combined,
+-	.no_dynamic_id = 	1,
+ };
+ 
+ static struct usb_serial_driver mct_u232_device = {
+@@ -97,7 +96,6 @@ static struct usb_serial_driver mct_u232_device = {
+ 		.name =		"mct_u232",
+ 	},
+ 	.description =	     "MCT U232",
+-	.usb_driver = 	     &mct_u232_driver,
+ 	.id_table =	     id_table_combined,
+ 	.num_ports =	     1,
+ 	.open =		     mct_u232_open,
+@@ -116,6 +114,10 @@ static struct usb_serial_driver mct_u232_device = {
+ 	.get_icount =        mct_u232_get_icount,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&mct_u232_device, NULL
++};
++
+ struct mct_u232_private {
+ 	spinlock_t lock;
+ 	unsigned int	     control_state; /* Modem Line Setting (TIOCM) */
+@@ -907,26 +909,18 @@ static int  mct_u232_get_icount(struct tty_struct *tty,
+ static int __init mct_u232_init(void)
+ {
+ 	int retval;
+-	retval = usb_serial_register(&mct_u232_device);
+-	if (retval)
+-		goto failed_usb_serial_register;
+-	retval = usb_register(&mct_u232_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
+-	return 0;
+-failed_usb_register:
+-	usb_serial_deregister(&mct_u232_device);
+-failed_usb_serial_register:
++
++	retval = usb_serial_register_drivers(&mct_u232_driver, serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++			       DRIVER_DESC "\n");
+ 	return retval;
+ }
+ 
+ 
+ static void __exit mct_u232_exit(void)
+ {
+-	usb_deregister(&mct_u232_driver);
+-	usb_serial_deregister(&mct_u232_device);
++	usb_serial_deregister_drivers(&mct_u232_driver, serial_drivers);
+ }
+ 
+ module_init(mct_u232_init);
+diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
+index 4fb29b4aaad6..4dfbad80418c 100644
+--- a/drivers/usb/serial/mos7720.c
++++ b/drivers/usb/serial/mos7720.c
+@@ -2169,7 +2169,6 @@ static struct usb_driver usb_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	moschip_port_id_table,
+-	.no_dynamic_id =	1,
+ };
+ 
+ static struct usb_serial_driver moschip7720_2port_driver = {
+@@ -2178,7 +2177,6 @@ static struct usb_serial_driver moschip7720_2port_driver = {
+ 		.name =		"moschip7720",
+ 	},
+ 	.description		= "Moschip 2 port adapter",
+-	.usb_driver		= &usb_driver,
+ 	.id_table		= moschip_port_id_table,
+ 	.calc_num_ports		= mos77xx_calc_num_ports,
+ 	.open			= mos7720_open,
+@@ -2201,38 +2199,26 @@ static struct usb_serial_driver moschip7720_2port_driver = {
+ 	.read_int_callback	= NULL  /* dynamically assigned in probe() */
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&moschip7720_2port_driver, NULL
++};
++
+ static int __init moschip7720_init(void)
+ {
+ 	int retval;
+ 
+ 	dbg("%s: Entering ..........", __func__);
+ 
+-	/* Register with the usb serial */
+-	retval = usb_serial_register(&moschip7720_2port_driver);
+-	if (retval)
+-		goto failed_port_device_register;
+-
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
+-
+-	/* Register with the usb */
+-	retval = usb_register(&usb_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-
+-	return 0;
+-
+-failed_usb_register:
+-	usb_serial_deregister(&moschip7720_2port_driver);
+-
+-failed_port_device_register:
++	retval = usb_serial_register_drivers(&usb_driver, serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++			       DRIVER_DESC "\n");
+ 	return retval;
+ }
+ 
+ static void __exit moschip7720_exit(void)
+ {
+-	usb_deregister(&usb_driver);
+-	usb_serial_deregister(&moschip7720_2port_driver);
++	usb_serial_deregister_drivers(&usb_driver, serial_drivers);
+ }
+ 
+ module_init(moschip7720_init);
+diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
+index 19b11cece6ba..b45522e12f68 100644
+--- a/drivers/usb/serial/mos7840.c
++++ b/drivers/usb/serial/mos7840.c
+@@ -2638,7 +2638,6 @@ static struct usb_driver io_driver = {
+ 	.probe = usb_serial_probe,
+ 	.disconnect = usb_serial_disconnect,
+ 	.id_table = moschip_id_table_combined,
+-	.no_dynamic_id = 1,
+ };
+ 
+ static struct usb_serial_driver moschip7840_4port_device = {
+@@ -2647,7 +2646,6 @@ static struct usb_serial_driver moschip7840_4port_device = {
+ 		   .name = "mos7840",
+ 		   },
+ 	.description = DRIVER_DESC,
+-	.usb_driver = &io_driver,
+ 	.id_table = moschip_port_id_table,
+ 	.num_ports = 4,
+ 	.open = mos7840_open,
+@@ -2674,6 +2672,10 @@ static struct usb_serial_driver moschip7840_4port_device = {
+ 	.read_int_callback = mos7840_interrupt_callback,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&moschip7840_4port_device, NULL
++};
++
+ /****************************************************************************
+  * moschip7840_init
+  *	This is called by the module subsystem, or on startup to initialize us
+@@ -2684,24 +2686,12 @@ static int __init moschip7840_init(void)
+ 
+ 	dbg("%s", " mos7840_init :entering..........");
+ 
+-	/* Register with the usb serial */
+-	retval = usb_serial_register(&moschip7840_4port_device);
+-
+-	if (retval)
+-		goto failed_port_device_register;
+-
+-	dbg("%s", "Entering...");
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
++	retval = usb_serial_register_drivers(&io_driver, serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++			       DRIVER_DESC "\n");
+ 
+-	/* Register with the usb */
+-	retval = usb_register(&io_driver);
+-	if (retval == 0) {
+-		dbg("%s", "Leaving...");
+-		return 0;
+-	}
+-	usb_serial_deregister(&moschip7840_4port_device);
+-failed_port_device_register:
++	dbg("%s", "Leaving...");
+ 	return retval;
+ }
+ 
+@@ -2714,9 +2704,7 @@ static void __exit moschip7840_exit(void)
+ 
+ 	dbg("%s", " mos7840_exit :entering..........");
+ 
+-	usb_deregister(&io_driver);
+-
+-	usb_serial_deregister(&moschip7840_4port_device);
++	usb_serial_deregister_drivers(&io_driver, serial_drivers);
+ 
+ 	dbg("%s", "Entering...");
+ }
+diff --git a/drivers/usb/serial/moto_modem.c b/drivers/usb/serial/moto_modem.c
+index e2bfecc46402..0af57d31ab82 100644
+--- a/drivers/usb/serial/moto_modem.c
++++ b/drivers/usb/serial/moto_modem.c
+@@ -36,7 +36,6 @@ static struct usb_driver moto_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table,
+-	.no_dynamic_id = 	1,
+ };
+ 
+ static struct usb_serial_driver moto_device = {
+@@ -45,27 +44,21 @@ static struct usb_serial_driver moto_device = {
+ 		.name =		"moto-modem",
+ 	},
+ 	.id_table =		id_table,
+-	.usb_driver =		&moto_driver,
+ 	.num_ports =		1,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&moto_device, NULL
++};
++
+ static int __init moto_init(void)
+ {
+-	int retval;
+-
+-	retval = usb_serial_register(&moto_device);
+-	if (retval)
+-		return retval;
+-	retval = usb_register(&moto_driver);
+-	if (retval)
+-		usb_serial_deregister(&moto_device);
+-	return retval;
++	return usb_serial_register_drivers(&moto_driver, serial_drivers);
+ }
+ 
+ static void __exit moto_exit(void)
+ {
+-	usb_deregister(&moto_driver);
+-	usb_serial_deregister(&moto_device);
++	usb_serial_deregister_drivers(&moto_driver, serial_drivers);
+ }
+ 
+ module_init(moto_init);

commit 7dbe2460989b10644651e779b17b683627feea48
+Author: Alan Stern 
+Date:   Thu Feb 23 14:56:57 2012 -0500
+
+    usb-serial: use new registration API in [i-j]* drivers
+    
+    This patch (as1525) modifies the following usb-serial drivers to
+    utilize the new usb_serial_{de}register_drivers() routines:
+    
+            io_edgeport, io_ti, ipaq, ipw, ir-usb, and iuu_phoenix.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
+index 616b07862771..55afa233aacd 100644
+--- a/drivers/usb/serial/io_edgeport.c
++++ b/drivers/usb/serial/io_edgeport.c
+@@ -3189,35 +3189,12 @@ static int __init edgeport_init(void)
+ {
+ 	int retval;
+ 
+-	retval = usb_serial_register(&edgeport_2port_device);
+-	if (retval)
+-		goto failed_2port_device_register;
+-	retval = usb_serial_register(&edgeport_4port_device);
+-	if (retval)
+-		goto failed_4port_device_register;
+-	retval = usb_serial_register(&edgeport_8port_device);
+-	if (retval)
+-		goto failed_8port_device_register;
+-	retval = usb_serial_register(&epic_device);
+-	if (retval)
+-		goto failed_epic_device_register;
+-	retval = usb_register(&io_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-	atomic_set(&CmdUrbs, 0);
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
+-	return 0;
+-
+-failed_usb_register:
+-	usb_serial_deregister(&epic_device);
+-failed_epic_device_register:
+-	usb_serial_deregister(&edgeport_8port_device);
+-failed_8port_device_register:
+-	usb_serial_deregister(&edgeport_4port_device);
+-failed_4port_device_register:
+-	usb_serial_deregister(&edgeport_2port_device);
+-failed_2port_device_register:
++	retval = usb_serial_register_drivers(&io_driver, serial_drivers);
++	if (retval == 0) {
++		atomic_set(&CmdUrbs, 0);
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++			       DRIVER_DESC "\n");
++	}
+ 	return retval;
+ }
+ 
+@@ -3228,11 +3205,7 @@ static int __init edgeport_init(void)
+  ****************************************************************************/
+ static void __exit edgeport_exit (void)
+ {
+-	usb_deregister(&io_driver);
+-	usb_serial_deregister(&edgeport_2port_device);
+-	usb_serial_deregister(&edgeport_4port_device);
+-	usb_serial_deregister(&edgeport_8port_device);
+-	usb_serial_deregister(&epic_device);
++	usb_serial_deregister_drivers(&io_driver, serial_drivers);
+ }
+ 
+ module_init(edgeport_init);
+diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
+index 178b22eb32b1..d0e7c9affb6f 100644
+--- a/drivers/usb/serial/io_tables.h
++++ b/drivers/usb/serial/io_tables.h
+@@ -100,7 +100,6 @@ static struct usb_driver io_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table_combined,
+-	.no_dynamic_id = 	1,
+ };
+ 
+ static struct usb_serial_driver edgeport_2port_device = {
+@@ -109,7 +108,6 @@ static struct usb_serial_driver edgeport_2port_device = {
+ 		.name		= "edgeport_2",
+ 	},
+ 	.description		= "Edgeport 2 port adapter",
+-	.usb_driver		= &io_driver,
+ 	.id_table		= edgeport_2port_id_table,
+ 	.num_ports		= 2,
+ 	.open			= edge_open,
+@@ -139,7 +137,6 @@ static struct usb_serial_driver edgeport_4port_device = {
+ 		.name		= "edgeport_4",
+ 	},
+ 	.description		= "Edgeport 4 port adapter",
+-	.usb_driver		= &io_driver,
+ 	.id_table		= edgeport_4port_id_table,
+ 	.num_ports		= 4,
+ 	.open			= edge_open,
+@@ -169,7 +166,6 @@ static struct usb_serial_driver edgeport_8port_device = {
+ 		.name		= "edgeport_8",
+ 	},
+ 	.description		= "Edgeport 8 port adapter",
+-	.usb_driver		= &io_driver,
+ 	.id_table		= edgeport_8port_id_table,
+ 	.num_ports		= 8,
+ 	.open			= edge_open,
+@@ -199,7 +195,6 @@ static struct usb_serial_driver epic_device = {
+ 		.name		= "epic",
+ 	},
+ 	.description		= "EPiC device",
+-	.usb_driver		= &io_driver,
+ 	.id_table		= Epic_port_id_table,
+ 	.num_ports		= 1,
+ 	.open			= edge_open,
+@@ -223,5 +218,10 @@ static struct usb_serial_driver epic_device = {
+ 	.write_bulk_callback	= edge_bulk_out_data_callback,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&edgeport_2port_device, &edgeport_4port_device,
++	&edgeport_8port_device, &epic_device, NULL
++};
++
+ #endif
+ 
+diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
+index 58a3697246a8..484db3331f88 100644
+--- a/drivers/usb/serial/io_ti.c
++++ b/drivers/usb/serial/io_ti.c
+@@ -202,7 +202,6 @@ static struct usb_driver io_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table_combined,
+-	.no_dynamic_id = 	1,
+ };
+ 
+ 
+@@ -2725,7 +2724,6 @@ static struct usb_serial_driver edgeport_1port_device = {
+ 		.name		= "edgeport_ti_1",
+ 	},
+ 	.description		= "Edgeport TI 1 port adapter",
+-	.usb_driver		= &io_driver,
+ 	.id_table		= edgeport_1port_id_table,
+ 	.num_ports		= 1,
+ 	.open			= edge_open,
+@@ -2757,7 +2755,6 @@ static struct usb_serial_driver edgeport_2port_device = {
+ 		.name		= "edgeport_ti_2",
+ 	},
+ 	.description		= "Edgeport TI 2 port adapter",
+-	.usb_driver		= &io_driver,
+ 	.id_table		= edgeport_2port_id_table,
+ 	.num_ports		= 2,
+ 	.open			= edge_open,
+@@ -2782,35 +2779,25 @@ static struct usb_serial_driver edgeport_2port_device = {
+ 	.write_bulk_callback	= edge_bulk_out_callback,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&edgeport_1port_device, &edgeport_2port_device, NULL
++};
++
+ 
+ static int __init edgeport_init(void)
+ {
+ 	int retval;
+-	retval = usb_serial_register(&edgeport_1port_device);
+-	if (retval)
+-		goto failed_1port_device_register;
+-	retval = usb_serial_register(&edgeport_2port_device);
+-	if (retval)
+-		goto failed_2port_device_register;
+-	retval = usb_register(&io_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
+-	return 0;
+-failed_usb_register:
+-	usb_serial_deregister(&edgeport_2port_device);
+-failed_2port_device_register:
+-	usb_serial_deregister(&edgeport_1port_device);
+-failed_1port_device_register:
++
++	retval = usb_serial_register_drivers(&io_driver, serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++			       DRIVER_DESC "\n");
+ 	return retval;
+ }
+ 
+ static void __exit edgeport_exit(void)
+ {
+-	usb_deregister(&io_driver);
+-	usb_serial_deregister(&edgeport_1port_device);
+-	usb_serial_deregister(&edgeport_2port_device);
++	usb_serial_deregister_drivers(&io_driver, serial_drivers);
+ }
+ 
+ module_init(edgeport_init);
+diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
+index 06053a920dd8..10c02b8b5664 100644
+--- a/drivers/usb/serial/ipaq.c
++++ b/drivers/usb/serial/ipaq.c
+@@ -510,7 +510,6 @@ static struct usb_driver ipaq_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	ipaq_id_table,
+-	.no_dynamic_id =	1,
+ };
+ 
+ 
+@@ -521,7 +520,6 @@ static struct usb_serial_driver ipaq_device = {
+ 		.name =		"ipaq",
+ 	},
+ 	.description =		"PocketPC PDA",
+-	.usb_driver =		&ipaq_driver,
+ 	.id_table =		ipaq_id_table,
+ 	.bulk_in_size =		256,
+ 	.bulk_out_size =	256,
+@@ -530,6 +528,10 @@ static struct usb_serial_driver ipaq_device = {
+ 	.calc_num_ports =	ipaq_calc_num_ports,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&ipaq_device, NULL
++};
++
+ static int ipaq_open(struct tty_struct *tty,
+ 			struct usb_serial_port *port)
+ {
+@@ -624,30 +626,22 @@ static int ipaq_startup(struct usb_serial *serial)
+ static int __init ipaq_init(void)
+ {
+ 	int retval;
+-	retval = usb_serial_register(&ipaq_device);
+-	if (retval)
+-		goto failed_usb_serial_register;
++
+ 	if (vendor) {
+ 		ipaq_id_table[0].idVendor = vendor;
+ 		ipaq_id_table[0].idProduct = product;
+ 	}
+-	retval = usb_register(&ipaq_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
+-	return 0;
+-failed_usb_register:
+-	usb_serial_deregister(&ipaq_device);
+-failed_usb_serial_register:
++
++	retval = usb_serial_register_drivers(&ipaq_driver, serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++			       DRIVER_DESC "\n");
+ 	return retval;
+ }
+ 
+ static void __exit ipaq_exit(void)
+ {
+-	usb_deregister(&ipaq_driver);
+-	usb_serial_deregister(&ipaq_device);
++	usb_serial_deregister_drivers(&ipaq_driver, serial_drivers);
+ }
+ 
+ 
+diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
+index 6f9356f3f99e..27b8886f1055 100644
+--- a/drivers/usb/serial/ipw.c
++++ b/drivers/usb/serial/ipw.c
+@@ -144,7 +144,6 @@ static struct usb_driver usb_ipw_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	usb_ipw_ids,
+-	.no_dynamic_id = 	1,
+ };
+ 
+ static bool debug;
+@@ -318,7 +317,6 @@ static struct usb_serial_driver ipw_device = {
+ 		.name =		"ipw",
+ 	},
+ 	.description =		"IPWireless converter",
+-	.usb_driver =		&usb_ipw_driver,
+ 	.id_table =		usb_ipw_ids,
+ 	.num_ports =		1,
+ 	.disconnect =		usb_wwan_disconnect,
+@@ -331,29 +329,25 @@ static struct usb_serial_driver ipw_device = {
+ 	.write =		usb_wwan_write,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&ipw_device, NULL
++};
+ 
+ 
+ static int __init usb_ipw_init(void)
+ {
+ 	int retval;
+ 
+-	retval = usb_serial_register(&ipw_device);
+-	if (retval)
+-		return retval;
+-	retval = usb_register(&usb_ipw_driver);
+-	if (retval) {
+-		usb_serial_deregister(&ipw_device);
+-		return retval;
+-	}
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
+-	return 0;
++	retval = usb_serial_register_drivers(&usb_ipw_driver, serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++			       DRIVER_DESC "\n");
++	return retval;
+ }
+ 
+ static void __exit usb_ipw_exit(void)
+ {
+-	usb_deregister(&usb_ipw_driver);
+-	usb_serial_deregister(&ipw_device);
++	usb_serial_deregister_drivers(&usb_ipw_driver, serial_drivers);
+ }
+ 
+ module_init(usb_ipw_init);
+diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
+index 84a396e83671..84965cd65c76 100644
+--- a/drivers/usb/serial/ir-usb.c
++++ b/drivers/usb/serial/ir-usb.c
+@@ -82,7 +82,6 @@ static struct usb_driver ir_driver = {
+ 	.probe		= usb_serial_probe,
+ 	.disconnect	= usb_serial_disconnect,
+ 	.id_table	= ir_id_table,
+-	.no_dynamic_id	= 1,
+ };
+ 
+ static struct usb_serial_driver ir_device = {
+@@ -91,7 +90,6 @@ static struct usb_serial_driver ir_device = {
+ 		.name	= "ir-usb",
+ 	},
+ 	.description		= "IR Dongle",
+-	.usb_driver		= &ir_driver,
+ 	.id_table		= ir_id_table,
+ 	.num_ports		= 1,
+ 	.set_termios		= ir_set_termios,
+@@ -101,6 +99,10 @@ static struct usb_serial_driver ir_device = {
+ 	.process_read_urb	= ir_process_read_urb,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&ir_device, NULL
++};
++
+ static inline void irda_usb_dump_class_desc(struct usb_irda_cs_descriptor *desc)
+ {
+ 	dbg("bLength=%x", desc->bLength);
+@@ -445,30 +447,16 @@ static int __init ir_init(void)
+ 		ir_device.bulk_out_size = buffer_size;
+ 	}
+ 
+-	retval = usb_serial_register(&ir_device);
+-	if (retval)
+-		goto failed_usb_serial_register;
+-
+-	retval = usb_register(&ir_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
+-
+-	return 0;
+-
+-failed_usb_register:
+-	usb_serial_deregister(&ir_device);
+-
+-failed_usb_serial_register:
++	retval = usb_serial_register_drivers(&ir_driver, serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++			       DRIVER_DESC "\n");
+ 	return retval;
+ }
+ 
+ static void __exit ir_exit(void)
+ {
+-	usb_deregister(&ir_driver);
+-	usb_serial_deregister(&ir_device);
++	usb_serial_deregister_drivers(&ir_driver, serial_drivers);
+ }
+ 
+ 
+diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
+index 3077a4436976..97a7ea2a5e4f 100644
+--- a/drivers/usb/serial/iuu_phoenix.c
++++ b/drivers/usb/serial/iuu_phoenix.c
+@@ -56,7 +56,6 @@ static struct usb_driver iuu_driver = {
+ 	.probe = usb_serial_probe,
+ 	.disconnect = usb_serial_disconnect,
+ 	.id_table = id_table,
+-	.no_dynamic_id = 1,
+ };
+ 
+ /* turbo parameter */
+@@ -1274,7 +1273,6 @@ static struct usb_serial_driver iuu_device = {
+ 		   .name = "iuu_phoenix",
+ 		   },
+ 	.id_table = id_table,
+-	.usb_driver = &iuu_driver,
+ 	.num_ports = 1,
+ 	.bulk_in_size = 512,
+ 	.bulk_out_size = 512,
+@@ -1292,28 +1290,24 @@ static struct usb_serial_driver iuu_device = {
+ 	.release = iuu_release,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&iuu_device, NULL
++};
++
+ static int __init iuu_init(void)
+ {
+ 	int retval;
+-	retval = usb_serial_register(&iuu_device);
+-	if (retval)
+-		goto failed_usb_serial_register;
+-	retval = usb_register(&iuu_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
+-	return 0;
+-failed_usb_register:
+-	usb_serial_deregister(&iuu_device);
+-failed_usb_serial_register:
++
++	retval = usb_serial_register_drivers(&iuu_driver, serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++			       DRIVER_DESC "\n");
+ 	return retval;
+ }
+ 
+ static void __exit iuu_exit(void)
+ {
+-	usb_deregister(&iuu_driver);
+-	usb_serial_deregister(&iuu_device);
++	usb_serial_deregister_drivers(&iuu_driver, serial_drivers);
+ }
+ 
+ module_init(iuu_init);

commit 97b6b6d2339f67eb17d954930a908b762af66228
+Author: Alan Stern 
+Date:   Thu Feb 23 14:56:32 2012 -0500
+
+    usb-serial: use new registration API in [d-h]* drivers
+    
+    This patch (as1524) modifies the following usb-serial drivers to
+    utilize the new usb_serial_{de}register_drivers() routines:
+    
+            digi_acceleport, empeg, ftdi_sio, funsoft, garmin_gps,
+            and hp4x.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
+index 2b1da0cc071a..f0e776bb1ffb 100644
+--- a/drivers/usb/serial/digi_acceleport.c
++++ b/drivers/usb/serial/digi_acceleport.c
+@@ -276,7 +276,6 @@ static struct usb_driver digi_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table_combined,
+-	.no_dynamic_id = 	1,
+ };
+ 
+ 
+@@ -288,7 +287,6 @@ static struct usb_serial_driver digi_acceleport_2_device = {
+ 		.name =			"digi_2",
+ 	},
+ 	.description =			"Digi 2 port USB adapter",
+-	.usb_driver = 			&digi_driver,
+ 	.id_table =			id_table_2,
+ 	.num_ports =			3,
+ 	.open =				digi_open,
+@@ -316,7 +314,6 @@ static struct usb_serial_driver digi_acceleport_4_device = {
+ 		.name =			"digi_4",
+ 	},
+ 	.description =			"Digi 4 port USB adapter",
+-	.usb_driver = 			&digi_driver,
+ 	.id_table =			id_table_4,
+ 	.num_ports =			4,
+ 	.open =				digi_open,
+@@ -337,6 +334,9 @@ static struct usb_serial_driver digi_acceleport_4_device = {
+ 	.release =			digi_release,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&digi_acceleport_2_device, &digi_acceleport_4_device, NULL
++};
+ 
+ /* Functions */
+ 
+@@ -1583,31 +1583,17 @@ static int digi_read_oob_callback(struct urb *urb)
+ static int __init digi_init(void)
+ {
+ 	int retval;
+-	retval = usb_serial_register(&digi_acceleport_2_device);
+-	if (retval)
+-		goto failed_acceleport_2_device;
+-	retval = usb_serial_register(&digi_acceleport_4_device);
+-	if (retval)
+-		goto failed_acceleport_4_device;
+-	retval = usb_register(&digi_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
+-	return 0;
+-failed_usb_register:
+-	usb_serial_deregister(&digi_acceleport_4_device);
+-failed_acceleport_4_device:
+-	usb_serial_deregister(&digi_acceleport_2_device);
+-failed_acceleport_2_device:
++
++	retval = usb_serial_register_drivers(&digi_driver, serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++			       DRIVER_DESC "\n");
+ 	return retval;
+ }
+ 
+ static void __exit digi_exit (void)
+ {
+-	usb_deregister(&digi_driver);
+-	usb_serial_deregister(&digi_acceleport_2_device);
+-	usb_serial_deregister(&digi_acceleport_4_device);
++	usb_serial_deregister_drivers(&digi_driver, serial_drivers);
+ }
+ 
+ 
+diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
+index aced6817bf95..51bcbd5d5e8e 100644
+--- a/drivers/usb/serial/empeg.c
++++ b/drivers/usb/serial/empeg.c
+@@ -56,7 +56,6 @@ static struct usb_driver empeg_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table,
+-	.no_dynamic_id =	1,
+ };
+ 
+ static struct usb_serial_driver empeg_device = {
+@@ -65,7 +64,6 @@ static struct usb_serial_driver empeg_device = {
+ 		.name =		"empeg",
+ 	},
+ 	.id_table =		id_table,
+-	.usb_driver =		&empeg_driver,
+ 	.num_ports =		1,
+ 	.bulk_out_size =	256,
+ 	.throttle =		usb_serial_generic_throttle,
+@@ -74,6 +72,10 @@ static struct usb_serial_driver empeg_device = {
+ 	.init_termios =		empeg_init_termios,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&empeg_device, NULL
++};
++
+ static int empeg_startup(struct usb_serial *serial)
+ {
+ 	int r;
+@@ -140,24 +142,16 @@ static int __init empeg_init(void)
+ {
+ 	int retval;
+ 
+-	retval = usb_serial_register(&empeg_device);
+-	if (retval)
+-		return retval;
+-	retval = usb_register(&empeg_driver);
+-	if (retval) {
+-		usb_serial_deregister(&empeg_device);
+-		return retval;
+-	}
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
+-
+-	return 0;
++	retval = usb_serial_register_drivers(&empeg_driver, serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++			       DRIVER_DESC "\n");
++	return retval;
+ }
+ 
+ static void __exit empeg_exit(void)
+ {
+-	usb_deregister(&empeg_driver);
+-	usb_serial_deregister(&empeg_device);
++	usb_serial_deregister_drivers(&empeg_driver, serial_drivers);
+ }
+ 
+ 
+diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
+index f770415305f8..615cf2c4915c 100644
+--- a/drivers/usb/serial/ftdi_sio.c
++++ b/drivers/usb/serial/ftdi_sio.c
+@@ -857,7 +857,6 @@ static struct usb_driver ftdi_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table_combined,
+-	.no_dynamic_id =	1,
+ };
+ 
+ static const char *ftdi_chip_name[] = {
+@@ -915,7 +914,6 @@ static struct usb_serial_driver ftdi_sio_device = {
+ 		.name =		"ftdi_sio",
+ 	},
+ 	.description =		"FTDI USB Serial Device",
+-	.usb_driver = 		&ftdi_driver,
+ 	.id_table =		id_table_combined,
+ 	.num_ports =		1,
+ 	.bulk_in_size =		512,
+@@ -938,6 +936,10 @@ static struct usb_serial_driver ftdi_sio_device = {
+ 	.break_ctl =		ftdi_break_ctl,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&ftdi_sio_device, NULL
++};
++
+ 
+ #define WDR_TIMEOUT 5000 /* default urb timeout */
+ #define WDR_SHORT_TIMEOUT 1000	/* shorter urb timeout */
+@@ -2420,19 +2422,10 @@ static int __init ftdi_init(void)
+ 		id_table_combined[i].idVendor = vendor;
+ 		id_table_combined[i].idProduct = product;
+ 	}
+-	retval = usb_serial_register(&ftdi_sio_device);
+-	if (retval)
+-		goto failed_sio_register;
+-	retval = usb_register(&ftdi_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
+-	return 0;
+-failed_usb_register:
+-	usb_serial_deregister(&ftdi_sio_device);
+-failed_sio_register:
++	retval = usb_serial_register_drivers(&ftdi_driver, serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++			       DRIVER_DESC "\n");
+ 	return retval;
+ }
+ 
+@@ -2440,8 +2433,7 @@ static void __exit ftdi_exit(void)
+ {
+ 	dbg("%s", __func__);
+ 
+-	usb_deregister(&ftdi_driver);
+-	usb_serial_deregister(&ftdi_sio_device);
++	usb_serial_deregister_drivers(&ftdi_driver, serial_drivers);
+ }
+ 
+ 
+diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c
+index 5d4b099dcf8b..bb274a244ae9 100644
+--- a/drivers/usb/serial/funsoft.c
++++ b/drivers/usb/serial/funsoft.c
+@@ -29,7 +29,6 @@ static struct usb_driver funsoft_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table,
+-	.no_dynamic_id = 	1,
+ };
+ 
+ static struct usb_serial_driver funsoft_device = {
+@@ -38,27 +37,21 @@ static struct usb_serial_driver funsoft_device = {
+ 		.name =		"funsoft",
+ 	},
+ 	.id_table =		id_table,
+-	.usb_driver = 		&funsoft_driver,
+ 	.num_ports =		1,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&funsoft_device, NULL
++};
++
+ static int __init funsoft_init(void)
+ {
+-	int retval;
+-
+-	retval = usb_serial_register(&funsoft_device);
+-	if (retval)
+-		return retval;
+-	retval = usb_register(&funsoft_driver);
+-	if (retval)
+-		usb_serial_deregister(&funsoft_device);
+-	return retval;
++	return usb_serial_register_drivers(&funsoft_driver, serial_drivers);
+ }
+ 
+ static void __exit funsoft_exit(void)
+ {
+-	usb_deregister(&funsoft_driver);
+-	usb_serial_deregister(&funsoft_device);
++	usb_serial_deregister_drivers(&funsoft_driver, serial_drivers);
+ }
+ 
+ module_init(funsoft_init);
+diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
+index 21343378c322..69da3abcb363 100644
+--- a/drivers/usb/serial/garmin_gps.c
++++ b/drivers/usb/serial/garmin_gps.c
+@@ -224,7 +224,6 @@ static struct usb_driver garmin_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table,
+-	.no_dynamic_id = 1,
+ };
+ 
+ 
+@@ -1497,7 +1496,6 @@ static struct usb_serial_driver garmin_device = {
+ 		.name        = "garmin_gps",
+ 	},
+ 	.description         = "Garmin GPS usb/tty",
+-	.usb_driver          = &garmin_driver,
+ 	.id_table            = id_table,
+ 	.num_ports           = 1,
+ 	.open                = garmin_open,
+@@ -1514,33 +1512,26 @@ static struct usb_serial_driver garmin_device = {
+ 	.read_int_callback   = garmin_read_int_callback,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&garmin_device, NULL
++};
+ 
+ 
+ static int __init garmin_init(void)
+ {
+ 	int retval;
+ 
+-	retval = usb_serial_register(&garmin_device);
+-	if (retval)
+-		goto failed_garmin_register;
+-	retval = usb_register(&garmin_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
+-
+-	return 0;
+-failed_usb_register:
+-	usb_serial_deregister(&garmin_device);
+-failed_garmin_register:
++	retval = usb_serial_register_drivers(&garmin_driver, serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++			       DRIVER_DESC "\n");
+ 	return retval;
+ }
+ 
+ 
+ static void __exit garmin_exit(void)
+ {
+-	usb_deregister(&garmin_driver);
+-	usb_serial_deregister(&garmin_device);
++	usb_serial_deregister_drivers(&garmin_driver, serial_drivers);
+ }
+ 
+ 
+diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c
+index 809379159b0e..325cf092b61c 100644
+--- a/drivers/usb/serial/hp4x.c
++++ b/drivers/usb/serial/hp4x.c
+@@ -41,7 +41,6 @@ static struct usb_driver hp49gp_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table,
+-	.no_dynamic_id = 	1,
+ };
+ 
+ static struct usb_serial_driver hp49gp_device = {
+@@ -50,32 +49,27 @@ static struct usb_serial_driver hp49gp_device = {
+ 		.name =		"hp4X",
+ 	},
+ 	.id_table =		id_table,
+-	.usb_driver = 		&hp49gp_driver,
+ 	.num_ports =		1,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&hp49gp_device, NULL
++};
++
+ static int __init hp49gp_init(void)
+ {
+ 	int retval;
+-	retval = usb_serial_register(&hp49gp_device);
+-	if (retval)
+-		goto failed_usb_serial_register;
+-	retval = usb_register(&hp49gp_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
+-	return 0;
+-failed_usb_register:
+-	usb_serial_deregister(&hp49gp_device);
+-failed_usb_serial_register:
++
++	retval = usb_serial_register_drivers(&hp49gp_driver, serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++			       DRIVER_DESC "\n");
+ 	return retval;
+ }
+ 
+ static void __exit hp49gp_exit(void)
+ {
+-	usb_deregister(&hp49gp_driver);
+-	usb_serial_deregister(&hp49gp_device);
++	usb_serial_deregister_drivers(&hp49gp_driver, serial_drivers);
+ }
+ 
+ module_init(hp49gp_init);

commit 08a4f6bc2e7046ce50849d7589b7d0763926d808
+Author: Alan Stern 
+Date:   Thu Feb 23 14:56:17 2012 -0500
+
+    usb-serial: use new registration API in [a-c]* drivers
+    
+    This patch (as1523) modifies the following usb-serial drivers to
+    utilize the new usb_serial_{de}register_drivers() routines:
+    
+            aircable, ark3116, belkin_sa, ch341, cp210x, cyberjack,
+            and cypress_m8.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
+index 123bf9155339..dbf3bddc1b51 100644
+--- a/drivers/usb/serial/aircable.c
++++ b/drivers/usb/serial/aircable.c
+@@ -175,7 +175,6 @@ static struct usb_driver aircable_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table,
+-	.no_dynamic_id =	1,
+ };
+ 
+ static struct usb_serial_driver aircable_device = {
+@@ -183,7 +182,6 @@ static struct usb_serial_driver aircable_device = {
+ 		.owner =	THIS_MODULE,
+ 		.name =		"aircable",
+ 	},
+-	.usb_driver = 		&aircable_driver,
+ 	.id_table = 		id_table,
+ 	.num_ports =		1,
+ 	.bulk_out_size =	HCI_COMPLETE_FRAME,
+@@ -194,27 +192,18 @@ static struct usb_serial_driver aircable_device = {
+ 	.unthrottle =		usb_serial_generic_unthrottle,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&aircable_device, NULL
++};
++
+ static int __init aircable_init(void)
+ {
+-	int retval;
+-	retval = usb_serial_register(&aircable_device);
+-	if (retval)
+-		goto failed_serial_register;
+-	retval = usb_register(&aircable_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-	return 0;
+-
+-failed_usb_register:
+-	usb_serial_deregister(&aircable_device);
+-failed_serial_register:
+-	return retval;
++	return usb_serial_register_drivers(&aircable_driver, serial_drivers);
+ }
+ 
+ static void __exit aircable_exit(void)
+ {
+-	usb_deregister(&aircable_driver);
+-	usb_serial_deregister(&aircable_device);
++	usb_serial_deregister_drivers(&aircable_driver, serial_drivers);
+ }
+ 
+ MODULE_AUTHOR(DRIVER_AUTHOR);
+diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
+index 69328dcfd91a..ab2cf1165c60 100644
+--- a/drivers/usb/serial/ark3116.c
++++ b/drivers/usb/serial/ark3116.c
+@@ -719,7 +719,6 @@ static struct usb_driver ark3116_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table,
+-	.no_dynamic_id =	1,
+ };
+ 
+ static struct usb_serial_driver ark3116_device = {
+@@ -728,7 +727,6 @@ static struct usb_serial_driver ark3116_device = {
+ 		.name =		"ark3116",
+ 	},
+ 	.id_table =		id_table,
+-	.usb_driver =		&ark3116_driver,
+ 	.num_ports =		1,
+ 	.attach =		ark3116_attach,
+ 	.release =		ark3116_release,
+@@ -745,28 +743,27 @@ static struct usb_serial_driver ark3116_device = {
+ 	.process_read_urb =	ark3116_process_read_urb,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&ark3116_device, NULL
++};
++
+ static int __init ark3116_init(void)
+ {
+ 	int retval;
+ 
+-	retval = usb_serial_register(&ark3116_device);
+-	if (retval)
+-		return retval;
+-	retval = usb_register(&ark3116_driver);
++	retval = usb_serial_register_drivers(&ark3116_driver, serial_drivers);
+ 	if (retval == 0) {
+ 		printk(KERN_INFO "%s:"
+ 		       DRIVER_VERSION ":"
+ 		       DRIVER_DESC "\n",
+ 		       KBUILD_MODNAME);
+-	} else
+-		usb_serial_deregister(&ark3116_device);
++	}
+ 	return retval;
+ }
+ 
+ static void __exit ark3116_exit(void)
+ {
+-	usb_deregister(&ark3116_driver);
+-	usb_serial_deregister(&ark3116_device);
++	usb_serial_deregister_drivers(&ark3116_driver, serial_drivers);
+ }
+ 
+ module_init(ark3116_init);
+diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
+index 29ffeb6279c7..e8b473f5acf7 100644
+--- a/drivers/usb/serial/belkin_sa.c
++++ b/drivers/usb/serial/belkin_sa.c
+@@ -78,7 +78,6 @@ static struct usb_driver belkin_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table_combined,
+-	.no_dynamic_id =	1,
+ };
+ 
+ /* All of the device info needed for the serial converters */
+@@ -88,7 +87,6 @@ static struct usb_serial_driver belkin_device = {
+ 		.name =		"belkin",
+ 	},
+ 	.description =		"Belkin / Peracom / GoHubs USB Serial Adapter",
+-	.usb_driver =		&belkin_driver,
+ 	.id_table =		id_table_combined,
+ 	.num_ports =		1,
+ 	.open =			belkin_sa_open,
+@@ -103,6 +101,10 @@ static struct usb_serial_driver belkin_device = {
+ 	.release =		belkin_sa_release,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&belkin_device, NULL
++};
++
+ struct belkin_sa_private {
+ 	spinlock_t		lock;
+ 	unsigned long		control_state;
+@@ -526,25 +528,17 @@ static int belkin_sa_tiocmset(struct tty_struct *tty,
+ static int __init belkin_sa_init(void)
+ {
+ 	int retval;
+-	retval = usb_serial_register(&belkin_device);
+-	if (retval)
+-		goto failed_usb_serial_register;
+-	retval = usb_register(&belkin_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
+-	return 0;
+-failed_usb_register:
+-	usb_serial_deregister(&belkin_device);
+-failed_usb_serial_register:
++
++	retval = usb_serial_register_drivers(&belkin_driver, serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++			       DRIVER_DESC "\n");
+ 	return retval;
+ }
+ 
+ static void __exit belkin_sa_exit (void)
+ {
+-	usb_deregister(&belkin_driver);
+-	usb_serial_deregister(&belkin_device);
++	usb_serial_deregister_drivers(&belkin_driver, serial_drivers);
+ }
+ 
+ 
+diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
+index 5e53cc59e652..23de3b039a28 100644
+--- a/drivers/usb/serial/ch341.c
++++ b/drivers/usb/serial/ch341.c
+@@ -625,7 +625,6 @@ static struct usb_driver ch341_driver = {
+ 	.resume		= usb_serial_resume,
+ 	.reset_resume	= ch341_reset_resume,
+ 	.id_table	= id_table,
+-	.no_dynamic_id	= 1,
+ 	.supports_autosuspend =	1,
+ };
+ 
+@@ -635,7 +634,6 @@ static struct usb_serial_driver ch341_device = {
+ 		.name	= "ch341-uart",
+ 	},
+ 	.id_table          = id_table,
+-	.usb_driver        = &ch341_driver,
+ 	.num_ports         = 1,
+ 	.open              = ch341_open,
+ 	.dtr_rts	   = ch341_dtr_rts,
+@@ -650,23 +648,18 @@ static struct usb_serial_driver ch341_device = {
+ 	.attach            = ch341_attach,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&ch341_device, NULL
++};
++
+ static int __init ch341_init(void)
+ {
+-	int retval;
+-
+-	retval = usb_serial_register(&ch341_device);
+-	if (retval)
+-		return retval;
+-	retval = usb_register(&ch341_driver);
+-	if (retval)
+-		usb_serial_deregister(&ch341_device);
+-	return retval;
++	return usb_serial_register_drivers(&ch341_driver, serial_drivers);
+ }
+ 
+ static void __exit ch341_exit(void)
+ {
+-	usb_deregister(&ch341_driver);
+-	usb_serial_deregister(&ch341_device);
++	usb_serial_deregister_drivers(&ch341_driver, serial_drivers);
+ }
+ 
+ module_init(ch341_init);
+diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
+index ec9dc4e9a3ff..01a9374357f1 100644
+--- a/drivers/usb/serial/cp210x.c
++++ b/drivers/usb/serial/cp210x.c
+@@ -154,7 +154,6 @@ static struct usb_driver cp210x_driver = {
+ 	.probe		= usb_serial_probe,
+ 	.disconnect	= usb_serial_disconnect,
+ 	.id_table	= id_table,
+-	.no_dynamic_id	= 	1,
+ };
+ 
+ static struct usb_serial_driver cp210x_device = {
+@@ -162,7 +161,6 @@ static struct usb_serial_driver cp210x_device = {
+ 		.owner =	THIS_MODULE,
+ 		.name = 	"cp210x",
+ 	},
+-	.usb_driver		= &cp210x_driver,
+ 	.id_table		= id_table,
+ 	.num_ports		= 1,
+ 	.bulk_in_size		= 256,
+@@ -177,6 +175,10 @@ static struct usb_serial_driver cp210x_device = {
+ 	.dtr_rts		= cp210x_dtr_rts
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&cp210x_device, NULL
++};
++
+ /* Config request types */
+ #define REQTYPE_HOST_TO_DEVICE	0x41
+ #define REQTYPE_DEVICE_TO_HOST	0xc1
+@@ -852,27 +854,16 @@ static int __init cp210x_init(void)
+ {
+ 	int retval;
+ 
+-	retval = usb_serial_register(&cp210x_device);
+-	if (retval)
+-		return retval; /* Failed to register */
+-
+-	retval = usb_register(&cp210x_driver);
+-	if (retval) {
+-		/* Failed to register */
+-		usb_serial_deregister(&cp210x_device);
+-		return retval;
+-	}
+-
+-	/* Success */
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
+-	return 0;
++	retval = usb_serial_register_drivers(&cp210x_driver, serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++			       DRIVER_DESC "\n");
++	return retval;
+ }
+ 
+ static void __exit cp210x_exit(void)
+ {
+-	usb_deregister(&cp210x_driver);
+-	usb_serial_deregister(&cp210x_device);
++	usb_serial_deregister_drivers(&cp210x_driver, serial_drivers);
+ }
+ 
+ module_init(cp210x_init);
+diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
+index 6bc3802a581a..d2e536f649ba 100644
+--- a/drivers/usb/serial/cyberjack.c
++++ b/drivers/usb/serial/cyberjack.c
+@@ -82,7 +82,6 @@ static struct usb_driver cyberjack_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table,
+-	.no_dynamic_id = 	1,
+ };
+ 
+ static struct usb_serial_driver cyberjack_device = {
+@@ -91,7 +90,6 @@ static struct usb_serial_driver cyberjack_device = {
+ 		.name =		"cyberjack",
+ 	},
+ 	.description =		"Reiner SCT Cyberjack USB card reader",
+-	.usb_driver = 		&cyberjack_driver,
+ 	.id_table =		id_table,
+ 	.num_ports =		1,
+ 	.attach =		cyberjack_startup,
+@@ -106,6 +104,10 @@ static struct usb_serial_driver cyberjack_device = {
+ 	.write_bulk_callback =	cyberjack_write_bulk_callback,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&cyberjack_device, NULL
++};
++
+ struct cyberjack_private {
+ 	spinlock_t	lock;		/* Lock for SMP */
+ 	short		rdtodo;		/* Bytes still to read */
+@@ -476,28 +478,19 @@ static void cyberjack_write_bulk_callback(struct urb *urb)
+ static int __init cyberjack_init(void)
+ {
+ 	int retval;
+-	retval  = usb_serial_register(&cyberjack_device);
+-	if (retval)
+-		goto failed_usb_serial_register;
+-	retval = usb_register(&cyberjack_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION " "
+-	       DRIVER_AUTHOR "\n");
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
+ 
+-	return 0;
+-failed_usb_register:
+-	usb_serial_deregister(&cyberjack_device);
+-failed_usb_serial_register:
++	retval = usb_serial_register_drivers(&cyberjack_driver, serial_drivers);
++	if (retval == 0) {
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION " "
++			       DRIVER_AUTHOR "\n");
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
++	}
+ 	return retval;
+ }
+ 
+ static void __exit cyberjack_exit(void)
+ {
+-	usb_deregister(&cyberjack_driver);
+-	usb_serial_deregister(&cyberjack_device);
++	usb_serial_deregister_drivers(&cyberjack_driver, serial_drivers);
+ }
+ 
+ module_init(cyberjack_init);
+diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
+index 5ae86b349cad..bc5057513d5d 100644
+--- a/drivers/usb/serial/cypress_m8.c
++++ b/drivers/usb/serial/cypress_m8.c
+@@ -94,7 +94,6 @@ static struct usb_driver cypress_driver = {
+ 	.probe =	usb_serial_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	id_table_combined,
+-	.no_dynamic_id = 	1,
+ };
+ 
+ enum packet_format {
+@@ -163,7 +162,6 @@ static struct usb_serial_driver cypress_earthmate_device = {
+ 		.name =			"earthmate",
+ 	},
+ 	.description =			"DeLorme Earthmate USB",
+-	.usb_driver = 			&cypress_driver,
+ 	.id_table =			id_table_earthmate,
+ 	.num_ports =			1,
+ 	.attach =			cypress_earthmate_startup,
+@@ -190,7 +188,6 @@ static struct usb_serial_driver cypress_hidcom_device = {
+ 		.name =			"cyphidcom",
+ 	},
+ 	.description =			"HID->COM RS232 Adapter",
+-	.usb_driver = 			&cypress_driver,
+ 	.id_table =			id_table_cyphidcomrs232,
+ 	.num_ports =			1,
+ 	.attach =			cypress_hidcom_startup,
+@@ -217,7 +214,6 @@ static struct usb_serial_driver cypress_ca42v2_device = {
+ 		.name =			"nokiaca42v2",
+ 	},
+ 	.description =			"Nokia CA-42 V2 Adapter",
+-	.usb_driver = 			&cypress_driver,
+ 	.id_table =			id_table_nokiaca42v2,
+ 	.num_ports =			1,
+ 	.attach =			cypress_ca42v2_startup,
+@@ -238,6 +234,11 @@ static struct usb_serial_driver cypress_ca42v2_device = {
+ 	.write_int_callback =		cypress_write_int_callback,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&cypress_earthmate_device, &cypress_hidcom_device,
++	&cypress_ca42v2_device, NULL
++};
++
+ /*****************************************************************************
+  * Cypress serial helper functions
+  *****************************************************************************/
+@@ -1356,30 +1357,10 @@ static int __init cypress_init(void)
+ 
+ 	dbg("%s", __func__);
+ 
+-	retval = usb_serial_register(&cypress_earthmate_device);
+-	if (retval)
+-		goto failed_em_register;
+-	retval = usb_serial_register(&cypress_hidcom_device);
+-	if (retval)
+-		goto failed_hidcom_register;
+-	retval = usb_serial_register(&cypress_ca42v2_device);
+-	if (retval)
+-		goto failed_ca42v2_register;
+-	retval = usb_register(&cypress_driver);
+-	if (retval)
+-		goto failed_usb_register;
+-
+-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+-	       DRIVER_DESC "\n");
+-	return 0;
+-
+-failed_usb_register:
+-	usb_serial_deregister(&cypress_ca42v2_device);
+-failed_ca42v2_register:
+-	usb_serial_deregister(&cypress_hidcom_device);
+-failed_hidcom_register:
+-	usb_serial_deregister(&cypress_earthmate_device);
+-failed_em_register:
++	retval = usb_serial_register_drivers(&cypress_driver, serial_drivers);
++	if (retval == 0)
++		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++			       DRIVER_DESC "\n");
+ 	return retval;
+ }
+ 
+@@ -1388,10 +1369,7 @@ static void __exit cypress_exit(void)
+ {
+ 	dbg("%s", __func__);
+ 
+-	usb_deregister(&cypress_driver);
+-	usb_serial_deregister(&cypress_earthmate_device);
+-	usb_serial_deregister(&cypress_hidcom_device);
+-	usb_serial_deregister(&cypress_ca42v2_device);
++	usb_serial_deregister_drivers(&cypress_driver, serial_drivers);
+ }
+ 
+ 

commit 765e0ba62613fb90f09c1b5926750df0aa56f349
+Author: Alan Stern 
+Date:   Thu Feb 23 14:55:59 2012 -0500
+
+    usb-serial: new API for driver registration
+    
+    This patch (as1522) adds two new routines to the usb-serial core, for
+    registering and unregistering serial drivers.  Instead of registering
+    the usb_driver and usb_serial_drivers separately, with error checking
+    for each one, the drivers can all be registered and unregistered by a
+    single function call.  This reduces duplicated code.
+    
+    More importantly, the new core routines change the order in which the
+    drivers are registered.  Currently the usb-serial drivers are all
+    registered first and the usb_driver is done last, which leaves a
+    window for problems.  A udev script may quickly add a new dynamic-ID
+    for a usb-serial driver, causing the corresponding usb_driver to be
+    probed.  If the usb_driver hasn't been registered yet then an oops
+    will occur.
+    
+    The new routine prevents such problems by registering the usb_driver
+    first.  To insure that it gets probed properly for already-attached
+    serial devices, we call driver_attach() after all the usb-serial
+    drivers have been registered.
+    
+    Along with adding the new routines, the patch modifies the "generic"
+    serial driver to use them.  Further patches will similarly modify all
+    the other in-tree USB serial drivers.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
+index 2a2fa2d0489d..664deb63807c 100644
+--- a/drivers/usb/serial/generic.c
++++ b/drivers/usb/serial/generic.c
+@@ -54,7 +54,6 @@ static struct usb_driver generic_driver = {
+ 	.probe =	generic_probe,
+ 	.disconnect =	usb_serial_disconnect,
+ 	.id_table =	generic_serial_ids,
+-	.no_dynamic_id =	1,
+ };
+ 
+ /* All of the device info needed for the Generic Serial Converter */
+@@ -64,7 +63,6 @@ struct usb_serial_driver usb_serial_generic_device = {
+ 		.name =		"generic",
+ 	},
+ 	.id_table =		generic_device_ids,
+-	.usb_driver = 		&generic_driver,
+ 	.num_ports =		1,
+ 	.disconnect =		usb_serial_generic_disconnect,
+ 	.release =		usb_serial_generic_release,
+@@ -73,6 +71,10 @@ struct usb_serial_driver usb_serial_generic_device = {
+ 	.resume =		usb_serial_generic_resume,
+ };
+ 
++static struct usb_serial_driver * const serial_drivers[] = {
++	&usb_serial_generic_device, NULL
++};
++
+ static int generic_probe(struct usb_interface *interface,
+ 			       const struct usb_device_id *id)
+ {
+@@ -97,13 +99,7 @@ int usb_serial_generic_register(int _debug)
+ 		USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT;
+ 
+ 	/* register our generic driver with ourselves */
+-	retval = usb_serial_register(&usb_serial_generic_device);
+-	if (retval)
+-		goto exit;
+-	retval = usb_register(&generic_driver);
+-	if (retval)
+-		usb_serial_deregister(&usb_serial_generic_device);
+-exit:
++	retval = usb_serial_register_drivers(&generic_driver, serial_drivers);
+ #endif
+ 	return retval;
+ }
+@@ -112,8 +108,7 @@ void usb_serial_generic_deregister(void)
+ {
+ #ifdef CONFIG_USB_SERIAL_GENERIC
+ 	/* remove our generic driver */
+-	usb_deregister(&generic_driver);
+-	usb_serial_deregister(&usb_serial_generic_device);
++	usb_serial_deregister_drivers(&generic_driver, serial_drivers);
+ #endif
+ }
+ 
+diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
+index 611b206591cb..45b3658c601f 100644
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -1338,6 +1338,11 @@ static void fixup_generic(struct usb_serial_driver *device)
+ 	set_to_generic_if_null(device, prepare_write_buffer);
+ }
+ 
++/*
++ * The next two routines are mainly for internal use.
++ * They are exported only for out-of-tree modules.
++ * New drivers should call usb_serial_{de}register_drivers() instead.
++ */
+ int usb_serial_register(struct usb_serial_driver *driver)
+ {
+ 	int retval;
+@@ -1386,6 +1391,76 @@ void usb_serial_deregister(struct usb_serial_driver *device)
+ }
+ EXPORT_SYMBOL_GPL(usb_serial_deregister);
+ 
++/**
++ * usb_serial_register_drivers - register drivers for a usb-serial module
++ * @udriver: usb_driver used for matching devices/interfaces
++ * @serial_drivers: NULL-terminated array of pointers to drivers to be registered
++ *
++ * Registers @udriver and all the drivers in the @serial_drivers array.
++ * Automatically fills in the .no_dynamic_id field in @udriver and
++ * the .usb_driver field in each serial driver.
++ */
++int usb_serial_register_drivers(struct usb_driver *udriver,
++		struct usb_serial_driver * const serial_drivers[])
++{
++	int rc;
++	const struct usb_device_id *saved_id_table;
++	struct usb_serial_driver * const *sd;
++
++	/*
++	 * udriver must be registered before any of the serial drivers,
++	 * because the store_new_id() routine for the serial drivers (in
++	 * bus.c) probes udriver.
++	 *
++	 * Performance hack: We don't want udriver to be probed until
++	 * the serial drivers are registered, because the probe would
++	 * simply fail for lack of a matching serial driver.
++	 * Therefore save off udriver's id_table until we are all set.
++	 */
++	saved_id_table = udriver->id_table;
++	udriver->id_table = NULL;
++
++	udriver->no_dynamic_id = 1;
++	rc = usb_register(udriver);
++	if (rc)
++		return rc;
++
++	for (sd = serial_drivers; *sd; ++sd) {
++		(*sd)->usb_driver = udriver;
++		rc = usb_serial_register(*sd);
++		if (rc)
++			goto failed;
++	}
++
++	/* Now restore udriver's id_table and look for matches */
++	udriver->id_table = saved_id_table;
++	rc = driver_attach(&udriver->drvwrap.driver);
++	return 0;
++
++ failed:
++	while (sd-- > serial_drivers)
++		usb_serial_deregister(*sd);
++	usb_deregister(udriver);
++	return rc;
++}
++EXPORT_SYMBOL_GPL(usb_serial_register_drivers);
++
++/**
++ * usb_serial_deregister_drivers - deregister drivers for a usb-serial module
++ * @udriver: usb_driver to unregister
++ * @serial_drivers: NULL-terminated array of pointers to drivers to be deregistered
++ *
++ * Deregisters @udriver and all the drivers in the @serial_drivers array.
++ */
++void usb_serial_deregister_drivers(struct usb_driver *udriver,
++		struct usb_serial_driver * const serial_drivers[])
++{
++	for (; *serial_drivers; ++serial_drivers)
++		usb_serial_deregister(*serial_drivers);
++	usb_deregister(udriver);
++}
++EXPORT_SYMBOL_GPL(usb_serial_deregister_drivers);
++
+ /* Module information */
+ MODULE_AUTHOR(DRIVER_AUTHOR);
+ MODULE_DESCRIPTION(DRIVER_DESC);
+diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
+index 10cb74d2ad1d..8c8dbf9c5b89 100644
+--- a/include/linux/usb/serial.h
++++ b/include/linux/usb/serial.h
+@@ -300,8 +300,17 @@ struct usb_serial_driver {
+ #define to_usb_serial_driver(d) \
+ 	container_of(d, struct usb_serial_driver, driver)
+ 
++/*
++ * These two routines are kept only for backward compatibility.
++ * Don't use them; call usb_serial_{de}register_drivers() instead.
++ */
+ extern int  usb_serial_register(struct usb_serial_driver *driver);
+ extern void usb_serial_deregister(struct usb_serial_driver *driver);
++
++extern int usb_serial_register_drivers(struct usb_driver *udriver,
++		struct usb_serial_driver * const serial_drivers[]);
++extern void usb_serial_deregister_drivers(struct usb_driver *udriver,
++		struct usb_serial_driver * const serial_drivers[]);
+ extern void usb_serial_port_softint(struct usb_serial_port *port);
+ 
+ extern int usb_serial_probe(struct usb_interface *iface,

commit bb94a406682770a35305daaa241ccdb7cab399de
+Author: Alan Stern 
+Date:   Tue Feb 21 13:16:32 2012 -0500
+
+    usb-storage: fix freezing of the scanning thread
+    
+    This patch (as1521b) fixes the interaction between usb-storage's
+    scanning thread and the freezer.  The current implementation has a
+    race: If the device is unplugged shortly after being plugged in and
+    just as a system sleep begins, the scanning thread may get frozen
+    before the khubd task.  Khubd won't be able to freeze until the
+    disconnect processing is complete, and the disconnect processing can't
+    proceed until the scanning thread finishes, so the sleep transition
+    will fail.
+    
+    The implementation in the 3.2 kernel suffers from an additional
+    problem.  There the scanning thread calls set_freezable_with_signal(),
+    and the signals sent by the freezer will mess up the thread's I/O
+    delays, which are all interruptible.
+    
+    The solution to both problems is the same: Replace the kernel thread
+    used for scanning with a delayed-work routine on the system freezable
+    work queue.  Freezable work queues have the nice property that you can
+    cancel a work item even while the work queue is frozen, and no signals
+    are needed.
+    
+    The 3.2 version of this patch solves the problem in Bugzilla #42730.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Seth Forshee 
+    CC: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 3dd7da9fd504..db51ba16dc07 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -788,15 +788,19 @@ static void quiesce_and_remove_host(struct us_data *us)
+ 	struct Scsi_Host *host = us_to_host(us);
+ 
+ 	/* If the device is really gone, cut short reset delays */
+-	if (us->pusb_dev->state == USB_STATE_NOTATTACHED)
++	if (us->pusb_dev->state == USB_STATE_NOTATTACHED) {
+ 		set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
++		wake_up(&us->delay_wait);
++	}
+ 
+-	/* Prevent SCSI-scanning (if it hasn't started yet)
+-	 * and wait for the SCSI-scanning thread to stop.
++	/* Prevent SCSI scanning (if it hasn't started yet)
++	 * or wait for the SCSI-scanning routine to stop.
+ 	 */
+-	set_bit(US_FLIDX_DONT_SCAN, &us->dflags);
+-	wake_up(&us->delay_wait);
+-	wait_for_completion(&us->scanning_done);
++	cancel_delayed_work_sync(&us->scan_dwork);
++
++	/* Balance autopm calls if scanning was cancelled */
++	if (test_bit(US_FLIDX_SCAN_PENDING, &us->dflags))
++		usb_autopm_put_interface_no_suspend(us->pusb_intf);
+ 
+ 	/* Removing the host will perform an orderly shutdown: caches
+ 	 * synchronized, disks spun down, etc.
+@@ -823,53 +827,28 @@ static void release_everything(struct us_data *us)
+ 	scsi_host_put(us_to_host(us));
+ }
+ 
+-/* Thread to carry out delayed SCSI-device scanning */
+-static int usb_stor_scan_thread(void * __us)
++/* Delayed-work routine to carry out SCSI-device scanning */
++static void usb_stor_scan_dwork(struct work_struct *work)
+ {
+-	struct us_data *us = (struct us_data *)__us;
++	struct us_data *us = container_of(work, struct us_data,
++			scan_dwork.work);
+ 	struct device *dev = &us->pusb_intf->dev;
+ 
+-	dev_dbg(dev, "device found\n");
+-
+-	set_freezable();
++	dev_dbg(dev, "starting scan\n");
+ 
+-	/*
+-	 * Wait for the timeout to expire or for a disconnect
+-	 *
+-	 * We can't freeze in this thread or we risk causing khubd to
+-	 * fail to freeze, but we can't be non-freezable either. Nor can
+-	 * khubd freeze while waiting for scanning to complete as it may
+-	 * hold the device lock, causing a hang when suspending devices.
+-	 * So instead of using wait_event_freezable(), explicitly test
+-	 * for (DONT_SCAN || freezing) in interruptible wait and proceed
+-	 * if any of DONT_SCAN, freezing or timeout has happened.
+-	 */
+-	if (delay_use > 0) {
+-		dev_dbg(dev, "waiting for device to settle "
+-				"before scanning\n");
+-		wait_event_interruptible_timeout(us->delay_wait,
+-				test_bit(US_FLIDX_DONT_SCAN, &us->dflags) ||
+-				freezing(current), delay_use * HZ);
++	/* For bulk-only devices, determine the max LUN value */
++	if (us->protocol == USB_PR_BULK && !(us->fflags & US_FL_SINGLE_LUN)) {
++		mutex_lock(&us->dev_mutex);
++		us->max_lun = usb_stor_Bulk_max_lun(us);
++		mutex_unlock(&us->dev_mutex);
+ 	}
++	scsi_scan_host(us_to_host(us));
++	dev_dbg(dev, "scan complete\n");
+ 
+-	/* If the device is still connected, perform the scanning */
+-	if (!test_bit(US_FLIDX_DONT_SCAN, &us->dflags)) {
+-
+-		/* For bulk-only devices, determine the max LUN value */
+-		if (us->protocol == USB_PR_BULK &&
+-				!(us->fflags & US_FL_SINGLE_LUN)) {
+-			mutex_lock(&us->dev_mutex);
+-			us->max_lun = usb_stor_Bulk_max_lun(us);
+-			mutex_unlock(&us->dev_mutex);
+-		}
+-		scsi_scan_host(us_to_host(us));
+-		dev_dbg(dev, "scan complete\n");
+-
+-		/* Should we unbind if no devices were detected? */
+-	}
++	/* Should we unbind if no devices were detected? */
+ 
+ 	usb_autopm_put_interface(us->pusb_intf);
+-	complete_and_exit(&us->scanning_done, 0);
++	clear_bit(US_FLIDX_SCAN_PENDING, &us->dflags);
+ }
+ 
+ static unsigned int usb_stor_sg_tablesize(struct usb_interface *intf)
+@@ -916,7 +895,7 @@ int usb_stor_probe1(struct us_data **pus,
+ 	init_completion(&us->cmnd_ready);
+ 	init_completion(&(us->notify));
+ 	init_waitqueue_head(&us->delay_wait);
+-	init_completion(&us->scanning_done);
++	INIT_DELAYED_WORK(&us->scan_dwork, usb_stor_scan_dwork);
+ 
+ 	/* Associate the us_data structure with the USB device */
+ 	result = associate_dev(us, intf);
+@@ -947,7 +926,6 @@ EXPORT_SYMBOL_GPL(usb_stor_probe1);
+ /* Second part of general USB mass-storage probing */
+ int usb_stor_probe2(struct us_data *us)
+ {
+-	struct task_struct *th;
+ 	int result;
+ 	struct device *dev = &us->pusb_intf->dev;
+ 
+@@ -988,20 +966,14 @@ int usb_stor_probe2(struct us_data *us)
+ 		goto BadDevice;
+ 	}
+ 
+-	/* Start up the thread for delayed SCSI-device scanning */
+-	th = kthread_create(usb_stor_scan_thread, us, "usb-stor-scan");
+-	if (IS_ERR(th)) {
+-		dev_warn(dev,
+-				"Unable to start the device-scanning thread\n");
+-		complete(&us->scanning_done);
+-		quiesce_and_remove_host(us);
+-		result = PTR_ERR(th);
+-		goto BadDevice;
+-	}
+-
++	/* Submit the delayed_work for SCSI-device scanning */
+ 	usb_autopm_get_interface_no_resume(us->pusb_intf);
+-	wake_up_process(th);
++	set_bit(US_FLIDX_SCAN_PENDING, &us->dflags);
+ 
++	if (delay_use > 0)
++		dev_dbg(dev, "waiting for device to settle before scanning\n");
++	queue_delayed_work(system_freezable_wq, &us->scan_dwork,
++			delay_use * HZ);
+ 	return 0;
+ 
+ 	/* We come here if there are any problems */
+diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
+index 7b0f2113632e..75f70f04f37b 100644
+--- a/drivers/usb/storage/usb.h
++++ b/drivers/usb/storage/usb.h
+@@ -47,6 +47,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ 
+ struct us_data;
+@@ -72,7 +73,7 @@ struct us_unusual_dev {
+ #define US_FLIDX_DISCONNECTING	3	/* disconnect in progress   */
+ #define US_FLIDX_RESETTING	4	/* device reset in progress */
+ #define US_FLIDX_TIMED_OUT	5	/* SCSI midlayer timed out  */
+-#define US_FLIDX_DONT_SCAN	6	/* don't scan (disconnect)  */
++#define US_FLIDX_SCAN_PENDING	6	/* scanning not yet done    */
+ #define US_FLIDX_REDO_READ10	7	/* redo READ(10) command    */
+ #define US_FLIDX_READ10_WORKED	8	/* previous READ(10) succeeded */
+ 
+@@ -147,8 +148,8 @@ struct us_data {
+ 	/* mutual exclusion and synchronization structures */
+ 	struct completion	cmnd_ready;	 /* to sleep thread on	    */
+ 	struct completion	notify;		 /* thread begin/end	    */
+-	wait_queue_head_t	delay_wait;	 /* wait during scan, reset */
+-	struct completion	scanning_done;	 /* wait for scan thread    */
++	wait_queue_head_t	delay_wait;	 /* wait during reset	    */
++	struct delayed_work	scan_dwork;	 /* for async scanning      */
+ 
+ 	/* subdriver information */
+ 	void			*extra;		 /* Any extra data          */

commit fea6d607e154cf96ab22254ccb48addfd43d4cb5
+Author: Alan Stern 
+Date:   Fri Feb 17 16:25:08 2012 -0500
+
+    [SCSI] scsi_pm: Fix bug in the SCSI power management handler
+    
+    This patch (as1520) fixes a bug in the SCSI layer's power management
+    implementation.
+    
+    LUN scanning can be carried out asynchronously in do_scan_async(), and
+    sd uses an asynchronous thread for the time-consuming parts of disk
+    probing in sd_probe_async().  Currently nothing coordinates these
+    async threads with system sleep transitions; they can and do attempt
+    to continue scanning/probing SCSI devices even after the host adapter
+    has been suspended.  As one might expect, the outcome is not ideal.
+    
+    This is what the "prepare" stage of system suspend was created for.
+    After the prepare callback has been called for a host, target, or
+    device, drivers are not allowed to register any children underneath
+    them.  Currently the SCSI prepare callback is not implemented; this
+    patch rectifies that omission.
+    
+    For SCSI hosts, the prepare routine calls scsi_complete_async_scans()
+    to wait until async scanning is finished.  It might be slightly more
+    efficient to wait only until the host in question has been scanned,
+    but there's currently no way to do that.  Besides, during a sleep
+    transition we will ultimately have to wait until all the host scanning
+    has finished anyway.
+    
+    For SCSI devices, the prepare routine calls async_synchronize_full()
+    to wait until sd probing is finished.  The routine does nothing for
+    SCSI targets, because asynchronous target scanning is done only as
+    part of host scanning.
+    
+    Signed-off-by: Alan Stern 
+    CC: 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
+index bf8bf79e6a1f..c4670642d023 100644
+--- a/drivers/scsi/scsi_pm.c
++++ b/drivers/scsi/scsi_pm.c
+@@ -7,6 +7,7 @@
+ 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ #include 
+@@ -92,6 +93,19 @@ static int scsi_bus_resume_common(struct device *dev)
+ 	return err;
+ }
+ 
++static int scsi_bus_prepare(struct device *dev)
++{
++	if (scsi_is_sdev_device(dev)) {
++		/* sd probing uses async_schedule.  Wait until it finishes. */
++		async_synchronize_full();
++
++	} else if (scsi_is_host_device(dev)) {
++		/* Wait until async scanning is finished */
++		scsi_complete_async_scans();
++	}
++	return 0;
++}
++
+ static int scsi_bus_suspend(struct device *dev)
+ {
+ 	return scsi_bus_suspend_common(dev, PMSG_SUSPEND);
+@@ -110,6 +124,7 @@ static int scsi_bus_poweroff(struct device *dev)
+ #else /* CONFIG_PM_SLEEP */
+ 
+ #define scsi_bus_resume_common		NULL
++#define scsi_bus_prepare		NULL
+ #define scsi_bus_suspend		NULL
+ #define scsi_bus_freeze			NULL
+ #define scsi_bus_poweroff		NULL
+@@ -218,6 +233,7 @@ void scsi_autopm_put_host(struct Scsi_Host *shost)
+ #endif /* CONFIG_PM_RUNTIME */
+ 
+ const struct dev_pm_ops scsi_bus_pm_ops = {
++	.prepare =		scsi_bus_prepare,
+ 	.suspend =		scsi_bus_suspend,
+ 	.resume =		scsi_bus_resume_common,
+ 	.freeze =		scsi_bus_freeze,
+diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
+index 68eadd1c67fd..be4fa6d179b1 100644
+--- a/drivers/scsi/scsi_priv.h
++++ b/drivers/scsi/scsi_priv.h
+@@ -109,6 +109,7 @@ extern void scsi_exit_procfs(void);
+ #endif /* CONFIG_PROC_FS */
+ 
+ /* scsi_scan.c */
++extern int scsi_complete_async_scans(void);
+ extern int scsi_scan_host_selected(struct Scsi_Host *, unsigned int,
+ 				   unsigned int, unsigned int, int);
+ extern void scsi_forget_host(struct Scsi_Host *);

commit af74d2dae8f85a0e90a30594beb507f5d954fa3f
+Author: Alan Stern 
+Date:   Tue Jan 10 13:43:40 2012 -0500
+
+    usb-storage: reorganize target-specific code
+    
+    Now that usb-storage has a target_alloc() routine, this patch (as1508)
+    moves some existing target-specific code out of the slave_alloc()
+    routine to where it really belongs.
+    
+    Signed-off-by: Alan Stern 
+    CC: Matthew Dharm 
+    Cc: James Bottomley 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index dc68cc9fef5d..a324a5d21e99 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -78,8 +78,6 @@ static const char* host_info(struct Scsi_Host *host)
+ 
+ static int slave_alloc (struct scsi_device *sdev)
+ {
+-	struct us_data *us = host_to_us(sdev->host);
+-
+ 	/*
+ 	 * Set the INQUIRY transfer length to 36.  We don't use any of
+ 	 * the extra data and many devices choke if asked for more or
+@@ -104,18 +102,6 @@ static int slave_alloc (struct scsi_device *sdev)
+ 	 */
+ 	blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
+ 
+-	/*
+-	 * The UFI spec treates the Peripheral Qualifier bits in an
+-	 * INQUIRY result as reserved and requires devices to set them
+-	 * to 0.  However the SCSI spec requires these bits to be set
+-	 * to 3 to indicate when a LUN is not present.
+-	 *
+-	 * Let the scanning code know if this target merely sets
+-	 * Peripheral Device Type to 0x1f to indicate no LUN.
+-	 */
+-	if (us->subclass == USB_SC_UFI)
+-		sdev->sdev_target->pdt_1f_for_no_lun = 1;
+-
+ 	return 0;
+ }
+ 
+@@ -278,6 +264,8 @@ static int slave_configure(struct scsi_device *sdev)
+ 
+ static int target_alloc(struct scsi_target *starget)
+ {
++	struct us_data *us = host_to_us(dev_to_shost(starget->dev.parent));
++
+ 	/*
+ 	 * Some USB drives don't support REPORT LUNS, even though they
+ 	 * report a SCSI revision level above 2.  Tell the SCSI layer
+@@ -285,6 +273,19 @@ static int target_alloc(struct scsi_target *starget)
+ 	 * scan instead.
+ 	 */
+ 	starget->no_report_luns = 1;
++
++	/*
++	 * The UFI spec treats the Peripheral Qualifier bits in an
++	 * INQUIRY result as reserved and requires devices to set them
++	 * to 0.  However the SCSI spec requires these bits to be set
++	 * to 3 to indicate when a LUN is not present.
++	 *
++	 * Let the scanning code know if this target merely sets
++	 * Peripheral Device Type to 0x1f to indicate no LUN.
++	 */
++	if (us->subclass == USB_SC_UFI)
++		starget->pdt_1f_for_no_lun = 1;
++
+ 	return 0;
+ }
+ 

commit 09b6b51b0b6c1b9bb61815baf205e4d74c89ff04
+Author: Alan Stern 
+Date:   Tue Jan 10 13:43:30 2012 -0500
+
+    SCSI & usb-storage: add flags for VPD pages and REPORT LUNS
+    
+    This patch (as1507) adds a skip_vpd_pages flag to struct scsi_device
+    and a no_report_luns flag to struct scsi_target.  The first is used to
+    control whether sd will look at VPD pages for information on block
+    provisioning, limits, and characteristics.  The second prevents
+    scsi_report_lun_scan() from issuing a REPORT LUNS command.
+    
+    The patch also modifies usb-storage to set the new flag bits for all
+    USB devices and targets, and to stop adjusting the scsi_level value.
+    
+    Historically we have seen that USB mass-storage devices often don't
+    support VPD pages or REPORT LUNS properly.  Until now we have avoided
+    these things by setting the scsi_level to SCSI_2 for all USB devices.
+    But this has the side effect of storing the LUN bits into the second
+    byte of each CDB, and now we have a report of a device which doesn't
+    like that.  The best solution is to stop abusing scsi_level and
+    instead have separate flags for VPD pages and REPORT LUNS.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Perry Wagle 
+    CC: Matthew Dharm 
+    Cc: James Bottomley 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+index 89da43f73c00..fd37bfbfbcdb 100644
+--- a/drivers/scsi/scsi_scan.c
++++ b/drivers/scsi/scsi_scan.c
+@@ -1295,6 +1295,7 @@ EXPORT_SYMBOL(int_to_scsilun);
+  *   LUNs even if it's older than SCSI-3.
+  *   If BLIST_NOREPORTLUN is set, return 1 always.
+  *   If BLIST_NOLUN is set, return 0 always.
++ *   If starget->no_report_luns is set, return 1 always.
+  *
+  * Return:
+  *     0: scan completed (or no memory, so further scanning is futile)
+@@ -1321,6 +1322,7 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
+ 	 * Only support SCSI-3 and up devices if BLIST_NOREPORTLUN is not set.
+ 	 * Also allow SCSI-2 if BLIST_REPORTLUN2 is set and host adapter does
+ 	 * support more than 8 LUNs.
++	 * Don't attempt if the target doesn't support REPORT LUNS.
+ 	 */
+ 	if (bflags & BLIST_NOREPORTLUN)
+ 		return 1;
+@@ -1332,6 +1334,8 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
+ 		return 1;
+ 	if (bflags & BLIST_NOLUN)
+ 		return 0;
++	if (starget->no_report_luns)
++		return 1;
+ 
+ 	if (!(sdev = scsi_device_lookup_by_target(starget, 0))) {
+ 		sdev = scsi_alloc_sdev(starget, 0, NULL);
+diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+index c691fb50e6cb..d173b90b25e9 100644
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -2349,7 +2349,7 @@ static int sd_try_extended_inquiry(struct scsi_device *sdp)
+ 	 * some USB ones crash on receiving them, and the pages
+ 	 * we currently ask for are for SPC-3 and beyond
+ 	 */
+-	if (sdp->scsi_level > SCSI_SPC_2)
++	if (sdp->scsi_level > SCSI_SPC_2 && !sdp->skip_vpd_pages)
+ 		return 1;
+ 	return 0;
+ }
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index 13b8bcdf3dba..dc68cc9fef5d 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -197,6 +197,9 @@ static int slave_configure(struct scsi_device *sdev)
+ 		 * page x08, so we will skip it. */
+ 		sdev->skip_ms_page_8 = 1;
+ 
++		/* Some devices don't handle VPD pages correctly */
++		sdev->skip_vpd_pages = 1;
++
+ 		/* Some disks return the total number of blocks in response
+ 		 * to READ CAPACITY rather than the highest block number.
+ 		 * If this device makes that mistake, tell the sd driver. */
+@@ -217,16 +220,6 @@ static int slave_configure(struct scsi_device *sdev)
+ 		if (sdev->scsi_level > SCSI_SPC_2)
+ 			us->fflags |= US_FL_SANE_SENSE;
+ 
+-		/* Some devices report a SCSI revision level above 2 but are
+-		 * unable to handle the REPORT LUNS command (for which
+-		 * support is mandatory at level 3).  Since we already have
+-		 * a Get-Max-LUN request, we won't lose much by setting the
+-		 * revision level down to 2.  The only devices that would be
+-		 * affected are those with sparse LUNs. */
+-		if (sdev->scsi_level > SCSI_2)
+-			sdev->sdev_target->scsi_level =
+-					sdev->scsi_level = SCSI_2;
+-
+ 		/* USB-IDE bridges tend to report SK = 0x04 (Non-recoverable
+ 		 * Hardware Error) when any low-level error occurs,
+ 		 * recoverable or not.  Setting this flag tells the SCSI
+@@ -283,6 +276,18 @@ static int slave_configure(struct scsi_device *sdev)
+ 	return 0;
+ }
+ 
++static int target_alloc(struct scsi_target *starget)
++{
++	/*
++	 * Some USB drives don't support REPORT LUNS, even though they
++	 * report a SCSI revision level above 2.  Tell the SCSI layer
++	 * not to issue that command; it will perform a normal sequential
++	 * scan instead.
++	 */
++	starget->no_report_luns = 1;
++	return 0;
++}
++
+ /* queue a command */
+ /* This is always called with scsi_lock(host) held */
+ static int queuecommand_lck(struct scsi_cmnd *srb,
+@@ -546,6 +551,7 @@ struct scsi_host_template usb_stor_host_template = {
+ 
+ 	.slave_alloc =			slave_alloc,
+ 	.slave_configure =		slave_configure,
++	.target_alloc =			target_alloc,
+ 
+ 	/* lots of sg segments can be handled */
+ 	.sg_tablesize =			SCSI_MAX_SG_CHAIN_SEGMENTS,
+diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
+index 01cb3c4cb74d..b3a1c2daf6cc 100644
+--- a/include/scsi/scsi_device.h
++++ b/include/scsi/scsi_device.h
+@@ -136,6 +136,7 @@ struct scsi_device {
+ 	unsigned use_10_for_ms:1; /* first try 10-byte mode sense/select */
+ 	unsigned skip_ms_page_8:1;	/* do not use MODE SENSE page 0x08 */
+ 	unsigned skip_ms_page_3f:1;	/* do not use MODE SENSE page 0x3f */
++	unsigned skip_vpd_pages:1;	/* do not read VPD pages */
+ 	unsigned use_192_bytes_for_3f:1; /* ask for 192 bytes from page 0x3f */
+ 	unsigned no_start_on_add:1;	/* do not issue start on add */
+ 	unsigned allow_restart:1; /* issue START_UNIT in error handler */
+@@ -248,6 +249,8 @@ struct scsi_target {
+ 						 * for the device at a time. */
+ 	unsigned int		pdt_1f_for_no_lun:1;	/* PDT = 0x1f
+ 						 * means no lun present. */
++	unsigned int		no_report_luns:1;	/* Don't use
++						 * REPORT LUNS for scanning. */
+ 	/* commands actually active on LLD. protected by host lock. */
+ 	unsigned int		target_busy;
+ 	/*

commit de8c46bfc032fbdf490cfb67f534d2a0188ebeb0
+Author: Alan Stern 
+Date:   Tue Jan 10 13:43:04 2012 -0500
+
+    SCSI: fix typo in definition of struct scsi_target
+    
+    This patch (as1506) corrects a typo in the definition of the
+    scsi_target structure.  pdt_1f_for_no_lun is supposed to be a
+    single-bit flag, not a full-sized integer.
+    
+    Signed-off-by: Alan Stern 
+    Cc: James Bottomley 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
+index 77273f2fdd80..01cb3c4cb74d 100644
+--- a/include/scsi/scsi_device.h
++++ b/include/scsi/scsi_device.h
+@@ -246,8 +246,8 @@ struct scsi_target {
+ 	unsigned int		single_lun:1;	/* Indicates we should only
+ 						 * allow I/O to one of the luns
+ 						 * for the device at a time. */
+-	unsigned int		pdt_1f_for_no_lun;	/* PDT = 0x1f */
+-						/* means no lun present */
++	unsigned int		pdt_1f_for_no_lun:1;	/* PDT = 0x1f
++						 * means no lun present. */
+ 	/* commands actually active on LLD. protected by host lock. */
+ 	unsigned int		target_busy;
+ 	/*

commit 0cb54a3e47cb4baf0bc7463f0a64cfeae5e35697
+Author: Alan Stern 
+Date:   Thu Feb 2 15:38:14 2012 -0500
+
+    USB: debugging code shouldn't alter control flow
+    
+    People have complained that debugging code shouldn't alter the flow of
+    control; it should restrict itself to printing out warnings and error
+    messages.  Bowing to popular opinion, this patch (as1518) changes the
+    debugging checks in usb_submit_urb() to follow this guideline.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Keith Packard 
+    CC: Pavel Machek 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
+index 909625b91eb3..f4f20c7b7765 100644
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -403,20 +403,17 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 	 * cause problems in HCDs if they get it wrong.
+ 	 */
+ 	{
+-	unsigned int	orig_flags = urb->transfer_flags;
+ 	unsigned int	allowed;
+ 	static int pipetypes[4] = {
+ 		PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
+ 	};
+ 
+ 	/* Check that the pipe's type matches the endpoint's type */
+-	if (usb_pipetype(urb->pipe) != pipetypes[xfertype]) {
+-		dev_err(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n",
++	if (usb_pipetype(urb->pipe) != pipetypes[xfertype])
++		dev_WARN(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n",
+ 			usb_pipetype(urb->pipe), pipetypes[xfertype]);
+-		return -EPIPE;		/* The most suitable error code :-) */
+-	}
+ 
+-	/* enforce simple/standard policy */
++	/* Check against a simple/standard policy */
+ 	allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT | URB_DIR_MASK |
+ 			URB_FREE_BUFFER);
+ 	switch (xfertype) {
+@@ -435,14 +432,12 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 		allowed |= URB_ISO_ASAP;
+ 		break;
+ 	}
+-	urb->transfer_flags &= allowed;
++	allowed &= urb->transfer_flags;
+ 
+-	/* fail if submitter gave bogus flags */
+-	if (urb->transfer_flags != orig_flags) {
+-		dev_err(&dev->dev, "BOGUS urb flags, %x --> %x\n",
+-			orig_flags, urb->transfer_flags);
+-		return -EINVAL;
+-	}
++	/* warn if submitter gave bogus flags */
++	if (allowed != urb->transfer_flags)
++		dev_WARN(&dev->dev, "BOGUS urb flags, %x --> %x\n",
++			urb->transfer_flags, allowed);
+ 	}
+ #endif
+ 	/*

commit 07d251460bbf9752c6532af8c1a68328c199dd70
+Author: Alan Stern 
+Date:   Fri Jan 27 10:24:40 2012 -0500
+
+    PCI/XEN: Fix bug introduced by a recent change
+    
+    This patch (as1516) fixes a bug introduced during the removal of
+    put_driver() and get_driver() from drivers/pci/xen-pcifront.c.
+    
+    Reported-by: Stephen Rothwell 
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
+index 6f819988a8da..98387caf59b3 100644
+--- a/drivers/pci/xen-pcifront.c
++++ b/drivers/pci/xen-pcifront.c
+@@ -593,7 +593,7 @@ static pci_ers_result_t pcifront_common_process(int cmd,
+ 	}
+ 	pdrv = pcidev->driver;
+ 
+-	if (pdrv->driver) {
++	if (pdrv) {
+ 		if (pdrv->err_handler && pdrv->err_handler->error_detected) {
+ 			dev_dbg(&pcidev->dev,
+ 				"trying to call AER service\n");

commit ed283e9f0a2cc0541870828c76c6c6997c51a318
+Author: Alan Stern 
+Date:   Tue Jan 24 14:35:13 2012 -0500
+
+    USB/PCI/PCMCIA: Clean up new_id and remove_id sysfs attribute routines
+    
+    This patch (as1514) cleans up some places where new_id and remove_id
+    sysfs attributes are created and deleted.  Handling both attributes in
+    a single routine rather than a pair of routines makes the code
+    smaller.  It also prevents certain kinds of errors, like one we
+    currently have in the USB subsystem: The removeid attribute is often
+    created even when newid isn't (because the driver's no_dynamid_id flag
+    is set).
+    
+    In the case of the PCMCIA subsystem, the newid attribute is created
+    but never explicitly deleted.  The patch adds a deletion routine.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Jesse Barnes 
+    Acked-by: Dominik Brodowski 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
+index ff540477fe8b..8d9616b821ca 100644
+--- a/drivers/pci/pci-driver.c
++++ b/drivers/pci/pci-driver.c
+@@ -188,43 +188,34 @@ store_remove_id(struct device_driver *driver, const char *buf, size_t count)
+ static DRIVER_ATTR(remove_id, S_IWUSR, NULL, store_remove_id);
+ 
+ static int
+-pci_create_newid_file(struct pci_driver *drv)
++pci_create_newid_files(struct pci_driver *drv)
+ {
+ 	int error = 0;
+-	if (drv->probe != NULL)
+-		error = driver_create_file(&drv->driver, &driver_attr_new_id);
+-	return error;
+-}
+-
+-static void pci_remove_newid_file(struct pci_driver *drv)
+-{
+-	driver_remove_file(&drv->driver, &driver_attr_new_id);
+-}
+ 
+-static int
+-pci_create_removeid_file(struct pci_driver *drv)
+-{
+-	int error = 0;
+-	if (drv->probe != NULL)
+-		error = driver_create_file(&drv->driver,&driver_attr_remove_id);
++	if (drv->probe != NULL) {
++		error = driver_create_file(&drv->driver, &driver_attr_new_id);
++		if (error == 0) {
++			error = driver_create_file(&drv->driver,
++					&driver_attr_remove_id);
++			if (error)
++				driver_remove_file(&drv->driver,
++						&driver_attr_new_id);
++		}
++	}
+ 	return error;
+ }
+ 
+-static void pci_remove_removeid_file(struct pci_driver *drv)
++static void pci_remove_newid_files(struct pci_driver *drv)
+ {
+ 	driver_remove_file(&drv->driver, &driver_attr_remove_id);
++	driver_remove_file(&drv->driver, &driver_attr_new_id);
+ }
+ #else /* !CONFIG_HOTPLUG */
+-static inline int pci_create_newid_file(struct pci_driver *drv)
++static inline int pci_create_newid_files(struct pci_driver *drv)
+ {
+ 	return 0;
+ }
+-static inline void pci_remove_newid_file(struct pci_driver *drv) {}
+-static inline int pci_create_removeid_file(struct pci_driver *drv)
+-{
+-	return 0;
+-}
+-static inline void pci_remove_removeid_file(struct pci_driver *drv) {}
++static inline void pci_remove_newid_files(struct pci_driver *drv) {}
+ #endif
+ 
+ /**
+@@ -1136,18 +1127,12 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner,
+ 	if (error)
+ 		goto out;
+ 
+-	error = pci_create_newid_file(drv);
++	error = pci_create_newid_files(drv);
+ 	if (error)
+ 		goto out_newid;
+-
+-	error = pci_create_removeid_file(drv);
+-	if (error)
+-		goto out_removeid;
+ out:
+ 	return error;
+ 
+-out_removeid:
+-	pci_remove_newid_file(drv);
+ out_newid:
+ 	driver_unregister(&drv->driver);
+ 	goto out;
+@@ -1166,8 +1151,7 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner,
+ void
+ pci_unregister_driver(struct pci_driver *drv)
+ {
+-	pci_remove_removeid_file(drv);
+-	pci_remove_newid_file(drv);
++	pci_remove_newid_files(drv);
+ 	driver_unregister(&drv->driver);
+ 	pci_free_dynids(drv);
+ }
+diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
+index 059699f6363d..249b8895807d 100644
+--- a/drivers/pcmcia/ds.c
++++ b/drivers/pcmcia/ds.c
+@@ -157,6 +157,11 @@ pcmcia_create_newid_file(struct pcmcia_driver *drv)
+ 	return error;
+ }
+ 
++static void
++pcmcia_remove_newid_file(struct pcmcia_driver *drv)
++{
++	driver_remove_file(&drv->drv, &driver_attr_new_id);
++}
+ 
+ /**
+  * pcmcia_register_driver - register a PCMCIA driver with the bus core
+@@ -201,6 +206,7 @@ EXPORT_SYMBOL(pcmcia_register_driver);
+ void pcmcia_unregister_driver(struct pcmcia_driver *driver)
+ {
+ 	pr_debug("unregistering driver %s\n", driver->name);
++	pcmcia_remove_newid_file(driver);
+ 	driver_unregister(&driver->drv);
+ 	pcmcia_free_dynids(driver);
+ }
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 54c493b4226b..4fee024ecc9b 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -129,43 +129,39 @@ store_remove_id(struct device_driver *driver, const char *buf, size_t count)
+ }
+ static DRIVER_ATTR(remove_id, S_IWUSR, NULL, store_remove_id);
+ 
+-static int usb_create_newid_file(struct usb_driver *usb_drv)
++static int usb_create_newid_files(struct usb_driver *usb_drv)
+ {
+ 	int error = 0;
+ 
+ 	if (usb_drv->no_dynamic_id)
+ 		goto exit;
+ 
+-	if (usb_drv->probe != NULL)
++	if (usb_drv->probe != NULL) {
+ 		error = driver_create_file(&usb_drv->drvwrap.driver,
+ 					   &driver_attr_new_id);
++		if (error == 0) {
++			error = driver_create_file(&usb_drv->drvwrap.driver,
++					&driver_attr_remove_id);
++			if (error)
++				driver_remove_file(&usb_drv->drvwrap.driver,
++						&driver_attr_new_id);
++		}
++	}
+ exit:
+ 	return error;
+ }
+ 
+-static void usb_remove_newid_file(struct usb_driver *usb_drv)
++static void usb_remove_newid_files(struct usb_driver *usb_drv)
+ {
+ 	if (usb_drv->no_dynamic_id)
+ 		return;
+ 
+-	if (usb_drv->probe != NULL)
++	if (usb_drv->probe != NULL) {
+ 		driver_remove_file(&usb_drv->drvwrap.driver,
+-				   &driver_attr_new_id);
+-}
+-
+-static int
+-usb_create_removeid_file(struct usb_driver *drv)
+-{
+-	int error = 0;
+-	if (drv->probe != NULL)
+-		error = driver_create_file(&drv->drvwrap.driver,
+ 				&driver_attr_remove_id);
+-	return error;
+-}
+-
+-static void usb_remove_removeid_file(struct usb_driver *drv)
+-{
+-	driver_remove_file(&drv->drvwrap.driver, &driver_attr_remove_id);
++		driver_remove_file(&usb_drv->drvwrap.driver,
++				   &driver_attr_new_id);
++	}
+ }
+ 
+ static void usb_free_dynids(struct usb_driver *usb_drv)
+@@ -180,22 +176,12 @@ static void usb_free_dynids(struct usb_driver *usb_drv)
+ 	spin_unlock(&usb_drv->dynids.lock);
+ }
+ #else
+-static inline int usb_create_newid_file(struct usb_driver *usb_drv)
+-{
+-	return 0;
+-}
+-
+-static void usb_remove_newid_file(struct usb_driver *usb_drv)
+-{
+-}
+-
+-static int
+-usb_create_removeid_file(struct usb_driver *drv)
++static inline int usb_create_newid_files(struct usb_driver *usb_drv)
+ {
+ 	return 0;
+ }
+ 
+-static void usb_remove_removeid_file(struct usb_driver *drv)
++static void usb_remove_newid_files(struct usb_driver *usb_drv)
+ {
+ }
+ 
+@@ -872,22 +858,16 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner,
+ 
+ 	usbfs_update_special();
+ 
+-	retval = usb_create_newid_file(new_driver);
++	retval = usb_create_newid_files(new_driver);
+ 	if (retval)
+ 		goto out_newid;
+ 
+-	retval = usb_create_removeid_file(new_driver);
+-	if (retval)
+-		goto out_removeid;
+-
+ 	pr_info("%s: registered new interface driver %s\n",
+ 			usbcore_name, new_driver->name);
+ 
+ out:
+ 	return retval;
+ 
+-out_removeid:
+-	usb_remove_newid_file(new_driver);
+ out_newid:
+ 	driver_unregister(&new_driver->drvwrap.driver);
+ 
+@@ -914,10 +894,9 @@ void usb_deregister(struct usb_driver *driver)
+ 	pr_info("%s: deregistering interface driver %s\n",
+ 			usbcore_name, driver->name);
+ 
+-	usb_remove_removeid_file(driver);
+-	usb_remove_newid_file(driver);
+-	usb_free_dynids(driver);
++	usb_remove_newid_files(driver);
+ 	driver_unregister(&driver->drvwrap.driver);
++	usb_free_dynids(driver);
+ 
+ 	usbfs_update_special();
+ }

commit 9875bb480cc89d9b690f7028aadf7e58454f0dae
+Author: Alan Stern 
+Date:   Tue Jan 24 13:35:37 2012 -0500
+
+    Eliminate get_driver() and put_driver()
+    
+    Now that there are no users of get_driver() or put_driver(), this
+    patch (as1513) removes those routines completely.
+    
+    Signed-off-by: Alan Stern 
+    CC: Dmitry Torokhov 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/base/driver.c b/drivers/base/driver.c
+index e979cad75c6e..60e4f77ca662 100644
+--- a/drivers/base/driver.c
++++ b/drivers/base/driver.c
+@@ -153,34 +153,6 @@ int driver_add_kobj(struct device_driver *drv, struct kobject *kobj,
+ }
+ EXPORT_SYMBOL_GPL(driver_add_kobj);
+ 
+-/**
+- * get_driver - increment driver reference count.
+- * @drv: driver.
+- */
+-struct device_driver *get_driver(struct device_driver *drv)
+-{
+-	if (drv) {
+-		struct driver_private *priv;
+-		struct kobject *kobj;
+-
+-		kobj = kobject_get(&drv->p->kobj);
+-		priv = to_driver(kobj);
+-		return priv->driver;
+-	}
+-	return NULL;
+-}
+-EXPORT_SYMBOL_GPL(get_driver);
+-
+-/**
+- * put_driver - decrement driver's refcount.
+- * @drv: driver.
+- */
+-void put_driver(struct device_driver *drv)
+-{
+-	kobject_put(&drv->p->kobj);
+-}
+-EXPORT_SYMBOL_GPL(put_driver);
+-
+ static int driver_add_groups(struct device_driver *drv,
+ 			     const struct attribute_group **groups)
+ {
+diff --git a/include/linux/device.h b/include/linux/device.h
+index a782d7ff9e8b..d28bd8295677 100644
+--- a/include/linux/device.h
++++ b/include/linux/device.h
+@@ -238,8 +238,6 @@ struct device_driver {
+ extern int __must_check driver_register(struct device_driver *drv);
+ extern void driver_unregister(struct device_driver *drv);
+ 
+-extern struct device_driver *get_driver(struct device_driver *drv);
+-extern void put_driver(struct device_driver *drv);
+ extern struct device_driver *driver_find(const char *name,
+ 					 struct bus_type *bus);
+ extern int driver_probe_done(void);

commit f3ff9247088a0af0c192a28908dab76ff3d8871f
+Author: Alan Stern 
+Date:   Tue Jan 24 13:35:24 2012 -0500
+
+    Remove useless get_driver()/put_driver() calls
+    
+    As part of the removal of get_driver()/put_driver(), this patch
+    (as1512) gets rid of various useless and unnecessary calls in several
+    drivers.  In some cases it may be desirable to pin the driver by
+    calling try_module_get(), but that can be done later.
+    
+    Signed-off-by: Alan Stern 
+    CC: "David S. Miller" 
+    CC: Konrad Rzeszutek Wilk 
+    CC: Michael Buesch 
+    CC: Joerg Roedel 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
+index f320f466f03b..e8c42d6a7d1c 100644
+--- a/drivers/net/phy/phy_device.c
++++ b/drivers/net/phy/phy_device.c
+@@ -915,9 +915,7 @@ static int phy_probe(struct device *dev)
+ 
+ 	phydev = to_phy_device(dev);
+ 
+-	/* Make sure the driver is held.
+-	 * XXX -- Is this correct? */
+-	drv = get_driver(phydev->dev.driver);
++	drv = phydev->dev.driver;
+ 	phydrv = to_phy_driver(drv);
+ 	phydev->drv = phydrv;
+ 
+@@ -957,8 +955,6 @@ static int phy_remove(struct device *dev)
+ 
+ 	if (phydev->drv->remove)
+ 		phydev->drv->remove(phydev);
+-
+-	put_driver(dev->driver);
+ 	phydev->drv = NULL;
+ 
+ 	return 0;
+diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
+index 7cf3d2fcf56a..6f819988a8da 100644
+--- a/drivers/pci/xen-pcifront.c
++++ b/drivers/pci/xen-pcifront.c
+@@ -593,7 +593,7 @@ static pci_ers_result_t pcifront_common_process(int cmd,
+ 	}
+ 	pdrv = pcidev->driver;
+ 
+-	if (get_driver(&pdrv->driver)) {
++	if (pdrv->driver) {
+ 		if (pdrv->err_handler && pdrv->err_handler->error_detected) {
+ 			dev_dbg(&pcidev->dev,
+ 				"trying to call AER service\n");
+@@ -623,7 +623,6 @@ static pci_ers_result_t pcifront_common_process(int cmd,
+ 				}
+ 			}
+ 		}
+-		put_driver(&pdrv->driver);
+ 	}
+ 	if (!flag)
+ 		result = PCI_ERS_RESULT_NONE;
+diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
+index bb6317fb925c..ff109ae94767 100644
+--- a/drivers/ssb/main.c
++++ b/drivers/ssb/main.c
+@@ -140,19 +140,6 @@ static void ssb_device_put(struct ssb_device *dev)
+ 		put_device(dev->dev);
+ }
+ 
+-static inline struct ssb_driver *ssb_driver_get(struct ssb_driver *drv)
+-{
+-	if (drv)
+-		get_driver(&drv->drv);
+-	return drv;
+-}
+-
+-static inline void ssb_driver_put(struct ssb_driver *drv)
+-{
+-	if (drv)
+-		put_driver(&drv->drv);
+-}
+-
+ static int ssb_device_resume(struct device *dev)
+ {
+ 	struct ssb_device *ssb_dev = dev_to_ssb_dev(dev);
+@@ -250,11 +237,9 @@ int ssb_devices_freeze(struct ssb_bus *bus, struct ssb_freeze_context *ctx)
+ 			ssb_device_put(sdev);
+ 			continue;
+ 		}
+-		sdrv = ssb_driver_get(drv_to_ssb_drv(sdev->dev->driver));
+-		if (!sdrv || SSB_WARN_ON(!sdrv->remove)) {
+-			ssb_device_put(sdev);
++		sdrv = drv_to_ssb_drv(sdev->dev->driver);
++		if (SSB_WARN_ON(!sdrv->remove))
+ 			continue;
+-		}
+ 		sdrv->remove(sdev);
+ 		ctx->device_frozen[i] = 1;
+ 	}
+@@ -293,7 +278,6 @@ int ssb_devices_thaw(struct ssb_freeze_context *ctx)
+ 				   dev_name(sdev->dev));
+ 			result = err;
+ 		}
+-		ssb_driver_put(sdrv);
+ 		ssb_device_put(sdev);
+ 	}
+ 
+diff --git a/lib/dma-debug.c b/lib/dma-debug.c
+index fea790a2b176..13ef2338be41 100644
+--- a/lib/dma-debug.c
++++ b/lib/dma-debug.c
+@@ -170,7 +170,7 @@ static bool driver_filter(struct device *dev)
+ 		return false;
+ 
+ 	/* driver filter on but not yet initialized */
+-	drv = get_driver(dev->driver);
++	drv = dev->driver;
+ 	if (!drv)
+ 		return false;
+ 
+@@ -185,7 +185,6 @@ static bool driver_filter(struct device *dev)
+ 	}
+ 
+ 	read_unlock_irqrestore(&driver_name_lock, flags);
+-	put_driver(drv);
+ 
+ 	return ret;
+ }

commit cef9bc56e1e944afd11f96de569657117a138c6d
+Author: Alan Stern 
+Date:   Tue Jan 24 13:34:41 2012 -0500
+
+    Dynamic ID addition doesn't need get_driver()
+    
+    As part of the removal of get_driver()/put_driver(), this patch
+    (as1511) changes all the places that add dynamic IDs for drivers.
+    Since these additions are done by writing to the drivers' sysfs
+    attribute files, and the attributes are removed when the drivers are
+    unregistered, there is no reason to take an extra reference to the
+    drivers.
+    
+    The one exception is the pci-stub driver, which calls pci_add_dynid()
+    as part of its registration.  But again, there's no reason to take an
+    extra reference here, because the driver can't be unloaded while it is
+    being registered.
+    
+    Signed-off-by: Alan Stern 
+    CC: Dmitry Torokhov 
+    CC: Jiri Kosina 
+    CC: Jesse Barnes 
+    CC: Dominik Brodowski 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
+index af08ce7207d9..bce53fa0e166 100644
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -1619,11 +1619,7 @@ static ssize_t store_new_id(struct device_driver *drv, const char *buf,
+ 	list_add_tail(&dynid->list, &hdrv->dyn_list);
+ 	spin_unlock(&hdrv->dyn_lock);
+ 
+-	ret = 0;
+-	if (get_driver(&hdrv->driver)) {
+-		ret = driver_attach(&hdrv->driver);
+-		put_driver(&hdrv->driver);
+-	}
++	ret = driver_attach(&hdrv->driver);
+ 
+ 	return ret ? : count;
+ }
+diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
+index 3623d65f8b86..ff540477fe8b 100644
+--- a/drivers/pci/pci-driver.c
++++ b/drivers/pci/pci-driver.c
+@@ -72,9 +72,7 @@ int pci_add_dynid(struct pci_driver *drv,
+ 	list_add_tail(&dynid->node, &drv->dynids.list);
+ 	spin_unlock(&drv->dynids.lock);
+ 
+-	get_driver(&drv->driver);
+ 	retval = driver_attach(&drv->driver);
+-	put_driver(&drv->driver);
+ 
+ 	return retval;
+ }
+diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
+index 749c2a16012c..059699f6363d 100644
+--- a/drivers/pcmcia/ds.c
++++ b/drivers/pcmcia/ds.c
+@@ -127,10 +127,7 @@ pcmcia_store_new_id(struct device_driver *driver, const char *buf, size_t count)
+ 	list_add_tail(&dynid->node, &pdrv->dynids.list);
+ 	mutex_unlock(&pdrv->dynids.lock);
+ 
+-	if (get_driver(&pdrv->drv)) {
+-		retval = driver_attach(&pdrv->drv);
+-		put_driver(&pdrv->drv);
+-	}
++	retval = driver_attach(&pdrv->drv);
+ 
+ 	if (retval)
+ 		return retval;
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index d40ff9568813..54c493b4226b 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -71,10 +71,7 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
+ 	list_add_tail(&dynid->node, &dynids->list);
+ 	spin_unlock(&dynids->lock);
+ 
+-	if (get_driver(driver)) {
+-		retval = driver_attach(driver);
+-		put_driver(driver);
+-	}
++	retval = driver_attach(driver);
+ 
+ 	if (retval)
+ 		return retval;

commit fde25a9b63b9a3dc91365c394a426ebe64cfc2da
+Author: Alan Stern 
+Date:   Tue Jan 24 13:34:24 2012 -0500
+
+    Driver core: driver_find() drops reference before returning
+    
+    As part of the removal of get_driver()/put_driver(), this patch
+    (as1510) changes driver_find(); it now drops the reference it acquires
+    before returning.  The patch also adjusts all the callers of
+    driver_find() to remove the now unnecessary calls to put_driver().
+    
+    In addition, the patch adds a warning to driver_find(): Callers must
+    make sure the driver they are searching for does not get unloaded
+    while they are using it.  This has always been the case; driver_find()
+    has never prevented a driver from being unregistered or unloaded.
+    Hence the patch will not introduce any new bugs.  The existing callers
+    all seem to be okay in this respect, however I don't understand the
+    video drivers well enough to be certain about them.
+    
+    Signed-off-by: Alan Stern 
+    CC: Dmitry Torokhov 
+    CC: Kyungmin Park 
+    CC: Andy Walls 
+    CC: Martin Schwidefsky 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/base/driver.c b/drivers/base/driver.c
+index b631f7c59453..e979cad75c6e 100644
+--- a/drivers/base/driver.c
++++ b/drivers/base/driver.c
+@@ -234,7 +234,6 @@ int driver_register(struct device_driver *drv)
+ 
+ 	other = driver_find(drv->name, drv->bus);
+ 	if (other) {
+-		put_driver(other);
+ 		printk(KERN_ERR "Error: Driver '%s' is already registered, "
+ 			"aborting...\n", drv->name);
+ 		return -EBUSY;
+@@ -275,7 +274,9 @@ EXPORT_SYMBOL_GPL(driver_unregister);
+  * Call kset_find_obj() to iterate over list of drivers on
+  * a bus to find driver by name. Return driver if found.
+  *
+- * Note that kset_find_obj increments driver's reference count.
++ * This routine provides no locking to prevent the driver it returns
++ * from being unregistered or unloaded while the caller is using it.
++ * The caller is responsible for preventing this.
+  */
+ struct device_driver *driver_find(const char *name, struct bus_type *bus)
+ {
+@@ -283,6 +284,8 @@ struct device_driver *driver_find(const char *name, struct bus_type *bus)
+ 	struct driver_private *priv;
+ 
+ 	if (k) {
++		/* Drop reference added by kset_find_obj() */
++		kobject_put(k);
+ 		priv = to_driver(k);
+ 		return priv->driver;
+ 	}
+diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
+index c351aa421f8f..da739d9d1905 100644
+--- a/drivers/input/gameport/gameport.c
++++ b/drivers/input/gameport/gameport.c
+@@ -449,7 +449,6 @@ static ssize_t gameport_rebind_driver(struct device *dev, struct device_attribut
+ 	} else if ((drv = driver_find(buf, &gameport_bus)) != NULL) {
+ 		gameport_disconnect_port(gameport);
+ 		error = gameport_bind_driver(gameport, to_gameport_driver(drv));
+-		put_driver(drv);
+ 	} else {
+ 		error = -EINVAL;
+ 	}
+diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
+index ba70058e2be3..d0f7533dbf88 100644
+--- a/drivers/input/serio/serio.c
++++ b/drivers/input/serio/serio.c
+@@ -441,7 +441,6 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *
+ 	} else if ((drv = driver_find(buf, &serio_bus)) != NULL) {
+ 		serio_disconnect_port(serio);
+ 		error = serio_bind_driver(serio, to_serio_driver(drv));
+-		put_driver(drv);
+ 		serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT);
+ 	} else {
+ 		error = -EINVAL;
+diff --git a/drivers/media/video/cx18/cx18-alsa-main.c b/drivers/media/video/cx18/cx18-alsa-main.c
+index a1e6c2a32478..e118361c2e7b 100644
+--- a/drivers/media/video/cx18/cx18-alsa-main.c
++++ b/drivers/media/video/cx18/cx18-alsa-main.c
+@@ -285,7 +285,6 @@ static void __exit cx18_alsa_exit(void)
+ 
+ 	drv = driver_find("cx18", &pci_bus_type);
+ 	ret = driver_for_each_device(drv, NULL, NULL, cx18_alsa_exit_callback);
+-	put_driver(drv);
+ 
+ 	cx18_ext_init = NULL;
+ 	printk(KERN_INFO "cx18-alsa: module unload complete\n");
+diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c
+index d0fbfcf7133d..e5e7fa9e737b 100644
+--- a/drivers/media/video/ivtv/ivtvfb.c
++++ b/drivers/media/video/ivtv/ivtvfb.c
+@@ -1293,7 +1293,6 @@ static int __init ivtvfb_init(void)
+ 
+ 	drv = driver_find("ivtv", &pci_bus_type);
+ 	err = driver_for_each_device(drv, NULL, ®istered, ivtvfb_callback_init);
+-	put_driver(drv);
+ 	if (!registered) {
+ 		printk(KERN_ERR "ivtvfb:  no cards found\n");
+ 		return -ENODEV;
+@@ -1310,7 +1309,6 @@ static void ivtvfb_cleanup(void)
+ 
+ 	drv = driver_find("ivtv", &pci_bus_type);
+ 	err = driver_for_each_device(drv, NULL, NULL, ivtvfb_callback_cleanup);
+-	put_driver(drv);
+ }
+ 
+ module_init(ivtvfb_init);
+diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.c b/drivers/media/video/s5p-fimc/fimc-mdevice.c
+index 8ea4ee116e46..63eccb55728f 100644
+--- a/drivers/media/video/s5p-fimc/fimc-mdevice.c
++++ b/drivers/media/video/s5p-fimc/fimc-mdevice.c
+@@ -344,16 +344,13 @@ static int fimc_md_register_platform_entities(struct fimc_md *fmd)
+ 		return -ENODEV;
+ 	ret = driver_for_each_device(driver, NULL, fmd,
+ 				     fimc_register_callback);
+-	put_driver(driver);
+ 	if (ret)
+ 		return ret;
+ 
+ 	driver = driver_find(CSIS_DRIVER_NAME, &platform_bus_type);
+-	if (driver) {
++	if (driver)
+ 		ret = driver_for_each_device(driver, NULL, fmd,
+ 					     csis_register_callback);
+-		put_driver(driver);
+-	}
+ 	return ret;
+ }
+ 
+diff --git a/drivers/media/video/s5p-tv/mixer_video.c b/drivers/media/video/s5p-tv/mixer_video.c
+index 7884baeff76a..f7ca5cc143c6 100644
+--- a/drivers/media/video/s5p-tv/mixer_video.c
++++ b/drivers/media/video/s5p-tv/mixer_video.c
+@@ -58,7 +58,6 @@ static struct v4l2_subdev *find_and_register_subdev(
+ 	}
+ 
+ done:
+-	put_driver(drv);
+ 	return sd;
+ }
+ 
+diff --git a/drivers/s390/net/smsgiucv_app.c b/drivers/s390/net/smsgiucv_app.c
+index 4d2ea4000422..32515a201bbc 100644
+--- a/drivers/s390/net/smsgiucv_app.c
++++ b/drivers/s390/net/smsgiucv_app.c
+@@ -168,7 +168,7 @@ static int __init smsgiucv_app_init(void)
+ 	rc = dev_set_name(smsg_app_dev, KMSG_COMPONENT);
+ 	if (rc) {
+ 		kfree(smsg_app_dev);
+-		goto fail_put_driver;
++		goto fail;
+ 	}
+ 	smsg_app_dev->bus = &iucv_bus;
+ 	smsg_app_dev->parent = iucv_root;
+@@ -177,7 +177,7 @@ static int __init smsgiucv_app_init(void)
+ 	rc = device_register(smsg_app_dev);
+ 	if (rc) {
+ 		put_device(smsg_app_dev);
+-		goto fail_put_driver;
++		goto fail;
+ 	}
+ 
+ 	/* convert sender to uppercase characters */
+@@ -191,12 +191,11 @@ static int __init smsgiucv_app_init(void)
+ 	rc = smsg_register_callback(SMSG_PREFIX, smsg_app_callback);
+ 	if (rc) {
+ 		device_unregister(smsg_app_dev);
+-		goto fail_put_driver;
++		goto fail;
+ 	}
+ 
+ 	rc = 0;
+-fail_put_driver:
+-	put_driver(smsgiucv_drv);
++fail:
+ 	return rc;
+ }
+ module_init(smsgiucv_app_init);

commit 194b3af4eb4b7ba84e2e4274daf9f58aa958bd04
+Author: Alan Stern 
+Date:   Tue Jan 24 11:58:15 2012 -0500
+
+    USB: OHCI: fix new compiler warnings
+    
+    This patch (as1515) fixes some unavoidably dumb compiler warnings:
+    
+      CC [M]  drivers/usb/renesas_usbhs/mod.o
+    In file included from drivers/usb/host/ohci-hcd.c:101:0:
+    drivers/usb/host/ohci-dbg.c: In function ‘fill_registers_buffer’:
+    drivers/usb/host/ohci-dbg.c:656:2: warning: the comparison will always evaluate as ‘true’ for the address of ‘next’ will never be NULL [-Waddress]
+    drivers/usb/host/ohci-dbg.c:675:3: warning: the comparison will always evaluate as ‘true’ for the address of ‘next’ will never be NULL [-Waddress]
+    
+    Instead of trying to fix the macro to work under all cirumstances,
+    just add a second macro for use in cases where the "next" argument is
+    the address of a local variable.
+    
+    Unfortunately the macro cannot be replaced by a real subroutine,
+    because there's no va_list version of ohci_dbg() or dev_dbg().
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
+index 5179fcd73d8a..e4bcb62b930a 100644
+--- a/drivers/usb/host/ohci-dbg.c
++++ b/drivers/usb/host/ohci-dbg.c
+@@ -82,6 +82,14 @@ urb_print(struct urb * urb, char * str, int small, int status)
+ 		ohci_dbg(ohci,format, ## arg ); \
+ 	} while (0);
+ 
++/* Version for use where "next" is the address of a local variable */
++#define ohci_dbg_nosw(ohci, next, size, format, arg...) \
++	do { \
++		unsigned s_len; \
++		s_len = scnprintf(*next, *size, format, ## arg); \
++		*size -= s_len; *next += s_len; \
++	} while (0);
++
+ 
+ static void ohci_dump_intr_mask (
+ 	struct ohci_hcd *ohci,
+@@ -653,7 +661,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
+ 
+ 	/* dump driver info, then registers in spec order */
+ 
+-	ohci_dbg_sw (ohci, &next, &size,
++	ohci_dbg_nosw(ohci, &next, &size,
+ 		"bus %s, device %s\n"
+ 		"%s\n"
+ 		"%s\n",
+@@ -672,7 +680,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
+ 
+ 	/* hcca */
+ 	if (ohci->hcca)
+-		ohci_dbg_sw (ohci, &next, &size,
++		ohci_dbg_nosw(ohci, &next, &size,
+ 			"hcca frame 0x%04x\n", ohci_frame_no(ohci));
+ 
+ 	/* other registers mostly affect frame timings */

commit b10d5efdf7892d18b3b7d899edce2c8d9b80aea9
+Author: Alan Stern 
+Date:   Tue Jan 17 11:39:00 2012 -0500
+
+    Documentation update for the driver model core
+    
+    This patch (as1509) documents two important points regarding the use
+    of device structures in the driver model:
+    
+            Structures must be initialized to all 0's before they are
+            passed to device_initialize().
+    
+            Structures must not be passed to device_add() or
+            device_register() more than once.
+    
+    Although these restrictions have applied ever since the driver model
+    was first created, they have not been mentioned anywhere.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/base/core.c b/drivers/base/core.c
+index 4a67cc0c8b37..ad29e928baaa 100644
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -632,6 +632,11 @@ static void klist_children_put(struct klist_node *n)
+  * may be used for reference counting of @dev after calling this
+  * function.
+  *
++ * All fields in @dev must be initialized by the caller to 0, except
++ * for those explicitly set to some other value.  The simplest
++ * approach is to use kzalloc() to allocate the structure containing
++ * @dev.
++ *
+  * NOTE: Use put_device() to give up your reference instead of freeing
+  * @dev directly once you have called this function.
+  */
+@@ -930,6 +935,13 @@ int device_private_init(struct device *dev)
+  * to the global and sibling lists for the device, then
+  * adds it to the other relevant subsystems of the driver model.
+  *
++ * Do not call this routine or device_register() more than once for
++ * any device structure.  The driver model core is not designed to work
++ * with devices that get unregistered and then spring back to life.
++ * (Among other things, it's very hard to guarantee that all references
++ * to the previous incarnation of @dev have been dropped.)  Allocate
++ * and register a fresh new struct device instead.
++ *
+  * NOTE: _Never_ directly free @dev after calling this function, even
+  * if it returned an error! Always use put_device() to give up your
+  * reference instead.
+@@ -1090,6 +1102,9 @@ int device_add(struct device *dev)
+  * have a clearly defined need to use and refcount the device
+  * before it is added to the hierarchy.
+  *
++ * For more information, see the kerneldoc for device_initialize()
++ * and device_add().
++ *
+  * NOTE: _Never_ directly free @dev after calling this function, even
+  * if it returned an error! Always use put_device() to give up the
+  * reference initialized in this function instead.

commit d8cae98cddd286e38db1724dda1b0e7b467f9237
+Author: Alan Stern 
+Date:   Wed Jan 4 16:36:35 2012 -0500
+
+    USB: update documentation for usbmon
+    
+    The documentation for usbmon is out of date; the usbfs "devices" file
+    now exists in /sys/kernel/debug/usb rather than /proc/bus/usb.  This
+    patch (as1505) updates the documentation accordingly, and also
+    mentions that the necessary information can be found by running lsusb.
+    
+    Signed-off-by: Alan Stern 
+    CC: Pete Zaitcev 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/usb/usbmon.txt b/Documentation/usb/usbmon.txt
+index a4efa0462f05..5335fa8b06eb 100644
+--- a/Documentation/usb/usbmon.txt
++++ b/Documentation/usb/usbmon.txt
+@@ -47,10 +47,11 @@ This allows to filter away annoying devices that talk continuously.
+ 
+ 2. Find which bus connects to the desired device
+ 
+-Run "cat /proc/bus/usb/devices", and find the T-line which corresponds to
+-the device. Usually you do it by looking for the vendor string. If you have
+-many similar devices, unplug one and compare two /proc/bus/usb/devices outputs.
+-The T-line will have a bus number. Example:
++Run "cat /sys/kernel/debug/usb/devices", and find the T-line which corresponds
++to the device. Usually you do it by looking for the vendor string. If you have
++many similar devices, unplug one and compare the two
++/sys/kernel/debug/usb/devices outputs. The T-line will have a bus number.
++Example:
+ 
+ T:  Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12  MxCh= 0
+ D:  Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
+@@ -58,7 +59,10 @@ P:  Vendor=0557 ProdID=2004 Rev= 1.00
+ S:  Manufacturer=ATEN
+ S:  Product=UC100KM V2.00
+ 
+-Bus=03 means it's bus 3.
++"Bus=03" means it's bus 3. Alternatively, you can look at the output from
++"lsusb" and get the bus number from the appropriate line. Example:
++
++Bus 003 Device 002: ID 0557:2004 ATEN UC100KM V2.00
+ 
+ 3. Start 'cat'
+ 

commit fe6b91f47080eb17d21cbf2a39311877d57f6938
+Author: Alan Stern 
+Date:   Tue Dec 6 23:24:52 2011 +0100
+
+    PM / Driver core: leave runtime PM enabled during system shutdown
+    
+    Disabling all runtime PM during system shutdown turns out not to be a
+    good idea, because some devices may need to be woken up from a
+    low-power state at that time.
+    
+    The whole point of disabling runtime PM for system shutdown was to
+    prevent untimely runtime-suspend method calls.  This patch (as1504)
+    accomplishes the same result by incrementing the usage count for each
+    device and waiting for ongoing runtime-PM callbacks to finish.  This
+    is what we already do during system suspend and hibernation, which
+    makes sense since the shutdown method is pretty much a legacy analog
+    of the pm->poweroff method.
+    
+    This fixes a recent regression on some OMAP systems introduced by
+    commit af8db1508f2c9f3b6e633e2d2d906c6557c617f9 (PM / driver core:
+    disable device's runtime PM during shutdown).
+    
+    Reported-and-tested-by: NeilBrown 
+    Signed-off-by: Alan Stern 
+    Acked-by: Greg Kroah-Hartman 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/base/core.c b/drivers/base/core.c
+index d8b3d89db043..919daa7cd5b1 100644
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -1743,8 +1743,10 @@ void device_shutdown(void)
+ 		 */
+ 		list_del_init(&dev->kobj.entry);
+ 		spin_unlock(&devices_kset->list_lock);
+-		/* Disable all device's runtime power management */
+-		pm_runtime_disable(dev);
++
++		/* Don't allow any more runtime suspends */
++		pm_runtime_get_noresume(dev);
++		pm_runtime_barrier(dev);
+ 
+ 		if (dev->bus && dev->bus->shutdown) {
+ 			dev_dbg(dev, "shutdown\n");

commit 045ddc8991698a8e9c5668c6190faa8b5d516dc0
+Author: Alan Stern 
+Date:   Mon Nov 21 10:15:13 2011 -0500
+
+    NLS: raname "maxlen" to "maxout" in UTF conversion routines
+    
+    As requested by NamJae Jeon, this patch (as1503) changes the name of
+    the "maxlen" parameters to "maxout" in the various UTF conversion
+    routines.  This should make the role of that parameter more clear.
+    
+    The patch also renames the "len" parameters to "inlen", for the same
+    reason.
+    
+    Signed-off-by: Alan Stern 
+    Reviewed-by: NamJae Jeon 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/fs/nls/nls_base.c b/fs/nls/nls_base.c
+index 0eb059ec6f28..fea6bd5831dc 100644
+--- a/fs/nls/nls_base.c
++++ b/fs/nls/nls_base.c
+@@ -52,7 +52,7 @@ static const struct utf8_table utf8_table[] =
+ #define SURROGATE_LOW	0x00000400
+ #define SURROGATE_BITS	0x000003ff
+ 
+-int utf8_to_utf32(const u8 *s, int len, unicode_t *pu)
++int utf8_to_utf32(const u8 *s, int inlen, unicode_t *pu)
+ {
+ 	unsigned long l;
+ 	int c0, c, nc;
+@@ -71,7 +71,7 @@ int utf8_to_utf32(const u8 *s, int len, unicode_t *pu)
+ 			*pu = (unicode_t) l;
+ 			return nc;
+ 		}
+-		if (len <= nc)
++		if (inlen <= nc)
+ 			return -1;
+ 		s++;
+ 		c = (*s ^ 0x80) & 0xFF;
+@@ -83,7 +83,7 @@ int utf8_to_utf32(const u8 *s, int len, unicode_t *pu)
+ }
+ EXPORT_SYMBOL(utf8_to_utf32);
+ 
+-int utf32_to_utf8(unicode_t u, u8 *s, int maxlen)
++int utf32_to_utf8(unicode_t u, u8 *s, int maxout)
+ {
+ 	unsigned long l;
+ 	int c, nc;
+@@ -97,7 +97,7 @@ int utf32_to_utf8(unicode_t u, u8 *s, int maxlen)
+ 		return -1;
+ 
+ 	nc = 0;
+-	for (t = utf8_table; t->cmask && maxlen; t++, maxlen--) {
++	for (t = utf8_table; t->cmask && maxout; t++, maxout--) {
+ 		nc++;
+ 		if (l <= t->lmask) {
+ 			c = t->shift;
+@@ -129,24 +129,24 @@ static inline void put_utf16(wchar_t *s, unsigned c, enum utf16_endian endian)
+ 	}
+ }
+ 
+-int utf8s_to_utf16s(const u8 *s, int len, enum utf16_endian endian,
+-		wchar_t *pwcs, int maxlen)
++int utf8s_to_utf16s(const u8 *s, int inlen, enum utf16_endian endian,
++		wchar_t *pwcs, int maxout)
+ {
+ 	u16 *op;
+ 	int size;
+ 	unicode_t u;
+ 
+ 	op = pwcs;
+-	while (len > 0 && maxlen > 0 && *s) {
++	while (inlen > 0 && maxout > 0 && *s) {
+ 		if (*s & 0x80) {
+-			size = utf8_to_utf32(s, len, &u);
++			size = utf8_to_utf32(s, inlen, &u);
+ 			if (size < 0)
+ 				return -EINVAL;
+ 			s += size;
+-			len -= size;
++			inlen -= size;
+ 
+ 			if (u >= PLANE_SIZE) {
+-				if (maxlen < 2)
++				if (maxout < 2)
+ 					break;
+ 				u -= PLANE_SIZE;
+ 				put_utf16(op++, SURROGATE_PAIR |
+@@ -156,15 +156,15 @@ int utf8s_to_utf16s(const u8 *s, int len, enum utf16_endian endian,
+ 						SURROGATE_LOW |
+ 						(u & SURROGATE_BITS),
+ 						endian);
+-				maxlen -= 2;
++				maxout -= 2;
+ 			} else {
+ 				put_utf16(op++, u, endian);
+-				maxlen--;
++				maxout--;
+ 			}
+ 		} else {
+ 			put_utf16(op++, *s++, endian);
+-			len--;
+-			maxlen--;
++			inlen--;
++			maxout--;
+ 		}
+ 	}
+ 	return op - pwcs;
+@@ -183,27 +183,27 @@ static inline unsigned long get_utf16(unsigned c, enum utf16_endian endian)
+ 	}
+ }
+ 
+-int utf16s_to_utf8s(const wchar_t *pwcs, int len, enum utf16_endian endian,
+-		u8 *s, int maxlen)
++int utf16s_to_utf8s(const wchar_t *pwcs, int inlen, enum utf16_endian endian,
++		u8 *s, int maxout)
+ {
+ 	u8 *op;
+ 	int size;
+ 	unsigned long u, v;
+ 
+ 	op = s;
+-	while (len > 0 && maxlen > 0) {
++	while (inlen > 0 && maxout > 0) {
+ 		u = get_utf16(*pwcs, endian);
+ 		if (!u)
+ 			break;
+ 		pwcs++;
+-		len--;
++		inlen--;
+ 		if (u > 0x7f) {
+ 			if ((u & SURROGATE_MASK) == SURROGATE_PAIR) {
+ 				if (u & SURROGATE_LOW) {
+ 					/* Ignore character and move on */
+ 					continue;
+ 				}
+-				if (len <= 0)
++				if (inlen <= 0)
+ 					break;
+ 				v = get_utf16(*pwcs, endian);
+ 				if ((v & SURROGATE_MASK) != SURROGATE_PAIR ||
+@@ -214,18 +214,18 @@ int utf16s_to_utf8s(const wchar_t *pwcs, int len, enum utf16_endian endian,
+ 				u = PLANE_SIZE + ((u & SURROGATE_BITS) << 10)
+ 						+ (v & SURROGATE_BITS);
+ 				pwcs++;
+-				len--;
++				inlen--;
+ 			}
+-			size = utf32_to_utf8(u, op, maxlen);
++			size = utf32_to_utf8(u, op, maxout);
+ 			if (size == -1) {
+ 				/* Ignore character and move on */
+ 			} else {
+ 				op += size;
+-				maxlen -= size;
++				maxout -= size;
+ 			}
+ 		} else {
+ 			*op++ = (u8) u;
+-			maxlen--;
++			maxout--;
+ 		}
+ 	}
+ 	return op - s;

commit c61875977458637226ab093a35d200f2d5789787
+Author: Alan Stern 
+Date:   Thu Nov 17 16:41:45 2011 -0500
+
+    OHCI: final fix for NVIDIA problems (I hope)
+    
+    Problems with NVIDIA's OHCI host controllers persist.  After looking
+    carefully through the spec, I finally realized that when a controller
+    is reset it then automatically goes into a SUSPEND state in which it
+    is completely quiescent (no DMA and no IRQs) and from which it will
+    not awaken until the system puts it into the OPERATIONAL state.
+    
+    Therefore there's no need to worry about controllers being in the
+    RESET state for extended periods, or remaining in the OPERATIONAL
+    state during system shutdown.  The proper action for device
+    initialization is to put the controller into the RESET state (if it's
+    not there already) and then to issue a software reset.  Similarly, the
+    proper action for device shutdown is simply to do a software reset.
+    
+    This patch (as1499) implements such an approach.  It simplifies
+    initialization and shutdown, and allows the NVIDIA shutdown-quirk code
+    to be removed.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Andre "Osku" Schmidt 
+    Tested-by: Arno Augustin 
+    Cc: stable  [after tested in 3.2 for a while]
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index 34efd479e068..b2639191549e 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -389,17 +389,14 @@ ohci_shutdown (struct usb_hcd *hcd)
+ 	struct ohci_hcd *ohci;
+ 
+ 	ohci = hcd_to_ohci (hcd);
+-	ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
+-	ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
++	ohci_writel(ohci, (u32) ~0, &ohci->regs->intrdisable);
+ 
+-	/* If the SHUTDOWN quirk is set, don't put the controller in RESET */
+-	ohci->hc_control &= (ohci->flags & OHCI_QUIRK_SHUTDOWN ?
+-			OHCI_CTRL_RWC | OHCI_CTRL_HCFS :
+-			OHCI_CTRL_RWC);
+-	ohci_writel(ohci, ohci->hc_control, &ohci->regs->control);
++	/* Software reset, after which the controller goes into SUSPEND */
++	ohci_writel(ohci, OHCI_HCR, &ohci->regs->cmdstatus);
++	ohci_readl(ohci, &ohci->regs->cmdstatus);	/* flush the writes */
++	udelay(10);
+ 
+-	/* flush the writes */
+-	(void) ohci_readl (ohci, &ohci->regs->control);
++	ohci_writel(ohci, ohci->fminterval, &ohci->regs->fminterval);
+ }
+ 
+ static int check_ed(struct ohci_hcd *ohci, struct ed *ed)
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index ad8166c681e2..bc01b064585a 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -175,28 +175,6 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd)
+ 	return 0;
+ }
+ 
+-/* nVidia controllers continue to drive Reset signalling on the bus
+- * even after system shutdown, wasting power.  This flag tells the
+- * shutdown routine to leave the controller OPERATIONAL instead of RESET.
+- */
+-static int ohci_quirk_nvidia_shutdown(struct usb_hcd *hcd)
+-{
+-	struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+-	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+-
+-	/* Evidently nVidia fixed their later hardware; this is a guess at
+-	 * the changeover point.
+-	 */
+-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB		0x026d
+-
+-	if (pdev->device < PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB) {
+-		ohci->flags |= OHCI_QUIRK_SHUTDOWN;
+-		ohci_dbg(ohci, "enabled nVidia shutdown quirk\n");
+-	}
+-
+-	return 0;
+-}
+-
+ static void sb800_prefetch(struct ohci_hcd *ohci, int on)
+ {
+ 	struct pci_dev *pdev;
+@@ -260,10 +238,6 @@ static const struct pci_device_id ohci_pci_quirks[] = {
+ 		PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399),
+ 		.driver_data = (unsigned long)ohci_quirk_amd700,
+ 	},
+-	{
+-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID),
+-		.driver_data = (unsigned long) ohci_quirk_nvidia_shutdown,
+-	},
+ 
+ 	/* FIXME for some of the early AMD 760 southbridges, OHCI
+ 	 * won't work at all.  blacklist them.
+diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
+index 35e5fd640ce7..0795b934d00c 100644
+--- a/drivers/usb/host/ohci.h
++++ b/drivers/usb/host/ohci.h
+@@ -403,7 +403,6 @@ struct ohci_hcd {
+ #define	OHCI_QUIRK_HUB_POWER	0x100			/* distrust firmware power/oc setup */
+ #define	OHCI_QUIRK_AMD_PLL	0x200			/* AMD PLL quirk*/
+ #define	OHCI_QUIRK_AMD_PREFETCH	0x400			/* pre-fetch for ISO transfer */
+-#define	OHCI_QUIRK_SHUTDOWN	0x800			/* nVidia power bug */
+ 	// there are also chip quirks/bugs in init logic
+ 
+ 	struct work_struct	nec_work;	/* Worker for NEC quirk */
+diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
+index c7fd6ce11904..caf87428ca43 100644
+--- a/drivers/usb/host/pci-quirks.c
++++ b/drivers/usb/host/pci-quirks.c
+@@ -37,6 +37,7 @@
+ #define OHCI_INTRENABLE		0x10
+ #define OHCI_INTRDISABLE	0x14
+ #define OHCI_FMINTERVAL		0x34
++#define OHCI_HCFS		(3 << 6)	/* hc functional state */
+ #define OHCI_HCR		(1 << 0)	/* host controller reset */
+ #define OHCI_OCR		(1 << 3)	/* ownership change request */
+ #define OHCI_CTRL_RWC		(1 << 9)	/* remote wakeup connected */
+@@ -466,6 +467,8 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
+ {
+ 	void __iomem *base;
+ 	u32 control;
++	u32 fminterval;
++	int cnt;
+ 
+ 	if (!mmio_resource_enabled(pdev, 0))
+ 		return;
+@@ -498,41 +501,32 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
+ 	}
+ #endif
+ 
+-	/* reset controller, preserving RWC (and possibly IR) */
+-	writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL);
+-	readl(base + OHCI_CONTROL);
++	/* disable interrupts */
++	writel((u32) ~0, base + OHCI_INTRDISABLE);
+ 
+-	/* Some NVIDIA controllers stop working if kept in RESET for too long */
+-	if (pdev->vendor == PCI_VENDOR_ID_NVIDIA) {
+-		u32 fminterval;
+-		int cnt;
++	/* Reset the USB bus, if the controller isn't already in RESET */
++	if (control & OHCI_HCFS) {
++		/* Go into RESET, preserving RWC (and possibly IR) */
++		writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL);
++		readl(base + OHCI_CONTROL);
+ 
+-		/* drive reset for at least 50 ms (7.1.7.5) */
++		/* drive bus reset for at least 50 ms (7.1.7.5) */
+ 		msleep(50);
++	}
+ 
+-		/* software reset of the controller, preserving HcFmInterval */
+-		fminterval = readl(base + OHCI_FMINTERVAL);
+-		writel(OHCI_HCR, base + OHCI_CMDSTATUS);
++	/* software reset of the controller, preserving HcFmInterval */
++	fminterval = readl(base + OHCI_FMINTERVAL);
++	writel(OHCI_HCR, base + OHCI_CMDSTATUS);
+ 
+-		/* reset requires max 10 us delay */
+-		for (cnt = 30; cnt > 0; --cnt) {	/* ... allow extra time */
+-			if ((readl(base + OHCI_CMDSTATUS) & OHCI_HCR) == 0)
+-				break;
+-			udelay(1);
+-		}
+-		writel(fminterval, base + OHCI_FMINTERVAL);
+-
+-		/* Now we're in the SUSPEND state with all devices reset
+-		 * and wakeups and interrupts disabled
+-		 */
++	/* reset requires max 10 us delay */
++	for (cnt = 30; cnt > 0; --cnt) {	/* ... allow extra time */
++		if ((readl(base + OHCI_CMDSTATUS) & OHCI_HCR) == 0)
++			break;
++		udelay(1);
+ 	}
++	writel(fminterval, base + OHCI_FMINTERVAL);
+ 
+-	/*
+-	 * disable interrupts
+-	 */
+-	writel(~(u32)0, base + OHCI_INTRDISABLE);
+-	writel(~(u32)0, base + OHCI_INTRSTATUS);
+-
++	/* Now the controller is safely in SUSPEND and nothing can wake it up */
+ 	iounmap(base);
+ }
+ 

commit 3f5eb8d5688a5266ab943cf94aebe4c0eea726a3
+Author: Alan Stern 
+Date:   Thu Nov 17 16:41:35 2011 -0500
+
+    USB: make the usbfs memory limit configurable
+    
+    The 16-MB global limit on memory used by usbfs isn't suitable for all
+    people.  It's a reasonable default, but there are applications
+    (especially for SuperSpeed devices) that need a lot more.
+    
+    This patch (as1498) creates a writable module parameter for usbcore to
+    control the global limit.  The default is still 16 MB, but users can
+    change it at runtime, even after usbcore has been loaded.  As a
+    special case, setting the value to 0 is treated the same as the hard
+    limit of 2047 MB.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
+index a0c5c5f4fce6..72c68bbec5d4 100644
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -2632,6 +2632,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
+ 			[USB] Start with the old device initialization
+ 			scheme (default 0 = off).
+ 
++	usbcore.usbfs_memory_mb=
++			[USB] Memory limit (in MB) for buffers allocated by
++			usbfs (default = 16, 0 = max = 2047).
++
+ 	usbcore.use_both_schemes=
+ 			[USB] Try the other device initialization scheme
+ 			if the first one fails (default 1 = enabled).
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index b69768b7d226..d8cf06f186f2 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -110,15 +110,33 @@ enum snoop_when {
+ #define USB_DEVICE_DEV		MKDEV(USB_DEVICE_MAJOR, 0)
+ 
+ /* Limit on the total amount of memory we can allocate for transfers */
+-#define MAX_USBFS_MEMORY_USAGE	16777216	/* 16 MB */
++static unsigned usbfs_memory_mb = 16;
++module_param(usbfs_memory_mb, uint, 0644);
++MODULE_PARM_DESC(usbfs_memory_mb,
++		"maximum MB allowed for usbfs buffers (0 = no limit)");
++
++/* Hard limit, necessary to avoid aithmetic overflow */
++#define USBFS_XFER_MAX		(UINT_MAX / 2 - 1000000)
+ 
+ static atomic_t usbfs_memory_usage;	/* Total memory currently allocated */
+ 
+ /* Check whether it's okay to allocate more memory for a transfer */
+ static int usbfs_increase_memory_usage(unsigned amount)
+ {
++	unsigned lim;
++
++	/*
++	 * Convert usbfs_memory_mb to bytes, avoiding overflows.
++	 * 0 means use the hard limit (effectively unlimited).
++	 */
++	lim = ACCESS_ONCE(usbfs_memory_mb);
++	if (lim == 0 || lim > (USBFS_XFER_MAX >> 20))
++		lim = USBFS_XFER_MAX;
++	else
++		lim <<= 20;
++
+ 	atomic_add(amount, &usbfs_memory_usage);
+-	if (atomic_read(&usbfs_memory_usage) <= MAX_USBFS_MEMORY_USAGE)
++	if (atomic_read(&usbfs_memory_usage) <= lim)
+ 		return 0;
+ 	atomic_sub(amount, &usbfs_memory_usage);
+ 	return -ENOMEM;
+@@ -907,7 +925,7 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
+ 	if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN)))
+ 		return -EINVAL;
+ 	len1 = bulk.len;
+-	if (len1 > MAX_USBFS_MEMORY_USAGE)
++	if (len1 >= USBFS_XFER_MAX)
+ 		return -EINVAL;
+ 	ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb));
+ 	if (ret)
+@@ -1227,7 +1245,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 		return -EINVAL;
+ 	}
+ 
+-	if (uurb->buffer_length > MAX_USBFS_MEMORY_USAGE) {
++	if (uurb->buffer_length >= USBFS_XFER_MAX) {
+ 		ret = -EINVAL;
+ 		goto error;
+ 	}

commit add1aaeabe6b08ed26381a2a06e505b2f09c3ba5
+Author: Alan Stern 
+Date:   Thu Nov 17 16:41:25 2011 -0500
+
+    USB: change the memory limits in usbfs URB submission
+    
+    For a long time people have complained about the limitations imposed
+    by usbfs.  URBs coming from userspace are not allowed to have transfer
+    buffers larger than a more-or-less arbitrary maximum.
+    
+    While it is generally a good idea to avoid large transfer buffers
+    (because the data has to be bounced to/from a contiguous kernel-space
+    buffer), it's not the kernel's job to enforce such limits.  Programs
+    should be allowed to submit URBs as large as they like; if there isn't
+    sufficient contiguous memory available then the submission will fail
+    with a simple ENOMEM error.
+    
+    On the other hand, we would like to prevent programs from submitting a
+    lot of small URBs and using up all the DMA-able kernel memory.  To
+    that end, this patch (as1497) replaces the old limits on individual
+    transfer buffers with a single global limit on the total amount of
+    memory in use by usbfs.  The global limit is set to 16 MB as a nice
+    compromise value: not too big, but large enough to hold about 300 ms
+    of data for high-speed transfers.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index e8ade68f64e2..b69768b7d226 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -86,6 +86,7 @@ struct async {
+ 	void __user *userbuffer;
+ 	void __user *userurb;
+ 	struct urb *urb;
++	unsigned int mem_usage;
+ 	int status;
+ 	u32 secid;
+ 	u8 bulk_addr;
+@@ -108,8 +109,26 @@ enum snoop_when {
+ 
+ #define USB_DEVICE_DEV		MKDEV(USB_DEVICE_MAJOR, 0)
+ 
+-#define	MAX_USBFS_BUFFER_SIZE	16384
++/* Limit on the total amount of memory we can allocate for transfers */
++#define MAX_USBFS_MEMORY_USAGE	16777216	/* 16 MB */
+ 
++static atomic_t usbfs_memory_usage;	/* Total memory currently allocated */
++
++/* Check whether it's okay to allocate more memory for a transfer */
++static int usbfs_increase_memory_usage(unsigned amount)
++{
++	atomic_add(amount, &usbfs_memory_usage);
++	if (atomic_read(&usbfs_memory_usage) <= MAX_USBFS_MEMORY_USAGE)
++		return 0;
++	atomic_sub(amount, &usbfs_memory_usage);
++	return -ENOMEM;
++}
++
++/* Memory for a transfer is being deallocated */
++static void usbfs_decrease_memory_usage(unsigned amount)
++{
++	atomic_sub(amount, &usbfs_memory_usage);
++}
+ 
+ static int connected(struct dev_state *ps)
+ {
+@@ -253,6 +272,7 @@ static void free_async(struct async *as)
+ 	kfree(as->urb->transfer_buffer);
+ 	kfree(as->urb->setup_packet);
+ 	usb_free_urb(as->urb);
++	usbfs_decrease_memory_usage(as->mem_usage);
+ 	kfree(as);
+ }
+ 
+@@ -792,9 +812,15 @@ static int proc_control(struct dev_state *ps, void __user *arg)
+ 	wLength = ctrl.wLength;		/* To suppress 64k PAGE_SIZE warning */
+ 	if (wLength > PAGE_SIZE)
+ 		return -EINVAL;
++	ret = usbfs_increase_memory_usage(PAGE_SIZE + sizeof(struct urb) +
++			sizeof(struct usb_ctrlrequest));
++	if (ret)
++		return ret;
+ 	tbuf = (unsigned char *)__get_free_page(GFP_KERNEL);
+-	if (!tbuf)
+-		return -ENOMEM;
++	if (!tbuf) {
++		ret = -ENOMEM;
++		goto done;
++	}
+ 	tmo = ctrl.timeout;
+ 	snoop(&dev->dev, "control urb: bRequestType=%02x "
+ 		"bRequest=%02x wValue=%04x "
+@@ -852,6 +878,8 @@ static int proc_control(struct dev_state *ps, void __user *arg)
+ 	ret = i;
+  done:
+ 	free_page((unsigned long) tbuf);
++	usbfs_decrease_memory_usage(PAGE_SIZE + sizeof(struct urb) +
++			sizeof(struct usb_ctrlrequest));
+ 	return ret;
+ }
+ 
+@@ -879,10 +907,15 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
+ 	if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN)))
+ 		return -EINVAL;
+ 	len1 = bulk.len;
+-	if (len1 > MAX_USBFS_BUFFER_SIZE)
++	if (len1 > MAX_USBFS_MEMORY_USAGE)
+ 		return -EINVAL;
+-	if (!(tbuf = kmalloc(len1, GFP_KERNEL)))
+-		return -ENOMEM;
++	ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb));
++	if (ret)
++		return ret;
++	if (!(tbuf = kmalloc(len1, GFP_KERNEL))) {
++		ret = -ENOMEM;
++		goto done;
++	}
+ 	tmo = bulk.timeout;
+ 	if (bulk.ep & 0x80) {
+ 		if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) {
+@@ -919,6 +952,7 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
+ 	ret = (i < 0 ? i : len2);
+  done:
+ 	kfree(tbuf);
++	usbfs_decrease_memory_usage(len1 + sizeof(struct urb));
+ 	return ret;
+ }
+ 
+@@ -1097,14 +1131,14 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 	}
+ 	if (!ep)
+ 		return -ENOENT;
++
++	u = 0;
+ 	switch(uurb->type) {
+ 	case USBDEVFS_URB_TYPE_CONTROL:
+ 		if (!usb_endpoint_xfer_control(&ep->desc))
+ 			return -EINVAL;
+-		/* min 8 byte setup packet,
+-		 * max 8 byte setup plus an arbitrary data stage */
+-		if (uurb->buffer_length < 8 ||
+-		    uurb->buffer_length > (8 + MAX_USBFS_BUFFER_SIZE))
++		/* min 8 byte setup packet */
++		if (uurb->buffer_length < 8)
+ 			return -EINVAL;
+ 		dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
+ 		if (!dr)
+@@ -1138,6 +1172,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 			__le16_to_cpup(&dr->wValue),
+ 			__le16_to_cpup(&dr->wIndex),
+ 			__le16_to_cpup(&dr->wLength));
++		u = sizeof(struct usb_ctrlrequest);
+ 		break;
+ 
+ 	case USBDEVFS_URB_TYPE_BULK:
+@@ -1151,8 +1186,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 			goto interrupt_urb;
+ 		}
+ 		uurb->number_of_packets = 0;
+-		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
+-			return -EINVAL;
+ 		break;
+ 
+ 	case USBDEVFS_URB_TYPE_INTERRUPT:
+@@ -1160,8 +1193,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 			return -EINVAL;
+  interrupt_urb:
+ 		uurb->number_of_packets = 0;
+-		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
+-			return -EINVAL;
+ 		break;
+ 
+ 	case USBDEVFS_URB_TYPE_ISO:
+@@ -1188,17 +1219,18 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 			}
+ 			totlen += isopkt[u].length;
+ 		}
+-		/* 3072 * 64 microframes */
+-		if (totlen > 196608) {
+-			ret = -EINVAL;
+-			goto error;
+-		}
++		u *= sizeof(struct usb_iso_packet_descriptor);
+ 		uurb->buffer_length = totlen;
+ 		break;
+ 
+ 	default:
+ 		return -EINVAL;
+ 	}
++
++	if (uurb->buffer_length > MAX_USBFS_MEMORY_USAGE) {
++		ret = -EINVAL;
++		goto error;
++	}
+ 	if (uurb->buffer_length > 0 &&
+ 			!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
+ 				uurb->buffer, uurb->buffer_length)) {
+@@ -1210,6 +1242,12 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 		ret = -ENOMEM;
+ 		goto error;
+ 	}
++	u += sizeof(struct async) + sizeof(struct urb) + uurb->buffer_length;
++	ret = usbfs_increase_memory_usage(u);
++	if (ret)
++		goto error;
++	as->mem_usage = u;
++
+ 	if (uurb->buffer_length > 0) {
+ 		as->urb->transfer_buffer = kmalloc(uurb->buffer_length,
+ 				GFP_KERNEL);

commit 52fb743d3aa7ee27a4f3182816aa02dc3e513d9d
+Author: Alan Stern 
+Date:   Thu Nov 17 16:41:14 2011 -0500
+
+    USB: unify some error pathways in usbfs
+    
+    This patch (as1496) unifies the error-return pathways of several
+    functions in the usbfs driver.  This is not a very important change by
+    itself; it merely prepares the way for the next patch in this series.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index e3beaf229ee3..e8ade68f64e2 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -806,8 +806,8 @@ static int proc_control(struct dev_state *ps, void __user *arg)
+ 	if (ctrl.bRequestType & 0x80) {
+ 		if (ctrl.wLength && !access_ok(VERIFY_WRITE, ctrl.data,
+ 					       ctrl.wLength)) {
+-			free_page((unsigned long)tbuf);
+-			return -EINVAL;
++			ret = -EINVAL;
++			goto done;
+ 		}
+ 		pipe = usb_rcvctrlpipe(dev, 0);
+ 		snoop_urb(dev, NULL, pipe, ctrl.wLength, tmo, SUBMIT, NULL, 0);
+@@ -821,15 +821,15 @@ static int proc_control(struct dev_state *ps, void __user *arg)
+ 			  tbuf, max(i, 0));
+ 		if ((i > 0) && ctrl.wLength) {
+ 			if (copy_to_user(ctrl.data, tbuf, i)) {
+-				free_page((unsigned long)tbuf);
+-				return -EFAULT;
++				ret = -EFAULT;
++				goto done;
+ 			}
+ 		}
+ 	} else {
+ 		if (ctrl.wLength) {
+ 			if (copy_from_user(tbuf, ctrl.data, ctrl.wLength)) {
+-				free_page((unsigned long)tbuf);
+-				return -EFAULT;
++				ret = -EFAULT;
++				goto done;
+ 			}
+ 		}
+ 		pipe = usb_sndctrlpipe(dev, 0);
+@@ -843,14 +843,16 @@ static int proc_control(struct dev_state *ps, void __user *arg)
+ 		usb_lock_device(dev);
+ 		snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE, NULL, 0);
+ 	}
+-	free_page((unsigned long)tbuf);
+ 	if (i < 0 && i != -EPIPE) {
+ 		dev_printk(KERN_DEBUG, &dev->dev, "usbfs: USBDEVFS_CONTROL "
+ 			   "failed cmd %s rqt %u rq %u len %u ret %d\n",
+ 			   current->comm, ctrl.bRequestType, ctrl.bRequest,
+ 			   ctrl.wLength, i);
+ 	}
+-	return i;
++	ret = i;
++ done:
++	free_page((unsigned long) tbuf);
++	return ret;
+ }
+ 
+ static int proc_bulk(struct dev_state *ps, void __user *arg)
+@@ -884,8 +886,8 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
+ 	tmo = bulk.timeout;
+ 	if (bulk.ep & 0x80) {
+ 		if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) {
+-			kfree(tbuf);
+-			return -EINVAL;
++			ret = -EINVAL;
++			goto done;
+ 		}
+ 		snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, NULL, 0);
+ 
+@@ -896,15 +898,15 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
+ 
+ 		if (!i && len2) {
+ 			if (copy_to_user(bulk.data, tbuf, len2)) {
+-				kfree(tbuf);
+-				return -EFAULT;
++				ret = -EFAULT;
++				goto done;
+ 			}
+ 		}
+ 	} else {
+ 		if (len1) {
+ 			if (copy_from_user(tbuf, bulk.data, len1)) {
+-				kfree(tbuf);
+-				return -EFAULT;
++				ret = -EFAULT;
++				goto done;
+ 			}
+ 		}
+ 		snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, tbuf, len1);
+@@ -914,10 +916,10 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
+ 		usb_lock_device(dev);
+ 		snoop_urb(dev, NULL, pipe, len2, i, COMPLETE, NULL, 0);
+ 	}
++	ret = (i < 0 ? i : len2);
++ done:
+ 	kfree(tbuf);
+-	if (i < 0)
+-		return i;
+-	return len2;
++	return ret;
+ }
+ 
+ static int proc_resetep(struct dev_state *ps, void __user *arg)
+@@ -1062,7 +1064,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ {
+ 	struct usbdevfs_iso_packet_desc *isopkt = NULL;
+ 	struct usb_host_endpoint *ep;
+-	struct async *as;
++	struct async *as = NULL;
+ 	struct usb_ctrlrequest *dr = NULL;
+ 	unsigned int u, totlen, isofrmlen;
+ 	int ret, ifnum = -1;
+@@ -1108,19 +1110,17 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 		if (!dr)
+ 			return -ENOMEM;
+ 		if (copy_from_user(dr, uurb->buffer, 8)) {
+-			kfree(dr);
+-			return -EFAULT;
++			ret = -EFAULT;
++			goto error;
+ 		}
+ 		if (uurb->buffer_length < (le16_to_cpup(&dr->wLength) + 8)) {
+-			kfree(dr);
+-			return -EINVAL;
++			ret = -EINVAL;
++			goto error;
+ 		}
+ 		ret = check_ctrlrecip(ps, dr->bRequestType, dr->bRequest,
+ 				      le16_to_cpup(&dr->wIndex));
+-		if (ret) {
+-			kfree(dr);
+-			return ret;
+-		}
++		if (ret)
++			goto error;
+ 		uurb->number_of_packets = 0;
+ 		uurb->buffer_length = le16_to_cpup(&dr->wLength);
+ 		uurb->buffer += 8;
+@@ -1176,22 +1176,22 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 		if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
+ 			return -ENOMEM;
+ 		if (copy_from_user(isopkt, iso_frame_desc, isofrmlen)) {
+-			kfree(isopkt);
+-			return -EFAULT;
++			ret = -EFAULT;
++			goto error;
+ 		}
+ 		for (totlen = u = 0; u < uurb->number_of_packets; u++) {
+ 			/* arbitrary limit,
+ 			 * sufficient for USB 2.0 high-bandwidth iso */
+ 			if (isopkt[u].length > 8192) {
+-				kfree(isopkt);
+-				return -EINVAL;
++				ret = -EINVAL;
++				goto error;
+ 			}
+ 			totlen += isopkt[u].length;
+ 		}
+ 		/* 3072 * 64 microframes */
+ 		if (totlen > 196608) {
+-			kfree(isopkt);
+-			return -EINVAL;
++			ret = -EINVAL;
++			goto error;
+ 		}
+ 		uurb->buffer_length = totlen;
+ 		break;
+@@ -1202,24 +1202,20 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 	if (uurb->buffer_length > 0 &&
+ 			!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
+ 				uurb->buffer, uurb->buffer_length)) {
+-		kfree(isopkt);
+-		kfree(dr);
+-		return -EFAULT;
++		ret = -EFAULT;
++		goto error;
+ 	}
+ 	as = alloc_async(uurb->number_of_packets);
+ 	if (!as) {
+-		kfree(isopkt);
+-		kfree(dr);
+-		return -ENOMEM;
++		ret = -ENOMEM;
++		goto error;
+ 	}
+ 	if (uurb->buffer_length > 0) {
+ 		as->urb->transfer_buffer = kmalloc(uurb->buffer_length,
+ 				GFP_KERNEL);
+ 		if (!as->urb->transfer_buffer) {
+-			kfree(isopkt);
+-			kfree(dr);
+-			free_async(as);
+-			return -ENOMEM;
++			ret = -ENOMEM;
++			goto error;
+ 		}
+ 		/* Isochronous input data may end up being discontiguous
+ 		 * if some of the packets are short.  Clear the buffer so
+@@ -1253,6 +1249,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 
+ 	as->urb->transfer_buffer_length = uurb->buffer_length;
+ 	as->urb->setup_packet = (unsigned char *)dr;
++	dr = NULL;
+ 	as->urb->start_frame = uurb->start_frame;
+ 	as->urb->number_of_packets = uurb->number_of_packets;
+ 	if (uurb->type == USBDEVFS_URB_TYPE_ISO ||
+@@ -1268,6 +1265,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 		totlen += isopkt[u].length;
+ 	}
+ 	kfree(isopkt);
++	isopkt = NULL;
+ 	as->ps = ps;
+ 	as->userurb = arg;
+ 	if (is_in && uurb->buffer_length > 0)
+@@ -1282,8 +1280,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 	if (!is_in && uurb->buffer_length > 0) {
+ 		if (copy_from_user(as->urb->transfer_buffer, uurb->buffer,
+ 				uurb->buffer_length)) {
+-			free_async(as);
+-			return -EFAULT;
++			ret = -EFAULT;
++			goto error;
+ 		}
+ 	}
+ 	snoop_urb(ps->dev, as->userurb, as->urb->pipe,
+@@ -1329,10 +1327,16 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 		snoop_urb(ps->dev, as->userurb, as->urb->pipe,
+ 				0, ret, COMPLETE, NULL, 0);
+ 		async_removepending(as);
+-		free_async(as);
+-		return ret;
++		goto error;
+ 	}
+ 	return 0;
++
++ error:
++	kfree(isopkt);
++	kfree(dr);
++	if (as)
++		free_async(as);
++	return ret;
+ }
+ 
+ static int proc_submiturb(struct dev_state *ps, void __user *arg)

commit 86dc243cb2ddecb6984401463ebb0963ceff3cdc
+Author: Alan Stern 
+Date:   Thu Nov 17 16:42:24 2011 -0500
+
+    USB: remove homegrown UTF conversion routine for gadgets
+    
+    This patch (as1502) removes the UTF8-to-UTF16 conversion routine in
+    the USB gadget library and replaces it with a call to the equivalent
+    function in the NLS library.
+    
+    The only downside worth noting is that the NLS library routine
+    requires the output buffer to be 16-bit aligned.  This is always true
+    in the gadget code, because the output buffer is always a
+    usb_request buffer being used to send a string descriptor.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
+index b21cd376c11a..a11dbc85d08b 100644
+--- a/drivers/usb/gadget/Kconfig
++++ b/drivers/usb/gadget/Kconfig
+@@ -15,6 +15,7 @@
+ 
+ menuconfig USB_GADGET
+ 	tristate "USB Gadget Support"
++	select NLS
+ 	help
+ 	   USB is a master/slave protocol, organized with one master
+ 	   host (such as a PC) controlling up to 127 peripheral devices.
+diff --git a/drivers/usb/gadget/usbstring.c b/drivers/usb/gadget/usbstring.c
+index 58c4d37d312a..4d25b9009edf 100644
+--- a/drivers/usb/gadget/usbstring.c
++++ b/drivers/usb/gadget/usbstring.c
+@@ -13,82 +13,17 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ #include 
+ 
+-#include 
+-
+-
+-static int utf8_to_utf16le(const char *s, __le16 *cp, unsigned len)
+-{
+-	int	count = 0;
+-	u8	c;
+-	u16	uchar;
+-
+-	/* this insists on correct encodings, though not minimal ones.
+-	 * BUT it currently rejects legit 4-byte UTF-8 code points,
+-	 * which need surrogate pairs.  (Unicode 3.1 can use them.)
+-	 */
+-	while (len != 0 && (c = (u8) *s++) != 0) {
+-		if (unlikely(c & 0x80)) {
+-			// 2-byte sequence:
+-			// 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
+-			if ((c & 0xe0) == 0xc0) {
+-				uchar = (c & 0x1f) << 6;
+-
+-				c = (u8) *s++;
+-				if ((c & 0xc0) != 0x80)
+-					goto fail;
+-				c &= 0x3f;
+-				uchar |= c;
+-
+-			// 3-byte sequence (most CJKV characters):
+-			// zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
+-			} else if ((c & 0xf0) == 0xe0) {
+-				uchar = (c & 0x0f) << 12;
+-
+-				c = (u8) *s++;
+-				if ((c & 0xc0) != 0x80)
+-					goto fail;
+-				c &= 0x3f;
+-				uchar |= c << 6;
+-
+-				c = (u8) *s++;
+-				if ((c & 0xc0) != 0x80)
+-					goto fail;
+-				c &= 0x3f;
+-				uchar |= c;
+-
+-				/* no bogus surrogates */
+-				if (0xd800 <= uchar && uchar <= 0xdfff)
+-					goto fail;
+-
+-			// 4-byte sequence (surrogate pairs, currently rare):
+-			// 11101110wwwwzzzzyy + 110111yyyyxxxxxx
+-			//     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
+-			// (uuuuu = wwww + 1)
+-			// FIXME accept the surrogate code points (only)
+-
+-			} else
+-				goto fail;
+-		} else
+-			uchar = c;
+-		put_unaligned_le16(uchar, cp++);
+-		count++;
+-		len--;
+-	}
+-	return count;
+-fail:
+-	return -1;
+-}
+-
+ 
+ /**
+  * usb_gadget_get_string - fill out a string descriptor 
+  * @table: of c strings encoded using UTF-8
+  * @id: string id, from low byte of wValue in get string descriptor
+- * @buf: at least 256 bytes
++ * @buf: at least 256 bytes, must be 16-bit aligned
+  *
+  * Finds the UTF-8 string matching the ID, and converts it into a
+  * string descriptor in utf16-le.
+@@ -125,8 +60,8 @@ usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf)
+ 
+ 	/* string descriptors have length, tag, then UTF16-LE text */
+ 	len = min ((size_t) 126, strlen (s->s));
+-	memset (buf + 2, 0, 2 * len);	/* zero all the bytes */
+-	len = utf8_to_utf16le(s->s, (__le16 *)&buf[2], len);
++	len = utf8s_to_utf16s(s->s, len, UTF16_LITTLE_ENDIAN,
++			(wchar_t *) &buf[2], 126);
+ 	if (len < 0)
+ 		return -EINVAL;
+ 	buf [0] = (len + 1) * 2;

commit 0720a06a7518c9d0c0125bd5d1f3b6264c55c3dd
+Author: Alan Stern 
+Date:   Thu Nov 17 16:42:19 2011 -0500
+
+    NLS: improve UTF8 -> UTF16 string conversion routine
+    
+    The utf8s_to_utf16s conversion routine needs to be improved.  Unlike
+    its utf16s_to_utf8s sibling, it doesn't accept arguments specifying
+    the maximum length of the output buffer or the endianness of its
+    16-bit output.
+    
+    This patch (as1501) adds the two missing arguments, and adjusts the
+    only two places in the kernel where the function is called.  A
+    follow-on patch will add a third caller that does utilize the new
+    capabilities.
+    
+    The two conversion routines are still annoyingly inconsistent in the
+    way they handle invalid byte combinations.  But that's a subject for a
+    different patch.
+    
+    Signed-off-by: Alan Stern 
+    CC: Clemens Ladisch 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
+index 89f52440fcf4..0e8343f585bb 100644
+--- a/drivers/hv/hv_kvp.c
++++ b/drivers/hv/hv_kvp.c
+@@ -212,11 +212,13 @@ kvp_respond_to_host(char *key, char *value, int error)
+ 	 * The windows host expects the key/value pair to be encoded
+ 	 * in utf16.
+ 	 */
+-	keylen = utf8s_to_utf16s(key_name, strlen(key_name),
+-				(wchar_t *)kvp_data->data.key);
++	keylen = utf8s_to_utf16s(key_name, strlen(key_name), UTF16_HOST_ENDIAN,
++				(wchar_t *) kvp_data->data.key,
++				HV_KVP_EXCHANGE_MAX_KEY_SIZE / 2);
+ 	kvp_data->data.key_size = 2*(keylen + 1); /* utf16 encoding */
+-	valuelen = utf8s_to_utf16s(value, strlen(value),
+-				(wchar_t *)kvp_data->data.value);
++	valuelen = utf8s_to_utf16s(value, strlen(value), UTF16_HOST_ENDIAN,
++				(wchar_t *) kvp_data->data.value,
++				HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2);
+ 	kvp_data->data.value_size = 2*(valuelen + 1); /* utf16 encoding */
+ 
+ 	kvp_data->data.value_type = REG_SZ; /* all our values are strings */
+diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
+index a87a65663c25..c25cf151b84b 100644
+--- a/fs/fat/namei_vfat.c
++++ b/fs/fat/namei_vfat.c
+@@ -512,7 +512,8 @@ xlate_to_uni(const unsigned char *name, int len, unsigned char *outname,
+ 	int charlen;
+ 
+ 	if (utf8) {
+-		*outlen = utf8s_to_utf16s(name, len, (wchar_t *)outname);
++		*outlen = utf8s_to_utf16s(name, len, UTF16_HOST_ENDIAN,
++				(wchar_t *) outname, FAT_LFN_LEN + 2);
+ 		if (*outlen < 0)
+ 			return *outlen;
+ 		else if (*outlen > FAT_LFN_LEN)
+diff --git a/fs/nls/nls_base.c b/fs/nls/nls_base.c
+index 44a88a9fa2c8..0eb059ec6f28 100644
+--- a/fs/nls/nls_base.c
++++ b/fs/nls/nls_base.c
+@@ -114,34 +114,57 @@ int utf32_to_utf8(unicode_t u, u8 *s, int maxlen)
+ }
+ EXPORT_SYMBOL(utf32_to_utf8);
+ 
+-int utf8s_to_utf16s(const u8 *s, int len, wchar_t *pwcs)
++static inline void put_utf16(wchar_t *s, unsigned c, enum utf16_endian endian)
++{
++	switch (endian) {
++	default:
++		*s = (wchar_t) c;
++		break;
++	case UTF16_LITTLE_ENDIAN:
++		*s = __cpu_to_le16(c);
++		break;
++	case UTF16_BIG_ENDIAN:
++		*s = __cpu_to_be16(c);
++		break;
++	}
++}
++
++int utf8s_to_utf16s(const u8 *s, int len, enum utf16_endian endian,
++		wchar_t *pwcs, int maxlen)
+ {
+ 	u16 *op;
+ 	int size;
+ 	unicode_t u;
+ 
+ 	op = pwcs;
+-	while (*s && len > 0) {
++	while (len > 0 && maxlen > 0 && *s) {
+ 		if (*s & 0x80) {
+ 			size = utf8_to_utf32(s, len, &u);
+ 			if (size < 0)
+ 				return -EINVAL;
++			s += size;
++			len -= size;
+ 
+ 			if (u >= PLANE_SIZE) {
++				if (maxlen < 2)
++					break;
+ 				u -= PLANE_SIZE;
+-				*op++ = (wchar_t) (SURROGATE_PAIR |
+-						((u >> 10) & SURROGATE_BITS));
+-				*op++ = (wchar_t) (SURROGATE_PAIR |
++				put_utf16(op++, SURROGATE_PAIR |
++						((u >> 10) & SURROGATE_BITS),
++						endian);
++				put_utf16(op++, SURROGATE_PAIR |
+ 						SURROGATE_LOW |
+-						(u & SURROGATE_BITS));
++						(u & SURROGATE_BITS),
++						endian);
++				maxlen -= 2;
+ 			} else {
+-				*op++ = (wchar_t) u;
++				put_utf16(op++, u, endian);
++				maxlen--;
+ 			}
+-			s += size;
+-			len -= size;
+ 		} else {
+-			*op++ = *s++;
++			put_utf16(op++, *s++, endian);
+ 			len--;
++			maxlen--;
+ 		}
+ 	}
+ 	return op - pwcs;
+diff --git a/include/linux/nls.h b/include/linux/nls.h
+index d47beef08dfd..5dc635f8d79e 100644
+--- a/include/linux/nls.h
++++ b/include/linux/nls.h
+@@ -43,7 +43,7 @@ enum utf16_endian {
+ 	UTF16_BIG_ENDIAN
+ };
+ 
+-/* nls.c */
++/* nls_base.c */
+ extern int register_nls(struct nls_table *);
+ extern int unregister_nls(struct nls_table *);
+ extern struct nls_table *load_nls(char *);
+@@ -52,7 +52,8 @@ extern struct nls_table *load_nls_default(void);
+ 
+ extern int utf8_to_utf32(const u8 *s, int len, unicode_t *pu);
+ extern int utf32_to_utf8(unicode_t u, u8 *s, int maxlen);
+-extern int utf8s_to_utf16s(const u8 *s, int len, wchar_t *pwcs);
++extern int utf8s_to_utf16s(const u8 *s, int len,
++		enum utf16_endian endian, wchar_t *pwcs, int maxlen);
+ extern int utf16s_to_utf8s(const wchar_t *pwcs, int len,
+ 		enum utf16_endian endian, u8 *s, int maxlen);
+ 

commit b7463c71fbbff7111d0c879d2f64fe2b08f51848
+Author: Alan Stern 
+Date:   Thu Nov 17 16:41:56 2011 -0500
+
+    OHCI: remove uses of hcd->state
+    
+    This patch (as1500) removes all uses of the objectionable hcd->state
+    variable from the ohci-hcd family of drivers.  It is replaced by a
+    private ohci->rh_state field, just as in uhci-hcd and ehci-hcd.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
+index 9b66df8278f3..40d886adff53 100644
+--- a/drivers/usb/host/ohci-au1xxx.c
++++ b/drivers/usb/host/ohci-au1xxx.c
+@@ -173,12 +173,9 @@ static int ohci_hcd_au1xxx_drv_suspend(struct device *dev)
+ 	 * mark HW unaccessible, bail out if RH has been resumed. Use
+ 	 * the spinlock to properly synchronize with possible pending
+ 	 * RH suspend or resume activity.
+-	 *
+-	 * This is still racy as hcd->state is manipulated outside of
+-	 * any locks =P But that will be a different fix.
+ 	 */
+ 	spin_lock_irqsave(&ohci->lock, flags);
+-	if (hcd->state != HC_STATE_SUSPENDED) {
++	if (ohci->rh_state != OHCI_RH_SUSPENDED) {
+ 		rc = -EINVAL;
+ 		goto bail;
+ 	}
+diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
+index d7d34492934a..5179fcd73d8a 100644
+--- a/drivers/usb/host/ohci-dbg.c
++++ b/drivers/usb/host/ohci-dbg.c
+@@ -127,6 +127,19 @@ static char *hcfs2string (int state)
+ 	return "?";
+ }
+ 
++static const char *rh_state_string(struct ohci_hcd *ohci)
++{
++	switch (ohci->rh_state) {
++	case OHCI_RH_HALTED:
++		return "halted";
++	case OHCI_RH_SUSPENDED:
++		return "suspended";
++	case OHCI_RH_RUNNING:
++		return "running";
++	}
++	return "?";
++}
++
+ // dump control and status registers
+ static void
+ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
+@@ -136,9 +149,10 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
+ 
+ 	temp = ohci_readl (controller, ®s->revision) & 0xff;
+ 	ohci_dbg_sw (controller, next, size,
+-		"OHCI %d.%d, %s legacy support registers\n",
++		"OHCI %d.%d, %s legacy support registers, rh state %s\n",
+ 		0x03 & (temp >> 4), (temp & 0x0f),
+-		(temp & 0x0100) ? "with" : "NO");
++		(temp & 0x0100) ? "with" : "NO",
++		rh_state_string(controller));
+ 
+ 	temp = ohci_readl (controller, ®s->control);
+ 	ohci_dbg_sw (controller, next, size,
+diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
+index dc45d489d00e..3d63574d2c7e 100644
+--- a/drivers/usb/host/ohci-ep93xx.c
++++ b/drivers/usb/host/ohci-ep93xx.c
+@@ -179,8 +179,6 @@ static int ohci_hcd_ep93xx_drv_suspend(struct platform_device *pdev, pm_message_
+ 	ohci->next_statechange = jiffies;
+ 
+ 	ep93xx_stop_hc(&pdev->dev);
+-	hcd->state = HC_STATE_SUSPENDED;
+-
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index 34efd479e068..03c4631dc27a 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -209,7 +209,7 @@ static int ohci_urb_enqueue (
+ 		retval = -ENODEV;
+ 		goto fail;
+ 	}
+-	if (!HC_IS_RUNNING(hcd->state)) {
++	if (ohci->rh_state != OHCI_RH_RUNNING) {
+ 		retval = -ENODEV;
+ 		goto fail;
+ 	}
+@@ -274,7 +274,7 @@ static int ohci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ 	rc = usb_hcd_check_unlink_urb(hcd, urb, status);
+ 	if (rc) {
+ 		;	/* Do nothing */
+-	} else if (HC_IS_RUNNING(hcd->state)) {
++	} else if (ohci->rh_state == OHCI_RH_RUNNING) {
+ 		urb_priv_t  *urb_priv;
+ 
+ 		/* Unless an IRQ completed the unlink while it was being
+@@ -321,7 +321,7 @@ ohci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ rescan:
+ 	spin_lock_irqsave (&ohci->lock, flags);
+ 
+-	if (!HC_IS_RUNNING (hcd->state)) {
++	if (ohci->rh_state != OHCI_RH_RUNNING) {
+ sanitize:
+ 		ed->state = ED_IDLE;
+ 		if (quirk_zfmicro(ohci) && ed->type == PIPE_INTERRUPT)
+@@ -377,6 +377,7 @@ static void ohci_usb_reset (struct ohci_hcd *ohci)
+ 	ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
+ 	ohci->hc_control &= OHCI_CTRL_RWC;
+ 	ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
++	ohci->rh_state = OHCI_RH_HALTED;
+ }
+ 
+ /* ohci_shutdown forcibly disables IRQs and DMA, helping kexec and
+@@ -503,7 +504,7 @@ static int ohci_init (struct ohci_hcd *ohci)
+ 	if (distrust_firmware)
+ 		ohci->flags |= OHCI_QUIRK_HUB_POWER;
+ 
+-	disable (ohci);
++	ohci->rh_state = OHCI_RH_HALTED;
+ 	ohci->regs = hcd->regs;
+ 
+ 	/* REVISIT this BIOS handshake is now moved into PCI "quirks", and
+@@ -578,7 +579,7 @@ static int ohci_run (struct ohci_hcd *ohci)
+ 	int			first = ohci->fminterval == 0;
+ 	struct usb_hcd		*hcd = ohci_to_hcd(ohci);
+ 
+-	disable (ohci);
++	ohci->rh_state = OHCI_RH_HALTED;
+ 
+ 	/* boot firmware should have set this up (5.1.1.3.1) */
+ 	if (first) {
+@@ -691,7 +692,7 @@ static int ohci_run (struct ohci_hcd *ohci)
+ 	ohci->hc_control &= OHCI_CTRL_RWC;
+ 	ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER;
+ 	ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
+-	hcd->state = HC_STATE_RUNNING;
++	ohci->rh_state = OHCI_RH_RUNNING;
+ 
+ 	/* wake on ConnectStatusChange, matching external hubs */
+ 	ohci_writel (ohci, RH_HS_DRWE, &ohci->regs->roothub.status);
+@@ -728,7 +729,6 @@ static int ohci_run (struct ohci_hcd *ohci)
+ 
+ 	// POTPGT delay is bits 24-31, in 2 ms units.
+ 	mdelay ((val >> 23) & 0x1fe);
+-	hcd->state = HC_STATE_RUNNING;
+ 
+ 	if (quirk_zfmicro(ohci)) {
+ 		/* Create timer to watch for bad queue state on ZF Micro */
+@@ -764,7 +764,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
+ 	 * of dead, unclocked, or unplugged (CardBus...) devices
+ 	 */
+ 	if (ints == ~(u32)0) {
+-		disable (ohci);
++		ohci->rh_state = OHCI_RH_HALTED;
+ 		ohci_dbg (ohci, "device removed!\n");
+ 		usb_hc_died(hcd);
+ 		return IRQ_HANDLED;
+@@ -774,7 +774,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
+ 	ints &= ohci_readl(ohci, ®s->intrenable);
+ 
+ 	/* interrupt for some other device? */
+-	if (ints == 0 || unlikely(hcd->state == HC_STATE_HALT))
++	if (ints == 0 || unlikely(ohci->rh_state == OHCI_RH_HALTED))
+ 		return IRQ_NOTMINE;
+ 
+ 	if (ints & OHCI_INTR_UE) {
+@@ -789,8 +789,8 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
+ 
+ 			schedule_work (&ohci->nec_work);
+ 		} else {
+-			disable (ohci);
+ 			ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n");
++			ohci->rh_state = OHCI_RH_HALTED;
+ 			usb_hc_died(hcd);
+ 		}
+ 
+@@ -874,11 +874,11 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
+ 	if ((ints & OHCI_INTR_SF) != 0
+ 			&& !ohci->ed_rm_list
+ 			&& !ohci->ed_to_check
+-			&& HC_IS_RUNNING(hcd->state))
++			&& ohci->rh_state == OHCI_RH_RUNNING)
+ 		ohci_writel (ohci, OHCI_INTR_SF, ®s->intrdisable);
+ 	spin_unlock (&ohci->lock);
+ 
+-	if (HC_IS_RUNNING(hcd->state)) {
++	if (ohci->rh_state == OHCI_RH_RUNNING) {
+ 		ohci_writel (ohci, ints, ®s->intrstatus);
+ 		ohci_writel (ohci, OHCI_INTR_MIE, ®s->intrenable);
+ 		// flush those writes
+@@ -932,7 +932,7 @@ static int ohci_restart (struct ohci_hcd *ohci)
+ 	struct urb_priv *priv;
+ 
+ 	spin_lock_irq(&ohci->lock);
+-	disable (ohci);
++	ohci->rh_state = OHCI_RH_HALTED;
+ 
+ 	/* Recycle any "live" eds/tds (and urbs). */
+ 	if (!list_empty (&ohci->pending))
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index 2f00040fc408..836772dfabd3 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -111,6 +111,7 @@ __acquires(ohci->lock)
+ 	if (!autostop) {
+ 		ohci->next_statechange = jiffies + msecs_to_jiffies (5);
+ 		ohci->autostop = 0;
++		ohci->rh_state = OHCI_RH_SUSPENDED;
+ 	}
+ 
+ done:
+@@ -140,7 +141,7 @@ __acquires(ohci->lock)
+ 
+ 	if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
+ 		/* this can happen after resuming a swsusp snapshot */
+-		if (hcd->state == HC_STATE_RESUMING) {
++		if (ohci->rh_state != OHCI_RH_RUNNING) {
+ 			ohci_dbg (ohci, "BIOS/SMM active, control %03x\n",
+ 					ohci->hc_control);
+ 			status = -EBUSY;
+@@ -274,6 +275,7 @@ __acquires(ohci->lock)
+ 		(void) ohci_readl (ohci, &ohci->regs->control);
+ 	}
+ 
++	ohci->rh_state = OHCI_RH_RUNNING;
+ 	return 0;
+ }
+ 
+@@ -336,11 +338,8 @@ static void ohci_finish_controller_resume(struct usb_hcd *hcd)
+ 	/* If needed, reinitialize and suspend the root hub */
+ 	if (need_reinit) {
+ 		spin_lock_irq(&ohci->lock);
+-		hcd->state = HC_STATE_RESUMING;
+ 		ohci_rh_resume(ohci);
+-		hcd->state = HC_STATE_QUIESCING;
+ 		ohci_rh_suspend(ohci, 0);
+-		hcd->state = HC_STATE_SUSPENDED;
+ 		spin_unlock_irq(&ohci->lock);
+ 	}
+ 
+diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
+index e4b8782cc6e2..db3968656d21 100644
+--- a/drivers/usb/host/ohci-omap.c
++++ b/drivers/usb/host/ohci-omap.c
+@@ -516,7 +516,6 @@ static int ohci_omap_suspend(struct platform_device *dev, pm_message_t message)
+ 	ohci->next_statechange = jiffies;
+ 
+ 	omap_ohci_clock_power(0);
+-	ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index ad8166c681e2..847187df50a1 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -334,12 +334,9 @@ static int ohci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+ 	 * mark HW unaccessible, bail out if RH has been resumed. Use
+ 	 * the spinlock to properly synchronize with possible pending
+ 	 * RH suspend or resume activity.
+-	 *
+-	 * This is still racy as hcd->state is manipulated outside of
+-	 * any locks =P But that will be a different fix.
+ 	 */
+ 	spin_lock_irqsave (&ohci->lock, flags);
+-	if (hcd->state != HC_STATE_SUSPENDED) {
++	if (ohci->rh_state != OHCI_RH_SUSPENDED) {
+ 		rc = -EINVAL;
+ 		goto bail;
+ 	}
+diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
+index 29dfefe1c726..6313e4439f37 100644
+--- a/drivers/usb/host/ohci-pxa27x.c
++++ b/drivers/usb/host/ohci-pxa27x.c
+@@ -502,8 +502,6 @@ static int ohci_hcd_pxa27x_drv_suspend(struct device *dev)
+ 	ohci->ohci.next_statechange = jiffies;
+ 
+ 	pxa27x_stop_hc(ohci, dev);
+-	hcd->state = HC_STATE_SUSPENDED;
+-
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
+index 15dc51ded61a..c5a1ea9145fa 100644
+--- a/drivers/usb/host/ohci-q.c
++++ b/drivers/usb/host/ohci-q.c
+@@ -912,7 +912,7 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick)
+ 		/* only take off EDs that the HC isn't using, accounting for
+ 		 * frame counter wraps and EDs with partially retired TDs
+ 		 */
+-		if (likely (HC_IS_RUNNING(ohci_to_hcd(ohci)->state))) {
++		if (likely(ohci->rh_state == OHCI_RH_RUNNING)) {
+ 			if (tick_before (tick, ed->tick)) {
+ skip_ed:
+ 				last = &ed->ed_next;
+@@ -1012,7 +1012,7 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick)
+ 
+ 		/* but if there's work queued, reschedule */
+ 		if (!list_empty (&ed->td_list)) {
+-			if (HC_IS_RUNNING(ohci_to_hcd(ohci)->state))
++			if (ohci->rh_state == OHCI_RH_RUNNING)
+ 				ed_schedule (ohci, ed);
+ 		}
+ 
+@@ -1021,9 +1021,7 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick)
+ 	}
+ 
+ 	/* maybe reenable control and bulk lists */
+-	if (HC_IS_RUNNING(ohci_to_hcd(ohci)->state)
+-			&& ohci_to_hcd(ohci)->state != HC_STATE_QUIESCING
+-			&& !ohci->ed_rm_list) {
++	if (ohci->rh_state == OHCI_RH_RUNNING && !ohci->ed_rm_list) {
+ 		u32	command = 0, control = 0;
+ 
+ 		if (ohci->ed_controltail) {
+diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c
+index afc4eb6bb9d0..84686d90805b 100644
+--- a/drivers/usb/host/ohci-sh.c
++++ b/drivers/usb/host/ohci-sh.c
+@@ -29,7 +29,6 @@ static int ohci_sh_start(struct usb_hcd *hcd)
+ 	ohci_hcd_init(ohci);
+ 	ohci_init(ohci);
+ 	ohci_run(ohci);
+-	hcd->state = HC_STATE_RUNNING;
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c
+index 968cea2b6d4e..5596ac2ba1ca 100644
+--- a/drivers/usb/host/ohci-sm501.c
++++ b/drivers/usb/host/ohci-sm501.c
+@@ -224,7 +224,6 @@ static int ohci_sm501_suspend(struct platform_device *pdev, pm_message_t msg)
+ 	ohci->next_statechange = jiffies;
+ 
+ 	sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 0);
+-	ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c
+index 69874654f3b5..95c16489e883 100644
+--- a/drivers/usb/host/ohci-spear.c
++++ b/drivers/usb/host/ohci-spear.c
+@@ -203,7 +203,6 @@ static int spear_ohci_hcd_drv_suspend(struct platform_device *dev,
+ 	ohci->next_statechange = jiffies;
+ 
+ 	spear_stop_ohci(ohci_p);
+-	ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c
+index 06331d931171..120bfe6ede38 100644
+--- a/drivers/usb/host/ohci-tmio.c
++++ b/drivers/usb/host/ohci-tmio.c
+@@ -318,9 +318,6 @@ static int ohci_hcd_tmio_drv_suspend(struct platform_device *dev, pm_message_t s
+ 		if (ret)
+ 			return ret;
+ 	}
+-
+-	hcd->state = HC_STATE_SUSPENDED;
+-
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
+index 35e5fd640ce7..3a978a2130cb 100644
+--- a/drivers/usb/host/ohci.h
++++ b/drivers/usb/host/ohci.h
+@@ -344,6 +344,12 @@ typedef struct urb_priv {
+  * a subset of what the full implementation needs. (Linus)
+  */
+ 
++enum ohci_rh_state {
++	OHCI_RH_HALTED,
++	OHCI_RH_SUSPENDED,
++	OHCI_RH_RUNNING
++};
++
+ struct ohci_hcd {
+ 	spinlock_t		lock;
+ 
+@@ -384,6 +390,7 @@ struct ohci_hcd {
+ 	/*
+ 	 * driver state
+ 	 */
++	enum ohci_rh_state	rh_state;
+ 	int			num_ports;
+ 	int			load [NUM_INTS];
+ 	u32			hc_control;	/* copy of hc control reg */
+@@ -680,11 +687,6 @@ static inline u16 ohci_hwPSW(const struct ohci_hcd *ohci,
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-static inline void disable (struct ohci_hcd *ohci)
+-{
+-	ohci_to_hcd(ohci)->state = HC_STATE_HALT;
+-}
+-
+ #define	FI			0x2edf		/* 12000 bits per frame (-1) */
+ #define	FSMP(fi)		(0x7fff & ((6 * ((fi) - 210)) / 7))
+ #define	FIT			(1 << 31)
+@@ -708,7 +710,7 @@ static inline void periodic_reinit (struct ohci_hcd *ohci)
+ #define read_roothub(hc, register, mask) ({ \
+ 	u32 temp = ohci_readl (hc, &hc->regs->roothub.register); \
+ 	if (temp == -1) \
+-		disable (hc); \
++		hc->rh_state = OHCI_RH_HALTED; \
+ 	else if (hc->flags & OHCI_QUIRK_AMD756) \
+ 		while (temp & mask) \
+ 			temp = ohci_readl (hc, &hc->regs->roothub.register); \

commit 2f640bf4c94324aeaa1b6385c10aab8c5ad1e1cf
+Author: Alan Stern 
+Date:   Tue Oct 25 10:50:58 2011 -0400
+
+    usb-storage: Accept 8020i-protocol commands longer than 12 bytes
+    
+    The 8020i protocol (also 8070i and QIC-157) uses 12-byte commands;
+    shorter commands must be padded.  Simon Detheridge reports that his
+    3-TB USB disk drive claims to use the 8020i protocol (which is
+    normally meant for ATAPI devices like CD drives), and because of its
+    large size, the disk drive requires the use of 16-byte commands.
+    However the usb_stor_pad12_command() routine in usb-storage always
+    sets the command length to 12, making the drive impossible to use.
+    
+    Since the SFF-8020i specification allows for 16-byte commands in
+    future extensions, we may as well accept them.  This patch (as1490)
+    changes usb_stor_pad12_command() to leave commands larger than 12
+    bytes alone rather than truncating them.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Simon Detheridge 
+    CC: Matthew Dharm 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
+index 93c1a4d86f51..82dd834709c7 100644
+--- a/drivers/usb/storage/protocol.c
++++ b/drivers/usb/storage/protocol.c
+@@ -59,7 +59,9 @@
+ 
+ void usb_stor_pad12_command(struct scsi_cmnd *srb, struct us_data *us)
+ {
+-	/* Pad the SCSI command with zeros out to 12 bytes
++	/*
++	 * Pad the SCSI command with zeros out to 12 bytes.  If the
++	 * command already is 12 bytes or longer, leave it alone.
+ 	 *
+ 	 * NOTE: This only works because a scsi_cmnd struct field contains
+ 	 * a unsigned char cmnd[16], so we know we have storage available
+@@ -67,9 +69,6 @@ void usb_stor_pad12_command(struct scsi_cmnd *srb, struct us_data *us)
+ 	for (; srb->cmd_len<12; srb->cmd_len++)
+ 		srb->cmnd[srb->cmd_len] = 0;
+ 
+-	/* set command length to 12 bytes */
+-	srb->cmd_len = 12;
+-
+ 	/* send the command to the transport layer */
+ 	usb_stor_invoke_transport(srb, us);
+ }

commit 968b822c0023861ef6e4e15bb68582b36e89ad29
+Author: Alan Stern 
+Date:   Thu Nov 3 12:03:38 2011 -0400
+
+    USB: Remove the SAW_IRQ hcd flag
+    
+    The HCD_FLAG_SAW_IRQ flag was introduced in order to catch IRQ routing
+    errors: If an URB was unlinked and the host controller hadn't gotten
+    any IRQs, it seemed likely that the IRQs were directed to the wrong
+    vector.
+    
+    This warning hasn't come up in many years, as far as I know; interrupt
+    routing now seems to be well under control.  Therefore there's no
+    reason to keep the flag around any more.  This patch (as1495) finally
+    removes it.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/c67x00/c67x00-hcd.c b/drivers/usb/c67x00/c67x00-hcd.c
+index d3e1356d091e..75e47b860a53 100644
+--- a/drivers/usb/c67x00/c67x00-hcd.c
++++ b/drivers/usb/c67x00/c67x00-hcd.c
+@@ -271,7 +271,6 @@ static void c67x00_hcd_irq(struct c67x00_sie *sie, u16 int_status, u16 msg)
+ 	if (int_status & SOFEOP_FLG(sie->sie_num)) {
+ 		c67x00_ll_usb_clear_status(sie, SOF_EOP_IRQ_FLG);
+ 		c67x00_sched_kick(c67x00);
+-		set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+ 	}
+ }
+ 
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index a004db35f6d0..d136b8f4c8a7 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -453,10 +453,6 @@ static int resume_common(struct device *dev, int event)
+ 
+ 	pci_set_master(pci_dev);
+ 
+-	clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+-	if (hcd->shared_hcd)
+-		clear_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags);
+-
+ 	if (hcd->driver->pci_resume && !HCD_DEAD(hcd)) {
+ 		if (event != PM_EVENT_AUTO_RESUME)
+ 			wait_for_companions(pci_dev, hcd);
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 13222d352a61..43a89e4ba928 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1168,20 +1168,6 @@ int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
+ 	if (urb->unlinked)
+ 		return -EBUSY;
+ 	urb->unlinked = status;
+-
+-	/* IRQ setup can easily be broken so that USB controllers
+-	 * never get completion IRQs ... maybe even the ones we need to
+-	 * finish unlinking the initial failed usb_set_address()
+-	 * or device descriptor fetch.
+-	 */
+-	if (!HCD_SAW_IRQ(hcd) && !is_root_hub(urb->dev)) {
+-		dev_warn(hcd->self.controller, "Unlink after no-IRQ?  "
+-			"Controller is probably using the wrong IRQ.\n");
+-		set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+-		if (hcd->shared_hcd)
+-			set_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags);
+-	}
+-
+ 	return 0;
+ }
+ EXPORT_SYMBOL_GPL(usb_hcd_check_unlink_urb);
+@@ -2148,16 +2134,12 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)
+ 	 */
+ 	local_irq_save(flags);
+ 
+-	if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd))) {
++	if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd)))
+ 		rc = IRQ_NONE;
+-	} else if (hcd->driver->irq(hcd) == IRQ_NONE) {
++	else if (hcd->driver->irq(hcd) == IRQ_NONE)
+ 		rc = IRQ_NONE;
+-	} else {
+-		set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+-		if (hcd->shared_hcd)
+-			set_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags);
++	else
+ 		rc = IRQ_HANDLED;
+-	}
+ 
+ 	local_irq_restore(flags);
+ 	return rc;
+diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c
+index 9bfac657572e..565d79f06e6f 100644
+--- a/drivers/usb/host/hwa-hc.c
++++ b/drivers/usb/host/hwa-hc.c
+@@ -776,7 +776,6 @@ static int hwahc_probe(struct usb_interface *usb_iface,
+ 		goto error_alloc;
+ 	}
+ 	usb_hcd->wireless = 1;
+-	set_bit(HCD_FLAG_SAW_IRQ, &usb_hcd->flags);
+ 	wusbhc = usb_hcd_to_wusbhc(usb_hcd);
+ 	hwahc = container_of(wusbhc, struct hwahc, wusbhc);
+ 	hwahc_init(hwahc);
+diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
+index 940321b3ec68..2f8c17381c6c 100644
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -2389,17 +2389,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
+ 
+ irqreturn_t xhci_msi_irq(int irq, struct usb_hcd *hcd)
+ {
+-	irqreturn_t ret;
+-	struct xhci_hcd *xhci;
+-
+-	xhci = hcd_to_xhci(hcd);
+-	set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+-	if (xhci->shared_hcd)
+-		set_bit(HCD_FLAG_SAW_IRQ, &xhci->shared_hcd->flags);
+-
+-	ret = xhci_irq(hcd);
+-
+-	return ret;
++	return xhci_irq(hcd);
+ }
+ 
+ /****		Endpoint Ring Operations	****/
+diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
+index 20a28731c338..12044c473c38 100644
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -661,7 +661,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
+ 
+ 		handled = IRQ_HANDLED;
+ 		musb->is_active = 1;
+-		set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+ 
+ 		musb->ep0_stage = MUSB_EP0_START;
+ 
+diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
+index 03354d557b79..b2f62f3a32af 100644
+--- a/include/linux/usb/hcd.h
++++ b/include/linux/usb/hcd.h
+@@ -99,7 +99,6 @@ struct usb_hcd {
+ 	 */
+ 	unsigned long		flags;
+ #define HCD_FLAG_HW_ACCESSIBLE		0	/* at full power */
+-#define HCD_FLAG_SAW_IRQ		1
+ #define HCD_FLAG_POLL_RH		2	/* poll for rh status? */
+ #define HCD_FLAG_POLL_PENDING		3	/* status has changed? */
+ #define HCD_FLAG_WAKEUP_PENDING		4	/* root hub is resuming? */
+@@ -110,7 +109,6 @@ struct usb_hcd {
+ 	 * be slightly faster than test_bit().
+ 	 */
+ #define HCD_HW_ACCESSIBLE(hcd)	((hcd)->flags & (1U << HCD_FLAG_HW_ACCESSIBLE))
+-#define HCD_SAW_IRQ(hcd)	((hcd)->flags & (1U << HCD_FLAG_SAW_IRQ))
+ #define HCD_POLL_RH(hcd)	((hcd)->flags & (1U << HCD_FLAG_POLL_RH))
+ #define HCD_POLL_PENDING(hcd)	((hcd)->flags & (1U << HCD_FLAG_POLL_PENDING))
+ #define HCD_WAKEUP_PENDING(hcd)	((hcd)->flags & (1U << HCD_FLAG_WAKEUP_PENDING))

commit f69e3120df82391a0ee8118e0a156239a06b2afb
+Author: Alan Stern 
+Date:   Thu Nov 3 11:37:10 2011 -0400
+
+    USB: XHCI: resume root hubs when the controller resumes
+    
+    This patch (as1494) fixes a problem in xhci-hcd's resume routine.
+    When the controller is runtime-resumed, this can only mean that one of
+    the two root hubs has made a wakeup request and therefore needs to be
+    resumed as well.  Rather than try to determine which root hub requires
+    attention (which might be difficult in the case where a new
+    non-SuperSpeed device has been plugged in), the patch simply resumes
+    both root hubs.
+    
+    Without this change, there is a race: The controller might be put back
+    to sleep before it can activate its IRQ line, and the wakeup condition
+    might never get handled.
+    
+    The patch also simplifies the logic in xhci_resume a little, combining
+    some repeated flag settings into a single pair of statements.
+    
+    Signed-off-by: Alan Stern 
+    CC: Sarah Sharp 
+    Cc: stable 
+    Tested-by: Linus Torvalds 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
+index 747c5ead922b..aa94c0195791 100644
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -799,7 +799,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
+ 	u32			command, temp = 0;
+ 	struct usb_hcd		*hcd = xhci_to_hcd(xhci);
+ 	struct usb_hcd		*secondary_hcd;
+-	int			retval;
++	int			retval = 0;
+ 
+ 	/* Wait a bit if either of the roothubs need to settle from the
+ 	 * transition into bus suspend.
+@@ -809,6 +809,9 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
+ 				xhci->bus_state[1].next_statechange))
+ 		msleep(100);
+ 
++	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
++	set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
++
+ 	spin_lock_irq(&xhci->lock);
+ 	if (xhci->quirks & XHCI_RESET_ON_RESUME)
+ 		hibernated = true;
+@@ -878,20 +881,13 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
+ 			return retval;
+ 		xhci_dbg(xhci, "Start the primary HCD\n");
+ 		retval = xhci_run(hcd->primary_hcd);
+-		if (retval)
+-			goto failed_restart;
+-
+-		xhci_dbg(xhci, "Start the secondary HCD\n");
+-		retval = xhci_run(secondary_hcd);
+ 		if (!retval) {
+-			set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+-			set_bit(HCD_FLAG_HW_ACCESSIBLE,
+-					&xhci->shared_hcd->flags);
++			xhci_dbg(xhci, "Start the secondary HCD\n");
++			retval = xhci_run(secondary_hcd);
+ 		}
+-failed_restart:
+ 		hcd->state = HC_STATE_SUSPENDED;
+ 		xhci->shared_hcd->state = HC_STATE_SUSPENDED;
+-		return retval;
++		goto done;
+ 	}
+ 
+ 	/* step 4: set Run/Stop bit */
+@@ -910,11 +906,14 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
+ 	 * Running endpoints by ringing their doorbells
+ 	 */
+ 
+-	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+-	set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
+-
+ 	spin_unlock_irq(&xhci->lock);
+-	return 0;
++
++ done:
++	if (retval == 0) {
++		usb_hcd_resume_root_hub(hcd);
++		usb_hcd_resume_root_hub(xhci->shared_hcd);
++	}
++	return retval;
+ }
+ #endif	/* CONFIG_PM */
+ 

commit 97ff22ee3b4cb3a334f7385e269773141aed702f
+Author: Alan Stern 
+Date:   Thu Oct 27 11:20:21 2011 -0400
+
+    USB: workaround for bug in old version of GCC
+    
+    This patch (as1491) works around a bug in GCC-3.4.6, which is still
+    supposed to be supported.  The number of microseconds in the udelay()
+    call in quirk_usb_disable_ehci() is fixed at 100, but the compiler
+    doesn't understand this and generates a link-time error.  So we
+    replace the otherwise unused variable "delta" with a simple constant
+    100.  This same pattern is already used in other delay loops in that
+    source file.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Konrad Rzepecki 
+    Tested-by: Konrad Rzepecki 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
+index 27a3dec32fa2..c7fd6ce11904 100644
+--- a/drivers/usb/host/pci-quirks.c
++++ b/drivers/usb/host/pci-quirks.c
+@@ -627,7 +627,7 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
+ 	void __iomem *base, *op_reg_base;
+ 	u32	hcc_params, cap, val;
+ 	u8	offset, cap_length;
+-	int	wait_time, delta, count = 256/4;
++	int	wait_time, count = 256/4;
+ 
+ 	if (!mmio_resource_enabled(pdev, 0))
+ 		return;
+@@ -673,11 +673,10 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
+ 		writel(val, op_reg_base + EHCI_USBCMD);
+ 
+ 		wait_time = 2000;
+-		delta = 100;
+ 		do {
+ 			writel(0x3f, op_reg_base + EHCI_USBSTS);
+-			udelay(delta);
+-			wait_time -= delta;
++			udelay(100);
++			wait_time -= 100;
+ 			val = readl(op_reg_base + EHCI_USBSTS);
+ 			if ((val == ~(u32)0) || (val & EHCI_USBSTS_HALTED)) {
+ 				break;

commit b2c0a863e14676fa5760c6d828fd373288e2f64a
+Author: Alan Stern 
+Date:   Fri Nov 4 00:52:46 2011 +0100
+
+    USB: Update last_busy time after autosuspend fails
+    
+    Originally, the runtime PM core would send an idle notification
+    whenever a suspend attempt failed.  The idle callback routine could
+    then schedule a delayed suspend for some time later.
+    
+    However this behavior was changed by commit
+    f71648d73c1650b8b4aceb3856bebbde6daa3b86 (PM / Runtime: Remove idle
+    notification after failing suspend).  No notifications were sent, and
+    there was no clear mechanism to retry failed suspends.
+    
+    This caused problems for the usbhid driver, because it fails
+    autosuspend attempts as long as a key is being held down.  A companion
+    patch changes the PM core's behavior, but we also need to change the
+    USB core.  In particular, this patch (as1493) updates the device's
+    last_busy time when an autosuspend fails, so that the PM core will
+    retry the autosuspend in the future when the delay time expires
+    again.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Henrik Rydberg 
+    Cc: 
+    Acked-by: Greg Kroah-Hartman 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 3b029a0a4787..c2c0ae57e7ff 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1667,6 +1667,11 @@ int usb_runtime_suspend(struct device *dev)
+ 		return -EAGAIN;
+ 
+ 	status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
++
++	/* Allow a retry if autosuspend failed temporarily */
++	if (status == -EAGAIN || status == -EBUSY)
++		usb_mark_last_busy(udev);
++
+ 	/* The PM core reacts badly unless the return code is 0,
+ 	 * -EAGAIN, or -EBUSY, so always return -EBUSY on an error.
+ 	 */

commit 886486b792e4f6f96d4fbe8ec5bf20811cab7d6a
+Author: Alan Stern 
+Date:   Thu Nov 3 23:39:18 2011 +0100
+
+    PM / Runtime: Automatically retry failed autosuspends
+    
+    Originally, the runtime PM core would send an idle notification
+    whenever a suspend attempt failed.  The idle callback routine could
+    then schedule a delayed suspend for some time later.
+    
+    However this behavior was changed by commit
+    f71648d73c1650b8b4aceb3856bebbde6daa3b86 (PM / Runtime: Remove idle
+    notification after failing suspend).  No notifications were sent, and
+    there was no clear mechanism to retry failed suspends.
+    
+    This caused problems for the usbhid driver, because it fails
+    autosuspend attempts as long as a key is being held down.  Therefore
+    this patch (as1492) adds a mechanism for retrying failed
+    autosuspends.  If the callback routine updates the last_busy field so
+    that the next autosuspend expiration time is in the future, the
+    autosuspend will automatically be rescheduled.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Henrik Rydberg 
+    Cc: 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt
+index 0e856088db7c..5336149f831b 100644
+--- a/Documentation/power/runtime_pm.txt
++++ b/Documentation/power/runtime_pm.txt
+@@ -789,6 +789,16 @@ will behave normally, not taking the autosuspend delay into account.
+ Similarly, if the power.use_autosuspend field isn't set then the autosuspend
+ helper functions will behave just like the non-autosuspend counterparts.
+ 
++Under some circumstances a driver or subsystem may want to prevent a device
++from autosuspending immediately, even though the usage counter is zero and the
++autosuspend delay time has expired.  If the ->runtime_suspend() callback
++returns -EAGAIN or -EBUSY, and if the next autosuspend delay expiration time is
++in the future (as it normally would be if the callback invoked
++pm_runtime_mark_last_busy()), the PM core will automatically reschedule the
++autosuspend.  The ->runtime_suspend() callback can't do this rescheduling
++itself because no suspend requests of any kind are accepted while the device is
++suspending (i.e., while the callback is running).
++
+ The implementation is well suited for asynchronous use in interrupt contexts.
+ However such use inevitably involves races, because the PM core can't
+ synchronize ->runtime_suspend() callbacks with the arrival of I/O requests.
+diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
+index 18ef87e525fa..124dbf60c9bf 100644
+--- a/drivers/base/power/runtime.c
++++ b/drivers/base/power/runtime.c
+@@ -293,6 +293,9 @@ static int rpm_callback(int (*cb)(struct device *), struct device *dev)
+  * the callback was running then carry it out, otherwise send an idle
+  * notification for its parent (if the suspend succeeded and both
+  * ignore_children of parent->power and irq_safe of dev->power are not set).
++ * If ->runtime_suspend failed with -EAGAIN or -EBUSY, and if the RPM_AUTO
++ * flag is set and the next autosuspend-delay expiration time is in the
++ * future, schedule another autosuspend attempt.
+  *
+  * This function must be called under dev->power.lock with interrupts disabled.
+  */
+@@ -413,10 +416,21 @@ static int rpm_suspend(struct device *dev, int rpmflags)
+ 	if (retval) {
+ 		__update_runtime_status(dev, RPM_ACTIVE);
+ 		dev->power.deferred_resume = false;
+-		if (retval == -EAGAIN || retval == -EBUSY)
++		if (retval == -EAGAIN || retval == -EBUSY) {
+ 			dev->power.runtime_error = 0;
+-		else
++
++			/*
++			 * If the callback routine failed an autosuspend, and
++			 * if the last_busy time has been updated so that there
++			 * is a new autosuspend expiration time, automatically
++			 * reschedule another autosuspend.
++			 */
++			if ((rpmflags & RPM_AUTO) &&
++			    pm_runtime_autosuspend_expiration(dev) != 0)
++				goto repeat;
++		} else {
+ 			pm_runtime_cancel_pending(dev);
++		}
+ 		wake_up_all(&dev->power.wait_queue);
+ 		goto out;
+ 	}

commit 68aa95d5d4de31c9348c1628ffa85c805305ebc5
+Author: Alan Stern 
+Date:   Wed Oct 12 10:39:14 2011 -0400
+
+    EHCI: workaround for MosChip controller bug
+    
+    This patch (as1489) works around a hardware bug in MosChip EHCI
+    controllers.  Evidently when one of these controllers increments the
+    frame-index register, it changes the three low-order bits (the
+    microframe counter) before changing the higher order bits (the frame
+    counter).  If the register is read at just the wrong time, the value
+    obtained is too low by 8.
+    
+    When the appropriate quirk flag is set, we work around this problem by
+    reading the frame-index register a second time if the first value's
+    three low-order bits are all 0.  This gives the hardware a chance to
+    finish updating the register, yielding the correct value.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Jason N Pitt 
+    CC: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
+index 9952505d2357..d6d74d2e09f4 100644
+--- a/drivers/usb/host/ehci-dbg.c
++++ b/drivers/usb/host/ehci-dbg.c
+@@ -821,7 +821,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
+ 	next += temp;
+ 
+ 	temp = scnprintf (next, size, "uframe %04x\n",
+-			ehci_readl(ehci, &ehci->regs->frame_index));
++			ehci_read_frame_index(ehci));
+ 	size -= temp;
+ 	next += temp;
+ 
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 05abbcd93cf4..59e81615e09c 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1195,8 +1195,7 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ static int ehci_get_frame (struct usb_hcd *hcd)
+ {
+ 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+-	return (ehci_readl(ehci, &ehci->regs->frame_index) >> 3) %
+-		ehci->periodic_size;
++	return (ehci_read_frame_index(ehci) >> 3) % ehci->periodic_size;
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index 8311de7c0a75..f4b627d343ac 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -224,6 +224,11 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 			pci_dev_put(p_smbus);
+ 		}
+ 		break;
++	case PCI_VENDOR_ID_NETMOS:
++		/* MosChip frame-index-register bug */
++		ehci_info(ehci, "applying MosChip frame-index workaround\n");
++		ehci->frame_index_bug = 1;
++		break;
+ 	}
+ 
+ 	/* optional debug port, normally in the first BAR */
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 488151bb45cb..2e829fae6482 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -36,6 +36,27 @@
+ 
+ static int ehci_get_frame (struct usb_hcd *hcd);
+ 
++#ifdef CONFIG_PCI
++
++static unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
++{
++	unsigned uf;
++
++	/*
++	 * The MosChip MCS9990 controller updates its microframe counter
++	 * a little before the frame counter, and occasionally we will read
++	 * the invalid intermediate value.  Avoid problems by checking the
++	 * microframe number (the low-order 3 bits); if they are 0 then
++	 * re-read the register to get the correct value.
++	 */
++	uf = ehci_readl(ehci, &ehci->regs->frame_index);
++	if (unlikely(ehci->frame_index_bug && ((uf & 7) == 0)))
++		uf = ehci_readl(ehci, &ehci->regs->frame_index);
++	return uf;
++}
++
++#endif
++
+ /*-------------------------------------------------------------------------*/
+ 
+ /*
+@@ -481,7 +502,7 @@ static int enable_periodic (struct ehci_hcd *ehci)
+ 	/* posted write ... PSS happens later */
+ 
+ 	/* make sure ehci_work scans these */
+-	ehci->next_uframe = ehci_readl(ehci, &ehci->regs->frame_index)
++	ehci->next_uframe = ehci_read_frame_index(ehci)
+ 		% (ehci->periodic_size << 3);
+ 	if (unlikely(ehci->broken_periodic))
+ 		ehci->last_periodic_enable = ktime_get_real();
+@@ -1408,7 +1429,7 @@ iso_stream_schedule (
+ 		goto fail;
+ 	}
+ 
+-	now = ehci_readl(ehci, &ehci->regs->frame_index) & (mod - 1);
++	now = ehci_read_frame_index(ehci) & (mod - 1);
+ 
+ 	/* Typical case: reuse current schedule, stream is still active.
+ 	 * Hopefully there are no gaps from the host falling behind
+@@ -2275,7 +2296,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 	 */
+ 	now_uframe = ehci->next_uframe;
+ 	if (ehci->rh_state == EHCI_RH_RUNNING) {
+-		clock = ehci_readl(ehci, &ehci->regs->frame_index);
++		clock = ehci_read_frame_index(ehci);
+ 		clock_frame = (clock >> 3) & (ehci->periodic_size - 1);
+ 	} else  {
+ 		clock = now_uframe + mod - 1;
+@@ -2454,8 +2475,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 					|| ehci->periodic_sched == 0)
+ 				break;
+ 			ehci->next_uframe = now_uframe;
+-			now = ehci_readl(ehci, &ehci->regs->frame_index) &
+-					(mod - 1);
++			now = ehci_read_frame_index(ehci) & (mod - 1);
+ 			if (now_uframe == now)
+ 				break;
+ 
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index c161d97de7dd..0a5fda73b3f2 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -146,6 +146,7 @@ struct ehci_hcd {			/* one per controller */
+ 	unsigned		fs_i_thresh:1;	/* Intel iso scheduling */
+ 	unsigned		use_dummy_qh:1;	/* AMD Frame List table quirk*/
+ 	unsigned		has_synopsys_hc_bug:1; /* Synopsys HC */
++	unsigned		frame_index_bug:1; /* MosChip (AKA NetMos) */
+ 
+ 	/* required for usb32 quirk */
+ 	#define OHCI_CTRL_HCFS          (3 << 6)
+@@ -747,6 +748,22 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++#ifdef CONFIG_PCI
++
++/* For working around the MosChip frame-index-register bug */
++static unsigned ehci_read_frame_index(struct ehci_hcd *ehci);
++
++#else
++
++static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
++{
++	return ehci_readl(ehci, &ehci->regs->frame_index);
++}
++
++#endif
++
++/*-------------------------------------------------------------------------*/
++
+ #ifndef DEBUG
+ #define STUB_DEBUG_FILES
+ #endif	/* DEBUG */

commit 8f88893c05f2f677f18f2ce5591b4bed5d4a7535
+Author: Alan Stern 
+Date:   Mon Sep 26 17:38:50 2011 +0200
+
+    PM: Update the policy on default wakeup settings
+    
+    This patch (as1485) documents a change to the kernel's default wakeup
+    policy.  Devices that forward wakeup requests between buses should be
+    enabled for wakeup by default.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt
+index 3384d5996be2..29b7a9817f5a 100644
+--- a/Documentation/power/devices.txt
++++ b/Documentation/power/devices.txt
+@@ -152,7 +152,9 @@ try to use its wakeup mechanism.  device_set_wakeup_enable() affects this flag;
+ for the most part drivers should not change its value.  The initial value of
+ should_wakeup is supposed to be false for the majority of devices; the major
+ exceptions are power buttons, keyboards, and Ethernet adapters whose WoL
+-(wake-on-LAN) feature has been set up with ethtool.
++(wake-on-LAN) feature has been set up with ethtool.  It should also default
++to true for devices that don't generate wakeup requests on their own but merely
++forward wakeup requests from one bus to another (like PCI bridges).
+ 
+ Whether or not a device is capable of issuing wakeup events is a hardware
+ matter, and the kernel is responsible for keeping track of it.  By contrast,
+diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
+index 84f7c7d5a098..14ee07e9cc43 100644
+--- a/drivers/base/power/wakeup.c
++++ b/drivers/base/power/wakeup.c
+@@ -276,7 +276,9 @@ EXPORT_SYMBOL_GPL(device_set_wakeup_capable);
+  *
+  * By default, most devices should leave wakeup disabled.  The exceptions are
+  * devices that everyone expects to be wakeup sources: keyboards, power buttons,
+- * possibly network interfaces, etc.
++ * possibly network interfaces, etc.  Also, devices that don't generate their
++ * own wakeup requests but merely forward requests from one bus to another
++ * (like PCI bridges) should have wakeup enabled by default.
+  */
+ int device_init_wakeup(struct device *dev, bool enable)
+ {

commit 30b1a7a32ca48fd8758f8ca44d60deebc0aa3d72
+Author: Alan Stern 
+Date:   Tue Sep 27 21:54:22 2011 +0200
+
+    USB: Add wakeup info to debugging messages
+    
+    This patch (as1487) improves the usbcore debugging output for port
+    suspend and bus suspend, by stating whether or not remote wakeup is
+    enabled.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Greg Kroah-Hartman 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index da582f4e486b..877e0e27b90a 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1959,8 +1959,9 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg)
+ 	int		status;
+ 	int		old_state = hcd->state;
+ 
+-	dev_dbg(&rhdev->dev, "bus %s%s\n",
+-			(PMSG_IS_AUTO(msg) ? "auto-" : ""), "suspend");
++	dev_dbg(&rhdev->dev, "bus %ssuspend, wakeup %d\n",
++			(PMSG_IS_AUTO(msg) ? "auto-" : ""),
++			rhdev->do_remote_wakeup);
+ 	if (HCD_DEAD(hcd)) {
+ 		dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "suspend");
+ 		return 0;
+@@ -1995,8 +1996,8 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
+ 	int		status;
+ 	int		old_state = hcd->state;
+ 
+-	dev_dbg(&rhdev->dev, "usb %s%s\n",
+-			(PMSG_IS_AUTO(msg) ? "auto-" : ""), "resume");
++	dev_dbg(&rhdev->dev, "usb %sresume\n",
++			(PMSG_IS_AUTO(msg) ? "auto-" : ""));
+ 	if (HCD_DEAD(hcd)) {
+ 		dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "resume");
+ 		return 0;
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index ee50e0bf84e8..13bc83240adb 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2324,8 +2324,6 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ 	int		port1 = udev->portnum;
+ 	int		status;
+ 
+-	// dev_dbg(hub->intfdev, "suspend port %d\n", port1);
+-
+ 	/* enable remote wakeup when appropriate; this lets the device
+ 	 * wake up the upstream hub (including maybe the root hub).
+ 	 *
+@@ -2371,8 +2369,9 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ 			status = 0;
+ 	} else {
+ 		/* device has up to 10 msec to fully suspend */
+-		dev_dbg(&udev->dev, "usb %ssuspend\n",
+-				(PMSG_IS_AUTO(msg) ? "auto-" : ""));
++		dev_dbg(&udev->dev, "usb %ssuspend, wakeup %d\n",
++				(PMSG_IS_AUTO(msg) ? "auto-" : ""),
++				udev->do_remote_wakeup);
+ 		usb_set_device_state(udev, USB_STATE_SUSPENDED);
+ 		msleep(10);
+ 	}

commit 5c12e7856d75f68c1ca8372d6cc76cdbc71763c0
+Author: Alan Stern 
+Date:   Mon Sep 26 11:25:26 2011 -0400
+
+    USB: UHCI: improve comments and logic for root-hub suspend
+    
+    This patch (as1488) improves the comments and logic in uhci-hcd's
+    suspend routine.  The existing comments are hard to understand and
+    don't give a good idea of what's really going on.
+    
+    The question of whether EGSM (Enter Global Suspend Mode) and RD
+    (enable Resume Detect interrupts) can be useful when they're not both
+    set is difficult.  The spec doesn't give any details on how they
+    interact with system wakeup, although clearly they are meant to be
+    used together.  To be safe, the patch changes the subroutine so that
+    neither bit gets set unless they both do.  There shouldn't be any
+    functional changes from this; only systems that are designed badly or
+    broken in some way need to avoid using those bits.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index fba99b120588..c8ae199cfbb8 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -294,50 +294,50 @@ __acquires(uhci->lock)
+ 	 * and that remote wakeups should be enabled.
+ 	 */
+ 	egsm_enable = USBCMD_EGSM;
+-	uhci->RD_enable = 1;
+ 	int_enable = USBINTR_RESUME;
+ 	wakeup_enable = 1;
+ 
+-	/* In auto-stop mode wakeups must always be detected, but
+-	 * Resume-Detect interrupts may be prohibited.  (In the absence
+-	 * of CONFIG_PM, they are always disallowed.)
++	/*
++	 * In auto-stop mode, we must be able to detect new connections.
++	 * The user can force us to poll by disabling remote wakeup;
++	 * otherwise we will use the EGSM/RD mechanism.
+ 	 */
+ 	if (auto_stop) {
+ 		if (!device_may_wakeup(&rhdev->dev))
+-			int_enable = 0;
++			egsm_enable = int_enable = 0;
++	}
+ 
+-	/* In bus-suspend mode wakeups may be disabled, but if they are
+-	 * allowed then so are Resume-Detect interrupts.
+-	 */
+-	} else {
+ #ifdef CONFIG_PM
++	/*
++	 * In bus-suspend mode, we use the wakeup setting specified
++	 * for the root hub.
++	 */
++	else {
+ 		if (!rhdev->do_remote_wakeup)
+ 			wakeup_enable = 0;
+-#endif
+ 	}
++#endif
+ 
+-	/* EGSM causes the root hub to echo a 'K' signal (resume) out any
+-	 * port which requests a remote wakeup.  According to the USB spec,
+-	 * every hub is supposed to do this.  But if we are ignoring
+-	 * remote-wakeup requests anyway then there's no point to it.
+-	 * We also shouldn't enable EGSM if it's broken.
+-	 */
+-	if (!wakeup_enable || global_suspend_mode_is_broken(uhci))
+-		egsm_enable = 0;
+-
+-	/* If we're ignoring wakeup events then there's no reason to
+-	 * enable Resume-Detect interrupts.  We also shouldn't enable
+-	 * them if they are broken or disallowed.
++	/*
++	 * UHCI doesn't distinguish between wakeup requests from downstream
++	 * devices and local connect/disconnect events.  There's no way to
++	 * enable one without the other; both are controlled by EGSM.  Thus
++	 * if wakeups are disallowed then EGSM must be turned off -- in which
++	 * case remote wakeup requests from downstream during system sleep
++	 * will be lost.
++	 *
++	 * In addition, if EGSM is broken then we can't use it.  Likewise,
++	 * if Resume-Detect interrupts are broken then we can't use them.
+ 	 *
+-	 * This logic may lead us to enabling RD but not EGSM.  The UHCI
+-	 * spec foolishly says that RD works only when EGSM is on, but
+-	 * there's no harm in enabling it anyway -- perhaps some chips
+-	 * will implement it!
++	 * Finally, neither EGSM nor RD is useful by itself.  Without EGSM,
++	 * the RD status bit will never get set.  Without RD, the controller
++	 * won't generate interrupts to tell the system about wakeup events.
+ 	 */
+-	if (!wakeup_enable || resume_detect_interrupts_are_broken(uhci) ||
+-			!int_enable)
+-		uhci->RD_enable = int_enable = 0;
++	if (!wakeup_enable || global_suspend_mode_is_broken(uhci) ||
++			resume_detect_interrupts_are_broken(uhci))
++		egsm_enable = int_enable = 0;
+ 
++	uhci->RD_enable = !!int_enable;
+ 	uhci_writew(uhci, int_enable, USBINTR);
+ 	uhci_writew(uhci, egsm_enable | USBCMD_CF, USBCMD);
+ 	mb();
+@@ -364,10 +364,12 @@ __acquires(uhci->lock)
+ 	uhci->rh_state = new_state;
+ 	uhci->is_stopped = UHCI_IS_STOPPED;
+ 
+-	/* If interrupts don't work and remote wakeup is enabled then
+-	 * the suspended root hub needs to be polled.
++	/*
++	 * If remote wakeup is enabled but either EGSM or RD interrupts
++	 * doesn't work, then we won't get an interrupt when a wakeup event
++	 * occurs.  Thus the suspended root hub needs to be polled.
+ 	 */
+-	if (!int_enable && wakeup_enable)
++	if (wakeup_enable && (!int_enable || !egsm_enable))
+ 		set_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags);
+ 	else
+ 		clear_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags);

commit a6eeeb9f45b5a417f574f3bc799b7122270bf59b
+Author: Alan Stern 
+Date:   Mon Sep 26 11:23:38 2011 -0400
+
+    USB: Update USB default wakeup settings
+    
+    This patch (as1486) implements the kernel's new wakeup policy for USB
+    host controllers.  Since they don't generate wakeup requests on their
+    but merely forward requests from their root hubs toward the CPU, they
+    should be enabled for wakeup by default.
+    
+    Also, to be compliant with both the old and new policies, root hubs
+    should not be enabled for remote wakeup by default.  Userspace must
+    enable it explicitly if it is desired.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 73cbbd85219f..100d4b002642 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -2429,7 +2429,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ 	 * but drivers can override it in reset() if needed, along with
+ 	 * recording the overall controller's system wakeup capability.
+ 	 */
+-	device_init_wakeup(&rhdev->dev, 1);
++	device_set_wakeup_capable(&rhdev->dev, 1);
+ 
+ 	/* HCD_FLAG_RH_RUNNING doesn't matter until the root hub is
+ 	 * registered.  But since the controller can die at any time,
+@@ -2478,6 +2478,13 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ 	}
+ 	if (hcd->uses_new_polling && HCD_POLL_RH(hcd))
+ 		usb_hcd_poll_rh_status(hcd);
++
++	/*
++	 * Host controllers don't generate their own wakeup requests;
++	 * they only forward requests from the root hub.  Therefore
++	 * controllers should always be enabled for remote wakeup.
++	 */
++	device_wakeup_enable(hcd->self.controller);
+ 	return retval;
+ 
+ error_create_attr_group:

commit 25aa55488c3644b19e33ba79c564191b8e33f477
+Author: Alan Stern 
+Date:   Wed Sep 14 12:33:16 2011 -0400
+
+    USB: document ehci-hcd's "companion" sysfs attribute
+    
+    This patch (as1484) adds documentation for ehci-hcd's "companion"
+    sysfs attribute, which was added to the kernel over four years ago but
+    never documented.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/ABI/testing/sysfs-bus-pci-drivers-ehci_hcd b/Documentation/ABI/testing/sysfs-bus-pci-drivers-ehci_hcd
+new file mode 100644
+index 000000000000..60c60fa624b2
+--- /dev/null
++++ b/Documentation/ABI/testing/sysfs-bus-pci-drivers-ehci_hcd
+@@ -0,0 +1,46 @@
++What:		/sys/bus/pci/drivers/ehci_hcd/.../companion
++		/sys/bus/usb/devices/usbN/../companion
++Date:		January 2007
++KernelVersion:	2.6.21
++Contact:	Alan Stern 
++Description:
++		PCI-based EHCI USB controllers (i.e., high-speed USB-2.0
++		controllers) are often implemented along with a set of
++		"companion" full/low-speed USB-1.1 controllers.  When a
++		high-speed device is plugged in, the connection is routed
++		to the EHCI controller; when a full- or low-speed device
++		is plugged in, the connection is routed to the companion
++		controller.
++
++		Sometimes you want to force a high-speed device to connect
++		at full speed, which can be accomplished by forcing the
++		connection to be routed to the companion controller.
++		That's what this file does.  Writing a port number to the
++		file causes connections on that port to be routed to the
++		companion controller, and writing the negative of a port
++		number returns the port to normal operation.
++
++		For example: To force the high-speed device attached to
++		port 4 on bus 2 to run at full speed:
++
++			echo 4 >/sys/bus/usb/devices/usb2/../companion
++
++		To return the port to high-speed operation:
++
++			echo -4 >/sys/bus/usb/devices/usb2/../companion
++
++		Reading the file gives the list of ports currently forced
++		to the companion controller.
++
++		Note: Some EHCI controllers do not have companions; they
++		may contain an internal "transaction translator" or they
++		may be attached directly to a "rate-matching hub".  This
++		mechanism will not work with such controllers.  Also, it
++		cannot be used to force a port on a high-speed hub to
++		connect at full speed.
++
++		Note: When this file was first added, it appeared in a
++		different sysfs directory.  The location given above is
++		correct for 2.6.35 (and probably several earlier kernel
++		versions as well).
++

commit 04eee25b1d754a837360504b7af426d1f86ffeb7
+Author: Alan Stern 
+Date:   Thu Aug 18 14:29:00 2011 -0400
+
+    USB: gadget: storage: remove alignment assumption
+    
+    This patch (as1481) fixes a problem affecting g_file_storage and
+    g_mass_storage when running at SuperSpeed.  The two drivers currently
+    assume that the bulk-out maxpacket size can evenly divide the SCSI
+    block size, which is 512 bytes.  But SuperSpeed bulk endpoints have a
+    maxpacket size of 1024, so the assumption is no longer true.
+    
+    This patch removes that assumption from the drivers, by getting rid of
+    a small optimization (they try to align VFS reads and writes on page
+    cache boundaries).  If a command's starting logical block address is
+    512 bytes below the end of a page, it's not okay to issue a USB
+    command for just those 512 bytes when the maxpacket size is 1024 -- it
+    would result in either babble (for an OUT transfer) or a short packet
+    (for an IN transfer).
+    
+    Also, for backward compatibility, the test for writes extending beyond
+    the end of the backing storage has to be changed.  If the host tries
+    to do this, we should accept the data that fits in the backing storage
+    and ignore the rest.  Because the storage's end may not align with a
+    USB packet boundary, this means we may have to accept a USB OUT
+    transfer that extends beyond the end of the storage and then write out
+    only the part of the data that fits.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Michal Nazarewicz 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
+index 1cdb1fa1b158..4306a8339487 100644
+--- a/drivers/usb/gadget/f_mass_storage.c
++++ b/drivers/usb/gadget/f_mass_storage.c
+@@ -744,7 +744,6 @@ static int do_read(struct fsg_common *common)
+ 	u32			amount_left;
+ 	loff_t			file_offset, file_offset_tmp;
+ 	unsigned int		amount;
+-	unsigned int		partial_page;
+ 	ssize_t			nread;
+ 
+ 	/*
+@@ -783,18 +782,10 @@ static int do_read(struct fsg_common *common)
+ 		 * Try to read the remaining amount.
+ 		 * But don't read more than the buffer size.
+ 		 * And don't try to read past the end of the file.
+-		 * Finally, if we're not at a page boundary, don't read past
+-		 *	the next page.
+-		 * If this means reading 0 then we were asked to read past
+-		 *	the end of file.
+ 		 */
+ 		amount = min(amount_left, FSG_BUFLEN);
+ 		amount = min((loff_t)amount,
+ 			     curlun->file_length - file_offset);
+-		partial_page = file_offset & (PAGE_CACHE_SIZE - 1);
+-		if (partial_page > 0)
+-			amount = min(amount, (unsigned int)PAGE_CACHE_SIZE -
+-					     partial_page);
+ 
+ 		/* Wait for the next buffer to become available */
+ 		bh = common->next_buffhd_to_fill;
+@@ -840,6 +831,12 @@ static int do_read(struct fsg_common *common)
+ 		file_offset  += nread;
+ 		amount_left  -= nread;
+ 		common->residue -= nread;
++
++		/*
++		 * Except at the end of the transfer, nread will be
++		 * equal to the buffer size, which is divisible by the
++		 * bulk-in maxpacket size.
++		 */
+ 		bh->inreq->length = nread;
+ 		bh->state = BUF_STATE_FULL;
+ 
+@@ -878,7 +875,6 @@ static int do_write(struct fsg_common *common)
+ 	u32			amount_left_to_req, amount_left_to_write;
+ 	loff_t			usb_offset, file_offset, file_offset_tmp;
+ 	unsigned int		amount;
+-	unsigned int		partial_page;
+ 	ssize_t			nwritten;
+ 	int			rc;
+ 
+@@ -934,24 +930,13 @@ static int do_write(struct fsg_common *common)
+ 
+ 			/*
+ 			 * Figure out how much we want to get:
+-			 * Try to get the remaining amount.
+-			 * But don't get more than the buffer size.
+-			 * And don't try to go past the end of the file.
+-			 * If we're not at a page boundary,
+-			 *	don't go past the next page.
+-			 * If this means getting 0, then we were asked
+-			 *	to write past the end of file.
+-			 * Finally, round down to a block boundary.
++			 * Try to get the remaining amount,
++			 * but not more than the buffer size.
+ 			 */
+ 			amount = min(amount_left_to_req, FSG_BUFLEN);
+-			amount = min((loff_t)amount,
+-				     curlun->file_length - usb_offset);
+-			partial_page = usb_offset & (PAGE_CACHE_SIZE - 1);
+-			if (partial_page > 0)
+-				amount = min(amount,
+-	(unsigned int)PAGE_CACHE_SIZE - partial_page);
+-
+-			if (amount == 0) {
++
++			/* Beyond the end of the backing file? */
++			if (usb_offset >= curlun->file_length) {
+ 				get_some_more = 0;
+ 				curlun->sense_data =
+ 					SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
+@@ -960,16 +945,6 @@ static int do_write(struct fsg_common *common)
+ 				curlun->info_valid = 1;
+ 				continue;
+ 			}
+-			amount = round_down(amount, curlun->blksize);
+-			if (amount == 0) {
+-
+-				/*
+-				 * Why were we were asked to transfer a
+-				 * partial block?
+-				 */
+-				get_some_more = 0;
+-				continue;
+-			}
+ 
+ 			/* Get the next buffer */
+ 			usb_offset += amount;
+@@ -979,8 +954,9 @@ static int do_write(struct fsg_common *common)
+ 				get_some_more = 0;
+ 
+ 			/*
+-			 * amount is always divisible by 512, hence by
+-			 * the bulk-out maxpacket size
++			 * Except at the end of the transfer, amount will be
++			 * equal to the buffer size, which is divisible by
++			 * the bulk-out maxpacket size.
+ 			 */
+ 			bh->outreq->length = amount;
+ 			bh->bulk_out_intended_length = amount;
+@@ -1019,6 +995,11 @@ static int do_write(struct fsg_common *common)
+ 				amount = curlun->file_length - file_offset;
+ 			}
+ 
++			/* Don't write a partial block */
++			amount = round_down(amount, curlun->blksize);
++			if (amount == 0)
++				goto empty_write;
++
+ 			/* Perform the write */
+ 			file_offset_tmp = file_offset;
+ 			nwritten = vfs_write(curlun->filp,
+@@ -1051,6 +1032,7 @@ static int do_write(struct fsg_common *common)
+ 				break;
+ 			}
+ 
++ empty_write:
+ 			/* Did the host decide to stop early? */
+ 			if (bh->outreq->actual != bh->outreq->length) {
+ 				common->short_packet_received = 1;
+@@ -1151,8 +1133,6 @@ static int do_verify(struct fsg_common *common)
+ 		 * Try to read the remaining amount, but not more than
+ 		 * the buffer size.
+ 		 * And don't try to read past the end of the file.
+-		 * If this means reading 0 then we were asked to read
+-		 * past the end of file.
+ 		 */
+ 		amount = min(amount_left, FSG_BUFLEN);
+ 		amount = min((loff_t)amount,
+@@ -1628,7 +1608,8 @@ static int throw_away_data(struct fsg_common *common)
+ 			amount = min(common->usb_amount_left, FSG_BUFLEN);
+ 
+ 			/*
+-			 * amount is always divisible by 512, hence by
++			 * Except at the end of the transfer, amount will be
++			 * equal to the buffer size, which is divisible by
+ 			 * the bulk-out maxpacket size.
+ 			 */
+ 			bh->outreq->length = amount;
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index 59d97750cecd..c6f96a2b3110 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -1135,7 +1135,6 @@ static int do_read(struct fsg_dev *fsg)
+ 	u32			amount_left;
+ 	loff_t			file_offset, file_offset_tmp;
+ 	unsigned int		amount;
+-	unsigned int		partial_page;
+ 	ssize_t			nread;
+ 
+ 	/* Get the starting Logical Block Address and check that it's
+@@ -1170,17 +1169,10 @@ static int do_read(struct fsg_dev *fsg)
+ 		 * Try to read the remaining amount.
+ 		 * But don't read more than the buffer size.
+ 		 * And don't try to read past the end of the file.
+-		 * Finally, if we're not at a page boundary, don't read past
+-		 *	the next page.
+-		 * If this means reading 0 then we were asked to read past
+-		 *	the end of file. */
++		 */
+ 		amount = min((unsigned int) amount_left, mod_data.buflen);
+ 		amount = min((loff_t) amount,
+ 				curlun->file_length - file_offset);
+-		partial_page = file_offset & (PAGE_CACHE_SIZE - 1);
+-		if (partial_page > 0)
+-			amount = min(amount, (unsigned int) PAGE_CACHE_SIZE -
+-					partial_page);
+ 
+ 		/* Wait for the next buffer to become available */
+ 		bh = fsg->next_buffhd_to_fill;
+@@ -1225,6 +1217,11 @@ static int do_read(struct fsg_dev *fsg)
+ 		file_offset  += nread;
+ 		amount_left  -= nread;
+ 		fsg->residue -= nread;
++
++		/* Except at the end of the transfer, nread will be
++		 * equal to the buffer size, which is divisible by the
++		 * bulk-in maxpacket size.
++		 */
+ 		bh->inreq->length = nread;
+ 		bh->state = BUF_STATE_FULL;
+ 
+@@ -1261,7 +1258,6 @@ static int do_write(struct fsg_dev *fsg)
+ 	u32			amount_left_to_req, amount_left_to_write;
+ 	loff_t			usb_offset, file_offset, file_offset_tmp;
+ 	unsigned int		amount;
+-	unsigned int		partial_page;
+ 	ssize_t			nwritten;
+ 	int			rc;
+ 
+@@ -1312,23 +1308,13 @@ static int do_write(struct fsg_dev *fsg)
+ 		if (bh->state == BUF_STATE_EMPTY && get_some_more) {
+ 
+ 			/* Figure out how much we want to get:
+-			 * Try to get the remaining amount.
+-			 * But don't get more than the buffer size.
+-			 * And don't try to go past the end of the file.
+-			 * If we're not at a page boundary,
+-			 *	don't go past the next page.
+-			 * If this means getting 0, then we were asked
+-			 *	to write past the end of file.
+-			 * Finally, round down to a block boundary. */
++			 * Try to get the remaining amount,
++			 * but not more than the buffer size.
++			 */
+ 			amount = min(amount_left_to_req, mod_data.buflen);
+-			amount = min((loff_t) amount, curlun->file_length -
+-					usb_offset);
+-			partial_page = usb_offset & (PAGE_CACHE_SIZE - 1);
+-			if (partial_page > 0)
+-				amount = min(amount,
+-	(unsigned int) PAGE_CACHE_SIZE - partial_page);
+-
+-			if (amount == 0) {
++
++			/* Beyond the end of the backing file? */
++			if (usb_offset >= curlun->file_length) {
+ 				get_some_more = 0;
+ 				curlun->sense_data =
+ 					SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
+@@ -1336,14 +1322,6 @@ static int do_write(struct fsg_dev *fsg)
+ 				curlun->info_valid = 1;
+ 				continue;
+ 			}
+-			amount = round_down(amount, curlun->blksize);
+-			if (amount == 0) {
+-
+-				/* Why were we were asked to transfer a
+-				 * partial block? */
+-				get_some_more = 0;
+-				continue;
+-			}
+ 
+ 			/* Get the next buffer */
+ 			usb_offset += amount;
+@@ -1352,8 +1330,10 @@ static int do_write(struct fsg_dev *fsg)
+ 			if (amount_left_to_req == 0)
+ 				get_some_more = 0;
+ 
+-			/* amount is always divisible by 512, hence by
+-			 * the bulk-out maxpacket size */
++			/* Except at the end of the transfer, amount will be
++			 * equal to the buffer size, which is divisible by
++			 * the bulk-out maxpacket size.
++			 */
+ 			bh->outreq->length = bh->bulk_out_intended_length =
+ 					amount;
+ 			bh->outreq->short_not_ok = 1;
+@@ -1389,6 +1369,11 @@ static int do_write(struct fsg_dev *fsg)
+ 				amount = curlun->file_length - file_offset;
+ 			}
+ 
++			/* Don't write a partial block */
++			amount = round_down(amount, curlun->blksize);
++			if (amount == 0)
++				goto empty_write;
++
+ 			/* Perform the write */
+ 			file_offset_tmp = file_offset;
+ 			nwritten = vfs_write(curlun->filp,
+@@ -1421,6 +1406,7 @@ static int do_write(struct fsg_dev *fsg)
+ 				break;
+ 			}
+ 
++ empty_write:
+ 			/* Did the host decide to stop early? */
+ 			if (bh->outreq->actual != bh->outreq->length) {
+ 				fsg->short_packet_received = 1;
+@@ -1517,8 +1503,7 @@ static int do_verify(struct fsg_dev *fsg)
+ 		 * Try to read the remaining amount, but not more than
+ 		 * the buffer size.
+ 		 * And don't try to read past the end of the file.
+-		 * If this means reading 0 then we were asked to read
+-		 * past the end of file. */
++		 */
+ 		amount = min((unsigned int) amount_left, mod_data.buflen);
+ 		amount = min((loff_t) amount,
+ 				curlun->file_length - file_offset);
+@@ -1981,8 +1966,10 @@ static int throw_away_data(struct fsg_dev *fsg)
+ 			amount = min(fsg->usb_amount_left,
+ 					(u32) mod_data.buflen);
+ 
+-			/* amount is always divisible by 512, hence by
+-			 * the bulk-out maxpacket size */
++			/* Except at the end of the transfer, amount will be
++			 * equal to the buffer size, which is divisible by
++			 * the bulk-out maxpacket size.
++			 */
+ 			bh->outreq->length = bh->bulk_out_intended_length =
+ 					amount;
+ 			bh->outreq->short_not_ok = 1;

commit e8799906045302776b35b66b16495c575db3b69c
+Author: Alan Stern 
+Date:   Thu Aug 18 16:31:30 2011 -0400
+
+    USB: EHCI: remove usages of hcd->state
+    
+    This patch (as1483) improves the ehci-hcd driver family by getting rid
+    of the reliance on the hcd->state variable.  It has no clear owner and
+    it isn't protected by the usual HCD locks.  In its place, the patch
+    adds a new, private ehci->rh_state field to record the state of the
+    root hub.
+    
+    Along the way, the patch removes a couple of lines containing
+    redundant assignments to the state variable.  Also, the QUIESCING
+    state simply gets changed to the RUNNING state, because the driver
+    doesn't make any distinction between them.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Jingoo Han 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
+index 42ae57409908..4363fea85151 100644
+--- a/drivers/usb/host/ehci-au1xxx.c
++++ b/drivers/usb/host/ehci-au1xxx.c
+@@ -293,7 +293,7 @@ static int ehci_hcd_au1xxx_drv_resume(struct device *dev)
+ 	/* here we "know" root ports should always stay powered */
+ 	ehci_port_power(ehci, 1);
+ 
+-	hcd->state = HC_STATE_SUSPENDED;
++	ehci->rh_state = EHCI_RH_SUSPENDED;
+ 
+ 	return 0;
+ }
+diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
+index 40a844c1dbb4..9952505d2357 100644
+--- a/drivers/usb/host/ehci-dbg.c
++++ b/drivers/usb/host/ehci-dbg.c
+@@ -697,6 +697,19 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
+ }
+ #undef DBG_SCHED_LIMIT
+ 
++static const char *rh_state_string(struct ehci_hcd *ehci)
++{
++	switch (ehci->rh_state) {
++	case EHCI_RH_HALTED:
++		return "halted";
++	case EHCI_RH_SUSPENDED:
++		return "suspended";
++	case EHCI_RH_RUNNING:
++		return "running";
++	}
++	return "?";
++}
++
+ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
+ {
+ 	struct usb_hcd		*hcd;
+@@ -730,11 +743,11 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
+ 	temp = scnprintf (next, size,
+ 		"bus %s, device %s\n"
+ 		"%s\n"
+-		"EHCI %x.%02x, hcd state %d\n",
++		"EHCI %x.%02x, rh state %s\n",
+ 		hcd->self.controller->bus->name,
+ 		dev_name(hcd->self.controller),
+ 		hcd->product_desc,
+-		i >> 8, i & 0x0ff, hcd->state);
++		i >> 8, i & 0x0ff, rh_state_string(ehci));
+ 	size -= temp;
+ 	next += temp;
+ 
+diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
+index 34a3140d1e5f..3bf9f16b4fd8 100644
+--- a/drivers/usb/host/ehci-fsl.c
++++ b/drivers/usb/host/ehci-fsl.c
+@@ -392,7 +392,7 @@ static int ehci_fsl_mpc512x_drv_suspend(struct device *dev)
+ 
+ 	dev_dbg(dev, "suspending...\n");
+ 
+-	hcd->state = HC_STATE_SUSPENDED;
++	ehci->rh_state = EHCI_RH_SUSPENDED;
+ 	dev->power.power_state = PMSG_SUSPEND;
+ 
+ 	/* ignore non-host interrupts */
+@@ -481,7 +481,7 @@ static int ehci_fsl_mpc512x_drv_resume(struct device *dev)
+ 	ehci_writel(ehci, pdata->pm_portsc, &ehci->regs->port_status[0]);
+ 
+ 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+-	hcd->state = HC_STATE_RUNNING;
++	ehci->rh_state = EHCI_RH_RUNNING;
+ 	dev->power.power_state = PMSG_ON;
+ 
+ 	tmp = ehci_readl(ehci, &ehci->regs->command);
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 2af3e2a89efc..8696489cde56 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -238,7 +238,7 @@ static int handshake_on_error_set_halt(struct ehci_hcd *ehci, void __iomem *ptr,
+ 	error = handshake(ehci, ptr, mask, done, usec);
+ 	if (error) {
+ 		ehci_halt(ehci);
+-		ehci_to_hcd(ehci)->state = HC_STATE_HALT;
++		ehci->rh_state = EHCI_RH_HALTED;
+ 		ehci_err(ehci, "force halt; handshake %p %08x %08x -> %d\n",
+ 			ptr, mask, done, error);
+ 	}
+@@ -278,7 +278,7 @@ static int ehci_reset (struct ehci_hcd *ehci)
+ 	command |= CMD_RESET;
+ 	dbg_cmd (ehci, "reset", command);
+ 	ehci_writel(ehci, command, &ehci->regs->command);
+-	ehci_to_hcd(ehci)->state = HC_STATE_HALT;
++	ehci->rh_state = EHCI_RH_HALTED;
+ 	ehci->next_statechange = jiffies;
+ 	retval = handshake (ehci, &ehci->regs->command,
+ 			    CMD_RESET, 0, 250 * 1000);
+@@ -307,7 +307,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
+ 	u32	temp;
+ 
+ #ifdef DEBUG
+-	if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
++	if (ehci->rh_state != EHCI_RH_RUNNING)
+ 		BUG ();
+ #endif
+ 
+@@ -356,7 +356,7 @@ static void ehci_iaa_watchdog(unsigned long param)
+ 	 */
+ 	if (ehci->reclaim
+ 			&& !timer_pending(&ehci->iaa_watchdog)
+-			&& HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) {
++			&& ehci->rh_state == EHCI_RH_RUNNING) {
+ 		u32 cmd, status;
+ 
+ 		/* If we get here, IAA is *REALLY* late.  It's barely
+@@ -496,7 +496,7 @@ static void ehci_work (struct ehci_hcd *ehci)
+ 	 * misplace IRQs, and should let us run completely without IRQs.
+ 	 * such lossage has been observed on both VT6202 and VT8235.
+ 	 */
+-	if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state) &&
++	if (ehci->rh_state == EHCI_RH_RUNNING &&
+ 			(ehci->async->qh_next.ptr != NULL ||
+ 			 ehci->periodic_sched != 0))
+ 		timer_action (ehci, TIMER_IO_WATCHDOG);
+@@ -516,7 +516,7 @@ static void ehci_stop (struct usb_hcd *hcd)
+ 	del_timer_sync(&ehci->iaa_watchdog);
+ 
+ 	spin_lock_irq(&ehci->lock);
+-	if (HC_IS_RUNNING (hcd->state))
++	if (ehci->rh_state == EHCI_RH_RUNNING)
+ 		ehci_quiesce (ehci);
+ 
+ 	ehci_silence_controller(ehci);
+@@ -741,7 +741,7 @@ static int ehci_run (struct usb_hcd *hcd)
+ 	 * be started before the port switching actions could complete.
+ 	 */
+ 	down_write(&ehci_cf_port_reset_rwsem);
+-	hcd->state = HC_STATE_RUNNING;
++	ehci->rh_state = EHCI_RH_RUNNING;
+ 	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
+ 	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
+ 	msleep(5);
+@@ -788,7 +788,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 
+ 	/* Shared IRQ? */
+ 	masked_status = status & INTR_MASK;
+-	if (!masked_status || unlikely(hcd->state == HC_STATE_HALT)) {
++	if (!masked_status || unlikely(ehci->rh_state == EHCI_RH_HALTED)) {
+ 		spin_unlock(&ehci->lock);
+ 		return IRQ_NONE;
+ 	}
+@@ -952,7 +952,7 @@ static int ehci_urb_enqueue (
+ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ {
+ 	/* failfast */
+-	if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state) && ehci->reclaim)
++	if (ehci->rh_state != EHCI_RH_RUNNING && ehci->reclaim)
+ 		end_unlink_async(ehci);
+ 
+ 	/* If the QH isn't linked then there's nothing we can do
+@@ -1079,7 +1079,7 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 		goto idle_timeout;
+ 	}
+ 
+-	if (!HC_IS_RUNNING (hcd->state))
++	if (ehci->rh_state != EHCI_RH_RUNNING)
+ 		qh->qh_state = QH_STATE_IDLE;
+ 	switch (qh->qh_state) {
+ 	case QH_STATE_LINKED:
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index e051b30c1847..c6104c4f1f38 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -236,10 +236,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 	}
+ 
+ 	/* stop schedules, clean any completed work */
+-	if (HC_IS_RUNNING(hcd->state)) {
++	if (ehci->rh_state == EHCI_RH_RUNNING)
+ 		ehci_quiesce (ehci);
+-		hcd->state = HC_STATE_QUIESCING;
+-	}
+ 	ehci->command = ehci_readl(ehci, &ehci->regs->command);
+ 	ehci_work(ehci);
+ 
+@@ -313,7 +311,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 
+ 	/* turn off now-idle HC */
+ 	ehci_halt (ehci);
+-	hcd->state = HC_STATE_SUSPENDED;
++	ehci->rh_state = EHCI_RH_SUSPENDED;
+ 
+ 	if (ehci->reclaim)
+ 		end_unlink_async(ehci);
+@@ -382,6 +380,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 
+ 	/* restore CMD_RUN, framelist size, and irq threshold */
+ 	ehci_writel(ehci, ehci->command, &ehci->regs->command);
++	ehci->rh_state = EHCI_RH_RUNNING;
+ 
+ 	/* Some controller/firmware combinations need a delay during which
+ 	 * they set up the port statuses.  See Bugzilla #8190. */
+@@ -452,7 +451,6 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 	}
+ 
+ 	ehci->next_statechange = jiffies + msecs_to_jiffies(5);
+-	hcd->state = HC_STATE_RUNNING;
+ 
+ 	/* Now we can safely re-enable irqs */
+ 	ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
+@@ -564,7 +562,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ 	u32		ppcd = 0;
+ 
+ 	/* if !USB_SUSPEND, root hub timers won't get shut down ... */
+-	if (!HC_IS_RUNNING(hcd->state))
++	if (ehci->rh_state != EHCI_RH_RUNNING)
+ 		return 0;
+ 
+ 	/* init status to no-changes */
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index 1102ce65a3a9..8311de7c0a75 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -439,7 +439,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)
+ 	/* here we "know" root ports should always stay powered */
+ 	ehci_port_power(ehci, 1);
+ 
+-	hcd->state = HC_STATE_SUSPENDED;
++	ehci->rh_state = EHCI_RH_SUSPENDED;
+ 	return 0;
+ }
+ #endif
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 0917e3a32465..6ce0b3a9a0f9 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -153,7 +153,7 @@ static void ehci_clear_tt_buffer_complete(struct usb_hcd *hcd,
+ 	spin_lock_irqsave(&ehci->lock, flags);
+ 	qh->clearing_tt = 0;
+ 	if (qh->qh_state == QH_STATE_IDLE && !list_empty(&qh->qtd_list)
+-			&& HC_IS_RUNNING(hcd->state))
++			&& ehci->rh_state == EHCI_RH_RUNNING)
+ 		qh_link_async(ehci, qh);
+ 	spin_unlock_irqrestore(&ehci->lock, flags);
+ }
+@@ -425,7 +425,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 
+ 		/* stop scanning when we reach qtds the hc is using */
+ 		} else if (likely (!stopped
+-				&& HC_IS_RUNNING (ehci_to_hcd(ehci)->state))) {
++				&& ehci->rh_state == EHCI_RH_RUNNING)) {
+ 			break;
+ 
+ 		/* scan the whole queue for unlinks whenever it stops */
+@@ -433,7 +433,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 			stopped = 1;
+ 
+ 			/* cancel everything if we halt, suspend, etc */
+-			if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state))
++			if (ehci->rh_state != EHCI_RH_RUNNING)
+ 				last_status = -ESHUTDOWN;
+ 
+ 			/* this qtd is active; skip it unless a previous qtd
+@@ -977,9 +977,8 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 			/* in case a clear of CMD_ASE didn't take yet */
+ 			(void)handshake(ehci, &ehci->regs->status,
+ 					STS_ASS, 0, 150);
+-			cmd |= CMD_ASE | CMD_RUN;
++			cmd |= CMD_ASE;
+ 			ehci_writel(ehci, cmd, &ehci->regs->command);
+-			ehci_to_hcd(ehci)->state = HC_STATE_RUNNING;
+ 			/* posted write need not be known to HC yet ... */
+ 		}
+ 	}
+@@ -1168,14 +1167,13 @@ static void end_unlink_async (struct ehci_hcd *ehci)
+ 
+ 	qh_completions (ehci, qh);
+ 
+-	if (!list_empty (&qh->qtd_list)
+-			&& HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
++	if (!list_empty(&qh->qtd_list) && ehci->rh_state == EHCI_RH_RUNNING) {
+ 		qh_link_async (ehci, qh);
+-	else {
++	} else {
+ 		/* it's not free to turn the async schedule on/off; leave it
+ 		 * active but idle for a while once it empties.
+ 		 */
+-		if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state)
++		if (ehci->rh_state == EHCI_RH_RUNNING
+ 				&& ehci->async->qh_next.qh == NULL)
+ 			timer_action (ehci, TIMER_ASYNC_OFF);
+ 	}
+@@ -1211,7 +1209,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	/* stop async schedule right now? */
+ 	if (unlikely (qh == ehci->async)) {
+ 		/* can't get here without STS_ASS set */
+-		if (ehci_to_hcd(ehci)->state != HC_STATE_HALT
++		if (ehci->rh_state != EHCI_RH_HALTED
+ 				&& !ehci->reclaim) {
+ 			/* ... and CMD_IAAD clear */
+ 			ehci_writel(ehci, cmd & ~CMD_ASE,
+@@ -1237,7 +1235,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	wmb ();
+ 
+ 	/* If the controller isn't running, we don't have to wait for it */
+-	if (unlikely(!HC_IS_RUNNING(ehci_to_hcd(ehci)->state))) {
++	if (unlikely(ehci->rh_state != EHCI_RH_RUNNING)) {
+ 		/* if (unlikely (qh->reclaim != 0))
+ 		 *	this will recurse, probably not much
+ 		 */
+@@ -1260,7 +1258,7 @@ static void scan_async (struct ehci_hcd *ehci)
+ 	enum ehci_timer_action	action = TIMER_IO_WATCHDOG;
+ 
+ 	timer_action_done (ehci, TIMER_ASYNC_SHRINK);
+-	stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state);
++	stopped = (ehci->rh_state != EHCI_RH_RUNNING);
+ 
+ 	ehci->qh_scan_next = ehci->async->qh_next.qh;
+ 	while (ehci->qh_scan_next) {
+diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c
+index b3958b3d3163..318e0c6d0ab1 100644
+--- a/drivers/usb/host/ehci-s5p.c
++++ b/drivers/usb/host/ehci-s5p.c
+@@ -269,7 +269,7 @@ static int s5p_ehci_resume(struct device *dev)
+ 	/* here we "know" root ports should always stay powered */
+ 	ehci_port_power(ehci, 1);
+ 
+-	hcd->state = HC_STATE_SUSPENDED;
++	ehci->rh_state = EHCI_RH_SUSPENDED;
+ 
+ 	return 0;
+ }
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 2abf8543f083..488151bb45cb 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -479,7 +479,6 @@ static int enable_periodic (struct ehci_hcd *ehci)
+ 	cmd = ehci_readl(ehci, &ehci->regs->command) | CMD_PSE;
+ 	ehci_writel(ehci, cmd, &ehci->regs->command);
+ 	/* posted write ... PSS happens later */
+-	ehci_to_hcd(ehci)->state = HC_STATE_RUNNING;
+ 
+ 	/* make sure ehci_work scans these */
+ 	ehci->next_uframe = ehci_readl(ehci, &ehci->regs->frame_index)
+@@ -677,7 +676,7 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 
+ 	/* reschedule QH iff another request is queued */
+ 	if (!list_empty(&qh->qtd_list) &&
+-			HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) {
++			ehci->rh_state == EHCI_RH_RUNNING) {
+ 		rc = qh_schedule(ehci, qh);
+ 
+ 		/* An error here likely indicates handshake failure
+@@ -2275,7 +2274,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 	 * Touches as few pages as possible:  cache-friendly.
+ 	 */
+ 	now_uframe = ehci->next_uframe;
+-	if (HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) {
++	if (ehci->rh_state == EHCI_RH_RUNNING) {
+ 		clock = ehci_readl(ehci, &ehci->regs->frame_index);
+ 		clock_frame = (clock >> 3) & (ehci->periodic_size - 1);
+ 	} else  {
+@@ -2310,7 +2309,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 			union ehci_shadow	temp;
+ 			int			live;
+ 
+-			live = HC_IS_RUNNING (ehci_to_hcd(ehci)->state);
++			live = (ehci->rh_state == EHCI_RH_RUNNING);
+ 			switch (hc32_to_cpu(ehci, type)) {
+ 			case Q_TYPE_QH:
+ 				/* handle any completions */
+@@ -2435,7 +2434,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 		 * We can't advance our scan without collecting the ISO
+ 		 * transfers that are still pending in this frame.
+ 		 */
+-		if (incomplete && HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) {
++		if (incomplete && ehci->rh_state == EHCI_RH_RUNNING) {
+ 			ehci->next_uframe = now_uframe;
+ 			break;
+ 		}
+@@ -2451,7 +2450,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 		if (now_uframe == clock) {
+ 			unsigned	now;
+ 
+-			if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)
++			if (ehci->rh_state != EHCI_RH_RUNNING
+ 					|| ehci->periodic_sched == 0)
+ 				break;
+ 			ehci->next_uframe = now_uframe;
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index cc7d337ec355..c161d97de7dd 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -62,6 +62,12 @@ struct ehci_stats {
+ 
+ #define	EHCI_MAX_ROOT_PORTS	15		/* see HCS_N_PORTS */
+ 
++enum ehci_rh_state {
++	EHCI_RH_HALTED,
++	EHCI_RH_SUSPENDED,
++	EHCI_RH_RUNNING
++};
++
+ struct ehci_hcd {			/* one per controller */
+ 	/* glue to PCI and HCD framework */
+ 	struct ehci_caps __iomem *caps;
+@@ -70,6 +76,7 @@ struct ehci_hcd {			/* one per controller */
+ 
+ 	__u32			hcs_params;	/* cached register copy */
+ 	spinlock_t		lock;
++	enum ehci_rh_state	rh_state;
+ 
+ 	/* async schedule support */
+ 	struct ehci_qh		*async;

commit 5b1b0b812a7b1a5b968c5d06d90d1cb88621b941
+Author: Alan Stern 
+Date:   Fri Aug 19 23:49:48 2011 +0200
+
+    PM / Runtime: Add macro to test for runtime PM events
+    
+    This patch (as1482) adds a macro for testing whether or not a
+    pm_message value represents an autosuspend or autoresume (i.e., a
+    runtime PM) event.  Encapsulating this notion seems preferable to
+    open-coding the test all over the place.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Greg Kroah-Hartman 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt
+index c9ffa9ced7ee..e8662a5fbc5d 100644
+--- a/Documentation/usb/power-management.txt
++++ b/Documentation/usb/power-management.txt
+@@ -439,10 +439,10 @@ cause autosuspends to fail with -EBUSY if the driver needs to use the
+ device.
+ 
+ External suspend calls should never be allowed to fail in this way,
+-only autosuspend calls.  The driver can tell them apart by checking
+-the PM_EVENT_AUTO bit in the message.event argument to the suspend
+-method; this bit will be set for internal PM events (autosuspend) and
+-clear for external PM events.
++only autosuspend calls.  The driver can tell them apart by applying
++the PMSG_IS_AUTO() macro to the message argument to the suspend
++method; it will return True for internal PM events (autosuspend) and
++False for external PM events.
+ 
+ 
+ 	Mutual exclusion
+diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
+index 91d13a9e8c65..91b190c40497 100644
+--- a/drivers/bluetooth/btusb.c
++++ b/drivers/bluetooth/btusb.c
+@@ -1103,7 +1103,7 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
+ 		return 0;
+ 
+ 	spin_lock_irq(&data->txlock);
+-	if (!((message.event & PM_EVENT_AUTO) && data->tx_in_flight)) {
++	if (!(PMSG_IS_AUTO(message) && data->tx_in_flight)) {
+ 		set_bit(BTUSB_SUSPENDING, &data->flags);
+ 		spin_unlock_irq(&data->txlock);
+ 	} else {
+diff --git a/drivers/hid/hid-picolcd.c b/drivers/hid/hid-picolcd.c
+index 9d8710f8bc79..1782693819f3 100644
+--- a/drivers/hid/hid-picolcd.c
++++ b/drivers/hid/hid-picolcd.c
+@@ -2409,7 +2409,7 @@ static int picolcd_raw_event(struct hid_device *hdev,
+ #ifdef CONFIG_PM
+ static int picolcd_suspend(struct hid_device *hdev, pm_message_t message)
+ {
+-	if (message.event & PM_EVENT_AUTO)
++	if (PMSG_IS_AUTO(message))
+ 		return 0;
+ 
+ 	picolcd_suspend_backlight(hid_get_drvdata(hdev));
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index ad978f5748d3..a9fa294ee7d3 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -1332,7 +1332,7 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
+ 	struct usbhid_device *usbhid = hid->driver_data;
+ 	int status;
+ 
+-	if (message.event & PM_EVENT_AUTO) {
++	if (PMSG_IS_AUTO(message)) {
+ 		spin_lock_irq(&usbhid->lock);	/* Sync with error handler */
+ 		if (!test_bit(HID_RESET_PENDING, &usbhid->iofl)
+ 		    && !test_bit(HID_CLEAR_HALT, &usbhid->iofl)
+@@ -1367,7 +1367,7 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
+ 			return -EIO;
+ 	}
+ 
+-	if (!ignoreled && (message.event & PM_EVENT_AUTO)) {
++	if (!ignoreled && PMSG_IS_AUTO(message)) {
+ 		spin_lock_irq(&usbhid->lock);
+ 		if (test_bit(HID_LED_ON, &usbhid->iofl)) {
+ 			spin_unlock_irq(&usbhid->lock);
+@@ -1380,8 +1380,7 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
+ 	hid_cancel_delayed_stuff(usbhid);
+ 	hid_cease_io(usbhid);
+ 
+-	if ((message.event & PM_EVENT_AUTO) &&
+-			test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) {
++	if (PMSG_IS_AUTO(message) && test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) {
+ 		/* lost race against keypresses */
+ 		status = hid_start_in(hid);
+ 		if (status < 0)
+diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
+index ce395fe5de26..f1c435ba5284 100644
+--- a/drivers/net/usb/usbnet.c
++++ b/drivers/net/usb/usbnet.c
+@@ -1470,7 +1470,7 @@ int usbnet_suspend (struct usb_interface *intf, pm_message_t message)
+ 	if (!dev->suspend_count++) {
+ 		spin_lock_irq(&dev->txq.lock);
+ 		/* don't autosuspend while transmitting */
+-		if (dev->txq.qlen && (message.event & PM_EVENT_AUTO)) {
++		if (dev->txq.qlen && PMSG_IS_AUTO(message)) {
+ 			spin_unlock_irq(&dev->txq.lock);
+ 			return -EBUSY;
+ 		} else {
+diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c
+index 298f2b0b6311..9a644d052f1e 100644
+--- a/drivers/net/wimax/i2400m/usb.c
++++ b/drivers/net/wimax/i2400m/usb.c
+@@ -599,7 +599,7 @@ void i2400mu_disconnect(struct usb_interface *iface)
+  *
+  *    As well, the device might refuse going to sleep for whichever
+  *    reason. In this case we just fail. For system suspend/hibernate,
+- *    we *can't* fail. We check PM_EVENT_AUTO to see if the
++ *    we *can't* fail. We check PMSG_IS_AUTO to see if the
+  *    suspend call comes from the USB stack or from the system and act
+  *    in consequence.
+  *
+@@ -615,7 +615,7 @@ int i2400mu_suspend(struct usb_interface *iface, pm_message_t pm_msg)
+ 	struct i2400m *i2400m = &i2400mu->i2400m;
+ 
+ #ifdef CONFIG_PM
+-	if (pm_msg.event & PM_EVENT_AUTO)
++	if (PMSG_IS_AUTO(pm_msg))
+ 		is_autosuspend = 1;
+ #endif
+ 
+diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
+index dac7676ce21b..94e6c5c09dd8 100644
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -1305,7 +1305,7 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message)
+ 	struct acm *acm = usb_get_intfdata(intf);
+ 	int cnt;
+ 
+-	if (message.event & PM_EVENT_AUTO) {
++	if (PMSG_IS_AUTO(message)) {
+ 		int b;
+ 
+ 		spin_lock_irq(&acm->write_lock);
+diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
+index 2b9ff518b509..42f180aca3fb 100644
+--- a/drivers/usb/class/cdc-wdm.c
++++ b/drivers/usb/class/cdc-wdm.c
+@@ -798,11 +798,11 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
+ 	dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor);
+ 
+ 	/* if this is an autosuspend the caller does the locking */
+-	if (!(message.event & PM_EVENT_AUTO))
++	if (!PMSG_IS_AUTO(message))
+ 		mutex_lock(&desc->lock);
+ 	spin_lock_irq(&desc->iuspin);
+ 
+-	if ((message.event & PM_EVENT_AUTO) &&
++	if (PMSG_IS_AUTO(message) &&
+ 			(test_bit(WDM_IN_USE, &desc->flags)
+ 			|| test_bit(WDM_RESPONDING, &desc->flags))) {
+ 		spin_unlock_irq(&desc->iuspin);
+@@ -815,7 +815,7 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
+ 		kill_urbs(desc);
+ 		cancel_work_sync(&desc->rxwork);
+ 	}
+-	if (!(message.event & PM_EVENT_AUTO))
++	if (!PMSG_IS_AUTO(message))
+ 		mutex_unlock(&desc->lock);
+ 
+ 	return rv;
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 34e3da5aa72a..e03042883c68 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1046,8 +1046,7 @@ static int usb_resume_device(struct usb_device *udev, pm_message_t msg)
+ 	/* Non-root devices on a full/low-speed bus must wait for their
+ 	 * companion high-speed root hub, in case a handoff is needed.
+ 	 */
+-	if (!(msg.event & PM_EVENT_AUTO) && udev->parent &&
+-			udev->bus->hs_companion)
++	if (!PMSG_IS_AUTO(msg) && udev->parent && udev->bus->hs_companion)
+ 		device_pm_wait_for_dev(&udev->dev,
+ 				&udev->bus->hs_companion->root_hub->dev);
+ 
+@@ -1075,7 +1074,7 @@ static int usb_suspend_interface(struct usb_device *udev,
+ 
+ 	if (driver->suspend) {
+ 		status = driver->suspend(intf, msg);
+-		if (status && !(msg.event & PM_EVENT_AUTO))
++		if (status && !PMSG_IS_AUTO(msg))
+ 			dev_err(&intf->dev, "%s error %d\n",
+ 					"suspend", status);
+ 	} else {
+@@ -1189,7 +1188,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 			status = usb_suspend_interface(udev, intf, msg);
+ 
+ 			/* Ignore errors during system sleep transitions */
+-			if (!(msg.event & PM_EVENT_AUTO))
++			if (!PMSG_IS_AUTO(msg))
+ 				status = 0;
+ 			if (status != 0)
+ 				break;
+@@ -1199,7 +1198,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 		status = usb_suspend_device(udev, msg);
+ 
+ 		/* Again, ignore errors during system sleep transitions */
+-		if (!(msg.event & PM_EVENT_AUTO))
++		if (!PMSG_IS_AUTO(msg))
+ 			status = 0;
+ 	}
+ 
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 8669ba3fe794..da582f4e486b 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1960,7 +1960,7 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg)
+ 	int		old_state = hcd->state;
+ 
+ 	dev_dbg(&rhdev->dev, "bus %s%s\n",
+-			(msg.event & PM_EVENT_AUTO ? "auto-" : ""), "suspend");
++			(PMSG_IS_AUTO(msg) ? "auto-" : ""), "suspend");
+ 	if (HCD_DEAD(hcd)) {
+ 		dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "suspend");
+ 		return 0;
+@@ -1996,7 +1996,7 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
+ 	int		old_state = hcd->state;
+ 
+ 	dev_dbg(&rhdev->dev, "usb %s%s\n",
+-			(msg.event & PM_EVENT_AUTO ? "auto-" : ""), "resume");
++			(PMSG_IS_AUTO(msg) ? "auto-" : ""), "resume");
+ 	if (HCD_DEAD(hcd)) {
+ 		dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "resume");
+ 		return 0;
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index a428aa080a36..ee50e0bf84e8 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2342,7 +2342,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ 			dev_dbg(&udev->dev, "won't remote wakeup, status %d\n",
+ 					status);
+ 			/* bail if autosuspend is requested */
+-			if (msg.event & PM_EVENT_AUTO)
++			if (PMSG_IS_AUTO(msg))
+ 				return status;
+ 		}
+ 	}
+@@ -2367,12 +2367,12 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ 				USB_CTRL_SET_TIMEOUT);
+ 
+ 		/* System sleep transitions should never fail */
+-		if (!(msg.event & PM_EVENT_AUTO))
++		if (!PMSG_IS_AUTO(msg))
+ 			status = 0;
+ 	} else {
+ 		/* device has up to 10 msec to fully suspend */
+ 		dev_dbg(&udev->dev, "usb %ssuspend\n",
+-				(msg.event & PM_EVENT_AUTO ? "auto-" : ""));
++				(PMSG_IS_AUTO(msg) ? "auto-" : ""));
+ 		usb_set_device_state(udev, USB_STATE_SUSPENDED);
+ 		msleep(10);
+ 	}
+@@ -2523,7 +2523,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
+ 	} else {
+ 		/* drive resume for at least 20 msec */
+ 		dev_dbg(&udev->dev, "usb %sresume\n",
+-				(msg.event & PM_EVENT_AUTO ? "auto-" : ""));
++				(PMSG_IS_AUTO(msg) ? "auto-" : ""));
+ 		msleep(25);
+ 
+ 		/* Virtual root hubs can trigger on GET_PORT_STATUS to
+@@ -2625,7 +2625,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+ 		udev = hdev->children [port1-1];
+ 		if (udev && udev->can_submit) {
+ 			dev_warn(&intf->dev, "port %d nyet suspended\n", port1);
+-			if (msg.event & PM_EVENT_AUTO)
++			if (PMSG_IS_AUTO(msg))
+ 				return -EBUSY;
+ 		}
+ 	}
+diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
+index d5d136a53b61..b18179bda0d8 100644
+--- a/drivers/usb/serial/sierra.c
++++ b/drivers/usb/serial/sierra.c
+@@ -1009,7 +1009,7 @@ static int sierra_suspend(struct usb_serial *serial, pm_message_t message)
+ 	struct sierra_intf_private *intfdata;
+ 	int b;
+ 
+-	if (message.event & PM_EVENT_AUTO) {
++	if (PMSG_IS_AUTO(message)) {
+ 		intfdata = serial->private;
+ 		spin_lock_irq(&intfdata->susp_lock);
+ 		b = intfdata->in_flight;
+diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
+index e4fad5e643d7..d555ca9567b8 100644
+--- a/drivers/usb/serial/usb_wwan.c
++++ b/drivers/usb/serial/usb_wwan.c
+@@ -651,7 +651,7 @@ int usb_wwan_suspend(struct usb_serial *serial, pm_message_t message)
+ 
+ 	dbg("%s entered", __func__);
+ 
+-	if (message.event & PM_EVENT_AUTO) {
++	if (PMSG_IS_AUTO(message)) {
+ 		spin_lock_irq(&intfdata->susp_lock);
+ 		b = intfdata->in_flight;
+ 		spin_unlock_irq(&intfdata->susp_lock);
+diff --git a/include/linux/pm.h b/include/linux/pm.h
+index f7c84c9abd30..18de9f893497 100644
+--- a/include/linux/pm.h
++++ b/include/linux/pm.h
+@@ -366,6 +366,8 @@ extern struct dev_pm_ops generic_subsys_pm_ops;
+ #define PMSG_AUTO_RESUME	((struct pm_message) \
+ 					{ .event = PM_EVENT_AUTO_RESUME, })
+ 
++#define PMSG_IS_AUTO(msg)	(((msg).event & PM_EVENT_AUTO) != 0)
++
+ /**
+  * Device run-time power management status.
+  *
+diff --git a/sound/usb/card.c b/sound/usb/card.c
+index 781d9e61adfb..d5754fa5e551 100644
+--- a/sound/usb/card.c
++++ b/sound/usb/card.c
+@@ -628,7 +628,7 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
+ 	if (chip == (void *)-1L)
+ 		return 0;
+ 
+-	if (!(message.event & PM_EVENT_AUTO)) {
++	if (!PMSG_IS_AUTO(message)) {
+ 		snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
+ 		if (!chip->num_suspended_intf++) {
+ 			list_for_each(p, &chip->pcm_list) {

commit e04f5f7e423018bcec84c11af2058cdce87816f3
+Author: Alan Stern 
+Date:   Tue Jul 19 14:01:23 2011 -0400
+
+    EHCI: fix direction handling for interrupt data toggles
+    
+    This patch (as1480) fixes a rather obscure bug in ehci-hcd.  The
+    qh_update() routine needs to know the number and direction of the
+    endpoint corresponding to its QH argument.  The number can be taken
+    directly from the QH data structure, but the direction isn't stored
+    there.  The direction is taken instead from the first qTD linked to
+    the QH.
+    
+    However, it turns out that for interrupt transfers, qh_update() gets
+    called before the qTDs are linked to the QH.  As a result, qh_update()
+    computes a bogus direction value, which messes up the endpoint toggle
+    handling.  Under the right combination of circumstances this causes
+    usb_reset_endpoint() not to work correctly, which causes packets to be
+    dropped and communications to fail.
+    
+    Now, it's silly for the QH structure not to have direct access to all
+    the descriptor information for the corresponding endpoint.  Ultimately
+    it may get a pointer to the usb_host_endpoint structure; for now,
+    adding a copy of the direction flag solves the immediate problem.
+    
+    This allows the Spyder2 color-calibration system (a low-speed USB
+    device that sends all its interrupt data packets with the toggle set
+    to 0 and hance requires constant use of usb_reset_endpoint) to work
+    when connected through a high-speed hub.  Thanks to Graeme Gill for
+    supplying the hardware that allowed me to track down this bug.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Graeme Gill 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 9bf3c0d983c4..0917e3a32465 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -103,7 +103,7 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
+ 	if (!(hw->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) {
+ 		unsigned	is_out, epnum;
+ 
+-		is_out = !(qtd->hw_token & cpu_to_hc32(ehci, 1 << 8));
++		is_out = qh->is_out;
+ 		epnum = (hc32_to_cpup(ehci, &hw->hw_info1) >> 8) & 0x0f;
+ 		if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) {
+ 			hw->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
+@@ -946,6 +946,7 @@ qh_make (
+ 	hw = qh->hw;
+ 	hw->hw_info1 = cpu_to_hc32(ehci, info1);
+ 	hw->hw_info2 = cpu_to_hc32(ehci, info2);
++	qh->is_out = !is_input;
+ 	usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1);
+ 	qh_refresh (ehci, qh);
+ 	return qh;
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index e4feec3457fb..cc7d337ec355 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -377,6 +377,7 @@ struct ehci_qh {
+ #define NO_FRAME ((unsigned short)~0)			/* pick new start */
+ 
+ 	struct usb_device	*dev;		/* access to TT */
++	unsigned		is_out:1;	/* bulk or intr OUT */
+ 	unsigned		clearing_tt:1;	/* Clear-TT-Buf in progress */
+ };
+ 

commit 6ea12a04d295235ed67010a09fdea58c949e3eb0
+Author: Alan Stern 
+Date:   Fri Jul 15 17:22:15 2011 -0400
+
+    USB: OHCI: fix another regression for NVIDIA controllers
+    
+    The NVIDIA series of OHCI controllers continues to be troublesome.  A
+    few people using the MCP67 chipset have reported that even with the
+    most recent kernels, the OHCI controller fails to handle new
+    connections and spams the system log with "unable to enumerate USB
+    port" messages.  This is different from the other problems previously
+    reported for NVIDIA OHCI controllers, although it is probably related.
+    
+    It turns out that the MCP67 controller does not like to be kept in the
+    RESET state very long.  After only a few seconds, it decides not to
+    work any more.  This patch (as1479) changes the PCI initialization
+    quirk code so that NVIDIA controllers are switched into the SUSPEND
+    state after 50 ms of RESET.  With no interrupts enabled and all the
+    downstream devices reset, and thus unable to send wakeup requests,
+    this should be perfectly safe (even for non-NVIDIA hardware).
+    
+    The removal code in ohci-hcd hasn't been changed; it will still leave
+    the controller in the RESET state.  As a result, if someone unloads
+    ohci-hcd and then reloads it, the controller won't work again until
+    the system is rebooted.  If anybody complains about this, the removal
+    code can be updated similarly.
+    
+    This fixes Bugzilla #22052.
+    
+    Tested-by: Larry Finger 
+    Cc: stable 
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
+index b5a7304fcbef..a9d315906e3d 100644
+--- a/drivers/usb/host/pci-quirks.c
++++ b/drivers/usb/host/pci-quirks.c
+@@ -35,6 +35,8 @@
+ #define OHCI_INTRSTATUS		0x0c
+ #define OHCI_INTRENABLE		0x10
+ #define OHCI_INTRDISABLE	0x14
++#define OHCI_FMINTERVAL		0x34
++#define OHCI_HCR		(1 << 0)	/* host controller reset */
+ #define OHCI_OCR		(1 << 3)	/* ownership change request */
+ #define OHCI_CTRL_RWC		(1 << 9)	/* remote wakeup connected */
+ #define OHCI_CTRL_IR		(1 << 8)	/* interrupt routing */
+@@ -497,6 +499,32 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
+ 
+ 	/* reset controller, preserving RWC (and possibly IR) */
+ 	writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL);
++	readl(base + OHCI_CONTROL);
++
++	/* Some NVIDIA controllers stop working if kept in RESET for too long */
++	if (pdev->vendor == PCI_VENDOR_ID_NVIDIA) {
++		u32 fminterval;
++		int cnt;
++
++		/* drive reset for at least 50 ms (7.1.7.5) */
++		msleep(50);
++
++		/* software reset of the controller, preserving HcFmInterval */
++		fminterval = readl(base + OHCI_FMINTERVAL);
++		writel(OHCI_HCR, base + OHCI_CMDSTATUS);
++
++		/* reset requires max 10 us delay */
++		for (cnt = 30; cnt > 0; --cnt) {	/* ... allow extra time */
++			if ((readl(base + OHCI_CMDSTATUS) & OHCI_HCR) == 0)
++				break;
++			udelay(1);
++		}
++		writel(fminterval, base + OHCI_FMINTERVAL);
++
++		/* Now we're in the SUSPEND state with all devices reset
++		 * and wakeups and interrupts disabled
++		 */
++	}
+ 
+ 	/*
+ 	 * disable interrupts

commit 004c19682884d4f40000ce1ded53f4a1d0b18206
+Author: Alan Stern 
+Date:   Tue Jul 5 12:34:05 2011 -0400
+
+    USB: EHCI: go back to using the system clock for QH unlinks
+    
+    This patch (as1477) fixes a problem affecting a few types of EHCI
+    controller.  Contrary to what one might expect, these controllers
+    automatically stop their internal frame counter when no ports are
+    enabled.  Since ehci-hcd currently relies on the frame counter for
+    determining when it should unlink QHs from the async schedule, those
+    controllers run into trouble: The frame counter stops and the QHs
+    never get unlinked.
+    
+    Some systems have also experienced other problems traced back to
+    commit b963801164618e25fbdc0cd452ce49c3628b46c8 (USB: ehci-hcd unlink
+    speedups), which made the original switch from using the system clock
+    to using the frame counter.  It never became clear what the reason was
+    for these problems, but evidently it is related to use of the frame
+    counter.
+    
+    To fix all these problems, this patch more or less reverts that commit
+    and goes back to using the system clock.  But this can't be done
+    cleanly because other changes have since been made to the scan_async()
+    subroutine.  One of these changes involved the tricky logic that tries
+    to avoid rescanning QHs that have already been seen when the scanning
+    loop is restarted, which happens whenever an URB is given back.
+    Switching back to clock-based unlinks would make this logic even more
+    complicated.
+    
+    Therefore the new code doesn't rescan the entire async list whenever a
+    giveback occurs.  Instead it rescans only the current QH and continues
+    on from there.  This requires the use of a separate pointer to keep
+    track of the next QH to scan, since the current QH may be unlinked
+    while the scanning is in progress.  That new pointer must be global,
+    so that it can be adjusted forward whenever the _next_ QH gets
+    unlinked.  (uhci-hcd uses this same trick.)
+    
+    Simplification of the scanning loop removes a level of indentation,
+    which accounts for the size of the patch.  The amount of code changed
+    is relatively small, and it isn't exactly a reversion of the
+    b963801164 commit.
+    
+    This fixes Bugzilla #32432.
+    
+    Signed-off-by: Alan Stern 
+    CC: 
+    Tested-by: Matej Kenda 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 4ee62bef3723..2902199fa8ff 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -90,7 +90,8 @@ static const char	hcd_name [] = "ehci_hcd";
+ #define EHCI_IAA_MSECS		10		/* arbitrary */
+ #define EHCI_IO_JIFFIES		(HZ/10)		/* io watchdog > irq_thresh */
+ #define EHCI_ASYNC_JIFFIES	(HZ/20)		/* async idle timeout */
+-#define EHCI_SHRINK_FRAMES	5		/* async qh unlink delay */
++#define EHCI_SHRINK_JIFFIES	(DIV_ROUND_UP(HZ, 200) + 1)
++						/* 200-ms async qh unlink delay */
+ 
+ /* Initial IRQ latency:  faster than hw default */
+ static int log2_irq_thresh = 0;		// 0 to 6
+@@ -148,10 +149,7 @@ timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action)
+ 			break;
+ 		/* case TIMER_ASYNC_SHRINK: */
+ 		default:
+-			/* add a jiffie since we synch against the
+-			 * 8 KHz uframe counter.
+-			 */
+-			t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1;
++			t = EHCI_SHRINK_JIFFIES;
+ 			break;
+ 		}
+ 		mod_timer(&ehci->watchdog, t + jiffies);
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 5d6bc624c961..9bf3c0d983c4 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -1231,6 +1231,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 
+ 	prev->hw->hw_next = qh->hw->hw_next;
+ 	prev->qh_next = qh->qh_next;
++	if (ehci->qh_scan_next == qh)
++		ehci->qh_scan_next = qh->qh_next.qh;
+ 	wmb ();
+ 
+ 	/* If the controller isn't running, we don't have to wait for it */
+@@ -1256,53 +1258,49 @@ static void scan_async (struct ehci_hcd *ehci)
+ 	struct ehci_qh		*qh;
+ 	enum ehci_timer_action	action = TIMER_IO_WATCHDOG;
+ 
+-	ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index);
+ 	timer_action_done (ehci, TIMER_ASYNC_SHRINK);
+-rescan:
+ 	stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state);
+-	qh = ehci->async->qh_next.qh;
+-	if (likely (qh != NULL)) {
+-		do {
+-			/* clean any finished work for this qh */
+-			if (!list_empty(&qh->qtd_list) && (stopped ||
+-					qh->stamp != ehci->stamp)) {
+-				int temp;
+-
+-				/* unlinks could happen here; completion
+-				 * reporting drops the lock.  rescan using
+-				 * the latest schedule, but don't rescan
+-				 * qhs we already finished (no looping)
+-				 * unless the controller is stopped.
+-				 */
+-				qh = qh_get (qh);
+-				qh->stamp = ehci->stamp;
+-				temp = qh_completions (ehci, qh);
+-				if (qh->needs_rescan)
+-					unlink_async(ehci, qh);
+-				qh_put (qh);
+-				if (temp != 0) {
+-					goto rescan;
+-				}
+-			}
+ 
+-			/* unlink idle entries, reducing DMA usage as well
+-			 * as HCD schedule-scanning costs.  delay for any qh
+-			 * we just scanned, there's a not-unusual case that it
+-			 * doesn't stay idle for long.
+-			 * (plus, avoids some kind of re-activation race.)
++	ehci->qh_scan_next = ehci->async->qh_next.qh;
++	while (ehci->qh_scan_next) {
++		qh = ehci->qh_scan_next;
++		ehci->qh_scan_next = qh->qh_next.qh;
++ rescan:
++		/* clean any finished work for this qh */
++		if (!list_empty(&qh->qtd_list)) {
++			int temp;
++
++			/*
++			 * Unlinks could happen here; completion reporting
++			 * drops the lock.  That's why ehci->qh_scan_next
++			 * always holds the next qh to scan; if the next qh
++			 * gets unlinked then ehci->qh_scan_next is adjusted
++			 * in start_unlink_async().
+ 			 */
+-			if (list_empty(&qh->qtd_list)
+-					&& qh->qh_state == QH_STATE_LINKED) {
+-				if (!ehci->reclaim && (stopped ||
+-					((ehci->stamp - qh->stamp) & 0x1fff)
+-						>= EHCI_SHRINK_FRAMES * 8))
+-					start_unlink_async(ehci, qh);
+-				else
+-					action = TIMER_ASYNC_SHRINK;
+-			}
++			qh = qh_get(qh);
++			temp = qh_completions(ehci, qh);
++			if (qh->needs_rescan)
++				unlink_async(ehci, qh);
++			qh->unlink_time = jiffies + EHCI_SHRINK_JIFFIES;
++			qh_put(qh);
++			if (temp != 0)
++				goto rescan;
++		}
+ 
+-			qh = qh->qh_next.qh;
+-		} while (qh);
++		/* unlink idle entries, reducing DMA usage as well
++		 * as HCD schedule-scanning costs.  delay for any qh
++		 * we just scanned, there's a not-unusual case that it
++		 * doesn't stay idle for long.
++		 * (plus, avoids some kind of re-activation race.)
++		 */
++		if (list_empty(&qh->qtd_list)
++				&& qh->qh_state == QH_STATE_LINKED) {
++			if (!ehci->reclaim && (stopped ||
++					time_after_eq(jiffies, qh->unlink_time)))
++				start_unlink_async(ehci, qh);
++			else
++				action = TIMER_ASYNC_SHRINK;
++		}
+ 	}
+ 	if (action == TIMER_ASYNC_SHRINK)
+ 		timer_action (ehci, TIMER_ASYNC_SHRINK);
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index fa3129fe1ee0..e4feec3457fb 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -75,6 +75,7 @@ struct ehci_hcd {			/* one per controller */
+ 	struct ehci_qh		*async;
+ 	struct ehci_qh		*dummy;		/* For AMD quirk use */
+ 	struct ehci_qh		*reclaim;
++	struct ehci_qh		*qh_scan_next;
+ 	unsigned		scanning : 1;
+ 
+ 	/* periodic schedule support */
+@@ -119,7 +120,6 @@ struct ehci_hcd {			/* one per controller */
+ 	struct timer_list	iaa_watchdog;
+ 	struct timer_list	watchdog;
+ 	unsigned long		actions;
+-	unsigned		stamp;
+ 	unsigned		periodic_stamp;
+ 	unsigned		random_frame;
+ 	unsigned long		next_statechange;
+@@ -345,6 +345,7 @@ struct ehci_qh {
+ 	struct ehci_qh		*reclaim;	/* next to reclaim */
+ 
+ 	struct ehci_hcd		*ehci;
++	unsigned long		unlink_time;
+ 
+ 	/*
+ 	 * Do NOT use atomic operations for QH refcounting. On some CPUs

commit ca5c485f55d326d9a23e4badd05890148aa53f74
+Author: Alan Stern 
+Date:   Wed Jul 6 17:03:45 2011 -0400
+
+    USB: additional regression fix for device removal
+    
+    Commit e534c5b831c8b8e9f5edee5c8a37753c808b80dc (USB: fix regression
+    occurring during device removal) didn't go far enough.  It failed to
+    take into account that when a driver claims multiple interfaces, it may
+    release them all at the same time.  As a result, some interfaces can
+    get released before they are unregistered, and we deadlock trying to
+    acquire the bandwidth_mutex that we already own.
+    
+    This patch (asl478) handles this case by setting the "unregistering"
+    flag on all the interfaces before removing any of them.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Tested-by: Éric Piel 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index e0719b4ee189..0b5ec234c787 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1147,6 +1147,14 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
+ 	 * any drivers bound to them (a key side effect)
+ 	 */
+ 	if (dev->actconfig) {
++		/*
++		 * FIXME: In order to avoid self-deadlock involving the
++		 * bandwidth_mutex, we have to mark all the interfaces
++		 * before unregistering any of them.
++		 */
++		for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++)
++			dev->actconfig->interface[i]->unregistering = 1;
++
+ 		for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
+ 			struct usb_interface	*interface;
+ 
+@@ -1156,7 +1164,6 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
+ 				continue;
+ 			dev_dbg(&dev->dev, "unregistering interface %s\n",
+ 				dev_name(&interface->dev));
+-			interface->unregistering = 1;
+ 			remove_intf_ep_devs(interface);
+ 			device_del(&interface->dev);
+ 		}

commit 69c843b45eb3b8f267019e6a05860c9c48337419
+Author: Alan Stern 
+Date:   Wed Jul 6 10:52:23 2011 +0200
+
+    PM / Runtime: Prevent runtime_resume from racing with probe
+    
+    This patch (as1475) adds device_lock() and device_unlock() calls to
+    the store methods for the power/control and power/autosuspend_delay_ms
+    sysfs attribute files.  We don't want badly timed writes to these
+    files to cause runtime_resume callbacks to occur while a driver is
+    being probed for a device.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
+index a9f5b8979611..942d6a7c9ae1 100644
+--- a/drivers/base/power/sysfs.c
++++ b/drivers/base/power/sysfs.c
+@@ -116,12 +116,14 @@ static ssize_t control_store(struct device * dev, struct device_attribute *attr,
+ 	cp = memchr(buf, '\n', n);
+ 	if (cp)
+ 		len = cp - buf;
++	device_lock(dev);
+ 	if (len == sizeof ctrl_auto - 1 && strncmp(buf, ctrl_auto, len) == 0)
+ 		pm_runtime_allow(dev);
+ 	else if (len == sizeof ctrl_on - 1 && strncmp(buf, ctrl_on, len) == 0)
+ 		pm_runtime_forbid(dev);
+ 	else
+-		return -EINVAL;
++		n = -EINVAL;
++	device_unlock(dev);
+ 	return n;
+ }
+ 
+@@ -205,7 +207,9 @@ static ssize_t autosuspend_delay_ms_store(struct device *dev,
+ 	if (strict_strtol(buf, 10, &delay) != 0 || delay != (int) delay)
+ 		return -EINVAL;
+ 
++	device_lock(dev);
+ 	pm_runtime_set_autosuspend_delay(dev, delay);
++	device_unlock(dev);
+ 	return n;
+ }
+ 

commit e534c5b831c8b8e9f5edee5c8a37753c808b80dc
+Author: Alan Stern 
+Date:   Fri Jul 1 16:43:02 2011 -0400
+
+    USB: fix regression occurring during device removal
+    
+    This patch (as1476) fixes a regression introduced by
+    fccf4e86200b8f5edd9a65da26f150e32ba79808 (USB: Free bandwidth when
+    usb_disable_device is called).  usb_disconnect() grabs the
+    bandwidth_mutex before calling usb_disable_device(), which calls down
+    indirectly to usb_set_interface(), which tries to acquire the
+    bandwidth_mutex.
+    
+    The fix causes usb_set_interface() to return early when it is called
+    for an interface that has already been unregistered, which is what
+    happens in usb_disable_device().
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Sarah Sharp 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 64c7ab4702df..e0719b4ee189 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1286,6 +1286,8 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
+ 			interface);
+ 		return -EINVAL;
+ 	}
++	if (iface->unregistering)
++		return -ENODEV;
+ 
+ 	alt = usb_altnum_to_altsetting(iface, alternate);
+ 	if (!alt) {

commit 6d0e0e84f66d32c33511984dd3badd32364b863c
+Author: Alan Stern 
+Date:   Sat Jun 18 22:42:09 2011 +0200
+
+    PM: Fix async resume following suspend failure
+    
+    The PM core doesn't handle suspend failures correctly when it comes to
+    asynchronously suspended devices.  These devices are moved onto the
+    dpm_suspended_list as soon as the corresponding async thread is
+    started up, and they remain on the list even if they fail to suspend
+    or the sleep transition is cancelled before they get suspended.  As a
+    result, when the PM core unwinds the transition, it tries to resume
+    the devices even though they were never suspended.
+    
+    This patch (as1474) fixes the problem by adding a new "is_suspended"
+    flag to dev_pm_info.  Devices are resumed only if the flag is set.
+    
+    [rjw:
+     * Moved the dev->power.is_suspended check into device_resume(),
+       because we need to complete dev->power.completion and clear
+       dev->power.is_prepared too for devices whose
+       dev->power.is_suspended flags are unset.
+     * Fixed __device_suspend() to avoid setting dev->power.is_suspended
+       if async_error is different from zero.]
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+    Cc: stable@kernel.org
+
+diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
+index bf5a59ac1957..06f09bf89cb2 100644
+--- a/drivers/base/power/main.c
++++ b/drivers/base/power/main.c
+@@ -58,6 +58,7 @@ static int async_error;
+ void device_pm_init(struct device *dev)
+ {
+ 	dev->power.is_prepared = false;
++	dev->power.is_suspended = false;
+ 	init_completion(&dev->power.completion);
+ 	complete_all(&dev->power.completion);
+ 	dev->power.wakeup = NULL;
+@@ -517,6 +518,9 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
+ 	 */
+ 	dev->power.is_prepared = false;
+ 
++	if (!dev->power.is_suspended)
++		goto Unlock;
++
+ 	if (dev->pwr_domain) {
+ 		pm_dev_dbg(dev, state, "power domain ");
+ 		error = pm_op(dev, &dev->pwr_domain->ops, state);
+@@ -552,6 +556,9 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
+ 	}
+ 
+  End:
++	dev->power.is_suspended = false;
++
++ Unlock:
+ 	device_unlock(dev);
+ 	complete_all(&dev->power.completion);
+ 
+@@ -839,11 +846,11 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
+ 	device_lock(dev);
+ 
+ 	if (async_error)
+-		goto End;
++		goto Unlock;
+ 
+ 	if (pm_wakeup_pending()) {
+ 		async_error = -EBUSY;
+-		goto End;
++		goto Unlock;
+ 	}
+ 
+ 	if (dev->pwr_domain) {
+@@ -881,6 +888,9 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
+ 	}
+ 
+  End:
++	dev->power.is_suspended = !error;
++
++ Unlock:
+ 	device_unlock(dev);
+ 	complete_all(&dev->power.completion);
+ 
+diff --git a/include/linux/pm.h b/include/linux/pm.h
+index cc536bd80984..411e4f4be52b 100644
+--- a/include/linux/pm.h
++++ b/include/linux/pm.h
+@@ -426,6 +426,7 @@ struct dev_pm_info {
+ 	unsigned int		can_wakeup:1;
+ 	unsigned int		async_suspend:1;
+ 	bool			is_prepared:1;	/* Owned by the PM core */
++	bool			is_suspended:1;	/* Ditto */
+ 	spinlock_t		lock;
+ #ifdef CONFIG_PM_SLEEP
+ 	struct list_head	entry;

commit f76b168b6f117a49d36307053e1acbe30580ea5b
+Author: Alan Stern 
+Date:   Sat Jun 18 20:22:23 2011 +0200
+
+    PM: Rename dev_pm_info.in_suspend to is_prepared
+    
+    This patch (as1473) renames the "in_suspend" field in struct
+    dev_pm_info to "is_prepared", in preparation for an upcoming change.
+    The new name is more descriptive of what the field really means.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+    Cc: stable@kernel.org
+
+diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
+index aa6320207745..bf5a59ac1957 100644
+--- a/drivers/base/power/main.c
++++ b/drivers/base/power/main.c
+@@ -57,7 +57,7 @@ static int async_error;
+  */
+ void device_pm_init(struct device *dev)
+ {
+-	dev->power.in_suspend = false;
++	dev->power.is_prepared = false;
+ 	init_completion(&dev->power.completion);
+ 	complete_all(&dev->power.completion);
+ 	dev->power.wakeup = NULL;
+@@ -91,7 +91,7 @@ void device_pm_add(struct device *dev)
+ 	pr_debug("PM: Adding info for %s:%s\n",
+ 		 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
+ 	mutex_lock(&dpm_list_mtx);
+-	if (dev->parent && dev->parent->power.in_suspend)
++	if (dev->parent && dev->parent->power.is_prepared)
+ 		dev_warn(dev, "parent %s should not be sleeping\n",
+ 			dev_name(dev->parent));
+ 	list_add_tail(&dev->power.entry, &dpm_list);
+@@ -511,7 +511,11 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
+ 	dpm_wait(dev->parent, async);
+ 	device_lock(dev);
+ 
+-	dev->power.in_suspend = false;
++	/*
++	 * This is a fib.  But we'll allow new children to be added below
++	 * a resumed device, even if the device hasn't been completed yet.
++	 */
++	dev->power.is_prepared = false;
+ 
+ 	if (dev->pwr_domain) {
+ 		pm_dev_dbg(dev, state, "power domain ");
+@@ -670,7 +674,7 @@ void dpm_complete(pm_message_t state)
+ 		struct device *dev = to_device(dpm_prepared_list.prev);
+ 
+ 		get_device(dev);
+-		dev->power.in_suspend = false;
++		dev->power.is_prepared = false;
+ 		list_move(&dev->power.entry, &list);
+ 		mutex_unlock(&dpm_list_mtx);
+ 
+@@ -1042,7 +1046,7 @@ int dpm_prepare(pm_message_t state)
+ 			put_device(dev);
+ 			break;
+ 		}
+-		dev->power.in_suspend = true;
++		dev->power.is_prepared = true;
+ 		if (!list_empty(&dev->power.entry))
+ 			list_move_tail(&dev->power.entry, &dpm_prepared_list);
+ 		put_device(dev);
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index e35a17687c05..aa3cc465a601 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -375,7 +375,7 @@ static int usb_unbind_interface(struct device *dev)
+ 		 * Just re-enable it without affecting the endpoint toggles.
+ 		 */
+ 		usb_enable_interface(udev, intf, false);
+-	} else if (!error && !intf->dev.power.in_suspend) {
++	} else if (!error && !intf->dev.power.is_prepared) {
+ 		r = usb_set_interface(udev, intf->altsetting[0].
+ 				desc.bInterfaceNumber, 0);
+ 		if (r < 0)
+@@ -960,7 +960,7 @@ void usb_rebind_intf(struct usb_interface *intf)
+ 	}
+ 
+ 	/* Try to rebind the interface */
+-	if (!intf->dev.power.in_suspend) {
++	if (!intf->dev.power.is_prepared) {
+ 		intf->needs_binding = 0;
+ 		rc = device_attach(&intf->dev);
+ 		if (rc < 0)
+@@ -1107,7 +1107,7 @@ static int usb_resume_interface(struct usb_device *udev,
+ 	if (intf->condition == USB_INTERFACE_UNBOUND) {
+ 
+ 		/* Carry out a deferred switch to altsetting 0 */
+-		if (intf->needs_altsetting0 && !intf->dev.power.in_suspend) {
++		if (intf->needs_altsetting0 && !intf->dev.power.is_prepared) {
+ 			usb_set_interface(udev, intf->altsetting[0].
+ 					desc.bInterfaceNumber, 0);
+ 			intf->needs_altsetting0 = 0;
+diff --git a/include/linux/device.h b/include/linux/device.h
+index c66111affca9..553fd37b173b 100644
+--- a/include/linux/device.h
++++ b/include/linux/device.h
+@@ -654,13 +654,13 @@ static inline int device_is_registered(struct device *dev)
+ 
+ static inline void device_enable_async_suspend(struct device *dev)
+ {
+-	if (!dev->power.in_suspend)
++	if (!dev->power.is_prepared)
+ 		dev->power.async_suspend = true;
+ }
+ 
+ static inline void device_disable_async_suspend(struct device *dev)
+ {
+-	if (!dev->power.in_suspend)
++	if (!dev->power.is_prepared)
+ 		dev->power.async_suspend = false;
+ }
+ 
+diff --git a/include/linux/pm.h b/include/linux/pm.h
+index 3160648ccdda..cc536bd80984 100644
+--- a/include/linux/pm.h
++++ b/include/linux/pm.h
+@@ -425,7 +425,7 @@ struct dev_pm_info {
+ 	pm_message_t		power_state;
+ 	unsigned int		can_wakeup:1;
+ 	unsigned int		async_suspend:1;
+-	unsigned int		in_suspend:1;	/* Owned by the PM core */
++	bool			is_prepared:1;	/* Owned by the PM core */
+ 	spinlock_t		lock;
+ #ifdef CONFIG_PM_SLEEP
+ 	struct list_head	entry;

commit 664a51a81f6ba39db30cd7b7de61577ca0b2d20d
+Author: Alan Stern 
+Date:   Wed Jun 15 16:31:37 2011 -0400
+
+    USB: deprecate g_file_storage
+    
+    This patch (as1471) deprecates the File-backed Storage Driver and
+    schedules its replacement for the 3.8 kernel release (about two years
+    from now).  Users are advised to switch to the Mass Storage Gadget
+    instead.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
+index 1a9446b59153..21f331d0473d 100644
+--- a/Documentation/feature-removal-schedule.txt
++++ b/Documentation/feature-removal-schedule.txt
+@@ -600,3 +600,10 @@ Why:	Superseded by the UVCIOC_CTRL_QUERY ioctl.
+ Who:	Laurent Pinchart 
+ 
+ ----------------------------
++
++What:	g_file_storage driver
++When:	3.8
++Why:	This driver has been superseded by g_mass_storage.
++Who:	Alan Stern 
++
++----------------------------
+diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
+index 9468adbe42bb..22e43fffbcc0 100644
+--- a/drivers/usb/gadget/Kconfig
++++ b/drivers/usb/gadget/Kconfig
+@@ -877,7 +877,7 @@ config USB_FUNCTIONFS_GENERIC
+ 	  no Ethernet interface.
+ 
+ config USB_FILE_STORAGE
+-	tristate "File-backed Storage Gadget"
++	tristate "File-backed Storage Gadget (DEPRECATED)"
+ 	depends on BLOCK
+ 	help
+ 	  The File-backed Storage Gadget acts as a USB Mass Storage
+@@ -888,6 +888,9 @@ config USB_FILE_STORAGE
+ 	  Say "y" to link the driver statically, or "m" to build a
+ 	  dynamically linked module called "g_file_storage".
+ 
++	  NOTE: This driver is deprecated.  Its replacement is the
++	  Mass Storage Gadget.
++
+ config USB_FILE_STORAGE_TEST
+ 	bool "File-backed Storage Gadget testing version"
+ 	depends on USB_FILE_STORAGE
+@@ -907,14 +910,11 @@ config USB_MASS_STORAGE
+ 	  device (in much the same way as the "loop" device driver),
+ 	  specified as a module parameter or sysfs option.
+ 
+-	  This is heavily based on File-backed Storage Gadget and in most
+-	  cases you will want to use FSG instead.  This gadget is mostly
+-	  here to test the functionality of the Mass Storage Function
+-	  which may be used with composite framework.
++	  This driver is an updated replacement for the deprecated
++	  File-backed Storage Gadget (g_file_storage).
+ 
+ 	  Say "y" to link the driver statically, or "m" to build
+-	  a dynamically linked module called "g_mass_storage".  If unsure,
+-	  consider File-backed Storage Gadget.
++	  a dynamically linked module called "g_mass_storage".
+ 
+ config USB_G_SERIAL
+ 	tristate "Serial Gadget (with CDC ACM and CDC OBEX support)"
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index 0360f56221ea..83bee30cdb94 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -3486,6 +3486,8 @@ static int __init fsg_bind(struct usb_gadget *gadget)
+ 	}
+ 
+ 	INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
++	INFO(fsg, "NOTE: This driver is deprecated.  "
++			"Consider using g_mass_storage instead.\n");
+ 	INFO(fsg, "Number of LUNs=%d\n", fsg->nluns);
+ 
+ 	pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);

commit 0af212ba8f123c2eba151af7726c34a50b127962
+Author: Alan Stern 
+Date:   Wed Jun 15 16:27:43 2011 -0400
+
+    USB: don't let errors prevent system sleep
+    
+    This patch (as1464) implements the recommended policy that most errors
+    during suspend or hibernation should not prevent the system from going
+    to sleep.  In particular, failure to suspend a USB driver or a USB
+    device should not prevent the sleep from succeeding:
+    
+    Failure to suspend a device won't matter, because the device will
+    automatically go into suspend mode when the USB bus stops carrying
+    packets.  (This might be less true for USB-3.0 devices, but let's not
+    worry about them now.)
+    
+    Failure of a driver to suspend might lead to trouble later on when the
+    system wakes up, but it isn't sufficient reason to prevent the system
+    from going to sleep.
+    
+    Signed-off-by: Alan Stern 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index e35a17687c05..81add81ab040 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1187,13 +1187,22 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 		for (i = n - 1; i >= 0; --i) {
+ 			intf = udev->actconfig->interface[i];
+ 			status = usb_suspend_interface(udev, intf, msg);
++
++			/* Ignore errors during system sleep transitions */
++			if (!(msg.event & PM_EVENT_AUTO))
++				status = 0;
+ 			if (status != 0)
+ 				break;
+ 		}
+ 	}
+-	if (status == 0)
++	if (status == 0) {
+ 		status = usb_suspend_device(udev, msg);
+ 
++		/* Again, ignore errors during system sleep transitions */
++		if (!(msg.event & PM_EVENT_AUTO))
++			status = 0;
++	}
++
+ 	/* If the suspend failed, resume interfaces that did get suspended */
+ 	if (status != 0) {
+ 		msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME);

commit cbb330045e5df8f665ac60227ff898421fc8fb92
+Author: Alan Stern 
+Date:   Wed Jun 15 16:29:16 2011 -0400
+
+    USB: don't let the hub driver prevent system sleep
+    
+    This patch (as1465) continues implementation of the policy that errors
+    during suspend or hibernation should not prevent the system from going
+    to sleep.
+    
+    In this case, failure to turn on the Suspend feature for a hub port
+    shouldn't be reported as an error.  There are situations where this
+    does actually occur (such as when the device plugged into that port
+    was disconnected in the recent past), and it turns out to be harmless.
+    There's no reason for it to prevent a system sleep.
+    
+    Also, don't allow the hub driver to fail a system suspend if the
+    downstream ports aren't all suspended.  This is also harmless (and
+    should never happen, given the change mentioned above); printing a
+    warning message in the kernel log is all we really need to do.
+    
+    Signed-off-by: Alan Stern 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 90ae1753dda1..c2ac08755f27 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2362,6 +2362,10 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ 				USB_DEVICE_REMOTE_WAKEUP, 0,
+ 				NULL, 0,
+ 				USB_CTRL_SET_TIMEOUT);
++
++		/* System sleep transitions should never fail */
++		if (!(msg.event & PM_EVENT_AUTO))
++			status = 0;
+ 	} else {
+ 		/* device has up to 10 msec to fully suspend */
+ 		dev_dbg(&udev->dev, "usb %ssuspend\n",
+@@ -2611,16 +2615,15 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+ 	struct usb_device	*hdev = hub->hdev;
+ 	unsigned		port1;
+ 
+-	/* fail if children aren't already suspended */
++	/* Warn if children aren't already suspended */
+ 	for (port1 = 1; port1 <= hdev->maxchild; port1++) {
+ 		struct usb_device	*udev;
+ 
+ 		udev = hdev->children [port1-1];
+ 		if (udev && udev->can_submit) {
+-			if (!(msg.event & PM_EVENT_AUTO))
+-				dev_dbg(&intf->dev, "port %d nyet suspended\n",
+-						port1);
+-			return -EBUSY;
++			dev_warn(&intf->dev, "port %d nyet suspended\n", port1);
++			if (msg.event & PM_EVENT_AUTO)
++				return -EBUSY;
+ 		}
+ 	}
+ 

commit 578333ab95f70db13951d30a9ad6b565b61639a9
+Author: Alan Stern 
+Date:   Wed Jun 15 16:32:46 2011 -0400
+
+    USB: change maintainership of ohci-hcd and ehci-hcd
+    
+    Following the loss of David Brownell, I volunteer to maintain the
+    ohci-hcd and ehci-hcd drivers.  This patch (as1472) makes it official.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index e50fc6eb99e0..4307673415f7 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -6430,8 +6430,9 @@ S:	Maintained
+ F:	drivers/usb/misc/rio500*
+ 
+ USB EHCI DRIVER
++M:	Alan Stern 
+ L:	linux-usb@vger.kernel.org
+-S:	Orphan
++S:	Maintained
+ F:	Documentation/usb/ehci.txt
+ F:	drivers/usb/host/ehci*
+ 
+@@ -6490,8 +6491,9 @@ S:	Maintained
+ F:	sound/usb/midi.*
+ 
+ USB OHCI DRIVER
++M:	Alan Stern 
+ L:	linux-usb@vger.kernel.org
+-S:	Orphan
++S:	Maintained
+ F:	Documentation/usb/ohci.txt
+ F:	drivers/usb/host/ohci*
+ 
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index b435ed67dd5c..f8030ee928e8 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1,4 +1,8 @@
+ /*
++ * Enhanced Host Controller Interface (EHCI) driver for USB.
++ *
++ * Maintainer: Alan Stern 
++ *
+  * Copyright (c) 2000-2004 by David Brownell
+  *
+  * This program is free software; you can redistribute it and/or modify it
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index 9aa10bdf3918..f9cf3f04b742 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -1,5 +1,7 @@
+ /*
+- * OHCI HCD (Host Controller Driver) for USB.
++ * Open Host Controller Interface (OHCI) driver for USB.
++ *
++ * Maintainer: Alan Stern 
+  *
+  * (C) Copyright 1999 Roman Weissgaerber 
+  * (C) Copyright 2000-2004 David Brownell 

commit 97b2f900335befbf6c4323ea6fd560ea5df4d154
+Author: Alan Stern 
+Date:   Tue Jun 7 11:31:05 2011 -0400
+
+    USB: CONFIG_USB_GADGET_DUALSPEED is not user-configurable
+    
+    This patch (as1468) changes the Kconfig definition for
+    USB_GADGET_DUALSPEED.  This option is determined entirely by which
+    device controller drivers are to be built, through Select statements;
+    it does not need to be (and should not be) configurable by the user.
+    
+    Also, the "default n" line is superfluous -- everything defaults to N.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Felipe Balbi 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
+index 58456d1aec21..029e288805b6 100644
+--- a/drivers/usb/gadget/Kconfig
++++ b/drivers/usb/gadget/Kconfig
+@@ -632,13 +632,10 @@ config USB_DUMMY_HCD
+ 
+ endchoice
+ 
++# Selected by UDC drivers that support high-speed operation.
+ config USB_GADGET_DUALSPEED
+ 	bool
+ 	depends on USB_GADGET
+-	default n
+-	help
+-	  Means that gadget drivers should include extra descriptors
+-	  and code to handle dual-speed controllers.
+ 
+ #
+ # USB Gadget Drivers

commit c5c69f3f0dcf9b569c8f3ad67f3af92cfcedac43
+Author: Alan Stern 
+Date:   Tue Jun 7 11:33:01 2011 -0400
+
+    USB: dummy-hcd needs the has_tt flag
+    
+    Like with other host controllers capable of operating at both high
+    speed and full speed, we need to indicate that the emulated controller
+    presented by dummy-hcd has this ability.  Otherwise usbcore will not
+    accept full-speed gadgets under dummy-hcd.  This patch (as1469) sets
+    the appropriate has_tt flag.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index 61ff927928ab..d3dcabc1a5fc 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -1906,6 +1906,7 @@ static int dummy_hcd_probe(struct platform_device *pdev)
+ 	if (!hcd)
+ 		return -ENOMEM;
+ 	the_controller = hcd_to_dummy (hcd);
++	hcd->has_tt = 1;
+ 
+ 	retval = usb_add_hcd(hcd, 0, 0);
+ 	if (retval != 0) {

commit 21c13a4f7bc185552c4b402b792c3bbb9aa69df0
+Author: Alan Stern 
+Date:   Tue Jun 7 11:35:52 2011 -0400
+
+    usb-storage: redo incorrect reads
+    
+    Some USB mass-storage devices have bugs that cause them not to handle
+    the first READ(10) command they receive correctly.  The Corsair
+    Padlock v2 returns completely bogus data for its first read (possibly
+    it returns the data in encrypted form even though the device is
+    supposed to be unlocked).  The Feiya SD/SDHC card reader fails to
+    complete the first READ(10) command after it is plugged in or after a
+    new card is inserted, returning a status code that indicates it thinks
+    the command was invalid, which prevents the kernel from retrying the
+    read.
+    
+    Since the first read of a new device or a new medium is for the
+    partition sector, the kernel is unable to retrieve the device's
+    partition table.  Users have to manually issue an "hdparm -z" or
+    "blockdev --rereadpt" command before they can access the device.
+    
+    This patch (as1470) works around the problem.  It adds a new quirk
+    flag, US_FL_INVALID_READ10, indicating that the first READ(10) should
+    always be retried immediately, as should any failing READ(10) commands
+    (provided the preceding READ(10) command succeeded, to avoid getting
+    stuck in a loop).  The patch also adds appropriate unusual_devs
+    entries containing the new flag.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Sven Geggus 
+    Tested-by: Paul Hartman 
+    CC: Matthew Dharm 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
+index d9a203b058f1..fd248a318211 100644
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -2598,6 +2598,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
+ 					unlock ejectable media);
+ 				m = MAX_SECTORS_64 (don't transfer more
+ 					than 64 sectors = 32 KB at a time);
++				n = INITIAL_READ10 (force a retry of the
++					initial READ(10) command);
+ 				o = CAPACITY_OK (accept the capacity
+ 					reported by the device);
+ 				r = IGNORE_RESIDUE (the device reports
+diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+index 00418995d8e9..e8ae21b2d387 100644
+--- a/drivers/usb/storage/transport.c
++++ b/drivers/usb/storage/transport.c
+@@ -819,6 +819,35 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 		}
+ 	}
+ 
++	/*
++	 * Some devices don't work or return incorrect data the first
++	 * time they get a READ(10) command, or for the first READ(10)
++	 * after a media change.  If the INITIAL_READ10 flag is set,
++	 * keep track of whether READ(10) commands succeed.  If the
++	 * previous one succeeded and this one failed, set the REDO_READ10
++	 * flag to force a retry.
++	 */
++	if (unlikely((us->fflags & US_FL_INITIAL_READ10) &&
++			srb->cmnd[0] == READ_10)) {
++		if (srb->result == SAM_STAT_GOOD) {
++			set_bit(US_FLIDX_READ10_WORKED, &us->dflags);
++		} else if (test_bit(US_FLIDX_READ10_WORKED, &us->dflags)) {
++			clear_bit(US_FLIDX_READ10_WORKED, &us->dflags);
++			set_bit(US_FLIDX_REDO_READ10, &us->dflags);
++		}
++
++		/*
++		 * Next, if the REDO_READ10 flag is set, return a result
++		 * code that will cause the SCSI core to retry the READ(10)
++		 * command immediately.
++		 */
++		if (test_bit(US_FLIDX_REDO_READ10, &us->dflags)) {
++			clear_bit(US_FLIDX_REDO_READ10, &us->dflags);
++			srb->result = DID_IMM_RETRY << 16;
++			srb->sense_buffer[0] = 0;
++		}
++	}
++
+ 	/* Did we transfer less than the minimum amount required? */
+ 	if ((srb->result == SAM_STAT_GOOD || srb->sense_buffer[2] == 0) &&
+ 			scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow)
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index c1602b8c5594..ccff3483eebc 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -1114,6 +1114,16 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
+ 		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ 		US_FL_FIX_CAPACITY ),
+ 
++/* Reported by Paul Hartman 
++ * This card reader returns "Illegal Request, Logical Block Address
++ * Out of Range" for the first READ(10) after a new card is inserted.
++ */
++UNUSUAL_DEV(  0x090c, 0x6000, 0x0100, 0x0100,
++		"Feiya",
++		"SD/SDHC Card Reader",
++		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
++		US_FL_INITIAL_READ10 ),
++
+ /* This Pentax still camera is not conformant
+  * to the USB storage specification: -
+  * - It does not like the INQUIRY command. So we must handle this command
+@@ -1888,6 +1898,15 @@ UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200,
+ 		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ 		US_FL_NO_READ_DISC_INFO ),
+ 
++/* Reported by Sven Geggus 
++ * This encrypted pen drive returns bogus data for the initial READ(10).
++ */
++UNUSUAL_DEV(  0x1b1c, 0x1ab5, 0x0200, 0x0200,
++		"Corsair",
++		"Padlock v2",
++		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
++		US_FL_INITIAL_READ10 ),
++
+ /* Patch by Richard Sch?tz 
+  * This external hard drive enclosure uses a JMicron chip which
+  * needs the US_FL_IGNORE_RESIDUE flag to work properly. */
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 5ee7ac42e08f..0ca095820f3e 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -440,7 +440,8 @@ static void adjust_quirks(struct us_data *us)
+ 			US_FL_NOT_LOCKABLE | US_FL_MAX_SECTORS_64 |
+ 			US_FL_CAPACITY_OK | US_FL_IGNORE_RESIDUE |
+ 			US_FL_SINGLE_LUN | US_FL_NO_WP_DETECT |
+-			US_FL_NO_READ_DISC_INFO | US_FL_NO_READ_CAPACITY_16);
++			US_FL_NO_READ_DISC_INFO | US_FL_NO_READ_CAPACITY_16 |
++			US_FL_INITIAL_READ10);
+ 
+ 	p = quirks;
+ 	while (*p) {
+@@ -490,6 +491,9 @@ static void adjust_quirks(struct us_data *us)
+ 		case 'm':
+ 			f |= US_FL_MAX_SECTORS_64;
+ 			break;
++		case 'n':
++			f |= US_FL_INITIAL_READ10;
++			break;
+ 		case 'o':
+ 			f |= US_FL_CAPACITY_OK;
+ 			break;
+@@ -953,6 +957,13 @@ int usb_stor_probe2(struct us_data *us)
+ 	if (result)
+ 		goto BadDevice;
+ 
++	/*
++	 * If the device returns invalid data for the first READ(10)
++	 * command, indicate the command should be retried.
++	 */
++	if (us->fflags & US_FL_INITIAL_READ10)
++		set_bit(US_FLIDX_REDO_READ10, &us->dflags);
++
+ 	/* Acquire all the other resources and add the host */
+ 	result = usb_stor_acquire_resources(us);
+ 	if (result)
+diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
+index 89d3bfff98df..7b0f2113632e 100644
+--- a/drivers/usb/storage/usb.h
++++ b/drivers/usb/storage/usb.h
+@@ -73,6 +73,8 @@ struct us_unusual_dev {
+ #define US_FLIDX_RESETTING	4	/* device reset in progress */
+ #define US_FLIDX_TIMED_OUT	5	/* SCSI midlayer timed out  */
+ #define US_FLIDX_DONT_SCAN	6	/* don't scan (disconnect)  */
++#define US_FLIDX_REDO_READ10	7	/* redo READ(10) command    */
++#define US_FLIDX_READ10_WORKED	8	/* previous READ(10) succeeded */
+ 
+ #define USB_STOR_STRING_LEN 32
+ 
+diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
+index 71693d4a4fe1..17df3600bcef 100644
+--- a/include/linux/usb_usual.h
++++ b/include/linux/usb_usual.h
+@@ -62,7 +62,9 @@
+ 	US_FLAG(NO_READ_DISC_INFO,	0x00040000)		\
+ 		/* cannot handle READ_DISC_INFO */		\
+ 	US_FLAG(NO_READ_CAPACITY_16,	0x00080000)		\
+-		/* cannot handle READ_CAPACITY_16 */
++		/* cannot handle READ_CAPACITY_16 */		\
++	US_FLAG(INITIAL_READ10,	0x00100000)			\
++		/* Initial READ(10) (and others) must be retried */
+ 
+ #define US_FLAG(name, value)	US_FL_##name = value ,
+ enum { US_DO_ALL_FLAGS };

commit bab1ff1bda27e654dfd382a1fbdfcda1f7ed0a37
+Author: Alan Stern 
+Date:   Wed May 18 10:44:50 2011 +0200
+
+    USB: UHCI: Use ACCESS_ONCE rather than using a full compiler barrier
+    
+    This patch (as1462) updates the special accessor functions defined in
+    uhci-hcd.h.  Rather than using a full compiler barrier, all we really
+    need is the ACCESS_ONCE() mechanism, because the idea is to force the
+    compiler to store a fixed copy of a possibly changing value.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index 10b68a846f65..0deeab6c9e56 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -168,12 +168,7 @@ struct uhci_qh {
+  * We need a special accessor for the element pointer because it is
+  * subject to asynchronous updates by the controller.
+  */
+-static inline __le32 qh_element(struct uhci_qh *qh) {
+-	__le32 element = qh->element;
+-
+-	barrier();
+-	return element;
+-}
++#define qh_element(qh)		ACCESS_ONCE((qh)->element)
+ 
+ #define LINK_TO_QH(qh)		(UHCI_PTR_QH | cpu_to_le32((qh)->dma_handle))
+ 
+@@ -263,12 +258,7 @@ struct uhci_td {
+  * We need a special accessor for the control/status word because it is
+  * subject to asynchronous updates by the controller.
+  */
+-static inline u32 td_status(struct uhci_td *td) {
+-	__le32 status = td->status;
+-
+-	barrier();
+-	return le32_to_cpu(status);
+-}
++#define td_status(td)		le32_to_cpu(ACCESS_ONCE((td)->status))
+ 
+ #define LINK_TO_TD(td)		(cpu_to_le32((td)->dma_handle))
+ 

commit 69fff59de4d844f8b4c2454c3c23d32b69dcbfd7
+Author: Alan Stern 
+Date:   Tue May 17 17:27:12 2011 -0400
+
+    USB: remove remaining usages of hcd->state from usbcore and fix regression
+    
+    This patch (as1467) removes the last usages of hcd->state from
+    usbcore.  We no longer check to see if an interrupt handler finds that
+    a controller has died; instead we rely on host controller drivers to
+    make an explicit call to usb_hc_died().
+    
+    This fixes a regression introduced by commit
+    9b37596a2e860404503a3f2a6513db60c296bfdc (USB: move usbcore away from
+    hcd->state).  It used to be that when a controller shared an IRQ with
+    another device and an interrupt arrived while hcd->state was set to
+    HC_STATE_HALT, the interrupt handler would be skipped.  The commit
+    removed that test; as a result the current code doesn't skip calling
+    the handler and ends up believing the controller has died, even though
+    it's only temporarily stopped.  The solution is to ignore HC_STATE_HALT
+    following the handler's return.
+    
+    As a consequence of this change, several of the host controller
+    drivers need to be modified.  They can no longer implicitly rely on
+    usbcore realizing that a controller has died because of hcd->state.
+    The patch adds calls to usb_hc_died() in the appropriate places.
+    
+    The patch also changes a few of the interrupt handlers.  They don't
+    expect to be called when hcd->state is equal to HC_STATE_HALT, even if
+    the controller is still alive.  Early returns were added to avoid any
+    confusion.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Manuel Lauss 
+    CC: Rodolfo Giometti 
+    CC: Olav Kongas 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 10936ba9c42b..ace9f8442e5d 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -986,7 +986,7 @@ static int register_root_hub(struct usb_hcd *hcd)
+ 		spin_unlock_irq (&hcd_root_hub_lock);
+ 
+ 		/* Did the HC die before the root hub was registered? */
+-		if (HCD_DEAD(hcd) || hcd->state == HC_STATE_HALT)
++		if (HCD_DEAD(hcd))
+ 			usb_hc_died (hcd);	/* This time clean up */
+ 	}
+ 
+@@ -2128,9 +2128,6 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)
+ 		set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+ 		if (hcd->shared_hcd)
+ 			set_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags);
+-
+-		if (unlikely(hcd->state == HC_STATE_HALT))
+-			usb_hc_died(hcd);
+ 		rc = IRQ_HANDLED;
+ 	}
+ 
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index c5719cd258c3..b435ed67dd5c 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -777,8 +777,9 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 		goto dead;
+ 	}
+ 
++	/* Shared IRQ? */
+ 	masked_status = status & INTR_MASK;
+-	if (!masked_status) {		/* irq sharing? */
++	if (!masked_status || unlikely(hcd->state == HC_STATE_HALT)) {
+ 		spin_unlock(&ehci->lock);
+ 		return IRQ_NONE;
+ 	}
+@@ -873,6 +874,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ dead:
+ 		ehci_reset(ehci);
+ 		ehci_writel(ehci, 0, &ehci->regs->configured_flag);
++		usb_hc_died(hcd);
+ 		/* generic layer kills/unlinks all urbs, then
+ 		 * uses ehci_stop to clean up the rest
+ 		 */
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index a7408d88fda0..6c9fbe352f73 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -471,8 +471,10 @@ static int enable_periodic (struct ehci_hcd *ehci)
+ 	 */
+ 	status = handshake_on_error_set_halt(ehci, &ehci->regs->status,
+ 					     STS_PSS, 0, 9 * 125);
+-	if (status)
++	if (status) {
++		usb_hc_died(ehci_to_hcd(ehci));
+ 		return status;
++	}
+ 
+ 	cmd = ehci_readl(ehci, &ehci->regs->command) | CMD_PSE;
+ 	ehci_writel(ehci, cmd, &ehci->regs->command);
+@@ -510,8 +512,10 @@ static int disable_periodic (struct ehci_hcd *ehci)
+ 	 */
+ 	status = handshake_on_error_set_halt(ehci, &ehci->regs->status,
+ 					     STS_PSS, STS_PSS, 9 * 125);
+-	if (status)
++	if (status) {
++		usb_hc_died(ehci_to_hcd(ehci));
+ 		return status;
++	}
+ 
+ 	cmd = ehci_readl(ehci, &ehci->regs->command) & ~CMD_PSE;
+ 	ehci_writel(ehci, cmd, &ehci->regs->command);
+diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
+index c0e22f26da19..baae4ccd16ac 100644
+--- a/drivers/usb/host/isp116x-hcd.c
++++ b/drivers/usb/host/isp116x-hcd.c
+@@ -612,6 +612,7 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd)
+ 			/* IRQ's are off, we do no DMA,
+ 			   perfectly ready to die ... */
+ 			hcd->state = HC_STATE_HALT;
++			usb_hc_died(hcd);
+ 			ret = IRQ_HANDLED;
+ 			goto done;
+ 		}
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index 8c8dc6559ac7..9aa10bdf3918 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -764,6 +764,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
+ 	if (ints == ~(u32)0) {
+ 		disable (ohci);
+ 		ohci_dbg (ohci, "device removed!\n");
++		usb_hc_died(hcd);
+ 		return IRQ_HANDLED;
+ 	}
+ 
+@@ -771,7 +772,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
+ 	ints &= ohci_readl(ohci, ®s->intrenable);
+ 
+ 	/* interrupt for some other device? */
+-	if (ints == 0)
++	if (ints == 0 || unlikely(hcd->state == HC_STATE_HALT))
+ 		return IRQ_NOTMINE;
+ 
+ 	if (ints & OHCI_INTR_UE) {
+@@ -788,6 +789,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
+ 		} else {
+ 			disable (ohci);
+ 			ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n");
++			usb_hc_died(hcd);
+ 		}
+ 
+ 		ohci_dump (ohci, 1);
+diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
+index 4a771f6cc822..5fbe997dc6df 100644
+--- a/drivers/usb/host/oxu210hp-hcd.c
++++ b/drivers/usb/host/oxu210hp-hcd.c
+@@ -1884,6 +1884,7 @@ static int enable_periodic(struct oxu_hcd *oxu)
+ 	status = handshake(oxu, &oxu->regs->status, STS_PSS, 0, 9 * 125);
+ 	if (status != 0) {
+ 		oxu_to_hcd(oxu)->state = HC_STATE_HALT;
++		usb_hc_died(oxu_to_hcd(oxu));
+ 		return status;
+ 	}
+ 
+@@ -1909,6 +1910,7 @@ static int disable_periodic(struct oxu_hcd *oxu)
+ 	status = handshake(oxu, &oxu->regs->status, STS_PSS, STS_PSS, 9 * 125);
+ 	if (status != 0) {
+ 		oxu_to_hcd(oxu)->state = HC_STATE_HALT;
++		usb_hc_died(oxu_to_hcd(oxu));
+ 		return status;
+ 	}
+ 
+@@ -2449,8 +2451,9 @@ static irqreturn_t oxu210_hcd_irq(struct usb_hcd *hcd)
+ 		goto dead;
+ 	}
+ 
++	/* Shared IRQ? */
+ 	status &= INTR_MASK;
+-	if (!status) {			/* irq sharing? */
++	if (!status || unlikely(hcd->state == HC_STATE_HALT)) {
+ 		spin_unlock(&oxu->lock);
+ 		return IRQ_NONE;
+ 	}
+@@ -2516,6 +2519,7 @@ static irqreturn_t oxu210_hcd_irq(struct usb_hcd *hcd)
+ dead:
+ 			ehci_reset(oxu);
+ 			writel(0, &oxu->regs->configured_flag);
++			usb_hc_died(hcd);
+ 			/* generic layer kills/unlinks all urbs, then
+ 			 * uses oxu_stop to clean up the rest
+ 			 */

commit a8e62dd6d91f3bc3687abbb26227e5fc39c4829c
+Author: Alan Stern 
+Date:   Tue May 17 14:45:48 2011 -0400
+
+    usb-storage: fix up the unusual_realtek device list
+    
+    This patch (as1461) fixes the unusual_devs entries for the Realtek USB
+    card reader.  They should be ordered by PID, and they should not
+    override the Subclass and Protocol values provided by the device.
+    Otherwise a notification about unnecessary entries gets printed in the
+    kernel log during probing.
+    
+    Signed-off-by: Alan Stern 
+    Tested-By: Tony Vroon 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_realtek.h b/drivers/usb/storage/unusual_realtek.h
+index 3236e0328516..e41f50c95ed4 100644
+--- a/drivers/usb/storage/unusual_realtek.h
++++ b/drivers/usb/storage/unusual_realtek.h
+@@ -23,19 +23,19 @@
+ #if defined(CONFIG_USB_STORAGE_REALTEK) || \
+ 		defined(CONFIG_USB_STORAGE_REALTEK_MODULE)
+ 
+-UNUSUAL_DEV(0x0bda, 0x0159, 0x0000, 0x9999,
++UNUSUAL_DEV(0x0bda, 0x0138, 0x0000, 0x9999,
+ 		"Realtek",
+ 		"USB Card Reader",
+-		USB_SC_SCSI, USB_PR_BULK, init_realtek_cr, 0),
++		USB_SC_DEVICE, USB_PR_DEVICE, init_realtek_cr, 0),
+ 
+ UNUSUAL_DEV(0x0bda, 0x0158, 0x0000, 0x9999,
+ 		"Realtek",
+ 		"USB Card Reader",
+-		USB_SC_SCSI, USB_PR_BULK, init_realtek_cr, 0),
++		USB_SC_DEVICE, USB_PR_DEVICE, init_realtek_cr, 0),
+ 
+-UNUSUAL_DEV(0x0bda, 0x0138, 0x0000, 0x9999,
++UNUSUAL_DEV(0x0bda, 0x0159, 0x0000, 0x9999,
+ 		"Realtek",
+ 		"USB Card Reader",
+-		USB_SC_SCSI, USB_PR_BULK, init_realtek_cr, 0),
++		USB_SC_DEVICE, USB_PR_DEVICE, init_realtek_cr, 0),
+ 
+ #endif  /* defined(CONFIG_USB_STORAGE_REALTEK) || ... */

commit 1e12c910eed82da6971f1c0421a069c680faba2e
+Author: Alan Stern 
+Date:   Tue May 17 10:40:51 2011 -0400
+
+    EHCI: don't rescan interrupt QHs needlessly
+    
+    This patch (as1466) speeds up processing of ehci-hcd's periodic list.
+    The existing code will pointlessly rescan an interrupt endpoint queue
+    each time it encounters the queue's QH in the periodic list, which can
+    happen quite a few times if the endpoint's period is low.  On some
+    embedded systems, this useless overhead can waste so much time that
+    the driver falls hopelessly behind and loses events.
+    
+    The patch introduces a "periodic_stamp" variable, which gets
+    incremented each time scan_periodic() runs and each time the scan
+    advances to a new frame.  If the corresponding stamp in an interrupt
+    QH is equal to the current periodic_stamp, we assume the QH has
+    already been scanned and skip over it.  Otherwise we scan the QH as
+    usual, and if none of its URBs have completed then we store the
+    current periodic_stamp in the QH's stamp, preventing it from being
+    scanned again.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index a46d6a1388c9..5d6bc624c961 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -826,6 +826,7 @@ qh_make (
+ 				is_input, 0,
+ 				hb_mult(maxp) * max_packet(maxp)));
+ 		qh->start = NO_FRAME;
++		qh->stamp = ehci->periodic_stamp;
+ 
+ 		if (urb->dev->speed == USB_SPEED_HIGH) {
+ 			qh->c_usecs = 0;
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 1543c838b3d1..a7408d88fda0 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -2287,6 +2287,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 	}
+ 	clock &= mod - 1;
+ 	clock_frame = clock >> 3;
++	++ehci->periodic_stamp;
+ 
+ 	for (;;) {
+ 		union ehci_shadow	q, *q_p;
+@@ -2315,10 +2316,14 @@ scan_periodic (struct ehci_hcd *ehci)
+ 				temp.qh = qh_get (q.qh);
+ 				type = Q_NEXT_TYPE(ehci, q.qh->hw->hw_next);
+ 				q = q.qh->qh_next;
+-				modified = qh_completions (ehci, temp.qh);
+-				if (unlikely(list_empty(&temp.qh->qtd_list) ||
+-						temp.qh->needs_rescan))
+-					intr_deschedule (ehci, temp.qh);
++				if (temp.qh->stamp != ehci->periodic_stamp) {
++					modified = qh_completions(ehci, temp.qh);
++					if (!modified)
++						temp.qh->stamp = ehci->periodic_stamp;
++					if (unlikely(list_empty(&temp.qh->qtd_list) ||
++							temp.qh->needs_rescan))
++						intr_deschedule(ehci, temp.qh);
++				}
+ 				qh_put (temp.qh);
+ 				break;
+ 			case Q_TYPE_FSTN:
+@@ -2460,6 +2465,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 			if (ehci->clock_frame != clock_frame) {
+ 				free_cached_lists(ehci);
+ 				ehci->clock_frame = clock_frame;
++				++ehci->periodic_stamp;
+ 			}
+ 		} else {
+ 			now_uframe++;
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 829213423dea..f68e419cae87 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -118,6 +118,7 @@ struct ehci_hcd {			/* one per controller */
+ 	struct timer_list	watchdog;
+ 	unsigned long		actions;
+ 	unsigned		stamp;
++	unsigned		periodic_stamp;
+ 	unsigned		random_frame;
+ 	unsigned long		next_statechange;
+ 	ktime_t			last_periodic_enable;

commit 2b7aaf503d56216b847c8265421d2a7d9b42df3e
+Author: Alan Stern 
+Date:   Mon May 16 12:15:19 2011 -0400
+
+    OHCI: fix regression caused by nVidia shutdown workaround
+    
+    This patch (as1463) fixes a regression caused by commit
+    3df7169e73fc1d71a39cffeacc969f6840cdf52b (OHCI: work around for nVidia
+    shutdown problem).
+    
+    The original problem encountered by people using NVIDIA chipsets was
+    that USB devices were not turning off when the system shut down.  For
+    example, the LED on an optical mouse would remain on, draining a
+    laptop's battery.  The problem was caused by a bug in the chipset; an
+    OHCI controller in the Reset state would continue to drive a bus reset
+    signal even after system shutdown.  The workaround was to put the
+    controllers into the Suspend state instead.
+    
+    It turns out that later NVIDIA chipsets do not suffer from this bug.
+    Instead some have the opposite bug: If a system is shut down while an
+    OHCI controller is in the Suspend state, USB devices remain powered!
+    On other systems, shutting down with a Suspended controller causes the
+    system to reboot immediately.  Thus, working around the original bug
+    on some machines exposes other bugs on other machines.
+    
+    The best solution seems to be to limit the workaround to OHCI
+    controllers with a low-numbered PCI product ID.  I don't know exactly
+    at what point NVIDIA changed their chipsets; the value used here is a
+    guess.  So far it was worked out okay for all the people who have
+    tested it.
+    
+    This fixes Bugzilla #35032.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Andre "Osku" Schmidt 
+    Tested-by: Yury Siamashka 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index d84d6f0314f9..ad8166c681e2 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -181,10 +181,18 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd)
+  */
+ static int ohci_quirk_nvidia_shutdown(struct usb_hcd *hcd)
+ {
++	struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+ 	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+ 
+-	ohci->flags |= OHCI_QUIRK_SHUTDOWN;
+-	ohci_dbg(ohci, "enabled nVidia shutdown quirk\n");
++	/* Evidently nVidia fixed their later hardware; this is a guess at
++	 * the changeover point.
++	 */
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB		0x026d
++
++	if (pdev->device < PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB) {
++		ohci->flags |= OHCI_QUIRK_SHUTDOWN;
++		ohci_dbg(ohci, "enabled nVidia shutdown quirk\n");
++	}
+ 
+ 	return 0;
+ }

commit cee6a262550f53a13acfefbc1e3e5ff35c96182c
+Author: Alan Stern 
+Date:   Mon May 2 14:21:44 2011 -0400
+
+    USB: fix regression in usbip by setting has_tt flag
+    
+    This patch (as1460) fixes a regression in the usbip driver caused by
+    the new check for Transaction Translators in USB-2 hubs.  The root hub
+    registered by vhci_hcd needs to have the has_tt flag set, because it
+    can connect to low- and full-speed devices as well as high-speed
+    devices.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Nikola Ciprich 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c
+index 0f02a4b12ae4..5d0caa8648e2 100644
+--- a/drivers/staging/usbip/vhci_hcd.c
++++ b/drivers/staging/usbip/vhci_hcd.c
+@@ -1139,7 +1139,7 @@ static int vhci_hcd_probe(struct platform_device *pdev)
+ 		usbip_uerr("create hcd failed\n");
+ 		return -ENOMEM;
+ 	}
+-
++	hcd->has_tt = 1;
+ 
+ 	/* this is private data for vhci_hcd */
+ 	the_controller = hcd_to_vhci(hcd);

commit 869410f82cbbb1464772046d87de8d18a916e706
+Author: Alan Stern 
+Date:   Thu Apr 14 11:21:04 2011 -0400
+
+    USB: add queued-unlinks test case to usbtest driver
+    
+    This patch (as1452b) adds a new test case to the usbtest driver.  Test
+    24 exercises the unlink-from-queue pathways in the host.  It queues a
+    user-specified number of bulk-OUT URBs of user-specified size, unlinks
+    the fourth- and second-from-last URBs in the queue, and then waits to
+    see if all the URBs complete in the expected way (except of course
+    that the unlinked URBs might complete normally, if they weren't
+    unlinked soon enough).
+    
+    This new test has confirmed the existence of a bug in the ehci-hcd
+    driver, to be fixed by a separate patch.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
+index 388cc128072a..58a5685fb7d1 100644
+--- a/drivers/usb/misc/usbtest.c
++++ b/drivers/usb/misc/usbtest.c
+@@ -1195,6 +1195,104 @@ static int unlink_simple(struct usbtest_dev *dev, int pipe, int len)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++struct queued_ctx {
++	struct completion	complete;
++	atomic_t		pending;
++	unsigned		num;
++	int			status;
++	struct urb		**urbs;
++};
++
++static void unlink_queued_callback(struct urb *urb)
++{
++	int			status = urb->status;
++	struct queued_ctx	*ctx = urb->context;
++
++	if (ctx->status)
++		goto done;
++	if (urb == ctx->urbs[ctx->num - 4] || urb == ctx->urbs[ctx->num - 2]) {
++		if (status == -ECONNRESET)
++			goto done;
++		/* What error should we report if the URB completed normally? */
++	}
++	if (status != 0)
++		ctx->status = status;
++
++ done:
++	if (atomic_dec_and_test(&ctx->pending))
++		complete(&ctx->complete);
++}
++
++static int unlink_queued(struct usbtest_dev *dev, int pipe, unsigned num,
++		unsigned size)
++{
++	struct queued_ctx	ctx;
++	struct usb_device	*udev = testdev_to_usbdev(dev);
++	void			*buf;
++	dma_addr_t		buf_dma;
++	int			i;
++	int			retval = -ENOMEM;
++
++	init_completion(&ctx.complete);
++	atomic_set(&ctx.pending, 1);	/* One more than the actual value */
++	ctx.num = num;
++	ctx.status = 0;
++
++	buf = usb_alloc_coherent(udev, size, GFP_KERNEL, &buf_dma);
++	if (!buf)
++		return retval;
++	memset(buf, 0, size);
++
++	/* Allocate and init the urbs we'll queue */
++	ctx.urbs = kcalloc(num, sizeof(struct urb *), GFP_KERNEL);
++	if (!ctx.urbs)
++		goto free_buf;
++	for (i = 0; i < num; i++) {
++		ctx.urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
++		if (!ctx.urbs[i])
++			goto free_urbs;
++		usb_fill_bulk_urb(ctx.urbs[i], udev, pipe, buf, size,
++				unlink_queued_callback, &ctx);
++		ctx.urbs[i]->transfer_dma = buf_dma;
++		ctx.urbs[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
++	}
++
++	/* Submit all the URBs and then unlink URBs num - 4 and num - 2. */
++	for (i = 0; i < num; i++) {
++		atomic_inc(&ctx.pending);
++		retval = usb_submit_urb(ctx.urbs[i], GFP_KERNEL);
++		if (retval != 0) {
++			dev_err(&dev->intf->dev, "submit urbs[%d] fail %d\n",
++					i, retval);
++			atomic_dec(&ctx.pending);
++			ctx.status = retval;
++			break;
++		}
++	}
++	if (i == num) {
++		usb_unlink_urb(ctx.urbs[num - 4]);
++		usb_unlink_urb(ctx.urbs[num - 2]);
++	} else {
++		while (--i >= 0)
++			usb_unlink_urb(ctx.urbs[i]);
++	}
++
++	if (atomic_dec_and_test(&ctx.pending))		/* The extra count */
++		complete(&ctx.complete);
++	wait_for_completion(&ctx.complete);
++	retval = ctx.status;
++
++ free_urbs:
++	for (i = 0; i < num; i++)
++		usb_free_urb(ctx.urbs[i]);
++	kfree(ctx.urbs);
++ free_buf:
++	usb_free_coherent(udev, size, buf, buf_dma);
++	return retval;
++}
++
++/*-------------------------------------------------------------------------*/
++
+ static int verify_not_halted(struct usbtest_dev *tdev, int ep, struct urb *urb)
+ {
+ 	int	retval;
+@@ -1970,8 +2068,6 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
+ 				dev->in_iso_pipe, dev->iso_in, 0);
+ 		break;
+ 
+-	/* FIXME unlink from queue (ring with N urbs) */
+-
+ 	/* FIXME scatterlist cancel (needs helper thread) */
+ 
+ 	/* Tests for bulk I/O using DMA mapping by core and odd address */
+@@ -2064,6 +2160,26 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
+ 				dev->in_iso_pipe, dev->iso_in, 1);
+ 		break;
+ 
++	/* unlink URBs from a bulk-OUT queue */
++	case 24:
++		if (dev->out_pipe == 0 || !param->length || param->sglen < 4)
++			break;
++		retval = 0;
++		dev_info(&intf->dev, "TEST 17:  unlink from %d queues of "
++				"%d %d-byte writes\n",
++				param->iterations, param->sglen, param->length);
++		for (i = param->iterations; retval == 0 && i > 0; --i) {
++			retval = unlink_queued(dev, dev->out_pipe,
++						param->sglen, param->length);
++			if (retval) {
++				dev_err(&intf->dev,
++					"unlink queued writes failed %d, "
++					"iterations left %d\n", retval, i);
++				break;
++			}
++		}
++		break;
++
+ 	}
+ 	do_gettimeofday(¶m->duration);
+ 	param->duration.tv_sec -= start.tv_sec;

commit 6498d9db6d2dad4cf5deb2dd09e0816904f41ca5
+Author: Alan Stern 
+Date:   Thu Apr 28 10:45:24 2011 -0400
+
+    USB: documentation update for the pre_reset method
+    
+    This patch (as1459) updates the documentation for the pre_reset method
+    in struct usb_driver.  When a driver is notified of an impending
+    reset, it must cancel all outstanding I/O and not start any new I/O
+    until it has been notified that the reset is complete.
+    
+    As far as I know, most existing drivers that implement pre_reset do
+    this now.  The major exceptions appear to be the SpeedTouch and
+    CDC-WDM drivers.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/usb/callbacks.txt b/Documentation/usb/callbacks.txt
+index bfb36b34b79e..9e85846bdb98 100644
+--- a/Documentation/usb/callbacks.txt
++++ b/Documentation/usb/callbacks.txt
+@@ -95,9 +95,11 @@ pre_reset
+ 
+ int (*pre_reset)(struct usb_interface *intf);
+ 
+-Another driver or user space is triggering a reset on the device which
+-contains the interface passed as an argument. Cease IO and save any
+-device state you need to restore.
++A driver or user space is triggering a reset on the device which
++contains the interface passed as an argument. Cease IO, wait for all
++outstanding URBs to complete, and save any device state you need to
++restore.  No more URBs may be submitted until the post_reset method
++is called.
+ 
+ If you need to allocate memory here, use GFP_NOIO or GFP_ATOMIC, if you
+ are in atomic context.
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 65f78ca5d88e..73c7df489607 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -806,8 +806,10 @@ struct usbdrv_wrap {
+  * @resume: Called when the device is being resumed by the system.
+  * @reset_resume: Called when the suspended device has been reset instead
+  *	of being resumed.
+- * @pre_reset: Called by usb_reset_device() when the device
+- *	is about to be reset.
++ * @pre_reset: Called by usb_reset_device() when the device is about to be
++ *	reset.  This routine must not return until the driver has no active
++ *	URBs for the device, and no more URBs may be submitted until the
++ *	post_reset method is called.
+  * @post_reset: Called by usb_reset_device() after the device
+  *	has been reset
+  * @id_table: USB drivers use ID table to support hotplugging.

commit 99083f16f04e050eab0059167b4980cd67e7aa5a
+Author: Alan Stern 
+Date:   Tue Apr 5 13:35:53 2011 -0400
+
+    USB: UHCI: don't try to revive a dead controller
+    
+    This patch (as1457) abandons the curious strategy of declaring a
+    controller dead following hibernation merely in order to reset and
+    then revive it.  The core no longer allow dead controllers to spring
+    back to life when the system resumes, so there's no reason to declare
+    a working controller temporarily dead.  Instead we do an explicit
+    reset.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 73db5569f57b..83344d688ff0 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -140,8 +140,6 @@ static void finish_reset(struct uhci_hcd *uhci)
+ 	uhci->rh_state = UHCI_RH_RESET;
+ 	uhci->is_stopped = UHCI_IS_STOPPED;
+ 	clear_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags);
+-
+-	uhci->dead = 0;		/* Full reset resurrects the controller */
+ }
+ 
+ /*
+@@ -837,16 +835,17 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
+ 	spin_lock_irq(&uhci->lock);
+ 
+ 	/* Make sure resume from hibernation re-enumerates everything */
+-	if (hibernated)
+-		uhci_hc_died(uhci);
++	if (hibernated) {
++		uhci_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr);
++		finish_reset(uhci);
++	}
+ 
+-	/* The firmware or a boot kernel may have changed the controller
+-	 * settings during a system wakeup.  Check it and reconfigure
+-	 * to avoid problems.
++	/* The firmware may have changed the controller settings during
++	 * a system wakeup.  Check it and reconfigure to avoid problems.
+ 	 */
+-	check_and_reset_hc(uhci);
+-
+-	/* If the controller was dead before, it's back alive now */
++	else {
++		check_and_reset_hc(uhci);
++	}
+ 	configure_hc(uhci);
+ 
+ 	/* Tell the core if the controller had to be reset */

commit 7d670a2ed770a3405a7edb1159e3fa9b3f43fe46
+Author: Alan Stern 
+Date:   Tue Apr 5 13:36:04 2011 -0400
+
+    USB: UHCI: remove uses of hcd->state
+    
+    This patch (as1456) removes all uses of hcd->state from the uhci-hcd
+    driver, as part of the overall strategy to eliminate hcd->state
+    completely.  Now when a controller dies we call usb_hc_died()
+    directly, instead of relying on the core interrupt handler to see that
+    hcd->state has changed to HC_STATE_HALT and make the call for us.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 4f65b14e5e08..73db5569f57b 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -139,7 +139,6 @@ static void finish_reset(struct uhci_hcd *uhci)
+ 	uhci->port_c_suspend = uhci->resuming_ports = 0;
+ 	uhci->rh_state = UHCI_RH_RESET;
+ 	uhci->is_stopped = UHCI_IS_STOPPED;
+-	uhci_to_hcd(uhci)->state = HC_STATE_HALT;
+ 	clear_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags);
+ 
+ 	uhci->dead = 0;		/* Full reset resurrects the controller */
+@@ -188,10 +187,6 @@ static void configure_hc(struct uhci_hcd *uhci)
+ 	outw(uhci->frame_number & UHCI_MAX_SOF_NUMBER,
+ 			uhci->io_addr + USBFRNUM);
+ 
+-	/* Mark controller as not halted before we enable interrupts */
+-	uhci_to_hcd(uhci)->state = HC_STATE_SUSPENDED;
+-	mb();
+-
+ 	/* Enable PIRQ */
+ 	pci_write_config_word(pdev, USBLEGSUP, USBLEGSUP_DEFAULT);
+ 
+@@ -360,7 +355,6 @@ __acquires(uhci->lock)
+ 
+ static void start_rh(struct uhci_hcd *uhci)
+ {
+-	uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;
+ 	uhci->is_stopped = 0;
+ 
+ 	/* Mark it configured and running with a 64-byte max packet.
+@@ -449,6 +443,7 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd)
+ 					lprintk(errbuf);
+ 				}
+ 				uhci_hc_died(uhci);
++				usb_hc_died(hcd);
+ 
+ 				/* Force a callback in case there are
+ 				 * pending unlinks */

commit ee81b3e086c907a3347b15ef219a24fc8bf900f6
+Author: Alan Stern 
+Date:   Fri Mar 25 11:46:27 2011 -0400
+
+    USB: g_file_storage: don't send padding when stall=n
+    
+    This patch (as1455) removes the extra padding sent by g_file_storage
+    and g_mass_storage when the gadget wants to send less data than
+    requested by the host and isn't allowed to halt the bulk-IN endpoint.
+    
+    Although the Bulk-Only Transport specification requires the padding to
+    be present, it isn't truly needed since the transfer will be terminated
+    by a short packet anyway.  Furthermore, many existing devices don't
+    bother to send any padding.
+    
+    Signed-off-by: Alan Stern 
+    Acked-By: Michal Nazarewicz 
+    CC: Roger Quadros 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
+index 125587ac5d0b..98d6b39061d2 100644
+--- a/drivers/usb/gadget/f_mass_storage.c
++++ b/drivers/usb/gadget/f_mass_storage.c
+@@ -1569,37 +1569,6 @@ static int wedge_bulk_in_endpoint(struct fsg_dev *fsg)
+ 	return rc;
+ }
+ 
+-static int pad_with_zeros(struct fsg_dev *fsg)
+-{
+-	struct fsg_buffhd	*bh = fsg->common->next_buffhd_to_fill;
+-	u32			nkeep = bh->inreq->length;
+-	u32			nsend;
+-	int			rc;
+-
+-	bh->state = BUF_STATE_EMPTY;		/* For the first iteration */
+-	fsg->common->usb_amount_left = nkeep + fsg->common->residue;
+-	while (fsg->common->usb_amount_left > 0) {
+-
+-		/* Wait for the next buffer to be free */
+-		while (bh->state != BUF_STATE_EMPTY) {
+-			rc = sleep_thread(fsg->common);
+-			if (rc)
+-				return rc;
+-		}
+-
+-		nsend = min(fsg->common->usb_amount_left, FSG_BUFLEN);
+-		memset(bh->buf + nkeep, 0, nsend - nkeep);
+-		bh->inreq->length = nsend;
+-		bh->inreq->zero = 0;
+-		start_transfer(fsg, fsg->bulk_in, bh->inreq,
+-			       &bh->inreq_busy, &bh->state);
+-		bh = fsg->common->next_buffhd_to_fill = bh->next;
+-		fsg->common->usb_amount_left -= nsend;
+-		nkeep = 0;
+-	}
+-	return 0;
+-}
+-
+ static int throw_away_data(struct fsg_common *common)
+ {
+ 	struct fsg_buffhd	*bh;
+@@ -1686,6 +1655,10 @@ static int finish_reply(struct fsg_common *common)
+ 		if (common->data_size == 0) {
+ 			/* Nothing to send */
+ 
++		/* Don't know what to do if common->fsg is NULL */
++		} else if (!fsg_is_set(common)) {
++			rc = -EIO;
++
+ 		/* If there's no residue, simply send the last buffer */
+ 		} else if (common->residue == 0) {
+ 			bh->inreq->zero = 0;
+@@ -1694,24 +1667,19 @@ static int finish_reply(struct fsg_common *common)
+ 			common->next_buffhd_to_fill = bh->next;
+ 
+ 		/*
+-		 * For Bulk-only, if we're allowed to stall then send the
+-		 * short packet and halt the bulk-in endpoint.  If we can't
+-		 * stall, pad out the remaining data with 0's.
++		 * For Bulk-only, mark the end of the data with a short
++		 * packet.  If we are allowed to stall, halt the bulk-in
++		 * endpoint.  (Note: This violates the Bulk-Only Transport
++		 * specification, which requires us to pad the data if we
++		 * don't halt the endpoint.  Presumably nobody will mind.)
+ 		 */
+-		} else if (common->can_stall) {
++		} else {
+ 			bh->inreq->zero = 1;
+ 			if (!start_in_transfer(common, bh))
+-				/* Don't know what to do if
+-				 * common->fsg is NULL */
+ 				rc = -EIO;
+ 			common->next_buffhd_to_fill = bh->next;
+-			if (common->fsg)
++			if (common->can_stall)
+ 				rc = halt_bulk_in_endpoint(common->fsg);
+-		} else if (fsg_is_set(common)) {
+-			rc = pad_with_zeros(common->fsg);
+-		} else {
+-			/* Don't know what to do if common->fsg is NULL */
+-			rc = -EIO;
+ 		}
+ 		break;
+ 
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index d04e0e6b019d..aebfb81f3ba4 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -1932,37 +1932,6 @@ static int wedge_bulk_in_endpoint(struct fsg_dev *fsg)
+ 	return rc;
+ }
+ 
+-static int pad_with_zeros(struct fsg_dev *fsg)
+-{
+-	struct fsg_buffhd	*bh = fsg->next_buffhd_to_fill;
+-	u32			nkeep = bh->inreq->length;
+-	u32			nsend;
+-	int			rc;
+-
+-	bh->state = BUF_STATE_EMPTY;		// For the first iteration
+-	fsg->usb_amount_left = nkeep + fsg->residue;
+-	while (fsg->usb_amount_left > 0) {
+-
+-		/* Wait for the next buffer to be free */
+-		while (bh->state != BUF_STATE_EMPTY) {
+-			rc = sleep_thread(fsg);
+-			if (rc)
+-				return rc;
+-		}
+-
+-		nsend = min(fsg->usb_amount_left, (u32) mod_data.buflen);
+-		memset(bh->buf + nkeep, 0, nsend - nkeep);
+-		bh->inreq->length = nsend;
+-		bh->inreq->zero = 0;
+-		start_transfer(fsg, fsg->bulk_in, bh->inreq,
+-				&bh->inreq_busy, &bh->state);
+-		bh = fsg->next_buffhd_to_fill = bh->next;
+-		fsg->usb_amount_left -= nsend;
+-		nkeep = 0;
+-	}
+-	return 0;
+-}
+-
+ static int throw_away_data(struct fsg_dev *fsg)
+ {
+ 	struct fsg_buffhd	*bh;
+@@ -2066,18 +2035,20 @@ static int finish_reply(struct fsg_dev *fsg)
+ 			}
+ 		}
+ 
+-		/* For Bulk-only, if we're allowed to stall then send the
+-		 * short packet and halt the bulk-in endpoint.  If we can't
+-		 * stall, pad out the remaining data with 0's. */
++		/*
++		 * For Bulk-only, mark the end of the data with a short
++		 * packet.  If we are allowed to stall, halt the bulk-in
++		 * endpoint.  (Note: This violates the Bulk-Only Transport
++		 * specification, which requires us to pad the data if we
++		 * don't halt the endpoint.  Presumably nobody will mind.)
++		 */
+ 		else {
+-			if (mod_data.can_stall) {
+-				bh->inreq->zero = 1;
+-				start_transfer(fsg, fsg->bulk_in, bh->inreq,
+-						&bh->inreq_busy, &bh->state);
+-				fsg->next_buffhd_to_fill = bh->next;
++			bh->inreq->zero = 1;
++			start_transfer(fsg, fsg->bulk_in, bh->inreq,
++					&bh->inreq_busy, &bh->state);
++			fsg->next_buffhd_to_fill = bh->next;
++			if (mod_data.can_stall)
+ 				rc = halt_bulk_in_endpoint(fsg);
+-			} else
+-				rc = pad_with_zeros(fsg);
+ 		}
+ 		break;
+ 

commit 94ae4976e253757e9b03a44d27d41b20f1829d80
+Author: Alan Stern 
+Date:   Tue Apr 5 13:36:15 2011 -0400
+
+    USB: EHCI: unlink unused QHs when the controller is stopped
+    
+    This patch (as1458) fixes a problem affecting ultra-reliable systems:
+    When hardware failover of an EHCI controller occurs, the data
+    structures do not get released correctly.  This is because the routine
+    responsible for removing unused QHs from the async schedule assumes
+    the controller is running properly (the frame counter is used in
+    determining how long the QH has been idle) -- but when a failover
+    causes the controller to be electronically disconnected from the PCI
+    bus, obviously it stops running.
+    
+    The solution is simple: Allow scan_async() to remove a QH from the
+    async schedule if it has been idle for long enough _or_ if the
+    controller is stopped.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-Tested-by: Dan Duval 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 98ded66e8d3f..42abd0f603bf 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -1247,24 +1247,27 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 
+ static void scan_async (struct ehci_hcd *ehci)
+ {
++	bool			stopped;
+ 	struct ehci_qh		*qh;
+ 	enum ehci_timer_action	action = TIMER_IO_WATCHDOG;
+ 
+ 	ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index);
+ 	timer_action_done (ehci, TIMER_ASYNC_SHRINK);
+ rescan:
++	stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state);
+ 	qh = ehci->async->qh_next.qh;
+ 	if (likely (qh != NULL)) {
+ 		do {
+ 			/* clean any finished work for this qh */
+-			if (!list_empty (&qh->qtd_list)
+-					&& qh->stamp != ehci->stamp) {
++			if (!list_empty(&qh->qtd_list) && (stopped ||
++					qh->stamp != ehci->stamp)) {
+ 				int temp;
+ 
+ 				/* unlinks could happen here; completion
+ 				 * reporting drops the lock.  rescan using
+ 				 * the latest schedule, but don't rescan
+-				 * qhs we already finished (no looping).
++				 * qhs we already finished (no looping)
++				 * unless the controller is stopped.
+ 				 */
+ 				qh = qh_get (qh);
+ 				qh->stamp = ehci->stamp;
+@@ -1285,9 +1288,9 @@ static void scan_async (struct ehci_hcd *ehci)
+ 			 */
+ 			if (list_empty(&qh->qtd_list)
+ 					&& qh->qh_state == QH_STATE_LINKED) {
+-				if (!ehci->reclaim
+-					&& ((ehci->stamp - qh->stamp) & 0x1fff)
+-						>= (EHCI_SHRINK_FRAMES * 8))
++				if (!ehci->reclaim && (stopped ||
++					((ehci->stamp - qh->stamp) & 0x1fff)
++						>= EHCI_SHRINK_FRAMES * 8))
+ 					start_unlink_async(ehci, qh);
+ 				else
+ 					action = TIMER_ASYNC_SHRINK;

commit b5a3b3d985493c173925907adfebf3edab236fe7
+Author: Alan Stern 
+Date:   Wed Mar 16 10:57:15 2011 -0400
+
+    ehci-hcd: Bug fix: don't set a QH's Halt bit
+    
+    This patch (as1453) fixes a long-standing bug in the ehci-hcd driver.
+    
+    There is no need to set the Halt bit in the overlay region for an
+    unlinked or blocked QH.  Contrary to what the comment says, setting
+    the Halt bit does not cause the QH to be patched later; that decision
+    (made in qh_refresh()) depends only on whether the QH is currently
+    pointing to a valid qTD.  Likewise, setting the Halt bit does not
+    prevent completions from activating the QH while it is "stopped"; they
+    are prevented by the fact that qh_completions() temporarily changes
+    qh->qh_state to QH_STATE_COMPLETING.
+    
+    On the other hand, there are circumstances in which the QH will be
+    reactivated _without_ being patched; this happens after an URB beyond
+    the head of the queue is unlinked.  Setting the Halt bit will then
+    cause the hardware to see the QH with both the Active and Halt bits
+    set, an invalid combination that will prevent the queue from
+    advancing and may even crash some controllers.
+    
+    Apparently the only reason this hasn't been reported before is that
+    unlinking URBs from the middle of a running queue is quite uncommon.
+    However Test 17, recently added to the usbtest driver, does exactly
+    this, and it confirms the presence of the bug.
+    
+    In short, there is no reason to set the Halt bit for an unlinked or
+    blocked QH, and there is a very good reason not to set it.  Therefore
+    the code that sets it is removed.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Andiry Xu 
+    CC: David Brownell 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index fe99895fb098..98ded66e8d3f 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -315,7 +315,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	int			stopped;
+ 	unsigned		count = 0;
+ 	u8			state;
+-	const __le32		halt = HALT_BIT(ehci);
+ 	struct ehci_qh_hw	*hw = qh->hw;
+ 
+ 	if (unlikely (list_empty (&qh->qtd_list)))
+@@ -422,7 +421,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 					&& !(qtd->hw_alt_next
+ 						& EHCI_LIST_END(ehci))) {
+ 				stopped = 1;
+-				goto halt;
+ 			}
+ 
+ 		/* stop scanning when we reach qtds the hc is using */
+@@ -456,16 +454,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 				 */
+ 				ehci_clear_tt_buffer(ehci, qh, urb, token);
+ 			}
+-
+-			/* force halt for unlinked or blocked qh, so we'll
+-			 * patch the qh later and so that completions can't
+-			 * activate it while we "know" it's stopped.
+-			 */
+-			if ((halt & hw->hw_token) == 0) {
+-halt:
+-				hw->hw_token |= halt;
+-				wmb ();
+-			}
+ 		}
+ 
+ 		/* unless we already know the urb's status, collect qtd status

commit 9b37596a2e860404503a3f2a6513db60c296bfdc
+Author: Alan Stern 
+Date:   Mon Mar 7 11:11:52 2011 -0500
+
+    USB: move usbcore away from hcd->state
+    
+    The hcd->state variable is a disaster.  It's not clearly owned by
+    either usbcore or the host controller drivers, and they both change it
+    from time to time, potentially stepping on each other's toes.  It's
+    not protected by any locks.  And there's no mechanism to prevent it
+    from going through an invalid transition.
+    
+    This patch (as1451) takes a first step toward fixing these problems.
+    As it turns out, usbcore uses hcd->state for essentially only two
+    things: checking whether the controller's root hub is running and
+    checking whether the controller has died.  Therefore the patch adds
+    two new atomic bitflags to the hcd structure, to store these pieces of
+    information.  The new flags are used only by usbcore, and a private
+    spinlock prevents invalid combinations (a dead controller's root hub
+    cannot be running).
+    
+    The patch does not change the places where usbcore sets hcd->state,
+    since HCDs may depend on them.  Furthermore, there is one place in
+    usb_hcd_irq() where usbcore still must use hcd->state: An HCD's
+    interrupt handler can implicitly indicate that the controller died by
+    setting hcd->state to HC_STATE_HALT.  Nevertheless, the new code is a
+    big improvement over the current code.
+    
+    The patch makes one other change.  The hcd_bus_suspend() and
+    hcd_bus_resume() routines now check first whether the host controller
+    has died; if it has then they return immediately without calling the
+    HCD's bus_suspend or bus_resume methods.
+    
+    This fixes the major problem reported in Bugzilla #29902: The system
+    fails to suspend after a host controller dies during system resume.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Alex Terekhov 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index f71e8e307e0f..d37088591d9a 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -363,8 +363,7 @@ static int check_root_hub_suspended(struct device *dev)
+ 	struct pci_dev		*pci_dev = to_pci_dev(dev);
+ 	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
+ 
+-	if (!(hcd->state == HC_STATE_SUSPENDED ||
+-			hcd->state == HC_STATE_HALT)) {
++	if (HCD_RH_RUNNING(hcd)) {
+ 		dev_warn(dev, "Root hub is not suspended\n");
+ 		return -EBUSY;
+ 	}
+@@ -386,7 +385,7 @@ static int suspend_common(struct device *dev, bool do_wakeup)
+ 	if (retval)
+ 		return retval;
+ 
+-	if (hcd->driver->pci_suspend) {
++	if (hcd->driver->pci_suspend && !HCD_DEAD(hcd)) {
+ 		/* Optimization: Don't suspend if a root-hub wakeup is
+ 		 * pending and it would cause the HCD to wake up anyway.
+ 		 */
+@@ -427,7 +426,7 @@ static int resume_common(struct device *dev, int event)
+ 	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
+ 	int			retval;
+ 
+-	if (hcd->state != HC_STATE_SUSPENDED) {
++	if (HCD_RH_RUNNING(hcd)) {
+ 		dev_dbg(dev, "can't resume, not suspended!\n");
+ 		return 0;
+ 	}
+@@ -442,7 +441,7 @@ static int resume_common(struct device *dev, int event)
+ 
+ 	clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+ 
+-	if (hcd->driver->pci_resume) {
++	if (hcd->driver->pci_resume && !HCD_DEAD(hcd)) {
+ 		if (event != PM_EVENT_AUTO_RESUME)
+ 			wait_for_companions(pci_dev, hcd);
+ 
+@@ -475,10 +474,10 @@ static int hcd_pci_suspend_noirq(struct device *dev)
+ 
+ 	pci_save_state(pci_dev);
+ 
+-	/* If the root hub is HALTed rather than SUSPENDed,
++	/* If the root hub is dead rather than suspended,
+ 	 * disallow remote wakeup.
+ 	 */
+-	if (hcd->state == HC_STATE_HALT)
++	if (HCD_DEAD(hcd))
+ 		device_set_wakeup_enable(dev, 0);
+ 	dev_dbg(dev, "wakeup: %d\n", device_may_wakeup(dev));
+ 
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 24765fd6cf12..e7d0c4571bbe 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -983,7 +983,7 @@ static int register_root_hub(struct usb_hcd *hcd)
+ 		spin_unlock_irq (&hcd_root_hub_lock);
+ 
+ 		/* Did the HC die before the root hub was registered? */
+-		if (hcd->state == HC_STATE_HALT)
++		if (HCD_DEAD(hcd) || hcd->state == HC_STATE_HALT)
+ 			usb_hc_died (hcd);	/* This time clean up */
+ 	}
+ 
+@@ -1089,13 +1089,10 @@ int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb)
+ 	 * Check the host controller's state and add the URB to the
+ 	 * endpoint's queue.
+ 	 */
+-	switch (hcd->state) {
+-	case HC_STATE_RUNNING:
+-	case HC_STATE_RESUMING:
++	if (HCD_RH_RUNNING(hcd)) {
+ 		urb->unlinked = 0;
+ 		list_add_tail(&urb->urb_list, &urb->ep->urb_list);
+-		break;
+-	default:
++	} else {
+ 		rc = -ESHUTDOWN;
+ 		goto done;
+ 	}
+@@ -1931,7 +1928,7 @@ int usb_hcd_get_frame_number (struct usb_device *udev)
+ {
+ 	struct usb_hcd	*hcd = bus_to_hcd(udev->bus);
+ 
+-	if (!HC_IS_RUNNING (hcd->state))
++	if (!HCD_RH_RUNNING(hcd))
+ 		return -ESHUTDOWN;
+ 	return hcd->driver->get_frame_number (hcd);
+ }
+@@ -1948,9 +1945,15 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg)
+ 
+ 	dev_dbg(&rhdev->dev, "bus %s%s\n",
+ 			(msg.event & PM_EVENT_AUTO ? "auto-" : ""), "suspend");
++	if (HCD_DEAD(hcd)) {
++		dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "suspend");
++		return 0;
++	}
++
+ 	if (!hcd->driver->bus_suspend) {
+ 		status = -ENOENT;
+ 	} else {
++		clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
+ 		hcd->state = HC_STATE_QUIESCING;
+ 		status = hcd->driver->bus_suspend(hcd);
+ 	}
+@@ -1958,7 +1961,12 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg)
+ 		usb_set_device_state(rhdev, USB_STATE_SUSPENDED);
+ 		hcd->state = HC_STATE_SUSPENDED;
+ 	} else {
+-		hcd->state = old_state;
++		spin_lock_irq(&hcd_root_hub_lock);
++		if (!HCD_DEAD(hcd)) {
++			set_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
++			hcd->state = old_state;
++		}
++		spin_unlock_irq(&hcd_root_hub_lock);
+ 		dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
+ 				"suspend", status);
+ 	}
+@@ -1973,9 +1981,13 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
+ 
+ 	dev_dbg(&rhdev->dev, "usb %s%s\n",
+ 			(msg.event & PM_EVENT_AUTO ? "auto-" : ""), "resume");
++	if (HCD_DEAD(hcd)) {
++		dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "resume");
++		return 0;
++	}
+ 	if (!hcd->driver->bus_resume)
+ 		return -ENOENT;
+-	if (hcd->state == HC_STATE_RUNNING)
++	if (HCD_RH_RUNNING(hcd))
+ 		return 0;
+ 
+ 	hcd->state = HC_STATE_RESUMING;
+@@ -1984,10 +1996,15 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
+ 	if (status == 0) {
+ 		/* TRSMRCY = 10 msec */
+ 		msleep(10);
+-		usb_set_device_state(rhdev, rhdev->actconfig
+-				? USB_STATE_CONFIGURED
+-				: USB_STATE_ADDRESS);
+-		hcd->state = HC_STATE_RUNNING;
++		spin_lock_irq(&hcd_root_hub_lock);
++		if (!HCD_DEAD(hcd)) {
++			usb_set_device_state(rhdev, rhdev->actconfig
++					? USB_STATE_CONFIGURED
++					: USB_STATE_ADDRESS);
++			set_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
++			hcd->state = HC_STATE_RUNNING;
++		}
++		spin_unlock_irq(&hcd_root_hub_lock);
+ 	} else {
+ 		hcd->state = old_state;
+ 		dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
+@@ -2098,7 +2115,7 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)
+ 	 */
+ 	local_irq_save(flags);
+ 
+-	if (unlikely(hcd->state == HC_STATE_HALT || !HCD_HW_ACCESSIBLE(hcd))) {
++	if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd))) {
+ 		rc = IRQ_NONE;
+ 	} else if (hcd->driver->irq(hcd) == IRQ_NONE) {
+ 		rc = IRQ_NONE;
+@@ -2132,6 +2149,8 @@ void usb_hc_died (struct usb_hcd *hcd)
+ 	dev_err (hcd->self.controller, "HC died; cleaning up\n");
+ 
+ 	spin_lock_irqsave (&hcd_root_hub_lock, flags);
++	clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
++	set_bit(HCD_FLAG_DEAD, &hcd->flags);
+ 	if (hcd->rh_registered) {
+ 		clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+ 
+@@ -2274,6 +2293,12 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ 	 */
+ 	device_init_wakeup(&rhdev->dev, 1);
+ 
++	/* HCD_FLAG_RH_RUNNING doesn't matter until the root hub is
++	 * registered.  But since the controller can die at any time,
++	 * let's initialize the flag before touching the hardware.
++	 */
++	set_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
++
+ 	/* "reset" is misnamed; its role is now one-time init. the controller
+ 	 * should already have been reset (and boot firmware kicked off etc).
+ 	 */
+@@ -2341,6 +2366,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ 	return retval;
+ 
+ error_create_attr_group:
++	clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
+ 	if (HC_IS_RUNNING(hcd->state))
+ 		hcd->state = HC_STATE_QUIESCING;
+ 	spin_lock_irq(&hcd_root_hub_lock);
+@@ -2393,6 +2419,7 @@ void usb_remove_hcd(struct usb_hcd *hcd)
+ 	usb_get_dev(rhdev);
+ 	sysfs_remove_group(&rhdev->dev.kobj, &usb_bus_attr_group);
+ 
++	clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
+ 	if (HC_IS_RUNNING (hcd->state))
+ 		hcd->state = HC_STATE_QUIESCING;
+ 
+diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
+index 9cfba4f2457b..8b65068c6af9 100644
+--- a/include/linux/usb/hcd.h
++++ b/include/linux/usb/hcd.h
+@@ -99,6 +99,8 @@ struct usb_hcd {
+ #define HCD_FLAG_POLL_RH		2	/* poll for rh status? */
+ #define HCD_FLAG_POLL_PENDING		3	/* status has changed? */
+ #define HCD_FLAG_WAKEUP_PENDING		4	/* root hub is resuming? */
++#define HCD_FLAG_RH_RUNNING		5	/* root hub is running? */
++#define HCD_FLAG_DEAD			6	/* controller has died? */
+ 
+ 	/* The flags can be tested using these macros; they are likely to
+ 	 * be slightly faster than test_bit().
+@@ -108,6 +110,8 @@ struct usb_hcd {
+ #define HCD_POLL_RH(hcd)	((hcd)->flags & (1U << HCD_FLAG_POLL_RH))
+ #define HCD_POLL_PENDING(hcd)	((hcd)->flags & (1U << HCD_FLAG_POLL_PENDING))
+ #define HCD_WAKEUP_PENDING(hcd)	((hcd)->flags & (1U << HCD_FLAG_WAKEUP_PENDING))
++#define HCD_RH_RUNNING(hcd)	((hcd)->flags & (1U << HCD_FLAG_RH_RUNNING))
++#define HCD_DEAD(hcd)		((hcd)->flags & (1U << HCD_FLAG_DEAD))
+ 
+ 	/* Flags that get set only during HCD registration or removal. */
+ 	unsigned		rh_registered:1;/* is root hub registered? */

commit 969e3033ae7733a0af8f7742ca74cd16c0857e71
+Author: Alan Stern 
+Date:   Wed Feb 23 15:28:18 2011 -0500
+
+    USB: serial drivers need to use larger bulk-in buffers
+    
+    When a driver doesn't know how much data a device is going to send,
+    the buffer size should be at least as big as the endpoint's maxpacket
+    value.  The serial drivers don't follow this rule; many of them
+    request only 256-byte bulk-in buffers.  As a result, they suffer
+    overflow errors if a high-speed device wants to send a lot of data,
+    because high-speed bulk endpoints are required to have a maxpacket
+    size of 512.
+    
+    This patch (as1450) fixes the problem by using the driver's
+    bulk_in_size value as a minimum, always allocating buffers no smaller
+    than the endpoint's maxpacket size.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Flynn Marquardt 
+    CC:  [after .39-rc1 is out]
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
+index 546a52179bec..2ff90a9c8f47 100644
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -911,9 +911,8 @@ int usb_serial_probe(struct usb_interface *interface,
+ 			dev_err(&interface->dev, "No free urbs available\n");
+ 			goto probe_error;
+ 		}
+-		buffer_size = serial->type->bulk_in_size;
+-		if (!buffer_size)
+-			buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
++		buffer_size = max_t(int, serial->type->bulk_in_size,
++				le16_to_cpu(endpoint->wMaxPacketSize));
+ 		port->bulk_in_size = buffer_size;
+ 		port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
+ 		port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
+diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
+index c9049139a7a5..45f3b9db4258 100644
+--- a/include/linux/usb/serial.h
++++ b/include/linux/usb/serial.h
+@@ -191,7 +191,8 @@ static inline void usb_set_serial_data(struct usb_serial *serial, void *data)
+  * @id_table: pointer to a list of usb_device_id structures that define all
+  *	of the devices this structure can support.
+  * @num_ports: the number of different ports this device will have.
+- * @bulk_in_size: bytes to allocate for bulk-in buffer (0 = end-point size)
++ * @bulk_in_size: minimum number of bytes to allocate for bulk-in buffer
++ *	(0 = end-point size)
+  * @bulk_out_size: bytes to allocate for bulk-out buffer (0 = end-point size)
+  * @calc_num_ports: pointer to a function to determine how many ports this
+  *	device has dynamically.  It will be called after the probe()

commit 3b29b68b1627781b5eecb581d3b9d5f0043a72f2
+Author: Alan Stern 
+Date:   Tue Feb 22 09:53:41 2011 -0500
+
+    USB: use "device number" instead of "address"
+    
+    The USB stack historically has conflated device numbers (i.e., the
+    value of udev->devnum) with device addresses.  This is understandable,
+    because until recently the two values were always the same.
+    
+    But with USB-3.0 they aren't the same, so we should start calling
+    these things by their correct names.  This patch (as1449b) changes many
+    of the references to "address" in the hub driver to "device number"
+    or "devnum".
+    
+    The patch also removes some unnecessary or misleading comments.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Luben Tuikov 
+    Reviewed-by: Sarah Sharp 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index d041c6826e43..c168121f9f97 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1499,6 +1499,13 @@ void usb_set_device_state(struct usb_device *udev,
+ EXPORT_SYMBOL_GPL(usb_set_device_state);
+ 
+ /*
++ * Choose a device number.
++ *
++ * Device numbers are used as filenames in usbfs.  On USB-1.1 and
++ * USB-2.0 buses they are also used as device addresses, however on
++ * USB-3.0 buses the address is assigned by the controller hardware
++ * and it usually is not the same as the device number.
++ *
+  * WUSB devices are simple: they have no hubs behind, so the mapping
+  * device <-> virtual port number becomes 1:1. Why? to simplify the
+  * life of the device connection logic in
+@@ -1520,7 +1527,7 @@ EXPORT_SYMBOL_GPL(usb_set_device_state);
+  * the HCD must setup data structures before issuing a set address
+  * command to the hardware.
+  */
+-static void choose_address(struct usb_device *udev)
++static void choose_devnum(struct usb_device *udev)
+ {
+ 	int		devnum;
+ 	struct usb_bus	*bus = udev->bus;
+@@ -1545,7 +1552,7 @@ static void choose_address(struct usb_device *udev)
+ 	}
+ }
+ 
+-static void release_address(struct usb_device *udev)
++static void release_devnum(struct usb_device *udev)
+ {
+ 	if (udev->devnum > 0) {
+ 		clear_bit(udev->devnum, udev->bus->devmap.devicemap);
+@@ -1553,7 +1560,7 @@ static void release_address(struct usb_device *udev)
+ 	}
+ }
+ 
+-static void update_address(struct usb_device *udev, int devnum)
++static void update_devnum(struct usb_device *udev, int devnum)
+ {
+ 	/* The address for a WUSB device is managed by wusbcore. */
+ 	if (!udev->wusb)
+@@ -1600,7 +1607,8 @@ void usb_disconnect(struct usb_device **pdev)
+ 	 * this quiesces everyting except pending urbs.
+ 	 */
+ 	usb_set_device_state(udev, USB_STATE_NOTATTACHED);
+-	dev_info (&udev->dev, "USB disconnect, address %d\n", udev->devnum);
++	dev_info(&udev->dev, "USB disconnect, device number %d\n",
++			udev->devnum);
+ 
+ 	usb_lock_device(udev);
+ 
+@@ -1630,7 +1638,7 @@ void usb_disconnect(struct usb_device **pdev)
+ 	/* Free the device number and delete the parent's children[]
+ 	 * (or root_hub) pointer.
+ 	 */
+-	release_address(udev);
++	release_devnum(udev);
+ 
+ 	/* Avoid races with recursively_mark_NOTATTACHED() */
+ 	spin_lock_irq(&device_state_lock);
+@@ -2071,7 +2079,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
+ 		case 0:
+ 			/* TRSTRCY = 10 ms; plus some extra */
+ 			msleep(10 + 40);
+-			update_address(udev, 0);
++			update_devnum(udev, 0);
+ 			if (hcd->driver->reset_device) {
+ 				status = hcd->driver->reset_device(hcd, udev);
+ 				if (status < 0) {
+@@ -2634,7 +2642,7 @@ static int hub_set_address(struct usb_device *udev, int devnum)
+ 				USB_REQ_SET_ADDRESS, 0, devnum, 0,
+ 				NULL, 0, USB_CTRL_SET_TIMEOUT);
+ 	if (retval == 0) {
+-		update_address(udev, devnum);
++		update_devnum(udev, devnum);
+ 		/* Device now using proper address. */
+ 		usb_set_device_state(udev, USB_STATE_ADDRESS);
+ 		usb_ep0_reinit(udev);
+@@ -2743,9 +2751,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ 	}
+ 	if (udev->speed != USB_SPEED_SUPER)
+ 		dev_info(&udev->dev,
+-				"%s %s speed %sUSB device using %s and address %d\n",
++				"%s %s speed %sUSB device number %d using %s\n",
+ 				(udev->config) ? "reset" : "new", speed, type,
+-				udev->bus->controller->driver->name, devnum);
++				devnum, udev->bus->controller->driver->name);
+ 
+ 	/* Set up TT records, if needed  */
+ 	if (hdev->tt) {
+@@ -2775,10 +2783,6 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ 	 * value.
+ 	 */
+ 	for (i = 0; i < GET_DESCRIPTOR_TRIES; (++i, msleep(100))) {
+-		/*
+-		 * An xHCI controller cannot send any packets to a device until
+-		 * a set address command successfully completes.
+-		 */
+ 		if (USE_NEW_SCHEME(retry_counter) && !(hcd->driver->flags & HCD_USB3)) {
+ 			struct usb_device_descriptor *buf;
+ 			int r = 0;
+@@ -2861,9 +2865,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ 			if (udev->speed == USB_SPEED_SUPER) {
+ 				devnum = udev->devnum;
+ 				dev_info(&udev->dev,
+-						"%s SuperSpeed USB device using %s and address %d\n",
++						"%s SuperSpeed USB device number %d using %s\n",
+ 						(udev->config) ? "reset" : "new",
+-						udev->bus->controller->driver->name, devnum);
++						devnum, udev->bus->controller->driver->name);
+ 			}
+ 
+ 			/* cope with hardware quirkiness:
+@@ -2926,7 +2930,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ fail:
+ 	if (retval) {
+ 		hub_port_disable(hub, port1, 0);
+-		update_address(udev, devnum);	/* for disconnect processing */
++		update_devnum(udev, devnum);	/* for disconnect processing */
+ 	}
+ 	mutex_unlock(&usb_address0_mutex);
+ 	return retval;
+@@ -3135,15 +3139,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 		else
+ 			udev->speed = USB_SPEED_UNKNOWN;
+ 
+-		/*
+-		 * Set the address.
+-		 * Note xHCI needs to issue an address device command later
+-		 * in the hub_port_init sequence for SS/HS/FS/LS devices,
+-		 * and xHC will assign an address to the device. But use
+-		 * kernel assigned address here, to avoid any address conflict
+-		 * issue.
+-		 */
+-		choose_address(udev);
++		choose_devnum(udev);
+ 		if (udev->devnum <= 0) {
+ 			status = -ENOTCONN;	/* Don't retry */
+ 			goto loop;
+@@ -3235,7 +3231,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 		hub_port_disable(hub, port1, 1);
+ loop:
+ 		usb_ep0_reinit(udev);
+-		release_address(udev);
++		release_devnum(udev);
+ 		hub_free_dev(udev);
+ 		usb_put_dev(udev);
+ 		if ((status == -ENOTCONN) || (status == -ENOTSUPP))

commit 3c18e30f87ac5466bddbb05cf955605efd7db025
+Author: Alan Stern 
+Date:   Thu Feb 17 10:26:38 2011 -0500
+
+    USB: add quirks entry for Keytouch QWERTY Panel
+    
+    This patch (as1448) adds a quirks entry for the Keytouch QWERTY Panel
+    firmware, used in the IEC 60945 keyboard.  This device crashes during
+    enumeration when the computer asks for its configuration string
+    descriptor.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: kholis 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index 44c595432d6f..92ce90b83126 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -68,6 +68,10 @@ static const struct usb_device_id usb_quirk_list[] = {
+ 	/* M-Systems Flash Disk Pioneers */
+ 	{ USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
+ 
++	/* Keytouch QWERTY Panel keyboard */
++	{ USB_DEVICE(0x0926, 0x3333), .driver_info =
++			USB_QUIRK_CONFIG_INTF_STRINGS },
++
+ 	/* X-Rite/Gretag-Macbeth Eye-One Pro display colorimeter */
+ 	{ USB_DEVICE(0x0971, 0x2000), .driver_info = USB_QUIRK_NO_SET_INTF },
+ 

commit 3ea3c9b5a8464ec8223125f95e5dddb3bfd02a39
+Author: Alan Stern 
+Date:   Tue Jan 25 13:07:04 2011 -0500
+
+    USB: usb-storage: unusual_devs entry for Coby MP3 player
+    
+    This patch (as1444) adds an unusual_devs entry for an MP3 player from
+    Coby electronics.  The device has two nasty bugs.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Jasper Mackenzie 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 79d76da91da0..c1602b8c5594 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -1897,6 +1897,13 @@ UNUSUAL_DEV(  0x1e68, 0x001b, 0x0000, 0x0000,
+ 		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ 		US_FL_IGNORE_RESIDUE | US_FL_SANE_SENSE ),
+ 
++/* Reported by Jasper Mackenzie  */
++UNUSUAL_DEV( 0x1e74, 0x4621, 0x0000, 0x0000,
++		"Coby Electronics",
++		"MP3 Player",
++		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
++		US_FL_BULK_IGNORE_TAG | US_FL_MAX_SECTORS_64 ),
++
+ UNUSUAL_DEV( 0x2116, 0x0320, 0x0001, 0x0001,
+ 		"ST",
+ 		"2A",

commit bf3d7d40e42a85ca73a34e1385ff34f092a384eb
+Author: Alan Stern 
+Date:   Wed Feb 2 13:59:33 2011 -0500
+
+    USB: fix race between root-hub resume and wakeup requests
+    
+    The USB core keeps track of pending resume requests for root hubs, in
+    order to resolve races between wakeup requests and suspends.  However
+    the code that does this is subject to another race (between wakeup
+    requests and resumes) because the WAKEUP_PENDING flag is cleared
+    before the resume occurs, leaving a window in which another wakeup
+    request might arrive.
+    
+    This patch (as1447) fixes the problem by clearing the WAKEUP_PENDING
+    flag after the resume instead of before it.
+    
+    This fixes Bugzilla #24952.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Paul Bender 
+    Tested-by: warpme 
+    Cc: stable  [.36+]
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 6a95017fa62b..e935f71d7a34 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1955,7 +1955,6 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
+ 
+ 	dev_dbg(&rhdev->dev, "usb %s%s\n",
+ 			(msg.event & PM_EVENT_AUTO ? "auto-" : ""), "resume");
+-	clear_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags);
+ 	if (!hcd->driver->bus_resume)
+ 		return -ENOENT;
+ 	if (hcd->state == HC_STATE_RUNNING)
+@@ -1963,6 +1962,7 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
+ 
+ 	hcd->state = HC_STATE_RESUMING;
+ 	status = hcd->driver->bus_resume(hcd);
++	clear_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags);
+ 	if (status == 0) {
+ 		/* TRSMRCY = 10 msec */
+ 		msleep(10);

commit d199c96d41d80a567493e12b8e96ea056a1350c1
+Author: Alan Stern 
+Date:   Mon Jan 31 10:56:37 2011 -0500
+
+    USB: prevent buggy hubs from crashing the USB stack
+    
+    If anyone comes across a high-speed hub that (by mistake or by design)
+    claims to have no Transaction Translators, plugging a full- or
+    low-speed device into it will cause the USB stack to crash.  This
+    patch (as1446) prevents the problem by ignoring such devices, since
+    the kernel has no way to communicate with them.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Perry Neben 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 4310cc4b1cb5..d041c6826e43 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2753,6 +2753,11 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ 		udev->ttport = hdev->ttport;
+ 	} else if (udev->speed != USB_SPEED_HIGH
+ 			&& hdev->speed == USB_SPEED_HIGH) {
++		if (!hub->tt.hub) {
++			dev_err(&udev->dev, "parent hub has no TT\n");
++			retval = -EINVAL;
++			goto fail;
++		}
+ 		udev->tt = &hub->tt;
+ 		udev->ttport = port1;
+ 	}

commit c3810c88788d505d4ffd786addd111b745e42161
+Author: Alan Stern 
+Date:   Tue Jan 25 20:50:07 2011 +0100
+
+    PM / Runtime: Don't enable interrupts while running in_interrupt
+    
+    This patch (as1445) fixes a bug in the runtime PM core left over from
+    the addition of the no_callbacks flag.  If this flag is set then it is
+    possible for rpm_suspend() to be called in_interrupt, so when
+    releasing spinlocks it's important not to re-enable interrupts.
+    
+    To avoid an unnecessary save-and-restore of the interrupt flag, the
+    patch also inlines a pm_request_idle() call.
+    
+    This fixes Bugzilla #27482.
+    
+    (The offending code was added in 2.6.37, so it's not necessary to apply
+    this to any earlier stable kernels.)
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: tim blechmann 
+    CC: 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
+index 656493a5e073..42615b419dfb 100644
+--- a/drivers/base/power/runtime.c
++++ b/drivers/base/power/runtime.c
+@@ -407,12 +407,15 @@ static int rpm_suspend(struct device *dev, int rpmflags)
+ 		goto out;
+ 	}
+ 
++	/* Maybe the parent is now able to suspend. */
+ 	if (parent && !parent->power.ignore_children && !dev->power.irq_safe) {
+-		spin_unlock_irq(&dev->power.lock);
++		spin_unlock(&dev->power.lock);
+ 
+-		pm_request_idle(parent);
++		spin_lock(&parent->power.lock);
++		rpm_idle(parent, RPM_ASYNC);
++		spin_unlock(&parent->power.lock);
+ 
+-		spin_lock_irq(&dev->power.lock);
++		spin_lock(&dev->power.lock);
+ 	}
+ 
+  out:

commit 5620b5f7f19e9ee3fcf6ecf493fed7821b7b495b
+Author: Alan Stern 
+Date:   Tue Jan 11 14:16:50 2011 -0500
+
+    USB serial: add missing .usb_driver field in serial drivers
+    
+    This patch (as1443) fixes a bug found in many of the USB serial
+    drivers: They don't set the .usb_driver field in their
+    usb_serial_driver structure.  This field is needed for assigning
+    dynamic IDs for device matching.
+    
+    In addition, starting with the 2.6.37 kernel, the .usb_driver field is
+    needed for proper autosuspend operation.  Without it, attempts to open
+    the device file will fail.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Dan Williams 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
+index 6ab2a3f97fe8..178b22eb32b1 100644
+--- a/drivers/usb/serial/io_tables.h
++++ b/drivers/usb/serial/io_tables.h
+@@ -199,6 +199,7 @@ static struct usb_serial_driver epic_device = {
+ 		.name		= "epic",
+ 	},
+ 	.description		= "EPiC device",
++	.usb_driver		= &io_driver,
+ 	.id_table		= Epic_port_id_table,
+ 	.num_ports		= 1,
+ 	.open			= edge_open,
+diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
+index 12ed594f5f80..99b97c04896f 100644
+--- a/drivers/usb/serial/iuu_phoenix.c
++++ b/drivers/usb/serial/iuu_phoenix.c
+@@ -1275,6 +1275,7 @@ static struct usb_serial_driver iuu_device = {
+ 		   .name = "iuu_phoenix",
+ 		   },
+ 	.id_table = id_table,
++	.usb_driver = &iuu_driver,
+ 	.num_ports = 1,
+ 	.bulk_in_size = 512,
+ 	.bulk_out_size = 512,
+diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
+index 2d8baf6ac472..ce134dc28ddf 100644
+--- a/drivers/usb/serial/keyspan.h
++++ b/drivers/usb/serial/keyspan.h
+@@ -546,6 +546,7 @@ static struct usb_serial_driver keyspan_pre_device = {
+ 		.name		= "keyspan_no_firm",
+ 	},
+ 	.description		= "Keyspan - (without firmware)",
++	.usb_driver		= &keyspan_driver,
+ 	.id_table		= keyspan_pre_ids,
+ 	.num_ports		= 1,
+ 	.attach			= keyspan_fake_startup,
+@@ -557,6 +558,7 @@ static struct usb_serial_driver keyspan_1port_device = {
+ 		.name		= "keyspan_1",
+ 	},
+ 	.description		= "Keyspan 1 port adapter",
++	.usb_driver		= &keyspan_driver,
+ 	.id_table		= keyspan_1port_ids,
+ 	.num_ports		= 1,
+ 	.open			= keyspan_open,
+@@ -579,6 +581,7 @@ static struct usb_serial_driver keyspan_2port_device = {
+ 		.name		= "keyspan_2",
+ 	},
+ 	.description		= "Keyspan 2 port adapter",
++	.usb_driver		= &keyspan_driver,
+ 	.id_table		= keyspan_2port_ids,
+ 	.num_ports		= 2,
+ 	.open			= keyspan_open,
+@@ -601,6 +604,7 @@ static struct usb_serial_driver keyspan_4port_device = {
+ 		.name		= "keyspan_4",
+ 	},
+ 	.description		= "Keyspan 4 port adapter",
++	.usb_driver		= &keyspan_driver,
+ 	.id_table		= keyspan_4port_ids,
+ 	.num_ports		= 4,
+ 	.open			= keyspan_open,
+diff --git a/drivers/usb/serial/moto_modem.c b/drivers/usb/serial/moto_modem.c
+index cf1718394e18..653465f61d4a 100644
+--- a/drivers/usb/serial/moto_modem.c
++++ b/drivers/usb/serial/moto_modem.c
+@@ -44,6 +44,7 @@ static struct usb_serial_driver moto_device = {
+ 		.name =		"moto-modem",
+ 	},
+ 	.id_table =		id_table,
++	.usb_driver =		&moto_driver,
+ 	.num_ports =		1,
+ };
+ 
+diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
+index 5be866bb7a41..73613205be7a 100644
+--- a/drivers/usb/serial/oti6858.c
++++ b/drivers/usb/serial/oti6858.c
+@@ -157,6 +157,7 @@ static struct usb_serial_driver oti6858_device = {
+ 		.name =		"oti6858",
+ 	},
+ 	.id_table =		id_table,
++	.usb_driver =		&oti6858_driver,
+ 	.num_ports =		1,
+ 	.open =			oti6858_open,
+ 	.close =		oti6858_close,
+diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c
+index b53865b8cd9c..30b73e68a904 100644
+--- a/drivers/usb/serial/qcaux.c
++++ b/drivers/usb/serial/qcaux.c
+@@ -86,6 +86,7 @@ static struct usb_serial_driver qcaux_device = {
+ 		.name =		"qcaux",
+ 	},
+ 	.id_table =		id_table,
++	.usb_driver =		&qcaux_driver,
+ 	.num_ports =		1,
+ };
+ 
+diff --git a/drivers/usb/serial/siemens_mpi.c b/drivers/usb/serial/siemens_mpi.c
+index cb8195cabfde..74cd4ccdb3fc 100644
+--- a/drivers/usb/serial/siemens_mpi.c
++++ b/drivers/usb/serial/siemens_mpi.c
+@@ -42,6 +42,7 @@ static struct usb_serial_driver siemens_usb_mpi_device = {
+ 		.name =		"siemens_mpi",
+ 	},
+ 	.id_table =		id_table,
++	.usb_driver =		&siemens_usb_mpi_driver,
+ 	.num_ports =		1,
+ };
+ 
+diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
+index 765aa983bf58..c7665d39d192 100644
+--- a/drivers/usb/serial/spcp8x5.c
++++ b/drivers/usb/serial/spcp8x5.c
+@@ -645,6 +645,7 @@ static struct usb_serial_driver spcp8x5_device = {
+ 		.name =		"SPCP8x5",
+ 	},
+ 	.id_table		= id_table,
++	.usb_driver		= &spcp8x5_driver,
+ 	.num_ports		= 1,
+ 	.open 			= spcp8x5_open,
+ 	.dtr_rts		= spcp8x5_dtr_rts,
+diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
+index 6954de50c0ff..546a52179bec 100644
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -1344,11 +1344,15 @@ int usb_serial_register(struct usb_serial_driver *driver)
+ 		return -ENODEV;
+ 
+ 	fixup_generic(driver);
+-	if (driver->usb_driver)
+-		driver->usb_driver->supports_autosuspend = 1;
+ 
+ 	if (!driver->description)
+ 		driver->description = driver->driver.name;
++	if (!driver->usb_driver) {
++		WARN(1, "Serial driver %s has no usb_driver\n",
++				driver->description);
++		return -EINVAL;
++	}
++	driver->usb_driver->supports_autosuspend = 1;
+ 
+ 	/* Add this device to our list of devices */
+ 	mutex_lock(&table_lock);
+diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c
+index f2ed6a31be77..95a82148ee81 100644
+--- a/drivers/usb/serial/usb_debug.c
++++ b/drivers/usb/serial/usb_debug.c
+@@ -75,6 +75,7 @@ static struct usb_serial_driver debug_device = {
+ 		.name =		"debug",
+ 	},
+ 	.id_table =		id_table,
++	.usb_driver =		&debug_driver,
+ 	.num_ports =		1,
+ 	.bulk_out_size =	USB_DEBUG_MAX_PACKET_SIZE,
+ 	.break_ctl =		usb_debug_break_ctl,

commit ad84e4a9efb7c8ed322bafb6ebdb9c3a49a3d3a8
+Author: Alan Stern 
+Date:   Mon Jan 10 11:24:14 2011 -0500
+
+    USB: g_printer: fix bug in module parameter definitions
+    
+    This patch (as1442) fixes a bug in g_printer: Module parameters should
+    not be marked "__initdata" if they are accessible in sysfs (i.e., if
+    the mode value in the module_param() macro is nonzero).  Otherwise
+    attempts to access the parameters will cause addressing violations.
+    
+    Character-string module parameters must not be marked "__initdata"
+    if the module can be unloaded, because the kernel needs to access the
+    parameter variable at unload time in order to free the
+    dynamically-allocated string.
+    
+    Signed-off-by: Alan Stern 
+    CC: Roland Kletzing 
+    CC: Craig W. Nadler 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
+index dacc67724fe1..12ff6cffedc9 100644
+--- a/drivers/usb/gadget/printer.c
++++ b/drivers/usb/gadget/printer.c
+@@ -131,31 +131,31 @@ static struct printer_dev usb_printer_gadget;
+  * parameters are in UTF-8 (superset of ASCII's 7 bit characters).
+  */
+ 
+-static ushort __initdata idVendor;
++static ushort idVendor;
+ module_param(idVendor, ushort, S_IRUGO);
+ MODULE_PARM_DESC(idVendor, "USB Vendor ID");
+ 
+-static ushort __initdata idProduct;
++static ushort idProduct;
+ module_param(idProduct, ushort, S_IRUGO);
+ MODULE_PARM_DESC(idProduct, "USB Product ID");
+ 
+-static ushort __initdata bcdDevice;
++static ushort bcdDevice;
+ module_param(bcdDevice, ushort, S_IRUGO);
+ MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)");
+ 
+-static char *__initdata iManufacturer;
++static char *iManufacturer;
+ module_param(iManufacturer, charp, S_IRUGO);
+ MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");
+ 
+-static char *__initdata iProduct;
++static char *iProduct;
+ module_param(iProduct, charp, S_IRUGO);
+ MODULE_PARM_DESC(iProduct, "USB Product string");
+ 
+-static char *__initdata iSerialNum;
++static char *iSerialNum;
+ module_param(iSerialNum, charp, S_IRUGO);
+ MODULE_PARM_DESC(iSerialNum, "1");
+ 
+-static char *__initdata iPNPstring;
++static char *iPNPstring;
+ module_param(iPNPstring, charp, S_IRUGO);
+ MODULE_PARM_DESC(iPNPstring, "MFG:linux;MDL:g_printer;CLS:PRINTER;SN:1;");
+ 

commit d5aa475180d03d45c5dc6134aa833f1b3e89c45e
+Author: Alan Stern 
+Date:   Mon Jan 10 11:23:05 2011 -0500
+
+    USB: g_printer: fix bug in unregistration
+    
+    This patch (as1441) fixes a bug in g_printer.  The gadget driver, char
+    device number, and class device should be unregistered in reverse
+    order of registration.  As it is now, when the module is unloaded the
+    class device gets unregistered first, causing a crash when the unbind
+    method tries to access it.
+    
+    This fixes Bugzilla #25882.
+    
+    Signed-off-by: Alan Stern 
+    CC: Roland Kletzing 
+    CC: Craig W. Nadler 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
+index 2fc8636316c5..dacc67724fe1 100644
+--- a/drivers/usb/gadget/printer.c
++++ b/drivers/usb/gadget/printer.c
+@@ -1596,13 +1596,12 @@ cleanup(void)
+ 	int status;
+ 
+ 	mutex_lock(&usb_printer_gadget.lock_printer_io);
+-	class_destroy(usb_gadget_class);
+-	unregister_chrdev_region(g_printer_devno, 2);
+-
+ 	status = usb_gadget_unregister_driver(&printer_driver);
+ 	if (status)
+ 		ERROR(dev, "usb_gadget_unregister_driver %x\n", status);
+ 
++	unregister_chrdev_region(g_printer_devno, 2);
++	class_destroy(usb_gadget_class);
+ 	mutex_unlock(&usb_printer_gadget.lock_printer_io);
+ }
+ module_exit(cleanup);

commit f75593ceaa08e6d27aec1a5de31cded19e850dd1
+Author: Alan Stern 
+Date:   Thu Jan 6 10:17:09 2011 -0500
+
+    USB: EHCI: fix DMA deallocation bug
+    
+    This patch (as1440) fixes a bug in ehci-hcd.  ehci->periodic_size is
+    used to compute the size in a dma_alloc_coherent() call, but then it
+    gets changed later on.  As a result, the corresponding call to
+    dma_free_coherent() passes a different size from the original
+    allocation.  Fix the problem by adjusting ehci->periodic_size before
+    carrying out any of the memory allocations.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Larry Finger 
+    CC: David Brownell 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 6fee3cd58efe..74dcf49bd015 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -572,6 +572,8 @@ static int ehci_init(struct usb_hcd *hcd)
+ 	ehci->iaa_watchdog.function = ehci_iaa_watchdog;
+ 	ehci->iaa_watchdog.data = (unsigned long) ehci;
+ 
++	hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params);
++
+ 	/*
+ 	 * hw default: 1K periodic list heads, one per frame.
+ 	 * periodic_size can shrink by USBCMD update if hcc_params allows.
+@@ -579,11 +581,20 @@ static int ehci_init(struct usb_hcd *hcd)
+ 	ehci->periodic_size = DEFAULT_I_TDPS;
+ 	INIT_LIST_HEAD(&ehci->cached_itd_list);
+ 	INIT_LIST_HEAD(&ehci->cached_sitd_list);
++
++	if (HCC_PGM_FRAMELISTLEN(hcc_params)) {
++		/* periodic schedule size can be smaller than default */
++		switch (EHCI_TUNE_FLS) {
++		case 0: ehci->periodic_size = 1024; break;
++		case 1: ehci->periodic_size = 512; break;
++		case 2: ehci->periodic_size = 256; break;
++		default:	BUG();
++		}
++	}
+ 	if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0)
+ 		return retval;
+ 
+ 	/* controllers may cache some of the periodic schedule ... */
+-	hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params);
+ 	if (HCC_ISOC_CACHE(hcc_params))		// full frame cache
+ 		ehci->i_thresh = 2 + 8;
+ 	else					// N microframes cached
+@@ -637,12 +648,6 @@ static int ehci_init(struct usb_hcd *hcd)
+ 		/* periodic schedule size can be smaller than default */
+ 		temp &= ~(3 << 2);
+ 		temp |= (EHCI_TUNE_FLS << 2);
+-		switch (EHCI_TUNE_FLS) {
+-		case 0: ehci->periodic_size = 1024; break;
+-		case 1: ehci->periodic_size = 512; break;
+-		case 2: ehci->periodic_size = 256; break;
+-		default:	BUG();
+-		}
+ 	}
+ 	if (HCC_LPM(hcc_params)) {
+ 		/* support link power management EHCI 1.1 addendum */

commit 12f68c480c7155a66bd2a76ab2fef28dd5f93fa2
+Author: Alan Stern 
+Date:   Mon Jan 3 16:47:49 2011 -0500
+
+    USB: usb-storage: unusual_devs entry for CamSport Evo
+    
+    This patch (as1438) adds an unusual_devs entry for the MagicPixel
+    FW_Omega2 chip, used in the CamSport Evo camera.  The firmware
+    incorrectly reports a vendor-specific bDeviceClass.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 2e630e6fadad..24bd5d7c3deb 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -1044,6 +1044,15 @@ UNUSUAL_DEV(  0x084d, 0x0011, 0x0110, 0x0110,
+ 		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ 		US_FL_BULK32),
+ 
++/* Reported by 
++ * The device reports a vendor-specific device class, requiring an
++ * explicit vendor/product match.
++ */
++UNUSUAL_DEV(  0x0851, 0x1542, 0x0002, 0x0002,
++		"MagicPixel",
++		"FW_Omega2",
++		USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0),
++
+ /* Andrew Lunn 
+  * PanDigital Digital Picture Frame. Does not like ALLOW_MEDIUM_REMOVAL
+  * on LUN 4.

commit 41511704b678f7b101a76e58d6c6b7bbe2a9ad70
+Author: Alan Stern 
+Date:   Mon Nov 15 16:04:56 2010 -0500
+
+    [SCSI] eliminate an unnecessary local variable from scsi_remove_target()
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
+index 76ee2e784f75..4c68d36f9ac2 100644
+--- a/drivers/scsi/scsi_sysfs.c
++++ b/drivers/scsi/scsi_sysfs.c
+@@ -993,16 +993,14 @@ static int __remove_child (struct device * dev, void * data)
+  */
+ void scsi_remove_target(struct device *dev)
+ {
+-	struct device *rdev;
+-
+ 	if (scsi_is_target_device(dev)) {
+ 		__scsi_remove_target(to_scsi_target(dev));
+ 		return;
+ 	}
+ 
+-	rdev = get_device(dev);
++	get_device(dev);
+ 	device_for_each_child(dev, NULL, __remove_child);
+-	put_device(rdev);
++	put_device(dev);
+ }
+ EXPORT_SYMBOL(scsi_remove_target);
+ 

commit c7b61de5b7b17f0df34dc7d2f8b9576f8bd36fce
+Author: Alan Stern 
+Date:   Wed Dec 1 00:14:42 2010 +0100
+
+    PM / Runtime: Add synchronous runtime interface for interrupt handlers (v3)
+    
+    This patch (as1431c) makes the synchronous runtime-PM interface
+    suitable for use in interrupt handlers.  Subsystems can call the new
+    pm_runtime_irq_safe() function to tell the PM core that a device's
+    runtime_suspend and runtime_resume callbacks should be invoked with
+    interrupts disabled and the spinlock held.  This permits the
+    pm_runtime_get_sync() and the new pm_runtime_put_sync_suspend()
+    routines to be called from within interrupt handlers.
+    
+    When a device is declared irq-safe in this way, the PM core increments
+    the parent's usage count, so the parent will never be runtime
+    suspended.  This prevents difficult situations in which an irq-safe
+    device can't resume because it is forced to wait for its non-irq-safe
+    parent.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt
+index 41cc7b30d7dd..ffe55ffa540a 100644
+--- a/Documentation/power/runtime_pm.txt
++++ b/Documentation/power/runtime_pm.txt
+@@ -50,6 +50,15 @@ type's callbacks are not defined) of given device.  The bus type, device type
+ and device class callbacks are referred to as subsystem-level callbacks in what
+ follows.
+ 
++By default, the callbacks are always invoked in process context with interrupts
++enabled.  However, subsystems can use the pm_runtime_irq_safe() helper function
++to tell the PM core that a device's ->runtime_suspend() and ->runtime_resume()
++callbacks should be invoked in atomic context with interrupts disabled
++(->runtime_idle() is still invoked the default way).  This implies that these
++callback routines must not block or sleep, but it also means that the
++synchronous helper functions listed at the end of Section 4 can be used within
++an interrupt handler or in an atomic context.
++
+ The subsystem-level suspend callback is _entirely_ _responsible_ for handling
+ the suspend of the device as appropriate, which may, but need not include
+ executing the device driver's own ->runtime_suspend() callback (from the
+@@ -237,6 +246,10 @@ defined in include/linux/pm.h:
+       Section 8); it may be modified only by the pm_runtime_no_callbacks()
+       helper function
+ 
++  unsigned int irq_safe;
++    - indicates that the ->runtime_suspend() and ->runtime_resume() callbacks
++      will be invoked with the spinlock held and interrupts disabled
++
+   unsigned int use_autosuspend;
+     - indicates that the device's driver supports delayed autosuspend (see
+       Section 9); it may be modified only by the
+@@ -344,6 +357,10 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
+     - decrement the device's usage counter; if the result is 0 then run
+       pm_runtime_idle(dev) and return its result
+ 
++  int pm_runtime_put_sync_suspend(struct device *dev);
++    - decrement the device's usage counter; if the result is 0 then run
++      pm_runtime_suspend(dev) and return its result
++
+   int pm_runtime_put_sync_autosuspend(struct device *dev);
+     - decrement the device's usage counter; if the result is 0 then run
+       pm_runtime_autosuspend(dev) and return its result
+@@ -397,6 +414,11 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
+       PM attributes from /sys/devices/.../power (or prevent them from being
+       added when the device is registered)
+ 
++  void pm_runtime_irq_safe(struct device *dev);
++    - set the power.irq_safe flag for the device, causing the runtime-PM
++      suspend and resume callbacks (but not the idle callback) to be invoked
++      with interrupts disabled
++
+   void pm_runtime_mark_last_busy(struct device *dev);
+     - set the power.last_busy field to the current time
+ 
+@@ -438,6 +460,15 @@ pm_runtime_suspended()
+ pm_runtime_mark_last_busy()
+ pm_runtime_autosuspend_expiration()
+ 
++If pm_runtime_irq_safe() has been called for a device then the following helper
++functions may also be used in interrupt context:
++
++pm_runtime_suspend()
++pm_runtime_autosuspend()
++pm_runtime_resume()
++pm_runtime_get_sync()
++pm_runtime_put_sync_suspend()
++
+ 5. Run-time PM Initialization, Device Probing and Removal
+ 
+ Initially, the run-time PM is disabled for all devices, which means that the
+diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
+index 02c652be83e7..656493a5e073 100644
+--- a/drivers/base/power/runtime.c
++++ b/drivers/base/power/runtime.c
+@@ -250,13 +250,16 @@ static int rpm_callback(int (*cb)(struct device *), struct device *dev)
+ 	if (!cb)
+ 		return -ENOSYS;
+ 
+-	spin_unlock_irq(&dev->power.lock);
++	if (dev->power.irq_safe) {
++		retval = cb(dev);
++	} else {
++		spin_unlock_irq(&dev->power.lock);
+ 
+-	retval = cb(dev);
++		retval = cb(dev);
+ 
+-	spin_lock_irq(&dev->power.lock);
++		spin_lock_irq(&dev->power.lock);
++	}
+ 	dev->power.runtime_error = retval;
+-
+ 	return retval;
+ }
+ 
+@@ -404,7 +407,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
+ 		goto out;
+ 	}
+ 
+-	if (parent && !parent->power.ignore_children) {
++	if (parent && !parent->power.ignore_children && !dev->power.irq_safe) {
+ 		spin_unlock_irq(&dev->power.lock);
+ 
+ 		pm_request_idle(parent);
+@@ -527,10 +530,13 @@ static int rpm_resume(struct device *dev, int rpmflags)
+ 
+ 	if (!parent && dev->parent) {
+ 		/*
+-		 * Increment the parent's resume counter and resume it if
+-		 * necessary.
++		 * Increment the parent's usage counter and resume it if
++		 * necessary.  Not needed if dev is irq-safe; then the
++		 * parent is permanently resumed.
+ 		 */
+ 		parent = dev->parent;
++		if (dev->power.irq_safe)
++			goto skip_parent;
+ 		spin_unlock(&dev->power.lock);
+ 
+ 		pm_runtime_get_noresume(parent);
+@@ -553,6 +559,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
+ 			goto out;
+ 		goto repeat;
+ 	}
++ skip_parent:
+ 
+ 	if (dev->power.no_callbacks)
+ 		goto no_callback;	/* Assume success. */
+@@ -584,7 +591,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
+ 		rpm_idle(dev, RPM_ASYNC);
+ 
+  out:
+-	if (parent) {
++	if (parent && !dev->power.irq_safe) {
+ 		spin_unlock_irq(&dev->power.lock);
+ 
+ 		pm_runtime_put(parent);
+@@ -1065,7 +1072,6 @@ EXPORT_SYMBOL_GPL(pm_runtime_allow);
+  * Set the power.no_callbacks flag, which tells the PM core that this
+  * device is power-managed through its parent and has no run-time PM
+  * callbacks of its own.  The run-time sysfs attributes will be removed.
+- *
+  */
+ void pm_runtime_no_callbacks(struct device *dev)
+ {
+@@ -1077,6 +1083,27 @@ void pm_runtime_no_callbacks(struct device *dev)
+ }
+ EXPORT_SYMBOL_GPL(pm_runtime_no_callbacks);
+ 
++/**
++ * pm_runtime_irq_safe - Leave interrupts disabled during callbacks.
++ * @dev: Device to handle
++ *
++ * Set the power.irq_safe flag, which tells the PM core that the
++ * ->runtime_suspend() and ->runtime_resume() callbacks for this device should
++ * always be invoked with the spinlock held and interrupts disabled.  It also
++ * causes the parent's usage counter to be permanently incremented, preventing
++ * the parent from runtime suspending -- otherwise an irq-safe child might have
++ * to wait for a non-irq-safe parent.
++ */
++void pm_runtime_irq_safe(struct device *dev)
++{
++	if (dev->parent)
++		pm_runtime_get_sync(dev->parent);
++	spin_lock_irq(&dev->power.lock);
++	dev->power.irq_safe = 1;
++	spin_unlock_irq(&dev->power.lock);
++}
++EXPORT_SYMBOL_GPL(pm_runtime_irq_safe);
++
+ /**
+  * update_autosuspend - Handle a change to a device's autosuspend settings.
+  * @dev: Device to handle.
+@@ -1199,4 +1226,6 @@ void pm_runtime_remove(struct device *dev)
+ 	/* Change the status back to 'suspended' to match the initial status. */
+ 	if (dev->power.runtime_status == RPM_ACTIVE)
+ 		pm_runtime_set_suspended(dev);
++	if (dev->power.irq_safe && dev->parent)
++		pm_runtime_put_sync(dev->parent);
+ }
+diff --git a/include/linux/pm.h b/include/linux/pm.h
+index 40f3f45702ba..61f2066e6852 100644
+--- a/include/linux/pm.h
++++ b/include/linux/pm.h
+@@ -486,6 +486,7 @@ struct dev_pm_info {
+ 	unsigned int		run_wake:1;
+ 	unsigned int		runtime_auto:1;
+ 	unsigned int		no_callbacks:1;
++	unsigned int		irq_safe:1;
+ 	unsigned int		use_autosuspend:1;
+ 	unsigned int		timer_autosuspends:1;
+ 	enum rpm_request	request;
+diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h
+index d19f1cca7f74..e9cc049ccb62 100644
+--- a/include/linux/pm_runtime.h
++++ b/include/linux/pm_runtime.h
+@@ -40,6 +40,7 @@ extern int pm_generic_runtime_idle(struct device *dev);
+ extern int pm_generic_runtime_suspend(struct device *dev);
+ extern int pm_generic_runtime_resume(struct device *dev);
+ extern void pm_runtime_no_callbacks(struct device *dev);
++extern void pm_runtime_irq_safe(struct device *dev);
+ extern void __pm_runtime_use_autosuspend(struct device *dev, bool use);
+ extern void pm_runtime_set_autosuspend_delay(struct device *dev, int delay);
+ extern unsigned long pm_runtime_autosuspend_expiration(struct device *dev);
+@@ -124,6 +125,7 @@ static inline int pm_generic_runtime_idle(struct device *dev) { return 0; }
+ static inline int pm_generic_runtime_suspend(struct device *dev) { return 0; }
+ static inline int pm_generic_runtime_resume(struct device *dev) { return 0; }
+ static inline void pm_runtime_no_callbacks(struct device *dev) {}
++static inline void pm_runtime_irq_safe(struct device *dev) {}
+ 
+ static inline void pm_runtime_mark_last_busy(struct device *dev) {}
+ static inline void __pm_runtime_use_autosuspend(struct device *dev,
+@@ -196,6 +198,11 @@ static inline int pm_runtime_put_sync(struct device *dev)
+ 	return __pm_runtime_idle(dev, RPM_GET_PUT);
+ }
+ 
++static inline int pm_runtime_put_sync_suspend(struct device *dev)
++{
++	return __pm_runtime_suspend(dev, RPM_GET_PUT);
++}
++
+ static inline int pm_runtime_put_sync_autosuspend(struct device *dev)
+ {
+ 	return __pm_runtime_suspend(dev, RPM_GET_PUT | RPM_AUTO);

commit 3ff5588d3f8afad65ded52ac0e4191462fe034cb
+Author: Alan Stern 
+Date:   Tue Sep 7 11:44:01 2010 -0400
+
+    [SCSI] sd: improve logic and efficiecy of media-change detection
+    
+    This patch (as1415) improves the formerly incomprehensible logic in
+    sd_media_changed() (the current code refers to "changed" as a state,
+    whereas in fact it is a relation between two states).  It also adds a
+    big comment so that everyone can understand what is really going on.
+    
+    The patch also improves efficiency by not reporting a media change
+    when no medium was ever present.  If no medium was present the last
+    time we checked and there's still no medium, it's not necessary to
+    tell the caller that a change occurred.  Doing so merely causes the
+    caller to attempt to revalidate a non-existent disk, which is a waste
+    of time.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+index 956496182c80..26f9d54a9c92 100644
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -583,7 +583,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
+ 		 * quietly refuse to do anything to a changed disc until 
+ 		 * the changed bit has been reset
+ 		 */
+-		/* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */
++		/* printk("SCSI disk has been changed or is not present. Prohibiting further I/O.\n"); */
+ 		goto out;
+ 	}
+ 
+@@ -1023,7 +1023,6 @@ static int sd_media_changed(struct gendisk *disk)
+ 	 */
+ 	if (!scsi_device_online(sdp)) {
+ 		set_media_not_present(sdkp);
+-		retval = 1;
+ 		goto out;
+ 	}
+ 
+@@ -1054,7 +1053,6 @@ static int sd_media_changed(struct gendisk *disk)
+ 		       /* 0x3a is medium not present */
+ 		       sshdr->asc == 0x3a)) {
+ 		set_media_not_present(sdkp);
+-		retval = 1;
+ 		goto out;
+ 	}
+ 
+@@ -1065,12 +1063,27 @@ static int sd_media_changed(struct gendisk *disk)
+ 	 */
+ 	sdkp->media_present = 1;
+ 
+-	retval = sdp->changed;
+-	sdp->changed = 0;
+ out:
+-	if (retval != sdkp->previous_state)
++	/*
++	 * Report a media change under the following conditions:
++	 *
++	 *	Medium is present now and wasn't present before.
++	 *	Medium wasn't present before and is present now.
++	 *	Medium was present at all times, but it changed while
++	 *		we weren't looking (sdp->changed is set).
++	 *
++	 * If there was no medium before and there is no medium now then
++	 * don't report a change, even if a medium was inserted and removed
++	 * while we weren't looking.
++	 */
++	retval = (sdkp->media_present != sdkp->previous_state ||
++			(sdkp->media_present && sdp->changed));
++	if (retval)
+ 		sdev_evt_send_simple(sdp, SDEV_EVT_MEDIA_CHANGE, GFP_KERNEL);
+-	sdkp->previous_state = retval;
++	sdkp->previous_state = sdkp->media_present;
++
++	/* sdp->changed indicates medium was changed or is not present */
++	sdp->changed = !sdkp->media_present;
+ 	kfree(sshdr);
+ 	return retval;
+ }

commit abf03184a31a3286fc0ab30f838ddee8ba9f9b7b
+Author: Alan Stern 
+Date:   Mon Nov 29 10:17:22 2010 -0500
+
+    USB: fix autosuspend bug in usb-serial
+    
+    This patch (as1437) fixes a bug in the usb-serial autosuspend
+    handling.  Since the usb-serial core now has autosuspend support, it
+    must set the .supports_autosuspend member in every serial driver it
+    registers.  Otherwise the usb_autopm_get_interface() call won't work.
+    
+    This fixes Bugzilla #23012.
+    
+    Signed-off-by: Alan Stern 
+    CC: stable@kernel.org
+    Reported-by: Kevin Smith 
+    Reported-and-tested-by: Simon Gerber 
+    Reported-and-tested-by: Matteo Croce 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
+index 861223f2af6e..6954de50c0ff 100644
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -51,6 +51,7 @@ static struct usb_driver usb_serial_driver = {
+ 	.suspend =	usb_serial_suspend,
+ 	.resume =	usb_serial_resume,
+ 	.no_dynamic_id = 	1,
++	.supports_autosuspend =	1,
+ };
+ 
+ /* There is no MODULE_DEVICE_TABLE for usbserial.c.  Instead
+@@ -1343,6 +1344,8 @@ int usb_serial_register(struct usb_serial_driver *driver)
+ 		return -ENODEV;
+ 
+ 	fixup_generic(driver);
++	if (driver->usb_driver)
++		driver->usb_driver->supports_autosuspend = 1;
+ 
+ 	if (!driver->description)
+ 		driver->description = driver->driver.name;

commit e030d58e8860f1c87b17631dbdd70747cbe1fb5b
+Author: Alan Stern 
+Date:   Mon Nov 15 15:46:07 2010 -0500
+
+    sysfs: remove useless test from sysfs_merge_group
+    
+    Dan Carpenter pointed out that the new sysfs_merge_group() and
+    sysfs_unmerge_group() routines requires their grp argument to be
+    non-NULL, because they dereference grp to obtain the list of
+    attributes.  Hence it's pointless for the routines to include a test
+    and special-case handling for when grp is NULL.  This patch (as1433)
+    removes the unneeded tests.
+    
+    Signed-off-by: Alan Stern 
+    CC: Dan Carpenter 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
+index 442f34ff1af8..c8769dc222d8 100644
+--- a/fs/sysfs/group.c
++++ b/fs/sysfs/group.c
+@@ -165,10 +165,7 @@ int sysfs_merge_group(struct kobject *kobj,
+ 	struct attribute *const *attr;
+ 	int i;
+ 
+-	if (grp)
+-		dir_sd = sysfs_get_dirent(kobj->sd, NULL, grp->name);
+-	else
+-		dir_sd = sysfs_get(kobj->sd);
++	dir_sd = sysfs_get_dirent(kobj->sd, NULL, grp->name);
+ 	if (!dir_sd)
+ 		return -ENOENT;
+ 
+@@ -195,10 +192,7 @@ void sysfs_unmerge_group(struct kobject *kobj,
+ 	struct sysfs_dirent *dir_sd;
+ 	struct attribute *const *attr;
+ 
+-	if (grp)
+-		dir_sd = sysfs_get_dirent(kobj->sd, NULL, grp->name);
+-	else
+-		dir_sd = sysfs_get(kobj->sd);
++	dir_sd = sysfs_get_dirent(kobj->sd, NULL, grp->name);
+ 	if (dir_sd) {
+ 		for (attr = grp->attrs; *attr; ++attr)
+ 			sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name);

commit 73d8c34f3d78ccf90a431c221df10377affce650
+Author: Alan Stern 
+Date:   Mon Nov 15 16:03:04 2010 -0500
+
+    SCSI: improve two error messages
+    
+    This trivial patch (as1338) makes two uninformative error messages in
+    scsi_sysfs_add_sdev() more explicit.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
+index 20ad59dff730..9c52ce4f7129 100644
+--- a/drivers/scsi/scsi_sysfs.c
++++ b/drivers/scsi/scsi_sysfs.c
+@@ -864,13 +864,15 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
+ 
+ 	error = device_add(&sdev->sdev_gendev);
+ 	if (error) {
+-		printk(KERN_INFO "error 1\n");
++		sdev_printk(KERN_INFO, sdev,
++				"failed to add device: %d\n", error);
+ 		return error;
+ 	}
+ 	device_enable_async_suspend(&sdev->sdev_dev);
+ 	error = device_add(&sdev->sdev_dev);
+ 	if (error) {
+-		printk(KERN_INFO "error 2\n");
++		sdev_printk(KERN_INFO, sdev,
++				"failed to add class device: %d\n", error);
+ 		device_del(&sdev->sdev_gendev);
+ 		return error;
+ 	}

commit 2f15744c1d90ee2e82f8ae5724b44b1cdf31715c
+Author: Alan Stern 
+Date:   Wed Nov 17 10:56:01 2010 -0500
+
+    USB: fix leftover references to udev->autosuspend_delay
+    
+    This patch (as1436) takes care of leftover references to
+    udev->autosuspend_delay that didn't get removed during the earlier
+    conversion to the runtime-PM autosuspend API.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/media/video/tlg2300/pd-main.c b/drivers/media/video/tlg2300/pd-main.c
+index 4555f4a5f4c8..e33b428a8015 100644
+--- a/drivers/media/video/tlg2300/pd-main.c
++++ b/drivers/media/video/tlg2300/pd-main.c
+@@ -453,7 +453,8 @@ static int poseidon_probe(struct usb_interface *interface,
+ 
+ 	device_init_wakeup(&udev->dev, 1);
+ #ifdef CONFIG_PM
+-	pd->udev->autosuspend_delay = HZ * PM_SUSPEND_DELAY;
++	pm_runtime_set_autosuspend_delay(&pd->udev->dev,
++			1000 * PM_SUSPEND_DELAY);
+ 	usb_enable_autosuspend(pd->udev);
+ 
+ 	if (in_hibernation(pd)) {
+diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c
+index d3365ac85dde..7cb375515e1e 100644
+--- a/drivers/net/wimax/i2400m/usb.c
++++ b/drivers/net/wimax/i2400m/usb.c
+@@ -514,7 +514,7 @@ int i2400mu_probe(struct usb_interface *iface,
+ #ifdef CONFIG_PM
+ 	iface->needs_remote_wakeup = 1;		/* autosuspend (15s delay) */
+ 	device_init_wakeup(dev, 1);
+-	usb_dev->autosuspend_delay = 15 * HZ;
++	pm_runtime_set_autosuspend_delay(&usb_dev->dev, 15000);
+ 	usb_enable_autosuspend(usb_dev);
+ #endif
+ 
+diff --git a/drivers/staging/bcm/InterfaceInit.c b/drivers/staging/bcm/InterfaceInit.c
+index 824f9a45007a..e97ad99b1bb4 100644
+--- a/drivers/staging/bcm/InterfaceInit.c
++++ b/drivers/staging/bcm/InterfaceInit.c
+@@ -277,7 +277,7 @@ usbbcm_device_probe(struct usb_interface *intf, const struct usb_device_id *id)
+ 		if(psAdapter->bDoSuspend)
+ 		{
+ #ifdef CONFIG_PM
+-			udev->autosuspend_delay = 0;
++			pm_runtime_set_autosuspend_delay(&udev->dev, 0);
+ 			intf->needs_remote_wakeup = 1;
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
+  			udev->autosuspend_disabled = 0;

commit c08512c761e7b9eaaab0e9167a389393f268e93c
+Author: Alan Stern 
+Date:   Mon Nov 15 15:57:58 2010 -0500
+
+    USB: improve uses of usb_mark_last_busy
+    
+    This patch (as1434) cleans up the uses of usb_mark_last_busy() in
+    usbcore.  The function will be called when a device is resumed and
+    whenever a usage count is decremented.  A call that was missing from
+    the hub driver is added: A hub is used whenever one of its ports gets
+    suspended (this prevents hubs from suspending immediately after their
+    last child).
+    
+    In addition, the call to disable autosuspend support for new devices
+    by default is moved from usb_detect_quirks() (where it doesn't really
+    belong) into usb_new_device() along with all the other runtime-PM
+    initializations.  Finally, an extra pm_runtime_get_noresume() is added
+    to prevent new devices from autosuspending while they are being
+    registered.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 43c25c29ac1f..b9278a1fb9e5 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1261,6 +1261,7 @@ static int usb_resume_both(struct usb_device *udev, pm_message_t msg)
+ 					udev->reset_resume);
+ 		}
+ 	}
++	usb_mark_last_busy(udev);
+ 
+  done:
+ 	dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
+@@ -1328,7 +1329,6 @@ int usb_resume(struct device *dev, pm_message_t msg)
+ 			pm_runtime_disable(dev);
+ 			pm_runtime_set_active(dev);
+ 			pm_runtime_enable(dev);
+-			usb_mark_last_busy(udev);
+ 			do_unbind_rebind(udev, DO_REBIND);
+ 		}
+ 	}
+@@ -1660,11 +1660,6 @@ static int usb_runtime_suspend(struct device *dev)
+ 		return -EAGAIN;
+ 
+ 	status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
+-
+-	/* Prevent the parent from suspending immediately after */
+-	if (status == 0 && udev->parent)
+-		usb_mark_last_busy(udev->parent);
+-
+ 	return status;
+ }
+ 
+@@ -1677,7 +1672,6 @@ static int usb_runtime_resume(struct device *dev)
+ 	 * and all its interfaces.
+ 	 */
+ 	status = usb_resume_both(udev, PMSG_AUTO_RESUME);
+-	usb_mark_last_busy(udev);
+ 	return status;
+ }
+ 
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index fdb62ca10d86..b98efae6a1cf 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1803,9 +1803,15 @@ int usb_new_device(struct usb_device *udev)
+ 
+ 	/* Tell the runtime-PM framework the device is active */
+ 	pm_runtime_set_active(&udev->dev);
++	pm_runtime_get_noresume(&udev->dev);
+ 	pm_runtime_use_autosuspend(&udev->dev);
+ 	pm_runtime_enable(&udev->dev);
+ 
++	/* By default, forbid autosuspend for all devices.  It will be
++	 * allowed for hubs during binding.
++	 */
++	usb_disable_autosuspend(udev);
++
+ 	err = usb_enumerate_device(udev);	/* Read descriptors */
+ 	if (err < 0)
+ 		goto fail;
+@@ -1831,6 +1837,8 @@ int usb_new_device(struct usb_device *udev)
+ 	}
+ 
+ 	(void) usb_create_ep_devs(&udev->dev, &udev->ep0, udev);
++	usb_mark_last_busy(udev);
++	pm_runtime_put_sync_autosuspend(&udev->dev);
+ 	return err;
+ 
+ fail:
+@@ -2221,6 +2229,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ 		usb_set_device_state(udev, USB_STATE_SUSPENDED);
+ 		msleep(10);
+ 	}
++	usb_mark_last_busy(hub->hdev);
+ 	return status;
+ }
+ 
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index e3531da16137..44c595432d6f 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -117,15 +117,6 @@ void usb_detect_quirks(struct usb_device *udev)
+ 		dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
+ 				udev->quirks);
+ 
+-#ifdef	CONFIG_USB_SUSPEND
+-
+-	/* By default, disable autosuspend for all devices.  The hub driver
+-	 * will enable it for hubs.
+-	 */
+-	usb_disable_autosuspend(udev);
+-
+-#endif
+-
+ 	/* For the present, all devices default to USB-PERSIST enabled */
+ #if 0		/* was: #ifdef CONFIG_PM */
+ 	/* Hubs are automatically enabled for USB-PERSIST */

commit fcc4a01eb8661226e80632327673f67bf6a5840b
+Author: Alan Stern 
+Date:   Mon Nov 15 15:57:51 2010 -0500
+
+    USB: use the runtime-PM autosuspend implementation
+    
+    This patch (as1428) converts USB over to the new runtime-PM core
+    autosuspend framework.  One slightly awkward aspect of the conversion
+    is that USB devices will now have two suspend-delay attributes: the
+    old power/autosuspend file and the new power/autosuspend_delay_ms
+    file.  One expresses the delay time in seconds and the other in
+    milliseconds, but otherwise they do the same thing.  The old attribute
+    can be deprecated and then removed eventually.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt
+index b29d8e56cf28..c9ffa9ced7ee 100644
+--- a/Documentation/usb/power-management.txt
++++ b/Documentation/usb/power-management.txt
+@@ -2,7 +2,7 @@
+ 
+ 		 Alan Stern 
+ 
+-			    December 11, 2009
++			    October 28, 2010
+ 
+ 
+ 
+@@ -107,9 +107,14 @@ allowed to issue dynamic suspends.
+ The user interface for controlling dynamic PM is located in the power/
+ subdirectory of each USB device's sysfs directory, that is, in
+ /sys/bus/usb/devices/.../power/ where "..." is the device's ID.  The
+-relevant attribute files are: wakeup, control, and autosuspend.
+-(There may also be a file named "level"; this file was deprecated
+-as of the 2.6.35 kernel and replaced by the "control" file.)
++relevant attribute files are: wakeup, control, and
++autosuspend_delay_ms.  (There may also be a file named "level"; this
++file was deprecated as of the 2.6.35 kernel and replaced by the
++"control" file.  In 2.6.38 the "autosuspend" file will be deprecated
++and replaced by the "autosuspend_delay_ms" file.  The only difference
++is that the newer file expresses the delay in milliseconds whereas the
++older file uses seconds.  Confusingly, both files are present in 2.6.37
++but only "autosuspend" works.)
+ 
+ 	power/wakeup
+ 
+@@ -140,33 +145,36 @@ as of the 2.6.35 kernel and replaced by the "control" file.)
+ 		suspended and autoresume was not allowed.  This
+ 		setting is no longer supported.)
+ 
+-	power/autosuspend
++	power/autosuspend_delay_ms
+ 
+ 		This file contains an integer value, which is the
+-		number of seconds the device should remain idle before
+-		the kernel will autosuspend it (the idle-delay time).
+-		The default is 2.  0 means to autosuspend as soon as
+-		the device becomes idle, and negative values mean
+-		never to autosuspend.  You can write a number to the
+-		file to change the autosuspend idle-delay time.
+-
+-Writing "-1" to power/autosuspend and writing "on" to power/control do
+-essentially the same thing -- they both prevent the device from being
+-autosuspended.  Yes, this is a redundancy in the API.
++		number of milliseconds the device should remain idle
++		before the kernel will autosuspend it (the idle-delay
++		time).  The default is 2000.  0 means to autosuspend
++		as soon as the device becomes idle, and negative
++		values mean never to autosuspend.  You can write a
++		number to the file to change the autosuspend
++		idle-delay time.
++
++Writing "-1" to power/autosuspend_delay_ms and writing "on" to
++power/control do essentially the same thing -- they both prevent the
++device from being autosuspended.  Yes, this is a redundancy in the
++API.
+ 
+ (In 2.6.21 writing "0" to power/autosuspend would prevent the device
+ from being autosuspended; the behavior was changed in 2.6.22.  The
+ power/autosuspend attribute did not exist prior to 2.6.21, and the
+ power/level attribute did not exist prior to 2.6.22.  power/control
+-was added in 2.6.34.)
++was added in 2.6.34, and power/autosuspend_delay_ms was added in
++2.6.37 but did not become functional until 2.6.38.)
+ 
+ 
+ 	Changing the default idle-delay time
+ 	------------------------------------
+ 
+-The default autosuspend idle-delay time is controlled by a module
+-parameter in usbcore.  You can specify the value when usbcore is
+-loaded.  For example, to set it to 5 seconds instead of 2 you would
++The default autosuspend idle-delay time (in seconds) is controlled by
++a module parameter in usbcore.  You can specify the value when usbcore
++is loaded.  For example, to set it to 5 seconds instead of 2 you would
+ do:
+ 
+ 	modprobe usbcore autosuspend=5
+@@ -234,25 +242,23 @@ every device.
+ 
+ If a driver knows that its device has proper suspend/resume support,
+ it can enable autosuspend all by itself.  For example, the video
+-driver for a laptop's webcam might do this, since these devices are
+-rarely used and so should normally be autosuspended.
++driver for a laptop's webcam might do this (in recent kernels they
++do), since these devices are rarely used and so should normally be
++autosuspended.
+ 
+ Sometimes it turns out that even when a device does work okay with
+-autosuspend there are still problems.  For example, there are
+-experimental patches adding autosuspend support to the usbhid driver,
+-which manages keyboards and mice, among other things.  Tests with a
+-number of keyboards showed that typing on a suspended keyboard, while
+-causing the keyboard to do a remote wakeup all right, would
+-nonetheless frequently result in lost keystrokes.  Tests with mice
+-showed that some of them would issue a remote-wakeup request in
+-response to button presses but not to motion, and some in response to
+-neither.
++autosuspend there are still problems.  For example, the usbhid driver,
++which manages keyboards and mice, has autosuspend support.  Tests with
++a number of keyboards show that typing on a suspended keyboard, while
++causing the keyboard to do a remote wakeup all right, will nonetheless
++frequently result in lost keystrokes.  Tests with mice show that some
++of them will issue a remote-wakeup request in response to button
++presses but not to motion, and some in response to neither.
+ 
+ The kernel will not prevent you from enabling autosuspend on devices
+ that can't handle it.  It is even possible in theory to damage a
+-device by suspending it at the wrong time -- for example, suspending a
+-USB hard disk might cause it to spin down without parking the heads.
+-(Highly unlikely, but possible.)  Take care.
++device by suspending it at the wrong time.  (Highly unlikely, but
++possible.)  Take care.
+ 
+ 
+ 	The driver interface for Power Management
+@@ -336,10 +342,6 @@ autosuspend the interface's device.  When the usage counter is = 0
+ then the interface is considered to be idle, and the kernel may
+ autosuspend the device.
+ 
+-(There is a similar usage counter field in struct usb_device,
+-associated with the device itself rather than any of its interfaces.
+-This counter is used only by the USB core.)
+-
+ Drivers need not be concerned about balancing changes to the usage
+ counter; the USB core will undo any remaining "get"s when a driver
+ is unbound from its interface.  As a corollary, drivers must not call
+@@ -409,11 +411,11 @@ during autosuspend.  For example, there's not much point
+ autosuspending a keyboard if the user can't cause the keyboard to do a
+ remote wakeup by typing on it.  If the driver sets
+ intf->needs_remote_wakeup to 1, the kernel won't autosuspend the
+-device if remote wakeup isn't available or has been disabled through
+-the power/wakeup attribute.  (If the device is already autosuspended,
+-though, setting this flag won't cause the kernel to autoresume it.
+-Normally a driver would set this flag in its probe method, at which
+-time the device is guaranteed not to be autosuspended.)
++device if remote wakeup isn't available.  (If the device is already
++autosuspended, though, setting this flag won't cause the kernel to
++autoresume it.  Normally a driver would set this flag in its probe
++method, at which time the device is guaranteed not to be
++autosuspended.)
+ 
+ If a driver does its I/O asynchronously in interrupt context, it
+ should call usb_autopm_get_interface_async() before starting output and
+@@ -422,20 +424,19 @@ it receives an input event, it should call
+ 
+ 	usb_mark_last_busy(struct usb_device *udev);
+ 
+-in the event handler.  This sets udev->last_busy to the current time.
+-udev->last_busy is the field used for idle-delay calculations;
+-updating it will cause any pending autosuspend to be moved back.  Most
+-of the usb_autopm_* routines will also set the last_busy field to the
+-current time.
++in the event handler.  This tells the PM core that the device was just
++busy and therefore the next autosuspend idle-delay expiration should
++be pushed back.  Many of the usb_autopm_* routines also make this call,
++so drivers need to worry only when interrupt-driven input arrives.
+ 
+ Asynchronous operation is always subject to races.  For example, a
+-driver may call one of the usb_autopm_*_interface_async() routines at
+-a time when the core has just finished deciding the device has been
+-idle for long enough but not yet gotten around to calling the driver's
+-suspend method.  The suspend method must be responsible for
+-synchronizing with the output request routine and the URB completion
+-handler; it should cause autosuspends to fail with -EBUSY if the
+-driver needs to use the device.
++driver may call the usb_autopm_get_interface_async() routine at a time
++when the core has just finished deciding the device has been idle for
++long enough but not yet gotten around to calling the driver's suspend
++method.  The suspend method must be responsible for synchronizing with
++the I/O request routine and the URB completion handler; it should
++cause autosuspends to fail with -EBUSY if the driver needs to use the
++device.
+ 
+ External suspend calls should never be allowed to fail in this way,
+ only autosuspend calls.  The driver can tell them apart by checking
+@@ -472,7 +473,9 @@ Firstly, a device may already be autosuspended when a system suspend
+ occurs.  Since system suspends are supposed to be as transparent as
+ possible, the device should remain suspended following the system
+ resume.  But this theory may not work out well in practice; over time
+-the kernel's behavior in this regard has changed.
++the kernel's behavior in this regard has changed.  As of 2.6.37 the
++policy is to resume all devices during a system resume and let them
++handle their own runtime suspends afterward.
+ 
+ Secondly, a dynamic power-management event may occur as a system
+ suspend is underway.  The window for this is short, since system
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 0a63e968c683..43c25c29ac1f 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1397,32 +1397,7 @@ void usb_autosuspend_device(struct usb_device *udev)
+ 	int	status;
+ 
+ 	usb_mark_last_busy(udev);
+-	status = pm_runtime_put_sync(&udev->dev);
+-	dev_vdbg(&udev->dev, "%s: cnt %d -> %d\n",
+-			__func__, atomic_read(&udev->dev.power.usage_count),
+-			status);
+-}
+-
+-/**
+- * usb_try_autosuspend_device - attempt an autosuspend of a USB device and its interfaces
+- * @udev: the usb_device to autosuspend
+- *
+- * This routine should be called when a core subsystem thinks @udev may
+- * be ready to autosuspend.
+- *
+- * @udev's usage counter left unchanged.  If it is 0 and all the interfaces
+- * are inactive then an autosuspend will be attempted.  The attempt may
+- * fail or be delayed.
+- *
+- * The caller must hold @udev's device lock.
+- *
+- * This routine can run only in process context.
+- */
+-void usb_try_autosuspend_device(struct usb_device *udev)
+-{
+-	int	status;
+-
+-	status = pm_runtime_idle(&udev->dev);
++	status = pm_runtime_put_sync_autosuspend(&udev->dev);
+ 	dev_vdbg(&udev->dev, "%s: cnt %d -> %d\n",
+ 			__func__, atomic_read(&udev->dev.power.usage_count),
+ 			status);
+@@ -1508,32 +1483,11 @@ EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
+ void usb_autopm_put_interface_async(struct usb_interface *intf)
+ {
+ 	struct usb_device	*udev = interface_to_usbdev(intf);
+-	unsigned long		last_busy;
+-	int			status = 0;
++	int			status;
+ 
+-	last_busy = udev->dev.power.last_busy;
+ 	usb_mark_last_busy(udev);
+ 	atomic_dec(&intf->pm_usage_cnt);
+-	pm_runtime_put_noidle(&intf->dev);
+-
+-	if (udev->dev.power.runtime_auto) {
+-		/* Optimization: Don't schedule a delayed autosuspend if
+-		 * the timer is already running and the expiration time
+-		 * wouldn't change.
+-		 *
+-		 * We have to use the interface's timer.  Attempts to
+-		 * schedule a suspend for the device would fail because
+-		 * the interface is still active.
+-		 */
+-		if (intf->dev.power.timer_expires == 0 ||
+-				round_jiffies_up(last_busy) !=
+-				round_jiffies_up(jiffies)) {
+-			status = pm_schedule_suspend(&intf->dev,
+-					jiffies_to_msecs(
+-					round_jiffies_up_relative(
+-						udev->autosuspend_delay)));
+-		}
+-	}
++	status = pm_runtime_put(&intf->dev);
+ 	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
+ 			__func__, atomic_read(&intf->dev.power.usage_count),
+ 			status);
+@@ -1651,7 +1605,6 @@ static int autosuspend_check(struct usb_device *udev)
+ {
+ 	int			w, i;
+ 	struct usb_interface	*intf;
+-	unsigned long		suspend_time, j;
+ 
+ 	/* Fail if autosuspend is disabled, or any interfaces are in use, or
+ 	 * any interface drivers require remote wakeup but it isn't available.
+@@ -1691,17 +1644,6 @@ static int autosuspend_check(struct usb_device *udev)
+ 		return -EOPNOTSUPP;
+ 	}
+ 	udev->do_remote_wakeup = w;
+-
+-	/* If everything is okay but the device hasn't been idle for long
+-	 * enough, queue a delayed autosuspend request.
+-	 */
+-	j = ACCESS_ONCE(jiffies);
+-	suspend_time = udev->dev.power.last_busy + udev->autosuspend_delay;
+-	if (time_before(j, suspend_time)) {
+-		pm_schedule_suspend(&udev->dev, jiffies_to_msecs(
+-				round_jiffies_up_relative(suspend_time - j)));
+-		return -EAGAIN;
+-	}
+ 	return 0;
+ }
+ 
+@@ -1719,17 +1661,8 @@ static int usb_runtime_suspend(struct device *dev)
+ 
+ 	status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
+ 
+-	/* If an interface fails the suspend, adjust the last_busy
+-	 * time so that we don't get another suspend attempt right
+-	 * away.
+-	 */
+-	if (status) {
+-		udev->dev.power.last_busy = jiffies +
+-				(udev->autosuspend_delay == 0 ? HZ/2 : 0);
+-	}
+-
+ 	/* Prevent the parent from suspending immediately after */
+-	else if (udev->parent)
++	if (status == 0 && udev->parent)
+ 		usb_mark_last_busy(udev->parent);
+ 
+ 	return status;
+@@ -1756,7 +1689,7 @@ static int usb_runtime_idle(struct device *dev)
+ 	 * autosuspend checks.
+ 	 */
+ 	if (autosuspend_check(udev) == 0)
+-		pm_runtime_suspend(dev);
++		pm_runtime_autosuspend(dev);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 7c2405eccc4b..fdb62ca10d86 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1803,6 +1803,7 @@ int usb_new_device(struct usb_device *udev)
+ 
+ 	/* Tell the runtime-PM framework the device is active */
+ 	pm_runtime_set_active(&udev->dev);
++	pm_runtime_use_autosuspend(&udev->dev);
+ 	pm_runtime_enable(&udev->dev);
+ 
+ 	err = usb_enumerate_device(udev);	/* Read descriptors */
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index 25719da45e33..e3531da16137 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -124,12 +124,6 @@ void usb_detect_quirks(struct usb_device *udev)
+ 	 */
+ 	usb_disable_autosuspend(udev);
+ 
+-	/* Autosuspend can also be disabled if the initial autosuspend_delay
+-	 * is negative.
+-	 */
+-	if (udev->autosuspend_delay < 0)
+-		usb_autoresume_device(udev);
+-
+ #endif
+ 
+ 	/* For the present, all devices default to USB-PERSIST enabled */
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 9561e087907d..6781c369ce2d 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -334,44 +334,20 @@ static DEVICE_ATTR(active_duration, S_IRUGO, show_active_duration, NULL);
+ static ssize_t
+ show_autosuspend(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+-	struct usb_device *udev = to_usb_device(dev);
+-
+-	return sprintf(buf, "%d\n", udev->autosuspend_delay / HZ);
++	return sprintf(buf, "%d\n", dev->power.autosuspend_delay / 1000);
+ }
+ 
+ static ssize_t
+ set_autosuspend(struct device *dev, struct device_attribute *attr,
+ 		const char *buf, size_t count)
+ {
+-	struct usb_device *udev = to_usb_device(dev);
+-	int value, old_delay;
+-	int rc;
++	int value;
+ 
+-	if (sscanf(buf, "%d", &value) != 1 || value >= INT_MAX/HZ ||
+-			value <= - INT_MAX/HZ)
++	if (sscanf(buf, "%d", &value) != 1 || value >= INT_MAX/1000 ||
++			value <= -INT_MAX/1000)
+ 		return -EINVAL;
+-	value *= HZ;
+-
+-	usb_lock_device(udev);
+-	old_delay = udev->autosuspend_delay;
+-	udev->autosuspend_delay = value;
+-
+-	if (old_delay < 0) {	/* Autosuspend wasn't allowed */
+-		if (value >= 0)
+-			usb_autosuspend_device(udev);
+-	} else {		/* Autosuspend was allowed */
+-		if (value < 0) {
+-			rc = usb_autoresume_device(udev);
+-			if (rc < 0) {
+-				count = rc;
+-				udev->autosuspend_delay = old_delay;
+-			}
+-		} else {
+-			usb_try_autosuspend_device(udev);
+-		}
+-	}
+ 
+-	usb_unlock_device(udev);
++	pm_runtime_set_autosuspend_delay(dev, value * 1000);
+ 	return count;
+ }
+ 
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index fdd4130fbb7d..079cb57bab4f 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -445,7 +445,8 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
+ 	INIT_LIST_HEAD(&dev->filelist);
+ 
+ #ifdef	CONFIG_PM
+-	dev->autosuspend_delay = usb_autosuspend_delay * HZ;
++	pm_runtime_set_autosuspend_delay(&dev->dev,
++			usb_autosuspend_delay * 1000);
+ 	dev->connect_time = jiffies;
+ 	dev->active_duration = -jiffies;
+ #endif
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index cd882203ad34..b975450f403e 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -75,14 +75,12 @@ static inline int usb_port_resume(struct usb_device *udev, pm_message_t msg)
+ #ifdef CONFIG_USB_SUSPEND
+ 
+ extern void usb_autosuspend_device(struct usb_device *udev);
+-extern void usb_try_autosuspend_device(struct usb_device *udev);
+ extern int usb_autoresume_device(struct usb_device *udev);
+ extern int usb_remote_wakeup(struct usb_device *dev);
+ 
+ #else
+ 
+ #define usb_autosuspend_device(udev)		do {} while (0)
+-#define usb_try_autosuspend_device(udev)	do {} while (0)
+ static inline int usb_autoresume_device(struct usb_device *udev)
+ {
+ 	return 0;
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 7d22b3340a7f..5ee2223af08c 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -408,7 +408,6 @@ struct usb_tt;
+  * @quirks: quirks of the whole device
+  * @urbnum: number of URBs submitted for the whole device
+  * @active_duration: total time device is not suspended
+- * @autosuspend_delay: in jiffies
+  * @connect_time: time device was first connected
+  * @do_remote_wakeup:  remote wakeup should be enabled
+  * @reset_resume: needs reset instead of resume
+@@ -481,7 +480,6 @@ struct usb_device {
+ 	unsigned long active_duration;
+ 
+ #ifdef CONFIG_PM
+-	int autosuspend_delay;
+ 	unsigned long connect_time;
+ 
+ 	unsigned do_remote_wakeup:1;

commit 045cac6b3b067a9286dabfb789f67ae4f433f88b
+Author: Alan Stern 
+Date:   Mon Nov 15 15:57:07 2010 -0500
+
+    USB: use sysfs_merge_group for power attributes
+    
+    This patch (as1426) makes use of the new sysfs_merge_group() and
+    sysfs_unmerge_group() routines to simplify the handling of power
+    attributes for USB devices.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 448f5b47fc48..9561e087907d 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -233,8 +233,6 @@ static DEVICE_ATTR(urbnum, S_IRUGO, show_urbnum, NULL);
+ 
+ #ifdef	CONFIG_PM
+ 
+-static const char power_group[] = "power";
+-
+ static ssize_t
+ show_persist(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+@@ -278,7 +276,7 @@ static int add_persist_attributes(struct device *dev)
+ 		if (udev->descriptor.bDeviceClass != USB_CLASS_HUB)
+ 			rc = sysfs_add_file_to_group(&dev->kobj,
+ 					&dev_attr_persist.attr,
+-					power_group);
++					power_group_name);
+ 	}
+ 	return rc;
+ }
+@@ -287,7 +285,7 @@ static void remove_persist_attributes(struct device *dev)
+ {
+ 	sysfs_remove_file_from_group(&dev->kobj,
+ 			&dev_attr_persist.attr,
+-			power_group);
++			power_group_name);
+ }
+ #else
+ 
+@@ -438,44 +436,30 @@ set_level(struct device *dev, struct device_attribute *attr,
+ 
+ static DEVICE_ATTR(level, S_IRUGO | S_IWUSR, show_level, set_level);
+ 
++static struct attribute *power_attrs[] = {
++	&dev_attr_autosuspend.attr,
++	&dev_attr_level.attr,
++	&dev_attr_connected_duration.attr,
++	&dev_attr_active_duration.attr,
++	NULL,
++};
++static struct attribute_group power_attr_group = {
++	.name	= power_group_name,
++	.attrs	= power_attrs,
++};
++
+ static int add_power_attributes(struct device *dev)
+ {
+ 	int rc = 0;
+ 
+-	if (is_usb_device(dev)) {
+-		rc = sysfs_add_file_to_group(&dev->kobj,
+-				&dev_attr_autosuspend.attr,
+-				power_group);
+-		if (rc == 0)
+-			rc = sysfs_add_file_to_group(&dev->kobj,
+-					&dev_attr_level.attr,
+-					power_group);
+-		if (rc == 0)
+-			rc = sysfs_add_file_to_group(&dev->kobj,
+-					&dev_attr_connected_duration.attr,
+-					power_group);
+-		if (rc == 0)
+-			rc = sysfs_add_file_to_group(&dev->kobj,
+-					&dev_attr_active_duration.attr,
+-					power_group);
+-	}
++	if (is_usb_device(dev))
++		rc = sysfs_merge_group(&dev->kobj, &power_attr_group);
+ 	return rc;
+ }
+ 
+ static void remove_power_attributes(struct device *dev)
+ {
+-	sysfs_remove_file_from_group(&dev->kobj,
+-			&dev_attr_active_duration.attr,
+-			power_group);
+-	sysfs_remove_file_from_group(&dev->kobj,
+-			&dev_attr_connected_duration.attr,
+-			power_group);
+-	sysfs_remove_file_from_group(&dev->kobj,
+-			&dev_attr_level.attr,
+-			power_group);
+-	sysfs_remove_file_from_group(&dev->kobj,
+-			&dev_attr_autosuspend.attr,
+-			power_group);
++	sysfs_unmerge_group(&dev->kobj, &power_attr_group);
+ }
+ 
+ #else

commit 02e2c51ba3e80acde600721ea784c3ef84da5ea1
+Author: Alan Stern 
+Date:   Tue Nov 16 10:57:37 2010 -0500
+
+    USB: EHCI: fix obscure race in ehci_endpoint_disable
+    
+    This patch (as1435) fixes an obscure and unlikely race in ehci-hcd.
+    When an async URB is unlinked, the corresponding QH is removed from
+    the async list.  If the QH's endpoint is then disabled while the URB
+    is being given back, ehci_endpoint_disable() won't find the QH on the
+    async list, causing it to believe that the QH has been lost.  This
+    will lead to a memory leak at best and quite possibly to an oops.
+    
+    The solution is to trust usbcore not to lose track of endpoints.  If
+    the QH isn't on the async list then it doesn't need to be taken off
+    the list, but the driver should still wait for the QH to become IDLE
+    before disabling it.
+    
+    In theory this fixes Bugzilla #20182.  In fact the race is so rare
+    that it's not possible to tell whether the bug is still present.
+    However, adding delays and making other changes to force the race
+    seems to show that the patch works.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Stefan Richter 
+    CC: David Brownell 
+    CC: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 502a7e6fef42..e9062806d4a2 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1063,10 +1063,11 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 				tmp && tmp != qh;
+ 				tmp = tmp->qh_next.qh)
+ 			continue;
+-		/* periodic qh self-unlinks on empty */
+-		if (!tmp)
+-			goto nogood;
+-		unlink_async (ehci, qh);
++		/* periodic qh self-unlinks on empty, and a COMPLETING qh
++		 * may already be unlinked.
++		 */
++		if (tmp)
++			unlink_async(ehci, qh);
+ 		/* FALL THROUGH */
+ 	case QH_STATE_UNLINK:		/* wait for hw to finish? */
+ 	case QH_STATE_UNLINK_WAIT:
+@@ -1083,7 +1084,6 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 		}
+ 		/* else FALL THROUGH */
+ 	default:
+-nogood:
+ 		/* caller was supposed to have unlinked any requests;
+ 		 * that's not our job.  just leak this memory.
+ 		 */

commit 56626a72a47bf3e50875d960d6b5f17b9bee0ab2
+Author: Alan Stern 
+Date:   Thu Oct 14 15:25:21 2010 -0400
+
+    USB: accept some invalid ep0-maxpacket values
+    
+    A few devices (such as the RCA VR5220 voice recorder) are so
+    non-compliant with the USB spec that they have invalid maxpacket sizes
+    for endpoint 0.  Nevertheless, as long as we can safely use them, we
+    may as well do so.
+    
+    This patch (as1432) softens our acceptance criterion by allowing
+    high-speed devices to have ep0-maxpacket sizes other than 64.  A
+    warning is printed in the system log when this happens, and the
+    existing error message is clarified.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: James 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 7f82c48a0bae..27115b45edc5 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2861,13 +2861,16 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ 	else
+ 		i = udev->descriptor.bMaxPacketSize0;
+ 	if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) {
+-		if (udev->speed != USB_SPEED_FULL ||
++		if (udev->speed == USB_SPEED_LOW ||
+ 				!(i == 8 || i == 16 || i == 32 || i == 64)) {
+-			dev_err(&udev->dev, "ep0 maxpacket = %d\n", i);
++			dev_err(&udev->dev, "Invalid ep0 maxpacket: %d\n", i);
+ 			retval = -EMSGSIZE;
+ 			goto fail;
+ 		}
+-		dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
++		if (udev->speed == USB_SPEED_FULL)
++			dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
++		else
++			dev_warn(&udev->dev, "Using ep0 maxpacket: %d\n", i);
+ 		udev->ep0.desc.wMaxPacketSize = cpu_to_le16(i);
+ 		usb_ep0_reinit(udev);
+ 	}

commit 80f0cf3947889014d3a3dc0ad60fb87cfda4b12a
+Author: Alan Stern 
+Date:   Thu Sep 30 15:16:23 2010 -0400
+
+    USB: disable endpoints after unbinding interfaces, not before
+    
+    This patch (as1430) fixes a bug in usbcore.  When a device
+    configuration change occurs or a device is removed, the endpoints for
+    the old config should be completely disabled.  However it turns out
+    they aren't; this is because usb_unbind_interface() calls
+    usb_enable_interface() or usb_set_interface() to put interfaces back
+    in altsetting 0, which re-enables the interfaces' endpoints.
+    
+    As a result, when a device goes through a config change or is
+    unconfigured, the ep_in[] and ep_out[] arrays may be left holding old
+    pointers to usb_host_endpoint structures.  If the device is
+    deauthorized these structures get freed, and the stale pointers cause
+    errors when the the device is eventually unplugged.
+    
+    The solution is to disable the endpoints after unbinding the
+    interfaces instead of before.  This isn't as large a change as it
+    sounds, since usb_unbind_interface() disables all the interface's
+    endpoints anyway before calling the driver's disconnect routine,
+    unless the driver claims to support "soft" unbind.
+    
+    This fixes Bugzilla #19192.  Thanks to "Tom" Lei Ming for diagnosing
+    the underlying cause of the problem.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Carsten Sommer 
+    CC: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 9f0ce7de0e36..d6e3e410477e 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1140,13 +1140,6 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
+ {
+ 	int i;
+ 
+-	dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__,
+-		skip_ep0 ? "non-ep0" : "all");
+-	for (i = skip_ep0; i < 16; ++i) {
+-		usb_disable_endpoint(dev, i, true);
+-		usb_disable_endpoint(dev, i + USB_DIR_IN, true);
+-	}
+-
+ 	/* getting rid of interfaces will disconnect
+ 	 * any drivers bound to them (a key side effect)
+ 	 */
+@@ -1176,6 +1169,13 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
+ 		if (dev->state == USB_STATE_CONFIGURED)
+ 			usb_set_device_state(dev, USB_STATE_ADDRESS);
+ 	}
++
++	dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__,
++		skip_ep0 ? "non-ep0" : "all");
++	for (i = skip_ep0; i < 16; ++i) {
++		usb_disable_endpoint(dev, i, true);
++		usb_disable_endpoint(dev, i + USB_DIR_IN, true);
++	}
+ }
+ 
+ /**

commit 834e2312e7a384877a876b0d34dffc3046c96bcb
+Author: Alan Stern 
+Date:   Mon Sep 13 10:43:25 2010 -0400
+
+    USB: teach "devices" file about Wireless and SuperSpeed USB
+    
+    The /sys/kernel/debug/usb/devices file doesn't know about Wireless or
+    SuperSpeed USB.  This patch (as1416b) teaches it, and updates the
+    Documentation/usb/proc_sub_info.txt file accordingly.
+    
+    Signed-off-by: Alan Stern 
+    CC: David Vrabel 
+    CC: Sarah Sharp 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/usb/proc_usb_info.txt b/Documentation/usb/proc_usb_info.txt
+index fafcd4723260..afe596d5f201 100644
+--- a/Documentation/usb/proc_usb_info.txt
++++ b/Documentation/usb/proc_usb_info.txt
+@@ -1,12 +1,17 @@
+ /proc/bus/usb filesystem output
+ ===============================
+-(version 2003.05.30)
++(version 2010.09.13)
+ 
+ 
+ The usbfs filesystem for USB devices is traditionally mounted at
+ /proc/bus/usb.  It provides the /proc/bus/usb/devices file, as well as
+ the /proc/bus/usb/BBB/DDD files.
+ 
++In many modern systems the usbfs filsystem isn't used at all.  Instead
++USB device nodes are created under /dev/usb/ or someplace similar.  The
++"devices" file is available in debugfs, typically as
++/sys/kernel/debug/usb/devices.
++
+ 
+ **NOTE**: If /proc/bus/usb appears empty, and a host controller
+ 	  driver has been linked, then you need to mount the
+@@ -106,8 +111,8 @@ Legend:
+ 
+ Topology info:
+ 
+-T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd
+-|   |      |      |       |       |      |        |       |__MaxChildren
++T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=dddd MxCh=dd
++|   |      |      |       |       |      |        |        |__MaxChildren
+ |   |      |      |       |       |      |        |__Device Speed in Mbps
+ |   |      |      |       |       |      |__DeviceNumber
+ |   |      |      |       |       |__Count of devices at this level
+@@ -120,8 +125,13 @@ T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd
+     Speed may be:
+     	1.5	Mbit/s for low speed USB
+ 	12	Mbit/s for full speed USB
+-	480	Mbit/s for high speed USB (added for USB 2.0)
++	480	Mbit/s for high speed USB (added for USB 2.0);
++		  also used for Wireless USB, which has no fixed speed
++	5000	Mbit/s for SuperSpeed USB (added for USB 3.0)
+ 
++    For reasons lost in the mists of time, the Port number is always
++    too low by 1.  For example, a device plugged into port 4 will
++    show up with "Port=03".
+ 
+ Bandwidth info:
+ B:  Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd
+@@ -291,7 +301,7 @@ Here's an example, from a system which has a UHCI root hub,
+ an external hub connected to the root hub, and a mouse and
+ a serial converter connected to the external hub.
+ 
+-T:  Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12  MxCh= 2
++T:  Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12   MxCh= 2
+ B:  Alloc= 28/900 us ( 3%), #Int=  2, #Iso=  0
+ D:  Ver= 1.00 Cls=09(hub  ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
+ P:  Vendor=0000 ProdID=0000 Rev= 0.00
+@@ -301,21 +311,21 @@ C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr=  0mA
+ I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
+ E:  Ad=81(I) Atr=03(Int.) MxPS=   8 Ivl=255ms
+ 
+-T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12  MxCh= 4
++T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12   MxCh= 4
+ D:  Ver= 1.00 Cls=09(hub  ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
+ P:  Vendor=0451 ProdID=1446 Rev= 1.00
+ C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
+ I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
+ E:  Ad=81(I) Atr=03(Int.) MxPS=   1 Ivl=255ms
+ 
+-T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5 MxCh= 0
++T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5  MxCh= 0
+ D:  Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
+ P:  Vendor=04b4 ProdID=0001 Rev= 0.00
+ C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
+ I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=mouse
+ E:  Ad=81(I) Atr=03(Int.) MxPS=   3 Ivl= 10ms
+ 
+-T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12  MxCh= 0
++T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12   MxCh= 0
+ D:  Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
+ P:  Vendor=0565 ProdID=0001 Rev= 1.08
+ S:  Manufacturer=Peracom Networks, Inc.
+@@ -330,12 +340,12 @@ E:  Ad=82(I) Atr=03(Int.) MxPS=   8 Ivl=  8ms
+ Selecting only the "T:" and "I:" lines from this (for example, by using
+ "procusb ti"), we have:
+ 
+-T:  Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12  MxCh= 2
+-T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12  MxCh= 4
++T:  Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12   MxCh= 2
++T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12   MxCh= 4
+ I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
+-T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5 MxCh= 0
++T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5  MxCh= 0
+ I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=mouse
+-T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12  MxCh= 0
++T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12   MxCh= 0
+ I:  If#= 0 Alt= 0 #EPs= 3 Cls=00(>ifc ) Sub=00 Prot=00 Driver=serial
+ 
+ 
+diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
+index 3449742c00e1..ddb4dc980923 100644
+--- a/drivers/usb/core/devices.c
++++ b/drivers/usb/core/devices.c
+@@ -66,8 +66,8 @@
+ #define ALLOW_SERIAL_NUMBER
+ 
+ static const char *format_topo =
+-/* T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd */
+-"\nT:  Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s MxCh=%2d\n";
++/* T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=dddd MxCh=dd */
++"\nT:  Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%-4s MxCh=%2d\n";
+ 
+ static const char *format_string_manufacturer =
+ /* S:  Manufacturer=xxxx */
+@@ -520,11 +520,14 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,
+ 		speed = "1.5"; break;
+ 	case USB_SPEED_UNKNOWN:		/* usb 1.1 root hub code */
+ 	case USB_SPEED_FULL:
+-		speed = "12 "; break;
++		speed = "12"; break;
++	case USB_SPEED_WIRELESS:	/* Wireless has no real fixed speed */
+ 	case USB_SPEED_HIGH:
+ 		speed = "480"; break;
++	case USB_SPEED_SUPER:
++		speed = "5000"; break;
+ 	default:
+-		speed = "?? ";
++		speed = "??";
+ 	}
+ 	data_end = pages_start + sprintf(pages_start, format_topo,
+ 			bus->busnum, level, parent_devnum,

commit 3df7169e73fc1d71a39cffeacc969f6840cdf52b
+Author: Alan Stern 
+Date:   Fri Sep 10 16:37:05 2010 -0400
+
+    OHCI: work around for nVidia shutdown problem
+    
+    This patch (as1417) fixes a problem affecting some (or all) nVidia
+    chipsets.  When the computer is shut down, the OHCI controllers
+    continue to power the USB buses and evidently they drive a Reset
+    signal out all their ports.  This prevents attached devices from going
+    to low power.  Mouse LEDs stay on, for example, which is disconcerting
+    for users and a drain on laptop batteries.
+    
+    The fix involves leaving each OHCI controller in the OPERATIONAL state
+    during system shutdown rather than putting it in the RESET state.
+    Although this nominally means the controller is running, in fact it's
+    not doing very much since all the schedules are all disabled.  However
+    there is ongoing DMA to the Host Controller Communications Area, so
+    the patch also disables the bus-master capability of all PCI USB
+    controllers after the shutdown routine runs.
+    
+    The fix is applied only to nVidia-based PCI OHCI controllers, so it
+    shouldn't cause problems on systems using other hardware.  As an added
+    safety measure, in case the kernel encounters one of these running
+    controllers during boot, the patch changes quirk_usb_handoff_ohci()
+    (which runs early on during PCI discovery) to reset the controller
+    before anything bad can happen.
+    
+    Reported-by: Pali Rohár 
+    Signed-off-by: Alan Stern 
+    CC: David Brownell 
+    Tested-by: Pali Rohár 
+    CC: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index c3f98543caaf..3799573bd385 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -329,8 +329,10 @@ void usb_hcd_pci_shutdown(struct pci_dev *dev)
+ 		return;
+ 
+ 	if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) &&
+-			hcd->driver->shutdown)
++			hcd->driver->shutdown) {
+ 		hcd->driver->shutdown(hcd);
++		pci_disable_device(dev);
++	}
+ }
+ EXPORT_SYMBOL_GPL(usb_hcd_pci_shutdown);
+ 
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index c3b4ccc7337b..8ef3c1944364 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -398,7 +398,14 @@ ohci_shutdown (struct usb_hcd *hcd)
+ 
+ 	ohci = hcd_to_ohci (hcd);
+ 	ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
+-	ohci_usb_reset (ohci);
++	ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
++
++	/* If the SHUTDOWN quirk is set, don't put the controller in RESET */
++	ohci->hc_control &= (ohci->flags & OHCI_QUIRK_SHUTDOWN ?
++			OHCI_CTRL_RWC | OHCI_CTRL_HCFS :
++			OHCI_CTRL_RWC);
++	ohci_writel(ohci, ohci->hc_control, &ohci->regs->control);
++
+ 	/* flush the writes */
+ 	(void) ohci_readl (ohci, &ohci->regs->control);
+ }
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index 6bdc8b25a6a1..36ee9a666e93 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -201,6 +201,20 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd)
+ 	return 0;
+ }
+ 
++/* nVidia controllers continue to drive Reset signalling on the bus
++ * even after system shutdown, wasting power.  This flag tells the
++ * shutdown routine to leave the controller OPERATIONAL instead of RESET.
++ */
++static int ohci_quirk_nvidia_shutdown(struct usb_hcd *hcd)
++{
++	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
++
++	ohci->flags |= OHCI_QUIRK_SHUTDOWN;
++	ohci_dbg(ohci, "enabled nVidia shutdown quirk\n");
++
++	return 0;
++}
++
+ /*
+  * The hardware normally enables the A-link power management feature, which
+  * lets the system lower the power consumption in idle states.
+@@ -332,6 +346,10 @@ static const struct pci_device_id ohci_pci_quirks[] = {
+ 		PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399),
+ 		.driver_data = (unsigned long)ohci_quirk_amd700,
+ 	},
++	{
++		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID),
++		.driver_data = (unsigned long) ohci_quirk_nvidia_shutdown,
++	},
+ 
+ 	/* FIXME for some of the early AMD 760 southbridges, OHCI
+ 	 * won't work at all.  blacklist them.
+diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
+index 5bf15fed0d9f..51facb985c84 100644
+--- a/drivers/usb/host/ohci.h
++++ b/drivers/usb/host/ohci.h
+@@ -403,6 +403,7 @@ struct ohci_hcd {
+ #define	OHCI_QUIRK_HUB_POWER	0x100			/* distrust firmware power/oc setup */
+ #define	OHCI_QUIRK_AMD_ISO	0x200			/* ISO transfers*/
+ #define	OHCI_QUIRK_AMD_PREFETCH	0x400			/* pre-fetch for ISO transfer */
++#define	OHCI_QUIRK_SHUTDOWN	0x800			/* nVidia power bug */
+ 	// there are also chip quirks/bugs in init logic
+ 
+ 	struct work_struct	nec_work;	/* Worker for NEC quirk */
+diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
+index 83b5f9cea85a..464ed977b45d 100644
+--- a/drivers/usb/host/pci-quirks.c
++++ b/drivers/usb/host/pci-quirks.c
+@@ -169,6 +169,7 @@ static int __devinit mmio_resource_enabled(struct pci_dev *pdev, int idx)
+ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
+ {
+ 	void __iomem *base;
++	u32 control;
+ 
+ 	if (!mmio_resource_enabled(pdev, 0))
+ 		return;
+@@ -177,10 +178,14 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
+ 	if (base == NULL)
+ 		return;
+ 
++	control = readl(base + OHCI_CONTROL);
++
+ /* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */
+-#ifndef __hppa__
+-{
+-	u32 control = readl(base + OHCI_CONTROL);
++#ifdef __hppa__
++#define	OHCI_CTRL_MASK		(OHCI_CTRL_RWC | OHCI_CTRL_IR)
++#else
++#define	OHCI_CTRL_MASK		OHCI_CTRL_RWC
++
+ 	if (control & OHCI_CTRL_IR) {
+ 		int wait_time = 500; /* arbitrary; 5 seconds */
+ 		writel(OHCI_INTR_OC, base + OHCI_INTRENABLE);
+@@ -194,13 +199,12 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
+ 			dev_warn(&pdev->dev, "OHCI: BIOS handoff failed"
+ 					" (BIOS bug?) %08x\n",
+ 					readl(base + OHCI_CONTROL));
+-
+-		/* reset controller, preserving RWC */
+-		writel(control & OHCI_CTRL_RWC, base + OHCI_CONTROL);
+ 	}
+-}
+ #endif
+ 
++	/* reset controller, preserving RWC (and possibly IR) */
++	writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL);
++
+ 	/*
+ 	 * disable interrupts
+ 	 */

commit d8087427ccefc0b3364735b96274375246fd452c
+Author: Alan Stern 
+Date:   Fri Sep 3 11:15:41 2010 -0400
+
+    USB: g_file_storage: don't generate automatic serial string
+    
+    This patch (as1413) changes g_file_storage to avoid generating a bogus
+    automatic serial-number string descriptor.  If the user doesn't provide
+    a valid serial number via a module parameter then a warning is logged
+    and the gadget won't have any serial string descriptor at all.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: David Brownell 
+    CC: Michal Nazarewicz 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index 132a1c0877bd..ce437f5dd674 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -89,6 +89,7 @@
+  *				Required if "removable" is not set, names of
+  *					the files or block devices used for
+  *					backing storage
++ *	serial=HHHH...		Required serial number (string of hex chars)
+  *	ro=b[,b...]		Default false, booleans for read-only access
+  *	removable		Default false, boolean for removable media
+  *	luns=N			Default N = number of filenames, number of
+@@ -108,12 +109,11 @@
+  *	vendor=0xVVVV		Default 0x0525 (NetChip), USB Vendor ID
+  *	product=0xPPPP		Default 0xa4a5 (FSG), USB Product ID
+  *	release=0xRRRR		Override the USB release number (bcdDevice)
+- *	serial=HHHH...		Override serial number (string of hex chars)
+  *	buflen=N		Default N=16384, buffer size used (will be
+  *					rounded down to a multiple of
+  *					PAGE_CACHE_SIZE)
+  *
+- * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro",
++ * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "serial", "ro",
+  * "removable", "luns", "nofua", "stall", and "cdrom" options are available;
+  * default values are used for everything else.
+  *
+@@ -273,13 +273,10 @@
+ 
+ #define DRIVER_DESC		"File-backed Storage Gadget"
+ #define DRIVER_NAME		"g_file_storage"
+-/* DRIVER_VERSION must be at least 6 characters long, as it is used
+- * to generate a fallback serial number. */
+-#define DRIVER_VERSION		"20 November 2008"
++#define DRIVER_VERSION		"1 September 2010"
+ 
+ static       char fsg_string_manufacturer[64];
+ static const char fsg_string_product[] = DRIVER_DESC;
+-static       char fsg_string_serial[13];
+ static const char fsg_string_config[] = "Self-powered";
+ static const char fsg_string_interface[] = "Mass Storage";
+ 
+@@ -305,6 +302,7 @@ MODULE_LICENSE("Dual BSD/GPL");
+ 
+ static struct {
+ 	char		*file[FSG_MAX_LUNS];
++	char		*serial;
+ 	int		ro[FSG_MAX_LUNS];
+ 	int		nofua[FSG_MAX_LUNS];
+ 	unsigned int	num_filenames;
+@@ -321,7 +319,6 @@ static struct {
+ 	unsigned short	vendor;
+ 	unsigned short	product;
+ 	unsigned short	release;
+-	char		*serial;
+ 	unsigned int	buflen;
+ 
+ 	int		transport_type;
+@@ -346,6 +343,9 @@ module_param_array_named(file, mod_data.file, charp, &mod_data.num_filenames,
+ 		S_IRUGO);
+ MODULE_PARM_DESC(file, "names of backing files or devices");
+ 
++module_param_named(serial, mod_data.serial, charp, S_IRUGO);
++MODULE_PARM_DESC(serial, "USB serial number");
++
+ module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO);
+ MODULE_PARM_DESC(ro, "true to force read-only");
+ 
+@@ -365,9 +365,6 @@ MODULE_PARM_DESC(stall, "false to prevent bulk stalls");
+ module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO);
+ MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk");
+ 
+-module_param_named(serial, mod_data.serial, charp, S_IRUGO);
+-MODULE_PARM_DESC(serial, "USB serial number");
+-
+ /* In the non-TEST version, only the module parameters listed above
+  * are available. */
+ #ifdef CONFIG_USB_FILE_STORAGE_TEST
+@@ -3214,7 +3211,6 @@ static int __init check_parameters(struct fsg_dev *fsg)
+ {
+ 	int	prot;
+ 	int	gcnum;
+-	int	i;
+ 
+ 	/* Store the default values */
+ 	mod_data.transport_type = USB_PR_BULK;
+@@ -3310,38 +3306,22 @@ static int __init check_parameters(struct fsg_dev *fsg)
+ 			if ((*ch < '0' || *ch > '9') &&
+ 			    (*ch < 'A' || *ch > 'F')) { /* not uppercase hex */
+ 				WARNING(fsg,
+-					"Invalid serial string character: %c; "
+-					"Failing back to default\n",
++					"Invalid serial string character: %c\n",
+ 					*ch);
+-				goto fill_serial;
++				goto no_serial;
+ 			}
+ 		}
+ 		if (len > 126 ||
+ 		    (mod_data.transport_type == USB_PR_BULK && len < 12) ||
+ 		    (mod_data.transport_type != USB_PR_BULK && len > 12)) {
+-			WARNING(fsg,
+-				"Invalid serial string length; "
+-				"Failing back to default\n");
+-			goto fill_serial;
++			WARNING(fsg, "Invalid serial string length!\n");
++			goto no_serial;
+ 		}
+ 		fsg_strings[FSG_STRING_SERIAL - 1].s = mod_data.serial;
+ 	} else {
+-		WARNING(fsg,
+-			"Userspace failed to provide serial number; "
+-			"Failing back to default\n");
+-fill_serial:
+-		/* Serial number not specified or invalid, make our own.
+-		 * We just encode it from the driver version string,
+-		 * 12 characters to comply with both CB[I] and BBB spec.
+-		 * Warning : Two devices running the same kernel will have
+-		 * the same fallback serial number. */
+-		for (i = 0; i < 12; i += 2) {
+-			unsigned char	c = DRIVER_VERSION[i / 2];
+-
+-			if (!c)
+-				break;
+-			sprintf(&fsg_string_serial[i], "%02X", c);
+-		}
++		WARNING(fsg, "No serial-number string provided!\n");
++ no_serial:
++		device_desc.iSerialNumber = 0;
+ 	}
+ 
+ 	return 0;
+diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c
+index 484acfb1a7c5..d7856c599d5a 100644
+--- a/drivers/usb/gadget/storage_common.c
++++ b/drivers/usb/gadget/storage_common.c
+@@ -26,7 +26,6 @@
+  * be defined (each of type pointer to char):
+  *  - fsg_string_manufacturer -- name of the manufacturer
+  *  - fsg_string_product      -- name of the product
+- *  - fsg_string_serial       -- product's serial
+  *  - fsg_string_config       -- name of the configuration
+  *  - fsg_string_interface    -- name of the interface
+  * The first four are only needed when FSG_DESCRIPTORS_DEVICE_STRINGS
+@@ -552,7 +551,7 @@ static struct usb_string		fsg_strings[] = {
+ #ifndef FSG_NO_DEVICE_STRINGS
+ 	{FSG_STRING_MANUFACTURER,	fsg_string_manufacturer},
+ 	{FSG_STRING_PRODUCT,		fsg_string_product},
+-	{FSG_STRING_SERIAL,		fsg_string_serial},
++	{FSG_STRING_SERIAL,		""},
+ 	{FSG_STRING_CONFIG,		fsg_string_config},
+ #endif
+ 	{FSG_STRING_INTERFACE,		fsg_string_interface},

commit 15bcb91d7e607d8a2e060f01f7784a7454668da4
+Author: Alan Stern 
+Date:   Sat Sep 25 23:35:21 2010 +0200
+
+    PM / Runtime: Implement autosuspend support
+    
+    This patch (as1427) implements the "autosuspend" facility for runtime
+    PM.  A few new fields are added to the dev_pm_info structure and
+    several new PM helper functions are defined, for telling the PM core
+    whether or not a device uses autosuspend, for setting the autosuspend
+    delay, and for marking periods of device activity.
+    
+    Drivers that do not want to use autosuspend can continue using the
+    same helper functions as before; their behavior will not change.  In
+    addition, drivers supporting autosuspend can also call the old helper
+    functions to get the old behavior.
+    
+    The details are all explained in Documentation/power/runtime_pm.txt
+    and Documentation/ABI/testing/sysfs-devices-power.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/Documentation/ABI/testing/sysfs-devices-power b/Documentation/ABI/testing/sysfs-devices-power
+index 6bb2dd3c3a71..7628cd1bc36a 100644
+--- a/Documentation/ABI/testing/sysfs-devices-power
++++ b/Documentation/ABI/testing/sysfs-devices-power
+@@ -147,3 +147,21 @@ Description:
+ 		milliseconds.  This attribute is read-only.  If the device is
+ 		not enabled to wake up the system from sleep states, this
+ 		attribute is empty.
++
++What:		/sys/devices/.../power/autosuspend_delay_ms
++Date:		September 2010
++Contact:	Alan Stern 
++Description:
++		The /sys/devices/.../power/autosuspend_delay_ms attribute
++		contains the autosuspend delay value (in milliseconds).  Some
++		drivers do not want their device to suspend as soon as it
++		becomes idle at run time; they want the device to remain
++		inactive for a certain minimum period of time first.  That
++		period is called the autosuspend delay.  Negative values will
++		prevent the device from being suspended at run time (similar
++		to writing "on" to the power/control attribute).  Values >=
++		1000 will cause the autosuspend timer expiration to be rounded
++		up to the nearest second.
++
++		Not all drivers support this attribute.  If it isn't supported,
++		attempts to read or write it will yield I/O errors.
+diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt
+index 9ba49b21ac86..489e9bacd165 100644
+--- a/Documentation/power/runtime_pm.txt
++++ b/Documentation/power/runtime_pm.txt
+@@ -158,7 +158,8 @@ rules:
+     to execute it, the other callbacks will not be executed for the same device.
+ 
+   * A request to execute ->runtime_resume() will cancel any pending or
+-    scheduled requests to execute the other callbacks for the same device.
++    scheduled requests to execute the other callbacks for the same device,
++    except for scheduled autosuspends.
+ 
+ 3. Run-time PM Device Fields
+ 
+@@ -166,7 +167,7 @@ The following device run-time PM fields are present in 'struct dev_pm_info', as
+ defined in include/linux/pm.h:
+ 
+   struct timer_list suspend_timer;
+-    - timer used for scheduling (delayed) suspend request
++    - timer used for scheduling (delayed) suspend and autosuspend requests
+ 
+   unsigned long timer_expires;
+     - timer expiration time, in jiffies (if this is different from zero, the
+@@ -236,6 +237,23 @@ defined in include/linux/pm.h:
+       Section 8); it may be modified only by the pm_runtime_no_callbacks()
+       helper function
+ 
++  unsigned int use_autosuspend;
++    - indicates that the device's driver supports delayed autosuspend (see
++      Section 9); it may be modified only by the
++      pm_runtime{_dont}_use_autosuspend() helper functions
++
++  unsigned int timer_autosuspends;
++    - indicates that the PM core should attempt to carry out an autosuspend
++      when the timer expires rather than a normal suspend
++
++  int autosuspend_delay;
++    - the delay time (in milliseconds) to be used for autosuspend
++
++  unsigned long last_busy;
++    - the time (in jiffies) when the pm_runtime_mark_last_busy() helper
++      function was last called for this device; used in calculating inactivity
++      periods for autosuspend
++
+ All of the above fields are members of the 'power' member of 'struct device'.
+ 
+ 4. Run-time PM Device Helper Functions
+@@ -261,6 +279,12 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
+       error code on failure, where -EAGAIN or -EBUSY means it is safe to attempt
+       to suspend the device again in future
+ 
++  int pm_runtime_autosuspend(struct device *dev);
++    - same as pm_runtime_suspend() except that the autosuspend delay is taken
++      into account; if pm_runtime_autosuspend_expiration() says the delay has
++      not yet expired then an autosuspend is scheduled for the appropriate time
++      and 0 is returned
++
+   int pm_runtime_resume(struct device *dev);
+     - execute the subsystem-level resume callback for the device; returns 0 on
+       success, 1 if the device's run-time PM status was already 'active' or
+@@ -273,6 +297,11 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
+       device (the request is represented by a work item in pm_wq); returns 0 on
+       success or error code if the request has not been queued up
+ 
++  int pm_request_autosuspend(struct device *dev);
++    - schedule the execution of the subsystem-level suspend callback for the
++      device when the autosuspend delay has expired; if the delay has already
++      expired then the work item is queued up immediately
++
+   int pm_schedule_suspend(struct device *dev, unsigned int delay);
+     - schedule the execution of the subsystem-level suspend callback for the
+       device in future, where 'delay' is the time to wait before queuing up a
+@@ -304,12 +333,20 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
+     - decrement the device's usage counter
+ 
+   int pm_runtime_put(struct device *dev);
+-    - decrement the device's usage counter, run pm_request_idle(dev) and return
+-      its result
++    - decrement the device's usage counter; if the result is 0 then run
++      pm_request_idle(dev) and return its result
++
++  int pm_runtime_put_autosuspend(struct device *dev);
++    - decrement the device's usage counter; if the result is 0 then run
++      pm_request_autosuspend(dev) and return its result
+ 
+   int pm_runtime_put_sync(struct device *dev);
+-    - decrement the device's usage counter, run pm_runtime_idle(dev) and return
+-      its result
++    - decrement the device's usage counter; if the result is 0 then run
++      pm_runtime_idle(dev) and return its result
++
++  int pm_runtime_put_sync_autosuspend(struct device *dev);
++    - decrement the device's usage counter; if the result is 0 then run
++      pm_runtime_autosuspend(dev) and return its result
+ 
+   void pm_runtime_enable(struct device *dev);
+     - enable the run-time PM helper functions to run the device bus type's
+@@ -360,19 +397,46 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
+       PM attributes from /sys/devices/.../power (or prevent them from being
+       added when the device is registered)
+ 
++  void pm_runtime_mark_last_busy(struct device *dev);
++    - set the power.last_busy field to the current time
++
++  void pm_runtime_use_autosuspend(struct device *dev);
++    - set the power.use_autosuspend flag, enabling autosuspend delays
++
++  void pm_runtime_dont_use_autosuspend(struct device *dev);
++    - clear the power.use_autosuspend flag, disabling autosuspend delays
++
++  void pm_runtime_set_autosuspend_delay(struct device *dev, int delay);
++    - set the power.autosuspend_delay value to 'delay' (expressed in
++      milliseconds); if 'delay' is negative then run-time suspends are
++      prevented
++
++  unsigned long pm_runtime_autosuspend_expiration(struct device *dev);
++    - calculate the time when the current autosuspend delay period will expire,
++      based on power.last_busy and power.autosuspend_delay; if the delay time
++      is 1000 ms or larger then the expiration time is rounded up to the
++      nearest second; returns 0 if the delay period has already expired or
++      power.use_autosuspend isn't set, otherwise returns the expiration time
++      in jiffies
++
+ It is safe to execute the following helper functions from interrupt context:
+ 
+ pm_request_idle()
++pm_request_autosuspend()
+ pm_schedule_suspend()
+ pm_request_resume()
+ pm_runtime_get_noresume()
+ pm_runtime_get()
+ pm_runtime_put_noidle()
+ pm_runtime_put()
++pm_runtime_put_autosuspend()
++pm_runtime_enable()
+ pm_suspend_ignore_children()
+ pm_runtime_set_active()
+ pm_runtime_set_suspended()
+-pm_runtime_enable()
++pm_runtime_suspended()
++pm_runtime_mark_last_busy()
++pm_runtime_autosuspend_expiration()
+ 
+ 5. Run-time PM Initialization, Device Probing and Removal
+ 
+@@ -561,3 +625,115 @@ As a consequence, the PM core will never directly inform the device's subsystem
+ or driver about run-time power changes.  Instead, the driver for the device's
+ parent must take responsibility for telling the device's driver when the
+ parent's power state changes.
++
++9. Autosuspend, or automatically-delayed suspends
++
++Changing a device's power state isn't free; it requires both time and energy.
++A device should be put in a low-power state only when there's some reason to
++think it will remain in that state for a substantial time.  A common heuristic
++says that a device which hasn't been used for a while is liable to remain
++unused; following this advice, drivers should not allow devices to be suspended
++at run-time until they have been inactive for some minimum period.  Even when
++the heuristic ends up being non-optimal, it will still prevent devices from
++"bouncing" too rapidly between low-power and full-power states.
++
++The term "autosuspend" is an historical remnant.  It doesn't mean that the
++device is automatically suspended (the subsystem or driver still has to call
++the appropriate PM routines); rather it means that run-time suspends will
++automatically be delayed until the desired period of inactivity has elapsed.
++
++Inactivity is determined based on the power.last_busy field.  Drivers should
++call pm_runtime_mark_last_busy() to update this field after carrying out I/O,
++typically just before calling pm_runtime_put_autosuspend().  The desired length
++of the inactivity period is a matter of policy.  Subsystems can set this length
++initially by calling pm_runtime_set_autosuspend_delay(), but after device
++registration the length should be controlled by user space, using the
++/sys/devices/.../power/autosuspend_delay_ms attribute.
++
++In order to use autosuspend, subsystems or drivers must call
++pm_runtime_use_autosuspend() (preferably before registering the device), and
++thereafter they should use the various *_autosuspend() helper functions instead
++of the non-autosuspend counterparts:
++
++	Instead of: pm_runtime_suspend    use: pm_runtime_autosuspend;
++	Instead of: pm_schedule_suspend   use: pm_request_autosuspend;
++	Instead of: pm_runtime_put        use: pm_runtime_put_autosuspend;
++	Instead of: pm_runtime_put_sync   use: pm_runtime_put_sync_autosuspend.
++
++Drivers may also continue to use the non-autosuspend helper functions; they
++will behave normally, not taking the autosuspend delay into account.
++Similarly, if the power.use_autosuspend field isn't set then the autosuspend
++helper functions will behave just like the non-autosuspend counterparts.
++
++The implementation is well suited for asynchronous use in interrupt contexts.
++However such use inevitably involves races, because the PM core can't
++synchronize ->runtime_suspend() callbacks with the arrival of I/O requests.
++This synchronization must be handled by the driver, using its private lock.
++Here is a schematic pseudo-code example:
++
++	foo_read_or_write(struct foo_priv *foo, void *data)
++	{
++		lock(&foo->private_lock);
++		add_request_to_io_queue(foo, data);
++		if (foo->num_pending_requests++ == 0)
++			pm_runtime_get(&foo->dev);
++		if (!foo->is_suspended)
++			foo_process_next_request(foo);
++		unlock(&foo->private_lock);
++	}
++
++	foo_io_completion(struct foo_priv *foo, void *req)
++	{
++		lock(&foo->private_lock);
++		if (--foo->num_pending_requests == 0) {
++			pm_runtime_mark_last_busy(&foo->dev);
++			pm_runtime_put_autosuspend(&foo->dev);
++		} else {
++			foo_process_next_request(foo);
++		}
++		unlock(&foo->private_lock);
++		/* Send req result back to the user ... */
++	}
++
++	int foo_runtime_suspend(struct device *dev)
++	{
++		struct foo_priv foo = container_of(dev, ...);
++		int ret = 0;
++
++		lock(&foo->private_lock);
++		if (foo->num_pending_requests > 0) {
++			ret = -EBUSY;
++		} else {
++			/* ... suspend the device ... */
++			foo->is_suspended = 1;
++		}
++		unlock(&foo->private_lock);
++		return ret;
++	}
++
++	int foo_runtime_resume(struct device *dev)
++	{
++		struct foo_priv foo = container_of(dev, ...);
++
++		lock(&foo->private_lock);
++		/* ... resume the device ... */
++		foo->is_suspended = 0;
++		pm_runtime_mark_last_busy(&foo->dev);
++		if (foo->num_pending_requests > 0)
++			foo_process_requests(foo);
++		unlock(&foo->private_lock);
++		return 0;
++	}
++
++The important point is that after foo_io_completion() asks for an autosuspend,
++the foo_runtime_suspend() callback may race with foo_read_or_write().
++Therefore foo_runtime_suspend() has to check whether there are any pending I/O
++requests (while holding the private lock) before allowing the suspend to
++proceed.
++
++In addition, the power.autosuspend_delay field can be changed by user space at
++any time.  If a driver cares about this, it can call
++pm_runtime_autosuspend_expiration() from within the ->runtime_suspend()
++callback while holding its private lock.  If the function returns a nonzero
++value then the delay has not yet expired and the callback should return
++-EAGAIN.
+diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
+index 5bd4daa93ef1..cd4e100a1362 100644
+--- a/drivers/base/power/runtime.c
++++ b/drivers/base/power/runtime.c
+@@ -9,7 +9,6 @@
+ 
+ #include 
+ #include 
+-#include 
+ #include "power.h"
+ 
+ static int rpm_resume(struct device *dev, int rpmflags);
+@@ -79,6 +78,53 @@ static void pm_runtime_cancel_pending(struct device *dev)
+ 	dev->power.request = RPM_REQ_NONE;
+ }
+ 
++/*
++ * pm_runtime_autosuspend_expiration - Get a device's autosuspend-delay expiration time.
++ * @dev: Device to handle.
++ *
++ * Compute the autosuspend-delay expiration time based on the device's
++ * power.last_busy time.  If the delay has already expired or is disabled
++ * (negative) or the power.use_autosuspend flag isn't set, return 0.
++ * Otherwise return the expiration time in jiffies (adjusted to be nonzero).
++ *
++ * This function may be called either with or without dev->power.lock held.
++ * Either way it can be racy, since power.last_busy may be updated at any time.
++ */
++unsigned long pm_runtime_autosuspend_expiration(struct device *dev)
++{
++	int autosuspend_delay;
++	long elapsed;
++	unsigned long last_busy;
++	unsigned long expires = 0;
++
++	if (!dev->power.use_autosuspend)
++		goto out;
++
++	autosuspend_delay = ACCESS_ONCE(dev->power.autosuspend_delay);
++	if (autosuspend_delay < 0)
++		goto out;
++
++	last_busy = ACCESS_ONCE(dev->power.last_busy);
++	elapsed = jiffies - last_busy;
++	if (elapsed < 0)
++		goto out;	/* jiffies has wrapped around. */
++
++	/*
++	 * If the autosuspend_delay is >= 1 second, align the timer by rounding
++	 * up to the nearest second.
++	 */
++	expires = last_busy + msecs_to_jiffies(autosuspend_delay);
++	if (autosuspend_delay >= 1000)
++		expires = round_jiffies(expires);
++	expires += !expires;
++	if (elapsed >= expires - last_busy)
++		expires = 0;	/* Already expired. */
++
++ out:
++	return expires;
++}
++EXPORT_SYMBOL_GPL(pm_runtime_autosuspend_expiration);
++
+ /**
+  * rpm_check_suspend_allowed - Test whether a device may be suspended.
+  * @dev: Device to test.
+@@ -234,6 +280,32 @@ static int rpm_suspend(struct device *dev, int rpmflags)
+ 	if (retval)
+ 		goto out;
+ 
++	/* If the autosuspend_delay time hasn't expired yet, reschedule. */
++	if ((rpmflags & RPM_AUTO)
++	    && dev->power.runtime_status != RPM_SUSPENDING) {
++		unsigned long expires = pm_runtime_autosuspend_expiration(dev);
++
++		if (expires != 0) {
++			/* Pending requests need to be canceled. */
++			dev->power.request = RPM_REQ_NONE;
++
++			/*
++			 * Optimization: If the timer is already running and is
++			 * set to expire at or before the autosuspend delay,
++			 * avoid the overhead of resetting it.  Just let it
++			 * expire; pm_suspend_timer_fn() will take care of the
++			 * rest.
++			 */
++			if (!(dev->power.timer_expires && time_before_eq(
++			    dev->power.timer_expires, expires))) {
++				dev->power.timer_expires = expires;
++				mod_timer(&dev->power.suspend_timer, expires);
++			}
++			dev->power.timer_autosuspends = 1;
++			goto out;
++		}
++	}
++
+ 	/* Other scheduled or pending requests need to be canceled. */
+ 	pm_runtime_cancel_pending(dev);
+ 
+@@ -268,7 +340,8 @@ static int rpm_suspend(struct device *dev, int rpmflags)
+ 
+ 	/* Carry out an asynchronous or a synchronous suspend. */
+ 	if (rpmflags & RPM_ASYNC) {
+-		dev->power.request = RPM_REQ_SUSPEND;
++		dev->power.request = (rpmflags & RPM_AUTO) ?
++		    RPM_REQ_AUTOSUSPEND : RPM_REQ_SUSPEND;
+ 		if (!dev->power.request_pending) {
+ 			dev->power.request_pending = true;
+ 			queue_work(pm_wq, &dev->power.work);
+@@ -383,8 +456,15 @@ static int rpm_resume(struct device *dev, int rpmflags)
+ 	if (retval)
+ 		goto out;
+ 
+-	/* Other scheduled or pending requests need to be canceled. */
+-	pm_runtime_cancel_pending(dev);
++	/*
++	 * Other scheduled or pending requests need to be canceled.  Small
++	 * optimization: If an autosuspend timer is running, leave it running
++	 * rather than cancelling it now only to restart it again in the near
++	 * future.
++	 */
++	dev->power.request = RPM_REQ_NONE;
++	if (!dev->power.timer_autosuspends)
++		pm_runtime_deactivate_timer(dev);
+ 
+ 	if (dev->power.runtime_status == RPM_ACTIVE) {
+ 		retval = 1;
+@@ -568,6 +648,9 @@ static void pm_runtime_work(struct work_struct *work)
+ 	case RPM_REQ_SUSPEND:
+ 		rpm_suspend(dev, RPM_NOWAIT);
+ 		break;
++	case RPM_REQ_AUTOSUSPEND:
++		rpm_suspend(dev, RPM_NOWAIT | RPM_AUTO);
++		break;
+ 	case RPM_REQ_RESUME:
+ 		rpm_resume(dev, RPM_NOWAIT);
+ 		break;
+@@ -595,7 +678,8 @@ static void pm_suspend_timer_fn(unsigned long data)
+ 	/* If 'expire' is after 'jiffies' we've been called too early. */
+ 	if (expires > 0 && !time_after(expires, jiffies)) {
+ 		dev->power.timer_expires = 0;
+-		rpm_suspend(dev, RPM_ASYNC);
++		rpm_suspend(dev, dev->power.timer_autosuspends ?
++		    (RPM_ASYNC | RPM_AUTO) : RPM_ASYNC);
+ 	}
+ 
+ 	spin_unlock_irqrestore(&dev->power.lock, flags);
+@@ -627,6 +711,7 @@ int pm_schedule_suspend(struct device *dev, unsigned int delay)
+ 
+ 	dev->power.timer_expires = jiffies + msecs_to_jiffies(delay);
+ 	dev->power.timer_expires += !dev->power.timer_expires;
++	dev->power.timer_autosuspends = 0;
+ 	mod_timer(&dev->power.suspend_timer, dev->power.timer_expires);
+ 
+  out:
+@@ -670,7 +755,9 @@ EXPORT_SYMBOL_GPL(__pm_runtime_idle);
+  * @dev: Device to suspend.
+  * @rpmflags: Flag bits.
+  *
+- * Carry out a suspend, either synchronous or asynchronous.
++ * If the RPM_GET_PUT flag is set, decrement the device's usage count and
++ * return immediately if it is larger than zero.  Then carry out a suspend,
++ * either synchronous or asynchronous.
+  *
+  * This routine may be called in atomic context if the RPM_ASYNC flag is set.
+  */
+@@ -679,6 +766,11 @@ int __pm_runtime_suspend(struct device *dev, int rpmflags)
+ 	unsigned long flags;
+ 	int retval;
+ 
++	if (rpmflags & RPM_GET_PUT) {
++		if (!atomic_dec_and_test(&dev->power.usage_count))
++			return 0;
++	}
++
+ 	spin_lock_irqsave(&dev->power.lock, flags);
+ 	retval = rpm_suspend(dev, rpmflags);
+ 	spin_unlock_irqrestore(&dev->power.lock, flags);
+@@ -980,7 +1072,7 @@ void pm_runtime_allow(struct device *dev)
+ 
+ 	dev->power.runtime_auto = true;
+ 	if (atomic_dec_and_test(&dev->power.usage_count))
+-		rpm_idle(dev, 0);
++		rpm_idle(dev, RPM_AUTO);
+ 
+  out:
+ 	spin_unlock_irq(&dev->power.lock);
+@@ -1006,6 +1098,86 @@ void pm_runtime_no_callbacks(struct device *dev)
+ }
+ EXPORT_SYMBOL_GPL(pm_runtime_no_callbacks);
+ 
++/**
++ * update_autosuspend - Handle a change to a device's autosuspend settings.
++ * @dev: Device to handle.
++ * @old_delay: The former autosuspend_delay value.
++ * @old_use: The former use_autosuspend value.
++ *
++ * Prevent runtime suspend if the new delay is negative and use_autosuspend is
++ * set; otherwise allow it.  Send an idle notification if suspends are allowed.
++ *
++ * This function must be called under dev->power.lock with interrupts disabled.
++ */
++static void update_autosuspend(struct device *dev, int old_delay, int old_use)
++{
++	int delay = dev->power.autosuspend_delay;
++
++	/* Should runtime suspend be prevented now? */
++	if (dev->power.use_autosuspend && delay < 0) {
++
++		/* If it used to be allowed then prevent it. */
++		if (!old_use || old_delay >= 0) {
++			atomic_inc(&dev->power.usage_count);
++			rpm_resume(dev, 0);
++		}
++	}
++
++	/* Runtime suspend should be allowed now. */
++	else {
++
++		/* If it used to be prevented then allow it. */
++		if (old_use && old_delay < 0)
++			atomic_dec(&dev->power.usage_count);
++
++		/* Maybe we can autosuspend now. */
++		rpm_idle(dev, RPM_AUTO);
++	}
++}
++
++/**
++ * pm_runtime_set_autosuspend_delay - Set a device's autosuspend_delay value.
++ * @dev: Device to handle.
++ * @delay: Value of the new delay in milliseconds.
++ *
++ * Set the device's power.autosuspend_delay value.  If it changes to negative
++ * and the power.use_autosuspend flag is set, prevent run-time suspends.  If it
++ * changes the other way, allow run-time suspends.
++ */
++void pm_runtime_set_autosuspend_delay(struct device *dev, int delay)
++{
++	int old_delay, old_use;
++
++	spin_lock_irq(&dev->power.lock);
++	old_delay = dev->power.autosuspend_delay;
++	old_use = dev->power.use_autosuspend;
++	dev->power.autosuspend_delay = delay;
++	update_autosuspend(dev, old_delay, old_use);
++	spin_unlock_irq(&dev->power.lock);
++}
++EXPORT_SYMBOL_GPL(pm_runtime_set_autosuspend_delay);
++
++/**
++ * __pm_runtime_use_autosuspend - Set a device's use_autosuspend flag.
++ * @dev: Device to handle.
++ * @use: New value for use_autosuspend.
++ *
++ * Set the device's power.use_autosuspend flag, and allow or prevent run-time
++ * suspends as needed.
++ */
++void __pm_runtime_use_autosuspend(struct device *dev, bool use)
++{
++	int old_delay, old_use;
++
++	spin_lock_irq(&dev->power.lock);
++	old_delay = dev->power.autosuspend_delay;
++	old_use = dev->power.use_autosuspend;
++	dev->power.use_autosuspend = use;
++	update_autosuspend(dev, old_delay, old_use);
++	spin_unlock_irq(&dev->power.lock);
++}
++EXPORT_SYMBOL_GPL(__pm_runtime_use_autosuspend);
++
+ /**
+  * pm_runtime_init - Initialize run-time PM fields in given device object.
+  * @dev: Device object to initialize.
+diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
+index b5708c47ce2d..0b1e46bf3e56 100644
+--- a/drivers/base/power/sysfs.c
++++ b/drivers/base/power/sysfs.c
+@@ -75,6 +75,18 @@
+  *	attribute is set to "enabled" by bus type code or device drivers and in
+  *	that cases it should be safe to leave the default value.
+  *
++ *	autosuspend_delay_ms - Report/change a device's autosuspend_delay value
++ *
++ *	Some drivers don't want to carry out a runtime suspend as soon as a
++ *	device becomes idle; they want it always to remain idle for some period
++ *	of time before suspending it.  This period is the autosuspend_delay
++ *	value (expressed in milliseconds) and it can be controlled by the user.
++ *	If the value is negative then the device will never be runtime
++ *	suspended.
++ *
++ *	NOTE: The autosuspend_delay_ms attribute and the autosuspend_delay
++ *	value are used only if the driver calls pm_runtime_use_autosuspend().
++ *
+  *	wakeup_count - Report the number of wakeup events related to the device
+  */
+ 
+@@ -173,6 +185,33 @@ static ssize_t rtpm_status_show(struct device *dev,
+ }
+ 
+ static DEVICE_ATTR(runtime_status, 0444, rtpm_status_show, NULL);
++
++static ssize_t autosuspend_delay_ms_show(struct device *dev,
++		struct device_attribute *attr, char *buf)
++{
++	if (!dev->power.use_autosuspend)
++		return -EIO;
++	return sprintf(buf, "%d\n", dev->power.autosuspend_delay);
++}
++
++static ssize_t autosuspend_delay_ms_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t n)
++{
++	long delay;
++
++	if (!dev->power.use_autosuspend)
++		return -EIO;
++
++	if (strict_strtol(buf, 10, &delay) != 0 || delay != (int) delay)
++		return -EINVAL;
++
++	pm_runtime_set_autosuspend_delay(dev, delay);
++	return n;
++}
++
++static DEVICE_ATTR(autosuspend_delay_ms, 0644, autosuspend_delay_ms_show,
++		autosuspend_delay_ms_store);
++
+ #endif
+ 
+ static ssize_t
+@@ -428,6 +467,7 @@ static struct attribute *runtime_attrs[] = {
+ 	&dev_attr_control.attr,
+ 	&dev_attr_runtime_suspended_time.attr,
+ 	&dev_attr_runtime_active_time.attr,
++	&dev_attr_autosuspend_delay_ms.attr,
+ 	NULL,
+ };
+ static struct attribute_group pm_runtime_attr_group = {
+diff --git a/include/linux/pm.h b/include/linux/pm.h
+index abd81ffaba3c..40f3f45702ba 100644
+--- a/include/linux/pm.h
++++ b/include/linux/pm.h
+@@ -444,6 +444,9 @@ enum rpm_status {
+  *
+  * RPM_REQ_SUSPEND	Run the device bus type's ->runtime_suspend() callback
+  *
++ * RPM_REQ_AUTOSUSPEND	Same as RPM_REQ_SUSPEND, but not until the device has
++ *			been inactive for as long as power.autosuspend_delay
++ *
+  * RPM_REQ_RESUME	Run the device bus type's ->runtime_resume() callback
+  */
+ 
+@@ -451,6 +454,7 @@ enum rpm_request {
+ 	RPM_REQ_NONE = 0,
+ 	RPM_REQ_IDLE,
+ 	RPM_REQ_SUSPEND,
++	RPM_REQ_AUTOSUSPEND,
+ 	RPM_REQ_RESUME,
+ };
+ 
+@@ -482,9 +486,13 @@ struct dev_pm_info {
+ 	unsigned int		run_wake:1;
+ 	unsigned int		runtime_auto:1;
+ 	unsigned int		no_callbacks:1;
++	unsigned int		use_autosuspend:1;
++	unsigned int		timer_autosuspends:1;
+ 	enum rpm_request	request;
+ 	enum rpm_status		runtime_status;
+ 	int			runtime_error;
++	int			autosuspend_delay;
++	unsigned long		last_busy;
+ 	unsigned long		active_jiffies;
+ 	unsigned long		suspended_jiffies;
+ 	unsigned long		accounting_timestamp;
+diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h
+index 8ca52f7c357e..99ed1aa8f933 100644
+--- a/include/linux/pm_runtime.h
++++ b/include/linux/pm_runtime.h
+@@ -12,12 +12,15 @@
+ #include 
+ #include 
+ 
++#include 
++
+ /* Runtime PM flag argument bits */
+ #define RPM_ASYNC		0x01	/* Request is asynchronous */
+ #define RPM_NOWAIT		0x02	/* Don't wait for concurrent
+ 					    state change */
+ #define RPM_GET_PUT		0x04	/* Increment/decrement the
+ 					    usage_count */
++#define RPM_AUTO		0x08	/* Use autosuspend_delay */
+ 
+ #ifdef CONFIG_PM_RUNTIME
+ 
+@@ -37,6 +40,9 @@ extern int pm_generic_runtime_idle(struct device *dev);
+ extern int pm_generic_runtime_suspend(struct device *dev);
+ extern int pm_generic_runtime_resume(struct device *dev);
+ extern void pm_runtime_no_callbacks(struct device *dev);
++extern void __pm_runtime_use_autosuspend(struct device *dev, bool use);
++extern void pm_runtime_set_autosuspend_delay(struct device *dev, int delay);
++extern unsigned long pm_runtime_autosuspend_expiration(struct device *dev);
+ 
+ static inline bool pm_children_suspended(struct device *dev)
+ {
+@@ -74,6 +80,11 @@ static inline bool pm_runtime_suspended(struct device *dev)
+ 	return dev->power.runtime_status == RPM_SUSPENDED;
+ }
+ 
++static inline void pm_runtime_mark_last_busy(struct device *dev)
++{
++	ACCESS_ONCE(dev->power.last_busy) = jiffies;
++}
++
+ #else /* !CONFIG_PM_RUNTIME */
+ 
+ static inline int __pm_runtime_idle(struct device *dev, int rpmflags)
+@@ -113,6 +124,14 @@ static inline int pm_generic_runtime_suspend(struct device *dev) { return 0; }
+ static inline int pm_generic_runtime_resume(struct device *dev) { return 0; }
+ static inline void pm_runtime_no_callbacks(struct device *dev) {}
+ 
++static inline void pm_runtime_mark_last_busy(struct device *dev) {}
++static inline void __pm_runtime_use_autosuspend(struct device *dev,
++						bool use) {}
++static inline void pm_runtime_set_autosuspend_delay(struct device *dev,
++						int delay) {}
++static inline unsigned long pm_runtime_autosuspend_expiration(
++				struct device *dev) { return 0; }
++
+ #endif /* !CONFIG_PM_RUNTIME */
+ 
+ static inline int pm_runtime_idle(struct device *dev)
+@@ -125,6 +144,11 @@ static inline int pm_runtime_suspend(struct device *dev)
+ 	return __pm_runtime_suspend(dev, 0);
+ }
+ 
++static inline int pm_runtime_autosuspend(struct device *dev)
++{
++	return __pm_runtime_suspend(dev, RPM_AUTO);
++}
++
+ static inline int pm_runtime_resume(struct device *dev)
+ {
+ 	return __pm_runtime_resume(dev, 0);
+@@ -155,11 +179,22 @@ static inline int pm_runtime_put(struct device *dev)
+ 	return __pm_runtime_idle(dev, RPM_GET_PUT | RPM_ASYNC);
+ }
+ 
++static inline int pm_runtime_put_autosuspend(struct device *dev)
++{
++	return __pm_runtime_suspend(dev,
++	    RPM_GET_PUT | RPM_ASYNC | RPM_AUTO);
++}
++
+ static inline int pm_runtime_put_sync(struct device *dev)
+ {
+ 	return __pm_runtime_idle(dev, RPM_GET_PUT);
+ }
+ 
++static inline int pm_runtime_put_sync_autosuspend(struct device *dev)
++{
++	return __pm_runtime_suspend(dev, RPM_GET_PUT | RPM_AUTO);
++}
++
+ static inline int pm_runtime_set_active(struct device *dev)
+ {
+ 	return __pm_runtime_set_status(dev, RPM_ACTIVE);
+@@ -175,4 +210,14 @@ static inline void pm_runtime_disable(struct device *dev)
+ 	__pm_runtime_disable(dev, true);
+ }
+ 
++static inline void pm_runtime_use_autosuspend(struct device *dev)
++{
++	__pm_runtime_use_autosuspend(dev, true);
++}
++
++static inline void pm_runtime_dont_use_autosuspend(struct device *dev)
++{
++	__pm_runtime_use_autosuspend(dev, false);
++}
++
+ #endif

commit 7490e44239e60293bca0c2663229050c36c660c2
+Author: Alan Stern 
+Date:   Sat Sep 25 23:35:15 2010 +0200
+
+    PM / Runtime: Add no_callbacks flag
+    
+    Some devices, such as USB interfaces, cannot be power-managed
+    independently of their parents, i.e., they cannot be put in low power
+    while the parent remains at full power.  This patch (as1425) creates a
+    new "no_callbacks" flag, which tells the PM core not to invoke the
+    runtime-PM callback routines for the such devices but instead to
+    assume that the callbacks always succeed.  In addition, the
+    non-debugging runtime-PM sysfs attributes for the devices are removed,
+    since they are pretty much meaningless.
+    
+    The advantage of this scheme comes not so much from avoiding the
+    callbacks themselves, but rather from the fact that without the need
+    for a process context in which to run the callbacks, more work can be
+    done in interrupt context.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt
+index 55b859b3bc72..9ba49b21ac86 100644
+--- a/Documentation/power/runtime_pm.txt
++++ b/Documentation/power/runtime_pm.txt
+@@ -1,6 +1,7 @@
+ Run-time Power Management Framework for I/O Devices
+ 
+ (C) 2009 Rafael J. Wysocki , Novell Inc.
++(C) 2010 Alan Stern 
+ 
+ 1. Introduction
+ 
+@@ -230,6 +231,11 @@ defined in include/linux/pm.h:
+       interface; it may only be modified with the help of the pm_runtime_allow()
+       and pm_runtime_forbid() helper functions
+ 
++  unsigned int no_callbacks;
++    - indicates that the device does not use the run-time PM callbacks (see
++      Section 8); it may be modified only by the pm_runtime_no_callbacks()
++      helper function
++
+ All of the above fields are members of the 'power' member of 'struct device'.
+ 
+ 4. Run-time PM Device Helper Functions
+@@ -349,6 +355,11 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
+       counter (used by the /sys/devices/.../power/control interface to
+       effectively prevent the device from being power managed at run time)
+ 
++  void pm_runtime_no_callbacks(struct device *dev);
++    - set the power.no_callbacks flag for the device and remove the run-time
++      PM attributes from /sys/devices/.../power (or prevent them from being
++      added when the device is registered)
++
+ It is safe to execute the following helper functions from interrupt context:
+ 
+ pm_request_idle()
+@@ -524,3 +535,29 @@ poweroff and run-time suspend callback, and similarly for system resume, thaw,
+ restore, and run-time resume, can achieve this with the help of the
+ UNIVERSAL_DEV_PM_OPS macro defined in include/linux/pm.h (possibly setting its
+ last argument to NULL).
++
++8. "No-Callback" Devices
++
++Some "devices" are only logical sub-devices of their parent and cannot be
++power-managed on their own.  (The prototype example is a USB interface.  Entire
++USB devices can go into low-power mode or send wake-up requests, but neither is
++possible for individual interfaces.)  The drivers for these devices have no
++need of run-time PM callbacks; if the callbacks did exist, ->runtime_suspend()
++and ->runtime_resume() would always return 0 without doing anything else and
++->runtime_idle() would always call pm_runtime_suspend().
++
++Subsystems can tell the PM core about these devices by calling
++pm_runtime_no_callbacks().  This should be done after the device structure is
++initialized and before it is registered (although after device registration is
++also okay).  The routine will set the device's power.no_callbacks flag and
++prevent the non-debugging run-time PM sysfs attributes from being created.
++
++When power.no_callbacks is set, the PM core will not invoke the
++->runtime_idle(), ->runtime_suspend(), or ->runtime_resume() callbacks.
++Instead it will assume that suspends and resumes always succeed and that idle
++devices should be suspended.
++
++As a consequence, the PM core will never directly inform the device's subsystem
++or driver about run-time power changes.  Instead, the driver for the device's
++parent must take responsibility for telling the device's driver when the
++parent's power state changes.
+diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
+index 8b2745c69e2a..698dde742587 100644
+--- a/drivers/base/power/power.h
++++ b/drivers/base/power/power.h
+@@ -60,6 +60,7 @@ static inline void device_pm_move_last(struct device *dev) {}
+ 
+ extern int dpm_sysfs_add(struct device *);
+ extern void dpm_sysfs_remove(struct device *);
++extern void rpm_sysfs_remove(struct device *);
+ 
+ #else /* CONFIG_PM */
+ 
+diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
+index ed227b7c1bb5..5bd4daa93ef1 100644
+--- a/drivers/base/power/runtime.c
++++ b/drivers/base/power/runtime.c
+@@ -10,8 +10,10 @@
+ #include 
+ #include 
+ #include 
++#include "power.h"
+ 
+ static int rpm_resume(struct device *dev, int rpmflags);
++static int rpm_suspend(struct device *dev, int rpmflags);
+ 
+ /**
+  * update_pm_runtime_accounting - Update the time accounting of power states
+@@ -148,6 +150,12 @@ static int rpm_idle(struct device *dev, int rpmflags)
+ 	/* Pending requests need to be canceled. */
+ 	dev->power.request = RPM_REQ_NONE;
+ 
++	if (dev->power.no_callbacks) {
++		/* Assume ->runtime_idle() callback would have suspended. */
++		retval = rpm_suspend(dev, rpmflags);
++		goto out;
++	}
++
+ 	/* Carry out an asynchronous or a synchronous idle notification. */
+ 	if (rpmflags & RPM_ASYNC) {
+ 		dev->power.request = RPM_REQ_IDLE;
+@@ -254,6 +262,10 @@ static int rpm_suspend(struct device *dev, int rpmflags)
+ 		goto repeat;
+ 	}
+ 
++	dev->power.deferred_resume = false;
++	if (dev->power.no_callbacks)
++		goto no_callback;	/* Assume success. */
++
+ 	/* Carry out an asynchronous or a synchronous suspend. */
+ 	if (rpmflags & RPM_ASYNC) {
+ 		dev->power.request = RPM_REQ_SUSPEND;
+@@ -265,7 +277,6 @@ static int rpm_suspend(struct device *dev, int rpmflags)
+ 	}
+ 
+ 	__update_runtime_status(dev, RPM_SUSPENDING);
+-	dev->power.deferred_resume = false;
+ 
+ 	if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) {
+ 		spin_unlock_irq(&dev->power.lock);
+@@ -305,6 +316,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
+ 			pm_runtime_cancel_pending(dev);
+ 		}
+ 	} else {
++ no_callback:
+ 		__update_runtime_status(dev, RPM_SUSPENDED);
+ 		pm_runtime_deactivate_timer(dev);
+ 
+@@ -409,6 +421,23 @@ static int rpm_resume(struct device *dev, int rpmflags)
+ 		goto repeat;
+ 	}
+ 
++	/*
++	 * See if we can skip waking up the parent.  This is safe only if
++	 * power.no_callbacks is set, because otherwise we don't know whether
++	 * the resume will actually succeed.
++	 */
++	if (dev->power.no_callbacks && !parent && dev->parent) {
++		spin_lock(&dev->parent->power.lock);
++		if (dev->parent->power.disable_depth > 0
++		    || dev->parent->power.ignore_children
++		    || dev->parent->power.runtime_status == RPM_ACTIVE) {
++			atomic_inc(&dev->parent->power.child_count);
++			spin_unlock(&dev->parent->power.lock);
++			goto no_callback;	/* Assume success. */
++		}
++		spin_unlock(&dev->parent->power.lock);
++	}
++
+ 	/* Carry out an asynchronous or a synchronous resume. */
+ 	if (rpmflags & RPM_ASYNC) {
+ 		dev->power.request = RPM_REQ_RESUME;
+@@ -449,6 +478,9 @@ static int rpm_resume(struct device *dev, int rpmflags)
+ 		goto repeat;
+ 	}
+ 
++	if (dev->power.no_callbacks)
++		goto no_callback;	/* Assume success. */
++
+ 	__update_runtime_status(dev, RPM_RESUMING);
+ 
+ 	if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_resume) {
+@@ -482,6 +514,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
+ 		__update_runtime_status(dev, RPM_SUSPENDED);
+ 		pm_runtime_cancel_pending(dev);
+ 	} else {
++ no_callback:
+ 		__update_runtime_status(dev, RPM_ACTIVE);
+ 		if (parent)
+ 			atomic_inc(&parent->power.child_count);
+@@ -954,6 +987,25 @@ void pm_runtime_allow(struct device *dev)
+ }
+ EXPORT_SYMBOL_GPL(pm_runtime_allow);
+ 
++/**
++ * pm_runtime_no_callbacks - Ignore run-time PM callbacks for a device.
++ * @dev: Device to handle.
++ *
++ * Set the power.no_callbacks flag, which tells the PM core that this
++ * device is power-managed through its parent and has no run-time PM
++ * callbacks of its own.  The run-time sysfs attributes will be removed.
++ *
++ */
++void pm_runtime_no_callbacks(struct device *dev)
++{
++	spin_lock_irq(&dev->power.lock);
++	dev->power.no_callbacks = 1;
++	spin_unlock_irq(&dev->power.lock);
++	if (device_is_registered(dev))
++		rpm_sysfs_remove(dev);
++}
++EXPORT_SYMBOL_GPL(pm_runtime_no_callbacks);
++
+ /**
+  * pm_runtime_init - Initialize run-time PM fields in given device object.
+  * @dev: Device object to initialize.
+diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
+index 8859780817e1..b5708c47ce2d 100644
+--- a/drivers/base/power/sysfs.c
++++ b/drivers/base/power/sysfs.c
+@@ -81,6 +81,9 @@
+ static const char enabled[] = "enabled";
+ static const char disabled[] = "disabled";
+ 
++const char power_group_name[] = "power";
++EXPORT_SYMBOL_GPL(power_group_name);
++
+ #ifdef CONFIG_PM_RUNTIME
+ static const char ctrl_auto[] = "auto";
+ static const char ctrl_on[] = "on";
+@@ -390,12 +393,6 @@ static DEVICE_ATTR(async, 0644, async_show, async_store);
+ #endif /* CONFIG_PM_ADVANCED_DEBUG */
+ 
+ static struct attribute * power_attrs[] = {
+-#ifdef CONFIG_PM_RUNTIME
+-	&dev_attr_control.attr,
+-	&dev_attr_runtime_status.attr,
+-	&dev_attr_runtime_suspended_time.attr,
+-	&dev_attr_runtime_active_time.attr,
+-#endif
+ 	&dev_attr_wakeup.attr,
+ #ifdef CONFIG_PM_SLEEP
+ 	&dev_attr_wakeup_count.attr,
+@@ -409,6 +406,7 @@ static struct attribute * power_attrs[] = {
+ #ifdef CONFIG_PM_ADVANCED_DEBUG
+ 	&dev_attr_async.attr,
+ #ifdef CONFIG_PM_RUNTIME
++	&dev_attr_runtime_status.attr,
+ 	&dev_attr_runtime_usage.attr,
+ 	&dev_attr_runtime_active_kids.attr,
+ 	&dev_attr_runtime_enabled.attr,
+@@ -417,10 +415,52 @@ static struct attribute * power_attrs[] = {
+ 	NULL,
+ };
+ static struct attribute_group pm_attr_group = {
+-	.name	= "power",
++	.name	= power_group_name,
+ 	.attrs	= power_attrs,
+ };
+ 
++#ifdef CONFIG_PM_RUNTIME
++
++static struct attribute *runtime_attrs[] = {
++#ifndef CONFIG_PM_ADVANCED_DEBUG
++	&dev_attr_runtime_status.attr,
++#endif
++	&dev_attr_control.attr,
++	&dev_attr_runtime_suspended_time.attr,
++	&dev_attr_runtime_active_time.attr,
++	NULL,
++};
++static struct attribute_group pm_runtime_attr_group = {
++	.name	= power_group_name,
++	.attrs	= runtime_attrs,
++};
++
++int dpm_sysfs_add(struct device *dev)
++{
++	int rc;
++
++	rc = sysfs_create_group(&dev->kobj, &pm_attr_group);
++	if (rc == 0 && !dev->power.no_callbacks) {
++		rc = sysfs_merge_group(&dev->kobj, &pm_runtime_attr_group);
++		if (rc)
++			sysfs_remove_group(&dev->kobj, &pm_attr_group);
++	}
++	return rc;
++}
++
++void rpm_sysfs_remove(struct device *dev)
++{
++	sysfs_unmerge_group(&dev->kobj, &pm_runtime_attr_group);
++}
++
++void dpm_sysfs_remove(struct device *dev)
++{
++	rpm_sysfs_remove(dev);
++	sysfs_remove_group(&dev->kobj, &pm_attr_group);
++}
++
++#else /* CONFIG_PM_RUNTIME */
++
+ int dpm_sysfs_add(struct device * dev)
+ {
+ 	return sysfs_create_group(&dev->kobj, &pm_attr_group);
+@@ -430,3 +470,5 @@ void dpm_sysfs_remove(struct device * dev)
+ {
+ 	sysfs_remove_group(&dev->kobj, &pm_attr_group);
+ }
++
++#endif
+diff --git a/include/linux/pm.h b/include/linux/pm.h
+index 1abfe84f447d..abd81ffaba3c 100644
+--- a/include/linux/pm.h
++++ b/include/linux/pm.h
+@@ -41,6 +41,12 @@ extern void (*pm_power_off_prepare)(void);
+ 
+ struct device;
+ 
++#ifdef CONFIG_PM
++extern const char power_group_name[];		/* = "power" */
++#else
++#define power_group_name	NULL
++#endif
++
+ typedef struct pm_message {
+ 	int event;
+ } pm_message_t;
+@@ -475,6 +481,7 @@ struct dev_pm_info {
+ 	unsigned int		deferred_resume:1;
+ 	unsigned int		run_wake:1;
+ 	unsigned int		runtime_auto:1;
++	unsigned int		no_callbacks:1;
+ 	enum rpm_request	request;
+ 	enum rpm_status		runtime_status;
+ 	int			runtime_error;
+diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h
+index 5869d87fffac..8ca52f7c357e 100644
+--- a/include/linux/pm_runtime.h
++++ b/include/linux/pm_runtime.h
+@@ -36,6 +36,7 @@ extern void pm_runtime_forbid(struct device *dev);
+ extern int pm_generic_runtime_idle(struct device *dev);
+ extern int pm_generic_runtime_suspend(struct device *dev);
+ extern int pm_generic_runtime_resume(struct device *dev);
++extern void pm_runtime_no_callbacks(struct device *dev);
+ 
+ static inline bool pm_children_suspended(struct device *dev)
+ {
+@@ -110,6 +111,7 @@ static inline bool pm_runtime_suspended(struct device *dev) { return false; }
+ static inline int pm_generic_runtime_idle(struct device *dev) { return 0; }
+ static inline int pm_generic_runtime_suspend(struct device *dev) { return 0; }
+ static inline int pm_generic_runtime_resume(struct device *dev) { return 0; }
++static inline void pm_runtime_no_callbacks(struct device *dev) {}
+ 
+ #endif /* !CONFIG_PM_RUNTIME */
+ 

commit 140a6c945211ee911dec776fafa52e03a7d7bb9a
+Author: Alan Stern 
+Date:   Sat Sep 25 23:35:07 2010 +0200
+
+    PM / Runtime: Combine runtime PM entry points
+    
+    This patch (as1424) combines the various public entry points for the
+    runtime PM routines into three simple functions: one for idle, one for
+    suspend, and one for resume.  A new bitflag specifies whether or not
+    to increment or decrement the usage_count field.
+    
+    The new entry points are named __pm_runtime_idle,
+    __pm_runtime_suspend, and __pm_runtime_resume, to reflect that they
+    are trampolines.  Simultaneously, the corresponding internal routines
+    are renamed to rpm_idle, rpm_suspend, and rpm_resume.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
+index d7b5d84c235c..ed227b7c1bb5 100644
+--- a/drivers/base/power/runtime.c
++++ b/drivers/base/power/runtime.c
+@@ -11,7 +11,7 @@
+ #include 
+ #include 
+ 
+-static int __pm_runtime_resume(struct device *dev, int rpmflags);
++static int rpm_resume(struct device *dev, int rpmflags);
+ 
+ /**
+  * update_pm_runtime_accounting - Update the time accounting of power states
+@@ -107,7 +107,7 @@ static int rpm_check_suspend_allowed(struct device *dev)
+ 
+ 
+ /**
+- * __pm_runtime_idle - Notify device bus type if the device can be suspended.
++ * rpm_idle - Notify device bus type if the device can be suspended.
+  * @dev: Device to notify the bus type about.
+  * @rpmflags: Flag bits.
+  *
+@@ -118,7 +118,7 @@ static int rpm_check_suspend_allowed(struct device *dev)
+  *
+  * This function must be called under dev->power.lock with interrupts disabled.
+  */
+-static int __pm_runtime_idle(struct device *dev, int rpmflags)
++static int rpm_idle(struct device *dev, int rpmflags)
+ 	__releases(&dev->power.lock) __acquires(&dev->power.lock)
+ {
+ 	int retval;
+@@ -189,23 +189,7 @@ static int __pm_runtime_idle(struct device *dev, int rpmflags)
+ }
+ 
+ /**
+- * pm_runtime_idle - Notify device bus type if the device can be suspended.
+- * @dev: Device to notify the bus type about.
+- */
+-int pm_runtime_idle(struct device *dev)
+-{
+-	int retval;
+-
+-	spin_lock_irq(&dev->power.lock);
+-	retval = __pm_runtime_idle(dev, 0);
+-	spin_unlock_irq(&dev->power.lock);
+-
+-	return retval;
+-}
+-EXPORT_SYMBOL_GPL(pm_runtime_idle);
+-
+-/**
+- * __pm_runtime_suspend - Carry out run-time suspend of given device.
++ * rpm_suspend - Carry out run-time suspend of given device.
+  * @dev: Device to suspend.
+  * @rpmflags: Flag bits.
+  *
+@@ -220,7 +204,7 @@ EXPORT_SYMBOL_GPL(pm_runtime_idle);
+  *
+  * This function must be called under dev->power.lock with interrupts disabled.
+  */
+-static int __pm_runtime_suspend(struct device *dev, int rpmflags)
++static int rpm_suspend(struct device *dev, int rpmflags)
+ 	__releases(&dev->power.lock) __acquires(&dev->power.lock)
+ {
+ 	struct device *parent = NULL;
+@@ -332,13 +316,13 @@ static int __pm_runtime_suspend(struct device *dev, int rpmflags)
+ 	wake_up_all(&dev->power.wait_queue);
+ 
+ 	if (dev->power.deferred_resume) {
+-		__pm_runtime_resume(dev, 0);
++		rpm_resume(dev, 0);
+ 		retval = -EAGAIN;
+ 		goto out;
+ 	}
+ 
+ 	if (notify)
+-		__pm_runtime_idle(dev, 0);
++		rpm_idle(dev, 0);
+ 
+ 	if (parent && !parent->power.ignore_children) {
+ 		spin_unlock_irq(&dev->power.lock);
+@@ -355,23 +339,7 @@ static int __pm_runtime_suspend(struct device *dev, int rpmflags)
+ }
+ 
+ /**
+- * pm_runtime_suspend - Carry out run-time suspend of given device.
+- * @dev: Device to suspend.
+- */
+-int pm_runtime_suspend(struct device *dev)
+-{
+-	int retval;
+-
+-	spin_lock_irq(&dev->power.lock);
+-	retval = __pm_runtime_suspend(dev, 0);
+-	spin_unlock_irq(&dev->power.lock);
+-
+-	return retval;
+-}
+-EXPORT_SYMBOL_GPL(pm_runtime_suspend);
+-
+-/**
+- * __pm_runtime_resume - Carry out run-time resume of given device.
++ * rpm_resume - Carry out run-time resume of given device.
+  * @dev: Device to resume.
+  * @rpmflags: Flag bits.
+  *
+@@ -387,7 +355,7 @@ EXPORT_SYMBOL_GPL(pm_runtime_suspend);
+  *
+  * This function must be called under dev->power.lock with interrupts disabled.
+  */
+-static int __pm_runtime_resume(struct device *dev, int rpmflags)
++static int rpm_resume(struct device *dev, int rpmflags)
+ 	__releases(&dev->power.lock) __acquires(&dev->power.lock)
+ {
+ 	struct device *parent = NULL;
+@@ -469,7 +437,7 @@ static int __pm_runtime_resume(struct device *dev, int rpmflags)
+ 		 */
+ 		if (!parent->power.disable_depth
+ 		    && !parent->power.ignore_children) {
+-			__pm_runtime_resume(parent, 0);
++			rpm_resume(parent, 0);
+ 			if (parent->power.runtime_status != RPM_ACTIVE)
+ 				retval = -EBUSY;
+ 		}
+@@ -521,7 +489,7 @@ static int __pm_runtime_resume(struct device *dev, int rpmflags)
+ 	wake_up_all(&dev->power.wait_queue);
+ 
+ 	if (!retval)
+-		__pm_runtime_idle(dev, RPM_ASYNC);
++		rpm_idle(dev, RPM_ASYNC);
+ 
+  out:
+ 	if (parent) {
+@@ -537,22 +505,6 @@ static int __pm_runtime_resume(struct device *dev, int rpmflags)
+ 	return retval;
+ }
+ 
+-/**
+- * pm_runtime_resume - Carry out run-time resume of given device.
+- * @dev: Device to suspend.
+- */
+-int pm_runtime_resume(struct device *dev)
+-{
+-	int retval;
+-
+-	spin_lock_irq(&dev->power.lock);
+-	retval = __pm_runtime_resume(dev, 0);
+-	spin_unlock_irq(&dev->power.lock);
+-
+-	return retval;
+-}
+-EXPORT_SYMBOL_GPL(pm_runtime_resume);
+-
+ /**
+  * pm_runtime_work - Universal run-time PM work function.
+  * @work: Work structure used for scheduling the execution of this function.
+@@ -578,13 +530,13 @@ static void pm_runtime_work(struct work_struct *work)
+ 	case RPM_REQ_NONE:
+ 		break;
+ 	case RPM_REQ_IDLE:
+-		__pm_runtime_idle(dev, RPM_NOWAIT);
++		rpm_idle(dev, RPM_NOWAIT);
+ 		break;
+ 	case RPM_REQ_SUSPEND:
+-		__pm_runtime_suspend(dev, RPM_NOWAIT);
++		rpm_suspend(dev, RPM_NOWAIT);
+ 		break;
+ 	case RPM_REQ_RESUME:
+-		__pm_runtime_resume(dev, RPM_NOWAIT);
++		rpm_resume(dev, RPM_NOWAIT);
+ 		break;
+ 	}
+ 
+@@ -592,23 +544,6 @@ static void pm_runtime_work(struct work_struct *work)
+ 	spin_unlock_irq(&dev->power.lock);
+ }
+ 
+-/**
+- * pm_request_idle - Submit an idle notification request for given device.
+- * @dev: Device to handle.
+- */
+-int pm_request_idle(struct device *dev)
+-{
+-	unsigned long flags;
+-	int retval;
+-
+-	spin_lock_irqsave(&dev->power.lock, flags);
+-	retval = __pm_runtime_idle(dev, RPM_ASYNC);
+-	spin_unlock_irqrestore(&dev->power.lock, flags);
+-
+-	return retval;
+-}
+-EXPORT_SYMBOL_GPL(pm_request_idle);
+-
+ /**
+  * pm_suspend_timer_fn - Timer function for pm_schedule_suspend().
+  * @data: Device pointer passed by pm_schedule_suspend().
+@@ -627,7 +562,7 @@ static void pm_suspend_timer_fn(unsigned long data)
+ 	/* If 'expire' is after 'jiffies' we've been called too early. */
+ 	if (expires > 0 && !time_after(expires, jiffies)) {
+ 		dev->power.timer_expires = 0;
+-		__pm_runtime_suspend(dev, RPM_ASYNC);
++		rpm_suspend(dev, RPM_ASYNC);
+ 	}
+ 
+ 	spin_unlock_irqrestore(&dev->power.lock, flags);
+@@ -646,7 +581,7 @@ int pm_schedule_suspend(struct device *dev, unsigned int delay)
+ 	spin_lock_irqsave(&dev->power.lock, flags);
+ 
+ 	if (!delay) {
+-		retval = __pm_runtime_suspend(dev, RPM_ASYNC);
++		retval = rpm_suspend(dev, RPM_ASYNC);
+ 		goto out;
+ 	}
+ 
+@@ -669,62 +604,81 @@ int pm_schedule_suspend(struct device *dev, unsigned int delay)
+ EXPORT_SYMBOL_GPL(pm_schedule_suspend);
+ 
+ /**
+- * pm_request_resume - Submit a resume request for given device.
+- * @dev: Device to resume.
++ * __pm_runtime_idle - Entry point for run-time idle operations.
++ * @dev: Device to send idle notification for.
++ * @rpmflags: Flag bits.
++ *
++ * If the RPM_GET_PUT flag is set, decrement the device's usage count and
++ * return immediately if it is larger than zero.  Then carry out an idle
++ * notification, either synchronous or asynchronous.
++ *
++ * This routine may be called in atomic context if the RPM_ASYNC flag is set.
+  */
+-int pm_request_resume(struct device *dev)
++int __pm_runtime_idle(struct device *dev, int rpmflags)
+ {
+ 	unsigned long flags;
+ 	int retval;
+ 
++	if (rpmflags & RPM_GET_PUT) {
++		if (!atomic_dec_and_test(&dev->power.usage_count))
++			return 0;
++	}
++
+ 	spin_lock_irqsave(&dev->power.lock, flags);
+-	retval = __pm_runtime_resume(dev, RPM_ASYNC);
++	retval = rpm_idle(dev, rpmflags);
+ 	spin_unlock_irqrestore(&dev->power.lock, flags);
+ 
+ 	return retval;
+ }
+-EXPORT_SYMBOL_GPL(pm_request_resume);
++EXPORT_SYMBOL_GPL(__pm_runtime_idle);
+ 
+ /**
+- * __pm_runtime_get - Reference count a device and wake it up, if necessary.
+- * @dev: Device to handle.
++ * __pm_runtime_suspend - Entry point for run-time put/suspend operations.
++ * @dev: Device to suspend.
+  * @rpmflags: Flag bits.
+  *
+- * Increment the usage count of the device and resume it or submit a resume
+- * request for it, depending on the RPM_ASYNC flag bit.
++ * Carry out a suspend, either synchronous or asynchronous.
++ *
++ * This routine may be called in atomic context if the RPM_ASYNC flag is set.
+  */
+-int __pm_runtime_get(struct device *dev, int rpmflags)
++int __pm_runtime_suspend(struct device *dev, int rpmflags)
+ {
++	unsigned long flags;
+ 	int retval;
+ 
+-	atomic_inc(&dev->power.usage_count);
+-	retval = (rpmflags & RPM_ASYNC) ?
+-	    pm_request_resume(dev) : pm_runtime_resume(dev);
++	spin_lock_irqsave(&dev->power.lock, flags);
++	retval = rpm_suspend(dev, rpmflags);
++	spin_unlock_irqrestore(&dev->power.lock, flags);
+ 
+ 	return retval;
+ }
+-EXPORT_SYMBOL_GPL(__pm_runtime_get);
++EXPORT_SYMBOL_GPL(__pm_runtime_suspend);
+ 
+ /**
+- * __pm_runtime_put - Decrement the device's usage counter and notify its bus.
+- * @dev: Device to handle.
++ * __pm_runtime_resume - Entry point for run-time resume operations.
++ * @dev: Device to resume.
+  * @rpmflags: Flag bits.
+  *
+- * Decrement the usage count of the device and if it reaches zero, carry out a
+- * synchronous idle notification or submit an idle notification request for it,
+- * depending on the RPM_ASYNC flag bit.
++ * If the RPM_GET_PUT flag is set, increment the device's usage count.  Then
++ * carry out a resume, either synchronous or asynchronous.
++ *
++ * This routine may be called in atomic context if the RPM_ASYNC flag is set.
+  */
+-int __pm_runtime_put(struct device *dev, int rpmflags)
++int __pm_runtime_resume(struct device *dev, int rpmflags)
+ {
+-	int retval = 0;
++	unsigned long flags;
++	int retval;
+ 
+-	if (atomic_dec_and_test(&dev->power.usage_count))
+-		retval = (rpmflags & RPM_ASYNC) ?
+-		    pm_request_idle(dev) : pm_runtime_idle(dev);
++	if (rpmflags & RPM_GET_PUT)
++		atomic_inc(&dev->power.usage_count);
++
++	spin_lock_irqsave(&dev->power.lock, flags);
++	retval = rpm_resume(dev, rpmflags);
++	spin_unlock_irqrestore(&dev->power.lock, flags);
+ 
+ 	return retval;
+ }
+-EXPORT_SYMBOL_GPL(__pm_runtime_put);
++EXPORT_SYMBOL_GPL(__pm_runtime_resume);
+ 
+ /**
+  * __pm_runtime_set_status - Set run-time PM status of a device.
+@@ -875,7 +829,7 @@ int pm_runtime_barrier(struct device *dev)
+ 
+ 	if (dev->power.request_pending
+ 	    && dev->power.request == RPM_REQ_RESUME) {
+-		__pm_runtime_resume(dev, 0);
++		rpm_resume(dev, 0);
+ 		retval = 1;
+ 	}
+ 
+@@ -924,7 +878,7 @@ void __pm_runtime_disable(struct device *dev, bool check_resume)
+ 		 */
+ 		pm_runtime_get_noresume(dev);
+ 
+-		__pm_runtime_resume(dev, 0);
++		rpm_resume(dev, 0);
+ 
+ 		pm_runtime_put_noidle(dev);
+ 	}
+@@ -972,7 +926,7 @@ void pm_runtime_forbid(struct device *dev)
+ 
+ 	dev->power.runtime_auto = false;
+ 	atomic_inc(&dev->power.usage_count);
+-	__pm_runtime_resume(dev, 0);
++	rpm_resume(dev, 0);
+ 
+  out:
+ 	spin_unlock_irq(&dev->power.lock);
+@@ -993,7 +947,7 @@ void pm_runtime_allow(struct device *dev)
+ 
+ 	dev->power.runtime_auto = true;
+ 	if (atomic_dec_and_test(&dev->power.usage_count))
+-		__pm_runtime_idle(dev, 0);
++		rpm_idle(dev, 0);
+ 
+  out:
+ 	spin_unlock_irq(&dev->power.lock);
+diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h
+index c030cac59aac..5869d87fffac 100644
+--- a/include/linux/pm_runtime.h
++++ b/include/linux/pm_runtime.h
+@@ -16,19 +16,17 @@
+ #define RPM_ASYNC		0x01	/* Request is asynchronous */
+ #define RPM_NOWAIT		0x02	/* Don't wait for concurrent
+ 					    state change */
++#define RPM_GET_PUT		0x04	/* Increment/decrement the
++					    usage_count */
+ 
+ #ifdef CONFIG_PM_RUNTIME
+ 
+ extern struct workqueue_struct *pm_wq;
+ 
+-extern int pm_runtime_idle(struct device *dev);
+-extern int pm_runtime_suspend(struct device *dev);
+-extern int pm_runtime_resume(struct device *dev);
+-extern int pm_request_idle(struct device *dev);
++extern int __pm_runtime_idle(struct device *dev, int rpmflags);
++extern int __pm_runtime_suspend(struct device *dev, int rpmflags);
++extern int __pm_runtime_resume(struct device *dev, int rpmflags);
+ extern int pm_schedule_suspend(struct device *dev, unsigned int delay);
+-extern int pm_request_resume(struct device *dev);
+-extern int __pm_runtime_get(struct device *dev, int rpmflags);
+-extern int __pm_runtime_put(struct device *dev, int rpmflags);
+ extern int __pm_runtime_set_status(struct device *dev, unsigned int status);
+ extern int pm_runtime_barrier(struct device *dev);
+ extern void pm_runtime_enable(struct device *dev);
+@@ -77,19 +75,22 @@ static inline bool pm_runtime_suspended(struct device *dev)
+ 
+ #else /* !CONFIG_PM_RUNTIME */
+ 
+-static inline int pm_runtime_idle(struct device *dev) { return -ENOSYS; }
+-static inline int pm_runtime_suspend(struct device *dev) { return -ENOSYS; }
+-static inline int pm_runtime_resume(struct device *dev) { return 0; }
+-static inline int pm_request_idle(struct device *dev) { return -ENOSYS; }
++static inline int __pm_runtime_idle(struct device *dev, int rpmflags)
++{
++	return -ENOSYS;
++}
++static inline int __pm_runtime_suspend(struct device *dev, int rpmflags)
++{
++	return -ENOSYS;
++}
++static inline int __pm_runtime_resume(struct device *dev, int rpmflags)
++{
++	return 1;
++}
+ static inline int pm_schedule_suspend(struct device *dev, unsigned int delay)
+ {
+ 	return -ENOSYS;
+ }
+-static inline int pm_request_resume(struct device *dev) { return 0; }
+-static inline int __pm_runtime_get(struct device *dev, int rpmflags)
+-					{ return 1; }
+-static inline int __pm_runtime_put(struct device *dev, int rpmflags)
+-					{ return 0; }
+ static inline int __pm_runtime_set_status(struct device *dev,
+ 					    unsigned int status) { return 0; }
+ static inline int pm_runtime_barrier(struct device *dev) { return 0; }
+@@ -112,24 +113,49 @@ static inline int pm_generic_runtime_resume(struct device *dev) { return 0; }
+ 
+ #endif /* !CONFIG_PM_RUNTIME */
+ 
++static inline int pm_runtime_idle(struct device *dev)
++{
++	return __pm_runtime_idle(dev, 0);
++}
++
++static inline int pm_runtime_suspend(struct device *dev)
++{
++	return __pm_runtime_suspend(dev, 0);
++}
++
++static inline int pm_runtime_resume(struct device *dev)
++{
++	return __pm_runtime_resume(dev, 0);
++}
++
++static inline int pm_request_idle(struct device *dev)
++{
++	return __pm_runtime_idle(dev, RPM_ASYNC);
++}
++
++static inline int pm_request_resume(struct device *dev)
++{
++	return __pm_runtime_resume(dev, RPM_ASYNC);
++}
++
+ static inline int pm_runtime_get(struct device *dev)
+ {
+-	return __pm_runtime_get(dev, RPM_ASYNC);
++	return __pm_runtime_resume(dev, RPM_GET_PUT | RPM_ASYNC);
+ }
+ 
+ static inline int pm_runtime_get_sync(struct device *dev)
+ {
+-	return __pm_runtime_get(dev, 0);
++	return __pm_runtime_resume(dev, RPM_GET_PUT);
+ }
+ 
+ static inline int pm_runtime_put(struct device *dev)
+ {
+-	return __pm_runtime_put(dev, RPM_ASYNC);
++	return __pm_runtime_idle(dev, RPM_GET_PUT | RPM_ASYNC);
+ }
+ 
+ static inline int pm_runtime_put_sync(struct device *dev)
+ {
+-	return __pm_runtime_put(dev, 0);
++	return __pm_runtime_idle(dev, RPM_GET_PUT);
+ }
+ 
+ static inline int pm_runtime_set_active(struct device *dev)

commit 1bfee5bc86fdaecc912e06080583eddab7263df2
+Author: Alan Stern 
+Date:   Sat Sep 25 23:35:00 2010 +0200
+
+    PM / Runtime: Merge synchronous and async runtime routines
+    
+    This patch (as1423) merges the asynchronous routines
+    __pm_request_idle(), __pm_request_suspend(), and __pm_request_resume()
+    with their synchronous counterparts.  The RPM_ASYNC bitflag argument
+    serves to indicate what sort of operation to perform.
+    
+    In the course of performing this merger, it became apparent that the
+    various functions don't all behave consistenly with regard to error
+    reporting and cancellation of outstanding requests.  A new routine,
+    rpm_check_suspend_allowed(), was written to centralize much of the
+    testing, and the other functions were revised to follow a simple
+    algorithm:
+    
+            If the operation is disallowed because of the device's
+            settings or current state, return an error.
+    
+            Cancel pending or scheduled requests of lower priority.
+    
+            Schedule, queue, or perform the desired operation.
+    
+    A few special cases and exceptions are noted in comments.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
+index 0c1db879544b..d7b5d84c235c 100644
+--- a/drivers/base/power/runtime.c
++++ b/drivers/base/power/runtime.c
+@@ -2,6 +2,7 @@
+  * drivers/base/power/runtime.c - Helper functions for device run-time PM
+  *
+  * Copyright (c) 2009 Rafael J. Wysocki , Novell Inc.
++ * Copyright (C) 2010 Alan Stern 
+  *
+  * This file is released under the GPLv2.
+  */
+@@ -11,8 +12,6 @@
+ #include 
+ 
+ static int __pm_runtime_resume(struct device *dev, int rpmflags);
+-static int __pm_request_idle(struct device *dev);
+-static int __pm_request_resume(struct device *dev);
+ 
+ /**
+  * update_pm_runtime_accounting - Update the time accounting of power states
+@@ -79,40 +78,84 @@ static void pm_runtime_cancel_pending(struct device *dev)
+ }
+ 
+ /**
+- * __pm_runtime_idle - Notify device bus type if the device can be suspended.
+- * @dev: Device to notify the bus type about.
+- *
+- * This function must be called under dev->power.lock with interrupts disabled.
++ * rpm_check_suspend_allowed - Test whether a device may be suspended.
++ * @dev: Device to test.
+  */
+-static int __pm_runtime_idle(struct device *dev)
+-	__releases(&dev->power.lock) __acquires(&dev->power.lock)
++static int rpm_check_suspend_allowed(struct device *dev)
+ {
+ 	int retval = 0;
+ 
+ 	if (dev->power.runtime_error)
+ 		retval = -EINVAL;
+-	else if (dev->power.idle_notification)
+-		retval = -EINPROGRESS;
+ 	else if (atomic_read(&dev->power.usage_count) > 0
+-	    || dev->power.disable_depth > 0
+-	    || dev->power.runtime_status != RPM_ACTIVE)
++	    || dev->power.disable_depth > 0)
+ 		retval = -EAGAIN;
+ 	else if (!pm_children_suspended(dev))
+ 		retval = -EBUSY;
++
++	/* Pending resume requests take precedence over suspends. */
++	else if ((dev->power.deferred_resume
++			&& dev->power.status == RPM_SUSPENDING)
++	    || (dev->power.request_pending
++			&& dev->power.request == RPM_REQ_RESUME))
++		retval = -EAGAIN;
++	else if (dev->power.runtime_status == RPM_SUSPENDED)
++		retval = 1;
++
++	return retval;
++}
++
++
++/**
++ * __pm_runtime_idle - Notify device bus type if the device can be suspended.
++ * @dev: Device to notify the bus type about.
++ * @rpmflags: Flag bits.
++ *
++ * Check if the device's run-time PM status allows it to be suspended.  If
++ * another idle notification has been started earlier, return immediately.  If
++ * the RPM_ASYNC flag is set then queue an idle-notification request; otherwise
++ * run the ->runtime_idle() callback directly.
++ *
++ * This function must be called under dev->power.lock with interrupts disabled.
++ */
++static int __pm_runtime_idle(struct device *dev, int rpmflags)
++	__releases(&dev->power.lock) __acquires(&dev->power.lock)
++{
++	int retval;
++
++	retval = rpm_check_suspend_allowed(dev);
++	if (retval < 0)
++		;	/* Conditions are wrong. */
++
++	/* Idle notifications are allowed only in the RPM_ACTIVE state. */
++	else if (dev->power.runtime_status != RPM_ACTIVE)
++		retval = -EAGAIN;
++
++	/*
++	 * Any pending request other than an idle notification takes
++	 * precedence over us, except that the timer may be running.
++	 */
++	else if (dev->power.request_pending &&
++	    dev->power.request > RPM_REQ_IDLE)
++		retval = -EAGAIN;
++
++	/* Act as though RPM_NOWAIT is always set. */
++	else if (dev->power.idle_notification)
++		retval = -EINPROGRESS;
+ 	if (retval)
+ 		goto out;
+ 
+-	if (dev->power.request_pending) {
+-		/*
+-		 * If an idle notification request is pending, cancel it.  Any
+-		 * other pending request takes precedence over us.
+-		 */
+-		if (dev->power.request == RPM_REQ_IDLE) {
+-			dev->power.request = RPM_REQ_NONE;
+-		} else if (dev->power.request != RPM_REQ_NONE) {
+-			retval = -EAGAIN;
+-			goto out;
++	/* Pending requests need to be canceled. */
++	dev->power.request = RPM_REQ_NONE;
++
++	/* Carry out an asynchronous or a synchronous idle notification. */
++	if (rpmflags & RPM_ASYNC) {
++		dev->power.request = RPM_REQ_IDLE;
++		if (!dev->power.request_pending) {
++			dev->power.request_pending = true;
++			queue_work(pm_wq, &dev->power.work);
+ 		}
++		goto out;
+ 	}
+ 
+ 	dev->power.idle_notification = true;
+@@ -154,7 +197,7 @@ int pm_runtime_idle(struct device *dev)
+ 	int retval;
+ 
+ 	spin_lock_irq(&dev->power.lock);
+-	retval = __pm_runtime_idle(dev);
++	retval = __pm_runtime_idle(dev, 0);
+ 	spin_unlock_irq(&dev->power.lock);
+ 
+ 	return retval;
+@@ -166,11 +209,14 @@ EXPORT_SYMBOL_GPL(pm_runtime_idle);
+  * @dev: Device to suspend.
+  * @rpmflags: Flag bits.
+  *
+- * Check if the device can be suspended and run the ->runtime_suspend() callback
+- * provided by its bus type.  If another suspend has been started earlier,
+- * either return immediately or wait for it to finish, depending on the
+- * RPM_NOWAIT flag.  If an idle notification or suspend request is pending or
+- * scheduled, cancel it.
++ * Check if the device's run-time PM status allows it to be suspended.  If
++ * another suspend has been started earlier, either return immediately or wait
++ * for it to finish, depending on the RPM_NOWAIT and RPM_ASYNC flags.  Cancel a
++ * pending idle notification.  If the RPM_ASYNC flag is set then queue a
++ * suspend request; otherwise run the ->runtime_suspend() callback directly.
++ * If a deferred resume was requested while the callback was running then carry
++ * it out; otherwise send an idle notification for the device (if the suspend
++ * failed) or for its parent (if the suspend succeeded).
+  *
+  * This function must be called under dev->power.lock with interrupts disabled.
+  */
+@@ -179,41 +225,30 @@ static int __pm_runtime_suspend(struct device *dev, int rpmflags)
+ {
+ 	struct device *parent = NULL;
+ 	bool notify = false;
+-	int retval = 0;
++	int retval;
+ 
+ 	dev_dbg(dev, "%s flags 0x%x\n", __func__, rpmflags);
+ 
+  repeat:
+-	if (dev->power.runtime_error) {
+-		retval = -EINVAL;
+-		goto out;
+-	}
++	retval = rpm_check_suspend_allowed(dev);
+ 
+-	/* Pending resume requests take precedence over us. */
+-	if (dev->power.request_pending
+-	    && dev->power.request == RPM_REQ_RESUME) {
++	if (retval < 0)
++		;	/* Conditions are wrong. */
++
++	/* Synchronous suspends are not allowed in the RPM_RESUMING state. */
++	else if (dev->power.runtime_status == RPM_RESUMING &&
++	    !(rpmflags & RPM_ASYNC))
+ 		retval = -EAGAIN;
++	if (retval)
+ 		goto out;
+-	}
+ 
+ 	/* Other scheduled or pending requests need to be canceled. */
+ 	pm_runtime_cancel_pending(dev);
+ 
+-	if (dev->power.runtime_status == RPM_SUSPENDED)
+-		retval = 1;
+-	else if (dev->power.runtime_status == RPM_RESUMING
+-	    || dev->power.disable_depth > 0
+-	    || atomic_read(&dev->power.usage_count) > 0)
+-		retval = -EAGAIN;
+-	else if (!pm_children_suspended(dev))
+-		retval = -EBUSY;
+-	if (retval)
+-		goto out;
+-
+ 	if (dev->power.runtime_status == RPM_SUSPENDING) {
+ 		DEFINE_WAIT(wait);
+ 
+-		if (rpmflags & RPM_NOWAIT) {
++		if (rpmflags & (RPM_ASYNC | RPM_NOWAIT)) {
+ 			retval = -EINPROGRESS;
+ 			goto out;
+ 		}
+@@ -235,6 +270,16 @@ static int __pm_runtime_suspend(struct device *dev, int rpmflags)
+ 		goto repeat;
+ 	}
+ 
++	/* Carry out an asynchronous or a synchronous suspend. */
++	if (rpmflags & RPM_ASYNC) {
++		dev->power.request = RPM_REQ_SUSPEND;
++		if (!dev->power.request_pending) {
++			dev->power.request_pending = true;
++			queue_work(pm_wq, &dev->power.work);
++		}
++		goto out;
++	}
++
+ 	__update_runtime_status(dev, RPM_SUSPENDING);
+ 	dev->power.deferred_resume = false;
+ 
+@@ -267,6 +312,7 @@ static int __pm_runtime_suspend(struct device *dev, int rpmflags)
+ 
+ 	if (retval) {
+ 		__update_runtime_status(dev, RPM_ACTIVE);
++		dev->power.deferred_resume = 0;
+ 		if (retval == -EAGAIN || retval == -EBUSY) {
+ 			if (dev->power.timer_expires == 0)
+ 				notify = true;
+@@ -292,7 +338,7 @@ static int __pm_runtime_suspend(struct device *dev, int rpmflags)
+ 	}
+ 
+ 	if (notify)
+-		__pm_runtime_idle(dev);
++		__pm_runtime_idle(dev, 0);
+ 
+ 	if (parent && !parent->power.ignore_children) {
+ 		spin_unlock_irq(&dev->power.lock);
+@@ -329,13 +375,15 @@ EXPORT_SYMBOL_GPL(pm_runtime_suspend);
+  * @dev: Device to resume.
+  * @rpmflags: Flag bits.
+  *
+- * Check if the device can be woken up and run the ->runtime_resume() callback
+- * provided by its bus type.  If another resume has been started earlier,
+- * either return imediately or wait for it to finish, depending on the
+- * RPM_NOWAIT flag.  If there's a suspend running in parallel with this
+- * function, either tell the other process to resume after suspending
+- * (deferred_resume) or wait for it to finish, depending on the RPM_NOWAIT
+- * flag.  Cancel any scheduled or pending requests.
++ * Check if the device's run-time PM status allows it to be resumed.  Cancel
++ * any scheduled or pending requests.  If another resume has been started
++ * earlier, either return imediately or wait for it to finish, depending on the
++ * RPM_NOWAIT and RPM_ASYNC flags.  Similarly, if there's a suspend running in
++ * parallel with this function, either tell the other process to resume after
++ * suspending (deferred_resume) or wait for it to finish.  If the RPM_ASYNC
++ * flag is set then queue a resume request; otherwise run the
++ * ->runtime_resume() callback directly.  Queue an idle notification for the
++ * device if the resume succeeded.
+  *
+  * This function must be called under dev->power.lock with interrupts disabled.
+  */
+@@ -348,28 +396,30 @@ static int __pm_runtime_resume(struct device *dev, int rpmflags)
+ 	dev_dbg(dev, "%s flags 0x%x\n", __func__, rpmflags);
+ 
+  repeat:
+-	if (dev->power.runtime_error) {
++	if (dev->power.runtime_error)
+ 		retval = -EINVAL;
++	else if (dev->power.disable_depth > 0)
++		retval = -EAGAIN;
++	if (retval)
+ 		goto out;
+-	}
+ 
++	/* Other scheduled or pending requests need to be canceled. */
+ 	pm_runtime_cancel_pending(dev);
+ 
+-	if (dev->power.runtime_status == RPM_ACTIVE)
++	if (dev->power.runtime_status == RPM_ACTIVE) {
+ 		retval = 1;
+-	else if (dev->power.disable_depth > 0)
+-		retval = -EAGAIN;
+-	if (retval)
+ 		goto out;
++	}
+ 
+ 	if (dev->power.runtime_status == RPM_RESUMING
+ 	    || dev->power.runtime_status == RPM_SUSPENDING) {
+ 		DEFINE_WAIT(wait);
+ 
+-		if (rpmflags & RPM_NOWAIT) {
++		if (rpmflags & (RPM_ASYNC | RPM_NOWAIT)) {
+ 			if (dev->power.runtime_status == RPM_SUSPENDING)
+ 				dev->power.deferred_resume = true;
+-			retval = -EINPROGRESS;
++			else
++				retval = -EINPROGRESS;
+ 			goto out;
+ 		}
+ 
+@@ -391,6 +441,17 @@ static int __pm_runtime_resume(struct device *dev, int rpmflags)
+ 		goto repeat;
+ 	}
+ 
++	/* Carry out an asynchronous or a synchronous resume. */
++	if (rpmflags & RPM_ASYNC) {
++		dev->power.request = RPM_REQ_RESUME;
++		if (!dev->power.request_pending) {
++			dev->power.request_pending = true;
++			queue_work(pm_wq, &dev->power.work);
++		}
++		retval = 0;
++		goto out;
++	}
++
+ 	if (!parent && dev->parent) {
+ 		/*
+ 		 * Increment the parent's resume counter and resume it if
+@@ -460,7 +521,7 @@ static int __pm_runtime_resume(struct device *dev, int rpmflags)
+ 	wake_up_all(&dev->power.wait_queue);
+ 
+ 	if (!retval)
+-		__pm_request_idle(dev);
++		__pm_runtime_idle(dev, RPM_ASYNC);
+ 
+  out:
+ 	if (parent) {
+@@ -517,7 +578,7 @@ static void pm_runtime_work(struct work_struct *work)
+ 	case RPM_REQ_NONE:
+ 		break;
+ 	case RPM_REQ_IDLE:
+-		__pm_runtime_idle(dev);
++		__pm_runtime_idle(dev, RPM_NOWAIT);
+ 		break;
+ 	case RPM_REQ_SUSPEND:
+ 		__pm_runtime_suspend(dev, RPM_NOWAIT);
+@@ -531,47 +592,6 @@ static void pm_runtime_work(struct work_struct *work)
+ 	spin_unlock_irq(&dev->power.lock);
+ }
+ 
+-/**
+- * __pm_request_idle - Submit an idle notification request for given device.
+- * @dev: Device to handle.
+- *
+- * Check if the device's run-time PM status is correct for suspending the device
+- * and queue up a request to run __pm_runtime_idle() for it.
+- *
+- * This function must be called under dev->power.lock with interrupts disabled.
+- */
+-static int __pm_request_idle(struct device *dev)
+-{
+-	int retval = 0;
+-
+-	if (dev->power.runtime_error)
+-		retval = -EINVAL;
+-	else if (atomic_read(&dev->power.usage_count) > 0
+-	    || dev->power.disable_depth > 0
+-	    || dev->power.runtime_status == RPM_SUSPENDED
+-	    || dev->power.runtime_status == RPM_SUSPENDING)
+-		retval = -EAGAIN;
+-	else if (!pm_children_suspended(dev))
+-		retval = -EBUSY;
+-	if (retval)
+-		return retval;
+-
+-	if (dev->power.request_pending) {
+-		/* Any requests other then RPM_REQ_IDLE take precedence. */
+-		if (dev->power.request == RPM_REQ_NONE)
+-			dev->power.request = RPM_REQ_IDLE;
+-		else if (dev->power.request != RPM_REQ_IDLE)
+-			retval = -EAGAIN;
+-		return retval;
+-	}
+-
+-	dev->power.request = RPM_REQ_IDLE;
+-	dev->power.request_pending = true;
+-	queue_work(pm_wq, &dev->power.work);
+-
+-	return retval;
+-}
+-
+ /**
+  * pm_request_idle - Submit an idle notification request for given device.
+  * @dev: Device to handle.
+@@ -582,67 +602,18 @@ int pm_request_idle(struct device *dev)
+ 	int retval;
+ 
+ 	spin_lock_irqsave(&dev->power.lock, flags);
+-	retval = __pm_request_idle(dev);
++	retval = __pm_runtime_idle(dev, RPM_ASYNC);
+ 	spin_unlock_irqrestore(&dev->power.lock, flags);
+ 
+ 	return retval;
+ }
+ EXPORT_SYMBOL_GPL(pm_request_idle);
+ 
+-/**
+- * __pm_request_suspend - Submit a suspend request for given device.
+- * @dev: Device to suspend.
+- *
+- * This function must be called under dev->power.lock with interrupts disabled.
+- */
+-static int __pm_request_suspend(struct device *dev)
+-{
+-	int retval = 0;
+-
+-	if (dev->power.runtime_error)
+-		return -EINVAL;
+-
+-	if (dev->power.runtime_status == RPM_SUSPENDED)
+-		retval = 1;
+-	else if (atomic_read(&dev->power.usage_count) > 0
+-	    || dev->power.disable_depth > 0)
+-		retval = -EAGAIN;
+-	else if (dev->power.runtime_status == RPM_SUSPENDING)
+-		retval = -EINPROGRESS;
+-	else if (!pm_children_suspended(dev))
+-		retval = -EBUSY;
+-	if (retval < 0)
+-		return retval;
+-
+-	pm_runtime_deactivate_timer(dev);
+-
+-	if (dev->power.request_pending) {
+-		/*
+-		 * Pending resume requests take precedence over us, but we can
+-		 * overtake any other pending request.
+-		 */
+-		if (dev->power.request == RPM_REQ_RESUME)
+-			retval = -EAGAIN;
+-		else if (dev->power.request != RPM_REQ_SUSPEND)
+-			dev->power.request = retval ?
+-						RPM_REQ_NONE : RPM_REQ_SUSPEND;
+-		return retval;
+-	} else if (retval) {
+-		return retval;
+-	}
+-
+-	dev->power.request = RPM_REQ_SUSPEND;
+-	dev->power.request_pending = true;
+-	queue_work(pm_wq, &dev->power.work);
+-
+-	return 0;
+-}
+-
+ /**
+  * pm_suspend_timer_fn - Timer function for pm_schedule_suspend().
+  * @data: Device pointer passed by pm_schedule_suspend().
+  *
+- * Check if the time is right and execute __pm_request_suspend() in that case.
++ * Check if the time is right and queue a suspend request.
+  */
+ static void pm_suspend_timer_fn(unsigned long data)
+ {
+@@ -656,7 +627,7 @@ static void pm_suspend_timer_fn(unsigned long data)
+ 	/* If 'expire' is after 'jiffies' we've been called too early. */
+ 	if (expires > 0 && !time_after(expires, jiffies)) {
+ 		dev->power.timer_expires = 0;
+-		__pm_request_suspend(dev);
++		__pm_runtime_suspend(dev, RPM_ASYNC);
+ 	}
+ 
+ 	spin_unlock_irqrestore(&dev->power.lock, flags);
+@@ -670,47 +641,24 @@ static void pm_suspend_timer_fn(unsigned long data)
+ int pm_schedule_suspend(struct device *dev, unsigned int delay)
+ {
+ 	unsigned long flags;
+-	int retval = 0;
++	int retval;
+ 
+ 	spin_lock_irqsave(&dev->power.lock, flags);
+ 
+-	if (dev->power.runtime_error) {
+-		retval = -EINVAL;
+-		goto out;
+-	}
+-
+ 	if (!delay) {
+-		retval = __pm_request_suspend(dev);
++		retval = __pm_runtime_suspend(dev, RPM_ASYNC);
+ 		goto out;
+ 	}
+ 
+-	pm_runtime_deactivate_timer(dev);
+-
+-	if (dev->power.request_pending) {
+-		/*
+-		 * Pending resume requests take precedence over us, but any
+-		 * other pending requests have to be canceled.
+-		 */
+-		if (dev->power.request == RPM_REQ_RESUME) {
+-			retval = -EAGAIN;
+-			goto out;
+-		}
+-		dev->power.request = RPM_REQ_NONE;
+-	}
+-
+-	if (dev->power.runtime_status == RPM_SUSPENDED)
+-		retval = 1;
+-	else if (atomic_read(&dev->power.usage_count) > 0
+-	    || dev->power.disable_depth > 0)
+-		retval = -EAGAIN;
+-	else if (!pm_children_suspended(dev))
+-		retval = -EBUSY;
++	retval = rpm_check_suspend_allowed(dev);
+ 	if (retval)
+ 		goto out;
+ 
++	/* Other scheduled or pending requests need to be canceled. */
++	pm_runtime_cancel_pending(dev);
++
+ 	dev->power.timer_expires = jiffies + msecs_to_jiffies(delay);
+-	if (!dev->power.timer_expires)
+-		dev->power.timer_expires = 1;
++	dev->power.timer_expires += !dev->power.timer_expires;
+ 	mod_timer(&dev->power.suspend_timer, dev->power.timer_expires);
+ 
+  out:
+@@ -720,49 +668,6 @@ int pm_schedule_suspend(struct device *dev, unsigned int delay)
+ }
+ EXPORT_SYMBOL_GPL(pm_schedule_suspend);
+ 
+-/**
+- * pm_request_resume - Submit a resume request for given device.
+- * @dev: Device to resume.
+- *
+- * This function must be called under dev->power.lock with interrupts disabled.
+- */
+-static int __pm_request_resume(struct device *dev)
+-{
+-	int retval = 0;
+-
+-	if (dev->power.runtime_error)
+-		return -EINVAL;
+-
+-	if (dev->power.runtime_status == RPM_ACTIVE)
+-		retval = 1;
+-	else if (dev->power.runtime_status == RPM_RESUMING)
+-		retval = -EINPROGRESS;
+-	else if (dev->power.disable_depth > 0)
+-		retval = -EAGAIN;
+-	if (retval < 0)
+-		return retval;
+-
+-	pm_runtime_deactivate_timer(dev);
+-
+-	if (dev->power.runtime_status == RPM_SUSPENDING) {
+-		dev->power.deferred_resume = true;
+-		return retval;
+-	}
+-	if (dev->power.request_pending) {
+-		/* If non-resume request is pending, we can overtake it. */
+-		dev->power.request = retval ? RPM_REQ_NONE : RPM_REQ_RESUME;
+-		return retval;
+-	}
+-	if (retval)
+-		return retval;
+-
+-	dev->power.request = RPM_REQ_RESUME;
+-	dev->power.request_pending = true;
+-	queue_work(pm_wq, &dev->power.work);
+-
+-	return retval;
+-}
+-
+ /**
+  * pm_request_resume - Submit a resume request for given device.
+  * @dev: Device to resume.
+@@ -773,7 +678,7 @@ int pm_request_resume(struct device *dev)
+ 	int retval;
+ 
+ 	spin_lock_irqsave(&dev->power.lock, flags);
+-	retval = __pm_request_resume(dev);
++	retval = __pm_runtime_resume(dev, RPM_ASYNC);
+ 	spin_unlock_irqrestore(&dev->power.lock, flags);
+ 
+ 	return retval;
+@@ -1088,7 +993,7 @@ void pm_runtime_allow(struct device *dev)
+ 
+ 	dev->power.runtime_auto = true;
+ 	if (atomic_dec_and_test(&dev->power.usage_count))
+-		__pm_runtime_idle(dev);
++		__pm_runtime_idle(dev, 0);
+ 
+  out:
+ 	spin_unlock_irq(&dev->power.lock);

commit 3f9af0513ae5b1f185302c2d0ba656640926d970
+Author: Alan Stern 
+Date:   Sat Sep 25 23:34:54 2010 +0200
+
+    PM / Runtime: Replace boolean arguments with bitflags
+    
+    The "from_wq" argument in __pm_runtime_suspend() and
+    __pm_runtime_resume() supposedly indicates whether or not the function
+    was called by the PM workqueue thread, but in fact it isn't always
+    used this way.  It really indicates whether or not the function should
+    return early if the requested operation is already in progress.
+    
+    Along with this badly-named boolean argument, later patches in this
+    series will add several other boolean arguments to these functions and
+    others.  Therefore this patch (as1422) begins the conversion process
+    by replacing from_wq with a bitflag argument.  The same bitflags are
+    also used in __pm_runtime_get() and __pm_runtime_put(), where they
+    indicate whether or not the operation should be asynchronous.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
+index ec08f1ae63f1..0c1db879544b 100644
+--- a/drivers/base/power/runtime.c
++++ b/drivers/base/power/runtime.c
+@@ -10,7 +10,7 @@
+ #include 
+ #include 
+ 
+-static int __pm_runtime_resume(struct device *dev, bool from_wq);
++static int __pm_runtime_resume(struct device *dev, int rpmflags);
+ static int __pm_request_idle(struct device *dev);
+ static int __pm_request_resume(struct device *dev);
+ 
+@@ -164,24 +164,24 @@ EXPORT_SYMBOL_GPL(pm_runtime_idle);
+ /**
+  * __pm_runtime_suspend - Carry out run-time suspend of given device.
+  * @dev: Device to suspend.
+- * @from_wq: If set, the function has been called via pm_wq.
++ * @rpmflags: Flag bits.
+  *
+  * Check if the device can be suspended and run the ->runtime_suspend() callback
+- * provided by its bus type.  If another suspend has been started earlier, wait
+- * for it to finish.  If an idle notification or suspend request is pending or
++ * provided by its bus type.  If another suspend has been started earlier,
++ * either return immediately or wait for it to finish, depending on the
++ * RPM_NOWAIT flag.  If an idle notification or suspend request is pending or
+  * scheduled, cancel it.
+  *
+  * This function must be called under dev->power.lock with interrupts disabled.
+  */
+-int __pm_runtime_suspend(struct device *dev, bool from_wq)
++static int __pm_runtime_suspend(struct device *dev, int rpmflags)
+ 	__releases(&dev->power.lock) __acquires(&dev->power.lock)
+ {
+ 	struct device *parent = NULL;
+ 	bool notify = false;
+ 	int retval = 0;
+ 
+-	dev_dbg(dev, "__pm_runtime_suspend()%s!\n",
+-		from_wq ? " from workqueue" : "");
++	dev_dbg(dev, "%s flags 0x%x\n", __func__, rpmflags);
+ 
+  repeat:
+ 	if (dev->power.runtime_error) {
+@@ -213,7 +213,7 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq)
+ 	if (dev->power.runtime_status == RPM_SUSPENDING) {
+ 		DEFINE_WAIT(wait);
+ 
+-		if (from_wq) {
++		if (rpmflags & RPM_NOWAIT) {
+ 			retval = -EINPROGRESS;
+ 			goto out;
+ 		}
+@@ -286,7 +286,7 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq)
+ 	wake_up_all(&dev->power.wait_queue);
+ 
+ 	if (dev->power.deferred_resume) {
+-		__pm_runtime_resume(dev, false);
++		__pm_runtime_resume(dev, 0);
+ 		retval = -EAGAIN;
+ 		goto out;
+ 	}
+@@ -303,7 +303,7 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq)
+ 	}
+ 
+  out:
+-	dev_dbg(dev, "__pm_runtime_suspend() returns %d!\n", retval);
++	dev_dbg(dev, "%s returns %d\n", __func__, retval);
+ 
+ 	return retval;
+ }
+@@ -317,7 +317,7 @@ int pm_runtime_suspend(struct device *dev)
+ 	int retval;
+ 
+ 	spin_lock_irq(&dev->power.lock);
+-	retval = __pm_runtime_suspend(dev, false);
++	retval = __pm_runtime_suspend(dev, 0);
+ 	spin_unlock_irq(&dev->power.lock);
+ 
+ 	return retval;
+@@ -327,24 +327,25 @@ EXPORT_SYMBOL_GPL(pm_runtime_suspend);
+ /**
+  * __pm_runtime_resume - Carry out run-time resume of given device.
+  * @dev: Device to resume.
+- * @from_wq: If set, the function has been called via pm_wq.
++ * @rpmflags: Flag bits.
+  *
+  * Check if the device can be woken up and run the ->runtime_resume() callback
+- * provided by its bus type.  If another resume has been started earlier, wait
+- * for it to finish.  If there's a suspend running in parallel with this
+- * function, wait for it to finish and resume the device.  Cancel any scheduled
+- * or pending requests.
++ * provided by its bus type.  If another resume has been started earlier,
++ * either return imediately or wait for it to finish, depending on the
++ * RPM_NOWAIT flag.  If there's a suspend running in parallel with this
++ * function, either tell the other process to resume after suspending
++ * (deferred_resume) or wait for it to finish, depending on the RPM_NOWAIT
++ * flag.  Cancel any scheduled or pending requests.
+  *
+  * This function must be called under dev->power.lock with interrupts disabled.
+  */
+-int __pm_runtime_resume(struct device *dev, bool from_wq)
++static int __pm_runtime_resume(struct device *dev, int rpmflags)
+ 	__releases(&dev->power.lock) __acquires(&dev->power.lock)
+ {
+ 	struct device *parent = NULL;
+ 	int retval = 0;
+ 
+-	dev_dbg(dev, "__pm_runtime_resume()%s!\n",
+-		from_wq ? " from workqueue" : "");
++	dev_dbg(dev, "%s flags 0x%x\n", __func__, rpmflags);
+ 
+  repeat:
+ 	if (dev->power.runtime_error) {
+@@ -365,7 +366,7 @@ int __pm_runtime_resume(struct device *dev, bool from_wq)
+ 	    || dev->power.runtime_status == RPM_SUSPENDING) {
+ 		DEFINE_WAIT(wait);
+ 
+-		if (from_wq) {
++		if (rpmflags & RPM_NOWAIT) {
+ 			if (dev->power.runtime_status == RPM_SUSPENDING)
+ 				dev->power.deferred_resume = true;
+ 			retval = -EINPROGRESS;
+@@ -407,7 +408,7 @@ int __pm_runtime_resume(struct device *dev, bool from_wq)
+ 		 */
+ 		if (!parent->power.disable_depth
+ 		    && !parent->power.ignore_children) {
+-			__pm_runtime_resume(parent, false);
++			__pm_runtime_resume(parent, 0);
+ 			if (parent->power.runtime_status != RPM_ACTIVE)
+ 				retval = -EBUSY;
+ 		}
+@@ -470,7 +471,7 @@ int __pm_runtime_resume(struct device *dev, bool from_wq)
+ 		spin_lock_irq(&dev->power.lock);
+ 	}
+ 
+-	dev_dbg(dev, "__pm_runtime_resume() returns %d!\n", retval);
++	dev_dbg(dev, "%s returns %d\n", __func__, retval);
+ 
+ 	return retval;
+ }
+@@ -484,7 +485,7 @@ int pm_runtime_resume(struct device *dev)
+ 	int retval;
+ 
+ 	spin_lock_irq(&dev->power.lock);
+-	retval = __pm_runtime_resume(dev, false);
++	retval = __pm_runtime_resume(dev, 0);
+ 	spin_unlock_irq(&dev->power.lock);
+ 
+ 	return retval;
+@@ -519,10 +520,10 @@ static void pm_runtime_work(struct work_struct *work)
+ 		__pm_runtime_idle(dev);
+ 		break;
+ 	case RPM_REQ_SUSPEND:
+-		__pm_runtime_suspend(dev, true);
++		__pm_runtime_suspend(dev, RPM_NOWAIT);
+ 		break;
+ 	case RPM_REQ_RESUME:
+-		__pm_runtime_resume(dev, true);
++		__pm_runtime_resume(dev, RPM_NOWAIT);
+ 		break;
+ 	}
+ 
+@@ -782,17 +783,18 @@ EXPORT_SYMBOL_GPL(pm_request_resume);
+ /**
+  * __pm_runtime_get - Reference count a device and wake it up, if necessary.
+  * @dev: Device to handle.
+- * @sync: If set and the device is suspended, resume it synchronously.
++ * @rpmflags: Flag bits.
+  *
+  * Increment the usage count of the device and resume it or submit a resume
+- * request for it, depending on the value of @sync.
++ * request for it, depending on the RPM_ASYNC flag bit.
+  */
+-int __pm_runtime_get(struct device *dev, bool sync)
++int __pm_runtime_get(struct device *dev, int rpmflags)
+ {
+ 	int retval;
+ 
+ 	atomic_inc(&dev->power.usage_count);
+-	retval = sync ? pm_runtime_resume(dev) : pm_request_resume(dev);
++	retval = (rpmflags & RPM_ASYNC) ?
++	    pm_request_resume(dev) : pm_runtime_resume(dev);
+ 
+ 	return retval;
+ }
+@@ -801,18 +803,19 @@ EXPORT_SYMBOL_GPL(__pm_runtime_get);
+ /**
+  * __pm_runtime_put - Decrement the device's usage counter and notify its bus.
+  * @dev: Device to handle.
+- * @sync: If the device's bus type is to be notified, do that synchronously.
++ * @rpmflags: Flag bits.
+  *
+  * Decrement the usage count of the device and if it reaches zero, carry out a
+  * synchronous idle notification or submit an idle notification request for it,
+- * depending on the value of @sync.
++ * depending on the RPM_ASYNC flag bit.
+  */
+-int __pm_runtime_put(struct device *dev, bool sync)
++int __pm_runtime_put(struct device *dev, int rpmflags)
+ {
+ 	int retval = 0;
+ 
+ 	if (atomic_dec_and_test(&dev->power.usage_count))
+-		retval = sync ? pm_runtime_idle(dev) : pm_request_idle(dev);
++		retval = (rpmflags & RPM_ASYNC) ?
++		    pm_request_idle(dev) : pm_runtime_idle(dev);
+ 
+ 	return retval;
+ }
+@@ -967,7 +970,7 @@ int pm_runtime_barrier(struct device *dev)
+ 
+ 	if (dev->power.request_pending
+ 	    && dev->power.request == RPM_REQ_RESUME) {
+-		__pm_runtime_resume(dev, false);
++		__pm_runtime_resume(dev, 0);
+ 		retval = 1;
+ 	}
+ 
+@@ -1016,7 +1019,7 @@ void __pm_runtime_disable(struct device *dev, bool check_resume)
+ 		 */
+ 		pm_runtime_get_noresume(dev);
+ 
+-		__pm_runtime_resume(dev, false);
++		__pm_runtime_resume(dev, 0);
+ 
+ 		pm_runtime_put_noidle(dev);
+ 	}
+@@ -1064,7 +1067,7 @@ void pm_runtime_forbid(struct device *dev)
+ 
+ 	dev->power.runtime_auto = false;
+ 	atomic_inc(&dev->power.usage_count);
+-	__pm_runtime_resume(dev, false);
++	__pm_runtime_resume(dev, 0);
+ 
+  out:
+ 	spin_unlock_irq(&dev->power.lock);
+diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h
+index 6e81888c6222..c030cac59aac 100644
+--- a/include/linux/pm_runtime.h
++++ b/include/linux/pm_runtime.h
+@@ -12,6 +12,11 @@
+ #include 
+ #include 
+ 
++/* Runtime PM flag argument bits */
++#define RPM_ASYNC		0x01	/* Request is asynchronous */
++#define RPM_NOWAIT		0x02	/* Don't wait for concurrent
++					    state change */
++
+ #ifdef CONFIG_PM_RUNTIME
+ 
+ extern struct workqueue_struct *pm_wq;
+@@ -22,8 +27,8 @@ extern int pm_runtime_resume(struct device *dev);
+ extern int pm_request_idle(struct device *dev);
+ extern int pm_schedule_suspend(struct device *dev, unsigned int delay);
+ extern int pm_request_resume(struct device *dev);
+-extern int __pm_runtime_get(struct device *dev, bool sync);
+-extern int __pm_runtime_put(struct device *dev, bool sync);
++extern int __pm_runtime_get(struct device *dev, int rpmflags);
++extern int __pm_runtime_put(struct device *dev, int rpmflags);
+ extern int __pm_runtime_set_status(struct device *dev, unsigned int status);
+ extern int pm_runtime_barrier(struct device *dev);
+ extern void pm_runtime_enable(struct device *dev);
+@@ -81,8 +86,10 @@ static inline int pm_schedule_suspend(struct device *dev, unsigned int delay)
+ 	return -ENOSYS;
+ }
+ static inline int pm_request_resume(struct device *dev) { return 0; }
+-static inline int __pm_runtime_get(struct device *dev, bool sync) { return 1; }
+-static inline int __pm_runtime_put(struct device *dev, bool sync) { return 0; }
++static inline int __pm_runtime_get(struct device *dev, int rpmflags)
++					{ return 1; }
++static inline int __pm_runtime_put(struct device *dev, int rpmflags)
++					{ return 0; }
+ static inline int __pm_runtime_set_status(struct device *dev,
+ 					    unsigned int status) { return 0; }
+ static inline int pm_runtime_barrier(struct device *dev) { return 0; }
+@@ -107,22 +114,22 @@ static inline int pm_generic_runtime_resume(struct device *dev) { return 0; }
+ 
+ static inline int pm_runtime_get(struct device *dev)
+ {
+-	return __pm_runtime_get(dev, false);
++	return __pm_runtime_get(dev, RPM_ASYNC);
+ }
+ 
+ static inline int pm_runtime_get_sync(struct device *dev)
+ {
+-	return __pm_runtime_get(dev, true);
++	return __pm_runtime_get(dev, 0);
+ }
+ 
+ static inline int pm_runtime_put(struct device *dev)
+ {
+-	return __pm_runtime_put(dev, false);
++	return __pm_runtime_put(dev, RPM_ASYNC);
+ }
+ 
+ static inline int pm_runtime_put_sync(struct device *dev)
+ {
+-	return __pm_runtime_put(dev, true);
++	return __pm_runtime_put(dev, 0);
+ }
+ 
+ static inline int pm_runtime_set_active(struct device *dev)

commit 4769373ca2c8d0b999749a070c48fd8648888831
+Author: Alan Stern 
+Date:   Sat Sep 25 23:34:46 2010 +0200
+
+    PM / Runtime: Move code in drivers/base/power/runtime.c
+    
+    This patch (as1421) moves the PM runtime accounting subroutines up to
+    the beginning of runtime.c, taking them out of the middle of the
+    functions that do the actual work.  No operational changes.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
+index e9520ad2d716..ec08f1ae63f1 100644
+--- a/drivers/base/power/runtime.c
++++ b/drivers/base/power/runtime.c
+@@ -14,6 +14,44 @@ static int __pm_runtime_resume(struct device *dev, bool from_wq);
+ static int __pm_request_idle(struct device *dev);
+ static int __pm_request_resume(struct device *dev);
+ 
++/**
++ * update_pm_runtime_accounting - Update the time accounting of power states
++ * @dev: Device to update the accounting for
++ *
++ * In order to be able to have time accounting of the various power states
++ * (as used by programs such as PowerTOP to show the effectiveness of runtime
++ * PM), we need to track the time spent in each state.
++ * update_pm_runtime_accounting must be called each time before the
++ * runtime_status field is updated, to account the time in the old state
++ * correctly.
++ */
++void update_pm_runtime_accounting(struct device *dev)
++{
++	unsigned long now = jiffies;
++	int delta;
++
++	delta = now - dev->power.accounting_timestamp;
++
++	if (delta < 0)
++		delta = 0;
++
++	dev->power.accounting_timestamp = now;
++
++	if (dev->power.disable_depth > 0)
++		return;
++
++	if (dev->power.runtime_status == RPM_SUSPENDED)
++		dev->power.suspended_jiffies += delta;
++	else
++		dev->power.active_jiffies += delta;
++}
++
++static void __update_runtime_status(struct device *dev, enum rpm_status status)
++{
++	update_pm_runtime_accounting(dev);
++	dev->power.runtime_status = status;
++}
++
+ /**
+  * pm_runtime_deactivate_timer - Deactivate given device's suspend timer.
+  * @dev: Device to handle.
+@@ -123,45 +161,6 @@ int pm_runtime_idle(struct device *dev)
+ }
+ EXPORT_SYMBOL_GPL(pm_runtime_idle);
+ 
+-
+-/**
+- * update_pm_runtime_accounting - Update the time accounting of power states
+- * @dev: Device to update the accounting for
+- *
+- * In order to be able to have time accounting of the various power states
+- * (as used by programs such as PowerTOP to show the effectiveness of runtime
+- * PM), we need to track the time spent in each state.
+- * update_pm_runtime_accounting must be called each time before the
+- * runtime_status field is updated, to account the time in the old state
+- * correctly.
+- */
+-void update_pm_runtime_accounting(struct device *dev)
+-{
+-	unsigned long now = jiffies;
+-	int delta;
+-
+-	delta = now - dev->power.accounting_timestamp;
+-
+-	if (delta < 0)
+-		delta = 0;
+-
+-	dev->power.accounting_timestamp = now;
+-
+-	if (dev->power.disable_depth > 0)
+-		return;
+-
+-	if (dev->power.runtime_status == RPM_SUSPENDED)
+-		dev->power.suspended_jiffies += delta;
+-	else
+-		dev->power.active_jiffies += delta;
+-}
+-
+-static void __update_runtime_status(struct device *dev, enum rpm_status status)
+-{
+-	update_pm_runtime_accounting(dev);
+-	dev->power.runtime_status = status;
+-}
+-
+ /**
+  * __pm_runtime_suspend - Carry out run-time suspend of given device.
+  * @dev: Device to suspend.

commit 69d44ffbd772bede8c2a6d182e6e14f94826520b
+Author: Alan Stern 
+Date:   Sat Sep 25 23:34:22 2010 +0200
+
+    sysfs: Add sysfs_merge_group() and sysfs_unmerge_group()
+    
+    This patch (as1420) adds sysfs_merge_group() and sysfs_unmerge_group()
+    functions, allowing drivers easily to add and remove sets of
+    attributes to a pre-existing attribute group directory.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Greg Kroah-Hartman 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
+index 23c1e598792a..442f34ff1af8 100644
+--- a/fs/sysfs/group.c
++++ b/fs/sysfs/group.c
+@@ -148,6 +148,65 @@ void sysfs_remove_group(struct kobject * kobj,
+ 	sysfs_put(sd);
+ }
+ 
++/**
++ * sysfs_merge_group - merge files into a pre-existing attribute group.
++ * @kobj:	The kobject containing the group.
++ * @grp:	The files to create and the attribute group they belong to.
++ *
++ * This function returns an error if the group doesn't exist or any of the
++ * files already exist in that group, in which case none of the new files
++ * are created.
++ */
++int sysfs_merge_group(struct kobject *kobj,
++		       const struct attribute_group *grp)
++{
++	struct sysfs_dirent *dir_sd;
++	int error = 0;
++	struct attribute *const *attr;
++	int i;
++
++	if (grp)
++		dir_sd = sysfs_get_dirent(kobj->sd, NULL, grp->name);
++	else
++		dir_sd = sysfs_get(kobj->sd);
++	if (!dir_sd)
++		return -ENOENT;
++
++	for ((i = 0, attr = grp->attrs); *attr && !error; (++i, ++attr))
++		error = sysfs_add_file(dir_sd, *attr, SYSFS_KOBJ_ATTR);
++	if (error) {
++		while (--i >= 0)
++			sysfs_hash_and_remove(dir_sd, NULL, (*--attr)->name);
++	}
++	sysfs_put(dir_sd);
++
++	return error;
++}
++EXPORT_SYMBOL_GPL(sysfs_merge_group);
++
++/**
++ * sysfs_unmerge_group - remove files from a pre-existing attribute group.
++ * @kobj:	The kobject containing the group.
++ * @grp:	The files to remove and the attribute group they belong to.
++ */
++void sysfs_unmerge_group(struct kobject *kobj,
++		       const struct attribute_group *grp)
++{
++	struct sysfs_dirent *dir_sd;
++	struct attribute *const *attr;
++
++	if (grp)
++		dir_sd = sysfs_get_dirent(kobj->sd, NULL, grp->name);
++	else
++		dir_sd = sysfs_get(kobj->sd);
++	if (dir_sd) {
++		for (attr = grp->attrs; *attr; ++attr)
++			sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name);
++		sysfs_put(dir_sd);
++	}
++}
++EXPORT_SYMBOL_GPL(sysfs_unmerge_group);
++
+ 
+ EXPORT_SYMBOL_GPL(sysfs_create_group);
+ EXPORT_SYMBOL_GPL(sysfs_update_group);
+diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
+index 96eb576d82fd..30b881555fa5 100644
+--- a/include/linux/sysfs.h
++++ b/include/linux/sysfs.h
+@@ -164,6 +164,10 @@ int sysfs_add_file_to_group(struct kobject *kobj,
+ 			const struct attribute *attr, const char *group);
+ void sysfs_remove_file_from_group(struct kobject *kobj,
+ 			const struct attribute *attr, const char *group);
++int sysfs_merge_group(struct kobject *kobj,
++		       const struct attribute_group *grp);
++void sysfs_unmerge_group(struct kobject *kobj,
++		       const struct attribute_group *grp);
+ 
+ void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr);
+ void sysfs_notify_dirent(struct sysfs_dirent *sd);
+@@ -302,6 +306,17 @@ static inline void sysfs_remove_file_from_group(struct kobject *kobj,
+ {
+ }
+ 
++static inline int sysfs_merge_group(struct kobject *kobj,
++		       const struct attribute_group *grp)
++{
++	return 0;
++}
++
++static inline void sysfs_unmerge_group(struct kobject *kobj,
++		       const struct attribute_group *grp)
++{
++}
++
+ static inline void sysfs_notify(struct kobject *kobj, const char *dir,
+ 				const char *attr)
+ {

commit 2dab3948f5eeffa320ad92207ef77c997518867b
+Author: Alan Stern 
+Date:   Fri Sep 24 11:41:46 2010 -0400
+
+    USB: update Kconfig help text for CONFIG_USB_SUSPEND
+    
+    This patch (as1429) updates the Kconfig help text for
+    CONFIG_USB_SUSPEND.  The power/level file is now deprecated; we should
+    tell people to use power/control instead.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
+index 7e594449600e..9eed5b52d9de 100644
+--- a/drivers/usb/core/Kconfig
++++ b/drivers/usb/core/Kconfig
+@@ -91,12 +91,12 @@ config USB_DYNAMIC_MINORS
+ 	  If you are unsure about this, say N here.
+ 
+ config USB_SUSPEND
+-	bool "USB runtime power management (suspend/resume and wakeup)"
++	bool "USB runtime power management (autosuspend) and wakeup"
+ 	depends on USB && PM_RUNTIME
+ 	help
+ 	  If you say Y here, you can use driver calls or the sysfs
+-	  "power/level" file to suspend or resume individual USB
+-	  peripherals and to enable or disable autosuspend (see
++	  "power/control" file to enable or disable autosuspend for
++	  individual USB peripherals (see
+ 	  Documentation/usb/power-management.txt for more details).
+ 
+ 	  Also, USB "remote wakeup" signaling is supported, whereby some

commit 0026e00523a85b90a92a93ddf6660939ecef3e54
+Author: Alan Stern 
+Date:   Tue Sep 21 15:01:53 2010 -0400
+
+    USB: fix bug in initialization of interface minor numbers
+    
+    Recent changes in the usbhid layer exposed a bug in usbcore.  If
+    CONFIG_USB_DYNAMIC_MINORS is enabled then an interface may be assigned
+    a minor number of 0.  However interfaces that aren't registered as USB
+    class devices also have their minor number set to 0, during
+    initialization.  As a result usb_find_interface() may return the
+    wrong interface, leading to a crash.
+    
+    This patch (as1418) fixes the problem by initializing every
+    interface's minor number to -1.  It also cleans up the
+    usb_register_dev() function, which besides being somewhat awkwardly
+    written, does not unwind completely on all its error paths.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Philip J. Turmel 
+    Tested-by: Gabriel Craciunescu 
+    Tested-by: Alex Riesen 
+    Tested-by: Matthias Bayer 
+    CC: Jiri Kosina 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
+index f06f5dbc8cdc..1e6ccef2cf0c 100644
+--- a/drivers/usb/core/file.c
++++ b/drivers/usb/core/file.c
+@@ -159,9 +159,9 @@ void usb_major_cleanup(void)
+ int usb_register_dev(struct usb_interface *intf,
+ 		     struct usb_class_driver *class_driver)
+ {
+-	int retval = -EINVAL;
++	int retval;
+ 	int minor_base = class_driver->minor_base;
+-	int minor = 0;
++	int minor;
+ 	char name[20];
+ 	char *temp;
+ 
+@@ -173,12 +173,17 @@ int usb_register_dev(struct usb_interface *intf,
+ 	 */
+ 	minor_base = 0;
+ #endif
+-	intf->minor = -1;
+-
+-	dbg ("looking for a minor, starting at %d", minor_base);
+ 
+ 	if (class_driver->fops == NULL)
+-		goto exit;
++		return -EINVAL;
++	if (intf->minor >= 0)
++		return -EADDRINUSE;
++
++	retval = init_usb_class();
++	if (retval)
++		return retval;
++
++	dev_dbg(&intf->dev, "looking for a minor, starting at %d", minor_base);
+ 
+ 	down_write(&minor_rwsem);
+ 	for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) {
+@@ -186,20 +191,12 @@ int usb_register_dev(struct usb_interface *intf,
+ 			continue;
+ 
+ 		usb_minors[minor] = class_driver->fops;
+-
+-		retval = 0;
++		intf->minor = minor;
+ 		break;
+ 	}
+ 	up_write(&minor_rwsem);
+-
+-	if (retval)
+-		goto exit;
+-
+-	retval = init_usb_class();
+-	if (retval)
+-		goto exit;
+-
+-	intf->minor = minor;
++	if (intf->minor < 0)
++		return -EXFULL;
+ 
+ 	/* create a usb class device for this usb interface */
+ 	snprintf(name, sizeof(name), class_driver->name, minor - minor_base);
+@@ -213,11 +210,11 @@ int usb_register_dev(struct usb_interface *intf,
+ 				      "%s", temp);
+ 	if (IS_ERR(intf->usb_dev)) {
+ 		down_write(&minor_rwsem);
+-		usb_minors[intf->minor] = NULL;
++		usb_minors[minor] = NULL;
++		intf->minor = -1;
+ 		up_write(&minor_rwsem);
+ 		retval = PTR_ERR(intf->usb_dev);
+ 	}
+-exit:
+ 	return retval;
+ }
+ EXPORT_SYMBOL_GPL(usb_register_dev);
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 844683e50383..9f0ce7de0e36 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1802,6 +1802,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 		intf->dev.groups = usb_interface_groups;
+ 		intf->dev.dma_mask = dev->dev.dma_mask;
+ 		INIT_WORK(&intf->reset_ws, __usb_queue_reset_device);
++		intf->minor = -1;
+ 		device_initialize(&intf->dev);
+ 		dev_set_name(&intf->dev, "%d-%s:%d.%d",
+ 			dev->bus->busnum, dev->devpath,

commit 50bb6d8492ff0c3f204b263aff90d4a7ebf4dd90
+Author: Alan Stern 
+Date:   Thu Sep 23 10:40:21 2010 -0400
+
+    HID: usbhid: remove unused hiddev_driver
+    
+    Now that hiddev_driver isn't being used for anything, there's no
+    reason to keep it around.  This patch (as1419) gets rid of it
+    entirely.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index c90fbbdbffa2..7a778ac4c5cb 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -1470,9 +1470,6 @@ static int __init hid_init(void)
+ 	retval = usbhid_quirks_init(quirks_param);
+ 	if (retval)
+ 		goto usbhid_quirks_init_fail;
+-	retval = hiddev_init();
+-	if (retval)
+-		goto hiddev_init_fail;
+ 	retval = usb_register(&hid_driver);
+ 	if (retval)
+ 		goto usb_register_fail;
+@@ -1480,8 +1477,6 @@ static int __init hid_init(void)
+ 
+ 	return 0;
+ usb_register_fail:
+-	hiddev_exit();
+-hiddev_init_fail:
+ 	usbhid_quirks_exit();
+ usbhid_quirks_init_fail:
+ 	hid_unregister_driver(&hid_usb_driver);
+@@ -1494,7 +1489,6 @@ static int __init hid_init(void)
+ static void __exit hid_exit(void)
+ {
+ 	usb_deregister(&hid_driver);
+-	hiddev_exit();
+ 	usbhid_quirks_exit();
+ 	hid_unregister_driver(&hid_usb_driver);
+ 	destroy_workqueue(resumption_waker);
+diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
+index 681e620eb95b..19ed90c8f503 100644
+--- a/drivers/hid/usbhid/hiddev.c
++++ b/drivers/hid/usbhid/hiddev.c
+@@ -67,8 +67,6 @@ struct hiddev_list {
+ 	struct mutex thread_lock;
+ };
+ 
+-static struct usb_driver hiddev_driver;
+-
+ /*
+  * Find a report, given the report's type and ID.  The ID can be specified
+  * indirectly by REPORT_ID_FIRST (which returns the first report of the given
+@@ -925,41 +923,3 @@ void hiddev_disconnect(struct hid_device *hid)
+ 		kfree(hiddev);
+ 	}
+ }
+-
+-/* Currently this driver is a USB driver.  It's not a conventional one in
+- * the sense that it doesn't probe at the USB level.  Instead it waits to
+- * be connected by HID through the hiddev_connect / hiddev_disconnect
+- * routines.  The reason to register as a USB device is to gain part of the
+- * minor number space from the USB major.
+- *
+- * In theory, should the HID code be generalized to more than one physical
+- * medium (say, IEEE 1384), this driver will probably need to register its
+- * own major number, and in doing so, no longer need to register with USB.
+- * At that point the probe routine and hiddev_driver struct below will no
+- * longer be useful.
+- */
+-
+-
+-/* We never attach in this manner, and rely on HID to connect us.  This
+- * is why there is no disconnect routine defined in the usb_driver either.
+- */
+-static int hiddev_usbd_probe(struct usb_interface *intf,
+-			     const struct usb_device_id *hiddev_info)
+-{
+-	return -ENODEV;
+-}
+-
+-static /* const */ struct usb_driver hiddev_driver = {
+-	.name =		"hiddev",
+-	.probe =	hiddev_usbd_probe,
+-};
+-
+-int __init hiddev_init(void)
+-{
+-	return usb_register(&hiddev_driver);
+-}
+-
+-void hiddev_exit(void)
+-{
+-	usb_deregister(&hiddev_driver);
+-}
+diff --git a/include/linux/hiddev.h b/include/linux/hiddev.h
+index bb6f58baf319..a3f481a3063b 100644
+--- a/include/linux/hiddev.h
++++ b/include/linux/hiddev.h
+@@ -226,8 +226,6 @@ void hiddev_disconnect(struct hid_device *);
+ void hiddev_hid_event(struct hid_device *hid, struct hid_field *field,
+ 		      struct hid_usage *usage, __s32 value);
+ void hiddev_report_event(struct hid_device *hid, struct hid_report *report);
+-int __init hiddev_init(void);
+-void hiddev_exit(void);
+ #else
+ static inline int hiddev_connect(struct hid_device *hid,
+ 		unsigned int force)
+@@ -236,8 +234,6 @@ static inline void hiddev_disconnect(struct hid_device *hid) { }
+ static inline void hiddev_hid_event(struct hid_device *hid, struct hid_field *field,
+ 		      struct hid_usage *usage, __s32 value) { }
+ static inline void hiddev_report_event(struct hid_device *hid, struct hid_report *report) { }
+-static inline int hiddev_init(void) { return 0; }
+-static inline void hiddev_exit(void) { }
+ #endif
+ 
+ #endif

commit 7e443312403ad1ff40ef3177590e96d1fe747c79
+Author: Alan Stern 
+Date:   Tue Sep 7 11:27:52 2010 -0400
+
+    [SCSI] sd: fix medium-removal bug
+    
+    Commit 409f3499a2cfcd1e9c2857c53af7fcce069f027f (scsi/sd: remove big
+    kernel lock) introduced a bug in the sd_release routine.  Medium
+    removal should be allowed when the number of open file references
+    drops to 0, not when it becomes non-zero.
+    
+    This patch (as1414) adjusts the test to fix the bug.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+index cd71f46a3d47..ffa0689ee840 100644
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -870,7 +870,7 @@ static int sd_release(struct gendisk *disk, fmode_t mode)
+ 
+ 	SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_release\n"));
+ 
+-	if (atomic_dec_return(&sdkp->openers) && sdev->removable) {
++	if (atomic_dec_return(&sdkp->openers) == 0 && sdev->removable) {
+ 		if (scsi_block_when_processing_errors(sdev))
+ 			scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW);
+ 	}

commit b409214c683ed06c26e2cdad0be546ad11463354
+Author: Alan Stern 
+Date:   Thu Aug 5 13:12:14 2010 -0400
+
+    USB: remove fake "address-of" expressions
+    
+    Fake "address-of" expressions that evaluate to NULL generally confuse
+    readers and can provoke compiler warnings.  This patch (as1412)
+    removes three such fake expressions, using "#ifdef"s in their place.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 880f65baf581..d7a4401ef019 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1791,15 +1791,13 @@ static const struct dev_pm_ops usb_bus_pm_ops = {
+ 	.runtime_idle =		usb_runtime_idle,
+ };
+ 
+-#else
+-
+-#define usb_bus_pm_ops	(*(const struct dev_pm_ops *) NULL)
+-
+ #endif /* CONFIG_USB_SUSPEND */
+ 
+ struct bus_type usb_bus_type = {
+ 	.name =		"usb",
+ 	.match =	usb_device_match,
+ 	.uevent =	usb_uevent,
++#ifdef CONFIG_USB_SUSPEND
+ 	.pm =		&usb_bus_pm_ops,
++#endif
+ };
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 5ae14f6c1e7a..fdd4130fbb7d 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -317,10 +317,6 @@ static const struct dev_pm_ops usb_device_pm_ops = {
+ 	.restore =	usb_dev_restore,
+ };
+ 
+-#else
+-
+-#define usb_device_pm_ops	(*(struct dev_pm_ops *) NULL)
+-
+ #endif	/* CONFIG_PM */
+ 
+ 
+@@ -338,7 +334,9 @@ struct device_type usb_device_type = {
+ 	.release =	usb_release_dev,
+ 	.uevent =	usb_dev_uevent,
+ 	.devnode = 	usb_devnode,
++#ifdef CONFIG_PM
+ 	.pm =		&usb_device_pm_ops,
++#endif
+ };
+ 
+ 
+diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
+index c168999722d1..6e7fb5f38db6 100644
+--- a/drivers/usb/host/uhci-debug.c
++++ b/drivers/usb/host/uhci-debug.c
+@@ -17,7 +17,6 @@
+ 
+ #include "uhci-hcd.h"
+ 
+-#define uhci_debug_operations (* (const struct file_operations *) NULL)
+ static struct dentry *uhci_debugfs_root;
+ 
+ #ifdef DEBUG
+@@ -558,7 +557,6 @@ static int uhci_debug_release(struct inode *inode, struct file *file)
+ 	return 0;
+ }
+ 
+-#undef uhci_debug_operations
+ static const struct file_operations uhci_debug_operations = {
+ 	.owner =	THIS_MODULE,
+ 	.open =		uhci_debug_open,
+@@ -566,6 +564,7 @@ static const struct file_operations uhci_debug_operations = {
+ 	.read =		uhci_debug_read,
+ 	.release =	uhci_debug_release,
+ };
++#define UHCI_DEBUG_OPS
+ 
+ #endif	/* CONFIG_DEBUG_FS */
+ 
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index b04506036b64..f52d04db28f4 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -597,7 +597,7 @@ static int uhci_start(struct usb_hcd *hcd)
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 	int retval = -EBUSY;
+ 	int i;
+-	struct dentry *dentry;
++	struct dentry __maybe_unused *dentry;
+ 
+ 	hcd->uses_new_polling = 1;
+ 
+@@ -607,18 +607,16 @@ static int uhci_start(struct usb_hcd *hcd)
+ 	INIT_LIST_HEAD(&uhci->idle_qh_list);
+ 	init_waitqueue_head(&uhci->waitqh);
+ 
+-	if (DEBUG_CONFIGURED) {
+-		dentry = debugfs_create_file(hcd->self.bus_name,
+-				S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root,
+-				uhci, &uhci_debug_operations);
+-		if (!dentry) {
+-			dev_err(uhci_dev(uhci), "couldn't create uhci "
+-					"debugfs entry\n");
+-			retval = -ENOMEM;
+-			goto err_create_debug_entry;
+-		}
+-		uhci->dentry = dentry;
++#ifdef UHCI_DEBUG_OPS
++	dentry = debugfs_create_file(hcd->self.bus_name,
++			S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root,
++			uhci, &uhci_debug_operations);
++	if (!dentry) {
++		dev_err(uhci_dev(uhci), "couldn't create uhci debugfs entry\n");
++		return -ENOMEM;
+ 	}
++	uhci->dentry = dentry;
++#endif
+ 
+ 	uhci->frame = dma_alloc_coherent(uhci_dev(uhci),
+ 			UHCI_NUMFRAMES * sizeof(*uhci->frame),
+@@ -732,7 +730,6 @@ static int uhci_start(struct usb_hcd *hcd)
+ err_alloc_frame:
+ 	debugfs_remove(uhci->dentry);
+ 
+-err_create_debug_entry:
+ 	return retval;
+ }
+ 

commit f283925fe9ef4ee75dc43e4c2bfbbd6b8a70bd0a
+Author: Alan Stern 
+Date:   Wed Jul 28 17:12:39 2010 -0400
+
+    USB: usb-storage: implement autosuspend
+    
+    This patch (as1400) adds runtime-PM support to usb-storage.  It
+    utilizes the SCSI layer's runtime-PM implementation, so its scope is
+    limited.  Currently the only effect is that disk-like devices (such as
+    card readers or flash drives) will be autosuspended if they aren't
+    mounted and their device files aren't open.  This would apply, for
+    example, to card readers that don't contain a memory card.
+    
+    Unfortunately this won't interact very well with the removable-media
+    polling normally carried out by hal or DeviceKit.  Maybe those
+    programs can be changed to use a longer polling interval, or maybe the
+    default autosuspend time for usb-storage should be set to something
+    below 1 second.
+    
+    Signed-off-by: Alan Stern 
+    Cc: James Bottomley 
+    Cc: Matthew Dharm 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index a7d0bf9d92a7..90bb0175a152 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -336,6 +336,7 @@ static int usb_stor_control_thread(void * __us)
+ 		else {
+ 			US_DEBUG(usb_stor_show_command(us->srb));
+ 			us->proto_handler(us->srb, us);
++			usb_mark_last_busy(us->pusb_dev);
+ 		}
+ 
+ 		/* lock access to the state */
+@@ -845,6 +846,7 @@ static int usb_stor_scan_thread(void * __us)
+ 		/* Should we unbind if no devices were detected? */
+ 	}
+ 
++	usb_autopm_put_interface(us->pusb_intf);
+ 	complete_and_exit(&us->scanning_done, 0);
+ }
+ 
+@@ -968,6 +970,7 @@ int usb_stor_probe2(struct us_data *us)
+ 		goto BadDevice;
+ 	}
+ 
++	usb_autopm_get_interface_no_resume(us->pusb_intf);
+ 	wake_up_process(th);
+ 
+ 	return 0;
+@@ -1040,6 +1043,7 @@ static struct usb_driver usb_storage_driver = {
+ 	.pre_reset =	usb_stor_pre_reset,
+ 	.post_reset =	usb_stor_post_reset,
+ 	.id_table =	usb_storage_usb_ids,
++	.supports_autosuspend = 1,
+ 	.soft_unbind =	1,
+ };
+ 

commit c4e0b508bcdd1af6b1b3c317042336936173591f
+Author: Alan Stern 
+Date:   Tue Jul 27 11:28:42 2010 -0400
+
+    USB: accept RNDIS configs if there's no alternative
+    
+    This patch (as1410) makes a slight change to the strategy used for
+    choosing a default configuration.  Currently we skip configs whose
+    first interface is RNDIS, if the kernel wasn't built with the
+    corresponding driver.  This risks losing access to the other
+    interfaces in those configs.  In addition, if there is only one config
+    then we will end up not configuring the device at all.
+    
+    This changes the logic; now such configurations will be skipped only
+    if there is at least one other config.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Adam Kropelin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
+index 9a34ccb0a1c0..69ecd3c92311 100644
+--- a/drivers/usb/core/generic.c
++++ b/drivers/usb/core/generic.c
+@@ -105,8 +105,10 @@ int usb_choose_configuration(struct usb_device *udev)
+ 		/* When the first config's first interface is one of Microsoft's
+ 		 * pet nonstandard Ethernet-over-USB protocols, ignore it unless
+ 		 * this kernel has enabled the necessary host side driver.
++		 * But: Don't ignore it if it's the only config.
+ 		 */
+-		if (i == 0 && desc && (is_rndis(desc) || is_activesync(desc))) {
++		if (i == 0 && num_configs > 1 && desc &&
++				(is_rndis(desc) || is_activesync(desc))) {
+ #if !defined(CONFIG_USB_NET_RNDIS_HOST) && !defined(CONFIG_USB_NET_RNDIS_HOST_MODULE)
+ 			continue;
+ #else

commit 88d8aa462b8a2128a75b96a0134b22f724ca45d1
+Author: Alan Stern 
+Date:   Wed Jul 14 11:03:57 2010 -0400
+
+    USB: EHCI: remove dead code in the periodic scheduler
+    
+    This patch (as1409) removes some dead code from the ehci-hcd
+    scheduler.  Thanks to the previous patch in this series, stream->depth
+    is no longer used.  And stream->start and stream->rescheduled
+    apparently have not been used for quite a while, except in some
+    statistics-reporting code that never gets invoked.
+    
+    Signed-off-by: Alan Stern 
+    CC: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 3381319a2b3f..a92526d6e5ae 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1074,15 +1074,6 @@ iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream)
+ 		if (stream->ep)
+ 			stream->ep->hcpriv = NULL;
+ 
+-		if (stream->rescheduled) {
+-			ehci_info (ehci, "ep%d%s-iso rescheduled "
+-				"%lu times in %lu seconds\n",
+-				stream->bEndpointAddress, is_in ? "in" : "out",
+-				stream->rescheduled,
+-				((jiffies - stream->start)/HZ)
+-				);
+-		}
+-
+ 		kfree(stream);
+ 	}
+ }
+@@ -1617,7 +1608,6 @@ itd_link_urb (
+ 			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
+ 			urb->interval,
+ 			next_uframe >> 3, next_uframe & 0x7);
+-		stream->start = jiffies;
+ 	}
+ 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
+ 
+@@ -1643,7 +1633,6 @@ itd_link_urb (
+ 		itd_patch(ehci, itd, iso_sched, packet, uframe);
+ 
+ 		next_uframe += stream->interval;
+-		stream->depth += stream->interval;
+ 		next_uframe &= mod - 1;
+ 		packet++;
+ 
+@@ -1699,7 +1688,6 @@ itd_complete (
+ 
+ 		t = hc32_to_cpup(ehci, &itd->hw_transaction [uframe]);
+ 		itd->hw_transaction [uframe] = 0;
+-		stream->depth -= stream->interval;
+ 
+ 		/* report transfer status */
+ 		if (unlikely (t & ISO_ERRS)) {
+@@ -2029,7 +2017,6 @@ sitd_link_urb (
+ 			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
+ 			(next_uframe >> 3) & (ehci->periodic_size - 1),
+ 			stream->interval, hc32_to_cpu(ehci, stream->splits));
+-		stream->start = jiffies;
+ 	}
+ 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
+ 
+@@ -2054,7 +2041,6 @@ sitd_link_urb (
+ 				sitd);
+ 
+ 		next_uframe += stream->interval << 3;
+-		stream->depth += stream->interval << 3;
+ 	}
+ 	stream->next_uframe = next_uframe & (mod - 1);
+ 
+@@ -2114,7 +2100,6 @@ sitd_complete (
+ 		desc->actual_length = desc->length - SITD_LENGTH(t);
+ 		urb->actual_length += desc->actual_length;
+ 	}
+-	stream->depth -= stream->interval << 3;
+ 
+ 	/* handle completion now? */
+ 	if ((urb_index + 1) != urb->number_of_packets)
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 2c050efd1deb..e5b9ece8a077 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -404,15 +404,12 @@ struct ehci_iso_stream {
+ 	u32			refcount;
+ 	u8			bEndpointAddress;
+ 	u8			highspeed;
+-	u16			depth;		/* depth in uframes */
+ 	struct list_head	td_list;	/* queued itds/sitds */
+ 	struct list_head	free_list;	/* list of unused itds/sitds */
+ 	struct usb_device	*udev;
+ 	struct usb_host_endpoint *ep;
+ 
+ 	/* output of (re)scheduling */
+-	unsigned long		start;		/* jiffies */
+-	unsigned long		rescheduled;
+ 	int			next_uframe;
+ 	__hc32			splits;
+ 

commit 1fb2e0558781b07d2ecaabf94c81c17ac820d8f0
+Author: Alan Stern 
+Date:   Wed Jul 14 11:03:53 2010 -0400
+
+    USB: EHCI: reorganize isochronous scheduler routine
+    
+    This patch (as1408) rearranges the scheduling code in ehci-hcd, partly
+    to improve its structure, but mainly to change the way it works.
+    Whether or not a transfer exceeds the hardware schedule length will
+    now be determined by looking at the last frame the transfer would use,
+    instead of the first available frame following the end of the transfer.
+    
+    The benefit of this change is that it allows the driver to accept
+    valid URBs which would otherwise be rejected.  For example, suppose
+    the schedule length is 1024 frames, the endpoint period is 256 frames,
+    and a four-packet URB is submitted.  The four transfers would occupy
+    slots that are 0, 256, 512, and 768 frames past the current frame
+    (plus an extra slop factor).  These don't exceed the 1024-frame limit,
+    so the URB should be accepted.  But the current code notices that the
+    next available slot would be 1024 frames (plus slop) in the future,
+    which is beyond the limit, and so the URB is rejected unnecessarily.
+    
+    Signed-off-by: Alan Stern 
+    CC: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index dd37350170bb..3381319a2b3f 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1413,13 +1413,6 @@ iso_stream_schedule (
+ 		goto fail;
+ 	}
+ 
+-	if (stream->depth + span > mod) {
+-		ehci_dbg (ehci, "request %p would overflow (%d+%d>%d)\n",
+-			urb, stream->depth, span, mod);
+-		status = -EFBIG;
+-		goto fail;
+-	}
+-
+ 	now = ehci_readl(ehci, &ehci->regs->frame_index) & (mod - 1);
+ 
+ 	/* Typical case: reuse current schedule, stream is still active.
+@@ -1428,7 +1421,7 @@ iso_stream_schedule (
+ 	 * slot in the schedule, implicitly assuming URB_ISO_ASAP.
+ 	 */
+ 	if (likely (!list_empty (&stream->td_list))) {
+-		start = stream->next_uframe;
++		u32	excess;
+ 
+ 		/* For high speed devices, allow scheduling within the
+ 		 * isochronous scheduling threshold.  For full speed devices
+@@ -1440,21 +1433,23 @@ iso_stream_schedule (
+ 		else
+ 			next = now;
+ 
+-		/* Fell behind (by up to twice the slop amount)? */
+-		if (((start - next) & (mod - 1)) >=
+-				mod - 2 * SCHEDULE_SLOP)
+-			start += period * DIV_ROUND_UP(
+-					(next - start) & (mod - 1),
+-					period);
+-
+-		/* Tried to schedule too far into the future? */
+-		if (unlikely(((start - now) & (mod - 1)) + span
+-					>= mod - 2 * SCHEDULE_SLOP)) {
++		/* Fell behind (by up to twice the slop amount)?
++		 * We decide based on the time of the last currently-scheduled
++		 * slot, not the time of the next available slot.
++		 */
++		excess = (stream->next_uframe - period - next) & (mod - 1);
++		if (excess >= mod - 2 * SCHEDULE_SLOP)
++			start = next + excess - mod + period *
++					DIV_ROUND_UP(mod - excess, period);
++		else
++			start = next + excess + period;
++		if (start - now >= mod) {
++			ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n",
++					urb, start - now - period, period,
++					mod);
+ 			status = -EFBIG;
+ 			goto fail;
+ 		}
+-		stream->next_uframe = start;
+-		goto ready;
+ 	}
+ 
+ 	/* need to schedule; when's the next (u)frame we could start?
+@@ -1463,51 +1458,60 @@ iso_stream_schedule (
+ 	 * can also help high bandwidth if the dma and irq loads don't
+ 	 * jump until after the queue is primed.
+ 	 */
+-	start = SCHEDULE_SLOP + (now & ~0x07);
+-	start &= mod - 1;
+-	stream->next_uframe = start;
+-
+-	/* NOTE:  assumes URB_ISO_ASAP, to limit complexity/bugs */
+-
+-	/* find a uframe slot with enough bandwidth */
+-	for (; start < (stream->next_uframe + period); start++) {
+-		int		enough_space;
+-
+-		/* check schedule: enough space? */
+-		if (stream->highspeed)
+-			enough_space = itd_slot_ok (ehci, mod, start,
+-					stream->usecs, period);
+-		else {
+-			if ((start % 8) >= 6)
+-				continue;
+-			enough_space = sitd_slot_ok (ehci, mod, stream,
+-					start, sched, period);
++	else {
++		start = SCHEDULE_SLOP + (now & ~0x07);
++
++		/* NOTE:  assumes URB_ISO_ASAP, to limit complexity/bugs */
++
++		/* find a uframe slot with enough bandwidth */
++		next = start + period;
++		for (; start < next; start++) {
++
++			/* check schedule: enough space? */
++			if (stream->highspeed) {
++				if (itd_slot_ok(ehci, mod, start,
++						stream->usecs, period))
++					break;
++			} else {
++				if ((start % 8) >= 6)
++					continue;
++				if (sitd_slot_ok(ehci, mod, stream,
++						start, sched, period))
++					break;
++			}
+ 		}
+ 
+-		/* schedule it here if there's enough bandwidth */
+-		if (enough_space) {
+-			stream->next_uframe = start & (mod - 1);
+-			goto ready;
++		/* no room in the schedule */
++		if (start == next) {
++			ehci_dbg(ehci, "iso resched full %p (now %d max %d)\n",
++				urb, now, now + mod);
++			status = -ENOSPC;
++			goto fail;
+ 		}
+ 	}
+ 
+-	/* no room in the schedule */
+-	ehci_dbg (ehci, "iso %ssched full %p (now %d max %d)\n",
+-		list_empty (&stream->td_list) ? "" : "re",
+-		urb, now, now + mod);
+-	status = -ENOSPC;
++	/* Tried to schedule too far into the future? */
++	if (unlikely(start - now + span - period
++				>= mod - 2 * SCHEDULE_SLOP)) {
++		ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n",
++				urb, start - now, span - period,
++				mod - 2 * SCHEDULE_SLOP);
++		status = -EFBIG;
++		goto fail;
++	}
+ 
+-fail:
+-	iso_sched_free (stream, sched);
+-	urb->hcpriv = NULL;
+-	return status;
++	stream->next_uframe = start & (mod - 1);
+ 
+-ready:
+ 	/* report high speed start in uframes; full speed, in frames */
+ 	urb->start_frame = stream->next_uframe;
+ 	if (!stream->highspeed)
+ 		urb->start_frame >>= 3;
+ 	return 0;
++
++ fail:
++	iso_sched_free(stream, sched);
++	urb->hcpriv = NULL;
++	return status;
+ }
+ 
+ /*-------------------------------------------------------------------------*/

commit ffda080353979273e8aa69fc1e6134f20643ae56
+Author: Alan Stern 
+Date:   Wed Jul 14 11:03:46 2010 -0400
+
+    USB: EHCI: add missing frame -> microframe conversion
+    
+    This patch (as1407) fixes a bug in ehci-hcd's isochronous scheduler.
+    All its calculations should be done in terms of microframes, but for
+    full-speed devices, sched->span is stored in frames.  It needs to be
+    converted.
+    
+    This fix is liable to expose problems in other drivers.  The old code
+    would accept URBs that should not have been accepted, so drivers have
+    had no reason to avoid submitting URBs that exceeded the maximum
+    schedule length.  In an attempt to partially compensate for this, the
+    patch also adjusts the schedule length from a minimum of 256 frames up
+    to a minimum of 512 frames.
+    
+    Signed-off-by: Alan Stern 
+    CC: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 2e704fa3cedf..34a928d3b7d2 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -79,7 +79,13 @@ static const char	hcd_name [] = "ehci_hcd";
+ #define	EHCI_TUNE_RL_TT		0
+ #define	EHCI_TUNE_MULT_HS	1	/* 1-3 transactions/uframe; 4.10.3 */
+ #define	EHCI_TUNE_MULT_TT	1
+-#define	EHCI_TUNE_FLS		2	/* (small) 256 frame schedule */
++/*
++ * Some drivers think it's safe to schedule isochronous transfers more than
++ * 256 ms into the future (partly as a result of an old bug in the scheduling
++ * code).  In an attempt to avoid trouble, we will use a minimum scheduling
++ * length of 512 frames instead of 256.
++ */
++#define	EHCI_TUNE_FLS		1	/* (medium) 512-frame schedule */
+ 
+ #define EHCI_IAA_MSECS		10		/* arbitrary */
+ #define EHCI_IO_JIFFIES		(HZ/10)		/* io watchdog > irq_thresh */
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 27dd841b9aa2..dd37350170bb 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1395,28 +1395,31 @@ iso_stream_schedule (
+ 	struct ehci_iso_stream	*stream
+ )
+ {
+-	u32			now, next, start, period;
++	u32			now, next, start, period, span;
+ 	int			status;
+ 	unsigned		mod = ehci->periodic_size << 3;
+ 	struct ehci_iso_sched	*sched = urb->hcpriv;
+ 
+-	if (sched->span > (mod - SCHEDULE_SLOP)) {
++	period = urb->interval;
++	span = sched->span;
++	if (!stream->highspeed) {
++		period <<= 3;
++		span <<= 3;
++	}
++
++	if (span > mod - SCHEDULE_SLOP) {
+ 		ehci_dbg (ehci, "iso request %p too long\n", urb);
+ 		status = -EFBIG;
+ 		goto fail;
+ 	}
+ 
+-	if ((stream->depth + sched->span) > mod) {
++	if (stream->depth + span > mod) {
+ 		ehci_dbg (ehci, "request %p would overflow (%d+%d>%d)\n",
+-			urb, stream->depth, sched->span, mod);
++			urb, stream->depth, span, mod);
+ 		status = -EFBIG;
+ 		goto fail;
+ 	}
+ 
+-	period = urb->interval;
+-	if (!stream->highspeed)
+-		period <<= 3;
+-
+ 	now = ehci_readl(ehci, &ehci->regs->frame_index) & (mod - 1);
+ 
+ 	/* Typical case: reuse current schedule, stream is still active.
+@@ -1445,7 +1448,7 @@ iso_stream_schedule (
+ 					period);
+ 
+ 		/* Tried to schedule too far into the future? */
+-		if (unlikely(((start - now) & (mod - 1)) + sched->span
++		if (unlikely(((start - now) & (mod - 1)) + span
+ 					>= mod - 2 * SCHEDULE_SLOP)) {
+ 			status = -EFBIG;
+ 			goto fail;

commit bccbefaae050186bed3bcc74b1fd1a9b8c6710b2
+Author: Alan Stern 
+Date:   Wed Jul 14 11:03:36 2010 -0400
+
+    USB: EHCI: simplify remainder computations
+    
+    This patch (as1406) adds a micro-optimization to ehci-hcd's scheduling
+    code.  Instead of computing remainders with respect to the schedule
+    length, use bitwise-and (which is quicker).  We know that the schedule
+    length will always be a power of two, but the compiler doesn't have
+    this information.
+    
+    Signed-off-by: Alan Stern 
+    CC: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index efadced4ae67..27dd841b9aa2 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1417,7 +1417,7 @@ iso_stream_schedule (
+ 	if (!stream->highspeed)
+ 		period <<= 3;
+ 
+-	now = ehci_readl(ehci, &ehci->regs->frame_index) % mod;
++	now = ehci_readl(ehci, &ehci->regs->frame_index) & (mod - 1);
+ 
+ 	/* Typical case: reuse current schedule, stream is still active.
+ 	 * Hopefully there are no gaps from the host falling behind
+@@ -1461,7 +1461,7 @@ iso_stream_schedule (
+ 	 * jump until after the queue is primed.
+ 	 */
+ 	start = SCHEDULE_SLOP + (now & ~0x07);
+-	start %= mod;
++	start &= mod - 1;
+ 	stream->next_uframe = start;
+ 
+ 	/* NOTE:  assumes URB_ISO_ASAP, to limit complexity/bugs */
+@@ -1483,7 +1483,7 @@ iso_stream_schedule (
+ 
+ 		/* schedule it here if there's enough bandwidth */
+ 		if (enough_space) {
+-			stream->next_uframe = start % mod;
++			stream->next_uframe = start & (mod - 1);
+ 			goto ready;
+ 		}
+ 	}
+@@ -1599,7 +1599,7 @@ itd_link_urb (
+ 	struct ehci_iso_sched	*iso_sched = urb->hcpriv;
+ 	struct ehci_itd		*itd;
+ 
+-	next_uframe = stream->next_uframe % mod;
++	next_uframe = stream->next_uframe & (mod - 1);
+ 
+ 	if (unlikely (list_empty(&stream->td_list))) {
+ 		ehci_to_hcd(ehci)->self.bandwidth_allocated
+@@ -1637,13 +1637,13 @@ itd_link_urb (
+ 
+ 		next_uframe += stream->interval;
+ 		stream->depth += stream->interval;
+-		next_uframe %= mod;
++		next_uframe &= mod - 1;
+ 		packet++;
+ 
+ 		/* link completed itds into the schedule */
+ 		if (((next_uframe >> 3) != frame)
+ 				|| packet == urb->number_of_packets) {
+-			itd_link (ehci, frame % ehci->periodic_size, itd);
++			itd_link(ehci, frame & (ehci->periodic_size - 1), itd);
+ 			itd = NULL;
+ 		}
+ 	}
+@@ -2020,7 +2020,7 @@ sitd_link_urb (
+ 			"sched devp %s ep%d%s-iso [%d] %dms/%04x\n",
+ 			urb->dev->devpath, stream->bEndpointAddress & 0x0f,
+ 			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
+-			(next_uframe >> 3) % ehci->periodic_size,
++			(next_uframe >> 3) & (ehci->periodic_size - 1),
+ 			stream->interval, hc32_to_cpu(ehci, stream->splits));
+ 		stream->start = jiffies;
+ 	}
+@@ -2043,13 +2043,13 @@ sitd_link_urb (
+ 		sitd->urb = urb;
+ 
+ 		sitd_patch(ehci, stream, sitd, sched, packet);
+-		sitd_link (ehci, (next_uframe >> 3) % ehci->periodic_size,
++		sitd_link(ehci, (next_uframe >> 3) & (ehci->periodic_size - 1),
+ 				sitd);
+ 
+ 		next_uframe += stream->interval << 3;
+ 		stream->depth += stream->interval << 3;
+ 	}
+-	stream->next_uframe = next_uframe % mod;
++	stream->next_uframe = next_uframe & (mod - 1);
+ 
+ 	/* don't need that schedule data any more */
+ 	iso_sched_free (stream, sched);
+@@ -2258,7 +2258,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 	now_uframe = ehci->next_uframe;
+ 	if (HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) {
+ 		clock = ehci_readl(ehci, &ehci->regs->frame_index);
+-		clock_frame = (clock >> 3) % ehci->periodic_size;
++		clock_frame = (clock >> 3) & (ehci->periodic_size - 1);
+ 	} else  {
+ 		clock = now_uframe + mod - 1;
+ 		clock_frame = -1;
+@@ -2267,7 +2267,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 		free_cached_lists(ehci);
+ 		ehci->clock_frame = clock_frame;
+ 	}
+-	clock %= mod;
++	clock &= mod - 1;
+ 	clock_frame = clock >> 3;
+ 
+ 	for (;;) {
+@@ -2356,7 +2356,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 				 * frame is current.
+ 				 */
+ 				if (((frame == clock_frame) ||
+-				     (((frame + 1) % ehci->periodic_size)
++				     (((frame + 1) & (ehci->periodic_size - 1))
+ 				      == clock_frame))
+ 				    && live
+ 				    && (q.sitd->hw_results &
+@@ -2423,7 +2423,8 @@ scan_periodic (struct ehci_hcd *ehci)
+ 					|| ehci->periodic_sched == 0)
+ 				break;
+ 			ehci->next_uframe = now_uframe;
+-			now = ehci_readl(ehci, &ehci->regs->frame_index) % mod;
++			now = ehci_readl(ehci, &ehci->regs->frame_index) &
++					(mod - 1);
+ 			if (now_uframe == now)
+ 				break;
+ 
+@@ -2436,7 +2437,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 			}
+ 		} else {
+ 			now_uframe++;
+-			now_uframe %= mod;
++			now_uframe &= mod - 1;
+ 		}
+ 	}
+ }

commit ae68a83bdc1971cb02fefc7a686ba6d077065e71
+Author: Alan Stern 
+Date:   Wed Jul 14 11:03:23 2010 -0400
+
+    USB: EHCI: remove PCI assumption
+    
+    This patch (as1405) fixes a small bug in ehci-hcd's isochronous
+    scheduler.  Not all EHCI controllers are PCI, and the code shouldn't
+    assume that they are.  Instead, introduce a special flag for
+    controllers which need to delay iso scheduling for full-speed devices
+    beyond the scheduling threshold.
+    
+    Signed-off-by: Alan Stern 
+    CC: Sarah Sharp 
+    CC: David Brownell 
+    CC: stable 
+    Acked-by: Sarah Sharp 
+
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index f555e4f35a04..58b72d741d93 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -114,6 +114,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 		break;
+ 	case PCI_VENDOR_ID_INTEL:
+ 		ehci->need_io_watchdog = 0;
++		ehci->fs_i_thresh = 1;
+ 		if (pdev->device == 0x27cc) {
+ 			ehci->broken_periodic = 1;
+ 			ehci_info(ehci, "using broken periodic workaround\n");
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index d640346f9b56..efadced4ae67 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1399,7 +1399,6 @@ iso_stream_schedule (
+ 	int			status;
+ 	unsigned		mod = ehci->periodic_size << 3;
+ 	struct ehci_iso_sched	*sched = urb->hcpriv;
+-	struct pci_dev		*pdev;
+ 
+ 	if (sched->span > (mod - SCHEDULE_SLOP)) {
+ 		ehci_dbg (ehci, "iso request %p too long\n", urb);
+@@ -1426,15 +1425,14 @@ iso_stream_schedule (
+ 	 * slot in the schedule, implicitly assuming URB_ISO_ASAP.
+ 	 */
+ 	if (likely (!list_empty (&stream->td_list))) {
+-		pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller);
+ 		start = stream->next_uframe;
+ 
+ 		/* For high speed devices, allow scheduling within the
+-		 * isochronous scheduling threshold.  For full speed devices,
+-		 * don't. (Work around for Intel ICH9 bug.)
++		 * isochronous scheduling threshold.  For full speed devices
++		 * and Intel PCI-based controllers, don't (work around for
++		 * Intel ICH9 bug).
+ 		 */
+-		if (!stream->highspeed &&
+-				pdev->vendor == PCI_VENDOR_ID_INTEL)
++		if (!stream->highspeed && ehci->fs_i_thresh)
+ 			next = now + ehci->i_thresh;
+ 		else
+ 			next = now;
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index a4a63ce290e9..2c050efd1deb 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -130,6 +130,7 @@ struct ehci_hcd {			/* one per controller */
+ 	unsigned		has_amcc_usb23:1;
+ 	unsigned		need_io_watchdog:1;
+ 	unsigned		broken_periodic:1;
++	unsigned		fs_i_thresh:1;	/* Intel iso scheduling */
+ 
+ 	/* required for usb32 quirk */
+ 	#define OHCI_CTRL_HCFS          (3 << 6)

commit 3da7cff4e79e4a7137b0dac1aaf6841b91bbff63
+Author: Alan Stern 
+Date:   Fri Jun 25 14:02:57 2010 -0400
+
+    USB: add runtime PM for PCI-based host controllers
+    
+    This patch (as1386) adds runtime-PM support for PCI-based USB host
+    controllers.  By default autosuspend is disallowed; the user must
+    enable it by writing "auto" to the controller's power/control sysfs
+    attribute.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index 352577baa53d..fe6b8d40a506 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -250,6 +250,9 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ 	if (retval != 0)
+ 		goto err4;
+ 	set_hs_companion(dev, hcd);
++
++	if (pci_dev_run_wake(dev))
++		pm_runtime_put_noidle(&dev->dev);
+ 	return retval;
+ 
+  err4:
+@@ -292,6 +295,9 @@ void usb_hcd_pci_remove(struct pci_dev *dev)
+ 	if (!hcd)
+ 		return;
+ 
++	if (pci_dev_run_wake(dev))
++		pm_runtime_get_noresume(&dev->dev);
++
+ 	/* Fake an interrupt request in order to give the driver a chance
+ 	 * to test whether the controller hardware has been removed (e.g.,
+ 	 * cardbus physical eject).
+@@ -325,12 +331,13 @@ void usb_hcd_pci_shutdown(struct pci_dev *dev)
+ 	if (!hcd)
+ 		return;
+ 
+-	if (hcd->driver->shutdown)
++	if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) &&
++			hcd->driver->shutdown)
+ 		hcd->driver->shutdown(hcd);
+ }
+ EXPORT_SYMBOL_GPL(usb_hcd_pci_shutdown);
+ 
+-#ifdef	CONFIG_PM_SLEEP
++#ifdef	CONFIG_PM_OPS
+ 
+ #ifdef	CONFIG_PPC_PMAC
+ static void powermac_set_asic(struct pci_dev *pci_dev, int enable)
+@@ -366,7 +373,7 @@ static int check_root_hub_suspended(struct device *dev)
+ 	return 0;
+ }
+ 
+-static int hcd_pci_suspend(struct device *dev)
++static int suspend_common(struct device *dev, bool do_wakeup)
+ {
+ 	struct pci_dev		*pci_dev = to_pci_dev(dev);
+ 	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
+@@ -381,13 +388,7 @@ static int hcd_pci_suspend(struct device *dev)
+ 	if (retval)
+ 		return retval;
+ 
+-	/* We might already be suspended (runtime PM -- not yet written) */
+-	if (pci_dev->current_state != PCI_D0)
+-		return retval;
+-
+ 	if (hcd->driver->pci_suspend) {
+-		bool	do_wakeup = device_may_wakeup(dev);
+-
+ 		/* Optimization: Don't suspend if a root-hub wakeup is
+ 		 * pending and it would cause the HCD to wake up anyway.
+ 		 */
+@@ -439,10 +440,8 @@ static int resume_common(struct device *dev, int event)
+ 	clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+ 
+ 	if (hcd->driver->pci_resume) {
+-		/* This call should be made only during system resume,
+-		 * not during runtime resume.
+-		 */
+-		wait_for_companions(pci_dev, hcd);
++		if (event != PM_EVENT_AUTO_RESUME)
++			wait_for_companions(pci_dev, hcd);
+ 
+ 		retval = hcd->driver->pci_resume(hcd,
+ 				event == PM_EVENT_RESTORE);
+@@ -454,6 +453,13 @@ static int resume_common(struct device *dev, int event)
+ 	return retval;
+ }
+ 
++#ifdef	CONFIG_PM_SLEEP
++
++static int hcd_pci_suspend(struct device *dev)
++{
++	return suspend_common(dev, device_may_wakeup(dev));
++}
++
+ static int hcd_pci_suspend_noirq(struct device *dev)
+ {
+ 	struct pci_dev		*pci_dev = to_pci_dev(dev);
+@@ -513,6 +519,46 @@ static int hcd_pci_restore(struct device *dev)
+ 	return resume_common(dev, PM_EVENT_RESTORE);
+ }
+ 
++#else
++
++#define hcd_pci_suspend		NULL
++#define hcd_pci_suspend_noirq	NULL
++#define hcd_pci_resume_noirq	NULL
++#define hcd_pci_resume		NULL
++#define hcd_pci_restore		NULL
++
++#endif	/* CONFIG_PM_SLEEP */
++
++#ifdef	CONFIG_PM_RUNTIME
++
++static int hcd_pci_runtime_suspend(struct device *dev)
++{
++	int	retval;
++
++	retval = suspend_common(dev, true);
++	if (retval == 0)
++		powermac_set_asic(to_pci_dev(dev), 0);
++	dev_dbg(dev, "hcd_pci_runtime_suspend: %d\n", retval);
++	return retval;
++}
++
++static int hcd_pci_runtime_resume(struct device *dev)
++{
++	int	retval;
++
++	powermac_set_asic(to_pci_dev(dev), 1);
++	retval = resume_common(dev, PM_EVENT_AUTO_RESUME);
++	dev_dbg(dev, "hcd_pci_runtime_resume: %d\n", retval);
++	return retval;
++}
++
++#else
++
++#define hcd_pci_runtime_suspend	NULL
++#define hcd_pci_runtime_resume	NULL
++
++#endif	/* CONFIG_PM_RUNTIME */
++
+ const struct dev_pm_ops usb_hcd_pci_pm_ops = {
+ 	.suspend	= hcd_pci_suspend,
+ 	.suspend_noirq	= hcd_pci_suspend_noirq,
+@@ -526,7 +572,9 @@ const struct dev_pm_ops usb_hcd_pci_pm_ops = {
+ 	.poweroff_noirq	= hcd_pci_suspend_noirq,
+ 	.restore_noirq	= hcd_pci_resume_noirq,
+ 	.restore	= hcd_pci_restore,
++	.runtime_suspend = hcd_pci_runtime_suspend,
++	.runtime_resume	= hcd_pci_runtime_resume,
+ };
+ EXPORT_SYMBOL_GPL(usb_hcd_pci_pm_ops);
+ 
+-#endif	/* CONFIG_PM_SLEEP */
++#endif	/* CONFIG_PM_OPS */

commit 0d436b425e07f9e4b0fe571cec061f5d136f1d8b
+Author: Alan Stern 
+Date:   Fri Jun 25 14:02:49 2010 -0400
+
+    USB: UHCI: add support for Intel's wakeup flags
+    
+    This patch (as1396) adds code to uhci-hcd to support the
+    vendor-specific wakeup settings found in Intel's ICHx hardware.  A
+    couple of unnecessary memory barriers are removed.  And the root hub
+    isn't put back into the "suspended" state if power was lost during a
+    system sleep -- there's not much point in doing so because the root hub
+    will be resumed shortly.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 9d4d81248f96..b04506036b64 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -176,6 +176,8 @@ static void check_and_reset_hc(struct uhci_hcd *uhci)
+  */
+ static void configure_hc(struct uhci_hcd *uhci)
+ {
++	struct pci_dev *pdev = to_pci_dev(uhci_dev(uhci));
++
+ 	/* Set the frame length to the default: 1 ms exactly */
+ 	outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF);
+ 
+@@ -191,8 +193,11 @@ static void configure_hc(struct uhci_hcd *uhci)
+ 	mb();
+ 
+ 	/* Enable PIRQ */
+-	pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
+-			USBLEGSUP_DEFAULT);
++	pci_write_config_word(pdev, USBLEGSUP, USBLEGSUP_DEFAULT);
++
++	/* Disable platform-specific non-PME# wakeup */
++	if (pdev->vendor == PCI_VENDOR_ID_INTEL)
++		pci_write_config_byte(pdev, USBRES_INTEL, 0);
+ }
+ 
+ 
+@@ -791,6 +796,7 @@ static int uhci_rh_resume(struct usb_hcd *hcd)
+ static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++	struct pci_dev *pdev = to_pci_dev(uhci_dev(uhci));
+ 	int rc = 0;
+ 
+ 	dev_dbg(uhci_dev(uhci), "%s\n", __func__);
+@@ -808,11 +814,15 @@ static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+ 	/* All PCI host controllers are required to disable IRQ generation
+ 	 * at the source, so we must turn off PIRQ.
+ 	 */
+-	pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0);
+-	mb();
++	pci_write_config_word(pdev, USBLEGSUP, 0);
+ 	clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+ 
+-	/* FIXME: Enable non-PME# remote wakeup? */
++	/* Enable platform-specific non-PME# wakeup */
++	if (do_wakeup) {
++		if (pdev->vendor == PCI_VENDOR_ID_INTEL)
++			pci_write_config_byte(pdev, USBRES_INTEL,
++					USBPORT1EN | USBPORT2EN);
++	}
+ 
+ done_okay:
+ 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+@@ -831,7 +841,6 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
+ 	 * even if the controller was dead.
+ 	 */
+ 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+-	mb();
+ 
+ 	spin_lock_irq(&uhci->lock);
+ 
+@@ -839,8 +848,6 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
+ 	if (hibernated)
+ 		uhci_hc_died(uhci);
+ 
+-	/* FIXME: Disable non-PME# remote wakeup? */
+-
+ 	/* The firmware or a boot kernel may have changed the controller
+ 	 * settings during a system wakeup.  Check it and reconfigure
+ 	 * to avoid problems.
+@@ -850,12 +857,9 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
+ 	/* If the controller was dead before, it's back alive now */
+ 	configure_hc(uhci);
+ 
+-	if (uhci->rh_state == UHCI_RH_RESET) {
+-
+-		/* The controller had to be reset */
++	/* Tell the core if the controller had to be reset */
++	if (uhci->rh_state == UHCI_RH_RESET)
+ 		usb_root_hub_lost_power(hcd->self.root_hub);
+-		suspend_rh(uhci, UHCI_RH_SUSPENDED);
+-	}
+ 
+ 	spin_unlock_irq(&uhci->lock);
+ 
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index 26bd1b2bcbfc..49bf2790f9c2 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -67,12 +67,17 @@
+ #define   USBPORTSC_RES3	0x4000	/* reserved, write zeroes */
+ #define   USBPORTSC_RES4	0x8000	/* reserved, write zeroes */
+ 
+-/* Legacy support register */
++/* PCI legacy support register */
+ #define USBLEGSUP		0xc0
+ #define   USBLEGSUP_DEFAULT	0x2000	/* only PIRQ enable set */
+ #define   USBLEGSUP_RWC		0x8f00	/* the R/WC bits */
+ #define   USBLEGSUP_RO		0x5040	/* R/O and reserved bits */
+ 
++/* PCI Intel-specific resume-enable register */
++#define USBRES_INTEL		0xc4
++#define   USBPORT1EN		0x01
++#define   USBPORT2EN		0x02
++
+ #define UHCI_PTR_BITS		cpu_to_le32(0x000F)
+ #define UHCI_PTR_TERM		cpu_to_le32(0x0001)
+ #define UHCI_PTR_QH		cpu_to_le32(0x0002)

commit ff2f07874362d34684296f2bd5547a099f33c6d4
+Author: Alan Stern 
+Date:   Fri Jun 25 14:02:35 2010 -0400
+
+    USB: fix race between root-hub wakeup & controller suspend
+    
+    This patch (as1395) adds code to hcd_pci_suspend() for handling wakeup
+    races.  This is another general race pattern, similar to the "open
+    vs. unregister" race we're all familiar with.  Here, the race is
+    between suspending a device and receiving a wakeup request from one of
+    the device's suspended children.
+    
+    In particular, if a root-hub wakeup is requested at about the same
+    time as the corresponding USB controller is suspended, and if the
+    controller is enabled for wakeup, then the controller should either
+    fail to suspend or else wake right back up again.
+    
+    During system sleep this won't happen very much, especially since host
+    controllers generally aren't enabled for wakeup during sleep.  However
+    it is definitely an issue for runtime PM.  Something like this will be
+    needed to prevent the controller from autosuspending while waiting for
+    a root-hub resume to take place.  (That is, in fact, the common case,
+    for which there is an extra test.)
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index e387e394f876..352577baa53d 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -388,8 +388,20 @@ static int hcd_pci_suspend(struct device *dev)
+ 	if (hcd->driver->pci_suspend) {
+ 		bool	do_wakeup = device_may_wakeup(dev);
+ 
++		/* Optimization: Don't suspend if a root-hub wakeup is
++		 * pending and it would cause the HCD to wake up anyway.
++		 */
++		if (do_wakeup && HCD_WAKEUP_PENDING(hcd))
++			return -EBUSY;
+ 		retval = hcd->driver->pci_suspend(hcd, do_wakeup);
+ 		suspend_report_result(hcd->driver->pci_suspend, retval);
++
++		/* Check again in case wakeup raced with pci_suspend */
++		if (retval == 0 && do_wakeup && HCD_WAKEUP_PENDING(hcd)) {
++			if (hcd->driver->pci_resume)
++				hcd->driver->pci_resume(hcd, false);
++			retval = -EBUSY;
++		}
+ 		if (retval)
+ 			return retval;
+ 	}
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index f2fe7c8e991d..0358c05e6e8a 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1940,6 +1940,7 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
+ 
+ 	dev_dbg(&rhdev->dev, "usb %s%s\n",
+ 			(msg.event & PM_EVENT_AUTO ? "auto-" : ""), "resume");
++	clear_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags);
+ 	if (!hcd->driver->bus_resume)
+ 		return -ENOENT;
+ 	if (hcd->state == HC_STATE_RUNNING)
+@@ -1993,8 +1994,10 @@ void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave (&hcd_root_hub_lock, flags);
+-	if (hcd->rh_registered)
++	if (hcd->rh_registered) {
++		set_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags);
+ 		queue_work(pm_wq, &hcd->wakeup_work);
++	}
+ 	spin_unlock_irqrestore (&hcd_root_hub_lock, flags);
+ }
+ EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub);
+diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
+index ae10020b4023..3b571f1ffbb3 100644
+--- a/include/linux/usb/hcd.h
++++ b/include/linux/usb/hcd.h
+@@ -98,6 +98,7 @@ struct usb_hcd {
+ #define HCD_FLAG_SAW_IRQ		1
+ #define HCD_FLAG_POLL_RH		2	/* poll for rh status? */
+ #define HCD_FLAG_POLL_PENDING		3	/* status has changed? */
++#define HCD_FLAG_WAKEUP_PENDING		4	/* root hub is resuming? */
+ 
+ 	/* The flags can be tested using these macros; they are likely to
+ 	 * be slightly faster than test_bit().
+@@ -106,6 +107,7 @@ struct usb_hcd {
+ #define HCD_SAW_IRQ(hcd)	((hcd)->flags & (1U << HCD_FLAG_SAW_IRQ))
+ #define HCD_POLL_RH(hcd)	((hcd)->flags & (1U << HCD_FLAG_POLL_RH))
+ #define HCD_POLL_PENDING(hcd)	((hcd)->flags & (1U << HCD_FLAG_POLL_PENDING))
++#define HCD_WAKEUP_PENDING(hcd)	((hcd)->flags & (1U << HCD_FLAG_WAKEUP_PENDING))
+ 
+ 	/* Flags that get set only during HCD registration or removal. */
+ 	unsigned		rh_registered:1;/* is root hub registered? */

commit ee0b9be829803e3ff5adec7456bd59a08425ffa1
+Author: Alan Stern 
+Date:   Fri Jun 25 14:02:24 2010 -0400
+
+    USB: controller resume should check the root hub
+    
+    This patch (as1394) adds code to ehci-hcd, ohci-hcd, and uhci-hcd for
+    automatically resuming the root hub when the controller is resumed, if
+    the root hub has a wakeup request pending on some port.
+    
+    During resume from system sleep this doesn't matter, because the root
+    hubs will naturally be resumed along with every other device in the
+    system.  However it _will_ matter for runtime PM: If the controller is
+    suspended and a remote wakeup request is received then the controller
+    will autoresume, but we need to ensure that the root hub also
+    autoresumes.  Otherwise the wakeup request would be ignored, the
+    controller would go back to sleep, and the cycle would repeat a large
+    number of times (I saw this happen before the patch was written).
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 1292a5b2197a..796ea0c8900f 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -166,6 +166,10 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
+ 			ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg);
+ 		}
+ 	}
++
++	/* Does the root hub have a port wakeup pending? */
++	if (!suspending && (ehci_readl(ehci, &ehci->regs->status) & STS_PCD))
++		usb_hcd_resume_root_hub(ehci_to_hcd(ehci));
+ }
+ 
+ static int ehci_bus_suspend (struct usb_hcd *hcd)
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index 4dd39022c388..cddcda95b579 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -355,6 +355,11 @@ static void ohci_finish_controller_resume(struct usb_hcd *hcd)
+ 		ohci_readl(ohci, &ohci->regs->intrenable);
+ 		msleep(20);
+ 	}
++
++	/* Does the root hub have a port wakeup pending? */
++	if (ohci_readl(ohci, &ohci->regs->intrstatus) &
++			(OHCI_INTR_RD | OHCI_INTR_RHSC))
++		usb_hcd_resume_root_hub(hcd);
+ }
+ 
+ /* Carry out polling-, autostop-, and autoresume-related state changes */
+@@ -364,7 +369,7 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ 	int	poll_rh = 1;
+ 	int	rhsc_enable;
+ 
+-	/* Some broken controllers never turn off RHCS in the interrupt
++	/* Some broken controllers never turn off RHSC in the interrupt
+ 	 * status register.  For their sake we won't re-enable RHSC
+ 	 * interrupts if the interrupt bit is already active.
+ 	 */
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index a7850f51fdc5..9d4d81248f96 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -862,10 +862,11 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
+ 	/* If interrupts don't work and remote wakeup is enabled then
+ 	 * the suspended root hub needs to be polled.
+ 	 */
+-	if (!uhci->RD_enable && hcd->self.root_hub->do_remote_wakeup) {
++	if (!uhci->RD_enable && hcd->self.root_hub->do_remote_wakeup)
+ 		set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+-		usb_hcd_poll_rh_status(hcd);
+-	}
++
++	/* Does the root hub have a port wakeup pending? */
++	usb_hcd_poll_rh_status(hcd);
+ 	return 0;
+ }
+ #endif
+diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
+index f0c58116c0ad..6d59c0f77f25 100644
+--- a/drivers/usb/host/uhci-hub.c
++++ b/drivers/usb/host/uhci-hub.c
+@@ -200,7 +200,7 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
+ 	    case UHCI_RH_SUSPENDING:
+ 	    case UHCI_RH_SUSPENDED:
+ 		/* if port change, ask to be resumed */
+-		if (status)
++		if (status || uhci->resuming_ports)
+ 			usb_hcd_resume_root_hub(hcd);
+ 		break;
+ 

commit 4147200d25c423e627ab4487530b3d9f2ef829c8
+Author: Alan Stern 
+Date:   Fri Jun 25 14:02:14 2010 -0400
+
+    USB: add do_wakeup parameter for PCI HCD suspend
+    
+    This patch (as1385) adds a "do_wakeup" parameter to the pci_suspend
+    method used by PCI-based host controller drivers.  ehci-hcd in
+    particular needs to know whether or not to enable wakeup when
+    suspending a controller.  Although that information is currently
+    available through device_may_wakeup(), when support is added for
+    runtime suspend this will no longer be true.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index f0156de8db67..e387e394f876 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -386,7 +386,9 @@ static int hcd_pci_suspend(struct device *dev)
+ 		return retval;
+ 
+ 	if (hcd->driver->pci_suspend) {
+-		retval = hcd->driver->pci_suspend(hcd);
++		bool	do_wakeup = device_may_wakeup(dev);
++
++		retval = hcd->driver->pci_suspend(hcd, do_wakeup);
+ 		suspend_report_result(hcd->driver->pci_suspend, retval);
+ 		if (retval)
+ 			return retval;
+diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
+index faa61748db70..2baf8a849086 100644
+--- a/drivers/usb/host/ehci-au1xxx.c
++++ b/drivers/usb/host/ehci-au1xxx.c
+@@ -228,7 +228,7 @@ static int ehci_hcd_au1xxx_drv_suspend(struct device *dev)
+ 	 * the root hub is either suspended or stopped.
+ 	 */
+ 	spin_lock_irqsave(&ehci->lock, flags);
+-	ehci_prepare_ports_for_controller_suspend(ehci);
++	ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev));
+ 	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+ 	(void)ehci_readl(ehci, &ehci->regs->intr_enable);
+ 
+diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
+index 5cd967d28938..a416421abfa2 100644
+--- a/drivers/usb/host/ehci-fsl.c
++++ b/drivers/usb/host/ehci-fsl.c
+@@ -313,7 +313,8 @@ static int ehci_fsl_drv_suspend(struct device *dev)
+ 	struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);
+ 	void __iomem *non_ehci = hcd->regs;
+ 
+-	ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd));
++	ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd),
++			device_may_wakeup(dev));
+ 	if (!fsl_deep_sleep())
+ 		return 0;
+ 
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 0931f5a7dec4..1292a5b2197a 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -107,7 +107,7 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
+ }
+ 
+ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
+-		bool suspending)
++		bool suspending, bool do_wakeup)
+ {
+ 	int		port;
+ 	u32		temp;
+@@ -117,8 +117,7 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
+ 	 * when the controller is suspended or resumed.  In all other
+ 	 * cases they don't need to be changed.
+ 	 */
+-	if (!ehci_to_hcd(ehci)->self.root_hub->do_remote_wakeup ||
+-			device_may_wakeup(ehci_to_hcd(ehci)->self.controller))
++	if (!ehci_to_hcd(ehci)->self.root_hub->do_remote_wakeup || do_wakeup)
+ 		return;
+ 
+ 	/* clear phy low-power mode before changing wakeup flags */
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index a307d550bdaf..f555e4f35a04 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -277,7 +277,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+  * Also they depend on separate root hub suspend/resume.
+  */
+ 
+-static int ehci_pci_suspend(struct usb_hcd *hcd)
++static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+ {
+ 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
+ 	unsigned long		flags;
+@@ -291,7 +291,7 @@ static int ehci_pci_suspend(struct usb_hcd *hcd)
+ 	 * the root hub is either suspended or stopped.
+ 	 */
+ 	spin_lock_irqsave (&ehci->lock, flags);
+-	ehci_prepare_ports_for_controller_suspend(ehci);
++	ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup);
+ 	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+ 	(void)ehci_readl(ehci, &ehci->regs->intr_enable);
+ 
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index e6c57cc416f6..a4a63ce290e9 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -540,11 +540,11 @@ struct ehci_fstn {
+ 
+ /* Prepare the PORTSC wakeup flags during controller suspend/resume */
+ 
+-#define ehci_prepare_ports_for_controller_suspend(ehci)		\
+-		ehci_adjust_port_wakeup_flags(ehci, true);
++#define ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup)	\
++		ehci_adjust_port_wakeup_flags(ehci, true, do_wakeup);
+ 
+-#define ehci_prepare_ports_for_controller_resume(ehci)		\
+-		ehci_adjust_port_wakeup_flags(ehci, false);
++#define ehci_prepare_ports_for_controller_resume(ehci)			\
++		ehci_adjust_port_wakeup_flags(ehci, false, false);
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index b8a1148f248e..6bdc8b25a6a1 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -392,7 +392,7 @@ static int __devinit ohci_pci_start (struct usb_hcd *hcd)
+ 
+ #ifdef	CONFIG_PM
+ 
+-static int ohci_pci_suspend(struct usb_hcd *hcd)
++static int ohci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+ {
+ 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
+ 	unsigned long	flags;
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 2743ec770f0c..a7850f51fdc5 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -788,7 +788,7 @@ static int uhci_rh_resume(struct usb_hcd *hcd)
+ 	return rc;
+ }
+ 
+-static int uhci_pci_suspend(struct usb_hcd *hcd)
++static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 	int rc = 0;
+diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
+index f8f8fa7a56e8..ae10020b4023 100644
+--- a/include/linux/usb/hcd.h
++++ b/include/linux/usb/hcd.h
+@@ -211,7 +211,7 @@ struct hc_driver {
+ 	 * a whole, not just the root hub; they're for PCI bus glue.
+ 	 */
+ 	/* called after suspending the hub, before entering D3 etc */
+-	int	(*pci_suspend)(struct usb_hcd *hcd);
++	int	(*pci_suspend)(struct usb_hcd *hcd, bool do_wakeup);
+ 
+ 	/* called after entering D0 (etc), before resuming the hub */
+ 	int	(*pci_resume)(struct usb_hcd *hcd, bool hibernated);

commit 057c58bfb1dc9bbb75b8ba3b6c6336cfca63b9d0
+Author: Alan Stern 
+Date:   Fri Jun 25 14:02:03 2010 -0400
+
+    USB: move PCI HCD resume routine
+    
+    This patch (as1384) moves the resume_common() routine in hcd-pci.c a
+    little higher in the source file to avoid forward references in an
+    upcoming patch.  It also replaces the "hibernated" argument with a
+    more general "event" argument, which will be useful when the routine
+    is called during a runtime resume.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index 7c3b0af62241..f0156de8db67 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -403,6 +403,43 @@ static int hcd_pci_suspend(struct device *dev)
+ 	return retval;
+ }
+ 
++static int resume_common(struct device *dev, int event)
++{
++	struct pci_dev		*pci_dev = to_pci_dev(dev);
++	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
++	int			retval;
++
++	if (hcd->state != HC_STATE_SUSPENDED) {
++		dev_dbg(dev, "can't resume, not suspended!\n");
++		return 0;
++	}
++
++	retval = pci_enable_device(pci_dev);
++	if (retval < 0) {
++		dev_err(dev, "can't re-enable after resume, %d!\n", retval);
++		return retval;
++	}
++
++	pci_set_master(pci_dev);
++
++	clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
++
++	if (hcd->driver->pci_resume) {
++		/* This call should be made only during system resume,
++		 * not during runtime resume.
++		 */
++		wait_for_companions(pci_dev, hcd);
++
++		retval = hcd->driver->pci_resume(hcd,
++				event == PM_EVENT_RESTORE);
++		if (retval) {
++			dev_err(dev, "PCI post-resume error %d!\n", retval);
++			usb_hc_died(hcd);
++		}
++	}
++	return retval;
++}
++
+ static int hcd_pci_suspend_noirq(struct device *dev)
+ {
+ 	struct pci_dev		*pci_dev = to_pci_dev(dev);
+@@ -452,50 +489,14 @@ static int hcd_pci_resume_noirq(struct device *dev)
+ 	return 0;
+ }
+ 
+-static int resume_common(struct device *dev, bool hibernated)
+-{
+-	struct pci_dev		*pci_dev = to_pci_dev(dev);
+-	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
+-	int			retval;
+-
+-	if (hcd->state != HC_STATE_SUSPENDED) {
+-		dev_dbg(dev, "can't resume, not suspended!\n");
+-		return 0;
+-	}
+-
+-	retval = pci_enable_device(pci_dev);
+-	if (retval < 0) {
+-		dev_err(dev, "can't re-enable after resume, %d!\n", retval);
+-		return retval;
+-	}
+-
+-	pci_set_master(pci_dev);
+-
+-	clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+-
+-	if (hcd->driver->pci_resume) {
+-		/* This call should be made only during system resume,
+-		 * not during runtime resume.
+-		 */
+-		wait_for_companions(pci_dev, hcd);
+-
+-		retval = hcd->driver->pci_resume(hcd, hibernated);
+-		if (retval) {
+-			dev_err(dev, "PCI post-resume error %d!\n", retval);
+-			usb_hc_died(hcd);
+-		}
+-	}
+-	return retval;
+-}
+-
+ static int hcd_pci_resume(struct device *dev)
+ {
+-	return resume_common(dev, false);
++	return resume_common(dev, PM_EVENT_RESUME);
+ }
+ 
+ static int hcd_pci_restore(struct device *dev)
+ {
+-	return resume_common(dev, true);
++	return resume_common(dev, PM_EVENT_RESTORE);
+ }
+ 
+ const struct dev_pm_ops usb_hcd_pci_pm_ops = {

commit 2138a1f1835274b1d131a1aafa1655f60b2af122
+Author: Alan Stern 
+Date:   Fri Jun 25 14:01:49 2010 -0400
+
+    USB: refactor the powermac-specific ASIC clock code
+    
+    This patch (as1383) takes the powermac-specific code from the PCI HCD
+    glue layer and encapsulates it in its own subroutine.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Benjamin Herrenschmidt 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index 7e2d5271b0c9..7c3b0af62241 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -332,6 +332,27 @@ EXPORT_SYMBOL_GPL(usb_hcd_pci_shutdown);
+ 
+ #ifdef	CONFIG_PM_SLEEP
+ 
++#ifdef	CONFIG_PPC_PMAC
++static void powermac_set_asic(struct pci_dev *pci_dev, int enable)
++{
++	/* Enanble or disable ASIC clocks for USB */
++	if (machine_is(powermac)) {
++		struct device_node	*of_node;
++
++		of_node = pci_device_to_OF_node(pci_dev);
++		if (of_node)
++			pmac_call_feature(PMAC_FTR_USB_ENABLE,
++					of_node, 0, enable);
++	}
++}
++
++#else
++
++static inline void powermac_set_asic(struct pci_dev *pci_dev, int enable)
++{}
++
++#endif	/* CONFIG_PPC_PMAC */
++
+ static int check_root_hub_suspended(struct device *dev)
+ {
+ 	struct pci_dev		*pci_dev = to_pci_dev(dev);
+@@ -416,16 +437,7 @@ static int hcd_pci_suspend_noirq(struct device *dev)
+ 		return retval;
+ 	}
+ 
+-#ifdef CONFIG_PPC_PMAC
+-	/* Disable ASIC clocks for USB */
+-	if (machine_is(powermac)) {
+-		struct device_node	*of_node;
+-
+-		of_node = pci_device_to_OF_node(pci_dev);
+-		if (of_node)
+-			pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0);
+-	}
+-#endif
++	powermac_set_asic(pci_dev, 0);
+ 	return retval;
+ }
+ 
+@@ -433,17 +445,7 @@ static int hcd_pci_resume_noirq(struct device *dev)
+ {
+ 	struct pci_dev		*pci_dev = to_pci_dev(dev);
+ 
+-#ifdef CONFIG_PPC_PMAC
+-	/* Reenable ASIC clocks for USB */
+-	if (machine_is(powermac)) {
+-		struct device_node *of_node;
+-
+-		of_node = pci_device_to_OF_node(pci_dev);
+-		if (of_node)
+-			pmac_call_feature(PMAC_FTR_USB_ENABLE,
+-						of_node, 0, 1);
+-	}
+-#endif
++	powermac_set_asic(pci_dev, 1);
+ 
+ 	/* Go back to D0 and disable remote wakeup */
+ 	pci_back_from_sleep(pci_dev);

commit 541c7d432f76771079e7c295d596ea47cc6a3030
+Author: Alan Stern 
+Date:   Tue Jun 22 16:39:10 2010 -0400
+
+    USB: convert usb_hcd bitfields into atomic flags
+    
+    This patch (as1393) converts several of the single-bit fields in
+    struct usb_hcd to atomic flags.  This is for safety's sake; not all
+    CPUs can update bitfield values atomically, and these flags are used
+    in multiple contexts.
+    
+    The flag fields that are set only during registration or removal can
+    remain as they are, since non-atomic accesses at those times will not
+    cause any problems.
+    
+    (Strictly speaking, the authorized_default flag should become atomic
+    as well.  I didn't bother with it because it gets changed only via
+    sysfs.  It can be done later, if anyone wants.)
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c
+index be5d8db98165..0574d848b900 100644
+--- a/drivers/staging/usbip/vhci_hcd.c
++++ b/drivers/staging/usbip/vhci_hcd.c
+@@ -215,7 +215,7 @@ static int vhci_hub_status(struct usb_hcd *hcd, char *buf)
+ 	vhci = hcd_to_vhci(hcd);
+ 
+ 	spin_lock_irqsave(&vhci->lock, flags);
+-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
++	if (!HCD_HW_ACCESSIBLE(hcd)) {
+ 		usbip_dbg_vhci_rh("hw accessible flag in on?\n");
+ 		goto done;
+ 	}
+@@ -269,7 +269,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+ 
+ 	u32 prev_port_status[VHCI_NPORTS];
+ 
+-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
++	if (!HCD_HW_ACCESSIBLE(hcd))
+ 		return -ETIMEDOUT;
+ 
+ 	/*
+@@ -1041,7 +1041,7 @@ static int vhci_bus_resume(struct usb_hcd *hcd)
+ 	dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
+ 
+ 	spin_lock_irq(&vhci->lock);
+-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
++	if (!HCD_HW_ACCESSIBLE(hcd)) {
+ 		rc = -ESHUTDOWN;
+ 	} else {
+ 		/* vhci->rh_state = DUMMY_RH_RUNNING;
+diff --git a/drivers/usb/c67x00/c67x00-hcd.c b/drivers/usb/c67x00/c67x00-hcd.c
+index a22b887f4e9e..d3e1356d091e 100644
+--- a/drivers/usb/c67x00/c67x00-hcd.c
++++ b/drivers/usb/c67x00/c67x00-hcd.c
+@@ -264,7 +264,7 @@ static void c67x00_hcd_irq(struct c67x00_sie *sie, u16 int_status, u16 msg)
+ 	if (unlikely(hcd->state == HC_STATE_HALT))
+ 		return;
+ 
+-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
++	if (!HCD_HW_ACCESSIBLE(hcd))
+ 		return;
+ 
+ 	/* Handle Start of frame events */
+@@ -282,7 +282,7 @@ static int c67x00_hcd_start(struct usb_hcd *hcd)
+ {
+ 	hcd->uses_new_polling = 1;
+ 	hcd->state = HC_STATE_RUNNING;
+-	hcd->poll_rh = 1;
++	set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+ 
+ 	return 0;
+ }
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 53f14c82ff2e..f2fe7c8e991d 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -679,7 +679,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
+ 		spin_lock_irqsave(&hcd_root_hub_lock, flags);
+ 		urb = hcd->status_urb;
+ 		if (urb) {
+-			hcd->poll_pending = 0;
++			clear_bit(HCD_FLAG_POLL_PENDING, &hcd->flags);
+ 			hcd->status_urb = NULL;
+ 			urb->actual_length = length;
+ 			memcpy(urb->transfer_buffer, buffer, length);
+@@ -690,7 +690,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
+ 			spin_lock(&hcd_root_hub_lock);
+ 		} else {
+ 			length = 0;
+-			hcd->poll_pending = 1;
++			set_bit(HCD_FLAG_POLL_PENDING, &hcd->flags);
+ 		}
+ 		spin_unlock_irqrestore(&hcd_root_hub_lock, flags);
+ 	}
+@@ -699,7 +699,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
+ 	 * exceed that limit if HZ is 100. The math is more clunky than
+ 	 * maybe expected, this is to make sure that all timers for USB devices
+ 	 * fire at the same time to give the CPU a break inbetween */
+-	if (hcd->uses_new_polling ? hcd->poll_rh :
++	if (hcd->uses_new_polling ? HCD_POLL_RH(hcd) :
+ 			(length == 0 && hcd->status_urb != NULL))
+ 		mod_timer (&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4));
+ }
+@@ -736,7 +736,7 @@ static int rh_queue_status (struct usb_hcd *hcd, struct urb *urb)
+ 		mod_timer(&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4));
+ 
+ 	/* If a status change has already occurred, report it ASAP */
+-	else if (hcd->poll_pending)
++	else if (HCD_POLL_PENDING(hcd))
+ 		mod_timer(&hcd->rh_timer, jiffies);
+ 	retval = 0;
+  done:
+@@ -1150,8 +1150,7 @@ int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
+ 	 * finish unlinking the initial failed usb_set_address()
+ 	 * or device descriptor fetch.
+ 	 */
+-	if (!test_bit(HCD_FLAG_SAW_IRQ, &hcd->flags) &&
+-			!is_root_hub(urb->dev)) {
++	if (!HCD_SAW_IRQ(hcd) && !is_root_hub(urb->dev)) {
+ 		dev_warn(hcd->self.controller, "Unlink after no-IRQ?  "
+ 			"Controller is probably using the wrong IRQ.\n");
+ 		set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+@@ -2063,8 +2062,7 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)
+ 	 */
+ 	local_irq_save(flags);
+ 
+-	if (unlikely(hcd->state == HC_STATE_HALT ||
+-		     !test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) {
++	if (unlikely(hcd->state == HC_STATE_HALT || !HCD_HW_ACCESSIBLE(hcd))) {
+ 		rc = IRQ_NONE;
+ 	} else if (hcd->driver->irq(hcd) == IRQ_NONE) {
+ 		rc = IRQ_NONE;
+@@ -2098,7 +2096,7 @@ void usb_hc_died (struct usb_hcd *hcd)
+ 
+ 	spin_lock_irqsave (&hcd_root_hub_lock, flags);
+ 	if (hcd->rh_registered) {
+-		hcd->poll_rh = 0;
++		clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+ 
+ 		/* make khubd clean up old urbs and devices */
+ 		usb_set_device_state (hcd->self.root_hub,
+@@ -2301,7 +2299,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ 		       retval);
+ 		goto error_create_attr_group;
+ 	}
+-	if (hcd->uses_new_polling && hcd->poll_rh)
++	if (hcd->uses_new_polling && HCD_POLL_RH(hcd))
+ 		usb_hcd_poll_rh_status(hcd);
+ 	return retval;
+ 
+@@ -2320,11 +2318,11 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ 	mutex_unlock(&usb_bus_list_lock);
+ err_register_root_hub:
+ 	hcd->rh_pollable = 0;
+-	hcd->poll_rh = 0;
++	clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+ 	del_timer_sync(&hcd->rh_timer);
+ 	hcd->driver->stop(hcd);
+ 	hcd->state = HC_STATE_HALT;
+-	hcd->poll_rh = 0;
++	clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+ 	del_timer_sync(&hcd->rh_timer);
+ err_hcd_driver_start:
+ 	if (hcd->irq >= 0)
+@@ -2380,14 +2378,14 @@ void usb_remove_hcd(struct usb_hcd *hcd)
+ 	 * the hub_status_data() callback.
+ 	 */
+ 	hcd->rh_pollable = 0;
+-	hcd->poll_rh = 0;
++	clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+ 	del_timer_sync(&hcd->rh_timer);
+ 
+ 	hcd->driver->stop(hcd);
+ 	hcd->state = HC_STATE_HALT;
+ 
+ 	/* In case the HCD restarted the timer, stop it again. */
+-	hcd->poll_rh = 0;
++	clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+ 	del_timer_sync(&hcd->rh_timer);
+ 
+ 	if (hcd->irq >= 0)
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index 4f9e578cde9d..dc6546248ed9 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -1542,7 +1542,7 @@ static int dummy_hub_status (struct usb_hcd *hcd, char *buf)
+ 	dum = hcd_to_dummy (hcd);
+ 
+ 	spin_lock_irqsave (&dum->lock, flags);
+-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
++	if (!HCD_HW_ACCESSIBLE(hcd))
+ 		goto done;
+ 
+ 	if (dum->resuming && time_after_eq (jiffies, dum->re_timeout)) {
+@@ -1588,7 +1588,7 @@ static int dummy_hub_control (
+ 	int		retval = 0;
+ 	unsigned long	flags;
+ 
+-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
++	if (!HCD_HW_ACCESSIBLE(hcd))
+ 		return -ETIMEDOUT;
+ 
+ 	dum = hcd_to_dummy (hcd);
+@@ -1739,7 +1739,7 @@ static int dummy_bus_resume (struct usb_hcd *hcd)
+ 	dev_dbg (&hcd->self.root_hub->dev, "%s\n", __func__);
+ 
+ 	spin_lock_irq (&dum->lock);
+-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
++	if (!HCD_HW_ACCESSIBLE(hcd)) {
+ 		rc = -ESHUTDOWN;
+ 	} else {
+ 		dum->rh_state = DUMMY_RH_RUNNING;
+diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
+index df5546bb8367..4498efb49b95 100644
+--- a/drivers/usb/host/ehci-dbg.c
++++ b/drivers/usb/host/ehci-dbg.c
+@@ -712,7 +712,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
+ 
+ 	spin_lock_irqsave (&ehci->lock, flags);
+ 
+-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
++	if (!HCD_HW_ACCESSIBLE(hcd)) {
+ 		size = scnprintf (next, size,
+ 			"bus %s, device %s\n"
+ 			"%s\n"
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 8697ad19f313..2a19336c9824 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -642,7 +642,6 @@ static int ehci_run (struct usb_hcd *hcd)
+ 	u32			hcc_params;
+ 
+ 	hcd->uses_new_polling = 1;
+-	hcd->poll_rh = 0;
+ 
+ 	/* EHCI spec section 4.1 */
+ 	if ((retval = ehci_reset(ehci)) != 0) {
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 84e792d71c22..0931f5a7dec4 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -316,7 +316,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 	if (time_before (jiffies, ehci->next_statechange))
+ 		msleep(5);
+ 	spin_lock_irq (&ehci->lock);
+-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
++	if (!HCD_HW_ACCESSIBLE(hcd)) {
+ 		spin_unlock_irq(&ehci->lock);
+ 		return -ESHUTDOWN;
+ 	}
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 11a79c4f4a9d..233c288e3f93 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -1126,8 +1126,7 @@ submit_async (
+ #endif
+ 
+ 	spin_lock_irqsave (&ehci->lock, flags);
+-	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
+-			       &ehci_to_hcd(ehci)->flags))) {
++	if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) {
+ 		rc = -ESHUTDOWN;
+ 		goto done;
+ 	}
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 805ec633a652..d640346f9b56 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -880,8 +880,7 @@ static int intr_submit (
+ 
+ 	spin_lock_irqsave (&ehci->lock, flags);
+ 
+-	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
+-			&ehci_to_hcd(ehci)->flags))) {
++	if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) {
+ 		status = -ESHUTDOWN;
+ 		goto done_not_linked;
+ 	}
+@@ -1815,8 +1814,7 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb,
+ 
+ 	/* schedule ... need to lock */
+ 	spin_lock_irqsave (&ehci->lock, flags);
+-	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
+-			       &ehci_to_hcd(ehci)->flags))) {
++	if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) {
+ 		status = -ESHUTDOWN;
+ 		goto done_not_linked;
+ 	}
+@@ -2201,8 +2199,7 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
+ 
+ 	/* schedule ... need to lock */
+ 	spin_lock_irqsave (&ehci->lock, flags);
+-	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
+-			       &ehci_to_hcd(ehci)->flags))) {
++	if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) {
+ 		status = -ESHUTDOWN;
+ 		goto done_not_linked;
+ 	}
+diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c
+index 35742f8c7cda..9bfac657572e 100644
+--- a/drivers/usb/host/hwa-hc.c
++++ b/drivers/usb/host/hwa-hc.c
+@@ -159,7 +159,7 @@ static int hwahc_op_start(struct usb_hcd *usb_hcd)
+ 		goto error_set_cluster_id;
+ 
+ 	usb_hcd->uses_new_polling = 1;
+-	usb_hcd->poll_rh = 1;
++	set_bit(HCD_FLAG_POLL_RH, &usb_hcd->flags);
+ 	usb_hcd->state = HC_STATE_RUNNING;
+ 	result = 0;
+ out:
+@@ -776,7 +776,7 @@ static int hwahc_probe(struct usb_interface *usb_iface,
+ 		goto error_alloc;
+ 	}
+ 	usb_hcd->wireless = 1;
+-	usb_hcd->flags |= HCD_FLAG_SAW_IRQ;
++	set_bit(HCD_FLAG_SAW_IRQ, &usb_hcd->flags);
+ 	wusbhc = usb_hcd_to_wusbhc(usb_hcd);
+ 	hwahc = container_of(wusbhc, struct hwahc, wusbhc);
+ 	hwahc_init(hwahc);
+diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c
+index dbcafa29c775..d1a3dfc9a408 100644
+--- a/drivers/usb/host/isp1760-hcd.c
++++ b/drivers/usb/host/isp1760-hcd.c
+@@ -482,7 +482,6 @@ static int isp1760_run(struct usb_hcd *hcd)
+ 	u32 chipid;
+ 
+ 	hcd->uses_new_polling = 1;
+-	hcd->poll_rh = 0;
+ 
+ 	hcd->state = HC_STATE_RUNNING;
+ 	isp1760_enable_interrupts(hcd);
+@@ -1450,7 +1449,7 @@ static int isp1760_prepare_enqueue(struct isp1760_hcd *priv, struct urb *urb,
+ 	epnum = urb->ep->desc.bEndpointAddress;
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &priv_to_hcd(priv)->flags)) {
++	if (!HCD_HW_ACCESSIBLE(priv_to_hcd(priv))) {
+ 		rc = -ESHUTDOWN;
+ 		goto done;
+ 	}
+diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
+index 8ad2441b0284..36abd2baa3ea 100644
+--- a/drivers/usb/host/ohci-dbg.c
++++ b/drivers/usb/host/ohci-dbg.c
+@@ -645,7 +645,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
+ 		hcd->product_desc,
+ 		hcd_name);
+ 
+-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
++	if (!HCD_HW_ACCESSIBLE(hcd)) {
+ 		size -= scnprintf (next, size,
+ 			"SUSPENDED (no register access)\n");
+ 		goto done;
+@@ -687,7 +687,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
+ 	next += temp;
+ 
+ 	temp = scnprintf (next, size, "hub poll timer %s\n",
+-			ohci_to_hcd(ohci)->poll_rh ? "ON" : "off");
++			HCD_POLL_RH(ohci_to_hcd(ohci)) ? "ON" : "off");
+ 	size -= temp;
+ 	next += temp;
+ 
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index 02864a237a2c..c3b4ccc7337b 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -212,7 +212,7 @@ static int ohci_urb_enqueue (
+ 	spin_lock_irqsave (&ohci->lock, flags);
+ 
+ 	/* don't submit to a dead HC */
+-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
++	if (!HCD_HW_ACCESSIBLE(hcd)) {
+ 		retval = -ENODEV;
+ 		goto fail;
+ 	}
+@@ -685,7 +685,7 @@ static int ohci_run (struct ohci_hcd *ohci)
+ 	}
+ 
+ 	/* use rhsc irqs after khubd is fully initialized */
+-	hcd->poll_rh = 1;
++	set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+ 	hcd->uses_new_polling = 1;
+ 
+ 	/* start controller operations */
+@@ -822,7 +822,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
+ 	else if (ints & OHCI_INTR_RD) {
+ 		ohci_vdbg(ohci, "resume detect\n");
+ 		ohci_writel(ohci, OHCI_INTR_RD, ®s->intrstatus);
+-		hcd->poll_rh = 1;
++		set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+ 		if (ohci->autostop) {
+ 			spin_lock (&ohci->lock);
+ 			ohci_rh_resume (ohci);
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index 65cac8cc8921..4dd39022c388 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -284,7 +284,7 @@ static int ohci_bus_suspend (struct usb_hcd *hcd)
+ 
+ 	spin_lock_irq (&ohci->lock);
+ 
+-	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
++	if (unlikely(!HCD_HW_ACCESSIBLE(hcd)))
+ 		rc = -ESHUTDOWN;
+ 	else
+ 		rc = ohci_rh_suspend (ohci, 0);
+@@ -302,7 +302,7 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
+ 
+ 	spin_lock_irq (&ohci->lock);
+ 
+-	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
++	if (unlikely(!HCD_HW_ACCESSIBLE(hcd)))
+ 		rc = -ESHUTDOWN;
+ 	else
+ 		rc = ohci_rh_resume (ohci);
+@@ -489,7 +489,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ 	unsigned long	flags;
+ 
+ 	spin_lock_irqsave (&ohci->lock, flags);
+-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
++	if (!HCD_HW_ACCESSIBLE(hcd))
+ 		goto done;
+ 
+ 	/* undocumented erratum seen on at least rev D */
+@@ -533,8 +533,12 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ 		}
+ 	}
+ 
+-	hcd->poll_rh = ohci_root_hub_state_changes(ohci, changed,
+-			any_connected, rhsc_status);
++	if (ohci_root_hub_state_changes(ohci, changed,
++			any_connected, rhsc_status))
++		set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
++	else
++		clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
++
+ 
+ done:
+ 	spin_unlock_irqrestore (&ohci->lock, flags);
+@@ -701,7 +705,7 @@ static int ohci_hub_control (
+ 	u32		temp;
+ 	int		retval = 0;
+ 
+-	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
++	if (unlikely(!HCD_HW_ACCESSIBLE(hcd)))
+ 		return -ESHUTDOWN;
+ 
+ 	switch (typeReq) {
+diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
+index f608dfd09a8a..d9c85a292737 100644
+--- a/drivers/usb/host/oxu210hp-hcd.c
++++ b/drivers/usb/host/oxu210hp-hcd.c
+@@ -1641,8 +1641,7 @@ static int submit_async(struct oxu_hcd	*oxu, struct urb *urb,
+ #endif
+ 
+ 	spin_lock_irqsave(&oxu->lock, flags);
+-	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
+-			       &oxu_to_hcd(oxu)->flags))) {
++	if (unlikely(!HCD_HW_ACCESSIBLE(oxu_to_hcd(oxu)))) {
+ 		rc = -ESHUTDOWN;
+ 		goto done;
+ 	}
+@@ -2209,8 +2208,7 @@ static int intr_submit(struct oxu_hcd *oxu, struct urb *urb,
+ 
+ 	spin_lock_irqsave(&oxu->lock, flags);
+ 
+-	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
+-			       &oxu_to_hcd(oxu)->flags))) {
++	if (unlikely(!HCD_HW_ACCESSIBLE(oxu_to_hcd(oxu)))) {
+ 		status = -ESHUTDOWN;
+ 		goto done;
+ 	}
+@@ -2715,7 +2713,6 @@ static int oxu_run(struct usb_hcd *hcd)
+ 	u32 temp, hcc_params;
+ 
+ 	hcd->uses_new_polling = 1;
+-	hcd->poll_rh = 0;
+ 
+ 	/* EHCI spec section 4.1 */
+ 	retval = ehci_reset(oxu);
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index d1dce2166eff..2743ec770f0c 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -140,7 +140,7 @@ static void finish_reset(struct uhci_hcd *uhci)
+ 	uhci->rh_state = UHCI_RH_RESET;
+ 	uhci->is_stopped = UHCI_IS_STOPPED;
+ 	uhci_to_hcd(uhci)->state = HC_STATE_HALT;
+-	uhci_to_hcd(uhci)->poll_rh = 0;
++	clear_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags);
+ 
+ 	uhci->dead = 0;		/* Full reset resurrects the controller */
+ }
+@@ -344,7 +344,10 @@ __acquires(uhci->lock)
+ 	/* If interrupts don't work and remote wakeup is enabled then
+ 	 * the suspended root hub needs to be polled.
+ 	 */
+-	uhci_to_hcd(uhci)->poll_rh = (!int_enable && wakeup_enable);
++	if (!int_enable && wakeup_enable)
++		set_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags);
++	else
++		clear_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags);
+ 
+ 	uhci_scan_schedule(uhci);
+ 	uhci_fsbr_off(uhci);
+@@ -363,7 +366,7 @@ static void start_rh(struct uhci_hcd *uhci)
+ 			uhci->io_addr + USBINTR);
+ 	mb();
+ 	uhci->rh_state = UHCI_RH_RUNNING;
+-	uhci_to_hcd(uhci)->poll_rh = 1;
++	set_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags);
+ }
+ 
+ static void wakeup_rh(struct uhci_hcd *uhci)
+@@ -733,7 +736,7 @@ static void uhci_stop(struct usb_hcd *hcd)
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 
+ 	spin_lock_irq(&uhci->lock);
+-	if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) && !uhci->dead)
++	if (HCD_HW_ACCESSIBLE(hcd) && !uhci->dead)
+ 		uhci_hc_died(uhci);
+ 	uhci_scan_schedule(uhci);
+ 	spin_unlock_irq(&uhci->lock);
+@@ -750,7 +753,7 @@ static int uhci_rh_suspend(struct usb_hcd *hcd)
+ 	int rc = 0;
+ 
+ 	spin_lock_irq(&uhci->lock);
+-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
++	if (!HCD_HW_ACCESSIBLE(hcd))
+ 		rc = -ESHUTDOWN;
+ 	else if (uhci->dead)
+ 		;		/* Dead controllers tell no tales */
+@@ -777,7 +780,7 @@ static int uhci_rh_resume(struct usb_hcd *hcd)
+ 	int rc = 0;
+ 
+ 	spin_lock_irq(&uhci->lock);
+-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
++	if (!HCD_HW_ACCESSIBLE(hcd))
+ 		rc = -ESHUTDOWN;
+ 	else if (!uhci->dead)
+ 		wakeup_rh(uhci);
+@@ -793,7 +796,7 @@ static int uhci_pci_suspend(struct usb_hcd *hcd)
+ 	dev_dbg(uhci_dev(uhci), "%s\n", __func__);
+ 
+ 	spin_lock_irq(&uhci->lock);
+-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
++	if (!HCD_HW_ACCESSIBLE(hcd) || uhci->dead)
+ 		goto done_okay;		/* Already suspended or dead */
+ 
+ 	if (uhci->rh_state > UHCI_RH_SUSPENDED) {
+@@ -807,7 +810,7 @@ static int uhci_pci_suspend(struct usb_hcd *hcd)
+ 	 */
+ 	pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0);
+ 	mb();
+-	hcd->poll_rh = 0;
++	clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+ 
+ 	/* FIXME: Enable non-PME# remote wakeup? */
+ 
+@@ -860,7 +863,7 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
+ 	 * the suspended root hub needs to be polled.
+ 	 */
+ 	if (!uhci->RD_enable && hcd->self.root_hub->do_remote_wakeup) {
+-		hcd->poll_rh = 1;
++		set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+ 		usb_hcd_poll_rh_status(hcd);
+ 	}
+ 	return 0;
+diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
+index 8270055848ca..f0c58116c0ad 100644
+--- a/drivers/usb/host/uhci-hub.c
++++ b/drivers/usb/host/uhci-hub.c
+@@ -190,7 +190,7 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
+ 	spin_lock_irqsave(&uhci->lock, flags);
+ 
+ 	uhci_scan_schedule(uhci);
+-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
++	if (!HCD_HW_ACCESSIBLE(hcd) || uhci->dead)
+ 		goto done;
+ 	uhci_check_ports(uhci);
+ 
+@@ -246,7 +246,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+ 	u16 wPortChange, wPortStatus;
+ 	unsigned long flags;
+ 
+-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
++	if (!HCD_HW_ACCESSIBLE(hcd) || uhci->dead)
+ 		return -ETIMEDOUT;
+ 
+ 	spin_lock_irqsave(&uhci->lock, flags);
+diff --git a/drivers/usb/host/whci/hcd.c b/drivers/usb/host/whci/hcd.c
+index e0d3401285c8..72b6892fda67 100644
+--- a/drivers/usb/host/whci/hcd.c
++++ b/drivers/usb/host/whci/hcd.c
+@@ -68,7 +68,7 @@ static int whc_start(struct usb_hcd *usb_hcd)
+ 	whc_write_wusbcmd(whc, WUSBCMD_RUN, WUSBCMD_RUN);
+ 
+ 	usb_hcd->uses_new_polling = 1;
+-	usb_hcd->poll_rh = 1;
++	set_bit(HCD_FLAG_POLL_RH, &usb_hcd->flags);
+ 	usb_hcd->state = HC_STATE_RUNNING;
+ 
+ out:
+diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
+index 343f1047f5d0..5e73386b3899 100644
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -427,7 +427,6 @@ int xhci_run(struct usb_hcd *hcd)
+ 	void (*doorbell)(struct xhci_hcd *) = NULL;
+ 
+ 	hcd->uses_new_polling = 1;
+-	hcd->poll_rh = 0;
+ 
+ 	xhci_dbg(xhci, "xhci_run\n");
+ #if 0	/* FIXME: MSI not setup yet */
+@@ -733,7 +732,7 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
+ 		ret = -EINVAL;
+ 		goto exit;
+ 	}
+-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
++	if (!HCD_HW_ACCESSIBLE(hcd)) {
+ 		if (!in_interrupt())
+ 			xhci_dbg(xhci, "urb submitted during PCI suspend\n");
+ 		ret = -ESHUTDOWN;
+diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c
+index 92e85e027cfb..43233c397b6e 100644
+--- a/drivers/usb/musb/musb_virthub.c
++++ b/drivers/usb/musb/musb_virthub.c
+@@ -244,7 +244,7 @@ int musb_hub_control(
+ 
+ 	spin_lock_irqsave(&musb->lock, flags);
+ 
+-	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) {
++	if (unlikely(!HCD_HW_ACCESSIBLE(hcd))) {
+ 		spin_unlock_irqrestore(&musb->lock, flags);
+ 		return -ESHUTDOWN;
+ 	}
+diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
+index 9b867e64a0f4..f8f8fa7a56e8 100644
+--- a/include/linux/usb/hcd.h
++++ b/include/linux/usb/hcd.h
+@@ -89,19 +89,31 @@ struct usb_hcd {
+ 	 */
+ 	const struct hc_driver	*driver;	/* hw-specific hooks */
+ 
+-	/* Flags that need to be manipulated atomically */
++	/* Flags that need to be manipulated atomically because they can
++	 * change while the host controller is running.  Always use
++	 * set_bit() or clear_bit() to change their values.
++	 */
+ 	unsigned long		flags;
+-#define HCD_FLAG_HW_ACCESSIBLE	0x00000001
+-#define HCD_FLAG_SAW_IRQ	0x00000002
++#define HCD_FLAG_HW_ACCESSIBLE		0	/* at full power */
++#define HCD_FLAG_SAW_IRQ		1
++#define HCD_FLAG_POLL_RH		2	/* poll for rh status? */
++#define HCD_FLAG_POLL_PENDING		3	/* status has changed? */
++
++	/* The flags can be tested using these macros; they are likely to
++	 * be slightly faster than test_bit().
++	 */
++#define HCD_HW_ACCESSIBLE(hcd)	((hcd)->flags & (1U << HCD_FLAG_HW_ACCESSIBLE))
++#define HCD_SAW_IRQ(hcd)	((hcd)->flags & (1U << HCD_FLAG_SAW_IRQ))
++#define HCD_POLL_RH(hcd)	((hcd)->flags & (1U << HCD_FLAG_POLL_RH))
++#define HCD_POLL_PENDING(hcd)	((hcd)->flags & (1U << HCD_FLAG_POLL_PENDING))
+ 
++	/* Flags that get set only during HCD registration or removal. */
+ 	unsigned		rh_registered:1;/* is root hub registered? */
+ 	unsigned		rh_pollable:1;	/* may we poll the root hub? */
+ 
+ 	/* The next flag is a stopgap, to be removed when all the HCDs
+ 	 * support the new root-hub polling mechanism. */
+ 	unsigned		uses_new_polling:1;
+-	unsigned		poll_rh:1;	/* poll for rh status? */
+-	unsigned		poll_pending:1;	/* status has changed? */
+ 	unsigned		wireless:1;	/* Wireless USB HCD */
+ 	unsigned		authorized_default:1;
+ 	unsigned		has_tt:1;	/* Integrated TT in root hub */

commit 37cd681c022a0a46ebcff025897a57457d3ca8cd
+Author: Alan Stern 
+Date:   Fri May 21 17:08:21 2010 -0400
+
+    USB: EHCI: make CONFIG_USB_EHCI_TT_NEWSCHED default to Y
+    
+    This patch (as1382) changes the USB_EHCI_TT_NEWSCHED Kconfig option to
+    be non-experimental and to default to Y.  This option has existed for
+    a long time, and I have not heard any complaints concerning it.  By
+    contrast, several people have reported that their devices could be
+    made to work only by enabling the option.
+    
+    The point of changing the default is to cause the option to be enabled
+    by distros that simply use the default settings for esoteric things
+    like this.
+    
+    This change was motivated by Bugzilla #15649.
+    
+    Signed-off-by: Alan Stern 
+    CC: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
+index f865be2276d4..2d926cec0725 100644
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -72,8 +72,9 @@ config USB_EHCI_ROOT_HUB_TT
+ 	  from ARC, and has since changed hands a few times.
+ 
+ config USB_EHCI_TT_NEWSCHED
+-	bool "Improved Transaction Translator scheduling (EXPERIMENTAL)"
+-	depends on USB_EHCI_HCD && EXPERIMENTAL
++	bool "Improved Transaction Translator scheduling"
++	depends on USB_EHCI_HCD
++	default y
+ 	---help---
+ 	  This changes the periodic scheduling code to fill more of the low
+ 	  and full speed bandwidth available from the Transaction Translator
+@@ -84,9 +85,11 @@ config USB_EHCI_TT_NEWSCHED
+ 	  If you have multiple periodic low/fullspeed devices connected to a
+ 	  highspeed USB hub which is connected to a highspeed USB Host
+ 	  Controller, and some of those devices will not work correctly
+-	  (possibly due to "ENOSPC" or "-28" errors), say Y.
++	  (possibly due to "ENOSPC" or "-28" errors), say Y.  Conversely, if
++	  you have only one such device and it doesn't work, you could try
++	  saying N.
+ 
+-	  If unsure, say N.
++	  If unsure, say Y.
+ 
+ config USB_EHCI_BIG_ENDIAN_MMIO
+ 	bool

commit ba297edde4dd7376832bafb23e032a40d5928b56
+Author: Alan Stern 
+Date:   Wed Jun 9 17:34:39 2010 -0400
+
+    USB: UHCI: acquire spinlock before calling start_rh()
+    
+    This patch (as1392) fixes a bug in uhci-hcd: The start_rh() routine is
+    supposed to be called with the private spinlock held.  If an IRQ comes
+    in at just the wrong time, the driver will think the controller has
+    died when in fact it simply hasn't start yet.
+    
+    The patch also addresses some issues that may prevent an URB from
+    being unlinked after the controller has stopped.  This is an abnormal
+    occurrence (ordinarily the controller stops only when the entire bus
+    is suspended and hence there are no active URBs), so the pathways
+    haven't gotten much testing.  These two changes may be a little more
+    than is strictly necessary, but clearly they won't hurt.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 6637e52736dd..d1dce2166eff 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -691,7 +691,9 @@ static int uhci_start(struct usb_hcd *hcd)
+ 
+ 	configure_hc(uhci);
+ 	uhci->is_initialized = 1;
++	spin_lock_irq(&uhci->lock);
+ 	start_rh(uhci);
++	spin_unlock_irq(&uhci->lock);
+ 	return 0;
+ 
+ /*
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index acd582c02802..d3ade4018487 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -565,7 +565,7 @@ static void uhci_unlink_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ 	qh->unlink_frame = uhci->frame_number;
+ 
+ 	/* Force an interrupt so we know when the QH is fully unlinked */
+-	if (list_empty(&uhci->skel_unlink_qh->node))
++	if (list_empty(&uhci->skel_unlink_qh->node) || uhci->is_stopped)
+ 		uhci_set_next_interrupt(uhci);
+ 
+ 	/* Move the QH from its old list to the end of the unlinking list */
+@@ -1667,7 +1667,7 @@ static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ 			qh->advance_jiffies = jiffies;
+ 			goto done;
+ 		}
+-		ret = 0;
++		ret = uhci->is_stopped;
+ 	}
+ 
+ 	/* The queue hasn't advanced; check for timeout */

commit c548795abe0d3520b74e18f23ca0a0d72deddab9
+Author: Alan Stern 
+Date:   Wed Jun 9 17:34:27 2010 -0400
+
+    USB: add check to detect host controller hardware removal
+    
+    This patch (as1391) fixes a problem that can occur when USB host
+    controller hardware is hot-unplugged.  If no interrupts are generated
+    by the unplug then the HCD may not realize that the controller is
+    gone, and the subsequent unbind may hang waiting for interrupts that
+    never arrive.
+    
+    The solution (for PCI-based controllers) is to call the HCD's
+    interrupt handler at the start of usb_hcd_pci_remove().  If the
+    hardware is gone, the handler will realize this when it tries to read
+    the controller's status register.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index 1cf2d1e79a5c..7e2d5271b0c9 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -292,6 +292,14 @@ void usb_hcd_pci_remove(struct pci_dev *dev)
+ 	if (!hcd)
+ 		return;
+ 
++	/* Fake an interrupt request in order to give the driver a chance
++	 * to test whether the controller hardware has been removed (e.g.,
++	 * cardbus physical eject).
++	 */
++	local_irq_disable();
++	usb_hcd_irq(0, hcd);
++	local_irq_enable();
++
+ 	usb_remove_hcd(hcd);
+ 	if (hcd->driver->flags & HCD_MEMORY) {
+ 		iounmap(hcd->regs);

commit 6d88e6792574497bfac9a81403cc47712040636f
+Author: Alan Stern 
+Date:   Wed Jun 9 17:34:17 2010 -0400
+
+    USB: don't stop root-hub status polls too soon
+    
+    This patch (as1390) fixes a problem that crops up when a UHCI host
+    controller is unbound from uhci-hcd while there are still some active
+    URBs.  The URBs have to be unlinked when the root hub is unregistered,
+    and uhci-hcd relies upon root-hub status polls as part of its
+    unlinking procedure.  But usb_hcd_poll_rh_status() won't make those
+    status calls if hcd->rh_registered is clear, and the flag is cleared
+    _before_ the unregistration takes place.
+    
+    Since hcd->rh_registered is used for other things and needs to be
+    cleared early, the solution is to add a new flag (rh_pollable) and use
+    it instead.  It gets cleared _after_ the root hub is unregistered.
+    
+    Now that the status polls don't end too soon, we have to make sure
+    they also don't occur too late -- after the root hub's usb_device
+    structure or the HCD's private structures are deallocated.  Therefore
+    the patch adds usb_get_device() and usb_put_device() calls to protect
+    the root hub structure, and it adds an extra del_timer_sync() to
+    prevent the root-hub timer from causing an unexpected status poll.
+    
+    This additional complexity would not be needed if the HCD framework
+    had provided separate stop() and release() callbacks instead of just
+    stop().  This lack could be fixed at some future time (although it
+    would require changes to every host controller driver); when that
+    happens this patch won't be needed any more.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index caae4625a1f1..53f14c82ff2e 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -667,7 +667,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
+ 	unsigned long	flags;
+ 	char		buffer[6];	/* Any root hubs with > 31 ports? */
+ 
+-	if (unlikely(!hcd->rh_registered))
++	if (unlikely(!hcd->rh_pollable))
+ 		return;
+ 	if (!hcd->uses_new_polling && !hcd->status_urb)
+ 		return;
+@@ -2217,6 +2217,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ 		retval = -ENOMEM;
+ 		goto err_allocate_root_hub;
+ 	}
++	hcd->self.root_hub = rhdev;
+ 
+ 	switch (hcd->driver->flags & HCD_MASK) {
+ 	case HCD_USB11:
+@@ -2231,7 +2232,6 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ 	default:
+ 		goto err_set_rh_speed;
+ 	}
+-	hcd->self.root_hub = rhdev;
+ 
+ 	/* wakeup flag init defaults to "everything works" for root hubs,
+ 	 * but drivers can override it in reset() if needed, along with
+@@ -2246,6 +2246,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ 		dev_err(hcd->self.controller, "can't setup\n");
+ 		goto err_hcd_driver_setup;
+ 	}
++	hcd->rh_pollable = 1;
+ 
+ 	/* NOTE: root hub and controller capabilities may not be the same */
+ 	if (device_can_wakeup(hcd->self.controller)
+@@ -2315,9 +2316,12 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ 	cancel_work_sync(&hcd->wakeup_work);
+ #endif
+ 	mutex_lock(&usb_bus_list_lock);
+-	usb_disconnect(&hcd->self.root_hub);
++	usb_disconnect(&rhdev);		/* Sets rhdev to NULL */
+ 	mutex_unlock(&usb_bus_list_lock);
+ err_register_root_hub:
++	hcd->rh_pollable = 0;
++	hcd->poll_rh = 0;
++	del_timer_sync(&hcd->rh_timer);
+ 	hcd->driver->stop(hcd);
+ 	hcd->state = HC_STATE_HALT;
+ 	hcd->poll_rh = 0;
+@@ -2328,8 +2332,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ err_request_irq:
+ err_hcd_driver_setup:
+ err_set_rh_speed:
+-	hcd->self.root_hub = NULL;
+-	usb_put_dev(rhdev);
++	usb_put_dev(hcd->self.root_hub);
+ err_allocate_root_hub:
+ 	usb_deregister_bus(&hcd->self);
+ err_register_bus:
+@@ -2348,9 +2351,12 @@ EXPORT_SYMBOL_GPL(usb_add_hcd);
+  */
+ void usb_remove_hcd(struct usb_hcd *hcd)
+ {
++	struct usb_device *rhdev = hcd->self.root_hub;
++
+ 	dev_info(hcd->self.controller, "remove, state %x\n", hcd->state);
+ 
+-	sysfs_remove_group(&hcd->self.root_hub->dev.kobj, &usb_bus_attr_group);
++	usb_get_dev(rhdev);
++	sysfs_remove_group(&rhdev->dev.kobj, &usb_bus_attr_group);
+ 
+ 	if (HC_IS_RUNNING (hcd->state))
+ 		hcd->state = HC_STATE_QUIESCING;
+@@ -2365,17 +2371,29 @@ void usb_remove_hcd(struct usb_hcd *hcd)
+ #endif
+ 
+ 	mutex_lock(&usb_bus_list_lock);
+-	usb_disconnect(&hcd->self.root_hub);
++	usb_disconnect(&rhdev);		/* Sets rhdev to NULL */
+ 	mutex_unlock(&usb_bus_list_lock);
+ 
++	/* Prevent any more root-hub status calls from the timer.
++	 * The HCD might still restart the timer (if a port status change
++	 * interrupt occurs), but usb_hcd_poll_rh_status() won't invoke
++	 * the hub_status_data() callback.
++	 */
++	hcd->rh_pollable = 0;
++	hcd->poll_rh = 0;
++	del_timer_sync(&hcd->rh_timer);
++
+ 	hcd->driver->stop(hcd);
+ 	hcd->state = HC_STATE_HALT;
+ 
++	/* In case the HCD restarted the timer, stop it again. */
+ 	hcd->poll_rh = 0;
+ 	del_timer_sync(&hcd->rh_timer);
+ 
+ 	if (hcd->irq >= 0)
+ 		free_irq(hcd->irq, hcd);
++
++	usb_put_dev(hcd->self.root_hub);
+ 	usb_deregister_bus(&hcd->self);
+ 	hcd_buffer_destroy(hcd);
+ }
+diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
+index 2e3a4ea1a3da..11b638195901 100644
+--- a/include/linux/usb/hcd.h
++++ b/include/linux/usb/hcd.h
+@@ -95,6 +95,7 @@ struct usb_hcd {
+ #define HCD_FLAG_SAW_IRQ	0x00000002
+ 
+ 	unsigned		rh_registered:1;/* is root hub registered? */
++	unsigned		rh_pollable:1;	/* may we poll the root hub? */
+ 
+ 	/* The next flag is a stopgap, to be removed when all the HCDs
+ 	 * support the new root-hub polling mechanism. */

commit 96e077ae347912dfce0e93f5958efc3ed6f311f4
+Author: Alan Stern 
+Date:   Wed Jun 9 17:34:05 2010 -0400
+
+    USB: fix failure path in usb_add_hcd()
+    
+    This patch (as1389) fixes some errors in the failure pathway of
+    usb_add_hcd().  The actions it takes ought to be exactly the same as
+    those taken by usb_remove_hcd(), but they aren't.
+    
+    In one case (removal of the usb_bus_attr_group), the two routines are
+    brought into agreement by changing usb_remove_hcd().  All the other
+    discrepancies are fixed by changing usb_add_hcd().
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 12742f152f43..caae4625a1f1 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -2229,7 +2229,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ 		rhdev->speed = USB_SPEED_SUPER;
+ 		break;
+ 	default:
+-		goto err_allocate_root_hub;
++		goto err_set_rh_speed;
+ 	}
+ 	hcd->self.root_hub = rhdev;
+ 
+@@ -2305,16 +2305,29 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ 	return retval;
+ 
+ error_create_attr_group:
++	if (HC_IS_RUNNING(hcd->state))
++		hcd->state = HC_STATE_QUIESCING;
++	spin_lock_irq(&hcd_root_hub_lock);
++	hcd->rh_registered = 0;
++	spin_unlock_irq(&hcd_root_hub_lock);
++
++#ifdef CONFIG_USB_SUSPEND
++	cancel_work_sync(&hcd->wakeup_work);
++#endif
+ 	mutex_lock(&usb_bus_list_lock);
+ 	usb_disconnect(&hcd->self.root_hub);
+ 	mutex_unlock(&usb_bus_list_lock);
+ err_register_root_hub:
+ 	hcd->driver->stop(hcd);
++	hcd->state = HC_STATE_HALT;
++	hcd->poll_rh = 0;
++	del_timer_sync(&hcd->rh_timer);
+ err_hcd_driver_start:
+ 	if (hcd->irq >= 0)
+ 		free_irq(irqnum, hcd);
+ err_request_irq:
+ err_hcd_driver_setup:
++err_set_rh_speed:
+ 	hcd->self.root_hub = NULL;
+ 	usb_put_dev(rhdev);
+ err_allocate_root_hub:
+@@ -2337,6 +2350,8 @@ void usb_remove_hcd(struct usb_hcd *hcd)
+ {
+ 	dev_info(hcd->self.controller, "remove, state %x\n", hcd->state);
+ 
++	sysfs_remove_group(&hcd->self.root_hub->dev.kobj, &usb_bus_attr_group);
++
+ 	if (HC_IS_RUNNING (hcd->state))
+ 		hcd->state = HC_STATE_QUIESCING;
+ 
+@@ -2349,7 +2364,6 @@ void usb_remove_hcd(struct usb_hcd *hcd)
+ 	cancel_work_sync(&hcd->wakeup_work);
+ #endif
+ 
+-	sysfs_remove_group(&hcd->self.root_hub->dev.kobj, &usb_bus_attr_group);
+ 	mutex_lock(&usb_bus_list_lock);
+ 	usb_disconnect(&hcd->self.root_hub);
+ 	mutex_unlock(&usb_bus_list_lock);

commit e6da54d84f9286edbe4c92ff5023ff481ce2a5c9
+Author: Alan Stern 
+Date:   Thu Aug 5 13:17:10 2010 -0400
+
+    SCSI: remove fake "address-of" expression
+    
+    Fake "address-of" expressions that evaluate to NULL generally confuse
+    readers and can provoke compiler warnings.  This patch (as1411) removes
+    one such fake expression, using an "#ifdef" in its place.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
+index 026295e2c539..b4056d14f812 100644
+--- a/drivers/scsi/scsi_priv.h
++++ b/drivers/scsi/scsi_priv.h
+@@ -148,8 +148,6 @@ static inline void scsi_netlink_exit(void) {}
+ /* scsi_pm.c */
+ #ifdef CONFIG_PM_OPS
+ extern const struct dev_pm_ops scsi_bus_pm_ops;
+-#else /* CONFIG_PM_OPS */
+-#define scsi_bus_pm_ops		(*NULL)
+ #endif
+ #ifdef CONFIG_PM_RUNTIME
+ extern void scsi_autopm_get_target(struct scsi_target *);
+diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
+index 562fb3bce261..c3f67373a4f8 100644
+--- a/drivers/scsi/scsi_sysfs.c
++++ b/drivers/scsi/scsi_sysfs.c
+@@ -381,7 +381,9 @@ struct bus_type scsi_bus_type = {
+         .name		= "scsi",
+         .match		= scsi_bus_match,
+ 	.uevent		= scsi_bus_uevent,
++#ifdef CONFIG_PM_OPS
+ 	.pm		= &scsi_bus_pm_ops,
++#endif
+ };
+ EXPORT_SYMBOL_GPL(scsi_bus_type);
+ 

commit 26845f585fad66dc23d87dad89d403cd64b48780
+Author: Alan Stern 
+Date:   Thu Aug 5 13:17:10 2010 -0400
+
+    [SCSI] remove fake "address-of" expression
+    
+    Fake "address-of" expressions that evaluate to NULL generally confuse
+    readers and can provoke compiler warnings.  This patch (as1411)
+    removes one such fake expression introduced by:
+    
+    commit db5bd1e0b505c54ff492172ce4abc245cf6cd639
+    Author: Alan Stern 
+    Date:   Thu Jun 17 10:36:49 2010 -0400
+    
+        [SCSI] convert to the new PM framework
+    
+    using an "#ifdef" in its place.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
+index 026295e2c539..b4056d14f812 100644
+--- a/drivers/scsi/scsi_priv.h
++++ b/drivers/scsi/scsi_priv.h
+@@ -148,8 +148,6 @@ static inline void scsi_netlink_exit(void) {}
+ /* scsi_pm.c */
+ #ifdef CONFIG_PM_OPS
+ extern const struct dev_pm_ops scsi_bus_pm_ops;
+-#else /* CONFIG_PM_OPS */
+-#define scsi_bus_pm_ops		(*NULL)
+ #endif
+ #ifdef CONFIG_PM_RUNTIME
+ extern void scsi_autopm_get_target(struct scsi_target *);
+diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
+index 562fb3bce261..c3f67373a4f8 100644
+--- a/drivers/scsi/scsi_sysfs.c
++++ b/drivers/scsi/scsi_sysfs.c
+@@ -381,7 +381,9 @@ struct bus_type scsi_bus_type = {
+         .name		= "scsi",
+         .match		= scsi_bus_match,
+ 	.uevent		= scsi_bus_uevent,
++#ifdef CONFIG_PM_OPS
+ 	.pm		= &scsi_bus_pm_ops,
++#endif
+ };
+ EXPORT_SYMBOL_GPL(scsi_bus_type);
+ 

commit f3ec4f87d607f40497afdb5ac03f11e2ea253d52
+Author: Alan Stern 
+Date:   Tue Jun 8 15:23:51 2010 -0400
+
+    PCI: change device runtime PM settings for probe and remove
+    
+    This patch (as1388) changes the way the PCI core handles runtime PM
+    settings when probing or unbinding drivers.  Now the core will make
+    sure the device is enabled for runtime PM, with a usage count >= 1,
+    when a driver is probed.  It does the same when calling a driver's
+    remove method.
+    
+    If the driver wants to use runtime PM, all it has to do is call
+    pm_runtime_pu_noidle() near the end of its probe routine (to cancel
+    the core's usage increment) and pm_runtime_get_noresume() near the
+    start of its remove routine (to restore the usage count).  It does not
+    need to mess around with setting the runtime state to enabled,
+    disabled, active, or suspended.
+    
+    The patch updates e1000e and r8169, the only PCI drivers that already
+    use the existing runtime PM interface.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Rafael J. Wysocki 
+    Signed-off-by: Jesse Barnes 
+
+diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
+index 57a7e41da69e..4afc8dd9b935 100644
+--- a/drivers/net/e1000e/netdev.c
++++ b/drivers/net/e1000e/netdev.c
+@@ -5721,11 +5721,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
+ 
+ 	e1000_print_device_info(adapter);
+ 
+-	if (pci_dev_run_wake(pdev)) {
+-		pm_runtime_set_active(&pdev->dev);
+-		pm_runtime_enable(&pdev->dev);
+-	}
+-	pm_schedule_suspend(&pdev->dev, MSEC_PER_SEC);
++	if (pci_dev_run_wake(pdev))
++		pm_runtime_put_noidle(&pdev->dev);
+ 
+ 	return 0;
+ 
+@@ -5771,8 +5768,6 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+ 	bool down = test_bit(__E1000_DOWN, &adapter->state);
+ 
+-	pm_runtime_get_sync(&pdev->dev);
+-
+ 	/*
+ 	 * flush_scheduled work may reschedule our watchdog task, so
+ 	 * explicitly disable watchdog tasks from being rescheduled
+@@ -5797,11 +5792,8 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
+ 		clear_bit(__E1000_DOWN, &adapter->state);
+ 	unregister_netdev(netdev);
+ 
+-	if (pci_dev_run_wake(pdev)) {
+-		pm_runtime_disable(&pdev->dev);
+-		pm_runtime_set_suspended(&pdev->dev);
+-	}
+-	pm_runtime_put_noidle(&pdev->dev);
++	if (pci_dev_run_wake(pdev))
++		pm_runtime_get_noresume(&pdev->dev);
+ 
+ 	/*
+ 	 * Release control of h/w to f/w.  If f/w is AMT enabled, this
+diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
+index cdc6a5c2e70d..c982a4763bef 100644
+--- a/drivers/net/r8169.c
++++ b/drivers/net/r8169.c
+@@ -3219,11 +3219,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 
+ 	device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL);
+ 
+-	if (pci_dev_run_wake(pdev)) {
+-		pm_runtime_set_active(&pdev->dev);
+-		pm_runtime_enable(&pdev->dev);
+-	}
+-	pm_runtime_idle(&pdev->dev);
++	if (pci_dev_run_wake(pdev))
++		pm_runtime_put_noidle(&pdev->dev);
+ 
+ out:
+ 	return rc;
+@@ -3246,17 +3243,12 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct rtl8169_private *tp = netdev_priv(dev);
+ 
+-	pm_runtime_get_sync(&pdev->dev);
+-
+ 	flush_scheduled_work();
+ 
+ 	unregister_netdev(dev);
+ 
+-	if (pci_dev_run_wake(pdev)) {
+-		pm_runtime_disable(&pdev->dev);
+-		pm_runtime_set_suspended(&pdev->dev);
+-	}
+-	pm_runtime_put_noidle(&pdev->dev);
++	if (pci_dev_run_wake(pdev))
++		pm_runtime_get_noresume(&pdev->dev);
+ 
+ 	/* restore original MAC address */
+ 	rtl_rar_set(tp, dev->perm_addr);
+diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
+index f9a0aec3abcf..8a6f797de8e5 100644
+--- a/drivers/pci/pci-driver.c
++++ b/drivers/pci/pci-driver.c
+@@ -289,8 +289,26 @@ struct drv_dev_and_id {
+ static long local_pci_probe(void *_ddi)
+ {
+ 	struct drv_dev_and_id *ddi = _ddi;
+-
+-	return ddi->drv->probe(ddi->dev, ddi->id);
++	struct device *dev = &ddi->dev->dev;
++	int rc;
++
++	/* Unbound PCI devices are always set to disabled and suspended.
++	 * During probe, the device is set to enabled and active and the
++	 * usage count is incremented.  If the driver supports runtime PM,
++	 * it should call pm_runtime_put_noidle() in its probe routine and
++	 * pm_runtime_get_noresume() in its remove routine.
++	 */
++	pm_runtime_get_noresume(dev);
++	pm_runtime_set_active(dev);
++	pm_runtime_enable(dev);
++
++	rc = ddi->drv->probe(ddi->dev, ddi->id);
++	if (rc) {
++		pm_runtime_disable(dev);
++		pm_runtime_set_suspended(dev);
++		pm_runtime_put_noidle(dev);
++	}
++	return rc;
+ }
+ 
+ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
+@@ -369,11 +387,19 @@ static int pci_device_remove(struct device * dev)
+ 	struct pci_driver * drv = pci_dev->driver;
+ 
+ 	if (drv) {
+-		if (drv->remove)
++		if (drv->remove) {
++			pm_runtime_get_sync(dev);
+ 			drv->remove(pci_dev);
++			pm_runtime_put_noidle(dev);
++		}
+ 		pci_dev->driver = NULL;
+ 	}
+ 
++	/* Undo the runtime PM settings in local_pci_probe() */
++	pm_runtime_disable(dev);
++	pm_runtime_set_suspended(dev);
++	pm_runtime_put_noidle(dev);
++
+ 	/*
+ 	 * If the device is still on, set the power state as "unknown",
+ 	 * since it might change by the next time we load the driver.

commit 478a8a0543021172220feeb0b39bb1b3e43c988f
+Author: Alan Stern 
+Date:   Wed Jun 16 14:52:17 2010 -0400
+
+    [SCSI] sd: add support for runtime PM
+    
+    This patch (as1399) adds runtime-PM support to the sd driver.  The
+    support is unsophisticated: If a SCSI disk device is mounted, or if
+    its device file is held open, then the device will not be
+    runtime-suspended; otherwise it will (provided userspace gives
+    permission by writing "auto" to the sysfs power/control attribute).
+    
+    In order to make this work, a dev_set_drvdata() call had to be moved
+    from sd_probe_async() to sd_probe().  Also, a few lines of code were
+    changed to use a local variable instead of recalculating the address
+    of an embedded struct device.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+index 8802e48bc063..cc8a1d1d915a 100644
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -759,6 +759,10 @@ static int sd_open(struct block_device *bdev, fmode_t mode)
+ 
+ 	sdev = sdkp->device;
+ 
++	retval = scsi_autopm_get_device(sdev);
++	if (retval)
++		goto error_autopm;
++
+ 	/*
+ 	 * If the device is in error recovery, wait until it is done.
+ 	 * If the device is offline, then disallow any access to it.
+@@ -803,6 +807,8 @@ static int sd_open(struct block_device *bdev, fmode_t mode)
+ 	return 0;
+ 
+ error_out:
++	scsi_autopm_put_device(sdev);
++error_autopm:
+ 	scsi_disk_put(sdkp);
+ 	return retval;	
+ }
+@@ -834,6 +840,8 @@ static int sd_release(struct gendisk *disk, fmode_t mode)
+ 	 * XXX and what if there are packets in flight and this close()
+ 	 * XXX is followed by a "rmmod sd_mod"?
+ 	 */
++
++	scsi_autopm_put_device(sdev);
+ 	scsi_disk_put(sdkp);
+ 	return 0;
+ }
+@@ -2232,7 +2240,6 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
+ 	if (sdp->removable)
+ 		gd->flags |= GENHD_FL_REMOVABLE;
+ 
+-	dev_set_drvdata(dev, sdkp);
+ 	add_disk(gd);
+ 	sd_dif_config_host(sdkp);
+ 
+@@ -2240,6 +2247,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
+ 
+ 	sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
+ 		  sdp->removable ? "removable " : "");
++	scsi_autopm_put_device(sdp);
+ 	put_device(&sdkp->dev);
+ }
+ 
+@@ -2317,14 +2325,15 @@ static int sd_probe(struct device *dev)
+ 	}
+ 
+ 	device_initialize(&sdkp->dev);
+-	sdkp->dev.parent = &sdp->sdev_gendev;
++	sdkp->dev.parent = dev;
+ 	sdkp->dev.class = &sd_disk_class;
+-	dev_set_name(&sdkp->dev, dev_name(&sdp->sdev_gendev));
++	dev_set_name(&sdkp->dev, dev_name(dev));
+ 
+ 	if (device_add(&sdkp->dev))
+ 		goto out_free_index;
+ 
+-	get_device(&sdp->sdev_gendev);
++	get_device(dev);
++	dev_set_drvdata(dev, sdkp);
+ 
+ 	get_device(&sdkp->dev);	/* prevent release before async_schedule */
+ 	async_schedule(sd_probe_async, sdkp);
+@@ -2358,8 +2367,10 @@ static int sd_remove(struct device *dev)
+ {
+ 	struct scsi_disk *sdkp;
+ 
+-	async_synchronize_full();
+ 	sdkp = dev_get_drvdata(dev);
++	scsi_autopm_get_device(sdkp->device);
++
++	async_synchronize_full();
+ 	blk_queue_prep_rq(sdkp->device->request_queue, scsi_prep_fn);
+ 	device_del(&sdkp->dev);
+ 	del_gendisk(sdkp->disk);

commit bc4f24014de58f045f169742701a6598884d93db
+Author: Alan Stern 
+Date:   Thu Jun 17 10:41:42 2010 -0400
+
+    [SCSI] implement runtime Power Management
+    
+    This patch (as1398b) adds runtime PM support to the SCSI layer.  Only
+    the machanism is provided; use of it is up to the various high-level
+    drivers, and the patch doesn't change any of them.  Except for sg --
+    the patch expicitly prevents a device from being runtime-suspended
+    while its sg device file is open.
+    
+    The implementation is simplistic.  In general, hosts and targets are
+    automatically suspended when all their children are asleep, but for
+    them the runtime-suspend code doesn't actually do anything.  (A host's
+    runtime PM status is propagated up the device tree, though, so a
+    runtime-PM-aware lower-level driver could power down the host adapter
+    hardware at the appropriate times.)  There are comments indicating
+    where a transport class might be notified or some other hooks added.
+    
+    LUNs are runtime-suspended by calling the drivers' existing suspend
+    handlers (and likewise for runtime-resume).  Somewhat arbitrarily, the
+    implementation delays for 100 ms before suspending an eligible LUN.
+    This is because there typically are occasions during bootup when the
+    same device file is opened and closed several times in quick
+    succession.
+    
+    The way this all works is that the SCSI core increments a device's
+    PM-usage count when it is registered.  If a high-level driver does
+    nothing then the device will not be eligible for runtime-suspend
+    because of the elevated usage count.  If a high-level driver wants to
+    use runtime PM then it can call scsi_autopm_put_device() in its probe
+    routine to decrement the usage count and scsi_autopm_get_device() in
+    its remove routine to restore the original count.
+    
+    Hosts, targets, and LUNs are not suspended while they are being probed
+    or removed, or while the error handler is running.  In fact, a fairly
+    large part of the patch consists of code to make sure that things
+    aren't suspended at such times.
+    
+    [jejb: fix up compile issues in PM config variations]
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
+index a2b1414da288..8a8f803439e1 100644
+--- a/drivers/scsi/hosts.c
++++ b/drivers/scsi/hosts.c
+@@ -32,6 +32,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ #include 
+@@ -156,6 +157,7 @@ EXPORT_SYMBOL(scsi_host_set_state);
+ void scsi_remove_host(struct Scsi_Host *shost)
+ {
+ 	unsigned long flags;
++
+ 	mutex_lock(&shost->scan_mutex);
+ 	spin_lock_irqsave(shost->host_lock, flags);
+ 	if (scsi_host_set_state(shost, SHOST_CANCEL))
+@@ -165,6 +167,8 @@ void scsi_remove_host(struct Scsi_Host *shost)
+ 			return;
+ 		}
+ 	spin_unlock_irqrestore(shost->host_lock, flags);
++
++	scsi_autopm_get_host(shost);
+ 	scsi_forget_host(shost);
+ 	mutex_unlock(&shost->scan_mutex);
+ 	scsi_proc_host_rm(shost);
+@@ -216,12 +220,14 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
+ 		shost->shost_gendev.parent = dev ? dev : &platform_bus;
+ 	shost->dma_dev = dma_dev;
+ 
+-	device_enable_async_suspend(&shost->shost_gendev);
+-
+ 	error = device_add(&shost->shost_gendev);
+ 	if (error)
+ 		goto out;
+ 
++	pm_runtime_set_active(&shost->shost_gendev);
++	pm_runtime_enable(&shost->shost_gendev);
++	device_enable_async_suspend(&shost->shost_gendev);
++
+ 	scsi_host_set_state(shost, SHOST_RUNNING);
+ 	get_device(shost->shost_gendev.parent);
+ 
+diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
+index c60cffbefa3c..2bf98469dc4c 100644
+--- a/drivers/scsi/scsi_error.c
++++ b/drivers/scsi/scsi_error.c
+@@ -1775,6 +1775,14 @@ int scsi_error_handler(void *data)
+ 		 * what we need to do to get it up and online again (if we can).
+ 		 * If we fail, we end up taking the thing offline.
+ 		 */
++		if (scsi_autopm_get_host(shost) != 0) {
++			SCSI_LOG_ERROR_RECOVERY(1,
++				printk(KERN_ERR "Error handler scsi_eh_%d "
++						"unable to autoresume\n",
++						shost->host_no));
++			continue;
++		}
++
+ 		if (shost->transportt->eh_strategy_handler)
+ 			shost->transportt->eh_strategy_handler(shost);
+ 		else
+@@ -1788,6 +1796,7 @@ int scsi_error_handler(void *data)
+ 		 * which are still online.
+ 		 */
+ 		scsi_restart_operations(shost);
++		scsi_autopm_put_host(shost);
+ 		set_current_state(TASK_INTERRUPTIBLE);
+ 	}
+ 	__set_current_state(TASK_RUNNING);
+@@ -1885,12 +1894,16 @@ scsi_reset_provider_done_command(struct scsi_cmnd *scmd)
+ int
+ scsi_reset_provider(struct scsi_device *dev, int flag)
+ {
+-	struct scsi_cmnd *scmd = scsi_get_command(dev, GFP_KERNEL);
++	struct scsi_cmnd *scmd;
+ 	struct Scsi_Host *shost = dev->host;
+ 	struct request req;
+ 	unsigned long flags;
+ 	int rtn;
+ 
++	if (scsi_autopm_get_host(shost) < 0)
++		return FAILED;
++
++	scmd = scsi_get_command(dev, GFP_KERNEL);
+ 	blk_rq_init(NULL, &req);
+ 	scmd->request = &req;
+ 
+@@ -1947,6 +1960,7 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
+ 	scsi_run_host_queues(shost);
+ 
+ 	scsi_next_command(scmd);
++	scsi_autopm_put_host(shost);
+ 	return rtn;
+ }
+ EXPORT_SYMBOL(scsi_reset_provider);
+diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
+index cd83758ce0a2..d70e91ae60af 100644
+--- a/drivers/scsi/scsi_pm.c
++++ b/drivers/scsi/scsi_pm.c
+@@ -59,6 +59,12 @@ static int scsi_bus_resume_common(struct device *dev)
+ 
+ 	if (scsi_is_sdev_device(dev))
+ 		err = scsi_dev_type_resume(dev);
++
++	if (err == 0) {
++		pm_runtime_disable(dev);
++		pm_runtime_set_active(dev);
++		pm_runtime_enable(dev);
++	}
+ 	return err;
+ }
+ 
+@@ -86,6 +92,107 @@ static int scsi_bus_poweroff(struct device *dev)
+ 
+ #endif /* CONFIG_PM_SLEEP */
+ 
++#ifdef CONFIG_PM_RUNTIME
++
++static int scsi_runtime_suspend(struct device *dev)
++{
++	int err = 0;
++
++	dev_dbg(dev, "scsi_runtime_suspend\n");
++	if (scsi_is_sdev_device(dev)) {
++		err = scsi_dev_type_suspend(dev, PMSG_AUTO_SUSPEND);
++		if (err == -EAGAIN)
++			pm_schedule_suspend(dev, jiffies_to_msecs(
++				round_jiffies_up_relative(HZ/10)));
++	}
++
++	/* Insert hooks here for targets, hosts, and transport classes */
++
++	return err;
++}
++
++static int scsi_runtime_resume(struct device *dev)
++{
++	int err = 0;
++
++	dev_dbg(dev, "scsi_runtime_resume\n");
++	if (scsi_is_sdev_device(dev))
++		err = scsi_dev_type_resume(dev);
++
++	/* Insert hooks here for targets, hosts, and transport classes */
++
++	return err;
++}
++
++static int scsi_runtime_idle(struct device *dev)
++{
++	int err;
++
++	dev_dbg(dev, "scsi_runtime_idle\n");
++
++	/* Insert hooks here for targets, hosts, and transport classes */
++
++	if (scsi_is_sdev_device(dev))
++		err = pm_schedule_suspend(dev, 100);
++	else
++		err = pm_runtime_suspend(dev);
++	return err;
++}
++
++int scsi_autopm_get_device(struct scsi_device *sdev)
++{
++	int	err;
++
++	err = pm_runtime_get_sync(&sdev->sdev_gendev);
++	if (err < 0)
++		pm_runtime_put_sync(&sdev->sdev_gendev);
++	else if (err > 0)
++		err = 0;
++	return err;
++}
++EXPORT_SYMBOL_GPL(scsi_autopm_get_device);
++
++void scsi_autopm_put_device(struct scsi_device *sdev)
++{
++	pm_runtime_put_sync(&sdev->sdev_gendev);
++}
++EXPORT_SYMBOL_GPL(scsi_autopm_put_device);
++
++void scsi_autopm_get_target(struct scsi_target *starget)
++{
++	pm_runtime_get_sync(&starget->dev);
++}
++
++void scsi_autopm_put_target(struct scsi_target *starget)
++{
++	pm_runtime_put_sync(&starget->dev);
++}
++
++int scsi_autopm_get_host(struct Scsi_Host *shost)
++{
++	int	err;
++
++	err = pm_runtime_get_sync(&shost->shost_gendev);
++	if (err < 0)
++		pm_runtime_put_sync(&shost->shost_gendev);
++	else if (err > 0)
++		err = 0;
++	return err;
++}
++
++void scsi_autopm_put_host(struct Scsi_Host *shost)
++{
++	pm_runtime_put_sync(&shost->shost_gendev);
++}
++
++#else
++
++#define scsi_runtime_suspend	NULL
++#define scsi_runtime_resume	NULL
++#define scsi_runtime_idle	NULL
++
++#endif /* CONFIG_PM_RUNTIME */
++
+ const struct dev_pm_ops scsi_bus_pm_ops = {
+ 	.suspend =		scsi_bus_suspend,
+ 	.resume =		scsi_bus_resume_common,
+@@ -93,4 +200,7 @@ const struct dev_pm_ops scsi_bus_pm_ops = {
+ 	.thaw =			scsi_bus_resume_common,
+ 	.poweroff =		scsi_bus_poweroff,
+ 	.restore =		scsi_bus_resume_common,
++	.runtime_suspend =	scsi_runtime_suspend,
++	.runtime_resume =	scsi_runtime_resume,
++	.runtime_idle =		scsi_runtime_idle,
+ };
+diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
+index dddacc732550..026295e2c539 100644
+--- a/drivers/scsi/scsi_priv.h
++++ b/drivers/scsi/scsi_priv.h
+@@ -7,6 +7,7 @@ struct request_queue;
+ struct request;
+ struct scsi_cmnd;
+ struct scsi_device;
++struct scsi_target;
+ struct scsi_host_template;
+ struct Scsi_Host;
+ struct scsi_nl_hdr;
+@@ -147,9 +148,20 @@ static inline void scsi_netlink_exit(void) {}
+ /* scsi_pm.c */
+ #ifdef CONFIG_PM_OPS
+ extern const struct dev_pm_ops scsi_bus_pm_ops;
+-#else
++#else /* CONFIG_PM_OPS */
+ #define scsi_bus_pm_ops		(*NULL)
+ #endif
++#ifdef CONFIG_PM_RUNTIME
++extern void scsi_autopm_get_target(struct scsi_target *);
++extern void scsi_autopm_put_target(struct scsi_target *);
++extern int scsi_autopm_get_host(struct Scsi_Host *);
++extern void scsi_autopm_put_host(struct Scsi_Host *);
++#else
++static inline void scsi_autopm_get_target(struct scsi_target *t) {}
++static inline void scsi_autopm_put_target(struct scsi_target *t) {}
++static inline int scsi_autopm_get_host(struct Scsi_Host *h) { return 0; }
++static inline void scsi_autopm_put_host(struct Scsi_Host *h) {}
++#endif /* CONFIG_PM_RUNTIME */
+ 
+ /* 
+  * internal scsi timeout functions: for use by mid-layer and transport
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+index 1c027a97d8b9..3d0a1e6e9c48 100644
+--- a/drivers/scsi/scsi_scan.c
++++ b/drivers/scsi/scsi_scan.c
+@@ -1513,14 +1513,18 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
+ 	starget = scsi_alloc_target(parent, channel, id);
+ 	if (!starget)
+ 		return ERR_PTR(-ENOMEM);
++	scsi_autopm_get_target(starget);
+ 
+ 	mutex_lock(&shost->scan_mutex);
+ 	if (!shost->async_scan)
+ 		scsi_complete_async_scans();
+ 
+-	if (scsi_host_scan_allowed(shost))
++	if (scsi_host_scan_allowed(shost) && scsi_autopm_get_host(shost) == 0) {
+ 		scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata);
++		scsi_autopm_put_host(shost);
++	}
+ 	mutex_unlock(&shost->scan_mutex);
++	scsi_autopm_put_target(starget);
+ 	scsi_target_reap(starget);
+ 	put_device(&starget->dev);
+ 
+@@ -1574,6 +1578,7 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel,
+ 	starget = scsi_alloc_target(parent, channel, id);
+ 	if (!starget)
+ 		return;
++	scsi_autopm_get_target(starget);
+ 
+ 	if (lun != SCAN_WILD_CARD) {
+ 		/*
+@@ -1599,6 +1604,7 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel,
+ 	}
+ 
+  out_reap:
++	scsi_autopm_put_target(starget);
+ 	/* now determine if the target has any children at all
+ 	 * and if not, nuke it */
+ 	scsi_target_reap(starget);
+@@ -1633,8 +1639,10 @@ void scsi_scan_target(struct device *parent, unsigned int channel,
+ 	if (!shost->async_scan)
+ 		scsi_complete_async_scans();
+ 
+-	if (scsi_host_scan_allowed(shost))
++	if (scsi_host_scan_allowed(shost) && scsi_autopm_get_host(shost) == 0) {
+ 		__scsi_scan_target(parent, channel, id, lun, rescan);
++		scsi_autopm_put_host(shost);
++	}
+ 	mutex_unlock(&shost->scan_mutex);
+ }
+ EXPORT_SYMBOL(scsi_scan_target);
+@@ -1686,7 +1694,7 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
+ 	if (!shost->async_scan)
+ 		scsi_complete_async_scans();
+ 
+-	if (scsi_host_scan_allowed(shost)) {
++	if (scsi_host_scan_allowed(shost) && scsi_autopm_get_host(shost) == 0) {
+ 		if (channel == SCAN_WILD_CARD)
+ 			for (channel = 0; channel <= shost->max_channel;
+ 			     channel++)
+@@ -1694,6 +1702,7 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
+ 						  rescan);
+ 		else
+ 			scsi_scan_channel(shost, channel, id, lun, rescan);
++		scsi_autopm_put_host(shost);
+ 	}
+ 	mutex_unlock(&shost->scan_mutex);
+ 
+@@ -1831,8 +1840,11 @@ static void do_scsi_scan_host(struct Scsi_Host *shost)
+ static int do_scan_async(void *_data)
+ {
+ 	struct async_scan_data *data = _data;
+-	do_scsi_scan_host(data->shost);
++	struct Scsi_Host *shost = data->shost;
++
++	do_scsi_scan_host(shost);
+ 	scsi_finish_async_scan(data);
++	scsi_autopm_put_host(shost);
+ 	return 0;
+ }
+ 
+@@ -1847,16 +1859,20 @@ void scsi_scan_host(struct Scsi_Host *shost)
+ 
+ 	if (strncmp(scsi_scan_type, "none", 4) == 0)
+ 		return;
++	if (scsi_autopm_get_host(shost) < 0)
++		return;
+ 
+ 	data = scsi_prep_async_scan(shost);
+ 	if (!data) {
+ 		do_scsi_scan_host(shost);
++		scsi_autopm_put_host(shost);
+ 		return;
+ 	}
+ 
+ 	p = kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no);
+ 	if (IS_ERR(p))
+ 		do_scan_async(data);
++	/* scsi_autopm_put_host(shost) is called in do_scan_async() */
+ }
+ EXPORT_SYMBOL(scsi_scan_host);
+ 
+diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
+index 5f85f8e831f3..562fb3bce261 100644
+--- a/drivers/scsi/scsi_sysfs.c
++++ b/drivers/scsi/scsi_sysfs.c
+@@ -11,6 +11,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ #include 
+@@ -802,8 +803,6 @@ static int scsi_target_add(struct scsi_target *starget)
+ 	if (starget->state != STARGET_CREATED)
+ 		return 0;
+ 
+-	device_enable_async_suspend(&starget->dev);
+-
+ 	error = device_add(&starget->dev);
+ 	if (error) {
+ 		dev_err(&starget->dev, "target device_add failed, error %d\n", error);
+@@ -812,6 +811,10 @@ static int scsi_target_add(struct scsi_target *starget)
+ 	transport_add_device(&starget->dev);
+ 	starget->state = STARGET_RUNNING;
+ 
++	pm_runtime_set_active(&starget->dev);
++	pm_runtime_enable(&starget->dev);
++	device_enable_async_suspend(&starget->dev);
++
+ 	return 0;
+ }
+ 
+@@ -841,7 +844,20 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
+ 		return error;
+ 
+ 	transport_configure_device(&starget->dev);
++
+ 	device_enable_async_suspend(&sdev->sdev_gendev);
++	scsi_autopm_get_target(starget);
++	pm_runtime_set_active(&sdev->sdev_gendev);
++	pm_runtime_forbid(&sdev->sdev_gendev);
++	pm_runtime_enable(&sdev->sdev_gendev);
++	scsi_autopm_put_target(starget);
++
++	/* The following call will keep sdev active indefinitely, until
++	 * its driver does a corresponding scsi_autopm_pm_device().  Only
++	 * drivers supporting autosuspend will do this.
++	 */
++	scsi_autopm_get_device(sdev);
++
+ 	error = device_add(&sdev->sdev_gendev);
+ 	if (error) {
+ 		printk(KERN_INFO "error 1\n");
+diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
+index d4549092400c..2968c6b83ddb 100644
+--- a/drivers/scsi/sg.c
++++ b/drivers/scsi/sg.c
+@@ -245,6 +245,10 @@ sg_open(struct inode *inode, struct file *filp)
+ 	if (retval)
+ 		goto sg_put;
+ 
++	retval = scsi_autopm_get_device(sdp->device);
++	if (retval)
++		goto sdp_put;
++
+ 	if (!((flags & O_NONBLOCK) ||
+ 	      scsi_block_when_processing_errors(sdp->device))) {
+ 		retval = -ENXIO;
+@@ -302,8 +306,11 @@ sg_open(struct inode *inode, struct file *filp)
+ 	}
+ 	retval = 0;
+ error_out:
+-	if (retval)
++	if (retval) {
++		scsi_autopm_put_device(sdp->device);
++sdp_put:
+ 		scsi_device_put(sdp->device);
++	}
+ sg_put:
+ 	if (sdp)
+ 		sg_put_dev(sdp);
+@@ -327,6 +334,7 @@ sg_release(struct inode *inode, struct file *filp)
+ 	sdp->exclude = 0;
+ 	wake_up_interruptible(&sdp->o_excl_wait);
+ 
++	scsi_autopm_put_device(sdp->device);
+ 	kref_put(&sfp->f_ref, sg_remove_sfp);
+ 	return 0;
+ }
+diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
+index d80b6dbed1ca..50cb34ffef11 100644
+--- a/include/scsi/scsi_device.h
++++ b/include/scsi/scsi_device.h
+@@ -381,6 +381,14 @@ extern int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
+ 			    struct scsi_sense_hdr *, int timeout, int retries,
+ 			    int *resid);
+ 
++#ifdef CONFIG_PM_RUNTIME
++extern int scsi_autopm_get_device(struct scsi_device *);
++extern void scsi_autopm_put_device(struct scsi_device *);
++#else
++static inline int scsi_autopm_get_device(struct scsi_device *d) { return 0; }
++static inline void scsi_autopm_put_device(struct scsi_device *d) {}
++#endif /* CONFIG_PM_RUNTIME */
++
+ static inline int __must_check scsi_device_reprobe(struct scsi_device *sdev)
+ {
+ 	return device_reprobe(&sdev->sdev_gendev);

commit db5bd1e0b505c54ff492172ce4abc245cf6cd639
+Author: Alan Stern 
+Date:   Thu Jun 17 10:36:49 2010 -0400
+
+    [SCSI] convert to the new PM framework
+    
+    This patch (as1397b) converts the SCSI midlayer to use the new PM
+    callbacks (struct dev_pm_ops).  A new source file, scsi_pm.c, is
+    created to hold the new callback routines, and the existing
+    suspend/resume code is moved there.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
+index 1c7ac49be649..2a3fca2eca6a 100644
+--- a/drivers/scsi/Makefile
++++ b/drivers/scsi/Makefile
+@@ -163,6 +163,7 @@ scsi_mod-$(CONFIG_SCSI_NETLINK)	+= scsi_netlink.o
+ scsi_mod-$(CONFIG_SYSCTL)	+= scsi_sysctl.o
+ scsi_mod-$(CONFIG_SCSI_PROC_FS)	+= scsi_proc.o
+ scsi_mod-y			+= scsi_trace.o
++scsi_mod-$(CONFIG_PM_OPS)	+= scsi_pm.o
+ 
+ scsi_tgt-y			+= scsi_tgt_lib.o scsi_tgt_if.o
+ 
+diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
+new file mode 100644
+index 000000000000..cd83758ce0a2
+--- /dev/null
++++ b/drivers/scsi/scsi_pm.c
+@@ -0,0 +1,96 @@
++/*
++ *	scsi_pm.c	Copyright (C) 2010 Alan Stern
++ *
++ *	SCSI dynamic Power Management
++ *		Initial version: Alan Stern 
++ */
++
++#include 
++
++#include 
++#include 
++#include 
++#include 
++
++#include "scsi_priv.h"
++
++static int scsi_dev_type_suspend(struct device *dev, pm_message_t msg)
++{
++	struct device_driver *drv;
++	int err;
++
++	err = scsi_device_quiesce(to_scsi_device(dev));
++	if (err == 0) {
++		drv = dev->driver;
++		if (drv && drv->suspend)
++			err = drv->suspend(dev, msg);
++	}
++	dev_dbg(dev, "scsi suspend: %d\n", err);
++	return err;
++}
++
++static int scsi_dev_type_resume(struct device *dev)
++{
++	struct device_driver *drv;
++	int err = 0;
++
++	drv = dev->driver;
++	if (drv && drv->resume)
++		err = drv->resume(dev);
++	scsi_device_resume(to_scsi_device(dev));
++	dev_dbg(dev, "scsi resume: %d\n", err);
++	return err;
++}
++
++#ifdef CONFIG_PM_SLEEP
++
++static int scsi_bus_suspend_common(struct device *dev, pm_message_t msg)
++{
++	int err = 0;
++
++	if (scsi_is_sdev_device(dev))
++		err = scsi_dev_type_suspend(dev, msg);
++	return err;
++}
++
++static int scsi_bus_resume_common(struct device *dev)
++{
++	int err = 0;
++
++	if (scsi_is_sdev_device(dev))
++		err = scsi_dev_type_resume(dev);
++	return err;
++}
++
++static int scsi_bus_suspend(struct device *dev)
++{
++	return scsi_bus_suspend_common(dev, PMSG_SUSPEND);
++}
++
++static int scsi_bus_freeze(struct device *dev)
++{
++	return scsi_bus_suspend_common(dev, PMSG_FREEZE);
++}
++
++static int scsi_bus_poweroff(struct device *dev)
++{
++	return scsi_bus_suspend_common(dev, PMSG_HIBERNATE);
++}
++
++#else /* CONFIG_PM_SLEEP */
++
++#define scsi_bus_resume_common		NULL
++#define scsi_bus_suspend		NULL
++#define scsi_bus_freeze			NULL
++#define scsi_bus_poweroff		NULL
++
++#endif /* CONFIG_PM_SLEEP */
++
++const struct dev_pm_ops scsi_bus_pm_ops = {
++	.suspend =		scsi_bus_suspend,
++	.resume =		scsi_bus_resume_common,
++	.freeze =		scsi_bus_freeze,
++	.thaw =			scsi_bus_resume_common,
++	.poweroff =		scsi_bus_poweroff,
++	.restore =		scsi_bus_resume_common,
++};
+diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
+index 1fbf7c78bba0..dddacc732550 100644
+--- a/drivers/scsi/scsi_priv.h
++++ b/drivers/scsi/scsi_priv.h
+@@ -144,6 +144,13 @@ static inline void scsi_netlink_init(void) {}
+ static inline void scsi_netlink_exit(void) {}
+ #endif
+ 
++/* scsi_pm.c */
++#ifdef CONFIG_PM_OPS
++extern const struct dev_pm_ops scsi_bus_pm_ops;
++#else
++#define scsi_bus_pm_ops		(*NULL)
++#endif
++
+ /* 
+  * internal scsi timeout functions: for use by mid-layer and transport
+  * classes.
+diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
+index c23ab978c3ba..5f85f8e831f3 100644
+--- a/drivers/scsi/scsi_sysfs.c
++++ b/drivers/scsi/scsi_sysfs.c
+@@ -376,57 +376,11 @@ static int scsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
+ 	return 0;
+ }
+ 
+-static int scsi_bus_suspend(struct device * dev, pm_message_t state)
+-{
+-	struct device_driver *drv;
+-	struct scsi_device *sdev;
+-	int err;
+-
+-	if (dev->type != &scsi_dev_type)
+-		return 0;
+-
+-	drv = dev->driver;
+-	sdev = to_scsi_device(dev);
+-
+-	err = scsi_device_quiesce(sdev);
+-	if (err)
+-		return err;
+-
+-	if (drv && drv->suspend) {
+-		err = drv->suspend(dev, state);
+-		if (err)
+-			return err;
+-	}
+-
+-	return 0;
+-}
+-
+-static int scsi_bus_resume(struct device * dev)
+-{
+-	struct device_driver *drv;
+-	struct scsi_device *sdev;
+-	int err = 0;
+-
+-	if (dev->type != &scsi_dev_type)
+-		return 0;
+-
+-	drv = dev->driver;
+-	sdev = to_scsi_device(dev);
+-
+-	if (drv && drv->resume)
+-		err = drv->resume(dev);
+-
+-	scsi_device_resume(sdev);
+-
+-	return err;
+-}
+-
+ struct bus_type scsi_bus_type = {
+         .name		= "scsi",
+         .match		= scsi_bus_match,
+ 	.uevent		= scsi_bus_uevent,
+-	.suspend	= scsi_bus_suspend,
+-	.resume		= scsi_bus_resume,
++	.pm		= &scsi_bus_pm_ops,
+ };
+ EXPORT_SYMBOL_GPL(scsi_bus_type);
+ 

commit 0fcb4eef8294492c8f1de8236b1ed81f09e42922
+Author: Alan Stern 
+Date:   Thu Jul 8 00:05:37 2010 +0200
+
+    PM / Runtime: Make runtime_status attribute not debug-only (v. 2)
+    
+    This patch (as1404b) makes the runtime_status sysfs attribute available
+    even in the absence of CONFIG_PM_ADVANCED_DEBUG, and it changes the
+    routine to display "unsupported" when runtime PM is disabled for a
+    device.  Although not strictly 100% accurate, this will almost always
+    be correct.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Dominik Brodowski 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
+index 81d344e0e95d..1eca50c8e7ca 100644
+--- a/drivers/base/power/sysfs.c
++++ b/drivers/base/power/sysfs.c
+@@ -110,6 +110,38 @@ static ssize_t control_store(struct device * dev, struct device_attribute *attr,
+ }
+ 
+ static DEVICE_ATTR(control, 0644, control_show, control_store);
++
++static ssize_t rtpm_status_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	const char *p;
++
++	if (dev->power.runtime_error) {
++		p = "error\n";
++	} else if (dev->power.disable_depth) {
++		p = "unsupported\n";
++	} else {
++		switch (dev->power.runtime_status) {
++		case RPM_SUSPENDED:
++			p = "suspended\n";
++			break;
++		case RPM_SUSPENDING:
++			p = "suspending\n";
++			break;
++		case RPM_RESUMING:
++			p = "resuming\n";
++			break;
++		case RPM_ACTIVE:
++			p = "active\n";
++			break;
++		default:
++			return -EIO;
++		}
++	}
++	return sprintf(buf, p);
++}
++
++static DEVICE_ATTR(runtime_status, 0444, rtpm_status_show, NULL);
+ #endif
+ 
+ static ssize_t
+@@ -184,27 +216,8 @@ static ssize_t rtpm_enabled_show(struct device *dev,
+ 	return sprintf(buf, "enabled\n");
+ }
+ 
+-static ssize_t rtpm_status_show(struct device *dev,
+-				struct device_attribute *attr, char *buf)
+-{
+-	if (dev->power.runtime_error)
+-		return sprintf(buf, "error\n");
+-	switch (dev->power.runtime_status) {
+-	case RPM_SUSPENDED:
+-		return sprintf(buf, "suspended\n");
+-	case RPM_SUSPENDING:
+-		return sprintf(buf, "suspending\n");
+-	case RPM_RESUMING:
+-		return sprintf(buf, "resuming\n");
+-	case RPM_ACTIVE:
+-		return sprintf(buf, "active\n");
+-	}
+-	return -EIO;
+-}
+-
+ static DEVICE_ATTR(runtime_usage, 0444, rtpm_usagecount_show, NULL);
+ static DEVICE_ATTR(runtime_active_kids, 0444, rtpm_children_show, NULL);
+-static DEVICE_ATTR(runtime_status, 0444, rtpm_status_show, NULL);
+ static DEVICE_ATTR(runtime_enabled, 0444, rtpm_enabled_show, NULL);
+ 
+ #endif
+@@ -240,6 +253,7 @@ static DEVICE_ATTR(async, 0644, async_show, async_store);
+ static struct attribute * power_attrs[] = {
+ #ifdef CONFIG_PM_RUNTIME
+ 	&dev_attr_control.attr,
++	&dev_attr_runtime_status.attr,
+ #endif
+ 	&dev_attr_wakeup.attr,
+ #ifdef CONFIG_PM_SLEEP
+@@ -250,7 +264,6 @@ static struct attribute * power_attrs[] = {
+ #ifdef CONFIG_PM_RUNTIME
+ 	&dev_attr_runtime_usage.attr,
+ 	&dev_attr_runtime_active_kids.attr,
+-	&dev_attr_runtime_status.attr,
+ 	&dev_attr_runtime_enabled.attr,
+ #endif
+ #endif

commit b14e033e17d0ea0ba12668d0d2f371cd31586994
+Author: Alan Stern 
+Date:   Tue Jun 29 22:49:24 2010 +0200
+
+    PNPACPI: Add support for remote wakeup
+    
+    This patch (as1354) adds remote-wakeup support to the pnpacpi driver.
+    The new can_wakeup method also allows other PNP protocol drivers
+    (pnpbios or iaspnp) to add wakeup support, but I don't know enough
+    about how they work to actually do it.
+    
+    Signed-off-by: Alan Stern 
+    Reviewed-by: Bjorn Helgaas 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c
+index 5dba90995d9e..88b3cde52596 100644
+--- a/drivers/pnp/core.c
++++ b/drivers/pnp/core.c
+@@ -164,6 +164,9 @@ int __pnp_add_device(struct pnp_dev *dev)
+ 	list_add_tail(&dev->global_list, &pnp_global);
+ 	list_add_tail(&dev->protocol_list, &dev->protocol->devices);
+ 	spin_unlock(&pnp_lock);
++	if (dev->protocol->can_wakeup)
++		device_set_wakeup_capable(&dev->dev,
++				dev->protocol->can_wakeup(dev));
+ 	return device_register(&dev->dev);
+ }
+ 
+diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
+index f7ff628b7d94..dc4e32e031e9 100644
+--- a/drivers/pnp/pnpacpi/core.c
++++ b/drivers/pnp/pnpacpi/core.c
+@@ -122,17 +122,37 @@ static int pnpacpi_disable_resources(struct pnp_dev *dev)
+ }
+ 
+ #ifdef CONFIG_ACPI_SLEEP
++static bool pnpacpi_can_wakeup(struct pnp_dev *dev)
++{
++	struct acpi_device *acpi_dev = dev->data;
++	acpi_handle handle = acpi_dev->handle;
++
++	return acpi_bus_can_wakeup(handle);
++}
++
+ static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state)
+ {
+ 	struct acpi_device *acpi_dev = dev->data;
+ 	acpi_handle handle = acpi_dev->handle;
+ 	int power_state;
+ 
++	if (device_can_wakeup(&dev->dev)) {
++		int rc = acpi_pm_device_sleep_wake(&dev->dev,
++				device_may_wakeup(&dev->dev));
++
++		if (rc)
++			return rc;
++	}
+ 	power_state = acpi_pm_device_sleep_state(&dev->dev, NULL);
+ 	if (power_state < 0)
+ 		power_state = (state.event == PM_EVENT_ON) ?
+ 				ACPI_STATE_D0 : ACPI_STATE_D3;
+ 
++	/* acpi_bus_set_power() often fails (keyboard port can't be
++	 * powered-down?), and in any case, our return value is ignored
++	 * by pnp_bus_suspend().  Hence we don't revert the wakeup
++	 * setting if the set_power fails.
++	 */
+ 	return acpi_bus_set_power(handle, power_state);
+ }
+ 
+@@ -141,6 +161,8 @@ static int pnpacpi_resume(struct pnp_dev *dev)
+ 	struct acpi_device *acpi_dev = dev->data;
+ 	acpi_handle handle = acpi_dev->handle;
+ 
++	if (device_may_wakeup(&dev->dev))
++		acpi_pm_device_sleep_wake(&dev->dev, false);
+ 	return acpi_bus_set_power(handle, ACPI_STATE_D0);
+ }
+ #endif
+@@ -151,6 +173,7 @@ struct pnp_protocol pnpacpi_protocol = {
+ 	.set	 = pnpacpi_set_resources,
+ 	.disable = pnpacpi_disable_resources,
+ #ifdef CONFIG_ACPI_SLEEP
++	.can_wakeup = pnpacpi_can_wakeup,
+ 	.suspend = pnpacpi_suspend,
+ 	.resume = pnpacpi_resume,
+ #endif
+diff --git a/include/linux/pnp.h b/include/linux/pnp.h
+index 7c4193eb0072..1bc1338b817b 100644
+--- a/include/linux/pnp.h
++++ b/include/linux/pnp.h
+@@ -414,6 +414,7 @@ struct pnp_protocol {
+ 	int (*disable) (struct pnp_dev *dev);
+ 
+ 	/* protocol specific suspend/resume */
++	bool (*can_wakeup) (struct pnp_dev *dev);
+ 	int (*suspend) (struct pnp_dev * dev, pm_message_t state);
+ 	int (*resume) (struct pnp_dev * dev);
+ 

commit 2430d12c94ff2bafcfe4f65edf7ee5f300d2d9c6
+Author: Alan Stern 
+Date:   Sun Jun 13 00:36:52 2010 +0200
+
+    PM: describe kernel policy regarding wakeup defaults (v. 2)
+    
+    This patch (as1381b) updates a comment describing the kernel's policy
+    toward enabling wakeup by default.
+    
+    It also makes device_set_wakeup_capable() actually do something when
+    CONFIG_PM isn't enabled.  It's not clear this is necessary; however if
+    it isn't then device_init_wakeup() and device_can_wakeup() should also
+    be do-nothing routines.  Furthermore, I don't expect this change to
+    have any noticeable effect -- but if it does then clearly the old
+    behavior was wrong.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h
+index 22d64c18056c..76aca48722ae 100644
+--- a/include/linux/pm_wakeup.h
++++ b/include/linux/pm_wakeup.h
+@@ -29,8 +29,11 @@
+ 
+ #ifdef CONFIG_PM
+ 
+-/* changes to device_may_wakeup take effect on the next pm state change.
+- * by default, devices should wakeup if they can.
++/* Changes to device_may_wakeup take effect on the next pm state change.
++ *
++ * By default, most devices should leave wakeup disabled.  The exceptions
++ * are devices that everyone expects to be wakeup sources: keyboards,
++ * power buttons, possibly network interfaces, etc.
+  */
+ static inline void device_init_wakeup(struct device *dev, bool val)
+ {
+@@ -59,7 +62,7 @@ static inline bool device_may_wakeup(struct device *dev)
+ 
+ #else /* !CONFIG_PM */
+ 
+-/* For some reason the next two routines work even without CONFIG_PM */
++/* For some reason the following routines work even without CONFIG_PM */
+ static inline void device_init_wakeup(struct device *dev, bool val)
+ {
+ 	dev->power.can_wakeup = val;
+@@ -67,6 +70,7 @@ static inline void device_init_wakeup(struct device *dev, bool val)
+ 
+ static inline void device_set_wakeup_capable(struct device *dev, bool capable)
+ {
++	dev->power.can_wakeup = capable;
+ }
+ 
+ static inline bool device_can_wakeup(struct device *dev)

commit 48826626263d4a61d06fd8c5805da31f925aefa0
+Author: Alan Stern 
+Date:   Tue Jun 22 16:14:48 2010 -0400
+
+    USB: obey the sysfs power/wakeup setting
+    
+    This patch (as1403) is a partial reversion of an earlier change
+    (commit 5f677f1d45b2bf08085bbba7394392dfa586fa8e "USB: fix remote
+    wakeup settings during system sleep").  After hearing from a user, I
+    realized that remote wakeup should be enabled during system sleep
+    whenever userspace allows it, and not only if a driver requests it
+    too.
+    
+    Indeed, there could be a device with no driver, that does nothing but
+    generate a wakeup request when the user presses a button.  Such a
+    device should be allowed to do its job.
+    
+    The problem fixed by the earlier patch -- device generating a wakeup
+    request for no reason, causing system suspend to abort -- was also
+    addressed by a later patch ("USB: don't enable remote wakeup by
+    default", accepted but not yet merged into mainline).  The device
+    won't be able to generate the bogus wakeup requests because it will be
+    disabled for remote wakeup by default.  Hence this reversion will not
+    re-introduce any old problems.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable  [.34]
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index de98a94d1853..a6bd53ace035 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1272,8 +1272,7 @@ static int usb_resume_both(struct usb_device *udev, pm_message_t msg)
+ 
+ static void choose_wakeup(struct usb_device *udev, pm_message_t msg)
+ {
+-	int			w, i;
+-	struct usb_interface	*intf;
++	int	w;
+ 
+ 	/* Remote wakeup is needed only when we actually go to sleep.
+ 	 * For things like FREEZE and QUIESCE, if the device is already
+@@ -1285,16 +1284,10 @@ static void choose_wakeup(struct usb_device *udev, pm_message_t msg)
+ 		return;
+ 	}
+ 
+-	/* If remote wakeup is permitted, see whether any interface drivers
++	/* Enable remote wakeup if it is allowed, even if no interface drivers
+ 	 * actually want it.
+ 	 */
+-	w = 0;
+-	if (device_may_wakeup(&udev->dev) && udev->actconfig) {
+-		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+-			intf = udev->actconfig->interface[i];
+-			w |= intf->needs_remote_wakeup;
+-		}
+-	}
++	w = device_may_wakeup(&udev->dev);
+ 
+ 	/* If the device is autosuspended with the wrong wakeup setting,
+ 	 * autoresume now so the setting can be changed.

commit 64d65872f96e2a754caa12ef48949c314384bd9f
+Author: Alan Stern 
+Date:   Fri Jun 18 10:16:33 2010 -0400
+
+    USB: fix oops in usb_sg_init()
+    
+    This patch (as1401) fixes a bug in usb_sg_init() that can cause an
+    invalid pointer dereference.  An inner loop reuses some local variables
+    in an unsafe manner, so new variables are introduced.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Ajay Kumar Gupta 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index a73e08fdab36..fd4c36ea5e46 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -416,8 +416,11 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
+ 			/* A length of zero means transfer the whole sg list */
+ 			len = length;
+ 			if (len == 0) {
+-				for_each_sg(sg, sg, nents, i)
+-					len += sg->length;
++				struct scatterlist	*sg2;
++				int			j;
++
++				for_each_sg(sg, sg2, nents, j)
++					len += sg2->length;
+ 			}
+ 		} else {
+ 			/*

commit c043f1245654a726925529007210e9f786426448
+Author: Alan Stern 
+Date:   Fri Jun 4 14:02:42 2010 -0400
+
+    USB: unbind all interfaces before rebinding them
+    
+    This patch (as1387) fixes a bug introduced during the changeover to
+    the runtime PM framework.  When a driver doesn't support resume or
+    reset-resume, and consequently its interfaces need to be unbound and
+    rebound, we have to unbind all the interfaces before trying to rebind
+    any of them.  Otherwise the driver's probe method for one interface
+    could try to claim a different interface and fail, because that other
+    interface hasn't been unbound yet.
+    
+    This fixes Bugzilla #15788.  The symptom is that some USB sound cards
+    don't work after hibernation.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: François Valenduc 
+    Cc: stable  [.34]
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index ded550eda5d9..de98a94d1853 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1328,6 +1328,7 @@ int usb_resume(struct device *dev, pm_message_t msg)
+ 
+ 	/* For all other calls, take the device back to full power and
+ 	 * tell the PM core in case it was autosuspended previously.
++	 * Unbind the interfaces that will need rebinding later.
+ 	 */
+ 	} else {
+ 		status = usb_resume_both(udev, msg);
+@@ -1336,6 +1337,7 @@ int usb_resume(struct device *dev, pm_message_t msg)
+ 			pm_runtime_set_active(dev);
+ 			pm_runtime_enable(dev);
+ 			udev->last_busy = jiffies;
++			do_unbind_rebind(udev, DO_REBIND);
+ 		}
+ 	}
+ 

commit f9e8894ae5157796dd69249c56062042d02a431d
+Author: Alan Stern 
+Date:   Thu Mar 18 15:39:30 2010 -0400
+
+    [SCSI] fix race in scsi_target_reap
+    
+    This patch (as1357) fixes a race in SCSI target allocation and
+    release.  Putting a target in the STARGET_DEL state isn't protected by
+    the host lock, so an old target structure could be reused by a new
+    device even though it's about to be deleted.  The cure is to change
+    the state while still holding the host lock.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+index c992ecf4e372..a77468cd5a33 100644
+--- a/drivers/scsi/scsi_scan.c
++++ b/drivers/scsi/scsi_scan.c
+@@ -492,19 +492,20 @@ void scsi_target_reap(struct scsi_target *starget)
+ 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ 	unsigned long flags;
+ 	enum scsi_target_state state;
+-	int empty;
++	int empty = 0;
+ 
+ 	spin_lock_irqsave(shost->host_lock, flags);
+ 	state = starget->state;
+-	empty = --starget->reap_ref == 0 &&
+-		list_empty(&starget->devices) ? 1 : 0;
++	if (--starget->reap_ref == 0 && list_empty(&starget->devices)) {
++		empty = 1;
++		starget->state = STARGET_DEL;
++	}
+ 	spin_unlock_irqrestore(shost->host_lock, flags);
+ 
+ 	if (!empty)
+ 		return;
+ 
+ 	BUG_ON(state == STARGET_DEL);
+-	starget->state = STARGET_DEL;
+ 	if (state == STARGET_CREATED)
+ 		scsi_target_destroy(starget);
+ 	else

commit ffa156590f98b750161757a16c37ac8e152a7859
+Author: Alan Stern 
+Date:   Mon Mar 8 16:46:19 2010 -0500
+
+    Driver core: don't initialize wakeup flags
+    
+    This patch (as1351) removes an unnecessary and unwanted assignment
+    from device_initialize().  The wakeup flags are set to 0 along with
+    everything else when the device structure is allocated, so we don't
+    need to do it again.  Furthermore, the subsystem might already have
+    set these flags to their correct values; we don't want to override it.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/base/core.c b/drivers/base/core.c
+index b56a0ba31d4a..e11c8c3e7416 100644
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -562,7 +562,6 @@ void device_initialize(struct device *dev)
+ 	init_MUTEX(&dev->sem);
+ 	spin_lock_init(&dev->devres_lock);
+ 	INIT_LIST_HEAD(&dev->devres_head);
+-	device_init_wakeup(dev, 0);
+ 	device_pm_init(dev);
+ 	set_dev_node(dev, -1);
+ }

commit 16032c4f5b291af541e9114a09ea20ff5a0dc474
+Author: Alan Stern 
+Date:   Wed May 12 18:21:35 2010 -0400
+
+    USB: EHCI: fix controller wakeup flag settings during suspend
+    
+    This patch (as1380) fixes a bug in the wakeup settings for EHCI host
+    controllers.  When the controller is suspended, if it isn't enabled
+    for remote wakeup then we have to turn off all the port wakeup flags.
+    Disabling PCI PME# isn't good enough, because some systems (Intel)
+    evidently use alternate wakeup signalling paths.
+    
+    In addition, the patch improves the handling of the Intel Moorestown
+    hardware by performing various power-up and power-down delays just
+    once instead of once for each port (i.e., the delays are moved outside
+    of the port loops).  This requires extra code, but the total delay
+    time is reduced.
+    
+    There are also a few additional minor cleanups.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Ondrej Zary 
+    CC: Alek Du 
+    CC: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
+index 7a27b7c4ee84..faa61748db70 100644
+--- a/drivers/usb/host/ehci-au1xxx.c
++++ b/drivers/usb/host/ehci-au1xxx.c
+@@ -224,26 +224,17 @@ static int ehci_hcd_au1xxx_drv_suspend(struct device *dev)
+ 		msleep(10);
+ 
+ 	/* Root hub was already suspended. Disable irq emission and
+-	 * mark HW unaccessible, bail out if RH has been resumed. Use
+-	 * the spinlock to properly synchronize with possible pending
+-	 * RH suspend or resume activity.
+-	 *
+-	 * This is still racy as hcd->state is manipulated outside of
+-	 * any locks =P But that will be a different fix.
++	 * mark HW unaccessible.  The PM and USB cores make sure that
++	 * the root hub is either suspended or stopped.
+ 	 */
+ 	spin_lock_irqsave(&ehci->lock, flags);
+-	if (hcd->state != HC_STATE_SUSPENDED) {
+-		rc = -EINVAL;
+-		goto bail;
+-	}
++	ehci_prepare_ports_for_controller_suspend(ehci);
+ 	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+ 	(void)ehci_readl(ehci, &ehci->regs->intr_enable);
+ 
+ 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ 
+ 	au1xxx_stop_ehc();
+-
+-bail:
+ 	spin_unlock_irqrestore(&ehci->lock, flags);
+ 
+ 	// could save FLADJ in case of Vaux power loss
+@@ -273,6 +264,7 @@ static int ehci_hcd_au1xxx_drv_resume(struct device *dev)
+ 	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
+ 		int	mask = INTR_MASK;
+ 
++		ehci_prepare_ports_for_controller_resume(ehci);
+ 		if (!hcd->self.root_hub->do_remote_wakeup)
+ 			mask &= ~STS_PCD;
+ 		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
+index 0e26aa13f158..5cd967d28938 100644
+--- a/drivers/usb/host/ehci-fsl.c
++++ b/drivers/usb/host/ehci-fsl.c
+@@ -313,6 +313,7 @@ static int ehci_fsl_drv_suspend(struct device *dev)
+ 	struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);
+ 	void __iomem *non_ehci = hcd->regs;
+ 
++	ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd));
+ 	if (!fsl_deep_sleep())
+ 		return 0;
+ 
+@@ -327,6 +328,7 @@ static int ehci_fsl_drv_resume(struct device *dev)
+ 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ 	void __iomem *non_ehci = hcd->regs;
+ 
++	ehci_prepare_ports_for_controller_resume(ehci);
+ 	if (!fsl_deep_sleep())
+ 		return 0;
+ 
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index ef956220f854..e7d3d8def282 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -106,12 +106,75 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
+ 	ehci->owned_ports = 0;
+ }
+ 
++static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
++		bool suspending)
++{
++	int		port;
++	u32		temp;
++
++	/* If remote wakeup is enabled for the root hub but disabled
++	 * for the controller, we must adjust all the port wakeup flags
++	 * when the controller is suspended or resumed.  In all other
++	 * cases they don't need to be changed.
++	 */
++	if (!ehci_to_hcd(ehci)->self.root_hub->do_remote_wakeup ||
++			device_may_wakeup(ehci_to_hcd(ehci)->self.controller))
++		return;
++
++	/* clear phy low-power mode before changing wakeup flags */
++	if (ehci->has_hostpc) {
++		port = HCS_N_PORTS(ehci->hcs_params);
++		while (port--) {
++			u32 __iomem	*hostpc_reg;
++
++			hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs
++					+ HOSTPC0 + 4 * port);
++			temp = ehci_readl(ehci, hostpc_reg);
++			ehci_writel(ehci, temp & ~HOSTPC_PHCD, hostpc_reg);
++		}
++		msleep(5);
++	}
++
++	port = HCS_N_PORTS(ehci->hcs_params);
++	while (port--) {
++		u32 __iomem	*reg = &ehci->regs->port_status[port];
++		u32		t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
++		u32		t2 = t1 & ~PORT_WAKE_BITS;
++
++		/* If we are suspending the controller, clear the flags.
++		 * If we are resuming the controller, set the wakeup flags.
++		 */
++		if (!suspending) {
++			if (t1 & PORT_CONNECT)
++				t2 |= PORT_WKOC_E | PORT_WKDISC_E;
++			else
++				t2 |= PORT_WKOC_E | PORT_WKCONN_E;
++		}
++		ehci_vdbg(ehci, "port %d, %08x -> %08x\n",
++				port + 1, t1, t2);
++		ehci_writel(ehci, t2, reg);
++	}
++
++	/* enter phy low-power mode again */
++	if (ehci->has_hostpc) {
++		port = HCS_N_PORTS(ehci->hcs_params);
++		while (port--) {
++			u32 __iomem	*hostpc_reg;
++
++			hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs
++					+ HOSTPC0 + 4 * port);
++			temp = ehci_readl(ehci, hostpc_reg);
++			ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg);
++		}
++	}
++}
++
+ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ {
+ 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+ 	int			port;
+ 	int			mask;
+-	u32 __iomem		*hostpc_reg = NULL;
++	int			changed;
+ 
+ 	ehci_dbg(ehci, "suspend root hub\n");
+ 
+@@ -155,15 +218,13 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 	 */
+ 	ehci->bus_suspended = 0;
+ 	ehci->owned_ports = 0;
++	changed = 0;
+ 	port = HCS_N_PORTS(ehci->hcs_params);
+ 	while (port--) {
+ 		u32 __iomem	*reg = &ehci->regs->port_status [port];
+ 		u32		t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
+-		u32		t2 = t1;
++		u32		t2 = t1 & ~PORT_WAKE_BITS;
+ 
+-		if (ehci->has_hostpc)
+-			hostpc_reg = (u32 __iomem *)((u8 *)ehci->regs
+-				+ HOSTPC0 + 4 * (port & 0xff));
+ 		/* keep track of which ports we suspend */
+ 		if (t1 & PORT_OWNER)
+ 			set_bit(port, &ehci->owned_ports);
+@@ -172,40 +233,45 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 			set_bit(port, &ehci->bus_suspended);
+ 		}
+ 
+-		/* enable remote wakeup on all ports */
++		/* enable remote wakeup on all ports, if told to do so */
+ 		if (hcd->self.root_hub->do_remote_wakeup) {
+ 			/* only enable appropriate wake bits, otherwise the
+ 			 * hardware can not go phy low power mode. If a race
+ 			 * condition happens here(connection change during bits
+ 			 * set), the port change detection will finally fix it.
+ 			 */
+-			if (t1 & PORT_CONNECT) {
++			if (t1 & PORT_CONNECT)
+ 				t2 |= PORT_WKOC_E | PORT_WKDISC_E;
+-				t2 &= ~PORT_WKCONN_E;
+-			} else {
++			else
+ 				t2 |= PORT_WKOC_E | PORT_WKCONN_E;
+-				t2 &= ~PORT_WKDISC_E;
+-			}
+-		} else
+-			t2 &= ~PORT_WAKE_BITS;
++		}
+ 
+ 		if (t1 != t2) {
+ 			ehci_vdbg (ehci, "port %d, %08x -> %08x\n",
+ 				port + 1, t1, t2);
+ 			ehci_writel(ehci, t2, reg);
+-			if (hostpc_reg) {
+-				u32	t3;
++			changed = 1;
++		}
++	}
+ 
+-				spin_unlock_irq(&ehci->lock);
+-				msleep(5);/* 5ms for HCD enter low pwr mode */
+-				spin_lock_irq(&ehci->lock);
+-				t3 = ehci_readl(ehci, hostpc_reg);
+-				ehci_writel(ehci, t3 | HOSTPC_PHCD, hostpc_reg);
+-				t3 = ehci_readl(ehci, hostpc_reg);
+-				ehci_dbg(ehci, "Port%d phy low pwr mode %s\n",
++	if (changed && ehci->has_hostpc) {
++		spin_unlock_irq(&ehci->lock);
++		msleep(5);	/* 5 ms for HCD to enter low-power mode */
++		spin_lock_irq(&ehci->lock);
++
++		port = HCS_N_PORTS(ehci->hcs_params);
++		while (port--) {
++			u32 __iomem	*hostpc_reg;
++			u32		t3;
++
++			hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs
++					+ HOSTPC0 + 4 * port);
++			t3 = ehci_readl(ehci, hostpc_reg);
++			ehci_writel(ehci, t3 | HOSTPC_PHCD, hostpc_reg);
++			t3 = ehci_readl(ehci, hostpc_reg);
++			ehci_dbg(ehci, "Port %d phy low-power mode %s\n",
+ 					port, (t3 & HOSTPC_PHCD) ?
+ 					"succeeded" : "failed");
+-			}
+ 		}
+ 	}
+ 
+@@ -291,19 +357,28 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 	msleep(8);
+ 	spin_lock_irq(&ehci->lock);
+ 
++	/* clear phy low-power mode before resume */
++	if (ehci->bus_suspended && ehci->has_hostpc) {
++		i = HCS_N_PORTS(ehci->hcs_params);
++		while (i--) {
++			if (test_bit(i, &ehci->bus_suspended)) {
++				u32 __iomem	*hostpc_reg;
++
++				hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs
++						+ HOSTPC0 + 4 * i);
++				temp = ehci_readl(ehci, hostpc_reg);
++				ehci_writel(ehci, temp & ~HOSTPC_PHCD,
++						hostpc_reg);
++			}
++		}
++		spin_unlock_irq(&ehci->lock);
++		msleep(5);
++		spin_lock_irq(&ehci->lock);
++	}
++
+ 	/* manually resume the ports we suspended during bus_suspend() */
+ 	i = HCS_N_PORTS (ehci->hcs_params);
+ 	while (i--) {
+-		/* clear phy low power mode before resume */
+-		if (ehci->has_hostpc) {
+-			u32 __iomem	*hostpc_reg =
+-				(u32 __iomem *)((u8 *)ehci->regs
+-				+ HOSTPC0 + 4 * (i & 0xff));
+-			temp = ehci_readl(ehci, hostpc_reg);
+-			ehci_writel(ehci, temp & ~HOSTPC_PHCD,
+-				hostpc_reg);
+-			mdelay(5);
+-		}
+ 		temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
+ 		temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
+ 		if (test_bit(i, &ehci->bus_suspended) &&
+@@ -685,23 +760,25 @@ static int ehci_hub_control (
+ 				goto error;
+ 			if (ehci->no_selective_suspend)
+ 				break;
+-			if (temp & PORT_SUSPEND) {
+-				if ((temp & PORT_PE) == 0)
+-					goto error;
+-				/* clear phy low power mode before resume */
+-				if (hostpc_reg) {
+-					temp1 = ehci_readl(ehci, hostpc_reg);
+-					ehci_writel(ehci, temp1 & ~HOSTPC_PHCD,
++			if (!(temp & PORT_SUSPEND))
++				break;
++			if ((temp & PORT_PE) == 0)
++				goto error;
++
++			/* clear phy low-power mode before resume */
++			if (hostpc_reg) {
++				temp1 = ehci_readl(ehci, hostpc_reg);
++				ehci_writel(ehci, temp1 & ~HOSTPC_PHCD,
+ 						hostpc_reg);
+-					mdelay(5);
+-				}
+-				/* resume signaling for 20 msec */
+-				temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
+-				ehci_writel(ehci, temp | PORT_RESUME,
+-						status_reg);
+-				ehci->reset_done [wIndex] = jiffies
+-						+ msecs_to_jiffies (20);
++				spin_unlock_irqrestore(&ehci->lock, flags);
++				msleep(5);/* wait to leave low-power mode */
++				spin_lock_irqsave(&ehci->lock, flags);
+ 			}
++			/* resume signaling for 20 msec */
++			temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
++			ehci_writel(ehci, temp | PORT_RESUME, status_reg);
++			ehci->reset_done[wIndex] = jiffies
++					+ msecs_to_jiffies(20);
+ 			break;
+ 		case USB_PORT_FEAT_C_SUSPEND:
+ 			clear_bit(wIndex, &ehci->port_c_suspend);
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index d120059bbbf7..d43d176161aa 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -287,23 +287,15 @@ static int ehci_pci_suspend(struct usb_hcd *hcd)
+ 		msleep(10);
+ 
+ 	/* Root hub was already suspended. Disable irq emission and
+-	 * mark HW unaccessible, bail out if RH has been resumed. Use
+-	 * the spinlock to properly synchronize with possible pending
+-	 * RH suspend or resume activity.
+-	 *
+-	 * This is still racy as hcd->state is manipulated outside of
+-	 * any locks =P But that will be a different fix.
++	 * mark HW unaccessible.  The PM and USB cores make sure that
++	 * the root hub is either suspended or stopped.
+ 	 */
+ 	spin_lock_irqsave (&ehci->lock, flags);
+-	if (hcd->state != HC_STATE_SUSPENDED) {
+-		rc = -EINVAL;
+-		goto bail;
+-	}
++	ehci_prepare_ports_for_controller_suspend(ehci);
+ 	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+ 	(void)ehci_readl(ehci, &ehci->regs->intr_enable);
+ 
+ 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+- bail:
+ 	spin_unlock_irqrestore (&ehci->lock, flags);
+ 
+ 	// could save FLADJ in case of Vaux power loss
+@@ -333,6 +325,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)
+ 				!hibernated) {
+ 		int	mask = INTR_MASK;
+ 
++		ehci_prepare_ports_for_controller_resume(ehci);
+ 		if (!hcd->self.root_hub->do_remote_wakeup)
+ 			mask &= ~STS_PCD;
+ 		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 4ebe9ad209e4..650a687f2854 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -536,6 +536,16 @@ struct ehci_fstn {
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++/* Prepare the PORTSC wakeup flags during controller suspend/resume */
++
++#define ehci_prepare_ports_for_controller_suspend(ehci)		\
++		ehci_adjust_port_wakeup_flags(ehci, true);
++
++#define ehci_prepare_ports_for_controller_resume(ehci)		\
++		ehci_adjust_port_wakeup_flags(ehci, false);
++
++/*-------------------------------------------------------------------------*/
++
+ #ifdef CONFIG_USB_EHCI_ROOT_HUB_TT
+ 
+ /*

commit 89842ae6515c49405e20c0629a6442b6885ad49d
+Author: Alan Stern 
+Date:   Tue May 11 11:44:06 2010 -0400
+
+    USB: fix interface runtime-PM settings
+    
+    This patch (as1379) reworks the logic for handling USB interface
+    runtime-PM settings -- hopefully it's right this time!  The problem is
+    that when a driver is unbound or binding fails, runtime PM for the
+    interface always gets disabled.  But pm_runtime_disable() nests, so it
+    shouldn't be called unless the interface was previously enabled for
+    runtime PM.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Rob Duncan 
+    Tested-by: Rob Duncan 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 207146743ea7..ded550eda5d9 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -334,7 +334,8 @@ static int usb_probe_interface(struct device *dev)
+ 	usb_cancel_queued_reset(intf);
+ 
+ 	/* Unbound interfaces are always runtime-PM-disabled and -suspended */
+-	pm_runtime_disable(dev);
++	if (driver->supports_autosuspend)
++		pm_runtime_disable(dev);
+ 	pm_runtime_set_suspended(dev);
+ 
+ 	usb_autosuspend_device(udev);
+@@ -389,7 +390,8 @@ static int usb_unbind_interface(struct device *dev)
+ 	intf->needs_remote_wakeup = 0;
+ 
+ 	/* Unbound interfaces are always runtime-PM-disabled and -suspended */
+-	pm_runtime_disable(dev);
++	if (driver->supports_autosuspend)
++		pm_runtime_disable(dev);
+ 	pm_runtime_set_suspended(dev);
+ 
+ 	/* Undo any residual pm_autopm_get_interface_* calls */
+@@ -438,14 +440,17 @@ int usb_driver_claim_interface(struct usb_driver *driver,
+ 
+ 	iface->condition = USB_INTERFACE_BOUND;
+ 
+-	/* Claimed interfaces are initially inactive (suspended).  They are
+-	 * runtime-PM-enabled only if the driver has autosuspend support.
+-	 * They are sensitive to their children's power states.
++	/* Claimed interfaces are initially inactive (suspended) and
++	 * runtime-PM-enabled, but only if the driver has autosuspend
++	 * support.  Otherwise they are marked active, to prevent the
++	 * device from being autosuspended, but left disabled.  In either
++	 * case they are sensitive to their children's power states.
+ 	 */
+-	pm_runtime_set_suspended(dev);
+ 	pm_suspend_ignore_children(dev, false);
+ 	if (driver->supports_autosuspend)
+ 		pm_runtime_enable(dev);
++	else
++		pm_runtime_set_active(dev);
+ 
+ 	/* if interface was already added, bind now; else let
+ 	 * the future device_add() bind it, bypassing probe()

commit 0ba169aff9181389f30f225ad92e113eeb2290b9
+Author: Alan Stern 
+Date:   Wed May 5 15:26:17 2010 -0400
+
+    USB: simplify usb_sg_init()
+    
+    This patch (as1377) simplifies the code in usb_sg_init(), without
+    changing its functionality.  It also removes a couple of unused fields
+    from the usb_sg_request structure.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 63919b8abee1..a73e08fdab36 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -371,79 +371,64 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
+ 	spin_lock_init(&io->lock);
+ 	io->dev = dev;
+ 	io->pipe = pipe;
+-	io->sg = sg;
+-	io->nents = nents;
+-	io->entries = nents;
+ 
+-	/* initialize all the urbs we'll use */
+ 	if (dev->bus->sg_tablesize > 0) {
+-		io->urbs = kmalloc(sizeof *io->urbs, mem_flags);
+ 		use_sg = true;
++		io->entries = 1;
+ 	} else {
+-		io->urbs = kmalloc(io->entries * sizeof *io->urbs, mem_flags);
+ 		use_sg = false;
++		io->entries = nents;
+ 	}
++
++	/* initialize all the urbs we'll use */
++	io->urbs = kmalloc(io->entries * sizeof *io->urbs, mem_flags);
+ 	if (!io->urbs)
+ 		goto nomem;
+ 
+-	urb_flags = 0;
++	urb_flags = URB_NO_INTERRUPT;
+ 	if (usb_pipein(pipe))
+ 		urb_flags |= URB_SHORT_NOT_OK;
+ 
+-	if (use_sg) {
+-		io->urbs[0] = usb_alloc_urb(0, mem_flags);
+-		if (!io->urbs[0]) {
+-			io->entries = 0;
+-			goto nomem;
+-		}
+-
+-		io->urbs[0]->dev = NULL;
+-		io->urbs[0]->pipe = pipe;
+-		io->urbs[0]->interval = period;
+-		io->urbs[0]->transfer_flags = urb_flags;
++	for_each_sg(sg, sg, io->entries, i) {
++		struct urb *urb;
++		unsigned len;
+ 
+-		io->urbs[0]->complete = sg_complete;
+-		io->urbs[0]->context = io;
+-
+-		/* A length of zero means transfer the whole sg list */
+-		io->urbs[0]->transfer_buffer_length = length;
+-		if (length == 0) {
+-			for_each_sg(sg, sg, io->entries, i) {
+-				io->urbs[0]->transfer_buffer_length +=
+-					sg->length;
+-			}
++		urb = usb_alloc_urb(0, mem_flags);
++		if (!urb) {
++			io->entries = i;
++			goto nomem;
+ 		}
+-		io->urbs[0]->sg = sg;
+-		io->urbs[0]->num_sgs = io->entries;
+-		io->entries = 1;
+-	} else {
+-		urb_flags |= URB_NO_INTERRUPT;
+-		for_each_sg(sg, sg, io->entries, i) {
+-			unsigned len;
+-
+-			io->urbs[i] = usb_alloc_urb(0, mem_flags);
+-			if (!io->urbs[i]) {
+-				io->entries = i;
+-				goto nomem;
++		io->urbs[i] = urb;
++
++		urb->dev = NULL;
++		urb->pipe = pipe;
++		urb->interval = period;
++		urb->transfer_flags = urb_flags;
++		urb->complete = sg_complete;
++		urb->context = io;
++		urb->sg = sg;
++
++		if (use_sg) {
++			/* There is no single transfer buffer */
++			urb->transfer_buffer = NULL;
++			urb->num_sgs = nents;
++
++			/* A length of zero means transfer the whole sg list */
++			len = length;
++			if (len == 0) {
++				for_each_sg(sg, sg, nents, i)
++					len += sg->length;
+ 			}
+-
+-			io->urbs[i]->dev = NULL;
+-			io->urbs[i]->pipe = pipe;
+-			io->urbs[i]->interval = period;
+-			io->urbs[i]->transfer_flags = urb_flags;
+-
+-			io->urbs[i]->complete = sg_complete;
+-			io->urbs[i]->context = io;
+-
++		} else {
+ 			/*
+ 			 * Some systems can't use DMA; they use PIO instead.
+ 			 * For their sakes, transfer_buffer is set whenever
+ 			 * possible.
+ 			 */
+ 			if (!PageHighMem(sg_page(sg)))
+-				io->urbs[i]->transfer_buffer = sg_virt(sg);
++				urb->transfer_buffer = sg_virt(sg);
+ 			else
+-				io->urbs[i]->transfer_buffer = NULL;
++				urb->transfer_buffer = NULL;
+ 
+ 			len = sg->length;
+ 			if (length) {
+@@ -452,12 +437,10 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
+ 				if (length == 0)
+ 					io->entries = i + 1;
+ 			}
+-			io->urbs[i]->transfer_buffer_length = len;
+-
+-			io->urbs[i]->sg = sg;
+ 		}
+-		io->urbs[--i]->transfer_flags &= ~URB_NO_INTERRUPT;
++		urb->transfer_buffer_length = len;
+ 	}
++	io->urbs[--i]->transfer_flags &= ~URB_NO_INTERRUPT;
+ 
+ 	/* transaction state */
+ 	io->count = io->entries;
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index eec9e74f332f..ce07062ebc28 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -1469,8 +1469,6 @@ struct usb_sg_request {
+ 
+ 	struct usb_device	*dev;
+ 	int			pipe;
+-	struct scatterlist	*sg;
+-	int			nents;
+ 
+ 	int			entries;
+ 	struct urb		**urbs;

commit 85bcb5ee889e0ebb9154718939e049de265fcdfb
+Author: Alan Stern 
+Date:   Fri Apr 30 16:35:37 2010 -0400
+
+    USB: remove URB_NO_SETUP_DMA_MAP
+    
+    Now that URB_NO_SETUP_DMA_MAP is no longer in use, this patch (as1376)
+    removes all references to it.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/usb/dma.txt b/Documentation/usb/dma.txt
+index a37e59cf2786..84ef865237db 100644
+--- a/Documentation/usb/dma.txt
++++ b/Documentation/usb/dma.txt
+@@ -16,11 +16,11 @@ OR:  they can now be DMA-aware.
+   manage dma mappings for existing dma-ready buffers (see below).
+ 
+ - URBs have an additional "transfer_dma" field, as well as a transfer_flags
+-  bit saying if it's valid.  (Control requests also have "setup_dma" and a
+-  corresponding transfer_flags bit.)
++  bit saying if it's valid.  (Control requests also have "setup_dma", but
++  drivers must not use it.)
+ 
+-- "usbcore" will map those DMA addresses, if a DMA-aware driver didn't do
+-  it first and set URB_NO_TRANSFER_DMA_MAP or URB_NO_SETUP_DMA_MAP.  HCDs
++- "usbcore" will map this DMA address, if a DMA-aware driver didn't do
++  it first and set URB_NO_TRANSFER_DMA_MAP.  HCDs
+   don't manage dma mappings for URBs.
+ 
+ - There's a new "generic DMA API", parts of which are usable by USB device
+@@ -53,12 +53,6 @@ and effects like cache-trashing can impose subtle penalties.
+   to use this type of memory ("dma-coherent"), and memory returned from
+   kmalloc() will work just fine.
+ 
+-  For control transfers you can use the buffer primitives or not for each
+-  of the transfer buffer and setup buffer independently.  Set the flag bits
+-  URB_NO_TRANSFER_DMA_MAP and URB_NO_SETUP_DMA_MAP to indicate which
+-  buffers you have prepared.  For non-control transfers URB_NO_SETUP_DMA_MAP
+-  is ignored.
+-
+   The memory buffer returned is "dma-coherent"; sometimes you might need to
+   force a consistent memory access ordering by using memory barriers.  It's
+   not using a streaming DMA mapping, so it's good for small transfers on
+@@ -130,8 +124,8 @@ of Documentation/PCI/PCI-DMA-mapping.txt, titled "What memory is DMA-able?")
+ 	void usb_buffer_unmap (struct urb *urb);
+ 
+   The calls manage urb->transfer_dma for you, and set URB_NO_TRANSFER_DMA_MAP
+-  so that usbcore won't map or unmap the buffer.  The same goes for
+-  urb->setup_dma and URB_NO_SETUP_DMA_MAP for control requests.
++  so that usbcore won't map or unmap the buffer.  They cannot be used for
++  setup_packet buffers in control requests.
+ 
+ Note that several of those interfaces are currently commented out, since
+ they don't have current users.  See the source code.  Other than the dmasync
+diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c
+index e3fa4216c1cd..52408164036f 100644
+--- a/drivers/staging/usbip/usbip_common.c
++++ b/drivers/staging/usbip/usbip_common.c
+@@ -562,7 +562,7 @@ EXPORT_SYMBOL_GPL(sockfd_to_socket);
+ /* there may be more cases to tweak the flags. */
+ static unsigned int tweak_transfer_flags(unsigned int flags)
+ {
+-	flags &= ~(URB_NO_TRANSFER_DMA_MAP|URB_NO_SETUP_DMA_MAP);
++	flags &= ~URB_NO_TRANSFER_DMA_MAP;
+ 	return flags;
+ }
+ 
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 3aaee2811f01..0abc5c537f39 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1316,8 +1316,7 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
+ 	 * or uses the provided scatter gather list for bulk.
+ 	 */
+ 
+-	if (usb_endpoint_xfer_control(&urb->ep->desc)
+-	    && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) {
++	if (usb_endpoint_xfer_control(&urb->ep->desc)) {
+ 		if (hcd->self.uses_dma) {
+ 			urb->setup_dma = dma_map_single(
+ 					hcd->self.controller,
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index a748815ee629..1eb4762d9ea8 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -953,7 +953,6 @@ extern int usb_disabled(void);
+ #define URB_ISO_ASAP		0x0002	/* iso-only, urb->start_frame
+ 					 * ignored */
+ #define URB_NO_TRANSFER_DMA_MAP	0x0004	/* urb->transfer_dma valid on submit */
+-#define URB_NO_SETUP_DMA_MAP	0x0008	/* urb->setup_dma valid on submit */
+ #define URB_NO_FSBR		0x0020	/* UHCI-specific */
+ #define URB_ZERO_PACKET		0x0040	/* Finish bulk OUT with short packet */
+ #define URB_NO_INTERRUPT	0x0080	/* HINT: no non-error interrupt
+@@ -1049,12 +1048,8 @@ typedef void (*usb_complete_t)(struct urb *);
+  * @setup_packet: Only used for control transfers, this points to eight bytes
+  *	of setup data.  Control transfers always start by sending this data
+  *	to the device.  Then transfer_buffer is read or written, if needed.
+- * @setup_dma: For control transfers with URB_NO_SETUP_DMA_MAP set, the
+- *	device driver has provided this DMA address for the setup packet.
+- *	The host controller driver should use this in preference to
+- *	setup_packet, but the HCD may chose to ignore the address if it must
+- *	copy the setup packet into internal structures.  Therefore, setup_packet
+- *	must always point to a valid buffer.
++ * @setup_dma: DMA pointer for the setup packet.  The caller must not use
++ *	this field; setup_packet must point to a valid buffer.
+  * @start_frame: Returns the initial frame for isochronous transfers.
+  * @number_of_packets: Lists the number of ISO transfer buffers.
+  * @interval: Specifies the polling interval for interrupt or isochronous
+@@ -1086,13 +1081,14 @@ typedef void (*usb_complete_t)(struct urb *);
+  * bounce buffer or talking to an IOMMU),
+  * although they're cheap on commodity x86 and ppc hardware.
+  *
+- * Alternatively, drivers may pass the URB_NO_xxx_DMA_MAP transfer flags,
+- * which tell the host controller driver that no such mapping is needed since
++ * Alternatively, drivers may pass the URB_NO_TRANSFER_DMA_MAP transfer flag,
++ * which tells the host controller driver that no such mapping is needed for
++ * the transfer_buffer since
+  * the device driver is DMA-aware.  For example, a device driver might
+  * allocate a DMA buffer with usb_alloc_coherent() or call usb_buffer_map().
+- * When these transfer flags are provided, host controller drivers will
+- * attempt to use the dma addresses found in the transfer_dma and/or
+- * setup_dma fields rather than determining a dma address themselves.
++ * When this transfer flag is provided, host controller drivers will
++ * attempt to use the dma address found in the transfer_dma
++ * field rather than determining a dma address themselves.
+  *
+  * Note that transfer_buffer must still be set if the controller
+  * does not support DMA (as indicated by bus.uses_dma) and when talking
+@@ -1115,11 +1111,9 @@ typedef void (*usb_complete_t)(struct urb *);
+  * should always terminate with a short packet, even if it means adding an
+  * extra zero length packet.
+  *
+- * Control URBs must provide a setup_packet.  The setup_packet and
+- * transfer_buffer may each be mapped for DMA or not, independently of
+- * the other.  The transfer_flags bits URB_NO_TRANSFER_DMA_MAP and
+- * URB_NO_SETUP_DMA_MAP indicate which buffers have already been mapped.
+- * URB_NO_SETUP_DMA_MAP is ignored for non-control URBs.
++ * Control URBs must provide a valid pointer in the setup_packet field.
++ * Unlike the transfer_buffer, the setup_packet may not be mapped for DMA
++ * beforehand.
+  *
+  * Interrupt URBs must provide an interval, saying how often (in milliseconds
+  * or, for highspeed devices, 125 microsecond units)

commit 842f16905dfc6743c1dd80c3d29b49ba3ab7f7c8
+Author: Alan Stern 
+Date:   Fri Apr 30 12:44:46 2010 -0400
+
+    USB: remove the usb_host_ss_ep_comp structure
+    
+    This patch (as1375) eliminates the usb_host_ss_ep_comp structure used
+    for storing a dynamically-allocated copy of the SuperSpeed endpoint
+    companion descriptor.  The SuperSpeed descriptor is placed directly in
+    the usb_host_endpoint structure, alongside the standard endpoint
+    descriptor.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Sarah Sharp 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
+index e4909c26becb..83126b03e7cf 100644
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -21,32 +21,6 @@ static inline const char *plural(int n)
+ 	return (n == 1 ? "" : "s");
+ }
+ 
+-/* FIXME: this is a kludge */
+-static int find_next_descriptor_more(unsigned char *buffer, int size,
+-    int dt1, int dt2, int dt3, int *num_skipped)
+-{
+-	struct usb_descriptor_header *h;
+-	int n = 0;
+-	unsigned char *buffer0 = buffer;
+-
+-	/* Find the next descriptor of type dt1 or dt2 or dt3 */
+-	while (size > 0) {
+-		h = (struct usb_descriptor_header *) buffer;
+-		if (h->bDescriptorType == dt1 || h->bDescriptorType == dt2 ||
+-				h->bDescriptorType == dt3)
+-			break;
+-		buffer += h->bLength;
+-		size -= h->bLength;
+-		++n;
+-	}
+-
+-	/* Store the number of descriptors skipped and return the
+-	 * number of bytes skipped */
+-	if (num_skipped)
+-		*num_skipped = n;
+-	return buffer - buffer0;
+-}
+-
+ static int find_next_descriptor(unsigned char *buffer, int size,
+     int dt1, int dt2, int *num_skipped)
+ {
+@@ -71,47 +45,41 @@ static int find_next_descriptor(unsigned char *buffer, int size,
+ 	return buffer - buffer0;
+ }
+ 
+-static int usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
++static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
+ 		int inum, int asnum, struct usb_host_endpoint *ep,
+-		int num_ep, unsigned char *buffer, int size)
++		unsigned char *buffer, int size)
+ {
+-	unsigned char *buffer_start = buffer;
+-	struct usb_ss_ep_comp_descriptor	*desc;
+-	int retval;
+-	int num_skipped;
++	struct usb_ss_ep_comp_descriptor *desc;
+ 	int max_tx;
+-	int i;
+ 
++	/* The SuperSpeed endpoint companion descriptor is supposed to
++	 * be the first thing immediately following the endpoint descriptor.
++	 */
+ 	desc = (struct usb_ss_ep_comp_descriptor *) buffer;
+-	if (desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP) {
++	if (desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP ||
++			size < USB_DT_SS_EP_COMP_SIZE) {
+ 		dev_warn(ddev, "No SuperSpeed endpoint companion for config %d "
+ 				" interface %d altsetting %d ep %d: "
+ 				"using minimum values\n",
+ 				cfgno, inum, asnum, ep->desc.bEndpointAddress);
+-		/*
+-		 * The next descriptor is for an Endpoint or Interface,
+-		 * no extra descriptors to copy into the companion structure,
+-		 * and we didn't eat up any of the buffer.
++
++		/* Fill in some default values.
++		 * Leave bmAttributes as zero, which will mean no streams for
++		 * bulk, and isoc won't support multiple bursts of packets.
++		 * With bursts of only one packet, and a Mult of 1, the max
++		 * amount of data moved per endpoint service interval is one
++		 * packet.
+ 		 */
+-		return 0;
++		ep->ss_ep_comp.bLength = USB_DT_SS_EP_COMP_SIZE;
++		ep->ss_ep_comp.bDescriptorType = USB_DT_SS_ENDPOINT_COMP;
++		if (usb_endpoint_xfer_isoc(&ep->desc) ||
++				usb_endpoint_xfer_int(&ep->desc))
++			ep->ss_ep_comp.wBytesPerInterval =
++					ep->desc.wMaxPacketSize;
++		return;
+ 	}
+-	memcpy(&ep->ss_ep_comp->desc, desc, USB_DT_SS_EP_COMP_SIZE);
+-	desc = &ep->ss_ep_comp->desc;
+-	buffer += desc->bLength;
+-	size -= desc->bLength;
+ 
+-	/* Eat up the other descriptors we don't care about */
+-	ep->ss_ep_comp->extra = buffer;
+-	i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
+-			USB_DT_INTERFACE, &num_skipped);
+-	ep->ss_ep_comp->extralen = i;
+-	buffer += i;
+-	size -= i;
+-	retval = buffer - buffer_start;
+-	if (num_skipped > 0)
+-		dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
+-				num_skipped, plural(num_skipped),
+-				"SuperSpeed endpoint companion");
++	memcpy(&ep->ss_ep_comp, desc, USB_DT_SS_EP_COMP_SIZE);
+ 
+ 	/* Check the various values */
+ 	if (usb_endpoint_xfer_control(&ep->desc) && desc->bMaxBurst != 0) {
+@@ -119,47 +87,48 @@ static int usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
+ 				"config %d interface %d altsetting %d ep %d: "
+ 				"setting to zero\n", desc->bMaxBurst,
+ 				cfgno, inum, asnum, ep->desc.bEndpointAddress);
+-		desc->bMaxBurst = 0;
+-	}
+-	if (desc->bMaxBurst > 15) {
++		ep->ss_ep_comp.bMaxBurst = 0;
++	} else if (desc->bMaxBurst > 15) {
+ 		dev_warn(ddev, "Endpoint with bMaxBurst = %d in "
+ 				"config %d interface %d altsetting %d ep %d: "
+ 				"setting to 15\n", desc->bMaxBurst,
+ 				cfgno, inum, asnum, ep->desc.bEndpointAddress);
+-		desc->bMaxBurst = 15;
++		ep->ss_ep_comp.bMaxBurst = 15;
+ 	}
+-	if ((usb_endpoint_xfer_control(&ep->desc) || usb_endpoint_xfer_int(&ep->desc))
+-			&& desc->bmAttributes != 0) {
++
++	if ((usb_endpoint_xfer_control(&ep->desc) ||
++			usb_endpoint_xfer_int(&ep->desc)) &&
++				desc->bmAttributes != 0) {
+ 		dev_warn(ddev, "%s endpoint with bmAttributes = %d in "
+ 				"config %d interface %d altsetting %d ep %d: "
+ 				"setting to zero\n",
+ 				usb_endpoint_xfer_control(&ep->desc) ? "Control" : "Bulk",
+ 				desc->bmAttributes,
+ 				cfgno, inum, asnum, ep->desc.bEndpointAddress);
+-		desc->bmAttributes = 0;
+-	}
+-	if (usb_endpoint_xfer_bulk(&ep->desc) && desc->bmAttributes > 16) {
++		ep->ss_ep_comp.bmAttributes = 0;
++	} else if (usb_endpoint_xfer_bulk(&ep->desc) &&
++			desc->bmAttributes > 16) {
+ 		dev_warn(ddev, "Bulk endpoint with more than 65536 streams in "
+ 				"config %d interface %d altsetting %d ep %d: "
+ 				"setting to max\n",
+ 				cfgno, inum, asnum, ep->desc.bEndpointAddress);
+-		desc->bmAttributes = 16;
+-	}
+-	if (usb_endpoint_xfer_isoc(&ep->desc) && desc->bmAttributes > 2) {
++		ep->ss_ep_comp.bmAttributes = 16;
++	} else if (usb_endpoint_xfer_isoc(&ep->desc) &&
++			desc->bmAttributes > 2) {
+ 		dev_warn(ddev, "Isoc endpoint has Mult of %d in "
+ 				"config %d interface %d altsetting %d ep %d: "
+ 				"setting to 3\n", desc->bmAttributes + 1,
+ 				cfgno, inum, asnum, ep->desc.bEndpointAddress);
+-		desc->bmAttributes = 2;
++		ep->ss_ep_comp.bmAttributes = 2;
+ 	}
+-	if (usb_endpoint_xfer_isoc(&ep->desc)) {
++
++	if (usb_endpoint_xfer_isoc(&ep->desc))
+ 		max_tx = ep->desc.wMaxPacketSize * (desc->bMaxBurst + 1) *
+ 			(desc->bmAttributes + 1);
+-	} else if (usb_endpoint_xfer_int(&ep->desc)) {
++	else if (usb_endpoint_xfer_int(&ep->desc))
+ 		max_tx = ep->desc.wMaxPacketSize * (desc->bMaxBurst + 1);
+-	} else {
+-		goto valid;
+-	}
++	else
++		max_tx = 999999;
+ 	if (desc->wBytesPerInterval > max_tx) {
+ 		dev_warn(ddev, "%s endpoint with wBytesPerInterval of %d in "
+ 				"config %d interface %d altsetting %d ep %d: "
+@@ -168,10 +137,8 @@ static int usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
+ 				desc->wBytesPerInterval,
+ 				cfgno, inum, asnum, ep->desc.bEndpointAddress,
+ 				max_tx);
+-		desc->wBytesPerInterval = max_tx;
++		ep->ss_ep_comp.wBytesPerInterval = max_tx;
+ 	}
+-valid:
+-	return retval;
+ }
+ 
+ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
+@@ -293,61 +260,19 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
+ 				cfgno, inum, asnum, d->bEndpointAddress,
+ 				maxp);
+ 	}
+-	/* Allocate room for and parse any SS endpoint companion descriptors */
+-	if (to_usb_device(ddev)->speed == USB_SPEED_SUPER) {
+-		endpoint->extra = buffer;
+-		i = find_next_descriptor_more(buffer, size, USB_DT_SS_ENDPOINT_COMP,
+-				USB_DT_ENDPOINT, USB_DT_INTERFACE, &n);
+-		endpoint->extralen = i;
+-		buffer += i;
+-		size -= i;
+-
+-		/* Allocate space for the SS endpoint companion descriptor */
+-		endpoint->ss_ep_comp = kzalloc(sizeof(struct usb_host_ss_ep_comp),
+-				GFP_KERNEL);
+-		if (!endpoint->ss_ep_comp)
+-			return -ENOMEM;
+ 
+-		/* Fill in some default values (may be overwritten later) */
+-		endpoint->ss_ep_comp->desc.bLength = USB_DT_SS_EP_COMP_SIZE;
+-		endpoint->ss_ep_comp->desc.bDescriptorType = USB_DT_SS_ENDPOINT_COMP;
+-		endpoint->ss_ep_comp->desc.bMaxBurst = 0;
+-		/*
+-		 * Leave bmAttributes as zero, which will mean no streams for
+-		 * bulk, and isoc won't support multiple bursts of packets.
+-		 * With bursts of only one packet, and a Mult of 1, the max
+-		 * amount of data moved per endpoint service interval is one
+-		 * packet.
+-		 */
+-		if (usb_endpoint_xfer_isoc(&endpoint->desc) ||
+-				usb_endpoint_xfer_int(&endpoint->desc))
+-			endpoint->ss_ep_comp->desc.wBytesPerInterval =
+-				endpoint->desc.wMaxPacketSize;
+-
+-		if (size > 0) {
+-			retval = usb_parse_ss_endpoint_companion(ddev, cfgno,
+-					inum, asnum, endpoint, num_ep, buffer,
+-					size);
+-			if (retval >= 0) {
+-				buffer += retval;
+-				retval = buffer - buffer0;
+-			}
+-		} else {
+-			dev_warn(ddev, "config %d interface %d altsetting %d "
+-				"endpoint 0x%X has no "
+-				"SuperSpeed companion descriptor\n",
+-				cfgno, inum, asnum, d->bEndpointAddress);
+-			retval = buffer - buffer0;
+-		}
+-	} else {
+-		/* Skip over any Class Specific or Vendor Specific descriptors;
+-		 * find the next endpoint or interface descriptor */
+-		endpoint->extra = buffer;
+-		i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
+-				USB_DT_INTERFACE, &n);
+-		endpoint->extralen = i;
+-		retval = buffer - buffer0 + i;
+-	}
++	/* Parse a possible SuperSpeed endpoint companion descriptor */
++	if (to_usb_device(ddev)->speed == USB_SPEED_SUPER)
++		usb_parse_ss_endpoint_companion(ddev, cfgno,
++				inum, asnum, endpoint, buffer, size);
++
++	/* Skip over any Class Specific or Vendor Specific descriptors;
++	 * find the next endpoint or interface descriptor */
++	endpoint->extra = buffer;
++	i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
++			USB_DT_INTERFACE, &n);
++	endpoint->extralen = i;
++	retval = buffer - buffer0 + i;
+ 	if (n > 0)
+ 		dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
+ 		    n, plural(n), "endpoint");
+diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
+index 4df752cb0f78..fd9e03afd91c 100644
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -1010,9 +1010,9 @@ static inline unsigned int xhci_get_endpoint_interval(struct usb_device *udev,
+ static inline u32 xhci_get_endpoint_mult(struct usb_device *udev,
+ 		struct usb_host_endpoint *ep)
+ {
+-	if (udev->speed != USB_SPEED_SUPER || !ep->ss_ep_comp)
++	if (udev->speed != USB_SPEED_SUPER)
+ 		return 0;
+-	return ep->ss_ep_comp->desc.bmAttributes;
++	return ep->ss_ep_comp.bmAttributes;
+ }
+ 
+ static inline u32 xhci_get_endpoint_type(struct usb_device *udev,
+@@ -1061,13 +1061,8 @@ static inline u32 xhci_get_max_esit_payload(struct xhci_hcd *xhci,
+ 			usb_endpoint_xfer_bulk(&ep->desc))
+ 		return 0;
+ 
+-	if (udev->speed == USB_SPEED_SUPER) {
+-		if (ep->ss_ep_comp)
+-			return ep->ss_ep_comp->desc.wBytesPerInterval;
+-		xhci_warn(xhci, "WARN no SS endpoint companion descriptor.\n");
+-		/* Assume no bursts, no multiple opportunities to send. */
+-		return ep->desc.wMaxPacketSize;
+-	}
++	if (udev->speed == USB_SPEED_SUPER)
++		return ep->ss_ep_comp.wBytesPerInterval;
+ 
+ 	max_packet = ep->desc.wMaxPacketSize & 0x3ff;
+ 	max_burst = (ep->desc.wMaxPacketSize & 0x1800) >> 11;
+@@ -1131,12 +1126,9 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
+ 		max_packet = ep->desc.wMaxPacketSize;
+ 		ep_ctx->ep_info2 |= MAX_PACKET(max_packet);
+ 		/* dig out max burst from ep companion desc */
+-		if (!ep->ss_ep_comp) {
+-			xhci_warn(xhci, "WARN no SS endpoint companion descriptor.\n");
+-			max_packet = 0;
+-		} else {
+-			max_packet = ep->ss_ep_comp->desc.bMaxBurst;
+-		}
++		max_packet = ep->ss_ep_comp.bMaxBurst;
++		if (!max_packet)
++			xhci_warn(xhci, "WARN no SS endpoint bMaxBurst\n");
+ 		ep_ctx->ep_info2 |= MAX_BURST(max_packet);
+ 		break;
+ 	case USB_SPEED_HIGH:
+diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
+index 3cac2ff8b50a..59f38a5f2fe6 100644
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -1476,13 +1476,7 @@ static int xhci_check_streams_endpoint(struct xhci_hcd *xhci,
+ 	ret = xhci_check_args(xhci_to_hcd(xhci), udev, ep, 1, __func__);
+ 	if (ret <= 0)
+ 		return -EINVAL;
+-	if (!ep->ss_ep_comp) {
+-		xhci_warn(xhci, "WARN: No SuperSpeed Endpoint Companion"
+-				" descriptor for ep 0x%x\n",
+-				ep->desc.bEndpointAddress);
+-		return -EINVAL;
+-	}
+-	if (ep->ss_ep_comp->desc.bmAttributes == 0) {
++	if (ep->ss_ep_comp.bmAttributes == 0) {
+ 		xhci_warn(xhci, "WARN: SuperSpeed Endpoint Companion"
+ 				" descriptor for ep 0x%x does not support streams\n",
+ 				ep->desc.bEndpointAddress);
+@@ -1540,7 +1534,6 @@ static int xhci_calculate_streams_and_bitmask(struct xhci_hcd *xhci,
+ 		struct usb_host_endpoint **eps, unsigned int num_eps,
+ 		unsigned int *num_streams, u32 *changed_ep_bitmask)
+ {
+-	struct usb_host_ss_ep_comp *ss_ep_comp;
+ 	unsigned int max_streams;
+ 	unsigned int endpoint_flag;
+ 	int i;
+@@ -1552,8 +1545,8 @@ static int xhci_calculate_streams_and_bitmask(struct xhci_hcd *xhci,
+ 		if (ret < 0)
+ 			return ret;
+ 
+-		ss_ep_comp = eps[i]->ss_ep_comp;
+-		max_streams = USB_SS_MAX_STREAMS(ss_ep_comp->desc.bmAttributes);
++		max_streams = USB_SS_MAX_STREAMS(
++				eps[i]->ss_ep_comp.bmAttributes);
+ 		if (max_streams < (*num_streams - 1)) {
+ 			xhci_dbg(xhci, "Ep 0x%x only supports %u stream IDs.\n",
+ 					eps[i]->desc.bEndpointAddress,
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 1ea25377ca0d..a748815ee629 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -45,27 +45,14 @@ struct wusb_dev;
+ 
+ struct ep_device;
+ 
+-/* For SS devices */
+-/**
+- * struct usb_host_ss_ep_comp - Valid for SuperSpeed devices only
+- * @desc: endpoint companion descriptor, wMaxPacketSize in native byteorder
+- * @extra: descriptors following this endpoint companion descriptor
+- * @extralen: how many bytes of "extra" are valid
+- */
+-struct usb_host_ss_ep_comp {
+-	struct usb_ss_ep_comp_descriptor	desc;
+-	unsigned char				*extra;   /* Extra descriptors */
+-	int					extralen;
+-};
+-
+ /**
+  * struct usb_host_endpoint - host-side endpoint descriptor and queue
+  * @desc: descriptor for this endpoint, wMaxPacketSize in native byteorder
++ * @ss_ep_comp: SuperSpeed companion descriptor for this endpoint
+  * @urb_list: urbs queued to this endpoint; maintained by usbcore
+  * @hcpriv: for use by HCD; typically holds hardware dma queue head (QH)
+  *	with one or more transfer descriptors (TDs) per urb
+  * @ep_dev: ep_device for sysfs info
+- * @ss_ep_comp: companion descriptor information for this endpoint
+  * @extra: descriptors following this endpoint in the configuration
+  * @extralen: how many bytes of "extra" are valid
+  * @enabled: URBs may be submitted to this endpoint
+@@ -74,11 +61,11 @@ struct usb_host_ss_ep_comp {
+  * descriptor within an active interface in a given USB configuration.
+  */
+ struct usb_host_endpoint {
+-	struct usb_endpoint_descriptor	desc;
++	struct usb_endpoint_descriptor		desc;
++	struct usb_ss_ep_comp_descriptor	ss_ep_comp;
+ 	struct list_head		urb_list;
+ 	void				*hcpriv;
+ 	struct ep_device 		*ep_dev;	/* For sysfs info */
+-	struct usb_host_ss_ep_comp	*ss_ep_comp;	/* For SS devices */
+ 
+ 	unsigned char *extra;   /* Extra descriptors */
+ 	int extralen;

commit 3b02ca3218cf878e206545041aa811073e4f6c79
+Author: Alan Stern 
+Date:   Fri Apr 30 12:42:23 2010 -0400
+
+    USB: export the new ch11.h file to userspce
+    
+    This patch (as1374) cleans up a few loose ends in the
+    include/linux/usb/ch11.h header file and exports it to userspace.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Eric Lescouet 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/include/linux/usb/Kbuild b/include/linux/usb/Kbuild
+index 29fd73b0bffc..51410e0200cf 100644
+--- a/include/linux/usb/Kbuild
++++ b/include/linux/usb/Kbuild
+@@ -1,6 +1,7 @@
+ header-y += audio.h
+ header-y += cdc.h
+ header-y += ch9.h
++header-y += ch11.h
+ header-y += gadgetfs.h
+ header-y += midi.h
+ header-y += g_printer.h
+diff --git a/include/linux/usb/ch11.h b/include/linux/usb/ch11.h
+index bd3185aba4ee..119194c85d10 100644
+--- a/include/linux/usb/ch11.h
++++ b/include/linux/usb/ch11.h
+@@ -6,12 +6,10 @@
+  * drivers.
+  */
+ 
+-#ifndef __LINUX_HUB_H
+-#define __LINUX_HUB_H
++#ifndef __LINUX_CH11_H
++#define __LINUX_CH11_H
+ 
+-#include 
+-#include 
+-#include 	/* likely()/unlikely() */
++#include 	/* __u8 etc */
+ 
+ /*
+  * Hub request types
+@@ -166,4 +164,4 @@ enum hub_led_mode {
+ #define HUB_TTTT_24_BITS	0x40
+ #define HUB_TTTT_32_BITS	0x60
+ 
+-#endif /* __LINUX_HUB_H */
++#endif /* __LINUX_CH11_H */

commit beb7b04a09a9da8b12417f7b74fbcceedb087fc3
+Author: Alan Stern 
+Date:   Fri Apr 30 12:14:04 2010 -0400
+
+    USB: remove leftover references to udev->autosuspend_disabled
+    
+    This patch (as1373) fixes a couple of drivers outside the USB
+    subtree.  Devices are now disabled or enabled for autosuspend by
+    calling a core function instead of setting a flag.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Stephen Rothwell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/media/video/tlg2300/pd-main.c b/drivers/media/video/tlg2300/pd-main.c
+index 2cf0ebf9f28b..a6400dad12ae 100644
+--- a/drivers/media/video/tlg2300/pd-main.c
++++ b/drivers/media/video/tlg2300/pd-main.c
+@@ -455,8 +455,8 @@ static int poseidon_probe(struct usb_interface *interface,
+ 
+ 	device_init_wakeup(&udev->dev, 1);
+ #ifdef CONFIG_PM
+-	pd->udev->autosuspend_disabled = 0;
+ 	pd->udev->autosuspend_delay = HZ * PM_SUSPEND_DELAY;
++	usb_enable_autosuspend(pd->udev);
+ 
+ 	if (in_hibernation(pd)) {
+ 		INIT_WORK(&pd->pm_work, hibernation_resume);
+diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c
+index d8c4d6497fdf..d555e37a665c 100644
+--- a/drivers/net/wimax/i2400m/usb.c
++++ b/drivers/net/wimax/i2400m/usb.c
+@@ -505,7 +505,7 @@ int i2400mu_probe(struct usb_interface *iface,
+ 	iface->needs_remote_wakeup = 1;		/* autosuspend (15s delay) */
+ 	device_init_wakeup(dev, 1);
+ 	usb_dev->autosuspend_delay = 15 * HZ;
+-	usb_dev->autosuspend_disabled = 0;
++	usb_enable_autosuspend(usb_dev);
+ #endif
+ 
+ 	result = i2400m_setup(i2400m, I2400M_BRI_MAC_REINIT);

commit a90309860b0935805d49e75499fb8dc59fea8e94
+Author: Alan Stern 
+Date:   Fri Apr 2 13:22:16 2010 -0400
+
+    USB: deprecate the power/level sysfs attribute
+    
+    This patch (as1367) deprecates USB's power/level sysfs attribute in
+    favor of the power/control attribute provided by the runtime PM core.
+    The two attributes do the same thing.
+    
+    It would be nice to replace power/level with a symlink to
+    power/control, but at the moment sysfs doesn't offer any way to do so.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/ABI/obsolete/sysfs-bus-usb b/Documentation/ABI/obsolete/sysfs-bus-usb
+new file mode 100644
+index 000000000000..bd096d33fbc7
+--- /dev/null
++++ b/Documentation/ABI/obsolete/sysfs-bus-usb
+@@ -0,0 +1,31 @@
++What:		/sys/bus/usb/devices/.../power/level
++Date:		March 2007
++KernelVersion:	2.6.21
++Contact:	Alan Stern 
++Description:
++		Each USB device directory will contain a file named
++		power/level.  This file holds a power-level setting for
++		the device, either "on" or "auto".
++
++		"on" means that the device is not allowed to autosuspend,
++		although normal suspends for system sleep will still
++		be honored.  "auto" means the device will autosuspend
++		and autoresume in the usual manner, according to the
++		capabilities of its driver.
++
++		During normal use, devices should be left in the "auto"
++		level.  The "on" level is meant for administrative uses.
++		If you want to suspend a device immediately but leave it
++		free to wake up in response to I/O requests, you should
++		write "0" to power/autosuspend.
++
++		Device not capable of proper suspend and resume should be
++		left in the "on" level.  Although the USB spec requires
++		devices to support suspend/resume, many of them do not.
++		In fact so many don't that by default, the USB core
++		initializes all non-hub devices in the "on" level.  Some
++		drivers may change this setting when they are bound.
++
++		This file is deprecated and will be removed after 2010.
++		Use the power/control file instead; it does exactly the
++		same thing.
+diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb
+index bcebb9eaedce..294aa864a60a 100644
+--- a/Documentation/ABI/testing/sysfs-bus-usb
++++ b/Documentation/ABI/testing/sysfs-bus-usb
+@@ -14,34 +14,6 @@ Description:
+ 		The autosuspend delay for newly-created devices is set to
+ 		the value of the usbcore.autosuspend module parameter.
+ 
+-What:		/sys/bus/usb/devices/.../power/level
+-Date:		March 2007
+-KernelVersion:	2.6.21
+-Contact:	Alan Stern 
+-Description:
+-		Each USB device directory will contain a file named
+-		power/level.  This file holds a power-level setting for
+-		the device, either "on" or "auto".
+-
+-		"on" means that the device is not allowed to autosuspend,
+-		although normal suspends for system sleep will still
+-		be honored.  "auto" means the device will autosuspend
+-		and autoresume in the usual manner, according to the
+-		capabilities of its driver.
+-
+-		During normal use, devices should be left in the "auto"
+-		level.  The "on" level is meant for administrative uses.
+-		If you want to suspend a device immediately but leave it
+-		free to wake up in response to I/O requests, you should
+-		write "0" to power/autosuspend.
+-
+-		Device not capable of proper suspend and resume should be
+-		left in the "on" level.  Although the USB spec requires
+-		devices to support suspend/resume, many of them do not.
+-		In fact so many don't that by default, the USB core
+-		initializes all non-hub devices in the "on" level.  Some
+-		drivers may change this setting when they are bound.
+-
+ What:		/sys/bus/usb/devices/.../power/persist
+ Date:		May 2007
+ KernelVersion:	2.6.23
+diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt
+index 2790ad48cfc2..b29d8e56cf28 100644
+--- a/Documentation/usb/power-management.txt
++++ b/Documentation/usb/power-management.txt
+@@ -107,7 +107,9 @@ allowed to issue dynamic suspends.
+ The user interface for controlling dynamic PM is located in the power/
+ subdirectory of each USB device's sysfs directory, that is, in
+ /sys/bus/usb/devices/.../power/ where "..." is the device's ID.  The
+-relevant attribute files are: wakeup, level, and autosuspend.
++relevant attribute files are: wakeup, control, and autosuspend.
++(There may also be a file named "level"; this file was deprecated
++as of the 2.6.35 kernel and replaced by the "control" file.)
+ 
+ 	power/wakeup
+ 
+@@ -120,7 +122,7 @@ relevant attribute files are: wakeup, level, and autosuspend.
+ 		while the device is suspended, the change won't take
+ 		effect until the following suspend.)
+ 
+-	power/level
++	power/control
+ 
+ 		This file contains one of two words: "on" or "auto".
+ 		You can write those words to the file to change the
+@@ -148,14 +150,15 @@ relevant attribute files are: wakeup, level, and autosuspend.
+ 		never to autosuspend.  You can write a number to the
+ 		file to change the autosuspend idle-delay time.
+ 
+-Writing "-1" to power/autosuspend and writing "on" to power/level do
++Writing "-1" to power/autosuspend and writing "on" to power/control do
+ essentially the same thing -- they both prevent the device from being
+ autosuspended.  Yes, this is a redundancy in the API.
+ 
+ (In 2.6.21 writing "0" to power/autosuspend would prevent the device
+ from being autosuspended; the behavior was changed in 2.6.22.  The
+ power/autosuspend attribute did not exist prior to 2.6.21, and the
+-power/level attribute did not exist prior to 2.6.22.)
++power/level attribute did not exist prior to 2.6.22.  power/control
++was added in 2.6.34.)
+ 
+ 
+ 	Changing the default idle-delay time
+@@ -212,7 +215,7 @@ among printers and scanners, but plenty of other types of device have
+ the same deficiency.
+ 
+ For this reason, by default the kernel disables autosuspend (the
+-power/level attribute is initialized to "on") for all devices other
++power/control attribute is initialized to "on") for all devices other
+ than hubs.  Hubs, at least, appear to be reasonably well-behaved in
+ this regard.
+ 
+@@ -373,7 +376,7 @@ usb_autopm_put_interface() in its close or release routine.  But other
+ patterns are possible.
+ 
+ The autosuspend attempts mentioned above will often fail for one
+-reason or another.  For example, the power/level attribute might be
++reason or another.  For example, the power/control attribute might be
+ set to "on", or another interface in the same device might not be
+ idle.  This is perfectly normal.  If the reason for failure was that
+ the device hasn't been idle for long enough, a timer is scheduled to
+@@ -394,12 +397,12 @@ Drivers can enable autosuspend for their devices by calling
+ 
+ in their probe() routine, if they know that the device is capable of
+ suspending and resuming correctly.  This is exactly equivalent to
+-writing "auto" to the device's power/level attribute.  Likewise,
++writing "auto" to the device's power/control attribute.  Likewise,
+ drivers can disable autosuspend by calling
+ 
+ 	usb_disable_autosuspend(struct usb_device *udev);
+ 
+-This is exactly the same as writing "on" to the power/level attribute.
++This is exactly the same as writing "on" to the power/control attribute.
+ 
+ Sometimes a driver needs to make sure that remote wakeup is enabled
+ during autosuspend.  For example, there's not much point
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index b65c1eaf3aba..06863befaf3a 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -383,12 +383,23 @@ static DEVICE_ATTR(autosuspend, S_IRUGO | S_IWUSR,
+ static const char on_string[] = "on";
+ static const char auto_string[] = "auto";
+ 
++static void warn_level(void) {
++	static int level_warned;
++
++	if (!level_warned) {
++		level_warned = 1;
++		printk(KERN_WARNING "WARNING! power/level is deprecated; "
++				"use power/control instead\n");
++	}
++}
++
+ static ssize_t
+ show_level(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+ 	struct usb_device *udev = to_usb_device(dev);
+ 	const char *p = auto_string;
+ 
++	warn_level();
+ 	if (udev->state != USB_STATE_SUSPENDED && !udev->dev.power.runtime_auto)
+ 		p = on_string;
+ 	return sprintf(buf, "%s\n", p);
+@@ -403,6 +414,7 @@ set_level(struct device *dev, struct device_attribute *attr,
+ 	char *cp;
+ 	int rc = count;
+ 
++	warn_level();
+ 	cp = memchr(buf, '\n', count);
+ 	if (cp)
+ 		len = cp - buf;

commit 9e18c821659d836bd63f88df3c19729327728496
+Author: Alan Stern 
+Date:   Fri Apr 2 13:22:09 2010 -0400
+
+    USB: use PM core routines to enable/disable autosuspend
+    
+    This patch (as1366) replaces the private routines
+    usb_enable_autosuspend() and usb_disable_autosuspend() with calls to
+    the standard pm_runtime_allow() and pm_runtime_forbid() functions in
+    the runtime PM framework.  They do the same thing.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 271e857be0fa..207146743ea7 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1356,13 +1356,9 @@ int usb_resume(struct device *dev, pm_message_t msg)
+  *
+  * The caller must hold @udev's device lock.
+  */
+-int usb_enable_autosuspend(struct usb_device *udev)
++void usb_enable_autosuspend(struct usb_device *udev)
+ {
+-	if (udev->autosuspend_disabled) {
+-		udev->autosuspend_disabled = 0;
+-		usb_autosuspend_device(udev);
+-	}
+-	return 0;
++	pm_runtime_allow(&udev->dev);
+ }
+ EXPORT_SYMBOL_GPL(usb_enable_autosuspend);
+ 
+@@ -1375,16 +1371,9 @@ EXPORT_SYMBOL_GPL(usb_enable_autosuspend);
+  *
+  * The caller must hold @udev's device lock.
+  */
+-int usb_disable_autosuspend(struct usb_device *udev)
++void usb_disable_autosuspend(struct usb_device *udev)
+ {
+-	int rc = 0;
+-
+-	if (!udev->autosuspend_disabled) {
+-		rc = usb_autoresume_device(udev);
+-		if (rc == 0)
+-			udev->autosuspend_disabled = 1;
+-	}
+-	return rc;
++	pm_runtime_forbid(&udev->dev);
+ }
+ EXPORT_SYMBOL_GPL(usb_disable_autosuspend);
+ 
+@@ -1528,7 +1517,7 @@ void usb_autopm_put_interface_async(struct usb_interface *intf)
+ 	atomic_dec(&intf->pm_usage_cnt);
+ 	pm_runtime_put_noidle(&intf->dev);
+ 
+-	if (!udev->autosuspend_disabled) {
++	if (udev->dev.power.runtime_auto) {
+ 		/* Optimization: Don't schedule a delayed autosuspend if
+ 		 * the timer is already running and the expiration time
+ 		 * wouldn't change.
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 43c002e3a9aa..b65c1eaf3aba 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -389,7 +389,7 @@ show_level(struct device *dev, struct device_attribute *attr, char *buf)
+ 	struct usb_device *udev = to_usb_device(dev);
+ 	const char *p = auto_string;
+ 
+-	if (udev->state != USB_STATE_SUSPENDED && udev->autosuspend_disabled)
++	if (udev->state != USB_STATE_SUSPENDED && !udev->dev.power.runtime_auto)
+ 		p = on_string;
+ 	return sprintf(buf, "%s\n", p);
+ }
+@@ -401,7 +401,7 @@ set_level(struct device *dev, struct device_attribute *attr,
+ 	struct usb_device *udev = to_usb_device(dev);
+ 	int len = count;
+ 	char *cp;
+-	int rc;
++	int rc = count;
+ 
+ 	cp = memchr(buf, '\n', count);
+ 	if (cp)
+@@ -411,17 +411,17 @@ set_level(struct device *dev, struct device_attribute *attr,
+ 
+ 	if (len == sizeof on_string - 1 &&
+ 			strncmp(buf, on_string, len) == 0)
+-		rc = usb_disable_autosuspend(udev);
++		usb_disable_autosuspend(udev);
+ 
+ 	else if (len == sizeof auto_string - 1 &&
+ 			strncmp(buf, auto_string, len) == 0)
+-		rc = usb_enable_autosuspend(udev);
++		usb_enable_autosuspend(udev);
+ 
+ 	else
+ 		rc = -EINVAL;
+ 
+ 	usb_unlock_device(udev);
+-	return (rc < 0 ? rc : count);
++	return rc;
+ }
+ 
+ static DEVICE_ATTR(level, S_IRUGO | S_IWUSR, show_level, set_level);
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 99833029e5a8..e32a849f81ce 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -425,7 +425,6 @@ struct usb_tt;
+  * @connect_time: time device was first connected
+  * @do_remote_wakeup:  remote wakeup should be enabled
+  * @reset_resume: needs reset instead of resume
+- * @autosuspend_disabled: autosuspend disabled by the user
+  * @wusb_dev: if this is a Wireless USB device, link to the WUSB
+  *	specific data for the device.
+  * @slot_id: Slot ID assigned by xHCI
+@@ -501,7 +500,6 @@ struct usb_device {
+ 
+ 	unsigned do_remote_wakeup:1;
+ 	unsigned reset_resume:1;
+-	unsigned autosuspend_disabled:1;
+ #endif
+ 	struct wusb_dev *wusb_dev;
+ 	int slot_id;
+@@ -526,8 +524,8 @@ extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id);
+ 
+ /* USB autosuspend and autoresume */
+ #ifdef CONFIG_USB_SUSPEND
+-extern int usb_enable_autosuspend(struct usb_device *udev);
+-extern int usb_disable_autosuspend(struct usb_device *udev);
++extern void usb_enable_autosuspend(struct usb_device *udev);
++extern void usb_disable_autosuspend(struct usb_device *udev);
+ 
+ extern int usb_autopm_get_interface(struct usb_interface *intf);
+ extern void usb_autopm_put_interface(struct usb_interface *intf);

commit 7aba8d014341341590ecb64050b7a026642a62eb
+Author: Alan Stern 
+Date:   Fri Apr 2 13:21:33 2010 -0400
+
+    USB: don't enable remote wakeup by default
+    
+    This patch (as1364) avoids enabling remote wakeup by default on all
+    non-root-hub USB devices.  Individual drivers or userspace will have
+    to enable it wherever it is needed, such as for keyboards or network
+    interfaces.  Note: This affects only system sleep, not autosuspend.
+    
+    External hubs will continue to relay wakeup requests received from
+    downstream through their upstream port, even when remote wakeup is not
+    enabled for the hub itself.  Disabling remote wakeup on a hub merely
+    prevents it from generating wakeup requests in response to connect,
+    disconnect, and overcurrent events.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 497dbb29744d..2a767b3143a4 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1783,7 +1783,6 @@ int usb_new_device(struct usb_device *udev)
+ 		 * sysfs power/wakeup controls wakeup enabled/disabled
+ 		 */
+ 		device_init_wakeup(&udev->dev, 0);
+-		device_set_wakeup_enable(&udev->dev, 1);
+ 	}
+ 
+ 	/* Tell the runtime-PM framework the device is active */

commit 7560d32ec70508a71f537a88e40f7717f15389ac
+Author: Alan Stern 
+Date:   Fri Apr 2 13:18:50 2010 -0400
+
+    USB: improve runtime remote wakeup settings
+    
+    This patch (as1362) adjusts the way the USB autosuspend routines
+    handle remote-wakeup settings.  They aren't supposed to use
+    device_may_wakeup(); that test is intended only for system sleep, not
+    runtime power management.  Instead the code checks to see if any
+    interface drivers need remote wakeup; if they do then it is enabled,
+    provided the device is capable of it.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index edff55a32575..271e857be0fa 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1486,9 +1486,6 @@ int usb_autoresume_device(struct usb_device *udev)
+  * 0, a delayed autosuspend request for @intf's device is attempted.  The
+  * attempt may fail (see autosuspend_check()).
+  *
+- * If the driver has set @intf->needs_remote_wakeup then autosuspend will
+- * take place only if the device's remote-wakeup facility is enabled.
+- *
+  * This routine can run only in process context.
+  */
+ void usb_autopm_put_interface(struct usb_interface *intf)
+@@ -1673,14 +1670,14 @@ EXPORT_SYMBOL_GPL(usb_autopm_get_interface_no_resume);
+ /* Internal routine to check whether we may autosuspend a device. */
+ static int autosuspend_check(struct usb_device *udev)
+ {
+-	int			i;
++	int			w, i;
+ 	struct usb_interface	*intf;
+ 	unsigned long		suspend_time, j;
+ 
+ 	/* Fail if autosuspend is disabled, or any interfaces are in use, or
+ 	 * any interface drivers require remote wakeup but it isn't available.
+ 	 */
+-	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
++	w = 0;
+ 	if (udev->actconfig) {
+ 		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+ 			intf = udev->actconfig->interface[i];
+@@ -1694,12 +1691,7 @@ static int autosuspend_check(struct usb_device *udev)
+ 				continue;
+ 			if (atomic_read(&intf->dev.power.usage_count) > 0)
+ 				return -EBUSY;
+-			if (intf->needs_remote_wakeup &&
+-					!udev->do_remote_wakeup) {
+-				dev_dbg(&udev->dev, "remote wakeup needed "
+-						"for autosuspend\n");
+-				return -EOPNOTSUPP;
+-			}
++			w |= intf->needs_remote_wakeup;
+ 
+ 			/* Don't allow autosuspend if the device will need
+ 			 * a reset-resume and any of its interface drivers
+@@ -1715,6 +1707,11 @@ static int autosuspend_check(struct usb_device *udev)
+ 			}
+ 		}
+ 	}
++	if (w && !device_can_wakeup(&udev->dev)) {
++		dev_dbg(&udev->dev, "remote wakeup needed for autosuspend\n");
++		return -EOPNOTSUPP;
++	}
++	udev->do_remote_wakeup = w;
+ 
+ 	/* If everything is okay but the device hasn't been idle for long
+ 	 * enough, queue a delayed autosuspend request.

commit ff9c895f07d36193c75533bda8193bde8ca99d02
+Author: Alan Stern 
+Date:   Fri Apr 2 13:27:28 2010 -0400
+
+    USB: fix usbmon and DMA mapping for scatter-gather URBs
+    
+    This patch (as1368) fixes a rather obscure bug in usbmon: When tracing
+    URBs sent by the scatter-gather library, it accesses the data buffers
+    while they are still mapped for DMA.
+    
+    The solution is to move the mapping and unmapping out of the s-g
+    library and into the usual place in hcd.c.  This requires the addition
+    of new URB flag bits to describe the kind of mapping needed, since we
+    have to call dma_map_sg() if the HCD supports native scatter-gather
+    operation and dma_map_page() if it doesn't.  The nice thing about
+    having the new flags is that they simplify the testing for unmapping.
+    
+    The patch removes the only caller of usb_buffer_[un]map_sg(), so those
+    functions are #if'ed out.  A later patch will remove them entirely.
+    
+    As a result of this change, urb->sg will be set in situations where
+    it wasn't set previously.  Hence the xhci and whci drivers are
+    adjusted to test urb->num_sgs instead, which retains its original
+    meaning and is nonzero only when the HCD has to handle a scatterlist.
+    
+    Finally, even when a submission error occurs we don't want to hand
+    URBs to usbmon before they are unmapped.  The submission path is
+    rearranged so that map_urb_for_dma() is called only for non-root-hub
+    URBs and unmap_urb_for_dma() is called immediately after a submission
+    error.  This simplifies the error handling.
+    
+    Signed-off-by: Alan Stern 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 38d4700926f7..6a05e6934455 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1259,6 +1259,51 @@ static void hcd_free_coherent(struct usb_bus *bus, dma_addr_t *dma_handle,
+ 	*dma_handle = 0;
+ }
+ 
++static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
++{
++	enum dma_data_direction dir;
++
++	if (urb->transfer_flags & URB_SETUP_MAP_SINGLE)
++		dma_unmap_single(hcd->self.controller,
++				urb->setup_dma,
++				sizeof(struct usb_ctrlrequest),
++				DMA_TO_DEVICE);
++	else if (urb->transfer_flags & URB_SETUP_MAP_LOCAL)
++		hcd_free_coherent(urb->dev->bus,
++				&urb->setup_dma,
++				(void **) &urb->setup_packet,
++				sizeof(struct usb_ctrlrequest),
++				DMA_TO_DEVICE);
++
++	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
++	if (urb->transfer_flags & URB_DMA_MAP_SG)
++		dma_unmap_sg(hcd->self.controller,
++				urb->sg->sg,
++				urb->num_sgs,
++				dir);
++	else if (urb->transfer_flags & URB_DMA_MAP_PAGE)
++		dma_unmap_page(hcd->self.controller,
++				urb->transfer_dma,
++				urb->transfer_buffer_length,
++				dir);
++	else if (urb->transfer_flags & URB_DMA_MAP_SINGLE)
++		dma_unmap_single(hcd->self.controller,
++				urb->transfer_dma,
++				urb->transfer_buffer_length,
++				dir);
++	else if (urb->transfer_flags & URB_MAP_LOCAL)
++		hcd_free_coherent(urb->dev->bus,
++				&urb->transfer_dma,
++				&urb->transfer_buffer,
++				urb->transfer_buffer_length,
++				dir);
++
++	/* Make it safe to call this routine more than once */
++	urb->transfer_flags &= ~(URB_SETUP_MAP_SINGLE | URB_SETUP_MAP_LOCAL |
++			URB_DMA_MAP_SG | URB_DMA_MAP_PAGE |
++			URB_DMA_MAP_SINGLE | URB_MAP_LOCAL);
++}
++
+ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
+ 			   gfp_t mem_flags)
+ {
+@@ -1270,8 +1315,6 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
+ 	 * unless it uses pio or talks to another transport,
+ 	 * or uses the provided scatter gather list for bulk.
+ 	 */
+-	if (is_root_hub(urb->dev))
+-		return 0;
+ 
+ 	if (usb_endpoint_xfer_control(&urb->ep->desc)
+ 	    && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) {
+@@ -1284,6 +1327,7 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
+ 			if (dma_mapping_error(hcd->self.controller,
+ 						urb->setup_dma))
+ 				return -EAGAIN;
++			urb->transfer_flags |= URB_SETUP_MAP_SINGLE;
+ 		} else if (hcd->driver->flags & HCD_LOCAL_MEM)
+ 			ret = hcd_alloc_coherent(
+ 					urb->dev->bus, mem_flags,
+@@ -1291,20 +1335,57 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
+ 					(void **)&urb->setup_packet,
+ 					sizeof(struct usb_ctrlrequest),
+ 					DMA_TO_DEVICE);
++			if (ret)
++				return ret;
++			urb->transfer_flags |= URB_SETUP_MAP_LOCAL;
+ 	}
+ 
+ 	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+-	if (ret == 0 && urb->transfer_buffer_length != 0
++	if (urb->transfer_buffer_length != 0
+ 	    && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
+ 		if (hcd->self.uses_dma) {
+-			urb->transfer_dma = dma_map_single (
+-					hcd->self.controller,
+-					urb->transfer_buffer,
+-					urb->transfer_buffer_length,
+-					dir);
+-			if (dma_mapping_error(hcd->self.controller,
++			if (urb->num_sgs) {
++				int n = dma_map_sg(
++						hcd->self.controller,
++						urb->sg->sg,
++						urb->num_sgs,
++						dir);
++				if (n <= 0)
++					ret = -EAGAIN;
++				else
++					urb->transfer_flags |= URB_DMA_MAP_SG;
++				if (n != urb->num_sgs) {
++					urb->num_sgs = n;
++					urb->transfer_flags |=
++							URB_DMA_SG_COMBINED;
++				}
++			} else if (urb->sg) {
++				struct scatterlist *sg;
++
++				sg = (struct scatterlist *) urb->sg;
++				urb->transfer_dma = dma_map_page(
++						hcd->self.controller,
++						sg_page(sg),
++						sg->offset,
++						urb->transfer_buffer_length,
++						dir);
++				if (dma_mapping_error(hcd->self.controller,
+ 						urb->transfer_dma))
+-				return -EAGAIN;
++					ret = -EAGAIN;
++				else
++					urb->transfer_flags |= URB_DMA_MAP_PAGE;
++			} else {
++				urb->transfer_dma = dma_map_single(
++						hcd->self.controller,
++						urb->transfer_buffer,
++						urb->transfer_buffer_length,
++						dir);
++				if (dma_mapping_error(hcd->self.controller,
++						urb->transfer_dma))
++					ret = -EAGAIN;
++				else
++					urb->transfer_flags |= URB_DMA_MAP_SINGLE;
++			}
+ 		} else if (hcd->driver->flags & HCD_LOCAL_MEM) {
+ 			ret = hcd_alloc_coherent(
+ 					urb->dev->bus, mem_flags,
+@@ -1312,55 +1393,16 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
+ 					&urb->transfer_buffer,
+ 					urb->transfer_buffer_length,
+ 					dir);
+-
+-			if (ret && usb_endpoint_xfer_control(&urb->ep->desc)
+-			    && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
+-				hcd_free_coherent(urb->dev->bus,
+-					&urb->setup_dma,
+-					(void **)&urb->setup_packet,
+-					sizeof(struct usb_ctrlrequest),
+-					DMA_TO_DEVICE);
++			if (ret == 0)
++				urb->transfer_flags |= URB_MAP_LOCAL;
+ 		}
++		if (ret && (urb->transfer_flags & (URB_SETUP_MAP_SINGLE |
++				URB_SETUP_MAP_LOCAL)))
++			unmap_urb_for_dma(hcd, urb);
+ 	}
+ 	return ret;
+ }
+ 
+-static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+-{
+-	enum dma_data_direction dir;
+-
+-	if (is_root_hub(urb->dev))
+-		return;
+-
+-	if (usb_endpoint_xfer_control(&urb->ep->desc)
+-	    && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) {
+-		if (hcd->self.uses_dma)
+-			dma_unmap_single(hcd->self.controller, urb->setup_dma,
+-					sizeof(struct usb_ctrlrequest),
+-					DMA_TO_DEVICE);
+-		else if (hcd->driver->flags & HCD_LOCAL_MEM)
+-			hcd_free_coherent(urb->dev->bus, &urb->setup_dma,
+-					(void **)&urb->setup_packet,
+-					sizeof(struct usb_ctrlrequest),
+-					DMA_TO_DEVICE);
+-	}
+-
+-	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+-	if (urb->transfer_buffer_length != 0
+-	    && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
+-		if (hcd->self.uses_dma)
+-			dma_unmap_single(hcd->self.controller,
+-					urb->transfer_dma,
+-					urb->transfer_buffer_length,
+-					dir);
+-		else if (hcd->driver->flags & HCD_LOCAL_MEM)
+-			hcd_free_coherent(urb->dev->bus, &urb->transfer_dma,
+-					&urb->transfer_buffer,
+-					urb->transfer_buffer_length,
+-					dir);
+-	}
+-}
+-
+ /*-------------------------------------------------------------------------*/
+ 
+ /* may be called in any context with a valid urb->dev usecount
+@@ -1389,21 +1431,20 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+ 	 * URBs must be submitted in process context with interrupts
+ 	 * enabled.
+ 	 */
+-	status = map_urb_for_dma(hcd, urb, mem_flags);
+-	if (unlikely(status)) {
+-		usbmon_urb_submit_error(&hcd->self, urb, status);
+-		goto error;
+-	}
+ 
+-	if (is_root_hub(urb->dev))
++	if (is_root_hub(urb->dev)) {
+ 		status = rh_urb_enqueue(hcd, urb);
+-	else
+-		status = hcd->driver->urb_enqueue(hcd, urb, mem_flags);
++	} else {
++		status = map_urb_for_dma(hcd, urb, mem_flags);
++		if (likely(status == 0)) {
++			status = hcd->driver->urb_enqueue(hcd, urb, mem_flags);
++			if (unlikely(status))
++				unmap_urb_for_dma(hcd, urb);
++		}
++	}
+ 
+ 	if (unlikely(status)) {
+ 		usbmon_urb_submit_error(&hcd->self, urb, status);
+-		unmap_urb_for_dma(hcd, urb);
+- error:
+ 		urb->hcpriv = NULL;
+ 		INIT_LIST_HEAD(&urb->urb_list);
+ 		atomic_dec(&urb->use_count);
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 619c44fb8a96..79d1cdf4a635 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -259,9 +259,6 @@ static void sg_clean(struct usb_sg_request *io)
+ 		kfree(io->urbs);
+ 		io->urbs = NULL;
+ 	}
+-	if (io->dev->dev.dma_mask != NULL)
+-		usb_buffer_unmap_sg(io->dev, usb_pipein(io->pipe),
+-				    io->sg, io->nents);
+ 	io->dev = NULL;
+ }
+ 
+@@ -364,7 +361,6 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
+ {
+ 	int i;
+ 	int urb_flags;
+-	int dma;
+ 	int use_sg;
+ 
+ 	if (!io || !dev || !sg
+@@ -378,21 +374,9 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
+ 	io->pipe = pipe;
+ 	io->sg = sg;
+ 	io->nents = nents;
+-
+-	/* not all host controllers use DMA (like the mainstream pci ones);
+-	 * they can use PIO (sl811) or be software over another transport.
+-	 */
+-	dma = (dev->dev.dma_mask != NULL);
+-	if (dma)
+-		io->entries = usb_buffer_map_sg(dev, usb_pipein(pipe),
+-						sg, nents);
+-	else
+-		io->entries = nents;
++	io->entries = nents;
+ 
+ 	/* initialize all the urbs we'll use */
+-	if (io->entries <= 0)
+-		return io->entries;
+-
+ 	if (dev->bus->sg_tablesize > 0) {
+ 		io->urbs = kmalloc(sizeof *io->urbs, mem_flags);
+ 		use_sg = true;
+@@ -404,8 +388,6 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
+ 		goto nomem;
+ 
+ 	urb_flags = 0;
+-	if (dma)
+-		urb_flags |= URB_NO_TRANSFER_DMA_MAP;
+ 	if (usb_pipein(pipe))
+ 		urb_flags |= URB_SHORT_NOT_OK;
+ 
+@@ -423,12 +405,13 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
+ 
+ 		io->urbs[0]->complete = sg_complete;
+ 		io->urbs[0]->context = io;
++
+ 		/* A length of zero means transfer the whole sg list */
+ 		io->urbs[0]->transfer_buffer_length = length;
+ 		if (length == 0) {
+ 			for_each_sg(sg, sg, io->entries, i) {
+ 				io->urbs[0]->transfer_buffer_length +=
+-					sg_dma_len(sg);
++					sg->length;
+ 			}
+ 		}
+ 		io->urbs[0]->sg = io;
+@@ -454,26 +437,16 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
+ 			io->urbs[i]->context = io;
+ 
+ 			/*
+-			 * Some systems need to revert to PIO when DMA is temporarily
+-			 * unavailable.  For their sakes, both transfer_buffer and
+-			 * transfer_dma are set when possible.
+-			 *
+-			 * Note that if IOMMU coalescing occurred, we cannot
+-			 * trust sg_page anymore, so check if S/G list shrunk.
++			 * Some systems can't use DMA; they use PIO instead.
++			 * For their sakes, transfer_buffer is set whenever
++			 * possible.
+ 			 */
+-			if (io->nents == io->entries && !PageHighMem(sg_page(sg)))
++			if (!PageHighMem(sg_page(sg)))
+ 				io->urbs[i]->transfer_buffer = sg_virt(sg);
+ 			else
+ 				io->urbs[i]->transfer_buffer = NULL;
+ 
+-			if (dma) {
+-				io->urbs[i]->transfer_dma = sg_dma_address(sg);
+-				len = sg_dma_len(sg);
+-			} else {
+-				/* hc may use _only_ transfer_buffer */
+-				len = sg->length;
+-			}
+-
++			len = sg->length;
+ 			if (length) {
+ 				len = min_t(unsigned, len, length);
+ 				length -= len;
+@@ -481,6 +454,8 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
+ 					io->entries = i + 1;
+ 			}
+ 			io->urbs[i]->transfer_buffer_length = len;
++
++			io->urbs[i]->sg = (struct usb_sg_request *) sg;
+ 		}
+ 		io->urbs[--i]->transfer_flags &= ~URB_NO_INTERRUPT;
+ 	}
+diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
+index 2532a0917f8c..a760e46871c5 100644
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -333,9 +333,12 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 		is_out = usb_endpoint_dir_out(&ep->desc);
+ 	}
+ 
+-	/* Cache the direction for later use */
+-	urb->transfer_flags = (urb->transfer_flags & ~URB_DIR_MASK) |
+-			(is_out ? URB_DIR_OUT : URB_DIR_IN);
++	/* Clear the internal flags and cache the direction for later use */
++	urb->transfer_flags &= ~(URB_DIR_MASK | URB_DMA_MAP_SINGLE |
++			URB_DMA_MAP_PAGE | URB_DMA_MAP_SG | URB_MAP_LOCAL |
++			URB_SETUP_MAP_SINGLE | URB_SETUP_MAP_LOCAL |
++			URB_DMA_SG_COMBINED);
++	urb->transfer_flags |= (is_out ? URB_DIR_OUT : URB_DIR_IN);
+ 
+ 	if (xfertype != USB_ENDPOINT_XFER_CONTROL &&
+ 			dev->state < USB_STATE_CONFIGURED)
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 097172e2ba06..8180ce533ebf 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -881,6 +881,7 @@ void usb_buffer_unmap(struct urb *urb)
+ EXPORT_SYMBOL_GPL(usb_buffer_unmap);
+ #endif  /*  0  */
+ 
++#if 0
+ /**
+  * usb_buffer_map_sg - create scatterlist DMA mapping(s) for an endpoint
+  * @dev: device to which the scatterlist will be mapped
+@@ -924,6 +925,7 @@ int usb_buffer_map_sg(const struct usb_device *dev, int is_in,
+ 			is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE) ? : -ENOMEM;
+ }
+ EXPORT_SYMBOL_GPL(usb_buffer_map_sg);
++#endif
+ 
+ /* XXX DISABLED, no users currently.  If you wish to re-enable this
+  * XXX please determine whether the sync is to transfer ownership of
+@@ -960,6 +962,7 @@ void usb_buffer_dmasync_sg(const struct usb_device *dev, int is_in,
+ EXPORT_SYMBOL_GPL(usb_buffer_dmasync_sg);
+ #endif
+ 
++#if 0
+ /**
+  * usb_buffer_unmap_sg - free DMA mapping(s) for a scatterlist
+  * @dev: device to which the scatterlist will be mapped
+@@ -985,6 +988,7 @@ void usb_buffer_unmap_sg(const struct usb_device *dev, int is_in,
+ 			is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
+ }
+ EXPORT_SYMBOL_GPL(usb_buffer_unmap_sg);
++#endif
+ 
+ /* To disable USB, kernel command line is 'nousb' not 'usbcore.nousb' */
+ #ifdef MODULE
+diff --git a/drivers/usb/host/whci/qset.c b/drivers/usb/host/whci/qset.c
+index 141d049beb3e..b388dd1fb4c4 100644
+--- a/drivers/usb/host/whci/qset.c
++++ b/drivers/usb/host/whci/qset.c
+@@ -646,7 +646,7 @@ int qset_add_urb(struct whc *whc, struct whc_qset *qset, struct urb *urb,
+ 	wurb->urb = urb;
+ 	INIT_WORK(&wurb->dequeue_work, urb_dequeue_work);
+ 
+-	if (urb->sg) {
++	if (urb->num_sgs) {
+ 		ret = qset_add_urb_sg(whc, qset, urb, mem_flags);
+ 		if (ret == -EINVAL) {
+ 			qset_free_stds(qset, urb);
+diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
+index 407d33fb5e84..c1359ed310b5 100644
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1962,7 +1962,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
+ 	int running_total, trb_buff_len, ret;
+ 	u64 addr;
+ 
+-	if (urb->sg)
++	if (urb->num_sgs)
+ 		return queue_bulk_sg_tx(xhci, mem_flags, urb, slot_id, ep_index);
+ 
+ 	ep_ring = xhci->devs[slot_id]->eps[ep_index].ring;
+diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
+index ddf7f9a1b336..8a7968df278f 100644
+--- a/drivers/usb/mon/mon_bin.c
++++ b/drivers/usb/mon/mon_bin.c
+@@ -416,7 +416,7 @@ static unsigned int mon_bin_get_data(const struct mon_reader_bin *rp,
+ 
+ 	} else {
+ 		/* If IOMMU coalescing occurred, we cannot trust sg_page */
+-		if (urb->sg->nents != urb->num_sgs) {
++		if (urb->transfer_flags & URB_DMA_SG_COMBINED) {
+ 			*flag = 'D';
+ 			return length;
+ 		}
+diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
+index 4d0be130f49b..d56260280f54 100644
+--- a/drivers/usb/mon/mon_text.c
++++ b/drivers/usb/mon/mon_text.c
+@@ -161,9 +161,7 @@ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
+ 	} else {
+ 		struct scatterlist *sg = urb->sg->sg;
+ 
+-		/* If IOMMU coalescing occurred, we cannot trust sg_page */
+-		if (urb->sg->nents != urb->num_sgs ||
+-				PageHighMem(sg_page(sg)))
++		if (PageHighMem(sg_page(sg)))
+ 			return 'D';
+ 
+ 		/* For the text interface we copy only the first sg buffer */
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 739f1fd1cc15..99833029e5a8 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -965,10 +965,19 @@ extern int usb_disabled(void);
+ 					 * needed */
+ #define URB_FREE_BUFFER		0x0100	/* Free transfer buffer with the URB */
+ 
++/* The following flags are used internally by usbcore and HCDs */
+ #define URB_DIR_IN		0x0200	/* Transfer from device to host */
+ #define URB_DIR_OUT		0
+ #define URB_DIR_MASK		URB_DIR_IN
+ 
++#define URB_DMA_MAP_SINGLE	0x00010000	/* Non-scatter-gather mapping */
++#define URB_DMA_MAP_PAGE	0x00020000	/* HCD-unsupported S-G */
++#define URB_DMA_MAP_SG		0x00040000	/* HCD-supported S-G */
++#define URB_MAP_LOCAL		0x00080000	/* HCD-local-memory mapping */
++#define URB_SETUP_MAP_SINGLE	0x00100000	/* Setup packet DMA mapped */
++#define URB_SETUP_MAP_LOCAL	0x00200000	/* HCD-local setup packet */
++#define URB_DMA_SG_COMBINED	0x00400000	/* S-G entries were combined */
++
+ struct usb_iso_packet_descriptor {
+ 	unsigned int offset;
+ 	unsigned int length;		/* expected length */

commit 0ede76fcec5415ef82a423a95120286895822e2d
+Author: Alan Stern 
+Date:   Fri Mar 5 15:10:17 2010 -0500
+
+    USB: remove uses of URB_NO_SETUP_DMA_MAP
+    
+    This patch (as1350) removes all usages of coherent buffers for USB
+    control-request setup-packet buffers.  There's no good reason to
+    reserve coherent memory for these things; control requests are hardly
+    ever used in large quantity (the major exception is firmware
+    transfers, and they aren't time-critical).  Furthermore, only seven
+    drivers used it.  We might as well always use streaming DMA mappings
+    for setup-packet buffers, and remove some extra complexity from
+    usbcore.
+    
+    The DMA-mapping portion of hcd.c is currently in flux.  A separate
+    patch will be submitted to remove support for URB_NO_SETUP_DMA_MAP
+    after everything else settles down.  The removal should go smoothly,
+    as by then nobody will be using it.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index 7b85b696fdab..6a510c9675fc 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -787,8 +787,7 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
+ 			&usbhid->inbuf_dma);
+ 	usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
+ 			&usbhid->outbuf_dma);
+-	usbhid->cr = usb_buffer_alloc(dev, sizeof(*usbhid->cr), GFP_KERNEL,
+-			&usbhid->cr_dma);
++	usbhid->cr = kmalloc(sizeof(*usbhid->cr), GFP_KERNEL);
+ 	usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
+ 			&usbhid->ctrlbuf_dma);
+ 	if (!usbhid->inbuf || !usbhid->outbuf || !usbhid->cr ||
+@@ -846,7 +845,7 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
+ 
+ 	usb_buffer_free(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma);
+ 	usb_buffer_free(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma);
+-	usb_buffer_free(dev, sizeof(*(usbhid->cr)), usbhid->cr, usbhid->cr_dma);
++	kfree(usbhid->cr);
+ 	usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma);
+ }
+ 
+@@ -1007,9 +1006,8 @@ static int usbhid_start(struct hid_device *hid)
+ 
+ 	usb_fill_control_urb(usbhid->urbctrl, dev, 0, (void *) usbhid->cr,
+ 			     usbhid->ctrlbuf, 1, hid_ctrl, hid);
+-	usbhid->urbctrl->setup_dma = usbhid->cr_dma;
+ 	usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma;
+-	usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
++	usbhid->urbctrl->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ 
+ 	if (!(hid->quirks & HID_QUIRK_NO_INIT_REPORTS))
+ 		usbhid_init_reports(hid);
+diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h
+index ec20400c7f29..693fd3e720df 100644
+--- a/drivers/hid/usbhid/usbhid.h
++++ b/drivers/hid/usbhid/usbhid.h
+@@ -75,7 +75,6 @@ struct usbhid_device {
+ 
+ 	struct urb *urbctrl;                                            /* Control URB */
+ 	struct usb_ctrlrequest *cr;                                     /* Control request struct */
+-	dma_addr_t cr_dma;                                              /* Control request struct dma */
+ 	struct hid_control_fifo ctrl[HID_CONTROL_FIFO_SIZE];  		/* Control fifo */
+ 	unsigned char ctrlhead, ctrltail;                               /* Control fifo head & tail */
+ 	char *ctrlbuf;                                                  /* Control buffer */
+diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c
+index f843443ba5c3..bdc7b09e8670 100644
+--- a/drivers/hid/usbhid/usbkbd.c
++++ b/drivers/hid/usbhid/usbkbd.c
+@@ -74,7 +74,6 @@ struct usb_kbd {
+ 	unsigned char *new;
+ 	struct usb_ctrlrequest *cr;
+ 	unsigned char *leds;
+-	dma_addr_t cr_dma;
+ 	dma_addr_t new_dma;
+ 	dma_addr_t leds_dma;
+ };
+@@ -199,7 +198,7 @@ static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd)
+ 		return -1;
+ 	if (!(kbd->new = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &kbd->new_dma)))
+ 		return -1;
+-	if (!(kbd->cr = usb_buffer_alloc(dev, sizeof(struct usb_ctrlrequest), GFP_ATOMIC, &kbd->cr_dma)))
++	if (!(kbd->cr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL)))
+ 		return -1;
+ 	if (!(kbd->leds = usb_buffer_alloc(dev, 1, GFP_ATOMIC, &kbd->leds_dma)))
+ 		return -1;
+@@ -212,7 +211,7 @@ static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd)
+ 	usb_free_urb(kbd->irq);
+ 	usb_free_urb(kbd->led);
+ 	usb_buffer_free(dev, 8, kbd->new, kbd->new_dma);
+-	usb_buffer_free(dev, sizeof(struct usb_ctrlrequest), kbd->cr, kbd->cr_dma);
++	kfree(kbd->cr);
+ 	usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma);
+ }
+ 
+@@ -304,9 +303,8 @@ static int usb_kbd_probe(struct usb_interface *iface,
+ 	usb_fill_control_urb(kbd->led, dev, usb_sndctrlpipe(dev, 0),
+ 			     (void *) kbd->cr, kbd->leds, 1,
+ 			     usb_kbd_led, kbd);
+-	kbd->led->setup_dma = kbd->cr_dma;
+ 	kbd->led->transfer_dma = kbd->leds_dma;
+-	kbd->led->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
++	kbd->led->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ 
+ 	error = input_register_device(kbd->dev);
+ 	if (error)
+diff --git a/drivers/input/misc/cm109.c b/drivers/input/misc/cm109.c
+index 86457feccfc4..8d2d291ee508 100644
+--- a/drivers/input/misc/cm109.c
++++ b/drivers/input/misc/cm109.c
+@@ -102,7 +102,6 @@ struct cm109_dev {
+ 	struct cm109_ctl_packet *ctl_data;
+ 	dma_addr_t ctl_dma;
+ 	struct usb_ctrlrequest *ctl_req;
+-	dma_addr_t ctl_req_dma;
+ 	struct urb *urb_ctl;
+ 	/*
+ 	 * The 3 bitfields below are protected by ctl_submit_lock.
+@@ -629,9 +628,7 @@ static const struct usb_device_id cm109_usb_table[] = {
+ 
+ static void cm109_usb_cleanup(struct cm109_dev *dev)
+ {
+-	if (dev->ctl_req)
+-		usb_buffer_free(dev->udev, sizeof(*(dev->ctl_req)),
+-				dev->ctl_req, dev->ctl_req_dma);
++	kfree(dev->ctl_req);
+ 	if (dev->ctl_data)
+ 		usb_buffer_free(dev->udev, USB_PKT_LEN,
+ 				dev->ctl_data, dev->ctl_dma);
+@@ -696,8 +693,7 @@ static int cm109_usb_probe(struct usb_interface *intf,
+ 	if (!dev->ctl_data)
+ 		goto err_out;
+ 
+-	dev->ctl_req = usb_buffer_alloc(udev, sizeof(*(dev->ctl_req)),
+-					GFP_KERNEL, &dev->ctl_req_dma);
++	dev->ctl_req = kmalloc(sizeof(*(dev->ctl_req)), GFP_KERNEL);
+ 	if (!dev->ctl_req)
+ 		goto err_out;
+ 
+@@ -735,10 +731,8 @@ static int cm109_usb_probe(struct usb_interface *intf,
+ 	usb_fill_control_urb(dev->urb_ctl, udev, usb_sndctrlpipe(udev, 0),
+ 			     (void *)dev->ctl_req, dev->ctl_data, USB_PKT_LEN,
+ 			     cm109_urb_ctl_callback, dev);
+-	dev->urb_ctl->setup_dma = dev->ctl_req_dma;
+ 	dev->urb_ctl->transfer_dma = dev->ctl_dma;
+-	dev->urb_ctl->transfer_flags |= URB_NO_SETUP_DMA_MAP |
+-					URB_NO_TRANSFER_DMA_MAP;
++	dev->urb_ctl->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ 	dev->urb_ctl->dev = udev;
+ 
+ 	/* find out the physical bus location */
+diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c
+index 668913d12044..7ba4b5f53fc2 100644
+--- a/drivers/input/misc/powermate.c
++++ b/drivers/input/misc/powermate.c
+@@ -64,7 +64,6 @@ struct powermate_device {
+ 	dma_addr_t data_dma;
+ 	struct urb *irq, *config;
+ 	struct usb_ctrlrequest *configcr;
+-	dma_addr_t configcr_dma;
+ 	struct usb_device *udev;
+ 	struct input_dev *input;
+ 	spinlock_t lock;
+@@ -182,8 +181,6 @@ static void powermate_sync_state(struct powermate_device *pm)
+ 	usb_fill_control_urb(pm->config, pm->udev, usb_sndctrlpipe(pm->udev, 0),
+ 			     (void *) pm->configcr, NULL, 0,
+ 			     powermate_config_complete, pm);
+-	pm->config->setup_dma = pm->configcr_dma;
+-	pm->config->transfer_flags |= URB_NO_SETUP_DMA_MAP;
+ 
+ 	if (usb_submit_urb(pm->config, GFP_ATOMIC))
+ 		printk(KERN_ERR "powermate: usb_submit_urb(config) failed");
+@@ -281,8 +278,7 @@ static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_dev
+ 	if (!pm->data)
+ 		return -1;
+ 
+-	pm->configcr = usb_buffer_alloc(udev, sizeof(*(pm->configcr)),
+-					GFP_ATOMIC, &pm->configcr_dma);
++	pm->configcr = kmalloc(sizeof(*(pm->configcr)), GFP_KERNEL);
+ 	if (!pm->configcr)
+ 		return -1;
+ 
+@@ -293,8 +289,7 @@ static void powermate_free_buffers(struct usb_device *udev, struct powermate_dev
+ {
+ 	usb_buffer_free(udev, POWERMATE_PAYLOAD_SIZE_MAX,
+ 			pm->data, pm->data_dma);
+-	usb_buffer_free(udev, sizeof(*(pm->configcr)),
+-			pm->configcr, pm->configcr_dma);
++	kfree(pm->configcr);
+ }
+ 
+ /* Called whenever a USB device matching one in our supported devices table is connected */
+diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c
+index 93a22ac0f88c..2828328e9dd0 100644
+--- a/drivers/input/misc/yealink.c
++++ b/drivers/input/misc/yealink.c
+@@ -111,7 +111,6 @@ struct yealink_dev {
+ 	struct yld_ctl_packet	*ctl_data;
+ 	dma_addr_t		ctl_dma;
+ 	struct usb_ctrlrequest	*ctl_req;
+-	dma_addr_t		ctl_req_dma;
+ 	struct urb		*urb_ctl;
+ 
+ 	char phys[64];			/* physical device path */
+@@ -836,8 +835,7 @@ static int usb_cleanup(struct yealink_dev *yld, int err)
+ 	usb_free_urb(yld->urb_irq);
+ 	usb_free_urb(yld->urb_ctl);
+ 
+-	usb_buffer_free(yld->udev, sizeof(*(yld->ctl_req)),
+-			yld->ctl_req, yld->ctl_req_dma);
++	kfree(yld->ctl_req);
+ 	usb_buffer_free(yld->udev, USB_PKT_LEN,
+ 			yld->ctl_data, yld->ctl_dma);
+ 	usb_buffer_free(yld->udev, USB_PKT_LEN,
+@@ -896,8 +894,7 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
+ 	if (!yld->ctl_data)
+ 		return usb_cleanup(yld, -ENOMEM);
+ 
+-	yld->ctl_req = usb_buffer_alloc(udev, sizeof(*(yld->ctl_req)),
+-					GFP_ATOMIC, &yld->ctl_req_dma);
++	yld->ctl_req = kmalloc(sizeof(*(yld->ctl_req)), GFP_KERNEL);
+ 	if (yld->ctl_req == NULL)
+ 		return usb_cleanup(yld, -ENOMEM);
+ 
+@@ -936,10 +933,8 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
+ 	usb_fill_control_urb(yld->urb_ctl, udev, usb_sndctrlpipe(udev, 0),
+ 			(void *)yld->ctl_req, yld->ctl_data, USB_PKT_LEN,
+ 			urb_ctl_callback, yld);
+-	yld->urb_ctl->setup_dma	= yld->ctl_req_dma;
+ 	yld->urb_ctl->transfer_dma	= yld->ctl_dma;
+-	yld->urb_ctl->transfer_flags	|= URB_NO_SETUP_DMA_MAP |
+-					URB_NO_TRANSFER_DMA_MAP;
++	yld->urb_ctl->transfer_flags	|= URB_NO_TRANSFER_DMA_MAP;
+ 	yld->urb_ctl->dev = udev;
+ 
+ 	/* find out the physical bus location */
+diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
+index 09301f4b7225..2532a0917f8c 100644
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -396,8 +396,8 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 		return -EPIPE;		/* The most suitable error code :-) */
+ 
+ 	/* enforce simple/standard policy */
+-	allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP |
+-			URB_NO_INTERRUPT | URB_DIR_MASK | URB_FREE_BUFFER);
++	allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT | URB_DIR_MASK |
++			URB_FREE_BUFFER);
+ 	switch (xfertype) {
+ 	case USB_ENDPOINT_XFER_BULK:
+ 		if (is_out)
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 1088abb4416c..097172e2ba06 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -775,7 +775,7 @@ EXPORT_SYMBOL_GPL(usb_free_coherent);
+  * @urb: urb whose transfer_buffer/setup_packet will be mapped
+  *
+  * Return value is either null (indicating no buffer could be mapped), or
+- * the parameter.  URB_NO_TRANSFER_DMA_MAP and URB_NO_SETUP_DMA_MAP are
++ * the parameter.  URB_NO_TRANSFER_DMA_MAP is
+  * added to urb->transfer_flags if the operation succeeds.  If the device
+  * is connected to this system through a non-DMA controller, this operation
+  * always succeeds.
+@@ -803,17 +803,11 @@ struct urb *usb_buffer_map(struct urb *urb)
+ 			urb->transfer_buffer, urb->transfer_buffer_length,
+ 			usb_pipein(urb->pipe)
+ 				? DMA_FROM_DEVICE : DMA_TO_DEVICE);
+-		if (usb_pipecontrol(urb->pipe))
+-			urb->setup_dma = dma_map_single(controller,
+-					urb->setup_packet,
+-					sizeof(struct usb_ctrlrequest),
+-					DMA_TO_DEVICE);
+ 	/* FIXME generic api broken like pci, can't report errors */
+ 	/* if (urb->transfer_dma == DMA_ADDR_INVALID) return 0; */
+ 	} else
+ 		urb->transfer_dma = ~0;
+-	urb->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP
+-				| URB_NO_SETUP_DMA_MAP);
++	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ 	return urb;
+ }
+ EXPORT_SYMBOL_GPL(usb_buffer_map);
+@@ -881,14 +875,8 @@ void usb_buffer_unmap(struct urb *urb)
+ 			urb->transfer_dma, urb->transfer_buffer_length,
+ 			usb_pipein(urb->pipe)
+ 				? DMA_FROM_DEVICE : DMA_TO_DEVICE);
+-		if (usb_pipecontrol(urb->pipe))
+-			dma_unmap_single(controller,
+-					urb->setup_dma,
+-					sizeof(struct usb_ctrlrequest),
+-					DMA_TO_DEVICE);
+ 	}
+-	urb->transfer_flags &= ~(URB_NO_TRANSFER_DMA_MAP
+-				| URB_NO_SETUP_DMA_MAP);
++	urb->transfer_flags &= ~URB_NO_TRANSFER_DMA_MAP;
+ }
+ EXPORT_SYMBOL_GPL(usb_buffer_unmap);
+ #endif  /*  0  */
+diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
+index a21cce6f7403..9dcc82337ced 100644
+--- a/drivers/usb/misc/usbtest.c
++++ b/drivers/usb/misc/usbtest.c
+@@ -977,15 +977,13 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
+ 		if (!u)
+ 			goto cleanup;
+ 
+-		reqp = usb_buffer_alloc (udev, sizeof *reqp, GFP_KERNEL,
+-				&u->setup_dma);
++		reqp = kmalloc(sizeof *reqp, GFP_KERNEL);
+ 		if (!reqp)
+ 			goto cleanup;
+ 		reqp->setup = req;
+ 		reqp->number = i % NUM_SUBCASES;
+ 		reqp->expected = expected;
+ 		u->setup_packet = (char *) &reqp->setup;
+-		u->transfer_flags |= URB_NO_SETUP_DMA_MAP;
+ 
+ 		u->context = &context;
+ 		u->complete = ctrl_complete;
+@@ -1017,10 +1015,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
+ 		if (!urb [i])
+ 			continue;
+ 		urb [i]->dev = udev;
+-		if (urb [i]->setup_packet)
+-			usb_buffer_free (udev, sizeof (struct usb_ctrlrequest),
+-					urb [i]->setup_packet,
+-					urb [i]->setup_dma);
++		kfree(urb[i]->setup_packet);
+ 		simple_free_urb (urb [i]);
+ 	}
+ 	kfree (urb);
+diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+index f253edec3bb8..44716427c51c 100644
+--- a/drivers/usb/storage/transport.c
++++ b/drivers/usb/storage/transport.c
+@@ -147,11 +147,9 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)
+ 	 * hasn't been mapped for DMA.  Yes, this is clunky, but it's
+ 	 * easier than always having the caller tell us whether the
+ 	 * transfer buffer has already been mapped. */
+-	us->current_urb->transfer_flags = URB_NO_SETUP_DMA_MAP;
+ 	if (us->current_urb->transfer_buffer == us->iobuf)
+ 		us->current_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ 	us->current_urb->transfer_dma = us->iobuf_dma;
+-	us->current_urb->setup_dma = us->cr_dma;
+ 
+ 	/* submit the URB */
+ 	status = usb_submit_urb(us->current_urb, GFP_NOIO);
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index bbeeb92a2131..c54a370c76c5 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -407,9 +407,8 @@ static int associate_dev(struct us_data *us, struct usb_interface *intf)
+ 	/* Store our private data in the interface */
+ 	usb_set_intfdata(intf, us);
+ 
+-	/* Allocate the device-related DMA-mapped buffers */
+-	us->cr = usb_buffer_alloc(us->pusb_dev, sizeof(*us->cr),
+-			GFP_KERNEL, &us->cr_dma);
++	/* Allocate the control/setup and DMA-mapped buffers */
++	us->cr = kmalloc(sizeof(*us->cr), GFP_KERNEL);
+ 	if (!us->cr) {
+ 		US_DEBUGP("usb_ctrlrequest allocation failed\n");
+ 		return -ENOMEM;
+@@ -757,13 +756,9 @@ static void dissociate_dev(struct us_data *us)
+ {
+ 	US_DEBUGP("-- %s\n", __func__);
+ 
+-	/* Free the device-related DMA-mapped buffers */
+-	if (us->cr)
+-		usb_buffer_free(us->pusb_dev, sizeof(*us->cr), us->cr,
+-				us->cr_dma);
+-	if (us->iobuf)
+-		usb_buffer_free(us->pusb_dev, US_IOBUF_SIZE, us->iobuf,
+-				us->iobuf_dma);
++	/* Free the buffers */
++	kfree(us->cr);
++	usb_buffer_free(us->pusb_dev, US_IOBUF_SIZE, us->iobuf, us->iobuf_dma);
+ 
+ 	/* Remove our private data from the interface */
+ 	usb_set_intfdata(us->pusb_intf, NULL);
+diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
+index 69717134231b..89d3bfff98df 100644
+--- a/drivers/usb/storage/usb.h
++++ b/drivers/usb/storage/usb.h
+@@ -139,8 +139,7 @@ struct us_data {
+ 	struct usb_ctrlrequest	*cr;		 /* control requests	 */
+ 	struct usb_sg_request	current_sg;	 /* scatter-gather req.  */
+ 	unsigned char		*iobuf;		 /* I/O buffer		 */
+-	dma_addr_t		cr_dma;		 /* buffer DMA addresses */
+-	dma_addr_t		iobuf_dma;
++	dma_addr_t		iobuf_dma;	 /* buffer DMA addresses */
+ 	struct task_struct	*ctl_thread;	 /* the control thread   */
+ 
+ 	/* mutual exclusion and synchronization structures */
+diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
+index 112ef7e26f6b..2ce6b7eccc6a 100644
+--- a/drivers/usb/wusbcore/wa-xfer.c
++++ b/drivers/usb/wusbcore/wa-xfer.c
+@@ -474,8 +474,6 @@ static void __wa_xfer_setup_hdr0(struct wa_xfer *xfer,
+ 		struct wa_xfer_ctl *xfer_ctl =
+ 			container_of(xfer_hdr0, struct wa_xfer_ctl, hdr);
+ 		xfer_ctl->bmAttribute = xfer->is_inbound ? 1 : 0;
+-		BUG_ON(xfer->urb->transfer_flags & URB_NO_SETUP_DMA_MAP
+-		       && xfer->urb->setup_packet == NULL);
+ 		memcpy(&xfer_ctl->baSetupData, xfer->urb->setup_packet,
+ 		       sizeof(xfer_ctl->baSetupData));
+ 		break;

commit 749da5f82fe33ff68dd4aa1a5e35cd9aa6246dab
+Author: Alan Stern 
+Date:   Thu Mar 4 17:05:08 2010 -0500
+
+    USB: straighten out port feature vs. port status usage
+    
+    This patch (as1349b) clears up the confusion in many USB host
+    controller drivers between port features and port statuses.  In mosty
+    cases it's true that the status bit is in the position given by the
+    corresponding feature value, but that's not always true and it's not
+    guaranteed in the USB spec.
+    
+    There's no functional change, just replacing expressions of the form
+    (1 << USB_PORT_FEAT_x) with USB_PORT_STAT_x, which has the same value.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 5ac27ed0c635..497dbb29744d 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -3037,7 +3037,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 
+ 		/* maybe switch power back on (e.g. root hub was reset) */
+ 		if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2
+-				&& !(portstatus & (1 << USB_PORT_FEAT_POWER)))
++				&& !(portstatus & USB_PORT_STAT_POWER))
+ 			set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
+ 
+ 		if (portstatus & USB_PORT_STAT_ENABLE)
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index c7178bcde67a..c44018109a13 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -659,7 +659,7 @@ static int ehci_hub_control (
+ 		 * Even if OWNER is set, so the port is owned by the
+ 		 * companion controller, khubd needs to be able to clear
+ 		 * the port-change status bits (especially
+-		 * USB_PORT_FEAT_C_CONNECTION).
++		 * USB_PORT_STAT_C_CONNECTION).
+ 		 */
+ 
+ 		switch (wValue) {
+@@ -729,12 +729,12 @@ static int ehci_hub_control (
+ 
+ 		// wPortChange bits
+ 		if (temp & PORT_CSC)
+-			status |= 1 << USB_PORT_FEAT_C_CONNECTION;
++			status |= USB_PORT_STAT_C_CONNECTION << 16;
+ 		if (temp & PORT_PEC)
+-			status |= 1 << USB_PORT_FEAT_C_ENABLE;
++			status |= USB_PORT_STAT_C_ENABLE << 16;
+ 
+ 		if ((temp & PORT_OCC) && !ignore_oc){
+-			status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT;
++			status |= USB_PORT_STAT_C_OVERCURRENT << 16;
+ 
+ 			/*
+ 			 * Hubs should disable port power on over-current.
+@@ -791,7 +791,7 @@ static int ehci_hub_control (
+ 		if ((temp & PORT_RESET)
+ 				&& time_after_eq(jiffies,
+ 					ehci->reset_done[wIndex])) {
+-			status |= 1 << USB_PORT_FEAT_C_RESET;
++			status |= USB_PORT_STAT_C_RESET << 16;
+ 			ehci->reset_done [wIndex] = 0;
+ 
+ 			/* force reset to complete */
+@@ -833,7 +833,7 @@ static int ehci_hub_control (
+ 		 */
+ 
+ 		if (temp & PORT_CONNECT) {
+-			status |= 1 << USB_PORT_FEAT_CONNECTION;
++			status |= USB_PORT_STAT_CONNECTION;
+ 			// status may be from integrated TT
+ 			if (ehci->has_hostpc) {
+ 				temp1 = ehci_readl(ehci, hostpc_reg);
+@@ -842,11 +842,11 @@ static int ehci_hub_control (
+ 				status |= ehci_port_speed(ehci, temp);
+ 		}
+ 		if (temp & PORT_PE)
+-			status |= 1 << USB_PORT_FEAT_ENABLE;
++			status |= USB_PORT_STAT_ENABLE;
+ 
+ 		/* maybe the port was unsuspended without our knowledge */
+ 		if (temp & (PORT_SUSPEND|PORT_RESUME)) {
+-			status |= 1 << USB_PORT_FEAT_SUSPEND;
++			status |= USB_PORT_STAT_SUSPEND;
+ 		} else if (test_bit(wIndex, &ehci->suspended_ports)) {
+ 			clear_bit(wIndex, &ehci->suspended_ports);
+ 			ehci->reset_done[wIndex] = 0;
+@@ -855,13 +855,13 @@ static int ehci_hub_control (
+ 		}
+ 
+ 		if (temp & PORT_OC)
+-			status |= 1 << USB_PORT_FEAT_OVER_CURRENT;
++			status |= USB_PORT_STAT_OVERCURRENT;
+ 		if (temp & PORT_RESET)
+-			status |= 1 << USB_PORT_FEAT_RESET;
++			status |= USB_PORT_STAT_RESET;
+ 		if (temp & PORT_POWER)
+-			status |= 1 << USB_PORT_FEAT_POWER;
++			status |= USB_PORT_STAT_POWER;
+ 		if (test_bit(wIndex, &ehci->port_c_suspend))
+-			status |= 1 << USB_PORT_FEAT_C_SUSPEND;
++			status |= USB_PORT_STAT_C_SUSPEND << 16;
+ 
+ #ifndef	VERBOSE_DEBUG
+ 	if (status & ~0xffff)	/* only if wPortChange is interesting */
+diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
+index acc157da7275..6a6a50849bfe 100644
+--- a/drivers/usb/host/isp1362-hcd.c
++++ b/drivers/usb/host/isp1362-hcd.c
+@@ -1265,7 +1265,7 @@ static int isp1362_urb_enqueue(struct usb_hcd *hcd,
+ 
+ 	/* don't submit to a dead or disabled port */
+ 	if (!((isp1362_hcd->rhport[0] | isp1362_hcd->rhport[1]) &
+-	      (1 << USB_PORT_FEAT_ENABLE)) ||
++	      USB_PORT_STAT_ENABLE) ||
+ 	    !HC_IS_RUNNING(hcd->state)) {
+ 		kfree(ep);
+ 		retval = -ENODEV;
+diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c
+index cfdac6da9556..13f7d1200bc0 100644
+--- a/drivers/usb/host/isp1760-hcd.c
++++ b/drivers/usb/host/isp1760-hcd.c
+@@ -1923,7 +1923,7 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
+ 		 * Even if OWNER is set, so the port is owned by the
+ 		 * companion controller, khubd needs to be able to clear
+ 		 * the port-change status bits (especially
+-		 * USB_PORT_FEAT_C_CONNECTION).
++		 * USB_PORT_STAT_C_CONNECTION).
+ 		 */
+ 
+ 		switch (wValue) {
+@@ -1987,7 +1987,7 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
+ 
+ 		/* wPortChange bits */
+ 		if (temp & PORT_CSC)
+-			status |= 1 << USB_PORT_FEAT_C_CONNECTION;
++			status |= USB_PORT_STAT_C_CONNECTION << 16;
+ 
+ 
+ 		/* whoever resumes must GetPortStatus to complete it!! */
+@@ -2007,7 +2007,7 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
+ 			/* resume completed? */
+ 			else if (time_after_eq(jiffies,
+ 					priv->reset_done)) {
+-				status |= 1 << USB_PORT_FEAT_C_SUSPEND;
++				status |= USB_PORT_STAT_C_SUSPEND << 16;
+ 				priv->reset_done = 0;
+ 
+ 				/* stop resume signaling */
+@@ -2031,7 +2031,7 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
+ 		if ((temp & PORT_RESET)
+ 				&& time_after_eq(jiffies,
+ 					priv->reset_done)) {
+-			status |= 1 << USB_PORT_FEAT_C_RESET;
++			status |= USB_PORT_STAT_C_RESET << 16;
+ 			priv->reset_done = 0;
+ 
+ 			/* force reset to complete */
+@@ -2062,18 +2062,18 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
+ 			printk(KERN_ERR "Warning: PORT_OWNER is set\n");
+ 
+ 		if (temp & PORT_CONNECT) {
+-			status |= 1 << USB_PORT_FEAT_CONNECTION;
++			status |= USB_PORT_STAT_CONNECTION;
+ 			/* status may be from integrated TT */
+ 			status |= ehci_port_speed(priv, temp);
+ 		}
+ 		if (temp & PORT_PE)
+-			status |= 1 << USB_PORT_FEAT_ENABLE;
++			status |= USB_PORT_STAT_ENABLE;
+ 		if (temp & (PORT_SUSPEND|PORT_RESUME))
+-			status |= 1 << USB_PORT_FEAT_SUSPEND;
++			status |= USB_PORT_STAT_SUSPEND;
+ 		if (temp & PORT_RESET)
+-			status |= 1 << USB_PORT_FEAT_RESET;
++			status |= USB_PORT_STAT_RESET;
+ 		if (temp & PORT_POWER)
+-			status |= 1 << USB_PORT_FEAT_POWER;
++			status |= USB_PORT_STAT_POWER;
+ 
+ 		put_unaligned(cpu_to_le32(status), (__le32 *) buf);
+ 		break;
+diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
+index 8f04c0afa59f..f608dfd09a8a 100644
+--- a/drivers/usb/host/oxu210hp-hcd.c
++++ b/drivers/usb/host/oxu210hp-hcd.c
+@@ -3201,7 +3201,7 @@ static int oxu_hub_control(struct usb_hcd *hcd, u16 typeReq,
+ 		 * Even if OWNER is set, so the port is owned by the
+ 		 * companion controller, khubd needs to be able to clear
+ 		 * the port-change status bits (especially
+-		 * USB_PORT_FEAT_C_CONNECTION).
++		 * USB_PORT_STAT_C_CONNECTION).
+ 		 */
+ 
+ 		switch (wValue) {
+@@ -3263,11 +3263,11 @@ static int oxu_hub_control(struct usb_hcd *hcd, u16 typeReq,
+ 
+ 		/* wPortChange bits */
+ 		if (temp & PORT_CSC)
+-			status |= 1 << USB_PORT_FEAT_C_CONNECTION;
++			status |= USB_PORT_STAT_C_CONNECTION << 16;
+ 		if (temp & PORT_PEC)
+-			status |= 1 << USB_PORT_FEAT_C_ENABLE;
++			status |= USB_PORT_STAT_C_ENABLE << 16;
+ 		if ((temp & PORT_OCC) && !ignore_oc)
+-			status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT;
++			status |= USB_PORT_STAT_C_OVERCURRENT << 16;
+ 
+ 		/* whoever resumes must GetPortStatus to complete it!! */
+ 		if (temp & PORT_RESUME) {
+@@ -3285,7 +3285,7 @@ static int oxu_hub_control(struct usb_hcd *hcd, u16 typeReq,
+ 			/* resume completed? */
+ 			else if (time_after_eq(jiffies,
+ 					oxu->reset_done[wIndex])) {
+-				status |= 1 << USB_PORT_FEAT_C_SUSPEND;
++				status |= USB_PORT_STAT_C_SUSPEND << 16;
+ 				oxu->reset_done[wIndex] = 0;
+ 
+ 				/* stop resume signaling */
+@@ -3308,7 +3308,7 @@ static int oxu_hub_control(struct usb_hcd *hcd, u16 typeReq,
+ 		if ((temp & PORT_RESET)
+ 				&& time_after_eq(jiffies,
+ 					oxu->reset_done[wIndex])) {
+-			status |= 1 << USB_PORT_FEAT_C_RESET;
++			status |= USB_PORT_STAT_C_RESET << 16;
+ 			oxu->reset_done[wIndex] = 0;
+ 
+ 			/* force reset to complete */
+@@ -3347,20 +3347,20 @@ static int oxu_hub_control(struct usb_hcd *hcd, u16 typeReq,
+ 		 */
+ 
+ 		if (temp & PORT_CONNECT) {
+-			status |= 1 << USB_PORT_FEAT_CONNECTION;
++			status |= USB_PORT_STAT_CONNECTION;
+ 			/* status may be from integrated TT */
+ 			status |= oxu_port_speed(oxu, temp);
+ 		}
+ 		if (temp & PORT_PE)
+-			status |= 1 << USB_PORT_FEAT_ENABLE;
++			status |= USB_PORT_STAT_ENABLE;
+ 		if (temp & (PORT_SUSPEND|PORT_RESUME))
+-			status |= 1 << USB_PORT_FEAT_SUSPEND;
++			status |= USB_PORT_STAT_SUSPEND;
+ 		if (temp & PORT_OC)
+-			status |= 1 << USB_PORT_FEAT_OVER_CURRENT;
++			status |= USB_PORT_STAT_OVERCURRENT;
+ 		if (temp & PORT_RESET)
+-			status |= 1 << USB_PORT_FEAT_RESET;
++			status |= USB_PORT_STAT_RESET;
+ 		if (temp & PORT_POWER)
+-			status |= 1 << USB_PORT_FEAT_POWER;
++			status |= USB_PORT_STAT_POWER;
+ 
+ #ifndef	OXU_VERBOSE_DEBUG
+ 	if (status & ~0xffff)	/* only if wPortChange is interesting */
+diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
+index a004a1220848..6db57ab6079d 100644
+--- a/drivers/usb/host/r8a66597-hcd.c
++++ b/drivers/usb/host/r8a66597-hcd.c
+@@ -1018,10 +1018,10 @@ static void start_root_hub_sampling(struct r8a66597 *r8a66597, int port,
+ 	rh->old_syssts = r8a66597_read(r8a66597, get_syssts_reg(port)) & LNST;
+ 	rh->scount = R8A66597_MAX_SAMPLING;
+ 	if (connect)
+-		rh->port |= 1 << USB_PORT_FEAT_CONNECTION;
++		rh->port |= USB_PORT_STAT_CONNECTION;
+ 	else
+-		rh->port &= ~(1 << USB_PORT_FEAT_CONNECTION);
+-	rh->port |= 1 << USB_PORT_FEAT_C_CONNECTION;
++		rh->port &= ~USB_PORT_STAT_CONNECTION;
++	rh->port |= USB_PORT_STAT_C_CONNECTION << 16;
+ 
+ 	r8a66597_root_hub_start_polling(r8a66597);
+ }
+@@ -1065,8 +1065,8 @@ static void r8a66597_usb_connect(struct r8a66597 *r8a66597, int port)
+ 	else if (speed == LSMODE)
+ 		rh->port |= USB_PORT_STAT_LOW_SPEED;
+ 
+-	rh->port &= ~(1 << USB_PORT_FEAT_RESET);
+-	rh->port |= 1 << USB_PORT_FEAT_ENABLE;
++	rh->port &= USB_PORT_STAT_RESET;
++	rh->port |= USB_PORT_STAT_ENABLE;
+ }
+ 
+ /* this function must be called with interrupt disabled */
+@@ -1705,7 +1705,7 @@ static void r8a66597_root_hub_control(struct r8a66597 *r8a66597, int port)
+ 	u16 tmp;
+ 	struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
+ 
+-	if (rh->port & (1 << USB_PORT_FEAT_RESET)) {
++	if (rh->port & USB_PORT_STAT_RESET) {
+ 		unsigned long dvstctr_reg = get_dvstctr_reg(port);
+ 
+ 		tmp = r8a66597_read(r8a66597, dvstctr_reg);
+@@ -1717,7 +1717,7 @@ static void r8a66597_root_hub_control(struct r8a66597 *r8a66597, int port)
+ 			r8a66597_usb_connect(r8a66597, port);
+ 	}
+ 
+-	if (!(rh->port & (1 << USB_PORT_FEAT_CONNECTION))) {
++	if (!(rh->port & USB_PORT_STAT_CONNECTION)) {
+ 		r8a66597_write(r8a66597, ~ATTCH, get_intsts_reg(port));
+ 		r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(port));
+ 	}
+@@ -2185,7 +2185,7 @@ static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+ 
+ 		switch (wValue) {
+ 		case USB_PORT_FEAT_ENABLE:
+-			rh->port &= ~(1 << USB_PORT_FEAT_POWER);
++			rh->port &= ~USB_PORT_STAT_POWER;
+ 			break;
+ 		case USB_PORT_FEAT_SUSPEND:
+ 			break;
+@@ -2226,12 +2226,12 @@ static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+ 			break;
+ 		case USB_PORT_FEAT_POWER:
+ 			r8a66597_port_power(r8a66597, port, 1);
+-			rh->port |= (1 << USB_PORT_FEAT_POWER);
++			rh->port |= USB_PORT_STAT_POWER;
+ 			break;
+ 		case USB_PORT_FEAT_RESET: {
+ 			struct r8a66597_device *dev = rh->dev;
+ 
+-			rh->port |= (1 << USB_PORT_FEAT_RESET);
++			rh->port |= USB_PORT_STAT_RESET;
+ 
+ 			disable_r8a66597_pipe_all(r8a66597, dev);
+ 			free_usb_address(r8a66597, dev, 1);
+@@ -2269,12 +2269,12 @@ static int r8a66597_bus_suspend(struct usb_hcd *hcd)
+ 		struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
+ 		unsigned long dvstctr_reg = get_dvstctr_reg(port);
+ 
+-		if (!(rh->port & (1 << USB_PORT_FEAT_ENABLE)))
++		if (!(rh->port & USB_PORT_STAT_ENABLE))
+ 			continue;
+ 
+ 		dbg("suspend port = %d", port);
+ 		r8a66597_bclr(r8a66597, UACT, dvstctr_reg);	/* suspend */
+-		rh->port |= 1 << USB_PORT_FEAT_SUSPEND;
++		rh->port |= USB_PORT_STAT_SUSPEND;
+ 
+ 		if (rh->dev->udev->do_remote_wakeup) {
+ 			msleep(3);	/* waiting last SOF */
+@@ -2300,12 +2300,12 @@ static int r8a66597_bus_resume(struct usb_hcd *hcd)
+ 		struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
+ 		unsigned long dvstctr_reg = get_dvstctr_reg(port);
+ 
+-		if (!(rh->port & (1 << USB_PORT_FEAT_SUSPEND)))
++		if (!(rh->port & USB_PORT_STAT_SUSPEND))
+ 			continue;
+ 
+ 		dbg("resume port = %d", port);
+-		rh->port &= ~(1 << USB_PORT_FEAT_SUSPEND);
+-		rh->port |= 1 << USB_PORT_FEAT_C_SUSPEND;
++		rh->port &= ~USB_PORT_STAT_SUSPEND;
++		rh->port |= USB_PORT_STAT_C_SUSPEND < 16;
+ 		r8a66597_mdfy(r8a66597, RESUME, RESUME | UACT, dvstctr_reg);
+ 		msleep(50);
+ 		r8a66597_mdfy(r8a66597, UACT, RESUME | UACT, dvstctr_reg);
+diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
+index dcd7fab7179c..bcf9f0e809de 100644
+--- a/drivers/usb/host/sl811-hcd.c
++++ b/drivers/usb/host/sl811-hcd.c
+@@ -90,10 +90,10 @@ static void port_power(struct sl811 *sl811, int is_on)
+ 
+ 	/* hub is inactive unless the port is powered */
+ 	if (is_on) {
+-		if (sl811->port1 & (1 << USB_PORT_FEAT_POWER))
++		if (sl811->port1 & USB_PORT_STAT_POWER)
+ 			return;
+ 
+-		sl811->port1 = (1 << USB_PORT_FEAT_POWER);
++		sl811->port1 = USB_PORT_STAT_POWER;
+ 		sl811->irq_enable = SL11H_INTMASK_INSRMV;
+ 	} else {
+ 		sl811->port1 = 0;
+@@ -407,7 +407,7 @@ static struct sl811h_ep	*start(struct sl811 *sl811, u8 bank)
+ 
+ static inline void start_transfer(struct sl811 *sl811)
+ {
+-	if (sl811->port1 & (1 << USB_PORT_FEAT_SUSPEND))
++	if (sl811->port1 & USB_PORT_STAT_SUSPEND)
+ 		return;
+ 	if (sl811->active_a == NULL) {
+ 		sl811->active_a = start(sl811, SL811_EP_A(SL811_HOST_BUF));
+@@ -721,23 +721,23 @@ static irqreturn_t sl811h_irq(struct usb_hcd *hcd)
+ 		 * force the reset and make khubd clean up later.
+ 		 */
+ 		if (irqstat & SL11H_INTMASK_RD)
+-			sl811->port1 &= ~(1 << USB_PORT_FEAT_CONNECTION);
++			sl811->port1 &= ~USB_PORT_STAT_CONNECTION;
+ 		else
+-			sl811->port1 |= 1 << USB_PORT_FEAT_CONNECTION;
++			sl811->port1 |= USB_PORT_STAT_CONNECTION;
+ 
+-		sl811->port1 |= 1 << USB_PORT_FEAT_C_CONNECTION;
++		sl811->port1 |= USB_PORT_STAT_C_CONNECTION << 16;
+ 
+ 	} else if (irqstat & SL11H_INTMASK_RD) {
+-		if (sl811->port1 & (1 << USB_PORT_FEAT_SUSPEND)) {
++		if (sl811->port1 & USB_PORT_STAT_SUSPEND) {
+ 			DBG("wakeup\n");
+-			sl811->port1 |= 1 << USB_PORT_FEAT_C_SUSPEND;
++			sl811->port1 |= USB_PORT_STAT_C_SUSPEND << 16;
+ 			sl811->stat_wake++;
+ 		} else
+ 			irqstat &= ~SL11H_INTMASK_RD;
+ 	}
+ 
+ 	if (irqstat) {
+-		if (sl811->port1 & (1 << USB_PORT_FEAT_ENABLE))
++		if (sl811->port1 & USB_PORT_STAT_ENABLE)
+ 			start_transfer(sl811);
+ 		ret = IRQ_HANDLED;
+ 		if (retries--)
+@@ -819,7 +819,7 @@ static int sl811h_urb_enqueue(
+ 	spin_lock_irqsave(&sl811->lock, flags);
+ 
+ 	/* don't submit to a dead or disabled port */
+-	if (!(sl811->port1 & (1 << USB_PORT_FEAT_ENABLE))
++	if (!(sl811->port1 & USB_PORT_STAT_ENABLE)
+ 			|| !HC_IS_RUNNING(hcd->state)) {
+ 		retval = -ENODEV;
+ 		kfree(ep);
+@@ -1119,8 +1119,8 @@ sl811h_timer(unsigned long _sl811)
+ 	unsigned long	flags;
+ 	u8		irqstat;
+ 	u8		signaling = sl811->ctrl1 & SL11H_CTL1MASK_FORCE;
+-	const u32	mask = (1 << USB_PORT_FEAT_CONNECTION)
+-				| (1 << USB_PORT_FEAT_ENABLE)
++	const u32	mask = USB_PORT_STAT_CONNECTION
++				| USB_PORT_STAT_ENABLE
+ 				| USB_PORT_STAT_LOW_SPEED;
+ 
+ 	spin_lock_irqsave(&sl811->lock, flags);
+@@ -1135,8 +1135,8 @@ sl811h_timer(unsigned long _sl811)
+ 	switch (signaling) {
+ 	case SL11H_CTL1MASK_SE0:
+ 		DBG("end reset\n");
+-		sl811->port1 = (1 << USB_PORT_FEAT_C_RESET)
+-				| (1 << USB_PORT_FEAT_POWER);
++		sl811->port1 = (USB_PORT_STAT_C_RESET << 16)
++				 | USB_PORT_STAT_POWER;
+ 		sl811->ctrl1 = 0;
+ 		/* don't wrongly ack RD */
+ 		if (irqstat & SL11H_INTMASK_INSRMV)
+@@ -1144,7 +1144,7 @@ sl811h_timer(unsigned long _sl811)
+ 		break;
+ 	case SL11H_CTL1MASK_K:
+ 		DBG("end resume\n");
+-		sl811->port1 &= ~(1 << USB_PORT_FEAT_SUSPEND);
++		sl811->port1 &= ~USB_PORT_STAT_SUSPEND;
+ 		break;
+ 	default:
+ 		DBG("odd timer signaling: %02x\n", signaling);
+@@ -1154,9 +1154,9 @@ sl811h_timer(unsigned long _sl811)
+ 
+ 	if (irqstat & SL11H_INTMASK_RD) {
+ 		/* usbcore nukes all pending transactions on disconnect */
+-		if (sl811->port1 & (1 << USB_PORT_FEAT_CONNECTION))
+-			sl811->port1 |= (1 << USB_PORT_FEAT_C_CONNECTION)
+-					| (1 << USB_PORT_FEAT_C_ENABLE);
++		if (sl811->port1 & USB_PORT_STAT_CONNECTION)
++			sl811->port1 |= (USB_PORT_STAT_C_CONNECTION << 16)
++					| (USB_PORT_STAT_C_ENABLE << 16);
+ 		sl811->port1 &= ~mask;
+ 		sl811->irq_enable = SL11H_INTMASK_INSRMV;
+ 	} else {
+@@ -1166,7 +1166,7 @@ sl811h_timer(unsigned long _sl811)
+ 		sl811->irq_enable = SL11H_INTMASK_INSRMV | SL11H_INTMASK_RD;
+ 	}
+ 
+-	if (sl811->port1 & (1 << USB_PORT_FEAT_CONNECTION)) {
++	if (sl811->port1 & USB_PORT_STAT_CONNECTION) {
+ 		u8	ctrl2 = SL811HS_CTL2_INIT;
+ 
+ 		sl811->irq_enable |= SL11H_INTMASK_DONE_A;
+@@ -1233,7 +1233,7 @@ sl811h_hub_control(
+ 
+ 		switch (wValue) {
+ 		case USB_PORT_FEAT_ENABLE:
+-			sl811->port1 &= (1 << USB_PORT_FEAT_POWER);
++			sl811->port1 &= USB_PORT_STAT_POWER;
+ 			sl811->ctrl1 = 0;
+ 			sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1);
+ 			sl811->irq_enable = SL11H_INTMASK_INSRMV;
+@@ -1241,7 +1241,7 @@ sl811h_hub_control(
+ 						sl811->irq_enable);
+ 			break;
+ 		case USB_PORT_FEAT_SUSPEND:
+-			if (!(sl811->port1 & (1 << USB_PORT_FEAT_SUSPEND)))
++			if (!(sl811->port1 & USB_PORT_STAT_SUSPEND))
+ 				break;
+ 
+ 			/* 20 msec of resume/K signaling, other irqs blocked */
+@@ -1290,9 +1290,9 @@ sl811h_hub_control(
+ 			goto error;
+ 		switch (wValue) {
+ 		case USB_PORT_FEAT_SUSPEND:
+-			if (sl811->port1 & (1 << USB_PORT_FEAT_RESET))
++			if (sl811->port1 & USB_PORT_STAT_RESET)
+ 				goto error;
+-			if (!(sl811->port1 & (1 << USB_PORT_FEAT_ENABLE)))
++			if (!(sl811->port1 & USB_PORT_STAT_ENABLE))
+ 				goto error;
+ 
+ 			DBG("suspend...\n");
+@@ -1303,9 +1303,9 @@ sl811h_hub_control(
+ 			port_power(sl811, 1);
+ 			break;
+ 		case USB_PORT_FEAT_RESET:
+-			if (sl811->port1 & (1 << USB_PORT_FEAT_SUSPEND))
++			if (sl811->port1 & USB_PORT_STAT_SUSPEND)
+ 				goto error;
+-			if (!(sl811->port1 & (1 << USB_PORT_FEAT_POWER)))
++			if (!(sl811->port1 & USB_PORT_STAT_POWER))
+ 				break;
+ 
+ 			/* 50 msec of reset/SE0 signaling, irqs blocked */
+@@ -1314,7 +1314,7 @@ sl811h_hub_control(
+ 						sl811->irq_enable);
+ 			sl811->ctrl1 = SL11H_CTL1MASK_SE0;
+ 			sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1);
+-			sl811->port1 |= (1 << USB_PORT_FEAT_RESET);
++			sl811->port1 |= USB_PORT_STAT_RESET;
+ 			mod_timer(&sl811->timer, jiffies
+ 					+ msecs_to_jiffies(50));
+ 			break;
+diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
+index dd69df1e4558..325b47a267b9 100644
+--- a/drivers/usb/host/xhci-hub.c
++++ b/drivers/usb/host/xhci-hub.c
+@@ -205,27 +205,27 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+ 
+ 		/* wPortChange bits */
+ 		if (temp & PORT_CSC)
+-			status |= 1 << USB_PORT_FEAT_C_CONNECTION;
++			status |= USB_PORT_STAT_C_CONNECTION << 16;
+ 		if (temp & PORT_PEC)
+-			status |= 1 << USB_PORT_FEAT_C_ENABLE;
++			status |= USB_PORT_STAT_C_ENABLE << 16;
+ 		if ((temp & PORT_OCC))
+-			status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT;
++			status |= USB_PORT_STAT_C_OVERCURRENT << 16;
+ 		/*
+ 		 * FIXME ignoring suspend, reset, and USB 2.1/3.0 specific
+ 		 * changes
+ 		 */
+ 		if (temp & PORT_CONNECT) {
+-			status |= 1 << USB_PORT_FEAT_CONNECTION;
++			status |= USB_PORT_STAT_CONNECTION;
+ 			status |= xhci_port_speed(temp);
+ 		}
+ 		if (temp & PORT_PE)
+-			status |= 1 << USB_PORT_FEAT_ENABLE;
++			status |= USB_PORT_STAT_ENABLE;
+ 		if (temp & PORT_OC)
+-			status |= 1 << USB_PORT_FEAT_OVER_CURRENT;
++			status |= USB_PORT_STAT_OVERCURRENT;
+ 		if (temp & PORT_RESET)
+-			status |= 1 << USB_PORT_FEAT_RESET;
++			status |= USB_PORT_STAT_RESET;
+ 		if (temp & PORT_POWER)
+-			status |= 1 << USB_PORT_FEAT_POWER;
++			status |= USB_PORT_STAT_POWER;
+ 		xhci_dbg(xhci, "Get port status returned 0x%x\n", status);
+ 		put_unaligned(cpu_to_le32(status), (__le32 *) buf);
+ 		break;
+diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
+index 705cc4ad8737..ced6d9ea9af3 100644
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -353,8 +353,7 @@ void musb_hnp_stop(struct musb *musb)
+ 	 * which cause occasional OPT A "Did not receive reset after connect"
+ 	 * errors.
+ 	 */
+-	musb->port1_status &=
+-		~(1 << USB_PORT_FEAT_C_CONNECTION);
++	musb->port1_status &= ~(USB_PORT_STAT_C_CONNECTION << 16);
+ }
+ 
+ #endif
+@@ -530,8 +529,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
+ 				musb_writeb(mbase, MUSB_DEVCTL, devctl);
+ 			} else {
+ 				musb->port1_status |=
+-					  (1 << USB_PORT_FEAT_OVER_CURRENT)
+-					| (1 << USB_PORT_FEAT_C_OVER_CURRENT);
++					  USB_PORT_STAT_OVERCURRENT
++					| (USB_PORT_STAT_C_OVERCURRENT << 16);
+ 			}
+ 			break;
+ 		default:
+diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c
+index 7775e1c0a215..92e85e027cfb 100644
+--- a/drivers/usb/musb/musb_virthub.c
++++ b/drivers/usb/musb/musb_virthub.c
+@@ -183,8 +183,8 @@ static void musb_port_reset(struct musb *musb, bool do_reset)
+ 
+ void musb_root_disconnect(struct musb *musb)
+ {
+-	musb->port1_status = (1 << USB_PORT_FEAT_POWER)
+-			| (1 << USB_PORT_FEAT_C_CONNECTION);
++	musb->port1_status = USB_PORT_STAT_POWER
++			| (USB_PORT_STAT_C_CONNECTION << 16);
+ 
+ 	usb_hcd_poll_rh_status(musb_to_hcd(musb));
+ 	musb->is_active = 0;

commit 288ead45fa6637e959015d055304f521cbbc0575
+Author: Alan Stern 
+Date:   Thu Mar 4 11:32:30 2010 -0500
+
+    USB: remove bogus USB_PORT_FEAT_*_SPEED symbols
+    
+    This patch (as1348) removes the bogus
+    USB_PORT_FEAT_{HIGHSPEED,SUPERSPEED} symbols from ch11.h.  No such
+    features are defined by the USB spec.  (There is a PORT_LOWSPEED
+    feature, but the spec doesn't mention it except to say that host
+    software should never use it.)  The speed indicators are port
+    statuses, not port features.
+    
+    As a temporary workaround for the xhci-hcd driver, a fictional
+    USB_PORT_STAT_SUPER_SPEED symbol is added.
+    
+    Signed-off-by: Alan Stern 
+    CC: Sarah Sharp 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 1883c3c7b69b..5ac27ed0c635 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -153,11 +153,11 @@ static int usb_reset_and_verify_device(struct usb_device *udev);
+ 
+ static inline char *portspeed(int portstatus)
+ {
+-	if (portstatus & (1 << USB_PORT_FEAT_HIGHSPEED))
++	if (portstatus & USB_PORT_STAT_HIGH_SPEED)
+     		return "480 Mb/s";
+-	else if (portstatus & (1 << USB_PORT_FEAT_LOWSPEED))
++	else if (portstatus & USB_PORT_STAT_LOW_SPEED)
+ 		return "1.5 Mb/s";
+-	else if (portstatus & (1 << USB_PORT_FEAT_SUPERSPEED))
++	else if (portstatus & USB_PORT_STAT_SUPER_SPEED)
+ 		return "5.0 Gb/s";
+ 	else
+ 		return "12 Mb/s";
+@@ -3075,7 +3075,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 		if (!(hcd->driver->flags & HCD_USB3))
+ 			udev->speed = USB_SPEED_UNKNOWN;
+ 		else if ((hdev->parent == NULL) &&
+-				(portstatus & (1 << USB_PORT_FEAT_SUPERSPEED)))
++				(portstatus & USB_PORT_STAT_SUPER_SPEED))
+ 			udev->speed = USB_SPEED_SUPER;
+ 		else
+ 			udev->speed = USB_SPEED_UNKNOWN;
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 556c0b48f3ab..4ebe9ad209e4 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -556,20 +556,20 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
+ 		case 0:
+ 			return 0;
+ 		case 1:
+-			return (1<root_hub[port];
+ 
+-	rh->port &= ~((1 << USB_PORT_FEAT_HIGHSPEED) |
+-		      (1 << USB_PORT_FEAT_LOWSPEED));
++	rh->port &= ~(USB_PORT_STAT_HIGH_SPEED | USB_PORT_STAT_LOW_SPEED);
+ 	if (speed == HSMODE)
+-		rh->port |= (1 << USB_PORT_FEAT_HIGHSPEED);
++		rh->port |= USB_PORT_STAT_HIGH_SPEED;
+ 	else if (speed == LSMODE)
+-		rh->port |= (1 << USB_PORT_FEAT_LOWSPEED);
++		rh->port |= USB_PORT_STAT_LOW_SPEED;
+ 
+ 	rh->port &= ~(1 << USB_PORT_FEAT_RESET);
+ 	rh->port |= 1 << USB_PORT_FEAT_ENABLE;
+diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
+index 8f2f477890c4..dcd7fab7179c 100644
+--- a/drivers/usb/host/sl811-hcd.c
++++ b/drivers/usb/host/sl811-hcd.c
+@@ -1121,7 +1121,7 @@ sl811h_timer(unsigned long _sl811)
+ 	u8		signaling = sl811->ctrl1 & SL11H_CTL1MASK_FORCE;
+ 	const u32	mask = (1 << USB_PORT_FEAT_CONNECTION)
+ 				| (1 << USB_PORT_FEAT_ENABLE)
+-				| (1 << USB_PORT_FEAT_LOWSPEED);
++				| USB_PORT_STAT_LOW_SPEED;
+ 
+ 	spin_lock_irqsave(&sl811->lock, flags);
+ 
+@@ -1162,7 +1162,7 @@ sl811h_timer(unsigned long _sl811)
+ 	} else {
+ 		sl811->port1 |= mask;
+ 		if (irqstat & SL11H_INTMASK_DP)
+-			sl811->port1 &= ~(1 << USB_PORT_FEAT_LOWSPEED);
++			sl811->port1 &= ~USB_PORT_STAT_LOW_SPEED;
+ 		sl811->irq_enable = SL11H_INTMASK_INSRMV | SL11H_INTMASK_RD;
+ 	}
+ 
+@@ -1173,7 +1173,7 @@ sl811h_timer(unsigned long _sl811)
+ #ifdef USE_B
+ 		sl811->irq_enable |= SL11H_INTMASK_DONE_B;
+ #endif
+-		if (sl811->port1 & (1 << USB_PORT_FEAT_LOWSPEED)) {
++		if (sl811->port1 & USB_PORT_STAT_LOW_SPEED) {
+ 			sl811->ctrl1 |= SL11H_CTL1MASK_LSPD;
+ 			ctrl2 |= SL811HS_CTL2MASK_DSWAP;
+ 		}
+diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
+index 208b805b80eb..dd69df1e4558 100644
+--- a/drivers/usb/host/xhci-hub.c
++++ b/drivers/usb/host/xhci-hub.c
+@@ -64,15 +64,15 @@ static void xhci_hub_descriptor(struct xhci_hcd *xhci,
+ static unsigned int xhci_port_speed(unsigned int port_status)
+ {
+ 	if (DEV_LOWSPEED(port_status))
+-		return 1 << USB_PORT_FEAT_LOWSPEED;
++		return USB_PORT_STAT_LOW_SPEED;
+ 	if (DEV_HIGHSPEED(port_status))
+-		return 1 << USB_PORT_FEAT_HIGHSPEED;
++		return USB_PORT_STAT_HIGH_SPEED;
+ 	if (DEV_SUPERSPEED(port_status))
+-		return 1 << USB_PORT_FEAT_SUPERSPEED;
++		return USB_PORT_STAT_SUPER_SPEED;
+ 	/*
+ 	 * FIXME: Yes, we should check for full speed, but the core uses that as
+ 	 * a default in portspeed() in usb/core/hub.c (which is the only place
+-	 * USB_PORT_FEAT_*SPEED is used).
++	 * USB_PORT_STAT_*_SPEED is used).
+ 	 */
+ 	return 0;
+ }
+diff --git a/include/linux/usb/ch11.h b/include/linux/usb/ch11.h
+index 35cb7357ff72..bd3185aba4ee 100644
+--- a/include/linux/usb/ch11.h
++++ b/include/linux/usb/ch11.h
+@@ -47,11 +47,7 @@
+ #define USB_PORT_FEAT_RESET		4
+ #define USB_PORT_FEAT_L1		5	/* L1 suspend */
+ #define USB_PORT_FEAT_POWER		8
+-#define USB_PORT_FEAT_LOWSPEED		9
+-/* This value was never in Table 11-17 */
+-#define USB_PORT_FEAT_HIGHSPEED		10
+-/* This value is also fake */
+-#define USB_PORT_FEAT_SUPERSPEED	11
++#define USB_PORT_FEAT_LOWSPEED		9	/* Should never be used */
+ #define USB_PORT_FEAT_C_CONNECTION	16
+ #define USB_PORT_FEAT_C_ENABLE		17
+ #define USB_PORT_FEAT_C_SUSPEND		18
+@@ -87,6 +83,7 @@ struct usb_port_status {
+ #define USB_PORT_STAT_TEST              0x0800
+ #define USB_PORT_STAT_INDICATOR         0x1000
+ /* bits 13 to 15 are reserved */
++#define USB_PORT_STAT_SUPER_SPEED	0x8000	/* Linux-internal */
+ 
+ /*
+  * wPortChange bit field

commit 52b265a12768b9a72679bec825eb82c784116464
+Author: Alan Stern 
+Date:   Mon Mar 8 16:48:49 2010 -0500
+
+    PCI: clearing wakeup flags not needed
+    
+    This patch (as1353) removes a couple of unnecessary assignments from
+    the PCI core.  The should_wakeup flag is naturally initialized to 0;
+    there's no need to clear it.
+    
+    Acked-by: Rafael J. Wysocki 
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Jesse Barnes 
+
+diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
+index 37499127c801..60fcb6f02c91 100644
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -1631,7 +1631,6 @@ void pci_pm_init(struct pci_dev *dev)
+ 		 * let the user space enable it to wake up the system as needed.
+ 		 */
+ 		device_set_wakeup_capable(&dev->dev, true);
+-		device_set_wakeup_enable(&dev->dev, false);
+ 		/* Disable the PME# generation functionality */
+ 		pci_pme_active(dev, false);
+ 	} else {
+@@ -1655,7 +1654,6 @@ void platform_pci_wakeup_init(struct pci_dev *dev)
+ 		return;
+ 
+ 	device_set_wakeup_capable(&dev->dev, true);
+-	device_set_wakeup_enable(&dev->dev, false);
+ 	platform_pci_sleep_wake(dev, false);
+ }
+ 

commit d6f9cda1fd241bc7a1d896da94950fd972eca9b7
+Author: Alan Stern 
+Date:   Fri Mar 26 23:53:55 2010 +0100
+
+    PM: Improve device power management document
+    
+    Improve the device power management document after it's been
+    updated by the previous patch.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt
+index 10018d19e0bf..57080cd74575 100644
+--- a/Documentation/power/devices.txt
++++ b/Documentation/power/devices.txt
+@@ -1,11 +1,13 @@
+ Device Power Management
+ 
+-(C) 2010 Rafael J. Wysocki , Novell Inc.
++Copyright (c) 2010 Rafael J. Wysocki , Novell Inc.
++Copyright (c) 2010 Alan Stern 
++
+ 
+ Most of the code in Linux is device drivers, so most of the Linux power
+-management code is also driver-specific.  Most drivers will do very little;
+-others, especially for platforms with small batteries (like cell phones),
+-will do a lot.
++management (PM) code is also driver-specific.  Most drivers will do very
++little; others, especially for platforms with small batteries (like cell
++phones), will do a lot.
+ 
+ This writeup gives an overview of how drivers interact with system-wide
+ power management goals, emphasizing the models and interfaces that are
+@@ -19,9 +21,10 @@ Drivers will use one or both of these models to put devices into low-power
+ states:
+ 
+     System Sleep model:
+-	Drivers can enter low power states as part of entering system-wide
+-	low-power states like "suspend-to-ram", or (mostly for systems with
+-	disks) "hibernate" (suspend-to-disk).
++	Drivers can enter low-power states as part of entering system-wide
++	low-power states like "suspend" (also known as "suspend-to-RAM"), or
++	(mostly for systems with disks) "hibernation" (also known as
++	"suspend-to-disk").
+ 
+ 	This is something that device, bus, and class drivers collaborate on
+ 	by implementing various role-specific suspend and resume methods to
+@@ -29,41 +32,41 @@ states:
+ 	them without loss of data.
+ 
+ 	Some drivers can manage hardware wakeup events, which make the system
+-	leave that low-power state.  This feature may be enabled or disabled
++	leave the low-power state.  This feature may be enabled or disabled
+ 	using the relevant /sys/devices/.../power/wakeup file (for Ethernet
+ 	drivers the ioctl interface used by ethtool may also be used for this
+ 	purpose); enabling it may cost some power usage, but let the whole
+-	system enter low power states more often.
++	system enter low-power states more often.
+ 
+     Runtime Power Management model:
+-	Devices may also be put into low power states while the system is
++	Devices may also be put into low-power states while the system is
+ 	running, independently of other power management activity in principle.
+ 	However, devices are not generally independent of each other (for
+-	example, parent device cannot be suspended unless all of its child
+-	devices have been suspended).  Moreover,  depending on the bus type the
++	example, a parent device cannot be suspended unless all of its child
++	devices have been suspended).  Moreover, depending on the bus type the
+ 	device is on, it may be necessary to carry out some bus-specific
+-	operations on the device for this purpose.  Also, devices put into low
+-	power states at run time may require special handling during system-wide
+-	power transitions, like suspend to RAM.
++	operations on the device for this purpose.  Devices put into low power
++	states at run time may require special handling during system-wide power
++	transitions (suspend or hibernation).
+ 
+ 	For these reasons not only the device driver itself, but also the
+-	appropriate subsystem (bus type, device type or device class) driver
+-	and the PM core are involved in the runtime power management of devices.
+-	Like in the system sleep power management case, they need to collaborate
+-	by implementing various role-specific suspend and resume methods, so
+-	that the hardware is cleanly powered down and reactivated without data
+-	or service loss.
+-
+-There's not a lot to be said about those low power states except that they
+-are very system-specific, and often device-specific.  Also, that if enough
+-devices have been put into low power states (at "run time"), the effect may be
+-very similar to entering some system-wide low-power state (system sleep) ... and
+-that synergies exist, so that several drivers using runtime PM might put the
+-system into a state where even deeper power saving options are available.
+-
+-Most suspended devices will have quiesced all I/O:  no more DMA or IRQs, no
+-more data read or written, and requests from upstream drivers are no longer
+-accepted.  A given bus or platform may have different requirements though.
++	appropriate subsystem (bus type, device type or device class) driver and
++	the PM core are involved in runtime power management.  As in the system
++	sleep power management case, they need to collaborate by implementing
++	various role-specific suspend and resume methods, so that the hardware
++	is cleanly powered down and reactivated without data or service loss.
++
++There's not a lot to be said about those low-power states except that they are
++very system-specific, and often device-specific.  Also, that if enough devices
++have been put into low-power states (at runtime), the effect may be very similar
++to entering some system-wide low-power state (system sleep) ... and that
++synergies exist, so that several drivers using runtime PM might put the system
++into a state where even deeper power saving options are available.
++
++Most suspended devices will have quiesced all I/O: no more DMA or IRQs (except
++for wakeup events), no more data read or written, and requests from upstream
++drivers are no longer accepted.  A given bus or platform may have different
++requirements though.
+ 
+ Examples of hardware wakeup events include an alarm from a real time clock,
+ network wake-on-LAN packets, keyboard or mouse activity, and media insertion
+@@ -72,10 +75,10 @@ or removal (for PCMCIA, MMC/SD, USB, and so on).
+ 
+ Interfaces for Entering System Sleep States
+ ===========================================
+-There are programming interfaces provided for subsystem (bus type, device type,
+-device class) and device drivers in order to allow them to participate in the
+-power management of devices they are concerned with.  They cover the system
+-sleep power management as well as the runtime power management of devices.
++There are programming interfaces provided for subsystems (bus type, device type,
++device class) and device drivers to allow them to participate in the power
++management of devices they are concerned with.  These interfaces cover both
++system sleep and runtime power management.
+ 
+ 
+ Device Power Management Operations
+@@ -106,16 +109,15 @@ struct dev_pm_ops {
+ 
+ This structure is defined in include/linux/pm.h and the methods included in it
+ are also described in that file.  Their roles will be explained in what follows.
+-For now, it should be sufficient to remember that the last three of them are
+-specific to runtime power management, while the remaining ones are used during
++For now, it should be sufficient to remember that the last three methods are
++specific to runtime power management while the remaining ones are used during
+ system-wide power transitions.
+ 
+-There also is an "old" or "legacy", deprecated way of implementing power
+-management operations available at least for some subsystems.  This approach
+-does not use struct dev_pm_ops objects and it only is suitable for implementing
+-system sleep power management methods.  Therefore it is not described in this
+-document, so please refer directly to the source code for more information about
+-it.
++There also is a deprecated "old" or "legacy" interface for power management
++operations available at least for some subsystems.  This approach does not use
++struct dev_pm_ops objects and it is suitable only for implementing system sleep
++power management methods.  Therefore it is not described in this document, so
++please refer directly to the source code for more information about it.
+ 
+ 
+ Subsystem-Level Methods
+@@ -125,10 +127,10 @@ pointed to by the pm member of struct bus_type, struct device_type and
+ struct class.  They are mostly of interest to the people writing infrastructure
+ for buses, like PCI or USB, or device type and device class drivers.
+ 
+-Bus drivers implement these methods as appropriate for the hardware and
+-the drivers using it; PCI works differently from USB, and so on.  Not many
+-people write subsystem-level drivers; most driver code is a "device driver" that
+-builds on top of bus-specific framework code.
++Bus drivers implement these methods as appropriate for the hardware and the
++drivers using it; PCI works differently from USB, and so on.  Not many people
++write subsystem-level drivers; most driver code is a "device driver" that builds
++on top of bus-specific framework code.
+ 
+ For more information on these driver calls, see the description later;
+ they are called in phases for every device, respecting the parent-child
+@@ -137,66 +139,78 @@ sequencing in the driver model tree.
+ 
+ /sys/devices/.../power/wakeup files
+ -----------------------------------
+-All devices in the driver model have two flags to control handling of
+-wakeup events, which are hardware signals that can force the device and/or
+-system out of a low power state.  These are initialized by bus or device
+-driver code using device_init_wakeup().
++All devices in the driver model have two flags to control handling of wakeup
++events (hardware signals that can force the device and/or system out of a low
++power state).  These flags are initialized by bus or device driver code using
++device_set_wakeup_capable() and device_set_wakeup_enable(), defined in
++include/linux/pm_wakeup.h.
+ 
+ The "can_wakeup" flag just records whether the device (and its driver) can
+-physically support wakeup events.  When that flag is clear, the sysfs
+-"wakeup" file is empty, and device_may_wakeup() returns false.
+-
+-For devices that can issue wakeup events, a separate flag controls whether
+-that device should try to use its wakeup mechanism.  The initial value of
+-device_may_wakeup() will be false for the majority of devices, except for
+-power buttons, keyboards, and Ethernet adapters whose WoL (wake-on-LAN) feature
+-has been set up with ethtool.  Thus in the majority of cases the device's
+-"wakeup" file will initially hold the value "disabled".  Userspace can change
+-that to "enabled", so that device_may_wakeup() returns true, or change it back
+-to "disabled", so that it returns false again.
++physically support wakeup events.  The device_set_wakeup_capable() routine
++affects this flag.  The "should_wakeup" flag controls whether the device should
++try to use its wakeup mechanism.  device_set_wakeup_enable() affects this flag;
++for the most part drivers should not change its value.  The initial value of
++should_wakeup is supposed to be false for the majority of devices; the major
++exceptions are power buttons, keyboards, and Ethernet adapters whose WoL
++(wake-on-LAN) feature has been set up with ethtool.
++
++Whether or not a device is capable of issuing wakeup events is a hardware
++matter, and the kernel is responsible for keeping track of it.  By contrast,
++whether or not a wakeup-capable device should issue wakeup events is a policy
++decision, and it is managed by user space through a sysfs attribute: the
++power/wakeup file.  User space can write the strings "enabled" or "disabled" to
++set or clear the should_wakeup flag, respectively.  Reads from the file will
++return the corresponding string if can_wakeup is true, but if can_wakeup is
++false then reads will return an empty string, to indicate that the device
++doesn't support wakeup events.  (But even though the file appears empty, writes
++will still affect the should_wakeup flag.)
++
++The device_may_wakeup() routine returns true only if both flags are set.
++Drivers should check this routine when putting devices in a low-power state
++during a system sleep transition, to see whether or not to enable the devices'
++wakeup mechanisms.  However for runtime power management, wakeup events should
++be enabled whenever the device and driver both support them, regardless of the
++should_wakeup flag.
+ 
+ 
+ /sys/devices/.../power/control files
+ ------------------------------------
+-All devices in the driver model have a flag to control the desired behavior of
+-its driver with respect to runtime power management.  This flag, called
+-runtime_auto, is initialized by the bus type (or generally subsystem) code using
+-pm_runtime_allow() or pm_runtime_forbid(), depending on whether or not the
+-driver is supposed to power manage the device at run time by default,
+-respectively.
+-
+-This setting may be adjusted by user space by writing either "on" or "auto" to
+-the device's "control" file.  If "auto" is written, the device's runtime_auto
+-flag will be set and the driver will be allowed to power manage the device if
+-capable of doing that.  If "on" is written, the driver is not allowed to power
+-manage the device which in turn is supposed to remain in the full power state at
+-run time.  User space can check the current value of the runtime_auto flag by
+-reading from the device's "control" file.
++Each device in the driver model has a flag to control whether it is subject to
++runtime power management.  This flag, called runtime_auto, is initialized by the
++bus type (or generally subsystem) code using pm_runtime_allow() or
++pm_runtime_forbid(); the default is to allow runtime power management.
++
++The setting can be adjusted by user space by writing either "on" or "auto" to
++the device's power/control sysfs file.  Writing "auto" calls pm_runtime_allow(),
++setting the flag and allowing the device to be runtime power-managed by its
++driver.  Writing "on" calls pm_runtime_forbid(), clearing the flag, returning
++the device to full power if it was in a low-power state, and preventing the
++device from being runtime power-managed.  User space can check the current value
++of the runtime_auto flag by reading the file.
+ 
+ The device's runtime_auto flag has no effect on the handling of system-wide
+-power transitions by its driver.  In particular, the device can (and in the
+-majority of cases should and will) be put into a low power state during a
+-system-wide transition to a sleep state (like "suspend-to-RAM") even though its
+-runtime_auto flag is unset (in which case its "control" file contains "on").
++power transitions.  In particular, the device can (and in the majority of cases
++should and will) be put into a low-power state during a system-wide transition
++to a sleep state even though its runtime_auto flag is clear.
+ 
+-For more information about the runtime power management framework for devices
+-refer to Documentation/power/runtime_pm.txt.
++For more information about the runtime power management framework, refer to
++Documentation/power/runtime_pm.txt.
+ 
+ 
+-Calling Drivers to Enter System Sleep States
+-============================================
+-When the system goes into a sleep state, each device's driver is asked
+-to suspend the device by putting it into state compatible with the target
++Calling Drivers to Enter and Leave System Sleep States
++======================================================
++When the system goes into a sleep state, each device's driver is asked to
++suspend the device by putting it into a state compatible with the target
+ system state.  That's usually some version of "off", but the details are
+ system-specific.  Also, wakeup-enabled devices will usually stay partly
+ functional in order to wake the system.
+ 
+-When the system leaves that low power state, the device's driver is asked
+-to resume it.  The suspend and resume operations always go together, and
+-both are multi-phase operations.
++When the system leaves that low-power state, the device's driver is asked to
++resume it by returning it to full power.  The suspend and resume operations
++always go together, and both are multi-phase operations.
+ 
+-For simple drivers, suspend might quiesce the device using the class code
+-and then turn its hardware as "off" as possible with late_suspend.  The
++For simple drivers, suspend might quiesce the device using class code
++and then turn its hardware as "off" as possible during suspend_noirq.  The
+ matching resume calls would then completely reinitialize the hardware
+ before reactivating its class I/O queues.
+ 
+@@ -224,269 +238,129 @@ devices have been suspended.  Device drivers must be prepared to cope with such
+ situations.
+ 
+ 
+-Suspending Devices
+-------------------
+-Suspending a given device is done in several phases.  Suspending the
+-system always includes every phase, executing calls for every device
+-before the next phase begins.  Not all busses or classes support all
+-these callbacks; and not all drivers use all the callbacks.
+-
+-Generally, different callbacks are used depending on whether the system is
+-going to the standby or memory sleep state ("suspend-to-RAM") or it is going to
+-be hibernated ("suspend-to-disk").
++System Power Management Phases
++------------------------------
++Suspending or resuming the system is done in several phases.  Different phases
++are used for standby or memory sleep states ("suspend-to-RAM") and the
++hibernation state ("suspend-to-disk").  Each phase involves executing callbacks
++for every device before the next phase begins.  Not all busses or classes
++support all these callbacks and not all drivers use all the callbacks.  The
++various phases always run after tasks have been frozen and before they are
++unfrozen.  Furthermore, the *_noirq phases run at a time when IRQ handlers have
++been disabled (except for those marked with the IRQ_WAKEUP flag).
+ 
+-If the system goes to the standby or memory sleep state the phases are seen by
+-driver notifications issued in this order:
++Most phases use bus, type, and class callbacks (that is, methods defined in
++dev->bus->pm, dev->type->pm, and dev->class->pm).  The prepare and complete
++phases are exceptions; they use only bus callbacks.  When multiple callbacks
++are used in a phase, they are invoked in the order:  during
++power-down transitions and in the opposite order during power-up transitions.
++For example, during the suspend phase the PM core invokes
+ 
+-   1	bus->pm.prepare(dev) is called after tasks are frozen and it is supposed
+-	to call the device driver's ->pm.prepare() method.
++	dev->class->pm.suspend(dev);
++	dev->type->pm.suspend(dev);
++	dev->bus->pm.suspend(dev);
+ 
+-	The purpose of this method is mainly to prevent new children of the
+-	device from being registered after it has returned.  It also may be used
+-	to generally prepare the device for the upcoming system transition, but
+-	it should not put the device into a low power state.
++before moving on to the next device, whereas during the resume phase the core
++invokes
+ 
+-   2	class->pm.suspend(dev) is called if dev is associated with a class that
+-	has such a method.  It may invoke the device driver's ->pm.suspend()
+-	method, unless type->pm.suspend(dev) or bus->pm.suspend() does that.
++	dev->bus->pm.resume(dev);
++	dev->type->pm.resume(dev);
++	dev->class->pm.resume(dev);
+ 
+-   3	type->pm.suspend(dev) is called if dev is associated with a device type
+-	that has such a method.  It may invoke the device driver's
+-	->pm.suspend() method, unless class->pm.suspend(dev) or
+-	bus->pm.suspend() does that.
++These callbacks may in turn invoke device- or driver-specific methods stored in
++dev->driver->pm, but they don't have to.
+ 
+-   4	bus->pm.suspend(dev) is called, if implemented.  It usually calls the
+-	device driver's ->pm.suspend() method.
+ 
+-	This call should generally quiesce the device so that it doesn't do any
+-	I/O after the call has returned.  It also may save the device registers
+-	and put it into the appropriate low power state, depending on the bus
+-	type the device is on.
+-
+-   5	bus->pm.suspend_noirq(dev) is called, if implemented.  It may call the
+-	device driver's ->pm.suspend_noirq() method, depending on the bus type
+-	in question.
+-
+-	This method is invoked after device interrupts have been suspended,
+-	which means that the driver's interrupt handler will not be called
+-	while it is running.  It should save the values of the device's
+-	registers that weren't saved previously and finally put the device into
+-	the appropriate low power state.
++Entering System Suspend
++-----------------------
++When the system goes into the standby or memory sleep state, the phases are:
++
++		prepare, suspend, suspend_noirq.
++
++    1.	The prepare phase is meant to prevent races by preventing new devices
++	from being registered; the PM core would never know that all the
++	children of a device had been suspended if new children could be
++	registered at will.  (By contrast, devices may be unregistered at any
++	time.)  Unlike the other suspend-related phases, during the prepare
++	phase the device tree is traversed top-down.
++
++	The prepare phase uses only a bus callback.  After the callback method
++	returns, no new children may be registered below the device.  The method
++	may also prepare the device or driver in some way for the upcoming
++	system power transition, but it should not put the device into a
++	low-power state.
++
++    2.	The suspend methods should quiesce the device to stop it from performing
++	I/O.  They also may save the device registers and put it into the
++	appropriate low-power state, depending on the bus type the device is on,
++	and they may enable wakeup events.
++
++    3.	The suspend_noirq phase occurs after IRQ handlers have been disabled,
++	which means that the driver's interrupt handler will not be called while
++	the callback method is running.  The methods should save the values of
++	the device's registers that weren't saved previously and finally put the
++	device into the appropriate low-power state.
+ 
+ 	The majority of subsystems and device drivers need not implement this
+-	method.  However, bus types allowing devices to share interrupt vectors,
+-	like PCI, generally need to use it to prevent interrupt handling issues
+-	from happening during suspend.
+-
+-At the end of those phases, drivers should normally have stopped all I/O
+-transactions (DMA, IRQs), saved enough state that they can re-initialize
+-or restore previous state (as needed by the hardware), and placed the
+-device into a low-power state.  On many platforms they will also use
+-gate off one or more clock sources; sometimes they will also switch off power
+-supplies, or reduce voltages.  [Drivers supporting runtime PM may already have
+-performed some or all of the steps needed to prepare for the upcoming system
+-state transition.]
++	callback.  However, bus types allowing devices to share interrupt
++	vectors, like PCI, generally need it; otherwise a driver might encounter
++	an error during the suspend phase by fielding a shared interrupt
++	generated by some other device after its own device had been set to low
++	power.
++
++At the end of these phases, drivers should have stopped all I/O transactions
++(DMA, IRQs), saved enough state that they can re-initialize or restore previous
++state (as needed by the hardware), and placed the device into a low-power state.
++On many platforms they will gate off one or more clock sources; sometimes they
++will also switch off power supplies or reduce voltages.  (Drivers supporting
++runtime PM may already have performed some or all of these steps.)
+ 
+ If device_may_wakeup(dev) returns true, the device should be prepared for
+-generating hardware wakeup signals when the system is in the sleep state to
+-trigger a system wakeup event.  For example, enable_irq_wake() might identify
++generating hardware wakeup signals to trigger a system wakeup event when the
++system is in the sleep state.  For example, enable_irq_wake() might identify
+ GPIO signals hooked up to a switch or other external hardware, and
+ pci_enable_wake() does something similar for the PCI PME signal.
+ 
+-If a driver (or subsystem) fails it suspend method, the system won't enter the
+-desired low power state; it will resume all the devices it's suspended so far.
+-
+-
+-Hibernation Phases
+-------------------
+-Hibernating the system is more complicated than putting it into the standby or
+-memory sleep state, because it involves creating a system image and saving it.
+-Therefore there are more phases of hibernation and special device PM methods are
+-used in this case.
+-
+-First, it is necessary to prepare the system for creating a hibernation image.
+-This is similar to putting the system into the standby or memory sleep state,
+-although it generally doesn't require that devices be put into low power states
+-(that is even not desirable at this point).  Driver notifications are then
+-issued in the following order:
+-
+-   1	bus->pm.prepare(dev) is called after tasks have been frozen and enough
+-	memory has been freed.
+-
+-   2	class->pm.freeze(dev) is called if implemented.  It may invoke the
+-        device driver's ->pm.freeze() method, unless type->pm.freeze(dev) or
+-        bus->pm.freeze() does that.
+-
+-   3	type->pm.freeze(dev) is called if implemented.  It may invoke the device
+-	driver's ->pm.suspend() method, unless class->pm.freeze(dev) or
+-	bus->pm.freeze() does that.
+-
+-   4	bus->pm.freeze(dev) is called, if implemented.  It usually calls the
+-	device driver's ->pm.freeze() method.
+-
+-   5	bus->pm.freeze_noirq(dev) is called, if implemented.  It may call the
+-	device driver's ->pm.freeze_noirq() method, depending on the bus type
+-	in question.
+-
+-The difference between ->pm.freeze() and the corresponding ->pm.suspend() (and
+-similarly for the "noirq" variants) is that the former should avoid preparing
+-devices to trigger system wakeup events and putting devices into low power
+-states, although they generally have to save the values of device registers
+-so that it's possible to restore them during system resume.
+-
+-Second, after the system image has been created, the functionality of devices
+-has to be restored so that the image can be saved.  That is similar to resuming
+-devices after the system has been woken up from the standby or memory sleep
+-state, which is described below, and causes the following device notifications
+-to be issued:
+-
+-   1	bus->pm.thaw_noirq(dev), if implemented; may call the device driver's
+-	->pm.thaw_noirq() method, depending on the bus type in question.
+-
+-   2	bus->pm.thaw(dev), if implemented; usually calls the device driver's
+-	->pm.thaw() method.
+-
+-   3	type->pm.thaw(dev), if implemented; may call the device driver's
+-	->pm.thaw() method if not called by the bus type or class.
+-
+-   4	class->pm.thaw(dev), if implemented; may call the device driver's
+-	->pm.thaw() method if not called by the bus type or device type.
+-
+-   5	bus->pm.complete(dev), if implemented; may call the device driver's
+-	->pm.complete() method.
+-
+-Generally, the role of the ->pm.thaw() methods (including the "noirq" variants)
+-is to bring the device back to the fully functional state, so that it may be
+-used for saving the image, if necessary.  The role of bus->pm.complete() is to
+-reverse whatever bus->pm.prepare() did (likewise for the analogous device driver
+-callbacks).
+-
+-After the image has been saved, the devices need to be prepared for putting the
+-system into the low power state.  That is analogous to suspending them before
+-putting the system into the standby or memory sleep state and involves the
+-following device notifications:
+-
+-   1	bus->pm.prepare(dev).
+-
+-   2	class->pm.poweroff(dev), if implemented; may invoke the device driver's
+-   	->pm.poweroff() method if not called by the bus type or device type.
+-
+-   3	type->pm.poweroff(dev), if implemented; may invoke the device driver's
+-   	->pm.poweroff() method if not called by the bus type or device class.
+-
+-   4	bus->pm.poweroff(dev), if implemented; usually calls the device driver's
+-   	->pm.poweroff() method (if not called by the device class or type).
+-
+-   5	bus->pm.poweroff_noirq(dev), if implemented; may call the device
+-	driver's ->pm.poweroff_noirq() method, depending on the bus type
+-	in question.
+-
+-The difference between ->pm.poweroff() and the corresponding ->pm.suspend() (and
+-analogously for the "noirq" variants) is that the former need not save the
+-device's registers.  Still, they should prepare the device for triggering
+-system wakeup events if necessary and finally put it into the appropriate low
+-power state.
+-
+-
+-Device Low Power (suspend) States
+----------------------------------
+-Device low-power states aren't standard.  One device might only handle
+-"on" and "off, while another might support a dozen different versions of
+-"on" (how many engines are active?), plus a state that gets back to "on"
+-faster than from a full "off".
+-
+-Some busses define rules about what different suspend states mean.  PCI
+-gives one example:  after the suspend sequence completes, a non-legacy
+-PCI device may not perform DMA or issue IRQs, and any wakeup events it
+-issues would be issued through the PME# bus signal.  Plus, there are
+-several PCI-standard device states, some of which are optional.
+-
+-In contrast, integrated system-on-chip processors often use IRQs as the
+-wakeup event sources (so drivers would call enable_irq_wake) and might
+-be able to treat DMA completion as a wakeup event (sometimes DMA can stay
+-active too, it'd only be the CPU and some peripherals that sleep).
+-
+-Some details here may be platform-specific.  Systems may have devices that
+-can be fully active in certain sleep states, such as an LCD display that's
+-refreshed using DMA while most of the system is sleeping lightly ... and
+-its frame buffer might even be updated by a DSP or other non-Linux CPU while
+-the Linux control processor stays idle.
+-
+-Moreover, the specific actions taken may depend on the target system state.
+-One target system state might allow a given device to be very operational;
+-another might require a hard shut down with re-initialization on resume.
+-And two different target systems might use the same device in different
+-ways; the aforementioned LCD might be active in one product's "standby",
+-but a different product using the same SOC might work differently.
++If any of these callbacks returns an error, the system won't enter the desired
++low-power state.  Instead the PM core will unwind its actions by resuming all
++the devices that were suspended.
+ 
+ 
+-Resuming Devices
+-----------------
+-Resuming is done in multiple phases, much like suspending, with all
+-devices processing each phase's calls before the next phase begins.
++Leaving System Suspend
++----------------------
++When resuming from standby or memory sleep, the phases are:
+ 
+-Again, however, different callbacks are used depending on whether the system is
+-waking up from the standby or memory sleep state ("suspend-to-RAM") or from
+-hibernation ("suspend-to-disk").
++		resume_noirq, resume, complete.
+ 
+-If the system is waking up from the standby or memory sleep state, the phases
+-are seen by driver notifications issued in this order:
+-
+-   1	bus->pm.resume_noirq(dev) is called, if implemented.  It may call the
+-	device driver's ->pm.resume_noirq() method, depending on the bus type in
+-	question.
+-
+-	The role of this method is to perform actions that need to be performed
+-	before device drivers' interrupt handlers are allowed to be invoked.  If
+-	the given bus type permits devices to share interrupt vectors, like PCI,
+-	this method should bring the device and its driver into a state in which
+-	the driver can recognize if the device is the source of incoming
+-	interrupts, if any, and handle them correctly.
++    1.	The resume_noirq callback methods should perform any actions needed
++	before the driver's interrupt handlers are invoked.  This generally
++	means undoing the actions of the suspend_noirq phase.  If the bus type
++	permits devices to share interrupt vectors, like PCI, the method should
++	bring the device and its driver into a state in which the driver can
++	recognize if the device is the source of incoming interrupts, if any,
++	and handle them correctly.
+ 
+ 	For example, the PCI bus type's ->pm.resume_noirq() puts the device into
+-	the full power state (D0 in the PCI terminology) and restores the
+-	standard configuration registers of the device.  Then, it calls the
++	the full-power state (D0 in the PCI terminology) and restores the
++	standard configuration registers of the device.  Then it calls the
+ 	device driver's ->pm.resume_noirq() method to perform device-specific
+-	actions needed at this stage of resume.
+-
+-   2	bus->pm.resume(dev) is called, if implemented.  It usually calls the
+-	device driver's ->pm.resume() method.
+-
+-	This call should generally bring the the device back to the working
+-	state, so that it can do I/O as requested after the call has returned.
+-	However, it may be more convenient to use the device class or device
+-	type ->pm.resume() for this purpose, in which case the bus type's
+-	->pm.resume() method need not be implemented at all.
+-
+-   3	type->pm.resume(dev) is called, if implemented.  It may invoke the
+-	device driver's ->pm.resume() method, unless class->pm.resume(dev) or
+-	bus->pm.resume() does that.
+-
+-	For devices that are not associated with any bus type or device class
+-	this method plays the role of bus->pm.resume().
+-
+-   4	class->pm.resume(dev) is called, if implemented.  It may invoke the
+-	device driver's ->pm.resume() method, unless bus->pm.resume(dev) or
+-	type->pm.resume() does that.
+-
+-	For devices that are not associated with any bus type or device type
+-	this method plays the role of bus->pm.resume().
++	actions.
+ 
+-   5	bus->pm.complete(dev) is called, if implemented.  It is supposed to
+-	invoke the device driver's ->pm.complete() method.
++    2.	The resume methods should bring the the device back to its operating
++	state, so that it can perform normal I/O.  This generally involves
++	undoing the actions of the suspend phase.
+ 
+-	The role of this method is to reverse whatever bus->pm.prepare(dev)
+-	(or the driver's ->pm.prepare()) did during suspend, if necessary.
++    3.	The complete phase uses only a bus callback.  The method should undo the
++	actions of the prepare phase.  Note, however, that new children may be
++	registered below the device as soon as the resume callbacks occur; it's
++	not necessary to wait until the complete phase.
+ 
+-At the end of those phases, drivers should normally be as functional as
+-they were before suspending:  I/O can be performed using DMA and IRQs, and
+-the relevant clocks are gated on.  In principle the device need not be
+-"fully on"; it might be in a runtime lowpower/suspend state during suspend and
+-the resume callbacks may try to restore that state, but that need not be
+-desirable from the user's point of view.  In fact, there are multiple reasons
+-why it's better to always put devices into the "fully working" state in the
+-system sleep resume callbacks and they are discussed in more detail in
+-Documentation/power/runtime_pm.txt.
++At the end of these phases, drivers should be as functional as they were before
++suspending: I/O can be performed using DMA and IRQs, and the relevant clocks are
++gated on.  Even if the device was in a low-power state before the system sleep
++because of runtime power management, afterwards it should be back in its
++full-power state.  There are multiple reasons why it's best to do this; they are
++discussed in more detail in Documentation/power/runtime_pm.txt.
+ 
+ However, the details here may again be platform-specific.  For example,
+ some systems support multiple "run" states, and the mode in effect at
+@@ -502,103 +376,156 @@ the suspend was carried out, but that can't be guaranteed (in fact, it ususally
+ is not the case).
+ 
+ Drivers must also be prepared to notice that the device has been removed
+-while the system was powered off, whenever that's physically possible.
++while the system was powered down, whenever that's physically possible.
+ PCMCIA, MMC, USB, Firewire, SCSI, and even IDE are common examples of busses
+ where common Linux platforms will see such removal.  Details of how drivers
+ will notice and handle such removals are currently bus-specific, and often
+ involve a separate thread.
+ 
++These callbacks may return an error value, but the PM core will ignore such
++errors since there's nothing it can do about them other than printing them in
++the system log.
+ 
+-Resume From Hibernation
+------------------------
++
++Entering Hibernation
++--------------------
++Hibernating the system is more complicated than putting it into the standby or
++memory sleep state, because it involves creating and saving a system image.
++Therefore there are more phases for hibernation, with a different set of
++callbacks.  These phases always run after tasks have been frozen and memory has
++been freed.
++
++The general procedure for hibernation is to quiesce all devices (freeze), create
++an image of the system memory while everything is stable, reactivate all
++devices (thaw), write the image to permanent storage, and finally shut down the
++system (poweroff).  The phases used to accomplish this are:
++
++	prepare, freeze, freeze_noirq, thaw_noirq, thaw, complete,
++	prepare, poweroff, poweroff_noirq
++
++    1.	The prepare phase is discussed in the "Entering System Suspend" section
++	above.
++
++    2.	The freeze methods should quiesce the device so that it doesn't generate
++	IRQs or DMA, and they may need to save the values of device registers.
++	However the device does not have to be put in a low-power state, and to
++	save time it's best not to do so.  Also, the device should not be
++	prepared to generate wakeup events.
++
++    3.	The freeze_noirq phase is analogous to the suspend_noirq phase discussed
++	above, except again that the device should not be put in a low-power
++	state and should not be allowed to generate wakeup events.
++
++At this point the system image is created.  All devices should be inactive and
++the contents of memory should remain undisturbed while this happens, so that the
++image forms an atomic snapshot of the system state.
++
++    4.	The thaw_noirq phase is analogous to the resume_noirq phase discussed
++	above.  The main difference is that its methods can assume the device is
++	in the same state as at the end of the freeze_noirq phase.
++
++    5.	The thaw phase is analogous to the resume phase discussed above.  Its
++	methods should bring the device back to an operating state, so that it
++	can be used for saving the image if necessary.
++
++    6.	The complete phase is discussed in the "Leaving System Suspend" section
++	above.
++
++At this point the system image is saved, and the devices then need to be
++prepared for the upcoming system shutdown.  This is much like suspending them
++before putting the system into the standby or memory sleep state, and the phases
++are similar.
++
++    7.	The prepare phase is discussed above.
++
++    8.	The poweroff phase is analogous to the suspend phase.
++
++    9.	The poweroff_noirq phase is analogous to the suspend_noirq phase.
++
++The poweroff and poweroff_noirq callbacks should do essentially the same things
++as the suspend and suspend_noirq callbacks.  The only notable difference is that
++they need not store the device register values, because the registers should
++already have been stored during the freeze or freeze_noirq phases.
++
++
++Leaving Hibernation
++-------------------
+ Resuming from hibernation is, again, more complicated than resuming from a sleep
+ state in which the contents of main memory are preserved, because it requires
+ a system image to be loaded into memory and the pre-hibernation memory contents
+ to be restored before control can be passed back to the image kernel.
+ 
+-In principle, the image might be loaded into memory and the pre-hibernation
+-memory contents might be restored by the boot loader.  For this purpose,
+-however, the boot loader would need to know the image kernel's entry point and
+-there's no protocol defined for passing that information to boot loaders.  As
+-a workaround, the boot loader loads a fresh instance of the kernel, called the
+-boot kernel, into memory and passes control to it in a usual way.  Then, the
+-boot kernel reads the hibernation image, restores the pre-hibernation memory
+-contents and passes control to the image kernel.  Thus, in fact, two different
+-kernels are involved in resuming from hibernation and in general they are not
+-only different because they play different roles in this operation.  Actually,
+-the boot kernel may be completely different from the image kernel.  Not only
+-the configuration of it, but also the version of it may be different.
+-The consequences of this are important to device drivers and their subsystems
+-(bus types, device classes and device types) too.
+-
+-Namely, to be able to load the hibernation image into memory, the boot kernel
+-needs to include at least the subset of device drivers allowing it to access the
+-storage medium containing the image, although it generally doesn't need to
+-include all of the drivers included into the image kernel.  After the image has
+-been loaded the devices handled by those drivers need to be prepared for passing
+-control back to the image kernel.  This is very similar to the preparation of
+-devices for creating a hibernation image described above.  In fact, it is done
+-in the same way, with the help of the ->pm.prepare(), ->pm.freeze() and
+-->pm.freeze_noirq() callbacks, but only for device drivers included in the boot
+-kernel (whose versions may generally be different from the versions of the
+-analogous drivers from the image kernel).
++Although in principle, the image might be loaded into memory and the
++pre-hibernation memory contents restored by the boot loader, in practice this
++can't be done because boot loaders aren't smart enough and there is no
++established protocol for passing the necessary information.  So instead, the
++boot loader loads a fresh instance of the kernel, called the boot kernel, into
++memory and passes control to it in the usual way.  Then the boot kernel reads
++the system image, restores the pre-hibernation memory contents, and passes
++control to the image kernel.  Thus two different kernels are involved in
++resuming from hibernation.  In fact, the boot kernel may be completely different
++from the image kernel: a different configuration and even a different version.
++This has important consequences for device drivers and their subsystems.
++
++To be able to load the system image into memory, the boot kernel needs to
++include at least a subset of device drivers allowing it to access the storage
++medium containing the image, although it doesn't need to include all of the
++drivers present in the image kernel.  After the image has been loaded, the
++devices managed by the boot kernel need to be prepared for passing control back
++to the image kernel.  This is very similar to the initial steps involved in
++creating a system image, and it is accomplished in the same way, using prepare,
++freeze, and freeze_noirq phases.  However the devices affected by these phases
++are only those having drivers in the boot kernel; other devices will still be in
++whatever state the boot loader left them.
+ 
+ Should the restoration of the pre-hibernation memory contents fail, the boot
+-kernel would carry out the procedure of "thawing" devices described above, using
+-the ->pm.thaw_noirq(), ->pm.thaw(), and ->pm.complete() callbacks provided by
+-subsystems and device drivers.  This, however, is a very rare condition.  Most
+-often the pre-hibernation memory contents are restored successfully and control
+-is passed to the image kernel that is now responsible for bringing the system
+-back to the working state.
++kernel would go through the "thawing" procedure described above, using the
++thaw_noirq, thaw, and complete phases, and then continue running normally.  This
++happens only rarely.  Most often the pre-hibernation memory contents are
++restored successfully and control is passed to the image kernel, which then
++becomes responsible for bringing the system back to the working state.
+ 
+-To achieve this goal, among other things, the image kernel restores the
+-pre-hibernation functionality of devices.  This operation is analogous to the
+-resuming of devices after waking up from the memory sleep state, although it
+-involves different device notifications which are the following:
++To achieve this, the image kernel must restore the devices' pre-hibernation
++functionality.  The operation is much like waking up from the memory sleep
++state, although it involves different phases:
+ 
+-   1	bus->pm.restore_noirq(dev), if implemented; may call the device driver's
+-	->pm.restore_noirq() method, depending on the bus type in question.
++	restore_noirq, restore, complete
+ 
+-   2	bus->pm.restore(dev), if implemented; usually calls the device driver's
+-	->pm.restore() method.
++    1.	The restore_noirq phase is analogous to the resume_noirq phase.
+ 
+-   3	type->pm.restore(dev), if implemented; may call the device driver's
+-	->pm.restore() method if not called by the bus type or class.
++    2.	The restore phase is analogous to the resume phase.
+ 
+-   4	class->pm.restore(dev), if implemented; may call the device driver's
+-	->pm.restore() method if not called by the bus type or device type.
++    3.	The complete phase is discussed above.
+ 
+-   5	bus->pm.complete(dev), if implemented; may call the device driver's
+-	->pm.complete() method.
+-
+-The roles of the ->pm.restore_noirq() and ->pm.restore() callbacks are analogous
+-to the roles of the corresponding resume callbacks, but they must assume that
+-the device may have been accessed before by the boot kernel.  Consequently, the
+-state of the device before they are called may be different from the state of it
+-right prior to calling the resume callbacks.  That difference usually doesn't
+-matter, so the majority of device drivers can set their resume and restore
+-callback pointers to the same routine.  Nevertheless, different callback
+-pointers are used in case there is a situation where it actually matters.
++The main difference from resume[_noirq] is that restore[_noirq] must assume the
++device has been accessed and reconfigured by the boot loader or the boot kernel.
++Consequently the state of the device may be different from the state remembered
++from the freeze and freeze_noirq phases.  The device may even need to be reset
++and completely re-initialized.  In many cases this difference doesn't matter, so
++the resume[_noirq] and restore[_norq] method pointers can be set to the same
++routines.  Nevertheless, different callback pointers are used in case there is a
++situation where it actually matters.
+ 
+ 
+ System Devices
+ --------------
+-System devices follow a slightly different API, which can be found in
++System devices (sysdevs) follow a slightly different API, which can be found in
+ 
+ 	include/linux/sysdev.h
+ 	drivers/base/sys.c
+ 
+-System devices will only be suspended with interrupts disabled, and after
+-all other devices have been suspended.  On resume, they will be resumed
+-before any other devices, and also with interrupts disabled.
++System devices will be suspended with interrupts disabled, and after all other
++devices have been suspended.  On resume, they will be resumed before any other
++devices, and also with interrupts disabled.  These things occur in special
++"sysdev_driver" phases, which affect only system devices.
+ 
+-That is, when the non-boot CPUs are all offline and IRQs are disabled on the
+-remaining online CPU, then the sysdev_driver.suspend() phase is carried out, and
+-the system enters a sleep state (or hibernation image is created).  During
+-resume (or after the image has been created) the sysdev_driver.resume() phase
+-is carried out, IRQs are enabled on the only online CPU, the non-boot CPUs are
+-enabled and that is followed by the "early resume" phase (in which the "noirq"
+-callbacks provided by subsystems and device drivers are invoked).
++Thus, after the suspend_noirq (or freeze_noirq or poweroff_noirq) phase, when
++the non-boot CPUs are all offline and IRQs are disabled on the remaining online
++CPU, then a sysdev_driver.suspend phase is carried out, and the system enters a
++sleep state (or a system image is created).  During resume (or after the image
++has been created or loaded) a sysdev_driver.resume phase is carried out, IRQs
++are enabled on the only online CPU, the non-boot CPUs are enabled, and the
++resume_noirq (or thaw_noirq or restore_noirq) phase begins.
+ 
+ Code to actually enter and exit the system-wide low power state sometimes
+ involves hardware details that are only known to the boot firmware, and
+@@ -606,18 +533,47 @@ may leave a CPU running software (from SRAM or flash memory) that monitors
+ the system and manages its wakeup sequence.
+ 
+ 
++Device Low Power (suspend) States
++---------------------------------
++Device low-power states aren't standard.  One device might only handle
++"on" and "off, while another might support a dozen different versions of
++"on" (how many engines are active?), plus a state that gets back to "on"
++faster than from a full "off".
++
++Some busses define rules about what different suspend states mean.  PCI
++gives one example:  after the suspend sequence completes, a non-legacy
++PCI device may not perform DMA or issue IRQs, and any wakeup events it
++issues would be issued through the PME# bus signal.  Plus, there are
++several PCI-standard device states, some of which are optional.
++
++In contrast, integrated system-on-chip processors often use IRQs as the
++wakeup event sources (so drivers would call enable_irq_wake) and might
++be able to treat DMA completion as a wakeup event (sometimes DMA can stay
++active too, it'd only be the CPU and some peripherals that sleep).
++
++Some details here may be platform-specific.  Systems may have devices that
++can be fully active in certain sleep states, such as an LCD display that's
++refreshed using DMA while most of the system is sleeping lightly ... and
++its frame buffer might even be updated by a DSP or other non-Linux CPU while
++the Linux control processor stays idle.
++
++Moreover, the specific actions taken may depend on the target system state.
++One target system state might allow a given device to be very operational;
++another might require a hard shut down with re-initialization on resume.
++And two different target systems might use the same device in different
++ways; the aforementioned LCD might be active in one product's "standby",
++but a different product using the same SOC might work differently.
++
++
+ Power Management Notifiers
+ --------------------------
+-As stated in Documentation/power/notifiers.txt, there are some operations that
+-cannot be carried out by the power management callbacks discussed above, because
+-carrying them out at these points would be too late or too early.  To handle
+-these cases subsystems and device drivers may register power management
+-notifiers that are called before tasks are frozen and after they have been
+-thawed.
+-
+-Generally speaking, the PM notifiers are suitable for performing actions that
+-either require user space to be available, or at least won't interfere with user
+-space in a wrong way.
++There are some operations that cannot be carried out by the power management
++callbacks discussed above, because the callbacks occur too late or too early.
++To handle these cases, subsystems and device drivers may register power
++management notifiers that are called before tasks are frozen and after they have
++been thawed.  Generally speaking, the PM notifiers are suitable for performing
++actions that either require user space to be available, or at least won't
++interfere with user space.
+ 
+ For details refer to Documentation/power/notifiers.txt.
+ 
+@@ -629,24 +585,23 @@ running. This feature is useful for devices that are not being used, and
+ can offer significant power savings on a running system.  These devices
+ often support a range of runtime power states, which might use names such
+ as "off", "sleep", "idle", "active", and so on.  Those states will in some
+-cases (like PCI) be partially constrained by a bus the device uses, and will
++cases (like PCI) be partially constrained by the bus the device uses, and will
+ usually include hardware states that are also used in system sleep states.
+ 
+-Note, however, that a system-wide power transition can be started while some
+-devices are in low power states due to the runtime power management.  The system
+-sleep PM callbacks should generally recognize such situations and react to them
+-appropriately, but the recommended actions to be taken in that cases are
+-subsystem-specific.
+-
+-In some cases the decision may be made at the subsystem level while in some
+-other cases the device driver may be left to decide.  In some cases it may be
+-desirable to leave a suspended device in that state during system-wide power
+-transition, but in some other cases the device ought to be put back into the
+-full power state, for example to be configured for system wakeup or so that its
+-system wakeup capability can be disabled.  That all depends on the hardware
+-and the design of the subsystem and device driver in question.
+-
+-During system-wide resume from a sleep state it's better to put devices into
+-the full power state, as explained in Documentation/power/runtime_pm.txt.  Refer
+-to that document for more information regarding this particular issue as well as
++A system-wide power transition can be started while some devices are in low
++power states due to runtime power management.  The system sleep PM callbacks
++should recognize such situations and react to them appropriately, but the
++necessary actions are subsystem-specific.
++
++In some cases the decision may be made at the subsystem level while in other
++cases the device driver may be left to decide.  In some cases it may be
++desirable to leave a suspended device in that state during a system-wide power
++transition, but in other cases the device must be put back into the full-power
++state temporarily, for example so that its system wakeup capability can be
++disabled.  This all depends on the hardware and the design of the subsystem and
++device driver in question.
++
++During system-wide resume from a sleep state it's best to put devices into the
++full-power state, as explained in Documentation/power/runtime_pm.txt.  Refer to
++that document for more information regarding this particular issue as well as
+ for information on the device runtime power management framework in general.

commit 240c7337a4cd3d91b196c5ef97ad461b3a22fa09
+Author: Alan Stern 
+Date:   Tue Mar 23 00:50:07 2010 +0100
+
+    PM: Allow runtime_suspend methods to call pm_schedule_suspend()
+    
+    This patch (as1361) changes the runtime PM interface slightly; it
+    allows suspend requests to be scheduled while the runtime_suspend
+    method is running.  If the method succeeds then the scheduled request
+    is cancelled, whereas if the method fails then an idle notification is
+    sent only if no request was scheduled.
+    
+    Being able to schedule suspend requests from within a runtime_suspend
+    method is useful for drivers that need to test for idleness and
+    suspend the device all while holding a single spinlock, or for drivers
+    that want to check for idleness by polling.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
+index 626dd147b75f..b0ec0e9f27e9 100644
+--- a/drivers/base/power/runtime.c
++++ b/drivers/base/power/runtime.c
+@@ -229,14 +229,16 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq)
+ 
+ 	if (retval) {
+ 		dev->power.runtime_status = RPM_ACTIVE;
+-		pm_runtime_cancel_pending(dev);
+-
+ 		if (retval == -EAGAIN || retval == -EBUSY) {
+-			notify = true;
++			if (dev->power.timer_expires == 0)
++				notify = true;
+ 			dev->power.runtime_error = 0;
++		} else {
++			pm_runtime_cancel_pending(dev);
+ 		}
+ 	} else {
+ 		dev->power.runtime_status = RPM_SUSPENDED;
++		pm_runtime_deactivate_timer(dev);
+ 
+ 		if (dev->parent) {
+ 			parent = dev->parent;
+@@ -659,8 +661,6 @@ int pm_schedule_suspend(struct device *dev, unsigned int delay)
+ 
+ 	if (dev->power.runtime_status == RPM_SUSPENDED)
+ 		retval = 1;
+-	else if (dev->power.runtime_status == RPM_SUSPENDING)
+-		retval = -EINPROGRESS;
+ 	else if (atomic_read(&dev->power.usage_count) > 0
+ 	    || dev->power.disable_depth > 0)
+ 		retval = -EAGAIN;

commit fde4e2f73208b8f34f123791e39c0cb6bc74b32a
+Author: Alan Stern 
+Date:   Fri May 7 10:41:10 2010 -0400
+
+    HID: fix suspend crash by moving initializations earlier
+    
+    Although the usbhid driver allocates its usbhid structure in the probe
+    routine, several critical fields in that structure don't get
+    initialized until usbhid_start().  However if report descriptor
+    parsing fails then usbhid_start() is never called.  This leads to
+    problems during system suspend -- the system will freeze.
+    
+    This patch (as1378) fixes the bug by moving the initialization
+    statements up into usbhid_probe().
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Bruno Prémont 
+    Tested-By: Bruno Prémont 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index 56d06cd8075b..7b85b696fdab 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -999,13 +999,6 @@ static int usbhid_start(struct hid_device *hid)
+ 		}
+ 	}
+ 
+-	init_waitqueue_head(&usbhid->wait);
+-	INIT_WORK(&usbhid->reset_work, hid_reset);
+-	INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues);
+-	setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
+-
+-	spin_lock_init(&usbhid->lock);
+-
+ 	usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
+ 	if (!usbhid->urbctrl) {
+ 		ret = -ENOMEM;
+@@ -1179,6 +1172,12 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
+ 	usbhid->intf = intf;
+ 	usbhid->ifnum = interface->desc.bInterfaceNumber;
+ 
++	init_waitqueue_head(&usbhid->wait);
++	INIT_WORK(&usbhid->reset_work, hid_reset);
++	INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues);
++	setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
++	spin_lock_init(&usbhid->lock);
++
+ 	ret = hid_add_device(hid);
+ 	if (ret) {
+ 		if (ret != -ENODEV)

commit fcf7d2141f4a363a4a8454c4a0f26bb69e766c5f
+Author: Alan Stern 
+Date:   Tue Apr 20 10:37:57 2010 -0400
+
+    USB: OHCI: don't look at the root hub to get the number of ports
+    
+    This patch (as1371) fixes a small bug in ohci-hcd.  The HCD already
+    knows how many ports the controller has; there's no need to go looking
+    at the root hub's usb_device structure to find out.  Especially since
+    the root hub's maxchild value is set correctly only while the root hub
+    is bound to the hub driver.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index 32bbce9718f0..65cac8cc8921 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -697,7 +697,7 @@ static int ohci_hub_control (
+ 	u16		wLength
+ ) {
+ 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
+-	int		ports = hcd_to_bus (hcd)->root_hub->maxchild;
++	int		ports = ohci->num_ports;
+ 	u32		temp;
+ 	int		retval = 0;
+ 

commit 62f9cfa3ece58268b3e92ca59c23b175f86205aa
+Author: Alan Stern 
+Date:   Tue Apr 20 10:40:59 2010 -0400
+
+    USB: don't choose configs with no interfaces
+    
+    This patch (as1372) fixes a bug in the routine that chooses the
+    default configuration to install when a new USB device is detected.
+    The algorithm is supposed to look for a config whose first interface
+    is for a non-vendor-specific class.  But the way it's currently
+    written, it will also accept a config with no interfaces at all, which
+    is not very useful.  (Believe it or not, such things do exist.)
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Andrew Victor 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
+index bdf87a8414a1..2c95153c0f24 100644
+--- a/drivers/usb/core/generic.c
++++ b/drivers/usb/core/generic.c
+@@ -120,7 +120,7 @@ int usb_choose_configuration(struct usb_device *udev)
+ 		 * than a vendor-specific driver. */
+ 		else if (udev->descriptor.bDeviceClass !=
+ 						USB_CLASS_VENDOR_SPEC &&
+-				(!desc || desc->bInterfaceClass !=
++				(desc && desc->bInterfaceClass !=
+ 						USB_CLASS_VENDOR_SPEC)) {
+ 			best = c;
+ 			break;

commit eef6a7d5c2f38adadab8240fabf43730fe796482
+Author: Alan Stern 
+Date:   Fri Feb 12 17:39:21 2010 +0900
+
+    workqueue: warn about flush_scheduled_work()
+    
+    This patch (as1319) adds kerneldoc and a pointed warning to
+    flush_scheduled_work().
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Tejun Heo 
+
+diff --git a/kernel/workqueue.c b/kernel/workqueue.c
+index 5bfb213984b2..0225fea89340 100644
+--- a/kernel/workqueue.c
++++ b/kernel/workqueue.c
+@@ -845,6 +845,30 @@ int schedule_on_each_cpu(work_func_t func)
+ 	return 0;
+ }
+ 
++/**
++ * flush_scheduled_work - ensure that any scheduled work has run to completion.
++ *
++ * Forces execution of the kernel-global workqueue and blocks until its
++ * completion.
++ *
++ * Think twice before calling this function!  It's very easy to get into
++ * trouble if you don't take great care.  Either of the following situations
++ * will lead to deadlock:
++ *
++ *	One of the work items currently on the workqueue needs to acquire
++ *	a lock held by your code or its caller.
++ *
++ *	Your code is running in the context of a work routine.
++ *
++ * They will be detected by lockdep when they occur, but the first might not
++ * occur very often.  It depends on what work items are on the workqueue and
++ * what locks they need, which you have no control over.
++ *
++ * In most situations flushing the entire workqueue is overkill; you merely
++ * need to know that a particular work item isn't queued and isn't running.
++ * In such cases you should use cancel_delayed_work_sync() or
++ * cancel_work_sync() instead.
++ */
+ void flush_scheduled_work(void)
+ {
+ 	flush_workqueue(keventd_wq);

commit 571dc79d62a163fd043de47d7d39bae58831e81e
+Author: Alan Stern 
+Date:   Fri Apr 9 16:03:43 2010 -0400
+
+    USB: put claimed interfaces in the "suspended" state
+    
+    This patch (as1370) fixes a bug in the USB runtime power management
+    code.  When a driver claims an interface, it doesn't expect to need to
+    call usb_autopm_get_interface() or usb_autopm_put_interface() for
+    runtime PM to work.  Runtime PM can be controlled by the driver's
+    primary interface; the additional interfaces it claims shouldn't
+    interfere.  As things stand, the claimed interfaces will prevent the
+    device from autosuspending.
+    
+    To fix this problem, the patch sets interfaces to the suspended state
+    when they are claimed.
+    
+    Also, although in theory this shouldn't matter, the patch changes the
+    suspend code so that interfaces are suspended in reverse order from
+    detection and resuming.  This is how the PM core works, and we ought
+    to use the same approach.
+    
+    Signed-off-by: Alan Stern 
+    Debugged-and-tested-by: Dominik Brodowski 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 64b91d6c5a5d..2f3dc4cdf79b 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -301,7 +301,7 @@ static int usb_probe_interface(struct device *dev)
+ 
+ 	intf->condition = USB_INTERFACE_BINDING;
+ 
+-	/* Bound interfaces are initially active.  They are
++	/* Probed interfaces are initially active.  They are
+ 	 * runtime-PM-enabled only if the driver has autosuspend support.
+ 	 * They are sensitive to their children's power states.
+ 	 */
+@@ -437,11 +437,11 @@ int usb_driver_claim_interface(struct usb_driver *driver,
+ 
+ 	iface->condition = USB_INTERFACE_BOUND;
+ 
+-	/* Bound interfaces are initially active.  They are
++	/* Claimed interfaces are initially inactive (suspended).  They are
+ 	 * runtime-PM-enabled only if the driver has autosuspend support.
+ 	 * They are sensitive to their children's power states.
+ 	 */
+-	pm_runtime_set_active(dev);
++	pm_runtime_set_suspended(dev);
+ 	pm_suspend_ignore_children(dev, false);
+ 	if (driver->supports_autosuspend)
+ 		pm_runtime_enable(dev);
+@@ -1170,7 +1170,7 @@ static int usb_resume_interface(struct usb_device *udev,
+ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ {
+ 	int			status = 0;
+-	int			i = 0;
++	int			i = 0, n = 0;
+ 	struct usb_interface	*intf;
+ 
+ 	if (udev->state == USB_STATE_NOTATTACHED ||
+@@ -1179,7 +1179,8 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 
+ 	/* Suspend all the interfaces and then udev itself */
+ 	if (udev->actconfig) {
+-		for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
++		n = udev->actconfig->desc.bNumInterfaces;
++		for (i = n - 1; i >= 0; --i) {
+ 			intf = udev->actconfig->interface[i];
+ 			status = usb_suspend_interface(udev, intf, msg);
+ 			if (status != 0)
+@@ -1192,7 +1193,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 	/* If the suspend failed, resume interfaces that did get suspended */
+ 	if (status != 0) {
+ 		msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME);
+-		while (--i >= 0) {
++		while (++i < n) {
+ 			intf = udev->actconfig->interface[i];
+ 			usb_resume_interface(udev, intf, msg, 0);
+ 		}

commit 0e5f231bc16ff9910882fa5b9d64d80e7691cfab
+Author: Alan Stern 
+Date:   Thu Apr 8 16:56:37 2010 -0400
+
+    USB: EHCI: defer reclamation of siTDs
+    
+    This patch (as1369) fixes a problem in ehci-hcd.  Some controllers
+    occasionally run into trouble when the driver reclaims siTDs too
+    quickly.  This can happen while streaming audio; it causes the
+    controller to crash.
+    
+    The patch changes siTD reclamation to work the same way as iTD
+    reclamation: Completed siTDs are stored on a list and not reused until
+    at least one frame has passed.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Nate Case 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 207e7a85aeb0..13ead00aecd5 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -543,6 +543,7 @@ static int ehci_init(struct usb_hcd *hcd)
+ 	 */
+ 	ehci->periodic_size = DEFAULT_I_TDPS;
+ 	INIT_LIST_HEAD(&ehci->cached_itd_list);
++	INIT_LIST_HEAD(&ehci->cached_sitd_list);
+ 	if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0)
+ 		return retval;
+ 
+diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
+index aeda96e0af67..1f3f01eacaf0 100644
+--- a/drivers/usb/host/ehci-mem.c
++++ b/drivers/usb/host/ehci-mem.c
+@@ -136,7 +136,7 @@ static inline void qh_put (struct ehci_qh *qh)
+ 
+ static void ehci_mem_cleanup (struct ehci_hcd *ehci)
+ {
+-	free_cached_itd_list(ehci);
++	free_cached_lists(ehci);
+ 	if (ehci->async)
+ 		qh_put (ehci->async);
+ 	ehci->async = NULL;
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index a0aaaaff2560..805ec633a652 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -510,7 +510,7 @@ static int disable_periodic (struct ehci_hcd *ehci)
+ 	ehci_writel(ehci, cmd, &ehci->regs->command);
+ 	/* posted write ... */
+ 
+-	free_cached_itd_list(ehci);
++	free_cached_lists(ehci);
+ 
+ 	ehci->next_uframe = -1;
+ 	return 0;
+@@ -2139,13 +2139,27 @@ sitd_complete (
+ 			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
+ 	}
+ 	iso_stream_put (ehci, stream);
+-	/* OK to recycle this SITD now that its completion callback ran. */
++
+ done:
+ 	sitd->urb = NULL;
+-	sitd->stream = NULL;
+-	list_move(&sitd->sitd_list, &stream->free_list);
+-	iso_stream_put(ehci, stream);
+-
++	if (ehci->clock_frame != sitd->frame) {
++		/* OK to recycle this SITD now. */
++		sitd->stream = NULL;
++		list_move(&sitd->sitd_list, &stream->free_list);
++		iso_stream_put(ehci, stream);
++	} else {
++		/* HW might remember this SITD, so we can't recycle it yet.
++		 * Move it to a safe place until a new frame starts.
++		 */
++		list_move(&sitd->sitd_list, &ehci->cached_sitd_list);
++		if (stream->refcount == 2) {
++			/* If iso_stream_put() were called here, stream
++			 * would be freed.  Instead, just prevent reuse.
++			 */
++			stream->ep->hcpriv = NULL;
++			stream->ep = NULL;
++		}
++	}
+ 	return retval;
+ }
+ 
+@@ -2211,9 +2225,10 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-static void free_cached_itd_list(struct ehci_hcd *ehci)
++static void free_cached_lists(struct ehci_hcd *ehci)
+ {
+ 	struct ehci_itd *itd, *n;
++	struct ehci_sitd *sitd, *sn;
+ 
+ 	list_for_each_entry_safe(itd, n, &ehci->cached_itd_list, itd_list) {
+ 		struct ehci_iso_stream	*stream = itd->stream;
+@@ -2221,6 +2236,13 @@ static void free_cached_itd_list(struct ehci_hcd *ehci)
+ 		list_move(&itd->itd_list, &stream->free_list);
+ 		iso_stream_put(ehci, stream);
+ 	}
++
++	list_for_each_entry_safe(sitd, sn, &ehci->cached_sitd_list, sitd_list) {
++		struct ehci_iso_stream	*stream = sitd->stream;
++		sitd->stream = NULL;
++		list_move(&sitd->sitd_list, &stream->free_list);
++		iso_stream_put(ehci, stream);
++	}
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -2247,7 +2269,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 		clock_frame = -1;
+ 	}
+ 	if (ehci->clock_frame != clock_frame) {
+-		free_cached_itd_list(ehci);
++		free_cached_lists(ehci);
+ 		ehci->clock_frame = clock_frame;
+ 	}
+ 	clock %= mod;
+@@ -2414,7 +2436,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 			clock = now;
+ 			clock_frame = clock >> 3;
+ 			if (ehci->clock_frame != clock_frame) {
+-				free_cached_itd_list(ehci);
++				free_cached_lists(ehci);
+ 				ehci->clock_frame = clock_frame;
+ 			}
+ 		} else {
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index b1dce96dd621..556c0b48f3ab 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -87,8 +87,9 @@ struct ehci_hcd {			/* one per controller */
+ 	int			next_uframe;	/* scan periodic, start here */
+ 	unsigned		periodic_sched;	/* periodic activity count */
+ 
+-	/* list of itds completed while clock_frame was still active */
++	/* list of itds & sitds completed while clock_frame was still active */
+ 	struct list_head	cached_itd_list;
++	struct list_head	cached_sitd_list;
+ 	unsigned		clock_frame;
+ 
+ 	/* per root hub port */
+@@ -195,7 +196,7 @@ timer_action_done (struct ehci_hcd *ehci, enum ehci_timer_action action)
+ 	clear_bit (action, &ehci->actions);
+ }
+ 
+-static void free_cached_itd_list(struct ehci_hcd *ehci);
++static void free_cached_lists(struct ehci_hcd *ehci);
+ 
+ /*-------------------------------------------------------------------------*/
+ 

commit 5f677f1d45b2bf08085bbba7394392dfa586fa8e
+Author: Alan Stern 
+Date:   Fri Apr 2 13:20:11 2010 -0400
+
+    USB: fix remote wakeup settings during system sleep
+    
+    This patch (as1363) changes the way USB remote wakeup is handled
+    during system sleeps.  It won't be enabled unless an interface driver
+    specifically needs it.  Also, it won't be enabled during the FREEZE or
+    QUIESCE phases of hibernation, when the system doesn't respond to
+    wakeup events anyway.  Finally, if the device is already
+    runtime-suspended with remote wakeup enabled, but wakeup is supposed
+    to be disabled for the system sleep, the device gets woken up so that
+    it can be suspended again with the proper wakeup setting.
+    
+    This will fix problems people have reported with certain USB webcams
+    that generate wakeup requests when they shouldn't, and as a result
+    cause system suspends to fail.  See
+    
+            https://bugs.launchpad.net/ubuntu/+source/linux/+bug/515109
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Erik Andrén 
+    CC: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 6a3b5cae3a6e..64b91d6c5a5d 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1263,13 +1263,47 @@ static int usb_resume_both(struct usb_device *udev, pm_message_t msg)
+ 	return status;
+ }
+ 
++static void choose_wakeup(struct usb_device *udev, pm_message_t msg)
++{
++	int			w, i;
++	struct usb_interface	*intf;
++
++	/* Remote wakeup is needed only when we actually go to sleep.
++	 * For things like FREEZE and QUIESCE, if the device is already
++	 * autosuspended then its current wakeup setting is okay.
++	 */
++	if (msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_QUIESCE) {
++		if (udev->state != USB_STATE_SUSPENDED)
++			udev->do_remote_wakeup = 0;
++		return;
++	}
++
++	/* If remote wakeup is permitted, see whether any interface drivers
++	 * actually want it.
++	 */
++	w = 0;
++	if (device_may_wakeup(&udev->dev) && udev->actconfig) {
++		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
++			intf = udev->actconfig->interface[i];
++			w |= intf->needs_remote_wakeup;
++		}
++	}
++
++	/* If the device is autosuspended with the wrong wakeup setting,
++	 * autoresume now so the setting can be changed.
++	 */
++	if (udev->state == USB_STATE_SUSPENDED && w != udev->do_remote_wakeup)
++		pm_runtime_resume(&udev->dev);
++	udev->do_remote_wakeup = w;
++}
++
+ /* The device lock is held by the PM core */
+ int usb_suspend(struct device *dev, pm_message_t msg)
+ {
+ 	struct usb_device	*udev = to_usb_device(dev);
+ 
+ 	do_unbind_rebind(udev, DO_UNBIND);
+-	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
++	choose_wakeup(udev, msg);
+ 	return usb_suspend_both(udev, msg);
+ }
+ 

commit 12fb8c1574d7d0c262d2f4c667047889c4f27ebe
+Author: Alan Stern 
+Date:   Thu Mar 18 15:41:22 2010 -0400
+
+    [SCSI] don't kfree an initialized struct device
+    
+    This patch (as1359) fixes a bug in scsi_alloc_target().  After a
+    device structure has been initialized (and especially after its name
+    has been set), it must not be freed directly.  One has to call
+    put_device() instead.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+index 38518b088073..c992ecf4e372 100644
+--- a/drivers/scsi/scsi_scan.c
++++ b/drivers/scsi/scsi_scan.c
+@@ -459,8 +459,7 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
+ 	found_target->reap_ref++;
+ 	spin_unlock_irqrestore(shost->host_lock, flags);
+ 	if (found_target->state != STARGET_DEL) {
+-		put_device(parent);
+-		kfree(starget);
++		put_device(dev);
+ 		return found_target;
+ 	}
+ 	/* Unfortunately, we found a dying target; need to

commit 1821438a9b6a8454281ec2e151014709f641d2d5
+Author: Alan Stern 
+Date:   Thu Mar 18 15:41:11 2010 -0400
+
+    [SCSI] don't reap targets upon device_add failure
+    
+    This patch (as1358) fixes a bug in the error pathway of
+    scsi_target_add().  If registration fails, the target should not be
+    reaped.  The reaping occurs later, when scanning is finished and all
+    the child devices are removed.  The current code leaves an unbalanced
+    value in starget->reap_ref.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
+index 429c9b73e3e4..838a0db8ea1f 100644
+--- a/drivers/scsi/scsi_sysfs.c
++++ b/drivers/scsi/scsi_sysfs.c
+@@ -853,9 +853,6 @@ static int scsi_target_add(struct scsi_target *starget)
+ 	error = device_add(&starget->dev);
+ 	if (error) {
+ 		dev_err(&starget->dev, "target device_add failed, error %d\n", error);
+-		get_device(&starget->dev);
+-		scsi_target_reap(starget);
+-		put_device(&starget->dev);
+ 		return error;
+ 	}
+ 	transport_add_device(&starget->dev);

commit 3d61510f4ecacfe47c75c0eb51c0659dfa77fb1b
+Author: Alan Stern 
+Date:   Fri Apr 2 13:21:58 2010 -0400
+
+    HID: usbhid: enable remote wakeup for keyboards
+    
+    This patch (as1365) enables remote wakeup by default for USB keyboard
+    devices.  Keyboards in general are supposed to be wakeup devices, but
+    the correct place to enable it depends on the device's bus; no single
+    approach will work for all keyboard devices.  In particular, this
+    covers only USB keyboards (and then only those supporting the boot
+    protocol).
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index 56d06cd8075b..9cd61a52e9e3 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -1026,12 +1026,15 @@ static int usbhid_start(struct hid_device *hid)
+ 	/* Some keyboards don't work until their LEDs have been set.
+ 	 * Since BIOSes do set the LEDs, it must be safe for any device
+ 	 * that supports the keyboard boot protocol.
++	 * In addition, enable remote wakeup by default for all keyboard
++	 * devices supporting the boot protocol.
+ 	 */
+ 	if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT &&
+ 			interface->desc.bInterfaceProtocol ==
+-				USB_INTERFACE_PROTOCOL_KEYBOARD)
++				USB_INTERFACE_PROTOCOL_KEYBOARD) {
+ 		usbhid_set_leds(hid);
+-
++		device_set_wakeup_enable(&dev->dev, 1);
++	}
+ 	return 0;
+ 
+ fail:
+diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c
+index f843443ba5c3..b2fd0b00de92 100644
+--- a/drivers/hid/usbhid/usbkbd.c
++++ b/drivers/hid/usbhid/usbkbd.c
+@@ -313,6 +313,7 @@ static int usb_kbd_probe(struct usb_interface *iface,
+ 		goto fail2;
+ 
+ 	usb_set_intfdata(iface, kbd);
++	device_set_wakeup_enable(&dev->dev, 1);
+ 	return 0;
+ 
+ fail2:	

commit 7152b592593b9d48b33f8997b1dfd6df9143f7ec
+Author: Alan Stern 
+Date:   Sat Mar 6 15:04:03 2010 -0500
+
+    USB: fix usbfs regression
+    
+    This patch (as1352) fixes a bug in the way isochronous input data is
+    returned to userspace for usbfs transfers.  The entire buffer must be
+    copied, not just the first actual_length bytes, because the individual
+    packets will be discontiguous if any of them are short.
+    
+    Reported-by: Markus Rechberger 
+    Signed-off-by: Alan Stern 
+    CC: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index e909ff7b9094..3466fdc5bb11 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -1207,6 +1207,13 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 			free_async(as);
+ 			return -ENOMEM;
+ 		}
++		/* Isochronous input data may end up being discontiguous
++		 * if some of the packets are short.  Clear the buffer so
++		 * that the gaps don't leak kernel data to userspace.
++		 */
++		if (is_in && uurb->type == USBDEVFS_URB_TYPE_ISO)
++			memset(as->urb->transfer_buffer, 0,
++					uurb->buffer_length);
+ 	}
+ 	as->urb->dev = ps->dev;
+ 	as->urb->pipe = (uurb->type << 30) |
+@@ -1345,10 +1352,14 @@ static int processcompl(struct async *as, void __user * __user *arg)
+ 	void __user *addr = as->userurb;
+ 	unsigned int i;
+ 
+-	if (as->userbuffer && urb->actual_length)
+-		if (copy_to_user(as->userbuffer, urb->transfer_buffer,
+-				 urb->actual_length))
++	if (as->userbuffer && urb->actual_length) {
++		if (urb->number_of_packets > 0)		/* Isochronous */
++			i = urb->transfer_buffer_length;
++		else					/* Non-Isoc */
++			i = urb->actual_length;
++		if (copy_to_user(as->userbuffer, urb->transfer_buffer, i))
+ 			goto err_out;
++	}
+ 	if (put_user(as->status, &userurb->status))
+ 		goto err_out;
+ 	if (put_user(urb->actual_length, &userurb->actual_length))

commit 3e6e15a862a0bc20128497bbdc54254cdec21835
+Author: Alan Stern 
+Date:   Mon Mar 8 23:42:46 2010 -0800
+
+    Input: enable remote wakeup for PNP i8042 keyboard ports
+    
+    This patch (as1355) enables remote wakeup by default on PNP i8042
+    keyboard ports.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Dmitry Torokhov 
+
+diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
+index 2a5982e532f8..3696cab40598 100644
+--- a/drivers/input/serio/i8042-x86ia64io.h
++++ b/drivers/input/serio/i8042-x86ia64io.h
+@@ -624,6 +624,9 @@ static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id *
+ 		strlcat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name));
+ 	}
+ 
++	/* Keyboard ports are always supposed to be wakeup-enabled */
++	device_set_wakeup_enable(&dev->dev, true);
++
+ 	i8042_pnp_kbd_devices++;
+ 	return 0;
+ }

commit 1f87158e44e79e62c8250f278c225ce4ab695f4b
+Author: Alan Stern 
+Date:   Wed Feb 17 10:05:47 2010 -0500
+
+    USB: remove references to port->port.count from the serial drivers
+    
+    This patch (as1344) removes references to port->port.count from the
+    USB serial drivers.  Now that serial ports are properly reference
+    counted, port.count checking is unnecessary and incorrect.  Drivers
+    should assume that the port is in use from the time the open method
+    runs until the close method is called.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
+index 2cbdc8f230b8..365db1097bfd 100644
+--- a/drivers/usb/serial/aircable.c
++++ b/drivers/usb/serial/aircable.c
+@@ -468,10 +468,6 @@ static void aircable_read_bulk_callback(struct urb *urb)
+ 
+ 	if (status) {
+ 		dbg("%s - urb status = %d", __func__, status);
+-		if (!port->port.count) {
+-			dbg("%s - port is closed, exiting.", __func__);
+-			return;
+-		}
+ 		if (status == -EPROTO) {
+ 			dbg("%s - caught -EPROTO, resubmitting the urb",
+ 			    __func__);
+@@ -530,23 +526,19 @@ static void aircable_read_bulk_callback(struct urb *urb)
+ 	}
+ 	tty_kref_put(tty);
+ 
+-	/* Schedule the next read _if_ we are still open */
+-	if (port->port.count) {
+-		usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+-				  usb_rcvbulkpipe(port->serial->dev,
+-					  port->bulk_in_endpointAddress),
+-				  port->read_urb->transfer_buffer,
+-				  port->read_urb->transfer_buffer_length,
+-				  aircable_read_bulk_callback, port);
+-
+-		result = usb_submit_urb(urb, GFP_ATOMIC);
+-		if (result)
+-			dev_err(&urb->dev->dev,
+-				"%s - failed resubmitting read urb, error %d\n",
+-				__func__, result);
+-	}
+-
+-	return;
++	/* Schedule the next read */
++	usb_fill_bulk_urb(port->read_urb, port->serial->dev,
++			  usb_rcvbulkpipe(port->serial->dev,
++				  port->bulk_in_endpointAddress),
++			  port->read_urb->transfer_buffer,
++			  port->read_urb->transfer_buffer_length,
++			  aircable_read_bulk_callback, port);
++
++	result = usb_submit_urb(urb, GFP_ATOMIC);
++	if (result && result != -EPERM)
++		dev_err(&urb->dev->dev,
++			"%s - failed resubmitting read urb, error %d\n",
++			__func__, result);
+ }
+ 
+ /* Based on ftdi_sio.c throttle */
+diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
+index 3a5d57f89dee..baf74b44e6ed 100644
+--- a/drivers/usb/serial/cypress_m8.c
++++ b/drivers/usb/serial/cypress_m8.c
+@@ -1321,9 +1321,9 @@ static void cypress_read_int_callback(struct urb *urb)
+ continue_read:
+ 	tty_kref_put(tty);
+ 
+-	/* Continue trying to always read... unless the port has closed. */
++	/* Continue trying to always read */
+ 
+-	if (port->port.count > 0 && priv->comm_is_ok) {
++	if (priv->comm_is_ok) {
+ 		usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev,
+ 				usb_rcvintpipe(port->serial->dev,
+ 					port->interrupt_in_endpointAddress),
+@@ -1332,7 +1332,7 @@ static void cypress_read_int_callback(struct urb *urb)
+ 				cypress_read_int_callback, port,
+ 				priv->read_urb_interval);
+ 		result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+-		if (result) {
++		if (result && result != -EPERM) {
+ 			dev_err(&urb->dev->dev, "%s - failed resubmitting "
+ 					"read urb, error %d\n", __func__,
+ 					result);
+diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
+index 381722858424..68b0aa5e516c 100644
+--- a/drivers/usb/serial/digi_acceleport.c
++++ b/drivers/usb/serial/digi_acceleport.c
+@@ -1262,10 +1262,10 @@ static void digi_write_bulk_callback(struct urb *urb)
+ 		return;
+ 	}
+ 
+-	/* try to send any buffered data on this port, if it is open */
++	/* try to send any buffered data on this port */
+ 	spin_lock(&priv->dp_port_lock);
+ 	priv->dp_write_urb_in_use = 0;
+-	if (port->port.count && priv->dp_out_buf_len > 0) {
++	if (priv->dp_out_buf_len > 0) {
+ 		*((unsigned char *)(port->write_urb->transfer_buffer))
+ 			= (unsigned char)DIGI_CMD_SEND_DATA;
+ 		*((unsigned char *)(port->write_urb->transfer_buffer) + 1)
+@@ -1288,7 +1288,7 @@ static void digi_write_bulk_callback(struct urb *urb)
+ 	schedule_work(&priv->dp_wakeup_work);
+ 
+ 	spin_unlock(&priv->dp_port_lock);
+-	if (ret)
++	if (ret && ret != -EPERM)
+ 		dev_err(&port->dev,
+ 			"%s: usb_submit_urb failed, ret=%d, port=%d\n",
+ 			__func__, ret, priv->dp_port_num);
+@@ -1353,8 +1353,7 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port)
+ 	struct digi_port *priv = usb_get_serial_port_data(port);
+ 	struct ktermios not_termios;
+ 
+-	dbg("digi_open: TOP: port=%d, open_count=%d",
+-		priv->dp_port_num, port->port.count);
++	dbg("digi_open: TOP: port=%d", priv->dp_port_num);
+ 
+ 	/* be sure the device is started up */
+ 	if (digi_startup_device(port->serial) != 0)
+@@ -1393,8 +1392,7 @@ static void digi_close(struct usb_serial_port *port)
+ 	unsigned char buf[32];
+ 	struct digi_port *priv = usb_get_serial_port_data(port);
+ 
+-	dbg("digi_close: TOP: port=%d, open_count=%d",
+-		priv->dp_port_num, port->port.count);
++	dbg("digi_close: TOP: port=%d", priv->dp_port_num);
+ 
+ 	mutex_lock(&port->serial->disc_mutex);
+ 	/* if disconnected, just clear flags */
+@@ -1629,7 +1627,7 @@ static void digi_read_bulk_callback(struct urb *urb)
+ 	/* continue read */
+ 	urb->dev = port->serial->dev;
+ 	ret = usb_submit_urb(urb, GFP_ATOMIC);
+-	if (ret != 0) {
++	if (ret != 0 && ret != -EPERM) {
+ 		dev_err(&port->dev,
+ 			"%s: failed resubmitting urb, ret=%d, port=%d\n",
+ 			__func__, ret, priv->dp_port_num);
+@@ -1662,7 +1660,7 @@ static int digi_read_inb_callback(struct urb *urb)
+ 
+ 	/* do not process callbacks on closed ports */
+ 	/* but do continue the read chain */
+-	if (port->port.count == 0)
++	if (urb->status == -ENOENT)
+ 		return 0;
+ 
+ 	/* short/multiple packet check */
+@@ -1767,8 +1765,7 @@ static int digi_read_oob_callback(struct urb *urb)
+ 
+ 		tty = tty_port_tty_get(&port->port);
+ 		rts = 0;
+-		if (port->port.count)
+-			rts = tty->termios->c_cflag & CRTSCTS;
++		rts = tty->termios->c_cflag & CRTSCTS;
+ 		
+ 		if (opcode == DIGI_CMD_READ_INPUT_SIGNALS) {
+ 			spin_lock(&priv->dp_port_lock);
+diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
+index 5288203d883f..89fac36684c5 100644
+--- a/drivers/usb/serial/generic.c
++++ b/drivers/usb/serial/generic.c
+@@ -20,6 +20,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ static int debug;
+ 
+@@ -585,7 +586,7 @@ int usb_serial_generic_resume(struct usb_serial *serial)
+ 
+ 	for (i = 0; i < serial->num_ports; i++) {
+ 		port = serial->port[i];
+-		if (!port->port.count)
++		if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags))
+ 			continue;
+ 
+ 		if (port->read_urb) {
+diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
+index c3e5d506aead..4a0f51974232 100644
+--- a/drivers/usb/serial/ir-usb.c
++++ b/drivers/usb/serial/ir-usb.c
+@@ -445,11 +445,6 @@ static void ir_read_bulk_callback(struct urb *urb)
+ 
+ 	dbg("%s - port %d", __func__, port->number);
+ 
+-	if (!port->port.count) {
+-		dbg("%s - port closed.", __func__);
+-		return;
+-	}
+-
+ 	switch (status) {
+ 	case 0: /* Successful */
+ 		/*
+diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
+index f8c4b07033ff..297163c3c610 100644
+--- a/drivers/usb/serial/keyspan.c
++++ b/drivers/usb/serial/keyspan.c
+@@ -464,13 +464,9 @@ static void	usa26_indat_callback(struct urb *urb)
+ 
+ 	/* Resubmit urb so we continue receiving */
+ 	urb->dev = port->serial->dev;
+-	if (port->port.count) {
+-		err = usb_submit_urb(urb, GFP_ATOMIC);
+-		if (err != 0)
+-			dbg("%s - resubmit read urb failed. (%d)",
+-					__func__, err);
+-	}
+-	return;
++	err = usb_submit_urb(urb, GFP_ATOMIC);
++	if (err != 0)
++		dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ }
+ 
+ /* Outdat handling is common for all devices */
+@@ -483,8 +479,7 @@ static void	usa2x_outdat_callback(struct urb *urb)
+ 	p_priv = usb_get_serial_port_data(port);
+ 	dbg("%s - urb %d", __func__, urb == p_priv->out_urbs[1]);
+ 
+-	if (port->port.count)
+-		usb_serial_port_softint(port);
++	usb_serial_port_softint(port);
+ }
+ 
+ static void	usa26_inack_callback(struct urb *urb)
+@@ -615,12 +610,10 @@ static void usa28_indat_callback(struct urb *urb)
+ 
+ 		/* Resubmit urb so we continue receiving */
+ 		urb->dev = port->serial->dev;
+-		if (port->port.count) {
+-			err = usb_submit_urb(urb, GFP_ATOMIC);
+-			if (err != 0)
+-				dbg("%s - resubmit read urb failed. (%d)",
+-								__func__, err);
+-		}
++		err = usb_submit_urb(urb, GFP_ATOMIC);
++		if (err != 0)
++			dbg("%s - resubmit read urb failed. (%d)",
++							__func__, err);
+ 		p_priv->in_flip ^= 1;
+ 
+ 		urb = p_priv->in_urbs[p_priv->in_flip];
+@@ -856,12 +849,9 @@ static void	usa49_indat_callback(struct urb *urb)
+ 
+ 	/* Resubmit urb so we continue receiving */
+ 	urb->dev = port->serial->dev;
+-	if (port->port.count) {
+-		err = usb_submit_urb(urb, GFP_ATOMIC);
+-		if (err != 0)
+-			dbg("%s - resubmit read urb failed. (%d)",
+-							__func__, err);
+-	}
++	err = usb_submit_urb(urb, GFP_ATOMIC);
++	if (err != 0)
++		dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ }
+ 
+ static void usa49wg_indat_callback(struct urb *urb)
+@@ -904,11 +894,7 @@ static void usa49wg_indat_callback(struct urb *urb)
+ 				/* no error on any byte */
+ 				i++;
+ 				for (x = 1; x < len ; ++x)
+-					if (port->port.count)
+-						tty_insert_flip_char(tty,
+-								data[i++], 0);
+-					else
+-						i++;
++					tty_insert_flip_char(tty, data[i++], 0);
+ 			} else {
+ 				/*
+ 				 * some bytes had errors, every byte has status
+@@ -922,14 +908,12 @@ static void usa49wg_indat_callback(struct urb *urb)
+ 					if (stat & RXERROR_PARITY)
+ 						flag |= TTY_PARITY;
+ 					/* XXX should handle break (0x10) */
+-					if (port->port.count)
+-						tty_insert_flip_char(tty,
++					tty_insert_flip_char(tty,
+ 							data[i+1], flag);
+ 					i += 2;
+ 				}
+ 			}
+-			if (port->port.count)
+-				tty_flip_buffer_push(tty);
++			tty_flip_buffer_push(tty);
+ 			tty_kref_put(tty);
+ 		}
+ 	}
+@@ -1013,13 +997,9 @@ static void usa90_indat_callback(struct urb *urb)
+ 
+ 	/* Resubmit urb so we continue receiving */
+ 	urb->dev = port->serial->dev;
+-	if (port->port.count) {
+-		err = usb_submit_urb(urb, GFP_ATOMIC);
+-		if (err != 0)
+-			dbg("%s - resubmit read urb failed. (%d)",
+-							__func__, err);
+-	}
+-	return;
++	err = usb_submit_urb(urb, GFP_ATOMIC);
++	if (err != 0)
++		dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ }
+ 
+ 
+@@ -2418,8 +2398,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
+ 		msg.portEnabled = 0;
+ 	/* Sending intermediate configs */
+ 	else {
+-		if (port->port.count)
+-			msg.portEnabled = 1;
++		msg.portEnabled = 1;
+ 		msg.txBreak = (p_priv->break_on);
+ 	}
+ 
+diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
+index 68c7457a98ae..db0541c5df79 100644
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -971,9 +971,9 @@ static void option_indat_callback(struct urb *urb)
+ 		tty_kref_put(tty);
+ 
+ 		/* Resubmit urb so we continue receiving */
+-		if (port->port.count && status != -ESHUTDOWN) {
++		if (status != -ESHUTDOWN) {
+ 			err = usb_submit_urb(urb, GFP_ATOMIC);
+-			if (err)
++			if (err && err != -EPERM)
+ 				printk(KERN_ERR "%s: resubmit read urb failed. "
+ 					"(%d)", __func__, err);
+ 			else
+diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
+index 839733431832..deeacdea05db 100644
+--- a/drivers/usb/serial/oti6858.c
++++ b/drivers/usb/serial/oti6858.c
+@@ -585,9 +585,6 @@ static int oti6858_open(struct tty_struct *tty, struct usb_serial_port *port)
+ 	usb_clear_halt(serial->dev, port->write_urb->pipe);
+ 	usb_clear_halt(serial->dev, port->read_urb->pipe);
+ 
+-	if (port->port.count != 1)
+-		return 0;
+-
+ 	buf = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL);
+ 	if (buf == NULL) {
+ 		dev_err(&port->dev, "%s(): out of memory!\n", __func__);
+@@ -934,10 +931,6 @@ static void oti6858_read_bulk_callback(struct urb *urb)
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+ 	if (status != 0) {
+-		if (!port->port.count) {
+-			dbg("%s(): port is closed, exiting", __func__);
+-			return;
+-		}
+ 		/*
+ 		if (status == -EPROTO) {
+ 			* PL2303 mysteriously fails with -EPROTO reschedule
+@@ -961,14 +954,12 @@ static void oti6858_read_bulk_callback(struct urb *urb)
+ 	}
+ 	tty_kref_put(tty);
+ 
+-	/* schedule the interrupt urb if we are still open */
+-	if (port->port.count != 0) {
+-		port->interrupt_in_urb->dev = port->serial->dev;
+-		result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+-		if (result != 0) {
+-			dev_err(&port->dev, "%s(): usb_submit_urb() failed,"
+-					" error %d\n", __func__, result);
+-		}
++	/* schedule the interrupt urb */
++	port->interrupt_in_urb->dev = port->serial->dev;
++	result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
++	if (result != 0 && result != -EPERM) {
++		dev_err(&port->dev, "%s(): usb_submit_urb() failed,"
++				" error %d\n", __func__, result);
+ 	}
+ }
+ 
+diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
+index a3e5a56dc066..571dcf182866 100644
+--- a/drivers/usb/serial/pl2303.c
++++ b/drivers/usb/serial/pl2303.c
+@@ -1071,10 +1071,6 @@ static void pl2303_read_bulk_callback(struct urb *urb)
+ 
+ 	if (status) {
+ 		dbg("%s - urb status = %d", __func__, status);
+-		if (!port->port.count) {
+-			dbg("%s - port is closed, exiting.", __func__);
+-			return;
+-		}
+ 		if (status == -EPROTO) {
+ 			/* PL2303 mysteriously fails with -EPROTO reschedule
+ 			 * the read */
+@@ -1107,15 +1103,11 @@ static void pl2303_read_bulk_callback(struct urb *urb)
+ 	}
+ 	tty_kref_put(tty);
+ 	/* Schedule the next read _if_ we are still open */
+-	if (port->port.count) {
+-		urb->dev = port->serial->dev;
+-		result = usb_submit_urb(urb, GFP_ATOMIC);
+-		if (result)
+-			dev_err(&urb->dev->dev, "%s - failed resubmitting"
+-				" read urb, error %d\n", __func__, result);
+-	}
+-
+-	return;
++	urb->dev = port->serial->dev;
++	result = usb_submit_urb(urb, GFP_ATOMIC);
++	if (result && result != -EPERM)
++		dev_err(&urb->dev->dev, "%s - failed resubmitting"
++			" read urb, error %d\n", __func__, result);
+ }
+ 
+ static void pl2303_write_bulk_callback(struct urb *urb)
+diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
+index c012e51665bd..34e6f894cba9 100644
+--- a/drivers/usb/serial/sierra.c
++++ b/drivers/usb/serial/sierra.c
+@@ -610,10 +610,10 @@ static void sierra_indat_callback(struct urb *urb)
+ 	}
+ 
+ 	/* Resubmit urb so we continue receiving */
+-	if (port->port.count && status != -ESHUTDOWN && status != -EPERM) {
++	if (status != -ESHUTDOWN && status != -EPERM) {
+ 		usb_mark_last_busy(port->serial->dev);
+ 		err = usb_submit_urb(urb, GFP_ATOMIC);
+-		if (err)
++		if (err && err != -EPERM)
+ 			dev_err(&port->dev, "resubmit read urb failed."
+ 				"(%d)\n", err);
+ 	}
+@@ -672,11 +672,11 @@ static void sierra_instat_callback(struct urb *urb)
+ 		dev_dbg(&port->dev, "%s: error %d\n", __func__, status);
+ 
+ 	/* Resubmit urb so we continue receiving IRQ data */
+-	if (port->port.count && status != -ESHUTDOWN && status != -ENOENT) {
++	if (status != -ESHUTDOWN && status != -ENOENT) {
+ 		usb_mark_last_busy(serial->dev);
+ 		urb->dev = serial->dev;
+ 		err = usb_submit_urb(urb, GFP_ATOMIC);
+-		if (err)
++		if (err && err != -EPERM)
+ 			dev_err(&port->dev, "%s: resubmit intr urb "
+ 				"failed. (%d)\n", __func__, err);
+ 	}
+diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
+index cf508e26f1c6..5d39191e7244 100644
+--- a/drivers/usb/serial/spcp8x5.c
++++ b/drivers/usb/serial/spcp8x5.c
+@@ -686,8 +686,6 @@ static void spcp8x5_read_bulk_callback(struct urb *urb)
+ 
+ 	/* check the urb status */
+ 	if (result) {
+-		if (!port->port.count)
+-			return;
+ 		if (result == -EPROTO) {
+ 			/* spcp8x5 mysteriously fails with -EPROTO */
+ 			/* reschedule the read */
+@@ -734,16 +732,11 @@ static void spcp8x5_read_bulk_callback(struct urb *urb)
+ 	}
+ 	tty_kref_put(tty);
+ 
+-	/* Schedule the next read _if_ we are still open */
+-	if (port->port.count) {
+-		urb->dev = port->serial->dev;
+-		result = usb_submit_urb(urb , GFP_ATOMIC);
+-		if (result)
+-			dev_dbg(&port->dev, "failed submitting read urb %d\n",
+-				result);
+-	}
+-
+-	return;
++	/* Schedule the next read */
++	urb->dev = port->serial->dev;
++	result = usb_submit_urb(urb , GFP_ATOMIC);
++	if (result)
++		dev_dbg(&port->dev, "failed submitting read urb %d\n", result);
+ }
+ 
+ /* get data from ring buffer and then write to usb bus */

commit cd780694920fbf869b23c8afb0bd083e7b0448c7
+Author: Alan Stern 
+Date:   Thu Feb 25 13:19:37 2010 -0500
+
+    USB: fix the idProduct value for USB-3.0 root hubs
+    
+    This patch (as1346) changes the idProduct value for USB-3.0 root hubs
+    from 0x0002 (which we already use for USB-2.0 root hubs) to 0x0003.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Sarah Sharp 
+    CC: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index b07ba051118d..2f8cedda8007 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -142,7 +142,7 @@ static const u8 usb3_rh_dev_descriptor[18] = {
+ 	0x09,       /*  __u8  bMaxPacketSize0; 2^9 = 512 Bytes */
+ 
+ 	0x6b, 0x1d, /*  __le16 idVendor; Linux Foundation */
+-	0x02, 0x00, /*  __le16 idProduct; device 0x0002 */
++	0x03, 0x00, /*  __le16 idProduct; device 0x0003 */
+ 	KERNEL_VER, KERNEL_REL, /*  __le16 bcdDevice */
+ 
+ 	0x03,       /*  __u8  iManufacturer; */

commit 49d6271b85a3e18062eaf4d6f8d899abe00a7725
+Author: Alan Stern 
+Date:   Fri Feb 26 11:49:39 2010 -0500
+
+    usb-storage: use max_hw_sectors instead of max_sectors
+    
+    This patch (as1347) makes some adjustments to the way usb-storage
+    handles the request-queue parameters.
+    
+    USB host controllers are able to handle arbitrarily long
+    scatter-gather lists, since they are limited only by main memory and
+    not by the controller hardware.  Hence the sg_tablesize field in the
+    host template can be increased to the maximum value.
+    
+    Drivers like usb-storage aren't supposed to touch the queue's
+    max_sectors parameter; instead they are supposed to use the
+    max_hw_sectors value.  Accordingly, the patch replaces calls of
+    queue_max_sectors() with calls of queue_max_hw_sectors().  Oddly
+    enough, the blk_queue_max_sectors() routine is nevertheless still
+    appropriate.
+    
+    The existing code imposes a limit of SCSI_DEFAULT_MAX_SECTORS (1024)
+    on the values accepted by the max_sectors attribute file.  There's no
+    reason not to accept larger values, so the limit is removed.  (It
+    would be nice to change the file's name to max_hw_sectors, but the old
+    name is already a well-established API.)
+    
+    Signed-off-by: Alan Stern 
+    CC: Matthew Dharm 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index aadc16b5eed7..4cc035562cc2 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -133,7 +133,7 @@ static int slave_configure(struct scsi_device *sdev)
+ 
+ 		if (us->fflags & US_FL_MAX_SECTORS_MIN)
+ 			max_sectors = PAGE_CACHE_SIZE >> 9;
+-		if (queue_max_sectors(sdev->request_queue) > max_sectors)
++		if (queue_max_hw_sectors(sdev->request_queue) > max_sectors)
+ 			blk_queue_max_hw_sectors(sdev->request_queue,
+ 					      max_sectors);
+ 	} else if (sdev->type == TYPE_TAPE) {
+@@ -484,7 +484,7 @@ static ssize_t show_max_sectors(struct device *dev, struct device_attribute *att
+ {
+ 	struct scsi_device *sdev = to_scsi_device(dev);
+ 
+-	return sprintf(buf, "%u\n", queue_max_sectors(sdev->request_queue));
++	return sprintf(buf, "%u\n", queue_max_hw_sectors(sdev->request_queue));
+ }
+ 
+ /* Input routine for the sysfs max_sectors file */
+@@ -494,9 +494,9 @@ static ssize_t store_max_sectors(struct device *dev, struct device_attribute *at
+ 	struct scsi_device *sdev = to_scsi_device(dev);
+ 	unsigned short ms;
+ 
+-	if (sscanf(buf, "%hu", &ms) > 0 && ms <= SCSI_DEFAULT_MAX_SECTORS) {
++	if (sscanf(buf, "%hu", &ms) > 0) {
+ 		blk_queue_max_hw_sectors(sdev->request_queue, ms);
+-		return strlen(buf);
++		return count;
+ 	}
+ 	return -EINVAL;	
+ }
+@@ -539,7 +539,7 @@ struct scsi_host_template usb_stor_host_template = {
+ 	.slave_configure =		slave_configure,
+ 
+ 	/* lots of sg segments can be handled */
+-	.sg_tablesize =			SG_ALL,
++	.sg_tablesize =			SCSI_MAX_SG_CHAIN_SEGMENTS,
+ 
+ 	/* limit the total size of a transfer to 120 KB */
+ 	.max_sectors =                  240,

commit cceffe9348f93188d7811bda95924d4bd3040d0f
+Author: Alan Stern 
+Date:   Mon Feb 8 09:45:12 2010 -0500
+
+    USB: remove debugging message for uevent constructions
+    
+    This patch (as1332) removes an unneeded and annoying debugging message
+    announcing all USB uevent constructions.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 6850ec6576f8..a7037bf81688 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -710,9 +710,6 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
+ {
+ 	struct usb_device *usb_dev;
+ 
+-	/* driver is often null here; dev_dbg() would oops */
+-	pr_debug("usb %s: uevent\n", dev_name(dev));
+-
+ 	if (is_usb_device(dev)) {
+ 		usb_dev = to_usb_device(dev);
+ 	} else if (is_usb_interface(dev)) {
+@@ -724,6 +721,7 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
+ 	}
+ 
+ 	if (usb_dev->devnum < 0) {
++		/* driver is often null here; dev_dbg() would oops */
+ 		pr_debug("usb %s: already deleted?\n", dev_name(dev));
+ 		return -ENODEV;
+ 	}

commit 9bbdf1e0afe771ca7650f9f476769310bee9d8f3
+Author: Alan Stern 
+Date:   Fri Jan 8 12:57:28 2010 -0500
+
+    USB: convert to the runtime PM framework
+    
+    This patch (as1329) converts the USB stack over to the PM core's
+    runtime PM framework.  This involves numerous changes throughout
+    usbcore, especially to hub.c and driver.c.  Perhaps the most notable
+    change is that CONFIG_USB_SUSPEND now depends on CONFIG_PM_RUNTIME
+    instead of CONFIG_PM.
+    
+    Several fields in the usb_device and usb_interface structures are no
+    longer needed.  Some code which used to depend on CONFIG_USB_PM now
+    depends on CONFIG_USB_SUSPEND (requiring some rearrangement of header
+    files).
+    
+    The only visible change in behavior should be that following a system
+    sleep (resume from RAM or resume from hibernation), autosuspended USB
+    devices will be resumed just like everything else.  They won't remain
+    suspended.  But if they aren't in use then they will naturally
+    autosuspend again in a few seconds.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt
+index e3fa189c257a..2790ad48cfc2 100644
+--- a/Documentation/usb/power-management.txt
++++ b/Documentation/usb/power-management.txt
+@@ -2,7 +2,7 @@
+ 
+ 		 Alan Stern 
+ 
+-			    November 10, 2009
++			    December 11, 2009
+ 
+ 
+ 
+@@ -29,9 +29,9 @@ covered to some extent (see Documentation/power/*.txt for more
+ information about system PM).
+ 
+ Note: Dynamic PM support for USB is present only if the kernel was
+-built with CONFIG_USB_SUSPEND enabled.  System PM support is present
+-only if the kernel was built with CONFIG_SUSPEND or CONFIG_HIBERNATION
+-enabled.
++built with CONFIG_USB_SUSPEND enabled (which depends on
++CONFIG_PM_RUNTIME).  System PM support is present only if the kernel
++was built with CONFIG_SUSPEND or CONFIG_HIBERNATION enabled.
+ 
+ 
+ 	What is Remote Wakeup?
+@@ -326,64 +326,63 @@ driver does so by calling these six functions:
+ 	void usb_autopm_get_interface_no_resume(struct usb_interface *intf);
+ 	void usb_autopm_put_interface_no_suspend(struct usb_interface *intf);
+ 
+-The functions work by maintaining a counter in the usb_interface
+-structure.  When intf->pm_usage_count is > 0 then the interface is
+-deemed to be busy, and the kernel will not autosuspend the interface's
+-device.  When intf->pm_usage_count is <= 0 then the interface is
+-considered to be idle, and the kernel may autosuspend the device.
++The functions work by maintaining a usage counter in the
++usb_interface's embedded device structure.  When the counter is > 0
++then the interface is deemed to be busy, and the kernel will not
++autosuspend the interface's device.  When the usage counter is = 0
++then the interface is considered to be idle, and the kernel may
++autosuspend the device.
+ 
+-(There is a similar pm_usage_count field in struct usb_device,
++(There is a similar usage counter field in struct usb_device,
+ associated with the device itself rather than any of its interfaces.
+-This field is used only by the USB core.)
+-
+-Drivers must not modify intf->pm_usage_count directly; its value
+-should be changed only be using the functions listed above.  Drivers
+-are responsible for insuring that the overall change to pm_usage_count
+-during their lifetime balances out to 0 (it may be necessary for the
+-disconnect method to call usb_autopm_put_interface() one or more times
+-to fulfill this requirement).  The first two routines use the PM mutex
+-in struct usb_device for mutual exclusion; drivers using the async
+-routines are responsible for their own synchronization and mutual
+-exclusion.
+-
+-	usb_autopm_get_interface() increments pm_usage_count and
+-	attempts an autoresume if the new value is > 0 and the
+-	device is suspended.
+-
+-	usb_autopm_put_interface() decrements pm_usage_count and
+-	attempts an autosuspend if the new value is <= 0 and the
+-	device isn't suspended.
++This counter is used only by the USB core.)
++
++Drivers need not be concerned about balancing changes to the usage
++counter; the USB core will undo any remaining "get"s when a driver
++is unbound from its interface.  As a corollary, drivers must not call
++any of the usb_autopm_* functions after their diconnect() routine has
++returned.
++
++Drivers using the async routines are responsible for their own
++synchronization and mutual exclusion.
++
++	usb_autopm_get_interface() increments the usage counter and
++	does an autoresume if the device is suspended.  If the
++	autoresume fails, the counter is decremented back.
++
++	usb_autopm_put_interface() decrements the usage counter and
++	attempts an autosuspend if the new value is = 0.
+ 
+ 	usb_autopm_get_interface_async() and
+ 	usb_autopm_put_interface_async() do almost the same things as
+-	their non-async counterparts.  The differences are: they do
+-	not acquire the PM mutex, and they use a workqueue to do their
++	their non-async counterparts.  The big difference is that they
++	use a workqueue to do the resume or suspend part of their
+ 	jobs.  As a result they can be called in an atomic context,
+ 	such as an URB's completion handler, but when they return the
+-	device will not generally not yet be in the desired state.
++	device will generally not yet be in the desired state.
+ 
+ 	usb_autopm_get_interface_no_resume() and
+ 	usb_autopm_put_interface_no_suspend() merely increment or
+-	decrement the pm_usage_count value; they do not attempt to
+-	carry out an autoresume or an autosuspend.  Hence they can be
+-	called in an atomic context.
++	decrement the usage counter; they do not attempt to carry out
++	an autoresume or an autosuspend.  Hence they can be called in
++	an atomic context.
+ 
+-The conventional usage pattern is that a driver calls
++The simplest usage pattern is that a driver calls
+ usb_autopm_get_interface() in its open routine and
+-usb_autopm_put_interface() in its close or release routine.  But
+-other patterns are possible.
++usb_autopm_put_interface() in its close or release routine.  But other
++patterns are possible.
+ 
+ The autosuspend attempts mentioned above will often fail for one
+ reason or another.  For example, the power/level attribute might be
+ set to "on", or another interface in the same device might not be
+ idle.  This is perfectly normal.  If the reason for failure was that
+-the device hasn't been idle for long enough, a delayed workqueue
+-routine is automatically set up to carry out the operation when the
+-autosuspend idle-delay has expired.
++the device hasn't been idle for long enough, a timer is scheduled to
++carry out the operation automatically when the autosuspend idle-delay
++has expired.
+ 
+ Autoresume attempts also can fail, although failure would mean that
+ the device is no longer present or operating properly.  Unlike
+-autosuspend, there's no delay for an autoresume.
++autosuspend, there's no idle-delay for an autoresume.
+ 
+ 
+ 	Other parts of the driver interface
+@@ -413,26 +412,27 @@ though, setting this flag won't cause the kernel to autoresume it.
+ Normally a driver would set this flag in its probe method, at which
+ time the device is guaranteed not to be autosuspended.)
+ 
+-The synchronous usb_autopm_* routines have to run in a sleepable
+-process context; they must not be called from an interrupt handler or
+-while holding a spinlock.  In fact, the entire autosuspend mechanism
+-is not well geared toward interrupt-driven operation.  However there
+-is one thing a driver can do in an interrupt handler:
++If a driver does its I/O asynchronously in interrupt context, it
++should call usb_autopm_get_interface_async() before starting output and
++usb_autopm_put_interface_async() when the output queue drains.  When
++it receives an input event, it should call
+ 
+ 	usb_mark_last_busy(struct usb_device *udev);
+ 
+-This sets udev->last_busy to the current time.  udev->last_busy is the
+-field used for idle-delay calculations; updating it will cause any
+-pending autosuspend to be moved back.  The usb_autopm_* routines will
+-also set the last_busy field to the current time.
+-
+-Calling urb_mark_last_busy() from within an URB completion handler is
+-subject to races: The kernel may have just finished deciding the
+-device has been idle for long enough but not yet gotten around to
+-calling the driver's suspend method.  The driver would have to be
+-responsible for synchronizing its suspend method with its URB
+-completion handler and causing the autosuspend to fail with -EBUSY if
+-an URB had completed too recently.
++in the event handler.  This sets udev->last_busy to the current time.
++udev->last_busy is the field used for idle-delay calculations;
++updating it will cause any pending autosuspend to be moved back.  Most
++of the usb_autopm_* routines will also set the last_busy field to the
++current time.
++
++Asynchronous operation is always subject to races.  For example, a
++driver may call one of the usb_autopm_*_interface_async() routines at
++a time when the core has just finished deciding the device has been
++idle for long enough but not yet gotten around to calling the driver's
++suspend method.  The suspend method must be responsible for
++synchronizing with the output request routine and the URB completion
++handler; it should cause autosuspends to fail with -EBUSY if the
++driver needs to use the device.
+ 
+ External suspend calls should never be allowed to fail in this way,
+ only autosuspend calls.  The driver can tell them apart by checking
+@@ -440,75 +440,23 @@ the PM_EVENT_AUTO bit in the message.event argument to the suspend
+ method; this bit will be set for internal PM events (autosuspend) and
+ clear for external PM events.
+ 
+-Many of the ingredients in the autosuspend framework are oriented
+-towards interfaces: The usb_interface structure contains the
+-pm_usage_cnt field, and the usb_autopm_* routines take an interface
+-pointer as their argument.  But somewhat confusingly, a few of the
+-pieces (i.e., usb_mark_last_busy()) use the usb_device structure
+-instead.  Drivers need to keep this straight; they can call
+-interface_to_usbdev() to find the device structure for a given
+-interface.
+ 
++	Mutual exclusion
++	----------------
+ 
+-	Locking requirements
+-	--------------------
+-
+-All three suspend/resume methods are always called while holding the
+-usb_device's PM mutex.  For external events -- but not necessarily for
+-autosuspend or autoresume -- the device semaphore (udev->dev.sem) will
+-also be held.  This implies that external suspend/resume events are
+-mutually exclusive with calls to probe, disconnect, pre_reset, and
+-post_reset; the USB core guarantees that this is true of internal
+-suspend/resume events as well.
++For external events -- but not necessarily for autosuspend or
++autoresume -- the device semaphore (udev->dev.sem) will be held when a
++suspend or resume method is called.  This implies that external
++suspend/resume events are mutually exclusive with calls to probe,
++disconnect, pre_reset, and post_reset; the USB core guarantees that
++this is true of autosuspend/autoresume events as well.
+ 
+ If a driver wants to block all suspend/resume calls during some
+-critical section, it can simply acquire udev->pm_mutex. Note that
+-calls to resume may be triggered indirectly. Block IO due to memory
+-allocations can make the vm subsystem resume a device. Thus while
+-holding this lock you must not allocate memory with GFP_KERNEL or
+-GFP_NOFS.
+-
+-Alternatively, if the critical section might call some of the
+-usb_autopm_* routines, the driver can avoid deadlock by doing:
+-
+-	down(&udev->dev.sem);
+-	rc = usb_autopm_get_interface(intf);
+-
+-and at the end of the critical section:
+-
+-	if (!rc)
+-		usb_autopm_put_interface(intf);
+-	up(&udev->dev.sem);
+-
+-Holding the device semaphore will block all external PM calls, and the
+-usb_autopm_get_interface() will prevent any internal PM calls, even if
+-it fails.  (Exercise: Why?)
+-
+-The rules for locking order are:
+-
+-	Never acquire any device semaphore while holding any PM mutex.
+-
+-	Never acquire udev->pm_mutex while holding the PM mutex for
+-	a device that isn't a descendant of udev.
+-
+-In other words, PM mutexes should only be acquired going up the device
+-tree, and they should be acquired only after locking all the device
+-semaphores you need to hold.  These rules don't matter to drivers very
+-much; they usually affect just the USB core.
+-
+-Still, drivers do need to be careful.  For example, many drivers use a
+-private mutex to synchronize their normal I/O activities with their
+-disconnect method.  Now if the driver supports autosuspend then it
+-must call usb_autopm_put_interface() from somewhere -- maybe from its
+-close method.  It should make the call while holding the private mutex,
+-since a driver shouldn't call any of the usb_autopm_* functions for an
+-interface from which it has been unbound.
+-
+-But the usb_autpm_* routines always acquire the device's PM mutex, and
+-consequently the locking order has to be: private mutex first, PM
+-mutex second.  Since the suspend method is always called with the PM
+-mutex held, it mustn't try to acquire the private mutex.  It has to
+-synchronize with the driver's I/O activities in some other way.
++critical section, the best way is to lock the device and call
++usb_autopm_get_interface() (and do the reverse at the end of the
++critical section).  Holding the device semaphore will block all
++external PM calls, and the usb_autopm_get_interface() will prevent any
++internal PM calls, even if it fails.  (Exercise: Why?)
+ 
+ 
+ 	Interaction between dynamic PM and system PM
+@@ -517,22 +465,11 @@ synchronize with the driver's I/O activities in some other way.
+ Dynamic power management and system power management can interact in
+ a couple of ways.
+ 
+-Firstly, a device may already be manually suspended or autosuspended
+-when a system suspend occurs.  Since system suspends are supposed to
+-be as transparent as possible, the device should remain suspended
+-following the system resume.  The 2.6.23 kernel obeys this principle
+-for manually suspended devices but not for autosuspended devices; they
+-do get resumed when the system wakes up.  (Presumably they will be
+-autosuspended again after their idle-delay time expires.)  In later
+-kernels this behavior will be fixed.
+-
+-(There is an exception.  If a device would undergo a reset-resume
+-instead of a normal resume, and the device is enabled for remote
+-wakeup, then the reset-resume takes place even if the device was
+-already suspended when the system suspend began.  The justification is
+-that a reset-resume is a kind of remote-wakeup event.  Or to put it
+-another way, a device which needs a reset won't be able to generate
+-normal remote-wakeup signals, so it ought to be resumed immediately.)
++Firstly, a device may already be autosuspended when a system suspend
++occurs.  Since system suspends are supposed to be as transparent as
++possible, the device should remain suspended following the system
++resume.  But this theory may not work out well in practice; over time
++the kernel's behavior in this regard has changed.
+ 
+ Secondly, a dynamic power-management event may occur as a system
+ suspend is underway.  The window for this is short, since system
+diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
+index ad925946f869..97a819c23ef3 100644
+--- a/drivers/usb/core/Kconfig
++++ b/drivers/usb/core/Kconfig
+@@ -91,8 +91,8 @@ config USB_DYNAMIC_MINORS
+ 	  If you are unsure about this, say N here.
+ 
+ config USB_SUSPEND
+-	bool "USB selective suspend/resume and wakeup"
+-	depends on USB && PM
++	bool "USB runtime power management (suspend/resume and wakeup)"
++	depends on USB && PM_RUNTIME
+ 	help
+ 	  If you say Y here, you can use driver calls or the sysfs
+ 	  "power/level" file to suspend or resume individual USB
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 638d54693a1c..6850ec6576f8 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -25,7 +25,7 @@
+ #include 
+ #include 
+ #include 
+-#include 
++#include 
+ #include "hcd.h"
+ #include "usb.h"
+ 
+@@ -221,7 +221,7 @@ static int usb_probe_device(struct device *dev)
+ {
+ 	struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);
+ 	struct usb_device *udev = to_usb_device(dev);
+-	int error = -ENODEV;
++	int error = 0;
+ 
+ 	dev_dbg(dev, "%s\n", __func__);
+ 
+@@ -230,18 +230,23 @@ static int usb_probe_device(struct device *dev)
+ 	/* The device should always appear to be in use
+ 	 * unless the driver suports autosuspend.
+ 	 */
+-	udev->pm_usage_cnt = !(udriver->supports_autosuspend);
++	if (!udriver->supports_autosuspend)
++		error = usb_autoresume_device(udev);
+ 
+-	error = udriver->probe(udev);
++	if (!error)
++		error = udriver->probe(udev);
+ 	return error;
+ }
+ 
+ /* called from driver core with dev locked */
+ static int usb_unbind_device(struct device *dev)
+ {
++	struct usb_device *udev = to_usb_device(dev);
+ 	struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);
+ 
+-	udriver->disconnect(to_usb_device(dev));
++	udriver->disconnect(udev);
++	if (!udriver->supports_autosuspend)
++		usb_autosuspend_device(udev);
+ 	return 0;
+ }
+ 
+@@ -293,17 +298,16 @@ static int usb_probe_interface(struct device *dev)
+ 	if (error)
+ 		return error;
+ 
+-	/* Interface "power state" doesn't correspond to any hardware
+-	 * state whatsoever.  We use it to record when it's bound to
+-	 * a driver that may start I/0:  it's not frozen/quiesced.
+-	 */
+-	mark_active(intf);
+ 	intf->condition = USB_INTERFACE_BINDING;
+ 
+-	/* The interface should always appear to be in use
+-	 * unless the driver suports autosuspend.
++	/* Bound interfaces are initially active.  They are
++	 * runtime-PM-enabled only if the driver has autosuspend support.
++	 * They are sensitive to their children's power states.
+ 	 */
+-	atomic_set(&intf->pm_usage_cnt, !driver->supports_autosuspend);
++	pm_runtime_set_active(dev);
++	pm_suspend_ignore_children(dev, false);
++	if (driver->supports_autosuspend)
++		pm_runtime_enable(dev);
+ 
+ 	/* Carry out a deferred switch to altsetting 0 */
+ 	if (intf->needs_altsetting0) {
+@@ -323,10 +327,14 @@ static int usb_probe_interface(struct device *dev)
+ 	return error;
+ 
+  err:
+-	mark_quiesced(intf);
+ 	intf->needs_remote_wakeup = 0;
+ 	intf->condition = USB_INTERFACE_UNBOUND;
+ 	usb_cancel_queued_reset(intf);
++
++	/* Unbound interfaces are always runtime-PM-disabled and -suspended */
++	pm_runtime_disable(dev);
++	pm_runtime_set_suspended(dev);
++
+ 	usb_autosuspend_device(udev);
+ 	return error;
+ }
+@@ -376,9 +384,17 @@ static int usb_unbind_interface(struct device *dev)
+ 	usb_set_intfdata(intf, NULL);
+ 
+ 	intf->condition = USB_INTERFACE_UNBOUND;
+-	mark_quiesced(intf);
+ 	intf->needs_remote_wakeup = 0;
+ 
++	/* Unbound interfaces are always runtime-PM-disabled and -suspended */
++	pm_runtime_disable(dev);
++	pm_runtime_set_suspended(dev);
++
++	/* Undo any residual pm_autopm_get_interface_* calls */
++	for (r = atomic_read(&intf->pm_usage_cnt); r > 0; --r)
++		usb_autopm_put_interface_no_suspend(intf);
++	atomic_set(&intf->pm_usage_cnt, 0);
++
+ 	if (!error)
+ 		usb_autosuspend_device(udev);
+ 
+@@ -409,7 +425,6 @@ int usb_driver_claim_interface(struct usb_driver *driver,
+ 				struct usb_interface *iface, void *priv)
+ {
+ 	struct device *dev = &iface->dev;
+-	struct usb_device *udev = interface_to_usbdev(iface);
+ 	int retval = 0;
+ 
+ 	if (dev->driver)
+@@ -419,11 +434,16 @@ int usb_driver_claim_interface(struct usb_driver *driver,
+ 	usb_set_intfdata(iface, priv);
+ 	iface->needs_binding = 0;
+ 
+-	usb_pm_lock(udev);
+ 	iface->condition = USB_INTERFACE_BOUND;
+-	mark_active(iface);
+-	atomic_set(&iface->pm_usage_cnt, !driver->supports_autosuspend);
+-	usb_pm_unlock(udev);
++
++	/* Bound interfaces are initially active.  They are
++	 * runtime-PM-enabled only if the driver has autosuspend support.
++	 * They are sensitive to their children's power states.
++	 */
++	pm_runtime_set_active(dev);
++	pm_suspend_ignore_children(dev, false);
++	if (driver->supports_autosuspend)
++		pm_runtime_enable(dev);
+ 
+ 	/* if interface was already added, bind now; else let
+ 	 * the future device_add() bind it, bypassing probe()
+@@ -982,7 +1002,6 @@ static void do_unbind_rebind(struct usb_device *udev, int action)
+ 	}
+ }
+ 
+-/* Caller has locked udev's pm_mutex */
+ static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
+ {
+ 	struct usb_device_driver	*udriver;
+@@ -1006,7 +1025,6 @@ static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
+ 	return status;
+ }
+ 
+-/* Caller has locked udev's pm_mutex */
+ static int usb_resume_device(struct usb_device *udev, pm_message_t msg)
+ {
+ 	struct usb_device_driver	*udriver;
+@@ -1040,27 +1058,20 @@ static int usb_resume_device(struct usb_device *udev, pm_message_t msg)
+ 	return status;
+ }
+ 
+-/* Caller has locked intf's usb_device's pm mutex */
+ static int usb_suspend_interface(struct usb_device *udev,
+ 		struct usb_interface *intf, pm_message_t msg)
+ {
+ 	struct usb_driver	*driver;
+ 	int			status = 0;
+ 
+-	/* with no hardware, USB interfaces only use FREEZE and ON states */
+-	if (udev->state == USB_STATE_NOTATTACHED || !is_active(intf))
+-		goto done;
+-
+-	/* This can happen; see usb_driver_release_interface() */
+-	if (intf->condition == USB_INTERFACE_UNBOUND)
++	if (udev->state == USB_STATE_NOTATTACHED ||
++			intf->condition == USB_INTERFACE_UNBOUND)
+ 		goto done;
+ 	driver = to_usb_driver(intf->dev.driver);
+ 
+ 	if (driver->suspend) {
+ 		status = driver->suspend(intf, msg);
+-		if (status == 0)
+-			mark_quiesced(intf);
+-		else if (!(msg.event & PM_EVENT_AUTO))
++		if (status && !(msg.event & PM_EVENT_AUTO))
+ 			dev_err(&intf->dev, "%s error %d\n",
+ 					"suspend", status);
+ 	} else {
+@@ -1068,7 +1079,6 @@ static int usb_suspend_interface(struct usb_device *udev,
+ 		intf->needs_binding = 1;
+ 		dev_warn(&intf->dev, "no %s for driver %s?\n",
+ 				"suspend", driver->name);
+-		mark_quiesced(intf);
+ 	}
+ 
+  done:
+@@ -1076,14 +1086,13 @@ static int usb_suspend_interface(struct usb_device *udev,
+ 	return status;
+ }
+ 
+-/* Caller has locked intf's usb_device's pm_mutex */
+ static int usb_resume_interface(struct usb_device *udev,
+ 		struct usb_interface *intf, pm_message_t msg, int reset_resume)
+ {
+ 	struct usb_driver	*driver;
+ 	int			status = 0;
+ 
+-	if (udev->state == USB_STATE_NOTATTACHED || is_active(intf))
++	if (udev->state == USB_STATE_NOTATTACHED)
+ 		goto done;
+ 
+ 	/* Don't let autoresume interfere with unbinding */
+@@ -1134,90 +1143,11 @@ static int usb_resume_interface(struct usb_device *udev,
+ 
+ done:
+ 	dev_vdbg(&intf->dev, "%s: status %d\n", __func__, status);
+-	if (status == 0 && intf->condition == USB_INTERFACE_BOUND)
+-		mark_active(intf);
+ 
+ 	/* Later we will unbind the driver and/or reprobe, if necessary */
+ 	return status;
+ }
+ 
+-#ifdef	CONFIG_USB_SUSPEND
+-
+-/* Internal routine to check whether we may autosuspend a device. */
+-static int autosuspend_check(struct usb_device *udev, int reschedule)
+-{
+-	int			i;
+-	struct usb_interface	*intf;
+-	unsigned long		suspend_time, j;
+-
+-	/* For autosuspend, fail fast if anything is in use or autosuspend
+-	 * is disabled.  Also fail if any interfaces require remote wakeup
+-	 * but it isn't available.
+-	 */
+-	if (udev->pm_usage_cnt > 0)
+-		return -EBUSY;
+-	if (udev->autosuspend_delay < 0 || udev->autosuspend_disabled)
+-		return -EPERM;
+-
+-	suspend_time = udev->last_busy + udev->autosuspend_delay;
+-	if (udev->actconfig) {
+-		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+-			intf = udev->actconfig->interface[i];
+-			if (!is_active(intf))
+-				continue;
+-			if (atomic_read(&intf->pm_usage_cnt) > 0)
+-				return -EBUSY;
+-			if (intf->needs_remote_wakeup &&
+-					!udev->do_remote_wakeup) {
+-				dev_dbg(&udev->dev, "remote wakeup needed "
+-						"for autosuspend\n");
+-				return -EOPNOTSUPP;
+-			}
+-
+-			/* Don't allow autosuspend if the device will need
+-			 * a reset-resume and any of its interface drivers
+-			 * doesn't include support.
+-			 */
+-			if (udev->quirks & USB_QUIRK_RESET_RESUME) {
+-				struct usb_driver *driver;
+-
+-				driver = to_usb_driver(intf->dev.driver);
+-				if (!driver->reset_resume ||
+-				    intf->needs_remote_wakeup)
+-					return -EOPNOTSUPP;
+-			}
+-		}
+-	}
+-
+-	/* If everything is okay but the device hasn't been idle for long
+-	 * enough, queue a delayed autosuspend request.  If the device
+-	 * _has_ been idle for long enough and the reschedule flag is set,
+-	 * likewise queue a delayed (1 second) autosuspend request.
+-	 */
+-	j = jiffies;
+-	if (time_before(j, suspend_time))
+-		reschedule = 1;
+-	else
+-		suspend_time = j + HZ;
+-	if (reschedule) {
+-		if (!timer_pending(&udev->autosuspend.timer)) {
+-			queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+-				round_jiffies_up_relative(suspend_time - j));
+-		}
+-		return -EAGAIN;
+-	}
+-	return 0;
+-}
+-
+-#else
+-
+-static inline int autosuspend_check(struct usb_device *udev, int reschedule)
+-{
+-	return 0;
+-}
+-
+-#endif	/* CONFIG_USB_SUSPEND */
+-
+ /**
+  * usb_suspend_both - suspend a USB device and its interfaces
+  * @udev: the usb_device to suspend
+@@ -1229,27 +1159,12 @@ static inline int autosuspend_check(struct usb_device *udev, int reschedule)
+  * all the interfaces which were suspended are resumed so that they remain
+  * in the same state as the device.
+  *
+- * If an autosuspend is in progress the routine checks first to make sure
+- * that neither the device itself or any of its active interfaces is in use
+- * (pm_usage_cnt is greater than 0).  If they are, the autosuspend fails.
+- *
+- * If the suspend succeeds, the routine recursively queues an autosuspend
+- * request for @udev's parent device, thereby propagating the change up
+- * the device tree.  If all of the parent's children are now suspended,
+- * the parent will autosuspend in turn.
+- *
+- * The suspend method calls are subject to mutual exclusion under control
+- * of @udev's pm_mutex.  Many of these calls are also under the protection
+- * of @udev's device lock (including all requests originating outside the
+- * USB subsystem), but autosuspend requests generated by a child device or
+- * interface driver may not be.  Usbcore will insure that the method calls
+- * do not arrive during bind, unbind, or reset operations.  However, drivers
+- * must be prepared to handle suspend calls arriving at unpredictable times.
+- * The only way to block such calls is to do an autoresume (preventing
+- * autosuspends) while holding @udev's device lock (preventing outside
+- * suspends).
+- *
+- * The caller must hold @udev->pm_mutex.
++ * Autosuspend requests originating from a child device or an interface
++ * driver may be made without the protection of @udev's device lock, but
++ * all other suspend calls will hold the lock.  Usbcore will insure that
++ * method calls do not arrive during bind, unbind, or reset operations.
++ * However drivers must be prepared to handle suspend calls arriving at
++ * unpredictable times.
+  *
+  * This routine can run only in process context.
+  */
+@@ -1258,20 +1173,11 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 	int			status = 0;
+ 	int			i = 0;
+ 	struct usb_interface	*intf;
+-	struct usb_device	*parent = udev->parent;
+ 
+ 	if (udev->state == USB_STATE_NOTATTACHED ||
+ 			udev->state == USB_STATE_SUSPENDED)
+ 		goto done;
+ 
+-	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
+-
+-	if (msg.event & PM_EVENT_AUTO) {
+-		status = autosuspend_check(udev, 0);
+-		if (status < 0)
+-			goto done;
+-	}
+-
+ 	/* Suspend all the interfaces and then udev itself */
+ 	if (udev->actconfig) {
+ 		for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
+@@ -1286,35 +1192,21 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 
+ 	/* If the suspend failed, resume interfaces that did get suspended */
+ 	if (status != 0) {
+-		pm_message_t msg2;
+-
+-		msg2.event = msg.event ^ (PM_EVENT_SUSPEND | PM_EVENT_RESUME);
++		msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME);
+ 		while (--i >= 0) {
+ 			intf = udev->actconfig->interface[i];
+-			usb_resume_interface(udev, intf, msg2, 0);
++			usb_resume_interface(udev, intf, msg, 0);
+ 		}
+ 
+-		/* Try another autosuspend when the interfaces aren't busy */
+-		if (msg.event & PM_EVENT_AUTO)
+-			autosuspend_check(udev, status == -EBUSY);
+-
+-	/* If the suspend succeeded then prevent any more URB submissions,
+-	 * flush any outstanding URBs, and propagate the suspend up the tree.
++	/* If the suspend succeeded then prevent any more URB submissions
++	 * and flush any outstanding URBs.
+ 	 */
+ 	} else {
+-		cancel_delayed_work(&udev->autosuspend);
+ 		udev->can_submit = 0;
+ 		for (i = 0; i < 16; ++i) {
+ 			usb_hcd_flush_endpoint(udev, udev->ep_out[i]);
+ 			usb_hcd_flush_endpoint(udev, udev->ep_in[i]);
+ 		}
+-
+-		/* If this is just a FREEZE or a PRETHAW, udev might
+-		 * not really be suspended.  Only true suspends get
+-		 * propagated up the device tree.
+-		 */
+-		if (parent && udev->state == USB_STATE_SUSPENDED)
+-			usb_autosuspend_device(parent);
+ 	}
+ 
+  done:
+@@ -1331,23 +1223,12 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+  * the resume method for @udev and then calls the resume methods for all
+  * the interface drivers in @udev.
+  *
+- * Before starting the resume, the routine calls itself recursively for
+- * the parent device of @udev, thereby propagating the change up the device
+- * tree and assuring that @udev will be able to resume.  If the parent is
+- * unable to resume successfully, the routine fails.
+- *
+- * The resume method calls are subject to mutual exclusion under control
+- * of @udev's pm_mutex.  Many of these calls are also under the protection
+- * of @udev's device lock (including all requests originating outside the
+- * USB subsystem), but autoresume requests generated by a child device or
+- * interface driver may not be.  Usbcore will insure that the method calls
+- * do not arrive during bind, unbind, or reset operations.  However, drivers
+- * must be prepared to handle resume calls arriving at unpredictable times.
+- * The only way to block such calls is to do an autoresume (preventing
+- * other autoresumes) while holding @udev's device lock (preventing outside
+- * resumes).
+- *
+- * The caller must hold @udev->pm_mutex.
++ * Autoresume requests originating from a child device or an interface
++ * driver may be made without the protection of @udev's device lock, but
++ * all other resume calls will hold the lock.  Usbcore will insure that
++ * method calls do not arrive during bind, unbind, or reset operations.
++ * However drivers must be prepared to handle resume calls arriving at
++ * unpredictable times.
+  *
+  * This routine can run only in process context.
+  */
+@@ -1356,48 +1237,18 @@ static int usb_resume_both(struct usb_device *udev, pm_message_t msg)
+ 	int			status = 0;
+ 	int			i;
+ 	struct usb_interface	*intf;
+-	struct usb_device	*parent = udev->parent;
+ 
+-	cancel_delayed_work(&udev->autosuspend);
+ 	if (udev->state == USB_STATE_NOTATTACHED) {
+ 		status = -ENODEV;
+ 		goto done;
+ 	}
+ 	udev->can_submit = 1;
+ 
+-	/* Propagate the resume up the tree, if necessary */
+-	if (udev->state == USB_STATE_SUSPENDED) {
+-		if (parent) {
+-			status = usb_autoresume_device(parent);
+-			if (status == 0) {
+-				status = usb_resume_device(udev, msg);
+-				if (status || udev->state ==
+-						USB_STATE_NOTATTACHED) {
+-					usb_autosuspend_device(parent);
+-
+-					/* It's possible usb_resume_device()
+-					 * failed after the port was
+-					 * unsuspended, causing udev to be
+-					 * logically disconnected.  We don't
+-					 * want usb_disconnect() to autosuspend
+-					 * the parent again, so tell it that
+-					 * udev disconnected while still
+-					 * suspended. */
+-					if (udev->state ==
+-							USB_STATE_NOTATTACHED)
+-						udev->discon_suspended = 1;
+-				}
+-			}
+-		} else {
+-
+-			/* We can't progagate beyond the USB subsystem,
+-			 * so if a root hub's controller is suspended
+-			 * then we're stuck. */
+-			status = usb_resume_device(udev, msg);
+-		}
+-	} else if (udev->reset_resume)
++	/* Resume the device */
++	if (udev->state == USB_STATE_SUSPENDED || udev->reset_resume)
+ 		status = usb_resume_device(udev, msg);
+ 
++	/* Resume the interfaces */
+ 	if (status == 0 && udev->actconfig) {
+ 		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+ 			intf = udev->actconfig->interface[i];
+@@ -1413,104 +1264,46 @@ static int usb_resume_both(struct usb_device *udev, pm_message_t msg)
+ 	return status;
+ }
+ 
+-/**
+- * usb_external_suspend_device - external suspend of a USB device and its interfaces
+- * @udev: the usb_device to suspend
+- * @msg: Power Management message describing this state transition
+- *
+- * This routine handles external suspend requests: ones not generated
+- * internally by a USB driver (autosuspend) but rather coming from the user
+- * (via sysfs) or the PM core (system sleep).  The suspend will be carried
+- * out regardless of @udev's usage counter or those of its interfaces,
+- * and regardless of whether or not remote wakeup is enabled.  Of course,
+- * interface drivers still have the option of failing the suspend (if
+- * there are unsuspended children, for example).
+- *
+- * The caller must hold @udev's device lock.
+- */
+-int usb_external_suspend_device(struct usb_device *udev, pm_message_t msg)
+-{
+-	int	status;
+-
+-	do_unbind_rebind(udev, DO_UNBIND);
+-	usb_pm_lock(udev);
+-	status = usb_suspend_both(udev, msg);
+-	usb_pm_unlock(udev);
+-	return status;
+-}
+-
+-/**
+- * usb_external_resume_device - external resume of a USB device and its interfaces
+- * @udev: the usb_device to resume
+- * @msg: Power Management message describing this state transition
+- *
+- * This routine handles external resume requests: ones not generated
+- * internally by a USB driver (autoresume) but rather coming from the user
+- * (via sysfs), the PM core (system resume), or the device itself (remote
+- * wakeup).  @udev's usage counter is unaffected.
+- *
+- * The caller must hold @udev's device lock.
+- */
+-int usb_external_resume_device(struct usb_device *udev, pm_message_t msg)
+-{
+-	int	status;
+-
+-	usb_pm_lock(udev);
+-	status = usb_resume_both(udev, msg);
+-	udev->last_busy = jiffies;
+-	usb_pm_unlock(udev);
+-	if (status == 0)
+-		do_unbind_rebind(udev, DO_REBIND);
+-
+-	/* Now that the device is awake, we can start trying to autosuspend
+-	 * it again. */
+-	if (status == 0)
+-		usb_try_autosuspend_device(udev);
+-	return status;
+-}
+-
++/* The device lock is held by the PM core */
+ int usb_suspend(struct device *dev, pm_message_t msg)
+ {
+-	struct usb_device	*udev;
+-
+-	udev = to_usb_device(dev);
++	struct usb_device	*udev = to_usb_device(dev);
+ 
+-	/* If udev is already suspended, we can skip this suspend and
+-	 * we should also skip the upcoming system resume.  High-speed
+-	 * root hubs are an exception; they need to resume whenever the
+-	 * system wakes up in order for USB-PERSIST port handover to work
+-	 * properly.
+-	 */
+-	if (udev->state == USB_STATE_SUSPENDED) {
+-		if (udev->parent || udev->speed != USB_SPEED_HIGH)
+-			udev->skip_sys_resume = 1;
+-		return 0;
+-	}
+-
+-	udev->skip_sys_resume = 0;
+-	return usb_external_suspend_device(udev, msg);
++	do_unbind_rebind(udev, DO_UNBIND);
++	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
++	return usb_suspend_both(udev, msg);
+ }
+ 
++/* The device lock is held by the PM core */
+ int usb_resume(struct device *dev, pm_message_t msg)
+ {
+-	struct usb_device	*udev;
++	struct usb_device	*udev = to_usb_device(dev);
+ 	int			status;
+ 
+-	udev = to_usb_device(dev);
++	/* For PM complete calls, all we do is rebind interfaces */
++	if (msg.event == PM_EVENT_ON) {
++		if (udev->state != USB_STATE_NOTATTACHED)
++			do_unbind_rebind(udev, DO_REBIND);
++		status = 0;
+ 
+-	/* If udev->skip_sys_resume is set then udev was already suspended
+-	 * when the system sleep started, so we don't want to resume it
+-	 * during this system wakeup.
++	/* For all other calls, take the device back to full power and
++	 * tell the PM core in case it was autosuspended previously.
+ 	 */
+-	if (udev->skip_sys_resume)
+-		return 0;
+-	status = usb_external_resume_device(udev, msg);
++	} else {
++		status = usb_resume_both(udev, msg);
++		if (status == 0) {
++			pm_runtime_disable(dev);
++			pm_runtime_set_active(dev);
++			pm_runtime_enable(dev);
++			udev->last_busy = jiffies;
++		}
++	}
+ 
+ 	/* Avoid PM error messages for devices disconnected while suspended
+ 	 * as we'll display regular disconnect messages just a bit later.
+ 	 */
+ 	if (status == -ENODEV)
+-		return 0;
++		status = 0;
+ 	return status;
+ }
+ 
+@@ -1560,54 +1353,6 @@ int usb_disable_autosuspend(struct usb_device *udev)
+ }
+ EXPORT_SYMBOL_GPL(usb_disable_autosuspend);
+ 
+-/* Internal routine to adjust a device's usage counter and change
+- * its autosuspend state.
+- */
+-static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt)
+-{
+-	int	status = 0;
+-
+-	usb_pm_lock(udev);
+-	udev->pm_usage_cnt += inc_usage_cnt;
+-	WARN_ON(udev->pm_usage_cnt < 0);
+-	if (inc_usage_cnt)
+-		udev->last_busy = jiffies;
+-	if (inc_usage_cnt >= 0 && udev->pm_usage_cnt > 0) {
+-		if (udev->state == USB_STATE_SUSPENDED)
+-			status = usb_resume_both(udev, PMSG_AUTO_RESUME);
+-		if (status != 0)
+-			udev->pm_usage_cnt -= inc_usage_cnt;
+-		else if (inc_usage_cnt)
+-			udev->last_busy = jiffies;
+-	} else if (inc_usage_cnt <= 0 && udev->pm_usage_cnt <= 0) {
+-		status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
+-	}
+-	usb_pm_unlock(udev);
+-	return status;
+-}
+-
+-/* usb_autosuspend_work - callback routine to autosuspend a USB device */
+-void usb_autosuspend_work(struct work_struct *work)
+-{
+-	struct usb_device *udev =
+-		container_of(work, struct usb_device, autosuspend.work);
+-
+-	usb_autopm_do_device(udev, 0);
+-}
+-
+-/* usb_autoresume_work - callback routine to autoresume a USB device */
+-void usb_autoresume_work(struct work_struct *work)
+-{
+-	struct usb_device *udev =
+-		container_of(work, struct usb_device, autoresume);
+-
+-	/* Wake it up, let the drivers do their thing, and then put it
+-	 * back to sleep.
+-	 */
+-	if (usb_autopm_do_device(udev, 1) == 0)
+-		usb_autopm_do_device(udev, -1);
+-}
+-
+ /**
+  * usb_autosuspend_device - delayed autosuspend of a USB device and its interfaces
+  * @udev: the usb_device to autosuspend
+@@ -1616,12 +1361,9 @@ void usb_autoresume_work(struct work_struct *work)
+  * @udev and wants to allow it to autosuspend.  Examples would be when
+  * @udev's device file in usbfs is closed or after a configuration change.
+  *
+- * @udev's usage counter is decremented.  If it or any of the usage counters
+- * for an active interface is greater than 0, no autosuspend request will be
+- * queued.  (If an interface driver does not support autosuspend then its
+- * usage counter is permanently positive.)  Furthermore, if an interface
+- * driver requires remote-wakeup capability during autosuspend but remote
+- * wakeup is disabled, the autosuspend will fail.
++ * @udev's usage counter is decremented; if it drops to 0 and all the
++ * interfaces are inactive then a delayed autosuspend will be attempted.
++ * The attempt may fail (see autosuspend_check()).
+  *
+  * The caller must hold @udev's device lock.
+  *
+@@ -1631,9 +1373,11 @@ void usb_autosuspend_device(struct usb_device *udev)
+ {
+ 	int	status;
+ 
+-	status = usb_autopm_do_device(udev, -1);
+-	dev_vdbg(&udev->dev, "%s: cnt %d\n",
+-			__func__, udev->pm_usage_cnt);
++	udev->last_busy = jiffies;
++	status = pm_runtime_put_sync(&udev->dev);
++	dev_vdbg(&udev->dev, "%s: cnt %d -> %d\n",
++			__func__, atomic_read(&udev->dev.power.usage_count),
++			status);
+ }
+ 
+ /**
+@@ -1643,9 +1387,9 @@ void usb_autosuspend_device(struct usb_device *udev)
+  * This routine should be called when a core subsystem thinks @udev may
+  * be ready to autosuspend.
+  *
+- * @udev's usage counter left unchanged.  If it or any of the usage counters
+- * for an active interface is greater than 0, or autosuspend is not allowed
+- * for any other reason, no autosuspend request will be queued.
++ * @udev's usage counter left unchanged.  If it is 0 and all the interfaces
++ * are inactive then an autosuspend will be attempted.  The attempt may
++ * fail or be delayed.
+  *
+  * The caller must hold @udev's device lock.
+  *
+@@ -1653,9 +1397,12 @@ void usb_autosuspend_device(struct usb_device *udev)
+  */
+ void usb_try_autosuspend_device(struct usb_device *udev)
+ {
+-	usb_autopm_do_device(udev, 0);
+-	dev_vdbg(&udev->dev, "%s: cnt %d\n",
+-			__func__, udev->pm_usage_cnt);
++	int	status;
++
++	status = pm_runtime_idle(&udev->dev);
++	dev_vdbg(&udev->dev, "%s: cnt %d -> %d\n",
++			__func__, atomic_read(&udev->dev.power.usage_count),
++			status);
+ }
+ 
+ /**
+@@ -1664,9 +1411,9 @@ void usb_try_autosuspend_device(struct usb_device *udev)
+  *
+  * This routine should be called when a core subsystem wants to use @udev
+  * and needs to guarantee that it is not suspended.  No autosuspend will
+- * occur until usb_autosuspend_device is called.  (Note that this will not
+- * prevent suspend events originating in the PM core.)  Examples would be
+- * when @udev's device file in usbfs is opened or when a remote-wakeup
++ * occur until usb_autosuspend_device() is called.  (Note that this will
++ * not prevent suspend events originating in the PM core.)  Examples would
++ * be when @udev's device file in usbfs is opened or when a remote-wakeup
+  * request is received.
+  *
+  * @udev's usage counter is incremented to prevent subsequent autosuspends.
+@@ -1680,42 +1427,14 @@ int usb_autoresume_device(struct usb_device *udev)
+ {
+ 	int	status;
+ 
+-	status = usb_autopm_do_device(udev, 1);
+-	dev_vdbg(&udev->dev, "%s: status %d cnt %d\n",
+-			__func__, status, udev->pm_usage_cnt);
+-	return status;
+-}
+-
+-/* Internal routine to adjust an interface's usage counter and change
+- * its device's autosuspend state.
+- */
+-static int usb_autopm_do_interface(struct usb_interface *intf,
+-		int inc_usage_cnt)
+-{
+-	struct usb_device	*udev = interface_to_usbdev(intf);
+-	int			status = 0;
+-
+-	usb_pm_lock(udev);
+-	if (intf->condition == USB_INTERFACE_UNBOUND)
+-		status = -ENODEV;
+-	else {
+-		atomic_add(inc_usage_cnt, &intf->pm_usage_cnt);
+-		udev->last_busy = jiffies;
+-		if (inc_usage_cnt >= 0 &&
+-				atomic_read(&intf->pm_usage_cnt) > 0) {
+-			if (udev->state == USB_STATE_SUSPENDED)
+-				status = usb_resume_both(udev,
+-						PMSG_AUTO_RESUME);
+-			if (status != 0)
+-				atomic_sub(inc_usage_cnt, &intf->pm_usage_cnt);
+-			else
+-				udev->last_busy = jiffies;
+-		} else if (inc_usage_cnt <= 0 &&
+-				atomic_read(&intf->pm_usage_cnt) <= 0) {
+-			status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
+-		}
+-	}
+-	usb_pm_unlock(udev);
++	status = pm_runtime_get_sync(&udev->dev);
++	if (status < 0)
++		pm_runtime_put_sync(&udev->dev);
++	dev_vdbg(&udev->dev, "%s: cnt %d -> %d\n",
++			__func__, atomic_read(&udev->dev.power.usage_count),
++			status);
++	if (status > 0)
++		status = 0;
+ 	return status;
+ }
+ 
+@@ -1729,34 +1448,25 @@ static int usb_autopm_do_interface(struct usb_interface *intf,
+  * closed.
+  *
+  * The routine decrements @intf's usage counter.  When the counter reaches
+- * 0, a delayed autosuspend request for @intf's device is queued.  When
+- * the delay expires, if @intf->pm_usage_cnt is still <= 0 along with all
+- * the other usage counters for the sibling interfaces and @intf's
+- * usb_device, the device and all its interfaces will be autosuspended.
+- *
+- * Note that @intf->pm_usage_cnt is owned by the interface driver.  The
+- * core will not change its value other than the increment and decrement
+- * in usb_autopm_get_interface and usb_autopm_put_interface.  The driver
+- * may use this simple counter-oriented discipline or may set the value
+- * any way it likes.
++ * 0, a delayed autosuspend request for @intf's device is attempted.  The
++ * attempt may fail (see autosuspend_check()).
+  *
+  * If the driver has set @intf->needs_remote_wakeup then autosuspend will
+  * take place only if the device's remote-wakeup facility is enabled.
+  *
+- * Suspend method calls queued by this routine can arrive at any time
+- * while @intf is resumed and its usage counter is equal to 0.  They are
+- * not protected by the usb_device's lock but only by its pm_mutex.
+- * Drivers must provide their own synchronization.
+- *
+  * This routine can run only in process context.
+  */
+ void usb_autopm_put_interface(struct usb_interface *intf)
+ {
+-	int	status;
++	struct usb_device	*udev = interface_to_usbdev(intf);
++	int			status;
+ 
+-	status = usb_autopm_do_interface(intf, -1);
+-	dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
+-			__func__, status, atomic_read(&intf->pm_usage_cnt));
++	udev->last_busy = jiffies;
++	atomic_dec(&intf->pm_usage_cnt);
++	status = pm_runtime_put_sync(&intf->dev);
++	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
++			__func__, atomic_read(&intf->dev.power.usage_count),
++			status);
+ }
+ EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
+ 
+@@ -1764,11 +1474,11 @@ EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
+  * usb_autopm_put_interface_async - decrement a USB interface's PM-usage counter
+  * @intf: the usb_interface whose counter should be decremented
+  *
+- * This routine does essentially the same thing as
+- * usb_autopm_put_interface(): it decrements @intf's usage counter and
+- * queues a delayed autosuspend request if the counter is <= 0.  The
+- * difference is that it does not acquire the device's pm_mutex;
+- * callers must handle all synchronization issues themselves.
++ * This routine does much the same thing as usb_autopm_put_interface():
++ * It decrements @intf's usage counter and schedules a delayed
++ * autosuspend request if the counter is <= 0.  The difference is that it
++ * does not perform any synchronization; callers should hold a private
++ * lock and handle all synchronization issues themselves.
+  *
+  * Typically a driver would call this routine during an URB's completion
+  * handler, if no more URBs were pending.
+@@ -1778,27 +1488,57 @@ EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
+ void usb_autopm_put_interface_async(struct usb_interface *intf)
+ {
+ 	struct usb_device	*udev = interface_to_usbdev(intf);
++	unsigned long		last_busy;
+ 	int			status = 0;
+ 
+-	if (intf->condition == USB_INTERFACE_UNBOUND) {
+-		status = -ENODEV;
+-	} else {
+-		udev->last_busy = jiffies;
+-		atomic_dec(&intf->pm_usage_cnt);
+-		if (udev->autosuspend_disabled || udev->autosuspend_delay < 0)
+-			status = -EPERM;
+-		else if (atomic_read(&intf->pm_usage_cnt) <= 0 &&
+-				!timer_pending(&udev->autosuspend.timer)) {
+-			queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
++	last_busy = udev->last_busy;
++	udev->last_busy = jiffies;
++	atomic_dec(&intf->pm_usage_cnt);
++	pm_runtime_put_noidle(&intf->dev);
++
++	if (!udev->autosuspend_disabled) {
++		/* Optimization: Don't schedule a delayed autosuspend if
++		 * the timer is already running and the expiration time
++		 * wouldn't change.
++		 *
++		 * We have to use the interface's timer.  Attempts to
++		 * schedule a suspend for the device would fail because
++		 * the interface is still active.
++		 */
++		if (intf->dev.power.timer_expires == 0 ||
++				round_jiffies_up(last_busy) !=
++				round_jiffies_up(jiffies)) {
++			status = pm_schedule_suspend(&intf->dev,
++					jiffies_to_msecs(
+ 					round_jiffies_up_relative(
+-						udev->autosuspend_delay));
++						udev->autosuspend_delay)));
+ 		}
+ 	}
+-	dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
+-			__func__, status, atomic_read(&intf->pm_usage_cnt));
++	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
++			__func__, atomic_read(&intf->dev.power.usage_count),
++			status);
+ }
+ EXPORT_SYMBOL_GPL(usb_autopm_put_interface_async);
+ 
++/**
++ * usb_autopm_put_interface_no_suspend - decrement a USB interface's PM-usage counter
++ * @intf: the usb_interface whose counter should be decremented
++ *
++ * This routine decrements @intf's usage counter but does not carry out an
++ * autosuspend.
++ *
++ * This routine can run in atomic context.
++ */
++void usb_autopm_put_interface_no_suspend(struct usb_interface *intf)
++{
++	struct usb_device	*udev = interface_to_usbdev(intf);
++
++	udev->last_busy = jiffies;
++	atomic_dec(&intf->pm_usage_cnt);
++	pm_runtime_put_noidle(&intf->dev);
++}
++EXPORT_SYMBOL_GPL(usb_autopm_put_interface_no_suspend);
++
+ /**
+  * usb_autopm_get_interface - increment a USB interface's PM-usage counter
+  * @intf: the usb_interface whose counter should be incremented
+@@ -1811,25 +1551,8 @@ EXPORT_SYMBOL_GPL(usb_autopm_put_interface_async);
+  * or @intf is unbound.  A typical example would be a character-device
+  * driver when its device file is opened.
+  *
+- *
+- * The routine increments @intf's usage counter.  (However if the
+- * autoresume fails then the counter is re-decremented.)  So long as the
+- * counter is greater than 0, autosuspend will not be allowed for @intf
+- * or its usb_device.  When the driver is finished using @intf it should
+- * call usb_autopm_put_interface() to decrement the usage counter and
+- * queue a delayed autosuspend request (if the counter is <= 0).
+- *
+- *
+- * Note that @intf->pm_usage_cnt is owned by the interface driver.  The
+- * core will not change its value other than the increment and decrement
+- * in usb_autopm_get_interface and usb_autopm_put_interface.  The driver
+- * may use this simple counter-oriented discipline or may set the value
+- * any way it likes.
+- *
+- * Resume method calls generated by this routine can arrive at any time
+- * while @intf is suspended.  They are not protected by the usb_device's
+- * lock but only by its pm_mutex.  Drivers must provide their own
+- * synchronization.
++ * @intf's usage counter is incremented to prevent subsequent autosuspends.
++ * However if the autoresume fails then the counter is re-decremented.
+  *
+  * This routine can run only in process context.
+  */
+@@ -1837,9 +1560,16 @@ int usb_autopm_get_interface(struct usb_interface *intf)
+ {
+ 	int	status;
+ 
+-	status = usb_autopm_do_interface(intf, 1);
+-	dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
+-			__func__, status, atomic_read(&intf->pm_usage_cnt));
++	status = pm_runtime_get_sync(&intf->dev);
++	if (status < 0)
++		pm_runtime_put_sync(&intf->dev);
++	else
++		atomic_inc(&intf->pm_usage_cnt);
++	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
++			__func__, atomic_read(&intf->dev.power.usage_count),
++			status);
++	if (status > 0)
++		status = 0;
+ 	return status;
+ }
+ EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
+@@ -1849,41 +1579,201 @@ EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
+  * @intf: the usb_interface whose counter should be incremented
+  *
+  * This routine does much the same thing as
+- * usb_autopm_get_interface(): it increments @intf's usage counter and
+- * queues an autoresume request if the result is > 0.  The differences
+- * are that it does not acquire the device's pm_mutex (callers must
+- * handle all synchronization issues themselves), and it does not
+- * autoresume the device directly (it only queues a request).  After a
+- * successful call, the device will generally not yet be resumed.
++ * usb_autopm_get_interface(): It increments @intf's usage counter and
++ * queues an autoresume request if the device is suspended.  The
++ * differences are that it does not perform any synchronization (callers
++ * should hold a private lock and handle all synchronization issues
++ * themselves), and it does not autoresume the device directly (it only
++ * queues a request).  After a successful call, the device may not yet be
++ * resumed.
+  *
+  * This routine can run in atomic context.
+  */
+ int usb_autopm_get_interface_async(struct usb_interface *intf)
+ {
+-	struct usb_device	*udev = interface_to_usbdev(intf);
+-	int			status = 0;
++	int		status = 0;
++	enum rpm_status	s;
+ 
+-	if (intf->condition == USB_INTERFACE_UNBOUND)
+-		status = -ENODEV;
+-	else {
++	/* Don't request a resume unless the interface is already suspending
++	 * or suspended.  Doing so would force a running suspend timer to be
++	 * cancelled.
++	 */
++	pm_runtime_get_noresume(&intf->dev);
++	s = ACCESS_ONCE(intf->dev.power.runtime_status);
++	if (s == RPM_SUSPENDING || s == RPM_SUSPENDED)
++		status = pm_request_resume(&intf->dev);
++
++	if (status < 0 && status != -EINPROGRESS)
++		pm_runtime_put_noidle(&intf->dev);
++	else
+ 		atomic_inc(&intf->pm_usage_cnt);
+-		if (atomic_read(&intf->pm_usage_cnt) > 0 &&
+-				udev->state == USB_STATE_SUSPENDED)
+-			queue_work(ksuspend_usb_wq, &udev->autoresume);
+-	}
+-	dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
+-			__func__, status, atomic_read(&intf->pm_usage_cnt));
++	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
++			__func__, atomic_read(&intf->dev.power.usage_count),
++			status);
++	if (status > 0)
++		status = 0;
+ 	return status;
+ }
+ EXPORT_SYMBOL_GPL(usb_autopm_get_interface_async);
+ 
+-#else
++/**
++ * usb_autopm_get_interface_no_resume - increment a USB interface's PM-usage counter
++ * @intf: the usb_interface whose counter should be incremented
++ *
++ * This routine increments @intf's usage counter but does not carry out an
++ * autoresume.
++ *
++ * This routine can run in atomic context.
++ */
++void usb_autopm_get_interface_no_resume(struct usb_interface *intf)
++{
++	struct usb_device	*udev = interface_to_usbdev(intf);
++
++	udev->last_busy = jiffies;
++	atomic_inc(&intf->pm_usage_cnt);
++	pm_runtime_get_noresume(&intf->dev);
++}
++EXPORT_SYMBOL_GPL(usb_autopm_get_interface_no_resume);
++
++/* Internal routine to check whether we may autosuspend a device. */
++static int autosuspend_check(struct usb_device *udev)
++{
++	int			i;
++	struct usb_interface	*intf;
++	unsigned long		suspend_time, j;
++
++	/* Fail if autosuspend is disabled, or any interfaces are in use, or
++	 * any interface drivers require remote wakeup but it isn't available.
++	 */
++	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
++	if (udev->actconfig) {
++		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
++			intf = udev->actconfig->interface[i];
++
++			/* We don't need to check interfaces that are
++			 * disabled for runtime PM.  Either they are unbound
++			 * or else their drivers don't support autosuspend
++			 * and so they are permanently active.
++			 */
++			if (intf->dev.power.disable_depth)
++				continue;
++			if (atomic_read(&intf->dev.power.usage_count) > 0)
++				return -EBUSY;
++			if (intf->needs_remote_wakeup &&
++					!udev->do_remote_wakeup) {
++				dev_dbg(&udev->dev, "remote wakeup needed "
++						"for autosuspend\n");
++				return -EOPNOTSUPP;
++			}
++
++			/* Don't allow autosuspend if the device will need
++			 * a reset-resume and any of its interface drivers
++			 * doesn't include support or needs remote wakeup.
++			 */
++			if (udev->quirks & USB_QUIRK_RESET_RESUME) {
++				struct usb_driver *driver;
++
++				driver = to_usb_driver(intf->dev.driver);
++				if (!driver->reset_resume ||
++						intf->needs_remote_wakeup)
++					return -EOPNOTSUPP;
++			}
++		}
++	}
++
++	/* If everything is okay but the device hasn't been idle for long
++	 * enough, queue a delayed autosuspend request.
++	 */
++	j = ACCESS_ONCE(jiffies);
++	suspend_time = udev->last_busy + udev->autosuspend_delay;
++	if (time_before(j, suspend_time)) {
++		pm_schedule_suspend(&udev->dev, jiffies_to_msecs(
++				round_jiffies_up_relative(suspend_time - j)));
++		return -EAGAIN;
++	}
++	return 0;
++}
++
++static int usb_runtime_suspend(struct device *dev)
++{
++	int	status = 0;
+ 
+-void usb_autosuspend_work(struct work_struct *work)
+-{}
++	/* A USB device can be suspended if it passes the various autosuspend
++	 * checks.  Runtime suspend for a USB device means suspending all the
++	 * interfaces and then the device itself.
++	 */
++	if (is_usb_device(dev)) {
++		struct usb_device	*udev = to_usb_device(dev);
++
++		if (autosuspend_check(udev) != 0)
++			return -EAGAIN;
++
++		status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
++
++		/* If an interface fails the suspend, adjust the last_busy
++		 * time so that we don't get another suspend attempt right
++		 * away.
++		 */
++		if (status) {
++			udev->last_busy = jiffies +
++					(udev->autosuspend_delay == 0 ?
++						HZ/2 : 0);
++		}
++
++		/* Prevent the parent from suspending immediately after */
++		else if (udev->parent) {
++			udev->parent->last_busy = jiffies;
++		}
++	}
++
++	/* Runtime suspend for a USB interface doesn't mean anything. */
++	return status;
++}
++
++static int usb_runtime_resume(struct device *dev)
++{
++	/* Runtime resume for a USB device means resuming both the device
++	 * and all its interfaces.
++	 */
++	if (is_usb_device(dev)) {
++		struct usb_device	*udev = to_usb_device(dev);
++		int			status;
++
++		status = usb_resume_both(udev, PMSG_AUTO_RESUME);
++		udev->last_busy = jiffies;
++		return status;
++	}
++
++	/* Runtime resume for a USB interface doesn't mean anything. */
++	return 0;
++}
++
++static int usb_runtime_idle(struct device *dev)
++{
++	/* An idle USB device can be suspended if it passes the various
++	 * autosuspend checks.  An idle interface can be suspended at
++	 * any time.
++	 */
++	if (is_usb_device(dev)) {
++		struct usb_device	*udev = to_usb_device(dev);
++
++		if (autosuspend_check(udev) != 0)
++			return 0;
++	}
++
++	pm_runtime_suspend(dev);
++	return 0;
++}
++
++static struct dev_pm_ops usb_bus_pm_ops = {
++	.runtime_suspend =	usb_runtime_suspend,
++	.runtime_resume =	usb_runtime_resume,
++	.runtime_idle =		usb_runtime_idle,
++};
++
++#else
+ 
+-void usb_autoresume_work(struct work_struct *work)
+-{}
++#define usb_bus_pm_ops	(*(struct dev_pm_ops *) NULL)
+ 
+ #endif /* CONFIG_USB_SUSPEND */
+ 
+@@ -1891,4 +1781,5 @@ struct bus_type usb_bus_type = {
+ 	.name =		"usb",
+ 	.match =	usb_device_match,
+ 	.uevent =	usb_uevent,
++	.pm =		&usb_bus_pm_ops,
+ };
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index fc4290b6691c..b07ba051118d 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -39,6 +39,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ 
+@@ -1858,6 +1859,10 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
+ 	return status;
+ }
+ 
++#endif	/* CONFIG_PM */
++
++#ifdef	CONFIG_USB_SUSPEND
++
+ /* Workqueue routine for root-hub remote wakeup */
+ static void hcd_resume_work(struct work_struct *work)
+ {
+@@ -1884,12 +1889,12 @@ void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
+ 
+ 	spin_lock_irqsave (&hcd_root_hub_lock, flags);
+ 	if (hcd->rh_registered)
+-		queue_work(ksuspend_usb_wq, &hcd->wakeup_work);
++		queue_work(pm_wq, &hcd->wakeup_work);
+ 	spin_unlock_irqrestore (&hcd_root_hub_lock, flags);
+ }
+ EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub);
+ 
+-#endif
++#endif	/* CONFIG_USB_SUSPEND */
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+@@ -2034,7 +2039,7 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
+ 	init_timer(&hcd->rh_timer);
+ 	hcd->rh_timer.function = rh_timer_func;
+ 	hcd->rh_timer.data = (unsigned long) hcd;
+-#ifdef CONFIG_PM
++#ifdef CONFIG_USB_SUSPEND
+ 	INIT_WORK(&hcd->wakeup_work, hcd_resume_work);
+ #endif
+ 	mutex_init(&hcd->bandwidth_mutex);
+@@ -2234,7 +2239,7 @@ void usb_remove_hcd(struct usb_hcd *hcd)
+ 	hcd->rh_registered = 0;
+ 	spin_unlock_irq (&hcd_root_hub_lock);
+ 
+-#ifdef CONFIG_PM
++#ifdef CONFIG_USB_SUSPEND
+ 	cancel_work_sync(&hcd->wakeup_work);
+ #endif
+ 
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index 70a7e490f81b..8953ded69541 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -80,7 +80,7 @@ struct usb_hcd {
+ 
+ 	struct timer_list	rh_timer;	/* drives root-hub polling */
+ 	struct urb		*status_urb;	/* the current status urb */
+-#ifdef CONFIG_PM
++#ifdef CONFIG_USB_SUSPEND
+ 	struct work_struct	wakeup_work;	/* for remote wakeup */
+ #endif
+ 
+@@ -464,16 +464,20 @@ extern int usb_find_interface_driver(struct usb_device *dev,
+ #define usb_endpoint_out(ep_dir)	(!((ep_dir) & USB_DIR_IN))
+ 
+ #ifdef CONFIG_PM
+-extern void usb_hcd_resume_root_hub(struct usb_hcd *hcd);
+ extern void usb_root_hub_lost_power(struct usb_device *rhdev);
+ extern int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg);
+ extern int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg);
++#endif /* CONFIG_PM */
++
++#ifdef CONFIG_USB_SUSPEND
++extern void usb_hcd_resume_root_hub(struct usb_hcd *hcd);
+ #else
+ static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
+ {
+ 	return;
+ }
+-#endif /* CONFIG_PM */
++#endif /* CONFIG_USB_SUSPEND */
++
+ 
+ /*
+  * USB device fs stuff
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 746f26f222ab..0e0a190bbd00 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -22,6 +22,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ #include 
+@@ -71,7 +72,6 @@ struct usb_hub {
+ 
+ 	unsigned		mA_per_port;	/* current for each child */
+ 
+-	unsigned		init_done:1;
+ 	unsigned		limited_power:1;
+ 	unsigned		quiescing:1;
+ 	unsigned		disconnected:1;
+@@ -820,7 +820,6 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ 	}
+  init3:
+ 	hub->quiescing = 0;
+-	hub->init_done = 1;
+ 
+ 	status = usb_submit_urb(hub->urb, GFP_NOIO);
+ 	if (status < 0)
+@@ -861,11 +860,6 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
+ 	int i;
+ 
+ 	cancel_delayed_work_sync(&hub->init_work);
+-	if (!hub->init_done) {
+-		hub->init_done = 1;
+-		usb_autopm_put_interface_no_suspend(
+-				to_usb_interface(hub->intfdev));
+-	}
+ 
+ 	/* khubd and related activity won't re-trigger */
+ 	hub->quiescing = 1;
+@@ -1405,10 +1399,8 @@ static void recursively_mark_NOTATTACHED(struct usb_device *udev)
+ 		if (udev->children[i])
+ 			recursively_mark_NOTATTACHED(udev->children[i]);
+ 	}
+-	if (udev->state == USB_STATE_SUSPENDED) {
+-		udev->discon_suspended = 1;
++	if (udev->state == USB_STATE_SUSPENDED)
+ 		udev->active_duration -= jiffies;
+-	}
+ 	udev->state = USB_STATE_NOTATTACHED;
+ }
+ 
+@@ -1532,31 +1524,6 @@ static void update_address(struct usb_device *udev, int devnum)
+ 		udev->devnum = devnum;
+ }
+ 
+-#ifdef	CONFIG_USB_SUSPEND
+-
+-static void usb_stop_pm(struct usb_device *udev)
+-{
+-	/* Synchronize with the ksuspend thread to prevent any more
+-	 * autosuspend requests from being submitted, and decrement
+-	 * the parent's count of unsuspended children.
+-	 */
+-	usb_pm_lock(udev);
+-	if (udev->parent && !udev->discon_suspended)
+-		usb_autosuspend_device(udev->parent);
+-	usb_pm_unlock(udev);
+-
+-	/* Stop any autosuspend or autoresume requests already submitted */
+-	cancel_delayed_work_sync(&udev->autosuspend);
+-	cancel_work_sync(&udev->autoresume);
+-}
+-
+-#else
+-
+-static inline void usb_stop_pm(struct usb_device *udev)
+-{ }
+-
+-#endif
+-
+ /**
+  * usb_disconnect - disconnect a device (usbcore-internal)
+  * @pdev: pointer to device being disconnected
+@@ -1625,8 +1592,6 @@ void usb_disconnect(struct usb_device **pdev)
+ 	*pdev = NULL;
+ 	spin_unlock_irq(&device_state_lock);
+ 
+-	usb_stop_pm(udev);
+-
+ 	put_device(&udev->dev);
+ }
+ 
+@@ -1803,9 +1768,6 @@ int usb_new_device(struct usb_device *udev)
+ 	int err;
+ 
+ 	if (udev->parent) {
+-		/* Increment the parent's count of unsuspended children */
+-		usb_autoresume_device(udev->parent);
+-
+ 		/* Initialize non-root-hub device wakeup to disabled;
+ 		 * device (un)configuration controls wakeup capable
+ 		 * sysfs power/wakeup controls wakeup enabled/disabled
+@@ -1814,6 +1776,10 @@ int usb_new_device(struct usb_device *udev)
+ 		device_set_wakeup_enable(&udev->dev, 1);
+ 	}
+ 
++	/* Tell the runtime-PM framework the device is active */
++	pm_runtime_set_active(&udev->dev);
++	pm_runtime_enable(&udev->dev);
++
+ 	usb_detect_quirks(udev);
+ 	err = usb_enumerate_device(udev);	/* Read descriptors */
+ 	if (err < 0)
+@@ -1844,7 +1810,8 @@ int usb_new_device(struct usb_device *udev)
+ 
+ fail:
+ 	usb_set_device_state(udev, USB_STATE_NOTATTACHED);
+-	usb_stop_pm(udev);
++	pm_runtime_disable(&udev->dev);
++	pm_runtime_set_suspended(&udev->dev);
+ 	return err;
+ }
+ 
+@@ -2408,8 +2375,11 @@ int usb_remote_wakeup(struct usb_device *udev)
+ 
+ 	if (udev->state == USB_STATE_SUSPENDED) {
+ 		dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-");
+-		usb_mark_last_busy(udev);
+-		status = usb_external_resume_device(udev, PMSG_REMOTE_RESUME);
++		status = usb_autoresume_device(udev);
++		if (status == 0) {
++			/* Let the drivers do their thing, then... */
++			usb_autosuspend_device(udev);
++		}
+ 	}
+ 	return status;
+ }
+@@ -2446,11 +2416,6 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
+ 	return status;
+ }
+ 
+-int usb_remote_wakeup(struct usb_device *udev)
+-{
+-	return 0;
+-}
+-
+ #endif
+ 
+ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+@@ -3268,7 +3233,7 @@ static void hub_events(void)
+ 		 * disconnected while waiting for the lock to succeed. */
+ 		usb_lock_device(hdev);
+ 		if (unlikely(hub->disconnected))
+-			goto loop2;
++			goto loop_disconnected;
+ 
+ 		/* If the hub has died, clean up after it */
+ 		if (hdev->state == USB_STATE_NOTATTACHED) {
+@@ -3428,7 +3393,7 @@ static void hub_events(void)
+ 		 * kick_khubd() and allow autosuspend.
+ 		 */
+ 		usb_autopm_put_interface(intf);
+- loop2:
++ loop_disconnected:
+ 		usb_unlock_device(hdev);
+ 		kref_put(&hub->kref, hub_release);
+ 
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index df73574a9cc9..73de41bb2546 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1843,7 +1843,6 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 		intf->dev.dma_mask = dev->dev.dma_mask;
+ 		INIT_WORK(&intf->reset_ws, __usb_queue_reset_device);
+ 		device_initialize(&intf->dev);
+-		mark_quiesced(intf);
+ 		dev_set_name(&intf->dev, "%d-%s:%d.%d",
+ 			dev->bus->busnum, dev->devpath,
+ 			configuration, alt->desc.bInterfaceNumber);
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 0daff0d968ba..32966ccdff63 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -49,9 +49,6 @@ const char *usbcore_name = "usbcore";
+ 
+ static int nousb;	/* Disable USB when built into kernel image */
+ 
+-/* Workqueue for autosuspend and for remote wakeup of root hubs */
+-struct workqueue_struct *ksuspend_usb_wq;
+-
+ #ifdef	CONFIG_USB_SUSPEND
+ static int usb_autosuspend_delay = 2;		/* Default delay value,
+ 						 * in seconds */
+@@ -264,23 +261,6 @@ static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
+ 
+ #ifdef	CONFIG_PM
+ 
+-static int ksuspend_usb_init(void)
+-{
+-	/* This workqueue is supposed to be both freezable and
+-	 * singlethreaded.  Its job doesn't justify running on more
+-	 * than one CPU.
+-	 */
+-	ksuspend_usb_wq = create_freezeable_workqueue("ksuspend_usbd");
+-	if (!ksuspend_usb_wq)
+-		return -ENOMEM;
+-	return 0;
+-}
+-
+-static void ksuspend_usb_cleanup(void)
+-{
+-	destroy_workqueue(ksuspend_usb_wq);
+-}
+-
+ /* USB device Power-Management thunks.
+  * There's no need to distinguish here between quiescing a USB device
+  * and powering it down; the generic_suspend() routine takes care of
+@@ -296,7 +276,7 @@ static int usb_dev_prepare(struct device *dev)
+ static void usb_dev_complete(struct device *dev)
+ {
+ 	/* Currently used only for rebinding interfaces */
+-	usb_resume(dev, PMSG_RESUME);	/* Message event is meaningless */
++	usb_resume(dev, PMSG_ON);	/* FIXME: change to PMSG_COMPLETE */
+ }
+ 
+ static int usb_dev_suspend(struct device *dev)
+@@ -342,9 +322,7 @@ static const struct dev_pm_ops usb_device_pm_ops = {
+ 
+ #else
+ 
+-#define ksuspend_usb_init()	0
+-#define ksuspend_usb_cleanup()	do {} while (0)
+-#define usb_device_pm_ops	(*(struct dev_pm_ops *)0)
++#define usb_device_pm_ops	(*(struct dev_pm_ops *) NULL)
+ 
+ #endif	/* CONFIG_PM */
+ 
+@@ -472,9 +450,6 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
+ 	INIT_LIST_HEAD(&dev->filelist);
+ 
+ #ifdef	CONFIG_PM
+-	mutex_init(&dev->pm_mutex);
+-	INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work);
+-	INIT_WORK(&dev->autoresume, usb_autoresume_work);
+ 	dev->autosuspend_delay = usb_autosuspend_delay * HZ;
+ 	dev->connect_time = jiffies;
+ 	dev->active_duration = -jiffies;
+@@ -1117,9 +1092,6 @@ static int __init usb_init(void)
+ 	if (retval)
+ 		goto out;
+ 
+-	retval = ksuspend_usb_init();
+-	if (retval)
+-		goto out;
+ 	retval = bus_register(&usb_bus_type);
+ 	if (retval)
+ 		goto bus_register_failed;
+@@ -1159,7 +1131,7 @@ static int __init usb_init(void)
+ bus_notifier_failed:
+ 	bus_unregister(&usb_bus_type);
+ bus_register_failed:
+-	ksuspend_usb_cleanup();
++	usb_debugfs_cleanup();
+ out:
+ 	return retval;
+ }
+@@ -1181,7 +1153,6 @@ static void __exit usb_exit(void)
+ 	usb_hub_cleanup();
+ 	bus_unregister_notifier(&usb_bus_type, &usb_bus_nb);
+ 	bus_unregister(&usb_bus_type);
+-	ksuspend_usb_cleanup();
+ 	usb_debugfs_cleanup();
+ }
+ 
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 2b74a7f99c41..cd882203ad34 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -55,25 +55,8 @@ extern void usb_major_cleanup(void);
+ extern int usb_suspend(struct device *dev, pm_message_t msg);
+ extern int usb_resume(struct device *dev, pm_message_t msg);
+ 
+-extern void usb_autosuspend_work(struct work_struct *work);
+-extern void usb_autoresume_work(struct work_struct *work);
+ extern int usb_port_suspend(struct usb_device *dev, pm_message_t msg);
+ extern int usb_port_resume(struct usb_device *dev, pm_message_t msg);
+-extern int usb_external_suspend_device(struct usb_device *udev,
+-		pm_message_t msg);
+-extern int usb_external_resume_device(struct usb_device *udev,
+-		pm_message_t msg);
+-extern int usb_remote_wakeup(struct usb_device *dev);
+-
+-static inline void usb_pm_lock(struct usb_device *udev)
+-{
+-	mutex_lock_nested(&udev->pm_mutex, udev->level);
+-}
+-
+-static inline void usb_pm_unlock(struct usb_device *udev)
+-{
+-	mutex_unlock(&udev->pm_mutex);
+-}
+ 
+ #else
+ 
+@@ -87,14 +70,6 @@ static inline int usb_port_resume(struct usb_device *udev, pm_message_t msg)
+ 	return 0;
+ }
+ 
+-static inline int usb_remote_wakeup(struct usb_device *udev)
+-{
+-	return 0;
+-}
+-
+-static inline void usb_pm_lock(struct usb_device *udev) {}
+-static inline void usb_pm_unlock(struct usb_device *udev) {}
+-
+ #endif
+ 
+ #ifdef CONFIG_USB_SUSPEND
+@@ -102,6 +77,7 @@ static inline void usb_pm_unlock(struct usb_device *udev) {}
+ extern void usb_autosuspend_device(struct usb_device *udev);
+ extern void usb_try_autosuspend_device(struct usb_device *udev);
+ extern int usb_autoresume_device(struct usb_device *udev);
++extern int usb_remote_wakeup(struct usb_device *dev);
+ 
+ #else
+ 
+@@ -112,9 +88,13 @@ static inline int usb_autoresume_device(struct usb_device *udev)
+ 	return 0;
+ }
+ 
++static inline int usb_remote_wakeup(struct usb_device *udev)
++{
++	return 0;
++}
++
+ #endif
+ 
+-extern struct workqueue_struct *ksuspend_usb_wq;
+ extern struct bus_type usb_bus_type;
+ extern struct device_type usb_device_type;
+ extern struct device_type usb_if_device_type;
+@@ -144,23 +124,6 @@ static inline int is_usb_device_driver(struct device_driver *drv)
+ 			for_devices;
+ }
+ 
+-/* Interfaces and their "power state" are owned by usbcore */
+-
+-static inline void mark_active(struct usb_interface *f)
+-{
+-	f->is_active = 1;
+-}
+-
+-static inline void mark_quiesced(struct usb_interface *f)
+-{
+-	f->is_active = 0;
+-}
+-
+-static inline int is_active(const struct usb_interface *f)
+-{
+-	return f->is_active;
+-}
+-
+ 
+ /* for labeling diagnostics */
+ extern const char *usbcore_name;
+diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
+index 3dab0c0b196f..707a87da77f8 100644
+--- a/drivers/usb/misc/usbtest.c
++++ b/drivers/usb/misc/usbtest.c
+@@ -1580,10 +1580,6 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
+ 		return -ERESTARTSYS;
+ 
+ 	/* FIXME: What if a system sleep starts while a test is running? */
+-	if (!intf->is_active) {
+-		mutex_unlock(&dev->lock);
+-		return -EHOSTUNREACH;
+-	}
+ 
+ 	/* some devices, like ez-usb default devices, need a non-default
+ 	 * altsetting to have any active endpoints.  some tests change
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index e6419ac89ea2..ad50fc8a7ad3 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -122,7 +122,6 @@ enum usb_interface_condition {
+  *	number from the USB core by calling usb_register_dev().
+  * @condition: binding state of the interface: not bound, binding
+  *	(in probe()), bound to a driver, or unbinding (in disconnect())
+- * @is_active: flag set when the interface is bound and not suspended.
+  * @sysfs_files_created: sysfs attributes exist
+  * @ep_devs_created: endpoint child pseudo-devices exist
+  * @unregistering: flag set when the interface is being unregistered
+@@ -135,8 +134,7 @@ enum usb_interface_condition {
+  * @dev: driver model's view of this device
+  * @usb_dev: if an interface is bound to the USB major, this will point
+  *	to the sysfs representation for that device.
+- * @pm_usage_cnt: PM usage counter for this interface; autosuspend is not
+- *	allowed unless the counter is 0.
++ * @pm_usage_cnt: PM usage counter for this interface
+  * @reset_ws: Used for scheduling resets from atomic context.
+  * @reset_running: set to 1 if the interface is currently running a
+  *      queued reset so that usb_cancel_queued_reset() doesn't try to
+@@ -184,7 +182,6 @@ struct usb_interface {
+ 	int minor;			/* minor number this interface is
+ 					 * bound to */
+ 	enum usb_interface_condition condition;		/* state of binding */
+-	unsigned is_active:1;		/* the interface is not suspended */
+ 	unsigned sysfs_files_created:1;	/* the sysfs attributes exist */
+ 	unsigned ep_devs_created:1;	/* endpoint "devices" exist */
+ 	unsigned unregistering:1;	/* unregistration is in progress */
+@@ -401,7 +398,6 @@ struct usb_tt;
+  * @portnum: parent port number (origin 1)
+  * @level: number of USB hub ancestors
+  * @can_submit: URBs may be submitted
+- * @discon_suspended: disconnected while suspended
+  * @persist_enabled:  USB_PERSIST enabled for this device
+  * @have_langid: whether string_langid is valid
+  * @authorized: policy has said we can use it;
+@@ -421,20 +417,15 @@ struct usb_tt;
+  * @usbfs_dentry: usbfs dentry entry for the device
+  * @maxchild: number of ports if hub
+  * @children: child devices - USB devices that are attached to this hub
+- * @pm_usage_cnt: usage counter for autosuspend
+  * @quirks: quirks of the whole device
+  * @urbnum: number of URBs submitted for the whole device
+  * @active_duration: total time device is not suspended
+- * @autosuspend: for delayed autosuspends
+- * @autoresume: for autoresumes requested while in_interrupt
+- * @pm_mutex: protects PM operations
+  * @last_busy: time of last use
+  * @autosuspend_delay: in jiffies
+  * @connect_time: time device was first connected
+  * @do_remote_wakeup:  remote wakeup should be enabled
+  * @reset_resume: needs reset instead of resume
+  * @autosuspend_disabled: autosuspend disabled by the user
+- * @skip_sys_resume: skip the next system resume
+  * @wusb_dev: if this is a Wireless USB device, link to the WUSB
+  *	specific data for the device.
+  * @slot_id: Slot ID assigned by xHCI
+@@ -475,7 +466,6 @@ struct usb_device {
+ 	u8 level;
+ 
+ 	unsigned can_submit:1;
+-	unsigned discon_suspended:1;
+ 	unsigned persist_enabled:1;
+ 	unsigned have_langid:1;
+ 	unsigned authorized:1;
+@@ -499,17 +489,12 @@ struct usb_device {
+ 	int maxchild;
+ 	struct usb_device *children[USB_MAXCHILDREN];
+ 
+-	int pm_usage_cnt;
+ 	u32 quirks;
+ 	atomic_t urbnum;
+ 
+ 	unsigned long active_duration;
+ 
+ #ifdef CONFIG_PM
+-	struct delayed_work autosuspend;
+-	struct work_struct autoresume;
+-	struct mutex pm_mutex;
+-
+ 	unsigned long last_busy;
+ 	int autosuspend_delay;
+ 	unsigned long connect_time;
+@@ -517,7 +502,6 @@ struct usb_device {
+ 	unsigned do_remote_wakeup:1;
+ 	unsigned reset_resume:1;
+ 	unsigned autosuspend_disabled:1;
+-	unsigned skip_sys_resume:1;
+ #endif
+ 	struct wusb_dev *wusb_dev;
+ 	int slot_id;
+@@ -549,17 +533,8 @@ extern int usb_autopm_get_interface(struct usb_interface *intf);
+ extern void usb_autopm_put_interface(struct usb_interface *intf);
+ extern int usb_autopm_get_interface_async(struct usb_interface *intf);
+ extern void usb_autopm_put_interface_async(struct usb_interface *intf);
+-
+-static inline void usb_autopm_get_interface_no_resume(
+-		struct usb_interface *intf)
+-{
+-	atomic_inc(&intf->pm_usage_cnt);
+-}
+-static inline void usb_autopm_put_interface_no_suspend(
+-		struct usb_interface *intf)
+-{
+-	atomic_dec(&intf->pm_usage_cnt);
+-}
++extern void usb_autopm_get_interface_no_resume(struct usb_interface *intf);
++extern void usb_autopm_put_interface_no_suspend(struct usb_interface *intf);
+ 
+ static inline void usb_mark_last_busy(struct usb_device *udev)
+ {

commit 0c590e2361511997430130e10e372217c1128da6
+Author: Alan Stern 
+Date:   Fri Jan 8 12:57:14 2010 -0500
+
+    USB: rearrange functions in driver.c
+    
+    This patch (as1328) reorders the functions in drivers/usb/core/driver.c
+    so as to put all the routines dependent on CONFIG_PM in one place.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 057eeab06004..638d54693a1c 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1413,6 +1413,109 @@ static int usb_resume_both(struct usb_device *udev, pm_message_t msg)
+ 	return status;
+ }
+ 
++/**
++ * usb_external_suspend_device - external suspend of a USB device and its interfaces
++ * @udev: the usb_device to suspend
++ * @msg: Power Management message describing this state transition
++ *
++ * This routine handles external suspend requests: ones not generated
++ * internally by a USB driver (autosuspend) but rather coming from the user
++ * (via sysfs) or the PM core (system sleep).  The suspend will be carried
++ * out regardless of @udev's usage counter or those of its interfaces,
++ * and regardless of whether or not remote wakeup is enabled.  Of course,
++ * interface drivers still have the option of failing the suspend (if
++ * there are unsuspended children, for example).
++ *
++ * The caller must hold @udev's device lock.
++ */
++int usb_external_suspend_device(struct usb_device *udev, pm_message_t msg)
++{
++	int	status;
++
++	do_unbind_rebind(udev, DO_UNBIND);
++	usb_pm_lock(udev);
++	status = usb_suspend_both(udev, msg);
++	usb_pm_unlock(udev);
++	return status;
++}
++
++/**
++ * usb_external_resume_device - external resume of a USB device and its interfaces
++ * @udev: the usb_device to resume
++ * @msg: Power Management message describing this state transition
++ *
++ * This routine handles external resume requests: ones not generated
++ * internally by a USB driver (autoresume) but rather coming from the user
++ * (via sysfs), the PM core (system resume), or the device itself (remote
++ * wakeup).  @udev's usage counter is unaffected.
++ *
++ * The caller must hold @udev's device lock.
++ */
++int usb_external_resume_device(struct usb_device *udev, pm_message_t msg)
++{
++	int	status;
++
++	usb_pm_lock(udev);
++	status = usb_resume_both(udev, msg);
++	udev->last_busy = jiffies;
++	usb_pm_unlock(udev);
++	if (status == 0)
++		do_unbind_rebind(udev, DO_REBIND);
++
++	/* Now that the device is awake, we can start trying to autosuspend
++	 * it again. */
++	if (status == 0)
++		usb_try_autosuspend_device(udev);
++	return status;
++}
++
++int usb_suspend(struct device *dev, pm_message_t msg)
++{
++	struct usb_device	*udev;
++
++	udev = to_usb_device(dev);
++
++	/* If udev is already suspended, we can skip this suspend and
++	 * we should also skip the upcoming system resume.  High-speed
++	 * root hubs are an exception; they need to resume whenever the
++	 * system wakes up in order for USB-PERSIST port handover to work
++	 * properly.
++	 */
++	if (udev->state == USB_STATE_SUSPENDED) {
++		if (udev->parent || udev->speed != USB_SPEED_HIGH)
++			udev->skip_sys_resume = 1;
++		return 0;
++	}
++
++	udev->skip_sys_resume = 0;
++	return usb_external_suspend_device(udev, msg);
++}
++
++int usb_resume(struct device *dev, pm_message_t msg)
++{
++	struct usb_device	*udev;
++	int			status;
++
++	udev = to_usb_device(dev);
++
++	/* If udev->skip_sys_resume is set then udev was already suspended
++	 * when the system sleep started, so we don't want to resume it
++	 * during this system wakeup.
++	 */
++	if (udev->skip_sys_resume)
++		return 0;
++	status = usb_external_resume_device(udev, msg);
++
++	/* Avoid PM error messages for devices disconnected while suspended
++	 * as we'll display regular disconnect messages just a bit later.
++	 */
++	if (status == -ENODEV)
++		return 0;
++	return status;
++}
++
++#endif /* CONFIG_PM */
++
+ #ifdef CONFIG_USB_SUSPEND
+ 
+ /**
+@@ -1784,109 +1887,6 @@ void usb_autoresume_work(struct work_struct *work)
+ 
+ #endif /* CONFIG_USB_SUSPEND */
+ 
+-/**
+- * usb_external_suspend_device - external suspend of a USB device and its interfaces
+- * @udev: the usb_device to suspend
+- * @msg: Power Management message describing this state transition
+- *
+- * This routine handles external suspend requests: ones not generated
+- * internally by a USB driver (autosuspend) but rather coming from the user
+- * (via sysfs) or the PM core (system sleep).  The suspend will be carried
+- * out regardless of @udev's usage counter or those of its interfaces,
+- * and regardless of whether or not remote wakeup is enabled.  Of course,
+- * interface drivers still have the option of failing the suspend (if
+- * there are unsuspended children, for example).
+- *
+- * The caller must hold @udev's device lock.
+- */
+-int usb_external_suspend_device(struct usb_device *udev, pm_message_t msg)
+-{
+-	int	status;
+-
+-	do_unbind_rebind(udev, DO_UNBIND);
+-	usb_pm_lock(udev);
+-	status = usb_suspend_both(udev, msg);
+-	usb_pm_unlock(udev);
+-	return status;
+-}
+-
+-/**
+- * usb_external_resume_device - external resume of a USB device and its interfaces
+- * @udev: the usb_device to resume
+- * @msg: Power Management message describing this state transition
+- *
+- * This routine handles external resume requests: ones not generated
+- * internally by a USB driver (autoresume) but rather coming from the user
+- * (via sysfs), the PM core (system resume), or the device itself (remote
+- * wakeup).  @udev's usage counter is unaffected.
+- *
+- * The caller must hold @udev's device lock.
+- */
+-int usb_external_resume_device(struct usb_device *udev, pm_message_t msg)
+-{
+-	int	status;
+-
+-	usb_pm_lock(udev);
+-	status = usb_resume_both(udev, msg);
+-	udev->last_busy = jiffies;
+-	usb_pm_unlock(udev);
+-	if (status == 0)
+-		do_unbind_rebind(udev, DO_REBIND);
+-
+-	/* Now that the device is awake, we can start trying to autosuspend
+-	 * it again. */
+-	if (status == 0)
+-		usb_try_autosuspend_device(udev);
+-	return status;
+-}
+-
+-int usb_suspend(struct device *dev, pm_message_t msg)
+-{
+-	struct usb_device	*udev;
+-
+-	udev = to_usb_device(dev);
+-
+-	/* If udev is already suspended, we can skip this suspend and
+-	 * we should also skip the upcoming system resume.  High-speed
+-	 * root hubs are an exception; they need to resume whenever the
+-	 * system wakes up in order for USB-PERSIST port handover to work
+-	 * properly.
+-	 */
+-	if (udev->state == USB_STATE_SUSPENDED) {
+-		if (udev->parent || udev->speed != USB_SPEED_HIGH)
+-			udev->skip_sys_resume = 1;
+-		return 0;
+-	}
+-
+-	udev->skip_sys_resume = 0;
+-	return usb_external_suspend_device(udev, msg);
+-}
+-
+-int usb_resume(struct device *dev, pm_message_t msg)
+-{
+-	struct usb_device	*udev;
+-	int			status;
+-
+-	udev = to_usb_device(dev);
+-
+-	/* If udev->skip_sys_resume is set then udev was already suspended
+-	 * when the system sleep started, so we don't want to resume it
+-	 * during this system wakeup.
+-	 */
+-	if (udev->skip_sys_resume)
+-		return 0;
+-	status = usb_external_resume_device(udev, msg);
+-
+-	/* Avoid PM error messages for devices disconnected while suspended
+-	 * as we'll display regular disconnect messages just a bit later.
+-	 */
+-	if (status == -ENODEV)
+-		return 0;
+-	return status;
+-}
+-
+-#endif /* CONFIG_PM */
+-
+ struct bus_type usb_bus_type = {
+ 	.name =		"usb",
+ 	.match =	usb_device_match,

commit 5899f1e020c8d53b2b6fbd6a6cf39c891ccdfade
+Author: Alan Stern 
+Date:   Fri Jan 8 12:57:02 2010 -0500
+
+    USB: change handling of negative autosuspend delays
+    
+    This patch (as1327) changes the way negative autosuspend delays
+    prevent device from autosuspending.  The current code checks for
+    negative values explicitly in the autosuspend_check() routine.  The
+    updated code keeps things from getting that far by using
+    usb_autoresume_device() to increment the usage counter when a negative
+    delay is set, and by using usb_autosuspend_device() to decrement the
+    usage counter when a non-negative delay is set.
+    
+    This complicates the set_autosuspend() attribute method code slightly,
+    but it will reduce the overall power management overhead.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index 4314f259524b..f073c5cb4e7b 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -103,11 +103,21 @@ void usb_detect_quirks(struct usb_device *udev)
+ 		dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
+ 				udev->quirks);
+ 
++#ifdef	CONFIG_USB_SUSPEND
++
+ 	/* By default, disable autosuspend for all devices.  The hub driver
+ 	 * will enable it for hubs.
+ 	 */
+ 	usb_disable_autosuspend(udev);
+ 
++	/* Autosuspend can also be disabled if the initial autosuspend_delay
++	 * is negative.
++	 */
++	if (udev->autosuspend_delay < 0)
++		usb_autoresume_device(udev);
++
++#endif
++
+ 	/* For the present, all devices default to USB-PERSIST enabled */
+ #if 0		/* was: #ifdef CONFIG_PM */
+ 	/* Hubs are automatically enabled for USB-PERSIST */
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 313e241f5ccc..43c002e3a9aa 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -346,7 +346,8 @@ set_autosuspend(struct device *dev, struct device_attribute *attr,
+ 		const char *buf, size_t count)
+ {
+ 	struct usb_device *udev = to_usb_device(dev);
+-	int value;
++	int value, old_delay;
++	int rc;
+ 
+ 	if (sscanf(buf, "%d", &value) != 1 || value >= INT_MAX/HZ ||
+ 			value <= - INT_MAX/HZ)
+@@ -354,13 +355,24 @@ set_autosuspend(struct device *dev, struct device_attribute *attr,
+ 	value *= HZ;
+ 
+ 	usb_lock_device(udev);
++	old_delay = udev->autosuspend_delay;
+ 	udev->autosuspend_delay = value;
+-	if (value >= 0)
+-		usb_try_autosuspend_device(udev);
+-	else {
+-		if (usb_autoresume_device(udev) == 0)
++
++	if (old_delay < 0) {	/* Autosuspend wasn't allowed */
++		if (value >= 0)
+ 			usb_autosuspend_device(udev);
++	} else {		/* Autosuspend was allowed */
++		if (value < 0) {
++			rc = usb_autoresume_device(udev);
++			if (rc < 0) {
++				count = rc;
++				udev->autosuspend_delay = old_delay;
++			}
++		} else {
++			usb_try_autosuspend_device(udev);
++		}
+ 	}
++
+ 	usb_unlock_device(udev);
+ 	return count;
+ }

commit 088f7fec8a0e683db72fd8826c5d3ab914e197b1
+Author: Alan Stern 
+Date:   Fri Jan 8 12:56:54 2010 -0500
+
+    USB: implement usb_enable_autosuspend
+    
+    This patch (as1326) adds usb_enable_autosuspend() and
+    usb_disable_autosuspend() routines for use by drivers.  If a driver
+    knows that its device can handle suspends and resumes correctly, it
+    can enable autosuspend all by itself.  This is equivalent to the user
+    writing "auto" to the device's power/level attribute.
+    
+    The implementation differs slightly from what it used to be.  Now
+    autosuspend is disabled simply by doing usb_autoresume_device() (to
+    increment the usage counter) and enabled by doing
+    usb_autosuspend_device() (to decrement the usage counter).
+    
+    The set_level() attribute method is updated to use the new routines,
+    and the USB Power-Management documentation is updated.
+    
+    The patch adds a usb_enable_autosuspend() call to the hub driver's
+    probe routine, allowing the special-case code for hubs in quirks.c to
+    be removed.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt
+index 3bf6818c8cf5..e3fa189c257a 100644
+--- a/Documentation/usb/power-management.txt
++++ b/Documentation/usb/power-management.txt
+@@ -229,6 +229,11 @@ necessary operations by hand or add them to a udev script.  You can
+ also change the idle-delay time; 2 seconds is not the best choice for
+ every device.
+ 
++If a driver knows that its device has proper suspend/resume support,
++it can enable autosuspend all by itself.  For example, the video
++driver for a laptop's webcam might do this, since these devices are
++rarely used and so should normally be autosuspended.
++
+ Sometimes it turns out that even when a device does work okay with
+ autosuspend there are still problems.  For example, there are
+ experimental patches adding autosuspend support to the usbhid driver,
+@@ -384,6 +389,19 @@ autosuspend, there's no delay for an autoresume.
+ 	Other parts of the driver interface
+ 	-----------------------------------
+ 
++Drivers can enable autosuspend for their devices by calling
++
++	usb_enable_autosuspend(struct usb_device *udev);
++
++in their probe() routine, if they know that the device is capable of
++suspending and resuming correctly.  This is exactly equivalent to
++writing "auto" to the device's power/level attribute.  Likewise,
++drivers can disable autosuspend by calling
++
++	usb_disable_autosuspend(struct usb_device *udev);
++
++This is exactly the same as writing "on" to the power/level attribute.
++
+ Sometimes a driver needs to make sure that remote wakeup is enabled
+ during autosuspend.  For example, there's not much point
+ autosuspending a keyboard if the user can't cause the keyboard to do a
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 2b39583040d0..057eeab06004 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1415,6 +1415,48 @@ static int usb_resume_both(struct usb_device *udev, pm_message_t msg)
+ 
+ #ifdef CONFIG_USB_SUSPEND
+ 
++/**
++ * usb_enable_autosuspend - allow a USB device to be autosuspended
++ * @udev: the USB device which may be autosuspended
++ *
++ * This routine allows @udev to be autosuspended.  An autosuspend won't
++ * take place until the autosuspend_delay has elapsed and all the other
++ * necessary conditions are satisfied.
++ *
++ * The caller must hold @udev's device lock.
++ */
++int usb_enable_autosuspend(struct usb_device *udev)
++{
++	if (udev->autosuspend_disabled) {
++		udev->autosuspend_disabled = 0;
++		usb_autosuspend_device(udev);
++	}
++	return 0;
++}
++EXPORT_SYMBOL_GPL(usb_enable_autosuspend);
++
++/**
++ * usb_disable_autosuspend - prevent a USB device from being autosuspended
++ * @udev: the USB device which may not be autosuspended
++ *
++ * This routine prevents @udev from being autosuspended and wakes it up
++ * if it is already autosuspended.
++ *
++ * The caller must hold @udev's device lock.
++ */
++int usb_disable_autosuspend(struct usb_device *udev)
++{
++	int rc = 0;
++
++	if (!udev->autosuspend_disabled) {
++		rc = usb_autoresume_device(udev);
++		if (rc == 0)
++			udev->autosuspend_disabled = 1;
++	}
++	return rc;
++}
++EXPORT_SYMBOL_GPL(usb_disable_autosuspend);
++
+ /* Internal routine to adjust a device's usage counter and change
+  * its autosuspend state.
+  */
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index bfa6123bbdb5..746f26f222ab 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1224,6 +1224,9 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
+ 	desc = intf->cur_altsetting;
+ 	hdev = interface_to_usbdev(intf);
+ 
++	/* Hubs have proper suspend/resume support */
++	usb_enable_autosuspend(hdev);
++
+ 	if (hdev->level == MAX_TOPO_LEVEL) {
+ 		dev_err(&intf->dev,
+ 			"Unsupported bus topology: hub nested too deep\n");
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index 0b689224394b..4314f259524b 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -103,11 +103,10 @@ void usb_detect_quirks(struct usb_device *udev)
+ 		dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
+ 				udev->quirks);
+ 
+-	/* By default, disable autosuspend for all non-hubs */
+-#ifdef	CONFIG_USB_SUSPEND
+-	if (udev->descriptor.bDeviceClass != USB_CLASS_HUB)
+-		udev->autosuspend_disabled = 1;
+-#endif
++	/* By default, disable autosuspend for all devices.  The hub driver
++	 * will enable it for hubs.
++	 */
++	usb_disable_autosuspend(udev);
+ 
+ 	/* For the present, all devices default to USB-PERSIST enabled */
+ #if 0		/* was: #ifdef CONFIG_PM */
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 5a1a0e2b6474..313e241f5ccc 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -389,34 +389,25 @@ set_level(struct device *dev, struct device_attribute *attr,
+ 	struct usb_device *udev = to_usb_device(dev);
+ 	int len = count;
+ 	char *cp;
+-	int rc = 0;
+-	int old_autosuspend_disabled;
++	int rc;
+ 
+ 	cp = memchr(buf, '\n', count);
+ 	if (cp)
+ 		len = cp - buf;
+ 
+ 	usb_lock_device(udev);
+-	old_autosuspend_disabled = udev->autosuspend_disabled;
+ 
+-	/* Setting the flags without calling usb_pm_lock is a subject to
+-	 * races, but who cares...
+-	 */
+ 	if (len == sizeof on_string - 1 &&
+-			strncmp(buf, on_string, len) == 0) {
+-		udev->autosuspend_disabled = 1;
+-		rc = usb_external_resume_device(udev, PMSG_USER_RESUME);
++			strncmp(buf, on_string, len) == 0)
++		rc = usb_disable_autosuspend(udev);
+ 
+-	} else if (len == sizeof auto_string - 1 &&
+-			strncmp(buf, auto_string, len) == 0) {
+-		udev->autosuspend_disabled = 0;
+-		rc = usb_external_resume_device(udev, PMSG_USER_RESUME);
++	else if (len == sizeof auto_string - 1 &&
++			strncmp(buf, auto_string, len) == 0)
++		rc = usb_enable_autosuspend(udev);
+ 
+-	} else
++	else
+ 		rc = -EINVAL;
+ 
+-	if (rc)
+-		udev->autosuspend_disabled = old_autosuspend_disabled;
+ 	usb_unlock_device(udev);
+ 	return (rc < 0 ? rc : count);
+ }
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 332eaea61021..e6419ac89ea2 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -542,6 +542,9 @@ extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id);
+ 
+ /* USB autosuspend and autoresume */
+ #ifdef CONFIG_USB_SUSPEND
++extern int usb_enable_autosuspend(struct usb_device *udev);
++extern int usb_disable_autosuspend(struct usb_device *udev);
++
+ extern int usb_autopm_get_interface(struct usb_interface *intf);
+ extern void usb_autopm_put_interface(struct usb_interface *intf);
+ extern int usb_autopm_get_interface_async(struct usb_interface *intf);
+@@ -565,6 +568,11 @@ static inline void usb_mark_last_busy(struct usb_device *udev)
+ 
+ #else
+ 
++static inline int usb_enable_autosuspend(struct usb_device *udev)
++{ return 0; }
++static inline int usb_disable_autosuspend(struct usb_device *udev)
++{ return 0; }
++
+ static inline int usb_autopm_get_interface(struct usb_interface *intf)
+ { return 0; }
+ static inline int usb_autopm_get_interface_async(struct usb_interface *intf)

commit 0c4db6df915bc470f0cd32fe48287fa6eb6adfb4
+Author: Alan Stern 
+Date:   Fri Jan 8 12:56:42 2010 -0500
+
+    USB: use the device lock for persist_enabled
+    
+    This patch (as1325) changes the locking for the persist_enabled flag
+    in struct usb_device.  Now it is protected by the device lock, along
+    with all its neighboring bit flags, instead of the PM lock (which is
+    about to vanish anyway).
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index d8f3bfe1559f..5a1a0e2b6474 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -256,9 +256,10 @@ set_persist(struct device *dev, struct device_attribute *attr,
+ 
+ 	if (sscanf(buf, "%d", &value) != 1)
+ 		return -EINVAL;
+-	usb_pm_lock(udev);
++
++	usb_lock_device(udev);
+ 	udev->persist_enabled = !!value;
+-	usb_pm_unlock(udev);
++	usb_unlock_device(udev);
+ 	return count;
+ }
+ 

commit 0534d46848990e8eed7cd0832d745d813e827261
+Author: Alan Stern 
+Date:   Fri Jan 8 12:56:30 2010 -0500
+
+    USB: consolidate remote wakeup routines
+    
+    This patch (as1324) makes a small change to the code used for remote
+    wakeup of root hubs.  hcd_resume_work() now calls the hub driver's
+    remote-wakeup routine instead of implementing its own version.
+    
+    The patch is complicated by the need to rename remote_wakeup() to
+    usb_remote_wakeup(), make it non-static, and declare it in a header
+    file.  There's also the additional complication required to make
+    everything work when CONFIG_PM isn't set; the do-nothing inline
+    routine had to be moved into the header file.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index cf0a098a5432..fc4290b6691c 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1865,8 +1865,7 @@ static void hcd_resume_work(struct work_struct *work)
+ 	struct usb_device *udev = hcd->self.root_hub;
+ 
+ 	usb_lock_device(udev);
+-	usb_mark_last_busy(udev);
+-	usb_external_resume_device(udev, PMSG_REMOTE_RESUME);
++	usb_remote_wakeup(udev);
+ 	usb_unlock_device(udev);
+ }
+ 
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 4986ff628465..bfa6123bbdb5 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2399,7 +2399,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
+ }
+ 
+ /* caller has locked udev */
+-static int remote_wakeup(struct usb_device *udev)
++int usb_remote_wakeup(struct usb_device *udev)
+ {
+ 	int	status = 0;
+ 
+@@ -2443,7 +2443,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
+ 	return status;
+ }
+ 
+-static inline int remote_wakeup(struct usb_device *udev)
++int usb_remote_wakeup(struct usb_device *udev)
+ {
+ 	return 0;
+ }
+@@ -2514,11 +2514,6 @@ EXPORT_SYMBOL_GPL(usb_root_hub_lost_power);
+ 
+ #else	/* CONFIG_PM */
+ 
+-static inline int remote_wakeup(struct usb_device *udev)
+-{
+-	return 0;
+-}
+-
+ #define hub_suspend		NULL
+ #define hub_resume		NULL
+ #define hub_reset_resume	NULL
+@@ -3017,7 +3012,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 			/* For a suspended device, treat this as a
+ 			 * remote wakeup event.
+ 			 */
+-			status = remote_wakeup(udev);
++			status = usb_remote_wakeup(udev);
+ #endif
+ 
+ 		} else {
+@@ -3363,7 +3358,7 @@ static void hub_events(void)
+ 					msleep(10);
+ 
+ 					usb_lock_device(udev);
+-					ret = remote_wakeup(hdev->
++					ret = usb_remote_wakeup(hdev->
+ 							children[i-1]);
+ 					usb_unlock_device(udev);
+ 					if (ret < 0)
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 4c36c7f512a0..2b74a7f99c41 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -63,6 +63,7 @@ extern int usb_external_suspend_device(struct usb_device *udev,
+ 		pm_message_t msg);
+ extern int usb_external_resume_device(struct usb_device *udev,
+ 		pm_message_t msg);
++extern int usb_remote_wakeup(struct usb_device *dev);
+ 
+ static inline void usb_pm_lock(struct usb_device *udev)
+ {
+@@ -86,6 +87,11 @@ static inline int usb_port_resume(struct usb_device *udev, pm_message_t msg)
+ 	return 0;
+ }
+ 
++static inline int usb_remote_wakeup(struct usb_device *udev)
++{
++	return 0;
++}
++
+ static inline void usb_pm_lock(struct usb_device *udev) {}
+ static inline void usb_pm_unlock(struct usb_device *udev) {}
+ 

commit 62e299e61a6ffe8131fa85a984c3058b68586f5d
+Author: Alan Stern 
+Date:   Fri Jan 8 12:56:19 2010 -0500
+
+    USB: change locking for device-level autosuspend
+    
+    This patch (as1323) changes the locking requirements for
+    usb_autosuspend_device(), usb_autoresume_device(), and
+    usb_try_autosuspend_device().  This isn't a very important change;
+    mainly it's meant to make the locking more uniform.
+    
+    The most tricky part of the patch involves changes to usbdev_open().
+    To avoid an ABBA locking problem, it was necessary to reduce the
+    region protected by usbfs_mutex.  Since that mutex now protects only
+    against simultaneous open and remove, this posed no difficulty -- its
+    scope was larger than necessary.
+    
+    And it turns out that usbfs_mutex is no longer needed in
+    usbdev_release() at all.  The list of usbfs "ps" structures is now
+    protected by the device lock instead of by usbfs_mutex.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 431d17287a86..825e0abfed0a 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -654,19 +654,21 @@ static int usbdev_open(struct inode *inode, struct file *file)
+ 	int ret;
+ 
+ 	lock_kernel();
+-	/* Protect against simultaneous removal or release */
+-	mutex_lock(&usbfs_mutex);
+ 
+ 	ret = -ENOMEM;
+ 	ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL);
+ 	if (!ps)
+-		goto out;
++		goto out_free_ps;
+ 
+ 	ret = -ENODEV;
+ 
++	/* Protect against simultaneous removal or release */
++	mutex_lock(&usbfs_mutex);
++
+ 	/* usbdev device-node */
+ 	if (imajor(inode) == USB_DEVICE_MAJOR)
+ 		dev = usbdev_lookup_by_devt(inode->i_rdev);
++
+ #ifdef CONFIG_USB_DEVICEFS
+ 	/* procfs file */
+ 	if (!dev) {
+@@ -678,13 +680,19 @@ static int usbdev_open(struct inode *inode, struct file *file)
+ 			dev = NULL;
+ 	}
+ #endif
+-	if (!dev || dev->state == USB_STATE_NOTATTACHED)
+-		goto out;
++	mutex_unlock(&usbfs_mutex);
++
++	if (!dev)
++		goto out_free_ps;
++
++	usb_lock_device(dev);
++	if (dev->state == USB_STATE_NOTATTACHED)
++		goto out_unlock_device;
++
+ 	ret = usb_autoresume_device(dev);
+ 	if (ret)
+-		goto out;
++		goto out_unlock_device;
+ 
+-	ret = 0;
+ 	ps->dev = dev;
+ 	ps->file = file;
+ 	spin_lock_init(&ps->lock);
+@@ -702,14 +710,17 @@ static int usbdev_open(struct inode *inode, struct file *file)
+ 	smp_wmb();
+ 	list_add_tail(&ps->list, &dev->filelist);
+ 	file->private_data = ps;
++	usb_unlock_device(dev);
+ 	snoop(&dev->dev, "opened by process %d: %s\n", task_pid_nr(current),
+ 			current->comm);
+- out:
+-	if (ret) {
+-		kfree(ps);
+-		usb_put_dev(dev);
+-	}
+-	mutex_unlock(&usbfs_mutex);
++	unlock_kernel();
++	return ret;
++
++ out_unlock_device:
++	usb_unlock_device(dev);
++	usb_put_dev(dev);
++ out_free_ps:
++	kfree(ps);
+ 	unlock_kernel();
+ 	return ret;
+ }
+@@ -724,10 +735,7 @@ static int usbdev_release(struct inode *inode, struct file *file)
+ 	usb_lock_device(dev);
+ 	usb_hub_release_all_ports(dev, ps);
+ 
+-	/* Protect against simultaneous open */
+-	mutex_lock(&usbfs_mutex);
+ 	list_del_init(&ps->list);
+-	mutex_unlock(&usbfs_mutex);
+ 
+ 	for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed);
+ 			ifnum++) {
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index fcafb2dce3ac..2b39583040d0 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1478,8 +1478,7 @@ void usb_autoresume_work(struct work_struct *work)
+  * driver requires remote-wakeup capability during autosuspend but remote
+  * wakeup is disabled, the autosuspend will fail.
+  *
+- * Often the caller will hold @udev's device lock, but this is not
+- * necessary.
++ * The caller must hold @udev's device lock.
+  *
+  * This routine can run only in process context.
+  */
+@@ -1503,6 +1502,8 @@ void usb_autosuspend_device(struct usb_device *udev)
+  * for an active interface is greater than 0, or autosuspend is not allowed
+  * for any other reason, no autosuspend request will be queued.
+  *
++ * The caller must hold @udev's device lock.
++ *
+  * This routine can run only in process context.
+  */
+ void usb_try_autosuspend_device(struct usb_device *udev)
+@@ -1526,8 +1527,7 @@ void usb_try_autosuspend_device(struct usb_device *udev)
+  * @udev's usage counter is incremented to prevent subsequent autosuspends.
+  * However if the autoresume fails then the usage counter is re-decremented.
+  *
+- * Often the caller will hold @udev's device lock, but this is not
+- * necessary (and attempting it might cause deadlock).
++ * The caller must hold @udev's device lock.
+  *
+  * This routine can run only in process context.
+  */
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 1b3c00b3ca3f..d8f3bfe1559f 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -352,6 +352,7 @@ set_autosuspend(struct device *dev, struct device_attribute *attr,
+ 		return -EINVAL;
+ 	value *= HZ;
+ 
++	usb_lock_device(udev);
+ 	udev->autosuspend_delay = value;
+ 	if (value >= 0)
+ 		usb_try_autosuspend_device(udev);
+@@ -359,6 +360,7 @@ set_autosuspend(struct device *dev, struct device_attribute *attr,
+ 		if (usb_autoresume_device(udev) == 0)
+ 			usb_autosuspend_device(udev);
+ 	}
++	usb_unlock_device(udev);
+ 	return count;
+ }
+ 

commit 0f3dda9f7ff2db8dbf4d6fbab4d4438251446002
+Author: Alan Stern 
+Date:   Fri Jan 8 12:56:04 2010 -0500
+
+    USB: rearrange code in usb_probe_interface
+    
+    This patch (as1322) reverses the two outcomes of an "if" statement in
+    usb_probe_interface(), to avoid an unnecessary level of indentation.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index f2f055eb6831..fcafb2dce3ac 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -274,56 +274,55 @@ static int usb_probe_interface(struct device *dev)
+ 	intf->needs_binding = 0;
+ 
+ 	if (usb_device_is_owned(udev))
+-		return -ENODEV;
++		return error;
+ 
+ 	if (udev->authorized == 0) {
+ 		dev_err(&intf->dev, "Device is not authorized for usage\n");
+-		return -ENODEV;
++		return error;
+ 	}
+ 
+ 	id = usb_match_id(intf, driver->id_table);
+ 	if (!id)
+ 		id = usb_match_dynamic_id(intf, driver);
+-	if (id) {
+-		dev_dbg(dev, "%s - got id\n", __func__);
+-
+-		error = usb_autoresume_device(udev);
+-		if (error)
+-			return error;
++	if (!id)
++		return error;
+ 
+-		/* Interface "power state" doesn't correspond to any hardware
+-		 * state whatsoever.  We use it to record when it's bound to
+-		 * a driver that may start I/0:  it's not frozen/quiesced.
+-		 */
+-		mark_active(intf);
+-		intf->condition = USB_INTERFACE_BINDING;
++	dev_dbg(dev, "%s - got id\n", __func__);
+ 
+-		/* The interface should always appear to be in use
+-		 * unless the driver suports autosuspend.
+-		 */
+-		atomic_set(&intf->pm_usage_cnt, !driver->supports_autosuspend);
++	error = usb_autoresume_device(udev);
++	if (error)
++		return error;
+ 
+-		/* Carry out a deferred switch to altsetting 0 */
+-		if (intf->needs_altsetting0) {
+-			error = usb_set_interface(udev, intf->altsetting[0].
+-					desc.bInterfaceNumber, 0);
+-			if (error < 0)
+-				goto err;
++	/* Interface "power state" doesn't correspond to any hardware
++	 * state whatsoever.  We use it to record when it's bound to
++	 * a driver that may start I/0:  it's not frozen/quiesced.
++	 */
++	mark_active(intf);
++	intf->condition = USB_INTERFACE_BINDING;
+ 
+-			intf->needs_altsetting0 = 0;
+-		}
++	/* The interface should always appear to be in use
++	 * unless the driver suports autosuspend.
++	 */
++	atomic_set(&intf->pm_usage_cnt, !driver->supports_autosuspend);
+ 
+-		error = driver->probe(intf, id);
+-		if (error)
++	/* Carry out a deferred switch to altsetting 0 */
++	if (intf->needs_altsetting0) {
++		error = usb_set_interface(udev, intf->altsetting[0].
++				desc.bInterfaceNumber, 0);
++		if (error < 0)
+ 			goto err;
+-
+-		intf->condition = USB_INTERFACE_BOUND;
+-		usb_autosuspend_device(udev);
++		intf->needs_altsetting0 = 0;
+ 	}
+ 
++	error = driver->probe(intf, id);
++	if (error)
++		goto err;
++
++	intf->condition = USB_INTERFACE_BOUND;
++	usb_autosuspend_device(udev);
+ 	return error;
+ 
+-err:
++ err:
+ 	mark_quiesced(intf);
+ 	intf->needs_remote_wakeup = 0;
+ 	intf->condition = USB_INTERFACE_UNBOUND;

commit f661c6f8c67bd55e93348f160d590ff9edf08904
+Author: Alan Stern 
+Date:   Fri Dec 11 16:20:20 2009 -0500
+
+    USB: check the endpoint type against the pipe type
+    
+    This patch (as1316) adds some error checking to usb_submit_urb().
+    It's conditional on CONFIG_USB_DEBUG, so it won't affect normal users.
+    The new check makes sure that the actual type of the endpoint
+    described by urb->pipe agrees with the type encoded in the pipe value.
+    
+    The USB error code documentation is updated to include the code
+    returned by the new check, and the usbfs SUBMITURB handler is updated
+    to use the correct pipe type when legacy user code tries to submit a
+    bulk transfer to an interrupt endpoint.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/usb/error-codes.txt b/Documentation/usb/error-codes.txt
+index 9cf83e8c27b8..d83703ea74b2 100644
+--- a/Documentation/usb/error-codes.txt
++++ b/Documentation/usb/error-codes.txt
+@@ -41,8 +41,8 @@ USB-specific:
+ 
+ -EFBIG		Host controller driver can't schedule that many ISO frames.
+ 
+--EPIPE		Specified endpoint is stalled.  For non-control endpoints,
+-		reset this status with usb_clear_halt().
++-EPIPE		The pipe type specified in the URB doesn't match the
++		endpoint's actual type.
+ 
+ -EMSGSIZE	(a) endpoint maxpacket size is zero; it is not usable
+ 		    in the current interface altsetting.
+@@ -60,6 +60,8 @@ USB-specific:
+ 
+ -EHOSTUNREACH	URB was rejected because the device is suspended.
+ 
++-ENOEXEC	A control URB doesn't contain a Setup packet.
++
+ 
+ **************************************************************************
+ *                   Error codes returned by in urb->status               *
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index a678186f218f..431d17287a86 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -1104,13 +1104,25 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 		case USB_ENDPOINT_XFER_CONTROL:
+ 		case USB_ENDPOINT_XFER_ISOC:
+ 			return -EINVAL;
+-		/* allow single-shot interrupt transfers, at bogus rates */
++		case USB_ENDPOINT_XFER_INT:
++			/* allow single-shot interrupt transfers */
++			uurb->type = USBDEVFS_URB_TYPE_INTERRUPT;
++			goto interrupt_urb;
+ 		}
+ 		uurb->number_of_packets = 0;
+ 		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
+ 			return -EINVAL;
+ 		break;
+ 
++	case USBDEVFS_URB_TYPE_INTERRUPT:
++		if (!usb_endpoint_xfer_int(&ep->desc))
++			return -EINVAL;
++ interrupt_urb:
++		uurb->number_of_packets = 0;
++		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
++			return -EINVAL;
++		break;
++
+ 	case USBDEVFS_URB_TYPE_ISO:
+ 		/* arbitrary limit */
+ 		if (uurb->number_of_packets < 1 ||
+@@ -1143,14 +1155,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 		uurb->buffer_length = totlen;
+ 		break;
+ 
+-	case USBDEVFS_URB_TYPE_INTERRUPT:
+-		uurb->number_of_packets = 0;
+-		if (!usb_endpoint_xfer_int(&ep->desc))
+-			return -EINVAL;
+-		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
+-			return -EINVAL;
+-		break;
+-
+ 	default:
+ 		return -EINVAL;
+ 	}
+diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
+index e7cae1334693..e2bd153cbd89 100644
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -387,6 +387,13 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 	{
+ 	unsigned int	orig_flags = urb->transfer_flags;
+ 	unsigned int	allowed;
++	static int pipetypes[4] = {
++		PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
++	};
++
++	/* Check that the pipe's type matches the endpoint's type */
++	if (usb_pipetype(urb->pipe) != pipetypes[xfertype])
++		return -EPIPE;		/* The most suitable error code :-) */
+ 
+ 	/* enforce simple/standard policy */
+ 	allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP |

commit 6d19c009cc780c63de25a046509ebc9473809fd6
+Author: Alan Stern 
+Date:   Fri Feb 12 12:21:11 2010 +0100
+
+    USB: implement non-tree resume ordering constraints for PCI host controllers
+    
+    This patch (as1331) adds non-tree ordering constraints needed for
+    proper resume of PCI USB host controllers from hibernation.  The main
+    issue is that non-high-speed devices must not be resumed before the
+    high-speed root hub, because it is the ehci_bus_resume() routine which
+    takes care of handing the device connection over to the companion
+    controller.  If the device resume is attempted before the handover
+    then the device won't be found and it will be treated as though it had
+    disconnected.
+    
+    The patch adds a new field to the usb_bus structure; for each
+    full/low-speed bus this field will contain a pointer to the companion
+    high-speed bus (if one exists).  It is used during normal device
+    resume; if the hs_companion pointer isn't NULL then we wait for the
+    root-hub device on the hs_companion bus.
+    
+    A secondary issue is that an EHCI controlller shouldn't be resumed
+    before any of its companions.  On some machines I have observed
+    handovers failing if the companion controller is reinitialized after
+    the handover.  Thus, the EHCI resume routine must wait for the
+    companion controllers to be resumed.
+    
+    The patch also fixes a small bug in usb_hcd_pci_probe(); an error path
+    jumps to the wrong label, causing a memory leak.
+    
+    [rjw: Fixed compilation for CONFIG_PM_SLEEP unset.]
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Greg Kroah-Hartman 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 60a45f1e3a67..f2f055eb6831 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1022,6 +1022,14 @@ static int usb_resume_device(struct usb_device *udev, pm_message_t msg)
+ 		goto done;
+ 	}
+ 
++	/* Non-root devices on a full/low-speed bus must wait for their
++	 * companion high-speed root hub, in case a handoff is needed.
++	 */
++	if (!(msg.event & PM_EVENT_AUTO) && udev->parent &&
++			udev->bus->hs_companion)
++		device_pm_wait_for_dev(&udev->dev,
++				&udev->bus->hs_companion->root_hub->dev);
++
+ 	if (udev->quirks & USB_QUIRK_RESET_RESUME)
+ 		udev->reset_resume = 1;
+ 
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index 2dcf906df569..15286533c15a 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -19,6 +19,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ 
+ #include 
+@@ -37,6 +38,122 @@
+ 
+ /* PCI-based HCs are common, but plenty of non-PCI HCs are used too */
+ 
++#ifdef CONFIG_PM_SLEEP
++
++/* Coordinate handoffs between EHCI and companion controllers
++ * during system resume
++ */
++
++static DEFINE_MUTEX(companions_mutex);
++
++#define CL_UHCI		PCI_CLASS_SERIAL_USB_UHCI
++#define CL_OHCI		PCI_CLASS_SERIAL_USB_OHCI
++#define CL_EHCI		PCI_CLASS_SERIAL_USB_EHCI
++
++enum companion_action {
++	SET_HS_COMPANION, CLEAR_HS_COMPANION, WAIT_FOR_COMPANIONS
++};
++
++static void companion_common(struct pci_dev *pdev, struct usb_hcd *hcd,
++		enum companion_action action)
++{
++	struct pci_dev		*companion;
++	struct usb_hcd		*companion_hcd;
++	unsigned int		slot = PCI_SLOT(pdev->devfn);
++
++	/* Iterate through other PCI functions in the same slot.
++	 * If pdev is OHCI or UHCI then we are looking for EHCI, and
++	 * vice versa.
++	 */
++	companion = NULL;
++	for (;;) {
++		companion = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, companion);
++		if (!companion)
++			break;
++		if (companion->bus != pdev->bus ||
++				PCI_SLOT(companion->devfn) != slot)
++			continue;
++
++		companion_hcd = pci_get_drvdata(companion);
++		if (!companion_hcd)
++			continue;
++
++		/* For SET_HS_COMPANION, store a pointer to the EHCI bus in
++		 * the OHCI/UHCI companion bus structure.
++		 * For CLEAR_HS_COMPANION, clear the pointer to the EHCI bus
++		 * in the OHCI/UHCI companion bus structure.
++		 * For WAIT_FOR_COMPANIONS, wait until the OHCI/UHCI
++		 * companion controllers have fully resumed.
++		 */
++
++		if ((pdev->class == CL_OHCI || pdev->class == CL_UHCI) &&
++				companion->class == CL_EHCI) {
++			/* action must be SET_HS_COMPANION */
++			dev_dbg(&companion->dev, "HS companion for %s\n",
++					dev_name(&pdev->dev));
++			hcd->self.hs_companion = &companion_hcd->self;
++
++		} else if (pdev->class == CL_EHCI &&
++				(companion->class == CL_OHCI ||
++				companion->class == CL_UHCI)) {
++			switch (action) {
++			case SET_HS_COMPANION:
++				dev_dbg(&pdev->dev, "HS companion for %s\n",
++						dev_name(&companion->dev));
++				companion_hcd->self.hs_companion = &hcd->self;
++				break;
++			case CLEAR_HS_COMPANION:
++				companion_hcd->self.hs_companion = NULL;
++				break;
++			case WAIT_FOR_COMPANIONS:
++				device_pm_wait_for_dev(&pdev->dev,
++						&companion->dev);
++				break;
++			}
++		}
++	}
++}
++
++static void set_hs_companion(struct pci_dev *pdev, struct usb_hcd *hcd)
++{
++	mutex_lock(&companions_mutex);
++	dev_set_drvdata(&pdev->dev, hcd);
++	companion_common(pdev, hcd, SET_HS_COMPANION);
++	mutex_unlock(&companions_mutex);
++}
++
++static void clear_hs_companion(struct pci_dev *pdev, struct usb_hcd *hcd)
++{
++	mutex_lock(&companions_mutex);
++	dev_set_drvdata(&pdev->dev, NULL);
++
++	/* If pdev is OHCI or UHCI, just clear its hs_companion pointer */
++	if (pdev->class == CL_OHCI || pdev->class == CL_UHCI)
++		hcd->self.hs_companion = NULL;
++
++	/* Otherwise search for companion buses and clear their pointers */
++	else
++		companion_common(pdev, hcd, CLEAR_HS_COMPANION);
++	mutex_unlock(&companions_mutex);
++}
++
++static void wait_for_companions(struct pci_dev *pdev, struct usb_hcd *hcd)
++{
++	/* Only EHCI controllers need to wait.
++	 * No locking is needed because a controller cannot be resumed
++	 * while one of its companions is getting unbound.
++	 */
++	if (pdev->class == CL_EHCI)
++		companion_common(pdev, hcd, WAIT_FOR_COMPANIONS);
++}
++
++#else /* !CONFIG_PM_SLEEP */
++
++static inline void set_hs_companion(struct pci_dev *d, struct usb_hcd *h) {}
++static inline void clear_hs_companion(struct pci_dev *d, struct usb_hcd *h) {}
++static inline void wait_for_companions(struct pci_dev *d, struct usb_hcd *h) {}
++
++#endif /* !CONFIG_PM_SLEEP */
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+@@ -123,7 +240,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ 		if (region == PCI_ROM_RESOURCE) {
+ 			dev_dbg(&dev->dev, "no i/o regions available\n");
+ 			retval = -EBUSY;
+-			goto err1;
++			goto err2;
+ 		}
+ 	}
+ 
+@@ -132,6 +249,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ 	retval = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED);
+ 	if (retval != 0)
+ 		goto err4;
++	set_hs_companion(dev, hcd);
+ 	return retval;
+ 
+  err4:
+@@ -142,6 +260,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ 	} else
+ 		release_region(hcd->rsrc_start, hcd->rsrc_len);
+  err2:
++	clear_hs_companion(dev, hcd);
+ 	usb_put_hcd(hcd);
+  err1:
+ 	pci_disable_device(dev);
+@@ -180,6 +299,7 @@ void usb_hcd_pci_remove(struct pci_dev *dev)
+ 	} else {
+ 		release_region(hcd->rsrc_start, hcd->rsrc_len);
+ 	}
++	clear_hs_companion(dev, hcd);
+ 	usb_put_hcd(hcd);
+ 	pci_disable_device(dev);
+ }
+@@ -344,6 +464,11 @@ static int resume_common(struct device *dev, bool hibernated)
+ 	clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+ 
+ 	if (hcd->driver->pci_resume) {
++		/* This call should be made only during system resume,
++		 * not during runtime resume.
++		 */
++		wait_for_companions(pci_dev, hcd);
++
+ 		retval = hcd->driver->pci_resume(hcd, hibernated);
+ 		if (retval) {
+ 			dev_err(dev, "PCI post-resume error %d!\n", retval);
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index d7ace1b80f09..332eaea61021 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -339,6 +339,7 @@ struct usb_bus {
+ 
+ 	struct usb_devmap devmap;	/* device address allocation map */
+ 	struct usb_device *root_hub;	/* Root hub */
++	struct usb_bus *hs_companion;	/* Companion EHCI bus, if any */
+ 	struct list_head bus_list;	/* list of busses */
+ 
+ 	int bandwidth_allocated;	/* on this bus: how much of the time

commit ee37e09d81a4acf328f68189af12f116401f8c0f
+Author: Alan Stern 
+Date:   Fri Feb 12 12:13:55 2010 -0500
+
+    [SCSI] fix duplicate removal on error path in scsi_sysfs_add_sdev
+    
+    This patch (as1335) fixes a bug in scsi_sysfs_add_sdev().  Its callers
+    always remove the device if anything goes wrong, so it should never
+    remove the device.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
+index 5a065055e68a..a4936c4e2f46 100644
+--- a/drivers/scsi/scsi_sysfs.c
++++ b/drivers/scsi/scsi_sysfs.c
+@@ -878,7 +878,8 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
+ 	struct request_queue *rq = sdev->request_queue;
+ 	struct scsi_target *starget = sdev->sdev_target;
+ 
+-	if ((error = scsi_device_set_state(sdev, SDEV_RUNNING)) != 0)
++	error = scsi_device_set_state(sdev, SDEV_RUNNING);
++	if (error)
+ 		return error;
+ 
+ 	error = scsi_target_add(starget);
+@@ -889,13 +890,13 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
+ 	error = device_add(&sdev->sdev_gendev);
+ 	if (error) {
+ 		printk(KERN_INFO "error 1\n");
+-		goto out_remove;
++		return error;
+ 	}
+ 	error = device_add(&sdev->sdev_dev);
+ 	if (error) {
+ 		printk(KERN_INFO "error 2\n");
+ 		device_del(&sdev->sdev_gendev);
+-		goto out_remove;
++		return error;
+ 	}
+ 	transport_add_device(&sdev->sdev_gendev);
+ 	sdev->is_visible = 1;
+@@ -910,14 +911,14 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
+ 	else
+ 		error = device_create_file(&sdev->sdev_gendev, &dev_attr_queue_depth);
+ 	if (error)
+-		goto out_remove;
++		return error;
+ 
+ 	if (sdev->host->hostt->change_queue_type)
+ 		error = device_create_file(&sdev->sdev_gendev, &sdev_attr_queue_type_rw);
+ 	else
+ 		error = device_create_file(&sdev->sdev_gendev, &dev_attr_queue_type);
+ 	if (error)
+-		goto out_remove;
++		return error;
+ 
+ 	error = bsg_register_queue(rq, &sdev->sdev_gendev, NULL, NULL);
+ 
+@@ -933,16 +934,11 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
+ 			error = device_create_file(&sdev->sdev_gendev,
+ 					sdev->host->hostt->sdev_attrs[i]);
+ 			if (error)
+-				goto out_remove;
++				return error;
+ 		}
+ 	}
+ 
+-	return 0;
+-
+- out_remove:
+-	__scsi_remove_device(sdev);
+ 	return error;
+-
+ }
+ 
+ void __scsi_remove_device(struct scsi_device *sdev)

commit d5469119f0098881ab7f991990ef4f81ef13a194
+Author: Alan Stern 
+Date:   Fri Feb 12 12:13:39 2010 -0500
+
+    [SCSI] fix refcounting bug in scsi_get_host_dev
+    
+    This patch (as1334) fixes a bug in scsi_get_host_dev().  It
+    incorrectly calls get_device() on the new device's target.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+index 60b262d66b5b..f697229ae5a9 100644
+--- a/drivers/scsi/scsi_scan.c
++++ b/drivers/scsi/scsi_scan.c
+@@ -1909,10 +1909,9 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)
+ 		goto out;
+ 
+ 	sdev = scsi_alloc_sdev(starget, 0, NULL);
+-	if (sdev) {
+-		sdev->sdev_gendev.parent = get_device(&starget->dev);
++	if (sdev)
+ 		sdev->borken = 0;
+-	} else
++	else
+ 		scsi_target_reap(starget);
+ 	put_device(&starget->dev);
+  out:

commit 75f8ee8e01a6c96652f27da40d4bdac9e2e485f0
+Author: Alan Stern 
+Date:   Fri Feb 12 12:13:31 2010 -0500
+
+    [SCSI] fix memory leak in scsi_report_lun_scan
+    
+    This patch (as1333) fixes a bug in scsi_report_lun_scan().  If a
+    newly-allocated device can't be used, it should be deleted.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+index 012f73a96880..60b262d66b5b 100644
+--- a/drivers/scsi/scsi_scan.c
++++ b/drivers/scsi/scsi_scan.c
+@@ -1339,8 +1339,10 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
+ 		sdev = scsi_alloc_sdev(starget, 0, NULL);
+ 		if (!sdev)
+ 			return 0;
+-		if (scsi_device_get(sdev))
++		if (scsi_device_get(sdev)) {
++			__scsi_remove_device(sdev);
+ 			return 0;
++		}
+ 	}
+ 
+ 	sprintf(devname, "host %d channel %d id %d",

commit 49d0f078f494b9d81e820a13dd8093a9bfb0b6b1
+Author: Alan Stern 
+Date:   Fri Jan 8 11:18:38 2010 -0500
+
+    USB: add missing delay during remote wakeup
+    
+    This patch (as1330) fixes a bug in khbud's handling of remote
+    wakeups.  When a device sends a remote-wakeup request, the parent hub
+    (or the host controller driver, for directly attached devices) begins
+    the resume sequence and notifies khubd when the sequence finishes.  At
+    this point the port's SUSPEND feature is automatically turned off.
+    
+    However the device needs an additional 10-ms resume-recovery time
+    (TRSMRCY in the USB spec).  Khubd does not wait for this delay if the
+    SUSPEND feature is off, and as a result some devices fail to behave
+    properly following a remote wakeup.  This patch adds the missing
+    delay to the remote-wakeup path.
+    
+    It also extends the resume-signalling delay used by ehci-hcd and
+    uhci-hcd from 20 ms (the value in the spec) to 25 ms (the value we use
+    for non-remote-wakeup resumes).  The extra time appears to help some
+    devices.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Cc: Rickard Bellini 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 0cec6caf6e9b..b9f5fcd713e2 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -3347,6 +3347,9 @@ static void hub_events(void)
+ 					USB_PORT_FEAT_C_SUSPEND);
+ 				udev = hdev->children[i-1];
+ 				if (udev) {
++					/* TRSMRCY = 10 msec */
++					msleep(10);
++
+ 					usb_lock_device(udev);
+ 					ret = remote_wakeup(hdev->
+ 							children[i-1]);
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 5859522d6edd..1ec3857f22e6 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -787,9 +787,10 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 
+ 			/* start 20 msec resume signaling from this port,
+ 			 * and make khubd collect PORT_STAT_C_SUSPEND to
+-			 * stop that signaling.
++			 * stop that signaling.  Use 5 ms extra for safety,
++			 * like usb_port_resume() does.
+ 			 */
+-			ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
++			ehci->reset_done[i] = jiffies + msecs_to_jiffies(25);
+ 			ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
+ 			mod_timer(&hcd->rh_timer, ehci->reset_done[i]);
+ 		}
+diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
+index 885b585360b9..8270055848ca 100644
+--- a/drivers/usb/host/uhci-hub.c
++++ b/drivers/usb/host/uhci-hub.c
+@@ -167,7 +167,7 @@ static void uhci_check_ports(struct uhci_hcd *uhci)
+ 				/* Port received a wakeup request */
+ 				set_bit(port, &uhci->resuming_ports);
+ 				uhci->ports_timeout = jiffies +
+-						msecs_to_jiffies(20);
++						msecs_to_jiffies(25);
+ 
+ 				/* Make sure we see the port again
+ 				 * after the resuming period is over. */

commit cec3a53c7fe794237b582e8e77fc0e48465e65ee
+Author: Alan Stern 
+Date:   Fri Jan 8 11:18:20 2010 -0500
+
+    USB: EHCI & UHCI: fix race between root-hub suspend and port resume
+    
+    This patch (as1321) fixes a problem with EHCI and UHCI root-hub
+    suspends: If the suspend occurs while a port is trying to resume, the
+    resume doesn't finish and simply gets lost.  When remote wakeup is
+    enabled, this is undesirable behavior.
+    
+    The patch checks first to see if any port resumes are in progress, and
+    if they are then it fails the root-hub suspend with -EBUSY.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 2c6571c05f35..c75d9270c752 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -120,9 +120,26 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 	del_timer_sync(&ehci->watchdog);
+ 	del_timer_sync(&ehci->iaa_watchdog);
+ 
+-	port = HCS_N_PORTS (ehci->hcs_params);
+ 	spin_lock_irq (&ehci->lock);
+ 
++	/* Once the controller is stopped, port resumes that are already
++	 * in progress won't complete.  Hence if remote wakeup is enabled
++	 * for the root hub and any ports are in the middle of a resume or
++	 * remote wakeup, we must fail the suspend.
++	 */
++	if (hcd->self.root_hub->do_remote_wakeup) {
++		port = HCS_N_PORTS(ehci->hcs_params);
++		while (port--) {
++			if (ehci->reset_done[port] != 0) {
++				spin_unlock_irq(&ehci->lock);
++				ehci_dbg(ehci, "suspend failed because "
++						"port %d is resuming\n",
++						port + 1);
++				return -EBUSY;
++			}
++		}
++	}
++
+ 	/* stop schedules, clean any completed work */
+ 	if (HC_IS_RUNNING(hcd->state)) {
+ 		ehci_quiesce (ehci);
+@@ -138,6 +155,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 	 */
+ 	ehci->bus_suspended = 0;
+ 	ehci->owned_ports = 0;
++	port = HCS_N_PORTS(ehci->hcs_params);
+ 	while (port--) {
+ 		u32 __iomem	*reg = &ehci->regs->port_status [port];
+ 		u32		t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 5cd0e48f67fb..99cd00fd3514 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -749,7 +749,20 @@ static int uhci_rh_suspend(struct usb_hcd *hcd)
+ 	spin_lock_irq(&uhci->lock);
+ 	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
+ 		rc = -ESHUTDOWN;
+-	else if (!uhci->dead)
++	else if (uhci->dead)
++		;		/* Dead controllers tell no tales */
++
++	/* Once the controller is stopped, port resumes that are already
++	 * in progress won't complete.  Hence if remote wakeup is enabled
++	 * for the root hub and any ports are in the middle of a resume or
++	 * remote wakeup, we must fail the suspend.
++	 */
++	else if (hcd->self.root_hub->do_remote_wakeup &&
++			uhci->resuming_ports) {
++		dev_dbg(uhci_dev(uhci), "suspend failed because a port "
++				"is resuming\n");
++		rc = -EBUSY;
++	} else
+ 		suspend_rh(uhci, UHCI_RH_SUSPENDED);
+ 	spin_unlock_irq(&uhci->lock);
+ 	return rc;

commit 1b9a38bfa6e664ff02511314f5586d711c83cc91
+Author: Alan Stern 
+Date:   Fri Jan 8 11:17:55 2010 -0500
+
+    USB: EHCI: fix handling of unusual interrupt intervals
+    
+    This patch (as1320) fixes two problems related to interrupt-URB
+    scheduling in ehci-hcd.
+    
+            URBs with an interval of 2 or 4 microframes aren't handled.
+            For the time being, the patch reduces to interval to 1 uframe.
+    
+            URBs are constrained to have an interval no larger than 1024
+            frames by usb_submit_urb().  But some EHCI controllers allow
+            use of a schedule as short as 256 frames; for these
+            controllers we may have to decrease the interval to the
+            actual schedule length.
+    
+    The second problem isn't very significant since few devices expose
+    interrupt endpoints with an interval larger than 256 frames.  But the
+    first problem is critical; it will prevent the kernel from working
+    with devices having interrupt intervals of 2 or 4 uframes.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Tested-by: Glynn Farrow 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index a427d3b00634..89521775c567 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -849,9 +849,10 @@ qh_make (
+ 				 * But interval 1 scheduling is simpler, and
+ 				 * includes high bandwidth.
+ 				 */
+-				dbg ("intr period %d uframes, NYET!",
+-						urb->interval);
+-				goto done;
++				urb->interval = 1;
++			} else if (qh->period > ehci->periodic_size) {
++				qh->period = ehci->periodic_size;
++				urb->interval = qh->period << 3;
+ 			}
+ 		} else {
+ 			int		think_time;
+@@ -874,6 +875,10 @@ qh_make (
+ 					usb_calc_bus_time (urb->dev->speed,
+ 					is_input, 0, max_packet (maxp)));
+ 			qh->period = urb->interval;
++			if (qh->period > ehci->periodic_size) {
++				qh->period = ehci->periodic_size;
++				urb->interval = qh->period;
++			}
+ 		}
+ 	}
+ 

commit a91b593edd4b3e8aa91f671b763b27b8119eb49d
+Author: Alan Stern 
+Date:   Tue Dec 22 23:16:32 2009 -0500
+
+    USB: fix bitmask merge error
+    
+    This patch adds a mask bit which was mistakenly omitted from the
+    as1311 patch (usb-storage: add BAD_SENSE flag).
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 5a53d4f0dd11..e9f995486ec1 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -434,7 +434,8 @@ static void adjust_quirks(struct us_data *us)
+ 	u16 vid = le16_to_cpu(us->pusb_dev->descriptor.idVendor);
+ 	u16 pid = le16_to_cpu(us->pusb_dev->descriptor.idProduct);
+ 	unsigned f = 0;
+-	unsigned int mask = (US_FL_SANE_SENSE | US_FL_FIX_CAPACITY |
++	unsigned int mask = (US_FL_SANE_SENSE | US_FL_BAD_SENSE |
++			US_FL_FIX_CAPACITY |
+ 			US_FL_CAPACITY_HEURISTICS | US_FL_IGNORE_DEVICE |
+ 			US_FL_NOT_LOCKABLE | US_FL_MAX_SECTORS_64 |
+ 			US_FL_CAPACITY_OK | US_FL_IGNORE_RESIDUE |

commit da307123c621b01cce147a4be313d8a754674f63
+Author: Alan Stern 
+Date:   Tue Dec 8 15:54:44 2009 -0500
+
+    USB: fix bugs in usb_(de)authorize_device
+    
+    This patch (as1315) fixes some bugs in the USB core authorization
+    code:
+    
+            usb_deauthorize_device() should deallocate the device strings
+            instead of leaking them, and it should invoke
+            usb_destroy_configuration() (which does proper reference
+            counting) instead of freeing the config information directly.
+    
+            usb_authorize_device() shouldn't change the device strings
+            until it knows that the authorization will succeed, and it should
+            autosuspend the device at the end (having autoresumed the
+            device at the start).
+    
+            Because the device strings can be changed, the sysfs routines
+            to display the strings must protect the string pointers by
+            locking the device.
+    
+    Signed-off-by: Alan Stern 
+    CC: Inaky Perez-Gonzalez 
+    Acked-by: David Vrabel 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 28738fa17afb..0cec6caf6e9b 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1849,21 +1849,23 @@ int usb_new_device(struct usb_device *udev)
+  */
+ int usb_deauthorize_device(struct usb_device *usb_dev)
+ {
+-	unsigned cnt;
+ 	usb_lock_device(usb_dev);
+ 	if (usb_dev->authorized == 0)
+ 		goto out_unauthorized;
++
+ 	usb_dev->authorized = 0;
+ 	usb_set_configuration(usb_dev, -1);
++
++	kfree(usb_dev->product);
+ 	usb_dev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL);
++	kfree(usb_dev->manufacturer);
+ 	usb_dev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL);
++	kfree(usb_dev->serial);
+ 	usb_dev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL);
+-	kfree(usb_dev->config);
+-	usb_dev->config = NULL;
+-	for (cnt = 0; cnt < usb_dev->descriptor.bNumConfigurations; cnt++)
+-		kfree(usb_dev->rawdescriptors[cnt]);
++
++	usb_destroy_configuration(usb_dev);
+ 	usb_dev->descriptor.bNumConfigurations = 0;
+-	kfree(usb_dev->rawdescriptors);
++
+ out_unauthorized:
+ 	usb_unlock_device(usb_dev);
+ 	return 0;
+@@ -1873,15 +1875,11 @@ int usb_deauthorize_device(struct usb_device *usb_dev)
+ int usb_authorize_device(struct usb_device *usb_dev)
+ {
+ 	int result = 0, c;
++
+ 	usb_lock_device(usb_dev);
+ 	if (usb_dev->authorized == 1)
+ 		goto out_authorized;
+-	kfree(usb_dev->product);
+-	usb_dev->product = NULL;
+-	kfree(usb_dev->manufacturer);
+-	usb_dev->manufacturer = NULL;
+-	kfree(usb_dev->serial);
+-	usb_dev->serial = NULL;
++
+ 	result = usb_autoresume_device(usb_dev);
+ 	if (result < 0) {
+ 		dev_err(&usb_dev->dev,
+@@ -1894,6 +1892,14 @@ int usb_authorize_device(struct usb_device *usb_dev)
+ 			"authorization: %d\n", result);
+ 		goto error_device_descriptor;
+ 	}
++
++	kfree(usb_dev->product);
++	usb_dev->product = NULL;
++	kfree(usb_dev->manufacturer);
++	usb_dev->manufacturer = NULL;
++	kfree(usb_dev->serial);
++	usb_dev->serial = NULL;
++
+ 	usb_dev->authorized = 1;
+ 	result = usb_enumerate_device(usb_dev);
+ 	if (result < 0)
+@@ -1912,8 +1918,10 @@ int usb_authorize_device(struct usb_device *usb_dev)
+ 		}
+ 	}
+ 	dev_info(&usb_dev->dev, "authorized to connect\n");
++
+ error_enumerate:
+ error_device_descriptor:
++	usb_autosuspend_device(usb_dev);
+ error_autoresume:
+ out_authorized:
+ 	usb_unlock_device(usb_dev);	// complements locktree
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 15477008b631..485edf937f25 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -82,9 +82,13 @@ static ssize_t  show_##name(struct device *dev,				\
+ 		struct device_attribute *attr, char *buf)		\
+ {									\
+ 	struct usb_device *udev;					\
++	int retval;							\
+ 									\
+ 	udev = to_usb_device(dev);					\
+-	return sprintf(buf, "%s\n", udev->name);			\
++	usb_lock_device(udev);						\
++	retval = sprintf(buf, "%s\n", udev->name);			\
++	usb_unlock_device(udev);					\
++	return retval;							\
+ }									\
+ static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
+ 

commit 8d8558d10806b7e805cb80df867ebb0a453d4765
+Author: Alan Stern 
+Date:   Tue Dec 8 15:50:41 2009 -0500
+
+    USB: rename usb_configure_device
+    
+    This patch (as1314) renames usb_configure_device() and
+    usb_configure_device_otg() in the hub driver.  Neither name is
+    appropriate because these routines enumerate devices, they don't
+    configure them.  That's handled by usb_choose_configuration() and
+    usb_set_configuration().
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 06af970e1064..28738fa17afb 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1658,12 +1658,12 @@ static inline void announce_device(struct usb_device *udev) { }
+ #endif
+ 
+ /**
+- * usb_configure_device_otg - FIXME (usbcore-internal)
++ * usb_enumerate_device_otg - FIXME (usbcore-internal)
+  * @udev: newly addressed device (in ADDRESS state)
+  *
+- * Do configuration for On-The-Go devices
++ * Finish enumeration for On-The-Go devices
+  */
+-static int usb_configure_device_otg(struct usb_device *udev)
++static int usb_enumerate_device_otg(struct usb_device *udev)
+ {
+ 	int err = 0;
+ 
+@@ -1734,7 +1734,7 @@ static int usb_configure_device_otg(struct usb_device *udev)
+ 
+ 
+ /**
+- * usb_configure_device - Detect and probe device intfs/otg (usbcore-internal)
++ * usb_enumerate_device - Read device configs/intfs/otg (usbcore-internal)
+  * @udev: newly addressed device (in ADDRESS state)
+  *
+  * This is only called by usb_new_device() and usb_authorize_device()
+@@ -1745,7 +1745,7 @@ static int usb_configure_device_otg(struct usb_device *udev)
+  * the string descriptors, as they will be errored out by the device
+  * until it has been authorized.
+  */
+-static int usb_configure_device(struct usb_device *udev)
++static int usb_enumerate_device(struct usb_device *udev)
+ {
+ 	int err;
+ 
+@@ -1769,7 +1769,7 @@ static int usb_configure_device(struct usb_device *udev)
+ 						      udev->descriptor.iManufacturer);
+ 		udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber);
+ 	}
+-	err = usb_configure_device_otg(udev);
++	err = usb_enumerate_device_otg(udev);
+ fail:
+ 	return err;
+ }
+@@ -1779,8 +1779,8 @@ static int usb_configure_device(struct usb_device *udev)
+  * usb_new_device - perform initial device setup (usbcore-internal)
+  * @udev: newly addressed device (in ADDRESS state)
+  *
+- * This is called with devices which have been enumerated, but not yet
+- * configured.  The device descriptor is available, but not descriptors
++ * This is called with devices which have been detected but not fully
++ * enumerated.  The device descriptor is available, but not descriptors
+  * for any device configuration.  The caller must have locked either
+  * the parent hub (if udev is a normal device) or else the
+  * usb_bus_list_lock (if udev is a root hub).  The parent's pointer to
+@@ -1803,8 +1803,8 @@ int usb_new_device(struct usb_device *udev)
+ 	if (udev->parent)
+ 		usb_autoresume_device(udev->parent);
+ 
+-	usb_detect_quirks(udev);		/* Determine quirks */
+-	err = usb_configure_device(udev);	/* detect & probe dev/intfs */
++	usb_detect_quirks(udev);
++	err = usb_enumerate_device(udev);	/* Read descriptors */
+ 	if (err < 0)
+ 		goto fail;
+ 	dev_dbg(&udev->dev, "udev %d, busnum %d, minor = %d\n",
+@@ -1895,9 +1895,9 @@ int usb_authorize_device(struct usb_device *usb_dev)
+ 		goto error_device_descriptor;
+ 	}
+ 	usb_dev->authorized = 1;
+-	result = usb_configure_device(usb_dev);
++	result = usb_enumerate_device(usb_dev);
+ 	if (result < 0)
+-		goto error_configure;
++		goto error_enumerate;
+ 	/* Choose and set the configuration.  This registers the interfaces
+ 	 * with the driver core and lets interface drivers bind to them.
+ 	 */
+@@ -1912,7 +1912,7 @@ int usb_authorize_device(struct usb_device *usb_dev)
+ 		}
+ 	}
+ 	dev_info(&usb_dev->dev, "authorized to connect\n");
+-error_configure:
++error_enumerate:
+ error_device_descriptor:
+ error_autoresume:
+ out_authorized:

commit baf67741bf52b985e318bed3c4acadcda5351e08
+Author: Alan Stern 
+Date:   Tue Dec 8 15:49:48 2009 -0500
+
+    USB: power management documentation update
+    
+    This patch (as1313) updates the documentation concerning USB power
+    management.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb
+index deb6b489e4e5..a07c0f366f91 100644
+--- a/Documentation/ABI/testing/sysfs-bus-usb
++++ b/Documentation/ABI/testing/sysfs-bus-usb
+@@ -21,25 +21,27 @@ Contact:	Alan Stern 
+ Description:
+ 		Each USB device directory will contain a file named
+ 		power/level.  This file holds a power-level setting for
+-		the device, one of "on", "auto", or "suspend".
++		the device, either "on" or "auto".
+ 
+ 		"on" means that the device is not allowed to autosuspend,
+ 		although normal suspends for system sleep will still
+ 		be honored.  "auto" means the device will autosuspend
+ 		and autoresume in the usual manner, according to the
+-		capabilities of its driver.  "suspend" means the device
+-		is forced into a suspended state and it will not autoresume
+-		in response to I/O requests.  However remote-wakeup requests
+-		from the device may still be enabled (the remote-wakeup
+-		setting is controlled separately by the power/wakeup
+-		attribute).
++		capabilities of its driver.
+ 
+ 		During normal use, devices should be left in the "auto"
+-		level.  The other levels are meant for administrative uses.
++		level.  The "on" level is meant for administrative uses.
+ 		If you want to suspend a device immediately but leave it
+ 		free to wake up in response to I/O requests, you should
+ 		write "0" to power/autosuspend.
+ 
++		Device not capable of proper suspend and resume should be
++		left in the "on" level.  Although the USB spec requires
++		devices to support suspend/resume, many of them do not.
++		In fact so many don't that by default, the USB core
++		initializes all non-hub devices in the "on" level.  Some
++		drivers may change this setting when they are bound.
++
+ What:		/sys/bus/usb/devices/.../power/persist
+ Date:		May 2007
+ KernelVersion:	2.6.23
+diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt
+index c7c1dc2f8017..3bf6818c8cf5 100644
+--- a/Documentation/usb/power-management.txt
++++ b/Documentation/usb/power-management.txt
+@@ -71,12 +71,10 @@ being accessed through sysfs, then it definitely is idle.
+ 	Forms of dynamic PM
+ 	-------------------
+ 
+-Dynamic suspends can occur in two ways: manual and automatic.
+-"Manual" means that the user has told the kernel to suspend a device,
+-whereas "automatic" means that the kernel has decided all by itself to
+-suspend a device.  Automatic suspend is called "autosuspend" for
+-short.  In general, a device won't be autosuspended unless it has been
+-idle for some minimum period of time, the so-called idle-delay time.
++Dynamic suspends occur when the kernel decides to suspend an idle
++device.  This is called "autosuspend" for short.  In general, a device
++won't be autosuspended unless it has been idle for some minimum period
++of time, the so-called idle-delay time.
+ 
+ Of course, nothing the kernel does on its own initiative should
+ prevent the computer or its devices from working properly.  If a
+@@ -96,10 +94,11 @@ idle.
+ We can categorize power management events in two broad classes:
+ external and internal.  External events are those triggered by some
+ agent outside the USB stack: system suspend/resume (triggered by
+-userspace), manual dynamic suspend/resume (also triggered by
+-userspace), and remote wakeup (triggered by the device).  Internal
+-events are those triggered within the USB stack: autosuspend and
+-autoresume.
++userspace), manual dynamic resume (also triggered by userspace), and
++remote wakeup (triggered by the device).  Internal events are those
++triggered within the USB stack: autosuspend and autoresume.  Note that
++all dynamic suspend events are internal; external agents are not
++allowed to issue dynamic suspends.
+ 
+ 
+ 	The user interface for dynamic PM
+@@ -145,9 +144,9 @@ relevant attribute files are: wakeup, level, and autosuspend.
+ 		number of seconds the device should remain idle before
+ 		the kernel will autosuspend it (the idle-delay time).
+ 		The default is 2.  0 means to autosuspend as soon as
+-		the device becomes idle, and -1 means never to
+-		autosuspend.  You can write a number to the file to
+-		change the autosuspend idle-delay time.
++		the device becomes idle, and negative values mean
++		never to autosuspend.  You can write a number to the
++		file to change the autosuspend idle-delay time.
+ 
+ Writing "-1" to power/autosuspend and writing "on" to power/level do
+ essentially the same thing -- they both prevent the device from being
+@@ -377,9 +376,9 @@ the device hasn't been idle for long enough, a delayed workqueue
+ routine is automatically set up to carry out the operation when the
+ autosuspend idle-delay has expired.
+ 
+-Autoresume attempts also can fail.  This will happen if power/level is
+-set to "suspend" or if the device doesn't manage to resume properly.
+-Unlike autosuspend, there's no delay for an autoresume.
++Autoresume attempts also can fail, although failure would mean that
++the device is no longer present or operating properly.  Unlike
++autosuspend, there's no delay for an autoresume.
+ 
+ 
+ 	Other parts of the driver interface
+@@ -527,13 +526,3 @@ succeed, it may still remain active and thus cause the system to
+ resume as soon as the system suspend is complete.  Or the remote
+ wakeup may fail and get lost.  Which outcome occurs depends on timing
+ and on the hardware and firmware design.
+-
+-More interestingly, a device might undergo a manual resume or
+-autoresume during system suspend.  With current kernels this shouldn't
+-happen, because manual resumes must be initiated by userspace and
+-autoresumes happen in response to I/O requests, but all user processes
+-and I/O should be quiescent during a system suspend -- thanks to the
+-freezer.  However there are plans to do away with the freezer, which
+-would mean these things would become possible.  If and when this comes
+-about, the USB core will carefully arrange matters so that either type
+-of resume will block until the entire system has resumed.

commit f1212ae1332b95fe3bafa7b5c063dd8e473247cf
+Author: Alan Stern 
+Date:   Tue Dec 22 20:43:40 2009 +0100
+
+    PM: Runtime PM documentation update
+    
+    This patch (as1318) updates the runtime PM documentation, adding a
+    section discussing the interaction between runtime PM and system sleep.
+    
+    [rjw: Rebased and made it agree with the other updates better.]
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt
+index 7b5ab2701247..356fd86f4ea8 100644
+--- a/Documentation/power/runtime_pm.txt
++++ b/Documentation/power/runtime_pm.txt
+@@ -381,3 +381,53 @@ incremented by the core before executing ->probe() and ->remove().  Still, it
+ may be desirable to suspend the device as soon as ->probe() or ->remove() has
+ finished, so the PM core uses pm_runtime_idle_sync() to invoke the
+ subsystem-level idle callback for the device at that time.
++
++6. Run-time PM and System Sleep
++
++Run-time PM and system sleep (i.e., system suspend and hibernation, also known
++as suspend-to-RAM and suspend-to-disk) interact with each other in a couple of
++ways.  If a device is active when a system sleep starts, everything is
++straightforward.  But what should happen if the device is already suspended?
++
++The device may have different wake-up settings for run-time PM and system sleep.
++For example, remote wake-up may be enabled for run-time suspend but disallowed
++for system sleep (device_may_wakeup(dev) returns 'false').  When this happens,
++the subsystem-level system suspend callback is responsible for changing the
++device's wake-up setting (it may leave that to the device driver's system
++suspend routine).  It may be necessary to resume the device and suspend it again
++in order to do so.  The same is true if the driver uses different power levels
++or other settings for run-time suspend and system sleep.
++
++During system resume, devices generally should be brought back to full power,
++even if they were suspended before the system sleep began.  There are several
++reasons for this, including:
++
++  * The device might need to switch power levels, wake-up settings, etc.
++
++  * Remote wake-up events might have been lost by the firmware.
++
++  * The device's children may need the device to be at full power in order
++    to resume themselves.
++
++  * The driver's idea of the device state may not agree with the device's
++    physical state.  This can happen during resume from hibernation.
++
++  * The device might need to be reset.
++
++  * Even though the device was suspended, if its usage counter was > 0 then most
++    likely it would need a run-time resume in the near future anyway.
++
++  * Always going back to full power is simplest.
++
++If the device was suspended before the sleep began, then its run-time PM status
++will have to be updated to reflect the actual post-system sleep status.  The way
++to do this is:
++
++	pm_runtime_disable(dev);
++	pm_runtime_set_active(dev);
++	pm_runtime_enable(dev);
++
++The PM core always increments the run-time usage counter before calling the
++->prepare() callback and decrements it after calling the ->complete() callback.
++Hence disabling run-time PM temporarily like this will not cause any run-time
++suspend callbacks to be lost.

commit aa0baaef97c89de2ef216fcc017215ee01662a10
+Author: Alan Stern 
+Date:   Mon Dec 21 02:46:11 2009 +0100
+
+    PM: Use pm_runtime_put_sync in system resume
+    
+    This patch (as1317) fixes a bug in the PM core.  When a device is
+    resumed following a system sleep, the core decrements the device's
+    runtime PM usage counter but doesn't issue an idle notification if the
+    counter reaches 0.  This could prevent an otherwise unused device from
+    being runtime-suspended again after the system sleep.
+    
+    The fix is to call pm_runtime_put_sync() instead of
+    pm_runtime_put_noidle().
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
+index 8052dafc0ba9..48adf80926a0 100644
+--- a/drivers/base/power/main.c
++++ b/drivers/base/power/main.c
+@@ -607,7 +607,7 @@ static void dpm_complete(pm_message_t state)
+ 			mutex_unlock(&dpm_list_mtx);
+ 
+ 			device_complete(dev, state);
+-			pm_runtime_put_noidle(dev);
++			pm_runtime_put_sync(dev);
+ 
+ 			mutex_lock(&dpm_list_mtx);
+ 		}
+@@ -880,7 +880,7 @@ static int dpm_prepare(pm_message_t state)
+ 		pm_runtime_get_noresume(dev);
+ 		if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) {
+ 			/* Wake-up requested during system sleep transition. */
+-			pm_runtime_put_noidle(dev);
++			pm_runtime_put_sync(dev);
+ 			error = -EBUSY;
+ 		} else {
+ 			error = device_prepare(dev, state);

commit 1d531c14d2ed4b24472a4d773f00ed6d1cd34ee7
+Author: Alan Stern 
+Date:   Sun Dec 13 20:28:30 2009 +0100
+
+    PM: allow for usage_count > 0 in pm_runtime_get()
+    
+    This patch (as1308c) fixes __pm_runtime_get().  Currently the routine
+    will resume a device if the prior usage count was 0.  But this isn't
+    right; thanks to pm_runtime_get_noresume() the usage count can be
+    positive even while the device is suspended.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
+index 5a01ecef4af3..40d7720a4b21 100644
+--- a/drivers/base/power/runtime.c
++++ b/drivers/base/power/runtime.c
+@@ -701,15 +701,15 @@ EXPORT_SYMBOL_GPL(pm_request_resume);
+  * @dev: Device to handle.
+  * @sync: If set and the device is suspended, resume it synchronously.
+  *
+- * Increment the usage count of the device and if it was zero previously,
+- * resume it or submit a resume request for it, depending on the value of @sync.
++ * Increment the usage count of the device and resume it or submit a resume
++ * request for it, depending on the value of @sync.
+  */
+ int __pm_runtime_get(struct device *dev, bool sync)
+ {
+-	int retval = 1;
++	int retval;
+ 
+-	if (atomic_add_return(1, &dev->power.usage_count) == 1)
+-		retval = sync ? pm_runtime_resume(dev) : pm_request_resume(dev);
++	atomic_inc(&dev->power.usage_count);
++	retval = sync ? pm_runtime_resume(dev) : pm_request_resume(dev);
+ 
+ 	return retval;
+ }

commit f3f6faa9edf67c1018270793e0547b0f81abb47e
+Author: Alan Stern 
+Date:   Mon Dec 7 16:47:43 2009 -0500
+
+    USB: usb-storage: fix bug in fill_inquiry
+    
+    This patch (as1312) fixes a minor bug in usb-storage.  The
+    fill_inquiry() routine neglects to pre-load the inquiry data buffer
+    with spaces.  As a result, if the vendor name is shorter than 8
+    characters or the product name is shorter than 16, the remainder will
+    be filled with garbage.
+    
+    The patch also removes some unnecessary calls to strlen().
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index f5c0264caa33..5a53d4f0dd11 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -232,6 +232,7 @@ void fill_inquiry_response(struct us_data *us, unsigned char *data,
+ 	if (data_len<36) // You lose.
+ 		return;
+ 
++	memset(data+8, ' ', 28);
+ 	if(data[0]&0x20) { /* USB device currently not connected. Return
+ 			      peripheral qualifier 001b ("...however, the
+ 			      physical device is not currently connected
+@@ -241,15 +242,15 @@ void fill_inquiry_response(struct us_data *us, unsigned char *data,
+ 			      device, it may return zeros or ASCII spaces 
+ 			      (20h) in those fields until the data is
+ 			      available from the device."). */
+-		memset(data+8,0,28);
+ 	} else {
+ 		u16 bcdDevice = le16_to_cpu(us->pusb_dev->descriptor.bcdDevice);
+-		memcpy(data+8, us->unusual_dev->vendorName, 
+-			strlen(us->unusual_dev->vendorName) > 8 ? 8 :
+-			strlen(us->unusual_dev->vendorName));
+-		memcpy(data+16, us->unusual_dev->productName, 
+-			strlen(us->unusual_dev->productName) > 16 ? 16 :
+-			strlen(us->unusual_dev->productName));
++		int n;
++
++		n = strlen(us->unusual_dev->vendorName);
++		memcpy(data+8, us->unusual_dev->vendorName, min(8, n));
++		n = strlen(us->unusual_dev->productName);
++		memcpy(data+16, us->unusual_dev->productName, min(16, n));
++
+ 		data[32] = 0x30 + ((bcdDevice>>12) & 0x0F);
+ 		data[33] = 0x30 + ((bcdDevice>>8) & 0x0F);
+ 		data[34] = 0x30 + ((bcdDevice>>4) & 0x0F);

commit a0bb108112a872c0b0c4b3ef4974f95fb75b155d
+Author: Alan Stern 
+Date:   Mon Dec 7 16:39:16 2009 -0500
+
+    USB: usb-storage: add BAD_SENSE flag
+    
+    This patch (as1311) fixes a problem in usb-storage: Some devices are
+    pretty broken when it comes to reporting sense data.  The information
+    they send back indicates that they have more than 18 bytes of sense
+    data available, but when the system asks for more than 18 they fail or
+    hang.  The symptom is that probing fails with multiple resets.
+    
+    The patch adds a new BAD_SENSE flag to indicate that usb-storage
+    should never ask for more than 18 bytes of sense data.  The flag can
+    be set in an unusual_devs entry or via the "quirks=" module parameter,
+    and it is set automatically whenever a REQUEST SENSE command for more
+    than 18 bytes fails or times out.
+    
+    An unusual_devs entry is added for the Agfa photo frame, which uses a
+    Prolific chip having this bug.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Daniel Kukula 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
+index 777dc8a32df8..3f886e298f62 100644
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -2663,6 +2663,8 @@ and is between 256 and 4096 characters. It is defined in the file
+ 			to a common usb-storage quirk flag as follows:
+ 				a = SANE_SENSE (collect more than 18 bytes
+ 					of sense data);
++				b = BAD_SENSE (don't collect more than 18
++					bytes of sense data);
+ 				c = FIX_CAPACITY (decrease the reported
+ 					device capacity by one sector);
+ 				h = CAPACITY_HEURISTICS (decrease the
+diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+index 589f6b4404f0..cc313d16d727 100644
+--- a/drivers/usb/storage/transport.c
++++ b/drivers/usb/storage/transport.c
+@@ -666,10 +666,11 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 	 * to wait for at least one CHECK_CONDITION to determine
+ 	 * SANE_SENSE support
+ 	 */
+-	if ((srb->cmnd[0] == ATA_16 || srb->cmnd[0] == ATA_12) &&
++	if (unlikely((srb->cmnd[0] == ATA_16 || srb->cmnd[0] == ATA_12) &&
+ 	    result == USB_STOR_TRANSPORT_GOOD &&
+ 	    !(us->fflags & US_FL_SANE_SENSE) &&
+-	    !(srb->cmnd[2] & 0x20)) {
++	    !(us->fflags & US_FL_BAD_SENSE) &&
++	    !(srb->cmnd[2] & 0x20))) {
+ 		US_DEBUGP("-- SAT supported, increasing auto-sense\n");
+ 		us->fflags |= US_FL_SANE_SENSE;
+ 	}
+@@ -718,6 +719,12 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 		if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
+ 			US_DEBUGP("-- auto-sense aborted\n");
+ 			srb->result = DID_ABORT << 16;
++
++			/* If SANE_SENSE caused this problem, disable it */
++			if (sense_size != US_SENSE_SIZE) {
++				us->fflags &= ~US_FL_SANE_SENSE;
++				us->fflags |= US_FL_BAD_SENSE;
++			}
+ 			goto Handle_Errors;
+ 		}
+ 
+@@ -727,10 +734,11 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 		 * (small) sense request. This fixes some USB GSM modems
+ 		 */
+ 		if (temp_result == USB_STOR_TRANSPORT_FAILED &&
+-		    (us->fflags & US_FL_SANE_SENSE) &&
+-		    sense_size != US_SENSE_SIZE) {
++				sense_size != US_SENSE_SIZE) {
+ 			US_DEBUGP("-- auto-sense failure, retry small sense\n");
+ 			sense_size = US_SENSE_SIZE;
++			us->fflags &= ~US_FL_SANE_SENSE;
++			us->fflags |= US_FL_BAD_SENSE;
+ 			goto Retry_Sense;
+ 		}
+ 
+@@ -754,6 +762,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 		 */
+ 		if (srb->sense_buffer[7] > (US_SENSE_SIZE - 8) &&
+ 		    !(us->fflags & US_FL_SANE_SENSE) &&
++		    !(us->fflags & US_FL_BAD_SENSE) &&
+ 		    (srb->sense_buffer[0] & 0x7C) == 0x70) {
+ 			US_DEBUGP("-- SANE_SENSE support enabled\n");
+ 			us->fflags |= US_FL_SANE_SENSE;
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index d4f034ebaa8a..64a0a2c27e12 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -818,6 +818,13 @@ UNUSUAL_DEV( 0x066f, 0x8000, 0x0001, 0x0001,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_FIX_CAPACITY ),
+ 
++/* Reported by Daniel Kukula  */
++UNUSUAL_DEV( 0x067b, 0x1063, 0x0100, 0x0100,
++		"Prolific Technology, Inc.",
++		"Prolific Storage Gadget",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_BAD_SENSE ),
++
+ /* Reported by Rogerio Brito  */
+ UNUSUAL_DEV( 0x067b, 0x2317, 0x0001, 0x001,
+ 		"Prolific Technology, Inc.",
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 1599d86154c4..f5c0264caa33 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -463,6 +463,9 @@ static void adjust_quirks(struct us_data *us)
+ 		case 'a':
+ 			f |= US_FL_SANE_SENSE;
+ 			break;
++		case 'b':
++			f |= US_FL_BAD_SENSE;
++			break;
+ 		case 'c':
+ 			f |= US_FL_FIX_CAPACITY;
+ 			break;
+diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
+index 3d15fb9bc116..a4b947e470a5 100644
+--- a/include/linux/usb_usual.h
++++ b/include/linux/usb_usual.h
+@@ -56,7 +56,9 @@
+ 	US_FLAG(SANE_SENSE,     0x00008000)			\
+ 		/* Sane Sense (> 18 bytes) */			\
+ 	US_FLAG(CAPACITY_OK,	0x00010000)			\
+-		/* READ CAPACITY response is correct */
++		/* READ CAPACITY response is correct */		\
++	US_FLAG(BAD_SENSE,	0x00020000)			\
++		/* Bad Sense (never more than 18 bytes) */
+ 
+ #define US_FLAG(name, value)	US_FL_##name = value ,
+ enum { US_DO_ALL_FLAGS };

commit 8e4ceb38eb5bbaef22fc00abe9bc11e26bea2ab5
+Author: Alan Stern 
+Date:   Mon Dec 7 13:01:37 2009 -0500
+
+    USB: prepare for changover to Runtime PM framework
+    
+    This patch (as1303) revises the USB Power Management infrastructure to
+    make it compatible with the new driver-model Runtime PM framework:
+    
+            Drivers are no longer allowed to access intf->pm_usage_cnt
+            directly; the PM framework manages its own usage counters.
+    
+            usb_autopm_set_interface() is eliminated, because it directly
+            sets intf->pm_usage_cnt.
+    
+            usb_autopm_enable() and usb_autopm_disable() are eliminated,
+            because they call usb_autopm_set_interface().
+    
+            usb_autopm_get_interface_no_resume() and
+            usb_autopm_put_interface_no_suspend() are added.  They
+            correspond to pm_runtime_get_noresume() and
+            pm_runtime_put_noidle() in the PM framework.
+    
+            The power/level attribute no longer accepts "suspend", only
+            "on" and "auto".  The PM framework doesn't allow devices to be
+            forced into a suspended mode.
+    
+    The hub driver contains the only code that violates the new
+    guidelines.  It is updated to use the new interface routines instead.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt
+index 8817368203d6..c7c1dc2f8017 100644
+--- a/Documentation/usb/power-management.txt
++++ b/Documentation/usb/power-management.txt
+@@ -2,7 +2,7 @@
+ 
+ 		 Alan Stern 
+ 
+-			    October 5, 2007
++			    November 10, 2009
+ 
+ 
+ 
+@@ -123,9 +123,9 @@ relevant attribute files are: wakeup, level, and autosuspend.
+ 
+ 	power/level
+ 
+-		This file contains one of three words: "on", "auto",
+-		or "suspend".  You can write those words to the file
+-		to change the device's setting.
++		This file contains one of two words: "on" or "auto".
++		You can write those words to the file to change the
++		device's setting.
+ 
+ 		"on" means that the device should be resumed and
+ 		autosuspend is not allowed.  (Of course, system
+@@ -134,10 +134,10 @@ relevant attribute files are: wakeup, level, and autosuspend.
+ 		"auto" is the normal state in which the kernel is
+ 		allowed to autosuspend and autoresume the device.
+ 
+-		"suspend" means that the device should remain
+-		suspended, and autoresume is not allowed.  (But remote
+-		wakeup may still be allowed, since it is controlled
+-		separately by the power/wakeup attribute.)
++		(In kernels up to 2.6.32, you could also specify
++		"suspend", meaning that the device should remain
++		suspended and autoresume was not allowed.  This
++		setting is no longer supported.)
+ 
+ 	power/autosuspend
+ 
+@@ -313,13 +313,14 @@ three of the methods listed above.  In addition, a driver indicates
+ that it supports autosuspend by setting the .supports_autosuspend flag
+ in its usb_driver structure.  It is then responsible for informing the
+ USB core whenever one of its interfaces becomes busy or idle.  The
+-driver does so by calling these five functions:
++driver does so by calling these six functions:
+ 
+ 	int  usb_autopm_get_interface(struct usb_interface *intf);
+ 	void usb_autopm_put_interface(struct usb_interface *intf);
+-	int  usb_autopm_set_interface(struct usb_interface *intf);
+ 	int  usb_autopm_get_interface_async(struct usb_interface *intf);
+ 	void usb_autopm_put_interface_async(struct usb_interface *intf);
++	void usb_autopm_get_interface_no_resume(struct usb_interface *intf);
++	void usb_autopm_put_interface_no_suspend(struct usb_interface *intf);
+ 
+ The functions work by maintaining a counter in the usb_interface
+ structure.  When intf->pm_usage_count is > 0 then the interface is
+@@ -331,11 +332,13 @@ considered to be idle, and the kernel may autosuspend the device.
+ associated with the device itself rather than any of its interfaces.
+ This field is used only by the USB core.)
+ 
+-The driver owns intf->pm_usage_count; it can modify the value however
+-and whenever it likes.  A nice aspect of the non-async usb_autopm_*
+-routines is that the changes they make are protected by the usb_device
+-structure's PM mutex (udev->pm_mutex); however drivers may change
+-pm_usage_count without holding the mutex.  Drivers using the async
++Drivers must not modify intf->pm_usage_count directly; its value
++should be changed only be using the functions listed above.  Drivers
++are responsible for insuring that the overall change to pm_usage_count
++during their lifetime balances out to 0 (it may be necessary for the
++disconnect method to call usb_autopm_put_interface() one or more times
++to fulfill this requirement).  The first two routines use the PM mutex
++in struct usb_device for mutual exclusion; drivers using the async
+ routines are responsible for their own synchronization and mutual
+ exclusion.
+ 
+@@ -347,11 +350,6 @@ exclusion.
+ 	attempts an autosuspend if the new value is <= 0 and the
+ 	device isn't suspended.
+ 
+-	usb_autopm_set_interface() leaves pm_usage_count alone.
+-	It attempts an autoresume if the value is > 0 and the device
+-	is suspended, and it attempts an autosuspend if the value is
+-	<= 0 and the device isn't suspended.
+-
+ 	usb_autopm_get_interface_async() and
+ 	usb_autopm_put_interface_async() do almost the same things as
+ 	their non-async counterparts.  The differences are: they do
+@@ -360,13 +358,11 @@ exclusion.
+ 	such as an URB's completion handler, but when they return the
+ 	device will not generally not yet be in the desired state.
+ 
+-There also are a couple of utility routines drivers can use:
+-
+-	usb_autopm_enable() sets pm_usage_cnt to 0 and then calls
+-	usb_autopm_set_interface(), which will attempt an autosuspend.
+-
+-	usb_autopm_disable() sets pm_usage_cnt to 1 and then calls
+-	usb_autopm_set_interface(), which will attempt an autoresume.
++	usb_autopm_get_interface_no_resume() and
++	usb_autopm_put_interface_no_suspend() merely increment or
++	decrement the pm_usage_count value; they do not attempt to
++	carry out an autoresume or an autosuspend.  Hence they can be
++	called in an atomic context.
+ 
+ The conventional usage pattern is that a driver calls
+ usb_autopm_get_interface() in its open routine and
+@@ -400,11 +396,11 @@ though, setting this flag won't cause the kernel to autoresume it.
+ Normally a driver would set this flag in its probe method, at which
+ time the device is guaranteed not to be autosuspended.)
+ 
+-The usb_autopm_* routines have to run in a sleepable process context;
+-they must not be called from an interrupt handler or while holding a
+-spinlock.  In fact, the entire autosuspend mechanism is not well geared
+-toward interrupt-driven operation.  However there is one thing a
+-driver can do in an interrupt handler:
++The synchronous usb_autopm_* routines have to run in a sleepable
++process context; they must not be called from an interrupt handler or
++while holding a spinlock.  In fact, the entire autosuspend mechanism
++is not well geared toward interrupt-driven operation.  However there
++is one thing a driver can do in an interrupt handler:
+ 
+ 	usb_mark_last_busy(struct usb_device *udev);
+ 
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 8016a296010e..7a05bab73960 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -948,8 +948,6 @@ static int usb_resume_device(struct usb_device *udev, pm_message_t msg)
+ 
+  done:
+ 	dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
+-	if (status == 0)
+-		udev->autoresume_disabled = 0;
+ 	return status;
+ }
+ 
+@@ -1280,11 +1278,6 @@ static int usb_resume_both(struct usb_device *udev, pm_message_t msg)
+ 
+ 	/* Propagate the resume up the tree, if necessary */
+ 	if (udev->state == USB_STATE_SUSPENDED) {
+-		if ((msg.event & PM_EVENT_AUTO) &&
+-				udev->autoresume_disabled) {
+-			status = -EPERM;
+-			goto done;
+-		}
+ 		if (parent) {
+ 			status = usb_autoresume_device(parent);
+ 			if (status == 0) {
+@@ -1638,8 +1631,6 @@ int usb_autopm_get_interface_async(struct usb_interface *intf)
+ 
+ 	if (intf->condition == USB_INTERFACE_UNBOUND)
+ 		status = -ENODEV;
+-	else if (udev->autoresume_disabled)
+-		status = -EPERM;
+ 	else {
+ 		atomic_inc(&intf->pm_usage_cnt);
+ 		if (atomic_read(&intf->pm_usage_cnt) > 0 &&
+@@ -1652,28 +1643,6 @@ int usb_autopm_get_interface_async(struct usb_interface *intf)
+ }
+ EXPORT_SYMBOL_GPL(usb_autopm_get_interface_async);
+ 
+-/**
+- * usb_autopm_set_interface - set a USB interface's autosuspend state
+- * @intf: the usb_interface whose state should be set
+- *
+- * This routine sets the autosuspend state of @intf's device according
+- * to @intf's usage counter, which the caller must have set previously.
+- * If the counter is <= 0, the device is autosuspended (if it isn't
+- * already suspended and if nothing else prevents the autosuspend).  If
+- * the counter is > 0, the device is autoresumed (if it isn't already
+- * awake).
+- */
+-int usb_autopm_set_interface(struct usb_interface *intf)
+-{
+-	int	status;
+-
+-	status = usb_autopm_do_interface(intf, 0);
+-	dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
+-			__func__, status, atomic_read(&intf->pm_usage_cnt));
+-	return status;
+-}
+-EXPORT_SYMBOL_GPL(usb_autopm_set_interface);
+-
+ #else
+ 
+ void usb_autosuspend_work(struct work_struct *work)
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 5413d712cae0..b38fd6730e2a 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -71,6 +71,7 @@ struct usb_hub {
+ 
+ 	unsigned		mA_per_port;	/* current for each child */
+ 
++	unsigned		init_done:1;
+ 	unsigned		limited_power:1;
+ 	unsigned		quiescing:1;
+ 	unsigned		disconnected:1;
+@@ -375,12 +376,13 @@ static void kick_khubd(struct usb_hub *hub)
+ {
+ 	unsigned long	flags;
+ 
+-	/* Suppress autosuspend until khubd runs */
+-	atomic_set(&to_usb_interface(hub->intfdev)->pm_usage_cnt, 1);
+-
+ 	spin_lock_irqsave(&hub_event_lock, flags);
+ 	if (!hub->disconnected && list_empty(&hub->event_list)) {
+ 		list_add_tail(&hub->event_list, &hub_event_list);
++
++		/* Suppress autosuspend until khubd runs */
++		usb_autopm_get_interface_no_resume(
++				to_usb_interface(hub->intfdev));
+ 		wake_up(&khubd_wait);
+ 	}
+ 	spin_unlock_irqrestore(&hub_event_lock, flags);
+@@ -665,7 +667,7 @@ int usb_remove_device(struct usb_device *udev)
+ }
+ 
+ enum hub_activation_type {
+-	HUB_INIT, HUB_INIT2, HUB_INIT3,
++	HUB_INIT, HUB_INIT2, HUB_INIT3,		/* INITs must come first */
+ 	HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME,
+ };
+ 
+@@ -710,8 +712,8 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ 					msecs_to_jiffies(delay));
+ 
+ 			/* Suppress autosuspend until init is done */
+-			atomic_set(&to_usb_interface(hub->intfdev)->
+-					pm_usage_cnt, 1);
++			usb_autopm_get_interface_no_resume(
++					to_usb_interface(hub->intfdev));
+ 			return;		/* Continues at init2: below */
+ 		} else {
+ 			hub_power_on(hub, true);
+@@ -818,6 +820,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ 	}
+  init3:
+ 	hub->quiescing = 0;
++	hub->init_done = 1;
+ 
+ 	status = usb_submit_urb(hub->urb, GFP_NOIO);
+ 	if (status < 0)
+@@ -827,6 +830,10 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ 
+ 	/* Scan all ports that need attention */
+ 	kick_khubd(hub);
++
++	/* Allow autosuspend if it was suppressed */
++	if (type <= HUB_INIT3)
++		usb_autopm_put_interface_async(to_usb_interface(hub->intfdev));
+ }
+ 
+ /* Implement the continuations for the delays above */
+@@ -854,6 +861,11 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
+ 	int i;
+ 
+ 	cancel_delayed_work_sync(&hub->init_work);
++	if (!hub->init_done) {
++		hub->init_done = 1;
++		usb_autopm_put_interface_no_suspend(
++				to_usb_interface(hub->intfdev));
++	}
+ 
+ 	/* khubd and related activity won't re-trigger */
+ 	hub->quiescing = 1;
+@@ -1176,7 +1188,10 @@ static void hub_disconnect(struct usb_interface *intf)
+ 
+ 	/* Take the hub off the event list and don't let it be added again */
+ 	spin_lock_irq(&hub_event_lock);
+-	list_del_init(&hub->event_list);
++	if (!list_empty(&hub->event_list)) {
++		list_del_init(&hub->event_list);
++		usb_autopm_put_interface_no_suspend(intf);
++	}
+ 	hub->disconnected = 1;
+ 	spin_unlock_irq(&hub_event_lock);
+ 
+@@ -3235,7 +3250,7 @@ static void hub_events(void)
+ 		 * disconnected while waiting for the lock to succeed. */
+ 		usb_lock_device(hdev);
+ 		if (unlikely(hub->disconnected))
+-			goto loop;
++			goto loop2;
+ 
+ 		/* If the hub has died, clean up after it */
+ 		if (hdev->state == USB_STATE_NOTATTACHED) {
+@@ -3384,11 +3399,15 @@ static void hub_events(void)
+ 			}
+ 		}
+ 
+-loop_autopm:
+-		/* Allow autosuspend if we're not going to run again */
+-		if (list_empty(&hub->event_list))
+-			usb_autopm_enable(intf);
+-loop:
++ loop_autopm:
++		/* Balance the usb_autopm_get_interface() above */
++		usb_autopm_put_interface_no_suspend(intf);
++ loop:
++		/* Balance the usb_autopm_get_interface_no_resume() in
++		 * kick_khubd() and allow autosuspend.
++		 */
++		usb_autopm_put_interface(intf);
++ loop2:
+ 		usb_unlock_device(hdev);
+ 		kref_put(&hub->kref, hub_release);
+ 
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index ae763974be25..15477008b631 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -327,7 +327,6 @@ static DEVICE_ATTR(autosuspend, S_IRUGO | S_IWUSR,
+ 
+ static const char on_string[] = "on";
+ static const char auto_string[] = "auto";
+-static const char suspend_string[] = "suspend";
+ 
+ static ssize_t
+ show_level(struct device *dev, struct device_attribute *attr, char *buf)
+@@ -335,13 +334,8 @@ show_level(struct device *dev, struct device_attribute *attr, char *buf)
+ 	struct usb_device *udev = to_usb_device(dev);
+ 	const char *p = auto_string;
+ 
+-	if (udev->state == USB_STATE_SUSPENDED) {
+-		if (udev->autoresume_disabled)
+-			p = suspend_string;
+-	} else {
+-		if (udev->autosuspend_disabled)
+-			p = on_string;
+-	}
++	if (udev->state != USB_STATE_SUSPENDED && udev->autosuspend_disabled)
++		p = on_string;
+ 	return sprintf(buf, "%s\n", p);
+ }
+ 
+@@ -353,7 +347,7 @@ set_level(struct device *dev, struct device_attribute *attr,
+ 	int len = count;
+ 	char *cp;
+ 	int rc = 0;
+-	int old_autosuspend_disabled, old_autoresume_disabled;
++	int old_autosuspend_disabled;
+ 
+ 	cp = memchr(buf, '\n', count);
+ 	if (cp)
+@@ -361,7 +355,6 @@ set_level(struct device *dev, struct device_attribute *attr,
+ 
+ 	usb_lock_device(udev);
+ 	old_autosuspend_disabled = udev->autosuspend_disabled;
+-	old_autoresume_disabled = udev->autoresume_disabled;
+ 
+ 	/* Setting the flags without calling usb_pm_lock is a subject to
+ 	 * races, but who cares...
+@@ -369,28 +362,18 @@ set_level(struct device *dev, struct device_attribute *attr,
+ 	if (len == sizeof on_string - 1 &&
+ 			strncmp(buf, on_string, len) == 0) {
+ 		udev->autosuspend_disabled = 1;
+-		udev->autoresume_disabled = 0;
+ 		rc = usb_external_resume_device(udev, PMSG_USER_RESUME);
+ 
+ 	} else if (len == sizeof auto_string - 1 &&
+ 			strncmp(buf, auto_string, len) == 0) {
+ 		udev->autosuspend_disabled = 0;
+-		udev->autoresume_disabled = 0;
+ 		rc = usb_external_resume_device(udev, PMSG_USER_RESUME);
+ 
+-	} else if (len == sizeof suspend_string - 1 &&
+-			strncmp(buf, suspend_string, len) == 0) {
+-		udev->autosuspend_disabled = 0;
+-		udev->autoresume_disabled = 1;
+-		rc = usb_external_suspend_device(udev, PMSG_USER_SUSPEND);
+-
+ 	} else
+ 		rc = -EINVAL;
+ 
+-	if (rc) {
++	if (rc)
+ 		udev->autosuspend_disabled = old_autosuspend_disabled;
+-		udev->autoresume_disabled = old_autoresume_disabled;
+-	}
+ 	usb_unlock_device(udev);
+ 	return (rc < 0 ? rc : count);
+ }
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 4b6f6db544ee..6af3581e1114 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -432,7 +432,6 @@ struct usb_tt;
+  * @do_remote_wakeup:  remote wakeup should be enabled
+  * @reset_resume: needs reset instead of resume
+  * @autosuspend_disabled: autosuspend disabled by the user
+- * @autoresume_disabled: autoresume disabled by the user
+  * @skip_sys_resume: skip the next system resume
+  * @wusb_dev: if this is a Wireless USB device, link to the WUSB
+  *	specific data for the device.
+@@ -516,7 +515,6 @@ struct usb_device {
+ 	unsigned do_remote_wakeup:1;
+ 	unsigned reset_resume:1;
+ 	unsigned autosuspend_disabled:1;
+-	unsigned autoresume_disabled:1;
+ 	unsigned skip_sys_resume:1;
+ #endif
+ 	struct wusb_dev *wusb_dev;
+@@ -542,22 +540,20 @@ extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id);
+ 
+ /* USB autosuspend and autoresume */
+ #ifdef CONFIG_USB_SUSPEND
+-extern int usb_autopm_set_interface(struct usb_interface *intf);
+ extern int usb_autopm_get_interface(struct usb_interface *intf);
+ extern void usb_autopm_put_interface(struct usb_interface *intf);
+ extern int usb_autopm_get_interface_async(struct usb_interface *intf);
+ extern void usb_autopm_put_interface_async(struct usb_interface *intf);
+ 
+-static inline void usb_autopm_enable(struct usb_interface *intf)
++static inline void usb_autopm_get_interface_no_resume(
++		struct usb_interface *intf)
+ {
+-	atomic_set(&intf->pm_usage_cnt, 0);
+-	usb_autopm_set_interface(intf);
++	atomic_inc(&intf->pm_usage_cnt);
+ }
+-
+-static inline void usb_autopm_disable(struct usb_interface *intf)
++static inline void usb_autopm_put_interface_no_suspend(
++		struct usb_interface *intf)
+ {
+-	atomic_set(&intf->pm_usage_cnt, 1);
+-	usb_autopm_set_interface(intf);
++	atomic_dec(&intf->pm_usage_cnt);
+ }
+ 
+ static inline void usb_mark_last_busy(struct usb_device *udev)
+@@ -567,12 +563,8 @@ static inline void usb_mark_last_busy(struct usb_device *udev)
+ 
+ #else
+ 
+-static inline int usb_autopm_set_interface(struct usb_interface *intf)
+-{ return 0; }
+-
+ static inline int usb_autopm_get_interface(struct usb_interface *intf)
+ { return 0; }
+-
+ static inline int usb_autopm_get_interface_async(struct usb_interface *intf)
+ { return 0; }
+ 
+@@ -580,9 +572,11 @@ static inline void usb_autopm_put_interface(struct usb_interface *intf)
+ { }
+ static inline void usb_autopm_put_interface_async(struct usb_interface *intf)
+ { }
+-static inline void usb_autopm_enable(struct usb_interface *intf)
++static inline void usb_autopm_get_interface_no_resume(
++		struct usb_interface *intf)
+ { }
+-static inline void usb_autopm_disable(struct usb_interface *intf)
++static inline void usb_autopm_put_interface_no_suspend(
++		struct usb_interface *intf)
+ { }
+ static inline void usb_mark_last_busy(struct usb_device *udev)
+ { }

commit fb34d53752d5bec5acc73422e462a9c68aeeaa2a
+Author: Alan Stern 
+Date:   Fri Nov 13 11:53:59 2009 -0500
+
+    USB: remove the auto_pm flag
+    
+    This patch (as1302) removes the auto_pm flag from struct usb_device.
+    The flag's only purpose was to distinguish between autosuspends and
+    external suspends, but that information is now available in the
+    pm_message_t argument passed to suspend methods.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt
+index ad642615ad4c..8817368203d6 100644
+--- a/Documentation/usb/power-management.txt
++++ b/Documentation/usb/power-management.txt
+@@ -423,15 +423,16 @@ an URB had completed too recently.
+ 
+ External suspend calls should never be allowed to fail in this way,
+ only autosuspend calls.  The driver can tell them apart by checking
+-udev->auto_pm; this flag will be set to 1 for internal PM events
+-(autosuspend or autoresume) and 0 for external PM events.
++the PM_EVENT_AUTO bit in the message.event argument to the suspend
++method; this bit will be set for internal PM events (autosuspend) and
++clear for external PM events.
+ 
+ Many of the ingredients in the autosuspend framework are oriented
+ towards interfaces: The usb_interface structure contains the
+ pm_usage_cnt field, and the usb_autopm_* routines take an interface
+ pointer as their argument.  But somewhat confusingly, a few of the
+-pieces (usb_mark_last_busy() and udev->auto_pm) use the usb_device
+-structure instead.  Drivers need to keep this straight; they can call
++pieces (i.e., usb_mark_last_busy()) use the usb_device structure
++instead.  Drivers need to keep this straight; they can call
+ interface_to_usbdev() to find the device structure for a given
+ interface.
+ 
+diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
+index 44bc8bbabf54..4d2905996751 100644
+--- a/drivers/bluetooth/btusb.c
++++ b/drivers/bluetooth/btusb.c
+@@ -1066,7 +1066,7 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
+ 		return 0;
+ 
+ 	spin_lock_irq(&data->txlock);
+-	if (!(interface_to_usbdev(intf)->auto_pm && data->tx_in_flight)) {
++	if (!((message.event & PM_EVENT_AUTO) && data->tx_in_flight)) {
+ 		set_bit(BTUSB_SUSPENDING, &data->flags);
+ 		spin_unlock_irq(&data->txlock);
+ 	} else {
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index 0258289f3b3e..e2997a8d5e1b 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -1253,10 +1253,9 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
+ {
+ 	struct hid_device *hid = usb_get_intfdata(intf);
+ 	struct usbhid_device *usbhid = hid->driver_data;
+-	struct usb_device *udev = interface_to_usbdev(intf);
+ 	int status;
+ 
+-	if (udev->auto_pm) {
++	if (message.event & PM_EVENT_AUTO) {
+ 		spin_lock_irq(&usbhid->lock);	/* Sync with error handler */
+ 		if (!test_bit(HID_RESET_PENDING, &usbhid->iofl)
+ 		    && !test_bit(HID_CLEAR_HALT, &usbhid->iofl)
+@@ -1281,7 +1280,7 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
+ 			return -EIO;
+ 	}
+ 
+-	if (!ignoreled && udev->auto_pm) {
++	if (!ignoreled && (message.event & PM_EVENT_AUTO)) {
+ 		spin_lock_irq(&usbhid->lock);
+ 		if (test_bit(HID_LED_ON, &usbhid->iofl)) {
+ 			spin_unlock_irq(&usbhid->lock);
+@@ -1294,7 +1293,8 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
+ 	hid_cancel_delayed_stuff(usbhid);
+ 	hid_cease_io(usbhid);
+ 
+-	if (udev->auto_pm && test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) {
++	if ((message.event & PM_EVENT_AUTO) &&
++			test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) {
+ 		/* lost race against keypresses */
+ 		status = hid_start_in(hid);
+ 		if (status < 0)
+diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c
+index 47e84ef355c5..3b48681f8a0d 100644
+--- a/drivers/net/wimax/i2400m/usb.c
++++ b/drivers/net/wimax/i2400m/usb.c
+@@ -579,7 +579,7 @@ void i2400mu_disconnect(struct usb_interface *iface)
+  *
+  *    As well, the device might refuse going to sleep for whichever
+  *    reason. In this case we just fail. For system suspend/hibernate,
+- *    we *can't* fail. We look at usb_dev->auto_pm to see if the
++ *    we *can't* fail. We check PM_EVENT_AUTO to see if the
+  *    suspend call comes from the USB stack or from the system and act
+  *    in consequence.
+  *
+@@ -591,14 +591,11 @@ int i2400mu_suspend(struct usb_interface *iface, pm_message_t pm_msg)
+ 	int result = 0;
+ 	struct device *dev = &iface->dev;
+ 	struct i2400mu *i2400mu = usb_get_intfdata(iface);
+-#ifdef CONFIG_PM
+-	struct usb_device *usb_dev = i2400mu->usb_dev;
+-#endif
+ 	unsigned is_autosuspend = 0;
+ 	struct i2400m *i2400m = &i2400mu->i2400m;
+ 
+ #ifdef CONFIG_PM
+-	if (usb_dev->auto_pm > 0)
++	if (pm_msg.event & PM_EVENT_AUTO)
+ 		is_autosuspend = 1;
+ #endif
+ 
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 4f864472c5c4..8016a296010e 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1341,7 +1341,6 @@ static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt)
+ 	int	status = 0;
+ 
+ 	usb_pm_lock(udev);
+-	udev->auto_pm = 1;
+ 	udev->pm_usage_cnt += inc_usage_cnt;
+ 	WARN_ON(udev->pm_usage_cnt < 0);
+ 	if (inc_usage_cnt)
+@@ -1473,7 +1472,6 @@ static int usb_autopm_do_interface(struct usb_interface *intf,
+ 	if (intf->condition == USB_INTERFACE_UNBOUND)
+ 		status = -ENODEV;
+ 	else {
+-		udev->auto_pm = 1;
+ 		atomic_add(inc_usage_cnt, &intf->pm_usage_cnt);
+ 		udev->last_busy = jiffies;
+ 		if (inc_usage_cnt >= 0 &&
+@@ -1707,7 +1705,6 @@ int usb_external_suspend_device(struct usb_device *udev, pm_message_t msg)
+ 
+ 	do_unbind_rebind(udev, DO_UNBIND);
+ 	usb_pm_lock(udev);
+-	udev->auto_pm = 0;
+ 	status = usb_suspend_both(udev, msg);
+ 	usb_pm_unlock(udev);
+ 	return status;
+@@ -1730,7 +1727,6 @@ int usb_external_resume_device(struct usb_device *udev, pm_message_t msg)
+ 	int	status;
+ 
+ 	usb_pm_lock(udev);
+-	udev->auto_pm = 0;
+ 	status = usb_resume_both(udev, msg);
+ 	udev->last_busy = jiffies;
+ 	usb_pm_unlock(udev);
+diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
+index 0d46bbec44b7..8751ec79a159 100644
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -1313,7 +1313,7 @@ static int option_suspend(struct usb_serial *serial, pm_message_t message)
+ 
+ 	dbg("%s entered", __func__);
+ 
+-	if (serial->dev->auto_pm) {
++	if (message.event & PM_EVENT_AUTO) {
+ 		spin_lock_irq(&intfdata->susp_lock);
+ 		b = intfdata->in_flight;
+ 		spin_unlock_irq(&intfdata->susp_lock);
+diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
+index c5c41aed106d..ac1b6449fb6a 100644
+--- a/drivers/usb/serial/sierra.c
++++ b/drivers/usb/serial/sierra.c
+@@ -1005,7 +1005,7 @@ static int sierra_suspend(struct usb_serial *serial, pm_message_t message)
+ 	struct sierra_intf_private *intfdata;
+ 	int b;
+ 
+-	if (serial->dev->auto_pm) {
++	if (message.event & PM_EVENT_AUTO) {
+ 		intfdata = serial->private;
+ 		spin_lock_irq(&intfdata->susp_lock);
+ 		b = intfdata->in_flight;
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 6e91ee4f5b81..4b6f6db544ee 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -429,7 +429,6 @@ struct usb_tt;
+  * @last_busy: time of last use
+  * @autosuspend_delay: in jiffies
+  * @connect_time: time device was first connected
+- * @auto_pm: autosuspend/resume in progress
+  * @do_remote_wakeup:  remote wakeup should be enabled
+  * @reset_resume: needs reset instead of resume
+  * @autosuspend_disabled: autosuspend disabled by the user
+@@ -514,7 +513,6 @@ struct usb_device {
+ 	int autosuspend_delay;
+ 	unsigned long connect_time;
+ 
+-	unsigned auto_pm:1;
+ 	unsigned do_remote_wakeup:1;
+ 	unsigned reset_resume:1;
+ 	unsigned autosuspend_disabled:1;

commit b375e1169d8ecc9e9db3ecba8147d484b5510833
+Author: Alan Stern 
+Date:   Fri Nov 6 12:32:23 2009 -0500
+
+    USB: add scatter-gather support to usbmon
+    
+    This patch (as1301) adds support to usbmon for scatter-gather URBs.
+    The text interface looks at only the first scatterlist element, since
+    it never copies more than 32 bytes of data anyway.  The binary
+    interface copies as much data as possible up to the first
+    non-addressable buffer.
+    
+    Signed-off-by: Alan Stern 
+    CC: Pete Zaitcev 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
+index 10f3205798e8..385ec0520167 100644
+--- a/drivers/usb/mon/mon_bin.c
++++ b/drivers/usb/mon/mon_bin.c
+@@ -16,6 +16,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ 
+@@ -221,7 +222,7 @@ static void mon_free_buff(struct mon_pgmap *map, int npages);
+ /*
+  * This is a "chunked memcpy". It does not manipulate any counters.
+  */
+-static void mon_copy_to_buff(const struct mon_reader_bin *this,
++static unsigned int mon_copy_to_buff(const struct mon_reader_bin *this,
+     unsigned int off, const unsigned char *from, unsigned int length)
+ {
+ 	unsigned int step_len;
+@@ -246,6 +247,7 @@ static void mon_copy_to_buff(const struct mon_reader_bin *this,
+ 		from += step_len;
+ 		length -= step_len;
+ 	}
++	return off;
+ }
+ 
+ /*
+@@ -394,14 +396,44 @@ static inline char mon_bin_get_setup(unsigned char *setupb,
+ 	return 0;
+ }
+ 
+-static char mon_bin_get_data(const struct mon_reader_bin *rp,
+-    unsigned int offset, struct urb *urb, unsigned int length)
++static unsigned int mon_bin_get_data(const struct mon_reader_bin *rp,
++    unsigned int offset, struct urb *urb, unsigned int length,
++    char *flag)
+ {
++	int i;
++	struct scatterlist *sg;
++	unsigned int this_len;
++
++	*flag = 0;
++	if (urb->num_sgs == 0) {
++		if (urb->transfer_buffer == NULL) {
++			*flag = 'Z';
++			return length;
++		}
++		mon_copy_to_buff(rp, offset, urb->transfer_buffer, length);
++		length = 0;
+ 
+-	if (urb->transfer_buffer == NULL)
+-		return 'Z';
+-	mon_copy_to_buff(rp, offset, urb->transfer_buffer, length);
+-	return 0;
++	} else {
++		/* If IOMMU coalescing occurred, we cannot trust sg_page */
++		if (urb->sg->nents != urb->num_sgs) {
++			*flag = 'D';
++			return length;
++		}
++
++		/* Copy up to the first non-addressable segment */
++		for_each_sg(urb->sg->sg, sg, urb->num_sgs, i) {
++			if (length == 0 || PageHighMem(sg_page(sg)))
++				break;
++			this_len = min_t(unsigned int, sg->length, length);
++			offset = mon_copy_to_buff(rp, offset, sg_virt(sg),
++					this_len);
++			length -= this_len;
++		}
++		if (i == 0)
++			*flag = 'D';
++	}
++
++	return length;
+ }
+ 
+ static void mon_bin_get_isodesc(const struct mon_reader_bin *rp,
+@@ -536,8 +568,9 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
+ 	}
+ 
+ 	if (length != 0) {
+-		ep->flag_data = mon_bin_get_data(rp, offset, urb, length);
+-		if (ep->flag_data != 0) {	/* Yes, it's 0x00, not '0' */
++		length = mon_bin_get_data(rp, offset, urb, length,
++				&ep->flag_data);
++		if (length > 0) {
+ 			delta = (ep->len_cap + PKT_ALIGN-1) & ~(PKT_ALIGN-1);
+ 			ep->len_cap -= length;
+ 			delta -= (ep->len_cap + PKT_ALIGN-1) & ~(PKT_ALIGN-1);
+diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
+index 9f1a9227ebe6..047568ff223d 100644
+--- a/drivers/usb/mon/mon_text.c
++++ b/drivers/usb/mon/mon_text.c
+@@ -10,6 +10,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ 
+ #include "usb_mon.h"
+@@ -137,6 +138,8 @@ static inline char mon_text_get_setup(struct mon_event_text *ep,
+ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
+     int len, char ev_type, struct mon_bus *mbus)
+ {
++	void *src;
++
+ 	if (len <= 0)
+ 		return 'L';
+ 	if (len >= DATA_MAX)
+@@ -150,10 +153,24 @@ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
+ 			return '>';
+ 	}
+ 
+-	if (urb->transfer_buffer == NULL)
+-		return 'Z';	/* '0' would be not as pretty. */
++	if (urb->num_sgs == 0) {
++		src = urb->transfer_buffer;
++		if (src == NULL)
++			return 'Z';	/* '0' would be not as pretty. */
++	} else {
++		struct scatterlist *sg = urb->sg->sg;
++
++		/* If IOMMU coalescing occurred, we cannot trust sg_page */
++		if (urb->sg->nents != urb->num_sgs ||
++				PageHighMem(sg_page(sg)))
++			return 'D';
++
++		/* For the text interface we copy only the first sg buffer */
++		len = min_t(int, sg->length, len);
++		src = sg_virt(sg);
++	}
+ 
+-	memcpy(ep->data, urb->transfer_buffer, len);
++	memcpy(ep->data, src, len);
+ 	return 0;
+ }
+ 

commit 40f8db8f8f5af2cafeb976ae15e11aca641a931d
+Author: Alan Stern 
+Date:   Fri Nov 6 12:29:40 2009 -0500
+
+    USB: EHCI: add native scatter-gather support
+    
+    This patch (as1300) adds native scatter-gather support to ehci-hcd.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 2a3265087ef3..5859522d6edd 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -605,6 +605,8 @@ static int ehci_init(struct usb_hcd *hcd)
+ 	}
+ 	ehci->command = temp;
+ 
++	/* Accept arbitrarily long scatter-gather lists */
++	hcd->self.sg_tablesize = ~0;
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 139a2cc3f641..a427d3b00634 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -616,9 +616,11 @@ qh_urb_transaction (
+ ) {
+ 	struct ehci_qtd		*qtd, *qtd_prev;
+ 	dma_addr_t		buf;
+-	int			len, maxpacket;
++	int			len, this_sg_len, maxpacket;
+ 	int			is_input;
+ 	u32			token;
++	int			i;
++	struct scatterlist	*sg;
+ 
+ 	/*
+ 	 * URBs map to sequences of QTDs:  one logical transaction
+@@ -659,7 +661,20 @@ qh_urb_transaction (
+ 	/*
+ 	 * data transfer stage:  buffer setup
+ 	 */
+-	buf = urb->transfer_dma;
++	i = urb->num_sgs;
++	if (len > 0 && i > 0) {
++		sg = urb->sg->sg;
++		buf = sg_dma_address(sg);
++
++		/* urb->transfer_buffer_length may be smaller than the
++		 * size of the scatterlist (or vice versa)
++		 */
++		this_sg_len = min_t(int, sg_dma_len(sg), len);
++	} else {
++		sg = NULL;
++		buf = urb->transfer_dma;
++		this_sg_len = len;
++	}
+ 
+ 	if (is_input)
+ 		token |= (1 /* "in" */ << 8);
+@@ -675,7 +690,9 @@ qh_urb_transaction (
+ 	for (;;) {
+ 		int this_qtd_len;
+ 
+-		this_qtd_len = qtd_fill(ehci, qtd, buf, len, token, maxpacket);
++		this_qtd_len = qtd_fill(ehci, qtd, buf, this_sg_len, token,
++				maxpacket);
++		this_sg_len -= this_qtd_len;
+ 		len -= this_qtd_len;
+ 		buf += this_qtd_len;
+ 
+@@ -691,8 +708,13 @@ qh_urb_transaction (
+ 		if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0)
+ 			token ^= QTD_TOGGLE;
+ 
+-		if (likely (len <= 0))
+-			break;
++		if (likely(this_sg_len <= 0)) {
++			if (--i <= 0 || len <= 0)
++				break;
++			sg = sg_next(sg);
++			buf = sg_dma_address(sg);
++			this_sg_len = min_t(int, sg_dma_len(sg), len);
++		}
+ 
+ 		qtd_prev = qtd;
+ 		qtd = ehci_qtd_alloc (ehci, flags);

commit ed1db3ada189c9af592c4d2971b22b482b68aafe
+Author: Alan Stern 
+Date:   Tue Oct 27 15:26:50 2009 -0400
+
+    USB: fix a bug in the scatter-gather library
+    
+    This patch (as1298) fixes a bug in the new scatter-gather URB
+    facility.  If an URB uses a scatterlist then it should not have the
+    URB_NO_INTERRUPT flag set; otherwise the system won't be notified when
+    the transfer completes.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: David Vrabel 
+    CC: Sarah Sharp 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 8d874cad6581..adb9c8ee0c1f 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -403,7 +403,7 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
+ 	if (!io->urbs)
+ 		goto nomem;
+ 
+-	urb_flags = URB_NO_INTERRUPT;
++	urb_flags = 0;
+ 	if (dma)
+ 		urb_flags |= URB_NO_TRANSFER_DMA_MAP;
+ 	if (usb_pipein(pipe))
+@@ -435,6 +435,7 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
+ 		io->urbs[0]->num_sgs = io->entries;
+ 		io->entries = 1;
+ 	} else {
++		urb_flags |= URB_NO_INTERRUPT;
+ 		for_each_sg(sg, sg, io->entries, i) {
+ 			unsigned len;
+ 

commit 253e05724f9230910344357b1142ad8642ff9f5a
+Author: Alan Stern 
+Date:   Tue Oct 27 15:20:13 2009 -0400
+
+    USB: add a "remove hardware" sysfs attribute
+    
+    This patch (as1297) adds a "remove" attribute to each USB device's
+    directory in sysfs.  Writing to this attribute causes the device to be
+    deconfigured (the same as writing 0 to the "bConfigurationValue"
+    attribute) and then tells the hub driver to disable the device's
+    upstream port.  The device remains locked during these activities so
+    there is no possibility of it getting reconfigured in between.  The
+    port will remain disabled until after the device is unplugged.
+    
+    The purpose of this is to provide a means for user programs to imitate
+    the "Safely remove hardware" applet in Windows.  Some devices do
+    expect their ports to be disabled before they are unplugged, and they
+    provide visual feedback to users indicating when they can safely be
+    unplugged.
+    
+    The security implications are minimal.  Writing to the "remove"
+    attribute is no more dangerous than writing to the
+    "bConfigurationValue" attribute.
+    
+    Signed-off-by: Alan Stern 
+    Cc: David Zeuthen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 708c63826100..5413d712cae0 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -60,6 +60,8 @@ struct usb_hub {
+ 							status change */
+ 	unsigned long		busy_bits[1];	/* ports being reset or
+ 							resumed */
++	unsigned long		removed_bits[1]; /* ports with a "removed"
++							device present */
+ #if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
+ #error event_bits[] is too short!
+ #endif
+@@ -635,6 +637,33 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
+  	kick_khubd(hub);
+ }
+ 
++/**
++ * usb_remove_device - disable a device's port on its parent hub
++ * @udev: device to be disabled and removed
++ * Context: @udev locked, must be able to sleep.
++ *
++ * After @udev's port has been disabled, khubd is notified and it will
++ * see that the device has been disconnected.  When the device is
++ * physically unplugged and something is plugged in, the events will
++ * be received and processed normally.
++ */
++int usb_remove_device(struct usb_device *udev)
++{
++	struct usb_hub *hub;
++	struct usb_interface *intf;
++
++	if (!udev->parent)	/* Can't remove a root hub */
++		return -EINVAL;
++	hub = hdev_to_hub(udev->parent);
++	intf = to_usb_interface(hub->intfdev);
++
++	usb_autopm_get_interface(intf);
++	set_bit(udev->portnum, hub->removed_bits);
++	hub_port_logical_disconnect(hub, udev->portnum);
++	usb_autopm_put_interface(intf);
++	return 0;
++}
++
+ enum hub_activation_type {
+ 	HUB_INIT, HUB_INIT2, HUB_INIT3,
+ 	HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME,
+@@ -730,6 +759,13 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ 					USB_PORT_FEAT_C_ENABLE);
+ 		}
+ 
++		/* We can forget about a "removed" device when there's a
++		 * physical disconnect or the connect status changes.
++		 */
++		if (!(portstatus & USB_PORT_STAT_CONNECTION) ||
++				(portchange & USB_PORT_STAT_C_CONNECTION))
++			clear_bit(port1, hub->removed_bits);
++
+ 		if (!udev || udev->state == USB_STATE_NOTATTACHED) {
+ 			/* Tell khubd to disconnect the device or
+ 			 * check for a new connection
+@@ -2965,6 +3001,13 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 		usb_disconnect(&hdev->children[port1-1]);
+ 	clear_bit(port1, hub->change_bits);
+ 
++	/* We can forget about a "removed" device when there's a physical
++	 * disconnect or the connect status changes.
++	 */
++	if (!(portstatus & USB_PORT_STAT_CONNECTION) ||
++			(portchange & USB_PORT_STAT_C_CONNECTION))
++		clear_bit(port1, hub->removed_bits);
++
+ 	if (portchange & (USB_PORT_STAT_C_CONNECTION |
+ 				USB_PORT_STAT_C_ENABLE)) {
+ 		status = hub_port_debounce(hub, port1);
+@@ -2978,8 +3021,11 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 		}
+ 	}
+ 
+-	/* Return now if debouncing failed or nothing is connected */
+-	if (!(portstatus & USB_PORT_STAT_CONNECTION)) {
++	/* Return now if debouncing failed or nothing is connected or
++	 * the device was "removed".
++	 */
++	if (!(portstatus & USB_PORT_STAT_CONNECTION) ||
++			test_bit(port1, hub->removed_bits)) {
+ 
+ 		/* maybe switch power back on (e.g. root hub was reset) */
+ 		if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 7ec3041ae79e..470e2413a9cf 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -508,6 +508,28 @@ static ssize_t usb_dev_authorized_store(struct device *dev,
+ static DEVICE_ATTR(authorized, 0644,
+ 	    usb_dev_authorized_show, usb_dev_authorized_store);
+ 
++/* "Safely remove a device" */
++static ssize_t usb_remove_store(struct device *dev,
++		struct device_attribute *attr,
++		const char *buf, size_t count)
++{
++	struct usb_device *udev = to_usb_device(dev);
++	int rc = 0;
++
++	usb_lock_device(udev);
++	if (udev->state != USB_STATE_NOTATTACHED) {
++
++		/* To avoid races, first unconfigure and then remove */
++		usb_set_configuration(udev, -1);
++		rc = usb_remove_device(udev);
++	}
++	if (rc == 0)
++		rc = count;
++	usb_unlock_device(udev);
++	return rc;
++}
++static DEVICE_ATTR(remove, 0200, NULL, usb_remove_store);
++
+ 
+ static struct attribute *dev_attrs[] = {
+ 	/* current configuration's attributes */
+@@ -533,6 +555,7 @@ static struct attribute *dev_attrs[] = {
+ 	&dev_attr_maxchild.attr,
+ 	&dev_attr_quirks.attr,
+ 	&dev_attr_authorized.attr,
++	&dev_attr_remove.attr,
+ 	NULL,
+ };
+ static struct attribute_group dev_attr_grp = {
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 9a8b15e6377a..4c36c7f512a0 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -24,6 +24,7 @@ extern void usb_disable_device(struct usb_device *dev, int skip_ep0);
+ extern int usb_deauthorize_device(struct usb_device *);
+ extern int usb_authorize_device(struct usb_device *);
+ extern void usb_detect_quirks(struct usb_device *udev);
++extern int usb_remove_device(struct usb_device *udev);
+ 
+ extern int usb_get_device_descriptor(struct usb_device *dev,
+ 		unsigned int size);

commit d697cdda43939a80432863e2e26df6701ce72b63
+Author: Alan Stern 
+Date:   Tue Oct 27 15:18:46 2009 -0400
+
+    USB: don't use a fixed DMA mapping for hub status URBs
+    
+    This patch (as1296) gets rid of the fixed DMA-buffer mapping used by
+    the hub driver for its status URB.  This URB doesn't get used much --
+    mainly when a device is plugged in or unplugged -- so the dynamic
+    mapping overhead is minimal.  And most systems have many fewer
+    external hubs than root hubs, which don't need a mapped buffer anyway.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 2ac115015229..708c63826100 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -45,7 +45,6 @@ struct usb_hub {
+ 
+ 	/* buffer for urb ... with extra space in case of babble */
+ 	char			(*buffer)[8];
+-	dma_addr_t		buffer_dma;	/* DMA address for buffer */
+ 	union {
+ 		struct usb_hub_status	hub;
+ 		struct usb_port_status	port;
+@@ -869,8 +868,7 @@ static int hub_configure(struct usb_hub *hub,
+ 	int maxp, ret;
+ 	char *message = "out of memory";
+ 
+-	hub->buffer = usb_buffer_alloc(hdev, sizeof(*hub->buffer), GFP_KERNEL,
+-			&hub->buffer_dma);
++	hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_KERNEL);
+ 	if (!hub->buffer) {
+ 		ret = -ENOMEM;
+ 		goto fail;
+@@ -1111,8 +1109,6 @@ static int hub_configure(struct usb_hub *hub,
+ 
+ 	usb_fill_int_urb(hub->urb, hdev, pipe, *hub->buffer, maxp, hub_irq,
+ 		hub, endpoint->bInterval);
+-	hub->urb->transfer_dma = hub->buffer_dma;
+-	hub->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ 
+ 	/* maybe cycle the hub leds */
+ 	if (hub->has_indicators && blinkenlights)
+@@ -1162,8 +1158,7 @@ static void hub_disconnect(struct usb_interface *intf)
+ 	kfree(hub->port_owners);
+ 	kfree(hub->descriptor);
+ 	kfree(hub->status);
+-	usb_buffer_free(hub->hdev, sizeof(*hub->buffer), hub->buffer,
+-			hub->buffer_dma);
++	kfree(hub->buffer);
+ 
+ 	kref_put(&hub->kref, hub_release);
+ }

commit 3589972e51fac1e02d0aaa576fa47f568cb94d40
+Author: Alan Stern 
+Date:   Fri Dec 4 11:06:57 2009 -0500
+
+    Driver core: fix race in dev_driver_string
+    
+    This patch (as1310) works around a race in dev_driver_string().  If
+    the device is unbound while the function is running, dev->driver might
+    become NULL after we test it and before we dereference it.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Cc: Oliver Neukum 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/base/core.c b/drivers/base/core.c
+index 353b13782165..f1290cbd1350 100644
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -56,7 +56,14 @@ static inline int device_is_not_partition(struct device *dev)
+  */
+ const char *dev_driver_string(const struct device *dev)
+ {
+-	return dev->driver ? dev->driver->name :
++	struct device_driver *drv;
++
++	/* dev->driver can change to NULL underneath us because of unbinding,
++	 * so be careful about accessing it.  dev->bus and dev->class should
++	 * never change once they are set, so they don't need special care.
++	 */
++	drv = ACCESS_ONCE(dev->driver);
++	return drv ? drv->name :
+ 			(dev->bus ? dev->bus->name :
+ 			(dev->class ? dev->class->name : ""));
+ }

commit 63c94801701abfea21570d3302687ec027ed33e8
+Author: Alan Stern 
+Date:   Thu Dec 3 20:22:34 2009 +0100
+
+    PM / Runtime: Use deferred_resume flag in pm_request_resume
+    
+    This patch (as1307) adds a small optimization to
+    __pm_request_resume().  If the device is currently being suspended,
+    there's no need to queue a work routine to resume it.  Setting the
+    deferred_resume flag will suffice.  (There's also a minor improvement
+    to the function's code layout: An unnecessary "else" is removed.)
+    
+    Also, the patch clarifies the usage of the deferred_resume flag.  It
+    is meaningful only while a suspend is in progress, so it should be
+    cleared just before a suspend starts, not just after one ends.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
+index 0a4b75f834c0..6e8577d1f750 100644
+--- a/drivers/base/power/runtime.c
++++ b/drivers/base/power/runtime.c
+@@ -185,6 +185,7 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq)
+ 	}
+ 
+ 	dev->power.runtime_status = RPM_SUSPENDING;
++	dev->power.deferred_resume = false;
+ 
+ 	if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) {
+ 		spin_unlock_irq(&dev->power.lock);
+@@ -200,7 +201,6 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq)
+ 	if (retval) {
+ 		dev->power.runtime_status = RPM_ACTIVE;
+ 		pm_runtime_cancel_pending(dev);
+-		dev->power.deferred_resume = false;
+ 
+ 		if (retval == -EAGAIN || retval == -EBUSY) {
+ 			notify = true;
+@@ -217,7 +217,6 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq)
+ 	wake_up_all(&dev->power.wait_queue);
+ 
+ 	if (dev->power.deferred_resume) {
+-		dev->power.deferred_resume = false;
+ 		__pm_runtime_resume(dev, false);
+ 		retval = -EAGAIN;
+ 		goto out;
+@@ -659,13 +658,17 @@ static int __pm_request_resume(struct device *dev)
+ 
+ 	pm_runtime_deactivate_timer(dev);
+ 
++	if (dev->power.runtime_status == RPM_SUSPENDING) {
++		dev->power.deferred_resume = true;
++		return retval;
++	}
+ 	if (dev->power.request_pending) {
+ 		/* If non-resume request is pending, we can overtake it. */
+ 		dev->power.request = retval ? RPM_REQ_NONE : RPM_REQ_RESUME;
+ 		return retval;
+-	} else if (retval) {
+-		return retval;
+ 	}
++	if (retval)
++		return retval;
+ 
+ 	dev->power.request = RPM_REQ_RESUME;
+ 	dev->power.request_pending = true;

commit 7b199ca2025f4756daceec8802f07da636c524c9
+Author: Alan Stern 
+Date:   Thu Dec 3 20:22:21 2009 +0100
+
+    PM / Runtime: Export the PM runtime workqueue
+    
+    This patch (as1306) exports the PM runtime workqueue for use by
+    loadable modules.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/kernel/power/main.c b/kernel/power/main.c
+index 347d2cc88cd0..0998c7139053 100644
+--- a/kernel/power/main.c
++++ b/kernel/power/main.c
+@@ -220,6 +220,7 @@ static struct attribute_group attr_group = {
+ 
+ #ifdef CONFIG_PM_RUNTIME
+ struct workqueue_struct *pm_wq;
++EXPORT_SYMBOL_GPL(pm_wq);
+ 
+ static int __init pm_start_workqueue(void)
+ {

commit c2f6595fbdb408d3d6850cfae590c8fa93e27399
+Author: Alan Stern 
+Date:   Wed Nov 18 11:37:15 2009 -0500
+
+    USB: EHCI: don't send Clear-TT-Buffer following a STALL
+    
+    This patch (as1304) fixes a regression in ehci-hcd.  Evidently some
+    hubs don't handle Clear-TT-Buffer requests correctly, so we should
+    avoid sending them when they don't appear to be absolutely necessary.
+    The reported symptom is that output on a downstream audio device cuts
+    out because the hub stops relaying isochronous packets.
+    
+    The patch prevents Clear-TT-Buffer requests from being sent following
+    a STALL handshake.  In theory a STALL indicates either that the
+    downstream device sent a STALL or that no matching TT buffer could be
+    found.  In either case, the transfer is completed and the TT buffer
+    does not remain busy, so it doesn't need to be cleared.
+    
+    Also, the patch fixes a minor flaw in the code that actually sends the
+    Clear-TT-Buffer requests.  Although the pipe direction isn't really
+    used for control transfers, it should be a Send rather than a Receive.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Javier Kohen 
+    CC: David Brownell 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 5ce839137ad6..0f857e645058 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -444,7 +444,7 @@ static void hub_irq(struct urb *urb)
+ static inline int
+ hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt)
+ {
+-	return usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
++	return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
+ 			       HUB_CLEAR_TT_BUFFER, USB_RT_PORT, devinfo,
+ 			       tt, NULL, 0, 1000);
+ }
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 00ad9ce392ed..139a2cc3f641 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -487,8 +487,20 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 			 * we must clear the TT buffer (11.17.5).
+ 			 */
+ 			if (unlikely(last_status != -EINPROGRESS &&
+-					last_status != -EREMOTEIO))
+-				ehci_clear_tt_buffer(ehci, qh, urb, token);
++					last_status != -EREMOTEIO)) {
++				/* The TT's in some hubs malfunction when they
++				 * receive this request following a STALL (they
++				 * stop sending isochronous packets).  Since a
++				 * STALL can't leave the TT buffer in a busy
++				 * state (if you believe Figures 11-48 - 11-51
++				 * in the USB 2.0 spec), we won't clear the TT
++				 * buffer in this case.  Strictly speaking this
++				 * is a violation of the spec.
++				 */
++				if (last_status != -EPIPE)
++					ehci_clear_tt_buffer(ehci, qh, urb,
++							token);
++			}
+ 		}
+ 
+ 		/* if we're removing something not at the queue head,

commit 862f89b3d4c6bf3caab7fc69661fc6e725edd00a
+Author: Alan Stern 
+Date:   Wed Nov 25 01:06:37 2009 +0100
+
+    PM: fix irq enable/disable in runtime PM code
+    
+    This patch (as1305) fixes a bug in the irq-enable settings and removes
+    some related overhead in the runtime PM code.
+    
+            In __pm_runtime_resume(), within the scope of the original
+            spin_lock_irq(), we know that irqs are disabled.  There's no
+            reason to go through a pair of enable/disable cycles when
+            acquiring and releasing the parent's lock.
+    
+            In __pm_runtime_set_status(), irqs are already disabled when
+            the parent's lock is acquired, and they must remain disabled
+            when it is released.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
+index a770498a74ec..846d89e3d122 100644
+--- a/drivers/base/power/runtime.c
++++ b/drivers/base/power/runtime.c
+@@ -328,11 +328,11 @@ int __pm_runtime_resume(struct device *dev, bool from_wq)
+ 		 * necessary.
+ 		 */
+ 		parent = dev->parent;
+-		spin_unlock_irq(&dev->power.lock);
++		spin_unlock(&dev->power.lock);
+ 
+ 		pm_runtime_get_noresume(parent);
+ 
+-		spin_lock_irq(&parent->power.lock);
++		spin_lock(&parent->power.lock);
+ 		/*
+ 		 * We can resume if the parent's run-time PM is disabled or it
+ 		 * is set to ignore children.
+@@ -343,9 +343,9 @@ int __pm_runtime_resume(struct device *dev, bool from_wq)
+ 			if (parent->power.runtime_status != RPM_ACTIVE)
+ 				retval = -EBUSY;
+ 		}
+-		spin_unlock_irq(&parent->power.lock);
++		spin_unlock(&parent->power.lock);
+ 
+-		spin_lock_irq(&dev->power.lock);
++		spin_lock(&dev->power.lock);
+ 		if (retval)
+ 			goto out;
+ 		goto repeat;
+@@ -777,7 +777,7 @@ int __pm_runtime_set_status(struct device *dev, unsigned int status)
+ 	}
+ 
+ 	if (parent) {
+-		spin_lock_irq(&parent->power.lock);
++		spin_lock(&parent->power.lock);
+ 
+ 		/*
+ 		 * It is invalid to put an active child under a parent that is
+@@ -793,7 +793,7 @@ int __pm_runtime_set_status(struct device *dev, unsigned int status)
+ 				atomic_inc(&parent->power.child_count);
+ 		}
+ 
+-		spin_unlock_irq(&parent->power.lock);
++		spin_unlock(&parent->power.lock);
+ 
+ 		if (error)
+ 			goto out;

commit fca94748c5136ff390eadc443871b82f1f77dcd6
+Author: Alan Stern 
+Date:   Wed Nov 4 11:35:53 2009 -0500
+
+    USB: usbmon: fix bug in mon_buff_area_shrink
+    
+    This patch (as1299b) fixes a bug in an error-handling path of usbmon's
+    binary interface.  The storage area for URB data is divided into
+    fixed-size blocks.  If an URB's data can't be copied, the area
+    reserved for it should be decreased to the size of the truncated
+    information (rounded up to a block boundary).  Rounding up the amount
+    to be removed and subtracting it from the reserved size is definitely
+    the wrong thing to do.
+    
+    Also, when the data for an isochronous URB can't be copied, we can
+    still copy the isoc packet descriptors.  In fact the current code does
+    copy the descriptors, but then sets the capture length to 0 so they
+    remain inaccessible.  The capture length should be reduced to the
+    length of the descriptors, not set to 0.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Pete Zaitcev 
+    CC: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
+index 9ed3e741bee1..10f3205798e8 100644
+--- a/drivers/usb/mon/mon_bin.c
++++ b/drivers/usb/mon/mon_bin.c
+@@ -348,12 +348,12 @@ static unsigned int mon_buff_area_alloc_contiguous(struct mon_reader_bin *rp,
+ 
+ /*
+  * Return a few (kilo-)bytes to the head of the buffer.
+- * This is used if a DMA fetch fails.
++ * This is used if a data fetch fails.
+  */
+ static void mon_buff_area_shrink(struct mon_reader_bin *rp, unsigned int size)
+ {
+ 
+-	size = (size + PKT_ALIGN-1) & ~(PKT_ALIGN-1);
++	/* size &= ~(PKT_ALIGN-1);  -- we're called with aligned size */
+ 	rp->b_cnt -= size;
+ 	if (rp->b_in < size)
+ 		rp->b_in += rp->b_size;
+@@ -433,6 +433,7 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
+ 	unsigned int urb_length;
+ 	unsigned int offset;
+ 	unsigned int length;
++	unsigned int delta;
+ 	unsigned int ndesc, lendesc;
+ 	unsigned char dir;
+ 	struct mon_bin_hdr *ep;
+@@ -537,8 +538,10 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
+ 	if (length != 0) {
+ 		ep->flag_data = mon_bin_get_data(rp, offset, urb, length);
+ 		if (ep->flag_data != 0) {	/* Yes, it's 0x00, not '0' */
+-			ep->len_cap = 0;
+-			mon_buff_area_shrink(rp, length);
++			delta = (ep->len_cap + PKT_ALIGN-1) & ~(PKT_ALIGN-1);
++			ep->len_cap -= length;
++			delta -= (ep->len_cap + PKT_ALIGN-1) & ~(PKT_ALIGN-1);
++			mon_buff_area_shrink(rp, delta);
+ 		}
+ 	} else {
+ 		ep->flag_data = data_tag;

commit f1a0743bc0e7a30c032b1eb78f6a2b0f805b4597
+Author: Alan Stern 
+Date:   Tue Oct 6 14:07:57 2009 -0400
+
+    USB: storage: When a device returns no sense data, call it a Hardware Error
+    
+    This patch (as1294) fixes a problem that has plagued users for several
+    kernel releases.  Some USB mass-storage devices don't return any sense
+    data when they encounter certain kinds of errors.  The SCSI layer
+    interprets this to mean that the operation should be retried, and the
+    same thing happens -- over and over again with no limit.  In some
+    circumstances (such as when a bus reset occurs) that is the right
+    thing to do, but not here.
+    
+    The patch checks for this condition (a transport failure with no sense
+    data) and changes the result code to DID_ERROR and the sense code to
+    Hardware Error.  This does get only a limited number of retries, and
+    so the command will fail relatively quickly instead of getting stuck
+    in an infinite loop.
+    
+    This fixes a large part of Bugzilla #14118.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Mantas Mikulenas 
+    CC: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+index e20dc525d177..3a4fb023af72 100644
+--- a/drivers/usb/storage/transport.c
++++ b/drivers/usb/storage/transport.c
+@@ -768,17 +768,32 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 		/* set the result so the higher layers expect this data */
+ 		srb->result = SAM_STAT_CHECK_CONDITION;
+ 
+-		/* If things are really okay, then let's show that.  Zero
+-		 * out the sense buffer so the higher layers won't realize
+-		 * we did an unsolicited auto-sense. */
+-		if (result == USB_STOR_TRANSPORT_GOOD &&
+-			/* Filemark 0, ignore EOM, ILI 0, no sense */
++		/* We often get empty sense data.  This could indicate that
++		 * everything worked or that there was an unspecified
++		 * problem.  We have to decide which.
++		 */
++		if (	/* Filemark 0, ignore EOM, ILI 0, no sense */
+ 				(srb->sense_buffer[2] & 0xaf) == 0 &&
+ 			/* No ASC or ASCQ */
+ 				srb->sense_buffer[12] == 0 &&
+ 				srb->sense_buffer[13] == 0) {
+-			srb->result = SAM_STAT_GOOD;
+-			srb->sense_buffer[0] = 0x0;
++
++			/* If things are really okay, then let's show that.
++			 * Zero out the sense buffer so the higher layers
++			 * won't realize we did an unsolicited auto-sense.
++			 */
++			if (result == USB_STOR_TRANSPORT_GOOD) {
++				srb->result = SAM_STAT_GOOD;
++				srb->sense_buffer[0] = 0x0;
++
++			/* If there was a problem, report an unspecified
++			 * hardware error to prevent the higher layers from
++			 * entering an infinite retry loop.
++			 */
++			} else {
++				srb->result = DID_ERROR << 16;
++				srb->sense_buffer[2] = HARDWARE_ERROR;
++			}
+ 		}
+ 	}
+ 

commit 06bad89da686f6323e95cf925105e8cf88d87caf
+Author: Alan Stern 
+Date:   Mon Oct 5 15:53:58 2009 -0400
+
+    USB: ipaq: fix oops when device is plugged in
+    
+    This patch (as1293) fixes a problem with the ipaq serial driver.  It
+    tries to bind to all the interfaces, even those that don't have enough
+    endpoints.  The symptom is an invalid memory reference and oops when
+    the device is plugged in.
+    
+    Signed-off-by: Alan Stern 
+    CC: stable 
+    Tested-by: Matthias Geissert 
+    Tested-by: Tilman Schmidt 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
+index 24fcc64b837d..d6231c38813e 100644
+--- a/drivers/usb/serial/ipaq.c
++++ b/drivers/usb/serial/ipaq.c
+@@ -966,6 +966,15 @@ static int ipaq_calc_num_ports(struct usb_serial *serial)
+ static int ipaq_startup(struct usb_serial *serial)
+ {
+ 	dbg("%s", __func__);
++
++	/* Some of the devices in ipaq_id_table[] are composite, and we
++	 * shouldn't bind to all the interfaces.  This test will rule out
++	 * some obviously invalid possibilities.
++	 */
++	if (serial->num_bulk_in < serial->num_ports ||
++			serial->num_bulk_out < serial->num_ports)
++		return -ENODEV;
++
+ 	if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
+ 		/*
+ 		 * FIXME: HP iPaq rx3715, possibly others, have 1 config that

commit a4720c650b68a5fe7faed2edeb0ad12645f7ae63
+Author: Alan Stern 
+Date:   Fri Oct 9 12:43:12 2009 -0400
+
+    USB: serial: don't call release without attach
+    
+    This patch (as1295) fixes a recently-added bug in the USB serial core.
+    If certain kinds of errors occur during probing, the core may call a
+    serial driver's release method without previously calling the attach
+    method.  This causes some drivers (io_ti in particular) to perform an
+    invalid memory access.
+    
+    The patch adds a new flag to keep track of whether or not attach has
+    been called.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Jean-Denis Girard 
+    CC: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
+index aa6b2ae951ae..2d0f75d63ff0 100644
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -156,7 +156,8 @@ static void destroy_serial(struct kref *kref)
+ 	if (serial->minor != SERIAL_TTY_NO_MINOR)
+ 		return_serial(serial);
+ 
+-	serial->type->release(serial);
++	if (serial->attached)
++		serial->type->release(serial);
+ 
+ 	/* Now that nothing is using the ports, they can be freed */
+ 	for (i = 0; i < serial->num_port_pointers; ++i) {
+@@ -1059,12 +1060,15 @@ int usb_serial_probe(struct usb_interface *interface,
+ 		module_put(type->driver.owner);
+ 		if (retval < 0)
+ 			goto probe_error;
++		serial->attached = 1;
+ 		if (retval > 0) {
+ 			/* quietly accept this device, but don't bind to a
+ 			   serial port as it's about to disappear */
+ 			serial->num_ports = 0;
+ 			goto exit;
+ 		}
++	} else {
++		serial->attached = 1;
+ 	}
+ 
+ 	if (get_free_serial(serial, num_ports, &minor) == NULL) {
+diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
+index c17eb64d7213..ce911ebf91e8 100644
+--- a/include/linux/usb/serial.h
++++ b/include/linux/usb/serial.h
+@@ -150,6 +150,7 @@ struct usb_serial {
+ 	struct usb_interface		*interface;
+ 	unsigned char			disconnected:1;
+ 	unsigned char			suspending:1;
++	unsigned char			attached:1;
+ 	unsigned char			minor;
+ 	unsigned char			num_ports;
+ 	unsigned char			num_port_pointers;

commit 01c6460f968d7b57fc6f98adb587952628c6e099
+Author: Alan Stern 
+Date:   Tue Sep 1 11:09:56 2009 -0400
+
+    USB: usbfs: add USBDEVFS_URB_BULK_CONTINUATION flag
+    
+    This patch (as1283) adds a new flag, USBDEVFS_URB_BULK_CONTINUATION,
+    to usbfs.  It is intended for userspace libraries such as libusb and
+    openusb.  When they have to break up a single usbfs bulk transfer into
+    multiple URBs, they will set the flag on all but the first URB of the
+    series.
+    
+    If an error other than an unlink occurs, the kernel will automatically
+    cancel all the following URBs for the same endpoint and refuse to
+    accept new submissions, until an URB is encountered that is not marked
+    as a BULK_CONTINUATION.  Such an URB would indicate the start of a new
+    transfer or the presence of an older library, so the kernel returns to
+    normal operation.
+    
+    This enables libraries to delimit bulk transfers correctly, even in
+    the presence of early termination as indicated by short packets.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 71514be8b715..181f78c84105 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -74,6 +74,7 @@ struct dev_state {
+ 	void __user *disccontext;
+ 	unsigned long ifclaimed;
+ 	u32 secid;
++	u32 disabled_bulk_eps;
+ };
+ 
+ struct async {
+@@ -88,6 +89,8 @@ struct async {
+ 	struct urb *urb;
+ 	int status;
+ 	u32 secid;
++	u8 bulk_addr;
++	u8 bulk_status;
+ };
+ 
+ static int usbfs_snoop;
+@@ -343,6 +346,43 @@ static void snoop_urb(struct usb_device *udev,
+ 	}
+ }
+ 
++#define AS_CONTINUATION	1
++#define AS_UNLINK	2
++
++static void cancel_bulk_urbs(struct dev_state *ps, unsigned bulk_addr)
++__releases(ps->lock)
++__acquires(ps->lock)
++{
++	struct async *as;
++
++	/* Mark all the pending URBs that match bulk_addr, up to but not
++	 * including the first one without AS_CONTINUATION.  If such an
++	 * URB is encountered then a new transfer has already started so
++	 * the endpoint doesn't need to be disabled; otherwise it does.
++	 */
++	list_for_each_entry(as, &ps->async_pending, asynclist) {
++		if (as->bulk_addr == bulk_addr) {
++			if (as->bulk_status != AS_CONTINUATION)
++				goto rescan;
++			as->bulk_status = AS_UNLINK;
++			as->bulk_addr = 0;
++		}
++	}
++	ps->disabled_bulk_eps |= (1 << bulk_addr);
++
++	/* Now carefully unlink all the marked pending URBs */
++ rescan:
++	list_for_each_entry(as, &ps->async_pending, asynclist) {
++		if (as->bulk_status == AS_UNLINK) {
++			as->bulk_status = 0;		/* Only once */
++			spin_unlock(&ps->lock);		/* Allow completions */
++			usb_unlink_urb(as->urb);
++			spin_lock(&ps->lock);
++			goto rescan;
++		}
++	}
++}
++
+ static void async_completed(struct urb *urb)
+ {
+ 	struct async *as = urb->context;
+@@ -371,6 +411,9 @@ static void async_completed(struct urb *urb)
+ 	snoop(&urb->dev->dev, "urb complete\n");
+ 	snoop_urb(urb->dev, as->userurb, urb->pipe, urb->actual_length,
+ 			as->status, COMPLETE);
++	if (as->status < 0 && as->bulk_addr && as->status != -ECONNRESET &&
++			as->status != -ENOENT)
++		cancel_bulk_urbs(ps, as->bulk_addr);
+ 	spin_unlock(&ps->lock);
+ 
+ 	if (signr)
+@@ -993,6 +1036,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 
+ 	if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP |
+ 				USBDEVFS_URB_SHORT_NOT_OK |
++				USBDEVFS_URB_BULK_CONTINUATION |
+ 				USBDEVFS_URB_NO_FSBR |
+ 				USBDEVFS_URB_ZERO_PACKET |
+ 				USBDEVFS_URB_NO_INTERRUPT))
+@@ -1194,7 +1238,39 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 	snoop_urb(ps->dev, as->userurb, as->urb->pipe,
+ 			as->urb->transfer_buffer_length, 0, SUBMIT);
+ 	async_newpending(as);
+-	if ((ret = usb_submit_urb(as->urb, GFP_KERNEL))) {
++
++	if (usb_endpoint_xfer_bulk(&ep->desc)) {
++		spin_lock_irq(&ps->lock);
++
++		/* Not exactly the endpoint address; the direction bit is
++		 * shifted to the 0x10 position so that the value will be
++		 * between 0 and 31.
++		 */
++		as->bulk_addr = usb_endpoint_num(&ep->desc) |
++			((ep->desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK)
++				>> 3);
++
++		/* If this bulk URB is the start of a new transfer, re-enable
++		 * the endpoint.  Otherwise mark it as a continuation URB.
++		 */
++		if (uurb->flags & USBDEVFS_URB_BULK_CONTINUATION)
++			as->bulk_status = AS_CONTINUATION;
++		else
++			ps->disabled_bulk_eps &= ~(1 << as->bulk_addr);
++
++		/* Don't accept continuation URBs if the endpoint is
++		 * disabled because of an earlier error.
++		 */
++		if (ps->disabled_bulk_eps & (1 << as->bulk_addr))
++			ret = -EREMOTEIO;
++		else
++			ret = usb_submit_urb(as->urb, GFP_ATOMIC);
++		spin_unlock_irq(&ps->lock);
++	} else {
++		ret = usb_submit_urb(as->urb, GFP_KERNEL);
++	}
++
++	if (ret) {
+ 		dev_printk(KERN_DEBUG, &ps->dev->dev,
+ 			   "usbfs: usb_submit_urb returned %d\n", ret);
+ 		snoop_urb(ps->dev, as->userurb, as->urb->pipe,
+diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
+index 00ceebeb9e5c..b2a7d8ba6ee3 100644
+--- a/include/linux/usbdevice_fs.h
++++ b/include/linux/usbdevice_fs.h
+@@ -77,6 +77,7 @@ struct usbdevfs_connectinfo {
+ 
+ #define USBDEVFS_URB_SHORT_NOT_OK	0x01
+ #define USBDEVFS_URB_ISO_ASAP		0x02
++#define USBDEVFS_URB_BULK_CONTINUATION	0x04
+ #define USBDEVFS_URB_NO_FSBR		0x20
+ #define USBDEVFS_URB_ZERO_PACKET	0x40
+ #define USBDEVFS_URB_NO_INTERRUPT	0x80

commit a448c9d8c58ff7d3f8cc2a8f835065460099b22d
+Author: Alan Stern 
+Date:   Wed Aug 19 12:22:44 2009 -0400
+
+    USB: EHCI: change deschedule logic for interrupt QHs
+    
+    This patch (as1281) changes the way ehci-hcd deschedules interrupt
+    QHs, copying the approach used for async QHs.  The caller is no longer
+    responsible for rescheduling the QH if its queue is non-empty; instead
+    the reschedule is done directly by intr_deschedule(), after calling
+    qh_completions().  This is exactly the same as how end_unlink_async()
+    works.
+    
+    ehci_urb_dequeue() and intr_deschedule() now correctly handle the case
+    where they are called while another interrupt URB for the same QH is
+    being given back.  This was a surprisingly large blind spot.  And
+    scan_periodic() now respects the new needs_rescan flag.
+    
+    Signed-off-by: Alan Stern 
+    CC: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index d7e85b6231b3..4f89d7ffd53a 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -934,8 +934,9 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ 			break;
+ 		switch (qh->qh_state) {
+ 		case QH_STATE_LINKED:
++		case QH_STATE_COMPLETING:
+ 			intr_deschedule (ehci, qh);
+-			/* FALL THROUGH */
++			break;
+ 		case QH_STATE_IDLE:
+ 			qh_completions (ehci, qh);
+ 			break;
+@@ -944,23 +945,6 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ 					qh, qh->qh_state);
+ 			goto done;
+ 		}
+-
+-		/* reschedule QH iff another request is queued */
+-		if (!list_empty (&qh->qtd_list)
+-				&& HC_IS_RUNNING (hcd->state)) {
+-			rc = qh_schedule(ehci, qh);
+-
+-			/* An error here likely indicates handshake failure
+-			 * or no space left in the schedule.  Neither fault
+-			 * should happen often ...
+-			 *
+-			 * FIXME kill the now-dysfunctional queued urbs
+-			 */
+-			if (rc != 0)
+-				ehci_err(ehci,
+-					"can't reschedule qh %p, err %d",
+-					qh, rc);
+-		}
+ 		break;
+ 
+ 	case PIPE_ISOCHRONOUS:
+@@ -1079,12 +1063,10 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 			 * while the QH is active.  Unlink it now;
+ 			 * re-linking will call qh_refresh().
+ 			 */
+-			if (eptype == USB_ENDPOINT_XFER_BULK) {
++			if (eptype == USB_ENDPOINT_XFER_BULK)
+ 				unlink_async(ehci, qh);
+-			} else {
++			else
+ 				intr_deschedule(ehci, qh);
+-				(void) qh_schedule(ehci, qh);
+-			}
+ 		}
+ 	}
+ 	spin_unlock_irqrestore(&ehci->lock, flags);
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 57a84795c43f..00ad9ce392ed 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -299,7 +299,6 @@ __acquires(ehci->lock)
+ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh);
+ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh);
+ 
+-static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh);
+ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh);
+ 
+ /*
+@@ -555,14 +554,9 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 			 * That should be rare for interrupt transfers,
+ 			 * except maybe high bandwidth ...
+ 			 */
+-			if ((cpu_to_hc32(ehci, QH_SMASK)
+-					& hw->hw_info2) != 0) {
+-				intr_deschedule (ehci, qh);
+-				(void) qh_schedule (ehci, qh);
+-			} else {
+-				/* Tell the caller to start an unlink */
+-				qh->needs_rescan = 1;
+-			}
++
++			/* Tell the caller to start an unlink */
++			qh->needs_rescan = 1;
+ 			break;
+ 		/* otherwise, unlink already started */
+ 		}
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 327437af2122..3ea05936851f 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -615,8 +615,19 @@ static int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 
+ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ {
+-	unsigned	wait;
+-	struct ehci_qh_hw *hw = qh->hw;
++	unsigned		wait;
++	struct ehci_qh_hw	*hw = qh->hw;
++	int			rc;
++
++	/* If the QH isn't linked then there's nothing we can do
++	 * unless we were called during a giveback, in which case
++	 * qh_completions() has to deal with it.
++	 */
++	if (qh->qh_state != QH_STATE_LINKED) {
++		if (qh->qh_state == QH_STATE_COMPLETING)
++			qh->needs_rescan = 1;
++		return;
++	}
+ 
+ 	qh_unlink_periodic (ehci, qh);
+ 
+@@ -636,6 +647,24 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	qh->qh_state = QH_STATE_IDLE;
+ 	hw->hw_next = EHCI_LIST_END(ehci);
+ 	wmb ();
++
++	qh_completions(ehci, qh);
++
++	/* reschedule QH iff another request is queued */
++	if (!list_empty(&qh->qtd_list) &&
++			HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) {
++		rc = qh_schedule(ehci, qh);
++
++		/* An error here likely indicates handshake failure
++		 * or no space left in the schedule.  Neither fault
++		 * should happen often ...
++		 *
++		 * FIXME kill the now-dysfunctional queued urbs
++		 */
++		if (rc != 0)
++			ehci_err(ehci, "can't reschedule qh %p, err %d\n",
++					qh, rc);
++	}
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -2213,7 +2242,8 @@ scan_periodic (struct ehci_hcd *ehci)
+ 				type = Q_NEXT_TYPE(ehci, q.qh->hw->hw_next);
+ 				q = q.qh->qh_next;
+ 				modified = qh_completions (ehci, temp.qh);
+-				if (unlikely (list_empty (&temp.qh->qtd_list)))
++				if (unlikely(list_empty(&temp.qh->qtd_list) ||
++						temp.qh->needs_rescan))
+ 					intr_deschedule (ehci, temp.qh);
+ 				qh_put (temp.qh);
+ 				break;

commit 3a44494e233c0fdd818d485cfea8998500543589
+Author: Alan Stern 
+Date:   Wed Aug 19 12:22:06 2009 -0400
+
+    USB: EHCI: rescan the queue after an unlink
+    
+    This patch (as1280) fixes an obscure bug in ehci-hcd's dequeuing logic
+    for async URBs.  If a later URB is unlinked and the completion
+    routine unlinks an earlier URB, then the earlier URB won't be given
+    back in a timely manner because the endpoint queue isn't rescanned as
+    it should be.
+    
+    Similar bugs occur if an endpoint is reset or a halt is cleared while
+    a completion routine is running, because the subroutines don't test
+    for the COMPLETING state.
+    
+    All these problems are solved by adding a new needs_rescan flag to the
+    ehci_qh structure.  If the flag is set while scanning through an idle
+    QH, the scan will be repeated.  If the QH isn't idle then an unlink
+    cycle will be initiated, and the proper action will be taken when it
+    becomes idle.
+    
+    Also, an unnecessary test is removed from qh_link_async(): That
+    routine is never called if the QH's state isn't IDLE.
+    
+    Signed-off-by: Alan Stern 
+    CC: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 6887aac5e73d..d7e85b6231b3 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -863,12 +863,18 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state) && ehci->reclaim)
+ 		end_unlink_async(ehci);
+ 
+-	/* if it's not linked then there's nothing to do */
+-	if (qh->qh_state != QH_STATE_LINKED)
+-		;
++	/* If the QH isn't linked then there's nothing we can do
++	 * unless we were called during a giveback, in which case
++	 * qh_completions() has to deal with it.
++	 */
++	if (qh->qh_state != QH_STATE_LINKED) {
++		if (qh->qh_state == QH_STATE_COMPLETING)
++			qh->needs_rescan = 1;
++		return;
++	}
+ 
+ 	/* defer till later if busy */
+-	else if (ehci->reclaim) {
++	if (ehci->reclaim) {
+ 		struct ehci_qh		*last;
+ 
+ 		for (last = ehci->reclaim;
+@@ -1001,6 +1007,7 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 		qh->qh_state = QH_STATE_IDLE;
+ 	switch (qh->qh_state) {
+ 	case QH_STATE_LINKED:
++	case QH_STATE_COMPLETING:
+ 		for (tmp = ehci->async->qh_next.qh;
+ 				tmp && tmp != qh;
+ 				tmp = tmp->qh_next.qh)
+@@ -1065,7 +1072,8 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 		usb_settoggle(qh->dev, epnum, is_out, 0);
+ 		if (!list_empty(&qh->qtd_list)) {
+ 			WARN_ONCE(1, "clear_halt for a busy endpoint\n");
+-		} else if (qh->qh_state == QH_STATE_LINKED) {
++		} else if (qh->qh_state == QH_STATE_LINKED ||
++				qh->qh_state == QH_STATE_COMPLETING) {
+ 
+ 			/* The toggle value in the QH can't be updated
+ 			 * while the QH is active.  Unlink it now;
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 377ed530b920..57a84795c43f 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -310,13 +310,13 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh);
+ static unsigned
+ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ {
+-	struct ehci_qtd		*last = NULL, *end = qh->dummy;
++	struct ehci_qtd		*last, *end = qh->dummy;
+ 	struct list_head	*entry, *tmp;
+-	int			last_status = -EINPROGRESS;
++	int			last_status;
+ 	int			stopped;
+ 	unsigned		count = 0;
+ 	u8			state;
+-	__le32			halt = HALT_BIT(ehci);
++	const __le32		halt = HALT_BIT(ehci);
+ 	struct ehci_qh_hw	*hw = qh->hw;
+ 
+ 	if (unlikely (list_empty (&qh->qtd_list)))
+@@ -327,11 +327,20 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	 * they add urbs to this qh's queue or mark them for unlinking.
+ 	 *
+ 	 * NOTE:  unlinking expects to be done in queue order.
++	 *
++	 * It's a bug for qh->qh_state to be anything other than
++	 * QH_STATE_IDLE, unless our caller is scan_async() or
++	 * scan_periodic().
+ 	 */
+ 	state = qh->qh_state;
+ 	qh->qh_state = QH_STATE_COMPLETING;
+ 	stopped = (state == QH_STATE_IDLE);
+ 
++ rescan:
++	last = NULL;
++	last_status = -EINPROGRESS;
++	qh->needs_rescan = 0;
++
+ 	/* remove de-activated QTDs from front of queue.
+ 	 * after faults (including short reads), cleanup this urb
+ 	 * then let the queue advance.
+@@ -507,6 +516,21 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		ehci_qtd_free (ehci, last);
+ 	}
+ 
++	/* Do we need to rescan for URBs dequeued during a giveback? */
++	if (unlikely(qh->needs_rescan)) {
++		/* If the QH is already unlinked, do the rescan now. */
++		if (state == QH_STATE_IDLE)
++			goto rescan;
++
++		/* Otherwise we have to wait until the QH is fully unlinked.
++		 * Our caller will start an unlink if qh->needs_rescan is
++		 * set.  But if an unlink has already started, nothing needs
++		 * to be done.
++		 */
++		if (state != QH_STATE_LINKED)
++			qh->needs_rescan = 0;
++	}
++
+ 	/* restore original state; caller must unlink or relink */
+ 	qh->qh_state = state;
+ 
+@@ -535,8 +559,10 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 					& hw->hw_info2) != 0) {
+ 				intr_deschedule (ehci, qh);
+ 				(void) qh_schedule (ehci, qh);
+-			} else
+-				unlink_async (ehci, qh);
++			} else {
++				/* Tell the caller to start an unlink */
++				qh->needs_rescan = 1;
++			}
+ 			break;
+ 		/* otherwise, unlink already started */
+ 		}
+@@ -916,6 +942,8 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	if (unlikely(qh->clearing_tt))
+ 		return;
+ 
++	WARN_ON(qh->qh_state != QH_STATE_IDLE);
++
+ 	/* (re)start the async schedule? */
+ 	head = ehci->async;
+ 	timer_action_done (ehci, TIMER_ASYNC_OFF);
+@@ -934,8 +962,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	}
+ 
+ 	/* clear halt and/or toggle; and maybe recover from silicon quirk */
+-	if (qh->qh_state == QH_STATE_IDLE)
+-		qh_refresh (ehci, qh);
++	qh_refresh(ehci, qh);
+ 
+ 	/* splice right after start */
+ 	qh->qh_next = head->qh_next;
+@@ -1220,6 +1247,8 @@ static void scan_async (struct ehci_hcd *ehci)
+ 				qh = qh_get (qh);
+ 				qh->stamp = ehci->stamp;
+ 				temp = qh_completions (ehci, qh);
++				if (qh->needs_rescan)
++					unlink_async(ehci, qh);
+ 				qh_put (qh);
+ 				if (temp != 0) {
+ 					goto rescan;
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index ec3dba6b8e48..064e76821ff5 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -341,6 +341,7 @@ struct ehci_qh {
+ 	u32			refcount;
+ 	unsigned		stamp;
+ 
++	u8			needs_rescan;	/* Dequeue during giveback */
+ 	u8			qh_state;
+ #define	QH_STATE_LINKED		1		/* HC sees this */
+ #define	QH_STATE_UNLINK		2		/* HC may still see this */

commit 823c3fd9cc71714fe22ea415a68da746800d5a9a
+Author: Alan Stern 
+Date:   Mon Aug 3 11:05:59 2009 -0400
+
+    USB: s3c2410: unregister should call unbind, not disconnect
+    
+    This patch (as1275) fixes the s3c2410 device controller driver.  Its
+    usb_gadget_unregister_driver() routine is supposed to call the gadget
+    driver's unbind method, not the disconnect method.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
+index a9b452fe6221..d5f4c1d45c97 100644
+--- a/drivers/usb/gadget/s3c2410_udc.c
++++ b/drivers/usb/gadget/s3c2410_udc.c
+@@ -1703,8 +1703,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+ 	dprintk(DEBUG_NORMAL,"usb_gadget_register_driver() '%s'\n",
+ 		driver->driver.name);
+ 
+-	if (driver->disconnect)
+-		driver->disconnect(&udc->gadget);
++	driver->unbind(&udc->gadget);
+ 
+ 	device_del(&udc->gadget.dev);
+ 	udc->driver = NULL;

commit e9238221d3fef990e2fd01702ebe5af90dda52a2
+Author: Alan Stern 
+Date:   Wed Jul 22 14:44:17 2009 -0400
+
+    USB: dummy-hcd: accept mismatch between wLength and transfer length
+    
+    This patch (as1269) fixes a bug in the way dummy_hcd handles control
+    URBs.  Currently it returns a -EOVERFLOW error if the wLength value in
+    the setup packet is different from the URB's transfer_buffer_length.
+    
+    Other host controller drivers don't do this.  There's no reason the
+    two length values have to be equal, and in fact they sometimes aren't
+    -- a driver might set the transfer length to the maxpacket value in
+    order to handle buggy devices that don't respect wLength.
+    
+    This patch simply removes the unnecessary check and error return.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index a56b24d305f8..5e0966485188 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -1306,11 +1306,6 @@ static void dummy_timer (unsigned long _dum)
+ 			setup = *(struct usb_ctrlrequest*) urb->setup_packet;
+ 			w_index = le16_to_cpu(setup.wIndex);
+ 			w_value = le16_to_cpu(setup.wValue);
+-			if (le16_to_cpu(setup.wLength) !=
+-					urb->transfer_buffer_length) {
+-				status = -EOVERFLOW;
+-				goto return_urb;
+-			}
+ 
+ 			/* paranoia, in case of stale queued data */
+ 			list_for_each_entry (req, &ep->queue, queue) {

commit 527101ce6a96c037a2555aa43222faa6fdd21e97
+Author: Alan Stern 
+Date:   Wed Jul 22 14:42:54 2009 -0400
+
+    USB: don't lose mode switch events on suspended devices
+    
+    This patch (as1268) changes the way usbcore handles child devices that
+    undergo a disconnection and reconnection while the parent hub is
+    suspended.  Currently, if the child isn't enabled for remote wakeup we
+    leave it alone, figuring that it will go through a reset-resume when
+    somebody tries to use it.
+    
+    However this isn't a good approach if the reason for the disconnection
+    is that the child decided to switch modes or in some other way alter
+    its descriptors.  In that case we want to re-enumerate it as soon as
+    possible, not wait until somebody forces a reset-resume.
+    
+    To resolve the issue, this patch treats reconnected suspended child
+    devices as though they had requested a remote wakeup, even if they
+    weren't enabled for it.  The mode switch or descriptor change will be
+    detected during the reset part of the reset-resume, and the device
+    will be re-enumerated immediately.
+    
+    The disadvantage of this change is that it will cause autosuspended
+    devices to be resumed when the computer wakes up from a system sleep
+    during which the root hub was reset or lost power.  This shouldn't
+    matter much; some people would even argue that autosuspended devices
+    should _always_ be resumed when the system wakes up!
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: "Yang Fei-AFY095" 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 645686a14214..a880516020f3 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2932,14 +2932,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 			/* For a suspended device, treat this as a
+ 			 * remote wakeup event.
+ 			 */
+-			if (udev->do_remote_wakeup)
+-				status = remote_wakeup(udev);
+-
+-			/* Otherwise leave it be; devices can't tell the
+-			 * difference between suspended and disabled.
+-			 */
+-			else
+-				status = 0;
++			status = remote_wakeup(udev);
+ #endif
+ 
+ 		} else {

commit 25118084ef03f4fc314ab33ef6a9d9271d0e616a
+Author: Alan Stern 
+Date:   Wed Jul 22 14:41:18 2009 -0400
+
+    USB: check for hub driver not bound to root hub device
+    
+    This patch (as1267) changes usb_kick_khubd() and hdev_to_hub() to make
+    them more resilient against situations where a hub device isn't bound
+    to the hub driver.  The code assumes that if a root hub was
+    successfully registered then it must be bound to the hub driver.
+    
+    But this assumption can fail if the user manually unbinds the hub
+    driver, or more importantly, if the host controller dies causing
+    usb_set_configuration to fail.
+    
+    To protect against these possibilities, make hdev_to_hub() check that
+    the hub device is configured before dereferencing the active
+    configuration, and make usb_kick_khubd() check that the pointer to the
+    hub's private data structure isn't NULL.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 69e3a966a4b7..645686a14214 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -163,8 +163,10 @@ static inline char *portspeed(int portstatus)
+ }
+ 
+ /* Note that hdev or one of its children must be locked! */
+-static inline struct usb_hub *hdev_to_hub(struct usb_device *hdev)
++static struct usb_hub *hdev_to_hub(struct usb_device *hdev)
+ {
++	if (!hdev || !hdev->actconfig)
++		return NULL;
+ 	return usb_get_intfdata(hdev->actconfig->interface[0]);
+ }
+ 
+@@ -385,8 +387,10 @@ static void kick_khubd(struct usb_hub *hub)
+ 
+ void usb_kick_khubd(struct usb_device *hdev)
+ {
+-	/* FIXME: What if hdev isn't bound to the hub driver? */
+-	kick_khubd(hdev_to_hub(hdev));
++	struct usb_hub *hub = hdev_to_hub(hdev);
++
++	if (hub)
++		kick_khubd(hub);
+ }
+ 
+ 

commit 4c6e8971cbe0148085fcf6fd30eaa3c39f8a8cce
+Author: Alan Stern 
+Date:   Mon Jun 29 11:02:04 2009 -0400
+
+    USB: make the "usbfs_snoop" log more pertinent
+    
+    This patch (as1261) reduces the amount of detailed URB information
+    logged by usbfs when the usbfs_snoop parameter is enabled.
+    
+    Currently we don't display the final status value for a completed URB.
+    But we do display the entire data buffer twice: both before submission
+    and after completion.  The after-completion display doesn't limit
+    itself to the actual_length value.  But since usbmon is readily
+    available in virtually all distributions, there's no reason for usbfs
+    to print out any buffer contents at all!
+    
+    So this patch restricts the information to: userspace buffer pointer,
+    endpoint number, type, and direction, length or actual_length, and
+    timeout value or status.  Now everything fits neatly into a single
+    line.
+    
+    Along with those changes, the patch also fixes the snoop output for
+    the REAPURBNDELAY and REAPURBNDELAY32 ioctls.  The current version
+    omits the 'N' from the names.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 165de5d59005..a1add776e89a 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -100,11 +100,15 @@ MODULE_PARM_DESC(usbfs_snoop, "true to log all usbfs traffic");
+ 			dev_info(dev , format , ## arg);	\
+ 	} while (0)
+ 
+-#define USB_DEVICE_DEV		MKDEV(USB_DEVICE_MAJOR, 0)
++enum snoop_when {
++	SUBMIT, COMPLETE
++};
+ 
++#define USB_DEVICE_DEV		MKDEV(USB_DEVICE_MAJOR, 0)
+ 
+ #define	MAX_USBFS_BUFFER_SIZE	16384
+ 
++
+ static int connected(struct dev_state *ps)
+ {
+ 	return (!list_empty(&ps->list) &&
+@@ -301,24 +305,42 @@ static struct async *async_getpending(struct dev_state *ps,
+ 	return NULL;
+ }
+ 
+-static void snoop_urb(struct urb *urb, void __user *userurb)
++static void snoop_urb(struct usb_device *udev,
++		void __user *userurb, int pipe, unsigned length,
++		int timeout_or_status, enum snoop_when when)
+ {
+-	unsigned j;
+-	unsigned char *data = urb->transfer_buffer;
++	static const char *types[] = {"isoc", "int", "ctrl", "bulk"};
++	static const char *dirs[] = {"out", "in"};
++	int ep;
++	const char *t, *d;
+ 
+ 	if (!usbfs_snoop)
+ 		return;
+ 
+-	dev_info(&urb->dev->dev, "direction=%s\n",
+-			usb_urb_dir_in(urb) ? "IN" : "OUT");
+-	dev_info(&urb->dev->dev, "userurb=%p\n", userurb);
+-	dev_info(&urb->dev->dev, "transfer_buffer_length=%u\n",
+-		 urb->transfer_buffer_length);
+-	dev_info(&urb->dev->dev, "actual_length=%u\n", urb->actual_length);
+-	dev_info(&urb->dev->dev, "data: ");
+-	for (j = 0; j < urb->transfer_buffer_length; ++j)
+-		printk("%02x ", data[j]);
+-	printk("\n");
++	ep = usb_pipeendpoint(pipe);
++	t = types[usb_pipetype(pipe)];
++	d = dirs[!!usb_pipein(pipe)];
++
++	if (userurb) {		/* Async */
++		if (when == SUBMIT)
++			dev_info(&udev->dev, "userurb %p, ep%d %s-%s, "
++					"length %u\n",
++					userurb, ep, t, d, length);
++		else
++			dev_info(&udev->dev, "userurb %p, ep%d %s-%s, "
++					"actual_length %u status %d\n",
++					userurb, ep, t, d, length,
++					timeout_or_status);
++	} else {
++		if (when == SUBMIT)
++			dev_info(&udev->dev, "ep%d %s-%s, length %u, "
++					"timeout %d\n",
++					ep, t, d, length, timeout_or_status);
++		else
++			dev_info(&udev->dev, "ep%d %s-%s, actual_length %u, "
++					"status %d\n",
++					ep, t, d, length, timeout_or_status);
++	}
+ }
+ 
+ static void async_completed(struct urb *urb)
+@@ -347,7 +369,8 @@ static void async_completed(struct urb *urb)
+ 		secid = as->secid;
+ 	}
+ 	snoop(&urb->dev->dev, "urb complete\n");
+-	snoop_urb(urb, as->userurb);
++	snoop_urb(urb->dev, as->userurb, urb->pipe, urb->actual_length,
++			as->status, COMPLETE);
+ 	spin_unlock(&ps->lock);
+ 
+ 	if (signr)
+@@ -690,7 +713,7 @@ static int proc_control(struct dev_state *ps, void __user *arg)
+ 	unsigned int tmo;
+ 	unsigned char *tbuf;
+ 	unsigned wLength;
+-	int i, j, ret;
++	int i, pipe, ret;
+ 
+ 	if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
+ 		return -EFAULT;
+@@ -710,24 +733,17 @@ static int proc_control(struct dev_state *ps, void __user *arg)
+ 			free_page((unsigned long)tbuf);
+ 			return -EINVAL;
+ 		}
+-		snoop(&dev->dev, "control read: bRequest=%02x "
+-				"bRrequestType=%02x wValue=%04x "
+-				"wIndex=%04x wLength=%04x\n",
+-			ctrl.bRequest, ctrl.bRequestType, ctrl.wValue,
+-				ctrl.wIndex, ctrl.wLength);
++		pipe = usb_rcvctrlpipe(dev, 0);
++		snoop_urb(dev, NULL, pipe, ctrl.wLength, tmo, SUBMIT);
+ 
+ 		usb_unlock_device(dev);
+-		i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.bRequest,
++		i = usb_control_msg(dev, pipe, ctrl.bRequest,
+ 				    ctrl.bRequestType, ctrl.wValue, ctrl.wIndex,
+ 				    tbuf, ctrl.wLength, tmo);
+ 		usb_lock_device(dev);
++		snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE);
++
+ 		if ((i > 0) && ctrl.wLength) {
+-			if (usbfs_snoop) {
+-				dev_info(&dev->dev, "control read: data ");
+-				for (j = 0; j < i; ++j)
+-					printk("%02x ", (u8)(tbuf)[j]);
+-				printk("\n");
+-			}
+ 			if (copy_to_user(ctrl.data, tbuf, i)) {
+ 				free_page((unsigned long)tbuf);
+ 				return -EFAULT;
+@@ -740,22 +756,15 @@ static int proc_control(struct dev_state *ps, void __user *arg)
+ 				return -EFAULT;
+ 			}
+ 		}
+-		snoop(&dev->dev, "control write: bRequest=%02x "
+-				"bRrequestType=%02x wValue=%04x "
+-				"wIndex=%04x wLength=%04x\n",
+-			ctrl.bRequest, ctrl.bRequestType, ctrl.wValue,
+-				ctrl.wIndex, ctrl.wLength);
+-		if (usbfs_snoop) {
+-			dev_info(&dev->dev, "control write: data: ");
+-			for (j = 0; j < ctrl.wLength; ++j)
+-				printk("%02x ", (unsigned char)(tbuf)[j]);
+-			printk("\n");
+-		}
++		pipe = usb_sndctrlpipe(dev, 0);
++		snoop_urb(dev, NULL, pipe, ctrl.wLength, tmo, SUBMIT);
++
+ 		usb_unlock_device(dev);
+ 		i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest,
+ 				    ctrl.bRequestType, ctrl.wValue, ctrl.wIndex,
+ 				    tbuf, ctrl.wLength, tmo);
+ 		usb_lock_device(dev);
++		snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE);
+ 	}
+ 	free_page((unsigned long)tbuf);
+ 	if (i < 0 && i != -EPIPE) {
+@@ -774,7 +783,7 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
+ 	unsigned int tmo, len1, pipe;
+ 	int len2;
+ 	unsigned char *tbuf;
+-	int i, j, ret;
++	int i, ret;
+ 
+ 	if (copy_from_user(&bulk, arg, sizeof(bulk)))
+ 		return -EFAULT;
+@@ -801,18 +810,14 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
+ 			kfree(tbuf);
+ 			return -EINVAL;
+ 		}
+-		snoop(&dev->dev, "bulk read: len=0x%02x timeout=%04d\n",
+-			bulk.len, bulk.timeout);
++		snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT);
++
+ 		usb_unlock_device(dev);
+ 		i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
+ 		usb_lock_device(dev);
++		snoop_urb(dev, NULL, pipe, len2, i, COMPLETE);
++
+ 		if (!i && len2) {
+-			if (usbfs_snoop) {
+-				dev_info(&dev->dev, "bulk read: data ");
+-				for (j = 0; j < len2; ++j)
+-					printk("%02x ", (u8)(tbuf)[j]);
+-				printk("\n");
+-			}
+ 			if (copy_to_user(bulk.data, tbuf, len2)) {
+ 				kfree(tbuf);
+ 				return -EFAULT;
+@@ -825,17 +830,12 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
+ 				return -EFAULT;
+ 			}
+ 		}
+-		snoop(&dev->dev, "bulk write: len=0x%02x timeout=%04d\n",
+-			bulk.len, bulk.timeout);
+-		if (usbfs_snoop) {
+-			dev_info(&dev->dev, "bulk write: data: ");
+-			for (j = 0; j < len1; ++j)
+-				printk("%02x ", (unsigned char)(tbuf)[j]);
+-			printk("\n");
+-		}
++		snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT);
++
+ 		usb_unlock_device(dev);
+ 		i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
+ 		usb_lock_device(dev);
++		snoop_urb(dev, NULL, pipe, len2, i, COMPLETE);
+ 	}
+ 	kfree(tbuf);
+ 	if (i < 0)
+@@ -1053,13 +1053,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 			is_in = 0;
+ 			uurb->endpoint &= ~USB_DIR_IN;
+ 		}
+-		snoop(&ps->dev->dev, "control urb: bRequest=%02x "
+-			"bRrequestType=%02x wValue=%04x "
+-			"wIndex=%04x wLength=%04x\n",
+-			dr->bRequest, dr->bRequestType,
+-			__le16_to_cpup(&dr->wValue),
+-			__le16_to_cpup(&dr->wIndex),
+-			__le16_to_cpup(&dr->wLength));
+ 		break;
+ 
+ 	case USBDEVFS_URB_TYPE_BULK:
+@@ -1072,7 +1065,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 		uurb->number_of_packets = 0;
+ 		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
+ 			return -EINVAL;
+-		snoop(&ps->dev->dev, "bulk urb\n");
+ 		break;
+ 
+ 	case USBDEVFS_URB_TYPE_ISO:
+@@ -1104,7 +1096,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 			return -EINVAL;
+ 		}
+ 		uurb->buffer_length = totlen;
+-		snoop(&ps->dev->dev, "iso urb\n");
+ 		break;
+ 
+ 	case USBDEVFS_URB_TYPE_INTERRUPT:
+@@ -1113,7 +1104,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 			return -EINVAL;
+ 		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
+ 			return -EINVAL;
+-		snoop(&ps->dev->dev, "interrupt urb\n");
+ 		break;
+ 
+ 	default:
+@@ -1200,11 +1190,14 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 			return -EFAULT;
+ 		}
+ 	}
+-	snoop_urb(as->urb, as->userurb);
++	snoop_urb(ps->dev, as->userurb, as->urb->pipe,
++			as->urb->transfer_buffer_length, 0, SUBMIT);
+ 	async_newpending(as);
+ 	if ((ret = usb_submit_urb(as->urb, GFP_KERNEL))) {
+ 		dev_printk(KERN_DEBUG, &ps->dev->dev,
+ 			   "usbfs: usb_submit_urb returned %d\n", ret);
++		snoop_urb(ps->dev, as->userurb, as->urb->pipe,
++				0, ret, COMPLETE);
+ 		async_removepending(as);
+ 		free_async(as);
+ 		return ret;
+@@ -1670,7 +1663,7 @@ static int usbdev_ioctl(struct inode *inode, struct file *file,
+ 		break;
+ 
+ 	case USBDEVFS_REAPURBNDELAY32:
+-		snoop(&dev->dev, "%s: REAPURBDELAY32\n", __func__);
++		snoop(&dev->dev, "%s: REAPURBNDELAY32\n", __func__);
+ 		ret = proc_reapurbnonblock_compat(ps, p);
+ 		break;
+ 
+@@ -1691,7 +1684,7 @@ static int usbdev_ioctl(struct inode *inode, struct file *file,
+ 		break;
+ 
+ 	case USBDEVFS_REAPURBNDELAY:
+-		snoop(&dev->dev, "%s: REAPURBDELAY\n", __func__);
++		snoop(&dev->dev, "%s: REAPURBNDELAY\n", __func__);
+ 		ret = proc_reapurbnonblock(ps, p);
+ 		break;
+ 

commit ccf5b801cef4f9e2d708d3b87e91e2bc6abd5206
+Author: Alan Stern 
+Date:   Mon Jun 29 11:00:01 2009 -0400
+
+    USB: make intf.pm_usage an atomic_t
+    
+    This patch (as1260) changes the pm_usage_cnt field in struct
+    usb_interface from an int to an atomic_t.  This is so that drivers can
+    invoke the usb_autopm_get_interface_async() and
+    usb_autopm_put_interface_async() routines without locking and without
+    fear of corrupting the pm_usage_cnt value.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 1bad4e5a6abb..1c976c141f33 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -235,7 +235,7 @@ static int usb_probe_interface(struct device *dev)
+ 		/* The interface should always appear to be in use
+ 		 * unless the driver suports autosuspend.
+ 		 */
+-		intf->pm_usage_cnt = !(driver->supports_autosuspend);
++		atomic_set(&intf->pm_usage_cnt, !driver->supports_autosuspend);
+ 
+ 		/* Carry out a deferred switch to altsetting 0 */
+ 		if (intf->needs_altsetting0) {
+@@ -347,7 +347,7 @@ int usb_driver_claim_interface(struct usb_driver *driver,
+ 	usb_pm_lock(udev);
+ 	iface->condition = USB_INTERFACE_BOUND;
+ 	mark_active(iface);
+-	iface->pm_usage_cnt = !(driver->supports_autosuspend);
++	atomic_set(&iface->pm_usage_cnt, !driver->supports_autosuspend);
+ 	usb_pm_unlock(udev);
+ 
+ 	/* if interface was already added, bind now; else let
+@@ -1068,7 +1068,7 @@ static int autosuspend_check(struct usb_device *udev, int reschedule)
+ 			intf = udev->actconfig->interface[i];
+ 			if (!is_active(intf))
+ 				continue;
+-			if (intf->pm_usage_cnt > 0)
++			if (atomic_read(&intf->pm_usage_cnt) > 0)
+ 				return -EBUSY;
+ 			if (intf->needs_remote_wakeup &&
+ 					!udev->do_remote_wakeup) {
+@@ -1464,17 +1464,19 @@ static int usb_autopm_do_interface(struct usb_interface *intf,
+ 		status = -ENODEV;
+ 	else {
+ 		udev->auto_pm = 1;
+-		intf->pm_usage_cnt += inc_usage_cnt;
++		atomic_add(inc_usage_cnt, &intf->pm_usage_cnt);
+ 		udev->last_busy = jiffies;
+-		if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) {
++		if (inc_usage_cnt >= 0 &&
++				atomic_read(&intf->pm_usage_cnt) > 0) {
+ 			if (udev->state == USB_STATE_SUSPENDED)
+ 				status = usb_resume_both(udev,
+ 						PMSG_AUTO_RESUME);
+ 			if (status != 0)
+-				intf->pm_usage_cnt -= inc_usage_cnt;
++				atomic_sub(inc_usage_cnt, &intf->pm_usage_cnt);
+ 			else
+ 				udev->last_busy = jiffies;
+-		} else if (inc_usage_cnt <= 0 && intf->pm_usage_cnt <= 0) {
++		} else if (inc_usage_cnt <= 0 &&
++				atomic_read(&intf->pm_usage_cnt) <= 0) {
+ 			status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
+ 		}
+ 	}
+@@ -1519,7 +1521,7 @@ void usb_autopm_put_interface(struct usb_interface *intf)
+ 
+ 	status = usb_autopm_do_interface(intf, -1);
+ 	dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
+-			__func__, status, intf->pm_usage_cnt);
++			__func__, status, atomic_read(&intf->pm_usage_cnt));
+ }
+ EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
+ 
+@@ -1547,10 +1549,10 @@ void usb_autopm_put_interface_async(struct usb_interface *intf)
+ 		status = -ENODEV;
+ 	} else {
+ 		udev->last_busy = jiffies;
+-		--intf->pm_usage_cnt;
++		atomic_dec(&intf->pm_usage_cnt);
+ 		if (udev->autosuspend_disabled || udev->autosuspend_delay < 0)
+ 			status = -EPERM;
+-		else if (intf->pm_usage_cnt <= 0 &&
++		else if (atomic_read(&intf->pm_usage_cnt) <= 0 &&
+ 				!timer_pending(&udev->autosuspend.timer)) {
+ 			queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+ 					round_jiffies_up_relative(
+@@ -1558,7 +1560,7 @@ void usb_autopm_put_interface_async(struct usb_interface *intf)
+ 		}
+ 	}
+ 	dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
+-			__func__, status, intf->pm_usage_cnt);
++			__func__, status, atomic_read(&intf->pm_usage_cnt));
+ }
+ EXPORT_SYMBOL_GPL(usb_autopm_put_interface_async);
+ 
+@@ -1602,7 +1604,7 @@ int usb_autopm_get_interface(struct usb_interface *intf)
+ 
+ 	status = usb_autopm_do_interface(intf, 1);
+ 	dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
+-			__func__, status, intf->pm_usage_cnt);
++			__func__, status, atomic_read(&intf->pm_usage_cnt));
+ 	return status;
+ }
+ EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
+@@ -1630,10 +1632,14 @@ int usb_autopm_get_interface_async(struct usb_interface *intf)
+ 		status = -ENODEV;
+ 	else if (udev->autoresume_disabled)
+ 		status = -EPERM;
+-	else if (++intf->pm_usage_cnt > 0 && udev->state == USB_STATE_SUSPENDED)
+-		queue_work(ksuspend_usb_wq, &udev->autoresume);
++	else {
++		atomic_inc(&intf->pm_usage_cnt);
++		if (atomic_read(&intf->pm_usage_cnt) > 0 &&
++				udev->state == USB_STATE_SUSPENDED)
++			queue_work(ksuspend_usb_wq, &udev->autoresume);
++	}
+ 	dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
+-			__func__, status, intf->pm_usage_cnt);
++			__func__, status, atomic_read(&intf->pm_usage_cnt));
+ 	return status;
+ }
+ EXPORT_SYMBOL_GPL(usb_autopm_get_interface_async);
+@@ -1655,7 +1661,7 @@ int usb_autopm_set_interface(struct usb_interface *intf)
+ 
+ 	status = usb_autopm_do_interface(intf, 0);
+ 	dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
+-			__func__, status, intf->pm_usage_cnt);
++			__func__, status, atomic_read(&intf->pm_usage_cnt));
+ 	return status;
+ }
+ EXPORT_SYMBOL_GPL(usb_autopm_set_interface);
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index cb54420ed583..69e3a966a4b7 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -373,7 +373,7 @@ static void kick_khubd(struct usb_hub *hub)
+ 	unsigned long	flags;
+ 
+ 	/* Suppress autosuspend until khubd runs */
+-	to_usb_interface(hub->intfdev)->pm_usage_cnt = 1;
++	atomic_set(&to_usb_interface(hub->intfdev)->pm_usage_cnt, 1);
+ 
+ 	spin_lock_irqsave(&hub_event_lock, flags);
+ 	if (!hub->disconnected && list_empty(&hub->event_list)) {
+@@ -678,7 +678,8 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ 					msecs_to_jiffies(delay));
+ 
+ 			/* Suppress autosuspend until init is done */
+-			to_usb_interface(hub->intfdev)->pm_usage_cnt = 1;
++			atomic_set(&to_usb_interface(hub->intfdev)->
++					pm_usage_cnt, 1);
+ 			return;		/* Continues at init2: below */
+ 		} else {
+ 			hub_power_on(hub, true);
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 3b45a0d27b80..a34fa89f1474 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -195,7 +195,7 @@ struct usb_interface {
+ 
+ 	struct device dev;		/* interface specific device info */
+ 	struct device *usb_dev;
+-	int pm_usage_cnt;		/* usage counter for autosuspend */
++	atomic_t pm_usage_cnt;		/* usage counter for autosuspend */
+ 	struct work_struct reset_ws;	/* for resets in atomic context */
+ };
+ #define	to_usb_interface(d) container_of(d, struct usb_interface, dev)
+@@ -551,13 +551,13 @@ extern void usb_autopm_put_interface_async(struct usb_interface *intf);
+ 
+ static inline void usb_autopm_enable(struct usb_interface *intf)
+ {
+-	intf->pm_usage_cnt = 0;
++	atomic_set(&intf->pm_usage_cnt, 0);
+ 	usb_autopm_set_interface(intf);
+ }
+ 
+ static inline void usb_autopm_disable(struct usb_interface *intf)
+ {
+-	intf->pm_usage_cnt = 1;
++	atomic_set(&intf->pm_usage_cnt, 1);
+ 	usb_autopm_set_interface(intf);
+ }
+ 

commit 7cbe5dca399a50ce8aa74314b1d276e2fb904e1b
+Author: Alan Stern 
+Date:   Mon Jun 29 10:56:54 2009 -0400
+
+    USB: add API for userspace drivers to "claim" ports
+    
+    This patch (as1258) implements a feature that users have been asking
+    for: It gives programs the ability to "claim" a port on a hub, via a
+    new usbfs ioctl.  A device plugged into a "claimed" port will not be
+    touched by the kernel beyond the immediate necessities of
+    initialization and enumeration.
+    
+    In particular, when a device is plugged into a "claimed" port, the
+    kernel will not select and install a configuration.  And when a config
+    is installed by usbfs or sysfs, the kernel will not probe any drivers
+    for any of the interfaces.  (However the kernel will fetch various
+    string descriptors during enumeration.  One could argue that this
+    isn't really necessary, but the strings are exported in sysfs.)
+    
+    The patch does not guarantee exclusive access to these devices; it is
+    still possible for more than one program to open the device file
+    concurrently.  Programs are responsible for coordinating access among
+    themselves.
+    
+    A demonstration program showing how to use the new interface can be
+    found in an attachment to
+    
+            http://marc.info/?l=linux-usb&m=124345857431452&w=2
+    
+    The patch also makes a small simplification to the hub driver,
+    replacing a bunch of more-or-less useless variants of "out of memory"
+    with a single message.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 4247eccf858c..165de5d59005 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -52,6 +52,7 @@
+ 
+ #include "hcd.h"	/* for usbcore internals */
+ #include "usb.h"
++#include "hub.h"
+ 
+ #define USB_MAXBUS			64
+ #define USB_DEVICE_MAX			USB_MAXBUS * 128
+@@ -655,6 +656,7 @@ static int usbdev_release(struct inode *inode, struct file *file)
+ 	struct async *as;
+ 
+ 	usb_lock_device(dev);
++	usb_hub_release_all_ports(dev, ps);
+ 
+ 	/* Protect against simultaneous open */
+ 	mutex_lock(&usbfs_mutex);
+@@ -1548,6 +1550,29 @@ static int proc_ioctl_compat(struct dev_state *ps, compat_uptr_t arg)
+ }
+ #endif
+ 
++static int proc_claim_port(struct dev_state *ps, void __user *arg)
++{
++	unsigned portnum;
++	int rc;
++
++	if (get_user(portnum, (unsigned __user *) arg))
++		return -EFAULT;
++	rc = usb_hub_claim_port(ps->dev, portnum, ps);
++	if (rc == 0)
++		snoop(&ps->dev->dev, "port %d claimed by process %d: %s\n",
++			portnum, task_pid_nr(current), current->comm);
++	return rc;
++}
++
++static int proc_release_port(struct dev_state *ps, void __user *arg)
++{
++	unsigned portnum;
++
++	if (get_user(portnum, (unsigned __user *) arg))
++		return -EFAULT;
++	return usb_hub_release_port(ps->dev, portnum, ps);
++}
++
+ /*
+  * NOTE:  All requests here that have interface numbers as parameters
+  * are assuming that somehow the configuration has been prevented from
+@@ -1689,6 +1714,16 @@ static int usbdev_ioctl(struct inode *inode, struct file *file,
+ 		snoop(&dev->dev, "%s: IOCTL\n", __func__);
+ 		ret = proc_ioctl_default(ps, p);
+ 		break;
++
++	case USBDEVFS_CLAIM_PORT:
++		snoop(&dev->dev, "%s: CLAIM_PORT\n", __func__);
++		ret = proc_claim_port(ps, p);
++		break;
++
++	case USBDEVFS_RELEASE_PORT:
++		snoop(&dev->dev, "%s: RELEASE_PORT\n", __func__);
++		ret = proc_release_port(ps, p);
++		break;
+ 	}
+ 	usb_unlock_device(dev);
+ 	if (ret >= 0)
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 69e5773abfce..1bad4e5a6abb 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -207,6 +207,9 @@ static int usb_probe_interface(struct device *dev)
+ 
+ 	intf->needs_binding = 0;
+ 
++	if (usb_device_is_owned(udev))
++		return -ENODEV;
++
+ 	if (udev->authorized == 0) {
+ 		dev_err(&intf->dev, "Device is not authorized for usage\n");
+ 		return -ENODEV;
+diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
+index 30ecac3af15a..05e6d313961e 100644
+--- a/drivers/usb/core/generic.c
++++ b/drivers/usb/core/generic.c
+@@ -158,7 +158,9 @@ static int generic_probe(struct usb_device *udev)
+ 	/* Choose and set the configuration.  This registers the interfaces
+ 	 * with the driver core and lets interface drivers bind to them.
+ 	 */
+-	if (udev->authorized == 0)
++	if (usb_device_is_owned(udev))
++		;		/* Don't configure if the device is owned */
++	else if (udev->authorized == 0)
+ 		dev_err(&udev->dev, "Device is not authorized for usage\n");
+ 	else {
+ 		c = usb_choose_configuration(udev);
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 71f86c60d83c..cb54420ed583 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -78,6 +78,7 @@ struct usb_hub {
+ 	u8			indicator[USB_MAXCHILDREN];
+ 	struct delayed_work	leds;
+ 	struct delayed_work	init_work;
++	void			**port_owners;
+ };
+ 
+ 
+@@ -860,19 +861,17 @@ static int hub_configure(struct usb_hub *hub,
+ 	u16 wHubCharacteristics;
+ 	unsigned int pipe;
+ 	int maxp, ret;
+-	char *message;
++	char *message = "out of memory";
+ 
+ 	hub->buffer = usb_buffer_alloc(hdev, sizeof(*hub->buffer), GFP_KERNEL,
+ 			&hub->buffer_dma);
+ 	if (!hub->buffer) {
+-		message = "can't allocate hub irq buffer";
+ 		ret = -ENOMEM;
+ 		goto fail;
+ 	}
+ 
+ 	hub->status = kmalloc(sizeof(*hub->status), GFP_KERNEL);
+ 	if (!hub->status) {
+-		message = "can't kmalloc hub status buffer";
+ 		ret = -ENOMEM;
+ 		goto fail;
+ 	}
+@@ -880,7 +879,6 @@ static int hub_configure(struct usb_hub *hub,
+ 
+ 	hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL);
+ 	if (!hub->descriptor) {
+-		message = "can't kmalloc hub descriptor";
+ 		ret = -ENOMEM;
+ 		goto fail;
+ 	}
+@@ -904,6 +902,12 @@ static int hub_configure(struct usb_hub *hub,
+ 	dev_info (hub_dev, "%d port%s detected\n", hdev->maxchild,
+ 		(hdev->maxchild == 1) ? "" : "s");
+ 
++	hub->port_owners = kzalloc(hdev->maxchild * sizeof(void *), GFP_KERNEL);
++	if (!hub->port_owners) {
++		ret = -ENOMEM;
++		goto fail;
++	}
++
+ 	wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
+ 
+ 	if (wHubCharacteristics & HUB_CHAR_COMPOUND) {
+@@ -1082,7 +1086,6 @@ static int hub_configure(struct usb_hub *hub,
+ 
+ 	hub->urb = usb_alloc_urb(0, GFP_KERNEL);
+ 	if (!hub->urb) {
+-		message = "couldn't allocate interrupt urb";
+ 		ret = -ENOMEM;
+ 		goto fail;
+ 	}
+@@ -1131,11 +1134,13 @@ static void hub_disconnect(struct usb_interface *intf)
+ 	hub_quiesce(hub, HUB_DISCONNECT);
+ 
+ 	usb_set_intfdata (intf, NULL);
++	hub->hdev->maxchild = 0;
+ 
+ 	if (hub->hdev->speed == USB_SPEED_HIGH)
+ 		highspeed_hubs--;
+ 
+ 	usb_free_urb(hub->urb);
++	kfree(hub->port_owners);
+ 	kfree(hub->descriptor);
+ 	kfree(hub->status);
+ 	usb_buffer_free(hub->hdev, sizeof(*hub->buffer), hub->buffer,
+@@ -1250,6 +1255,79 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
+ 	}
+ }
+ 
++/*
++ * Allow user programs to claim ports on a hub.  When a device is attached
++ * to one of these "claimed" ports, the program will "own" the device.
++ */
++static int find_port_owner(struct usb_device *hdev, unsigned port1,
++		void ***ppowner)
++{
++	if (hdev->state == USB_STATE_NOTATTACHED)
++		return -ENODEV;
++	if (port1 == 0 || port1 > hdev->maxchild)
++		return -EINVAL;
++
++	/* This assumes that devices not managed by the hub driver
++	 * will always have maxchild equal to 0.
++	 */
++	*ppowner = &(hdev_to_hub(hdev)->port_owners[port1 - 1]);
++	return 0;
++}
++
++/* In the following three functions, the caller must hold hdev's lock */
++int usb_hub_claim_port(struct usb_device *hdev, unsigned port1, void *owner)
++{
++	int rc;
++	void **powner;
++
++	rc = find_port_owner(hdev, port1, &powner);
++	if (rc)
++		return rc;
++	if (*powner)
++		return -EBUSY;
++	*powner = owner;
++	return rc;
++}
++
++int usb_hub_release_port(struct usb_device *hdev, unsigned port1, void *owner)
++{
++	int rc;
++	void **powner;
++
++	rc = find_port_owner(hdev, port1, &powner);
++	if (rc)
++		return rc;
++	if (*powner != owner)
++		return -ENOENT;
++	*powner = NULL;
++	return rc;
++}
++
++void usb_hub_release_all_ports(struct usb_device *hdev, void *owner)
++{
++	int n;
++	void **powner;
++
++	n = find_port_owner(hdev, 1, &powner);
++	if (n == 0) {
++		for (; n < hdev->maxchild; (++n, ++powner)) {
++			if (*powner == owner)
++				*powner = NULL;
++		}
++	}
++}
++
++/* The caller must hold udev's lock */
++bool usb_device_is_owned(struct usb_device *udev)
++{
++	struct usb_hub *hub;
++
++	if (udev->state == USB_STATE_NOTATTACHED || !udev->parent)
++		return false;
++	hub = hdev_to_hub(udev->parent);
++	return !!hub->port_owners[udev->portnum - 1];
++}
++
+ 
+ static void recursively_mark_NOTATTACHED(struct usb_device *udev)
+ {
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index c0e0ae2bb8e7..9a8b15e6377a 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -37,6 +37,13 @@ extern int usb_match_device(struct usb_device *dev,
+ extern void usb_forced_unbind_intf(struct usb_interface *intf);
+ extern void usb_rebind_intf(struct usb_interface *intf);
+ 
++extern int usb_hub_claim_port(struct usb_device *hdev, unsigned port,
++		void *owner);
++extern int usb_hub_release_port(struct usb_device *hdev, unsigned port,
++		void *owner);
++extern void usb_hub_release_all_ports(struct usb_device *hdev, void *owner);
++extern bool usb_device_is_owned(struct usb_device *udev);
++
+ extern int  usb_hub_init(void);
+ extern void usb_hub_cleanup(void);
+ extern int usb_major_init(void);
+diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
+index 0044d9b4cb85..00ceebeb9e5c 100644
+--- a/include/linux/usbdevice_fs.h
++++ b/include/linux/usbdevice_fs.h
+@@ -175,4 +175,6 @@ struct usbdevfs_ioctl32 {
+ #define USBDEVFS_CLEAR_HALT        _IOR('U', 21, unsigned int)
+ #define USBDEVFS_DISCONNECT        _IO('U', 22)
+ #define USBDEVFS_CONNECT           _IO('U', 23)
++#define USBDEVFS_CLAIM_PORT        _IOR('U', 24, unsigned int)
++#define USBDEVFS_RELEASE_PORT      _IOR('U', 25, unsigned int)
+ #endif /* _LINUX_USBDEVICE_FS_H */

commit 7bd032dc2793afcbaf4a350056768da84cdbd89b
+Author: Alan Stern 
+Date:   Fri Sep 4 15:29:59 2009 -0400
+
+    USB serial: update the console driver
+    
+    This patch (as1292) modifies the USB serial console driver, to make it
+    compatible with the recent changes to the USB serial core.  The most
+    important change is that serial->disc_mutex now has to be unlocked
+    following a successful call to usb_serial_get_by_index().
+    
+    Other less notable changes include:
+    
+            Use the requested port number instead of port 0 always.
+    
+            Prevent the serial device from being autosuspended.
+    
+            Use the ASYNCB_INITIALIZED flag bit to indicate when the
+            port hardware has been initialized.
+    
+    In spite of these changes, there's no question that the USB serial
+    console code is still a big hack.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
+index be086e4c76b6..b22ac3258523 100644
+--- a/drivers/usb/serial/console.c
++++ b/drivers/usb/serial/console.c
+@@ -16,6 +16,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ 
+@@ -63,7 +64,7 @@ static int usb_console_setup(struct console *co, char *options)
+ 	char *s;
+ 	struct usb_serial *serial;
+ 	struct usb_serial_port *port;
+-	int retval = 0;
++	int retval;
+ 	struct tty_struct *tty = NULL;
+ 	struct ktermios *termios = NULL, dummy;
+ 
+@@ -116,13 +117,17 @@ static int usb_console_setup(struct console *co, char *options)
+ 		return -ENODEV;
+ 	}
+ 
+-	port = serial->port[0];
++	retval = usb_autopm_get_interface(serial->interface);
++	if (retval)
++		goto error_get_interface;
++
++	port = serial->port[co->index - serial->minor];
+ 	tty_port_tty_set(&port->port, NULL);
+ 
+ 	info->port = port;
+ 
+ 	++port->port.count;
+-	if (port->port.count == 1) {
++	if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) {
+ 		if (serial->type->set_termios) {
+ 			/*
+ 			 * allocate a fake tty so the driver can initialize
+@@ -168,6 +173,7 @@ static int usb_console_setup(struct console *co, char *options)
+ 			kfree(termios);
+ 			kfree(tty);
+ 		}
++		set_bit(ASYNCB_INITIALIZED, &port->port.flags);
+ 	}
+ 	/* Now that any required fake tty operations are completed restore
+ 	 * the tty port count */
+@@ -175,18 +181,22 @@ static int usb_console_setup(struct console *co, char *options)
+ 	/* The console is special in terms of closing the device so
+ 	 * indicate this port is now acting as a system console. */
+ 	port->console = 1;
+-	retval = 0;
+ 
+-out:
++	mutex_unlock(&serial->disc_mutex);
+ 	return retval;
+-free_termios:
++
++ free_termios:
+ 	kfree(termios);
+ 	tty_port_tty_set(&port->port, NULL);
+-free_tty:
++ free_tty:
+ 	kfree(tty);
+-reset_open_count:
++ reset_open_count:
+ 	port->port.count = 0;
+-	goto out;
++	usb_autopm_put_interface(serial->interface);
++ error_get_interface:
++	usb_serial_put(serial);
++	mutex_unlock(&serial->disc_mutex);
++	return retval;
+ }
+ 
+ static void usb_console_write(struct console *co,

commit 320348c8d5c9b591282633ddb8959b42f7fc7a1c
+Author: Alan Stern 
+Date:   Tue Sep 1 11:39:59 2009 -0400
+
+    usb-serial: straighten out serial_open
+    
+    This patch (as1291) removes a bunch of code from serial_open(), things
+    that were rendered unnecessary by earlier patches.  A missing spinlock
+    is added to protect port->port.count, which needs to be incremented
+    even if the open fails but not if the tty has gotten a hangup.  The
+    test for whether the hardware has been initialized, based on the use
+    count, is replaced by a more transparent test of the
+    ASYNCB_INITIALIZED bit in the port flags.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
+index 9a3258046c8c..9d7ca4868d37 100644
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -245,55 +245,40 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
+ 	return retval;
+ }
+ 
+-static int serial_open (struct tty_struct *tty, struct file *filp)
++static int serial_open(struct tty_struct *tty, struct file *filp)
+ {
+-	struct usb_serial *serial;
+-	struct usb_serial_port *port;
+-	int retval = 0;
+-	int first = 0;
+-
+-	port = tty->driver_data;
+-	serial = port->serial;
++	struct usb_serial_port *port = tty->driver_data;
++	struct usb_serial *serial = port->serial;
++	int retval;
+ 
+ 	dbg("%s - port %d", __func__, port->number);
+ 
+-	if (mutex_lock_interruptible(&port->mutex))
+-		return -ERESTARTSYS;
+-
+-	++port->port.count;
++	spin_lock_irq(&port->port.lock);
++	if (!tty_hung_up_p(filp))
++		++port->port.count;
++	spin_unlock_irq(&port->port.lock);
+ 	tty_port_tty_set(&port->port, tty);
+ 
+-	/* If the console is attached, the device is already open */
+-	if (port->port.count == 1 && !port->console) {
+-		first = 1;
++	/* Do the device-specific open only if the hardware isn't
++	 * already initialized.
++	 */
++	if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) {
++		if (mutex_lock_interruptible(&port->mutex))
++			return -ERESTARTSYS;
+ 		mutex_lock(&serial->disc_mutex);
+-
+-		/* only call the device specific open if this
+-		 * is the first time the port is opened */
+-		retval = serial->type->open(tty, port);
+-		if (retval)
+-			goto bailout_module_put;
++		if (serial->disconnected)
++			retval = -ENODEV;
++		else
++			retval = port->serial->type->open(tty, port);
+ 		mutex_unlock(&serial->disc_mutex);
++		mutex_unlock(&port->mutex);
++		if (retval)
++			return retval;
+ 		set_bit(ASYNCB_INITIALIZED, &port->port.flags);
+ 	}
+-	mutex_unlock(&port->mutex);
++
+ 	/* Now do the correct tty layer semantics */
+ 	retval = tty_port_block_til_ready(&port->port, tty, filp);
+-	if (retval == 0) {
+-		if (!first)
+-			usb_serial_put(serial);
+-		return 0;
+-	}
+-	mutex_lock(&port->mutex);
+-	if (first == 0)
+-		goto bailout_mutex_unlock;
+-	/* Undo the initial port actions */
+-	mutex_lock(&serial->disc_mutex);
+-bailout_module_put:
+-	mutex_unlock(&serial->disc_mutex);
+-bailout_mutex_unlock:
+-	port->port.count = 0;
+-	mutex_unlock(&port->mutex);
+ 	return retval;
+ }
+ 

commit ff8324df1187b7280e507c976777df76c73a1ef1
+Author: Alan Stern 
+Date:   Tue Sep 1 11:39:51 2009 -0400
+
+    usb-serial: add missing tests and debug lines
+    
+    This patch (as1290) adds some missing tests.  serial_down() isn't
+    supposed to do anything if the hardware hasn't been initialized, and
+    serial_close() isn't supposed to do anything if the tty has gotten a
+    hangup (because serial_hangup() takes care of shutting down the
+    hardware).
+    
+    The patch also updates and adds a few debugging lines.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
+index 28125de7d902..9a3258046c8c 100644
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -200,6 +200,8 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
+ 	struct usb_serial_port *port;
+ 	int retval = -ENODEV;
+ 
++	dbg("%s", __func__);
++
+ 	serial = usb_serial_get_by_index(idx);
+ 	if (!serial)
+ 		return retval;
+@@ -250,11 +252,11 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
+ 	int retval = 0;
+ 	int first = 0;
+ 
+-	dbg("%s", __func__);
+-
+ 	port = tty->driver_data;
+ 	serial = port->serial;
+ 
++	dbg("%s - port %d", __func__, port->number);
++
+ 	if (mutex_lock_interruptible(&port->mutex))
+ 		return -ERESTARTSYS;
+ 
+@@ -315,6 +317,12 @@ static void serial_down(struct usb_serial_port *port)
+ 	if (port->console)
+ 		return;
+ 
++	/* Don't call the close method if the hardware hasn't been
++	 * initialized.
++	 */
++	if (!test_and_clear_bit(ASYNCB_INITIALIZED, &port->port.flags))
++		return;
++
+ 	mutex_lock(&port->mutex);
+ 	serial = port->serial;
+ 	owner = serial->type->driver.owner;
+@@ -328,10 +336,11 @@ static void serial_down(struct usb_serial_port *port)
+ static void serial_hangup(struct tty_struct *tty)
+ {
+ 	struct usb_serial_port *port = tty->driver_data;
++
++	dbg("%s - port %d", __func__, port->number);
++
+ 	serial_down(port);
+ 	tty_port_hangup(&port->port);
+-	/* We must not free port yet - the USB serial layer depends on it's
+-	   continued existence */
+ }
+ 
+ static void serial_close(struct tty_struct *tty, struct file *filp)
+@@ -340,6 +349,8 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
+ 
+ 	dbg("%s - port %d", __func__, port->number);
+ 
++	if (tty_hung_up_p(filp))
++		return;
+ 	if (tty_port_close_start(&port->port, tty, filp) == 0)
+ 		return;
+ 	serial_down(port);
+@@ -368,6 +379,8 @@ static void serial_release(struct tty_struct *tty)
+ 	if (port->console)
+ 		return;
+ 
++	dbg("%s - port %d", __func__, port->number);
++
+ 	/* Standard shutdown processing */
+ 	tty_shutdown(tty);
+ 

commit 74556123e034c8337b69a3ebac2f3a5fc0a97032
+Author: Alan Stern 
+Date:   Tue Sep 1 11:39:40 2009 -0400
+
+    usb-serial: rename subroutines
+    
+    This patch (as1289) renames serial_do_down() to serial_down() and
+    serial_do_free() to serial_release().  It also adds a missing call to
+    tty_shutdown() in serial_release().
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
+index 1bc0a24b896b..28125de7d902 100644
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -191,7 +191,7 @@ void usb_serial_put(struct usb_serial *serial)
+  * This is the first place a new tty gets used.  Hence this is where we
+  * acquire references to the usb_serial structure and the driver module,
+  * where we store a pointer to the port, and where we do an autoresume.
+- * All these actions are reversed in serial_do_free().
++ * All these actions are reversed in serial_release().
+  */
+ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
+ {
+@@ -296,13 +296,13 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
+ }
+ 
+ /**
+- * serial_do_down - shut down hardware
++ * serial_down - shut down hardware
+  * @port: port to shut down
+  *
+  * Shut down a USB serial port unless it is the console.  We never
+  * shut down the console hardware as it will always be in use.
+  */
+-static void serial_do_down(struct usb_serial_port *port)
++static void serial_down(struct usb_serial_port *port)
+ {
+ 	struct usb_serial_driver *drv = port->serial->type;
+ 	struct usb_serial *serial;
+@@ -328,7 +328,7 @@ static void serial_do_down(struct usb_serial_port *port)
+ static void serial_hangup(struct tty_struct *tty)
+ {
+ 	struct usb_serial_port *port = tty->driver_data;
+-	serial_do_down(port);
++	serial_down(port);
+ 	tty_port_hangup(&port->port);
+ 	/* We must not free port yet - the USB serial layer depends on it's
+ 	   continued existence */
+@@ -342,13 +342,13 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
+ 
+ 	if (tty_port_close_start(&port->port, tty, filp) == 0)
+ 		return;
+-	serial_do_down(port);
++	serial_down(port);
+ 	tty_port_close_end(&port->port, tty);
+ 	tty_port_tty_set(&port->port, NULL);
+ }
+ 
+ /**
+- * serial_do_free - free resources post close/hangup
++ * serial_release - free resources post close/hangup
+  * @port: port to free up
+  *
+  * Do the resource freeing and refcount dropping for the port.
+@@ -356,7 +356,7 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
+  *
+  * Called when the last tty kref is dropped.
+  */
+-static void serial_do_free(struct tty_struct *tty)
++static void serial_release(struct tty_struct *tty)
+ {
+ 	struct usb_serial_port *port = tty->driver_data;
+ 	struct usb_serial *serial;
+@@ -368,6 +368,9 @@ static void serial_do_free(struct tty_struct *tty)
+ 	if (port->console)
+ 		return;
+ 
++	/* Standard shutdown processing */
++	tty_shutdown(tty);
++
+ 	tty->driver_data = NULL;
+ 
+ 	serial = port->serial;
+@@ -1204,7 +1207,7 @@ static const struct tty_operations serial_ops = {
+ 	.chars_in_buffer =	serial_chars_in_buffer,
+ 	.tiocmget =		serial_tiocmget,
+ 	.tiocmset =		serial_tiocmset,
+-	.shutdown = 		serial_do_free,
++	.shutdown = 		serial_release,
+ 	.install = 		serial_install,
+ 	.proc_fops =		&serial_proc_fops,
+ };

commit 7e29bb4b779f4f35385e6f21994758845bf14d23
+Author: Alan Stern 
+Date:   Tue Sep 1 11:39:22 2009 -0400
+
+    usb-serial: fix termios initialization logic
+    
+    This patch (as1288) fixes the initialization logic in
+    serial_install().  A new tty always needs to have a termios
+    initialized no matter what, not just in the case where the lower
+    driver will override the termios settings.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
+index 7d207d91a6a8..1bc0a24b896b 100644
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -210,22 +210,21 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
+ 	if (!try_module_get(serial->type->driver.owner))
+ 		goto error_module_get;
+ 
++	/* perform the standard setup */
++	retval = tty_init_termios(tty);
++	if (retval)
++		goto error_init_termios;
++
+ 	retval = usb_autopm_get_interface(serial->interface);
+ 	if (retval)
+ 		goto error_get_interface;
+ 
+-	/* If the termios setup has yet to be done */
+-	if (tty->driver->termios[idx] == NULL) {
+-		/* perform the standard setup */
+-		retval = tty_init_termios(tty);
+-		if (retval)
+-			goto error_init_termios;
+-		/* allow the driver to update it */
+-		if (serial->type->init_termios)
+-			serial->type->init_termios(tty);
+-	}
+ 	mutex_unlock(&serial->disc_mutex);
+ 
++	/* allow the driver to update the settings */
++	if (serial->type->init_termios)
++		serial->type->init_termios(tty);
++
+ 	tty->driver_data = port;
+ 
+ 	/* Final install (we use the default method) */
+@@ -234,9 +233,8 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
+ 	driver->ttys[idx] = tty;
+ 	return retval;
+ 
+- error_init_termios:
+-	usb_autopm_put_interface(serial->interface);
+  error_get_interface:
++ error_init_termios:
+ 	module_put(serial->type->driver.owner);
+  error_module_get:
+  error_no_port:

commit cc56cd0157753c04a987888a2f793803df661a40
+Author: Alan Stern 
+Date:   Tue Sep 1 11:39:13 2009 -0400
+
+    usb-serial: acquire references when a new tty is installed
+    
+    This patch (as1287) makes serial_install() be reponsible for acquiring
+    references to the usb_serial structure and the driver module when a
+    tty is first used.  This is more sensible than having serial_open() do
+    it, because a tty can be opened many times whereas it is installed
+    only once, when it is created.  (Not to mention that these actions are
+    reversed when the tty is released, not when it is closed.)  Finally,
+    it is at install time that the TTY core takes its own reference to the
+    usb_serial module, so it is only fitting that we should act the same
+    way in regard to the lower-level serial driver.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
+index 87802ea8bbc8..7d207d91a6a8 100644
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -187,100 +187,92 @@ void usb_serial_put(struct usb_serial *serial)
+  * Create the termios objects for this tty.  We use the default
+  * USB serial settings but permit them to be overridden by
+  * serial->type->init_termios.
++ *
++ * This is the first place a new tty gets used.  Hence this is where we
++ * acquire references to the usb_serial structure and the driver module,
++ * where we store a pointer to the port, and where we do an autoresume.
++ * All these actions are reversed in serial_do_free().
+  */
+ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
+ {
+ 	int idx = tty->index;
+ 	struct usb_serial *serial;
+-	int retval;
++	struct usb_serial_port *port;
++	int retval = -ENODEV;
++
++	serial = usb_serial_get_by_index(idx);
++	if (!serial)
++		return retval;
++
++	port = serial->port[idx - serial->minor];
++	if (!port)
++		goto error_no_port;
++	if (!try_module_get(serial->type->driver.owner))
++		goto error_module_get;
++
++	retval = usb_autopm_get_interface(serial->interface);
++	if (retval)
++		goto error_get_interface;
+ 
+ 	/* If the termios setup has yet to be done */
+ 	if (tty->driver->termios[idx] == NULL) {
+ 		/* perform the standard setup */
+ 		retval = tty_init_termios(tty);
+ 		if (retval)
+-			return retval;
++			goto error_init_termios;
+ 		/* allow the driver to update it */
+-		serial = usb_serial_get_by_index(tty->index);
+-		if (serial) {
+-			if (serial->type->init_termios)
+-				serial->type->init_termios(tty);
+-			usb_serial_put(serial);
+-			mutex_unlock(&serial->disc_mutex);
+-		}
++		if (serial->type->init_termios)
++			serial->type->init_termios(tty);
+ 	}
++	mutex_unlock(&serial->disc_mutex);
++
++	tty->driver_data = port;
++
+ 	/* Final install (we use the default method) */
+ 	tty_driver_kref_get(driver);
+ 	tty->count++;
+ 	driver->ttys[idx] = tty;
+-	return 0;
++	return retval;
++
++ error_init_termios:
++	usb_autopm_put_interface(serial->interface);
++ error_get_interface:
++	module_put(serial->type->driver.owner);
++ error_module_get:
++ error_no_port:
++	usb_serial_put(serial);
++	mutex_unlock(&serial->disc_mutex);
++	return retval;
+ }
+ 
+ static int serial_open (struct tty_struct *tty, struct file *filp)
+ {
+ 	struct usb_serial *serial;
+ 	struct usb_serial_port *port;
+-	unsigned int portNumber;
+ 	int retval = 0;
+ 	int first = 0;
+ 
+ 	dbg("%s", __func__);
+ 
+-	/* get the serial object associated with this tty pointer */
+-	serial = usb_serial_get_by_index(tty->index);
+-	if (!serial) {
+-		tty->driver_data = NULL;
+-		return -ENODEV;
+-	}
+-
+-	portNumber = tty->index - serial->minor;
+-	port = serial->port[portNumber];
+-	if (!port || serial->disconnected)
+-		retval = -ENODEV;
+-	/*
+-	 * Note: Our locking order requirement does not allow port->mutex
+-	 * to be acquired while serial->disc_mutex is held.
+-	 */
+-	mutex_unlock(&serial->disc_mutex);
+-	if (retval)
+-		goto bailout_serial_put;
++	port = tty->driver_data;
++	serial = port->serial;
+ 
+-	if (mutex_lock_interruptible(&port->mutex)) {
+-		retval = -ERESTARTSYS;
+-		goto bailout_serial_put;
+-	}
++	if (mutex_lock_interruptible(&port->mutex))
++		return -ERESTARTSYS;
+ 
+ 	++port->port.count;
+-
+-	/* set up our port structure making the tty driver
+-	 * remember our port object, and us it */
+-	tty->driver_data = port;
+ 	tty_port_tty_set(&port->port, tty);
+ 
+ 	/* If the console is attached, the device is already open */
+ 	if (port->port.count == 1 && !port->console) {
+ 		first = 1;
+-		/* lock this module before we call it
+-		 * this may fail, which means we must bail out,
+-		 * safe because we are called with BKL held */
+-		if (!try_module_get(serial->type->driver.owner)) {
+-			retval = -ENODEV;
+-			goto bailout_mutex_unlock;
+-		}
+-
+ 		mutex_lock(&serial->disc_mutex);
+-		if (serial->disconnected)
+-			retval = -ENODEV;
+-		else
+-			retval = usb_autopm_get_interface(serial->interface);
+-		if (retval)
+-			goto bailout_module_put;
+ 
+ 		/* only call the device specific open if this
+ 		 * is the first time the port is opened */
+ 		retval = serial->type->open(tty, port);
+ 		if (retval)
+-			goto bailout_interface_put;
++			goto bailout_module_put;
+ 		mutex_unlock(&serial->disc_mutex);
+ 		set_bit(ASYNCB_INITIALIZED, &port->port.flags);
+ 	}
+@@ -297,18 +289,11 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
+ 		goto bailout_mutex_unlock;
+ 	/* Undo the initial port actions */
+ 	mutex_lock(&serial->disc_mutex);
+-bailout_interface_put:
+-	usb_autopm_put_interface(serial->interface);
+ bailout_module_put:
+ 	mutex_unlock(&serial->disc_mutex);
+-	module_put(serial->type->driver.owner);
+ bailout_mutex_unlock:
+ 	port->port.count = 0;
+-	tty->driver_data = NULL;
+-	tty_port_tty_set(&port->port, NULL);
+ 	mutex_unlock(&port->mutex);
+-bailout_serial_put:
+-	usb_serial_put(serial);
+ 	return retval;
+ }
+ 
+@@ -355,9 +340,6 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
+ {
+ 	struct usb_serial_port *port = tty->driver_data;
+ 
+-	if (!port)
+-		return;
+-
+ 	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (tty_port_close_start(&port->port, tty, filp) == 0)
+@@ -365,7 +347,6 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
+ 	serial_do_down(port);
+ 	tty_port_close_end(&port->port, tty);
+ 	tty_port_tty_set(&port->port, NULL);
+-
+ }
+ 
+ /**
+@@ -386,9 +367,11 @@ static void serial_do_free(struct tty_struct *tty)
+ 	/* The console is magical.  Do not hang up the console hardware
+ 	 * or there will be tears.
+ 	 */
+-	if (port == NULL || port->console)
++	if (port->console)
+ 		return;
+ 
++	tty->driver_data = NULL;
++
+ 	serial = port->serial;
+ 	owner = serial->type->driver.owner;
+ 

commit 8bc2c1b2daf95029658868cb1427baea2da87139
+Author: Alan Stern 
+Date:   Tue Sep 1 11:38:59 2009 -0400
+
+    usb-serial: change logic of serial lookups
+    
+    This patch (as1286) changes usb_serial_get_by_index().  Now the
+    routine will check whether the serial device has been disconnected; if
+    it has then the return value will be NULL.  If the device hasn't been
+    disconnected then the routine will return with serial->disc_mutex
+    held, so that the caller can use the structure without fear of racing
+    against driver unloads.
+    
+    This permits the scope of table_mutex in destroy_serial() to be
+    reduced.  Instead of protecting the entire function, it suffices to
+    protect the part that actually uses serial_table[], i.e., the call to
+    return_serial().  There's no longer any danger of the refcount being
+    incremented after it reaches 0 (which was the reason for having the
+    large scope previously), because it can't reach 0 until the serial
+    device has been disconnected.
+    
+    Also, the patch makes serial_install() check that serial is non-NULL
+    before attempting to use it.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
+index 266dc583867b..87802ea8bbc8 100644
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -66,6 +66,11 @@ static struct usb_serial *serial_table[SERIAL_TTY_MINORS];
+ static DEFINE_MUTEX(table_lock);
+ static LIST_HEAD(usb_serial_driver_list);
+ 
++/*
++ * Look up the serial structure.  If it is found and it hasn't been
++ * disconnected, return with its disc_mutex held and its refcount
++ * incremented.  Otherwise return NULL.
++ */
+ struct usb_serial *usb_serial_get_by_index(unsigned index)
+ {
+ 	struct usb_serial *serial;
+@@ -73,8 +78,15 @@ struct usb_serial *usb_serial_get_by_index(unsigned index)
+ 	mutex_lock(&table_lock);
+ 	serial = serial_table[index];
+ 
+-	if (serial)
+-		kref_get(&serial->kref);
++	if (serial) {
++		mutex_lock(&serial->disc_mutex);
++		if (serial->disconnected) {
++			mutex_unlock(&serial->disc_mutex);
++			serial = NULL;
++		} else {
++			kref_get(&serial->kref);
++		}
++	}
+ 	mutex_unlock(&table_lock);
+ 	return serial;
+ }
+@@ -123,8 +135,10 @@ static void return_serial(struct usb_serial *serial)
+ 
+ 	dbg("%s", __func__);
+ 
++	mutex_lock(&table_lock);
+ 	for (i = 0; i < serial->num_ports; ++i)
+ 		serial_table[serial->minor + i] = NULL;
++	mutex_unlock(&table_lock);
+ }
+ 
+ static void destroy_serial(struct kref *kref)
+@@ -158,9 +172,7 @@ static void destroy_serial(struct kref *kref)
+ 
+ void usb_serial_put(struct usb_serial *serial)
+ {
+-	mutex_lock(&table_lock);
+ 	kref_put(&serial->kref, destroy_serial);
+-	mutex_unlock(&table_lock);
+ }
+ 
+ /*****************************************************************************
+@@ -190,9 +202,12 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
+ 			return retval;
+ 		/* allow the driver to update it */
+ 		serial = usb_serial_get_by_index(tty->index);
+-		if (serial->type->init_termios)
+-			serial->type->init_termios(tty);
+-		usb_serial_put(serial);
++		if (serial) {
++			if (serial->type->init_termios)
++				serial->type->init_termios(tty);
++			usb_serial_put(serial);
++			mutex_unlock(&serial->disc_mutex);
++		}
+ 	}
+ 	/* Final install (we use the default method) */
+ 	tty_driver_kref_get(driver);
+@@ -218,7 +233,6 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
+ 		return -ENODEV;
+ 	}
+ 
+-	mutex_lock(&serial->disc_mutex);
+ 	portNumber = tty->index - serial->minor;
+ 	port = serial->port[portNumber];
+ 	if (!port || serial->disconnected)
+@@ -529,6 +543,7 @@ static int serial_proc_show(struct seq_file *m, void *v)
+ 
+ 		seq_putc(m, '\n');
+ 		usb_serial_put(serial);
++		mutex_unlock(&serial->disc_mutex);
+ 	}
+ 	return 0;
+ }

commit f5b0953a89fa3407fb293cc54ead7d8feec489e4
+Author: Alan Stern 
+Date:   Tue Sep 1 11:38:44 2009 -0400
+
+    usb-serial: put subroutines in logical order
+    
+    This patch (as1285) rearranges the subroutines in usb-serial.c
+    concerned with tty lifetimes into a more logical order: install, open,
+    hangup, close, release.  It also updates the formatting of the
+    kerneldoc comments.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
+index f1a1f0fb6d1b..266dc583867b 100644
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -166,6 +166,41 @@ void usb_serial_put(struct usb_serial *serial)
+ /*****************************************************************************
+  * Driver tty interface functions
+  *****************************************************************************/
++
++/**
++ * serial_install - install tty
++ * @driver: the driver (USB in our case)
++ * @tty: the tty being created
++ *
++ * Create the termios objects for this tty.  We use the default
++ * USB serial settings but permit them to be overridden by
++ * serial->type->init_termios.
++ */
++static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
++{
++	int idx = tty->index;
++	struct usb_serial *serial;
++	int retval;
++
++	/* If the termios setup has yet to be done */
++	if (tty->driver->termios[idx] == NULL) {
++		/* perform the standard setup */
++		retval = tty_init_termios(tty);
++		if (retval)
++			return retval;
++		/* allow the driver to update it */
++		serial = usb_serial_get_by_index(tty->index);
++		if (serial->type->init_termios)
++			serial->type->init_termios(tty);
++		usb_serial_put(serial);
++	}
++	/* Final install (we use the default method) */
++	tty_driver_kref_get(driver);
++	tty->count++;
++	driver->ttys[idx] = tty;
++	return 0;
++}
++
+ static int serial_open (struct tty_struct *tty, struct file *filp)
+ {
+ 	struct usb_serial *serial;
+@@ -264,13 +299,11 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
+ }
+ 
+ /**
+- *	serial_do_down		-	shut down hardware
+- *	@port: port to shut down
++ * serial_do_down - shut down hardware
++ * @port: port to shut down
+  *
+- *	Shut down a USB port unless it is the console. We never shut down the
+- *	console hardware as it will always be in use.
+- *
+- *	Don't free any resources at this point
++ * Shut down a USB serial port unless it is the console.  We never
++ * shut down the console hardware as it will always be in use.
+  */
+ static void serial_do_down(struct usb_serial_port *port)
+ {
+@@ -278,8 +311,10 @@ static void serial_do_down(struct usb_serial_port *port)
+ 	struct usb_serial *serial;
+ 	struct module *owner;
+ 
+-	/* The console is magical, do not hang up the console hardware
+-	   or there will be tears */
++	/*
++	 * The console is magical.  Do not hang up the console hardware
++	 * or there will be tears.
++	 */
+ 	if (port->console)
+ 		return;
+ 
+@@ -293,24 +328,50 @@ static void serial_do_down(struct usb_serial_port *port)
+ 	mutex_unlock(&port->mutex);
+ }
+ 
++static void serial_hangup(struct tty_struct *tty)
++{
++	struct usb_serial_port *port = tty->driver_data;
++	serial_do_down(port);
++	tty_port_hangup(&port->port);
++	/* We must not free port yet - the USB serial layer depends on it's
++	   continued existence */
++}
++
++static void serial_close(struct tty_struct *tty, struct file *filp)
++{
++	struct usb_serial_port *port = tty->driver_data;
++
++	if (!port)
++		return;
++
++	dbg("%s - port %d", __func__, port->number);
++
++	if (tty_port_close_start(&port->port, tty, filp) == 0)
++		return;
++	serial_do_down(port);
++	tty_port_close_end(&port->port, tty);
++	tty_port_tty_set(&port->port, NULL);
++
++}
++
+ /**
+- *	serial_do_free		-	free resources post close/hangup
+- *	@port: port to free up
++ * serial_do_free - free resources post close/hangup
++ * @port: port to free up
+  *
+- *	Do the resource freeing and refcount dropping for the port. We must
+- *	be careful about ordering and we must avoid freeing up the console.
++ * Do the resource freeing and refcount dropping for the port.
++ * Avoid freeing the console.
+  *
+- *	Called when the last tty kref is dropped.
++ * Called when the last tty kref is dropped.
+  */
+-
+ static void serial_do_free(struct tty_struct *tty)
+ {
+ 	struct usb_serial_port *port = tty->driver_data;
+ 	struct usb_serial *serial;
+ 	struct module *owner;
+ 
+-	/* The console is magical, do not hang up the console hardware
+-	   or there will be tears */
++	/* The console is magical.  Do not hang up the console hardware
++	 * or there will be tears.
++	 */
+ 	if (port == NULL || port->console)
+ 		return;
+ 
+@@ -326,32 +387,6 @@ static void serial_do_free(struct tty_struct *tty)
+ 	module_put(owner);
+ }
+ 
+-static void serial_close(struct tty_struct *tty, struct file *filp)
+-{
+-	struct usb_serial_port *port = tty->driver_data;
+-
+-	if (!port)
+-		return;
+-
+-	dbg("%s - port %d", __func__, port->number);
+-
+-	if (tty_port_close_start(&port->port, tty, filp) == 0)
+-		return;
+-	serial_do_down(port);		
+-	tty_port_close_end(&port->port, tty);
+-	tty_port_tty_set(&port->port, NULL);
+-
+-}
+-
+-static void serial_hangup(struct tty_struct *tty)
+-{
+-	struct usb_serial_port *port = tty->driver_data;
+-	serial_do_down(port);
+-	tty_port_hangup(&port->port);
+-	/* We must not free port yet - the USB serial layer depends on it's
+-	   continued existence */
+-}
+-
+ static int serial_write(struct tty_struct *tty, const unsigned char *buf,
+ 								int count)
+ {
+@@ -699,41 +734,6 @@ static const struct tty_port_operations serial_port_ops = {
+ 	.dtr_rts = serial_dtr_rts,
+ };
+ 
+-/**
+- *	serial_install		-	install tty
+- *	@driver: the driver (USB in our case)
+- *	@tty: the tty being created
+- *
+- *	Create the termios objects for this tty. We use the default USB
+- *	serial ones but permit them to be overriddenby serial->type->termios.
+- *	This lets us remove all the ugly hackery
+- */
+-
+-static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
+-{
+-	int idx = tty->index;
+-	struct usb_serial *serial;
+-	int retval;
+-
+-	/* If the termios setup has yet to be done */
+-	if (tty->driver->termios[idx] == NULL) {
+-		/* perform the standard setup */
+-		retval = tty_init_termios(tty);
+-		if (retval)
+-			return retval;
+-		/* allow the driver to update it */
+-		serial = usb_serial_get_by_index(tty->index);
+-		if (serial->type->init_termios)
+-			serial->type->init_termios(tty);
+-		usb_serial_put(serial);
+-	}
+-	/* Final install (we use the default method) */
+-	tty_driver_kref_get(driver);
+-	tty->count++;
+-	driver->ttys[idx] = tty;
+-	return 0;
+-}
+-
+ int usb_serial_probe(struct usb_interface *interface,
+ 			       const struct usb_device_id *id)
+ {

commit 41bd34ddd7aa46dbc03b5bb33896e0fa8100fe7b
+Author: Alan Stern 
+Date:   Tue Sep 1 11:38:34 2009 -0400
+
+    usb-serial: change referencing of port and serial structures
+    
+    This patch (as1284) changes the referencing of the usb_serial and
+    usb_serial_port structures in usb-serial.c.  It's not feasible to make
+    the port structures keep a reference to the serial structure, because
+    the ports need to remain in existence when serial is released -- quite
+    a few of the drivers expect this.  Consequently taking a reference
+    to the port when the device file is open is insufficient; such a
+    reference would not pin serial.
+    
+    To fix this, we now take a reference to serial when the device file is
+    opened.  The final put_device() for the ports occurs in
+    destroy_serial(), so that the ports will last as long as they are
+    needed.
+    
+    The patch initializes all the port devices, including those in the
+    unused "fake" ports.  This makes the code more uniform because they
+    can all be released in the same way.  The error handling code in
+    usb_serial_probe() is much simplified by this approach; instead of
+    freeing everything by hand we can use a single usb_serial_put() call.
+    
+    Also simplified is the port-release mechanism.  Instead of being two
+    separate routines, port_release() and port_free() can be combined into
+    one.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
+index 80c1f4d8e910..f1a1f0fb6d1b 100644
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -43,8 +43,6 @@
+ #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
+ #define DRIVER_DESC "USB Serial Driver core"
+ 
+-static void port_free(struct usb_serial_port *port);
+-
+ /* Driver structure we register with the USB core */
+ static struct usb_driver usb_serial_driver = {
+ 	.name =		"usbserial",
+@@ -145,27 +143,16 @@ static void destroy_serial(struct kref *kref)
+ 
+ 	serial->type->release(serial);
+ 
+-	for (i = 0; i < serial->num_ports; ++i) {
++	/* Now that nothing is using the ports, they can be freed */
++	for (i = 0; i < serial->num_port_pointers; ++i) {
+ 		port = serial->port[i];
+-		if (port)
++		if (port) {
++			port->serial = NULL;
+ 			put_device(&port->dev);
+-	}
+-
+-	/* If this is a "fake" port, we have to clean it up here, as it will
+-	 * not get cleaned up in port_release() as it was never registered with
+-	 * the driver core */
+-	if (serial->num_ports < serial->num_port_pointers) {
+-		for (i = serial->num_ports;
+-					i < serial->num_port_pointers; ++i) {
+-			port = serial->port[i];
+-			if (port)
+-				port_free(port);
+ 		}
+ 	}
+ 
+ 	usb_put_dev(serial->dev);
+-
+-	/* free up any memory that we allocated */
+ 	kfree(serial);
+ }
+ 
+@@ -201,8 +188,6 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
+ 	port = serial->port[portNumber];
+ 	if (!port || serial->disconnected)
+ 		retval = -ENODEV;
+-	else
+-		get_device(&port->dev);
+ 	/*
+ 	 * Note: Our locking order requirement does not allow port->mutex
+ 	 * to be acquired while serial->disc_mutex is held.
+@@ -213,7 +198,7 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
+ 
+ 	if (mutex_lock_interruptible(&port->mutex)) {
+ 		retval = -ERESTARTSYS;
+-		goto bailout_port_put;
++		goto bailout_serial_put;
+ 	}
+ 
+ 	++port->port.count;
+@@ -273,8 +258,6 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
+ 	tty->driver_data = NULL;
+ 	tty_port_tty_set(&port->port, NULL);
+ 	mutex_unlock(&port->mutex);
+-bailout_port_put:
+-	put_device(&port->dev);
+ bailout_serial_put:
+ 	usb_serial_put(serial);
+ 	return retval;
+@@ -333,14 +316,13 @@ static void serial_do_free(struct tty_struct *tty)
+ 
+ 	serial = port->serial;
+ 	owner = serial->type->driver.owner;
+-	put_device(&port->dev);
+-	/* Mustn't dereference port any more */
++
+ 	mutex_lock(&serial->disc_mutex);
+ 	if (!serial->disconnected)
+ 		usb_autopm_put_interface(serial->interface);
+ 	mutex_unlock(&serial->disc_mutex);
++
+ 	usb_serial_put(serial);
+-	/* Mustn't dereference serial any more */
+ 	module_put(owner);
+ }
+ 
+@@ -581,14 +563,6 @@ static void usb_serial_port_work(struct work_struct *work)
+ 	tty_kref_put(tty);
+ }
+ 
+-static void port_release(struct device *dev)
+-{
+-	struct usb_serial_port *port = to_usb_serial_port(dev);
+-
+-	dbg ("%s - %s", __func__, dev_name(dev));
+-	port_free(port);
+-}
+-
+ static void kill_traffic(struct usb_serial_port *port)
+ {
+ 	usb_kill_urb(port->read_urb);
+@@ -608,8 +582,12 @@ static void kill_traffic(struct usb_serial_port *port)
+ 	usb_kill_urb(port->interrupt_out_urb);
+ }
+ 
+-static void port_free(struct usb_serial_port *port)
++static void port_release(struct device *dev)
+ {
++	struct usb_serial_port *port = to_usb_serial_port(dev);
++
++	dbg ("%s - %s", __func__, dev_name(dev));
++
+ 	/*
+ 	 * Stop all the traffic before cancelling the work, so that
+ 	 * nobody will restart it by calling usb_serial_port_softint.
+@@ -955,6 +933,11 @@ int usb_serial_probe(struct usb_interface *interface,
+ 		mutex_init(&port->mutex);
+ 		INIT_WORK(&port->work, usb_serial_port_work);
+ 		serial->port[i] = port;
++		port->dev.parent = &interface->dev;
++		port->dev.driver = NULL;
++		port->dev.bus = &usb_serial_bus_type;
++		port->dev.release = &port_release;
++		device_initialize(&port->dev);
+ 	}
+ 
+ 	/* set up the endpoint information */
+@@ -1097,15 +1080,10 @@ int usb_serial_probe(struct usb_interface *interface,
+ 	/* register all of the individual ports with the driver core */
+ 	for (i = 0; i < num_ports; ++i) {
+ 		port = serial->port[i];
+-		port->dev.parent = &interface->dev;
+-		port->dev.driver = NULL;
+-		port->dev.bus = &usb_serial_bus_type;
+-		port->dev.release = &port_release;
+-
+ 		dev_set_name(&port->dev, "ttyUSB%d", port->number);
+ 		dbg ("%s - registering %s", __func__, dev_name(&port->dev));
+ 		port->dev_state = PORT_REGISTERING;
+-		retval = device_register(&port->dev);
++		retval = device_add(&port->dev);
+ 		if (retval) {
+ 			dev_err(&port->dev, "Error registering port device, "
+ 				"continuing\n");
+@@ -1123,39 +1101,7 @@ int usb_serial_probe(struct usb_interface *interface,
+ 	return 0;
+ 
+ probe_error:
+-	for (i = 0; i < num_bulk_in; ++i) {
+-		port = serial->port[i];
+-		if (!port)
+-			continue;
+-		usb_free_urb(port->read_urb);
+-		kfree(port->bulk_in_buffer);
+-	}
+-	for (i = 0; i < num_bulk_out; ++i) {
+-		port = serial->port[i];
+-		if (!port)
+-			continue;
+-		usb_free_urb(port->write_urb);
+-		kfree(port->bulk_out_buffer);
+-	}
+-	for (i = 0; i < num_interrupt_in; ++i) {
+-		port = serial->port[i];
+-		if (!port)
+-			continue;
+-		usb_free_urb(port->interrupt_in_urb);
+-		kfree(port->interrupt_in_buffer);
+-	}
+-	for (i = 0; i < num_interrupt_out; ++i) {
+-		port = serial->port[i];
+-		if (!port)
+-			continue;
+-		usb_free_urb(port->interrupt_out_urb);
+-		kfree(port->interrupt_out_buffer);
+-	}
+-
+-	/* free up any memory that we allocated */
+-	for (i = 0; i < serial->num_port_pointers; ++i)
+-		kfree(serial->port[i]);
+-	kfree(serial);
++	usb_serial_put(serial);
+ 	return -EIO;
+ }
+ EXPORT_SYMBOL_GPL(usb_serial_probe);
+@@ -1206,8 +1152,7 @@ void usb_serial_disconnect(struct usb_interface *interface)
+ 	}
+ 	serial->type->disconnect(serial);
+ 
+-	/* let the last holder of this object
+-	 * cause it to be cleaned up */
++	/* let the last holder of this object cause it to be cleaned up */
+ 	usb_serial_put(serial);
+ 	dev_info(dev, "device disconnected\n");
+ }

commit 1f5c13fad4ec5617b610e12205902c06298c096a
+Author: Alan Stern 
+Date:   Thu Aug 20 15:23:47 2009 -0400
+
+    TTY: fix typos
+    
+    This patch (as1282) fixes some obvious typos in the TTY core.
+    
+    Signed-off-by: Alan Stern 
+    CC: Alan Cox 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c
+index c767e30a1425..a4bbb28f10be 100644
+--- a/drivers/char/tty_port.c
++++ b/drivers/char/tty_port.c
+@@ -100,7 +100,7 @@ EXPORT_SYMBOL(tty_port_tty_set);
+ static void tty_port_shutdown(struct tty_port *port)
+ {
+ 	if (port->ops->shutdown &&
+-		test_and_clear_bit(ASYNC_INITIALIZED, &port->flags))
++		test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags))
+ 			port->ops->shutdown(port);
+ 
+ }
+@@ -311,7 +311,7 @@ int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct f
+ 			port->ops->drop(port);
+ 		return 0;
+ 	}
+-	set_bit(ASYNC_CLOSING, &port->flags);
++	set_bit(ASYNCB_CLOSING, &port->flags);
+ 	tty->closing = 1;
+ 	spin_unlock_irqrestore(&port->lock, flags);
+ 	/* Don't block on a stalled port, just pull the chain */

commit 2023c610dc54a4f4130b0494309a9bd668ca3df8
+Author: Alan Stern 
+Date:   Thu Jul 30 15:27:18 2009 -0400
+
+    Driver core: add new device to bus's list before probing
+    
+    This patch (as1271) affects when new devices get linked into their
+    bus's list of devices.  Currently this happens after probing, and it
+    doesn't happen at all if probing fails.  Clearly this is wrong,
+    because at that point quite a few symbolic links have already been
+    created in sysfs.  We are committed to adding the device, so it should
+    be linked into the bus's list regardless.
+    
+    In addition, this needs to happen before the uevent announcing the new
+    device gets issued.  Otherwise user programs might try to access the
+    device before it has been added to the bus.
+    
+    To fix both these problems, the patch moves the call to
+    klist_add_tail() forward from bus_attach_device() to bus_add_device().
+    Since bus_attach_device() now does nothing but probe for drivers, it
+    has been renamed to bus_probe_device().  And lastly, the kerneldoc is
+    updated.
+    
+    Signed-off-by: Alan Stern 
+    CC: Kay Sievers 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/base/base.h b/drivers/base/base.h
+index b528145a078f..1e52c125f437 100644
+--- a/drivers/base/base.h
++++ b/drivers/base/base.h
+@@ -104,7 +104,7 @@ extern int system_bus_init(void);
+ extern int cpu_dev_init(void);
+ 
+ extern int bus_add_device(struct device *dev);
+-extern void bus_attach_device(struct device *dev);
++extern void bus_probe_device(struct device *dev);
+ extern void bus_remove_device(struct device *dev);
+ 
+ extern int bus_add_driver(struct device_driver *drv);
+diff --git a/drivers/base/bus.c b/drivers/base/bus.c
+index 4b04a15146d7..973bf2ad4e0d 100644
+--- a/drivers/base/bus.c
++++ b/drivers/base/bus.c
+@@ -459,8 +459,9 @@ static inline void remove_deprecated_bus_links(struct device *dev) { }
+  * bus_add_device - add device to bus
+  * @dev: device being added
+  *
++ * - Add device's bus attributes.
++ * - Create links to device's bus.
+  * - Add the device to its bus's list of devices.
+- * - Create link to device's bus.
+  */
+ int bus_add_device(struct device *dev)
+ {
+@@ -483,6 +484,7 @@ int bus_add_device(struct device *dev)
+ 		error = make_deprecated_bus_links(dev);
+ 		if (error)
+ 			goto out_deprecated;
++		klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices);
+ 	}
+ 	return 0;
+ 
+@@ -498,24 +500,19 @@ int bus_add_device(struct device *dev)
+ }
+ 
+ /**
+- * bus_attach_device - add device to bus
+- * @dev: device tried to attach to a driver
++ * bus_probe_device - probe drivers for a new device
++ * @dev: device to probe
+  *
+- * - Add device to bus's list of devices.
+- * - Try to attach to driver.
++ * - Automatically probe for a driver if the bus allows it.
+  */
+-void bus_attach_device(struct device *dev)
++void bus_probe_device(struct device *dev)
+ {
+ 	struct bus_type *bus = dev->bus;
+-	int ret = 0;
++	int ret;
+ 
+-	if (bus) {
+-		if (bus->p->drivers_autoprobe)
+-			ret = device_attach(dev);
++	if (bus && bus->p->drivers_autoprobe) {
++		ret = device_attach(dev);
+ 		WARN_ON(ret < 0);
+-		if (ret >= 0)
+-			klist_add_tail(&dev->p->knode_bus,
+-				       &bus->p->klist_devices);
+ 	}
+ }
+ 
+diff --git a/drivers/base/core.c b/drivers/base/core.c
+index 7ecb1938e590..c34774d0b9d3 100644
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -945,7 +945,7 @@ int device_add(struct device *dev)
+ 					     BUS_NOTIFY_ADD_DEVICE, dev);
+ 
+ 	kobject_uevent(&dev->kobj, KOBJ_ADD);
+-	bus_attach_device(dev);
++	bus_probe_device(dev);
+ 	if (parent)
+ 		klist_add_tail(&dev->p->knode_parent,
+ 			       &parent->p->klist_children);

commit ef4638f955f2c4a667c8af20769d03f5ed3781ca
+Author: Alan Stern 
+Date:   Fri Jul 31 10:41:40 2009 -0400
+
+    USB: EHCI: fix counting of transaction error retries
+    
+    This patch (as1274) simplifies the counting of transaction-error
+    retries.  Now we will count up from 0 to QH_XACTERR_MAX instead of
+    down from QH_XACTERR_MAX to 0.
+    
+    The patch also fixes a small bug: qh->xacterr was not getting
+    initialized for interrupt endpoints.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Matthijs Kooijman 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index b27380505576..7673554fa64d 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -375,12 +375,11 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 				 */
+ 				if ((token & QTD_STS_XACT) &&
+ 						QTD_CERR(token) == 0 &&
+-						--qh->xacterrs > 0 &&
++						++qh->xacterrs < QH_XACTERR_MAX &&
+ 						!urb->unlinked) {
+ 					ehci_dbg(ehci,
+ 	"detected XactErr len %zu/%zu retry %d\n",
+-	qtd->length - QTD_LENGTH(token), qtd->length,
+-	QH_XACTERR_MAX - qh->xacterrs);
++	qtd->length - QTD_LENGTH(token), qtd->length, qh->xacterrs);
+ 
+ 					/* reset the token in the qtd and the
+ 					 * qh overlay (which still contains
+@@ -494,7 +493,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		last = qtd;
+ 
+ 		/* reinit the xacterr counter for the next qtd */
+-		qh->xacterrs = QH_XACTERR_MAX;
++		qh->xacterrs = 0;
+ 	}
+ 
+ 	/* last urb's completion might still need calling */
+@@ -941,7 +940,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	head->hw_next = dma;
+ 
+ 	qh_get(qh);
+-	qh->xacterrs = QH_XACTERR_MAX;
++	qh->xacterrs = 0;
+ 	qh->qh_state = QH_STATE_LINKED;
+ 	/* qtd completions reported later by interrupt */
+ }
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 74f7f83b29ad..edd61ee90323 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -542,6 +542,7 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		}
+ 	}
+ 	qh->qh_state = QH_STATE_LINKED;
++	qh->xacterrs = 0;
+ 	qh_get (qh);
+ 
+ 	/* update per-qh bandwidth for usbfs */

commit 7a0f0d951273eee889c2441846842348ebc00a2a
+Author: Alan Stern 
+Date:   Fri Jul 31 10:40:22 2009 -0400
+
+    USB: EHCI: fix two new bugs related to Clear-TT-Buffer
+    
+    This patch (as1273) fixes two(!) bugs introduced by the new
+    Clear-TT-Buffer implementation in ehci-hcd.
+    
+            It is now possible for an idle QH to have some URBs on its
+            queue -- this will happen if a Clear-TT-Buffer is pending for
+            the QH's endpoint.  Consequently we should not issue a warning
+            when someone tries to unlink an URB from an idle QH; instead
+            we should process the request immediately.
+    
+            The refcounts for QHs could get messed up, because
+            submit_async() would increment the refcount when calling
+            qh_link_async() and qh_link_async() would then refuse to link
+            the QH into the schedule if a Clear-TT-Buffer was pending.
+            Instead we should increment the refcount only when the QH
+            actually is added to the schedule.  The current code tries to
+            be clever by leaving the refcount alone if an unlink is
+            immediately followed by a relink; the patch changes this to an
+            unconditional decrement and increment (although they occur in
+            the opposite order).
+    
+    Signed-off-by: Alan Stern 
+    CC: David Brownell 
+    Tested-by: Manuel Lauss 
+    Tested-by: Matthijs Kooijman 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 7d03549c3339..11c627ce6022 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -903,7 +903,8 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ 			/* already started */
+ 			break;
+ 		case QH_STATE_IDLE:
+-			WARN_ON(1);
++			/* QH might be waiting for a Clear-TT-Buffer */
++			qh_completions(ehci, qh);
+ 			break;
+ 		}
+ 		break;
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 9a1384747f3b..b27380505576 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -940,6 +940,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	head->qh_next.qh = qh;
+ 	head->hw_next = dma;
+ 
++	qh_get(qh);
+ 	qh->xacterrs = QH_XACTERR_MAX;
+ 	qh->qh_state = QH_STATE_LINKED;
+ 	/* qtd completions reported later by interrupt */
+@@ -1080,7 +1081,7 @@ submit_async (
+ 	 * the HC and TT handle it when the TT has a buffer ready.
+ 	 */
+ 	if (likely (qh->qh_state == QH_STATE_IDLE))
+-		qh_link_async (ehci, qh_get (qh));
++		qh_link_async(ehci, qh);
+  done:
+ 	spin_unlock_irqrestore (&ehci->lock, flags);
+ 	if (unlikely (qh == NULL))
+@@ -1115,8 +1116,6 @@ static void end_unlink_async (struct ehci_hcd *ehci)
+ 			&& HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
+ 		qh_link_async (ehci, qh);
+ 	else {
+-		qh_put (qh);		// refcount from async list
+-
+ 		/* it's not free to turn the async schedule on/off; leave it
+ 		 * active but idle for a while once it empties.
+ 		 */
+@@ -1124,6 +1123,7 @@ static void end_unlink_async (struct ehci_hcd *ehci)
+ 				&& ehci->async->qh_next.qh == NULL)
+ 			timer_action (ehci, TIMER_ASYNC_OFF);
+ 	}
++	qh_put(qh);			/* refcount from async list */
+ 
+ 	if (next) {
+ 		ehci->reclaim = NULL;

commit 01105a246345f011fde64d24a601090b646e9e4c
+Author: Alan Stern 
+Date:   Thu Jul 30 15:28:14 2009 -0400
+
+    USB: usbfs: fix -ENOENT error code to be -ENODEV
+    
+    This patch (as1272) changes the error code returned when an open call
+    for a USB device node fails to locate the corresponding device.  The
+    appropriate error code is -ENODEV, not -ENOENT.
+    
+    Signed-off-by: Alan Stern 
+    CC: Kay Sievers 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index e192fa05f8a1..4247eccf858c 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -595,7 +595,7 @@ static int usbdev_open(struct inode *inode, struct file *file)
+ 	if (!ps)
+ 		goto out;
+ 
+-	ret = -ENOENT;
++	ret = -ENODEV;
+ 
+ 	/* usbdev device-node */
+ 	if (imajor(inode) == USB_DEVICE_MAJOR)

commit 0f157ef3a1284f41d9804ecb87fdcc8ea946b9fa
+Author: Alan Stern 
+Date:   Tue Jul 28 11:56:17 2009 -0400
+
+    USB: usbtest: no need for USB_DEVICEFS
+    
+    THis patch (as1270) allows the usbtest module to be built even when
+    USB_DEVICEFS isn't configured.  Tests can be performed without
+    USB_DEVICEFS, using the /dev/bus/usb/*/* device files.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
+index a68d91a11bee..abe3aa67ed00 100644
+--- a/drivers/usb/misc/Kconfig
++++ b/drivers/usb/misc/Kconfig
+@@ -220,7 +220,7 @@ config USB_IOWARRIOR
+ 
+ config USB_TEST
+ 	tristate "USB testing driver"
+-	depends on USB && USB_DEVICEFS
++	depends on USB
+ 	help
+ 	  This driver is for testing host controller software.  It is used
+ 	  with specialized device firmware for regression and stress testing,

commit 9180135bc80ab11199d482b6111e23f74d65af4a
+Author: Alan Stern 
+Date:   Mon Jun 29 11:04:54 2009 -0400
+
+    USB: handle zero-length usbfs submissions correctly
+    
+    This patch (as1262) fixes a bug in usbfs: It refuses to accept
+    zero-length transfers, and it insists that the buffer pointer be valid
+    even if there is no data being transferred.
+    
+    The patch also consolidates a bunch of repetitive access_ok() checks
+    into a single check, which incidentally fixes the lack of such a check
+    for Isochronous URBs.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 46ca2af5ef1c..38b8bce782d6 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -995,7 +995,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 				USBDEVFS_URB_ZERO_PACKET |
+ 				USBDEVFS_URB_NO_INTERRUPT))
+ 		return -EINVAL;
+-	if (!uurb->buffer)
++	if (uurb->buffer_length > 0 && !uurb->buffer)
+ 		return -EINVAL;
+ 	if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL &&
+ 	    (uurb->endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) {
+@@ -1051,11 +1051,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 			is_in = 0;
+ 			uurb->endpoint &= ~USB_DIR_IN;
+ 		}
+-		if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
+-				uurb->buffer, uurb->buffer_length)) {
+-			kfree(dr);
+-			return -EFAULT;
+-		}
+ 		snoop(&ps->dev->dev, "control urb: bRequest=%02x "
+ 			"bRrequestType=%02x wValue=%04x "
+ 			"wIndex=%04x wLength=%04x\n",
+@@ -1075,9 +1070,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 		uurb->number_of_packets = 0;
+ 		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
+ 			return -EINVAL;
+-		if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
+-				uurb->buffer, uurb->buffer_length))
+-			return -EFAULT;
+ 		snoop(&ps->dev->dev, "bulk urb\n");
+ 		break;
+ 
+@@ -1119,28 +1111,35 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 			return -EINVAL;
+ 		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
+ 			return -EINVAL;
+-		if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
+-				uurb->buffer, uurb->buffer_length))
+-			return -EFAULT;
+ 		snoop(&ps->dev->dev, "interrupt urb\n");
+ 		break;
+ 
+ 	default:
+ 		return -EINVAL;
+ 	}
+-	as = alloc_async(uurb->number_of_packets);
+-	if (!as) {
++	if (uurb->buffer_length > 0 &&
++			!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
++				uurb->buffer, uurb->buffer_length)) {
+ 		kfree(isopkt);
+ 		kfree(dr);
+-		return -ENOMEM;
++		return -EFAULT;
+ 	}
+-	as->urb->transfer_buffer = kmalloc(uurb->buffer_length, GFP_KERNEL);
+-	if (!as->urb->transfer_buffer) {
++	as = alloc_async(uurb->number_of_packets);
++	if (!as) {
+ 		kfree(isopkt);
+ 		kfree(dr);
+-		free_async(as);
+ 		return -ENOMEM;
+ 	}
++	if (uurb->buffer_length > 0) {
++		as->urb->transfer_buffer = kmalloc(uurb->buffer_length,
++				GFP_KERNEL);
++		if (!as->urb->transfer_buffer) {
++			kfree(isopkt);
++			kfree(dr);
++			free_async(as);
++			return -ENOMEM;
++		}
++	}
+ 	as->urb->dev = ps->dev;
+ 	as->urb->pipe = (uurb->type << 30) |
+ 			__create_pipe(ps->dev, uurb->endpoint & 0xf) |
+@@ -1182,7 +1181,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 	kfree(isopkt);
+ 	as->ps = ps;
+ 	as->userurb = arg;
+-	if (uurb->endpoint & USB_DIR_IN)
++	if (is_in && uurb->buffer_length > 0)
+ 		as->userbuffer = uurb->buffer;
+ 	else
+ 		as->userbuffer = NULL;
+@@ -1192,9 +1191,9 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 	as->uid = cred->uid;
+ 	as->euid = cred->euid;
+ 	security_task_getsecid(current, &as->secid);
+-	if (!is_in) {
++	if (!is_in && uurb->buffer_length > 0) {
+ 		if (copy_from_user(as->urb->transfer_buffer, uurb->buffer,
+-				as->urb->transfer_buffer_length)) {
++				uurb->buffer_length)) {
+ 			free_async(as);
+ 			return -EFAULT;
+ 		}

commit ec6d67e39f5638c792eb7490bf32586ccb9d8005
+Author: Alan Stern 
+Date:   Mon Jun 29 14:34:59 2009 -0400
+
+    USB: EHCI: report actual_length for iso transfers
+    
+    This patch (as1259b) makes ehci-hcd return the total number of bytes
+    transferred in urb->actual_length for Isochronous transfers.
+    Until now, the actual_length value was unaccountably left at 0.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: David Brownell 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 9d1babc7ff65..74f7f83b29ad 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1619,11 +1619,14 @@ itd_complete (
+ 				desc->status = -EPROTO;
+ 
+ 			/* HC need not update length with this error */
+-			if (!(t & EHCI_ISOC_BABBLE))
+-				desc->actual_length = EHCI_ITD_LENGTH (t);
++			if (!(t & EHCI_ISOC_BABBLE)) {
++				desc->actual_length = EHCI_ITD_LENGTH(t);
++				urb->actual_length += desc->actual_length;
++			}
+ 		} else if (likely ((t & EHCI_ISOC_ACTIVE) == 0)) {
+ 			desc->status = 0;
+-			desc->actual_length = EHCI_ITD_LENGTH (t);
++			desc->actual_length = EHCI_ITD_LENGTH(t);
++			urb->actual_length += desc->actual_length;
+ 		} else {
+ 			/* URB was too late */
+ 			desc->status = -EXDEV;
+@@ -2014,7 +2017,8 @@ sitd_complete (
+ 			desc->status = -EPROTO;
+ 	} else {
+ 		desc->status = 0;
+-		desc->actual_length = desc->length - SITD_LENGTH (t);
++		desc->actual_length = desc->length - SITD_LENGTH(t);
++		urb->actual_length += desc->actual_length;
+ 	}
+ 	stream->depth -= stream->interval << 3;
+ 

commit f092c240494f2d807401d93f95f683909b90af96
+Author: Alan Stern 
+Date:   Thu Jul 9 12:58:43 2009 -0400
+
+    USB: option: remove unnecessary and erroneous code
+    
+    This patch (as1264) removes a bunch of unnecessary and erroneous stuff
+    from the option USB-serial driver.  Clearly there's no need to verify
+    that the device pointer stored in the URBs is right or to store the
+    same pointer over again.  After all, the pointer can't change once it
+    has been set up.
+    
+    There's also no need to call usb_clear_halt for the IN endpoint
+    multiple times -- in fact, doing so is an error since every time after
+    the first there will be active URBs queued for that endpoint.  Since
+    the Clear-Halts don't appear to be needed at all, the patch simply
+    removes them.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
+index 4526064752fa..98262dd552bb 100644
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -748,7 +748,6 @@ static int option_write(struct tty_struct *tty, struct usb_serial_port *port,
+ 		memcpy(this_urb->transfer_buffer, buf, todo);
+ 		this_urb->transfer_buffer_length = todo;
+ 
+-		this_urb->dev = port->serial->dev;
+ 		err = usb_submit_urb(this_urb, GFP_ATOMIC);
+ 		if (err) {
+ 			dbg("usb_submit_urb %p (write bulk) failed "
+@@ -876,7 +875,6 @@ static void option_instat_callback(struct urb *urb)
+ 
+ 	/* Resubmit urb so we continue receiving IRQ data */
+ 	if (status != -ESHUTDOWN && status != -ENOENT) {
+-		urb->dev = serial->dev;
+ 		err = usb_submit_urb(urb, GFP_ATOMIC);
+ 		if (err)
+ 			dbg("%s: resubmit intr urb failed. (%d)",
+@@ -937,23 +935,11 @@ static int option_open(struct tty_struct *tty,
+ 
+ 	dbg("%s", __func__);
+ 
+-	/* Reset low level data toggle and start reading from endpoints */
++	/* Start reading from the IN endpoint */
+ 	for (i = 0; i < N_IN_URB; i++) {
+ 		urb = portdata->in_urbs[i];
+ 		if (!urb)
+ 			continue;
+-		if (urb->dev != serial->dev) {
+-			dbg("%s: dev %p != %p", __func__,
+-				urb->dev, serial->dev);
+-			continue;
+-		}
+-
+-		/*
+-		 * make sure endpoint data toggle is synchronized with the
+-		 * device
+-		 */
+-		usb_clear_halt(urb->dev, urb->pipe);
+-
+ 		err = usb_submit_urb(urb, GFP_KERNEL);
+ 		if (err) {
+ 			dbg("%s: submit urb %d failed (%d) %d",
+@@ -962,16 +948,6 @@ static int option_open(struct tty_struct *tty,
+ 		}
+ 	}
+ 
+-	/* Reset low level data toggle on out endpoints */
+-	for (i = 0; i < N_OUT_URB; i++) {
+-		urb = portdata->out_urbs[i];
+-		if (!urb)
+-			continue;
+-		urb->dev = serial->dev;
+-		/* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+-				usb_pipeout(urb->pipe), 0); */
+-	}
+-
+ 	option_send_setup(port);
+ 
+ 	return 0;
+@@ -1234,7 +1210,6 @@ static int option_resume(struct usb_serial *serial)
+ 			dbg("%s: No interrupt URB for port %d\n", __func__, i);
+ 			continue;
+ 		}
+-		port->interrupt_in_urb->dev = serial->dev;
+ 		err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO);
+ 		dbg("Submitted interrupt URB for port %d (result %d)", i, err);
+ 		if (err < 0) {

commit 4d2fae8b3597bc787f1f1c06637ce5ab8187e5a7
+Author: Alan Stern 
+Date:   Thu Jul 9 12:59:57 2009 -0400
+
+    USB: cypress_m8: remove invalid Clear-Halt
+    
+    This patch (as1265) removes an erroneous call to usb_clear_halt from
+    the cypress_m8 driver.  The call isn't valid because it is made from
+    interrupt context whereas usb_clear_halt is a blocking routine.
+    
+    Presumably the code has never been executed; if it did it would cause
+    an oops.  So instead treat -EPIPE like any other sort of unexplained
+    error.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
+index 9734085fd2fe..59adfe123110 100644
+--- a/drivers/usb/serial/cypress_m8.c
++++ b/drivers/usb/serial/cypress_m8.c
+@@ -1228,8 +1228,8 @@ static void cypress_read_int_callback(struct urb *urb)
+ 		/* precursor to disconnect so just go away */
+ 		return;
+ 	case -EPIPE:
+-		usb_clear_halt(port->serial->dev, 0x81);
+-		break;
++		/* Can't call usb_clear_halt while in_interrupt */
++		/* FALLS THROUGH */
+ 	default:
+ 		/* something ugly is going on... */
+ 		dev_err(&urb->dev->dev,

commit 7bae0a070db4bc2761dd9515f450cdfa3f3f248c
+Author: Alan Stern 
+Date:   Tue Jul 7 09:50:14 2009 -0400
+
+    USB: Sierra: fix oops upon device close
+    
+    This patch (as1263) fixes a mixup that occurred when conflicting
+    patches for the sierra driver were merged incorrectly.  The former
+    sierra_shutdown routine should have been become sierra_release, not
+    sierra_disconnect.
+    
+    The symptom this fixes is an oops when the device file is closed after
+    a Sierra device has been unplugged (Bugzilla #13675).
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Peter Naulls 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
+index 032f7aeb40a4..5062815baed0 100644
+--- a/drivers/usb/serial/sierra.c
++++ b/drivers/usb/serial/sierra.c
+@@ -814,7 +814,7 @@ static int sierra_startup(struct usb_serial *serial)
+ 	return 0;
+ }
+ 
+-static void sierra_disconnect(struct usb_serial *serial)
++static void sierra_release(struct usb_serial *serial)
+ {
+ 	int i;
+ 	struct usb_serial_port *port;
+@@ -830,7 +830,6 @@ static void sierra_disconnect(struct usb_serial *serial)
+ 		if (!portdata)
+ 			continue;
+ 		kfree(portdata);
+-		usb_set_serial_port_data(port, NULL);
+ 	}
+ }
+ 
+@@ -853,7 +852,7 @@ static struct usb_serial_driver sierra_device = {
+ 	.tiocmget          = sierra_tiocmget,
+ 	.tiocmset          = sierra_tiocmset,
+ 	.attach            = sierra_startup,
+-	.disconnect        = sierra_disconnect,
++	.release           = sierra_release,
+ 	.read_int_callback = sierra_instat_callback,
+ };
+ 

commit ba516de332c0e574457e58fb5aa0293e628b7b10
+Author: Alan Stern 
+Date:   Mon Jun 29 17:36:14 2009 -0400
+
+    USB: EHCI: check for STALL before other errors
+    
+    This patch (as1257) revises the way ehci-hcd detects STALLs.  The
+    logic is a little peculiar because there's no hardware status bit
+    specifically meant to indicate a STALL.  You just have to guess that a
+    STALL was received if the BABBLE bit (which is fatal) isn't set and
+    the transfer stopped before all its retries were used up.
+    
+    The existing code doesn't do this properly, because it tests for MMF
+    (Missed MicroFrame) and DBE (Data Buffer Error) before testing the
+    retry counter.  Thus, if a transaction gets either MMF or DBE the
+    corresponding flag is set and the transaction is retried.  If the
+    second attempt receives a STALL then -EPIPE is the correct return
+    value.  But the existing code would see the MMF or DBE flag instead
+    and return -EPROTO, -ENOSR, or -ECOMM.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index e3d2b627bfb3..9a1384747f3b 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -214,6 +214,14 @@ static int qtd_copy_status (
+ 		if (token & QTD_STS_BABBLE) {
+ 			/* FIXME "must" disable babbling device's port too */
+ 			status = -EOVERFLOW;
++		/* CERR nonzero + halt --> stall */
++		} else if (QTD_CERR(token)) {
++			status = -EPIPE;
++
++		/* In theory, more than one of the following bits can be set
++		 * since they are sticky and the transaction is retried.
++		 * Which to test first is rather arbitrary.
++		 */
+ 		} else if (token & QTD_STS_MMF) {
+ 			/* fs/ls interrupt xfer missed the complete-split */
+ 			status = -EPROTO;
+@@ -222,21 +230,15 @@ static int qtd_copy_status (
+ 				? -ENOSR  /* hc couldn't read data */
+ 				: -ECOMM; /* hc couldn't write data */
+ 		} else if (token & QTD_STS_XACT) {
+-			/* timeout, bad crc, wrong PID, etc; retried */
+-			if (QTD_CERR (token))
+-				status = -EPIPE;
+-			else {
+-				ehci_dbg (ehci, "devpath %s ep%d%s 3strikes\n",
+-					urb->dev->devpath,
+-					usb_pipeendpoint (urb->pipe),
+-					usb_pipein (urb->pipe) ? "in" : "out");
+-				status = -EPROTO;
+-			}
+-		/* CERR nonzero + no errors + halt --> stall */
+-		} else if (QTD_CERR (token))
+-			status = -EPIPE;
+-		else	/* unknown */
++			/* timeout, bad CRC, wrong PID, etc */
++			ehci_dbg(ehci, "devpath %s ep%d%s 3strikes\n",
++				urb->dev->devpath,
++				usb_pipeendpoint(urb->pipe),
++				usb_pipein(urb->pipe) ? "in" : "out");
++			status = -EPROTO;
++		} else {	/* unknown */
+ 			status = -EPROTO;
++		}
+ 
+ 		ehci_vdbg (ehci,
+ 			"dev%d ep%d%s qtd token %08x --> status %d\n",

commit 914b701280a76f96890ad63eb0fa99bf204b961c
+Author: Alan Stern 
+Date:   Mon Jun 29 10:47:30 2009 -0400
+
+    USB: EHCI: use the new clear_tt_buffer interface
+    
+    This patch (as1256) changes ehci-hcd and all the other drivers in the
+    EHCI family to make use of the new clear_tt_buffer callbacks.  When a
+    Clear-TT-Buffer request is in progress for a QH, the QH is not allowed
+    to be linked into the async schedule until the request is finished.
+    At that time, if there are any URBs queued for the QH, it is linked
+    into the async schedule.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
+index c3a778bd359c..59d208d94d4e 100644
+--- a/drivers/usb/host/ehci-au1xxx.c
++++ b/drivers/usb/host/ehci-au1xxx.c
+@@ -113,6 +113,8 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
+ 	.bus_resume		= ehci_bus_resume,
+ 	.relinquish_port	= ehci_relinquish_port,
+ 	.port_handed_over	= ehci_port_handed_over,
++
++	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
+ };
+ 
+ static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
+diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
+index bf86809c5120..991174937db3 100644
+--- a/drivers/usb/host/ehci-fsl.c
++++ b/drivers/usb/host/ehci-fsl.c
+@@ -325,6 +325,8 @@ static const struct hc_driver ehci_fsl_hc_driver = {
+ 	.bus_resume = ehci_bus_resume,
+ 	.relinquish_port = ehci_relinquish_port,
+ 	.port_handed_over = ehci_port_handed_over,
++
++	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+ };
+ 
+ static int ehci_fsl_drv_probe(struct platform_device *pdev)
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 99c75603ec87..7d03549c3339 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1003,6 +1003,8 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 		schedule_timeout_uninterruptible(1);
+ 		goto rescan;
+ 	case QH_STATE_IDLE:		/* fully unlinked */
++		if (qh->clearing_tt)
++			goto idle_timeout;
+ 		if (list_empty (&qh->qtd_list)) {
+ 			qh_put (qh);
+ 			break;
+diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c
+index a44bb4a94954..89b7c70c6ed6 100644
+--- a/drivers/usb/host/ehci-ixp4xx.c
++++ b/drivers/usb/host/ehci-ixp4xx.c
+@@ -61,6 +61,8 @@ static const struct hc_driver ixp4xx_ehci_hc_driver = {
+ #endif
+ 	.relinquish_port	= ehci_relinquish_port,
+ 	.port_handed_over	= ehci_port_handed_over,
++
++	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
+ };
+ 
+ static int ixp4xx_ehci_probe(struct platform_device *pdev)
+diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
+index 770dd9aba62a..dc2ac613a9d1 100644
+--- a/drivers/usb/host/ehci-orion.c
++++ b/drivers/usb/host/ehci-orion.c
+@@ -165,6 +165,8 @@ static const struct hc_driver ehci_orion_hc_driver = {
+ 	.bus_resume = ehci_bus_resume,
+ 	.relinquish_port = ehci_relinquish_port,
+ 	.port_handed_over = ehci_port_handed_over,
++
++	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+ };
+ 
+ static void __init
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index f3683e1da161..c2f1b7df918c 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -404,6 +404,8 @@ static const struct hc_driver ehci_pci_hc_driver = {
+ 	.bus_resume =		ehci_bus_resume,
+ 	.relinquish_port =	ehci_relinquish_port,
+ 	.port_handed_over =	ehci_port_handed_over,
++
++	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
+ };
+ 
+ /*-------------------------------------------------------------------------*/
+diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c
+index fbd272288fc2..36f96da129f5 100644
+--- a/drivers/usb/host/ehci-ppc-of.c
++++ b/drivers/usb/host/ehci-ppc-of.c
+@@ -79,6 +79,8 @@ static const struct hc_driver ehci_ppc_of_hc_driver = {
+ #endif
+ 	.relinquish_port	= ehci_relinquish_port,
+ 	.port_handed_over	= ehci_port_handed_over,
++
++	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
+ };
+ 
+ 
+diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
+index 93f7035d00a1..1dee33b9139e 100644
+--- a/drivers/usb/host/ehci-ps3.c
++++ b/drivers/usb/host/ehci-ps3.c
+@@ -75,6 +75,8 @@ static const struct hc_driver ps3_ehci_hc_driver = {
+ #endif
+ 	.relinquish_port	= ehci_relinquish_port,
+ 	.port_handed_over	= ehci_port_handed_over,
++
++	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
+ };
+ 
+ static int __devinit ps3_ehci_probe(struct ps3_system_bus_device *dev)
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 68bf81e982d2..e3d2b627bfb3 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -139,6 +139,55 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++static void qh_link_async(struct ehci_hcd *ehci, struct ehci_qh *qh);
++
++static void ehci_clear_tt_buffer_complete(struct usb_hcd *hcd,
++		struct usb_host_endpoint *ep)
++{
++	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
++	struct ehci_qh		*qh = ep->hcpriv;
++	unsigned long		flags;
++
++	spin_lock_irqsave(&ehci->lock, flags);
++	qh->clearing_tt = 0;
++	if (qh->qh_state == QH_STATE_IDLE && !list_empty(&qh->qtd_list)
++			&& HC_IS_RUNNING(hcd->state))
++		qh_link_async(ehci, qh);
++	spin_unlock_irqrestore(&ehci->lock, flags);
++}
++
++static void ehci_clear_tt_buffer(struct ehci_hcd *ehci, struct ehci_qh *qh,
++		struct urb *urb, u32 token)
++{
++
++	/* If an async split transaction gets an error or is unlinked,
++	 * the TT buffer may be left in an indeterminate state.  We
++	 * have to clear the TT buffer.
++	 *
++	 * Note: this routine is never called for Isochronous transfers.
++	 */
++	if (urb->dev->tt && !usb_pipeint(urb->pipe) && !qh->clearing_tt) {
++#ifdef DEBUG
++		struct usb_device *tt = urb->dev->tt->hub;
++		dev_dbg(&tt->dev,
++			"clear tt buffer port %d, a%d ep%d t%08x\n",
++			urb->dev->ttport, urb->dev->devnum,
++			usb_pipeendpoint(urb->pipe), token);
++#endif /* DEBUG */
++		if (!ehci_is_TDI(ehci)
++				|| urb->dev->tt->hub !=
++				   ehci_to_hcd(ehci)->self.root_hub) {
++			if (usb_hub_clear_tt_buffer(urb) == 0)
++				qh->clearing_tt = 1;
++		} else {
++
++			/* REVISIT ARC-derived cores don't clear the root
++			 * hub TT buffer in this way...
++			 */
++		}
++	}
++}
++
+ static int qtd_copy_status (
+ 	struct ehci_hcd *ehci,
+ 	struct urb *urb,
+@@ -195,28 +244,6 @@ static int qtd_copy_status (
+ 			usb_pipeendpoint (urb->pipe),
+ 			usb_pipein (urb->pipe) ? "in" : "out",
+ 			token, status);
+-
+-		/* if async CSPLIT failed, try cleaning out the TT buffer */
+-		if (status != -EPIPE
+-				&& urb->dev->tt
+-				&& !usb_pipeint(urb->pipe)
+-				&& ((token & QTD_STS_MMF) != 0
+-					|| QTD_CERR(token) == 0)
+-				&& (!ehci_is_TDI(ehci)
+-			                || urb->dev->tt->hub !=
+-					   ehci_to_hcd(ehci)->self.root_hub)) {
+-#ifdef DEBUG
+-			struct usb_device *tt = urb->dev->tt->hub;
+-			dev_dbg (&tt->dev,
+-				"clear tt buffer port %d, a%d ep%d t%08x\n",
+-				urb->dev->ttport, urb->dev->devnum,
+-				usb_pipeendpoint (urb->pipe), token);
+-#endif /* DEBUG */
+-			/* REVISIT ARC-derived cores don't clear the root
+-			 * hub TT buffer in this way...
+-			 */
+-			usb_hub_clear_tt_buffer(urb);
+-		}
+ 	}
+ 
+ 	return status;
+@@ -407,9 +434,16 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 			/* qh unlinked; token in overlay may be most current */
+ 			if (state == QH_STATE_IDLE
+ 					&& cpu_to_hc32(ehci, qtd->qtd_dma)
+-						== qh->hw_current)
++						== qh->hw_current) {
+ 				token = hc32_to_cpu(ehci, qh->hw_token);
+ 
++				/* An unlink may leave an incomplete
++				 * async transaction in the TT buffer.
++				 * We have to clear it.
++				 */
++				ehci_clear_tt_buffer(ehci, qh, urb, token);
++			}
++
+ 			/* force halt for unlinked or blocked qh, so we'll
+ 			 * patch the qh later and so that completions can't
+ 			 * activate it while we "know" it's stopped.
+@@ -435,6 +469,13 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 					&& (qtd->hw_alt_next
+ 						& EHCI_LIST_END(ehci)))
+ 				last_status = -EINPROGRESS;
++
++			/* As part of low/full-speed endpoint-halt processing
++			 * we must clear the TT buffer (11.17.5).
++			 */
++			if (unlikely(last_status != -EINPROGRESS &&
++					last_status != -EREMOTEIO))
++				ehci_clear_tt_buffer(ehci, qh, urb, token);
+ 		}
+ 
+ 		/* if we're removing something not at the queue head,
+@@ -864,6 +905,10 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	__hc32		dma = QH_NEXT(ehci, qh->qh_dma);
+ 	struct ehci_qh	*head;
+ 
++	/* Don't link a QH if there's a Clear-TT-Buffer pending */
++	if (unlikely(qh->clearing_tt))
++		return;
++
+ 	/* (re)start the async schedule? */
+ 	head = ehci->async;
+ 	timer_action_done (ehci, TIMER_ASYNC_OFF);
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 90ad3395bb21..2bfff30f4704 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -354,7 +354,9 @@ struct ehci_qh {
+ 	unsigned short		period;		/* polling interval */
+ 	unsigned short		start;		/* where polling starts */
+ #define NO_FRAME ((unsigned short)~0)			/* pick new start */
++
+ 	struct usb_device	*dev;		/* access to TT */
++	unsigned		clearing_tt:1;	/* Clear-TT-Buf in progress */
+ } __attribute__ ((aligned (32)));
+ 
+ /*-------------------------------------------------------------------------*/

commit cb88a1b887bb8908f6e00ce29e893ea52b074940
+Author: Alan Stern 
+Date:   Mon Jun 29 10:43:32 2009 -0400
+
+    USB: fix the clear_tt_buffer interface
+    
+    This patch (as1255) updates the interface for calling
+    usb_hub_clear_tt_buffer().  Even the name of the function is changed!
+    
+    When an async URB (i.e., Control or Bulk) going through a high-speed
+    hub to a non-high-speed device is cancelled or fails, the hub's
+    Transaction Translator buffer may be left busy still trying to
+    complete the transaction.  The buffer has to be cleared; that's what
+    usb_hub_clear_tt_buffer() does.
+    
+    It isn't safe to send any more URBs to the same endpoint until the TT
+    buffer is fully clear.  Therefore the HCD needs to be told when the
+    Clear-TT-Buffer request has finished.  This patch adds a callback
+    method to struct hc_driver for that purpose, and makes the hub driver
+    invoke the callback at the proper time.
+    
+    The patch also changes a couple of names; "hub_tt_kevent" and
+    "tt.kevent" now look rather antiquated.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index d397ecfd5b17..ec5c67ea07b7 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -227,6 +227,10 @@ struct hc_driver {
+ 		/* has a port been handed over to a companion? */
+ 	int	(*port_handed_over)(struct usb_hcd *, int);
+ 
++		/* CLEAR_TT_BUFFER completion callback */
++	void	(*clear_tt_buffer_complete)(struct usb_hcd *,
++				struct usb_host_endpoint *);
++
+ 	/* xHCI specific functions */
+ 		/* Called by usb_alloc_dev to alloc HC device structures */
+ 	int	(*alloc_dev)(struct usb_hcd *, struct usb_device *);
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 2af3b4f06054..71f86c60d83c 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -450,10 +450,10 @@ hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt)
+  * talking to TTs must queue control transfers (not just bulk and iso), so
+  * both can talk to the same hub concurrently.
+  */
+-static void hub_tt_kevent (struct work_struct *work)
++static void hub_tt_work(struct work_struct *work)
+ {
+ 	struct usb_hub		*hub =
+-		container_of(work, struct usb_hub, tt.kevent);
++		container_of(work, struct usb_hub, tt.clear_work);
+ 	unsigned long		flags;
+ 	int			limit = 100;
+ 
+@@ -462,6 +462,7 @@ static void hub_tt_kevent (struct work_struct *work)
+ 		struct list_head	*next;
+ 		struct usb_tt_clear	*clear;
+ 		struct usb_device	*hdev = hub->hdev;
++		const struct hc_driver	*drv;
+ 		int			status;
+ 
+ 		next = hub->tt.clear_list.next;
+@@ -471,21 +472,25 @@ static void hub_tt_kevent (struct work_struct *work)
+ 		/* drop lock so HCD can concurrently report other TT errors */
+ 		spin_unlock_irqrestore (&hub->tt.lock, flags);
+ 		status = hub_clear_tt_buffer (hdev, clear->devinfo, clear->tt);
+-		spin_lock_irqsave (&hub->tt.lock, flags);
+-
+ 		if (status)
+ 			dev_err (&hdev->dev,
+ 				"clear tt %d (%04x) error %d\n",
+ 				clear->tt, clear->devinfo, status);
++
++		/* Tell the HCD, even if the operation failed */
++		drv = clear->hcd->driver;
++		if (drv->clear_tt_buffer_complete)
++			(drv->clear_tt_buffer_complete)(clear->hcd, clear->ep);
++
+ 		kfree(clear);
++		spin_lock_irqsave(&hub->tt.lock, flags);
+ 	}
+ 	spin_unlock_irqrestore (&hub->tt.lock, flags);
+ }
+ 
+ /**
+- * usb_hub_tt_clear_buffer - clear control/bulk TT state in high speed hub
+- * @udev: the device whose split transaction failed
+- * @pipe: identifies the endpoint of the failed transaction
++ * usb_hub_clear_tt_buffer - clear control/bulk TT state in high speed hub
++ * @urb: an URB associated with the failed or incomplete split transaction
+  *
+  * High speed HCDs use this to tell the hub driver that some split control or
+  * bulk transaction failed in a way that requires clearing internal state of
+@@ -495,8 +500,10 @@ static void hub_tt_kevent (struct work_struct *work)
+  * It may not be possible for that hub to handle additional full (or low)
+  * speed transactions until that state is fully cleared out.
+  */
+-void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe)
++int usb_hub_clear_tt_buffer(struct urb *urb)
+ {
++	struct usb_device	*udev = urb->dev;
++	int			pipe = urb->pipe;
+ 	struct usb_tt		*tt = udev->tt;
+ 	unsigned long		flags;
+ 	struct usb_tt_clear	*clear;
+@@ -508,7 +515,7 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe)
+ 	if ((clear = kmalloc (sizeof *clear, GFP_ATOMIC)) == NULL) {
+ 		dev_err (&udev->dev, "can't save CLEAR_TT_BUFFER state\n");
+ 		/* FIXME recover somehow ... RESET_TT? */
+-		return;
++		return -ENOMEM;
+ 	}
+ 
+ 	/* info that CLEAR_TT_BUFFER needs */
+@@ -520,14 +527,19 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe)
+ 			: (USB_ENDPOINT_XFER_BULK << 11);
+ 	if (usb_pipein (pipe))
+ 		clear->devinfo |= 1 << 15;
+-	
++
++	/* info for completion callback */
++	clear->hcd = bus_to_hcd(udev->bus);
++	clear->ep = urb->ep;
++
+ 	/* tell keventd to clear state for this TT */
+ 	spin_lock_irqsave (&tt->lock, flags);
+ 	list_add_tail (&clear->clear_list, &tt->clear_list);
+-	schedule_work (&tt->kevent);
++	schedule_work(&tt->clear_work);
+ 	spin_unlock_irqrestore (&tt->lock, flags);
++	return 0;
+ }
+-EXPORT_SYMBOL_GPL(usb_hub_tt_clear_buffer);
++EXPORT_SYMBOL_GPL(usb_hub_clear_tt_buffer);
+ 
+ /* If do_delay is false, return the number of milliseconds the caller
+  * needs to delay.
+@@ -818,7 +830,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
+ 	if (hub->has_indicators)
+ 		cancel_delayed_work_sync(&hub->leds);
+ 	if (hub->tt.hub)
+-		cancel_work_sync(&hub->tt.kevent);
++		cancel_work_sync(&hub->tt.clear_work);
+ }
+ 
+ /* caller has locked the hub device */
+@@ -935,7 +947,7 @@ static int hub_configure(struct usb_hub *hub,
+ 
+ 	spin_lock_init (&hub->tt.lock);
+ 	INIT_LIST_HEAD (&hub->tt.clear_list);
+-	INIT_WORK (&hub->tt.kevent, hub_tt_kevent);
++	INIT_WORK(&hub->tt.clear_work, hub_tt_work);
+ 	switch (hdev->descriptor.bDeviceProtocol) {
+ 		case 0:
+ 			break;
+diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
+index 889c0f32a40b..de8081f065ed 100644
+--- a/drivers/usb/core/hub.h
++++ b/drivers/usb/core/hub.h
+@@ -188,16 +188,18 @@ struct usb_tt {
+ 	/* for control/bulk error recovery (CLEAR_TT_BUFFER) */
+ 	spinlock_t		lock;
+ 	struct list_head	clear_list;	/* of usb_tt_clear */
+-	struct work_struct			kevent;
++	struct work_struct	clear_work;
+ };
+ 
+ struct usb_tt_clear {
+ 	struct list_head	clear_list;
+ 	unsigned		tt;
+ 	u16			devinfo;
++	struct usb_hcd		*hcd;
++	struct usb_host_endpoint	*ep;
+ };
+ 
+-extern void usb_hub_tt_clear_buffer(struct usb_device *dev, int pipe);
++extern int usb_hub_clear_tt_buffer(struct urb *urb);
+ extern void usb_ep0_reinit(struct usb_device *);
+ 
+ #endif /* __LINUX_HUB_H */
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 1976b1b3778c..68bf81e982d2 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -215,7 +215,7 @@ static int qtd_copy_status (
+ 			/* REVISIT ARC-derived cores don't clear the root
+ 			 * hub TT buffer in this way...
+ 			 */
+-			usb_hub_tt_clear_buffer (urb->dev, urb->pipe);
++			usb_hub_clear_tt_buffer(urb);
+ 		}
+ 	}
+ 

commit a455212d19d312f6a99b3a4a86fb79fb91dd76c7
+Author: Alan Stern 
+Date:   Thu Jun 11 14:56:22 2009 -0400
+
+    USB: EHCI: update toggle state for linked QHs
+    
+    This is an update to the "usb-ehci-update-toggle-state-for-linked-qhs"
+    patch.  Since an HCD's endpoint_reset method can be called in
+    interrupt context, it mustn't assume that interrupts are enabled or
+    that it can sleep.
+    
+    So we revert to the original way of refreshing QHs' toggle bits.  Now
+    the endpoint_reset method merely clears the toggle flag in the device
+    structure (as was done before) and starts an async QH unlink.  When the
+    QH is linked again, after the unlink finishes and an URB is queued,
+    the qh_refresh() routine will update the QH's toggle bit.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: David 
+    CC: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 2b72473544d3..99c75603ec87 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1030,12 +1030,14 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
+ 	struct ehci_qh		*qh;
+ 	int			eptype = usb_endpoint_type(&ep->desc);
++	int			epnum = usb_endpoint_num(&ep->desc);
++	int			is_out = usb_endpoint_dir_out(&ep->desc);
++	unsigned long		flags;
+ 
+ 	if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT)
+ 		return;
+ 
+- rescan:
+-	spin_lock_irq(&ehci->lock);
++	spin_lock_irqsave(&ehci->lock, flags);
+ 	qh = ep->hcpriv;
+ 
+ 	/* For Bulk and Interrupt endpoints we maintain the toggle state
+@@ -1044,29 +1046,24 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 	 * the toggle bit in the QH.
+ 	 */
+ 	if (qh) {
++		usb_settoggle(qh->dev, epnum, is_out, 0);
+ 		if (!list_empty(&qh->qtd_list)) {
+ 			WARN_ONCE(1, "clear_halt for a busy endpoint\n");
+-		} else if (qh->qh_state == QH_STATE_IDLE) {
+-			qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
+-		} else {
+-			/* It's not safe to write into the overlay area
+-			 * while the QH is active.  Unlink it first and
+-			 * wait for the unlink to complete.
++		} else if (qh->qh_state == QH_STATE_LINKED) {
++
++			/* The toggle value in the QH can't be updated
++			 * while the QH is active.  Unlink it now;
++			 * re-linking will call qh_refresh().
+ 			 */
+-			if (qh->qh_state == QH_STATE_LINKED) {
+-				if (eptype == USB_ENDPOINT_XFER_BULK) {
+-					unlink_async(ehci, qh);
+-				} else {
+-					intr_deschedule(ehci, qh);
+-					(void) qh_schedule(ehci, qh);
+-				}
++			if (eptype == USB_ENDPOINT_XFER_BULK) {
++				unlink_async(ehci, qh);
++			} else {
++				intr_deschedule(ehci, qh);
++				(void) qh_schedule(ehci, qh);
+ 			}
+-			spin_unlock_irq(&ehci->lock);
+-			schedule_timeout_uninterruptible(1);
+-			goto rescan;
+ 		}
+ 	}
+-	spin_unlock_irq(&ehci->lock);
++	spin_unlock_irqrestore(&ehci->lock, flags);
+ }
+ 
+ static int ehci_get_frame (struct usb_hcd *hcd)
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 3192f683f807..1976b1b3778c 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -93,6 +93,22 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
+ 	qh->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma);
+ 	qh->hw_alt_next = EHCI_LIST_END(ehci);
+ 
++	/* Except for control endpoints, we make hardware maintain data
++	 * toggle (like OHCI) ... here (re)initialize the toggle in the QH,
++	 * and set the pseudo-toggle in udev. Only usb_clear_halt() will
++	 * ever clear it.
++	 */
++	if (!(qh->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) {
++		unsigned	is_out, epnum;
++
++		is_out = !(qtd->hw_token & cpu_to_hc32(ehci, 1 << 8));
++		epnum = (hc32_to_cpup(ehci, &qh->hw_info1) >> 8) & 0x0f;
++		if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) {
++			qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
++			usb_settoggle (qh->dev, epnum, is_out, 1);
++		}
++	}
++
+ 	/* HC must see latest qtd and qh data before we clear ACTIVE+HALT */
+ 	wmb ();
+ 	qh->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING);
+@@ -834,6 +850,7 @@ qh_make (
+ 	qh->qh_state = QH_STATE_IDLE;
+ 	qh->hw_info1 = cpu_to_hc32(ehci, info1);
+ 	qh->hw_info2 = cpu_to_hc32(ehci, info2);
++	usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1);
+ 	qh_refresh (ehci, qh);
+ 	return qh;
+ }
+@@ -864,7 +881,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		}
+ 	}
+ 
+-	/* clear halt and maybe recover from silicon quirk */
++	/* clear halt and/or toggle; and maybe recover from silicon quirk */
+ 	if (qh->qh_state == QH_STATE_IDLE)
+ 		qh_refresh (ehci, qh);
+ 

commit f9c99bb8b3a1ec81af68d484a551307326c2e933
+Author: Alan Stern 
+Date:   Tue Jun 2 11:53:55 2009 -0400
+
+    USB: usb-serial: replace shutdown with disconnect, release
+    
+    This patch (as1254) splits up the shutdown method of usb_serial_driver
+    into a disconnect and a release method.
+    
+    The problem is that the usb-serial core was calling shutdown during
+    disconnect handling, but drivers didn't expect it to be called until
+    after all the open file references had been closed.  The result was an
+    oops when the close method tried to use memory that had been
+    deallocated by shutdown.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/uc2322/aten2011.c b/drivers/staging/uc2322/aten2011.c
+index 9c62f787cc9c..39d0926d1a90 100644
+--- a/drivers/staging/uc2322/aten2011.c
++++ b/drivers/staging/uc2322/aten2011.c
+@@ -2336,7 +2336,7 @@ static int ATEN2011_startup(struct usb_serial *serial)
+ 	return 0;
+ }
+ 
+-static void ATEN2011_shutdown(struct usb_serial *serial)
++static void ATEN2011_release(struct usb_serial *serial)
+ {
+ 	int i;
+ 	struct ATENINTL_port *ATEN2011_port;
+@@ -2382,7 +2382,7 @@ static struct usb_serial_driver aten_serial_driver = {
+ 	.tiocmget =		ATEN2011_tiocmget,
+ 	.tiocmset =		ATEN2011_tiocmset,
+ 	.attach =		ATEN2011_startup,
+-	.shutdown =		ATEN2011_shutdown,
++	.release =		ATEN2011_release,
+ 	.read_bulk_callback =	ATEN2011_bulk_in_callback,
+ 	.read_int_callback =	ATEN2011_interrupt_callback,
+ };
+diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
+index 6d106e74265e..2cbfab3716e5 100644
+--- a/drivers/usb/serial/aircable.c
++++ b/drivers/usb/serial/aircable.c
+@@ -364,7 +364,7 @@ static int aircable_attach(struct usb_serial *serial)
+ 	return 0;
+ }
+ 
+-static void aircable_shutdown(struct usb_serial *serial)
++static void aircable_release(struct usb_serial *serial)
+ {
+ 
+ 	struct usb_serial_port *port = serial->port[0];
+@@ -375,7 +375,6 @@ static void aircable_shutdown(struct usb_serial *serial)
+ 	if (priv) {
+ 		serial_buf_free(priv->tx_buf);
+ 		serial_buf_free(priv->rx_buf);
+-		usb_set_serial_port_data(port, NULL);
+ 		kfree(priv);
+ 	}
+ }
+@@ -601,7 +600,7 @@ static struct usb_serial_driver aircable_device = {
+ 	.num_ports =		1,
+ 	.attach =		aircable_attach,
+ 	.probe =		aircable_probe,
+-	.shutdown =		aircable_shutdown,
++	.release =		aircable_release,
+ 	.write =		aircable_write,
+ 	.write_room =		aircable_write_room,
+ 	.write_bulk_callback =	aircable_write_bulk_callback,
+diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
+index 2bfd6dd85b5a..7033b031b443 100644
+--- a/drivers/usb/serial/belkin_sa.c
++++ b/drivers/usb/serial/belkin_sa.c
+@@ -90,7 +90,7 @@ static int debug;
+ 
+ /* function prototypes for a Belkin USB Serial Adapter F5U103 */
+ static int  belkin_sa_startup(struct usb_serial *serial);
+-static void belkin_sa_shutdown(struct usb_serial *serial);
++static void belkin_sa_release(struct usb_serial *serial);
+ static int  belkin_sa_open(struct tty_struct *tty,
+ 			struct usb_serial_port *port, struct file *filp);
+ static void belkin_sa_close(struct usb_serial_port *port);
+@@ -142,7 +142,7 @@ static struct usb_serial_driver belkin_device = {
+ 	.tiocmget =		belkin_sa_tiocmget,
+ 	.tiocmset =		belkin_sa_tiocmset,
+ 	.attach =		belkin_sa_startup,
+-	.shutdown =		belkin_sa_shutdown,
++	.release =		belkin_sa_release,
+ };
+ 
+ 
+@@ -197,14 +197,13 @@ static int belkin_sa_startup(struct usb_serial *serial)
+ }
+ 
+ 
+-static void belkin_sa_shutdown(struct usb_serial *serial)
++static void belkin_sa_release(struct usb_serial *serial)
+ {
+ 	struct belkin_sa_private *priv;
+ 	int i;
+ 
+ 	dbg("%s", __func__);
+ 
+-	/* stop reads and writes on all ports */
+ 	for (i = 0; i < serial->num_ports; ++i) {
+ 		/* My special items, the standard routines free my urbs */
+ 		priv = usb_get_serial_port_data(serial->port[i]);
+diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
+index 16a154d3b2fe..2b9eeda62bfe 100644
+--- a/drivers/usb/serial/cp210x.c
++++ b/drivers/usb/serial/cp210x.c
+@@ -50,7 +50,7 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port, struct file *,
+ 		unsigned int, unsigned int);
+ static void cp210x_break_ctl(struct tty_struct *, int);
+ static int cp210x_startup(struct usb_serial *);
+-static void cp210x_shutdown(struct usb_serial *);
++static void cp210x_disconnect(struct usb_serial *);
+ 
+ static int debug;
+ 
+@@ -137,7 +137,7 @@ static struct usb_serial_driver cp210x_device = {
+ 	.tiocmget 		= cp210x_tiocmget,
+ 	.tiocmset		= cp210x_tiocmset,
+ 	.attach			= cp210x_startup,
+-	.shutdown		= cp210x_shutdown,
++	.disconnect		= cp210x_disconnect,
+ };
+ 
+ /* Config request types */
+@@ -792,7 +792,7 @@ static int cp210x_startup(struct usb_serial *serial)
+ 	return 0;
+ }
+ 
+-static void cp210x_shutdown(struct usb_serial *serial)
++static void cp210x_disconnect(struct usb_serial *serial)
+ {
+ 	int i;
+ 
+diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
+index 933ba913e66c..336523fd7366 100644
+--- a/drivers/usb/serial/cyberjack.c
++++ b/drivers/usb/serial/cyberjack.c
+@@ -58,7 +58,8 @@ static int debug;
+ 
+ /* Function prototypes */
+ static int cyberjack_startup(struct usb_serial *serial);
+-static void cyberjack_shutdown(struct usb_serial *serial);
++static void cyberjack_disconnect(struct usb_serial *serial);
++static void cyberjack_release(struct usb_serial *serial);
+ static int  cyberjack_open(struct tty_struct *tty,
+ 			struct usb_serial_port *port, struct file *filp);
+ static void cyberjack_close(struct usb_serial_port *port);
+@@ -94,7 +95,8 @@ static struct usb_serial_driver cyberjack_device = {
+ 	.id_table =		id_table,
+ 	.num_ports =		1,
+ 	.attach =		cyberjack_startup,
+-	.shutdown =		cyberjack_shutdown,
++	.disconnect =		cyberjack_disconnect,
++	.release =		cyberjack_release,
+ 	.open =			cyberjack_open,
+ 	.close =		cyberjack_close,
+ 	.write =		cyberjack_write,
+@@ -148,17 +150,25 @@ static int cyberjack_startup(struct usb_serial *serial)
+ 	return 0;
+ }
+ 
+-static void cyberjack_shutdown(struct usb_serial *serial)
++static void cyberjack_disconnect(struct usb_serial *serial)
+ {
+ 	int i;
+ 
+ 	dbg("%s", __func__);
+ 
+-	for (i = 0; i < serial->num_ports; ++i) {
++	for (i = 0; i < serial->num_ports; ++i)
+ 		usb_kill_urb(serial->port[i]->interrupt_in_urb);
++}
++
++static void cyberjack_release(struct usb_serial *serial)
++{
++	int i;
++
++	dbg("%s", __func__);
++
++	for (i = 0; i < serial->num_ports; ++i) {
+ 		/* My special items, the standard routines free my urbs */
+ 		kfree(usb_get_serial_port_data(serial->port[i]));
+-		usb_set_serial_port_data(serial->port[i], NULL);
+ 	}
+ }
+ 
+diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
+index 669f93848539..9734085fd2fe 100644
+--- a/drivers/usb/serial/cypress_m8.c
++++ b/drivers/usb/serial/cypress_m8.c
+@@ -171,7 +171,7 @@ struct cypress_buf {
+ static int  cypress_earthmate_startup(struct usb_serial *serial);
+ static int  cypress_hidcom_startup(struct usb_serial *serial);
+ static int  cypress_ca42v2_startup(struct usb_serial *serial);
+-static void cypress_shutdown(struct usb_serial *serial);
++static void cypress_release(struct usb_serial *serial);
+ static int  cypress_open(struct tty_struct *tty,
+ 			struct usb_serial_port *port, struct file *filp);
+ static void cypress_close(struct usb_serial_port *port);
+@@ -215,7 +215,7 @@ static struct usb_serial_driver cypress_earthmate_device = {
+ 	.id_table =			id_table_earthmate,
+ 	.num_ports =			1,
+ 	.attach =			cypress_earthmate_startup,
+-	.shutdown =			cypress_shutdown,
++	.release =			cypress_release,
+ 	.open =				cypress_open,
+ 	.close =			cypress_close,
+ 	.dtr_rts =			cypress_dtr_rts,
+@@ -242,7 +242,7 @@ static struct usb_serial_driver cypress_hidcom_device = {
+ 	.id_table =			id_table_cyphidcomrs232,
+ 	.num_ports =			1,
+ 	.attach =			cypress_hidcom_startup,
+-	.shutdown =			cypress_shutdown,
++	.release =			cypress_release,
+ 	.open =				cypress_open,
+ 	.close =			cypress_close,
+ 	.dtr_rts =			cypress_dtr_rts,
+@@ -269,7 +269,7 @@ static struct usb_serial_driver cypress_ca42v2_device = {
+ 	.id_table =			id_table_nokiaca42v2,
+ 	.num_ports =			1,
+ 	.attach =			cypress_ca42v2_startup,
+-	.shutdown =			cypress_shutdown,
++	.release =			cypress_release,
+ 	.open =				cypress_open,
+ 	.close =			cypress_close,
+ 	.dtr_rts =			cypress_dtr_rts,
+@@ -616,7 +616,7 @@ static int cypress_ca42v2_startup(struct usb_serial *serial)
+ } /* cypress_ca42v2_startup */
+ 
+ 
+-static void cypress_shutdown(struct usb_serial *serial)
++static void cypress_release(struct usb_serial *serial)
+ {
+ 	struct cypress_private *priv;
+ 
+@@ -629,7 +629,6 @@ static void cypress_shutdown(struct usb_serial *serial)
+ 	if (priv) {
+ 		cypress_buf_free(priv->buf);
+ 		kfree(priv);
+-		usb_set_serial_port_data(serial->port[0], NULL);
+ 	}
+ }
+ 
+diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
+index 30f5140eff03..f4808091c47c 100644
+--- a/drivers/usb/serial/digi_acceleport.c
++++ b/drivers/usb/serial/digi_acceleport.c
+@@ -460,7 +460,8 @@ static int digi_carrier_raised(struct usb_serial_port *port);
+ static void digi_dtr_rts(struct usb_serial_port *port, int on);
+ static int digi_startup_device(struct usb_serial *serial);
+ static int digi_startup(struct usb_serial *serial);
+-static void digi_shutdown(struct usb_serial *serial);
++static void digi_disconnect(struct usb_serial *serial);
++static void digi_release(struct usb_serial *serial);
+ static void digi_read_bulk_callback(struct urb *urb);
+ static int digi_read_inb_callback(struct urb *urb);
+ static int digi_read_oob_callback(struct urb *urb);
+@@ -524,7 +525,8 @@ static struct usb_serial_driver digi_acceleport_2_device = {
+ 	.tiocmget =			digi_tiocmget,
+ 	.tiocmset =			digi_tiocmset,
+ 	.attach =			digi_startup,
+-	.shutdown =			digi_shutdown,
++	.disconnect =			digi_disconnect,
++	.release =			digi_release,
+ };
+ 
+ static struct usb_serial_driver digi_acceleport_4_device = {
+@@ -550,7 +552,8 @@ static struct usb_serial_driver digi_acceleport_4_device = {
+ 	.tiocmget =			digi_tiocmget,
+ 	.tiocmset =			digi_tiocmset,
+ 	.attach =			digi_startup,
+-	.shutdown =			digi_shutdown,
++	.disconnect =			digi_disconnect,
++	.release =			digi_release,
+ };
+ 
+ 
+@@ -1556,16 +1559,23 @@ static int digi_startup(struct usb_serial *serial)
+ }
+ 
+ 
+-static void digi_shutdown(struct usb_serial *serial)
++static void digi_disconnect(struct usb_serial *serial)
+ {
+ 	int i;
+-	dbg("digi_shutdown: TOP, in_interrupt()=%ld", in_interrupt());
++	dbg("digi_disconnect: TOP, in_interrupt()=%ld", in_interrupt());
+ 
+ 	/* stop reads and writes on all ports */
+ 	for (i = 0; i < serial->type->num_ports + 1; i++) {
+ 		usb_kill_urb(serial->port[i]->read_urb);
+ 		usb_kill_urb(serial->port[i]->write_urb);
+ 	}
++}
++
++
++static void digi_release(struct usb_serial *serial)
++{
++	int i;
++	dbg("digi_release: TOP, in_interrupt()=%ld", in_interrupt());
+ 
+ 	/* free the private data structures for all ports */
+ 	/* number of regular ports + 1 for the out-of-band port */
+diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
+index 2b141ccb0cd9..80cb3471adbe 100644
+--- a/drivers/usb/serial/empeg.c
++++ b/drivers/usb/serial/empeg.c
+@@ -90,7 +90,6 @@ static int  empeg_chars_in_buffer(struct tty_struct *tty);
+ static void empeg_throttle(struct tty_struct *tty);
+ static void empeg_unthrottle(struct tty_struct *tty);
+ static int  empeg_startup(struct usb_serial *serial);
+-static void empeg_shutdown(struct usb_serial *serial);
+ static void empeg_set_termios(struct tty_struct *tty,
+ 		struct usb_serial_port *port, struct ktermios *old_termios);
+ static void empeg_write_bulk_callback(struct urb *urb);
+@@ -124,7 +123,6 @@ static struct usb_serial_driver empeg_device = {
+ 	.throttle =		empeg_throttle,
+ 	.unthrottle =		empeg_unthrottle,
+ 	.attach =		empeg_startup,
+-	.shutdown =		empeg_shutdown,
+ 	.set_termios =		empeg_set_termios,
+ 	.write =		empeg_write,
+ 	.write_room =		empeg_write_room,
+@@ -427,12 +425,6 @@ static int  empeg_startup(struct usb_serial *serial)
+ }
+ 
+ 
+-static void empeg_shutdown(struct usb_serial *serial)
+-{
+-	dbg("%s", __func__);
+-}
+-
+-
+ static void empeg_set_termios(struct tty_struct *tty,
+ 		struct usb_serial_port *port, struct ktermios *old_termios)
+ {
+diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
+index fc423583eede..3dc3768ca71c 100644
+--- a/drivers/usb/serial/ftdi_sio.c
++++ b/drivers/usb/serial/ftdi_sio.c
+@@ -720,7 +720,6 @@ static const char *ftdi_chip_name[] = {
+ /* function prototypes for a FTDI serial converter */
+ static int  ftdi_sio_probe(struct usb_serial *serial,
+ 					const struct usb_device_id *id);
+-static void ftdi_shutdown(struct usb_serial *serial);
+ static int  ftdi_sio_port_probe(struct usb_serial_port *port);
+ static int  ftdi_sio_port_remove(struct usb_serial_port *port);
+ static int  ftdi_open(struct tty_struct *tty,
+@@ -779,7 +778,6 @@ static struct usb_serial_driver ftdi_sio_device = {
+ 	.ioctl =		ftdi_ioctl,
+ 	.set_termios =		ftdi_set_termios,
+ 	.break_ctl =		ftdi_break_ctl,
+-	.shutdown =		ftdi_shutdown,
+ };
+ 
+ 
+@@ -1594,18 +1592,6 @@ static int ftdi_mtxorb_hack_setup(struct usb_serial *serial)
+ 	return 0;
+ }
+ 
+-/* ftdi_shutdown is called from usbserial:usb_serial_disconnect
+- *   it is called when the usb device is disconnected
+- *
+- *   usbserial:usb_serial_disconnect
+- *      calls __serial_close for each open of the port
+- *      shutdown is called then (ie ftdi_shutdown)
+- */
+-static void ftdi_shutdown(struct usb_serial *serial)
+-{
+-	dbg("%s", __func__);
+-}
+-
+ static void ftdi_sio_priv_release(struct kref *k)
+ {
+ 	struct ftdi_private *priv = container_of(k, struct ftdi_private, kref);
+diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
+index 5092d6aba659..8839f1c70b7f 100644
+--- a/drivers/usb/serial/garmin_gps.c
++++ b/drivers/usb/serial/garmin_gps.c
+@@ -1475,7 +1475,7 @@ static int garmin_attach(struct usb_serial *serial)
+ }
+ 
+ 
+-static void garmin_shutdown(struct usb_serial *serial)
++static void garmin_disconnect(struct usb_serial *serial)
+ {
+ 	struct usb_serial_port *port = serial->port[0];
+ 	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
+@@ -1484,8 +1484,17 @@ static void garmin_shutdown(struct usb_serial *serial)
+ 
+ 	usb_kill_urb(port->interrupt_in_urb);
+ 	del_timer_sync(&garmin_data_p->timer);
++}
++
++
++static void garmin_release(struct usb_serial *serial)
++{
++	struct usb_serial_port *port = serial->port[0];
++	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
++
++	dbg("%s", __func__);
++
+ 	kfree(garmin_data_p);
+-	usb_set_serial_port_data(port, NULL);
+ }
+ 
+ 
+@@ -1504,7 +1513,8 @@ static struct usb_serial_driver garmin_device = {
+ 	.throttle            = garmin_throttle,
+ 	.unthrottle          = garmin_unthrottle,
+ 	.attach              = garmin_attach,
+-	.shutdown            = garmin_shutdown,
++	.disconnect          = garmin_disconnect,
++	.release             = garmin_release,
+ 	.write               = garmin_write,
+ 	.write_room          = garmin_write_room,
+ 	.write_bulk_callback = garmin_write_bulk_callback,
+diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
+index 8dabac1929b0..932d6241b787 100644
+--- a/drivers/usb/serial/generic.c
++++ b/drivers/usb/serial/generic.c
+@@ -63,7 +63,8 @@ struct usb_serial_driver usb_serial_generic_device = {
+ 	.id_table =		generic_device_ids,
+ 	.usb_driver = 		&generic_driver,
+ 	.num_ports =		1,
+-	.shutdown =		usb_serial_generic_shutdown,
++	.disconnect =		usb_serial_generic_disconnect,
++	.release =		usb_serial_generic_release,
+ 	.throttle =		usb_serial_generic_throttle,
+ 	.unthrottle =		usb_serial_generic_unthrottle,
+ 	.resume =		usb_serial_generic_resume,
+@@ -551,7 +552,7 @@ int usb_serial_handle_break(struct usb_serial_port *port)
+ }
+ EXPORT_SYMBOL_GPL(usb_serial_handle_break);
+ 
+-void usb_serial_generic_shutdown(struct usb_serial *serial)
++void usb_serial_generic_disconnect(struct usb_serial *serial)
+ {
+ 	int i;
+ 
+@@ -562,3 +563,7 @@ void usb_serial_generic_shutdown(struct usb_serial *serial)
+ 		generic_cleanup(serial->port[i]);
+ }
+ 
++void usb_serial_generic_release(struct usb_serial *serial)
++{
++	dbg("%s", __func__);
++}
+diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
+index 53ef5996e33d..0191693625d6 100644
+--- a/drivers/usb/serial/io_edgeport.c
++++ b/drivers/usb/serial/io_edgeport.c
+@@ -224,7 +224,8 @@ static int  edge_tiocmget(struct tty_struct *tty, struct file *file);
+ static int  edge_tiocmset(struct tty_struct *tty, struct file *file,
+ 					unsigned int set, unsigned int clear);
+ static int  edge_startup(struct usb_serial *serial);
+-static void edge_shutdown(struct usb_serial *serial);
++static void edge_disconnect(struct usb_serial *serial);
++static void edge_release(struct usb_serial *serial);
+ 
+ #include "io_tables.h"	/* all of the devices that this driver supports */
+ 
+@@ -3193,21 +3194,16 @@ static int edge_startup(struct usb_serial *serial)
+ 
+ 
+ /****************************************************************************
+- * edge_shutdown
++ * edge_disconnect
+  *	This function is called whenever the device is removed from the usb bus.
+  ****************************************************************************/
+-static void edge_shutdown(struct usb_serial *serial)
++static void edge_disconnect(struct usb_serial *serial)
+ {
+ 	struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
+-	int i;
+ 
+ 	dbg("%s", __func__);
+ 
+ 	/* stop reads and writes on all ports */
+-	for (i = 0; i < serial->num_ports; ++i) {
+-		kfree(usb_get_serial_port_data(serial->port[i]));
+-		usb_set_serial_port_data(serial->port[i],  NULL);
+-	}
+ 	/* free up our endpoint stuff */
+ 	if (edge_serial->is_epic) {
+ 		usb_kill_urb(edge_serial->interrupt_read_urb);
+@@ -3218,9 +3214,24 @@ static void edge_shutdown(struct usb_serial *serial)
+ 		usb_free_urb(edge_serial->read_urb);
+ 		kfree(edge_serial->bulk_in_buffer);
+ 	}
++}
++
++
++/****************************************************************************
++ * edge_release
++ *	This function is called when the device structure is deallocated.
++ ****************************************************************************/
++static void edge_release(struct usb_serial *serial)
++{
++	struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
++	int i;
++
++	dbg("%s", __func__);
++
++	for (i = 0; i < serial->num_ports; ++i)
++		kfree(usb_get_serial_port_data(serial->port[i]));
+ 
+ 	kfree(edge_serial);
+-	usb_set_serial_data(serial, NULL);
+ }
+ 
+ 
+diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
+index 7eb9d67b81b6..9241d3147513 100644
+--- a/drivers/usb/serial/io_tables.h
++++ b/drivers/usb/serial/io_tables.h
+@@ -117,7 +117,8 @@ static struct usb_serial_driver edgeport_2port_device = {
+ 	.throttle		= edge_throttle,
+ 	.unthrottle		= edge_unthrottle,
+ 	.attach			= edge_startup,
+-	.shutdown		= edge_shutdown,
++	.disconnect		= edge_disconnect,
++	.release		= edge_release,
+ 	.ioctl			= edge_ioctl,
+ 	.set_termios		= edge_set_termios,
+ 	.tiocmget		= edge_tiocmget,
+@@ -145,7 +146,8 @@ static struct usb_serial_driver edgeport_4port_device = {
+ 	.throttle		= edge_throttle,
+ 	.unthrottle		= edge_unthrottle,
+ 	.attach			= edge_startup,
+-	.shutdown		= edge_shutdown,
++	.disconnect		= edge_disconnect,
++	.release		= edge_release,
+ 	.ioctl			= edge_ioctl,
+ 	.set_termios		= edge_set_termios,
+ 	.tiocmget		= edge_tiocmget,
+@@ -173,7 +175,8 @@ static struct usb_serial_driver edgeport_8port_device = {
+ 	.throttle		= edge_throttle,
+ 	.unthrottle		= edge_unthrottle,
+ 	.attach			= edge_startup,
+-	.shutdown		= edge_shutdown,
++	.disconnect		= edge_disconnect,
++	.release		= edge_release,
+ 	.ioctl			= edge_ioctl,
+ 	.set_termios		= edge_set_termios,
+ 	.tiocmget		= edge_tiocmget,
+@@ -200,7 +203,8 @@ static struct usb_serial_driver epic_device = {
+ 	.throttle		= edge_throttle,
+ 	.unthrottle		= edge_unthrottle,
+ 	.attach			= edge_startup,
+-	.shutdown		= edge_shutdown,
++	.disconnect		= edge_disconnect,
++	.release		= edge_release,
+ 	.ioctl			= edge_ioctl,
+ 	.set_termios		= edge_set_termios,
+ 	.tiocmget		= edge_tiocmget,
+diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
+index db964db42d3c..e8bc42f92e79 100644
+--- a/drivers/usb/serial/io_ti.c
++++ b/drivers/usb/serial/io_ti.c
+@@ -2663,7 +2663,7 @@ static int edge_startup(struct usb_serial *serial)
+ 	return -ENOMEM;
+ }
+ 
+-static void edge_shutdown(struct usb_serial *serial)
++static void edge_disconnect(struct usb_serial *serial)
+ {
+ 	int i;
+ 	struct edgeport_port *edge_port;
+@@ -2673,12 +2673,22 @@ static void edge_shutdown(struct usb_serial *serial)
+ 	for (i = 0; i < serial->num_ports; ++i) {
+ 		edge_port = usb_get_serial_port_data(serial->port[i]);
+ 		edge_remove_sysfs_attrs(edge_port->port);
++	}
++}
++
++static void edge_release(struct usb_serial *serial)
++{
++	int i;
++	struct edgeport_port *edge_port;
++
++	dbg("%s", __func__);
++
++	for (i = 0; i < serial->num_ports; ++i) {
++		edge_port = usb_get_serial_port_data(serial->port[i]);
+ 		edge_buf_free(edge_port->ep_out_buf);
+ 		kfree(edge_port);
+-		usb_set_serial_port_data(serial->port[i], NULL);
+ 	}
+ 	kfree(usb_get_serial_data(serial));
+-	usb_set_serial_data(serial, NULL);
+ }
+ 
+ 
+@@ -2915,7 +2925,8 @@ static struct usb_serial_driver edgeport_1port_device = {
+ 	.throttle		= edge_throttle,
+ 	.unthrottle		= edge_unthrottle,
+ 	.attach			= edge_startup,
+-	.shutdown		= edge_shutdown,
++	.disconnect		= edge_disconnect,
++	.release		= edge_release,
+ 	.port_probe		= edge_create_sysfs_attrs,
+ 	.ioctl			= edge_ioctl,
+ 	.set_termios		= edge_set_termios,
+@@ -2944,7 +2955,8 @@ static struct usb_serial_driver edgeport_2port_device = {
+ 	.throttle		= edge_throttle,
+ 	.unthrottle		= edge_unthrottle,
+ 	.attach			= edge_startup,
+-	.shutdown		= edge_shutdown,
++	.disconnect		= edge_disconnect,
++	.release		= edge_release,
+ 	.port_probe		= edge_create_sysfs_attrs,
+ 	.ioctl			= edge_ioctl,
+ 	.set_termios		= edge_set_termios,
+diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
+index c610a99fa477..2545d45ce16f 100644
+--- a/drivers/usb/serial/ipaq.c
++++ b/drivers/usb/serial/ipaq.c
+@@ -79,7 +79,6 @@ static int  ipaq_open(struct tty_struct *tty,
+ static void ipaq_close(struct usb_serial_port *port);
+ static int  ipaq_calc_num_ports(struct usb_serial *serial);
+ static int  ipaq_startup(struct usb_serial *serial);
+-static void ipaq_shutdown(struct usb_serial *serial);
+ static int ipaq_write(struct tty_struct *tty, struct usb_serial_port *port,
+ 			const unsigned char *buf, int count);
+ static int ipaq_write_bulk(struct usb_serial_port *port,
+@@ -576,7 +575,6 @@ static struct usb_serial_driver ipaq_device = {
+ 	.close =		ipaq_close,
+ 	.attach =		ipaq_startup,
+ 	.calc_num_ports =	ipaq_calc_num_ports,
+-	.shutdown =		ipaq_shutdown,
+ 	.write =		ipaq_write,
+ 	.write_room =		ipaq_write_room,
+ 	.chars_in_buffer =	ipaq_chars_in_buffer,
+@@ -990,11 +988,6 @@ static int ipaq_startup(struct usb_serial *serial)
+ 	return usb_reset_configuration(serial->dev);
+ }
+ 
+-static void ipaq_shutdown(struct usb_serial *serial)
+-{
+-	dbg("%s", __func__);
+-}
+-
+ static int __init ipaq_init(void)
+ {
+ 	int retval;
+diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
+index 76a3cc327bb9..96873a7a32b0 100644
+--- a/drivers/usb/serial/iuu_phoenix.c
++++ b/drivers/usb/serial/iuu_phoenix.c
+@@ -121,8 +121,8 @@ static int iuu_startup(struct usb_serial *serial)
+ 	return 0;
+ }
+ 
+-/* Shutdown function */
+-static void iuu_shutdown(struct usb_serial *serial)
++/* Release function */
++static void iuu_release(struct usb_serial *serial)
+ {
+ 	struct usb_serial_port *port = serial->port[0];
+ 	struct iuu_private *priv = usb_get_serial_port_data(port);
+@@ -1202,7 +1202,7 @@ static struct usb_serial_driver iuu_device = {
+ 	.tiocmset = iuu_tiocmset,
+ 	.set_termios = iuu_set_termios,
+ 	.attach = iuu_startup,
+-	.shutdown = iuu_shutdown,
++	.release = iuu_release,
+ };
+ 
+ static int __init iuu_init(void)
+diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
+index f1195a98f316..2594b8743d3f 100644
+--- a/drivers/usb/serial/keyspan.c
++++ b/drivers/usb/serial/keyspan.c
+@@ -2689,7 +2689,7 @@ static int keyspan_startup(struct usb_serial *serial)
+ 	return 0;
+ }
+ 
+-static void keyspan_shutdown(struct usb_serial *serial)
++static void keyspan_disconnect(struct usb_serial *serial)
+ {
+ 	int				i, j;
+ 	struct usb_serial_port		*port;
+@@ -2729,6 +2729,17 @@ static void keyspan_shutdown(struct usb_serial *serial)
+ 			usb_free_urb(p_priv->out_urbs[j]);
+ 		}
+ 	}
++}
++
++static void keyspan_release(struct usb_serial *serial)
++{
++	int				i;
++	struct usb_serial_port		*port;
++	struct keyspan_serial_private 	*s_priv;
++
++	dbg("%s", __func__);
++
++	s_priv = usb_get_serial_data(serial);
+ 
+ 	/*  dbg("Freeing serial->private."); */
+ 	kfree(s_priv);
+diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
+index 0d4569b60768..3107ed15af64 100644
+--- a/drivers/usb/serial/keyspan.h
++++ b/drivers/usb/serial/keyspan.h
+@@ -41,7 +41,8 @@ static int  keyspan_open		(struct tty_struct *tty,
+ static void keyspan_close		(struct usb_serial_port *port);
+ static void keyspan_dtr_rts		(struct usb_serial_port *port, int on);
+ static int  keyspan_startup		(struct usb_serial *serial);
+-static void keyspan_shutdown		(struct usb_serial *serial);
++static void keyspan_disconnect		(struct usb_serial *serial);
++static void keyspan_release		(struct usb_serial *serial);
+ static int  keyspan_write_room		(struct tty_struct *tty);
+ 
+ static int  keyspan_write		(struct tty_struct *tty,
+@@ -569,7 +570,8 @@ static struct usb_serial_driver keyspan_1port_device = {
+ 	.tiocmget		= keyspan_tiocmget,
+ 	.tiocmset		= keyspan_tiocmset,
+ 	.attach			= keyspan_startup,
+-	.shutdown		= keyspan_shutdown,
++	.disconnect		= keyspan_disconnect,
++	.release		= keyspan_release,
+ };
+ 
+ static struct usb_serial_driver keyspan_2port_device = {
+@@ -590,7 +592,8 @@ static struct usb_serial_driver keyspan_2port_device = {
+ 	.tiocmget		= keyspan_tiocmget,
+ 	.tiocmset		= keyspan_tiocmset,
+ 	.attach			= keyspan_startup,
+-	.shutdown		= keyspan_shutdown,
++	.disconnect		= keyspan_disconnect,
++	.release		= keyspan_release,
+ };
+ 
+ static struct usb_serial_driver keyspan_4port_device = {
+@@ -611,7 +614,8 @@ static struct usb_serial_driver keyspan_4port_device = {
+ 	.tiocmget		= keyspan_tiocmget,
+ 	.tiocmset		= keyspan_tiocmset,
+ 	.attach			= keyspan_startup,
+-	.shutdown		= keyspan_shutdown,
++	.disconnect		= keyspan_disconnect,
++	.release		= keyspan_release,
+ };
+ 
+ #endif
+diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
+index ab769dbea1b3..d0b12e40c2b1 100644
+--- a/drivers/usb/serial/keyspan_pda.c
++++ b/drivers/usb/serial/keyspan_pda.c
+@@ -809,7 +809,7 @@ static int keyspan_pda_startup(struct usb_serial *serial)
+ 	return 0;
+ }
+ 
+-static void keyspan_pda_shutdown(struct usb_serial *serial)
++static void keyspan_pda_release(struct usb_serial *serial)
+ {
+ 	dbg("%s", __func__);
+ 
+@@ -869,7 +869,7 @@ static struct usb_serial_driver keyspan_pda_device = {
+ 	.tiocmget =		keyspan_pda_tiocmget,
+ 	.tiocmset =		keyspan_pda_tiocmset,
+ 	.attach =		keyspan_pda_startup,
+-	.shutdown =		keyspan_pda_shutdown,
++	.release =		keyspan_pda_release,
+ };
+ 
+ 
+diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
+index fa817c66b3e8..0f44bb8e8d4f 100644
+--- a/drivers/usb/serial/kl5kusb105.c
++++ b/drivers/usb/serial/kl5kusb105.c
+@@ -73,7 +73,8 @@ static int debug;
+  * Function prototypes
+  */
+ static int  klsi_105_startup(struct usb_serial *serial);
+-static void klsi_105_shutdown(struct usb_serial *serial);
++static void klsi_105_disconnect(struct usb_serial *serial);
++static void klsi_105_release(struct usb_serial *serial);
+ static int  klsi_105_open(struct tty_struct *tty,
+ 			struct usb_serial_port *port, struct file *filp);
+ static void klsi_105_close(struct usb_serial_port *port);
+@@ -131,7 +132,8 @@ static struct usb_serial_driver kl5kusb105d_device = {
+ 	.tiocmget =          klsi_105_tiocmget,
+ 	.tiocmset =          klsi_105_tiocmset,
+ 	.attach =	     klsi_105_startup,
+-	.shutdown =	     klsi_105_shutdown,
++	.disconnect =	     klsi_105_disconnect,
++	.release =	     klsi_105_release,
+ 	.throttle =	     klsi_105_throttle,
+ 	.unthrottle =	     klsi_105_unthrottle,
+ };
+@@ -315,7 +317,7 @@ static int klsi_105_startup(struct usb_serial *serial)
+ } /* klsi_105_startup */
+ 
+ 
+-static void klsi_105_shutdown(struct usb_serial *serial)
++static void klsi_105_disconnect(struct usb_serial *serial)
+ {
+ 	int i;
+ 
+@@ -325,33 +327,36 @@ static void klsi_105_shutdown(struct usb_serial *serial)
+ 	for (i = 0; i < serial->num_ports; ++i) {
+ 		struct klsi_105_private *priv =
+ 				usb_get_serial_port_data(serial->port[i]);
+-		unsigned long flags;
+ 
+ 		if (priv) {
+ 			/* kill our write urb pool */
+ 			int j;
+ 			struct urb **write_urbs = priv->write_urb_pool;
+-			spin_lock_irqsave(&priv->lock, flags);
+ 
+ 			for (j = 0; j < NUM_URBS; j++) {
+ 				if (write_urbs[j]) {
+-					/* FIXME - uncomment the following
+-					 * usb_kill_urb call when the host
+-					 * controllers get fixed to set
+-					 * urb->dev = NULL after the urb is
+-					 * finished.  Otherwise this call
+-					 * oopses. */
+-					/* usb_kill_urb(write_urbs[j]); */
+-					kfree(write_urbs[j]->transfer_buffer);
++					usb_kill_urb(write_urbs[j]);
+ 					usb_free_urb(write_urbs[j]);
+ 				}
+ 			}
+-			spin_unlock_irqrestore(&priv->lock, flags);
+-			kfree(priv);
+-			usb_set_serial_port_data(serial->port[i], NULL);
+ 		}
+ 	}
+-} /* klsi_105_shutdown */
++} /* klsi_105_disconnect */
++
++
++static void klsi_105_release(struct usb_serial *serial)
++{
++	int i;
++
++	dbg("%s", __func__);
++
++	for (i = 0; i < serial->num_ports; ++i) {
++		struct klsi_105_private *priv =
++				usb_get_serial_port_data(serial->port[i]);
++
++		kfree(priv);
++	}
++} /* klsi_105_release */
+ 
+ static int  klsi_105_open(struct tty_struct *tty,
+ 			struct usb_serial_port *port, struct file *filp)
+diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
+index 6b570498287f..6db0e561f680 100644
+--- a/drivers/usb/serial/kobil_sct.c
++++ b/drivers/usb/serial/kobil_sct.c
+@@ -69,7 +69,7 @@ static int debug;
+ 
+ /* Function prototypes */
+ static int  kobil_startup(struct usb_serial *serial);
+-static void kobil_shutdown(struct usb_serial *serial);
++static void kobil_release(struct usb_serial *serial);
+ static int  kobil_open(struct tty_struct *tty,
+ 			struct usb_serial_port *port, struct file *filp);
+ static void kobil_close(struct usb_serial_port *port);
+@@ -117,7 +117,7 @@ static struct usb_serial_driver kobil_device = {
+ 	.id_table =		id_table,
+ 	.num_ports =		1,
+ 	.attach =		kobil_startup,
+-	.shutdown =		kobil_shutdown,
++	.release =		kobil_release,
+ 	.ioctl =		kobil_ioctl,
+ 	.set_termios =		kobil_set_termios,
+ 	.tiocmget =		kobil_tiocmget,
+@@ -201,17 +201,13 @@ static int kobil_startup(struct usb_serial *serial)
+ }
+ 
+ 
+-static void kobil_shutdown(struct usb_serial *serial)
++static void kobil_release(struct usb_serial *serial)
+ {
+ 	int i;
+ 	dbg("%s - port %d", __func__, serial->port[0]->number);
+ 
+-	for (i = 0; i < serial->num_ports; ++i) {
+-		while (serial->port[i]->port.count > 0)
+-			kobil_close(serial->port[i]);
++	for (i = 0; i < serial->num_ports; ++i)
+ 		kfree(usb_get_serial_port_data(serial->port[i]));
+-		usb_set_serial_port_data(serial->port[i], NULL);
+-	}
+ }
+ 
+ 
+diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
+index 873795548fc0..d8825e159aa5 100644
+--- a/drivers/usb/serial/mct_u232.c
++++ b/drivers/usb/serial/mct_u232.c
+@@ -92,7 +92,7 @@ static int debug;
+  * Function prototypes
+  */
+ static int  mct_u232_startup(struct usb_serial *serial);
+-static void mct_u232_shutdown(struct usb_serial *serial);
++static void mct_u232_release(struct usb_serial *serial);
+ static int  mct_u232_open(struct tty_struct *tty,
+ 			struct usb_serial_port *port, struct file *filp);
+ static void mct_u232_close(struct usb_serial_port *port);
+@@ -149,7 +149,7 @@ static struct usb_serial_driver mct_u232_device = {
+ 	.tiocmget =	     mct_u232_tiocmget,
+ 	.tiocmset =	     mct_u232_tiocmset,
+ 	.attach =	     mct_u232_startup,
+-	.shutdown =	     mct_u232_shutdown,
++	.release =	     mct_u232_release,
+ };
+ 
+ 
+@@ -407,7 +407,7 @@ static int mct_u232_startup(struct usb_serial *serial)
+ } /* mct_u232_startup */
+ 
+ 
+-static void mct_u232_shutdown(struct usb_serial *serial)
++static void mct_u232_release(struct usb_serial *serial)
+ {
+ 	struct mct_u232_private *priv;
+ 	int i;
+@@ -417,12 +417,9 @@ static void mct_u232_shutdown(struct usb_serial *serial)
+ 	for (i = 0; i < serial->num_ports; ++i) {
+ 		/* My special items, the standard routines free my urbs */
+ 		priv = usb_get_serial_port_data(serial->port[i]);
+-		if (priv) {
+-			usb_set_serial_port_data(serial->port[i], NULL);
+-			kfree(priv);
+-		}
++		kfree(priv);
+ 	}
+-} /* mct_u232_shutdown */
++} /* mct_u232_release */
+ 
+ static int  mct_u232_open(struct tty_struct *tty,
+ 			struct usb_serial_port *port, struct file *filp)
+diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
+index 9e1a013ee7f6..bfc5ce000ef9 100644
+--- a/drivers/usb/serial/mos7720.c
++++ b/drivers/usb/serial/mos7720.c
+@@ -1521,19 +1521,16 @@ static int mos7720_startup(struct usb_serial *serial)
+ 	return 0;
+ }
+ 
+-static void mos7720_shutdown(struct usb_serial *serial)
++static void mos7720_release(struct usb_serial *serial)
+ {
+ 	int i;
+ 
+ 	/* free private structure allocated for serial port */
+-	for (i = 0; i < serial->num_ports; ++i) {
++	for (i = 0; i < serial->num_ports; ++i)
+ 		kfree(usb_get_serial_port_data(serial->port[i]));
+-		usb_set_serial_port_data(serial->port[i], NULL);
+-	}
+ 
+ 	/* free private structure allocated for serial device */
+ 	kfree(usb_get_serial_data(serial));
+-	usb_set_serial_data(serial, NULL);
+ }
+ 
+ static struct usb_driver usb_driver = {
+@@ -1558,7 +1555,7 @@ static struct usb_serial_driver moschip7720_2port_driver = {
+ 	.throttle		= mos7720_throttle,
+ 	.unthrottle		= mos7720_unthrottle,
+ 	.attach			= mos7720_startup,
+-	.shutdown		= mos7720_shutdown,
++	.release		= mos7720_release,
+ 	.ioctl			= mos7720_ioctl,
+ 	.set_termios		= mos7720_set_termios,
+ 	.write			= mos7720_write,
+diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
+index 5fe9fe3df772..c40f95c1951c 100644
+--- a/drivers/usb/serial/mos7840.c
++++ b/drivers/usb/serial/mos7840.c
+@@ -2633,16 +2633,16 @@ static int mos7840_startup(struct usb_serial *serial)
+ }
+ 
+ /****************************************************************************
+- * mos7840_shutdown
++ * mos7840_disconnect
+  *	This function is called whenever the device is removed from the usb bus.
+  ****************************************************************************/
+ 
+-static void mos7840_shutdown(struct usb_serial *serial)
++static void mos7840_disconnect(struct usb_serial *serial)
+ {
+ 	int i;
+ 	unsigned long flags;
+ 	struct moschip_port *mos7840_port;
+-	dbg("%s", " shutdown :entering..........");
++	dbg("%s", " disconnect :entering..........");
+ 
+ 	if (!serial) {
+ 		dbg("%s", "Invalid Handler");
+@@ -2662,11 +2662,42 @@ static void mos7840_shutdown(struct usb_serial *serial)
+ 			mos7840_port->zombie = 1;
+ 			spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
+ 			usb_kill_urb(mos7840_port->control_urb);
++		}
++	}
++
++	dbg("%s", "Thank u :: ");
++
++}
++
++/****************************************************************************
++ * mos7840_release
++ *	This function is called when the usb_serial structure is freed.
++ ****************************************************************************/
++
++static void mos7840_release(struct usb_serial *serial)
++{
++	int i;
++	struct moschip_port *mos7840_port;
++	dbg("%s", " release :entering..........");
++
++	if (!serial) {
++		dbg("%s", "Invalid Handler");
++		return;
++	}
++
++	/* check for the ports to be closed,close the ports and disconnect */
++
++	/* free private structure allocated for serial port  *
++	 * stop reads and writes on all ports                */
++
++	for (i = 0; i < serial->num_ports; ++i) {
++		mos7840_port = mos7840_get_port_private(serial->port[i]);
++		dbg("mos7840_port %d = %p", i, mos7840_port);
++		if (mos7840_port) {
+ 			kfree(mos7840_port->ctrl_buf);
+ 			kfree(mos7840_port->dr);
+ 			kfree(mos7840_port);
+ 		}
+-		mos7840_set_port_private(serial->port[i], NULL);
+ 	}
+ 
+ 	dbg("%s", "Thank u :: ");
+@@ -2707,7 +2738,8 @@ static struct usb_serial_driver moschip7840_4port_device = {
+ 	.tiocmget = mos7840_tiocmget,
+ 	.tiocmset = mos7840_tiocmset,
+ 	.attach = mos7840_startup,
+-	.shutdown = mos7840_shutdown,
++	.disconnect = mos7840_disconnect,
++	.release = mos7840_release,
+ 	.read_bulk_callback = mos7840_bulk_in_callback,
+ 	.read_int_callback = mos7840_interrupt_callback,
+ };
+diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
+index 1104617334f5..56857ddbd70b 100644
+--- a/drivers/usb/serial/omninet.c
++++ b/drivers/usb/serial/omninet.c
+@@ -72,7 +72,8 @@ static void omninet_write_bulk_callback(struct urb *urb);
+ static int  omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
+ 				const unsigned char *buf, int count);
+ static int  omninet_write_room(struct tty_struct *tty);
+-static void omninet_shutdown(struct usb_serial *serial);
++static void omninet_disconnect(struct usb_serial *serial);
++static void omninet_release(struct usb_serial *serial);
+ static int omninet_attach(struct usb_serial *serial);
+ 
+ static struct usb_device_id id_table[] = {
+@@ -108,7 +109,8 @@ static struct usb_serial_driver zyxel_omninet_device = {
+ 	.write_room =		omninet_write_room,
+ 	.read_bulk_callback =	omninet_read_bulk_callback,
+ 	.write_bulk_callback =	omninet_write_bulk_callback,
+-	.shutdown =		omninet_shutdown,
++	.disconnect =		omninet_disconnect,
++	.release =		omninet_release,
+ };
+ 
+ 
+@@ -345,13 +347,22 @@ static void omninet_write_bulk_callback(struct urb *urb)
+ }
+ 
+ 
+-static void omninet_shutdown(struct usb_serial *serial)
++static void omninet_disconnect(struct usb_serial *serial)
+ {
+ 	struct usb_serial_port *wport = serial->port[1];
+-	struct usb_serial_port *port = serial->port[0];
++
+ 	dbg("%s", __func__);
+ 
+ 	usb_kill_urb(wport->write_urb);
++}
++
++
++static void omninet_release(struct usb_serial *serial)
++{
++	struct usb_serial_port *port = serial->port[0];
++
++	dbg("%s", __func__);
++
+ 	kfree(usb_get_serial_port_data(port));
+ }
+ 
+diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c
+index c20480aa9755..336bba79ad32 100644
+--- a/drivers/usb/serial/opticon.c
++++ b/drivers/usb/serial/opticon.c
+@@ -463,7 +463,7 @@ static int opticon_startup(struct usb_serial *serial)
+ 	return retval;
+ }
+ 
+-static void opticon_shutdown(struct usb_serial *serial)
++static void opticon_disconnect(struct usb_serial *serial)
+ {
+ 	struct opticon_private *priv = usb_get_serial_data(serial);
+ 
+@@ -471,9 +471,16 @@ static void opticon_shutdown(struct usb_serial *serial)
+ 
+ 	usb_kill_urb(priv->bulk_read_urb);
+ 	usb_free_urb(priv->bulk_read_urb);
++}
++
++static void opticon_release(struct usb_serial *serial)
++{
++	struct opticon_private *priv = usb_get_serial_data(serial);
++
++	dbg("%s", __func__);
++
+ 	kfree(priv->bulk_in_buffer);
+ 	kfree(priv);
+-	usb_set_serial_data(serial, NULL);
+ }
+ 
+ static int opticon_suspend(struct usb_interface *intf, pm_message_t message)
+@@ -524,7 +531,8 @@ static struct usb_serial_driver opticon_device = {
+ 	.close =		opticon_close,
+ 	.write =		opticon_write,
+ 	.write_room = 		opticon_write_room,
+-	.shutdown =		opticon_shutdown,
++	.disconnect =		opticon_disconnect,
++	.release =		opticon_release,
+ 	.throttle = 		opticon_throttle,
+ 	.unthrottle =		opticon_unthrottle,
+ 	.ioctl =		opticon_ioctl,
+diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
+index a38971cc3731..575816e6ba37 100644
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -51,7 +51,8 @@ static void option_close(struct usb_serial_port *port);
+ static void option_dtr_rts(struct usb_serial_port *port, int on);
+ 
+ static int  option_startup(struct usb_serial *serial);
+-static void option_shutdown(struct usb_serial *serial);
++static void option_disconnect(struct usb_serial *serial);
++static void option_release(struct usb_serial *serial);
+ static int  option_write_room(struct tty_struct *tty);
+ 
+ static void option_instat_callback(struct urb *urb);
+@@ -568,7 +569,8 @@ static struct usb_serial_driver option_1port_device = {
+ 	.tiocmget          = option_tiocmget,
+ 	.tiocmset          = option_tiocmset,
+ 	.attach            = option_startup,
+-	.shutdown          = option_shutdown,
++	.disconnect        = option_disconnect,
++	.release           = option_release,
+ 	.read_int_callback = option_instat_callback,
+ 	.suspend           = option_suspend,
+ 	.resume            = option_resume,
+@@ -1149,7 +1151,14 @@ static void stop_read_write_urbs(struct usb_serial *serial)
+ 	}
+ }
+ 
+-static void option_shutdown(struct usb_serial *serial)
++static void option_disconnect(struct usb_serial *serial)
++{
++	dbg("%s", __func__);
++
++	stop_read_write_urbs(serial);
++}
++
++static void option_release(struct usb_serial *serial)
+ {
+ 	int i, j;
+ 	struct usb_serial_port *port;
+@@ -1157,8 +1166,6 @@ static void option_shutdown(struct usb_serial *serial)
+ 
+ 	dbg("%s", __func__);
+ 
+-	stop_read_write_urbs(serial);
+-
+ 	/* Now free them */
+ 	for (i = 0; i < serial->num_ports; ++i) {
+ 		port = serial->port[i];
+diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
+index 7de54781fe61..3cece27325e7 100644
+--- a/drivers/usb/serial/oti6858.c
++++ b/drivers/usb/serial/oti6858.c
+@@ -159,7 +159,7 @@ static int oti6858_tiocmget(struct tty_struct *tty, struct file *file);
+ static int oti6858_tiocmset(struct tty_struct *tty, struct file *file,
+ 				unsigned int set, unsigned int clear);
+ static int oti6858_startup(struct usb_serial *serial);
+-static void oti6858_shutdown(struct usb_serial *serial);
++static void oti6858_release(struct usb_serial *serial);
+ 
+ /* functions operating on buffers */
+ static struct oti6858_buf *oti6858_buf_alloc(unsigned int size);
+@@ -194,7 +194,7 @@ static struct usb_serial_driver oti6858_device = {
+ 	.write_room =		oti6858_write_room,
+ 	.chars_in_buffer =	oti6858_chars_in_buffer,
+ 	.attach =		oti6858_startup,
+-	.shutdown =		oti6858_shutdown,
++	.release =		oti6858_release,
+ };
+ 
+ struct oti6858_private {
+@@ -782,7 +782,7 @@ static int oti6858_ioctl(struct tty_struct *tty, struct file *file,
+ }
+ 
+ 
+-static void oti6858_shutdown(struct usb_serial *serial)
++static void oti6858_release(struct usb_serial *serial)
+ {
+ 	struct oti6858_private *priv;
+ 	int i;
+@@ -794,7 +794,6 @@ static void oti6858_shutdown(struct usb_serial *serial)
+ 		if (priv) {
+ 			oti6858_buf_free(priv->buf);
+ 			kfree(priv);
+-			usb_set_serial_port_data(serial->port[i], NULL);
+ 		}
+ 	}
+ }
+diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
+index 6357b57f628c..ec6c132a25b5 100644
+--- a/drivers/usb/serial/pl2303.c
++++ b/drivers/usb/serial/pl2303.c
+@@ -878,7 +878,7 @@ static void pl2303_break_ctl(struct tty_struct *tty, int break_state)
+ 		dbg("%s - error sending break = %d", __func__, result);
+ }
+ 
+-static void pl2303_shutdown(struct usb_serial *serial)
++static void pl2303_release(struct usb_serial *serial)
+ {
+ 	int i;
+ 	struct pl2303_private *priv;
+@@ -890,7 +890,6 @@ static void pl2303_shutdown(struct usb_serial *serial)
+ 		if (priv) {
+ 			pl2303_buf_free(priv->buf);
+ 			kfree(priv);
+-			usb_set_serial_port_data(serial->port[i], NULL);
+ 		}
+ 	}
+ }
+@@ -1123,7 +1122,7 @@ static struct usb_serial_driver pl2303_device = {
+ 	.write_room =		pl2303_write_room,
+ 	.chars_in_buffer =	pl2303_chars_in_buffer,
+ 	.attach =		pl2303_startup,
+-	.shutdown =		pl2303_shutdown,
++	.release =		pl2303_release,
+ };
+ 
+ static int __init pl2303_init(void)
+diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
+index a88cde950161..032f7aeb40a4 100644
+--- a/drivers/usb/serial/sierra.c
++++ b/drivers/usb/serial/sierra.c
+@@ -814,7 +814,7 @@ static int sierra_startup(struct usb_serial *serial)
+ 	return 0;
+ }
+ 
+-static void sierra_shutdown(struct usb_serial *serial)
++static void sierra_disconnect(struct usb_serial *serial)
+ {
+ 	int i;
+ 	struct usb_serial_port *port;
+@@ -853,7 +853,7 @@ static struct usb_serial_driver sierra_device = {
+ 	.tiocmget          = sierra_tiocmget,
+ 	.tiocmset          = sierra_tiocmset,
+ 	.attach            = sierra_startup,
+-	.shutdown          = sierra_shutdown,
++	.disconnect        = sierra_disconnect,
+ 	.read_int_callback = sierra_instat_callback,
+ };
+ 
+diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
+index 8f7ed8f13996..3c249d8e8b8e 100644
+--- a/drivers/usb/serial/spcp8x5.c
++++ b/drivers/usb/serial/spcp8x5.c
+@@ -356,7 +356,7 @@ static int spcp8x5_startup(struct usb_serial *serial)
+ }
+ 
+ /* call when the device plug out. free all the memory alloced by probe */
+-static void spcp8x5_shutdown(struct usb_serial *serial)
++static void spcp8x5_release(struct usb_serial *serial)
+ {
+ 	int i;
+ 	struct spcp8x5_private *priv;
+@@ -366,7 +366,6 @@ static void spcp8x5_shutdown(struct usb_serial *serial)
+ 		if (priv) {
+ 			free_ringbuf(priv->buf);
+ 			kfree(priv);
+-			usb_set_serial_port_data(serial->port[i] , NULL);
+ 		}
+ 	}
+ }
+@@ -1020,7 +1019,7 @@ static struct usb_serial_driver spcp8x5_device = {
+ 	.write_bulk_callback	= spcp8x5_write_bulk_callback,
+ 	.chars_in_buffer 	= spcp8x5_chars_in_buffer,
+ 	.attach 		= spcp8x5_startup,
+-	.shutdown 		= spcp8x5_shutdown,
++	.release 		= spcp8x5_release,
+ };
+ 
+ static int __init spcp8x5_init(void)
+diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c
+index 8b07ebc6baeb..6157fac9366b 100644
+--- a/drivers/usb/serial/symbolserial.c
++++ b/drivers/usb/serial/symbolserial.c
+@@ -267,7 +267,7 @@ static int symbol_startup(struct usb_serial *serial)
+ 	return retval;
+ }
+ 
+-static void symbol_shutdown(struct usb_serial *serial)
++static void symbol_disconnect(struct usb_serial *serial)
+ {
+ 	struct symbol_private *priv = usb_get_serial_data(serial);
+ 
+@@ -275,9 +275,16 @@ static void symbol_shutdown(struct usb_serial *serial)
+ 
+ 	usb_kill_urb(priv->int_urb);
+ 	usb_free_urb(priv->int_urb);
++}
++
++static void symbol_release(struct usb_serial *serial)
++{
++	struct symbol_private *priv = usb_get_serial_data(serial);
++
++	dbg("%s", __func__);
++
+ 	kfree(priv->int_buffer);
+ 	kfree(priv);
+-	usb_set_serial_data(serial, NULL);
+ }
+ 
+ static struct usb_driver symbol_driver = {
+@@ -299,7 +306,8 @@ static struct usb_serial_driver symbol_device = {
+ 	.attach =		symbol_startup,
+ 	.open =			symbol_open,
+ 	.close =		symbol_close,
+-	.shutdown =		symbol_shutdown,
++	.disconnect =		symbol_disconnect,
++	.release =		symbol_release,
+ 	.throttle = 		symbol_throttle,
+ 	.unthrottle =		symbol_unthrottle,
+ };
+diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
+index 42cb04c403be..991d8232e376 100644
+--- a/drivers/usb/serial/ti_usb_3410_5052.c
++++ b/drivers/usb/serial/ti_usb_3410_5052.c
+@@ -97,7 +97,7 @@ struct ti_device {
+ /* Function Declarations */
+ 
+ static int ti_startup(struct usb_serial *serial);
+-static void ti_shutdown(struct usb_serial *serial);
++static void ti_release(struct usb_serial *serial);
+ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port,
+ 		struct file *file);
+ static void ti_close(struct usb_serial_port *port);
+@@ -230,7 +230,7 @@ static struct usb_serial_driver ti_1port_device = {
+ 	.id_table		= ti_id_table_3410,
+ 	.num_ports		= 1,
+ 	.attach			= ti_startup,
+-	.shutdown		= ti_shutdown,
++	.release		= ti_release,
+ 	.open			= ti_open,
+ 	.close			= ti_close,
+ 	.write			= ti_write,
+@@ -258,7 +258,7 @@ static struct usb_serial_driver ti_2port_device = {
+ 	.id_table		= ti_id_table_5052,
+ 	.num_ports		= 2,
+ 	.attach			= ti_startup,
+-	.shutdown		= ti_shutdown,
++	.release		= ti_release,
+ 	.open			= ti_open,
+ 	.close			= ti_close,
+ 	.write			= ti_write,
+@@ -473,7 +473,7 @@ static int ti_startup(struct usb_serial *serial)
+ }
+ 
+ 
+-static void ti_shutdown(struct usb_serial *serial)
++static void ti_release(struct usb_serial *serial)
+ {
+ 	int i;
+ 	struct ti_device *tdev = usb_get_serial_data(serial);
+@@ -486,12 +486,10 @@ static void ti_shutdown(struct usb_serial *serial)
+ 		if (tport) {
+ 			ti_buf_free(tport->tp_write_buf);
+ 			kfree(tport);
+-			usb_set_serial_port_data(serial->port[i], NULL);
+ 		}
+ 	}
+ 
+ 	kfree(tdev);
+-	usb_set_serial_data(serial, NULL);
+ }
+ 
+ 
+diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
+index da890f030fac..d595aa5586a7 100644
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -141,6 +141,14 @@ static void destroy_serial(struct kref *kref)
+ 	if (serial->minor != SERIAL_TTY_NO_MINOR)
+ 		return_serial(serial);
+ 
++	serial->type->release(serial);
++
++	for (i = 0; i < serial->num_ports; ++i) {
++		port = serial->port[i];
++		if (port)
++			put_device(&port->dev);
++	}
++
+ 	/* If this is a "fake" port, we have to clean it up here, as it will
+ 	 * not get cleaned up in port_release() as it was never registered with
+ 	 * the driver core */
+@@ -148,9 +156,8 @@ static void destroy_serial(struct kref *kref)
+ 		for (i = serial->num_ports;
+ 					i < serial->num_port_pointers; ++i) {
+ 			port = serial->port[i];
+-			if (!port)
+-				continue;
+-			port_free(port);
++			if (port)
++				port_free(port);
+ 		}
+ 	}
+ 
+@@ -1118,10 +1125,6 @@ void usb_serial_disconnect(struct usb_interface *interface)
+ 	serial->disconnected = 1;
+ 	mutex_unlock(&serial->disc_mutex);
+ 
+-	/* Unfortunately, many of the sub-drivers expect the port structures
+-	 * to exist when their shutdown method is called, so we have to go
+-	 * through this awkward two-step unregistration procedure.
+-	 */
+ 	for (i = 0; i < serial->num_ports; ++i) {
+ 		port = serial->port[i];
+ 		if (port) {
+@@ -1153,14 +1156,7 @@ void usb_serial_disconnect(struct usb_interface *interface)
+ 			}
+ 		}
+ 	}
+-	serial->type->shutdown(serial);
+-	for (i = 0; i < serial->num_ports; ++i) {
+-		port = serial->port[i];
+-		if (port) {
+-			put_device(&port->dev);
+-			serial->port[i] = NULL;
+-		}
+-	}
++	serial->type->disconnect(serial);
+ 
+ 	/* let the last holder of this object
+ 	 * cause it to be cleaned up */
+@@ -1338,7 +1334,8 @@ static void fixup_generic(struct usb_serial_driver *device)
+ 	set_to_generic_if_null(device, chars_in_buffer);
+ 	set_to_generic_if_null(device, read_bulk_callback);
+ 	set_to_generic_if_null(device, write_bulk_callback);
+-	set_to_generic_if_null(device, shutdown);
++	set_to_generic_if_null(device, disconnect);
++	set_to_generic_if_null(device, release);
+ }
+ 
+ int usb_serial_register(struct usb_serial_driver *driver)
+diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
+index b15f1c0e1d4a..f5d0f64dcc52 100644
+--- a/drivers/usb/serial/visor.c
++++ b/drivers/usb/serial/visor.c
+@@ -47,7 +47,7 @@ static void visor_unthrottle(struct tty_struct *tty);
+ static int  visor_probe(struct usb_serial *serial,
+ 					const struct usb_device_id *id);
+ static int  visor_calc_num_ports(struct usb_serial *serial);
+-static void visor_shutdown(struct usb_serial *serial);
++static void visor_release(struct usb_serial *serial);
+ static void visor_write_bulk_callback(struct urb *urb);
+ static void visor_read_bulk_callback(struct urb *urb);
+ static void visor_read_int_callback(struct urb *urb);
+@@ -202,7 +202,7 @@ static struct usb_serial_driver handspring_device = {
+ 	.attach =		treo_attach,
+ 	.probe =		visor_probe,
+ 	.calc_num_ports =	visor_calc_num_ports,
+-	.shutdown =		visor_shutdown,
++	.release =		visor_release,
+ 	.write =		visor_write,
+ 	.write_room =		visor_write_room,
+ 	.write_bulk_callback =	visor_write_bulk_callback,
+@@ -227,7 +227,7 @@ static struct usb_serial_driver clie_5_device = {
+ 	.attach =		clie_5_attach,
+ 	.probe =		visor_probe,
+ 	.calc_num_ports =	visor_calc_num_ports,
+-	.shutdown =		visor_shutdown,
++	.release =		visor_release,
+ 	.write =		visor_write,
+ 	.write_room =		visor_write_room,
+ 	.write_bulk_callback =	visor_write_bulk_callback,
+@@ -918,7 +918,7 @@ static int clie_5_attach(struct usb_serial *serial)
+ 	return generic_startup(serial);
+ }
+ 
+-static void visor_shutdown(struct usb_serial *serial)
++static void visor_release(struct usb_serial *serial)
+ {
+ 	struct visor_private *priv;
+ 	int i;
+@@ -927,10 +927,7 @@ static void visor_shutdown(struct usb_serial *serial)
+ 
+ 	for (i = 0; i < serial->num_ports; i++) {
+ 		priv = usb_get_serial_port_data(serial->port[i]);
+-		if (priv) {
+-			usb_set_serial_port_data(serial->port[i], NULL);
+-			kfree(priv);
+-		}
++		kfree(priv);
+ 	}
+ }
+ 
+diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
+index 7c7295d09f34..8d126dd7a02e 100644
+--- a/drivers/usb/serial/whiteheat.c
++++ b/drivers/usb/serial/whiteheat.c
+@@ -144,7 +144,7 @@ static int  whiteheat_firmware_attach(struct usb_serial *serial);
+ 
+ /* function prototypes for the Connect Tech WhiteHEAT serial converter */
+ static int  whiteheat_attach(struct usb_serial *serial);
+-static void whiteheat_shutdown(struct usb_serial *serial);
++static void whiteheat_release(struct usb_serial *serial);
+ static int  whiteheat_open(struct tty_struct *tty,
+ 			struct usb_serial_port *port, struct file *filp);
+ static void whiteheat_close(struct usb_serial_port *port);
+@@ -189,7 +189,7 @@ static struct usb_serial_driver whiteheat_device = {
+ 	.id_table =		id_table_std,
+ 	.num_ports =		4,
+ 	.attach =		whiteheat_attach,
+-	.shutdown =		whiteheat_shutdown,
++	.release =		whiteheat_release,
+ 	.open =			whiteheat_open,
+ 	.close =		whiteheat_close,
+ 	.write =		whiteheat_write,
+@@ -617,7 +617,7 @@ static int whiteheat_attach(struct usb_serial *serial)
+ }
+ 
+ 
+-static void whiteheat_shutdown(struct usb_serial *serial)
++static void whiteheat_release(struct usb_serial *serial)
+ {
+ 	struct usb_serial_port *command_port;
+ 	struct usb_serial_port *port;
+diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
+index ed4aa0fa7ed8..44801d26a37a 100644
+--- a/include/linux/usb/serial.h
++++ b/include/linux/usb/serial.h
+@@ -194,8 +194,10 @@ static inline void usb_set_serial_data(struct usb_serial *serial, void *data)
+  *	This will be called when the struct usb_serial structure is fully set
+  *	set up.  Do any local initialization of the device, or any private
+  *	memory structure allocation at this point in time.
+- * @shutdown: pointer to the driver's shutdown function.  This will be
+- *	called when the device is removed from the system.
++ * @disconnect: pointer to the driver's disconnect function.  This will be
++ *	called when the device is unplugged or unbound from the driver.
++ * @release: pointer to the driver's release function.  This will be called
++ *	when the usb_serial data structure is about to be destroyed.
+  * @usb_driver: pointer to the struct usb_driver that controls this
+  *	device.  This is necessary to allow dynamic ids to be added to
+  *	the driver from sysfs.
+@@ -226,7 +228,8 @@ struct usb_serial_driver {
+ 	int (*attach)(struct usb_serial *serial);
+ 	int (*calc_num_ports) (struct usb_serial *serial);
+ 
+-	void (*shutdown)(struct usb_serial *serial);
++	void (*disconnect)(struct usb_serial *serial);
++	void (*release)(struct usb_serial *serial);
+ 
+ 	int (*port_probe)(struct usb_serial_port *port);
+ 	int (*port_remove)(struct usb_serial_port *port);
+@@ -308,7 +311,8 @@ extern void usb_serial_generic_read_bulk_callback(struct urb *urb);
+ extern void usb_serial_generic_write_bulk_callback(struct urb *urb);
+ extern void usb_serial_generic_throttle(struct tty_struct *tty);
+ extern void usb_serial_generic_unthrottle(struct tty_struct *tty);
+-extern void usb_serial_generic_shutdown(struct usb_serial *serial);
++extern void usb_serial_generic_disconnect(struct usb_serial *serial);
++extern void usb_serial_generic_release(struct usb_serial *serial);
+ extern int usb_serial_generic_register(int debug);
+ extern void usb_serial_generic_deregister(void);
+ extern void usb_serial_generic_resubmit_read_urb(struct usb_serial_port *port,

commit c706ebdfc8955b850e477255a8c0f93f9f14712d
+Author: Alan Stern 
+Date:   Tue Jun 2 11:54:11 2009 -0400
+
+    USB: usb-serial: call port_probe and port_remove at the right times
+    
+    This patch (as1253) prevents the usb-serial core from calling a
+    driver's port_probe and port_remove methods more than once per port.
+    It also removes some unnecessary try_module_get() calls and adds a
+    missing port_remove method call in a failure path.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
+index 83bbb5bca2ef..ba555c528cc6 100644
+--- a/drivers/usb/serial/bus.c
++++ b/drivers/usb/serial/bus.c
+@@ -59,23 +59,22 @@ static int usb_serial_device_probe(struct device *dev)
+ 		retval = -ENODEV;
+ 		goto exit;
+ 	}
++	if (port->dev_state != PORT_REGISTERING)
++		goto exit;
+ 
+ 	driver = port->serial->type;
+ 	if (driver->port_probe) {
+-		if (!try_module_get(driver->driver.owner)) {
+-			dev_err(dev, "module get failed, exiting\n");
+-			retval = -EIO;
+-			goto exit;
+-		}
+ 		retval = driver->port_probe(port);
+-		module_put(driver->driver.owner);
+ 		if (retval)
+ 			goto exit;
+ 	}
+ 
+ 	retval = device_create_file(dev, &dev_attr_port_number);
+-	if (retval)
++	if (retval) {
++		if (driver->port_remove)
++			retval = driver->port_remove(port);
+ 		goto exit;
++	}
+ 
+ 	minor = port->number;
+ 	tty_register_device(usb_serial_tty_driver, minor, dev);
+@@ -98,19 +97,15 @@ static int usb_serial_device_remove(struct device *dev)
+ 	if (!port)
+ 		return -ENODEV;
+ 
++	if (port->dev_state != PORT_UNREGISTERING)
++		return retval;
++
+ 	device_remove_file(&port->dev, &dev_attr_port_number);
+ 
+ 	driver = port->serial->type;
+-	if (driver->port_remove) {
+-		if (!try_module_get(driver->driver.owner)) {
+-			dev_err(dev, "module get failed, exiting\n");
+-			retval = -EIO;
+-			goto exit;
+-		}
++	if (driver->port_remove)
+ 		retval = driver->port_remove(port);
+-		module_put(driver->driver.owner);
+-	}
+-exit:
++
+ 	minor = port->number;
+ 	tty_unregister_device(usb_serial_tty_driver, minor);
+ 	dev_info(dev, "%s converter now disconnected from ttyUSB%d\n",
+diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
+index 1967a7edc10c..da890f030fac 100644
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -1046,10 +1046,15 @@ int usb_serial_probe(struct usb_interface *interface,
+ 
+ 		dev_set_name(&port->dev, "ttyUSB%d", port->number);
+ 		dbg ("%s - registering %s", __func__, dev_name(&port->dev));
++		port->dev_state = PORT_REGISTERING;
+ 		retval = device_register(&port->dev);
+-		if (retval)
++		if (retval) {
+ 			dev_err(&port->dev, "Error registering port device, "
+ 				"continuing\n");
++			port->dev_state = PORT_UNREGISTERED;
++		} else {
++			port->dev_state = PORT_REGISTERED;
++		}
+ 	}
+ 
+ 	usb_serial_console_init(debug, minor);
+@@ -1130,7 +1135,22 @@ void usb_serial_disconnect(struct usb_interface *interface)
+ 			}
+ 			kill_traffic(port);
+ 			cancel_work_sync(&port->work);
+-			device_del(&port->dev);
++			if (port->dev_state == PORT_REGISTERED) {
++
++				/* Make sure the port is bound so that the
++				 * driver's port_remove method is called.
++				 */
++				if (!port->dev.driver) {
++					int rc;
++
++					port->dev.driver =
++							&serial->type->driver;
++					rc = device_bind_driver(&port->dev);
++				}
++				port->dev_state = PORT_UNREGISTERING;
++				device_del(&port->dev);
++				port->dev_state = PORT_UNREGISTERED;
++			}
+ 		}
+ 	}
+ 	serial->type->shutdown(serial);
+diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
+index e29ebcf3287b..ed4aa0fa7ed8 100644
+--- a/include/linux/usb/serial.h
++++ b/include/linux/usb/serial.h
+@@ -27,6 +27,13 @@
+ /* parity check flag */
+ #define RELEVANT_IFLAG(iflag)	(iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
+ 
++enum port_dev_state {
++	PORT_UNREGISTERED,
++	PORT_REGISTERING,
++	PORT_REGISTERED,
++	PORT_UNREGISTERING,
++};
++
+ /**
+  * usb_serial_port: structure for the specific ports of a device.
+  * @serial: pointer back to the struct usb_serial owner of this port.
+@@ -102,6 +109,7 @@ struct usb_serial_port {
+ 	char			console;
+ 	unsigned long		sysrq; /* sysrq timeout */
+ 	struct device		dev;
++	enum port_dev_state	dev_state;
+ };
+ #define to_usb_serial_port(d) container_of(d, struct usb_serial_port, dev)
+ 

commit b18ffd49e86102a9ed0a1cc83fdafe3891e844e5
+Author: Alan Stern 
+Date:   Wed May 27 18:21:56 2009 -0400
+
+    USB: EHCI: update toggle state for linked QHs
+    
+    This patch (as1245) fixes a bug in ehci-hcd.  When an URB is queued
+    for an endpoint whose QH is already in the LINKED state, the QH
+    doesn't get refreshed.  As a result, if usb_clear_halt() was called
+    during the time that the QH was linked but idle, the data toggle value
+    in the QH doesn't get reset.
+    
+    The symptom is that after a clear_halt, data gets lost and transfers
+    time out.  This problem is starting to show up now because the
+    "ehci-hcd unlink speedups" patch causes QHs with no queued URBs to
+    remain linked for a suitable time.
+    
+    The patch utilizes the new endpoint_reset mechanism to fix the
+    problem.  When an endpoint is reset, the new method forcibly unlinks
+    the QH (if necessary) and safely updates the toggle value.  This
+    allows qh_update() to be simplified and avoids using usb_device's
+    toggle bits in a rather unintuitive way.
+    
+    Signed-off-by: Alan Stern 
+    CC: David Brownell 
+    Tested-by: David 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
+index bf69f4739107..c3a778bd359c 100644
+--- a/drivers/usb/host/ehci-au1xxx.c
++++ b/drivers/usb/host/ehci-au1xxx.c
+@@ -97,6 +97,7 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
+ 	.urb_enqueue		= ehci_urb_enqueue,
+ 	.urb_dequeue		= ehci_urb_dequeue,
+ 	.endpoint_disable	= ehci_endpoint_disable,
++	.endpoint_reset		= ehci_endpoint_reset,
+ 
+ 	/*
+ 	 * scheduling support
+diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
+index 01c3da34f678..bf86809c5120 100644
+--- a/drivers/usb/host/ehci-fsl.c
++++ b/drivers/usb/host/ehci-fsl.c
+@@ -309,6 +309,7 @@ static const struct hc_driver ehci_fsl_hc_driver = {
+ 	.urb_enqueue = ehci_urb_enqueue,
+ 	.urb_dequeue = ehci_urb_dequeue,
+ 	.endpoint_disable = ehci_endpoint_disable,
++	.endpoint_reset = ehci_endpoint_reset,
+ 
+ 	/*
+ 	 * scheduling support
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index a2ca9cbf2809..2b72473544d3 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1024,6 +1024,51 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 	return;
+ }
+ 
++static void
++ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
++{
++	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
++	struct ehci_qh		*qh;
++	int			eptype = usb_endpoint_type(&ep->desc);
++
++	if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT)
++		return;
++
++ rescan:
++	spin_lock_irq(&ehci->lock);
++	qh = ep->hcpriv;
++
++	/* For Bulk and Interrupt endpoints we maintain the toggle state
++	 * in the hardware; the toggle bits in udev aren't used at all.
++	 * When an endpoint is reset by usb_clear_halt() we must reset
++	 * the toggle bit in the QH.
++	 */
++	if (qh) {
++		if (!list_empty(&qh->qtd_list)) {
++			WARN_ONCE(1, "clear_halt for a busy endpoint\n");
++		} else if (qh->qh_state == QH_STATE_IDLE) {
++			qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
++		} else {
++			/* It's not safe to write into the overlay area
++			 * while the QH is active.  Unlink it first and
++			 * wait for the unlink to complete.
++			 */
++			if (qh->qh_state == QH_STATE_LINKED) {
++				if (eptype == USB_ENDPOINT_XFER_BULK) {
++					unlink_async(ehci, qh);
++				} else {
++					intr_deschedule(ehci, qh);
++					(void) qh_schedule(ehci, qh);
++				}
++			}
++			spin_unlock_irq(&ehci->lock);
++			schedule_timeout_uninterruptible(1);
++			goto rescan;
++		}
++	}
++	spin_unlock_irq(&ehci->lock);
++}
++
+ static int ehci_get_frame (struct usb_hcd *hcd)
+ {
+ 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c
+index 9c32063a0c2f..a44bb4a94954 100644
+--- a/drivers/usb/host/ehci-ixp4xx.c
++++ b/drivers/usb/host/ehci-ixp4xx.c
+@@ -51,6 +51,7 @@ static const struct hc_driver ixp4xx_ehci_hc_driver = {
+ 	.urb_enqueue		= ehci_urb_enqueue,
+ 	.urb_dequeue		= ehci_urb_dequeue,
+ 	.endpoint_disable	= ehci_endpoint_disable,
++	.endpoint_reset		= ehci_endpoint_reset,
+ 	.get_frame_number	= ehci_get_frame,
+ 	.hub_status_data	= ehci_hub_status_data,
+ 	.hub_control		= ehci_hub_control,
+diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
+index 17dc15407a07..770dd9aba62a 100644
+--- a/drivers/usb/host/ehci-orion.c
++++ b/drivers/usb/host/ehci-orion.c
+@@ -149,6 +149,7 @@ static const struct hc_driver ehci_orion_hc_driver = {
+ 	.urb_enqueue = ehci_urb_enqueue,
+ 	.urb_dequeue = ehci_urb_dequeue,
+ 	.endpoint_disable = ehci_endpoint_disable,
++	.endpoint_reset = ehci_endpoint_reset,
+ 
+ 	/*
+ 	 * scheduling support
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index e74948898f76..f3683e1da161 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -388,6 +388,7 @@ static const struct hc_driver ehci_pci_hc_driver = {
+ 	.urb_enqueue =		ehci_urb_enqueue,
+ 	.urb_dequeue =		ehci_urb_dequeue,
+ 	.endpoint_disable =	ehci_endpoint_disable,
++	.endpoint_reset =	ehci_endpoint_reset,
+ 
+ 	/*
+ 	 * scheduling support
+diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c
+index ef732b704f53..fbd272288fc2 100644
+--- a/drivers/usb/host/ehci-ppc-of.c
++++ b/drivers/usb/host/ehci-ppc-of.c
+@@ -61,6 +61,7 @@ static const struct hc_driver ehci_ppc_of_hc_driver = {
+ 	.urb_enqueue		= ehci_urb_enqueue,
+ 	.urb_dequeue		= ehci_urb_dequeue,
+ 	.endpoint_disable	= ehci_endpoint_disable,
++	.endpoint_reset		= ehci_endpoint_reset,
+ 
+ 	/*
+ 	 * scheduling support
+diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
+index 1ba9f9a8c308..4b4df23efddf 100644
+--- a/drivers/usb/host/ehci-ps3.c
++++ b/drivers/usb/host/ehci-ps3.c
+@@ -65,6 +65,7 @@ static const struct hc_driver ps3_ehci_hc_driver = {
+ 	.urb_enqueue		= ehci_urb_enqueue,
+ 	.urb_dequeue		= ehci_urb_dequeue,
+ 	.endpoint_disable	= ehci_endpoint_disable,
++	.endpoint_reset		= ehci_endpoint_reset,
+ 	.get_frame_number	= ehci_get_frame,
+ 	.hub_status_data	= ehci_hub_status_data,
+ 	.hub_control		= ehci_hub_control,
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 1976b1b3778c..3192f683f807 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -93,22 +93,6 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
+ 	qh->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma);
+ 	qh->hw_alt_next = EHCI_LIST_END(ehci);
+ 
+-	/* Except for control endpoints, we make hardware maintain data
+-	 * toggle (like OHCI) ... here (re)initialize the toggle in the QH,
+-	 * and set the pseudo-toggle in udev. Only usb_clear_halt() will
+-	 * ever clear it.
+-	 */
+-	if (!(qh->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) {
+-		unsigned	is_out, epnum;
+-
+-		is_out = !(qtd->hw_token & cpu_to_hc32(ehci, 1 << 8));
+-		epnum = (hc32_to_cpup(ehci, &qh->hw_info1) >> 8) & 0x0f;
+-		if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) {
+-			qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
+-			usb_settoggle (qh->dev, epnum, is_out, 1);
+-		}
+-	}
+-
+ 	/* HC must see latest qtd and qh data before we clear ACTIVE+HALT */
+ 	wmb ();
+ 	qh->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING);
+@@ -850,7 +834,6 @@ qh_make (
+ 	qh->qh_state = QH_STATE_IDLE;
+ 	qh->hw_info1 = cpu_to_hc32(ehci, info1);
+ 	qh->hw_info2 = cpu_to_hc32(ehci, info2);
+-	usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1);
+ 	qh_refresh (ehci, qh);
+ 	return qh;
+ }
+@@ -881,7 +864,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		}
+ 	}
+ 
+-	/* clear halt and/or toggle; and maybe recover from silicon quirk */
++	/* clear halt and maybe recover from silicon quirk */
+ 	if (qh->qh_state == QH_STATE_IDLE)
+ 		qh_refresh (ehci, qh);
+ 

commit 68335e816a92411649955a9903b1f30c388ea322
+Author: Alan Stern 
+Date:   Fri May 22 17:02:33 2009 -0400
+
+    USB: EHCI: stagger frames for interrupt transfers
+    
+    This patch (as1243) tries to improve ehci-hcd's scheduling of
+    interrupt transfers.  Instead of trying to cram all transfers with the
+    same period into the same frame, the new code will spread the
+    transfers out among lots of different frames.  This should reduce the
+    periodic schedule load in any one frame -- some host controllers have
+    trouble when there's too much work to do.
+    
+    A more thorough approach would stagger the uframe values as well.  But
+    this is enough to make a big improvement.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Dwayne Fontenot 
+    Cc: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 556d0ec0c1f8..9d1babc7ff65 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -760,8 +760,10 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	if (status) {
+ 		/* "normal" case, uframing flexible except with splits */
+ 		if (qh->period) {
+-			frame = qh->period - 1;
+-			do {
++			int		i;
++
++			for (i = qh->period; status && i > 0; --i) {
++				frame = ++ehci->random_frame % qh->period;
+ 				for (uframe = 0; uframe < 8; uframe++) {
+ 					status = check_intr_schedule (ehci,
+ 							frame, uframe, qh,
+@@ -769,7 +771,7 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 					if (status == 0)
+ 						break;
+ 				}
+-			} while (status && frame--);
++			}
+ 
+ 		/* qh->period == 0 means every uframe */
+ 		} else {
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 6cff195e1a36..90ad3395bb21 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -116,6 +116,7 @@ struct ehci_hcd {			/* one per controller */
+ 	struct timer_list	watchdog;
+ 	unsigned long		actions;
+ 	unsigned		stamp;
++	unsigned		random_frame;
+ 	unsigned long		next_statechange;
+ 	u32			command;
+ 

commit be475d9027a07069407a19980d1a4fcb7b18b23c
+Author: Alan Stern 
+Date:   Thu May 21 17:37:58 2009 -0400
+
+    USB: usb-storage: fix return values from init functions
+    
+    This patch (as1242) fixes the return values from the special
+    init functions in usb-storage.  They are supposed to return 0 for
+    success, not USB_STOR_TRANSPORT_GOOD.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/option_ms.c b/drivers/usb/storage/option_ms.c
+index 126ea3424c03..0d8853339bb6 100644
+--- a/drivers/usb/storage/option_ms.c
++++ b/drivers/usb/storage/option_ms.c
+@@ -96,7 +96,7 @@ int option_ms_init(struct us_data *us)
+ 	    udev->descriptor.bDeviceSubClass != 0 ||
+ 	    udev->descriptor.bDeviceProtocol != 0 ||
+ 	    udev->actconfig->desc.bNumInterfaces == 3)
+-		return USB_STOR_TRANSPORT_GOOD;
++		return 0;
+ 
+ 	US_DEBUGP("Option MS: option_ms_init called\n");
+ 
+@@ -107,7 +107,7 @@ int option_ms_init(struct us_data *us)
+ 	    iface_desc->desc.bInterfaceProtocol != 0x50) {
+ 		US_DEBUGP("Option MS: mass storage interface not found, no action "
+ 		          "required\n");
+-		return USB_STOR_TRANSPORT_GOOD;
++		return 0;
+ 	}
+ 
+ 	/* Find the mass storage bulk endpoints */
+@@ -127,7 +127,7 @@ int option_ms_init(struct us_data *us)
+ 	if (!ep_in_size || !ep_out_size) {
+ 		US_DEBUGP("Option MS: mass storage endpoints not found, no action "
+ 		          "required\n");
+-		return USB_STOR_TRANSPORT_GOOD;
++		return 0;
+ 	}
+ 
+ 	/* Force Modem mode */
+@@ -143,6 +143,6 @@ int option_ms_init(struct us_data *us)
+ 		          " requests it\n");
+ 	}
+ 
+-	return USB_STOR_TRANSPORT_GOOD;
++	return 0;
+ }
+ 
+diff --git a/drivers/usb/storage/sierra_ms.c b/drivers/usb/storage/sierra_ms.c
+index 4359a2cb42df..4395c4100ec2 100644
+--- a/drivers/usb/storage/sierra_ms.c
++++ b/drivers/usb/storage/sierra_ms.c
+@@ -202,6 +202,6 @@ int sierra_ms_init(struct us_data *us)
+ complete:
+ 	result = device_create_file(&us->pusb_intf->dev, &dev_attr_truinst);
+ 
+-	return USB_STOR_TRANSPORT_GOOD;
++	return 0;
+ }
+ 

commit 6ec4beb5c701f728548b587082c83ef62eb36035
+Author: Alan Stern 
+Date:   Mon Apr 27 13:33:41 2009 -0400
+
+    USB: new flag for resume-from-hibernation
+    
+    This patch (as1237) changes the way the PCI host controller drivers
+    avoid retaining bogus hardware states during resume-from-hibernation.
+    Previously we had reset the hardware as part of preparing to reinstate
+    the memory image.  But we can do better now with the new PM framework,
+    since we know exactly which resume operations are from hibernation.
+    
+    The pci_resume method is changed to accept a flag indicating whether
+    the system is resuming from hibernation.  When this flag is set, the
+    drivers will reset the hardware to get rid of any existing state.
+    
+    Similarly, the pci_suspend method is changed to remove the
+    pm_message_t argument.  It's no longer needed, since no special action
+    has to be taken when preparing to reinstate the memory image.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Rafael J. Wysocki 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index 5db4d40db832..91f2885b6ee1 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -237,7 +237,7 @@ static int hcd_pci_suspend(struct device *dev)
+ 		return retval;
+ 
+ 	if (hcd->driver->pci_suspend) {
+-		retval = hcd->driver->pci_suspend(hcd, PMSG_SUSPEND);
++		retval = hcd->driver->pci_suspend(hcd);
+ 		suspend_report_result(hcd->driver->pci_suspend, retval);
+ 		if (retval)
+ 			return retval;
+@@ -344,7 +344,7 @@ static int resume_common(struct device *dev, bool hibernated)
+ 	clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+ 
+ 	if (hcd->driver->pci_resume) {
+-		retval = hcd->driver->pci_resume(hcd);
++		retval = hcd->driver->pci_resume(hcd, hibernated);
+ 		if (retval) {
+ 			dev_err(dev, "PCI post-resume error %d!\n", retval);
+ 			usb_hc_died(hcd);
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index 7f068d6e6940..174170f14f06 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -182,10 +182,10 @@ struct hc_driver {
+ 	 * a whole, not just the root hub; they're for PCI bus glue.
+ 	 */
+ 	/* called after suspending the hub, before entering D3 etc */
+-	int	(*pci_suspend) (struct usb_hcd *hcd, pm_message_t message);
++	int	(*pci_suspend)(struct usb_hcd *hcd);
+ 
+ 	/* called after entering D0 (etc), before resuming the hub */
+-	int	(*pci_resume) (struct usb_hcd *hcd);
++	int	(*pci_resume)(struct usb_hcd *hcd, bool hibernated);
+ 
+ 	/* cleanly make HCD stop writing memory and doing I/O */
+ 	void	(*stop) (struct usb_hcd *hcd);
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index 8172383e8908..e74948898f76 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -268,7 +268,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+  * Also they depend on separate root hub suspend/resume.
+  */
+ 
+-static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
++static int ehci_pci_suspend(struct usb_hcd *hcd)
+ {
+ 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
+ 	unsigned long		flags;
+@@ -293,12 +293,6 @@ static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
+ 	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+ 	(void)ehci_readl(ehci, &ehci->regs->intr_enable);
+ 
+-	/* make sure snapshot being resumed re-enumerates everything */
+-	if (message.event == PM_EVENT_PRETHAW) {
+-		ehci_halt(ehci);
+-		ehci_reset(ehci);
+-	}
+-
+ 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+  bail:
+ 	spin_unlock_irqrestore (&ehci->lock, flags);
+@@ -309,7 +303,7 @@ static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
+ 	return rc;
+ }
+ 
+-static int ehci_pci_resume(struct usb_hcd *hcd)
++static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)
+ {
+ 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
+ 	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
+@@ -322,10 +316,12 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
+ 	/* Mark hardware accessible again as we are out of D3 state by now */
+ 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ 
+-	/* If CF is still set, we maintained PCI Vaux power.
++	/* If CF is still set and we aren't resuming from hibernation
++	 * then we maintained PCI Vaux power.
+ 	 * Just undo the effect of ehci_pci_suspend().
+ 	 */
+-	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
++	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF &&
++				!hibernated) {
+ 		int	mask = INTR_MASK;
+ 
+ 		if (!hcd->self.root_hub->do_remote_wakeup)
+@@ -335,7 +331,6 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
+ 		return 0;
+ 	}
+ 
+-	ehci_dbg(ehci, "lost power, restarting\n");
+ 	usb_root_hub_lost_power(hcd->self.root_hub);
+ 
+ 	/* Else reset, to cope with power loss or flush-to-storage
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index ee0a68ca5fda..d2ba04dd785e 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -372,7 +372,7 @@ static int __devinit ohci_pci_start (struct usb_hcd *hcd)
+ 
+ #ifdef	CONFIG_PM
+ 
+-static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
++static int ohci_pci_suspend(struct usb_hcd *hcd)
+ {
+ 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
+ 	unsigned long	flags;
+@@ -394,10 +394,6 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
+ 	ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
+ 	(void)ohci_readl(ohci, &ohci->regs->intrdisable);
+ 
+-	/* make sure snapshot being resumed re-enumerates everything */
+-	if (message.event == PM_EVENT_PRETHAW)
+-		ohci_usb_reset(ohci);
+-
+ 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+  bail:
+ 	spin_unlock_irqrestore (&ohci->lock, flags);
+@@ -406,9 +402,14 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
+ }
+ 
+ 
+-static int ohci_pci_resume (struct usb_hcd *hcd)
++static int ohci_pci_resume(struct usb_hcd *hcd, bool hibernated)
+ {
+ 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
++
++	/* Make sure resume from hibernation re-enumerates everything */
++	if (hibernated)
++		ohci_usb_reset(hcd_to_ohci(hcd));
++
+ 	ohci_finish_controller_resume(hcd);
+ 	return 0;
+ }
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index c0133211e3ec..274751b4409c 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -769,7 +769,7 @@ static int uhci_rh_resume(struct usb_hcd *hcd)
+ 	return rc;
+ }
+ 
+-static int uhci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
++static int uhci_pci_suspend(struct usb_hcd *hcd)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 	int rc = 0;
+@@ -795,10 +795,6 @@ static int uhci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
+ 
+ 	/* FIXME: Enable non-PME# remote wakeup? */
+ 
+-	/* make sure snapshot being resumed re-enumerates everything */
+-	if (message.event == PM_EVENT_PRETHAW)
+-		uhci_hc_died(uhci);
+-
+ done_okay:
+ 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ done:
+@@ -806,7 +802,7 @@ static int uhci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
+ 	return rc;
+ }
+ 
+-static int uhci_pci_resume(struct usb_hcd *hcd)
++static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 
+@@ -820,6 +816,10 @@ static int uhci_pci_resume(struct usb_hcd *hcd)
+ 
+ 	spin_lock_irq(&uhci->lock);
+ 
++	/* Make sure resume from hibernation re-enumerates everything */
++	if (hibernated)
++		uhci_hc_died(uhci);
++
+ 	/* FIXME: Disable non-PME# remote wakeup? */
+ 
+ 	/* The firmware or a boot kernel may have changed the controller

commit abb306416a7ec2386678de0da6b632a6cb068af0
+Author: Alan Stern 
+Date:   Mon Apr 27 13:33:24 2009 -0400
+
+    USB: move PCI host controllers to new PM framework
+    
+    This patch (as1236) converts the USB PCI power management routines
+    over to the new PM framework.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Rafael J. Wysocki 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index a4301dc02d27..5db4d40db832 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -185,194 +185,198 @@ void usb_hcd_pci_remove(struct pci_dev *dev)
+ }
+ EXPORT_SYMBOL_GPL(usb_hcd_pci_remove);
+ 
+-
+-#ifdef	CONFIG_PM
+-
+ /**
+- * usb_hcd_pci_suspend - power management suspend of a PCI-based HCD
+- * @dev: USB Host Controller being suspended
+- * @message: Power Management message describing this state transition
+- *
+- * Store this function in the HCD's struct pci_driver as .suspend.
++ * usb_hcd_pci_shutdown - shutdown host controller
++ * @dev: USB Host Controller being shutdown
+  */
+-int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message)
++void usb_hcd_pci_shutdown(struct pci_dev *dev)
++{
++	struct usb_hcd		*hcd;
++
++	hcd = pci_get_drvdata(dev);
++	if (!hcd)
++		return;
++
++	if (hcd->driver->shutdown)
++		hcd->driver->shutdown(hcd);
++}
++EXPORT_SYMBOL_GPL(usb_hcd_pci_shutdown);
++
++#ifdef	CONFIG_PM_SLEEP
++
++static int check_root_hub_suspended(struct device *dev)
++{
++	struct pci_dev		*pci_dev = to_pci_dev(dev);
++	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
++
++	if (!(hcd->state == HC_STATE_SUSPENDED ||
++			hcd->state == HC_STATE_HALT)) {
++		dev_warn(dev, "Root hub is not suspended\n");
++		return -EBUSY;
++	}
++	return 0;
++}
++
++static int hcd_pci_suspend(struct device *dev)
+ {
+-	struct usb_hcd		*hcd = pci_get_drvdata(dev);
+-	int			retval = 0;
+-	int			wake, w;
+-	int			has_pci_pm;
++	struct pci_dev		*pci_dev = to_pci_dev(dev);
++	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
++	int			retval;
+ 
+ 	/* Root hub suspend should have stopped all downstream traffic,
+ 	 * and all bus master traffic.  And done so for both the interface
+ 	 * and the stub usb_device (which we check here).  But maybe it
+ 	 * didn't; writing sysfs power/state files ignores such rules...
+-	 *
+-	 * We must ignore the FREEZE vs SUSPEND distinction here, because
+-	 * otherwise the swsusp will save (and restore) garbage state.
+ 	 */
+-	if (!(hcd->state == HC_STATE_SUSPENDED ||
+-			hcd->state == HC_STATE_HALT)) {
+-		dev_warn(&dev->dev, "Root hub is not suspended\n");
+-		retval = -EBUSY;
+-		goto done;
+-	}
++	retval = check_root_hub_suspended(dev);
++	if (retval)
++		return retval;
+ 
+ 	/* We might already be suspended (runtime PM -- not yet written) */
+-	if (dev->current_state != PCI_D0)
+-		goto done;
++	if (pci_dev->current_state != PCI_D0)
++		return retval;
+ 
+ 	if (hcd->driver->pci_suspend) {
+-		retval = hcd->driver->pci_suspend(hcd, message);
++		retval = hcd->driver->pci_suspend(hcd, PMSG_SUSPEND);
+ 		suspend_report_result(hcd->driver->pci_suspend, retval);
+ 		if (retval)
+-			goto done;
++			return retval;
+ 	}
+ 
+-	synchronize_irq(dev->irq);
++	synchronize_irq(pci_dev->irq);
+ 
+ 	/* Downstream ports from this root hub should already be quiesced, so
+ 	 * there will be no DMA activity.  Now we can shut down the upstream
+-	 * link (except maybe for PME# resume signaling) and enter some PCI
+-	 * low power state, if the hardware allows.
++	 * link (except maybe for PME# resume signaling).  We'll enter a
++	 * low power state during suspend_noirq, if the hardware allows.
+ 	 */
+-	pci_disable_device(dev);
++	pci_disable_device(pci_dev);
++	return retval;
++}
++
++static int hcd_pci_suspend_noirq(struct device *dev)
++{
++	struct pci_dev		*pci_dev = to_pci_dev(dev);
++	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
++	int			retval;
++
++	retval = check_root_hub_suspended(dev);
++	if (retval)
++		return retval;
+ 
+-	pci_save_state(dev);
++	pci_save_state(pci_dev);
+ 
+-	/* Don't fail on error to enable wakeup.  We rely on pci code
+-	 * to reject requests the hardware can't implement, rather
+-	 * than coding the same thing.
++	/* If the root hub is HALTed rather than SUSPENDed,
++	 * disallow remote wakeup.
+ 	 */
+-	wake = (hcd->state == HC_STATE_SUSPENDED &&
+-			device_may_wakeup(&dev->dev));
+-	w = pci_wake_from_d3(dev, wake);
+-	if (w < 0)
+-		wake = w;
+-	dev_dbg(&dev->dev, "wakeup: %d\n", wake);
+-
+-	/* Don't change state if we don't need to */
+-	if (message.event == PM_EVENT_FREEZE ||
+-			message.event == PM_EVENT_PRETHAW) {
+-		dev_dbg(&dev->dev, "--> no state change\n");
+-		goto done;
+-	}
++	if (hcd->state == HC_STATE_HALT)
++		device_set_wakeup_enable(dev, 0);
++	dev_dbg(dev, "wakeup: %d\n", device_may_wakeup(dev));
+ 
+-	has_pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM);
+-	if (!has_pci_pm) {
+-		dev_dbg(&dev->dev, "--> PCI D0 legacy\n");
++	/* Possibly enable remote wakeup,
++	 * choose the appropriate low-power state, and go to that state.
++	 */
++	retval = pci_prepare_to_sleep(pci_dev);
++	if (retval == -EIO) {		/* Low-power not supported */
++		dev_dbg(dev, "--> PCI D0 legacy\n");
++		retval = 0;
++	} else if (retval == 0) {
++		dev_dbg(dev, "--> PCI %s\n",
++				pci_power_name(pci_dev->current_state));
+ 	} else {
+-
+-		/* NOTE:  dev->current_state becomes nonzero only here, and
+-		 * only for devices that support PCI PM.  Also, exiting
+-		 * PCI_D3 (but not PCI_D1 or PCI_D2) is allowed to reset
+-		 * some device state (e.g. as part of clock reinit).
+-		 */
+-		retval = pci_set_power_state(dev, PCI_D3hot);
+-		suspend_report_result(pci_set_power_state, retval);
+-		if (retval == 0) {
+-			dev_dbg(&dev->dev, "--> PCI D3\n");
+-		} else {
+-			dev_dbg(&dev->dev, "PCI D3 suspend fail, %d\n",
+-					retval);
+-			pci_restore_state(dev);
+-		}
++		suspend_report_result(pci_prepare_to_sleep, retval);
++		return retval;
+ 	}
+ 
+ #ifdef CONFIG_PPC_PMAC
+-	if (retval == 0) {
+-		/* Disable ASIC clocks for USB */
+-		if (machine_is(powermac)) {
+-			struct device_node	*of_node;
+-
+-			of_node = pci_device_to_OF_node(dev);
+-			if (of_node)
+-				pmac_call_feature(PMAC_FTR_USB_ENABLE,
+-							of_node, 0, 0);
+-		}
++	/* Disable ASIC clocks for USB */
++	if (machine_is(powermac)) {
++		struct device_node	*of_node;
++
++		of_node = pci_device_to_OF_node(pci_dev);
++		if (of_node)
++			pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0);
+ 	}
+ #endif
+-
+- done:
+ 	return retval;
+ }
+-EXPORT_SYMBOL_GPL(usb_hcd_pci_suspend);
+ 
+-/**
+- * usb_hcd_pci_resume - power management resume of a PCI-based HCD
+- * @dev: USB Host Controller being resumed
+- *
+- * Store this function in the HCD's struct pci_driver as .resume.
+- */
+-int usb_hcd_pci_resume(struct pci_dev *dev)
++static int hcd_pci_resume_noirq(struct device *dev)
+ {
+-	struct usb_hcd		*hcd;
+-	int			retval;
++	struct pci_dev		*pci_dev = to_pci_dev(dev);
+ 
+ #ifdef CONFIG_PPC_PMAC
+ 	/* Reenable ASIC clocks for USB */
+ 	if (machine_is(powermac)) {
+ 		struct device_node *of_node;
+ 
+-		of_node = pci_device_to_OF_node(dev);
++		of_node = pci_device_to_OF_node(pci_dev);
+ 		if (of_node)
+ 			pmac_call_feature(PMAC_FTR_USB_ENABLE,
+ 						of_node, 0, 1);
+ 	}
+ #endif
+ 
+-	pci_restore_state(dev);
++	/* Go back to D0 and disable remote wakeup */
++	pci_back_from_sleep(pci_dev);
++	return 0;
++}
++
++static int resume_common(struct device *dev, bool hibernated)
++{
++	struct pci_dev		*pci_dev = to_pci_dev(dev);
++	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
++	int			retval;
+ 
+-	hcd = pci_get_drvdata(dev);
+ 	if (hcd->state != HC_STATE_SUSPENDED) {
+-		dev_dbg(hcd->self.controller,
+-				"can't resume, not suspended!\n");
++		dev_dbg(dev, "can't resume, not suspended!\n");
+ 		return 0;
+ 	}
+ 
+-	pci_enable_wake(dev, PCI_D0, false);
+-
+-	retval = pci_enable_device(dev);
++	retval = pci_enable_device(pci_dev);
+ 	if (retval < 0) {
+-		dev_err(&dev->dev, "can't re-enable after resume, %d!\n",
+-				retval);
++		dev_err(dev, "can't re-enable after resume, %d!\n", retval);
+ 		return retval;
+ 	}
+ 
+-	pci_set_master(dev);
+-
+-	/* yes, ignore this result too... */
+-	(void) pci_wake_from_d3(dev, 0);
++	pci_set_master(pci_dev);
+ 
+ 	clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+ 
+ 	if (hcd->driver->pci_resume) {
+ 		retval = hcd->driver->pci_resume(hcd);
+ 		if (retval) {
+-			dev_err(hcd->self.controller,
+-				"PCI post-resume error %d!\n", retval);
++			dev_err(dev, "PCI post-resume error %d!\n", retval);
+ 			usb_hc_died(hcd);
+ 		}
+ 	}
+ 	return retval;
+ }
+-EXPORT_SYMBOL_GPL(usb_hcd_pci_resume);
+ 
+-#endif	/* CONFIG_PM */
+-
+-/**
+- * usb_hcd_pci_shutdown - shutdown host controller
+- * @dev: USB Host Controller being shutdown
+- */
+-void usb_hcd_pci_shutdown(struct pci_dev *dev)
++static int hcd_pci_resume(struct device *dev)
+ {
+-	struct usb_hcd		*hcd;
+-
+-	hcd = pci_get_drvdata(dev);
+-	if (!hcd)
+-		return;
++	return resume_common(dev, false);
++}
+ 
+-	if (hcd->driver->shutdown)
+-		hcd->driver->shutdown(hcd);
++static int hcd_pci_restore(struct device *dev)
++{
++	return resume_common(dev, true);
+ }
+-EXPORT_SYMBOL_GPL(usb_hcd_pci_shutdown);
+ 
++struct dev_pm_ops usb_hcd_pci_pm_ops = {
++	.suspend	= hcd_pci_suspend,
++	.suspend_noirq	= hcd_pci_suspend_noirq,
++	.resume_noirq	= hcd_pci_resume_noirq,
++	.resume		= hcd_pci_resume,
++	.freeze		= check_root_hub_suspended,
++	.freeze_noirq	= check_root_hub_suspended,
++	.thaw_noirq	= NULL,
++	.thaw		= NULL,
++	.poweroff	= hcd_pci_suspend,
++	.poweroff_noirq	= hcd_pci_suspend_noirq,
++	.restore_noirq	= hcd_pci_resume_noirq,
++	.restore	= hcd_pci_restore,
++};
++EXPORT_SYMBOL_GPL(usb_hcd_pci_pm_ops);
++
++#endif	/* CONFIG_PM_SLEEP */
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index e7d4479de41c..7f068d6e6940 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -261,14 +261,11 @@ struct pci_device_id;
+ extern int usb_hcd_pci_probe(struct pci_dev *dev,
+ 				const struct pci_device_id *id);
+ extern void usb_hcd_pci_remove(struct pci_dev *dev);
+-
+-#ifdef CONFIG_PM
+-extern int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t msg);
+-extern int usb_hcd_pci_resume(struct pci_dev *dev);
+-#endif /* CONFIG_PM */
+-
+ extern void usb_hcd_pci_shutdown(struct pci_dev *dev);
+ 
++#ifdef CONFIG_PM_SLEEP
++extern struct dev_pm_ops	usb_hcd_pci_pm_ops;
++#endif
+ #endif /* CONFIG_PCI */
+ 
+ /* pci-ish (pdev null is ok) buffer alloc/mapping support */
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index 5aa8bce90e1f..8172383e8908 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -429,10 +429,11 @@ static struct pci_driver ehci_pci_driver = {
+ 
+ 	.probe =	usb_hcd_pci_probe,
+ 	.remove =	usb_hcd_pci_remove,
++	.shutdown = 	usb_hcd_pci_shutdown,
+ 
+-#ifdef	CONFIG_PM
+-	.suspend =	usb_hcd_pci_suspend,
+-	.resume =	usb_hcd_pci_resume,
++#ifdef CONFIG_PM_SLEEP
++	.driver =	{
++		.pm =	&usb_hcd_pci_pm_ops
++	},
+ #endif
+-	.shutdown = 	usb_hcd_pci_shutdown,
+ };
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index f9961b4c0da3..ee0a68ca5fda 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -484,12 +484,11 @@ static struct pci_driver ohci_pci_driver = {
+ 
+ 	.probe =	usb_hcd_pci_probe,
+ 	.remove =	usb_hcd_pci_remove,
++	.shutdown =	usb_hcd_pci_shutdown,
+ 
+-#ifdef	CONFIG_PM
+-	.suspend =	usb_hcd_pci_suspend,
+-	.resume =	usb_hcd_pci_resume,
++#ifdef CONFIG_PM_SLEEP
++	.driver =	{
++		.pm =	&usb_hcd_pci_pm_ops
++	},
+ #endif
+-
+-	.shutdown =	usb_hcd_pci_shutdown,
+ };
+-
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index f2fd709fcce7..c0133211e3ec 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -940,10 +940,11 @@ static struct pci_driver uhci_pci_driver = {
+ 	.remove =	usb_hcd_pci_remove,
+ 	.shutdown =	uhci_shutdown,
+ 
+-#ifdef	CONFIG_PM
+-	.suspend =	usb_hcd_pci_suspend,
+-	.resume =	usb_hcd_pci_resume,
+-#endif	/* PM */
++#ifdef CONFIG_PM_SLEEP
++	.driver =	{
++		.pm =	&usb_hcd_pci_pm_ops
++	},
++#endif
+ };
+  
+ static int __init uhci_hcd_init(void)

commit 00240c3839d843ccf07abd52806f421f7b87bbdc
+Author: Alan Stern 
+Date:   Mon Apr 27 13:33:16 2009 -0400
+
+    PCI: add power-state name strings
+    
+    This patch (as1235) adds an array of PCI power-state names, together
+    with a simple inline accessor routine.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Rafael J. Wysocki 
+    Acked-by: Jesse Barnes 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
+index 1a91bf9687af..07bbb9b3b93f 100644
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -24,6 +24,11 @@
+ #include 
+ #include "pci.h"
+ 
++const char *pci_power_names[] = {
++	"error", "D0", "D1", "D2", "D3hot", "D3cold", "unknown",
++};
++EXPORT_SYMBOL_GPL(pci_power_names);
++
+ unsigned int pci_pm_d3_delay = PCI_PM_D3_WAIT;
+ 
+ #ifdef CONFIG_PCI_DOMAINS
+diff --git a/include/linux/pci.h b/include/linux/pci.h
+index 72698d89e767..8e366bb0705f 100644
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -124,6 +124,14 @@ typedef int __bitwise pci_power_t;
+ #define PCI_UNKNOWN	((pci_power_t __force) 5)
+ #define PCI_POWER_ERROR	((pci_power_t __force) -1)
+ 
++/* Remember to update this when the list above changes! */
++extern const char *pci_power_names[];
++
++static inline const char *pci_power_name(pci_power_t state)
++{
++	return pci_power_names[1 + (int) state];
++}
++
+ #define PCI_PM_D2_DELAY	200
+ #define PCI_PM_D3_WAIT	10
+ #define PCI_PM_BUS_WAIT	50

commit 604eb89ffed9fba268582dc44d5b462ea94cc0ca
+Author: Alan Stern 
+Date:   Mon Apr 27 13:19:41 2009 -0400
+
+    USB: g_file_storage: use the "unaligned" accessors
+    
+    This patch (as1233) makes g_file_storage use the "unaligned" accessors.
+    This is based on work originally done by Harvey Harrison.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Harvey Harrison 
+    Acked-by: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index 381a53b3e11c..1e6aa504d58a 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -248,6 +248,8 @@
+ #include 
+ #include 
+ 
++#include 
++
+ #include 
+ #include 
+ 
+@@ -799,29 +801,9 @@ static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
+ 
+ /* Routines for unaligned data access */
+ 
+-static u16 get_be16(u8 *buf)
+-{
+-	return ((u16) buf[0] << 8) | ((u16) buf[1]);
+-}
+-
+-static u32 get_be32(u8 *buf)
+-{
+-	return ((u32) buf[0] << 24) | ((u32) buf[1] << 16) |
+-			((u32) buf[2] << 8) | ((u32) buf[3]);
+-}
+-
+-static void put_be16(u8 *buf, u16 val)
+-{
+-	buf[0] = val >> 8;
+-	buf[1] = val;
+-}
+-
+-static void put_be32(u8 *buf, u32 val)
++static u32 get_unaligned_be24(u8 *buf)
+ {
+-	buf[0] = val >> 24;
+-	buf[1] = val >> 16;
+-	buf[2] = val >> 8;
+-	buf[3] = val & 0xff;
++	return 0xffffff & (u32) get_unaligned_be32(buf - 1);
+ }
+ 
+ 
+@@ -1582,9 +1564,9 @@ static int do_read(struct fsg_dev *fsg)
+ 	/* Get the starting Logical Block Address and check that it's
+ 	 * not too big */
+ 	if (fsg->cmnd[0] == SC_READ_6)
+-		lba = (fsg->cmnd[1] << 16) | get_be16(&fsg->cmnd[2]);
++		lba = get_unaligned_be24(&fsg->cmnd[1]);
+ 	else {
+-		lba = get_be32(&fsg->cmnd[2]);
++		lba = get_unaligned_be32(&fsg->cmnd[2]);
+ 
+ 		/* We allow DPO (Disable Page Out = don't save data in the
+ 		 * cache) and FUA (Force Unit Access = don't read from the
+@@ -1717,9 +1699,9 @@ static int do_write(struct fsg_dev *fsg)
+ 	/* Get the starting Logical Block Address and check that it's
+ 	 * not too big */
+ 	if (fsg->cmnd[0] == SC_WRITE_6)
+-		lba = (fsg->cmnd[1] << 16) | get_be16(&fsg->cmnd[2]);
++		lba = get_unaligned_be24(&fsg->cmnd[1]);
+ 	else {
+-		lba = get_be32(&fsg->cmnd[2]);
++		lba = get_unaligned_be32(&fsg->cmnd[2]);
+ 
+ 		/* We allow DPO (Disable Page Out = don't save data in the
+ 		 * cache) and FUA (Force Unit Access = write directly to the
+@@ -1940,7 +1922,7 @@ static int do_verify(struct fsg_dev *fsg)
+ 
+ 	/* Get the starting Logical Block Address and check that it's
+ 	 * not too big */
+-	lba = get_be32(&fsg->cmnd[2]);
++	lba = get_unaligned_be32(&fsg->cmnd[2]);
+ 	if (lba >= curlun->num_sectors) {
+ 		curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
+ 		return -EINVAL;
+@@ -1953,7 +1935,7 @@ static int do_verify(struct fsg_dev *fsg)
+ 		return -EINVAL;
+ 	}
+ 
+-	verification_length = get_be16(&fsg->cmnd[7]);
++	verification_length = get_unaligned_be16(&fsg->cmnd[7]);
+ 	if (unlikely(verification_length == 0))
+ 		return -EIO;		// No default reply
+ 
+@@ -2103,7 +2085,7 @@ static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
+ 	memset(buf, 0, 18);
+ 	buf[0] = valid | 0x70;			// Valid, current error
+ 	buf[2] = SK(sd);
+-	put_be32(&buf[3], sdinfo);		// Sense information
++	put_unaligned_be32(sdinfo, &buf[3]);	/* Sense information */
+ 	buf[7] = 18 - 8;			// Additional sense length
+ 	buf[12] = ASC(sd);
+ 	buf[13] = ASCQ(sd);
+@@ -2114,7 +2096,7 @@ static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
+ static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh)
+ {
+ 	struct lun	*curlun = fsg->curlun;
+-	u32		lba = get_be32(&fsg->cmnd[2]);
++	u32		lba = get_unaligned_be32(&fsg->cmnd[2]);
+ 	int		pmi = fsg->cmnd[8];
+ 	u8		*buf = (u8 *) bh->buf;
+ 
+@@ -2124,8 +2106,9 @@ static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh)
+ 		return -EINVAL;
+ 	}
+ 
+-	put_be32(&buf[0], curlun->num_sectors - 1);	// Max logical block
+-	put_be32(&buf[4], 512);				// Block length
++	put_unaligned_be32(curlun->num_sectors - 1, &buf[0]);
++						/* Max logical block */
++	put_unaligned_be32(512, &buf[4]);	/* Block length */
+ 	return 8;
+ }
+ 
+@@ -2144,7 +2127,7 @@ static void store_cdrom_address(u8 *dest, int msf, u32 addr)
+ 		dest[0] = 0;		/* Reserved */
+ 	} else {
+ 		/* Absolute sector */
+-		put_be32(dest, addr);
++		put_unaligned_be32(addr, dest);
+ 	}
+ }
+ 
+@@ -2152,7 +2135,7 @@ static int do_read_header(struct fsg_dev *fsg, struct fsg_buffhd *bh)
+ {
+ 	struct lun	*curlun = fsg->curlun;
+ 	int		msf = fsg->cmnd[1] & 0x02;
+-	u32		lba = get_be32(&fsg->cmnd[2]);
++	u32		lba = get_unaligned_be32(&fsg->cmnd[2]);
+ 	u8		*buf = (u8 *) bh->buf;
+ 
+ 	if ((fsg->cmnd[1] & ~0x02) != 0) {		/* Mask away MSF */
+@@ -2252,10 +2235,13 @@ static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
+ 			buf[2] = 0x04;	// Write cache enable,
+ 					// Read cache not disabled
+ 					// No cache retention priorities
+-			put_be16(&buf[4], 0xffff);  // Don't disable prefetch
+-					// Minimum prefetch = 0
+-			put_be16(&buf[8], 0xffff);  // Maximum prefetch
+-			put_be16(&buf[10], 0xffff); // Maximum prefetch ceiling
++			put_unaligned_be16(0xffff, &buf[4]);
++					/* Don't disable prefetch */
++					/* Minimum prefetch = 0 */
++			put_unaligned_be16(0xffff, &buf[8]);
++					/* Maximum prefetch */
++			put_unaligned_be16(0xffff, &buf[10]);
++					/* Maximum prefetch ceiling */
+ 		}
+ 		buf += 12;
+ 	}
+@@ -2272,7 +2258,7 @@ static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
+ 	if (mscmnd == SC_MODE_SENSE_6)
+ 		buf0[0] = len - 1;
+ 	else
+-		put_be16(buf0, len - 2);
++		put_unaligned_be16(len - 2, buf0);
+ 	return len;
+ }
+ 
+@@ -2360,9 +2346,10 @@ static int do_read_format_capacities(struct fsg_dev *fsg,
+ 	buf[3] = 8;		// Only the Current/Maximum Capacity Descriptor
+ 	buf += 4;
+ 
+-	put_be32(&buf[0], curlun->num_sectors);		// Number of blocks
+-	put_be32(&buf[4], 512);				// Block length
+-	buf[4] = 0x02;					// Current capacity
++	put_unaligned_be32(curlun->num_sectors, &buf[0]);
++						/* Number of blocks */
++	put_unaligned_be32(512, &buf[4]);	/* Block length */
++	buf[4] = 0x02;				/* Current capacity */
+ 	return 12;
+ }
+ 
+@@ -2882,7 +2869,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
+ 		break;
+ 
+ 	case SC_MODE_SELECT_10:
+-		fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]);
++		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
+ 		if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST,
+ 				(1<<1) | (3<<7), 0,
+ 				"MODE SELECT(10)")) == 0)
+@@ -2898,7 +2885,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
+ 		break;
+ 
+ 	case SC_MODE_SENSE_10:
+-		fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]);
++		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
+ 		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
+ 				(1<<1) | (1<<2) | (3<<7), 0,
+ 				"MODE SENSE(10)")) == 0)
+@@ -2923,7 +2910,8 @@ static int do_scsi_command(struct fsg_dev *fsg)
+ 		break;
+ 
+ 	case SC_READ_10:
+-		fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]) << 9;
++		fsg->data_size_from_cmnd =
++				get_unaligned_be16(&fsg->cmnd[7]) << 9;
+ 		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
+ 				(1<<1) | (0xf<<2) | (3<<7), 1,
+ 				"READ(10)")) == 0)
+@@ -2931,7 +2919,8 @@ static int do_scsi_command(struct fsg_dev *fsg)
+ 		break;
+ 
+ 	case SC_READ_12:
+-		fsg->data_size_from_cmnd = get_be32(&fsg->cmnd[6]) << 9;
++		fsg->data_size_from_cmnd =
++				get_unaligned_be32(&fsg->cmnd[6]) << 9;
+ 		if ((reply = check_command(fsg, 12, DATA_DIR_TO_HOST,
+ 				(1<<1) | (0xf<<2) | (0xf<<6), 1,
+ 				"READ(12)")) == 0)
+@@ -2949,7 +2938,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
+ 	case SC_READ_HEADER:
+ 		if (!mod_data.cdrom)
+ 			goto unknown_cmnd;
+-		fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]);
++		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
+ 		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
+ 				(3<<7) | (0x1f<<1), 1,
+ 				"READ HEADER")) == 0)
+@@ -2959,7 +2948,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
+ 	case SC_READ_TOC:
+ 		if (!mod_data.cdrom)
+ 			goto unknown_cmnd;
+-		fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]);
++		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
+ 		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
+ 				(7<<6) | (1<<1), 1,
+ 				"READ TOC")) == 0)
+@@ -2967,7 +2956,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
+ 		break;
+ 
+ 	case SC_READ_FORMAT_CAPACITIES:
+-		fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]);
++		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
+ 		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
+ 				(3<<7), 1,
+ 				"READ FORMAT CAPACITIES")) == 0)
+@@ -3025,7 +3014,8 @@ static int do_scsi_command(struct fsg_dev *fsg)
+ 		break;
+ 
+ 	case SC_WRITE_10:
+-		fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]) << 9;
++		fsg->data_size_from_cmnd =
++				get_unaligned_be16(&fsg->cmnd[7]) << 9;
+ 		if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST,
+ 				(1<<1) | (0xf<<2) | (3<<7), 1,
+ 				"WRITE(10)")) == 0)
+@@ -3033,7 +3023,8 @@ static int do_scsi_command(struct fsg_dev *fsg)
+ 		break;
+ 
+ 	case SC_WRITE_12:
+-		fsg->data_size_from_cmnd = get_be32(&fsg->cmnd[6]) << 9;
++		fsg->data_size_from_cmnd =
++				get_unaligned_be32(&fsg->cmnd[6]) << 9;
+ 		if ((reply = check_command(fsg, 12, DATA_DIR_FROM_HOST,
+ 				(1<<1) | (0xf<<2) | (0xf<<6), 1,
+ 				"WRITE(12)")) == 0)

commit 74675a58507e769beee7d949dbed788af3c4139d
+Author: Alan Stern 
+Date:   Thu Apr 30 10:08:18 2009 -0400
+
+    NLS: update handling of Unicode
+    
+    This patch (as1239) updates the kernel's treatment of Unicode.  The
+    character-set conversion routines are well behind the current state of
+    the Unicode specification: They don't recognize the existence of code
+    points beyond plane 0 or of surrogate pairs in the UTF-16 encoding.
+    
+    The old wchar_t 16-bit type is retained because it's still used in
+    lots of places.  This shouldn't cause any new problems; if a
+    conversion now results in an invalid 16-bit code then before it must
+    have yielded an undefined code.
+    
+    Difficult-to-read names like "utf_mbstowcs" are replaced with more
+    transparent names like "utf8s_to_utf16s" and the ordering of the
+    parameters is rationalized (buffer lengths come immediate after the
+    pointers they refer to, and the inputs precede the outputs).
+    Fortunately the low-level conversion routines are used in only a few
+    places; the interfaces to the higher-level uni2char and char2uni
+    methods have been left unchanged.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Clemens Ladisch 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index e98f928c08ea..9bd26dec7599 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -780,14 +780,13 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
+ {
+ 	unsigned char *tbuf;
+ 	int err;
+-	unsigned int u;
+ 
+ 	if (dev->state == USB_STATE_SUSPENDED)
+ 		return -EHOSTUNREACH;
+ 	if (size <= 0 || !buf || !index)
+ 		return -EINVAL;
+ 	buf[0] = 0;
+-	tbuf = kmalloc(256 + 2, GFP_NOIO);
++	tbuf = kmalloc(256, GFP_NOIO);
+ 	if (!tbuf)
+ 		return -ENOMEM;
+ 
+@@ -814,12 +813,9 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
+ 	if (err < 0)
+ 		goto errout;
+ 
+-	for (u = 2; u < err; u += 2)
+-		le16_to_cpus((u16 *)&tbuf[u]);
+-	tbuf[u] = 0;
+-	tbuf[u + 1] = 0;
+ 	size--;		/* leave room for trailing NULL char in output buffer */
+-	err = utf8_wcstombs(buf, (u16 *)&tbuf[2], size);
++	err = utf16s_to_utf8s((wchar_t *) &tbuf[2], (err - 2) / 2,
++			UTF16_LITTLE_ENDIAN, buf, size);
+ 	buf[err] = 0;
+ 
+ 	if (tbuf[1] != USB_DT_STRING)
+diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
+index 9367b6297d84..89cd2deeb4af 100644
+--- a/fs/befs/linuxvfs.c
++++ b/fs/befs/linuxvfs.c
+@@ -513,7 +513,7 @@ befs_utf2nls(struct super_block *sb, const char *in,
+ {
+ 	struct nls_table *nls = BEFS_SB(sb)->nls;
+ 	int i, o;
+-	wchar_t uni;
++	unicode_t uni;
+ 	int unilen, utflen;
+ 	char *result;
+ 	/* The utf8->nls conversion won't make the final nls string bigger
+@@ -539,16 +539,16 @@ befs_utf2nls(struct super_block *sb, const char *in,
+ 	for (i = o = 0; i < in_len; i += utflen, o += unilen) {
+ 
+ 		/* convert from UTF-8 to Unicode */
+-		utflen = utf8_mbtowc(&uni, &in[i], in_len - i);
+-		if (utflen < 0) {
++		utflen = utf8_to_utf32(&in[i], in_len - i, &uni);
++		if (utflen < 0)
+ 			goto conv_err;
+-		}
+ 
+ 		/* convert from Unicode to nls */
++		if (uni > MAX_WCHAR_T)
++			goto conv_err;
+ 		unilen = nls->uni2char(uni, &result[o], in_len - o);
+-		if (unilen < 0) {
++		if (unilen < 0)
+ 			goto conv_err;
+-		}
+ 	}
+ 	result[o] = '\0';
+ 	*out_len = o;
+@@ -619,15 +619,13 @@ befs_nls2utf(struct super_block *sb, const char *in,
+ 
+ 		/* convert from nls to unicode */
+ 		unilen = nls->char2uni(&in[i], in_len - i, &uni);
+-		if (unilen < 0) {
++		if (unilen < 0)
+ 			goto conv_err;
+-		}
+ 
+ 		/* convert from unicode to UTF-8 */
+-		utflen = utf8_wctomb(&result[o], uni, 3);
+-		if (utflen <= 0) {
++		utflen = utf32_to_utf8(uni, &result[o], 3);
++		if (utflen <= 0)
+ 			goto conv_err;
+-		}
+ 	}
+ 
+ 	result[o] = '\0';
+diff --git a/fs/fat/dir.c b/fs/fat/dir.c
+index f3500294eec5..7c14c8cbbaba 100644
+--- a/fs/fat/dir.c
++++ b/fs/fat/dir.c
+@@ -22,6 +22,19 @@
+ #include 
+ #include "fat.h"
+ 
++/*
++ * Maximum buffer size of short name.
++ * [(MSDOS_NAME + '.') * max one char + nul]
++ * For msdos style, ['.' (hidden) + MSDOS_NAME + '.' + nul]
++ */
++#define FAT_MAX_SHORT_SIZE	((MSDOS_NAME + 1) * NLS_MAX_CHARSET_SIZE + 1)
++/*
++ * Maximum buffer size of unicode chars from slots.
++ * [(max longname slots * 13 (size in a slot) + nul) * sizeof(wchar_t)]
++ */
++#define FAT_MAX_UNI_CHARS	((MSDOS_SLOTS - 1) * 13 + 1)
++#define FAT_MAX_UNI_SIZE	(FAT_MAX_UNI_CHARS * sizeof(wchar_t))
++
+ static inline loff_t fat_make_i_pos(struct super_block *sb,
+ 				    struct buffer_head *bh,
+ 				    struct msdos_dir_entry *de)
+@@ -171,7 +184,8 @@ static inline int fat_uni_to_x8(struct msdos_sb_info *sbi, const wchar_t *uni,
+ 				unsigned char *buf, int size)
+ {
+ 	if (sbi->options.utf8)
+-		return utf8_wcstombs(buf, uni, size);
++		return utf16s_to_utf8s(uni, FAT_MAX_UNI_CHARS,
++				UTF16_HOST_ENDIAN, buf, size);
+ 	else
+ 		return uni16_to_x8(buf, uni, size, sbi->options.unicode_xlate,
+ 				   sbi->nls_io);
+@@ -324,19 +338,6 @@ static int fat_parse_long(struct inode *dir, loff_t *pos,
+ 	return 0;
+ }
+ 
+-/*
+- * Maximum buffer size of short name.
+- * [(MSDOS_NAME + '.') * max one char + nul]
+- * For msdos style, ['.' (hidden) + MSDOS_NAME + '.' + nul]
+- */
+-#define FAT_MAX_SHORT_SIZE	((MSDOS_NAME + 1) * NLS_MAX_CHARSET_SIZE + 1)
+-/*
+- * Maximum buffer size of unicode chars from slots.
+- * [(max longname slots * 13 (size in a slot) + nul) * sizeof(wchar_t)]
+- */
+-#define FAT_MAX_UNI_CHARS	((MSDOS_SLOTS - 1) * 13 + 1)
+-#define FAT_MAX_UNI_SIZE	(FAT_MAX_UNI_CHARS * sizeof(wchar_t))
+-
+ /*
+  * Return values: negative -> error, 0 -> not found, positive -> found,
+  * value is the total amount of slots, including the shortname entry.
+diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
+index b50ecbe97f83..f92ad9995356 100644
+--- a/fs/fat/namei_vfat.c
++++ b/fs/fat/namei_vfat.c
+@@ -502,11 +502,11 @@ xlate_to_uni(const unsigned char *name, int len, unsigned char *outname,
+ 	if (utf8) {
+ 		int name_len = strlen(name);
+ 
+-		*outlen = utf8_mbstowcs((wchar_t *)outname, name, PATH_MAX);
++		*outlen = utf8s_to_utf16s(name, PATH_MAX, (wchar_t *) outname);
+ 
+ 		/*
+ 		 * We stripped '.'s before and set len appropriately,
+-		 * but utf8_mbstowcs doesn't care about len
++		 * but utf8s_to_utf16s doesn't care about len
+ 		 */
+ 		*outlen -= (name_len - len);
+ 
+diff --git a/fs/isofs/joliet.c b/fs/isofs/joliet.c
+index 92c14b850e9c..a048de81c093 100644
+--- a/fs/isofs/joliet.c
++++ b/fs/isofs/joliet.c
+@@ -37,37 +37,6 @@ uni16_to_x8(unsigned char *ascii, __be16 *uni, int len, struct nls_table *nls)
+ 	return (op - ascii);
+ }
+ 
+-/* Convert big endian wide character string to utf8 */
+-static int
+-wcsntombs_be(__u8 *s, const __u8 *pwcs, int inlen, int maxlen)
+-{
+-	const __u8 *ip;
+-	__u8 *op;
+-	int size;
+-	__u16 c;
+-
+-	op = s;
+-	ip = pwcs;
+-	while ((*ip || ip[1]) && (maxlen > 0) && (inlen > 0)) {
+-		c = (*ip << 8) | ip[1];
+-		if (c > 0x7f) {
+-			size = utf8_wctomb(op, c, maxlen);
+-			if (size == -1) {
+-				/* Ignore character and move on */
+-				maxlen--;
+-			} else {
+-				op += size;
+-				maxlen -= size;
+-			}
+-		} else {
+-			*op++ = (__u8) c;
+-		}
+-		ip += 2;
+-		inlen--;
+-	}
+-	return (op - s);
+-}
+-
+ int
+ get_joliet_filename(struct iso_directory_record * de, unsigned char *outname, struct inode * inode)
+ {
+@@ -79,8 +48,9 @@ get_joliet_filename(struct iso_directory_record * de, unsigned char *outname, st
+ 	nls = ISOFS_SB(inode->i_sb)->s_nls_iocharset;
+ 
+ 	if (utf8) {
+-		len = wcsntombs_be(outname, de->name,
+-				de->name_len[0] >> 1, PAGE_SIZE);
++		len = utf16s_to_utf8s((const wchar_t *) de->name,
++				de->name_len[0] >> 1, UTF16_BIG_ENDIAN,
++				outname, PAGE_SIZE);
+ 	} else {
+ 		len = uni16_to_x8(outname, (__be16 *) de->name,
+ 				de->name_len[0] >> 1, nls);
+diff --git a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c
+index 97645f112114..0ec6237a5970 100644
+--- a/fs/ncpfs/ncplib_kernel.c
++++ b/fs/ncpfs/ncplib_kernel.c
+@@ -1113,11 +1113,13 @@ ncp__io2vol(struct ncp_server *server, unsigned char *vname, unsigned int *vlen,
+ 
+ 		if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) {
+ 			int k;
++			unicode_t u;
+ 
+-			k = utf8_mbtowc(&ec, iname, iname_end - iname);
+-			if (k < 0)
++			k = utf8_to_utf32(iname, iname_end - iname, &u);
++			if (k < 0 || u > MAX_WCHAR_T)
+ 				return -EINVAL;
+ 			iname += k;
++			ec = u;
+ 		} else {
+ 			if (*iname == NCP_ESC) {
+ 				int k;
+@@ -1214,7 +1216,7 @@ ncp__vol2io(struct ncp_server *server, unsigned char *iname, unsigned int *ilen,
+ 		if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) {
+ 			int k;
+ 
+-			k = utf8_wctomb(iname, ec, iname_end - iname);
++			k = utf32_to_utf8(ec, iname, iname_end - iname);
+ 			if (k < 0) {
+ 				err = -ENAMETOOLONG;
+ 				goto quit;
+diff --git a/fs/nls/nls_base.c b/fs/nls/nls_base.c
+index 750abf211e26..477d37d83b31 100644
+--- a/fs/nls/nls_base.c
++++ b/fs/nls/nls_base.c
+@@ -15,6 +15,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ static struct nls_table default_table;
+ static struct nls_table *tables = &default_table;
+@@ -43,10 +44,17 @@ static const struct utf8_table utf8_table[] =
+     {0,						       /* end of table    */}
+ };
+ 
+-int
+-utf8_mbtowc(wchar_t *p, const __u8 *s, int n)
++#define UNICODE_MAX	0x0010ffff
++#define PLANE_SIZE	0x00010000
++
++#define SURROGATE_MASK	0xfffff800
++#define SURROGATE_PAIR	0x0000d800
++#define SURROGATE_LOW	0x00000400
++#define SURROGATE_BITS	0x000003ff
++
++int utf8_to_utf32(const u8 *s, int len, unicode_t *pu)
+ {
+-	long l;
++	unsigned long l;
+ 	int c0, c, nc;
+ 	const struct utf8_table *t;
+   
+@@ -57,12 +65,13 @@ utf8_mbtowc(wchar_t *p, const __u8 *s, int n)
+ 		nc++;
+ 		if ((c0 & t->cmask) == t->cval) {
+ 			l &= t->lmask;
+-			if (l < t->lval)
++			if (l < t->lval || l > UNICODE_MAX ||
++					(l & SURROGATE_MASK) == SURROGATE_PAIR)
+ 				return -1;
+-			*p = l;
++			*pu = (unicode_t) l;
+ 			return nc;
+ 		}
+-		if (n <= nc)
++		if (len <= nc)
+ 			return -1;
+ 		s++;
+ 		c = (*s ^ 0x80) & 0xFF;
+@@ -72,76 +81,119 @@ utf8_mbtowc(wchar_t *p, const __u8 *s, int n)
+ 	}
+ 	return -1;
+ }
++EXPORT_SYMBOL(utf8_to_utf32);
+ 
+-int
+-utf8_mbstowcs(wchar_t *pwcs, const __u8 *s, int n)
++int utf32_to_utf8(unicode_t u, u8 *s, int maxlen)
+ {
+-	__u16 *op;
+-	const __u8 *ip;
+-	int size;
+-
+-	op = pwcs;
+-	ip = s;
+-	while (*ip && n > 0) {
+-		if (*ip & 0x80) {
+-			size = utf8_mbtowc(op, ip, n);
+-			if (size == -1) {
+-				/* Ignore character and move on */
+-				ip++;
+-				n--;
+-			} else {
+-				op++;
+-				ip += size;
+-				n -= size;
+-			}
+-		} else {
+-			*op++ = *ip++;
+-			n--;
+-		}
+-	}
+-	return (op - pwcs);
+-}
+-
+-int
+-utf8_wctomb(__u8 *s, wchar_t wc, int maxlen)
+-{
+-	long l;
++	unsigned long l;
+ 	int c, nc;
+ 	const struct utf8_table *t;
+-  
++
+ 	if (!s)
+ 		return 0;
+-  
+-	l = wc;
++
++	l = u;
++	if (l > UNICODE_MAX || (l & SURROGATE_MASK) == SURROGATE_PAIR)
++		return -1;
++
+ 	nc = 0;
+ 	for (t = utf8_table; t->cmask && maxlen; t++, maxlen--) {
+ 		nc++;
+ 		if (l <= t->lmask) {
+ 			c = t->shift;
+-			*s = t->cval | (l >> c);
++			*s = (u8) (t->cval | (l >> c));
+ 			while (c > 0) {
+ 				c -= 6;
+ 				s++;
+-				*s = 0x80 | ((l >> c) & 0x3F);
++				*s = (u8) (0x80 | ((l >> c) & 0x3F));
+ 			}
+ 			return nc;
+ 		}
+ 	}
+ 	return -1;
+ }
++EXPORT_SYMBOL(utf32_to_utf8);
+ 
+-int
+-utf8_wcstombs(__u8 *s, const wchar_t *pwcs, int maxlen)
++int utf8s_to_utf16s(const u8 *s, int len, wchar_t *pwcs)
+ {
+-	const __u16 *ip;
+-	__u8 *op;
++	u16 *op;
+ 	int size;
++	unicode_t u;
++
++	op = pwcs;
++	while (*s && len > 0) {
++		if (*s & 0x80) {
++			size = utf8_to_utf32(s, len, &u);
++			if (size < 0) {
++				/* Ignore character and move on */
++				size = 1;
++			} else if (u >= PLANE_SIZE) {
++				u -= PLANE_SIZE;
++				*op++ = (wchar_t) (SURROGATE_PAIR |
++						((u >> 10) & SURROGATE_BITS));
++				*op++ = (wchar_t) (SURROGATE_PAIR |
++						SURROGATE_LOW |
++						(u & SURROGATE_BITS));
++			} else {
++				*op++ = (wchar_t) u;
++			}
++			s += size;
++			len -= size;
++		} else {
++			*op++ = *s++;
++			len--;
++		}
++	}
++	return op - pwcs;
++}
++EXPORT_SYMBOL(utf8s_to_utf16s);
++
++static inline unsigned long get_utf16(unsigned c, enum utf16_endian endian)
++{
++	switch (endian) {
++	default:
++		return c;
++	case UTF16_LITTLE_ENDIAN:
++		return __le16_to_cpu(c);
++	case UTF16_BIG_ENDIAN:
++		return __be16_to_cpu(c);
++	}
++}
++
++int utf16s_to_utf8s(const wchar_t *pwcs, int len, enum utf16_endian endian,
++		u8 *s, int maxlen)
++{
++	u8 *op;
++	int size;
++	unsigned long u, v;
+ 
+ 	op = s;
+-	ip = pwcs;
+-	while (*ip && maxlen > 0) {
+-		if (*ip > 0x7f) {
+-			size = utf8_wctomb(op, *ip, maxlen);
++	while (len > 0 && maxlen > 0) {
++		u = get_utf16(*pwcs, endian);
++		if (!u)
++			break;
++		pwcs++;
++		len--;
++		if (u > 0x7f) {
++			if ((u & SURROGATE_MASK) == SURROGATE_PAIR) {
++				if (u & SURROGATE_LOW) {
++					/* Ignore character and move on */
++					continue;
++				}
++				if (len <= 0)
++					break;
++				v = get_utf16(*pwcs, endian);
++				if ((v & SURROGATE_MASK) != SURROGATE_PAIR ||
++						!(v & SURROGATE_LOW)) {
++					/* Ignore character and move on */
++					continue;
++				}
++				u = PLANE_SIZE + ((u & SURROGATE_BITS) << 10)
++						+ (v & SURROGATE_BITS);
++				pwcs++;
++				len--;
++			}
++			size = utf32_to_utf8(u, op, maxlen);
+ 			if (size == -1) {
+ 				/* Ignore character and move on */
+ 			} else {
+@@ -149,13 +201,13 @@ utf8_wcstombs(__u8 *s, const wchar_t *pwcs, int maxlen)
+ 				maxlen -= size;
+ 			}
+ 		} else {
+-			*op++ = (__u8) *ip;
++			*op++ = (u8) u;
+ 			maxlen--;
+ 		}
+-		ip++;
+ 	}
+-	return (op - s);
++	return op - s;
+ }
++EXPORT_SYMBOL(utf16s_to_utf8s);
+ 
+ int register_nls(struct nls_table * nls)
+ {
+@@ -467,9 +519,5 @@ EXPORT_SYMBOL(unregister_nls);
+ EXPORT_SYMBOL(unload_nls);
+ EXPORT_SYMBOL(load_nls);
+ EXPORT_SYMBOL(load_nls_default);
+-EXPORT_SYMBOL(utf8_mbtowc);
+-EXPORT_SYMBOL(utf8_mbstowcs);
+-EXPORT_SYMBOL(utf8_wctomb);
+-EXPORT_SYMBOL(utf8_wcstombs);
+ 
+ MODULE_LICENSE("Dual BSD/GPL");
+diff --git a/fs/nls/nls_utf8.c b/fs/nls/nls_utf8.c
+index aa2c42fdd977..0d60a44acacd 100644
+--- a/fs/nls/nls_utf8.c
++++ b/fs/nls/nls_utf8.c
+@@ -15,7 +15,11 @@ static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
+ {
+ 	int n;
+ 
+-	if ( (n = utf8_wctomb(out, uni, boundlen)) == -1) {
++	if (boundlen <= 0)
++		return -ENAMETOOLONG;
++
++	n = utf32_to_utf8(uni, out, boundlen);
++	if (n < 0) {
+ 		*out = '?';
+ 		return -EINVAL;
+ 	}
+@@ -25,11 +29,14 @@ static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
+ static int char2uni(const unsigned char *rawstring, int boundlen, wchar_t *uni)
+ {
+ 	int n;
++	unicode_t u;
+ 
+-	if ( (n = utf8_mbtowc(uni, rawstring, boundlen)) == -1) {
++	n = utf8_to_utf32(rawstring, boundlen, &u);
++	if (n < 0 || u > MAX_WCHAR_T) {
+ 		*uni = 0x003f;	/* ? */
+-		n = -EINVAL;
++		return -EINVAL;
+ 	}
++	*uni = (wchar_t) u;
+ 	return n;
+ }
+ 
+diff --git a/include/linux/nls.h b/include/linux/nls.h
+index 52b1a76c1b43..d47beef08dfd 100644
+--- a/include/linux/nls.h
++++ b/include/linux/nls.h
+@@ -3,8 +3,23 @@
+ 
+ #include 
+ 
+-/* unicode character */
+-typedef __u16 wchar_t;
++/* Unicode has changed over the years.  Unicode code points no longer
++ * fit into 16 bits; as of Unicode 5 valid code points range from 0
++ * to 0x10ffff (17 planes, where each plane holds 65536 code points).
++ *
++ * The original decision to represent Unicode characters as 16-bit
++ * wchar_t values is now outdated.  But plane 0 still includes the
++ * most commonly used characters, so we will retain it.  The newer
++ * 32-bit unicode_t type can be used when it is necessary to
++ * represent the full Unicode character set.
++ */
++
++/* Plane-0 Unicode character */
++typedef u16 wchar_t;
++#define MAX_WCHAR_T	0xffff
++
++/* Arbitrary Unicode character */
++typedef u32 unicode_t;
+ 
+ struct nls_table {
+ 	const char *charset;
+@@ -21,6 +36,13 @@ struct nls_table {
+ /* this value hold the maximum octet of charset */
+ #define NLS_MAX_CHARSET_SIZE 6 /* for UTF-8 */
+ 
++/* Byte order for UTF-16 strings */
++enum utf16_endian {
++	UTF16_HOST_ENDIAN,
++	UTF16_LITTLE_ENDIAN,
++	UTF16_BIG_ENDIAN
++};
++
+ /* nls.c */
+ extern int register_nls(struct nls_table *);
+ extern int unregister_nls(struct nls_table *);
+@@ -28,10 +50,11 @@ extern struct nls_table *load_nls(char *);
+ extern void unload_nls(struct nls_table *);
+ extern struct nls_table *load_nls_default(void);
+ 
+-extern int utf8_mbtowc(wchar_t *, const __u8 *, int);
+-extern int utf8_mbstowcs(wchar_t *, const __u8 *, int);
+-extern int utf8_wctomb(__u8 *, wchar_t, int);
+-extern int utf8_wcstombs(__u8 *, const wchar_t *, int);
++extern int utf8_to_utf32(const u8 *s, int len, unicode_t *pu);
++extern int utf32_to_utf8(unicode_t u, u8 *s, int maxlen);
++extern int utf8s_to_utf16s(const u8 *s, int len, wchar_t *pwcs);
++extern int utf16s_to_utf8s(const wchar_t *pwcs, int len,
++		enum utf16_endian endian, u8 *s, int maxlen);
+ 
+ static inline unsigned char nls_tolower(struct nls_table *t, unsigned char c)
+ {

commit 91f8d063d30358fcb76831c238071f7d4b13c35e
+Author: Alan Stern 
+Date:   Thu Apr 16 15:35:09 2009 -0400
+
+    USB: consolidate usb_unbind_interface and usb_driver_release_interface
+    
+    This patch (as1230) consolidates code in usb_unbind_interface() and
+    usb_driver_release_interface().  In fact, it makes release_interface
+    call unbind_interface, thereby removing the need for duplicated code.
+    
+    It works like this: If the interface has already been registered with
+    the driver core when a driver releases it, then the usual driver-core
+    mechanism will call unbind_interface.  If it hasn't been unregistered
+    then we will make the call ourselves.
+    
+    As a nice bonus, drivers now don't have to worry about whether their
+    disconnect method will get called when they release an interface -- it
+    always will.  Previously it would be called only if the interface was
+    registered.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index d0a21a5f8201..c115eed0fdc3 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -385,7 +385,6 @@ void usb_driver_release_interface(struct usb_driver *driver,
+ 					struct usb_interface *iface)
+ {
+ 	struct device *dev = &iface->dev;
+-	struct usb_device *udev = interface_to_usbdev(iface);
+ 
+ 	/* this should never happen, don't release something that's not ours */
+ 	if (!dev->driver || dev->driver != &driver->drvwrap.driver)
+@@ -394,23 +393,19 @@ void usb_driver_release_interface(struct usb_driver *driver,
+ 	/* don't release from within disconnect() */
+ 	if (iface->condition != USB_INTERFACE_BOUND)
+ 		return;
++	iface->condition = USB_INTERFACE_UNBINDING;
+ 
+-	/* don't release if the interface hasn't been added yet */
++	/* Release via the driver core only if the interface
++	 * has already been registered
++	 */
+ 	if (device_is_registered(dev)) {
+-		iface->condition = USB_INTERFACE_UNBINDING;
+ 		device_release_driver(dev);
+ 	} else {
+-		iface->condition = USB_INTERFACE_UNBOUND;
+-		usb_cancel_queued_reset(iface);
++		down(&dev->sem);
++		usb_unbind_interface(dev);
++		dev->driver = NULL;
++		up(&dev->sem);
+ 	}
+-	dev->driver = NULL;
+-	usb_set_intfdata(iface, NULL);
+-
+-	usb_pm_lock(udev);
+-	iface->condition = USB_INTERFACE_UNBOUND;
+-	mark_quiesced(iface);
+-	iface->needs_remote_wakeup = 0;
+-	usb_pm_unlock(udev);
+ }
+ EXPORT_SYMBOL_GPL(usb_driver_release_interface);
+ 

commit d161630297a20802d01c55847bfcba85d2118a9f
+Author: Alan Stern 
+Date:   Sun May 24 22:05:42 2009 +0200
+
+    PM core: rename suspend and resume functions
+    
+    This patch (as1241) renames a bunch of functions in the PM core.
+    Rather than go through a boring list of name changes, suffice it to
+    say that in the end we have a bunch of pairs of functions:
+    
+            device_resume_noirq     dpm_resume_noirq
+            device_resume           dpm_resume
+            device_complete         dpm_complete
+            device_suspend_noirq    dpm_suspend_noirq
+            device_suspend          dpm_suspend
+            device_prepare          dpm_prepare
+    
+    in which device_X does the X operation on a single device and dpm_X
+    invokes device_X for all devices in the dpm_list.
+    
+    In addition, the old dpm_power_up and device_resume_noirq have been
+    combined into a single function (dpm_resume_noirq).
+    
+    Lastly, dpm_suspend_start and dpm_resume_end are the renamed versions
+    of the former top-level device_suspend and device_resume routines.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Magnus Damm 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
+index 31ae547da159..79302e9a33a4 100644
+--- a/arch/x86/kernel/apm_32.c
++++ b/arch/x86/kernel/apm_32.c
+@@ -1233,9 +1233,9 @@ static int suspend(int vetoable)
+ 	int err;
+ 	struct apm_user	*as;
+ 
+-	device_suspend(PMSG_SUSPEND);
++	dpm_suspend_start(PMSG_SUSPEND);
+ 
+-	device_suspend_noirq(PMSG_SUSPEND);
++	dpm_suspend_noirq(PMSG_SUSPEND);
+ 
+ 	local_irq_disable();
+ 	sysdev_suspend(PMSG_SUSPEND);
+@@ -1259,9 +1259,9 @@ static int suspend(int vetoable)
+ 	sysdev_resume();
+ 	local_irq_enable();
+ 
+-	device_resume_noirq(PMSG_RESUME);
++	dpm_resume_noirq(PMSG_RESUME);
+ 
+-	device_resume(PMSG_RESUME);
++	dpm_resume_end(PMSG_RESUME);
+ 	queue_event(APM_NORMAL_RESUME, NULL);
+ 	spin_lock(&user_list_lock);
+ 	for (as = user_list; as != NULL; as = as->next) {
+@@ -1277,7 +1277,7 @@ static void standby(void)
+ {
+ 	int err;
+ 
+-	device_suspend_noirq(PMSG_SUSPEND);
++	dpm_suspend_noirq(PMSG_SUSPEND);
+ 
+ 	local_irq_disable();
+ 	sysdev_suspend(PMSG_SUSPEND);
+@@ -1291,7 +1291,7 @@ static void standby(void)
+ 	sysdev_resume();
+ 	local_irq_enable();
+ 
+-	device_resume_noirq(PMSG_RESUME);
++	dpm_resume_noirq(PMSG_RESUME);
+ }
+ 
+ static apm_event_t get_event(void)
+@@ -1376,7 +1376,7 @@ static void check_events(void)
+ 			ignore_bounce = 1;
+ 			if ((event != APM_NORMAL_RESUME)
+ 			    || (ignore_normal_resume == 0)) {
+-				device_resume(PMSG_RESUME);
++				dpm_resume_end(PMSG_RESUME);
+ 				queue_event(event, NULL);
+ 			}
+ 			ignore_normal_resume = 0;
+diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
+index c5a35bc9d63b..1f3d82260db4 100644
+--- a/drivers/base/power/main.c
++++ b/drivers/base/power/main.c
+@@ -315,13 +315,13 @@ static void pm_dev_err(struct device *dev, pm_message_t state, char *info,
+ /*------------------------- Resume routines -------------------------*/
+ 
+ /**
+- *	__device_resume_noirq - Power on one device (early resume).
++ *	device_resume_noirq - Power on one device (early resume).
+  *	@dev:	Device.
+  *	@state: PM transition of the system being carried out.
+  *
+  *	Must be called with interrupts disabled.
+  */
+-static int __device_resume_noirq(struct device *dev, pm_message_t state)
++static int device_resume_noirq(struct device *dev, pm_message_t state)
+ {
+ 	int error = 0;
+ 
+@@ -344,16 +344,16 @@ static int __device_resume_noirq(struct device *dev, pm_message_t state)
+ }
+ 
+ /**
+- *	dpm_power_up - Power on all regular (non-sysdev) devices.
++ *	dpm_resume_noirq - Power on all regular (non-sysdev) devices.
+  *	@state: PM transition of the system being carried out.
+  *
+- *	Execute the appropriate "noirq resume" callback for all devices marked
+- *	as DPM_OFF_IRQ.
++ *	Call the "noirq" resume handlers for all devices marked as
++ *	DPM_OFF_IRQ and enable device drivers to receive interrupts.
+  *
+  *	Must be called under dpm_list_mtx.  Device drivers should not receive
+  *	interrupts while it's being executed.
+  */
+-static void dpm_power_up(pm_message_t state)
++void dpm_resume_noirq(pm_message_t state)
+ {
+ 	struct device *dev;
+ 
+@@ -363,33 +363,21 @@ static void dpm_power_up(pm_message_t state)
+ 			int error;
+ 
+ 			dev->power.status = DPM_OFF;
+-			error = __device_resume_noirq(dev, state);
++			error = device_resume_noirq(dev, state);
+ 			if (error)
+ 				pm_dev_err(dev, state, " early", error);
+ 		}
+ 	mutex_unlock(&dpm_list_mtx);
+-}
+-
+-/**
+- *	device_resume_noirq - Turn on all devices that need special attention.
+- *	@state: PM transition of the system being carried out.
+- *
+- *	Call the "early" resume handlers and enable device drivers to receive
+- *	interrupts.
+- */
+-void device_resume_noirq(pm_message_t state)
+-{
+-	dpm_power_up(state);
+ 	resume_device_irqs();
+ }
+-EXPORT_SYMBOL_GPL(device_resume_noirq);
++EXPORT_SYMBOL_GPL(dpm_resume_noirq);
+ 
+ /**
+- *	resume_device - Restore state for one device.
++ *	device_resume - Restore state for one device.
+  *	@dev:	Device.
+  *	@state: PM transition of the system being carried out.
+  */
+-static int resume_device(struct device *dev, pm_message_t state)
++static int device_resume(struct device *dev, pm_message_t state)
+ {
+ 	int error = 0;
+ 
+@@ -462,7 +450,7 @@ static void dpm_resume(pm_message_t state)
+ 			dev->power.status = DPM_RESUMING;
+ 			mutex_unlock(&dpm_list_mtx);
+ 
+-			error = resume_device(dev, state);
++			error = device_resume(dev, state);
+ 
+ 			mutex_lock(&dpm_list_mtx);
+ 			if (error)
+@@ -480,11 +468,11 @@ static void dpm_resume(pm_message_t state)
+ }
+ 
+ /**
+- *	complete_device - Complete a PM transition for given device
++ *	device_complete - Complete a PM transition for given device
+  *	@dev:	Device.
+  *	@state: PM transition of the system being carried out.
+  */
+-static void complete_device(struct device *dev, pm_message_t state)
++static void device_complete(struct device *dev, pm_message_t state)
+ {
+ 	down(&dev->sem);
+ 
+@@ -527,7 +515,7 @@ static void dpm_complete(pm_message_t state)
+ 			dev->power.status = DPM_ON;
+ 			mutex_unlock(&dpm_list_mtx);
+ 
+-			complete_device(dev, state);
++			device_complete(dev, state);
+ 
+ 			mutex_lock(&dpm_list_mtx);
+ 		}
+@@ -540,19 +528,19 @@ static void dpm_complete(pm_message_t state)
+ }
+ 
+ /**
+- *	device_resume - Restore state of each device in system.
++ *	dpm_resume_end - Restore state of each device in system.
+  *	@state: PM transition of the system being carried out.
+  *
+  *	Resume all the devices, unlock them all, and allow new
+  *	devices to be registered once again.
+  */
+-void device_resume(pm_message_t state)
++void dpm_resume_end(pm_message_t state)
+ {
+ 	might_sleep();
+ 	dpm_resume(state);
+ 	dpm_complete(state);
+ }
+-EXPORT_SYMBOL_GPL(device_resume);
++EXPORT_SYMBOL_GPL(dpm_resume_end);
+ 
+ 
+ /*------------------------- Suspend routines -------------------------*/
+@@ -577,13 +565,13 @@ static pm_message_t resume_event(pm_message_t sleep_state)
+ }
+ 
+ /**
+- *	__device_suspend_noirq - Shut down one device (late suspend).
++ *	device_suspend_noirq - Shut down one device (late suspend).
+  *	@dev:	Device.
+  *	@state: PM transition of the system being carried out.
+  *
+  *	This is called with interrupts off and only a single CPU running.
+  */
+-static int __device_suspend_noirq(struct device *dev, pm_message_t state)
++static int device_suspend_noirq(struct device *dev, pm_message_t state)
+ {
+ 	int error = 0;
+ 
+@@ -602,15 +590,15 @@ static int __device_suspend_noirq(struct device *dev, pm_message_t state)
+ }
+ 
+ /**
+- *	device_suspend_noirq - Shut down special devices.
++ *	dpm_suspend_noirq - Power down all regular (non-sysdev) devices.
+  *	@state: PM transition of the system being carried out.
+  *
+- *	Prevent device drivers from receiving interrupts and call the "late"
++ *	Prevent device drivers from receiving interrupts and call the "noirq"
+  *	suspend handlers.
+  *
+  *	Must be called under dpm_list_mtx.
+  */
+-int device_suspend_noirq(pm_message_t state)
++int dpm_suspend_noirq(pm_message_t state)
+ {
+ 	struct device *dev;
+ 	int error = 0;
+@@ -618,7 +606,7 @@ int device_suspend_noirq(pm_message_t state)
+ 	suspend_device_irqs();
+ 	mutex_lock(&dpm_list_mtx);
+ 	list_for_each_entry_reverse(dev, &dpm_list, power.entry) {
+-		error = __device_suspend_noirq(dev, state);
++		error = device_suspend_noirq(dev, state);
+ 		if (error) {
+ 			pm_dev_err(dev, state, " late", error);
+ 			break;
+@@ -627,17 +615,17 @@ int device_suspend_noirq(pm_message_t state)
+ 	}
+ 	mutex_unlock(&dpm_list_mtx);
+ 	if (error)
+-		device_resume_noirq(resume_event(state));
++		dpm_resume_noirq(resume_event(state));
+ 	return error;
+ }
+-EXPORT_SYMBOL_GPL(device_suspend_noirq);
++EXPORT_SYMBOL_GPL(dpm_suspend_noirq);
+ 
+ /**
+- *	suspend_device - Save state of one device.
++ *	device_suspend - Save state of one device.
+  *	@dev:	Device.
+  *	@state: PM transition of the system being carried out.
+  */
+-static int suspend_device(struct device *dev, pm_message_t state)
++static int device_suspend(struct device *dev, pm_message_t state)
+ {
+ 	int error = 0;
+ 
+@@ -704,7 +692,7 @@ static int dpm_suspend(pm_message_t state)
+ 		get_device(dev);
+ 		mutex_unlock(&dpm_list_mtx);
+ 
+-		error = suspend_device(dev, state);
++		error = device_suspend(dev, state);
+ 
+ 		mutex_lock(&dpm_list_mtx);
+ 		if (error) {
+@@ -723,11 +711,11 @@ static int dpm_suspend(pm_message_t state)
+ }
+ 
+ /**
+- *	prepare_device - Execute the ->prepare() callback(s) for given device.
++ *	device_prepare - Execute the ->prepare() callback(s) for given device.
+  *	@dev:	Device.
+  *	@state: PM transition of the system being carried out.
+  */
+-static int prepare_device(struct device *dev, pm_message_t state)
++static int device_prepare(struct device *dev, pm_message_t state)
+ {
+ 	int error = 0;
+ 
+@@ -781,7 +769,7 @@ static int dpm_prepare(pm_message_t state)
+ 		dev->power.status = DPM_PREPARING;
+ 		mutex_unlock(&dpm_list_mtx);
+ 
+-		error = prepare_device(dev, state);
++		error = device_prepare(dev, state);
+ 
+ 		mutex_lock(&dpm_list_mtx);
+ 		if (error) {
+@@ -807,12 +795,12 @@ static int dpm_prepare(pm_message_t state)
+ }
+ 
+ /**
+- *	device_suspend - Save state and stop all devices in system.
++ *	dpm_suspend_start - Save state and stop all devices in system.
+  *	@state: PM transition of the system being carried out.
+  *
+  *	Prepare and suspend all devices.
+  */
+-int device_suspend(pm_message_t state)
++int dpm_suspend_start(pm_message_t state)
+ {
+ 	int error;
+ 
+@@ -822,7 +810,7 @@ int device_suspend(pm_message_t state)
+ 		error = dpm_suspend(state);
+ 	return error;
+ }
+-EXPORT_SYMBOL_GPL(device_suspend);
++EXPORT_SYMBOL_GPL(dpm_suspend_start);
+ 
+ void __suspend_report_result(const char *function, void *fn, int ret)
+ {
+diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
+index d5b327ac4039..10d03d7931c4 100644
+--- a/drivers/xen/manage.c
++++ b/drivers/xen/manage.c
+@@ -43,7 +43,7 @@ static int xen_suspend(void *data)
+ 	if (err) {
+ 		printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n",
+ 			err);
+-		device_resume_noirq(PMSG_RESUME);
++		dpm_resume_noirq(PMSG_RESUME);
+ 		return err;
+ 	}
+ 
+@@ -69,7 +69,7 @@ static int xen_suspend(void *data)
+ 	}
+ 
+ 	sysdev_resume();
+-	device_resume_noirq(PMSG_RESUME);
++	dpm_resume_noirq(PMSG_RESUME);
+ 
+ 	return 0;
+ }
+@@ -92,18 +92,18 @@ static void do_suspend(void)
+ 	}
+ #endif
+ 
+-	err = device_suspend(PMSG_SUSPEND);
++	err = dpm_suspend_start(PMSG_SUSPEND);
+ 	if (err) {
+-		printk(KERN_ERR "xen suspend: device_suspend %d\n", err);
++		printk(KERN_ERR "xen suspend: dpm_suspend_start %d\n", err);
+ 		goto out;
+ 	}
+ 
+ 	printk(KERN_DEBUG "suspending xenstore...\n");
+ 	xs_suspend();
+ 
+-	err = device_suspend_noirq(PMSG_SUSPEND);
++	err = dpm_suspend_noirq(PMSG_SUSPEND);
+ 	if (err) {
+-		printk(KERN_ERR "device_suspend_noirq failed: %d\n", err);
++		printk(KERN_ERR "dpm_suspend_noirq failed: %d\n", err);
+ 		goto resume_devices;
+ 	}
+ 
+@@ -119,10 +119,10 @@ static void do_suspend(void)
+ 	} else
+ 		xs_suspend_cancel();
+ 
+-	device_resume_noirq(PMSG_RESUME);
++	dpm_resume_noirq(PMSG_RESUME);
+ 
+ resume_devices:
+-	device_resume(PMSG_RESUME);
++	dpm_resume_end(PMSG_RESUME);
+ 
+ 	/* Make sure timer events get retriggered on all CPUs */
+ 	clock_was_set();
+diff --git a/include/linux/pm.h b/include/linux/pm.h
+index 2170252074f3..b3f74764a586 100644
+--- a/include/linux/pm.h
++++ b/include/linux/pm.h
+@@ -382,14 +382,13 @@ struct dev_pm_info {
+ #ifdef CONFIG_PM_SLEEP
+ extern void device_pm_lock(void);
+ extern int sysdev_resume(void);
+-extern void device_resume_noirq(pm_message_t state);
+-extern void device_resume(pm_message_t state);
++extern void dpm_resume_noirq(pm_message_t state);
++extern void dpm_resume_end(pm_message_t state);
+ 
+ extern void device_pm_unlock(void);
+ extern int sysdev_suspend(pm_message_t state);
+-extern int device_suspend_noirq(pm_message_t state);
+-extern int device_suspend(pm_message_t state);
+-extern int device_prepare_suspend(pm_message_t state);
++extern int dpm_suspend_noirq(pm_message_t state);
++extern int dpm_suspend_start(pm_message_t state);
+ 
+ extern void __suspend_report_result(const char *function, void *fn, int ret);
+ 
+@@ -403,7 +402,7 @@ extern void __suspend_report_result(const char *function, void *fn, int ret);
+ #define device_pm_lock() do {} while (0)
+ #define device_pm_unlock() do {} while (0)
+ 
+-static inline int device_suspend(pm_message_t state)
++static inline int dpm_suspend_start(pm_message_t state)
+ {
+ 	return 0;
+ }
+diff --git a/kernel/kexec.c b/kernel/kexec.c
+index 5a3da87adae0..ae1c35201cc8 100644
+--- a/kernel/kexec.c
++++ b/kernel/kexec.c
+@@ -1448,17 +1448,17 @@ int kernel_kexec(void)
+ 			goto Restore_console;
+ 		}
+ 		suspend_console();
+-		error = device_suspend(PMSG_FREEZE);
++		error = dpm_suspend_start(PMSG_FREEZE);
+ 		if (error)
+ 			goto Resume_console;
+-		/* At this point, device_suspend() has been called,
+-		 * but *not* device_suspend_noirq(). We *must* call
+-		 * device_suspend_noirq() now.  Otherwise, drivers for
++		/* At this point, dpm_suspend_start() has been called,
++		 * but *not* dpm_suspend_noirq(). We *must* call
++		 * dpm_suspend_noirq() now.  Otherwise, drivers for
+ 		 * some devices (e.g. interrupt controllers) become
+ 		 * desynchronized with the actual state of the
+ 		 * hardware at resume time, and evil weirdness ensues.
+ 		 */
+-		error = device_suspend_noirq(PMSG_FREEZE);
++		error = dpm_suspend_noirq(PMSG_FREEZE);
+ 		if (error)
+ 			goto Resume_devices;
+ 		error = disable_nonboot_cpus();
+@@ -1486,9 +1486,9 @@ int kernel_kexec(void)
+ 		local_irq_enable();
+  Enable_cpus:
+ 		enable_nonboot_cpus();
+-		device_resume_noirq(PMSG_RESTORE);
++		dpm_resume_noirq(PMSG_RESTORE);
+  Resume_devices:
+-		device_resume(PMSG_RESTORE);
++		dpm_resume_end(PMSG_RESTORE);
+  Resume_console:
+ 		resume_console();
+ 		thaw_processes();
+diff --git a/kernel/power/disk.c b/kernel/power/disk.c
+index 1c18bc894a2d..a9beba68b6c7 100644
+--- a/kernel/power/disk.c
++++ b/kernel/power/disk.c
+@@ -215,13 +215,13 @@ static int create_image(int platform_mode)
+ 	if (error)
+ 		return error;
+ 
+-	/* At this point, device_suspend() has been called, but *not*
+-	 * device_suspend_noirq(). We *must* call device_suspend_noirq() now.
++	/* At this point, dpm_suspend_start() has been called, but *not*
++	 * dpm_suspend_noirq(). We *must* call dpm_suspend_noirq() now.
+ 	 * Otherwise, drivers for some devices (e.g. interrupt controllers)
+ 	 * become desynchronized with the actual state of the hardware
+ 	 * at resume time, and evil weirdness ensues.
+ 	 */
+-	error = device_suspend_noirq(PMSG_FREEZE);
++	error = dpm_suspend_noirq(PMSG_FREEZE);
+ 	if (error) {
+ 		printk(KERN_ERR "PM: Some devices failed to power down, "
+ 			"aborting hibernation\n");
+@@ -262,7 +262,7 @@ static int create_image(int platform_mode)
+ 
+  Power_up:
+ 	sysdev_resume();
+-	/* NOTE:  device_resume_noirq() is just a resume() for devices
++	/* NOTE:  dpm_resume_noirq() is just a resume() for devices
+ 	 * that suspended with irqs off ... no overall powerup.
+ 	 */
+ 
+@@ -275,7 +275,7 @@ static int create_image(int platform_mode)
+  Platform_finish:
+ 	platform_finish(platform_mode);
+ 
+-	device_resume_noirq(in_suspend ?
++	dpm_resume_noirq(in_suspend ?
+ 		(error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
+ 
+ 	return error;
+@@ -304,7 +304,7 @@ int hibernation_snapshot(int platform_mode)
+ 		goto Close;
+ 
+ 	suspend_console();
+-	error = device_suspend(PMSG_FREEZE);
++	error = dpm_suspend_start(PMSG_FREEZE);
+ 	if (error)
+ 		goto Recover_platform;
+ 
+@@ -315,7 +315,7 @@ int hibernation_snapshot(int platform_mode)
+ 	/* Control returns here after successful restore */
+ 
+  Resume_devices:
+-	device_resume(in_suspend ?
++	dpm_resume_end(in_suspend ?
+ 		(error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
+ 	resume_console();
+  Close:
+@@ -339,7 +339,7 @@ static int resume_target_kernel(bool platform_mode)
+ {
+ 	int error;
+ 
+-	error = device_suspend_noirq(PMSG_QUIESCE);
++	error = dpm_suspend_noirq(PMSG_QUIESCE);
+ 	if (error) {
+ 		printk(KERN_ERR "PM: Some devices failed to power down, "
+ 			"aborting resume\n");
+@@ -394,7 +394,7 @@ static int resume_target_kernel(bool platform_mode)
+  Cleanup:
+ 	platform_restore_cleanup(platform_mode);
+ 
+-	device_resume_noirq(PMSG_RECOVER);
++	dpm_resume_noirq(PMSG_RECOVER);
+ 
+ 	return error;
+ }
+@@ -414,10 +414,10 @@ int hibernation_restore(int platform_mode)
+ 
+ 	pm_prepare_console();
+ 	suspend_console();
+-	error = device_suspend(PMSG_QUIESCE);
++	error = dpm_suspend_start(PMSG_QUIESCE);
+ 	if (!error) {
+ 		error = resume_target_kernel(platform_mode);
+-		device_resume(PMSG_RECOVER);
++		dpm_resume_end(PMSG_RECOVER);
+ 	}
+ 	resume_console();
+ 	pm_restore_console();
+@@ -447,14 +447,14 @@ int hibernation_platform_enter(void)
+ 
+ 	entering_platform_hibernation = true;
+ 	suspend_console();
+-	error = device_suspend(PMSG_HIBERNATE);
++	error = dpm_suspend_start(PMSG_HIBERNATE);
+ 	if (error) {
+ 		if (hibernation_ops->recover)
+ 			hibernation_ops->recover();
+ 		goto Resume_devices;
+ 	}
+ 
+-	error = device_suspend_noirq(PMSG_HIBERNATE);
++	error = dpm_suspend_noirq(PMSG_HIBERNATE);
+ 	if (error)
+ 		goto Resume_devices;
+ 
+@@ -479,11 +479,11 @@ int hibernation_platform_enter(void)
+  Platofrm_finish:
+ 	hibernation_ops->finish();
+ 
+-	device_suspend_noirq(PMSG_RESTORE);
++	dpm_suspend_noirq(PMSG_RESTORE);
+ 
+  Resume_devices:
+ 	entering_platform_hibernation = false;
+-	device_resume(PMSG_RESTORE);
++	dpm_resume_end(PMSG_RESTORE);
+ 	resume_console();
+ 
+  Close:
+diff --git a/kernel/power/main.c b/kernel/power/main.c
+index 2f6638ee03c0..46386b9f8dd1 100644
+--- a/kernel/power/main.c
++++ b/kernel/power/main.c
+@@ -295,7 +295,7 @@ static int suspend_enter(suspend_state_t state)
+ 			return error;
+ 	}
+ 
+-	error = device_suspend_noirq(PMSG_SUSPEND);
++	error = dpm_suspend_noirq(PMSG_SUSPEND);
+ 	if (error) {
+ 		printk(KERN_ERR "PM: Some devices failed to power down\n");
+ 		goto Platfrom_finish;
+@@ -335,7 +335,7 @@ static int suspend_enter(suspend_state_t state)
+ 		suspend_ops->wake();
+ 
+  Power_up_devices:
+-	device_resume_noirq(PMSG_RESUME);
++	dpm_resume_noirq(PMSG_RESUME);
+ 
+  Platfrom_finish:
+ 	if (suspend_ops->finish)
+@@ -363,7 +363,7 @@ int suspend_devices_and_enter(suspend_state_t state)
+ 	}
+ 	suspend_console();
+ 	suspend_test_start();
+-	error = device_suspend(PMSG_SUSPEND);
++	error = dpm_suspend_start(PMSG_SUSPEND);
+ 	if (error) {
+ 		printk(KERN_ERR "PM: Some devices failed to suspend\n");
+ 		goto Recover_platform;
+@@ -376,7 +376,7 @@ int suspend_devices_and_enter(suspend_state_t state)
+ 
+  Resume_devices:
+ 	suspend_test_start();
+-	device_resume(PMSG_RESUME);
++	dpm_resume_end(PMSG_RESUME);
+ 	suspend_test_finish("resume devices");
+ 	resume_console();
+  Close:

commit 0a3c8549ea7e94d74a41096d42bc6cdf43d183bf
+Author: Alan Stern 
+Date:   Wed May 27 11:25:52 2009 -0400
+
+    usb-serial: fix crash when sub-driver updates firmware
+    
+    This patch (as1244) fixes a crash in usb-serial that occurs when a
+    sub-driver returns a positive value from its attach method, indicating
+    that new firmware was loaded and the device will disconnect and
+    reconnect.  The usb-serial core then skips the step of registering the
+    port devices; when the disconnect occurs, the attempt to unregister
+    the ports fails dramatically.
+    
+    This problem shows up with Keyspan devices and it might affect others
+    as well.
+    
+    When the attach method returns a positive value, the patch sets
+    num_ports to 0.  This tells usb_serial_disconnect() not to try
+    unregistering any of the ports; instead they are cleaned up by
+    destroy_serial().
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Benjamin Herrenschmidt 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
+index 0a566eea49c0..f331e2bde88a 100644
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -974,6 +974,7 @@ int usb_serial_probe(struct usb_interface *interface,
+ 		if (retval > 0) {
+ 			/* quietly accept this device, but don't bind to a
+ 			   serial port as it's about to disappear */
++			serial->num_ports = 0;
+ 			goto exit;
+ 		}
+ 	}

commit 14faf12f7df8404c3e8e54baad8d178c327a2f87
+Author: Alan Stern 
+Date:   Thu Mar 12 11:08:51 2009 -0400
+
+    [SCSI] Increase default timeout for INQUIRY
+    
+    This patch (as1224) changes the default timeout for INQUIRY commands
+    from 3 seconds to 20 seconds, which is the value used by Windows for
+    USB Mass-Storage devices.  Some of these devices, like the Corsair
+    Flash Voyager (see Bugzilla #12188) really do need a long timeout.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+index e2b50d8f57a8..c44783801402 100644
+--- a/drivers/scsi/scsi_scan.c
++++ b/drivers/scsi/scsi_scan.c
+@@ -115,12 +115,12 @@ MODULE_PARM_DESC(max_report_luns,
+ 		 "REPORT LUNS maximum number of LUNS received (should be"
+ 		 " between 1 and 16384)");
+ 
+-static unsigned int scsi_inq_timeout = SCSI_TIMEOUT/HZ+3;
++static unsigned int scsi_inq_timeout = SCSI_TIMEOUT/HZ + 18;
+ 
+ module_param_named(inq_timeout, scsi_inq_timeout, uint, S_IRUGO|S_IWUSR);
+ MODULE_PARM_DESC(inq_timeout, 
+ 		 "Timeout (in seconds) waiting for devices to answer INQUIRY."
+-		 " Default is 5. Some non-compliant devices need more.");
++		 " Default is 20. Some devices may need more; most need less.");
+ 
+ /* This lock protects only this list */
+ static DEFINE_SPINLOCK(async_scan_lock);

commit b820aabf6cb987fd03d85b0b5f599685051e0426
+Author: Alan Stern 
+Date:   Wed May 6 15:48:49 2009 -0400
+
+    HID: add NOGET quirk for devices from CH Products
+    
+    This patch (as1240) adds the NOGET quirk for three devices from CH
+    Products: the Pro pedals, the Combatstick joystick, and the Flight-Sim
+    yoke.  Without these quirks, the devices haven't worked for many
+    kernel releases.  Sometimes replugging them after boot-up would get
+    them to work and sometimes they wouldn't work at all.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Sean Hildebrand 
+    Reported-by: Sid Boyce 
+    Tested-by: Sean Hildebrand 
+    Tested-by: Sid Boyce 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
+index aa1b995dd033..4d5ee2bbc62b 100644
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -113,6 +113,11 @@
+ #define USB_VENDOR_ID_BERKSHIRE		0x0c98
+ #define USB_DEVICE_ID_BERKSHIRE_PCWD	0x1140
+ 
++#define USB_VENDOR_ID_CH		0x068e
++#define USB_DEVICE_ID_CH_PRO_PEDALS	0x00f2
++#define USB_DEVICE_ID_CH_COMBATSTICK	0x00f4
++#define USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE	0x00ff
++
+ #define USB_VENDOR_ID_CHERRY		0x046a
+ #define USB_DEVICE_ID_CHERRY_CYMOTION	0x0023
+ 
+diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
+index 4391717d2519..d8f7423f363e 100644
+--- a/drivers/hid/usbhid/hid-quirks.c
++++ b/drivers/hid/usbhid/hid-quirks.c
+@@ -50,6 +50,9 @@ static const struct hid_blacklist {
+ 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
++	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_COMBATSTICK, HID_QUIRK_NOGET },
++	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE, HID_QUIRK_NOGET },
++	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_PEDALS, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },

commit c45d63202fbaccef7ef7946c03f27f72c809b1cc
+Author: Alan Stern 
+Date:   Thu Apr 30 10:06:19 2009 -0400
+
+    usb-serial: ftdi_sio: fix reference counting of ftdi_private
+    
+    This patch (as1238) adds proper reference counting for ftdi_sio's
+    private data structure.  Without it, the driver will free the
+    structure while it is still in use if the user unplugs the serial
+    device before closing the device file.
+    
+    The patch also replaces a slightly dangerous
+    cancel_delayed_work/flush_scheduled_work pair with
+    cancel_delayed_work_sync, which is always safer.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Daniel Mack 
+    Tested-by: Daniel Mack 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
+index aab567644b99..0ab8474b00cb 100644
+--- a/drivers/usb/serial/ftdi_sio.c
++++ b/drivers/usb/serial/ftdi_sio.c
+@@ -56,6 +56,7 @@ static __u16 vendor = FTDI_VID;
+ static __u16 product;
+ 
+ struct ftdi_private {
++	struct kref kref;
+ 	ftdi_chip_type_t chip_type;
+ 				/* type of device, either SIO or FT8U232AM */
+ 	int baud_base;		/* baud base clock for divisor setting */
+@@ -1354,6 +1355,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
+ 		return -ENOMEM;
+ 	}
+ 
++	kref_init(&priv->kref);
+ 	spin_lock_init(&priv->rx_lock);
+ 	spin_lock_init(&priv->tx_lock);
+ 	init_waitqueue_head(&priv->delta_msr_wait);
+@@ -1470,6 +1472,13 @@ static void ftdi_shutdown(struct usb_serial *serial)
+ 	dbg("%s", __func__);
+ }
+ 
++static void ftdi_sio_priv_release(struct kref *k)
++{
++	struct ftdi_private *priv = container_of(k, struct ftdi_private, kref);
++
++	kfree(priv);
++}
++
+ static int ftdi_sio_port_remove(struct usb_serial_port *port)
+ {
+ 	struct ftdi_private *priv = usb_get_serial_port_data(port);
+@@ -1484,7 +1493,7 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port)
+ 
+ 	if (priv) {
+ 		usb_set_serial_port_data(port, NULL);
+-		kfree(priv);
++		kref_put(&priv->kref, ftdi_sio_priv_release);
+ 	}
+ 
+ 	return 0;
+@@ -1549,7 +1558,8 @@ static int ftdi_open(struct tty_struct *tty,
+ 		dev_err(&port->dev,
+ 			"%s - failed submitting read urb, error %d\n",
+ 			__func__, result);
+-
++	else
++		kref_get(&priv->kref);
+ 
+ 	return result;
+ } /* ftdi_open */
+@@ -1591,11 +1601,11 @@ static void ftdi_close(struct tty_struct *tty,
+ 	mutex_unlock(&port->serial->disc_mutex);
+ 
+ 	/* cancel any scheduled reading */
+-	cancel_delayed_work(&priv->rx_work);
+-	flush_scheduled_work();
++	cancel_delayed_work_sync(&priv->rx_work);
+ 
+ 	/* shutdown our bulk read */
+ 	usb_kill_urb(port->read_urb);
++	kref_put(&priv->kref, ftdi_sio_priv_release);
+ } /* ftdi_close */
+ 
+ 

commit 0f43158caddcbb110916212ebe4e39993ae70864
+Author: Alan Stern 
+Date:   Mon Apr 27 13:22:40 2009 -0400
+
+    USB: Gadget: fix UTF conversion in the usbstring library
+    
+    This patch (as1234) fixes a bug in the UTF8 -> UTF-16 conversion
+    routine in the gadget/usbstring library.  In a UTF-8 multi-byte
+    sequence, all bytes after the first should have their high-order
+    two bits set to 10, not 11.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: David Brownell 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/usbstring.c b/drivers/usb/gadget/usbstring.c
+index 4154be375c7a..58c4d37d312a 100644
+--- a/drivers/usb/gadget/usbstring.c
++++ b/drivers/usb/gadget/usbstring.c
+@@ -38,7 +38,7 @@ static int utf8_to_utf16le(const char *s, __le16 *cp, unsigned len)
+ 				uchar = (c & 0x1f) << 6;
+ 
+ 				c = (u8) *s++;
+-				if ((c & 0xc0) != 0xc0)
++				if ((c & 0xc0) != 0x80)
+ 					goto fail;
+ 				c &= 0x3f;
+ 				uchar |= c;
+@@ -49,13 +49,13 @@ static int utf8_to_utf16le(const char *s, __le16 *cp, unsigned len)
+ 				uchar = (c & 0x0f) << 12;
+ 
+ 				c = (u8) *s++;
+-				if ((c & 0xc0) != 0xc0)
++				if ((c & 0xc0) != 0x80)
+ 					goto fail;
+ 				c &= 0x3f;
+ 				uchar |= c << 6;
+ 
+ 				c = (u8) *s++;
+-				if ((c & 0xc0) != 0xc0)
++				if ((c & 0xc0) != 0x80)
+ 					goto fail;
+ 				c &= 0x3f;
+ 				uchar |= c;

commit 82a10a81c853be3859b3d222db0f372ee8d2eaa2
+Author: Alan Stern 
+Date:   Thu Apr 16 15:37:28 2009 -0400
+
+    USB: g_file_storage: fix use-after-free bug when closing files
+    
+    This patch (as1231) fixes a use-after-free bug in g_file_storage.  A
+    device's name may not be available after the device is unregistered,
+    even if the device structure itself is still allocated.  Since
+    close_backing_file() prints a LUN's name for debugging, it shouldn't
+    be called after the LUN has been unregistered.
+    
+    That whole area needed to be cleaned up; the backing files were
+    getting closed in a couple of different places.  The patch fixes
+    things so that they get closed in just one place, as part of the
+    unbind procedure, immediately before the LUN is unregistered.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index 5c030b080d4c..381a53b3e11c 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -738,7 +738,6 @@ static struct fsg_dev			*the_fsg;
+ static struct usb_gadget_driver		fsg_driver;
+ 
+ static void	close_backing_file(struct lun *curlun);
+-static void	close_all_backing_files(struct fsg_dev *fsg);
+ 
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -3593,12 +3592,10 @@ static int fsg_main_thread(void *fsg_)
+ 	fsg->thread_task = NULL;
+ 	spin_unlock_irq(&fsg->lock);
+ 
+-	/* In case we are exiting because of a signal, unregister the
+-	 * gadget driver and close the backing file. */
+-	if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags)) {
++	/* If we are exiting because of a signal, unregister the
++	 * gadget driver. */
++	if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags))
+ 		usb_gadget_unregister_driver(&fsg_driver);
+-		close_all_backing_files(fsg);
+-	}
+ 
+ 	/* Let the unbind and cleanup routines know the thread has exited */
+ 	complete_and_exit(&fsg->thread_notifier, 0);
+@@ -3703,14 +3700,6 @@ static void close_backing_file(struct lun *curlun)
+ 	}
+ }
+ 
+-static void close_all_backing_files(struct fsg_dev *fsg)
+-{
+-	int	i;
+-
+-	for (i = 0; i < fsg->nluns; ++i)
+-		close_backing_file(&fsg->luns[i]);
+-}
+-
+ 
+ static ssize_t show_ro(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+@@ -3845,6 +3834,7 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)
+ 		if (curlun->registered) {
+ 			device_remove_file(&curlun->dev, &dev_attr_ro);
+ 			device_remove_file(&curlun->dev, &dev_attr_file);
++			close_backing_file(curlun);
+ 			device_unregister(&curlun->dev);
+ 			curlun->registered = 0;
+ 		}
+@@ -4190,7 +4180,6 @@ static int __init fsg_bind(struct usb_gadget *gadget)
+ out:
+ 	fsg->state = FSG_STATE_TERMINATED;	// The thread is dead
+ 	fsg_unbind(gadget);
+-	close_all_backing_files(fsg);
+ 	complete(&fsg->thread_notifier);
+ 	return rc;
+ }
+@@ -4284,7 +4273,6 @@ static void __exit fsg_cleanup(void)
+ 	/* Wait for the thread to finish up */
+ 	wait_for_completion(&fsg->thread_notifier);
+ 
+-	close_all_backing_files(fsg);
+ 	kref_put(&fsg->ref, fsg_release);
+ }
+ module_exit(fsg_cleanup);

commit 2d93148ab6988cad872e65d694c95e8944e1b626
+Author: Alan Stern 
+Date:   Tue Apr 14 11:31:02 2009 -0400
+
+    USB: serial: fix lifetime and locking problems
+    
+    This patch (as1229) fixes a few lifetime and locking problems in the
+    usb-serial driver.  The main symptom is that an invalid kevent is
+    created when the serial device is unplugged while a connection is
+    active.
+    
+            Ports should be unregistered when device is disconnected,
+            not when the parent usb_serial structure is deallocated.
+    
+            Each open file should hold a reference to the corresponding
+            port structure, and the reference should be released when
+            the file is closed.
+    
+            serial->disc_mutex should be acquired in serial_open(), to
+            resolve the classic race between open and disconnect.
+    
+            serial_close() doesn't need to hold both serial->disc_mutex
+            and port->mutex at the same time.
+    
+            Release the subdriver's module reference only after releasing
+            all the other references, in case one of the release routines
+            needs to invoke some code in the subdriver module.
+    
+            Replace a call to flush_scheduled_work() (which is prone to
+            deadlocks) with cancel_work_sync().  Also, add a call to
+            cancel_work_sync() in the disconnect routine.
+    
+            Reduce the scope of serial->disc_mutex in serial_disconnect().
+            The only place it really needs to protect is where the
+            "disconnected" flag is set.
+    
+    This fixes the bug reported in
+    
+            http://bugs.freedesktop.org/show_bug.cgi?id=20703
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Dan Williams 
+    Tested-by: Ming Lei 
+    Reviewed-by: Oliver Neukum 
+    Acked-by: Alan Cox 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
+index 2a70563bbee1..0a566eea49c0 100644
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -137,22 +137,10 @@ static void destroy_serial(struct kref *kref)
+ 
+ 	dbg("%s - %s", __func__, serial->type->description);
+ 
+-	serial->type->shutdown(serial);
+-
+ 	/* return the minor range that this device had */
+ 	if (serial->minor != SERIAL_TTY_NO_MINOR)
+ 		return_serial(serial);
+ 
+-	for (i = 0; i < serial->num_ports; ++i)
+-		serial->port[i]->port.count = 0;
+-
+-	/* the ports are cleaned up and released in port_release() */
+-	for (i = 0; i < serial->num_ports; ++i)
+-		if (serial->port[i]->dev.parent != NULL) {
+-			device_unregister(&serial->port[i]->dev);
+-			serial->port[i] = NULL;
+-		}
+-
+ 	/* If this is a "fake" port, we have to clean it up here, as it will
+ 	 * not get cleaned up in port_release() as it was never registered with
+ 	 * the driver core */
+@@ -187,7 +175,7 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
+ 	struct usb_serial *serial;
+ 	struct usb_serial_port *port;
+ 	unsigned int portNumber;
+-	int retval;
++	int retval = 0;
+ 
+ 	dbg("%s", __func__);
+ 
+@@ -198,21 +186,24 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
+ 		return -ENODEV;
+ 	}
+ 
++	mutex_lock(&serial->disc_mutex);
+ 	portNumber = tty->index - serial->minor;
+ 	port = serial->port[portNumber];
+-	if (!port) {
+-		retval = -ENODEV;
+-		goto bailout_kref_put;
+-	}
+-
+-	if (port->serial->disconnected) {
++	if (!port || serial->disconnected)
+ 		retval = -ENODEV;
+-		goto bailout_kref_put;
+-	}
++	else
++		get_device(&port->dev);
++	/*
++	 * Note: Our locking order requirement does not allow port->mutex
++	 * to be acquired while serial->disc_mutex is held.
++	 */
++	mutex_unlock(&serial->disc_mutex);
++	if (retval)
++		goto bailout_serial_put;
+ 
+ 	if (mutex_lock_interruptible(&port->mutex)) {
+ 		retval = -ERESTARTSYS;
+-		goto bailout_kref_put;
++		goto bailout_port_put;
+ 	}
+ 
+ 	++port->port.count;
+@@ -232,14 +223,20 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
+ 			goto bailout_mutex_unlock;
+ 		}
+ 
+-		retval = usb_autopm_get_interface(serial->interface);
++		mutex_lock(&serial->disc_mutex);
++		if (serial->disconnected)
++			retval = -ENODEV;
++		else
++			retval = usb_autopm_get_interface(serial->interface);
+ 		if (retval)
+ 			goto bailout_module_put;
++
+ 		/* only call the device specific open if this
+ 		 * is the first time the port is opened */
+ 		retval = serial->type->open(tty, port, filp);
+ 		if (retval)
+ 			goto bailout_interface_put;
++		mutex_unlock(&serial->disc_mutex);
+ 	}
+ 
+ 	mutex_unlock(&port->mutex);
+@@ -248,13 +245,16 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
+ bailout_interface_put:
+ 	usb_autopm_put_interface(serial->interface);
+ bailout_module_put:
++	mutex_unlock(&serial->disc_mutex);
+ 	module_put(serial->type->driver.owner);
+ bailout_mutex_unlock:
+ 	port->port.count = 0;
+ 	tty->driver_data = NULL;
+ 	tty_port_tty_set(&port->port, NULL);
+ 	mutex_unlock(&port->mutex);
+-bailout_kref_put:
++bailout_port_put:
++	put_device(&port->dev);
++bailout_serial_put:
+ 	usb_serial_put(serial);
+ 	return retval;
+ }
+@@ -262,6 +262,9 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
+ static void serial_close(struct tty_struct *tty, struct file *filp)
+ {
+ 	struct usb_serial_port *port = tty->driver_data;
++	struct usb_serial *serial;
++	struct module *owner;
++	int count;
+ 
+ 	if (!port)
+ 		return;
+@@ -269,6 +272,8 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
+ 	dbg("%s - port %d", __func__, port->number);
+ 
+ 	mutex_lock(&port->mutex);
++	serial = port->serial;
++	owner = serial->type->driver.owner;
+ 
+ 	if (port->port.count == 0) {
+ 		mutex_unlock(&port->mutex);
+@@ -281,7 +286,7 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
+ 		 * this before we drop the port count. The call is protected
+ 		 * by the port mutex
+ 		 */
+-		port->serial->type->close(tty, port, filp);
++		serial->type->close(tty, port, filp);
+ 
+ 	if (port->port.count == (port->console ? 2 : 1)) {
+ 		struct tty_struct *tty = tty_port_tty_get(&port->port);
+@@ -295,17 +300,23 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
+ 		}
+ 	}
+ 
+-	if (port->port.count == 1) {
+-		mutex_lock(&port->serial->disc_mutex);
+-		if (!port->serial->disconnected)
+-			usb_autopm_put_interface(port->serial->interface);
+-		mutex_unlock(&port->serial->disc_mutex);
+-		module_put(port->serial->type->driver.owner);
+-	}
+ 	--port->port.count;
+-
++	count = port->port.count;
+ 	mutex_unlock(&port->mutex);
+-	usb_serial_put(port->serial);
++	put_device(&port->dev);
++
++	/* Mustn't dereference port any more */
++	if (count == 0) {
++		mutex_lock(&serial->disc_mutex);
++		if (!serial->disconnected)
++			usb_autopm_put_interface(serial->interface);
++		mutex_unlock(&serial->disc_mutex);
++	}
++	usb_serial_put(serial);
++
++	/* Mustn't dereference serial any more */
++	if (count == 0)
++		module_put(owner);
+ }
+ 
+ static int serial_write(struct tty_struct *tty, const unsigned char *buf,
+@@ -549,7 +560,13 @@ static void kill_traffic(struct usb_serial_port *port)
+ 
+ static void port_free(struct usb_serial_port *port)
+ {
++	/*
++	 * Stop all the traffic before cancelling the work, so that
++	 * nobody will restart it by calling usb_serial_port_softint.
++	 */
+ 	kill_traffic(port);
++	cancel_work_sync(&port->work);
++
+ 	usb_free_urb(port->read_urb);
+ 	usb_free_urb(port->write_urb);
+ 	usb_free_urb(port->interrupt_in_urb);
+@@ -558,7 +575,6 @@ static void port_free(struct usb_serial_port *port)
+ 	kfree(port->bulk_out_buffer);
+ 	kfree(port->interrupt_in_buffer);
+ 	kfree(port->interrupt_out_buffer);
+-	flush_scheduled_work();		/* port->work */
+ 	kfree(port);
+ }
+ 
+@@ -1043,6 +1059,12 @@ void usb_serial_disconnect(struct usb_interface *interface)
+ 	usb_set_intfdata(interface, NULL);
+ 	/* must set a flag, to signal subdrivers */
+ 	serial->disconnected = 1;
++	mutex_unlock(&serial->disc_mutex);
++
++	/* Unfortunately, many of the sub-drivers expect the port structures
++	 * to exist when their shutdown method is called, so we have to go
++	 * through this awkward two-step unregistration procedure.
++	 */
+ 	for (i = 0; i < serial->num_ports; ++i) {
+ 		port = serial->port[i];
+ 		if (port) {
+@@ -1052,11 +1074,21 @@ void usb_serial_disconnect(struct usb_interface *interface)
+ 				tty_kref_put(tty);
+ 			}
+ 			kill_traffic(port);
++			cancel_work_sync(&port->work);
++			device_del(&port->dev);
++		}
++	}
++	serial->type->shutdown(serial);
++	for (i = 0; i < serial->num_ports; ++i) {
++		port = serial->port[i];
++		if (port) {
++			put_device(&port->dev);
++			serial->port[i] = NULL;
+ 		}
+ 	}
++
+ 	/* let the last holder of this object
+ 	 * cause it to be cleaned up */
+-	mutex_unlock(&serial->disc_mutex);
+ 	usb_serial_put(serial);
+ 	dev_info(dev, "device disconnected\n");
+ }

commit dfc15e8955338fedf5c5d15622c4042c1e4ee332
+Author: Alan Stern 
+Date:   Thu Apr 9 14:59:44 2009 -0400
+
+    usb-storage: fix mistake in Makefile
+    
+    This patch (as1228) fixes a Makefile error introduced when the
+    subdrivers in usb-storage were split out into separate modules.  The
+    intention is that when CONFIG_USB_LIBUSUAL is set, libusual.o and
+    usual-tables.o should be combined into a single object file (called
+    usb-libusual).  The current Makefile will instead create two separate
+    objects, and the result won't load properly.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Alan Jenkins 
+    Reported-and-tested-by: Mike Galbraith 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
+index 5be54c019662..ef7e5a8ceab5 100644
+--- a/drivers/usb/storage/Makefile
++++ b/drivers/usb/storage/Makefile
+@@ -17,7 +17,8 @@ usb-storage-objs :=	scsiglue.o protocol.o transport.o usb.o \
+ ifeq ($(CONFIG_USB_LIBUSUAL),)
+ 	usb-storage-objs	+= usual-tables.o
+ else
+-	obj-$(CONFIG_USB)	+= libusual.o usual-tables.o
++	obj-$(CONFIG_USB)	+= usb-libusual.o
++	usb-libusual-objs	:= libusual.o usual-tables.o
+ endif
+ 
+ obj-$(CONFIG_USB_STORAGE_ALAUDA)	+= ums-alauda.o

commit e4813eec8d47c8299d968bd5349dc881fa481c26
+Author: Alan Stern 
+Date:   Tue Mar 24 10:39:13 2009 -0400
+
+    USB: usb-storage: augment unusual_devs entry for Simple Tech/Datafab
+    
+    This patch (as1227) adds the MAX_SECTORS_64 flag to the unusual_devs
+    entry for the Simple Tech/Datafab controller.  This fixes Bugzilla
+    #12882.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: binbin 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 6ff2b283edb1..96db479d1165 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -975,12 +975,14 @@ UNUSUAL_DEV(  0x07c4, 0xa400, 0x0000, 0xffff,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_FIX_INQUIRY | US_FL_FIX_CAPACITY ),
+ 
+-/* Reported by Rauch Wolke  */
++/* Reported by Rauch Wolke 
++ * and augmented by binbin  (Bugzilla #12882)
++ */
+ UNUSUAL_DEV(  0x07c4, 0xa4a5, 0x0000, 0xffff,
+ 		"Simple Tech/Datafab",
+ 		"CF+SM Reader",
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_IGNORE_RESIDUE ),
++		US_FL_IGNORE_RESIDUE | US_FL_MAX_SECTORS_64 ),
+ 
+ /* Casio QV 2x00/3x00/4000/8000 digital still cameras are not conformant
+  * to the USB storage specification in two ways:

commit d34d9721a559fd11ec682bd9ef17220de0162060
+Author: Alan Stern 
+Date:   Mon Mar 9 13:44:48 2009 -0400
+
+    USB: usbfs: remove unneeded "inline" annotations
+    
+    This patch (as1223) removes a bunch of unnecessary "inline"
+    annotations from the usbfs driver.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 8f022af2fd7a..d3883f639604 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -104,7 +104,7 @@ MODULE_PARM_DESC(usbfs_snoop, "true to log all usbfs traffic");
+ 
+ #define	MAX_USBFS_BUFFER_SIZE	16384
+ 
+-static inline int connected(struct dev_state *ps)
++static int connected(struct dev_state *ps)
+ {
+ 	return (!list_empty(&ps->list) &&
+ 			ps->dev->state != USB_STATE_NOTATTACHED);
+@@ -248,7 +248,7 @@ static void free_async(struct async *as)
+ 	kfree(as);
+ }
+ 
+-static inline void async_newpending(struct async *as)
++static void async_newpending(struct async *as)
+ {
+ 	struct dev_state *ps = as->ps;
+ 	unsigned long flags;
+@@ -258,7 +258,7 @@ static inline void async_newpending(struct async *as)
+ 	spin_unlock_irqrestore(&ps->lock, flags);
+ }
+ 
+-static inline void async_removepending(struct async *as)
++static void async_removepending(struct async *as)
+ {
+ 	struct dev_state *ps = as->ps;
+ 	unsigned long flags;
+@@ -268,7 +268,7 @@ static inline void async_removepending(struct async *as)
+ 	spin_unlock_irqrestore(&ps->lock, flags);
+ }
+ 
+-static inline struct async *async_getcompleted(struct dev_state *ps)
++static struct async *async_getcompleted(struct dev_state *ps)
+ {
+ 	unsigned long flags;
+ 	struct async *as = NULL;
+@@ -283,7 +283,7 @@ static inline struct async *async_getcompleted(struct dev_state *ps)
+ 	return as;
+ }
+ 
+-static inline struct async *async_getpending(struct dev_state *ps,
++static struct async *async_getpending(struct dev_state *ps,
+ 					     void __user *userurb)
+ {
+ 	unsigned long flags;
+@@ -376,7 +376,7 @@ static void destroy_async_on_interface(struct dev_state *ps,
+ 	destroy_async(ps, &hitlist);
+ }
+ 
+-static inline void destroy_all_async(struct dev_state *ps)
++static void destroy_all_async(struct dev_state *ps)
+ {
+ 	destroy_async(ps, &ps->async_pending);
+ }

commit 4fe0387afa893b44c5a21b9bfbb0888354ef4656
+Author: Alan Stern 
+Date:   Thu Feb 26 10:21:02 2009 -0500
+
+    USB: don't send Set-Interface after reset
+    
+    This patch (as1221) changes the way usbcore reinitializes a device
+    following a reset or a reset-resume.  Currently we call
+    usb_set_interface() for every interface in the active configuration;
+    this is to put the interface into the same altsetting as before the
+    reset and to make sure that the host's endpoint state matches the
+    device's endpoint state.
+    
+    However, sending a Set-Interface request is a waste of time if an
+    interface was already in altsetting 0 before the reset, since it is
+    certainly in altsetting 0 afterward.  In addition, many devices can't
+    handle Set-Interface requests -- they crash when they receive them.
+    
+    So instead, the patch adds code to check each interface.  If the
+    interface wasn't in altsetting 0 before the reset, we go head with the
+    Set-Interface request as before.  But if it was then we skip sending
+    the Set-Interface request, and we clear out the host-side endpoint
+    state by calling usb_disable_interface() followed by
+    usb_enable_interface().
+    
+    The patch also adds a couple of new comments to explain what's going
+    on.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index f17d9ebc44af..81eb3e6b6592 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -3393,10 +3393,10 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
+ 		udev->descriptor = descriptor;	/* for disconnect() calls */
+ 		goto re_enumerate;
+   	}
+-  
++
++	/* Restore the device's previous configuration */
+ 	if (!udev->actconfig)
+ 		goto done;
+-
+ 	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ 			USB_REQ_SET_CONFIGURATION, 0,
+ 			udev->actconfig->desc.bConfigurationValue, 0,
+@@ -3409,16 +3409,25 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
+   	}
+ 	usb_set_device_state(udev, USB_STATE_CONFIGURED);
+ 
++	/* Put interfaces back into the same altsettings as before.
++	 * Don't bother to send the Set-Interface request for interfaces
++	 * that were already in altsetting 0; besides being unnecessary,
++	 * many devices can't handle it.  Instead just reset the host-side
++	 * endpoint state.
++	 */
+ 	for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+ 		struct usb_interface *intf = udev->actconfig->interface[i];
+ 		struct usb_interface_descriptor *desc;
+ 
+-		/* set_interface resets host side toggle even
+-		 * for altsetting zero.  the interface may have no driver.
+-		 */
+ 		desc = &intf->cur_altsetting->desc;
+-		ret = usb_set_interface(udev, desc->bInterfaceNumber,
+-			desc->bAlternateSetting);
++		if (desc->bAlternateSetting == 0) {
++			usb_disable_interface(udev, intf, true);
++			usb_enable_interface(udev, intf, true);
++			ret = 0;
++		} else {
++			ret = usb_set_interface(udev, desc->bInterfaceNumber,
++					desc->bAlternateSetting);
++		}
+ 		if (ret < 0) {
+ 			dev_err(&udev->dev, "failed to restore interface %d "
+ 				"altsetting %d (error=%d)\n",

commit 7ea0a2bcfe40b1c525e63e931b7142ab22b64269
+Author: Alan Stern 
+Date:   Thu Mar 5 11:01:11 2009 -0500
+
+    USB: uhci: don't use pseudo negative values
+    
+    The code in uhci-q.c doesn't have to use pseudo-negative values.  I did
+    it that way because it was easy and because it would give the expected
+    output during debugging.  But it doesn't have to work that way.  Here's
+    another approach.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Roel Kluin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
+index 20cc58b97807..e52b954dda47 100644
+--- a/drivers/usb/host/uhci-debug.c
++++ b/drivers/usb/host/uhci-debug.c
+@@ -118,7 +118,9 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space)
+ 	}
+ 
+ 	out += sprintf(out, "%s%s", ptype, (urbp->fsbr ? " FSBR" : ""));
+-	out += sprintf(out, " Actlen=%d", urbp->urb->actual_length);
++	out += sprintf(out, " Actlen=%d%s", urbp->urb->actual_length,
++			(urbp->qh->type == USB_ENDPOINT_XFER_CONTROL ?
++				"-8" : ""));
+ 
+ 	if (urbp->urb->unlinked)
+ 		out += sprintf(out, " Unlinked=%d", urbp->urb->unlinked);
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 58f873679145..3e5807d14ffb 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -899,8 +899,6 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
+ 	}
+ 	if (qh->state != QH_STATE_ACTIVE)
+ 		qh->skel = skel;
+-
+-	urb->actual_length = -8;	/* Account for the SETUP packet */
+ 	return 0;
+ 
+ nomem:
+@@ -1494,11 +1492,10 @@ __acquires(uhci->lock)
+ 
+ 	if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
+ 
+-		/* urb->actual_length < 0 means the setup transaction didn't
+-		 * complete successfully.  Either it failed or the URB was
+-		 * unlinked first.  Regardless, don't confuse people with a
+-		 * negative length. */
+-		urb->actual_length = max(urb->actual_length, 0);
++		/* Subtract off the length of the SETUP packet from
++		 * urb->actual_length.
++		 */
++		urb->actual_length -= min_t(u32, 8, urb->actual_length);
+ 	}
+ 
+ 	/* When giving back the first URB in an Isochronous queue,

commit 9cfb95ef72c637bc9b90260e0f98a23f3f49b1bb
+Author: Alan Stern 
+Date:   Thu Feb 12 14:48:33 2009 -0500
+
+    usb-storage: make onetouch a separate module
+    
+    This patch (as1217) converts usb-storage's onetouch subdriver into a
+    separate module.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
+index 8adece1dd294..8a372bac0e43 100644
+--- a/drivers/usb/storage/Kconfig
++++ b/drivers/usb/storage/Kconfig
+@@ -131,7 +131,7 @@ config USB_STORAGE_ALAUDA
+ 	  If this driver is compiled as a module, it will be named ums-alauda.
+ 
+ config USB_STORAGE_ONETOUCH
+-	bool "Support OneTouch Button on Maxtor Hard Drives"
++	tristate "Support OneTouch Button on Maxtor Hard Drives"
+ 	depends on USB_STORAGE
+ 	depends on INPUT=y || INPUT=USB_STORAGE
+ 	help
+@@ -143,6 +143,8 @@ config USB_STORAGE_ONETOUCH
+ 	  this input in any keybinding software. (e.g. gnome's keyboard short-
+ 	  cuts)
+ 
++	  If this driver is compiled as a module, it will be named ums-onetouch.
++
+ config USB_STORAGE_KARMA
+ 	tristate "Support for Rio Karma music player"
+ 	depends on USB_STORAGE
+diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
+index 870680ea3709..5be54c019662 100644
+--- a/drivers/usb/storage/Makefile
++++ b/drivers/usb/storage/Makefile
+@@ -10,7 +10,6 @@ EXTRA_CFLAGS	:= -Idrivers/scsi
+ obj-$(CONFIG_USB_STORAGE)	+= usb-storage.o
+ 
+ usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG)	+= debug.o
+-usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH)	+= onetouch.o
+ 
+ usb-storage-objs :=	scsiglue.o protocol.o transport.o usb.o \
+ 			initializers.o sierra_ms.o option_ms.o $(usb-storage-obj-y)
+@@ -28,6 +27,7 @@ obj-$(CONFIG_USB_STORAGE_FREECOM)	+= ums-freecom.o
+ obj-$(CONFIG_USB_STORAGE_ISD200)	+= ums-isd200.o
+ obj-$(CONFIG_USB_STORAGE_JUMPSHOT)	+= ums-jumpshot.o
+ obj-$(CONFIG_USB_STORAGE_KARMA)		+= ums-karma.o
++obj-$(CONFIG_USB_STORAGE_ONETOUCH)	+= ums-onetouch.o
+ obj-$(CONFIG_USB_STORAGE_SDDR09)	+= ums-sddr09.o
+ obj-$(CONFIG_USB_STORAGE_SDDR55)	+= ums-sddr55.o
+ obj-$(CONFIG_USB_STORAGE_USBAT)		+= ums-usbat.o
+@@ -39,6 +39,7 @@ ums-freecom-objs	:= freecom.o
+ ums-isd200-objs		:= isd200.o
+ ums-jumpshot-objs	:= jumpshot.o
+ ums-karma-objs		:= karma.o
++ums-onetouch-objs	:= onetouch.o
+ ums-sddr09-objs		:= sddr09.o
+ ums-sddr55-objs		:= sddr55.o
+ ums-usbat-objs		:= shuttle_usbat.o
+diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
+index c7bf8954b4e4..8bd095635a99 100644
+--- a/drivers/usb/storage/onetouch.c
++++ b/drivers/usb/storage/onetouch.c
+@@ -35,9 +35,12 @@
+ #include 
+ #include 
+ #include "usb.h"
+-#include "onetouch.h"
+ #include "debug.h"
+ 
++#define ONETOUCH_PKT_LEN        0x02
++#define ONETOUCH_BUTTON         KEY_PROG1
++
++static int onetouch_connect_input(struct us_data *ss);
+ static void onetouch_release_input(void *onetouch_);
+ 
+ struct usb_onetouch {
+@@ -52,6 +55,46 @@ struct usb_onetouch {
+ 	unsigned int is_open:1;
+ };
+ 
++
++/*
++ * The table of devices
++ */
++#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
++		    vendorName, productName, useProtocol, useTransport, \
++		    initFunction, flags) \
++{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
++  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
++
++struct usb_device_id onetouch_usb_ids[] = {
++#	include "unusual_onetouch.h"
++	{ }		/* Terminating entry */
++};
++MODULE_DEVICE_TABLE(usb, onetouch_usb_ids);
++
++#undef UNUSUAL_DEV
++
++/*
++ * The flags table
++ */
++#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
++		    vendor_name, product_name, use_protocol, use_transport, \
++		    init_function, Flags) \
++{ \
++	.vendorName = vendor_name,	\
++	.productName = product_name,	\
++	.useProtocol = use_protocol,	\
++	.useTransport = use_transport,	\
++	.initFunction = init_function,	\
++}
++
++static struct us_unusual_dev onetouch_unusual_dev_list[] = {
++#	include "unusual_onetouch.h"
++	{ }		/* Terminating entry */
++};
++
++#undef UNUSUAL_DEV
++
++
+ static void usb_onetouch_irq(struct urb *urb)
+ {
+ 	struct usb_onetouch *onetouch = urb->context;
+@@ -127,7 +170,7 @@ static void usb_onetouch_pm_hook(struct us_data *us, int action)
+ }
+ #endif /* CONFIG_PM */
+ 
+-int onetouch_connect_input(struct us_data *ss)
++static int onetouch_connect_input(struct us_data *ss)
+ {
+ 	struct usb_device *udev = ss->pusb_dev;
+ 	struct usb_host_interface *interface;
+@@ -236,3 +279,46 @@ static void onetouch_release_input(void *onetouch_)
+ 				onetouch->data, onetouch->data_dma);
+ 	}
+ }
++
++static int onetouch_probe(struct usb_interface *intf,
++			 const struct usb_device_id *id)
++{
++	struct us_data *us;
++	int result;
++
++	result = usb_stor_probe1(&us, intf, id,
++			(id - onetouch_usb_ids) + onetouch_unusual_dev_list);
++	if (result)
++		return result;
++
++	/* Use default transport and protocol */
++
++	result = usb_stor_probe2(us);
++	return result;
++}
++
++static struct usb_driver onetouch_driver = {
++	.name =		"ums-onetouch",
++	.probe =	onetouch_probe,
++	.disconnect =	usb_stor_disconnect,
++	.suspend =	usb_stor_suspend,
++	.resume =	usb_stor_resume,
++	.reset_resume =	usb_stor_reset_resume,
++	.pre_reset =	usb_stor_pre_reset,
++	.post_reset =	usb_stor_post_reset,
++	.id_table =	onetouch_usb_ids,
++	.soft_unbind =	1,
++};
++
++static int __init onetouch_init(void)
++{
++	return usb_register(&onetouch_driver);
++}
++
++static void __exit onetouch_exit(void)
++{
++	usb_deregister(&onetouch_driver);
++}
++
++module_init(onetouch_init);
++module_exit(onetouch_exit);
+diff --git a/drivers/usb/storage/onetouch.h b/drivers/usb/storage/onetouch.h
+deleted file mode 100644
+index 41c7aa8f0446..000000000000
+--- a/drivers/usb/storage/onetouch.h
++++ /dev/null
+@@ -1,9 +0,0 @@
+-#ifndef _ONETOUCH_H_
+-#define _ONETOUCH_H_
+-
+-#define ONETOUCH_PKT_LEN        0x02
+-#define ONETOUCH_BUTTON         KEY_PROG1
+-
+-int onetouch_connect_input(struct us_data *ss);
+-
+-#endif
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 83e34a6ad59d..1c1f643e8a78 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -1182,23 +1182,6 @@ UNUSUAL_DEV( 0x0c45, 0x1060, 0x0100, 0x0100,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_SINGLE_LUN ),
+ 
+-/* Submitted by: Nick Sillik 
+- * Needed for OneTouch extension to usb-storage
+- *
+- */
+-#ifdef CONFIG_USB_STORAGE_ONETOUCH
+-	UNUSUAL_DEV(  0x0d49, 0x7000, 0x0000, 0x9999,
+-			"Maxtor",
+-			"OneTouch External Harddrive",
+-			US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input,
+-			0),
+-	UNUSUAL_DEV(  0x0d49, 0x7010, 0x0000, 0x9999,
+-			"Maxtor",
+-			"OneTouch External Harddrive",
+-			US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input,
+-			0),
+-#endif
+-
+ /* Submitted by Joris Struyve  */
+ UNUSUAL_DEV( 0x0d96, 0x410a, 0x0001, 0xffff,
+ 		"Medion",
+diff --git a/drivers/usb/storage/unusual_onetouch.h b/drivers/usb/storage/unusual_onetouch.h
+new file mode 100644
+index 000000000000..bd9306b637df
+--- /dev/null
++++ b/drivers/usb/storage/unusual_onetouch.h
+@@ -0,0 +1,36 @@
++/* Unusual Devices File for the Maxtor OneTouch USB hard drive's button
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2, or (at your option) any
++ * later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#if defined(CONFIG_USB_STORAGE_ONETOUCH) || \
++		defined(CONFIG_USB_STORAGE_ONETOUCH_MODULE)
++
++/* Submitted by: Nick Sillik 
++ * Needed for OneTouch extension to usb-storage
++ */
++UNUSUAL_DEV(  0x0d49, 0x7000, 0x0000, 0x9999,
++		"Maxtor",
++		"OneTouch External Harddrive",
++		US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input,
++		0),
++
++UNUSUAL_DEV(  0x0d49, 0x7010, 0x0000, 0x9999,
++		"Maxtor",
++		"OneTouch External Harddrive",
++		US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input,
++		0),
++
++#endif /* defined(CONFIG_USB_STORAGE_ONETOUCH) || ... */
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index c5abf9bbce16..8060b85fe1a3 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -66,9 +66,6 @@
+ #include "debug.h"
+ #include "initializers.h"
+ 
+-#ifdef CONFIG_USB_STORAGE_ONETOUCH
+-#include "onetouch.h"
+-#endif
+ #include "sierra_ms.h"
+ #include "option_ms.h"
+ 
+diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c
+index bce086fcef5e..468bde7d1971 100644
+--- a/drivers/usb/storage/usual-tables.c
++++ b/drivers/usb/storage/usual-tables.c
+@@ -84,6 +84,7 @@ static struct ignore_entry ignore_ids[] = {
+ #	include "unusual_isd200.h"
+ #	include "unusual_jumpshot.h"
+ #	include "unusual_karma.h"
++#	include "unusual_onetouch.h"
+ #	include "unusual_sddr09.h"
+ #	include "unusual_sddr55.h"
+ #	include "unusual_usbat.h"

commit c10337846c93bd914dd3003ffb001adc583b313e
+Author: Alan Stern 
+Date:   Thu Feb 12 14:48:26 2009 -0500
+
+    usb-storage: make karma a separate module
+    
+    This patch (as1216) converts usb-storage's karma subdriver into a
+    separate module.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
+index c56c2c6d37b7..8adece1dd294 100644
+--- a/drivers/usb/storage/Kconfig
++++ b/drivers/usb/storage/Kconfig
+@@ -144,7 +144,7 @@ config USB_STORAGE_ONETOUCH
+ 	  cuts)
+ 
+ config USB_STORAGE_KARMA
+-	bool "Support for Rio Karma music player"
++	tristate "Support for Rio Karma music player"
+ 	depends on USB_STORAGE
+ 	help
+ 	  Say Y here to include additional code to support the Rio Karma
+@@ -155,6 +155,8 @@ config USB_STORAGE_KARMA
+ 	  on the resulting scsi device node returns the Karma to normal
+ 	  operation.
+ 
++	  If this driver is compiled as a module, it will be named ums-karma.
++
+ config USB_STORAGE_CYPRESS_ATACB
+ 	tristate "SAT emulation on Cypress USB/ATA Bridge with ATACB"
+ 	depends on USB_STORAGE
+diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
+index fea05c0b6765..870680ea3709 100644
+--- a/drivers/usb/storage/Makefile
++++ b/drivers/usb/storage/Makefile
+@@ -11,7 +11,6 @@ obj-$(CONFIG_USB_STORAGE)	+= usb-storage.o
+ 
+ usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG)	+= debug.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH)	+= onetouch.o
+-usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA)	+= karma.o
+ 
+ usb-storage-objs :=	scsiglue.o protocol.o transport.o usb.o \
+ 			initializers.o sierra_ms.o option_ms.o $(usb-storage-obj-y)
+@@ -28,6 +27,7 @@ obj-$(CONFIG_USB_STORAGE_DATAFAB)	+= ums-datafab.o
+ obj-$(CONFIG_USB_STORAGE_FREECOM)	+= ums-freecom.o
+ obj-$(CONFIG_USB_STORAGE_ISD200)	+= ums-isd200.o
+ obj-$(CONFIG_USB_STORAGE_JUMPSHOT)	+= ums-jumpshot.o
++obj-$(CONFIG_USB_STORAGE_KARMA)		+= ums-karma.o
+ obj-$(CONFIG_USB_STORAGE_SDDR09)	+= ums-sddr09.o
+ obj-$(CONFIG_USB_STORAGE_SDDR55)	+= ums-sddr55.o
+ obj-$(CONFIG_USB_STORAGE_USBAT)		+= ums-usbat.o
+@@ -38,6 +38,7 @@ ums-datafab-objs	:= datafab.o
+ ums-freecom-objs	:= freecom.o
+ ums-isd200-objs		:= isd200.o
+ ums-jumpshot-objs	:= jumpshot.o
++ums-karma-objs		:= karma.o
+ ums-sddr09-objs		:= sddr09.o
+ ums-sddr55-objs		:= sddr55.o
+ ums-usbat-objs		:= shuttle_usbat.o
+diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c
+index 0d79ae5683f7..cfb8e60866b8 100644
+--- a/drivers/usb/storage/karma.c
++++ b/drivers/usb/storage/karma.c
+@@ -18,6 +18,8 @@
+  * 675 Mass Ave, Cambridge, MA 02139, USA.
+  */
+ 
++#include 
++
+ #include 
+ #include 
+ #include 
+@@ -25,7 +27,6 @@
+ #include "usb.h"
+ #include "transport.h"
+ #include "debug.h"
+-#include "karma.h"
+ 
+ #define RIO_PREFIX "RIOP\x00"
+ #define RIO_PREFIX_LEN 5
+@@ -36,13 +37,53 @@
+ #define RIO_LEAVE_STORAGE 0x2
+ #define RIO_RESET 0xC
+ 
+-extern int usb_stor_Bulk_transport(struct scsi_cmnd *, struct us_data *);
+-
+ struct karma_data {
+ 	int in_storage;
+ 	char *recv;
+ };
+ 
++static int rio_karma_init(struct us_data *us);
++
++
++/*
++ * The table of devices
++ */
++#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
++		    vendorName, productName, useProtocol, useTransport, \
++		    initFunction, flags) \
++{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
++  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
++
++struct usb_device_id karma_usb_ids[] = {
++#	include "unusual_karma.h"
++	{ }		/* Terminating entry */
++};
++MODULE_DEVICE_TABLE(usb, karma_usb_ids);
++
++#undef UNUSUAL_DEV
++
++/*
++ * The flags table
++ */
++#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
++		    vendor_name, product_name, use_protocol, use_transport, \
++		    init_function, Flags) \
++{ \
++	.vendorName = vendor_name,	\
++	.productName = product_name,	\
++	.useProtocol = use_protocol,	\
++	.useTransport = use_transport,	\
++	.initFunction = init_function,	\
++}
++
++static struct us_unusual_dev karma_unusual_dev_list[] = {
++#	include "unusual_karma.h"
++	{ }		/* Terminating entry */
++};
++
++#undef UNUSUAL_DEV
++
++
+ /*
+  * Send commands to Rio Karma.
+  *
+@@ -104,7 +145,7 @@ static int rio_karma_send_command(char cmd, struct us_data *us)
+  * Trap START_STOP and READ_10 to leave/re-enter storage mode.
+  * Everything else is propagated to the normal bulk layer.
+  */
+-int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us)
++static int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us)
+ {
+ 	int ret;
+ 	struct karma_data *data = (struct karma_data *) us->extra;
+@@ -133,7 +174,7 @@ static void rio_karma_destructor(void *extra)
+ 	kfree(data->recv);
+ }
+ 
+-int rio_karma_init(struct us_data *us)
++static int rio_karma_init(struct us_data *us)
+ {
+ 	int ret = 0;
+ 	struct karma_data *data = kzalloc(sizeof(struct karma_data), GFP_NOIO);
+@@ -153,3 +194,48 @@ int rio_karma_init(struct us_data *us)
+ out:
+ 	return ret;
+ }
++
++static int karma_probe(struct usb_interface *intf,
++			 const struct usb_device_id *id)
++{
++	struct us_data *us;
++	int result;
++
++	result = usb_stor_probe1(&us, intf, id,
++			(id - karma_usb_ids) + karma_unusual_dev_list);
++	if (result)
++		return result;
++
++	us->transport_name = "Rio Karma/Bulk";
++	us->transport = rio_karma_transport;
++	us->transport_reset = usb_stor_Bulk_reset;
++
++	result = usb_stor_probe2(us);
++	return result;
++}
++
++static struct usb_driver karma_driver = {
++	.name =		"ums-karma",
++	.probe =	karma_probe,
++	.disconnect =	usb_stor_disconnect,
++	.suspend =	usb_stor_suspend,
++	.resume =	usb_stor_resume,
++	.reset_resume =	usb_stor_reset_resume,
++	.pre_reset =	usb_stor_pre_reset,
++	.post_reset =	usb_stor_post_reset,
++	.id_table =	karma_usb_ids,
++	.soft_unbind =	1,
++};
++
++static int __init karma_init(void)
++{
++	return usb_register(&karma_driver);
++}
++
++static void __exit karma_exit(void)
++{
++	usb_deregister(&karma_driver);
++}
++
++module_init(karma_init);
++module_exit(karma_exit);
+diff --git a/drivers/usb/storage/karma.h b/drivers/usb/storage/karma.h
+deleted file mode 100644
+index 8a60972af8c5..000000000000
+--- a/drivers/usb/storage/karma.h
++++ /dev/null
+@@ -1,7 +0,0 @@
+-#ifndef _KARMA_USB_H
+-#define _KARMA_USB_H
+-
+-extern int rio_karma_init(struct us_data *us);
+-extern int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us);
+-
+-#endif
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index bcdb74dfa3db..83e34a6ad59d 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -276,13 +276,6 @@ UNUSUAL_DEV(  0x0457, 0x0151, 0x0100, 0x0100,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_NOT_LOCKABLE ),
+ 
+-#ifdef CONFIG_USB_STORAGE_KARMA
+-UNUSUAL_DEV(  0x045a, 0x5210, 0x0101, 0x0101,
+-		"Rio",
+-		"Rio Karma",
+-		US_SC_SCSI, US_PR_KARMA, rio_karma_init, 0),
+-#endif
+-
+ /* Reported by Tamas Kerecsen 
+  * Obviously the PROM has not been customized by the VAR;
+  * the Vendor and Product string descriptors are:
+diff --git a/drivers/usb/storage/unusual_karma.h b/drivers/usb/storage/unusual_karma.h
+new file mode 100644
+index 000000000000..12ae3a03e802
+--- /dev/null
++++ b/drivers/usb/storage/unusual_karma.h
+@@ -0,0 +1,26 @@
++/* Unusual Devices File for the Rio Karma
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2, or (at your option) any
++ * later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#if defined(CONFIG_USB_STORAGE_KARMA) || \
++		defined(CONFIG_USB_STORAGE_KARMA_MODULE)
++
++UNUSUAL_DEV(  0x045a, 0x5210, 0x0101, 0x0101,
++		"Rio",
++		"Rio Karma",
++		US_SC_SCSI, US_PR_KARMA, rio_karma_init, 0),
++
++#endif /* defined(CONFIG_USB_STORAGE_KARMA) || ... */
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index cd039c008462..c5abf9bbce16 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -69,9 +69,6 @@
+ #ifdef CONFIG_USB_STORAGE_ONETOUCH
+ #include "onetouch.h"
+ #endif
+-#ifdef CONFIG_USB_STORAGE_KARMA
+-#include "karma.h"
+-#endif
+ #include "sierra_ms.h"
+ #include "option_ms.h"
+ 
+@@ -594,15 +591,6 @@ static void get_transport(struct us_data *us)
+ 		us->transport = usb_stor_Bulk_transport;
+ 		us->transport_reset = usb_stor_Bulk_reset;
+ 		break;
+-
+-#ifdef CONFIG_USB_STORAGE_KARMA
+-	case US_PR_KARMA:
+-		us->transport_name = "Rio Karma/Bulk";
+-		us->transport = rio_karma_transport;
+-		us->transport_reset = usb_stor_Bulk_reset;
+-		break;
+-#endif
+-
+ 	}
+ }
+ 
+diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c
+index ad102e8e191b..bce086fcef5e 100644
+--- a/drivers/usb/storage/usual-tables.c
++++ b/drivers/usb/storage/usual-tables.c
+@@ -83,6 +83,7 @@ static struct ignore_entry ignore_ids[] = {
+ #	include "unusual_freecom.h"
+ #	include "unusual_isd200.h"
+ #	include "unusual_jumpshot.h"
++#	include "unusual_karma.h"
+ #	include "unusual_sddr09.h"
+ #	include "unusual_sddr55.h"
+ #	include "unusual_usbat.h"

commit a74bba3bf92cb6425789ae5050bdcca1283bc6f4
+Author: Alan Stern 
+Date:   Thu Feb 12 14:48:22 2009 -0500
+
+    usb-storage: make alauda a separate module
+    
+    This patch (as1215) converts usb-storage's alauda subdriver into a
+    separate module.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
+index 43e1afeb7f8c..c56c2c6d37b7 100644
+--- a/drivers/usb/storage/Kconfig
++++ b/drivers/usb/storage/Kconfig
+@@ -119,7 +119,7 @@ config USB_STORAGE_JUMPSHOT
+ 	  If this driver is compiled as a module, it will be named ums-jumpshot.
+ 
+ config USB_STORAGE_ALAUDA
+-	bool "Olympus MAUSB-10/Fuji DPC-R1 support"
++	tristate "Olympus MAUSB-10/Fuji DPC-R1 support"
+ 	depends on USB_STORAGE
+ 	help
+ 	  Say Y here to include additional code to support the Olympus MAUSB-10
+@@ -128,6 +128,8 @@ config USB_STORAGE_ALAUDA
+ 	  These devices are based on the Alauda chip and support both
+ 	  XD and SmartMedia cards.
+ 
++	  If this driver is compiled as a module, it will be named ums-alauda.
++
+ config USB_STORAGE_ONETOUCH
+ 	bool "Support OneTouch Button on Maxtor Hard Drives"
+ 	depends on USB_STORAGE
+diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
+index 7b9d53563d34..fea05c0b6765 100644
+--- a/drivers/usb/storage/Makefile
++++ b/drivers/usb/storage/Makefile
+@@ -10,7 +10,6 @@ EXTRA_CFLAGS	:= -Idrivers/scsi
+ obj-$(CONFIG_USB_STORAGE)	+= usb-storage.o
+ 
+ usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG)	+= debug.o
+-usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA)	+= alauda.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH)	+= onetouch.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA)	+= karma.o
+ 
+@@ -23,6 +22,7 @@ else
+ 	obj-$(CONFIG_USB)	+= libusual.o usual-tables.o
+ endif
+ 
++obj-$(CONFIG_USB_STORAGE_ALAUDA)	+= ums-alauda.o
+ obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o
+ obj-$(CONFIG_USB_STORAGE_DATAFAB)	+= ums-datafab.o
+ obj-$(CONFIG_USB_STORAGE_FREECOM)	+= ums-freecom.o
+@@ -32,6 +32,7 @@ obj-$(CONFIG_USB_STORAGE_SDDR09)	+= ums-sddr09.o
+ obj-$(CONFIG_USB_STORAGE_SDDR55)	+= ums-sddr55.o
+ obj-$(CONFIG_USB_STORAGE_USBAT)		+= ums-usbat.o
+ 
++ums-alauda-objs		:= alauda.o
+ ums-cypress-objs	:= cypress_atacb.o
+ ums-datafab-objs	:= datafab.o
+ ums-freecom-objs	:= freecom.o
+diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c
+index 5407411e30e0..d3a88ebe690b 100644
+--- a/drivers/usb/storage/alauda.c
++++ b/drivers/usb/storage/alauda.c
+@@ -31,6 +31,8 @@
+  * 675 Mass Ave, Cambridge, MA 02139, USA.
+  */
+ 
++#include 
++
+ #include 
+ #include 
+ #include 
+@@ -39,7 +41,75 @@
+ #include "transport.h"
+ #include "protocol.h"
+ #include "debug.h"
+-#include "alauda.h"
++
++/*
++ * Status bytes
++ */
++#define ALAUDA_STATUS_ERROR		0x01
++#define ALAUDA_STATUS_READY		0x40
++
++/*
++ * Control opcodes (for request field)
++ */
++#define ALAUDA_GET_XD_MEDIA_STATUS	0x08
++#define ALAUDA_GET_SM_MEDIA_STATUS	0x98
++#define ALAUDA_ACK_XD_MEDIA_CHANGE	0x0a
++#define ALAUDA_ACK_SM_MEDIA_CHANGE	0x9a
++#define ALAUDA_GET_XD_MEDIA_SIG		0x86
++#define ALAUDA_GET_SM_MEDIA_SIG		0x96
++
++/*
++ * Bulk command identity (byte 0)
++ */
++#define ALAUDA_BULK_CMD			0x40
++
++/*
++ * Bulk opcodes (byte 1)
++ */
++#define ALAUDA_BULK_GET_REDU_DATA	0x85
++#define ALAUDA_BULK_READ_BLOCK		0x94
++#define ALAUDA_BULK_ERASE_BLOCK		0xa3
++#define ALAUDA_BULK_WRITE_BLOCK		0xb4
++#define ALAUDA_BULK_GET_STATUS2		0xb7
++#define ALAUDA_BULK_RESET_MEDIA		0xe0
++
++/*
++ * Port to operate on (byte 8)
++ */
++#define ALAUDA_PORT_XD			0x00
++#define ALAUDA_PORT_SM			0x01
++
++/*
++ * LBA and PBA are unsigned ints. Special values.
++ */
++#define UNDEF    0xffff
++#define SPARE    0xfffe
++#define UNUSABLE 0xfffd
++
++struct alauda_media_info {
++	unsigned long capacity;		/* total media size in bytes */
++	unsigned int pagesize;		/* page size in bytes */
++	unsigned int blocksize;		/* number of pages per block */
++	unsigned int uzonesize;		/* number of usable blocks per zone */
++	unsigned int zonesize;		/* number of blocks per zone */
++	unsigned int blockmask;		/* mask to get page from address */
++
++	unsigned char pageshift;
++	unsigned char blockshift;
++	unsigned char zoneshift;
++
++	u16 **lba_to_pba;		/* logical to physical block map */
++	u16 **pba_to_lba;		/* physical to logical block map */
++};
++
++struct alauda_info {
++	struct alauda_media_info port[2];
++	int wr_ep;			/* endpoint to write data out of */
++
++	unsigned char sense_key;
++	unsigned long sense_asc;	/* additional sense code */
++	unsigned long sense_ascq;	/* additional sense code qualifier */
++};
+ 
+ #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) )
+ #define LSB_of(s) ((s)&0xFF)
+@@ -52,6 +122,48 @@
+ #define PBA_HI(pba) (pba >> 3)
+ #define PBA_ZONE(pba) (pba >> 11)
+ 
++static int init_alauda(struct us_data *us);
++
++
++/*
++ * The table of devices
++ */
++#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
++		    vendorName, productName, useProtocol, useTransport, \
++		    initFunction, flags) \
++{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
++  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
++
++struct usb_device_id alauda_usb_ids[] = {
++#	include "unusual_alauda.h"
++	{ }		/* Terminating entry */
++};
++MODULE_DEVICE_TABLE(usb, alauda_usb_ids);
++
++#undef UNUSUAL_DEV
++
++/*
++ * The flags table
++ */
++#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
++		    vendor_name, product_name, use_protocol, use_transport, \
++		    init_function, Flags) \
++{ \
++	.vendorName = vendor_name,	\
++	.productName = product_name,	\
++	.useProtocol = use_protocol,	\
++	.useTransport = use_transport,	\
++	.initFunction = init_function,	\
++}
++
++static struct us_unusual_dev alauda_unusual_dev_list[] = {
++#	include "unusual_alauda.h"
++	{ }		/* Terminating entry */
++};
++
++#undef UNUSUAL_DEV
++
++
+ /*
+  * Media handling
+  */
+@@ -998,7 +1110,7 @@ static void alauda_info_destructor(void *extra)
+ /*
+  * Initialize alauda_info struct and find the data-write endpoint
+  */
+-int init_alauda(struct us_data *us)
++static int init_alauda(struct us_data *us)
+ {
+ 	struct alauda_info *info;
+ 	struct usb_host_interface *altsetting = us->pusb_intf->cur_altsetting;
+@@ -1020,7 +1132,7 @@ int init_alauda(struct us_data *us)
+ 	return USB_STOR_TRANSPORT_GOOD;
+ }
+ 
+-int alauda_transport(struct scsi_cmnd *srb, struct us_data *us)
++static int alauda_transport(struct scsi_cmnd *srb, struct us_data *us)
+ {
+ 	int rc;
+ 	struct alauda_info *info = (struct alauda_info *) us->extra;
+@@ -1128,3 +1240,48 @@ int alauda_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 	return USB_STOR_TRANSPORT_FAILED;
+ }
+ 
++static int alauda_probe(struct usb_interface *intf,
++			 const struct usb_device_id *id)
++{
++	struct us_data *us;
++	int result;
++
++	result = usb_stor_probe1(&us, intf, id,
++			(id - alauda_usb_ids) + alauda_unusual_dev_list);
++	if (result)
++		return result;
++
++	us->transport_name  = "Alauda Control/Bulk";
++	us->transport = alauda_transport;
++	us->transport_reset = usb_stor_Bulk_reset;
++	us->max_lun = 1;
++
++	result = usb_stor_probe2(us);
++	return result;
++}
++
++static struct usb_driver alauda_driver = {
++	.name =		"ums-alauda",
++	.probe =	alauda_probe,
++	.disconnect =	usb_stor_disconnect,
++	.suspend =	usb_stor_suspend,
++	.resume =	usb_stor_resume,
++	.reset_resume =	usb_stor_reset_resume,
++	.pre_reset =	usb_stor_pre_reset,
++	.post_reset =	usb_stor_post_reset,
++	.id_table =	alauda_usb_ids,
++	.soft_unbind =	1,
++};
++
++static int __init alauda_init(void)
++{
++	return usb_register(&alauda_driver);
++}
++
++static void __exit alauda_exit(void)
++{
++	usb_deregister(&alauda_driver);
++}
++
++module_init(alauda_init);
++module_exit(alauda_exit);
+diff --git a/drivers/usb/storage/alauda.h b/drivers/usb/storage/alauda.h
+deleted file mode 100644
+index a700f87d0803..000000000000
+--- a/drivers/usb/storage/alauda.h
++++ /dev/null
+@@ -1,100 +0,0 @@
+-/*
+- * Driver for Alauda-based card readers
+- *
+- * Current development and maintenance by:
+- *    (c) 2005 Daniel Drake 
+- *
+- * See alauda.c for more explanation.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the
+- * Free Software Foundation; either version 2, or (at your option) any
+- * later version.
+- *
+- * This program is distributed in the hope that it will be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#ifndef _USB_ALAUDA_H
+-#define _USB_ALAUDA_H
+-
+-/*
+- * Status bytes
+- */
+-#define ALAUDA_STATUS_ERROR		0x01
+-#define ALAUDA_STATUS_READY		0x40
+-
+-/*
+- * Control opcodes (for request field)
+- */
+-#define ALAUDA_GET_XD_MEDIA_STATUS	0x08
+-#define ALAUDA_GET_SM_MEDIA_STATUS	0x98
+-#define ALAUDA_ACK_XD_MEDIA_CHANGE	0x0a
+-#define ALAUDA_ACK_SM_MEDIA_CHANGE	0x9a
+-#define ALAUDA_GET_XD_MEDIA_SIG		0x86
+-#define ALAUDA_GET_SM_MEDIA_SIG		0x96
+-
+-/*
+- * Bulk command identity (byte 0)
+- */
+-#define ALAUDA_BULK_CMD			0x40
+-
+-/*
+- * Bulk opcodes (byte 1)
+- */
+-#define ALAUDA_BULK_GET_REDU_DATA	0x85
+-#define ALAUDA_BULK_READ_BLOCK		0x94
+-#define ALAUDA_BULK_ERASE_BLOCK		0xa3
+-#define ALAUDA_BULK_WRITE_BLOCK		0xb4
+-#define ALAUDA_BULK_GET_STATUS2		0xb7
+-#define ALAUDA_BULK_RESET_MEDIA		0xe0
+-
+-/*
+- * Port to operate on (byte 8)
+- */
+-#define ALAUDA_PORT_XD			0x00
+-#define ALAUDA_PORT_SM			0x01
+-
+-/*
+- * LBA and PBA are unsigned ints. Special values.
+- */
+-#define UNDEF    0xffff
+-#define SPARE    0xfffe
+-#define UNUSABLE 0xfffd
+-
+-int init_alauda(struct us_data *us);
+-int alauda_transport(struct scsi_cmnd *srb, struct us_data *us);
+-
+-struct alauda_media_info {
+-	unsigned long capacity;		/* total media size in bytes */
+-	unsigned int pagesize;		/* page size in bytes */
+-	unsigned int blocksize;		/* number of pages per block */
+-	unsigned int uzonesize;		/* number of usable blocks per zone */
+-	unsigned int zonesize;		/* number of blocks per zone */
+-	unsigned int blockmask;		/* mask to get page from address */
+-
+-	unsigned char pageshift;
+-	unsigned char blockshift;
+-	unsigned char zoneshift;
+-
+-	u16 **lba_to_pba;		/* logical to physical block map */
+-	u16 **pba_to_lba;		/* physical to logical block map */
+-};
+-
+-struct alauda_info {
+-	struct alauda_media_info port[2];
+-	int wr_ep;			/* endpoint to write data out of */
+-
+-	unsigned char sense_key;
+-	unsigned long sense_asc;	/* additional sense code */
+-	unsigned long sense_ascq;	/* additional sense code qualifier */
+-};
+-
+-#endif
+-
+diff --git a/drivers/usb/storage/unusual_alauda.h b/drivers/usb/storage/unusual_alauda.h
+new file mode 100644
+index 000000000000..8c412f885dd2
+--- /dev/null
++++ b/drivers/usb/storage/unusual_alauda.h
+@@ -0,0 +1,31 @@
++/* Unusual Devices File for the Alauda-based card readers
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2, or (at your option) any
++ * later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#if defined(CONFIG_USB_STORAGE_ALAUDA) || \
++		defined(CONFIG_USB_STORAGE_ALAUDA_MODULE)
++
++UNUSUAL_DEV(  0x0584, 0x0008, 0x0102, 0x0102,
++		"Fujifilm",
++		"DPC-R1 (Alauda)",
++		US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0),
++
++UNUSUAL_DEV(  0x07b4, 0x010a, 0x0102, 0x0102,
++		"Olympus",
++		"MAUSB-10 (Alauda)",
++		US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0),
++
++#endif /* defined(CONFIG_USB_STORAGE_ALAUDA) || ... */
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 24e23c29d292..bcdb74dfa3db 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -692,13 +692,6 @@ UNUSUAL_DEV(  0x057b, 0x0022, 0x0000, 0x9999,
+ 		"Silicon Media R/W",
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL, 0),
+ 
+-#ifdef CONFIG_USB_STORAGE_ALAUDA
+-UNUSUAL_DEV(  0x0584, 0x0008, 0x0102, 0x0102,
+-		"Fujifilm",
+-		"DPC-R1 (Alauda)",
+- 		US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ),
+-#endif
+-
+ /* Reported by RTE  */
+ UNUSUAL_DEV(  0x058f, 0x6387, 0x0141, 0x0141,
+ 		"JetFlash",
+@@ -977,13 +970,6 @@ UNUSUAL_DEV(  0x07af, 0x0006, 0x0100, 0x0100,
+ 		US_FL_SINGLE_LUN ),
+ #endif
+ 
+-#ifdef CONFIG_USB_STORAGE_ALAUDA
+-UNUSUAL_DEV(  0x07b4, 0x010a, 0x0102, 0x0102,
+-		"Olympus",
+-		"MAUSB-10 (Alauda)",
+- 		US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ),
+-#endif
+-
+ /* Datafab KECF-USB / Sagatek DCS-CF / Simpletech Flashlink UCF-100
+  * Only revision 1.13 tested (same for all of the above devices,
+  * based on the Datafab DF-UG-07 chip).  Needed for US_FL_FIX_INQUIRY.
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 2ea57691a7ba..cd039c008462 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -69,9 +69,6 @@
+ #ifdef CONFIG_USB_STORAGE_ONETOUCH
+ #include "onetouch.h"
+ #endif
+-#ifdef CONFIG_USB_STORAGE_ALAUDA
+-#include "alauda.h"
+-#endif
+ #ifdef CONFIG_USB_STORAGE_KARMA
+ #include "karma.h"
+ #endif
+@@ -598,15 +595,6 @@ static void get_transport(struct us_data *us)
+ 		us->transport_reset = usb_stor_Bulk_reset;
+ 		break;
+ 
+-#ifdef CONFIG_USB_STORAGE_ALAUDA
+-	case US_PR_ALAUDA:
+-		us->transport_name  = "Alauda Control/Bulk";
+-		us->transport = alauda_transport;
+-		us->transport_reset = usb_stor_Bulk_reset;
+-		us->max_lun = 1;
+-		break;
+-#endif
+-
+ #ifdef CONFIG_USB_STORAGE_KARMA
+ 	case US_PR_KARMA:
+ 		us->transport_name = "Rio Karma/Bulk";
+diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c
+index 182a097e0767..ad102e8e191b 100644
+--- a/drivers/usb/storage/usual-tables.c
++++ b/drivers/usb/storage/usual-tables.c
+@@ -77,6 +77,7 @@ struct ignore_entry {
+ }
+ 
+ static struct ignore_entry ignore_ids[] = {
++#	include "unusual_alauda.h"
+ #	include "unusual_cypress.h"
+ #	include "unusual_datafab.h"
+ #	include "unusual_freecom.h"

commit a9fb6d05d59c9e118ad8c355adfdf88c970c61bc
+Author: Alan Stern 
+Date:   Thu Feb 12 14:48:19 2009 -0500
+
+    usb-storage: make jumpshot a separate module
+    
+    This patch (as1214) converts usb-storage's jumpshot subdriver into a
+    separate module.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
+index 7dac413e0f2f..43e1afeb7f8c 100644
+--- a/drivers/usb/storage/Kconfig
++++ b/drivers/usb/storage/Kconfig
+@@ -110,12 +110,14 @@ config USB_STORAGE_SDDR55
+ 	  If this driver is compiled as a module, it will be named ums-sddr55.
+ 
+ config USB_STORAGE_JUMPSHOT
+-	bool "Lexar Jumpshot Compact Flash Reader"
++	tristate "Lexar Jumpshot Compact Flash Reader"
+ 	depends on USB_STORAGE
+ 	help
+ 	  Say Y here to include additional code to support the Lexar Jumpshot
+ 	  USB CompactFlash reader.
+ 
++	  If this driver is compiled as a module, it will be named ums-jumpshot.
++
+ config USB_STORAGE_ALAUDA
+ 	bool "Olympus MAUSB-10/Fuji DPC-R1 support"
+ 	depends on USB_STORAGE
+diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
+index 0f78bd680f0f..7b9d53563d34 100644
+--- a/drivers/usb/storage/Makefile
++++ b/drivers/usb/storage/Makefile
+@@ -10,7 +10,6 @@ EXTRA_CFLAGS	:= -Idrivers/scsi
+ obj-$(CONFIG_USB_STORAGE)	+= usb-storage.o
+ 
+ usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG)	+= debug.o
+-usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT)	+= jumpshot.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA)	+= alauda.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH)	+= onetouch.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA)	+= karma.o
+@@ -28,6 +27,7 @@ obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o
+ obj-$(CONFIG_USB_STORAGE_DATAFAB)	+= ums-datafab.o
+ obj-$(CONFIG_USB_STORAGE_FREECOM)	+= ums-freecom.o
+ obj-$(CONFIG_USB_STORAGE_ISD200)	+= ums-isd200.o
++obj-$(CONFIG_USB_STORAGE_JUMPSHOT)	+= ums-jumpshot.o
+ obj-$(CONFIG_USB_STORAGE_SDDR09)	+= ums-sddr09.o
+ obj-$(CONFIG_USB_STORAGE_SDDR55)	+= ums-sddr55.o
+ obj-$(CONFIG_USB_STORAGE_USBAT)		+= ums-usbat.o
+@@ -36,6 +36,7 @@ ums-cypress-objs	:= cypress_atacb.o
+ ums-datafab-objs	:= datafab.o
+ ums-freecom-objs	:= freecom.o
+ ums-isd200-objs		:= isd200.o
++ums-jumpshot-objs	:= jumpshot.o
+ ums-sddr09-objs		:= sddr09.o
+ ums-sddr55-objs		:= sddr55.o
+ ums-usbat-objs		:= shuttle_usbat.o
+diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c
+index df67f13c9e73..a50d6dc1fe64 100644
+--- a/drivers/usb/storage/jumpshot.c
++++ b/drivers/usb/storage/jumpshot.c
+@@ -46,6 +46,7 @@
+   */
+ 
+ #include 
++#include 
+ #include 
+ 
+ #include 
+@@ -55,9 +56,57 @@
+ #include "transport.h"
+ #include "protocol.h"
+ #include "debug.h"
+-#include "jumpshot.h"
+ 
+ 
++/*
++ * The table of devices
++ */
++#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
++		    vendorName, productName, useProtocol, useTransport, \
++		    initFunction, flags) \
++{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
++  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
++
++struct usb_device_id jumpshot_usb_ids[] = {
++#	include "unusual_jumpshot.h"
++	{ }		/* Terminating entry */
++};
++MODULE_DEVICE_TABLE(usb, jumpshot_usb_ids);
++
++#undef UNUSUAL_DEV
++
++/*
++ * The flags table
++ */
++#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
++		    vendor_name, product_name, use_protocol, use_transport, \
++		    init_function, Flags) \
++{ \
++	.vendorName = vendor_name,	\
++	.productName = product_name,	\
++	.useProtocol = use_protocol,	\
++	.useTransport = use_transport,	\
++	.initFunction = init_function,	\
++}
++
++static struct us_unusual_dev jumpshot_unusual_dev_list[] = {
++#	include "unusual_jumpshot.h"
++	{ }		/* Terminating entry */
++};
++
++#undef UNUSUAL_DEV
++
++
++struct jumpshot_info {
++   unsigned long   sectors;     /* total sector count */
++   unsigned long   ssize;       /* sector size in bytes */
++
++   /* the following aren't used yet */
++   unsigned char   sense_key;
++   unsigned long   sense_asc;   /* additional sense code */
++   unsigned long   sense_ascq;  /* additional sense code qualifier */
++};
++
+ static inline int jumpshot_bulk_read(struct us_data *us,
+ 				     unsigned char *data, 
+ 				     unsigned int len)
+@@ -429,7 +478,7 @@ static void jumpshot_info_destructor(void *extra)
+ 
+ // Transport for the Lexar 'Jumpshot'
+ //
+-int jumpshot_transport(struct scsi_cmnd * srb, struct us_data *us)
++static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
+ {
+ 	struct jumpshot_info *info;
+ 	int rc;
+@@ -592,3 +641,49 @@ int jumpshot_transport(struct scsi_cmnd * srb, struct us_data *us)
+ 	info->sense_ascq = 0x00;
+ 	return USB_STOR_TRANSPORT_FAILED;
+ }
++
++static int jumpshot_probe(struct usb_interface *intf,
++			 const struct usb_device_id *id)
++{
++	struct us_data *us;
++	int result;
++
++	result = usb_stor_probe1(&us, intf, id,
++			(id - jumpshot_usb_ids) + jumpshot_unusual_dev_list);
++	if (result)
++		return result;
++
++	us->transport_name  = "Lexar Jumpshot Control/Bulk";
++	us->transport = jumpshot_transport;
++	us->transport_reset = usb_stor_Bulk_reset;
++	us->max_lun = 1;
++
++	result = usb_stor_probe2(us);
++	return result;
++}
++
++static struct usb_driver jumpshot_driver = {
++	.name =		"ums-jumpshot",
++	.probe =	jumpshot_probe,
++	.disconnect =	usb_stor_disconnect,
++	.suspend =	usb_stor_suspend,
++	.resume =	usb_stor_resume,
++	.reset_resume =	usb_stor_reset_resume,
++	.pre_reset =	usb_stor_pre_reset,
++	.post_reset =	usb_stor_post_reset,
++	.id_table =	jumpshot_usb_ids,
++	.soft_unbind =	1,
++};
++
++static int __init jumpshot_init(void)
++{
++	return usb_register(&jumpshot_driver);
++}
++
++static void __exit jumpshot_exit(void)
++{
++	usb_deregister(&jumpshot_driver);
++}
++
++module_init(jumpshot_init);
++module_exit(jumpshot_exit);
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index a5867c6d761b..24e23c29d292 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -794,14 +794,6 @@ UNUSUAL_DEV(  0x05c6, 0x1000, 0x0000, 0x9999,
+ 		US_SC_DEVICE, US_PR_DEVICE, option_ms_init,
+ 		0),
+ 
+-#ifdef CONFIG_USB_STORAGE_JUMPSHOT
+-UNUSUAL_DEV(  0x05dc, 0x0001, 0x0000, 0x0001,
+-		"Lexar",
+-		"Jumpshot USB CF Reader",
+-		US_SC_SCSI, US_PR_JUMPSHOT, NULL,
+-		US_FL_NEED_OVERRIDE ),
+-#endif
+-
+ /* Reported by Blake Matheny  */
+ UNUSUAL_DEV(  0x05dc, 0xb002, 0x0000, 0x0113,
+ 		"Lexar",
+diff --git a/drivers/usb/storage/jumpshot.h b/drivers/usb/storage/unusual_jumpshot.h
+similarity index 50%
+rename from drivers/usb/storage/jumpshot.h
+rename to drivers/usb/storage/unusual_jumpshot.h
+index 19bac9d1558f..2e549b1c2c62 100644
+--- a/drivers/usb/storage/jumpshot.h
++++ b/drivers/usb/storage/unusual_jumpshot.h
+@@ -1,10 +1,4 @@
+-/* Driver for Lexar "Jumpshot" USB Compact Flash reader
+- * Header File
+- *
+- * Current development and maintenance by:
+- *   (c) 2000 Jimmie Mayfield (mayfield+usb@sackheads.org)
+- *
+- * See jumpshot.c for more explanation
++/* Unusual Devices File for the Lexar "Jumpshot" Compact Flash reader
+  *
+  * This program is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License as published by the
+@@ -21,19 +15,13 @@
+  * 675 Mass Ave, Cambridge, MA 02139, USA.
+  */
+ 
+-#ifndef _USB_JUMPSHOT_H
+-#define _USB_JUMPSHOT_H
+-
+-extern int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us);
++#if defined(CONFIG_USB_STORAGE_JUMPSHOT) || \
++		defined(CONFIG_USB_STORAGE_JUMPSHOT_MODULE)
+ 
+-struct jumpshot_info {
+-   unsigned long   sectors;     // total sector count
+-   unsigned long   ssize;       // sector size in bytes
+- 
+-   // the following aren't used yet
+-   unsigned char   sense_key;
+-   unsigned long   sense_asc;   // additional sense code
+-   unsigned long   sense_ascq;  // additional sense code qualifier
+-};
++UNUSUAL_DEV(  0x05dc, 0x0001, 0x0000, 0x0001,
++		"Lexar",
++		"Jumpshot USB CF Reader",
++		US_SC_SCSI, US_PR_JUMPSHOT, NULL,
++		US_FL_NEED_OVERRIDE),
+ 
+-#endif
++#endif /* defined(CONFIG_USB_STORAGE_JUMPSHOT) || ... */
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index a537b3513b9b..2ea57691a7ba 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -66,9 +66,6 @@
+ #include "debug.h"
+ #include "initializers.h"
+ 
+-#ifdef CONFIG_USB_STORAGE_JUMPSHOT
+-#include "jumpshot.h"
+-#endif
+ #ifdef CONFIG_USB_STORAGE_ONETOUCH
+ #include "onetouch.h"
+ #endif
+@@ -601,15 +598,6 @@ static void get_transport(struct us_data *us)
+ 		us->transport_reset = usb_stor_Bulk_reset;
+ 		break;
+ 
+-#ifdef CONFIG_USB_STORAGE_JUMPSHOT
+-	case US_PR_JUMPSHOT:
+-		us->transport_name  = "Lexar Jumpshot Control/Bulk";
+-		us->transport = jumpshot_transport;
+-		us->transport_reset = usb_stor_Bulk_reset;
+-		us->max_lun = 1;
+-		break;
+-#endif
+-
+ #ifdef CONFIG_USB_STORAGE_ALAUDA
+ 	case US_PR_ALAUDA:
+ 		us->transport_name  = "Alauda Control/Bulk";
+diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c
+index c6ceac62cf60..182a097e0767 100644
+--- a/drivers/usb/storage/usual-tables.c
++++ b/drivers/usb/storage/usual-tables.c
+@@ -81,6 +81,7 @@ static struct ignore_entry ignore_ids[] = {
+ #	include "unusual_datafab.h"
+ #	include "unusual_freecom.h"
+ #	include "unusual_isd200.h"
++#	include "unusual_jumpshot.h"
+ #	include "unusual_sddr09.h"
+ #	include "unusual_sddr55.h"
+ #	include "unusual_usbat.h"

commit 2cbbf3576aa9eae9a92f2669f38a453b6cb8e956
+Author: Alan Stern 
+Date:   Thu Feb 12 14:48:15 2009 -0500
+
+    usb-storage: make datafab a separate module
+    
+    This patch (as1213) converts usb-storage's datafab subdriver into a
+    separate module.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
+index 14508b8a55fb..7dac413e0f2f 100644
+--- a/drivers/usb/storage/Kconfig
++++ b/drivers/usb/storage/Kconfig
+@@ -32,12 +32,14 @@ config USB_STORAGE_DEBUG
+ 	  verbose debugging messages.
+ 
+ config USB_STORAGE_DATAFAB
+-	bool "Datafab Compact Flash Reader support"
++	tristate "Datafab Compact Flash Reader support"
+ 	depends on USB_STORAGE
+ 	help
+ 	  Support for certain Datafab CompactFlash readers.
+ 	  Datafab has a web page at .
+ 
++	  If this driver is compiled as a module, it will be named ums-datafab.
++
+ config USB_STORAGE_FREECOM
+ 	tristate "Freecom USB/ATAPI Bridge support"
+ 	depends on USB_STORAGE
+diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
+index 93e91ec3a2d2..0f78bd680f0f 100644
+--- a/drivers/usb/storage/Makefile
++++ b/drivers/usb/storage/Makefile
+@@ -10,7 +10,6 @@ EXTRA_CFLAGS	:= -Idrivers/scsi
+ obj-$(CONFIG_USB_STORAGE)	+= usb-storage.o
+ 
+ usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG)	+= debug.o
+-usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB)	+= datafab.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT)	+= jumpshot.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA)	+= alauda.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH)	+= onetouch.o
+@@ -26,6 +25,7 @@ else
+ endif
+ 
+ obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o
++obj-$(CONFIG_USB_STORAGE_DATAFAB)	+= ums-datafab.o
+ obj-$(CONFIG_USB_STORAGE_FREECOM)	+= ums-freecom.o
+ obj-$(CONFIG_USB_STORAGE_ISD200)	+= ums-isd200.o
+ obj-$(CONFIG_USB_STORAGE_SDDR09)	+= ums-sddr09.o
+@@ -33,6 +33,7 @@ obj-$(CONFIG_USB_STORAGE_SDDR55)	+= ums-sddr55.o
+ obj-$(CONFIG_USB_STORAGE_USBAT)		+= ums-usbat.o
+ 
+ ums-cypress-objs	:= cypress_atacb.o
++ums-datafab-objs	:= datafab.o
+ ums-freecom-objs	:= freecom.o
+ ums-isd200-objs		:= isd200.o
+ ums-sddr09-objs		:= sddr09.o
+diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c
+index 17f1ae232919..2d8d83519090 100644
+--- a/drivers/usb/storage/datafab.c
++++ b/drivers/usb/storage/datafab.c
+@@ -49,6 +49,7 @@
+  */
+ 
+ #include 
++#include 
+ #include 
+ 
+ #include 
+@@ -58,12 +59,61 @@
+ #include "transport.h"
+ #include "protocol.h"
+ #include "debug.h"
+-#include "datafab.h"
++
++struct datafab_info {
++	unsigned long   sectors;	/* total sector count */
++	unsigned long   ssize;		/* sector size in bytes */
++	signed char	lun;		/* used for dual-slot readers */
++
++	/* the following aren't used yet */
++	unsigned char   sense_key;
++	unsigned long   sense_asc;	/* additional sense code */
++	unsigned long   sense_ascq;	/* additional sense code qualifier */
++};
+ 
+ static int datafab_determine_lun(struct us_data *us,
+ 				 struct datafab_info *info);
+ 
+ 
++/*
++ * The table of devices
++ */
++#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
++		    vendorName, productName, useProtocol, useTransport, \
++		    initFunction, flags) \
++{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
++  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
++
++struct usb_device_id datafab_usb_ids[] = {
++#	include "unusual_datafab.h"
++	{ }		/* Terminating entry */
++};
++MODULE_DEVICE_TABLE(usb, datafab_usb_ids);
++
++#undef UNUSUAL_DEV
++
++/*
++ * The flags table
++ */
++#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
++		    vendor_name, product_name, use_protocol, use_transport, \
++		    init_function, Flags) \
++{ \
++	.vendorName = vendor_name,	\
++	.productName = product_name,	\
++	.useProtocol = use_protocol,	\
++	.useTransport = use_transport,	\
++	.initFunction = init_function,	\
++}
++
++static struct us_unusual_dev datafab_unusual_dev_list[] = {
++#	include "unusual_datafab.h"
++	{ }		/* Terminating entry */
++};
++
++#undef UNUSUAL_DEV
++
++
+ static inline int
+ datafab_bulk_read(struct us_data *us, unsigned char *data, unsigned int len) {
+ 	if (len == 0)
+@@ -500,7 +550,7 @@ static void datafab_info_destructor(void *extra)
+ 
+ // Transport for the Datafab MDCFE-B
+ //
+-int datafab_transport(struct scsi_cmnd * srb, struct us_data *us)
++static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
+ {
+ 	struct datafab_info *info;
+ 	int rc;
+@@ -665,3 +715,49 @@ int datafab_transport(struct scsi_cmnd * srb, struct us_data *us)
+ 	info->sense_ascq = 0x00;
+ 	return USB_STOR_TRANSPORT_FAILED;
+ }
++
++static int datafab_probe(struct usb_interface *intf,
++			 const struct usb_device_id *id)
++{
++	struct us_data *us;
++	int result;
++
++	result = usb_stor_probe1(&us, intf, id,
++			(id - datafab_usb_ids) + datafab_unusual_dev_list);
++	if (result)
++		return result;
++
++	us->transport_name  = "Datafab Bulk-Only";
++	us->transport = datafab_transport;
++	us->transport_reset = usb_stor_Bulk_reset;
++	us->max_lun = 1;
++
++	result = usb_stor_probe2(us);
++	return result;
++}
++
++static struct usb_driver datafab_driver = {
++	.name =		"ums-datafab",
++	.probe =	datafab_probe,
++	.disconnect =	usb_stor_disconnect,
++	.suspend =	usb_stor_suspend,
++	.resume =	usb_stor_resume,
++	.reset_resume =	usb_stor_reset_resume,
++	.pre_reset =	usb_stor_pre_reset,
++	.post_reset =	usb_stor_post_reset,
++	.id_table =	datafab_usb_ids,
++	.soft_unbind =	1,
++};
++
++static int __init datafab_init(void)
++{
++	return usb_register(&datafab_driver);
++}
++
++static void __exit datafab_exit(void)
++{
++	usb_deregister(&datafab_driver);
++}
++
++module_init(datafab_init);
++module_exit(datafab_exit);
+diff --git a/drivers/usb/storage/datafab.h b/drivers/usb/storage/datafab.h
+deleted file mode 100644
+index 32e3f271e582..000000000000
+--- a/drivers/usb/storage/datafab.h
++++ /dev/null
+@@ -1,40 +0,0 @@
+-/* Driver for Datafab MDCFE-B USB Compact Flash reader
+- * Header File
+- *
+- * Current development and maintenance by:
+- *   (c) 2000 Jimmie Mayfield (mayfield+datafab@sackheads.org)
+- *
+- * See datafab.c for more explanation
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the
+- * Free Software Foundation; either version 2, or (at your option) any
+- * later version.
+- *
+- * This program is distributed in the hope that it will be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#ifndef _USB_DATAFAB_MDCFE_B_H
+-#define _USB_DATAFAB_MDCFE_B_H
+-
+-extern int datafab_transport(struct scsi_cmnd *srb, struct us_data *us);
+-
+-struct datafab_info {
+-	unsigned long   sectors;	// total sector count
+-	unsigned long   ssize;		// sector size in bytes
+-	signed char	lun;		// used for dual-slot readers
+-	
+-	// the following aren't used yet
+-	unsigned char   sense_key;
+-	unsigned long   sense_asc;	// additional sense code
+-	unsigned long   sense_ascq;	// additional sense code qualifier
+-};
+-
+-#endif
+diff --git a/drivers/usb/storage/unusual_datafab.h b/drivers/usb/storage/unusual_datafab.h
+new file mode 100644
+index 000000000000..c9298ce9f223
+--- /dev/null
++++ b/drivers/usb/storage/unusual_datafab.h
+@@ -0,0 +1,98 @@
++/* Unusual Devices File for the Datafab USB Compact Flash reader
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2, or (at your option) any
++ * later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#if defined(CONFIG_USB_STORAGE_DATAFAB) || \
++		defined(CONFIG_USB_STORAGE_DATAFAB_MODULE)
++
++UNUSUAL_DEV(  0x07c4, 0xa000, 0x0000, 0x0015,
++		"Datafab",
++		"MDCFE-B USB CF Reader",
++		US_SC_SCSI, US_PR_DATAFAB, NULL,
++		0),
++
++/*
++ * The following Datafab-based devices may or may not work
++ * using the current driver...the 0xffff is arbitrary since I
++ * don't know what device versions exist for these guys.
++ *
++ * The 0xa003 and 0xa004 devices in particular I'm curious about.
++ * I'm told they exist but so far nobody has come forward to say that
++ * they work with this driver.  Given the success we've had getting
++ * other Datafab-based cards operational with this driver, I've decided
++ * to leave these two devices in the list.
++ */
++UNUSUAL_DEV( 0x07c4, 0xa001, 0x0000, 0xffff,
++		"SIIG/Datafab",
++		"SIIG/Datafab Memory Stick+CF Reader/Writer",
++		US_SC_SCSI, US_PR_DATAFAB, NULL,
++		0),
++
++/* Reported by Josef Reisinger  */
++UNUSUAL_DEV( 0x07c4, 0xa002, 0x0000, 0xffff,
++		"Datafab/Unknown",
++		"MD2/MD3 Disk enclosure",
++		US_SC_SCSI, US_PR_DATAFAB, NULL,
++		US_FL_SINGLE_LUN),
++
++UNUSUAL_DEV( 0x07c4, 0xa003, 0x0000, 0xffff,
++		"Datafab/Unknown",
++		"Datafab-based Reader",
++		US_SC_SCSI, US_PR_DATAFAB, NULL,
++		0),
++
++UNUSUAL_DEV( 0x07c4, 0xa004, 0x0000, 0xffff,
++		"Datafab/Unknown",
++		"Datafab-based Reader",
++		US_SC_SCSI, US_PR_DATAFAB, NULL,
++		0),
++
++UNUSUAL_DEV( 0x07c4, 0xa005, 0x0000, 0xffff,
++		"PNY/Datafab",
++		"PNY/Datafab CF+SM Reader",
++		US_SC_SCSI, US_PR_DATAFAB, NULL,
++		0),
++
++UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xffff,
++		"Simple Tech/Datafab",
++		"Simple Tech/Datafab CF+SM Reader",
++		US_SC_SCSI, US_PR_DATAFAB, NULL,
++		0),
++
++/* Submitted by Olaf Hering  */
++UNUSUAL_DEV(  0x07c4, 0xa109, 0x0000, 0xffff,
++		"Datafab Systems, Inc.",
++		"USB to CF + SM Combo (LC1)",
++		US_SC_SCSI, US_PR_DATAFAB, NULL,
++		0),
++
++/* Reported by Felix Moeller 
++ * in Germany this is sold by Hama with the productnumber 46952
++ * as "DualSlot CompactFlash(TM) & MStick Drive USB"
++ */
++UNUSUAL_DEV(  0x07c4, 0xa10b, 0x0000, 0xffff,
++		"DataFab Systems Inc.",
++		"USB CF+MS",
++		US_SC_SCSI, US_PR_DATAFAB, NULL,
++		0),
++
++UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff,
++		"Acomdata",
++		"CF",
++		US_SC_SCSI, US_PR_DATAFAB, NULL,
++		US_FL_SINGLE_LUN),
++
++#endif /* defined(CONFIG_USB_STORAGE_DATAFAB) || ... */
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index eef2075cf2eb..a5867c6d761b 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -992,84 +992,6 @@ UNUSUAL_DEV(  0x07b4, 0x010a, 0x0102, 0x0102,
+  		US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ),
+ #endif
+ 
+-#ifdef CONFIG_USB_STORAGE_DATAFAB
+-UNUSUAL_DEV(  0x07c4, 0xa000, 0x0000, 0x0015,
+-		"Datafab",
+-		"MDCFE-B USB CF Reader",
+-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+-		0 ),
+-
+-/*
+- * The following Datafab-based devices may or may not work
+- * using the current driver...the 0xffff is arbitrary since I
+- * don't know what device versions exist for these guys.
+- *
+- * The 0xa003 and 0xa004 devices in particular I'm curious about.
+- * I'm told they exist but so far nobody has come forward to say that
+- * they work with this driver.  Given the success we've had getting
+- * other Datafab-based cards operational with this driver, I've decided
+- * to leave these two devices in the list.
+- */
+-UNUSUAL_DEV( 0x07c4, 0xa001, 0x0000, 0xffff,
+-		"SIIG/Datafab",
+-		"SIIG/Datafab Memory Stick+CF Reader/Writer",
+-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+-		0 ),
+-
+-/* Reported by Josef Reisinger  */
+-UNUSUAL_DEV( 0x07c4, 0xa002, 0x0000, 0xffff,
+-		"Datafab/Unknown",
+-		"MD2/MD3 Disk enclosure",
+-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+-		US_FL_SINGLE_LUN ),
+-
+-UNUSUAL_DEV( 0x07c4, 0xa003, 0x0000, 0xffff,
+-		"Datafab/Unknown",
+-		"Datafab-based Reader",
+-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+-		0 ),
+-
+-UNUSUAL_DEV( 0x07c4, 0xa004, 0x0000, 0xffff,
+-		"Datafab/Unknown",
+-		"Datafab-based Reader",
+-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+-		0 ),
+-
+-UNUSUAL_DEV( 0x07c4, 0xa005, 0x0000, 0xffff,
+-		"PNY/Datafab",
+-		"PNY/Datafab CF+SM Reader",
+-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+-		0 ),
+-
+-UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xffff,
+-		"Simple Tech/Datafab",
+-		"Simple Tech/Datafab CF+SM Reader",
+-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+-		0 ),
+-#endif
+-
+-#ifdef CONFIG_USB_STORAGE_DATAFAB
+-/* Submitted by Olaf Hering  */
+-UNUSUAL_DEV(  0x07c4, 0xa109, 0x0000, 0xffff,
+-		"Datafab Systems, Inc.",
+-		"USB to CF + SM Combo (LC1)",
+-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+-		0 ),
+-#endif
+-
+-#ifdef CONFIG_USB_STORAGE_DATAFAB
+-/* Reported by Felix Moeller 
+- * in Germany this is sold by Hama with the productnumber 46952
+- * as "DualSlot CompactFlash(TM) & MStick Drive USB"
+- */
+-UNUSUAL_DEV(  0x07c4, 0xa10b, 0x0000, 0xffff,
+-		"DataFab Systems Inc.",
+-		"USB CF+MS",
+-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+-		0 ),
+-
+-#endif
+-
+ /* Datafab KECF-USB / Sagatek DCS-CF / Simpletech Flashlink UCF-100
+  * Only revision 1.13 tested (same for all of the above devices,
+  * based on the Datafab DF-UG-07 chip).  Needed for US_FL_FIX_INQUIRY.
+@@ -1273,14 +1195,6 @@ UNUSUAL_DEV( 0x0bc2, 0x3010, 0x0000, 0x0000,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_SANE_SENSE ),
+ 
+-#ifdef CONFIG_USB_STORAGE_DATAFAB
+-UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff,
+-		"Acomdata",
+-		"CF",
+-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+-		US_FL_SINGLE_LUN ),
+-#endif
+-
+ UNUSUAL_DEV(  0x0d49, 0x7310, 0x0000, 0x9999,
+ 		"Maxtor",
+ 		"USB to SATA",
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 985275d5d4c5..a537b3513b9b 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -66,9 +66,6 @@
+ #include "debug.h"
+ #include "initializers.h"
+ 
+-#ifdef CONFIG_USB_STORAGE_DATAFAB
+-#include "datafab.h"
+-#endif
+ #ifdef CONFIG_USB_STORAGE_JUMPSHOT
+ #include "jumpshot.h"
+ #endif
+@@ -604,15 +601,6 @@ static void get_transport(struct us_data *us)
+ 		us->transport_reset = usb_stor_Bulk_reset;
+ 		break;
+ 
+-#ifdef CONFIG_USB_STORAGE_DATAFAB
+-	case US_PR_DATAFAB:
+-		us->transport_name  = "Datafab Bulk-Only";
+-		us->transport = datafab_transport;
+-		us->transport_reset = usb_stor_Bulk_reset;
+-		us->max_lun = 1;
+-		break;
+-#endif
+-
+ #ifdef CONFIG_USB_STORAGE_JUMPSHOT
+ 	case US_PR_JUMPSHOT:
+ 		us->transport_name  = "Lexar Jumpshot Control/Bulk";
+diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c
+index a50f0eefb739..c6ceac62cf60 100644
+--- a/drivers/usb/storage/usual-tables.c
++++ b/drivers/usb/storage/usual-tables.c
+@@ -78,6 +78,7 @@ struct ignore_entry {
+ 
+ static struct ignore_entry ignore_ids[] = {
+ #	include "unusual_cypress.h"
++#	include "unusual_datafab.h"
+ #	include "unusual_freecom.h"
+ #	include "unusual_isd200.h"
+ #	include "unusual_sddr09.h"

commit 0d62939fab3cf28a23ac6934cec599793d3a1d9d
+Author: Alan Stern 
+Date:   Thu Feb 12 14:48:11 2009 -0500
+
+    usb-storage: make freecom a separate module
+    
+    This patch (as1212) converts usb-storage's freecom subdriver into a
+    separate module.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
+index 44c6b1940f77..14508b8a55fb 100644
+--- a/drivers/usb/storage/Kconfig
++++ b/drivers/usb/storage/Kconfig
+@@ -39,12 +39,14 @@ config USB_STORAGE_DATAFAB
+ 	  Datafab has a web page at .
+ 
+ config USB_STORAGE_FREECOM
+-	bool "Freecom USB/ATAPI Bridge support"
++	tristate "Freecom USB/ATAPI Bridge support"
+ 	depends on USB_STORAGE
+ 	help
+ 	  Support for the Freecom USB to IDE/ATAPI adaptor.
+ 	  Freecom has a web page at .
+ 
++	  If this driver is compiled as a module, it will be named ums-freecom.
++
+ config USB_STORAGE_ISD200
+ 	tristate "ISD-200 USB/ATA Bridge support"
+ 	depends on USB_STORAGE
+diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
+index 2387368cb7ae..93e91ec3a2d2 100644
+--- a/drivers/usb/storage/Makefile
++++ b/drivers/usb/storage/Makefile
+@@ -10,7 +10,6 @@ EXTRA_CFLAGS	:= -Idrivers/scsi
+ obj-$(CONFIG_USB_STORAGE)	+= usb-storage.o
+ 
+ usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG)	+= debug.o
+-usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM)	+= freecom.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB)	+= datafab.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT)	+= jumpshot.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA)	+= alauda.o
+@@ -27,12 +26,14 @@ else
+ endif
+ 
+ obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o
++obj-$(CONFIG_USB_STORAGE_FREECOM)	+= ums-freecom.o
+ obj-$(CONFIG_USB_STORAGE_ISD200)	+= ums-isd200.o
+ obj-$(CONFIG_USB_STORAGE_SDDR09)	+= ums-sddr09.o
+ obj-$(CONFIG_USB_STORAGE_SDDR55)	+= ums-sddr55.o
+ obj-$(CONFIG_USB_STORAGE_USBAT)		+= ums-usbat.o
+ 
+ ums-cypress-objs	:= cypress_atacb.o
++ums-freecom-objs	:= freecom.o
+ ums-isd200-objs		:= isd200.o
+ ums-sddr09-objs		:= sddr09.o
+ ums-sddr55-objs		:= sddr55.o
+diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
+index 73ac7262239e..393047b3890d 100644
+--- a/drivers/usb/storage/freecom.c
++++ b/drivers/usb/storage/freecom.c
+@@ -26,6 +26,7 @@
+  * (http://www.freecom.de/)
+  */
+ 
++#include 
+ #include 
+ #include 
+ 
+@@ -33,7 +34,6 @@
+ #include "transport.h"
+ #include "protocol.h"
+ #include "debug.h"
+-#include "freecom.h"
+ 
+ #ifdef CONFIG_USB_STORAGE_DEBUG
+ static void pdump (void *, int);
+@@ -103,6 +103,47 @@ struct freecom_status {
+ #define FCM_PACKET_LENGTH		64
+ #define FCM_STATUS_PACKET_LENGTH	4
+ 
++static int init_freecom(struct us_data *us);
++
++
++/*
++ * The table of devices
++ */
++#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
++		    vendorName, productName, useProtocol, useTransport, \
++		    initFunction, flags) \
++{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
++  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
++
++struct usb_device_id freecom_usb_ids[] = {
++#	include "unusual_freecom.h"
++	{ }		/* Terminating entry */
++};
++MODULE_DEVICE_TABLE(usb, freecom_usb_ids);
++
++#undef UNUSUAL_DEV
++
++/*
++ * The flags table
++ */
++#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
++		    vendor_name, product_name, use_protocol, use_transport, \
++		    init_function, Flags) \
++{ \
++	.vendorName = vendor_name,	\
++	.productName = product_name,	\
++	.useProtocol = use_protocol,	\
++	.useTransport = use_transport,	\
++	.initFunction = init_function,	\
++}
++
++static struct us_unusual_dev freecom_unusual_dev_list[] = {
++#	include "unusual_freecom.h"
++	{ }		/* Terminating entry */
++};
++
++#undef UNUSUAL_DEV
++
+ static int
+ freecom_readdata (struct scsi_cmnd *srb, struct us_data *us,
+ 		unsigned int ipipe, unsigned int opipe, int count)
+@@ -173,7 +214,7 @@ freecom_writedata (struct scsi_cmnd *srb, struct us_data *us,
+  * Transport for the Freecom USB/IDE adaptor.
+  *
+  */
+-int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
++static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
+ {
+ 	struct freecom_cb_wrap *fcb;
+ 	struct freecom_status  *fst;
+@@ -377,8 +418,7 @@ int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 	return USB_STOR_TRANSPORT_GOOD;
+ }
+ 
+-int
+-freecom_init (struct us_data *us)
++static int init_freecom(struct us_data *us)
+ {
+ 	int result;
+ 	char *buffer = us->iobuf;
+@@ -417,7 +457,7 @@ freecom_init (struct us_data *us)
+ 	return USB_STOR_TRANSPORT_GOOD;
+ }
+ 
+-int usb_stor_freecom_reset(struct us_data *us)
++static int usb_stor_freecom_reset(struct us_data *us)
+ {
+ 	printk (KERN_CRIT "freecom reset called\n");
+ 
+@@ -479,3 +519,48 @@ static void pdump (void *ibuffer, int length)
+ }
+ #endif
+ 
++static int freecom_probe(struct usb_interface *intf,
++			 const struct usb_device_id *id)
++{
++	struct us_data *us;
++	int result;
++
++	result = usb_stor_probe1(&us, intf, id,
++			(id - freecom_usb_ids) + freecom_unusual_dev_list);
++	if (result)
++		return result;
++
++	us->transport_name = "Freecom";
++	us->transport = freecom_transport;
++	us->transport_reset = usb_stor_freecom_reset;
++	us->max_lun = 0;
++
++	result = usb_stor_probe2(us);
++	return result;
++}
++
++static struct usb_driver freecom_driver = {
++	.name =		"ums-freecom",
++	.probe =	freecom_probe,
++	.disconnect =	usb_stor_disconnect,
++	.suspend =	usb_stor_suspend,
++	.resume =	usb_stor_resume,
++	.reset_resume =	usb_stor_reset_resume,
++	.pre_reset =	usb_stor_pre_reset,
++	.post_reset =	usb_stor_post_reset,
++	.id_table =	freecom_usb_ids,
++	.soft_unbind =	1,
++};
++
++static int __init freecom_init(void)
++{
++	return usb_register(&freecom_driver);
++}
++
++static void __exit freecom_exit(void)
++{
++	usb_deregister(&freecom_driver);
++}
++
++module_init(freecom_init);
++module_exit(freecom_exit);
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 6462c4c54dc0..eef2075cf2eb 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -958,13 +958,6 @@ UNUSUAL_DEV(  0x0781, 0x0100, 0x0100, 0x0100,
+ 		US_SC_SCSI, US_PR_CB, NULL,
+ 		US_FL_SINGLE_LUN ),
+ 
+-#ifdef CONFIG_USB_STORAGE_FREECOM
+-UNUSUAL_DEV(  0x07ab, 0xfc01, 0x0000, 0x9999,
+-		"Freecom",
+-		"USB-IDE",
+-		US_SC_QIC, US_PR_FREECOM, freecom_init, 0),
+-#endif
+-
+ /* Reported by Eero Volotinen  */
+ UNUSUAL_DEV(  0x07ab, 0xfccd, 0x0000, 0x9999,
+ 		"Freecom Technologies",
+diff --git a/drivers/usb/storage/freecom.h b/drivers/usb/storage/unusual_freecom.h
+similarity index 60%
+rename from drivers/usb/storage/freecom.h
+rename to drivers/usb/storage/unusual_freecom.h
+index 20d0fe6ba0c8..375867942391 100644
+--- a/drivers/usb/storage/freecom.h
++++ b/drivers/usb/storage/unusual_freecom.h
+@@ -1,13 +1,4 @@
+-/* Driver for Freecom USB/IDE adaptor
+- *
+- * Freecom v0.1:
+- *
+- * First release
+- *
+- * Current development and maintenance by:
+- *   (c) 2000 David Brown 
+- *
+- * See freecom.c for more explanation
++/* Unusual Devices File for the Freecom USB/IDE adaptor
+  *
+  * This program is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License as published by the
+@@ -24,11 +15,12 @@
+  * 675 Mass Ave, Cambridge, MA 02139, USA.
+  */
+ 
+-#ifndef _FREECOM_USB_H
+-#define _FREECOM_USB_H
++#if defined(CONFIG_USB_STORAGE_FREECOM) || \
++		defined(CONFIG_USB_STORAGE_FREECOM_MODULE)
+ 
+-extern int freecom_transport(struct scsi_cmnd *srb, struct us_data *us);
+-extern int usb_stor_freecom_reset(struct us_data *us);
+-extern int freecom_init (struct us_data *us);
++UNUSUAL_DEV(  0x07ab, 0xfc01, 0x0000, 0x9999,
++		"Freecom",
++		"USB-IDE",
++		US_SC_QIC, US_PR_FREECOM, init_freecom, 0),
+ 
+-#endif
++#endif /* defined(CONFIG_USB_STORAGE_FREECOM) || ... */
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 3ad22a8142cc..985275d5d4c5 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -66,9 +66,6 @@
+ #include "debug.h"
+ #include "initializers.h"
+ 
+-#ifdef CONFIG_USB_STORAGE_FREECOM
+-#include "freecom.h"
+-#endif
+ #ifdef CONFIG_USB_STORAGE_DATAFAB
+ #include "datafab.h"
+ #endif
+@@ -607,15 +604,6 @@ static void get_transport(struct us_data *us)
+ 		us->transport_reset = usb_stor_Bulk_reset;
+ 		break;
+ 
+-#ifdef CONFIG_USB_STORAGE_FREECOM
+-	case US_PR_FREECOM:
+-		us->transport_name = "Freecom";
+-		us->transport = freecom_transport;
+-		us->transport_reset = usb_stor_freecom_reset;
+-		us->max_lun = 0;
+-		break;
+-#endif
+-
+ #ifdef CONFIG_USB_STORAGE_DATAFAB
+ 	case US_PR_DATAFAB:
+ 		us->transport_name  = "Datafab Bulk-Only";
+diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c
+index 899a8c8da712..a50f0eefb739 100644
+--- a/drivers/usb/storage/usual-tables.c
++++ b/drivers/usb/storage/usual-tables.c
+@@ -78,6 +78,7 @@ struct ignore_entry {
+ 
+ static struct ignore_entry ignore_ids[] = {
+ #	include "unusual_cypress.h"
++#	include "unusual_freecom.h"
+ #	include "unusual_isd200.h"
+ #	include "unusual_sddr09.h"
+ #	include "unusual_sddr55.h"

commit 26d6818f19d0ab018f28a20d699511c1efdf508b
+Author: Alan Stern 
+Date:   Thu Feb 12 14:48:08 2009 -0500
+
+    usb-storage: make shuttle_usbat a separate module
+    
+    This patch (as1211) converts usb-storage's shuttle_usbat subdriver
+    into a separate module.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
+index 2c73fa97d94d..44c6b1940f77 100644
+--- a/drivers/usb/storage/Kconfig
++++ b/drivers/usb/storage/Kconfig
+@@ -64,7 +64,7 @@ config USB_STORAGE_ISD200
+ 	  If this driver is compiled as a module, it will be named ums-isd200.
+ 
+ config USB_STORAGE_USBAT
+-	bool "USBAT/USBAT02-based storage support"
++	tristate "USBAT/USBAT02-based storage support"
+ 	depends on USB_STORAGE
+ 	help
+ 	  Say Y here to include additional code to support storage devices
+@@ -84,6 +84,8 @@ config USB_STORAGE_USBAT
+ 	  - RCA LYRA MP3 portable
+ 	  - Sandisk ImageMate SDDR-05b
+ 
++	  If this driver is compiled as a module, it will be named ums-usbat.
++
+ config USB_STORAGE_SDDR09
+ 	tristate "SanDisk SDDR-09 (and other SmartMedia, including DPCM) support"
+ 	depends on USB_STORAGE
+diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
+index 0650f022e561..2387368cb7ae 100644
+--- a/drivers/usb/storage/Makefile
++++ b/drivers/usb/storage/Makefile
+@@ -10,7 +10,6 @@ EXTRA_CFLAGS	:= -Idrivers/scsi
+ obj-$(CONFIG_USB_STORAGE)	+= usb-storage.o
+ 
+ usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG)	+= debug.o
+-usb-storage-obj-$(CONFIG_USB_STORAGE_USBAT)	+= shuttle_usbat.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM)	+= freecom.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB)	+= datafab.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT)	+= jumpshot.o
+@@ -31,8 +30,10 @@ obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o
+ obj-$(CONFIG_USB_STORAGE_ISD200)	+= ums-isd200.o
+ obj-$(CONFIG_USB_STORAGE_SDDR09)	+= ums-sddr09.o
+ obj-$(CONFIG_USB_STORAGE_SDDR55)	+= ums-sddr55.o
++obj-$(CONFIG_USB_STORAGE_USBAT)		+= ums-usbat.o
+ 
+ ums-cypress-objs	:= cypress_atacb.o
+ ums-isd200-objs		:= isd200.o
+ ums-sddr09-objs		:= sddr09.o
+ ums-sddr55-objs		:= sddr55.o
++ums-usbat-objs		:= shuttle_usbat.o
+diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
+index ae6d64810d2a..d4fe0bb327a7 100644
+--- a/drivers/usb/storage/shuttle_usbat.c
++++ b/drivers/usb/storage/shuttle_usbat.c
+@@ -42,6 +42,7 @@
+  */
+ 
+ #include 
++#include 
+ #include 
+ #include 
+ 
+@@ -52,7 +53,97 @@
+ #include "transport.h"
+ #include "protocol.h"
+ #include "debug.h"
+-#include "shuttle_usbat.h"
++
++
++/* Supported device types */
++#define USBAT_DEV_HP8200	0x01
++#define USBAT_DEV_FLASH		0x02
++
++#define USBAT_EPP_PORT		0x10
++#define USBAT_EPP_REGISTER	0x30
++#define USBAT_ATA		0x40
++#define USBAT_ISA		0x50
++
++/* Commands (need to be logically OR'd with an access type */
++#define USBAT_CMD_READ_REG		0x00
++#define USBAT_CMD_WRITE_REG		0x01
++#define USBAT_CMD_READ_BLOCK	0x02
++#define USBAT_CMD_WRITE_BLOCK	0x03
++#define USBAT_CMD_COND_READ_BLOCK	0x04
++#define USBAT_CMD_COND_WRITE_BLOCK	0x05
++#define USBAT_CMD_WRITE_REGS	0x07
++
++/* Commands (these don't need an access type) */
++#define USBAT_CMD_EXEC_CMD	0x80
++#define USBAT_CMD_SET_FEAT	0x81
++#define USBAT_CMD_UIO		0x82
++
++/* Methods of accessing UIO register */
++#define USBAT_UIO_READ	1
++#define USBAT_UIO_WRITE	0
++
++/* Qualifier bits */
++#define USBAT_QUAL_FCQ	0x20	/* full compare */
++#define USBAT_QUAL_ALQ	0x10	/* auto load subcount */
++
++/* USBAT Flash Media status types */
++#define USBAT_FLASH_MEDIA_NONE	0
++#define USBAT_FLASH_MEDIA_CF	1
++
++/* USBAT Flash Media change types */
++#define USBAT_FLASH_MEDIA_SAME	0
++#define USBAT_FLASH_MEDIA_CHANGED	1
++
++/* USBAT ATA registers */
++#define USBAT_ATA_DATA      0x10  /* read/write data (R/W) */
++#define USBAT_ATA_FEATURES  0x11  /* set features (W) */
++#define USBAT_ATA_ERROR     0x11  /* error (R) */
++#define USBAT_ATA_SECCNT    0x12  /* sector count (R/W) */
++#define USBAT_ATA_SECNUM    0x13  /* sector number (R/W) */
++#define USBAT_ATA_LBA_ME    0x14  /* cylinder low (R/W) */
++#define USBAT_ATA_LBA_HI    0x15  /* cylinder high (R/W) */
++#define USBAT_ATA_DEVICE    0x16  /* head/device selection (R/W) */
++#define USBAT_ATA_STATUS    0x17  /* device status (R) */
++#define USBAT_ATA_CMD       0x17  /* device command (W) */
++#define USBAT_ATA_ALTSTATUS 0x0E  /* status (no clear IRQ) (R) */
++
++/* USBAT User I/O Data registers */
++#define USBAT_UIO_EPAD		0x80 /* Enable Peripheral Control Signals */
++#define USBAT_UIO_CDT		0x40 /* Card Detect (Read Only) */
++				     /* CDT = ACKD & !UI1 & !UI0 */
++#define USBAT_UIO_1		0x20 /* I/O 1 */
++#define USBAT_UIO_0		0x10 /* I/O 0 */
++#define USBAT_UIO_EPP_ATA	0x08 /* 1=EPP mode, 0=ATA mode */
++#define USBAT_UIO_UI1		0x04 /* Input 1 */
++#define USBAT_UIO_UI0		0x02 /* Input 0 */
++#define USBAT_UIO_INTR_ACK	0x01 /* Interrupt (ATA/ISA)/Acknowledge (EPP) */
++
++/* USBAT User I/O Enable registers */
++#define USBAT_UIO_DRVRST	0x80 /* Reset Peripheral */
++#define USBAT_UIO_ACKD		0x40 /* Enable Card Detect */
++#define USBAT_UIO_OE1		0x20 /* I/O 1 set=output/clr=input */
++				     /* If ACKD=1, set OE1 to 1 also. */
++#define USBAT_UIO_OE0		0x10 /* I/O 0 set=output/clr=input */
++#define USBAT_UIO_ADPRST	0x01 /* Reset SCM chip */
++
++/* USBAT Features */
++#define USBAT_FEAT_ETEN	0x80	/* External trigger enable */
++#define USBAT_FEAT_U1	0x08
++#define USBAT_FEAT_U0	0x04
++#define USBAT_FEAT_ET1	0x02
++#define USBAT_FEAT_ET2	0x01
++
++struct usbat_info {
++	int devicetype;
++
++	/* Used for Flash readers only */
++	unsigned long sectors;     /* total sector count */
++	unsigned long ssize;       /* sector size in bytes */
++
++	unsigned char sense_key;
++	unsigned long sense_asc;   /* additional sense code */
++	unsigned long sense_ascq;  /* additional sense code qualifier */
++};
+ 
+ #define short_pack(LSB,MSB) ( ((u16)(LSB)) | ( ((u16)(MSB))<<8 ) )
+ #define LSB_of(s) ((s)&0xFF)
+@@ -63,6 +154,48 @@ static int transferred = 0;
+ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us);
+ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us);
+ 
++static int init_usbat_cd(struct us_data *us);
++static int init_usbat_flash(struct us_data *us);
++
++
++/*
++ * The table of devices
++ */
++#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
++		    vendorName, productName, useProtocol, useTransport, \
++		    initFunction, flags) \
++{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
++  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
++
++struct usb_device_id usbat_usb_ids[] = {
++#	include "unusual_usbat.h"
++	{ }		/* Terminating entry */
++};
++MODULE_DEVICE_TABLE(usb, usbat_usb_ids);
++
++#undef UNUSUAL_DEV
++
++/*
++ * The flags table
++ */
++#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
++		    vendor_name, product_name, use_protocol, use_transport, \
++		    init_function, Flags) \
++{ \
++	.vendorName = vendor_name,	\
++	.productName = product_name,	\
++	.useProtocol = use_protocol,	\
++	.useTransport = use_transport,	\
++	.initFunction = init_function,	\
++}
++
++static struct us_unusual_dev usbat_unusual_dev_list[] = {
++#	include "unusual_usbat.h"
++	{ }		/* Terminating entry */
++};
++
++#undef UNUSUAL_DEV
++
+ /*
+  * Convenience function to produce an ATA read/write sectors command
+  * Use cmd=0x20 for read, cmd=0x30 for write
+@@ -1684,37 +1817,61 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
+ 	return USB_STOR_TRANSPORT_FAILED;
+ }
+ 
+-int init_usbat_cd(struct us_data *us)
++static int init_usbat_cd(struct us_data *us)
+ {
+ 	return init_usbat(us, USBAT_DEV_HP8200);
+ }
+ 
+-
+-int init_usbat_flash(struct us_data *us)
++static int init_usbat_flash(struct us_data *us)
+ {
+ 	return init_usbat(us, USBAT_DEV_FLASH);
+ }
+ 
+-int init_usbat_probe(struct us_data *us)
++static int usbat_probe(struct usb_interface *intf,
++			 const struct usb_device_id *id)
+ {
+-	return init_usbat(us, 0);
++	struct us_data *us;
++	int result;
++
++	result = usb_stor_probe1(&us, intf, id,
++			(id - usbat_usb_ids) + usbat_unusual_dev_list);
++	if (result)
++		return result;
++
++	/* The actual transport will be determined later by the
++	 * initialization routine; this is just a placeholder.
++	 */
++	us->transport_name = "Shuttle USBAT";
++	us->transport = usbat_flash_transport;
++	us->transport_reset = usb_stor_CB_reset;
++	us->max_lun = 1;
++
++	result = usb_stor_probe2(us);
++	return result;
+ }
+ 
+-/*
+- * Default transport function. Attempts to detect which transport function
+- * should be called, makes it the new default, and calls it.
+- *
+- * This function should never be called. Our usbat_init() function detects the
+- * device type and changes the us->transport ptr to the transport function
+- * relevant to the device.
+- * However, we'll support this impossible(?) case anyway.
+- */
+-int usbat_transport(struct scsi_cmnd *srb, struct us_data *us)
++static struct usb_driver usbat_driver = {
++	.name =		"ums-usbat",
++	.probe =	usbat_probe,
++	.disconnect =	usb_stor_disconnect,
++	.suspend =	usb_stor_suspend,
++	.resume =	usb_stor_resume,
++	.reset_resume =	usb_stor_reset_resume,
++	.pre_reset =	usb_stor_pre_reset,
++	.post_reset =	usb_stor_post_reset,
++	.id_table =	usbat_usb_ids,
++	.soft_unbind =	1,
++};
++
++static int __init usbat_init(void)
+ {
+-	struct usbat_info *info = (struct usbat_info*) (us->extra);
+-
+-	if (usbat_set_transport(us, info, 0))
+-		return USB_STOR_TRANSPORT_ERROR;
++	return usb_register(&usbat_driver);
++}
+ 
+-	return us->transport(srb, us);	
++static void __exit usbat_exit(void)
++{
++	usb_deregister(&usbat_driver);
+ }
++
++module_init(usbat_init);
++module_exit(usbat_exit);
+diff --git a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h
+deleted file mode 100644
+index d8bfc43e9044..000000000000
+--- a/drivers/usb/storage/shuttle_usbat.h
++++ /dev/null
+@@ -1,123 +0,0 @@
+-/* Driver for SCM Microsystems USB-ATAPI cable
+- * Header File
+- *
+- * Current development and maintenance by:
+- *   (c) 2000 Robert Baruch (autophile@dol.net)
+- *   (c) 2004, 2005 Daniel Drake 
+- *
+- * See shuttle_usbat.c for more explanation
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the
+- * Free Software Foundation; either version 2, or (at your option) any
+- * later version.
+- *
+- * This program is distributed in the hope that it will be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#ifndef _USB_SHUTTLE_USBAT_H
+-#define _USB_SHUTTLE_USBAT_H
+-
+-/* Supported device types */
+-#define USBAT_DEV_HP8200	0x01
+-#define USBAT_DEV_FLASH		0x02
+-
+-#define USBAT_EPP_PORT		0x10
+-#define USBAT_EPP_REGISTER	0x30
+-#define USBAT_ATA		0x40
+-#define USBAT_ISA		0x50
+-
+-/* Commands (need to be logically OR'd with an access type */
+-#define USBAT_CMD_READ_REG		0x00
+-#define USBAT_CMD_WRITE_REG		0x01
+-#define USBAT_CMD_READ_BLOCK	0x02
+-#define USBAT_CMD_WRITE_BLOCK	0x03
+-#define USBAT_CMD_COND_READ_BLOCK	0x04
+-#define USBAT_CMD_COND_WRITE_BLOCK	0x05
+-#define USBAT_CMD_WRITE_REGS	0x07
+-
+-/* Commands (these don't need an access type) */
+-#define USBAT_CMD_EXEC_CMD	0x80
+-#define USBAT_CMD_SET_FEAT	0x81
+-#define USBAT_CMD_UIO		0x82
+-
+-/* Methods of accessing UIO register */
+-#define USBAT_UIO_READ	1
+-#define USBAT_UIO_WRITE	0
+-
+-/* Qualifier bits */
+-#define USBAT_QUAL_FCQ	0x20	/* full compare */
+-#define USBAT_QUAL_ALQ	0x10	/* auto load subcount */
+-
+-/* USBAT Flash Media status types */
+-#define USBAT_FLASH_MEDIA_NONE	0
+-#define USBAT_FLASH_MEDIA_CF	1
+-
+-/* USBAT Flash Media change types */
+-#define USBAT_FLASH_MEDIA_SAME	0
+-#define USBAT_FLASH_MEDIA_CHANGED	1
+-
+-/* USBAT ATA registers */
+-#define USBAT_ATA_DATA      0x10  /* read/write data (R/W) */
+-#define USBAT_ATA_FEATURES  0x11  /* set features (W) */
+-#define USBAT_ATA_ERROR     0x11  /* error (R) */
+-#define USBAT_ATA_SECCNT    0x12  /* sector count (R/W) */
+-#define USBAT_ATA_SECNUM    0x13  /* sector number (R/W) */
+-#define USBAT_ATA_LBA_ME    0x14  /* cylinder low (R/W) */
+-#define USBAT_ATA_LBA_HI    0x15  /* cylinder high (R/W) */
+-#define USBAT_ATA_DEVICE    0x16  /* head/device selection (R/W) */
+-#define USBAT_ATA_STATUS    0x17  /* device status (R) */
+-#define USBAT_ATA_CMD       0x17  /* device command (W) */
+-#define USBAT_ATA_ALTSTATUS 0x0E  /* status (no clear IRQ) (R) */
+-
+-/* USBAT User I/O Data registers */
+-#define USBAT_UIO_EPAD		0x80 /* Enable Peripheral Control Signals */
+-#define USBAT_UIO_CDT		0x40 /* Card Detect (Read Only) */
+-				     /* CDT = ACKD & !UI1 & !UI0 */
+-#define USBAT_UIO_1		0x20 /* I/O 1 */
+-#define USBAT_UIO_0		0x10 /* I/O 0 */
+-#define USBAT_UIO_EPP_ATA	0x08 /* 1=EPP mode, 0=ATA mode */
+-#define USBAT_UIO_UI1		0x04 /* Input 1 */
+-#define USBAT_UIO_UI0		0x02 /* Input 0 */
+-#define USBAT_UIO_INTR_ACK	0x01 /* Interrupt (ATA/ISA)/Acknowledge (EPP) */
+-
+-/* USBAT User I/O Enable registers */
+-#define USBAT_UIO_DRVRST	0x80 /* Reset Peripheral */
+-#define USBAT_UIO_ACKD		0x40 /* Enable Card Detect */
+-#define USBAT_UIO_OE1		0x20 /* I/O 1 set=output/clr=input */
+-				     /* If ACKD=1, set OE1 to 1 also. */
+-#define USBAT_UIO_OE0		0x10 /* I/O 0 set=output/clr=input */
+-#define USBAT_UIO_ADPRST	0x01 /* Reset SCM chip */
+-
+-/* USBAT Features */
+-#define USBAT_FEAT_ETEN	0x80	/* External trigger enable */
+-#define USBAT_FEAT_U1	0x08
+-#define USBAT_FEAT_U0	0x04
+-#define USBAT_FEAT_ET1	0x02
+-#define USBAT_FEAT_ET2	0x01
+-
+-extern int usbat_transport(struct scsi_cmnd *srb, struct us_data *us);
+-extern int init_usbat_cd(struct us_data *us);
+-extern int init_usbat_flash(struct us_data *us);
+-extern int init_usbat_probe(struct us_data *us);
+-
+-struct usbat_info {
+-	int devicetype;
+-
+-	/* Used for Flash readers only */
+-	unsigned long sectors;     /* total sector count */
+-	unsigned long ssize;       /* sector size in bytes */
+-
+-	unsigned char sense_key;
+-	unsigned long sense_asc;   /* additional sense code */
+-	unsigned long sense_ascq;  /* additional sense code qualifier */
+-};
+-
+-#endif
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index eff97aed7bfe..6462c4c54dc0 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -85,18 +85,6 @@ UNUSUAL_DEV(  0x03f0, 0x0107, 0x0200, 0x0200,
+ 		"CD-Writer+",
+ 		US_SC_8070, US_PR_CB, NULL, 0),
+ 
+-#ifdef CONFIG_USB_STORAGE_USBAT
+-UNUSUAL_DEV(  0x03f0, 0x0207, 0x0001, 0x0001,
+-		"HP",
+-		"CD-Writer+ 8200e",
+-		US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
+-
+-UNUSUAL_DEV(  0x03f0, 0x0307, 0x0001, 0x0001,
+-		"HP",
+-		"CD-Writer+ CD-4e",
+-		US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
+-#endif
+-
+ /* Reported by Ben Efros  */
+ UNUSUAL_DEV(  0x03f0, 0x070c, 0x0000, 0x0000,
+ 		"HP",
+@@ -506,14 +494,6 @@ UNUSUAL_DEV(  0x04e6, 0x0101, 0x0200, 0x0200,
+ 		"CD-RW Device",
+ 		US_SC_8020, US_PR_CB, NULL, 0),
+ 
+-#ifdef CONFIG_USB_STORAGE_USBAT
+-UNUSUAL_DEV(  0x04e6, 0x1010, 0x0000, 0x9999,
+-		"Shuttle/SCM",
+-		"USBAT-02",
+-		US_SC_SCSI, US_PR_USBAT, init_usbat_flash,
+-		US_FL_SINGLE_LUN),
+-#endif
+-
+ /* Reported by Dmitry Khlystov  */
+ UNUSUAL_DEV(  0x04e8, 0x507c, 0x0220, 0x0220,
+ 		"Samsung",
+@@ -972,14 +952,6 @@ UNUSUAL_DEV(  0x0781, 0x0002, 0x0009, 0x0009,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_FIX_CAPACITY ),
+ 
+-#ifdef CONFIG_USB_STORAGE_USBAT
+-UNUSUAL_DEV(  0x0781, 0x0005, 0x0005, 0x0005,
+-		"Sandisk",
+-		"ImageMate SDDR-05b",
+-		US_SC_SCSI, US_PR_USBAT, init_usbat_flash,
+-		US_FL_SINGLE_LUN ),
+-#endif
+-
+ UNUSUAL_DEV(  0x0781, 0x0100, 0x0100, 0x0100,
+ 		"Sandisk",
+ 		"ImageMate SDDR-12",
+diff --git a/drivers/usb/storage/unusual_usbat.h b/drivers/usb/storage/unusual_usbat.h
+new file mode 100644
+index 000000000000..80e869f10180
+--- /dev/null
++++ b/drivers/usb/storage/unusual_usbat.h
+@@ -0,0 +1,43 @@
++/* Unusual Devices File for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2, or (at your option) any
++ * later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#if defined(CONFIG_USB_STORAGE_USBAT) || \
++		defined(CONFIG_USB_STORAGE_USBAT_MODULE)
++
++UNUSUAL_DEV(  0x03f0, 0x0207, 0x0001, 0x0001,
++		"HP",
++		"CD-Writer+ 8200e",
++		US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
++
++UNUSUAL_DEV(  0x03f0, 0x0307, 0x0001, 0x0001,
++		"HP",
++		"CD-Writer+ CD-4e",
++		US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
++
++UNUSUAL_DEV(  0x04e6, 0x1010, 0x0000, 0x9999,
++		"Shuttle/SCM",
++		"USBAT-02",
++		US_SC_SCSI, US_PR_USBAT, init_usbat_flash,
++		US_FL_SINGLE_LUN),
++
++UNUSUAL_DEV(  0x0781, 0x0005, 0x0005, 0x0005,
++		"Sandisk",
++		"ImageMate SDDR-05b",
++		US_SC_SCSI, US_PR_USBAT, init_usbat_flash,
++		US_FL_SINGLE_LUN),
++
++#endif /* defined(CONFIG_USB_STORAGE_USBAT) || ... */
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 241e1944cf10..3ad22a8142cc 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -66,9 +66,6 @@
+ #include "debug.h"
+ #include "initializers.h"
+ 
+-#ifdef CONFIG_USB_STORAGE_USBAT
+-#include "shuttle_usbat.h"
+-#endif
+ #ifdef CONFIG_USB_STORAGE_FREECOM
+ #include "freecom.h"
+ #endif
+@@ -610,15 +607,6 @@ static void get_transport(struct us_data *us)
+ 		us->transport_reset = usb_stor_Bulk_reset;
+ 		break;
+ 
+-#ifdef CONFIG_USB_STORAGE_USBAT
+-	case US_PR_USBAT:
+-		us->transport_name = "Shuttle USBAT";
+-		us->transport = usbat_transport;
+-		us->transport_reset = usb_stor_CB_reset;
+-		us->max_lun = 1;
+-		break;
+-#endif
+-
+ #ifdef CONFIG_USB_STORAGE_FREECOM
+ 	case US_PR_FREECOM:
+ 		us->transport_name = "Freecom";
+diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c
+index be461ee9f005..899a8c8da712 100644
+--- a/drivers/usb/storage/usual-tables.c
++++ b/drivers/usb/storage/usual-tables.c
+@@ -81,6 +81,7 @@ static struct ignore_entry ignore_ids[] = {
+ #	include "unusual_isd200.h"
+ #	include "unusual_sddr09.h"
+ #	include "unusual_sddr55.h"
++#	include "unusual_usbat.h"
+ 	{ }		/* Terminating entry */
+ };
+ 

commit fcdb51401f7f695b7fb782721b2e33372c5a06ce
+Author: Alan Stern 
+Date:   Thu Feb 12 14:48:04 2009 -0500
+
+    usb-storage: make cypress_atacb a separate module
+    
+    This patch (as1210) converts usb-storage's cypress_atacb subdriver
+    into a separate module.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
+index e6cc245257f8..2c73fa97d94d 100644
+--- a/drivers/usb/storage/Kconfig
++++ b/drivers/usb/storage/Kconfig
+@@ -146,7 +146,7 @@ config USB_STORAGE_KARMA
+ 	  operation.
+ 
+ config USB_STORAGE_CYPRESS_ATACB
+-	bool "SAT emulation on Cypress USB/ATA Bridge with ATACB"
++	tristate "SAT emulation on Cypress USB/ATA Bridge with ATACB"
+ 	depends on USB_STORAGE
+ 	---help---
+ 	  Say Y here if you want to use SAT (ata pass through) on devices based
+@@ -156,6 +156,8 @@ config USB_STORAGE_CYPRESS_ATACB
+ 	  If you say no here your device will still work with the standard usb
+ 	  mass storage class.
+ 
++	  If this driver is compiled as a module, it will be named ums-cypress.
++
+ config USB_LIBUSUAL
+ 	bool "The shared table of common (or usual) storage devices"
+ 	depends on USB
+diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
+index 5fb7847e41a4..0650f022e561 100644
+--- a/drivers/usb/storage/Makefile
++++ b/drivers/usb/storage/Makefile
+@@ -17,7 +17,6 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT)	+= jumpshot.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA)	+= alauda.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH)	+= onetouch.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA)	+= karma.o
+-usb-storage-obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += cypress_atacb.o
+ 
+ usb-storage-objs :=	scsiglue.o protocol.o transport.o usb.o \
+ 			initializers.o sierra_ms.o option_ms.o $(usb-storage-obj-y)
+@@ -28,10 +27,12 @@ else
+ 	obj-$(CONFIG_USB)	+= libusual.o usual-tables.o
+ endif
+ 
++obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o
+ obj-$(CONFIG_USB_STORAGE_ISD200)	+= ums-isd200.o
+ obj-$(CONFIG_USB_STORAGE_SDDR09)	+= ums-sddr09.o
+ obj-$(CONFIG_USB_STORAGE_SDDR55)	+= ums-sddr55.o
+ 
++ums-cypress-objs	:= cypress_atacb.o
+ ums-isd200-objs		:= isd200.o
+ ums-sddr09-objs		:= sddr09.o
+ ums-sddr55-objs		:= sddr55.o
+diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c
+index 9466a99baab6..19306f7b1dae 100644
+--- a/drivers/usb/storage/cypress_atacb.c
++++ b/drivers/usb/storage/cypress_atacb.c
+@@ -19,6 +19,7 @@
+  * 675 Mass Ave, Cambridge, MA 02139, USA.
+  */
+ 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -29,6 +30,46 @@
+ #include "scsiglue.h"
+ #include "debug.h"
+ 
++
++/*
++ * The table of devices
++ */
++#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
++		    vendorName, productName, useProtocol, useTransport, \
++		    initFunction, flags) \
++{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
++  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
++
++struct usb_device_id cypress_usb_ids[] = {
++#	include "unusual_cypress.h"
++	{ }		/* Terminating entry */
++};
++MODULE_DEVICE_TABLE(usb, cypress_usb_ids);
++
++#undef UNUSUAL_DEV
++
++/*
++ * The flags table
++ */
++#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
++		    vendor_name, product_name, use_protocol, use_transport, \
++		    init_function, Flags) \
++{ \
++	.vendorName = vendor_name,	\
++	.productName = product_name,	\
++	.useProtocol = use_protocol,	\
++	.useTransport = use_transport,	\
++	.initFunction = init_function,	\
++}
++
++static struct us_unusual_dev cypress_unusual_dev_list[] = {
++#	include "unusual_cypress.h"
++	{ }		/* Terminating entry */
++};
++
++#undef UNUSUAL_DEV
++
++
+ /*
+  * ATACB is a protocol used on cypress usb<->ata bridge to
+  * send raw ATA command over mass storage
+@@ -36,7 +77,7 @@
+  * More info that be found on cy7c68310_8.pdf and cy7c68300c_8.pdf
+  * datasheet from cypress.com.
+  */
+-void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us)
++static void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us)
+ {
+ 	unsigned char save_cmnd[MAX_COMMAND_SIZE];
+ 
+@@ -197,3 +238,48 @@ void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us)
+ 	if (srb->cmnd[0] == ATA_12)
+ 		srb->cmd_len = 12;
+ }
++
++
++static int cypress_probe(struct usb_interface *intf,
++			 const struct usb_device_id *id)
++{
++	struct us_data *us;
++	int result;
++
++	result = usb_stor_probe1(&us, intf, id,
++			(id - cypress_usb_ids) + cypress_unusual_dev_list);
++	if (result)
++		return result;
++
++	us->protocol_name = "Transparent SCSI with Cypress ATACB";
++	us->proto_handler = cypress_atacb_passthrough;
++
++	result = usb_stor_probe2(us);
++	return result;
++}
++
++static struct usb_driver cypress_driver = {
++	.name =		"ums-cypress",
++	.probe =	cypress_probe,
++	.disconnect =	usb_stor_disconnect,
++	.suspend =	usb_stor_suspend,
++	.resume =	usb_stor_resume,
++	.reset_resume =	usb_stor_reset_resume,
++	.pre_reset =	usb_stor_pre_reset,
++	.post_reset =	usb_stor_post_reset,
++	.id_table =	cypress_usb_ids,
++	.soft_unbind =	1,
++};
++
++static int __init cypress_init(void)
++{
++	return usb_register(&cypress_driver);
++}
++
++static void __exit cypress_exit(void)
++{
++	usb_deregister(&cypress_driver);
++}
++
++module_init(cypress_init);
++module_exit(cypress_exit);
+diff --git a/drivers/usb/storage/cypress_atacb.h b/drivers/usb/storage/unusual_cypress.h
+similarity index 54%
+rename from drivers/usb/storage/cypress_atacb.h
+rename to drivers/usb/storage/unusual_cypress.h
+index fbada898d56b..44be6d75dab6 100644
+--- a/drivers/usb/storage/cypress_atacb.h
++++ b/drivers/usb/storage/unusual_cypress.h
+@@ -1,8 +1,5 @@
+-/*
+- * Support for emulating SAT (ata pass through) on devices based
+- *       on the Cypress USB/ATA bridge supporting ATACB.
+- *
+- * Copyright (c) 2008 Matthieu Castet (castet.matthieu@free.fr)
++/* Unusual Devices File for devices based on the Cypress USB/ATA bridge
++ *	with support for ATACB
+  *
+  * This program is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License as published by the
+@@ -19,7 +16,19 @@
+  * 675 Mass Ave, Cambridge, MA 02139, USA.
+  */
+ 
+-#ifndef _CYPRESS_ATACB_H_
+-#define _CYPRESS_ATACB_H_
+-extern void cypress_atacb_passthrough(struct scsi_cmnd*, struct us_data*);
+-#endif
++#if defined(CONFIG_USB_STORAGE_CYPRESS_ATACB) || \
++		defined(CONFIG_USB_STORAGE_CYPRESS_ATACB_MODULE)
++
++/* CY7C68300 : support atacb */
++UNUSUAL_DEV(  0x04b4, 0x6830, 0x0000, 0x9999,
++		"Cypress",
++		"Cypress AT2LP",
++		US_SC_CYP_ATACB, US_PR_DEVICE, NULL, 0),
++
++/* CY7C68310 : support atacb and atacb2 */
++UNUSUAL_DEV(  0x04b4, 0x6831, 0x0000, 0x9999,
++		"Cypress",
++		"Cypress ISD-300LP",
++		US_SC_CYP_ATACB, US_PR_DEVICE, NULL, 0),
++
++#endif /* defined(CONFIG_USB_STORAGE_CYPRESS_ATACB) || ... */
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 50034e141f94..eff97aed7bfe 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -375,22 +375,6 @@ UNUSUAL_DEV(  0x04b3, 0x4001, 0x0110, 0x0110,
+ 		US_SC_DEVICE, US_PR_CB, NULL,
+ 		US_FL_MAX_SECTORS_MIN),
+ 
+-#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB
+-/* CY7C68300 : support atacb */
+-UNUSUAL_DEV(  0x04b4, 0x6830, 0x0000, 0x9999,
+-		"Cypress",
+-		"Cypress AT2LP",
+-		US_SC_CYP_ATACB, US_PR_DEVICE, NULL,
+-		0),
+-
+-/* CY7C68310 : support atacb and atacb2 */
+-UNUSUAL_DEV(  0x04b4, 0x6831, 0x0000, 0x9999,
+-		"Cypress",
+-		"Cypress ISD-300LP",
+-		US_SC_CYP_ATACB, US_PR_DEVICE, NULL,
+-		0),
+-#endif
+-
+ /* Reported by Simon Levitt 
+  * This entry needs Sub and Proto fields */
+ UNUSUAL_DEV(  0x04b8, 0x0601, 0x0100, 0x0100,
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 238f271d8171..241e1944cf10 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -87,9 +87,6 @@
+ #ifdef CONFIG_USB_STORAGE_KARMA
+ #include "karma.h"
+ #endif
+-#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB
+-#include "cypress_atacb.h"
+-#endif
+ #include "sierra_ms.h"
+ #include "option_ms.h"
+ 
+@@ -705,14 +702,6 @@ static void get_protocol(struct us_data *us)
+ 		us->protocol_name = "Uniform Floppy Interface (UFI)";
+ 		us->proto_handler = usb_stor_ufi_command;
+ 		break;
+-
+-#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB
+-	case US_SC_CYP_ATACB:
+-		us->protocol_name = "Transparent SCSI with Cypress ATACB";
+-		us->proto_handler = cypress_atacb_passthrough;
+-		break;
+-#endif
+-
+ 	}
+ }
+ 
+diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c
+index 5f2703fa48e6..be461ee9f005 100644
+--- a/drivers/usb/storage/usual-tables.c
++++ b/drivers/usb/storage/usual-tables.c
+@@ -77,6 +77,7 @@ struct ignore_entry {
+ }
+ 
+ static struct ignore_entry ignore_ids[] = {
++#	include "unusual_cypress.h"
+ #	include "unusual_isd200.h"
+ #	include "unusual_sddr09.h"
+ #	include "unusual_sddr55.h"

commit 70fcc0050733a7cd1b452cfa3de3a9b376412565
+Author: Alan Stern 
+Date:   Thu Feb 12 14:47:59 2009 -0500
+
+    usb-storage: make sddr55 a separate module
+    
+    This patch (as1209) converts usb-storage's sddr55 subdriver into a
+    separate module.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
+index fc356a770a76..e6cc245257f8 100644
+--- a/drivers/usb/storage/Kconfig
++++ b/drivers/usb/storage/Kconfig
+@@ -95,12 +95,14 @@ config USB_STORAGE_SDDR09
+ 	  If this driver is compiled as a module, it will be named ums-sddr09.
+ 
+ config USB_STORAGE_SDDR55
+-	bool "SanDisk SDDR-55 SmartMedia support"
++	tristate "SanDisk SDDR-55 SmartMedia support"
+ 	depends on USB_STORAGE
+ 	help
+ 	  Say Y here to include additional code to support the Sandisk SDDR-55
+ 	  SmartMedia reader in the USB Mass Storage driver.
+ 
++	  If this driver is compiled as a module, it will be named ums-sddr55.
++
+ config USB_STORAGE_JUMPSHOT
+ 	bool "Lexar Jumpshot Compact Flash Reader"
+ 	depends on USB_STORAGE
+diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
+index b47f94e59fdc..5fb7847e41a4 100644
+--- a/drivers/usb/storage/Makefile
++++ b/drivers/usb/storage/Makefile
+@@ -11,7 +11,6 @@ obj-$(CONFIG_USB_STORAGE)	+= usb-storage.o
+ 
+ usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG)	+= debug.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_USBAT)	+= shuttle_usbat.o
+-usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR55)	+= sddr55.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM)	+= freecom.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB)	+= datafab.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT)	+= jumpshot.o
+@@ -31,6 +30,8 @@ endif
+ 
+ obj-$(CONFIG_USB_STORAGE_ISD200)	+= ums-isd200.o
+ obj-$(CONFIG_USB_STORAGE_SDDR09)	+= ums-sddr09.o
++obj-$(CONFIG_USB_STORAGE_SDDR55)	+= ums-sddr55.o
+ 
+ ums-isd200-objs		:= isd200.o
+ ums-sddr09-objs		:= sddr09.o
++ums-sddr55-objs		:= sddr55.o
+diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c
+index 5a0106ba256c..e97716f8eb02 100644
+--- a/drivers/usb/storage/sddr55.c
++++ b/drivers/usb/storage/sddr55.c
+@@ -24,6 +24,7 @@
+ 
+ #include 
+ #include 
++#include 
+ #include 
+ 
+ #include 
+@@ -33,7 +34,45 @@
+ #include "transport.h"
+ #include "protocol.h"
+ #include "debug.h"
+-#include "sddr55.h"
++
++
++/*
++ * The table of devices
++ */
++#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
++		    vendorName, productName, useProtocol, useTransport, \
++		    initFunction, flags) \
++{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
++  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
++
++struct usb_device_id sddr55_usb_ids[] = {
++#	include "unusual_sddr55.h"
++	{ }		/* Terminating entry */
++};
++MODULE_DEVICE_TABLE(usb, sddr55_usb_ids);
++
++#undef UNUSUAL_DEV
++
++/*
++ * The flags table
++ */
++#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
++		    vendor_name, product_name, use_protocol, use_transport, \
++		    init_function, Flags) \
++{ \
++	.vendorName = vendor_name,	\
++	.productName = product_name,	\
++	.useProtocol = use_protocol,	\
++	.useTransport = use_transport,	\
++	.initFunction = init_function,	\
++}
++
++static struct us_unusual_dev sddr55_unusual_dev_list[] = {
++#	include "unusual_sddr55.h"
++	{ }		/* Terminating entry */
++};
++
++#undef UNUSUAL_DEV
+ 
+ 
+ #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) )
+@@ -513,7 +552,8 @@ static int sddr55_read_deviceID(struct us_data *us,
+ }
+ 
+ 
+-int sddr55_reset(struct us_data *us) {
++static int sddr55_reset(struct us_data *us)
++{
+ 	return 0;
+ }
+ 
+@@ -734,7 +774,7 @@ static void sddr55_card_info_destructor(void *extra) {
+ /*
+  * Transport for the Sandisk SDDR-55
+  */
+-int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)
++static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)
+ {
+ 	int result;
+ 	static unsigned char inquiry_response[8] = {
+@@ -931,3 +971,49 @@ int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 	return USB_STOR_TRANSPORT_FAILED; // FIXME: sense buffer?
+ }
+ 
++
++static int sddr55_probe(struct usb_interface *intf,
++			 const struct usb_device_id *id)
++{
++	struct us_data *us;
++	int result;
++
++	result = usb_stor_probe1(&us, intf, id,
++			(id - sddr55_usb_ids) + sddr55_unusual_dev_list);
++	if (result)
++		return result;
++
++	us->transport_name = "SDDR55";
++	us->transport = sddr55_transport;
++	us->transport_reset = sddr55_reset;
++	us->max_lun = 0;
++
++	result = usb_stor_probe2(us);
++	return result;
++}
++
++static struct usb_driver sddr55_driver = {
++	.name =		"ums-sddr55",
++	.probe =	sddr55_probe,
++	.disconnect =	usb_stor_disconnect,
++	.suspend =	usb_stor_suspend,
++	.resume =	usb_stor_resume,
++	.reset_resume =	usb_stor_reset_resume,
++	.pre_reset =	usb_stor_pre_reset,
++	.post_reset =	usb_stor_post_reset,
++	.id_table =	sddr55_usb_ids,
++	.soft_unbind =	1,
++};
++
++static int __init sddr55_init(void)
++{
++	return usb_register(&sddr55_driver);
++}
++
++static void __exit sddr55_exit(void)
++{
++	usb_deregister(&sddr55_driver);
++}
++
++module_init(sddr55_init);
++module_exit(sddr55_exit);
+diff --git a/drivers/usb/storage/sddr55.h b/drivers/usb/storage/sddr55.h
+deleted file mode 100644
+index a815a0470c84..000000000000
+--- a/drivers/usb/storage/sddr55.h
++++ /dev/null
+@@ -1,32 +0,0 @@
+-/* Driver for SanDisk SDDR-55 SmartMedia reader
+- * Header File
+- *
+- * Current development and maintenance by:
+- *   (c) 2002 Simon Munton
+- *
+- * See sddr55.c for more explanation
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the
+- * Free Software Foundation; either version 2, or (at your option) any
+- * later version.
+- *
+- * This program is distributed in the hope that it will be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#ifndef _USB_SHUTTLE_EUSB_SDDR55_H
+-#define _USB_SHUTTLE_EUSB_SDDR55_H
+-
+-/* Sandisk SDDR-55 stuff */
+-
+-extern int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us);
+-extern int sddr55_reset(struct us_data *us);
+-
+-#endif
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 83ce1d33554a..50034e141f94 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -1098,15 +1098,6 @@ UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xffff,
+ 		US_SC_SCSI, US_PR_DATAFAB, NULL,
+ 		0 ),
+ #endif
+-		
+-#ifdef CONFIG_USB_STORAGE_SDDR55
+-/* Contributed by Peter Waechtler */
+-UNUSUAL_DEV( 0x07c4, 0xa103, 0x0000, 0x9999,
+-		"Datafab",
+-		"MDSM-B reader",
+-		US_SC_SCSI, US_PR_SDDR55, NULL,
+-		US_FL_FIX_INQUIRY ),
+-#endif
+ 
+ #ifdef CONFIG_USB_STORAGE_DATAFAB
+ /* Submitted by Olaf Hering  */
+@@ -1116,14 +1107,6 @@ UNUSUAL_DEV(  0x07c4, 0xa109, 0x0000, 0xffff,
+ 		US_SC_SCSI, US_PR_DATAFAB, NULL,
+ 		0 ),
+ #endif
+-#ifdef CONFIG_USB_STORAGE_SDDR55
+-/* SM part - aeb  */
+-UNUSUAL_DEV(  0x07c4, 0xa109, 0x0000, 0xffff,
+-		"Datafab Systems, Inc.",
+-		"USB to CF + SM Combo (LC1)",
+-		US_SC_SCSI, US_PR_SDDR55, NULL,
+-		US_FL_SINGLE_LUN ),
+-#endif
+ 
+ #ifdef CONFIG_USB_STORAGE_DATAFAB
+ /* Reported by Felix Moeller 
+@@ -1348,13 +1331,6 @@ UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff,
+ 		US_SC_SCSI, US_PR_DATAFAB, NULL,
+ 		US_FL_SINGLE_LUN ),
+ #endif
+-#ifdef CONFIG_USB_STORAGE_SDDR55
+-UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff,
+-		"Acomdata",
+-		"SM",
+-		US_SC_SCSI, US_PR_SDDR55, NULL,
+-		US_FL_SINGLE_LUN ),
+-#endif
+ 
+ UNUSUAL_DEV(  0x0d49, 0x7310, 0x0000, 0x9999,
+ 		"Maxtor",
+@@ -2041,14 +2017,6 @@ UNUSUAL_DEV(  0x4146, 0xba01, 0x0100, 0x0100,
+ 		"Micro Mini 1GB",
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
+ 
+-#ifdef CONFIG_USB_STORAGE_SDDR55
+-UNUSUAL_DEV(  0x55aa, 0xa103, 0x0000, 0x9999, 
+-		"Sandisk",
+-		"ImageMate SDDR55",
+-		US_SC_SCSI, US_PR_SDDR55, NULL,
+-		US_FL_SINGLE_LUN),
+-#endif
+-
+ /* Reported by Andrew Simmons  */
+ UNUSUAL_DEV(  0xed06, 0x4500, 0x0001, 0x0001,
+ 		"DataStor",
+diff --git a/drivers/usb/storage/unusual_sddr55.h b/drivers/usb/storage/unusual_sddr55.h
+new file mode 100644
+index 000000000000..ae81ef7a1cfd
+--- /dev/null
++++ b/drivers/usb/storage/unusual_sddr55.h
+@@ -0,0 +1,44 @@
++/* Unusual Devices File for SanDisk SDDR-55 SmartMedia reader
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2, or (at your option) any
++ * later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#if defined(CONFIG_USB_STORAGE_SDDR55) || \
++		defined(CONFIG_USB_STORAGE_SDDR55_MODULE)
++
++/* Contributed by Peter Waechtler */
++UNUSUAL_DEV( 0x07c4, 0xa103, 0x0000, 0x9999,
++		"Datafab",
++		"MDSM-B reader",
++		US_SC_SCSI, US_PR_SDDR55, NULL,
++		US_FL_FIX_INQUIRY),
++
++/* SM part - aeb  */
++UNUSUAL_DEV(  0x07c4, 0xa109, 0x0000, 0xffff,
++		"Datafab Systems, Inc.",
++		"USB to CF + SM Combo (LC1)",
++		US_SC_SCSI, US_PR_SDDR55, NULL, 0),
++
++UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff,
++		"Acomdata",
++		"SM",
++		US_SC_SCSI, US_PR_SDDR55, NULL, 0),
++
++UNUSUAL_DEV(  0x55aa, 0xa103, 0x0000, 0x9999,
++		"Sandisk",
++		"ImageMate SDDR55",
++		US_SC_SCSI, US_PR_SDDR55, NULL, 0),
++
++#endif /* defined(CONFIG_USB_STORAGE_SDDR55) || ... */
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index e65cbba452b0..238f271d8171 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -69,9 +69,6 @@
+ #ifdef CONFIG_USB_STORAGE_USBAT
+ #include "shuttle_usbat.h"
+ #endif
+-#ifdef CONFIG_USB_STORAGE_SDDR55
+-#include "sddr55.h"
+-#endif
+ #ifdef CONFIG_USB_STORAGE_FREECOM
+ #include "freecom.h"
+ #endif
+@@ -625,15 +622,6 @@ static void get_transport(struct us_data *us)
+ 		break;
+ #endif
+ 
+-#ifdef CONFIG_USB_STORAGE_SDDR55
+-	case US_PR_SDDR55:
+-		us->transport_name = "SDDR55";
+-		us->transport = sddr55_transport;
+-		us->transport_reset = sddr55_reset;
+-		us->max_lun = 0;
+-		break;
+-#endif
+-
+ #ifdef CONFIG_USB_STORAGE_FREECOM
+ 	case US_PR_FREECOM:
+ 		us->transport_name = "Freecom";
+diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c
+index 61ebddcc9ae0..5f2703fa48e6 100644
+--- a/drivers/usb/storage/usual-tables.c
++++ b/drivers/usb/storage/usual-tables.c
+@@ -79,6 +79,7 @@ struct ignore_entry {
+ static struct ignore_entry ignore_ids[] = {
+ #	include "unusual_isd200.h"
+ #	include "unusual_sddr09.h"
++#	include "unusual_sddr55.h"
+ 	{ }		/* Terminating entry */
+ };
+ 

commit 32d5493eb83a217c3b1eba4b98cd6d19864f71a8
+Author: Alan Stern 
+Date:   Thu Feb 12 14:47:54 2009 -0500
+
+    usb-storage: make isd200 a separate module
+    
+    This patch (as1208) converts usb-storage's isd200 subdriver into a
+    separate module.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
+index 7be8899f2559..fc356a770a76 100644
+--- a/drivers/usb/storage/Kconfig
++++ b/drivers/usb/storage/Kconfig
+@@ -46,7 +46,7 @@ config USB_STORAGE_FREECOM
+ 	  Freecom has a web page at .
+ 
+ config USB_STORAGE_ISD200
+-	bool "ISD-200 USB/ATA Bridge support"
++	tristate "ISD-200 USB/ATA Bridge support"
+ 	depends on USB_STORAGE
+ 	---help---
+ 	  Say Y here if you want to use USB Mass Store devices based
+@@ -61,6 +61,8 @@ config USB_STORAGE_ISD200
+ 	  - CyQ've CQ8060A CDRW drive
+ 	  - Planex eXtreme Drive RX-25HU USB-IDE cable (not model RX-25U)
+ 
++	  If this driver is compiled as a module, it will be named ums-isd200.
++
+ config USB_STORAGE_USBAT
+ 	bool "USBAT/USBAT02-based storage support"
+ 	depends on USB_STORAGE
+diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
+index a52740a95602..b47f94e59fdc 100644
+--- a/drivers/usb/storage/Makefile
++++ b/drivers/usb/storage/Makefile
+@@ -13,7 +13,6 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG)	+= debug.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_USBAT)	+= shuttle_usbat.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR55)	+= sddr55.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM)	+= freecom.o
+-usb-storage-obj-$(CONFIG_USB_STORAGE_ISD200)	+= isd200.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB)	+= datafab.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT)	+= jumpshot.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA)	+= alauda.o
+@@ -30,6 +29,8 @@ else
+ 	obj-$(CONFIG_USB)	+= libusual.o usual-tables.o
+ endif
+ 
++obj-$(CONFIG_USB_STORAGE_ISD200)	+= ums-isd200.o
+ obj-$(CONFIG_USB_STORAGE_SDDR09)	+= ums-sddr09.o
+ 
++ums-isd200-objs		:= isd200.o
+ ums-sddr09-objs		:= sddr09.o
+diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
+index 383abf2516a5..df943008538c 100644
+--- a/drivers/usb/storage/isd200.c
++++ b/drivers/usb/storage/isd200.c
+@@ -44,6 +44,7 @@
+ 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -57,7 +58,50 @@
+ #include "protocol.h"
+ #include "debug.h"
+ #include "scsiglue.h"
+-#include "isd200.h"
++
++
++static int isd200_Initialization(struct us_data *us);
++
++
++/*
++ * The table of devices
++ */
++#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
++		    vendorName, productName, useProtocol, useTransport, \
++		    initFunction, flags) \
++{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
++  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
++
++struct usb_device_id isd200_usb_ids[] = {
++#	include "unusual_isd200.h"
++	{ }		/* Terminating entry */
++};
++MODULE_DEVICE_TABLE(usb, isd200_usb_ids);
++
++#undef UNUSUAL_DEV
++#undef USUAL_DEV
++
++/*
++ * The flags table
++ */
++#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
++		    vendor_name, product_name, use_protocol, use_transport, \
++		    init_function, Flags) \
++{ \
++	.vendorName = vendor_name,	\
++	.productName = product_name,	\
++	.useProtocol = use_protocol,	\
++	.useTransport = use_transport,	\
++	.initFunction = init_function,	\
++}
++
++static struct us_unusual_dev isd200_unusual_dev_list[] = {
++#	include "unusual_isd200.h"
++	{ }		/* Terminating entry */
++};
++
++#undef UNUSUAL_DEV
++#undef USUAL_DEV
+ 
+ 
+ /* Timeout defines (in Seconds) */
+@@ -1518,7 +1562,7 @@ static int isd200_init_info(struct us_data *us)
+  * Initialization for the ISD200 
+  */
+ 
+-int isd200_Initialization(struct us_data *us)
++static int isd200_Initialization(struct us_data *us)
+ {
+ 	US_DEBUGP("ISD200 Initialization...\n");
+ 
+@@ -1549,7 +1593,7 @@ int isd200_Initialization(struct us_data *us)
+  *
+  */
+ 
+-void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us)
++static void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us)
+ {
+ 	int sendToTransport = 1, orig_bufflen;
+ 	union ata_cdb ataCdb;
+@@ -1570,3 +1614,47 @@ void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us)
+ 
+ 	isd200_srb_set_bufflen(srb, orig_bufflen);
+ }
++
++static int isd200_probe(struct usb_interface *intf,
++			 const struct usb_device_id *id)
++{
++	struct us_data *us;
++	int result;
++
++	result = usb_stor_probe1(&us, intf, id,
++			(id - isd200_usb_ids) + isd200_unusual_dev_list);
++	if (result)
++		return result;
++
++	us->protocol_name = "ISD200 ATA/ATAPI";
++	us->proto_handler = isd200_ata_command;
++
++	result = usb_stor_probe2(us);
++	return result;
++}
++
++static struct usb_driver isd200_driver = {
++	.name =		"ums-isd200",
++	.probe =	isd200_probe,
++	.disconnect =	usb_stor_disconnect,
++	.suspend =	usb_stor_suspend,
++	.resume =	usb_stor_resume,
++	.reset_resume =	usb_stor_reset_resume,
++	.pre_reset =	usb_stor_pre_reset,
++	.post_reset =	usb_stor_post_reset,
++	.id_table =	isd200_usb_ids,
++	.soft_unbind =	1,
++};
++
++static int __init isd200_init(void)
++{
++	return usb_register(&isd200_driver);
++}
++
++static void __exit isd200_exit(void)
++{
++	usb_deregister(&isd200_driver);
++}
++
++module_init(isd200_init);
++module_exit(isd200_exit);
+diff --git a/drivers/usb/storage/isd200.h b/drivers/usb/storage/isd200.h
+deleted file mode 100644
+index 0a35f4fa78f8..000000000000
+--- a/drivers/usb/storage/isd200.h
++++ /dev/null
+@@ -1,31 +0,0 @@
+-/* Header File for In-System Design, Inc. ISD200 ASIC
+- *
+- * First release
+- *
+- * Current development and maintenance by:
+- *   (c) 2000 In-System Design, Inc. (support@in-system.com)
+- *
+- * See isd200.c for more information.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the
+- * Free Software Foundation; either version 2, or (at your option) any
+- * later version.
+- *
+- * This program is distributed in the hope that it will be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#ifndef _USB_ISD200_H
+-#define _USB_ISD200_H
+-
+-extern void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us);
+-extern int isd200_Initialization(struct us_data *us);
+-
+-#endif
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 1fe7062f1cda..83ce1d33554a 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -632,14 +632,6 @@ UNUSUAL_DEV(  0x054c, 0x0025, 0x0100, 0x0100,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_SINGLE_LUN ),
+ 
+-#ifdef CONFIG_USB_STORAGE_ISD200
+-UNUSUAL_DEV(  0x054c, 0x002b, 0x0100, 0x0110,
+-		"Sony",
+-		"Portable USB Harddrive V2",
+-		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
+-		0 ),
+-#endif
+-
+ /* Submitted by Olaf Hering,  SuSE Bugzilla #49049 */
+ UNUSUAL_DEV(  0x054c, 0x002c, 0x0501, 0x2000,
+ 		"Sony",
+@@ -785,32 +777,6 @@ UNUSUAL_DEV(  0x05ab, 0x0060, 0x1104, 0x1110,
+ 		US_SC_SCSI, US_PR_BULK, NULL,
+ 		US_FL_NEED_OVERRIDE ),
+ 
+-#ifdef CONFIG_USB_STORAGE_ISD200
+-UNUSUAL_DEV(  0x05ab, 0x0031, 0x0100, 0x0110,
+-		"In-System",
+-		"USB/IDE Bridge (ATA/ATAPI)",
+-		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
+-		0 ),
+-
+-UNUSUAL_DEV(  0x05ab, 0x0301, 0x0100, 0x0110,
+-		"In-System",
+-		"Portable USB Harddrive V2",
+-		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
+-		0 ),
+-
+-UNUSUAL_DEV(  0x05ab, 0x0351, 0x0100, 0x0110,
+-		"In-System",
+-		"Portable USB Harddrive V2",
+-		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
+-		0 ),
+-
+-UNUSUAL_DEV(  0x05ab, 0x5701, 0x0100, 0x0110,
+-		"In-System",
+-		"USB Storage Adapter V2",
+-		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
+-		0 ),
+-#endif
+-
+ /* Submitted by Sven Anderson 
+  * There are at least four ProductIDs used for iPods, so I added 0x1202 and
+  * 0x1204. They just need the US_FL_FIX_CAPACITY. As the bcdDevice appears
+@@ -1375,14 +1341,6 @@ UNUSUAL_DEV( 0x0bc2, 0x3010, 0x0000, 0x0000,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_SANE_SENSE ),
+ 
+-#ifdef CONFIG_USB_STORAGE_ISD200
+-UNUSUAL_DEV(  0x0bf6, 0xa001, 0x0100, 0x0110,
+-		"ATI",
+-		"USB Cable 205",
+-		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
+-		0 ),
+-#endif
+-
+ #ifdef CONFIG_USB_STORAGE_DATAFAB
+ UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff,
+ 		"Acomdata",
+diff --git a/drivers/usb/storage/unusual_isd200.h b/drivers/usb/storage/unusual_isd200.h
+new file mode 100644
+index 000000000000..0d99dde3382a
+--- /dev/null
++++ b/drivers/usb/storage/unusual_isd200.h
+@@ -0,0 +1,57 @@
++/* Unusual Devices File for In-System Design, Inc. ISD200 ASIC
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2, or (at your option) any
++ * later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#if defined(CONFIG_USB_STORAGE_ISD200) || \
++		defined(CONFIG_USB_STORAGE_ISD200_MODULE)
++
++UNUSUAL_DEV(  0x054c, 0x002b, 0x0100, 0x0110,
++		"Sony",
++		"Portable USB Harddrive V2",
++		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
++		0),
++
++UNUSUAL_DEV(  0x05ab, 0x0031, 0x0100, 0x0110,
++		"In-System",
++		"USB/IDE Bridge (ATA/ATAPI)",
++		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
++		0),
++
++UNUSUAL_DEV(  0x05ab, 0x0301, 0x0100, 0x0110,
++		"In-System",
++		"Portable USB Harddrive V2",
++		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
++		0),
++
++UNUSUAL_DEV(  0x05ab, 0x0351, 0x0100, 0x0110,
++		"In-System",
++		"Portable USB Harddrive V2",
++		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
++		0),
++
++UNUSUAL_DEV(  0x05ab, 0x5701, 0x0100, 0x0110,
++		"In-System",
++		"USB Storage Adapter V2",
++		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
++		0),
++
++UNUSUAL_DEV(  0x0bf6, 0xa001, 0x0100, 0x0110,
++		"ATI",
++		"USB Cable 205",
++		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
++		0),
++
++#endif /* defined(CONFIG_USB_STORAGE_ISD200) || ... */
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 33cce41a5e8a..e65cbba452b0 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -75,9 +75,6 @@
+ #ifdef CONFIG_USB_STORAGE_FREECOM
+ #include "freecom.h"
+ #endif
+-#ifdef CONFIG_USB_STORAGE_ISD200
+-#include "isd200.h"
+-#endif
+ #ifdef CONFIG_USB_STORAGE_DATAFAB
+ #include "datafab.h"
+ #endif
+@@ -721,13 +718,6 @@ static void get_protocol(struct us_data *us)
+ 		us->proto_handler = usb_stor_ufi_command;
+ 		break;
+ 
+-#ifdef CONFIG_USB_STORAGE_ISD200
+-	case US_SC_ISD200:
+-		us->protocol_name = "ISD200 ATA/ATAPI";
+-		us->proto_handler = isd200_ata_command;
+-		break;
+-#endif
+-
+ #ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB
+ 	case US_SC_CYP_ATACB:
+ 		us->protocol_name = "Transparent SCSI with Cypress ATACB";
+diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c
+index f808c5262d0c..61ebddcc9ae0 100644
+--- a/drivers/usb/storage/usual-tables.c
++++ b/drivers/usb/storage/usual-tables.c
+@@ -77,6 +77,7 @@ struct ignore_entry {
+ }
+ 
+ static struct ignore_entry ignore_ids[] = {
++#	include "unusual_isd200.h"
+ #	include "unusual_sddr09.h"
+ 	{ }		/* Terminating entry */
+ };

commit 0ff71883b2d60136430458413c135d545c69b0c4
+Author: Alan Stern 
+Date:   Thu Feb 12 14:47:49 2009 -0500
+
+    usb-storage: make sddr09 a separate module
+    
+    This patch (as1207) converts usb-storage's sddr09 subdriver into a
+    separate module.
+    
+    An unexpected complication arises because of DPCM devices, in which
+    one LUN uses the sddr09 transport and one uses the standard CB
+    transport.  Since these devices can be used even when
+    USB_STORAGE_SDDR09 isn't configured, their entries in unusual_devs.h
+    require special treatment.  If SDDR09 isn't configured then the
+    entries remain in unusual_devs.h; if it is then the entries are
+    present in unusual_sddr09.h instead.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
+index 5c367566be8d..7be8899f2559 100644
+--- a/drivers/usb/storage/Kconfig
++++ b/drivers/usb/storage/Kconfig
+@@ -83,13 +83,15 @@ config USB_STORAGE_USBAT
+ 	  - Sandisk ImageMate SDDR-05b
+ 
+ config USB_STORAGE_SDDR09
+-	bool "SanDisk SDDR-09 (and other SmartMedia, including DPCM) support"
++	tristate "SanDisk SDDR-09 (and other SmartMedia, including DPCM) support"
+ 	depends on USB_STORAGE
+ 	help
+ 	  Say Y here to include additional code to support the Sandisk SDDR-09
+ 	  SmartMedia reader in the USB Mass Storage driver.
+ 	  Also works for the Microtech Zio! CompactFlash/SmartMedia reader.
+ 
++	  If this driver is compiled as a module, it will be named ums-sddr09.
++
+ config USB_STORAGE_SDDR55
+ 	bool "SanDisk SDDR-55 SmartMedia support"
+ 	depends on USB_STORAGE
+diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
+index a9e475e127a5..a52740a95602 100644
+--- a/drivers/usb/storage/Makefile
++++ b/drivers/usb/storage/Makefile
+@@ -11,7 +11,6 @@ obj-$(CONFIG_USB_STORAGE)	+= usb-storage.o
+ 
+ usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG)	+= debug.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_USBAT)	+= shuttle_usbat.o
+-usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR09)	+= sddr09.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR55)	+= sddr55.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM)	+= freecom.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_ISD200)	+= isd200.o
+@@ -30,3 +29,7 @@ ifeq ($(CONFIG_USB_LIBUSUAL),)
+ else
+ 	obj-$(CONFIG_USB)	+= libusual.o usual-tables.o
+ endif
++
++obj-$(CONFIG_USB_STORAGE_SDDR09)	+= ums-sddr09.o
++
++ums-sddr09-objs		:= sddr09.o
+diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
+index b667c7d2b837..170ad86b2d3e 100644
+--- a/drivers/usb/storage/sddr09.c
++++ b/drivers/usb/storage/sddr09.c
+@@ -41,6 +41,7 @@
+  */
+ 
+ #include 
++#include 
+ #include 
+ 
+ #include 
+@@ -51,7 +52,50 @@
+ #include "transport.h"
+ #include "protocol.h"
+ #include "debug.h"
+-#include "sddr09.h"
++
++
++static int usb_stor_sddr09_dpcm_init(struct us_data *us);
++static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us);
++static int usb_stor_sddr09_init(struct us_data *us);
++
++
++/*
++ * The table of devices
++ */
++#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
++		    vendorName, productName, useProtocol, useTransport, \
++		    initFunction, flags) \
++{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
++  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
++
++struct usb_device_id sddr09_usb_ids[] = {
++#	include "unusual_sddr09.h"
++	{ }		/* Terminating entry */
++};
++MODULE_DEVICE_TABLE(usb, sddr09_usb_ids);
++
++#undef UNUSUAL_DEV
++
++/*
++ * The flags table
++ */
++#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
++		    vendor_name, product_name, use_protocol, use_transport, \
++		    init_function, Flags) \
++{ \
++	.vendorName = vendor_name,	\
++	.productName = product_name,	\
++	.useProtocol = use_protocol,	\
++	.useTransport = use_transport,	\
++	.initFunction = init_function,	\
++}
++
++static struct us_unusual_dev sddr09_unusual_dev_list[] = {
++#	include "unusual_sddr09.h"
++	{ }		/* Terminating entry */
++};
++
++#undef UNUSUAL_DEV
+ 
+ 
+ #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) )
+@@ -1406,7 +1450,7 @@ sddr09_common_init(struct us_data *us) {
+  * unusual devices list but called from here then LUN 0 of the combo reader
+  * is not recognized. But I do not know what precisely these calls do.
+  */
+-int
++static int
+ usb_stor_sddr09_dpcm_init(struct us_data *us) {
+ 	int result;
+ 	unsigned char *data = us->iobuf;
+@@ -1456,7 +1500,7 @@ usb_stor_sddr09_dpcm_init(struct us_data *us) {
+ /*
+  * Transport for the Microtech DPCM-USB
+  */
+-int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us)
++static int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us)
+ {
+ 	int ret;
+ 
+@@ -1498,7 +1542,7 @@ int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us)
+ /*
+  * Transport for the Sandisk SDDR-09
+  */
+-int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
++static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
+ {
+ 	static unsigned char sensekey = 0, sensecode = 0;
+ 	static unsigned char havefakesense = 0;
+@@ -1697,7 +1741,60 @@ int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
+ /*
+  * Initialization routine for the sddr09 subdriver
+  */
+-int
++static int
+ usb_stor_sddr09_init(struct us_data *us) {
+ 	return sddr09_common_init(us);
+ }
++
++static int sddr09_probe(struct usb_interface *intf,
++			 const struct usb_device_id *id)
++{
++	struct us_data *us;
++	int result;
++
++	result = usb_stor_probe1(&us, intf, id,
++			(id - sddr09_usb_ids) + sddr09_unusual_dev_list);
++	if (result)
++		return result;
++
++	if (us->protocol == US_PR_DPCM_USB) {
++		us->transport_name = "Control/Bulk-EUSB/SDDR09";
++		us->transport = dpcm_transport;
++		us->transport_reset = usb_stor_CB_reset;
++		us->max_lun = 1;
++	} else {
++		us->transport_name = "EUSB/SDDR09";
++		us->transport = sddr09_transport;
++		us->transport_reset = usb_stor_CB_reset;
++		us->max_lun = 0;
++	}
++
++	result = usb_stor_probe2(us);
++	return result;
++}
++
++static struct usb_driver sddr09_driver = {
++	.name =		"ums-sddr09",
++	.probe =	sddr09_probe,
++	.disconnect =	usb_stor_disconnect,
++	.suspend =	usb_stor_suspend,
++	.resume =	usb_stor_resume,
++	.reset_resume =	usb_stor_reset_resume,
++	.pre_reset =	usb_stor_pre_reset,
++	.post_reset =	usb_stor_post_reset,
++	.id_table =	sddr09_usb_ids,
++	.soft_unbind =	1,
++};
++
++static int __init sddr09_init(void)
++{
++	return usb_register(&sddr09_driver);
++}
++
++static void __exit sddr09_exit(void)
++{
++	usb_deregister(&sddr09_driver);
++}
++
++module_init(sddr09_init);
++module_exit(sddr09_exit);
+diff --git a/drivers/usb/storage/sddr09.h b/drivers/usb/storage/sddr09.h
+deleted file mode 100644
+index b701172e12e3..000000000000
+--- a/drivers/usb/storage/sddr09.h
++++ /dev/null
+@@ -1,38 +0,0 @@
+-/* Driver for SanDisk SDDR-09 SmartMedia reader
+- * Header File
+- *
+- * Current development and maintenance by:
+- *   (c) 2000 Robert Baruch (autophile@dol.net)
+- *   (c) 2002 Andries Brouwer (aeb@cwi.nl)
+- *
+- * See sddr09.c for more explanation
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the
+- * Free Software Foundation; either version 2, or (at your option) any
+- * later version.
+- *
+- * This program is distributed in the hope that it will be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#ifndef _USB_SHUTTLE_EUSB_SDDR09_H
+-#define _USB_SHUTTLE_EUSB_SDDR09_H
+-
+-/* Sandisk SDDR-09 stuff */
+-
+-extern int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us);
+-extern int usb_stor_sddr09_init(struct us_data *us);
+-
+-/* Microtech DPCM-USB stuff */
+-
+-extern int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us);
+-extern int usb_stor_sddr09_dpcm_init(struct us_data *us);
+-
+-#endif
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index cfde74a6faa3..1fe7062f1cda 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -53,6 +53,11 @@
+  * as opposed to devices that do something strangely or wrongly.
+  */
+ 
++#if !defined(CONFIG_USB_STORAGE_SDDR09) && \
++		!defined(CONFIG_USB_STORAGE_SDDR09_MODULE)
++#define NO_SDDR09
++#endif
++
+ /* patch submitted by Vivian Bregier 
+  */
+ UNUSUAL_DEV(  0x03eb, 0x2002, 0x0100, 0x0100,
+@@ -246,12 +251,7 @@ UNUSUAL_DEV(  0x0424, 0x0fdc, 0x0210, 0x0210,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_SINGLE_LUN ),
+ 
+-#ifdef CONFIG_USB_STORAGE_SDDR09
+-UNUSUAL_DEV(  0x0436, 0x0005, 0x0100, 0x0100,
+-		"Microtech",
+-		"CameraMate (DPCM_USB)",
+- 		US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ),
+-#else
++#ifdef NO_SDDR09
+ UNUSUAL_DEV(  0x0436, 0x0005, 0x0100, 0x0100,
+ 		"Microtech",
+ 		"CameraMate",
+@@ -467,20 +467,7 @@ UNUSUAL_DEV(  0x04e6, 0x0002, 0x0100, 0x0100,
+ 		US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init, 
+ 		US_FL_SCM_MULT_TARG ),
+ 
+-#ifdef CONFIG_USB_STORAGE_SDDR09
+-UNUSUAL_DEV(  0x04e6, 0x0003, 0x0000, 0x9999,
+-		"Sandisk",
+-		"ImageMate SDDR09",
+-		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
+-		0),
+-
+-/* This entry is from Andries.Brouwer@cwi.nl */
+-UNUSUAL_DEV(  0x04e6, 0x0005, 0x0100, 0x0208,
+-		"SCM Microsystems",
+-		"eUSB SmartMedia / CompactFlash Adapter",
+-		US_SC_SCSI, US_PR_DPCM_USB, usb_stor_sddr09_dpcm_init,
+-		0),
+-#else
++#ifdef NO_SDDR09
+ UNUSUAL_DEV(  0x04e6, 0x0005, 0x0100, 0x0208,
+ 		"SCM Microsystems",
+ 		"eUSB CompactFlash Adapter",
+@@ -935,14 +922,6 @@ UNUSUAL_DEV(  0x0644, 0x0000, 0x0100, 0x0100,
+ 		"Floppy Drive",
+ 		US_SC_UFI, US_PR_CB, NULL, 0 ),
+ 
+-#ifdef CONFIG_USB_STORAGE_SDDR09
+-UNUSUAL_DEV(  0x066b, 0x0105, 0x0100, 0x0100,
+-		"Olympus",
+-		"Camedia MAUSB-2",
+-		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
+-		0),
+-#endif
+-
+ /* Reported by Darsen Lu  */
+ UNUSUAL_DEV( 0x066f, 0x8000, 0x0001, 0x0001,
+ 		"SigmaTel",
+@@ -1057,14 +1036,6 @@ UNUSUAL_DEV(  0x0781, 0x0100, 0x0100, 0x0100,
+ 		US_SC_SCSI, US_PR_CB, NULL,
+ 		US_FL_SINGLE_LUN ),
+ 
+-#ifdef CONFIG_USB_STORAGE_SDDR09
+-UNUSUAL_DEV(  0x0781, 0x0200, 0x0000, 0x9999,
+-		"Sandisk",
+-		"ImageMate SDDR-09",
+-		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
+-		0),
+-#endif
+-
+ #ifdef CONFIG_USB_STORAGE_FREECOM
+ UNUSUAL_DEV(  0x07ab, 0xfc01, 0x0000, 0x9999,
+ 		"Freecom",
+@@ -1091,12 +1062,7 @@ UNUSUAL_DEV(  0x07af, 0x0005, 0x0100, 0x0100,
+ 		US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init,
+ 		US_FL_SCM_MULT_TARG ),
+ 
+-#ifdef CONFIG_USB_STORAGE_SDDR09
+-UNUSUAL_DEV(  0x07af, 0x0006, 0x0100, 0x0100,
+-		"Microtech",
+-		"CameraMate (DPCM_USB)",
+- 		US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ),
+-#else
++#ifdef NO_SDDR09
+ UNUSUAL_DEV(  0x07af, 0x0006, 0x0100, 0x0100,
+ 		"Microtech",
+ 		"CameraMate",
+diff --git a/drivers/usb/storage/unusual_sddr09.h b/drivers/usb/storage/unusual_sddr09.h
+new file mode 100644
+index 000000000000..50cab511a4d7
+--- /dev/null
++++ b/drivers/usb/storage/unusual_sddr09.h
+@@ -0,0 +1,56 @@
++/* Unusual Devices File for SanDisk SDDR-09 SmartMedia reader
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2, or (at your option) any
++ * later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#if defined(CONFIG_USB_STORAGE_SDDR09) || \
++		defined(CONFIG_USB_STORAGE_SDDR09_MODULE)
++
++UNUSUAL_DEV(  0x0436, 0x0005, 0x0100, 0x0100,
++		"Microtech",
++		"CameraMate (DPCM_USB)",
++		US_SC_SCSI, US_PR_DPCM_USB, NULL, 0),
++
++UNUSUAL_DEV(  0x04e6, 0x0003, 0x0000, 0x9999,
++		"Sandisk",
++		"ImageMate SDDR09",
++		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
++		0),
++
++/* This entry is from Andries.Brouwer@cwi.nl */
++UNUSUAL_DEV(  0x04e6, 0x0005, 0x0100, 0x0208,
++		"SCM Microsystems",
++		"eUSB SmartMedia / CompactFlash Adapter",
++		US_SC_SCSI, US_PR_DPCM_USB, usb_stor_sddr09_dpcm_init,
++		0),
++
++UNUSUAL_DEV(  0x066b, 0x0105, 0x0100, 0x0100,
++		"Olympus",
++		"Camedia MAUSB-2",
++		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
++		0),
++
++UNUSUAL_DEV(  0x0781, 0x0200, 0x0000, 0x9999,
++		"Sandisk",
++		"ImageMate SDDR-09",
++		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
++		0),
++
++UNUSUAL_DEV(  0x07af, 0x0006, 0x0100, 0x0100,
++		"Microtech",
++		"CameraMate (DPCM_USB)",
++		US_SC_SCSI, US_PR_DPCM_USB, NULL, 0),
++
++#endif /* defined(CONFIG_USB_STORAGE_SDDR09) || ... */
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 490ea761398c..33cce41a5e8a 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -69,9 +69,6 @@
+ #ifdef CONFIG_USB_STORAGE_USBAT
+ #include "shuttle_usbat.h"
+ #endif
+-#ifdef CONFIG_USB_STORAGE_SDDR09
+-#include "sddr09.h"
+-#endif
+ #ifdef CONFIG_USB_STORAGE_SDDR55
+ #include "sddr55.h"
+ #endif
+@@ -631,15 +628,6 @@ static void get_transport(struct us_data *us)
+ 		break;
+ #endif
+ 
+-#ifdef CONFIG_USB_STORAGE_SDDR09
+-	case US_PR_EUSB_SDDR09:
+-		us->transport_name = "EUSB/SDDR09";
+-		us->transport = sddr09_transport;
+-		us->transport_reset = usb_stor_CB_reset;
+-		us->max_lun = 0;
+-		break;
+-#endif
+-
+ #ifdef CONFIG_USB_STORAGE_SDDR55
+ 	case US_PR_SDDR55:
+ 		us->transport_name = "SDDR55";
+@@ -649,15 +637,6 @@ static void get_transport(struct us_data *us)
+ 		break;
+ #endif
+ 
+-#ifdef CONFIG_USB_STORAGE_DPCM
+-	case US_PR_DPCM_USB:
+-		us->transport_name = "Control/Bulk-EUSB/SDDR09";
+-		us->transport = dpcm_transport;
+-		us->transport_reset = usb_stor_CB_reset;
+-		us->max_lun = 1;
+-		break;
+-#endif
+-
+ #ifdef CONFIG_USB_STORAGE_FREECOM
+ 	case US_PR_FREECOM:
+ 		us->transport_name = "Freecom";
+diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c
+index 1924e3229409..f808c5262d0c 100644
+--- a/drivers/usb/storage/usual-tables.c
++++ b/drivers/usb/storage/usual-tables.c
+@@ -77,6 +77,7 @@ struct ignore_entry {
+ }
+ 
+ static struct ignore_entry ignore_ids[] = {
++#	include "unusual_sddr09.h"
+ 	{ }		/* Terminating entry */
+ };
+ 

commit e6e244b6cb1f70e7109381626293cd40a8334ed3
+Author: Alan Stern 
+Date:   Thu Feb 12 14:47:44 2009 -0500
+
+    usb-storage: prepare for subdriver separation
+    
+    This patch (as1206) is the first step in converting usb-storage's
+    subdrivers into separate modules.  It makes the following large-scale
+    changes:
+    
+            Remove a bunch of unnecessary #ifdef's from usb_usual.h.
+            Not truly necessary, but it does clean things up.
+    
+            Move the USB device-ID table (which is duplicated between
+            libusual and usb-storage) into its own source file,
+            usual-tables.c, and arrange for this to be linked with
+            either libusual or usb-storage according to whether
+            USB_LIBUSUAL is configured.
+    
+            Add to usual-tables.c a new usb_usual_ignore_device()
+            function to detect whether a particular device needs to be
+            managed by a subdriver and not by the standard handlers
+            in usb-storage.
+    
+            Export a whole bunch of functions in usb-storage, renaming
+            some of them because their names don't already begin with
+            "usb_stor_".  These functions will be needed by the new
+            subdriver modules.
+    
+            Split usb-storage's probe routine into two functions.
+            The subdrivers will call the probe1 routine, then fill in
+            their transport and protocol settings, and then call the
+            probe2 routine.
+    
+            Take the default cases and error checking out of
+            get_transport() and get_protocol(), which run during
+            probe1, and instead put a check for invalid transport
+            or protocol values into the probe2 function.
+    
+            Add a new probe routine to be used for standard devices,
+            i.e., those that don't need a subdriver.  This new routine
+            checks whether the device should be ignored (because it
+            should be handled by ub or by a subdriver), and if not,
+            calls the probe1 and probe2 functions.
+    
+    Signed-off-by: Alan Stern 
+    CC: Matthew Dharm 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/block/ub.c b/drivers/block/ub.c
+index b36b84fbe390..69b7f8e77596 100644
+--- a/drivers/block/ub.c
++++ b/drivers/block/ub.c
+@@ -391,7 +391,7 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum);
+  */
+ #ifdef CONFIG_USB_LIBUSUAL
+ 
+-#define ub_usb_ids  storage_usb_ids
++#define ub_usb_ids  usb_storage_usb_ids
+ #else
+ 
+ static struct usb_device_id ub_usb_ids[] = {
+diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
+index b32069313390..a9e475e127a5 100644
+--- a/drivers/usb/storage/Makefile
++++ b/drivers/usb/storage/Makefile
+@@ -25,6 +25,8 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += cypress_atacb.o
+ usb-storage-objs :=	scsiglue.o protocol.o transport.o usb.o \
+ 			initializers.o sierra_ms.o option_ms.o $(usb-storage-obj-y)
+ 
+-ifneq ($(CONFIG_USB_LIBUSUAL),)
+-	obj-$(CONFIG_USB)	+= libusual.o
++ifeq ($(CONFIG_USB_LIBUSUAL),)
++	usb-storage-objs	+= usual-tables.o
++else
++	obj-$(CONFIG_USB)	+= libusual.o usual-tables.o
+ endif
+diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c
+index f970b27ba308..fe3ffe1459b2 100644
+--- a/drivers/usb/storage/libusual.c
++++ b/drivers/usb/storage/libusual.c
+@@ -37,37 +37,6 @@ static atomic_t total_threads = ATOMIC_INIT(0);
+ 
+ static int usu_probe_thread(void *arg);
+ 
+-/*
+- * The table.
+- */
+-#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+-		    vendorName, productName,useProtocol, useTransport, \
+-		    initFunction, flags) \
+-{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \
+-  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+-
+-#define COMPLIANT_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+-		    vendorName, productName, useProtocol, useTransport, \
+-		    initFunction, flags) \
+-{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
+-  .driver_info = (flags) }
+-
+-#define USUAL_DEV(useProto, useTrans, useType) \
+-{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
+-  .driver_info = ((useType)<<24) }
+-
+-struct usb_device_id storage_usb_ids [] = {
+-#	include "unusual_devs.h"
+-	{ } /* Terminating entry */
+-};
+-
+-#undef USUAL_DEV
+-#undef UNUSUAL_DEV
+-#undef COMPLIANT_DEV
+-
+-MODULE_DEVICE_TABLE(usb, storage_usb_ids);
+-EXPORT_SYMBOL_GPL(storage_usb_ids);
+-
+ /*
+  * @type: the module type as an integer
+  */
+@@ -167,7 +136,7 @@ static struct usb_driver usu_driver = {
+ 	.name =		"libusual",
+ 	.probe =	usu_probe,
+ 	.disconnect =	usu_disconnect,
+-	.id_table =	storage_usb_ids,
++	.id_table =	usb_storage_usb_ids,
+ };
+ 
+ /*
+diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
+index be441d84bc64..fc310f75eada 100644
+--- a/drivers/usb/storage/protocol.c
++++ b/drivers/usb/storage/protocol.c
+@@ -121,6 +121,7 @@ void usb_stor_transparent_scsi_command(struct scsi_cmnd *srb,
+ 	/* send the command to the transport layer */
+ 	usb_stor_invoke_transport(srb, us);
+ }
++EXPORT_SYMBOL_GPL(usb_stor_transparent_scsi_command);
+ 
+ /***********************************************************************
+  * Scatter-gather transfer buffer access routines
+@@ -199,6 +200,7 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
+ 	/* Return the amount actually transferred */
+ 	return cnt;
+ }
++EXPORT_SYMBOL_GPL(usb_stor_access_xfer_buf);
+ 
+ /* Store the contents of buffer into srb's transfer buffer and set the
+  * SCSI residue.
+@@ -215,3 +217,4 @@ void usb_stor_set_xfer_buf(unsigned char *buffer,
+ 	if (buflen < scsi_bufflen(srb))
+ 		scsi_set_resid(srb, scsi_bufflen(srb) - buflen);
+ }
++EXPORT_SYMBOL_GPL(usb_stor_set_xfer_buf);
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index ed710bcdaab2..4ca3b5860643 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -569,4 +569,4 @@ unsigned char usb_stor_sense_invalidCDB[18] = {
+ 	[7]	= 0x0a,			    /* additional length */
+ 	[12]	= 0x24			    /* Invalid Field in CDB */
+ };
+-
++EXPORT_SYMBOL_GPL(usb_stor_sense_invalidCDB);
+diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+index fb65d221cedf..d48c8553539d 100644
+--- a/drivers/usb/storage/transport.c
++++ b/drivers/usb/storage/transport.c
+@@ -220,6 +220,7 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
+ 		status = us->current_urb->actual_length;
+ 	return status;
+ }
++EXPORT_SYMBOL_GPL(usb_stor_control_msg);
+ 
+ /* This is a version of usb_clear_halt() that allows early termination and
+  * doesn't read the status from the device -- this is because some devices
+@@ -254,6 +255,7 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe)
+ 	US_DEBUGP("%s: result = %d\n", __func__, result);
+ 	return result;
+ }
++EXPORT_SYMBOL_GPL(usb_stor_clear_halt);
+ 
+ 
+ /*
+@@ -352,6 +354,7 @@ int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
+ 	return interpret_urb_result(us, pipe, size, result,
+ 			us->current_urb->actual_length);
+ }
++EXPORT_SYMBOL_GPL(usb_stor_ctrl_transfer);
+ 
+ /*
+  * Receive one interrupt buffer, without timeouts, but allowing early
+@@ -407,6 +410,7 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
+ 	return interpret_urb_result(us, pipe, length, result, 
+ 			us->current_urb->actual_length);
+ }
++EXPORT_SYMBOL_GPL(usb_stor_bulk_transfer_buf);
+ 
+ /*
+  * Transfer a scatter-gather list via bulk transfer
+@@ -474,6 +478,7 @@ int usb_stor_bulk_srb(struct us_data* us, unsigned int pipe,
+ 	scsi_set_resid(srb, scsi_bufflen(srb) - partial);
+ 	return result;
+ }
++EXPORT_SYMBOL_GPL(usb_stor_bulk_srb);
+ 
+ /*
+  * Transfer an entire SCSI command's worth of data payload over the bulk
+@@ -509,6 +514,7 @@ int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe,
+ 		*residual = length_left;
+ 	return result;
+ }
++EXPORT_SYMBOL_GPL(usb_stor_bulk_transfer_sg);
+ 
+ /***********************************************************************
+  * Transport routines
+@@ -940,6 +946,7 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 		usb_stor_clear_halt(us, pipe);
+ 	return USB_STOR_TRANSPORT_FAILED;
+ }
++EXPORT_SYMBOL_GPL(usb_stor_CB_transport);
+ 
+ /*
+  * Bulk only transport
+@@ -1156,6 +1163,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 	/* we should never get here, but if we do, we're in trouble */
+ 	return USB_STOR_TRANSPORT_ERROR;
+ }
++EXPORT_SYMBOL_GPL(usb_stor_Bulk_transport);
+ 
+ /***********************************************************************
+  * Reset routines
+@@ -1230,6 +1238,7 @@ int usb_stor_CB_reset(struct us_data *us)
+ 				 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ 				 0, us->ifnum, us->iobuf, CB_RESET_CMD_SIZE);
+ }
++EXPORT_SYMBOL_GPL(usb_stor_CB_reset);
+ 
+ /* This issues a Bulk-only Reset to the device in question, including
+  * clearing the subsequent endpoint halts that may occur.
+@@ -1242,6 +1251,7 @@ int usb_stor_Bulk_reset(struct us_data *us)
+ 				 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ 				 0, us->ifnum, NULL, 0);
+ }
++EXPORT_SYMBOL_GPL(usb_stor_Bulk_reset);
+ 
+ /* Issue a USB port reset to the device.  The caller must not hold
+  * us->dev_mutex.
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index b01dade63cb3..490ea761398c 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -5,7 +5,7 @@
+  *
+  * Developed with the assistance of:
+  *   (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
+- *   (c) 2003 Alan Stern (stern@rowland.harvard.edu)
++ *   (c) 2003-2009 Alan Stern (stern@rowland.harvard.edu)
+  *
+  * Initial work by:
+  *   (c) 1999 Michael Gee (michael@linuxspecific.com)
+@@ -118,36 +118,8 @@ MODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks");
+ 
+ /*
+  * The entries in this table correspond, line for line,
+- * with the entries of us_unusual_dev_list[].
++ * with the entries in usb_storage_usb_ids[], defined in usual-tables.c.
+  */
+-#ifndef CONFIG_USB_LIBUSUAL
+-
+-#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+-		    vendorName, productName,useProtocol, useTransport, \
+-		    initFunction, flags) \
+-{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \
+-  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+-
+-#define COMPLIANT_DEV	UNUSUAL_DEV
+-
+-#define USUAL_DEV(useProto, useTrans, useType) \
+-{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
+-  .driver_info = (USB_US_TYPE_STOR<<24) }
+-
+-static struct usb_device_id storage_usb_ids [] = {
+-
+-#	include "unusual_devs.h"
+-#undef UNUSUAL_DEV
+-#undef COMPLIANT_DEV
+-#undef USUAL_DEV
+-	/* Terminating entry */
+-	{ }
+-};
+-
+-MODULE_DEVICE_TABLE (usb, storage_usb_ids);
+-#endif /* CONFIG_USB_LIBUSUAL */
+-
+-/* This is the list of devices we recognize, along with their flag data */
+ 
+ /* The vendor name should be kept at eight characters or less, and
+  * the product name should be kept at 16 characters or less. If a device
+@@ -179,18 +151,17 @@ MODULE_DEVICE_TABLE (usb, storage_usb_ids);
+ 
+ static struct us_unusual_dev us_unusual_dev_list[] = {
+ #	include "unusual_devs.h" 
+-#	undef UNUSUAL_DEV
+-#	undef COMPLIANT_DEV
+-#	undef USUAL_DEV
+-
+-	/* Terminating entry */
+-	{ NULL }
++	{ }		/* Terminating entry */
+ };
+ 
++#undef UNUSUAL_DEV
++#undef COMPLIANT_DEV
++#undef USUAL_DEV
++
+ 
+ #ifdef CONFIG_PM	/* Minimal support for suspend and resume */
+ 
+-static int storage_suspend(struct usb_interface *iface, pm_message_t message)
++int usb_stor_suspend(struct usb_interface *iface, pm_message_t message)
+ {
+ 	struct us_data *us = usb_get_intfdata(iface);
+ 
+@@ -207,8 +178,9 @@ static int storage_suspend(struct usb_interface *iface, pm_message_t message)
+ 	mutex_unlock(&us->dev_mutex);
+ 	return 0;
+ }
++EXPORT_SYMBOL_GPL(usb_stor_suspend);
+ 
+-static int storage_resume(struct usb_interface *iface)
++int usb_stor_resume(struct usb_interface *iface)
+ {
+ 	struct us_data *us = usb_get_intfdata(iface);
+ 
+@@ -221,8 +193,9 @@ static int storage_resume(struct usb_interface *iface)
+ 	mutex_unlock(&us->dev_mutex);
+ 	return 0;
+ }
++EXPORT_SYMBOL_GPL(usb_stor_resume);
+ 
+-static int storage_reset_resume(struct usb_interface *iface)
++int usb_stor_reset_resume(struct usb_interface *iface)
+ {
+ 	struct us_data *us = usb_get_intfdata(iface);
+ 
+@@ -235,6 +208,7 @@ static int storage_reset_resume(struct usb_interface *iface)
+ 	 * the device */
+ 	return 0;
+ }
++EXPORT_SYMBOL_GPL(usb_stor_reset_resume);
+ 
+ #endif /* CONFIG_PM */
+ 
+@@ -243,7 +217,7 @@ static int storage_reset_resume(struct usb_interface *iface)
+  * a USB port reset, whether from this driver or a different one.
+  */
+ 
+-static int storage_pre_reset(struct usb_interface *iface)
++int usb_stor_pre_reset(struct usb_interface *iface)
+ {
+ 	struct us_data *us = usb_get_intfdata(iface);
+ 
+@@ -253,8 +227,9 @@ static int storage_pre_reset(struct usb_interface *iface)
+ 	mutex_lock(&us->dev_mutex);
+ 	return 0;
+ }
++EXPORT_SYMBOL_GPL(usb_stor_pre_reset);
+ 
+-static int storage_post_reset(struct usb_interface *iface)
++int usb_stor_post_reset(struct usb_interface *iface)
+ {
+ 	struct us_data *us = usb_get_intfdata(iface);
+ 
+@@ -269,6 +244,7 @@ static int storage_post_reset(struct usb_interface *iface)
+ 	mutex_unlock(&us->dev_mutex);
+ 	return 0;
+ }
++EXPORT_SYMBOL_GPL(usb_stor_post_reset);
+ 
+ /*
+  * fill_inquiry_response takes an unsigned char array (which must
+@@ -311,6 +287,7 @@ void fill_inquiry_response(struct us_data *us, unsigned char *data,
+ 
+ 	usb_stor_set_xfer_buf(data, data_len, us->srb);
+ }
++EXPORT_SYMBOL_GPL(fill_inquiry_response);
+ 
+ static int usb_stor_control_thread(void * __us)
+ {
+@@ -551,20 +528,13 @@ static void adjust_quirks(struct us_data *us)
+ 			vid, pid, f);
+ }
+ 
+-/* Find an unusual_dev descriptor (always succeeds in the current code) */
+-static struct us_unusual_dev *find_unusual(const struct usb_device_id *id)
+-{
+-	const int id_index = id - storage_usb_ids;
+-	return &us_unusual_dev_list[id_index];
+-}
+-
+ /* Get the unusual_devs entries and the string descriptors */
+-static int get_device_info(struct us_data *us, const struct usb_device_id *id)
++static int get_device_info(struct us_data *us, const struct usb_device_id *id,
++		struct us_unusual_dev *unusual_dev)
+ {
+ 	struct usb_device *dev = us->pusb_dev;
+ 	struct usb_interface_descriptor *idesc =
+ 		&us->pusb_intf->cur_altsetting->desc;
+-	struct us_unusual_dev *unusual_dev = find_unusual(id);
+ 
+ 	/* Store the entries */
+ 	us->unusual_dev = unusual_dev;
+@@ -629,7 +599,7 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id)
+ }
+ 
+ /* Get the transport settings */
+-static int get_transport(struct us_data *us)
++static void get_transport(struct us_data *us)
+ {
+ 	switch (us->protocol) {
+ 	case US_PR_CB:
+@@ -732,19 +702,11 @@ static int get_transport(struct us_data *us)
+ 		break;
+ #endif
+ 
+-	default:
+-		return -EIO;
+ 	}
+-	US_DEBUGP("Transport: %s\n", us->transport_name);
+-
+-	/* fix for single-lun devices */
+-	if (us->fflags & US_FL_SINGLE_LUN)
+-		us->max_lun = 0;
+-	return 0;
+ }
+ 
+ /* Get the protocol settings */
+-static int get_protocol(struct us_data *us)
++static void get_protocol(struct us_data *us)
+ {
+ 	switch (us->subclass) {
+ 	case US_SC_RBC:
+@@ -794,11 +756,7 @@ static int get_protocol(struct us_data *us)
+ 		break;
+ #endif
+ 
+-	default:
+-		return -EIO;
+ 	}
+-	US_DEBUGP("Protocol: %s\n", us->protocol_name);
+-	return 0;
+ }
+ 
+ /* Get the pipe settings */
+@@ -1012,17 +970,15 @@ static int usb_stor_scan_thread(void * __us)
+ }
+ 
+ 
+-/* Probe to see if we can drive a newly-connected USB device */
+-static int storage_probe(struct usb_interface *intf,
+-			 const struct usb_device_id *id)
++/* First part of general USB mass-storage probing */
++int usb_stor_probe1(struct us_data **pus,
++		struct usb_interface *intf,
++		const struct usb_device_id *id,
++		struct us_unusual_dev *unusual_dev)
+ {
+ 	struct Scsi_Host *host;
+ 	struct us_data *us;
+ 	int result;
+-	struct task_struct *th;
+-
+-	if (usb_usual_check_type(id, USB_US_TYPE_STOR))
+-		return -ENXIO;
+ 
+ 	US_DEBUGP("USB Mass Storage device detected\n");
+ 
+@@ -1041,7 +997,7 @@ static int storage_probe(struct usb_interface *intf,
+ 	 * Allow 16-byte CDBs and thus > 2TB
+ 	 */
+ 	host->max_cmd_len = 16;
+-	us = host_to_us(host);
++	*pus = us = host_to_us(host);
+ 	memset(us, 0, sizeof(struct us_data));
+ 	mutex_init(&(us->dev_mutex));
+ 	init_completion(&us->cmnd_ready);
+@@ -1054,24 +1010,46 @@ static int storage_probe(struct usb_interface *intf,
+ 	if (result)
+ 		goto BadDevice;
+ 
+-	/*
+-	 * Get the unusual_devs entries and the descriptors
+-	 *
+-	 * id_index is calculated in the declaration to be the index number
+-	 * of the match from the usb_device_id table, so we can find the
+-	 * corresponding entry in the private table.
+-	 */
+-	result = get_device_info(us, id);
++	/* Get the unusual_devs entries and the descriptors */
++	result = get_device_info(us, id, unusual_dev);
+ 	if (result)
+ 		goto BadDevice;
+ 
+-	/* Get the transport, protocol, and pipe settings */
+-	result = get_transport(us);
+-	if (result)
+-		goto BadDevice;
+-	result = get_protocol(us);
+-	if (result)
++	/* Get standard transport and protocol settings */
++	get_transport(us);
++	get_protocol(us);
++
++	/* Give the caller a chance to fill in specialized transport
++	 * or protocol settings.
++	 */
++	return 0;
++
++BadDevice:
++	US_DEBUGP("storage_probe() failed\n");
++	release_everything(us);
++	return result;
++}
++EXPORT_SYMBOL_GPL(usb_stor_probe1);
++
++/* Second part of general USB mass-storage probing */
++int usb_stor_probe2(struct us_data *us)
++{
++	struct task_struct *th;
++	int result;
++
++	/* Make sure the transport and protocol have both been set */
++	if (!us->transport || !us->proto_handler) {
++		result = -ENXIO;
+ 		goto BadDevice;
++	}
++	US_DEBUGP("Transport: %s\n", us->transport_name);
++	US_DEBUGP("Protocol: %s\n", us->protocol_name);
++
++	/* fix for single-lun devices */
++	if (us->fflags & US_FL_SINGLE_LUN)
++		us->max_lun = 0;
++
++	/* Find the endpoints and calculate pipe values */
+ 	result = get_pipes(us);
+ 	if (result)
+ 		goto BadDevice;
+@@ -1080,7 +1058,7 @@ static int storage_probe(struct usb_interface *intf,
+ 	result = usb_stor_acquire_resources(us);
+ 	if (result)
+ 		goto BadDevice;
+-	result = scsi_add_host(host, &intf->dev);
++	result = scsi_add_host(us_to_host(us), &us->pusb_intf->dev);
+ 	if (result) {
+ 		printk(KERN_WARNING USB_STORAGE
+ 			"Unable to add the scsi host\n");
+@@ -1108,9 +1086,10 @@ static int storage_probe(struct usb_interface *intf,
+ 	release_everything(us);
+ 	return result;
+ }
++EXPORT_SYMBOL_GPL(usb_stor_probe2);
+ 
+-/* Handle a disconnect event from the USB core */
+-static void storage_disconnect(struct usb_interface *intf)
++/* Handle a USB mass-storage disconnect */
++void usb_stor_disconnect(struct usb_interface *intf)
+ {
+ 	struct us_data *us = usb_get_intfdata(intf);
+ 
+@@ -1118,6 +1097,42 @@ static void storage_disconnect(struct usb_interface *intf)
+ 	quiesce_and_remove_host(us);
+ 	release_everything(us);
+ }
++EXPORT_SYMBOL_GPL(usb_stor_disconnect);
++
++/* The main probe routine for standard devices */
++static int storage_probe(struct usb_interface *intf,
++			 const struct usb_device_id *id)
++{
++	struct us_data *us;
++	int result;
++
++	/*
++	 * If libusual is configured, let it decide whether a standard
++	 * device should be handled by usb-storage or by ub.
++	 * If the device isn't standard (is handled by a subdriver
++	 * module) then don't accept it.
++	 */
++	if (usb_usual_check_type(id, USB_US_TYPE_STOR) ||
++			usb_usual_ignore_device(intf))
++		return -ENXIO;
++
++	/*
++	 * Call the general probe procedures.
++	 *
++	 * The unusual_dev_list array is parallel to the usb_storage_usb_ids
++	 * table, so we use the index of the id entry to find the
++	 * corresponding unusual_devs entry.
++	 */
++	result = usb_stor_probe1(&us, intf, id,
++			(id - usb_storage_usb_ids) + us_unusual_dev_list);
++	if (result)
++		return result;
++
++	/* No special transport or protocol settings in the main module */
++
++	result = usb_stor_probe2(us);
++	return result;
++}
+ 
+ /***********************************************************************
+  * Initialization and registration
+@@ -1126,15 +1141,13 @@ static void storage_disconnect(struct usb_interface *intf)
+ static struct usb_driver usb_storage_driver = {
+ 	.name =		"usb-storage",
+ 	.probe =	storage_probe,
+-	.disconnect =	storage_disconnect,
+-#ifdef CONFIG_PM
+-	.suspend =	storage_suspend,
+-	.resume =	storage_resume,
+-	.reset_resume =	storage_reset_resume,
+-#endif
+-	.pre_reset =	storage_pre_reset,
+-	.post_reset =	storage_post_reset,
+-	.id_table =	storage_usb_ids,
++	.disconnect =	usb_stor_disconnect,
++	.suspend =	usb_stor_suspend,
++	.resume =	usb_stor_resume,
++	.reset_resume =	usb_stor_reset_resume,
++	.pre_reset =	usb_stor_pre_reset,
++	.post_reset =	usb_stor_post_reset,
++	.id_table =	usb_storage_usb_ids,
+ 	.soft_unbind =	1,
+ };
+ 
+diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
+index 65e674e4be99..2609efb2bd7e 100644
+--- a/drivers/usb/storage/usb.h
++++ b/drivers/usb/storage/usb.h
+@@ -177,4 +177,25 @@ extern void fill_inquiry_response(struct us_data *us,
+ #define scsi_unlock(host)	spin_unlock_irq(host->host_lock)
+ #define scsi_lock(host)		spin_lock_irq(host->host_lock)
+ 
++/* General routines provided by the usb-storage standard core */
++#ifdef CONFIG_PM
++extern int usb_stor_suspend(struct usb_interface *iface, pm_message_t message);
++extern int usb_stor_resume(struct usb_interface *iface);
++extern int usb_stor_reset_resume(struct usb_interface *iface);
++#else
++#define usb_stor_suspend	NULL
++#define usb_stor_resume		NULL
++#define usb_stor_reset_resume	NULL
++#endif
++
++extern int usb_stor_pre_reset(struct usb_interface *iface);
++extern int usb_stor_post_reset(struct usb_interface *iface);
++
++extern int usb_stor_probe1(struct us_data **pus,
++		struct usb_interface *intf,
++		const struct usb_device_id *id,
++		struct us_unusual_dev *unusual_dev);
++extern int usb_stor_probe2(struct us_data *us);
++extern void usb_stor_disconnect(struct usb_interface *intf);
++
+ #endif
+diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c
+new file mode 100644
+index 000000000000..1924e3229409
+--- /dev/null
++++ b/drivers/usb/storage/usual-tables.c
+@@ -0,0 +1,105 @@
++/* Driver for USB Mass Storage devices
++ * Usual Tables File for usb-storage and libusual
++ *
++ * Copyright (C) 2009 Alan Stern (stern@rowland.harvard.edu)
++ *
++ * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more
++ * information about this driver.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2, or (at your option) any
++ * later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include 
++#include 
++#include 
++#include 
++
++
++/*
++ * The table of devices
++ */
++#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
++		    vendorName, productName, useProtocol, useTransport, \
++		    initFunction, flags) \
++{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
++  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
++
++#define COMPLIANT_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
++		    vendorName, productName, useProtocol, useTransport, \
++		    initFunction, flags) \
++{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
++  .driver_info = (flags) }
++
++#define USUAL_DEV(useProto, useTrans, useType) \
++{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
++  .driver_info = ((useType)<<24) }
++
++struct usb_device_id usb_storage_usb_ids[] = {
++#	include "unusual_devs.h"
++	{ }		/* Terminating entry */
++};
++EXPORT_SYMBOL_GPL(usb_storage_usb_ids);
++
++MODULE_DEVICE_TABLE(usb, usb_storage_usb_ids);
++
++#undef UNUSUAL_DEV
++#undef COMPLIANT_DEV
++#undef USUAL_DEV
++
++
++/*
++ * The table of devices to ignore
++ */
++struct ignore_entry {
++	u16	vid, pid, bcdmin, bcdmax;
++};
++
++#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
++		    vendorName, productName, useProtocol, useTransport, \
++		    initFunction, flags) \
++{					\
++	.vid	= id_vendor,		\
++	.pid 	= id_product,		\
++	.bcdmin	= bcdDeviceMin,		\
++	.bcdmax = bcdDeviceMax,		\
++}
++
++static struct ignore_entry ignore_ids[] = {
++	{ }		/* Terminating entry */
++};
++
++#undef UNUSUAL_DEV
++
++
++/* Return an error if a device is in the ignore_ids list */
++int usb_usual_ignore_device(struct usb_interface *intf)
++{
++	struct usb_device *udev;
++	unsigned vid, pid, bcd;
++	struct ignore_entry *p;
++
++	udev = interface_to_usbdev(intf);
++	vid = le16_to_cpu(udev->descriptor.idVendor);
++	pid = le16_to_cpu(udev->descriptor.idProduct);
++	bcd = le16_to_cpu(udev->descriptor.bcdDevice);
++
++	for (p = ignore_ids; p->vid; ++p) {
++		if (p->vid == vid && p->pid == pid &&
++				p->bcdmin <= bcd && p->bcdmax >= bcd)
++			return -ENXIO;
++	}
++	return 0;
++}
++EXPORT_SYMBOL_GPL(usb_usual_ignore_device);
+diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
+index 1eea1ab68dc4..3d15fb9bc116 100644
+--- a/include/linux/usb_usual.h
++++ b/include/linux/usb_usual.h
+@@ -96,39 +96,26 @@ enum { US_DO_ALL_FLAGS };
+ #define US_PR_CBI	0x00		/* Control/Bulk/Interrupt */
+ #define US_PR_CB	0x01		/* Control/Bulk w/o interrupt */
+ #define US_PR_BULK	0x50		/* bulk only */
+-#ifdef CONFIG_USB_STORAGE_USBAT
++
+ #define US_PR_USBAT	0x80		/* SCM-ATAPI bridge */
+-#endif
+-#ifdef CONFIG_USB_STORAGE_SDDR09
+ #define US_PR_EUSB_SDDR09	0x81	/* SCM-SCSI bridge for SDDR-09 */
+-#endif
+-#ifdef CONFIG_USB_STORAGE_SDDR55
+ #define US_PR_SDDR55	0x82		/* SDDR-55 (made up) */
+-#endif
+ #define US_PR_DPCM_USB  0xf0		/* Combination CB/SDDR09 */
+-#ifdef CONFIG_USB_STORAGE_FREECOM
+ #define US_PR_FREECOM   0xf1		/* Freecom */
+-#endif
+-#ifdef CONFIG_USB_STORAGE_DATAFAB
+ #define US_PR_DATAFAB   0xf2		/* Datafab chipsets */
+-#endif
+-#ifdef CONFIG_USB_STORAGE_JUMPSHOT
+ #define US_PR_JUMPSHOT  0xf3		/* Lexar Jumpshot */
+-#endif
+-#ifdef CONFIG_USB_STORAGE_ALAUDA
+ #define US_PR_ALAUDA    0xf4		/* Alauda chipsets */
+-#endif
+-#ifdef CONFIG_USB_STORAGE_KARMA
+ #define US_PR_KARMA     0xf5		/* Rio Karma */
+-#endif
+ 
+ #define US_PR_DEVICE	0xff		/* Use device's value */
+ 
+ /*
+  */
++extern int usb_usual_ignore_device(struct usb_interface *intf);
++extern struct usb_device_id usb_storage_usb_ids[];
++
+ #ifdef CONFIG_USB_LIBUSUAL
+ 
+-extern struct usb_device_id storage_usb_ids[];
+ extern void usb_usual_set_present(int type);
+ extern void usb_usual_clear_present(int type);
+ extern int usb_usual_check_type(const struct usb_device_id *, int type);

commit a2c2706e1043c17139c2dafd171c4a5cf008ef7e
+Author: Alan Stern 
+Date:   Tue Feb 10 10:16:58 2009 -0500
+
+    USB: EHCI: add software retry for transaction errors
+    
+    This patch (as1204) adds a software retry mechanism to ehci-hcd.  It
+    gets invoked when the driver encounters transaction errors on an
+    asynchronous endpoint.  On many systems, hardware deficiencies cause
+    such errors to occur if one device is unplugged while the host is
+    communicating with another device.  With the patch, the failed
+    transactions are retried and generally succeed the second or third
+    time through.
+    
+    This is based on code originally written by Koichiro Saito.
+    
+    Signed-off-by: Alan Stern 
+    Tested by: Koichiro Saito 
+    CC: David Brownell 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index ecc9b66c03cd..01132ac74eb8 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -333,12 +333,40 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		token = hc32_to_cpu(ehci, qtd->hw_token);
+ 
+ 		/* always clean up qtds the hc de-activated */
++ retry_xacterr:
+ 		if ((token & QTD_STS_ACTIVE) == 0) {
+ 
+ 			/* on STALL, error, and short reads this urb must
+ 			 * complete and all its qtds must be recycled.
+ 			 */
+ 			if ((token & QTD_STS_HALT) != 0) {
++
++				/* retry transaction errors until we
++				 * reach the software xacterr limit
++				 */
++				if ((token & QTD_STS_XACT) &&
++						QTD_CERR(token) == 0 &&
++						--qh->xacterrs > 0 &&
++						!urb->unlinked) {
++					ehci_dbg(ehci,
++	"detected XactErr len %d/%d retry %d\n",
++	qtd->length - QTD_LENGTH(token), qtd->length,
++	QH_XACTERR_MAX - qh->xacterrs);
++
++					/* reset the token in the qtd and the
++					 * qh overlay (which still contains
++					 * the qtd) so that we pick up from
++					 * where we left off
++					 */
++					token &= ~QTD_STS_HALT;
++					token |= QTD_STS_ACTIVE |
++							(EHCI_TUNE_CERR << 10);
++					qtd->hw_token = cpu_to_hc32(ehci,
++							token);
++					wmb();
++					qh->hw_token = cpu_to_hc32(ehci, token);
++					goto retry_xacterr;
++				}
+ 				stopped = 1;
+ 
+ 			/* magic dummy for some short reads; qh won't advance.
+@@ -421,6 +449,9 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		/* remove qtd; it's recycled after possible urb completion */
+ 		list_del (&qtd->qtd_list);
+ 		last = qtd;
++
++		/* reinit the xacterr counter for the next qtd */
++		qh->xacterrs = QH_XACTERR_MAX;
+ 	}
+ 
+ 	/* last urb's completion might still need calling */
+@@ -862,6 +893,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	head->qh_next.qh = qh;
+ 	head->hw_next = dma;
+ 
++	qh->xacterrs = QH_XACTERR_MAX;
+ 	qh->qh_state = QH_STATE_LINKED;
+ 	/* qtd completions reported later by interrupt */
+ }
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 0042deb671dd..9aba560fd569 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -342,6 +342,9 @@ struct ehci_qh {
+ #define	QH_STATE_UNLINK_WAIT	4		/* LINKED and on reclaim q */
+ #define	QH_STATE_COMPLETING	5		/* don't touch token.HALT */
+ 
++	u8			xacterrs;	/* XactErr retry counter */
++#define	QH_XACTERR_MAX		32		/* XactErr retry limit */
++
+ 	/* periodic schedule info */
+ 	u8			usecs;		/* intr bandwidth */
+ 	u8			gap_uf;		/* uframes split/csplit gap */

commit bc29847e16cb6b571157220ec9b20a7d86e58046
+Author: Alan Stern 
+Date:   Wed Feb 11 14:26:38 2009 -0500
+
+    USB: EHCI: Make timer_action out-of-line
+    
+    This patch (as1205) moves timer_action() from ehci.h to ehci-hcd.c and
+    makes it out-of-line.  Over the years it has grown too big to be inline
+    any more.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index e551bb38852b..f2618d17710d 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -110,6 +110,42 @@ MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications");
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++static void
++timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action)
++{
++	/* Don't override timeouts which shrink or (later) disable
++	 * the async ring; just the I/O watchdog.  Note that if a
++	 * SHRINK were pending, OFF would never be requested.
++	 */
++	if (timer_pending(&ehci->watchdog)
++			&& ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF))
++				& ehci->actions))
++		return;
++
++	if (!test_and_set_bit(action, &ehci->actions)) {
++		unsigned long t;
++
++		switch (action) {
++		case TIMER_IO_WATCHDOG:
++			t = EHCI_IO_JIFFIES;
++			break;
++		case TIMER_ASYNC_OFF:
++			t = EHCI_ASYNC_JIFFIES;
++			break;
++		/* case TIMER_ASYNC_SHRINK: */
++		default:
++			/* add a jiffie since we synch against the
++			 * 8 KHz uframe counter.
++			 */
++			t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1;
++			break;
++		}
++		mod_timer(&ehci->watchdog, t + jiffies);
++	}
++}
++
++/*-------------------------------------------------------------------------*/
++
+ /*
+  * handshake - spin reading hc until handshake completes or fails
+  * @ptr: address of hc register to be read
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 262b00c9b334..0042deb671dd 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -190,40 +190,6 @@ timer_action_done (struct ehci_hcd *ehci, enum ehci_timer_action action)
+ 	clear_bit (action, &ehci->actions);
+ }
+ 
+-static inline void
+-timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
+-{
+-	/* Don't override timeouts which shrink or (later) disable
+-	 * the async ring; just the I/O watchdog.  Note that if a
+-	 * SHRINK were pending, OFF would never be requested.
+-	 */
+-	if (timer_pending(&ehci->watchdog)
+-			&& ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF))
+-				& ehci->actions))
+-		return;
+-
+-	if (!test_and_set_bit (action, &ehci->actions)) {
+-		unsigned long t;
+-
+-		switch (action) {
+-		case TIMER_IO_WATCHDOG:
+-			t = EHCI_IO_JIFFIES;
+-			break;
+-		case TIMER_ASYNC_OFF:
+-			t = EHCI_ASYNC_JIFFIES;
+-			break;
+-		// case TIMER_ASYNC_SHRINK:
+-		default:
+-			/* add a jiffie since we synch against the
+-			 * 8 KHz uframe counter.
+-			 */
+-			t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1;
+-			break;
+-		}
+-		mod_timer(&ehci->watchdog, t + jiffies);
+-	}
+-}
+-
+ static void free_cached_itd_list(struct ehci_hcd *ehci);
+ 
+ /*-------------------------------------------------------------------------*/

commit 5c16034d73da2c1b663aa25dedadbc533b3d811c
+Author: Alan Stern 
+Date:   Mon Mar 23 09:51:02 2009 -0400
+
+    USB: usb-storage: increase max_sectors for tape drives
+    
+    This patch (as1203) increases the max_sector limit for USB tape
+    drives.  By default usb-storage sets max_sectors to 240 (i.e., 120 KB)
+    for all devices.  But tape drives need a higher limit, since tapes can
+    and do have very large block sizes.  Without the ability to transfer
+    an entire large block in a single command, such tapes can't be used.
+    
+    This fixes Bugzilla #12207.
+    
+    Signed-off-by: Alan Stern 
+    Reported-and-tested-by: Phil Mitchell 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index 727c506417cc..ed710bcdaab2 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -135,6 +135,12 @@ static int slave_configure(struct scsi_device *sdev)
+ 		if (sdev->request_queue->max_sectors > max_sectors)
+ 			blk_queue_max_sectors(sdev->request_queue,
+ 					      max_sectors);
++	} else if (sdev->type == TYPE_TAPE) {
++		/* Tapes need much higher max_sector limits, so just
++		 * raise it to the maximum possible (4 GB / 512) and
++		 * let the queue segment size sort out the real limit.
++		 */
++		blk_queue_max_sectors(sdev->request_queue, 0x7FFFFF);
+ 	}
+ 
+ 	/* Some USB host controllers can't do DMA; they have to use PIO.

commit 1662e3a7f076e51e3073faf9ce77157b529c475b
+Author: Alan Stern 
+Date:   Wed Mar 18 14:28:53 2009 -0400
+
+    USB: add quirk to avoid config and interface strings
+    
+    Apparently the Configuration and Interface strings aren't used as
+    often as the Vendor, Product, and Serial strings.  In at least one
+    device (a Saitek Cyborg Gold 3D joystick), attempts to read the
+    Configuration string cause the device to stop responding to Control
+    requests.
+    
+    This patch (as1226) adds a quirks flag, telling the kernel not to
+    read a device's Configuration or Interface strings, together with a
+    new quirk for the offending joystick.
+    
+    Reported-by: Melchior FRANZ 
+    Tested-by: Melchior FRANZ 
+    Signed-off-by: Alan Stern 
+    Cc: stable   [2.6.28 and 2.6.29, nothing earlier]
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 49e7f56e0d7f..3922fa915ed2 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1719,7 +1719,8 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 	}
+ 	kfree(new_interfaces);
+ 
+-	if (cp->string == NULL)
++	if (cp->string == NULL &&
++			!(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
+ 		cp->string = usb_cache_string(dev, cp->desc.iConfiguration);
+ 
+ 	/* Now that all the interfaces are set up, register them
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index c070b34b669d..ab93918d9207 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -54,6 +54,10 @@ static const struct usb_device_id usb_quirk_list[] = {
+ 	{ USB_DEVICE(0x0638, 0x0a13), .driver_info =
+ 	  USB_QUIRK_STRING_FETCH_255 },
+ 
++	/* Saitek Cyborg Gold Joystick */
++	{ USB_DEVICE(0x06a3, 0x0006), .driver_info =
++			USB_QUIRK_CONFIG_INTF_STRINGS },
++
+ 	/* M-Systems Flash Disk Pioneers */
+ 	{ USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
+ 
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 4cc2456ef3be..c66789197927 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -13,6 +13,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include "usb.h"
+ 
+ /* Active configuration fields */
+@@ -813,7 +814,8 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf)
+ 	if (intf->sysfs_files_created || intf->unregistering)
+ 		return 0;
+ 
+-	if (alt->string == NULL)
++	if (alt->string == NULL &&
++			!(udev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
+ 		alt->string = usb_cache_string(udev, alt->desc.iInterface);
+ 	if (alt->string)
+ 		retval = device_create_file(&intf->dev, &dev_attr_interface);
+diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h
+index 7f6c603db654..2526f3bbd273 100644
+--- a/include/linux/usb/quirks.h
++++ b/include/linux/usb/quirks.h
+@@ -16,4 +16,7 @@
+ /* device can't handle Set-Interface requests */
+ #define USB_QUIRK_NO_SET_INTF		0x00000004
+ 
++/* device can't handle its Configuration or Interface strings */
++#define USB_QUIRK_CONFIG_INTF_STRINGS	0x00000008
++
+ #endif /* __LINUX_USB_QUIRKS_H */

commit 391016f6e2fe3b9979b4c6880a76e5e434d6947c
+Author: Alan Stern 
+Date:   Mon Mar 16 14:21:56 2009 -0400
+
+    USB: EHCI: expedite unlinks when the root hub is suspended
+    
+    This patch (as1225) fixes a bug in ehci-hcd.  The condition for
+    whether unlinked QHs can become IDLE should not be that the controller
+    is halted, but rather that the controller isn't running.  In other
+    words when the root hub is suspended, the hardware doesn't own any
+    QHs.
+    
+    This fixes a problem that can show up during hibernation: If a QH is
+    only partially unlinked when the root hub is frozen, then when the
+    root hub is thawed the QH won't be in the IDLE state.  As a result it
+    can't be used properly for new URB submissions.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Brandon Philips 
+    Tested-by: Brandon Philips 
+    Acked-by: David Brownell 
+    Cc: Stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 3712b925b315..ecc9b66c03cd 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -1095,7 +1095,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	prev->qh_next = qh->qh_next;
+ 	wmb ();
+ 
+-	if (unlikely (ehci_to_hcd(ehci)->state == HC_STATE_HALT)) {
++	/* If the controller isn't running, we don't have to wait for it */
++	if (unlikely(!HC_IS_RUNNING(ehci_to_hcd(ehci)->state))) {
+ 		/* if (unlikely (qh->reclaim != 0))
+ 		 *	this will recurse, probably not much
+ 		 */

commit 6ff10464096540e14d7575a72c50d0316d003714
+Author: Alan Stern 
+Date:   Mon Mar 9 13:44:02 2009 -0400
+
+    USB: usbfs: keep async URBs until the device file is closed
+    
+    The usbfs driver manages a list of completed asynchronous URBs.  But
+    it is too eager to free the entries on this list: destroy_async() gets
+    called whenever an interface is unbound or a device is removed, and it
+    deallocates the outstanding struct async entries for all URBs on that
+    interface or device.  This is wrong; the user program should be able
+    to reap an URB any time after it has completed, regardless of whether
+    or not the interface is still bound or the device is still present.
+    
+    This patch (as1222) moves the code for deallocating the completed list
+    entries from destroy_async() to usbdev_release().  The outstanding
+    entries won't be freed until the user program has closed the device
+    file, thereby eliminating any possibility that the remaining URBs
+    might still be reaped.
+    
+    This fixes a bug in which a program can hang in the USBDEVFS_REAPURB
+    ioctl when the device is unplugged.
+    
+    Reported-and-tested-by: Martin Poupe 
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 7513bb083c15..6585f527e381 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -359,11 +359,6 @@ static void destroy_async(struct dev_state *ps, struct list_head *list)
+ 		spin_lock_irqsave(&ps->lock, flags);
+ 	}
+ 	spin_unlock_irqrestore(&ps->lock, flags);
+-	as = async_getcompleted(ps);
+-	while (as) {
+-		free_async(as);
+-		as = async_getcompleted(ps);
+-	}
+ }
+ 
+ static void destroy_async_on_interface(struct dev_state *ps,
+@@ -643,6 +638,7 @@ static int usbdev_release(struct inode *inode, struct file *file)
+ 	struct dev_state *ps = file->private_data;
+ 	struct usb_device *dev = ps->dev;
+ 	unsigned int ifnum;
++	struct async *as;
+ 
+ 	usb_lock_device(dev);
+ 
+@@ -661,6 +657,12 @@ static int usbdev_release(struct inode *inode, struct file *file)
+ 	usb_unlock_device(dev);
+ 	usb_put_dev(dev);
+ 	put_pid(ps->disc_pid);
++
++	as = async_getcompleted(ps);
++	while (as) {
++		free_async(as);
++		as = async_getcompleted(ps);
++	}
+ 	kfree(ps);
+ 	return 0;
+ }

commit 77c019768f0607c36e25bec11ce3e1eabef09277
+Author: Alan Stern 
+Date:   Fri Feb 27 16:51:42 2009 -0500
+
+    [SCSI] fix /proc memory leak in the SCSI core
+    
+    The SCSI core calls scsi_proc_hostdir_add() from within
+    scsi_host_alloc(), but the corresponding scsi_proc_hostdir_rm()
+    routine is called from within scsi_remove_host().  As a result, if a
+    host is allocated and then deallocated without ever being registered,
+    the host's directory in /proc is leaked.
+    
+    This patch (as1181b) fixes this bug in the SCSI core by moving
+    scsi_proc_hostdir_rm() into scsi_host_dev_release().
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
+index aa670a1d1513..89d41a424b33 100644
+--- a/drivers/scsi/hosts.c
++++ b/drivers/scsi/hosts.c
+@@ -176,7 +176,6 @@ void scsi_remove_host(struct Scsi_Host *shost)
+ 	transport_unregister_device(&shost->shost_gendev);
+ 	device_unregister(&shost->shost_dev);
+ 	device_del(&shost->shost_gendev);
+-	scsi_proc_hostdir_rm(shost->hostt);
+ }
+ EXPORT_SYMBOL(scsi_remove_host);
+ 
+@@ -270,6 +269,8 @@ static void scsi_host_dev_release(struct device *dev)
+ 	struct Scsi_Host *shost = dev_to_shost(dev);
+ 	struct device *parent = dev->parent;
+ 
++	scsi_proc_hostdir_rm(shost->hostt);
++
+ 	if (shost->ehandler)
+ 		kthread_stop(shost->ehandler);
+ 	if (shost->work_q)

commit 5c211caa9f341f9eefbda89436d1440d1eccb3bc
+Author: Alan Stern 
+Date:   Wed Feb 18 10:54:44 2009 -0500
+
+    [SCSI] sd: tell the user when a disk's capacity is adjusted
+    
+    This patch (as1188) combines the tests for decrementing a drive's
+    reported capacity and expands the comment.  It also adds an
+    informational message to the system log, informing the user when the
+    reported value has been changed.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+index 4970ae4a62d6..e744ee40be69 100644
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -1383,18 +1383,22 @@ sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer)
+ 		sd_read_protection_type(sdkp, buffer);
+ 	}	
+ 
+-	/* Some devices return the total number of sectors, not the
+-	 * highest sector number.  Make the necessary adjustment. */
+-	if (sdp->fix_capacity) {
++	/* Some devices are known to return the total number of blocks,
++	 * not the highest block number.  Some devices have versions
++	 * which do this and others which do not.  Some devices we might
++	 * suspect of doing this but we don't know for certain.
++	 *
++	 * If we know the reported capacity is wrong, decrement it.  If
++	 * we can only guess, then assume the number of blocks is even
++	 * (usually true but not always) and err on the side of lowering
++	 * the capacity.
++	 */
++	if (sdp->fix_capacity ||
++	    (sdp->guess_capacity && (sdkp->capacity & 0x01))) {
++		sd_printk(KERN_INFO, sdkp, "Adjusting the sector count "
++				"from its reported value: %llu\n",
++				(unsigned long long) sdkp->capacity);
+ 		--sdkp->capacity;
+-
+-	/* Some devices have version which report the correct sizes
+-	 * and others which do not. We guess size according to a heuristic
+-	 * and err on the side of lowering the capacity. */
+-	} else {
+-		if (sdp->guess_capacity)
+-			if (sdkp->capacity & 0x01) /* odd sizes are odd */
+-				--sdkp->capacity;
+ 	}
+ 
+ got_data:

commit 67f5a4ba9741fcef3f4db3509ad03565d9e33af2
+Author: Alan Stern 
+Date:   Fri Feb 20 16:33:08 2009 -0500
+
+    USB: usb_get_string should check the descriptor type
+    
+    This patch (as1218) fixes a problem with a radio-control joystick used
+    in the "walkera 4#3" helicopter.  This device responds to the initial
+    Get-String-Descriptor request for string 0 (which is really the list
+    of supported languages) by sending its config descriptor!  The
+    usb_get_string() routine needs to check whether it got the right
+    type of descriptor.
+    
+    Oddly enough, this sort of check is already present in
+    usb_get_descriptor().  The patch changes the error code from -EPROTO
+    to -ENODATA, because -EPROTO shows up in so many other contexts to
+    indicate a hardware failure rather than a firmware error.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Guillermo Jarabo 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+    
+    ===================================================================
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 31fb204f44c6..49e7f56e0d7f 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -653,7 +653,7 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type,
+ 		if (result <= 0 && result != -ETIMEDOUT)
+ 			continue;
+ 		if (result > 1 && ((u8 *)buf)[1] != type) {
+-			result = -EPROTO;
++			result = -ENODATA;
+ 			continue;
+ 		}
+ 		break;
+@@ -696,8 +696,13 @@ static int usb_get_string(struct usb_device *dev, unsigned short langid,
+ 			USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+ 			(USB_DT_STRING << 8) + index, langid, buf, size,
+ 			USB_CTRL_GET_TIMEOUT);
+-		if (!(result == 0 || result == -EPIPE))
+-			break;
++		if (result == 0 || result == -EPIPE)
++			continue;
++		if (result > 1 && ((u8 *) buf)[1] != USB_DT_STRING) {
++			result = -ENODATA;
++			continue;
++		}
++		break;
+ 	}
+ 	return result;
+ }

commit ce459ec1d278b19be8e0719dbfd47dd1d6687bfb
+Author: Alan Stern 
+Date:   Tue Feb 24 16:19:47 2009 -0500
+
+    USB: g_file_storage: automatically disable stalls under Atmel
+    
+    This patch (as1220) automatically disables stalls when g_file_storage
+    finds itself running with an Atmel device controller, because the
+    Atmel hardware/driver isn't capable of halting bulk endpoints
+    correctly.
+    
+    Reported-by: Stanislaw Gruszka 
+    Signed-off-by: Alan Stern 
+    Acked-by: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index b10fa31cc915..1ab9dac7e12d 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -3879,7 +3879,11 @@ static int __init check_parameters(struct fsg_dev *fsg)
+ 	mod_data.protocol_type = USB_SC_SCSI;
+ 	mod_data.protocol_name = "Transparent SCSI";
+ 
+-	if (gadget_is_sh(fsg->gadget))
++	/* Some peripheral controllers are known not to be able to
++	 * halt bulk endpoints correctly.  If one of them is present,
++	 * disable stalls.
++	 */
++	if (gadget_is_sh(fsg->gadget) || gadget_is_at91(fsg->gadget))
+ 		mod_data.can_stall = 0;
+ 
+ 	if (mod_data.release == 0xffff) {	// Parameter wasn't set

commit 5126a2674ddac0804450f59da25a058cca629d38
+Author: Alan Stern 
+Date:   Mon Feb 23 12:02:05 2009 -0500
+
+    USB: usb-storage: add IGNORE_RESIDUE flag for Genesys Logic adapters
+    
+    This patch (as1219) adds the IGNORE_RESIDUE flag to the unusual_devs
+    entries for Genesys Logic's USB-IDE adapter.  Although this device
+    usually gets the residue correct, there is one command crucial to the
+    operation of CD and DVD drives which it messes up.
+    
+    Tested-by: Mike Lampard 
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 50dc33a6065b..6f59c8e510ea 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -907,13 +907,13 @@ UNUSUAL_DEV(  0x05e3, 0x0701, 0x0000, 0xffff,
+ 		"Genesys Logic",
+ 		"USB to IDE Optical",
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 ),
++		US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 | US_FL_IGNORE_RESIDUE ),
+ 
+ UNUSUAL_DEV(  0x05e3, 0x0702, 0x0000, 0xffff,
+ 		"Genesys Logic",
+ 		"USB to IDE Disk",
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 ),
++		US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 | US_FL_IGNORE_RESIDUE ),
+ 
+ /* Reported by Ben Efros  */
+ UNUSUAL_DEV(  0x05e3, 0x0723, 0x9451, 0x9451,

commit 506e9469833c66ed6bb9acd902e208f7301b6adb
+Author: Alan Stern 
+Date:   Wed Feb 4 15:48:03 2009 -0500
+
+    USB: usb-storage: add Pentax to the bad-vendor list
+    
+    This patch (as1202) adds Pentax to usb-storage's list of bad vendors
+    whose devices always need the CAPACITY_HEURISTICS flag.  This is in
+    addition to the existing entries: Nokia, Nikon, and Motorola.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Virgo Pärna 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index 2a42b862aa9f..727c506417cc 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -64,6 +64,7 @@
+  */
+ #define VENDOR_ID_NOKIA		0x0421
+ #define VENDOR_ID_NIKON		0x04b0
++#define VENDOR_ID_PENTAX	0x0a17
+ #define VENDOR_ID_MOTOROLA	0x22b8
+ 
+ /***********************************************************************
+@@ -158,6 +159,7 @@ static int slave_configure(struct scsi_device *sdev)
+ 		switch (le16_to_cpu(us->pusb_dev->descriptor.idVendor)) {
+ 		case VENDOR_ID_NOKIA:
+ 		case VENDOR_ID_NIKON:
++		case VENDOR_ID_PENTAX:
+ 		case VENDOR_ID_MOTOROLA:
+ 			if (!(us->fflags & (US_FL_FIX_CAPACITY |
+ 					US_FL_CAPACITY_OK)))
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 69269f739563..8e878cab8dc7 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -1354,21 +1354,6 @@ UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_FIX_INQUIRY ),
+ 
+-
+-/* Submitted by Per Winkvist  */
+-UNUSUAL_DEV( 0x0a17, 0x006, 0x0000, 0xffff,
+-		"Pentax",
+-		"Optio S/S4",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_FIX_INQUIRY ),
+-
+-/* Reported by Jaak Ristioja  */
+-UNUSUAL_DEV( 0x0a17, 0x006e, 0x0100, 0x0100,
+-		"Pentax",
+-		"K10D",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_FIX_CAPACITY ),
+-
+ /* These are virtual windows driver CDs, which the zd1211rw driver
+  * automatically converts into WLAN devices. */
+ UNUSUAL_DEV( 0x0ace, 0x2011, 0x0101, 0x0101,

commit 0d020aae0a154cffce680a7775c74788fa0bea92
+Author: Alan Stern 
+Date:   Mon Feb 2 09:51:01 2009 -0500
+
+    USB: usb-storage: remove WARN from last-sector hacks
+    
+    This patch (as1201) removes the WARN() from the last-sector hacks in
+    usb-storage, thereby making the code match the version now in
+    .27-stable and .28-stable.  The WARN() isn't needed, since there is no
+    longer any intention of assuming that all storage devices have an even
+    number of sectors, and it annoys users for no good reason.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+index 1d5438e6363b..fb65d221cedf 100644
+--- a/drivers/usb/storage/transport.c
++++ b/drivers/usb/storage/transport.c
+@@ -558,32 +558,10 @@ static void last_sector_hacks(struct us_data *us, struct scsi_cmnd *srb)
+ 
+ 	if (srb->result == SAM_STAT_GOOD && scsi_get_resid(srb) == 0) {
+ 
+-		/* The command succeeded.  If the capacity is odd
+-		 * (i.e., if the sector number is even) then the
+-		 * "always-even" heuristic would be wrong for this
+-		 * device.  Issue a WARN() so that the kerneloops.org
+-		 * project will be notified and we will then know to
+-		 * mark the device with a CAPACITY_OK flag.  Hopefully
+-		 * this will occur for only a few devices.
+-		 *
+-		 * Use the sign of us->last_sector_hacks to tell whether
+-		 * the warning has already been issued; we don't need
+-		 * more than one warning per device.
++		/* The command succeeded.  We know this device doesn't
++		 * have the last-sector bug, so stop checking it.
+ 		 */
+-		if (!(sector & 1) && us->use_last_sector_hacks > 0) {
+-			unsigned vid = le16_to_cpu(
+-					us->pusb_dev->descriptor.idVendor);
+-			unsigned pid = le16_to_cpu(
+-					us->pusb_dev->descriptor.idProduct);
+-			unsigned rev = le16_to_cpu(
+-					us->pusb_dev->descriptor.bcdDevice);
+-
+-			WARN(1, "%s: Successful last sector success at %u, "
+-					"device %04x:%04x:%04x\n",
+-					sdkp->disk->disk_name, sector,
+-					vid, pid, rev);
+-			us->use_last_sector_hacks = -1;
+-		}
++		us->use_last_sector_hacks = 0;
+ 
+ 	} else {
+ 		/* The command failed.  Allow up to 3 retries in case this
+@@ -599,14 +577,6 @@ static void last_sector_hacks(struct us_data *us, struct scsi_cmnd *srb)
+ 		srb->result = SAM_STAT_CHECK_CONDITION;
+ 		memcpy(srb->sense_buffer, record_not_found,
+ 				sizeof(record_not_found));
+-
+-		/* In theory we might want to issue a WARN() here if the
+-		 * capacity is even, since it could indicate the device
+-		 * has the READ CAPACITY bug _and_ the real capacity is
+-		 * odd.  But it could also indicate that the device
+-		 * simply can't access its last sector, a failure mode
+-		 * which is surprisingly common.  So no warning.
+-		 */
+ 	}
+ 
+  done:

commit 501950d846218ed80a776d2aae5aed9c8b92e778
+Author: Alan Stern 
+Date:   Tue Jan 13 11:33:42 2009 -0500
+
+    USB: fix char-device disconnect handling
+    
+    This patch (as1198) fixes a conceptual bug: Somewhere along the line
+    we managed to confuse USB class devices with USB char devices.  As a
+    result, the code to send a disconnect signal to userspace would not be
+    built if both CONFIG_USB_DEVICE_CLASS and CONFIG_USB_DEVICEFS were
+    disabled.
+    
+    The usb_fs_classdev_common_remove() routine has been renamed to
+    usbdev_remove() and it is now called whenever any USB device is
+    removed, not just when a class device is unregistered.  The notifier
+    registration and unregistration calls are no longer conditionally
+    compiled.  And since the common removal code will always be called as
+    part of the char device interface, there's no need to call it again as
+    part of the usbfs interface; thus the invocation of
+    usb_fs_classdev_common_remove() has been taken out of
+    usbfs_remove_device().
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Alon Bar-Lev 
+    Tested-by: Alon Bar-Lev 
+    Cc: stable 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 26fece124e0e..7513bb083c15 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -1700,7 +1700,7 @@ const struct file_operations usbdev_file_operations = {
+ 	.release =	usbdev_release,
+ };
+ 
+-void usb_fs_classdev_common_remove(struct usb_device *udev)
++static void usbdev_remove(struct usb_device *udev)
+ {
+ 	struct dev_state *ps;
+ 	struct siginfo sinfo;
+@@ -1742,10 +1742,15 @@ static void usb_classdev_remove(struct usb_device *dev)
+ {
+ 	if (dev->usb_classdev)
+ 		device_unregister(dev->usb_classdev);
+-	usb_fs_classdev_common_remove(dev);
+ }
+ 
+-static int usb_classdev_notify(struct notifier_block *self,
++#else
++#define usb_classdev_add(dev)		0
++#define usb_classdev_remove(dev)	do {} while (0)
++
++#endif
++
++static int usbdev_notify(struct notifier_block *self,
+ 			       unsigned long action, void *dev)
+ {
+ 	switch (action) {
+@@ -1755,15 +1760,15 @@ static int usb_classdev_notify(struct notifier_block *self,
+ 		break;
+ 	case USB_DEVICE_REMOVE:
+ 		usb_classdev_remove(dev);
++		usbdev_remove(dev);
+ 		break;
+ 	}
+ 	return NOTIFY_OK;
+ }
+ 
+ static struct notifier_block usbdev_nb = {
+-	.notifier_call = 	usb_classdev_notify,
++	.notifier_call = 	usbdev_notify,
+ };
+-#endif
+ 
+ static struct cdev usb_device_cdev;
+ 
+@@ -1798,9 +1803,8 @@ int __init usb_devio_init(void)
+ 	 * to /sys/dev
+ 	 */
+ 	usb_classdev_class->dev_kobj = NULL;
+-
+-	usb_register_notify(&usbdev_nb);
+ #endif
++	usb_register_notify(&usbdev_nb);
+ out:
+ 	return retval;
+ 
+@@ -1811,8 +1815,8 @@ int __init usb_devio_init(void)
+ 
+ void usb_devio_cleanup(void)
+ {
+-#ifdef CONFIG_USB_DEVICE_CLASS
+ 	usb_unregister_notify(&usbdev_nb);
++#ifdef CONFIG_USB_DEVICE_CLASS
+ 	class_destroy(usb_classdev_class);
+ #endif
+ 	cdev_del(&usb_device_cdev);
+diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
+index 2a129cb7bb56..dff5760a37f6 100644
+--- a/drivers/usb/core/inode.c
++++ b/drivers/usb/core/inode.c
+@@ -717,7 +717,6 @@ static void usbfs_remove_device(struct usb_device *dev)
+ 		fs_remove_file (dev->usbfs_dentry);
+ 		dev->usbfs_dentry = NULL;
+ 	}
+-	usb_fs_classdev_common_remove(dev);
+ }
+ 
+ static int usbfs_notify(struct notifier_block *self, unsigned long action, void *dev)
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 9d0f33fe8719..79d8a9ea559b 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -152,7 +152,6 @@ extern struct usb_driver usbfs_driver;
+ extern const struct file_operations usbfs_devices_fops;
+ extern const struct file_operations usbdev_file_operations;
+ extern void usbfs_conn_disc_event(void);
+-extern void usb_fs_classdev_common_remove(struct usb_device *udev);
+ 
+ extern int usb_devio_init(void);
+ extern void usb_devio_cleanup(void);

commit bcca06efea883bdf3803a0bb0ffa60f26730387d
+Author: Alan Stern 
+Date:   Tue Jan 13 11:35:54 2009 -0500
+
+    USB: don't enable wakeup by default for PCI host controllers
+    
+    This patch (as1199) changes the initial wakeup settings for PCI USB
+    host controllers.  The controllers are marked as capable of waking the
+    system, but wakeup is not enabled by default.
+    
+    It turns out that enabling wakeup for USB host controllers has a lot
+    of bad consequences.  As the simplest example, if a USB mouse or
+    keyboard is unplugged immediately after the computer is put to sleep,
+    the unplug will cause the system to wake back up again!  We are better
+    off marking them as wakeup-capable and leaving wakeup disabled.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Rafael J. Wysocki 
+    CC: David Brownell 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index 507741ed4482..99432785f438 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -128,7 +128,6 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ 	}
+ 
+ 	pci_set_master(dev);
+-	device_set_wakeup_enable(&dev->dev, 1);
+ 
+ 	retval = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED);
+ 	if (retval != 0)
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index bdc6e86e1f8b..9faa5c8fe025 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -230,7 +230,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 		pci_read_config_word(pdev, 0x62, &port_wake);
+ 		if (port_wake & 0x0001) {
+ 			dev_warn(&pdev->dev, "Enabling legacy PCI PM\n");
+-			device_init_wakeup(&pdev->dev, 1);
++			device_set_wakeup_capable(&pdev->dev, 1);
+ 		}
+ 	}
+ 
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index 65a9609f4ad6..5cf5f1eca4f4 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -593,12 +593,10 @@ static int ohci_run (struct ohci_hcd *ohci)
+ 	 * to be checked in case boot firmware (BIOS/SMM/...) has set up
+ 	 * wakeup in a way the bus isn't aware of (e.g., legacy PCI PM).
+ 	 * If the bus glue detected wakeup capability then it should
+-	 * already be enabled.  Either way, if wakeup should be enabled
+-	 * but isn't, we'll enable it now.
++	 * already be enabled; if so we'll just enable it again.
+ 	 */
+-	if ((ohci->hc_control & OHCI_CTRL_RWC) != 0
+-			&& !device_can_wakeup(hcd->self.controller))
+-		device_init_wakeup(hcd->self.controller, 1);
++	if ((ohci->hc_control & OHCI_CTRL_RWC) != 0)
++		device_set_wakeup_capable(hcd->self.controller, 1);
+ 
+ 	switch (ohci->hc_control & OHCI_CTRL_HCFS) {
+ 	case OHCI_USB_OPER:

commit ddeac4e75f2527a340f9dc655bde49bb2429b39b
+Author: Alan Stern 
+Date:   Thu Jan 15 17:03:33 2009 -0500
+
+    USB: fix toggle mismatch in disable_endpoint paths
+    
+    This patch (as1200) finishes some fixes that were left incomplete by
+    an earlier patch.
+    
+    Although nobody has addressed this issue in the past, it turns out
+    that we need to distinguish between two different modes of disabling
+    and enabling endpoints.  In one mode only the data structures in
+    usbcore are affected, and in the other mode the host controller and
+    device hardware states are affected as well.
+    
+    The earlier patch added an extra argument to the routines in the
+    enable_endpoint pathways to reflect this difference.  This patch adds
+    corresponding arguments to the disable_endpoint pathways.  Without
+    this change, the endpoint toggle state can get out of sync between
+    the host and the device.  The exact mechanism depends on the details
+    of the host controller (whether or not it stores its own copy of the
+    toggle values).
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: Dan Streetman 
+    Tested-by: Dan Streetman 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 98760553bc95..d0a21a5f8201 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -284,7 +284,7 @@ static int usb_unbind_interface(struct device *dev)
+ 	 * supports "soft" unbinding.
+ 	 */
+ 	if (!driver->soft_unbind)
+-		usb_disable_interface(udev, intf);
++		usb_disable_interface(udev, intf, false);
+ 
+ 	driver->disconnect(intf);
+ 	usb_cancel_queued_reset(intf);
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 94d5ee263c20..cd50d86029e7 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2382,8 +2382,8 @@ static int hub_port_debounce(struct usb_hub *hub, int port1)
+ 
+ void usb_ep0_reinit(struct usb_device *udev)
+ {
+-	usb_disable_endpoint(udev, 0 + USB_DIR_IN);
+-	usb_disable_endpoint(udev, 0 + USB_DIR_OUT);
++	usb_disable_endpoint(udev, 0 + USB_DIR_IN, true);
++	usb_disable_endpoint(udev, 0 + USB_DIR_OUT, true);
+ 	usb_enable_endpoint(udev, &udev->ep0, true);
+ }
+ EXPORT_SYMBOL_GPL(usb_ep0_reinit);
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index de51667dd64d..31fb204f44c6 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1039,14 +1039,15 @@ static void remove_intf_ep_devs(struct usb_interface *intf)
+  * @dev: the device whose endpoint is being disabled
+  * @epaddr: the endpoint's address.  Endpoint number for output,
+  *	endpoint number + USB_DIR_IN for input
++ * @reset_hardware: flag to erase any endpoint state stored in the
++ *	controller hardware
+  *
+- * Deallocates hcd/hardware state for this endpoint ... and nukes all
+- * pending urbs.
+- *
+- * If the HCD hasn't registered a disable() function, this sets the
+- * endpoint's maxpacket size to 0 to prevent further submissions.
++ * Disables the endpoint for URB submission and nukes all pending URBs.
++ * If @reset_hardware is set then also deallocates hcd/hardware state
++ * for the endpoint.
+  */
+-void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr)
++void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr,
++		bool reset_hardware)
+ {
+ 	unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;
+ 	struct usb_host_endpoint *ep;
+@@ -1056,15 +1057,18 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr)
+ 
+ 	if (usb_endpoint_out(epaddr)) {
+ 		ep = dev->ep_out[epnum];
+-		dev->ep_out[epnum] = NULL;
++		if (reset_hardware)
++			dev->ep_out[epnum] = NULL;
+ 	} else {
+ 		ep = dev->ep_in[epnum];
+-		dev->ep_in[epnum] = NULL;
++		if (reset_hardware)
++			dev->ep_in[epnum] = NULL;
+ 	}
+ 	if (ep) {
+ 		ep->enabled = 0;
+ 		usb_hcd_flush_endpoint(dev, ep);
+-		usb_hcd_disable_endpoint(dev, ep);
++		if (reset_hardware)
++			usb_hcd_disable_endpoint(dev, ep);
+ 	}
+ }
+ 
+@@ -1072,17 +1076,21 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr)
+  * usb_disable_interface -- Disable all endpoints for an interface
+  * @dev: the device whose interface is being disabled
+  * @intf: pointer to the interface descriptor
++ * @reset_hardware: flag to erase any endpoint state stored in the
++ *	controller hardware
+  *
+  * Disables all the endpoints for the interface's current altsetting.
+  */
+-void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf)
++void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf,
++		bool reset_hardware)
+ {
+ 	struct usb_host_interface *alt = intf->cur_altsetting;
+ 	int i;
+ 
+ 	for (i = 0; i < alt->desc.bNumEndpoints; ++i) {
+ 		usb_disable_endpoint(dev,
+-				alt->endpoint[i].desc.bEndpointAddress);
++				alt->endpoint[i].desc.bEndpointAddress,
++				reset_hardware);
+ 	}
+ }
+ 
+@@ -1103,8 +1111,8 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
+ 	dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__,
+ 		skip_ep0 ? "non-ep0" : "all");
+ 	for (i = skip_ep0; i < 16; ++i) {
+-		usb_disable_endpoint(dev, i);
+-		usb_disable_endpoint(dev, i + USB_DIR_IN);
++		usb_disable_endpoint(dev, i, true);
++		usb_disable_endpoint(dev, i + USB_DIR_IN, true);
+ 	}
+ 	dev->toggle[0] = dev->toggle[1] = 0;
+ 
+@@ -1274,7 +1282,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
+ 		remove_intf_ep_devs(iface);
+ 		usb_remove_sysfs_intf_files(iface);
+ 	}
+-	usb_disable_interface(dev, iface);
++	usb_disable_interface(dev, iface, true);
+ 
+ 	iface->cur_altsetting = alt;
+ 
+@@ -1353,8 +1361,8 @@ int usb_reset_configuration(struct usb_device *dev)
+ 	 */
+ 
+ 	for (i = 1; i < 16; ++i) {
+-		usb_disable_endpoint(dev, i);
+-		usb_disable_endpoint(dev, i + USB_DIR_IN);
++		usb_disable_endpoint(dev, i, true);
++		usb_disable_endpoint(dev, i + USB_DIR_IN, true);
+ 	}
+ 
+ 	config = dev->actconfig;
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 386177867a8a..9d0f33fe8719 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -15,9 +15,10 @@ extern void usb_enable_endpoint(struct usb_device *dev,
+ 		struct usb_host_endpoint *ep, bool reset_toggle);
+ extern void usb_enable_interface(struct usb_device *dev,
+ 		struct usb_interface *intf, bool reset_toggles);
+-extern void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr);
++extern void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr,
++		bool reset_hardware);
+ extern void usb_disable_interface(struct usb_device *dev,
+-		struct usb_interface *intf);
++		struct usb_interface *intf, bool reset_hardware);
+ extern void usb_release_interface_cache(struct kref *ref);
+ extern void usb_disable_device(struct usb_device *dev, int skip_ep0);
+ extern int usb_deauthorize_device(struct usb_device *);

commit bebd590ca27e80ffe3129ab4f0a3124f0a340f43
+Author: Alan Stern 
+Date:   Tue Dec 16 14:06:58 2008 -0500
+
+    PCI: fix incorrect error return in pci_enable_wake
+    
+    This patch (as1186) fixes a minor mistake in pci_enable_wake().  When
+    the routine is asked to disable remote wakeup, it should not return an
+    error merely because the device is not allowed to do wakeups!
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Rafael J. Wysocki 
+    Signed-off-by: Jesse Barnes 
+
+diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
+index d4d71fae6233..1fb7cff4cdae 100644
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -1091,7 +1091,7 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable)
+ 	int error = 0;
+ 	bool pme_done = false;
+ 
+-	if (!device_may_wakeup(&dev->dev))
++	if (enable && !device_may_wakeup(&dev->dev))
+ 		return -EINVAL;
+ 
+ 	/*

commit 2caf7fcdb8532045680f06b67b9e63f0c9613aaa
+Author: Alan Stern 
+Date:   Wed Dec 31 11:31:33 2008 -0500
+
+    USB: re-enable interface after driver unbinds
+    
+    This patch (as1197) fixes an error introduced recently.  Since a
+    significant number of devices can't handle Set-Interface requests, we
+    no longer call usb_set_interface() when a driver unbinds from an
+    interface, provided the interface is already in altsetting 0.  However
+    the interface still does get disabled, and the call to
+    usb_set_interface() was the only thing re-enabling it.  Since the
+    interface doesn't get re-enabled, further attempts to use it fail.
+    
+    So the patch adds a call to usb_enable_interface() when a driver
+    unbinds and the interface is in altsetting 0.  For this to work
+    right, the interface's endpoints have to be re-enabled but their
+    toggles have to be left alone.  Therefore an additional argument is
+    added to usb_enable_endpoint() and usb_enable_interface(), a flag
+    indicating whether or not the endpoint toggles should be reset.
+    
+    This is a forward-ported version of a patch which fixes Bugzilla
+    #12301.
+    
+    Signed-off-by: Alan Stern 
+    Reported-by: David Roka 
+    Reported-by: Erik Ekman 
+    Tested-by: Erik Ekman 
+    Tested-by: Alon Bar-Lev 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 41c06025506e..98760553bc95 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -295,9 +295,12 @@ static int usb_unbind_interface(struct device *dev)
+ 	 * altsetting means creating new endpoint device entries).
+ 	 * When either of these happens, defer the Set-Interface.
+ 	 */
+-	if (intf->cur_altsetting->desc.bAlternateSetting == 0)
+-		;	/* Already in altsetting 0 so skip Set-Interface */
+-	else if (!error && intf->dev.power.status == DPM_ON)
++	if (intf->cur_altsetting->desc.bAlternateSetting == 0) {
++		/* Already in altsetting 0 so skip Set-Interface.
++		 * Just re-enable it without affecting the endpoint toggles.
++		 */
++		usb_enable_interface(udev, intf, false);
++	} else if (!error && intf->dev.power.status == DPM_ON)
+ 		usb_set_interface(udev, intf->altsetting[0].
+ 				desc.bInterfaceNumber, 0);
+ 	else
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 756b8d9993fc..d5d0e40b1e2d 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2384,7 +2384,7 @@ void usb_ep0_reinit(struct usb_device *udev)
+ {
+ 	usb_disable_endpoint(udev, 0 + USB_DIR_IN);
+ 	usb_disable_endpoint(udev, 0 + USB_DIR_OUT);
+-	usb_enable_endpoint(udev, &udev->ep0);
++	usb_enable_endpoint(udev, &udev->ep0, true);
+ }
+ EXPORT_SYMBOL_GPL(usb_ep0_reinit);
+ 
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 5589686981f1..de51667dd64d 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1143,22 +1143,26 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
+  * usb_enable_endpoint - Enable an endpoint for USB communications
+  * @dev: the device whose interface is being enabled
+  * @ep: the endpoint
++ * @reset_toggle: flag to set the endpoint's toggle back to 0
+  *
+- * Resets the endpoint toggle, and sets dev->ep_{in,out} pointers.
++ * Resets the endpoint toggle if asked, and sets dev->ep_{in,out} pointers.
+  * For control endpoints, both the input and output sides are handled.
+  */
+-void usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep)
++void usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep,
++		bool reset_toggle)
+ {
+ 	int epnum = usb_endpoint_num(&ep->desc);
+ 	int is_out = usb_endpoint_dir_out(&ep->desc);
+ 	int is_control = usb_endpoint_xfer_control(&ep->desc);
+ 
+ 	if (is_out || is_control) {
+-		usb_settoggle(dev, epnum, 1, 0);
++		if (reset_toggle)
++			usb_settoggle(dev, epnum, 1, 0);
+ 		dev->ep_out[epnum] = ep;
+ 	}
+ 	if (!is_out || is_control) {
+-		usb_settoggle(dev, epnum, 0, 0);
++		if (reset_toggle)
++			usb_settoggle(dev, epnum, 0, 0);
+ 		dev->ep_in[epnum] = ep;
+ 	}
+ 	ep->enabled = 1;
+@@ -1168,17 +1172,18 @@ void usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep)
+  * usb_enable_interface - Enable all the endpoints for an interface
+  * @dev: the device whose interface is being enabled
+  * @intf: pointer to the interface descriptor
++ * @reset_toggles: flag to set the endpoints' toggles back to 0
+  *
+  * Enables all the endpoints for the interface's current altsetting.
+  */
+-static void usb_enable_interface(struct usb_device *dev,
+-				 struct usb_interface *intf)
++void usb_enable_interface(struct usb_device *dev,
++		struct usb_interface *intf, bool reset_toggles)
+ {
+ 	struct usb_host_interface *alt = intf->cur_altsetting;
+ 	int i;
+ 
+ 	for (i = 0; i < alt->desc.bNumEndpoints; ++i)
+-		usb_enable_endpoint(dev, &alt->endpoint[i]);
++		usb_enable_endpoint(dev, &alt->endpoint[i], reset_toggles);
+ }
+ 
+ /**
+@@ -1303,7 +1308,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
+ 	 * during the SETUP stage - hence EP0 toggles are "don't care" here.
+ 	 * (Likewise, EP0 never "halts" on well designed devices.)
+ 	 */
+-	usb_enable_interface(dev, iface);
++	usb_enable_interface(dev, iface, true);
+ 	if (device_is_registered(&iface->dev)) {
+ 		usb_create_sysfs_intf_files(iface);
+ 		create_intf_ep_devs(iface);
+@@ -1382,7 +1387,7 @@ int usb_reset_configuration(struct usb_device *dev)
+ 			usb_remove_sysfs_intf_files(intf);
+ 		}
+ 		intf->cur_altsetting = alt;
+-		usb_enable_interface(dev, intf);
++		usb_enable_interface(dev, intf, true);
+ 		if (device_is_registered(&intf->dev)) {
+ 			usb_create_sysfs_intf_files(intf);
+ 			create_intf_ep_devs(intf);
+@@ -1685,7 +1690,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 			alt = &intf->altsetting[0];
+ 
+ 		intf->cur_altsetting = alt;
+-		usb_enable_interface(dev, intf);
++		usb_enable_interface(dev, intf, true);
+ 		intf->dev.parent = &dev->dev;
+ 		intf->dev.driver = NULL;
+ 		intf->dev.bus = &usb_bus_type;
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index c0821564a3fe..dcfc072630c1 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -362,7 +362,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
+ 	dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;
+ 	dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;
+ 	/* ep0 maxpacket comes later, from device descriptor */
+-	usb_enable_endpoint(dev, &dev->ep0);
++	usb_enable_endpoint(dev, &dev->ep0, true);
+ 	dev->can_submit = 1;
+ 
+ 	/* Save readable and stable topology id, distinguishing devices
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 381eae90c3b7..386177867a8a 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -12,7 +12,9 @@ extern int usb_create_ep_devs(struct device *parent,
+ extern void usb_remove_ep_devs(struct usb_host_endpoint *endpoint);
+ 
+ extern void usb_enable_endpoint(struct usb_device *dev,
+-		struct usb_host_endpoint *ep);
++		struct usb_host_endpoint *ep, bool reset_toggle);
++extern void usb_enable_interface(struct usb_device *dev,
++		struct usb_interface *intf, bool reset_toggles);
+ extern void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr);
+ extern void usb_disable_interface(struct usb_device *dev,
+ 		struct usb_interface *intf);

commit df718962bf91c7bd345060aadaa24b03f6140b07
+Author: Alan Stern 
+Date:   Fri Dec 19 10:27:56 2008 -0500
+
+    USB: cancel pending Set-Config requests if userspace gets there first
+    
+    This patch (as1195) eliminates a potential problem identified by
+    Oliver Neukum.  When a driver queues an asynchronous Set-Config
+    request using usb_driver_set_configuration(), the request should be
+    cancelled if userspace changes the configuration first.  The patch
+    introduces a linked list of pending async Set-Config requests, and
+    uses it to invalidate the requests for a particular device whenever
+    that device's configuration is set.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Oliver Neukum 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 7943901c641c..5589686981f1 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -18,6 +18,8 @@
+ #include "hcd.h"	/* for usbcore internals */
+ #include "usb.h"
+ 
++static void cancel_async_set_config(struct usb_device *udev);
++
+ struct api_context {
+ 	struct completion	done;
+ 	int			status;
+@@ -1636,6 +1638,9 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 	if (dev->state != USB_STATE_ADDRESS)
+ 		usb_disable_device(dev, 1);	/* Skip ep0 */
+ 
++	/* Get rid of pending async Set-Config requests for this device */
++	cancel_async_set_config(dev);
++
+ 	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ 			      USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
+ 			      NULL, 0, USB_CTRL_SET_TIMEOUT);
+@@ -1725,10 +1730,14 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 	return 0;
+ }
+ 
++static LIST_HEAD(set_config_list);
++static DEFINE_SPINLOCK(set_config_lock);
++
+ struct set_config_request {
+ 	struct usb_device	*udev;
+ 	int			config;
+ 	struct work_struct	work;
++	struct list_head	node;
+ };
+ 
+ /* Worker routine for usb_driver_set_configuration() */
+@@ -1736,14 +1745,35 @@ static void driver_set_config_work(struct work_struct *work)
+ {
+ 	struct set_config_request *req =
+ 		container_of(work, struct set_config_request, work);
++	struct usb_device *udev = req->udev;
+ 
+-	usb_lock_device(req->udev);
+-	usb_set_configuration(req->udev, req->config);
+-	usb_unlock_device(req->udev);
+-	usb_put_dev(req->udev);
++	usb_lock_device(udev);
++	spin_lock(&set_config_lock);
++	list_del(&req->node);
++	spin_unlock(&set_config_lock);
++
++	if (req->config >= -1)		/* Is req still valid? */
++		usb_set_configuration(udev, req->config);
++	usb_unlock_device(udev);
++	usb_put_dev(udev);
+ 	kfree(req);
+ }
+ 
++/* Cancel pending Set-Config requests for a device whose configuration
++ * was just changed
++ */
++static void cancel_async_set_config(struct usb_device *udev)
++{
++	struct set_config_request *req;
++
++	spin_lock(&set_config_lock);
++	list_for_each_entry(req, &set_config_list, node) {
++		if (req->udev == udev)
++			req->config = -999;	/* Mark as cancelled */
++	}
++	spin_unlock(&set_config_lock);
++}
++
+ /**
+  * usb_driver_set_configuration - Provide a way for drivers to change device configurations
+  * @udev: the device whose configuration is being updated
+@@ -1775,6 +1805,10 @@ int usb_driver_set_configuration(struct usb_device *udev, int config)
+ 	req->config = config;
+ 	INIT_WORK(&req->work, driver_set_config_work);
+ 
++	spin_lock(&set_config_lock);
++	list_add(&req->node, &set_config_list);
++	spin_unlock(&set_config_lock);
++
+ 	usb_get_dev(udev);
+ 	schedule_work(&req->work);
+ 	return 0;

commit 6fd9086a518d4f14213a32fe6c9ac17fabebbc1e
+Author: Alan Stern 
+Date:   Wed Dec 17 17:20:38 2008 -0500
+
+    USB: automatically enable wakeup for PCI host controllers
+    
+    This patch (as1193b) enables wakeup during initialization for all PCI
+    host controllers, and it removes some code (and comments!) that are no
+    longer needed now that the PCI core automatically initializes wakeup
+    settings for all new devices.
+    
+    The idea is that the bus should initialize wakeup, and the bus glue
+    or controller driver should enable it.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index 99432785f438..507741ed4482 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -128,6 +128,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ 	}
+ 
+ 	pci_set_master(dev);
++	device_set_wakeup_enable(&dev->dev, 1);
+ 
+ 	retval = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED);
+ 	if (retval != 0)
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index 6af47a0937b8..bdc6e86e1f8b 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -219,15 +219,19 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 	/* Serial Bus Release Number is at PCI 0x60 offset */
+ 	pci_read_config_byte(pdev, 0x60, &ehci->sbrn);
+ 
+-	/* Workaround current PCI init glitch:  wakeup bits aren't
+-	 * being set from PCI PM capability.
++	/* Keep this around for a while just in case some EHCI
++	 * implementation uses legacy PCI PM support.  This test
++	 * can be removed on 17 Dec 2009 if the dev_warn() hasn't
++	 * been triggered by then.
+ 	 */
+ 	if (!device_can_wakeup(&pdev->dev)) {
+ 		u16	port_wake;
+ 
+ 		pci_read_config_word(pdev, 0x62, &port_wake);
+-		if (port_wake & 0x0001)
++		if (port_wake & 0x0001) {
++			dev_warn(&pdev->dev, "Enabling legacy PCI PM\n");
+ 			device_init_wakeup(&pdev->dev, 1);
++		}
+ 	}
+ 
+ #ifdef	CONFIG_USB_SUSPEND
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index 8aa3f4556a32..65a9609f4ad6 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -589,13 +589,15 @@ static int ohci_run (struct ohci_hcd *ohci)
+ 		/* also: power/overcurrent flags in roothub.a */
+ 	}
+ 
+-	/* Reset USB nearly "by the book".  RemoteWakeupConnected was
+-	 * saved if boot firmware (BIOS/SMM/...) told us it's connected,
+-	 * or if bus glue did the same (e.g. for PCI add-in cards with
+-	 * PCI PM support).
++	/* Reset USB nearly "by the book".  RemoteWakeupConnected has
++	 * to be checked in case boot firmware (BIOS/SMM/...) has set up
++	 * wakeup in a way the bus isn't aware of (e.g., legacy PCI PM).
++	 * If the bus glue detected wakeup capability then it should
++	 * already be enabled.  Either way, if wakeup should be enabled
++	 * but isn't, we'll enable it now.
+ 	 */
+ 	if ((ohci->hc_control & OHCI_CTRL_RWC) != 0
+-			&& !device_may_wakeup(hcd->self.controller))
++			&& !device_can_wakeup(hcd->self.controller))
+ 		device_init_wakeup(hcd->self.controller, 1);
+ 
+ 	switch (ohci->hc_control & OHCI_CTRL_HCFS) {
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index 8380cc2e961a..8b28ae7865ba 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -355,9 +355,9 @@ static int __devinit ohci_pci_start (struct usb_hcd *hcd)
+ 
+ 		/* RWC may not be set for add-in PCI cards, since boot
+ 		 * firmware probably ignored them.  This transfers PCI
+-		 * PM wakeup capabilities (once the PCI layer is fixed).
++		 * PM wakeup capabilities.
+ 		 */
+-		if (device_may_wakeup(&pdev->dev))
++		if (device_can_wakeup(&pdev->dev))
+ 			ohci->hc_control |= OHCI_CTRL_RWC;
+ 	}
+ #endif /* CONFIG_PM */

commit a0d4922da2e4ccb0973095d8d29f36f6b1b5f703
+Author: Alan Stern 
+Date:   Wed Dec 17 15:06:03 2008 -0500
+
+    USB: fix up suspend and resume for PCI host controllers
+    
+    This patch (as1192) rearranges the USB PCI host controller suspend and
+    resume and resume routines:
+    
+            Use pci_wake_from_d3() for enabling and disabling wakeup,
+            instead of pci_enable_wake().
+    
+            Carry out the actual state change while interrupts are
+            disabled.
+    
+            Change the order of the preparations to agree with the
+            general recommendation for PCI devices, instead of
+            messing around with the wakeup settings while the device
+            is in D3.
+    
+                    In .suspend:
+                            Call the underlying driver to disable IRQ
+                                    generation;
+                            pci_wake_from_d3(device_may_wakeup());
+                            pci_disable_device();
+    
+                    In .suspend_late:
+                            pci_save_state();
+                            pci_set_power_state(D3hot);
+                            (for PPC_PMAC) Disable ASIC clocks
+    
+                    In .resume_early:
+                            (for PPC_PMAC) Enable ASIC clocks
+                            pci_set_power_state(D0);
+                            pci_restore_state();
+    
+                    In .resume:
+                            pci_enable_device();
+                            pci_set_master();
+                            pci_wake_from_d3(0);
+                            Call the underlying driver to reenable IRQ
+                                    generation
+    
+            Add the necessary .suspend_late and .resume_early method
+            pointers to the PCI host controller drivers.
+    
+    Signed-off-by: Alan Stern 
+    CC: Rafael J. Wysocki 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index 5b87ae7f0a6a..99432785f438 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -191,17 +191,15 @@ EXPORT_SYMBOL_GPL(usb_hcd_pci_remove);
+ /**
+  * usb_hcd_pci_suspend - power management suspend of a PCI-based HCD
+  * @dev: USB Host Controller being suspended
+- * @message: semantics in flux
++ * @message: Power Management message describing this state transition
+  *
+- * Store this function in the HCD's struct pci_driver as suspend().
++ * Store this function in the HCD's struct pci_driver as .suspend.
+  */
+ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message)
+ {
+-	struct usb_hcd		*hcd;
++	struct usb_hcd		*hcd = pci_get_drvdata(dev);
+ 	int			retval = 0;
+-	int			has_pci_pm;
+-
+-	hcd = pci_get_drvdata(dev);
++	int			wake, w;
+ 
+ 	/* Root hub suspend should have stopped all downstream traffic,
+ 	 * and all bus master traffic.  And done so for both the interface
+@@ -212,8 +210,15 @@ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message)
+ 	 * otherwise the swsusp will save (and restore) garbage state.
+ 	 */
+ 	if (!(hcd->state == HC_STATE_SUSPENDED ||
+-			hcd->state == HC_STATE_HALT))
+-		return -EBUSY;
++			hcd->state == HC_STATE_HALT)) {
++		dev_warn(&dev->dev, "Root hub is not suspended\n");
++		retval = -EBUSY;
++		goto done;
++	}
++
++	/* We might already be suspended (runtime PM -- not yet written) */
++	if (dev->current_state != PCI_D0)
++		goto done;
+ 
+ 	if (hcd->driver->pci_suspend) {
+ 		retval = hcd->driver->pci_suspend(hcd, message);
+@@ -221,49 +226,60 @@ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message)
+ 		if (retval)
+ 			goto done;
+ 	}
+-	synchronize_irq(dev->irq);
+ 
+-	/* FIXME until the generic PM interfaces change a lot more, this
+-	 * can't use PCI D1 and D2 states.  For example, the confusion
+-	 * between messages and states will need to vanish, and messages
+-	 * will need to provide a target system state again.
+-	 *
+-	 * It'll be important to learn characteristics of the target state,
+-	 * especially on embedded hardware where the HCD will often be in
+-	 * charge of an external VBUS power supply and one or more clocks.
+-	 * Some target system states will leave them active; others won't.
+-	 * (With PCI, that's often handled by platform BIOS code.)
+-	 */
++	synchronize_irq(dev->irq);
+ 
+-	/* even when the PCI layer rejects some of the PCI calls
+-	 * below, HCs can try global suspend and reduce DMA traffic.
+-	 * PM-sensitive HCDs may already have done this.
++	/* Don't fail on error to enable wakeup.  We rely on pci code
++	 * to reject requests the hardware can't implement, rather
++	 * than coding the same thing.
+ 	 */
+-	has_pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM);
++	wake = (hcd->state == HC_STATE_SUSPENDED &&
++			device_may_wakeup(&dev->dev));
++	w = pci_wake_from_d3(dev, wake);
++	if (w < 0)
++		wake = w;
++	dev_dbg(&dev->dev, "wakeup: %d\n", wake);
+ 
+ 	/* Downstream ports from this root hub should already be quiesced, so
+ 	 * there will be no DMA activity.  Now we can shut down the upstream
+ 	 * link (except maybe for PME# resume signaling) and enter some PCI
+ 	 * low power state, if the hardware allows.
+ 	 */
+-	if (hcd->state == HC_STATE_SUSPENDED) {
++	pci_disable_device(dev);
++ done:
++	return retval;
++}
++EXPORT_SYMBOL_GPL(usb_hcd_pci_suspend);
+ 
+-		/* no DMA or IRQs except when HC is active */
+-		if (dev->current_state == PCI_D0) {
+-			pci_save_state(dev);
+-			pci_disable_device(dev);
+-		}
++/**
++ * usb_hcd_pci_suspend_late - suspend a PCI-based HCD after IRQs are disabled
++ * @dev: USB Host Controller being suspended
++ * @message: Power Management message describing this state transition
++ *
++ * Store this function in the HCD's struct pci_driver as .suspend_late.
++ */
++int usb_hcd_pci_suspend_late(struct pci_dev *dev, pm_message_t message)
++{
++	int			retval = 0;
++	int			has_pci_pm;
+ 
+-		if (message.event == PM_EVENT_FREEZE ||
+-				message.event == PM_EVENT_PRETHAW) {
+-			dev_dbg(hcd->self.controller, "--> no state change\n");
+-			goto done;
+-		}
++	/* We might already be suspended (runtime PM -- not yet written) */
++	if (dev->current_state != PCI_D0)
++		goto done;
+ 
+-		if (!has_pci_pm) {
+-			dev_dbg(hcd->self.controller, "--> PCI D0/legacy\n");
+-			goto done;
+-		}
++	pci_save_state(dev);
++
++	/* Don't change state if we don't need to */
++	if (message.event == PM_EVENT_FREEZE ||
++			message.event == PM_EVENT_PRETHAW) {
++		dev_dbg(&dev->dev, "--> no state change\n");
++		goto done;
++	}
++
++	has_pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM);
++	if (!has_pci_pm) {
++		dev_dbg(&dev->dev, "--> PCI D0 legacy\n");
++	} else {
+ 
+ 		/* NOTE:  dev->current_state becomes nonzero only here, and
+ 		 * only for devices that support PCI PM.  Also, exiting
+@@ -273,35 +289,16 @@ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message)
+ 		retval = pci_set_power_state(dev, PCI_D3hot);
+ 		suspend_report_result(pci_set_power_state, retval);
+ 		if (retval == 0) {
+-			int wake = device_can_wakeup(&hcd->self.root_hub->dev);
+-
+-			wake = wake && device_may_wakeup(hcd->self.controller);
+-
+-			dev_dbg(hcd->self.controller, "--> PCI D3%s\n",
+-					wake ? "/wakeup" : "");
+-
+-			/* Ignore these return values.  We rely on pci code to
+-			 * reject requests the hardware can't implement, rather
+-			 * than coding the same thing.
+-			 */
+-			(void) pci_enable_wake(dev, PCI_D3hot, wake);
+-			(void) pci_enable_wake(dev, PCI_D3cold, wake);
++			dev_dbg(&dev->dev, "--> PCI D3\n");
+ 		} else {
+ 			dev_dbg(&dev->dev, "PCI D3 suspend fail, %d\n",
+ 					retval);
+-			(void) usb_hcd_pci_resume(dev);
++			pci_restore_state(dev);
+ 		}
+-
+-	} else if (hcd->state != HC_STATE_HALT) {
+-		dev_dbg(hcd->self.controller, "hcd state %d; not suspended\n",
+-			hcd->state);
+-		WARN_ON(1);
+-		retval = -EINVAL;
+ 	}
+ 
+-done:
+-	if (retval == 0) {
+ #ifdef CONFIG_PPC_PMAC
++	if (retval == 0) {
+ 		/* Disable ASIC clocks for USB */
+ 		if (machine_is(powermac)) {
+ 			struct device_node	*of_node;
+@@ -311,30 +308,24 @@ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message)
+ 				pmac_call_feature(PMAC_FTR_USB_ENABLE,
+ 							of_node, 0, 0);
+ 		}
+-#endif
+ 	}
++#endif
+ 
++ done:
+ 	return retval;
+ }
+-EXPORT_SYMBOL_GPL(usb_hcd_pci_suspend);
++EXPORT_SYMBOL_GPL(usb_hcd_pci_suspend_late);
+ 
+ /**
+- * usb_hcd_pci_resume - power management resume of a PCI-based HCD
++ * usb_hcd_pci_resume_early - resume a PCI-based HCD before IRQs are enabled
+  * @dev: USB Host Controller being resumed
+  *
+- * Store this function in the HCD's struct pci_driver as resume().
++ * Store this function in the HCD's struct pci_driver as .resume_early.
+  */
+-int usb_hcd_pci_resume(struct pci_dev *dev)
++int usb_hcd_pci_resume_early(struct pci_dev *dev)
+ {
+-	struct usb_hcd		*hcd;
+-	int			retval;
+-
+-	hcd = pci_get_drvdata(dev);
+-	if (hcd->state != HC_STATE_SUSPENDED) {
+-		dev_dbg(hcd->self.controller,
+-				"can't resume, not suspended!\n");
+-		return 0;
+-	}
++	int		retval = 0;
++	pci_power_t	state = dev->current_state;
+ 
+ #ifdef CONFIG_PPC_PMAC
+ 	/* Reenable ASIC clocks for USB */
+@@ -352,7 +343,7 @@ int usb_hcd_pci_resume(struct pci_dev *dev)
+ 	 * calls "standby", "suspend to RAM", and so on).  There are also
+ 	 * dirty cases when swsusp fakes a suspend in "shutdown" mode.
+ 	 */
+-	if (dev->current_state != PCI_D0) {
++	if (state != PCI_D0) {
+ #ifdef	DEBUG
+ 		int	pci_pm;
+ 		u16	pmcr;
+@@ -364,8 +355,7 @@ int usb_hcd_pci_resume(struct pci_dev *dev)
+ 			/* Clean case:  power to USB and to HC registers was
+ 			 * maintained; remote wakeup is easy.
+ 			 */
+-			dev_dbg(hcd->self.controller, "resume from PCI D%d\n",
+-					pmcr);
++			dev_dbg(&dev->dev, "resume from PCI D%d\n", pmcr);
+ 		} else {
+ 			/* Clean:  HC lost Vcc power, D0 uninitialized
+ 			 *   + Vaux may have preserved port and transceiver
+@@ -376,32 +366,55 @@ int usb_hcd_pci_resume(struct pci_dev *dev)
+ 			 *   + after BIOS init
+ 			 *   + after Linux init (HCD statically linked)
+ 			 */
+-			dev_dbg(hcd->self.controller,
+-				"PCI D0, from previous PCI D%d\n",
+-				dev->current_state);
++			dev_dbg(&dev->dev, "resume from previous PCI D%d\n",
++					state);
+ 		}
+ #endif
+-		/* yes, ignore these results too... */
+-		(void) pci_enable_wake(dev, dev->current_state, 0);
+-		(void) pci_enable_wake(dev, PCI_D3cold, 0);
++
++		retval = pci_set_power_state(dev, PCI_D0);
+ 	} else {
+ 		/* Same basic cases: clean (powered/not), dirty */
+-		dev_dbg(hcd->self.controller, "PCI legacy resume\n");
++		dev_dbg(&dev->dev, "PCI legacy resume\n");
++	}
++
++	if (retval < 0)
++		dev_err(&dev->dev, "can't resume: %d\n", retval);
++	else
++		pci_restore_state(dev);
++
++	return retval;
++}
++EXPORT_SYMBOL_GPL(usb_hcd_pci_resume_early);
++
++/**
++ * usb_hcd_pci_resume - power management resume of a PCI-based HCD
++ * @dev: USB Host Controller being resumed
++ *
++ * Store this function in the HCD's struct pci_driver as .resume.
++ */
++int usb_hcd_pci_resume(struct pci_dev *dev)
++{
++	struct usb_hcd		*hcd;
++	int			retval;
++
++	hcd = pci_get_drvdata(dev);
++	if (hcd->state != HC_STATE_SUSPENDED) {
++		dev_dbg(hcd->self.controller,
++				"can't resume, not suspended!\n");
++		return 0;
+ 	}
+ 
+-	/* NOTE:  the PCI API itself is asymmetric here.  We don't need to
+-	 * pci_set_power_state(PCI_D0) since that's part of re-enabling;
+-	 * but that won't re-enable bus mastering.  Yet pci_disable_device()
+-	 * explicitly disables bus mastering...
+-	 */
+ 	retval = pci_enable_device(dev);
+ 	if (retval < 0) {
+-		dev_err(hcd->self.controller,
+-			"can't re-enable after resume, %d!\n", retval);
++		dev_err(&dev->dev, "can't re-enable after resume, %d!\n",
++				retval);
+ 		return retval;
+ 	}
++
+ 	pci_set_master(dev);
+-	pci_restore_state(dev);
++
++	/* yes, ignore this result too... */
++	(void) pci_wake_from_d3(dev, 0);
+ 
+ 	clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+ 
+@@ -413,7 +426,6 @@ int usb_hcd_pci_resume(struct pci_dev *dev)
+ 			usb_hc_died(hcd);
+ 		}
+ 	}
+-
+ 	return retval;
+ }
+ EXPORT_SYMBOL_GPL(usb_hcd_pci_resume);
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index aa5da82d9071..572d2cf46e8d 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -256,7 +256,9 @@ extern int usb_hcd_pci_probe(struct pci_dev *dev,
+ extern void usb_hcd_pci_remove(struct pci_dev *dev);
+ 
+ #ifdef CONFIG_PM
+-extern int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t state);
++extern int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t msg);
++extern int usb_hcd_pci_suspend_late(struct pci_dev *dev, pm_message_t msg);
++extern int usb_hcd_pci_resume_early(struct pci_dev *dev);
+ extern int usb_hcd_pci_resume(struct pci_dev *dev);
+ #endif /* CONFIG_PM */
+ 
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index 36864f958444..6af47a0937b8 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -428,6 +428,8 @@ static struct pci_driver ehci_pci_driver = {
+ 
+ #ifdef	CONFIG_PM
+ 	.suspend =	usb_hcd_pci_suspend,
++	.suspend_late =	usb_hcd_pci_suspend_late,
++	.resume_early =	usb_hcd_pci_resume_early,
+ 	.resume =	usb_hcd_pci_resume,
+ #endif
+ 	.shutdown = 	usb_hcd_pci_shutdown,
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index a9c2ae36c7ad..8380cc2e961a 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -487,6 +487,8 @@ static struct pci_driver ohci_pci_driver = {
+ 
+ #ifdef	CONFIG_PM
+ 	.suspend =	usb_hcd_pci_suspend,
++	.suspend_late =	usb_hcd_pci_suspend_late,
++	.resume_early =	usb_hcd_pci_resume_early,
+ 	.resume =	usb_hcd_pci_resume,
+ #endif
+ 
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index cf5e4cf7ea42..4e221060f58c 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -942,6 +942,8 @@ static struct pci_driver uhci_pci_driver = {
+ 
+ #ifdef	CONFIG_PM
+ 	.suspend =	usb_hcd_pci_suspend,
++	.suspend_late =	usb_hcd_pci_suspend_late,
++	.resume_early =	usb_hcd_pci_resume_early,
+ 	.resume =	usb_hcd_pci_resume,
+ #endif	/* PM */
+ };

commit a81a81a25d3ecdab777abca87c5ddf484056103d
+Author: Alan Stern 
+Date:   Thu Dec 18 16:41:49 2008 -0500
+
+    USB: storage: set CAPACITY_HEURISTICS flag for bad vendors
+    
+    This patch (as1194) makes usb-storage set the CAPACITY_HEURISTICS flag
+    for all devices made by Nokia, Nikon, or Motorola.  These companies
+    seem to include the READ CAPACITY bug in all of their devices.
+    
+    Since cell phones and digital cameras rely on flash storage, which
+    always has an even number of sectors, setting CAPACITY_HEURISTICS
+    shouldn't cause any problems.  Not even if the companies wise up and
+    start making devices without the bug.
+    
+    A large number of unusual_devs entries are now unnecessary, so the
+    patch removes them.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index 8d78084abf9f..2a42b862aa9f 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -59,6 +59,13 @@
+ #include "transport.h"
+ #include "protocol.h"
+ 
++/* Vendor IDs for companies that seem to include the READ CAPACITY bug
++ * in all their devices
++ */
++#define VENDOR_ID_NOKIA		0x0421
++#define VENDOR_ID_NIKON		0x04b0
++#define VENDOR_ID_MOTOROLA	0x22b8
++
+ /***********************************************************************
+  * Host functions 
+  ***********************************************************************/
+@@ -142,6 +149,22 @@ static int slave_configure(struct scsi_device *sdev)
+ 	 * settings can't be overridden via the scsi devinfo mechanism. */
+ 	if (sdev->type == TYPE_DISK) {
+ 
++		/* Some vendors seem to put the READ CAPACITY bug into
++		 * all their devices -- primarily makers of cell phones
++		 * and digital cameras.  Since these devices always use
++		 * flash media and can be expected to have an even number
++		 * of sectors, we will always enable the CAPACITY_HEURISTICS
++		 * flag unless told otherwise. */
++		switch (le16_to_cpu(us->pusb_dev->descriptor.idVendor)) {
++		case VENDOR_ID_NOKIA:
++		case VENDOR_ID_NIKON:
++		case VENDOR_ID_MOTOROLA:
++			if (!(us->fflags & (US_FL_FIX_CAPACITY |
++					US_FL_CAPACITY_OK)))
++				us->fflags |= US_FL_CAPACITY_HEURISTICS;
++			break;
++		}
++
+ 		/* Disk-type devices use MODE SENSE(6) if the protocol
+ 		 * (SubClass) is Transparent SCSI, otherwise they use
+ 		 * MODE SENSE(10). */
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 035bbc5d8231..a7f9513fa19d 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -174,42 +174,6 @@ UNUSUAL_DEV(  0x0421, 0x0019, 0x0592, 0x0592,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_MAX_SECTORS_64 ),
+ 
+-/* Reported by Filip Joelsson  */
+-UNUSUAL_DEV(  0x0421, 0x005d, 0x0001, 0x0600,
+-		"Nokia",
+-		"Nokia 3110c",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_FIX_CAPACITY ),
+-
+-/* Reported by Ozan Sener  */
+-UNUSUAL_DEV(  0x0421, 0x0060, 0x0551, 0x0551,
+-		"Nokia",
+-		"3500c",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_FIX_CAPACITY ),
+-
+-/* Reported by CSECSY Laszlo  */
+-UNUSUAL_DEV(  0x0421, 0x0063, 0x0001, 0x0601,
+-		"Nokia",
+-		"Nokia 3109c",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_FIX_CAPACITY ),
+-
+-/* Patch for Nokia 5310 capacity */
+-UNUSUAL_DEV(  0x0421, 0x006a, 0x0000, 0x0701,
+-		"Nokia",
+-		"5310",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_FIX_CAPACITY ),
+-
+-/* Submitted by Ricky Wong Yung Fei  */
+-/* Nokia 7610 Supernova - Too many sectors reported in usb storage mode */
+-UNUSUAL_DEV(  0x0421, 0x00f5, 0x0000, 0x0470,
+-		"Nokia",
+-		"7610 Supernova",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_FIX_CAPACITY ),
+-
+ /* Reported by Mario Rettig  */
+ UNUSUAL_DEV(  0x0421, 0x042e, 0x0100, 0x0100,
+ 		"Nokia",
+@@ -275,27 +239,6 @@ UNUSUAL_DEV(  0x0421, 0x0495, 0x0370, 0x0370,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_MAX_SECTORS_64 ),
+ 
+-/* Reported by Cedric Godin  */
+-UNUSUAL_DEV(  0x0421, 0x04b9, 0x0500, 0x0551,
+-		"Nokia",
+-		"5300",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_FIX_CAPACITY ),
+-
+-/* Reported by Paulo Fessel  */
+-UNUSUAL_DEV(  0x0421, 0x04bd, 0x0000, 0x9999,
+-		"Nokia",
+-		"5200",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_FIX_CAPACITY ),
+-
+-/* Reported by Richard Nauber  */
+-UNUSUAL_DEV(  0x0421, 0x04fa, 0x0550, 0x0660,
+-		"Nokia",
+-		"6300",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_FIX_CAPACITY ),
+-
+ /* Reported by Olaf Hering  from novell bug #105878 */
+ UNUSUAL_DEV(  0x0424, 0x0fdc, 0x0210, 0x0210,
+ 		"SMSC",
+@@ -425,83 +368,6 @@ UNUSUAL_DEV(  0x04b0, 0x0301, 0x0010, 0x0010,
+ 		US_SC_DEVICE, US_PR_DEVICE,NULL,
+ 		US_FL_NOT_LOCKABLE ),
+ 
+-/* Reported by Stefan de Konink  */
+-UNUSUAL_DEV(  0x04b0, 0x0401, 0x0200, 0x0200,
+-		"NIKON",
+-		"NIKON DSC D100",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_FIX_CAPACITY),
+-
+-/* Reported by Tobias Kunze Briseno  */
+-UNUSUAL_DEV(  0x04b0, 0x0403, 0x0200, 0x0200,
+-		"NIKON",
+-		"NIKON DSC D2H",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_FIX_CAPACITY),
+-
+-/* Reported by Milinevsky Dmitry  */
+-UNUSUAL_DEV(  0x04b0, 0x0409, 0x0100, 0x0100,
+-		"NIKON",
+-		"NIKON DSC D50",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_FIX_CAPACITY),
+-
+-/* Reported by Andreas Bockhold  */
+-UNUSUAL_DEV(  0x04b0, 0x0405, 0x0100, 0x0100,
+-		"NIKON",
+-		"NIKON DSC D70",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_FIX_CAPACITY),
+-
+-/* Reported by Jamie Kitson  */
+-UNUSUAL_DEV(  0x04b0, 0x040d, 0x0100, 0x0100,
+-		"NIKON",
+-		"NIKON DSC D70s",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_FIX_CAPACITY),
+-
+-/* Reported by Graber and Mike Pagano  */
+-UNUSUAL_DEV(  0x04b0, 0x040f, 0x0100, 0x0200,
+-		"NIKON",
+-		"NIKON DSC D200",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_FIX_CAPACITY),
+-
+-/* Reported by Emil Larsson  */
+-UNUSUAL_DEV(  0x04b0, 0x0411, 0x0100, 0x0111,
+-		"NIKON",
+-		"NIKON DSC D80",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_FIX_CAPACITY),
+-
+-/* Reported by Ortwin Glueck  */
+-UNUSUAL_DEV(  0x04b0, 0x0413, 0x0110, 0x0111,
+-		"NIKON",
+-		"NIKON DSC D40",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_FIX_CAPACITY),
+-
+-/* Reported by Paul Check  */
+-UNUSUAL_DEV(  0x04b0, 0x0415, 0x0100, 0x0100,
+-		"NIKON",
+-		"NIKON DSC D2Xs",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_FIX_CAPACITY),
+-
+-/* Reported by Shan Destromp (shansan@gmail.com) */
+-UNUSUAL_DEV(  0x04b0, 0x0417, 0x0100, 0x0100,
+-		"NIKON",
+-		"NIKON DSC D40X",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_FIX_CAPACITY),
+-
+-/* Reported by paul ready  */
+-UNUSUAL_DEV(  0x04b0, 0x0419, 0x0100, 0x0200,
+-		"NIKON",
+-		"NIKON DSC D300",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_FIX_CAPACITY),
+-
+ /* Reported by Doug Maxey (dwm@austin.ibm.com) */
+ UNUSUAL_DEV(  0x04b3, 0x4001, 0x0110, 0x0110,
+ 		"IBM",
+@@ -2184,27 +2050,6 @@ UNUSUAL_DEV(  0x22b8, 0x3010, 0x0001, 0x0001,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ),
+ 
+-/*
+- * Patch by Pete Zaitcev 
+- * Report by Mark Patton. Red Hat bz#208928.
+- * Added support for rev 0x0002 (Motorola ROKR W5)
+- * by Javier Smaldone 
+- */
+-UNUSUAL_DEV(  0x22b8, 0x4810, 0x0001, 0x0002,
+-		"Motorola",
+-		"RAZR V3i/ROKR W5",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_FIX_CAPACITY),
+-
+-/*
+- * Patch by Jost Diederichs 
+- */
+-UNUSUAL_DEV(0x22b8, 0x6410, 0x0001, 0x9999,
+-		"Motorola Inc.",
+-		"Motorola Phone (RAZRV3xx)",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_FIX_CAPACITY),
+-
+ /*
+  * Patch by Constantin Baranov 
+  * Report by Andreas Koenecke.

commit c838ea4626d6e982489ff519f9ecf5e1649ca90b
+Author: Alan Stern 
+Date:   Mon Dec 15 10:40:06 2008 -0500
+
+    USB: storage: make the "quirks=" module parameter writable
+    
+    This patch (as1190) makes usb-storage's "quirks=" module parameter
+    writable, so that users can add entries for their devices at runtime
+    with no need to reboot or reload usb-storage.
+    
+    New codes are added for the SANE_SENSE, CAPACITY_HEURISTICS, and
+    CAPACITY_OK flags.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
+index 8eb6e35405cd..a58fc8b73398 100644
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -2396,14 +2396,21 @@ and is between 256 and 4096 characters. It is defined in the file
+ 			and Product ID values (4-digit hex numbers) and
+ 			Flags is a set of characters, each corresponding
+ 			to a common usb-storage quirk flag as follows:
++				a = SANE_SENSE (collect more than 18 bytes
++					of sense data);
+ 				c = FIX_CAPACITY (decrease the reported
+ 					device capacity by one sector);
++				h = CAPACITY_HEURISTICS (decrease the
++					reported device capacity by one
++					sector if the number is odd);
+ 				i = IGNORE_DEVICE (don't bind to this
+ 					device);
+ 				l = NOT_LOCKABLE (don't try to lock and
+ 					unlock ejectable media);
+ 				m = MAX_SECTORS_64 (don't transfer more
+ 					than 64 sectors = 32 KB at a time);
++				o = CAPACITY_OK (accept the capacity
++					reported by the device);
+ 				r = IGNORE_RESIDUE (the device reports
+ 					bogus residue values);
+ 				s = SINGLE_LUN (the device has only one
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 80e234bf4e50..4becf495ca2d 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -111,16 +111,10 @@ static unsigned int delay_use = 5;
+ module_param(delay_use, uint, S_IRUGO | S_IWUSR);
+ MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device");
+ 
+-static char *quirks;
+-module_param(quirks, charp, S_IRUGO);
++static char quirks[128];
++module_param_string(quirks, quirks, sizeof(quirks), S_IRUGO | S_IWUSR);
+ MODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks");
+ 
+-struct quirks_entry {
+-	u16	vid, pid;
+-	u32	fflags;
+-};
+-static struct quirks_entry *quirks_list, *quirks_end;
+-
+ 
+ /*
+  * The entries in this table correspond, line for line,
+@@ -481,28 +475,80 @@ static int associate_dev(struct us_data *us, struct usb_interface *intf)
+ 	return 0;
+ }
+ 
++/* Works only for digits and letters, but small and fast */
++#define TOLOWER(x) ((x) | 0x20)
++
+ /* Adjust device flags based on the "quirks=" module parameter */
+ static void adjust_quirks(struct us_data *us)
+ {
+-	u16 vid, pid;
+-	struct quirks_entry *q;
+-	unsigned int mask = (US_FL_FIX_CAPACITY | US_FL_IGNORE_DEVICE |
++	char *p;
++	u16 vid = le16_to_cpu(us->pusb_dev->descriptor.idVendor);
++	u16 pid = le16_to_cpu(us->pusb_dev->descriptor.idProduct);
++	unsigned f = 0;
++	unsigned int mask = (US_FL_SANE_SENSE | US_FL_FIX_CAPACITY |
++			US_FL_CAPACITY_HEURISTICS | US_FL_IGNORE_DEVICE |
+ 			US_FL_NOT_LOCKABLE | US_FL_MAX_SECTORS_64 |
+-			US_FL_IGNORE_RESIDUE | US_FL_SINGLE_LUN |
+-			US_FL_NO_WP_DETECT);
+-
+-	vid = le16_to_cpu(us->pusb_dev->descriptor.idVendor);
+-	pid = le16_to_cpu(us->pusb_dev->descriptor.idProduct);
+-
+-	for (q = quirks_list; q != quirks_end; ++q) {
+-		if (q->vid == vid && q->pid == pid) {
+-			us->fflags = (us->fflags & ~mask) | q->fflags;
+-			dev_info(&us->pusb_intf->dev, "Quirks match for "
+-					"vid %04x pid %04x: %x\n",
+-					vid, pid, q->fflags);
++			US_FL_CAPACITY_OK | US_FL_IGNORE_RESIDUE |
++			US_FL_SINGLE_LUN | US_FL_NO_WP_DETECT);
++
++	p = quirks;
++	while (*p) {
++		/* Each entry consists of VID:PID:flags */
++		if (vid == simple_strtoul(p, &p, 16) &&
++				*p == ':' &&
++				pid == simple_strtoul(p+1, &p, 16) &&
++				*p == ':')
+ 			break;
++
++		/* Move forward to the next entry */
++		while (*p) {
++			if (*p++ == ',')
++				break;
+ 		}
+ 	}
++	if (!*p)	/* No match */
++		return;
++
++	/* Collect the flags */
++	while (*++p && *p != ',') {
++		switch (TOLOWER(*p)) {
++		case 'a':
++			f |= US_FL_SANE_SENSE;
++			break;
++		case 'c':
++			f |= US_FL_FIX_CAPACITY;
++			break;
++		case 'h':
++			f |= US_FL_CAPACITY_HEURISTICS;
++			break;
++		case 'i':
++			f |= US_FL_IGNORE_DEVICE;
++			break;
++		case 'l':
++			f |= US_FL_NOT_LOCKABLE;
++			break;
++		case 'm':
++			f |= US_FL_MAX_SECTORS_64;
++			break;
++		case 'o':
++			f |= US_FL_CAPACITY_OK;
++			break;
++		case 'r':
++			f |= US_FL_IGNORE_RESIDUE;
++			break;
++		case 's':
++			f |= US_FL_SINGLE_LUN;
++			break;
++		case 'w':
++			f |= US_FL_NO_WP_DETECT;
++			break;
++		/* Ignore unrecognized flag characters */
++		}
++	}
++	us->fflags = (us->fflags & ~mask) | f;
++	dev_info(&us->pusb_intf->dev, "Quirks match for "
++			"vid %04x pid %04x: %x\n",
++			vid, pid, f);
+ }
+ 
+ /* Find an unusual_dev descriptor (always succeeds in the current code) */
+@@ -1092,88 +1138,11 @@ static struct usb_driver usb_storage_driver = {
+ 	.soft_unbind =	1,
+ };
+ 
+-/* Works only for digits and letters, but small and fast */
+-#define TOLOWER(x) ((x) | 0x20)
+-
+-static void __init parse_quirks(void)
+-{
+-	int n, i;
+-	char *p;
+-
+-	if (!quirks)
+-		return;
+-
+-	/* Count the ':' characters to get 2 * the number of entries */
+-	n = 0;
+-	for (p = quirks; *p; ++p) {
+-		if (*p == ':')
+-			++n;
+-	}
+-	n /= 2;
+-	if (n == 0)
+-		return;		/* Don't allocate 0 bytes */
+-
+-	quirks_list = kmalloc(n * sizeof(*quirks_list), GFP_KERNEL);
+-	if (!quirks_list)
+-		return;
+-
+-	p = quirks;
+-	quirks_end = quirks_list;
+-	for (i = 0; i < n && *p; ++i) {
+-		unsigned f = 0;
+-
+-		/* Each entry consists of VID:PID:flags */
+-		quirks_end->vid = simple_strtoul(p, &p, 16);
+-		if (*p != ':')
+-			goto skip_to_next;
+-		quirks_end->pid = simple_strtoul(p+1, &p, 16);
+-		if (*p != ':')
+-			goto skip_to_next;
+-
+-		while (*++p && *p != ',') {
+-			switch (TOLOWER(*p)) {
+-			case 'c':
+-				f |= US_FL_FIX_CAPACITY;
+-				break;
+-			case 'i':
+-				f |= US_FL_IGNORE_DEVICE;
+-				break;
+-			case 'l':
+-				f |= US_FL_NOT_LOCKABLE;
+-				break;
+-			case 'm':
+-				f |= US_FL_MAX_SECTORS_64;
+-				break;
+-			case 'r':
+-				f |= US_FL_IGNORE_RESIDUE;
+-				break;
+-			case 's':
+-				f |= US_FL_SINGLE_LUN;
+-				break;
+-			case 'w':
+-				f |= US_FL_NO_WP_DETECT;
+-				break;
+-			/* Ignore unrecognized flag characters */
+-			}
+-		}
+-		quirks_end->fflags = f;
+-		++quirks_end;
+-
+- skip_to_next:
+-		/* Entries are separated by commas */
+-		while (*p) {
+-			if (*p++ == ',')
+-				break;
+-		}
+-	} /* for (i = 0; ...) */
+-}
+-
+ static int __init usb_stor_init(void)
+ {
+ 	int retval;
+ 
+ 	printk(KERN_INFO "Initializing USB Mass Storage driver...\n");
+-	parse_quirks();
+ 
+ 	/* register the driver, return usb_register return code if error */
+ 	retval = usb_register(&usb_storage_driver);

commit 25ff1c316f6a763f1eefe7f8984b2d8c03888432
+Author: Alan Stern 
+Date:   Mon Dec 15 12:43:41 2008 -0500
+
+    USB: storage: add last-sector hacks
+    
+    This patch (as1189b) adds some hacks to usb-storage for dealing with
+    the growing problems involving bad capacity values and last-sector
+    accesses:
+    
+            A new flag, US_FL_CAPACITY_OK, is created to indicate that
+            the device is known to report its capacity correctly.  An
+            unusual_devs entry for Linux's own File-backed Storage Gadget
+            is added with this flag set, since g_file_storage always
+            reports the correct capacity and since the capacity need
+            not be even (it is determined by the size of the backing
+            file).
+    
+            An entry in unusual_devs.h which has only the CAPACITY_OK
+            flag set shouldn't prejudice libusual, since the device will
+            work perfectly well with either usb-storage or ub.  So a
+            new macro, COMPLIANT_DEV, is added to let libusual know
+            about these entries.
+    
+            When a last-sector access succeeds and the total number of
+            sectors is odd (the unexpected case, in which guessing that
+            the number is even might cause trouble), a WARN is triggered.
+            The kerneloops.org project will collect these warnings,
+            allowing us to add CAPACITY_OK flags for the devices in
+            question before implementing the default-to-even heuristic.
+            If users want to prevent the stack dump produced by the WARN,
+            they can disable the hack by adding an unusual_devs entry
+            for their device with the CAPACITY_OK flag.
+    
+            When a last-sector access fails three times in a row and
+            neither the FIX_CAPACITY nor the CAPACITY_OK flag is set,
+            we assume the last-sector bug is present.  We replace the
+            existing status and sense data with values that will cause
+            the SCSI core to fail the access immediately rather than
+            retry indefinitely.  This should fix the difficulties
+            people have been having with Nokia phones.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c
+index d617e8ae6b00..f970b27ba308 100644
+--- a/drivers/usb/storage/libusual.c
++++ b/drivers/usb/storage/libusual.c
+@@ -46,6 +46,12 @@ static int usu_probe_thread(void *arg);
+ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \
+   .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+ 
++#define COMPLIANT_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
++		    vendorName, productName, useProtocol, useTransport, \
++		    initFunction, flags) \
++{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
++  .driver_info = (flags) }
++
+ #define USUAL_DEV(useProto, useTrans, useType) \
+ { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
+   .driver_info = ((useType)<<24) }
+@@ -57,6 +63,7 @@ struct usb_device_id storage_usb_ids [] = {
+ 
+ #undef USUAL_DEV
+ #undef UNUSUAL_DEV
++#undef COMPLIANT_DEV
+ 
+ MODULE_DEVICE_TABLE(usb, storage_usb_ids);
+ EXPORT_SYMBOL_GPL(storage_usb_ids);
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index e9d6c196a7ab..8d78084abf9f 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -208,6 +208,14 @@ static int slave_configure(struct scsi_device *sdev)
+ 		 * sector in a larger then 1 sector read, since the performance
+ 		 * impact is negible we set this flag for all USB disks */
+ 		sdev->last_sector_bug = 1;
++
++		/* Enable last-sector hacks for single-target devices using
++		 * the Bulk-only transport, unless we already know the
++		 * capacity will be decremented or is correct. */
++		if (!(us->fflags & (US_FL_FIX_CAPACITY | US_FL_CAPACITY_OK |
++					US_FL_SCM_MULT_TARG)) &&
++				us->protocol == US_PR_BULK)
++			us->use_last_sector_hacks = 1;
+ 	} else {
+ 
+ 		/* Non-disk-type devices don't need to blacklist any pages
+diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+index 9cc30afd6d31..1d5438e6363b 100644
+--- a/drivers/usb/storage/transport.c
++++ b/drivers/usb/storage/transport.c
+@@ -57,6 +57,9 @@
+ #include "scsiglue.h"
+ #include "debug.h"
+ 
++#include 
++#include "../../scsi/sd.h"
++
+ 
+ /***********************************************************************
+  * Data transfer routines
+@@ -511,6 +514,110 @@ int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe,
+  * Transport routines
+  ***********************************************************************/
+ 
++/* There are so many devices that report the capacity incorrectly,
++ * this routine was written to counteract some of the resulting
++ * problems.
++ */
++static void last_sector_hacks(struct us_data *us, struct scsi_cmnd *srb)
++{
++	struct gendisk *disk;
++	struct scsi_disk *sdkp;
++	u32 sector;
++
++	/* To Report "Medium Error: Record Not Found */
++	static unsigned char record_not_found[18] = {
++		[0]	= 0x70,			/* current error */
++		[2]	= MEDIUM_ERROR,		/* = 0x03 */
++		[7]	= 0x0a,			/* additional length */
++		[12]	= 0x14			/* Record Not Found */
++	};
++
++	/* If last-sector problems can't occur, whether because the
++	 * capacity was already decremented or because the device is
++	 * known to report the correct capacity, then we don't need
++	 * to do anything.
++	 */
++	if (!us->use_last_sector_hacks)
++		return;
++
++	/* Was this command a READ(10) or a WRITE(10)? */
++	if (srb->cmnd[0] != READ_10 && srb->cmnd[0] != WRITE_10)
++		goto done;
++
++	/* Did this command access the last sector? */
++	sector = (srb->cmnd[2] << 24) | (srb->cmnd[3] << 16) |
++			(srb->cmnd[4] << 8) | (srb->cmnd[5]);
++	disk = srb->request->rq_disk;
++	if (!disk)
++		goto done;
++	sdkp = scsi_disk(disk);
++	if (!sdkp)
++		goto done;
++	if (sector + 1 != sdkp->capacity)
++		goto done;
++
++	if (srb->result == SAM_STAT_GOOD && scsi_get_resid(srb) == 0) {
++
++		/* The command succeeded.  If the capacity is odd
++		 * (i.e., if the sector number is even) then the
++		 * "always-even" heuristic would be wrong for this
++		 * device.  Issue a WARN() so that the kerneloops.org
++		 * project will be notified and we will then know to
++		 * mark the device with a CAPACITY_OK flag.  Hopefully
++		 * this will occur for only a few devices.
++		 *
++		 * Use the sign of us->last_sector_hacks to tell whether
++		 * the warning has already been issued; we don't need
++		 * more than one warning per device.
++		 */
++		if (!(sector & 1) && us->use_last_sector_hacks > 0) {
++			unsigned vid = le16_to_cpu(
++					us->pusb_dev->descriptor.idVendor);
++			unsigned pid = le16_to_cpu(
++					us->pusb_dev->descriptor.idProduct);
++			unsigned rev = le16_to_cpu(
++					us->pusb_dev->descriptor.bcdDevice);
++
++			WARN(1, "%s: Successful last sector success at %u, "
++					"device %04x:%04x:%04x\n",
++					sdkp->disk->disk_name, sector,
++					vid, pid, rev);
++			us->use_last_sector_hacks = -1;
++		}
++
++	} else {
++		/* The command failed.  Allow up to 3 retries in case this
++		 * is some normal sort of failure.  After that, assume the
++		 * capacity is wrong and we're trying to access the sector
++		 * beyond the end.  Replace the result code and sense data
++		 * with values that will cause the SCSI core to fail the
++		 * command immediately, instead of going into an infinite
++		 * (or even just a very long) retry loop.
++		 */
++		if (++us->last_sector_retries < 3)
++			return;
++		srb->result = SAM_STAT_CHECK_CONDITION;
++		memcpy(srb->sense_buffer, record_not_found,
++				sizeof(record_not_found));
++
++		/* In theory we might want to issue a WARN() here if the
++		 * capacity is even, since it could indicate the device
++		 * has the READ CAPACITY bug _and_ the real capacity is
++		 * odd.  But it could also indicate that the device
++		 * simply can't access its last sector, a failure mode
++		 * which is surprisingly common.  So no warning.
++		 */
++	}
++
++ done:
++	/* Don't reset the retry counter for TEST UNIT READY commands,
++	 * because they get issued after device resets which might be
++	 * caused by a failed last-sector access.
++	 */
++	if (srb->cmnd[0] != TEST_UNIT_READY)
++		us->last_sector_retries = 0;
++}
++
+ /* Invoke the transport and basic error-handling/recovery methods
+  *
+  * This is used by the protocol layers to actually send the message to
+@@ -544,6 +651,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 	/* if the transport provided its own sense data, don't auto-sense */
+ 	if (result == USB_STOR_TRANSPORT_NO_SENSE) {
+ 		srb->result = SAM_STAT_CHECK_CONDITION;
++		last_sector_hacks(us, srb);
+ 		return;
+ 	}
+ 
+@@ -705,6 +813,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 			scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow)
+ 		srb->result = (DID_ERROR << 16) | (SUGGEST_RETRY << 24);
+ 
++	last_sector_hacks(us, srb);
+ 	return;
+ 
+ 	/* Error and abort processing: try to resynchronize with the device
+@@ -732,6 +841,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 		us->transport_reset(us);
+ 	}
+ 	clear_bit(US_FLIDX_RESETTING, &us->dflags);
++	last_sector_hacks(us, srb);
+ }
+ 
+ /* Stop the current URB transfer */
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 0330ed53ec1c..035bbc5d8231 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -27,7 +27,8 @@
+ 
+ /* IMPORTANT NOTE: This file must be included in another file which does
+  * the following thing for it to work:
+- * The macro UNUSUAL_DEV() must be defined before this file is included
++ * The UNUSUAL_DEV, COMPLIANT_DEV, and USUAL_DEV macros must be defined
++ * before this file is included.
+  */
+ 
+ /* If you edit this file, please try to keep it sorted first by VendorID,
+@@ -46,6 +47,12 @@
+  * 
+  */
+ 
++/* Note: If you add an entry only in order to set the CAPACITY_OK flag,
++ * use the COMPLIANT_DEV macro instead of UNUSUAL_DEV.  This is
++ * because such entries mark devices which actually work correctly,
++ * as opposed to devices that do something strangely or wrongly.
++ */
++
+ /* patch submitted by Vivian Bregier 
+  */
+ UNUSUAL_DEV(  0x03eb, 0x2002, 0x0100, 0x0100,
+@@ -704,6 +711,13 @@ UNUSUAL_DEV(  0x0525, 0xa140, 0x0100, 0x0100,
+ 		US_SC_8070, US_PR_DEVICE, NULL,
+ 		US_FL_FIX_INQUIRY ),
+ 
++/* Added by Alan Stern  */
++COMPLIANT_DEV(0x0525, 0xa4a5, 0x0000, 0x9999,
++		"Linux",
++		"File-backed Storage Gadget",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_CAPACITY_OK ),
++
+ /* Yakumo Mega Image 37
+  * Submitted by Stephan Fuhrmann  */
+ UNUSUAL_DEV(  0x052b, 0x1801, 0x0100, 0x0100,
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index ce0b580db5ea..80e234bf4e50 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -134,6 +134,8 @@ static struct quirks_entry *quirks_list, *quirks_end;
+ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \
+   .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+ 
++#define COMPLIANT_DEV	UNUSUAL_DEV
++
+ #define USUAL_DEV(useProto, useTrans, useType) \
+ { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
+   .driver_info = (USB_US_TYPE_STOR<<24) }
+@@ -142,6 +144,7 @@ static struct usb_device_id storage_usb_ids [] = {
+ 
+ #	include "unusual_devs.h"
+ #undef UNUSUAL_DEV
++#undef COMPLIANT_DEV
+ #undef USUAL_DEV
+ 	/* Terminating entry */
+ 	{ }
+@@ -172,6 +175,8 @@ MODULE_DEVICE_TABLE (usb, storage_usb_ids);
+ 	.initFunction = init_function,	\
+ }
+ 
++#define COMPLIANT_DEV	UNUSUAL_DEV
++
+ #define USUAL_DEV(use_protocol, use_transport, use_type) \
+ { \
+ 	.useProtocol = use_protocol,	\
+@@ -181,6 +186,7 @@ MODULE_DEVICE_TABLE (usb, storage_usb_ids);
+ static struct us_unusual_dev us_unusual_dev_list[] = {
+ #	include "unusual_devs.h" 
+ #	undef UNUSUAL_DEV
++#	undef COMPLIANT_DEV
+ #	undef USUAL_DEV
+ 
+ 	/* Terminating entry */
+diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
+index e4674fc715e6..65e674e4be99 100644
+--- a/drivers/usb/storage/usb.h
++++ b/drivers/usb/storage/usb.h
+@@ -154,6 +154,10 @@ struct us_data {
+ #ifdef CONFIG_PM
+ 	pm_hook			suspend_resume_hook;
+ #endif
++
++	/* hacks for READ CAPACITY bug handling */
++	int			use_last_sector_hacks;
++	int			last_sector_retries;
+ };
+ 
+ /* Convert between us_data and the corresponding Scsi_Host */
+diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
+index 998e5cbbf29e..1eea1ab68dc4 100644
+--- a/include/linux/usb_usual.h
++++ b/include/linux/usb_usual.h
+@@ -53,8 +53,10 @@
+ 		/* Sets max_sectors to arch min */		\
+ 	US_FLAG(BULK_IGNORE_TAG,0x00004000)			\
+ 		/* Ignore tag mismatch in bulk operations */    \
+-	US_FLAG(SANE_SENSE,     0x00008000)
+-		/* Sane Sense (> 18 bytes) */
++	US_FLAG(SANE_SENSE,     0x00008000)			\
++		/* Sane Sense (> 18 bytes) */			\
++	US_FLAG(CAPACITY_OK,	0x00010000)			\
++		/* READ CAPACITY response is correct */
+ 
+ #define US_FLAG(name, value)	US_FL_##name = value ,
+ enum { US_DO_ALL_FLAGS };

commit 3b23dd6f8a718e5339de4f7d86ce76a078b5f771
+Author: Alan Stern 
+Date:   Fri Dec 5 14:10:34 2008 -0500
+
+    USB: utilize the bus notifiers
+    
+    This patch (as1185) makes usbcore take advantage of the bus
+    notifications sent out by the driver core.  Now we can create all our
+    device and interface attribute files before the device or interface
+    uevent is broadcast.
+    
+    A side effect is that we no longer create the endpoint "pseudo"
+    devices at the same time as a device or interface is registered -- it
+    seems like a bad idea to try registering an endpoint before the
+    registration of its parent is complete.  So the routines for creating
+    and removing endpoint devices have been split out and renamed, and
+    they are called explicitly when needed.  A new bitflag is used for
+    keeping track of whether or not the interface's endpoint devices have
+    been created, since (just as with the interface attributes) they vary
+    with the altsetting and hence can be changed at random times.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Kay Sievers 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
+index 946fae43d622..e1710f260b4f 100644
+--- a/drivers/usb/core/endpoint.c
++++ b/drivers/usb/core/endpoint.c
+@@ -276,7 +276,7 @@ static void ep_device_release(struct device *dev)
+ 	kfree(ep_dev);
+ }
+ 
+-int usb_create_ep_files(struct device *parent,
++int usb_create_ep_devs(struct device *parent,
+ 			struct usb_host_endpoint *endpoint,
+ 			struct usb_device *udev)
+ {
+@@ -340,7 +340,7 @@ int usb_create_ep_files(struct device *parent,
+ 	return retval;
+ }
+ 
+-void usb_remove_ep_files(struct usb_host_endpoint *endpoint)
++void usb_remove_ep_devs(struct usb_host_endpoint *endpoint)
+ {
+ 	struct ep_device *ep_dev = endpoint->ep_dev;
+ 
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 5abdc11be1e5..756b8d9993fc 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1437,17 +1437,12 @@ void usb_disconnect(struct usb_device **pdev)
+ 	usb_disable_device(udev, 0);
+ 	usb_hcd_synchronize_unlinks(udev);
+ 
++	usb_remove_ep_devs(&udev->ep0);
+ 	usb_unlock_device(udev);
+ 
+-	/* Remove the device-specific files from sysfs.  This must be
+-	 * done with udev unlocked, because some of the attribute
+-	 * routines try to acquire the device lock.
+-	 */
+-	usb_remove_sysfs_dev_files(udev);
+-
+ 	/* Unregister the device.  The device driver is responsible
+-	 * for removing the device files from usbfs and sysfs and for
+-	 * de-configuring the device.
++	 * for de-configuring the device and invoking the remove-device
++	 * notifier chain (used by usbfs and possibly others).
+ 	 */
+ 	device_del(&udev->dev);
+ 
+@@ -1654,8 +1649,8 @@ int usb_new_device(struct usb_device *udev)
+ 	announce_device(udev);
+ 
+ 	/* Register the device.  The device driver is responsible
+-	 * for adding the device files to sysfs and for configuring
+-	 * the device.
++	 * for configuring the device and invoking the add-device
++	 * notifier chain (used by usbfs and possibly others).
+ 	 */
+ 	err = device_add(&udev->dev);
+ 	if (err) {
+@@ -1663,8 +1658,7 @@ int usb_new_device(struct usb_device *udev)
+ 		goto fail;
+ 	}
+ 
+-	/* put device-specific files into sysfs */
+-	usb_create_sysfs_dev_files(udev);
++	(void) usb_create_ep_devs(&udev->dev, &udev->ep0, udev);
+ 	return err;
+ 
+ fail:
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index aadf29f09c45..7943901c641c 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1004,6 +1004,34 @@ int usb_clear_halt(struct usb_device *dev, int pipe)
+ }
+ EXPORT_SYMBOL_GPL(usb_clear_halt);
+ 
++static int create_intf_ep_devs(struct usb_interface *intf)
++{
++	struct usb_device *udev = interface_to_usbdev(intf);
++	struct usb_host_interface *alt = intf->cur_altsetting;
++	int i;
++
++	if (intf->ep_devs_created || intf->unregistering)
++		return 0;
++
++	for (i = 0; i < alt->desc.bNumEndpoints; ++i)
++		(void) usb_create_ep_devs(&intf->dev, &alt->endpoint[i], udev);
++	intf->ep_devs_created = 1;
++	return 0;
++}
++
++static void remove_intf_ep_devs(struct usb_interface *intf)
++{
++	struct usb_host_interface *alt = intf->cur_altsetting;
++	int i;
++
++	if (!intf->ep_devs_created)
++		return;
++
++	for (i = 0; i < alt->desc.bNumEndpoints; ++i)
++		usb_remove_ep_devs(&alt->endpoint[i]);
++	intf->ep_devs_created = 0;
++}
++
+ /**
+  * usb_disable_endpoint -- Disable an endpoint by address
+  * @dev: the device whose endpoint is being disabled
+@@ -1092,7 +1120,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
+ 			dev_dbg(&dev->dev, "unregistering interface %s\n",
+ 				dev_name(&interface->dev));
+ 			interface->unregistering = 1;
+-			usb_remove_sysfs_intf_files(interface);
++			remove_intf_ep_devs(interface);
+ 			device_del(&interface->dev);
+ 		}
+ 
+@@ -1235,8 +1263,10 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
+ 	 */
+ 
+ 	/* prevent submissions using previous endpoint settings */
+-	if (iface->cur_altsetting != alt)
++	if (iface->cur_altsetting != alt) {
++		remove_intf_ep_devs(iface);
+ 		usb_remove_sysfs_intf_files(iface);
++	}
+ 	usb_disable_interface(dev, iface);
+ 
+ 	iface->cur_altsetting = alt;
+@@ -1272,9 +1302,10 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
+ 	 * (Likewise, EP0 never "halts" on well designed devices.)
+ 	 */
+ 	usb_enable_interface(dev, iface);
+-	if (device_is_registered(&iface->dev))
++	if (device_is_registered(&iface->dev)) {
+ 		usb_create_sysfs_intf_files(iface);
+-
++		create_intf_ep_devs(iface);
++	}
+ 	return 0;
+ }
+ EXPORT_SYMBOL_GPL(usb_set_interface);
+@@ -1334,7 +1365,6 @@ int usb_reset_configuration(struct usb_device *dev)
+ 		struct usb_interface *intf = config->interface[i];
+ 		struct usb_host_interface *alt;
+ 
+-		usb_remove_sysfs_intf_files(intf);
+ 		alt = usb_altnum_to_altsetting(intf, 0);
+ 
+ 		/* No altsetting 0?  We'll assume the first altsetting.
+@@ -1345,10 +1375,16 @@ int usb_reset_configuration(struct usb_device *dev)
+ 		if (!alt)
+ 			alt = &intf->altsetting[0];
+ 
++		if (alt != intf->cur_altsetting) {
++			remove_intf_ep_devs(intf);
++			usb_remove_sysfs_intf_files(intf);
++		}
+ 		intf->cur_altsetting = alt;
+ 		usb_enable_interface(dev, intf);
+-		if (device_is_registered(&intf->dev))
++		if (device_is_registered(&intf->dev)) {
+ 			usb_create_sysfs_intf_files(intf);
++			create_intf_ep_devs(intf);
++		}
+ 	}
+ 	return 0;
+ }
+@@ -1682,7 +1718,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 				dev_name(&intf->dev), ret);
+ 			continue;
+ 		}
+-		usb_create_sysfs_intf_files(intf);
++		create_intf_ep_devs(intf);
+ 	}
+ 
+ 	usb_autosuspend_device(dev);
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 0f0ccf640114..4cc2456ef3be 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -629,9 +629,6 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
+ 	struct device *dev = &udev->dev;
+ 	int retval;
+ 
+-	/* Unforunately these attributes cannot be created before
+-	 * the uevent is broadcast.
+-	 */
+ 	retval = device_create_bin_file(dev, &dev_bin_attr_descriptors);
+ 	if (retval)
+ 		goto error;
+@@ -643,11 +640,7 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
+ 	retval = add_power_attributes(dev);
+ 	if (retval)
+ 		goto error;
+-
+-	retval = usb_create_ep_files(dev, &udev->ep0, udev);
+-	if (retval)
+-		goto error;
+-	return 0;
++	return retval;
+ error:
+ 	usb_remove_sysfs_dev_files(udev);
+ 	return retval;
+@@ -657,7 +650,6 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)
+ {
+ 	struct device *dev = &udev->dev;
+ 
+-	usb_remove_ep_files(&udev->ep0);
+ 	remove_power_attributes(dev);
+ 	remove_persist_attributes(dev);
+ 	device_remove_bin_file(dev, &dev_bin_attr_descriptors);
+@@ -816,36 +808,24 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf)
+ {
+ 	struct usb_device *udev = interface_to_usbdev(intf);
+ 	struct usb_host_interface *alt = intf->cur_altsetting;
+-	int i;
+ 	int retval;
+ 
+ 	if (intf->sysfs_files_created || intf->unregistering)
+ 		return 0;
+ 
+-	/* The interface string may be present in some altsettings
+-	 * and missing in others.  Hence its attribute cannot be created
+-	 * before the uevent is broadcast.
+-	 */
+ 	if (alt->string == NULL)
+ 		alt->string = usb_cache_string(udev, alt->desc.iInterface);
+ 	if (alt->string)
+ 		retval = device_create_file(&intf->dev, &dev_attr_interface);
+-	for (i = 0; i < alt->desc.bNumEndpoints; ++i)
+-		usb_create_ep_files(&intf->dev, &alt->endpoint[i], udev);
+ 	intf->sysfs_files_created = 1;
+ 	return 0;
+ }
+ 
+ void usb_remove_sysfs_intf_files(struct usb_interface *intf)
+ {
+-	struct usb_host_interface *alt = intf->cur_altsetting;
+-	int i;
+-
+ 	if (!intf->sysfs_files_created)
+ 		return;
+ 
+-	for (i = 0; i < alt->desc.bNumEndpoints; ++i)
+-		usb_remove_ep_files(&alt->endpoint[i]);
+ 	device_remove_file(&intf->dev, &dev_attr_interface);
+ 	intf->sysfs_files_created = 0;
+ }
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 4c98f3975afe..c0821564a3fe 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -970,6 +970,37 @@ int usb_disabled(void)
+ }
+ EXPORT_SYMBOL_GPL(usb_disabled);
+ 
++/*
++ * Notifications of device and interface registration
++ */
++static int usb_bus_notify(struct notifier_block *nb, unsigned long action,
++		void *data)
++{
++	struct device *dev = data;
++
++	switch (action) {
++	case BUS_NOTIFY_ADD_DEVICE:
++		if (dev->type == &usb_device_type)
++			(void) usb_create_sysfs_dev_files(to_usb_device(dev));
++		else if (dev->type == &usb_if_device_type)
++			(void) usb_create_sysfs_intf_files(
++					to_usb_interface(dev));
++		break;
++
++	case BUS_NOTIFY_DEL_DEVICE:
++		if (dev->type == &usb_device_type)
++			usb_remove_sysfs_dev_files(to_usb_device(dev));
++		else if (dev->type == &usb_if_device_type)
++			usb_remove_sysfs_intf_files(to_usb_interface(dev));
++		break;
++	}
++	return 0;
++}
++
++static struct notifier_block usb_bus_nb = {
++	.notifier_call = usb_bus_notify,
++};
++
+ /*
+  * Init
+  */
+@@ -987,6 +1018,9 @@ static int __init usb_init(void)
+ 	retval = bus_register(&usb_bus_type);
+ 	if (retval)
+ 		goto bus_register_failed;
++	retval = bus_register_notifier(&usb_bus_type, &usb_bus_nb);
++	if (retval)
++		goto bus_notifier_failed;
+ 	retval = usb_host_init();
+ 	if (retval)
+ 		goto host_init_failed;
+@@ -1021,6 +1055,8 @@ static int __init usb_init(void)
+ major_init_failed:
+ 	usb_host_cleanup();
+ host_init_failed:
++	bus_unregister_notifier(&usb_bus_type, &usb_bus_nb);
++bus_notifier_failed:
+ 	bus_unregister(&usb_bus_type);
+ bus_register_failed:
+ 	ksuspend_usb_cleanup();
+@@ -1044,6 +1080,7 @@ static void __exit usb_exit(void)
+ 	usb_devio_cleanup();
+ 	usb_hub_cleanup();
+ 	usb_host_cleanup();
++	bus_unregister_notifier(&usb_bus_type, &usb_bus_nb);
+ 	bus_unregister(&usb_bus_type);
+ 	ksuspend_usb_cleanup();
+ }
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 9fb195665fa8..381eae90c3b7 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -6,10 +6,10 @@ extern int usb_create_sysfs_dev_files(struct usb_device *dev);
+ extern void usb_remove_sysfs_dev_files(struct usb_device *dev);
+ extern int usb_create_sysfs_intf_files(struct usb_interface *intf);
+ extern void usb_remove_sysfs_intf_files(struct usb_interface *intf);
+-extern int usb_create_ep_files(struct device *parent,
++extern int usb_create_ep_devs(struct device *parent,
+ 				struct usb_host_endpoint *endpoint,
+ 				struct usb_device *udev);
+-extern void usb_remove_ep_files(struct usb_host_endpoint *endpoint);
++extern void usb_remove_ep_devs(struct usb_host_endpoint *endpoint);
+ 
+ extern void usb_enable_endpoint(struct usb_device *dev,
+ 		struct usb_host_endpoint *ep);
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 74d0b9990c73..e9d63562325a 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -108,6 +108,7 @@ enum usb_interface_condition {
+  *	(in probe()), bound to a driver, or unbinding (in disconnect())
+  * @is_active: flag set when the interface is bound and not suspended.
+  * @sysfs_files_created: sysfs attributes exist
++ * @ep_devs_created: endpoint child pseudo-devices exist
+  * @unregistering: flag set when the interface is being unregistered
+  * @needs_remote_wakeup: flag set when the driver requires remote-wakeup
+  *	capability during autosuspend.
+@@ -169,6 +170,7 @@ struct usb_interface {
+ 	enum usb_interface_condition condition;		/* state of binding */
+ 	unsigned is_active:1;		/* the interface is not suspended */
+ 	unsigned sysfs_files_created:1;	/* the sysfs attributes exist */
++	unsigned ep_devs_created:1;	/* endpoint "devices" exist */
+ 	unsigned unregistering:1;	/* unregistration is in progress */
+ 	unsigned needs_remote_wakeup:1;	/* driver requires remote wakeup */
+ 	unsigned needs_altsetting0:1;	/* switch to altsetting 0 is pending */

commit c20b15fde50c32174af4b48851e5ddadba36330e
+Author: Alan Stern 
+Date:   Mon Dec 1 10:36:15 2008 -0500
+
+    USB: usb-storage: merge DPCM support into SDDR09
+    
+    The DPCM subdriver is a little peculiar, in that it's meant to support
+    devices where LUN 0 is Compact Flash and uses the CB transport whereas
+    LUN 1 is SmartMedia and uses the SDDR09 transport.  Thus DPCM isn't
+    really a transport in itself; it's more like a demultiplexer.
+    
+    Much of the DPCM code is part of the SDDR09 subdriver already, and the
+    remaining part is fairly small.  This patch (as1182) moves that extra
+    piece into sddr09.c, thereby eliminating dpcm.c.  Also eliminated is
+    the Kconfig entry for DPCM support; it is now listed as part of the
+    SDDR09 entry.
+    
+    In order to make sure that the semantics are the same as before, each
+    unusual_devs entry for DPCM is now present twice: once with DPCM
+    support if SDDR09 is configured (as before), and once with the
+    SINGLE_LUN flag and CB support otherwise.
+    
+    Signed-off-by: Alan Stern 
+    CC: Matthew Dharm 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
+index c68b738900bd..9df6887b91f6 100644
+--- a/drivers/usb/storage/Kconfig
++++ b/drivers/usb/storage/Kconfig
+@@ -61,13 +61,6 @@ config USB_STORAGE_ISD200
+ 	  - CyQ've CQ8060A CDRW drive
+ 	  - Planex eXtreme Drive RX-25HU USB-IDE cable (not model RX-25U)
+ 
+-config USB_STORAGE_DPCM
+-	bool "Microtech/ZiO! CompactFlash/SmartMedia support"
+-	depends on USB_STORAGE
+-	help
+-	  Say Y here to support the Microtech/ZiO! CompactFlash reader.
+-	  There is a web page at .
+-
+ config USB_STORAGE_USBAT
+ 	bool "USBAT/USBAT02-based storage support"
+ 	depends on USB_STORAGE
+@@ -90,12 +83,12 @@ config USB_STORAGE_USBAT
+ 	  - Sandisk ImageMate SDDR-05b
+ 
+ config USB_STORAGE_SDDR09
+-	bool "SanDisk SDDR-09 (and other SmartMedia) support"
++	bool "SanDisk SDDR-09 (and other SmartMedia, including DPCM) support"
+ 	depends on USB_STORAGE
+ 	help
+ 	  Say Y here to include additional code to support the Sandisk SDDR-09
+ 	  SmartMedia reader in the USB Mass Storage driver.
+-	  Also works for the Microtech Zio! SmartMedia reader.
++	  Also works for the Microtech Zio! CompactFlash/SmartMedia reader.
+ 
+ config USB_STORAGE_SDDR55
+ 	bool "SanDisk SDDR-55 SmartMedia support"
+diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
+index 7f8beb5366ae..facf610f1683 100644
+--- a/drivers/usb/storage/Makefile
++++ b/drivers/usb/storage/Makefile
+@@ -14,7 +14,6 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_USBAT)	+= shuttle_usbat.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR09)	+= sddr09.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR55)	+= sddr55.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM)	+= freecom.o
+-usb-storage-obj-$(CONFIG_USB_STORAGE_DPCM)	+= dpcm.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_ISD200)	+= isd200.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB)	+= datafab.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT)	+= jumpshot.o
+diff --git a/drivers/usb/storage/dpcm.c b/drivers/usb/storage/dpcm.c
+deleted file mode 100644
+index 939923471af4..000000000000
+--- a/drivers/usb/storage/dpcm.c
++++ /dev/null
+@@ -1,86 +0,0 @@
+-/* Driver for Microtech DPCM-USB CompactFlash/SmartMedia reader
+- *
+- * DPCM driver v0.1:
+- *
+- * First release
+- *
+- * Current development and maintenance by:
+- *   (c) 2000 Brian Webb (webbb@earthlink.net)
+- *
+- * This device contains both a CompactFlash card reader, which
+- * uses the Control/Bulk w/o Interrupt protocol and
+- * a SmartMedia card reader that uses the same protocol
+- * as the SDDR09.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the
+- * Free Software Foundation; either version 2, or (at your option) any
+- * later version.
+- *
+- * This program is distributed in the hope that it will be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#include 
+-#include 
+-#include 
+-
+-#include "usb.h"
+-#include "transport.h"
+-#include "protocol.h"
+-#include "debug.h"
+-#include "dpcm.h"
+-#include "sddr09.h"
+-
+-/*
+- * Transport for the Microtech DPCM-USB
+- *
+- */
+-int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us)
+-{
+-	int ret;
+-
+-	if (srb == NULL)
+-		return USB_STOR_TRANSPORT_ERROR;
+-
+-	US_DEBUGP("dpcm_transport: LUN=%d\n", srb->device->lun);
+-
+-	switch (srb->device->lun) {
+-		case 0:
+-
+-			/*
+-			 * LUN 0 corresponds to the CompactFlash card reader.
+-			 */
+-			ret = usb_stor_CB_transport(srb, us);
+-			break;
+-
+-#ifdef CONFIG_USB_STORAGE_SDDR09
+-		case 1:
+-
+-			/*
+-			 * LUN 1 corresponds to the SmartMedia card reader.
+-			 */
+-
+-			/*
+-			 * Set the LUN to 0 (just in case).
+-			 */
+-			srb->device->lun = 0; us->srb->device->lun = 0;
+-			ret = sddr09_transport(srb, us);
+-			srb->device->lun = 1; us->srb->device->lun = 1;
+-			break;
+-
+-#endif
+-
+-		default:
+-			US_DEBUGP("dpcm_transport: Invalid LUN %d\n", srb->device->lun);
+-			ret = USB_STOR_TRANSPORT_ERROR;
+-			break;
+-	}
+-	return ret;
+-}
+diff --git a/drivers/usb/storage/dpcm.h b/drivers/usb/storage/dpcm.h
+deleted file mode 100644
+index e7b7b0f120d7..000000000000
+--- a/drivers/usb/storage/dpcm.h
++++ /dev/null
+@@ -1,32 +0,0 @@
+-/* Driver for Microtech DPCM-USB CompactFlash/SmartMedia reader
+- *
+- * DPCM driver v0.1:
+- *
+- * First release
+- *
+- * Current development and maintenance by:
+- *   (c) 2000 Brian Webb (webbb@earthlink.net)
+- *
+- * See dpcm.c for more explanation
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the
+- * Free Software Foundation; either version 2, or (at your option) any
+- * later version.
+- *
+- * This program is distributed in the hope that it will be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#ifndef _MICROTECH_DPCM_USB_H
+-#define _MICROTECH_DPCM_USB_H
+-
+-extern int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us);
+-
+-#endif
+diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
+index c5a54b872c24..531ae5c5abf3 100644
+--- a/drivers/usb/storage/sddr09.c
++++ b/drivers/usb/storage/sddr09.c
+@@ -45,6 +45,7 @@
+ 
+ #include 
+ #include 
++#include 
+ 
+ #include "usb.h"
+ #include "transport.h"
+@@ -1445,6 +1446,48 @@ usb_stor_sddr09_dpcm_init(struct us_data *us) {
+ 	return 0;		/* not result */
+ }
+ 
++/*
++ * Transport for the Microtech DPCM-USB
++ */
++int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us)
++{
++	int ret;
++
++	US_DEBUGP("dpcm_transport: LUN=%d\n", srb->device->lun);
++
++	switch (srb->device->lun) {
++	case 0:
++
++		/*
++		 * LUN 0 corresponds to the CompactFlash card reader.
++		 */
++		ret = usb_stor_CB_transport(srb, us);
++		break;
++
++	case 1:
++
++		/*
++		 * LUN 1 corresponds to the SmartMedia card reader.
++		 */
++
++		/*
++		 * Set the LUN to 0 (just in case).
++		 */
++		srb->device->lun = 0;
++		ret = sddr09_transport(srb, us);
++		srb->device->lun = 1;
++		break;
++
++	default:
++		US_DEBUGP("dpcm_transport: Invalid LUN %d\n",
++				srb->device->lun);
++		ret = USB_STOR_TRANSPORT_ERROR;
++		break;
++	}
++	return ret;
++}
++
++
+ /*
+  * Transport for the Sandisk SDDR-09
+  */
+diff --git a/drivers/usb/storage/sddr09.h b/drivers/usb/storage/sddr09.h
+index e50033ad7b19..b701172e12e3 100644
+--- a/drivers/usb/storage/sddr09.h
++++ b/drivers/usb/storage/sddr09.h
+@@ -28,8 +28,11 @@
+ /* Sandisk SDDR-09 stuff */
+ 
+ extern int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us);
++extern int usb_stor_sddr09_init(struct us_data *us);
++
++/* Microtech DPCM-USB stuff */
+ 
++extern int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us);
+ extern int usb_stor_sddr09_dpcm_init(struct us_data *us);
+-extern int usb_stor_sddr09_init(struct us_data *us);
+ 
+ #endif
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 745809778310..0fd42a0c794f 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -296,11 +296,17 @@ UNUSUAL_DEV(  0x0424, 0x0fdc, 0x0210, 0x0210,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_SINGLE_LUN ),
+ 
+-#ifdef CONFIG_USB_STORAGE_DPCM
++#ifdef CONFIG_USB_STORAGE_SDDR09
+ UNUSUAL_DEV(  0x0436, 0x0005, 0x0100, 0x0100,
+ 		"Microtech",
+ 		"CameraMate (DPCM_USB)",
+  		US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ),
++#else
++UNUSUAL_DEV(  0x0436, 0x0005, 0x0100, 0x0100,
++		"Microtech",
++		"CameraMate",
++		US_SC_SCSI, US_PR_CB, NULL,
++		US_FL_SINGLE_LUN ),
+ #endif
+ 
+ /* Patch submitted by Daniel Drake 
+@@ -601,6 +607,12 @@ UNUSUAL_DEV(  0x04e6, 0x0005, 0x0100, 0x0208,
+ 		"eUSB SmartMedia / CompactFlash Adapter",
+ 		US_SC_SCSI, US_PR_DPCM_USB, usb_stor_sddr09_dpcm_init,
+ 		0),
++#else
++UNUSUAL_DEV(  0x04e6, 0x0005, 0x0100, 0x0208,
++		"SCM Microsystems",
++		"eUSB CompactFlash Adapter",
++		US_SC_SCSI, US_PR_CB, NULL,
++		US_FL_SINGLE_LUN),
+ #endif
+ 
+ /* Reported by Markus Demleitner  */
+@@ -1175,11 +1187,17 @@ UNUSUAL_DEV(  0x07af, 0x0005, 0x0100, 0x0100,
+ 		US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init,
+ 		US_FL_SCM_MULT_TARG ),
+ 
+-#ifdef CONFIG_USB_STORAGE_DPCM
++#ifdef CONFIG_USB_STORAGE_SDDR09
+ UNUSUAL_DEV(  0x07af, 0x0006, 0x0100, 0x0100,
+ 		"Microtech",
+ 		"CameraMate (DPCM_USB)",
+  		US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ),
++#else
++UNUSUAL_DEV(  0x07af, 0x0006, 0x0100, 0x0100,
++		"Microtech",
++		"CameraMate",
++		US_SC_SCSI, US_PR_CB, NULL,
++		US_FL_SINGLE_LUN ),
+ #endif
+ 
+ #ifdef CONFIG_USB_STORAGE_ALAUDA
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 06c735703f4a..b25c448d5eb7 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -75,9 +75,6 @@
+ #ifdef CONFIG_USB_STORAGE_SDDR55
+ #include "sddr55.h"
+ #endif
+-#ifdef CONFIG_USB_STORAGE_DPCM
+-#include "dpcm.h"
+-#endif
+ #ifdef CONFIG_USB_STORAGE_FREECOM
+ #include "freecom.h"
+ #endif

commit 65bfd2967c906ca322a4bb69a285fe0de8916ac6
+Author: Alan Stern 
+Date:   Tue Nov 25 16:39:18 2008 -0500
+
+    USB: Enhance usage of pm_message_t
+    
+    This patch (as1177) modifies the USB core suspend and resume
+    routines.  The resume functions now will take a pm_message_t argument,
+    so they will know what sort of resume is occurring.  The new argument
+    is also passed to the port suspend/resume and bus suspend/resume
+    routines (although they don't use it for anything but debugging).
+    
+    In addition, special pm_message_t values are used for user-initiated,
+    device-initiated (i.e., remote wakeup), and automatic suspend/resume.
+    By testing these values, drivers can tell whether or not a particular
+    suspend was an autosuspend.  Unfortunately, they can't do the same for
+    resumes -- not until the pm_message_t argument is also passed to the
+    drivers' resume methods.  That will require a bigger change.
+    
+    IMO, the whole Power Management framework should have been set up this
+    way in the first place.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
+index d50a99f70aee..00b47ea24f86 100644
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -1275,7 +1275,7 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message)
+ 	struct acm *acm = usb_get_intfdata(intf);
+ 	int cnt;
+ 
+-	if (acm->dev->auto_pm) {
++	if (message.event & PM_EVENT_AUTO) {
+ 		int b;
+ 
+ 		spin_lock_irq(&acm->read_lock);
+diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
+index 5a8ecc045e3f..3771d6e6d0cc 100644
+--- a/drivers/usb/class/cdc-wdm.c
++++ b/drivers/usb/class/cdc-wdm.c
+@@ -764,7 +764,8 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
+ 
+ 	mutex_lock(&desc->plock);
+ #ifdef CONFIG_PM
+-	if (interface_to_usbdev(desc->intf)->auto_pm && test_bit(WDM_IN_USE, &desc->flags)) {
++	if ((message.event & PM_EVENT_AUTO) &&
++			test_bit(WDM_IN_USE, &desc->flags)) {
+ 		rv = -EBUSY;
+ 	} else {
+ #endif
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 0226e019326a..41c06025506e 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -922,7 +922,7 @@ static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
+ }
+ 
+ /* Caller has locked udev's pm_mutex */
+-static int usb_resume_device(struct usb_device *udev)
++static int usb_resume_device(struct usb_device *udev, pm_message_t msg)
+ {
+ 	struct usb_device_driver	*udriver;
+ 	int				status = 0;
+@@ -940,7 +940,7 @@ static int usb_resume_device(struct usb_device *udev)
+ 		udev->reset_resume = 1;
+ 
+ 	udriver = to_usb_device_driver(udev->dev.driver);
+-	status = udriver->resume(udev);
++	status = udriver->resume(udev, msg);
+ 
+  done:
+ 	dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
+@@ -969,7 +969,7 @@ static int usb_suspend_interface(struct usb_device *udev,
+ 		status = driver->suspend(intf, msg);
+ 		if (status == 0)
+ 			mark_quiesced(intf);
+-		else if (!udev->auto_pm)
++		else if (!(msg.event & PM_EVENT_AUTO))
+ 			dev_err(&intf->dev, "%s error %d\n",
+ 					"suspend", status);
+ 	} else {
+@@ -987,7 +987,7 @@ static int usb_suspend_interface(struct usb_device *udev,
+ 
+ /* Caller has locked intf's usb_device's pm_mutex */
+ static int usb_resume_interface(struct usb_device *udev,
+-		struct usb_interface *intf, int reset_resume)
++		struct usb_interface *intf, pm_message_t msg, int reset_resume)
+ {
+ 	struct usb_driver	*driver;
+ 	int			status = 0;
+@@ -1138,10 +1138,9 @@ static inline int autosuspend_check(struct usb_device *udev, int reschedule)
+  * all the interfaces which were suspended are resumed so that they remain
+  * in the same state as the device.
+  *
+- * If an autosuspend is in progress (@udev->auto_pm is set), the routine
+- * checks first to make sure that neither the device itself or any of its
+- * active interfaces is in use (pm_usage_cnt is greater than 0).  If they
+- * are, the autosuspend fails.
++ * If an autosuspend is in progress the routine checks first to make sure
++ * that neither the device itself or any of its active interfaces is in use
++ * (pm_usage_cnt is greater than 0).  If they are, the autosuspend fails.
+  *
+  * If the suspend succeeds, the routine recursively queues an autosuspend
+  * request for @udev's parent device, thereby propagating the change up
+@@ -1176,7 +1175,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 
+ 	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
+ 
+-	if (udev->auto_pm) {
++	if (msg.event & PM_EVENT_AUTO) {
+ 		status = autosuspend_check(udev, 0);
+ 		if (status < 0)
+ 			goto done;
+@@ -1196,13 +1195,16 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 
+ 	/* If the suspend failed, resume interfaces that did get suspended */
+ 	if (status != 0) {
++		pm_message_t msg2;
++
++		msg2.event = msg.event ^ (PM_EVENT_SUSPEND | PM_EVENT_RESUME);
+ 		while (--i >= 0) {
+ 			intf = udev->actconfig->interface[i];
+-			usb_resume_interface(udev, intf, 0);
++			usb_resume_interface(udev, intf, msg2, 0);
+ 		}
+ 
+ 		/* Try another autosuspend when the interfaces aren't busy */
+-		if (udev->auto_pm)
++		if (msg.event & PM_EVENT_AUTO)
+ 			autosuspend_check(udev, status == -EBUSY);
+ 
+ 	/* If the suspend succeeded then prevent any more URB submissions,
+@@ -1232,6 +1234,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ /**
+  * usb_resume_both - resume a USB device and its interfaces
+  * @udev: the usb_device to resume
++ * @msg: Power Management message describing this state transition
+  *
+  * This is the central routine for resuming USB devices.  It calls the
+  * the resume method for @udev and then calls the resume methods for all
+@@ -1257,7 +1260,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+  *
+  * This routine can run only in process context.
+  */
+-static int usb_resume_both(struct usb_device *udev)
++static int usb_resume_both(struct usb_device *udev, pm_message_t msg)
+ {
+ 	int			status = 0;
+ 	int			i;
+@@ -1273,14 +1276,15 @@ static int usb_resume_both(struct usb_device *udev)
+ 
+ 	/* Propagate the resume up the tree, if necessary */
+ 	if (udev->state == USB_STATE_SUSPENDED) {
+-		if (udev->auto_pm && udev->autoresume_disabled) {
++		if ((msg.event & PM_EVENT_AUTO) &&
++				udev->autoresume_disabled) {
+ 			status = -EPERM;
+ 			goto done;
+ 		}
+ 		if (parent) {
+ 			status = usb_autoresume_device(parent);
+ 			if (status == 0) {
+-				status = usb_resume_device(udev);
++				status = usb_resume_device(udev, msg);
+ 				if (status || udev->state ==
+ 						USB_STATE_NOTATTACHED) {
+ 					usb_autosuspend_device(parent);
+@@ -1303,15 +1307,16 @@ static int usb_resume_both(struct usb_device *udev)
+ 			/* We can't progagate beyond the USB subsystem,
+ 			 * so if a root hub's controller is suspended
+ 			 * then we're stuck. */
+-			status = usb_resume_device(udev);
++			status = usb_resume_device(udev, msg);
+ 		}
+ 	} else if (udev->reset_resume)
+-		status = usb_resume_device(udev);
++		status = usb_resume_device(udev, msg);
+ 
+ 	if (status == 0 && udev->actconfig) {
+ 		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+ 			intf = udev->actconfig->interface[i];
+-			usb_resume_interface(udev, intf, udev->reset_resume);
++			usb_resume_interface(udev, intf, msg,
++					udev->reset_resume);
+ 		}
+ 	}
+ 
+@@ -1339,13 +1344,13 @@ static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt)
+ 		udev->last_busy = jiffies;
+ 	if (inc_usage_cnt >= 0 && udev->pm_usage_cnt > 0) {
+ 		if (udev->state == USB_STATE_SUSPENDED)
+-			status = usb_resume_both(udev);
++			status = usb_resume_both(udev, PMSG_AUTO_RESUME);
+ 		if (status != 0)
+ 			udev->pm_usage_cnt -= inc_usage_cnt;
+ 		else if (inc_usage_cnt)
+ 			udev->last_busy = jiffies;
+ 	} else if (inc_usage_cnt <= 0 && udev->pm_usage_cnt <= 0) {
+-		status = usb_suspend_both(udev, PMSG_SUSPEND);
++		status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
+ 	}
+ 	usb_pm_unlock(udev);
+ 	return status;
+@@ -1469,13 +1474,14 @@ static int usb_autopm_do_interface(struct usb_interface *intf,
+ 		udev->last_busy = jiffies;
+ 		if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) {
+ 			if (udev->state == USB_STATE_SUSPENDED)
+-				status = usb_resume_both(udev);
++				status = usb_resume_both(udev,
++						PMSG_AUTO_RESUME);
+ 			if (status != 0)
+ 				intf->pm_usage_cnt -= inc_usage_cnt;
+ 			else
+ 				udev->last_busy = jiffies;
+ 		} else if (inc_usage_cnt <= 0 && intf->pm_usage_cnt <= 0) {
+-			status = usb_suspend_both(udev, PMSG_SUSPEND);
++			status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
+ 		}
+ 	}
+ 	usb_pm_unlock(udev);
+@@ -1700,6 +1706,7 @@ int usb_external_suspend_device(struct usb_device *udev, pm_message_t msg)
+ /**
+  * usb_external_resume_device - external resume of a USB device and its interfaces
+  * @udev: the usb_device to resume
++ * @msg: Power Management message describing this state transition
+  *
+  * This routine handles external resume requests: ones not generated
+  * internally by a USB driver (autoresume) but rather coming from the user
+@@ -1708,13 +1715,13 @@ int usb_external_suspend_device(struct usb_device *udev, pm_message_t msg)
+  *
+  * The caller must hold @udev's device lock.
+  */
+-int usb_external_resume_device(struct usb_device *udev)
++int usb_external_resume_device(struct usb_device *udev, pm_message_t msg)
+ {
+ 	int	status;
+ 
+ 	usb_pm_lock(udev);
+ 	udev->auto_pm = 0;
+-	status = usb_resume_both(udev);
++	status = usb_resume_both(udev, msg);
+ 	udev->last_busy = jiffies;
+ 	usb_pm_unlock(udev);
+ 	if (status == 0)
+@@ -1727,7 +1734,7 @@ int usb_external_resume_device(struct usb_device *udev)
+ 	return status;
+ }
+ 
+-int usb_suspend(struct device *dev, pm_message_t message)
++int usb_suspend(struct device *dev, pm_message_t msg)
+ {
+ 	struct usb_device	*udev;
+ 
+@@ -1746,10 +1753,10 @@ int usb_suspend(struct device *dev, pm_message_t message)
+ 	}
+ 
+ 	udev->skip_sys_resume = 0;
+-	return usb_external_suspend_device(udev, message);
++	return usb_external_suspend_device(udev, msg);
+ }
+ 
+-int usb_resume(struct device *dev)
++int usb_resume(struct device *dev, pm_message_t msg)
+ {
+ 	struct usb_device	*udev;
+ 
+@@ -1761,7 +1768,7 @@ int usb_resume(struct device *dev)
+ 	 */
+ 	if (udev->skip_sys_resume)
+ 		return 0;
+-	return usb_external_resume_device(udev);
++	return usb_external_resume_device(udev, msg);
+ }
+ 
+ #endif /* CONFIG_PM */
+diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
+index 7e912f21fd36..30ecac3af15a 100644
+--- a/drivers/usb/core/generic.c
++++ b/drivers/usb/core/generic.c
+@@ -200,18 +200,18 @@ static int generic_suspend(struct usb_device *udev, pm_message_t msg)
+ 	 * interfaces manually by doing a bus (or "global") suspend.
+ 	 */
+ 	if (!udev->parent)
+-		rc = hcd_bus_suspend(udev);
++		rc = hcd_bus_suspend(udev, msg);
+ 
+ 	/* Non-root devices don't need to do anything for FREEZE or PRETHAW */
+ 	else if (msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_PRETHAW)
+ 		rc = 0;
+ 	else
+-		rc = usb_port_suspend(udev);
++		rc = usb_port_suspend(udev, msg);
+ 
+ 	return rc;
+ }
+ 
+-static int generic_resume(struct usb_device *udev)
++static int generic_resume(struct usb_device *udev, pm_message_t msg)
+ {
+ 	int rc;
+ 
+@@ -221,9 +221,9 @@ static int generic_resume(struct usb_device *udev)
+ 	 * interfaces manually by doing a bus (or "global") resume.
+ 	 */
+ 	if (!udev->parent)
+-		rc = hcd_bus_resume(udev);
++		rc = hcd_bus_resume(udev, msg);
+ 	else
+-		rc = usb_port_resume(udev);
++		rc = usb_port_resume(udev, msg);
+ 	return rc;
+ }
+ 
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 7403ed871abd..a0079876d74e 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1573,14 +1573,14 @@ int usb_hcd_get_frame_number (struct usb_device *udev)
+ 
+ #ifdef	CONFIG_PM
+ 
+-int hcd_bus_suspend(struct usb_device *rhdev)
++int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg)
+ {
+ 	struct usb_hcd	*hcd = container_of(rhdev->bus, struct usb_hcd, self);
+ 	int		status;
+ 	int		old_state = hcd->state;
+ 
+ 	dev_dbg(&rhdev->dev, "bus %s%s\n",
+-			rhdev->auto_pm ? "auto-" : "", "suspend");
++			(msg.event & PM_EVENT_AUTO ? "auto-" : ""), "suspend");
+ 	if (!hcd->driver->bus_suspend) {
+ 		status = -ENOENT;
+ 	} else {
+@@ -1598,14 +1598,14 @@ int hcd_bus_suspend(struct usb_device *rhdev)
+ 	return status;
+ }
+ 
+-int hcd_bus_resume(struct usb_device *rhdev)
++int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
+ {
+ 	struct usb_hcd	*hcd = container_of(rhdev->bus, struct usb_hcd, self);
+ 	int		status;
+ 	int		old_state = hcd->state;
+ 
+ 	dev_dbg(&rhdev->dev, "usb %s%s\n",
+-			rhdev->auto_pm ? "auto-" : "", "resume");
++			(msg.event & PM_EVENT_AUTO ? "auto-" : ""), "resume");
+ 	if (!hcd->driver->bus_resume)
+ 		return -ENOENT;
+ 	if (hcd->state == HC_STATE_RUNNING)
+@@ -1638,7 +1638,7 @@ static void hcd_resume_work(struct work_struct *work)
+ 
+ 	usb_lock_device(udev);
+ 	usb_mark_last_busy(udev);
+-	usb_external_resume_device(udev);
++	usb_external_resume_device(udev, PMSG_REMOTE_RESUME);
+ 	usb_unlock_device(udev);
+ }
+ 
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index 0aaa9cea6b38..aa5da82d9071 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -388,8 +388,8 @@ extern int usb_find_interface_driver(struct usb_device *dev,
+ #ifdef CONFIG_PM
+ extern void usb_hcd_resume_root_hub(struct usb_hcd *hcd);
+ extern void usb_root_hub_lost_power(struct usb_device *rhdev);
+-extern int hcd_bus_suspend(struct usb_device *rhdev);
+-extern int hcd_bus_resume(struct usb_device *rhdev);
++extern int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg);
++extern int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg);
+ #else
+ static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
+ {
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index ff066edf4dca..fc99ef67761d 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1984,7 +1984,7 @@ static int check_port_resume_type(struct usb_device *udev,
+  *
+  * Returns 0 on success, else negative errno.
+  */
+-int usb_port_suspend(struct usb_device *udev)
++int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ {
+ 	struct usb_hub	*hub = hdev_to_hub(udev->parent);
+ 	int		port1 = udev->portnum;
+@@ -2023,7 +2023,7 @@ int usb_port_suspend(struct usb_device *udev)
+ 	} else {
+ 		/* device has up to 10 msec to fully suspend */
+ 		dev_dbg(&udev->dev, "usb %ssuspend\n",
+-				udev->auto_pm ? "auto-" : "");
++				(msg.event & PM_EVENT_AUTO ? "auto-" : ""));
+ 		usb_set_device_state(udev, USB_STATE_SUSPENDED);
+ 		msleep(10);
+ 	}
+@@ -2142,7 +2142,7 @@ static int finish_port_resume(struct usb_device *udev)
+  *
+  * Returns 0 on success, else negative errno.
+  */
+-int usb_port_resume(struct usb_device *udev)
++int usb_port_resume(struct usb_device *udev, pm_message_t msg)
+ {
+ 	struct usb_hub	*hub = hdev_to_hub(udev->parent);
+ 	int		port1 = udev->portnum;
+@@ -2167,7 +2167,7 @@ int usb_port_resume(struct usb_device *udev)
+ 	} else {
+ 		/* drive resume for at least 20 msec */
+ 		dev_dbg(&udev->dev, "usb %sresume\n",
+-				udev->auto_pm ? "auto-" : "");
++				(msg.event & PM_EVENT_AUTO ? "auto-" : ""));
+ 		msleep(25);
+ 
+ 		/* Virtual root hubs can trigger on GET_PORT_STATUS to
+@@ -2208,7 +2208,7 @@ static int remote_wakeup(struct usb_device *udev)
+ 	if (udev->state == USB_STATE_SUSPENDED) {
+ 		dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-");
+ 		usb_mark_last_busy(udev);
+-		status = usb_external_resume_device(udev);
++		status = usb_external_resume_device(udev, PMSG_REMOTE_RESUME);
+ 	}
+ 	return status;
+ }
+@@ -2217,14 +2217,14 @@ static int remote_wakeup(struct usb_device *udev)
+ 
+ /* When CONFIG_USB_SUSPEND isn't set, we never suspend or resume any ports. */
+ 
+-int usb_port_suspend(struct usb_device *udev)
++int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ {
+ 	return 0;
+ }
+ 
+ /* However we may need to do a reset-resume */
+ 
+-int usb_port_resume(struct usb_device *udev)
++int usb_port_resume(struct usb_device *udev, pm_message_t msg)
+ {
+ 	struct usb_hub	*hub = hdev_to_hub(udev->parent);
+ 	int		port1 = udev->portnum;
+@@ -2264,7 +2264,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+ 
+ 		udev = hdev->children [port1-1];
+ 		if (udev && udev->can_submit) {
+-			if (!hdev->auto_pm)
++			if (!(msg.event & PM_EVENT_AUTO))
+ 				dev_dbg(&intf->dev, "port %d nyet suspended\n",
+ 						port1);
+ 			return -EBUSY;
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 8c65fa75b5c2..0f0ccf640114 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -359,19 +359,19 @@ set_level(struct device *dev, struct device_attribute *attr,
+ 			strncmp(buf, on_string, len) == 0) {
+ 		udev->autosuspend_disabled = 1;
+ 		udev->autoresume_disabled = 0;
+-		rc = usb_external_resume_device(udev);
++		rc = usb_external_resume_device(udev, PMSG_USER_RESUME);
+ 
+ 	} else if (len == sizeof auto_string - 1 &&
+ 			strncmp(buf, auto_string, len) == 0) {
+ 		udev->autosuspend_disabled = 0;
+ 		udev->autoresume_disabled = 0;
+-		rc = usb_external_resume_device(udev);
++		rc = usb_external_resume_device(udev, PMSG_USER_RESUME);
+ 
+ 	} else if (len == sizeof suspend_string - 1 &&
+ 			strncmp(buf, suspend_string, len) == 0) {
+ 		udev->autosuspend_disabled = 0;
+ 		udev->autoresume_disabled = 1;
+-		rc = usb_external_suspend_device(udev, PMSG_SUSPEND);
++		rc = usb_external_suspend_device(udev, PMSG_USER_SUSPEND);
+ 
+ 	} else
+ 		rc = -EINVAL;
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 51854c2bc912..4c98f3975afe 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -253,7 +253,7 @@ static int usb_dev_prepare(struct device *dev)
+ static void usb_dev_complete(struct device *dev)
+ {
+ 	/* Currently used only for rebinding interfaces */
+-	usb_resume(dev);	/* Implement eventually? */
++	usb_resume(dev, PMSG_RESUME);	/* Message event is meaningless */
+ }
+ 
+ static int usb_dev_suspend(struct device *dev)
+@@ -263,7 +263,7 @@ static int usb_dev_suspend(struct device *dev)
+ 
+ static int usb_dev_resume(struct device *dev)
+ {
+-	return usb_resume(dev);
++	return usb_resume(dev, PMSG_RESUME);
+ }
+ 
+ static int usb_dev_freeze(struct device *dev)
+@@ -273,7 +273,7 @@ static int usb_dev_freeze(struct device *dev)
+ 
+ static int usb_dev_thaw(struct device *dev)
+ {
+-	return usb_resume(dev);
++	return usb_resume(dev, PMSG_THAW);
+ }
+ 
+ static int usb_dev_poweroff(struct device *dev)
+@@ -283,7 +283,7 @@ static int usb_dev_poweroff(struct device *dev)
+ 
+ static int usb_dev_restore(struct device *dev)
+ {
+-	return usb_resume(dev);
++	return usb_resume(dev, PMSG_RESTORE);
+ }
+ 
+ static struct dev_pm_ops usb_device_pm_ops = {
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index b60ebb4de1a8..9fb195665fa8 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -1,3 +1,5 @@
++#include 
++
+ /* Functions local to drivers/usb/core/ */
+ 
+ extern int usb_create_sysfs_dev_files(struct usb_device *dev);
+@@ -42,15 +44,16 @@ extern void usb_host_cleanup(void);
+ #ifdef	CONFIG_PM
+ 
+ extern int usb_suspend(struct device *dev, pm_message_t msg);
+-extern int usb_resume(struct device *dev);
++extern int usb_resume(struct device *dev, pm_message_t msg);
+ 
+ extern void usb_autosuspend_work(struct work_struct *work);
+ extern void usb_autoresume_work(struct work_struct *work);
+-extern int usb_port_suspend(struct usb_device *dev);
+-extern int usb_port_resume(struct usb_device *dev);
++extern int usb_port_suspend(struct usb_device *dev, pm_message_t msg);
++extern int usb_port_resume(struct usb_device *dev, pm_message_t msg);
+ extern int usb_external_suspend_device(struct usb_device *udev,
+ 		pm_message_t msg);
+-extern int usb_external_resume_device(struct usb_device *udev);
++extern int usb_external_resume_device(struct usb_device *udev,
++		pm_message_t msg);
+ 
+ static inline void usb_pm_lock(struct usb_device *udev)
+ {
+@@ -64,12 +67,12 @@ static inline void usb_pm_unlock(struct usb_device *udev)
+ 
+ #else
+ 
+-static inline int usb_port_suspend(struct usb_device *udev)
++static inline int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ {
+ 	return 0;
+ }
+ 
+-static inline int usb_port_resume(struct usb_device *udev)
++static inline int usb_port_resume(struct usb_device *udev, pm_message_t msg)
+ {
+ 	return 0;
+ }
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 8bc81bffc195..74d0b9990c73 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -1067,7 +1067,7 @@ struct usb_device_driver {
+ 	void (*disconnect) (struct usb_device *udev);
+ 
+ 	int (*suspend) (struct usb_device *udev, pm_message_t message);
+-	int (*resume) (struct usb_device *udev);
++	int (*resume) (struct usb_device *udev, pm_message_t message);
+ 	struct usbdrv_wrap drvwrap;
+ 	unsigned int supports_autosuspend:1;
+ };

commit 4ec06d629628b6e5c7ff50d349a26ef5c35696e3
+Author: Alan Stern 
+Date:   Tue Nov 25 16:40:02 2008 -0500
+
+    USB: utilize round_jiffies_up_relative()
+    
+    This patch (as1178) uses the new round_jiffies_up_relative() routine
+    for setting the autosuspend delayed_work timer.  It's appropriate
+    since we don't care too much about the exact length of the delay, but
+    we don't want it to be too short (rounded down).
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 7e26fb3c2759..0226e019326a 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1111,7 +1111,7 @@ static int autosuspend_check(struct usb_device *udev, int reschedule)
+ 	if (reschedule) {
+ 		if (!timer_pending(&udev->autosuspend.timer)) {
+ 			queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+-				round_jiffies_relative(suspend_time - j));
++				round_jiffies_up_relative(suspend_time - j));
+ 		}
+ 		return -EAGAIN;
+ 	}
+@@ -1553,7 +1553,7 @@ void usb_autopm_put_interface_async(struct usb_interface *intf)
+ 		else if (intf->pm_usage_cnt <= 0 &&
+ 				!timer_pending(&udev->autosuspend.timer)) {
+ 			queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+-					round_jiffies_relative(
++					round_jiffies_up_relative(
+ 						udev->autosuspend_delay));
+ 		}
+ 	}

commit 96983d2d861bf94b7f70bc47ac3c5b289f519a2d
+Author: Alan Stern 
+Date:   Fri Nov 21 11:46:17 2008 -0500
+
+    USB: storage: set bounce limit for non-DMA-capable host controllers
+    
+    This patch (as1175) makes usb-storage set a SCSI device's
+    request-queue bounce limit such that all buffers will be located in
+    addressable memory (i.e., not in high memory) if the host controller's
+    dma_mask is NULL.  This is necessary when the host controller doesn't
+    support DMA: If a buffer is in high memory then the both the virtual
+    and DMA addresses produced by the scatter-gather library will be NULL,
+    preventing the HCD from accessing the buffer's data.
+    
+    In particular, the isp1760 driver needs this when used on a system
+    with more than 1 GB of memory.
+    
+    Signed-off-by: Alan Stern 
+    CC: Matthew Dharm 
+    Acked-by: Jens Axboe 
+    Tested-by: Thomas Hommel 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index 1b35e011a34f..e9d6c196a7ab 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -129,6 +129,14 @@ static int slave_configure(struct scsi_device *sdev)
+ 					      max_sectors);
+ 	}
+ 
++	/* Some USB host controllers can't do DMA; they have to use PIO.
++	 * They indicate this by setting their dma_mask to NULL.  For
++	 * such controllers we need to make sure the block layer sets
++	 * up bounce buffers in addressable memory.
++	 */
++	if (!us->pusb_dev->bus->controller->dma_mask)
++		blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_HIGH);
++
+ 	/* We can't put these settings in slave_alloc() because that gets
+ 	 * called before the device type is known.  Consequently these
+ 	 * settings can't be overridden via the scsi devinfo mechanism. */

commit 3dae5345311271fe598a61bd01f563fc835b4217
+Author: Alan Stern 
+Date:   Thu Nov 20 14:22:18 2008 -0500
+
+    USB: usb-storage: merge ATAPI and QIC-157 protocol routines
+    
+    This patch (as1174) merges usb-storage's QIC-157 and ATAPI protocol
+    routines.  Since the two functions are identical, there's no reason to
+    keep them separate.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Matthew Dharm 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
+index 3b3357e20ea7..be441d84bc64 100644
+--- a/drivers/usb/storage/protocol.c
++++ b/drivers/usb/storage/protocol.c
+@@ -56,9 +56,9 @@
+  * Protocol routines
+  ***********************************************************************/
+ 
+-void usb_stor_qic157_command(struct scsi_cmnd *srb, struct us_data *us)
++void usb_stor_pad12_command(struct scsi_cmnd *srb, struct us_data *us)
+ {
+-	/* Pad the ATAPI command with zeros 
++	/* Pad the SCSI command with zeros out to 12 bytes
+ 	 *
+ 	 * NOTE: This only works because a scsi_cmnd struct field contains
+ 	 * a unsigned char cmnd[16], so we know we have storage available
+@@ -73,26 +73,6 @@ void usb_stor_qic157_command(struct scsi_cmnd *srb, struct us_data *us)
+ 	usb_stor_invoke_transport(srb, us);
+ }
+ 
+-void usb_stor_ATAPI_command(struct scsi_cmnd *srb, struct us_data *us)
+-{
+-	/* Pad the ATAPI command with zeros 
+-	 *
+-	 * NOTE: This only works because a scsi_cmnd struct field contains
+-	 * a unsigned char cmnd[16], so we know we have storage available
+-	 */
+-
+-	/* Pad the ATAPI command with zeros */
+-	for (; srb->cmd_len<12; srb->cmd_len++)
+-		srb->cmnd[srb->cmd_len] = 0;
+-
+-	/* set command length to 12 bytes */
+-	srb->cmd_len = 12;
+-
+-	/* send the command to the transport layer */
+-	usb_stor_invoke_transport(srb, us);
+-}
+-
+-
+ void usb_stor_ufi_command(struct scsi_cmnd *srb, struct us_data *us)
+ {
+ 	/* fix some commands -- this is a form of mode translation
+diff --git a/drivers/usb/storage/protocol.h b/drivers/usb/storage/protocol.h
+index 487056ffb516..ffc3e2af0156 100644
+--- a/drivers/usb/storage/protocol.h
++++ b/drivers/usb/storage/protocol.h
+@@ -40,8 +40,7 @@
+ #define _PROTOCOL_H_
+ 
+ /* Protocol handling routines */
+-extern void usb_stor_ATAPI_command(struct scsi_cmnd*, struct us_data*);
+-extern void usb_stor_qic157_command(struct scsi_cmnd*, struct us_data*);
++extern void usb_stor_pad12_command(struct scsi_cmnd*, struct us_data*);
+ extern void usb_stor_ufi_command(struct scsi_cmnd*, struct us_data*);
+ extern void usb_stor_transparent_scsi_command(struct scsi_cmnd*,
+ 		struct us_data*);
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index cdd009fae3cd..06c735703f4a 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -704,19 +704,19 @@ static int get_protocol(struct us_data *us)
+ 
+ 	case US_SC_8020:
+ 		us->protocol_name = "8020i";
+-		us->proto_handler = usb_stor_ATAPI_command;
++		us->proto_handler = usb_stor_pad12_command;
+ 		us->max_lun = 0;
+ 		break;
+ 
+ 	case US_SC_QIC:
+ 		us->protocol_name = "QIC-157";
+-		us->proto_handler = usb_stor_qic157_command;
++		us->proto_handler = usb_stor_pad12_command;
+ 		us->max_lun = 0;
+ 		break;
+ 
+ 	case US_SC_8070:
+ 		us->protocol_name = "8070i";
+-		us->proto_handler = usb_stor_ATAPI_command;
++		us->proto_handler = usb_stor_pad12_command;
+ 		us->max_lun = 0;
+ 		break;
+ 

commit 64648a9dc4d7ac0189364188207310ec6bc75bbe
+Author: Alan Stern 
+Date:   Thu Nov 20 14:20:03 2008 -0500
+
+    USB: usb-storage: merge CB and CBI transport routines
+    
+    This patch (as1173) merges usb-storage's CB and CBI transports into a
+    single routine.  So much of their code is common, it's silly to keep
+    them separate.
+    
+    Signed-off-by: Alan Stern 
+    CC: Matthew Dharm 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+index f584e72cc689..9cc30afd6d31 100644
+--- a/drivers/usb/storage/transport.c
++++ b/drivers/usb/storage/transport.c
+@@ -756,10 +756,10 @@ void usb_stor_stop_transport(struct us_data *us)
+ }
+ 
+ /*
+- * Control/Bulk/Interrupt transport
++ * Control/Bulk and Control/Bulk/Interrupt transport
+  */
+ 
+-int usb_stor_CBI_transport(struct scsi_cmnd *srb, struct us_data *us)
++int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us)
+ {
+ 	unsigned int transfer_length = scsi_bufflen(srb);
+ 	unsigned int pipe = 0;
+@@ -801,6 +801,13 @@ int usb_stor_CBI_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 	}
+ 
+ 	/* STATUS STAGE */
++
++	/* NOTE: CB does not have a status stage.  Silly, I know.  So
++	 * we have to catch this at a higher level.
++	 */
++	if (us->protocol != US_PR_CBI)
++		return USB_STOR_TRANSPORT_GOOD;
++
+ 	result = usb_stor_intr_transfer(us, us->iobuf, 2);
+ 	US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n", 
+ 			us->iobuf[0], us->iobuf[1]);
+@@ -854,56 +861,6 @@ int usb_stor_CBI_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 	return USB_STOR_TRANSPORT_FAILED;
+ }
+ 
+-/*
+- * Control/Bulk transport
+- */
+-int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us)
+-{
+-	unsigned int transfer_length = scsi_bufflen(srb);
+-	int result;
+-
+-	/* COMMAND STAGE */
+-	/* let's send the command via the control pipe */
+-	result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe,
+-				      US_CBI_ADSC, 
+-				      USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, 
+-				      us->ifnum, srb->cmnd, srb->cmd_len);
+-
+-	/* check the return code for the command */
+-	US_DEBUGP("Call to usb_stor_ctrl_transfer() returned %d\n", result);
+-
+-	/* if we stalled the command, it means command failed */
+-	if (result == USB_STOR_XFER_STALLED) {
+-		return USB_STOR_TRANSPORT_FAILED;
+-	}
+-
+-	/* Uh oh... serious problem here */
+-	if (result != USB_STOR_XFER_GOOD) {
+-		return USB_STOR_TRANSPORT_ERROR;
+-	}
+-
+-	/* DATA STAGE */
+-	/* transfer the data payload for this command, if one exists*/
+-	if (transfer_length) {
+-		unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? 
+-				us->recv_bulk_pipe : us->send_bulk_pipe;
+-		result = usb_stor_bulk_srb(us, pipe, srb);
+-		US_DEBUGP("CB data stage result is 0x%x\n", result);
+-
+-		/* if we stalled the data transfer it means command failed */
+-		if (result == USB_STOR_XFER_STALLED)
+-			return USB_STOR_TRANSPORT_FAILED;
+-		if (result > USB_STOR_XFER_STALLED)
+-			return USB_STOR_TRANSPORT_ERROR;
+-	}
+-
+-	/* STATUS STAGE */
+-	/* NOTE: CB does not have a status stage.  Silly, I know.  So
+-	 * we have to catch this at a higher level.
+-	 */
+-	return USB_STOR_TRANSPORT_GOOD;
+-}
+-
+ /*
+  * Bulk only transport
+  */
+diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
+index e70b88182f0e..242ff5e791a5 100644
+--- a/drivers/usb/storage/transport.h
++++ b/drivers/usb/storage/transport.h
+@@ -113,8 +113,6 @@ struct bulk_cs_wrap {
+ 
+ #define US_CBI_ADSC		0
+ 
+-extern int usb_stor_CBI_transport(struct scsi_cmnd *, struct us_data*);
+-
+ extern int usb_stor_CB_transport(struct scsi_cmnd *, struct us_data*);
+ extern int usb_stor_CB_reset(struct us_data*);
+ 
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 099e07c6af7b..cdd009fae3cd 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -591,7 +591,7 @@ static int get_transport(struct us_data *us)
+ 
+ 	case US_PR_CBI:
+ 		us->transport_name = "Control/Bulk/Interrupt";
+-		us->transport = usb_stor_CBI_transport;
++		us->transport = usb_stor_CB_transport;
+ 		us->transport_reset = usb_stor_CB_reset;
+ 		us->max_lun = 7;
+ 		break;

commit 12aae68a203e97a58d3f8237fc389201a4d9282d
+Author: Alan Stern 
+Date:   Thu Nov 20 14:13:12 2008 -0500
+
+    USB: g_file_storage: add CD-ROM emulation
+    
+    This patch (as1172) adds the ability to emulate a CD-ROM drive to
+    g_file_storage.  The emulation is limited, since it presents as a disc
+    containing a single data track and no audio tracks.  Still, it may
+    come in useful on occasion.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index 2e71368f45b4..93933155e81c 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -1,7 +1,7 @@
+ /*
+  * file_storage.c -- File-backed USB Storage Gadget, for USB development
+  *
+- * Copyright (C) 2003-2007 Alan Stern
++ * Copyright (C) 2003-2008 Alan Stern
+  * All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+@@ -38,16 +38,17 @@
+ 
+ /*
+  * The File-backed Storage Gadget acts as a USB Mass Storage device,
+- * appearing to the host as a disk drive.  In addition to providing an
+- * example of a genuinely useful gadget driver for a USB device, it also
+- * illustrates a technique of double-buffering for increased throughput.
+- * Last but not least, it gives an easy way to probe the behavior of the
+- * Mass Storage drivers in a USB host.
++ * appearing to the host as a disk drive or as a CD-ROM drive.  In addition
++ * to providing an example of a genuinely useful gadget driver for a USB
++ * device, it also illustrates a technique of double-buffering for increased
++ * throughput.  Last but not least, it gives an easy way to probe the
++ * behavior of the Mass Storage drivers in a USB host.
+  *
+  * Backing storage is provided by a regular file or a block device, specified
+  * by the "file" module parameter.  Access can be limited to read-only by
+- * setting the optional "ro" module parameter.  The gadget will indicate that
+- * it has removable media if the optional "removable" module parameter is set.
++ * setting the optional "ro" module parameter.  (For CD-ROM emulation,
++ * access is always read-only.)  The gadget will indicate that it has
++ * removable media if the optional "removable" module parameter is set.
+  *
+  * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI),
+  * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected
+@@ -64,7 +65,12 @@
+  * The default number of LUNs is taken from the number of "file" elements;
+  * it is 1 if "file" is not given.  If "removable" is not set then a backing
+  * file must be specified for each LUN.  If it is set, then an unspecified
+- * or empty backing filename means the LUN's medium is not loaded.
++ * or empty backing filename means the LUN's medium is not loaded.  Ideally
++ * each LUN would be settable independently as a disk drive or a CD-ROM
++ * drive, but currently all LUNs have to be the same type.  The CD-ROM
++ * emulation includes a single data track and no audio tracks; hence there
++ * need be only one backing file per LUN.  Note also that the CD-ROM block
++ * length is set to 512 rather than the more common value 2048.
+  *
+  * Requirements are modest; only a bulk-in and a bulk-out endpoint are
+  * needed (an interrupt-out endpoint is also needed for CBI).  The memory
+@@ -91,6 +97,8 @@
+  *					USB device controller (usually true),
+  *					boolean to permit the driver to halt
+  *					bulk endpoints
++ *	cdrom			Default false, boolean for whether to emulate
++ *					a CD-ROM drive
+  *	transport=XXX		Default BBB, transport name (CB, CBI, or BBB)
+  *	protocol=YYY		Default SCSI, protocol name (RBC, 8020 or
+  *					ATAPI, QIC, UFI, 8070, or SCSI;
+@@ -103,15 +111,16 @@
+  *					PAGE_CACHE_SIZE)
+  *
+  * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro",
+- * "removable", "luns", and "stall" options are available; default values
+- * are used for everything else.
++ * "removable", "luns", "stall", and "cdrom" options are available; default
++ * values are used for everything else.
+  *
+  * The pathnames of the backing files and the ro settings are available in
+  * the attribute files "file" and "ro" in the lun subdirectory of the
+  * gadget's sysfs directory.  If the "removable" option is set, writing to
+  * these files will simulate ejecting/loading the medium (writing an empty
+  * line means eject) and adjusting a write-enable tab.  Changes to the ro
+- * setting are not allowed when the medium is loaded.
++ * setting are not allowed when the medium is loaded or if CD-ROM emulation
++ * is being used.
+  *
+  * This gadget driver is heavily based on "Gadget Zero" by David Brownell.
+  * The driver's SCSI command interface was based on the "Information
+@@ -261,7 +270,7 @@
+ 
+ #define DRIVER_DESC		"File-backed Storage Gadget"
+ #define DRIVER_NAME		"g_file_storage"
+-#define DRIVER_VERSION		"7 August 2007"
++#define DRIVER_VERSION		"20 November 2008"
+ 
+ static const char longname[] = DRIVER_DESC;
+ static const char shortname[] = DRIVER_NAME;
+@@ -341,6 +350,7 @@ static struct {
+ 
+ 	int		removable;
+ 	int		can_stall;
++	int		cdrom;
+ 
+ 	char		*transport_parm;
+ 	char		*protocol_parm;
+@@ -359,6 +369,7 @@ static struct {
+ 	.protocol_parm		= "SCSI",
+ 	.removable		= 0,
+ 	.can_stall		= 1,
++	.cdrom			= 0,
+ 	.vendor			= DRIVER_VENDOR_ID,
+ 	.product		= DRIVER_PRODUCT_ID,
+ 	.release		= 0xffff,	// Use controller chip type
+@@ -382,6 +393,9 @@ MODULE_PARM_DESC(removable, "true to simulate removable media");
+ module_param_named(stall, mod_data.can_stall, bool, S_IRUGO);
+ MODULE_PARM_DESC(stall, "false to prevent bulk stalls");
+ 
++module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO);
++MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk");
++
+ 
+ /* In the non-TEST version, only the module parameters listed above
+  * are available. */
+@@ -411,6 +425,10 @@ MODULE_PARM_DESC(buflen, "I/O buffer size");
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++/* SCSI device types */
++#define TYPE_DISK	0x00
++#define TYPE_CDROM	0x05
++
+ /* USB protocol value = the transport method */
+ #define USB_PR_CBI	0x00		// Control/Bulk/Interrupt
+ #define USB_PR_CB	0x01		// Control/Bulk w/o interrupt
+@@ -487,6 +505,8 @@ struct interrupt_data {
+ #define SC_READ_12			0xa8
+ #define SC_READ_CAPACITY		0x25
+ #define SC_READ_FORMAT_CAPACITIES	0x23
++#define SC_READ_HEADER			0x44
++#define SC_READ_TOC			0x43
+ #define SC_RELEASE			0x17
+ #define SC_REQUEST_SENSE		0x03
+ #define SC_RESERVE			0x16
+@@ -2006,23 +2026,28 @@ static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh)
+ 	u8	*buf = (u8 *) bh->buf;
+ 
+ 	static char vendor_id[] = "Linux   ";
+-	static char product_id[] = "File-Stor Gadget";
++	static char product_disk_id[] = "File-Stor Gadget";
++	static char product_cdrom_id[] = "File-CD Gadget  ";
+ 
+ 	if (!fsg->curlun) {		// Unsupported LUNs are okay
+ 		fsg->bad_lun_okay = 1;
+ 		memset(buf, 0, 36);
+ 		buf[0] = 0x7f;		// Unsupported, no device-type
++		buf[4] = 31;		// Additional length
+ 		return 36;
+ 	}
+ 
+-	memset(buf, 0, 8);	// Non-removable, direct-access device
++	memset(buf, 0, 8);
++	buf[0] = (mod_data.cdrom ? TYPE_CDROM : TYPE_DISK);
+ 	if (mod_data.removable)
+ 		buf[1] = 0x80;
+ 	buf[2] = 2;		// ANSI SCSI level 2
+ 	buf[3] = 2;		// SCSI-2 INQUIRY data format
+ 	buf[4] = 31;		// Additional length
+ 				// No special options
+-	sprintf(buf + 8, "%-8s%-16s%04x", vendor_id, product_id,
++	sprintf(buf + 8, "%-8s%-16s%04x", vendor_id,
++			(mod_data.cdrom ? product_cdrom_id :
++				product_disk_id),
+ 			mod_data.release);
+ 	return 36;
+ }
+@@ -2101,6 +2126,75 @@ static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh)
+ }
+ 
+ 
++static void store_cdrom_address(u8 *dest, int msf, u32 addr)
++{
++	if (msf) {
++		/* Convert to Minutes-Seconds-Frames */
++		addr >>= 2;		/* Convert to 2048-byte frames */
++		addr += 2*75;		/* Lead-in occupies 2 seconds */
++		dest[3] = addr % 75;	/* Frames */
++		addr /= 75;
++		dest[2] = addr % 60;	/* Seconds */
++		addr /= 60;
++		dest[1] = addr;		/* Minutes */
++		dest[0] = 0;		/* Reserved */
++	} else {
++		/* Absolute sector */
++		put_be32(dest, addr);
++	}
++}
++
++static int do_read_header(struct fsg_dev *fsg, struct fsg_buffhd *bh)
++{
++	struct lun	*curlun = fsg->curlun;
++	int		msf = fsg->cmnd[1] & 0x02;
++	u32		lba = get_be32(&fsg->cmnd[2]);
++	u8		*buf = (u8 *) bh->buf;
++
++	if ((fsg->cmnd[1] & ~0x02) != 0) {		/* Mask away MSF */
++		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
++		return -EINVAL;
++	}
++	if (lba >= curlun->num_sectors) {
++		curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
++		return -EINVAL;
++	}
++
++	memset(buf, 0, 8);
++	buf[0] = 0x01;		/* 2048 bytes of user data, rest is EC */
++	store_cdrom_address(&buf[4], msf, lba);
++	return 8;
++}
++
++
++static int do_read_toc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
++{
++	struct lun	*curlun = fsg->curlun;
++	int		msf = fsg->cmnd[1] & 0x02;
++	int		start_track = fsg->cmnd[6];
++	u8		*buf = (u8 *) bh->buf;
++
++	if ((fsg->cmnd[1] & ~0x02) != 0 ||		/* Mask away MSF */
++			start_track > 1) {
++		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
++		return -EINVAL;
++	}
++
++	memset(buf, 0, 20);
++	buf[1] = (20-2);		/* TOC data length */
++	buf[2] = 1;			/* First track number */
++	buf[3] = 1;			/* Last track number */
++	buf[5] = 0x16;			/* Data track, copying allowed */
++	buf[6] = 0x01;			/* Only track is number 1 */
++	store_cdrom_address(&buf[8], msf, 0);
++
++	buf[13] = 0x16;			/* Lead-out track is data */
++	buf[14] = 0xAA;			/* Lead-out track number */
++	store_cdrom_address(&buf[16], msf, curlun->num_sectors);
++	return 20;
++}
++
++
+ static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
+ {
+ 	struct lun	*curlun = fsg->curlun;
+@@ -2848,6 +2942,26 @@ static int do_scsi_command(struct fsg_dev *fsg)
+ 			reply = do_read_capacity(fsg, bh);
+ 		break;
+ 
++	case SC_READ_HEADER:
++		if (!mod_data.cdrom)
++			goto unknown_cmnd;
++		fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]);
++		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
++				(3<<7) | (0x1f<<1), 1,
++				"READ HEADER")) == 0)
++			reply = do_read_header(fsg, bh);
++		break;
++
++	case SC_READ_TOC:
++		if (!mod_data.cdrom)
++			goto unknown_cmnd;
++		fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]);
++		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
++				(7<<6) | (1<<1), 1,
++				"READ TOC")) == 0)
++			reply = do_read_toc(fsg, bh);
++		break;
++
+ 	case SC_READ_FORMAT_CAPACITIES:
+ 		fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]);
+ 		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
+@@ -2933,6 +3047,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
+ 		// Fall through
+ 
+ 	default:
++ unknown_cmnd:
+ 		fsg->data_size_from_cmnd = 0;
+ 		sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]);
+ 		if ((reply = check_command(fsg, fsg->cmnd_size,
+@@ -3498,6 +3613,7 @@ static int open_backing_file(struct lun *curlun, const char *filename)
+ 	struct inode			*inode = NULL;
+ 	loff_t				size;
+ 	loff_t				num_sectors;
++	loff_t				min_sectors;
+ 
+ 	/* R/W if we can, R/O if we must */
+ 	ro = curlun->ro;
+@@ -3541,8 +3657,19 @@ static int open_backing_file(struct lun *curlun, const char *filename)
+ 		rc = (int) size;
+ 		goto out;
+ 	}
+-	num_sectors = size >> 9;	// File size in 512-byte sectors
+-	if (num_sectors == 0) {
++	num_sectors = size >> 9;	// File size in 512-byte blocks
++	min_sectors = 1;
++	if (mod_data.cdrom) {
++		num_sectors &= ~3;	// Reduce to a multiple of 2048
++		min_sectors = 300*4;	// Smallest track is 300 frames
++		if (num_sectors >= 256*60*75*4) {
++			num_sectors = (256*60*75 - 1) * 4;
++			LINFO(curlun, "file too big: %s\n", filename);
++			LINFO(curlun, "using only first %d blocks\n",
++					(int) num_sectors);
++		}
++	}
++	if (num_sectors < min_sectors) {
+ 		LINFO(curlun, "file too small: %s\n", filename);
+ 		rc = -ETOOSMALL;
+ 		goto out;
+@@ -3845,9 +3972,12 @@ static int __init fsg_bind(struct usb_gadget *gadget)
+ 		goto out;
+ 
+ 	if (mod_data.removable) {	// Enable the store_xxx attributes
+-		dev_attr_ro.attr.mode = dev_attr_file.attr.mode = 0644;
+-		dev_attr_ro.store = store_ro;
++		dev_attr_file.attr.mode = 0644;
+ 		dev_attr_file.store = store_file;
++		if (!mod_data.cdrom) {
++			dev_attr_ro.attr.mode = 0644;
++			dev_attr_ro.store = store_ro;
++		}
+ 	}
+ 
+ 	/* Find out how many LUNs there should be */
+@@ -3872,6 +4002,8 @@ static int __init fsg_bind(struct usb_gadget *gadget)
+ 	for (i = 0; i < fsg->nluns; ++i) {
+ 		curlun = &fsg->luns[i];
+ 		curlun->ro = mod_data.ro[i];
++		if (mod_data.cdrom)
++			curlun->ro = 1;
+ 		curlun->dev.release = lun_release;
+ 		curlun->dev.parent = &gadget->dev;
+ 		curlun->dev.driver = &fsg_driver.driver;
+@@ -4031,9 +4163,9 @@ static int __init fsg_bind(struct usb_gadget *gadget)
+ 			mod_data.protocol_name, mod_data.protocol_type);
+ 	DBG(fsg, "VendorID=x%04x, ProductID=x%04x, Release=x%04x\n",
+ 			mod_data.vendor, mod_data.product, mod_data.release);
+-	DBG(fsg, "removable=%d, stall=%d, buflen=%u\n",
++	DBG(fsg, "removable=%d, stall=%d, cdrom=%d, buflen=%u\n",
+ 			mod_data.removable, mod_data.can_stall,
+-			mod_data.buflen);
++			mod_data.cdrom, mod_data.buflen);
+ 	DBG(fsg, "I/O thread pid: %d\n", task_pid_nr(fsg->thread_task));
+ 
+ 	set_bit(REGISTERED, &fsg->atomic_bitflags);

commit a658367dae9dc572480f41817dbe1088a1a049ee
+Author: Alan Stern 
+Date:   Tue Nov 18 14:08:38 2008 -0500
+
+    USB: usb-storage: remove us->sensebuf
+    
+    This patch (as1171) removes us->sensebuf, since it isn't used anywhere.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index eb1a53a3e5ca..099e07c6af7b 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -474,12 +474,6 @@ static int associate_dev(struct us_data *us, struct usb_interface *intf)
+ 		US_DEBUGP("I/O buffer allocation failed\n");
+ 		return -ENOMEM;
+ 	}
+-
+-	us->sensebuf = kmalloc(US_SENSE_SIZE, GFP_KERNEL);
+-	if (!us->sensebuf) {
+-		US_DEBUGP("Sense buffer allocation failed\n");
+-		return -ENOMEM;
+-	}
+ 	return 0;
+ }
+ 
+@@ -875,8 +869,6 @@ static void dissociate_dev(struct us_data *us)
+ {
+ 	US_DEBUGP("-- %s\n", __func__);
+ 
+-	kfree(us->sensebuf);
+-
+ 	/* Free the device-related DMA-mapped buffers */
+ 	if (us->cr)
+ 		usb_buffer_free(us->pusb_dev, sizeof(*us->cr), us->cr,
+diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
+index a4ad73bd832d..e4674fc715e6 100644
+--- a/drivers/usb/storage/usb.h
++++ b/drivers/usb/storage/usb.h
+@@ -138,7 +138,6 @@ struct us_data {
+ 	struct usb_ctrlrequest	*cr;		 /* control requests	 */
+ 	struct usb_sg_request	current_sg;	 /* scatter-gather req.  */
+ 	unsigned char		*iobuf;		 /* I/O buffer		 */
+-	unsigned char		*sensebuf;	 /* sense data buffer	 */
+ 	dma_addr_t		cr_dma;		 /* buffer DMA addresses */
+ 	dma_addr_t		iobuf_dma;
+ 	struct task_struct	*ctl_thread;	 /* the control thread   */

commit f9dc8f99e5846606b1f475b3905eaf5ae1017c50
+Author: Alan Stern 
+Date:   Tue Nov 18 14:08:07 2008 -0500
+
+    usb-storage: clean up unusual_devs.h
+    
+    This patch (as1170) removes some duplicate entries in unusual_devs.h
+    and rearranges a few others to put the list in proper numerical order.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 8a0eb00024d4..0e0ebf275a22 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -188,6 +188,14 @@ UNUSUAL_DEV(  0x0421, 0x006a, 0x0000, 0x0701,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_FIX_CAPACITY ),
+ 
++/* Submitted by Ricky Wong Yung Fei  */
++/* Nokia 7610 Supernova - Too many sectors reported in usb storage mode */
++UNUSUAL_DEV(  0x0421, 0x00f5, 0x0000, 0x0470,
++		"Nokia",
++		"7610 Supernova",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_FIX_CAPACITY ),
++
+ /* Reported by Mario Rettig  */
+ UNUSUAL_DEV(  0x0421, 0x042e, 0x0100, 0x0100,
+ 		"Nokia",
+@@ -274,21 +282,6 @@ UNUSUAL_DEV(  0x0421, 0x04fa, 0x0550, 0x0660,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_FIX_CAPACITY ),
+ 
+-/* Patch for Nokia 5310 capacity */
+-UNUSUAL_DEV(  0x0421, 0x006a, 0x0000, 0x0591,
+-	"Nokia",
+-	"5310",
+-	US_SC_DEVICE, US_PR_DEVICE, NULL,
+-	US_FL_FIX_CAPACITY ),
+-
+-/* Submitted by Ricky Wong Yung Fei  */
+-/* Nokia 7610 Supernova - Too many sectors reported in usb storage mode */
+-UNUSUAL_DEV(  0x0421, 0x00f5, 0x0000, 0x0470,
+-	"Nokia",
+-	"7610 Supernova",
+-	US_SC_DEVICE, US_PR_DEVICE, NULL,
+-	US_FL_FIX_CAPACITY ),
+-
+ /* Reported by Olaf Hering  from novell bug #105878 */
+ UNUSUAL_DEV(  0x0424, 0x0fdc, 0x0210, 0x0210,
+ 		"SMSC",
+@@ -395,6 +388,15 @@ UNUSUAL_DEV(  0x04a4, 0x0004, 0x0001, 0x0001,
+ 		"DVD-CAM DZ-MV100A Camcorder",
+ 		US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN),
+ 
++/* BENQ DC5330
++ * Reported by Manuel Fombuena  and
++ * Frank Copeland  */
++UNUSUAL_DEV(  0x04a5, 0x3010, 0x0100, 0x0100,
++		"Tekom Technologies, Inc",
++		"300_CAMERA",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_IGNORE_RESIDUE ),
++
+ /* Patch for Nikon coolpix 2000
+  * Submitted by Fabien Cosse */
+ UNUSUAL_DEV(  0x04b0, 0x0301, 0x0010, 0x0010,
+@@ -487,15 +489,6 @@ UNUSUAL_DEV(  0x04b3, 0x4001, 0x0110, 0x0110,
+ 		US_SC_DEVICE, US_PR_CB, NULL,
+ 		US_FL_MAX_SECTORS_MIN),
+ 
+-/* BENQ DC5330
+- * Reported by Manuel Fombuena  and
+- * Frank Copeland  */
+-UNUSUAL_DEV(  0x04a5, 0x3010, 0x0100, 0x0100,
+-		"Tekom Technologies, Inc",
+-		"300_CAMERA",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_IGNORE_RESIDUE ),
+-
+ #ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB
+ /* CY7C68300 : support atacb */
+ UNUSUAL_DEV(  0x04b4, 0x6830, 0x0000, 0x9999,
+@@ -814,15 +807,15 @@ UNUSUAL_DEV(  0x054c, 0x006d, 0x0000, 0x9999,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_FIX_INQUIRY ),
+ 
+-/* Submitted by Mike Alborn  */
+-UNUSUAL_DEV(  0x054c, 0x016a, 0x0000, 0x9999,
++/* Submitted by Frank Engel  */
++UNUSUAL_DEV(  0x054c, 0x0099, 0x0000, 0x9999,
+ 		"Sony",
+ 		"PEG Mass Storage",
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_FIX_INQUIRY ),
+-		
+-/* Submitted by Frank Engel  */
+-UNUSUAL_DEV(  0x054c, 0x0099, 0x0000, 0x9999,
++
++/* Submitted by Mike Alborn  */
++UNUSUAL_DEV(  0x054c, 0x016a, 0x0000, 0x9999,
+ 		"Sony",
+ 		"PEG Mass Storage",
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+@@ -1357,17 +1350,6 @@ UNUSUAL_DEV(  0x0851, 0x1543, 0x0200, 0x0200,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_NOT_LOCKABLE),
+ 
+-/* Andrew Lunn 
+- * PanDigital Digital Picture Frame. Does not like ALLOW_MEDIUM_REMOVAL
+- * on LUN 4.
+- * Note: Vend:Prod clash with "Ltd Maxell WS30 Slim Digital Camera"
+-*/
+-UNUSUAL_DEV(  0x0851, 0x1543, 0x0200, 0x0200,
+-		"PanDigital",
+-		"Photo Frame",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_NOT_LOCKABLE),
+-
+ /* Submitted by Jan De Luyck  */
+ UNUSUAL_DEV(  0x08bd, 0x1100, 0x0000, 0x0000,
+ 		"CITIZEN",
+@@ -1493,6 +1475,16 @@ UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff,
+ 		US_FL_SINGLE_LUN ),
+ #endif
+ 
++/*
++ * Pete Zaitcev , bz#164688.
++ * The device blatantly ignores LUN and returns 1 in GetMaxLUN.
++ */
++UNUSUAL_DEV( 0x0c45, 0x1060, 0x0100, 0x0100,
++		"Unknown",
++		"Unknown",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_SINGLE_LUN ),
++
+ /* Submitted by: Nick Sillik 
+  * Needed for OneTouch extension to usb-storage
+  *
+@@ -1510,16 +1502,6 @@ UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff,
+ 			0),
+ #endif
+ 
+-/*
+- * Pete Zaitcev , bz#164688.
+- * The device blatantly ignores LUN and returns 1 in GetMaxLUN.
+- */
+-UNUSUAL_DEV( 0x0c45, 0x1060, 0x0100, 0x0100,
+-		"Unknown",
+-		"Unknown",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_SINGLE_LUN ),
+-
+ /* Submitted by Joris Struyve  */
+ UNUSUAL_DEV( 0x0d96, 0x410a, 0x0001, 0xffff,
+ 		"Medion",
+@@ -1666,13 +1648,6 @@ UNUSUAL_DEV(  0x0fce, 0xe030, 0x0000, 0x0000,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ),
+ 
+-/* Reported by Ricardo Barberis  */
+-UNUSUAL_DEV(  0x0fce, 0xe092, 0x0000, 0x0000,
+-		"Sony Ericsson",
+-		"P1i",
+-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_IGNORE_RESIDUE ),
+-
+ /* Reported by Emmanuel Vasilakis  */
+ UNUSUAL_DEV(  0x0fce, 0xe031, 0x0000, 0x0000,
+ 		"Sony Ericsson",
+@@ -1680,6 +1655,13 @@ UNUSUAL_DEV(  0x0fce, 0xe031, 0x0000, 0x0000,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
+ 
++/* Reported by Ricardo Barberis  */
++UNUSUAL_DEV(  0x0fce, 0xe092, 0x0000, 0x0000,
++		"Sony Ericsson",
++		"P1i",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_IGNORE_RESIDUE ),
++
+ /* Reported by Kevin Cernekee 
+  * Tested on hardware version 1.10.
+  * Entry is needed only for the initializer function override.

commit 6cd132015d92356b1287f6f3377a3ad955b6cf2f
+Author: Alan Stern 
+Date:   Thu Nov 13 15:08:30 2008 -0500
+
+    USB: announce new devices earlier
+    
+    This patch (as1166) changes usb_new_device().  Now new devices will be
+    announced in the log _prior_ to being registered; this way the "new
+    device" lines will appear before all the output from driver probing,
+    which seems much more logical.
+    
+    Also, the patch adds a call to usb_stop_pm() to the failure pathway,
+    so that the parent's count of unsuspended children will remain correct
+    if registration fails.  In order for this to work properly, the code
+    to increment that count has to be moved forward, before the first
+    point where a failure can occur.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index e65881899c8f..ff066edf4dca 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1636,6 +1636,10 @@ int usb_new_device(struct usb_device *udev)
+ {
+ 	int err;
+ 
++	/* Increment the parent's count of unsuspended children */
++	if (udev->parent)
++		usb_autoresume_device(udev->parent);
++
+ 	usb_detect_quirks(udev);		/* Determine quirks */
+ 	err = usb_configure_device(udev);	/* detect & probe dev/intfs */
+ 	if (err < 0)
+@@ -1644,9 +1648,8 @@ int usb_new_device(struct usb_device *udev)
+ 	udev->dev.devt = MKDEV(USB_DEVICE_MAJOR,
+ 			(((udev->bus->busnum-1) * 128) + (udev->devnum-1)));
+ 
+-	/* Increment the parent's count of unsuspended children */
+-	if (udev->parent)
+-		usb_autoresume_device(udev->parent);
++	/* Tell the world! */
++	announce_device(udev);
+ 
+ 	/* Register the device.  The device driver is responsible
+ 	 * for adding the device files to sysfs and for configuring
+@@ -1660,13 +1663,11 @@ int usb_new_device(struct usb_device *udev)
+ 
+ 	/* put device-specific files into sysfs */
+ 	usb_create_sysfs_dev_files(udev);
+-
+-	/* Tell the world! */
+-	announce_device(udev);
+ 	return err;
+ 
+ fail:
+ 	usb_set_device_state(udev, USB_STATE_NOTATTACHED);
++	usb_stop_pm(udev);
+ 	return err;
+ }
+ 

commit 9ac39f28b5237a629e41ccfc1f73d3a55723045c
+Author: Alan Stern 
+Date:   Wed Nov 12 16:19:49 2008 -0500
+
+    USB: add asynchronous autosuspend/autoresume support
+    
+    This patch (as1160b) adds support routines for asynchronous autosuspend
+    and autoresume, with accompanying documentation updates.  There
+    already are several potential users of this interface, and others are
+    likely to arise as autosuspend support becomes more widespread.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt
+index e48ea1d51010..ad642615ad4c 100644
+--- a/Documentation/usb/power-management.txt
++++ b/Documentation/usb/power-management.txt
+@@ -313,11 +313,13 @@ three of the methods listed above.  In addition, a driver indicates
+ that it supports autosuspend by setting the .supports_autosuspend flag
+ in its usb_driver structure.  It is then responsible for informing the
+ USB core whenever one of its interfaces becomes busy or idle.  The
+-driver does so by calling these three functions:
++driver does so by calling these five functions:
+ 
+ 	int  usb_autopm_get_interface(struct usb_interface *intf);
+ 	void usb_autopm_put_interface(struct usb_interface *intf);
+ 	int  usb_autopm_set_interface(struct usb_interface *intf);
++	int  usb_autopm_get_interface_async(struct usb_interface *intf);
++	void usb_autopm_put_interface_async(struct usb_interface *intf);
+ 
+ The functions work by maintaining a counter in the usb_interface
+ structure.  When intf->pm_usage_count is > 0 then the interface is
+@@ -330,10 +332,12 @@ associated with the device itself rather than any of its interfaces.
+ This field is used only by the USB core.)
+ 
+ The driver owns intf->pm_usage_count; it can modify the value however
+-and whenever it likes.  A nice aspect of the usb_autopm_* routines is
+-that the changes they make are protected by the usb_device structure's
+-PM mutex (udev->pm_mutex); however drivers may change pm_usage_count
+-without holding the mutex.
++and whenever it likes.  A nice aspect of the non-async usb_autopm_*
++routines is that the changes they make are protected by the usb_device
++structure's PM mutex (udev->pm_mutex); however drivers may change
++pm_usage_count without holding the mutex.  Drivers using the async
++routines are responsible for their own synchronization and mutual
++exclusion.
+ 
+ 	usb_autopm_get_interface() increments pm_usage_count and
+ 	attempts an autoresume if the new value is > 0 and the
+@@ -348,6 +352,14 @@ without holding the mutex.
+ 	is suspended, and it attempts an autosuspend if the value is
+ 	<= 0 and the device isn't suspended.
+ 
++	usb_autopm_get_interface_async() and
++	usb_autopm_put_interface_async() do almost the same things as
++	their non-async counterparts.  The differences are: they do
++	not acquire the PM mutex, and they use a workqueue to do their
++	jobs.  As a result they can be called in an atomic context,
++	such as an URB's completion handler, but when they return the
++	device will not generally not yet be in the desired state.
++
+ There also are a couple of utility routines drivers can use:
+ 
+ 	usb_autopm_enable() sets pm_usage_cnt to 0 and then calls
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 8c081308b0e2..23b3c7e79d4b 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1341,6 +1341,19 @@ void usb_autosuspend_work(struct work_struct *work)
+ 	usb_autopm_do_device(udev, 0);
+ }
+ 
++/* usb_autoresume_work - callback routine to autoresume a USB device */
++void usb_autoresume_work(struct work_struct *work)
++{
++	struct usb_device *udev =
++		container_of(work, struct usb_device, autoresume);
++
++	/* Wake it up, let the drivers do their thing, and then put it
++	 * back to sleep.
++	 */
++	if (usb_autopm_do_device(udev, 1) == 0)
++		usb_autopm_do_device(udev, -1);
++}
++
+ /**
+  * usb_autosuspend_device - delayed autosuspend of a USB device and its interfaces
+  * @udev: the usb_device to autosuspend
+@@ -1491,6 +1504,45 @@ void usb_autopm_put_interface(struct usb_interface *intf)
+ }
+ EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
+ 
++/**
++ * usb_autopm_put_interface_async - decrement a USB interface's PM-usage counter
++ * @intf: the usb_interface whose counter should be decremented
++ *
++ * This routine does essentially the same thing as
++ * usb_autopm_put_interface(): it decrements @intf's usage counter and
++ * queues a delayed autosuspend request if the counter is <= 0.  The
++ * difference is that it does not acquire the device's pm_mutex;
++ * callers must handle all synchronization issues themselves.
++ *
++ * Typically a driver would call this routine during an URB's completion
++ * handler, if no more URBs were pending.
++ *
++ * This routine can run in atomic context.
++ */
++void usb_autopm_put_interface_async(struct usb_interface *intf)
++{
++	struct usb_device	*udev = interface_to_usbdev(intf);
++	int			status = 0;
++
++	if (intf->condition == USB_INTERFACE_UNBOUND) {
++		status = -ENODEV;
++	} else {
++		udev->last_busy = jiffies;
++		--intf->pm_usage_cnt;
++		if (udev->autosuspend_disabled || udev->autosuspend_delay < 0)
++			status = -EPERM;
++		else if (intf->pm_usage_cnt <= 0 &&
++				!timer_pending(&udev->autosuspend.timer)) {
++			queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
++					round_jiffies_relative(
++						udev->autosuspend_delay));
++		}
++	}
++	dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
++			__func__, status, intf->pm_usage_cnt);
++}
++EXPORT_SYMBOL_GPL(usb_autopm_put_interface_async);
++
+ /**
+  * usb_autopm_get_interface - increment a USB interface's PM-usage counter
+  * @intf: the usb_interface whose counter should be incremented
+@@ -1536,6 +1588,37 @@ int usb_autopm_get_interface(struct usb_interface *intf)
+ }
+ EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
+ 
++/**
++ * usb_autopm_get_interface_async - increment a USB interface's PM-usage counter
++ * @intf: the usb_interface whose counter should be incremented
++ *
++ * This routine does much the same thing as
++ * usb_autopm_get_interface(): it increments @intf's usage counter and
++ * queues an autoresume request if the result is > 0.  The differences
++ * are that it does not acquire the device's pm_mutex (callers must
++ * handle all synchronization issues themselves), and it does not
++ * autoresume the device directly (it only queues a request).  After a
++ * successful call, the device will generally not yet be resumed.
++ *
++ * This routine can run in atomic context.
++ */
++int usb_autopm_get_interface_async(struct usb_interface *intf)
++{
++	struct usb_device	*udev = interface_to_usbdev(intf);
++	int			status = 0;
++
++	if (intf->condition == USB_INTERFACE_UNBOUND)
++		status = -ENODEV;
++	else if (udev->autoresume_disabled)
++		status = -EPERM;
++	else if (++intf->pm_usage_cnt > 0 && udev->state == USB_STATE_SUSPENDED)
++		queue_work(ksuspend_usb_wq, &udev->autoresume);
++	dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
++			__func__, status, intf->pm_usage_cnt);
++	return status;
++}
++EXPORT_SYMBOL_GPL(usb_autopm_get_interface_async);
++
+ /**
+  * usb_autopm_set_interface - set a USB interface's autosuspend state
+  * @intf: the usb_interface whose state should be set
+@@ -1563,6 +1646,9 @@ EXPORT_SYMBOL_GPL(usb_autopm_set_interface);
+ void usb_autosuspend_work(struct work_struct *work)
+ {}
+ 
++void usb_autoresume_work(struct work_struct *work)
++{}
++
+ #endif /* CONFIG_USB_SUSPEND */
+ 
+ /**
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index b19cbfcd51da..95fb3104ba4f 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1374,8 +1374,9 @@ static void usb_stop_pm(struct usb_device *udev)
+ 		usb_autosuspend_device(udev->parent);
+ 	usb_pm_unlock(udev);
+ 
+-	/* Stop any autosuspend requests already submitted */
+-	cancel_rearming_delayed_work(&udev->autosuspend);
++	/* Stop any autosuspend or autoresume requests already submitted */
++	cancel_delayed_work_sync(&udev->autosuspend);
++	cancel_work_sync(&udev->autoresume);
+ }
+ 
+ #else
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 400fa4cc9a34..44f2fc750b6d 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -402,6 +402,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
+ #ifdef	CONFIG_PM
+ 	mutex_init(&dev->pm_mutex);
+ 	INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work);
++	INIT_WORK(&dev->autoresume, usb_autoresume_work);
+ 	dev->autosuspend_delay = usb_autosuspend_delay * HZ;
+ 	dev->connect_time = jiffies;
+ 	dev->active_duration = -jiffies;
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 9a1a45ac3add..b60ebb4de1a8 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -45,6 +45,7 @@ extern int usb_suspend(struct device *dev, pm_message_t msg);
+ extern int usb_resume(struct device *dev);
+ 
+ extern void usb_autosuspend_work(struct work_struct *work);
++extern void usb_autoresume_work(struct work_struct *work);
+ extern int usb_port_suspend(struct usb_device *dev);
+ extern int usb_port_resume(struct usb_device *dev);
+ extern int usb_external_suspend_device(struct usb_device *udev,
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index f72aa51f7bcd..859a88e6ce9c 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -398,6 +398,7 @@ struct usb_tt;
+  * @urbnum: number of URBs submitted for the whole device
+  * @active_duration: total time device is not suspended
+  * @autosuspend: for delayed autosuspends
++ * @autoresume: for autoresumes requested while in_interrupt
+  * @pm_mutex: protects PM operations
+  * @last_busy: time of last use
+  * @autosuspend_delay: in jiffies
+@@ -476,6 +477,7 @@ struct usb_device {
+ 
+ #ifdef CONFIG_PM
+ 	struct delayed_work autosuspend;
++	struct work_struct autoresume;
+ 	struct mutex pm_mutex;
+ 
+ 	unsigned long last_busy;
+@@ -513,6 +515,8 @@ extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id);
+ extern int usb_autopm_set_interface(struct usb_interface *intf);
+ extern int usb_autopm_get_interface(struct usb_interface *intf);
+ extern void usb_autopm_put_interface(struct usb_interface *intf);
++extern int usb_autopm_get_interface_async(struct usb_interface *intf);
++extern void usb_autopm_put_interface_async(struct usb_interface *intf);
+ 
+ static inline void usb_autopm_enable(struct usb_interface *intf)
+ {
+@@ -539,8 +543,13 @@ static inline int usb_autopm_set_interface(struct usb_interface *intf)
+ static inline int usb_autopm_get_interface(struct usb_interface *intf)
+ { return 0; }
+ 
++static inline int usb_autopm_get_interface_async(struct usb_interface *intf)
++{ return 0; }
++
+ static inline void usb_autopm_put_interface(struct usb_interface *intf)
+ { }
++static inline void usb_autopm_put_interface_async(struct usb_interface *intf)
++{ }
+ static inline void usb_autopm_enable(struct usb_interface *intf)
+ { }
+ static inline void usb_autopm_disable(struct usb_interface *intf)

commit d4f373e57d3916814110968c5ea1155a8d972b5a
+Author: Alan Stern 
+Date:   Mon Nov 10 14:07:45 2008 -0500
+
+    USB: usb-storage: add "quirks=" module parameter
+    
+    This patch (as1163b) adds a "quirks=" module parameter to usb-storage.
+    This will allow people to make short-term changes to their
+    unusual_devs list without rebuilding the entire driver.  Testing will
+    become much easier, and less-sophisticated users will be able to
+    access their buggy devices after a simple config-file change instead
+    of having to wait for a new kernel release.
+    
+    The patch also adds a documentation entry for usb-storage's
+    "delay_use" parameter, which has been around for years but but was
+    never listed among the kernel parameters.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
+index 0b3f6711d2f1..8eb6e35405cd 100644
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -91,6 +91,7 @@ parameter is applicable:
+ 	SUSPEND	System suspend states are enabled.
+ 	FTRACE	Function tracing enabled.
+ 	TS	Appropriate touchscreen support is enabled.
++	UMS	USB Mass Storage support is enabled.
+ 	USB	USB support is enabled.
+ 	USBHID	USB Human Interface Device support is enabled.
+ 	V4L	Video For Linux support is enabled.
+@@ -2383,6 +2384,34 @@ and is between 256 and 4096 characters. It is defined in the file
+ 	usbhid.mousepoll=
+ 			[USBHID] The interval which mice are to be polled at.
+ 
++	usb-storage.delay_use=
++			[UMS] The delay in seconds before a new device is
++			scanned for Logical Units (default 5).
++
++	usb-storage.quirks=
++			[UMS] A list of quirks entries to supplement or
++			override the built-in unusual_devs list.  List
++			entries are separated by commas.  Each entry has
++			the form VID:PID:Flags where VID and PID are Vendor
++			and Product ID values (4-digit hex numbers) and
++			Flags is a set of characters, each corresponding
++			to a common usb-storage quirk flag as follows:
++				c = FIX_CAPACITY (decrease the reported
++					device capacity by one sector);
++				i = IGNORE_DEVICE (don't bind to this
++					device);
++				l = NOT_LOCKABLE (don't try to lock and
++					unlock ejectable media);
++				m = MAX_SECTORS_64 (don't transfer more
++					than 64 sectors = 32 KB at a time);
++				r = IGNORE_RESIDUE (the device reports
++					bogus residue values);
++				s = SINGLE_LUN (the device has only one
++					Logical Unit);
++				w = NO_WP_DETECT (don't test whether the
++					medium is write-protected).
++			Example: quirks=0419:aaf5:rl,0421:0433:rc
++
+ 	add_efi_memmap	[EFI; x86-32,X86-64] Include EFI memory map in
+ 			kernel's map of available physical RAM.
+ 
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 27016fd2cad1..eb1a53a3e5ca 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -113,6 +113,16 @@ static unsigned int delay_use = 5;
+ module_param(delay_use, uint, S_IRUGO | S_IWUSR);
+ MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device");
+ 
++static char *quirks;
++module_param(quirks, charp, S_IRUGO);
++MODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks");
++
++struct quirks_entry {
++	u16	vid, pid;
++	u32	fflags;
++};
++static struct quirks_entry *quirks_list, *quirks_end;
++
+ 
+ /*
+  * The entries in this table correspond, line for line,
+@@ -473,6 +483,30 @@ static int associate_dev(struct us_data *us, struct usb_interface *intf)
+ 	return 0;
+ }
+ 
++/* Adjust device flags based on the "quirks=" module parameter */
++static void adjust_quirks(struct us_data *us)
++{
++	u16 vid, pid;
++	struct quirks_entry *q;
++	unsigned int mask = (US_FL_FIX_CAPACITY | US_FL_IGNORE_DEVICE |
++			US_FL_NOT_LOCKABLE | US_FL_MAX_SECTORS_64 |
++			US_FL_IGNORE_RESIDUE | US_FL_SINGLE_LUN |
++			US_FL_NO_WP_DETECT);
++
++	vid = le16_to_cpu(us->pusb_dev->descriptor.idVendor);
++	pid = le16_to_cpu(us->pusb_dev->descriptor.idProduct);
++
++	for (q = quirks_list; q != quirks_end; ++q) {
++		if (q->vid == vid && q->pid == pid) {
++			us->fflags = (us->fflags & ~mask) | q->fflags;
++			dev_info(&us->pusb_intf->dev, "Quirks match for "
++					"vid %04x pid %04x: %x\n",
++					vid, pid, q->fflags);
++			break;
++		}
++	}
++}
++
+ /* Find an unusual_dev descriptor (always succeeds in the current code) */
+ static struct us_unusual_dev *find_unusual(const struct usb_device_id *id)
+ {
+@@ -497,6 +531,7 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id)
+ 			idesc->bInterfaceProtocol :
+ 			unusual_dev->useTransport;
+ 	us->fflags = USB_US_ORIG_FLAGS(id->driver_info);
++	adjust_quirks(us);
+ 
+ 	if (us->fflags & US_FL_IGNORE_DEVICE) {
+ 		printk(KERN_INFO USB_STORAGE "device ignored\n");
+@@ -1061,10 +1096,88 @@ static struct usb_driver usb_storage_driver = {
+ 	.soft_unbind =	1,
+ };
+ 
++/* Works only for digits and letters, but small and fast */
++#define TOLOWER(x) ((x) | 0x20)
++
++static void __init parse_quirks(void)
++{
++	int n, i;
++	char *p;
++
++	if (!quirks)
++		return;
++
++	/* Count the ':' characters to get 2 * the number of entries */
++	n = 0;
++	for (p = quirks; *p; ++p) {
++		if (*p == ':')
++			++n;
++	}
++	n /= 2;
++	if (n == 0)
++		return;		/* Don't allocate 0 bytes */
++
++	quirks_list = kmalloc(n * sizeof(*quirks_list), GFP_KERNEL);
++	if (!quirks_list)
++		return;
++
++	p = quirks;
++	quirks_end = quirks_list;
++	for (i = 0; i < n && *p; ++i) {
++		unsigned f = 0;
++
++		/* Each entry consists of VID:PID:flags */
++		quirks_end->vid = simple_strtoul(p, &p, 16);
++		if (*p != ':')
++			goto skip_to_next;
++		quirks_end->pid = simple_strtoul(p+1, &p, 16);
++		if (*p != ':')
++			goto skip_to_next;
++
++		while (*++p && *p != ',') {
++			switch (TOLOWER(*p)) {
++			case 'c':
++				f |= US_FL_FIX_CAPACITY;
++				break;
++			case 'i':
++				f |= US_FL_IGNORE_DEVICE;
++				break;
++			case 'l':
++				f |= US_FL_NOT_LOCKABLE;
++				break;
++			case 'm':
++				f |= US_FL_MAX_SECTORS_64;
++				break;
++			case 'r':
++				f |= US_FL_IGNORE_RESIDUE;
++				break;
++			case 's':
++				f |= US_FL_SINGLE_LUN;
++				break;
++			case 'w':
++				f |= US_FL_NO_WP_DETECT;
++				break;
++			/* Ignore unrecognized flag characters */
++			}
++		}
++		quirks_end->fflags = f;
++		++quirks_end;
++
++ skip_to_next:
++		/* Entries are separated by commas */
++		while (*p) {
++			if (*p++ == ',')
++				break;
++		}
++	} /* for (i = 0; ...) */
++}
++
+ static int __init usb_stor_init(void)
+ {
+ 	int retval;
++
+ 	printk(KERN_INFO "Initializing USB Mass Storage driver...\n");
++	parse_quirks();
+ 
+ 	/* register the driver, return usb_register return code if error */
+ 	retval = usb_register(&usb_storage_driver);

commit 011b15df465745474e3ec85482633685933ed5a7
+Author: Alan Stern 
+Date:   Tue Nov 4 11:29:27 2008 -0500
+
+    USB: change interface to usb_lock_device_for_reset()
+    
+    This patch (as1161) changes the interface to
+    usb_lock_device_for_reset().  The existing interface is apparently not
+    very clear, judging from the fact that several of its callers don't
+    use it correctly.  The new interface always returns 0 for success and
+    it always requires the caller to unlock the device afterward.
+    
+    The new routine will not return immediately if it is called while the
+    driver's probe method is running.  Instead it will wait until the
+    probe is over and the device has been unlocked.  This shouldn't cause
+    any problems; I don't know of any cases where drivers call
+    usb_lock_device_for_reset() during probe.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Pete Zaitcev 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/block/ub.c b/drivers/block/ub.c
+index 048d71d244d7..12fb816db7b0 100644
+--- a/drivers/block/ub.c
++++ b/drivers/block/ub.c
+@@ -1579,7 +1579,7 @@ static void ub_reset_task(struct work_struct *work)
+ 	struct ub_dev *sc = container_of(work, struct ub_dev, reset_work);
+ 	unsigned long flags;
+ 	struct ub_lun *lun;
+-	int lkr, rc;
++	int rc;
+ 
+ 	if (!sc->reset) {
+ 		printk(KERN_WARNING "%s: Running reset unrequested\n",
+@@ -1597,10 +1597,11 @@ static void ub_reset_task(struct work_struct *work)
+ 	} else if (sc->dev->actconfig->desc.bNumInterfaces != 1) {
+ 		;
+ 	} else {
+-		if ((lkr = usb_lock_device_for_reset(sc->dev, sc->intf)) < 0) {
++		rc = usb_lock_device_for_reset(sc->dev, sc->intf);
++		if (rc < 0) {
+ 			printk(KERN_NOTICE
+ 			    "%s: usb_lock_device_for_reset failed (%d)\n",
+-			    sc->name, lkr);
++			    sc->name, rc);
+ 		} else {
+ 			rc = usb_reset_device(sc->dev);
+ 			if (rc < 0) {
+@@ -1608,9 +1609,7 @@ static void ub_reset_task(struct work_struct *work)
+ 				    "usb_lock_device_for_reset failed (%d)\n",
+ 				    sc->name, rc);
+ 			}
+-
+-			if (lkr)
+-				usb_unlock_device(sc->dev);
++			usb_unlock_device(sc->dev);
+ 		}
+ 	}
+ 
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index 03cb494af1c5..f0a0f72238ab 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -102,7 +102,7 @@ static void hid_reset(struct work_struct *work)
+ 	struct usbhid_device *usbhid =
+ 		container_of(work, struct usbhid_device, reset_work);
+ 	struct hid_device *hid = usbhid->hid;
+-	int rc_lock, rc = 0;
++	int rc = 0;
+ 
+ 	if (test_bit(HID_CLEAR_HALT, &usbhid->iofl)) {
+ 		dev_dbg(&usbhid->intf->dev, "clear halt\n");
+@@ -113,11 +113,10 @@ static void hid_reset(struct work_struct *work)
+ 
+ 	else if (test_bit(HID_RESET_PENDING, &usbhid->iofl)) {
+ 		dev_dbg(&usbhid->intf->dev, "resetting device\n");
+-		rc = rc_lock = usb_lock_device_for_reset(hid_to_usb_dev(hid), usbhid->intf);
+-		if (rc_lock >= 0) {
++		rc = usb_lock_device_for_reset(hid_to_usb_dev(hid), usbhid->intf);
++		if (rc == 0) {
+ 			rc = usb_reset_device(hid_to_usb_dev(hid));
+-			if (rc_lock)
+-				usb_unlock_device(hid_to_usb_dev(hid));
++			usb_unlock_device(hid_to_usb_dev(hid));
+ 		}
+ 		clear_bit(HID_RESET_PENDING, &usbhid->iofl);
+ 	}
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+index 8fb92ac78c7b..fa304e5f252a 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+@@ -3655,7 +3655,7 @@ void pvr2_hdw_device_reset(struct pvr2_hdw *hdw)
+ 	int ret;
+ 	pvr2_trace(PVR2_TRACE_INIT,"Performing a device reset...");
+ 	ret = usb_lock_device_for_reset(hdw->usb_dev,NULL);
+-	if (ret == 1) {
++	if (ret == 0) {
+ 		ret = usb_reset_device(hdw->usb_dev);
+ 		usb_unlock_device(hdw->usb_dev);
+ 	} else {
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 399e15fc5052..400fa4cc9a34 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -513,10 +513,7 @@ EXPORT_SYMBOL_GPL(usb_put_intf);
+  * disconnect; in some drivers (such as usb-storage) the disconnect()
+  * or suspend() method will block waiting for a device reset to complete.
+  *
+- * Returns a negative error code for failure, otherwise 1 or 0 to indicate
+- * that the device will or will not have to be unlocked.  (0 can be
+- * returned when an interface is given and is BINDING, because in that
+- * case the driver already owns the device lock.)
++ * Returns a negative error code for failure, otherwise 0.
+  */
+ int usb_lock_device_for_reset(struct usb_device *udev,
+ 			      const struct usb_interface *iface)
+@@ -527,16 +524,9 @@ int usb_lock_device_for_reset(struct usb_device *udev,
+ 		return -ENODEV;
+ 	if (udev->state == USB_STATE_SUSPENDED)
+ 		return -EHOSTUNREACH;
+-	if (iface) {
+-		switch (iface->condition) {
+-		case USB_INTERFACE_BINDING:
+-			return 0;
+-		case USB_INTERFACE_BOUND:
+-			break;
+-		default:
+-			return -EINTR;
+-		}
+-	}
++	if (iface && (iface->condition == USB_INTERFACE_UNBINDING ||
++			iface->condition == USB_INTERFACE_UNBOUND))
++		return -EINTR;
+ 
+ 	while (usb_trylock_device(udev) != 0) {
+ 
+@@ -550,10 +540,11 @@ int usb_lock_device_for_reset(struct usb_device *udev,
+ 			return -ENODEV;
+ 		if (udev->state == USB_STATE_SUSPENDED)
+ 			return -EHOSTUNREACH;
+-		if (iface && iface->condition != USB_INTERFACE_BOUND)
++		if (iface && (iface->condition == USB_INTERFACE_UNBINDING ||
++				iface->condition == USB_INTERFACE_UNBOUND))
+ 			return -EINTR;
+ 	}
+-	return 1;
++	return 0;
+ }
+ EXPORT_SYMBOL_GPL(usb_lock_device_for_reset);
+ 
+diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
+index 885867a86de8..4541dfcea88f 100644
+--- a/drivers/usb/image/microtek.c
++++ b/drivers/usb/image/microtek.c
+@@ -350,17 +350,16 @@ static int mts_scsi_abort(struct scsi_cmnd *srb)
+ static int mts_scsi_host_reset(struct scsi_cmnd *srb)
+ {
+ 	struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]);
+-	int result, rc;
++	int result;
+ 
+ 	MTS_DEBUG_GOT_HERE();
+ 	mts_debug_dump(desc);
+ 
+-	rc = usb_lock_device_for_reset(desc->usb_dev, desc->usb_intf);
+-	if (rc < 0)
+-		return FAILED;
+-	result = usb_reset_device(desc->usb_dev);
+-	if (rc)
++	result = usb_lock_device_for_reset(desc->usb_dev, desc->usb_intf);
++	if (result == 0) {
++		result = usb_reset_device(desc->usb_dev);
+ 		usb_unlock_device(desc->usb_dev);
++	}
+ 	return result ? FAILED : SUCCESS;
+ }
+ 
+diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+index 79108d5d3171..2058db41618c 100644
+--- a/drivers/usb/storage/transport.c
++++ b/drivers/usb/storage/transport.c
+@@ -1173,10 +1173,9 @@ int usb_stor_Bulk_reset(struct us_data *us)
+  */
+ int usb_stor_port_reset(struct us_data *us)
+ {
+-	int result, rc_lock;
++	int result;
+ 
+-	result = rc_lock =
+-		usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf);
++	result = usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf);
+ 	if (result < 0)
+ 		US_DEBUGP("unable to lock device for reset: %d\n", result);
+ 	else {
+@@ -1189,8 +1188,7 @@ int usb_stor_port_reset(struct us_data *us)
+ 			US_DEBUGP("usb_reset_device returns %d\n",
+ 					result);
+ 		}
+-		if (rc_lock)
+-			usb_unlock_device(us->pusb_dev);
++		usb_unlock_device(us->pusb_dev);
+ 	}
+ 	return result;
+ }

commit 92b0da1571353a39d07e0a592c4dda294cc2e04c
+Author: Alan Stern 
+Date:   Wed Oct 29 15:18:50 2008 -0400
+
+    USB: straighten out inline code in sysfs.c
+    
+    This patch (as1156) straightens out some code in usbcore.  The
+    usb_create_intf_ep_files() and usb_remove_intf_ep_files() routines
+    don't need to be separate inlines; they should be moved bodily into
+    the places where they get used.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 4fb65fdc9dc3..8c65fa75b5c2 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -812,32 +812,11 @@ struct attribute_group *usb_interface_groups[] = {
+ 	NULL
+ };
+ 
+-static inline void usb_create_intf_ep_files(struct usb_interface *intf,
+-		struct usb_device *udev)
+-{
+-	struct usb_host_interface *iface_desc;
+-	int i;
+-
+-	iface_desc = intf->cur_altsetting;
+-	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i)
+-		usb_create_ep_files(&intf->dev, &iface_desc->endpoint[i],
+-				udev);
+-}
+-
+-static inline void usb_remove_intf_ep_files(struct usb_interface *intf)
+-{
+-	struct usb_host_interface *iface_desc;
+-	int i;
+-
+-	iface_desc = intf->cur_altsetting;
+-	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i)
+-		usb_remove_ep_files(&iface_desc->endpoint[i]);
+-}
+-
+ int usb_create_sysfs_intf_files(struct usb_interface *intf)
+ {
+ 	struct usb_device *udev = interface_to_usbdev(intf);
+ 	struct usb_host_interface *alt = intf->cur_altsetting;
++	int i;
+ 	int retval;
+ 
+ 	if (intf->sysfs_files_created || intf->unregistering)
+@@ -851,18 +830,22 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf)
+ 		alt->string = usb_cache_string(udev, alt->desc.iInterface);
+ 	if (alt->string)
+ 		retval = device_create_file(&intf->dev, &dev_attr_interface);
+-	usb_create_intf_ep_files(intf, udev);
++	for (i = 0; i < alt->desc.bNumEndpoints; ++i)
++		usb_create_ep_files(&intf->dev, &alt->endpoint[i], udev);
+ 	intf->sysfs_files_created = 1;
+ 	return 0;
+ }
+ 
+ void usb_remove_sysfs_intf_files(struct usb_interface *intf)
+ {
+-	struct device *dev = &intf->dev;
++	struct usb_host_interface *alt = intf->cur_altsetting;
++	int i;
+ 
+ 	if (!intf->sysfs_files_created)
+ 		return;
+-	usb_remove_intf_ep_files(intf);
+-	device_remove_file(dev, &dev_attr_interface);
++
++	for (i = 0; i < alt->desc.bNumEndpoints; ++i)
++		usb_remove_ep_files(&alt->endpoint[i]);
++	device_remove_file(&intf->dev, &dev_attr_interface);
+ 	intf->sysfs_files_created = 0;
+ }

commit ec0676ee28528dc8dda13a93ee4b1f215a0c2f9d
+Author: Alan Stern 
+Date:   Fri Dec 5 14:10:31 2008 -0500
+
+    Driver core: move the bus notifier call points
+    
+    This patch (as1184) changes the location of the notifications in
+    device_add() and device_del().  Now the BUS_NOTIFY_ADD_DEVICE message
+    is sent after dpm_sysfs_add(), which is necessary for clients that
+    want to add attributes to the power/ subdirectory.  The
+    BUS_NOTIFY_DEL_DEVICE message is correspondingly moved before
+    dpm_sysfs_remove().
+    
+    Signed-off-by: Alan Stern 
+    Cc: Kay Sievers 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/base/core.c b/drivers/base/core.c
+index 180ff84ea26c..ee555d7d5c3f 100644
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -894,11 +894,6 @@ int device_add(struct device *dev)
+ 	if (platform_notify)
+ 		platform_notify(dev);
+ 
+-	/* notify clients of device entry (new way) */
+-	if (dev->bus)
+-		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
+-					     BUS_NOTIFY_ADD_DEVICE, dev);
+-
+ 	error = device_create_file(dev, &uevent_attr);
+ 	if (error)
+ 		goto attrError;
+@@ -926,6 +921,14 @@ int device_add(struct device *dev)
+ 	if (error)
+ 		goto DPMError;
+ 	device_pm_add(dev);
++
++	/* Notify clients of device addition.  This call must come
++	 * after dpm_sysf_add() and before kobject_uevent().
++	 */
++	if (dev->bus)
++		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
++					     BUS_NOTIFY_ADD_DEVICE, dev);
++
+ 	kobject_uevent(&dev->kobj, KOBJ_ADD);
+ 	bus_attach_device(dev);
+ 	if (parent)
+@@ -951,9 +954,6 @@ int device_add(struct device *dev)
+  DPMError:
+ 	bus_remove_device(dev);
+  BusError:
+-	if (dev->bus)
+-		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
+-					     BUS_NOTIFY_DEL_DEVICE, dev);
+ 	device_remove_attrs(dev);
+  AttrsError:
+ 	device_remove_class_symlinks(dev);
+@@ -1038,6 +1038,12 @@ void device_del(struct device *dev)
+ 	struct device *parent = dev->parent;
+ 	struct class_interface *class_intf;
+ 
++	/* Notify clients of device removal.  This call must come
++	 * before dpm_sysfs_remove().
++	 */
++	if (dev->bus)
++		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
++					     BUS_NOTIFY_DEL_DEVICE, dev);
+ 	device_pm_remove(dev);
+ 	dpm_sysfs_remove(dev);
+ 	if (parent)
+@@ -1075,9 +1081,6 @@ void device_del(struct device *dev)
+ 	 */
+ 	if (platform_notify_remove)
+ 		platform_notify_remove(dev);
+-	if (dev->bus)
+-		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
+-					     BUS_NOTIFY_DEL_DEVICE, dev);
+ 	kobject_uevent(&dev->kobj, KOBJ_REMOVE);
+ 	cleanup_device_parent(dev);
+ 	kobject_del(&dev->kobj);

commit 7f4f5d4516b441d712fa0ffe5380618fb7fc545e
+Author: Alan Stern 
+Date:   Mon Nov 17 11:14:19 2008 -0500
+
+    Fix misspellings in pm.h macros
+    
+    This patch (as1167) fixes some misspellings in various recently-added
+    macros in pm.h.  Fortunately these macros are not yet used anywhere.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Rafael J. Wysocki 
+
+diff --git a/include/linux/pm.h b/include/linux/pm.h
+index 5785666d0cc4..de2e0a8f6728 100644
+--- a/include/linux/pm.h
++++ b/include/linux/pm.h
+@@ -252,7 +252,7 @@ struct dev_pm_ops {
+ #define PM_EVENT_SLEEP		(PM_EVENT_SUSPEND | PM_EVENT_HIBERNATE)
+ #define PM_EVENT_USER_SUSPEND	(PM_EVENT_USER | PM_EVENT_SUSPEND)
+ #define PM_EVENT_USER_RESUME	(PM_EVENT_USER | PM_EVENT_RESUME)
+-#define PM_EVENT_REMOTE_WAKEUP	(PM_EVENT_REMOTE | PM_EVENT_RESUME)
++#define PM_EVENT_REMOTE_RESUME	(PM_EVENT_REMOTE | PM_EVENT_RESUME)
+ #define PM_EVENT_AUTO_SUSPEND	(PM_EVENT_AUTO | PM_EVENT_SUSPEND)
+ #define PM_EVENT_AUTO_RESUME	(PM_EVENT_AUTO | PM_EVENT_RESUME)
+ 
+@@ -265,15 +265,15 @@ struct dev_pm_ops {
+ #define PMSG_THAW	((struct pm_message){ .event = PM_EVENT_THAW, })
+ #define PMSG_RESTORE	((struct pm_message){ .event = PM_EVENT_RESTORE, })
+ #define PMSG_RECOVER	((struct pm_message){ .event = PM_EVENT_RECOVER, })
+-#define PMSG_USER_SUSPEND	((struct pm_messge) \
++#define PMSG_USER_SUSPEND	((struct pm_message) \
+ 					{ .event = PM_EVENT_USER_SUSPEND, })
+-#define PMSG_USER_RESUME	((struct pm_messge) \
++#define PMSG_USER_RESUME	((struct pm_message) \
+ 					{ .event = PM_EVENT_USER_RESUME, })
+-#define PMSG_REMOTE_RESUME	((struct pm_messge) \
++#define PMSG_REMOTE_RESUME	((struct pm_message) \
+ 					{ .event = PM_EVENT_REMOTE_RESUME, })
+-#define PMSG_AUTO_SUSPEND	((struct pm_messge) \
++#define PMSG_AUTO_SUSPEND	((struct pm_message) \
+ 					{ .event = PM_EVENT_AUTO_SUSPEND, })
+-#define PMSG_AUTO_RESUME		((struct pm_messge) \
++#define PMSG_AUTO_RESUME	((struct pm_message) \
+ 					{ .event = PM_EVENT_AUTO_RESUME, })
+ 
+ /**

commit 08ef08ee8c5a8d538ca9a3c433d4213c128af863
+Author: Alan Stern 
+Date:   Thu Oct 30 23:58:51 2008 +0100
+
+    HID: automatically call usbhid_set_leds in usbhid driver
+    
+    This patch (as1146c) makes usbhid automatically call usbhid_set_leds()
+    for any device that supports the keyboard boot protocol.
+    
+    In theory this should be perfectly safe.  BIOSes send the LED output
+    report as part of their normal device initialization, so any keyboard
+    device supporting the boot protocol has to be able to handle it.
+    
+    As a side effect, the hid-dell and hid-bright drivers are no longer
+    needed, and the Logitech keyboard driver can be removed from hid-lg.
+    
+    CC: Mauro Carvalho Chehab 
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
+index b4fd8ca701a4..65b577eaf823 100644
+--- a/drivers/hid/Kconfig
++++ b/drivers/hid/Kconfig
+@@ -107,13 +107,6 @@ config HID_BELKIN
+ 	---help---
+ 	Support for Belkin Flip KVM and Wireless keyboard.
+ 
+-config HID_BRIGHT
+-	tristate "Bright" if EMBEDDED
+-	depends on USB_HID
+-	default y
+-	---help---
+-	Support for Bright ABNT-2 keyboard.
+-
+ config HID_CHERRY
+ 	tristate "Cherry" if EMBEDDED
+ 	depends on USB_HID
+@@ -135,14 +128,6 @@ config HID_CYPRESS
+ 	---help---
+ 	Support for cypress mouse and barcode readers.
+ 
+-config HID_DELL
+-	tristate "Dell" if EMBEDDED
+-	depends on USB_HID
+-	default y
+-	---help---
+-	Support for quirky Dell HID hardware that require
+-	special LED handling (W7658 and SK8115 models)
+-
+ config HID_EZKEY
+ 	tristate "Ezkey" if EMBEDDED
+ 	depends on USB_HID
+diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
+index b09e43e7413e..e2294a8b2a68 100644
+--- a/drivers/hid/Makefile
++++ b/drivers/hid/Makefile
+@@ -23,11 +23,9 @@ endif
+ obj-$(CONFIG_HID_A4TECH)	+= hid-a4tech.o
+ obj-$(CONFIG_HID_APPLE)		+= hid-apple.o
+ obj-$(CONFIG_HID_BELKIN)	+= hid-belkin.o
+-obj-$(CONFIG_HID_BRIGHT)	+= hid-bright.o
+ obj-$(CONFIG_HID_CHERRY)	+= hid-cherry.o
+ obj-$(CONFIG_HID_CHICONY)	+= hid-chicony.o
+ obj-$(CONFIG_HID_CYPRESS)	+= hid-cypress.o
+-obj-$(CONFIG_HID_DELL)		+= hid-dell.o
+ obj-$(CONFIG_HID_EZKEY)		+= hid-ezkey.o
+ obj-$(CONFIG_HID_GYRATION)	+= hid-gyration.o
+ obj-$(CONFIG_HID_LOGITECH)	+= hid-logitech.o
+diff --git a/drivers/hid/hid-bright.c b/drivers/hid/hid-bright.c
+deleted file mode 100644
+index 38517a117dfd..000000000000
+--- a/drivers/hid/hid-bright.c
++++ /dev/null
+@@ -1,71 +0,0 @@
+-/*
+- *  HID driver for some bright "special" devices
+- *
+- *  Copyright (c) 2008 Mauro Carvalho Chehab 
+- *
+- * Based on hid-dell driver
+- */
+-
+-/*
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the Free
+- * Software Foundation; either version 2 of the License, or (at your option)
+- * any later version.
+- */
+-
+-#include 
+-#include 
+-#include 
+-
+-#include "hid-ids.h"
+-
+-static int bright_probe(struct hid_device *hdev, const struct hid_device_id *id)
+-{
+-	int ret;
+-
+-	ret = hid_parse(hdev);
+-	if (ret) {
+-		dev_err(&hdev->dev, "parse failed\n");
+-		goto err_free;
+-	}
+-
+-	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+-	if (ret) {
+-		dev_err(&hdev->dev, "hw start failed\n");
+-		goto err_free;
+-	}
+-
+-	usbhid_set_leds(hdev);
+-
+-	return 0;
+-err_free:
+-	return ret;
+-}
+-
+-static const struct hid_device_id bright_devices[] = {
+-	{ HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) },
+-	{ }
+-};
+-MODULE_DEVICE_TABLE(hid, bright_devices);
+-
+-static struct hid_driver bright_driver = {
+-	.name = "bright",
+-	.id_table = bright_devices,
+-	.probe = bright_probe,
+-};
+-
+-static int bright_init(void)
+-{
+-	return hid_register_driver(&bright_driver);
+-}
+-
+-static void bright_exit(void)
+-{
+-	hid_unregister_driver(&bright_driver);
+-}
+-
+-module_init(bright_init);
+-module_exit(bright_exit);
+-MODULE_LICENSE("GPL");
+-
+-HID_COMPAT_LOAD_DRIVER(bright);
+diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
+index 839de38a43c7..8be30037cffe 100644
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -1256,16 +1256,12 @@ static const struct hid_device_id hid_blacklist[] = {
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
+-	{ HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) },
+-	{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) },
+-	{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
+-	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) },
+@@ -1279,7 +1275,6 @@ static const struct hid_device_id hid_blacklist[] = {
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) },
+-	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) },
+diff --git a/drivers/hid/hid-dell.c b/drivers/hid/hid-dell.c
+deleted file mode 100644
+index f5474300b83a..000000000000
+--- a/drivers/hid/hid-dell.c
++++ /dev/null
+@@ -1,76 +0,0 @@
+-/*
+- *  HID driver for some dell "special" devices
+- *
+- *  Copyright (c) 1999 Andreas Gal
+- *  Copyright (c) 2000-2005 Vojtech Pavlik 
+- *  Copyright (c) 2005 Michael Haboustak  for Concept2, Inc
+- *  Copyright (c) 2006-2007 Jiri Kosina
+- *  Copyright (c) 2007 Paul Walmsley
+- *  Copyright (c) 2008 Jiri Slaby
+- */
+-
+-/*
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the Free
+- * Software Foundation; either version 2 of the License, or (at your option)
+- * any later version.
+- */
+-
+-#include 
+-#include 
+-#include 
+-
+-#include "hid-ids.h"
+-
+-static int dell_probe(struct hid_device *hdev, const struct hid_device_id *id)
+-{
+-	int ret;
+-
+-	ret = hid_parse(hdev);
+-	if (ret) {
+-		dev_err(&hdev->dev, "parse failed\n");
+-		goto err_free;
+-	}
+-
+-	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+-	if (ret) {
+-		dev_err(&hdev->dev, "hw start failed\n");
+-		goto err_free;
+-	}
+-
+-	usbhid_set_leds(hdev);
+-
+-	return 0;
+-err_free:
+-	return ret;
+-}
+-
+-static const struct hid_device_id dell_devices[] = {
+-	{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) },
+-	{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) },
+-	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) },
+-	{ }
+-};
+-MODULE_DEVICE_TABLE(hid, dell_devices);
+-
+-static struct hid_driver dell_driver = {
+-	.name = "dell",
+-	.id_table = dell_devices,
+-	.probe = dell_probe,
+-};
+-
+-static int dell_init(void)
+-{
+-	return hid_register_driver(&dell_driver);
+-}
+-
+-static void dell_exit(void)
+-{
+-	hid_unregister_driver(&dell_driver);
+-}
+-
+-module_init(dell_init);
+-module_exit(dell_exit);
+-MODULE_LICENSE("GPL");
+-
+-HID_COMPAT_LOAD_DRIVER(dell);
+diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
+index 39289699c32f..aae2ceca0bce 100644
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -107,9 +107,6 @@
+ #define USB_VENDOR_ID_BELKIN           0x050d
+ #define USB_DEVICE_ID_FLIP_KVM         0x3201
+ 
+-#define USB_VENDOR_ID_BRIGHT		0x1241
+-#define USB_DEVICE_ID_BRIGHT_ABNT2	0x1503
+-
+ #define USB_VENDOR_ID_BERKSHIRE		0x0c98
+ #define USB_DEVICE_ID_BERKSHIRE_PCWD	0x1140
+ 
+@@ -141,10 +138,6 @@
+ #define USB_DEVICE_ID_CYPRESS_BARCODE_1	0xde61
+ #define USB_DEVICE_ID_CYPRESS_BARCODE_2	0xde64
+ 
+-#define USB_VENDOR_ID_DELL		0x413c
+-#define USB_DEVICE_ID_DELL_W7658	0x2005
+-#define USB_DEVICE_ID_DELL_SK8115	0x2105
+-
+ #define USB_VENDOR_ID_DELORME		0x1163
+ #define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
+ #define USB_DEVICE_ID_DELORME_EM_LT20	0x0200
+@@ -167,9 +160,6 @@
+ 
+ #define USB_VENDOR_ID_GENERAL_TOUCH	0x0dfc
+ 
+-#define USB_VENDOR_ID_GENERIC_13BA	0x13ba
+-#define USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE	0x0017
+-
+ #define USB_VENDOR_ID_GLAB		0x06c2
+ #define USB_DEVICE_ID_4_PHIDGETSERVO_30	0x0038
+ #define USB_DEVICE_ID_1_PHIDGETSERVO_30	0x0039
+@@ -292,7 +282,6 @@
+ #define USB_DEVICE_ID_LOGITECH_WHEEL	0xc294
+ #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL	0xc295
+ #define USB_DEVICE_ID_LOGITECH_ELITE_KBD	0xc30a
+-#define USB_DEVICE_ID_LOGITECH_KBD	0xc311
+ #define USB_DEVICE_ID_S510_RECEIVER	0xc50c
+ #define USB_DEVICE_ID_S510_RECEIVER_2	0xc517
+ #define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500	0xc512
+diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
+index 2bae340eafe2..83e07c9f4144 100644
+--- a/drivers/hid/hid-lg.c
++++ b/drivers/hid/hid-lg.c
+@@ -26,7 +26,6 @@
+ #define LG_RDESC		0x001
+ #define LG_BAD_RELATIVE_KEYS	0x002
+ #define LG_DUPLICATE_USAGES	0x004
+-#define LG_RESET_LEDS		0x008
+ #define LG_EXPANDED_KEYMAP	0x010
+ #define LG_IGNORE_DOUBLED_WHEEL	0x020
+ #define LG_WIRELESS		0x040
+@@ -248,9 +247,6 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
+ 		goto err_free;
+ 	}
+ 
+-	if (quirks & LG_RESET_LEDS)
+-		usbhid_set_leds(hdev);
+-
+ 	if (quirks & LG_FF)
+ 		lgff_init(hdev);
+ 	if (quirks & LG_FF2)
+@@ -279,9 +275,6 @@ static const struct hid_device_id lg_devices[] = {
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI),
+ 		.driver_data = LG_DUPLICATE_USAGES },
+ 
+-	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD),
+-		.driver_data = LG_RESET_LEDS },
+-
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD),
+ 		.driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500),
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index 2afc8617f591..6383145b5840 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -874,6 +874,15 @@ static int usbhid_start(struct hid_device *hid)
+ 
+ 	set_bit(HID_STARTED, &usbhid->iofl);
+ 
++	/* Some keyboards don't work until their LEDs have been set.
++	 * Since BIOSes do set the LEDs, it must be safe for any device
++	 * that supports the keyboard boot protocol.
++	 */
++	if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT &&
++			interface->desc.bInterfaceProtocol ==
++				USB_INTERFACE_PROTOCOL_KEYBOARD)
++		usbhid_set_leds(hid);
++
+ 	return 0;
+ 
+ fail:

commit 3dbf6a54046052d79743822c9206af191e582ab0
+Author: Alan Stern 
+Date:   Mon Dec 15 10:31:28 2008 -0500
+
+    [SCSI] Fix uninitialized variable error in scsi_io_completion
+    
+    This patch (as1191) adds a missing "default" case in
+    scsi_io_completion(), thereby fixing an "uninitialized variable"
+    error.  It also adds a missing newline to a log entry.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index f2f51e0333eb..8c73bb4e0a2f 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -1029,6 +1029,10 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
+ 				case 0x09: /* self test in progress */
+ 					action = ACTION_DELAYED_RETRY;
+ 					break;
++				default:
++					description = "Device not ready";
++					action = ACTION_FAIL;
++					break;
+ 				}
+ 			} else {
+ 				description = "Device not ready";
+@@ -1054,7 +1058,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
+ 		/* Give up and fail the remainder of the request */
+ 		if (!(req->cmd_flags & REQ_QUIET)) {
+ 			if (description)
+-				scmd_printk(KERN_INFO, cmd, "%s",
++				scmd_printk(KERN_INFO, cmd, "%s\n",
+ 					    description);
+ 			scsi_print_result(cmd);
+ 			if (driver_byte(result) & DRIVER_SENSE)

commit b60af5b0adf0da24c673598c8d3fb4d4189a15ce
+Author: Alan Stern 
+Date:   Mon Nov 3 15:56:47 2008 -0500
+
+    [SCSI] simplify scsi_io_completion()
+    
+    This patch (as1142b) consolidates a lot of repetitious code in
+    scsi_io_completion().  It also fixes a few comments.  Most
+    importantly, however, it clearly distinguishes among the three sorts
+    of retries that can be done when a command fails to complete:
+    
+            Unprepare the request and resubmit it, so that a new
+            command will be created for it.
+    
+            Requeue the request directly so that it will be retried
+            immediately using the same command.
+    
+            Requeue the request so that it will be retried following
+            a short delay.
+    
+            Complete the remainder of the request with an I/O error.
+    
+    [jejb: Updates
+         1. For several error conditions, we would now print the sense twice
+            in slightly different ways, so unify the location of sense
+            printing.
+         2. I added more descriptions to actual failure conditions for
+            better debugging
+         3. according to spec, ABORTED_COMMAND is supposed to be retried
+            (except on DIF failure).  Our old behaviour of erroring it looks
+            to be a bug.
+         4. I'd prefer not to default initialise the action variable because
+            that ensures that every leg of the error handler has an
+            associated action and the compiler will warn if someone later
+            accidentally misses one or removes one.
+    ]
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index 148d3af92aef..ecfbbd30dce5 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -875,16 +875,24 @@ static void scsi_end_bidi_request(struct scsi_cmnd *cmd)
+  *              (the normal case for most drivers), we don't need
+  *              the logic to deal with cleaning up afterwards.
+  *
+- *		We must do one of several things here:
+- *
+- *		a) Call scsi_end_request.  This will finish off the
+- *		   specified number of sectors.  If we are done, the
+- *		   command block will be released, and the queue
+- *		   function will be goosed.  If we are not done, then
+- *		   scsi_end_request will directly goose the queue.
+- *
+- *		b) We can just use scsi_requeue_command() here.  This would
+- *		   be used if we just wanted to retry, for example.
++ *		We must call scsi_end_request().  This will finish off
++ *		the specified number of sectors.  If we are done, the
++ *		command block will be released and the queue function
++ *		will be goosed.  If we are not done then we have to
++ *		figure out what to do next:
++ *
++ *		a) We can call scsi_requeue_command().  The request
++ *		   will be unprepared and put back on the queue.  Then
++ *		   a new command will be created for it.  This should
++ *		   be used if we made forward progress, or if we want
++ *		   to switch from READ(10) to READ(6) for example.
++ *
++ *		b) We can call scsi_queue_insert().  The request will
++ *		   be put back on the queue and retried using the same
++ *		   command as before, possibly after a delay.
++ *
++ *		c) We can call blk_end_request() with -EIO to fail
++ *		   the remainder of the request.
+  */
+ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
+ {
+@@ -896,6 +904,9 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
+ 	struct scsi_sense_hdr sshdr;
+ 	int sense_valid = 0;
+ 	int sense_deferred = 0;
++	enum {ACTION_FAIL, ACTION_REPREP, ACTION_RETRY,
++	      ACTION_DELAYED_RETRY} action;
++	char *description = NULL;
+ 
+ 	if (result) {
+ 		sense_valid = scsi_command_normalize_sense(cmd, &sshdr);
+@@ -947,10 +958,13 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
+ 		return;
+ 	this_count = blk_rq_bytes(req);
+ 
+-	/* good_bytes = 0, or (inclusive) there were leftovers and
+-	 * result = 0, so scsi_end_request couldn't retry.
+-	 */
+-	if (sense_valid && !sense_deferred) {
++	if (host_byte(result) == DID_RESET) {
++		/* Third party bus reset or reset for error recovery
++		 * reasons.  Just retry the command and see what
++		 * happens.
++		 */
++		action = ACTION_RETRY;
++	} else if (sense_valid && !sense_deferred) {
+ 		switch (sshdr.sense_key) {
+ 		case UNIT_ATTENTION:
+ 			if (cmd->device->removable) {
+@@ -958,16 +972,15 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
+ 				 * and quietly refuse further access.
+ 				 */
+ 				cmd->device->changed = 1;
+-				scsi_end_request(cmd, -EIO, this_count, 1);
+-				return;
++				description = "Media Changed";
++				action = ACTION_FAIL;
+ 			} else {
+ 				/* Must have been a power glitch, or a
+ 				 * bus reset.  Could not have been a
+ 				 * media change, so we just retry the
+-				 * request and see what happens.
++				 * command and see what happens.
+ 				 */
+-				scsi_requeue_command(q, cmd);
+-				return;
++				action = ACTION_RETRY;
+ 			}
+ 			break;
+ 		case ILLEGAL_REQUEST:
+@@ -983,21 +996,18 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
+ 			    sshdr.asc == 0x20 && sshdr.ascq == 0x00) &&
+ 			    (cmd->cmnd[0] == READ_10 ||
+ 			     cmd->cmnd[0] == WRITE_10)) {
++				/* This will issue a new 6-byte command. */
+ 				cmd->device->use_10_for_rw = 0;
+-				/* This will cause a retry with a
+-				 * 6-byte command.
+-				 */
+-				scsi_requeue_command(q, cmd);
+-			} else if (sshdr.asc == 0x10) /* DIX */
+-				scsi_end_request(cmd, -EIO, this_count, 0);
+-			else
+-				scsi_end_request(cmd, -EIO, this_count, 1);
+-			return;
++				action = ACTION_REPREP;
++			} else
++				action = ACTION_FAIL;
++			break;
+ 		case ABORTED_COMMAND:
+ 			if (sshdr.asc == 0x10) { /* DIF */
+-				scsi_end_request(cmd, -EIO, this_count, 0);
+-				return;
+-			}
++				action = ACTION_FAIL;
++				description = "Data Integrity Failure";
++			} else
++				action = ACTION_RETRY;
+ 			break;
+ 		case NOT_READY:
+ 			/* If the device is in the process of becoming
+@@ -1012,49 +1022,57 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
+ 				case 0x07: /* operation in progress */
+ 				case 0x08: /* Long write in progress */
+ 				case 0x09: /* self test in progress */
+-					scsi_requeue_command(q, cmd);
+-					return;
+-				default:
++					action = ACTION_DELAYED_RETRY;
+ 					break;
+ 				}
++			} else {
++				description = "Device not ready";
++				action = ACTION_FAIL;
+ 			}
+-			if (!(req->cmd_flags & REQ_QUIET))
+-				scsi_cmd_print_sense_hdr(cmd,
+-							 "Device not ready",
+-							 &sshdr);
+-
+-			scsi_end_request(cmd, -EIO, this_count, 1);
+-			return;
++			break;
+ 		case VOLUME_OVERFLOW:
+-			if (!(req->cmd_flags & REQ_QUIET)) {
+-				scmd_printk(KERN_INFO, cmd,
+-					    "Volume overflow, CDB: ");
+-				__scsi_print_command(cmd->cmnd);
+-				scsi_print_sense("", cmd);
+-			}
+ 			/* See SSC3rXX or current. */
+-			scsi_end_request(cmd, -EIO, this_count, 1);
+-			return;
++			action = ACTION_FAIL;
++			break;
+ 		default:
++			description = "Unhandled sense code";
++			action = ACTION_FAIL;
+ 			break;
+ 		}
++	} else {
++		description = "Unhandled error code";
++		action = ACTION_FAIL;
+ 	}
+-	if (host_byte(result) == DID_RESET) {
+-		/* Third party bus reset or reset for error recovery
+-		 * reasons.  Just retry the request and see what
+-		 * happens.
+-		 */
+-		scsi_requeue_command(q, cmd);
+-		return;
+-	}
+-	if (result) {
++
++	switch (action) {
++	case ACTION_FAIL:
++		/* Give up and fail the remainder of the request */
+ 		if (!(req->cmd_flags & REQ_QUIET)) {
++			if (description)
++				scmd_printk(KERN_INFO, cmd, "%s",
++					    description);
+ 			scsi_print_result(cmd);
+ 			if (driver_byte(result) & DRIVER_SENSE)
+ 				scsi_print_sense("", cmd);
+ 		}
++		blk_end_request(req, -EIO, blk_rq_bytes(req));
++		scsi_next_command(cmd);
++		break;
++	case ACTION_REPREP:
++		/* Unprep the request and put it back at the head of the queue.
++		 * A new command will be prepared and issued.
++		 */
++		scsi_requeue_command(q, cmd);
++		break;
++	case ACTION_RETRY:
++		/* Retry the same command immediately */
++		scsi_queue_insert(cmd, SCSI_MLQUEUE_EH_RETRY);
++		break;
++	case ACTION_DELAYED_RETRY:
++		/* Retry the same command after a delay */
++		scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);
++		break;
+ 	}
+-	scsi_end_request(cmd, -EIO, this_count, !result);
+ }
+ 
+ static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb,

commit 24c0996a6b73e2554104961afcc8659534503e0d
+Author: Alan Stern 
+Date:   Mon Dec 1 10:24:41 2008 -0500
+
+    USB: skip Set-Interface(0) if already in altsetting 0
+    
+    When a driver unbinds from an interface, usbcore always sends a
+    Set-Interface request to reinstall altsetting 0.  Unforunately, quite
+    a few devices have buggy firmware that crashes when it receives this
+    request.
+    
+    To avoid such problems, this patch (as1180) arranges to send the
+    Set-Interface request only when the interface is not already in
+    altsetting 0.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 3d7793d93031..8c081308b0e2 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -279,7 +279,9 @@ static int usb_unbind_interface(struct device *dev)
+ 	 * altsetting means creating new endpoint device entries).
+ 	 * When either of these happens, defer the Set-Interface.
+ 	 */
+-	if (!error && intf->dev.power.status == DPM_ON)
++	if (intf->cur_altsetting->desc.bAlternateSetting == 0)
++		;	/* Already in altsetting 0 so skip Set-Interface */
++	else if (!error && intf->dev.power.status == DPM_ON)
+ 		usb_set_interface(udev, intf->altsetting[0].
+ 				desc.bInterfaceNumber, 0);
+ 	else

commit a4b188095912eee83d065f000dfe06f25919750b
+Author: Alan Stern 
+Date:   Mon Dec 1 10:23:43 2008 -0500
+
+    usb-storage: update unusual_devs entry for Nokia 5310
+    
+    This patch (as1179) updates the unusual_devs entry for Nokia's 5310
+    phone to include a more recent firmware revision.
+    
+    This fixes Bugzilla #12099.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Robson Roberto Souza Peixoto 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 06bf064c4394..bfcc1fe82518 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -182,7 +182,7 @@ UNUSUAL_DEV(  0x0421, 0x0063, 0x0001, 0x0601,
+ 		US_FL_FIX_CAPACITY ),
+ 
+ /* Patch for Nokia 5310 capacity */
+-UNUSUAL_DEV(  0x0421, 0x006a, 0x0000, 0x0591,
++UNUSUAL_DEV(  0x0421, 0x006a, 0x0000, 0x0701,
+ 		"Nokia",
+ 		"5310",
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,

commit a6b7b034d7f20761c55743be2acb762ce09a0c6b
+Author: Alan Stern 
+Date:   Fri Nov 21 16:15:12 2008 -0500
+
+    USB: storage: unusual_devs entry for Mio C520-GPS
+    
+    This patch (as1176) adds an unusual_devs entry for the Mio C520 GPS
+    unit.  Other devices also based on the Mitac hardware use the same USB
+    interface firmware, so the Vendor and Product names are generalized.
+    
+    This fixes Bugzilla #11583.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Tamas Kerecsen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 6da9a7a962a8..e8e3edaa7cbf 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -318,6 +318,18 @@ UNUSUAL_DEV(  0x045a, 0x5210, 0x0101, 0x0101,
+ 		US_SC_SCSI, US_PR_KARMA, rio_karma_init, 0),
+ #endif
+ 
++/* Reported by Tamas Kerecsen 
++ * Obviously the PROM has not been customized by the VAR;
++ * the Vendor and Product string descriptors are:
++ *	Generic Mass Storage (PROTOTYPE--Remember to change idVendor)
++ *	Generic Manufacturer (PROTOTYPE--Remember to change idVendor)
++ */
++UNUSUAL_DEV(  0x045e, 0xffff, 0x0000, 0x0000,
++		"Mitac",
++		"GPS",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_MAX_SECTORS_64 ),
++
+ /*
+  * This virtual floppy is found in Sun equipment (x4600, x4200m2, etc.)
+  * Reported by Pete Zaitcev 

commit 589afd3bec907f02c133d7b8185b8af534f14a8e
+Author: Alan Stern 
+Date:   Mon Nov 17 14:32:16 2008 -0500
+
+    USB: storage: update unusual_devs entries for Nokia 5300 and 5310
+    
+    This patch (as1168) updates the unusual_devs entry for the Nokia 5300.
+    According to Jorge Lucangeli Obes , some existing
+    models have a revision number lower than the lower limit of the
+    current entry.
+    
+    The patch also moves the entry for the Nokia 5310 to its correct place
+    in the file.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 096a439baa37..6da9a7a962a8 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -167,6 +167,13 @@ UNUSUAL_DEV(  0x0421, 0x005d, 0x0001, 0x0600,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_FIX_CAPACITY ),
+ 
++/* Patch for Nokia 5310 capacity */
++UNUSUAL_DEV(  0x0421, 0x006a, 0x0000, 0x0591,
++		"Nokia",
++		"5310",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_FIX_CAPACITY ),
++
+ /* Reported by Mario Rettig  */
+ UNUSUAL_DEV(  0x0421, 0x042e, 0x0100, 0x0100,
+ 		"Nokia",
+@@ -233,7 +240,7 @@ UNUSUAL_DEV(  0x0421, 0x0495, 0x0370, 0x0370,
+ 		US_FL_MAX_SECTORS_64 ),
+ 
+ /* Reported by Cedric Godin  */
+-UNUSUAL_DEV(  0x0421, 0x04b9, 0x0551, 0x0551,
++UNUSUAL_DEV(  0x0421, 0x04b9, 0x0500, 0x0551,
+ 		"Nokia",
+ 		"5300",
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,

commit 9beba53dc5c330d781ecc0ad8ea081c2d100ff9f
+Author: Alan Stern 
+Date:   Mon Nov 17 16:12:32 2008 -0500
+
+    USB: storage: updates unusual_devs entry for the Nokia 6300
+    
+    This patch (as1169) modifies the unusual_devs entry for the Nokia
+    6300.  According to Maciej Gierok  and David
+    McBride , the revision limits need to be wider.
+    
+    This fixes Bugzilla #11768.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index d4e5fc86e43c..096a439baa37 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -240,7 +240,7 @@ UNUSUAL_DEV(  0x0421, 0x04b9, 0x0551, 0x0551,
+ 		US_FL_FIX_CAPACITY ),
+ 
+ /* Reported by Richard Nauber  */
+-UNUSUAL_DEV(  0x0421, 0x04fa, 0x0601, 0x0601,
++UNUSUAL_DEV(  0x0421, 0x04fa, 0x0550, 0x0660,
+ 		"Nokia",
+ 		"6300",
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,

commit 372dd6e8ed924e876f3beb598721e813ad7fa323
+Author: Alan Stern 
+Date:   Wed Nov 12 17:02:57 2008 -0500
+
+    USB: EHCI: fix divide-by-zero bug
+    
+    This patch (as1164) fixes a bug in the EHCI scheduler.  The interval
+    value it uses is already in linear format, not logarithmically coded.
+    The existing code can sometimes crash the system by trying to divide
+    by zero.
+    
+    Signed-off-by: Alan Stern 
+    Cc: David Brownell 
+    Cc: Stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 4a0c5a78b2ed..a081ee65bde6 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -918,7 +918,7 @@ iso_stream_init (
+ 		 */
+ 		stream->usecs = HS_USECS_ISO (maxp);
+ 		bandwidth = stream->usecs * 8;
+-		bandwidth /= 1 << (interval - 1);
++		bandwidth /= interval;
+ 
+ 	} else {
+ 		u32		addr;
+@@ -951,7 +951,7 @@ iso_stream_init (
+ 		} else
+ 			stream->raw_mask = smask_out [hs_transfers - 1];
+ 		bandwidth = stream->usecs + stream->c_usecs;
+-		bandwidth /= 1 << (interval + 2);
++		bandwidth /= interval << 3;
+ 
+ 		/* stream->splits gets created from raw_mask later */
+ 		stream->address = cpu_to_hc32(ehci, addr);

commit 67b2e029743a52670d77864723b4d0d40f7733b5
+Author: Alan Stern 
+Date:   Wed Nov 12 17:04:53 2008 -0500
+
+    USB: EHCI: fix handling of dead controllers
+    
+    This patch (as1165) makes a few small changes in the logic used by
+    ehci-hcd when it encounters a controller error:
+    
+            Instead of printing out the masked status, it prints the
+            original status as read directly from the hardware.
+    
+            It doesn't check for the STS_HALT status bit before taking
+            action.  The mere fact that the STS_FATAL bit is set means
+            that something bad has happened and the controller needs to
+            be reset.  With the old code this test could never succeed
+            because the STS_HALT bit was masked out from the status.
+    
+    I anticipate that this will prevent the occasional "irq X: nobody cared"
+    problem people encounter when their EHCI controllers die.
+    
+    Signed-off-by: Alan Stern 
+    Cc: David Brownell 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 15a803b206b8..4725d15d096f 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -643,7 +643,7 @@ static int ehci_run (struct usb_hcd *hcd)
+ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ {
+ 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+-	u32			status, pcd_status = 0, cmd;
++	u32			status, masked_status, pcd_status = 0, cmd;
+ 	int			bh;
+ 
+ 	spin_lock (&ehci->lock);
+@@ -656,14 +656,14 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 		goto dead;
+ 	}
+ 
+-	status &= INTR_MASK;
+-	if (!status) {			/* irq sharing? */
++	masked_status = status & INTR_MASK;
++	if (!masked_status) {		/* irq sharing? */
+ 		spin_unlock(&ehci->lock);
+ 		return IRQ_NONE;
+ 	}
+ 
+ 	/* clear (just) interrupts */
+-	ehci_writel(ehci, status, &ehci->regs->status);
++	ehci_writel(ehci, masked_status, &ehci->regs->status);
+ 	cmd = ehci_readl(ehci, &ehci->regs->command);
+ 	bh = 0;
+ 
+@@ -734,18 +734,17 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 
+ 	/* PCI errors [4.15.2.4] */
+ 	if (unlikely ((status & STS_FATAL) != 0)) {
++		ehci_err(ehci, "fatal error\n");
+ 		dbg_cmd(ehci, "fatal", cmd);
+ 		dbg_status(ehci, "fatal", status);
+-		if (status & STS_HALT) {
+-			ehci_err (ehci, "fatal error\n");
++		ehci_halt(ehci);
+ dead:
+-			ehci_reset (ehci);
+-			ehci_writel(ehci, 0, &ehci->regs->configured_flag);
+-			/* generic layer kills/unlinks all urbs, then
+-			 * uses ehci_stop to clean up the rest
+-			 */
+-			bh = 1;
+-		}
++		ehci_reset(ehci);
++		ehci_writel(ehci, 0, &ehci->regs->configured_flag);
++		/* generic layer kills/unlinks all urbs, then
++		 * uses ehci_stop to clean up the rest
++		 */
++		bh = 1;
+ 	}
+ 
+ 	if (bh)

commit 8010e06cc90367b4d3fba3b0ec3ced32360ac890
+Author: Alan Stern 
+Date:   Tue Nov 4 11:33:35 2008 -0500
+
+    USB: unusual_devs entry for Argosy USB mass-storage interface
+    
+    This patch (as1162) adds an unusual_devs entry for Argosy's USB-IDE
+    interface.  This fixes Bugzilla #11843.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Luciano Rocha 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index f379291d5387..b2ec15208523 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -1265,6 +1265,13 @@ UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_FIX_INQUIRY),
+ 
++/* Reported by Luciano Rocha  */
++UNUSUAL_DEV( 0x0840, 0x0082, 0x0001, 0x0001,
++		"Argosy",
++		"Storage",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_FIX_CAPACITY),
++
+ /* Entry and supporting patch by Theodore Kilgore .
+  * Flag will support Bulk devices which use a standards-violating 32-byte
+  * Command Block Wrapper. Here, the "DC2MEGA" cameras (several brands) with

commit 352d026338378b1f13f044e33c1047da6e470056
+Author: Alan Stern 
+Date:   Wed Oct 29 15:16:58 2008 -0400
+
+    USB: don't register endpoints for interfaces that are going away
+    
+    This patch (as1155) fixes a bug in usbcore.  When interfaces are
+    deleted, either because the device was disconnected or because of a
+    configuration change, the extra attribute files and child endpoint
+    devices may get left behind.  This is because the core removes them
+    before calling device_del().  But during device_del(), after the
+    driver is unbound the core will reinstall altsetting 0 and recreate
+    those extra attributes and children.
+    
+    The patch prevents this by adding a flag to record when the interface
+    is in the midst of being unregistered.  When the flag is set, the
+    attribute files and child devices will not be created.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable  [2.6.27, 2.6.26, 2.6.25]
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 887738577b28..6d1048faf08e 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1091,6 +1091,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
+ 				continue;
+ 			dev_dbg(&dev->dev, "unregistering interface %s\n",
+ 				dev_name(&interface->dev));
++			interface->unregistering = 1;
+ 			usb_remove_sysfs_intf_files(interface);
+ 			device_del(&interface->dev);
+ 		}
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index f66fba11fbd5..4fb65fdc9dc3 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -840,7 +840,7 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf)
+ 	struct usb_host_interface *alt = intf->cur_altsetting;
+ 	int retval;
+ 
+-	if (intf->sysfs_files_created)
++	if (intf->sysfs_files_created || intf->unregistering)
+ 		return 0;
+ 
+ 	/* The interface string may be present in some altsettings
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 8fa973bede5e..f72aa51f7bcd 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -108,6 +108,7 @@ enum usb_interface_condition {
+  *	(in probe()), bound to a driver, or unbinding (in disconnect())
+  * @is_active: flag set when the interface is bound and not suspended.
+  * @sysfs_files_created: sysfs attributes exist
++ * @unregistering: flag set when the interface is being unregistered
+  * @needs_remote_wakeup: flag set when the driver requires remote-wakeup
+  *	capability during autosuspend.
+  * @needs_altsetting0: flag set when a set-interface request for altsetting 0
+@@ -163,6 +164,7 @@ struct usb_interface {
+ 	enum usb_interface_condition condition;		/* state of binding */
+ 	unsigned is_active:1;		/* the interface is not suspended */
+ 	unsigned sysfs_files_created:1;	/* the sysfs attributes exist */
++	unsigned unregistering:1;	/* unregistration is in progress */
+ 	unsigned needs_remote_wakeup:1;	/* driver requires remote wakeup */
+ 	unsigned needs_altsetting0:1;	/* switch to altsetting 0 is pending */
+ 	unsigned needs_binding:1;	/* needs delayed unbind/rebind */

commit 7838c15b8dd18e78a523513749e5b54bda07b0cb
+Author: Alan Stern 
+Date:   Thu Nov 6 08:42:49 2008 +0100
+
+    Block: use round_jiffies_up()
+    
+    This patch (as1159b) changes the timeout routines in the block core to
+    use round_jiffies_up().  There's no point in rounding the timer
+    deadline down, since if it expires too early we will have to restart
+    it.
+    
+    The patch also removes some unnecessary tests when a request is
+    removed from the queue's timer list.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/blk-timeout.c b/block/blk-timeout.c
+index 972a63f848fb..69185ea9fae2 100644
+--- a/block/blk-timeout.c
++++ b/block/blk-timeout.c
+@@ -75,14 +75,7 @@ void blk_delete_timer(struct request *req)
+ {
+ 	struct request_queue *q = req->q;
+ 
+-	/*
+-	 * Nothing to detach
+-	 */
+-	if (!q->rq_timed_out_fn || !req->deadline)
+-		return;
+-
+ 	list_del_init(&req->timeout_list);
+-
+ 	if (list_empty(&q->timeout_list))
+ 		del_timer(&q->timeout);
+ }
+@@ -142,7 +135,7 @@ void blk_rq_timed_out_timer(unsigned long data)
+ 	}
+ 
+ 	if (next_set && !list_empty(&q->timeout_list))
+-		mod_timer(&q->timeout, round_jiffies(next));
++		mod_timer(&q->timeout, round_jiffies_up(next));
+ 
+ 	spin_unlock_irqrestore(q->queue_lock, flags);
+ }
+@@ -198,17 +191,10 @@ void blk_add_timer(struct request *req)
+ 
+ 	/*
+ 	 * If the timer isn't already pending or this timeout is earlier
+-	 * than an existing one, modify the timer. Round to next nearest
++	 * than an existing one, modify the timer. Round up to next nearest
+ 	 * second.
+ 	 */
+-	expiry = round_jiffies(req->deadline);
+-
+-	/*
+-	 * We use ->deadline == 0 to detect whether a timer was added or
+-	 * not, so just increase to next jiffy for that specific case
+-	 */
+-	if (unlikely(!req->deadline))
+-		req->deadline = 1;
++	expiry = round_jiffies_up(req->deadline);
+ 
+ 	if (!timer_pending(&q->timeout) ||
+ 	    time_before(expiry, q->timeout.expires))

commit 9c133c469d38043d5aadaa03f2fb840d88d1cf4f
+Author: Alan Stern 
+Date:   Thu Nov 6 08:42:48 2008 +0100
+
+    Add round_jiffies_up and related routines
+    
+    This patch (as1158b) adds round_jiffies_up() and friends.  These
+    routines work like the analogous round_jiffies() functions, except
+    that they will never round down.
+    
+    The new routines will be useful for timeouts where we don't care
+    exactly when the timer expires, provided it doesn't expire too soon.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/include/linux/timer.h b/include/linux/timer.h
+index d4ba79248a27..daf9685b861c 100644
+--- a/include/linux/timer.h
++++ b/include/linux/timer.h
+@@ -186,4 +186,9 @@ unsigned long __round_jiffies_relative(unsigned long j, int cpu);
+ unsigned long round_jiffies(unsigned long j);
+ unsigned long round_jiffies_relative(unsigned long j);
+ 
++unsigned long __round_jiffies_up(unsigned long j, int cpu);
++unsigned long __round_jiffies_up_relative(unsigned long j, int cpu);
++unsigned long round_jiffies_up(unsigned long j);
++unsigned long round_jiffies_up_relative(unsigned long j);
++
+ #endif
+diff --git a/kernel/timer.c b/kernel/timer.c
+index 56becf373c58..dbd50fabe4c7 100644
+--- a/kernel/timer.c
++++ b/kernel/timer.c
+@@ -112,27 +112,8 @@ timer_set_base(struct timer_list *timer, struct tvec_base *new_base)
+ 				      tbase_get_deferrable(timer->base));
+ }
+ 
+-/**
+- * __round_jiffies - function to round jiffies to a full second
+- * @j: the time in (absolute) jiffies that should be rounded
+- * @cpu: the processor number on which the timeout will happen
+- *
+- * __round_jiffies() rounds an absolute time in the future (in jiffies)
+- * up or down to (approximately) full seconds. This is useful for timers
+- * for which the exact time they fire does not matter too much, as long as
+- * they fire approximately every X seconds.
+- *
+- * By rounding these timers to whole seconds, all such timers will fire
+- * at the same time, rather than at various times spread out. The goal
+- * of this is to have the CPU wake up less, which saves power.
+- *
+- * The exact rounding is skewed for each processor to avoid all
+- * processors firing at the exact same time, which could lead
+- * to lock contention or spurious cache line bouncing.
+- *
+- * The return value is the rounded version of the @j parameter.
+- */
+-unsigned long __round_jiffies(unsigned long j, int cpu)
++static unsigned long round_jiffies_common(unsigned long j, int cpu,
++		bool force_up)
+ {
+ 	int rem;
+ 	unsigned long original = j;
+@@ -154,8 +135,9 @@ unsigned long __round_jiffies(unsigned long j, int cpu)
+ 	 * due to delays of the timer irq, long irq off times etc etc) then
+ 	 * we should round down to the whole second, not up. Use 1/4th second
+ 	 * as cutoff for this rounding as an extreme upper bound for this.
++	 * But never round down if @force_up is set.
+ 	 */
+-	if (rem < HZ/4) /* round down */
++	if (rem < HZ/4 && !force_up) /* round down */
+ 		j = j - rem;
+ 	else /* round up */
+ 		j = j - rem + HZ;
+@@ -167,6 +149,31 @@ unsigned long __round_jiffies(unsigned long j, int cpu)
+ 		return original;
+ 	return j;
+ }
++
++/**
++ * __round_jiffies - function to round jiffies to a full second
++ * @j: the time in (absolute) jiffies that should be rounded
++ * @cpu: the processor number on which the timeout will happen
++ *
++ * __round_jiffies() rounds an absolute time in the future (in jiffies)
++ * up or down to (approximately) full seconds. This is useful for timers
++ * for which the exact time they fire does not matter too much, as long as
++ * they fire approximately every X seconds.
++ *
++ * By rounding these timers to whole seconds, all such timers will fire
++ * at the same time, rather than at various times spread out. The goal
++ * of this is to have the CPU wake up less, which saves power.
++ *
++ * The exact rounding is skewed for each processor to avoid all
++ * processors firing at the exact same time, which could lead
++ * to lock contention or spurious cache line bouncing.
++ *
++ * The return value is the rounded version of the @j parameter.
++ */
++unsigned long __round_jiffies(unsigned long j, int cpu)
++{
++	return round_jiffies_common(j, cpu, false);
++}
+ EXPORT_SYMBOL_GPL(__round_jiffies);
+ 
+ /**
+@@ -191,13 +198,10 @@ EXPORT_SYMBOL_GPL(__round_jiffies);
+  */
+ unsigned long __round_jiffies_relative(unsigned long j, int cpu)
+ {
+-	/*
+-	 * In theory the following code can skip a jiffy in case jiffies
+-	 * increments right between the addition and the later subtraction.
+-	 * However since the entire point of this function is to use approximate
+-	 * timeouts, it's entirely ok to not handle that.
+-	 */
+-	return  __round_jiffies(j + jiffies, cpu) - jiffies;
++	unsigned long j0 = jiffies;
++
++	/* Use j0 because jiffies might change while we run */
++	return round_jiffies_common(j + j0, cpu, false) - j0;
+ }
+ EXPORT_SYMBOL_GPL(__round_jiffies_relative);
+ 
+@@ -218,7 +222,7 @@ EXPORT_SYMBOL_GPL(__round_jiffies_relative);
+  */
+ unsigned long round_jiffies(unsigned long j)
+ {
+-	return __round_jiffies(j, raw_smp_processor_id());
++	return round_jiffies_common(j, raw_smp_processor_id(), false);
+ }
+ EXPORT_SYMBOL_GPL(round_jiffies);
+ 
+@@ -243,6 +247,71 @@ unsigned long round_jiffies_relative(unsigned long j)
+ }
+ EXPORT_SYMBOL_GPL(round_jiffies_relative);
+ 
++/**
++ * __round_jiffies_up - function to round jiffies up to a full second
++ * @j: the time in (absolute) jiffies that should be rounded
++ * @cpu: the processor number on which the timeout will happen
++ *
++ * This is the same as __round_jiffies() except that it will never
++ * round down.  This is useful for timeouts for which the exact time
++ * of firing does not matter too much, as long as they don't fire too
++ * early.
++ */
++unsigned long __round_jiffies_up(unsigned long j, int cpu)
++{
++	return round_jiffies_common(j, cpu, true);
++}
++EXPORT_SYMBOL_GPL(__round_jiffies_up);
++
++/**
++ * __round_jiffies_up_relative - function to round jiffies up to a full second
++ * @j: the time in (relative) jiffies that should be rounded
++ * @cpu: the processor number on which the timeout will happen
++ *
++ * This is the same as __round_jiffies_relative() except that it will never
++ * round down.  This is useful for timeouts for which the exact time
++ * of firing does not matter too much, as long as they don't fire too
++ * early.
++ */
++unsigned long __round_jiffies_up_relative(unsigned long j, int cpu)
++{
++	unsigned long j0 = jiffies;
++
++	/* Use j0 because jiffies might change while we run */
++	return round_jiffies_common(j + j0, cpu, true) - j0;
++}
++EXPORT_SYMBOL_GPL(__round_jiffies_up_relative);
++
++/**
++ * round_jiffies_up - function to round jiffies up to a full second
++ * @j: the time in (absolute) jiffies that should be rounded
++ *
++ * This is the same as round_jiffies() except that it will never
++ * round down.  This is useful for timeouts for which the exact time
++ * of firing does not matter too much, as long as they don't fire too
++ * early.
++ */
++unsigned long round_jiffies_up(unsigned long j)
++{
++	return round_jiffies_common(j, raw_smp_processor_id(), true);
++}
++EXPORT_SYMBOL_GPL(round_jiffies_up);
++
++/**
++ * round_jiffies_up_relative - function to round jiffies up to a full second
++ * @j: the time in (relative) jiffies that should be rounded
++ *
++ * This is the same as round_jiffies_relative() except that it will never
++ * round down.  This is useful for timeouts for which the exact time
++ * of firing does not matter too much, as long as they don't fire too
++ * early.
++ */
++unsigned long round_jiffies_up_relative(unsigned long j)
++{
++	return __round_jiffies_up_relative(j, raw_smp_processor_id());
++}
++EXPORT_SYMBOL_GPL(round_jiffies_up_relative);
++
+ 
+ static inline void set_running_timer(struct tvec_base *base,
+ 					struct timer_list *timer)

commit fa157bdfe87c5ea98a80b96cb08f1ab509e21a52
+Author: Alan Stern 
+Date:   Thu Oct 30 01:06:13 2008 +0100
+
+    HID: add quirk entry for no-name keyboard (0x13ba/0x0017)
+    
+    This patch (as1157) adds a no-name PS/2-to-USB keyboard+mouse adapter
+    to the hid-dell driver.  (The device shows up with a Product string
+    saying "Generic USB K/B", nothing more.)  This will force an initial
+    "Set-LEDs" report to be sent to the device, without which it won't
+    send any keystroke information.  Several bug reports mentioning this
+    device have been filed in various forums; the patch should resolve
+    them.
+    
+    This is just a temporary stop-gap for 2.6.28.  A later patch for
+    2.6.29 will introduce a more generic mechanism for "Set-LEDs", making
+    this change (and the entire hid-dell driver) unnecessary.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
+index 743e6f8cb202..1903e7515650 100644
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -1263,6 +1263,7 @@ static const struct hid_device_id hid_blacklist[] = {
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
++	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
+diff --git a/drivers/hid/hid-dell.c b/drivers/hid/hid-dell.c
+index 1a0d0dfc62fc..f5474300b83a 100644
+--- a/drivers/hid/hid-dell.c
++++ b/drivers/hid/hid-dell.c
+@@ -48,6 +48,7 @@ static int dell_probe(struct hid_device *hdev, const struct hid_device_id *id)
+ static const struct hid_device_id dell_devices[] = {
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) },
++	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) },
+ 	{ }
+ };
+ MODULE_DEVICE_TABLE(hid, dell_devices);
+diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
+index a0d6a6cb1842..5cc404291736 100644
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -163,6 +163,9 @@
+ 
+ #define USB_VENDOR_ID_GENERAL_TOUCH	0x0dfc
+ 
++#define USB_VENDOR_ID_GENERIC_13BA	0x13ba
++#define USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE	0x0017
++
+ #define USB_VENDOR_ID_GLAB		0x06c2
+ #define USB_DEVICE_ID_4_PHIDGETSERVO_30	0x0038
+ #define USB_DEVICE_ID_1_PHIDGETSERVO_30	0x0039

commit 61fbeba11c553c489ba5284c0ed67067dc7b7c0f
+Author: Alan Stern 
+Date:   Mon Oct 27 12:07:44 2008 -0400
+
+    USB: prevent autosuspend during hub initialization
+    
+    This patch (as1153) fixes a potential problem in hub initialization.
+    Starting in 2.6.28, initialization was split into several tasks to
+    help speed up booting.  This opens the possibility that the hub may be
+    autosuspended before all the initialization tasks can complete.
+    
+    Normally that wouldn't matter, but with incomplete initialization
+    there is a risk that the hub would never autoresume -- especially if
+    devices were plugged into the hub beforehand.  The solution is a
+    simple one-line change to suppress autosuspend until the
+    initialization is finished.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 37ff8aed256d..b19cbfcd51da 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -659,6 +659,9 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ 			PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func2);
+ 			schedule_delayed_work(&hub->init_work,
+ 					msecs_to_jiffies(delay));
++
++			/* Suppress autosuspend until init is done */
++			to_usb_interface(hub->intfdev)->pm_usage_cnt = 1;
+ 			return;		/* Continues at init2: below */
+ 		} else {
+ 			hub_power_on(hub, true);

commit cde217a556ec552d28ac9e136c5a94684a69ae94
+Author: Alan Stern 
+Date:   Tue Oct 21 15:28:46 2008 -0400
+
+    USB: fix crash when URBs are unlinked after the device is gone
+    
+    This patch (as1151) protects usbcore against drivers that try to
+    unlink an URB after the URB's device or bus have been removed.  The
+    core does not currently check for this, and certain drivers can cause
+    a crash if they are running while an HCD is unloaded.
+    
+    Certainly it would be best to fix the guilty drivers.  But a little
+    defensive programming doesn't hurt, especially since it appears that
+    quite a few drivers need to be fixed.
+    
+    The patch prevents the problem by grabbing a reference to the device
+    while an unlink is in progress and using a new spinlock to synchronize
+    unlinks with device removal.  (There's no need to acquire a reference
+    to the bus as well, since the device structure itself keeps a
+    reference to the bus.)  In addition, the kerneldoc is updated to
+    indicate that URBs should not be unlinked after the disconnect method
+    returns.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index fc9018e72a09..e1b42626d04d 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -106,6 +106,9 @@ static DEFINE_SPINLOCK(hcd_root_hub_lock);
+ /* used when updating an endpoint's URB list */
+ static DEFINE_SPINLOCK(hcd_urb_list_lock);
+ 
++/* used to protect against unlinking URBs after the device is gone */
++static DEFINE_SPINLOCK(hcd_urb_unlink_lock);
++
+ /* wait queue for synchronous unlinks */
+ DECLARE_WAIT_QUEUE_HEAD(usb_kill_urb_queue);
+ 
+@@ -1376,10 +1379,25 @@ static int unlink1(struct usb_hcd *hcd, struct urb *urb, int status)
+ int usb_hcd_unlink_urb (struct urb *urb, int status)
+ {
+ 	struct usb_hcd		*hcd;
+-	int			retval;
++	int			retval = -EIDRM;
++	unsigned long		flags;
+ 
+-	hcd = bus_to_hcd(urb->dev->bus);
+-	retval = unlink1(hcd, urb, status);
++	/* Prevent the device and bus from going away while
++	 * the unlink is carried out.  If they are already gone
++	 * then urb->use_count must be 0, since disconnected
++	 * devices can't have any active URBs.
++	 */
++	spin_lock_irqsave(&hcd_urb_unlink_lock, flags);
++	if (atomic_read(&urb->use_count) > 0) {
++		retval = 0;
++		usb_get_dev(urb->dev);
++	}
++	spin_unlock_irqrestore(&hcd_urb_unlink_lock, flags);
++	if (retval == 0) {
++		hcd = bus_to_hcd(urb->dev->bus);
++		retval = unlink1(hcd, urb, status);
++		usb_put_dev(urb->dev);
++	}
+ 
+ 	if (retval == 0)
+ 		retval = -EINPROGRESS;
+@@ -1528,6 +1546,17 @@ void usb_hcd_disable_endpoint(struct usb_device *udev,
+ 		hcd->driver->endpoint_disable(hcd, ep);
+ }
+ 
++/* Protect against drivers that try to unlink URBs after the device
++ * is gone, by waiting until all unlinks for @udev are finished.
++ * Since we don't currently track URBs by device, simply wait until
++ * nothing is running in the locked region of usb_hcd_unlink_urb().
++ */
++void usb_hcd_synchronize_unlinks(struct usb_device *udev)
++{
++	spin_lock_irq(&hcd_urb_unlink_lock);
++	spin_unlock_irq(&hcd_urb_unlink_lock);
++}
++
+ /*-------------------------------------------------------------------------*/
+ 
+ /* called in any context */
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index 2dcde61c465e..9465e70f4dd0 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -232,6 +232,7 @@ extern void usb_hcd_flush_endpoint(struct usb_device *udev,
+ 		struct usb_host_endpoint *ep);
+ extern void usb_hcd_disable_endpoint(struct usb_device *udev,
+ 		struct usb_host_endpoint *ep);
++extern void usb_hcd_synchronize_unlinks(struct usb_device *udev);
+ extern int usb_hcd_get_frame_number(struct usb_device *udev);
+ 
+ extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver,
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 9b3f16bd12cb..37ff8aed256d 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1429,6 +1429,7 @@ void usb_disconnect(struct usb_device **pdev)
+ 	 */
+ 	dev_dbg (&udev->dev, "unregistering device\n");
+ 	usb_disable_device(udev, 0);
++	usb_hcd_synchronize_unlinks(udev);
+ 
+ 	usb_unlock_device(udev);
+ 
+diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
+index f2638009a464..4342bd9c3bb6 100644
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -474,6 +474,12 @@ EXPORT_SYMBOL_GPL(usb_submit_urb);
+  * indicating that the request has been canceled (rather than any other
+  * code).
+  *
++ * Drivers should not call this routine or related routines, such as
++ * usb_kill_urb() or usb_unlink_anchored_urbs(), after their disconnect
++ * method has returned.  The disconnect function should synchronize with
++ * a driver's I/O routines to insure that all URB-related activity has
++ * completed before it returns.
++ *
+  * This request is always asynchronous.  Success is indicated by
+  * returning -EINPROGRESS, at which time the URB will probably not yet
+  * have been given back to the device driver.  When it is eventually
+@@ -550,6 +556,9 @@ EXPORT_SYMBOL_GPL(usb_unlink_urb);
+  * This routine may not be used in an interrupt context (such as a bottom
+  * half or a completion handler), or when holding a spinlock, or in other
+  * situations where the caller can't schedule().
++ *
++ * This routine should not be called by a driver after its disconnect
++ * method has returned.
+  */
+ void usb_kill_urb(struct urb *urb)
+ {
+@@ -588,6 +597,9 @@ EXPORT_SYMBOL_GPL(usb_kill_urb);
+  * This routine may not be used in an interrupt context (such as a bottom
+  * half or a completion handler), or when holding a spinlock, or in other
+  * situations where the caller can't schedule().
++ *
++ * This routine should not be called by a driver after its disconnect
++ * method has returned.
+  */
+ void usb_poison_urb(struct urb *urb)
+ {
+@@ -622,6 +634,9 @@ EXPORT_SYMBOL_GPL(usb_unpoison_urb);
+  *
+  * this allows all outstanding URBs to be killed starting
+  * from the back of the queue
++ *
++ * This routine should not be called by a driver after its disconnect
++ * method has returned.
+  */
+ void usb_kill_anchored_urbs(struct usb_anchor *anchor)
+ {
+@@ -651,6 +666,9 @@ EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs);
+  * this allows all outstanding URBs to be poisoned starting
+  * from the back of the queue. Newly added URBs will also be
+  * poisoned
++ *
++ * This routine should not be called by a driver after its disconnect
++ * method has returned.
+  */
+ void usb_poison_anchored_urbs(struct usb_anchor *anchor)
+ {
+@@ -672,6 +690,7 @@ void usb_poison_anchored_urbs(struct usb_anchor *anchor)
+ 	spin_unlock_irq(&anchor->lock);
+ }
+ EXPORT_SYMBOL_GPL(usb_poison_anchored_urbs);
++
+ /**
+  * usb_unlink_anchored_urbs - asynchronously cancel transfer requests en masse
+  * @anchor: anchor the requests are bound to
+@@ -680,6 +699,9 @@ EXPORT_SYMBOL_GPL(usb_poison_anchored_urbs);
+  * from the back of the queue. This function is asynchronous.
+  * The unlinking is just tiggered. It may happen after this
+  * function has returned.
++ *
++ * This routine should not be called by a driver after its disconnect
++ * method has returned.
+  */
+ void usb_unlink_anchored_urbs(struct usb_anchor *anchor)
+ {

commit d4c9b736080056ae3ba81dcf2ac418193c57dbb1
+Author: Alan Stern 
+Date:   Fri Oct 10 16:03:20 2008 -0400
+
+    [SCSI] sd: remove command-size switching code
+    
+    This patch (as1138) removes from sd.c some old code for switching from
+    10-byte commands to 6-byte commands.  This code is redundant -- the
+    switching for READ and WRITE is already handled in
+    scsi_io_completion() and the switching for MODE SENSE is already
+    handled in scsi_mode_sense().  (There is no comparable switch for MODE
+    SELECT, but I doubt one is needed.)
+    
+    Furthermore the other handlers do a better job; they check for
+    appropriate ASC and ASCQ values before blindly switching the size.
+    The code in sd.c is known to cause problems with some devices by
+    switching when it shouldn't.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+index 55e6ed4b886d..7e22aa7b8b8a 100644
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -1084,15 +1084,6 @@ static int sd_done(struct scsi_cmnd *SCpnt)
+ 			scsi_print_sense("sd", SCpnt);
+ 			good_bytes = sd_completed_bytes(SCpnt);
+ 		}
+-		if (!scsi_device_protection(SCpnt->device) &&
+-		    SCpnt->device->use_10_for_rw &&
+-		    (SCpnt->cmnd[0] == READ_10 ||
+-		     SCpnt->cmnd[0] == WRITE_10))
+-			SCpnt->device->use_10_for_rw = 0;
+-		if (SCpnt->device->use_10_for_ms &&
+-		    (SCpnt->cmnd[0] == MODE_SENSE_10 ||
+-		     SCpnt->cmnd[0] == MODE_SELECT_10))
+-			SCpnt->device->use_10_for_ms = 0;
+ 		break;
+ 	default:
+ 		break;

commit 6c6409459a18a825ce12ecb003d5686af61f7a2f
+Author: Alan Stern 
+Date:   Tue Oct 21 15:40:03 2008 -0400
+
+    USB: don't rebind drivers after failed resume or reset
+    
+    This patch (as1152) may help prevent some problems associated with the
+    new policy of unbinding drivers that don't support suspend/resume or
+    pre_reset/post_reset.  If for any reason the resume or reset fails, and
+    the device is logically disconnected, there's no point in trying to
+    rebind the driver.  So the patch checks for success before carrying
+    out the unbind/rebind.
+    
+    There was a report from one user that this fixed a problem he was
+    experiencing, but the details never became fully clear.  In any case,
+    adding these tests can't hurt.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index e935be7eb468..3d7793d93031 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1610,7 +1610,8 @@ int usb_external_resume_device(struct usb_device *udev)
+ 	status = usb_resume_both(udev);
+ 	udev->last_busy = jiffies;
+ 	usb_pm_unlock(udev);
+-	do_unbind_rebind(udev, DO_REBIND);
++	if (status == 0)
++		do_unbind_rebind(udev, DO_REBIND);
+ 
+ 	/* Now that the device is awake, we can start trying to autosuspend
+ 	 * it again. */
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index d73ce262c365..9b3f16bd12cb 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -3504,7 +3504,7 @@ int usb_reset_device(struct usb_device *udev)
+ 						USB_INTERFACE_BOUND)
+ 					rebind = 1;
+ 			}
+-			if (rebind)
++			if (ret == 0 && rebind)
+ 				usb_rebind_intf(cintf);
+ 		}
+ 	}

commit 8fc7aeab3851ed8c3ecf28901ca2c6f0400955c7
+Author: Alan Stern 
+Date:   Mon Oct 20 09:52:12 2008 -0400
+
+    USB: Speedtouch: add pre_reset and post_reset routines
+    
+    This patch (as1150) fixes a problem in the speedtch driver.  When it
+    resets the modem during probe it will be unbound from the other
+    interfaces it has claimed, because it doesn't define a pre_reset and a
+    post_reset method.
+    
+    The patch defines "do-nothing" methods.  This fixes Bugzilla #11767.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
+index 76fce44c2f9a..3e862401a638 100644
+--- a/drivers/usb/atm/speedtch.c
++++ b/drivers/usb/atm/speedtch.c
+@@ -722,6 +722,16 @@ static void speedtch_atm_stop(struct usbatm_data *usbatm, struct atm_dev *atm_de
+ 	flush_scheduled_work();
+ }
+ 
++static int speedtch_pre_reset(struct usb_interface *intf)
++{
++	return 0;
++}
++
++static int speedtch_post_reset(struct usb_interface *intf)
++{
++	return 0;
++}
++
+ 
+ /**********
+ **  USB  **
+@@ -740,6 +750,8 @@ static struct usb_driver speedtch_usb_driver = {
+ 	.name		= speedtch_driver_name,
+ 	.probe		= speedtch_usb_probe,
+ 	.disconnect	= usbatm_usb_disconnect,
++	.pre_reset	= speedtch_pre_reset,
++	.post_reset	= speedtch_post_reset,
+ 	.id_table	= speedtch_usb_ids
+ };
+ 

commit 71b7497c078a97e2afb774ad7c1f8ff5bdda8a60
+Author: Alan Stern 
+Date:   Thu Oct 9 15:40:23 2008 -0400
+
+    USB: OHCI: fix endless polling behavior
+    
+    This patch (as1149) fixes an obscure problem in OHCI polling.  In the
+    current code, if the RHSC interrupt status flag turns on at a time
+    when RHSC interrupts are disabled, it will remain on forever:
+    
+            The interrupt handler is the only place where RHSC status
+            gets turned back off;
+    
+            The interrupt handler won't turn RHSC status off because it
+            doesn't turn off status flags if the corresponding interrupt
+            isn't enabled;
+    
+            RHSC interrupts will never get enabled because
+            ohci_root_hub_state_changes() doesn't reenable RHSC if RHSC
+            status is on!
+    
+    As a result we will continue polling indefinitely instead of reverting
+    to interrupt-driven operation, and the root hub will not autosuspend.
+    This particular sequence of events is not at all unusual; in fact
+    plugging a USB device into an OHCI controller will usually cause it to
+    occur.
+    
+    Of course, this is a bug.  The proper thing to do is to turn off RHSC
+    status just before reading the actual port status values.  That way
+    either a port status change will be detected (if it occurs before the
+    status read) or it will turn RHSC back on.  Possibly both, but that
+    won't hurt anything.
+    
+    We can still check for systems in which RHSC is totally broken, by
+    re-reading RHSC after clearing it and before reading the port
+    statuses.  (This re-read has to be done anyway, to post the earlier
+    write.)  If RHSC is on but no port-change statuses are set, then we
+    know that RHSC is broken and we can avoid re-enabling it.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index a150e85c901a..32bbce9718f0 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -359,17 +359,15 @@ static void ohci_finish_controller_resume(struct usb_hcd *hcd)
+ 
+ /* Carry out polling-, autostop-, and autoresume-related state changes */
+ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+-		int any_connected)
++		int any_connected, int rhsc_status)
+ {
+ 	int	poll_rh = 1;
+-	int	rhsc_status, rhsc_enable;
++	int	rhsc_enable;
+ 
+ 	/* Some broken controllers never turn off RHCS in the interrupt
+ 	 * status register.  For their sake we won't re-enable RHSC
+ 	 * interrupts if the interrupt bit is already active.
+ 	 */
+-	rhsc_status = ohci_readl(ohci, &ohci->regs->intrstatus) &
+-			OHCI_INTR_RHSC;
+ 	rhsc_enable = ohci_readl(ohci, &ohci->regs->intrenable) &
+ 			OHCI_INTR_RHSC;
+ 
+@@ -421,14 +419,23 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ 				ohci_rh_resume(ohci);
+ 			else
+ 				usb_hcd_resume_root_hub(ohci_to_hcd(ohci));
++
++		/* If remote wakeup is disabled, stop polling */
++		} else if (!ohci->autostop &&
++				!ohci_to_hcd(ohci)->self.root_hub->
++					do_remote_wakeup) {
++			poll_rh = 0;
++
+ 		} else {
+-			if (!rhsc_enable && !rhsc_status && (ohci->autostop ||
+-					ohci_to_hcd(ohci)->self.root_hub->
+-						do_remote_wakeup)) {
++			/* If no status changes are pending,
++			 * enable RHSC interrupts
++			 */
++			if (!rhsc_enable && !rhsc_status) {
+ 				rhsc_enable = OHCI_INTR_RHSC;
+ 				ohci_writel(ohci, rhsc_enable,
+ 						&ohci->regs->intrenable);
+ 			}
++			/* Keep polling until RHSC is enabled */
+ 			if (rhsc_enable)
+ 				poll_rh = 0;
+ 		}
+@@ -448,22 +455,22 @@ static inline int ohci_rh_resume(struct ohci_hcd *ohci)
+  * autostop isn't used when CONFIG_PM is turned off.
+  */
+ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+-		int any_connected)
++		int any_connected, int rhsc_status)
+ {
+-	int	rhsc_status;
+-
+ 	/* If RHSC is enabled, don't poll */
+ 	if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC)
+ 		return 0;
+ 
+-	/* If no status changes are pending, enable RHSC interrupts */
+-	rhsc_status = ohci_readl(ohci, &ohci->regs->intrstatus) &
+-			OHCI_INTR_RHSC;
+-	if (!changed && !rhsc_status) {
+-		ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
+-		return 0;
+-	}
+-	return 1;
++	/* If status changes are pending, continue polling.
++	 * Conversely, if no status changes are pending but the RHSC
++	 * status bit was set, then RHSC may be broken so continue polling.
++	 */
++	if (changed || rhsc_status)
++		return 1;
++
++	/* It's safe to re-enable RHSC interrupts */
++	ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
++	return 0;
+ }
+ 
+ #endif	/* CONFIG_PM */
+@@ -478,6 +485,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
+ 	int		i, changed = 0, length = 1;
+ 	int		any_connected = 0;
++	int		rhsc_status;
+ 	unsigned long	flags;
+ 
+ 	spin_lock_irqsave (&ohci->lock, flags);
+@@ -503,6 +511,11 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ 		length++;
+ 	}
+ 
++	/* Clear the RHSC status flag before reading the port statuses */
++	ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrstatus);
++	rhsc_status = ohci_readl(ohci, &ohci->regs->intrstatus) &
++			OHCI_INTR_RHSC;
++
+ 	/* look at each port */
+ 	for (i = 0; i < ohci->num_ports; i++) {
+ 		u32	status = roothub_portstatus (ohci, i);
+@@ -521,7 +534,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ 	}
+ 
+ 	hcd->poll_rh = ohci_root_hub_state_changes(ohci, changed,
+-			any_connected);
++			any_connected, rhsc_status);
+ 
+ done:
+ 	spin_unlock_irqrestore (&ohci->lock, flags);

commit eafe5b99f2135488b21cf17a262c54997c44f784
+Author: Alan Stern 
+Date:   Mon Oct 6 11:25:53 2008 -0400
+
+    USB: EHCI: fix remote-wakeup support for ARC/TDI core
+    
+    This patch (as1147) fixes the remote-wakeup support for EHCI
+    controllers using the ARC/TDI "embedded-TT" core.  These controllers
+    turn off the RESUME bit by themselves when a port resume is complete;
+    hence we need to keep separate track of which ports are suspended or
+    in the process of resuming.
+    
+    The patch also makes a couple of small improvements in ehci_irq(),
+    replacing reads of the command register with the value already stored
+    in a local variable.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Thomas Reitmayr 
+    CC: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 358df2a6c396..d343afacb0b0 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -706,7 +706,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 		pcd_status = status;
+ 
+ 		/* resume root hub? */
+-		if (!(ehci_readl(ehci, &ehci->regs->command) & CMD_RUN))
++		if (!(cmd & CMD_RUN))
+ 			usb_hcd_resume_root_hub(hcd);
+ 
+ 		while (i--) {
+@@ -715,8 +715,11 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 
+ 			if (pstatus & PORT_OWNER)
+ 				continue;
+-			if (!(pstatus & PORT_RESUME)
+-					|| ehci->reset_done [i] != 0)
++			if (!(test_bit(i, &ehci->suspended_ports) &&
++					((pstatus & PORT_RESUME) ||
++						!(pstatus & PORT_SUSPEND)) &&
++					(pstatus & PORT_PE) &&
++					ehci->reset_done[i] == 0))
+ 				continue;
+ 
+ 			/* start 20 msec resume signaling from this port,
+@@ -731,9 +734,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 
+ 	/* PCI errors [4.15.2.4] */
+ 	if (unlikely ((status & STS_FATAL) != 0)) {
+-		dbg_cmd (ehci, "fatal", ehci_readl(ehci,
+-						   &ehci->regs->command));
+-		dbg_status (ehci, "fatal", status);
++		dbg_cmd(ehci, "fatal", cmd);
++		dbg_status(ehci, "fatal", status);
+ 		if (status & STS_HALT) {
+ 			ehci_err (ehci, "fatal error\n");
+ dead:
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 740835bb8575..218f9660d7ee 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -236,10 +236,8 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 		temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
+ 		temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
+ 		if (test_bit(i, &ehci->bus_suspended) &&
+-				(temp & PORT_SUSPEND)) {
+-			ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
++				(temp & PORT_SUSPEND))
+ 			temp |= PORT_RESUME;
+-		}
+ 		ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
+ 	}
+ 	i = HCS_N_PORTS (ehci->hcs_params);
+@@ -482,10 +480,9 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ 		 * controller by the user.
+ 		 */
+ 
+-		if ((temp & mask) != 0
+-				|| ((temp & PORT_RESUME) != 0
+-					&& time_after_eq(jiffies,
+-						ehci->reset_done[i]))) {
++		if ((temp & mask) != 0 || test_bit(i, &ehci->port_c_suspend)
++				|| (ehci->reset_done[i] && time_after_eq(
++					jiffies, ehci->reset_done[i]))) {
+ 			if (i < 7)
+ 			    buf [0] |= 1 << (i + 1);
+ 			else
+@@ -688,6 +685,7 @@ static int ehci_hub_control (
+ 			/* resume completed? */
+ 			else if (time_after_eq(jiffies,
+ 					ehci->reset_done[wIndex])) {
++				clear_bit(wIndex, &ehci->suspended_ports);
+ 				set_bit(wIndex, &ehci->port_c_suspend);
+ 				ehci->reset_done[wIndex] = 0;
+ 
+@@ -734,6 +732,9 @@ static int ehci_hub_control (
+ 					ehci_readl(ehci, status_reg));
+ 		}
+ 
++		if (!(temp & (PORT_RESUME|PORT_RESET)))
++			ehci->reset_done[wIndex] = 0;
++
+ 		/* transfer dedicated ports to the companion hc */
+ 		if ((temp & PORT_CONNECT) &&
+ 				test_bit(wIndex, &ehci->companion_ports)) {
+@@ -757,8 +758,17 @@ static int ehci_hub_control (
+ 		}
+ 		if (temp & PORT_PE)
+ 			status |= 1 << USB_PORT_FEAT_ENABLE;
+-		if (temp & (PORT_SUSPEND|PORT_RESUME))
++
++		/* maybe the port was unsuspended without our knowledge */
++		if (temp & (PORT_SUSPEND|PORT_RESUME)) {
+ 			status |= 1 << USB_PORT_FEAT_SUSPEND;
++		} else if (test_bit(wIndex, &ehci->suspended_ports)) {
++			clear_bit(wIndex, &ehci->suspended_ports);
++			ehci->reset_done[wIndex] = 0;
++			if (temp & PORT_PE)
++				set_bit(wIndex, &ehci->port_c_suspend);
++		}
++
+ 		if (temp & PORT_OC)
+ 			status |= 1 << USB_PORT_FEAT_OVER_CURRENT;
+ 		if (temp & PORT_RESET)
+@@ -803,6 +813,7 @@ static int ehci_hub_control (
+ 					|| (temp & PORT_RESET) != 0)
+ 				goto error;
+ 			ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
++			set_bit(wIndex, &ehci->suspended_ports);
+ 			break;
+ 		case USB_PORT_FEAT_POWER:
+ 			if (HCS_PPC (ehci->hcs_params))
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index a6fd550b6903..b11798d17ae5 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -99,6 +99,8 @@ struct ehci_hcd {			/* one per controller */
+ 			owned by the companion during a bus suspend */
+ 	unsigned long		port_c_suspend;		/* which ports have
+ 			the change-suspend feature turned on */
++	unsigned long		suspended_ports;	/* which ports are
++			suspended */
+ 
+ 	/* per-HC memory pools (could be per-bus, but ...) */
+ 	struct dma_pool		*qh_pool;	/* qh per active urb */

commit 2da41d5f6c036e7a6e496a7e601a685f8b87acb0
+Author: Alan Stern 
+Date:   Mon Oct 6 11:24:26 2008 -0400
+
+    USB: snoop processes opening usbfs device files
+    
+    This patch (as1148) adds a new "snoop" message to usbfs when a device
+    file is opened, identifying the process responsible.  This comes in
+    extremely handy when trying to determine which program is doing some
+    unwanted USB access.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 7a4fa791dc19..528befdcc781 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -624,6 +624,8 @@ static int usbdev_open(struct inode *inode, struct file *file)
+ 	smp_wmb();
+ 	list_add_tail(&ps->list, &dev->filelist);
+ 	file->private_data = ps;
++	snoop(&dev->dev, "opened by process %d: %s\n", task_pid_nr(current),
++			current->comm);
+  out:
+ 	if (ret) {
+ 		kfree(ps);

commit 9beeee6584b9aa4f9192055512411484a2a624df
+Author: Alan Stern 
+Date:   Thu Oct 2 11:48:13 2008 -0400
+
+    USB: EHCI: log a warning if ehci-hcd is not loaded first
+    
+    This patch (as1139) adds a warning to the system log whenever ehci-hcd
+    is loaded after ohci-hcd or uhci-hcd.  Nowadays most distributions are
+    pretty good about not doing this; maybe the warning will help convince
+    anyone still doing it wrong.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable   [2.6.27]
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index c8035a8216bd..fc9018e72a09 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -81,6 +81,10 @@
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++/* Keep track of which host controller drivers are loaded */
++unsigned long usb_hcds_loaded;
++EXPORT_SYMBOL_GPL(usb_hcds_loaded);
++
+ /* host controllers we manage */
+ LIST_HEAD (usb_bus_list);
+ EXPORT_SYMBOL_GPL (usb_bus_list);
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index e710ce04e228..2dcde61c465e 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -482,4 +482,10 @@ static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb,
+  */
+ extern struct rw_semaphore ehci_cf_port_reset_rwsem;
+ 
++/* Keep track of which host controller drivers are loaded */
++#define USB_UHCI_LOADED		0
++#define USB_OHCI_LOADED		1
++#define USB_EHCI_LOADED		2
++extern unsigned long usb_hcds_loaded;
++
+ #endif /* __KERNEL__ */
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index fcbc1f2b2377..358df2a6c396 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1046,6 +1046,12 @@ static int __init ehci_hcd_init(void)
+ 		return -ENODEV;
+ 
+ 	printk(KERN_INFO "%s: " DRIVER_DESC "\n", hcd_name);
++	set_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
++	if (test_bit(USB_UHCI_LOADED, &usb_hcds_loaded) ||
++			test_bit(USB_OHCI_LOADED, &usb_hcds_loaded))
++		printk(KERN_WARNING "Warning! ehci_hcd should always be loaded"
++				" before uhci_hcd and ohci_hcd, not after\n");
++
+ 	pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n",
+ 		 hcd_name,
+ 		 sizeof(struct ehci_qh), sizeof(struct ehci_qtd),
+@@ -1053,8 +1059,10 @@ static int __init ehci_hcd_init(void)
+ 
+ #ifdef DEBUG
+ 	ehci_debug_root = debugfs_create_dir("ehci", NULL);
+-	if (!ehci_debug_root)
+-		return -ENOENT;
++	if (!ehci_debug_root) {
++		retval = -ENOENT;
++		goto err_debug;
++	}
+ #endif
+ 
+ #ifdef PLATFORM_DRIVER
+@@ -1102,6 +1110,8 @@ static int __init ehci_hcd_init(void)
+ 	debugfs_remove(ehci_debug_root);
+ 	ehci_debug_root = NULL;
+ #endif
++err_debug:
++	clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
+ 	return retval;
+ }
+ module_init(ehci_hcd_init);
+@@ -1123,6 +1133,7 @@ static void __exit ehci_hcd_cleanup(void)
+ #ifdef DEBUG
+ 	debugfs_remove(ehci_debug_root);
+ #endif
++	clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
+ }
+ module_exit(ehci_hcd_cleanup);
+ 
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index 0afeda836df3..8647dab0d7f9 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -1095,6 +1095,7 @@ static int __init ohci_hcd_mod_init(void)
+ 	printk(KERN_INFO "%s: " DRIVER_DESC "\n", hcd_name);
+ 	pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name,
+ 		sizeof (struct ed), sizeof (struct td));
++	set_bit(USB_OHCI_LOADED, &usb_hcds_loaded);
+ 
+ #ifdef DEBUG
+ 	ohci_debug_root = debugfs_create_dir("ohci", NULL);
+@@ -1181,6 +1182,7 @@ static int __init ohci_hcd_mod_init(void)
+  error_debug:
+ #endif
+ 
++	clear_bit(USB_OHCI_LOADED, &usb_hcds_loaded);
+ 	return retval;
+ }
+ module_init(ohci_hcd_mod_init);
+@@ -1211,6 +1213,7 @@ static void __exit ohci_hcd_mod_exit(void)
+ #ifdef DEBUG
+ 	debugfs_remove(ohci_debug_root);
+ #endif
++	clear_bit(USB_OHCI_LOADED, &usb_hcds_loaded);
+ }
+ module_exit(ohci_hcd_mod_exit);
+ 
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 2dddb258b0db..cf5e4cf7ea42 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -955,6 +955,7 @@ static int __init uhci_hcd_init(void)
+ 
+ 	printk(KERN_INFO "uhci_hcd: " DRIVER_DESC "%s\n",
+ 			ignore_oc ? ", overcurrent ignored" : "");
++	set_bit(USB_UHCI_LOADED, &usb_hcds_loaded);
+ 
+ 	if (DEBUG_CONFIGURED) {
+ 		errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL);
+@@ -987,6 +988,7 @@ static int __init uhci_hcd_init(void)
+ 
+ errbuf_failed:
+ 
++	clear_bit(USB_UHCI_LOADED, &usb_hcds_loaded);
+ 	return retval;
+ }
+ 
+@@ -996,6 +998,7 @@ static void __exit uhci_hcd_cleanup(void)
+ 	kmem_cache_destroy(uhci_up_cachep);
+ 	debugfs_remove(uhci_debugfs_root);
+ 	kfree(errbuf);
++	clear_bit(USB_UHCI_LOADED, &usb_hcds_loaded);
+ }
+ 
+ module_init(uhci_hcd_init);

commit 2b70f07343389cb474235def00b021a645ede916
+Author: Alan Stern 
+Date:   Thu Oct 2 11:47:15 2008 -0400
+
+    USB: EHCI, OHCI, UHCI: remove version numbers
+    
+    This patch (as1145) removes the essentially useless driver-version
+    strings from ehci-hcd, ohci-hcd, and uhci-hcd.  It also unifies the
+    form of the banner lines they display upon loading and adds a missing
+    test for usb_disabled() to ehci-hcd.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
+index 5d57773e730e..0cb53ca8d343 100644
+--- a/drivers/usb/host/ehci-dbg.c
++++ b/drivers/usb/host/ehci-dbg.c
+@@ -675,7 +675,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
+ 
+ 	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+ 		size = scnprintf (next, size,
+-			"bus %s, device %s (driver " DRIVER_VERSION ")\n"
++			"bus %s, device %s\n"
+ 			"%s\n"
+ 			"SUSPENDED (no register access)\n",
+ 			hcd->self.controller->bus->name,
+@@ -687,7 +687,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
+ 	/* Capability Registers */
+ 	i = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase));
+ 	temp = scnprintf (next, size,
+-		"bus %s, device %s (driver " DRIVER_VERSION ")\n"
++		"bus %s, device %s\n"
+ 		"%s\n"
+ 		"EHCI %x.%02x, hcd state %d\n",
+ 		hcd->self.controller->bus->name,
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index c6f9961eed3c..fcbc1f2b2377 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -60,7 +60,6 @@
+  * providing early devices for those host controllers to talk to!
+  */
+ 
+-#define DRIVER_VERSION "10 Dec 2004"
+ #define DRIVER_AUTHOR "David Brownell"
+ #define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver"
+ 
+@@ -621,9 +620,9 @@ static int ehci_run (struct usb_hcd *hcd)
+ 
+ 	temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase));
+ 	ehci_info (ehci,
+-		"USB %x.%x started, EHCI %x.%02x, driver %s%s\n",
++		"USB %x.%x started, EHCI %x.%02x%s\n",
+ 		((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
+-		temp >> 8, temp & 0xff, DRIVER_VERSION,
++		temp >> 8, temp & 0xff,
+ 		ignore_oc ? ", overcurrent ignored" : "");
+ 
+ 	ehci_writel(ehci, INTR_MASK,
+@@ -995,9 +994,7 @@ static int ehci_get_frame (struct usb_hcd *hcd)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC
+-
+-MODULE_DESCRIPTION (DRIVER_INFO);
++MODULE_DESCRIPTION(DRIVER_DESC);
+ MODULE_AUTHOR (DRIVER_AUTHOR);
+ MODULE_LICENSE ("GPL");
+ 
+@@ -1045,6 +1042,10 @@ static int __init ehci_hcd_init(void)
+ {
+ 	int retval = 0;
+ 
++	if (usb_disabled())
++		return -ENODEV;
++
++	printk(KERN_INFO "%s: " DRIVER_DESC "\n", hcd_name);
+ 	pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n",
+ 		 hcd_name,
+ 		 sizeof(struct ehci_qh), sizeof(struct ehci_qtd),
+diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
+index 7cef1d2f7ccc..d3269656aa4d 100644
+--- a/drivers/usb/host/ohci-dbg.c
++++ b/drivers/usb/host/ohci-dbg.c
+@@ -649,7 +649,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
+ 	ohci_dbg_sw (ohci, &next, &size,
+ 		"bus %s, device %s\n"
+ 		"%s\n"
+-		"%s version " DRIVER_VERSION "\n",
++		"%s\n",
+ 		hcd->self.controller->bus->name,
+ 		dev_name(hcd->self.controller),
+ 		hcd->product_desc,
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index 89901962cbfd..0afeda836df3 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -46,7 +46,6 @@
+ 
+ #include "../core/hcd.h"
+ 
+-#define DRIVER_VERSION "2006 August 04"
+ #define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell"
+ #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver"
+ 
+@@ -984,10 +983,8 @@ static int ohci_restart (struct ohci_hcd *ohci)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC
+-
+ MODULE_AUTHOR (DRIVER_AUTHOR);
+-MODULE_DESCRIPTION (DRIVER_INFO);
++MODULE_DESCRIPTION(DRIVER_DESC);
+ MODULE_LICENSE ("GPL");
+ 
+ #ifdef CONFIG_PCI
+@@ -1095,7 +1092,7 @@ static int __init ohci_hcd_mod_init(void)
+ 	if (usb_disabled())
+ 		return -ENODEV;
+ 
+-	printk (KERN_DEBUG "%s: " DRIVER_INFO "\n", hcd_name);
++	printk(KERN_INFO "%s: " DRIVER_DESC "\n", hcd_name);
+ 	pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name,
+ 		sizeof (struct ed), sizeof (struct td));
+ 
+diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c
+index 658a2a978c32..e306ca6aef3d 100644
+--- a/drivers/usb/host/ohci-pnx4008.c
++++ b/drivers/usb/host/ohci-pnx4008.c
+@@ -331,7 +331,7 @@ static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev)
+ 
+ 	int ret = 0, irq;
+ 
+-	dev_dbg(&pdev->dev, "%s: " DRIVER_INFO " (pnx4008)\n", hcd_name);
++	dev_dbg(&pdev->dev, "%s: " DRIVER_DESC " (pnx4008)\n", hcd_name);
+ 	if (usb_disabled()) {
+ 		err("USB is disabled");
+ 		ret = -ENODEV;
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 3a7bfe7a8874..2dddb258b0db 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -53,7 +53,6 @@
+ /*
+  * Version Information
+  */
+-#define DRIVER_VERSION "v3.0"
+ #define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, \
+ Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \
+ Alan Stern"
+@@ -951,12 +950,12 @@ static int __init uhci_hcd_init(void)
+ {
+ 	int retval = -ENOMEM;
+ 
+-	printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION "%s\n",
+-			ignore_oc ? ", overcurrent ignored" : "");
+-
+ 	if (usb_disabled())
+ 		return -ENODEV;
+ 
++	printk(KERN_INFO "uhci_hcd: " DRIVER_DESC "%s\n",
++			ignore_oc ? ", overcurrent ignored" : "");
++
+ 	if (DEBUG_CONFIGURED) {
+ 		errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL);
+ 		if (!errbuf)

commit e58dcebcd83b5902411e747ee7807219dee6bcf2
+Author: Alan Stern 
+Date:   Thu Sep 25 16:59:57 2008 -0400
+
+    USB: UHCI: improve scheduling of interrupt URBs
+    
+    This patch (as1140) adds a little intelligence to the interrupt-URB
+    scheduler in uhci-hcd.  Right now the scheduler is stupid; every URB
+    having the same period is assigned to the same slot.  Thus a large
+    group of period-N URBs can fill their slot and cause -ENOSPC errors
+    even when all the lower-period slots are empty.
+    
+    With the patch, if an URB doesn't fit in its assigned slot then the
+    scheduler will try using lower-period slots.  This will provide
+    greater flexibility.  As an example, the driver will be able to handle
+    more than just three or four mice, which the current driver cannot.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 1f0c2cf26e5d..5631d89c8730 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -1065,13 +1065,18 @@ static int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb,
+ 		}
+ 		if (exponent < 0)
+ 			return -EINVAL;
+-		qh->period = 1 << exponent;
+-		qh->skel = SKEL_INDEX(exponent);
+ 
+-		/* For now, interrupt phase is fixed by the layout
+-		 * of the QH lists. */
+-		qh->phase = (qh->period / 2) & (MAX_PHASE - 1);
+-		ret = uhci_check_bandwidth(uhci, qh);
++		/* If the slot is full, try a lower period */
++		do {
++			qh->period = 1 << exponent;
++			qh->skel = SKEL_INDEX(exponent);
++
++			/* For now, interrupt phase is fixed by the layout
++			 * of the QH lists.
++			 */
++			qh->phase = (qh->period / 2) & (MAX_PHASE - 1);
++			ret = uhci_check_bandwidth(uhci, qh);
++		} while (ret != 0 && --exponent >= 0);
+ 		if (ret)
+ 			return ret;
+ 	} else if (qh->period > urb->interval)

commit 8520f38099ccfdac2147a0852f84ee7a8ee5e197
+Author: Alan Stern 
+Date:   Mon Sep 22 14:44:26 2008 -0400
+
+    USB: change hub initialization sleeps to delayed_work
+    
+    This patch (as1137) changes the hub_activate() routine, replacing the
+    power-power-up and debounce delays with delayed_work calls.  The idea
+    is that on systems where the USB stack is compiled into the kernel
+    rather than built as modules, these delays will no longer block the
+    boot thread.  At least 100 ms is saved for each root hub, which can
+    add up to a significant savings in total boot time.
+    
+    Arjan van de Ven was very pleased to see that this shaved 700 ms off
+    his computer's boot time.  Since his total boot time is on the order
+    of two seconds, the improvement is considerable.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Arjan van de Ven 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index d99963873e37..b97110ca352d 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -77,6 +77,7 @@ struct usb_hub {
+ 	unsigned		has_indicators:1;
+ 	u8			indicator[USB_MAXCHILDREN];
+ 	struct delayed_work	leds;
++	struct delayed_work	init_work;
+ };
+ 
+ 
+@@ -515,10 +516,14 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe)
+ }
+ EXPORT_SYMBOL_GPL(usb_hub_tt_clear_buffer);
+ 
+-static void hub_power_on(struct usb_hub *hub)
++/* If do_delay is false, return the number of milliseconds the caller
++ * needs to delay.
++ */
++static unsigned hub_power_on(struct usb_hub *hub, bool do_delay)
+ {
+ 	int port1;
+ 	unsigned pgood_delay = hub->descriptor->bPwrOn2PwrGood * 2;
++	unsigned delay;
+ 	u16 wHubCharacteristics =
+ 			le16_to_cpu(hub->descriptor->wHubCharacteristics);
+ 
+@@ -537,7 +542,10 @@ static void hub_power_on(struct usb_hub *hub)
+ 		set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER);
+ 
+ 	/* Wait at least 100 msec for power to become stable */
+-	msleep(max(pgood_delay, (unsigned) 100));
++	delay = max(pgood_delay, (unsigned) 100);
++	if (do_delay)
++		msleep(delay);
++	return delay;
+ }
+ 
+ static int hub_hub_status(struct usb_hub *hub,
+@@ -599,21 +607,55 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
+ }
+ 
+ enum hub_activation_type {
+-	HUB_INIT, HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME
++	HUB_INIT, HUB_INIT2, HUB_INIT3,
++	HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME,
+ };
+ 
++static void hub_init_func2(struct work_struct *ws);
++static void hub_init_func3(struct work_struct *ws);
++
+ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ {
+ 	struct usb_device *hdev = hub->hdev;
+ 	int port1;
+ 	int status;
+ 	bool need_debounce_delay = false;
++	unsigned delay;
++
++	/* Continue a partial initialization */
++	if (type == HUB_INIT2)
++		goto init2;
++	if (type == HUB_INIT3)
++		goto init3;
+ 
+ 	/* After a resume, port power should still be on.
+ 	 * For any other type of activation, turn it on.
+ 	 */
+-	if (type != HUB_RESUME)
+-		hub_power_on(hub);
++	if (type != HUB_RESUME) {
++
++		/* Speed up system boot by using a delayed_work for the
++		 * hub's initial power-up delays.  This is pretty awkward
++		 * and the implementation looks like a home-brewed sort of
++		 * setjmp/longjmp, but it saves at least 100 ms for each
++		 * root hub (assuming usbcore is compiled into the kernel
++		 * rather than as a module).  It adds up.
++		 *
++		 * This can't be done for HUB_RESUME or HUB_RESET_RESUME
++		 * because for those activation types the ports have to be
++		 * operational when we return.  In theory this could be done
++		 * for HUB_POST_RESET, but it's easier not to.
++		 */
++		if (type == HUB_INIT) {
++			delay = hub_power_on(hub, false);
++			PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func2);
++			schedule_delayed_work(&hub->init_work,
++					msecs_to_jiffies(delay));
++			return;		/* Continues at init2: below */
++		} else {
++			hub_power_on(hub, true);
++		}
++	}
++ init2:
+ 
+ 	/* Check each port and set hub->change_bits to let khubd know
+ 	 * which ports need attention.
+@@ -692,9 +734,20 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ 	 * If any port-status changes do occur during this delay, khubd
+ 	 * will see them later and handle them normally.
+ 	 */
+-	if (need_debounce_delay)
+-		msleep(HUB_DEBOUNCE_STABLE);
+-
++	if (need_debounce_delay) {
++		delay = HUB_DEBOUNCE_STABLE;
++
++		/* Don't do a long sleep inside a workqueue routine */
++		if (type == HUB_INIT2) {
++			PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func3);
++			schedule_delayed_work(&hub->init_work,
++					msecs_to_jiffies(delay));
++			return;		/* Continues at init3: below */
++		} else {
++			msleep(delay);
++		}
++	}
++ init3:
+ 	hub->quiescing = 0;
+ 
+ 	status = usb_submit_urb(hub->urb, GFP_NOIO);
+@@ -707,6 +760,21 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ 	kick_khubd(hub);
+ }
+ 
++/* Implement the continuations for the delays above */
++static void hub_init_func2(struct work_struct *ws)
++{
++	struct usb_hub *hub = container_of(ws, struct usb_hub, init_work.work);
++
++	hub_activate(hub, HUB_INIT2);
++}
++
++static void hub_init_func3(struct work_struct *ws)
++{
++	struct usb_hub *hub = container_of(ws, struct usb_hub, init_work.work);
++
++	hub_activate(hub, HUB_INIT3);
++}
++
+ enum hub_quiescing_type {
+ 	HUB_DISCONNECT, HUB_PRE_RESET, HUB_SUSPEND
+ };
+@@ -716,6 +784,8 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
+ 	struct usb_device *hdev = hub->hdev;
+ 	int i;
+ 
++	cancel_delayed_work_sync(&hub->init_work);
++
+ 	/* khubd and related activity won't re-trigger */
+ 	hub->quiescing = 1;
+ 
+@@ -1099,6 +1169,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
+ 	hub->intfdev = &intf->dev;
+ 	hub->hdev = hdev;
+ 	INIT_DELAYED_WORK(&hub->leds, led_work);
++	INIT_DELAYED_WORK(&hub->init_work, NULL);
+ 	usb_get_intf(intf);
+ 
+ 	usb_set_intfdata (intf, hub);
+@@ -3035,7 +3106,7 @@ static void hub_events(void)
+ 					i);
+ 				clear_port_feature(hdev, i,
+ 					USB_PORT_FEAT_C_OVER_CURRENT);
+-				hub_power_on(hub);
++				hub_power_on(hub, true);
+ 			}
+ 
+ 			if (portchange & USB_PORT_STAT_C_RESET) {
+@@ -3070,7 +3141,7 @@ static void hub_events(void)
+ 				dev_dbg (hub_dev, "overcurrent change\n");
+ 				msleep(500);	/* Cool down */
+ 				clear_hub_feature(hdev, C_HUB_OVER_CURRENT);
+-                        	hub_power_on(hub);
++                        	hub_power_on(hub, true);
+ 			}
+ 		}
+ 

commit 4a511bc3f5829bc18428bcf11c25417a79d09396
+Author: Alan Stern 
+Date:   Wed Sep 3 16:38:32 2008 -0400
+
+    OHCI: Allow broken controllers to auto-stop
+    
+    This patch (as1134) attempts to improve the way we handle OHCI
+    controllers with broken Root Hub Status Change interrupt support.  In
+    these controllers the RHSC interrupt bit essentially never turns off,
+    making RHSC interrupts useless -- they have to remain permanently
+    disabled.
+    
+    Such controllers should still be allowed to turn off their root hubs
+    when no devices are attached.  Polling for new connections can
+    continue while the root hub is suspended.  The patch implements this
+    feature.  (It won't have much effect unless CONFIG_PM is enabled and
+    CONFIG_USB_SUSPEND is disabled, but since the overhead is very small
+    we may as well do it.)
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index 7ea9a7b31155..a150e85c901a 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -362,18 +362,23 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ 		int any_connected)
+ {
+ 	int	poll_rh = 1;
+-	int	rhsc;
++	int	rhsc_status, rhsc_enable;
+ 
+-	rhsc = ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC;
+-	switch (ohci->hc_control & OHCI_CTRL_HCFS) {
++	/* Some broken controllers never turn off RHCS in the interrupt
++	 * status register.  For their sake we won't re-enable RHSC
++	 * interrupts if the interrupt bit is already active.
++	 */
++	rhsc_status = ohci_readl(ohci, &ohci->regs->intrstatus) &
++			OHCI_INTR_RHSC;
++	rhsc_enable = ohci_readl(ohci, &ohci->regs->intrenable) &
++			OHCI_INTR_RHSC;
+ 
++	switch (ohci->hc_control & OHCI_CTRL_HCFS) {
+ 	case OHCI_USB_OPER:
+-		/* If no status changes are pending, enable status-change
+-		 * interrupts.
+-		 */
+-		if (!rhsc && !changed) {
+-			rhsc = OHCI_INTR_RHSC;
+-			ohci_writel(ohci, rhsc, &ohci->regs->intrenable);
++		/* If no status changes are pending, enable RHSC interrupts. */
++		if (!rhsc_enable && !rhsc_status && !changed) {
++			rhsc_enable = OHCI_INTR_RHSC;
++			ohci_writel(ohci, rhsc_enable, &ohci->regs->intrenable);
+ 		}
+ 
+ 		/* Keep on polling until we know a device is connected
+@@ -383,7 +388,7 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ 			if (any_connected ||
+ 					!device_may_wakeup(&ohci_to_hcd(ohci)
+ 						->self.root_hub->dev)) {
+-				if (rhsc)
++				if (rhsc_enable)
+ 					poll_rh = 0;
+ 			} else {
+ 				ohci->autostop = 1;
+@@ -396,34 +401,36 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ 				ohci->autostop = 0;
+ 				ohci->next_statechange = jiffies +
+ 						STATECHANGE_DELAY;
+-			} else if (rhsc && time_after_eq(jiffies,
++			} else if (time_after_eq(jiffies,
+ 						ohci->next_statechange)
+ 					&& !ohci->ed_rm_list
+ 					&& !(ohci->hc_control &
+ 						OHCI_SCHED_ENABLES)) {
+ 				ohci_rh_suspend(ohci, 1);
+-				poll_rh = 0;
++				if (rhsc_enable)
++					poll_rh = 0;
+ 			}
+ 		}
+ 		break;
+ 
+-	/* if there is a port change, autostart or ask to be resumed */
+ 	case OHCI_USB_SUSPEND:
+ 	case OHCI_USB_RESUME:
++		/* if there is a port change, autostart or ask to be resumed */
+ 		if (changed) {
+ 			if (ohci->autostop)
+ 				ohci_rh_resume(ohci);
+ 			else
+ 				usb_hcd_resume_root_hub(ohci_to_hcd(ohci));
+ 		} else {
+-			if (!rhsc && (ohci->autostop ||
++			if (!rhsc_enable && !rhsc_status && (ohci->autostop ||
+ 					ohci_to_hcd(ohci)->self.root_hub->
+-						do_remote_wakeup))
+-				ohci_writel(ohci, OHCI_INTR_RHSC,
++						do_remote_wakeup)) {
++				rhsc_enable = OHCI_INTR_RHSC;
++				ohci_writel(ohci, rhsc_enable,
+ 						&ohci->regs->intrenable);
+-
+-			/* everything is idle, no need for polling */
+-			poll_rh = 0;
++			}
++			if (rhsc_enable)
++				poll_rh = 0;
+ 		}
+ 		break;
+ 	}
+@@ -443,12 +450,16 @@ static inline int ohci_rh_resume(struct ohci_hcd *ohci)
+ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ 		int any_connected)
+ {
++	int	rhsc_status;
++
+ 	/* If RHSC is enabled, don't poll */
+ 	if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC)
+ 		return 0;
+ 
+-	/* If no status changes are pending, enable status-change interrupts */
+-	if (!changed) {
++	/* If no status changes are pending, enable RHSC interrupts */
++	rhsc_status = ohci_readl(ohci, &ohci->regs->intrstatus) &
++			OHCI_INTR_RHSC;
++	if (!changed && !rhsc_status) {
+ 		ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
+ 		return 0;
+ 	}
+@@ -492,13 +503,6 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ 		length++;
+ 	}
+ 
+-	/* Some broken controllers never turn off RHCS in the interrupt
+-	 * status register.  For their sake we won't re-enable RHSC
+-	 * interrupts if the flag is already set.
+-	 */
+-	if (ohci_readl(ohci, &ohci->regs->intrstatus) & OHCI_INTR_RHSC)
+-		changed = 1;
+-
+ 	/* look at each port */
+ 	for (i = 0; i < ohci->num_ports; i++) {
+ 		u32	status = roothub_portstatus (ohci, i);

commit 8bfa24727087d7252f9ecfb5fea2dfc92d797fbd
+Author: Alan Stern 
+Date:   Tue Sep 2 10:12:11 2008 -0400
+
+    usb-storage: report underflow with no sense data
+    
+    This patch (as1118) addresses a problem with certain USB mass-storage
+    devices.  These devices sometimes return less data than asked for and
+    then provide no sense data to explain the problem.  Currently
+    usb-storage leaves it up to the SCSI layer to decide how this should
+    be handled, and the SCSI layer interprets the lack of sense data to
+    mean that nothing went wrong.  But if we got less data than required
+    then something definitely _did_ go wrong, and we should say so.
+    
+    The patch tells the SCSI layer to retry the command when this sort of
+    thing happens.  Retrying may not solve the underlying problem, but
+    it's better than believing that data was transferred when it wasn't.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+index 3523a0bfa0ff..79108d5d3171 100644
+--- a/drivers/usb/storage/transport.c
++++ b/drivers/usb/storage/transport.c
+@@ -663,7 +663,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 	}
+ 
+ 	/* Did we transfer less than the minimum amount required? */
+-	if (srb->result == SAM_STAT_GOOD &&
++	if ((srb->result == SAM_STAT_GOOD || srb->sense_buffer[2] == 0) &&
+ 			scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow)
+ 		srb->result = (DID_ERROR << 16) | (SUGGEST_RETRY << 24);
+ 

commit 8066134ff8140ae9d8d15cdad3fc6c60c2a8a4e5
+Author: Alan Stern 
+Date:   Thu Aug 14 15:49:11 2008 -0400
+
+    USB: gadget: net2280: implement set_wedge
+    
+    This patch (as1132) implements the set_wedge() method for net2280.
+    This method is necessary for strict USBCV compliance in
+    g_file_storage.
+    
+    Signed-off-by: Alan Stern 
+    CC: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
+index 5cfb5ebf3881..8ae70de2c37d 100644
+--- a/drivers/usb/gadget/net2280.c
++++ b/drivers/usb/gadget/net2280.c
+@@ -178,6 +178,7 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
+ 
+ 	/* ep_reset() has already been called */
+ 	ep->stopped = 0;
++	ep->wedged = 0;
+ 	ep->out_overflow = 0;
+ 
+ 	/* set speed-dependent max packet; may kick in high bandwidth */
+@@ -1218,7 +1219,7 @@ static int net2280_dequeue (struct usb_ep *_ep, struct usb_request *_req)
+ static int net2280_fifo_status (struct usb_ep *_ep);
+ 
+ static int
+-net2280_set_halt (struct usb_ep *_ep, int value)
++net2280_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)
+ {
+ 	struct net2280_ep	*ep;
+ 	unsigned long		flags;
+@@ -1239,16 +1240,21 @@ net2280_set_halt (struct usb_ep *_ep, int value)
+ 	else if (ep->is_in && value && net2280_fifo_status (_ep) != 0)
+ 		retval = -EAGAIN;
+ 	else {
+-		VDEBUG (ep->dev, "%s %s halt\n", _ep->name,
+-				value ? "set" : "clear");
++		VDEBUG (ep->dev, "%s %s %s\n", _ep->name,
++				value ? "set" : "clear",
++				wedged ? "wedge" : "halt");
+ 		/* set/clear, then synch memory views with the device */
+ 		if (value) {
+ 			if (ep->num == 0)
+ 				ep->dev->protocol_stall = 1;
+ 			else
+ 				set_halt (ep);
+-		} else
++			if (wedged)
++				ep->wedged = 1;
++		} else {
+ 			clear_halt (ep);
++			ep->wedged = 0;
++		}
+ 		(void) readl (&ep->regs->ep_rsp);
+ 	}
+ 	spin_unlock_irqrestore (&ep->dev->lock, flags);
+@@ -1256,6 +1262,20 @@ net2280_set_halt (struct usb_ep *_ep, int value)
+ 	return retval;
+ }
+ 
++static int
++net2280_set_halt(struct usb_ep *_ep, int value)
++{
++	return net2280_set_halt_and_wedge(_ep, value, 0);
++}
++
++static int
++net2280_set_wedge(struct usb_ep *_ep)
++{
++	if (!_ep || _ep->name == ep0name)
++		return -EINVAL;
++	return net2280_set_halt_and_wedge(_ep, 1, 1);
++}
++
+ static int
+ net2280_fifo_status (struct usb_ep *_ep)
+ {
+@@ -1302,6 +1322,7 @@ static const struct usb_ep_ops net2280_ep_ops = {
+ 	.dequeue	= net2280_dequeue,
+ 
+ 	.set_halt	= net2280_set_halt,
++	.set_wedge	= net2280_set_wedge,
+ 	.fifo_status	= net2280_fifo_status,
+ 	.fifo_flush	= net2280_fifo_flush,
+ };
+@@ -2410,9 +2431,14 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
+ 				goto do_stall;
+ 			if ((e = get_ep_by_addr (dev, w_index)) == 0)
+ 				goto do_stall;
+-			clear_halt (e);
++			if (e->wedged) {
++				VDEBUG(dev, "%s wedged, halt not cleared\n",
++						ep->ep.name);
++			} else {
++				VDEBUG(dev, "%s clear halt\n", ep->ep.name);
++				clear_halt(e);
++			}
+ 			allow_status (ep);
+-			VDEBUG (dev, "%s clear halt\n", ep->ep.name);
+ 			goto next_endpoints;
+ 			}
+ 			break;
+@@ -2427,6 +2453,8 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
+ 				goto do_stall;
+ 			if ((e = get_ep_by_addr (dev, w_index)) == 0)
+ 				goto do_stall;
++			if (e->ep.name == ep0name)
++				goto do_stall;
+ 			set_halt (e);
+ 			allow_status (ep);
+ 			VDEBUG (dev, "%s set halt\n", ep->ep.name);
+diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h
+index 81a71dbdc2c6..c36852263d93 100644
+--- a/drivers/usb/gadget/net2280.h
++++ b/drivers/usb/gadget/net2280.h
+@@ -109,6 +109,7 @@ struct net2280_ep {
+ 						in_fifo_validate : 1,
+ 						out_overflow : 1,
+ 						stopped : 1,
++						wedged : 1,
+ 						is_in : 1,
+ 						is_iso : 1,
+ 						responded : 1;

commit 851a526dcf97964265cadcc6664a9f0ff7c143c7
+Author: Alan Stern 
+Date:   Thu Aug 14 15:48:30 2008 -0400
+
+    USB: gadget: dummy_hcd: implement set_wedge
+    
+    This patch (as1131) implements the set_wedge() method for dummy_hcd.
+    This method is necessary for strict USBCV compliance in
+    g_file_storage.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index 7600a0c78753..9064696636ac 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -82,6 +82,7 @@ struct dummy_ep {
+ 	const struct usb_endpoint_descriptor *desc;
+ 	struct usb_ep			ep;
+ 	unsigned			halted : 1;
++	unsigned			wedged : 1;
+ 	unsigned			already_seen : 1;
+ 	unsigned			setup_stage : 1;
+ };
+@@ -436,6 +437,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
+ 	/* at this point real hardware should be NAKing transfers
+ 	 * to that endpoint, until a buffer is queued to it.
+ 	 */
++	ep->halted = ep->wedged = 0;
+ 	retval = 0;
+ done:
+ 	return retval;
+@@ -597,7 +599,7 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req)
+ }
+ 
+ static int
+-dummy_set_halt (struct usb_ep *_ep, int value)
++dummy_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)
+ {
+ 	struct dummy_ep		*ep;
+ 	struct dummy		*dum;
+@@ -609,16 +611,32 @@ dummy_set_halt (struct usb_ep *_ep, int value)
+ 	if (!dum->driver)
+ 		return -ESHUTDOWN;
+ 	if (!value)
+-		ep->halted = 0;
++		ep->halted = ep->wedged = 0;
+ 	else if (ep->desc && (ep->desc->bEndpointAddress & USB_DIR_IN) &&
+ 			!list_empty (&ep->queue))
+ 		return -EAGAIN;
+-	else
++	else {
+ 		ep->halted = 1;
++		if (wedged)
++			ep->wedged = 1;
++	}
+ 	/* FIXME clear emulated data toggle too */
+ 	return 0;
+ }
+ 
++static int
++dummy_set_halt(struct usb_ep *_ep, int value)
++{
++	return dummy_set_halt_and_wedge(_ep, value, 0);
++}
++
++static int dummy_set_wedge(struct usb_ep *_ep)
++{
++	if (!_ep || _ep->name == ep0name)
++		return -EINVAL;
++	return dummy_set_halt_and_wedge(_ep, 1, 1);
++}
++
+ static const struct usb_ep_ops dummy_ep_ops = {
+ 	.enable		= dummy_enable,
+ 	.disable	= dummy_disable,
+@@ -630,6 +648,7 @@ static const struct usb_ep_ops dummy_ep_ops = {
+ 	.dequeue	= dummy_dequeue,
+ 
+ 	.set_halt	= dummy_set_halt,
++	.set_wedge	= dummy_set_wedge,
+ };
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -760,7 +779,8 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
+ 		ep->ep.name = ep_name [i];
+ 		ep->ep.ops = &dummy_ep_ops;
+ 		list_add_tail (&ep->ep.ep_list, &dum->gadget.ep_list);
+-		ep->halted = ep->already_seen = ep->setup_stage = 0;
++		ep->halted = ep->wedged = ep->already_seen =
++				ep->setup_stage = 0;
+ 		ep->ep.maxpacket = ~0;
+ 		ep->last_io = jiffies;
+ 		ep->gadget = &dum->gadget;
+@@ -1351,7 +1371,7 @@ static void dummy_timer (unsigned long _dum)
+ 				} else if (setup.bRequestType == Ep_Request) {
+ 					// endpoint halt
+ 					ep2 = find_endpoint (dum, w_index);
+-					if (!ep2) {
++					if (!ep2 || ep2->ep.name == ep0name) {
+ 						value = -EOPNOTSUPP;
+ 						break;
+ 					}
+@@ -1380,7 +1400,8 @@ static void dummy_timer (unsigned long _dum)
+ 						value = -EOPNOTSUPP;
+ 						break;
+ 					}
+-					ep2->halted = 0;
++					if (!ep2->wedged)
++						ep2->halted = 0;
+ 					value = 0;
+ 					status = 0;
+ 				}

commit 5257d97a219e17abf8188f136e1189da3b3af33c
+Author: Alan Stern 
+Date:   Mon Sep 22 14:43:08 2008 -0400
+
+    USB: revert recovery from transient errors
+    
+    This patch (as1135) essentially reverts the major parts of two earlier
+    patches to usbcore, because they ended up causing a regression.
+    
+    Trying to recover from transient communication errors can lead to
+    other problems, because operations that failed during the error period
+    are not always retried.  The simplest example is the initial
+    Set-Config request sent after device enumeration; if it gets lost then
+    it will not be retried and the device will remain unconfigured.
+    
+    This patch restores the old behavior in which any port disconnect or
+    port disable causes the entire device structure to be removed, fixing a
+    reported regression.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Frans Pop 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 6a5cb018383d..d99963873e37 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2683,35 +2683,17 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 				USB_PORT_STAT_C_ENABLE);
+ #endif
+ 
+-	/* Try to use the debounce delay for protection against
+-	 * port-enable changes caused, for example, by EMI.
+-	 */
+-	if (portchange & (USB_PORT_STAT_C_CONNECTION |
+-				USB_PORT_STAT_C_ENABLE)) {
+-		status = hub_port_debounce(hub, port1);
+-		if (status < 0) {
+-			if (printk_ratelimit())
+-				dev_err (hub_dev, "connect-debounce failed, "
+-						"port %d disabled\n", port1);
+-			portstatus &= ~USB_PORT_STAT_CONNECTION;
+-		} else {
+-			portstatus = status;
+-		}
+-	}
+-
+ 	/* Try to resuscitate an existing device */
+ 	udev = hdev->children[port1-1];
+ 	if ((portstatus & USB_PORT_STAT_CONNECTION) && udev &&
+ 			udev->state != USB_STATE_NOTATTACHED) {
+-
+ 		usb_lock_device(udev);
+ 		if (portstatus & USB_PORT_STAT_ENABLE) {
+ 			status = 0;		/* Nothing to do */
+-		} else if (!udev->persist_enabled) {
+-			status = -ENODEV;	/* Mustn't resuscitate */
+ 
+ #ifdef CONFIG_USB_SUSPEND
+-		} else if (udev->state == USB_STATE_SUSPENDED) {
++		} else if (udev->state == USB_STATE_SUSPENDED &&
++				udev->persist_enabled) {
+ 			/* For a suspended device, treat this as a
+ 			 * remote wakeup event.
+ 			 */
+@@ -2726,7 +2708,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ #endif
+ 
+ 		} else {
+-			status = usb_reset_device(udev);
++			status = -ENODEV;	/* Don't resuscitate */
+ 		}
+ 		usb_unlock_device(udev);
+ 
+@@ -2741,6 +2723,19 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 		usb_disconnect(&hdev->children[port1-1]);
+ 	clear_bit(port1, hub->change_bits);
+ 
++	if (portchange & (USB_PORT_STAT_C_CONNECTION |
++				USB_PORT_STAT_C_ENABLE)) {
++		status = hub_port_debounce(hub, port1);
++		if (status < 0) {
++			if (printk_ratelimit())
++				dev_err(hub_dev, "connect-debounce failed, "
++						"port %d disabled\n", port1);
++			portstatus &= ~USB_PORT_STAT_CONNECTION;
++		} else {
++			portstatus = status;
++		}
++	}
++
+ 	/* Return now if debouncing failed or nothing is connected */
+ 	if (!(portstatus & USB_PORT_STAT_CONNECTION)) {
+ 
+@@ -2748,7 +2743,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 		if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2
+ 				&& !(portstatus & (1 << USB_PORT_FEAT_POWER)))
+ 			set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
+- 
++
+ 		if (portstatus & USB_PORT_STAT_ENABLE)
+   			goto done;
+ 		return;

commit fe1926a0f549741ed0ca778aa1c7d3e208895dee
+Author: Alan Stern 
+Date:   Thu Sep 4 09:56:35 2008 -0400
+
+    USB: unusual_devs addition for RockChip MP3 player
+    
+    This patch (as1136) adds an unusual_devs entry for a version of the
+    RockChip MP3 player which can't handle the MODE SENSE command used for
+    write-protect detection.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index b311300cf788..4d9ca02ac677 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -1001,6 +1001,13 @@ UNUSUAL_DEV(  0x069b, 0x3004, 0x0001, 0x0001,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_FIX_CAPACITY ),
+ 
++/* Reported by Adrian Pilchowiec  */
++UNUSUAL_DEV(  0x071b, 0x3203, 0x0000, 0x0000,
++		"RockChip",
++		"MP3",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_NO_WP_DETECT | US_FL_MAX_SECTORS_64),
++
+ /* Reported by Massimiliano Ghilardi 
+  * This USB MP3/AVI player device fails and disconnects if more than 128
+  * sectors (64kB) are read/written in a single command, and may be present

commit b5fb454f69642f9d933b327b185a2ba06dd0945c
+Author: Alan Stern 
+Date:   Wed Aug 20 17:22:05 2008 -0400
+
+    USB: automatically enable RHSC interrupts
+    
+    This patch (as1069c) changes the way OHCI root-hub status-change
+    interrupts are enabled.  Currently a special HCD method,
+    hub_irq_enable(), is called when the hub driver is finished using a
+    root hub.  This approach turns out to be subject to races, resulting
+    in unnecessary polling.
+    
+    The patch does away with the method entirely.  Instead, the driver
+    automatically enables the RHSC interrupt when no more status changes
+    are present.  This scheme is safe with controllers using
+    level-triggered semantics for their interrupt flags.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index f7bfd72ef115..8abd4e59bf4a 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -924,15 +924,6 @@ static int register_root_hub(struct usb_hcd *hcd)
+ 	return retval;
+ }
+ 
+-void usb_enable_root_hub_irq (struct usb_bus *bus)
+-{
+-	struct usb_hcd *hcd;
+-
+-	hcd = container_of (bus, struct usb_hcd, self);
+-	if (hcd->driver->hub_irq_enable && hcd->state != HC_STATE_HALT)
+-		hcd->driver->hub_irq_enable (hcd);
+-}
+-
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index 5b0b59b0d89b..e710ce04e228 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -212,8 +212,6 @@ struct hc_driver {
+ 	int	(*bus_suspend)(struct usb_hcd *);
+ 	int	(*bus_resume)(struct usb_hcd *);
+ 	int	(*start_port_reset)(struct usb_hcd *, unsigned port_num);
+-	void	(*hub_irq_enable)(struct usb_hcd *);
+-		/* Needed only if port-change IRQs are level-triggered */
+ 
+ 		/* force handover of high-speed port to full-speed companion */
+ 	void	(*relinquish_port)(struct usb_hcd *, int);
+@@ -379,8 +377,6 @@ extern struct list_head usb_bus_list;
+ extern struct mutex usb_bus_list_lock;
+ extern wait_queue_head_t usb_kill_urb_queue;
+ 
+-extern void usb_enable_root_hub_irq(struct usb_bus *bus);
+-
+ extern int usb_find_interface_driver(struct usb_device *dev,
+ 	struct usb_interface *interface);
+ 
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 107e1d25ddec..6a5cb018383d 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2102,8 +2102,6 @@ int usb_port_resume(struct usb_device *udev)
+ 	}
+ 
+ 	clear_bit(port1, hub->busy_bits);
+-	if (!hub->hdev->parent && !hub->busy_bits[0])
+-		usb_enable_root_hub_irq(hub->hdev->bus);
+ 
+ 	status = check_port_resume_type(udev,
+ 			hub, port1, status, portchange, portstatus);
+@@ -3081,11 +3079,6 @@ static void hub_events(void)
+ 			}
+ 		}
+ 
+-		/* If this is a root hub, tell the HCD it's okay to
+-		 * re-enable port-change interrupts now. */
+-		if (!hdev->parent && !hub->busy_bits[0])
+-			usb_enable_root_hub_irq(hdev->bus);
+-
+ loop_autopm:
+ 		/* Allow autosuspend if we're not going to run again */
+ 		if (list_empty(&hub->event_list))
+@@ -3311,8 +3304,6 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
+ 			break;
+ 	}
+ 	clear_bit(port1, parent_hub->busy_bits);
+-	if (!parent_hdev->parent && !parent_hub->busy_bits[0])
+-		usb_enable_root_hub_irq(parent_hdev->bus);
+ 
+ 	if (ret < 0)
+ 		goto re_enumerate;
+diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
+index 6db7a2889e66..4ed228a89943 100644
+--- a/drivers/usb/host/ohci-at91.c
++++ b/drivers/usb/host/ohci-at91.c
+@@ -260,7 +260,6 @@ static const struct hc_driver ohci_at91_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
+index c0948008fe3d..2ac4e022a13f 100644
+--- a/drivers/usb/host/ohci-au1xxx.c
++++ b/drivers/usb/host/ohci-au1xxx.c
+@@ -163,7 +163,6 @@ static const struct hc_driver ohci_au1xxx_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
+index cb0b506f8259..fb3055f084b5 100644
+--- a/drivers/usb/host/ohci-ep93xx.c
++++ b/drivers/usb/host/ohci-ep93xx.c
+@@ -134,7 +134,6 @@ static struct hc_driver ohci_ep93xx_hc_driver = {
+ 	.get_frame_number	= ohci_get_frame,
+ 	.hub_status_data	= ohci_hub_status_data,
+ 	.hub_control		= ohci_hub_control,
+-	.hub_irq_enable		= ohci_rhsc_enable,
+ #ifdef CONFIG_PM
+ 	.bus_suspend		= ohci_bus_suspend,
+ 	.bus_resume		= ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index 439beb784f3e..7ea9a7b31155 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -36,18 +36,6 @@
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-/* hcd->hub_irq_enable() */
+-static void ohci_rhsc_enable (struct usb_hcd *hcd)
+-{
+-	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+-
+-	spin_lock_irq(&ohci->lock);
+-	if (!ohci->autostop)
+-		del_timer(&hcd->rh_timer);	/* Prevent next poll */
+-	ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
+-	spin_unlock_irq(&ohci->lock);
+-}
+-
+ #define OHCI_SCHED_ENABLES \
+ 	(OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
+ 
+@@ -374,18 +362,28 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ 		int any_connected)
+ {
+ 	int	poll_rh = 1;
++	int	rhsc;
+ 
++	rhsc = ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC;
+ 	switch (ohci->hc_control & OHCI_CTRL_HCFS) {
+ 
+ 	case OHCI_USB_OPER:
+-		/* keep on polling until we know a device is connected
+-		 * and RHSC is enabled */
++		/* If no status changes are pending, enable status-change
++		 * interrupts.
++		 */
++		if (!rhsc && !changed) {
++			rhsc = OHCI_INTR_RHSC;
++			ohci_writel(ohci, rhsc, &ohci->regs->intrenable);
++		}
++
++		/* Keep on polling until we know a device is connected
++		 * and RHSC is enabled, or until we autostop.
++		 */
+ 		if (!ohci->autostop) {
+ 			if (any_connected ||
+ 					!device_may_wakeup(&ohci_to_hcd(ohci)
+ 						->self.root_hub->dev)) {
+-				if (ohci_readl(ohci, &ohci->regs->intrenable) &
+-						OHCI_INTR_RHSC)
++				if (rhsc)
+ 					poll_rh = 0;
+ 			} else {
+ 				ohci->autostop = 1;
+@@ -398,12 +396,13 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ 				ohci->autostop = 0;
+ 				ohci->next_statechange = jiffies +
+ 						STATECHANGE_DELAY;
+-			} else if (time_after_eq(jiffies,
++			} else if (rhsc && time_after_eq(jiffies,
+ 						ohci->next_statechange)
+ 					&& !ohci->ed_rm_list
+ 					&& !(ohci->hc_control &
+ 						OHCI_SCHED_ENABLES)) {
+ 				ohci_rh_suspend(ohci, 1);
++				poll_rh = 0;
+ 			}
+ 		}
+ 		break;
+@@ -417,6 +416,12 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ 			else
+ 				usb_hcd_resume_root_hub(ohci_to_hcd(ohci));
+ 		} else {
++			if (!rhsc && (ohci->autostop ||
++					ohci_to_hcd(ohci)->self.root_hub->
++						do_remote_wakeup))
++				ohci_writel(ohci, OHCI_INTR_RHSC,
++						&ohci->regs->intrenable);
++
+ 			/* everything is idle, no need for polling */
+ 			poll_rh = 0;
+ 		}
+@@ -438,12 +443,16 @@ static inline int ohci_rh_resume(struct ohci_hcd *ohci)
+ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ 		int any_connected)
+ {
+-	int	poll_rh = 1;
+-
+-	/* keep on polling until RHSC is enabled */
++	/* If RHSC is enabled, don't poll */
+ 	if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC)
+-		poll_rh = 0;
+-	return poll_rh;
++		return 0;
++
++	/* If no status changes are pending, enable status-change interrupts */
++	if (!changed) {
++		ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
++		return 0;
++	}
++	return 1;
+ }
+ 
+ #endif	/* CONFIG_PM */
+diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c
+index 9e31d440d115..de42283149c7 100644
+--- a/drivers/usb/host/ohci-lh7a404.c
++++ b/drivers/usb/host/ohci-lh7a404.c
+@@ -193,7 +193,6 @@ static const struct hc_driver ohci_lh7a404_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
+index 3d532b709670..1eb64d08b60a 100644
+--- a/drivers/usb/host/ohci-omap.c
++++ b/drivers/usb/host/ohci-omap.c
+@@ -470,7 +470,6 @@ static const struct hc_driver ohci_omap_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index 083e8df0a817..a9c2ae36c7ad 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -459,7 +459,6 @@ static const struct hc_driver ohci_pci_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c
+index b02cd0761977..658a2a978c32 100644
+--- a/drivers/usb/host/ohci-pnx4008.c
++++ b/drivers/usb/host/ohci-pnx4008.c
+@@ -277,7 +277,6 @@ static const struct hc_driver ohci_pnx4008_hc_driver = {
+ 	 */
+ 	.hub_status_data = ohci_hub_status_data,
+ 	.hub_control = ohci_hub_control,
+-	.hub_irq_enable = ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend = ohci_bus_suspend,
+ 	.bus_resume = ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-pnx8550.c b/drivers/usb/host/ohci-pnx8550.c
+index 605d59cba28e..28467e288a93 100644
+--- a/drivers/usb/host/ohci-pnx8550.c
++++ b/drivers/usb/host/ohci-pnx8550.c
+@@ -201,7 +201,6 @@ static const struct hc_driver ohci_pnx8550_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
+index 91e6e101a4cc..7ac53264ead3 100644
+--- a/drivers/usb/host/ohci-ppc-of.c
++++ b/drivers/usb/host/ohci-ppc-of.c
+@@ -72,7 +72,6 @@ static const struct hc_driver ohci_ppc_of_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
+index 523c30125577..cd3398b675b2 100644
+--- a/drivers/usb/host/ohci-ppc-soc.c
++++ b/drivers/usb/host/ohci-ppc-soc.c
+@@ -172,7 +172,6 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c
+index 55c95647f008..2089d8a46c4b 100644
+--- a/drivers/usb/host/ohci-ps3.c
++++ b/drivers/usb/host/ohci-ps3.c
+@@ -68,7 +68,6 @@ static const struct hc_driver ps3_ohci_hc_driver = {
+ 	.get_frame_number	= ohci_get_frame,
+ 	.hub_status_data	= ohci_hub_status_data,
+ 	.hub_control		= ohci_hub_control,
+-	.hub_irq_enable		= ohci_rhsc_enable,
+ 	.start_port_reset	= ohci_start_port_reset,
+ #if defined(CONFIG_PM)
+ 	.bus_suspend 		= ohci_bus_suspend,
+diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
+index 8c9c4849db6e..7f0f35c78185 100644
+--- a/drivers/usb/host/ohci-pxa27x.c
++++ b/drivers/usb/host/ohci-pxa27x.c
+@@ -298,7 +298,6 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef  CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
+index 9e3dc4069e8b..f46af7a718d4 100644
+--- a/drivers/usb/host/ohci-s3c2410.c
++++ b/drivers/usb/host/ohci-s3c2410.c
+@@ -466,7 +466,6 @@ static const struct hc_driver ohci_s3c2410_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_s3c2410_hub_status_data,
+ 	.hub_control =		ohci_s3c2410_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
+index 4626b002e670..e4bbe8e188e4 100644
+--- a/drivers/usb/host/ohci-sa1111.c
++++ b/drivers/usb/host/ohci-sa1111.c
+@@ -231,7 +231,6 @@ static const struct hc_driver ohci_sa1111_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c
+index e7ee607278fe..60f03cc7ec4f 100644
+--- a/drivers/usb/host/ohci-sh.c
++++ b/drivers/usb/host/ohci-sh.c
+@@ -68,7 +68,6 @@ static const struct hc_driver ohci_sh_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c
+index 21b164e4abeb..cff23637cfcc 100644
+--- a/drivers/usb/host/ohci-sm501.c
++++ b/drivers/usb/host/ohci-sm501.c
+@@ -75,7 +75,6 @@ static const struct hc_driver ohci_sm501_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c
+index 3660c83d80af..23fd6a886bdd 100644
+--- a/drivers/usb/host/ohci-ssb.c
++++ b/drivers/usb/host/ohci-ssb.c
+@@ -81,7 +81,6 @@ static const struct hc_driver ssb_ohci_hc_driver = {
+ 
+ 	.hub_status_data	= ohci_hub_status_data,
+ 	.hub_control		= ohci_hub_control,
+-	.hub_irq_enable		= ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend		= ohci_bus_suspend,
+ 	.bus_resume		= ohci_bus_resume,
+diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
+index 20ad3c48fcb2..228f2b070f2b 100644
+--- a/drivers/usb/host/u132-hcd.c
++++ b/drivers/usb/host/u132-hcd.c
+@@ -2934,16 +2934,6 @@ static int u132_start_port_reset(struct usb_hcd *hcd, unsigned port_num)
+ 		return 0;
+ }
+ 
+-static void u132_hub_irq_enable(struct usb_hcd *hcd)
+-{
+-	struct u132 *u132 = hcd_to_u132(hcd);
+-	if (u132->going > 1) {
+-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-			, u132->going);
+-	} else if (u132->going > 0)
+-		dev_err(&u132->platform_dev->dev, "device is being removed\n");
+-}
+-
+ 
+ #ifdef CONFIG_PM
+ static int u132_bus_suspend(struct usb_hcd *hcd)
+@@ -2995,7 +2985,6 @@ static struct hc_driver u132_hc_driver = {
+ 	.bus_suspend = u132_bus_suspend,
+ 	.bus_resume = u132_bus_resume,
+ 	.start_port_reset = u132_start_port_reset,
+-	.hub_irq_enable = u132_hub_irq_enable,
+ };
+ 
+ /*

commit 5096aedcd2eb70fbea83f09281f97f9ec973d9de
+Author: Alan Stern 
+Date:   Tue Aug 12 14:34:14 2008 -0400
+
+    USB: Don't rebind before "complete" callback
+    
+    This patch (as1130) fixes an incompatibility between the new PM
+    infrastructure and USB power management.  We are not allowed to call
+    drivers' probe routines during a system sleep transition between the
+    "prepare" and "complete" callbacks, but that's exactly what we do when
+    a driver doesn't have full suspend/resume support.  Such drivers are
+    unbound during the "suspend" call and reprobed during the "resume" call.
+    
+    The patch causes the reprobe step to be skipped if the "complete"
+    callback hasn't been issued yet, i.e., if the interface's
+    dev.power.status field is not equal to DPM_ON.  Thus during the
+    "resume" callback nothing bad will happen, and during the final
+    "complete" callback the reprobing will occur as desired.
+    
+    This fixes the problem reported in Bugzilla #11263.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 2da70b4d33fe..5a7fa6f09958 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -814,7 +814,8 @@ void usb_forced_unbind_intf(struct usb_interface *intf)
+  * The caller must hold @intf's device's lock, but not its pm_mutex
+  * and not @intf->dev.sem.
+  *
+- * FIXME: The caller must block system sleep transitions.
++ * Note: Rebinds will be skipped if a system sleep transition is in
++ * progress and the PM "complete" callback hasn't occurred yet.
+  */
+ void usb_rebind_intf(struct usb_interface *intf)
+ {
+@@ -830,10 +831,12 @@ void usb_rebind_intf(struct usb_interface *intf)
+ 	}
+ 
+ 	/* Try to rebind the interface */
+-	intf->needs_binding = 0;
+-	rc = device_attach(&intf->dev);
+-	if (rc < 0)
+-		dev_warn(&intf->dev, "rebind failed: %d\n", rc);
++	if (intf->dev.power.status == DPM_ON) {
++		intf->needs_binding = 0;
++		rc = device_attach(&intf->dev);
++		if (rc < 0)
++			dev_warn(&intf->dev, "rebind failed: %d\n", rc);
++	}
+ }
+ 
+ #ifdef CONFIG_PM
+@@ -845,7 +848,6 @@ void usb_rebind_intf(struct usb_interface *intf)
+  * or rebind interfaces that have been unbound, according to @action.
+  *
+  * The caller must hold @udev's device lock.
+- * FIXME: For rebinds, the caller must block system sleep transitions.
+  */
+ static void do_unbind_rebind(struct usb_device *udev, int action)
+ {
+@@ -867,22 +869,8 @@ static void do_unbind_rebind(struct usb_device *udev, int action)
+ 				}
+ 				break;
+ 			case DO_REBIND:
+-				if (intf->needs_binding) {
+-
+-	/* FIXME: The next line is needed because we are going to probe
+-	 * the interface, but as far as the PM core is concerned the
+-	 * interface is still suspended.  The problem wouldn't exist
+-	 * if we could rebind the interface during the interface's own
+-	 * resume() call, but at the time the usb_device isn't locked!
+-	 *
+-	 * The real solution will be to carry this out during the device's
+-	 * complete() callback.  Until that is implemented, we have to
+-	 * use this hack.
+-	 */
+-//					intf->dev.power.sleeping = 0;
+-
++				if (intf->needs_binding)
+ 					usb_rebind_intf(intf);
+-				}
+ 				break;
+ 			}
+ 		}

commit f2189c477c986db47ac7f9cc32d05f6df18bfe9e
+Author: Alan Stern 
+Date:   Tue Aug 12 14:34:10 2008 -0400
+
+    USB: Add new PM callback methods for USB
+    
+    This patch (as1129) adds support for the new PM callbacks to usbcore.
+    The new callbacks merely invoke the same old USB power management
+    routines as the old ones did.
+    
+    A minor improvement is that the callbacks are present only in the
+    "USB-device" device_type structure, rather than in the bus_type
+    structure.  This way they will be invoked only for USB devices, not
+    for USB interfaces.  The core USB PM routines automatically handle
+    suspending and resuming interfaces along with their devices.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 637b2bea5563..2da70b4d33fe 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1630,12 +1630,10 @@ int usb_external_resume_device(struct usb_device *udev)
+ 	return status;
+ }
+ 
+-static int usb_suspend(struct device *dev, pm_message_t message)
++int usb_suspend(struct device *dev, pm_message_t message)
+ {
+ 	struct usb_device	*udev;
+ 
+-	if (!is_usb_device(dev))	/* Ignore PM for interfaces */
+-		return 0;
+ 	udev = to_usb_device(dev);
+ 
+ 	/* If udev is already suspended, we can skip this suspend and
+@@ -1654,12 +1652,10 @@ static int usb_suspend(struct device *dev, pm_message_t message)
+ 	return usb_external_suspend_device(udev, message);
+ }
+ 
+-static int usb_resume(struct device *dev)
++int usb_resume(struct device *dev)
+ {
+ 	struct usb_device	*udev;
+ 
+-	if (!is_usb_device(dev))	/* Ignore PM for interfaces */
+-		return 0;
+ 	udev = to_usb_device(dev);
+ 
+ 	/* If udev->skip_sys_resume is set then udev was already suspended
+@@ -1671,17 +1667,10 @@ static int usb_resume(struct device *dev)
+ 	return usb_external_resume_device(udev);
+ }
+ 
+-#else
+-
+-#define usb_suspend	NULL
+-#define usb_resume	NULL
+-
+ #endif /* CONFIG_PM */
+ 
+ struct bus_type usb_bus_type = {
+ 	.name =		"usb",
+ 	.match =	usb_device_match,
+ 	.uevent =	usb_uevent,
+-	.suspend =	usb_suspend,
+-	.resume =	usb_resume,
+ };
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 84fcaa6a21ec..be1fa0723f2c 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -219,12 +219,6 @@ static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
+ }
+ #endif	/* CONFIG_HOTPLUG */
+ 
+-struct device_type usb_device_type = {
+-	.name =		"usb_device",
+-	.release =	usb_release_dev,
+-	.uevent =	usb_dev_uevent,
+-};
+-
+ #ifdef	CONFIG_PM
+ 
+ static int ksuspend_usb_init(void)
+@@ -244,13 +238,80 @@ static void ksuspend_usb_cleanup(void)
+ 	destroy_workqueue(ksuspend_usb_wq);
+ }
+ 
++/* USB device Power-Management thunks.
++ * There's no need to distinguish here between quiescing a USB device
++ * and powering it down; the generic_suspend() routine takes care of
++ * it by skipping the usb_port_suspend() call for a quiesce.  And for
++ * USB interfaces there's no difference at all.
++ */
++
++static int usb_dev_prepare(struct device *dev)
++{
++	return 0;		/* Implement eventually? */
++}
++
++static void usb_dev_complete(struct device *dev)
++{
++	/* Currently used only for rebinding interfaces */
++	usb_resume(dev);	/* Implement eventually? */
++}
++
++static int usb_dev_suspend(struct device *dev)
++{
++	return usb_suspend(dev, PMSG_SUSPEND);
++}
++
++static int usb_dev_resume(struct device *dev)
++{
++	return usb_resume(dev);
++}
++
++static int usb_dev_freeze(struct device *dev)
++{
++	return usb_suspend(dev, PMSG_FREEZE);
++}
++
++static int usb_dev_thaw(struct device *dev)
++{
++	return usb_resume(dev);
++}
++
++static int usb_dev_poweroff(struct device *dev)
++{
++	return usb_suspend(dev, PMSG_HIBERNATE);
++}
++
++static int usb_dev_restore(struct device *dev)
++{
++	return usb_resume(dev);
++}
++
++static struct pm_ops usb_device_pm_ops = {
++	.prepare =	usb_dev_prepare,
++	.complete =	usb_dev_complete,
++	.suspend =	usb_dev_suspend,
++	.resume =	usb_dev_resume,
++	.freeze =	usb_dev_freeze,
++	.thaw =		usb_dev_thaw,
++	.poweroff =	usb_dev_poweroff,
++	.restore =	usb_dev_restore,
++};
++
+ #else
+ 
+ #define ksuspend_usb_init()	0
+ #define ksuspend_usb_cleanup()	do {} while (0)
++#define usb_device_pm_ops	(*(struct pm_ops *)0)
+ 
+ #endif	/* CONFIG_PM */
+ 
++struct device_type usb_device_type = {
++	.name =		"usb_device",
++	.release =	usb_release_dev,
++	.uevent =	usb_dev_uevent,
++	.pm =		&usb_device_pm_ops,
++};
++
+ 
+ /* Returns 1 if @usb_bus is WUSB, 0 otherwise */
+ static unsigned usb_bus_is_wusb(struct usb_bus *bus)
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index d9a6e16dbf84..9a1a45ac3add 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -41,6 +41,9 @@ extern void usb_host_cleanup(void);
+ 
+ #ifdef	CONFIG_PM
+ 
++extern int usb_suspend(struct device *dev, pm_message_t msg);
++extern int usb_resume(struct device *dev);
++
+ extern void usb_autosuspend_work(struct work_struct *work);
+ extern int usb_port_suspend(struct usb_device *dev);
+ extern int usb_port_resume(struct usb_device *dev);

commit 55151d7daba185f94e9dc561a5a2ba36b5f647dd
+Author: Alan Stern 
+Date:   Tue Aug 12 14:33:59 2008 -0400
+
+    USB: Defer Set-Interface for suspended devices
+    
+    This patch (as1128) fixes one of the problems related to the new PM
+    infrastructure.  We are not allowed to register new child devices
+    during the middle of a system sleep transition, but unbinding a USB
+    driver causes the core to automatically install altsetting 0 and
+    thereby create new endpoint pseudo-devices.
+    
+    The patch fixes this problem (and the related problem that installing
+    altsetting 0 will fail if the device is suspended) by deferring the
+    Set-Interface call until some later time when it is legal and can
+    succeed.  Possible later times are: when a new driver is being probed
+    for the interface, and when the interface is being resumed.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index ed1cc8530a93..637b2bea5563 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -230,6 +230,13 @@ static int usb_probe_interface(struct device *dev)
+ 		 */
+ 		intf->pm_usage_cnt = !(driver->supports_autosuspend);
+ 
++		/* Carry out a deferred switch to altsetting 0 */
++		if (intf->needs_altsetting0) {
++			usb_set_interface(udev, intf->altsetting[0].
++					desc.bInterfaceNumber, 0);
++			intf->needs_altsetting0 = 0;
++		}
++
+ 		error = driver->probe(intf, id);
+ 		if (error) {
+ 			mark_quiesced(intf);
+@@ -266,8 +273,17 @@ static int usb_unbind_interface(struct device *dev)
+ 
+ 	driver->disconnect(intf);
+ 
+-	/* reset other interface state */
+-	usb_set_interface(udev, intf->altsetting[0].desc.bInterfaceNumber, 0);
++	/* Reset other interface state.
++	 * We cannot do a Set-Interface if the device is suspended or
++	 * if it is prepared for a system sleep (since installing a new
++	 * altsetting means creating new endpoint device entries).
++	 * When either of these happens, defer the Set-Interface.
++	 */
++	if (!error && intf->dev.power.status == DPM_ON)
++		usb_set_interface(udev, intf->altsetting[0].
++				desc.bInterfaceNumber, 0);
++	else
++		intf->needs_altsetting0 = 1;
+ 	usb_set_intfdata(intf, NULL);
+ 
+ 	intf->condition = USB_INTERFACE_UNBOUND;
+@@ -975,8 +991,17 @@ static int usb_resume_interface(struct usb_device *udev,
+ 		goto done;
+ 
+ 	/* Can't resume it if it doesn't have a driver. */
+-	if (intf->condition == USB_INTERFACE_UNBOUND)
++	if (intf->condition == USB_INTERFACE_UNBOUND) {
++
++		/* Carry out a deferred switch to altsetting 0 */
++		if (intf->needs_altsetting0 &&
++				intf->dev.power.status == DPM_ON) {
++			usb_set_interface(udev, intf->altsetting[0].
++					desc.bInterfaceNumber, 0);
++			intf->needs_altsetting0 = 0;
++		}
+ 		goto done;
++	}
+ 
+ 	/* Don't resume if the interface is marked for rebinding */
+ 	if (intf->needs_binding)
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 0924cd9c30f6..94ac74aba6b6 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -110,6 +110,8 @@ enum usb_interface_condition {
+  * @sysfs_files_created: sysfs attributes exist
+  * @needs_remote_wakeup: flag set when the driver requires remote-wakeup
+  *	capability during autosuspend.
++ * @needs_altsetting0: flag set when a set-interface request for altsetting 0
++ *	has been deferred.
+  * @needs_binding: flag set when the driver should be re-probed or unbound
+  *	following a reset or suspend operation it doesn't support.
+  * @dev: driver model's view of this device
+@@ -162,6 +164,7 @@ struct usb_interface {
+ 	unsigned is_active:1;		/* the interface is not suspended */
+ 	unsigned sysfs_files_created:1;	/* the sysfs attributes exist */
+ 	unsigned needs_remote_wakeup:1;	/* driver requires remote wakeup */
++	unsigned needs_altsetting0:1;	/* switch to altsetting 0 is pending */
+ 	unsigned needs_binding:1;	/* needs delayed unbind/rebind */
+ 
+ 	struct device dev;		/* interface specific device info */

commit 65605ae8e587d714f73e674369bc4cd5a1e53a9b
+Author: Alan Stern 
+Date:   Tue Aug 12 14:33:27 2008 -0400
+
+    USB: Add udev argument to interface suspend/resume functions
+    
+    This patch (as1127) makes a minor change to the prototypes of the
+    usb_suspend_interface() and usb_resume_interface() routines.  Now the
+    usb_device structure is passed as an argument, instead of being
+    computed on-the-fly from the usb_interface argument.
+    
+    It makes the code look simpler, even if it really isn't much different
+    from before.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 2be37fe466f2..ed1cc8530a93 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -926,14 +926,14 @@ static int usb_resume_device(struct usb_device *udev)
+ }
+ 
+ /* Caller has locked intf's usb_device's pm mutex */
+-static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
++static int usb_suspend_interface(struct usb_device *udev,
++		struct usb_interface *intf, pm_message_t msg)
+ {
+ 	struct usb_driver	*driver;
+ 	int			status = 0;
+ 
+ 	/* with no hardware, USB interfaces only use FREEZE and ON states */
+-	if (interface_to_usbdev(intf)->state == USB_STATE_NOTATTACHED ||
+-			!is_active(intf))
++	if (udev->state == USB_STATE_NOTATTACHED || !is_active(intf))
+ 		goto done;
+ 
+ 	if (intf->condition == USB_INTERFACE_UNBOUND)	/* This can't happen */
+@@ -944,7 +944,7 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
+ 		status = driver->suspend(intf, msg);
+ 		if (status == 0)
+ 			mark_quiesced(intf);
+-		else if (!interface_to_usbdev(intf)->auto_pm)
++		else if (!udev->auto_pm)
+ 			dev_err(&intf->dev, "%s error %d\n",
+ 					"suspend", status);
+ 	} else {
+@@ -961,13 +961,13 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
+ }
+ 
+ /* Caller has locked intf's usb_device's pm_mutex */
+-static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
++static int usb_resume_interface(struct usb_device *udev,
++		struct usb_interface *intf, int reset_resume)
+ {
+ 	struct usb_driver	*driver;
+ 	int			status = 0;
+ 
+-	if (interface_to_usbdev(intf)->state == USB_STATE_NOTATTACHED ||
+-			is_active(intf))
++	if (udev->state == USB_STATE_NOTATTACHED || is_active(intf))
+ 		goto done;
+ 
+ 	/* Don't let autoresume interfere with unbinding */
+@@ -1151,7 +1151,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 	if (udev->actconfig) {
+ 		for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
+ 			intf = udev->actconfig->interface[i];
+-			status = usb_suspend_interface(intf, msg);
++			status = usb_suspend_interface(udev, intf, msg);
+ 			if (status != 0)
+ 				break;
+ 		}
+@@ -1163,7 +1163,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 	if (status != 0) {
+ 		while (--i >= 0) {
+ 			intf = udev->actconfig->interface[i];
+-			usb_resume_interface(intf, 0);
++			usb_resume_interface(udev, intf, 0);
+ 		}
+ 
+ 		/* Try another autosuspend when the interfaces aren't busy */
+@@ -1276,7 +1276,7 @@ static int usb_resume_both(struct usb_device *udev)
+ 	if (status == 0 && udev->actconfig) {
+ 		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+ 			intf = udev->actconfig->interface[i];
+-			usb_resume_interface(intf, udev->reset_resume);
++			usb_resume_interface(udev, intf, udev->reset_resume);
+ 		}
+ 	}
+ 

commit 3b98aeaf3a75f544dc945694f4fcf6e1c4bab89d
+Author: Alan Stern 
+Date:   Thu Aug 7 13:06:12 2008 -0400
+
+    PM: don't skip device PM init when CONFIG_PM_SLEEP isn't set and CONFIG_PM is set
+    
+    This patch (as1124) fixes a couple of bugs in the PM core.  The new
+    dev->power.status field should be initialized regardless of whether
+    CONFIG_PM_SLEEP is enabled, and similarly dpm_sysfs_add() should be
+    called whenever CONFIG_PM is enabled.
+    
+    The patch separates out the call to dpm_sysfs_add() from the call to
+    device_pm_add().  As a result device_pm_add() can no longer return an
+    error, so its return type is changed to void.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Romit Dasgupta 
+    Acked-by: Rafael J. Wysocki 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/base/core.c b/drivers/base/core.c
+index 44bad73d8192..40041319657d 100644
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -541,6 +541,7 @@ void device_initialize(struct device *dev)
+ 	spin_lock_init(&dev->devres_lock);
+ 	INIT_LIST_HEAD(&dev->devres_head);
+ 	device_init_wakeup(dev, 0);
++	device_pm_init(dev);
+ 	set_dev_node(dev, -1);
+ }
+ 
+@@ -897,9 +898,10 @@ int device_add(struct device *dev)
+ 	error = bus_add_device(dev);
+ 	if (error)
+ 		goto BusError;
+-	error = device_pm_add(dev);
++	error = dpm_sysfs_add(dev);
+ 	if (error)
+-		goto PMError;
++		goto DPMError;
++	device_pm_add(dev);
+ 	kobject_uevent(&dev->kobj, KOBJ_ADD);
+ 	bus_attach_device(dev);
+ 	if (parent)
+@@ -920,7 +922,7 @@ int device_add(struct device *dev)
+  Done:
+ 	put_device(dev);
+ 	return error;
+- PMError:
++ DPMError:
+ 	bus_remove_device(dev);
+  BusError:
+ 	if (dev->bus)
+@@ -1007,6 +1009,7 @@ void device_del(struct device *dev)
+ 	struct class_interface *class_intf;
+ 
+ 	device_pm_remove(dev);
++	dpm_sysfs_remove(dev);
+ 	if (parent)
+ 		klist_del(&dev->knode_parent);
+ 	if (MAJOR(dev->devt)) {
+diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
+index 3250c5257b74..284f564bb12b 100644
+--- a/drivers/base/power/main.c
++++ b/drivers/base/power/main.c
+@@ -67,10 +67,8 @@ void device_pm_unlock(void)
+  *	device_pm_add - add a device to the list of active devices
+  *	@dev:	Device to be added to the list
+  */
+-int device_pm_add(struct device *dev)
++void device_pm_add(struct device *dev)
+ {
+-	int error;
+-
+ 	pr_debug("PM: Adding info for %s:%s\n",
+ 		 dev->bus ? dev->bus->name : "No Bus",
+ 		 kobject_name(&dev->kobj));
+@@ -89,13 +87,9 @@ int device_pm_add(struct device *dev)
+ 		 */
+ 		WARN_ON(true);
+ 	}
+-	error = dpm_sysfs_add(dev);
+-	if (!error) {
+-		dev->power.status = DPM_ON;
+-		list_add_tail(&dev->power.entry, &dpm_list);
+-	}
++
++	list_add_tail(&dev->power.entry, &dpm_list);
+ 	mutex_unlock(&dpm_list_mtx);
+-	return error;
+ }
+ 
+ /**
+@@ -110,7 +104,6 @@ void device_pm_remove(struct device *dev)
+ 		 dev->bus ? dev->bus->name : "No Bus",
+ 		 kobject_name(&dev->kobj));
+ 	mutex_lock(&dpm_list_mtx);
+-	dpm_sysfs_remove(dev);
+ 	list_del_init(&dev->power.entry);
+ 	mutex_unlock(&dpm_list_mtx);
+ }
+diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
+index a3252c0e2887..41f51fae042f 100644
+--- a/drivers/base/power/power.h
++++ b/drivers/base/power/power.h
+@@ -1,3 +1,8 @@
++static inline void device_pm_init(struct device *dev)
++{
++	dev->power.status = DPM_ON;
++}
++
+ #ifdef CONFIG_PM_SLEEP
+ 
+ /*
+@@ -11,12 +16,12 @@ static inline struct device *to_device(struct list_head *entry)
+ 	return container_of(entry, struct device, power.entry);
+ }
+ 
+-extern int device_pm_add(struct device *);
++extern void device_pm_add(struct device *);
+ extern void device_pm_remove(struct device *);
+ 
+ #else /* CONFIG_PM_SLEEP */
+ 
+-static inline int device_pm_add(struct device *dev) { return 0; }
++static inline void device_pm_add(struct device *dev) {}
+ static inline void device_pm_remove(struct device *dev) {}
+ 
+ #endif

commit 9ff78433f0aeb1f731a22a90206b685df4eaf52e
+Author: Alan Stern 
+Date:   Thu Aug 7 13:04:51 2008 -0400
+
+    USB: fix compiler warning fix
+    
+    This patch (as1123b) fixes a compiler warning: do_unbind_rebind() is
+    defined but not used if CONFIG_PM=n.
+    
+    Problem originally found and initial patch submitted by Alexander
+    Beregalov .
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 6618bc89eb69..2be37fe466f2 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -774,8 +774,6 @@ void usb_deregister(struct usb_driver *driver)
+ }
+ EXPORT_SYMBOL_GPL(usb_deregister);
+ 
+-#ifdef CONFIG_PM
+-
+ /* Forced unbinding of a USB interface driver, either because
+  * it doesn't support pre_reset/post_reset/reset_resume or
+  * because it doesn't support suspend/resume.
+@@ -822,6 +820,8 @@ void usb_rebind_intf(struct usb_interface *intf)
+ 		dev_warn(&intf->dev, "rebind failed: %d\n", rc);
+ }
+ 
++#ifdef CONFIG_PM
++
+ #define DO_UNBIND	0
+ #define DO_REBIND	1
+ 

commit d28525f8866244a77b677c0470d4859cb2b6c2a8
+Author: Alan Stern 
+Date:   Thu Aug 7 13:02:40 2008 -0400
+
+    usb-storage: unusual_devs entry for Nokia 5300
+    
+    This patch (as1120) adds an unusual_devs entry for the Nokia 5300.
+    Maybe once Nokia releases the Symbian code we'll be able to fix all
+    the problems it has with the USB mass-storage protocol.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Cedric Godin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 564999c42d78..ba412e68d474 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -225,6 +225,13 @@ UNUSUAL_DEV(  0x0421, 0x0495, 0x0370, 0x0370,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_MAX_SECTORS_64 ),
+ 
++/* Reported by Cedric Godin  */
++UNUSUAL_DEV(  0x0421, 0x04b9, 0x0551, 0x0551,
++		"Nokia",
++		"5300",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_FIX_CAPACITY ),
++
+ /* Reported by Olaf Hering  from novell bug #105878 */
+ UNUSUAL_DEV(  0x0424, 0x0fdc, 0x0210, 0x0210,
+ 		"SMSC",

commit 368ee6469c327364ea10082a348f91c1f5ba47f7
+Author: Alan Stern 
+Date:   Mon Jul 21 10:08:28 2008 -0400
+
+    usb-storage: unusual_devs entries for iRiver T10 and Datafab CF+SM reader
+    
+    This patch (as1115) adds unusual_devs entries with the IGNORE_RESIDE
+    flag for the iRiver T10 and the Simple Tech/Datafab CF+SM card
+    reader.  Apparently these devices provide reasonable residue values
+    for READ and WRITE operations, but not for others like INQUIRY or READ
+    CAPACITY.
+    
+    This fixes the iRiver T10 problem reported in Bugzilla #11125.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 35ec1c69be1f..11249bf5d74f 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -1185,6 +1185,13 @@ UNUSUAL_DEV(  0x07c4, 0xa400, 0x0000, 0xffff,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_FIX_INQUIRY ),
+ 
++/* Reported by Rauch Wolke  */
++UNUSUAL_DEV(  0x07c4, 0xa4a5, 0x0000, 0xffff,
++		"Simple Tech/Datafab",
++		"CF+SM Reader",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_IGNORE_RESIDUE ),
++
+ /* Casio QV 2x00/3x00/4000/8000 digital still cameras are not conformant
+  * to the USB storage specification in two ways:
+  * - They tell us they are using transport protocol CBI. In reality they
+@@ -1767,6 +1774,13 @@ UNUSUAL_DEV(  0x2770, 0x915d, 0x0010, 0x0010,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_FIX_CAPACITY ),
+ 
++/* Reported by Andrey Rahmatullin  */
++UNUSUAL_DEV(  0x4102, 0x1020, 0x0100,  0x0100,
++		"iRiver",
++		"MP3 T10",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_IGNORE_RESIDUE ),
++
+ /*
+  * David Härdeman 
+  * The key makes the SCSI stack print confusing (but harmless) messages

commit 59f4ff2ecff4cef36378928cec891785b402e80c
+Author: Alan Stern 
+Date:   Tue Jul 29 11:58:06 2008 -0400
+
+    usb-storage: automatically recognize bad residues
+    
+    This patch (as1119) will help to reduce the clutter of usb-storage's
+    unusual_devs file by automatically detecting some devices that need
+    the IGNORE_RESIDUE flag.  The idea is that devices should never return
+    a non-zero residue for an INQUIRY or a READ CAPACITY command unless
+    they failed to transfer all the requested data.  So if one of these
+    commands transfers a standard amount of data but there is a positive
+    residue, we know that the residue is bogus and we can set the flag.
+    
+    This fixes the problems reported in Bugzilla #11125.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+index fcbbfdb7b2b0..3523a0bfa0ff 100644
+--- a/drivers/usb/storage/transport.c
++++ b/drivers/usb/storage/transport.c
+@@ -1032,8 +1032,21 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 
+ 	/* try to compute the actual residue, based on how much data
+ 	 * was really transferred and what the device tells us */
+-	if (residue) {
+-		if (!(us->fflags & US_FL_IGNORE_RESIDUE)) {
++	if (residue && !(us->fflags & US_FL_IGNORE_RESIDUE)) {
++
++		/* Heuristically detect devices that generate bogus residues
++		 * by seeing what happens with INQUIRY and READ CAPACITY
++		 * commands.
++		 */
++		if (bcs->Status == US_BULK_STAT_OK &&
++				scsi_get_resid(srb) == 0 &&
++					((srb->cmnd[0] == INQUIRY &&
++						transfer_length == 36) ||
++					(srb->cmnd[0] == READ_CAPACITY &&
++						transfer_length == 8))) {
++			us->fflags |= US_FL_IGNORE_RESIDUE;
++
++		} else {
+ 			residue = min(residue, transfer_length);
+ 			scsi_set_resid(srb, max(scsi_get_resid(srb),
+ 			                                       (int) residue));

commit 1a21175a615ed346e8043f5e9d60a672266b84b4
+Author: Alan Stern 
+Date:   Wed Jul 30 11:31:50 2008 -0400
+
+    USB: fix interface unregistration logic
+    
+    This patch (as1122) fixes a bug: When an interface is unregistered,
+    its children (sysfs files and endpoint devices) are unregistered after
+    it instead of before.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Kay Sievers 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 586d6f1376cf..286b4431a097 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1091,8 +1091,8 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
+ 				continue;
+ 			dev_dbg(&dev->dev, "unregistering interface %s\n",
+ 				dev_name(&interface->dev));
+-			device_del(&interface->dev);
+ 			usb_remove_sysfs_intf_files(interface);
++			device_del(&interface->dev);
+ 		}
+ 
+ 		/* Now that the interfaces are unbound, nobody should

commit 0282b7f2a874e72c18fcd5a112ccf67f71ba7f5c
+Author: Alan Stern 
+Date:   Tue Jul 29 12:01:04 2008 -0400
+
+    usb-serial: don't release unregistered minors
+    
+    This patch (as1121) fixes a bug in the USB serial core.  When a device
+    is unregistered, the core will give back its minors -- even if the
+    device hasn't been assigned any!
+    
+    The patch reserves the highest minor value (255) to mean that no minor
+    was assigned.  It also removes some dead code and does a small style
+    fixup.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
+index 8c2d531eedea..b157c48e8b78 100644
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -122,9 +122,6 @@ static void return_serial(struct usb_serial *serial)
+ 
+ 	dbg("%s", __func__);
+ 
+-	if (serial == NULL)
+-		return;
+-
+ 	for (i = 0; i < serial->num_ports; ++i)
+ 		serial_table[serial->minor + i] = NULL;
+ }
+@@ -142,7 +139,8 @@ static void destroy_serial(struct kref *kref)
+ 	serial->type->shutdown(serial);
+ 
+ 	/* return the minor range that this device had */
+-	return_serial(serial);
++	if (serial->minor != SERIAL_TTY_NO_MINOR)
++		return_serial(serial);
+ 
+ 	for (i = 0; i < serial->num_ports; ++i)
+ 		serial->port[i]->port.count = 0;
+@@ -575,6 +573,7 @@ static struct usb_serial *create_serial(struct usb_device *dev,
+ 	serial->interface = interface;
+ 	kref_init(&serial->kref);
+ 	mutex_init(&serial->disc_mutex);
++	serial->minor = SERIAL_TTY_NO_MINOR;
+ 
+ 	return serial;
+ }
+diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
+index 09a3e6a7518f..655341d0f534 100644
+--- a/include/linux/usb/serial.h
++++ b/include/linux/usb/serial.h
+@@ -17,7 +17,8 @@
+ #include 
+ 
+ #define SERIAL_TTY_MAJOR	188	/* Nice legal number now */
+-#define SERIAL_TTY_MINORS	255	/* loads of devices :) */
++#define SERIAL_TTY_MINORS	254	/* loads of devices :) */
++#define SERIAL_TTY_NO_MINOR	255	/* No minor was assigned */
+ 
+ /* The maximum number of ports one device can grab at once */
+ #define MAX_NUM_PORTS		8

commit 38b375d9610e2467cb793a84d17c6f65e44cdb39
+Author: Alan Stern 
+Date:   Mon Jul 21 09:56:26 2008 -0400
+
+    USB: OHCI: fix system hang caused by earlier patch
+    
+    This patch (as1114) fixes a problem that was revealed by an earlier
+    patch (as1069b).  Some broken controllers seem never to turn off their
+    RHCS interrupt status bit, even when told to do so.  As a result they
+    generate an interrupt storm and hang the system.
+    
+    The patch avoids enabling RHSC interrupt requests when the RHCS status
+    bit is already set.  This should have no adverse affects on normal
+    controllers, since they won't set the status bit until a root-hub
+    status change actually occurs, in which case we wouldn't enable RHSC
+    interrupt requests anyway -- we would wait until the status change had
+    been processed and cleared.
+    
+    Signed-off-by: Alan Stern 
+    Tested by: Andrey Borzenkov 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index b56739221d11..d54183f1d701 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -483,6 +483,13 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ 		length++;
+ 	}
+ 
++	/* Some broken controllers never turn off RHCS in the interrupt
++	 * status register.  For their sake we won't re-enable RHSC
++	 * interrupts if the flag is already set.
++	 */
++	if (ohci_readl(ohci, &ohci->regs->intrstatus) & OHCI_INTR_RHSC)
++		changed = 1;
++
+ 	/* look at each port */
+ 	for (i = 0; i < ohci->num_ports; i++) {
+ 		u32	status = roothub_portstatus (ohci, i);

commit f4f4d58734916e816d4b4a7cf61b3fc22ce02683
+Author: Alan Stern 
+Date:   Mon Jul 28 10:39:28 2008 -0400
+
+    USB: add missing kerneldoc line for "needs_binding"
+    
+    This patch (as1117) adds a kerneldoc line for the "needs_binding"
+    field in struct usb_interface.  It was accidentally omitted when the
+    field was added.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 5811c5da69f9..0924cd9c30f6 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -110,6 +110,8 @@ enum usb_interface_condition {
+  * @sysfs_files_created: sysfs attributes exist
+  * @needs_remote_wakeup: flag set when the driver requires remote-wakeup
+  *	capability during autosuspend.
++ * @needs_binding: flag set when the driver should be re-probed or unbound
++ *	following a reset or suspend operation it doesn't support.
+  * @dev: driver model's view of this device
+  * @usb_dev: if an interface is bound to the USB major, this will point
+  *	to the sysfs representation for that device.

commit 580da34847488b404218d1d7f53b156f245f5555
+Author: Alan Stern 
+Date:   Tue Aug 5 13:05:17 2008 -0400
+
+    Fix USB storage hang on command abort
+    
+    Okay, I found the cause of the hang.  It is a simple bug in the USB
+    scatter-gather library, caused by changes added in response to the S-G
+    chaining modification.
+    
+    This patch (as1125) fixes a bug in the USB scatter-gather library.
+    Early exit from the S-G initialization loop does not reset the count of
+    outstanding URBs.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Matthew Dharm 
+    Cc: David Brownell 
+    Cc: Alan Jenkins 
+    Cc: James Bottomley 
+    Cc: Greg KH 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 2fcc06eb5e60..586d6f1376cf 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -389,7 +389,6 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
+ 	if (io->entries <= 0)
+ 		return io->entries;
+ 
+-	io->count = io->entries;
+ 	io->urbs = kmalloc(io->entries * sizeof *io->urbs, mem_flags);
+ 	if (!io->urbs)
+ 		goto nomem;
+@@ -458,6 +457,7 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
+ 	io->urbs[--i]->transfer_flags &= ~URB_NO_INTERRUPT;
+ 
+ 	/* transaction state */
++	io->count = io->entries;
+ 	io->status = 0;
+ 	io->bytes = 0;
+ 	init_completion(&io->complete);

commit 12265709ac6e197f4d40d9ec1fd3af97b4196a35
+Author: Alan Stern 
+Date:   Mon Jul 21 10:25:52 2008 -0400
+
+    [SCSI] scsi_eh_prep_cmnd should save scmd->underflow
+    
+    This patch (as1116) fixes a bug in scsi_eh_prep_cmnd() and
+    scsi_eh_restore_cmnd().  These routines are supposed to save any
+    values they change and restore them later, but someone forgot to
+    save & restore scmd->underflow.
+    
+    This fixes part of the problem reported in Bugzilla #9638.
+    
+    [jejb: fix up rejections around DIF/DIX]
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
+index fc4b2d05f2e1..171b82d748cf 100644
+--- a/drivers/scsi/scsi_error.c
++++ b/drivers/scsi/scsi_error.c
+@@ -667,6 +667,7 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
+ 	ses->sdb = scmd->sdb;
+ 	ses->next_rq = scmd->request->next_rq;
+ 	ses->result = scmd->result;
++	ses->underflow = scmd->underflow;
+ 	ses->prot_op = scmd->prot_op;
+ 
+ 	scmd->prot_op = SCSI_PROT_NORMAL;
+@@ -727,6 +728,7 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
+ 	scmd->sdb = ses->sdb;
+ 	scmd->request->next_rq = ses->next_rq;
+ 	scmd->result = ses->result;
++	scmd->underflow = ses->underflow;
+ 	scmd->prot_op = ses->prot_op;
+ }
+ EXPORT_SYMBOL(scsi_eh_restore_cmnd);
+diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h
+index e5499ed0e376..06a8790893ef 100644
+--- a/include/scsi/scsi_eh.h
++++ b/include/scsi/scsi_eh.h
+@@ -74,6 +74,7 @@ struct scsi_eh_save {
+ 	/* saved state */
+ 	int result;
+ 	enum dma_data_direction data_direction;
++	unsigned underflow;
+ 	unsigned char cmd_len;
+ 	unsigned char prot_op;
+ 	unsigned char *cmnd;

commit 8111d1b552349921aae1acf73e4e8cea98e80970
+Author: Alan Stern 
+Date:   Wed Jul 23 21:28:37 2008 -0700
+
+    pm: add new PM_EVENT codes for runtime power transitions
+    
+    This patch (as1112) adds some new PM_EVENT_* codes for use by kernel
+    subsystems.  They describe runtime power-state transitions of the sort already
+    implemented by the USB subsystem.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+    Acked-by: Pavel Machek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/pm.h b/include/linux/pm.h
+index ed98d967f9fb..4dcce54b6d76 100644
+--- a/include/linux/pm.h
++++ b/include/linux/pm.h
+@@ -245,6 +245,21 @@ struct pm_ext_ops {
+  * RECOVER	Creation of a hibernation image or restoration of the main
+  *		memory contents from a hibernation image has failed, call
+  *		->thaw() and ->complete() for all devices.
++ *
++ * The following PM_EVENT_ messages are defined for internal use by
++ * kernel subsystems.  They are never issued by the PM core.
++ *
++ * USER_SUSPEND		Manual selective suspend was issued by userspace.
++ *
++ * USER_RESUME		Manual selective resume was issued by userspace.
++ *
++ * REMOTE_WAKEUP	Remote-wakeup request was received from the device.
++ *
++ * AUTO_SUSPEND		Automatic (device idle) runtime suspend was
++ *			initiated by the subsystem.
++ *
++ * AUTO_RESUME		Automatic (device needed) runtime resume was
++ *			requested by a driver.
+  */
+ 
+ #define PM_EVENT_ON		0x0000
+@@ -256,9 +271,18 @@ struct pm_ext_ops {
+ #define PM_EVENT_THAW		0x0020
+ #define PM_EVENT_RESTORE	0x0040
+ #define PM_EVENT_RECOVER	0x0080
++#define PM_EVENT_USER		0x0100
++#define PM_EVENT_REMOTE		0x0200
++#define PM_EVENT_AUTO		0x0400
+ 
+-#define PM_EVENT_SLEEP	(PM_EVENT_SUSPEND | PM_EVENT_HIBERNATE)
++#define PM_EVENT_SLEEP		(PM_EVENT_SUSPEND | PM_EVENT_HIBERNATE)
++#define PM_EVENT_USER_SUSPEND	(PM_EVENT_USER | PM_EVENT_SUSPEND)
++#define PM_EVENT_USER_RESUME	(PM_EVENT_USER | PM_EVENT_RESUME)
++#define PM_EVENT_REMOTE_WAKEUP	(PM_EVENT_REMOTE | PM_EVENT_RESUME)
++#define PM_EVENT_AUTO_SUSPEND	(PM_EVENT_AUTO | PM_EVENT_SUSPEND)
++#define PM_EVENT_AUTO_RESUME	(PM_EVENT_AUTO | PM_EVENT_RESUME)
+ 
++#define PMSG_ON		((struct pm_message){ .event = PM_EVENT_ON, })
+ #define PMSG_FREEZE	((struct pm_message){ .event = PM_EVENT_FREEZE, })
+ #define PMSG_QUIESCE	((struct pm_message){ .event = PM_EVENT_QUIESCE, })
+ #define PMSG_SUSPEND	((struct pm_message){ .event = PM_EVENT_SUSPEND, })
+@@ -267,7 +291,16 @@ struct pm_ext_ops {
+ #define PMSG_THAW	((struct pm_message){ .event = PM_EVENT_THAW, })
+ #define PMSG_RESTORE	((struct pm_message){ .event = PM_EVENT_RESTORE, })
+ #define PMSG_RECOVER	((struct pm_message){ .event = PM_EVENT_RECOVER, })
+-#define PMSG_ON		((struct pm_message){ .event = PM_EVENT_ON, })
++#define PMSG_USER_SUSPEND	((struct pm_messge) \
++					{ .event = PM_EVENT_USER_SUSPEND, })
++#define PMSG_USER_RESUME	((struct pm_messge) \
++					{ .event = PM_EVENT_USER_RESUME, })
++#define PMSG_REMOTE_RESUME	((struct pm_messge) \
++					{ .event = PM_EVENT_REMOTE_RESUME, })
++#define PMSG_AUTO_SUSPEND	((struct pm_messge) \
++					{ .event = PM_EVENT_AUTO_SUSPEND, })
++#define PMSG_AUTO_RESUME		((struct pm_messge) \
++					{ .event = PM_EVENT_AUTO_RESUME, })
+ 
+ /**
+  * Device power management states

commit f756cbd458ab71c996a069cb3928fb1e2d7cd9cc
+Author: Alan Stern 
+Date:   Mon Jun 30 13:39:59 2008 -0400
+
+    usb-storage: revert DMA-alignment change for Wireless USB
+    
+    This patch (as1110) reverts an earlier patch meant to help with
+    Wireless USB host controllers.  These controllers can have bulk
+    maxpacket values larger than 512, which puts unusual constraints on
+    the sizes of scatter-gather list elements.  However it turns out that
+    the block layer does not provide the support we need to enforce these
+    constraints; merely changing the DMA alignment mask doesn't help.
+    Hence there's no reason to keep the original patch.  The Wireless USB
+    problem will have to be solved a different way.
+    
+    In addition, there is a reason to get rid of the earlier patch.  By
+    dereferencing a pointer stored in the ep_in array of struct
+    usb_device, the current code risks an invalid memory access when it
+    runs concurrently with device removal.  The members of that array are
+    cleared before the driver's disconnect method is called, so it should
+    not try to use them.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index b4c9e0f18a82..09779f6a8179 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -71,7 +71,6 @@ static const char* host_info(struct Scsi_Host *host)
+ static int slave_alloc (struct scsi_device *sdev)
+ {
+ 	struct us_data *us = host_to_us(sdev->host);
+-	struct usb_host_endpoint *bulk_in_ep;
+ 
+ 	/*
+ 	 * Set the INQUIRY transfer length to 36.  We don't use any of
+@@ -80,16 +79,22 @@ static int slave_alloc (struct scsi_device *sdev)
+ 	 */
+ 	sdev->inquiry_len = 36;
+ 
+-	/* Scatter-gather buffers (all but the last) must have a length
+-	 * divisible by the bulk maxpacket size.  Otherwise a data packet
+-	 * would end up being short, causing a premature end to the data
+-	 * transfer.  We'll use the maxpacket value of the bulk-IN pipe
+-	 * to set the SCSI device queue's DMA alignment mask.
++	/* USB has unusual DMA-alignment requirements: Although the
++	 * starting address of each scatter-gather element doesn't matter,
++	 * the length of each element except the last must be divisible
++	 * by the Bulk maxpacket value.  There's currently no way to
++	 * express this by block-layer constraints, so we'll cop out
++	 * and simply require addresses to be aligned at 512-byte
++	 * boundaries.  This is okay since most block I/O involves
++	 * hardware sectors that are multiples of 512 bytes in length,
++	 * and since host controllers up through USB 2.0 have maxpacket
++	 * values no larger than 512.
++	 *
++	 * But it doesn't suffice for Wireless USB, where Bulk maxpacket
++	 * values can be as large as 2048.  To make that work properly
++	 * will require changes to the block layer.
+ 	 */
+-	bulk_in_ep = us->pusb_dev->ep_in[usb_pipeendpoint(us->recv_bulk_pipe)];
+-	blk_queue_update_dma_alignment(sdev->request_queue,
+-			le16_to_cpu(bulk_in_ep->desc.wMaxPacketSize) - 1);
+-			/* wMaxPacketSize must be a power of 2 */
++	blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
+ 
+ 	/*
+ 	 * The UFI spec treates the Peripheral Qualifier bits in an

commit 86c57edf60f5c98adb496880f56cd0e5a3423153
+Author: Alan Stern 
+Date:   Mon Jun 30 11:14:43 2008 -0400
+
+    USB: use reset_resume when normal resume fails
+    
+    This patch (as1109b) makes USB-Persist more resilient to errors.  With
+    the current code, if a normal resume fails, it's an unrecoverable
+    error.  With the patch, if a normal resume fails (and if the device is
+    enabled for USB-Persist) then a reset-resume is tried.
+    
+    This fixes the problem reported in Bugzilla #10977.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/usb/persist.txt b/Documentation/usb/persist.txt
+index d56cb1a11550..074b159b77c2 100644
+--- a/Documentation/usb/persist.txt
++++ b/Documentation/usb/persist.txt
+@@ -81,8 +81,11 @@ re-enumeration shows that the device now attached to that port has the
+ same descriptors as before, including the Vendor and Product IDs, then
+ the kernel continues to use the same device structure.  In effect, the
+ kernel treats the device as though it had merely been reset instead of
+-unplugged.  The same thing happens if the host controller is in the
+-expected state but a USB device was unplugged and then replugged.
++unplugged.
++
++The same thing happens if the host controller is in the expected state
++but a USB device was unplugged and then replugged, or if a USB device
++fails to carry out a normal resume.
+ 
+ If no device is now attached to the port, or if the descriptors are
+ different from what the kernel remembers, then the treatment is what
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index f1efabbc1ca2..107e1d25ddec 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1822,9 +1822,15 @@ static int check_port_resume_type(struct usb_device *udev,
+ 			status = -ENODEV;
+ 	}
+ 
+-	/* Can't do a normal resume if the port isn't enabled */
+-	else if (!(portstatus & USB_PORT_STAT_ENABLE) && !udev->reset_resume)
+-		status = -ENODEV;
++	/* Can't do a normal resume if the port isn't enabled,
++	 * so try a reset-resume instead.
++	 */
++	else if (!(portstatus & USB_PORT_STAT_ENABLE) && !udev->reset_resume) {
++		if (udev->persist_enabled)
++			udev->reset_resume = 1;
++		else
++			status = -ENODEV;
++	}
+ 
+ 	if (status) {
+ 		dev_dbg(hub->intfdev,
+@@ -1973,6 +1979,7 @@ static int finish_port_resume(struct usb_device *udev)
+ 	 * resumed.
+ 	 */
+ 	if (udev->reset_resume)
++ retry_reset_resume:
+ 		status = usb_reset_and_verify_device(udev);
+ 
+  	/* 10.5.4.5 says be sure devices in the tree are still there.
+@@ -1984,6 +1991,13 @@ static int finish_port_resume(struct usb_device *udev)
+ 		status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
+ 		if (status >= 0)
+ 			status = (status > 0 ? 0 : -ENODEV);
++
++		/* If a normal resume failed, try doing a reset-resume */
++		if (status && !udev->reset_resume && udev->persist_enabled) {
++			dev_dbg(&udev->dev, "retry with reset-resume\n");
++			udev->reset_resume = 1;
++			goto retry_reset_resume;
++		}
+ 	}
+ 
+ 	if (status) {

commit e04199b2167e88f0e2d0410fafaa2c35ff7ba8c1
+Author: Alan Stern 
+Date:   Tue Jun 24 14:47:29 2008 -0400
+
+    usbfs: don't store bad pointers in registration
+    
+    This patch (as1107) fixes a small bug in the usbfs registration and
+    unregistration code.  It avoids leaving an error value stored in the
+    device's usb_classdev field and it avoids trying to unregister a NULL
+    pointer.  (It also fixes a rather extreme overuse of whitespace.)
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index c44e98f6099e..5580c6e59bae 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -1726,20 +1726,21 @@ static struct class *usb_classdev_class;
+ 
+ static int usb_classdev_add(struct usb_device *dev)
+ {
+-	int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1);
+-
+-	dev->usb_classdev = device_create(usb_classdev_class, &dev->dev,
+-				MKDEV(USB_DEVICE_MAJOR, minor),
+-				"usbdev%d.%d", dev->bus->busnum, dev->devnum);
+-	if (IS_ERR(dev->usb_classdev))
+-		return PTR_ERR(dev->usb_classdev);
+-
++	struct device *cldev;
++
++	cldev = device_create(usb_classdev_class, &dev->dev, dev->dev.devt,
++			      "usbdev%d.%d", dev->bus->busnum,
++			      dev->devnum);
++	if (IS_ERR(cldev))
++		return PTR_ERR(cldev);
++	dev->usb_classdev = cldev;
+ 	return 0;
+ }
+ 
+ static void usb_classdev_remove(struct usb_device *dev)
+ {
+-	device_unregister(dev->usb_classdev);
++	if (dev->usb_classdev)
++		device_unregister(dev->usb_classdev);
+ 	usb_fs_classdev_common_remove(dev);
+ }
+ 

commit d64aac36394b3c26db53538bfedd8444a3a2206e
+Author: Alan Stern 
+Date:   Tue Jun 24 14:47:19 2008 -0400
+
+    usbfs: fix race between open and unregister
+    
+    This patch (as1106) fixes a race between opening and unregistering
+    device files in usbfs.  The current code drops its reference to the
+    device and then reacquires it, ignoring the possibility that the
+    device structure might have been removed in the meantime.  It also
+    doesn't check whether the device is already in the NOTATTACHED state
+    when the file is opened.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 57bedcebf96c..c44e98f6099e 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -562,7 +562,6 @@ static struct usb_device *usbdev_lookup_by_devt(dev_t devt)
+ 	dev = bus_find_device(&usb_bus_type, NULL, (void *) devt, match_devt);
+ 	if (!dev)
+ 		return NULL;
+-	put_device(dev);
+ 	return container_of(dev, struct usb_device, dev);
+ }
+ 
+@@ -591,16 +590,21 @@ static int usbdev_open(struct inode *inode, struct file *file)
+ 		dev = usbdev_lookup_by_devt(inode->i_rdev);
+ #ifdef CONFIG_USB_DEVICEFS
+ 	/* procfs file */
+-	if (!dev)
++	if (!dev) {
+ 		dev = inode->i_private;
++		if (dev && dev->usbfs_dentry &&
++					dev->usbfs_dentry->d_inode == inode)
++			usb_get_dev(dev);
++		else
++			dev = NULL;
++	}
+ #endif
+-	if (!dev)
++	if (!dev || dev->state == USB_STATE_NOTATTACHED)
+ 		goto out;
+ 	ret = usb_autoresume_device(dev);
+ 	if (ret)
+ 		goto out;
+ 
+-	usb_get_dev(dev);
+ 	ret = 0;
+ 	ps->dev = dev;
+ 	ps->file = file;
+@@ -620,8 +624,10 @@ static int usbdev_open(struct inode *inode, struct file *file)
+ 	list_add_tail(&ps->list, &dev->filelist);
+ 	file->private_data = ps;
+  out:
+-	if (ret)
++	if (ret) {
+ 		kfree(ps);
++		usb_put_dev(dev);
++	}
+ 	mutex_unlock(&usbfs_mutex);
+ 	unlock_kernel();
+ 	return ret;

commit 61ad04a89f0e3e6adaed0d9adfc0c9b431ccbb92
+Author: Alan Stern 
+Date:   Tue Jun 24 14:47:12 2008 -0400
+
+    usbfs: simplify the lookup-by-minor routines
+    
+    This patch (as1105) simplifies the lookup-by-minor-number code in
+    usbfs.  Instead of passing the minor number to the callback, which
+    must then reconstruct the entire dev_t value, the patch passes the
+    dev_t value directly.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index bbd029f68faa..57bedcebf96c 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -550,20 +550,16 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype,
+ 	return ret;
+ }
+ 
+-static int __match_minor(struct device *dev, void *data)
++static int match_devt(struct device *dev, void *data)
+ {
+-	int minor = *((int *)data);
+-
+-	if (dev->devt == MKDEV(USB_DEVICE_MAJOR, minor))
+-		return 1;
+-	return 0;
++	return (dev->devt == (dev_t) data);
+ }
+ 
+-static struct usb_device *usbdev_lookup_by_minor(int minor)
++static struct usb_device *usbdev_lookup_by_devt(dev_t devt)
+ {
+ 	struct device *dev;
+ 
+-	dev = bus_find_device(&usb_bus_type, NULL, &minor, __match_minor);
++	dev = bus_find_device(&usb_bus_type, NULL, (void *) devt, match_devt);
+ 	if (!dev)
+ 		return NULL;
+ 	put_device(dev);
+@@ -589,9 +585,10 @@ static int usbdev_open(struct inode *inode, struct file *file)
+ 		goto out;
+ 
+ 	ret = -ENOENT;
++
+ 	/* usbdev device-node */
+ 	if (imajor(inode) == USB_DEVICE_MAJOR)
+-		dev = usbdev_lookup_by_minor(iminor(inode));
++		dev = usbdev_lookup_by_devt(inode->i_rdev);
+ #ifdef CONFIG_USB_DEVICEFS
+ 	/* procfs file */
+ 	if (!dev)

commit cd9f03759d3eb588e185b04e1854c778b050833e
+Author: Alan Stern 
+Date:   Tue Jun 24 14:47:04 2008 -0400
+
+    usbfs: send disconnect signals when device is unregistered
+    
+    USB device files are accessible in two ways: as files in usbfs and as
+    character device nodes.  The two paths are supposed to behave
+    identically, but they don't.  When the underlying USB device is
+    unplugged, disconnect signals are sent to processes with open usbfs
+    files (if they requested these signals) but not to processes with open
+    device node files.
+    
+    This patch (as1104) fixes the bug by moving the disconnect-signalling
+    code into a common subroutine which is called from both paths.
+    Putting this subroutine in devio.c removes the only out-of-file
+    reference to struct dev_state, and so the structure's declaration can
+    be moved from usb.h into devio.c.
+    
+    Finally, the new subroutine performs one extra action: It kills all
+    the outstanding async URBs.  (I'd kill the outstanding synchronous
+    URBs too, if there was any way to do it.)  In the past this hasn't
+    mattered much, because devices were unregistered from usbfs only
+    when they were disconnected.  But now the unregistration can also
+    occur whenever devices are unbound from the usb_generic driver.  At
+    any rate, killing URBs when a device is unregistered from usbfs seems
+    like a good thing to do.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index e09935acae80..bbd029f68faa 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -59,6 +59,22 @@
+ /* Mutual exclusion for removal, open, and release */
+ DEFINE_MUTEX(usbfs_mutex);
+ 
++struct dev_state {
++	struct list_head list;      /* state list */
++	struct usb_device *dev;
++	struct file *file;
++	spinlock_t lock;            /* protects the async urb lists */
++	struct list_head async_pending;
++	struct list_head async_completed;
++	wait_queue_head_t wait;     /* wake up if a request completed */
++	unsigned int discsignr;
++	struct pid *disc_pid;
++	uid_t disc_uid, disc_euid;
++	void __user *disccontext;
++	unsigned long ifclaimed;
++	u32 secid;
++};
++
+ struct async {
+ 	struct list_head asynclist;
+ 	struct dev_state *ps;
+@@ -1680,6 +1696,28 @@ const struct file_operations usbdev_file_operations = {
+ 	.release =	usbdev_release,
+ };
+ 
++void usb_fs_classdev_common_remove(struct usb_device *udev)
++{
++	struct dev_state *ps;
++	struct siginfo sinfo;
++
++	while (!list_empty(&udev->filelist)) {
++		ps = list_entry(udev->filelist.next, struct dev_state, list);
++		destroy_all_async(ps);
++		wake_up_all(&ps->wait);
++		list_del_init(&ps->list);
++		if (ps->discsignr) {
++			sinfo.si_signo = ps->discsignr;
++			sinfo.si_errno = EPIPE;
++			sinfo.si_code = SI_ASYNCIO;
++			sinfo.si_addr = ps->disccontext;
++			kill_pid_info_as_uid(ps->discsignr, &sinfo,
++					ps->disc_pid, ps->disc_uid,
++					ps->disc_euid, ps->secid);
++		}
++	}
++}
++
+ #ifdef CONFIG_USB_DEVICE_CLASS
+ static struct class *usb_classdev_class;
+ 
+@@ -1699,6 +1737,7 @@ static int usb_classdev_add(struct usb_device *dev)
+ static void usb_classdev_remove(struct usb_device *dev)
+ {
+ 	device_unregister(dev->usb_classdev);
++	usb_fs_classdev_common_remove(dev);
+ }
+ 
+ static int usb_classdev_notify(struct notifier_block *self,
+diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
+index 1d253dd4ea81..db410e92c80d 100644
+--- a/drivers/usb/core/inode.c
++++ b/drivers/usb/core/inode.c
+@@ -712,25 +712,11 @@ static void usbfs_add_device(struct usb_device *dev)
+ 
+ static void usbfs_remove_device(struct usb_device *dev)
+ {
+-	struct dev_state *ds;
+-	struct siginfo sinfo;
+-
+ 	if (dev->usbfs_dentry) {
+ 		fs_remove_file (dev->usbfs_dentry);
+ 		dev->usbfs_dentry = NULL;
+ 	}
+-	while (!list_empty(&dev->filelist)) {
+-		ds = list_entry(dev->filelist.next, struct dev_state, list);
+-		wake_up_all(&ds->wait);
+-		list_del_init(&ds->list);
+-		if (ds->discsignr) {
+-			sinfo.si_signo = ds->discsignr;
+-			sinfo.si_errno = EPIPE;
+-			sinfo.si_code = SI_ASYNCIO;
+-			sinfo.si_addr = ds->disccontext;
+-			kill_pid_info_as_uid(ds->discsignr, &sinfo, ds->disc_pid, ds->disc_uid, ds->disc_euid, ds->secid);
+-		}
+-	}
++	usb_fs_classdev_common_remove(dev);
+ }
+ 
+ static int usbfs_notify(struct notifier_block *self, unsigned long action, void *dev)
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index d3eb0a29bca1..d9a6e16dbf84 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -142,26 +142,11 @@ extern struct usb_driver usbfs_driver;
+ extern const struct file_operations usbfs_devices_fops;
+ extern const struct file_operations usbdev_file_operations;
+ extern void usbfs_conn_disc_event(void);
++extern void usb_fs_classdev_common_remove(struct usb_device *udev);
+ 
+ extern int usb_devio_init(void);
+ extern void usb_devio_cleanup(void);
+ 
+-struct dev_state {
+-	struct list_head list;      /* state list */
+-	struct usb_device *dev;
+-	struct file *file;
+-	spinlock_t lock;            /* protects the async urb lists */
+-	struct list_head async_pending;
+-	struct list_head async_completed;
+-	wait_queue_head_t wait;     /* wake up if a request completed */
+-	unsigned int discsignr;
+-	struct pid *disc_pid;
+-	uid_t disc_uid, disc_euid;
+-	void __user *disccontext;
+-	unsigned long ifclaimed;
+-	u32 secid;
+-};
+-
+ /* internal notify stuff */
+ extern void usb_notify_add_device(struct usb_device *udev);
+ extern void usb_notify_remove_device(struct usb_device *udev);

commit 78d9a487ee961c356e1a934d9a92eca38ffb3a70
+Author: Alan Stern 
+Date:   Mon Jun 23 16:00:40 2008 -0400
+
+    USB: Force unbinding of drivers lacking reset_resume or other methods
+    
+    This patch (as1024) takes care of a FIXME issue: Drivers that don't
+    have the necessary suspend, resume, reset_resume, pre_reset, or
+    post_reset methods will be unbound and their interface reprobed when
+    one of the unsupported events occurs.
+    
+    This is made slightly more difficult by the fact that bind operations
+    won't work during a system sleep transition.  So instead the code has
+    to defer the operation until the transition ends.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 8da1a56659be..ddb54e14a5c5 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -201,6 +201,7 @@ static int usb_probe_interface(struct device *dev)
+ 
+ 	intf = to_usb_interface(dev);
+ 	udev = interface_to_usbdev(intf);
++	intf->needs_binding = 0;
+ 
+ 	if (udev->authorized == 0) {
+ 		dev_err(&intf->dev, "Device is not authorized for usage\n");
+@@ -311,6 +312,7 @@ int usb_driver_claim_interface(struct usb_driver *driver,
+ 
+ 	dev->driver = &driver->drvwrap.driver;
+ 	usb_set_intfdata(iface, priv);
++	iface->needs_binding = 0;
+ 
+ 	usb_pm_lock(udev);
+ 	iface->condition = USB_INTERFACE_BOUND;
+@@ -772,6 +774,104 @@ void usb_deregister(struct usb_driver *driver)
+ }
+ EXPORT_SYMBOL_GPL(usb_deregister);
+ 
++
++/* Forced unbinding of a USB interface driver, either because
++ * it doesn't support pre_reset/post_reset/reset_resume or
++ * because it doesn't support suspend/resume.
++ *
++ * The caller must hold @intf's device's lock, but not its pm_mutex
++ * and not @intf->dev.sem.
++ */
++void usb_forced_unbind_intf(struct usb_interface *intf)
++{
++	struct usb_driver *driver = to_usb_driver(intf->dev.driver);
++
++	dev_dbg(&intf->dev, "forced unbind\n");
++	usb_driver_release_interface(driver, intf);
++
++	/* Mark the interface for later rebinding */
++	intf->needs_binding = 1;
++}
++
++/* Delayed forced unbinding of a USB interface driver and scan
++ * for rebinding.
++ *
++ * The caller must hold @intf's device's lock, but not its pm_mutex
++ * and not @intf->dev.sem.
++ *
++ * FIXME: The caller must block system sleep transitions.
++ */
++void usb_rebind_intf(struct usb_interface *intf)
++{
++	int rc;
++
++	/* Delayed unbind of an existing driver */
++	if (intf->dev.driver) {
++		struct usb_driver *driver =
++				to_usb_driver(intf->dev.driver);
++
++		dev_dbg(&intf->dev, "forced unbind\n");
++		usb_driver_release_interface(driver, intf);
++	}
++
++	/* Try to rebind the interface */
++	intf->needs_binding = 0;
++	rc = device_attach(&intf->dev);
++	if (rc < 0)
++		dev_warn(&intf->dev, "rebind failed: %d\n", rc);
++}
++
++#define DO_UNBIND	0
++#define DO_REBIND	1
++
++/* Unbind drivers for @udev's interfaces that don't support suspend/resume,
++ * or rebind interfaces that have been unbound, according to @action.
++ *
++ * The caller must hold @udev's device lock.
++ * FIXME: For rebinds, the caller must block system sleep transitions.
++ */
++static void do_unbind_rebind(struct usb_device *udev, int action)
++{
++	struct usb_host_config	*config;
++	int			i;
++	struct usb_interface	*intf;
++	struct usb_driver	*drv;
++
++	config = udev->actconfig;
++	if (config) {
++		for (i = 0; i < config->desc.bNumInterfaces; ++i) {
++			intf = config->interface[i];
++			switch (action) {
++			case DO_UNBIND:
++				if (intf->dev.driver) {
++					drv = to_usb_driver(intf->dev.driver);
++					if (!drv->suspend || !drv->resume)
++						usb_forced_unbind_intf(intf);
++				}
++				break;
++			case DO_REBIND:
++				if (intf->needs_binding) {
++
++	/* FIXME: The next line is needed because we are going to probe
++	 * the interface, but as far as the PM core is concerned the
++	 * interface is still suspended.  The problem wouldn't exist
++	 * if we could rebind the interface during the interface's own
++	 * resume() call, but at the time the usb_device isn't locked!
++	 *
++	 * The real solution will be to carry this out during the device's
++	 * complete() callback.  Until that is implemented, we have to
++	 * use this hack.
++	 */
++//					intf->dev.power.sleeping = 0;
++
++					usb_rebind_intf(intf);
++				}
++				break;
++			}
++		}
++	}
++}
++
+ #ifdef CONFIG_PM
+ 
+ /* Caller has locked udev's pm_mutex */
+@@ -841,7 +941,7 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
+ 		goto done;
+ 	driver = to_usb_driver(intf->dev.driver);
+ 
+-	if (driver->suspend && driver->resume) {
++	if (driver->suspend) {
+ 		status = driver->suspend(intf, msg);
+ 		if (status == 0)
+ 			mark_quiesced(intf);
+@@ -849,12 +949,10 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
+ 			dev_err(&intf->dev, "%s error %d\n",
+ 					"suspend", status);
+ 	} else {
+-		/*
+-		 * FIXME else if there's no suspend method, disconnect...
+-		 * Not possible if auto_pm is set...
+-		 */
+-		dev_warn(&intf->dev, "no suspend for driver %s?\n",
+-				driver->name);
++		/* Later we will unbind the driver and reprobe */
++		intf->needs_binding = 1;
++		dev_warn(&intf->dev, "no %s for driver %s?\n",
++				"suspend", driver->name);
+ 		mark_quiesced(intf);
+ 	}
+ 
+@@ -878,10 +976,12 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
+ 		goto done;
+ 
+ 	/* Can't resume it if it doesn't have a driver. */
+-	if (intf->condition == USB_INTERFACE_UNBOUND) {
+-		status = -ENOTCONN;
++	if (intf->condition == USB_INTERFACE_UNBOUND)
++		goto done;
++
++	/* Don't resume if the interface is marked for rebinding */
++	if (intf->needs_binding)
+ 		goto done;
+-	}
+ 	driver = to_usb_driver(intf->dev.driver);
+ 
+ 	if (reset_resume) {
+@@ -891,7 +991,7 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
+ 				dev_err(&intf->dev, "%s error %d\n",
+ 						"reset_resume", status);
+ 		} else {
+-			/* status = -EOPNOTSUPP; */
++			intf->needs_binding = 1;
+ 			dev_warn(&intf->dev, "no %s for driver %s?\n",
+ 					"reset_resume", driver->name);
+ 		}
+@@ -902,7 +1002,7 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
+ 				dev_err(&intf->dev, "%s error %d\n",
+ 						"resume", status);
+ 		} else {
+-			/* status = -EOPNOTSUPP; */
++			intf->needs_binding = 1;
+ 			dev_warn(&intf->dev, "no %s for driver %s?\n",
+ 					"resume", driver->name);
+ 		}
+@@ -910,11 +1010,10 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
+ 
+ done:
+ 	dev_vdbg(&intf->dev, "%s: status %d\n", __func__, status);
+-	if (status == 0)
++	if (status == 0 && intf->condition == USB_INTERFACE_BOUND)
+ 		mark_active(intf);
+ 
+-	/* FIXME: Unbind the driver and reprobe if the resume failed
+-	 * (not possible if auto_pm is set) */
++	/* Later we will unbind the driver and/or reprobe, if necessary */
+ 	return status;
+ }
+ 
+@@ -1470,6 +1569,7 @@ int usb_external_suspend_device(struct usb_device *udev, pm_message_t msg)
+ {
+ 	int	status;
+ 
++	do_unbind_rebind(udev, DO_UNBIND);
+ 	usb_pm_lock(udev);
+ 	udev->auto_pm = 0;
+ 	status = usb_suspend_both(udev, msg);
+@@ -1497,6 +1597,7 @@ int usb_external_resume_device(struct usb_device *udev)
+ 	status = usb_resume_both(udev);
+ 	udev->last_busy = jiffies;
+ 	usb_pm_unlock(udev);
++	do_unbind_rebind(udev, DO_REBIND);
+ 
+ 	/* Now that the device is awake, we can start trying to autosuspend
+ 	 * it again. */
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index bb3ecc4c08f2..f1efabbc1ca2 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -3367,6 +3367,11 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
+  * this from a driver probe() routine after downloading new firmware.
+  * For calls that might not occur during probe(), drivers should lock
+  * the device using usb_lock_device_for_reset().
++ *
++ * If an interface is currently being probed or disconnected, we assume
++ * its driver knows how to handle resets.  For all other interfaces,
++ * if the driver doesn't have pre_reset and post_reset methods then
++ * we attempt to unbind it and rebind afterward.
+  */
+ int usb_reset_device(struct usb_device *udev)
+ {
+@@ -3388,12 +3393,17 @@ int usb_reset_device(struct usb_device *udev)
+ 		for (i = 0; i < config->desc.bNumInterfaces; ++i) {
+ 			struct usb_interface *cintf = config->interface[i];
+ 			struct usb_driver *drv;
++			int unbind = 0;
+ 
+ 			if (cintf->dev.driver) {
+ 				drv = to_usb_driver(cintf->dev.driver);
+-				if (drv->pre_reset)
+-					(drv->pre_reset)(cintf);
+-	/* FIXME: Unbind if pre_reset returns an error or isn't defined */
++				if (drv->pre_reset && drv->post_reset)
++					unbind = (drv->pre_reset)(cintf);
++				else if (cintf->condition ==
++						USB_INTERFACE_BOUND)
++					unbind = 1;
++				if (unbind)
++					usb_forced_unbind_intf(cintf);
+ 			}
+ 		}
+ 	}
+@@ -3404,13 +3414,18 @@ int usb_reset_device(struct usb_device *udev)
+ 		for (i = config->desc.bNumInterfaces - 1; i >= 0; --i) {
+ 			struct usb_interface *cintf = config->interface[i];
+ 			struct usb_driver *drv;
++			int rebind = cintf->needs_binding;
+ 
+-			if (cintf->dev.driver) {
++			if (!rebind && cintf->dev.driver) {
+ 				drv = to_usb_driver(cintf->dev.driver);
+ 				if (drv->post_reset)
+-					(drv->post_reset)(cintf);
+-	/* FIXME: Unbind if post_reset returns an error or isn't defined */
++					rebind = (drv->post_reset)(cintf);
++				else if (cintf->condition ==
++						USB_INTERFACE_BOUND)
++					rebind = 1;
+ 			}
++			if (rebind)
++				usb_rebind_intf(cintf);
+ 		}
+ 	}
+ 
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 1a8bc21c335e..d3eb0a29bca1 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -29,6 +29,8 @@ extern int usb_choose_configuration(struct usb_device *udev);
+ extern void usb_kick_khubd(struct usb_device *dev);
+ extern int usb_match_device(struct usb_device *dev,
+ 			    const struct usb_device_id *id);
++extern void usb_forced_unbind_intf(struct usb_interface *intf);
++extern void usb_rebind_intf(struct usb_interface *intf);
+ 
+ extern int  usb_hub_init(void);
+ extern void usb_hub_cleanup(void);
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 3cc8db5254d1..5811c5da69f9 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -160,6 +160,7 @@ struct usb_interface {
+ 	unsigned is_active:1;		/* the interface is not suspended */
+ 	unsigned sysfs_files_created:1;	/* the sysfs attributes exist */
+ 	unsigned needs_remote_wakeup:1;	/* driver requires remote wakeup */
++	unsigned needs_binding:1;	/* needs delayed unbind/rebind */
+ 
+ 	struct device dev;		/* interface specific device info */
+ 	struct device *usb_dev;

commit 7c3e28bc56bd2e4310dc0af99f2b95eeda9a2ff7
+Author: Alan Stern 
+Date:   Mon Jun 16 12:11:39 2008 -0400
+
+    USB: use standard SG iterator in the scatter-gather library
+    
+    This patch (as1103) changes the iteration in the USB scatter-gather to
+    use a standard SG iterator.  Otherwise the iteration will fail if it
+    encounters a chained SG list.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Jens Axboe 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 315363b744a3..08af1083ebfc 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -400,7 +400,7 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
+ 	if (usb_pipein(pipe))
+ 		urb_flags |= URB_SHORT_NOT_OK;
+ 
+-	for (i = 0; i < io->entries; i++) {
++	for_each_sg(sg, sg, io->entries, i) {
+ 		unsigned len;
+ 
+ 		io->urbs[i] = usb_alloc_urb(0, mem_flags);
+@@ -434,17 +434,17 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
+ 		 * to prevent stale pointers and to help spot bugs.
+ 		 */
+ 		if (dma) {
+-			io->urbs[i]->transfer_dma = sg_dma_address(sg + i);
+-			len = sg_dma_len(sg + i);
++			io->urbs[i]->transfer_dma = sg_dma_address(sg);
++			len = sg_dma_len(sg);
+ #if defined(CONFIG_HIGHMEM) || defined(CONFIG_GART_IOMMU)
+ 			io->urbs[i]->transfer_buffer = NULL;
+ #else
+-			io->urbs[i]->transfer_buffer = sg_virt(&sg[i]);
++			io->urbs[i]->transfer_buffer = sg_virt(sg);
+ #endif
+ 		} else {
+ 			/* hc may use _only_ transfer_buffer */
+-			io->urbs[i]->transfer_buffer = sg_virt(&sg[i]);
+-			len = sg[i].length;
++			io->urbs[i]->transfer_buffer = sg_virt(sg);
++			len = sg->length;
+ 		}
+ 
+ 		if (length) {

commit f579c2b46f74038e8f5a762c7f10c2385b33e3dc
+Author: Alan Stern 
+Date:   Mon Jun 2 16:26:48 2008 -0400
+
+    USB Gadget: documentation update
+    
+    This patch (as1102) clarifies two points in the USB Gadget kerneldoc:
+    
+            Request completion callbacks are always made with interrupts
+            disabled;
+    
+            Device controllers may not support STALLing the status stage
+            of a control transfer after the data stage is over.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
+index 0ebedaec075d..0460a746480c 100644
+--- a/include/linux/usb/gadget.h
++++ b/include/linux/usb/gadget.h
+@@ -33,7 +33,8 @@ struct usb_ep;
+  * @short_not_ok: When reading data, makes short packets be
+  *     treated as errors (queue stops advancing till cleanup).
+  * @complete: Function called when request completes, so this request and
+- *	its buffer may be re-used.
++ *	its buffer may be re-used.  The function will always be called with
++ *	interrupts disabled, and it must not sleep.
+  *	Reads terminate with a short packet, or when the buffer fills,
+  *	whichever comes first.  When writes terminate, some data bytes
+  *	will usually still be in flight (often in a hardware fifo).
+@@ -271,7 +272,10 @@ static inline void usb_ep_free_request(struct usb_ep *ep,
+  * (Note that some USB device controllers disallow protocol stall responses
+  * in some cases.)  When control responses are deferred (the response is
+  * written after the setup callback returns), then usb_ep_set_halt() may be
+- * used on ep0 to trigger protocol stalls.
++ * used on ep0 to trigger protocol stalls.  Depending on the controller,
++ * it may not be possible to trigger a status-stage protocol stall when the
++ * data stage is over, that is, from within the response's completion
++ * routine.
+  *
+  * For periodic endpoints, like interrupt or isochronous ones, the usb host
+  * arranges to poll once per interval, and the gadget driver usually will

commit 543f7810fba2a62e412efa9473ad08167b691f09
+Author: Alan Stern 
+Date:   Thu May 8 11:55:59 2008 -0400
+
+    usb-storage: implement "soft" unbinding
+    
+    This patch (as1092) implements "soft" unbinding for usb-storage.  When
+    the disconnect routine is called, all commands and reset delays are
+    allowed to complete normally until after scsi_remove_host() returns.
+    This means that the commands needed for an orderly shutdown will be
+    sent through to the device.
+    
+    Unlike before, the driver will now execute every command that it
+    accepts.  Hence there's no need for special code to catch unexecuted
+    commands and fail them.
+    
+    The new sequence of events when disconnect runs goes as follows:
+    
+            If the device is truly unplugged, set the DISCONNECTING
+            flag so we won't try to access it any more.
+    
+            If the SCSI-scanning thread hasn't started up yet, prevent
+            it from doing anything by setting the new DONT_SCAN flag.
+            Then wake it up and wait for it to terminate.
+    
+            Remove the SCSI host.  This unbinds the upper-level drivers,
+            doing an orderly shutdown.  Commands sent to quiesce the
+            device will be transmitted normally, unless the device is
+            unplugged.
+    
+            Set the DISCONNECTING flag so that we won't accept any new
+            commands that might get submitted (there aren't supposed to be
+            any) and we won't try to access the device for resets.
+    
+            Tell the control thread to exit by waking it up with no
+            pending command, and wait for it to terminate.
+    
+            Go on to do all the other normal stuff: releasing resources,
+            freeing memory, and so on.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+index 2f88bb958bad..94138df557b9 100644
+--- a/drivers/usb/storage/transport.c
++++ b/drivers/usb/storage/transport.c
+@@ -127,8 +127,8 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)
+ 	long timeleft;
+ 	int status;
+ 
+-	/* don't submit URBs during abort/disconnect processing */
+-	if (us->dflags & ABORTING_OR_DISCONNECTING)
++	/* don't submit URBs during abort processing */
++	if (test_bit(US_FLIDX_ABORTING, &us->dflags))
+ 		return -EIO;
+ 
+ 	/* set up data structures for the wakeup system */
+@@ -161,8 +161,8 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)
+ 	 * to cancel it */
+ 	set_bit(US_FLIDX_URB_ACTIVE, &us->dflags);
+ 
+-	/* did an abort/disconnect occur during the submission? */
+-	if (us->dflags & ABORTING_OR_DISCONNECTING) {
++	/* did an abort occur during the submission? */
++	if (test_bit(US_FLIDX_ABORTING, &us->dflags)) {
+ 
+ 		/* cancel the URB, if it hasn't been cancelled already */
+ 		if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) {
+@@ -419,8 +419,8 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
+ {
+ 	int result;
+ 
+-	/* don't submit s-g requests during abort/disconnect processing */
+-	if (us->dflags & ABORTING_OR_DISCONNECTING)
++	/* don't submit s-g requests during abort processing */
++	if (test_bit(US_FLIDX_ABORTING, &us->dflags))
+ 		return USB_STOR_XFER_ERROR;
+ 
+ 	/* initialize the scatter-gather request block */
+@@ -437,8 +437,8 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
+ 	 * okay to cancel it */
+ 	set_bit(US_FLIDX_SG_ACTIVE, &us->dflags);
+ 
+-	/* did an abort/disconnect occur during the submission? */
+-	if (us->dflags & ABORTING_OR_DISCONNECTING) {
++	/* did an abort occur during the submission? */
++	if (test_bit(US_FLIDX_ABORTING, &us->dflags)) {
+ 
+ 		/* cancel the request, if it hasn't been cancelled already */
+ 		if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags)) {
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 6b14f8d253f1..6bfd99dd57aa 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -320,16 +320,17 @@ static int usb_stor_control_thread(void * __us)
+ 		/* lock the device pointers */
+ 		mutex_lock(&(us->dev_mutex));
+ 
+-		/* if the device has disconnected, we are free to exit */
+-		if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
+-			US_DEBUGP("-- exiting\n");
++		/* lock access to the state */
++		scsi_lock(host);
++
++		/* When we are called with no command pending, we're done */
++		if (us->srb == NULL) {
++			scsi_unlock(host);
+ 			mutex_unlock(&us->dev_mutex);
++			US_DEBUGP("-- exiting\n");
+ 			break;
+ 		}
+ 
+-		/* lock access to the state */
+-		scsi_lock(host);
+-
+ 		/* has the command timed out *already* ? */
+ 		if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
+ 			us->srb->result = DID_ABORT << 16;
+@@ -384,12 +385,8 @@ static int usb_stor_control_thread(void * __us)
+ 		/* lock access to the state */
+ 		scsi_lock(host);
+ 
+-		/* did the command already complete because of a disconnect? */
+-		if (!us->srb)
+-			;		/* nothing to do */
+-
+ 		/* indicate that the command is done */
+-		else if (us->srb->result != DID_ABORT << 16) {
++		if (us->srb->result != DID_ABORT << 16) {
+ 			US_DEBUGP("scsi cmd done, result=0x%x\n", 
+ 				   us->srb->result);
+ 			us->srb->scsi_done(us->srb);
+@@ -820,11 +817,10 @@ static void usb_stor_release_resources(struct us_data *us)
+ 	US_DEBUGP("-- %s\n", __func__);
+ 
+ 	/* Tell the control thread to exit.  The SCSI host must
+-	 * already have been removed so it won't try to queue
+-	 * any more commands.
++	 * already have been removed and the DISCONNECTING flag set
++	 * so that we won't accept any more commands.
+ 	 */
+ 	US_DEBUGP("-- sending exit command to thread\n");
+-	set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
+ 	complete(&us->cmnd_ready);
+ 	if (us->ctl_thread)
+ 		kthread_stop(us->ctl_thread);
+@@ -859,39 +855,36 @@ static void dissociate_dev(struct us_data *us)
+ 	usb_set_intfdata(us->pusb_intf, NULL);
+ }
+ 
+-/* First stage of disconnect processing: stop all commands and remove
+- * the host */
++/* First stage of disconnect processing: stop SCSI scanning,
++ * remove the host, and stop accepting new commands
++ */
+ static void quiesce_and_remove_host(struct us_data *us)
+ {
+ 	struct Scsi_Host *host = us_to_host(us);
+ 
+-	/* Prevent new USB transfers, stop the current command, and
+-	 * interrupt a SCSI-scan or device-reset delay */
+-	scsi_lock(host);
+-	set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
+-	scsi_unlock(host);
+-	usb_stor_stop_transport(us);
+-	wake_up(&us->delay_wait);
++	/* If the device is really gone, cut short reset delays */
++	if (us->pusb_dev->state == USB_STATE_NOTATTACHED)
++		set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
+ 
+-	/* queuecommand won't accept any new commands and the control
+-	 * thread won't execute a previously-queued command.  If there
+-	 * is such a command pending, complete it with an error. */
+-	mutex_lock(&us->dev_mutex);
+-	if (us->srb) {
+-		us->srb->result = DID_NO_CONNECT << 16;
+-		scsi_lock(host);
+-		us->srb->scsi_done(us->srb);
+-		us->srb = NULL;
+-		complete(&us->notify);		/* in case of an abort */
+-		scsi_unlock(host);
+-	}
+-	mutex_unlock(&us->dev_mutex);
++	/* Prevent SCSI-scanning (if it hasn't started yet)
++	 * and wait for the SCSI-scanning thread to stop.
++	 */
++	set_bit(US_FLIDX_DONT_SCAN, &us->dflags);
++	wake_up(&us->delay_wait);
++	wait_for_completion(&us->scanning_done);
+ 
+-	/* Now we own no commands so it's safe to remove the SCSI host */
++	/* Removing the host will perform an orderly shutdown: caches
++	 * synchronized, disks spun down, etc.
++	 */
+ 	scsi_remove_host(host);
+ 
+-	/* Wait for the SCSI-scanning thread to stop */
+-	wait_for_completion(&us->scanning_done);
++	/* Prevent any new commands from being accepted and cut short
++	 * reset delays.
++	 */
++	scsi_lock(host);
++	set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
++	scsi_unlock(host);
++	wake_up(&us->delay_wait);
+ }
+ 
+ /* Second stage of disconnect processing: deallocate all resources */
+@@ -919,12 +912,12 @@ static int usb_stor_scan_thread(void * __us)
+ 		printk(KERN_DEBUG "usb-storage: waiting for device "
+ 				"to settle before scanning\n");
+ 		wait_event_freezable_timeout(us->delay_wait,
+-				test_bit(US_FLIDX_DISCONNECTING, &us->dflags),
++				test_bit(US_FLIDX_DONT_SCAN, &us->dflags),
+ 				delay_use * HZ);
+ 	}
+ 
+ 	/* If the device is still connected, perform the scanning */
+-	if (!test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
++	if (!test_bit(US_FLIDX_DONT_SCAN, &us->dflags)) {
+ 
+ 		/* For bulk-only devices, determine the max LUN value */
+ 		if (us->protocol == US_PR_BULK &&
+@@ -1023,6 +1016,7 @@ static int storage_probe(struct usb_interface *intf,
+ 	if (IS_ERR(th)) {
+ 		printk(KERN_WARNING USB_STORAGE 
+ 		       "Unable to start the device-scanning thread\n");
++		complete(&us->scanning_done);
+ 		quiesce_and_remove_host(us);
+ 		result = PTR_ERR(th);
+ 		goto BadDevice;
+@@ -1065,6 +1059,7 @@ static struct usb_driver usb_storage_driver = {
+ 	.pre_reset =	storage_pre_reset,
+ 	.post_reset =	storage_post_reset,
+ 	.id_table =	storage_usb_ids,
++	.soft_unbind =	1,
+ };
+ 
+ static int __init usb_stor_init(void)
+diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
+index 8da96da5875d..47906dc620db 100644
+--- a/drivers/usb/storage/usb.h
++++ b/drivers/usb/storage/usb.h
+@@ -72,11 +72,9 @@ struct us_unusual_dev {
+ #define US_FLIDX_SG_ACTIVE	1	/* current_sg is in use     */
+ #define US_FLIDX_ABORTING	2	/* abort is in progress     */
+ #define US_FLIDX_DISCONNECTING	3	/* disconnect in progress   */
+-#define ABORTING_OR_DISCONNECTING	((1UL << US_FLIDX_ABORTING) | \
+-					 (1UL << US_FLIDX_DISCONNECTING))
+ #define US_FLIDX_RESETTING	4	/* device reset in progress */
+ #define US_FLIDX_TIMED_OUT	5	/* SCSI midlayer timed out  */
+-
++#define US_FLIDX_DONT_SCAN	6	/* don't scan (disconnect)  */
+ 
+ #define USB_STOR_STRING_LEN 32
+ 

commit 9da82bd4649334817ef0e752a69eb99051645dad
+Author: Alan Stern 
+Date:   Thu May 8 11:54:37 2008 -0400
+
+    USB: implement "soft" unbinding
+    
+    This patch (as1091) changes the way usbcore handles interface
+    unbinding.  If the interface's driver supports "soft" unbinding (a new
+    flag in the driver structure) then in-flight URBs are not cancelled
+    and endpoints are not disabled.  Instead the driver is allowed to
+    continue communicating with the device (although of course it should
+    stop before its disconnect routine returns).
+    
+    The purpose of this change is to allow drivers to do a clean shutdown
+    when they get unbound from a device that is still plugged in.  Killing
+    all the URBs and disabling the endpoints before calling the driver's
+    disconnect method doesn't give the driver any control over what
+    happens, and it can leave devices in indeterminate states.  For
+    example, when usb-storage unbinds it doesn't want to stop while in the
+    middle of transmitting a SCSI command.
+    
+    The soft_unbind flag is added because in the past, a number of drivers
+    have experienced problems related to ongoing I/O after their disconnect
+    routine returned.  Hence "soft" unbinding is made available only to
+    drivers that claim to support it.
+    
+    The patch also replaces "interface_to_usbdev(intf)" with "udev" in a
+    couple of places, a minor simplification.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 0a0e8cea0afc..8da1a56659be 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -257,15 +257,16 @@ static int usb_unbind_interface(struct device *dev)
+ 	udev = interface_to_usbdev(intf);
+ 	error = usb_autoresume_device(udev);
+ 
+-	/* release all urbs for this interface */
+-	usb_disable_interface(interface_to_usbdev(intf), intf);
++	/* Terminate all URBs for this interface unless the driver
++	 * supports "soft" unbinding.
++	 */
++	if (!driver->soft_unbind)
++		usb_disable_interface(udev, intf);
+ 
+ 	driver->disconnect(intf);
+ 
+ 	/* reset other interface state */
+-	usb_set_interface(interface_to_usbdev(intf),
+-			intf->altsetting[0].desc.bInterfaceNumber,
+-			0);
++	usb_set_interface(udev, intf->altsetting[0].desc.bInterfaceNumber, 0);
+ 	usb_set_intfdata(intf, NULL);
+ 
+ 	intf->condition = USB_INTERFACE_UNBOUND;
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index cee7fbb2b605..8429d08bd2fd 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -972,6 +972,8 @@ struct usbdrv_wrap {
+  *	added to this driver by preventing the sysfs file from being created.
+  * @supports_autosuspend: if set to 0, the USB core will not allow autosuspend
+  *	for interfaces bound to this driver.
++ * @soft_unbind: if set to 1, the USB core will not kill URBs and disable
++ *	endpoints before calling the driver's disconnect method.
+  *
+  * USB interface drivers must provide a name, probe() and disconnect()
+  * methods, and an id_table.  Other driver fields are optional.
+@@ -1012,6 +1014,7 @@ struct usb_driver {
+ 	struct usbdrv_wrap drvwrap;
+ 	unsigned int no_dynamic_id:1;
+ 	unsigned int supports_autosuspend:1;
++	unsigned int soft_unbind:1;
+ };
+ #define	to_usb_driver(d) container_of(d, struct usb_driver, drvwrap.driver)
+ 

commit 7119e3c37fbf7c27adb5929f344c826ecb8c7859
+Author: Alan Stern 
+Date:   Thu May 1 15:36:13 2008 -0400
+
+    usb-storage: change remaining semaphore to completion
+    
+    This patch (as1090) converts the one remaining semaphore in
+    usb-storage into a completion.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Matthew Dharm 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index 1caf3f7af349..043b60b2ad17 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -248,7 +248,7 @@ static int queuecommand(struct scsi_cmnd *srb,
+ 	/* enqueue the command and wake up the control thread */
+ 	srb->scsi_done = done;
+ 	us->srb = srb;
+-	up(&(us->sema));
++	complete(&us->cmnd_ready);
+ 
+ 	return 0;
+ }
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 78c0c7ee6b99..6b14f8d253f1 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -312,9 +312,9 @@ static int usb_stor_control_thread(void * __us)
+ 
+ 	for(;;) {
+ 		US_DEBUGP("*** thread sleeping.\n");
+-		if(down_interruptible(&us->sema))
++		if (wait_for_completion_interruptible(&us->cmnd_ready))
+ 			break;
+-			
++
+ 		US_DEBUGP("*** thread awakened.\n");
+ 
+ 		/* lock the device pointers */
+@@ -825,7 +825,7 @@ static void usb_stor_release_resources(struct us_data *us)
+ 	 */
+ 	US_DEBUGP("-- sending exit command to thread\n");
+ 	set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
+-	up(&us->sema);
++	complete(&us->cmnd_ready);
+ 	if (us->ctl_thread)
+ 		kthread_stop(us->ctl_thread);
+ 
+@@ -975,7 +975,7 @@ static int storage_probe(struct usb_interface *intf,
+ 	us = host_to_us(host);
+ 	memset(us, 0, sizeof(struct us_data));
+ 	mutex_init(&(us->dev_mutex));
+-	init_MUTEX_LOCKED(&(us->sema));
++	init_completion(&us->cmnd_ready);
+ 	init_completion(&(us->notify));
+ 	init_waitqueue_head(&us->delay_wait);
+ 	init_completion(&us->scanning_done);
+diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
+index b169132f021b..8da96da5875d 100644
+--- a/drivers/usb/storage/usb.h
++++ b/drivers/usb/storage/usb.h
+@@ -148,7 +148,7 @@ struct us_data {
+ 	struct task_struct	*ctl_thread;	 /* the control thread   */
+ 
+ 	/* mutual exclusion and synchronization structures */
+-	struct semaphore	sema;		 /* to sleep thread on	    */
++	struct completion	cmnd_ready;	 /* to sleep thread on	    */
+ 	struct completion	notify;		 /* thread begin/end	    */
+ 	wait_queue_head_t	delay_wait;	 /* wait during scan, reset */
+ 	struct completion	scanning_done;	 /* wait for scan thread    */

commit 7e4d6c387994294ac8198b624ee71e75de60dfd2
+Author: Alan Stern 
+Date:   Thu May 1 15:35:18 2008 -0400
+
+    usb-storage: separate dynamic flags from fixed flags
+    
+    This patch (as1089) separates out the dynamic atomic bitflags and the
+    static bitfields in usb-storage.  Until now the two sorts of flags
+    have been sharing the same word; this has always been awkward.
+    
+    To help prevent possible confusion, the two new fields each have a
+    different name from the original.  us->fflags contains the fixed
+    bitfields (mostly taken from the USB ID table in unusual_devs.h), and
+    us->dflags contains the dynamic atomic bitflags (used with set_bit,
+    test_bit, and so on).
+    
+    Signed-off-by: Alan Stern 
+    Cc: Matthew Dharm 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
+index 3addcd8f827b..a153335f3648 100644
+--- a/drivers/usb/storage/isd200.c
++++ b/drivers/usb/storage/isd200.c
+@@ -586,7 +586,7 @@ static void isd200_invoke_transport( struct us_data *us,
+ 	/* if the command gets aborted by the higher layers, we need to
+ 	 * short-circuit all other processing
+ 	 */
+-	if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
++	if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
+ 		US_DEBUGP("-- command was aborted\n");
+ 		goto Handle_Abort;
+ 	}
+@@ -633,7 +633,7 @@ static void isd200_invoke_transport( struct us_data *us,
+ 
+ 	if (need_auto_sense) {
+ 		result = isd200_read_regs(us);
+-		if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
++		if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
+ 			US_DEBUGP("-- auto-sense aborted\n");
+ 			goto Handle_Abort;
+ 		}
+@@ -663,7 +663,7 @@ static void isd200_invoke_transport( struct us_data *us,
+ 	srb->result = DID_ABORT << 16;
+ 
+ 	/* permit the reset transfer to take place */
+-	clear_bit(US_FLIDX_ABORTING, &us->flags);
++	clear_bit(US_FLIDX_ABORTING, &us->dflags);
+ 	/* Need reset here */
+ }
+ 
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index 3fcde9f0fa5f..1caf3f7af349 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -116,10 +116,10 @@ static int slave_configure(struct scsi_device *sdev)
+ 	 * while others have trouble with more than 64K. At this time we
+ 	 * are limiting both to 32K (64 sectores).
+ 	 */
+-	if (us->flags & (US_FL_MAX_SECTORS_64 | US_FL_MAX_SECTORS_MIN)) {
++	if (us->fflags & (US_FL_MAX_SECTORS_64 | US_FL_MAX_SECTORS_MIN)) {
+ 		unsigned int max_sectors = 64;
+ 
+-		if (us->flags & US_FL_MAX_SECTORS_MIN)
++		if (us->fflags & US_FL_MAX_SECTORS_MIN)
+ 			max_sectors = PAGE_CACHE_SIZE >> 9;
+ 		if (sdev->request_queue->max_sectors > max_sectors)
+ 			blk_queue_max_sectors(sdev->request_queue,
+@@ -148,7 +148,7 @@ static int slave_configure(struct scsi_device *sdev)
+ 		 * majority of devices work fine, but a few still can't
+ 		 * handle it.  The sd driver will simply assume those
+ 		 * devices are write-enabled. */
+-		if (us->flags & US_FL_NO_WP_DETECT)
++		if (us->fflags & US_FL_NO_WP_DETECT)
+ 			sdev->skip_ms_page_3f = 1;
+ 
+ 		/* A number of devices have problems with MODE SENSE for
+@@ -158,13 +158,13 @@ static int slave_configure(struct scsi_device *sdev)
+ 		/* Some disks return the total number of blocks in response
+ 		 * to READ CAPACITY rather than the highest block number.
+ 		 * If this device makes that mistake, tell the sd driver. */
+-		if (us->flags & US_FL_FIX_CAPACITY)
++		if (us->fflags & US_FL_FIX_CAPACITY)
+ 			sdev->fix_capacity = 1;
+ 
+ 		/* A few disks have two indistinguishable version, one of
+ 		 * which reports the correct capacity and the other does not.
+ 		 * The sd driver has to guess which is the case. */
+-		if (us->flags & US_FL_CAPACITY_HEURISTICS)
++		if (us->fflags & US_FL_CAPACITY_HEURISTICS)
+ 			sdev->guess_capacity = 1;
+ 
+ 		/* Some devices report a SCSI revision level above 2 but are
+@@ -213,7 +213,7 @@ static int slave_configure(struct scsi_device *sdev)
+ 
+ 	/* Some devices choke when they receive a PREVENT-ALLOW MEDIUM
+ 	 * REMOVAL command, so suppress those commands. */
+-	if (us->flags & US_FL_NOT_LOCKABLE)
++	if (us->fflags & US_FL_NOT_LOCKABLE)
+ 		sdev->lockable = 0;
+ 
+ 	/* this is to satisfy the compiler, tho I don't think the 
+@@ -238,7 +238,7 @@ static int queuecommand(struct scsi_cmnd *srb,
+ 	}
+ 
+ 	/* fail the command if we are disconnecting */
+-	if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
++	if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
+ 		US_DEBUGP("Fail command during disconnect\n");
+ 		srb->result = DID_NO_CONNECT << 16;
+ 		done(srb);
+@@ -280,9 +280,9 @@ static int command_abort(struct scsi_cmnd *srb)
+ 	 * with the reset).  Note that we must retain the host lock while
+ 	 * calling usb_stor_stop_transport(); otherwise it might interfere
+ 	 * with an auto-reset that begins as soon as we release the lock. */
+-	set_bit(US_FLIDX_TIMED_OUT, &us->flags);
+-	if (!test_bit(US_FLIDX_RESETTING, &us->flags)) {
+-		set_bit(US_FLIDX_ABORTING, &us->flags);
++	set_bit(US_FLIDX_TIMED_OUT, &us->dflags);
++	if (!test_bit(US_FLIDX_RESETTING, &us->dflags)) {
++		set_bit(US_FLIDX_ABORTING, &us->dflags);
+ 		usb_stor_stop_transport(us);
+ 	}
+ 	scsi_unlock(us_to_host(us));
+@@ -329,7 +329,7 @@ void usb_stor_report_device_reset(struct us_data *us)
+ 	struct Scsi_Host *host = us_to_host(us);
+ 
+ 	scsi_report_device_reset(host, 0, 0);
+-	if (us->flags & US_FL_SCM_MULT_TARG) {
++	if (us->fflags & US_FL_SCM_MULT_TARG) {
+ 		for (i = 1; i < host->max_id; ++i)
+ 			scsi_report_device_reset(host, 0, i);
+ 	}
+@@ -400,7 +400,7 @@ static int proc_info (struct Scsi_Host *host, char *buffer,
+ 		pos += sprintf(pos, "       Quirks:");
+ 
+ #define US_FLAG(name, value) \
+-	if (us->flags & value) pos += sprintf(pos, " " #name);
++	if (us->fflags & value) pos += sprintf(pos, " " #name);
+ US_DO_ALL_FLAGS
+ #undef US_FLAG
+ 
+diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+index 6610d2dd1e7f..2f88bb958bad 100644
+--- a/drivers/usb/storage/transport.c
++++ b/drivers/usb/storage/transport.c
+@@ -75,14 +75,14 @@
+  * by a separate code path.)
+  *
+  * The abort function (usb_storage_command_abort() in scsiglue.c) first
+- * sets the machine state and the ABORTING bit in us->flags to prevent
++ * sets the machine state and the ABORTING bit in us->dflags to prevent
+  * new URBs from being submitted.  It then calls usb_stor_stop_transport()
+- * below, which atomically tests-and-clears the URB_ACTIVE bit in us->flags
++ * below, which atomically tests-and-clears the URB_ACTIVE bit in us->dflags
+  * to see if the current_urb needs to be stopped.  Likewise, the SG_ACTIVE
+  * bit is tested to see if the current_sg scatter-gather request needs to be
+  * stopped.  The timeout callback routine does much the same thing.
+  *
+- * When a disconnect occurs, the DISCONNECTING bit in us->flags is set to
++ * When a disconnect occurs, the DISCONNECTING bit in us->dflags is set to
+  * prevent new URBs from being submitted, and usb_stor_stop_transport() is
+  * called to stop any ongoing requests.
+  *
+@@ -128,7 +128,7 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)
+ 	int status;
+ 
+ 	/* don't submit URBs during abort/disconnect processing */
+-	if (us->flags & ABORTING_OR_DISCONNECTING)
++	if (us->dflags & ABORTING_OR_DISCONNECTING)
+ 		return -EIO;
+ 
+ 	/* set up data structures for the wakeup system */
+@@ -159,13 +159,13 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)
+ 
+ 	/* since the URB has been submitted successfully, it's now okay
+ 	 * to cancel it */
+-	set_bit(US_FLIDX_URB_ACTIVE, &us->flags);
++	set_bit(US_FLIDX_URB_ACTIVE, &us->dflags);
+ 
+ 	/* did an abort/disconnect occur during the submission? */
+-	if (us->flags & ABORTING_OR_DISCONNECTING) {
++	if (us->dflags & ABORTING_OR_DISCONNECTING) {
+ 
+ 		/* cancel the URB, if it hasn't been cancelled already */
+-		if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->flags)) {
++		if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) {
+ 			US_DEBUGP("-- cancelling URB\n");
+ 			usb_unlink_urb(us->current_urb);
+ 		}
+@@ -175,7 +175,7 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)
+ 	timeleft = wait_for_completion_interruptible_timeout(
+ 			&urb_done, timeout ? : MAX_SCHEDULE_TIMEOUT);
+  
+-	clear_bit(US_FLIDX_URB_ACTIVE, &us->flags);
++	clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags);
+ 
+ 	if (timeleft <= 0) {
+ 		US_DEBUGP("%s -- cancelling URB\n",
+@@ -420,7 +420,7 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
+ 	int result;
+ 
+ 	/* don't submit s-g requests during abort/disconnect processing */
+-	if (us->flags & ABORTING_OR_DISCONNECTING)
++	if (us->dflags & ABORTING_OR_DISCONNECTING)
+ 		return USB_STOR_XFER_ERROR;
+ 
+ 	/* initialize the scatter-gather request block */
+@@ -435,13 +435,13 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
+ 
+ 	/* since the block has been initialized successfully, it's now
+ 	 * okay to cancel it */
+-	set_bit(US_FLIDX_SG_ACTIVE, &us->flags);
++	set_bit(US_FLIDX_SG_ACTIVE, &us->dflags);
+ 
+ 	/* did an abort/disconnect occur during the submission? */
+-	if (us->flags & ABORTING_OR_DISCONNECTING) {
++	if (us->dflags & ABORTING_OR_DISCONNECTING) {
+ 
+ 		/* cancel the request, if it hasn't been cancelled already */
+-		if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->flags)) {
++		if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags)) {
+ 			US_DEBUGP("-- cancelling sg request\n");
+ 			usb_sg_cancel(&us->current_sg);
+ 		}
+@@ -449,7 +449,7 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
+ 
+ 	/* wait for the completion of the transfer */
+ 	usb_sg_wait(&us->current_sg);
+-	clear_bit(US_FLIDX_SG_ACTIVE, &us->flags);
++	clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags);
+ 
+ 	result = us->current_sg.status;
+ 	if (act_len)
+@@ -530,7 +530,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 	/* if the command gets aborted by the higher layers, we need to
+ 	 * short-circuit all other processing
+ 	 */
+-	if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
++	if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
+ 		US_DEBUGP("-- command was aborted\n");
+ 		srb->result = DID_ABORT << 16;
+ 		goto Handle_Errors;
+@@ -616,7 +616,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 		/* let's clean up right away */
+ 		scsi_eh_restore_cmnd(srb, &ses);
+ 
+-		if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
++		if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
+ 			US_DEBUGP("-- auto-sense aborted\n");
+ 			srb->result = DID_ABORT << 16;
+ 			goto Handle_Errors;
+@@ -629,7 +629,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 			 * auto-sense is perfectly valid
+ 			 */
+ 			srb->result = DID_ERROR << 16;
+-			if (!(us->flags & US_FL_SCM_MULT_TARG))
++			if (!(us->fflags & US_FL_SCM_MULT_TARG))
+ 				goto Handle_Errors;
+ 			return;
+ 		}
+@@ -679,8 +679,8 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 	/* Set the RESETTING bit, and clear the ABORTING bit so that
+ 	 * the reset may proceed. */
+ 	scsi_lock(us_to_host(us));
+-	set_bit(US_FLIDX_RESETTING, &us->flags);
+-	clear_bit(US_FLIDX_ABORTING, &us->flags);
++	set_bit(US_FLIDX_RESETTING, &us->dflags);
++	clear_bit(US_FLIDX_ABORTING, &us->dflags);
+ 	scsi_unlock(us_to_host(us));
+ 
+ 	/* We must release the device lock because the pre_reset routine
+@@ -695,7 +695,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 		scsi_unlock(us_to_host(us));
+ 		us->transport_reset(us);
+ 	}
+-	clear_bit(US_FLIDX_RESETTING, &us->flags);
++	clear_bit(US_FLIDX_RESETTING, &us->dflags);
+ }
+ 
+ /* Stop the current URB transfer */
+@@ -707,13 +707,13 @@ void usb_stor_stop_transport(struct us_data *us)
+ 	 * let's wake it up.  The test_and_clear_bit() call
+ 	 * guarantees that if a URB has just been submitted,
+ 	 * it won't be cancelled more than once. */
+-	if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->flags)) {
++	if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) {
+ 		US_DEBUGP("-- cancelling URB\n");
+ 		usb_unlink_urb(us->current_urb);
+ 	}
+ 
+ 	/* If we are waiting for a scatter-gather operation, cancel it. */
+-	if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->flags)) {
++	if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags)) {
+ 		US_DEBUGP("-- cancelling sg request\n");
+ 		usb_sg_cancel(&us->current_sg);
+ 	}
+@@ -914,7 +914,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 	unsigned int cbwlen = US_BULK_CB_WRAP_LEN;
+ 
+ 	/* Take care of BULK32 devices; set extra byte to 0 */
+-	if ( unlikely(us->flags & US_FL_BULK32)) {
++	if (unlikely(us->fflags & US_FL_BULK32)) {
+ 		cbwlen = 32;
+ 		us->iobuf[31] = 0;
+ 	}
+@@ -925,7 +925,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 	bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ? 1 << 7 : 0;
+ 	bcb->Tag = ++us->tag;
+ 	bcb->Lun = srb->device->lun;
+-	if (us->flags & US_FL_SCM_MULT_TARG)
++	if (us->fflags & US_FL_SCM_MULT_TARG)
+ 		bcb->Lun |= srb->device->id << 4;
+ 	bcb->Length = srb->cmd_len;
+ 
+@@ -951,7 +951,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 	/* Some USB-IDE converter chips need a 100us delay between the
+ 	 * command phase and the data phase.  Some devices need a little
+ 	 * more than that, probably because of clock rate inaccuracies. */
+-	if (unlikely(us->flags & US_FL_GO_SLOW))
++	if (unlikely(us->fflags & US_FL_GO_SLOW))
+ 		udelay(125);
+ 
+ 	if (transfer_length) {
+@@ -1010,7 +1010,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 	US_DEBUGP("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",
+ 			le32_to_cpu(bcs->Signature), bcs->Tag, 
+ 			residue, bcs->Status);
+-	if (!(bcs->Tag == us->tag || (us->flags & US_FL_BULK_IGNORE_TAG)) ||
++	if (!(bcs->Tag == us->tag || (us->fflags & US_FL_BULK_IGNORE_TAG)) ||
+ 		bcs->Status > US_BULK_STAT_PHASE) {
+ 		US_DEBUGP("Bulk logical error\n");
+ 		return USB_STOR_TRANSPORT_ERROR;
+@@ -1035,7 +1035,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 	/* try to compute the actual residue, based on how much data
+ 	 * was really transferred and what the device tells us */
+ 	if (residue) {
+-		if (!(us->flags & US_FL_IGNORE_RESIDUE)) {
++		if (!(us->fflags & US_FL_IGNORE_RESIDUE)) {
+ 			residue = min(residue, transfer_length);
+ 			scsi_set_resid(srb, max(scsi_get_resid(srb),
+ 			                                       (int) residue));
+@@ -1090,7 +1090,7 @@ static int usb_stor_reset_common(struct us_data *us,
+ 	int result;
+ 	int result2;
+ 
+-	if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
++	if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
+ 		US_DEBUGP("No reset during disconnect\n");
+ 		return -EIO;
+ 	}
+@@ -1103,12 +1103,12 @@ static int usb_stor_reset_common(struct us_data *us,
+ 		return result;
+ 	}
+ 
+- 	/* Give the device some time to recover from the reset,
+- 	 * but don't delay disconnect processing. */
+- 	wait_event_interruptible_timeout(us->delay_wait,
+- 			test_bit(US_FLIDX_DISCONNECTING, &us->flags),
+- 			HZ*6);
+-	if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
++	/* Give the device some time to recover from the reset,
++	 * but don't delay disconnect processing. */
++	wait_event_interruptible_timeout(us->delay_wait,
++			test_bit(US_FLIDX_DISCONNECTING, &us->dflags),
++			HZ*6);
++	if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
+ 		US_DEBUGP("Reset interrupted by disconnect\n");
+ 		return -EIO;
+ 	}
+@@ -1170,7 +1170,7 @@ int usb_stor_port_reset(struct us_data *us)
+ 		US_DEBUGP("unable to lock device for reset: %d\n", result);
+ 	else {
+ 		/* Were we disconnected while waiting for the lock? */
+-		if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
++		if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
+ 			result = -EIO;
+ 			US_DEBUGP("No reset during disconnect\n");
+ 		} else {
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index e268aacb773a..78c0c7ee6b99 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -321,7 +321,7 @@ static int usb_stor_control_thread(void * __us)
+ 		mutex_lock(&(us->dev_mutex));
+ 
+ 		/* if the device has disconnected, we are free to exit */
+-		if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
++		if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
+ 			US_DEBUGP("-- exiting\n");
+ 			mutex_unlock(&us->dev_mutex);
+ 			break;
+@@ -331,7 +331,7 @@ static int usb_stor_control_thread(void * __us)
+ 		scsi_lock(host);
+ 
+ 		/* has the command timed out *already* ? */
+-		if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
++		if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
+ 			us->srb->result = DID_ABORT << 16;
+ 			goto SkipForAbort;
+ 		}
+@@ -350,7 +350,7 @@ static int usb_stor_control_thread(void * __us)
+ 		 * the maximum known LUN
+ 		 */
+ 		else if (us->srb->device->id && 
+-				!(us->flags & US_FL_SCM_MULT_TARG)) {
++				!(us->fflags & US_FL_SCM_MULT_TARG)) {
+ 			US_DEBUGP("Bad target number (%d:%d)\n",
+ 				  us->srb->device->id, us->srb->device->lun);
+ 			us->srb->result = DID_BAD_TARGET << 16;
+@@ -365,7 +365,7 @@ static int usb_stor_control_thread(void * __us)
+ 		/* Handle those devices which need us to fake 
+ 		 * their inquiry data */
+ 		else if ((us->srb->cmnd[0] == INQUIRY) &&
+-			    (us->flags & US_FL_FIX_INQUIRY)) {
++			    (us->fflags & US_FL_FIX_INQUIRY)) {
+ 			unsigned char data_ptr[36] = {
+ 			    0x00, 0x80, 0x02, 0x02,
+ 			    0x1F, 0x00, 0x00, 0x00};
+@@ -403,12 +403,12 @@ static int usb_stor_control_thread(void * __us)
+ 		 * the TIMED_OUT flag, not srb->result == DID_ABORT, because
+ 		 * the timeout might have occurred after the command had
+ 		 * already completed with a different result code. */
+-		if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
++		if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
+ 			complete(&(us->notify));
+ 
+ 			/* Allow USB transfers to resume */
+-			clear_bit(US_FLIDX_ABORTING, &us->flags);
+-			clear_bit(US_FLIDX_TIMED_OUT, &us->flags);
++			clear_bit(US_FLIDX_ABORTING, &us->dflags);
++			clear_bit(US_FLIDX_TIMED_OUT, &us->dflags);
+ 		}
+ 
+ 		/* finished working on this command */
+@@ -500,9 +500,9 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id)
+ 	us->protocol = (unusual_dev->useTransport == US_PR_DEVICE) ?
+ 			idesc->bInterfaceProtocol :
+ 			unusual_dev->useTransport;
+-	us->flags = USB_US_ORIG_FLAGS(id->driver_info);
++	us->fflags = USB_US_ORIG_FLAGS(id->driver_info);
+ 
+-	if (us->flags & US_FL_IGNORE_DEVICE) {
++	if (us->fflags & US_FL_IGNORE_DEVICE) {
+ 		printk(KERN_INFO USB_STORAGE "device ignored\n");
+ 		return -ENODEV;
+ 	}
+@@ -512,7 +512,7 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id)
+ 	 * disable it if we're in full-speed
+ 	 */
+ 	if (dev->speed != USB_SPEED_HIGH)
+-		us->flags &= ~US_FL_GO_SLOW;
++		us->fflags &= ~US_FL_GO_SLOW;
+ 
+ 	/* Log a message if a non-generic unusual_dev entry contains an
+ 	 * unnecessary subclass or protocol override.  This may stimulate
+@@ -533,7 +533,7 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id)
+ 		if (unusual_dev->useTransport != US_PR_DEVICE &&
+ 			us->protocol == idesc->bInterfaceProtocol)
+ 			msg += 2;
+-		if (msg >= 0 && !(us->flags & US_FL_NEED_OVERRIDE))
++		if (msg >= 0 && !(us->fflags & US_FL_NEED_OVERRIDE))
+ 			printk(KERN_NOTICE USB_STORAGE "This device "
+ 				"(%04x,%04x,%04x S %02x P %02x)"
+ 				" has %s in unusual_devs.h (kernel"
+@@ -663,7 +663,7 @@ static int get_transport(struct us_data *us)
+ 	US_DEBUGP("Transport: %s\n", us->transport_name);
+ 
+ 	/* fix for single-lun devices */
+-	if (us->flags & US_FL_SINGLE_LUN)
++	if (us->fflags & US_FL_SINGLE_LUN)
+ 		us->max_lun = 0;
+ 	return 0;
+ }
+@@ -824,7 +824,7 @@ static void usb_stor_release_resources(struct us_data *us)
+ 	 * any more commands.
+ 	 */
+ 	US_DEBUGP("-- sending exit command to thread\n");
+-	set_bit(US_FLIDX_DISCONNECTING, &us->flags);
++	set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
+ 	up(&us->sema);
+ 	if (us->ctl_thread)
+ 		kthread_stop(us->ctl_thread);
+@@ -868,7 +868,7 @@ static void quiesce_and_remove_host(struct us_data *us)
+ 	/* Prevent new USB transfers, stop the current command, and
+ 	 * interrupt a SCSI-scan or device-reset delay */
+ 	scsi_lock(host);
+-	set_bit(US_FLIDX_DISCONNECTING, &us->flags);
++	set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
+ 	scsi_unlock(host);
+ 	usb_stor_stop_transport(us);
+ 	wake_up(&us->delay_wait);
+@@ -919,16 +919,16 @@ static int usb_stor_scan_thread(void * __us)
+ 		printk(KERN_DEBUG "usb-storage: waiting for device "
+ 				"to settle before scanning\n");
+ 		wait_event_freezable_timeout(us->delay_wait,
+-				test_bit(US_FLIDX_DISCONNECTING, &us->flags),
++				test_bit(US_FLIDX_DISCONNECTING, &us->dflags),
+ 				delay_use * HZ);
+ 	}
+ 
+ 	/* If the device is still connected, perform the scanning */
+-	if (!test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
++	if (!test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
+ 
+ 		/* For bulk-only devices, determine the max LUN value */
+ 		if (us->protocol == US_PR_BULK &&
+-				!(us->flags & US_FL_SINGLE_LUN)) {
++				!(us->fflags & US_FL_SINGLE_LUN)) {
+ 			mutex_lock(&us->dev_mutex);
+ 			us->max_lun = usb_stor_Bulk_max_lun(us);
+ 			mutex_unlock(&us->dev_mutex);
+diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
+index 8d87503e2560..b169132f021b 100644
+--- a/drivers/usb/storage/usb.h
++++ b/drivers/usb/storage/usb.h
+@@ -67,15 +67,15 @@ struct us_unusual_dev {
+ };
+ 
+ 
+-/* Dynamic flag definitions: used in set_bit() etc. */
+-#define US_FLIDX_URB_ACTIVE	18  /* 0x00040000  current_urb is in use  */
+-#define US_FLIDX_SG_ACTIVE	19  /* 0x00080000  current_sg is in use   */
+-#define US_FLIDX_ABORTING	20  /* 0x00100000  abort is in progress   */
+-#define US_FLIDX_DISCONNECTING	21  /* 0x00200000  disconnect in progress */
++/* Dynamic bitflag definitions (us->dflags): used in set_bit() etc. */
++#define US_FLIDX_URB_ACTIVE	0	/* current_urb is in use    */
++#define US_FLIDX_SG_ACTIVE	1	/* current_sg is in use     */
++#define US_FLIDX_ABORTING	2	/* abort is in progress     */
++#define US_FLIDX_DISCONNECTING	3	/* disconnect in progress   */
+ #define ABORTING_OR_DISCONNECTING	((1UL << US_FLIDX_ABORTING) | \
+ 					 (1UL << US_FLIDX_DISCONNECTING))
+-#define US_FLIDX_RESETTING	22  /* 0x00400000  device reset in progress */
+-#define US_FLIDX_TIMED_OUT	23  /* 0x00800000  SCSI midlayer timed out  */
++#define US_FLIDX_RESETTING	4	/* device reset in progress */
++#define US_FLIDX_TIMED_OUT	5	/* SCSI midlayer timed out  */
+ 
+ 
+ #define USB_STOR_STRING_LEN 32
+@@ -109,7 +109,8 @@ struct us_data {
+ 	struct usb_device	*pusb_dev;	 /* this usb_device */
+ 	struct usb_interface	*pusb_intf;	 /* this interface */
+ 	struct us_unusual_dev   *unusual_dev;	 /* device-filter entry     */
+-	unsigned long		flags;		 /* from filter initially */
++	unsigned long		fflags;		 /* fixed flags from filter */
++	unsigned long		dflags;		 /* dynamic atomic bitflags */
+ 	unsigned int		send_bulk_pipe;	 /* cached pipe values */
+ 	unsigned int		recv_bulk_pipe;
+ 	unsigned int		send_ctrl_pipe;

commit 4330354f7660828d97834598633054b413f6264d
+Author: Alan Stern 
+Date:   Mon Apr 28 11:07:31 2008 -0400
+
+    USB: combine hub_quiesce and hub_stop
+    
+    This patch (as1083) combines hub_quiesce() and hub_stop() into a
+    single routine.  There's no point keeping them separate since they are
+    usually called together.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 4c629a036aed..e678ed8bd8c2 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -538,19 +538,6 @@ static void hub_power_on(struct usb_hub *hub)
+ 	msleep(max(pgood_delay, (unsigned) 100));
+ }
+ 
+-static void hub_quiesce(struct usb_hub *hub)
+-{
+-	/* (nonblocking) khubd and related activity won't re-trigger */
+-	hub->quiescing = 1;
+-
+-	/* (blocking) stop khubd and related activity */
+-	usb_kill_urb(hub->urb);
+-	if (hub->has_indicators)
+-		cancel_delayed_work_sync(&hub->leds);
+-	if (hub->tt.hub)
+-		cancel_work_sync(&hub->tt.kevent);
+-}
+-
+ static int hub_hub_status(struct usb_hub *hub,
+ 		u16 *status, u16 *change)
+ {
+@@ -609,20 +596,6 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
+  	kick_khubd(hub);
+ }
+ 
+-/* caller has locked the hub device */
+-static void hub_stop(struct usb_hub *hub)
+-{
+-	struct usb_device *hdev = hub->hdev;
+-	int i;
+-
+-	/* Disconnect all the children */
+-	for (i = 0; i < hdev->maxchild; ++i) {
+-		if (hdev->children[i])
+-			usb_disconnect(&hdev->children[i]);
+-	}
+-	hub_quiesce(hub);
+-}
+-
+ enum hub_activation_type {
+ 	HUB_INIT, HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME
+ };
+@@ -732,12 +705,40 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ 	kick_khubd(hub);
+ }
+ 
++enum hub_quiescing_type {
++	HUB_DISCONNECT, HUB_PRE_RESET, HUB_SUSPEND
++};
++
++static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
++{
++	struct usb_device *hdev = hub->hdev;
++	int i;
++
++	/* khubd and related activity won't re-trigger */
++	hub->quiescing = 1;
++
++	if (type != HUB_SUSPEND) {
++		/* Disconnect all the children */
++		for (i = 0; i < hdev->maxchild; ++i) {
++			if (hdev->children[i])
++				usb_disconnect(&hdev->children[i]);
++		}
++	}
++
++	/* Stop khubd and related activity */
++	usb_kill_urb(hub->urb);
++	if (hub->has_indicators)
++		cancel_delayed_work_sync(&hub->leds);
++	if (hub->tt.hub)
++		cancel_work_sync(&hub->tt.kevent);
++}
++
+ /* caller has locked the hub device */
+ static int hub_pre_reset(struct usb_interface *intf)
+ {
+ 	struct usb_hub *hub = usb_get_intfdata(intf);
+ 
+-	hub_stop(hub);
++	hub_quiesce(hub, HUB_PRE_RESET);
+ 	return 0;
+ }
+ 
+@@ -1024,7 +1025,7 @@ static void hub_disconnect(struct usb_interface *intf)
+ 
+ 	/* Disconnect all children and quiesce the hub */
+ 	hub->error = 0;
+-	hub_stop(hub);
++	hub_quiesce(hub, HUB_DISCONNECT);
+ 
+ 	usb_set_intfdata (intf, NULL);
+ 
+@@ -2167,7 +2168,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+ 	dev_dbg(&intf->dev, "%s\n", __func__);
+ 
+ 	/* stop khubd and related activity */
+-	hub_quiesce(hub);
++	hub_quiesce(hub, HUB_SUSPEND);
+ 	return 0;
+ }
+ 
+@@ -2914,7 +2915,7 @@ static void hub_events(void)
+ 		/* If the hub has died, clean up after it */
+ 		if (hdev->state == USB_STATE_NOTATTACHED) {
+ 			hub->error = -ENODEV;
+-			hub_stop(hub);
++			hub_quiesce(hub, HUB_DISCONNECT);
+ 			goto loop;
+ 		}
+ 

commit f2835219ed5e29ec959a0e635af4339d6174b2a7
+Author: Alan Stern 
+Date:   Mon Apr 28 11:07:17 2008 -0400
+
+    USB: combine hub_activate and hub_restart
+    
+    This patch (as1071) combines hub_activate() and hub_restart() into a
+    single routine.  There's no point keeping them separate, since they
+    are always called together.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index bc80168957b8..4c629a036aed 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -551,22 +551,6 @@ static void hub_quiesce(struct usb_hub *hub)
+ 		cancel_work_sync(&hub->tt.kevent);
+ }
+ 
+-static void hub_activate(struct usb_hub *hub)
+-{
+-	int	status;
+-
+-	hub->quiescing = 0;
+-
+-	status = usb_submit_urb(hub->urb, GFP_NOIO);
+-	if (status < 0)
+-		dev_err(hub->intfdev, "activate --> %d\n", status);
+-	if (hub->has_indicators && blinkenlights)
+-		schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD);
+-
+-	/* scan all ports ASAP */
+-	kick_khubd(hub);
+-}
+-
+ static int hub_hub_status(struct usb_hub *hub,
+ 		u16 *status, u16 *change)
+ {
+@@ -643,18 +627,24 @@ enum hub_activation_type {
+ 	HUB_INIT, HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME
+ };
+ 
+-static void hub_restart(struct usb_hub *hub, enum hub_activation_type type)
++static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ {
+ 	struct usb_device *hdev = hub->hdev;
+ 	int port1;
++	int status;
+ 	bool need_debounce_delay = false;
+ 
++	/* After a resume, port power should still be on.
++	 * For any other type of activation, turn it on.
++	 */
++	if (type != HUB_RESUME)
++		hub_power_on(hub);
++
+ 	/* Check each port and set hub->change_bits to let khubd know
+ 	 * which ports need attention.
+ 	 */
+ 	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
+ 		struct usb_device *udev = hdev->children[port1-1];
+-		int status;
+ 		u16 portstatus, portchange;
+ 
+ 		portstatus = portchange = 0;
+@@ -729,7 +719,17 @@ static void hub_restart(struct usb_hub *hub, enum hub_activation_type type)
+ 	 */
+ 	if (need_debounce_delay)
+ 		msleep(HUB_DEBOUNCE_STABLE);
+-	hub_activate(hub);
++
++	hub->quiescing = 0;
++
++	status = usb_submit_urb(hub->urb, GFP_NOIO);
++	if (status < 0)
++		dev_err(hub->intfdev, "activate --> %d\n", status);
++	if (hub->has_indicators && blinkenlights)
++		schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD);
++
++	/* Scan all ports that need attention */
++	kick_khubd(hub);
+ }
+ 
+ /* caller has locked the hub device */
+@@ -746,8 +746,7 @@ static int hub_post_reset(struct usb_interface *intf)
+ {
+ 	struct usb_hub *hub = usb_get_intfdata(intf);
+ 
+-	hub_power_on(hub);
+-	hub_restart(hub, HUB_POST_RESET);
++	hub_activate(hub, HUB_POST_RESET);
+ 	return 0;
+ }
+ 
+@@ -993,8 +992,7 @@ static int hub_configure(struct usb_hub *hub,
+ 	if (hub->has_indicators && blinkenlights)
+ 		hub->indicator [0] = INDICATOR_CYCLE;
+ 
+-	hub_power_on(hub);
+-	hub_activate(hub);
++	hub_activate(hub, HUB_INIT);
+ 	return 0;
+ 
+ fail:
+@@ -2178,7 +2176,7 @@ static int hub_resume(struct usb_interface *intf)
+ 	struct usb_hub *hub = usb_get_intfdata(intf);
+ 
+ 	dev_dbg(&intf->dev, "%s\n", __func__);
+-	hub_restart(hub, HUB_RESUME);
++	hub_activate(hub, HUB_RESUME);
+ 	return 0;
+ }
+ 
+@@ -2187,8 +2185,7 @@ static int hub_reset_resume(struct usb_interface *intf)
+ 	struct usb_hub *hub = usb_get_intfdata(intf);
+ 
+ 	dev_dbg(&intf->dev, "%s\n", __func__);
+-	hub_power_on(hub);
+-	hub_restart(hub, HUB_RESET_RESUME);
++	hub_activate(hub, HUB_RESET_RESUME);
+ 	return 0;
+ }
+ 

commit 948fea37dcebfef8f0f2faf00930e7ec7e756e07
+Author: Alan Stern 
+Date:   Mon Apr 28 11:07:07 2008 -0400
+
+    USB: optimize port debouncing during hub activation
+    
+    This patch (as1082) makes a small optimization to the way the hub
+    driver carries out port debouncing immediately after a hub is
+    activated (i.e., initialized, reset, or resumed).  If any port-change
+    statuses are observed, the code will delay for a minimal debounce
+    period -- thereby making a good start at debouncing all the ports at
+    once.
+    
+    If this wasn't sufficient then khubd will debounce any port that still
+    requires attention.  But in most cases it should suffice; it's rare
+    for a device to need more than a minimal debounce delay.  (In the
+    cases of hub initialization or reset even that is most likely not
+    needed, since any devices plugged in at such times have probably been
+    attached for a while.)
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 8ea095e59099..bc80168957b8 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -130,6 +130,10 @@ MODULE_PARM_DESC(use_both_schemes,
+ DECLARE_RWSEM(ehci_cf_port_reset_rwsem);
+ EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem);
+ 
++#define HUB_DEBOUNCE_TIMEOUT	1500
++#define HUB_DEBOUNCE_STEP	  25
++#define HUB_DEBOUNCE_STABLE	 100
++
+ 
+ static inline char *portspeed(int portstatus)
+ {
+@@ -643,6 +647,7 @@ static void hub_restart(struct usb_hub *hub, enum hub_activation_type type)
+ {
+ 	struct usb_device *hdev = hub->hdev;
+ 	int port1;
++	bool need_debounce_delay = false;
+ 
+ 	/* Check each port and set hub->change_bits to let khubd know
+ 	 * which ports need attention.
+@@ -673,6 +678,18 @@ static void hub_restart(struct usb_hub *hub, enum hub_activation_type type)
+ 			portstatus &= ~USB_PORT_STAT_ENABLE;
+ 		}
+ 
++		/* Clear status-change flags; we'll debounce later */
++		if (portchange & USB_PORT_STAT_C_CONNECTION) {
++			need_debounce_delay = true;
++			clear_port_feature(hub->hdev, port1,
++					USB_PORT_FEAT_C_CONNECTION);
++		}
++		if (portchange & USB_PORT_STAT_C_ENABLE) {
++			need_debounce_delay = true;
++			clear_port_feature(hub->hdev, port1,
++					USB_PORT_FEAT_C_ENABLE);
++		}
++
+ 		if (!udev || udev->state == USB_STATE_NOTATTACHED) {
+ 			/* Tell khubd to disconnect the device or
+ 			 * check for a new connection
+@@ -702,6 +719,16 @@ static void hub_restart(struct usb_hub *hub, enum hub_activation_type type)
+ 		}
+ 	}
+ 
++	/* If no port-status-change flags were set, we don't need any
++	 * debouncing.  If flags were set we can try to debounce the
++	 * ports all at once right now, instead of letting khubd do them
++	 * one at a time later on.
++	 *
++	 * If any port-status changes do occur during this delay, khubd
++	 * will see them later and handle them normally.
++	 */
++	if (need_debounce_delay)
++		msleep(HUB_DEBOUNCE_STABLE);
+ 	hub_activate(hub);
+ }
+ 
+@@ -2211,11 +2238,6 @@ static inline int remote_wakeup(struct usb_device *udev)
+  * every 25ms for transient disconnects.  When the port status has been
+  * unchanged for 100ms it returns the port status.
+  */
+-
+-#define HUB_DEBOUNCE_TIMEOUT	1500
+-#define HUB_DEBOUNCE_STEP	  25
+-#define HUB_DEBOUNCE_STABLE	 100
+-
+ static int hub_port_debounce(struct usb_hub *hub, int port1)
+ {
+ 	int ret;

commit 8808f00c7adfc8dc0b797c34ec03490b237fce4e
+Author: Alan Stern 
+Date:   Mon Apr 28 11:06:55 2008 -0400
+
+    USB: try to salvage lost power sessions
+    
+    This patch (as1073) adds to khubd a way to recover from power-session
+    interruption caused by transient connect-change or enable-change
+    events.  After the debouncing period, khubd attempts to do a
+    USB-Persist-style reset or reset-resume.  If it works, the connection
+    will remain unscathed.
+    
+    The upshot is that we will be more immune to noise caused by EMI.  The
+    grace period is on the order of 100 ms, so this won't permit recovery
+    from the "accidentally knocked the USB cable out of its socket" type
+    of event, but it's a start.
+    
+    As an added bonus, if a device was suspended when the system goes to
+    sleep then we no longer need to check for power-session interruptions
+    when the system wakes up.  Khubd will naturally see the status change
+    while processing the device's parent hub and will do the right thing.
+    
+    The remote_wakeup() routine is changed; now it expects the caller to
+    acquire the device lock rather than acquiring the lock itself.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index bf1585b203ca..0a0e8cea0afc 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1537,14 +1537,11 @@ static int usb_resume(struct device *dev)
+ 	udev = to_usb_device(dev);
+ 
+ 	/* If udev->skip_sys_resume is set then udev was already suspended
+-	 * when the system suspend started, so we don't want to resume
+-	 * udev during this system wakeup.  However a reset-resume counts
+-	 * as a wakeup event, so allow a reset-resume to occur if remote
+-	 * wakeup is enabled. */
+-	if (udev->skip_sys_resume) {
+-		if (!(udev->reset_resume && udev->do_remote_wakeup))
+-			return -EHOSTUNREACH;
+-	}
++	 * when the system sleep started, so we don't want to resume it
++	 * during this system wakeup.
++	 */
++	if (udev->skip_sys_resume)
++		return 0;
+ 	return usb_external_resume_device(udev);
+ }
+ 
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 054a76dc5d5b..8ea095e59099 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -690,18 +690,11 @@ static void hub_restart(struct usb_hub *hub, enum hub_activation_type type)
+ 				set_bit(port1, hub->change_bits);
+ 
+ 		} else if (udev->persist_enabled) {
+-			/* Turn off the status changes to prevent khubd
+-			 * from disconnecting the device.
+-			 */
+-			if (portchange & USB_PORT_STAT_C_ENABLE)
+-				clear_port_feature(hub->hdev, port1,
+-						USB_PORT_FEAT_C_ENABLE);
+-			if (portchange & USB_PORT_STAT_C_CONNECTION)
+-				clear_port_feature(hub->hdev, port1,
+-						USB_PORT_FEAT_C_CONNECTION);
+ #ifdef CONFIG_PM
+ 			udev->reset_resume = 1;
+ #endif
++			set_bit(port1, hub->change_bits);
++
+ 		} else {
+ 			/* The power session is gone; tell khubd */
+ 			usb_set_device_state(udev, USB_STATE_NOTATTACHED);
+@@ -2075,17 +2068,16 @@ int usb_port_resume(struct usb_device *udev)
+ 	return status;
+ }
+ 
++/* caller has locked udev */
+ static int remote_wakeup(struct usb_device *udev)
+ {
+ 	int	status = 0;
+ 
+-	usb_lock_device(udev);
+ 	if (udev->state == USB_STATE_SUSPENDED) {
+ 		dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-");
+ 		usb_mark_last_busy(udev);
+ 		status = usb_external_resume_device(udev);
+ 	}
+-	usb_unlock_device(udev);
+ 	return status;
+ }
+ 
+@@ -2632,6 +2624,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 	struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
+ 	unsigned wHubCharacteristics =
+ 			le16_to_cpu(hub->descriptor->wHubCharacteristics);
++	struct usb_device *udev;
+ 	int status, i;
+ 
+ 	dev_dbg (hub_dev,
+@@ -2666,8 +2659,45 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 		}
+ 	}
+ 
++	/* Try to resuscitate an existing device */
++	udev = hdev->children[port1-1];
++	if ((portstatus & USB_PORT_STAT_CONNECTION) && udev &&
++			udev->state != USB_STATE_NOTATTACHED) {
++
++		usb_lock_device(udev);
++		if (portstatus & USB_PORT_STAT_ENABLE) {
++			status = 0;		/* Nothing to do */
++		} else if (!udev->persist_enabled) {
++			status = -ENODEV;	/* Mustn't resuscitate */
++
++#ifdef CONFIG_USB_SUSPEND
++		} else if (udev->state == USB_STATE_SUSPENDED) {
++			/* For a suspended device, treat this as a
++			 * remote wakeup event.
++			 */
++			if (udev->do_remote_wakeup)
++				status = remote_wakeup(udev);
++
++			/* Otherwise leave it be; devices can't tell the
++			 * difference between suspended and disabled.
++			 */
++			else
++				status = 0;
++#endif
++
++		} else {
++			status = usb_reset_composite_device(udev, NULL);
++		}
++		usb_unlock_device(udev);
++
++		if (status == 0) {
++			clear_bit(port1, hub->change_bits);
++			return;
++		}
++	}
++
+ 	/* Disconnect any existing devices under this port */
+-	if (hdev->children[port1-1])
++	if (udev)
+ 		usb_disconnect(&hdev->children[port1-1]);
+ 	clear_bit(port1, hub->change_bits);
+ 
+@@ -2685,7 +2715,6 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 	}
+ 
+ 	for (i = 0; i < SET_CONFIG_TRIES; i++) {
+-		struct usb_device *udev;
+ 
+ 		/* reallocate for each attempt, since references
+ 		 * to the previous one can escape in various ways
+@@ -2944,11 +2973,16 @@ static void hub_events(void)
+ 			}
+ 
+ 			if (portchange & USB_PORT_STAT_C_SUSPEND) {
++				struct usb_device *udev;
++
+ 				clear_port_feature(hdev, i,
+ 					USB_PORT_FEAT_C_SUSPEND);
+-				if (hdev->children[i-1]) {
++				udev = hdev->children[i-1];
++				if (udev) {
++					usb_lock_device(udev);
+ 					ret = remote_wakeup(hdev->
+ 							children[i-1]);
++					usb_unlock_device(udev);
+ 					if (ret < 0)
+ 						connect_change = 1;
+ 				} else {

commit 6ee0b270c733027b2b716b1c80b9aced41e08d20
+Author: Alan Stern 
+Date:   Mon Apr 28 11:06:42 2008 -0400
+
+    USB: simplify hub_restart() logic
+    
+    This patch (as1081) straightens out the logic of the hub_restart()
+    routine.  Each port of the hub is scanned and the driver makes sure
+    that ports which are supposed to be disabled really _are_ disabled.
+    Any ports with a significant change in status are flagged in
+    hub->change_bits, so that khubd can focus on them without the need to
+    scan all the ports a second time -- which means the hub->activating
+    flag is no longer needed.
+    
+    Also, it is now recognized explicitly that the only reason for
+    resuming a port which was not suspended is to carry out a reset-resume
+    operation, which happens only in a non-CONFIG_USB_SUSPEND setting.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index d0b37d776afe..bf1585b203ca 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -805,8 +805,6 @@ static int usb_resume_device(struct usb_device *udev)
+ 
+ 	if (udev->state == USB_STATE_NOTATTACHED)
+ 		goto done;
+-	if (udev->state != USB_STATE_SUSPENDED && !udev->reset_resume)
+-		goto done;
+ 
+ 	/* Can't resume it if it doesn't have a driver. */
+ 	if (udev->dev.driver == NULL) {
+@@ -1173,11 +1171,8 @@ static int usb_resume_both(struct usb_device *udev)
+ 			 * then we're stuck. */
+ 			status = usb_resume_device(udev);
+ 		}
+-	} else {
+-
+-		/* Needed for reset-resume */
++	} else if (udev->reset_resume)
+ 		status = usb_resume_device(udev);
+-	}
+ 
+ 	if (status == 0 && udev->actconfig) {
+ 		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 976da1c4919b..054a76dc5d5b 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -72,7 +72,6 @@ struct usb_hub {
+ 
+ 	unsigned		limited_power:1;
+ 	unsigned		quiescing:1;
+-	unsigned		activating:1;
+ 	unsigned		disconnected:1;
+ 
+ 	unsigned		has_indicators:1;
+@@ -539,7 +538,6 @@ static void hub_quiesce(struct usb_hub *hub)
+ {
+ 	/* (nonblocking) khubd and related activity won't re-trigger */
+ 	hub->quiescing = 1;
+-	hub->activating = 0;
+ 
+ 	/* (blocking) stop khubd and related activity */
+ 	usb_kill_urb(hub->urb);
+@@ -554,7 +552,6 @@ static void hub_activate(struct usb_hub *hub)
+ 	int	status;
+ 
+ 	hub->quiescing = 0;
+-	hub->activating = 1;
+ 
+ 	status = usb_submit_urb(hub->urb, GFP_NOIO);
+ 	if (status < 0)
+@@ -638,81 +635,83 @@ static void hub_stop(struct usb_hub *hub)
+ 	hub_quiesce(hub);
+ }
+ 
+-#define HUB_RESET		1
+-#define HUB_RESUME		2
+-#define HUB_RESET_RESUME	3
+-
+-#ifdef CONFIG_PM
++enum hub_activation_type {
++	HUB_INIT, HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME
++};
+ 
+-static void hub_restart(struct usb_hub *hub, int type)
++static void hub_restart(struct usb_hub *hub, enum hub_activation_type type)
+ {
+ 	struct usb_device *hdev = hub->hdev;
+ 	int port1;
+ 
+-	/* Check each of the children to see if they require
+-	 * USB-PERSIST handling or disconnection.  Also check
+-	 * each unoccupied port to make sure it is still disabled.
++	/* Check each port and set hub->change_bits to let khubd know
++	 * which ports need attention.
+ 	 */
+ 	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
+ 		struct usb_device *udev = hdev->children[port1-1];
+-		int status = 0;
++		int status;
+ 		u16 portstatus, portchange;
+ 
+-		if (!udev || udev->state == USB_STATE_NOTATTACHED) {
+-			if (type != HUB_RESET) {
+-				status = hub_port_status(hub, port1,
+-						&portstatus, &portchange);
+-				if (status == 0 && (portstatus &
+-						USB_PORT_STAT_ENABLE))
+-					clear_port_feature(hdev, port1,
+-							USB_PORT_FEAT_ENABLE);
+-			}
+-			continue;
++		portstatus = portchange = 0;
++		status = hub_port_status(hub, port1, &portstatus, &portchange);
++		if (udev || (portstatus & USB_PORT_STAT_CONNECTION))
++			dev_dbg(hub->intfdev,
++					"port %d: status %04x change %04x\n",
++					port1, portstatus, portchange);
++
++		/* After anything other than HUB_RESUME (i.e., initialization
++		 * or any sort of reset), every port should be disabled.
++		 * Unconnected ports should likewise be disabled (paranoia),
++		 * and so should ports for which we have no usb_device.
++		 */
++		if ((portstatus & USB_PORT_STAT_ENABLE) && (
++				type != HUB_RESUME ||
++				!(portstatus & USB_PORT_STAT_CONNECTION) ||
++				!udev ||
++				udev->state == USB_STATE_NOTATTACHED)) {
++			clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
++			portstatus &= ~USB_PORT_STAT_ENABLE;
+ 		}
+ 
+-		/* Was the power session lost while we were suspended? */
+-		switch (type) {
+-		case HUB_RESET_RESUME:
+-			portstatus = 0;
+-			portchange = USB_PORT_STAT_C_CONNECTION;
+-			break;
+-
+-		case HUB_RESET:
+-		case HUB_RESUME:
+-			status = hub_port_status(hub, port1,
+-					&portstatus, &portchange);
+-			break;
+-		}
++		if (!udev || udev->state == USB_STATE_NOTATTACHED) {
++			/* Tell khubd to disconnect the device or
++			 * check for a new connection
++			 */
++			if (udev || (portstatus & USB_PORT_STAT_CONNECTION))
++				set_bit(port1, hub->change_bits);
++
++		} else if (portstatus & USB_PORT_STAT_ENABLE) {
++			/* The power session apparently survived the resume.
++			 * If there was an overcurrent or suspend change
++			 * (i.e., remote wakeup request), have khubd
++			 * take care of it.
++			 */
++			if (portchange)
++				set_bit(port1, hub->change_bits);
+ 
+-		/* For "USB_PERSIST"-enabled children we must
+-		 * mark the child device for reset-resume and
+-		 * turn off the various status changes to prevent
+-		 * khubd from disconnecting it later.
+-		 */
+-		if (udev->persist_enabled && status == 0 &&
+-				!(portstatus & USB_PORT_STAT_ENABLE)) {
++		} else if (udev->persist_enabled) {
++			/* Turn off the status changes to prevent khubd
++			 * from disconnecting the device.
++			 */
+ 			if (portchange & USB_PORT_STAT_C_ENABLE)
+ 				clear_port_feature(hub->hdev, port1,
+ 						USB_PORT_FEAT_C_ENABLE);
+ 			if (portchange & USB_PORT_STAT_C_CONNECTION)
+ 				clear_port_feature(hub->hdev, port1,
+ 						USB_PORT_FEAT_C_CONNECTION);
++#ifdef CONFIG_PM
+ 			udev->reset_resume = 1;
++#endif
++		} else {
++			/* The power session is gone; tell khubd */
++			usb_set_device_state(udev, USB_STATE_NOTATTACHED);
++			set_bit(port1, hub->change_bits);
+ 		}
+-
+-		/* Otherwise for a reset_resume we must disconnect the child,
+-		 * but as we may not lock the child device here
+-		 * we have to do a "logical" disconnect.
+-		 */
+-		else if (type == HUB_RESET_RESUME)
+-			hub_port_logical_disconnect(hub, port1);
+ 	}
+ 
+ 	hub_activate(hub);
+ }
+ 
+-#endif	/* CONFIG_PM */
+-
+ /* caller has locked the hub device */
+ static int hub_pre_reset(struct usb_interface *intf)
+ {
+@@ -728,7 +727,7 @@ static int hub_post_reset(struct usb_interface *intf)
+ 	struct usb_hub *hub = usb_get_intfdata(intf);
+ 
+ 	hub_power_on(hub);
+-	hub_activate(hub);
++	hub_restart(hub, HUB_POST_RESET);
+ 	return 0;
+ }
+ 
+@@ -2903,7 +2902,7 @@ static void hub_events(void)
+ 				continue;
+ 			connect_change = test_bit(i, hub->change_bits);
+ 			if (!test_and_clear_bit(i, hub->event_bits) &&
+-					!connect_change && !hub->activating)
++					!connect_change)
+ 				continue;
+ 
+ 			ret = hub_port_status(hub, i,
+@@ -2911,11 +2910,6 @@ static void hub_events(void)
+ 			if (ret < 0)
+ 				continue;
+ 
+-			if (hub->activating && !hdev->children[i-1] &&
+-					(portstatus &
+-						USB_PORT_STAT_CONNECTION))
+-				connect_change = 1;
+-
+ 			if (portchange & USB_PORT_STAT_C_CONNECTION) {
+ 				clear_port_feature(hdev, i,
+ 					USB_PORT_FEAT_C_CONNECTION);
+@@ -3011,8 +3005,6 @@ static void hub_events(void)
+ 			}
+ 		}
+ 
+-		hub->activating = 0;
+-
+ 		/* If this is a root hub, tell the HCD it's okay to
+ 		 * re-enable port-change interrupts now. */
+ 		if (!hdev->parent && !hub->busy_bits[0])

commit 24618b0cd42f936cda461bdf6144670a5c925178
+Author: Alan Stern 
+Date:   Mon Apr 28 11:06:28 2008 -0400
+
+    USB: debounce before unregistering
+    
+    This patch (as1080) makes a significant change to the way khubd
+    handles port connect-change and enable-change events.  Both types of
+    event are now debounced, and the debouncing is carried out _before_ an
+    existing usb_device is unregistered, instead of afterward.
+    
+    This means that drivers will have to deal with longer runs of errors
+    when a device is unplugged, but they are supposed to be prepared for
+    that in any case.
+    
+    The advantage is that when an enable-change occurs (caused for example
+    by electromagnetic interference), the debouncing period will provide
+    time for the cause of the problem to die away.  A simple port reset
+    (added in a forthcoming patch) will then allow us to recover from the
+    fault.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index d14da2123eb5..d741b9457427 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2673,9 +2673,10 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 	struct usb_device *hdev = hub->hdev;
+ 	struct device *hub_dev = hub->intfdev;
+ 	struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
+-	u16 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
++	unsigned wHubCharacteristics =
++			le16_to_cpu(hub->descriptor->wHubCharacteristics);
+ 	int status, i;
+- 
++
+ 	dev_dbg (hub_dev,
+ 		"port %d, status %04x, change %04x, %s\n",
+ 		port1, portstatus, portchange, portspeed (portstatus));
+@@ -2684,30 +2685,36 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 		set_port_led(hub, port1, HUB_LED_AUTO);
+ 		hub->indicator[port1-1] = INDICATOR_AUTO;
+ 	}
+- 
+-	/* Disconnect any existing devices under this port */
+-	if (hdev->children[port1-1])
+-		usb_disconnect(&hdev->children[port1-1]);
+-	clear_bit(port1, hub->change_bits);
+ 
+ #ifdef	CONFIG_USB_OTG
+ 	/* during HNP, don't repeat the debounce */
+ 	if (hdev->bus->is_b_host)
+-		portchange &= ~USB_PORT_STAT_C_CONNECTION;
++		portchange &= ~(USB_PORT_STAT_C_CONNECTION |
++				USB_PORT_STAT_C_ENABLE);
+ #endif
+ 
+-	if (portchange & USB_PORT_STAT_C_CONNECTION) {
++	/* Try to use the debounce delay for protection against
++	 * port-enable changes caused, for example, by EMI.
++	 */
++	if (portchange & (USB_PORT_STAT_C_CONNECTION |
++				USB_PORT_STAT_C_ENABLE)) {
+ 		status = hub_port_debounce(hub, port1);
+ 		if (status < 0) {
+ 			if (printk_ratelimit())
+ 				dev_err (hub_dev, "connect-debounce failed, "
+ 						"port %d disabled\n", port1);
+-			goto done;
++			portstatus &= ~USB_PORT_STAT_CONNECTION;
++		} else {
++			portstatus = status;
+ 		}
+-		portstatus = status;
+ 	}
+ 
+-	/* Return now if nothing is connected */
++	/* Disconnect any existing devices under this port */
++	if (hdev->children[port1-1])
++		usb_disconnect(&hdev->children[port1-1]);
++	clear_bit(port1, hub->change_bits);
++
++	/* Return now if debouncing failed or nothing is connected */
+ 	if (!(portstatus & USB_PORT_STAT_CONNECTION)) {
+ 
+ 		/* maybe switch power back on (e.g. root hub was reset) */

commit b01b03f3ad82b4293f6ca4da9b2692b6a377c609
+Author: Alan Stern 
+Date:   Mon Apr 28 11:06:11 2008 -0400
+
+    USB: add new routine for checking port-resume type
+    
+    This patch (as1070) creates a new subroutine to check whether a device
+    can be resumed.  This code is needed even when CONFIG_USB_SUSPEND
+    isn't set, because devices do suspend themselves when the root hub
+    (and hence the entire bus) is suspended, and power sessions can get
+    lost during a system sleep even without individual port suspends.
+    
+    The patch also fixes a loose end in USB-Persist reset-resume handling.
+    When a low- or full-speed device is attached to an EHCI's companion
+    controller, the port handoff during resume will cause the companion
+    port's connect-status-change feature to be set.  If that flag isn't
+    cleared, the port-reset code will think it indicates that the device
+    has been unplugged and the reset-resume will fail.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 2a5c2833de38..d14da2123eb5 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1821,6 +1821,45 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
+ 
+ #ifdef	CONFIG_PM
+ 
++#define MASK_BITS	(USB_PORT_STAT_POWER | USB_PORT_STAT_CONNECTION | \
++				USB_PORT_STAT_SUSPEND)
++#define WANT_BITS	(USB_PORT_STAT_POWER | USB_PORT_STAT_CONNECTION)
++
++/* Determine whether the device on a port is ready for a normal resume,
++ * is ready for a reset-resume, or should be disconnected.
++ */
++static int check_port_resume_type(struct usb_device *udev,
++		struct usb_hub *hub, int port1,
++		int status, unsigned portchange, unsigned portstatus)
++{
++	/* Is the device still present? */
++	if (status || (portstatus & MASK_BITS) != WANT_BITS) {
++		if (status >= 0)
++			status = -ENODEV;
++	}
++
++	/* Can't do a normal resume if the port isn't enabled */
++	else if (!(portstatus & USB_PORT_STAT_ENABLE) && !udev->reset_resume)
++		status = -ENODEV;
++
++	if (status) {
++		dev_dbg(hub->intfdev,
++				"port %d status %04x.%04x after resume, %d\n",
++				port1, portchange, portstatus, status);
++	} else if (udev->reset_resume) {
++
++		/* Late port handoff can set status-change bits */
++		if (portchange & USB_PORT_STAT_C_CONNECTION)
++			clear_port_feature(hub->hdev, port1,
++					USB_PORT_FEAT_C_CONNECTION);
++		if (portchange & USB_PORT_STAT_C_ENABLE)
++			clear_port_feature(hub->hdev, port1,
++					USB_PORT_FEAT_C_ENABLE);
++	}
++
++	return status;
++}
++
+ #ifdef	CONFIG_USB_SUSPEND
+ 
+ /*
+@@ -2025,7 +2064,6 @@ int usb_port_resume(struct usb_device *udev)
+ 	int		port1 = udev->portnum;
+ 	int		status;
+ 	u16		portchange, portstatus;
+-	unsigned	mask_flags, want_flags;
+ 
+ 	/* Skip the initial Clear-Suspend step for a remote wakeup */
+ 	status = hub_port_status(hub, port1, &portstatus, &portchange);
+@@ -2054,35 +2092,23 @@ int usb_port_resume(struct usb_device *udev)
+ 		 */
+ 		status = hub_port_status(hub, port1, &portstatus, &portchange);
+ 
+- SuspendCleared:
+-		if (udev->reset_resume)
+-			want_flags = USB_PORT_STAT_POWER
+-					| USB_PORT_STAT_CONNECTION;
+-		else
+-			want_flags = USB_PORT_STAT_POWER
+-					| USB_PORT_STAT_CONNECTION
+-					| USB_PORT_STAT_ENABLE;
+-		mask_flags = want_flags | USB_PORT_STAT_SUSPEND;
++		/* TRSMRCY = 10 msec */
++		msleep(10);
++	}
+ 
+-		if (status < 0 || (portstatus & mask_flags) != want_flags) {
+-			dev_dbg(hub->intfdev,
+-				"port %d status %04x.%04x after resume, %d\n",
+-				port1, portchange, portstatus, status);
+-			if (status >= 0)
+-				status = -ENODEV;
+-		} else {
+-			if (portchange & USB_PORT_STAT_C_SUSPEND)
+-				clear_port_feature(hub->hdev, port1,
+-						USB_PORT_FEAT_C_SUSPEND);
+-			/* TRSMRCY = 10 msec */
+-			msleep(10);
+-		}
++ SuspendCleared:
++	if (status == 0) {
++		if (portchange & USB_PORT_STAT_C_SUSPEND)
++			clear_port_feature(hub->hdev, port1,
++					USB_PORT_FEAT_C_SUSPEND);
+ 	}
+ 
+ 	clear_bit(port1, hub->busy_bits);
+ 	if (!hub->hdev->parent && !hub->busy_bits[0])
+ 		usb_enable_root_hub_irq(hub->hdev->bus);
+ 
++	status = check_port_resume_type(udev,
++			hub, port1, status, portchange, portstatus);
+ 	if (status == 0)
+ 		status = finish_port_resume(udev);
+ 	if (status < 0) {
+@@ -2115,12 +2141,23 @@ int usb_port_suspend(struct usb_device *udev)
+ 	return 0;
+ }
+ 
++/* However we may need to do a reset-resume */
++
+ int usb_port_resume(struct usb_device *udev)
+ {
+-	int status = 0;
++	struct usb_hub	*hub = hdev_to_hub(udev->parent);
++	int		port1 = udev->portnum;
++	int		status;
++	u16		portchange, portstatus;
+ 
+-	/* However we may need to do a reset-resume */
+-	if (udev->reset_resume) {
++	status = hub_port_status(hub, port1, &portstatus, &portchange);
++	status = check_port_resume_type(udev,
++			hub, port1, status, portchange, portstatus);
++
++	if (status) {
++		dev_dbg(&udev->dev, "can't resume, status %d\n", status);
++		hub_port_logical_disconnect(hub, port1);
++	} else if (udev->reset_resume) {
+ 		dev_dbg(&udev->dev, "reset-resume\n");
+ 		status = usb_reset_device(udev);
+ 	}

commit bdb2b8cab4392ce41ddfbd6773a3da3334daf836
+Author: Alan Stern 
+Date:   Tue Jun 24 14:03:14 2008 -0400
+
+    [SCSI] erase invalid data returned by device
+    
+    This patch (as1108) fixes a problem that can occur with certain USB
+    mass-storage devices: They return invalid data together with a residue
+    indicating that the data should be ignored.  Rather than leave the
+    invalid data in a transfer buffer, where it can get misinterpreted,
+    the patch clears the invalid portion of the buffer.
+    
+    This solves a problem (wrong write-protect setting detected) reported
+    by Maciej Rutecki and Peter Teoh.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Peter Teoh 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index a82d2fe80fb5..cbf55d59a54c 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -207,6 +207,15 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
+ 	 */
+ 	blk_execute_rq(req->q, NULL, req, 1);
+ 
++	/*
++	 * Some devices (USB mass-storage in particular) may transfer
++	 * garbage data together with a residue indicating that the data
++	 * is invalid.  Prevent the garbage from being misinterpreted
++	 * and prevent security leaks by zeroing out the excess data.
++	 */
++	if (unlikely(req->data_len > 0 && req->data_len <= bufflen))
++		memset(buffer + (bufflen - req->data_len), 0, req->data_len);
++
+ 	ret = req->errors;
+  out:
+ 	blk_put_request(req);

commit 1236edf1c70107a0d31b3fba0b2a8783615d0d24
+Author: Alan Stern 
+Date:   Tue Jul 1 10:45:51 2008 -0400
+
+    USB: don't lose disconnections during suspend
+    
+    This patch (as1111) fixes a bug in the hub driver.  When a hub
+    resumes, disconnections that occurred while the hub was suspended are
+    lost.
+    
+    A completely different fix for this problem has already been accepted
+    for 2.6.27; however the problem still needs to be handled in 2.6.26.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Lukas Hejtmanek 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 94789be54ca3..512d2d57d41e 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -713,18 +713,11 @@ static void hub_restart(struct usb_hub *hub, int type)
+ 		}
+ 
+ 		/* Was the power session lost while we were suspended? */
+-		switch (type) {
+-		case HUB_RESET_RESUME:
+-			portstatus = 0;
+-			portchange = USB_PORT_STAT_C_CONNECTION;
+-			break;
++		status = hub_port_status(hub, port1, &portstatus, &portchange);
+ 
+-		case HUB_RESET:
+-		case HUB_RESUME:
+-			status = hub_port_status(hub, port1,
+-					&portstatus, &portchange);
+-			break;
+-		}
++		/* If the device is gone, khubd will handle it later */
++		if (status == 0 && !(portstatus & USB_PORT_STAT_CONNECTION))
++			continue;
+ 
+ 		/* For "USB_PERSIST"-enabled children we must
+ 		 * mark the child device for reset-resume and

commit 19c4158bcdf42ee3b2394342caf14f8471d2c78e
+Author: Alan Stern 
+Date:   Fri Mar 7 11:20:25 2008 -0500
+
+    [SCSI] SCSI: remove dev->power.power_state from mesh driver
+    
+    power.power_state is scheduled for removal.  This patch (as1055)
+    removes all uses of that field from the SCSI mesh driver.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Paul Mackerras 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c
+index fd63b06d9ef1..11aa917629ac 100644
+--- a/drivers/scsi/mesh.c
++++ b/drivers/scsi/mesh.c
+@@ -1765,7 +1765,7 @@ static int mesh_suspend(struct macio_dev *mdev, pm_message_t mesg)
+ 	default:
+ 		return 0;
+ 	}
+-	if (mesg.event == mdev->ofdev.dev.power.power_state.event)
++	if (ms->phase == sleeping)
+ 		return 0;
+ 
+ 	scsi_block_requests(ms->host);
+@@ -1780,8 +1780,6 @@ static int mesh_suspend(struct macio_dev *mdev, pm_message_t mesg)
+ 	disable_irq(ms->meshintr);
+ 	set_mesh_power(ms, 0);
+ 
+-	mdev->ofdev.dev.power.power_state = mesg;
+-
+ 	return 0;
+ }
+ 
+@@ -1790,7 +1788,7 @@ static int mesh_resume(struct macio_dev *mdev)
+ 	struct mesh_state *ms = (struct mesh_state *)macio_get_drvdata(mdev);
+ 	unsigned long flags;
+ 
+-	if (mdev->ofdev.dev.power.power_state.event == PM_EVENT_ON)
++	if (ms->phase != sleeping)
+ 		return 0;
+ 
+ 	set_mesh_power(ms, 1);
+@@ -1801,8 +1799,6 @@ static int mesh_resume(struct macio_dev *mdev)
+ 	enable_irq(ms->meshintr);
+ 	scsi_unblock_requests(ms->host);
+ 
+-	mdev->ofdev.dev.power.power_state.event = PM_EVENT_ON;
+-
+ 	return 0;
+ }
+ 

commit c7257bd2ecb7b4cc42f9f152c7c059258d434169
+Author: Alan Stern 
+Date:   Wed May 21 13:53:01 2008 -0400
+
+    USB: usb-storage: unusual_devs update for Cypress ATACB
+    
+    This patch (as1101) updates the unusual_devs entry for the Cypress
+    ATACB pass-through.  The protocol field is changed from US_PR_BULK to
+    US_PR_DEVICE, since the Cypress devices already set bInterfaceProtocol
+    to Bulk-only.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 1b09578cbb10..5d56893fc1cc 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -405,7 +405,7 @@ UNUSUAL_DEV(  0x04a5, 0x3010, 0x0100, 0x0100,
+ UNUSUAL_DEV(  0x04b4, 0x6830, 0x0000, 0x9999,
+ 		"Cypress",
+ 		"Cypress AT2LP",
+-		US_SC_CYP_ATACB, US_PR_BULK, NULL,
++		US_SC_CYP_ATACB, US_PR_DEVICE, NULL,
+ 		0),
+ #endif
+ 

commit fa38dfcc56b5f6cce787f9aaa5d1830509213802
+Author: Alan Stern 
+Date:   Tue May 20 16:59:33 2008 -0400
+
+    USB: EHCI: fix performance regression
+    
+    This patch (as1099) fixes a performance regression in ehci-hcd.  The
+    fundamental problem is that queue headers get removed from the
+    schedule too quickly, since the code checks for a counter advancing
+    rather than making an actual time-based check.  The latency involved
+    in removing the queue header and then relinking it can severely
+    degrade certain kinds of workloads.
+    
+    The patch replaces a simple counter with a timestamp derived from the
+    controller's uframe value.  In addition, the delay for unlinking an
+    idle queue header is increased from 5 ms to 10 ms; since some
+    controllers (nVidia) have a latency of up to 1 ms for unlinking, this
+    reduces the relative impact from 20% to 10%.
+    
+    Finally, a logical error left over from the IAA watchdog-timer
+    conversion is corrected.  Now the driver will always either unlink an
+    idle queue header or set up a timer to unlink it later.  The old code
+    would sometimes fail to do either.
+    
+    Signed-off-by: Alan Stern 
+    Cc: David Brownell 
+    Cc: Leonid 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 369a8a5ea7bb..3e3c5d3ea0ad 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -84,7 +84,8 @@ static const char	hcd_name [] = "ehci_hcd";
+ #define EHCI_IAA_MSECS		10		/* arbitrary */
+ #define EHCI_IO_JIFFIES		(HZ/10)		/* io watchdog > irq_thresh */
+ #define EHCI_ASYNC_JIFFIES	(HZ/20)		/* async idle timeout */
+-#define EHCI_SHRINK_JIFFIES	(HZ/200)	/* async qh unlink delay */
++#define EHCI_SHRINK_JIFFIES	(HZ/100)	/* async qh unlink delay */
++#define EHCI_SHRINK_UFRAMES	(10*8)		/* same value in uframes */
+ 
+ /* Initial IRQ latency:  faster than hw default */
+ static int log2_irq_thresh = 0;		// 0 to 6
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index b85b54160cda..5200481deb27 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -1116,8 +1116,7 @@ static void scan_async (struct ehci_hcd *ehci)
+ 	struct ehci_qh		*qh;
+ 	enum ehci_timer_action	action = TIMER_IO_WATCHDOG;
+ 
+-	if (!++(ehci->stamp))
+-		ehci->stamp++;
++	ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index);
+ 	timer_action_done (ehci, TIMER_ASYNC_SHRINK);
+ rescan:
+ 	qh = ehci->async->qh_next.qh;
+@@ -1148,12 +1147,14 @@ static void scan_async (struct ehci_hcd *ehci)
+ 			 * doesn't stay idle for long.
+ 			 * (plus, avoids some kind of re-activation race.)
+ 			 */
+-			if (list_empty (&qh->qtd_list)) {
+-				if (qh->stamp == ehci->stamp)
++			if (list_empty(&qh->qtd_list) &&
++					qh->qh_state == QH_STATE_LINKED) {
++				if (!ehci->reclaim &&
++				    ((ehci->stamp - qh->stamp) & 8191) >=
++						EHCI_SHRINK_UFRAMES)
++					start_unlink_async(ehci, qh);
++				else
+ 					action = TIMER_ASYNC_SHRINK;
+-				else if (!ehci->reclaim
+-					    && qh->qh_state == QH_STATE_LINKED)
+-					start_unlink_async (ehci, qh);
+ 			}
+ 
+ 			qh = qh->qh_next.qh;

commit b40e43fcc532fa44a375a37d592e32cd0d50fe7a
+Author: Alan Stern 
+Date:   Tue May 20 16:59:10 2008 -0400
+
+    USB: EHCI: fix bug in Iso scheduling
+    
+    This patch (as1098) changes the way ehci-hcd schedules its periodic
+    Iso transfers.  That the current scheduling code is wrong is clear on
+    the face of it: Sometimes it returns -EL2NSYNC (meaning that an URB
+    couldn't be scheduled because it was submitted too late), but it does
+    this even when the URB_ISO_ASAP flag is set (meaning the URB should be
+    scheduled as soon as possible).
+    
+    The new code properly implements as-soon-as-possible scheduling,
+    assigning the next unexpired slot as the URB's starting point.  It
+    also is more careful about checking for Iso URB completion: It doesn't
+    bother to check for activity during frames that are already over,
+    and it allows for the possibility that some of the URB's packets may
+    have raced the hardware when they were submitted and so never got used
+    (the packet status is set to -EXDEV).
+    
+    This fixes problems several people have experienced with USB video
+    applications.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index be575e46eac3..b7853c8bac0f 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1349,18 +1349,27 @@ iso_stream_schedule (
+ 	/* when's the last uframe this urb could start? */
+ 	max = now + mod;
+ 
+-	/* typical case: reuse current schedule. stream is still active,
+-	 * and no gaps from host falling behind (irq delays etc)
++	/* Typical case: reuse current schedule, stream is still active.
++	 * Hopefully there are no gaps from the host falling behind
++	 * (irq delays etc), but if there are we'll take the next
++	 * slot in the schedule, implicitly assuming URB_ISO_ASAP.
+ 	 */
+ 	if (likely (!list_empty (&stream->td_list))) {
+ 		start = stream->next_uframe;
+ 		if (start < now)
+ 			start += mod;
+-		if (likely ((start + sched->span) < max))
+-			goto ready;
+-		/* else fell behind; someday, try to reschedule */
+-		status = -EL2NSYNC;
+-		goto fail;
++
++		/* Fell behind (by up to twice the slop amount)? */
++		if (start >= max - 2 * 8 * SCHEDULE_SLOP)
++			start += stream->interval * DIV_ROUND_UP(
++					max - start, stream->interval) - mod;
++
++		/* Tried to schedule too far into the future? */
++		if (unlikely((start + sched->span) >= max)) {
++			status = -EFBIG;
++			goto fail;
++		}
++		goto ready;
+ 	}
+ 
+ 	/* need to schedule; when's the next (u)frame we could start?
+@@ -1613,6 +1622,9 @@ itd_complete (
+ 		} else if (likely ((t & EHCI_ISOC_ACTIVE) == 0)) {
+ 			desc->status = 0;
+ 			desc->actual_length = EHCI_ITD_LENGTH (t);
++		} else {
++			/* URB was too late */
++			desc->status = -EXDEV;
+ 		}
+ 	}
+ 
+@@ -2095,7 +2107,7 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
+ static void
+ scan_periodic (struct ehci_hcd *ehci)
+ {
+-	unsigned	frame, clock, now_uframe, mod;
++	unsigned	now_uframe, frame, clock, clock_frame, mod;
+ 	unsigned	modified;
+ 
+ 	mod = ehci->periodic_size << 3;
+@@ -2111,6 +2123,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 	else
+ 		clock = now_uframe + mod - 1;
+ 	clock %= mod;
++	clock_frame = clock >> 3;
+ 
+ 	for (;;) {
+ 		union ehci_shadow	q, *q_p;
+@@ -2157,22 +2170,26 @@ scan_periodic (struct ehci_hcd *ehci)
+ 			case Q_TYPE_ITD:
+ 				/* If this ITD is still active, leave it for
+ 				 * later processing ... check the next entry.
++				 * No need to check for activity unless the
++				 * frame is current.
+ 				 */
+-				rmb ();
+-				for (uf = 0; uf < 8 && live; uf++) {
+-					if (0 == (q.itd->hw_transaction [uf]
+-							& ITD_ACTIVE(ehci)))
+-						continue;
+-					incomplete = true;
+-					q_p = &q.itd->itd_next;
+-					hw_p = &q.itd->hw_next;
+-					type = Q_NEXT_TYPE(ehci,
++				if (frame == clock_frame && live) {
++					rmb();
++					for (uf = 0; uf < 8; uf++) {
++						if (q.itd->hw_transaction[uf] &
++							    ITD_ACTIVE(ehci))
++							break;
++					}
++					if (uf < 8) {
++						incomplete = true;
++						q_p = &q.itd->itd_next;
++						hw_p = &q.itd->hw_next;
++						type = Q_NEXT_TYPE(ehci,
+ 							q.itd->hw_next);
+-					q = *q_p;
+-					break;
++						q = *q_p;
++						break;
++					}
+ 				}
+-				if (uf < 8 && live)
+-					break;
+ 
+ 				/* Take finished ITDs out of the schedule
+ 				 * and process them:  recycle, maybe report
+@@ -2189,9 +2206,12 @@ scan_periodic (struct ehci_hcd *ehci)
+ 			case Q_TYPE_SITD:
+ 				/* If this SITD is still active, leave it for
+ 				 * later processing ... check the next entry.
++				 * No need to check for activity unless the
++				 * frame is current.
+ 				 */
+-				if ((q.sitd->hw_results & SITD_ACTIVE(ehci))
+-						&& live) {
++				if (frame == clock_frame && live &&
++						(q.sitd->hw_results &
++							SITD_ACTIVE(ehci))) {
+ 					incomplete = true;
+ 					q_p = &q.sitd->sitd_next;
+ 					hw_p = &q.sitd->hw_next;
+@@ -2260,6 +2280,7 @@ scan_periodic (struct ehci_hcd *ehci)
+ 
+ 			/* rescan the rest of this frame, then ... */
+ 			clock = now;
++			clock_frame = clock >> 3;
+ 		} else {
+ 			now_uframe++;
+ 			now_uframe %= mod;

commit d1f114d12bb4db3147e1b1342ae31083c5a79c84
+Author: Alan Stern 
+Date:   Tue May 20 16:58:58 2008 -0400
+
+    USB: EHCI: fix remote-wakeup regression
+    
+    This patch (as1097) fixes a bug in the remote-wakeup handling in
+    ehci-hcd.  The driver currently does not keep track of whether the
+    change-suspend feature is enabled for each port; the feature is
+    automatically reset the first time it is read.  But recent changes to
+    the hub driver require that the feature be read at least twice in
+    order to work properly.
+    
+    A bit-vector is added for storing the change-suspend feature values.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index d613dc9e9c05..740835bb8575 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -609,7 +609,7 @@ static int ehci_hub_control (
+ 			}
+ 			break;
+ 		case USB_PORT_FEAT_C_SUSPEND:
+-			/* we auto-clear this feature */
++			clear_bit(wIndex, &ehci->port_c_suspend);
+ 			break;
+ 		case USB_PORT_FEAT_POWER:
+ 			if (HCS_PPC (ehci->hcs_params))
+@@ -688,7 +688,7 @@ static int ehci_hub_control (
+ 			/* resume completed? */
+ 			else if (time_after_eq(jiffies,
+ 					ehci->reset_done[wIndex])) {
+-				status |= 1 << USB_PORT_FEAT_C_SUSPEND;
++				set_bit(wIndex, &ehci->port_c_suspend);
+ 				ehci->reset_done[wIndex] = 0;
+ 
+ 				/* stop resume signaling */
+@@ -765,6 +765,8 @@ static int ehci_hub_control (
+ 			status |= 1 << USB_PORT_FEAT_RESET;
+ 		if (temp & PORT_POWER)
+ 			status |= 1 << USB_PORT_FEAT_POWER;
++		if (test_bit(wIndex, &ehci->port_c_suspend))
++			status |= 1 << USB_PORT_FEAT_C_SUSPEND;
+ 
+ #ifndef	VERBOSE_DEBUG
+ 	if (status & ~0xffff)	/* only if wPortChange is interesting */
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 3cb482308343..35a03095757e 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -97,6 +97,8 @@ struct ehci_hcd {			/* one per controller */
+ 			dedicated to the companion controller */
+ 	unsigned long		owned_ports;		/* which ports are
+ 			owned by the companion during a bus suspend */
++	unsigned long		port_c_suspend;		/* which ports have
++			the change-suspend feature turned on */
+ 
+ 	/* per-HC memory pools (could be per-bus, but ...) */
+ 	struct dma_pool		*qh_pool;	/* qh per active urb */

commit 3a31155cfff0935e4b178f3dca733d2d60d2eb8d
+Author: Alan Stern 
+Date:   Tue May 20 16:58:29 2008 -0400
+
+    USB: EHCI: suppress unwanted error messages
+    
+    This patch (as1096) fixes an annoying problem: When a full-speed or
+    low-speed device is plugged into an EHCI controller, it fails to
+    enumerate at high speed and then is handed over to the companion
+    controller.  But usbcore logs a misleading and unwanted error message
+    when the high-speed enumeration fails.
+    
+    The patch adds a new HCD method, port_handed_over, which asks whether
+    a port has been handed over to a companion controller.  If it has, the
+    error message is suppressed.
+    
+    Signed-off-by: Alan Stern 
+    CC: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index 1e4b81e9eb50..a0bf5df6cb6f 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -213,6 +213,8 @@ struct hc_driver {
+ 
+ 		/* force handover of high-speed port to full-speed companion */
+ 	void	(*relinquish_port)(struct usb_hcd *, int);
++		/* has a port been handed over to a companion? */
++	int	(*port_handed_over)(struct usb_hcd *, int);
+ };
+ 
+ extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 1a3d2879bc1d..8eb4da332f56 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2753,7 +2753,11 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 		if ((status == -ENOTCONN) || (status == -ENOTSUPP))
+ 			break;
+ 	}
+-	dev_err(hub_dev, "unable to enumerate USB device on port %d\n", port1);
++	if (hub->hdev->parent ||
++			!hcd->driver->port_handed_over ||
++			!(hcd->driver->port_handed_over)(hcd, port1))
++		dev_err(hub_dev, "unable to enumerate USB device on port %d\n",
++				port1);
+  
+ done:
+ 	hub_port_disable(hub, port1, 1);
+diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
+index 8b5f991e949c..08a4335401a9 100644
+--- a/drivers/usb/host/ehci-au1xxx.c
++++ b/drivers/usb/host/ehci-au1xxx.c
+@@ -223,6 +223,7 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
+ 	.bus_suspend = ehci_bus_suspend,
+ 	.bus_resume = ehci_bus_resume,
+ 	.relinquish_port = ehci_relinquish_port,
++	.port_handed_over = ehci_port_handed_over,
+ };
+ 
+ /*-------------------------------------------------------------------------*/
+diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
+index 4843062e6e21..7370d6187c64 100644
+--- a/drivers/usb/host/ehci-fsl.c
++++ b/drivers/usb/host/ehci-fsl.c
+@@ -318,6 +318,7 @@ static const struct hc_driver ehci_fsl_hc_driver = {
+ 	.bus_suspend = ehci_bus_suspend,
+ 	.bus_resume = ehci_bus_resume,
+ 	.relinquish_port = ehci_relinquish_port,
++	.port_handed_over = ehci_port_handed_over,
+ };
+ 
+ static int ehci_fsl_drv_probe(struct platform_device *pdev)
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 382587c4457c..d613dc9e9c05 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -875,3 +875,13 @@ static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum)
+ 	set_owner(ehci, --portnum, PORT_OWNER);
+ }
+ 
++static int ehci_port_handed_over(struct usb_hcd *hcd, int portnum)
++{
++	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
++	u32 __iomem		*reg;
++
++	if (ehci_is_TDI(ehci))
++		return 0;
++	reg = &ehci->regs->port_status[portnum - 1];
++	return ehci_readl(ehci, reg) & PORT_OWNER;
++}
+diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c
+index 539257f15924..9d042f220097 100644
+--- a/drivers/usb/host/ehci-ixp4xx.c
++++ b/drivers/usb/host/ehci-ixp4xx.c
+@@ -59,6 +59,7 @@ static const struct hc_driver ixp4xx_ehci_hc_driver = {
+ 	.bus_resume		= ehci_bus_resume,
+ #endif
+ 	.relinquish_port	= ehci_relinquish_port,
++	.port_handed_over	= ehci_port_handed_over,
+ };
+ 
+ static int ixp4xx_ehci_probe(struct platform_device *pdev)
+diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
+index 9c5266d02d6c..ab625f0ba1d9 100644
+--- a/drivers/usb/host/ehci-orion.c
++++ b/drivers/usb/host/ehci-orion.c
+@@ -162,6 +162,7 @@ static const struct hc_driver ehci_orion_hc_driver = {
+ 	.bus_suspend = ehci_bus_suspend,
+ 	.bus_resume = ehci_bus_resume,
+ 	.relinquish_port = ehci_relinquish_port,
++	.port_handed_over = ehci_port_handed_over,
+ };
+ 
+ static void __init
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index 6ff453f935e7..c46a58f9181d 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -379,6 +379,7 @@ static const struct hc_driver ehci_pci_hc_driver = {
+ 	.bus_suspend =		ehci_bus_suspend,
+ 	.bus_resume =		ehci_bus_resume,
+ 	.relinquish_port =	ehci_relinquish_port,
++	.port_handed_over =	ehci_port_handed_over,
+ };
+ 
+ /*-------------------------------------------------------------------------*/
+diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c
+index d94a2ef4944c..b018deed2e8f 100644
+--- a/drivers/usb/host/ehci-ppc-of.c
++++ b/drivers/usb/host/ehci-ppc-of.c
+@@ -77,6 +77,7 @@ static const struct hc_driver ehci_ppc_of_hc_driver = {
+ 	.bus_resume		= ehci_bus_resume,
+ #endif
+ 	.relinquish_port	= ehci_relinquish_port,
++	.port_handed_over	= ehci_port_handed_over,
+ };
+ 
+ 
+diff --git a/drivers/usb/host/ehci-ppc-soc.c b/drivers/usb/host/ehci-ppc-soc.c
+index 6c76036783a1..529590eb4037 100644
+--- a/drivers/usb/host/ehci-ppc-soc.c
++++ b/drivers/usb/host/ehci-ppc-soc.c
+@@ -163,6 +163,7 @@ static const struct hc_driver ehci_ppc_soc_hc_driver = {
+ 	.bus_suspend = ehci_bus_suspend,
+ 	.bus_resume = ehci_bus_resume,
+ 	.relinquish_port = ehci_relinquish_port,
++	.port_handed_over = ehci_port_handed_over,
+ };
+ 
+ static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev)
+diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
+index 69782221bcf3..37e6abeb794c 100644
+--- a/drivers/usb/host/ehci-ps3.c
++++ b/drivers/usb/host/ehci-ps3.c
+@@ -73,6 +73,7 @@ static const struct hc_driver ps3_ehci_hc_driver = {
+ 	.bus_resume		= ehci_bus_resume,
+ #endif
+ 	.relinquish_port	= ehci_relinquish_port,
++	.port_handed_over	= ehci_port_handed_over,
+ };
+ 
+ static int ps3_ehci_probe(struct ps3_system_bus_device *dev)

commit a8e5177583e975fc1f7c621c93956f494df9b979
+Author: Alan Stern 
+Date:   Tue May 20 16:58:11 2008 -0400
+
+    USB: EHCI: fix up root-hub TT mess
+    
+    This patch (as1095) cleans up the HCD glue and several of the EHCI
+    bus-glue files.  The ehci->is_tdi_rh_tt flag is redundant, since it
+    means the same thing as the hcd->has_tt flag, so it is removed and the
+    other flag used in its place.
+    
+    Some of the bus-glue files didn't get the relinquish_port method added
+    to their hc_driver structures.  Although that routine currently
+    doesn't do anything for controllers with an integrated TT, in the
+    future it might.  So the patch adds it where it is missing.
+    
+    Lastly, some of the bus-glue files have erroneous entries for their
+    hc_driver's suspend and resume methods.  These method pointers are
+    specific to PCI and shouldn't be used otherwise.
+    
+    (The patch also includes an invisible whitespace fix.)
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: David Brownell 
+
+diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
+index 6d9bed6c1f48..4843062e6e21 100644
+--- a/drivers/usb/host/ehci-fsl.c
++++ b/drivers/usb/host/ehci-fsl.c
+@@ -269,7 +269,7 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
+ 	if (retval)
+ 		return retval;
+ 
+-	ehci->is_tdi_rh_tt = 1;
++	hcd->has_tt = 1;
+ 
+ 	ehci->sbrn = 0x20;
+ 
+@@ -295,10 +295,6 @@ static const struct hc_driver ehci_fsl_hc_driver = {
+ 	 */
+ 	.reset = ehci_fsl_setup,
+ 	.start = ehci_run,
+-#ifdef	CONFIG_PM
+-	.suspend = ehci_bus_suspend,
+-	.resume = ehci_bus_resume,
+-#endif
+ 	.stop = ehci_stop,
+ 	.shutdown = ehci_shutdown,
+ 
+diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c
+index 601c8795a854..539257f15924 100644
+--- a/drivers/usb/host/ehci-ixp4xx.c
++++ b/drivers/usb/host/ehci-ixp4xx.c
+@@ -26,7 +26,7 @@ static int ixp4xx_ehci_init(struct usb_hcd *hcd)
+ 		+ HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+ 	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+ 
+-	ehci->is_tdi_rh_tt = 1;
++	hcd->has_tt = 1;
+ 	ehci_reset(ehci);
+ 
+ 	retval = ehci_init(hcd);
+@@ -58,6 +58,7 @@ static const struct hc_driver ixp4xx_ehci_hc_driver = {
+ 	.bus_suspend		= ehci_bus_suspend,
+ 	.bus_resume		= ehci_bus_resume,
+ #endif
++	.relinquish_port	= ehci_relinquish_port,
+ };
+ 
+ static int ixp4xx_ehci_probe(struct platform_device *pdev)
+diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
+index 3adfda813a7b..9c5266d02d6c 100644
+--- a/drivers/usb/host/ehci-orion.c
++++ b/drivers/usb/host/ehci-orion.c
+@@ -139,10 +139,6 @@ static const struct hc_driver ehci_orion_hc_driver = {
+ 	 */
+ 	.reset = ehci_orion_setup,
+ 	.start = ehci_run,
+-#ifdef CONFIG_PM
+-	.suspend = ehci_bus_suspend,
+-	.resume = ehci_bus_resume,
+-#endif
+ 	.stop = ehci_stop,
+ 	.shutdown = ehci_shutdown,
+ 
+@@ -165,6 +161,7 @@ static const struct hc_driver ehci_orion_hc_driver = {
+ 	.hub_control = ehci_hub_control,
+ 	.bus_suspend = ehci_bus_suspend,
+ 	.bus_resume = ehci_bus_resume,
++	.relinquish_port = ehci_relinquish_port,
+ };
+ 
+ static void __init
+@@ -250,7 +247,7 @@ static int __init ehci_orion_drv_probe(struct platform_device *pdev)
+ 	ehci->regs = hcd->regs + 0x100 +
+ 		HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+ 	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+-	ehci->is_tdi_rh_tt = 1;
++	hcd->has_tt = 1;
+ 	ehci->sbrn = 0x20;
+ 
+ 	/*
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index 5bb7f6bb13f3..6ff453f935e7 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -129,7 +129,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 	switch (pdev->vendor) {
+ 	case PCI_VENDOR_ID_TDI:
+ 		if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
+-			ehci->is_tdi_rh_tt = 1;
+ 			hcd->has_tt = 1;
+ 			tdi_reset(ehci);
+ 		}
+@@ -379,7 +378,7 @@ static const struct hc_driver ehci_pci_hc_driver = {
+ 	.hub_control =		ehci_hub_control,
+ 	.bus_suspend =		ehci_bus_suspend,
+ 	.bus_resume =		ehci_bus_resume,
+-	.relinquish_port = 	ehci_relinquish_port,
++	.relinquish_port =	ehci_relinquish_port,
+ };
+ 
+ /*-------------------------------------------------------------------------*/
+diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c
+index ee305b1f99ff..d94a2ef4944c 100644
+--- a/drivers/usb/host/ehci-ppc-of.c
++++ b/drivers/usb/host/ehci-ppc-of.c
+@@ -76,6 +76,7 @@ static const struct hc_driver ehci_ppc_of_hc_driver = {
+ 	.bus_suspend		= ehci_bus_suspend,
+ 	.bus_resume		= ehci_bus_resume,
+ #endif
++	.relinquish_port	= ehci_relinquish_port,
+ };
+ 
+ 
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index bf92d209a1a9..3cb482308343 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -112,7 +112,6 @@ struct ehci_hcd {			/* one per controller */
+ 	u32			command;
+ 
+ 	/* SILICON QUIRKS */
+-	unsigned		is_tdi_rh_tt:1;	/* TDI roothub with TT */
+ 	unsigned		no_selective_suspend:1;
+ 	unsigned		has_fsl_port_bug:1; /* FreeScale */
+ 	unsigned		big_endian_mmio:1;
+@@ -678,7 +677,7 @@ struct ehci_fstn {
+  * needed (mostly in root hub code).
+  */
+ 
+-#define	ehci_is_TDI(e)			((e)->is_tdi_rh_tt)
++#define	ehci_is_TDI(e)			(ehci_to_hcd(e)->has_tt)
+ 
+ /* Returns the speed of a device attached to a port on the root hub. */
+ static inline unsigned int

commit 217a9081d8e69026186067711131b77f0ce219ed
+Author: Alan Stern 
+Date:   Tue May 20 16:40:42 2008 -0400
+
+    USB: add all configs to the "descriptors" attribute
+    
+    This patch (as1094) changes the output of the "descriptors" binary
+    attribute.  Now it will contain the device descriptor followed by all
+    the configuration descriptors, not just the descriptor for the current
+    config.
+    
+    Userspace libraries want to have access to the kernel's cached
+    descriptor information, so they can learn about device characteristics
+    without having to wake up suspended devices.  So far the only user of
+    this attribute is the new libusb-1.0 library; thus changing its
+    contents shouldn't cause any problems.
+    
+    This should be considered for 2.6.26, if for no other reason than to
+    minimize the range of releases in which the attribute contains only the
+    current config descriptor.
+    
+    Also, it doesn't hurt that the patch removes the device locking --
+    which was formerly needed in order to know for certain which config was
+    indeed current.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index c783cb111847..5e1f5d55bf04 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -588,35 +588,33 @@ read_descriptors(struct kobject *kobj, struct bin_attribute *attr,
+ 			container_of(kobj, struct device, kobj));
+ 	size_t nleft = count;
+ 	size_t srclen, n;
++	int cfgno;
++	void *src;
+ 
+-	usb_lock_device(udev);
+-
+-	/* The binary attribute begins with the device descriptor */
+-	srclen = sizeof(struct usb_device_descriptor);
+-	if (off < srclen) {
+-		n = min_t(size_t, nleft, srclen - off);
+-		memcpy(buf, off + (char *) &udev->descriptor, n);
+-		nleft -= n;
+-		buf += n;
+-		off = 0;
+-	} else {
+-		off -= srclen;
+-	}
+-
+-	/* Then follows the raw descriptor entry for the current
+-	 * configuration (config plus subsidiary descriptors).
++	/* The binary attribute begins with the device descriptor.
++	 * Following that are the raw descriptor entries for all the
++	 * configurations (config plus subsidiary descriptors).
+ 	 */
+-	if (udev->actconfig) {
+-		int cfgno = udev->actconfig - udev->config;
+-
+-		srclen = __le16_to_cpu(udev->actconfig->desc.wTotalLength);
++	for (cfgno = -1; cfgno < udev->descriptor.bNumConfigurations &&
++			nleft > 0; ++cfgno) {
++		if (cfgno < 0) {
++			src = &udev->descriptor;
++			srclen = sizeof(struct usb_device_descriptor);
++		} else {
++			src = udev->rawdescriptors[cfgno];
++			srclen = __le16_to_cpu(udev->config[cfgno].desc.
++					wTotalLength);
++		}
+ 		if (off < srclen) {
+-			n = min_t(size_t, nleft, srclen - off);
+-			memcpy(buf, off + udev->rawdescriptors[cfgno], n);
++			n = min(nleft, srclen - (size_t) off);
++			memcpy(buf, src + off, n);
+ 			nleft -= n;
++			buf += n;
++			off = 0;
++		} else {
++			off -= srclen;
+ 		}
+ 	}
+-	usb_unlock_device(udev);
+ 	return count - nleft;
+ }
+ 

commit e16362a0c8d90e9adbfe477acbe32b021823fb22
+Author: Alan Stern 
+Date:   Tue May 20 16:37:34 2008 -0400
+
+    USB: fix possible deadlock involving sysfs attributes
+    
+    There is a potential deadlock when the usb_generic driver is unbound
+    from a device.  The problem is that generic_disconnect() is called
+    with the device lock held, and it removes a bunch of device attributes
+    from sysfs.  If a user task happens to be running an attribute method
+    at the time, the removal will block until the method returns.  But at
+    least one of the attribute methods (the store routine for power/level)
+    needs to acquire the device lock!
+    
+    This patch (as1093) eliminates the deadlock by moving the calls to
+    create and remove the sysfs attributes from the usb_generic driver
+    into usb_new_device() and usb_disconnect(), where they can be invoked
+    without holding the device lock.
+    
+    Besides, the other sysfs attributes are created when the device is
+    registered and removed when the device is unregistered.  So it seems
+    only fitting for the extra attributes to be created and removed at the
+    same time.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
+index c1cb94e9f242..7e912f21fd36 100644
+--- a/drivers/usb/core/generic.c
++++ b/drivers/usb/core/generic.c
+@@ -155,9 +155,6 @@ static int generic_probe(struct usb_device *udev)
+ {
+ 	int err, c;
+ 
+-	/* put device-specific files into sysfs */
+-	usb_create_sysfs_dev_files(udev);
+-
+ 	/* Choose and set the configuration.  This registers the interfaces
+ 	 * with the driver core and lets interface drivers bind to them.
+ 	 */
+@@ -189,8 +186,6 @@ static void generic_disconnect(struct usb_device *udev)
+ 	 * unconfigure the device */
+ 	if (udev->actconfig)
+ 		usb_set_configuration(udev, -1);
+-
+-	usb_remove_sysfs_dev_files(udev);
+ }
+ 
+ #ifdef	CONFIG_PM
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index eb57fcc701d7..1a3d2879bc1d 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1326,6 +1326,12 @@ void usb_disconnect(struct usb_device **pdev)
+ 
+ 	usb_unlock_device(udev);
+ 
++	/* Remove the device-specific files from sysfs.  This must be
++	 * done with udev unlocked, because some of the attribute
++	 * routines try to acquire the device lock.
++	 */
++	usb_remove_sysfs_dev_files(udev);
++
+ 	/* Unregister the device.  The device driver is responsible
+ 	 * for removing the device files from usbfs and sysfs and for
+ 	 * de-configuring the device.
+@@ -1541,6 +1547,9 @@ int usb_new_device(struct usb_device *udev)
+ 		goto fail;
+ 	}
+ 
++	/* put device-specific files into sysfs */
++	usb_create_sysfs_dev_files(udev);
++
+ 	/* Tell the world! */
+ 	announce_device(udev);
+ 	return err;

commit 2e5f10e4f0a9649186d8a8c793822b2e0dae8373
+Author: Alan Stern 
+Date:   Wed Apr 30 15:37:19 2008 -0400
+
+    USB: create attributes before sending uevent
+    
+    This patch (as1087d) fixes a long-standing problem in usbcore: Device,
+    interface, and endpoint attributes aren't added until _after_ the
+    creation uevent has already been broadcast.
+    
+    Unfortunately there are a few attributes which cannot be created that
+    early.  The "descriptors" attribute is binary and so must be created
+    separately.  The power-management attributes can't be created until
+    the dev/power/ group exists.  And the interface string can vary from
+    one altsetting to another, so it has to be created dynamically.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Kay Sievers 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
+index 99e5a68a3f12..fae55a31e26d 100644
+--- a/drivers/usb/core/endpoint.c
++++ b/drivers/usb/core/endpoint.c
+@@ -156,6 +156,10 @@ static struct attribute *ep_dev_attrs[] = {
+ static struct attribute_group ep_dev_attr_grp = {
+ 	.attrs = ep_dev_attrs,
+ };
++static struct attribute_group *ep_dev_groups[] = {
++	&ep_dev_attr_grp,
++	NULL
++};
+ 
+ static int usb_endpoint_major_init(void)
+ {
+@@ -298,6 +302,7 @@ int usb_create_ep_files(struct device *parent,
+ 
+ 	ep_dev->desc = &endpoint->desc;
+ 	ep_dev->udev = udev;
++	ep_dev->dev.groups = ep_dev_groups;
+ 	ep_dev->dev.devt = MKDEV(usb_endpoint_major, ep_dev->minor);
+ 	ep_dev->dev.class = ep_class->class;
+ 	ep_dev->dev.parent = parent;
+@@ -309,9 +314,6 @@ int usb_create_ep_files(struct device *parent,
+ 	retval = device_register(&ep_dev->dev);
+ 	if (retval)
+ 		goto error_chrdev;
+-	retval = sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
+-	if (retval)
+-		goto error_group;
+ 
+ 	/* create the symlink to the old-style "ep_XX" directory */
+ 	sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress);
+@@ -322,8 +324,6 @@ int usb_create_ep_files(struct device *parent,
+ 	return retval;
+ 
+ error_link:
+-	sysfs_remove_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
+-error_group:
+ 	device_unregister(&ep_dev->dev);
+ 	destroy_endpoint_class();
+ 	return retval;
+@@ -348,7 +348,6 @@ void usb_remove_ep_files(struct usb_host_endpoint *endpoint)
+ 
+ 		sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress);
+ 		sysfs_remove_link(&ep_dev->dev.parent->kobj, name);
+-		sysfs_remove_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
+ 		device_unregister(&ep_dev->dev);
+ 		endpoint->ep_dev = NULL;
+ 		destroy_endpoint_class();
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 3e69266e1f4d..fe47d145255a 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1607,6 +1607,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 		intf->dev.driver = NULL;
+ 		intf->dev.bus = &usb_bus_type;
+ 		intf->dev.type = &usb_if_device_type;
++		intf->dev.groups = usb_interface_groups;
+ 		intf->dev.dma_mask = dev->dev.dma_mask;
+ 		device_initialize(&intf->dev);
+ 		mark_quiesced(intf);
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 5b20a60de8ba..c783cb111847 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -538,6 +538,46 @@ static struct attribute_group dev_attr_grp = {
+ 	.attrs = dev_attrs,
+ };
+ 
++/* When modifying this list, be sure to modify dev_string_attrs_are_visible()
++ * accordingly.
++ */
++static struct attribute *dev_string_attrs[] = {
++	&dev_attr_manufacturer.attr,
++	&dev_attr_product.attr,
++	&dev_attr_serial.attr,
++	NULL
++};
++
++static mode_t dev_string_attrs_are_visible(struct kobject *kobj,
++		struct attribute *a, int n)
++{
++	struct usb_device *udev = to_usb_device(
++			container_of(kobj, struct device, kobj));
++
++	if (a == &dev_attr_manufacturer.attr) {
++		if (udev->manufacturer == NULL)
++			return 0;
++	} else if (a == &dev_attr_product.attr) {
++		if (udev->product == NULL)
++			return 0;
++	} else if (a == &dev_attr_serial.attr) {
++		if (udev->serial == NULL)
++			return 0;
++	}
++	return a->mode;
++}
++
++static struct attribute_group dev_string_attr_grp = {
++	.attrs =	dev_string_attrs,
++	.is_visible =	dev_string_attrs_are_visible,
++};
++
++struct attribute_group *usb_device_groups[] = {
++	&dev_attr_grp,
++	&dev_string_attr_grp,
++	NULL
++};
++
+ /* Binary descriptors */
+ 
+ static ssize_t
+@@ -591,10 +631,9 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
+ 	struct device *dev = &udev->dev;
+ 	int retval;
+ 
+-	retval = sysfs_create_group(&dev->kobj, &dev_attr_grp);
+-	if (retval)
+-		return retval;
+-
++	/* Unforunately these attributes cannot be created before
++	 * the uevent is broadcast.
++	 */
+ 	retval = device_create_bin_file(dev, &dev_bin_attr_descriptors);
+ 	if (retval)
+ 		goto error;
+@@ -607,21 +646,6 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
+ 	if (retval)
+ 		goto error;
+ 
+-	if (udev->manufacturer) {
+-		retval = device_create_file(dev, &dev_attr_manufacturer);
+-		if (retval)
+-			goto error;
+-	}
+-	if (udev->product) {
+-		retval = device_create_file(dev, &dev_attr_product);
+-		if (retval)
+-			goto error;
+-	}
+-	if (udev->serial) {
+-		retval = device_create_file(dev, &dev_attr_serial);
+-		if (retval)
+-			goto error;
+-	}
+ 	retval = usb_create_ep_files(dev, &udev->ep0, udev);
+ 	if (retval)
+ 		goto error;
+@@ -636,13 +660,9 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)
+ 	struct device *dev = &udev->dev;
+ 
+ 	usb_remove_ep_files(&udev->ep0);
+-	device_remove_file(dev, &dev_attr_manufacturer);
+-	device_remove_file(dev, &dev_attr_product);
+-	device_remove_file(dev, &dev_attr_serial);
+ 	remove_power_attributes(dev);
+ 	remove_persist_attributes(dev);
+ 	device_remove_bin_file(dev, &dev_bin_attr_descriptors);
+-	sysfs_remove_group(&dev->kobj, &dev_attr_grp);
+ }
+ 
+ /* Interface Accociation Descriptor fields */
+@@ -688,17 +708,15 @@ static ssize_t show_interface_string(struct device *dev,
+ 		struct device_attribute *attr, char *buf)
+ {
+ 	struct usb_interface *intf;
+-	struct usb_device *udev;
+-	int len;
++	char *string;
+ 
+ 	intf = to_usb_interface(dev);
+-	udev = interface_to_usbdev(intf);
+-	len = snprintf(buf, 256, "%s", intf->cur_altsetting->string);
+-	if (len < 0)
++	string = intf->cur_altsetting->string;
++	barrier();		/* The altsetting might change! */
++
++	if (!string)
+ 		return 0;
+-	buf[len] = '\n';
+-	buf[len+1] = 0;
+-	return len+1;
++	return sprintf(buf, "%s\n", string);
+ }
+ static DEVICE_ATTR(interface, S_IRUGO, show_interface_string, NULL);
+ 
+@@ -727,18 +745,6 @@ static ssize_t show_modalias(struct device *dev,
+ }
+ static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
+ 
+-static struct attribute *intf_assoc_attrs[] = {
+-	&dev_attr_iad_bFirstInterface.attr,
+-	&dev_attr_iad_bInterfaceCount.attr,
+-	&dev_attr_iad_bFunctionClass.attr,
+-	&dev_attr_iad_bFunctionSubClass.attr,
+-	&dev_attr_iad_bFunctionProtocol.attr,
+-	NULL,
+-};
+-static struct attribute_group intf_assoc_attr_grp = {
+-	.attrs = intf_assoc_attrs,
+-};
+-
+ static struct attribute *intf_attrs[] = {
+ 	&dev_attr_bInterfaceNumber.attr,
+ 	&dev_attr_bAlternateSetting.attr,
+@@ -753,6 +759,37 @@ static struct attribute_group intf_attr_grp = {
+ 	.attrs = intf_attrs,
+ };
+ 
++static struct attribute *intf_assoc_attrs[] = {
++	&dev_attr_iad_bFirstInterface.attr,
++	&dev_attr_iad_bInterfaceCount.attr,
++	&dev_attr_iad_bFunctionClass.attr,
++	&dev_attr_iad_bFunctionSubClass.attr,
++	&dev_attr_iad_bFunctionProtocol.attr,
++	NULL,
++};
++
++static mode_t intf_assoc_attrs_are_visible(struct kobject *kobj,
++		struct attribute *a, int n)
++{
++	struct usb_interface *intf = to_usb_interface(
++			container_of(kobj, struct device, kobj));
++
++	if (intf->intf_assoc == NULL)
++		return 0;
++	return a->mode;
++}
++
++static struct attribute_group intf_assoc_attr_grp = {
++	.attrs =	intf_assoc_attrs,
++	.is_visible =	intf_assoc_attrs_are_visible,
++};
++
++struct attribute_group *usb_interface_groups[] = {
++	&intf_attr_grp,
++	&intf_assoc_attr_grp,
++	NULL
++};
++
+ static inline void usb_create_intf_ep_files(struct usb_interface *intf,
+ 		struct usb_device *udev)
+ {
+@@ -777,23 +814,21 @@ static inline void usb_remove_intf_ep_files(struct usb_interface *intf)
+ 
+ int usb_create_sysfs_intf_files(struct usb_interface *intf)
+ {
+-	struct device *dev = &intf->dev;
+ 	struct usb_device *udev = interface_to_usbdev(intf);
+ 	struct usb_host_interface *alt = intf->cur_altsetting;
+ 	int retval;
+ 
+ 	if (intf->sysfs_files_created)
+ 		return 0;
+-	retval = sysfs_create_group(&dev->kobj, &intf_attr_grp);
+-	if (retval)
+-		return retval;
+ 
++	/* The interface string may be present in some altsettings
++	 * and missing in others.  Hence its attribute cannot be created
++	 * before the uevent is broadcast.
++	 */
+ 	if (alt->string == NULL)
+ 		alt->string = usb_cache_string(udev, alt->desc.iInterface);
+ 	if (alt->string)
+-		retval = device_create_file(dev, &dev_attr_interface);
+-	if (intf->intf_assoc)
+-		retval = sysfs_create_group(&dev->kobj, &intf_assoc_attr_grp);
++		retval = device_create_file(&intf->dev, &dev_attr_interface);
+ 	usb_create_intf_ep_files(intf, udev);
+ 	intf->sysfs_files_created = 1;
+ 	return 0;
+@@ -807,7 +842,5 @@ void usb_remove_sysfs_intf_files(struct usb_interface *intf)
+ 		return;
+ 	usb_remove_intf_ep_files(intf);
+ 	device_remove_file(dev, &dev_attr_interface);
+-	sysfs_remove_group(&dev->kobj, &intf_attr_grp);
+-	sysfs_remove_group(&intf->dev.kobj, &intf_assoc_attr_grp);
+ 	intf->sysfs_files_created = 0;
+ }
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 1f0db51190cc..325774375837 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -291,6 +291,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
+ 	device_initialize(&dev->dev);
+ 	dev->dev.bus = &usb_bus_type;
+ 	dev->dev.type = &usb_device_type;
++	dev->dev.groups = usb_device_groups;
+ 	dev->dev.dma_mask = bus->controller->dma_mask;
+ 	set_dev_node(&dev->dev, dev_to_node(bus->controller));
+ 	dev->state = USB_STATE_ATTACHED;
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 1bf8ccb9c58d..1a8bc21c335e 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -130,6 +130,10 @@ static inline int is_active(const struct usb_interface *f)
+ /* for labeling diagnostics */
+ extern const char *usbcore_name;
+ 
++/* sysfs stuff */
++extern struct attribute_group *usb_device_groups[];
++extern struct attribute_group *usb_interface_groups[];
++
+ /* usbfs stuff */
+ extern struct mutex usbfs_mutex;
+ extern struct usb_driver usbfs_driver;

commit d8f12ab5d984761726e638a4222299a9fc516233
+Author: Alan Stern 
+Date:   Tue Apr 22 10:49:15 2008 -0400
+
+    USB: UHCI: disable remote wakeup when it's not needed
+    
+    This patch (as1084b) fixes the way uhci-hcd handles polling and
+    remote wakeups for its root hubs.  When remote wakeup is disabled,
+    neither interrupts nor polling should be enabled during a root-hub
+    suspend.  Likewise, if interrupts are enabled during suspend then
+    polling isn't needed.
+    
+    Furthermore the EGSM (Enter Global Suspend Mode) bit shouldn't be set
+    in the Command register unless remote wakeup is enabled.  Apparently
+    some controllers will issue a remote-wakeup interrupt whenever EGSM
+    is on, even if Resume-Detect interrupts are supposedly disabled.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index d3e0d8aa3980..3a7bfe7a8874 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -234,7 +234,7 @@ static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
+ 	return 0;
+ }
+ 
+-static int remote_wakeup_is_broken(struct uhci_hcd *uhci)
++static int global_suspend_mode_is_broken(struct uhci_hcd *uhci)
+ {
+ 	int port;
+ 	const char *sys_info;
+@@ -261,27 +261,60 @@ __releases(uhci->lock)
+ __acquires(uhci->lock)
+ {
+ 	int auto_stop;
+-	int int_enable, egsm_enable;
++	int int_enable, egsm_enable, wakeup_enable;
+ 	struct usb_device *rhdev = uhci_to_hcd(uhci)->self.root_hub;
+ 
+ 	auto_stop = (new_state == UHCI_RH_AUTO_STOPPED);
+ 	dev_dbg(&rhdev->dev, "%s%s\n", __func__,
+ 			(auto_stop ? " (auto-stop)" : ""));
+ 
+-	/* Enable resume-detect interrupts if they work.
+-	 * Then enter Global Suspend mode if _it_ works, still configured.
++	/* Start off by assuming Resume-Detect interrupts and EGSM work
++	 * and that remote wakeups should be enabled.
+ 	 */
+ 	egsm_enable = USBCMD_EGSM;
+-	uhci->working_RD = 1;
++	uhci->RD_enable = 1;
+ 	int_enable = USBINTR_RESUME;
+-	if (remote_wakeup_is_broken(uhci))
+-		egsm_enable = 0;
+-	if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable ||
++	wakeup_enable = 1;
++
++	/* In auto-stop mode wakeups must always be detected, but
++	 * Resume-Detect interrupts may be prohibited.  (In the absence
++	 * of CONFIG_PM, they are always disallowed.)
++	 */
++	if (auto_stop) {
++		if (!device_may_wakeup(&rhdev->dev))
++			int_enable = 0;
++
++	/* In bus-suspend mode wakeups may be disabled, but if they are
++	 * allowed then so are Resume-Detect interrupts.
++	 */
++	} else {
+ #ifdef CONFIG_PM
+-			(!auto_stop && !rhdev->do_remote_wakeup) ||
++		if (!rhdev->do_remote_wakeup)
++			wakeup_enable = 0;
+ #endif
+-			(auto_stop && !device_may_wakeup(&rhdev->dev)))
+-		uhci->working_RD = int_enable = 0;
++	}
++
++	/* EGSM causes the root hub to echo a 'K' signal (resume) out any
++	 * port which requests a remote wakeup.  According to the USB spec,
++	 * every hub is supposed to do this.  But if we are ignoring
++	 * remote-wakeup requests anyway then there's no point to it.
++	 * We also shouldn't enable EGSM if it's broken.
++	 */
++	if (!wakeup_enable || global_suspend_mode_is_broken(uhci))
++		egsm_enable = 0;
++
++	/* If we're ignoring wakeup events then there's no reason to
++	 * enable Resume-Detect interrupts.  We also shouldn't enable
++	 * them if they are broken or disallowed.
++	 *
++	 * This logic may lead us to enabling RD but not EGSM.  The UHCI
++	 * spec foolishly says that RD works only when EGSM is on, but
++	 * there's no harm in enabling it anyway -- perhaps some chips
++	 * will implement it!
++	 */
++	if (!wakeup_enable || resume_detect_interrupts_are_broken(uhci) ||
++			!int_enable)
++		uhci->RD_enable = int_enable = 0;
+ 
+ 	outw(int_enable, uhci->io_addr + USBINTR);
+ 	outw(egsm_enable | USBCMD_CF, uhci->io_addr + USBCMD);
+@@ -308,7 +341,11 @@ __acquires(uhci->lock)
+ 
+ 	uhci->rh_state = new_state;
+ 	uhci->is_stopped = UHCI_IS_STOPPED;
+-	uhci_to_hcd(uhci)->poll_rh = !int_enable;
++
++	/* If interrupts don't work and remote wakeup is enabled then
++	 * the suspended root hub needs to be polled.
++	 */
++	uhci_to_hcd(uhci)->poll_rh = (!int_enable && wakeup_enable);
+ 
+ 	uhci_scan_schedule(uhci);
+ 	uhci_fsbr_off(uhci);
+@@ -344,9 +381,12 @@ __acquires(uhci->lock)
+ 	 * for 20 ms.
+ 	 */
+ 	if (uhci->rh_state == UHCI_RH_SUSPENDED) {
++		unsigned egsm;
++
++		/* Keep EGSM on if it was set before */
++		egsm = inw(uhci->io_addr + USBCMD) & USBCMD_EGSM;
+ 		uhci->rh_state = UHCI_RH_RESUMING;
+-		outw(USBCMD_FGR | USBCMD_EGSM | USBCMD_CF,
+-				uhci->io_addr + USBCMD);
++		outw(USBCMD_FGR | USBCMD_CF | egsm, uhci->io_addr + USBCMD);
+ 		spin_unlock_irq(&uhci->lock);
+ 		msleep(20);
+ 		spin_lock_irq(&uhci->lock);
+@@ -801,8 +841,10 @@ static int uhci_pci_resume(struct usb_hcd *hcd)
+ 
+ 	spin_unlock_irq(&uhci->lock);
+ 
+-	if (!uhci->working_RD) {
+-		/* Suspended root hub needs to be polled */
++	/* If interrupts don't work and remote wakeup is enabled then
++	 * the suspended root hub needs to be polled.
++	 */
++	if (!uhci->RD_enable && hcd->self.root_hub->do_remote_wakeup) {
+ 		hcd->poll_rh = 1;
+ 		usb_hcd_poll_rh_status(hcd);
+ 	}
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index 340d6ed3e6e9..7d01c5677f92 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -400,8 +400,9 @@ struct uhci_hcd {
+ 	unsigned int scan_in_progress:1;	/* Schedule scan is running */
+ 	unsigned int need_rescan:1;		/* Redo the schedule scan */
+ 	unsigned int dead:1;			/* Controller has died */
+-	unsigned int working_RD:1;		/* Suspended root hub doesn't
+-						   need to be polled */
++	unsigned int RD_enable:1;		/* Suspended root hub with
++						   Resume-Detect interrupts
++						   enabled */
+ 	unsigned int is_initialized:1;		/* Data structure is usable */
+ 	unsigned int fsbr_is_on:1;		/* FSBR is turned on */
+ 	unsigned int fsbr_is_wanted:1;		/* Does any URB want FSBR? */

commit 1b7b61c5d4071b9a25f6a9aae6f0a1e0efdbb2ae
+Author: Alan Stern 
+Date:   Tue Apr 22 10:50:18 2008 -0400
+
+    USB: OHCI: work around bogus compiler warning
+    
+    The patch (as1086) works around a bogus "uninitialized variable"
+    warning generated by some versions of GCC.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index 17dc2eccda83..79a78029f896 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -613,7 +613,7 @@ static void start_hnp(struct ohci_hcd *ohci);
+ static inline int root_port_reset (struct ohci_hcd *ohci, unsigned port)
+ {
+ 	__hc32 __iomem *portstat = &ohci->regs->roothub.portstatus [port];
+-	u32	temp;
++	u32	temp = 0;
+ 	u16	now = ohci_readl(ohci, &ohci->regs->fmnumber);
+ 	u16	reset_done = now + PORT_RESET_MSEC;
+ 	int	limit_1 = DIV_ROUND_UP(PORT_RESET_MSEC, PORT_RESET_HW_MSEC);

commit b28884c1729940df83d87c515a5e66e5afbe9dea
+Author: Alan Stern 
+Date:   Mon Apr 28 10:26:13 2008 -0400
+
+    usb-storage: add unusual_devs entry for Samsung YP-U3
+    
+    This patch (as1088) adds an unusual_devs entry for Samsung's YP-U3.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Phil Dibowitz 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 732bf52a775e..47f6dd7603ef 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -557,6 +557,13 @@ UNUSUAL_DEV(  0x04e6, 0x1010, 0x0000, 0x9999,
+ 		US_FL_SINGLE_LUN),
+ #endif
+ 
++/* Reported by Dmitry Khlystov  */
++UNUSUAL_DEV(  0x04e8, 0x507c, 0x0220, 0x0220,
++		"Samsung",
++		"YP-U3",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_MAX_SECTORS_64),
++
+ /* Reported by Bob Sass  -- only rev 1.33 tested */
+ UNUSUAL_DEV(  0x050d, 0x0115, 0x0133, 0x0133,
+ 		"Belkin",

commit 14722ef4acedc643f0b78b7165ceff2d300dae4d
+Author: Alan Stern 
+Date:   Thu Apr 17 10:18:11 2008 -0400
+
+    USB: usbfs: export the URB_NO_INTERRUPT flag to userspace
+    
+    This patch (as1079) cleans up the way URB_* flags are exported in
+    usbfs.
+    
+            The URB_NO_INTERRUPT flag is now exported (this is the
+            only behavioral change).
+    
+            USBDEVFS_URB_* macros are added for URB_NO_FSBR,
+            URB_ZERO_PACKET, and URB_NO_INTERRUPT, making explicit the
+            fact that the kernel accepts them.
+    
+            The flag matching takes into account that the URB_* values
+            may change as the kernel evolves, whereas the USBDEVFS_URB_*
+            values must remain fixed since they are a user API.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 039ba23cc8b6..6c4cd82d7d14 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -948,8 +948,11 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 	int ret, ifnum = -1;
+ 	int is_in;
+ 
+-	if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK|
+-			   URB_NO_FSBR|URB_ZERO_PACKET))
++	if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP |
++				USBDEVFS_URB_SHORT_NOT_OK |
++				USBDEVFS_URB_NO_FSBR |
++				USBDEVFS_URB_ZERO_PACKET |
++				USBDEVFS_URB_NO_INTERRUPT))
+ 		return -EINVAL;
+ 	if (!uurb->buffer)
+ 		return -EINVAL;
+@@ -1104,8 +1107,24 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 	as->urb->pipe = (uurb->type << 30) |
+ 			__create_pipe(ps->dev, uurb->endpoint & 0xf) |
+ 			(uurb->endpoint & USB_DIR_IN);
+-	as->urb->transfer_flags = uurb->flags |
+-			(is_in ? URB_DIR_IN : URB_DIR_OUT);
++
++	/* This tedious sequence is necessary because the URB_* flags
++	 * are internal to the kernel and subject to change, whereas
++	 * the USBDEVFS_URB_* flags are a user API and must not be changed.
++	 */
++	u = (is_in ? URB_DIR_IN : URB_DIR_OUT);
++	if (uurb->flags & USBDEVFS_URB_ISO_ASAP)
++		u |= URB_ISO_ASAP;
++	if (uurb->flags & USBDEVFS_URB_SHORT_NOT_OK)
++		u |= URB_SHORT_NOT_OK;
++	if (uurb->flags & USBDEVFS_URB_NO_FSBR)
++		u |= URB_NO_FSBR;
++	if (uurb->flags & USBDEVFS_URB_ZERO_PACKET)
++		u |= URB_ZERO_PACKET;
++	if (uurb->flags & USBDEVFS_URB_NO_INTERRUPT)
++		u |= URB_NO_INTERRUPT;
++	as->urb->transfer_flags = u;
++
+ 	as->urb->transfer_buffer_length = uurb->buffer_length;
+ 	as->urb->setup_packet = (unsigned char *)dr;
+ 	as->urb->start_frame = uurb->start_frame;
+diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
+index 17cb108b7db0..3118ede2c67b 100644
+--- a/include/linux/usbdevice_fs.h
++++ b/include/linux/usbdevice_fs.h
+@@ -77,8 +77,11 @@ struct usbdevfs_connectinfo {
+ 	unsigned char slow;
+ };
+ 
+-#define USBDEVFS_URB_SHORT_NOT_OK          1
+-#define USBDEVFS_URB_ISO_ASAP              2
++#define USBDEVFS_URB_SHORT_NOT_OK	0x01
++#define USBDEVFS_URB_ISO_ASAP		0x02
++#define USBDEVFS_URB_NO_FSBR		0x20
++#define USBDEVFS_URB_ZERO_PACKET	0x40
++#define USBDEVFS_URB_NO_INTERRUPT	0x80
+ 
+ #define USBDEVFS_URB_TYPE_ISO		   0
+ #define USBDEVFS_URB_TYPE_INTERRUPT	   1

commit aff6d18f95bb81b2d07994372c8edcc2c2b41180
+Author: Alan Stern 
+Date:   Fri Apr 18 11:11:26 2008 -0400
+
+    USB: fix compile problems in ehci-hcd
+    
+    This patch (as1072) fixes some recently-introduced compile problems
+    that show up in ehci-hcd when CONFIG_PM is turned off.
+    
+            PORT_WAKE_BITS needs to be defined always.
+    
+            ehci_port_power() is called during initialization by all the
+            EHCI variants other than the PCI version, in which it is
+            "defined but not used".  So add a call to it.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 536b433d24f7..efffef64f59d 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -28,10 +28,10 @@
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-#ifdef	CONFIG_PM
+-
+ #define	PORT_WAKE_BITS	(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
+ 
++#ifdef	CONFIG_PM
++
+ static int ehci_hub_control(
+ 	struct usb_hcd	*hcd,
+ 	u16		typeReq,
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index 88dad4b53131..5bb7f6bb13f3 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -222,6 +222,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 		ehci_warn(ehci, "selective suspend/wakeup unavailable\n");
+ #endif
+ 
++	ehci_port_power(ehci, 1);
+ 	retval = ehci_pci_reinit(ehci, pdev);
+ done:
+ 	return retval;

commit e872154921a6b5256a3c412dd69158ac0b135176
+Author: Alan Stern 
+Date:   Mon Apr 14 12:17:56 2008 -0400
+
+    USB: don't explicitly reenable root-hub status interrupts
+    
+    This patch (as1069b) changes the way OHCI root-hub status-change
+    interrupts are enabled.  Currently a special HCD method,
+    hub_irq_enable(), is called when the hub driver is finished using a
+    root hub.  This approach turns out to be subject to races, resulting
+    in unnecessary polling.
+    
+    The patch does away with the method entirely.  Instead, the driver
+    automatically enables the RHSC interrupt when no more status changes
+    are present.  This scheme is safe with controllers using
+    level-triggered semantics for their interrupt flags.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index e68fef5361d2..bf10e9c4195e 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -924,15 +924,6 @@ static int register_root_hub(struct usb_hcd *hcd)
+ 	return retval;
+ }
+ 
+-void usb_enable_root_hub_irq (struct usb_bus *bus)
+-{
+-	struct usb_hcd *hcd;
+-
+-	hcd = container_of (bus, struct usb_hcd, self);
+-	if (hcd->driver->hub_irq_enable && hcd->state != HC_STATE_HALT)
+-		hcd->driver->hub_irq_enable (hcd);
+-}
+-
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index 3ba258eb05de..1e4b81e9eb50 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -210,8 +210,6 @@ struct hc_driver {
+ 	int	(*bus_suspend)(struct usb_hcd *);
+ 	int	(*bus_resume)(struct usb_hcd *);
+ 	int	(*start_port_reset)(struct usb_hcd *, unsigned port_num);
+-	void	(*hub_irq_enable)(struct usb_hcd *);
+-		/* Needed only if port-change IRQs are level-triggered */
+ 
+ 		/* force handover of high-speed port to full-speed companion */
+ 	void	(*relinquish_port)(struct usb_hcd *, int);
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 1e23e360ea91..5a338a5d4fe7 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2001,8 +2001,6 @@ int usb_port_resume(struct usb_device *udev)
+ 	}
+ 
+ 	clear_bit(port1, hub->busy_bits);
+-	if (!hub->hdev->parent && !hub->busy_bits[0])
+-		usb_enable_root_hub_irq(hub->hdev->bus);
+ 
+ 	if (status == 0)
+ 		status = finish_port_resume(udev);
+@@ -2918,11 +2916,6 @@ static void hub_events(void)
+ 
+ 		hub->activating = 0;
+ 
+-		/* If this is a root hub, tell the HCD it's okay to
+-		 * re-enable port-change interrupts now. */
+-		if (!hdev->parent && !hub->busy_bits[0])
+-			usb_enable_root_hub_irq(hdev->bus);
+-
+ loop_autopm:
+ 		/* Allow autosuspend if we're not going to run again */
+ 		if (list_empty(&hub->event_list))
+@@ -3148,8 +3141,6 @@ int usb_reset_device(struct usb_device *udev)
+ 			break;
+ 	}
+ 	clear_bit(port1, parent_hub->busy_bits);
+-	if (!parent_hdev->parent && !parent_hub->busy_bits[0])
+-		usb_enable_root_hub_irq(parent_hdev->bus);
+ 
+ 	if (ret < 0)
+ 		goto re_enumerate;
+diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
+index e534f9de0f05..c96db1153dcf 100644
+--- a/drivers/usb/host/ohci-at91.c
++++ b/drivers/usb/host/ohci-at91.c
+@@ -261,7 +261,6 @@ static const struct hc_driver ohci_at91_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
+index f90fe0c7373f..1b9abdba920b 100644
+--- a/drivers/usb/host/ohci-au1xxx.c
++++ b/drivers/usb/host/ohci-au1xxx.c
+@@ -288,7 +288,6 @@ static const struct hc_driver ohci_au1xxx_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
+index 5adaf36e47d0..06aadfb0ec29 100644
+--- a/drivers/usb/host/ohci-ep93xx.c
++++ b/drivers/usb/host/ohci-ep93xx.c
+@@ -135,7 +135,6 @@ static struct hc_driver ohci_ep93xx_hc_driver = {
+ 	.get_frame_number	= ohci_get_frame,
+ 	.hub_status_data	= ohci_hub_status_data,
+ 	.hub_control		= ohci_hub_control,
+-	.hub_irq_enable		= ohci_rhsc_enable,
+ #ifdef CONFIG_PM
+ 	.bus_suspend		= ohci_bus_suspend,
+ 	.bus_resume		= ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index 355a82f25274..5be3bb3e6a9d 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -36,18 +36,6 @@
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-/* hcd->hub_irq_enable() */
+-static void ohci_rhsc_enable (struct usb_hcd *hcd)
+-{
+-	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+-
+-	spin_lock_irq(&ohci->lock);
+-	if (!ohci->autostop)
+-		del_timer(&hcd->rh_timer);	/* Prevent next poll */
+-	ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
+-	spin_unlock_irq(&ohci->lock);
+-}
+-
+ #define OHCI_SCHED_ENABLES \
+ 	(OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
+ 
+@@ -374,18 +362,28 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ 		int any_connected)
+ {
+ 	int	poll_rh = 1;
++	int	rhsc;
+ 
++	rhsc = ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC;
+ 	switch (ohci->hc_control & OHCI_CTRL_HCFS) {
+ 
+ 	case OHCI_USB_OPER:
+-		/* keep on polling until we know a device is connected
+-		 * and RHSC is enabled */
++		/* If no status changes are pending, enable status-change
++		 * interrupts.
++		 */
++		if (!rhsc && !changed) {
++			rhsc = OHCI_INTR_RHSC;
++			ohci_writel(ohci, rhsc, &ohci->regs->intrenable);
++		}
++
++		/* Keep on polling until we know a device is connected
++		 * and RHSC is enabled, or until we autostop.
++		 */
+ 		if (!ohci->autostop) {
+ 			if (any_connected ||
+ 					!device_may_wakeup(&ohci_to_hcd(ohci)
+ 						->self.root_hub->dev)) {
+-				if (ohci_readl(ohci, &ohci->regs->intrenable) &
+-						OHCI_INTR_RHSC)
++				if (rhsc)
+ 					poll_rh = 0;
+ 			} else {
+ 				ohci->autostop = 1;
+@@ -398,12 +396,13 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ 				ohci->autostop = 0;
+ 				ohci->next_statechange = jiffies +
+ 						STATECHANGE_DELAY;
+-			} else if (time_after_eq(jiffies,
++			} else if (rhsc && time_after_eq(jiffies,
+ 						ohci->next_statechange)
+ 					&& !ohci->ed_rm_list
+ 					&& !(ohci->hc_control &
+ 						OHCI_SCHED_ENABLES)) {
+ 				ohci_rh_suspend(ohci, 1);
++				poll_rh = 0;
+ 			}
+ 		}
+ 		break;
+@@ -417,6 +416,12 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ 			else
+ 				usb_hcd_resume_root_hub(ohci_to_hcd(ohci));
+ 		} else {
++			if (!rhsc && (ohci->autostop ||
++					ohci_to_hcd(ohci)->self.root_hub->
++						do_remote_wakeup))
++				ohci_writel(ohci, OHCI_INTR_RHSC,
++						&ohci->regs->intrenable);
++
+ 			/* everything is idle, no need for polling */
+ 			poll_rh = 0;
+ 		}
+@@ -438,12 +443,16 @@ static inline int ohci_rh_resume(struct ohci_hcd *ohci)
+ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ 		int any_connected)
+ {
+-	int	poll_rh = 1;
+-
+-	/* keep on polling until RHSC is enabled */
++	/* If RHSC is enabled, don't poll */
+ 	if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC)
+-		poll_rh = 0;
+-	return poll_rh;
++		return 0;
++
++	/* If no status changes are pending, enable status-change interrupts */
++	if (!changed) {
++		ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
++		return 0;
++	}
++	return 1;
+ }
+ 
+ #endif	/* CONFIG_PM */
+diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c
+index 13c12ed22252..96d14fa1d833 100644
+--- a/drivers/usb/host/ohci-lh7a404.c
++++ b/drivers/usb/host/ohci-lh7a404.c
+@@ -193,7 +193,6 @@ static const struct hc_driver ohci_lh7a404_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
+index 3a7c24c03671..6859fb5f1d6f 100644
+--- a/drivers/usb/host/ohci-omap.c
++++ b/drivers/usb/host/ohci-omap.c
+@@ -466,7 +466,6 @@ static const struct hc_driver ohci_omap_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index 4696cc912e16..3bf175d95a23 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -327,7 +327,6 @@ static const struct hc_driver ohci_pci_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c
+index 28b458f20cc3..664f07ee8732 100644
+--- a/drivers/usb/host/ohci-pnx4008.c
++++ b/drivers/usb/host/ohci-pnx4008.c
+@@ -280,7 +280,6 @@ static const struct hc_driver ohci_pnx4008_hc_driver = {
+ 	 */
+ 	.hub_status_data = ohci_hub_status_data,
+ 	.hub_control = ohci_hub_control,
+-	.hub_irq_enable = ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend = ohci_bus_suspend,
+ 	.bus_resume = ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-pnx8550.c b/drivers/usb/host/ohci-pnx8550.c
+index 605d59cba28e..28467e288a93 100644
+--- a/drivers/usb/host/ohci-pnx8550.c
++++ b/drivers/usb/host/ohci-pnx8550.c
+@@ -201,7 +201,6 @@ static const struct hc_driver ohci_pnx8550_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
+index a67252791223..50e55db13636 100644
+--- a/drivers/usb/host/ohci-ppc-of.c
++++ b/drivers/usb/host/ohci-ppc-of.c
+@@ -72,7 +72,6 @@ static const struct hc_driver ohci_ppc_of_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
+index 523c30125577..cd3398b675b2 100644
+--- a/drivers/usb/host/ohci-ppc-soc.c
++++ b/drivers/usb/host/ohci-ppc-soc.c
+@@ -172,7 +172,6 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c
+index c1935ae537f8..bfdeb0d22d05 100644
+--- a/drivers/usb/host/ohci-ps3.c
++++ b/drivers/usb/host/ohci-ps3.c
+@@ -68,7 +68,6 @@ static const struct hc_driver ps3_ohci_hc_driver = {
+ 	.get_frame_number	= ohci_get_frame,
+ 	.hub_status_data	= ohci_hub_status_data,
+ 	.hub_control		= ohci_hub_control,
+-	.hub_irq_enable		= ohci_rhsc_enable,
+ 	.start_port_reset	= ohci_start_port_reset,
+ #if defined(CONFIG_PM)
+ 	.bus_suspend 		= ohci_bus_suspend,
+diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
+index d4ee27d92be8..70b0d4b459e7 100644
+--- a/drivers/usb/host/ohci-pxa27x.c
++++ b/drivers/usb/host/ohci-pxa27x.c
+@@ -298,7 +298,6 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef  CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
+index ead4772f0f27..a73d2ff322e2 100644
+--- a/drivers/usb/host/ohci-s3c2410.c
++++ b/drivers/usb/host/ohci-s3c2410.c
+@@ -466,7 +466,6 @@ static const struct hc_driver ohci_s3c2410_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_s3c2410_hub_status_data,
+ 	.hub_control =		ohci_s3c2410_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
+index 0f48f2d99226..99438c65981b 100644
+--- a/drivers/usb/host/ohci-sa1111.c
++++ b/drivers/usb/host/ohci-sa1111.c
+@@ -231,7 +231,6 @@ static const struct hc_driver ohci_sa1111_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c
+index e7ee607278fe..60f03cc7ec4f 100644
+--- a/drivers/usb/host/ohci-sh.c
++++ b/drivers/usb/host/ohci-sh.c
+@@ -68,7 +68,6 @@ static const struct hc_driver ohci_sh_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c
+index 4a11e1816017..77204f001b9a 100644
+--- a/drivers/usb/host/ohci-sm501.c
++++ b/drivers/usb/host/ohci-sm501.c
+@@ -75,7 +75,6 @@ static const struct hc_driver ohci_sm501_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c
+index 7275186db315..c4265caec780 100644
+--- a/drivers/usb/host/ohci-ssb.c
++++ b/drivers/usb/host/ohci-ssb.c
+@@ -81,7 +81,6 @@ static const struct hc_driver ssb_ohci_hc_driver = {
+ 
+ 	.hub_status_data	= ohci_hub_status_data,
+ 	.hub_control		= ohci_hub_control,
+-	.hub_irq_enable		= ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend		= ohci_bus_suspend,
+ 	.bus_resume		= ohci_bus_resume,
+diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
+index 9b6323f768b2..f29307405bb3 100644
+--- a/drivers/usb/host/u132-hcd.c
++++ b/drivers/usb/host/u132-hcd.c
+@@ -2934,16 +2934,6 @@ static int u132_start_port_reset(struct usb_hcd *hcd, unsigned port_num)
+ 		return 0;
+ }
+ 
+-static void u132_hub_irq_enable(struct usb_hcd *hcd)
+-{
+-	struct u132 *u132 = hcd_to_u132(hcd);
+-	if (u132->going > 1) {
+-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-			, u132->going);
+-	} else if (u132->going > 0)
+-		dev_err(&u132->platform_dev->dev, "device is being removed\n");
+-}
+-
+ 
+ #ifdef CONFIG_PM
+ static int u132_bus_suspend(struct usb_hcd *hcd)
+@@ -2995,7 +2985,6 @@ static struct hc_driver u132_hc_driver = {
+ 	.bus_suspend = u132_bus_suspend,
+ 	.bus_resume = u132_bus_resume,
+ 	.start_port_reset = u132_start_port_reset,
+-	.hub_irq_enable = u132_hub_irq_enable,
+ };
+ 
+ /*

commit 5f47493cdf90b8afe5353e59de30e449e775ea8b
+Author: Alan Stern 
+Date:   Mon Apr 14 12:17:49 2008 -0400
+
+    USB: OHCI: turn off RD when remote wakeup is disabled
+    
+    This patch (as1068b) disables the RD interrupt flag when an OHCI root
+    hub is suspended with remote wakeup disabled.  Although the spec
+    clearly states that this flag permits the controller to issue an
+    interrupt when a resume request from downstream is detected and not
+    when a local status change occurs, some controllers mistakenly use it
+    for both types of event.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index cf3e1d255639..355a82f25274 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -106,7 +106,8 @@ __acquires(ohci->lock)
+ 	if (ohci_to_hcd(ohci)->self.root_hub->do_remote_wakeup || autostop) {
+ 		ohci->hc_control |= OHCI_CTRL_RWE;
+ 	} else {
+-		ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable);
++		ohci_writel(ohci, OHCI_INTR_RHSC | OHCI_INTR_RD,
++				&ohci->regs->intrdisable);
+ 		ohci->hc_control &= ~OHCI_CTRL_RWE;
+ 	}
+ 

commit 58a97ffeb2297f154659f339d77eb3f32c4d8b3e
+Author: Alan Stern 
+Date:   Mon Apr 14 12:17:10 2008 -0400
+
+    USB: HCDs use the do_remote_wakeup flag
+    
+    When a USB device is suspended, whether or not it is enabled for
+    remote wakeup depends on the device_may_wakeup() setting.  The setting
+    is then saved in the do_remote_wakeup flag.
+    
+    Later on, however, the device_may_wakeup() value can change because of
+    user activity.  So when testing whether a suspended device is or
+    should be enabled for remote wakeup, we should always test
+    do_remote_wakeup instead of device_may_wakeup().  This patch (as1076)
+    makes that change for root hubs in several places.
+    
+    The patch also adjusts uhci-hcd so that when an autostopped controller
+    is suspended, the remote wakeup setting agrees with the value recorded
+    in the root hub's do_remote_wakeup flag.
+    
+    And the patch adjusts ehci-hcd so that wakeup events on selectively
+    suspended ports (i.e., the bus itself isn't suspended) don't turn on
+    the PME# wakeup signal.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 2ea333a43d65..edc31e13e95e 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -932,7 +932,6 @@ static int autosuspend_check(struct usb_device *udev, int reschedule)
+ 	 * is disabled.  Also fail if any interfaces require remote wakeup
+ 	 * but it isn't available.
+ 	 */
+-	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
+ 	if (udev->pm_usage_cnt > 0)
+ 		return -EBUSY;
+ 	if (udev->autosuspend_delay < 0 || udev->autosuspend_disabled)
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 21ac3781f21a..536b433d24f7 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -30,6 +30,8 @@
+ 
+ #ifdef	CONFIG_PM
+ 
++#define	PORT_WAKE_BITS	(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
++
+ static int ehci_hub_control(
+ 	struct usb_hcd	*hcd,
+ 	u16		typeReq,
+@@ -149,10 +151,10 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 		}
+ 
+ 		/* enable remote wakeup on all ports */
+-		if (device_may_wakeup(&hcd->self.root_hub->dev))
+-			t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E;
++		if (hcd->self.root_hub->do_remote_wakeup)
++			t2 |= PORT_WAKE_BITS;
+ 		else
+-			t2 &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E);
++			t2 &= ~PORT_WAKE_BITS;
+ 
+ 		if (t1 != t2) {
+ 			ehci_vdbg (ehci, "port %d, %08x -> %08x\n",
+@@ -174,7 +176,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 
+ 	/* allow remote wakeup */
+ 	mask = INTR_MASK;
+-	if (!device_may_wakeup(&hcd->self.root_hub->dev))
++	if (!hcd->self.root_hub->do_remote_wakeup)
+ 		mask &= ~STS_PCD;
+ 	ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+ 	ehci_readl(ehci, &ehci->regs->intr_enable);
+@@ -232,8 +234,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 	i = HCS_N_PORTS (ehci->hcs_params);
+ 	while (i--) {
+ 		temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
+-		temp &= ~(PORT_RWC_BITS
+-			| PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E);
++		temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
+ 		if (test_bit(i, &ehci->bus_suspended) &&
+ 				(temp & PORT_SUSPEND)) {
+ 			ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
+@@ -534,8 +535,6 @@ ehci_hub_descriptor (
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-#define	PORT_WAKE_BITS	(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
+-
+ static int ehci_hub_control (
+ 	struct usb_hcd	*hcd,
+ 	u16		typeReq,
+@@ -801,8 +800,6 @@ static int ehci_hub_control (
+ 			if ((temp & PORT_PE) == 0
+ 					|| (temp & PORT_RESET) != 0)
+ 				goto error;
+-			if (device_may_wakeup(&hcd->self.root_hub->dev))
+-				temp |= PORT_WAKE_BITS;
+ 			ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
+ 			break;
+ 		case USB_PORT_FEAT_POWER:
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index a0afc78b273e..88dad4b53131 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -300,7 +300,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
+ 	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
+ 		int	mask = INTR_MASK;
+ 
+-		if (!device_may_wakeup(&hcd->self.root_hub->dev))
++		if (!hcd->self.root_hub->do_remote_wakeup)
+ 			mask &= ~STS_PCD;
+ 		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+ 		ehci_readl(ehci, &ehci->regs->intr_enable);
+diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
+index 66d773c726f6..20b9a0d07420 100644
+--- a/drivers/usb/host/isp116x-hcd.c
++++ b/drivers/usb/host/isp116x-hcd.c
+@@ -1400,7 +1400,7 @@ static int isp116x_bus_suspend(struct usb_hcd *hcd)
+ 		spin_unlock_irqrestore(&isp116x->lock, flags);
+ 		val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE);
+ 		val |= HCCONTROL_USB_SUSPEND;
+-		if (device_may_wakeup(&hcd->self.root_hub->dev))
++		if (hcd->self.root_hub->do_remote_wakeup)
+ 			val |= HCCONTROL_RWE;
+ 		/* Wait for usb transfers to finish */
+ 		msleep(2);
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index 28d6d775eb5f..cf3e1d255639 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -103,10 +103,9 @@ __acquires(ohci->lock)
+ 	finish_unlinks (ohci, ohci_frame_no(ohci));
+ 
+ 	/* maybe resume can wake root hub */
+-	if (device_may_wakeup(&ohci_to_hcd(ohci)->self.root_hub->dev) ||
+-			autostop)
++	if (ohci_to_hcd(ohci)->self.root_hub->do_remote_wakeup || autostop) {
+ 		ohci->hc_control |= OHCI_CTRL_RWE;
+-	else {
++	} else {
+ 		ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable);
+ 		ohci->hc_control &= ~OHCI_CTRL_RWE;
+ 	}
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index fec9872dd9dc..f65d5a858733 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -262,20 +262,12 @@ __acquires(uhci->lock)
+ {
+ 	int auto_stop;
+ 	int int_enable, egsm_enable;
++	struct usb_device *rhdev = uhci_to_hcd(uhci)->self.root_hub;
+ 
+ 	auto_stop = (new_state == UHCI_RH_AUTO_STOPPED);
+-	dev_dbg(&uhci_to_hcd(uhci)->self.root_hub->dev,
+-			"%s%s\n", __FUNCTION__,
++	dev_dbg(&rhdev->dev, "%s%s\n", __func__,
+ 			(auto_stop ? " (auto-stop)" : ""));
+ 
+-	/* If we get a suspend request when we're already auto-stopped
+-	 * then there's nothing to do.
+-	 */
+-	if (uhci->rh_state == UHCI_RH_AUTO_STOPPED) {
+-		uhci->rh_state = new_state;
+-		return;
+-	}
+-
+ 	/* Enable resume-detect interrupts if they work.
+ 	 * Then enter Global Suspend mode if _it_ works, still configured.
+ 	 */
+@@ -285,8 +277,10 @@ __acquires(uhci->lock)
+ 	if (remote_wakeup_is_broken(uhci))
+ 		egsm_enable = 0;
+ 	if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable ||
+-			!device_may_wakeup(
+-				&uhci_to_hcd(uhci)->self.root_hub->dev))
++#ifdef CONFIG_PM
++			(!auto_stop && !rhdev->do_remote_wakeup) ||
++#endif
++			(auto_stop && !device_may_wakeup(&rhdev->dev)))
+ 		uhci->working_RD = int_enable = 0;
+ 
+ 	outw(int_enable, uhci->io_addr + USBINTR);
+@@ -308,8 +302,7 @@ __acquires(uhci->lock)
+ 			return;
+ 	}
+ 	if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH))
+-		dev_warn(&uhci_to_hcd(uhci)->self.root_hub->dev,
+-			"Controller not stopped yet!\n");
++		dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n");
+ 
+ 	uhci_get_current_frame_number(uhci);
+ 

commit b950bdbc67041412cb042e404938667204c7902c
+Author: Alan Stern 
+Date:   Mon Apr 14 11:45:29 2008 -0400
+
+    USB: g_file_storage: ignore bulk-out data after invalid CBW
+    
+    This patch (as1061) makes g_file_storage more compliant with the
+    Bulk-Only Transport specification.  After an invalid CBW is received,
+    the gadget must ignore any further bulk-OUT data until it is reset.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index 017a196d041f..0a726e106ccd 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -644,7 +644,7 @@ struct fsg_dev {
+ 
+ 	unsigned long		atomic_bitflags;
+ #define REGISTERED		0
+-#define CLEAR_BULK_HALTS	1
++#define IGNORE_BULK_OUT		1
+ #define SUSPENDED		2
+ 
+ 	struct usb_ep		*bulk_in;
+@@ -2936,8 +2936,8 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
+ 	struct usb_request	*req = bh->outreq;
+ 	struct bulk_cb_wrap	*cbw = req->buf;
+ 
+-	/* Was this a real packet? */
+-	if (req->status)
++	/* Was this a real packet?  Should it be ignored? */
++	if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
+ 		return -EINVAL;
+ 
+ 	/* Is the CBW valid? */
+@@ -2948,13 +2948,17 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
+ 				req->actual,
+ 				le32_to_cpu(cbw->Signature));
+ 
+-		/* The Bulk-only spec says we MUST stall the bulk pipes!
+-		 * If we want to avoid stalls, set a flag so that we will
+-		 * clear the endpoint halts at the next reset. */
+-		if (!mod_data.can_stall)
+-			set_bit(CLEAR_BULK_HALTS, &fsg->atomic_bitflags);
+-		fsg_set_halt(fsg, fsg->bulk_out);
++		/* The Bulk-only spec says we MUST stall the IN endpoint
++		 * (6.6.1), so it's unavoidable.  It also says we must
++		 * retain this state until the next reset, but there's
++		 * no way to tell the controller driver it should ignore
++		 * Clear-Feature(HALT) requests.
++		 *
++		 * We aren't required to halt the OUT endpoint; instead
++		 * we can simply accept and discard any data received
++		 * until the next reset. */
+ 		halt_bulk_in_endpoint(fsg);
++		set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -3140,6 +3144,7 @@ static int do_set_interface(struct fsg_dev *fsg, int altsetting)
+ 		goto reset;
+ 	fsg->bulk_out_enabled = 1;
+ 	fsg->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize);
++	clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
+ 
+ 	if (transport_is_cbi()) {
+ 		d = ep_desc(fsg->gadget, &fs_intr_in_desc, &hs_intr_in_desc);
+@@ -3321,11 +3326,8 @@ static void handle_exception(struct fsg_dev *fsg)
+ 		/* In case we were forced against our will to halt a
+ 		 * bulk endpoint, clear the halt now.  (The SuperH UDC
+ 		 * requires this.) */
+-		if (test_and_clear_bit(CLEAR_BULK_HALTS,
+-				&fsg->atomic_bitflags)) {
++		if (test_and_clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
+ 			usb_ep_clear_halt(fsg->bulk_in);
+-			usb_ep_clear_halt(fsg->bulk_out);
+-		}
+ 
+ 		if (transport_is_bbb()) {
+ 			if (fsg->ep0_req_tag == exception_req_tag)

commit 6427f7995338387ddded92f98adec19ddbf0ae5e
+Author: Alan Stern 
+Date:   Thu Apr 10 12:45:34 2008 -0400
+
+    USB: log an error message when USB enumeration fails
+    
+    This patch (as1077) logs an error message whenever the kernel is
+    unable to enumerate a new USB device.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 9fc5179dfc60..1e23e360ea91 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2708,6 +2708,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 		if ((status == -ENOTCONN) || (status == -ENOTSUPP))
+ 			break;
+ 	}
++	dev_err(hub_dev, "unable to enumerate USB device on port %d\n", port1);
+  
+ done:
+ 	hub_port_disable(hub, port1, 1);

commit a89a2cd396b20c46a37fa8db4b652fb00f29d0a4
+Author: Alan Stern 
+Date:   Mon Apr 7 15:03:25 2008 -0400
+
+    USB: dummy-hcd: use dynamic allocation for platform_devices
+    
+    This patch (as1075) changes dummy-hcd to dynamically allocate its
+    platform_device structures, using the core platform_device_alloc()
+    interface.  This is what it should have done all along, because the
+    dynamically-allocated structures have a release method in the driver
+    core and are therefore immune to being released after the module has
+    been unloaded.
+    
+    Thanks to Richard Purdie for pointing out the need for this change.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Richard Purdie 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index 433f8c47cce5..74f51a703b42 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -1933,69 +1933,57 @@ static struct platform_driver dummy_hcd_driver = {
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-/* These don't need to do anything because the pdev structures are
+- * statically allocated. */
+-static void
+-dummy_udc_release (struct device *dev) {}
+-
+-static void
+-dummy_hcd_release (struct device *dev) {}
+-
+-static struct platform_device		the_udc_pdev = {
+-	.name		= (char *) gadget_name,
+-	.id		= -1,
+-	.dev		= {
+-		.release	= dummy_udc_release,
+-	},
+-};
+-
+-static struct platform_device		the_hcd_pdev = {
+-	.name		= (char *) driver_name,
+-	.id		= -1,
+-	.dev		= {
+-		.release	= dummy_hcd_release,
+-	},
+-};
++static struct platform_device *the_udc_pdev;
++static struct platform_device *the_hcd_pdev;
+ 
+ static int __init init (void)
+ {
+-	int	retval;
++	int	retval = -ENOMEM;
+ 
+ 	if (usb_disabled ())
+ 		return -ENODEV;
+ 
+-	retval = platform_driver_register (&dummy_hcd_driver);
+-	if (retval < 0)
++	the_hcd_pdev = platform_device_alloc(driver_name, -1);
++	if (!the_hcd_pdev)
+ 		return retval;
++	the_udc_pdev = platform_device_alloc(gadget_name, -1);
++	if (!the_udc_pdev)
++		goto err_alloc_udc;
+ 
+-	retval = platform_driver_register (&dummy_udc_driver);
++	retval = platform_driver_register(&dummy_hcd_driver);
++	if (retval < 0)
++		goto err_register_hcd_driver;
++	retval = platform_driver_register(&dummy_udc_driver);
+ 	if (retval < 0)
+ 		goto err_register_udc_driver;
+ 
+-	retval = platform_device_register (&the_hcd_pdev);
++	retval = platform_device_add(the_hcd_pdev);
+ 	if (retval < 0)
+-		goto err_register_hcd;
+-
+-	retval = platform_device_register (&the_udc_pdev);
++		goto err_add_hcd;
++	retval = platform_device_add(the_udc_pdev);
+ 	if (retval < 0)
+-		goto err_register_udc;
++		goto err_add_udc;
+ 	return retval;
+ 
+-err_register_udc:
+-	platform_device_unregister (&the_hcd_pdev);
+-err_register_hcd:
+-	platform_driver_unregister (&dummy_udc_driver);
++err_add_udc:
++	platform_device_del(the_hcd_pdev);
++err_add_hcd:
++	platform_driver_unregister(&dummy_udc_driver);
+ err_register_udc_driver:
+-	platform_driver_unregister (&dummy_hcd_driver);
++	platform_driver_unregister(&dummy_hcd_driver);
++err_register_hcd_driver:
++	platform_device_put(the_udc_pdev);
++err_alloc_udc:
++	platform_device_put(the_hcd_pdev);
+ 	return retval;
+ }
+ module_init (init);
+ 
+ static void __exit cleanup (void)
+ {
+-	platform_device_unregister (&the_udc_pdev);
+-	platform_device_unregister (&the_hcd_pdev);
+-	platform_driver_unregister (&dummy_udc_driver);
+-	platform_driver_unregister (&dummy_hcd_driver);
++	platform_device_unregister(the_udc_pdev);
++	platform_device_unregister(the_hcd_pdev);
++	platform_driver_unregister(&dummy_udc_driver);
++	platform_driver_unregister(&dummy_hcd_driver);
+ }
+ module_exit (cleanup);

commit 61a5c657892a43653d6189972159590751a0673e
+Author: Alan Stern 
+Date:   Fri Apr 4 23:46:59 2008 -0400
+
+    USB: rework sysfs removal of interface files
+    
+    Removing an interface's sysfs files before unregistering the interface
+    doesn't work properly, because usb_unbind_interface() will reinstall
+    altsetting 0 and thereby create new sysfs files.  This patch (as1074)
+    removes the files after the unregistration is finished.  It's not
+    quite as clean, but at least it works.
+    
+    Also, there's no need to check if an interface has been registered
+    before removing its sysfs files.  If it hasn't been registered then
+    the files won't have been created, so usb_remove_sysfs_intf_files()
+    will simply do nothing.
+    
+    Signed-off-by: Alan Stern 
+    Tested-by: Jiri Slaby 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index a3695b5115ff..5b23f6b017d7 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1089,8 +1089,8 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
+ 				continue;
+ 			dev_dbg(&dev->dev, "unregistering interface %s\n",
+ 				interface->dev.bus_id);
+-			usb_remove_sysfs_intf_files(interface);
+ 			device_del(&interface->dev);
++			usb_remove_sysfs_intf_files(interface);
+ 		}
+ 
+ 		/* Now that the interfaces are unbound, nobody should
+@@ -1231,7 +1231,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
+ 	 */
+ 
+ 	/* prevent submissions using previous endpoint settings */
+-	if (iface->cur_altsetting != alt && device_is_registered(&iface->dev))
++	if (iface->cur_altsetting != alt)
+ 		usb_remove_sysfs_intf_files(iface);
+ 	usb_disable_interface(dev, iface);
+ 
+@@ -1330,8 +1330,7 @@ int usb_reset_configuration(struct usb_device *dev)
+ 		struct usb_interface *intf = config->interface[i];
+ 		struct usb_host_interface *alt;
+ 
+-		if (device_is_registered(&intf->dev))
+-			usb_remove_sysfs_intf_files(intf);
++		usb_remove_sysfs_intf_files(intf);
+ 		alt = usb_altnum_to_altsetting(intf, 0);
+ 
+ 		/* No altsetting 0?  We'll assume the first altsetting.

commit 43bbb7e015c4380064796c5868b536437b165615
+Author: Alan Stern 
+Date:   Thu Apr 3 18:03:17 2008 -0400
+
+    USB: OHCI: host-controller resumes leave root hub suspended
+    
+    Drivers in the ohci-hcd family should perform certain tasks whenever
+    their controller device is resumed.  These include checking for loss
+    of power during suspend, turning on port power, and enabling interrupt
+    requests.
+    
+    Until now these jobs have been carried out when the root hub is
+    resumed, not when the controller is.  Many drivers work around the
+    resulting awkwardness by automatically resuming their root hub
+    whenever the controller is resumed.  But this is wasteful and
+    unnecessary.
+    
+    To simplify the situation, this patch (as1066) adds a new core
+    routine, ohci_finish_controller_resume(), which can be used by all the
+    OHCI-variant drivers.  They can call the new routine instead of
+    resuming their root hubs.  And ohci-pci.c can call it instead of using
+    its own special-purpose handler.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
+index d72dc07dda01..e534f9de0f05 100644
+--- a/drivers/usb/host/ohci-at91.c
++++ b/drivers/usb/host/ohci-at91.c
+@@ -348,6 +348,7 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *pdev)
+ 	if (!clocked)
+ 		at91_start_clock();
+ 
++	ohci_finish_controller_resume(hcd);
+ 	return 0;
+ }
+ #else
+diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
+index 40c683f8987d..5adaf36e47d0 100644
+--- a/drivers/usb/host/ohci-ep93xx.c
++++ b/drivers/usb/host/ohci-ep93xx.c
+@@ -192,8 +192,8 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev)
+ 	ohci->next_statechange = jiffies;
+ 
+ 	ep93xx_start_hc(&pdev->dev);
+-	usb_hcd_resume_root_hub(hcd);
+ 
++	ohci_finish_controller_resume(hcd);
+ 	return 0;
+ }
+ #endif
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index c638e6b33c43..28d6d775eb5f 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -326,6 +326,49 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
+ 	return rc;
+ }
+ 
++/* Carry out the final steps of resuming the controller device */
++static void ohci_finish_controller_resume(struct usb_hcd *hcd)
++{
++	struct ohci_hcd		*ohci = hcd_to_ohci(hcd);
++	int			port;
++	bool			need_reinit = false;
++
++	/* See if the controller is already running or has been reset */
++	ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
++	if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
++		need_reinit = true;
++	} else {
++		switch (ohci->hc_control & OHCI_CTRL_HCFS) {
++		case OHCI_USB_OPER:
++		case OHCI_USB_RESET:
++			need_reinit = true;
++		}
++	}
++
++	/* If needed, reinitialize and suspend the root hub */
++	if (need_reinit) {
++		spin_lock_irq(&ohci->lock);
++		hcd->state = HC_STATE_RESUMING;
++		ohci_rh_resume(ohci);
++		hcd->state = HC_STATE_QUIESCING;
++		ohci_rh_suspend(ohci, 0);
++		hcd->state = HC_STATE_SUSPENDED;
++		spin_unlock_irq(&ohci->lock);
++	}
++
++	/* Normally just turn on port power and enable interrupts */
++	else {
++		ohci_dbg(ohci, "powerup ports\n");
++		for (port = 0; port < ohci->num_ports; port++)
++			ohci_writel(ohci, RH_PS_PPS,
++					&ohci->regs->roothub.portstatus[port]);
++
++		ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrenable);
++		ohci_readl(ohci, &ohci->regs->intrenable);
++		msleep(20);
++	}
++}
++
+ /* Carry out polling-, autostop-, and autoresume-related state changes */
+ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ 		int any_connected)
+diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
+index 2aafa7b6c81f..3a7c24c03671 100644
+--- a/drivers/usb/host/ohci-omap.c
++++ b/drivers/usb/host/ohci-omap.c
+@@ -510,14 +510,15 @@ static int ohci_omap_suspend(struct platform_device *dev, pm_message_t message)
+ 
+ static int ohci_omap_resume(struct platform_device *dev)
+ {
+-	struct ohci_hcd	*ohci = hcd_to_ohci(platform_get_drvdata(dev));
++	struct usb_hcd	*hcd = platform_get_drvdata(dev);
++	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+ 
+ 	if (time_before(jiffies, ohci->next_statechange))
+ 		msleep(5);
+ 	ohci->next_statechange = jiffies;
+ 
+ 	omap_ohci_clock_power(1);
+-	usb_hcd_resume_root_hub(platform_get_drvdata(dev));
++	ohci_finish_controller_resume(hcd);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index 40b62a35fd3c..4696cc912e16 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -238,42 +238,6 @@ static int __devinit ohci_pci_start (struct usb_hcd *hcd)
+ 	return ret;
+ }
+ 
+-#if	defined(CONFIG_USB_PERSIST) && (defined(CONFIG_USB_EHCI_HCD) || \
+-		defined(CONFIG_USB_EHCI_HCD_MODULE))
+-
+-/* Following a power loss, we must prepare to regain control of the ports
+- * we used to own.  This means turning on the port power before ehci-hcd
+- * tries to switch ownership.
+- *
+- * This isn't a 100% perfect solution.  On most systems the OHCI controllers
+- * lie at lower PCI addresses than the EHCI controller, so they will be
+- * discovered (and hence resumed) first.  But there is no guarantee things
+- * will always work this way.  If the EHCI controller is resumed first and
+- * the OHCI ports are unpowered, then the handover will fail.
+- */
+-static void prepare_for_handover(struct usb_hcd *hcd)
+-{
+-	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+-	int		port;
+-
+-	/* Here we "know" root ports should always stay powered */
+-	ohci_dbg(ohci, "powerup ports\n");
+-	for (port = 0; port < ohci->num_ports; port++)
+-		ohci_writel(ohci, RH_PS_PPS,
+-				&ohci->regs->roothub.portstatus[port]);
+-
+-	/* Flush those writes */
+-	ohci_readl(ohci, &ohci->regs->control);
+-	msleep(20);
+-}
+-
+-#else
+-
+-static inline void prepare_for_handover(struct usb_hcd *hcd)
+-{ }
+-
+-#endif	/* CONFIG_USB_PERSIST etc. */
+-
+ #ifdef	CONFIG_PM
+ 
+ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
+@@ -312,13 +276,8 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
+ 
+ static int ohci_pci_resume (struct usb_hcd *hcd)
+ {
+-	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+-
+ 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+-
+-	/* FIXME: we should try to detect loss of VBUS power here */
+-	prepare_for_handover(hcd);
+-	ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrenable);
++	ohci_finish_controller_resume(hcd);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
+index 5d470263eed8..d4ee27d92be8 100644
+--- a/drivers/usb/host/ohci-pxa27x.c
++++ b/drivers/usb/host/ohci-pxa27x.c
+@@ -356,8 +356,7 @@ static int ohci_hcd_pxa27x_drv_resume(struct platform_device *pdev)
+ 	if ((status = pxa27x_start_hc(&pdev->dev)) < 0)
+ 		return status;
+ 
+-	usb_hcd_resume_root_hub(hcd);
+-
++	ohci_finish_controller_resume(hcd);
+ 	return 0;
+ }
+ #endif
+diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c
+index 54b6ac2e3e4a..4a11e1816017 100644
+--- a/drivers/usb/host/ohci-sm501.c
++++ b/drivers/usb/host/ohci-sm501.c
+@@ -231,14 +231,15 @@ static int ohci_sm501_suspend(struct platform_device *pdev, pm_message_t msg)
+ static int ohci_sm501_resume(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+-	struct ohci_hcd	*ohci = hcd_to_ohci(platform_get_drvdata(pdev));
++	struct usb_hcd	*hcd = platform_get_drvdata(pdev);
++	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+ 
+ 	if (time_before(jiffies, ohci->next_statechange))
+ 		msleep(5);
+ 	ohci->next_statechange = jiffies;
+ 
+ 	sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 1);
+-	usb_hcd_resume_root_hub(platform_get_drvdata(pdev));
++	ohci_finish_controller_resume(hcd);
+ 	return 0;
+ }
+ #else
+diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c
+index 7879f2fdad84..7275186db315 100644
+--- a/drivers/usb/host/ohci-ssb.c
++++ b/drivers/usb/host/ohci-ssb.c
+@@ -189,6 +189,7 @@ static int ssb_ohci_resume(struct ssb_device *dev)
+ 
+ 	ssb_device_enable(dev, ohcidev->enable_flags);
+ 
++	ohci_finish_controller_resume(hcd);
+ 	return 0;
+ }
+ 

commit 7be7d7418776a41badce7ca00246e270d408e4b9
+Author: Alan Stern 
+Date:   Thu Apr 3 18:03:06 2008 -0400
+
+    USB: clarify usage of hcd->suspend/resume methods
+    
+    The .suspend and .resume method pointers in struct usb_hcd have not
+    been fully understood by host-controller driver writers.  They are
+    meant for use with PCI controllers; other platform-specific drivers
+    generally should not refer to them.
+    
+    To try and clarify matters, this patch (as1065) renames those methods
+    to .pci_suspend and .pci_resume.  It eliminates corresponding dead code
+    and bogus references in the ohci-ssb and u132-hcd drivers.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index 739407bb8492..5b87ae7f0a6a 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -215,9 +215,9 @@ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message)
+ 			hcd->state == HC_STATE_HALT))
+ 		return -EBUSY;
+ 
+-	if (hcd->driver->suspend) {
+-		retval = hcd->driver->suspend(hcd, message);
+-		suspend_report_result(hcd->driver->suspend, retval);
++	if (hcd->driver->pci_suspend) {
++		retval = hcd->driver->pci_suspend(hcd, message);
++		suspend_report_result(hcd->driver->pci_suspend, retval);
+ 		if (retval)
+ 			goto done;
+ 	}
+@@ -405,8 +405,8 @@ int usb_hcd_pci_resume(struct pci_dev *dev)
+ 
+ 	clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+ 
+-	if (hcd->driver->resume) {
+-		retval = hcd->driver->resume(hcd);
++	if (hcd->driver->pci_resume) {
++		retval = hcd->driver->pci_resume(hcd);
+ 		if (retval) {
+ 			dev_err(hcd->self.controller,
+ 				"PCI post-resume error %d!\n", retval);
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index e0e99471c3fc..3ba258eb05de 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -178,10 +178,10 @@ struct hc_driver {
+ 	 * a whole, not just the root hub; they're for PCI bus glue.
+ 	 */
+ 	/* called after suspending the hub, before entering D3 etc */
+-	int	(*suspend) (struct usb_hcd *hcd, pm_message_t message);
++	int	(*pci_suspend) (struct usb_hcd *hcd, pm_message_t message);
+ 
+ 	/* called after entering D0 (etc), before resuming the hub */
+-	int	(*resume) (struct usb_hcd *hcd);
++	int	(*pci_resume) (struct usb_hcd *hcd);
+ 
+ 	/* cleanly make HCD stop writing memory and doing I/O */
+ 	void	(*stop) (struct usb_hcd *hcd);
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index 7c8a2ccf78f1..a0afc78b273e 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -353,8 +353,8 @@ static const struct hc_driver ehci_pci_hc_driver = {
+ 	.reset =		ehci_pci_setup,
+ 	.start =		ehci_run,
+ #ifdef	CONFIG_PM
+-	.suspend =		ehci_pci_suspend,
+-	.resume =		ehci_pci_resume,
++	.pci_suspend =		ehci_pci_suspend,
++	.pci_resume =		ehci_pci_resume,
+ #endif
+ 	.stop =			ehci_stop,
+ 	.shutdown =		ehci_shutdown,
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index b0e2275755c8..40b62a35fd3c 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -347,9 +347,8 @@ static const struct hc_driver ohci_pci_hc_driver = {
+ 	.shutdown =		ohci_shutdown,
+ 
+ #ifdef	CONFIG_PM
+-	/* these suspend/resume entries are for upstream PCI glue ONLY */
+-	.suspend =		ohci_pci_suspend,
+-	.resume =		ohci_pci_resume,
++	.pci_suspend =		ohci_pci_suspend,
++	.pci_resume =		ohci_pci_resume,
+ #endif
+ 
+ 	/*
+diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c
+index 6e9c2d6db887..7879f2fdad84 100644
+--- a/drivers/usb/host/ohci-ssb.c
++++ b/drivers/usb/host/ohci-ssb.c
+@@ -60,36 +60,6 @@ static int ssb_ohci_start(struct usb_hcd *hcd)
+ 	return err;
+ }
+ 
+-#ifdef CONFIG_PM
+-static int ssb_ohci_hcd_suspend(struct usb_hcd *hcd, pm_message_t message)
+-{
+-	struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
+-	struct ohci_hcd *ohci = &ohcidev->ohci;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&ohci->lock, flags);
+-
+-	ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
+-	ohci_readl(ohci, &ohci->regs->intrdisable); /* commit write */
+-
+-	/* make sure snapshot being resumed re-enumerates everything */
+-	if (message.event == PM_EVENT_PRETHAW)
+-		ohci_usb_reset(ohci);
+-
+-	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+-
+-	spin_unlock_irqrestore(&ohci->lock, flags);
+-	return 0;
+-}
+-
+-static int ssb_ohci_hcd_resume(struct usb_hcd *hcd)
+-{
+-	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+-	usb_hcd_resume_root_hub(hcd);
+-	return 0;
+-}
+-#endif /* CONFIG_PM */
+-
+ static const struct hc_driver ssb_ohci_hc_driver = {
+ 	.description		= "ssb-usb-ohci",
+ 	.product_desc		= "SSB OHCI Controller",
+@@ -103,11 +73,6 @@ static const struct hc_driver ssb_ohci_hc_driver = {
+ 	.stop			= ohci_stop,
+ 	.shutdown		= ohci_shutdown,
+ 
+-#ifdef CONFIG_PM
+-	.suspend		= ssb_ohci_hcd_suspend,
+-	.resume			= ssb_ohci_hcd_resume,
+-#endif
+-
+ 	.urb_enqueue		= ohci_urb_enqueue,
+ 	.urb_dequeue		= ohci_urb_dequeue,
+ 	.endpoint_disable	= ohci_endpoint_disable,
+diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
+index 4616a880d89c..9b6323f768b2 100644
+--- a/drivers/usb/host/u132-hcd.c
++++ b/drivers/usb/host/u132-hcd.c
+@@ -2946,34 +2946,6 @@ static void u132_hub_irq_enable(struct usb_hcd *hcd)
+ 
+ 
+ #ifdef CONFIG_PM
+-static int u132_hcd_suspend(struct usb_hcd *hcd, pm_message_t message)
+-{
+-	struct u132 *u132 = hcd_to_u132(hcd);
+-	if (u132->going > 1) {
+-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-			, u132->going);
+-		return -ENODEV;
+-	} else if (u132->going > 0) {
+-		dev_err(&u132->platform_dev->dev, "device is being removed\n");
+-		return -ESHUTDOWN;
+-	} else
+-		return 0;
+-}
+-
+-static int u132_hcd_resume(struct usb_hcd *hcd)
+-{
+-	struct u132 *u132 = hcd_to_u132(hcd);
+-	if (u132->going > 1) {
+-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-			, u132->going);
+-		return -ENODEV;
+-	} else if (u132->going > 0) {
+-		dev_err(&u132->platform_dev->dev, "device is being removed\n");
+-		return -ESHUTDOWN;
+-	} else
+-		return 0;
+-}
+-
+ static int u132_bus_suspend(struct usb_hcd *hcd)
+ {
+ 	struct u132 *u132 = hcd_to_u132(hcd);
+@@ -3003,8 +2975,6 @@ static int u132_bus_resume(struct usb_hcd *hcd)
+ }
+ 
+ #else
+-#define u132_hcd_suspend NULL
+-#define u132_hcd_resume NULL
+ #define u132_bus_suspend NULL
+ #define u132_bus_resume NULL
+ #endif
+@@ -3015,8 +2985,6 @@ static struct hc_driver u132_hc_driver = {
+ 	.flags = HCD_USB11 | HCD_MEMORY,
+ 	.reset = u132_hcd_reset,
+ 	.start = u132_hcd_start,
+-	.suspend = u132_hcd_suspend,
+-	.resume = u132_hcd_resume,
+ 	.stop = u132_hcd_stop,
+ 	.urb_enqueue = u132_urb_enqueue,
+ 	.urb_dequeue = u132_urb_dequeue,
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index ec987897b8ed..fec9872dd9dc 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -737,7 +737,7 @@ static int uhci_rh_resume(struct usb_hcd *hcd)
+ 	return rc;
+ }
+ 
+-static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
++static int uhci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 	int rc = 0;
+@@ -774,7 +774,7 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
+ 	return rc;
+ }
+ 
+-static int uhci_resume(struct usb_hcd *hcd)
++static int uhci_pci_resume(struct usb_hcd *hcd)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 
+@@ -872,8 +872,8 @@ static const struct hc_driver uhci_driver = {
+ 	.reset =		uhci_init,
+ 	.start =		uhci_start,
+ #ifdef CONFIG_PM
+-	.suspend =		uhci_suspend,
+-	.resume =		uhci_resume,
++	.pci_suspend =		uhci_pci_suspend,
++	.pci_resume =		uhci_pci_resume,
+ 	.bus_suspend =		uhci_rh_suspend,
+ 	.bus_resume =		uhci_rh_resume,
+ #endif

commit 7329e211b987a493cbcfca0e98c60eb108ab42df
+Author: Alan Stern 
+Date:   Thu Apr 3 18:02:56 2008 -0400
+
+    USB: root hubs don't lie about their number of TTs
+    
+    Currently EHCI root hubs enumerate with a bDeviceProtocol code
+    indicating that they possess a Transaction Translator.  However the
+    vast majority of controllers do not; they rely on a companion
+    controller to handle full- and low-speed communications.  This patch
+    (as1064) changes the root-hub device descriptor to match the actual
+    situation.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index f936de75f44e..e68fef5361d2 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -129,7 +129,7 @@ static const u8 usb2_rh_dev_descriptor [18] = {
+ 
+ 	0x09,	    /*  __u8  bDeviceClass; HUB_CLASSCODE */
+ 	0x00,	    /*  __u8  bDeviceSubClass; */
+-	0x01,       /*  __u8  bDeviceProtocol; [ usb 2.0 single TT ]*/
++	0x00,       /*  __u8  bDeviceProtocol; [ usb 2.0 no TT ] */
+ 	0x40,       /*  __u8  bMaxPacketSize0; 64 Bytes */
+ 
+ 	0x6b, 0x1d, /*  __le16 idVendor; Linux Foundation */
+@@ -354,9 +354,10 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
+ 		__attribute__((aligned(4)));
+ 	const u8	*bufp = tbuf;
+ 	int		len = 0;
+-	int		patch_wakeup = 0;
+ 	int		status;
+ 	int		n;
++	u8		patch_wakeup = 0;
++	u8		patch_protocol = 0;
+ 
+ 	might_sleep();
+ 
+@@ -433,6 +434,8 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
+ 			else
+ 				goto error;
+ 			len = 18;
++			if (hcd->has_tt)
++				patch_protocol = 1;
+ 			break;
+ 		case USB_DT_CONFIG << 8:
+ 			if (hcd->driver->flags & HCD_USB2) {
+@@ -527,6 +530,13 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
+ 						bmAttributes))
+ 			((struct usb_config_descriptor *)ubuf)->bmAttributes
+ 				|= USB_CONFIG_ATT_WAKEUP;
++
++		/* report whether RH hardware has an integrated TT */
++		if (patch_protocol &&
++				len > offsetof(struct usb_device_descriptor,
++						bDeviceProtocol))
++			((struct usb_device_descriptor *) ubuf)->
++					bDeviceProtocol = 1;
+ 	}
+ 
+ 	/* any errors get returned through the urb completion */
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index 2c086b8460b1..e0e99471c3fc 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -99,6 +99,7 @@ struct usb_hcd {
+ 	unsigned		poll_pending:1;	/* status has changed? */
+ 	unsigned		wireless:1;	/* Wireless USB HCD */
+ 	unsigned		authorized_default:1;
++	unsigned		has_tt:1;	/* Integrated TT in root hub */
+ 
+ 	int			irq;		/* irq allocated */
+ 	void __iomem		*regs;		/* device memory/io */
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index 040bd8632eb3..7c8a2ccf78f1 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -130,6 +130,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 	case PCI_VENDOR_ID_TDI:
+ 		if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
+ 			ehci->is_tdi_rh_tt = 1;
++			hcd->has_tt = 1;
+ 			tdi_reset(ehci);
+ 		}
+ 		break;

commit 0d22f65515307c878ddd20b1305cce925ca9516c
+Author: Alan Stern 
+Date:   Thu Apr 3 11:35:26 2008 -0400
+
+    USB: OHCI: fix bug in controller resume
+    
+    This patch (as1063) fixes a bug in the way ohci-hcd resumes its
+    controllers.  It leaves the Master Interrupt Enable bit turned off.
+    
+    If the root hub is resumed immediately this won't matter.  But if the
+    root hub is suspended (say because no devices are plugged in), it won't
+    ever wake up by itself.
+    
+    Signed-off-by: Alan Stern 
+    CC: David Brownell 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index d0360f65ebd9..b0e2275755c8 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -312,11 +312,13 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
+ 
+ static int ohci_pci_resume (struct usb_hcd *hcd)
+ {
++	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
++
+ 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ 
+ 	/* FIXME: we should try to detect loss of VBUS power here */
+ 	prepare_for_handover(hcd);
+-
++	ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrenable);
+ 	return 0;
+ }
+ 

commit 148d9fe4c91a6356dae1b05b76b8133586c26be4
+Author: Alan Stern 
+Date:   Thu Mar 27 14:52:57 2008 -0400
+
+    USB: usb-storage: use adaptive DMA mask
+    
+    This patch (as1060) makes usb-storage set the DMA alignment mask for
+    SCSI slaves to match the maxpacket size of the bulk-IN endpoint,
+    rather than always setting it to 511.  For full-speed devices that
+    mask is too restrictive, and wireless USB devices can have maxpacket
+    sizes larger than 512.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index 5405ba8cd9d2..521f0297aef9 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -73,6 +73,7 @@ static const char* host_info(struct Scsi_Host *host)
+ static int slave_alloc (struct scsi_device *sdev)
+ {
+ 	struct us_data *us = host_to_us(sdev->host);
++	struct usb_host_endpoint *bulk_in_ep;
+ 
+ 	/*
+ 	 * Set the INQUIRY transfer length to 36.  We don't use any of
+@@ -84,12 +85,13 @@ static int slave_alloc (struct scsi_device *sdev)
+ 	/* Scatter-gather buffers (all but the last) must have a length
+ 	 * divisible by the bulk maxpacket size.  Otherwise a data packet
+ 	 * would end up being short, causing a premature end to the data
+-	 * transfer.  Since high-speed bulk pipes have a maxpacket size
+-	 * of 512, we'll use that as the scsi device queue's DMA alignment
+-	 * mask.  Guaranteeing proper alignment of the first buffer will
+-	 * have the desired effect because, except at the beginning and
+-	 * the end, scatter-gather buffers follow page boundaries. */
+-	blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
++	 * transfer.  We'll use the maxpacket value of the bulk-IN pipe
++	 * to set the SCSI device queue's DMA alignment mask.
++	 */
++	bulk_in_ep = us->pusb_dev->ep_in[usb_pipeendpoint(us->recv_bulk_pipe)];
++	blk_queue_update_dma_alignment(sdev->request_queue,
++			le16_to_cpu(bulk_in_ep->desc.wMaxPacketSize) - 1);
++			/* wMaxPacketSize must be a power of 2 */
+ 
+ 	/*
+ 	 * The UFI spec treates the Peripheral Qualifier bits in an

commit 70a1c9e086c2e267fbc4533cb870f34999b531d6
+Author: Alan Stern 
+Date:   Thu Mar 6 17:00:58 2008 -0500
+
+    USB: remove dev->power.power_state
+    
+    power.power_state is scheduled for removal.  This patch (as1053)
+    removes all uses of that field from drivers/usb.  Almost all of them
+    were write-only, the most significant exceptions being sl811-hcd.c and
+    u132-hcd.c.
+    
+    Part of this patch was written by Pavel Machek.
+    
+    Signed-off-by: Alan Stern 
+    Cc: David Brownell 
+    Acked-by: Pavel Machek 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index ebccdefcc6f2..2ea333a43d65 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -794,8 +794,6 @@ static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
+ 
+  done:
+ 	dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+-	if (status == 0)
+-		udev->dev.power.power_state.event = msg.event;
+ 	return status;
+ }
+ 
+@@ -824,10 +822,8 @@ static int usb_resume_device(struct usb_device *udev)
+ 
+  done:
+ 	dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+-	if (status == 0) {
++	if (status == 0)
+ 		udev->autoresume_disabled = 0;
+-		udev->dev.power.power_state.event = PM_EVENT_ON;
+-	}
+ 	return status;
+ }
+ 
+@@ -1180,8 +1176,7 @@ static int usb_resume_both(struct usb_device *udev)
+ 		}
+ 	} else {
+ 
+-		/* Needed for setting udev->dev.power.power_state.event,
+-		 * for possible debugging message, and for reset_resume. */
++		/* Needed for reset-resume */
+ 		status = usb_resume_device(udev);
+ 	}
+ 
+@@ -1194,7 +1189,8 @@ static int usb_resume_both(struct usb_device *udev)
+ 
+  done:
+ 	dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+-	udev->reset_resume = 0;
++	if (!status)
++		udev->reset_resume = 0;
+ 	return status;
+ }
+ 
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index 84760ddbc332..739407bb8492 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -73,7 +73,6 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ 	if (pci_enable_device(dev) < 0)
+ 		return -ENODEV;
+ 	dev->current_state = PCI_D0;
+-	dev->dev.power.power_state = PMSG_ON;
+ 
+ 	if (!dev->irq) {
+ 		dev_err(&dev->dev,
+@@ -302,8 +301,6 @@ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message)
+ 
+ done:
+ 	if (retval == 0) {
+-		dev->dev.power.power_state = PMSG_SUSPEND;
+-
+ #ifdef CONFIG_PPC_PMAC
+ 		/* Disable ASIC clocks for USB */
+ 		if (machine_is(powermac)) {
+@@ -406,8 +403,6 @@ int usb_hcd_pci_resume(struct pci_dev *dev)
+ 	pci_set_master(dev);
+ 	pci_restore_state(dev);
+ 
+-	dev->dev.power.power_state = PMSG_ON;
+-
+ 	clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+ 
+ 	if (hcd->driver->resume) {
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 2375194a9d43..1bf8ccb9c58d 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -114,13 +114,11 @@ static inline int is_usb_device_driver(struct device_driver *drv)
+ static inline void mark_active(struct usb_interface *f)
+ {
+ 	f->is_active = 1;
+-	f->dev.power.power_state.event = PM_EVENT_ON;
+ }
+ 
+ static inline void mark_quiesced(struct usb_interface *f)
+ {
+ 	f->is_active = 0;
+-	f->dev.power.power_state.event = PM_EVENT_SUSPEND;
+ }
+ 
+ static inline int is_active(const struct usb_interface *f)
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index cbe44535c0f0..e454775c2ff2 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -900,7 +900,6 @@ static int dummy_udc_suspend (struct platform_device *pdev, pm_message_t state)
+ 	set_link_state (dum);
+ 	spin_unlock_irq (&dum->lock);
+ 
+-	pdev->dev.power.power_state = state;
+ 	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
+ 	return 0;
+ }
+@@ -915,7 +914,6 @@ static int dummy_udc_resume (struct platform_device *pdev)
+ 	set_link_state (dum);
+ 	spin_unlock_irq (&dum->lock);
+ 
+-	pdev->dev.power.power_state = PMSG_ON;
+ 	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
+ 	return 0;
+ }
+diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
+index ee1e9a314cd1..56277d24f041 100644
+--- a/drivers/usb/gadget/omap_udc.c
++++ b/drivers/usb/gadget/omap_udc.c
+@@ -1265,8 +1265,6 @@ static int can_pullup(struct omap_udc *udc)
+ 
+ static void pullup_enable(struct omap_udc *udc)
+ {
+-	udc->gadget.dev.parent->power.power_state = PMSG_ON;
+-	udc->gadget.dev.power.power_state = PMSG_ON;
+ 	UDC_SYSCON1_REG |= UDC_PULLUP_EN;
+ 	if (!gadget_is_otg(&udc->gadget) && !cpu_is_omap15xx())
+ 		OTG_CTRL_REG |= OTG_BSESSVLD;
+@@ -3061,8 +3059,6 @@ static int omap_udc_suspend(struct platform_device *dev, pm_message_t message)
+ 		omap_pullup(&udc->gadget, 0);
+ 	}
+ 
+-	udc->gadget.dev.power.power_state = PMSG_SUSPEND;
+-	udc->gadget.dev.parent->power.power_state = PMSG_SUSPEND;
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
+index 38eb92e5dc42..4af90df8e7de 100644
+--- a/drivers/usb/host/ehci-dbg.c
++++ b/drivers/usb/host/ehci-dbg.c
+@@ -670,7 +670,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
+ 
+ 	spin_lock_irqsave (&ehci->lock, flags);
+ 
+-	if (buf->bus->controller->power.power_state.event) {
++	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+ 		size = scnprintf (next, size,
+ 			"bus %s, device %s (driver " DRIVER_VERSION ")\n"
+ 			"%s\n"
+diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
+index bbda58eb8813..69782221bcf3 100644
+--- a/drivers/usb/host/ehci-ps3.c
++++ b/drivers/usb/host/ehci-ps3.c
+@@ -125,7 +125,6 @@ static int ps3_ehci_probe(struct ps3_system_bus_device *dev)
+ 		goto fail_irq;
+ 	}
+ 
+-	dev->core.power.power_state = PMSG_ON;
+ 	dev->core.dma_mask = &dummy_mask; /* FIXME: for improper usb code */
+ 
+ 	hcd = usb_create_hcd(&ps3_ehci_hc_driver, &dev->core, dev->core.bus_id);
+diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
+index 203a3359a648..66d773c726f6 100644
+--- a/drivers/usb/host/isp116x-hcd.c
++++ b/drivers/usb/host/isp116x-hcd.c
+@@ -1442,11 +1442,6 @@ static int isp116x_bus_resume(struct usb_hcd *hcd)
+ 		break;
+ 	case HCCONTROL_USB_OPER:
+ 		spin_unlock_irq(&isp116x->lock);
+-		/* Without setting power_state here the
+-		   SUSPENDED state won't be removed from
+-		   sysfs/usbN/power.state as a response to remote
+-		   wakeup. Maybe in the future. */
+-		hcd->self.root_hub->dev.power.power_state = PMSG_ON;
+ 		return 0;
+ 	default:
+ 		/* HCCONTROL_USB_RESET: this may happen, when during
+@@ -1460,7 +1455,6 @@ static int isp116x_bus_resume(struct usb_hcd *hcd)
+ 		if ((isp116x->rhdesca & RH_A_NDP) == 2)
+ 			isp116x_hub_control(hcd, SetPortFeature,
+ 					    USB_PORT_FEAT_POWER, 2, NULL, 0);
+-		hcd->self.root_hub->dev.power.power_state = PMSG_ON;
+ 		return 0;
+ 	}
+ 
+@@ -1486,8 +1480,6 @@ static int isp116x_bus_resume(struct usb_hcd *hcd)
+ 	isp116x_write_reg32(isp116x, HCCONTROL,
+ 			    (val & ~HCCONTROL_HCFS) | HCCONTROL_USB_OPER);
+ 	spin_unlock_irq(&isp116x->lock);
+-	/* see analogous comment above */
+-	hcd->self.root_hub->dev.power.power_state = PMSG_ON;
+ 	hcd->state = HC_STATE_RUNNING;
+ 
+ 	return 0;
+@@ -1663,7 +1655,6 @@ static int __devinit isp116x_probe(struct platform_device *pdev)
+ static int isp116x_suspend(struct platform_device *dev, pm_message_t state)
+ {
+ 	VDBG("%s: state %x\n", __func__, state.event);
+-	dev->dev.power.power_state = state;
+ 	return 0;
+ }
+ 
+@@ -1672,8 +1663,7 @@ static int isp116x_suspend(struct platform_device *dev, pm_message_t state)
+ */
+ static int isp116x_resume(struct platform_device *dev)
+ {
+-	VDBG("%s:  state %x\n", __func__, dev->power.power_state.event);
+-	dev->dev.power.power_state = PMSG_ON;
++	VDBG("%s\n", __func__);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
+index a22c30aa745d..e06bfaebec54 100644
+--- a/drivers/usb/host/ohci-dbg.c
++++ b/drivers/usb/host/ohci-dbg.c
+@@ -655,7 +655,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
+ 		hcd->product_desc,
+ 		hcd_name);
+ 
+-	if (bus->controller->power.power_state.event) {
++	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+ 		size -= scnprintf (next, size,
+ 			"SUSPENDED (no register access)\n");
+ 		goto done;
+diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
+index 156e93a9d0df..40c683f8987d 100644
+--- a/drivers/usb/host/ohci-ep93xx.c
++++ b/drivers/usb/host/ohci-ep93xx.c
+@@ -177,7 +177,6 @@ static int ohci_hcd_ep93xx_drv_suspend(struct platform_device *pdev, pm_message_
+ 
+ 	ep93xx_stop_hc(&pdev->dev);
+ 	hcd->state = HC_STATE_SUSPENDED;
+-	pdev->dev.power.power_state = PMSG_SUSPEND;
+ 
+ 	return 0;
+ }
+@@ -193,7 +192,6 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev)
+ 	ohci->next_statechange = jiffies;
+ 
+ 	ep93xx_start_hc(&pdev->dev);
+-	pdev->dev.power.power_state = PMSG_ON;
+ 	usb_hcd_resume_root_hub(hcd);
+ 
+ 	return 0;
+diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
+index 7bfca1ed1b58..2aafa7b6c81f 100644
+--- a/drivers/usb/host/ohci-omap.c
++++ b/drivers/usb/host/ohci-omap.c
+@@ -505,7 +505,6 @@ static int ohci_omap_suspend(struct platform_device *dev, pm_message_t message)
+ 
+ 	omap_ohci_clock_power(0);
+ 	ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
+-	dev->dev.power.power_state = PMSG_SUSPEND;
+ 	return 0;
+ }
+ 
+@@ -518,7 +517,6 @@ static int ohci_omap_resume(struct platform_device *dev)
+ 	ohci->next_statechange = jiffies;
+ 
+ 	omap_ohci_clock_power(1);
+-	dev->dev.power.power_state = PMSG_ON;
+ 	usb_hcd_resume_root_hub(platform_get_drvdata(dev));
+ 	return 0;
+ }
+diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c
+index 01a0caeaa6bc..c1935ae537f8 100644
+--- a/drivers/usb/host/ohci-ps3.c
++++ b/drivers/usb/host/ohci-ps3.c
+@@ -127,7 +127,6 @@ static int ps3_ohci_probe(struct ps3_system_bus_device *dev)
+ 		goto fail_irq;
+ 	}
+ 
+-	dev->core.power.power_state = PMSG_ON;
+ 	dev->core.dma_mask = &dummy_mask; /* FIXME: for improper usb code */
+ 
+ 	hcd = usb_create_hcd(&ps3_ohci_hc_driver, &dev->core, dev->core.bus_id);
+diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
+index 8ad9b3b604b5..5d470263eed8 100644
+--- a/drivers/usb/host/ohci-pxa27x.c
++++ b/drivers/usb/host/ohci-pxa27x.c
+@@ -339,7 +339,6 @@ static int ohci_hcd_pxa27x_drv_suspend(struct platform_device *pdev, pm_message_
+ 
+ 	pxa27x_stop_hc(&pdev->dev);
+ 	hcd->state = HC_STATE_SUSPENDED;
+-	pdev->dev.power.power_state = PMSG_SUSPEND;
+ 
+ 	return 0;
+ }
+@@ -357,7 +356,6 @@ static int ohci_hcd_pxa27x_drv_resume(struct platform_device *pdev)
+ 	if ((status = pxa27x_start_hc(&pdev->dev)) < 0)
+ 		return status;
+ 
+-	pdev->dev.power.power_state = PMSG_ON;
+ 	usb_hcd_resume_root_hub(hcd);
+ 
+ 	return 0;
+diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c
+index 8ffcd3e5f56b..ab1e366d7790 100644
+--- a/drivers/usb/host/ohci-sm501.c
++++ b/drivers/usb/host/ohci-sm501.c
+@@ -224,7 +224,6 @@ static int ohci_sm501_suspend(struct platform_device *pdev, pm_message_t msg)
+ 
+ 	sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 0);
+ 	ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
+-	dev->power.power_state = PMSG_SUSPEND;
+ 	return 0;
+ }
+ 
+@@ -238,7 +237,6 @@ static int ohci_sm501_resume(struct platform_device *pdev)
+ 	ohci->next_statechange = jiffies;
+ 
+ 	sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 1);
+-	dev->power.power_state = PMSG_ON;
+ 	usb_hcd_resume_root_hub(platform_get_drvdata(pdev));
+ 	return 0;
+ }
+diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
+index afd4fbe7713c..b46ff9a80b66 100644
+--- a/drivers/usb/host/r8a66597-hcd.c
++++ b/drivers/usb/host/r8a66597-hcd.c
+@@ -2107,13 +2107,11 @@ static struct hc_driver r8a66597_hc_driver = {
+ #if defined(CONFIG_PM)
+ static int r8a66597_suspend(struct platform_device *pdev, pm_message_t state)
+ {
+-	pdev->dev.power.power_state = state;
+ 	return 0;
+ }
+ 
+ static int r8a66597_resume(struct platform_device *pdev)
+ {
+-	pdev->dev.power.power_state = PMSG_ON;
+ 	return 0;
+ }
+ #else	/* if defined(CONFIG_PM) */
+diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
+index 629bca0ebe8f..df256d61e2c6 100644
+--- a/drivers/usb/host/sl811-hcd.c
++++ b/drivers/usb/host/sl811-hcd.c
+@@ -94,12 +94,10 @@ static void port_power(struct sl811 *sl811, int is_on)
+ 
+ 		sl811->port1 = (1 << USB_PORT_FEAT_POWER);
+ 		sl811->irq_enable = SL11H_INTMASK_INSRMV;
+-		hcd->self.controller->power.power_state = PMSG_ON;
+ 	} else {
+ 		sl811->port1 = 0;
+ 		sl811->irq_enable = 0;
+ 		hcd->state = HC_STATE_HALT;
+-		hcd->self.controller->power.power_state = PMSG_SUSPEND;
+ 	}
+ 	sl811->ctrl1 = 0;
+ 	sl811_write(sl811, SL11H_IRQ_ENABLE, 0);
+@@ -1772,8 +1770,6 @@ sl811h_suspend(struct platform_device *dev, pm_message_t state)
+ 		port_power(sl811, 0);
+ 		break;
+ 	}
+-	if (retval == 0)
+-		dev->dev.power.power_state = state;
+ 	return retval;
+ }
+ 
+@@ -1786,15 +1782,13 @@ sl811h_resume(struct platform_device *dev)
+ 	/* with no "check to see if VBUS is still powered" board hook,
+ 	 * let's assume it'd only be powered to enable remote wakeup.
+ 	 */
+-	if (dev->dev.power.power_state.event == PM_EVENT_SUSPEND
+-			|| !device_can_wakeup(&hcd->self.root_hub->dev)) {
++	if (!sl811->port1 || !device_can_wakeup(&hcd->self.root_hub->dev)) {
+ 		sl811->port1 = 0;
+ 		port_power(sl811, 1);
+ 		usb_root_hub_lost_power(hcd->self.root_hub);
+ 		return 0;
+ 	}
+ 
+-	dev->dev.power.power_state = PMSG_ON;
+ 	return sl811h_bus_resume(hcd);
+ }
+ 
+diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
+index 8e117a795e93..6e9b7edff528 100644
+--- a/drivers/usb/host/u132-hcd.c
++++ b/drivers/usb/host/u132-hcd.c
+@@ -1534,11 +1534,9 @@ static void u132_power(struct u132 *u132, int is_on)
+                 if (u132->power)
+                         return;
+                 u132->power = 1;
+-                hcd->self.controller->power.power_state = PMSG_ON;
+         } else {
+                 u132->power = 0;
+                 hcd->state = HC_STATE_HALT;
+-                hcd->self.controller->power.power_state = PMSG_SUSPEND;
+         }
+ }
+ 
+@@ -3227,8 +3225,6 @@ static int u132_suspend(struct platform_device *pdev, pm_message_t state)
+                         }
+ 			break;
+ 		}
+-                if (retval == 0)
+-                        pdev->dev.power.power_state = state;
+                 return retval;
+         }
+ }
+@@ -3246,14 +3242,13 @@ static int u132_resume(struct platform_device *pdev)
+                 return -ESHUTDOWN;
+         } else {
+                 int retval = 0;
+-                if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
++		if (!u132->port[0].power) {
+                         int ports = MAX_U132_PORTS;
+                         while (ports-- > 0) {
+                                 port_power(u132, ports, 1);
+                         }
+                         retval = 0;
+                 } else {
+-                        pdev->dev.power.power_state = PMSG_ON;
+                         retval = u132_bus_resume(hcd);
+                 }
+                 return retval;
+diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
+index 17100471e461..2c4fd4d6df95 100644
+--- a/drivers/usb/misc/usbtest.c
++++ b/drivers/usb/misc/usbtest.c
+@@ -1564,7 +1564,8 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
+ 	if (mutex_lock_interruptible(&dev->lock))
+ 		return -ERESTARTSYS;
+ 
+-	if (intf->dev.power.power_state.event != PM_EVENT_ON) {
++	/* FIXME: What if a system sleep starts while a test is running? */
++	if (!intf->is_active) {
+ 		mutex_unlock(&dev->lock);
+ 		return -EHOSTUNREACH;
+ 	}

commit 9214d1d80c19016172e685ce7bde0ea757c49097
+Author: Alan Stern 
+Date:   Thu Mar 6 11:04:13 2008 -0500
+
+    USB: enable USB-PERSIST by default
+    
+    This patch (as1052) enables USB-PERSIST for all devices by default.
+    The user won't have to remember to enable it explicitly for devices
+    containing mounted filesystems.
+    
+    Eventually userspace tools like hal may be able to set the persist
+    attribute automatically when a filesystem is mounted on a USB device.
+    When that time comes this patch can be reverted, if people think it
+    matters.
+    
+    This approach has the advantage of giving the user the ability to turn
+    off USB-PERSIST for devices with mounted filesystems, rather than
+    making the kernel always assume it should be on.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index f384edf35b44..2e2019390290 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -98,12 +98,14 @@ void usb_detect_quirks(struct usb_device *udev)
+ 		udev->autosuspend_disabled = 1;
+ #endif
+ 
+-#ifdef	CONFIG_PM
++	/* For the present, all devices default to USB-PERSIST enabled */
++#if 0		/* was: #ifdef CONFIG_PM */
+ 	/* Hubs are automatically enabled for USB-PERSIST */
+ 	if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
+ 		udev->persist_enabled = 1;
++
+ #else
+-	/* In the absense of PM, we can safely enable USB-PERSIST
++	/* In the absence of PM, we can safely enable USB-PERSIST
+ 	 * for all devices.  It will affect things like hub resets
+ 	 * and EMF-related port disables.
+ 	 */

commit eb764c4be1e5db3ee34df5745e98cf2f148c7320
+Author: Alan Stern 
+Date:   Mon Mar 3 15:16:04 2008 -0500
+
+    USB: check serial-number string after device reset
+    
+    This patch (as1048) extends the descriptor checking after a device is
+    reset.  Now the SerialNumber string descriptor is compared to its old
+    value, in addition to the device and configuration descriptors.
+    
+    As a consequence, the kmalloc() call in usb_string() is now on the
+    error-handling pathway for usb-storage.  Hence its allocation type is
+    changed to GFO_NOIO.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/usb/persist.txt b/Documentation/usb/persist.txt
+index bea58dbd30fe..d56cb1a11550 100644
+--- a/Documentation/usb/persist.txt
++++ b/Documentation/usb/persist.txt
+@@ -136,10 +136,10 @@ aren't guaranteed to be 100% accurate.
+ 
+ If you replace one USB device with another of the same type (same
+ manufacturer, same IDs, and so on) there's an excellent chance the
+-kernel won't detect the change.  Serial numbers and other strings are
+-not compared.  In many cases it wouldn't help if they were, because
+-manufacturers frequently omit serial numbers entirely in their
+-devices.
++kernel won't detect the change.  The serial number string and other
++descriptors are compared with the kernel's stored values, but this
++might not help since manufacturers frequently omit serial numbers
++entirely in their devices.
+ 
+ Furthermore it's quite possible to leave a USB device exactly the same
+ while changing its media.  If you replace the flash memory card in a
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 6dc589955d75..9fc5179dfc60 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -3010,16 +3010,36 @@ void usb_hub_cleanup(void)
+ 	usb_deregister(&hub_driver);
+ } /* usb_hub_cleanup() */
+ 
+-static int config_descriptors_changed(struct usb_device *udev)
+-{
+-	unsigned			index;
+-	unsigned			len = 0;
+-	struct usb_config_descriptor	*buf;
++static int descriptors_changed(struct usb_device *udev,
++		struct usb_device_descriptor *old_device_descriptor)
++{
++	int		changed = 0;
++	unsigned	index;
++	unsigned	serial_len = 0;
++	unsigned	len;
++	unsigned	old_length;
++	int		length;
++	char		*buf;
++
++	if (memcmp(&udev->descriptor, old_device_descriptor,
++			sizeof(*old_device_descriptor)) != 0)
++		return 1;
++
++	/* Since the idVendor, idProduct, and bcdDevice values in the
++	 * device descriptor haven't changed, we will assume the
++	 * Manufacturer and Product strings haven't changed either.
++	 * But the SerialNumber string could be different (e.g., a
++	 * different flash card of the same brand).
++	 */
++	if (udev->serial)
++		serial_len = strlen(udev->serial) + 1;
+ 
++	len = serial_len;
+ 	for (index = 0; index < udev->descriptor.bNumConfigurations; index++) {
+-		if (len < le16_to_cpu(udev->config[index].desc.wTotalLength))
+-			len = le16_to_cpu(udev->config[index].desc.wTotalLength);
++		old_length = le16_to_cpu(udev->config[index].desc.wTotalLength);
++		len = max(len, old_length);
+ 	}
++
+ 	buf = kmalloc(len, GFP_NOIO);
+ 	if (buf == NULL) {
+ 		dev_err(&udev->dev, "no mem to re-read configs after reset\n");
+@@ -3027,25 +3047,41 @@ static int config_descriptors_changed(struct usb_device *udev)
+ 		return 1;
+ 	}
+ 	for (index = 0; index < udev->descriptor.bNumConfigurations; index++) {
+-		int length;
+-		int old_length = le16_to_cpu(udev->config[index].desc.wTotalLength);
+-
++		old_length = le16_to_cpu(udev->config[index].desc.wTotalLength);
+ 		length = usb_get_descriptor(udev, USB_DT_CONFIG, index, buf,
+ 				old_length);
+-		if (length < old_length) {
++		if (length != old_length) {
+ 			dev_dbg(&udev->dev, "config index %d, error %d\n",
+ 					index, length);
++			changed = 1;
+ 			break;
+ 		}
+ 		if (memcmp (buf, udev->rawdescriptors[index], old_length)
+ 				!= 0) {
+ 			dev_dbg(&udev->dev, "config index %d changed (#%d)\n",
+-				index, buf->bConfigurationValue);
++				index,
++				((struct usb_config_descriptor *) buf)->
++					bConfigurationValue);
++			changed = 1;
+ 			break;
+ 		}
+ 	}
++
++	if (!changed && serial_len) {
++		length = usb_string(udev, udev->descriptor.iSerialNumber,
++				buf, serial_len);
++		if (length + 1 != serial_len) {
++			dev_dbg(&udev->dev, "serial string error %d\n",
++					length);
++			changed = 1;
++		} else if (memcmp(buf, udev->serial, length) != 0) {
++			dev_dbg(&udev->dev, "serial string changed\n");
++			changed = 1;
++		}
++	}
++
+ 	kfree(buf);
+-	return index != udev->descriptor.bNumConfigurations;
++	return changed;
+ }
+ 
+ /**
+@@ -3118,8 +3154,7 @@ int usb_reset_device(struct usb_device *udev)
+ 		goto re_enumerate;
+  
+ 	/* Device might have changed firmware (DFU or similar) */
+-	if (memcmp(&udev->descriptor, &descriptor, sizeof descriptor)
+-			|| config_descriptors_changed (udev)) {
++	if (descriptors_changed(udev, &descriptor)) {
+ 		dev_info(&udev->dev, "device firmware changed\n");
+ 		udev->descriptor = descriptor;	/* for disconnect() calls */
+ 		goto re_enumerate;
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index c311f67b7f08..a3695b5115ff 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -784,7 +784,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
+ 	if (size <= 0 || !buf || !index)
+ 		return -EINVAL;
+ 	buf[0] = 0;
+-	tbuf = kmalloc(256, GFP_KERNEL);
++	tbuf = kmalloc(256, GFP_NOIO);
+ 	if (!tbuf)
+ 		return -ENOMEM;
+ 

commit feccc30d90155bcbc937f87643182a43d25873eb
+Author: Alan Stern 
+Date:   Mon Mar 3 15:15:59 2008 -0500
+
+    USB: remove CONFIG_USB_PERSIST setting
+    
+    This patch (as1047) removes the USB_PERSIST Kconfig option, enabling
+    it permanently.  It also prevents the power/persist attribute from
+    being created for hub devices; there's no point in having it since
+    USB-PERSIST is always turned on for hubs.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/usb/persist.txt b/Documentation/usb/persist.txt
+index df54d645cbb5..bea58dbd30fe 100644
+--- a/Documentation/usb/persist.txt
++++ b/Documentation/usb/persist.txt
+@@ -2,7 +2,7 @@
+ 
+ 		   Alan Stern 
+ 
+-		 September 2, 2006 (Updated May 29, 2007)
++		September 2, 2006 (Updated February 25, 2008)
+ 
+ 
+ 	What is the problem?
+@@ -65,9 +65,10 @@ much better.)
+ 
+ 	What is the solution?
+ 
+-Setting CONFIG_USB_PERSIST will cause the kernel to work around these
+-issues.  It enables a mode in which the core USB device data
+-structures are allowed to persist across a power-session disruption.
++The kernel includes a feature called USB-persist.  It tries to work
++around these issues by allowing the core USB device data structures to
++persist across a power-session disruption.
++
+ It works like this.  If the kernel sees that a USB host controller is
+ not in the expected state during resume (i.e., if the controller was
+ reset or otherwise had lost power) then it applies a persistence check
+@@ -80,28 +81,30 @@ re-enumeration shows that the device now attached to that port has the
+ same descriptors as before, including the Vendor and Product IDs, then
+ the kernel continues to use the same device structure.  In effect, the
+ kernel treats the device as though it had merely been reset instead of
+-unplugged.
++unplugged.  The same thing happens if the host controller is in the
++expected state but a USB device was unplugged and then replugged.
+ 
+ If no device is now attached to the port, or if the descriptors are
+ different from what the kernel remembers, then the treatment is what
+ you would expect.  The kernel destroys the old device structure and
+ behaves as though the old device had been unplugged and a new device
+-plugged in, just as it would without the CONFIG_USB_PERSIST option.
++plugged in.
+ 
+ The end result is that the USB device remains available and usable.
+ Filesystem mounts and memory mappings are unaffected, and the world is
+ now a good and happy place.
+ 
+-Note that even when CONFIG_USB_PERSIST is set, the "persist" feature
+-will be applied only to those devices for which it is enabled.  You
+-can enable the feature by doing (as root):
++Note that the "USB-persist" feature will be applied only to those
++devices for which it is enabled.  You can enable the feature by doing
++(as root):
+ 
+ 	echo 1 >/sys/bus/usb/devices/.../power/persist
+ 
+ where the "..." should be filled in the with the device's ID.  Disable
+ the feature by writing 0 instead of 1.  For hubs the feature is
+-automatically and permanently enabled, so you only have to worry about
+-setting it for devices where it really matters.
++automatically and permanently enabled and the power/persist file
++doesn't even exist, so you only have to worry about setting it for
++devices where it really matters.
+ 
+ 
+ 	Is this the best solution?
+@@ -112,19 +115,19 @@ centralized Logical Volume Manager.  Such a solution would allow you
+ to plug in a USB flash device, create a persistent volume associated
+ with it, unplug the flash device, plug it back in later, and still
+ have the same persistent volume associated with the device.  As such
+-it would be more far-reaching than CONFIG_USB_PERSIST.
++it would be more far-reaching than USB-persist.
+ 
+ On the other hand, writing a persistent volume manager would be a big
+ job and using it would require significant input from the user.  This
+ solution is much quicker and easier -- and it exists now, a giant
+ point in its favor!
+ 
+-Furthermore, the USB_PERSIST option applies to _all_ USB devices, not
++Furthermore, the USB-persist feature applies to _all_ USB devices, not
+ just mass-storage devices.  It might turn out to be equally useful for
+ other device types, such as network interfaces.
+ 
+ 
+-	WARNING: Using CONFIG_USB_PERSIST can be dangerous!!
++	WARNING: USB-persist can be dangerous!!
+ 
+ When recovering an interrupted power session the kernel does its best
+ to make sure the USB device hasn't been changed; that is, the same
+@@ -152,5 +155,5 @@ but yourself.
+ YOU HAVE BEEN WARNED!  USE AT YOUR OWN RISK!
+ 
+ That having been said, most of the time there shouldn't be any trouble
+-at all.  The "persist" feature can be extremely useful.  Make the most
+-of it.
++at all.  The USB-persist feature can be extremely useful.  Make the
++most of it.
+diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
+index a2b0aa48b8ea..c15621d64579 100644
+--- a/drivers/usb/core/Kconfig
++++ b/drivers/usb/core/Kconfig
+@@ -102,31 +102,6 @@ config USB_SUSPEND
+ 
+ 	  If you are unsure about this, say N here.
+ 
+-config USB_PERSIST
+-	bool "USB device persistence during system suspend (DANGEROUS)"
+-	depends on USB && PM && EXPERIMENTAL
+-	default n
+-	help
+-
+-	  If you say Y here and enable the "power/persist" attribute
+-	  for a USB device, the device's data structures will remain
+-	  persistent across system suspend, even if the USB bus loses
+-	  power.  (This includes hibernation, also known as swsusp or
+-	  suspend-to-disk.)  The devices will reappear as if by magic
+-	  when the system wakes up, with no need to unmount USB
+-	  filesystems, rmmod host-controller drivers, or do anything
+-	  else.
+-
+-	  	WARNING: This option can be dangerous!
+-
+-	  If a USB device is replaced by another of the same type while
+-	  the system is asleep, there's a good chance the kernel won't
+-	  detect the change.  Likewise if the media in a USB storage
+-	  device is replaced.  When this happens it's almost certain to
+-	  cause data corruption and maybe even crash your system.
+-
+-	  If you are unsure, say N here.
+-
+ config USB_OTG
+ 	bool
+ 	depends on USB && EXPERIMENTAL
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index df68e2562582..6dc589955d75 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -30,12 +30,6 @@
+ #include "hcd.h"
+ #include "hub.h"
+ 
+-#ifdef	CONFIG_USB_PERSIST
+-#define	USB_PERSIST	1
+-#else
+-#define	USB_PERSIST	0
+-#endif
+-
+ /* if we are in debug mode, always announce new devices */
+ #ifdef DEBUG
+ #ifndef CONFIG_USB_ANNOUNCE_NEW_DEVICES
+@@ -695,7 +689,7 @@ static void hub_restart(struct usb_hub *hub, int type)
+ 		 * turn off the various status changes to prevent
+ 		 * khubd from disconnecting it later.
+ 		 */
+-		if (USB_PERSIST && udev->persist_enabled && status == 0 &&
++		if (udev->persist_enabled && status == 0 &&
+ 				!(portstatus & USB_PORT_STAT_ENABLE)) {
+ 			if (portchange & USB_PORT_STAT_C_ENABLE)
+ 				clear_port_feature(hub->hdev, port1,
+@@ -1923,9 +1917,8 @@ static int finish_port_resume(struct usb_device *udev)
+  * the host and the device is the same as it was when the device
+  * suspended.
+  *
+- * If CONFIG_USB_PERSIST and @udev->reset_resume are both set then this
+- * routine won't check that the port is still enabled.  Furthermore,
+- * if @udev->reset_resume is set then finish_port_resume() above will
++ * If @udev->reset_resume is set then this routine won't check that the
++ * port is still enabled.  Furthermore, finish_port_resume() above will
+  * reset @udev.  The end result is that a broken power session can be
+  * recovered and @udev will appear to persist across a loss of VBUS power.
+  *
+@@ -1937,8 +1930,8 @@ static int finish_port_resume(struct usb_device *udev)
+  * to it will be lost.  Using the USB_PERSIST facility, the device can be
+  * made to appear as if it had not disconnected.
+  *
+- * This facility is inherently dangerous.  Although usb_reset_device()
+- * makes every effort to insure that the same device is present after the
++ * This facility can be dangerous.  Although usb_reset_device() makes
++ * every effort to insure that the same device is present after the
+  * reset as before, it cannot provide a 100% guarantee.  Furthermore it's
+  * quite possible for a device to remain unaltered but its media to be
+  * changed.  If the user replaces a flash memory card while the system is
+@@ -1983,7 +1976,7 @@ int usb_port_resume(struct usb_device *udev)
+ 		status = hub_port_status(hub, port1, &portstatus, &portchange);
+ 
+  SuspendCleared:
+-		if (USB_PERSIST && udev->reset_resume)
++		if (udev->reset_resume)
+ 			want_flags = USB_PORT_STAT_POWER
+ 					| USB_PORT_STAT_CONNECTION;
+ 		else
+@@ -2113,10 +2106,10 @@ static int hub_reset_resume(struct usb_interface *intf)
+  *
+  * The USB host controller driver calls this function when its root hub
+  * is resumed and Vbus power has been interrupted or the controller
+- * has been reset.  The routine marks @rhdev as having lost power.  When
+- * the hub driver is resumed it will take notice; if CONFIG_USB_PERSIST
+- * is enabled then it will carry out power-session recovery, otherwise
+- * it will disconnect all the child devices.
++ * has been reset.  The routine marks @rhdev as having lost power.
++ * When the hub driver is resumed it will take notice and carry out
++ * power-session recovery for all the "USB-PERSIST"-enabled child devices;
++ * the others will be disconnected.
+  */
+ void usb_root_hub_lost_power(struct usb_device *rhdev)
+ {
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index dfc5418ea10c..f384edf35b44 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -97,4 +97,16 @@ void usb_detect_quirks(struct usb_device *udev)
+ 	if (udev->descriptor.bDeviceClass != USB_CLASS_HUB)
+ 		udev->autosuspend_disabled = 1;
+ #endif
++
++#ifdef	CONFIG_PM
++	/* Hubs are automatically enabled for USB-PERSIST */
++	if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
++		udev->persist_enabled = 1;
++#else
++	/* In the absense of PM, we can safely enable USB-PERSIST
++	 * for all devices.  It will affect things like hub resets
++	 * and EMF-related port disables.
++	 */
++	udev->persist_enabled = 1;
++#endif	/* CONFIG_PM */
+ }
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index a37ccbd1e007..5b20a60de8ba 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -180,11 +180,9 @@ show_urbnum(struct device *dev, struct device_attribute *attr, char *buf)
+ static DEVICE_ATTR(urbnum, S_IRUGO, show_urbnum, NULL);
+ 
+ 
+-#if defined(CONFIG_USB_PERSIST) || defined(CONFIG_USB_SUSPEND)
+-static const char power_group[] = "power";
+-#endif
++#ifdef	CONFIG_PM
+ 
+-#ifdef	CONFIG_USB_PERSIST
++static const char power_group[] = "power";
+ 
+ static ssize_t
+ show_persist(struct device *dev, struct device_attribute *attr, char *buf)
+@@ -222,12 +220,13 @@ static int add_persist_attributes(struct device *dev)
+ 	if (is_usb_device(dev)) {
+ 		struct usb_device *udev = to_usb_device(dev);
+ 
+-		/* Hubs are automatically enabled for USB_PERSIST */
+-		if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
+-			udev->persist_enabled = 1;
+-		rc = sysfs_add_file_to_group(&dev->kobj,
+-				&dev_attr_persist.attr,
+-				power_group);
++		/* Hubs are automatically enabled for USB_PERSIST,
++		 * no point in creating the attribute file.
++		 */
++		if (udev->descriptor.bDeviceClass != USB_CLASS_HUB)
++			rc = sysfs_add_file_to_group(&dev->kobj,
++					&dev_attr_persist.attr,
++					power_group);
+ 	}
+ 	return rc;
+ }
+@@ -238,13 +237,12 @@ static void remove_persist_attributes(struct device *dev)
+ 			&dev_attr_persist.attr,
+ 			power_group);
+ }
+-
+ #else
+ 
+ #define add_persist_attributes(dev)	0
+ #define remove_persist_attributes(dev)	do {} while (0)
+ 
+-#endif	/* CONFIG_USB_PERSIST */
++#endif	/* CONFIG_PM */
+ 
+ #ifdef	CONFIG_USB_SUSPEND
+ 
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 8d513a15d0cd..fea9e47192db 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -28,7 +28,7 @@
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-#ifdef	CONFIG_USB_PERSIST
++#ifdef	CONFIG_PM
+ 
+ static int ehci_hub_control(
+ 	struct usb_hcd	*hcd,
+@@ -104,15 +104,6 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
+ 	ehci->owned_ports = 0;
+ }
+ 
+-#else	/* CONFIG_USB_PERSIST */
+-
+-static inline void ehci_handover_companion_ports(struct ehci_hcd *ehci)
+-{ }
+-
+-#endif
+-
+-#ifdef	CONFIG_PM
+-
+ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ {
+ 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 583e0481dfa0..7e31cacfe69c 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -387,6 +387,7 @@ struct usb_device {
+ 
+ 	unsigned can_submit:1;		/* URBs may be submitted */
+ 	unsigned discon_suspended:1;	/* Disconnected while suspended */
++	unsigned persist_enabled:1;	/* USB_PERSIST enabled for this dev */
+ 	unsigned have_langid:1;		/* whether string_langid is valid */
+ 	unsigned authorized:1;		/* Policy has said we can use it */
+ 	unsigned wusb:1;		/* Device is Wireless USB */
+@@ -433,7 +434,6 @@ struct usb_device {
+ 	unsigned auto_pm:1;		/* autosuspend/resume in progress */
+ 	unsigned do_remote_wakeup:1;	/* remote wakeup should be enabled */
+ 	unsigned reset_resume:1;	/* needs reset instead of resume */
+-	unsigned persist_enabled:1;	/* USB_PERSIST enabled for this dev */
+ 	unsigned autosuspend_disabled:1; /* autosuspend and autoresume */
+ 	unsigned autoresume_disabled:1;  /*  disabled by the user */
+ 	unsigned skip_sys_resume:1;	/* skip the next system resume */

commit 5e6effaed6da94e727cd45f945ad2489af8570b3
+Author: Alan Stern 
+Date:   Mon Mar 3 15:15:51 2008 -0500
+
+    USB: make USB-PERSIST work after every system sleep
+    
+    This patch (as1046) makes USB-PERSIST work more in accordance with
+    the documentation.  Currently it takes effect only in cases where the
+    root hub has lost power or been reset, but it is supposed to operate
+    whenever a power session was dropped during a system sleep.
+    
+    A new hub_restart() routine carries out the duties required during a
+    reset or a reset-resume.  It checks to see whether occupied ports are
+    still enabled, and if they aren't then it clears the enable-change and
+    connect-change features (to prevent interference by khubd) and sets
+    the child device's reset_resume flag.  It also checks ports that are
+    supposed to be unoccupied to verify that the firmware hasn't left the
+    port in an enabled state.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 087e3bb70e09..df68e2562582 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -644,6 +644,81 @@ static void hub_stop(struct usb_hub *hub)
+ 	hub_quiesce(hub);
+ }
+ 
++#define HUB_RESET		1
++#define HUB_RESUME		2
++#define HUB_RESET_RESUME	3
++
++#ifdef CONFIG_PM
++
++static void hub_restart(struct usb_hub *hub, int type)
++{
++	struct usb_device *hdev = hub->hdev;
++	int port1;
++
++	/* Check each of the children to see if they require
++	 * USB-PERSIST handling or disconnection.  Also check
++	 * each unoccupied port to make sure it is still disabled.
++	 */
++	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
++		struct usb_device *udev = hdev->children[port1-1];
++		int status = 0;
++		u16 portstatus, portchange;
++
++		if (!udev || udev->state == USB_STATE_NOTATTACHED) {
++			if (type != HUB_RESET) {
++				status = hub_port_status(hub, port1,
++						&portstatus, &portchange);
++				if (status == 0 && (portstatus &
++						USB_PORT_STAT_ENABLE))
++					clear_port_feature(hdev, port1,
++							USB_PORT_FEAT_ENABLE);
++			}
++			continue;
++		}
++
++		/* Was the power session lost while we were suspended? */
++		switch (type) {
++		case HUB_RESET_RESUME:
++			portstatus = 0;
++			portchange = USB_PORT_STAT_C_CONNECTION;
++			break;
++
++		case HUB_RESET:
++		case HUB_RESUME:
++			status = hub_port_status(hub, port1,
++					&portstatus, &portchange);
++			break;
++		}
++
++		/* For "USB_PERSIST"-enabled children we must
++		 * mark the child device for reset-resume and
++		 * turn off the various status changes to prevent
++		 * khubd from disconnecting it later.
++		 */
++		if (USB_PERSIST && udev->persist_enabled && status == 0 &&
++				!(portstatus & USB_PORT_STAT_ENABLE)) {
++			if (portchange & USB_PORT_STAT_C_ENABLE)
++				clear_port_feature(hub->hdev, port1,
++						USB_PORT_FEAT_C_ENABLE);
++			if (portchange & USB_PORT_STAT_C_CONNECTION)
++				clear_port_feature(hub->hdev, port1,
++						USB_PORT_FEAT_C_CONNECTION);
++			udev->reset_resume = 1;
++		}
++
++		/* Otherwise for a reset_resume we must disconnect the child,
++		 * but as we may not lock the child device here
++		 * we have to do a "logical" disconnect.
++		 */
++		else if (type == HUB_RESET_RESUME)
++			hub_port_logical_disconnect(hub, port1);
++	}
++
++	hub_activate(hub);
++}
++
++#endif	/* CONFIG_PM */
++
+ /* caller has locked the hub device */
+ static int hub_pre_reset(struct usb_interface *intf)
+ {
+@@ -2015,49 +2090,20 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+ 
+ static int hub_resume(struct usb_interface *intf)
+ {
+-	struct usb_hub		*hub = usb_get_intfdata (intf);
+-
+-	dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
++	struct usb_hub *hub = usb_get_intfdata(intf);
+ 
+-	/* tell khubd to look for changes on this hub */
+-	hub_activate(hub);
++	dev_dbg(&intf->dev, "%s\n", __func__);
++	hub_restart(hub, HUB_RESUME);
+ 	return 0;
+ }
+ 
+ static int hub_reset_resume(struct usb_interface *intf)
+ {
+ 	struct usb_hub *hub = usb_get_intfdata(intf);
+-	struct usb_device *hdev = hub->hdev;
+-	int port1;
+ 
++	dev_dbg(&intf->dev, "%s\n", __func__);
+ 	hub_power_on(hub);
+-
+-	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
+-		struct usb_device *child = hdev->children[port1-1];
+-
+-		if (child) {
+-
+-			/* For "USB_PERSIST"-enabled children we must
+-			 * mark the child device for reset-resume and
+-			 * turn off the connect-change status to prevent
+-			 * khubd from disconnecting it later.
+-			 */
+-			if (USB_PERSIST && child->persist_enabled) {
+-				child->reset_resume = 1;
+-				clear_port_feature(hdev, port1,
+-						USB_PORT_FEAT_C_CONNECTION);
+-
+-			/* Otherwise we must disconnect the child,
+-			 * but as we may not lock the child device here
+-			 * we have to do a "logical" disconnect.
+-			 */
+-			} else {
+-				hub_port_logical_disconnect(hub, port1);
+-			}
+-		}
+-	}
+-
+-	hub_activate(hub);
++	hub_restart(hub, HUB_RESET_RESUME);
+ 	return 0;
+ }
+ 

commit 3eb14915a300f539f271e3716f2421bb0697ed48
+Author: Alan Stern 
+Date:   Mon Mar 3 15:15:43 2008 -0500
+
+    USB: reorganize code in hub.c
+    
+    This patch (as1045) reorganizes some code in the hub driver.
+    hub_port_status() is moved earlier in the file, and a new hub_stop()
+    routine is created to do the work currently in hub_preset() (i.e.,
+    disconnect all child devices and quiesce the hub).
+    
+    There are no functional changes.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index a42db75c2336..087e3bb70e09 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -333,6 +333,27 @@ static int get_port_status(struct usb_device *hdev, int port1,
+ 	return status;
+ }
+ 
++static int hub_port_status(struct usb_hub *hub, int port1,
++		u16 *status, u16 *change)
++{
++	int ret;
++
++	mutex_lock(&hub->status_mutex);
++	ret = get_port_status(hub->hdev, port1, &hub->status->port);
++	if (ret < 4) {
++		dev_err(hub->intfdev,
++			"%s failed (err = %d)\n", __func__, ret);
++		if (ret >= 0)
++			ret = -EIO;
++	} else {
++		*status = le16_to_cpu(hub->status->port.wPortStatus);
++		*change = le16_to_cpu(hub->status->port.wPortChange);
++		ret = 0;
++	}
++	mutex_unlock(&hub->status_mutex);
++	return ret;
++}
++
+ static void kick_khubd(struct usb_hub *hub)
+ {
+ 	unsigned long	flags;
+@@ -610,9 +631,8 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
+ }
+ 
+ /* caller has locked the hub device */
+-static int hub_pre_reset(struct usb_interface *intf)
++static void hub_stop(struct usb_hub *hub)
+ {
+-	struct usb_hub *hub = usb_get_intfdata(intf);
+ 	struct usb_device *hdev = hub->hdev;
+ 	int i;
+ 
+@@ -622,6 +642,14 @@ static int hub_pre_reset(struct usb_interface *intf)
+ 			usb_disconnect(&hdev->children[i]);
+ 	}
+ 	hub_quiesce(hub);
++}
++
++/* caller has locked the hub device */
++static int hub_pre_reset(struct usb_interface *intf)
++{
++	struct usb_hub *hub = usb_get_intfdata(intf);
++
++	hub_stop(hub);
+ 	return 0;
+ }
+ 
+@@ -910,7 +938,7 @@ static void hub_disconnect(struct usb_interface *intf)
+ 
+ 	/* Disconnect all children and quiesce the hub */
+ 	hub->error = 0;
+-	hub_pre_reset(intf);
++	hub_stop(hub);
+ 
+ 	usb_set_intfdata (intf, NULL);
+ 
+@@ -1510,28 +1538,6 @@ int usb_authorize_device(struct usb_device *usb_dev)
+ }
+ 
+ 
+-static int hub_port_status(struct usb_hub *hub, int port1,
+-			       u16 *status, u16 *change)
+-{
+-	int ret;
+-
+-	mutex_lock(&hub->status_mutex);
+-	ret = get_port_status(hub->hdev, port1, &hub->status->port);
+-	if (ret < 4) {
+-		dev_err (hub->intfdev,
+-			"%s failed (err = %d)\n", __FUNCTION__, ret);
+-		if (ret >= 0)
+-			ret = -EIO;
+-	} else {
+-		*status = le16_to_cpu(hub->status->port.wPortStatus);
+-		*change = le16_to_cpu(hub->status->port.wPortChange); 
+-		ret = 0;
+-	}
+-	mutex_unlock(&hub->status_mutex);
+-	return ret;
+-}
+-
+-
+ /* Returns 1 if @hub is a WUSB root hub, 0 otherwise */
+ static unsigned hub_is_wusb(struct usb_hub *hub)
+ {
+@@ -2726,7 +2732,7 @@ static void hub_events(void)
+ 		/* If the hub has died, clean up after it */
+ 		if (hdev->state == USB_STATE_NOTATTACHED) {
+ 			hub->error = -ENODEV;
+-			hub_pre_reset(intf);
++			hub_stop(hub);
+ 			goto loop;
+ 		}
+ 

commit 3bb1af5243d41af9518728445e9c9bd30dd47237
+Author: Alan Stern 
+Date:   Mon Mar 3 15:15:36 2008 -0500
+
+    USB: EHCI: carry out port handover during each root-hub resume
+    
+    This patch (as1044) causes EHCI port handover for non-high-speed
+    devices to occur during every root-hub resume, not just in cases where
+    the controller lost power or was reset.  This is necessary because:
+    
+            When some machines go into suspend, they remove power from
+            on-board USB devices while retaining suspend current for USB
+            controllers.
+    
+            The user might well unplug a USB device while the system is
+            suspended and then plug it back in before resuming.
+    
+    A corresponding change is made to the core resume routine; now
+    high-speed root hubs will always be resumed when the system wakes up,
+    even if they were suspended before the system went to sleep.  If this
+    weren't done then EHCI port handover wouldn't work, since it is called
+    when the EHCI root hub is resumed.
+    
+    Finally, a comment is added to the hub driver explaining the khubd has
+    to be freezable; if it weren't frozen then it could interfere with
+    port handover.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 801b6f142fa7..ebccdefcc6f2 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1523,9 +1523,14 @@ static int usb_suspend(struct device *dev, pm_message_t message)
+ 	udev = to_usb_device(dev);
+ 
+ 	/* If udev is already suspended, we can skip this suspend and
+-	 * we should also skip the upcoming system resume. */
++	 * we should also skip the upcoming system resume.  High-speed
++	 * root hubs are an exception; they need to resume whenever the
++	 * system wakes up in order for USB-PERSIST port handover to work
++	 * properly.
++	 */
+ 	if (udev->state == USB_STATE_SUSPENDED) {
+-		udev->skip_sys_resume = 1;
++		if (udev->parent || udev->speed != USB_SPEED_HIGH)
++			udev->skip_sys_resume = 1;
+ 		return 0;
+ 	}
+ 
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 57aeca160f38..a42db75c2336 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2890,7 +2890,13 @@ static void hub_events(void)
+ 
+ static int hub_thread(void *__unused)
+ {
++	/* khubd needs to be freezable to avoid intefering with USB-PERSIST
++	 * port handover.  Otherwise it might see that a full-speed device
++	 * was gone before the EHCI controller had handed its port over to
++	 * the companion full-speed controller.
++	 */
+ 	set_freezable();
++
+ 	do {
+ 		hub_events();
+ 		wait_event_freezable(khubd_wait,
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 4e065e556e4b..8d513a15d0cd 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -281,9 +281,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 	ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
+ 
+ 	spin_unlock_irq (&ehci->lock);
+-
+-	if (!power_okay)
+-		ehci_handover_companion_ports(ehci);
++	ehci_handover_companion_ports(ehci);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index 72ccd56e36dd..040bd8632eb3 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -329,7 +329,6 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
+ 
+ 	/* here we "know" root ports should always stay powered */
+ 	ehci_port_power(ehci, 1);
+-	ehci_handover_companion_ports(ehci);
+ 
+ 	hcd->state = HC_STATE_SUSPENDED;
+ 	return 0;

commit 9a3df1f7de0ecaf77a1dde86f2a4dc020f37f87e
+Author: Alan Stern 
+Date:   Wed Mar 19 22:39:13 2008 +0100
+
+    PM: Convert wakeup flag accessors to inline functions
+    
+    This patch (as1058) improves the wakeup macros in include/linux/pm.h.
+    All but the trivial ones are converted to inline routines, which
+    requires moving them to a separate header file since they depend on
+    the definition of struct device.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/include/linux/device.h b/include/linux/device.h
+index d57661129cb2..d7a1ae063b65 100644
+--- a/include/linux/device.h
++++ b/include/linux/device.h
+@@ -475,6 +475,9 @@ struct device {
+ 	void	(*release)(struct device *dev);
+ };
+ 
++/* Get the wakeup routines, which depend on struct device */
++#include 
++
+ #ifdef CONFIG_NUMA
+ static inline int dev_to_node(struct device *dev)
+ {
+diff --git a/include/linux/pm.h b/include/linux/pm.h
+index 3342627e2bd6..1de72cbbe0d1 100644
+--- a/include/linux/pm.h
++++ b/include/linux/pm.h
+@@ -212,54 +212,10 @@ static inline int device_suspend(pm_message_t state)
+ 	return 0;
+ }
+ 
+-#define suspend_report_result(fn, ret) do { } while (0)
++#define suspend_report_result(fn, ret)		do {} while (0)
+ 
+ #endif /* !CONFIG_PM_SLEEP */
+ 
+-#ifdef CONFIG_PM
+-
+-#define device_set_wakeup_enable(dev,val) \
+-	((dev)->power.should_wakeup = !!(val))
+-#define device_may_wakeup(dev) \
+-	(device_can_wakeup(dev) && (dev)->power.should_wakeup)
+-
+-/*
+- * Platform hook to activate device wakeup capability, if that's not already
+- * handled by enable_irq_wake() etc.
+- * Returns zero on success, else negative errno
+- */
+-extern int (*platform_enable_wakeup)(struct device *dev, int is_on);
+-
+-static inline int call_platform_enable_wakeup(struct device *dev, int is_on)
+-{
+-	if (platform_enable_wakeup)
+-		return (*platform_enable_wakeup)(dev, is_on);
+-	return 0;
+-}
+-
+-#else /* !CONFIG_PM */
+-
+-#define device_set_wakeup_enable(dev,val)	do{}while(0)
+-#define device_may_wakeup(dev)			(0)
+-
+-static inline int call_platform_enable_wakeup(struct device *dev, int is_on)
+-{
+-	return 0;
+-}
+-
+-#endif /* !CONFIG_PM */
+-
+-/* changes to device_may_wakeup take effect on the next pm state change.
+- * by default, devices should wakeup if they can.
+- */
+-#define device_can_wakeup(dev) \
+-	((dev)->power.can_wakeup)
+-#define device_init_wakeup(dev,val) \
+-	do { \
+-		device_can_wakeup(dev) = !!(val); \
+-		device_set_wakeup_enable(dev,val); \
+-	} while(0)
+-
+ /*
+  * Global Power Management flags
+  * Used to keep APM and ACPI from both being active
+diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h
+new file mode 100644
+index 000000000000..f0d0b2cb8d20
+--- /dev/null
++++ b/include/linux/pm_wakeup.h
+@@ -0,0 +1,90 @@
++/*
++ *  pm_wakeup.h - Power management wakeup interface
++ *
++ *  Copyright (C) 2008 Alan Stern
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#ifndef _LINUX_PM_WAKEUP_H
++#define _LINUX_PM_WAKEUP_H
++
++#ifndef _DEVICE_H_
++# error "please don't include this file directly"
++#endif
++
++#ifdef CONFIG_PM
++
++/* changes to device_may_wakeup take effect on the next pm state change.
++ * by default, devices should wakeup if they can.
++ */
++static inline void device_init_wakeup(struct device *dev, int val)
++{
++	dev->power.can_wakeup = dev->power.should_wakeup = !!val;
++}
++
++static inline int device_can_wakeup(struct device *dev)
++{
++	return dev->power.can_wakeup;
++}
++
++static inline void device_set_wakeup_enable(struct device *dev, int val)
++{
++	dev->power.should_wakeup = !!val;
++}
++
++static inline int device_may_wakeup(struct device *dev)
++{
++	return dev->power.can_wakeup & dev->power.should_wakeup;
++}
++
++/*
++ * Platform hook to activate device wakeup capability, if that's not already
++ * handled by enable_irq_wake() etc.
++ * Returns zero on success, else negative errno
++ */
++extern int (*platform_enable_wakeup)(struct device *dev, int is_on);
++
++static inline int call_platform_enable_wakeup(struct device *dev, int is_on)
++{
++	if (platform_enable_wakeup)
++		return (*platform_enable_wakeup)(dev, is_on);
++	return 0;
++}
++
++#else /* !CONFIG_PM */
++
++/* For some reason the next two routines work even without CONFIG_PM */
++static inline void device_init_wakeup(struct device *dev, int val)
++{
++	dev->power.can_wakeup = !!val;
++}
++
++static inline int device_can_wakeup(struct device *dev)
++{
++	return dev->power.can_wakeup;
++}
++
++#define device_set_wakeup_enable(dev, val)	do {} while (0)
++#define device_may_wakeup(dev)			0
++
++static inline int call_platform_enable_wakeup(struct device *dev, int is_on)
++{
++	return 0;
++}
++
++#endif /* !CONFIG_PM */
++
++#endif /* _LINUX_PM_WAKEUP_H */

commit d288e47c471e1090e80c62ad95882fafbf3f499d
+Author: Alan Stern 
+Date:   Wed Mar 19 22:37:42 2008 +0100
+
+    PM: Make wakeup flags available whenever CONFIG_PM is set
+    
+    The various wakeup flags and their accessor macros in struct
+    dev_pm_info should be available whenever CONFIG_PM is enabled, not
+    just when CONFIG_PM_SLEEP is on.  Otherwise remote wakeup won't always
+    be configurable for runtime power management.  This patch (as1056b)
+    fixes the oversight.
+    
+    David Brownell adds:
+            More accurately, fixes the "regression" ... as noted sometime
+            last summer, after 296699de6bdc717189a331ab6bbe90e05c94db06
+            introduced CONFIG_SUSPEND.  But that didn't make the regression
+            list for that kernel, ergo the delay in fixing it.
+    
+    [rjw: rebased]
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
+index 93a146940b91..5630af302b2f 100644
+--- a/drivers/base/power/main.c
++++ b/drivers/base/power/main.c
+@@ -57,8 +57,6 @@ static DEFINE_MUTEX(dpm_list_mtx);
+ /* 'true' if all devices have been suspended, protected by dpm_list_mtx */
+ static bool all_sleeping;
+ 
+-int (*platform_enable_wakeup)(struct device *dev, int is_on);
+-
+ /**
+  *	device_pm_add - add a device to the list of active devices
+  *	@dev:	Device to be added to the list
+diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
+index f2ed179cd695..d11f74b038db 100644
+--- a/drivers/base/power/sysfs.c
++++ b/drivers/base/power/sysfs.c
+@@ -6,6 +6,8 @@
+ #include 
+ #include "power.h"
+ 
++int (*platform_enable_wakeup)(struct device *dev, int is_on);
++
+ 
+ /*
+  *	wakeup - Report/change current wakeup option for device
+diff --git a/include/linux/pm.h b/include/linux/pm.h
+index e6b9f29e27d7..3342627e2bd6 100644
+--- a/include/linux/pm.h
++++ b/include/linux/pm.h
+@@ -183,9 +183,9 @@ typedef struct pm_message {
+ struct dev_pm_info {
+ 	pm_message_t		power_state;
+ 	unsigned		can_wakeup:1;
++	unsigned		should_wakeup:1;
+ 	bool			sleeping:1;	/* Owned by the PM core */
+ #ifdef	CONFIG_PM_SLEEP
+-	unsigned		should_wakeup:1;
+ 	struct list_head	entry;
+ #endif
+ };
+@@ -198,11 +198,6 @@ extern void device_resume(void);
+ extern int device_suspend(pm_message_t state);
+ extern int device_prepare_suspend(pm_message_t state);
+ 
+-#define device_set_wakeup_enable(dev,val) \
+-	((dev)->power.should_wakeup = !!(val))
+-#define device_may_wakeup(dev) \
+-	(device_can_wakeup(dev) && (dev)->power.should_wakeup)
+-
+ extern void __suspend_report_result(const char *function, void *fn, int ret);
+ 
+ #define suspend_report_result(fn, ret)					\
+@@ -210,6 +205,24 @@ extern void __suspend_report_result(const char *function, void *fn, int ret);
+ 		__suspend_report_result(__FUNCTION__, fn, ret);		\
+ 	} while (0)
+ 
++#else /* !CONFIG_PM_SLEEP */
++
++static inline int device_suspend(pm_message_t state)
++{
++	return 0;
++}
++
++#define suspend_report_result(fn, ret) do { } while (0)
++
++#endif /* !CONFIG_PM_SLEEP */
++
++#ifdef CONFIG_PM
++
++#define device_set_wakeup_enable(dev,val) \
++	((dev)->power.should_wakeup = !!(val))
++#define device_may_wakeup(dev) \
++	(device_can_wakeup(dev) && (dev)->power.should_wakeup)
++
+ /*
+  * Platform hook to activate device wakeup capability, if that's not already
+  * handled by enable_irq_wake() etc.
+@@ -224,24 +237,17 @@ static inline int call_platform_enable_wakeup(struct device *dev, int is_on)
+ 	return 0;
+ }
+ 
+-#else /* !CONFIG_PM_SLEEP */
+-
+-static inline int device_suspend(pm_message_t state)
+-{
+-	return 0;
+-}
++#else /* !CONFIG_PM */
+ 
+ #define device_set_wakeup_enable(dev,val)	do{}while(0)
+ #define device_may_wakeup(dev)			(0)
+ 
+-#define suspend_report_result(fn, ret) do { } while (0)
+-
+ static inline int call_platform_enable_wakeup(struct device *dev, int is_on)
+ {
+ 	return 0;
+ }
+ 
+-#endif /* !CONFIG_PM_SLEEP */
++#endif /* !CONFIG_PM */
+ 
+ /* changes to device_may_wakeup take effect on the next pm state change.
+  * by default, devices should wakeup if they can.

commit 74081f8667d73ad59961cf63be5f0e9d6a87c8a3
+Author: Alan Stern 
+Date:   Wed Mar 19 22:35:13 2008 +0100
+
+    PM: Fix misuse of wakeup flag accessors in serial core
+    
+    This patch (as1059) fixes a mistake in the way the serial core
+    initializes a device's wakeup settings.  It should use the accessor
+    routine instead of relying on a macro producing an lvalue.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
+index c32c1ca75f63..a9ca03ead3e5 100644
+--- a/drivers/serial/serial_core.c
++++ b/drivers/serial/serial_core.c
+@@ -2422,7 +2422,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
+ 	 */
+ 	tty_dev = tty_register_device(drv->tty_driver, port->line, port->dev);
+ 	if (likely(!IS_ERR(tty_dev))) {
+-		device_can_wakeup(tty_dev) = 1;
++		device_init_wakeup(tty_dev, 1);
+ 		device_set_wakeup_enable(tty_dev, 0);
+ 	} else
+ 		printk(KERN_ERR "Cannot register tty device on line %d\n",

commit 4756febb10d96104e08661031ba835771075419c
+Author: Alan Stern 
+Date:   Thu Mar 27 10:15:22 2008 -0400
+
+    USB: fix bug in sg initialization in usbtest
+    
+    This patch (as1062) fixes a bug in the scatter-gather initialization
+    code in the usbtest driver.  When the sg-helper conversion was
+    performed, it wasn't done correctly.
+    
+    Signed-off-by: Alan Stern 
+    CC: Jens Axboe 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
+index da922dfc0dcc..b6b5b2affad1 100644
+--- a/drivers/usb/misc/usbtest.c
++++ b/drivers/usb/misc/usbtest.c
+@@ -378,6 +378,7 @@ alloc_sglist (int nents, int max, int vary)
+ 	sg = kmalloc (nents * sizeof *sg, GFP_KERNEL);
+ 	if (!sg)
+ 		return NULL;
++	sg_init_table(sg, nents);
+ 
+ 	for (i = 0; i < nents; i++) {
+ 		char		*buf;
+@@ -390,7 +391,7 @@ alloc_sglist (int nents, int max, int vary)
+ 		}
+ 
+ 		/* kmalloc pages are always physically contiguous! */
+-		sg_init_one(&sg[i], buf, size);
++		sg_set_buf(&sg[i], buf, size);
+ 
+ 		switch (pattern) {
+ 		case 0:

commit 392e1d9817d0024c96aae237c3c4349e47c976fd
+Author: Alan Stern 
+Date:   Tue Mar 11 10:20:12 2008 -0400
+
+    USB: new quirk flag to avoid Set-Interface
+    
+    This patch (as1057) fixes a problem with the X-Rite/Gretag-Macbeth
+    Eye-One Pro display colorimeter; the device crashes when it receives a
+    Set-Interface request.  A new quirk (USB_QUIRK_NO_SET_INTF) is
+    introduced and a quirks entry is created for this device.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index fefb92296e8f..c311f67b7f08 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1206,7 +1206,10 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
+ 		return -EINVAL;
+ 	}
+ 
+-	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
++	if (dev->quirks & USB_QUIRK_NO_SET_INTF)
++		ret = -EPIPE;
++	else
++		ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ 				   USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE,
+ 				   alternate, interface, NULL, 0, 5000);
+ 
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index d9d1eb19f2a1..dfc5418ea10c 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -50,6 +50,9 @@ static const struct usb_device_id usb_quirk_list[] = {
+ 	/* M-Systems Flash Disk Pioneers */
+ 	{ USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
+ 
++	/* X-Rite/Gretag-Macbeth Eye-One Pro display colorimeter */
++	{ USB_DEVICE(0x0971, 0x2000), .driver_info = USB_QUIRK_NO_SET_INTF },
++
+ 	/* Action Semiconductor flash disk */
+ 	{ USB_DEVICE(0x10d6, 0x2200), .driver_info =
+ 			USB_QUIRK_STRING_FETCH_255 },
+diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h
+index 2692ec9389ca..1f999ec8d08c 100644
+--- a/include/linux/usb/quirks.h
++++ b/include/linux/usb/quirks.h
+@@ -9,3 +9,6 @@
+ 
+ /* device can't resume correctly so reset it instead */
+ #define USB_QUIRK_RESET_RESUME		0x00000002
++
++/* device can't handle Set-Interface requests */
++#define USB_QUIRK_NO_SET_INTF		0x00000004

commit 6d512a80c26d87f8599057c86dc920fbfe0aa3aa
+Author: Alan Stern 
+Date:   Fri Feb 22 17:00:06 2008 -0500
+
+    usb-storage: update earlier scatter-gather bug fix
+    
+    This patch (as1037) makes a small update to the earlier as1035 patch.
+    The minimum-length computation shouldn't be done in
+    usb_stor_access_xfer_buf(), since that routine can be called multiple
+    times for a single transfer.  It should be done in
+    usb_stor_set_xfer_buf() instead, which gets called only once.
+    
+    The way it is now isn't really _wrong_, but it isn't really _right_
+    either.  Moving the statement will be an improvement.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
+index 958f5b17847c..b9b8ede61fb3 100644
+--- a/drivers/usb/storage/protocol.c
++++ b/drivers/usb/storage/protocol.c
+@@ -170,7 +170,6 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
+ 
+ 	if (!sg)
+ 		sg = scsi_sglist(srb);
+-	buflen = min(buflen, scsi_bufflen(srb));
+ 
+ 	/* This loop handles a single s-g list entry, which may
+ 	 * include multiple pages.  Find the initial page structure
+@@ -232,6 +231,7 @@ void usb_stor_set_xfer_buf(unsigned char *buffer,
+ 	unsigned int offset = 0;
+ 	struct scatterlist *sg = NULL;
+ 
++	buflen = min(buflen, scsi_bufflen(srb));
+ 	buflen = usb_stor_access_xfer_buf(buffer, buflen, srb, &sg, &offset,
+ 			TO_XFER_BUF);
+ 	if (buflen < scsi_bufflen(srb))

commit 14f3546f32d69adaa303b72e5a999e85abe83f9a
+Author: Alan Stern 
+Date:   Wed Feb 27 15:43:47 2008 -0500
+
+    USB: spruce up the device blacklist
+    
+    This patch (as1040) fixes up the blacklist of USB device quirks.  A
+    couple of lines are broken to comply with the 80-column rule, and
+    entries are sorted into the proper numerical order.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index f90ab5e94c58..d9d1eb19f2a1 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -28,35 +28,38 @@
+  * devices is broken...
+  */
+ static const struct usb_device_id usb_quirk_list[] = {
+-	/* Action Semiconductor flash disk */
+-	{ USB_DEVICE(0x10d6, 0x2200), .driver_info = USB_QUIRK_STRING_FETCH_255},
+-
+ 	/* CBM - Flash disk */
+ 	{ USB_DEVICE(0x0204, 0x6025), .driver_info = USB_QUIRK_RESET_RESUME },
++
+ 	/* HP 5300/5370C scanner */
+-	{ USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 },
++	{ USB_DEVICE(0x03f0, 0x0701), .driver_info =
++			USB_QUIRK_STRING_FETCH_255 },
+ 
+ 	/* Creative SB Audigy 2 NX */
+ 	{ USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME },
+ 
++	/* Philips PSC805 audio device */
++	{ USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME },
++
+ 	/* Roland SC-8820 */
+ 	{ USB_DEVICE(0x0582, 0x0007), .driver_info = USB_QUIRK_RESET_RESUME },
+ 
+ 	/* Edirol SD-20 */
+ 	{ USB_DEVICE(0x0582, 0x0027), .driver_info = USB_QUIRK_RESET_RESUME },
+ 
+-	/* INTEL VALUE SSD */
+-	{ USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
+-
+ 	/* M-Systems Flash Disk Pioneers */
+ 	{ USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
+ 
+-	/* Philips PSC805 audio device */
+-	{ USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME },
++	/* Action Semiconductor flash disk */
++	{ USB_DEVICE(0x10d6, 0x2200), .driver_info =
++			USB_QUIRK_STRING_FETCH_255 },
+ 
+ 	/* SKYMEDI USB_DRIVE */
+ 	{ USB_DEVICE(0x1516, 0x8628), .driver_info = USB_QUIRK_RESET_RESUME },
+ 
++	/* INTEL VALUE SSD */
++	{ USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
++
+ 	{ }  /* terminating entry must be last */
+ };
+ 

commit c2c8d1fdadda4abc90efdb7176f44cb903634511
+Author: Alan Stern 
+Date:   Mon Feb 25 11:43:32 2008 -0500
+
+    USB: update Kconfig entry for USB_SUSPEND
+    
+    This patch (as1039) updates the Kconfig entry for USB_SUSPEND.  The
+    out-of-date reference to "power/state" is fixed, autosuspend is
+    mentioned, and the dependency on EXPERIMENTAL is removed.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
+index 5c33cdb9cac7..a2b0aa48b8ea 100644
+--- a/drivers/usb/core/Kconfig
++++ b/drivers/usb/core/Kconfig
+@@ -87,12 +87,13 @@ config USB_DYNAMIC_MINORS
+ 	  If you are unsure about this, say N here.
+ 
+ config USB_SUSPEND
+-	bool "USB selective suspend/resume and wakeup (EXPERIMENTAL)"
+-	depends on USB && PM && EXPERIMENTAL
++	bool "USB selective suspend/resume and wakeup"
++	depends on USB && PM
+ 	help
+ 	  If you say Y here, you can use driver calls or the sysfs
+-	  "power/state" file to suspend or resume individual USB
+-	  peripherals.
++	  "power/level" file to suspend or resume individual USB
++	  peripherals and to enable or disable autosuspend (see
++	  Documentation/usb/power-management.txt for more details).
+ 
+ 	  Also, USB "remote wakeup" signaling is supported, whereby some
+ 	  USB devices (like keyboards and network adapters) can wake up

commit 1b3cbec1dcb6747b587b40335f5de1d9e035063c
+Author: Alan Stern 
+Date:   Fri Feb 29 11:50:22 2008 -0500
+
+    PM: fix new mutex-locking bug in the PM core
+    
+    This patch (as1041) fixes a bug introduced by the
+    acquire-all-device-semaphores reversion.  The error pathway of
+    dpm_suspend() fails to reacquire a mutex it should be holding.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
+index b0c16f6fc186..d887d5cb5bef 100644
+--- a/drivers/base/power/main.c
++++ b/drivers/base/power/main.c
+@@ -428,6 +428,7 @@ static int dpm_suspend(pm_message_t state)
+ 
+ 		mutex_unlock(&dpm_list_mtx);
+ 		error = suspend_device(dev, state);
++		mutex_lock(&dpm_list_mtx);
+ 		if (error) {
+ 			printk(KERN_ERR "Could not suspend device %s: "
+ 					"error %d%s\n",
+@@ -438,7 +439,6 @@ static int dpm_suspend(pm_message_t state)
+ 					""));
+ 			break;
+ 		}
+-		mutex_lock(&dpm_list_mtx);
+ 		if (!list_empty(&dev->power.entry))
+ 			list_move(&dev->power.entry, &dpm_off);
+ 	}

commit 7084191d53b224b953c8e1db525ea6c31aca5fc7
+Author: Alan Stern 
+Date:   Wed Feb 20 14:15:58 2008 -0500
+
+    USB: usb-storage: don't access beyond the end of the sg buffer
+    
+    This patch (as1035) fixes a bug in usb_stor_access_xfer_buf() (the bug
+    was originally found by Boaz Harrosh): The routine must not attempt to
+    write beyond the end of a scatter-gather list or beyond the number of
+    bytes requested.  It also fixes up the formatting of a few comments
+    and similar whitespace issues.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
+index a41ce21c0697..958f5b17847c 100644
+--- a/drivers/usb/storage/protocol.c
++++ b/drivers/usb/storage/protocol.c
+@@ -150,13 +150,14 @@ void usb_stor_transparent_scsi_command(struct scsi_cmnd *srb,
+ 
+ /* Copy a buffer of length buflen to/from the srb's transfer buffer.
+  * Update the **sgptr and *offset variables so that the next copy will
+- * pick up from where this one left off. */
+-
++ * pick up from where this one left off.
++ */
+ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
+ 	unsigned int buflen, struct scsi_cmnd *srb, struct scatterlist **sgptr,
+ 	unsigned int *offset, enum xfer_buf_dir dir)
+ {
+ 	unsigned int cnt;
++	struct scatterlist *sg = *sgptr;
+ 
+ 	/* We have to go through the list one entry
+ 	 * at a time.  Each s-g entry contains some number of pages, and
+@@ -164,22 +165,23 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
+ 	 * in kernel-addressable memory then kmap() will return its address.
+ 	 * If the page is not directly accessible -- such as a user buffer
+ 	 * located in high memory -- then kmap() will map it to a temporary
+-	 * position in the kernel's virtual address space. */
+-	struct scatterlist *sg = *sgptr;
++	 * position in the kernel's virtual address space.
++	 */
+ 
+ 	if (!sg)
+ 		sg = scsi_sglist(srb);
++	buflen = min(buflen, scsi_bufflen(srb));
+ 
+ 	/* This loop handles a single s-g list entry, which may
+-		* include multiple pages.  Find the initial page structure
+-		* and the starting offset within the page, and update
+-		* the *offset and **sgptr values for the next loop. */
++	 * include multiple pages.  Find the initial page structure
++	 * and the starting offset within the page, and update
++	 * the *offset and **sgptr values for the next loop.
++	 */
+ 	cnt = 0;
+-	while (cnt < buflen) {
++	while (cnt < buflen && sg) {
+ 		struct page *page = sg_page(sg) +
+ 				((sg->offset + *offset) >> PAGE_SHIFT);
+-		unsigned int poff =
+-				(sg->offset + *offset) & (PAGE_SIZE-1);
++		unsigned int poff = (sg->offset + *offset) & (PAGE_SIZE-1);
+ 		unsigned int sglen = sg->length - *offset;
+ 
+ 		if (sglen > buflen - cnt) {
+@@ -222,14 +224,15 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
+ }
+ 
+ /* Store the contents of buffer into srb's transfer buffer and set the
+- * SCSI residue. */
++ * SCSI residue.
++ */
+ void usb_stor_set_xfer_buf(unsigned char *buffer,
+ 	unsigned int buflen, struct scsi_cmnd *srb)
+ {
+ 	unsigned int offset = 0;
+ 	struct scatterlist *sg = NULL;
+ 
+-	usb_stor_access_xfer_buf(buffer, buflen, srb, &sg, &offset,
++	buflen = usb_stor_access_xfer_buf(buffer, buflen, srb, &sg, &offset,
+ 			TO_XFER_BUF);
+ 	if (buflen < scsi_bufflen(srb))
+ 		scsi_set_resid(srb, scsi_bufflen(srb) - buflen);

commit 274399d14f121d7676ecb75a461cfed6cf9e4cdb
+Author: Alan Stern 
+Date:   Wed Feb 20 12:10:04 2008 -0500
+
+    USB: quirks and unusual_devs entry for Actions flash drive
+    
+    This patch (as1033) adds a quirks entry and an unusual_devs entry for
+    the Actions Semiconductor flash drive.  This device has a 64-byte
+    string descriptor, which it doesn't terminate with a 0-length packet.
+    
+    Oddly enough, the reporter's logs show that when the device was
+    plugged in at boot time, it changes its behavior completely -- it uses
+    a different product ID, product string descriptor, and bDeviceClass.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index dc51790582d6..f90ab5e94c58 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -28,6 +28,9 @@
+  * devices is broken...
+  */
+ static const struct usb_device_id usb_quirk_list[] = {
++	/* Action Semiconductor flash disk */
++	{ USB_DEVICE(0x10d6, 0x2200), .driver_info = USB_QUIRK_STRING_FETCH_255},
++
+ 	/* CBM - Flash disk */
+ 	{ USB_DEVICE(0x0204, 0x6025), .driver_info = USB_QUIRK_RESET_RESUME },
+ 	/* HP 5300/5370C scanner */
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 6494cc52a11d..99679a8cfa02 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -1500,6 +1500,15 @@ UNUSUAL_DEV(  0x1019, 0x0c55, 0x0000, 0x0110,
+ 		US_SC_DEVICE, US_PR_DEVICE, usb_stor_ucr61s2b_init,
+ 		0 ),
+ 
++/* Reported by Fabio Venturi 
++ * The device reports a vendor-specific bDeviceClass.
++ */
++UNUSUAL_DEV(  0x10d6, 0x2200, 0x0100, 0x0100,
++		"Actions Semiconductor",
++		"Mtp device",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		0),
++
+ /* Reported by Kevin Lloyd 
+  * Entry is needed for the initializer function override,
+  * which instructs the device to load as a modem

commit a462549b6ad6d4de19a7702c13fbb954d9a10f29
+Author: Alan Stern 
+Date:   Wed Feb 13 10:45:28 2008 -0500
+
+    USB: usb-storage: don't clear-halt when Get-Max-LUN stalls
+    
+    This patch (as1032) removes the Clear-Halt calls in
+    usb_stor_Bulk_max_lun().  Evidently some devices (such as the Oracom
+    MP3 player) really don't like to receive these requests when their
+    bulk endpoints aren't halted.
+    
+    The only reason for adding them originally was to get an ancient
+    ZIP-100 drive to work.  But since this device has only a single LUN,
+    we don't need to send it a Get-Max-LUN request at all.  Adding an
+    unusual_devs entry for the ZIP-100 with the SINGLE_LUN flag set will
+    cause this step to be skipped.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+index d9f4912f873d..5780ed15f1ad 100644
+--- a/drivers/usb/storage/transport.c
++++ b/drivers/usb/storage/transport.c
+@@ -891,17 +891,6 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
+ 	if (result > 0)
+ 		return us->iobuf[0];
+ 
+-	/* 
+-	 * Some devices (i.e. Iomega Zip100) need this -- apparently
+-	 * the bulk pipes get STALLed when the GetMaxLUN request is
+-	 * processed.   This is, in theory, harmless to all other devices
+-	 * (regardless of if they stall or not).
+-	 */
+-	if (result == -EPIPE) {
+-		usb_stor_clear_halt(us, us->recv_bulk_pipe);
+-		usb_stor_clear_halt(us, us->send_bulk_pipe);
+-	}
+-
+ 	/*
+ 	 * Some devices don't like GetMaxLUN.  They may STALL the control
+ 	 * pipe, they may return a zero-length result, they may do nothing at
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index fe12737e0e2b..a97e7ef252f0 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -759,6 +759,18 @@ UNUSUAL_DEV(  0x0595, 0x4343, 0x0000, 0x2210,
+ 		"Digital Camera EX-20 DSC",
+ 		US_SC_8070, US_PR_DEVICE, NULL, 0 ),
+ 
++/* Reported by Andre Welter 
++ * This antique device predates the release of the Bulk-only Transport
++ * spec, and if it gets a Get-Max-LUN then it requires the host to do a
++ * Clear-Halt on the bulk endpoints.  The SINGLE_LUN flag will prevent
++ * us from sending the request.
++ */
++UNUSUAL_DEV(  0x059b, 0x0001, 0x0100, 0x0100,
++		"Iomega",
++		"ZIP 100",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_SINGLE_LUN ),
++
+ /* Reported by  */
+ UNUSUAL_DEV(  0x059f, 0x0643, 0x0000, 0x0000,
+ 		"LaCie",

commit 825257569350e913bee3bc918508c0aa6e3398cd
+Author: Alan Stern 
+Date:   Mon Nov 19 23:49:18 2007 +0100
+
+    PM: Convert PM notifiers to out-of-line code
+    
+    This patch (as1008b) converts the PM notifier routines from inline
+    calls to out-of-line code.  It also prevents pm_chain_head from
+    being created when CONFIG_PM_SLEEP isn't enabled, and EXPORTs the
+    notifier registration and unregistration routines.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Rafael J. Wysocki 
+    Signed-off-by: Len Brown 
+
+diff --git a/include/linux/suspend.h b/include/linux/suspend.h
+index 40280df2a3db..51283e0745b3 100644
+--- a/include/linux/suspend.h
++++ b/include/linux/suspend.h
+@@ -213,17 +213,8 @@ void save_processor_state(void);
+ void restore_processor_state(void);
+ 
+ /* kernel/power/main.c */
+-extern struct blocking_notifier_head pm_chain_head;
+-
+-static inline int register_pm_notifier(struct notifier_block *nb)
+-{
+-	return blocking_notifier_chain_register(&pm_chain_head, nb);
+-}
+-
+-static inline int unregister_pm_notifier(struct notifier_block *nb)
+-{
+-	return blocking_notifier_chain_unregister(&pm_chain_head, nb);
+-}
++extern int register_pm_notifier(struct notifier_block *nb);
++extern int unregister_pm_notifier(struct notifier_block *nb);
+ 
+ #define pm_notifier(fn, pri) {				\
+ 	static struct notifier_block fn##_nb =			\
+diff --git a/kernel/power/main.c b/kernel/power/main.c
+index fc717b836828..0a9f269075ee 100644
+--- a/kernel/power/main.c
++++ b/kernel/power/main.c
+@@ -24,13 +24,37 @@
+ 
+ #include "power.h"
+ 
+-BLOCKING_NOTIFIER_HEAD(pm_chain_head);
+-
+ DEFINE_MUTEX(pm_mutex);
+ 
+ unsigned int pm_flags;
+ EXPORT_SYMBOL(pm_flags);
+ 
++#ifdef CONFIG_PM_SLEEP
++
++/* Routines for PM-transition notifications */
++
++static BLOCKING_NOTIFIER_HEAD(pm_chain_head);
++
++int register_pm_notifier(struct notifier_block *nb)
++{
++	return blocking_notifier_chain_register(&pm_chain_head, nb);
++}
++EXPORT_SYMBOL_GPL(register_pm_notifier);
++
++int unregister_pm_notifier(struct notifier_block *nb)
++{
++	return blocking_notifier_chain_unregister(&pm_chain_head, nb);
++}
++EXPORT_SYMBOL_GPL(unregister_pm_notifier);
++
++int pm_notifier_call_chain(unsigned long val)
++{
++	return (blocking_notifier_call_chain(&pm_chain_head, val, NULL)
++			== NOTIFY_BAD) ? -EINVAL : 0;
++}
++
++#endif /* CONFIG_PM_SLEEP */
++
+ #ifdef CONFIG_PM_DEBUG
+ int pm_test_level = TEST_NONE;
+ 
+diff --git a/kernel/power/power.h b/kernel/power/power.h
+index f9f0d4d26c50..a9732fd12239 100644
+--- a/kernel/power/power.h
++++ b/kernel/power/power.h
+@@ -172,14 +172,10 @@ static inline int suspend_devices_and_enter(suspend_state_t state)
+ }
+ #endif /* !CONFIG_SUSPEND */
+ 
+-/* kernel/power/common.c */
+-extern struct blocking_notifier_head pm_chain_head;
+-
+-static inline int pm_notifier_call_chain(unsigned long val)
+-{
+-	return (blocking_notifier_call_chain(&pm_chain_head, val, NULL)
+-			== NOTIFY_BAD) ? -EINVAL : 0;
+-}
++#ifdef CONFIG_PM_SLEEP
++/* kernel/power/main.c */
++extern int pm_notifier_call_chain(unsigned long val);
++#endif
+ 
+ #ifdef CONFIG_HIGHMEM
+ unsigned int count_highmem_pages(void);

commit c3e94d899c864e558f938f9845ddb8c2e5d5ccd0
+Author: Alan Stern 
+Date:   Mon Nov 19 23:38:25 2007 +0100
+
+    Hibernation: Add PM_RESTORE_PREPARE and PM_POST_RESTORE notifiers (rev. 2)
+    
+    Add PM_RESTORE_PREPARE and PM_POST_RESTORE notifiers to the PM core, to be used
+    in analogy with the existing PM_HIBERNATION_PREPARE and PM_POST_HIBERNATION
+    notifiers.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Pavel Machek 
+    Signed-off-by: "Rafael J. Wysocki" 
+    Signed-off-by: Len Brown 
+
+diff --git a/Documentation/power/notifiers.txt b/Documentation/power/notifiers.txt
+index 9293e4bc857c..ae1b7ec07684 100644
+--- a/Documentation/power/notifiers.txt
++++ b/Documentation/power/notifiers.txt
+@@ -28,6 +28,14 @@ PM_POST_HIBERNATION	The system memory state has been restored from a
+ 			hibernation.  Device drivers' .resume() callbacks have
+ 			been executed and tasks have been thawed.
+ 
++PM_RESTORE_PREPARE	The system is going to restore a hibernation image.
++			If all goes well the restored kernel will issue a
++			PM_POST_HIBERNATION notification.
++
++PM_POST_RESTORE		An error occurred during the hibernation restore.
++			Device drivers' .resume() callbacks have been executed
++			and tasks have been thawed.
++
+ PM_SUSPEND_PREPARE	The system is preparing for a suspend.
+ 
+ PM_POST_SUSPEND		The system has just resumed or an error occured during
+diff --git a/include/linux/notifier.h b/include/linux/notifier.h
+index 5dfbc684ce7d..f4df40038f0c 100644
+--- a/include/linux/notifier.h
++++ b/include/linux/notifier.h
+@@ -228,6 +228,8 @@ static inline int notifier_to_errno(int ret)
+ #define PM_POST_HIBERNATION	0x0002 /* Hibernation finished */
+ #define PM_SUSPEND_PREPARE	0x0003 /* Going to suspend the system */
+ #define PM_POST_SUSPEND		0x0004 /* Suspend finished */
++#define PM_RESTORE_PREPARE	0x0005 /* Going to restore a saved image */
++#define PM_POST_RESTORE		0x0006 /* Restore failed */
+ 
+ /* Console keyboard events.
+  * Note: KBD_KEYCODE is always sent before KBD_UNBOUND_KEYCODE, KBD_UNICODE and
+diff --git a/kernel/power/disk.c b/kernel/power/disk.c
+index b138b431e271..659736508239 100644
+--- a/kernel/power/disk.c
++++ b/kernel/power/disk.c
+@@ -499,6 +499,10 @@ static int software_resume(void)
+ 		goto Unlock;
+ 	}
+ 
++	error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
++	if (error)
++		goto Finish;
++
+ 	error = create_basic_memory_bitmaps();
+ 	if (error)
+ 		goto Finish;
+@@ -522,6 +526,7 @@ static int software_resume(void)
+  Done:
+ 	free_basic_memory_bitmaps();
+  Finish:
++	pm_notifier_call_chain(PM_POST_RESTORE);
+ 	atomic_inc(&snapshot_device_available);
+ 	/* For success case, the suspend path will release the lock */
+  Unlock:
+diff --git a/kernel/power/user.c b/kernel/power/user.c
+index b902a7e3bd12..f5512cb3aa86 100644
+--- a/kernel/power/user.c
++++ b/kernel/power/user.c
+@@ -67,6 +67,7 @@ atomic_t snapshot_device_available = ATOMIC_INIT(1);
+ static int snapshot_open(struct inode *inode, struct file *filp)
+ {
+ 	struct snapshot_data *data;
++	int error;
+ 
+ 	if (!atomic_add_unless(&snapshot_device_available, -1, 0))
+ 		return -EBUSY;
+@@ -87,9 +88,19 @@ static int snapshot_open(struct inode *inode, struct file *filp)
+ 		data->swap = swsusp_resume_device ?
+ 			swap_type_of(swsusp_resume_device, 0, NULL) : -1;
+ 		data->mode = O_RDONLY;
++		error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
++		if (error)
++			pm_notifier_call_chain(PM_POST_RESTORE);
+ 	} else {
+ 		data->swap = -1;
+ 		data->mode = O_WRONLY;
++		error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
++		if (error)
++			pm_notifier_call_chain(PM_POST_HIBERNATION);
++	}
++	if (error) {
++		atomic_inc(&snapshot_device_available);
++		return error;
+ 	}
+ 	data->frozen = 0;
+ 	data->ready = 0;
+@@ -111,6 +122,8 @@ static int snapshot_release(struct inode *inode, struct file *filp)
+ 		thaw_processes();
+ 		mutex_unlock(&pm_mutex);
+ 	}
++	pm_notifier_call_chain(data->mode == O_WRONLY ?
++			PM_POST_HIBERNATION : PM_POST_RESTORE);
+ 	atomic_inc(&snapshot_device_available);
+ 	return 0;
+ }
+@@ -174,18 +187,13 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
+ 		if (data->frozen)
+ 			break;
+ 		mutex_lock(&pm_mutex);
+-		error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
+-		if (!error) {
+-			printk("Syncing filesystems ... ");
+-			sys_sync();
+-			printk("done.\n");
+-
+-			error = freeze_processes();
+-			if (error)
+-				thaw_processes();
+-		}
++		printk("Syncing filesystems ... ");
++		sys_sync();
++		printk("done.\n");
++
++		error = freeze_processes();
+ 		if (error)
+-			pm_notifier_call_chain(PM_POST_HIBERNATION);
++			thaw_processes();
+ 		mutex_unlock(&pm_mutex);
+ 		if (!error)
+ 			data->frozen = 1;
+@@ -196,7 +204,6 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
+ 			break;
+ 		mutex_lock(&pm_mutex);
+ 		thaw_processes();
+-		pm_notifier_call_chain(PM_POST_HIBERNATION);
+ 		mutex_unlock(&pm_mutex);
+ 		data->frozen = 0;
+ 		break;

commit cd930c931417295ac6b4d9fea62accc67192ac34
+Author: Alan Stern 
+Date:   Thu Jan 10 11:14:53 2008 -0500
+
+    USB: EHCI: add a short delay to the bus_suspend routine
+    
+    This patch (as1031) adds a short delay to the bus-suspend routine in
+    ehci-hcd.  Without it some devices disconnect when they should
+    suspend.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 7919a411d5f9..ccd88ae011c6 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -172,6 +172,10 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 		}
+ 	}
+ 
++	/* Apparently some devices need a >= 1-uframe delay here */
++	if (ehci->bus_suspended)
++		udelay(150);
++
+ 	/* turn off now-idle HC */
+ 	ehci_halt (ehci);
+ 	hcd->state = HC_STATE_SUSPENDED;

commit f8fa7571a928d6d0e1b7444b0ea69ec7dc7db3b6
+Author: Alan Stern 
+Date:   Thu Jan 10 16:43:15 2008 -0500
+
+    USB: EHCI: move del_timer_sync calls outside spinlocked region
+    
+    This patch (as1030b) moves a del_timer_sync() call outside the scope of a
+    spinlock, where it could cause a deadlock, and adds a new
+    del_timer_sync() call for the new IAA watchdog timer (it was omitted
+    by mistake).
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index a249d03a5024..7919a411d5f9 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -123,6 +123,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 
+ 	if (time_before (jiffies, ehci->next_statechange))
+ 		msleep(5);
++	del_timer_sync(&ehci->watchdog);
++	del_timer_sync(&ehci->iaa_watchdog);
+ 
+ 	port = HCS_N_PORTS (ehci->hcs_params);
+ 	spin_lock_irq (&ehci->lock);
+@@ -171,7 +173,6 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 	}
+ 
+ 	/* turn off now-idle HC */
+-	del_timer_sync (&ehci->watchdog);
+ 	ehci_halt (ehci);
+ 	hcd->state = HC_STATE_SUSPENDED;
+ 

commit caf29f62655e7aa57996821535d11fa3b0537b6b
+Author: Alan Stern 
+Date:   Thu Dec 6 11:10:39 2007 -0500
+
+    USB: dummy_hcd: change the default power budget
+    
+    This patch (as1025) changes the default power budget for dummy-hcd to
+    500 mA and makes it a preprocessor parameter for easier testing.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index 1a8a5f33443e..cbe44535c0f0 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -61,6 +61,8 @@
+ #define DRIVER_DESC	"USB Host+Gadget Emulator"
+ #define DRIVER_VERSION	"02 May 2005"
+ 
++#define POWER_BUDGET	500	/* in mA; use 8 for low-power port testing */
++
+ static const char	driver_name [] = "dummy_hcd";
+ static const char	driver_desc [] = "USB Host+Gadget Emulator";
+ 
+@@ -1810,8 +1812,7 @@ static int dummy_start (struct usb_hcd *hcd)
+ 
+ 	INIT_LIST_HEAD (&dum->urbp_list);
+ 
+-	/* only show a low-power port: just 8mA */
+-	hcd->power_budget = 8;
++	hcd->power_budget = POWER_BUDGET;
+ 	hcd->state = HC_STATE_RUNNING;
+ 	hcd->uses_new_polling = 1;
+ 

commit 07d29b63ef6b39963ab37818653284d861cf55af
+Author: Alan Stern 
+Date:   Tue Dec 11 16:05:30 2007 -0500
+
+    USB: EHCI: add separate IAA watchdog timer
+    
+    This patch (as1028) was mostly written by David Brownell; I made only
+    a few changes (extra log info and a small bug fix -- which might
+    account for why David's version had to be reverted).  It adds a new
+    watchdog timer to the ehci-hcd driver to be used exclusively for
+    detecting lost or missing IAA notifications.
+    
+    Previously a shared timer had been used, which may have led to some
+    problems as reported by Christian Hoffmann.
+    
+    Signed-off-by: Alan Stern 
+    Cc: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
+index 39673f8194d9..64ebfc5548a3 100644
+--- a/drivers/usb/host/ehci-dbg.c
++++ b/drivers/usb/host/ehci-dbg.c
+@@ -786,9 +786,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
+ 	}
+ 
+ 	if (ehci->reclaim) {
+-		temp = scnprintf (next, size, "reclaim qh %p%s\n",
+-				ehci->reclaim,
+-				ehci->reclaim_ready ? " ready" : "");
++		temp = scnprintf(next, size, "reclaim qh %p\n", ehci->reclaim);
+ 		size -= temp;
+ 		next += temp;
+ 	}
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 264182654f4c..5917c6b7ce33 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -110,7 +110,7 @@ static const char	hcd_name [] = "ehci_hcd";
+ #define	EHCI_TUNE_MULT_TT	1
+ #define	EHCI_TUNE_FLS		2	/* (small) 256 frame schedule */
+ 
+-#define EHCI_IAA_JIFFIES	(HZ/100)	/* arbitrary; ~10 msec */
++#define EHCI_IAA_MSECS		10		/* arbitrary */
+ #define EHCI_IO_JIFFIES		(HZ/10)		/* io watchdog > irq_thresh */
+ #define EHCI_ASYNC_JIFFIES	(HZ/20)		/* async idle timeout */
+ #define EHCI_SHRINK_JIFFIES	(HZ/200)	/* async qh unlink delay */
+@@ -267,6 +267,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++static void end_unlink_async(struct ehci_hcd *ehci);
+ static void ehci_work(struct ehci_hcd *ehci);
+ 
+ #include "ehci-hub.c"
+@@ -276,25 +277,41 @@ static void ehci_work(struct ehci_hcd *ehci);
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-static void ehci_watchdog (unsigned long param)
++static void ehci_iaa_watchdog(unsigned long param)
+ {
+ 	struct ehci_hcd		*ehci = (struct ehci_hcd *) param;
+ 	unsigned long		flags;
++	u32			status, cmd;
+ 
+ 	spin_lock_irqsave (&ehci->lock, flags);
++	WARN_ON(!ehci->reclaim);
+ 
+-	/* lost IAA irqs wedge things badly; seen with a vt8235 */
++	status = ehci_readl(ehci, &ehci->regs->status);
++	cmd = ehci_readl(ehci, &ehci->regs->command);
++	ehci_dbg(ehci, "IAA watchdog: status %x cmd %x\n", status, cmd);
++
++	/* lost IAA irqs wedge things badly; seen first with a vt8235 */
+ 	if (ehci->reclaim) {
+-		u32		status = ehci_readl(ehci, &ehci->regs->status);
+ 		if (status & STS_IAA) {
+ 			ehci_vdbg (ehci, "lost IAA\n");
+ 			COUNT (ehci->stats.lost_iaa);
+ 			ehci_writel(ehci, STS_IAA, &ehci->regs->status);
+-			ehci->reclaim_ready = 1;
+ 		}
++		ehci_writel(ehci, cmd & ~CMD_IAAD, &ehci->regs->command);
++		end_unlink_async(ehci);
+ 	}
+ 
+- 	/* stop async processing after it's idled a bit */
++	spin_unlock_irqrestore(&ehci->lock, flags);
++}
++
++static void ehci_watchdog(unsigned long param)
++{
++	struct ehci_hcd		*ehci = (struct ehci_hcd *) param;
++	unsigned long		flags;
++
++	spin_lock_irqsave(&ehci->lock, flags);
++
++	/* stop async processing after it's idled a bit */
+ 	if (test_bit (TIMER_ASYNC_OFF, &ehci->actions))
+ 		start_unlink_async (ehci, ehci->async);
+ 
+@@ -364,8 +381,6 @@ static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
+ static void ehci_work (struct ehci_hcd *ehci)
+ {
+ 	timer_action_done (ehci, TIMER_IO_WATCHDOG);
+-	if (ehci->reclaim_ready)
+-		end_unlink_async (ehci);
+ 
+ 	/* another CPU may drop ehci->lock during a schedule scan while
+ 	 * it reports urb completions.  this flag guards against bogus
+@@ -400,6 +415,7 @@ static void ehci_stop (struct usb_hcd *hcd)
+ 
+ 	/* no more interrupts ... */
+ 	del_timer_sync (&ehci->watchdog);
++	del_timer_sync(&ehci->iaa_watchdog);
+ 
+ 	spin_lock_irq(&ehci->lock);
+ 	if (HC_IS_RUNNING (hcd->state))
+@@ -448,6 +464,10 @@ static int ehci_init(struct usb_hcd *hcd)
+ 	ehci->watchdog.function = ehci_watchdog;
+ 	ehci->watchdog.data = (unsigned long) ehci;
+ 
++	init_timer(&ehci->iaa_watchdog);
++	ehci->iaa_watchdog.function = ehci_iaa_watchdog;
++	ehci->iaa_watchdog.data = (unsigned long) ehci;
++
+ 	/*
+ 	 * hw default: 1K periodic list heads, one per frame.
+ 	 * periodic_size can shrink by USBCMD update if hcc_params allows.
+@@ -464,7 +484,6 @@ static int ehci_init(struct usb_hcd *hcd)
+ 		ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params);
+ 
+ 	ehci->reclaim = NULL;
+-	ehci->reclaim_ready = 0;
+ 	ehci->next_uframe = -1;
+ 
+ 	/*
+@@ -655,8 +674,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 	/* complete the unlinking of some qh [4.15.2.3] */
+ 	if (status & STS_IAA) {
+ 		COUNT (ehci->stats.reclaim);
+-		ehci->reclaim_ready = 1;
+-		bh = 1;
++		end_unlink_async(ehci);
+ 	}
+ 
+ 	/* remote wakeup [4.3.1] */
+@@ -762,10 +780,16 @@ static int ehci_urb_enqueue (
+ 
+ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ {
+-	/* if we need to use IAA and it's busy, defer */
+-	if (qh->qh_state == QH_STATE_LINKED
+-			&& ehci->reclaim
+-			&& HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) {
++	/* failfast */
++	if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state))
++		end_unlink_async(ehci);
++
++	/* if it's not linked then there's nothing to do */
++	if (qh->qh_state != QH_STATE_LINKED)
++		;
++
++	/* defer till later if busy */
++	else if (ehci->reclaim) {
+ 		struct ehci_qh		*last;
+ 
+ 		for (last = ehci->reclaim;
+@@ -775,12 +799,8 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		qh->qh_state = QH_STATE_UNLINK_WAIT;
+ 		last->reclaim = qh;
+ 
+-	/* bypass IAA if the hc can't care */
+-	} else if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim)
+-		end_unlink_async (ehci);
+-
+-	/* something else might have unlinked the qh by now */
+-	if (qh->qh_state == QH_STATE_LINKED)
++	/* start IAA cycle */
++	} else
+ 		start_unlink_async (ehci, qh);
+ }
+ 
+@@ -807,7 +827,19 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ 		qh = (struct ehci_qh *) urb->hcpriv;
+ 		if (!qh)
+ 			break;
+-		unlink_async (ehci, qh);
++		switch (qh->qh_state) {
++		case QH_STATE_LINKED:
++		case QH_STATE_COMPLETING:
++			unlink_async(ehci, qh);
++			break;
++		case QH_STATE_UNLINK:
++		case QH_STATE_UNLINK_WAIT:
++			/* already started */
++			break;
++		case QH_STATE_IDLE:
++			WARN_ON(1);
++			break;
++		}
+ 		break;
+ 
+ 	case PIPE_INTERRUPT:
+@@ -899,6 +931,7 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+ 		unlink_async (ehci, qh);
+ 		/* FALL THROUGH */
+ 	case QH_STATE_UNLINK:		/* wait for hw to finish? */
++	case QH_STATE_UNLINK_WAIT:
+ idle_timeout:
+ 		spin_unlock_irqrestore (&ehci->lock, flags);
+ 		schedule_timeout_uninterruptible(1);
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index a165e0a0961c..a249d03a5024 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -134,7 +134,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 	}
+ 	ehci->command = ehci_readl(ehci, &ehci->regs->command);
+ 	if (ehci->reclaim)
+-		ehci->reclaim_ready = 1;
++		end_unlink_async(ehci);
+ 	ehci_work(ehci);
+ 
+ 	/* Unlike other USB host controller types, EHCI doesn't have
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index 45e040000280..3ba01664f821 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -305,7 +305,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
+ 	/* emptying the schedule aborts any urbs */
+ 	spin_lock_irq(&ehci->lock);
+ 	if (ehci->reclaim)
+-		ehci->reclaim_ready = 1;
++		end_unlink_async(ehci);
+ 	ehci_work(ehci);
+ 	spin_unlock_irq(&ehci->lock);
+ 
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index b10f39c047e9..853e5e6396a5 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -973,7 +973,7 @@ static void end_unlink_async (struct ehci_hcd *ehci)
+ 	struct ehci_qh		*qh = ehci->reclaim;
+ 	struct ehci_qh		*next;
+ 
+-	timer_action_done (ehci, TIMER_IAA_WATCHDOG);
++	iaa_watchdog_done(ehci);
+ 
+ 	// qh->hw_next = cpu_to_hc32(qh->qh_dma);
+ 	qh->qh_state = QH_STATE_IDLE;
+@@ -983,7 +983,6 @@ static void end_unlink_async (struct ehci_hcd *ehci)
+ 	/* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */
+ 	next = qh->reclaim;
+ 	ehci->reclaim = next;
+-	ehci->reclaim_ready = 0;
+ 	qh->reclaim = NULL;
+ 
+ 	qh_completions (ehci, qh);
+@@ -1059,11 +1058,10 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		return;
+ 	}
+ 
+-	ehci->reclaim_ready = 0;
+ 	cmd |= CMD_IAAD;
+ 	ehci_writel(ehci, cmd, &ehci->regs->command);
+ 	(void)ehci_readl(ehci, &ehci->regs->command);
+-	timer_action (ehci, TIMER_IAA_WATCHDOG);
++	iaa_watchdog_start(ehci);
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 10e71417c352..eeda4c88ebae 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -74,7 +74,6 @@ struct ehci_hcd {			/* one per controller */
+ 	/* async schedule support */
+ 	struct ehci_qh		*async;
+ 	struct ehci_qh		*reclaim;
+-	unsigned		reclaim_ready : 1;
+ 	unsigned		scanning : 1;
+ 
+ 	/* periodic schedule support */
+@@ -105,6 +104,7 @@ struct ehci_hcd {			/* one per controller */
+ 	struct dma_pool		*itd_pool;	/* itd per iso urb */
+ 	struct dma_pool		*sitd_pool;	/* sitd per split iso urb */
+ 
++	struct timer_list	iaa_watchdog;
+ 	struct timer_list	watchdog;
+ 	unsigned long		actions;
+ 	unsigned		stamp;
+@@ -148,9 +148,21 @@ static inline struct usb_hcd *ehci_to_hcd (struct ehci_hcd *ehci)
+ }
+ 
+ 
++static inline void
++iaa_watchdog_start(struct ehci_hcd *ehci)
++{
++	WARN_ON(timer_pending(&ehci->iaa_watchdog));
++	mod_timer(&ehci->iaa_watchdog,
++			jiffies + msecs_to_jiffies(EHCI_IAA_MSECS));
++}
++
++static inline void iaa_watchdog_done(struct ehci_hcd *ehci)
++{
++	del_timer(&ehci->iaa_watchdog);
++}
++
+ enum ehci_timer_action {
+ 	TIMER_IO_WATCHDOG,
+-	TIMER_IAA_WATCHDOG,
+ 	TIMER_ASYNC_SHRINK,
+ 	TIMER_ASYNC_OFF,
+ };
+@@ -168,9 +180,6 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
+ 		unsigned long t;
+ 
+ 		switch (action) {
+-		case TIMER_IAA_WATCHDOG:
+-			t = EHCI_IAA_JIFFIES;
+-			break;
+ 		case TIMER_IO_WATCHDOG:
+ 			t = EHCI_IO_JIFFIES;
+ 			break;
+@@ -187,8 +196,7 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
+ 		// async queue SHRINK often precedes IAA.  while it's ready
+ 		// to go OFF neither can matter, and afterwards the IO
+ 		// watchdog stops unless there's still periodic traffic.
+-		if (action != TIMER_IAA_WATCHDOG
+-				&& t > ehci->watchdog.expires
++		if (time_before_eq(t, ehci->watchdog.expires)
+ 				&& timer_pending (&ehci->watchdog))
+ 			return;
+ 		mod_timer (&ehci->watchdog, t);

commit 2e2eb83ffd1aeb92bf8793eea892b5bc05a993ea
+Author: Alan Stern 
+Date:   Tue Dec 4 14:35:15 2007 -0500
+
+    USB: add usbfs stubs for suspend and resume
+    
+    This patch (as1022b) adds stub methods for suspend and resume to the
+    usbfs driver.  There isn't much they can do since there's no way to
+    inform a user task about the events.  But it's important to have the
+    stubs, because an upcoming change to usbcore will automatically unbind
+    drivers that don't have those methods when a suspend occurs.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 85ec65ada123..32e5591ae7b1 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -402,10 +402,25 @@ static void driver_disconnect(struct usb_interface *intf)
+ 	destroy_async_on_interface(ps, ifnum);
+ }
+ 
++/* The following routines are merely placeholders.  There is no way
++ * to inform a user task about suspend or resumes.
++ */
++static int driver_suspend(struct usb_interface *intf, pm_message_t msg)
++{
++	return 0;
++}
++
++static int driver_resume(struct usb_interface *intf)
++{
++	return 0;
++}
++
+ struct usb_driver usbfs_driver = {
+ 	.name =		"usbfs",
+ 	.probe =	driver_probe,
+ 	.disconnect =	driver_disconnect,
++	.suspend =	driver_suspend,
++	.resume =	driver_resume,
+ };
+ 
+ static int claimintf(struct dev_state *ps, unsigned int ifnum)

commit 852c4b43bdd0953483e93bb97ca2fac7e5111dcb
+Author: Alan Stern 
+Date:   Mon Dec 3 15:44:29 2007 -0500
+
+    USB: updates to usb_reset_composite_device()
+    
+    This patch (as1023) updates the code in usb_reset_composite_device():
+    
+            Some local variable declarations are moved to inner loops.
+    
+            The interface locks are not acquired.  This isn't necessary
+            any more; its only reason was to prevent an interface from
+            being suspended or resumed during the reset.  But now
+            interface power management is controlled by the USB device
+            lock, not by the interface lock.
+    
+            The check for whether the interface is registered is removed.
+            There doesn't seem to be any reason for checking; a driver
+            for a non-registered interface deserves to be informed of
+            device resets just as much as any other.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index f7c2219c800f..cc93aa9336fe 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -3125,16 +3125,12 @@ EXPORT_SYMBOL(usb_reset_device);
+  * this from a driver probe() routine after downloading new firmware.
+  * For calls that might not occur during probe(), drivers should lock
+  * the device using usb_lock_device_for_reset().
+- *
+- * The interface locks are acquired during the pre_reset stage and released
+- * during the post_reset stage.  However if iface is not NULL and is
+- * currently being probed, we assume that the caller already owns its
+- * lock.
+  */
+ int usb_reset_composite_device(struct usb_device *udev,
+ 		struct usb_interface *iface)
+ {
+ 	int ret;
++	int i;
+ 	struct usb_host_config *config = udev->actconfig;
+ 
+ 	if (udev->state == USB_STATE_NOTATTACHED ||
+@@ -3151,16 +3147,11 @@ int usb_reset_composite_device(struct usb_device *udev,
+ 		iface = NULL;
+ 
+ 	if (config) {
+-		int i;
+-		struct usb_interface *cintf;
+-		struct usb_driver *drv;
+-
+ 		for (i = 0; i < config->desc.bNumInterfaces; ++i) {
+-			cintf = config->interface[i];
+-			if (cintf != iface)
+-				down(&cintf->dev.sem);
+-			if (device_is_registered(&cintf->dev) &&
+-					cintf->dev.driver) {
++			struct usb_interface *cintf = config->interface[i];
++			struct usb_driver *drv;
++
++			if (cintf->dev.driver) {
+ 				drv = to_usb_driver(cintf->dev.driver);
+ 				if (drv->pre_reset)
+ 					(drv->pre_reset)(cintf);
+@@ -3172,21 +3163,16 @@ int usb_reset_composite_device(struct usb_device *udev,
+ 	ret = usb_reset_device(udev);
+ 
+ 	if (config) {
+-		int i;
+-		struct usb_interface *cintf;
+-		struct usb_driver *drv;
+-
+ 		for (i = config->desc.bNumInterfaces - 1; i >= 0; --i) {
+-			cintf = config->interface[i];
+-			if (device_is_registered(&cintf->dev) &&
+-					cintf->dev.driver) {
++			struct usb_interface *cintf = config->interface[i];
++			struct usb_driver *drv;
++
++			if (cintf->dev.driver) {
+ 				drv = to_usb_driver(cintf->dev.driver);
+ 				if (drv->post_reset)
+ 					(drv->post_reset)(cintf);
+ 	/* FIXME: Unbind if post_reset returns an error or isn't defined */
+ 			}
+-			if (cintf != iface)
+-				up(&cintf->dev.sem);
+ 		}
+ 	}
+ 

commit 885e97478bf95b46a7cff40df49c2bb1a5503afd
+Author: Alan Stern 
+Date:   Mon Dec 3 15:42:10 2007 -0500
+
+    USB: repair USBDEVFS_CONNECT ioctl
+    
+    For as long as I've known about it, the USBDEVFS_CONNECT ioctl hasn't
+    done what it's supposed to.  The current code reprobes _all_ the
+    unbound USB interfaces; this patch (as1021) makes it reprobe only the
+    interface for which it was called.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 1f4f6d02fe25..85ec65ada123 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -1373,9 +1373,10 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
+ 
+ 	/* let kernel drivers try to (re)bind to the interface */
+ 	case USBDEVFS_CONNECT:
+-		usb_unlock_device(ps->dev);
+-		retval = bus_rescan_devices(intf->dev.bus);
+-		usb_lock_device(ps->dev);
++		if (!intf->dev.driver)
++			retval = device_attach(&intf->dev);
++		else
++			retval = -EBUSY;
+ 		break;
+ 
+ 	/* talk directly to the interface's driver */

commit 5933101718ea3d283983a923c5524c88138e5564
+Author: Alan Stern 
+Date:   Tue Nov 20 16:28:55 2007 -0500
+
+    USB: dummy_hcd: don't register drivers on the platform bus
+    
+    This patch (as1017) makes dummy_hcd behave more like the other USB
+    peripheral controller drivers by no longer registering its
+    gadget driver on the platform bus.  Doing that has always been a
+    mistake, since a usb_gadget_driver isn't a platform_driver.  Instead
+    the gadget driver is left unregistered in sysfs.
+    
+    Signed-off-by: Alan Stern 
+    CC: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index 9db2482bdfa2..1a8a5f33443e 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -772,18 +772,17 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
+ 	list_del_init (&dum->ep [0].ep.ep_list);
+ 	INIT_LIST_HEAD(&dum->fifo_req.queue);
+ 
++	driver->driver.bus = NULL;
+ 	dum->driver = driver;
+ 	dum->gadget.dev.driver = &driver->driver;
+ 	dev_dbg (udc_dev(dum), "binding gadget driver '%s'\n",
+ 			driver->driver.name);
+-	if ((retval = driver->bind (&dum->gadget)) != 0)
+-		goto err_bind_gadget;
+-
+-	driver->driver.bus = dum->gadget.dev.parent->bus;
+-	if ((retval = driver_register (&driver->driver)) != 0)
+-		goto err_register;
+-	if ((retval = device_bind_driver (&dum->gadget.dev)) != 0)
+-		goto err_bind_driver;
++	retval = driver->bind(&dum->gadget);
++	if (retval) {
++		dum->driver = NULL;
++		dum->gadget.dev.driver = NULL;
++		return retval;
++	}
+ 
+ 	/* khubd will enumerate this in a while */
+ 	spin_lock_irq (&dum->lock);
+@@ -793,20 +792,6 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
+ 
+ 	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
+ 	return 0;
+-
+-err_bind_driver:
+-	driver_unregister (&driver->driver);
+-err_register:
+-	if (driver->unbind)
+-		driver->unbind (&dum->gadget);
+-	spin_lock_irq (&dum->lock);
+-	dum->pullup = 0;
+-	set_link_state (dum);
+-	spin_unlock_irq (&dum->lock);
+-err_bind_gadget:
+-	dum->driver = NULL;
+-	dum->gadget.dev.driver = NULL;
+-	return retval;
+ }
+ EXPORT_SYMBOL (usb_gadget_register_driver);
+ 
+@@ -830,11 +815,9 @@ usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
+ 	spin_unlock_irqrestore (&dum->lock, flags);
+ 
+ 	driver->unbind (&dum->gadget);
++	dum->gadget.dev.driver = NULL;
+ 	dum->driver = NULL;
+ 
+-	device_release_driver (&dum->gadget.dev);
+-	driver_unregister (&driver->driver);
+-
+ 	spin_lock_irqsave (&dum->lock, flags);
+ 	dum->pullup = 0;
+ 	set_link_state (dum);

commit 269954e542328f014fc07fbb0a986192f7a1cced
+Author: Alan Stern 
+Date:   Mon Nov 19 15:57:45 2007 -0500
+
+    USB: don't change HC power state for a FREEZE
+    
+    This patch (as1016) prevents PCI-based host controllers from
+    undergoing a power-state change during a FREEZE or a PRETHAW.  Such
+    changes are needed only during a SUSPEND.
+    
+    Signed-off-by: Alan Stern 
+    CC: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index 3fb9af80cbf4..424674203fd3 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -250,6 +250,12 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
+ 			pci_disable_device (dev);
+ 		}
+ 
++		if (message.event == PM_EVENT_FREEZE ||
++				message.event == PM_EVENT_PRETHAW) {
++			dev_dbg(hcd->self.controller, "--> no state change\n");
++			goto done;
++		}
++
+ 		if (!has_pci_pm) {
+ 			dev_dbg (hcd->self.controller, "--> PCI D0/legacy\n");
+ 			goto done;

commit 4145ed6dc597a9bea5f6ae8c574653b2de10620f
+Author: Alan Stern 
+Date:   Mon Nov 19 10:15:02 2007 -0500
+
+    USB: make ksuspend_usbd thread non-freezable
+    
+    This patch (as1012b) makes the ksuspend_usbd kernel thread
+    non-freezable.  Since the PM core has been changed to lock all devices
+    during a system sleep, the thread no longer needs to be frozen.  It
+    won't interfere with a system sleep because before trying to resume a
+    root hub device, it acquires the device's lock.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 8f142370103d..bc5edacb0c34 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -230,7 +230,7 @@ static int ksuspend_usb_init(void)
+ 	 * singlethreaded.  Its job doesn't justify running on more
+ 	 * than one CPU.
+ 	 */
+-	ksuspend_usb_wq = create_freezeable_workqueue("ksuspend_usbd");
++	ksuspend_usb_wq = create_singlethread_workqueue("ksuspend_usbd");
+ 	if (!ksuspend_usb_wq)
+ 		return -ENOMEM;
+ 	return 0;

commit 676d3aa16f66d94bf5654781b77d1e070c8b0514
+Author: Alan Stern 
+Date:   Thu Nov 8 15:15:28 2007 -0500
+
+    USB: usb-storage: new "lockable" subclass 0x07
+    
+    This patch (as1011) adds a #define for the newly-created Lockable
+    (i.e., password-protected) subclass 0x07 for USB mass-storage devices.
+    The private ISD200 entry (which had been mapped to subclass 0x07) is
+    moved to 0xf0, which is unlikely to conflict with any official
+    subclass designation.
+    
+    The US_SC_MIN and US_SC_MAX constants aren't used anywhere, so the
+    patch removes them.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Matthew Dharm 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
+index a417b09b8b3d..cee0623b3c7b 100644
+--- a/include/linux/usb_usual.h
++++ b/include/linux/usb_usual.h
+@@ -80,10 +80,9 @@ enum { US_DO_ALL_FLAGS };
+ #define US_SC_UFI	0x04		/* Floppy */
+ #define US_SC_8070	0x05		/* Removable media */
+ #define US_SC_SCSI	0x06		/* Transparent */
+-#define US_SC_ISD200    0x07		/* ISD200 ATA */
+-#define US_SC_MIN	US_SC_RBC
+-#define US_SC_MAX	US_SC_ISD200
++#define US_SC_LOCKABLE	0x07		/* Password-protected */
+ 
++#define US_SC_ISD200    0xf0		/* ISD200 ATA */
+ #define US_SC_DEVICE	0xff		/* Use device's value */
+ 
+ /* Protocols */

commit 09f82ea92822a7bbb7e816508abbda47ed54a77f
+Author: Alan Stern 
+Date:   Mon Nov 19 10:53:40 2007 -0500
+
+    Kobject: drop child->parent ref at unregistration
+    
+    This patch (as1015) reverts changes that were made to the driver core
+    about four years ago.  The intent back then was to avoid certain kinds
+    of invalid memory accesses by leaving kernel objects allocated as long
+    as any of their children were still allocated.  The original and
+    correct approach was to wait only as long as any children were still
+    _registered_; that's what this patch reinstates.
+    
+    This fixes a problem in the SCSI core made visible by the class_device
+    to regular device conversion: A reference loop (scsi_device holds
+    reference to request_queue, which is the child of a gendisk, which is
+    the child of the scsi_device) prevents the data structures from being
+    released, even though they are deregistered okay.
+    
+    It's possible that this change will cause a few bugs to surface,
+    things that have been hidden for several years.  They can be fixed
+    easily enough by having the child device take an explicit reference to
+    the parent whenever needed.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Kay Sievers 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/lib/kobject.c b/lib/kobject.c
+index 1015f74212d0..493e991abb1b 100644
+--- a/lib/kobject.c
++++ b/lib/kobject.c
+@@ -149,12 +149,16 @@ void kobject_init(struct kobject * kobj)
+ 
+ static void unlink(struct kobject * kobj)
+ {
++	struct kobject *parent = kobj->parent;
++
+ 	if (kobj->kset) {
+ 		spin_lock(&kobj->kset->list_lock);
+ 		list_del_init(&kobj->entry);
+ 		spin_unlock(&kobj->kset->list_lock);
+ 	}
++	kobj->parent = NULL;
+ 	kobject_put(kobj);
++	kobject_put(parent);
+ }
+ 
+ /**
+@@ -208,7 +212,6 @@ int kobject_add(struct kobject * kobj)
+ 	if (error) {
+ 		/* unlink does the kobject_put() for us */
+ 		unlink(kobj);
+-		kobject_put(parent);
+ 
+ 		/* be noisy on error issues */
+ 		if (error == -EEXIST)
+@@ -590,7 +593,6 @@ static void kobject_cleanup(struct kobject *kobj)
+ {
+ 	struct kobj_type * t = get_ktype(kobj);
+ 	struct kset * s = kobj->kset;
+-	struct kobject * parent = kobj->parent;
+ 	const char *name = kobj->k_name;
+ 
+ 	pr_debug("kobject: '%s' (%p): %s\n",
+@@ -604,7 +606,6 @@ static void kobject_cleanup(struct kobject *kobj)
+ 	}
+ 	if (s)
+ 		kset_put(s);
+-	kobject_put(parent);
+ }
+ 
+ static void kobject_release(struct kref *kref)

commit ef2c51746dc89c2326ce522f8fb8a57695780e75
+Author: Alan Stern 
+Date:   Fri Nov 16 11:57:28 2007 -0500
+
+    Driver core: fix race in __device_release_driver
+    
+    This patch (as1013) was suggested by David Woodhouse; it fixes a race
+    in the driver core.  If a device is unregistered at the same time as
+    its driver is unloaded, the driver's code pages may be unmapped while
+    the remove method is still running.  The calls to get_driver() and
+    put_driver() were intended to prevent this, but they don't work if the
+    driver's module count has already dropped to 0.
+    
+    Instead, the patch keeps the device on the driver's list until after
+    the remove method has returned.  This forces the necessary
+    synchronization to occur.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: David Woodhouse 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/base/dd.c b/drivers/base/dd.c
+index 54922647522d..b0726eb6405e 100644
+--- a/drivers/base/dd.c
++++ b/drivers/base/dd.c
+@@ -289,11 +289,10 @@ static void __device_release_driver(struct device * dev)
+ {
+ 	struct device_driver * drv;
+ 
+-	drv = get_driver(dev->driver);
++	drv = dev->driver;
+ 	if (drv) {
+ 		driver_sysfs_remove(dev);
+ 		sysfs_remove_link(&dev->kobj, "driver");
+-		klist_remove(&dev->knode_driver);
+ 
+ 		if (dev->bus)
+ 			blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
+@@ -306,7 +305,7 @@ static void __device_release_driver(struct device * dev)
+ 			drv->remove(dev);
+ 		devres_release_all(dev);
+ 		dev->driver = NULL;
+-		put_driver(drv);
++		klist_remove(&dev->knode_driver);
+ 	}
+ }
+ 

commit 442258e2ff69276ff767f3703b30ce6a31fdd181
+Author: Alan Stern 
+Date:   Thu Dec 6 14:47:08 2007 -0500
+
+    USB: use IRQF_DISABLED for HCD interrupt handlers
+    
+    Host controller IRQs are supposed to be serviced with interrupts
+    disabled.  This patch (as1026) adds an IRQF_DISABLED flag to all the
+    controller drivers that lack it.  It also replaces the
+    spin_lock_irqsave() and spin_unlock_irqrestore() calls in uhci_irq()
+    with simple spin_lock() and spin_unlock().
+    
+    This fixes Bugzilla #9335.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: David Brownell 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index 5cf6d5f9acbd..3fb9af80cbf4 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -125,7 +125,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
+ 
+ 	pci_set_master (dev);
+ 
+-	retval = usb_add_hcd (hcd, dev->irq, IRQF_SHARED);
++	retval = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED);
+ 	if (retval != 0)
+ 		goto err4;
+ 	return retval;
+diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
+index b7b7bfbce527..430821cb95c8 100644
+--- a/drivers/usb/host/ehci-fsl.c
++++ b/drivers/usb/host/ehci-fsl.c
+@@ -122,7 +122,7 @@ int usb_hcd_fsl_probe(const struct hc_driver *driver,
+ 	temp = in_le32(hcd->regs + 0x1a8);
+ 	out_le32(hcd->regs + 0x1a8, temp | 0x3);
+ 
+-	retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
++	retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
+ 	if (retval != 0)
+ 		goto err4;
+ 	return retval;
+diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
+index 0a7426920150..0c3e6b790b7b 100644
+--- a/drivers/usb/host/ohci-ppc-of.c
++++ b/drivers/usb/host/ohci-ppc-of.c
+@@ -142,7 +142,7 @@ ohci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match)
+ 
+ 	ohci_hcd_init(ohci);
+ 
+-	rv = usb_add_hcd(hcd, irq, 0);
++	rv = usb_add_hcd(hcd, irq, IRQF_DISABLED);
+ 	if (rv == 0)
+ 		return 0;
+ 
+diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c
+index fe70e72340de..6e9c2d6db887 100644
+--- a/drivers/usb/host/ohci-ssb.c
++++ b/drivers/usb/host/ohci-ssb.c
+@@ -160,7 +160,7 @@ static int ssb_ohci_attach(struct ssb_device *dev)
+ 	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
+ 	if (!hcd->regs)
+ 		goto err_put_hcd;
+-	err = usb_add_hcd(hcd, dev->irq, IRQF_SHARED);
++	err = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED);
+ 	if (err)
+ 		goto err_iounmap;
+ 
+diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
+index ae8ec4474eb8..0ce2fc5e396b 100644
+--- a/drivers/usb/host/r8a66597-hcd.c
++++ b/drivers/usb/host/r8a66597-hcd.c
+@@ -2197,7 +2197,7 @@ static int __init r8a66597_probe(struct platform_device *pdev)
+ 	INIT_LIST_HEAD(&r8a66597->child_device);
+ 
+ 	hcd->rsrc_start = res->start;
+-	ret = usb_add_hcd(hcd, irq, 0);
++	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED);
+ 	if (ret != 0) {
+ 		err("Failed to add hcd");
+ 		goto clean_up;
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 4db17f75f4f1..ec987897b8ed 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -378,7 +378,6 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 	unsigned short status;
+-	unsigned long flags;
+ 
+ 	/*
+ 	 * Read the interrupt status, and write it back to clear the
+@@ -398,7 +397,7 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd)
+ 			dev_err(uhci_dev(uhci), "host controller process "
+ 					"error, something bad happened!\n");
+ 		if (status & USBSTS_HCH) {
+-			spin_lock_irqsave(&uhci->lock, flags);
++			spin_lock(&uhci->lock);
+ 			if (uhci->rh_state >= UHCI_RH_RUNNING) {
+ 				dev_err(uhci_dev(uhci),
+ 					"host controller halted, "
+@@ -415,16 +414,16 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd)
+ 				 * pending unlinks */
+ 				mod_timer(&hcd->rh_timer, jiffies);
+ 			}
+-			spin_unlock_irqrestore(&uhci->lock, flags);
++			spin_unlock(&uhci->lock);
+ 		}
+ 	}
+ 
+ 	if (status & USBSTS_RD)
+ 		usb_hcd_poll_rh_status(hcd);
+ 	else {
+-		spin_lock_irqsave(&uhci->lock, flags);
++		spin_lock(&uhci->lock);
+ 		uhci_scan_schedule(uhci);
+-		spin_unlock_irqrestore(&uhci->lock, flags);
++		spin_unlock(&uhci->lock);
+ 	}
+ 
+ 	return IRQ_HANDLED;

commit d48bd977e0dd8c17081d12242bfc09d743ea0d26
+Author: Alan Stern 
+Date:   Tue Dec 11 16:02:23 2007 -0500
+
+    USB: fix locking loop by avoiding flush_scheduled_work
+    
+    This patch (as1027) replaces a call to flush_scheduled_work() -- a
+    dangerous routine to invoke, especially while holding any sort of lock
+    -- with calls to cancel_work_sync() and cancel_delayed_work_sync().
+    
+    This fixes Bugzilla #9532.
+    
+    Signed-off-by: Alan Stern 
+    CC: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 13b326a13377..b04d232d4c65 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -522,9 +522,9 @@ static void hub_quiesce(struct usb_hub *hub)
+ 	/* (blocking) stop khubd and related activity */
+ 	usb_kill_urb(hub->urb);
+ 	if (hub->has_indicators)
+-		cancel_delayed_work(&hub->leds);
+-	if (hub->has_indicators || hub->tt.hub)
+-		flush_scheduled_work();
++		cancel_delayed_work_sync(&hub->leds);
++	if (hub->tt.hub)
++		cancel_work_sync(&hub->tt.kevent);
+ }
+ 
+ static void hub_activate(struct usb_hub *hub)

commit f1e8de0dbb9ee30cd6eb9c510249847d28443cb1
+Author: Alan Stern 
+Date:   Mon Nov 26 10:23:05 2007 -0500
+
+    USB: usb-storage: unusual_devs entry for JetFlash TS1GJF2A
+    
+    This patch (as1018) adds an unusual_devs entry for the JetFlash
+    TS1GJF2A.  This device doesn't like read requests for more than 188
+    sectors.  Setting max_sectors down to 64 is overkill, but at least
+    it will work without errors.
+    
+    For the torturous debugging history, see this thread:
+    
+            http://marc.info/?t=118745764700005&r=1&w=2
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 7398229c5255..2c27721bd259 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -731,6 +731,13 @@ UNUSUAL_DEV(  0x0584, 0x0008, 0x0102, 0x0102,
+  		US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ),
+ #endif
+ 
++/* Reported by RTE  */
++UNUSUAL_DEV(  0x058f, 0x6387, 0x0141, 0x0141,
++		"JetFlash",
++		"TS1GJF2A/120",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_MAX_SECTORS_64 ),
++
+ /* Fabrizio Fellini  */
+ UNUSUAL_DEV(  0x0595, 0x4343, 0x0000, 0x2210,
+ 		"Fujifilm",

commit 4a9bee8256a2dec26290a3bfff86ab86b8992547
+Author: Alan Stern 
+Date:   Tue Nov 6 15:01:52 2007 -0500
+
+    USB: uevent environment key fix
+    
+    This patch (as1010) was written by both Kay Sievers and me.  It solves
+    the problem of duplicated keys in USB uevent structures by refactoring
+    the uevent subroutines, taking advantage of the way the hotplug core
+    calls uevent handlers for the device's bus and for the device's type.
+    Keys needed for both USB-device and USB-interface events are added in
+    usb_uevent(), which is the bus handler.  Keys appropriate only for
+    USB-device or USB-interface events are added in usb_dev_uevent() or
+    usb_if_uevent() respectively, the type handlers.
+    
+    In addition, unnecessary tests for NULL pointers are removed as are
+    duplicated debugging log statements.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Kay Sievers 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 8586817698ad..c51f8e9312e0 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -585,9 +585,6 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
+ {
+ 	struct usb_device *usb_dev;
+ 
+-	if (!dev)
+-		return -ENODEV;
+-
+ 	/* driver is often null here; dev_dbg() would oops */
+ 	pr_debug ("usb %s: uevent\n", dev->bus_id);
+ 
+@@ -631,14 +628,6 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
+ 			   usb_dev->descriptor.bDeviceProtocol))
+ 		return -ENOMEM;
+ 
+-	if (add_uevent_var(env, "BUSNUM=%03d",
+-			   usb_dev->bus->busnum))
+-		return -ENOMEM;
+-
+-	if (add_uevent_var(env, "DEVNUM=%03d",
+-			   usb_dev->devnum))
+-		return -ENOMEM;
+-
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 40fd39de5bf9..fcd40ecbeecc 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1346,34 +1346,10 @@ static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
+ 	struct usb_interface *intf;
+ 	struct usb_host_interface *alt;
+ 
+-	if (!dev)
+-		return -ENODEV;
+-
+-	/* driver is often null here; dev_dbg() would oops */
+-	pr_debug ("usb %s: uevent\n", dev->bus_id);
+-
+ 	intf = to_usb_interface(dev);
+ 	usb_dev = interface_to_usbdev(intf);
+ 	alt = intf->cur_altsetting;
+ 
+-#ifdef CONFIG_USB_DEVICEFS
+-	if (add_uevent_var(env, "DEVICE=/proc/bus/usb/%03d/%03d",
+-			   usb_dev->bus->busnum, usb_dev->devnum))
+-		return -ENOMEM;
+-#endif
+-
+-	if (add_uevent_var(env, "PRODUCT=%x/%x/%x",
+-			   le16_to_cpu(usb_dev->descriptor.idVendor),
+-			   le16_to_cpu(usb_dev->descriptor.idProduct),
+-			   le16_to_cpu(usb_dev->descriptor.bcdDevice)))
+-		return -ENOMEM;
+-
+-	if (add_uevent_var(env, "TYPE=%d/%d/%d",
+-			   usb_dev->descriptor.bDeviceClass,
+-			   usb_dev->descriptor.bDeviceSubClass,
+-			   usb_dev->descriptor.bDeviceProtocol))
+-		return -ENOMEM;
+-
+ 	if (add_uevent_var(env, "INTERFACE=%d/%d/%d",
+ 		   alt->desc.bInterfaceClass,
+ 		   alt->desc.bInterfaceSubClass,
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index c4a6f1095b8b..8f142370103d 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -192,9 +192,34 @@ static void usb_release_dev(struct device *dev)
+ 	kfree(udev);
+ }
+ 
++#ifdef	CONFIG_HOTPLUG
++static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
++{
++	struct usb_device *usb_dev;
++
++	usb_dev = to_usb_device(dev);
++
++	if (add_uevent_var(env, "BUSNUM=%03d", usb_dev->bus->busnum))
++		return -ENOMEM;
++
++	if (add_uevent_var(env, "DEVNUM=%03d", usb_dev->devnum))
++		return -ENOMEM;
++
++	return 0;
++}
++
++#else
++
++static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
++{
++	return -ENODEV;
++}
++#endif	/* CONFIG_HOTPLUG */
++
+ struct device_type usb_device_type = {
+ 	.name =		"usb_device",
+ 	.release =	usb_release_dev,
++	.uevent =	usb_dev_uevent,
+ };
+ 
+ #ifdef	CONFIG_PM

commit 7e61559f6199bb387037abfc7d10a893973561fc
+Author: Alan Stern 
+Date:   Tue Nov 6 11:43:42 2007 -0500
+
+    USB: keep track of whether interface sysfs files exist
+    
+    This patch (as1009) solves the problem of multiple registrations for
+    USB sysfs files in a more satisfying way than the existing code.  It
+    simply adds a flag to keep track of whether or not the files have been
+    created; that way the files can be created or removed as needed.
+    
+    Signed-off-by: Alan Stern 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 316a746e0080..40fd39de5bf9 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1172,7 +1172,6 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
+ 	struct usb_host_interface *alt;
+ 	int ret;
+ 	int manual = 0;
+-	int changed;
+ 
+ 	if (dev->state == USB_STATE_SUSPENDED)
+ 		return -EHOSTUNREACH;
+@@ -1212,8 +1211,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
+ 	 */
+ 
+ 	/* prevent submissions using previous endpoint settings */
+-	changed = (iface->cur_altsetting != alt);
+-	if (changed && device_is_registered(&iface->dev))
++	if (iface->cur_altsetting != alt && device_is_registered(&iface->dev))
+ 		usb_remove_sysfs_intf_files(iface);
+ 	usb_disable_interface(dev, iface);
+ 
+@@ -1250,7 +1248,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
+ 	 * (Likewise, EP0 never "halts" on well designed devices.)
+ 	 */
+ 	usb_enable_interface(dev, iface);
+-	if (changed && device_is_registered(&iface->dev))
++	if (device_is_registered(&iface->dev))
+ 		usb_create_sysfs_intf_files(iface);
+ 
+ 	return 0;
+@@ -1641,12 +1639,6 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 				intf->dev.bus_id, ret);
+ 			continue;
+ 		}
+-
+-		/* The driver's probe method can call usb_set_interface(),
+-		 * which would mean the interface's sysfs files are already
+-		 * created.  Just in case, we'll remove them first.
+-		 */
+-		usb_remove_sysfs_intf_files(intf);
+ 		usb_create_sysfs_intf_files(intf);
+ 	}
+ 
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index b04afd06e502..32bd130b1eed 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -735,6 +735,8 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf)
+ 	struct usb_host_interface *alt = intf->cur_altsetting;
+ 	int retval;
+ 
++	if (intf->sysfs_files_created)
++		return 0;
+ 	retval = sysfs_create_group(&dev->kobj, &intf_attr_grp);
+ 	if (retval)
+ 		return retval;
+@@ -746,6 +748,7 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf)
+ 	if (intf->intf_assoc)
+ 		retval = sysfs_create_group(&dev->kobj, &intf_assoc_attr_grp);
+ 	usb_create_intf_ep_files(intf, udev);
++	intf->sysfs_files_created = 1;
+ 	return 0;
+ }
+ 
+@@ -753,8 +756,11 @@ void usb_remove_sysfs_intf_files(struct usb_interface *intf)
+ {
+ 	struct device *dev = &intf->dev;
+ 
++	if (!intf->sysfs_files_created)
++		return;
+ 	usb_remove_intf_ep_files(intf);
+ 	device_remove_file(dev, &dev_attr_interface);
+ 	sysfs_remove_group(&dev->kobj, &intf_attr_grp);
+ 	sysfs_remove_group(&intf->dev.kobj, &intf_assoc_attr_grp);
++	intf->sysfs_files_created = 0;
+ }
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index c5c8f169d3cf..416ee7617d9e 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -157,6 +157,7 @@ struct usb_interface {
+ 					 * bound to */
+ 	enum usb_interface_condition condition;		/* state of binding */
+ 	unsigned is_active:1;		/* the interface is not suspended */
++	unsigned sysfs_files_created:1;	/* the sysfs attributes exist */
+ 	unsigned needs_remote_wakeup:1;	/* driver requires remote wakeup */
+ 
+ 	struct device dev;		/* interface specific device info */

commit ddc1fd6ac1f3ad3275e19451fb07d2eff249161c
+Author: Alan Stern 
+Date:   Wed Nov 21 15:13:10 2007 -0800
+
+    USB HCD: avoid duplicate local_irq_disable()
+    
+    Arnd Bergmann wrote:
+    
+    usb_hcd_flush_endpoint() has a retry loop that starts with a spin_lock_irq(),
+    but only gives up the spinlock, not the irq_disable before jumping to the
+    rescan label.
+    
+    Alan Stern:
+    
+    I agree with your sentiment, but it would be better to solve this
+    problem without using local_irq_disable().
+    
+    Signed-off-by: Alan Stern 
+    Cc: Arnd Bergmann 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index fea8256a18d6..d5ed3fa9e304 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1311,8 +1311,8 @@ void usb_hcd_flush_endpoint(struct usb_device *udev,
+ 	hcd = bus_to_hcd(udev->bus);
+ 
+ 	/* No more submits can occur */
+-rescan:
+ 	spin_lock_irq(&hcd_urb_list_lock);
++rescan:
+ 	list_for_each_entry (urb, &ep->urb_list, urb_list) {
+ 		int	is_in;
+ 
+@@ -1345,6 +1345,7 @@ void usb_hcd_flush_endpoint(struct usb_device *udev,
+ 		usb_put_urb (urb);
+ 
+ 		/* list contents may have changed */
++		spin_lock(&hcd_urb_list_lock);
+ 		goto rescan;
+ 	}
+ 	spin_unlock_irq(&hcd_urb_list_lock);

commit 3c886c50486cfbef2a2382b99bf4083a465c970a
+Author: Alan Stern 
+Date:   Fri Nov 16 11:58:15 2007 -0500
+
+    USB: power-management documenation update
+    
+    This patch (as1014) was partly written by Tilman Schmidt.  It
+    clarifies the USB power-management documentation by explaining that
+    when a disconnect occurs, a suspend method call might not be followed
+    by either a resume or a reset_resume call.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Tilman Schmidt 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt
+index 97842deec471..b2fc4d4a9917 100644
+--- a/Documentation/usb/power-management.txt
++++ b/Documentation/usb/power-management.txt
+@@ -278,6 +278,14 @@ optional.  The methods' jobs are quite simple:
+ 	(although the interfaces will be in the same altsettings as
+ 	before the suspend).
+ 
++If the device is disconnected or powered down while it is suspended,
++the disconnect method will be called instead of the resume or
++reset_resume method.  This is also quite likely to happen when
++waking up from hibernation, as many systems do not maintain suspend
++current to the USB host controllers during hibernation.  (It's
++possible to work around the hibernation-forces-disconnect problem by
++using the USB Persist facility.)
++
+ The reset_resume method is used by the USB Persist facility (see
+ Documentation/usb/persist.txt) and it can also be used under certain
+ circumstances when CONFIG_USB_PERSIST is not enabled.  Currently, if a

commit 439a903a9663c0caa8094f3907ca60069d6c36e7
+Author: Alan Stern 
+Date:   Fri Oct 19 09:51:58 2007 -0400
+
+    USB: fix interface sysfs file-creation bug
+    
+    This patch (as1005) fixes a rather subtle problem.  When
+    usb_set_configuration() registers the interfaces and their files in
+    sysfs, it doesn't expect those files to exist already.  But when an
+    interface is registered, its driver may call usb_set_interface() and
+    thereby cause the sysfs files to be created.  The result is an error
+    when usb_set_configuration() goes on to create those same files again.
+    
+    The (not-so-great) solution is to have usb_set_configuration() remove
+    any existing files before creating them.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 8bdaa157ffe7..eb4ac47612a5 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1641,7 +1641,13 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 				intf->dev.bus_id, ret);
+ 			continue;
+ 		}
+-		usb_create_sysfs_intf_files (intf);
++
++		/* The driver's probe method can call usb_set_interface(),
++		 * which would mean the interface's sysfs files are already
++		 * created.  Just in case, we'll remove them first.
++		 */
++		usb_remove_sysfs_intf_files(intf);
++		usb_create_sysfs_intf_files(intf);
+ 	}
+ 
+ 	usb_autosuspend_device(dev);

commit 7898ffc543566a9c4a1b4ff39f43857d2d84a51c
+Author: Alan Stern 
+Date:   Tue Oct 16 11:55:30 2007 -0400
+
+    USB: fix scheduling of Iso URBs in uhci-hcd
+    
+    This patch (as1003) changes uhci-hcd to treat the URB_ISO_ASAP flag
+    the same as other host controller drivers, namely, to schedule an Iso
+    URB for the first available time slot that hasn't already expired.
+    URBs in which the flag isn't set will be scheduled for the first slot
+    following the last URB, even if it has expired.
+    
+    This fixes a problem reported by Martin Bachem.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index e5d60d5b105a..60379b17bbc1 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -1271,7 +1271,8 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
+ 	} else if (qh->period != urb->interval) {
+ 		return -EINVAL;		/* Can't change the period */
+ 
+-	} else {	/* Pick up where the last URB leaves off */
++	} else {
++		/* Find the next unused frame */
+ 		if (list_empty(&qh->queue)) {
+ 			frame = qh->iso_frame;
+ 		} else {
+@@ -1283,10 +1284,18 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
+ 					lurb->number_of_packets *
+ 					lurb->interval;
+ 		}
+-		if (urb->transfer_flags & URB_ISO_ASAP)
+-			urb->start_frame = frame;
+-		else if (urb->start_frame != frame)
+-			return -EINVAL;
++		if (urb->transfer_flags & URB_ISO_ASAP) {
++			/* Skip some frames if necessary to insure
++			 * the start frame is in the future.
++			 */
++			uhci_get_current_frame_number(uhci);
++			if (uhci_frame_before_eq(frame, uhci->frame_number)) {
++				frame = uhci->frame_number + 1;
++				frame += ((qh->phase - frame) &
++					(qh->period - 1));
++			}
++		}	/* Otherwise pick up where the last URB leaves off */
++		urb->start_frame = frame;
+ 	}
+ 
+ 	/* Make sure we won't have to go too far into the future */

commit d1aa3e6aa8edfeb864af7c930523d9e588b28bea
+Author: Alan Stern 
+Date:   Thu Oct 11 16:47:36 2007 -0400
+
+    USB: fix race in autosuspend reschedule
+    
+    This patch (as1002) fixes a small race which can occur when a driver
+    expects usbcore to reschedule an autosuspend request.  If the request
+    arrives too late, it won't be rescheduled.  The patch adds an extra
+    argument to autosuspend_check(), indicating that a reschedule is
+    needed no matter how much time has elapsed.
+    
+    It also tries to avoid letting asynchronous changes to the value of
+    jiffies cause a delay to become negative, by caching a local copy of
+    the current time.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 8c1eac27f2de..c27bc080d84e 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -950,11 +950,11 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
+ #ifdef	CONFIG_USB_SUSPEND
+ 
+ /* Internal routine to check whether we may autosuspend a device. */
+-static int autosuspend_check(struct usb_device *udev)
++static int autosuspend_check(struct usb_device *udev, int reschedule)
+ {
+ 	int			i;
+ 	struct usb_interface	*intf;
+-	unsigned long		suspend_time;
++	unsigned long		suspend_time, j;
+ 
+ 	/* For autosuspend, fail fast if anything is in use or autosuspend
+ 	 * is disabled.  Also fail if any interfaces require remote wakeup
+@@ -996,20 +996,20 @@ static int autosuspend_check(struct usb_device *udev)
+ 	}
+ 
+ 	/* If everything is okay but the device hasn't been idle for long
+-	 * enough, queue a delayed autosuspend request.
++	 * enough, queue a delayed autosuspend request.  If the device
++	 * _has_ been idle for long enough and the reschedule flag is set,
++	 * likewise queue a delayed (1 second) autosuspend request.
+ 	 */
+-	if (time_after(suspend_time, jiffies)) {
++	j = jiffies;
++	if (time_before(j, suspend_time))
++		reschedule = 1;
++	else
++		suspend_time = j + HZ;
++	if (reschedule) {
+ 		if (!timer_pending(&udev->autosuspend.timer)) {
+-
+-			/* The value of jiffies may change between the
+-			 * time_after() comparison above and the subtraction
+-			 * below.  That's okay; the system behaves sanely
+-			 * when a timer is registered for the present moment
+-			 * or for the past.
+-			 */
+ 			queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+-				round_jiffies_relative(suspend_time - jiffies));
+-			}
++				round_jiffies_relative(suspend_time - j));
++		}
+ 		return -EAGAIN;
+ 	}
+ 	return 0;
+@@ -1017,7 +1017,7 @@ static int autosuspend_check(struct usb_device *udev)
+ 
+ #else
+ 
+-static inline int autosuspend_check(struct usb_device *udev)
++static inline int autosuspend_check(struct usb_device *udev, int reschedule)
+ {
+ 	return 0;
+ }
+@@ -1074,7 +1074,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
+ 
+ 	if (udev->auto_pm) {
+-		status = autosuspend_check(udev);
++		status = autosuspend_check(udev, 0);
+ 		if (status < 0)
+ 			goto done;
+ 	}
+@@ -1100,7 +1100,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 
+ 		/* Try another autosuspend when the interfaces aren't busy */
+ 		if (udev->auto_pm)
+-			autosuspend_check(udev);
++			autosuspend_check(udev, status == -EBUSY);
+ 
+ 	/* If the suspend succeeded then prevent any more URB submissions,
+ 	 * flush any outstanding URBs, and propagate the suspend up the tree.

commit 063a2da8f01806906f7d7b1a1424b9afddebc443
+Author: Alan Stern 
+Date:   Wed Oct 10 16:24:06 2007 -0400
+
+    USB: serial core should respect driver requirements
+    
+    This patch (as997) fixes a bug in the USB serial core.  The core needs
+    to pay attention to drivers' requirements regarding the number and
+    type of endpoints a device has.
+    
+    At the same time, the patch changes the NUM_DONT_CARE constant (which
+    is stored in a single-byte field) from -1 to a safer, unsigned value.
+    It also improves the kerneldoc for several fields in the
+    usb_serial_driver structure.
+    
+    Finally, the patch replaces a list_for_each() with list_for_each_entry().
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
+index 26e015c39a31..4b1bd7def4a5 100644
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -662,16 +662,14 @@ static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
+ 
+ static struct usb_serial_driver *search_serial_device(struct usb_interface *iface)
+ {
+-	struct list_head *p;
+ 	const struct usb_device_id *id;
+-	struct usb_serial_driver *t;
++	struct usb_serial_driver *drv;
+ 
+ 	/* Check if the usb id matches a known device */
+-	list_for_each(p, &usb_serial_driver_list) {
+-		t = list_entry(p, struct usb_serial_driver, driver_list);
+-		id = get_iface_id(t, iface);
++	list_for_each_entry(drv, &usb_serial_driver_list, driver_list) {
++		id = get_iface_id(drv, iface);
+ 		if (id)
+-			return t;
++			return drv;
+ 	}
+ 
+ 	return NULL;
+@@ -811,9 +809,6 @@ int usb_serial_probe(struct usb_interface *interface,
+ 	/* END HORRIBLE HACK FOR PL2303 */
+ #endif
+ 
+-	/* found all that we need */
+-	dev_info(&interface->dev, "%s converter detected\n", type->description);
+-
+ #ifdef CONFIG_USB_SERIAL_GENERIC
+ 	if (type == &usb_serial_generic_device) {
+ 		num_ports = num_bulk_out;
+@@ -847,6 +842,24 @@ int usb_serial_probe(struct usb_interface *interface,
+ 	serial->num_interrupt_in = num_interrupt_in;
+ 	serial->num_interrupt_out = num_interrupt_out;
+ 
++	/* check that the device meets the driver's requirements */
++	if ((type->num_interrupt_in != NUM_DONT_CARE &&
++				type->num_interrupt_in != num_interrupt_in)
++			|| (type->num_interrupt_out != NUM_DONT_CARE &&
++				type->num_interrupt_out != num_interrupt_out)
++			|| (type->num_bulk_in != NUM_DONT_CARE &&
++				type->num_bulk_in != num_bulk_in)
++			|| (type->num_bulk_out != NUM_DONT_CARE &&
++				type->num_bulk_out != num_bulk_out)) {
++		dbg("wrong number of endpoints");
++		kfree(serial);
++		return -EIO;
++	}
++
++	/* found all that we need */
++	dev_info(&interface->dev, "%s converter detected\n",
++			type->description);
++
+ 	/* create our ports, we need as many as the max endpoints */
+ 	/* we don't use num_ports here cauz some devices have more endpoint pairs than ports */
+ 	max_endpoints = max(num_bulk_in, num_bulk_out);
+diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
+index e8b8928232c8..488ce128885c 100644
+--- a/include/linux/usb/serial.h
++++ b/include/linux/usb/serial.h
+@@ -141,7 +141,7 @@ struct usb_serial {
+ };
+ #define to_usb_serial(d) container_of(d, struct usb_serial, kref)
+ 
+-#define NUM_DONT_CARE	(-1)
++#define NUM_DONT_CARE	99
+ 
+ /* get and set the serial private data pointer helper functions */
+ static inline void *usb_get_serial_data (struct usb_serial *serial)
+@@ -160,12 +160,18 @@ static inline void usb_set_serial_data (struct usb_serial *serial, void *data)
+  *	in the syslog messages when a device is inserted or removed.
+  * @id_table: pointer to a list of usb_device_id structures that define all
+  *	of the devices this structure can support.
+- * @num_interrupt_in: the number of interrupt in endpoints this device will
+- *	have.
+- * @num_interrupt_out: the number of interrupt out endpoints this device will
+- *	have.
+- * @num_bulk_in: the number of bulk in endpoints this device will have.
+- * @num_bulk_out: the number of bulk out endpoints this device will have.
++ * @num_interrupt_in: If a device doesn't have this many interrupt-in
++ *	endpoints, it won't be sent to the driver's attach() method.
++ *	(But it might still be sent to the probe() method.)
++ * @num_interrupt_out: If a device doesn't have this many interrupt-out
++ *	endpoints, it won't be sent to the driver's attach() method.
++ *	(But it might still be sent to the probe() method.)
++ * @num_bulk_in: If a device doesn't have this many bulk-in
++ *	endpoints, it won't be sent to the driver's attach() method.
++ *	(But it might still be sent to the probe() method.)
++ * @num_bulk_out: If a device doesn't have this many bulk-out
++ *	endpoints, it won't be sent to the driver's attach() method.
++ *	(But it might still be sent to the probe() method.)
+  * @num_ports: the number of different ports this device will have.
+  * @calc_num_ports: pointer to a function to determine how many ports this
+  *	device has dynamically.  It will be called after the probe()

commit cd38c1e1ae5273c28a12baacaf17c1faa062661f
+Author: Alan Stern 
+Date:   Wed Oct 10 16:24:56 2007 -0400
+
+    USB: documentation for USB power management
+    
+    This patch (as998) adds documentation on how USB power management
+    works and how to use it.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt
+new file mode 100644
+index 000000000000..97842deec471
+--- /dev/null
++++ b/Documentation/usb/power-management.txt
+@@ -0,0 +1,517 @@
++			Power Management for USB
++
++		 Alan Stern 
++
++			    October 5, 2007
++
++
++
++	What is Power Management?
++	-------------------------
++
++Power Management (PM) is the practice of saving energy by suspending
++parts of a computer system when they aren't being used.  While a
++component is "suspended" it is in a nonfunctional low-power state; it
++might even be turned off completely.  A suspended component can be
++"resumed" (returned to a functional full-power state) when the kernel
++needs to use it.  (There also are forms of PM in which components are
++placed in a less functional but still usable state instead of being
++suspended; an example would be reducing the CPU's clock rate.  This
++document will not discuss those other forms.)
++
++When the parts being suspended include the CPU and most of the rest of
++the system, we speak of it as a "system suspend".  When a particular
++device is turned off while the system as a whole remains running, we
++call it a "dynamic suspend" (also known as a "runtime suspend" or
++"selective suspend").  This document concentrates mostly on how
++dynamic PM is implemented in the USB subsystem, although system PM is
++covered to some extent (see Documentation/power/*.txt for more
++information about system PM).
++
++Note: Dynamic PM support for USB is present only if the kernel was
++built with CONFIG_USB_SUSPEND enabled.  System PM support is present
++only if the kernel was built with CONFIG_SUSPEND or CONFIG_HIBERNATION
++enabled.
++
++
++	What is Remote Wakeup?
++	----------------------
++
++When a device has been suspended, it generally doesn't resume until
++the computer tells it to.  Likewise, if the entire computer has been
++suspended, it generally doesn't resume until the user tells it to, say
++by pressing a power button or opening the cover.
++
++However some devices have the capability of resuming by themselves, or
++asking the kernel to resume them, or even telling the entire computer
++to resume.  This capability goes by several names such as "Wake On
++LAN"; we will refer to it generically as "remote wakeup".  When a
++device is enabled for remote wakeup and it is suspended, it may resume
++itself (or send a request to be resumed) in response to some external
++event.  Examples include a suspended keyboard resuming when a key is
++pressed, or a suspended USB hub resuming when a device is plugged in.
++
++
++	When is a USB device idle?
++	--------------------------
++
++A device is idle whenever the kernel thinks it's not busy doing
++anything important and thus is a candidate for being suspended.  The
++exact definition depends on the device's driver; drivers are allowed
++to declare that a device isn't idle even when there's no actual
++communication taking place.  (For example, a hub isn't considered idle
++unless all the devices plugged into that hub are already suspended.)
++In addition, a device isn't considered idle so long as a program keeps
++its usbfs file open, whether or not any I/O is going on.
++
++If a USB device has no driver, its usbfs file isn't open, and it isn't
++being accessed through sysfs, then it definitely is idle.
++
++
++	Forms of dynamic PM
++	-------------------
++
++Dynamic suspends can occur in two ways: manual and automatic.
++"Manual" means that the user has told the kernel to suspend a device,
++whereas "automatic" means that the kernel has decided all by itself to
++suspend a device.  Automatic suspend is called "autosuspend" for
++short.  In general, a device won't be autosuspended unless it has been
++idle for some minimum period of time, the so-called idle-delay time.
++
++Of course, nothing the kernel does on its own initiative should
++prevent the computer or its devices from working properly.  If a
++device has been autosuspended and a program tries to use it, the
++kernel will automatically resume the device (autoresume).  For the
++same reason, an autosuspended device will usually have remote wakeup
++enabled, if the device supports remote wakeup.
++
++It is worth mentioning that many USB drivers don't support
++autosuspend.  In fact, at the time of this writing (Linux 2.6.23) the
++only drivers which do support it are the hub driver, kaweth, asix,
++usblp, usblcd, and usb-skeleton (which doesn't count).  If a
++non-supporting driver is bound to a device, the device won't be
++autosuspended.  In effect, the kernel pretends the device is never
++idle.
++
++We can categorize power management events in two broad classes:
++external and internal.  External events are those triggered by some
++agent outside the USB stack: system suspend/resume (triggered by
++userspace), manual dynamic suspend/resume (also triggered by
++userspace), and remote wakeup (triggered by the device).  Internal
++events are those triggered within the USB stack: autosuspend and
++autoresume.
++
++
++	The user interface for dynamic PM
++	---------------------------------
++
++The user interface for controlling dynamic PM is located in the power/
++subdirectory of each USB device's sysfs directory, that is, in
++/sys/bus/usb/devices/.../power/ where "..." is the device's ID.  The
++relevant attribute files are: wakeup, level, and autosuspend.
++
++	power/wakeup
++
++		This file is empty if the device does not support
++		remote wakeup.  Otherwise the file contains either the
++		word "enabled" or the word "disabled", and you can
++		write those words to the file.  The setting determines
++		whether or not remote wakeup will be enabled when the
++		device is next suspended.  (If the setting is changed
++		while the device is suspended, the change won't take
++		effect until the following suspend.)
++
++	power/level
++
++		This file contains one of three words: "on", "auto",
++		or "suspend".  You can write those words to the file
++		to change the device's setting.
++
++		"on" means that the device should be resumed and
++		autosuspend is not allowed.  (Of course, system
++		suspends are still allowed.)
++
++		"auto" is the normal state in which the kernel is
++		allowed to autosuspend and autoresume the device.
++
++		"suspend" means that the device should remain
++		suspended, and autoresume is not allowed.  (But remote
++		wakeup may still be allowed, since it is controlled
++		separately by the power/wakeup attribute.)
++
++	power/autosuspend
++
++		This file contains an integer value, which is the
++		number of seconds the device should remain idle before
++		the kernel will autosuspend it (the idle-delay time).
++		The default is 2.  0 means to autosuspend as soon as
++		the device becomes idle, and -1 means never to
++		autosuspend.  You can write a number to the file to
++		change the autosuspend idle-delay time.
++
++Writing "-1" to power/autosuspend and writing "on" to power/level do
++essentially the same thing -- they both prevent the device from being
++autosuspended.  Yes, this is a redundancy in the API.
++
++(In 2.6.21 writing "0" to power/autosuspend would prevent the device
++from being autosuspended; the behavior was changed in 2.6.22.  The
++power/autosuspend attribute did not exist prior to 2.6.21, and the
++power/level attribute did not exist prior to 2.6.22.)
++
++
++	Changing the default idle-delay time
++	------------------------------------
++
++The default autosuspend idle-delay time is controlled by a module
++parameter in usbcore.  You can specify the value when usbcore is
++loaded.  For example, to set it to 5 seconds instead of 2 you would
++do:
++
++	modprobe usbcore autosuspend=5
++
++Equivalently, you could add to /etc/modprobe.conf a line saying:
++
++	options usbcore autosuspend=5
++
++Some distributions load the usbcore module very early during the boot
++process, by means of a program or script running from an initramfs
++image.  To alter the parameter value you would have to rebuild that
++image.
++
++If usbcore is compiled into the kernel rather than built as a loadable
++module, you can add
++
++	usbcore.autosuspend=5
++
++to the kernel's boot command line.
++
++Finally, the parameter value can be changed while the system is
++running.  If you do:
++
++	echo 5 >/sys/module/usbcore/parameters/autosuspend
++
++then each new USB device will have its autosuspend idle-delay
++initialized to 5.  (The idle-delay values for already existing devices
++will not be affected.)
++
++Setting the initial default idle-delay to -1 will prevent any
++autosuspend of any USB device.  This is a simple alternative to
++disabling CONFIG_USB_SUSPEND and rebuilding the kernel, and it has the
++added benefit of allowing you to enable autosuspend for selected
++devices.
++
++
++	Warnings
++	--------
++
++The USB specification states that all USB devices must support power
++management.  Nevertheless, the sad fact is that many devices do not
++support it very well.  You can suspend them all right, but when you
++try to resume them they disconnect themselves from the USB bus or
++they stop working entirely.  This seems to be especially prevalent
++among printers and scanners, but plenty of other types of device have
++the same deficiency.
++
++For this reason, by default the kernel disables autosuspend (the
++power/level attribute is initialized to "on") for all devices other
++than hubs.  Hubs, at least, appear to be reasonably well-behaved in
++this regard.
++
++(In 2.6.21 and 2.6.22 this wasn't the case.  Autosuspend was enabled
++by default for almost all USB devices.  A number of people experienced
++problems as a result.)
++
++This means that non-hub devices won't be autosuspended unless the user
++or a program explicitly enables it.  As of this writing there aren't
++any widespread programs which will do this; we hope that in the near
++future device managers such as HAL will take on this added
++responsibility.  In the meantime you can always carry out the
++necessary operations by hand or add them to a udev script.  You can
++also change the idle-delay time; 2 seconds is not the best choice for
++every device.
++
++Sometimes it turns out that even when a device does work okay with
++autosuspend there are still problems.  For example, there are
++experimental patches adding autosuspend support to the usbhid driver,
++which manages keyboards and mice, among other things.  Tests with a
++number of keyboards showed that typing on a suspended keyboard, while
++causing the keyboard to do a remote wakeup all right, would
++nonetheless frequently result in lost keystrokes.  Tests with mice
++showed that some of them would issue a remote-wakeup request in
++response to button presses but not to motion, and some in response to
++neither.
++
++The kernel will not prevent you from enabling autosuspend on devices
++that can't handle it.  It is even possible in theory to damage a
++device by suspending it at the wrong time -- for example, suspending a
++USB hard disk might cause it to spin down without parking the heads.
++(Highly unlikely, but possible.)  Take care.
++
++
++	The driver interface for Power Management
++	-----------------------------------------
++
++The requirements for a USB driver to support external power management
++are pretty modest; the driver need only define
++
++	.suspend
++	.resume
++	.reset_resume
++
++methods in its usb_driver structure, and the reset_resume method is
++optional.  The methods' jobs are quite simple:
++
++	The suspend method is called to warn the driver that the
++	device is going to be suspended.  If the driver returns a
++	negative error code, the suspend will be aborted.  Normally
++	the driver will return 0, in which case it must cancel all
++	outstanding URBs (usb_kill_urb()) and not submit any more.
++
++	The resume method is called to tell the driver that the
++	device has been resumed and the driver can return to normal
++	operation.  URBs may once more be submitted.
++
++	The reset_resume method is called to tell the driver that
++	the device has been resumed and it also has been reset.
++	The driver should redo any necessary device initialization,
++	since the device has probably lost most or all of its state
++	(although the interfaces will be in the same altsettings as
++	before the suspend).
++
++The reset_resume method is used by the USB Persist facility (see
++Documentation/usb/persist.txt) and it can also be used under certain
++circumstances when CONFIG_USB_PERSIST is not enabled.  Currently, if a
++device is reset during a resume and the driver does not have a
++reset_resume method, the driver won't receive any notification about
++the resume.  Later kernels will call the driver's disconnect method;
++2.6.23 doesn't do this.
++
++USB drivers are bound to interfaces, so their suspend and resume
++methods get called when the interfaces are suspended or resumed.  In
++principle one might want to suspend some interfaces on a device (i.e.,
++force the drivers for those interface to stop all activity) without
++suspending the other interfaces.  The USB core doesn't allow this; all
++interfaces are suspended when the device itself is suspended and all
++interfaces are resumed when the device is resumed.  It isn't possible
++to suspend or resume some but not all of a device's interfaces.  The
++closest you can come is to unbind the interfaces' drivers.
++
++
++	The driver interface for autosuspend and autoresume
++	---------------------------------------------------
++
++To support autosuspend and autoresume, a driver should implement all
++three of the methods listed above.  In addition, a driver indicates
++that it supports autosuspend by setting the .supports_autosuspend flag
++in its usb_driver structure.  It is then responsible for informing the
++USB core whenever one of its interfaces becomes busy or idle.  The
++driver does so by calling these three functions:
++
++	int  usb_autopm_get_interface(struct usb_interface *intf);
++	void usb_autopm_put_interface(struct usb_interface *intf);
++	int  usb_autopm_set_interface(struct usb_interface *intf);
++
++The functions work by maintaining a counter in the usb_interface
++structure.  When intf->pm_usage_count is > 0 then the interface is
++deemed to be busy, and the kernel will not autosuspend the interface's
++device.  When intf->pm_usage_count is <= 0 then the interface is
++considered to be idle, and the kernel may autosuspend the device.
++
++(There is a similar pm_usage_count field in struct usb_device,
++associated with the device itself rather than any of its interfaces.
++This field is used only by the USB core.)
++
++The driver owns intf->pm_usage_count; it can modify the value however
++and whenever it likes.  A nice aspect of the usb_autopm_* routines is
++that the changes they make are protected by the usb_device structure's
++PM mutex (udev->pm_mutex); however drivers may change pm_usage_count
++without holding the mutex.
++
++	usb_autopm_get_interface() increments pm_usage_count and
++	attempts an autoresume if the new value is > 0 and the
++	device is suspended.
++
++	usb_autopm_put_interface() decrements pm_usage_count and
++	attempts an autosuspend if the new value is <= 0 and the
++	device isn't suspended.
++
++	usb_autopm_set_interface() leaves pm_usage_count alone.
++	It attempts an autoresume if the value is > 0 and the device
++	is suspended, and it attempts an autosuspend if the value is
++	<= 0 and the device isn't suspended.
++
++There also are a couple of utility routines drivers can use:
++
++	usb_autopm_enable() sets pm_usage_cnt to 1 and then calls
++	usb_autopm_set_interface(), which will attempt an autoresume.
++
++	usb_autopm_disable() sets pm_usage_cnt to 0 and then calls
++	usb_autopm_set_interface(), which will attempt an autosuspend.
++
++The conventional usage pattern is that a driver calls
++usb_autopm_get_interface() in its open routine and
++usb_autopm_put_interface() in its close or release routine.  But
++other patterns are possible.
++
++The autosuspend attempts mentioned above will often fail for one
++reason or another.  For example, the power/level attribute might be
++set to "on", or another interface in the same device might not be
++idle.  This is perfectly normal.  If the reason for failure was that
++the device hasn't been idle for long enough, a delayed workqueue
++routine is automatically set up to carry out the operation when the
++autosuspend idle-delay has expired.
++
++Autoresume attempts also can fail.  This will happen if power/level is
++set to "suspend" or if the device doesn't manage to resume properly.
++Unlike autosuspend, there's no delay for an autoresume.
++
++
++	Other parts of the driver interface
++	-----------------------------------
++
++Sometimes a driver needs to make sure that remote wakeup is enabled
++during autosuspend.  For example, there's not much point
++autosuspending a keyboard if the user can't cause the keyboard to do a
++remote wakeup by typing on it.  If the driver sets
++intf->needs_remote_wakeup to 1, the kernel won't autosuspend the
++device if remote wakeup isn't available or has been disabled through
++the power/wakeup attribute.  (If the device is already autosuspended,
++though, setting this flag won't cause the kernel to autoresume it.
++Normally a driver would set this flag in its probe method, at which
++time the device is guaranteed not to be autosuspended.)
++
++The usb_autopm_* routines have to run in a sleepable process context;
++they must not be called from an interrupt handler or while holding a
++spinlock.  In fact, the entire autosuspend mechanism is not well geared
++toward interrupt-driven operation.  However there is one thing a
++driver can do in an interrupt handler:
++
++	usb_mark_last_busy(struct usb_device *udev);
++
++This sets udev->last_busy to the current time.  udev->last_busy is the
++field used for idle-delay calculations; updating it will cause any
++pending autosuspend to be moved back.  The usb_autopm_* routines will
++also set the last_busy field to the current time.
++
++Calling urb_mark_last_busy() from within an URB completion handler is
++subject to races: The kernel may have just finished deciding the
++device has been idle for long enough but not yet gotten around to
++calling the driver's suspend method.  The driver would have to be
++responsible for synchronizing its suspend method with its URB
++completion handler and causing the autosuspend to fail with -EBUSY if
++an URB had completed too recently.
++
++External suspend calls should never be allowed to fail in this way,
++only autosuspend calls.  The driver can tell them apart by checking
++udev->auto_pm; this flag will be set to 1 for internal PM events
++(autosuspend or autoresume) and 0 for external PM events.
++
++Many of the ingredients in the autosuspend framework are oriented
++towards interfaces: The usb_interface structure contains the
++pm_usage_cnt field, and the usb_autopm_* routines take an interface
++pointer as their argument.  But somewhat confusingly, a few of the
++pieces (usb_mark_last_busy() and udev->auto_pm) use the usb_device
++structure instead.  Drivers need to keep this straight; they can call
++interface_to_usbdev() to find the device structure for a given
++interface.
++
++
++	Locking requirements
++	--------------------
++
++All three suspend/resume methods are always called while holding the
++usb_device's PM mutex.  For external events -- but not necessarily for
++autosuspend or autoresume -- the device semaphore (udev->dev.sem) will
++also be held.  This implies that external suspend/resume events are
++mutually exclusive with calls to probe, disconnect, pre_reset, and
++post_reset; the USB core guarantees that this is true of internal
++suspend/resume events as well.
++
++If a driver wants to block all suspend/resume calls during some
++critical section, it can simply acquire udev->pm_mutex.
++Alternatively, if the critical section might call some of the
++usb_autopm_* routines, the driver can avoid deadlock by doing:
++
++	down(&udev->dev.sem);
++	rc = usb_autopm_get_interface(intf);
++
++and at the end of the critical section:
++
++	if (!rc)
++		usb_autopm_put_interface(intf);
++	up(&udev->dev.sem);
++
++Holding the device semaphore will block all external PM calls, and the
++usb_autopm_get_interface() will prevent any internal PM calls, even if
++it fails.  (Exercise: Why?)
++
++The rules for locking order are:
++
++	Never acquire any device semaphore while holding any PM mutex.
++
++	Never acquire udev->pm_mutex while holding the PM mutex for
++	a device that isn't a descendant of udev.
++
++In other words, PM mutexes should only be acquired going up the device
++tree, and they should be acquired only after locking all the device
++semaphores you need to hold.  These rules don't matter to drivers very
++much; they usually affect just the USB core.
++
++Still, drivers do need to be careful.  For example, many drivers use a
++private mutex to synchronize their normal I/O activities with their
++disconnect method.  Now if the driver supports autosuspend then it
++must call usb_autopm_put_interface() from somewhere -- maybe from its
++close method.  It should make the call while holding the private mutex,
++since a driver shouldn't call any of the usb_autopm_* functions for an
++interface from which it has been unbound.
++
++But the usb_autpm_* routines always acquire the device's PM mutex, and
++consequently the locking order has to be: private mutex first, PM
++mutex second.  Since the suspend method is always called with the PM
++mutex held, it mustn't try to acquire the private mutex.  It has to
++synchronize with the driver's I/O activities in some other way.
++
++
++	Interaction between dynamic PM and system PM
++	--------------------------------------------
++
++Dynamic power management and system power management can interact in
++a couple of ways.
++
++Firstly, a device may already be manually suspended or autosuspended
++when a system suspend occurs.  Since system suspends are supposed to
++be as transparent as possible, the device should remain suspended
++following the system resume.  The 2.6.23 kernel obeys this principle
++for manually suspended devices but not for autosuspended devices; they
++do get resumed when the system wakes up.  (Presumably they will be
++autosuspended again after their idle-delay time expires.)  In later
++kernels this behavior will be fixed.
++
++(There is an exception.  If a device would undergo a reset-resume
++instead of a normal resume, and the device is enabled for remote
++wakeup, then the reset-resume takes place even if the device was
++already suspended when the system suspend began.  The justification is
++that a reset-resume is a kind of remote-wakeup event.  Or to put it
++another way, a device which needs a reset won't be able to generate
++normal remote-wakeup signals, so it ought to be resumed immediately.)
++
++Secondly, a dynamic power-management event may occur as a system
++suspend is underway.  The window for this is short, since system
++suspends don't take long (a few seconds usually), but it can happen.
++For example, a suspended device may send a remote-wakeup signal while
++the system is suspending.  The remote wakeup may succeed, which would
++cause the system suspend to abort.  If the remote wakeup doesn't
++succeed, it may still remain active and thus cause the system to
++resume as soon as the system suspend is complete.  Or the remote
++wakeup may fail and get lost.  Which outcome occurs depends on timing
++and on the hardware and firmware design.
++
++More interestingly, a device might undergo a manual resume or
++autoresume during system suspend.  With current kernels this shouldn't
++happen, because manual resumes must be initiated by userspace and
++autoresumes happen in response to I/O requests, but all user processes
++and I/O should be quiescent during a system suspend -- thanks to the
++freezer.  However there are plans to do away with the freezer, which
++would mean these things would become possible.  If and when this comes
++about, the USB core will carefully arrange matters so that either type
++of resume will block until the entire system has resumed.

commit 271f9e68f3450ac8d1ff3bda36581f1ec0d0cc1f
+Author: Alan Stern 
+Date:   Wed Oct 10 16:30:12 2007 -0400
+
+    USB: skip autosuspended devices during system resume
+    
+    System suspends and hibernation are supposed to be as transparent as
+    possible.  By this reasoning, if a USB device is already autosuspended
+    before the system sleep begins then it should remain autosuspended
+    after the system wakes up.
+    
+    This patch (as1001) adds a skip_sys_resume flag to the usb_device
+    structure and uses it to avoid waking up devices which were suspended
+    when a system sleep began.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 3f734240e0ec..8c1eac27f2de 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1540,9 +1540,21 @@ int usb_external_resume_device(struct usb_device *udev)
+ 
+ static int usb_suspend(struct device *dev, pm_message_t message)
+ {
++	struct usb_device	*udev;
++
+ 	if (!is_usb_device(dev))	/* Ignore PM for interfaces */
+ 		return 0;
+-	return usb_external_suspend_device(to_usb_device(dev), message);
++	udev = to_usb_device(dev);
++
++	/* If udev is already suspended, we can skip this suspend and
++	 * we should also skip the upcoming system resume. */
++	if (udev->state == USB_STATE_SUSPENDED) {
++		udev->skip_sys_resume = 1;
++		return 0;
++	}
++
++	udev->skip_sys_resume = 0;
++	return usb_external_suspend_device(udev, message);
+ }
+ 
+ static int usb_resume(struct device *dev)
+@@ -1553,13 +1565,14 @@ static int usb_resume(struct device *dev)
+ 		return 0;
+ 	udev = to_usb_device(dev);
+ 
+-	/* If autoresume is disabled then we also want to prevent resume
+-	 * during system wakeup.  However, a "persistent-device" reset-resume
+-	 * after power loss counts as a wakeup event.  So allow a
+-	 * reset-resume to occur if remote wakeup is enabled. */
+-	if (udev->autoresume_disabled) {
++	/* If udev->skip_sys_resume is set then udev was already suspended
++	 * when the system suspend started, so we don't want to resume
++	 * udev during this system wakeup.  However a reset-resume counts
++	 * as a wakeup event, so allow a reset-resume to occur if remote
++	 * wakeup is enabled. */
++	if (udev->skip_sys_resume) {
+ 		if (!(udev->reset_resume && udev->do_remote_wakeup))
+-			return -EPERM;
++			return -EHOSTUNREACH;
+ 	}
+ 	return usb_external_resume_device(udev);
+ }
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index c10935fdc03a..c5c8f169d3cf 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -430,6 +430,7 @@ struct usb_device {
+ 	unsigned persist_enabled:1;	/* USB_PERSIST enabled for this dev */
+ 	unsigned autosuspend_disabled:1; /* autosuspend and autoresume */
+ 	unsigned autoresume_disabled:1;  /*  disabled by the user */
++	unsigned skip_sys_resume:1;	/* skip the next system resume */
+ #endif
+ };
+ #define	to_usb_device(d) container_of(d, struct usb_device, dev)

commit 32fe01985aa2cb2562f6fc171e526e279abe10db
+Author: Alan Stern 
+Date:   Wed Oct 10 16:27:07 2007 -0400
+
+    USB: mutual exclusion for EHCI init and port resets
+    
+    This patch (as999) fixes a problem that sometimes shows up when host
+    controller driver modules are loaded in the wrong order.  If ehci-hcd
+    happens to initialize an EHCI controller while the companion OHCI or
+    UHCI controller is in the middle of a port reset, the reset can fail
+    and the companion may get very confused.  The patch adds an
+    rw-semaphore and uses it to keep EHCI initialization and port resets
+    mutually exclusive.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: David Brownell 
+    Cc: David Miller 
+    Cc: Dely L Sy 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index 1396141274f1..98e24194a4ab 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -19,6 +19,8 @@
+ 
+ #ifdef __KERNEL__
+ 
++#include 
++
+ /* This file contains declarations of usbcore internals that are mostly
+  * used or exposed by Host Controller Drivers.
+  */
+@@ -470,5 +472,9 @@ static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb,
+ 		: (in_interrupt () ? "in_interrupt" : "can sleep"))
+ 
+ 
+-#endif /* __KERNEL__ */
++/* This rwsem is for use only by the hub driver and ehci-hcd.
++ * Nobody else should touch it.
++ */
++extern struct rw_semaphore ehci_cf_port_reset_rwsem;
+ 
++#endif /* __KERNEL__ */
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 481dca641ea2..d20cb545a6e4 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -125,6 +125,12 @@ MODULE_PARM_DESC(use_both_schemes,
+ 		"try the other device initialization scheme if the "
+ 		"first one fails");
+ 
++/* Mutual exclusion for EHCI CF initialization.  This interferes with
++ * port reset on some companion controllers.
++ */
++DECLARE_RWSEM(ehci_cf_port_reset_rwsem);
++EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem);
++
+ 
+ static inline char *portspeed(int portstatus)
+ {
+@@ -1581,6 +1587,11 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
+ {
+ 	int i, status;
+ 
++	/* Block EHCI CF initialization during the port reset.
++	 * Some companion controllers don't like it when they mix.
++	 */
++	down_read(&ehci_cf_port_reset_rwsem);
++
+ 	/* Reset the port */
+ 	for (i = 0; i < PORT_RESET_TRIES; i++) {
+ 		status = set_port_feature(hub->hdev,
+@@ -1612,7 +1623,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
+ 			usb_set_device_state(udev, status
+ 					? USB_STATE_NOTATTACHED
+ 					: USB_STATE_DEFAULT);
+-			return status;
++			goto done;
+ 		}
+ 
+ 		dev_dbg (hub->intfdev,
+@@ -1625,6 +1636,8 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
+ 		"Cannot enable port %i.  Maybe the USB cable is bad?\n",
+ 		port1);
+ 
++ done:
++	up_read(&ehci_cf_port_reset_rwsem);
+ 	return status;
+ }
+ 
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index db00492588b6..c1514442883e 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -570,10 +570,18 @@ static int ehci_run (struct usb_hcd *hcd)
+ 	 * are explicitly handed to companion controller(s), so no TT is
+ 	 * involved with the root hub.  (Except where one is integrated,
+ 	 * and there's no companion controller unless maybe for USB OTG.)
++	 *
++	 * Turning on the CF flag will transfer ownership of all ports
++	 * from the companions to the EHCI controller.  If any of the
++	 * companions are in the middle of a port reset at the time, it
++	 * could cause trouble.  Write-locking ehci_cf_port_reset_rwsem
++	 * guarantees that no resets are in progress.
+ 	 */
++	down_write(&ehci_cf_port_reset_rwsem);
+ 	hcd->state = HC_STATE_RUNNING;
+ 	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
+ 	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
++	up_write(&ehci_cf_port_reset_rwsem);
+ 
+ 	temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase));
+ 	ehci_info (ehci,

commit 3046c6db575019ba4ce6b9deac352d438ddf733d
+Author: Alan Stern 
+Date:   Fri Oct 5 14:43:00 2007 -0400
+
+    USB: unusual_devs entry for Nikon DSC D2Xs
+    
+    This patch (as996) adds an unusual_devs entry for the Nikon DSC D2Xs
+    camera.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Phil Dibowitz 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 5129b538be90..edf92914674a 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -362,6 +362,13 @@ UNUSUAL_DEV(  0x04b0, 0x0413, 0x0110, 0x0110,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_FIX_CAPACITY),
+ 
++/* Reported by Paul Check  */
++UNUSUAL_DEV(  0x04b0, 0x0415, 0x0100, 0x0100,
++		"NIKON",
++		"NIKON DSC D2Xs",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_FIX_CAPACITY),
++
+ /* BENQ DC5330
+  * Reported by Manuel Fombuena  and
+  * Frank Copeland  */

commit a691efa9888e71232dfb4088fb8a8304ffc7b0f9
+Author: Alan Stern 
+Date:   Fri Sep 21 16:57:54 2007 -0400
+
+    USB: remove USB_QUIRK_NO_AUTOSUSPEND
+    
+    This patch (as995) cleans up the remains of the former NO_AUTOSUSPEND
+    quirk.  Since autosuspend is disabled by default, we will let
+    userspace worry about which devices can safely be suspended.  Thus the
+    lengthy series of quirk entries is no longer needed, and neither is
+    the quirk ID.  I suppose someone might eventually run across a hub
+    that can't be suspended; let's ignore the possibility for now.
+    
+    The patch also cleans up the hasty way in which autosuspend gets
+    disabled.  Setting udev->autosuspend_delay to -1 wasn't quite right,
+    because the value is always supposed to be a multiple of HZ.  It's
+    better to leave the delay value alone and set autosuspend_disabled,
+    which is what the quirk routine used to do.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index ebf3dc20110a..d42c561c75f1 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -32,52 +32,6 @@ static const struct usb_device_id usb_quirk_list[] = {
+ 	{ USB_DEVICE(0x0204, 0x6025), .driver_info = USB_QUIRK_RESET_RESUME },
+ 	/* HP 5300/5370C scanner */
+ 	{ USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 },
+-	/* Hewlett-Packard PhotoSmart 720 / PhotoSmart 935 (storage) */
+-	{ USB_DEVICE(0x03f0, 0x4002), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-
+-	/* SGS Thomson Microelectronics 4in1 card reader */
+-	{ USB_DEVICE(0x0483, 0x0321), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-
+-	/* Acer Peripherals Inc. (now BenQ Corp.) Prisa 640BU */
+-	{ USB_DEVICE(0x04a5, 0x207e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-	/* Benq S2W 3300U */
+-	{ USB_DEVICE(0x04a5, 0x20b0), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-	/* Canon, Inc. CanoScan N1240U/LiDE30 */
+-	{ USB_DEVICE(0x04a9, 0x220e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-	/* Canon, Inc. CanoScan N650U/N656U */
+-	{ USB_DEVICE(0x04a9, 0x2206), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-	/* Canon, Inc. CanoScan 1220U */
+-	{ USB_DEVICE(0x04a9, 0x2207), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-	/* Canon, Inc. CanoScan N670U/N676U/LiDE 20 */
+-	{ USB_DEVICE(0x04a9, 0x220d), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-	/* old Cannon scanner */
+-	{ USB_DEVICE(0x04a9, 0x2220), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-	/* Seiko Epson Corp. Perfection 1200 */
+-	{ USB_DEVICE(0x04b8, 0x0104), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-	/* Seiko Epson Corp. Perfection 660 */
+-	{ USB_DEVICE(0x04b8, 0x0114), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-	/* Epson Perfection 1260 Photo */
+-	{ USB_DEVICE(0x04b8, 0x011d), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-	/* Seiko Epson Corp - Perfection 1670 */
+-	{ USB_DEVICE(0x04b8, 0x011f), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-	/* EPSON Perfection 2480 */
+-	{ USB_DEVICE(0x04b8, 0x0121), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-	/* Seiko Epson Corp.*/
+-	{ USB_DEVICE(0x04b8, 0x0122), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-	/* Samsung ML-2010 printer */
+-	{ USB_DEVICE(0x04e8, 0x326c), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-	/* Samsung ML-2510 Series printer */
+-	{ USB_DEVICE(0x04e8, 0x327e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-	/* Elsa MicroLink 56k (V.250) */
+-	{ USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-	/* Ultima Electronics Corp.*/
+-	{ USB_DEVICE(0x05d8, 0x4005), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-
+-	/* Genesys USB-to-IDE */
+-	{ USB_DEVICE(0x0503, 0x0702), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-
+-	/* USB Graphical LCD - EEH Datalink GmbH */
+-	{ USB_DEVICE(0x060c, 0x04eb), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+ 
+ 	/* INTEL VALUE SSD */
+ 	{ USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
+@@ -85,44 +39,15 @@ static const struct usb_device_id usb_quirk_list[] = {
+ 	/* M-Systems Flash Disk Pioneers */
+ 	{ USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
+ 
+-	/* Agfa Snapscan1212u */
+-	{ USB_DEVICE(0x06bd, 0x2061), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-	/* Seagate RSS LLC */
+-	{ USB_DEVICE(0x0bc2, 0x3000), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-	/* Umax [hex] Astra 3400U */
+-	{ USB_DEVICE(0x1606, 0x0060), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-
+ 	/* Philips PSC805 audio device */
+ 	{ USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME },
+ 
+-	/* Alcor multi-card reader */
+-	{ USB_DEVICE(0x058f, 0x6366), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-
+-	/* Canon EOS 5D in PC Connection mode */
+-	{ USB_DEVICE(0x04a9, 0x3101), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-
+-	/* RIM Blackberry */
+-	{ USB_DEVICE(0x0fca, 0x0001), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-	{ USB_DEVICE(0x0fca, 0x0004), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-	{ USB_DEVICE(0x0fca, 0x0006), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-
+-	/* Apple iPhone */
+-	{ USB_DEVICE(0x05ac, 0x1290), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+-
+ 	/* SKYMEDI USB_DRIVE */
+ 	{ USB_DEVICE(0x1516, 0x8628), .driver_info = USB_QUIRK_RESET_RESUME },
+ 
+ 	{ }  /* terminating entry must be last */
+ };
+ 
+-static void usb_autosuspend_quirk(struct usb_device *udev)
+-{
+-#ifdef	CONFIG_USB_SUSPEND
+-	/* disable autosuspend, but allow the user to re-enable it via sysfs */
+-	udev->autosuspend_disabled = 1;
+-#endif
+-}
+-
+ static const struct usb_device_id *find_id(struct usb_device *udev)
+ {
+ 	const struct usb_device_id *id = usb_quirk_list;
+@@ -149,13 +74,9 @@ void usb_detect_quirks(struct usb_device *udev)
+ 		dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
+ 				udev->quirks);
+ 
+-	/* do any special quirk handling here if needed */
+-	if (udev->quirks & USB_QUIRK_NO_AUTOSUSPEND)
+-		usb_autosuspend_quirk(udev);
+-
+ 	/* By default, disable autosuspend for all non-hubs */
+ #ifdef	CONFIG_USB_SUSPEND
+ 	if (udev->descriptor.bDeviceClass != USB_CLASS_HUB)
+-		udev->autosuspend_delay = -1;
++		udev->autosuspend_disabled = 1;
+ #endif
+ }
+diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h
+index 8da374caf582..2692ec9389ca 100644
+--- a/include/linux/usb/quirks.h
++++ b/include/linux/usb/quirks.h
+@@ -4,11 +4,8 @@
+  * belong here.
+  */
+ 
+-/* device must not be autosuspended */
+-#define USB_QUIRK_NO_AUTOSUSPEND	0x00000001
+-
+ /* string descriptors must not be fetched using a 255-byte read */
+-#define USB_QUIRK_STRING_FETCH_255	0x00000002
++#define USB_QUIRK_STRING_FETCH_255	0x00000001
+ 
+ /* device can't resume correctly so reset it instead */
+-#define USB_QUIRK_RESET_RESUME		0x00000004
++#define USB_QUIRK_RESET_RESUME		0x00000002

commit 7108f28465a0a37d5afc05c5ad788938423b74a7
+Author: Alan Stern 
+Date:   Thu Sep 20 12:37:50 2007 -0400
+
+    USB: don't propagate FREEZE or PRETHAW suspends
+    
+    This patch (as992) fixes a recently-added bug.  During a FREEZE or
+    PRETHAW suspend notification, non-root devices don't actually get
+    suspended.  So we shouldn't tell their parent hubs that they did.
+    
+    (This code path used to be skipped over, until the FREEZE/PRETHAW test
+    got moved out of usb_suspend_both() into generic_suspend().)
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index ba5bbc7eedcc..3f734240e0ec 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1112,7 +1112,12 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 			usb_hcd_flush_endpoint(udev, udev->ep_out[i]);
+ 			usb_hcd_flush_endpoint(udev, udev->ep_in[i]);
+ 		}
+-		if (parent)
++
++		/* If this is just a FREEZE or a PRETHAW, udev might
++		 * not really be suspended.  Only true suspends get
++		 * propagated up the device tree.
++		 */
++		if (parent && udev->state == USB_STATE_SUSPENDED)
+ 			usb_autosuspend_device(parent);
+ 	}
+ 

commit 393e5511a5f58e82b88589f1dd2464f6b661df06
+Author: Alan Stern 
+Date:   Tue Sep 18 10:09:32 2007 -0400
+
+    USB: unusual_devs update for Nokia 6131
+    
+    This patch (as991) updates the unusual_devs entry for the Nokia 6131
+    phone.  As reported by Juan Ignacio Cherrutti, there's new firmware
+    available but it still has the same old transfer-size limit.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 94b1dd2aeb3b..b0ff02955804 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -198,7 +198,7 @@ UNUSUAL_DEV(  0x0421, 0x044e, 0x0100, 0x0100,
+ 		US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
+ 
+ /* Reported by Bardur Arantsson  */
+-UNUSUAL_DEV(  0x0421, 0x047c, 0x0370, 0x0370,
++UNUSUAL_DEV(  0x0421, 0x047c, 0x0370, 0x0610,
+ 		"Nokia",
+ 		"6131",
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,

commit 6840d2555afd66290be7a39b400b5e66a840b82d
+Author: Alan Stern 
+Date:   Mon Sep 10 11:34:26 2007 -0400
+
+    USB: flush outstanding URBs when suspending
+    
+    This patch (as989) makes usbcore flush all outstanding URBs for each
+    device as the device is suspended.  This will be true even when
+    CONFIG_USB_SUSPEND is not enabled.
+    
+    In addition, an extra can_submit flag is added to the usb_device
+    structure.  That flag will be turned off whenever a suspend request
+    has been received for the device, even if the device isn't actually
+    suspended because CONFIG_USB_SUSPEND isn't set.
+    
+    It's no longer necessary to check for the device state being equal to
+    USB_STATE_SUSPENDED during URB submission; that check can be replaced
+    by a check of the can_submit flag.  This also permits us to remove
+    some questionable references to the deprecated power.power_state field.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index ca43a6f824ab..ba5bbc7eedcc 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1102,9 +1102,16 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 		if (udev->auto_pm)
+ 			autosuspend_check(udev);
+ 
+-	/* If the suspend succeeded, propagate it up the tree */
++	/* If the suspend succeeded then prevent any more URB submissions,
++	 * flush any outstanding URBs, and propagate the suspend up the tree.
++	 */
+ 	} else {
+ 		cancel_delayed_work(&udev->autosuspend);
++		udev->can_submit = 0;
++		for (i = 0; i < 16; ++i) {
++			usb_hcd_flush_endpoint(udev, udev->ep_out[i]);
++			usb_hcd_flush_endpoint(udev, udev->ep_in[i]);
++		}
+ 		if (parent)
+ 			usb_autosuspend_device(parent);
+ 	}
+@@ -1154,6 +1161,7 @@ static int usb_resume_both(struct usb_device *udev)
+ 		status = -ENODEV;
+ 		goto done;
+ 	}
++	udev->can_submit = 1;
+ 
+ 	/* Propagate the resume up the tree, if necessary */
+ 	if (udev->state == USB_STATE_SUSPENDED) {
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index e5874e8b8cbc..2c79aa6ca2b4 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1014,6 +1014,11 @@ int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb)
+ 		goto done;
+ 	}
+ 
++	if (unlikely(!urb->dev->can_submit)) {
++		rc = -EHOSTUNREACH;
++		goto done;
++	}
++
+ 	/*
+ 	 * Check the host controller's state and add the URB to the
+ 	 * endpoint's queue.
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index bd08d51d7f41..691acf2223c2 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1955,14 +1955,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+ 		struct usb_device	*udev;
+ 
+ 		udev = hdev->children [port1-1];
+-		if (udev && msg.event == PM_EVENT_SUSPEND &&
+-#ifdef	CONFIG_USB_SUSPEND
+-				udev->state != USB_STATE_SUSPENDED
+-#else
+-				udev->dev.power.power_state.event
+-					== PM_EVENT_ON
+-#endif
+-				) {
++		if (udev && udev->can_submit) {
+ 			if (!hdev->auto_pm)
+ 				dev_dbg(&intf->dev, "port %d nyet suspended\n",
+ 						port1);
+diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
+index 76db76fdb4ec..c20c03aaf012 100644
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -286,9 +286,6 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 		return -EINVAL;
+ 	if (!(dev = urb->dev) || dev->state < USB_STATE_DEFAULT)
+ 		return -ENODEV;
+-	if (dev->bus->controller->power.power_state.event != PM_EVENT_ON
+-			|| dev->state == USB_STATE_SUSPENDED)
+-		return -EHOSTUNREACH;
+ 
+ 	/* For now, get the endpoint from the pipe.  Eventually drivers
+ 	 * will be required to set urb->ep directly and we will eliminate
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index e5ff161776fa..8121edbd1494 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -272,6 +272,7 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
+ 	dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;
+ 	/* ep0 maxpacket comes later, from device descriptor */
+ 	usb_enable_endpoint(dev, &dev->ep0);
++	dev->can_submit = 1;
+ 
+ 	/* Save readable and stable topology id, distinguishing devices
+ 	 * by location for diagnostics, tools, driver model, etc.  The
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 5b14b4c81fd6..e5b35e0dca23 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -383,6 +383,7 @@ struct usb_device {
+ 	u8 portnum;			/* Parent port number (origin 1) */
+ 	u8 level;			/* Number of USB hub ancestors */
+ 
++	unsigned can_submit:1;		/* URBs may be submitted */
+ 	unsigned discon_suspended:1;	/* Disconnected while suspended */
+ 	unsigned have_langid:1;		/* whether string_langid is valid */
+ 	unsigned authorized:1;		/* Policy has determined we can use it */

commit 95cf82f99cfbd697c15572c444bd4f54f19745b0
+Author: Alan Stern 
+Date:   Mon Sep 10 11:33:05 2007 -0400
+
+    USB: break apart flush_endpoint and disable_endpoint
+    
+    This patch (as988) breaks usb_hcd_endpoint_disable() apart into two
+    routines.  The first, usb_hcd_flush_endpoint() does the -ESHUTDOWN
+    unlinking of all URBs in the endpoint's queue and waits for them to
+    complete.  The second, usb_hcd_disable_endpoint() -- renamed for
+    better grammatical style -- merely calls the HCD's endpoint_disable
+    method.  The changeover is easy because the routine currently has only
+    one caller.
+    
+    This separation of function will be exploited in the following patch:
+    When a device is suspended, the core will be able to cancel all
+    outstanding URBs for that device while leaving the HCD's
+    endpoint-related data structures intact for later.
+    
+    As an added benefit, HCDs no longer need to check for existing URBs in
+    their endpoint_disable methods.  It is now guaranteed that there will
+    be none.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 1c5e5d35e08d..e5874e8b8cbc 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1289,24 +1289,22 @@ EXPORT_SYMBOL (usb_hcd_giveback_urb);
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-/* disables the endpoint: cancels any pending urbs, then synchronizes with
+- * the hcd to make sure all endpoint state is gone from hardware, and then
+- * waits until the endpoint's queue is completely drained. use for
+- * set_configuration, set_interface, driver removal, physical disconnect.
+- *
+- * example:  a qh stored in ep->hcpriv, holding state related to endpoint
+- * type, maxpacket size, toggle, halt status, and scheduling.
++/* Cancel all URBs pending on this endpoint and wait for the endpoint's
++ * queue to drain completely.  The caller must first insure that no more
++ * URBs can be submitted for this endpoint.
+  */
+-void usb_hcd_endpoint_disable (struct usb_device *udev,
++void usb_hcd_flush_endpoint(struct usb_device *udev,
+ 		struct usb_host_endpoint *ep)
+ {
+ 	struct usb_hcd		*hcd;
+ 	struct urb		*urb;
+ 
++	if (!ep)
++		return;
+ 	might_sleep();
+ 	hcd = bus_to_hcd(udev->bus);
+ 
+-	/* ep is already gone from udev->ep_{in,out}[]; no more submits */
++	/* No more submits can occur */
+ rescan:
+ 	spin_lock_irq(&hcd_urb_list_lock);
+ 	list_for_each_entry (urb, &ep->urb_list, urb_list) {
+@@ -1345,18 +1343,7 @@ void usb_hcd_endpoint_disable (struct usb_device *udev,
+ 	}
+ 	spin_unlock_irq(&hcd_urb_list_lock);
+ 
+-	/* synchronize with the hardware, so old configuration state
+-	 * clears out immediately (and will be freed).
+-	 */
+-	if (hcd->driver->endpoint_disable)
+-		hcd->driver->endpoint_disable (hcd, ep);
+-
+-	/* Wait until the endpoint queue is completely empty.  Most HCDs
+-	 * will have done this already in their endpoint_disable method,
+-	 * but some might not.  And there could be root-hub control URBs
+-	 * still pending since they aren't affected by the HCDs'
+-	 * endpoint_disable methods.
+-	 */
++	/* Wait until the endpoint queue is completely empty */
+ 	while (!list_empty (&ep->urb_list)) {
+ 		spin_lock_irq(&hcd_urb_list_lock);
+ 
+@@ -1376,6 +1363,25 @@ void usb_hcd_endpoint_disable (struct usb_device *udev,
+ 	}
+ }
+ 
++/* Disables the endpoint: synchronizes with the hcd to make sure all
++ * endpoint state is gone from hardware.  usb_hcd_flush_endpoint() must
++ * have been called previously.  Use for set_configuration, set_interface,
++ * driver removal, physical disconnect.
++ *
++ * example:  a qh stored in ep->hcpriv, holding state related to endpoint
++ * type, maxpacket size, toggle, halt status, and scheduling.
++ */
++void usb_hcd_disable_endpoint(struct usb_device *udev,
++		struct usb_host_endpoint *ep)
++{
++	struct usb_hcd		*hcd;
++
++	might_sleep();
++	hcd = bus_to_hcd(udev->bus);
++	if (hcd->driver->endpoint_disable)
++		hcd->driver->endpoint_disable(hcd, ep);
++}
++
+ /*-------------------------------------------------------------------------*/
+ 
+ /* called in any context */
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index 0fc7b95259f5..1396141274f1 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -219,7 +219,9 @@ extern int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags);
+ extern int usb_hcd_unlink_urb (struct urb *urb, int status);
+ extern void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb,
+ 		int status);
+-extern void usb_hcd_endpoint_disable (struct usb_device *udev,
++extern void usb_hcd_flush_endpoint(struct usb_device *udev,
++		struct usb_host_endpoint *ep);
++extern void usb_hcd_disable_endpoint(struct usb_device *udev,
+ 		struct usb_host_endpoint *ep);
+ extern int usb_hcd_get_frame_number (struct usb_device *udev);
+ 
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index d638375e22e7..98fcddba6908 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1017,7 +1017,8 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr)
+ 	}
+ 	if (ep) {
+ 		ep->enabled = 0;
+-		usb_hcd_endpoint_disable(dev, ep);
++		usb_hcd_flush_endpoint(dev, ep);
++		usb_hcd_disable_endpoint(dev, ep);
+ 	}
+ }
+ 

commit 5ad4f71e2f19a06f738463da1f09ea7fda3a3db2
+Author: Alan Stern 
+Date:   Mon Sep 10 11:31:43 2007 -0400
+
+    USB: move decision to ignore FREEZE events
+    
+    This patch (as987) changes the way FREEZE and PRETHAW suspend events
+    are handled in usbcore.  The decision about whether or not to ignore
+    them for non-root devices is pushed down into the USB-device driver,
+    instead of being made in the core code.
+    
+    This is appropriate, since devices exported to a virtualized guest or
+    over a network may indeed need to handle these types of suspend, even
+    though normal devices don't.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 8da4801bb922..ca43a6f824ab 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1088,15 +1088,8 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 				break;
+ 		}
+ 	}
+-	if (status == 0) {
+-
+-		/* Non-root devices don't need to do anything for FREEZE
+-		 * or PRETHAW. */
+-		if (udev->parent && (msg.event == PM_EVENT_FREEZE ||
+-				msg.event == PM_EVENT_PRETHAW))
+-			goto done;
++	if (status == 0)
+ 		status = usb_suspend_device(udev, msg);
+-	}
+ 
+ 	/* If the suspend failed, resume interfaces that did get suspended */
+ 	if (status != 0) {
+diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
+index 9148b69785c5..c1cb94e9f242 100644
+--- a/drivers/usb/core/generic.c
++++ b/drivers/usb/core/generic.c
+@@ -206,8 +206,13 @@ static int generic_suspend(struct usb_device *udev, pm_message_t msg)
+ 	 */
+ 	if (!udev->parent)
+ 		rc = hcd_bus_suspend(udev);
++
++	/* Non-root devices don't need to do anything for FREEZE or PRETHAW */
++	else if (msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_PRETHAW)
++		rc = 0;
+ 	else
+ 		rc = usb_port_suspend(udev);
++
+ 	return rc;
+ }
+ 

commit 7477120e34eef65a530cfb3fea5fe612c89669e5
+Author: Alan Stern 
+Date:   Mon Sep 10 11:35:14 2007 -0400
+
+    USB: Get rid of annoying endpoint-release message
+    
+    This patch (as990) removes an annoying debugging message.  Nobody
+    really cares when endpoint pseudo-devices are released.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
+index e0ec7045e865..7dc123d6b2d0 100644
+--- a/drivers/usb/core/endpoint.c
++++ b/drivers/usb/core/endpoint.c
+@@ -267,7 +267,6 @@ static void ep_device_release(struct device *dev)
+ {
+ 	struct ep_device *ep_dev = to_ep_device(dev);
+ 
+-	dev_dbg(dev, "%s called for %s\n", __FUNCTION__, dev->bus_id);
+ 	endpoint_free_minor(ep_dev);
+ 	kfree(ep_dev);
+ }

commit 63f991b2871bdb1431e8ff62cae2b7b94b4e5b0c
+Author: Alan Stern 
+Date:   Tue Sep 4 09:53:24 2007 -0400
+
+    USB: fix location of statement label in dummy-hcd
+    
+    This patch (as984) fixes a rather elementary mistake in dummy_hcd.
+    The new statement label should come before the spin_unlock_irqrestore,
+    not after it.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index 58e4d7208805..6479a36d6f0e 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -1001,8 +1001,8 @@ static int dummy_urb_enqueue (
+ 	if (!timer_pending (&dum->timer))
+ 		mod_timer (&dum->timer, jiffies + 1);
+ 
+-	spin_unlock_irqrestore (&dum->lock, flags);
+  done:
++	spin_unlock_irqrestore(&dum->lock, flags);
+ 	return rc;
+ }
+ 

commit e015268d2fcfcaef70a1ec535e6381f75aafbf81
+Author: Alan Stern 
+Date:   Fri Aug 24 15:42:52 2007 -0400
+
+    USB: remove traces of urb->status from usbcore
+    
+    This patch (as981) removes the remaining nontrivial usages of
+    urb->status from usbcore.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index b9f1edd6af53..e5ad76b4a738 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -71,6 +71,7 @@ struct async {
+ 	void __user *userbuffer;
+ 	void __user *userurb;
+ 	struct urb *urb;
++	int status;
+ 	u32 secid;
+ };
+ 
+@@ -310,9 +311,10 @@ static void async_completed(struct urb *urb)
+         spin_lock(&ps->lock);
+         list_move_tail(&as->asynclist, &ps->async_completed);
+         spin_unlock(&ps->lock);
++	as->status = urb->status;
+ 	if (as->signr) {
+ 		sinfo.si_signo = as->signr;
+-		sinfo.si_errno = as->urb->status;
++		sinfo.si_errno = as->status;
+ 		sinfo.si_code = SI_ASYNCIO;
+ 		sinfo.si_addr = as->userurb;
+ 		kill_pid_info_as_uid(as->signr, &sinfo, as->pid, as->uid,
+@@ -1132,7 +1134,7 @@ static int processcompl(struct async *as, void __user * __user *arg)
+ 	if (as->userbuffer)
+ 		if (copy_to_user(as->userbuffer, urb->transfer_buffer, urb->transfer_buffer_length))
+ 			return -EFAULT;
+-	if (put_user(urb->status, &userurb->status))
++	if (put_user(as->status, &userurb->status))
+ 		return -EFAULT;
+ 	if (put_user(urb->actual_length, &userurb->actual_length))
+ 		return -EFAULT;
+@@ -1246,7 +1248,7 @@ static int processcompl_compat(struct async *as, void __user * __user *arg)
+ 	if (as->userbuffer)
+ 		if (copy_to_user(as->userbuffer, urb->transfer_buffer, urb->transfer_buffer_length))
+ 			return -EFAULT;
+-	if (put_user(urb->status, &userurb->status))
++	if (put_user(as->status, &userurb->status))
+ 		return -EFAULT;
+ 	if (put_user(urb->actual_length, &userurb->actual_length))
+ 		return -EFAULT;
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 4c495c4d5053..bd08d51d7f41 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -347,11 +347,11 @@ void usb_kick_khubd(struct usb_device *hdev)
+ static void hub_irq(struct urb *urb)
+ {
+ 	struct usb_hub *hub = urb->context;
+-	int status;
++	int status = urb->status;
+ 	int i;
+ 	unsigned long bits;
+ 
+-	switch (urb->status) {
++	switch (status) {
+ 	case -ENOENT:		/* synchronous unlink */
+ 	case -ECONNRESET:	/* async unlink */
+ 	case -ESHUTDOWN:	/* hardware going away */
+@@ -359,10 +359,10 @@ static void hub_irq(struct urb *urb)
+ 
+ 	default:		/* presumably an error */
+ 		/* Cause a hub reset after 10 consecutive errors */
+-		dev_dbg (hub->intfdev, "transfer --> %d\n", urb->status);
++		dev_dbg (hub->intfdev, "transfer --> %d\n", status);
+ 		if ((++hub->nerrors < 10) || hub->error)
+ 			goto resubmit;
+-		hub->error = urb->status;
++		hub->error = status;
+ 		/* FALL THROUGH */
+ 
+ 	/* let khubd handle things */

commit 1431d2a44ccf68a547094976f363f94177ab00c6
+Author: Alan Stern 
+Date:   Fri Aug 24 15:42:39 2007 -0400
+
+    USB: get rid of urb->lock
+    
+    Now that urb->status isn't used, urb->lock doesn't protect anything.
+    This patch (as980) removes it and replaces it with a private mutex in
+    the one remaining place it was still used: usb_kill_urb.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
+index 19f5f66c2733..76db76fdb4ec 100644
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -39,7 +39,6 @@ void usb_init_urb(struct urb *urb)
+ 	if (urb) {
+ 		memset(urb, 0, sizeof(*urb));
+ 		kref_init(&urb->kref);
+-		spin_lock_init(&urb->lock);
+ 		INIT_LIST_HEAD(&urb->anchor_list);
+ 	}
+ }
+@@ -541,19 +540,21 @@ int usb_unlink_urb(struct urb *urb)
+  */
+ void usb_kill_urb(struct urb *urb)
+ {
++	static DEFINE_MUTEX(reject_mutex);
++
+ 	might_sleep();
+ 	if (!(urb && urb->dev && urb->ep))
+ 		return;
+-	spin_lock_irq(&urb->lock);
++	mutex_lock(&reject_mutex);
+ 	++urb->reject;
+-	spin_unlock_irq(&urb->lock);
++	mutex_unlock(&reject_mutex);
+ 
+ 	usb_hcd_unlink_urb(urb, -ENOENT);
+ 	wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0);
+ 
+-	spin_lock_irq(&urb->lock);
++	mutex_lock(&reject_mutex);
+ 	--urb->reject;
+-	spin_unlock_irq(&urb->lock);
++	mutex_unlock(&reject_mutex);
+ }
+ 
+ /**
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 5c7b79088add..5b14b4c81fd6 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -1241,7 +1241,6 @@ struct urb
+ {
+ 	/* private: usb core and host controller only fields in the urb */
+ 	struct kref kref;		/* reference count of the URB */
+-	spinlock_t lock;		/* lock for the URB */
+ 	void *hcpriv;			/* private data for host controller */
+ 	atomic_t use_count;		/* concurrent submissions counter */
+ 	u8 reject;			/* submissions will fail */
+@@ -1299,7 +1298,6 @@ static inline void usb_fill_control_urb (struct urb *urb,
+ 					 usb_complete_t complete_fn,
+ 					 void *context)
+ {
+-	spin_lock_init(&urb->lock);
+ 	urb->dev = dev;
+ 	urb->pipe = pipe;
+ 	urb->setup_packet = setup_packet;
+@@ -1330,7 +1328,6 @@ static inline void usb_fill_bulk_urb (struct urb *urb,
+ 				      usb_complete_t complete_fn,
+ 				      void *context)
+ {
+-	spin_lock_init(&urb->lock);
+ 	urb->dev = dev;
+ 	urb->pipe = pipe;
+ 	urb->transfer_buffer = transfer_buffer;
+@@ -1366,7 +1363,6 @@ static inline void usb_fill_int_urb (struct urb *urb,
+ 				     void *context,
+ 				     int interval)
+ {
+-	spin_lock_init(&urb->lock);
+ 	urb->dev = dev;
+ 	urb->pipe = pipe;
+ 	urb->transfer_buffer = transfer_buffer;

commit 4a00027dcb088bf90fa8fb14a7e8ba3506d78f22
+Author: Alan Stern 
+Date:   Fri Aug 24 15:42:24 2007 -0400
+
+    USB: Eliminate urb->status usage!
+    
+    This patch (as979) removes the last vestiges of urb->status from the
+    host controller drivers and the root-hub emulator.  Now the field
+    doesn't get set until just before the URB's completion routine is
+    called.
+    
+    Signed-off-by: Alan Stern 
+    CC: David Brownell 
+    CC: Olav Kongas 
+    CC: Yoshihiro Shimoda 
+    CC: Tony Olech 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 4ac021e42cd8..1c5e5d35e08d 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -532,7 +532,6 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
+ 
+ 	/* any errors get returned through the urb completion */
+ 	spin_lock_irq(&hcd_root_hub_lock);
+-	urb->status = status;
+ 	usb_hcd_unlink_urb_from_ep(hcd, urb);
+ 
+ 	/* This peculiar use of spinlocks echoes what real HC drivers do.
+@@ -540,7 +539,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
+ 	 * RT-friendly.
+ 	 */
+ 	spin_unlock(&hcd_root_hub_lock);
+-	usb_hcd_giveback_urb(hcd, urb);
++	usb_hcd_giveback_urb(hcd, urb, status);
+ 	spin_lock(&hcd_root_hub_lock);
+ 
+ 	spin_unlock_irq(&hcd_root_hub_lock);
+@@ -578,13 +577,12 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
+ 		if (urb) {
+ 			hcd->poll_pending = 0;
+ 			hcd->status_urb = NULL;
+-			urb->status = 0;
+ 			urb->actual_length = length;
+ 			memcpy(urb->transfer_buffer, buffer, length);
+ 
+ 			usb_hcd_unlink_urb_from_ep(hcd, urb);
+ 			spin_unlock(&hcd_root_hub_lock);
+-			usb_hcd_giveback_urb(hcd, urb);
++			usb_hcd_giveback_urb(hcd, urb, 0);
+ 			spin_lock(&hcd_root_hub_lock);
+ 		} else {
+ 			length = 0;
+@@ -677,7 +675,7 @@ static int usb_rh_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ 			usb_hcd_unlink_urb_from_ep(hcd, urb);
+ 
+ 			spin_unlock(&hcd_root_hub_lock);
+-			usb_hcd_giveback_urb(hcd, urb);
++			usb_hcd_giveback_urb(hcd, urb, status);
+ 			spin_lock(&hcd_root_hub_lock);
+ 		}
+ 	}
+@@ -1252,6 +1250,7 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
+  * usb_hcd_giveback_urb - return URB from HCD to device driver
+  * @hcd: host controller returning the URB
+  * @urb: urb being returned to the USB device driver.
++ * @status: completion status code for the URB.
+  * Context: in_interrupt()
+  *
+  * This hands the URB from HCD to its USB device driver, using its
+@@ -1260,25 +1259,26 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
+  * the device driver won't cause problems if it frees, modifies,
+  * or resubmits this URB.
+  *
+- * If @urb was unlinked, the value of @urb->status will be overridden by
++ * If @urb was unlinked, the value of @status will be overridden by
+  * @urb->unlinked.  Erroneous short transfers are detected in case
+  * the HCD hasn't checked for them.
+  */
+-void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
++void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status)
+ {
+ 	urb->hcpriv = NULL;
+ 	if (unlikely(urb->unlinked))
+-		urb->status = urb->unlinked;
++		status = urb->unlinked;
+ 	else if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) &&
+ 			urb->actual_length < urb->transfer_buffer_length &&
+-			!urb->status))
+-		urb->status = -EREMOTEIO;
++			!status))
++		status = -EREMOTEIO;
+ 
+ 	unmap_urb_for_dma(hcd, urb);
+-	usbmon_urb_complete(&hcd->self, urb, urb->status);
++	usbmon_urb_complete(&hcd->self, urb, status);
+ 	usb_unanchor_urb(urb);
+ 
+ 	/* pass ownership to the completion handler */
++	urb->status = status;
+ 	urb->complete (urb);
+ 	atomic_dec (&urb->use_count);
+ 	if (unlikely (urb->reject))
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index 729b7a03acd8..0fc7b95259f5 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -217,7 +217,8 @@ extern void usb_hcd_unlink_urb_from_ep(struct usb_hcd *hcd, struct urb *urb);
+ 
+ extern int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags);
+ extern int usb_hcd_unlink_urb (struct urb *urb, int status);
+-extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb);
++extern void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb,
++		int status);
+ extern void usb_hcd_endpoint_disable (struct usb_device *udev,
+ 		struct usb_host_endpoint *ep);
+ extern int usb_hcd_get_frame_number (struct usb_device *udev);
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index c1af7bab26f0..58e4d7208805 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -1511,8 +1511,7 @@ static void dummy_timer (unsigned long _dum)
+ 
+ 		usb_hcd_unlink_urb_from_ep(dummy_to_hcd(dum), urb);
+ 		spin_unlock (&dum->lock);
+-		urb->status = status;
+-		usb_hcd_giveback_urb (dummy_to_hcd(dum), urb);
++		usb_hcd_giveback_urb(dummy_to_hcd(dum), urb, status);
+ 		spin_lock (&dum->lock);
+ 
+ 		goto restart;
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 794d27e07807..b10f39c047e9 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -256,8 +256,7 @@ __acquires(ehci->lock)
+ 	/* complete() can reenter this HCD */
+ 	usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
+ 	spin_unlock (&ehci->lock);
+-	urb->status = status;
+-	usb_hcd_giveback_urb (ehci_to_hcd(ehci), urb);
++	usb_hcd_giveback_urb(ehci_to_hcd(ehci), urb, status);
+ 	spin_lock (&ehci->lock);
+ }
+ 
+diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
+index 35b3507ff401..c27417f5b9d8 100644
+--- a/drivers/usb/host/isp116x-hcd.c
++++ b/drivers/usb/host/isp116x-hcd.c
+@@ -277,7 +277,7 @@ static void preproc_atl_queue(struct isp116x *isp116x)
+   processed urbs.
+ */
+ static void finish_request(struct isp116x *isp116x, struct isp116x_ep *ep,
+-			   struct urb *urb)
++			   struct urb *urb, int status)
+ __releases(isp116x->lock) __acquires(isp116x->lock)
+ {
+ 	unsigned i;
+@@ -291,7 +291,7 @@ __releases(isp116x->lock) __acquires(isp116x->lock)
+ 
+ 	usb_hcd_unlink_urb_from_ep(isp116x_to_hcd(isp116x), urb);
+ 	spin_unlock(&isp116x->lock);
+-	usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb);
++	usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb, status);
+ 	spin_lock(&isp116x->lock);
+ 
+ 	/* take idle endpoints out of the schedule */
+@@ -453,13 +453,8 @@ static void postproc_atl_queue(struct isp116x *isp116x)
+ 		}
+ 
+  done:
+-		if (status != -EINPROGRESS) {
+-			spin_lock(&urb->lock);
+-			urb->status = status;
+-			spin_unlock(&urb->lock);
+-		}
+-		if (urb->status != -EINPROGRESS || urb->unlinked)
+-			finish_request(isp116x, ep, urb);
++		if (status != -EINPROGRESS || urb->unlinked)
++			finish_request(isp116x, ep, urb, status);
+ 	}
+ }
+ 
+@@ -853,7 +848,7 @@ static int isp116x_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
+ 			}
+ 
+ 	if (urb)
+-		finish_request(isp116x, ep, urb);
++		finish_request(isp116x, ep, urb, status);
+  done:
+ 	spin_unlock_irqrestore(&isp116x->lock, flags);
+ 	return rc;
+diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
+index 13d31edd1a86..51817322232b 100644
+--- a/drivers/usb/host/ohci-q.c
++++ b/drivers/usb/host/ohci-q.c
+@@ -62,8 +62,7 @@ __acquires(ohci->lock)
+ 	/* urb->complete() can reenter this HCD */
+ 	usb_hcd_unlink_urb_from_ep(ohci_to_hcd(ohci), urb);
+ 	spin_unlock (&ohci->lock);
+-	urb->status = status;
+-	usb_hcd_giveback_urb (ohci_to_hcd(ohci), urb);
++	usb_hcd_giveback_urb(ohci_to_hcd(ohci), urb, status);
+ 	spin_lock (&ohci->lock);
+ 
+ 	/* stop periodic dma if it's not needed */
+diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
+index fea6036771f6..fd00f1e33fb5 100644
+--- a/drivers/usb/host/r8a66597-hcd.c
++++ b/drivers/usb/host/r8a66597-hcd.c
+@@ -782,12 +782,12 @@ static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address)
+ 		kfree(td);
+ 
+ 		if (urb) {
+-			urb->status = -ENODEV;
+ 			usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597),
+ 					urb);
+ 
+ 			spin_unlock(&r8a66597->lock);
+-			usb_hcd_giveback_urb(r8a66597_to_hcd(r8a66597), urb);
++			usb_hcd_giveback_urb(r8a66597_to_hcd(r8a66597), urb,
++					-ENODEV);
+ 			spin_lock(&r8a66597->lock);
+ 		}
+ 		break;
+@@ -1134,10 +1134,8 @@ __releases(r8a66597->lock) __acquires(r8a66597->lock)
+ 			urb->start_frame = r8a66597_get_frame(hcd);
+ 
+ 		usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), urb);
+-
+-		urb->status = status;
+ 		spin_unlock(&r8a66597->lock);
+-		usb_hcd_giveback_urb(hcd, urb);
++		usb_hcd_giveback_urb(hcd, urb, status);
+ 		spin_lock(&r8a66597->lock);
+ 	}
+ 
+diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
+index 515152809d37..94d859aa73f8 100644
+--- a/drivers/usb/host/sl811-hcd.c
++++ b/drivers/usb/host/sl811-hcd.c
+@@ -436,9 +436,8 @@ static void finish_request(
+ 		ep->nextpid = USB_PID_SETUP;
+ 
+ 	usb_hcd_unlink_urb_from_ep(sl811_to_hcd(sl811), urb);
+-	urb->status = status;
+ 	spin_unlock(&sl811->lock);
+-	usb_hcd_giveback_urb(sl811_to_hcd(sl811), urb);
++	usb_hcd_giveback_urb(sl811_to_hcd(sl811), urb, status);
+ 	spin_lock(&sl811->lock);
+ 
+ 	/* leave active endpoints in the schedule */
+diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
+index db800a434b83..2b379a78d0d5 100644
+--- a/drivers/usb/host/u132-hcd.c
++++ b/drivers/usb/host/u132-hcd.c
+@@ -518,7 +518,6 @@ static void u132_hcd_giveback_urb(struct u132 *u132, struct u132_endp *endp,
+         unsigned long irqs;
+         struct usb_hcd *hcd = u132_to_hcd(u132);
+         urb->error_count = 0;
+-        urb->status = status;
+         spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+ 	usb_hcd_unlink_urb_from_ep(hcd, urb);
+         endp->queue_next += 1;
+@@ -542,7 +541,7 @@ static void u132_hcd_giveback_urb(struct u132 *u132, struct u132_endp *endp,
+         u132_ring_queue_work(u132, ring, 0);
+         up(&u132->scheduler_lock);
+         u132_endp_put_kref(u132, endp);
+-        usb_hcd_giveback_urb(hcd, urb);
++	usb_hcd_giveback_urb(hcd, urb, status);
+         return;
+ }
+ 
+@@ -558,7 +557,6 @@ static void u132_hcd_abandon_urb(struct u132 *u132, struct u132_endp *endp,
+         unsigned long irqs;
+         struct usb_hcd *hcd = u132_to_hcd(u132);
+         urb->error_count = 0;
+-        urb->status = status;
+         spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+ 	usb_hcd_unlink_urb_from_ep(hcd, urb);
+         endp->queue_next += 1;
+@@ -575,7 +573,7 @@ static void u132_hcd_abandon_urb(struct u132 *u132, struct u132_endp *endp,
+                 endp->active = 0;
+                 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                 kfree(urbq);
+-        } usb_hcd_giveback_urb(hcd, urb);
++	} usb_hcd_giveback_urb(hcd, urb, status);
+         return;
+ }
+ 
+@@ -719,7 +717,7 @@ static void u132_hcd_interrupt_recv(void *data, struct urb *urb, u8 *buf,
+ 		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ 				"unlinked=%d\n", urb, urb->unlinked);
+                 up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
++		u132_hcd_giveback_urb(u132, endp, urb, 0);
+                 return;
+         }
+ }
+@@ -771,7 +769,7 @@ static void u132_hcd_bulk_output_sent(void *data, struct urb *urb, u8 *buf,
+ 		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ 				"unlinked=%d\n", urb, urb->unlinked);
+                 up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
++		u132_hcd_giveback_urb(u132, endp, urb, 0);
+                 return;
+         }
+ }
+@@ -874,7 +872,7 @@ static void u132_hcd_bulk_input_recv(void *data, struct urb *urb, u8 *buf,
+ 		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ 				"unlinked=%d\n", urb, urb->unlinked);
+                 up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
++		u132_hcd_giveback_urb(u132, endp, urb, 0);
+                 return;
+         }
+ }
+@@ -911,7 +909,7 @@ static void u132_hcd_configure_empty_sent(void *data, struct urb *urb, u8 *buf,
+ 		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ 				"unlinked=%d\n", urb, urb->unlinked);
+                 up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
++		u132_hcd_giveback_urb(u132, endp, urb, 0);
+                 return;
+         }
+ }
+@@ -983,7 +981,7 @@ static void u132_hcd_configure_input_recv(void *data, struct urb *urb, u8 *buf,
+ 		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ 				"unlinked=%d\n", urb, urb->unlinked);
+                 up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
++		u132_hcd_giveback_urb(u132, endp, urb, 0);
+                 return;
+         }
+ }
+@@ -1020,7 +1018,7 @@ static void u132_hcd_configure_empty_recv(void *data, struct urb *urb, u8 *buf,
+ 		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ 				"unlinked=%d\n", urb, urb->unlinked);
+                 up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
++		u132_hcd_giveback_urb(u132, endp, urb, 0);
+                 return;
+         }
+ }
+@@ -1080,7 +1078,7 @@ static void u132_hcd_configure_setup_sent(void *data, struct urb *urb, u8 *buf,
+ 		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ 				"unlinked=%d\n", urb, urb->unlinked);
+                 up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
++		u132_hcd_giveback_urb(u132, endp, urb, 0);
+                 return;
+         }
+ }
+@@ -1121,7 +1119,7 @@ static void u132_hcd_enumeration_empty_recv(void *data, struct urb *urb,
+ 		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ 				"unlinked=%d\n", urb, urb->unlinked);
+                 up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
++		u132_hcd_giveback_urb(u132, endp, urb, 0);
+                 return;
+         }
+ }
+@@ -1165,7 +1163,7 @@ static void u132_hcd_enumeration_address_sent(void *data, struct urb *urb,
+ 		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ 				"unlinked=%d\n", urb, urb->unlinked);
+                 up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
++		u132_hcd_giveback_urb(u132, endp, urb, 0);
+                 return;
+         }
+ }
+@@ -1202,7 +1200,7 @@ static void u132_hcd_initial_empty_sent(void *data, struct urb *urb, u8 *buf,
+ 		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ 				"unlinked=%d\n", urb, urb->unlinked);
+                 up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
++		u132_hcd_giveback_urb(u132, endp, urb, 0);
+                 return;
+         }
+ }
+@@ -1254,7 +1252,7 @@ static void u132_hcd_initial_input_recv(void *data, struct urb *urb, u8 *buf,
+ 		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ 				"unlinked=%d\n", urb, urb->unlinked);
+                 up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
++		u132_hcd_giveback_urb(u132, endp, urb, 0);
+                 return;
+         }
+ }
+@@ -1299,7 +1297,7 @@ static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf,
+ 		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ 				"unlinked=%d\n", urb, urb->unlinked);
+                 up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
++		u132_hcd_giveback_urb(u132, endp, urb, 0);
+                 return;
+         }
+ }
+@@ -2428,7 +2426,7 @@ static int dequeue_from_overflow_chain(struct u132 *u132,
+                         list_del(scan);
+                         endp->queue_size -= 1;
+                         urb->error_count = 0;
+-                        usb_hcd_giveback_urb(hcd, urb);
++			usb_hcd_giveback_urb(hcd, urb, 0);
+                         return 0;
+                 } else
+                         continue;
+@@ -2472,7 +2470,7 @@ static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp,
+                         return 0;
+                 } else {
+                         spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+-                        u132_hcd_abandon_urb(u132, endp, urb, urb->status);
++			u132_hcd_abandon_urb(u132, endp, urb, status);
+                         return 0;
+                 }
+         } else {
+@@ -2513,7 +2511,7 @@ static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp,
+                                         irqs);
+                                 kfree(urbq);
+                         } urb->error_count = 0;
+-                        usb_hcd_giveback_urb(hcd, urb);
++			usb_hcd_giveback_urb(hcd, urb, status);
+                         return 0;
+                 } else if (list_empty(&endp->urb_more)) {
+                         dev_err(&u132->platform_dev->dev, "urb=%p not found in "
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index e46d2b0203cb..340d6ed3e6e9 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -456,21 +456,6 @@ struct urb_priv {
+ };
+ 
+ 
+-/*
+- * Locking in uhci.c
+- *
+- * Almost everything relating to the hardware schedule and processing
+- * of URBs is protected by uhci->lock.  urb->status is protected by
+- * urb->lock; that's the one exception.
+- *
+- * To prevent deadlocks, never lock uhci->lock while holding urb->lock.
+- * The safe order of locking is:
+- *
+- * #1 uhci->lock
+- * #2 urb->lock
+- */
+-
+-
+ /* Some special IDs */
+ 
+ #define PCI_VENDOR_ID_GENESYS		0x17a0
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index bab567266559..e5d60d5b105a 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -1480,7 +1480,7 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+  * Finish unlinking an URB and give it back
+  */
+ static void uhci_giveback_urb(struct uhci_hcd *uhci, struct uhci_qh *qh,
+-		struct urb *urb)
++		struct urb *urb, int status)
+ __releases(uhci->lock)
+ __acquires(uhci->lock)
+ {
+@@ -1520,7 +1520,7 @@ __acquires(uhci->lock)
+ 	usb_hcd_unlink_urb_from_ep(uhci_to_hcd(uhci), urb);
+ 
+ 	spin_unlock(&uhci->lock);
+-	usb_hcd_giveback_urb(uhci_to_hcd(uhci), urb);
++	usb_hcd_giveback_urb(uhci_to_hcd(uhci), urb, status);
+ 	spin_lock(&uhci->lock);
+ 
+ 	/* If the queue is now empty, we can unlink the QH and give up its
+@@ -1556,10 +1556,6 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ 		if (status == -EINPROGRESS)
+ 			break;
+ 
+-		spin_lock(&urb->lock);
+-		urb->status = status;
+-		spin_unlock(&urb->lock);
+-
+ 		/* Dequeued but completed URBs can't be given back unless
+ 		 * the QH is stopped or has finished unlinking. */
+ 		if (urb->unlinked) {
+@@ -1569,7 +1565,7 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ 				return;
+ 		}
+ 
+-		uhci_giveback_urb(uhci, qh, urb);
++		uhci_giveback_urb(uhci, qh, urb, status);
+ 		if (status < 0)
+ 			break;
+ 	}
+@@ -1594,7 +1590,7 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ 				qh->is_stopped = 0;
+ 				return;
+ 			}
+-			uhci_giveback_urb(uhci, qh, urb);
++			uhci_giveback_urb(uhci, qh, urb, 0);
+ 			goto restart;
+ 		}
+ 	}

commit 9347d51c52afcf1a77d2104f162cf8a085624c83
+Author: Alan Stern 
+Date:   Fri Aug 24 15:41:41 2007 -0400
+
+    USB: reorganize urb->status use in usbmon
+    
+    This patch (as978) reorganizes the way usbmon uses urb->status.  It
+    now accepts the status value as an argument.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Pete Zaitcev 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 8b17babf5c55..4ac021e42cd8 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1275,7 +1275,7 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
+ 		urb->status = -EREMOTEIO;
+ 
+ 	unmap_urb_for_dma(hcd, urb);
+-	usbmon_urb_complete(&hcd->self, urb);
++	usbmon_urb_complete(&hcd->self, urb, urb->status);
+ 	usb_unanchor_urb(urb);
+ 
+ 	/* pass ownership to the completion handler */
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index 745be2566f62..729b7a03acd8 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -413,7 +413,7 @@ static inline void usbfs_cleanup(void) { }
+ struct usb_mon_operations {
+ 	void (*urb_submit)(struct usb_bus *bus, struct urb *urb);
+ 	void (*urb_submit_error)(struct usb_bus *bus, struct urb *urb, int err);
+-	void (*urb_complete)(struct usb_bus *bus, struct urb *urb);
++	void (*urb_complete)(struct usb_bus *bus, struct urb *urb, int status);
+ 	/* void (*urb_unlink)(struct usb_bus *bus, struct urb *urb); */
+ };
+ 
+@@ -432,10 +432,11 @@ static inline void usbmon_urb_submit_error(struct usb_bus *bus, struct urb *urb,
+ 		(*mon_ops->urb_submit_error)(bus, urb, error);
+ }
+ 
+-static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb)
++static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb,
++		int status)
+ {
+ 	if (bus->monitored)
+-		(*mon_ops->urb_complete)(bus, urb);
++		(*mon_ops->urb_complete)(bus, urb, status);
+ }
+ 
+ int usb_mon_register(struct usb_mon_operations *ops);
+@@ -446,7 +447,8 @@ void usb_mon_deregister(void);
+ static inline void usbmon_urb_submit(struct usb_bus *bus, struct urb *urb) {}
+ static inline void usbmon_urb_submit_error(struct usb_bus *bus, struct urb *urb,
+     int error) {}
+-static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb) {}
++static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb,
++		int status) {}
+ 
+ #endif /* CONFIG_USB_MON */
+ 
+diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
+index 3d6f03819ffd..f06e4e2b49d3 100644
+--- a/drivers/usb/mon/mon_bin.c
++++ b/drivers/usb/mon/mon_bin.c
+@@ -386,7 +386,7 @@ static char mon_bin_get_data(const struct mon_reader_bin *rp,
+ }
+ 
+ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
+-    char ev_type)
++    char ev_type, int status)
+ {
+ 	const struct usb_endpoint_descriptor *epd = &urb->ep->desc;
+ 	unsigned long flags;
+@@ -452,7 +452,7 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
+ 	ep->id = (unsigned long) urb;
+ 	ep->ts_sec = ts.tv_sec;
+ 	ep->ts_usec = ts.tv_usec;
+-	ep->status = urb->status;
++	ep->status = status;
+ 	ep->len_urb = urb_length;
+ 	ep->len_cap = length;
+ 
+@@ -475,13 +475,13 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
+ static void mon_bin_submit(void *data, struct urb *urb)
+ {
+ 	struct mon_reader_bin *rp = data;
+-	mon_bin_event(rp, urb, 'S');
++	mon_bin_event(rp, urb, 'S', -EINPROGRESS);
+ }
+ 
+-static void mon_bin_complete(void *data, struct urb *urb)
++static void mon_bin_complete(void *data, struct urb *urb, int status)
+ {
+ 	struct mon_reader_bin *rp = data;
+-	mon_bin_event(rp, urb, 'C');
++	mon_bin_event(rp, urb, 'C', status);
+ }
+ 
+ static void mon_bin_error(void *data, struct urb *urb, int error)
+diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c
+index 2e317bd79e92..b371ffd39d36 100644
+--- a/drivers/usb/mon/mon_main.c
++++ b/drivers/usb/mon/mon_main.c
+@@ -129,7 +129,8 @@ static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int error)
+ 
+ /*
+  */
+-static void mon_bus_complete(struct mon_bus *mbus, struct urb *urb)
++static void mon_bus_complete(struct mon_bus *mbus, struct urb *urb,
++		int status)
+ {
+ 	unsigned long flags;
+ 	struct list_head *pos;
+@@ -139,18 +140,18 @@ static void mon_bus_complete(struct mon_bus *mbus, struct urb *urb)
+ 	mbus->cnt_events++;
+ 	list_for_each (pos, &mbus->r_list) {
+ 		r = list_entry(pos, struct mon_reader, r_link);
+-		r->rnf_complete(r->r_data, urb);
++		r->rnf_complete(r->r_data, urb, status);
+ 	}
+ 	spin_unlock_irqrestore(&mbus->lock, flags);
+ }
+ 
+-static void mon_complete(struct usb_bus *ubus, struct urb *urb)
++static void mon_complete(struct usb_bus *ubus, struct urb *urb, int status)
+ {
+ 	struct mon_bus *mbus;
+ 
+ 	if ((mbus = ubus->mon_bus) != NULL)
+-		mon_bus_complete(mbus, urb);
+-	mon_bus_complete(&mon_bus0, urb);
++		mon_bus_complete(mbus, urb, status);
++	mon_bus_complete(&mon_bus0, urb, status);
+ }
+ 
+ /* int (*unlink_urb) (struct urb *urb, int status); */
+diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
+index 663a702a17dd..ebb04ac4857b 100644
+--- a/drivers/usb/mon/mon_text.c
++++ b/drivers/usb/mon/mon_text.c
+@@ -183,7 +183,7 @@ static inline unsigned int mon_get_timestamp(void)
+ }
+ 
+ static void mon_text_event(struct mon_reader_text *rp, struct urb *urb,
+-    char ev_type)
++    char ev_type, int status)
+ {
+ 	struct mon_event_text *ep;
+ 	unsigned int stamp;
+@@ -210,7 +210,7 @@ static void mon_text_event(struct mon_reader_text *rp, struct urb *urb,
+ 	ep->length = (ev_type == 'S') ?
+ 	    urb->transfer_buffer_length : urb->actual_length;
+ 	/* Collecting status makes debugging sense for submits, too */
+-	ep->status = urb->status;
++	ep->status = status;
+ 
+ 	if (ep->xfertype == USB_ENDPOINT_XFER_INT) {
+ 		ep->interval = urb->interval;
+@@ -248,13 +248,13 @@ static void mon_text_event(struct mon_reader_text *rp, struct urb *urb,
+ static void mon_text_submit(void *data, struct urb *urb)
+ {
+ 	struct mon_reader_text *rp = data;
+-	mon_text_event(rp, urb, 'S');
++	mon_text_event(rp, urb, 'S', -EINPROGRESS);
+ }
+ 
+-static void mon_text_complete(void *data, struct urb *urb)
++static void mon_text_complete(void *data, struct urb *urb, int status)
+ {
+ 	struct mon_reader_text *rp = data;
+-	mon_text_event(rp, urb, 'C');
++	mon_text_event(rp, urb, 'C', status);
+ }
+ 
+ static void mon_text_error(void *data, struct urb *urb, int error)
+diff --git a/drivers/usb/mon/usb_mon.h b/drivers/usb/mon/usb_mon.h
+index f68ad6d99ad7..f5d84ff8c101 100644
+--- a/drivers/usb/mon/usb_mon.h
++++ b/drivers/usb/mon/usb_mon.h
+@@ -46,7 +46,7 @@ struct mon_reader {
+ 
+ 	void (*rnf_submit)(void *data, struct urb *urb);
+ 	void (*rnf_error)(void *data, struct urb *urb, int error);
+-	void (*rnf_complete)(void *data, struct urb *urb);
++	void (*rnf_complete)(void *data, struct urb *urb, int status);
+ };
+ 
+ void mon_reader_add(struct mon_bus *mbus, struct mon_reader *r);

commit 888fda47051716765175d0008450126c837adb32
+Author: Alan Stern 
+Date:   Fri Aug 24 15:41:18 2007 -0400
+
+    USB: reorganize urb->status use in r8a66597-hcd
+    
+    This patch (as977) reorganizes the way r8a66597-hcd sets urb->status.  It
+    now keeps the information in a local variable until the last moment.
+    
+    Parts of this patch were written by Yoshihiro Shimoda.
+    
+    Signed-off-by: Alan Stern 
+    CC: Yoshihiro Shimoda 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
+index 98b9e0547544..fea6036771f6 100644
+--- a/drivers/usb/host/r8a66597-hcd.c
++++ b/drivers/usb/host/r8a66597-hcd.c
+@@ -1109,7 +1109,7 @@ static void set_td_timer(struct r8a66597 *r8a66597, struct r8a66597_td *td)
+ 
+ /* this function must be called with interrupt disabled */
+ static void finish_request(struct r8a66597 *r8a66597, struct r8a66597_td *td,
+-		u16 pipenum, struct urb *urb)
++		u16 pipenum, struct urb *urb, int status)
+ __releases(r8a66597->lock) __acquires(r8a66597->lock)
+ {
+ 	int restart = 0;
+@@ -1118,7 +1118,7 @@ __releases(r8a66597->lock) __acquires(r8a66597->lock)
+ 	r8a66597->timeout_map &= ~(1 << pipenum);
+ 
+ 	if (likely(td)) {
+-		if (td->set_address && (urb->status != 0 || urb->unlinked))
++		if (td->set_address && (status != 0 || urb->unlinked))
+ 			r8a66597->address_map &= ~(1 << urb->setup_packet[2]);
+ 
+ 		pipe_toggle_save(r8a66597, td->pipe, urb);
+@@ -1135,6 +1135,7 @@ __releases(r8a66597->lock) __acquires(r8a66597->lock)
+ 
+ 		usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), urb);
+ 
++		urb->status = status;
+ 		spin_unlock(&r8a66597->lock);
+ 		usb_hcd_giveback_urb(hcd, urb);
+ 		spin_lock(&r8a66597->lock);
+@@ -1167,11 +1168,10 @@ static void packet_read(struct r8a66597 *r8a66597, u16 pipenum)
+ 	fifo_change_from_pipe(r8a66597, td->pipe);
+ 	tmp = r8a66597_read(r8a66597, td->pipe->fifoctr);
+ 	if (unlikely((tmp & FRDY) == 0)) {
+-		urb->status = -EPIPE;
+ 		pipe_stop(r8a66597, td->pipe);
+ 		pipe_irq_disable(r8a66597, pipenum);
+ 		err("in fifo not ready (%d)", pipenum);
+-		finish_request(r8a66597, td, pipenum, td->urb);
++		finish_request(r8a66597, td, pipenum, td->urb, -EPIPE);
+ 		return;
+ 	}
+ 
+@@ -1224,10 +1224,8 @@ static void packet_read(struct r8a66597 *r8a66597, u16 pipenum)
+ 					   buf, size);
+ 	}
+ 
+-	if (finish && pipenum != 0) {
+-		td->urb->status = status;
+-		finish_request(r8a66597, td, pipenum, urb);
+-	}
++	if (finish && pipenum != 0)
++		finish_request(r8a66597, td, pipenum, urb, status);
+ }
+ 
+ static void packet_write(struct r8a66597 *r8a66597, u16 pipenum)
+@@ -1245,11 +1243,10 @@ static void packet_write(struct r8a66597 *r8a66597, u16 pipenum)
+ 	fifo_change_from_pipe(r8a66597, td->pipe);
+ 	tmp = r8a66597_read(r8a66597, td->pipe->fifoctr);
+ 	if (unlikely((tmp & FRDY) == 0)) {
+-		urb->status = -EPIPE;
+ 		pipe_stop(r8a66597, td->pipe);
+ 		pipe_irq_disable(r8a66597, pipenum);
+ 		err("out write fifo not ready. (%d)", pipenum);
+-		finish_request(r8a66597, td, pipenum, td->urb);
++		finish_request(r8a66597, td, pipenum, urb, -EPIPE);
+ 		return;
+ 	}
+ 
+@@ -1294,7 +1291,7 @@ static void packet_write(struct r8a66597 *r8a66597, u16 pipenum)
+ }
+ 
+ 
+-static void check_next_phase(struct r8a66597 *r8a66597)
++static void check_next_phase(struct r8a66597 *r8a66597, int status)
+ {
+ 	struct r8a66597_td *td = r8a66597_get_td(r8a66597, 0);
+ 	struct urb *urb;
+@@ -1320,28 +1317,28 @@ static void check_next_phase(struct r8a66597 *r8a66597)
+ 		break;
+ 	case USB_PID_ACK:
+ 		finish = 1;
+-		urb->status = 0;
+ 		break;
+ 	}
+ 
+-	if (finish || urb->unlinked)
+-		finish_request(r8a66597, td, 0, urb);
++	if (finish || status != 0 || urb->unlinked)
++		finish_request(r8a66597, td, 0, urb, status);
+ 	else
+ 		start_transfer(r8a66597, td);
+ }
+ 
+-static void set_urb_error(struct r8a66597 *r8a66597, u16 pipenum)
++static int get_urb_error(struct r8a66597 *r8a66597, u16 pipenum)
+ {
+ 	struct r8a66597_td *td = r8a66597_get_td(r8a66597, pipenum);
+ 
+-	if (td && td->urb) {
++	if (td) {
+ 		u16 pid = r8a66597_read(r8a66597, td->pipe->pipectr) & PID;
+ 
+ 		if (pid == PID_NAK)
+-			td->urb->status = -ECONNRESET;
++			return -ECONNRESET;
+ 		else
+-			td->urb->status = -EPIPE;
++			return -EPIPE;
+ 	}
++	return 0;
+ }
+ 
+ static void irq_pipe_ready(struct r8a66597 *r8a66597)
+@@ -1360,7 +1357,7 @@ static void irq_pipe_ready(struct r8a66597 *r8a66597)
+ 			packet_read(r8a66597, 0);
+ 		else
+ 			pipe_irq_disable(r8a66597, 0);
+-		check_next_phase(r8a66597);
++		check_next_phase(r8a66597, 0);
+ 	}
+ 
+ 	for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
+@@ -1394,7 +1391,7 @@ static void irq_pipe_empty(struct r8a66597 *r8a66597)
+ 		td = r8a66597_get_td(r8a66597, 0);
+ 		if (td && td->type != USB_PID_OUT)
+ 			disable_irq_empty(r8a66597, 0);
+-		check_next_phase(r8a66597);
++		check_next_phase(r8a66597, 0);
+ 	}
+ 
+ 	for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
+@@ -1409,8 +1406,8 @@ static void irq_pipe_empty(struct r8a66597 *r8a66597)
+ 			if ((tmp & INBUFM) == 0) {
+ 				disable_irq_empty(r8a66597, pipenum);
+ 				pipe_irq_disable(r8a66597, pipenum);
+-				td->urb->status = 0;
+-				finish_request(r8a66597, td, pipenum, td->urb);
++				finish_request(r8a66597, td, pipenum, td->urb,
++						0);
+ 			}
+ 		}
+ 	}
+@@ -1421,15 +1418,16 @@ static void irq_pipe_nrdy(struct r8a66597 *r8a66597)
+ 	u16 check;
+ 	u16 pipenum;
+ 	u16 mask;
++	int status;
+ 
+ 	mask = r8a66597_read(r8a66597, NRDYSTS)
+ 	       & r8a66597_read(r8a66597, NRDYENB);
+ 	r8a66597_write(r8a66597, ~mask, NRDYSTS);
+ 	if (mask & NRDY0) {
+ 		cfifo_change(r8a66597, 0);
+-		set_urb_error(r8a66597, 0);
++		status = get_urb_error(r8a66597, 0);
+ 		pipe_irq_disable(r8a66597, 0);
+-		check_next_phase(r8a66597);
++		check_next_phase(r8a66597, status);
+ 	}
+ 
+ 	for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
+@@ -1440,10 +1438,10 @@ static void irq_pipe_nrdy(struct r8a66597 *r8a66597)
+ 			if (unlikely(!td))
+ 				continue;
+ 
+-			set_urb_error(r8a66597, pipenum);
++			status = get_urb_error(r8a66597, pipenum);
+ 			pipe_irq_disable(r8a66597, pipenum);
+ 			pipe_stop(r8a66597, td->pipe);
+-			finish_request(r8a66597, td, pipenum, td->urb);
++			finish_request(r8a66597, td, pipenum, td->urb, status);
+ 		}
+ 	}
+ }
+@@ -1463,6 +1461,7 @@ static irqreturn_t r8a66597_irq(struct usb_hcd *hcd)
+ 	u16 intsts0, intsts1, intsts2;
+ 	u16 intenb0, intenb1, intenb2;
+ 	u16 mask0, mask1, mask2;
++	int status;
+ 
+ 	spin_lock(&r8a66597->lock);
+ 
+@@ -1506,12 +1505,12 @@ static irqreturn_t r8a66597_irq(struct usb_hcd *hcd)
+ 		}
+ 		if (mask1 & SIGN) {
+ 			r8a66597_write(r8a66597, ~SIGN, INTSTS1);
+-			set_urb_error(r8a66597, 0);
+-			check_next_phase(r8a66597);
++			status = get_urb_error(r8a66597, 0);
++			check_next_phase(r8a66597, status);
+ 		}
+ 		if (mask1 & SACK) {
+ 			r8a66597_write(r8a66597, ~SACK, INTSTS1);
+-			check_next_phase(r8a66597);
++			check_next_phase(r8a66597, 0);
+ 		}
+ 	}
+ 	if (mask0) {
+@@ -1790,7 +1789,7 @@ static int r8a66597_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
+ 		pipe_stop(r8a66597, td->pipe);
+ 		pipe_irq_disable(r8a66597, td->pipenum);
+ 		disable_irq_empty(r8a66597, td->pipenum);
+-		finish_request(r8a66597, td, td->pipenum, urb);
++		finish_request(r8a66597, td, td->pipenum, urb, status);
+ 	}
+  done:
+ 	spin_unlock_irqrestore(&r8a66597->lock, flags);
+@@ -1824,7 +1823,7 @@ static void r8a66597_endpoint_disable(struct usb_hcd *hcd,
+ 	td = r8a66597_get_td(r8a66597, pipenum);
+ 	if (td)
+ 		urb = td->urb;
+-	finish_request(r8a66597, td, pipenum, urb);
++	finish_request(r8a66597, td, pipenum, urb, -ESHUTDOWN);
+ 	kfree(hep->hcpriv);
+ 	hep->hcpriv = NULL;
+ 	spin_unlock_irqrestore(&r8a66597->lock, flags);

commit 65e51098d9094c7e840b6d6291867b95538d9442
+Author: Alan Stern 
+Date:   Fri Aug 24 15:40:47 2007 -0400
+
+    USB: reorganize urb->status use in sl811-hcd
+    
+    This patch (as976) reorganizes the way sl811-hcd sets urb->status.  It
+    now keeps the information in a local variable until the last moment.
+    
+    The patch also improves the handling of faults during the status stage
+    of a control transfer, since it no longer needs to retain the error
+    information from the earlier stages.
+    
+    Signed-off-by: Alan Stern 
+    CC: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
+index f0fa94148d9d..515152809d37 100644
+--- a/drivers/usb/host/sl811-hcd.c
++++ b/drivers/usb/host/sl811-hcd.c
+@@ -435,11 +435,8 @@ static void finish_request(
+ 	if (usb_pipecontrol(urb->pipe))
+ 		ep->nextpid = USB_PID_SETUP;
+ 
+-	spin_lock(&urb->lock);
+-	urb->status = status;
+-	spin_unlock(&urb->lock);
+-
+ 	usb_hcd_unlink_urb_from_ep(sl811_to_hcd(sl811), urb);
++	urb->status = status;
+ 	spin_unlock(&sl811->lock);
+ 	usb_hcd_giveback_urb(sl811_to_hcd(sl811), urb);
+ 	spin_lock(&sl811->lock);
+@@ -537,27 +534,20 @@ done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank)
+ 						bank + SL11H_XFERCNTREG);
+ 			if (len > ep->length) {
+ 				len = ep->length;
+-				urb->status = -EOVERFLOW;
++				urbstat = -EOVERFLOW;
+ 			}
+ 			urb->actual_length += len;
+ 			sl811_read_buf(sl811, SL811HS_PACKET_BUF(bank == 0),
+ 					buf, len);
+ 			usb_dotoggle(udev, ep->epnum, 0);
+-			if (urb->actual_length == urb->transfer_buffer_length
+-					|| len < ep->maxpacket)
+-				urbstat = 0;
+-			if (usb_pipecontrol(urb->pipe) && urbstat == 0) {
+-
+-				/* NOTE if the status stage STALLs (why?),
+-				 * this reports the wrong urb status.
+-				 */
+-				spin_lock(&urb->lock);
+-				if (urb->status == -EINPROGRESS)
+-					urb->status = urbstat;
+-				spin_unlock(&urb->lock);
+-
+-				urb = NULL;
+-				ep->nextpid = USB_PID_ACK;
++			if (urbstat == -EINPROGRESS &&
++					(len < ep->maxpacket ||
++						urb->actual_length ==
++						urb->transfer_buffer_length)) {
++				if (usb_pipecontrol(urb->pipe))
++					ep->nextpid = USB_PID_ACK;
++				else
++					urbstat = 0;
+ 			}
+ 			break;
+ 		case USB_PID_SETUP:
+@@ -597,7 +587,7 @@ done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank)
+ 				bank, status, ep, urbstat);
+ 	}
+ 
+-	if (urb && (urbstat != -EINPROGRESS || urb->unlinked))
++	if (urbstat != -EINPROGRESS || urb->unlinked)
+ 		finish_request(sl811, ep, urb, urbstat);
+ }
+ 

commit 55d8496837cf124f68656e4242a5e20eb592fd54
+Author: Alan Stern 
+Date:   Fri Aug 24 15:40:34 2007 -0400
+
+    USB: reorganize urb->status use in ohci-hcd
+    
+    This patch (as975) reorganizes the way ohci-hcd sets urb->status.  It
+    now keeps the information in a local variable until the last moment.
+    
+    Signed-off-by: Alan Stern 
+    CC: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
+index f61c6cdd06f2..ebab5ce8f5ce 100644
+--- a/drivers/usb/host/ohci-dbg.c
++++ b/drivers/usb/host/ohci-dbg.c
+@@ -24,7 +24,7 @@
+  * small: 0) header + data packets 1) just header
+  */
+ static void __maybe_unused
+-urb_print (struct urb * urb, char * str, int small)
++urb_print(struct urb * urb, char * str, int small, int status)
+ {
+ 	unsigned int pipe= urb->pipe;
+ 
+@@ -34,7 +34,7 @@ urb_print (struct urb * urb, char * str, int small)
+ 	}
+ 
+ #ifndef	OHCI_VERBOSE_DEBUG
+-	if (urb->status != 0)
++	if (status != 0)
+ #endif
+ 	dbg("%s %p dev=%d ep=%d%s-%s flags=%x len=%d/%d stat=%d",
+ 		    str,
+@@ -46,7 +46,7 @@ urb_print (struct urb * urb, char * str, int small)
+ 		    urb->transfer_flags,
+ 		    urb->actual_length,
+ 		    urb->transfer_buffer_length,
+-		    urb->status);
++		    status);
+ 
+ #ifdef	OHCI_VERBOSE_DEBUG
+ 	if (!small) {
+@@ -66,7 +66,7 @@ urb_print (struct urb * urb, char * str, int small)
+ 						urb->transfer_buffer_length: urb->actual_length;
+ 			for (i = 0; i < 16 && i < len; i++)
+ 				printk (" %02x", ((__u8 *) urb->transfer_buffer) [i]);
+-			printk ("%s stat:%d\n", i < len? "...": "", urb->status);
++			printk ("%s stat:%d\n", i < len? "...": "", status);
+ 		}
+ 	}
+ #endif
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index 6b06ab69938f..f7c6ced2bc03 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -129,7 +129,7 @@ static int ohci_urb_enqueue (
+ 	int		retval = 0;
+ 
+ #ifdef OHCI_VERBOSE_DEBUG
+-	urb_print (urb, "SUB", usb_pipein (pipe));
++	urb_print(urb, "SUB", usb_pipein(pipe), -EINPROGRESS);
+ #endif
+ 
+ 	/* every endpoint has a ed, locate and maybe (re)initialize it */
+@@ -240,8 +240,8 @@ static int ohci_urb_enqueue (
+ }
+ 
+ /*
+- * decouple the URB from the HC queues (TDs, urb_priv); it's
+- * already marked using urb->status.  reporting is always done
++ * decouple the URB from the HC queues (TDs, urb_priv).
++ * reporting is always done
+  * asynchronously, and we might be dealing with an urb that's
+  * partially transferred, or an ED with other urbs being unlinked.
+  */
+@@ -252,7 +252,7 @@ static int ohci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ 	int			rc;
+ 
+ #ifdef OHCI_VERBOSE_DEBUG
+-	urb_print (urb, "UNLINK", 1);
++	urb_print(urb, "UNLINK", 1, status);
+ #endif
+ 
+ 	spin_lock_irqsave (&ohci->lock, flags);
+@@ -277,7 +277,7 @@ static int ohci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ 		 * any more ... just clean up every urb's memory.
+ 		 */
+ 		if (urb->hcpriv)
+-			finish_urb (ohci, urb);
++			finish_urb(ohci, urb, status);
+ 	}
+ 	spin_unlock_irqrestore (&ohci->lock, flags);
+ 	return rc;
+@@ -927,9 +927,8 @@ static int ohci_restart (struct ohci_hcd *ohci)
+ 					ed, ed->state);
+ 		}
+ 
+-		spin_lock (&urb->lock);
+-		urb->status = -ESHUTDOWN;
+-		spin_unlock (&urb->lock);
++		if (!urb->unlinked)
++			urb->unlinked = -ESHUTDOWN;
+ 	}
+ 	finish_unlinks (ohci, 0);
+ 	spin_unlock_irq(&ohci->lock);
+diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
+index 860e55ff67a1..13d31edd1a86 100644
+--- a/drivers/usb/host/ohci-q.c
++++ b/drivers/usb/host/ohci-q.c
+@@ -36,18 +36,15 @@ static void urb_free_priv (struct ohci_hcd *hc, urb_priv_t *urb_priv)
+  * PRECONDITION:  ohci lock held, irqs blocked.
+  */
+ static void
+-finish_urb (struct ohci_hcd *ohci, struct urb *urb)
++finish_urb(struct ohci_hcd *ohci, struct urb *urb, int status)
+ __releases(ohci->lock)
+ __acquires(ohci->lock)
+ {
+ 	// ASSERT (urb->hcpriv != 0);
+ 
+ 	urb_free_priv (ohci, urb->hcpriv);
+-
+-	spin_lock (&urb->lock);
+-	if (likely (urb->status == -EINPROGRESS))
+-		urb->status = 0;
+-	spin_unlock (&urb->lock);
++	if (likely(status == -EINPROGRESS))
++		status = 0;
+ 
+ 	switch (usb_pipetype (urb->pipe)) {
+ 	case PIPE_ISOCHRONOUS:
+@@ -59,12 +56,13 @@ __acquires(ohci->lock)
+ 	}
+ 
+ #ifdef OHCI_VERBOSE_DEBUG
+-	urb_print (urb, "RET", usb_pipeout (urb->pipe));
++	urb_print(urb, "RET", usb_pipeout (urb->pipe), status);
+ #endif
+ 
+ 	/* urb->complete() can reenter this HCD */
+ 	usb_hcd_unlink_urb_from_ep(ohci_to_hcd(ohci), urb);
+ 	spin_unlock (&ohci->lock);
++	urb->status = status;
+ 	usb_hcd_giveback_urb (ohci_to_hcd(ohci), urb);
+ 	spin_lock (&ohci->lock);
+ 
+@@ -702,19 +700,18 @@ static void td_submit_urb (
+  * Done List handling functions
+  *-------------------------------------------------------------------------*/
+ 
+-/* calculate transfer length/status and update the urb
+- * PRECONDITION:  irqsafe (only for urb->status locking)
+- */
+-static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
++/* calculate transfer length/status and update the urb */
++static int td_done(struct ohci_hcd *ohci, struct urb *urb, struct td *td)
+ {
+ 	u32	tdINFO = hc32_to_cpup (ohci, &td->hwINFO);
+ 	int	cc = 0;
++	int	status = -EINPROGRESS;
+ 
+ 	list_del (&td->td_list);
+ 
+ 	/* ISO ... drivers see per-TD length/status */
+ 	if (tdINFO & TD_ISO) {
+-		u16	tdPSW = ohci_hwPSW (ohci, td, 0);
++		u16	tdPSW = ohci_hwPSW(ohci, td, 0);
+ 		int	dlen = 0;
+ 
+ 		/* NOTE:  assumes FC in tdINFO == 0, and that
+@@ -723,7 +720,7 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
+ 
+ 		cc = (tdPSW >> 12) & 0xF;
+ 		if (tdINFO & TD_CC)	/* hc didn't touch? */
+-			return;
++			return status;
+ 
+ 		if (usb_pipeout (urb->pipe))
+ 			dlen = urb->iso_frame_desc [td->index].length;
+@@ -756,11 +753,8 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
+ 		if (cc == TD_DATAUNDERRUN
+ 				&& !(urb->transfer_flags & URB_SHORT_NOT_OK))
+ 			cc = TD_CC_NOERROR;
+-		if (cc != TD_CC_NOERROR && cc < 0x0E) {
+-			spin_lock (&urb->lock);
+-			urb->status = cc_to_error[cc];
+-			spin_unlock (&urb->lock);
+-		}
++		if (cc != TD_CC_NOERROR && cc < 0x0E)
++			status = cc_to_error[cc];
+ 
+ 		/* count all non-empty packets except control SETUP packet */
+ 		if ((type != PIPE_CONTROL || td->index != 0) && tdBE != 0) {
+@@ -779,6 +773,7 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
+ 				urb->actual_length,
+ 				urb->transfer_buffer_length);
+ 	}
++	return status;
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -979,7 +974,7 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick)
+ 			/* if URB is done, clean up */
+ 			if (urb_priv->td_cnt == urb_priv->length) {
+ 				modified = completed = 1;
+-				finish_urb (ohci, urb);
++				finish_urb(ohci, urb, 0);
+ 			}
+ 		}
+ 		if (completed && !list_empty (&ed->td_list))
+@@ -1062,14 +1057,15 @@ static void takeback_td(struct ohci_hcd *ohci, struct td *td)
+ 	struct urb	*urb = td->urb;
+ 	urb_priv_t	*urb_priv = urb->hcpriv;
+ 	struct ed	*ed = td->ed;
++	int		status;
+ 
+ 	/* update URB's length and status from TD */
+-	td_done(ohci, urb, td);
++	status = td_done(ohci, urb, td);
+ 	urb_priv->td_cnt++;
+ 
+ 	/* If all this urb's TDs are done, call complete() */
+ 	if (urb_priv->td_cnt == urb_priv->length)
+-		finish_urb(ohci, urb);
++		finish_urb(ohci, urb, status);
+ 
+ 	/* clean schedule:  unlink EDs that are no longer busy */
+ 	if (list_empty(&ed->td_list)) {

commit 14c04c0f88f228fee1f412be91d6edcb935c78aa
+Author: Alan Stern 
+Date:   Fri Aug 24 15:40:19 2007 -0400
+
+    USB: reorganize urb->status use in ehci-hcd
+    
+    This patch (as974) reorganizes the way ehci-hcd sets urb->status.  It
+    now keeps the information in a local variable until the last moment.
+    
+    The patch also simplifies the handling of -EREMOTEIO, since the only
+    use of that code is to set the do_status flag.
+    
+    Signed-off-by: Alan Stern 
+    CC: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index a8f5408c161d..794d27e07807 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -139,63 +139,65 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-static void qtd_copy_status (
++static int qtd_copy_status (
+ 	struct ehci_hcd *ehci,
+ 	struct urb *urb,
+ 	size_t length,
+ 	u32 token
+ )
+ {
++	int	status = -EINPROGRESS;
++
+ 	/* count IN/OUT bytes, not SETUP (even short packets) */
+ 	if (likely (QTD_PID (token) != 2))
+ 		urb->actual_length += length - QTD_LENGTH (token);
+ 
+ 	/* don't modify error codes */
+ 	if (unlikely(urb->unlinked))
+-		return;
++		return status;
+ 
+ 	/* force cleanup after short read; not always an error */
+ 	if (unlikely (IS_SHORT_READ (token)))
+-		urb->status = -EREMOTEIO;
++		status = -EREMOTEIO;
+ 
+ 	/* serious "can't proceed" faults reported by the hardware */
+ 	if (token & QTD_STS_HALT) {
+ 		if (token & QTD_STS_BABBLE) {
+ 			/* FIXME "must" disable babbling device's port too */
+-			urb->status = -EOVERFLOW;
++			status = -EOVERFLOW;
+ 		} else if (token & QTD_STS_MMF) {
+ 			/* fs/ls interrupt xfer missed the complete-split */
+-			urb->status = -EPROTO;
++			status = -EPROTO;
+ 		} else if (token & QTD_STS_DBE) {
+-			urb->status = (QTD_PID (token) == 1) /* IN ? */
++			status = (QTD_PID (token) == 1) /* IN ? */
+ 				? -ENOSR  /* hc couldn't read data */
+ 				: -ECOMM; /* hc couldn't write data */
+ 		} else if (token & QTD_STS_XACT) {
+ 			/* timeout, bad crc, wrong PID, etc; retried */
+ 			if (QTD_CERR (token))
+-				urb->status = -EPIPE;
++				status = -EPIPE;
+ 			else {
+ 				ehci_dbg (ehci, "devpath %s ep%d%s 3strikes\n",
+ 					urb->dev->devpath,
+ 					usb_pipeendpoint (urb->pipe),
+ 					usb_pipein (urb->pipe) ? "in" : "out");
+-				urb->status = -EPROTO;
++				status = -EPROTO;
+ 			}
+ 		/* CERR nonzero + no errors + halt --> stall */
+ 		} else if (QTD_CERR (token))
+-			urb->status = -EPIPE;
++			status = -EPIPE;
+ 		else	/* unknown */
+-			urb->status = -EPROTO;
++			status = -EPROTO;
+ 
+ 		ehci_vdbg (ehci,
+ 			"dev%d ep%d%s qtd token %08x --> status %d\n",
+ 			usb_pipedevice (urb->pipe),
+ 			usb_pipeendpoint (urb->pipe),
+ 			usb_pipein (urb->pipe) ? "in" : "out",
+-			token, urb->status);
++			token, status);
+ 
+ 		/* if async CSPLIT failed, try cleaning out the TT buffer */
+-		if (urb->status != -EPIPE
++		if (status != -EPIPE
+ 				&& urb->dev->tt && !usb_pipeint (urb->pipe)
+ 				&& ((token & QTD_STS_MMF) != 0
+ 					|| QTD_CERR(token) == 0)
+@@ -212,10 +214,12 @@ static void qtd_copy_status (
+ 			usb_hub_tt_clear_buffer (urb->dev, urb->pipe);
+ 		}
+ 	}
++
++	return status;
+ }
+ 
+ static void
+-ehci_urb_done (struct ehci_hcd *ehci, struct urb *urb)
++ehci_urb_done(struct ehci_hcd *ehci, struct urb *urb, int status)
+ __releases(ehci->lock)
+ __acquires(ehci->lock)
+ {
+@@ -231,17 +235,13 @@ __acquires(ehci->lock)
+ 		qh_put (qh);
+ 	}
+ 
+-	spin_lock (&urb->lock);
+ 	if (unlikely(urb->unlinked)) {
+ 		COUNT(ehci->stats.unlink);
+ 	} else {
+-		if (likely(urb->status == -EINPROGRESS ||
+-				(urb->status == -EREMOTEIO &&
+-				 !(urb->transfer_flags & URB_SHORT_NOT_OK))))
+-			urb->status = 0;
++		if (likely(status == -EINPROGRESS))
++			status = 0;
+ 		COUNT(ehci->stats.complete);
+ 	}
+-	spin_unlock (&urb->lock);
+ 
+ #ifdef EHCI_URB_TRACE
+ 	ehci_dbg (ehci,
+@@ -249,13 +249,14 @@ __acquires(ehci->lock)
+ 		__FUNCTION__, urb->dev->devpath, urb,
+ 		usb_pipeendpoint (urb->pipe),
+ 		usb_pipein (urb->pipe) ? "in" : "out",
+-		urb->status,
++		status,
+ 		urb->actual_length, urb->transfer_buffer_length);
+ #endif
+ 
+ 	/* complete() can reenter this HCD */
+ 	usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
+ 	spin_unlock (&ehci->lock);
++	urb->status = status;
+ 	usb_hcd_giveback_urb (ehci_to_hcd(ehci), urb);
+ 	spin_lock (&ehci->lock);
+ }
+@@ -276,6 +277,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ {
+ 	struct ehci_qtd		*last = NULL, *end = qh->dummy;
+ 	struct list_head	*entry, *tmp;
++	int			last_status = -EINPROGRESS;
+ 	int			stopped;
+ 	unsigned		count = 0;
+ 	int			do_status = 0;
+@@ -304,6 +306,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		struct ehci_qtd	*qtd;
+ 		struct urb	*urb;
+ 		u32		token = 0;
++		int		qtd_status;
+ 
+ 		qtd = list_entry (entry, struct ehci_qtd, qtd_list);
+ 		urb = qtd->urb;
+@@ -311,11 +314,12 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		/* clean up any state from previous QTD ...*/
+ 		if (last) {
+ 			if (likely (last->urb != urb)) {
+-				ehci_urb_done (ehci, last->urb);
++				ehci_urb_done(ehci, last->urb, last_status);
+ 				count++;
+ 			}
+ 			ehci_qtd_free (ehci, last);
+ 			last = NULL;
++			last_status = -EINPROGRESS;
+ 		}
+ 
+ 		/* ignore urbs submitted during completions we reported */
+@@ -351,13 +355,13 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 			stopped = 1;
+ 
+ 			if (unlikely (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)))
+-				urb->status = -ESHUTDOWN;
++				last_status = -ESHUTDOWN;
+ 
+ 			/* ignore active urbs unless some previous qtd
+ 			 * for the urb faulted (including short read) or
+ 			 * its urb was canceled.  we may patch qh or qtds.
+ 			 */
+-			if (likely(urb->status == -EINPROGRESS &&
++			if (likely(last_status == -EINPROGRESS &&
+ 					!urb->unlinked))
+ 				continue;
+ 
+@@ -386,14 +390,14 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		}
+ 
+ 		/* remove it from the queue */
+-		spin_lock (&urb->lock);
+-		qtd_copy_status (ehci, urb, qtd->length, token);
+-		if (unlikely(urb->status == -EREMOTEIO)) {
++		qtd_status = qtd_copy_status(ehci, urb, qtd->length, token);
++		if (unlikely(qtd_status == -EREMOTEIO)) {
+ 			do_status = (!urb->unlinked &&
+ 					usb_pipecontrol(urb->pipe));
+-			urb->status = 0;
++			qtd_status = 0;
+ 		}
+-		spin_unlock (&urb->lock);
++		if (likely(last_status == -EINPROGRESS))
++			last_status = qtd_status;
+ 
+ 		if (stopped && qtd->qtd_list.prev != &qh->qtd_list) {
+ 			last = list_entry (qtd->qtd_list.prev,
+@@ -406,7 +410,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 
+ 	/* last urb's completion might still need calling */
+ 	if (likely (last != NULL)) {
+-		ehci_urb_done (ehci, last->urb);
++		ehci_urb_done(ehci, last->urb, last_status);
+ 		count++;
+ 		ehci_qtd_free (ehci, last);
+ 	}
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 8b267b3fd2bb..80d99bce2b38 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1627,7 +1627,7 @@ itd_complete (
+ 
+ 	/* give urb back to the driver ... can be out-of-order */
+ 	dev = urb->dev;
+-	ehci_urb_done (ehci, urb);
++	ehci_urb_done(ehci, urb, 0);
+ 	urb = NULL;
+ 
+ 	/* defer stopping schedule; completion can submit */
+@@ -2000,7 +2000,7 @@ sitd_complete (
+ 
+ 	/* give urb back to the driver */
+ 	dev = urb->dev;
+-	ehci_urb_done (ehci, urb);
++	ehci_urb_done(ehci, urb, 0);
+ 	urb = NULL;
+ 
+ 	/* defer stopping schedule; completion can submit */

commit 4d2f110c51eec853c50f68cf068888a77551c8d3
+Author: Alan Stern 
+Date:   Fri Aug 24 15:40:10 2007 -0400
+
+    USB: reorganize urb->status use in dummy-hcd
+    
+    This patch (as973) reorganizes the way dummy-hcd sets urb->status.  It
+    now keeps the information in a local variable until the last moment.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index f2b124cf3206..c1af7bab26f0 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -1026,16 +1026,10 @@ static int dummy_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ 	return rc;
+ }
+ 
+-static void maybe_set_status (struct urb *urb, int status)
+-{
+-	spin_lock (&urb->lock);
+-	urb->status = status;
+-	spin_unlock (&urb->lock);
+-}
+-
+ /* transfer up to a frame's worth; caller must own lock */
+ static int
+-transfer (struct dummy *dum, struct urb *urb, struct dummy_ep *ep, int limit)
++transfer(struct dummy *dum, struct urb *urb, struct dummy_ep *ep, int limit,
++		int *status)
+ {
+ 	struct dummy_request	*req;
+ 
+@@ -1103,15 +1097,15 @@ transfer (struct dummy *dum, struct urb *urb, struct dummy_ep *ep, int limit)
+ 		if (is_short) {
+ 			if (host_len == dev_len) {
+ 				req->req.status = 0;
+-				maybe_set_status (urb, 0);
++				*status = 0;
+ 			} else if (to_host) {
+ 				req->req.status = 0;
+ 				if (dev_len > host_len)
+-					maybe_set_status (urb, -EOVERFLOW);
++					*status = -EOVERFLOW;
+ 				else
+-					maybe_set_status (urb, 0);
++					*status = 0;
+ 			} else if (!to_host) {
+-				maybe_set_status (urb, 0);
++				*status = 0;
+ 				if (host_len > dev_len)
+ 					req->req.status = -EOVERFLOW;
+ 				else
+@@ -1125,9 +1119,8 @@ transfer (struct dummy *dum, struct urb *urb, struct dummy_ep *ep, int limit)
+ 				req->req.status = 0;
+ 			if (urb->transfer_buffer_length == urb->actual_length
+ 					&& !(urb->transfer_flags
+-						& URB_ZERO_PACKET)) {
+-				maybe_set_status (urb, 0);
+-			}
++						& URB_ZERO_PACKET))
++				*status = 0;
+ 		}
+ 
+ 		/* device side completion --> continuable */
+@@ -1143,7 +1136,7 @@ transfer (struct dummy *dum, struct urb *urb, struct dummy_ep *ep, int limit)
+ 		}
+ 
+ 		/* host side completion --> terminate */
+-		if (urb->status != -EINPROGRESS)
++		if (*status != -EINPROGRESS)
+ 			break;
+ 
+ 		/* rescan to continue with any other queued i/o */
+@@ -1254,6 +1247,7 @@ static void dummy_timer (unsigned long _dum)
+ 		u8			address;
+ 		struct dummy_ep		*ep = NULL;
+ 		int			type;
++		int			status = -EINPROGRESS;
+ 
+ 		urb = urbp->urb;
+ 		if (urb->unlinked)
+@@ -1279,7 +1273,7 @@ static void dummy_timer (unsigned long _dum)
+ 			dev_dbg (dummy_dev(dum),
+ 				"no ep configured for urb %p\n",
+ 				urb);
+-			maybe_set_status (urb, -EPROTO);
++			status = -EPROTO;
+ 			goto return_urb;
+ 		}
+ 
+@@ -1294,7 +1288,7 @@ static void dummy_timer (unsigned long _dum)
+ 			/* NOTE: must not be iso! */
+ 			dev_dbg (dummy_dev(dum), "ep %s halted, urb %p\n",
+ 					ep->ep.name, urb);
+-			maybe_set_status (urb, -EPIPE);
++			status = -EPIPE;
+ 			goto return_urb;
+ 		}
+ 		/* FIXME make sure both ends agree on maxpacket */
+@@ -1312,7 +1306,7 @@ static void dummy_timer (unsigned long _dum)
+ 			w_value = le16_to_cpu(setup.wValue);
+ 			if (le16_to_cpu(setup.wLength) !=
+ 					urb->transfer_buffer_length) {
+-				maybe_set_status (urb, -EOVERFLOW);
++				status = -EOVERFLOW;
+ 				goto return_urb;
+ 			}
+ 
+@@ -1342,7 +1336,7 @@ static void dummy_timer (unsigned long _dum)
+ 				if (setup.bRequestType != Dev_Request)
+ 					break;
+ 				dum->address = w_value;
+-				maybe_set_status (urb, 0);
++				status = 0;
+ 				dev_dbg (udc_dev(dum), "set_address = %d\n",
+ 						w_value);
+ 				value = 0;
+@@ -1369,7 +1363,7 @@ static void dummy_timer (unsigned long _dum)
+ 					if (value == 0) {
+ 						dum->devstatus |=
+ 							(1 << w_value);
+-						maybe_set_status (urb, 0);
++						status = 0;
+ 					}
+ 
+ 				} else if (setup.bRequestType == Ep_Request) {
+@@ -1381,7 +1375,7 @@ static void dummy_timer (unsigned long _dum)
+ 					}
+ 					ep2->halted = 1;
+ 					value = 0;
+-					maybe_set_status (urb, 0);
++					status = 0;
+ 				}
+ 				break;
+ 			case USB_REQ_CLEAR_FEATURE:
+@@ -1391,7 +1385,7 @@ static void dummy_timer (unsigned long _dum)
+ 						dum->devstatus &= ~(1 <<
+ 							USB_DEVICE_REMOTE_WAKEUP);
+ 						value = 0;
+-						maybe_set_status (urb, 0);
++						status = 0;
+ 						break;
+ 					default:
+ 						value = -EOPNOTSUPP;
+@@ -1406,7 +1400,7 @@ static void dummy_timer (unsigned long _dum)
+ 					}
+ 					ep2->halted = 0;
+ 					value = 0;
+-					maybe_set_status (urb, 0);
++					status = 0;
+ 				}
+ 				break;
+ 			case USB_REQ_GET_STATUS:
+@@ -1443,7 +1437,7 @@ static void dummy_timer (unsigned long _dum)
+ 					urb->actual_length = min (2,
+ 						urb->transfer_buffer_length);
+ 					value = 0;
+-					maybe_set_status (urb, 0);
++					status = 0;
+ 				}
+ 				break;
+ 			}
+@@ -1470,7 +1464,7 @@ static void dummy_timer (unsigned long _dum)
+ 					dev_dbg (udc_dev(dum),
+ 						"setup --> %d\n",
+ 						value);
+-				maybe_set_status (urb, -EPIPE);
++				status = -EPIPE;
+ 				urb->actual_length = 0;
+ 			}
+ 
+@@ -1487,7 +1481,7 @@ static void dummy_timer (unsigned long _dum)
+ 			 * report random errors, to debug drivers.
+ 			 */
+ 			limit = max (limit, periodic_bytes (dum, ep));
+-			maybe_set_status (urb, -ENOSYS);
++			status = -ENOSYS;
+ 			break;
+ 
+ 		case PIPE_INTERRUPT:
+@@ -1501,12 +1495,12 @@ static void dummy_timer (unsigned long _dum)
+ 		default:
+ 		treat_control_like_bulk:
+ 			ep->last_io = jiffies;
+-			total = transfer (dum, urb, ep, limit);
++			total = transfer(dum, urb, ep, limit, &status);
+ 			break;
+ 		}
+ 
+ 		/* incomplete transfer? */
+-		if (urb->status == -EINPROGRESS)
++		if (status == -EINPROGRESS)
+ 			continue;
+ 
+ return_urb:
+@@ -1517,6 +1511,7 @@ static void dummy_timer (unsigned long _dum)
+ 
+ 		usb_hcd_unlink_urb_from_ep(dummy_to_hcd(dum), urb);
+ 		spin_unlock (&dum->lock);
++		urb->status = status;
+ 		usb_hcd_giveback_urb (dummy_to_hcd(dum), urb);
+ 		spin_lock (&dum->lock);
+ 

commit 12943f097e5a4a0550f52f98ab8f476435e2ce15
+Author: Alan Stern 
+Date:   Fri Aug 24 16:27:50 2007 -0400
+
+    USB: less-restrictive command checking in g-file-storage
+    
+    This patch (as983) makes a test for minimum-length command sizes in
+    g_file_storage less restrictive.  It doesn't matter because commands
+    with bad lengths will be detected later on anyway, and doing it like
+    this makes the driver interoperable with certain buggy hosts such as
+    the JVC HiFi (reported by Samuel Hangouet).
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index 9998cd7af418..0551140010ee 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -2964,7 +2964,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
+ 
+ 	/* Is the CBW meaningful? */
+ 	if (cbw->Lun >= MAX_LUNS || cbw->Flags & ~USB_BULK_IN_FLAG ||
+-			cbw->Length < 6 || cbw->Length > MAX_COMMAND_SIZE) {
++			cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) {
+ 		DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, "
+ 				"cmdlen %u\n",
+ 				cbw->Lun, cbw->Flags, cbw->Length);

commit 6e8fe43b26085a64327d1cbb751ab895f3ad3f5d
+Author: Alan Stern 
+Date:   Wed Aug 22 13:08:40 2007 -0400
+
+    USB: avoid the donelist after an error in ohci-hcd
+    
+    This patch (as972) changes ohci-hcd so that after an error occurs, the
+    remaining TDs for the URB will be skipped over entirely instead of
+    going through the donelist.  This enables the driver to give back the
+    URB as soon as the error is detected, avoiding the need to store the
+    error status in urb->status.
+    
+    Signed-off-by: Alan Stern 
+    CC: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
+index 3c793fad178d..860e55ff67a1 100644
+--- a/drivers/usb/host/ohci-q.c
++++ b/drivers/usb/host/ohci-q.c
+@@ -783,10 +783,10 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-static inline struct td *
+-ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev)
++static void ed_halted(struct ohci_hcd *ohci, struct td *td, int cc)
+ {
+ 	struct urb		*urb = td->urb;
++	urb_priv_t		*urb_priv = urb->hcpriv;
+ 	struct ed		*ed = td->ed;
+ 	struct list_head	*tmp = td->td_list.next;
+ 	__hc32			toggle = ed->hwHeadP & cpu_to_hc32 (ohci, ED_C);
+@@ -798,13 +798,12 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev)
+ 	wmb ();
+ 	ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_H);
+ 
+-	/* put any later tds from this urb onto the donelist, after 'td',
+-	 * order won't matter here: no errors, and nothing was transferred.
+-	 * also patch the ed so it looks as if those tds completed normally.
++	/* Get rid of all later tds from this urb.  We don't have
++	 * to be careful: no errors and nothing was transferred.
++	 * Also patch the ed so it looks as if those tds completed normally.
+ 	 */
+ 	while (tmp != &ed->td_list) {
+ 		struct td	*next;
+-		__hc32		info;
+ 
+ 		next = list_entry (tmp, struct td, td_list);
+ 		tmp = next->td_list.next;
+@@ -819,14 +818,9 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev)
+ 		 * then we need to leave the control STATUS packet queued
+ 		 * and clear ED_SKIP.
+ 		 */
+-		info = next->hwINFO;
+-		info |= cpu_to_hc32 (ohci, TD_DONE);
+-		info &= ~cpu_to_hc32 (ohci, TD_CC);
+-		next->hwINFO = info;
+-
+-		next->next_dl_td = rev;
+-		rev = next;
+ 
++		list_del(&next->td_list);
++		urb_priv->td_cnt++;
+ 		ed->hwHeadP = next->hwNextTD | toggle;
+ 	}
+ 
+@@ -852,8 +846,6 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev)
+ 			hc32_to_cpu (ohci, td->hwINFO),
+ 			cc, cc_to_error [cc]);
+ 	}
+-
+-	return rev;
+ }
+ 
+ /* replies to the request have to be on a FIFO basis so
+@@ -890,7 +882,7 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
+ 		 */
+ 		if (cc != TD_CC_NOERROR
+ 				&& (td->ed->hwHeadP & cpu_to_hc32 (ohci, ED_H)))
+-			td_rev = ed_halted (ohci, td, cc, td_rev);
++			ed_halted(ohci, td, cc);
+ 
+ 		td->next_dl_td = td_rev;
+ 		td_rev = td;

commit 1f5a3d0f34fd5719081c6b8f3dbbcbe328d4da31
+Author: Alan Stern 
+Date:   Wed Aug 22 13:06:53 2007 -0400
+
+    USB: fix mistake in usb_hcd_giveback_urb
+    
+    This patch (as971) fixes a small mistake: The URB's completion status
+    needs to be adjusted before the URB is passed to usmon_urb_complete(),
+    not afterward.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index ec17fc4d2861..8b17babf5c55 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1266,9 +1266,6 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
+  */
+ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
+ {
+-	unmap_urb_for_dma(hcd, urb);
+-	usbmon_urb_complete (&hcd->self, urb);
+-	usb_unanchor_urb(urb);
+ 	urb->hcpriv = NULL;
+ 	if (unlikely(urb->unlinked))
+ 		urb->status = urb->unlinked;
+@@ -1277,6 +1274,10 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
+ 			!urb->status))
+ 		urb->status = -EREMOTEIO;
+ 
++	unmap_urb_for_dma(hcd, urb);
++	usbmon_urb_complete(&hcd->self, urb);
++	usb_unanchor_urb(urb);
++
+ 	/* pass ownership to the completion handler */
+ 	urb->complete (urb);
+ 	atomic_dec (&urb->use_count);

commit eb23105462304fd35571fd0cab1de7aec79a9ec5
+Author: Alan Stern 
+Date:   Tue Aug 21 15:40:36 2007 -0400
+
+    USB: add urb->unlinked field
+    
+    This patch (as970) adds a new urb->unlinked field, which is used to
+    store the status of unlinked URBs since we can't use urb->status for
+    that purpose any more.  To help simplify the HCDs, usbcore will check
+    urb->unlinked before calling the completion handler; if the value is
+    set it will automatically override the status reported by the HCD.
+    
+    Signed-off-by: Alan Stern 
+    CC: David Brownell 
+    CC: Olav Kongas 
+    CC: Yoshihiro Shimoda 
+    CC: Tony Olech 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 22a098b318c0..ec17fc4d2861 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -532,8 +532,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
+ 
+ 	/* any errors get returned through the urb completion */
+ 	spin_lock_irq(&hcd_root_hub_lock);
+-	if (urb->status == -EINPROGRESS)
+-		urb->status = status;
++	urb->status = status;
+ 	usb_hcd_unlink_urb_from_ep(hcd, urb);
+ 
+ 	/* This peculiar use of spinlocks echoes what real HC drivers do.
+@@ -1024,6 +1023,7 @@ int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb)
+ 	switch (hcd->state) {
+ 	case HC_STATE_RUNNING:
+ 	case HC_STATE_RESUMING:
++		urb->unlinked = 0;
+ 		list_add_tail(&urb->urb_list, &urb->ep->urb_list);
+ 		break;
+ 	default:
+@@ -1071,9 +1071,9 @@ int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
+ 	/* Any status except -EINPROGRESS means something already started to
+ 	 * unlink this URB from the hardware.  So there's no more work to do.
+ 	 */
+-	if (urb->status != -EINPROGRESS)
++	if (urb->unlinked)
+ 		return -EBUSY;
+-	urb->status = status;
++	urb->unlinked = status;
+ 
+ 	/* IRQ setup can easily be broken so that USB controllers
+ 	 * never get completion IRQs ... maybe even the ones we need to
+@@ -1259,6 +1259,10 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
+  * (and is done using urb->hcpriv).  It also released all HCD locks;
+  * the device driver won't cause problems if it frees, modifies,
+  * or resubmits this URB.
++ *
++ * If @urb was unlinked, the value of @urb->status will be overridden by
++ * @urb->unlinked.  Erroneous short transfers are detected in case
++ * the HCD hasn't checked for them.
+  */
+ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
+ {
+@@ -1266,7 +1270,9 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
+ 	usbmon_urb_complete (&hcd->self, urb);
+ 	usb_unanchor_urb(urb);
+ 	urb->hcpriv = NULL;
+-	if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) &&
++	if (unlikely(urb->unlinked))
++		urb->status = urb->unlinked;
++	else if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) &&
+ 			urb->actual_length < urb->transfer_buffer_length &&
+ 			!urb->status))
+ 		urb->status = -EREMOTEIO;
+@@ -1305,8 +1311,7 @@ void usb_hcd_endpoint_disable (struct usb_device *udev,
+ 	list_for_each_entry (urb, &ep->urb_list, urb_list) {
+ 		int	is_in;
+ 
+-		/* the urb may already have been unlinked */
+-		if (urb->status != -EINPROGRESS)
++		if (urb->unlinked)
+ 			continue;
+ 		usb_get_urb (urb);
+ 		is_in = usb_urb_dir_in(urb);
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index 0cb032526ca2..f2b124cf3206 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -1029,8 +1029,7 @@ static int dummy_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ static void maybe_set_status (struct urb *urb, int status)
+ {
+ 	spin_lock (&urb->lock);
+-	if (urb->status == -EINPROGRESS)
+-		urb->status = status;
++	urb->status = status;
+ 	spin_unlock (&urb->lock);
+ }
+ 
+@@ -1257,10 +1256,9 @@ static void dummy_timer (unsigned long _dum)
+ 		int			type;
+ 
+ 		urb = urbp->urb;
+-		if (urb->status != -EINPROGRESS) {
+-			/* likely it was just unlinked */
++		if (urb->unlinked)
+ 			goto return_urb;
+-		} else if (dum->rh_state != DUMMY_RH_RUNNING)
++		else if (dum->rh_state != DUMMY_RH_RUNNING)
+ 			continue;
+ 		type = usb_pipetype (urb->pipe);
+ 
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index e80b5c417d74..a8f5408c161d 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -151,7 +151,7 @@ static void qtd_copy_status (
+ 		urb->actual_length += length - QTD_LENGTH (token);
+ 
+ 	/* don't modify error codes */
+-	if (unlikely (urb->status != -EINPROGRESS))
++	if (unlikely(urb->unlinked))
+ 		return;
+ 
+ 	/* force cleanup after short read; not always an error */
+@@ -232,21 +232,14 @@ __acquires(ehci->lock)
+ 	}
+ 
+ 	spin_lock (&urb->lock);
+-	switch (urb->status) {
+-	case -EINPROGRESS:		/* success */
+-		urb->status = 0;
+-	default:			/* fault */
+-		COUNT (ehci->stats.complete);
+-		break;
+-	case -EREMOTEIO:		/* fault or normal */
+-		if (!(urb->transfer_flags & URB_SHORT_NOT_OK))
++	if (unlikely(urb->unlinked)) {
++		COUNT(ehci->stats.unlink);
++	} else {
++		if (likely(urb->status == -EINPROGRESS ||
++				(urb->status == -EREMOTEIO &&
++				 !(urb->transfer_flags & URB_SHORT_NOT_OK))))
+ 			urb->status = 0;
+-		COUNT (ehci->stats.complete);
+-		break;
+-	case -ECONNRESET:		/* canceled */
+-	case -ENOENT:
+-		COUNT (ehci->stats.unlink);
+-		break;
++		COUNT(ehci->stats.complete);
+ 	}
+ 	spin_unlock (&urb->lock);
+ 
+@@ -364,7 +357,8 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 			 * for the urb faulted (including short read) or
+ 			 * its urb was canceled.  we may patch qh or qtds.
+ 			 */
+-			if (likely (urb->status == -EINPROGRESS))
++			if (likely(urb->status == -EINPROGRESS &&
++					!urb->unlinked))
+ 				continue;
+ 
+ 			/* issue status after short control reads */
+@@ -395,7 +389,8 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		spin_lock (&urb->lock);
+ 		qtd_copy_status (ehci, urb, qtd->length, token);
+ 		if (unlikely(urb->status == -EREMOTEIO)) {
+-			do_status = usb_pipecontrol(urb->pipe);
++			do_status = (!urb->unlinked &&
++					usb_pipecontrol(urb->pipe));
+ 			urb->status = 0;
+ 		}
+ 		spin_unlock (&urb->lock);
+diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
+index c2919dbc3f54..35b3507ff401 100644
+--- a/drivers/usb/host/isp116x-hcd.c
++++ b/drivers/usb/host/isp116x-hcd.c
+@@ -455,11 +455,10 @@ static void postproc_atl_queue(struct isp116x *isp116x)
+  done:
+ 		if (status != -EINPROGRESS) {
+ 			spin_lock(&urb->lock);
+-			if (urb->status == -EINPROGRESS)
+-				urb->status = status;
++			urb->status = status;
+ 			spin_unlock(&urb->lock);
+ 		}
+-		if (urb->status != -EINPROGRESS)
++		if (urb->status != -EINPROGRESS || urb->unlinked)
+ 			finish_request(isp116x, ep, urb);
+ 	}
+ }
+diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
+index 8aad6199cdcc..3c793fad178d 100644
+--- a/drivers/usb/host/ohci-q.c
++++ b/drivers/usb/host/ohci-q.c
+@@ -758,8 +758,7 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
+ 			cc = TD_CC_NOERROR;
+ 		if (cc != TD_CC_NOERROR && cc < 0x0E) {
+ 			spin_lock (&urb->lock);
+-			if (urb->status == -EINPROGRESS)
+-				urb->status = cc_to_error [cc];
++			urb->status = cc_to_error[cc];
+ 			spin_unlock (&urb->lock);
+ 		}
+ 
+@@ -972,7 +971,7 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick)
+ 			urb = td->urb;
+ 			urb_priv = td->urb->hcpriv;
+ 
+-			if (urb->status == -EINPROGRESS) {
++			if (!urb->unlinked) {
+ 				prev = &td->hwNextTD;
+ 				continue;
+ 			}
+diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
+index 60248b01ce14..98b9e0547544 100644
+--- a/drivers/usb/host/r8a66597-hcd.c
++++ b/drivers/usb/host/r8a66597-hcd.c
+@@ -1118,7 +1118,7 @@ __releases(r8a66597->lock) __acquires(r8a66597->lock)
+ 	r8a66597->timeout_map &= ~(1 << pipenum);
+ 
+ 	if (likely(td)) {
+-		if (td->set_address && urb->status != 0)
++		if (td->set_address && (urb->status != 0 || urb->unlinked))
+ 			r8a66597->address_map &= ~(1 << urb->setup_packet[2]);
+ 
+ 		pipe_toggle_save(r8a66597, td->pipe, urb);
+@@ -1225,8 +1225,7 @@ static void packet_read(struct r8a66597 *r8a66597, u16 pipenum)
+ 	}
+ 
+ 	if (finish && pipenum != 0) {
+-		if (td->urb->status == -EINPROGRESS)
+-			td->urb->status = status;
++		td->urb->status = status;
+ 		finish_request(r8a66597, td, pipenum, urb);
+ 	}
+ }
+@@ -1308,32 +1307,24 @@ static void check_next_phase(struct r8a66597 *r8a66597)
+ 	switch (td->type) {
+ 	case USB_PID_IN:
+ 	case USB_PID_OUT:
+-		if (urb->status != -EINPROGRESS) {
+-			finish = 1;
+-			break;
+-		}
+ 		if (check_transfer_finish(td, urb))
+ 			td->type = USB_PID_ACK;
+ 		break;
+ 	case USB_PID_SETUP:
+-		if (urb->status != -EINPROGRESS)
+-			finish = 1;
+-		else if (urb->transfer_buffer_length == urb->actual_length) {
++		if (urb->transfer_buffer_length == urb->actual_length)
+ 			td->type = USB_PID_ACK;
+-			urb->status = 0;
+-		} else if (usb_pipeout(urb->pipe))
++		else if (usb_pipeout(urb->pipe))
+ 			td->type = USB_PID_OUT;
+ 		else
+ 			td->type = USB_PID_IN;
+ 		break;
+ 	case USB_PID_ACK:
+ 		finish = 1;
+-		if (urb->status == -EINPROGRESS)
+-			urb->status = 0;
++		urb->status = 0;
+ 		break;
+ 	}
+ 
+-	if (finish)
++	if (finish || urb->unlinked)
+ 		finish_request(r8a66597, td, 0, urb);
+ 	else
+ 		start_transfer(r8a66597, td);
+@@ -1418,8 +1409,7 @@ static void irq_pipe_empty(struct r8a66597 *r8a66597)
+ 			if ((tmp & INBUFM) == 0) {
+ 				disable_irq_empty(r8a66597, pipenum);
+ 				pipe_irq_disable(r8a66597, pipenum);
+-				if (td->urb->status == -EINPROGRESS)
+-					td->urb->status = 0;
++				td->urb->status = 0;
+ 				finish_request(r8a66597, td, pipenum, td->urb);
+ 			}
+ 		}
+diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
+index e90953a9c9fb..f0fa94148d9d 100644
+--- a/drivers/usb/host/sl811-hcd.c
++++ b/drivers/usb/host/sl811-hcd.c
+@@ -436,8 +436,7 @@ static void finish_request(
+ 		ep->nextpid = USB_PID_SETUP;
+ 
+ 	spin_lock(&urb->lock);
+-	if (urb->status == -EINPROGRESS)
+-		urb->status = status;
++	urb->status = status;
+ 	spin_unlock(&urb->lock);
+ 
+ 	usb_hcd_unlink_urb_from_ep(sl811_to_hcd(sl811), urb);
+@@ -598,7 +597,7 @@ done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank)
+ 				bank, status, ep, urbstat);
+ 	}
+ 
+-	if (urb && (urbstat != -EINPROGRESS || urb->status != -EINPROGRESS))
++	if (urb && (urbstat != -EINPROGRESS || urb->unlinked))
+ 		finish_request(sl811, ep, urb, urbstat);
+ }
+ 
+diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
+index 1381275d448f..db800a434b83 100644
+--- a/drivers/usb/host/u132-hcd.c
++++ b/drivers/usb/host/u132-hcd.c
+@@ -645,12 +645,12 @@ static void u132_hcd_interrupt_recv(void *data, struct urb *urb, u8 *buf,
+                 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                 return;
+         } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+-                        "%p status=%d\n", urb, urb->status);
++		dev_err(&u132->platform_dev->dev, "device is being removed "
++				"urb=%p\n", urb);
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                 return;
+-        } else if (urb->status == -EINPROGRESS) {
++	} else if (!urb->unlinked) {
+                 struct u132_ring *ring = endp->ring;
+                 u8 *u = urb->transfer_buffer + urb->actual_length;
+                 u8 *b = buf;
+@@ -716,8 +716,8 @@ static void u132_hcd_interrupt_recv(void *data, struct urb *urb, u8 *buf,
+                         return;
+                 }
+         } else {
+-                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+-                        "s=%d\n", urb, urb->status);
++		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
++				"unlinked=%d\n", urb, urb->unlinked);
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                 return;
+@@ -744,12 +744,12 @@ static void u132_hcd_bulk_output_sent(void *data, struct urb *urb, u8 *buf,
+                 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                 return;
+         } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+-                        "%p status=%d\n", urb, urb->status);
++		dev_err(&u132->platform_dev->dev, "device is being removed "
++				"urb=%p\n", urb);
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                 return;
+-        } else if (urb->status == -EINPROGRESS) {
++	} else if (!urb->unlinked) {
+                 struct u132_ring *ring = endp->ring;
+                 urb->actual_length += len;
+                 endp->toggle_bits = toggle_bits;
+@@ -768,8 +768,8 @@ static void u132_hcd_bulk_output_sent(void *data, struct urb *urb, u8 *buf,
+                         return;
+                 }
+         } else {
+-                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+-                        "s=%d\n", urb, urb->status);
++		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
++				"unlinked=%d\n", urb, urb->unlinked);
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                 return;
+@@ -797,12 +797,12 @@ static void u132_hcd_bulk_input_recv(void *data, struct urb *urb, u8 *buf,
+                 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                 return;
+         } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+-                        "%p status=%d\n", urb, urb->status);
++		dev_err(&u132->platform_dev->dev, "device is being removed "
++				"urb=%p\n", urb);
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                 return;
+-        } else if (urb->status == -EINPROGRESS) {
++	} else if (!urb->unlinked) {
+                 struct u132_ring *ring = endp->ring;
+                 u8 *u = urb->transfer_buffer + urb->actual_length;
+                 u8 *b = buf;
+@@ -871,8 +871,8 @@ static void u132_hcd_bulk_input_recv(void *data, struct urb *urb, u8 *buf,
+                         return;
+                 }
+         } else {
+-                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+-                        "s=%d\n", urb, urb->status);
++		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
++				"unlinked=%d\n", urb, urb->unlinked);
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                 return;
+@@ -898,18 +898,18 @@ static void u132_hcd_configure_empty_sent(void *data, struct urb *urb, u8 *buf,
+                 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                 return;
+         } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+-                        "%p status=%d\n", urb, urb->status);
++		dev_err(&u132->platform_dev->dev, "device is being removed "
++				"urb=%p\n", urb);
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                 return;
+-        } else if (urb->status == -EINPROGRESS) {
++	} else if (!urb->unlinked) {
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, 0);
+                 return;
+         } else {
+-                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+-                        "s=%d\n", urb, urb->status);
++		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
++				"unlinked=%d\n", urb, urb->unlinked);
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                 return;
+@@ -936,12 +936,12 @@ static void u132_hcd_configure_input_recv(void *data, struct urb *urb, u8 *buf,
+                 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                 return;
+         } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+-                        "%p status=%d\n", urb, urb->status);
++		dev_err(&u132->platform_dev->dev, "device is being removed "
++				"urb=%p\n", urb);
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                 return;
+-        } else if (urb->status == -EINPROGRESS) {
++	} else if (!urb->unlinked) {
+                 struct u132_ring *ring = endp->ring;
+                 u8 *u = urb->transfer_buffer;
+                 u8 *b = buf;
+@@ -980,8 +980,8 @@ static void u132_hcd_configure_input_recv(void *data, struct urb *urb, u8 *buf,
+                         return;
+                 }
+         } else {
+-                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+-                        "s=%d\n", urb, urb->status);
++		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
++				"unlinked=%d\n", urb, urb->unlinked);
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                 return;
+@@ -1007,18 +1007,18 @@ static void u132_hcd_configure_empty_recv(void *data, struct urb *urb, u8 *buf,
+                 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                 return;
+         } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+-                        "%p status=%d\n", urb, urb->status);
++		dev_err(&u132->platform_dev->dev, "device is being removed "
++				"urb=%p\n", urb);
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                 return;
+-        } else if (urb->status == -EINPROGRESS) {
++	} else if (!urb->unlinked) {
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, 0);
+                 return;
+         } else {
+-                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+-                        "s=%d\n", urb, urb->status);
++		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
++				"unlinked=%d\n", urb, urb->unlinked);
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                 return;
+@@ -1045,12 +1045,12 @@ static void u132_hcd_configure_setup_sent(void *data, struct urb *urb, u8 *buf,
+                 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                 return;
+         } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+-                        "%p status=%d\n", urb, urb->status);
++		dev_err(&u132->platform_dev->dev, "device is being removed "
++				"urb=%p\n", urb);
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                 return;
+-        } else if (urb->status == -EINPROGRESS) {
++	} else if (!urb->unlinked) {
+                 if (usb_pipein(urb->pipe)) {
+                         int retval;
+                         struct u132_ring *ring = endp->ring;
+@@ -1077,8 +1077,8 @@ static void u132_hcd_configure_setup_sent(void *data, struct urb *urb, u8 *buf,
+                         return;
+                 }
+         } else {
+-                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+-                        "s=%d\n", urb, urb->status);
++		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
++				"unlinked=%d\n", urb, urb->unlinked);
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                 return;
+@@ -1106,20 +1106,20 @@ static void u132_hcd_enumeration_empty_recv(void *data, struct urb *urb,
+                 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                 return;
+         } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+-                        "%p status=%d\n", urb, urb->status);
++		dev_err(&u132->platform_dev->dev, "device is being removed "
++				"urb=%p\n", urb);
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                 return;
+-        } else if (urb->status == -EINPROGRESS) {
++	} else if (!urb->unlinked) {
+                 u132->addr[0].address = 0;
+                 endp->usb_addr = udev->usb_addr;
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, 0);
+                 return;
+         } else {
+-                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+-                        "s=%d\n", urb, urb->status);
++		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
++				"unlinked=%d\n", urb, urb->unlinked);
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                 return;
+@@ -1145,12 +1145,12 @@ static void u132_hcd_enumeration_address_sent(void *data, struct urb *urb,
+                 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                 return;
+         } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+-                        "%p status=%d\n", urb, urb->status);
++		dev_err(&u132->platform_dev->dev, "device is being removed "
++				"urb=%p\n", urb);
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                 return;
+-        } else if (urb->status == -EINPROGRESS) {
++	} else if (!urb->unlinked) {
+                 int retval;
+                 struct u132_ring *ring = endp->ring;
+                 up(&u132->scheduler_lock);
+@@ -1162,8 +1162,8 @@ static void u132_hcd_enumeration_address_sent(void *data, struct urb *urb,
+                         u132_hcd_giveback_urb(u132, endp, urb, retval);
+                 return;
+         } else {
+-                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+-                        "s=%d\n", urb, urb->status);
++		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
++				"unlinked=%d\n", urb, urb->unlinked);
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                 return;
+@@ -1189,18 +1189,18 @@ static void u132_hcd_initial_empty_sent(void *data, struct urb *urb, u8 *buf,
+                 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                 return;
+         } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+-                        "%p status=%d\n", urb, urb->status);
++		dev_err(&u132->platform_dev->dev, "device is being removed "
++				"urb=%p\n", urb);
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                 return;
+-        } else if (urb->status == -EINPROGRESS) {
++	} else if (!urb->unlinked) {
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, 0);
+                 return;
+         } else {
+-                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+-                        "s=%d\n", urb, urb->status);
++		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
++				"unlinked=%d\n", urb, urb->unlinked);
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                 return;
+@@ -1227,12 +1227,12 @@ static void u132_hcd_initial_input_recv(void *data, struct urb *urb, u8 *buf,
+                 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                 return;
+         } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+-                        "%p status=%d\n", urb, urb->status);
++		dev_err(&u132->platform_dev->dev, "device is being removed "
++				"urb=%p\n", urb);
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                 return;
+-        } else if (urb->status == -EINPROGRESS) {
++	} else if (!urb->unlinked) {
+                 int retval;
+                 struct u132_ring *ring = endp->ring;
+                 u8 *u = urb->transfer_buffer;
+@@ -1251,8 +1251,8 @@ static void u132_hcd_initial_input_recv(void *data, struct urb *urb, u8 *buf,
+                         u132_hcd_giveback_urb(u132, endp, urb, retval);
+                 return;
+         } else {
+-                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+-                        "s=%d\n", urb, urb->status);
++		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
++				"unlinked=%d\n", urb, urb->unlinked);
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                 return;
+@@ -1279,12 +1279,12 @@ static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf,
+                 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                 return;
+         } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+-                        "%p status=%d\n", urb, urb->status);
++		dev_err(&u132->platform_dev->dev, "device is being removed "
++				"urb=%p\n", urb);
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                 return;
+-        } else if (urb->status == -EINPROGRESS) {
++	} else if (!urb->unlinked) {
+                 int retval;
+                 struct u132_ring *ring = endp->ring;
+                 up(&u132->scheduler_lock);
+@@ -1296,8 +1296,8 @@ static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf,
+                         u132_hcd_giveback_urb(u132, endp, urb, retval);
+                 return;
+         } else {
+-                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+-                        "s=%d\n", urb, urb->status);
++		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
++				"unlinked=%d\n", urb, urb->unlinked);
+                 up(&u132->scheduler_lock);
+                 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                 return;
+@@ -2279,8 +2279,8 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
+                         , u132->going);
+                 return -ENODEV;
+         } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+-                        "%p status=%d\n", urb, urb->status);
++		dev_err(&u132->platform_dev->dev, "device is being removed "
++				"urb=%p\n", urb);
+                 return -ESHUTDOWN;
+         } else {
+                 u8 usb_addr = usb_pipedevice(urb->pipe);
+diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
+index 1497371583b9..20cc58b97807 100644
+--- a/drivers/usb/host/uhci-debug.c
++++ b/drivers/usb/host/uhci-debug.c
+@@ -120,8 +120,8 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space)
+ 	out += sprintf(out, "%s%s", ptype, (urbp->fsbr ? " FSBR" : ""));
+ 	out += sprintf(out, " Actlen=%d", urbp->urb->actual_length);
+ 
+-	if (urbp->urb->status != -EINPROGRESS)
+-		out += sprintf(out, " Status=%d", urbp->urb->status);
++	if (urbp->urb->unlinked)
++		out += sprintf(out, " Unlinked=%d", urbp->urb->unlinked);
+ 	out += sprintf(out, "\n");
+ 
+ 	i = nactive = ninactive = 0;
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index fbc3af392c26..bab567266559 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -1557,15 +1557,12 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ 			break;
+ 
+ 		spin_lock(&urb->lock);
+-		if (urb->status == -EINPROGRESS)	/* Not dequeued */
+-			urb->status = status;
+-		else
+-			status = ECONNRESET;		/* Not -ECONNRESET */
++		urb->status = status;
+ 		spin_unlock(&urb->lock);
+ 
+ 		/* Dequeued but completed URBs can't be given back unless
+ 		 * the QH is stopped or has finished unlinking. */
+-		if (status == ECONNRESET) {
++		if (urb->unlinked) {
+ 			if (QH_FINISHED_UNLINKING(qh))
+ 				qh->is_stopped = 1;
+ 			else if (!qh->is_stopped)
+@@ -1588,7 +1585,7 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ restart:
+ 	list_for_each_entry(urbp, &qh->queue, node) {
+ 		urb = urbp->urb;
+-		if (urb->status != -EINPROGRESS) {
++		if (urb->unlinked) {
+ 
+ 			/* Fix up the TD links and save the toggles for
+ 			 * non-Isochronous queues.  For Isochronous queues,
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 92d63c6b6fc6..5c7b79088add 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -1245,6 +1245,7 @@ struct urb
+ 	void *hcpriv;			/* private data for host controller */
+ 	atomic_t use_count;		/* concurrent submissions counter */
+ 	u8 reject;			/* submissions will fail */
++	int unlinked;			/* unlink error code */
+ 
+ 	/* public: documented fields in the urb that can be used by drivers */
+ 	struct list_head urb_list;	/* list head for use by the urb's

commit b0d9efba3ec53468984aecef8eeaf079089f2e5a
+Author: Alan Stern 
+Date:   Tue Aug 21 15:39:21 2007 -0400
+
+    USB: centralize -EREMOTEIO handling
+    
+    This patch (as969) continues the ongoing changes to the way HCDs
+    report URB statuses.  The programming interface has been simplified by
+    making usbcore responsible for clearing urb->hcpriv and for setting
+    -EREMOTEIO status when an URB with the URB_SHORT_NOT_OK flag ends up
+    as a short transfer.
+    
+    By moving the work out of the HCDs, this removes a fair amount of
+    repeated code.
+    
+    Signed-off-by: Alan Stern 
+    CC: David Brownell 
+    CC: Olav Kongas 
+    CC: Yoshihiro Shimoda 
+    CC: Tony Olech 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index a853f63b9254..22a098b318c0 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -366,6 +366,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
+ 	spin_unlock_irq(&hcd_root_hub_lock);
+ 	if (status)
+ 		return status;
++	urb->hcpriv = hcd;	/* Indicate it's queued */
+ 
+ 	cmd = (struct usb_ctrlrequest *) urb->setup_packet;
+ 	typeReq  = (cmd->bRequestType << 8) | cmd->bRequest;
+@@ -579,7 +580,6 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
+ 			hcd->poll_pending = 0;
+ 			hcd->status_urb = NULL;
+ 			urb->status = 0;
+-			urb->hcpriv = NULL;
+ 			urb->actual_length = length;
+ 			memcpy(urb->transfer_buffer, buffer, length);
+ 
+@@ -675,7 +675,6 @@ static int usb_rh_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ 			del_timer (&hcd->rh_timer);
+ 		if (urb == hcd->status_urb) {
+ 			hcd->status_urb = NULL;
+-			urb->hcpriv = NULL;
+ 			usb_hcd_unlink_urb_from_ep(hcd, urb);
+ 
+ 			spin_unlock(&hcd_root_hub_lock);
+@@ -1192,6 +1191,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+ 	if (unlikely(status)) {
+ 		usbmon_urb_submit_error(&hcd->self, urb, status);
+ 		unmap_urb_for_dma(hcd, urb);
++		urb->hcpriv = NULL;
+ 		INIT_LIST_HEAD(&urb->urb_list);
+ 		atomic_dec(&urb->use_count);
+ 		if (urb->reject)
+@@ -1265,6 +1265,11 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
+ 	unmap_urb_for_dma(hcd, urb);
+ 	usbmon_urb_complete (&hcd->self, urb);
+ 	usb_unanchor_urb(urb);
++	urb->hcpriv = NULL;
++	if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) &&
++			urb->actual_length < urb->transfer_buffer_length &&
++			!urb->status))
++		urb->status = -EREMOTEIO;
+ 
+ 	/* pass ownership to the completion handler */
+ 	urb->complete (urb);
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index c441d10c087e..0cb032526ca2 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -1099,8 +1099,7 @@ transfer (struct dummy *dum, struct urb *urb, struct dummy_ep *ep, int limit)
+ 		 *
+ 		 * partially filling a buffer optionally blocks queue advances
+ 		 * (so completion handlers can clean up the queue) but we don't
+-		 * need to emulate such data-in-flight.  so we only show part
+-		 * of the URB_SHORT_NOT_OK effect: completion status.
++		 * need to emulate such data-in-flight.
+ 		 */
+ 		if (is_short) {
+ 			if (host_len == dev_len) {
+@@ -1111,10 +1110,7 @@ transfer (struct dummy *dum, struct urb *urb, struct dummy_ep *ep, int limit)
+ 				if (dev_len > host_len)
+ 					maybe_set_status (urb, -EOVERFLOW);
+ 				else
+-					maybe_set_status (urb,
+-						(urb->transfer_flags
+-							& URB_SHORT_NOT_OK)
+-						? -EREMOTEIO : 0);
++					maybe_set_status (urb, 0);
+ 			} else if (!to_host) {
+ 				maybe_set_status (urb, 0);
+ 				if (host_len > dev_len)
+@@ -1516,7 +1512,6 @@ static void dummy_timer (unsigned long _dum)
+ 			continue;
+ 
+ return_urb:
+-		urb->hcpriv = NULL;
+ 		list_del (&urbp->urbp_list);
+ 		kfree (urbp);
+ 		if (ep)
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 1da2de4d34ed..e80b5c417d74 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -232,7 +232,6 @@ __acquires(ehci->lock)
+ 	}
+ 
+ 	spin_lock (&urb->lock);
+-	urb->hcpriv = NULL;
+ 	switch (urb->status) {
+ 	case -EINPROGRESS:		/* success */
+ 		urb->status = 0;
+@@ -395,8 +394,10 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		/* remove it from the queue */
+ 		spin_lock (&urb->lock);
+ 		qtd_copy_status (ehci, urb, qtd->length, token);
+-		do_status = (urb->status == -EREMOTEIO)
+-				&& usb_pipecontrol (urb->pipe);
++		if (unlikely(urb->status == -EREMOTEIO)) {
++			do_status = usb_pipecontrol(urb->pipe);
++			urb->status = 0;
++		}
+ 		spin_unlock (&urb->lock);
+ 
+ 		if (stopped && qtd->qtd_list.prev != &qh->qtd_list) {
+diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
+index f2b5d6281c5d..c2919dbc3f54 100644
+--- a/drivers/usb/host/isp116x-hcd.c
++++ b/drivers/usb/host/isp116x-hcd.c
+@@ -282,7 +282,6 @@ __releases(isp116x->lock) __acquires(isp116x->lock)
+ {
+ 	unsigned i;
+ 
+-	urb->hcpriv = NULL;
+ 	ep->error_count = 0;
+ 
+ 	if (usb_pipecontrol(urb->pipe))
+@@ -446,12 +445,7 @@ static void postproc_atl_queue(struct isp116x *isp116x)
+ 			if (PTD_GET_ACTIVE(ptd)
+ 			    || (cc != TD_CC_NOERROR && cc < 0x0E))
+ 				break;
+-			if ((urb->transfer_flags & URB_SHORT_NOT_OK) &&
+-					urb->actual_length <
+-						urb->transfer_buffer_length)
+-				status = -EREMOTEIO;
+-			else
+-				status = 0;
++			status = 0;
+ 			ep->nextpid = 0;
+ 			break;
+ 		default:
+diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
+index 889c0720743b..8aad6199cdcc 100644
+--- a/drivers/usb/host/ohci-q.c
++++ b/drivers/usb/host/ohci-q.c
+@@ -43,21 +43,10 @@ __acquires(ohci->lock)
+ 	// ASSERT (urb->hcpriv != 0);
+ 
+ 	urb_free_priv (ohci, urb->hcpriv);
+-	urb->hcpriv = NULL;
+ 
+ 	spin_lock (&urb->lock);
+ 	if (likely (urb->status == -EINPROGRESS))
+ 		urb->status = 0;
+-	/* report short control reads right even though the data TD always
+-	 * has TD_R set.  (much simpler, but creates the 1-td limit.)
+-	 */
+-	if (unlikely (urb->transfer_flags & URB_SHORT_NOT_OK)
+-			&& unlikely (usb_pipecontrol (urb->pipe))
+-			&& urb->actual_length < urb->transfer_buffer_length
+-			&& usb_pipein (urb->pipe)
+-			&& urb->status == 0) {
+-		urb->status = -EREMOTEIO;
+-	}
+ 	spin_unlock (&urb->lock);
+ 
+ 	switch (usb_pipetype (urb->pipe)) {
+diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
+index 49cf998c172a..60248b01ce14 100644
+--- a/drivers/usb/host/r8a66597-hcd.c
++++ b/drivers/usb/host/r8a66597-hcd.c
+@@ -783,7 +783,6 @@ static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address)
+ 
+ 		if (urb) {
+ 			urb->status = -ENODEV;
+-			urb->hcpriv = NULL;
+ 			usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597),
+ 					urb);
+ 
+@@ -1134,7 +1133,6 @@ __releases(r8a66597->lock) __acquires(r8a66597->lock)
+ 		if (usb_pipeisoc(urb->pipe))
+ 			urb->start_frame = r8a66597_get_frame(hcd);
+ 
+-		urb->hcpriv = NULL;
+ 		usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), urb);
+ 
+ 		spin_unlock(&r8a66597->lock);
+@@ -1202,9 +1200,6 @@ static void packet_read(struct r8a66597 *r8a66597, u16 pipenum)
+ 		td->zero_packet = 1;
+ 	if (rcv_len < bufsize) {
+ 		td->short_packet = 1;
+-		if (urb->transfer_buffer_length != urb->actual_length &&
+-		    urb->transfer_flags & URB_SHORT_NOT_OK)
+-			status = -EREMOTEIO;
+ 	}
+ 	if (usb_pipeisoc(urb->pipe)) {
+ 		urb->iso_frame_desc[td->iso_cnt].actual_length = size;
+@@ -1214,7 +1209,7 @@ static void packet_read(struct r8a66597 *r8a66597, u16 pipenum)
+ 	}
+ 
+ 	/* check transfer finish */
+-	if (check_transfer_finish(td, urb)) {
++	if (finish || check_transfer_finish(td, urb)) {
+ 		pipe_stop(r8a66597, td->pipe);
+ 		pipe_irq_disable(r8a66597, pipenum);
+ 		finish = 1;
+diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
+index 15a93f946afd..e90953a9c9fb 100644
+--- a/drivers/usb/host/sl811-hcd.c
++++ b/drivers/usb/host/sl811-hcd.c
+@@ -438,7 +438,6 @@ static void finish_request(
+ 	spin_lock(&urb->lock);
+ 	if (urb->status == -EINPROGRESS)
+ 		urb->status = status;
+-	urb->hcpriv = NULL;
+ 	spin_unlock(&urb->lock);
+ 
+ 	usb_hcd_unlink_urb_from_ep(sl811_to_hcd(sl811), urb);
+@@ -545,17 +544,10 @@ done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank)
+ 			sl811_read_buf(sl811, SL811HS_PACKET_BUF(bank == 0),
+ 					buf, len);
+ 			usb_dotoggle(udev, ep->epnum, 0);
+-			if (urb->actual_length == urb->transfer_buffer_length)
++			if (urb->actual_length == urb->transfer_buffer_length
++					|| len < ep->maxpacket)
+ 				urbstat = 0;
+-			else if (len < ep->maxpacket) {
+-				if (urb->transfer_flags & URB_SHORT_NOT_OK)
+-					urbstat = -EREMOTEIO;
+-				else
+-					urbstat = 0;
+-			}
+-			if (usb_pipecontrol(urb->pipe)
+-					&& (urbstat == -EREMOTEIO
+-						|| urbstat == 0)) {
++			if (usb_pipecontrol(urb->pipe) && urbstat == 0) {
+ 
+ 				/* NOTE if the status stage STALLs (why?),
+ 				 * this reports the wrong urb status.
+diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
+index c87660b5edc3..1381275d448f 100644
+--- a/drivers/usb/host/u132-hcd.c
++++ b/drivers/usb/host/u132-hcd.c
+@@ -519,7 +519,6 @@ static void u132_hcd_giveback_urb(struct u132 *u132, struct u132_endp *endp,
+         struct usb_hcd *hcd = u132_to_hcd(u132);
+         urb->error_count = 0;
+         urb->status = status;
+-        urb->hcpriv = NULL;
+         spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+ 	usb_hcd_unlink_urb_from_ep(hcd, urb);
+         endp->queue_next += 1;
+@@ -560,7 +559,6 @@ static void u132_hcd_abandon_urb(struct u132 *u132, struct u132_endp *endp,
+         struct usb_hcd *hcd = u132_to_hcd(u132);
+         urb->error_count = 0;
+         urb->status = status;
+-        urb->hcpriv = NULL;
+         spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+ 	usb_hcd_unlink_urb_from_ep(hcd, urb);
+         endp->queue_next += 1;
+@@ -2430,7 +2428,6 @@ static int dequeue_from_overflow_chain(struct u132 *u132,
+                         list_del(scan);
+                         endp->queue_size -= 1;
+                         urb->error_count = 0;
+-                        urb->hcpriv = NULL;
+                         usb_hcd_giveback_urb(hcd, urb);
+                         return 0;
+                 } else
+@@ -2472,7 +2469,6 @@ static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp,
+                         endp->edset_flush = 1;
+                         u132_endp_queue_work(u132, endp, 0);
+                         spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+-                        urb->hcpriv = NULL;
+                         return 0;
+                 } else {
+                         spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+@@ -2517,7 +2513,6 @@ static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp,
+                                         irqs);
+                                 kfree(urbq);
+                         } urb->error_count = 0;
+-                        urb->hcpriv = NULL;
+                         usb_hcd_giveback_urb(hcd, urb);
+                         return 0;
+                 } else if (list_empty(&endp->urb_more)) {
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 793a04685ef4..fbc3af392c26 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -757,7 +757,6 @@ static void uhci_free_urb_priv(struct uhci_hcd *uhci,
+ 		uhci_free_td(uhci, td);
+ 	}
+ 
+-	urbp->urb->hcpriv = NULL;
+ 	kmem_cache_free(uhci_up_cachep, urbp);
+ }
+ 
+@@ -1494,13 +1493,6 @@ __acquires(uhci->lock)
+ 		 * unlinked first.  Regardless, don't confuse people with a
+ 		 * negative length. */
+ 		urb->actual_length = max(urb->actual_length, 0);
+-
+-		/* Report erroneous short transfers */
+-		if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) &&
+-				urb->actual_length <
+-					urb->transfer_buffer_length &&
+-				urb->status == 0))
+-			urb->status = -EREMOTEIO;
+ 	}
+ 
+ 	/* When giving back the first URB in an Isochronous queue,

commit ee7d1f3f0c32d8abe9627aa73dc62ee5bf2daf7f
+Author: Alan Stern 
+Date:   Tue Aug 21 15:37:50 2007 -0400
+
+    USB: remove Iso status value in uhci-hcd
+    
+    This patch (968) changes the way uhci-hcd reports status for
+    Isochronous URBs.  Until now urb->status has been set to the last
+    detected error code.  But other HCDs don't do this; they leave the
+    status set to 0 and report errors only in the individual iso packet
+    descriptors.  So this patch removes the extra computation and makes
+    uhci-hcd behave like the others.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index 1b3d23406ac4..e46d2b0203cb 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -146,7 +146,6 @@ struct uhci_qh {
+ 	short phase;			/* Between 0 and period-1 */
+ 	short load;			/* Periodic time requirement, in us */
+ 	unsigned int iso_frame;		/* Frame # for iso_packet_desc */
+-	int iso_status;			/* Status for Isochronous URBs */
+ 
+ 	int state;			/* QH_STATE_xxx; see above */
+ 	int type;			/* Queue type (control, bulk, etc) */
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index bff200cb3d2e..793a04685ef4 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -1324,7 +1324,6 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
+ 	if (list_empty(&qh->queue)) {
+ 		qh->iso_packet_desc = &urb->iso_frame_desc[0];
+ 		qh->iso_frame = urb->start_frame;
+-		qh->iso_status = 0;
+ 	}
+ 
+ 	qh->skel = SKEL_ISO;
+@@ -1361,18 +1360,15 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb)
+ 			qh->iso_packet_desc->actual_length = actlength;
+ 			qh->iso_packet_desc->status = status;
+ 		}
+-
+-		if (status) {
++		if (status)
+ 			urb->error_count++;
+-			qh->iso_status = status;
+-		}
+ 
+ 		uhci_remove_td_from_urbp(td);
+ 		uhci_free_td(uhci, td);
+ 		qh->iso_frame += qh->period;
+ 		++qh->iso_packet_desc;
+ 	}
+-	return qh->iso_status;
++	return 0;
+ }
+ 
+ static int uhci_urb_enqueue(struct usb_hcd *hcd,
+@@ -1517,7 +1513,6 @@ __acquires(uhci->lock)
+ 
+ 		qh->iso_packet_desc = &nurb->iso_frame_desc[0];
+ 		qh->iso_frame = nurb->start_frame;
+-		qh->iso_status = 0;
+ 	}
+ 
+ 	/* Take the URB off the QH's queue.  If the queue is now empty,
+@@ -1586,7 +1581,7 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ 		}
+ 
+ 		uhci_giveback_urb(uhci, qh, urb);
+-		if (status < 0 && qh->type != USB_ENDPOINT_XFER_ISOC)
++		if (status < 0)
+ 			break;
+ 	}
+ 

commit dfd1e53777afe1050e3a0a3f0dd063a64242b818
+Author: Alan Stern 
+Date:   Tue Aug 21 15:36:52 2007 -0400
+
+    USB: minor fixes for r8a66597 driver
+    
+    This patch (as967) makes a few relatively minor changes to the
+    r8a66597 driver:
+    
+            finish_request() does nothing but call done(), so merge the
+            two routines.
+    
+            Detect and report -EOVERFLOW errors.
+    
+            Fix the calculation that checks for short packets.
+    
+    Signed-off-by: Alan Stern 
+    CC: Yoshihiro Shimoda 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
+index 94bb229df3bc..49cf998c172a 100644
+--- a/drivers/usb/host/r8a66597-hcd.c
++++ b/drivers/usb/host/r8a66597-hcd.c
+@@ -1109,8 +1109,9 @@ static void set_td_timer(struct r8a66597 *r8a66597, struct r8a66597_td *td)
+ }
+ 
+ /* this function must be called with interrupt disabled */
+-static void done(struct r8a66597 *r8a66597, struct r8a66597_td *td,
+-		 u16 pipenum, struct urb *urb)
++static void finish_request(struct r8a66597 *r8a66597, struct r8a66597_td *td,
++		u16 pipenum, struct urb *urb)
++__releases(r8a66597->lock) __acquires(r8a66597->lock)
+ {
+ 	int restart = 0;
+ 	struct usb_hcd *hcd = r8a66597_to_hcd(r8a66597);
+@@ -1151,14 +1152,6 @@ static void done(struct r8a66597 *r8a66597, struct r8a66597_td *td,
+ 	}
+ }
+ 
+-/* this function must be called with interrupt disabled */
+-static void finish_request(struct r8a66597 *r8a66597, struct r8a66597_td *td,
+-			   u16 pipenum, struct urb *urb)
+-__releases(r8a66597->lock) __acquires(r8a66597->lock)
+-{
+-	done(r8a66597, td, pipenum, urb);
+-}
+-
+ static void packet_read(struct r8a66597 *r8a66597, u16 pipenum)
+ {
+ 	u16 tmp;
+@@ -1167,6 +1160,7 @@ static void packet_read(struct r8a66597 *r8a66597, u16 pipenum)
+ 	struct r8a66597_td *td = r8a66597_get_td(r8a66597, pipenum);
+ 	struct urb *urb;
+ 	int finish = 0;
++	int status = 0;
+ 
+ 	if (unlikely(!td))
+ 		return;
+@@ -1185,7 +1179,6 @@ static void packet_read(struct r8a66597 *r8a66597, u16 pipenum)
+ 
+ 	/* prepare parameters */
+ 	rcv_len = tmp & DTLN;
+-	bufsize = td->maxpacket;
+ 	if (usb_pipeisoc(urb->pipe)) {
+ 		buf = (u16 *)(urb->transfer_buffer +
+ 				urb->iso_frame_desc[td->iso_cnt].offset);
+@@ -1194,25 +1187,30 @@ static void packet_read(struct r8a66597 *r8a66597, u16 pipenum)
+ 		buf = (void *)urb->transfer_buffer + urb->actual_length;
+ 		urb_len = urb->transfer_buffer_length - urb->actual_length;
+ 	}
+-	if (rcv_len < bufsize)
+-		size = min(rcv_len, urb_len);
+-	else
+-		size = min(bufsize, urb_len);
++	bufsize = min(urb_len, (int) td->maxpacket);
++	if (rcv_len <= bufsize) {
++		size = rcv_len;
++	} else {
++		size = bufsize;
++		status = -EOVERFLOW;
++		finish = 1;
++	}
+ 
+ 	/* update parameters */
+ 	urb->actual_length += size;
+ 	if (rcv_len == 0)
+ 		td->zero_packet = 1;
+-	if ((size % td->maxpacket) > 0) {
++	if (rcv_len < bufsize) {
+ 		td->short_packet = 1;
+ 		if (urb->transfer_buffer_length != urb->actual_length &&
+ 		    urb->transfer_flags & URB_SHORT_NOT_OK)
+-			td->urb->status = -EREMOTEIO;
++			status = -EREMOTEIO;
+ 	}
+ 	if (usb_pipeisoc(urb->pipe)) {
+ 		urb->iso_frame_desc[td->iso_cnt].actual_length = size;
+-		urb->iso_frame_desc[td->iso_cnt].status = 0;
++		urb->iso_frame_desc[td->iso_cnt].status = status;
+ 		td->iso_cnt++;
++		finish = 0;
+ 	}
+ 
+ 	/* check transfer finish */
+@@ -1233,7 +1231,7 @@ static void packet_read(struct r8a66597 *r8a66597, u16 pipenum)
+ 
+ 	if (finish && pipenum != 0) {
+ 		if (td->urb->status == -EINPROGRESS)
+-			td->urb->status = 0;
++			td->urb->status = status;
+ 		finish_request(r8a66597, td, pipenum, urb);
+ 	}
+ }
+@@ -1807,7 +1805,7 @@ static int r8a66597_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
+ 		pipe_stop(r8a66597, td->pipe);
+ 		pipe_irq_disable(r8a66597, td->pipenum);
+ 		disable_irq_empty(r8a66597, td->pipenum);
+-		done(r8a66597, td, td->pipenum, urb);
++		finish_request(r8a66597, td, td->pipenum, urb);
+ 	}
+  done:
+ 	spin_unlock_irqrestore(&r8a66597->lock, flags);
+@@ -1841,7 +1839,7 @@ static void r8a66597_endpoint_disable(struct usb_hcd *hcd,
+ 	td = r8a66597_get_td(r8a66597, pipenum);
+ 	if (td)
+ 		urb = td->urb;
+-	done(r8a66597, td, pipenum, urb);
++	finish_request(r8a66597, td, pipenum, urb);
+ 	kfree(hep->hcpriv);
+ 	hep->hcpriv = NULL;
+ 	spin_unlock_irqrestore(&r8a66597->lock, flags);

commit e39ab592f182cd0be48acc4ad49f93ef4100017c
+Author: Alan Stern 
+Date:   Thu Aug 16 16:17:49 2007 -0400
+
+    USB: remove unnecessary tests in isp116x and sl811
+    
+    This patch (as962) cleans up some code I forgot to remove earlier in
+    the isp116x and sl811 HCDs.  There is no longer any need to check for
+    unlink-during-submit; it can't happen since the endpoint queues are
+    now under the protection of the HCD-private spinlock.
+    
+    Signed-off-by: Alan Stern 
+    CC: David Brownell 
+    CC: Olav Kongas 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
+index d5027dc75a57..f2b5d6281c5d 100644
+--- a/drivers/usb/host/isp116x-hcd.c
++++ b/drivers/usb/host/isp116x-hcd.c
+@@ -815,12 +815,6 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
+ 		}
+ 	}
+ 
+-	/* in case of unlink-during-submit */
+-	if (urb->status != -EINPROGRESS) {
+-		finish_request(isp116x, ep, urb);
+-		ret = 0;
+-		goto fail;
+-	}
+ 	urb->hcpriv = hep;
+ 	start_atl_transfers(isp116x);
+ 
+diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
+index 3d3a63d002c5..15a93f946afd 100644
+--- a/drivers/usb/host/sl811-hcd.c
++++ b/drivers/usb/host/sl811-hcd.c
+@@ -957,17 +957,7 @@ static int sl811h_urb_enqueue(
+ 		sofirq_on(sl811);
+ 	}
+ 
+-	/* in case of unlink-during-submit */
+-	spin_lock(&urb->lock);
+-	if (urb->status != -EINPROGRESS) {
+-		spin_unlock(&urb->lock);
+-		finish_request(sl811, ep, urb, 0);
+-		retval = 0;
+-		goto fail;
+-	}
+ 	urb->hcpriv = hep;
+-	spin_unlock(&urb->lock);
+-
+ 	start_transfer(sl811);
+ 	sl811_write(sl811, SL11H_IRQ_ENABLE, sl811->irq_enable);
+ fail:

commit 79a7d9ee1a2e8b8dc44dd217f07496911850ec0e
+Author: Alan Stern 
+Date:   Wed Aug 8 17:10:11 2007 -0400
+
+    USB: cleanups for g_file_storage
+    
+    This patch (as957) makes some minor cleanups to the g_file_storage
+    driver:
+    
+            Update the copyright date and version string;
+    
+            Uniformize the logging macros for the gadget and the LUNs;
+    
+            Remove "inline" markers -- nowadays we rely on the compiler
+            to decide which routines are best inlined;
+    
+            Use the print_hex_dump() library routines;
+    
+            Remove some unnecessary assignments within conditionals
+            and fix some close-brace indenting levels;
+    
+            Fix some column-80 violations.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index 0019116ee411..9998cd7af418 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -1,7 +1,7 @@
+ /*
+  * file_storage.c -- File-backed USB Storage Gadget, for USB development
+  *
+- * Copyright (C) 2003-2005 Alan Stern
++ * Copyright (C) 2003-2007 Alan Stern
+  * All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+@@ -218,7 +218,7 @@
+ 
+ 
+ /* #define VERBOSE_DEBUG */
+-#undef DUMP_MSGS
++/* #define DUMP_MSGS */
+ 
+ 
+ #include 
+@@ -249,7 +249,7 @@
+ 
+ #define DRIVER_DESC		"File-backed Storage Gadget"
+ #define DRIVER_NAME		"g_file_storage"
+-#define DRIVER_VERSION		"28 November 2005"
++#define DRIVER_VERSION		"7 August 2007"
+ 
+ static const char longname[] = DRIVER_DESC;
+ static const char shortname[] = DRIVER_NAME;
+@@ -275,12 +275,9 @@ MODULE_LICENSE("Dual BSD/GPL");
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-#define yprintk(l,level,fmt,args...) \
+-	dev_printk(level , &(l)->dev , fmt , ## args)
+-
+ #ifdef DEBUG
+ #define LDBG(lun,fmt,args...) \
+-	yprintk(lun , KERN_DEBUG , fmt , ## args)
++	dev_dbg(&(lun)->dev , fmt , ## args)
+ #define MDBG(fmt,args...) \
+ 	printk(KERN_DEBUG DRIVER_NAME ": " fmt , ## args)
+ #else
+@@ -300,11 +297,11 @@ MODULE_LICENSE("Dual BSD/GPL");
+ #endif /* VERBOSE_DEBUG */
+ 
+ #define LERROR(lun,fmt,args...) \
+-	yprintk(lun , KERN_ERR , fmt , ## args)
++	dev_err(&(lun)->dev , fmt , ## args)
+ #define LWARN(lun,fmt,args...) \
+-	yprintk(lun , KERN_WARNING , fmt , ## args)
++	dev_warn(&(lun)->dev , fmt , ## args)
+ #define LINFO(lun,fmt,args...) \
+-	yprintk(lun , KERN_INFO , fmt , ## args)
++	dev_info(&(lun)->dev , fmt , ## args)
+ 
+ #define MINFO(fmt,args...) \
+ 	printk(KERN_INFO DRIVER_NAME ": " fmt , ## args)
+@@ -558,7 +555,7 @@ struct lun {
+ 
+ #define backing_file_is_open(curlun)	((curlun)->filp != NULL)
+ 
+-static inline struct lun *dev_to_lun(struct device *dev)
++static struct lun *dev_to_lun(struct device *dev)
+ {
+ 	return container_of(dev, struct lun, dev);
+ }
+@@ -691,13 +688,13 @@ struct fsg_dev {
+ 
+ typedef void (*fsg_routine_t)(struct fsg_dev *);
+ 
+-static int inline exception_in_progress(struct fsg_dev *fsg)
++static int exception_in_progress(struct fsg_dev *fsg)
+ {
+ 	return (fsg->state > FSG_STATE_IDLE);
+ }
+ 
+ /* Make bulk-out requests be divisible by the maxpacket size */
+-static void inline set_bulk_out_req_length(struct fsg_dev *fsg,
++static void set_bulk_out_req_length(struct fsg_dev *fsg,
+ 		struct fsg_buffhd *bh, unsigned int length)
+ {
+ 	unsigned int	rem;
+@@ -723,50 +720,36 @@ static void	close_all_backing_files(struct fsg_dev *fsg);
+ static void dump_msg(struct fsg_dev *fsg, const char *label,
+ 		const u8 *buf, unsigned int length)
+ {
+-	unsigned int	start, num, i;
+-	char		line[52], *p;
+-
+-	if (length >= 512)
+-		return;
+-	DBG(fsg, "%s, length %u:\n", label, length);
+-
+-	start = 0;
+-	while (length > 0) {
+-		num = min(length, 16u);
+-		p = line;
+-		for (i = 0; i < num; ++i) {
+-			if (i == 8)
+-				*p++ = ' ';
+-			sprintf(p, " %02x", buf[i]);
+-			p += 3;
+-		}
+-		*p = 0;
+-		printk(KERN_DEBUG "%6x: %s\n", start, line);
+-		buf += num;
+-		start += num;
+-		length -= num;
++	if (length < 512) {
++		DBG(fsg, "%s, length %u:\n", label, length);
++		print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET,
++				16, 1, buf, length, 0);
+ 	}
+ }
+ 
+-static void inline dump_cdb(struct fsg_dev *fsg)
++static void dump_cdb(struct fsg_dev *fsg)
+ {}
+ 
+ #else
+ 
+-static void inline dump_msg(struct fsg_dev *fsg, const char *label,
++static void dump_msg(struct fsg_dev *fsg, const char *label,
+ 		const u8 *buf, unsigned int length)
+ {}
+ 
+-static void inline dump_cdb(struct fsg_dev *fsg)
+-{
+-	int	i;
+-	char	cmdbuf[3*MAX_COMMAND_SIZE + 1];
++#ifdef VERBOSE_DEBUG
+ 
+-	for (i = 0; i < fsg->cmnd_size; ++i)
+-		sprintf(cmdbuf + i*3, " %02x", fsg->cmnd[i]);
+-	VDBG(fsg, "SCSI CDB: %s\n", cmdbuf);
++static void dump_cdb(struct fsg_dev *fsg)
++{
++	print_hex_dump(KERN_DEBUG, "SCSI CDB: ", DUMP_PREFIX_NONE,
++			16, 1, fsg->cmnd, fsg->cmnd_size, 0);
+ }
+ 
++#else
++
++static void dump_cdb(struct fsg_dev *fsg)
++{}
++
++#endif /* VERBOSE_DEBUG */
+ #endif /* DUMP_MSGS */
+ 
+ 
+@@ -789,24 +772,24 @@ static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
+ 
+ /* Routines for unaligned data access */
+ 
+-static u16 inline get_be16(u8 *buf)
++static u16 get_be16(u8 *buf)
+ {
+ 	return ((u16) buf[0] << 8) | ((u16) buf[1]);
+ }
+ 
+-static u32 inline get_be32(u8 *buf)
++static u32 get_be32(u8 *buf)
+ {
+ 	return ((u32) buf[0] << 24) | ((u32) buf[1] << 16) |
+ 			((u32) buf[2] << 8) | ((u32) buf[3]);
+ }
+ 
+-static void inline put_be16(u8 *buf, u16 val)
++static void put_be16(u8 *buf, u16 val)
+ {
+ 	buf[0] = val >> 8;
+ 	buf[1] = val;
+ }
+ 
+-static void inline put_be32(u8 *buf, u32 val)
++static void put_be32(u8 *buf, u32 val)
+ {
+ 	buf[0] = val >> 24;
+ 	buf[1] = val >> 16;
+@@ -992,7 +975,7 @@ static const struct usb_descriptor_header *hs_function[] = {
+ #define HS_FUNCTION_PRE_EP_ENTRIES	2
+ 
+ /* Maxpacket and other transfer characteristics vary by speed. */
+-static inline struct usb_endpoint_descriptor *
++static struct usb_endpoint_descriptor *
+ ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs,
+ 		struct usb_endpoint_descriptor *hs)
+ {
+@@ -1616,7 +1599,8 @@ static int do_read(struct fsg_dev *fsg)
+ 		/* Wait for the next buffer to become available */
+ 		bh = fsg->next_buffhd_to_fill;
+ 		while (bh->state != BUF_STATE_EMPTY) {
+-			if ((rc = sleep_thread(fsg)) != 0)
++			rc = sleep_thread(fsg);
++			if (rc)
+ 				return rc;
+ 		}
+ 
+@@ -1855,7 +1839,8 @@ static int do_write(struct fsg_dev *fsg)
+ 		}
+ 
+ 		/* Wait for something to happen */
+-		if ((rc = sleep_thread(fsg)) != 0)
++		rc = sleep_thread(fsg);
++		if (rc)
+ 			return rc;
+ 	}
+ 
+@@ -2339,7 +2324,8 @@ static int pad_with_zeros(struct fsg_dev *fsg)
+ 
+ 		/* Wait for the next buffer to be free */
+ 		while (bh->state != BUF_STATE_EMPTY) {
+-			if ((rc = sleep_thread(fsg)) != 0)
++			rc = sleep_thread(fsg);
++			if (rc)
+ 				return rc;
+ 		}
+ 
+@@ -2399,7 +2385,8 @@ static int throw_away_data(struct fsg_dev *fsg)
+ 		}
+ 
+ 		/* Otherwise wait for something to happen */
+-		if ((rc = sleep_thread(fsg)) != 0)
++		rc = sleep_thread(fsg);
++		if (rc)
+ 			return rc;
+ 	}
+ 	return 0;
+@@ -2521,7 +2508,8 @@ static int send_status(struct fsg_dev *fsg)
+ 	/* Wait for the next buffer to become available */
+ 	bh = fsg->next_buffhd_to_fill;
+ 	while (bh->state != BUF_STATE_EMPTY) {
+-		if ((rc = sleep_thread(fsg)) != 0)
++		rc = sleep_thread(fsg);
++		if (rc)
+ 			return rc;
+ 	}
+ 
+@@ -2741,9 +2729,10 @@ static int do_scsi_command(struct fsg_dev *fsg)
+ 	/* Wait for the next buffer to become available for data or status */
+ 	bh = fsg->next_buffhd_to_drain = fsg->next_buffhd_to_fill;
+ 	while (bh->state != BUF_STATE_EMPTY) {
+-		if ((rc = sleep_thread(fsg)) != 0)
++		rc = sleep_thread(fsg);
++		if (rc)
+ 			return rc;
+-		}
++	}
+ 	fsg->phase_error = 0;
+ 	fsg->short_packet_received = 0;
+ 
+@@ -3015,9 +3004,10 @@ static int get_next_command(struct fsg_dev *fsg)
+ 		/* Wait for the next buffer to become available */
+ 		bh = fsg->next_buffhd_to_fill;
+ 		while (bh->state != BUF_STATE_EMPTY) {
+-			if ((rc = sleep_thread(fsg)) != 0)
++			rc = sleep_thread(fsg);
++			if (rc)
+ 				return rc;
+-			}
++		}
+ 
+ 		/* Queue a request to read a Bulk-only CBW */
+ 		set_bulk_out_req_length(fsg, bh, USB_BULK_CB_WRAP_LEN);
+@@ -3031,9 +3021,10 @@ static int get_next_command(struct fsg_dev *fsg)
+ 
+ 		/* Wait for the CBW to arrive */
+ 		while (bh->state != BUF_STATE_FULL) {
+-			if ((rc = sleep_thread(fsg)) != 0)
++			rc = sleep_thread(fsg);
++			if (rc)
+ 				return rc;
+-			}
++		}
+ 		smp_rmb();
+ 		rc = received_cbw(fsg, bh);
+ 		bh->state = BUF_STATE_EMPTY;
+@@ -3042,9 +3033,10 @@ static int get_next_command(struct fsg_dev *fsg)
+ 
+ 		/* Wait for the next command to arrive */
+ 		while (fsg->cbbuf_cmnd_size == 0) {
+-			if ((rc = sleep_thread(fsg)) != 0)
++			rc = sleep_thread(fsg);
++			if (rc)
+ 				return rc;
+-			}
++		}
+ 
+ 		/* Is the previous status interrupt request still busy?
+ 		 * The host is allowed to skip reading the status,
+@@ -3565,7 +3557,8 @@ static ssize_t show_ro(struct device *dev, struct device_attribute *attr, char *
+ 	return sprintf(buf, "%d\n", curlun->ro);
+ }
+ 
+-static ssize_t show_file(struct device *dev, struct device_attribute *attr, char *buf)
++static ssize_t show_file(struct device *dev, struct device_attribute *attr,
++		char *buf)
+ {
+ 	struct lun	*curlun = dev_to_lun(dev);
+ 	struct fsg_dev	*fsg = dev_get_drvdata(dev);
+@@ -3574,8 +3567,8 @@ static ssize_t show_file(struct device *dev, struct device_attribute *attr, char
+ 
+ 	down_read(&fsg->filesem);
+ 	if (backing_file_is_open(curlun)) {	// Get the complete pathname
+-		p = d_path(curlun->filp->f_path.dentry, curlun->filp->f_path.mnt,
+-				buf, PAGE_SIZE - 1);
++		p = d_path(curlun->filp->f_path.dentry,
++				curlun->filp->f_path.mnt, buf, PAGE_SIZE - 1);
+ 		if (IS_ERR(p))
+ 			rc = PTR_ERR(p);
+ 		else {
+@@ -3593,7 +3586,8 @@ static ssize_t show_file(struct device *dev, struct device_attribute *attr, char
+ }
+ 
+ 
+-static ssize_t store_ro(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++static ssize_t store_ro(struct device *dev, struct device_attribute *attr,
++		const char *buf, size_t count)
+ {
+ 	ssize_t		rc = count;
+ 	struct lun	*curlun = dev_to_lun(dev);
+@@ -3617,7 +3611,8 @@ static ssize_t store_ro(struct device *dev, struct device_attribute *attr, const
+ 	return rc;
+ }
+ 
+-static ssize_t store_file(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++static ssize_t store_file(struct device *dev, struct device_attribute *attr,
++		const char *buf, size_t count)
+ {
+ 	struct lun	*curlun = dev_to_lun(dev);
+ 	struct fsg_dev	*fsg = dev_get_drvdata(dev);

commit d74d4a69dc1cc7ddc0eabb9c9f1e45005e2984eb
+Author: Alan Stern 
+Date:   Wed Aug 8 11:59:18 2007 -0400
+
+    USB: don't touch sysfs stuff when altsetting is unchanged
+    
+    This patch (as955) prevents the interface-related sysfs files and
+    endpoint pseudo-devices from being deleted and recreated when a call
+    to usb_set_interface() specifies the current altsetting.  Since the
+    altsetting doesn't get changed, there's no need to do anything.
+    
+    Furthermore, avoiding changes to the endpoint devices will be
+    necessary in the future.  This code is called from usb_reset_device(),
+    which gets invoked for reset-resume processing, but upcoming changes
+    to the PM and driver cores will make it impossible to register devices
+    while a suspend/resume transition is in progress.  Since we don't need
+    to re-register those endpoint devices anyhow, it's best to skip the
+    whole thing.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index c905b35d4f85..d638375e22e7 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1173,6 +1173,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
+ 	struct usb_host_interface *alt;
+ 	int ret;
+ 	int manual = 0;
++	int changed;
+ 
+ 	if (dev->state == USB_STATE_SUSPENDED)
+ 		return -EHOSTUNREACH;
+@@ -1212,7 +1213,8 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
+ 	 */
+ 
+ 	/* prevent submissions using previous endpoint settings */
+-	if (device_is_registered(&iface->dev))
++	changed = (iface->cur_altsetting != alt);
++	if (changed && device_is_registered(&iface->dev))
+ 		usb_remove_sysfs_intf_files(iface);
+ 	usb_disable_interface(dev, iface);
+ 
+@@ -1249,7 +1251,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
+ 	 * (Likewise, EP0 never "halts" on well designed devices.)
+ 	 */
+ 	usb_enable_interface(dev, iface);
+-	if (device_is_registered(&iface->dev))
++	if (changed && device_is_registered(&iface->dev))
+ 		usb_create_sysfs_intf_files(iface);
+ 
+ 	return 0;

commit e9df41c5c5899259541dc928872cad4d07b82076
+Author: Alan Stern 
+Date:   Wed Aug 8 11:48:02 2007 -0400
+
+    USB: make HCDs responsible for managing endpoint queues
+    
+    This patch (as954) implements a suggestion of David Brownell's.  Now
+    the host controller drivers are responsible for linking and unlinking
+    URBs to/from their endpoint queues.  This eliminates the possiblity of
+    strange situations where usbcore thinks an URB is linked but the HCD
+    thinks it isn't.  It also means HCDs no longer have to check for URBs
+    being dequeued before they were fully enqueued.
+    
+    In addition to the core changes, this requires changing every host
+    controller driver and the root-hub URB handler.  For the most part the
+    required changes are fairly small; drivers have to call
+    usb_hcd_link_urb_to_ep() in their urb_enqueue method,
+    usb_hcd_check_unlink_urb() in their urb_dequeue method, and
+    usb_hcd_unlink_urb_from_ep() before giving URBs back.  A few HCDs make
+    matters more complicated by the way they split up the flow of control.
+    
+    In addition some method interfaces get changed.  The endpoint argument
+    for urb_enqueue is now redundant so it is removed.  The unlink status
+    is required by usb_hcd_check_unlink_urb(), so it has been added to
+    urb_dequeue.
+    
+    Signed-off-by: Alan Stern 
+    CC: David Brownell 
+    CC: Olav Kongas 
+    CC: Tony Olech 
+    CC: Yoshihiro Shimoda 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index a5a46a55376b..a853f63b9254 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -356,11 +356,17 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
+ 	const u8	*bufp = tbuf;
+ 	int		len = 0;
+ 	int		patch_wakeup = 0;
+-	int		status = 0;
++	int		status;
+ 	int		n;
+ 
+ 	might_sleep();
+ 
++	spin_lock_irq(&hcd_root_hub_lock);
++	status = usb_hcd_link_urb_to_ep(hcd, urb);
++	spin_unlock_irq(&hcd_root_hub_lock);
++	if (status)
++		return status;
++
+ 	cmd = (struct usb_ctrlrequest *) urb->setup_packet;
+ 	typeReq  = (cmd->bRequestType << 8) | cmd->bRequest;
+ 	wValue   = le16_to_cpu (cmd->wValue);
+@@ -525,10 +531,9 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
+ 
+ 	/* any errors get returned through the urb completion */
+ 	spin_lock_irq(&hcd_root_hub_lock);
+-	spin_lock(&urb->lock);
+ 	if (urb->status == -EINPROGRESS)
+ 		urb->status = status;
+-	spin_unlock(&urb->lock);
++	usb_hcd_unlink_urb_from_ep(hcd, urb);
+ 
+ 	/* This peculiar use of spinlocks echoes what real HC drivers do.
+ 	 * Avoiding calls to local_irq_disable/enable makes the code
+@@ -571,26 +576,21 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
+ 		spin_lock_irqsave(&hcd_root_hub_lock, flags);
+ 		urb = hcd->status_urb;
+ 		if (urb) {
+-			spin_lock(&urb->lock);
+-			if (urb->status == -EINPROGRESS) {
+-				hcd->poll_pending = 0;
+-				hcd->status_urb = NULL;
+-				urb->status = 0;
+-				urb->hcpriv = NULL;
+-				urb->actual_length = length;
+-				memcpy(urb->transfer_buffer, buffer, length);
+-			} else		/* urb has been unlinked */
+-				length = 0;
+-			spin_unlock(&urb->lock);
++			hcd->poll_pending = 0;
++			hcd->status_urb = NULL;
++			urb->status = 0;
++			urb->hcpriv = NULL;
++			urb->actual_length = length;
++			memcpy(urb->transfer_buffer, buffer, length);
+ 
++			usb_hcd_unlink_urb_from_ep(hcd, urb);
+ 			spin_unlock(&hcd_root_hub_lock);
+ 			usb_hcd_giveback_urb(hcd, urb);
+ 			spin_lock(&hcd_root_hub_lock);
+-		} else
++		} else {
+ 			length = 0;
+-
+-		if (length <= 0)
+ 			hcd->poll_pending = 1;
++		}
+ 		spin_unlock_irqrestore(&hcd_root_hub_lock, flags);
+ 	}
+ 
+@@ -619,24 +619,26 @@ static int rh_queue_status (struct usb_hcd *hcd, struct urb *urb)
+ 	int		len = 1 + (urb->dev->maxchild / 8);
+ 
+ 	spin_lock_irqsave (&hcd_root_hub_lock, flags);
+-	if (urb->status != -EINPROGRESS)	/* already unlinked */
+-		retval = urb->status;
+-	else if (hcd->status_urb || urb->transfer_buffer_length < len) {
++	if (hcd->status_urb || urb->transfer_buffer_length < len) {
+ 		dev_dbg (hcd->self.controller, "not queuing rh status urb\n");
+ 		retval = -EINVAL;
+-	} else {
+-		hcd->status_urb = urb;
+-		urb->hcpriv = hcd;	/* indicate it's queued */
++		goto done;
++	}
+ 
+-		if (!hcd->uses_new_polling)
+-			mod_timer (&hcd->rh_timer,
+-				(jiffies/(HZ/4) + 1) * (HZ/4));
++	retval = usb_hcd_link_urb_to_ep(hcd, urb);
++	if (retval)
++		goto done;
+ 
+-		/* If a status change has already occurred, report it ASAP */
+-		else if (hcd->poll_pending)
+-			mod_timer (&hcd->rh_timer, jiffies);
+-		retval = 0;
+-	}
++	hcd->status_urb = urb;
++	urb->hcpriv = hcd;	/* indicate it's queued */
++	if (!hcd->uses_new_polling)
++		mod_timer(&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4));
++
++	/* If a status change has already occurred, report it ASAP */
++	else if (hcd->poll_pending)
++		mod_timer(&hcd->rh_timer, jiffies);
++	retval = 0;
++ done:
+ 	spin_unlock_irqrestore (&hcd_root_hub_lock, flags);
+ 	return retval;
+ }
+@@ -655,11 +657,16 @@ static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb)
+ /* Unlinks of root-hub control URBs are legal, but they don't do anything
+  * since these URBs always execute synchronously.
+  */
+-static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
++static int usb_rh_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ {
+ 	unsigned long	flags;
++	int		rc;
+ 
+ 	spin_lock_irqsave(&hcd_root_hub_lock, flags);
++	rc = usb_hcd_check_unlink_urb(hcd, urb, status);
++	if (rc)
++		goto done;
++
+ 	if (usb_endpoint_num(&urb->ep->desc) == 0) {	/* Control URB */
+ 		;	/* Do nothing */
+ 
+@@ -669,14 +676,16 @@ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
+ 		if (urb == hcd->status_urb) {
+ 			hcd->status_urb = NULL;
+ 			urb->hcpriv = NULL;
++			usb_hcd_unlink_urb_from_ep(hcd, urb);
+ 
+ 			spin_unlock(&hcd_root_hub_lock);
+ 			usb_hcd_giveback_urb(hcd, urb);
+ 			spin_lock(&hcd_root_hub_lock);
+ 		}
+ 	}
++ done:
+ 	spin_unlock_irqrestore(&hcd_root_hub_lock, flags);
+-	return 0;
++	return rc;
+ }
+ 
+ 
+@@ -977,12 +986,26 @@ EXPORT_SYMBOL (usb_calc_bus_time);
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-static int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb)
++/**
++ * usb_hcd_link_urb_to_ep - add an URB to its endpoint queue
++ * @hcd: host controller to which @urb was submitted
++ * @urb: URB being submitted
++ *
++ * Host controller drivers should call this routine in their enqueue()
++ * method.  The HCD's private spinlock must be held and interrupts must
++ * be disabled.  The actions carried out here are required for URB
++ * submission, as well as for endpoint shutdown and for usb_kill_urb.
++ *
++ * Returns 0 for no error, otherwise a negative error code (in which case
++ * the enqueue() method must fail).  If no error occurs but enqueue() fails
++ * anyway, it must call usb_hcd_unlink_urb_from_ep() before releasing
++ * the private spinlock and returning.
++ */
++int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb)
+ {
+-	unsigned long	flags;
+ 	int		rc = 0;
+ 
+-	spin_lock_irqsave(&hcd_urb_list_lock, flags);
++	spin_lock(&hcd_urb_list_lock);
+ 
+ 	/* Check that the URB isn't being killed */
+ 	if (unlikely(urb->reject)) {
+@@ -1009,48 +1032,48 @@ static int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb)
+ 		goto done;
+ 	}
+  done:
+-	spin_unlock_irqrestore(&hcd_urb_list_lock, flags);
++	spin_unlock(&hcd_urb_list_lock);
+ 	return rc;
+ }
++EXPORT_SYMBOL_GPL(usb_hcd_link_urb_to_ep);
+ 
+-static int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
++/**
++ * usb_hcd_check_unlink_urb - check whether an URB may be unlinked
++ * @hcd: host controller to which @urb was submitted
++ * @urb: URB being checked for unlinkability
++ * @status: error code to store in @urb if the unlink succeeds
++ *
++ * Host controller drivers should call this routine in their dequeue()
++ * method.  The HCD's private spinlock must be held and interrupts must
++ * be disabled.  The actions carried out here are required for making
++ * sure than an unlink is valid.
++ *
++ * Returns 0 for no error, otherwise a negative error code (in which case
++ * the dequeue() method must fail).  The possible error codes are:
++ *
++ *	-EIDRM: @urb was not submitted or has already completed.
++ *		The completion function may not have been called yet.
++ *
++ *	-EBUSY: @urb has already been unlinked.
++ */
++int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
+ 		int status)
+ {
+-	unsigned long		flags;
+ 	struct list_head	*tmp;
+-	int			rc = 0;
+-
+-	/*
+-	 * we contend for urb->status with the hcd core,
+-	 * which changes it while returning the urb.
+-	 *
+-	 * Caller guaranteed that the urb pointer hasn't been freed, and
+-	 * that it was submitted.  But as a rule it can't know whether or
+-	 * not it's already been unlinked ... so we respect the reversed
+-	 * lock sequence needed for the usb_hcd_giveback_urb() code paths
+-	 * (urb lock, then hcd_urb_list_lock) in case some other CPU is now
+-	 * unlinking it.
+-	 */
+-	spin_lock_irqsave(&urb->lock, flags);
+-	spin_lock(&hcd_urb_list_lock);
+ 
+ 	/* insist the urb is still queued */
+ 	list_for_each(tmp, &urb->ep->urb_list) {
+ 		if (tmp == &urb->urb_list)
+ 			break;
+ 	}
+-	if (tmp != &urb->urb_list) {
+-		rc = -EIDRM;
+-		goto done;
+-	}
++	if (tmp != &urb->urb_list)
++		return -EIDRM;
+ 
+ 	/* Any status except -EINPROGRESS means something already started to
+ 	 * unlink this URB from the hardware.  So there's no more work to do.
+ 	 */
+-	if (urb->status != -EINPROGRESS) {
+-		rc = -EBUSY;
+-		goto done;
+-	}
++	if (urb->status != -EINPROGRESS)
++		return -EBUSY;
+ 	urb->status = status;
+ 
+ 	/* IRQ setup can easily be broken so that USB controllers
+@@ -1065,21 +1088,28 @@ static int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
+ 		set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+ 	}
+ 
+- done:
+-	spin_unlock(&hcd_urb_list_lock);
+-	spin_unlock_irqrestore (&urb->lock, flags);
+-	return rc;
++	return 0;
+ }
++EXPORT_SYMBOL_GPL(usb_hcd_check_unlink_urb);
+ 
+-static void usb_hcd_unlink_urb_from_ep(struct usb_hcd *hcd, struct urb *urb)
++/**
++ * usb_hcd_unlink_urb_from_ep - remove an URB from its endpoint queue
++ * @hcd: host controller to which @urb was submitted
++ * @urb: URB being unlinked
++ *
++ * Host controller drivers should call this routine before calling
++ * usb_hcd_giveback_urb().  The HCD's private spinlock must be held and
++ * interrupts must be disabled.  The actions carried out here are required
++ * for URB completion.
++ */
++void usb_hcd_unlink_urb_from_ep(struct usb_hcd *hcd, struct urb *urb)
+ {
+-	unsigned long		flags;
+-
+ 	/* clear all state linking urb to this dev (and hcd) */
+-	spin_lock_irqsave(&hcd_urb_list_lock, flags);
++	spin_lock(&hcd_urb_list_lock);
+ 	list_del_init(&urb->urb_list);
+-	spin_unlock_irqrestore(&hcd_urb_list_lock, flags);
++	spin_unlock(&hcd_urb_list_lock);
+ }
++EXPORT_SYMBOL_GPL(usb_hcd_unlink_urb_from_ep);
+ 
+ static void map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+ {
+@@ -1153,20 +1183,15 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+ 	 * URBs must be submitted in process context with interrupts
+ 	 * enabled.
+ 	 */
+-	status = usb_hcd_link_urb_to_ep(hcd, urb);
+-	if (!status) {
+-		map_urb_for_dma(hcd, urb);
+-		if (is_root_hub(urb->dev))
+-			status = rh_urb_enqueue(hcd, urb);
+-		else
+-			status = hcd->driver->urb_enqueue(hcd, urb->ep, urb,
+-					mem_flags);
+-	}
++	map_urb_for_dma(hcd, urb);
++	if (is_root_hub(urb->dev))
++		status = rh_urb_enqueue(hcd, urb);
++	else
++		status = hcd->driver->urb_enqueue(hcd, urb, mem_flags);
+ 
+ 	if (unlikely(status)) {
+ 		usbmon_urb_submit_error(&hcd->self, urb, status);
+ 		unmap_urb_for_dma(hcd, urb);
+-		usb_hcd_unlink_urb_from_ep(hcd, urb);
+ 		INIT_LIST_HEAD(&urb->urb_list);
+ 		atomic_dec(&urb->use_count);
+ 		if (urb->reject)
+@@ -1183,24 +1208,19 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+  * soon as practical.  we've already set up the urb's return status,
+  * but we can't know if the callback completed already.
+  */
+-static int
+-unlink1 (struct usb_hcd *hcd, struct urb *urb)
++static int unlink1(struct usb_hcd *hcd, struct urb *urb, int status)
+ {
+ 	int		value;
+ 
+ 	if (is_root_hub(urb->dev))
+-		value = usb_rh_urb_dequeue (hcd, urb);
++		value = usb_rh_urb_dequeue(hcd, urb, status);
+ 	else {
+ 
+ 		/* The only reason an HCD might fail this call is if
+ 		 * it has not yet fully queued the urb to begin with.
+ 		 * Such failures should be harmless. */
+-		value = hcd->driver->urb_dequeue (hcd, urb);
++		value = hcd->driver->urb_dequeue(hcd, urb, status);
+ 	}
+-
+-	if (value != 0)
+-		dev_dbg (hcd->self.controller, "dequeue %p --> %d\n",
+-				urb, value);
+ 	return value;
+ }
+ 
+@@ -1216,14 +1236,11 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
+ 	int			retval;
+ 
+ 	hcd = bus_to_hcd(urb->dev->bus);
+-
+-	retval = usb_hcd_check_unlink_urb(hcd, urb, status);
+-	if (!retval)
+-		retval = unlink1(hcd, urb);
++	retval = unlink1(hcd, urb, status);
+ 
+ 	if (retval == 0)
+ 		retval = -EINPROGRESS;
+-	else if (retval != -EIDRM)
++	else if (retval != -EIDRM && retval != -EBUSY)
+ 		dev_dbg(&urb->dev->dev, "hcd_unlink_urb %p fail %d\n",
+ 				urb, retval);
+ 	return retval;
+@@ -1245,7 +1262,6 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
+  */
+ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
+ {
+-	usb_hcd_unlink_urb_from_ep(hcd, urb);
+ 	unmap_urb_for_dma(hcd, urb);
+ 	usbmon_urb_complete (&hcd->self, urb);
+ 	usb_unanchor_urb(urb);
+@@ -1282,7 +1298,6 @@ void usb_hcd_endpoint_disable (struct usb_device *udev,
+ rescan:
+ 	spin_lock_irq(&hcd_urb_list_lock);
+ 	list_for_each_entry (urb, &ep->urb_list, urb_list) {
+-		int	tmp;
+ 		int	is_in;
+ 
+ 		/* the urb may already have been unlinked */
+@@ -1292,34 +1307,26 @@ void usb_hcd_endpoint_disable (struct usb_device *udev,
+ 		is_in = usb_urb_dir_in(urb);
+ 		spin_unlock(&hcd_urb_list_lock);
+ 
+-		spin_lock (&urb->lock);
+-		tmp = urb->status;
+-		if (tmp == -EINPROGRESS)
+-			urb->status = -ESHUTDOWN;
+-		spin_unlock (&urb->lock);
+-
+-		/* kick hcd unless it's already returning this */
+-		if (tmp == -EINPROGRESS) {
+-			unlink1 (hcd, urb);
+-			dev_dbg (hcd->self.controller,
+-				"shutdown urb %p ep%d%s%s\n",
+-				urb, usb_endpoint_num(&ep->desc),
+-				is_in ? "in" : "out",
+-				({	char *s;
+-
+-					switch (usb_endpoint_type(&ep->desc)) {
+-					case USB_ENDPOINT_XFER_CONTROL:
+-						s = ""; break;
+-					case USB_ENDPOINT_XFER_BULK:
+-						s = "-bulk"; break;
+-					case USB_ENDPOINT_XFER_INT:
+-						s = "-intr"; break;
+-					default:
+-				 		s = "-iso"; break;
+-					};
+-					s;
+-				}));
+-		}
++		/* kick hcd */
++		unlink1(hcd, urb, -ESHUTDOWN);
++		dev_dbg (hcd->self.controller,
++			"shutdown urb %p ep%d%s%s\n",
++			urb, usb_endpoint_num(&ep->desc),
++			is_in ? "in" : "out",
++			({	char *s;
++
++				 switch (usb_endpoint_type(&ep->desc)) {
++				 case USB_ENDPOINT_XFER_CONTROL:
++					s = ""; break;
++				 case USB_ENDPOINT_XFER_BULK:
++					s = "-bulk"; break;
++				 case USB_ENDPOINT_XFER_INT:
++					s = "-intr"; break;
++				 default:
++			 		s = "-iso"; break;
++				};
++				s;
++			}));
+ 		usb_put_urb (urb);
+ 
+ 		/* list contents may have changed */
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index 8683142e70e1..745be2566f62 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -189,11 +189,10 @@ struct hc_driver {
+ 	int	(*get_frame_number) (struct usb_hcd *hcd);
+ 
+ 	/* manage i/o requests, device state */
+-	int	(*urb_enqueue) (struct usb_hcd *hcd,
+-					struct usb_host_endpoint *ep,
+-					struct urb *urb,
+-					gfp_t mem_flags);
+-	int	(*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb);
++	int	(*urb_enqueue)(struct usb_hcd *hcd,
++				struct urb *urb, gfp_t mem_flags);
++	int	(*urb_dequeue)(struct usb_hcd *hcd,
++				struct urb *urb, int status);
+ 
+ 	/* hw synch, freeing endpoint resources that urb_dequeue can't */
+ 	void 	(*endpoint_disable)(struct usb_hcd *hcd,
+@@ -211,6 +210,11 @@ struct hc_driver {
+ 		/* Needed only if port-change IRQs are level-triggered */
+ };
+ 
++extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
++extern int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
++		int status);
++extern void usb_hcd_unlink_urb_from_ep(struct usb_hcd *hcd, struct urb *urb);
++
+ extern int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags);
+ extern int usb_hcd_unlink_urb (struct urb *urb, int status);
+ extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb);
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index d008d1360a7a..c441d10c087e 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -962,13 +962,13 @@ static struct platform_driver dummy_udc_driver = {
+ 
+ static int dummy_urb_enqueue (
+ 	struct usb_hcd			*hcd,
+-	struct usb_host_endpoint	*ep,
+ 	struct urb			*urb,
+ 	gfp_t				mem_flags
+ ) {
+ 	struct dummy	*dum;
+ 	struct urbp	*urbp;
+ 	unsigned long	flags;
++	int		rc;
+ 
+ 	if (!urb->transfer_buffer && urb->transfer_buffer_length)
+ 		return -EINVAL;
+@@ -980,6 +980,11 @@ static int dummy_urb_enqueue (
+ 
+ 	dum = hcd_to_dummy (hcd);
+ 	spin_lock_irqsave (&dum->lock, flags);
++	rc = usb_hcd_link_urb_to_ep(hcd, urb);
++	if (rc) {
++		kfree(urbp);
++		goto done;
++	}
+ 
+ 	if (!dum->udev) {
+ 		dum->udev = urb->dev;
+@@ -997,22 +1002,28 @@ static int dummy_urb_enqueue (
+ 		mod_timer (&dum->timer, jiffies + 1);
+ 
+ 	spin_unlock_irqrestore (&dum->lock, flags);
+-	return 0;
++ done:
++	return rc;
+ }
+ 
+-static int dummy_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
++static int dummy_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ {
+ 	struct dummy	*dum;
+ 	unsigned long	flags;
++	int		rc;
+ 
+ 	/* giveback happens automatically in timer callback,
+ 	 * so make sure the callback happens */
+ 	dum = hcd_to_dummy (hcd);
+ 	spin_lock_irqsave (&dum->lock, flags);
+-	if (dum->rh_state != DUMMY_RH_RUNNING && !list_empty(&dum->urbp_list))
++
++	rc = usb_hcd_check_unlink_urb(hcd, urb, status);
++	if (!rc && dum->rh_state != DUMMY_RH_RUNNING &&
++			!list_empty(&dum->urbp_list))
+ 		mod_timer (&dum->timer, jiffies);
++
+ 	spin_unlock_irqrestore (&dum->lock, flags);
+-	return 0;
++	return rc;
+ }
+ 
+ static void maybe_set_status (struct urb *urb, int status)
+@@ -1511,6 +1522,7 @@ static void dummy_timer (unsigned long _dum)
+ 		if (ep)
+ 			ep->already_seen = ep->setup_stage = 0;
+ 
++		usb_hcd_unlink_urb_from_ep(dummy_to_hcd(dum), urb);
+ 		spin_unlock (&dum->lock);
+ 		usb_hcd_giveback_urb (dummy_to_hcd(dum), urb);
+ 		spin_lock (&dum->lock);
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 35cdba10411b..db00492588b6 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -719,7 +719,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+  */
+ static int ehci_urb_enqueue (
+ 	struct usb_hcd	*hcd,
+-	struct usb_host_endpoint *ep,
+ 	struct urb	*urb,
+ 	gfp_t		mem_flags
+ ) {
+@@ -734,12 +733,12 @@ static int ehci_urb_enqueue (
+ 	default:
+ 		if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags))
+ 			return -ENOMEM;
+-		return submit_async (ehci, ep, urb, &qtd_list, mem_flags);
++		return submit_async(ehci, urb, &qtd_list, mem_flags);
+ 
+ 	case PIPE_INTERRUPT:
+ 		if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags))
+ 			return -ENOMEM;
+-		return intr_submit (ehci, ep, urb, &qtd_list, mem_flags);
++		return intr_submit(ehci, urb, &qtd_list, mem_flags);
+ 
+ 	case PIPE_ISOCHRONOUS:
+ 		if (urb->dev->speed == USB_SPEED_HIGH)
+@@ -777,13 +776,18 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+  * completions normally happen asynchronously
+  */
+ 
+-static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
++static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ {
+ 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+ 	struct ehci_qh		*qh;
+ 	unsigned long		flags;
++	int			rc;
+ 
+ 	spin_lock_irqsave (&ehci->lock, flags);
++	rc = usb_hcd_check_unlink_urb(hcd, urb, status);
++	if (rc)
++		goto done;
++
+ 	switch (usb_pipetype (urb->pipe)) {
+ 	// case PIPE_CONTROL:
+ 	// case PIPE_BULK:
+@@ -838,7 +842,7 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
+ 	}
+ done:
+ 	spin_unlock_irqrestore (&ehci->lock, flags);
+-	return 0;
++	return rc;
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 140bfa423e07..1da2de4d34ed 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -262,6 +262,7 @@ __acquires(ehci->lock)
+ #endif
+ 
+ 	/* complete() can reenter this HCD */
++	usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
+ 	spin_unlock (&ehci->lock);
+ 	usb_hcd_giveback_urb (ehci_to_hcd(ehci), urb);
+ 	spin_lock (&ehci->lock);
+@@ -913,7 +914,6 @@ static struct ehci_qh *qh_append_tds (
+ static int
+ submit_async (
+ 	struct ehci_hcd		*ehci,
+-	struct usb_host_endpoint *ep,
+ 	struct urb		*urb,
+ 	struct list_head	*qtd_list,
+ 	gfp_t			mem_flags
+@@ -922,10 +922,10 @@ submit_async (
+ 	int			epnum;
+ 	unsigned long		flags;
+ 	struct ehci_qh		*qh = NULL;
+-	int			rc = 0;
++	int			rc;
+ 
+ 	qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list);
+-	epnum = ep->desc.bEndpointAddress;
++	epnum = urb->ep->desc.bEndpointAddress;
+ 
+ #ifdef EHCI_URB_TRACE
+ 	ehci_dbg (ehci,
+@@ -933,7 +933,7 @@ submit_async (
+ 		__FUNCTION__, urb->dev->devpath, urb,
+ 		epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out",
+ 		urb->transfer_buffer_length,
+-		qtd, ep->hcpriv);
++		qtd, urb->ep->hcpriv);
+ #endif
+ 
+ 	spin_lock_irqsave (&ehci->lock, flags);
+@@ -942,9 +942,13 @@ submit_async (
+ 		rc = -ESHUTDOWN;
+ 		goto done;
+ 	}
++	rc = usb_hcd_link_urb_to_ep(ehci_to_hcd(ehci), urb);
++	if (unlikely(rc))
++		goto done;
+ 
+-	qh = qh_append_tds (ehci, urb, qtd_list, epnum, &ep->hcpriv);
++	qh = qh_append_tds(ehci, urb, qtd_list, epnum, &urb->ep->hcpriv);
+ 	if (unlikely(qh == NULL)) {
++		usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
+ 		rc = -ENOMEM;
+ 		goto done;
+ 	}
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index e682f2342ef8..8b267b3fd2bb 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -797,7 +797,6 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 
+ static int intr_submit (
+ 	struct ehci_hcd		*ehci,
+-	struct usb_host_endpoint *ep,
+ 	struct urb		*urb,
+ 	struct list_head	*qtd_list,
+ 	gfp_t			mem_flags
+@@ -805,23 +804,26 @@ static int intr_submit (
+ 	unsigned		epnum;
+ 	unsigned long		flags;
+ 	struct ehci_qh		*qh;
+-	int			status = 0;
++	int			status;
+ 	struct list_head	empty;
+ 
+ 	/* get endpoint and transfer/schedule data */
+-	epnum = ep->desc.bEndpointAddress;
++	epnum = urb->ep->desc.bEndpointAddress;
+ 
+ 	spin_lock_irqsave (&ehci->lock, flags);
+ 
+ 	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
+ 			&ehci_to_hcd(ehci)->flags))) {
+ 		status = -ESHUTDOWN;
+-		goto done;
++		goto done_not_linked;
+ 	}
++	status = usb_hcd_link_urb_to_ep(ehci_to_hcd(ehci), urb);
++	if (unlikely(status))
++		goto done_not_linked;
+ 
+ 	/* get qh and force any scheduling errors */
+ 	INIT_LIST_HEAD (&empty);
+-	qh = qh_append_tds (ehci, urb, &empty, epnum, &ep->hcpriv);
++	qh = qh_append_tds(ehci, urb, &empty, epnum, &urb->ep->hcpriv);
+ 	if (qh == NULL) {
+ 		status = -ENOMEM;
+ 		goto done;
+@@ -832,13 +834,16 @@ static int intr_submit (
+ 	}
+ 
+ 	/* then queue the urb's tds to the qh */
+-	qh = qh_append_tds (ehci, urb, qtd_list, epnum, &ep->hcpriv);
++	qh = qh_append_tds(ehci, urb, qtd_list, epnum, &urb->ep->hcpriv);
+ 	BUG_ON (qh == NULL);
+ 
+ 	/* ... update usbfs periodic stats */
+ 	ehci_to_hcd(ehci)->self.bandwidth_int_reqs++;
+ 
+ done:
++	if (unlikely(status))
++		usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
++done_not_linked:
+ 	spin_unlock_irqrestore (&ehci->lock, flags);
+ 	if (status)
+ 		qtd_list_free (ehci, urb, qtd_list);
+@@ -1686,12 +1691,19 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb,
+ 	/* schedule ... need to lock */
+ 	spin_lock_irqsave (&ehci->lock, flags);
+ 	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
+-			       &ehci_to_hcd(ehci)->flags)))
++			       &ehci_to_hcd(ehci)->flags))) {
+ 		status = -ESHUTDOWN;
+-	else
+-		status = iso_stream_schedule (ehci, urb, stream);
++		goto done_not_linked;
++	}
++	status = usb_hcd_link_urb_to_ep(ehci_to_hcd(ehci), urb);
++	if (unlikely(status))
++		goto done_not_linked;
++	status = iso_stream_schedule(ehci, urb, stream);
+ 	if (likely (status == 0))
+ 		itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
++	else
++		usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
++done_not_linked:
+ 	spin_unlock_irqrestore (&ehci->lock, flags);
+ 
+ done:
+@@ -2049,12 +2061,19 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
+ 	/* schedule ... need to lock */
+ 	spin_lock_irqsave (&ehci->lock, flags);
+ 	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
+-			       &ehci_to_hcd(ehci)->flags)))
++			       &ehci_to_hcd(ehci)->flags))) {
+ 		status = -ESHUTDOWN;
+-	else
+-		status = iso_stream_schedule (ehci, urb, stream);
++		goto done_not_linked;
++	}
++	status = usb_hcd_link_urb_to_ep(ehci_to_hcd(ehci), urb);
++	if (unlikely(status))
++		goto done_not_linked;
++	status = iso_stream_schedule(ehci, urb, stream);
+ 	if (status == 0)
+ 		sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
++	else
++		usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
++done_not_linked:
+ 	spin_unlock_irqrestore (&ehci->lock, flags);
+ 
+ done:
+diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
+index 5c851a36de72..d5027dc75a57 100644
+--- a/drivers/usb/host/isp116x-hcd.c
++++ b/drivers/usb/host/isp116x-hcd.c
+@@ -290,6 +290,7 @@ __releases(isp116x->lock) __acquires(isp116x->lock)
+ 
+ 	urb_dbg(urb, "Finish");
+ 
++	usb_hcd_unlink_urb_from_ep(isp116x_to_hcd(isp116x), urb);
+ 	spin_unlock(&isp116x->lock);
+ 	usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb);
+ 	spin_lock(&isp116x->lock);
+@@ -673,7 +674,7 @@ static int balance(struct isp116x *isp116x, u16 period, u16 load)
+ /*-----------------------------------------------------------------*/
+ 
+ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
+-			       struct usb_host_endpoint *hep, struct urb *urb,
++			       struct urb *urb,
+ 			       gfp_t mem_flags)
+ {
+ 	struct isp116x *isp116x = hcd_to_isp116x(hcd);
+@@ -682,6 +683,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
+ 	int is_out = !usb_pipein(pipe);
+ 	int type = usb_pipetype(pipe);
+ 	int epnum = usb_pipeendpoint(pipe);
++	struct usb_host_endpoint *hep = urb->ep;
+ 	struct isp116x_ep *ep = NULL;
+ 	unsigned long flags;
+ 	int i;
+@@ -705,7 +707,12 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
+ 	if (!HC_IS_RUNNING(hcd->state)) {
+ 		kfree(ep);
+ 		ret = -ENODEV;
+-		goto fail;
++		goto fail_not_linked;
++	}
++	ret = usb_hcd_link_urb_to_ep(hcd, urb);
++	if (ret) {
++		kfree(ep);
++		goto fail_not_linked;
+ 	}
+ 
+ 	if (hep->hcpriv)
+@@ -818,6 +825,9 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
+ 	start_atl_transfers(isp116x);
+ 
+       fail:
++	if (ret)
++		usb_hcd_unlink_urb_from_ep(hcd, urb);
++      fail_not_linked:
+ 	spin_unlock_irqrestore(&isp116x->lock, flags);
+ 	return ret;
+ }
+@@ -825,20 +835,21 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
+ /*
+    Dequeue URBs.
+ */
+-static int isp116x_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
++static int isp116x_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
++		int status)
+ {
+ 	struct isp116x *isp116x = hcd_to_isp116x(hcd);
+ 	struct usb_host_endpoint *hep;
+ 	struct isp116x_ep *ep, *ep_act;
+ 	unsigned long flags;
++	int rc;
+ 
+ 	spin_lock_irqsave(&isp116x->lock, flags);
++	rc = usb_hcd_check_unlink_urb(hcd, urb, status);
++	if (rc)
++		goto done;
++
+ 	hep = urb->hcpriv;
+-	/* URB already unlinked (or never linked)? */
+-	if (!hep) {
+-		spin_unlock_irqrestore(&isp116x->lock, flags);
+-		return 0;
+-	}
+ 	ep = hep->hcpriv;
+ 	WARN_ON(hep != ep->hep);
+ 
+@@ -856,9 +867,9 @@ static int isp116x_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
+ 
+ 	if (urb)
+ 		finish_request(isp116x, ep, urb);
+-
++ done:
+ 	spin_unlock_irqrestore(&isp116x->lock, flags);
+-	return 0;
++	return rc;
+ }
+ 
+ static void isp116x_endpoint_disable(struct usb_hcd *hcd,
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index d673cb9c36b1..6b06ab69938f 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -117,7 +117,6 @@ MODULE_PARM_DESC (no_handshake, "true (not default) disables BIOS handshake");
+  */
+ static int ohci_urb_enqueue (
+ 	struct usb_hcd	*hcd,
+-	struct usb_host_endpoint *ep,
+ 	struct urb	*urb,
+ 	gfp_t		mem_flags
+ ) {
+@@ -134,7 +133,7 @@ static int ohci_urb_enqueue (
+ #endif
+ 
+ 	/* every endpoint has a ed, locate and maybe (re)initialize it */
+-	if (! (ed = ed_get (ohci, ep, urb->dev, pipe, urb->interval)))
++	if (! (ed = ed_get (ohci, urb->ep, urb->dev, pipe, urb->interval)))
+ 		return -ENOMEM;
+ 
+ 	/* for the private part of the URB we need the number of TDs (size) */
+@@ -199,22 +198,17 @@ static int ohci_urb_enqueue (
+ 		retval = -ENODEV;
+ 		goto fail;
+ 	}
+-
+-	/* in case of unlink-during-submit */
+-	spin_lock (&urb->lock);
+-	if (urb->status != -EINPROGRESS) {
+-		spin_unlock (&urb->lock);
+-		urb->hcpriv = urb_priv;
+-		finish_urb (ohci, urb);
+-		retval = 0;
++	retval = usb_hcd_link_urb_to_ep(hcd, urb);
++	if (retval)
+ 		goto fail;
+-	}
+ 
+ 	/* schedule the ed if needed */
+ 	if (ed->state == ED_IDLE) {
+ 		retval = ed_schedule (ohci, ed);
+-		if (retval < 0)
+-			goto fail0;
++		if (retval < 0) {
++			usb_hcd_unlink_urb_from_ep(hcd, urb);
++			goto fail;
++		}
+ 		if (ed->type == PIPE_ISOCHRONOUS) {
+ 			u16	frame = ohci_frame_no(ohci);
+ 
+@@ -238,8 +232,6 @@ static int ohci_urb_enqueue (
+ 	urb->hcpriv = urb_priv;
+ 	td_submit_urb (ohci, urb);
+ 
+-fail0:
+-	spin_unlock (&urb->lock);
+ fail:
+ 	if (retval)
+ 		urb_free_priv (ohci, urb_priv);
+@@ -253,17 +245,21 @@ static int ohci_urb_enqueue (
+  * asynchronously, and we might be dealing with an urb that's
+  * partially transferred, or an ED with other urbs being unlinked.
+  */
+-static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
++static int ohci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ {
+ 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+ 	unsigned long		flags;
++	int			rc;
+ 
+ #ifdef OHCI_VERBOSE_DEBUG
+ 	urb_print (urb, "UNLINK", 1);
+ #endif
+ 
+ 	spin_lock_irqsave (&ohci->lock, flags);
+-	if (HC_IS_RUNNING(hcd->state)) {
++	rc = usb_hcd_check_unlink_urb(hcd, urb, status);
++	if (rc) {
++		;	/* Do nothing */
++	} else if (HC_IS_RUNNING(hcd->state)) {
+ 		urb_priv_t  *urb_priv;
+ 
+ 		/* Unless an IRQ completed the unlink while it was being
+@@ -284,7 +280,7 @@ static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
+ 			finish_urb (ohci, urb);
+ 	}
+ 	spin_unlock_irqrestore (&ohci->lock, flags);
+-	return 0;
++	return rc;
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
+index 547d39be3eb9..889c0720743b 100644
+--- a/drivers/usb/host/ohci-q.c
++++ b/drivers/usb/host/ohci-q.c
+@@ -74,6 +74,7 @@ __acquires(ohci->lock)
+ #endif
+ 
+ 	/* urb->complete() can reenter this HCD */
++	usb_hcd_unlink_urb_from_ep(ohci_to_hcd(ohci), urb);
+ 	spin_unlock (&ohci->lock);
+ 	usb_hcd_giveback_urb (ohci_to_hcd(ohci), urb);
+ 	spin_lock (&ohci->lock);
+diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
+index 40a1de4c256e..94bb229df3bc 100644
+--- a/drivers/usb/host/r8a66597-hcd.c
++++ b/drivers/usb/host/r8a66597-hcd.c
+@@ -784,6 +784,9 @@ static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address)
+ 		if (urb) {
+ 			urb->status = -ENODEV;
+ 			urb->hcpriv = NULL;
++			usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597),
++					urb);
++
+ 			spin_unlock(&r8a66597->lock);
+ 			usb_hcd_giveback_urb(r8a66597_to_hcd(r8a66597), urb);
+ 			spin_lock(&r8a66597->lock);
+@@ -1131,6 +1134,8 @@ static void done(struct r8a66597 *r8a66597, struct r8a66597_td *td,
+ 			urb->start_frame = r8a66597_get_frame(hcd);
+ 
+ 		urb->hcpriv = NULL;
++		usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), urb);
++
+ 		spin_unlock(&r8a66597->lock);
+ 		usb_hcd_giveback_urb(hcd, urb);
+ 		spin_lock(&r8a66597->lock);
+@@ -1722,21 +1727,25 @@ static struct r8a66597_td *r8a66597_make_td(struct r8a66597 *r8a66597,
+ }
+ 
+ static int r8a66597_urb_enqueue(struct usb_hcd *hcd,
+-				struct usb_host_endpoint *hep,
+ 				struct urb *urb,
+ 				gfp_t mem_flags)
+ {
++	struct usb_host_endpoint *hep = urb->ep;
+ 	struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+ 	struct r8a66597_td *td = NULL;
+-	int ret = 0, request = 0;
++	int ret, request = 0;
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&r8a66597->lock, flags);
+ 	if (!get_urb_to_r8a66597_dev(r8a66597, urb)) {
+ 		ret = -ENODEV;
+-		goto error;
++		goto error_not_linked;
+ 	}
+ 
++	ret = usb_hcd_link_urb_to_ep(hcd, urb);
++	if (ret)
++		goto error_not_linked;
++
+ 	if (!hep->hcpriv) {
+ 		hep->hcpriv = kzalloc(sizeof(struct r8a66597_pipe),
+ 				GFP_ATOMIC);
+@@ -1761,15 +1770,7 @@ static int r8a66597_urb_enqueue(struct usb_hcd *hcd,
+ 	if (list_empty(&r8a66597->pipe_queue[td->pipenum]))
+ 		request = 1;
+ 	list_add_tail(&td->queue, &r8a66597->pipe_queue[td->pipenum]);
+-
+-	spin_lock(&urb->lock);
+-	if (urb->status != -EINPROGRESS) {
+-		spin_unlock(&urb->lock);
+-		ret = -EPIPE;
+-		goto error;
+-	}
+ 	urb->hcpriv = td;
+-	spin_unlock(&urb->lock);
+ 
+ 	if (request) {
+ 		ret = start_transfer(r8a66597, td);
+@@ -1781,17 +1782,26 @@ static int r8a66597_urb_enqueue(struct usb_hcd *hcd,
+ 		set_td_timer(r8a66597, td);
+ 
+ error:
++	if (ret)
++		usb_hcd_unlink_urb_from_ep(hcd, urb);
++error_not_linked:
+ 	spin_unlock_irqrestore(&r8a66597->lock, flags);
+ 	return ret;
+ }
+ 
+-static int r8a66597_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
++static int r8a66597_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
++		int status)
+ {
+ 	struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+ 	struct r8a66597_td *td;
+ 	unsigned long flags;
++	int rc;
+ 
+ 	spin_lock_irqsave(&r8a66597->lock, flags);
++	rc = usb_hcd_check_unlink_urb(hcd, urb, status);
++	if (rc)
++		goto done;
++
+ 	if (urb->hcpriv) {
+ 		td = urb->hcpriv;
+ 		pipe_stop(r8a66597, td->pipe);
+@@ -1799,8 +1809,9 @@ static int r8a66597_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
+ 		disable_irq_empty(r8a66597, td->pipenum);
+ 		done(r8a66597, td, td->pipenum, urb);
+ 	}
++ done:
+ 	spin_unlock_irqrestore(&r8a66597->lock, flags);
+-	return 0;
++	return rc;
+ }
+ 
+ static void r8a66597_endpoint_disable(struct usb_hcd *hcd,
+diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
+index 4cfa3ff2c993..3d3a63d002c5 100644
+--- a/drivers/usb/host/sl811-hcd.c
++++ b/drivers/usb/host/sl811-hcd.c
+@@ -441,6 +441,7 @@ static void finish_request(
+ 	urb->hcpriv = NULL;
+ 	spin_unlock(&urb->lock);
+ 
++	usb_hcd_unlink_urb_from_ep(sl811_to_hcd(sl811), urb);
+ 	spin_unlock(&sl811->lock);
+ 	usb_hcd_giveback_urb(sl811_to_hcd(sl811), urb);
+ 	spin_lock(&sl811->lock);
+@@ -807,7 +808,6 @@ static int balance(struct sl811 *sl811, u16 period, u16 load)
+ 
+ static int sl811h_urb_enqueue(
+ 	struct usb_hcd		*hcd,
+-	struct usb_host_endpoint *hep,
+ 	struct urb		*urb,
+ 	gfp_t			mem_flags
+ ) {
+@@ -820,7 +820,8 @@ static int sl811h_urb_enqueue(
+ 	struct sl811h_ep	*ep = NULL;
+ 	unsigned long		flags;
+ 	int			i;
+-	int			retval = 0;
++	int			retval;
++	struct usb_host_endpoint	*hep = urb->ep;
+ 
+ #ifdef	DISABLE_ISO
+ 	if (type == PIPE_ISOCHRONOUS)
+@@ -838,7 +839,12 @@ static int sl811h_urb_enqueue(
+ 			|| !HC_IS_RUNNING(hcd->state)) {
+ 		retval = -ENODEV;
+ 		kfree(ep);
+-		goto fail;
++		goto fail_not_linked;
++	}
++	retval = usb_hcd_link_urb_to_ep(hcd, urb);
++	if (retval) {
++		kfree(ep);
++		goto fail_not_linked;
+ 	}
+ 
+ 	if (hep->hcpriv) {
+@@ -965,23 +971,27 @@ static int sl811h_urb_enqueue(
+ 	start_transfer(sl811);
+ 	sl811_write(sl811, SL11H_IRQ_ENABLE, sl811->irq_enable);
+ fail:
++	if (retval)
++		usb_hcd_unlink_urb_from_ep(hcd, urb);
++fail_not_linked:
+ 	spin_unlock_irqrestore(&sl811->lock, flags);
+ 	return retval;
+ }
+ 
+-static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
++static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ {
+ 	struct sl811		*sl811 = hcd_to_sl811(hcd);
+ 	struct usb_host_endpoint *hep;
+ 	unsigned long		flags;
+ 	struct sl811h_ep	*ep;
+-	int			retval = 0;
++	int			retval;
+ 
+ 	spin_lock_irqsave(&sl811->lock, flags);
+-	hep = urb->hcpriv;
+-	if (!hep)
++	retval = usb_hcd_check_unlink_urb(hcd, urb, status);
++	if (retval)
+ 		goto fail;
+ 
++	hep = urb->hcpriv;
+ 	ep = hep->hcpriv;
+ 	if (ep) {
+ 		/* finish right away if this urb can't be active ...
+@@ -1029,8 +1039,8 @@ static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
+ 			VDBG("dequeue, urb %p active %s; wait4irq\n", urb,
+ 				(sl811->active_a == ep) ? "A" : "B");
+ 	} else
+-fail:
+ 		retval = -EINVAL;
++ fail:
+ 	spin_unlock_irqrestore(&sl811->lock, flags);
+ 	return retval;
+ }
+diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
+index 598ad098aeeb..c87660b5edc3 100644
+--- a/drivers/usb/host/u132-hcd.c
++++ b/drivers/usb/host/u132-hcd.c
+@@ -521,6 +521,7 @@ static void u132_hcd_giveback_urb(struct u132 *u132, struct u132_endp *endp,
+         urb->status = status;
+         urb->hcpriv = NULL;
+         spin_lock_irqsave(&endp->queue_lock.slock, irqs);
++	usb_hcd_unlink_urb_from_ep(hcd, urb);
+         endp->queue_next += 1;
+         if (ENDP_QUEUE_SIZE > --endp->queue_size) {
+                 endp->active = 0;
+@@ -561,6 +562,7 @@ static void u132_hcd_abandon_urb(struct u132 *u132, struct u132_endp *endp,
+         urb->status = status;
+         urb->hcpriv = NULL;
+         spin_lock_irqsave(&endp->queue_lock.slock, irqs);
++	usb_hcd_unlink_urb_from_ep(hcd, urb);
+         endp->queue_next += 1;
+         if (ENDP_QUEUE_SIZE > --endp->queue_size) {
+                 endp->active = 0;
+@@ -1876,20 +1878,32 @@ static int u132_hcd_reset(struct usb_hcd *hcd)
+ }
+ 
+ static int create_endpoint_and_queue_int(struct u132 *u132,
+-        struct u132_udev *udev, struct usb_host_endpoint *hep, struct urb *urb,
++	struct u132_udev *udev, struct urb *urb,
+         struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
+         gfp_t mem_flags)
+ {
+         struct u132_ring *ring;
+         unsigned long irqs;
+-        u8 endp_number = ++u132->num_endpoints;
+-        struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] =
+-                kmalloc(sizeof(struct u132_endp), mem_flags);
++	int rc;
++	u8 endp_number;
++	struct u132_endp *endp = kmalloc(sizeof(struct u132_endp), mem_flags);
++
+         if (!endp) {
+                 return -ENOMEM;
+         }
++
++	spin_lock_init(&endp->queue_lock.slock);
++	spin_lock_irqsave(&endp->queue_lock.slock, irqs);
++	rc = usb_hcd_link_urb_to_ep(u132_to_hcd(u132), urb);
++	if (rc) {
++		spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++		kfree(endp);
++		return rc;
++	}
++
++	endp_number = ++u132->num_endpoints;
++	urb->ep->hcpriv = u132->endp[endp_number - 1] = endp;
+         INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
+-        spin_lock_init(&endp->queue_lock.slock);
+         INIT_LIST_HEAD(&endp->urb_more);
+         ring = endp->ring = &u132->ring[0];
+         if (ring->curr_endp) {
+@@ -1905,7 +1919,7 @@ static int create_endpoint_and_queue_int(struct u132 *u132,
+         endp->delayed = 0;
+         endp->endp_number = endp_number;
+         endp->u132 = u132;
+-        endp->hep = hep;
++	endp->hep = urb->ep;
+         endp->pipetype = usb_pipetype(urb->pipe);
+         u132_endp_init_kref(u132, endp);
+         if (usb_pipein(urb->pipe)) {
+@@ -1924,7 +1938,6 @@ static int create_endpoint_and_queue_int(struct u132 *u132,
+                 u132_udev_get_kref(u132, udev);
+         }
+         urb->hcpriv = u132;
+-        spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+         endp->delayed = 1;
+         endp->jiffies = jiffies + msecs_to_jiffies(urb->interval);
+         endp->udev_number = address;
+@@ -1939,8 +1952,8 @@ static int create_endpoint_and_queue_int(struct u132 *u132,
+         return 0;
+ }
+ 
+-static int queue_int_on_old_endpoint(struct u132 *u132, struct u132_udev *udev,
+-        struct usb_host_endpoint *hep, struct urb *urb,
++static int queue_int_on_old_endpoint(struct u132 *u132,
++	struct u132_udev *udev, struct urb *urb,
+         struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
+         u8 usb_endp, u8 address)
+ {
+@@ -1964,21 +1977,33 @@ static int queue_int_on_old_endpoint(struct u132 *u132, struct u132_udev *udev,
+ }
+ 
+ static int create_endpoint_and_queue_bulk(struct u132 *u132,
+-        struct u132_udev *udev, struct usb_host_endpoint *hep, struct urb *urb,
++	struct u132_udev *udev, struct urb *urb,
+         struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
+         gfp_t mem_flags)
+ {
+         int ring_number;
+         struct u132_ring *ring;
+         unsigned long irqs;
+-        u8 endp_number = ++u132->num_endpoints;
+-        struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] =
+-                kmalloc(sizeof(struct u132_endp), mem_flags);
++	int rc;
++	u8 endp_number;
++	struct u132_endp *endp = kmalloc(sizeof(struct u132_endp), mem_flags);
++
+         if (!endp) {
+                 return -ENOMEM;
+         }
++
++	spin_lock_init(&endp->queue_lock.slock);
++	spin_lock_irqsave(&endp->queue_lock.slock, irqs);
++	rc = usb_hcd_link_urb_to_ep(u132_to_hcd(u132), urb);
++	if (rc) {
++		spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++		kfree(endp);
++		return rc;
++	}
++
++	endp_number = ++u132->num_endpoints;
++	urb->ep->hcpriv = u132->endp[endp_number - 1] = endp;
+         INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
+-        spin_lock_init(&endp->queue_lock.slock);
+         INIT_LIST_HEAD(&endp->urb_more);
+         endp->dequeueing = 0;
+         endp->edset_flush = 0;
+@@ -1986,7 +2011,7 @@ static int create_endpoint_and_queue_bulk(struct u132 *u132,
+         endp->delayed = 0;
+         endp->endp_number = endp_number;
+         endp->u132 = u132;
+-        endp->hep = hep;
++	endp->hep = urb->ep;
+         endp->pipetype = usb_pipetype(urb->pipe);
+         u132_endp_init_kref(u132, endp);
+         if (usb_pipein(urb->pipe)) {
+@@ -2015,7 +2040,6 @@ static int create_endpoint_and_queue_bulk(struct u132 *u132,
+         }
+         ring->length += 1;
+         urb->hcpriv = u132;
+-        spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+         endp->udev_number = address;
+         endp->usb_addr = usb_addr;
+         endp->usb_endp = usb_endp;
+@@ -2029,7 +2053,7 @@ static int create_endpoint_and_queue_bulk(struct u132 *u132,
+ }
+ 
+ static int queue_bulk_on_old_endpoint(struct u132 *u132, struct u132_udev *udev,
+-         struct usb_host_endpoint *hep, struct urb *urb,
++	struct urb *urb,
+         struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
+         u8 usb_endp, u8 address)
+ {
+@@ -2051,19 +2075,32 @@ static int queue_bulk_on_old_endpoint(struct u132 *u132, struct u132_udev *udev,
+ }
+ 
+ static int create_endpoint_and_queue_control(struct u132 *u132,
+-        struct usb_host_endpoint *hep, struct urb *urb,
++	struct urb *urb,
+         struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp,
+         gfp_t mem_flags)
+ {
+         struct u132_ring *ring;
+-        u8 endp_number = ++u132->num_endpoints;
+-        struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] =
+-                kmalloc(sizeof(struct u132_endp), mem_flags);
++	unsigned long irqs;
++	int rc;
++	u8 endp_number;
++	struct u132_endp *endp = kmalloc(sizeof(struct u132_endp), mem_flags);
++
+         if (!endp) {
+                 return -ENOMEM;
+         }
++
++	spin_lock_init(&endp->queue_lock.slock);
++	spin_lock_irqsave(&endp->queue_lock.slock, irqs);
++	rc = usb_hcd_link_urb_to_ep(u132_to_hcd(u132), urb);
++	if (rc) {
++		spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++		kfree(endp);
++		return rc;
++	}
++
++	endp_number = ++u132->num_endpoints;
++	urb->ep->hcpriv = u132->endp[endp_number - 1] = endp;
+         INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
+-        spin_lock_init(&endp->queue_lock.slock);
+         INIT_LIST_HEAD(&endp->urb_more);
+         ring = endp->ring = &u132->ring[0];
+         if (ring->curr_endp) {
+@@ -2079,11 +2116,10 @@ static int create_endpoint_and_queue_control(struct u132 *u132,
+         endp->delayed = 0;
+         endp->endp_number = endp_number;
+         endp->u132 = u132;
+-        endp->hep = hep;
++	endp->hep = urb->ep;
+         u132_endp_init_kref(u132, endp);
+         u132_endp_get_kref(u132, endp);
+         if (usb_addr == 0) {
+-                unsigned long irqs;
+                 u8 address = u132->addr[usb_addr].address;
+                 struct u132_udev *udev = &u132->udev[address];
+                 endp->udev_number = address;
+@@ -2097,7 +2133,6 @@ static int create_endpoint_and_queue_control(struct u132 *u132,
+                 udev->endp_number_in[usb_endp] = endp_number;
+                 udev->endp_number_out[usb_endp] = endp_number;
+                 urb->hcpriv = u132;
+-                spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+                 endp->queue_size = 1;
+                 endp->queue_last = 0;
+                 endp->queue_next = 0;
+@@ -2106,7 +2141,6 @@ static int create_endpoint_and_queue_control(struct u132 *u132,
+                 u132_endp_queue_work(u132, endp, 0);
+                 return 0;
+         } else {                /*(usb_addr > 0) */
+-                unsigned long irqs;
+                 u8 address = u132->addr[usb_addr].address;
+                 struct u132_udev *udev = &u132->udev[address];
+                 endp->udev_number = address;
+@@ -2120,7 +2154,6 @@ static int create_endpoint_and_queue_control(struct u132 *u132,
+                 udev->endp_number_in[usb_endp] = endp_number;
+                 udev->endp_number_out[usb_endp] = endp_number;
+                 urb->hcpriv = u132;
+-                spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+                 endp->queue_size = 1;
+                 endp->queue_last = 0;
+                 endp->queue_next = 0;
+@@ -2132,7 +2165,7 @@ static int create_endpoint_and_queue_control(struct u132 *u132,
+ }
+ 
+ static int queue_control_on_old_endpoint(struct u132 *u132,
+-        struct usb_host_endpoint *hep, struct urb *urb,
++	struct urb *urb,
+         struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
+         u8 usb_endp)
+ {
+@@ -2232,8 +2265,8 @@ static int queue_control_on_old_endpoint(struct u132 *u132,
+         }
+ }
+ 
+-static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep,
+-        struct urb *urb, gfp_t mem_flags)
++static int u132_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
++		gfp_t mem_flags)
+ {
+         struct u132 *u132 = hcd_to_u132(hcd);
+         if (irqs_disabled()) {
+@@ -2258,16 +2291,24 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep,
+                 if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
+                         u8 address = u132->addr[usb_addr].address;
+                         struct u132_udev *udev = &u132->udev[address];
+-                        struct u132_endp *endp = hep->hcpriv;
++                        struct u132_endp *endp = urb->ep->hcpriv;
+                         urb->actual_length = 0;
+                         if (endp) {
+                                 unsigned long irqs;
+                                 int retval;
+                                 spin_lock_irqsave(&endp->queue_lock.slock,
+                                         irqs);
+-                                retval = queue_int_on_old_endpoint(u132, udev,
+-                                        hep, urb, usb_dev, endp, usb_addr,
+-                                        usb_endp, address);
++				retval = usb_hcd_link_urb_to_ep(hcd, urb);
++				if (retval == 0) {
++					retval = queue_int_on_old_endpoint(
++							u132, udev, urb,
++							usb_dev, endp,
++							usb_addr, usb_endp,
++							address);
++					if (retval)
++						usb_hcd_unlink_urb_from_ep(
++								hcd, urb);
++				}
+                                 spin_unlock_irqrestore(&endp->queue_lock.slock,
+                                         irqs);
+                                 if (retval) {
+@@ -2282,8 +2323,8 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep,
+                                 return -EINVAL;
+                         } else {        /*(endp == NULL) */
+                                 return create_endpoint_and_queue_int(u132, udev,
+-                                         hep, urb, usb_dev, usb_addr, usb_endp,
+-                                        address, mem_flags);
++						urb, usb_dev, usb_addr,
++						usb_endp, address, mem_flags);
+                         }
+                 } else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+                         dev_err(&u132->platform_dev->dev, "the hardware does no"
+@@ -2292,16 +2333,24 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep,
+                 } else if (usb_pipetype(urb->pipe) == PIPE_BULK) {
+                         u8 address = u132->addr[usb_addr].address;
+                         struct u132_udev *udev = &u132->udev[address];
+-                        struct u132_endp *endp = hep->hcpriv;
++                        struct u132_endp *endp = urb->ep->hcpriv;
+                         urb->actual_length = 0;
+                         if (endp) {
+                                 unsigned long irqs;
+                                 int retval;
+                                 spin_lock_irqsave(&endp->queue_lock.slock,
+                                         irqs);
+-                                retval = queue_bulk_on_old_endpoint(u132, udev,
+-                                        hep, urb, usb_dev, endp, usb_addr,
+-                                        usb_endp, address);
++				retval = usb_hcd_link_urb_to_ep(hcd, urb);
++				if (retval == 0) {
++					retval = queue_bulk_on_old_endpoint(
++							u132, udev, urb,
++							usb_dev, endp,
++							usb_addr, usb_endp,
++							address);
++					if (retval)
++						usb_hcd_unlink_urb_from_ep(
++								hcd, urb);
++				}
+                                 spin_unlock_irqrestore(&endp->queue_lock.slock,
+                                         irqs);
+                                 if (retval) {
+@@ -2314,10 +2363,10 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep,
+                                 return -EINVAL;
+                         } else
+                                 return create_endpoint_and_queue_bulk(u132,
+-                                        udev, hep, urb, usb_dev, usb_addr,
++					udev, urb, usb_dev, usb_addr,
+                                         usb_endp, address, mem_flags);
+                 } else {
+-                        struct u132_endp *endp = hep->hcpriv;
++                        struct u132_endp *endp = urb->ep->hcpriv;
+                         u16 urb_size = 8;
+                         u8 *b = urb->setup_packet;
+                         int i = 0;
+@@ -2340,9 +2389,16 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep,
+                                 int retval;
+                                 spin_lock_irqsave(&endp->queue_lock.slock,
+                                         irqs);
+-                                retval = queue_control_on_old_endpoint(u132,
+-                                        hep, urb, usb_dev, endp, usb_addr,
+-                                        usb_endp);
++				retval = usb_hcd_link_urb_to_ep(hcd, urb);
++				if (retval == 0) {
++					retval = queue_control_on_old_endpoint(
++							u132, urb, usb_dev,
++							endp, usb_addr,
++							usb_endp);
++					if (retval)
++						usb_hcd_unlink_urb_from_ep(
++								hcd, urb);
++				}
+                                 spin_unlock_irqrestore(&endp->queue_lock.slock,
+                                         irqs);
+                                 if (retval) {
+@@ -2355,7 +2411,7 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep,
+                                 return -EINVAL;
+                         } else
+                                 return create_endpoint_and_queue_control(u132,
+-                                        hep, urb, usb_dev, usb_addr, usb_endp,
++					urb, usb_dev, usb_addr, usb_endp,
+                                         mem_flags);
+                 }
+         }
+@@ -2390,10 +2446,17 @@ static int dequeue_from_overflow_chain(struct u132 *u132,
+ }
+ 
+ static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp,
+-        struct urb *urb)
++		struct urb *urb, int status)
+ {
+         unsigned long irqs;
++	int rc;
++
+         spin_lock_irqsave(&endp->queue_lock.slock, irqs);
++	rc = usb_hcd_check_unlink_urb(u132_to_hcd(u132), urb, status);
++	if (rc) {
++		spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++		return rc;
++	}
+         if (endp->queue_size == 0) {
+                 dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]"
+                         "=%p ring[%d] %c%c usb_endp=%d usb_addr=%d\n", urb,
+@@ -2438,6 +2501,8 @@ static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp,
+                 }
+                 if (urb_slot) {
+                         struct usb_hcd *hcd = u132_to_hcd(u132);
++
++			usb_hcd_unlink_urb_from_ep(hcd, urb);
+                         endp->queue_size -= 1;
+                         if (list_empty(&endp->urb_more)) {
+                                 spin_unlock_irqrestore(&endp->queue_lock.slock,
+@@ -2467,7 +2532,10 @@ static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp,
+                         spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                         return -EINVAL;
+                 } else {
+-                        int retval = dequeue_from_overflow_chain(u132, endp,
++			int retval;
++
++			usb_hcd_unlink_urb_from_ep(u132_to_hcd(u132), urb);
++			retval = dequeue_from_overflow_chain(u132, endp,
+                                 urb);
+                         spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                         return retval;
+@@ -2475,7 +2543,7 @@ static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp,
+         }
+ }
+ 
+-static int u132_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
++static int u132_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ {
+         struct u132 *u132 = hcd_to_u132(hcd);
+         if (u132->going > 2) {
+@@ -2490,11 +2558,11 @@ static int u132_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
+                 if (usb_pipein(urb->pipe)) {
+                         u8 endp_number = udev->endp_number_in[usb_endp];
+                         struct u132_endp *endp = u132->endp[endp_number - 1];
+-                        return u132_endp_urb_dequeue(u132, endp, urb);
++                        return u132_endp_urb_dequeue(u132, endp, urb, status);
+                 } else {
+                         u8 endp_number = udev->endp_number_out[usb_endp];
+                         struct u132_endp *endp = u132->endp[endp_number - 1];
+-                        return u132_endp_urb_dequeue(u132, endp, urb);
++                        return u132_endp_urb_dequeue(u132, endp, urb, status);
+                 }
+         }
+ }
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 3bb908ca38e9..bff200cb3d2e 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -1376,7 +1376,6 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb)
+ }
+ 
+ static int uhci_urb_enqueue(struct usb_hcd *hcd,
+-		struct usb_host_endpoint *hep,
+ 		struct urb *urb, gfp_t mem_flags)
+ {
+ 	int ret;
+@@ -1387,19 +1386,19 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd,
+ 
+ 	spin_lock_irqsave(&uhci->lock, flags);
+ 
+-	ret = urb->status;
+-	if (ret != -EINPROGRESS)		/* URB already unlinked! */
+-		goto done;
++	ret = usb_hcd_link_urb_to_ep(hcd, urb);
++	if (ret)
++		goto done_not_linked;
+ 
+ 	ret = -ENOMEM;
+ 	urbp = uhci_alloc_urb_priv(uhci, urb);
+ 	if (!urbp)
+ 		goto done;
+ 
+-	if (hep->hcpriv)
+-		qh = (struct uhci_qh *) hep->hcpriv;
++	if (urb->ep->hcpriv)
++		qh = urb->ep->hcpriv;
+ 	else {
+-		qh = uhci_alloc_qh(uhci, urb->dev, hep);
++		qh = uhci_alloc_qh(uhci, urb->dev, urb->ep);
+ 		if (!qh)
+ 			goto err_no_qh;
+ 	}
+@@ -1440,27 +1439,29 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd,
+ err_submit_failed:
+ 	if (qh->state == QH_STATE_IDLE)
+ 		uhci_make_qh_idle(uhci, qh);	/* Reclaim unused QH */
+-
+ err_no_qh:
+ 	uhci_free_urb_priv(uhci, urbp);
+-
+ done:
++	if (ret)
++		usb_hcd_unlink_urb_from_ep(hcd, urb);
++done_not_linked:
+ 	spin_unlock_irqrestore(&uhci->lock, flags);
+ 	return ret;
+ }
+ 
+-static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
++static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 	unsigned long flags;
+-	struct urb_priv *urbp;
+ 	struct uhci_qh *qh;
++	int rc;
+ 
+ 	spin_lock_irqsave(&uhci->lock, flags);
+-	urbp = urb->hcpriv;
+-	if (!urbp)			/* URB was never linked! */
++	rc = usb_hcd_check_unlink_urb(hcd, urb, status);
++	if (rc)
+ 		goto done;
+-	qh = urbp->qh;
++
++	qh = ((struct urb_priv *) urb->hcpriv)->qh;
+ 
+ 	/* Remove Isochronous TDs from the frame list ASAP */
+ 	if (qh->type == USB_ENDPOINT_XFER_ISOC) {
+@@ -1477,7 +1478,7 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
+ 
+ done:
+ 	spin_unlock_irqrestore(&uhci->lock, flags);
+-	return 0;
++	return rc;
+ }
+ 
+ /*
+@@ -1529,6 +1530,7 @@ __acquires(uhci->lock)
+ 	}
+ 
+ 	uhci_free_urb_priv(uhci, urbp);
++	usb_hcd_unlink_urb_from_ep(uhci_to_hcd(uhci), urb);
+ 
+ 	spin_unlock(&uhci->lock);
+ 	usb_hcd_giveback_urb(uhci_to_hcd(uhci), urb);

commit 9a9bf406df3ce238089d14f4cb41157ca56d8ad3
+Author: Alan Stern 
+Date:   Thu Aug 2 15:06:54 2007 -0400
+
+    USB: separate out endpoint queue management and DMA mapping routines
+    
+    This patch (as953) separates out three key portions from
+    usb_hcd_submit_urb(), usb_hcd_unlink_urb(), and usb_hcd_giveback_urb()
+    and puts them in separate functions of their own.  In the next patch,
+    these functions will be called directly by host controller drivers
+    while holding their private spinlocks, which will remove the
+    possibility of some unpleasant races.
+    
+    The code responsible for mapping and unmapping DMA buffers is also
+    placed into a couple of separate subroutines, for the sake of
+    cleanliness and consistency.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index f8e7deb03ee9..eb2121788264 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -914,99 +914,117 @@ EXPORT_SYMBOL (usb_calc_bus_time);
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-static void urb_unlink(struct usb_hcd *hcd, struct urb *urb)
++static int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb)
+ {
+-	unsigned long		flags;
++	unsigned long	flags;
++	int		rc = 0;
+ 
+-	/* clear all state linking urb to this dev (and hcd) */
+ 	spin_lock_irqsave(&hcd_urb_list_lock, flags);
+-	list_del_init (&urb->urb_list);
+-	spin_unlock_irqrestore(&hcd_urb_list_lock, flags);
+ 
+-	if (hcd->self.uses_dma && !is_root_hub(urb->dev)) {
+-		if (usb_endpoint_xfer_control(&urb->ep->desc)
+-			&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
+-			dma_unmap_single (hcd->self.controller, urb->setup_dma,
+-					sizeof (struct usb_ctrlrequest),
+-					DMA_TO_DEVICE);
+-		if (urb->transfer_buffer_length != 0
+-			&& !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
+-			dma_unmap_single (hcd->self.controller,
+-					urb->transfer_dma,
+-					urb->transfer_buffer_length,
+-					usb_urb_dir_in(urb)
+-					    ? DMA_FROM_DEVICE
+-					    : DMA_TO_DEVICE);
++	/* Check that the URB isn't being killed */
++	if (unlikely(urb->reject)) {
++		rc = -EPERM;
++		goto done;
+ 	}
+-}
+-
+-/* may be called in any context with a valid urb->dev usecount
+- * caller surrenders "ownership" of urb
+- * expects usb_submit_urb() to have sanity checked and conditioned all
+- * inputs in the urb
+- */
+-int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+-{
+-	int			status;
+-	struct usb_hcd		*hcd = bus_to_hcd(urb->dev->bus);
+-	unsigned long		flags;
+-
+-	if (!hcd)
+-		return -ENODEV;
+ 
+-	usbmon_urb_submit(&hcd->self, urb);
++	if (unlikely(!urb->ep->enabled)) {
++		rc = -ENOENT;
++		goto done;
++	}
+ 
+ 	/*
+-	 * Atomically queue the urb,  first to our records, then to the HCD.
+-	 * Access to urb->status is controlled by urb->lock ... changes on
+-	 * i/o completion (normal or fault) or unlinking.
++	 * Check the host controller's state and add the URB to the
++	 * endpoint's queue.
+ 	 */
+-
+-	// FIXME:  verify that quiescing hc works right (RH cleans up)
+-
+-	spin_lock_irqsave(&hcd_urb_list_lock, flags);
+-	if (unlikely(!urb->ep->enabled))
+-		status = -ENOENT;
+-	else if (unlikely (urb->reject))
+-		status = -EPERM;
+-	else switch (hcd->state) {
++	switch (hcd->state) {
+ 	case HC_STATE_RUNNING:
+ 	case HC_STATE_RESUMING:
+-		list_add_tail (&urb->urb_list, &urb->ep->urb_list);
+-		status = 0;
++		list_add_tail(&urb->urb_list, &urb->ep->urb_list);
+ 		break;
+ 	default:
+-		status = -ESHUTDOWN;
+-		break;
++		rc = -ESHUTDOWN;
++		goto done;
+ 	}
++ done:
+ 	spin_unlock_irqrestore(&hcd_urb_list_lock, flags);
+-	if (status) {
+-		INIT_LIST_HEAD (&urb->urb_list);
+-		usbmon_urb_submit_error(&hcd->self, urb, status);
+-		return status;
++	return rc;
++}
++
++static int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
++		int status)
++{
++	unsigned long		flags;
++	struct list_head	*tmp;
++	int			rc = 0;
++
++	/*
++	 * we contend for urb->status with the hcd core,
++	 * which changes it while returning the urb.
++	 *
++	 * Caller guaranteed that the urb pointer hasn't been freed, and
++	 * that it was submitted.  But as a rule it can't know whether or
++	 * not it's already been unlinked ... so we respect the reversed
++	 * lock sequence needed for the usb_hcd_giveback_urb() code paths
++	 * (urb lock, then hcd_urb_list_lock) in case some other CPU is now
++	 * unlinking it.
++	 */
++	spin_lock_irqsave(&urb->lock, flags);
++	spin_lock(&hcd_urb_list_lock);
++
++	/* insist the urb is still queued */
++	list_for_each(tmp, &urb->ep->urb_list) {
++		if (tmp == &urb->urb_list)
++			break;
++	}
++	if (tmp != &urb->urb_list) {
++		rc = -EIDRM;
++		goto done;
+ 	}
+ 
+-	/* increment urb's reference count as part of giving it to the HCD
+-	 * (which now controls it).  HCD guarantees that it either returns
+-	 * an error or calls giveback(), but not both.
++	/* Any status except -EINPROGRESS means something already started to
++	 * unlink this URB from the hardware.  So there's no more work to do.
+ 	 */
+-	urb = usb_get_urb (urb);
+-	atomic_inc (&urb->use_count);
+-
+-	if (is_root_hub(urb->dev)) {
+-		/* NOTE:  requirement on hub callers (usbfs and the hub
+-		 * driver, for now) that URBs' urb->transfer_buffer be
+-		 * valid and usb_buffer_{sync,unmap}() not be needed, since
+-		 * they could clobber root hub response data.
+-		 */
+-		status = rh_urb_enqueue (hcd, urb);
++	if (urb->status != -EINPROGRESS) {
++		rc = -EBUSY;
+ 		goto done;
+ 	}
++	urb->status = status;
++
++	/* IRQ setup can easily be broken so that USB controllers
++	 * never get completion IRQs ... maybe even the ones we need to
++	 * finish unlinking the initial failed usb_set_address()
++	 * or device descriptor fetch.
++	 */
++	if (!test_bit(HCD_FLAG_SAW_IRQ, &hcd->flags) &&
++			!is_root_hub(urb->dev)) {
++		dev_warn(hcd->self.controller, "Unlink after no-IRQ?  "
++			"Controller is probably using the wrong IRQ.\n");
++		set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
++	}
++
++ done:
++	spin_unlock(&hcd_urb_list_lock);
++	spin_unlock_irqrestore (&urb->lock, flags);
++	return rc;
++}
++
++static void usb_hcd_unlink_urb_from_ep(struct usb_hcd *hcd, struct urb *urb)
++{
++	unsigned long		flags;
+ 
+-	/* lower level hcd code should use *_dma exclusively,
++	/* clear all state linking urb to this dev (and hcd) */
++	spin_lock_irqsave(&hcd_urb_list_lock, flags);
++	list_del_init(&urb->urb_list);
++	spin_unlock_irqrestore(&hcd_urb_list_lock, flags);
++}
++
++static void map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
++{
++	/* Map the URB's buffers for DMA access.
++	 * Lower level HCD code should use *_dma exclusively,
+ 	 * unless it uses pio or talks to another transport.
+ 	 */
+-	if (hcd->self.uses_dma) {
++	if (hcd->self.uses_dma && !is_root_hub(urb->dev)) {
+ 		if (usb_endpoint_xfer_control(&urb->ep->desc)
+ 			&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
+ 			urb->setup_dma = dma_map_single (
+@@ -1024,16 +1042,73 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+ 					    ? DMA_FROM_DEVICE
+ 					    : DMA_TO_DEVICE);
+ 	}
++}
+ 
+-	status = hcd->driver->urb_enqueue (hcd, urb->ep, urb, mem_flags);
+-done:
+-	if (unlikely (status)) {
+-		urb_unlink(hcd, urb);
+-		atomic_dec (&urb->use_count);
+-		if (urb->reject)
+-			wake_up (&usb_kill_urb_queue);
++static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
++{
++	if (hcd->self.uses_dma && !is_root_hub(urb->dev)) {
++		if (usb_endpoint_xfer_control(&urb->ep->desc)
++			&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
++			dma_unmap_single(hcd->self.controller, urb->setup_dma,
++					sizeof(struct usb_ctrlrequest),
++					DMA_TO_DEVICE);
++		if (urb->transfer_buffer_length != 0
++			&& !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
++			dma_unmap_single(hcd->self.controller,
++					urb->transfer_dma,
++					urb->transfer_buffer_length,
++					usb_urb_dir_in(urb)
++					    ? DMA_FROM_DEVICE
++					    : DMA_TO_DEVICE);
++	}
++}
++
++/*-------------------------------------------------------------------------*/
++
++/* may be called in any context with a valid urb->dev usecount
++ * caller surrenders "ownership" of urb
++ * expects usb_submit_urb() to have sanity checked and conditioned all
++ * inputs in the urb
++ */
++int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
++{
++	int			status;
++	struct usb_hcd		*hcd = bus_to_hcd(urb->dev->bus);
++
++	/* increment urb's reference count as part of giving it to the HCD
++	 * (which will control it).  HCD guarantees that it either returns
++	 * an error or calls giveback(), but not both.
++	 */
++	usb_get_urb(urb);
++	atomic_inc(&urb->use_count);
++	usbmon_urb_submit(&hcd->self, urb);
++
++	/* NOTE requirements on root-hub callers (usbfs and the hub
++	 * driver, for now):  URBs' urb->transfer_buffer must be
++	 * valid and usb_buffer_{sync,unmap}() not be needed, since
++	 * they could clobber root hub response data.  Also, control
++	 * URBs must be submitted in process context with interrupts
++	 * enabled.
++	 */
++	status = usb_hcd_link_urb_to_ep(hcd, urb);
++	if (!status) {
++		map_urb_for_dma(hcd, urb);
++		if (is_root_hub(urb->dev))
++			status = rh_urb_enqueue(hcd, urb);
++		else
++			status = hcd->driver->urb_enqueue(hcd, urb->ep, urb,
++					mem_flags);
++	}
++
++	if (unlikely(status)) {
+ 		usbmon_urb_submit_error(&hcd->self, urb, status);
+-		usb_put_urb (urb);
++		unmap_urb_for_dma(hcd, urb);
++		usb_hcd_unlink_urb_from_ep(hcd, urb);
++		INIT_LIST_HEAD(&urb->urb_list);
++		atomic_dec(&urb->use_count);
++		if (urb->reject)
++			wake_up(&usb_kill_urb_queue);
++		usb_put_urb(urb);
+ 	}
+ 	return status;
+ }
+@@ -1074,78 +1149,20 @@ unlink1 (struct usb_hcd *hcd, struct urb *urb)
+  */
+ int usb_hcd_unlink_urb (struct urb *urb, int status)
+ {
+-	struct usb_hcd			*hcd = NULL;
+-	struct device			*sys = NULL;
+-	unsigned long			flags;
+-	struct list_head		*tmp;
+-	int				retval;
+-
+-	/*
+-	 * we contend for urb->status with the hcd core,
+-	 * which changes it while returning the urb.
+-	 *
+-	 * Caller guaranteed that the urb pointer hasn't been freed, and
+-	 * that it was submitted.  But as a rule it can't know whether or
+-	 * not it's already been unlinked ... so we respect the reversed
+-	 * lock sequence needed for the usb_hcd_giveback_urb() code paths
+-	 * (urb lock, then hcd_urb_list_lock) in case some other CPU is now
+-	 * unlinking it.
+-	 */
+-	spin_lock_irqsave (&urb->lock, flags);
+-	spin_lock(&hcd_urb_list_lock);
++	struct usb_hcd		*hcd;
++	int			retval;
+ 
+-	sys = &urb->dev->dev;
+ 	hcd = bus_to_hcd(urb->dev->bus);
+-	if (hcd == NULL) {
+-		retval = -ENODEV;
+-		goto done;
+-	}
+-
+-	/* insist the urb is still queued */
+-	list_for_each(tmp, &urb->ep->urb_list) {
+-		if (tmp == &urb->urb_list)
+-			break;
+-	}
+-	if (tmp != &urb->urb_list) {
+-		retval = -EIDRM;
+-		goto done;
+-	}
+ 
+-	/* Any status except -EINPROGRESS means something already started to
+-	 * unlink this URB from the hardware.  So there's no more work to do.
+-	 */
+-	if (urb->status != -EINPROGRESS) {
+-		retval = -EBUSY;
+-		goto done;
+-	}
++	retval = usb_hcd_check_unlink_urb(hcd, urb, status);
++	if (!retval)
++		retval = unlink1(hcd, urb);
+ 
+-	/* IRQ setup can easily be broken so that USB controllers
+-	 * never get completion IRQs ... maybe even the ones we need to
+-	 * finish unlinking the initial failed usb_set_address()
+-	 * or device descriptor fetch.
+-	 */
+-	if (!test_bit(HCD_FLAG_SAW_IRQ, &hcd->flags) &&
+-			!is_root_hub(urb->dev)) {
+-		dev_warn (hcd->self.controller, "Unlink after no-IRQ?  "
+-			"Controller is probably using the wrong IRQ.\n");
+-		set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+-	}
+-
+-	urb->status = status;
+-
+-	spin_unlock(&hcd_urb_list_lock);
+-	spin_unlock_irqrestore (&urb->lock, flags);
+-
+-	retval = unlink1 (hcd, urb);
+ 	if (retval == 0)
+ 		retval = -EINPROGRESS;
+-	return retval;
+-
+-done:
+-	spin_unlock(&hcd_urb_list_lock);
+-	spin_unlock_irqrestore (&urb->lock, flags);
+-	if (retval != -EIDRM && sys && sys->driver)
+-		dev_dbg (sys, "hcd_unlink_urb %p fail %d\n", urb, retval);
++	else if (retval != -EIDRM)
++		dev_dbg(&urb->dev->dev, "hcd_unlink_urb %p fail %d\n",
++				urb, retval);
+ 	return retval;
+ }
+ 
+@@ -1165,7 +1182,8 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
+  */
+ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
+ {
+-	urb_unlink(hcd, urb);
++	usb_hcd_unlink_urb_from_ep(hcd, urb);
++	unmap_urb_for_dma(hcd, urb);
+ 	usbmon_urb_complete (&hcd->self, urb);
+ 	usb_unanchor_urb(urb);
+ 
+@@ -1194,12 +1212,12 @@ void usb_hcd_endpoint_disable (struct usb_device *udev,
+ 	struct usb_hcd		*hcd;
+ 	struct urb		*urb;
+ 
++	might_sleep();
+ 	hcd = bus_to_hcd(udev->bus);
+-	local_irq_disable ();
+ 
+ 	/* ep is already gone from udev->ep_{in,out}[]; no more submits */
+ rescan:
+-	spin_lock(&hcd_urb_list_lock);
++	spin_lock_irq(&hcd_urb_list_lock);
+ 	list_for_each_entry (urb, &ep->urb_list, urb_list) {
+ 		int	tmp;
+ 		int	is_in;
+@@ -1244,13 +1262,11 @@ void usb_hcd_endpoint_disable (struct usb_device *udev,
+ 		/* list contents may have changed */
+ 		goto rescan;
+ 	}
+-	spin_unlock(&hcd_urb_list_lock);
+-	local_irq_enable ();
++	spin_unlock_irq(&hcd_urb_list_lock);
+ 
+ 	/* synchronize with the hardware, so old configuration state
+ 	 * clears out immediately (and will be freed).
+ 	 */
+-	might_sleep ();
+ 	if (hcd->driver->endpoint_disable)
+ 		hcd->driver->endpoint_disable (hcd, ep);
+ 

commit 9439eb94b5c374d5b02699f8897fc43aa3603701
+Author: Alan Stern 
+Date:   Thu Aug 2 15:05:45 2007 -0400
+
+    USB: update spinlock usage for root-hub URBs
+    
+    This patch (as952) adjusts the spinlock usage in the root-hub
+    emulation part of usbcore, to make it match more closely the pattern
+    used by regular host controller drivers.  To wit: The private lock
+    (usb_hcd_root_hub_lock) is held throughout the important parts, and it
+    is dropped temporarily without re-enabling interrupts around the call
+    to usb_hcd_giveback_urb().
+    
+    A nice side effect is that the code now avoids calling
+    local_irq_save(), thereby becoming more RT-friendly.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 47a055a2acf5..f8e7deb03ee9 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -356,10 +356,11 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
+ 	const u8	*bufp = tbuf;
+ 	int		len = 0;
+ 	int		patch_wakeup = 0;
+-	unsigned long	flags;
+ 	int		status = 0;
+ 	int		n;
+ 
++	might_sleep();
++
+ 	cmd = (struct usb_ctrlrequest *) urb->setup_packet;
+ 	typeReq  = (cmd->bRequestType << 8) | cmd->bRequest;
+ 	wValue   = le16_to_cpu (cmd->wValue);
+@@ -523,13 +524,21 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
+ 	}
+ 
+ 	/* any errors get returned through the urb completion */
+-	local_irq_save (flags);
+-	spin_lock (&urb->lock);
++	spin_lock_irq(&hcd_root_hub_lock);
++	spin_lock(&urb->lock);
+ 	if (urb->status == -EINPROGRESS)
+ 		urb->status = status;
+-	spin_unlock (&urb->lock);
+-	usb_hcd_giveback_urb (hcd, urb);
+-	local_irq_restore (flags);
++	spin_unlock(&urb->lock);
++
++	/* This peculiar use of spinlocks echoes what real HC drivers do.
++	 * Avoiding calls to local_irq_disable/enable makes the code
++	 * RT-friendly.
++	 */
++	spin_unlock(&hcd_root_hub_lock);
++	usb_hcd_giveback_urb(hcd, urb);
++	spin_lock(&hcd_root_hub_lock);
++
++	spin_unlock_irq(&hcd_root_hub_lock);
+ 	return 0;
+ }
+ 
+@@ -559,8 +568,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
+ 	if (length > 0) {
+ 
+ 		/* try to complete the status urb */
+-		local_irq_save (flags);
+-		spin_lock(&hcd_root_hub_lock);
++		spin_lock_irqsave(&hcd_root_hub_lock, flags);
+ 		urb = hcd->status_urb;
+ 		if (urb) {
+ 			spin_lock(&urb->lock);
+@@ -574,16 +582,16 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
+ 			} else		/* urb has been unlinked */
+ 				length = 0;
+ 			spin_unlock(&urb->lock);
++
++			spin_unlock(&hcd_root_hub_lock);
++			usb_hcd_giveback_urb(hcd, urb);
++			spin_lock(&hcd_root_hub_lock);
+ 		} else
+ 			length = 0;
+-		spin_unlock(&hcd_root_hub_lock);
+ 
+-		/* local irqs are always blocked in completions */
+-		if (length > 0)
+-			usb_hcd_giveback_urb (hcd, urb);
+-		else
++		if (length <= 0)
+ 			hcd->poll_pending = 1;
+-		local_irq_restore (flags);
++		spin_unlock_irqrestore(&hcd_root_hub_lock, flags);
+ 	}
+ 
+ 	/* The USB 2.0 spec says 256 ms.  This is close enough and won't
+@@ -651,25 +659,23 @@ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
+ {
+ 	unsigned long	flags;
+ 
++	spin_lock_irqsave(&hcd_root_hub_lock, flags);
+ 	if (usb_endpoint_num(&urb->ep->desc) == 0) {	/* Control URB */
+ 		;	/* Do nothing */
+ 
+ 	} else {				/* Status URB */
+ 		if (!hcd->uses_new_polling)
+ 			del_timer (&hcd->rh_timer);
+-		local_irq_save (flags);
+-		spin_lock (&hcd_root_hub_lock);
+ 		if (urb == hcd->status_urb) {
+ 			hcd->status_urb = NULL;
+ 			urb->hcpriv = NULL;
+-		} else
+-			urb = NULL;		/* wasn't fully queued */
+-		spin_unlock (&hcd_root_hub_lock);
+-		if (urb)
+-			usb_hcd_giveback_urb (hcd, urb);
+-		local_irq_restore (flags);
+-	}
+ 
++			spin_unlock(&hcd_root_hub_lock);
++			usb_hcd_giveback_urb(hcd, urb);
++			spin_lock(&hcd_root_hub_lock);
++		}
++	}
++	spin_unlock_irqrestore(&hcd_root_hub_lock, flags);
+ 	return 0;
+ }
+ 

commit d617bc83ff48ebf0df253605529d8b3bef15773a
+Author: Alan Stern 
+Date:   Thu Aug 2 15:04:52 2007 -0400
+
+    USB: cleanup for previous patches
+    
+    This patch (as951) cleans up a few loose ends from earlier patches.
+    Redundant checks for non-NULL urb->dev are removed, as are checks of
+    urb->dev->bus (which can never be NULL).  Conversely, a check for
+    non-NULL urb->ep is added to the unlink paths.
+    
+    A homegrown round-down-to-power-of-2 loop is simplified by using the
+    ilog2 routine.  The comparison in usb_urb_dir_in() is made more
+    transparent.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 739c5e0aa3b8..47a055a2acf5 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1074,11 +1074,6 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
+ 	struct list_head		*tmp;
+ 	int				retval;
+ 
+-	if (!urb)
+-		return -EINVAL;
+-	if (!urb->dev || !urb->dev->bus)
+-		return -ENODEV;
+-
+ 	/*
+ 	 * we contend for urb->status with the hcd core,
+ 	 * which changes it while returning the urb.
+diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
+index 1acca8696bcd..19f5f66c2733 100644
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -3,6 +3,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include "hcd.h"
+@@ -441,10 +442,8 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 		default:
+ 			return -EINVAL;
+ 		}
+-		/* power of two? */
+-		while (max > urb->interval)
+-			max >>= 1;
+-		urb->interval = max;
++		/* Round down to a power of 2, no more than max */
++		urb->interval = min(max, 1 << ilog2(urb->interval));
+ 	}
+ 
+ 	return usb_hcd_submit_urb(urb, mem_flags);
+@@ -513,8 +512,10 @@ int usb_unlink_urb(struct urb *urb)
+ {
+ 	if (!urb)
+ 		return -EINVAL;
+-	if (!(urb->dev && urb->dev->bus))
++	if (!urb->dev)
+ 		return -ENODEV;
++	if (!urb->ep)
++		return -EIDRM;
+ 	return usb_hcd_unlink_urb(urb, -ECONNRESET);
+ }
+ 
+@@ -541,7 +542,7 @@ int usb_unlink_urb(struct urb *urb)
+ void usb_kill_urb(struct urb *urb)
+ {
+ 	might_sleep();
+-	if (!(urb && urb->dev && urb->dev->bus))
++	if (!(urb && urb->dev && urb->ep))
+ 		return;
+ 	spin_lock_irq(&urb->lock);
+ 	++urb->reject;
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 019ae963a9fe..a51f34e80572 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -1395,7 +1395,7 @@ extern int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor,
+  */
+ static inline int usb_urb_dir_in(struct urb *urb)
+ {
+-	return (urb->transfer_flags & URB_DIR_MASK) != URB_DIR_OUT;
++	return (urb->transfer_flags & URB_DIR_MASK) == URB_DIR_IN;
+ }
+ 
+ /**

commit 18ea5d00d05fa6300606f0711748016c95fb26dc
+Author: Alan Stern 
+Date:   Mon Jul 30 17:10:36 2007 -0400
+
+    USB: avoid urb->pipe in usbmon
+    
+    This patch (as949) changes the usbmon driver to use the new urb->ep
+    field rather than urb->pipe.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Pete Zaitcev 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
+index c03dfd7a9d36..0b0d77c669da 100644
+--- a/drivers/usb/mon/mon_bin.c
++++ b/drivers/usb/mon/mon_bin.c
+@@ -354,7 +354,7 @@ static inline char mon_bin_get_setup(unsigned char *setupb,
+     const struct urb *urb, char ev_type)
+ {
+ 
+-	if (!usb_pipecontrol(urb->pipe) || ev_type != 'S')
++	if (!usb_endpoint_xfer_control(&urb->ep->desc) || ev_type != 'S')
+ 		return '-';
+ 
+ 	if (urb->dev->bus->uses_dma &&
+@@ -410,7 +410,7 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
+ 	if (length >= rp->b_size/5)
+ 		length = rp->b_size/5;
+ 
+-	if (usb_pipein(urb->pipe)) {
++	if (usb_urb_dir_in(urb)) {
+ 		if (ev_type == 'S') {
+ 			length = 0;
+ 			data_tag = '<';
+@@ -440,10 +440,22 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
+ 	 */
+ 	memset(ep, 0, PKT_SIZE);
+ 	ep->type = ev_type;
+-	ep->xfer_type = usb_pipetype(urb->pipe);
+-	/* We use the fact that usb_pipein() returns 0x80 */
+-	ep->epnum = usb_pipeendpoint(urb->pipe) | usb_pipein(urb->pipe);
+-	ep->devnum = usb_pipedevice(urb->pipe);
++	switch (usb_endpoint_type(&urb->ep->desc)) {
++	case USB_ENDPOINT_XFER_CONTROL:
++		ep->xfer_type = PIPE_CONTROL;
++		break;
++	case USB_ENDPOINT_XFER_BULK:
++		ep->xfer_type = PIPE_BULK;
++		break;
++	case USB_ENDPOINT_XFER_INT:
++		ep->xfer_type = PIPE_INTERRUPT;
++		break;
++	default:
++		ep->xfer_type = PIPE_ISOCHRONOUS;
++		break;
++	}
++	ep->epnum = urb->ep->desc.bEndpointAddress;
++	ep->devnum = urb->dev->devnum;
+ 	ep->busnum = urb->dev->bus->busnum;
+ 	ep->id = (unsigned long) urb;
+ 	ep->ts_sec = ts.tv_sec;
+@@ -500,10 +512,22 @@ static void mon_bin_error(void *data, struct urb *urb, int error)
+ 
+ 	memset(ep, 0, PKT_SIZE);
+ 	ep->type = 'E';
+-	ep->xfer_type = usb_pipetype(urb->pipe);
+-	/* We use the fact that usb_pipein() returns 0x80 */
+-	ep->epnum = usb_pipeendpoint(urb->pipe) | usb_pipein(urb->pipe);
+-	ep->devnum = usb_pipedevice(urb->pipe);
++	switch (usb_endpoint_type(&urb->ep->desc)) {
++	case USB_ENDPOINT_XFER_CONTROL:
++		ep->xfer_type = PIPE_CONTROL;
++		break;
++	case USB_ENDPOINT_XFER_BULK:
++		ep->xfer_type = PIPE_BULK;
++		break;
++	case USB_ENDPOINT_XFER_INT:
++		ep->xfer_type = PIPE_INTERRUPT;
++		break;
++	default:
++		ep->xfer_type = PIPE_ISOCHRONOUS;
++		break;
++	}
++	ep->epnum = urb->ep->desc.bEndpointAddress;
++	ep->devnum = urb->dev->devnum;
+ 	ep->busnum = urb->dev->bus->busnum;
+ 	ep->id = (unsigned long) urb;
+ 	ep->status = error;
+diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c
+index ce61d8b0fd86..e58f761d060f 100644
+--- a/drivers/usb/mon/mon_main.c
++++ b/drivers/usb/mon/mon_main.c
+@@ -154,8 +154,8 @@ static void mon_complete(struct usb_bus *ubus, struct urb *urb)
+ 		 * This should not happen.
+ 		 * At this point we do not even know the bus number...
+ 		 */
+-		printk(KERN_ERR TAG ": Null mon bus in URB, pipe 0x%x\n",
+-		    urb->pipe);
++		printk(KERN_ERR TAG ": Null mon bus in URB, address %p\n",
++		    urb);
+ 		return;
+ 	}
+ 
+diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
+index 8f27a9e1c36b..9d0070ceef52 100644
+--- a/drivers/usb/mon/mon_text.c
++++ b/drivers/usb/mon/mon_text.c
+@@ -50,10 +50,12 @@ struct mon_iso_desc {
+ struct mon_event_text {
+ 	struct list_head e_link;
+ 	int type;		/* submit, complete, etc. */
+-	unsigned int pipe;	/* Pipe */
+ 	unsigned long id;	/* From pointer, most of the time */
+ 	unsigned int tstamp;
++	int xfertype;
+ 	int busnum;
++	int devnum;
++	int epnum;
+ 	int length;		/* Depends on type: xfer length or act length */
+ 	int status;
+ 	int interval;
+@@ -61,6 +63,7 @@ struct mon_event_text {
+ 	int error_count;
+ 	char setup_flag;
+ 	char data_flag;
++	char is_in;
+ 	int numdesc;		/* Full number */
+ 	struct mon_iso_desc isodesc[ISODESC_MAX];
+ 	unsigned char setup[SETUP_MAX];
+@@ -121,7 +124,7 @@ static inline char mon_text_get_setup(struct mon_event_text *ep,
+     struct urb *urb, char ev_type, struct mon_bus *mbus)
+ {
+ 
+-	if (!usb_pipecontrol(urb->pipe) || ev_type != 'S')
++	if (ep->xfertype != USB_ENDPOINT_XFER_CONTROL || ev_type != 'S')
+ 		return '-';
+ 
+ 	if (urb->dev->bus->uses_dma &&
+@@ -138,14 +141,12 @@ static inline char mon_text_get_setup(struct mon_event_text *ep,
+ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
+     int len, char ev_type, struct mon_bus *mbus)
+ {
+-	int pipe = urb->pipe;
+-
+ 	if (len <= 0)
+ 		return 'L';
+ 	if (len >= DATA_MAX)
+ 		len = DATA_MAX;
+ 
+-	if (usb_pipein(pipe)) {
++	if (ep->is_in) {
+ 		if (ev_type != 'C')
+ 			return '<';
+ 	} else {
+@@ -203,24 +204,28 @@ static void mon_text_event(struct mon_reader_text *rp, struct urb *urb,
+ 	}
+ 
+ 	ep->type = ev_type;
+-	ep->pipe = urb->pipe;
+ 	ep->id = (unsigned long) urb;
+ 	ep->busnum = urb->dev->bus->busnum;
++	ep->devnum = urb->dev->devnum;
++	ep->epnum = usb_endpoint_num(&urb->ep->desc);
++	ep->xfertype = usb_endpoint_type(&urb->ep->desc);
++	ep->is_in = usb_urb_dir_in(urb);
+ 	ep->tstamp = stamp;
+ 	ep->length = (ev_type == 'S') ?
+ 	    urb->transfer_buffer_length : urb->actual_length;
+ 	/* Collecting status makes debugging sense for submits, too */
+ 	ep->status = urb->status;
+ 
+-	if (usb_pipeint(urb->pipe)) {
++	if (ep->xfertype == USB_ENDPOINT_XFER_INT) {
+ 		ep->interval = urb->interval;
+-	} else if (usb_pipeisoc(urb->pipe)) {
++	} else if (ep->xfertype == USB_ENDPOINT_XFER_ISOC) {
+ 		ep->interval = urb->interval;
+ 		ep->start_frame = urb->start_frame;
+ 		ep->error_count = urb->error_count;
+ 	}
+ 	ep->numdesc = urb->number_of_packets;
+-	if (usb_pipeisoc(urb->pipe) && urb->number_of_packets > 0) {
++	if (ep->xfertype == USB_ENDPOINT_XFER_ISOC &&
++			urb->number_of_packets > 0) {
+ 		if ((ndesc = urb->number_of_packets) > ISODESC_MAX)
+ 			ndesc = ISODESC_MAX;
+ 		fp = urb->iso_frame_desc;
+@@ -268,9 +273,12 @@ static void mon_text_error(void *data, struct urb *urb, int error)
+ 	}
+ 
+ 	ep->type = 'E';
+-	ep->pipe = urb->pipe;
+ 	ep->id = (unsigned long) urb;
+ 	ep->busnum = 0;
++	ep->devnum = urb->dev->devnum;
++	ep->epnum = usb_endpoint_num(&urb->ep->desc);
++	ep->xfertype = usb_endpoint_type(&urb->ep->desc);
++	ep->is_in = usb_urb_dir_in(urb);
+ 	ep->tstamp = 0;
+ 	ep->length = 0;
+ 	ep->status = error;
+@@ -413,10 +421,10 @@ static ssize_t mon_text_read_u(struct file *file, char __user *buf,
+ 	mon_text_read_head_u(rp, &ptr, ep);
+ 	if (ep->type == 'E') {
+ 		mon_text_read_statset(rp, &ptr, ep);
+-	} else if (usb_pipeisoc(ep->pipe)) {
++	} else if (ep->xfertype == USB_ENDPOINT_XFER_ISOC) {
+ 		mon_text_read_isostat(rp, &ptr, ep);
+ 		mon_text_read_isodesc(rp, &ptr, ep);
+-	} else if (usb_pipeint(ep->pipe)) {
++	} else if (ep->xfertype == USB_ENDPOINT_XFER_INT) {
+ 		mon_text_read_intstat(rp, &ptr, ep);
+ 	} else {
+ 		mon_text_read_statset(rp, &ptr, ep);
+@@ -468,18 +476,17 @@ static void mon_text_read_head_t(struct mon_reader_text *rp,
+ {
+ 	char udir, utype;
+ 
+-	udir = usb_pipein(ep->pipe) ? 'i' : 'o';
+-	switch (usb_pipetype(ep->pipe)) {
+-	case PIPE_ISOCHRONOUS:	utype = 'Z'; break;
+-	case PIPE_INTERRUPT:	utype = 'I'; break;
+-	case PIPE_CONTROL:	utype = 'C'; break;
++	udir = (ep->is_in ? 'i' : 'o');
++	switch (ep->xfertype) {
++	case USB_ENDPOINT_XFER_ISOC:	utype = 'Z'; break;
++	case USB_ENDPOINT_XFER_INT:	utype = 'I'; break;
++	case USB_ENDPOINT_XFER_CONTROL:	utype = 'C'; break;
+ 	default: /* PIPE_BULK */  utype = 'B';
+ 	}
+ 	p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+ 	    "%lx %u %c %c%c:%03u:%02u",
+ 	    ep->id, ep->tstamp, ep->type,
+-	    utype, udir,
+-	    usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe));
++	    utype, udir, ep->devnum, ep->epnum);
+ }
+ 
+ static void mon_text_read_head_u(struct mon_reader_text *rp,
+@@ -487,18 +494,17 @@ static void mon_text_read_head_u(struct mon_reader_text *rp,
+ {
+ 	char udir, utype;
+ 
+-	udir = usb_pipein(ep->pipe) ? 'i' : 'o';
+-	switch (usb_pipetype(ep->pipe)) {
+-	case PIPE_ISOCHRONOUS:	utype = 'Z'; break;
+-	case PIPE_INTERRUPT:	utype = 'I'; break;
+-	case PIPE_CONTROL:	utype = 'C'; break;
++	udir = (ep->is_in ? 'i' : 'o');
++	switch (ep->xfertype) {
++	case USB_ENDPOINT_XFER_ISOC:	utype = 'Z'; break;
++	case USB_ENDPOINT_XFER_INT:	utype = 'I'; break;
++	case USB_ENDPOINT_XFER_CONTROL:	utype = 'C'; break;
+ 	default: /* PIPE_BULK */  utype = 'B';
+ 	}
+ 	p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+ 	    "%lx %u %c %c%c:%d:%03u:%u",
+ 	    ep->id, ep->tstamp, ep->type,
+-	    utype, udir,
+-	    ep->busnum, usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe));
++	    utype, udir, ep->busnum, ep->devnum, ep->epnum);
+ }
+ 
+ static void mon_text_read_statset(struct mon_reader_text *rp,

commit 93cf9b909efb773f74b5d87659d41f957ccbce7e
+Author: Alan Stern 
+Date:   Mon Jul 30 17:09:28 2007 -0400
+
+    USB: avoid urb->pipe in usbfs
+    
+    This patch (as948) removes most of the references to urb->pipe from
+    the usbfs routines in devio.c.  The one tricky aspect is in
+    snoop_urb(), which can be called before the URB is submitted and which
+    uses usb_urb_dir_in().  For this to work properly, the URB's direction
+    flag must be set manually in proc_do_submiturb().
+    
+    The patch also fixes a minor bug; the wValue, wIndex, and wLength
+    fields were snooped in proc_do_submiturb() without conversion from
+    le16 to CPU-byte-ordering.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 927a181120a9..b9f1edd6af53 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -289,10 +289,8 @@ static void snoop_urb(struct urb *urb, void __user *userurb)
+ 	if (!usbfs_snoop)
+ 		return;
+ 
+-	if (urb->pipe & USB_DIR_IN)
+-		dev_info(&urb->dev->dev, "direction=IN\n");
+-	else
+-		dev_info(&urb->dev->dev, "direction=OUT\n");
++	dev_info(&urb->dev->dev, "direction=%s\n",
++			usb_urb_dir_in(urb) ? "IN" : "OUT");
+ 	dev_info(&urb->dev->dev, "userurb=%p\n", userurb);
+ 	dev_info(&urb->dev->dev, "transfer_buffer_length=%d\n",
+ 		 urb->transfer_buffer_length);
+@@ -910,6 +908,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 	struct usb_ctrlrequest *dr = NULL;
+ 	unsigned int u, totlen, isofrmlen;
+ 	int ret, ifnum = -1;
++	int is_in;
+ 
+ 	if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK|
+ 			   URB_NO_FSBR|URB_ZERO_PACKET))
+@@ -924,16 +923,18 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 		if ((ret = checkintf(ps, ifnum)))
+ 			return ret;
+ 	}
+-	if ((uurb->endpoint & USB_ENDPOINT_DIR_MASK) != 0)
+-		ep = ps->dev->ep_in [uurb->endpoint & USB_ENDPOINT_NUMBER_MASK];
+-	else
+-		ep = ps->dev->ep_out [uurb->endpoint & USB_ENDPOINT_NUMBER_MASK];
++	if ((uurb->endpoint & USB_ENDPOINT_DIR_MASK) != 0) {
++		is_in = 1;
++		ep = ps->dev->ep_in[uurb->endpoint & USB_ENDPOINT_NUMBER_MASK];
++	} else {
++		is_in = 0;
++		ep = ps->dev->ep_out[uurb->endpoint & USB_ENDPOINT_NUMBER_MASK];
++	}
+ 	if (!ep)
+ 		return -ENOENT;
+ 	switch(uurb->type) {
+ 	case USBDEVFS_URB_TYPE_CONTROL:
+-		if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+-				!= USB_ENDPOINT_XFER_CONTROL)
++		if (!usb_endpoint_xfer_control(&ep->desc))
+ 			return -EINVAL;
+ 		/* min 8 byte setup packet, max 8 byte setup plus an arbitrary data stage */
+ 		if (uurb->buffer_length < 8 || uurb->buffer_length > (8 + MAX_USBFS_BUFFER_SIZE))
+@@ -952,23 +953,32 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 			kfree(dr);
+ 			return ret;
+ 		}
+-		uurb->endpoint = (uurb->endpoint & ~USB_ENDPOINT_DIR_MASK) | (dr->bRequestType & USB_ENDPOINT_DIR_MASK);
+ 		uurb->number_of_packets = 0;
+ 		uurb->buffer_length = le16_to_cpup(&dr->wLength);
+ 		uurb->buffer += 8;
+-		if (!access_ok((uurb->endpoint & USB_DIR_IN) ?  VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length)) {
++		if ((dr->bRequestType & USB_DIR_IN) && uurb->buffer_length) {
++			is_in = 1;
++			uurb->endpoint |= USB_DIR_IN;
++		} else {
++			is_in = 0;
++			uurb->endpoint &= ~USB_DIR_IN;
++		}
++		if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
++				uurb->buffer, uurb->buffer_length)) {
+ 			kfree(dr);
+ 			return -EFAULT;
+ 		}
+ 		snoop(&ps->dev->dev, "control urb: bRequest=%02x "
+ 			"bRrequestType=%02x wValue=%04x "
+ 			"wIndex=%04x wLength=%04x\n",
+-			dr->bRequest, dr->bRequestType, dr->wValue,
+-			dr->wIndex, dr->wLength);
++			dr->bRequest, dr->bRequestType,
++			__le16_to_cpup(&dr->wValue),
++			__le16_to_cpup(&dr->wIndex),
++			__le16_to_cpup(&dr->wLength));
+ 		break;
+ 
+ 	case USBDEVFS_URB_TYPE_BULK:
+-		switch (ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
++		switch (usb_endpoint_type(&ep->desc)) {
+ 		case USB_ENDPOINT_XFER_CONTROL:
+ 		case USB_ENDPOINT_XFER_ISOC:
+ 			return -EINVAL;
+@@ -977,7 +987,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 		uurb->number_of_packets = 0;
+ 		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
+ 			return -EINVAL;
+-		if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length))
++		if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
++				uurb->buffer, uurb->buffer_length))
+ 			return -EFAULT;
+ 		snoop(&ps->dev->dev, "bulk urb\n");
+ 		break;
+@@ -986,8 +997,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 		/* arbitrary limit */
+ 		if (uurb->number_of_packets < 1 || uurb->number_of_packets > 128)
+ 			return -EINVAL;
+-		if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+-				!= USB_ENDPOINT_XFER_ISOC)
++		if (!usb_endpoint_xfer_isoc(&ep->desc))
+ 			return -EINVAL;
+ 		isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb->number_of_packets;
+ 		if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
+@@ -1014,12 +1024,12 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 
+ 	case USBDEVFS_URB_TYPE_INTERRUPT:
+ 		uurb->number_of_packets = 0;
+-		if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+-				!= USB_ENDPOINT_XFER_INT)
++		if (!usb_endpoint_xfer_int(&ep->desc))
+ 			return -EINVAL;
+ 		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
+ 			return -EINVAL;
+-		if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length))
++		if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
++				uurb->buffer, uurb->buffer_length))
+ 			return -EFAULT;
+ 		snoop(&ps->dev->dev, "interrupt urb\n");
+ 		break;
+@@ -1039,8 +1049,11 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 		return -ENOMEM;
+ 	}
+         as->urb->dev = ps->dev;
+-        as->urb->pipe = (uurb->type << 30) | __create_pipe(ps->dev, uurb->endpoint & 0xf) | (uurb->endpoint & USB_DIR_IN);
+-        as->urb->transfer_flags = uurb->flags;
++        as->urb->pipe = (uurb->type << 30) |
++			__create_pipe(ps->dev, uurb->endpoint & 0xf) |
++			(uurb->endpoint & USB_DIR_IN);
++        as->urb->transfer_flags = uurb->flags |
++			(is_in ? URB_DIR_IN : URB_DIR_OUT);
+ 	as->urb->transfer_buffer_length = uurb->buffer_length;
+ 	as->urb->setup_packet = (unsigned char*)dr;
+ 	as->urb->start_frame = uurb->start_frame;
+@@ -1070,13 +1083,13 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 	as->uid = current->uid;
+ 	as->euid = current->euid;
+ 	security_task_getsecid(current, &as->secid);
+-	if (!(uurb->endpoint & USB_DIR_IN)) {
+-		if (copy_from_user(as->urb->transfer_buffer, uurb->buffer, as->urb->transfer_buffer_length)) {
++	if (!is_in) {
++		if (copy_from_user(as->urb->transfer_buffer, uurb->buffer,
++				as->urb->transfer_buffer_length)) {
+ 			free_async(as);
+ 			return -EFAULT;
+ 		}
+ 	}
+-	snoop(&as->urb->dev->dev, "submit urb\n");
+ 	snoop_urb(as->urb, as->userurb);
+         async_newpending(as);
+         if ((ret = usb_submit_urb(as->urb, GFP_KERNEL))) {
+@@ -1126,7 +1139,7 @@ static int processcompl(struct async *as, void __user * __user *arg)
+ 	if (put_user(urb->error_count, &userurb->error_count))
+ 		return -EFAULT;
+ 
+-	if (usb_pipeisoc(urb->pipe)) {
++	if (usb_endpoint_xfer_isoc(&urb->ep->desc)) {
+ 		for (i = 0; i < urb->number_of_packets; i++) {
+ 			if (put_user(urb->iso_frame_desc[i].actual_length,
+ 				     &userurb->iso_frame_desc[i].actual_length))
+@@ -1240,7 +1253,7 @@ static int processcompl_compat(struct async *as, void __user * __user *arg)
+ 	if (put_user(urb->error_count, &userurb->error_count))
+ 		return -EFAULT;
+ 
+-	if (usb_pipeisoc(urb->pipe)) {
++	if (usb_endpoint_xfer_isoc(&urb->ep->desc)) {
+ 		for (i = 0; i < urb->number_of_packets; i++) {
+ 			if (put_user(urb->iso_frame_desc[i].actual_length,
+ 				     &userurb->iso_frame_desc[i].actual_length))

commit 4326ed0be93574dac5b5e475713015159108bd88
+Author: Alan Stern 
+Date:   Mon Jul 30 17:08:43 2007 -0400
+
+    USB: address-0 handling during device initialization
+    
+    This patch (as947) changes the device initialization and enumeration
+    code in hub.c; now udev->devnum will be set to 0 while the device is
+    being accessed at address 0.  Until now this wasn't needed because the
+    address value was passed as part of urb->pipe; without that field the
+    device address must be stored elsewhere.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index c8a01f66df70..34be27a6cbb4 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1481,6 +1481,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
+ 		case 0:
+ 			/* TRSTRCY = 10 ms; plus some extra */
+ 			msleep(10 + 40);
++		  	udev->devnum = 0;	/* Device now at address 0 */
+ 			/* FALL THROUGH */
+ 		case -ENOTCONN:
+ 		case -ENODEV:
+@@ -2005,20 +2006,21 @@ static void ep0_reinit(struct usb_device *udev)
+ #define usb_sndaddr0pipe()	(PIPE_CONTROL << 30)
+ #define usb_rcvaddr0pipe()	((PIPE_CONTROL << 30) | USB_DIR_IN)
+ 
+-static int hub_set_address(struct usb_device *udev)
++static int hub_set_address(struct usb_device *udev, int devnum)
+ {
+ 	int retval;
+ 
+-	if (udev->devnum == 0)
++	if (devnum <= 1)
+ 		return -EINVAL;
+ 	if (udev->state == USB_STATE_ADDRESS)
+ 		return 0;
+ 	if (udev->state != USB_STATE_DEFAULT)
+ 		return -EINVAL;
+ 	retval = usb_control_msg(udev, usb_sndaddr0pipe(),
+-		USB_REQ_SET_ADDRESS, 0, udev->devnum, 0,
++		USB_REQ_SET_ADDRESS, 0, devnum, 0,
+ 		NULL, 0, USB_CTRL_SET_TIMEOUT);
+ 	if (retval == 0) {
++		udev->devnum = devnum;	/* Device now using proper address */
+ 		usb_set_device_state(udev, USB_STATE_ADDRESS);
+ 		ep0_reinit(udev);
+ 	}
+@@ -2045,6 +2047,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ 	unsigned		delay = HUB_SHORT_RESET_TIME;
+ 	enum usb_device_speed	oldspeed = udev->speed;
+ 	char 			*speed, *type;
++	int			devnum = udev->devnum;
+ 
+ 	/* root hub ports have a slightly longer reset period
+ 	 * (from USB 2.0 spec, section 7.1.7.5)
+@@ -2074,7 +2077,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ 		goto fail;
+ 	}
+ 	oldspeed = udev->speed;
+-  
++
+ 	/* USB 2.0 section 5.5.3 talks about ep0 maxpacket ...
+ 	 * it's fixed size except for full speed devices.
+ 	 * For Wireless USB devices, ep0 max packet is always 512 (tho
+@@ -2115,7 +2118,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ 	dev_info (&udev->dev,
+ 		  "%s %s speed %sUSB device using %s and address %d\n",
+ 		  (udev->config) ? "reset" : "new", speed, type,
+-		  udev->bus->controller->driver->name, udev->devnum);
++		  udev->bus->controller->driver->name, devnum);
+ 
+ 	/* Set up TT records, if needed  */
+ 	if (hdev->tt) {
+@@ -2202,7 +2205,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ 		}
+ 
+ 		for (j = 0; j < SET_ADDRESS_TRIES; ++j) {
+-			retval = hub_set_address(udev);
++			retval = hub_set_address(udev, devnum);
+ 			if (retval >= 0)
+ 				break;
+ 			msleep(200);
+@@ -2210,7 +2213,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ 		if (retval < 0) {
+ 			dev_err(&udev->dev,
+ 				"device not accepting address %d, error %d\n",
+-				udev->devnum, retval);
++				devnum, retval);
+ 			goto fail;
+ 		}
+  
+@@ -2263,8 +2266,10 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ 	retval = 0;
+ 
+ fail:
+-	if (retval)
++	if (retval) {
+ 		hub_port_disable(hub, port1, 0);
++		udev->devnum = devnum;	/* for disconnect processing */
++	}
+ 	mutex_unlock(&usb_address0_mutex);
+ 	return retval;
+ }
+diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
+index 1a64a6a850f3..1acca8696bcd 100644
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -284,9 +284,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 
+ 	if (!urb || urb->hcpriv || !urb->complete)
+ 		return -EINVAL;
+-	if (!(dev = urb->dev) ||
+-	    (dev->state < USB_STATE_DEFAULT) ||
+-	    (!dev->bus) || (dev->devnum <= 0))
++	if (!(dev = urb->dev) || dev->state < USB_STATE_DEFAULT)
+ 		return -ENODEV;
+ 	if (dev->bus->controller->power.power_state.event != PM_EVENT_ON
+ 			|| dev->state == USB_STATE_SUSPENDED)

commit 5e60a16139c2a48b9876b0ff910671eee5fb32ec
+Author: Alan Stern 
+Date:   Mon Jul 30 17:07:21 2007 -0400
+
+    USB: avoid using urb->pipe in usbcore
+    
+    This patch (as946) eliminates many of the uses of urb->pipe in
+    usbcore.  Unfortunately there will have to be a significant API
+    change, affecting all USB drivers, before we can remove it entirely.
+    This patch contents itself with changing only the interface to
+    usb_buffer_map_sg() and friends: The pipe argument is replaced with a
+    direction flag.  That can be done easily because those routines get
+    used in only one place.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index bcbaedc897d5..739c5e0aa3b8 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -635,9 +635,9 @@ static int rh_queue_status (struct usb_hcd *hcd, struct urb *urb)
+ 
+ static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb)
+ {
+-	if (usb_pipeint (urb->pipe))
++	if (usb_endpoint_xfer_int(&urb->ep->desc))
+ 		return rh_queue_status (hcd, urb);
+-	if (usb_pipecontrol (urb->pipe))
++	if (usb_endpoint_xfer_control(&urb->ep->desc))
+ 		return rh_call_control (hcd, urb);
+ 	return -EINVAL;
+ }
+@@ -651,7 +651,7 @@ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
+ {
+ 	unsigned long	flags;
+ 
+-	if (usb_pipeendpoint(urb->pipe) == 0) {	/* Control URB */
++	if (usb_endpoint_num(&urb->ep->desc) == 0) {	/* Control URB */
+ 		;	/* Do nothing */
+ 
+ 	} else {				/* Status URB */
+@@ -918,7 +918,7 @@ static void urb_unlink(struct usb_hcd *hcd, struct urb *urb)
+ 	spin_unlock_irqrestore(&hcd_urb_list_lock, flags);
+ 
+ 	if (hcd->self.uses_dma && !is_root_hub(urb->dev)) {
+-		if (usb_pipecontrol (urb->pipe)
++		if (usb_endpoint_xfer_control(&urb->ep->desc)
+ 			&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
+ 			dma_unmap_single (hcd->self.controller, urb->setup_dma,
+ 					sizeof (struct usb_ctrlrequest),
+@@ -1001,7 +1001,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+ 	 * unless it uses pio or talks to another transport.
+ 	 */
+ 	if (hcd->self.uses_dma) {
+-		if (usb_pipecontrol (urb->pipe)
++		if (usb_endpoint_xfer_control(&urb->ep->desc)
+ 			&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
+ 			urb->setup_dma = dma_map_single (
+ 					hcd->self.controller,
+@@ -1201,11 +1201,13 @@ void usb_hcd_endpoint_disable (struct usb_device *udev,
+ 	spin_lock(&hcd_urb_list_lock);
+ 	list_for_each_entry (urb, &ep->urb_list, urb_list) {
+ 		int	tmp;
++		int	is_in;
+ 
+ 		/* the urb may already have been unlinked */
+ 		if (urb->status != -EINPROGRESS)
+ 			continue;
+ 		usb_get_urb (urb);
++		is_in = usb_urb_dir_in(urb);
+ 		spin_unlock(&hcd_urb_list_lock);
+ 
+ 		spin_lock (&urb->lock);
+@@ -1216,19 +1218,25 @@ void usb_hcd_endpoint_disable (struct usb_device *udev,
+ 
+ 		/* kick hcd unless it's already returning this */
+ 		if (tmp == -EINPROGRESS) {
+-			tmp = urb->pipe;
+ 			unlink1 (hcd, urb);
+ 			dev_dbg (hcd->self.controller,
+-				"shutdown urb %p pipe %08x ep%d%s%s\n",
+-				urb, tmp, usb_pipeendpoint (tmp),
+-				(tmp & USB_DIR_IN) ? "in" : "out",
+-				({ char *s; \
+-				 switch (usb_pipetype (tmp)) { \
+-				 case PIPE_CONTROL:	s = ""; break; \
+-				 case PIPE_BULK:	s = "-bulk"; break; \
+-				 case PIPE_INTERRUPT:	s = "-intr"; break; \
+-				 default: 		s = "-iso"; break; \
+-				}; s;}));
++				"shutdown urb %p ep%d%s%s\n",
++				urb, usb_endpoint_num(&ep->desc),
++				is_in ? "in" : "out",
++				({	char *s;
++
++					switch (usb_endpoint_type(&ep->desc)) {
++					case USB_ENDPOINT_XFER_CONTROL:
++						s = ""; break;
++					case USB_ENDPOINT_XFER_BULK:
++						s = "-bulk"; break;
++					case USB_ENDPOINT_XFER_INT:
++						s = "-intr"; break;
++					default:
++				 		s = "-iso"; break;
++					};
++					s;
++				}));
+ 		}
+ 		usb_put_urb (urb);
+ 
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 0d618647758e..a26a7292b61a 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -59,8 +59,8 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
+ 		dev_dbg(&urb->dev->dev,
+ 			"%s timed out on ep%d%s len=%d/%d\n",
+ 			current->comm,
+-			usb_pipeendpoint(urb->pipe),
+-			usb_pipein(urb->pipe) ? "in" : "out",
++			usb_endpoint_num(&urb->ep->desc),
++			usb_urb_dir_in(urb) ? "in" : "out",
+ 			urb->actual_length,
+ 			urb->transfer_buffer_length);
+ 	} else
+@@ -250,7 +250,8 @@ static void sg_clean (struct usb_sg_request *io)
+ 		io->urbs = NULL;
+ 	}
+ 	if (io->dev->dev.dma_mask != NULL)
+-		usb_buffer_unmap_sg (io->dev, io->pipe, io->sg, io->nents);
++		usb_buffer_unmap_sg (io->dev, usb_pipein(io->pipe),
++				io->sg, io->nents);
+ 	io->dev = NULL;
+ }
+ 
+@@ -278,8 +279,8 @@ static void sg_complete (struct urb *urb)
+ 		dev_err (io->dev->bus->controller,
+ 			"dev %s ep%d%s scatterlist error %d/%d\n",
+ 			io->dev->devpath,
+-			usb_pipeendpoint (urb->pipe),
+-			usb_pipein (urb->pipe) ? "in" : "out",
++			usb_endpoint_num(&urb->ep->desc),
++			usb_urb_dir_in(urb) ? "in" : "out",
+ 			status, io->status);
+ 		// BUG ();
+ 	}
+@@ -379,7 +380,8 @@ int usb_sg_init (
+ 	 */
+ 	dma = (dev->dev.dma_mask != NULL);
+ 	if (dma)
+-		io->entries = usb_buffer_map_sg (dev, pipe, sg, nents);
++		io->entries = usb_buffer_map_sg(dev, usb_pipein(pipe),
++				sg, nents);
+ 	else
+ 		io->entries = nents;
+ 
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index d3c68d8eafb2..67e2e582e463 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -748,7 +748,7 @@ void usb_buffer_unmap(struct urb *urb)
+ /**
+  * usb_buffer_map_sg - create scatterlist DMA mapping(s) for an endpoint
+  * @dev: device to which the scatterlist will be mapped
+- * @pipe: endpoint defining the mapping direction
++ * @is_in: mapping transfer direction
+  * @sg: the scatterlist to map
+  * @nents: the number of entries in the scatterlist
+  *
+@@ -771,14 +771,13 @@ void usb_buffer_unmap(struct urb *urb)
+  *
+  * Reverse the effect of this call with usb_buffer_unmap_sg().
+  */
+-int usb_buffer_map_sg(const struct usb_device *dev, unsigned pipe,
++int usb_buffer_map_sg(const struct usb_device *dev, int is_in,
+ 		      struct scatterlist *sg, int nents)
+ {
+ 	struct usb_bus		*bus;
+ 	struct device		*controller;
+ 
+ 	if (!dev
+-			|| usb_pipecontrol(pipe)
+ 			|| !(bus = dev->bus)
+ 			|| !(controller = bus->controller)
+ 			|| !controller->dma_mask)
+@@ -786,7 +785,7 @@ int usb_buffer_map_sg(const struct usb_device *dev, unsigned pipe,
+ 
+ 	// FIXME generic api broken like pci, can't report errors
+ 	return dma_map_sg(controller, sg, nents,
+-			usb_pipein(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
++			is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
+ }
+ 
+ /* XXX DISABLED, no users currently.  If you wish to re-enable this
+@@ -799,14 +798,14 @@ int usb_buffer_map_sg(const struct usb_device *dev, unsigned pipe,
+ /**
+  * usb_buffer_dmasync_sg - synchronize DMA and CPU view of scatterlist buffer(s)
+  * @dev: device to which the scatterlist will be mapped
+- * @pipe: endpoint defining the mapping direction
++ * @is_in: mapping transfer direction
+  * @sg: the scatterlist to synchronize
+  * @n_hw_ents: the positive return value from usb_buffer_map_sg
+  *
+  * Use this when you are re-using a scatterlist's data buffers for
+  * another USB request.
+  */
+-void usb_buffer_dmasync_sg(const struct usb_device *dev, unsigned pipe,
++void usb_buffer_dmasync_sg(const struct usb_device *dev, int is_in,
+ 			   struct scatterlist *sg, int n_hw_ents)
+ {
+ 	struct usb_bus		*bus;
+@@ -819,20 +818,20 @@ void usb_buffer_dmasync_sg(const struct usb_device *dev, unsigned pipe,
+ 		return;
+ 
+ 	dma_sync_sg(controller, sg, n_hw_ents,
+-			usb_pipein(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
++			is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
+ }
+ #endif
+ 
+ /**
+  * usb_buffer_unmap_sg - free DMA mapping(s) for a scatterlist
+  * @dev: device to which the scatterlist will be mapped
+- * @pipe: endpoint defining the mapping direction
++ * @is_in: mapping transfer direction
+  * @sg: the scatterlist to unmap
+  * @n_hw_ents: the positive return value from usb_buffer_map_sg
+  *
+  * Reverses the effect of usb_buffer_map_sg().
+  */
+-void usb_buffer_unmap_sg(const struct usb_device *dev, unsigned pipe,
++void usb_buffer_unmap_sg(const struct usb_device *dev, int is_in,
+ 			 struct scatterlist *sg, int n_hw_ents)
+ {
+ 	struct usb_bus		*bus;
+@@ -845,7 +844,7 @@ void usb_buffer_unmap_sg(const struct usb_device *dev, unsigned pipe,
+ 		return;
+ 
+ 	dma_unmap_sg(controller, sg, n_hw_ents,
+-			usb_pipein(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
++			is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
+ }
+ 
+ /* format to disable USB on kernel command line is: nousb */
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 9d08f5a5ba76..019ae963a9fe 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -1422,13 +1422,13 @@ void usb_buffer_unmap (struct urb *urb);
+ #endif
+ 
+ struct scatterlist;
+-int usb_buffer_map_sg(const struct usb_device *dev, unsigned pipe,
++int usb_buffer_map_sg(const struct usb_device *dev, int is_in,
+ 		      struct scatterlist *sg, int nents);
+ #if 0
+-void usb_buffer_dmasync_sg(const struct usb_device *dev, unsigned pipe,
++void usb_buffer_dmasync_sg(const struct usb_device *dev, int is_in,
+ 			   struct scatterlist *sg, int n_hw_ents);
+ #endif
+-void usb_buffer_unmap_sg(const struct usb_device *dev, unsigned pipe,
++void usb_buffer_unmap_sg(const struct usb_device *dev, int is_in,
+ 			 struct scatterlist *sg, int n_hw_ents);
+ 
+ /*-------------------------------------------------------------------*

commit fea3409112a93581db18da4c4332c8bf8d68af6b
+Author: Alan Stern 
+Date:   Mon Jul 30 17:06:16 2007 -0400
+
+    USB: add direction bit to urb->transfer_flags
+    
+    This patch (as945) adds a bit to urb->transfer_flags for recording the
+    direction of the URB.  The bit is set/cleared automatically in
+    usb_submit_urb() so drivers don't have to worry about it (although as
+    a result, it isn't valid until the URB has been submitted).  Inline
+    routines are added for easily checking an URB's direction.  They
+    replace calls to usb_pipein in the DMA-mapping parts of hcd.c.
+    
+    For non-control endpoints, the direction is determined directly from
+    the endpoint descriptor.  However control endpoints are
+    bi-directional; for them the direction is determined from the
+    bRequestType byte and the wLength value in the setup packet.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index cc5b1d3c3680..bcbaedc897d5 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -928,7 +928,7 @@ static void urb_unlink(struct usb_hcd *hcd, struct urb *urb)
+ 			dma_unmap_single (hcd->self.controller,
+ 					urb->transfer_dma,
+ 					urb->transfer_buffer_length,
+-					usb_pipein (urb->pipe)
++					usb_urb_dir_in(urb)
+ 					    ? DMA_FROM_DEVICE
+ 					    : DMA_TO_DEVICE);
+ 	}
+@@ -1014,7 +1014,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+ 					hcd->self.controller,
+ 					urb->transfer_buffer,
+ 					urb->transfer_buffer_length,
+-					usb_pipein (urb->pipe)
++					usb_urb_dir_in(urb)
+ 					    ? DMA_FROM_DEVICE
+ 					    : DMA_TO_DEVICE);
+ 	}
+diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
+index ff53acb4fab2..1a64a6a850f3 100644
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -309,7 +309,21 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 	 * and don't need to duplicate tests
+ 	 */
+ 	xfertype = usb_endpoint_type(&ep->desc);
+-	is_out = usb_pipeout(urb->pipe);
++	if (xfertype == USB_ENDPOINT_XFER_CONTROL) {
++		struct usb_ctrlrequest *setup =
++				(struct usb_ctrlrequest *) urb->setup_packet;
++
++		if (!setup)
++			return -ENOEXEC;
++		is_out = !(setup->bRequestType & USB_DIR_IN) ||
++				!setup->wLength;
++	} else {
++		is_out = usb_endpoint_dir_out(&ep->desc);
++	}
++
++	/* Cache the direction for later use */
++	urb->transfer_flags = (urb->transfer_flags & ~URB_DIR_MASK) |
++			(is_out ? URB_DIR_OUT : URB_DIR_IN);
+ 
+ 	if (xfertype != USB_ENDPOINT_XFER_CONTROL &&
+ 			dev->state < USB_STATE_CONFIGURED)
+@@ -363,7 +377,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 
+ 	/* enforce simple/standard policy */
+ 	allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP |
+-			URB_NO_INTERRUPT);
++			URB_NO_INTERRUPT | URB_DIR_MASK);
+ 	switch (xfertype) {
+ 	case USB_ENDPOINT_XFER_BULK:
+ 		if (is_out)
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 818a1b4f737a..9d08f5a5ba76 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -1021,6 +1021,8 @@ extern int usb_disabled(void);
+ 
+ /*
+  * urb->transfer_flags:
++ *
++ * Note: URB_DIR_IN/OUT is automatically set in usb_submit_urb().
+  */
+ #define URB_SHORT_NOT_OK	0x0001	/* report short reads as errors */
+ #define URB_ISO_ASAP		0x0002	/* iso-only, urb->start_frame
+@@ -1033,6 +1035,10 @@ extern int usb_disabled(void);
+ 					 * needed */
+ #define URB_FREE_BUFFER		0x0100	/* Free transfer buffer with the URB */
+ 
++#define URB_DIR_IN		0x0200	/* Transfer from device to host */
++#define URB_DIR_OUT		0
++#define URB_DIR_MASK		URB_DIR_IN
++
+ struct usb_iso_packet_descriptor {
+ 	unsigned int offset;
+ 	unsigned int length;		/* expected length */
+@@ -1380,6 +1386,30 @@ extern void usb_unanchor_urb(struct urb *urb);
+ extern int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor,
+ 					 unsigned int timeout);
+ 
++/**
++ * usb_urb_dir_in - check if an URB describes an IN transfer
++ * @urb: URB to be checked
++ *
++ * Returns 1 if @urb describes an IN transfer (device-to-host),
++ * otherwise 0.
++ */
++static inline int usb_urb_dir_in(struct urb *urb)
++{
++	return (urb->transfer_flags & URB_DIR_MASK) != URB_DIR_OUT;
++}
++
++/**
++ * usb_urb_dir_out - check if an URB describes an OUT transfer
++ * @urb: URB to be checked
++ *
++ * Returns 1 if @urb describes an OUT transfer (host-to-device),
++ * otherwise 0.
++ */
++static inline int usb_urb_dir_out(struct urb *urb)
++{
++	return (urb->transfer_flags & URB_DIR_MASK) == URB_DIR_OUT;
++}
++
+ void *usb_buffer_alloc (struct usb_device *dev, size_t size,
+ 	gfp_t mem_flags, dma_addr_t *dma);
+ void usb_buffer_free (struct usb_device *dev, size_t size,

commit bdd016ba64d909329cb4bacacc8443901c00e112
+Author: Alan Stern 
+Date:   Mon Jul 30 17:05:22 2007 -0400
+
+    USB: add ep->enable
+    
+    This patch (as944) adds an explicit "enabled" field to the
+    usb_host_endpoint structure and uses it in place of the current
+    mechanism.  This is merely a time-space tradeoff; it makes checking
+    whether URBs may be submitted to an endpoint simpler.  The existing
+    mechanism is efficient when converting urb->pipe to an endpoint
+    pointer, but it's not so efficient when urb->ep is used instead.
+    
+    As a side effect, the procedure for enabling an endpoint is now a
+    little more complicated.  The ad-hoc inline code in usb.c and hub.c
+    for enabling ep0 is now replaced with calls to usb_enable_endpoint,
+    which is no longer static.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index fb82c500caf4..cc5b1d3c3680 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -943,7 +943,6 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+ {
+ 	int			status;
+ 	struct usb_hcd		*hcd = bus_to_hcd(urb->dev->bus);
+-	struct usb_host_endpoint *ep;
+ 	unsigned long		flags;
+ 
+ 	if (!hcd)
+@@ -960,9 +959,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+ 	// FIXME:  verify that quiescing hc works right (RH cleans up)
+ 
+ 	spin_lock_irqsave(&hcd_urb_list_lock, flags);
+-	ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out)
+-			[usb_pipeendpoint(urb->pipe)];
+-	if (unlikely(ep != urb->ep))
++	if (unlikely(!urb->ep->enabled))
+ 		status = -ENOENT;
+ 	else if (unlikely (urb->reject))
+ 		status = -EPERM;
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index f7b337feb3ea..c8a01f66df70 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1999,7 +1999,7 @@ static void ep0_reinit(struct usb_device *udev)
+ {
+ 	usb_disable_endpoint(udev, 0 + USB_DIR_IN);
+ 	usb_disable_endpoint(udev, 0 + USB_DIR_OUT);
+-	udev->ep_in[0] = udev->ep_out[0] = &udev->ep0;
++	usb_enable_endpoint(udev, &udev->ep0);
+ }
+ 
+ #define usb_sndaddr0pipe()	(PIPE_CONTROL << 30)
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index d8f7b089a8f0..0d618647758e 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1013,8 +1013,10 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr)
+ 		ep = dev->ep_in[epnum];
+ 		dev->ep_in[epnum] = NULL;
+ 	}
+-	if (ep && dev->bus)
++	if (ep) {
++		ep->enabled = 0;
+ 		usb_hcd_endpoint_disable(dev, ep);
++	}
+ }
+ 
+ /**
+@@ -1096,23 +1098,21 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
+  * Resets the endpoint toggle, and sets dev->ep_{in,out} pointers.
+  * For control endpoints, both the input and output sides are handled.
+  */
+-static void
+-usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep)
++void usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep)
+ {
+-	unsigned int epaddr = ep->desc.bEndpointAddress;
+-	unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;
+-	int is_control;
++	int epnum = usb_endpoint_num(&ep->desc);
++	int is_out = usb_endpoint_dir_out(&ep->desc);
++	int is_control = usb_endpoint_xfer_control(&ep->desc);
+ 
+-	is_control = ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+-			== USB_ENDPOINT_XFER_CONTROL);
+-	if (usb_endpoint_out(epaddr) || is_control) {
++	if (is_out || is_control) {
+ 		usb_settoggle(dev, epnum, 1, 0);
+ 		dev->ep_out[epnum] = ep;
+ 	}
+-	if (!usb_endpoint_out(epaddr) || is_control) {
++	if (!is_out || is_control) {
+ 		usb_settoggle(dev, epnum, 0, 0);
+ 		dev->ep_in[epnum] = ep;
+ 	}
++	ep->enabled = 1;
+ }
+ 
+ /*
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 0fee5c66fd64..d3c68d8eafb2 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -260,7 +260,7 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
+ 	dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;
+ 	dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;
+ 	/* ep0 maxpacket comes later, from device descriptor */
+-	dev->ep_in[0] = dev->ep_out[0] = &dev->ep0;
++	usb_enable_endpoint(dev, &dev->ep0);
+ 
+ 	/* Save readable and stable topology id, distinguishing devices
+ 	 * by location for diagnostics, tools, driver model, etc.  The
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index ad5fa0338f49..cde6e52b84fe 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -8,6 +8,8 @@ extern int usb_create_ep_files(struct device *parent, struct usb_host_endpoint *
+ 				struct usb_device *udev);
+ extern void usb_remove_ep_files(struct usb_host_endpoint *endpoint);
+ 
++extern void usb_enable_endpoint(struct usb_device *dev,
++		struct usb_host_endpoint *ep);
+ extern void usb_disable_endpoint (struct usb_device *dev, unsigned int epaddr);
+ extern void usb_disable_interface (struct usb_device *dev,
+ 		struct usb_interface *intf);
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 105e3e9362d0..818a1b4f737a 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -52,6 +52,7 @@ struct ep_device;
+  * @ep_dev: ep_device for sysfs info
+  * @extra: descriptors following this endpoint in the configuration
+  * @extralen: how many bytes of "extra" are valid
++ * @enabled: URBs may be submitted to this endpoint
+  *
+  * USB requests are always queued to a given endpoint, identified by a
+  * descriptor within an active interface in a given USB configuration.
+@@ -64,6 +65,7 @@ struct usb_host_endpoint {
+ 
+ 	unsigned char *extra;   /* Extra descriptors */
+ 	int extralen;
++	int enabled;
+ };
+ 
+ /* host-side wrapper for one interface setting's parsed descriptors */

commit 5b653c79c04c6b152b8dc7d18f8c8a7f77f4b235
+Author: Alan Stern 
+Date:   Mon Jul 30 17:04:37 2007 -0400
+
+    USB: add urb->ep
+    
+    This patch (as943) prepares the way for eliminating urb->pipe by
+    introducing an endpoint pointer into struct urb.  For now urb->ep
+    is set by usb_submit_urb() from the pipe value; eventually drivers
+    will set it themselves and we will remove urb->pipe completely.
+    
+    The patch also adds new inline routines to retrieve an endpoint
+    descriptor's number and transfer type, essentially as replacements for
+    usb_pipeendpoint and usb_pipetype.
+    
+    usb_submit_urb(), usb_hcd_submit_urb(), and usb_hcd_unlink_urb() are
+    converted to use the new field and new routines.  Other parts of
+    usbcore will be converted in later patches.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 42ef1d5f6c8a..fb82c500caf4 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -962,14 +962,14 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+ 	spin_lock_irqsave(&hcd_urb_list_lock, flags);
+ 	ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out)
+ 			[usb_pipeendpoint(urb->pipe)];
+-	if (unlikely (!ep))
++	if (unlikely(ep != urb->ep))
+ 		status = -ENOENT;
+ 	else if (unlikely (urb->reject))
+ 		status = -EPERM;
+ 	else switch (hcd->state) {
+ 	case HC_STATE_RUNNING:
+ 	case HC_STATE_RESUMING:
+-		list_add_tail (&urb->urb_list, &ep->urb_list);
++		list_add_tail (&urb->urb_list, &urb->ep->urb_list);
+ 		status = 0;
+ 		break;
+ 	default:
+@@ -1022,7 +1022,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+ 					    : DMA_TO_DEVICE);
+ 	}
+ 
+-	status = hcd->driver->urb_enqueue (hcd, ep, urb, mem_flags);
++	status = hcd->driver->urb_enqueue (hcd, urb->ep, urb, mem_flags);
+ done:
+ 	if (unlikely (status)) {
+ 		urb_unlink(hcd, urb);
+@@ -1071,7 +1071,6 @@ unlink1 (struct usb_hcd *hcd, struct urb *urb)
+  */
+ int usb_hcd_unlink_urb (struct urb *urb, int status)
+ {
+-	struct usb_host_endpoint	*ep;
+ 	struct usb_hcd			*hcd = NULL;
+ 	struct device			*sys = NULL;
+ 	unsigned long			flags;
+@@ -1082,10 +1081,6 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
+ 		return -EINVAL;
+ 	if (!urb->dev || !urb->dev->bus)
+ 		return -ENODEV;
+-	ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out)
+-			[usb_pipeendpoint(urb->pipe)];
+-	if (!ep)
+-		return -ENODEV;
+ 
+ 	/*
+ 	 * we contend for urb->status with the hcd core,
+@@ -1109,7 +1104,7 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
+ 	}
+ 
+ 	/* insist the urb is still queued */
+-	list_for_each(tmp, &ep->urb_list) {
++	list_for_each(tmp, &urb->ep->urb_list) {
+ 		if (tmp == &urb->urb_list)
+ 			break;
+ 	}
+diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
+index be630228461c..ff53acb4fab2 100644
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -277,9 +277,10 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
+  */
+ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ {
+-	int			pipe, temp, max;
+-	struct usb_device	*dev;
+-	int			is_out;
++	int				xfertype, max;
++	struct usb_device		*dev;
++	struct usb_host_endpoint	*ep;
++	int				is_out;
+ 
+ 	if (!urb || urb->hcpriv || !urb->complete)
+ 		return -EINVAL;
+@@ -291,30 +292,34 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 			|| dev->state == USB_STATE_SUSPENDED)
+ 		return -EHOSTUNREACH;
+ 
++	/* For now, get the endpoint from the pipe.  Eventually drivers
++	 * will be required to set urb->ep directly and we will eliminate
++	 * urb->pipe.
++	 */
++	ep = (usb_pipein(urb->pipe) ? dev->ep_in : dev->ep_out)
++			[usb_pipeendpoint(urb->pipe)];
++	if (!ep)
++		return -ENOENT;
++
++	urb->ep = ep;
+ 	urb->status = -EINPROGRESS;
+ 	urb->actual_length = 0;
+ 
+ 	/* Lots of sanity checks, so HCDs can rely on clean data
+ 	 * and don't need to duplicate tests
+ 	 */
+-	pipe = urb->pipe;
+-	temp = usb_pipetype(pipe);
+-	is_out = usb_pipeout(pipe);
++	xfertype = usb_endpoint_type(&ep->desc);
++	is_out = usb_pipeout(urb->pipe);
+ 
+-	if (!usb_pipecontrol(pipe) && dev->state < USB_STATE_CONFIGURED)
++	if (xfertype != USB_ENDPOINT_XFER_CONTROL &&
++			dev->state < USB_STATE_CONFIGURED)
+ 		return -ENODEV;
+ 
+-	/* FIXME there should be a sharable lock protecting us against
+-	 * config/altsetting changes and disconnects, kicking in here.
+-	 * (here == before maxpacket, and eventually endpoint type,
+-	 * checks get made.)
+-	 */
+-
+-	max = usb_maxpacket(dev, pipe, is_out);
++	max = le16_to_cpu(ep->desc.wMaxPacketSize);
+ 	if (max <= 0) {
+ 		dev_dbg(&dev->dev,
+ 			"bogus endpoint ep%d%s in %s (bad maxpacket %d)\n",
+-			usb_pipeendpoint(pipe), is_out ? "out" : "in",
++			usb_endpoint_num(&ep->desc), is_out ? "out" : "in",
+ 			__FUNCTION__, max);
+ 		return -EMSGSIZE;
+ 	}
+@@ -323,7 +328,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 	 * but drivers only control those sizes for ISO.
+ 	 * while we're checking, initialize return status.
+ 	 */
+-	if (temp == PIPE_ISOCHRONOUS) {
++	if (xfertype == USB_ENDPOINT_XFER_ISOC) {
+ 		int	n, len;
+ 
+ 		/* "high bandwidth" mode, 1-3 packets/uframe? */
+@@ -359,19 +364,19 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 	/* enforce simple/standard policy */
+ 	allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP |
+ 			URB_NO_INTERRUPT);
+-	switch (temp) {
+-	case PIPE_BULK:
++	switch (xfertype) {
++	case USB_ENDPOINT_XFER_BULK:
+ 		if (is_out)
+ 			allowed |= URB_ZERO_PACKET;
+ 		/* FALLTHROUGH */
+-	case PIPE_CONTROL:
++	case USB_ENDPOINT_XFER_CONTROL:
+ 		allowed |= URB_NO_FSBR;	/* only affects UHCI */
+ 		/* FALLTHROUGH */
+ 	default:			/* all non-iso endpoints */
+ 		if (!is_out)
+ 			allowed |= URB_SHORT_NOT_OK;
+ 		break;
+-	case PIPE_ISOCHRONOUS:
++	case USB_ENDPOINT_XFER_ISOC:
+ 		allowed |= URB_ISO_ASAP;
+ 		break;
+ 	}
+@@ -393,9 +398,9 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 	 * supports different values... this uses EHCI/UHCI defaults (and
+ 	 * EHCI can use smaller non-default values).
+ 	 */
+-	switch (temp) {
+-	case PIPE_ISOCHRONOUS:
+-	case PIPE_INTERRUPT:
++	switch (xfertype) {
++	case USB_ENDPOINT_XFER_ISOC:
++	case USB_ENDPOINT_XFER_INT:
+ 		/* too small? */
+ 		if (urb->interval <= 0)
+ 			return -EINVAL;
+@@ -405,29 +410,29 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 			// NOTE usb handles 2^15
+ 			if (urb->interval > (1024 * 8))
+ 				urb->interval = 1024 * 8;
+-			temp = 1024 * 8;
++			max = 1024 * 8;
+ 			break;
+ 		case USB_SPEED_FULL:	/* units are frames/msec */
+ 		case USB_SPEED_LOW:
+-			if (temp == PIPE_INTERRUPT) {
++			if (xfertype == USB_ENDPOINT_XFER_INT) {
+ 				if (urb->interval > 255)
+ 					return -EINVAL;
+ 				// NOTE ohci only handles up to 32
+-				temp = 128;
++				max = 128;
+ 			} else {
+ 				if (urb->interval > 1024)
+ 					urb->interval = 1024;
+ 				// NOTE usb and ohci handle up to 2^15
+-				temp = 1024;
++				max = 1024;
+ 			}
+ 			break;
+ 		default:
+ 			return -EINVAL;
+ 		}
+ 		/* power of two? */
+-		while (temp > urb->interval)
+-			temp >>= 1;
+-		urb->interval = temp;
++		while (max > urb->interval)
++			max >>= 1;
++		urb->interval = max;
+ 	}
+ 
+ 	return usb_hcd_submit_urb(urb, mem_flags);
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 4f33a58fa9d1..105e3e9362d0 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -554,6 +554,29 @@ static inline int usb_make_path (struct usb_device *dev, char *buf,
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++/**
++ * usb_endpoint_num - get the endpoint's number
++ * @epd: endpoint to be checked
++ *
++ * Returns @epd's number: 0 to 15.
++ */
++static inline int usb_endpoint_num(const struct usb_endpoint_descriptor *epd)
++{
++	return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
++}
++
++/**
++ * usb_endpoint_type - get the endpoint's transfer type
++ * @epd: endpoint to be checked
++ *
++ * Returns one of USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT} according
++ * to @epd's transfer type.
++ */
++static inline int usb_endpoint_type(const struct usb_endpoint_descriptor *epd)
++{
++	return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
++}
++
+ /**
+  * usb_endpoint_dir_in - check if the endpoint has IN direction
+  * @epd: endpoint to be checked
+@@ -1037,6 +1060,8 @@ typedef void (*usb_complete_t)(struct urb *);
+  * @urb_list: For use by current owner of the URB.
+  * @anchor_list: membership in the list of an anchor
+  * @anchor: to anchor URBs to a common mooring
++ * @ep: Points to the endpoint's data structure.  Will eventually
++ *	replace @pipe.
+  * @pipe: Holds endpoint number, direction, type, and more.
+  *	Create these values with the eight macros available;
+  *	usb_{snd,rcv}TYPEpipe(dev,endpoint), where the TYPE is "ctrl"
+@@ -1212,6 +1237,7 @@ struct urb
+ 	struct list_head anchor_list;	/* the URB may be anchored by the driver */
+ 	struct usb_anchor *anchor;
+ 	struct usb_device *dev; 	/* (in) pointer to associated device */
++	struct usb_host_endpoint *ep;	/* (internal) pointer to endpoint struct */
+ 	unsigned int pipe;		/* (in) pipe information */
+ 	int status;			/* (return) non-ISO status */
+ 	unsigned int transfer_flags;	/* (in) URB_SHORT_NOT_OK | ...*/

commit cd59abfcc441b2abb4cf2cd62c1eb0f02a60e8dd
+Author: Alan Stern 
+Date:   Fri Sep 21 15:36:56 2007 -0400
+
+    PM: merge device power-management source files
+    
+    This patch (as993) merges the suspend.c and resume.c files in
+    drivers/base/power into main.c, making some public symbols private.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Rafael J. Wysocki 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile
+index 9caeaea753a3..a803733c839e 100644
+--- a/drivers/base/power/Makefile
++++ b/drivers/base/power/Makefile
+@@ -1,5 +1,5 @@
+ obj-y			:= shutdown.o
+-obj-$(CONFIG_PM_SLEEP)	+= main.o suspend.o resume.o sysfs.o
++obj-$(CONFIG_PM_SLEEP)	+= main.o sysfs.o
+ obj-$(CONFIG_PM_TRACE)	+= trace.o
+ 
+ ifeq ($(CONFIG_DEBUG_DRIVER),y)
+diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
+index eb9f38d0aa58..0ab4ab21f564 100644
+--- a/drivers/base/power/main.c
++++ b/drivers/base/power/main.c
+@@ -20,19 +20,24 @@
+  */
+ 
+ #include 
++#include 
+ #include 
++#include 
++#include 
+ 
++#include "../base.h"
+ #include "power.h"
+ 
+ LIST_HEAD(dpm_active);
+-LIST_HEAD(dpm_off);
+-LIST_HEAD(dpm_off_irq);
++static LIST_HEAD(dpm_off);
++static LIST_HEAD(dpm_off_irq);
+ 
+-DEFINE_MUTEX(dpm_mtx);
+-DEFINE_MUTEX(dpm_list_mtx);
++static DEFINE_MUTEX(dpm_mtx);
++static DEFINE_MUTEX(dpm_list_mtx);
+ 
+ int (*platform_enable_wakeup)(struct device *dev, int is_on);
+ 
++
+ int device_pm_add(struct device *dev)
+ {
+ 	int error;
+@@ -61,3 +66,334 @@ void device_pm_remove(struct device *dev)
+ }
+ 
+ 
++/*------------------------- Resume routines -------------------------*/
++
++/**
++ *	resume_device - Restore state for one device.
++ *	@dev:	Device.
++ *
++ */
++
++static int resume_device(struct device * dev)
++{
++	int error = 0;
++
++	TRACE_DEVICE(dev);
++	TRACE_RESUME(0);
++
++	down(&dev->sem);
++
++	if (dev->bus && dev->bus->resume) {
++		dev_dbg(dev,"resuming\n");
++		error = dev->bus->resume(dev);
++	}
++
++	if (!error && dev->type && dev->type->resume) {
++		dev_dbg(dev,"resuming\n");
++		error = dev->type->resume(dev);
++	}
++
++	if (!error && dev->class && dev->class->resume) {
++		dev_dbg(dev,"class resume\n");
++		error = dev->class->resume(dev);
++	}
++
++	up(&dev->sem);
++
++	TRACE_RESUME(error);
++	return error;
++}
++
++
++static int resume_device_early(struct device * dev)
++{
++	int error = 0;
++
++	TRACE_DEVICE(dev);
++	TRACE_RESUME(0);
++	if (dev->bus && dev->bus->resume_early) {
++		dev_dbg(dev,"EARLY resume\n");
++		error = dev->bus->resume_early(dev);
++	}
++	TRACE_RESUME(error);
++	return error;
++}
++
++/*
++ * Resume the devices that have either not gone through
++ * the late suspend, or that did go through it but also
++ * went through the early resume
++ */
++static void dpm_resume(void)
++{
++	mutex_lock(&dpm_list_mtx);
++	while(!list_empty(&dpm_off)) {
++		struct list_head * entry = dpm_off.next;
++		struct device * dev = to_device(entry);
++
++		get_device(dev);
++		list_move_tail(entry, &dpm_active);
++
++		mutex_unlock(&dpm_list_mtx);
++		resume_device(dev);
++		mutex_lock(&dpm_list_mtx);
++		put_device(dev);
++	}
++	mutex_unlock(&dpm_list_mtx);
++}
++
++
++/**
++ *	device_resume - Restore state of each device in system.
++ *
++ *	Walk the dpm_off list, remove each entry, resume the device,
++ *	then add it to the dpm_active list.
++ */
++
++void device_resume(void)
++{
++	might_sleep();
++	mutex_lock(&dpm_mtx);
++	dpm_resume();
++	mutex_unlock(&dpm_mtx);
++}
++
++EXPORT_SYMBOL_GPL(device_resume);
++
++
++/**
++ *	dpm_power_up - Power on some devices.
++ *
++ *	Walk the dpm_off_irq list and power each device up. This
++ *	is used for devices that required they be powered down with
++ *	interrupts disabled. As devices are powered on, they are moved
++ *	to the dpm_active list.
++ *
++ *	Interrupts must be disabled when calling this.
++ */
++
++static void dpm_power_up(void)
++{
++	while(!list_empty(&dpm_off_irq)) {
++		struct list_head * entry = dpm_off_irq.next;
++		struct device * dev = to_device(entry);
++
++		list_move_tail(entry, &dpm_off);
++		resume_device_early(dev);
++	}
++}
++
++
++/**
++ *	device_power_up - Turn on all devices that need special attention.
++ *
++ *	Power on system devices then devices that required we shut them down
++ *	with interrupts disabled.
++ *	Called with interrupts disabled.
++ */
++
++void device_power_up(void)
++{
++	sysdev_resume();
++	dpm_power_up();
++}
++
++EXPORT_SYMBOL_GPL(device_power_up);
++
++
++/*------------------------- Suspend routines -------------------------*/
++
++/*
++ * The entries in the dpm_active list are in a depth first order, simply
++ * because children are guaranteed to be discovered after parents, and
++ * are inserted at the back of the list on discovery.
++ *
++ * All list on the suspend path are done in reverse order, so we operate
++ * on the leaves of the device tree (or forests, depending on how you want
++ * to look at it ;) first. As nodes are removed from the back of the list,
++ * they are inserted into the front of their destintation lists.
++ *
++ * Things are the reverse on the resume path - iterations are done in
++ * forward order, and nodes are inserted at the back of their destination
++ * lists. This way, the ancestors will be accessed before their descendents.
++ */
++
++static inline char *suspend_verb(u32 event)
++{
++	switch (event) {
++	case PM_EVENT_SUSPEND:	return "suspend";
++	case PM_EVENT_FREEZE:	return "freeze";
++	case PM_EVENT_PRETHAW:	return "prethaw";
++	default:		return "(unknown suspend event)";
++	}
++}
++
++
++static void
++suspend_device_dbg(struct device *dev, pm_message_t state, char *info)
++{
++	dev_dbg(dev, "%s%s%s\n", info, suspend_verb(state.event),
++		((state.event == PM_EVENT_SUSPEND) && device_may_wakeup(dev)) ?
++		", may wakeup" : "");
++}
++
++/**
++ *	suspend_device - Save state of one device.
++ *	@dev:	Device.
++ *	@state:	Power state device is entering.
++ */
++
++static int suspend_device(struct device * dev, pm_message_t state)
++{
++	int error = 0;
++
++	down(&dev->sem);
++	if (dev->power.power_state.event) {
++		dev_dbg(dev, "PM: suspend %d-->%d\n",
++			dev->power.power_state.event, state.event);
++	}
++
++	if (dev->class && dev->class->suspend) {
++		suspend_device_dbg(dev, state, "class ");
++		error = dev->class->suspend(dev, state);
++		suspend_report_result(dev->class->suspend, error);
++	}
++
++	if (!error && dev->type && dev->type->suspend) {
++		suspend_device_dbg(dev, state, "type ");
++		error = dev->type->suspend(dev, state);
++		suspend_report_result(dev->type->suspend, error);
++	}
++
++	if (!error && dev->bus && dev->bus->suspend) {
++		suspend_device_dbg(dev, state, "");
++		error = dev->bus->suspend(dev, state);
++		suspend_report_result(dev->bus->suspend, error);
++	}
++	up(&dev->sem);
++	return error;
++}
++
++
++/*
++ * This is called with interrupts off, only a single CPU
++ * running. We can't acquire a mutex or semaphore (and we don't
++ * need the protection)
++ */
++static int suspend_device_late(struct device *dev, pm_message_t state)
++{
++	int error = 0;
++
++	if (dev->bus && dev->bus->suspend_late) {
++		suspend_device_dbg(dev, state, "LATE ");
++		error = dev->bus->suspend_late(dev, state);
++		suspend_report_result(dev->bus->suspend_late, error);
++	}
++	return error;
++}
++
++/**
++ *	device_suspend - Save state and stop all devices in system.
++ *	@state:		Power state to put each device in.
++ *
++ *	Walk the dpm_active list, call ->suspend() for each device, and move
++ *	it to the dpm_off list.
++ *
++ *	(For historical reasons, if it returns -EAGAIN, that used to mean
++ *	that the device would be called again with interrupts disabled.
++ *	These days, we use the "suspend_late()" callback for that, so we
++ *	print a warning and consider it an error).
++ *
++ *	If we get a different error, try and back out.
++ *
++ *	If we hit a failure with any of the devices, call device_resume()
++ *	above to bring the suspended devices back to life.
++ *
++ */
++
++int device_suspend(pm_message_t state)
++{
++	int error = 0;
++
++	might_sleep();
++	mutex_lock(&dpm_mtx);
++	mutex_lock(&dpm_list_mtx);
++	while (!list_empty(&dpm_active) && error == 0) {
++		struct list_head * entry = dpm_active.prev;
++		struct device * dev = to_device(entry);
++
++		get_device(dev);
++		mutex_unlock(&dpm_list_mtx);
++
++		error = suspend_device(dev, state);
++
++		mutex_lock(&dpm_list_mtx);
++
++		/* Check if the device got removed */
++		if (!list_empty(&dev->power.entry)) {
++			/* Move it to the dpm_off list */
++			if (!error)
++				list_move(&dev->power.entry, &dpm_off);
++		}
++		if (error)
++			printk(KERN_ERR "Could not suspend device %s: "
++				"error %d%s\n",
++				kobject_name(&dev->kobj), error,
++				error == -EAGAIN ? " (please convert to suspend_late)" : "");
++		put_device(dev);
++	}
++	mutex_unlock(&dpm_list_mtx);
++	if (error)
++		dpm_resume();
++
++	mutex_unlock(&dpm_mtx);
++	return error;
++}
++
++EXPORT_SYMBOL_GPL(device_suspend);
++
++/**
++ *	device_power_down - Shut down special devices.
++ *	@state:		Power state to enter.
++ *
++ *	Walk the dpm_off_irq list, calling ->power_down() for each device that
++ *	couldn't power down the device with interrupts enabled. When we're
++ *	done, power down system devices.
++ */
++
++int device_power_down(pm_message_t state)
++{
++	int error = 0;
++	struct device * dev;
++
++	while (!list_empty(&dpm_off)) {
++		struct list_head * entry = dpm_off.prev;
++
++		dev = to_device(entry);
++		error = suspend_device_late(dev, state);
++		if (error)
++			goto Error;
++		list_move(&dev->power.entry, &dpm_off_irq);
++	}
++
++	error = sysdev_suspend(state);
++ Done:
++	return error;
++ Error:
++	printk(KERN_ERR "Could not power down device %s: "
++		"error %d\n", kobject_name(&dev->kobj), error);
++	dpm_power_up();
++	goto Done;
++}
++
++EXPORT_SYMBOL_GPL(device_power_down);
++
++void __suspend_report_result(const char *function, void *fn, int ret)
++{
++	if (ret) {
++		printk(KERN_ERR "%s(): ", function);
++		print_fn_descriptor_symbol("%s() returns ", (unsigned long)fn);
++		printk("%d\n", ret);
++	}
++}
++EXPORT_SYMBOL_GPL(__suspend_report_result);
+diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
+index 49e64dbcce96..5c4efd493fa5 100644
+--- a/drivers/base/power/power.h
++++ b/drivers/base/power/power.h
+@@ -11,32 +11,11 @@ extern void device_shutdown(void);
+  * main.c
+  */
+ 
+-/*
+- * Used to synchronize global power management operations.
+- */
+-extern struct mutex dpm_mtx;
+-
+-/*
+- * Used to serialize changes to the dpm_* lists.
+- */
+-extern struct mutex dpm_list_mtx;
+-
+-/*
+- * The PM lists.
+- */
+-extern struct list_head dpm_active;
+-extern struct list_head dpm_off;
+-extern struct list_head dpm_off_irq;
+-
+-
+-static inline struct dev_pm_info * to_pm_info(struct list_head * entry)
+-{
+-	return container_of(entry, struct dev_pm_info, entry);
+-}
++extern struct list_head dpm_active;	/* The active device list */
+ 
+ static inline struct device * to_device(struct list_head * entry)
+ {
+-	return container_of(to_pm_info(entry), struct device, power);
++	return container_of(entry, struct device, power.entry);
+ }
+ 
+ extern int device_pm_add(struct device *);
+@@ -49,13 +28,6 @@ extern void device_pm_remove(struct device *);
+ extern int dpm_sysfs_add(struct device *);
+ extern void dpm_sysfs_remove(struct device *);
+ 
+-/*
+- * resume.c
+- */
+-
+-extern void dpm_resume(void);
+-extern void dpm_power_up(void);
+-
+ #else /* CONFIG_PM_SLEEP */
+ 
+ 
+diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c
+deleted file mode 100644
+index 67948bac9938..000000000000
+--- a/drivers/base/power/resume.c
++++ /dev/null
+@@ -1,149 +0,0 @@
+-/*
+- * resume.c - Functions for waking devices up.
+- *
+- * Copyright (c) 2003 Patrick Mochel
+- * Copyright (c) 2003 Open Source Development Labs
+- *
+- * This file is released under the GPLv2
+- *
+- */
+-
+-#include 
+-#include 
+-#include "../base.h"
+-#include "power.h"
+-
+-
+-/**
+- *	resume_device - Restore state for one device.
+- *	@dev:	Device.
+- *
+- */
+-
+-static int resume_device(struct device * dev)
+-{
+-	int error = 0;
+-
+-	TRACE_DEVICE(dev);
+-	TRACE_RESUME(0);
+-
+-	down(&dev->sem);
+-
+-	if (dev->bus && dev->bus->resume) {
+-		dev_dbg(dev,"resuming\n");
+-		error = dev->bus->resume(dev);
+-	}
+-
+-	if (!error && dev->type && dev->type->resume) {
+-		dev_dbg(dev,"resuming\n");
+-		error = dev->type->resume(dev);
+-	}
+-
+-	if (!error && dev->class && dev->class->resume) {
+-		dev_dbg(dev,"class resume\n");
+-		error = dev->class->resume(dev);
+-	}
+-
+-	up(&dev->sem);
+-
+-	TRACE_RESUME(error);
+-	return error;
+-}
+-
+-
+-static int resume_device_early(struct device * dev)
+-{
+-	int error = 0;
+-
+-	TRACE_DEVICE(dev);
+-	TRACE_RESUME(0);
+-	if (dev->bus && dev->bus->resume_early) {
+-		dev_dbg(dev,"EARLY resume\n");
+-		error = dev->bus->resume_early(dev);
+-	}
+-	TRACE_RESUME(error);
+-	return error;
+-}
+-
+-/*
+- * Resume the devices that have either not gone through
+- * the late suspend, or that did go through it but also
+- * went through the early resume
+- */
+-void dpm_resume(void)
+-{
+-	mutex_lock(&dpm_list_mtx);
+-	while(!list_empty(&dpm_off)) {
+-		struct list_head * entry = dpm_off.next;
+-		struct device * dev = to_device(entry);
+-
+-		get_device(dev);
+-		list_move_tail(entry, &dpm_active);
+-
+-		mutex_unlock(&dpm_list_mtx);
+-		resume_device(dev);
+-		mutex_lock(&dpm_list_mtx);
+-		put_device(dev);
+-	}
+-	mutex_unlock(&dpm_list_mtx);
+-}
+-
+-
+-/**
+- *	device_resume - Restore state of each device in system.
+- *
+- *	Walk the dpm_off list, remove each entry, resume the device,
+- *	then add it to the dpm_active list.
+- */
+-
+-void device_resume(void)
+-{
+-	might_sleep();
+-	mutex_lock(&dpm_mtx);
+-	dpm_resume();
+-	mutex_unlock(&dpm_mtx);
+-}
+-
+-EXPORT_SYMBOL_GPL(device_resume);
+-
+-
+-/**
+- *	dpm_power_up - Power on some devices.
+- *
+- *	Walk the dpm_off_irq list and power each device up. This
+- *	is used for devices that required they be powered down with
+- *	interrupts disabled. As devices are powered on, they are moved
+- *	to the dpm_active list.
+- *
+- *	Interrupts must be disabled when calling this.
+- */
+-
+-void dpm_power_up(void)
+-{
+-	while(!list_empty(&dpm_off_irq)) {
+-		struct list_head * entry = dpm_off_irq.next;
+-		struct device * dev = to_device(entry);
+-
+-		list_move_tail(entry, &dpm_off);
+-		resume_device_early(dev);
+-	}
+-}
+-
+-
+-/**
+- *	device_power_up - Turn on all devices that need special attention.
+- *
+- *	Power on system devices then devices that required we shut them down
+- *	with interrupts disabled.
+- *	Called with interrupts disabled.
+- */
+-
+-void device_power_up(void)
+-{
+-	sysdev_resume();
+-	dpm_power_up();
+-}
+-
+-EXPORT_SYMBOL_GPL(device_power_up);
+-
+-
+diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c
+deleted file mode 100644
+index 204517afb15e..000000000000
+--- a/drivers/base/power/suspend.c
++++ /dev/null
+@@ -1,210 +0,0 @@
+-/*
+- * suspend.c - Functions for putting devices to sleep.
+- *
+- * Copyright (c) 2003 Patrick Mochel
+- * Copyright (c) 2003 Open Source Development Labs
+- *
+- * This file is released under the GPLv2
+- *
+- */
+-
+-#include 
+-#include 
+-#include 
+-#include "../base.h"
+-#include "power.h"
+-
+-/*
+- * The entries in the dpm_active list are in a depth first order, simply
+- * because children are guaranteed to be discovered after parents, and
+- * are inserted at the back of the list on discovery.
+- *
+- * All list on the suspend path are done in reverse order, so we operate
+- * on the leaves of the device tree (or forests, depending on how you want
+- * to look at it ;) first. As nodes are removed from the back of the list,
+- * they are inserted into the front of their destintation lists.
+- *
+- * Things are the reverse on the resume path - iterations are done in
+- * forward order, and nodes are inserted at the back of their destination
+- * lists. This way, the ancestors will be accessed before their descendents.
+- */
+-
+-static inline char *suspend_verb(u32 event)
+-{
+-	switch (event) {
+-	case PM_EVENT_SUSPEND:	return "suspend";
+-	case PM_EVENT_FREEZE:	return "freeze";
+-	case PM_EVENT_PRETHAW:	return "prethaw";
+-	default:		return "(unknown suspend event)";
+-	}
+-}
+-
+-
+-static void
+-suspend_device_dbg(struct device *dev, pm_message_t state, char *info)
+-{
+-	dev_dbg(dev, "%s%s%s\n", info, suspend_verb(state.event),
+-		((state.event == PM_EVENT_SUSPEND) && device_may_wakeup(dev)) ?
+-		", may wakeup" : "");
+-}
+-
+-/**
+- *	suspend_device - Save state of one device.
+- *	@dev:	Device.
+- *	@state:	Power state device is entering.
+- */
+-
+-static int suspend_device(struct device * dev, pm_message_t state)
+-{
+-	int error = 0;
+-
+-	down(&dev->sem);
+-	if (dev->power.power_state.event) {
+-		dev_dbg(dev, "PM: suspend %d-->%d\n",
+-			dev->power.power_state.event, state.event);
+-	}
+-
+-	if (dev->class && dev->class->suspend) {
+-		suspend_device_dbg(dev, state, "class ");
+-		error = dev->class->suspend(dev, state);
+-		suspend_report_result(dev->class->suspend, error);
+-	}
+-
+-	if (!error && dev->type && dev->type->suspend) {
+-		suspend_device_dbg(dev, state, "type ");
+-		error = dev->type->suspend(dev, state);
+-		suspend_report_result(dev->type->suspend, error);
+-	}
+-
+-	if (!error && dev->bus && dev->bus->suspend) {
+-		suspend_device_dbg(dev, state, "");
+-		error = dev->bus->suspend(dev, state);
+-		suspend_report_result(dev->bus->suspend, error);
+-	}
+-	up(&dev->sem);
+-	return error;
+-}
+-
+-
+-/*
+- * This is called with interrupts off, only a single CPU
+- * running. We can't acquire a mutex or semaphore (and we don't
+- * need the protection)
+- */
+-static int suspend_device_late(struct device *dev, pm_message_t state)
+-{
+-	int error = 0;
+-
+-	if (dev->bus && dev->bus->suspend_late) {
+-		suspend_device_dbg(dev, state, "LATE ");
+-		error = dev->bus->suspend_late(dev, state);
+-		suspend_report_result(dev->bus->suspend_late, error);
+-	}
+-	return error;
+-}
+-
+-/**
+- *	device_suspend - Save state and stop all devices in system.
+- *	@state:		Power state to put each device in.
+- *
+- *	Walk the dpm_active list, call ->suspend() for each device, and move
+- *	it to the dpm_off list.
+- *
+- *	(For historical reasons, if it returns -EAGAIN, that used to mean
+- *	that the device would be called again with interrupts disabled.
+- *	These days, we use the "suspend_late()" callback for that, so we
+- *	print a warning and consider it an error).
+- *
+- *	If we get a different error, try and back out.
+- *
+- *	If we hit a failure with any of the devices, call device_resume()
+- *	above to bring the suspended devices back to life.
+- *
+- */
+-
+-int device_suspend(pm_message_t state)
+-{
+-	int error = 0;
+-
+-	might_sleep();
+-	mutex_lock(&dpm_mtx);
+-	mutex_lock(&dpm_list_mtx);
+-	while (!list_empty(&dpm_active) && error == 0) {
+-		struct list_head * entry = dpm_active.prev;
+-		struct device * dev = to_device(entry);
+-
+-		get_device(dev);
+-		mutex_unlock(&dpm_list_mtx);
+-
+-		error = suspend_device(dev, state);
+-
+-		mutex_lock(&dpm_list_mtx);
+-
+-		/* Check if the device got removed */
+-		if (!list_empty(&dev->power.entry)) {
+-			/* Move it to the dpm_off list */
+-			if (!error)
+-				list_move(&dev->power.entry, &dpm_off);
+-		}
+-		if (error)
+-			printk(KERN_ERR "Could not suspend device %s: "
+-				"error %d%s\n",
+-				kobject_name(&dev->kobj), error,
+-				error == -EAGAIN ? " (please convert to suspend_late)" : "");
+-		put_device(dev);
+-	}
+-	mutex_unlock(&dpm_list_mtx);
+-	if (error)
+-		dpm_resume();
+-
+-	mutex_unlock(&dpm_mtx);
+-	return error;
+-}
+-
+-EXPORT_SYMBOL_GPL(device_suspend);
+-
+-/**
+- *	device_power_down - Shut down special devices.
+- *	@state:		Power state to enter.
+- *
+- *	Walk the dpm_off_irq list, calling ->power_down() for each device that
+- *	couldn't power down the device with interrupts enabled. When we're
+- *	done, power down system devices.
+- */
+-
+-int device_power_down(pm_message_t state)
+-{
+-	int error = 0;
+-	struct device * dev;
+-
+-	while (!list_empty(&dpm_off)) {
+-		struct list_head * entry = dpm_off.prev;
+-
+-		dev = to_device(entry);
+-		error = suspend_device_late(dev, state);
+-		if (error)
+-			goto Error;
+-		list_move(&dev->power.entry, &dpm_off_irq);
+-	}
+-
+-	error = sysdev_suspend(state);
+- Done:
+-	return error;
+- Error:
+-	printk(KERN_ERR "Could not power down device %s: "
+-		"error %d\n", kobject_name(&dev->kobj), error);
+-	dpm_power_up();
+-	goto Done;
+-}
+-
+-EXPORT_SYMBOL_GPL(device_power_down);
+-
+-void __suspend_report_result(const char *function, void *fn, int ret)
+-{
+-	if (ret) {
+-		printk(KERN_ERR "%s(): ", function);
+-		print_fn_descriptor_symbol("%s() returns ", (unsigned long)fn);
+-		printk("%d\n", ret);
+-	}
+-}
+-EXPORT_SYMBOL_GPL(__suspend_report_result);

commit 7d2c592609a7da950b458403f1936d382f38ff9c
+Author: Alan Stern 
+Date:   Mon Aug 20 10:48:05 2007 -0400
+
+    USB: disable autosuspend by default for non-hubs
+    
+    This patch (as965) disables autosuspend by default for all USB devices
+    other than hubs.  We are seeing too many devices that can't suspend or
+    resume properly, the blacklist is growing unreasonably quickly, and
+    this sort of thing should be handled in userspace.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index 7f17d0fd76c0..ebf3dc20110a 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -152,4 +152,10 @@ void usb_detect_quirks(struct usb_device *udev)
+ 	/* do any special quirk handling here if needed */
+ 	if (udev->quirks & USB_QUIRK_NO_AUTOSUSPEND)
+ 		usb_autosuspend_quirk(udev);
++
++	/* By default, disable autosuspend for all non-hubs */
++#ifdef	CONFIG_USB_SUSPEND
++	if (udev->descriptor.bDeviceClass != USB_CLASS_HUB)
++		udev->autosuspend_delay = -1;
++#endif
+ }

commit c269b6abd65c24517b70ccc9430c4c50dbc0dc84
+Author: Alan Stern 
+Date:   Tue Sep 4 10:12:44 2007 -0400
+
+    USB: prevent Genesys USB-IDE from autosuspending
+    
+    This patch (as986) prevents the troublesome Genesys USB-IDE adapter
+    from autosuspending.  It may not be necessary for all such devices,
+    but the one in Bugzilla #8892 sometimes fails to resume.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index af3b627a93cf..e388cbceaad9 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -70,6 +70,10 @@ static const struct usb_device_id usb_quirk_list[] = {
+ 	{ USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+ 	/* Ultima Electronics Corp.*/
+ 	{ USB_DEVICE(0x05d8, 0x4005), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
++
++	/* Genesys USB-to-IDE */
++	{ USB_DEVICE(0x0503, 0x0702), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
++
+ 	/* Agfa Snapscan1212u */
+ 	{ USB_DEVICE(0x06bd, 0x2061), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+ 	/* Seagate RSS LLC */

commit d7790baf62a0e9f034e4668bb4b5fdaaa248412b
+Author: Alan Stern 
+Date:   Tue Sep 4 10:11:56 2007 -0400
+
+    USB: prevent Thomson card reader from autosuspending
+    
+    This patch (as985) prevents the SGS THomson Microelectronics 4in1 card
+    reader from autosuspending.  This resolves Bugzilla #8885.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index a5cde8ba1655..af3b627a93cf 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -32,6 +32,10 @@ static const struct usb_device_id usb_quirk_list[] = {
+ 	{ USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 },
+ 	/* Hewlett-Packard PhotoSmart 720 / PhotoSmart 935 (storage) */
+ 	{ USB_DEVICE(0x03f0, 0x4002), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
++
++	/* SGS Thomson Microelectronics 4in1 card reader */
++	{ USB_DEVICE(0x0483, 0x0321), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
++
+ 	/* Acer Peripherals Inc. (now BenQ Corp.) Prisa 640BU */
+ 	{ USB_DEVICE(0x04a5, 0x207e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+ 	/* Benq S2W 3300U */

commit 5f1835da79df8607ecbd69f648b5b140b7a0b8ba
+Author: Alan Stern 
+Date:   Thu Aug 16 16:13:06 2007 -0400
+
+    sysfs: don't warn on removal of a nonexistent binary file
+    
+    This patch (as960) removes the error message and stack dump logged by
+    sysfs_remove_bin_file() when someone tries to remove a nonexistent
+    file.  The warning doesn't seem to be needed, since none of the other
+    file-, symlink-, or directory-removal routines in sysfs complain in a
+    comparable way.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Tejun Heo 
+    Acked-by: Cornelia Huck 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
+index 135353f8a296..5afe2a26f5d8 100644
+--- a/fs/sysfs/bin.c
++++ b/fs/sysfs/bin.c
+@@ -248,12 +248,7 @@ int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr)
+ 
+ void sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr)
+ {
+-	if (sysfs_hash_and_remove(kobj->sd, attr->attr.name) < 0) {
+-		printk(KERN_ERR "%s: "
+-			"bad dentry or inode or no such file: \"%s\"\n",
+-			__FUNCTION__, attr->attr.name);
+-		dump_stack();
+-	}
++	sysfs_hash_and_remove(kobj->sd, attr->attr.name);
+ }
+ 
+ EXPORT_SYMBOL_GPL(sysfs_create_bin_file);

commit d1a94f080f5bdfe46c9fb4954ffe8ae9ec29e44a
+Author: Alan Stern 
+Date:   Fri Aug 17 10:58:16 2007 -0400
+
+    USB: g_file_storage: fix bug in DMA buffer handling
+    
+    This patch (as963) fixes a recently-introduced bug.  The gadget
+    conversion removing DMA-mapped buffer allocation did not remove quite
+    enough code from the g_file_storage driver; DMA pointers were being
+    set to 0.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index 01ddb6d3e51b..965ad7bec7b7 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -599,7 +599,6 @@ enum fsg_buffer_state {
+ 
+ struct fsg_buffhd {
+ 	void				*buf;
+-	dma_addr_t			dma;
+ 	enum fsg_buffer_state		state;
+ 	struct fsg_buffhd		*next;
+ 
+@@ -2612,7 +2611,6 @@ static int send_status(struct fsg_dev *fsg)
+ 
+ 		fsg->intr_buffhd = bh;		// Point to the right buffhd
+ 		fsg->intreq->buf = bh->inreq->buf;
+-		fsg->intreq->dma = bh->inreq->dma;
+ 		fsg->intreq->context = bh;
+ 		start_transfer(fsg, fsg->intr_in, fsg->intreq,
+ 				&fsg->intreq_busy, &bh->state);
+@@ -3201,7 +3199,6 @@ static int do_set_interface(struct fsg_dev *fsg, int altsetting)
+ 		if ((rc = alloc_request(fsg, fsg->bulk_out, &bh->outreq)) != 0)
+ 			goto reset;
+ 		bh->inreq->buf = bh->outreq->buf = bh->buf;
+-		bh->inreq->dma = bh->outreq->dma = bh->dma;
+ 		bh->inreq->context = bh->outreq->context = bh;
+ 		bh->inreq->complete = bulk_in_complete;
+ 		bh->outreq->complete = bulk_out_complete;

commit 013d27f265de6934ad7fb48fb29ab0172a20ab40
+Author: Alan Stern 
+Date:   Mon Aug 20 12:18:39 2007 -0400
+
+    USB: update last_busy field correctly
+    
+    This patch (as966) fixes a bug in the autosuspend code.  The last_busy
+    field should be updated whenever any event occurs, not just events
+    that cause an autosuspend or an autoresume.
+    
+    This partially fixes Bugzilla #8892.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 654857493a82..a1ad11d0c47c 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1224,6 +1224,8 @@ static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt)
+ 	udev->auto_pm = 1;
+ 	udev->pm_usage_cnt += inc_usage_cnt;
+ 	WARN_ON(udev->pm_usage_cnt < 0);
++	if (inc_usage_cnt)
++		udev->last_busy = jiffies;
+ 	if (inc_usage_cnt >= 0 && udev->pm_usage_cnt > 0) {
+ 		if (udev->state == USB_STATE_SUSPENDED)
+ 			status = usb_resume_both(udev);
+@@ -1232,8 +1234,6 @@ static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt)
+ 		else if (inc_usage_cnt)
+ 			udev->last_busy = jiffies;
+ 	} else if (inc_usage_cnt <= 0 && udev->pm_usage_cnt <= 0) {
+-		if (inc_usage_cnt)
+-			udev->last_busy = jiffies;
+ 		status = usb_suspend_both(udev, PMSG_SUSPEND);
+ 	}
+ 	usb_pm_unlock(udev);
+@@ -1342,16 +1342,15 @@ static int usb_autopm_do_interface(struct usb_interface *intf,
+ 	else {
+ 		udev->auto_pm = 1;
+ 		intf->pm_usage_cnt += inc_usage_cnt;
++		udev->last_busy = jiffies;
+ 		if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) {
+ 			if (udev->state == USB_STATE_SUSPENDED)
+ 				status = usb_resume_both(udev);
+ 			if (status != 0)
+ 				intf->pm_usage_cnt -= inc_usage_cnt;
+-			else if (inc_usage_cnt)
++			else
+ 				udev->last_busy = jiffies;
+ 		} else if (inc_usage_cnt <= 0 && intf->pm_usage_cnt <= 0) {
+-			if (inc_usage_cnt)
+-				udev->last_busy = jiffies;
+ 			status = usb_suspend_both(udev, PMSG_SUSPEND);
+ 		}
+ 	}

commit c39772d82ad453647ea4bf9d793010d86ef5e597
+Author: Alan Stern 
+Date:   Mon Aug 20 10:45:28 2007 -0400
+
+    USB: allow retry on descriptor fetch errors
+    
+    This patch (as964) was suggested by Steffen Koepf.  It makes
+    usb_get_descriptor() retry on all errors other than ETIMEDOUT, instead
+    of only on EPIPE.  This helps with some devices.
+    
+    Signed-off-by: Alan Stern 
+    CC: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index b6bd05e3d439..5498506e9c5e 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -637,12 +637,12 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char
+ 	memset(buf,0,size);	// Make sure we parse really received data
+ 
+ 	for (i = 0; i < 3; ++i) {
+-		/* retry on length 0 or stall; some devices are flakey */
++		/* retry on length 0 or error; some devices are flakey */
+ 		result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ 				USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+ 				(type << 8) + index, 0, buf, size,
+ 				USB_CTRL_GET_TIMEOUT);
+-		if (result == 0 || result == -EPIPE)
++		if (result <= 0 && result != -ETIMEDOUT)
+ 			continue;
+ 		if (result > 1 && ((u8 *)buf)[1] != type) {
+ 			result = -EPROTO;

commit 2f67cd5b1d5066d11761aebb0bf4b76bc253cc99
+Author: Alan Stern 
+Date:   Thu Aug 16 16:16:00 2007 -0400
+
+    usb-storage: fix bugs in the disconnect pathway
+    
+    This patch (as961) fixes a couple of bugs in the disconnect pathway of
+    usb-storage.
+    
+    The first problem, which apparently has been around for a while
+    although nobody noticed it, shows up when an aborted command is still
+    pending when a disconnect occurs.  The SCSI error-handler will
+    continue to wait in command_abort() until the us->notify completion is
+    signalled.  Thus quiesce_and_remove_host() needs to signal it.
+    
+    The second problem was introduced recently along with autosuspend
+    support.  Since usb_stor_scan_thread() now calls
+    usb_autopm_put_interface() before exiting, we can't simply leave the
+    scanning thread running after a disconnect; we must wait until the
+    thread exits.  This is solved by adding a new struct completion to the
+    private data structure.  Fortuitously, it allows the removal of the
+    rather clunky mechanism used in the past to insure that all threads
+    have finished before the module is unloaded.
+    
+    Signed-off-by: Alan Stern 
+    CC: Matthew Dharm 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 28842d208bb0..25e557d4fe6b 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -112,13 +112,6 @@ module_param(delay_use, uint, S_IRUGO | S_IWUSR);
+ MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device");
+ 
+ 
+-/* These are used to make sure the module doesn't unload before all the
+- * threads have exited.
+- */
+-static atomic_t total_threads = ATOMIC_INIT(0);
+-static DECLARE_COMPLETION(threads_gone);
+-
+-
+ /*
+  * The entries in this table correspond, line for line,
+  * with the entries of us_unusual_dev_list[].
+@@ -879,9 +872,6 @@ static void quiesce_and_remove_host(struct us_data *us)
+ 	usb_stor_stop_transport(us);
+ 	wake_up(&us->delay_wait);
+ 
+-	/* It doesn't matter if the SCSI-scanning thread is still running.
+-	 * The thread will exit when it sees the DISCONNECTING flag. */
+-
+ 	/* queuecommand won't accept any new commands and the control
+ 	 * thread won't execute a previously-queued command.  If there
+ 	 * is such a command pending, complete it with an error. */
+@@ -891,12 +881,16 @@ static void quiesce_and_remove_host(struct us_data *us)
+ 		scsi_lock(host);
+ 		us->srb->scsi_done(us->srb);
+ 		us->srb = NULL;
++		complete(&us->notify);		/* in case of an abort */
+ 		scsi_unlock(host);
+ 	}
+ 	mutex_unlock(&us->dev_mutex);
+ 
+ 	/* Now we own no commands so it's safe to remove the SCSI host */
+ 	scsi_remove_host(host);
++
++	/* Wait for the SCSI-scanning thread to stop */
++	wait_for_completion(&us->scanning_done);
+ }
+ 
+ /* Second stage of disconnect processing: deallocate all resources */
+@@ -947,9 +941,8 @@ static int usb_stor_scan_thread(void * __us)
+ 		/* Should we unbind if no devices were detected? */
+ 	}
+ 
+-	scsi_host_put(us_to_host(us));
+ 	usb_autopm_put_interface(us->pusb_intf);
+-	complete_and_exit(&threads_gone, 0);
++	complete_and_exit(&us->scanning_done, 0);
+ }
+ 
+ 
+@@ -984,6 +977,7 @@ static int storage_probe(struct usb_interface *intf,
+ 	init_MUTEX_LOCKED(&(us->sema));
+ 	init_completion(&(us->notify));
+ 	init_waitqueue_head(&us->delay_wait);
++	init_completion(&us->scanning_done);
+ 
+ 	/* Associate the us_data structure with the USB device */
+ 	result = associate_dev(us, intf);
+@@ -1033,11 +1027,6 @@ static int storage_probe(struct usb_interface *intf,
+ 		goto BadDevice;
+ 	}
+ 
+-	/* Take a reference to the host for the scanning thread and
+-	 * count it among all the threads we have launched.  Then
+-	 * start it up. */
+-	scsi_host_get(us_to_host(us));
+-	atomic_inc(&total_threads);
+ 	usb_autopm_get_interface(intf); /* dropped in the scanning thread */
+ 	wake_up_process(th);
+ 
+@@ -1104,16 +1093,6 @@ static void __exit usb_stor_exit(void)
+ 	US_DEBUGP("-- calling usb_deregister()\n");
+ 	usb_deregister(&usb_storage_driver) ;
+ 
+-	/* Don't return until all of our control and scanning threads
+-	 * have exited.  Since each thread signals threads_gone as its
+-	 * last act, we have to call wait_for_completion the right number
+-	 * of times.
+-	 */
+-	while (atomic_read(&total_threads) > 0) {
+-		wait_for_completion(&threads_gone);
+-		atomic_dec(&total_threads);
+-	}
+-
+ 	usb_usual_clear_present(USB_US_TYPE_STOR);
+ }
+ 
+diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
+index 6445665b1577..8d87503e2560 100644
+--- a/drivers/usb/storage/usb.h
++++ b/drivers/usb/storage/usb.h
+@@ -150,6 +150,7 @@ struct us_data {
+ 	struct semaphore	sema;		 /* to sleep thread on	    */
+ 	struct completion	notify;		 /* thread begin/end	    */
+ 	wait_queue_head_t	delay_wait;	 /* wait during scan, reset */
++	struct completion	scanning_done;	 /* wait for scan thread    */
+ 
+ 	/* subdriver information */
+ 	void			*extra;		 /* Any extra data          */

commit 46dede4690bbb23a2c9d60561e2e4fdc3e6bee61
+Author: Alan Stern 
+Date:   Tue Aug 14 10:56:10 2007 -0400
+
+    USB: accept 1-byte Device Status replies, fixing some b0rken devices
+    
+    Some devices have a bug which causes them to send a 1-byte reply to
+    Get-Device-Status requests instead of 2 bytes as required by the
+    spec.  This doesn't play well with autosuspend, since we look for a
+    valid status reply to make sure the device is still present when it
+    resumes.  Without both bytes, we assume the device has been
+    disconnected.
+    
+    Lack of the second byte shouldn't matter much, since the spec requires
+    it always to be equal to 0.  Hence this patch (as959) causes
+    finish_port_resume() to accept a 1-byte reply as valid.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index e341a1da517f..f7b337feb3ea 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1644,9 +1644,10 @@ static int finish_port_resume(struct usb_device *udev)
+ 	 * and device drivers will know about any resume quirks.
+ 	 */
+ 	if (status == 0) {
++		devstatus = 0;
+ 		status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
+ 		if (status >= 0)
+-			status = (status == 2 ? 0 : -ENODEV);
++			status = (status > 0 ? 0 : -ENODEV);
+ 	}
+ 
+ 	if (status) {

commit 0bd307e1b950e0aca1dbbc2b76f542f9c96b9a95
+Author: Alan Stern 
+Date:   Wed Aug 8 17:16:12 2007 -0400
+
+    USB: remove DEBUG definition from dummy_hcd
+    
+    This patch (as958) removes an unneeded and unwanted #define line from
+    dummy_hcd.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index f2fbdc7fe376..d008d1360a7a 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -34,8 +34,6 @@
+  * bypassing some hardware (and driver) issues.  UML could help too.
+  */
+ 
+-#define DEBUG
+-
+ #include 
+ #include 
+ #include 

commit 74da5d68a54d66667664fbe233ededab2376a070
+Author: Alan Stern 
+Date:   Thu Aug 2 13:29:10 2007 -0400
+
+    USB: cdc-acm: fix sysfs attribute registration bug
+    
+    This patch (as950) fixes a bug in the cdc-acm driver.  It doesn't keep
+    track of which interface (control or data) the sysfs attributes get
+    registered for, and as a result, during disconnect it will sometimes
+    attempt to remove the attributes from the wrong interface.  The
+    left-over attributes can cause a crash later on, particularly if the driver
+    module has been unloaded.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Oliver Neukum 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
+index fe940e0536e0..f51e22490edf 100644
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -921,6 +921,10 @@ static int acm_probe (struct usb_interface *intf,
+ 			return -EINVAL;
+ 		}
+ 	}
++
++	/* Accept probe requests only for the control interface */
++	if (intf != control_interface)
++		return -ENODEV;
+ 	
+ 	if (usb_interface_claimed(data_interface)) { /* valid in this context */
+ 		dev_dbg(&intf->dev,"The data interface isn't available");
+@@ -1109,10 +1113,12 @@ static void acm_disconnect(struct usb_interface *intf)
+ 		return;
+ 	}
+ 	if (acm->country_codes){
+-		device_remove_file(&intf->dev, &dev_attr_wCountryCodes);
+-		device_remove_file(&intf->dev, &dev_attr_iCountryCodeRelDate);
++		device_remove_file(&acm->control->dev,
++				&dev_attr_wCountryCodes);
++		device_remove_file(&acm->control->dev,
++				&dev_attr_iCountryCodeRelDate);
+ 	}
+-	device_remove_file(&intf->dev, &dev_attr_bmCapabilities);
++	device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities);
+ 	acm->dev = NULL;
+ 	usb_set_intfdata(acm->control, NULL);
+ 	usb_set_intfdata(acm->data, NULL);

commit eb9a9a56316f4fea98ee32873ccbf7098b7bd69b
+Author: Alan Stern 
+Date:   Fri Aug 10 13:01:07 2007 -0700
+
+    hex_dump: add missing "const" qualifiers
+    
+    Add missing "const" qualifiers to the print_hex_dump_bytes() library routines.
+    
+    (akpm: rumoured to fix some compile warning somewhere)
+    
+    Signed-off-by: Alan Stern 
+    Cc: Artem Bityutskiy 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/kernel.h b/include/linux/kernel.h
+index b4f5b81b4257..f592df74b3cf 100644
+--- a/include/linux/kernel.h
++++ b/include/linux/kernel.h
+@@ -226,7 +226,7 @@ extern void print_hex_dump(const char *level, const char *prefix_str,
+ 				int prefix_type, int rowsize, int groupsize,
+ 				const void *buf, size_t len, bool ascii);
+ extern void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
+-			void *buf, size_t len);
++			const void *buf, size_t len);
+ #define hex_asc(x)	"0123456789abcdef"[x]
+ 
+ #ifdef DEBUG
+diff --git a/lib/hexdump.c b/lib/hexdump.c
+index 16f2e2935e87..bd5edaeaa80b 100644
+--- a/lib/hexdump.c
++++ b/lib/hexdump.c
+@@ -189,7 +189,7 @@ EXPORT_SYMBOL(print_hex_dump);
+  * rowsize of 16, groupsize of 1, and ASCII output included.
+  */
+ void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
+-			void *buf, size_t len)
++			const void *buf, size_t len)
+ {
+ 	print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, 16, 1,
+ 			buf, len, 1);

commit 67f5dde3d4961032aeeecaf0d1c7a9232bef3f44
+Author: Alan Stern 
+Date:   Tue Jul 24 18:23:23 2007 -0400
+
+    USB: Fix a bug in usb_start_wait_urb
+    
+    This patch (as941) fixes a bug recently added to the USB synchronous
+    API.  The status of a completed URB must be preserved separately
+    across a completion callback.  Also, the actual_length value isn't
+    available until after the URB has fully completed.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index ad4b956380d2..b6bd05e3d439 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -18,9 +18,17 @@
+ #include "hcd.h"	/* for usbcore internals */
+ #include "usb.h"
+ 
++struct api_context {
++	struct completion	done;
++	int			status;
++};
++
+ static void usb_api_blocking_completion(struct urb *urb)
+ {
+-	complete((struct completion *)urb->context);
++	struct api_context *ctx = urb->context;
++
++	ctx->status = urb->status;
++	complete(&ctx->done);
+ }
+ 
+ 
+@@ -32,20 +40,21 @@ static void usb_api_blocking_completion(struct urb *urb)
+  */
+ static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
+ { 
+-	struct completion done;
++	struct api_context ctx;
+ 	unsigned long expire;
+ 	int retval;
+-	int status = urb->status;
+ 
+-	init_completion(&done); 	
+-	urb->context = &done;
++	init_completion(&ctx.done);
++	urb->context = &ctx;
+ 	urb->actual_length = 0;
+ 	retval = usb_submit_urb(urb, GFP_NOIO);
+ 	if (unlikely(retval))
+ 		goto out;
+ 
+ 	expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT;
+-	if (!wait_for_completion_timeout(&done, expire)) {
++	if (!wait_for_completion_timeout(&ctx.done, expire)) {
++		usb_kill_urb(urb);
++		retval = (ctx.status == -ENOENT ? -ETIMEDOUT : ctx.status);
+ 
+ 		dev_dbg(&urb->dev->dev,
+ 			"%s timed out on ep%d%s len=%d/%d\n",
+@@ -54,11 +63,8 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
+ 			usb_pipein(urb->pipe) ? "in" : "out",
+ 			urb->actual_length,
+ 			urb->transfer_buffer_length);
+-
+-		usb_kill_urb(urb);
+-		retval = status == -ENOENT ? -ETIMEDOUT : status;
+ 	} else
+-		retval = status;
++		retval = ctx.status;
+ out:
+ 	if (actual_length)
+ 		*actual_length = urb->actual_length;

commit bb1995d52b05f7e671914454d0ae57bd4170ef47
+Author: Alan Stern 
+Date:   Sat Jul 21 17:10:42 2007 +0200
+
+    x86: Make Alt-SysRq-p display the debug register contents
+    
+    This patch (as921) adds code to the show_regs() routine in i386 and x86_64
+    to print the contents of the debug registers along with all the others.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Roland McGrath 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Andi Kleen 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
+index 6c49acb96982..84664710b784 100644
+--- a/arch/i386/kernel/process.c
++++ b/arch/i386/kernel/process.c
+@@ -300,6 +300,7 @@ early_param("idle", idle_setup);
+ void show_regs(struct pt_regs * regs)
+ {
+ 	unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
++	unsigned long d0, d1, d2, d3, d6, d7;
+ 
+ 	printk("\n");
+ 	printk("Pid: %d, comm: %20s\n", current->pid, current->comm);
+@@ -324,6 +325,17 @@ void show_regs(struct pt_regs * regs)
+ 	cr3 = read_cr3();
+ 	cr4 = read_cr4_safe();
+ 	printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4);
++
++	get_debugreg(d0, 0);
++	get_debugreg(d1, 1);
++	get_debugreg(d2, 2);
++	get_debugreg(d3, 3);
++	printk("DR0: %08lx DR1: %08lx DR2: %08lx DR3: %08lx\n",
++			d0, d1, d2, d3);
++	get_debugreg(d6, 6);
++	get_debugreg(d7, 7);
++	printk("DR6: %08lx DR7: %08lx\n", d6, d7);
++
+ 	show_trace(NULL, regs, ®s->esp);
+ }
+ 
+diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
+index 180f4c0fcbc4..bbfc957f045f 100644
+--- a/arch/x86_64/kernel/process.c
++++ b/arch/x86_64/kernel/process.c
+@@ -306,6 +306,7 @@ early_param("idle", idle_setup);
+ void __show_regs(struct pt_regs * regs)
+ {
+ 	unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L, fs, gs, shadowgs;
++	unsigned long d0, d1, d2, d3, d6, d7;
+ 	unsigned int fsindex,gsindex;
+ 	unsigned int ds,cs,es; 
+ 
+@@ -350,6 +351,15 @@ void __show_regs(struct pt_regs * regs)
+ 	       fs,fsindex,gs,gsindex,shadowgs); 
+ 	printk("CS:  %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds, es, cr0); 
+ 	printk("CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3, cr4);
++
++	get_debugreg(d0, 0);
++	get_debugreg(d1, 1);
++	get_debugreg(d2, 2);
++	printk("DR0: %016lx DR1: %016lx DR2: %016lx\n", d0, d1, d2);
++	get_debugreg(d3, 3);
++	get_debugreg(d6, 6);
++	get_debugreg(d7, 7);
++	printk("DR3: %016lx DR6: %016lx DR7: %016lx\n", d3, d6, d7);
+ }
+ 
+ void show_regs(struct pt_regs *regs)

commit 809a58b896ba07e771adc76a47c83e4ca1969da8
+Author: Alan Stern 
+Date:   Wed Jul 18 12:14:24 2007 -0400
+
+    USB: change name of spinlock in hcd.c
+    
+    This patch (as940 renames hcd_data_lock in hcd.c to hcd_urb_list_lock,
+    which is more descriptive of the lock's job.  It also introduces a
+    convenient inline routine for testing whether a particular USB device
+    is a root hub.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 032b118c2883..42ef1d5f6c8a 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -99,12 +99,17 @@ EXPORT_SYMBOL_GPL (usb_bus_list_lock);
+ /* used for controlling access to virtual root hubs */
+ static DEFINE_SPINLOCK(hcd_root_hub_lock);
+ 
+-/* used when updating hcd data */
+-static DEFINE_SPINLOCK(hcd_data_lock);
++/* used when updating an endpoint's URB list */
++static DEFINE_SPINLOCK(hcd_urb_list_lock);
+ 
+ /* wait queue for synchronous unlinks */
+ DECLARE_WAIT_QUEUE_HEAD(usb_kill_urb_queue);
+ 
++static inline int is_root_hub(struct usb_device *udev)
++{
++	return (udev->parent == NULL);
++}
++
+ /*-------------------------------------------------------------------------*/
+ 
+ /*
+@@ -906,14 +911,13 @@ EXPORT_SYMBOL (usb_calc_bus_time);
+ static void urb_unlink(struct usb_hcd *hcd, struct urb *urb)
+ {
+ 	unsigned long		flags;
+-	int at_root_hub = (urb->dev == hcd->self.root_hub);
+ 
+ 	/* clear all state linking urb to this dev (and hcd) */
+-	spin_lock_irqsave (&hcd_data_lock, flags);
++	spin_lock_irqsave(&hcd_urb_list_lock, flags);
+ 	list_del_init (&urb->urb_list);
+-	spin_unlock_irqrestore (&hcd_data_lock, flags);
++	spin_unlock_irqrestore(&hcd_urb_list_lock, flags);
+ 
+-	if (hcd->self.uses_dma && !at_root_hub) {
++	if (hcd->self.uses_dma && !is_root_hub(urb->dev)) {
+ 		if (usb_pipecontrol (urb->pipe)
+ 			&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
+ 			dma_unmap_single (hcd->self.controller, urb->setup_dma,
+@@ -955,7 +959,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+ 
+ 	// FIXME:  verify that quiescing hc works right (RH cleans up)
+ 
+-	spin_lock_irqsave (&hcd_data_lock, flags);
++	spin_lock_irqsave(&hcd_urb_list_lock, flags);
+ 	ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out)
+ 			[usb_pipeendpoint(urb->pipe)];
+ 	if (unlikely (!ep))
+@@ -972,7 +976,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+ 		status = -ESHUTDOWN;
+ 		break;
+ 	}
+-	spin_unlock_irqrestore (&hcd_data_lock, flags);
++	spin_unlock_irqrestore(&hcd_urb_list_lock, flags);
+ 	if (status) {
+ 		INIT_LIST_HEAD (&urb->urb_list);
+ 		usbmon_urb_submit_error(&hcd->self, urb, status);
+@@ -986,7 +990,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+ 	urb = usb_get_urb (urb);
+ 	atomic_inc (&urb->use_count);
+ 
+-	if (urb->dev == hcd->self.root_hub) {
++	if (is_root_hub(urb->dev)) {
+ 		/* NOTE:  requirement on hub callers (usbfs and the hub
+ 		 * driver, for now) that URBs' urb->transfer_buffer be
+ 		 * valid and usb_buffer_{sync,unmap}() not be needed, since
+@@ -1043,7 +1047,7 @@ unlink1 (struct usb_hcd *hcd, struct urb *urb)
+ {
+ 	int		value;
+ 
+-	if (urb->dev == hcd->self.root_hub)
++	if (is_root_hub(urb->dev))
+ 		value = usb_rh_urb_dequeue (hcd, urb);
+ 	else {
+ 
+@@ -1091,11 +1095,11 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
+ 	 * that it was submitted.  But as a rule it can't know whether or
+ 	 * not it's already been unlinked ... so we respect the reversed
+ 	 * lock sequence needed for the usb_hcd_giveback_urb() code paths
+-	 * (urb lock, then hcd_data_lock) in case some other CPU is now
++	 * (urb lock, then hcd_urb_list_lock) in case some other CPU is now
+ 	 * unlinking it.
+ 	 */
+ 	spin_lock_irqsave (&urb->lock, flags);
+-	spin_lock (&hcd_data_lock);
++	spin_lock(&hcd_urb_list_lock);
+ 
+ 	sys = &urb->dev->dev;
+ 	hcd = bus_to_hcd(urb->dev->bus);
+@@ -1127,17 +1131,16 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
+ 	 * finish unlinking the initial failed usb_set_address()
+ 	 * or device descriptor fetch.
+ 	 */
+-	if (!test_bit(HCD_FLAG_SAW_IRQ, &hcd->flags)
+-	    && hcd->self.root_hub != urb->dev) {
++	if (!test_bit(HCD_FLAG_SAW_IRQ, &hcd->flags) &&
++			!is_root_hub(urb->dev)) {
+ 		dev_warn (hcd->self.controller, "Unlink after no-IRQ?  "
+-			"Controller is probably using the wrong IRQ."
+-			"\n");
++			"Controller is probably using the wrong IRQ.\n");
+ 		set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+ 	}
+ 
+ 	urb->status = status;
+ 
+-	spin_unlock (&hcd_data_lock);
++	spin_unlock(&hcd_urb_list_lock);
+ 	spin_unlock_irqrestore (&urb->lock, flags);
+ 
+ 	retval = unlink1 (hcd, urb);
+@@ -1146,7 +1149,7 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
+ 	return retval;
+ 
+ done:
+-	spin_unlock (&hcd_data_lock);
++	spin_unlock(&hcd_urb_list_lock);
+ 	spin_unlock_irqrestore (&urb->lock, flags);
+ 	if (retval != -EIDRM && sys && sys->driver)
+ 		dev_dbg (sys, "hcd_unlink_urb %p fail %d\n", urb, retval);
+@@ -1203,7 +1206,7 @@ void usb_hcd_endpoint_disable (struct usb_device *udev,
+ 
+ 	/* ep is already gone from udev->ep_{in,out}[]; no more submits */
+ rescan:
+-	spin_lock (&hcd_data_lock);
++	spin_lock(&hcd_urb_list_lock);
+ 	list_for_each_entry (urb, &ep->urb_list, urb_list) {
+ 		int	tmp;
+ 
+@@ -1211,7 +1214,7 @@ void usb_hcd_endpoint_disable (struct usb_device *udev,
+ 		if (urb->status != -EINPROGRESS)
+ 			continue;
+ 		usb_get_urb (urb);
+-		spin_unlock (&hcd_data_lock);
++		spin_unlock(&hcd_urb_list_lock);
+ 
+ 		spin_lock (&urb->lock);
+ 		tmp = urb->status;
+@@ -1240,7 +1243,7 @@ void usb_hcd_endpoint_disable (struct usb_device *udev,
+ 		/* list contents may have changed */
+ 		goto rescan;
+ 	}
+-	spin_unlock (&hcd_data_lock);
++	spin_unlock(&hcd_urb_list_lock);
+ 	local_irq_enable ();
+ 
+ 	/* synchronize with the hardware, so old configuration state
+@@ -1257,7 +1260,7 @@ void usb_hcd_endpoint_disable (struct usb_device *udev,
+ 	 * endpoint_disable methods.
+ 	 */
+ 	while (!list_empty (&ep->urb_list)) {
+-		spin_lock_irq (&hcd_data_lock);
++		spin_lock_irq(&hcd_urb_list_lock);
+ 
+ 		/* The list may have changed while we acquired the spinlock */
+ 		urb = NULL;
+@@ -1266,7 +1269,7 @@ void usb_hcd_endpoint_disable (struct usb_device *udev,
+ 					urb_list);
+ 			usb_get_urb (urb);
+ 		}
+-		spin_unlock_irq (&hcd_data_lock);
++		spin_unlock_irq(&hcd_urb_list_lock);
+ 
+ 		if (urb) {
+ 			usb_kill_urb (urb);

commit 32aca5600526189dd876e6c92b64fd88cf052c8d
+Author: Alan Stern 
+Date:   Wed Jul 18 12:08:02 2007 -0400
+
+    USB: move routines in hcd.c
+    
+    This patch (as939) moves a couple of routine in hcd.c around.  The
+    purpose is to put all the general URB- and endpoint-related routines
+    (submit, unlink, giveback, and disable) together in one spot.
+    
+    There are no functional changes.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 963520fbef90..032b118c2883 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1033,18 +1033,6 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-/* called in any context */
+-int usb_hcd_get_frame_number (struct usb_device *udev)
+-{
+-	struct usb_hcd	*hcd = bus_to_hcd(udev->bus);
+-
+-	if (!HC_IS_RUNNING (hcd->state))
+-		return -ESHUTDOWN;
+-	return hcd->driver->get_frame_number (hcd);
+-}
+-
+-/*-------------------------------------------------------------------------*/
+-
+ /* this makes the hcd giveback() the urb more quickly, by kicking it
+  * off hardware queues (which may take a while) and returning it as
+  * soon as practical.  we've already set up the urb's return status,
+@@ -1167,6 +1155,35 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++/**
++ * usb_hcd_giveback_urb - return URB from HCD to device driver
++ * @hcd: host controller returning the URB
++ * @urb: urb being returned to the USB device driver.
++ * Context: in_interrupt()
++ *
++ * This hands the URB from HCD to its USB device driver, using its
++ * completion function.  The HCD has freed all per-urb resources
++ * (and is done using urb->hcpriv).  It also released all HCD locks;
++ * the device driver won't cause problems if it frees, modifies,
++ * or resubmits this URB.
++ */
++void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
++{
++	urb_unlink(hcd, urb);
++	usbmon_urb_complete (&hcd->self, urb);
++	usb_unanchor_urb(urb);
++
++	/* pass ownership to the completion handler */
++	urb->complete (urb);
++	atomic_dec (&urb->use_count);
++	if (unlikely (urb->reject))
++		wake_up (&usb_kill_urb_queue);
++	usb_put_urb (urb);
++}
++EXPORT_SYMBOL (usb_hcd_giveback_urb);
++
++/*-------------------------------------------------------------------------*/
++
+ /* disables the endpoint: cancels any pending urbs, then synchronizes with
+  * the hcd to make sure all endpoint state is gone from hardware, and then
+  * waits until the endpoint's queue is completely drained. use for
+@@ -1260,6 +1277,18 @@ void usb_hcd_endpoint_disable (struct usb_device *udev,
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++/* called in any context */
++int usb_hcd_get_frame_number (struct usb_device *udev)
++{
++	struct usb_hcd	*hcd = bus_to_hcd(udev->bus);
++
++	if (!HC_IS_RUNNING (hcd->state))
++		return -ESHUTDOWN;
++	return hcd->driver->get_frame_number (hcd);
++}
++
++/*-------------------------------------------------------------------------*/
++
+ #ifdef	CONFIG_PM
+ 
+ int hcd_bus_suspend(struct usb_device *rhdev)
+@@ -1394,35 +1423,6 @@ EXPORT_SYMBOL (usb_bus_start_enum);
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-/**
+- * usb_hcd_giveback_urb - return URB from HCD to device driver
+- * @hcd: host controller returning the URB
+- * @urb: urb being returned to the USB device driver.
+- * Context: in_interrupt()
+- *
+- * This hands the URB from HCD to its USB device driver, using its
+- * completion function.  The HCD has freed all per-urb resources
+- * (and is done using urb->hcpriv).  It also released all HCD locks;
+- * the device driver won't cause problems if it frees, modifies,
+- * or resubmits this URB.
+- */
+-void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
+-{
+-	urb_unlink(hcd, urb);
+-	usbmon_urb_complete (&hcd->self, urb);
+-	usb_unanchor_urb(urb);
+-
+-	/* pass ownership to the completion handler */
+-	urb->complete (urb);
+-	atomic_dec (&urb->use_count);
+-	if (unlikely (urb->reject))
+-		wake_up (&usb_kill_urb_queue);
+-	usb_put_urb (urb);
+-}
+-EXPORT_SYMBOL (usb_hcd_giveback_urb);
+-
+-/*-------------------------------------------------------------------------*/
+-
+ /**
+  * usb_hcd_irq - hook IRQs to HCD framework (bus glue)
+  * @irq: the IRQ being raised

commit d8fbba2f59c0c131a1babf5a66f003faee02e01a
+Author: Alan Stern 
+Date:   Mon Jul 16 15:30:20 2007 -0400
+
+    USB: usb-storage: unusual_devs entry for Nikon D100
+    
+    This patch (as938) adds an unusual_devs entry for the Nikon DSC D100.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Phil Dibowitz 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 26fd196869b9..a624e72f81dc 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -313,6 +313,13 @@ UNUSUAL_DEV(  0x04b0, 0x0301, 0x0010, 0x0010,
+ 		US_SC_DEVICE, US_PR_DEVICE,NULL,
+ 		US_FL_NOT_LOCKABLE ),
+ 
++/* Reported by Stefan de Konink  */
++UNUSUAL_DEV(  0x04b0, 0x0401, 0x0200, 0x0200,
++		"NIKON",
++		"NIKON DSC D100",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_FIX_CAPACITY),
++
+ /* Reported by Andreas Bockhold  */
+ UNUSUAL_DEV(  0x04b0, 0x0405, 0x0100, 0x0100,
+ 		"NIKON",

commit beafef072af10bc8497c9ee51ce2804aa7da26be
+Author: Alan Stern 
+Date:   Fri Jul 13 15:47:16 2007 -0400
+
+    USB: documentation update for usb_unlink_urb
+    
+    This patch (as936) updates the kerneldoc for usb_unlink_urb.  The
+    explanation of how endpoint queues are meant to work is now clearer
+    and in better agreement with reality.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
+index 52ec44b828f3..be630228461c 100644
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -440,55 +440,57 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+  * @urb: pointer to urb describing a previously submitted request,
+  *	may be NULL
+  *
+- * This routine cancels an in-progress request.  URBs complete only
+- * once per submission, and may be canceled only once per submission.
+- * Successful cancellation means the requests's completion handler will
+- * be called with a status code indicating that the request has been
+- * canceled (rather than any other code) and will quickly be removed
+- * from host controller data structures.
+- *
+- * This request is always asynchronous.
+- * Success is indicated by returning -EINPROGRESS,
+- * at which time the URB will normally have been unlinked but not yet
+- * given back to the device driver.  When it is called, the completion
+- * function will see urb->status == -ECONNRESET.  Failure is indicated
+- * by any other return value.  Unlinking will fail when the URB is not
+- * currently "linked" (i.e., it was never submitted, or it was unlinked
+- * before, or the hardware is already finished with it), even if the
+- * completion handler has not yet run.
++ * This routine cancels an in-progress request.  URBs complete only once
++ * per submission, and may be canceled only once per submission.
++ * Successful cancellation means termination of @urb will be expedited
++ * and the completion handler will be called with a status code
++ * indicating that the request has been canceled (rather than any other
++ * code).
++ *
++ * This request is always asynchronous.  Success is indicated by
++ * returning -EINPROGRESS, at which time the URB will probably not yet
++ * have been given back to the device driver.  When it is eventually
++ * called, the completion function will see @urb->status == -ECONNRESET.
++ * Failure is indicated by usb_unlink_urb() returning any other value.
++ * Unlinking will fail when @urb is not currently "linked" (i.e., it was
++ * never submitted, or it was unlinked before, or the hardware is already
++ * finished with it), even if the completion handler has not yet run.
+  *
+  * Unlinking and Endpoint Queues:
+  *
++ * [The behaviors and guarantees described below do not apply to virtual
++ * root hubs but only to endpoint queues for physical USB devices.]
++ *
+  * Host Controller Drivers (HCDs) place all the URBs for a particular
+  * endpoint in a queue.  Normally the queue advances as the controller
+  * hardware processes each request.  But when an URB terminates with an
+- * error its queue stops, at least until that URB's completion routine
+- * returns.  It is guaranteed that the queue will not restart until all
+- * its unlinked URBs have been fully retired, with their completion
+- * routines run, even if that's not until some time after the original
+- * completion handler returns.  Normally the same behavior and guarantees
+- * apply when an URB terminates because it was unlinked; however if an
+- * URB is unlinked before the hardware has started to execute it, then
+- * its queue is not guaranteed to stop until all the preceding URBs have
+- * completed.
+- *
+- * This means that USB device drivers can safely build deep queues for
+- * large or complex transfers, and clean them up reliably after any sort
+- * of aborted transfer by unlinking all pending URBs at the first fault.
+- *
+- * Note that an URB terminating early because a short packet was received
+- * will count as an error if and only if the URB_SHORT_NOT_OK flag is set.
+- * Also, that all unlinks performed in any URB completion handler must
+- * be asynchronous.
+- *
+- * Queues for isochronous endpoints are treated differently, because they
+- * advance at fixed rates.  Such queues do not stop when an URB is unlinked.
+- * An unlinked URB may leave a gap in the stream of packets.  It is undefined
+- * whether such gaps can be filled in.
+- *
+- * When a control URB terminates with an error, it is likely that the
+- * status stage of the transfer will not take place, even if it is merely
+- * a soft error resulting from a short-packet with URB_SHORT_NOT_OK set.
++ * error its queue generally stops (see below), at least until that URB's
++ * completion routine returns.  It is guaranteed that a stopped queue
++ * will not restart until all its unlinked URBs have been fully retired,
++ * with their completion routines run, even if that's not until some time
++ * after the original completion handler returns.  The same behavior and
++ * guarantee apply when an URB terminates because it was unlinked.
++ *
++ * Bulk and interrupt endpoint queues are guaranteed to stop whenever an
++ * URB terminates with any sort of error, including -ECONNRESET, -ENOENT,
++ * and -EREMOTEIO.  Control endpoint queues behave the same way except
++ * that they are not guaranteed to stop for -EREMOTEIO errors.  Queues
++ * for isochronous endpoints are treated differently, because they must
++ * advance at fixed rates.  Such queues do not stop when an URB
++ * encounters an error or is unlinked.  An unlinked isochronous URB may
++ * leave a gap in the stream of packets; it is undefined whether such
++ * gaps can be filled in.
++ *
++ * Note that early termination of an URB because a short packet was
++ * received will generate a -EREMOTEIO error if and only if the
++ * URB_SHORT_NOT_OK flag is set.  By setting this flag, USB device
++ * drivers can build deep queues for large or complex bulk transfers
++ * and clean them up reliably after any sort of aborted transfer by
++ * unlinking all pending URBs at the first fault.
++ *
++ * When a control URB terminates with an error other than -EREMOTEIO, it
++ * is quite likely that the status stage of the transfer will not take
++ * place.
+  */
+ int usb_unlink_urb(struct urb *urb)
+ {

commit e7e7c360fb07020b24652843aec442325baad0ce
+Author: Alan Stern 
+Date:   Fri Jul 13 15:46:29 2007 -0400
+
+    UHCI: short control URBs get a status stage
+    
+    It has recently been pointed out that short control transfers should
+    have a status stage, even if they generate an error because
+    URB_SHORT_NOT_OK was set.  This patch (as935) changes uhci-hcd to
+    enable the status stage when this happens.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 4aed305982ec..3bb908ca38e9 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -827,8 +827,10 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
+ 	 * If direction is "send", change the packet ID from SETUP (0x2D)
+ 	 * to OUT (0xE1).  Else change it from SETUP to IN (0x69) and
+ 	 * set Short Packet Detect (SPD) for all data packets.
++	 *
++	 * 0-length transfers always get treated as "send".
+ 	 */
+-	if (usb_pipeout(urb->pipe))
++	if (usb_pipeout(urb->pipe) || len == 0)
+ 		destination ^= (USB_PID_SETUP ^ USB_PID_OUT);
+ 	else {
+ 		destination ^= (USB_PID_SETUP ^ USB_PID_IN);
+@@ -839,7 +841,12 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
+ 	 * Build the DATA TDs
+ 	 */
+ 	while (len > 0) {
+-		int pktsze = min(len, maxsze);
++		int pktsze = maxsze;
++
++		if (len <= pktsze) {		/* The last data packet */
++			pktsze = len;
++			status &= ~TD_CTRL_SPD;
++		}
+ 
+ 		td = uhci_alloc_td(uhci);
+ 		if (!td)
+@@ -866,20 +873,10 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
+ 		goto nomem;
+ 	*plink = LINK_TO_TD(td);
+ 
+-	/*
+-	 * It's IN if the pipe is an output pipe or we're not expecting
+-	 * data back.
+-	 */
+-	destination &= ~TD_TOKEN_PID_MASK;
+-	if (usb_pipeout(urb->pipe) || !urb->transfer_buffer_length)
+-		destination |= USB_PID_IN;
+-	else
+-		destination |= USB_PID_OUT;
+-
++	/* Change direction for the status transaction */
++	destination ^= (USB_PID_IN ^ USB_PID_OUT);
+ 	destination |= TD_TOKEN_TOGGLE;		/* End in Data1 */
+ 
+-	status &= ~TD_CTRL_SPD;
+-
+ 	uhci_add_td_to_urbp(td, urbp);
+ 	uhci_fill_td(td, status | TD_CTRL_IOC,
+ 			destination | uhci_explen(0), 0);
+@@ -1185,10 +1182,18 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
+ 				}
+ 			}
+ 
++		/* Did we receive a short packet? */
+ 		} else if (len < uhci_expected_length(td_token(td))) {
+ 
+-			/* We received a short packet */
+-			if (urb->transfer_flags & URB_SHORT_NOT_OK)
++			/* For control transfers, go to the status TD if
++			 * this isn't already the last data TD */
++			if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
++				if (td->list.next != urbp->td_list.prev)
++					ret = 1;
++			}
++
++			/* For bulk and interrupt, this may be an error */
++			else if (urb->transfer_flags & URB_SHORT_NOT_OK)
+ 				ret = -EREMOTEIO;
+ 
+ 			/* Fixup needed only if this isn't the URB's last TD */
+@@ -1208,10 +1213,6 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
+ 
+ err:
+ 	if (ret < 0) {
+-		/* In case a control transfer gets an error
+-		 * during the setup stage */
+-		urb->actual_length = max(urb->actual_length, 0);
+-
+ 		/* Note that the queue has stopped and save
+ 		 * the next toggle value */
+ 		qh->element = UHCI_PTR_TERM;
+@@ -1489,9 +1490,25 @@ __acquires(uhci->lock)
+ {
+ 	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
+ 
++	if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
++
++		/* urb->actual_length < 0 means the setup transaction didn't
++		 * complete successfully.  Either it failed or the URB was
++		 * unlinked first.  Regardless, don't confuse people with a
++		 * negative length. */
++		urb->actual_length = max(urb->actual_length, 0);
++
++		/* Report erroneous short transfers */
++		if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) &&
++				urb->actual_length <
++					urb->transfer_buffer_length &&
++				urb->status == 0))
++			urb->status = -EREMOTEIO;
++	}
++
+ 	/* When giving back the first URB in an Isochronous queue,
+ 	 * reinitialize the QH's iso-related members for the next URB. */
+-	if (qh->type == USB_ENDPOINT_XFER_ISOC &&
++	else if (qh->type == USB_ENDPOINT_XFER_ISOC &&
+ 			urbp->node.prev == &qh->queue &&
+ 			urbp->node.next != &qh->queue) {
+ 		struct urb *nurb = list_entry(urbp->node.next,

commit 195af2cce5ff81c4609c7ba585b6698a7771cbfc
+Author: Alan Stern 
+Date:   Mon Jul 16 15:28:19 2007 -0400
+
+    USB: fix warning caused by autosuspend counter going negative
+    
+    This patch (as937) fixes a minor bug in the autosuspend usage-counting
+    code.  Each hub's usage counter keeps track of the number of
+    unsuspended children.  However the current driver increments the
+    counter after registering a new child, by which time the child may
+    already have been suspended and caused the counter to go negative.
+    The obvious solution is to increment the counter before registering
+    the child.
+    
+    Signed-off-by: Alan Stern 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index fd74c50b1804..e341a1da517f 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1335,6 +1335,10 @@ int usb_new_device(struct usb_device *udev)
+ 	udev->dev.devt = MKDEV(USB_DEVICE_MAJOR,
+ 			(((udev->bus->busnum-1) * 128) + (udev->devnum-1)));
+ 
++	/* Increment the parent's count of unsuspended children */
++	if (udev->parent)
++		usb_autoresume_device(udev->parent);
++
+ 	/* Register the device.  The device driver is responsible
+ 	 * for adding the device files to sysfs and for configuring
+ 	 * the device.
+@@ -1342,13 +1346,11 @@ int usb_new_device(struct usb_device *udev)
+ 	err = device_add(&udev->dev);
+ 	if (err) {
+ 		dev_err(&udev->dev, "can't device_add, error %d\n", err);
++		if (udev->parent)
++			usb_autosuspend_device(udev->parent);
+ 		goto fail;
+ 	}
+ 
+-	/* Increment the parent's count of unsuspended children */
+-	if (udev->parent)
+-		usb_autoresume_device(udev->parent);
+-
+ exit:
+ 	return err;
+ 

commit 69d42a78f935d19384d1f6e4f94b65bb162b36df
+Author: Alan Stern 
+Date:   Thu Jul 12 17:06:23 2007 -0400
+
+    USB: add "descriptors" binary sysfs attribute
+    
+    This patch (as934) adds a new readonly binary sysfs attribute file
+    called "descriptors" for each USB device.  The attribute contains the
+    device descriptor followed by the raw descriptor entry (config plug
+    subsidiary descriptors) for the current configuration.
+    
+    Having this information available in fixed-format binary makes life a
+    lot easier for user programs by avoiding the need to open, read, and
+    parse multiple sysfs text files.
+    
+    The information in this attribute file is much like that in usbfs's
+    device file, but there are some significant differences:
+    
+            The 2-byte fields in the device descriptor are left in
+            little-endian byte order, as they appear on the bus and
+            in the kernel.
+    
+            Only one raw descriptor set is presented, that of the
+            current configuration.
+    
+            Opening this file will not cause a suspended device to be
+            autoresumed.
+    
+    The last item in particular should be a big selling point for libusb,
+    which currently forces all USB devices to be resumed as it scans the
+    device tree.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Dave Mielke 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index d47ae89154a7..2ab222be8fd1 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -441,6 +441,54 @@ static struct attribute_group dev_attr_grp = {
+ 	.attrs = dev_attrs,
+ };
+ 
++/* Binary descriptors */
++
++static ssize_t
++read_descriptors(struct kobject *kobj, struct bin_attribute *attr,
++		char *buf, loff_t off, size_t count)
++{
++	struct usb_device *udev = to_usb_device(
++			container_of(kobj, struct device, kobj));
++	size_t nleft = count;
++	size_t srclen, n;
++
++	usb_lock_device(udev);
++
++	/* The binary attribute begins with the device descriptor */
++	srclen = sizeof(struct usb_device_descriptor);
++	if (off < srclen) {
++		n = min_t(size_t, nleft, srclen - off);
++		memcpy(buf, off + (char *) &udev->descriptor, n);
++		nleft -= n;
++		buf += n;
++		off = 0;
++	} else {
++		off -= srclen;
++	}
++
++	/* Then follows the raw descriptor entry for the current
++	 * configuration (config plus subsidiary descriptors).
++	 */
++	if (udev->actconfig) {
++		int cfgno = udev->actconfig - udev->config;
++
++		srclen = __le16_to_cpu(udev->actconfig->desc.wTotalLength);
++		if (off < srclen) {
++			n = min_t(size_t, nleft, srclen - off);
++			memcpy(buf, off + udev->rawdescriptors[cfgno], n);
++			nleft -= n;
++		}
++	}
++	usb_unlock_device(udev);
++	return count - nleft;
++}
++
++static struct bin_attribute dev_bin_attr_descriptors = {
++	.attr = {.name = "descriptors", .mode = 0444},
++	.read = read_descriptors,
++	.size = 18 + 65535,	/* dev descr + max-size raw descriptor */
++};
++
+ int usb_create_sysfs_dev_files(struct usb_device *udev)
+ {
+ 	struct device *dev = &udev->dev;
+@@ -450,6 +498,10 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
+ 	if (retval)
+ 		return retval;
+ 
++	retval = device_create_bin_file(dev, &dev_bin_attr_descriptors);
++	if (retval)
++		goto error;
++
+ 	retval = add_persist_attributes(dev);
+ 	if (retval)
+ 		goto error;
+@@ -492,6 +544,7 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)
+ 	device_remove_file(dev, &dev_attr_serial);
+ 	remove_power_attributes(dev);
+ 	remove_persist_attributes(dev);
++	device_remove_bin_file(dev, &dev_bin_attr_descriptors);
+ 	sysfs_remove_group(&dev->kobj, &dev_attr_grp);
+ }
+ 

commit 1b4cd43bd3f9aa7a794e29b80b0d984a8e144df4
+Author: Alan Stern 
+Date:   Thu Jul 12 17:03:01 2007 -0400
+
+    isp116x-hcd: prepare for urb->status
+    
+    This patch (as931b), adapted from a patch by Olav Kongas, makes a small
+    set of conservative changes to the isp116x-hcd driver in preparation
+    for the removal of urb->status.
+    
+            finish_request() is moved up in the source and is called
+            as soon as the URB is known to have completed, rather than
+            after all the active endpoints have been scanned.
+    
+            The status of a completed URB is kept in a local variable
+            and copied to urb->status only when the URB is about to be
+            given back.
+    
+            -EREMOTEIO error status for control transfers is set after
+            the status stage rather than when the short packet arrives.
+    
+            Some unnecessary uses of urb->lock are removed.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Olav Kongas 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
+index 46873f2534b5..5c851a36de72 100644
+--- a/drivers/usb/host/isp116x-hcd.c
++++ b/drivers/usb/host/isp116x-hcd.c
+@@ -228,7 +228,6 @@ static void preproc_atl_queue(struct isp116x *isp116x)
+ 				   struct urb, urb_list);
+ 		ptd = &ep->ptd;
+ 		len = ep->length;
+-		spin_lock(&urb->lock);
+ 		ep->data = (unsigned char *)urb->transfer_buffer
+ 		    + urb->actual_length;
+ 
+@@ -264,7 +263,6 @@ static void preproc_atl_queue(struct isp116x *isp116x)
+ 		    | PTD_EP(ep->epnum);
+ 		ptd->len = PTD_LEN(len) | PTD_DIR(dir);
+ 		ptd->faddr = PTD_FA(usb_pipedevice(urb->pipe));
+-		spin_unlock(&urb->lock);
+ 		if (!ep->active) {
+ 			ptd->mps |= PTD_LAST_MSK;
+ 			isp116x->atl_last_dir = dir;
+@@ -274,6 +272,61 @@ static void preproc_atl_queue(struct isp116x *isp116x)
+ 	}
+ }
+ 
++/*
++  Take done or failed requests out of schedule. Give back
++  processed urbs.
++*/
++static void finish_request(struct isp116x *isp116x, struct isp116x_ep *ep,
++			   struct urb *urb)
++__releases(isp116x->lock) __acquires(isp116x->lock)
++{
++	unsigned i;
++
++	urb->hcpriv = NULL;
++	ep->error_count = 0;
++
++	if (usb_pipecontrol(urb->pipe))
++		ep->nextpid = USB_PID_SETUP;
++
++	urb_dbg(urb, "Finish");
++
++	spin_unlock(&isp116x->lock);
++	usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb);
++	spin_lock(&isp116x->lock);
++
++	/* take idle endpoints out of the schedule */
++	if (!list_empty(&ep->hep->urb_list))
++		return;
++
++	/* async deschedule */
++	if (!list_empty(&ep->schedule)) {
++		list_del_init(&ep->schedule);
++		return;
++	}
++
++	/* periodic deschedule */
++	DBG("deschedule qh%d/%p branch %d\n", ep->period, ep, ep->branch);
++	for (i = ep->branch; i < PERIODIC_SIZE; i += ep->period) {
++		struct isp116x_ep *temp;
++		struct isp116x_ep **prev = &isp116x->periodic[i];
++
++		while (*prev && ((temp = *prev) != ep))
++			prev = &temp->next;
++		if (*prev)
++			*prev = ep->next;
++		isp116x->load[i] -= ep->load;
++	}
++	ep->branch = PERIODIC_SIZE;
++	isp116x_to_hcd(isp116x)->self.bandwidth_allocated -=
++	    ep->load / ep->period;
++
++	/* switch irq type? */
++	if (!--isp116x->periodic_count) {
++		isp116x->irqenb &= ~HCuPINT_SOF;
++		isp116x->irqenb |= HCuPINT_ATL;
++	}
++}
++
+ /*
+   Analyze transfer results, handle partial transfers and errors
+ */
+@@ -284,6 +337,7 @@ static void postproc_atl_queue(struct isp116x *isp116x)
+ 	struct usb_device *udev;
+ 	struct ptd *ptd;
+ 	int short_not_ok;
++	int status;
+ 	u8 cc;
+ 
+ 	for (ep = isp116x->atl_active; ep; ep = ep->active) {
+@@ -294,7 +348,7 @@ static void postproc_atl_queue(struct isp116x *isp116x)
+ 		ptd = &ep->ptd;
+ 		cc = PTD_GET_CC(ptd);
+ 		short_not_ok = 1;
+-		spin_lock(&urb->lock);
++		status = -EINPROGRESS;
+ 
+ 		/* Data underrun is special. For allowed underrun
+ 		   we clear the error and continue as normal. For
+@@ -302,47 +356,36 @@ static void postproc_atl_queue(struct isp116x *isp116x)
+ 		   immediately while for control transfer,
+ 		   we do a STATUS stage. */
+ 		if (cc == TD_DATAUNDERRUN) {
+-			if (!(urb->transfer_flags & URB_SHORT_NOT_OK)) {
+-				DBG("Allowed data underrun\n");
++			if (!(urb->transfer_flags & URB_SHORT_NOT_OK) ||
++					usb_pipecontrol(urb->pipe)) {
++				DBG("Allowed or control data underrun\n");
+ 				cc = TD_CC_NOERROR;
+ 				short_not_ok = 0;
+ 			} else {
+ 				ep->error_count = 1;
+-				if (usb_pipecontrol(urb->pipe))
+-					ep->nextpid = USB_PID_ACK;
+-				else
+-					usb_settoggle(udev, ep->epnum,
+-						      ep->nextpid ==
+-						      USB_PID_OUT,
+-						      PTD_GET_TOGGLE(ptd));
++				usb_settoggle(udev, ep->epnum,
++					      ep->nextpid == USB_PID_OUT,
++					      PTD_GET_TOGGLE(ptd));
+ 				urb->actual_length += PTD_GET_COUNT(ptd);
+-				urb->status = cc_to_error[TD_DATAUNDERRUN];
+-				spin_unlock(&urb->lock);
+-				continue;
++				status = cc_to_error[TD_DATAUNDERRUN];
++				goto done;
+ 			}
+ 		}
+-		/* Keep underrun error through the STATUS stage */
+-		if (urb->status == cc_to_error[TD_DATAUNDERRUN])
+-			cc = TD_DATAUNDERRUN;
+ 
+ 		if (cc != TD_CC_NOERROR && cc != TD_NOTACCESSED
+ 		    && (++ep->error_count >= 3 || cc == TD_CC_STALL
+ 			|| cc == TD_DATAOVERRUN)) {
+-			if (urb->status == -EINPROGRESS)
+-				urb->status = cc_to_error[cc];
++			status = cc_to_error[cc];
+ 			if (ep->nextpid == USB_PID_ACK)
+ 				ep->nextpid = 0;
+-			spin_unlock(&urb->lock);
+-			continue;
++			goto done;
+ 		}
+ 		/* According to usb spec, zero-length Int transfer signals
+ 		   finishing of the urb. Hey, does this apply only
+ 		   for IN endpoints? */
+ 		if (usb_pipeint(urb->pipe) && !PTD_GET_LEN(ptd)) {
+-			if (urb->status == -EINPROGRESS)
+-				urb->status = 0;
+-			spin_unlock(&urb->lock);
+-			continue;
++			status = 0;
++			goto done;
+ 		}
+ 
+ 		/* Relax after previously failed, but later succeeded
+@@ -381,8 +424,8 @@ static void postproc_atl_queue(struct isp116x *isp116x)
+ 			/* All data for this URB is transferred, let's finish */
+ 			if (usb_pipecontrol(urb->pipe))
+ 				ep->nextpid = USB_PID_ACK;
+-			else if (urb->status == -EINPROGRESS)
+-				urb->status = 0;
++			else
++				status = 0;
+ 			break;
+ 		case USB_PID_SETUP:
+ 			if (PTD_GET_ACTIVE(ptd)
+@@ -402,69 +445,27 @@ static void postproc_atl_queue(struct isp116x *isp116x)
+ 			if (PTD_GET_ACTIVE(ptd)
+ 			    || (cc != TD_CC_NOERROR && cc < 0x0E))
+ 				break;
+-			if (urb->status == -EINPROGRESS)
+-				urb->status = 0;
++			if ((urb->transfer_flags & URB_SHORT_NOT_OK) &&
++					urb->actual_length <
++						urb->transfer_buffer_length)
++				status = -EREMOTEIO;
++			else
++				status = 0;
+ 			ep->nextpid = 0;
+ 			break;
+ 		default:
+ 			BUG();
+ 		}
+-		spin_unlock(&urb->lock);
+-	}
+-}
+-
+-/*
+-  Take done or failed requests out of schedule. Give back
+-  processed urbs.
+-*/
+-static void finish_request(struct isp116x *isp116x, struct isp116x_ep *ep,
+-			   struct urb *urb)
+-__releases(isp116x->lock) __acquires(isp116x->lock)
+-{
+-	unsigned i;
+-
+-	urb->hcpriv = NULL;
+-	ep->error_count = 0;
+-
+-	if (usb_pipecontrol(urb->pipe))
+-		ep->nextpid = USB_PID_SETUP;
+-
+-	urb_dbg(urb, "Finish");
+-
+-	spin_unlock(&isp116x->lock);
+-	usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb);
+-	spin_lock(&isp116x->lock);
+-
+-	/* take idle endpoints out of the schedule */
+-	if (!list_empty(&ep->hep->urb_list))
+-		return;
+-
+-	/* async deschedule */
+-	if (!list_empty(&ep->schedule)) {
+-		list_del_init(&ep->schedule);
+-		return;
+-	}
+ 
+-	/* periodic deschedule */
+-	DBG("deschedule qh%d/%p branch %d\n", ep->period, ep, ep->branch);
+-	for (i = ep->branch; i < PERIODIC_SIZE; i += ep->period) {
+-		struct isp116x_ep *temp;
+-		struct isp116x_ep **prev = &isp116x->periodic[i];
+-
+-		while (*prev && ((temp = *prev) != ep))
+-			prev = &temp->next;
+-		if (*prev)
+-			*prev = ep->next;
+-		isp116x->load[i] -= ep->load;
+-	}
+-	ep->branch = PERIODIC_SIZE;
+-	isp116x_to_hcd(isp116x)->self.bandwidth_allocated -=
+-	    ep->load / ep->period;
+-
+-	/* switch irq type? */
+-	if (!--isp116x->periodic_count) {
+-		isp116x->irqenb &= ~HCuPINT_SOF;
+-		isp116x->irqenb |= HCuPINT_ATL;
++ done:
++		if (status != -EINPROGRESS) {
++			spin_lock(&urb->lock);
++			if (urb->status == -EINPROGRESS)
++				urb->status = status;
++			spin_unlock(&urb->lock);
++		}
++		if (urb->status != -EINPROGRESS)
++			finish_request(isp116x, ep, urb);
+ 	}
+ }
+ 
+@@ -570,9 +571,6 @@ static void start_atl_transfers(struct isp116x *isp116x)
+ */
+ static void finish_atl_transfers(struct isp116x *isp116x)
+ {
+-	struct isp116x_ep *ep;
+-	struct urb *urb;
+-
+ 	if (!isp116x->atl_active)
+ 		return;
+ 	/* Fifo not ready? */
+@@ -582,16 +580,6 @@ static void finish_atl_transfers(struct isp116x *isp116x)
+ 	atomic_inc(&isp116x->atl_finishing);
+ 	unpack_fifo(isp116x);
+ 	postproc_atl_queue(isp116x);
+-	for (ep = isp116x->atl_active; ep; ep = ep->active) {
+-		urb =
+-		    container_of(ep->hep->urb_list.next, struct urb, urb_list);
+-		/* USB_PID_ACK check here avoids finishing of
+-		   control transfers, for which TD_DATAUNDERRUN
+-		   occured, while URB_SHORT_NOT_OK was set */
+-		if (urb && urb->status != -EINPROGRESS
+-		    && ep->nextpid != USB_PID_ACK)
+-			finish_request(isp116x, ep, urb);
+-	}
+ 	atomic_dec(&isp116x->atl_finishing);
+ }
+ 
+@@ -821,15 +809,12 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
+ 	}
+ 
+ 	/* in case of unlink-during-submit */
+-	spin_lock(&urb->lock);
+ 	if (urb->status != -EINPROGRESS) {
+-		spin_unlock(&urb->lock);
+ 		finish_request(isp116x, ep, urb);
+ 		ret = 0;
+ 		goto fail;
+ 	}
+ 	urb->hcpriv = hep;
+-	spin_unlock(&urb->lock);
+ 	start_atl_transfers(isp116x);
+ 
+       fail:

commit 3f8df781fc5f9ee5253a54ba669e1c8872844b86
+Author: Alan Stern 
+Date:   Thu Jul 12 16:57:22 2007 -0400
+
+    PM: remove deprecated dpm_runtime_* routines
+    
+    This patch (as933) removes the deprecated dpm_runtime_suspend() and
+    dpm_runtime_resume() routines from the PM core.  The only user of
+    those routines is the PCMCIA ds driver; local replacements are added.
+    
+    Signed-off-by: Alan Stern 
+    CC: Dominik Brodowski 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
+index 9cf9d8346289..1b5c70758a1a 100644
+--- a/Documentation/feature-removal-schedule.txt
++++ b/Documentation/feature-removal-schedule.txt
+@@ -27,7 +27,6 @@ Who:	Hans Verkuil  and
+ ---------------------------
+ 
+ What:	dev->power.power_state
+-	dpm_runtime_{suspend,resume)()
+ When:	July 2007
+ Why:	Broken design for runtime control over driver power states, confusing
+ 	driver-internal runtime power management with:  mechanisms to support
+diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile
+index 91f230939c1e..fff178007208 100644
+--- a/drivers/base/power/Makefile
++++ b/drivers/base/power/Makefile
+@@ -1,5 +1,5 @@
+ obj-y			:= shutdown.o
+-obj-$(CONFIG_PM)	+= main.o suspend.o resume.o runtime.o sysfs.o
++obj-$(CONFIG_PM)	+= main.o suspend.o resume.o sysfs.o
+ obj-$(CONFIG_PM_TRACE)	+= trace.o
+ 
+ ifeq ($(CONFIG_DEBUG_DRIVER),y)
+diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
+index 2760f25b3ac5..591a0dd5deee 100644
+--- a/drivers/base/power/power.h
++++ b/drivers/base/power/power.h
+@@ -62,11 +62,6 @@ extern int resume_device(struct device *);
+  */
+ extern int suspend_device(struct device *, pm_message_t);
+ 
+-
+-/*
+- * runtime.c
+- */
+-
+ #else /* CONFIG_PM */
+ 
+ 
+diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
+deleted file mode 100644
+index df6174d85866..000000000000
+--- a/drivers/base/power/runtime.c
++++ /dev/null
+@@ -1,85 +0,0 @@
+-/*
+- * drivers/base/power/runtime.c - Handling dynamic device power management.
+- *
+- * Copyright (c) 2003 Patrick Mochel
+- * Copyright (c) 2003 Open Source Development Lab
+- *
+- */
+-
+-#include 
+-#include "power.h"
+-
+-
+-static void runtime_resume(struct device * dev)
+-{
+-	dev_dbg(dev, "resuming\n");
+-	if (!dev->power.power_state.event)
+-		return;
+-	if (!resume_device(dev))
+-		dev->power.power_state = PMSG_ON;
+-}
+-
+-
+-/**
+- *	dpm_runtime_resume - Power one device back on.
+- *	@dev:	Device.
+- *
+- *	Bring one device back to the on state by first powering it
+- *	on, then restoring state. We only operate on devices that aren't
+- *	already on.
+- *	FIXME: We need to handle devices that are in an unknown state.
+- */
+-
+-void dpm_runtime_resume(struct device * dev)
+-{
+-	mutex_lock(&dpm_mtx);
+-	runtime_resume(dev);
+-	mutex_unlock(&dpm_mtx);
+-}
+-EXPORT_SYMBOL(dpm_runtime_resume);
+-
+-
+-/**
+- *	dpm_runtime_suspend - Put one device in low-power state.
+- *	@dev:	Device.
+- *	@state:	State to enter.
+- */
+-
+-int dpm_runtime_suspend(struct device * dev, pm_message_t state)
+-{
+-	int error = 0;
+-
+-	mutex_lock(&dpm_mtx);
+-	if (dev->power.power_state.event == state.event)
+-		goto Done;
+-
+-	if (dev->power.power_state.event)
+-		runtime_resume(dev);
+-
+-	if (!(error = suspend_device(dev, state)))
+-		dev->power.power_state = state;
+- Done:
+-	mutex_unlock(&dpm_mtx);
+-	return error;
+-}
+-EXPORT_SYMBOL(dpm_runtime_suspend);
+-
+-
+-#if 0
+-/**
+- *	dpm_set_power_state - Update power_state field.
+- *	@dev:	Device.
+- *	@state:	Power state device is in.
+- *
+- *	This is an update mechanism for drivers to notify the core
+- *	what power state a device is in. Device probing code may not
+- *	always be able to tell, but we need accurate information to
+- *	work reliably.
+- */
+-void dpm_set_power_state(struct device * dev, pm_message_t state)
+-{
+-	mutex_lock(&dpm_mtx);
+-	dev->power.power_state = state;
+-	mutex_unlock(&dpm_mtx);
+-}
+-#endif  /*  0  */
+diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
+index 143c6efc478a..a99607142fc8 100644
+--- a/drivers/pcmcia/ds.c
++++ b/drivers/pcmcia/ds.c
+@@ -1127,6 +1127,34 @@ static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp,
+ 
+ #endif
+ 
++/************************ runtime PM support ***************************/
++
++static int pcmcia_dev_suspend(struct device *dev, pm_message_t state);
++static int pcmcia_dev_resume(struct device *dev);
++
++static int runtime_suspend(struct device *dev)
++{
++	int rc;
++
++	down(&dev->sem);
++	rc = pcmcia_dev_suspend(dev, PMSG_SUSPEND);
++	up(&dev->sem);
++	if (!rc)
++		dev->power.power_state.event = PM_EVENT_SUSPEND;
++	return rc;
++}
++
++static void runtime_resume(struct device *dev)
++{
++	int rc;
++
++	down(&dev->sem);
++	rc = pcmcia_dev_resume(dev);
++	up(&dev->sem);
++	if (!rc)
++		dev->power.power_state.event = PM_EVENT_ON;
++}
++
+ /************************ per-device sysfs output ***************************/
+ 
+ #define pcmcia_device_attr(field, test, format)				\
+@@ -1173,9 +1201,9 @@ static ssize_t pcmcia_store_pm_state(struct device *dev, struct device_attribute
+                 return -EINVAL;
+ 
+ 	if ((!p_dev->suspended) && !strncmp(buf, "off", 3))
+-		ret = dpm_runtime_suspend(dev, PMSG_SUSPEND);
++		ret = runtime_suspend(dev);
+ 	else if (p_dev->suspended && !strncmp(buf, "on", 2))
+-		dpm_runtime_resume(dev);
++		runtime_resume(dev);
+ 
+ 	return ret ? ret : count;
+ }
+@@ -1312,10 +1340,10 @@ static int pcmcia_bus_suspend_callback(struct device *dev, void * _data)
+ 	struct pcmcia_socket *skt = _data;
+ 	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+ 
+-	if (p_dev->socket != skt)
++	if (p_dev->socket != skt || p_dev->suspended)
+ 		return 0;
+ 
+-	return dpm_runtime_suspend(dev, PMSG_SUSPEND);
++	return runtime_suspend(dev);
+ }
+ 
+ static int pcmcia_bus_resume_callback(struct device *dev, void * _data)
+@@ -1323,10 +1351,10 @@ static int pcmcia_bus_resume_callback(struct device *dev, void * _data)
+ 	struct pcmcia_socket *skt = _data;
+ 	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+ 
+-	if (p_dev->socket != skt)
++	if (p_dev->socket != skt || !p_dev->suspended)
+ 		return 0;
+ 
+-	dpm_runtime_resume(dev);
++	runtime_resume(dev);
+ 
+ 	return 0;
+ }
+diff --git a/include/linux/pm.h b/include/linux/pm.h
+index 273781c82e4d..2735b7cadd20 100644
+--- a/include/linux/pm.h
++++ b/include/linux/pm.h
+@@ -284,8 +284,6 @@ extern int device_prepare_suspend(pm_message_t state);
+ #define device_may_wakeup(dev) \
+ 	(device_can_wakeup(dev) && (dev)->power.should_wakeup)
+ 
+-extern int dpm_runtime_suspend(struct device *, pm_message_t);
+-extern void dpm_runtime_resume(struct device *);
+ extern void __suspend_report_result(const char *function, void *fn, int ret);
+ 
+ #define suspend_report_result(fn, ret)					\
+@@ -317,15 +315,6 @@ static inline int device_suspend(pm_message_t state)
+ #define device_set_wakeup_enable(dev,val)	do{}while(0)
+ #define device_may_wakeup(dev)			(0)
+ 
+-static inline int dpm_runtime_suspend(struct device * dev, pm_message_t state)
+-{
+-	return 0;
+-}
+-
+-static inline void dpm_runtime_resume(struct device * dev)
+-{
+-}
+-
+ #define suspend_report_result(fn, ret) do { } while (0)
+ 
+ static inline int call_platform_enable_wakeup(struct device *dev, int is_on)

commit 471d0558045fe35f8c5f291c1ee63815eb9c2dcd
+Author: Alan Stern 
+Date:   Thu Jul 12 16:55:07 2007 -0400
+
+    PM: Remove deprecated sysfs files
+    
+    This patch (as932) removes the deprecated sysfs .../power/state
+    attribute files.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Pavel Machek 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
+index d05e6243b4df..9cf9d8346289 100644
+--- a/Documentation/feature-removal-schedule.txt
++++ b/Documentation/feature-removal-schedule.txt
+@@ -26,8 +26,7 @@ Who:	Hans Verkuil  and
+ 
+ ---------------------------
+ 
+-What:	/sys/devices/.../power/state
+-	dev->power.power_state
++What:	dev->power.power_state
+ 	dpm_runtime_{suspend,resume)()
+ When:	July 2007
+ Why:	Broken design for runtime control over driver power states, confusing
+diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
+index 2d47517dbe32..f2ed179cd695 100644
+--- a/drivers/base/power/sysfs.c
++++ b/drivers/base/power/sysfs.c
+@@ -7,69 +7,6 @@
+ #include "power.h"
+ 
+ 
+-#ifdef	CONFIG_PM_SYSFS_DEPRECATED
+-
+-/**
+- *	state - Control current power state of device
+- *
+- *	show() returns the current power state of the device. '0' indicates
+- *	the device is on. Other values (2) indicate the device is in some low
+- *	power state.
+- *
+- *	store() sets the current power state, which is an integer valued
+- *	0, 2, or 3.  Devices with bus.suspend_late(), or bus.resume_early()
+- *	methods fail this operation; those methods couldn't be called.
+- *	Otherwise,
+- *
+- *	- If the recorded dev->power.power_state.event matches the
+- *	  target value, nothing is done.
+- *	- If the recorded event code is nonzero, the device is reactivated
+- *	  by calling bus.resume() and/or class.resume().
+- *	- If the target value is nonzero, the device is suspended by
+- *	  calling class.suspend() and/or bus.suspend() with event code
+- *	  PM_EVENT_SUSPEND.
+- *
+- *	This mechanism is DEPRECATED and should only be used for testing.
+- */
+-
+-static ssize_t state_show(struct device * dev, struct device_attribute *attr, char * buf)
+-{
+-	if (dev->power.power_state.event)
+-		return sprintf(buf, "2\n");
+-	else
+-		return sprintf(buf, "0\n");
+-}
+-
+-static ssize_t state_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t n)
+-{
+-	pm_message_t state;
+-	int error = -EINVAL;
+-
+-	/* disallow incomplete suspend sequences */
+-	if (dev->bus && (dev->bus->suspend_late || dev->bus->resume_early))
+-		return error;
+-
+-	state.event = PM_EVENT_SUSPEND;
+-	/* Older apps expected to write "3" here - confused with PCI D3 */
+-	if ((n == 1) && !strcmp(buf, "3"))
+-		error = dpm_runtime_suspend(dev, state);
+-
+-	if ((n == 1) && !strcmp(buf, "2"))
+-		error = dpm_runtime_suspend(dev, state);
+-
+-	if ((n == 1) && !strcmp(buf, "0")) {
+-		dpm_runtime_resume(dev);
+-		error = 0;
+-	}
+-
+-	return error ? error : n;
+-}
+-
+-static DEVICE_ATTR(state, 0644, state_show, state_store);
+-
+-
+-#endif	/* CONFIG_PM_SYSFS_DEPRECATED */
+-
+ /*
+  *	wakeup - Report/change current wakeup option for device
+  *
+@@ -143,9 +80,6 @@ static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
+ 
+ 
+ static struct attribute * power_attrs[] = {
+-#ifdef	CONFIG_PM_SYSFS_DEPRECATED
+-	&dev_attr_state.attr,
+-#endif
+ 	&dev_attr_wakeup.attr,
+ 	NULL,
+ };
+diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
+index 495b7d4dd330..73328476761c 100644
+--- a/kernel/power/Kconfig
++++ b/kernel/power/Kconfig
+@@ -65,18 +65,6 @@ config PM_TRACE
+ 	CAUTION: this option will cause your machine's real-time clock to be
+ 	set to an invalid time after a resume.
+ 
+-config PM_SYSFS_DEPRECATED
+-	bool "Driver model /sys/devices/.../power/state files (DEPRECATED)"
+-	depends on PM && SYSFS
+-	default n
+-	help
+-	  The driver model started out with a sysfs file intended to provide
+-	  a userspace hook for device power management.  This feature has never
+-	  worked very well, except for limited testing purposes, and so it will
+-	  be removed.   It's not clear that a generic mechanism could really
+-	  handle the wide variability of device power states; any replacements
+-	  are likely to be bus or driver specific.
+-
+ config SOFTWARE_SUSPEND
+ 	bool "Software Suspend (Hibernation)"
+ 	depends on PM && SWAP && (((X86 || PPC64_SWSUSP) && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP))

commit 8dfe4b14869fd185ca25ee88b02ada58a3005eaf
+Author: Alan Stern 
+Date:   Fri Jul 6 14:24:27 2007 -0400
+
+    usb-storage: implement autosuspend
+    
+    This patch (as930) implements autosuspend for usb-storage.  It is
+    adapted from a patch by Oliver Neukum.  Autosuspend is allowed except
+    during LUN scanning, resets, and command execution.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index 1ba19eaa1970..47e56079925d 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -285,10 +285,15 @@ static int device_reset(struct scsi_cmnd *srb)
+ 
+ 	US_DEBUGP("%s called\n", __FUNCTION__);
+ 
+-	/* lock the device pointers and do the reset */
+-	mutex_lock(&(us->dev_mutex));
+-	result = us->transport_reset(us);
+-	mutex_unlock(&us->dev_mutex);
++	result = usb_autopm_get_interface(us->pusb_intf);
++	if (result == 0) {
++
++		/* lock the device pointers and do the reset */
++		mutex_lock(&(us->dev_mutex));
++		result = us->transport_reset(us);
++		mutex_unlock(&us->dev_mutex);
++		usb_autopm_put_interface(us->pusb_intf);
++	}
+ 
+ 	return result < 0 ? FAILED : SUCCESS;
+ }
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index cf3fc91234e7..bef8bcd9bd98 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -191,16 +191,14 @@ static int storage_suspend(struct usb_interface *iface, pm_message_t message)
+ {
+ 	struct us_data *us = usb_get_intfdata(iface);
+ 
++	US_DEBUGP("%s\n", __FUNCTION__);
++
+ 	/* Wait until no command is running */
+ 	mutex_lock(&us->dev_mutex);
+ 
+-	US_DEBUGP("%s\n", __FUNCTION__);
+ 	if (us->suspend_resume_hook)
+ 		(us->suspend_resume_hook)(us, US_SUSPEND);
+ 
+-	/* When runtime PM is working, we'll set a flag to indicate
+-	 * whether we should autoresume when a SCSI request arrives. */
+-
+ 	mutex_unlock(&us->dev_mutex);
+ 	return 0;
+ }
+@@ -209,13 +207,11 @@ static int storage_resume(struct usb_interface *iface)
+ {
+ 	struct us_data *us = usb_get_intfdata(iface);
+ 
+-	mutex_lock(&us->dev_mutex);
+-
+ 	US_DEBUGP("%s\n", __FUNCTION__);
++
+ 	if (us->suspend_resume_hook)
+ 		(us->suspend_resume_hook)(us, US_RESUME);
+ 
+-	mutex_unlock(&us->dev_mutex);
+ 	return 0;
+ }
+ 
+@@ -313,6 +309,7 @@ static int usb_stor_control_thread(void * __us)
+ {
+ 	struct us_data *us = (struct us_data *)__us;
+ 	struct Scsi_Host *host = us_to_host(us);
++	int autopm_rc;
+ 
+ 	current->flags |= PF_NOFREEZE;
+ 
+@@ -323,6 +320,9 @@ static int usb_stor_control_thread(void * __us)
+ 			
+ 		US_DEBUGP("*** thread awakened.\n");
+ 
++		/* Autoresume the device */
++		autopm_rc = usb_autopm_get_interface(us->pusb_intf);
++
+ 		/* lock the device pointers */
+ 		mutex_lock(&(us->dev_mutex));
+ 
+@@ -381,6 +381,12 @@ static int usb_stor_control_thread(void * __us)
+ 			us->srb->result = SAM_STAT_GOOD;
+ 		}
+ 
++		/* Did the autoresume fail? */
++		else if (autopm_rc < 0) {
++			US_DEBUGP("Could not wake device\n");
++			us->srb->result = DID_ERROR << 16;
++		}
++
+ 		/* we've got a command, let's do it! */
+ 		else {
+ 			US_DEBUG(usb_stor_show_command(us->srb));
+@@ -423,6 +429,10 @@ static int usb_stor_control_thread(void * __us)
+ 
+ 		/* unlock the device pointers */
+ 		mutex_unlock(&us->dev_mutex);
++
++		/* Start an autosuspend */
++		if (autopm_rc == 0)
++			usb_autopm_put_interface(us->pusb_intf);
+ 	} /* for (;;) */
+ 
+ 	/* Wait until we are told to stop */
+@@ -939,6 +949,7 @@ static int usb_stor_scan_thread(void * __us)
+ 	}
+ 
+ 	scsi_host_put(us_to_host(us));
++	usb_autopm_put_interface(us->pusb_intf);
+ 	complete_and_exit(&threads_gone, 0);
+ }
+ 
+@@ -1028,6 +1039,7 @@ static int storage_probe(struct usb_interface *intf,
+ 	 * start it up. */
+ 	scsi_host_get(us_to_host(us));
+ 	atomic_inc(&total_threads);
++	usb_autopm_get_interface(intf); /* dropped in the scanning thread */
+ 	wake_up_process(th);
+ 
+ 	return 0;
+@@ -1065,6 +1077,7 @@ static struct usb_driver usb_storage_driver = {
+ 	.pre_reset =	storage_pre_reset,
+ 	.post_reset =	storage_post_reset,
+ 	.id_table =	storage_usb_ids,
++	.supports_autosuspend = 1,
+ };
+ 
+ static int __init usb_stor_init(void)

commit 8ccef0df54642f0f72f922d8aa57e8b290e31671
+Author: Alan Stern 
+Date:   Thu Jun 21 16:26:46 2007 -0400
+
+    USB: Fix off-by-1 error in the scatter-gather library
+    
+    The loop in usb_sg_wait() is structured in a way that makes it hard to
+    tell, when the loop exits, whether or not the last URB submission
+    succeeded.  This patch (as928) changes it from a "for" loop to a
+    "while" loop and keeps "i" always equal to the number of successful
+    submissions.  This fixes an off-by-one error which can show up when
+    the first URB submission fails.
+    
+    The patch also removes a couple of lines that initialize fields which
+    don't need to be initialized.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index f9fed34bf7d8..4c1432314711 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -404,8 +404,6 @@ int usb_sg_init (
+ 
+ 		io->urbs [i]->complete = sg_complete;
+ 		io->urbs [i]->context = io;
+-		io->urbs [i]->status = -EINPROGRESS;
+-		io->urbs [i]->actual_length = 0;
+ 
+ 		/*
+ 		 * Some systems need to revert to PIO when DMA is temporarily
+@@ -499,7 +497,8 @@ void usb_sg_wait (struct usb_sg_request *io)
+ 
+ 	/* queue the urbs.  */
+ 	spin_lock_irq (&io->lock);
+-	for (i = 0; i < entries && !io->status; i++) {
++	i = 0;
++	while (i < entries && !io->status) {
+ 		int	retval;
+ 
+ 		io->urbs [i]->dev = io->dev;
+@@ -516,7 +515,6 @@ void usb_sg_wait (struct usb_sg_request *io)
+ 		case -ENOMEM:
+ 			io->urbs[i]->dev = NULL;
+ 			retval = 0;
+-			i--;
+ 			yield ();
+ 			break;
+ 
+@@ -527,6 +525,7 @@ void usb_sg_wait (struct usb_sg_request *io)
+ 			 * URBs are queued at once; N milliseconds?
+ 			 */
+ 		case 0:
++			++i;
+ 			cpu_relax ();
+ 			break;
+ 

commit cfa59dab27d1b282886e7772a8f9548236883892
+Author: Alan Stern 
+Date:   Thu Jun 21 16:25:35 2007 -0400
+
+    USB: Don't resume root hub if the controller is suspended
+    
+    Root hubs can't be resumed if their parent controller device is still
+    suspended.  This patch (as925) adds a check for that condition in
+    hcd_bus_resume() and prevents it from being treated as a fatal
+    controller failure.
+    
+    ehci-hcd is updated to add the corresponding test.  Unnecessary
+    debugging messages are removed from uhci-hcd and dummy-hcd.  The
+    error return code from dummy-hcd is changed to -ESHUTDOWN, the same as
+    the others.  ohci-hcd doesn't need any changes.
+    
+    Suspend handling in the non-PCI host drivers is somewhat hit-and-miss.
+    This patch shouldn't have any effect on them.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 5254c50086a8..963520fbef90 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1291,6 +1291,7 @@ int hcd_bus_resume(struct usb_device *rhdev)
+ {
+ 	struct usb_hcd	*hcd = container_of(rhdev->bus, struct usb_hcd, self);
+ 	int		status;
++	int		old_state = hcd->state;
+ 
+ 	dev_dbg(&rhdev->dev, "usb %s%s\n",
+ 			rhdev->auto_pm ? "auto-" : "", "resume");
+@@ -1309,9 +1310,11 @@ int hcd_bus_resume(struct usb_device *rhdev)
+ 				: USB_STATE_ADDRESS);
+ 		hcd->state = HC_STATE_RUNNING;
+ 	} else {
++		hcd->state = old_state;
+ 		dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
+ 				"resume", status);
+-		usb_hc_died(hcd);
++		if (status != -ESHUTDOWN)
++			usb_hc_died(hcd);
+ 	}
+ 	return status;
+ }
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index fcb5526cb085..9040b50d6425 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -1784,8 +1784,7 @@ static int dummy_bus_resume (struct usb_hcd *hcd)
+ 
+ 	spin_lock_irq (&dum->lock);
+ 	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+-		dev_warn (&hcd->self.root_hub->dev, "HC isn't running!\n");
+-		rc = -ENODEV;
++		rc = -ESHUTDOWN;
+ 	} else {
+ 		dum->rh_state = DUMMY_RH_RUNNING;
+ 		set_link_state (dum);
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 71aeca019e88..0dcb4164dc83 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -199,6 +199,10 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 	if (time_before (jiffies, ehci->next_statechange))
+ 		msleep(5);
+ 	spin_lock_irq (&ehci->lock);
++	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
++		spin_unlock_irq(&ehci->lock);
++		return -ESHUTDOWN;
++	}
+ 
+ 	/* Ideally and we've got a real resume here, and no port's power
+ 	 * was lost.  (For PCI, that means Vaux was maintained.)  But we
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index d22da26ff167..76c555a67dac 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -730,10 +730,9 @@ static int uhci_rh_resume(struct usb_hcd *hcd)
+ 	int rc = 0;
+ 
+ 	spin_lock_irq(&uhci->lock);
+-	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+-		dev_warn(&hcd->self.root_hub->dev, "HC isn't running!\n");
++	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
+ 		rc = -ESHUTDOWN;
+-	} else if (!uhci->dead)
++	else if (!uhci->dead)
+ 		wakeup_rh(uhci);
+ 	spin_unlock_irq(&uhci->lock);
+ 	return rc;

commit e7e6da9eb189dfa221e3bf9c21d58f02adc8983c
+Author: Alan Stern 
+Date:   Thu Jun 21 16:25:17 2007 -0400
+
+    USB: Remove usages of dev->power.power_state
+    
+    This patch (as922) removes all but one of the remaining vestiges of
+    dev->power.power_state from usbcore.  The only usage left must remain
+    until the deprecated "power/state" sysfs attribute is gone.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 3cd9af2638fc..a3aed8d87ddc 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1196,11 +1196,7 @@ static int usb_resume_both(struct usb_device *udev)
+ 			/* We can't progagate beyond the USB subsystem,
+ 			 * so if a root hub's controller is suspended
+ 			 * then we're stuck. */
+-			if (udev->dev.parent->power.power_state.event !=
+-					PM_EVENT_ON)
+-				status = -EHOSTUNREACH;
+-			else
+-				status = usb_resume_device(udev);
++			status = usb_resume_device(udev);
+  		}
+ 	} else {
+ 
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 3df538539b48..5254c50086a8 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -965,19 +965,9 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+ 	else switch (hcd->state) {
+ 	case HC_STATE_RUNNING:
+ 	case HC_STATE_RESUMING:
+-doit:
+ 		list_add_tail (&urb->urb_list, &ep->urb_list);
+ 		status = 0;
+ 		break;
+-	case HC_STATE_SUSPENDED:
+-		/* HC upstream links (register access, wakeup signaling) can work
+-		 * even when the downstream links (and DMA etc) are quiesced; let
+-		 * usbcore talk to the root hub.
+-		 */
+-		if (hcd->self.controller->power.power_state.event == PM_EVENT_ON
+-				&& urb->dev->parent == NULL)
+-			goto doit;
+-		/* FALL THROUGH */
+ 	default:
+ 		status = -ESHUTDOWN;
+ 		break;

commit 60aac1ec26b960fe77bf600457bc6c06f8aa7db4
+Author: Alan Stern 
+Date:   Fri Jun 8 15:25:02 2007 -0400
+
+    USB: Handle bogus low-speed Bulk endpoints
+    
+    A noticeable number of low-speed devices mistakenly include
+    descriptors for Bulk endpoints, which is forbidden by the USB spec.
+    In an attempt to make such devices more usable, this patch (as924)
+    converts the descriptors to Interrupt with an interval of 1 ms.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
+index dd3482328ad2..9152e12dcf71 100644
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -124,6 +124,21 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
+ 		endpoint->desc.bInterval = n;
+ 	}
+ 
++	/* Some buggy low-speed devices have Bulk endpoints, which is
++	 * explicitly forbidden by the USB spec.  In an attempt to make
++	 * them usable, we will try treating them as Interrupt endpoints.
++	 */
++	if (to_usb_device(ddev)->speed == USB_SPEED_LOW &&
++			usb_endpoint_xfer_bulk(d)) {
++		dev_warn(ddev, "config %d interface %d altsetting %d "
++		    "endpoint 0x%X is Bulk; changing to Interrupt\n",
++		    cfgno, inum, asnum, d->bEndpointAddress);
++		endpoint->desc.bmAttributes = USB_ENDPOINT_XFER_INT;
++		endpoint->desc.bInterval = 1;
++		if (le16_to_cpu(endpoint->desc.wMaxPacketSize) > 8)
++			endpoint->desc.wMaxPacketSize = cpu_to_le16(8);
++	}
++
+ 	/* Skip over any Class Specific or Vendor Specific descriptors;
+ 	 * find the next endpoint or interface descriptor */
+ 	endpoint->extra = buffer;

commit ed76cacbea08ebfdb678c8687f98237cb7c67bb6
+Author: Alan Stern 
+Date:   Thu Jun 7 17:12:25 2007 -0400
+
+    USB: usb-storage: use kthread_stop() for the control thread
+    
+    This patch (as923) makes usb-storage's control thread use
+    kthread_should_stop()/kthread_stop().  The scanning thread can't be
+    similarly converted until the core kthread implementation allows
+    threads to call do_exit().
+    
+    The advantage of this change is that we can now be certain the control
+    thread has terminated before storage_disconnect() returns.  This will
+    simplify the locking requirements when autosuspend support is added.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Matthew Dharm 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 00521f1d6a6b..cf3fc91234e7 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -425,23 +425,15 @@ static int usb_stor_control_thread(void * __us)
+ 		mutex_unlock(&us->dev_mutex);
+ 	} /* for (;;) */
+ 
+-	scsi_host_put(host);
+-
+-	/* notify the exit routine that we're actually exiting now 
+-	 *
+-	 * complete()/wait_for_completion() is similar to up()/down(),
+-	 * except that complete() is safe in the case where the structure
+-	 * is getting deleted in a parallel mode of execution (i.e. just
+-	 * after the down() -- that's necessary for the thread-shutdown
+-	 * case.
+-	 *
+-	 * complete_and_exit() goes even further than this -- it is safe in
+-	 * the case that the thread of the caller is going away (not just
+-	 * the structure) -- this is necessary for the module-remove case.
+-	 * This is important in preemption kernels, which transfer the flow
+-	 * of execution immediately upon a complete().
+-	 */
+-	complete_and_exit(&threads_gone, 0);
++	/* Wait until we are told to stop */
++	for (;;) {
++		set_current_state(TASK_INTERRUPTIBLE);
++		if (kthread_should_stop())
++			break;
++		schedule();
++	}
++	__set_current_state(TASK_RUNNING);
++	return 0;
+ }	
+ 
+ /***********************************************************************
+@@ -809,19 +801,13 @@ static int usb_stor_acquire_resources(struct us_data *us)
+ 	}
+ 
+ 	/* Start up our control thread */
+-	th = kthread_create(usb_stor_control_thread, us, "usb-storage");
++	th = kthread_run(usb_stor_control_thread, us, "usb-storage");
+ 	if (IS_ERR(th)) {
+ 		printk(KERN_WARNING USB_STORAGE 
+ 		       "Unable to start control thread\n");
+ 		return PTR_ERR(th);
+ 	}
+-
+-	/* Take a reference to the host for the control thread and
+-	 * count it among all the threads we have launched.  Then
+-	 * start it up. */
+-	scsi_host_get(us_to_host(us));
+-	atomic_inc(&total_threads);
+-	wake_up_process(th);
++	us->ctl_thread = th;
+ 
+ 	return 0;
+ }
+@@ -838,6 +824,8 @@ static void usb_stor_release_resources(struct us_data *us)
+ 	US_DEBUGP("-- sending exit command to thread\n");
+ 	set_bit(US_FLIDX_DISCONNECTING, &us->flags);
+ 	up(&us->sema);
++	if (us->ctl_thread)
++		kthread_stop(us->ctl_thread);
+ 
+ 	/* Call the destructor routine, if it exists */
+ 	if (us->extra_destructor) {
+diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
+index 6dac1ffdde86..6445665b1577 100644
+--- a/drivers/usb/storage/usb.h
++++ b/drivers/usb/storage/usb.h
+@@ -144,6 +144,7 @@ struct us_data {
+ 	unsigned char		*sensebuf;	 /* sense data buffer	 */
+ 	dma_addr_t		cr_dma;		 /* buffer DMA addresses */
+ 	dma_addr_t		iobuf_dma;
++	struct task_struct	*ctl_thread;	 /* the control thread   */
+ 
+ 	/* mutual exclusion and synchronization structures */
+ 	struct semaphore	sema;		 /* to sleep thread on	    */

commit 59c2afa072506aae10ef93126aab651142e0c908
+Author: Alan Stern 
+Date:   Tue Jun 5 16:46:26 2007 -0700
+
+    USB: option: fix usage of urb->status abuse
+    
+    Might fix bug 8561
+    
+    On Mon, 4 Jun 2007, Paulo Pereira wrote:
+    
+    > The patch that you send is not resolving the problem... :(
+    > I stil have Kernel panic after 45/60 min of work with Ktorrent/Amule...
+    >
+    > The Drump is:
+    >
+    > Call Trace:
+    > [] usb_hcd_submit+0xb1/0x763
+    > [] ipt_do_table+0x2c7/0x2ef [ip_tables]
+    > [] nf_ct_deliver_cached_events+0x41/0x96 [nf_conntrak]
+    > [] ipv4_confirm+0x36/0c3b [nf_conntrack_ipv4]
+    > [] tcp_v4_rcv+0x827/0x899
+    > [] nf_hook_slow+0x4d/0xb5
+    > [] irq_enter+0x19/0x23
+    > [] irq_enter+0x19/0x23
+    > [] do_IRQ+0xbd/0xd1
+    > [] option_write+0xa7/0xef [option]
+    
+    Okay, from this it looks like there's a problem in the option.c serial
+    driver.  Glancing at the code, it's obvious why: The thing totally
+    abuses the USB API.
+    
+    Try applying this patch; it should help.
+    
+    From: Alan Stern 
+    Cc: Paulo Pereira 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
+index 5d3999e3ff61..b37d65fc8752 100644
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -38,6 +38,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ 
+@@ -240,6 +241,7 @@ struct option_port_private {
+ 	/* Output endpoints and buffer for this port */
+ 	struct urb *out_urbs[N_OUT_URB];
+ 	char out_buffer[N_OUT_URB][OUT_BUFLEN];
++	unsigned long out_busy;		/* Bit vector of URBs in use */
+ 
+ 	/* Settings for the port */
+ 	int rts_state;	/* Handshaking pins (outputs) */
+@@ -370,7 +372,7 @@ static int option_write(struct usb_serial_port *port,
+ 			todo = OUT_BUFLEN;
+ 
+ 		this_urb = portdata->out_urbs[i];
+-		if (this_urb->status == -EINPROGRESS) {
++		if (test_and_set_bit(i, &portdata->out_busy)) {
+ 			if (time_before(jiffies,
+ 					portdata->tx_start_time[i] + 10 * HZ))
+ 				continue;
+@@ -394,6 +396,7 @@ static int option_write(struct usb_serial_port *port,
+ 			dbg("usb_submit_urb %p (write bulk) failed "
+ 				"(%d, has %d)", this_urb,
+ 				err, this_urb->status);
++			clear_bit(i, &portdata->out_busy);
+ 			continue;
+ 		}
+ 		portdata->tx_start_time[i] = jiffies;
+@@ -446,12 +449,23 @@ static void option_indat_callback(struct urb *urb)
+ static void option_outdat_callback(struct urb *urb)
+ {
+ 	struct usb_serial_port *port;
++	struct option_port_private *portdata;
++	int i;
+ 
+ 	dbg("%s", __FUNCTION__);
+ 
+ 	port = (struct usb_serial_port *) urb->context;
+ 
+ 	usb_serial_port_softint(port);
++
++	portdata = usb_get_serial_port_data(port);
++	for (i = 0; i < N_OUT_URB; ++i) {
++		if (portdata->out_urbs[i] == urb) {
++			smp_mb__before_clear_bit();
++			clear_bit(i, &portdata->out_busy);
++			break;
++		}
++	}
+ }
+ 
+ static void option_instat_callback(struct urb *urb)
+@@ -518,7 +532,7 @@ static int option_write_room(struct usb_serial_port *port)
+ 
+ 	for (i=0; i < N_OUT_URB; i++) {
+ 		this_urb = portdata->out_urbs[i];
+-		if (this_urb && this_urb->status != -EINPROGRESS)
++		if (this_urb && !test_bit(i, &portdata->out_busy))
+ 			data_len += OUT_BUFLEN;
+ 	}
+ 
+@@ -537,7 +551,7 @@ static int option_chars_in_buffer(struct usb_serial_port *port)
+ 
+ 	for (i=0; i < N_OUT_URB; i++) {
+ 		this_urb = portdata->out_urbs[i];
+-		if (this_urb && this_urb->status == -EINPROGRESS)
++		if (this_urb && test_bit(i, &portdata->out_busy))
+ 			data_len += this_urb->transfer_buffer_length;
+ 	}
+ 	dbg("%s: %d", __FUNCTION__, data_len);

commit b41a60eca833d76593d4dac8a59f5c38714194ee
+Author: Alan Stern 
+Date:   Wed May 30 15:39:33 2007 -0400
+
+    USB: add power/persist device attribute
+    
+    This patch (as920) adds an extra level of protection to the
+    USB-Persist facility.  Now it will apply by default only to hubs; for
+    all other devices the user must enable it explicitly by setting the
+    power/persist device attribute.
+    
+    The disconnect_all_children() routine in hub.c has been removed and
+    its code placed inline.  This is the way it was originally as part of
+    hub_pre_reset(); the revised usage in hub_reset_resume() is
+    sufficiently different that the code can no longer be shared.
+    Likewise, mark_children_for_reset() is now inline as part of
+    hub_reset_resume().  The end result looks much cleaner than before.
+    
+    The sysfs interface is updated to add the new attribute file, and
+    there are corresponding documentation updates.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb
+index f9937add033d..9734577d1711 100644
+--- a/Documentation/ABI/testing/sysfs-bus-usb
++++ b/Documentation/ABI/testing/sysfs-bus-usb
+@@ -39,3 +39,16 @@ Description:
+ 		If you want to suspend a device immediately but leave it
+ 		free to wake up in response to I/O requests, you should
+ 		write "0" to power/autosuspend.
++
++What:		/sys/bus/usb/devices/.../power/persist
++Date:		May 2007
++KernelVersion:	2.6.23
++Contact:	Alan Stern 
++Description:
++		If CONFIG_USB_PERSIST is set, then each USB device directory
++		will contain a file named power/persist.  The file holds a
++		boolean value (0 or 1) indicating whether or not the
++		"USB-Persist" facility is enabled for the device.  Since the
++		facility is inherently dangerous, it is disabled by default
++		for all devices except hubs.  For more information, see
++		Documentation/usb/persist.txt.
+diff --git a/Documentation/usb/persist.txt b/Documentation/usb/persist.txt
+index 6dcd5f884795..df54d645cbb5 100644
+--- a/Documentation/usb/persist.txt
++++ b/Documentation/usb/persist.txt
+@@ -2,7 +2,7 @@
+ 
+ 		   Alan Stern 
+ 
+-		 September 2, 2006 (Updated March 27, 2007)
++		 September 2, 2006 (Updated May 29, 2007)
+ 
+ 
+ 	What is the problem?
+@@ -52,9 +52,9 @@ you can convince the BIOS supplier to fix the problem (lots of luck!).
+ 
+ On many systems the USB host controllers will get reset after a
+ suspend-to-RAM.  On almost all systems, no suspend current is
+-available during suspend-to-disk (also known as swsusp).  You can
+-check the kernel log after resuming to see if either of these has
+-happened; look for lines saying "root hub lost power or was reset".
++available during hibernation (also known as swsusp or suspend-to-disk).
++You can check the kernel log after resuming to see if either of these
++has happened; look for lines saying "root hub lost power or was reset".
+ 
+ In practice, people are forced to unmount any filesystems on a USB
+ device before suspending.  If the root filesystem is on a USB device,
+@@ -71,15 +71,16 @@ structures are allowed to persist across a power-session disruption.
+ It works like this.  If the kernel sees that a USB host controller is
+ not in the expected state during resume (i.e., if the controller was
+ reset or otherwise had lost power) then it applies a persistence check
+-to each of the USB devices below that controller.  It doesn't try to
+-resume the device; that can't work once the power session is gone.
+-Instead it issues a USB port reset and then re-enumerates the device.
+-(This is exactly the same thing that happens whenever a USB device is
+-reset.)  If the re-enumeration shows that the device now attached to
+-that port has the same descriptors as before, including the Vendor and
+-Product IDs, then the kernel continues to use the same device
+-structure.  In effect, the kernel treats the device as though it had
+-merely been reset instead of unplugged.
++to each of the USB devices below that controller for which the
++"persist" attribute is set.  It doesn't try to resume the device; that
++can't work once the power session is gone.  Instead it issues a USB
++port reset and then re-enumerates the device.  (This is exactly the
++same thing that happens whenever a USB device is reset.)  If the
++re-enumeration shows that the device now attached to that port has the
++same descriptors as before, including the Vendor and Product IDs, then
++the kernel continues to use the same device structure.  In effect, the
++kernel treats the device as though it had merely been reset instead of
++unplugged.
+ 
+ If no device is now attached to the port, or if the descriptors are
+ different from what the kernel remembers, then the treatment is what
+@@ -91,6 +92,17 @@ The end result is that the USB device remains available and usable.
+ Filesystem mounts and memory mappings are unaffected, and the world is
+ now a good and happy place.
+ 
++Note that even when CONFIG_USB_PERSIST is set, the "persist" feature
++will be applied only to those devices for which it is enabled.  You
++can enable the feature by doing (as root):
++
++	echo 1 >/sys/bus/usb/devices/.../power/persist
++
++where the "..." should be filled in the with the device's ID.  Disable
++the feature by writing 0 instead of 1.  For hubs the feature is
++automatically and permanently enabled, so you only have to worry about
++setting it for devices where it really matters.
++
+ 
+ 	Is this the best solution?
+ 
+diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
+index 5113ef4cb7f6..97b09f282705 100644
+--- a/drivers/usb/core/Kconfig
++++ b/drivers/usb/core/Kconfig
+@@ -91,12 +91,15 @@ config USB_PERSIST
+ 	depends on USB && PM && EXPERIMENTAL
+ 	default n
+ 	help
+-	  If you say Y here, USB device data structures will remain
++
++	  If you say Y here and enable the "power/persist" attribute
++	  for a USB device, the device's data structures will remain
+ 	  persistent across system suspend, even if the USB bus loses
+-	  power.  (This includes software-suspend, also known as swsusp,
+-	  or suspend-to-disk.)  The devices will reappear as if by magic
+-	  when the system wakes up, with no need to unmount USB filesystems,
+-	  rmmod host-controller drivers, or do anything else.
++	  power.  (This includes hibernation, also known as swsusp or
++	  suspend-to-disk.)  The devices will reappear as if by magic
++	  when the system wakes up, with no need to unmount USB
++	  filesystems, rmmod host-controller drivers, or do anything
++	  else.
+ 
+ 	  	WARNING: This option can be dangerous!
+ 
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index c4cdb69a6e9e..50e79010401c 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -596,27 +596,18 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
+  	kick_khubd(hub);
+ }
+ 
+-static void disconnect_all_children(struct usb_hub *hub, int logical)
+-{
+-	struct usb_device *hdev = hub->hdev;
+-	int port1;
+-
+-	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
+-		if (hdev->children[port1-1]) {
+-			if (logical)
+-				hub_port_logical_disconnect(hub, port1);
+-			else
+-				usb_disconnect(&hdev->children[port1-1]);
+-		}
+-	}
+-}
+-
+ /* caller has locked the hub device */
+ static int hub_pre_reset(struct usb_interface *intf)
+ {
+ 	struct usb_hub *hub = usb_get_intfdata(intf);
++	struct usb_device *hdev = hub->hdev;
++	int i;
+ 
+-	disconnect_all_children(hub, 0);
++	/* Disconnect all the children */
++	for (i = 0; i < hdev->maxchild; ++i) {
++		if (hdev->children[i])
++			usb_disconnect(&hdev->children[i]);
++	}
+ 	hub_quiesce(hub);
+ 	return 0;
+ }
+@@ -1872,50 +1863,39 @@ static int hub_resume(struct usb_interface *intf)
+ 	return 0;
+ }
+ 
+-#ifdef	CONFIG_USB_PERSIST
+-
+-/* For "persistent-device" resets we must mark the child devices for reset
+- * and turn off a possible connect-change status (so khubd won't disconnect
+- * them later).
+- */
+-static void mark_children_for_reset_resume(struct usb_hub *hub)
++static int hub_reset_resume(struct usb_interface *intf)
+ {
++	struct usb_hub *hub = usb_get_intfdata(intf);
+ 	struct usb_device *hdev = hub->hdev;
+ 	int port1;
+ 
++	hub_power_on(hub);
++
+ 	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
+ 		struct usb_device *child = hdev->children[port1-1];
+ 
+ 		if (child) {
+-			child->reset_resume = 1;
+-			clear_port_feature(hdev, port1,
+-					USB_PORT_FEAT_C_CONNECTION);
++
++			/* For "USB_PERSIST"-enabled children we must
++			 * mark the child device for reset-resume and
++			 * turn off the connect-change status to prevent
++			 * khubd from disconnecting it later.
++			 */
++			if (USB_PERSIST && child->persist_enabled) {
++				child->reset_resume = 1;
++				clear_port_feature(hdev, port1,
++						USB_PORT_FEAT_C_CONNECTION);
++
++			/* Otherwise we must disconnect the child,
++			 * but as we may not lock the child device here
++			 * we have to do a "logical" disconnect.
++			 */
++			} else {
++				hub_port_logical_disconnect(hub, port1);
++			}
+ 		}
+ 	}
+-}
+-
+-#else
+-
+-static inline void mark_children_for_reset_resume(struct usb_hub *hub)
+-{ }
+-
+-#endif	/* CONFIG_USB_PERSIST */
+-
+-static int hub_reset_resume(struct usb_interface *intf)
+-{
+-	struct usb_hub *hub = usb_get_intfdata(intf);
+ 
+-	hub_power_on(hub);
+-	if (USB_PERSIST)
+-		mark_children_for_reset_resume(hub);
+-	else {
+-		/* Reset-resume doesn't call pre_reset, so we have to
+-		 * disconnect the children here.  But we may not lock
+-		 * the child devices, so we have to do a "logical"
+-		 * disconnect.
+-		 */
+-		disconnect_all_children(hub, 1);
+-	}
+ 	hub_activate(hub);
+ 	return 0;
+ }
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index be37c863fdfb..5dfe31bc32ba 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -169,6 +169,73 @@ show_quirks(struct device *dev, struct device_attribute *attr, char *buf)
+ }
+ static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL);
+ 
++
++#if defined(CONFIG_USB_PERSIST) || defined(CONFIG_USB_SUSPEND)
++static const char power_group[] = "power";
++#endif
++
++#ifdef	CONFIG_USB_PERSIST
++
++static ssize_t
++show_persist(struct device *dev, struct device_attribute *attr, char *buf)
++{
++	struct usb_device *udev = to_usb_device(dev);
++
++	return sprintf(buf, "%d\n", udev->persist_enabled);
++}
++
++static ssize_t
++set_persist(struct device *dev, struct device_attribute *attr,
++		const char *buf, size_t count)
++{
++	struct usb_device *udev = to_usb_device(dev);
++	int value;
++
++	/* Hubs are always enabled for USB_PERSIST */
++	if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
++		return -EPERM;
++
++	if (sscanf(buf, "%d", &value) != 1)
++		return -EINVAL;
++	usb_pm_lock(udev);
++	udev->persist_enabled = !!value;
++	usb_pm_unlock(udev);
++	return count;
++}
++
++static DEVICE_ATTR(persist, S_IRUGO | S_IWUSR, show_persist, set_persist);
++
++static int add_persist_attributes(struct device *dev)
++{
++	int rc = 0;
++
++	if (is_usb_device(dev)) {
++		struct usb_device *udev = to_usb_device(dev);
++
++		/* Hubs are automatically enabled for USB_PERSIST */
++		if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
++			udev->persist_enabled = 1;
++		rc = sysfs_add_file_to_group(&dev->kobj,
++				&dev_attr_persist.attr,
++				power_group);
++	}
++	return rc;
++}
++
++static void remove_persist_attributes(struct device *dev)
++{
++	sysfs_remove_file_from_group(&dev->kobj,
++			&dev_attr_persist.attr,
++			power_group);
++}
++
++#else
++
++#define add_persist_attributes(dev)	0
++#define remove_persist_attributes(dev)	do {} while (0)
++
++#endif	/* CONFIG_USB_PERSIST */
++
+ #ifdef	CONFIG_USB_SUSPEND
+ 
+ static ssize_t
+@@ -276,8 +343,6 @@ set_level(struct device *dev, struct device_attribute *attr,
+ 
+ static DEVICE_ATTR(level, S_IRUGO | S_IWUSR, show_level, set_level);
+ 
+-static char power_group[] = "power";
+-
+ static int add_power_attributes(struct device *dev)
+ {
+ 	int rc = 0;
+@@ -311,6 +376,7 @@ static void remove_power_attributes(struct device *dev)
+ 
+ #endif	/* CONFIG_USB_SUSPEND */
+ 
++
+ /* Descriptor fields */
+ #define usb_descriptor_attr_le16(field, format_string)			\
+ static ssize_t								\
+@@ -384,6 +450,10 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
+ 	if (retval)
+ 		return retval;
+ 
++	retval = add_persist_attributes(dev);
++	if (retval)
++		goto error;
++
+ 	retval = add_power_attributes(dev);
+ 	if (retval)
+ 		goto error;
+@@ -421,6 +491,7 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)
+ 	device_remove_file(dev, &dev_attr_product);
+ 	device_remove_file(dev, &dev_attr_serial);
+ 	remove_power_attributes(dev);
++	remove_persist_attributes(dev);
+ 	sysfs_remove_group(&dev->kobj, &dev_attr_grp);
+ }
+ 
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index bde8c65e2bfc..efce9a4c511c 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -404,6 +404,7 @@ struct usb_device {
+ 	unsigned auto_pm:1;		/* autosuspend/resume in progress */
+ 	unsigned do_remote_wakeup:1;	/* remote wakeup should be enabled */
+ 	unsigned reset_resume:1;	/* needs reset instead of resume */
++	unsigned persist_enabled:1;	/* USB_PERSIST enabled for this dev */
+ 	unsigned autosuspend_disabled:1; /* autosuspend and autoresume */
+ 	unsigned autoresume_disabled:1;  /*  disabled by the user */
+ #endif

commit 54515fe528d8c6f9bfaf7d0b9fffb908deecad78
+Author: Alan Stern 
+Date:   Wed May 30 15:38:58 2007 -0400
+
+    USB: unify reset_resume and normal resume
+    
+    This patch (as919) unifies the code paths used for normal resume and
+    for reset-resume.  Earlier I had failed to note a section in the USB
+    spec which requires the host to resume a suspended port before
+    resetting it if the attached device is enabled for remote wakeup.
+    Since the port has to be resumed anyway, we might as well reuse the
+    existing code.
+    
+    The main changes are:
+    
+            usb_reset_suspended_device() is eliminated.
+    
+            usb_root_hub_lost_power() is moved down next to the
+            hub_reset_resume() routine, to which it is logically
+            related.
+    
+            finish_port_resume() does a port reset() if the device's
+            reset_resume flag is set.
+    
+            usb_port_resume() doesn't check whether the port is initially
+            enabled if this is a USB-Persist sort of resume.
+    
+            Code to perform the port reset is added to the resume pathway
+            for the non-CONFIG_USB_SUSPEND case.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
+index 4cbe7b339513..b2fc2b115256 100644
+--- a/drivers/usb/core/generic.c
++++ b/drivers/usb/core/generic.c
+@@ -219,8 +219,6 @@ static int generic_resume(struct usb_device *udev)
+ 	 */
+ 	if (!udev->parent)
+ 		rc = hcd_bus_resume(udev);
+-	else if (udev->reset_resume)
+-		rc = usb_reset_suspended_device(udev);
+ 	else
+ 		rc = usb_port_resume(udev);
+ 	return rc;
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 0b8ed414d5cf..c4cdb69a6e9e 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -31,6 +31,12 @@
+ #include "hcd.h"
+ #include "hub.h"
+ 
++#ifdef	CONFIG_USB_PERSIST
++#define	USB_PERSIST	1
++#else
++#define	USB_PERSIST	0
++#endif
++
+ struct usb_hub {
+ 	struct device		*intfdev;	/* the "interface" device */
+ 	struct usb_device	*hdev;
+@@ -1080,72 +1086,6 @@ void usb_set_device_state(struct usb_device *udev,
+ 	spin_unlock_irqrestore(&device_state_lock, flags);
+ }
+ 
+-
+-#ifdef	CONFIG_PM
+-
+-/**
+- * usb_reset_suspended_device - reset a suspended device instead of resuming it
+- * @udev: device to be reset instead of resumed
+- *
+- * If a host controller doesn't maintain VBUS suspend current during a
+- * system sleep or is reset when the system wakes up, all the USB
+- * power sessions below it will be broken.  This is especially troublesome
+- * for mass-storage devices containing mounted filesystems, since the
+- * device will appear to have disconnected and all the memory mappings
+- * to it will be lost.
+- *
+- * As an alternative, this routine attempts to recover power sessions for
+- * devices that are still present by resetting them instead of resuming
+- * them.  If all goes well, the devices will appear to persist across the
+- * the interruption of the power sessions.
+- *
+- * This facility is inherently dangerous.  Although usb_reset_device()
+- * makes every effort to insure that the same device is present after the
+- * reset as before, it cannot provide a 100% guarantee.  Furthermore it's
+- * quite possible for a device to remain unaltered but its media to be
+- * changed.  If the user replaces a flash memory card while the system is
+- * asleep, he will have only himself to blame when the filesystem on the
+- * new card is corrupted and the system crashes.
+- */
+-int usb_reset_suspended_device(struct usb_device *udev)
+-{
+-	int rc = 0;
+-
+-	dev_dbg(&udev->dev, "usb %sresume\n", "reset-");
+-
+-	/* After we're done the device won't be suspended any more.
+-	 * In addition, the reset won't work if udev->state is SUSPENDED.
+-	 */
+-	usb_set_device_state(udev, udev->actconfig
+-			? USB_STATE_CONFIGURED
+-			: USB_STATE_ADDRESS);
+-
+-	/* Root hubs don't need to be (and can't be) reset */
+-	if (udev->parent)
+-		rc = usb_reset_device(udev);
+-	return rc;
+-}
+-
+-/**
+- * usb_root_hub_lost_power - called by HCD if the root hub lost Vbus power
+- * @rhdev: struct usb_device for the root hub
+- *
+- * The USB host controller driver calls this function when its root hub
+- * is resumed and Vbus power has been interrupted or the controller
+- * has been reset.  The routine marks @rhdev as having lost power.  When
+- * the hub driver is resumed it will take notice; if CONFIG_USB_PERSIST
+- * is enabled then it will carry out power-session recovery, otherwise
+- * it will disconnect all the child devices.
+- */
+-void usb_root_hub_lost_power(struct usb_device *rhdev)
+-{
+-	dev_warn(&rhdev->dev, "root hub lost power or was reset\n");
+-	rhdev->reset_resume = 1;
+-}
+-EXPORT_SYMBOL_GPL(usb_root_hub_lost_power);
+-
+-#endif	/* CONFIG_PM */
+-
+ static void choose_address(struct usb_device *udev)
+ {
+ 	int		devnum;
+@@ -1672,18 +1612,22 @@ int usb_port_suspend(struct usb_device *udev)
+ /*
+  * If the USB "suspend" state is in use (rather than "global suspend"),
+  * many devices will be individually taken out of suspend state using
+- * special" resume" signaling.  These routines kick in shortly after
++ * special "resume" signaling.  This routine kicks in shortly after
+  * hardware resume signaling is finished, either because of selective
+  * resume (by host) or remote wakeup (by device) ... now see what changed
+  * in the tree that's rooted at this device.
++ *
++ * If @udev->reset_resume is set then the device is reset before the
++ * status check is done.
+  */
+ static int finish_port_resume(struct usb_device *udev)
+ {
+-	int	status;
++	int	status = 0;
+ 	u16	devstatus;
+ 
+ 	/* caller owns the udev device lock */
+-	dev_dbg(&udev->dev, "finish resume\n");
++	dev_dbg(&udev->dev, "finish %sresume\n",
++			udev->reset_resume ? "reset-" : "");
+ 
+ 	/* usb ch9 identifies four variants of SUSPENDED, based on what
+ 	 * state the device resumes to.  Linux currently won't see the
+@@ -1694,13 +1638,23 @@ static int finish_port_resume(struct usb_device *udev)
+ 			? USB_STATE_CONFIGURED
+ 			: USB_STATE_ADDRESS);
+ 
++	/* 10.5.4.5 says not to reset a suspended port if the attached
++	 * device is enabled for remote wakeup.  Hence the reset
++	 * operation is carried out here, after the port has been
++	 * resumed.
++	 */
++	if (udev->reset_resume)
++		status = usb_reset_device(udev);
++
+  	/* 10.5.4.5 says be sure devices in the tree are still there.
+  	 * For now let's assume the device didn't go crazy on resume,
+ 	 * and device drivers will know about any resume quirks.
+ 	 */
+-	status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
+-	if (status >= 0)
+-		status = (status == 2 ? 0 : -ENODEV);
++	if (status == 0) {
++		status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
++		if (status >= 0)
++			status = (status == 2 ? 0 : -ENODEV);
++	}
+ 
+ 	if (status) {
+ 		dev_dbg(&udev->dev, "gone after usb resume? status %d\n",
+@@ -1735,6 +1689,28 @@ static int finish_port_resume(struct usb_device *udev)
+  * the host and the device is the same as it was when the device
+  * suspended.
+  *
++ * If CONFIG_USB_PERSIST and @udev->reset_resume are both set then this
++ * routine won't check that the port is still enabled.  Furthermore,
++ * if @udev->reset_resume is set then finish_port_resume() above will
++ * reset @udev.  The end result is that a broken power session can be
++ * recovered and @udev will appear to persist across a loss of VBUS power.
++ *
++ * For example, if a host controller doesn't maintain VBUS suspend current
++ * during a system sleep or is reset when the system wakes up, all the USB
++ * power sessions below it will be broken.  This is especially troublesome
++ * for mass-storage devices containing mounted filesystems, since the
++ * device will appear to have disconnected and all the memory mappings
++ * to it will be lost.  Using the USB_PERSIST facility, the device can be
++ * made to appear as if it had not disconnected.
++ *
++ * This facility is inherently dangerous.  Although usb_reset_device()
++ * makes every effort to insure that the same device is present after the
++ * reset as before, it cannot provide a 100% guarantee.  Furthermore it's
++ * quite possible for a device to remain unaltered but its media to be
++ * changed.  If the user replaces a flash memory card while the system is
++ * asleep, he will have only himself to blame when the filesystem on the
++ * new card is corrupted and the system crashes.
++ *
+  * Returns 0 on success, else negative errno.
+  */
+ int usb_port_resume(struct usb_device *udev)
+@@ -1743,6 +1719,7 @@ int usb_port_resume(struct usb_device *udev)
+ 	int		port1 = udev->portnum;
+ 	int		status;
+ 	u16		portchange, portstatus;
++	unsigned	mask_flags, want_flags;
+ 
+ 	/* Skip the initial Clear-Suspend step for a remote wakeup */
+ 	status = hub_port_status(hub, port1, &portstatus, &portchange);
+@@ -1765,20 +1742,23 @@ int usb_port_resume(struct usb_device *udev)
+ 				udev->auto_pm ? "auto-" : "");
+ 		msleep(25);
+ 
+-#define LIVE_FLAGS	( USB_PORT_STAT_POWER \
+-			| USB_PORT_STAT_ENABLE \
+-			| USB_PORT_STAT_CONNECTION)
+-
+ 		/* Virtual root hubs can trigger on GET_PORT_STATUS to
+ 		 * stop resume signaling.  Then finish the resume
+ 		 * sequence.
+ 		 */
+ 		status = hub_port_status(hub, port1, &portstatus, &portchange);
+-SuspendCleared:
+-		if (status < 0
+-				|| (portstatus & LIVE_FLAGS) != LIVE_FLAGS
+-				|| (portstatus & USB_PORT_STAT_SUSPEND) != 0
+-				) {
++
++ SuspendCleared:
++		if (USB_PERSIST && udev->reset_resume)
++			want_flags = USB_PORT_STAT_POWER
++					| USB_PORT_STAT_CONNECTION;
++		else
++			want_flags = USB_PORT_STAT_POWER
++					| USB_PORT_STAT_CONNECTION
++					| USB_PORT_STAT_ENABLE;
++		mask_flags = want_flags | USB_PORT_STAT_SUSPEND;
++
++		if (status < 0 || (portstatus & mask_flags) != want_flags) {
+ 			dev_dbg(hub->intfdev,
+ 				"port %d status %04x.%04x after resume, %d\n",
+ 				port1, portchange, portstatus, status);
+@@ -1790,18 +1770,19 @@ int usb_port_resume(struct usb_device *udev)
+ 						USB_PORT_FEAT_C_SUSPEND);
+ 			/* TRSMRCY = 10 msec */
+ 			msleep(10);
+-			status = finish_port_resume(udev);
+ 		}
+ 	}
+-	if (status < 0) {
+-		dev_dbg(&udev->dev, "can't resume, status %d\n", status);
+-		hub_port_logical_disconnect(hub, port1);
+-	}
+ 
+ 	clear_bit(port1, hub->busy_bits);
+ 	if (!hub->hdev->parent && !hub->busy_bits[0])
+ 		usb_enable_root_hub_irq(hub->hdev->bus);
+ 
++	if (status == 0)
++		status = finish_port_resume(udev);
++	if (status < 0) {
++		dev_dbg(&udev->dev, "can't resume, status %d\n", status);
++		hub_port_logical_disconnect(hub, port1);
++	}
+ 	return status;
+ }
+ 
+@@ -1830,7 +1811,14 @@ int usb_port_suspend(struct usb_device *udev)
+ 
+ int usb_port_resume(struct usb_device *udev)
+ {
+-	return 0;
++	int status = 0;
++
++	/* However we may need to do a reset-resume */
++	if (udev->reset_resume) {
++		dev_dbg(&udev->dev, "reset-resume\n");
++		status = usb_reset_device(udev);
++	}
++	return status;
+ }
+ 
+ static inline int remote_wakeup(struct usb_device *udev)
+@@ -1886,8 +1874,6 @@ static int hub_resume(struct usb_interface *intf)
+ 
+ #ifdef	CONFIG_USB_PERSIST
+ 
+-#define USB_PERSIST	1
+-
+ /* For "persistent-device" resets we must mark the child devices for reset
+  * and turn off a possible connect-change status (so khubd won't disconnect
+  * them later).
+@@ -1910,8 +1896,6 @@ static void mark_children_for_reset_resume(struct usb_hub *hub)
+ 
+ #else
+ 
+-#define USB_PERSIST	0
+-
+ static inline void mark_children_for_reset_resume(struct usb_hub *hub)
+ { }
+ 
+@@ -1936,6 +1920,24 @@ static int hub_reset_resume(struct usb_interface *intf)
+ 	return 0;
+ }
+ 
++/**
++ * usb_root_hub_lost_power - called by HCD if the root hub lost Vbus power
++ * @rhdev: struct usb_device for the root hub
++ *
++ * The USB host controller driver calls this function when its root hub
++ * is resumed and Vbus power has been interrupted or the controller
++ * has been reset.  The routine marks @rhdev as having lost power.  When
++ * the hub driver is resumed it will take notice; if CONFIG_USB_PERSIST
++ * is enabled then it will carry out power-session recovery, otherwise
++ * it will disconnect all the child devices.
++ */
++void usb_root_hub_lost_power(struct usb_device *rhdev)
++{
++	dev_warn(&rhdev->dev, "root hub lost power or was reset\n");
++	rhdev->reset_resume = 1;
++}
++EXPORT_SYMBOL_GPL(usb_root_hub_lost_power);
++
+ #else	/* CONFIG_PM */
+ 
+ static inline int remote_wakeup(struct usb_device *udev)
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index a547499c45f4..ad5fa0338f49 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -36,7 +36,6 @@ extern void usb_host_cleanup(void);
+ extern void usb_autosuspend_work(struct work_struct *work);
+ extern int usb_port_suspend(struct usb_device *dev);
+ extern int usb_port_resume(struct usb_device *dev);
+-extern int usb_reset_suspended_device(struct usb_device *udev);
+ extern int usb_external_suspend_device(struct usb_device *udev,
+ 		pm_message_t msg);
+ extern int usb_external_resume_device(struct usb_device *udev);

commit f07600cf9eb3ee92777b2001e564faa413144a99
+Author: Alan Stern 
+Date:   Wed May 30 15:38:16 2007 -0400
+
+    USB: add reset_resume method
+    
+    This patch (as918) introduces a new USB driver method: reset_resume.
+    It is called when a device needs to be reset as part of a resume
+    procedure (whether because of a device quirk or because of the
+    USB-Persist facility), thereby taking over a role formerly assigned to
+    the post_reset method.  As a consequence, post_reset no longer needs
+    an argument indicating whether it is being called as part of a
+    reset-resume.  This separation of functions makes the code clearer.
+    
+    In addition, the pre_reset and post_reset method return types are
+    changed; they now must return an error code.  The return value is
+    unused at present, but at some later time we may unbind drivers and
+    re-probe if they encounter an error during reset handling.
+    
+    The existing pre_reset and post_reset methods in the usbhid,
+    usb-storage, and hub drivers are updated to match the new
+    requirements.  For usbhid the post_reset routine is also used for
+    reset_resume (duplicate method pointers); for the other drivers a new
+    reset_resume routine is added.  The change to hub.c looks bigger than
+    it really is, because mark_children_for_reset_resume() gets moved down
+    next to the new hub_reset_resume() routine.
+    
+    A minor change to usb-storage makes the usb_stor_report_bus_reset()
+    routine acquire the host lock instead of requiring the caller to hold
+    it already.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Jiri Kosina 
+    CC: Matthew Dharm 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index e221b0d1f667..b2baeaeba9be 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -1009,20 +1009,22 @@ static int hid_resume(struct usb_interface *intf)
+ }
+ 
+ /* Treat USB reset pretty much the same as suspend/resume */
+-static void hid_pre_reset(struct usb_interface *intf)
++static int hid_pre_reset(struct usb_interface *intf)
+ {
+ 	/* FIXME: What if the interface is already suspended? */
+ 	hid_suspend(intf, PMSG_ON);
++	return 0;
+ }
+ 
+-static void hid_post_reset(struct usb_interface *intf, int reset_resume)
++/* Same routine used for post_reset and reset_resume */
++static int hid_post_reset(struct usb_interface *intf)
+ {
+ 	struct usb_device *dev = interface_to_usbdev (intf);
+ 
+ 	hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0);
+ 	/* FIXME: Any more reinitialization needed? */
+ 
+-	hid_resume(intf);
++	return hid_resume(intf);
+ }
+ 
+ static struct usb_device_id hid_usb_ids [] = {
+@@ -1039,6 +1041,7 @@ static struct usb_driver hid_driver = {
+ 	.disconnect =	hid_disconnect,
+ 	.suspend =	hid_suspend,
+ 	.resume =	hid_resume,
++	.reset_resume =	hid_post_reset,
+ 	.pre_reset =	hid_pre_reset,
+ 	.post_reset =	hid_post_reset,
+ 	.id_table =	hid_usb_ids,
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 6c62a6d91484..3cd9af2638fc 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -915,21 +915,37 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
+ 	}
+ 	driver = to_usb_driver(intf->dev.driver);
+ 
+-	if (reset_resume && driver->post_reset)
+-		driver->post_reset(intf, reset_resume);
+-	else if (driver->resume) {
+-		status = driver->resume(intf);
+-		if (status)
+-			dev_err(&intf->dev, "%s error %d\n",
+-					"resume", status);
+-	} else
+-		dev_warn(&intf->dev, "no resume for driver %s?\n",
+-				driver->name);
++	if (reset_resume) {
++		if (driver->reset_resume) {
++			status = driver->reset_resume(intf);
++			if (status)
++				dev_err(&intf->dev, "%s error %d\n",
++						"reset_resume", status);
++		} else {
++			// status = -EOPNOTSUPP;
++			dev_warn(&intf->dev, "no %s for driver %s?\n",
++					"reset_resume", driver->name);
++		}
++	} else {
++		if (driver->resume) {
++			status = driver->resume(intf);
++			if (status)
++				dev_err(&intf->dev, "%s error %d\n",
++						"resume", status);
++		} else {
++			// status = -EOPNOTSUPP;
++			dev_warn(&intf->dev, "no %s for driver %s?\n",
++					"resume", driver->name);
++		}
++	}
+ 
+ done:
+ 	dev_vdbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
+ 	if (status == 0)
+ 		mark_active(intf);
++
++	/* FIXME: Unbind the driver and reprobe if the resume failed
++	 * (not possible if auto_pm is set) */
+ 	return status;
+ }
+ 
+@@ -966,6 +982,18 @@ static int autosuspend_check(struct usb_device *udev)
+ 						"for autosuspend\n");
+ 				return -EOPNOTSUPP;
+ 			}
++
++			/* Don't allow autosuspend if the device will need
++			 * a reset-resume and any of its interface drivers
++			 * doesn't include support.
++			 */
++			if (udev->quirks & USB_QUIRK_RESET_RESUME) {
++				struct usb_driver *driver;
++
++				driver = to_usb_driver(intf->dev.driver);
++				if (!driver->reset_resume)
++					return -EOPNOTSUPP;
++			}
+ 		}
+ 	}
+ 
+@@ -1146,7 +1174,8 @@ static int usb_resume_both(struct usb_device *udev)
+ 			status = usb_autoresume_device(parent);
+ 			if (status == 0) {
+ 				status = usb_resume_device(udev);
+-				if (status) {
++				if (status || udev->state ==
++						USB_STATE_NOTATTACHED) {
+ 					usb_autosuspend_device(parent);
+ 
+ 					/* It's possible usb_resume_device()
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index ca3dbf84e800..0b8ed414d5cf 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -605,73 +605,26 @@ static void disconnect_all_children(struct usb_hub *hub, int logical)
+ 	}
+ }
+ 
+-#ifdef	CONFIG_USB_PERSIST
+-
+-#define USB_PERSIST	1
+-
+-/* For "persistent-device" resets we must mark the child devices for reset
+- * and turn off a possible connect-change status (so khubd won't disconnect
+- * them later).
+- */
+-static void mark_children_for_reset_resume(struct usb_hub *hub)
+-{
+-	struct usb_device *hdev = hub->hdev;
+-	int port1;
+-
+-	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
+-		struct usb_device *child = hdev->children[port1-1];
+-
+-		if (child) {
+-			child->reset_resume = 1;
+-			clear_port_feature(hdev, port1,
+-					USB_PORT_FEAT_C_CONNECTION);
+-		}
+-	}
+-}
+-
+-#else
+-
+-#define USB_PERSIST	0
+-
+-static inline void mark_children_for_reset_resume(struct usb_hub *hub)
+-{ }
+-
+-#endif	/* CONFIG_USB_PERSIST */
+-
+ /* caller has locked the hub device */
+-static void hub_pre_reset(struct usb_interface *intf)
++static int hub_pre_reset(struct usb_interface *intf)
+ {
+ 	struct usb_hub *hub = usb_get_intfdata(intf);
+ 
+-	/* This routine doesn't run as part of a reset-resume, so it's safe
+-	 * to disconnect all the drivers below the hub.
+-	 */
+ 	disconnect_all_children(hub, 0);
+ 	hub_quiesce(hub);
++	return 0;
+ }
+ 
+ /* caller has locked the hub device */
+-static void hub_post_reset(struct usb_interface *intf, int reset_resume)
++static int hub_post_reset(struct usb_interface *intf)
+ {
+ 	struct usb_hub *hub = usb_get_intfdata(intf);
+ 
+ 	hub_power_on(hub);
+-	if (reset_resume) {
+-		if (USB_PERSIST)
+-			mark_children_for_reset_resume(hub);
+-		else {
+-			/* Reset-resume doesn't call pre_reset, so we have to
+-			 * disconnect the children here.  But we may not lock
+-			 * the child devices, so we have to do a "logical"
+-			 * disconnect.
+-			 */
+-			disconnect_all_children(hub, 1);
+-		}
+-	}
+ 	hub_activate(hub);
++	return 0;
+ }
+ 
+-
+ static int hub_configure(struct usb_hub *hub,
+ 	struct usb_endpoint_descriptor *endpoint)
+ {
+@@ -1931,6 +1884,58 @@ static int hub_resume(struct usb_interface *intf)
+ 	return 0;
+ }
+ 
++#ifdef	CONFIG_USB_PERSIST
++
++#define USB_PERSIST	1
++
++/* For "persistent-device" resets we must mark the child devices for reset
++ * and turn off a possible connect-change status (so khubd won't disconnect
++ * them later).
++ */
++static void mark_children_for_reset_resume(struct usb_hub *hub)
++{
++	struct usb_device *hdev = hub->hdev;
++	int port1;
++
++	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
++		struct usb_device *child = hdev->children[port1-1];
++
++		if (child) {
++			child->reset_resume = 1;
++			clear_port_feature(hdev, port1,
++					USB_PORT_FEAT_C_CONNECTION);
++		}
++	}
++}
++
++#else
++
++#define USB_PERSIST	0
++
++static inline void mark_children_for_reset_resume(struct usb_hub *hub)
++{ }
++
++#endif	/* CONFIG_USB_PERSIST */
++
++static int hub_reset_resume(struct usb_interface *intf)
++{
++	struct usb_hub *hub = usb_get_intfdata(intf);
++
++	hub_power_on(hub);
++	if (USB_PERSIST)
++		mark_children_for_reset_resume(hub);
++	else {
++		/* Reset-resume doesn't call pre_reset, so we have to
++		 * disconnect the children here.  But we may not lock
++		 * the child devices, so we have to do a "logical"
++		 * disconnect.
++		 */
++		disconnect_all_children(hub, 1);
++	}
++	hub_activate(hub);
++	return 0;
++}
++
+ #else	/* CONFIG_PM */
+ 
+ static inline int remote_wakeup(struct usb_device *udev)
+@@ -1938,8 +1943,9 @@ static inline int remote_wakeup(struct usb_device *udev)
+ 	return 0;
+ }
+ 
+-#define hub_suspend NULL
+-#define hub_resume NULL
++#define hub_suspend		NULL
++#define hub_resume		NULL
++#define hub_reset_resume	NULL
+ #endif
+ 
+ 
+@@ -2768,6 +2774,7 @@ static struct usb_driver hub_driver = {
+ 	.disconnect =	hub_disconnect,
+ 	.suspend =	hub_suspend,
+ 	.resume =	hub_resume,
++	.reset_resume =	hub_reset_resume,
+ 	.pre_reset =	hub_pre_reset,
+ 	.post_reset =	hub_post_reset,
+ 	.ioctl =	hub_ioctl,
+@@ -3021,6 +3028,7 @@ int usb_reset_composite_device(struct usb_device *udev,
+ 				drv = to_usb_driver(cintf->dev.driver);
+ 				if (drv->pre_reset)
+ 					(drv->pre_reset)(cintf);
++	/* FIXME: Unbind if pre_reset returns an error or isn't defined */
+ 			}
+ 		}
+ 	}
+@@ -3038,7 +3046,8 @@ int usb_reset_composite_device(struct usb_device *udev,
+ 					cintf->dev.driver) {
+ 				drv = to_usb_driver(cintf->dev.driver);
+ 				if (drv->post_reset)
+-					(drv->post_reset)(cintf, 0);
++					(drv->post_reset)(cintf);
++	/* FIXME: Unbind if post_reset returns an error or isn't defined */
+ 			}
+ 			if (cintf != iface)
+ 				up(&cintf->dev.sem);
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index e227f64d5641..1ba19eaa1970 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -321,10 +321,14 @@ void usb_stor_report_device_reset(struct us_data *us)
+ 
+ /* Report a driver-initiated bus reset to the SCSI layer.
+  * Calling this for a SCSI-initiated reset is unnecessary but harmless.
+- * The caller must own the SCSI host lock. */
++ * The caller must not own the SCSI host lock. */
+ void usb_stor_report_bus_reset(struct us_data *us)
+ {
+-	scsi_report_bus_reset(us_to_host(us), 0);
++	struct Scsi_Host *host = us_to_host(us);
++
++	scsi_lock(host);
++	scsi_report_bus_reset(host, 0);
++	scsi_unlock(host);
+ }
+ 
+ /***********************************************************************
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index be4cd8fe4ce6..00521f1d6a6b 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -219,6 +219,20 @@ static int storage_resume(struct usb_interface *iface)
+ 	return 0;
+ }
+ 
++static int storage_reset_resume(struct usb_interface *iface)
++{
++	struct us_data *us = usb_get_intfdata(iface);
++
++	US_DEBUGP("%s\n", __FUNCTION__);
++
++	/* Report the reset to the SCSI core */
++	usb_stor_report_bus_reset(us);
++
++	/* FIXME: Notify the subdrivers that they need to reinitialize
++	 * the device */
++	return 0;
++}
++
+ #endif /* CONFIG_PM */
+ 
+ /*
+@@ -226,7 +240,7 @@ static int storage_resume(struct usb_interface *iface)
+  * a USB port reset, whether from this driver or a different one.
+  */
+ 
+-static void storage_pre_reset(struct usb_interface *iface)
++static int storage_pre_reset(struct usb_interface *iface)
+ {
+ 	struct us_data *us = usb_get_intfdata(iface);
+ 
+@@ -234,26 +248,23 @@ static void storage_pre_reset(struct usb_interface *iface)
+ 
+ 	/* Make sure no command runs during the reset */
+ 	mutex_lock(&us->dev_mutex);
++	return 0;
+ }
+ 
+-static void storage_post_reset(struct usb_interface *iface, int reset_resume)
++static int storage_post_reset(struct usb_interface *iface)
+ {
+ 	struct us_data *us = usb_get_intfdata(iface);
+ 
+ 	US_DEBUGP("%s\n", __FUNCTION__);
+ 
+ 	/* Report the reset to the SCSI core */
+-	scsi_lock(us_to_host(us));
+ 	usb_stor_report_bus_reset(us);
+-	scsi_unlock(us_to_host(us));
+ 
+ 	/* FIXME: Notify the subdrivers that they need to reinitialize
+ 	 * the device */
+ 
+-	/* If this is a reset-resume then the pre_reset routine wasn't
+-	 * called, so we don't need to unlock the mutex. */
+-	if (!reset_resume)
+-		mutex_unlock(&us->dev_mutex);
++	mutex_unlock(&us->dev_mutex);
++	return 0;
+ }
+ 
+ /*
+@@ -1061,6 +1072,7 @@ static struct usb_driver usb_storage_driver = {
+ #ifdef CONFIG_PM
+ 	.suspend =	storage_suspend,
+ 	.resume =	storage_resume,
++	.reset_resume =	storage_reset_resume,
+ #endif
+ 	.pre_reset =	storage_pre_reset,
+ 	.post_reset =	storage_post_reset,
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 0873c6219efc..bde8c65e2bfc 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -839,6 +839,8 @@ struct usbdrv_wrap {
+  *	do (or don't) show up otherwise in the filesystem.
+  * @suspend: Called when the device is going to be suspended by the system.
+  * @resume: Called when the device is being resumed by the system.
++ * @reset_resume: Called when the suspended device has been reset instead
++ *	of being resumed.
+  * @pre_reset: Called by usb_reset_composite_device() when the device
+  *	is about to be reset.
+  * @post_reset: Called by usb_reset_composite_device() after the device
+@@ -885,9 +887,10 @@ struct usb_driver {
+ 
+ 	int (*suspend) (struct usb_interface *intf, pm_message_t message);
+ 	int (*resume) (struct usb_interface *intf);
++	int (*reset_resume)(struct usb_interface *intf);
+ 
+-	void (*pre_reset) (struct usb_interface *intf);
+-	void (*post_reset) (struct usb_interface *intf, int reset_resume);
++	int (*pre_reset)(struct usb_interface *intf);
++	int (*post_reset)(struct usb_interface *intf);
+ 
+ 	const struct usb_device_id *id_table;
+ 

commit 624d6c0732d2c4ac00945ad79dbb6ff39ba90ee3
+Author: Alan Stern 
+Date:   Wed May 30 15:35:16 2007 -0400
+
+    USB: remove excess code from hub.c
+    
+    This patch (as917) removes a now-unnecessary level of subroutine
+    nesting from hub.c.  Since usb_port_suspend() does nothing but call
+    hub_port_suspend(), and usb_port_resume() does nothing but call
+    hub_port_resume(), there's no reason to keep the routines separate.
+    
+    Also included in the patch are a few cosmetic changes involving
+    whitespace and use of braces.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index ac1ef1527dd2..ca3dbf84e800 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1625,6 +1625,19 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
+ #ifdef	CONFIG_USB_SUSPEND
+ 
+ /*
++ * usb_port_suspend - suspend a usb device's upstream port
++ * @udev: device that's no longer in active use, not a root hub
++ * Context: must be able to sleep; device not locked; pm locks held
++ *
++ * Suspends a USB device that isn't in active use, conserving power.
++ * Devices may wake out of a suspend, if anything important happens,
++ * using the remote wakeup mechanism.  They may also be taken out of
++ * suspend by the host, using usb_port_resume().  It's also routine
++ * to disconnect devices while they are suspended.
++ *
++ * This only affects the USB hardware for a device; its interfaces
++ * (and, for hubs, child devices) must already have been suspended.
++ *
+  * Selective port suspend reduces power; most suspended devices draw
+  * less than 500 uA.  It's also used in OTG, along with remote wakeup.
+  * All devices below the suspended port are also suspended.
+@@ -1633,11 +1646,35 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
+  * also support "remote wakeup", where the device can activate the USB
+  * tree above them to deliver data, such as a keypress or packet.  In
+  * some cases, this wakes the USB host.
++ *
++ * Suspending OTG devices may trigger HNP, if that's been enabled
++ * between a pair of dual-role devices.  That will change roles, such
++ * as from A-Host to A-Peripheral or from B-Host back to B-Peripheral.
++ *
++ * Devices on USB hub ports have only one "suspend" state, corresponding
++ * to ACPI D2, "may cause the device to lose some context".
++ * State transitions include:
++ *
++ *   - suspend, resume ... when the VBUS power link stays live
++ *   - suspend, disconnect ... VBUS lost
++ *
++ * Once VBUS drop breaks the circuit, the port it's using has to go through
++ * normal re-enumeration procedures, starting with enabling VBUS power.
++ * Other than re-initializing the hub (plug/unplug, except for root hubs),
++ * Linux (2.6) currently has NO mechanisms to initiate that:  no khubd
++ * timer, no SRP, no requests through sysfs.
++ *
++ * If CONFIG_USB_SUSPEND isn't enabled, devices only really suspend when
++ * the root hub for their bus goes into global suspend ... so we don't
++ * (falsely) update the device power state to say it suspended.
++ *
++ * Returns 0 on success, else negative errno.
+  */
+-static int hub_port_suspend(struct usb_hub *hub, int port1,
+-		struct usb_device *udev)
++int usb_port_suspend(struct usb_device *udev)
+ {
+-	int	status;
++	struct usb_hub	*hub = hdev_to_hub(udev->parent);
++	int		port1 = udev->portnum;
++	int		status;
+ 
+ 	// dev_dbg(hub->intfdev, "suspend port %d\n", port1);
+ 
+@@ -1654,17 +1691,15 @@ static int hub_port_suspend(struct usb_hub *hub, int port1,
+ 				NULL, 0,
+ 				USB_CTRL_SET_TIMEOUT);
+ 		if (status)
+-			dev_dbg(&udev->dev,
+-				"won't remote wakeup, status %d\n",
+-				status);
++			dev_dbg(&udev->dev, "won't remote wakeup, status %d\n",
++					status);
+ 	}
+ 
+ 	/* see 7.1.7.6 */
+ 	status = set_port_feature(hub->hdev, port1, USB_PORT_FEAT_SUSPEND);
+ 	if (status) {
+-		dev_dbg(hub->intfdev,
+-			"can't suspend port %d, status %d\n",
+-			port1, status);
++		dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",
++				port1, status);
+ 		/* paranoia:  "should not happen" */
+ 		(void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ 				USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE,
+@@ -1681,52 +1716,6 @@ static int hub_port_suspend(struct usb_hub *hub, int port1,
+ 	return status;
+ }
+ 
+-/*
+- * usb_port_suspend - suspend a usb device's upstream port
+- * @udev: device that's no longer in active use
+- * Context: must be able to sleep; device not locked; pm locks held
+- *
+- * Suspends a USB device that isn't in active use, conserving power.
+- * Devices may wake out of a suspend, if anything important happens,
+- * using the remote wakeup mechanism.  They may also be taken out of
+- * suspend by the host, using usb_port_resume().  It's also routine
+- * to disconnect devices while they are suspended.
+- *
+- * This only affects the USB hardware for a device; its interfaces
+- * (and, for hubs, child devices) must already have been suspended.
+- *
+- * Suspending OTG devices may trigger HNP, if that's been enabled
+- * between a pair of dual-role devices.  That will change roles, such
+- * as from A-Host to A-Peripheral or from B-Host back to B-Peripheral.
+- *
+- * Devices on USB hub ports have only one "suspend" state, corresponding
+- * to ACPI D2, "may cause the device to lose some context".
+- * State transitions include:
+- *
+- *   - suspend, resume ... when the VBUS power link stays live
+- *   - suspend, disconnect ... VBUS lost
+- *
+- * Once VBUS drop breaks the circuit, the port it's using has to go through
+- * normal re-enumeration procedures, starting with enabling VBUS power.
+- * Other than re-initializing the hub (plug/unplug, except for root hubs),
+- * Linux (2.6) currently has NO mechanisms to initiate that:  no khubd
+- * timer, no SRP, no requests through sysfs.
+- *
+- * If CONFIG_USB_SUSPEND isn't enabled, devices only really suspend when
+- * the root hub for their bus goes into global suspend ... so we don't
+- * (falsely) update the device power state to say it suspended.
+- *
+- * Returns 0 on success, else negative errno.
+- */
+-int usb_port_suspend(struct usb_device *udev)
+-{
+-	int	status = 0;
+-
+-	status = hub_port_suspend(hdev_to_hub(udev->parent),
+-			udev->portnum, udev);
+-	return status;
+-}
+-
+ /*
+  * If the USB "suspend" state is in use (rather than "global suspend"),
+  * many devices will be individually taken out of suspend state using
+@@ -1760,11 +1749,10 @@ static int finish_port_resume(struct usb_device *udev)
+ 	if (status >= 0)
+ 		status = (status == 2 ? 0 : -ENODEV);
+ 
+-	if (status)
+-		dev_dbg(&udev->dev,
+-			"gone after usb resume? status %d\n",
+-			status);
+-	else if (udev->actconfig) {
++	if (status) {
++		dev_dbg(&udev->dev, "gone after usb resume? status %d\n",
++				status);
++	} else if (udev->actconfig) {
+ 		le16_to_cpus(&devstatus);
+ 		if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) {
+ 			status = usb_control_msg(udev,
+@@ -1783,11 +1771,25 @@ static int finish_port_resume(struct usb_device *udev)
+ 	return status;
+ }
+ 
+-static int
+-hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
++/*
++ * usb_port_resume - re-activate a suspended usb device's upstream port
++ * @udev: device to re-activate, not a root hub
++ * Context: must be able to sleep; device not locked; pm locks held
++ *
++ * This will re-activate the suspended device, increasing power usage
++ * while letting drivers communicate again with its endpoints.
++ * USB resume explicitly guarantees that the power session between
++ * the host and the device is the same as it was when the device
++ * suspended.
++ *
++ * Returns 0 on success, else negative errno.
++ */
++int usb_port_resume(struct usb_device *udev)
+ {
+-	int	status;
+-	u16	portchange, portstatus;
++	struct usb_hub	*hub = hdev_to_hub(udev->parent);
++	int		port1 = udev->portnum;
++	int		status;
++	u16		portchange, portstatus;
+ 
+ 	/* Skip the initial Clear-Suspend step for a remote wakeup */
+ 	status = hub_port_status(hub, port1, &portstatus, &portchange);
+@@ -1802,9 +1804,8 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+ 	status = clear_port_feature(hub->hdev,
+ 			port1, USB_PORT_FEAT_SUSPEND);
+ 	if (status) {
+-		dev_dbg(hub->intfdev,
+-			"can't resume port %d, status %d\n",
+-			port1, status);
++		dev_dbg(hub->intfdev, "can't resume port %d, status %d\n",
++				port1, status);
+ 	} else {
+ 		/* drive resume for at least 20 msec */
+ 		dev_dbg(&udev->dev, "usb %sresume\n",
+@@ -1839,8 +1840,10 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+ 			status = finish_port_resume(udev);
+ 		}
+ 	}
+-	if (status < 0)
++	if (status < 0) {
++		dev_dbg(&udev->dev, "can't resume, status %d\n", status);
+ 		hub_port_logical_disconnect(hub, port1);
++	}
+ 
+ 	clear_bit(port1, hub->busy_bits);
+ 	if (!hub->hdev->parent && !hub->busy_bits[0])
+@@ -1849,30 +1852,6 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+ 	return status;
+ }
+ 
+-/*
+- * usb_port_resume - re-activate a suspended usb device's upstream port
+- * @udev: device to re-activate
+- * Context: must be able to sleep; device not locked; pm locks held
+- *
+- * This will re-activate the suspended device, increasing power usage
+- * while letting drivers communicate again with its endpoints.
+- * USB resume explicitly guarantees that the power session between
+- * the host and the device is the same as it was when the device
+- * suspended.
+- *
+- * Returns 0 on success, else negative errno.
+- */
+-int usb_port_resume(struct usb_device *udev)
+-{
+-	int	status;
+-
+-	status = hub_port_resume(hdev_to_hub(udev->parent),
+-			udev->portnum, udev);
+-	if (status < 0)
+-		dev_dbg(&udev->dev, "can't resume, status %d\n", status);
+-	return status;
+-}
+-
+ static int remote_wakeup(struct usb_device *udev)
+ {
+ 	int	status = 0;
+@@ -1896,18 +1875,6 @@ int usb_port_suspend(struct usb_device *udev)
+ 	return 0;
+ }
+ 
+-static inline int
+-finish_port_resume(struct usb_device *udev)
+-{
+-	return 0;
+-}
+-
+-static inline int
+-hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+-{
+-	return 0;
+-}
+-
+ int usb_port_resume(struct usb_device *udev)
+ {
+ 	return 0;

commit 686314cfbdac21c9019c0e04487b5d940db62406
+Author: Alan Stern 
+Date:   Wed May 30 15:34:36 2007 -0400
+
+    USB: separate root and non-root suspend/resume
+    
+    This patch (as916) completes the separation of code paths for suspend
+    and resume of root hubs as opposed to non-root devices.  Root hubs
+    will be power-managed through their bus_suspend and bus_resume
+    methods, whereas normal devices will use usb_port_suspend() and
+    usb_port_resume().
+    
+    Changes to the hcd_bus_{suspend,resume} routines mostly represent
+    motion of code that was already present elsewhere.  They include:
+    
+            Adding debugging log messages,
+    
+            Setting the device state appropriately, and
+    
+            Adding a resume recovery time delay.
+    
+    Changes to the port-suspend and port-resume routines in hub.c include:
+    
+            Removal of checks for root devices (since they will never
+            be triggered), and
+    
+            Removal of checks for NULL or invalid device pointers (these
+            were left over from earlier kernel versions and aren't needed
+            at all).
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
+index d363b0ea7345..4cbe7b339513 100644
+--- a/drivers/usb/core/generic.c
++++ b/drivers/usb/core/generic.c
+@@ -196,20 +196,15 @@ static int generic_suspend(struct usb_device *udev, pm_message_t msg)
+ {
+ 	int rc;
+ 
+-	rc = usb_port_suspend(udev);
+-
+-	/* Root hubs don't have upstream ports to suspend,
+-	 * so the line above won't do much for them.  We have to
+-	 * shut down their downstream HC-to-USB interfaces manually,
+-	 * by doing a bus (or "global") suspend.
++	/* Normal USB devices suspend through their upstream port.
++	 * Root hubs don't have upstream ports to suspend,
++	 * so we have to shut down their downstream HC-to-USB
++	 * interfaces manually by doing a bus (or "global") suspend.
+ 	 */
+-	if (rc == 0 && !udev->parent) {
+-		rc = hcd_bus_suspend(udev->bus);
+-		if (rc) {
+-			dev_dbg(&udev->dev, "'global' suspend %d\n", rc);
+-			usb_port_resume(udev);
+-		}
+-	}
++	if (!udev->parent)
++		rc = hcd_bus_suspend(udev);
++	else
++		rc = usb_port_suspend(udev);
+ 	return rc;
+ }
+ 
+@@ -217,25 +212,17 @@ static int generic_resume(struct usb_device *udev)
+ {
+ 	int rc;
+ 
+-	if (udev->reset_resume)
++	/* Normal USB devices resume/reset through their upstream port.
++	 * Root hubs don't have upstream ports to resume or reset,
++	 * so we have to start up their downstream HC-to-USB
++	 * interfaces manually by doing a bus (or "global") resume.
++	 */
++	if (!udev->parent)
++		rc = hcd_bus_resume(udev);
++	else if (udev->reset_resume)
+ 		rc = usb_reset_suspended_device(udev);
+ 	else
+ 		rc = usb_port_resume(udev);
+-
+-	/* Root hubs don't have upstream ports to resume or reset,
+-	 * so the line above won't do much for them.  We have to
+-	 * start up their downstream HC-to-USB interfaces manually,
+-	 * by doing a bus (or "global") resume.
+-	 */
+-	if (rc == 0 && !udev->parent) {
+-		rc = hcd_bus_resume(udev->bus);
+-		if (rc)
+-			dev_dbg(&udev->dev, "'global' resume %d\n", rc);
+-		else {
+-			/* TRSMRCY = 10 msec */
+-			msleep(10);
+-		}
+-	}
+ 	return rc;
+ }
+ 
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 87d6edf11f92..e5058fb26a7e 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1257,40 +1257,54 @@ void usb_hcd_endpoint_disable (struct usb_device *udev,
+ 
+ #ifdef	CONFIG_PM
+ 
+-int hcd_bus_suspend (struct usb_bus *bus)
++int hcd_bus_suspend(struct usb_device *rhdev)
+ {
+-	struct usb_hcd		*hcd;
+-	int			status;
++	struct usb_hcd	*hcd = container_of(rhdev->bus, struct usb_hcd, self);
++	int		status;
++	int		old_state = hcd->state;
+ 
+-	hcd = container_of (bus, struct usb_hcd, self);
+-	if (!hcd->driver->bus_suspend)
+-		return -ENOENT;
+-	hcd->state = HC_STATE_QUIESCING;
+-	status = hcd->driver->bus_suspend (hcd);
+-	if (status == 0)
++	dev_dbg(&rhdev->dev, "bus %s%s\n",
++			rhdev->auto_pm ? "auto-" : "", "suspend");
++	if (!hcd->driver->bus_suspend) {
++		status = -ENOENT;
++	} else {
++		hcd->state = HC_STATE_QUIESCING;
++		status = hcd->driver->bus_suspend(hcd);
++	}
++	if (status == 0) {
++		usb_set_device_state(rhdev, USB_STATE_SUSPENDED);
+ 		hcd->state = HC_STATE_SUSPENDED;
+-	else
+-		dev_dbg(&bus->root_hub->dev, "%s fail, err %d\n",
++	} else {
++		hcd->state = old_state;
++		dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
+ 				"suspend", status);
++	}
+ 	return status;
+ }
+ 
+-int hcd_bus_resume (struct usb_bus *bus)
++int hcd_bus_resume(struct usb_device *rhdev)
+ {
+-	struct usb_hcd		*hcd;
+-	int			status;
++	struct usb_hcd	*hcd = container_of(rhdev->bus, struct usb_hcd, self);
++	int		status;
+ 
+-	hcd = container_of (bus, struct usb_hcd, self);
++	dev_dbg(&rhdev->dev, "usb %s%s\n",
++			rhdev->auto_pm ? "auto-" : "", "resume");
+ 	if (!hcd->driver->bus_resume)
+ 		return -ENOENT;
+ 	if (hcd->state == HC_STATE_RUNNING)
+ 		return 0;
++
+ 	hcd->state = HC_STATE_RESUMING;
+-	status = hcd->driver->bus_resume (hcd);
+-	if (status == 0)
++	status = hcd->driver->bus_resume(hcd);
++	if (status == 0) {
++		/* TRSMRCY = 10 msec */
++		msleep(10);
++		usb_set_device_state(rhdev, rhdev->actconfig
++				? USB_STATE_CONFIGURED
++				: USB_STATE_ADDRESS);
+ 		hcd->state = HC_STATE_RUNNING;
+-	else {
+-		dev_dbg(&bus->root_hub->dev, "%s fail, err %d\n",
++	} else {
++		dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
+ 				"resume", status);
+ 		usb_hc_died(hcd);
+ 	}
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index ef50fa494e47..b5ebb73c2332 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -364,23 +364,13 @@ extern int usb_find_interface_driver (struct usb_device *dev,
+ #ifdef CONFIG_PM
+ extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
+ extern void usb_root_hub_lost_power (struct usb_device *rhdev);
+-extern int hcd_bus_suspend (struct usb_bus *bus);
+-extern int hcd_bus_resume (struct usb_bus *bus);
++extern int hcd_bus_suspend(struct usb_device *rhdev);
++extern int hcd_bus_resume(struct usb_device *rhdev);
+ #else
+ static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
+ {
+ 	return;
+ }
+-
+-static inline int hcd_bus_suspend(struct usb_bus *bus)
+-{
+-	return 0;
+-}
+-
+-static inline int hcd_bus_resume (struct usb_bus *bus)
+-{
+-	return 0;
+-}
+ #endif /* CONFIG_PM */
+ 
+ /*
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 04d6fde57d88..ac1ef1527dd2 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1722,17 +1722,8 @@ int usb_port_suspend(struct usb_device *udev)
+ {
+ 	int	status = 0;
+ 
+-	/* we change the device's upstream USB link,
+-	 * but root hubs have no upstream USB link.
+-	 */
+-	if (udev->parent)
+-		status = hub_port_suspend(hdev_to_hub(udev->parent),
+-				udev->portnum, udev);
+-	else {
+-		dev_dbg(&udev->dev, "usb %ssuspend\n",
+-				udev->auto_pm ? "auto-" : "");
+-		usb_set_device_state(udev, USB_STATE_SUSPENDED);
+-	}
++	status = hub_port_suspend(hdev_to_hub(udev->parent),
++			udev->portnum, udev);
+ 	return status;
+ }
+ 
+@@ -1775,8 +1766,7 @@ static int finish_port_resume(struct usb_device *udev)
+ 			status);
+ 	else if (udev->actconfig) {
+ 		le16_to_cpus(&devstatus);
+-		if ((devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP))
+-				&& udev->parent) {
++		if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) {
+ 			status = usb_control_msg(udev,
+ 					usb_sndctrlpipe(udev, 0),
+ 					USB_REQ_CLEAR_FEATURE,
+@@ -1789,10 +1779,6 @@ static int finish_port_resume(struct usb_device *udev)
+ 					"wakeup, status %d\n", status);
+ 		}
+ 		status = 0;
+-
+-	} else if (udev->devnum <= 0) {
+-		dev_dbg(&udev->dev, "bogus resume!\n");
+-		status = -EINVAL;
+ 	}
+ 	return status;
+ }
+@@ -1821,9 +1807,8 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+ 			port1, status);
+ 	} else {
+ 		/* drive resume for at least 20 msec */
+-		if (udev)
+-			dev_dbg(&udev->dev, "usb %sresume\n",
+-					udev->auto_pm ? "auto-" : "");
++		dev_dbg(&udev->dev, "usb %sresume\n",
++				udev->auto_pm ? "auto-" : "");
+ 		msleep(25);
+ 
+ #define LIVE_FLAGS	( USB_PORT_STAT_POWER \
+@@ -1851,8 +1836,7 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+ 						USB_PORT_FEAT_C_SUSPEND);
+ 			/* TRSMRCY = 10 msec */
+ 			msleep(10);
+-			if (udev)
+-				status = finish_port_resume(udev);
++			status = finish_port_resume(udev);
+ 		}
+ 	}
+ 	if (status < 0)
+@@ -1882,18 +1866,8 @@ int usb_port_resume(struct usb_device *udev)
+ {
+ 	int	status;
+ 
+-	/* we change the device's upstream USB link,
+-	 * but root hubs have no upstream USB link.
+-	 */
+-	if (udev->parent) {
+-		// NOTE this fails if parent is also suspended...
+-		status = hub_port_resume(hdev_to_hub(udev->parent),
+-				udev->portnum, udev);
+-	} else {
+-		dev_dbg(&udev->dev, "usb %sresume\n",
+-				udev->auto_pm ? "auto-" : "");
+-		status = finish_port_resume(udev);
+-	}
++	status = hub_port_resume(hdev_to_hub(udev->parent),
++			udev->portnum, udev);
+ 	if (status < 0)
+ 		dev_dbg(&udev->dev, "can't resume, status %d\n", status);
+ 	return status;

commit 4956eccdd6101c5abb71966079e8183d12796d6c
+Author: Alan Stern 
+Date:   Wed May 30 16:51:28 2007 -0400
+
+    USB: remove __usb_port_suspend
+    
+    This patch (as915b) combines the public routine usb_port_suspend() and
+    the private routine __usb_port_suspend() into a single function.
+    
+    By removing the explicit mention of otg_port in the call to
+    __usb_port_suspend(), we prevent a possible error in which the system
+    tries to perform HNP on the wrong port when a non-targeted device is
+    plugged into a non-OTG port.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 7946d7b6c71a..04d6fde57d88 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1333,7 +1333,6 @@ static inline void show_string(struct usb_device *udev, char *id, char *string)
+ 
+ #ifdef	CONFIG_USB_OTG
+ #include "otg_whitelist.h"
+-static int __usb_port_suspend(struct usb_device *, int port1);
+ #endif
+ 
+ /**
+@@ -1439,7 +1438,7 @@ int usb_new_device(struct usb_device *udev)
+ 		 * (Includes HNP test device.)
+ 		 */
+ 		if (udev->bus->b_hnp_enable || udev->bus->is_b_host) {
+-			err = __usb_port_suspend(udev, udev->bus->otg_port);
++			err = usb_port_suspend(udev);
+ 			if (err < 0)
+ 				dev_dbg(&udev->dev, "HNP fail, %d\n", err);
+ 		}
+@@ -1683,6 +1682,23 @@ static int hub_port_suspend(struct usb_hub *hub, int port1,
+ }
+ 
+ /*
++ * usb_port_suspend - suspend a usb device's upstream port
++ * @udev: device that's no longer in active use
++ * Context: must be able to sleep; device not locked; pm locks held
++ *
++ * Suspends a USB device that isn't in active use, conserving power.
++ * Devices may wake out of a suspend, if anything important happens,
++ * using the remote wakeup mechanism.  They may also be taken out of
++ * suspend by the host, using usb_port_resume().  It's also routine
++ * to disconnect devices while they are suspended.
++ *
++ * This only affects the USB hardware for a device; its interfaces
++ * (and, for hubs, child devices) must already have been suspended.
++ *
++ * Suspending OTG devices may trigger HNP, if that's been enabled
++ * between a pair of dual-role devices.  That will change roles, such
++ * as from A-Host to A-Peripheral or from B-Host back to B-Peripheral.
++ *
+  * Devices on USB hub ports have only one "suspend" state, corresponding
+  * to ACPI D2, "may cause the device to lose some context".
+  * State transitions include:
+@@ -1699,21 +1715,19 @@ static int hub_port_suspend(struct usb_hub *hub, int port1,
+  * If CONFIG_USB_SUSPEND isn't enabled, devices only really suspend when
+  * the root hub for their bus goes into global suspend ... so we don't
+  * (falsely) update the device power state to say it suspended.
++ *
++ * Returns 0 on success, else negative errno.
+  */
+-static int __usb_port_suspend (struct usb_device *udev, int port1)
++int usb_port_suspend(struct usb_device *udev)
+ {
+ 	int	status = 0;
+ 
+-	/* caller owns the udev device lock */
+-	if (port1 < 0)
+-		return port1;
+-
+ 	/* we change the device's upstream USB link,
+ 	 * but root hubs have no upstream USB link.
+ 	 */
+ 	if (udev->parent)
+-		status = hub_port_suspend(hdev_to_hub(udev->parent), port1,
+-				udev);
++		status = hub_port_suspend(hdev_to_hub(udev->parent),
++				udev->portnum, udev);
+ 	else {
+ 		dev_dbg(&udev->dev, "usb %ssuspend\n",
+ 				udev->auto_pm ? "auto-" : "");
+@@ -1722,31 +1736,6 @@ static int __usb_port_suspend (struct usb_device *udev, int port1)
+ 	return status;
+ }
+ 
+-/*
+- * usb_port_suspend - suspend a usb device's upstream port
+- * @udev: device that's no longer in active use
+- * Context: must be able to sleep; device not locked; pm locks held
+- *
+- * Suspends a USB device that isn't in active use, conserving power.
+- * Devices may wake out of a suspend, if anything important happens,
+- * using the remote wakeup mechanism.  They may also be taken out of
+- * suspend by the host, using usb_port_resume().  It's also routine
+- * to disconnect devices while they are suspended.
+- *
+- * This only affects the USB hardware for a device; its interfaces
+- * (and, for hubs, child devices) must already have been suspended.
+- *
+- * Suspending OTG devices may trigger HNP, if that's been enabled
+- * between a pair of dual-role devices.  That will change roles, such
+- * as from A-Host to A-Peripheral or from B-Host back to B-Peripheral.
+- *
+- * Returns 0 on success, else negative errno.
+- */
+-int usb_port_suspend(struct usb_device *udev)
+-{
+-	return __usb_port_suspend(udev, udev->portnum);
+-}
+-
+ /*
+  * If the USB "suspend" state is in use (rather than "global suspend"),
+  * many devices will be individually taken out of suspend state using
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 1a4862886733..a547499c45f4 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -53,8 +53,16 @@ static inline void usb_pm_unlock(struct usb_device *udev)
+ 
+ #else
+ 
+-#define usb_port_suspend(dev)		0
+-#define usb_port_resume(dev)		0
++static inline int usb_port_suspend(struct usb_device *udev)
++{
++	return 0;
++}
++
++static inline int usb_port_resume(struct usb_device *udev)
++{
++	return 0;
++}
++
+ static inline void usb_pm_lock(struct usb_device *udev) {}
+ static inline void usb_pm_unlock(struct usb_device *udev) {}
+ 

commit 20dfdad74a2baabeecc2896c770efcbf698b9b8d
+Author: Alan Stern 
+Date:   Tue May 22 11:50:17 2007 -0400
+
+    USB: rework C++-style comments
+    
+    This patch (as911) replaces some C++-style commented-out debugging
+    lines in driver.c with a new "verbose debugging" macro.  It makes the
+    code look cleaner, and it's easier to turn the debugging on or off.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 02d6db61c940..6c62a6d91484 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -29,6 +29,14 @@
+ #include "hcd.h"
+ #include "usb.h"
+ 
++#define VERBOSE_DEBUG	0
++
++#if VERBOSE_DEBUG
++#define dev_vdbg	dev_dbg
++#else
++#define dev_vdbg(dev, fmt, args...)	do { } while (0)
++#endif
++
+ #ifdef CONFIG_HOTPLUG
+ 
+ /*
+@@ -812,8 +820,8 @@ static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
+ 	}
+ 	status = udriver->suspend(udev, msg);
+ 
+-done:
+-	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
++ done:
++	dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+ 	if (status == 0)
+ 		udev->dev.power.power_state.event = msg.event;
+ 	return status;
+@@ -842,8 +850,8 @@ static int usb_resume_device(struct usb_device *udev)
+ 	udriver = to_usb_device_driver(udev->dev.driver);
+ 	status = udriver->resume(udev);
+ 
+-done:
+-	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
++ done:
++	dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+ 	if (status == 0) {
+ 		udev->autoresume_disabled = 0;
+ 		udev->dev.power.power_state.event = PM_EVENT_ON;
+@@ -881,8 +889,8 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
+ 		mark_quiesced(intf);
+ 	}
+ 
+-done:
+-	// dev_dbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
++ done:
++	dev_vdbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
+ 	return status;
+ }
+ 
+@@ -919,7 +927,7 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
+ 				driver->name);
+ 
+ done:
+-	// dev_dbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
++	dev_vdbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
+ 	if (status == 0)
+ 		mark_active(intf);
+ 	return status;
+@@ -1083,7 +1091,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 	}
+ 
+  done:
+-	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
++	dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+ 	return status;
+ }
+ 
+@@ -1180,7 +1188,7 @@ static int usb_resume_both(struct usb_device *udev)
+ 	}
+ 
+  done:
+-	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
++	dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+ 	udev->reset_resume = 0;
+ 	return status;
+ }
+@@ -1248,8 +1256,8 @@ void usb_autosuspend_device(struct usb_device *udev)
+ 	int	status;
+ 
+ 	status = usb_autopm_do_device(udev, -1);
+-	// dev_dbg(&udev->dev, "%s: cnt %d\n",
+-	//		__FUNCTION__, udev->pm_usage_cnt);
++	dev_vdbg(&udev->dev, "%s: cnt %d\n",
++			__FUNCTION__, udev->pm_usage_cnt);
+ }
+ 
+ /**
+@@ -1268,8 +1276,8 @@ void usb_autosuspend_device(struct usb_device *udev)
+ void usb_try_autosuspend_device(struct usb_device *udev)
+ {
+ 	usb_autopm_do_device(udev, 0);
+-	// dev_dbg(&udev->dev, "%s: cnt %d\n",
+-	// 		__FUNCTION__, udev->pm_usage_cnt);
++	dev_vdbg(&udev->dev, "%s: cnt %d\n",
++			__FUNCTION__, udev->pm_usage_cnt);
+ }
+ 
+ /**
+@@ -1296,8 +1304,8 @@ int usb_autoresume_device(struct usb_device *udev)
+ 	int	status;
+ 
+ 	status = usb_autopm_do_device(udev, 1);
+-	// dev_dbg(&udev->dev, "%s: status %d cnt %d\n",
+-	//		__FUNCTION__, status, udev->pm_usage_cnt);
++	dev_vdbg(&udev->dev, "%s: status %d cnt %d\n",
++			__FUNCTION__, status, udev->pm_usage_cnt);
+ 	return status;
+ }
+ 
+@@ -1369,8 +1377,8 @@ void usb_autopm_put_interface(struct usb_interface *intf)
+ 	int	status;
+ 
+ 	status = usb_autopm_do_interface(intf, -1);
+-	// dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
+-	//		__FUNCTION__, status, intf->pm_usage_cnt);
++	dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
++			__FUNCTION__, status, intf->pm_usage_cnt);
+ }
+ EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
+ 
+@@ -1413,8 +1421,8 @@ int usb_autopm_get_interface(struct usb_interface *intf)
+ 	int	status;
+ 
+ 	status = usb_autopm_do_interface(intf, 1);
+-	// dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
+-	//		__FUNCTION__, status, intf->pm_usage_cnt);
++	dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
++			__FUNCTION__, status, intf->pm_usage_cnt);
+ 	return status;
+ }
+ EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
+@@ -1435,8 +1443,8 @@ int usb_autopm_set_interface(struct usb_interface *intf)
+ 	int	status;
+ 
+ 	status = usb_autopm_do_interface(intf, 0);
+-	// dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
+-	//		__FUNCTION__, status, intf->pm_usage_cnt);
++	dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
++			__FUNCTION__, status, intf->pm_usage_cnt);
+ 	return status;
+ }
+ EXPORT_SYMBOL_GPL(usb_autopm_set_interface);

commit d4ead16f50f9ad30bdc7276ec8fee7a24c72f294
+Author: Alan Stern 
+Date:   Tue May 22 11:46:41 2007 -0400
+
+    USB: prevent char device open/deregister race
+    
+    This patch (as908) adds central protection in usbcore for the
+    prototypical race between opening and unregistering a char device.
+    The spinlock used to protect the minor-numbers array is replaced with
+    an rwsem, which can remain locked across a call to a driver's open()
+    method.  This guarantees that open() and deregister() will be mutually
+    exclusive.
+    
+    The private locks currently used in several individual drivers for
+    this purpose are no longer necessary, and the patch removes them.  The
+    following USB drivers are affected: usblcd, idmouse, auerswald,
+    legousbtower, sisusbvga/sisusb, ldusb, adutux, iowarrior, and
+    usb-skeleton.
+    
+    As a side effect of this change, usb_deregister_dev() must not be
+    called while holding a lock that is acquired by open().  Unfortunately
+    a number of drivers do this, but luckily the solution is simple: call
+    usb_deregister_dev() before acquiring the lock.
+    
+    In addition to these changes (and their consequent code
+    simplifications), the patch fixes a use-after-free bug in adutux and a
+    race between open() and release() in iowarrior.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
+index 01c857ac27af..5d860bc9b421 100644
+--- a/drivers/usb/core/file.c
++++ b/drivers/usb/core/file.c
+@@ -16,15 +16,15 @@
+  */
+ 
+ #include 
+-#include 
+ #include 
++#include 
+ #include 
+ 
+ #include "usb.h"
+ 
+ #define MAX_USB_MINORS	256
+ static const struct file_operations *usb_minors[MAX_USB_MINORS];
+-static DEFINE_SPINLOCK(minor_lock);
++static DECLARE_RWSEM(minor_rwsem);
+ 
+ static int usb_open(struct inode * inode, struct file * file)
+ {
+@@ -33,14 +33,11 @@ static int usb_open(struct inode * inode, struct file * file)
+ 	int err = -ENODEV;
+ 	const struct file_operations *old_fops, *new_fops = NULL;
+ 
+-	spin_lock (&minor_lock);
++	down_read(&minor_rwsem);
+ 	c = usb_minors[minor];
+ 
+-	if (!c || !(new_fops = fops_get(c))) {
+-		spin_unlock(&minor_lock);
+-		return err;
+-	}
+-	spin_unlock(&minor_lock);
++	if (!c || !(new_fops = fops_get(c)))
++		goto done;
+ 
+ 	old_fops = file->f_op;
+ 	file->f_op = new_fops;
+@@ -52,6 +49,8 @@ static int usb_open(struct inode * inode, struct file * file)
+ 		file->f_op = fops_get(old_fops);
+ 	}
+ 	fops_put(old_fops);
++ done:
++	up_read(&minor_rwsem);
+ 	return err;
+ }
+ 
+@@ -166,7 +165,7 @@ int usb_register_dev(struct usb_interface *intf,
+ 	if (class_driver->fops == NULL)
+ 		goto exit;
+ 
+-	spin_lock (&minor_lock);
++	down_write(&minor_rwsem);
+ 	for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) {
+ 		if (usb_minors[minor])
+ 			continue;
+@@ -176,7 +175,7 @@ int usb_register_dev(struct usb_interface *intf,
+ 		retval = 0;
+ 		break;
+ 	}
+-	spin_unlock (&minor_lock);
++	up_write(&minor_rwsem);
+ 
+ 	if (retval)
+ 		goto exit;
+@@ -197,9 +196,9 @@ int usb_register_dev(struct usb_interface *intf,
+ 	intf->usb_dev = device_create(usb_class->class, &intf->dev,
+ 				      MKDEV(USB_MAJOR, minor), "%s", temp);
+ 	if (IS_ERR(intf->usb_dev)) {
+-		spin_lock (&minor_lock);
++		down_write(&minor_rwsem);
+ 		usb_minors[intf->minor] = NULL;
+-		spin_unlock (&minor_lock);
++		up_write(&minor_rwsem);
+ 		retval = PTR_ERR(intf->usb_dev);
+ 	}
+ exit:
+@@ -236,9 +235,9 @@ void usb_deregister_dev(struct usb_interface *intf,
+ 
+ 	dbg ("removing %d minor", intf->minor);
+ 
+-	spin_lock (&minor_lock);
++	down_write(&minor_rwsem);
+ 	usb_minors[intf->minor] = NULL;
+-	spin_unlock (&minor_lock);
++	up_write(&minor_rwsem);
+ 
+ 	snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base);
+ 	device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor));
+@@ -247,5 +246,3 @@ void usb_deregister_dev(struct usb_interface *intf,
+ 	destroy_usb_class();
+ }
+ EXPORT_SYMBOL(usb_deregister_dev);
+-
+-
+diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
+index 77145f9db043..d72c42e5f22d 100644
+--- a/drivers/usb/misc/adutux.c
++++ b/drivers/usb/misc/adutux.c
+@@ -108,8 +108,6 @@ struct adu_device {
+ 	struct urb*		interrupt_out_urb;
+ };
+ 
+-/* prevent races between open() and disconnect */
+-static DEFINE_MUTEX(disconnect_mutex);
+ static struct usb_driver adu_driver;
+ 
+ static void adu_debug_data(int level, const char *function, int size,
+@@ -256,8 +254,6 @@ static int adu_open(struct inode *inode, struct file *file)
+ 
+ 	subminor = iminor(inode);
+ 
+-	mutex_lock(&disconnect_mutex);
+-
+ 	interface = usb_find_interface(&adu_driver, subminor);
+ 	if (!interface) {
+ 		err("%s - error, can't find device for minor %d",
+@@ -306,7 +302,6 @@ static int adu_open(struct inode *inode, struct file *file)
+ 	up(&dev->sem);
+ 
+ exit_no_device:
+-	mutex_unlock(&disconnect_mutex);
+ 	dbg(2,"%s : leave, return value %d ", __FUNCTION__, retval);
+ 
+ 	return retval;
+@@ -318,12 +313,6 @@ static int adu_release_internal(struct adu_device *dev)
+ 
+ 	dbg(2," %s : enter", __FUNCTION__);
+ 
+-	if (dev->udev == NULL) {
+-		/* the device was unplugged before the file was released */
+-		adu_delete(dev);
+-		goto exit;
+-	}
+-
+ 	/* decrement our usage count for the device */
+ 	--dev->open_count;
+ 	dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
+@@ -332,7 +321,6 @@ static int adu_release_internal(struct adu_device *dev)
+ 		dev->open_count = 0;
+ 	}
+ 
+-exit:
+ 	dbg(2," %s : leave", __FUNCTION__);
+ 	return retval;
+ }
+@@ -367,8 +355,15 @@ static int adu_release(struct inode *inode, struct file *file)
+ 		goto exit;
+ 	}
+ 
+-	/* do the work */
+-	retval = adu_release_internal(dev);
++	if (dev->udev == NULL) {
++		/* the device was unplugged before the file was released */
++		up(&dev->sem);
++		adu_delete(dev);
++		dev = NULL;
++	} else {
++		/* do the work */
++		retval = adu_release_internal(dev);
++	}
+ 
+ exit:
+ 	if (dev)
+@@ -831,19 +826,17 @@ static void adu_disconnect(struct usb_interface *interface)
+ 
+ 	dbg(2," %s : enter", __FUNCTION__);
+ 
+-	mutex_lock(&disconnect_mutex); /* not interruptible */
+-
+ 	dev = usb_get_intfdata(interface);
+ 	usb_set_intfdata(interface, NULL);
+ 
+-	down(&dev->sem); /* not interruptible */
+-
+ 	minor = dev->minor;
+ 
+ 	/* give back our minor */
+ 	usb_deregister_dev(interface, &adu_class);
+ 	dev->minor = 0;
+ 
++	down(&dev->sem); /* not interruptible */
++
+ 	/* if the device is not opened, then we clean up right now */
+ 	dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
+ 	if (!dev->open_count) {
+@@ -854,8 +847,6 @@ static void adu_disconnect(struct usb_interface *interface)
+ 		up(&dev->sem);
+ 	}
+ 
+-	mutex_unlock(&disconnect_mutex);
+-
+ 	dev_info(&interface->dev, "ADU device adutux%d now disconnected",
+ 		 (minor - ADU_MINOR_BASE));
+ 
+diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
+index cac1500cba62..1fd5fc220cd7 100644
+--- a/drivers/usb/misc/auerswald.c
++++ b/drivers/usb/misc/auerswald.c
+@@ -2034,12 +2034,12 @@ static void auerswald_disconnect (struct usb_interface *intf)
+ 	if (!cp)
+ 		return;
+ 
+-	down (&cp->mutex);
+-	info ("device /dev/%s now disconnecting", cp->name);
+-
+ 	/* give back our USB minor number */
+ 	usb_deregister_dev(intf, &auerswald_class);
+ 
++	down (&cp->mutex);
++	info ("device /dev/%s now disconnecting", cp->name);
++
+ 	/* Stop the interrupt endpoint */
+ 	auerswald_int_release (cp);
+ 
+diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c
+index 8d0e360636e6..e6fd024024f5 100644
+--- a/drivers/usb/misc/idmouse.c
++++ b/drivers/usb/misc/idmouse.c
+@@ -119,9 +119,6 @@ static struct usb_driver idmouse_driver = {
+ 	.id_table = idmouse_table,
+ };
+ 
+-/* prevent races between open() and disconnect() */
+-static DEFINE_MUTEX(disconnect_mutex);
+-
+ static int idmouse_create_image(struct usb_idmouse *dev)
+ {
+ 	int bytes_read;
+@@ -211,21 +208,15 @@ static int idmouse_open(struct inode *inode, struct file *file)
+ 	struct usb_interface *interface;
+ 	int result;
+ 
+-	/* prevent disconnects */
+-	mutex_lock(&disconnect_mutex);
+-
+ 	/* get the interface from minor number and driver information */
+ 	interface = usb_find_interface (&idmouse_driver, iminor (inode));
+-	if (!interface) {
+-		mutex_unlock(&disconnect_mutex);
++	if (!interface)
+ 		return -ENODEV;
+-	}
++
+ 	/* get the device information block from the interface */
+ 	dev = usb_get_intfdata(interface);
+-	if (!dev) {
+-		mutex_unlock(&disconnect_mutex);
++	if (!dev)
+ 		return -ENODEV;
+-	}
+ 
+ 	/* lock this device */
+ 	down(&dev->sem);
+@@ -255,9 +246,6 @@ static int idmouse_open(struct inode *inode, struct file *file)
+ 
+ 	/* unlock this device */
+ 	up(&dev->sem);
+-
+-	/* unlock the disconnect semaphore */
+-	mutex_unlock(&disconnect_mutex);
+ 	return result;
+ }
+ 
+@@ -265,15 +253,10 @@ static int idmouse_release(struct inode *inode, struct file *file)
+ {
+ 	struct usb_idmouse *dev;
+ 
+-	/* prevent a race condition with open() */
+-	mutex_lock(&disconnect_mutex);
+-
+ 	dev = file->private_data;
+ 
+-	if (dev == NULL) {
+-		mutex_unlock(&disconnect_mutex);
++	if (dev == NULL)
+ 		return -ENODEV;
+-	}
+ 
+ 	/* lock our device */
+ 	down(&dev->sem);
+@@ -281,7 +264,6 @@ static int idmouse_release(struct inode *inode, struct file *file)
+ 	/* are we really open? */
+ 	if (dev->open <= 0) {
+ 		up(&dev->sem);
+-		mutex_unlock(&disconnect_mutex);
+ 		return -ENODEV;
+ 	}
+ 
+@@ -291,12 +273,9 @@ static int idmouse_release(struct inode *inode, struct file *file)
+ 		/* the device was unplugged before the file was released */
+ 		up(&dev->sem);
+ 		idmouse_delete(dev);
+-		mutex_unlock(&disconnect_mutex);
+-		return 0;
++	} else {
++		up(&dev->sem);
+ 	}
+-
+-	up(&dev->sem);
+-	mutex_unlock(&disconnect_mutex);
+ 	return 0;
+ }
+ 
+@@ -391,30 +370,27 @@ static void idmouse_disconnect(struct usb_interface *interface)
+ {
+ 	struct usb_idmouse *dev;
+ 
+-	/* prevent races with open() */
+-	mutex_lock(&disconnect_mutex);
+-
+ 	/* get device structure */
+ 	dev = usb_get_intfdata(interface);
+ 	usb_set_intfdata(interface, NULL);
+ 
+-	/* lock it */
+-	down(&dev->sem);
+-
+ 	/* give back our minor */
+ 	usb_deregister_dev(interface, &idmouse_class);
+ 
++	/* lock it */
++	down(&dev->sem);
++
+ 	/* prevent device read, write and ioctl */
+ 	dev->present = 0;
+ 
+-	/* unlock */
+-	up(&dev->sem);
+-
+ 	/* if the device is opened, idmouse_release will clean this up */
+-	if (!dev->open)
++	if (!dev->open) {
++		up(&dev->sem);
+ 		idmouse_delete(dev);
+-
+-	mutex_unlock(&disconnect_mutex);
++	} else {
++		/* unlock */
++		up(&dev->sem);
++	}
+ 
+ 	info("%s disconnected", DRIVER_DESC);
+ }
+diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
+index 3bb33f7bfa36..28548d186712 100644
+--- a/drivers/usb/misc/iowarrior.c
++++ b/drivers/usb/misc/iowarrior.c
+@@ -100,8 +100,6 @@ struct iowarrior {
+ /*--------------*/
+ /*    globals   */
+ /*--------------*/
+-/* prevent races between open() and disconnect() */
+-static DECLARE_MUTEX(disconnect_sem);
+ 
+ /*
+  *  USB spec identifies 5 second timeouts.
+@@ -600,22 +598,18 @@ static int iowarrior_open(struct inode *inode, struct file *file)
+ 
+ 	subminor = iminor(inode);
+ 
+-	/* prevent disconnects */
+-	down(&disconnect_sem);
+-
+ 	interface = usb_find_interface(&iowarrior_driver, subminor);
+ 	if (!interface) {
+ 		err("%s - error, can't find device for minor %d", __FUNCTION__,
+ 		    subminor);
+-		retval = -ENODEV;
+-		goto out;
++		return -ENODEV;
+ 	}
+ 
+ 	dev = usb_get_intfdata(interface);
+-	if (!dev) {
+-		retval = -ENODEV;
+-		goto out;
+-	}
++	if (!dev)
++		return -ENODEV;
++
++	mutex_lock(&dev->mutex);
+ 
+ 	/* Only one process can open each device, no sharing. */
+ 	if (dev->opened) {
+@@ -636,7 +630,7 @@ static int iowarrior_open(struct inode *inode, struct file *file)
+ 	retval = 0;
+ 
+ out:
+-	up(&disconnect_sem);
++	mutex_unlock(&dev->mutex);
+ 	return retval;
+ }
+ 
+@@ -868,19 +862,16 @@ static void iowarrior_disconnect(struct usb_interface *interface)
+ 	struct iowarrior *dev;
+ 	int minor;
+ 
+-	/* prevent races with open() */
+-	down(&disconnect_sem);
+-
+ 	dev = usb_get_intfdata(interface);
+ 	usb_set_intfdata(interface, NULL);
+ 
+-	mutex_lock(&dev->mutex);
+-
+ 	minor = dev->minor;
+ 
+ 	/* give back our minor */
+ 	usb_deregister_dev(interface, &iowarrior_class);
+ 
++	mutex_lock(&dev->mutex);
++
+ 	/* prevent device read, write and ioctl */
+ 	dev->present = 0;
+ 
+@@ -898,7 +889,6 @@ static void iowarrior_disconnect(struct usb_interface *interface)
+ 		/* no process is using the device, cleanup now */
+ 		iowarrior_delete(dev);
+ 	}
+-	up(&disconnect_sem);
+ 
+ 	dev_info(&interface->dev, "I/O-Warror #%d now disconnected\n",
+ 		 minor - IOWARRIOR_MINOR_BASE);
+diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
+index 7bad49404762..5e950b90c541 100644
+--- a/drivers/usb/misc/ldusb.c
++++ b/drivers/usb/misc/ldusb.c
+@@ -176,9 +176,6 @@ struct ld_usb {
+ 	int			interrupt_out_busy;
+ };
+ 
+-/* prevent races between open() and disconnect() */
+-static DEFINE_MUTEX(disconnect_mutex);
+-
+ static struct usb_driver ld_usb_driver;
+ 
+ /**
+@@ -298,35 +295,28 @@ static int ld_usb_open(struct inode *inode, struct file *file)
+ {
+ 	struct ld_usb *dev;
+ 	int subminor;
+-	int retval = 0;
++	int retval;
+ 	struct usb_interface *interface;
+ 
+ 	nonseekable_open(inode, file);
+ 	subminor = iminor(inode);
+ 
+-	mutex_lock(&disconnect_mutex);
+-
+ 	interface = usb_find_interface(&ld_usb_driver, subminor);
+ 
+ 	if (!interface) {
+ 		err("%s - error, can't find device for minor %d\n",
+ 		     __FUNCTION__, subminor);
+-		retval = -ENODEV;
+-		goto unlock_disconnect_exit;
++		return -ENODEV;
+ 	}
+ 
+ 	dev = usb_get_intfdata(interface);
+ 
+-	if (!dev) {
+-		retval = -ENODEV;
+-		goto unlock_disconnect_exit;
+-	}
++	if (!dev)
++		return -ENODEV;
+ 
+ 	/* lock this device */
+-	if (down_interruptible(&dev->sem)) {
+-		retval = -ERESTARTSYS;
+-		goto unlock_disconnect_exit;
+-	}
++	if (down_interruptible(&dev->sem))
++		return -ERESTARTSYS;
+ 
+ 	/* allow opening only once */
+ 	if (dev->open_count) {
+@@ -366,9 +356,6 @@ static int ld_usb_open(struct inode *inode, struct file *file)
+ unlock_exit:
+ 	up(&dev->sem);
+ 
+-unlock_disconnect_exit:
+-	mutex_unlock(&disconnect_mutex);
+-
+ 	return retval;
+ }
+ 
+@@ -766,18 +753,16 @@ static void ld_usb_disconnect(struct usb_interface *intf)
+ 	struct ld_usb *dev;
+ 	int minor;
+ 
+-	mutex_lock(&disconnect_mutex);
+-
+ 	dev = usb_get_intfdata(intf);
+ 	usb_set_intfdata(intf, NULL);
+ 
+-	down(&dev->sem);
+-
+ 	minor = intf->minor;
+ 
+ 	/* give back our minor */
+ 	usb_deregister_dev(intf, &ld_usb_class);
+ 
++	down(&dev->sem);
++
+ 	/* if the device is not opened, then we clean up right now */
+ 	if (!dev->open_count) {
+ 		up(&dev->sem);
+@@ -787,8 +772,6 @@ static void ld_usb_disconnect(struct usb_interface *intf)
+ 		up(&dev->sem);
+ 	}
+ 
+-	mutex_unlock(&disconnect_mutex);
+-
+ 	dev_info(&intf->dev, "LD USB Device #%d now disconnected\n",
+ 		 (minor - USB_LD_MINOR_BASE));
+ }
+diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
+index 1713e19a7899..2ed0daea894c 100644
+--- a/drivers/usb/misc/legousbtower.c
++++ b/drivers/usb/misc/legousbtower.c
+@@ -254,9 +254,6 @@ static int  tower_probe	(struct usb_interface *interface, const struct usb_devic
+ static void tower_disconnect	(struct usb_interface *interface);
+ 
+ 
+-/* prevent races between open() and disconnect */
+-static DEFINE_MUTEX (disconnect_mutex);
+-
+ /* file operations needed when we register this driver */
+ static const struct file_operations tower_fops = {
+ 	.owner =	THIS_MODULE,
+@@ -344,28 +341,26 @@ static int tower_open (struct inode *inode, struct file *file)
+ 	nonseekable_open(inode, file);
+ 	subminor = iminor(inode);
+ 
+-	mutex_lock (&disconnect_mutex);
+-
+ 	interface = usb_find_interface (&tower_driver, subminor);
+ 
+ 	if (!interface) {
+ 		err ("%s - error, can't find device for minor %d",
+ 		     __FUNCTION__, subminor);
+ 		retval = -ENODEV;
+-		goto unlock_disconnect_exit;
++		goto exit;
+ 	}
+ 
+ 	dev = usb_get_intfdata(interface);
+ 
+ 	if (!dev) {
+ 		retval = -ENODEV;
+-		goto unlock_disconnect_exit;
++		goto exit;
+ 	}
+ 
+ 	/* lock this device */
+ 	if (down_interruptible (&dev->sem)) {
+ 	        retval = -ERESTARTSYS;
+-		goto unlock_disconnect_exit;
++		goto exit;
+ 	}
+ 
+ 	/* allow opening only once */
+@@ -421,9 +416,7 @@ static int tower_open (struct inode *inode, struct file *file)
+ unlock_exit:
+ 	up (&dev->sem);
+ 
+-unlock_disconnect_exit:
+-	mutex_unlock (&disconnect_mutex);
+-
++exit:
+ 	dbg(2, "%s: leave, return value %d ", __FUNCTION__, retval);
+ 
+ 	return retval;
+@@ -993,19 +986,16 @@ static void tower_disconnect (struct usb_interface *interface)
+ 
+ 	dbg(2, "%s: enter", __FUNCTION__);
+ 
+-	mutex_lock (&disconnect_mutex);
+-
+ 	dev = usb_get_intfdata (interface);
+ 	usb_set_intfdata (interface, NULL);
+ 
+-
+-	down (&dev->sem);
+-
+ 	minor = dev->minor;
+ 
+ 	/* give back our minor */
+ 	usb_deregister_dev (interface, &tower_class);
+ 
++	down (&dev->sem);
++
+ 	/* if the device is not opened, then we clean up right now */
+ 	if (!dev->open_count) {
+ 		up (&dev->sem);
+@@ -1015,8 +1005,6 @@ static void tower_disconnect (struct usb_interface *interface)
+ 		up (&dev->sem);
+ 	}
+ 
+-	mutex_unlock (&disconnect_mutex);
+-
+ 	info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE));
+ 
+ 	dbg(2, "%s: leave", __FUNCTION__);
+diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
+index 6f8b134a79cb..9f37ba44c132 100644
+--- a/drivers/usb/misc/sisusbvga/sisusb.c
++++ b/drivers/usb/misc/sisusbvga/sisusb.c
+@@ -72,8 +72,6 @@ MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES
+ 
+ static struct usb_driver sisusb_driver;
+ 
+-DEFINE_MUTEX(disconnect_mutex);
+-
+ static void
+ sisusb_free_buffers(struct sisusb_usb_data *sisusb)
+ {
+@@ -2511,31 +2509,24 @@ sisusb_open(struct inode *inode, struct file *file)
+ 	struct usb_interface *interface;
+ 	int subminor = iminor(inode);
+ 
+-	mutex_lock(&disconnect_mutex);
+-
+ 	if (!(interface = usb_find_interface(&sisusb_driver, subminor))) {
+ 		printk(KERN_ERR "sisusb[%d]: Failed to find interface\n",
+ 				subminor);
+-		mutex_unlock(&disconnect_mutex);
+ 		return -ENODEV;
+ 	}
+ 
+-	if (!(sisusb = usb_get_intfdata(interface))) {
+-		mutex_unlock(&disconnect_mutex);
++	if (!(sisusb = usb_get_intfdata(interface)))
+ 		return -ENODEV;
+-	}
+ 
+ 	mutex_lock(&sisusb->lock);
+ 
+ 	if (!sisusb->present || !sisusb->ready) {
+ 		mutex_unlock(&sisusb->lock);
+-		mutex_unlock(&disconnect_mutex);
+ 		return -ENODEV;
+ 	}
+ 
+ 	if (sisusb->isopen) {
+ 		mutex_unlock(&sisusb->lock);
+-		mutex_unlock(&disconnect_mutex);
+ 		return -EBUSY;
+ 	}
+ 
+@@ -2543,7 +2534,6 @@ sisusb_open(struct inode *inode, struct file *file)
+ 		if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) {
+ 			if (sisusb_init_gfxdevice(sisusb, 0)) {
+ 				mutex_unlock(&sisusb->lock);
+-				mutex_unlock(&disconnect_mutex);
+ 				printk(KERN_ERR
+ 					"sisusbvga[%d]: Failed to initialize "
+ 					"device\n",
+@@ -2552,7 +2542,6 @@ sisusb_open(struct inode *inode, struct file *file)
+ 			}
+ 		} else {
+ 			mutex_unlock(&sisusb->lock);
+-			mutex_unlock(&disconnect_mutex);
+ 			printk(KERN_ERR
+ 				"sisusbvga[%d]: Device not attached to "
+ 				"USB 2.0 hub\n",
+@@ -2570,8 +2559,6 @@ sisusb_open(struct inode *inode, struct file *file)
+ 
+ 	mutex_unlock(&sisusb->lock);
+ 
+-	mutex_unlock(&disconnect_mutex);
+-
+ 	return 0;
+ }
+ 
+@@ -2601,12 +2588,8 @@ sisusb_release(struct inode *inode, struct file *file)
+ 	struct sisusb_usb_data *sisusb;
+ 	int myminor;
+ 
+-	mutex_lock(&disconnect_mutex);
+-
+-	if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) {
+-		mutex_unlock(&disconnect_mutex);
++	if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
+ 		return -ENODEV;
+-	}
+ 
+ 	mutex_lock(&sisusb->lock);
+ 
+@@ -2626,8 +2609,6 @@ sisusb_release(struct inode *inode, struct file *file)
+ 	/* decrement the usage count on our device */
+ 	kref_put(&sisusb->kref, sisusb_delete);
+ 
+-	mutex_unlock(&disconnect_mutex);
+-
+ 	return 0;
+ }
+ 
+@@ -3383,12 +3364,9 @@ static void sisusb_disconnect(struct usb_interface *intf)
+ 	sisusb_console_exit(sisusb);
+ #endif
+ 
+-	/* The above code doesn't need the disconnect
+-	 * semaphore to be down; its meaning is to
+-	 * protect all other routines from the disconnect
+-	 * case, not the other way round.
+-	 */
+-	mutex_lock(&disconnect_mutex);
++	minor = sisusb->minor;
++
++	usb_deregister_dev(intf, &usb_sisusb_class);
+ 
+ 	mutex_lock(&sisusb->lock);
+ 
+@@ -3396,12 +3374,8 @@ static void sisusb_disconnect(struct usb_interface *intf)
+ 	if (!sisusb_wait_all_out_complete(sisusb))
+ 		sisusb_kill_all_busy(sisusb);
+ 
+-	minor = sisusb->minor;
+-
+ 	usb_set_intfdata(intf, NULL);
+ 
+-	usb_deregister_dev(intf, &usb_sisusb_class);
+-
+ #ifdef SISUSB_OLD_CONFIG_COMPAT
+ 	if (sisusb->ioctl32registered) {
+ 		int ret;
+@@ -3426,8 +3400,6 @@ static void sisusb_disconnect(struct usb_interface *intf)
+ 	/* decrement our usage count */
+ 	kref_put(&sisusb->kref, sisusb_delete);
+ 
+-	mutex_unlock(&disconnect_mutex);
+-
+ 	printk(KERN_INFO "sisusbvga[%d]: Disconnected\n", minor);
+ }
+ 
+diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c
+index 5947afb0017e..8d0edc867f33 100644
+--- a/drivers/usb/misc/sisusbvga/sisusb_con.c
++++ b/drivers/usb/misc/sisusbvga/sisusb_con.c
+@@ -214,18 +214,13 @@ sisusbcon_init(struct vc_data *c, int init)
+ 	 * are set up/restored.
+ 	 */
+ 
+-	mutex_lock(&disconnect_mutex);
+-
+-	if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {
+-		mutex_unlock(&disconnect_mutex);
++	if (!(sisusb = sisusb_get_sisusb(c->vc_num)))
+ 		return;
+-	}
+ 
+ 	mutex_lock(&sisusb->lock);
+ 
+ 	if (!sisusb_sisusb_valid(sisusb)) {
+ 		mutex_unlock(&sisusb->lock);
+-		mutex_unlock(&disconnect_mutex);
+ 		return;
+ 	}
+ 
+@@ -264,8 +259,6 @@ sisusbcon_init(struct vc_data *c, int init)
+ 
+ 	mutex_unlock(&sisusb->lock);
+ 
+-	mutex_unlock(&disconnect_mutex);
+-
+ 	if (init) {
+ 		c->vc_cols = cols;
+ 		c->vc_rows = rows;
+@@ -284,12 +277,8 @@ sisusbcon_deinit(struct vc_data *c)
+ 	 * and others, ie not under our control.
+ 	 */
+ 
+-	mutex_lock(&disconnect_mutex);
+-
+-	if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {
+-		mutex_unlock(&disconnect_mutex);
++	if (!(sisusb = sisusb_get_sisusb(c->vc_num)))
+ 		return;
+-	}
+ 
+ 	mutex_lock(&sisusb->lock);
+ 
+@@ -314,8 +303,6 @@ sisusbcon_deinit(struct vc_data *c)
+ 
+ 	/* decrement the usage count on our sisusb */
+ 	kref_put(&sisusb->kref, sisusb_delete);
+-
+-	mutex_unlock(&disconnect_mutex);
+ }
+ 
+ /* interface routine */
+@@ -1490,14 +1477,11 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
+ {
+ 	int i, ret, minor = sisusb->minor;
+ 
+-	mutex_lock(&disconnect_mutex);
+-
+ 	mutex_lock(&sisusb->lock);
+ 
+ 	/* Erm.. that should not happen */
+ 	if (sisusb->haveconsole || !sisusb->SiS_Pr) {
+ 		mutex_unlock(&sisusb->lock);
+-		mutex_unlock(&disconnect_mutex);
+ 		return 1;
+ 	}
+ 
+@@ -1508,14 +1492,12 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
+ 	    first > MAX_NR_CONSOLES ||
+ 	    last > MAX_NR_CONSOLES) {
+ 		mutex_unlock(&sisusb->lock);
+-		mutex_unlock(&disconnect_mutex);
+ 		return 1;
+ 	}
+ 
+ 	/* If gfxcore not initialized or no consoles given, quit graciously */
+ 	if (!sisusb->gfxinit || first < 1 || last < 1) {
+ 		mutex_unlock(&sisusb->lock);
+-		mutex_unlock(&disconnect_mutex);
+ 		return 0;
+ 	}
+ 
+@@ -1526,7 +1508,6 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
+ 	/* Set up text mode (and upload  default font) */
+ 	if (sisusb_reset_text_mode(sisusb, 1)) {
+ 		mutex_unlock(&sisusb->lock);
+-		mutex_unlock(&disconnect_mutex);
+ 		printk(KERN_ERR
+ 			"sisusbvga[%d]: Failed to set up text mode\n",
+ 			minor);
+@@ -1550,7 +1531,6 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
+ 	/* Allocate screen buffer */
+ 	if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) {
+ 		mutex_unlock(&sisusb->lock);
+-		mutex_unlock(&disconnect_mutex);
+ 		printk(KERN_ERR
+ 			"sisusbvga[%d]: Failed to allocate screen buffer\n",
+ 			minor);
+@@ -1558,7 +1538,6 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
+ 	}
+ 
+ 	mutex_unlock(&sisusb->lock);
+-	mutex_unlock(&disconnect_mutex);
+ 
+ 	/* Now grab the desired console(s) */
+ 	ret = take_over_console(&sisusb_con, first - 1, last - 1, 0);
+diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.h b/drivers/usb/misc/sisusbvga/sisusb_init.h
+index f05f83268af4..864bc0e96591 100644
+--- a/drivers/usb/misc/sisusbvga/sisusb_init.h
++++ b/drivers/usb/misc/sisusbvga/sisusb_init.h
+@@ -808,8 +808,6 @@ static const struct SiS_VCLKData SiSUSB_VCLKData[] =
+ 	{ 0x2b,0xc2, 35}  /* 0x71 768@576@60 */
+ };
+ 
+-extern struct mutex disconnect_mutex;
+-
+ int		SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+ int		SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);
+ 
+diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
+index 12bad8a205a7..6e093c2aac2c 100644
+--- a/drivers/usb/misc/usblcd.c
++++ b/drivers/usb/misc/usblcd.c
+@@ -51,7 +51,6 @@ struct usb_lcd {
+ #define USB_LCD_CONCURRENT_WRITES	5
+ 
+ static struct usb_driver lcd_driver;
+-static DEFINE_MUTEX(usb_lcd_open_mutex);
+ 
+ 
+ static void lcd_delete(struct kref *kref)
+@@ -69,24 +68,19 @@ static int lcd_open(struct inode *inode, struct file *file)
+ 	struct usb_lcd *dev;
+ 	struct usb_interface *interface;
+ 	int subminor;
+-	int retval = 0;
+ 
+ 	subminor = iminor(inode);
+ 
+-	mutex_lock(&usb_lcd_open_mutex);
+ 	interface = usb_find_interface(&lcd_driver, subminor);
+ 	if (!interface) {
+ 		err ("USBLCD: %s - error, can't find device for minor %d",
+ 		     __FUNCTION__, subminor);
+-		retval = -ENODEV;
+-		goto exit;
++		return -ENODEV;
+ 	}
+ 
+ 	dev = usb_get_intfdata(interface);
+-	if (!dev) {
+-		retval = -ENODEV;
+-		goto exit;
+-	}
++	if (!dev)
++		return -ENODEV;
+ 
+ 	/* increment our usage count for the device */
+ 	kref_get(&dev->kref);
+@@ -94,9 +88,7 @@ static int lcd_open(struct inode *inode, struct file *file)
+ 	/* save our object in the file's private structure */
+ 	file->private_data = dev;
+ 
+-exit:
+-	mutex_unlock(&usb_lcd_open_mutex);
+-	return retval;
++	return 0;
+ }
+ 
+ static int lcd_release(struct inode *inode, struct file *file)
+@@ -363,17 +355,12 @@ static void lcd_disconnect(struct usb_interface *interface)
+ 	struct usb_lcd *dev;
+         int minor = interface->minor;
+ 
+-        /* prevent skel_open() from racing skel_disconnect() */
+-        mutex_lock(&usb_lcd_open_mutex);
+-
+         dev = usb_get_intfdata(interface);
+         usb_set_intfdata(interface, NULL);
+ 
+         /* give back our minor */
+         usb_deregister_dev(interface, &lcd_class);
+  
+-	mutex_unlock(&usb_lcd_open_mutex);
+-
+ 	/* decrement our usage count */
+ 	kref_put(&dev->kref, lcd_delete);
+ 
+diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
+index 8432bf171d2e..38f8e4df9dd6 100644
+--- a/drivers/usb/usb-skeleton.c
++++ b/drivers/usb/usb-skeleton.c
+@@ -34,9 +34,6 @@ static struct usb_device_id skel_table [] = {
+ };
+ MODULE_DEVICE_TABLE(usb, skel_table);
+ 
+-/* to prevent a race between open and disconnect */
+-static DEFINE_MUTEX(skel_open_lock);
+-
+ 
+ /* Get a minor range for your devices from the usb maintainer */
+ #define USB_SKEL_MINOR_BASE	192
+@@ -83,10 +80,8 @@ static int skel_open(struct inode *inode, struct file *file)
+ 
+ 	subminor = iminor(inode);
+ 
+-	mutex_lock(&skel_open_lock);
+ 	interface = usb_find_interface(&skel_driver, subminor);
+ 	if (!interface) {
+-		mutex_unlock(&skel_open_lock);
+ 		err ("%s - error, can't find device for minor %d",
+ 		     __FUNCTION__, subminor);
+ 		retval = -ENODEV;
+@@ -95,15 +90,12 @@ static int skel_open(struct inode *inode, struct file *file)
+ 
+ 	dev = usb_get_intfdata(interface);
+ 	if (!dev) {
+-		mutex_unlock(&skel_open_lock);
+ 		retval = -ENODEV;
+ 		goto exit;
+ 	}
+ 
+ 	/* increment our usage count for the device */
+ 	kref_get(&dev->kref);
+-	/* now we can drop the lock */
+-	mutex_unlock(&skel_open_lock);
+ 
+ 	/* prevent the device from being autosuspended */
+ 	retval = usb_autopm_get_interface(interface);
+@@ -368,23 +360,17 @@ static void skel_disconnect(struct usb_interface *interface)
+ 	struct usb_skel *dev;
+ 	int minor = interface->minor;
+ 
+-	/* prevent skel_open() from racing skel_disconnect() */
+-	mutex_lock(&skel_open_lock);
+-
+ 	dev = usb_get_intfdata(interface);
+ 	usb_set_intfdata(interface, NULL);
+ 
+ 	/* give back our minor */
+ 	usb_deregister_dev(interface, &skel_class);
+-	mutex_unlock(&skel_open_lock);
+ 
+ 	/* prevent more I/O from starting */
+ 	mutex_lock(&dev->io_mutex);
+ 	dev->interface = NULL;
+ 	mutex_unlock(&dev->io_mutex);
+ 
+-
+-
+ 	/* decrement our usage count */
+ 	kref_put(&dev->kref, skel_delete);
+ 

commit dd4dd19e8d13e1e9bf8295bf71f132b511b130bf
+Author: Alan Stern 
+Date:   Fri May 4 11:55:54 2007 -0400
+
+    USB: Make device reset stop retrying after disconnect
+    
+    This patch (as898) changes the port reset code in the hub driver.  If
+    a connect change occurs, it is reported the same way as a disconnect
+    (which of course is what it really is).
+    
+    It also changes usb_reset_device(), to prevent the routine from futilely
+    retrying the reset after a disconnect has occurred.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index d37ad083d5ef..f4ef7c25096e 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1539,9 +1539,9 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
+ 		if (!(portstatus & USB_PORT_STAT_CONNECTION))
+ 			return -ENOTCONN;
+ 
+-		/* bomb out completely if something weird happened */
++		/* bomb out completely if the connection bounced */
+ 		if ((portchange & USB_PORT_STAT_C_CONNECTION))
+-			return -EINVAL;
++			return -ENOTCONN;
+ 
+ 		/* if we`ve finished resetting, then break out of the loop */
+ 		if (!(portstatus & USB_PORT_STAT_RESET) &&
+@@ -2974,7 +2974,7 @@ int usb_reset_device(struct usb_device *udev)
+ 		 * Other endpoints will be handled by re-enumeration. */
+ 		ep0_reinit(udev);
+ 		ret = hub_port_init(parent_hub, udev, port1, i);
+-		if (ret >= 0)
++		if (ret >= 0 || ret == -ENOTCONN || ret == -ENODEV)
+ 			break;
+ 	}
+ 	clear_bit(port1, parent_hub->busy_bits);

commit 3c519b846c4d5edf7c94d1eede42445a815bf65c
+Author: Alan Stern 
+Date:   Fri May 4 11:55:31 2007 -0400
+
+    USB: EHCI: fix handover for designated full-speed ports
+    
+    This patch (as895) fixes up a loose end in the port-handover code for
+    the USB-Persist facility.  A special case occurs when a high-speed
+    device is attached to a port which the user has designated to run at
+    full-speed only; the port must be disabled before the handover can
+    take place.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 3e80de7c7f5b..27291f502651 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -60,11 +60,13 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
+ 	while (port--) {
+ 		if (test_bit(port, &ehci->owned_ports)) {
+ 			reg = &ehci->regs->port_status[port];
+-			status = ehci_readl(ehci, reg);
++			status = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
+ 
+ 			/* Port already owned by companion? */
+ 			if (status & PORT_OWNER)
+ 				clear_bit(port, &ehci->owned_ports);
++			else if (test_bit(port, &ehci->companion_ports))
++				ehci_writel(ehci, status & ~PORT_PE, reg);
+ 			else
+ 				ehci_hub_control(hcd, SetPortFeature,
+ 						USB_PORT_FEAT_RESET, port + 1,

commit 6bc6cff52e0c4c4c876b1b8a5750041da61ad42b
+Author: Alan Stern 
+Date:   Fri May 4 11:53:03 2007 -0400
+
+    USB: add RESET_RESUME device quirk
+    
+    This patch (as888) adds a new USB device quirk for devices which are
+    unable to resume correctly.  By using the new code added for the
+    USB-persist facility, it is a simple matter to reset these devices
+    instead of resuming them.  To get things kicked off, a quirk entry is
+    added for the Philips PSC805.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 12dd986bdffd..02d6db61c940 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -24,6 +24,7 @@
+ 
+ #include 
+ #include 
++#include 
+ #include 
+ #include "hcd.h"
+ #include "usb.h"
+@@ -835,6 +836,9 @@ static int usb_resume_device(struct usb_device *udev)
+ 		goto done;
+ 	}
+ 
++	if (udev->quirks & USB_QUIRK_RESET_RESUME)
++		udev->reset_resume = 1;
++
+ 	udriver = to_usb_device_driver(udev->dev.driver);
+ 	status = udriver->resume(udev);
+ 
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 51d2d304568b..d37ad083d5ef 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2939,6 +2939,11 @@ static int config_descriptors_changed(struct usb_device *udev)
+  * this from a driver probe() routine after downloading new firmware.
+  * For calls that might not occur during probe(), drivers should lock
+  * the device using usb_lock_device_for_reset().
++ *
++ * Locking exception: This routine may also be called from within an
++ * autoresume handler.  Such usage won't conflict with other tasks
++ * holding the device lock because these tasks should always call
++ * usb_autopm_resume_device(), thereby preventing any unwanted autoresume.
+  */
+ int usb_reset_device(struct usb_device *udev)
+ {
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index 739f520908aa..f37fa012f329 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -35,6 +35,9 @@ static const struct usb_device_id usb_quirk_list[] = {
+ 	/* Elsa MicroLink 56k (V.250) */
+ 	{ USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+ 
++	/* Philips PSC805 audio device */
++	{ USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME },
++
+ 	{ }  /* terminating entry must be last */
+ };
+ 
+diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h
+index 6bac8faacbc6..8da374caf582 100644
+--- a/include/linux/usb/quirks.h
++++ b/include/linux/usb/quirks.h
+@@ -9,3 +9,6 @@
+ 
+ /* string descriptors must not be fetched using a 255-byte read */
+ #define USB_QUIRK_STRING_FETCH_255	0x00000002
++
++/* device can't resume correctly so reset it instead */
++#define USB_QUIRK_RESET_RESUME		0x00000004

commit 383975d765523a56dc43a6cd6d52e9b376800cf2
+Author: Alan Stern 
+Date:   Fri May 4 11:52:40 2007 -0400
+
+    USB: EHCI, OHCI: handover changes
+    
+    This patch (as887) changes the way ehci-hcd and ohci-hcd handle a loss
+    of VBUS power during suspend.  In order for the USB-persist facility
+    to work correctly, it is necessary for low- and full-speed devices
+    attached to a high-speed port to be handed back to the companion
+    controller during resume processing.
+    
+    This entails three changes: adding code to ehci-hcd to perform the
+    handover, removing code from ohci-hcd to turn off ports during
+    root-hub reinit, and adding code to ohci-hcd to turn on ports during
+    PCI controller resume.  (Other bus glue resume methods for platforms
+    supporting high-speed controllers would need a similar change, if any
+    existed.)
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 99ab31e9778b..b5a7aa90209a 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -399,6 +399,8 @@ static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
+ 				is_on ? SetPortFeature : ClearPortFeature,
+ 				USB_PORT_FEAT_POWER,
+ 				port--, NULL, 0);
++	/* Flush those writes */
++	ehci_readl(ehci, &ehci->regs->command);
+ 	msleep(20);
+ }
+ 
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index f4d301bc83b9..3e80de7c7f5b 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -28,6 +28,87 @@
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++#ifdef	CONFIG_USB_PERSIST
++
++static int ehci_hub_control(
++	struct usb_hcd	*hcd,
++	u16		typeReq,
++	u16		wValue,
++	u16		wIndex,
++	char		*buf,
++	u16		wLength
++);
++
++/* After a power loss, ports that were owned by the companion must be
++ * reset so that the companion can still own them.
++ */
++static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
++{
++	u32 __iomem	*reg;
++	u32		status;
++	int		port;
++	__le32		buf;
++	struct usb_hcd	*hcd = ehci_to_hcd(ehci);
++
++	if (!ehci->owned_ports)
++		return;
++
++	/* Give the connections some time to appear */
++	msleep(20);
++
++	port = HCS_N_PORTS(ehci->hcs_params);
++	while (port--) {
++		if (test_bit(port, &ehci->owned_ports)) {
++			reg = &ehci->regs->port_status[port];
++			status = ehci_readl(ehci, reg);
++
++			/* Port already owned by companion? */
++			if (status & PORT_OWNER)
++				clear_bit(port, &ehci->owned_ports);
++			else
++				ehci_hub_control(hcd, SetPortFeature,
++						USB_PORT_FEAT_RESET, port + 1,
++						NULL, 0);
++		}
++	}
++
++	if (!ehci->owned_ports)
++		return;
++	msleep(90);		/* Wait for resets to complete */
++
++	port = HCS_N_PORTS(ehci->hcs_params);
++	while (port--) {
++		if (test_bit(port, &ehci->owned_ports)) {
++			ehci_hub_control(hcd, GetPortStatus,
++					0, port + 1,
++					(char *) &buf, sizeof(buf));
++
++			/* The companion should now own the port,
++			 * but if something went wrong the port must not
++			 * remain enabled.
++			 */
++			reg = &ehci->regs->port_status[port];
++			status = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
++			if (status & PORT_OWNER)
++				ehci_writel(ehci, status | PORT_CSC, reg);
++			else {
++				ehci_dbg(ehci, "failed handover port %d: %x\n",
++						port + 1, status);
++				ehci_writel(ehci, status & ~PORT_PE, reg);
++			}
++		}
++	}
++
++	ehci->owned_ports = 0;
++}
++
++#else	/* CONFIG_USB_PERSIST */
++
++static inline void ehci_handover_companion_ports(struct ehci_hcd *ehci)
++{ }
++
++#endif
++
+ #ifdef	CONFIG_PM
+ 
+ static int ehci_bus_suspend (struct usb_hcd *hcd)
+@@ -60,14 +141,16 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 	 * then manually resume them in the bus_resume() routine.
+ 	 */
+ 	ehci->bus_suspended = 0;
++	ehci->owned_ports = 0;
+ 	while (port--) {
+ 		u32 __iomem	*reg = &ehci->regs->port_status [port];
+ 		u32		t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
+ 		u32		t2 = t1;
+ 
+ 		/* keep track of which ports we suspend */
+-		if ((t1 & PORT_PE) && !(t1 & PORT_OWNER) &&
+-				!(t1 & PORT_SUSPEND)) {
++		if (t1 & PORT_OWNER)
++			set_bit(port, &ehci->owned_ports);
++		else if ((t1 & PORT_PE) && !(t1 & PORT_SUSPEND)) {
+ 			t2 |= PORT_SUSPEND;
+ 			set_bit(port, &ehci->bus_suspended);
+ 		}
+@@ -108,6 +191,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ {
+ 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+ 	u32			temp;
++	u32			power_okay;
+ 	int			i;
+ 
+ 	if (time_before (jiffies, ehci->next_statechange))
+@@ -120,8 +204,9 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 	 * the last user of the controller, not reset/pm hardware keeping
+ 	 * state we gave to it.
+ 	 */
+-	temp = ehci_readl(ehci, &ehci->regs->intr_enable);
+-	ehci_dbg(ehci, "resume root hub%s\n", temp ? "" : " after power loss");
++	power_okay = ehci_readl(ehci, &ehci->regs->intr_enable);
++	ehci_dbg(ehci, "resume root hub%s\n",
++			power_okay ? "" : " after power loss");
+ 
+ 	/* at least some APM implementations will try to deliver
+ 	 * IRQs right away, so delay them until we're ready.
+@@ -184,6 +269,9 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 	ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
+ 
+ 	spin_unlock_irq (&ehci->lock);
++
++	if (!power_okay)
++		ehci_handover_companion_ports(ehci);
+ 	return 0;
+ }
+ 
+@@ -448,7 +536,8 @@ static int ehci_hub_control (
+ ) {
+ 	struct ehci_hcd	*ehci = hcd_to_ehci (hcd);
+ 	int		ports = HCS_N_PORTS (ehci->hcs_params);
+-	u32 __iomem	*status_reg = &ehci->regs->port_status[wIndex - 1];
++	u32 __iomem	*status_reg = &ehci->regs->port_status[
++				(wIndex & 0xff) - 1];
+ 	u32		temp, status;
+ 	unsigned long	flags;
+ 	int		retval = 0;
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index 966965f72338..a7816e392a85 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -312,13 +312,14 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
+ 	ehci_work(ehci);
+ 	spin_unlock_irq(&ehci->lock);
+ 
+-	/* here we "know" root ports should always stay powered */
+-	ehci_port_power(ehci, 1);
+-
+ 	ehci_writel(ehci, ehci->command, &ehci->regs->command);
+ 	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
+ 	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
+ 
++	/* here we "know" root ports should always stay powered */
++	ehci_port_power(ehci, 1);
++	ehci_handover_companion_ports(ehci);
++
+ 	hcd->state = HC_STATE_SUSPENDED;
+ 	return 0;
+ }
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 6ef9d775775b..4d617108f552 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -96,11 +96,14 @@ struct ehci_hcd {			/* one per controller */
+ 
+ 	/* per root hub port */
+ 	unsigned long		reset_done [EHCI_MAX_ROOT_PORTS];
++
+ 	/* bit vectors (one bit per port) */
+ 	unsigned long		bus_suspended;		/* which ports were
+ 			already suspended at the start of a bus suspend */
+ 	unsigned long		companion_ports;	/* which ports are
+ 			dedicated to the companion controller */
++	unsigned long		owned_ports;		/* which ports are
++			owned by the companion during a bus suspend */
+ 
+ 	/* per-HC memory pools (could be per-bus, but ...) */
+ 	struct dma_pool		*qh_pool;	/* qh per active urb */
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index a66637e725f3..ce05e5f7bed6 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -510,15 +510,7 @@ static int ohci_run (struct ohci_hcd *ohci)
+ 	// flush the writes
+ 	(void) ohci_readl (ohci, &ohci->regs->control);
+ 	msleep(temp);
+-	temp = roothub_a (ohci);
+-	if (!(temp & RH_A_NPS)) {
+-		/* power down each port */
+-		for (temp = 0; temp < ohci->num_ports; temp++)
+-			ohci_writel (ohci, RH_PS_LSDA,
+-				&ohci->regs->roothub.portstatus [temp]);
+-	}
+-	// flush those writes
+-	(void) ohci_readl (ohci, &ohci->regs->control);
++
+ 	memset (ohci->hcca, 0, sizeof (struct ohci_hcca));
+ 
+ 	/* 2msec timelimit here means no irqs/preempt */
+@@ -826,17 +818,8 @@ static int ohci_restart (struct ohci_hcd *ohci)
+ 	if ((temp = ohci_run (ohci)) < 0) {
+ 		ohci_err (ohci, "can't restart, %d\n", temp);
+ 		return temp;
+-	} else {
+-		/* here we "know" root ports should always stay powered,
+-		 * and that if we try to turn them back on the root hub
+-		 * will respond to CSC processing.
+-		 */
+-		i = ohci->num_ports;
+-		while (i--)
+-			ohci_writel (ohci, RH_PS_PSS,
+-				&ohci->regs->roothub.portstatus [i]);
+-		ohci_dbg (ohci, "restart complete\n");
+ 	}
++	ohci_dbg(ohci, "restart complete\n");
+ 	return 0;
+ }
+ #endif
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index ca62cb583221..15013f4519ad 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -202,6 +202,42 @@ static int __devinit ohci_pci_start (struct usb_hcd *hcd)
+ 	return ret;
+ }
+ 
++#if	defined(CONFIG_USB_PERSIST) && (defined(CONFIG_USB_EHCI_HCD) || \
++		defined(CONFIG_USB_EHCI_HCD_MODULE))
++
++/* Following a power loss, we must prepare to regain control of the ports
++ * we used to own.  This means turning on the port power before ehci-hcd
++ * tries to switch ownership.
++ *
++ * This isn't a 100% perfect solution.  On most systems the OHCI controllers
++ * lie at lower PCI addresses than the EHCI controller, so they will be
++ * discovered (and hence resumed) first.  But there is no guarantee things
++ * will always work this way.  If the EHCI controller is resumed first and
++ * the OHCI ports are unpowered, then the handover will fail.
++ */
++static void prepare_for_handover(struct usb_hcd *hcd)
++{
++	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
++	int		port;
++
++	/* Here we "know" root ports should always stay powered */
++	ohci_dbg(ohci, "powerup ports\n");
++	for (port = 0; port < ohci->num_ports; port++)
++		ohci_writel(ohci, RH_PS_PPS,
++				&ohci->regs->roothub.portstatus[port]);
++
++	/* Flush those writes */
++	ohci_readl(ohci, &ohci->regs->control);
++	msleep(20);
++}
++
++#else
++
++static inline void prepare_for_handover(struct usb_hcd *hcd)
++{ }
++
++#endif	/* CONFIG_USB_PERSIST etc. */
++
+ #ifdef	CONFIG_PM
+ 
+ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
+@@ -241,7 +277,10 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
+ static int ohci_pci_resume (struct usb_hcd *hcd)
+ {
+ 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+-	usb_hcd_resume_root_hub(hcd);
++
++	/* FIXME: we should try to detect loss of VBUS power here */
++	prepare_for_handover(hcd);
++
+ 	return 0;
+ }
+ 

commit 0458d5b4c9cc4ca0f62625d0144ddc4b4bc97a3c
+Author: Alan Stern 
+Date:   Fri May 4 11:52:20 2007 -0400
+
+    USB: add USB-Persist facility
+    
+    This patch (as886) adds the controversial USB-persist facility,
+    allowing USB devices to persist across a power loss during system
+    suspend.
+    
+    The facility is controlled by a new Kconfig option (with appropriate
+    warnings about the potential dangers); when the option is off the
+    behavior will remain the same as it is now.  But when the option is
+    on, people will be able to use suspend-to-disk and keep their USB
+    filesystems intact -- something particularly valuable for small
+    machines where the root filesystem is on a USB device!
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt
+index 5b8d6953f05e..152b510d1bbb 100644
+--- a/Documentation/power/swsusp.txt
++++ b/Documentation/power/swsusp.txt
+@@ -393,6 +393,9 @@ safest thing is to unmount all filesystems on removable media (such USB,
+ Firewire, CompactFlash, MMC, external SATA, or even IDE hotplug bays)
+ before suspending; then remount them after resuming.
+ 
++There is a work-around for this problem.  For more information, see
++Documentation/usb/persist.txt.
++
+ Q: I upgraded the kernel from 2.6.15 to 2.6.16. Both kernels were
+ compiled with the similar configuration files. Anyway I found that
+ suspend to disk (and resume) is much slower on 2.6.16 compared to
+diff --git a/Documentation/usb/persist.txt b/Documentation/usb/persist.txt
+new file mode 100644
+index 000000000000..6dcd5f884795
+--- /dev/null
++++ b/Documentation/usb/persist.txt
+@@ -0,0 +1,144 @@
++		USB device persistence during system suspend
++
++		   Alan Stern 
++
++		 September 2, 2006 (Updated March 27, 2007)
++
++
++	What is the problem?
++
++According to the USB specification, when a USB bus is suspended the
++bus must continue to supply suspend current (around 1-5 mA).  This
++is so that devices can maintain their internal state and hubs can
++detect connect-change events (devices being plugged in or unplugged).
++The technical term is "power session".
++
++If a USB device's power session is interrupted then the system is
++required to behave as though the device has been unplugged.  It's a
++conservative approach; in the absence of suspend current the computer
++has no way to know what has actually happened.  Perhaps the same
++device is still attached or perhaps it was removed and a different
++device plugged into the port.  The system must assume the worst.
++
++By default, Linux behaves according to the spec.  If a USB host
++controller loses power during a system suspend, then when the system
++wakes up all the devices attached to that controller are treated as
++though they had disconnected.  This is always safe and it is the
++"officially correct" thing to do.
++
++For many sorts of devices this behavior doesn't matter in the least.
++If the kernel wants to believe that your USB keyboard was unplugged
++while the system was asleep and a new keyboard was plugged in when the
++system woke up, who cares?  It'll still work the same when you type on
++it.
++
++Unfortunately problems _can_ arise, particularly with mass-storage
++devices.  The effect is exactly the same as if the device really had
++been unplugged while the system was suspended.  If you had a mounted
++filesystem on the device, you're out of luck -- everything in that
++filesystem is now inaccessible.  This is especially annoying if your
++root filesystem was located on the device, since your system will
++instantly crash.
++
++Loss of power isn't the only mechanism to worry about.  Anything that
++interrupts a power session will have the same effect.  For example,
++even though suspend current may have been maintained while the system
++was asleep, on many systems during the initial stages of wakeup the
++firmware (i.e., the BIOS) resets the motherboard's USB host
++controllers.  Result: all the power sessions are destroyed and again
++it's as though you had unplugged all the USB devices.  Yes, it's
++entirely the BIOS's fault, but that doesn't do _you_ any good unless
++you can convince the BIOS supplier to fix the problem (lots of luck!).
++
++On many systems the USB host controllers will get reset after a
++suspend-to-RAM.  On almost all systems, no suspend current is
++available during suspend-to-disk (also known as swsusp).  You can
++check the kernel log after resuming to see if either of these has
++happened; look for lines saying "root hub lost power or was reset".
++
++In practice, people are forced to unmount any filesystems on a USB
++device before suspending.  If the root filesystem is on a USB device,
++the system can't be suspended at all.  (All right, it _can_ be
++suspended -- but it will crash as soon as it wakes up, which isn't
++much better.)
++
++
++	What is the solution?
++
++Setting CONFIG_USB_PERSIST will cause the kernel to work around these
++issues.  It enables a mode in which the core USB device data
++structures are allowed to persist across a power-session disruption.
++It works like this.  If the kernel sees that a USB host controller is
++not in the expected state during resume (i.e., if the controller was
++reset or otherwise had lost power) then it applies a persistence check
++to each of the USB devices below that controller.  It doesn't try to
++resume the device; that can't work once the power session is gone.
++Instead it issues a USB port reset and then re-enumerates the device.
++(This is exactly the same thing that happens whenever a USB device is
++reset.)  If the re-enumeration shows that the device now attached to
++that port has the same descriptors as before, including the Vendor and
++Product IDs, then the kernel continues to use the same device
++structure.  In effect, the kernel treats the device as though it had
++merely been reset instead of unplugged.
++
++If no device is now attached to the port, or if the descriptors are
++different from what the kernel remembers, then the treatment is what
++you would expect.  The kernel destroys the old device structure and
++behaves as though the old device had been unplugged and a new device
++plugged in, just as it would without the CONFIG_USB_PERSIST option.
++
++The end result is that the USB device remains available and usable.
++Filesystem mounts and memory mappings are unaffected, and the world is
++now a good and happy place.
++
++
++	Is this the best solution?
++
++Perhaps not.  Arguably, keeping track of mounted filesystems and
++memory mappings across device disconnects should be handled by a
++centralized Logical Volume Manager.  Such a solution would allow you
++to plug in a USB flash device, create a persistent volume associated
++with it, unplug the flash device, plug it back in later, and still
++have the same persistent volume associated with the device.  As such
++it would be more far-reaching than CONFIG_USB_PERSIST.
++
++On the other hand, writing a persistent volume manager would be a big
++job and using it would require significant input from the user.  This
++solution is much quicker and easier -- and it exists now, a giant
++point in its favor!
++
++Furthermore, the USB_PERSIST option applies to _all_ USB devices, not
++just mass-storage devices.  It might turn out to be equally useful for
++other device types, such as network interfaces.
++
++
++	WARNING: Using CONFIG_USB_PERSIST can be dangerous!!
++
++When recovering an interrupted power session the kernel does its best
++to make sure the USB device hasn't been changed; that is, the same
++device is still plugged into the port as before.  But the checks
++aren't guaranteed to be 100% accurate.
++
++If you replace one USB device with another of the same type (same
++manufacturer, same IDs, and so on) there's an excellent chance the
++kernel won't detect the change.  Serial numbers and other strings are
++not compared.  In many cases it wouldn't help if they were, because
++manufacturers frequently omit serial numbers entirely in their
++devices.
++
++Furthermore it's quite possible to leave a USB device exactly the same
++while changing its media.  If you replace the flash memory card in a
++USB card reader while the system is asleep, the kernel will have no
++way to know you did it.  The kernel will assume that nothing has
++happened and will continue to use the partition tables, inodes, and
++memory mappings for the old card.
++
++If the kernel gets fooled in this way, it's almost certain to cause
++data corruption and to crash your system.  You'll have no one to blame
++but yourself.
++
++YOU HAVE BEEN WARNED!  USE AT YOUR OWN RISK!
++
++That having been said, most of the time there shouldn't be any trouble
++at all.  The "persist" feature can be extremely useful.  Make the most
++of it.
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index 3afa4a5035b7..e221b0d1f667 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -1015,7 +1015,7 @@ static void hid_pre_reset(struct usb_interface *intf)
+ 	hid_suspend(intf, PMSG_ON);
+ }
+ 
+-static void hid_post_reset(struct usb_interface *intf)
++static void hid_post_reset(struct usb_interface *intf, int reset_resume)
+ {
+ 	struct usb_device *dev = interface_to_usbdev (intf);
+ 
+diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
+index 346fc030c929..5113ef4cb7f6 100644
+--- a/drivers/usb/core/Kconfig
++++ b/drivers/usb/core/Kconfig
+@@ -86,6 +86,28 @@ config USB_SUSPEND
+ 
+ 	  If you are unsure about this, say N here.
+ 
++config USB_PERSIST
++	bool "USB device persistence during system suspend (DANGEROUS)"
++	depends on USB && PM && EXPERIMENTAL
++	default n
++	help
++	  If you say Y here, USB device data structures will remain
++	  persistent across system suspend, even if the USB bus loses
++	  power.  (This includes software-suspend, also known as swsusp,
++	  or suspend-to-disk.)  The devices will reappear as if by magic
++	  when the system wakes up, with no need to unmount USB filesystems,
++	  rmmod host-controller drivers, or do anything else.
++
++	  	WARNING: This option can be dangerous!
++
++	  If a USB device is replaced by another of the same type while
++	  the system is asleep, there's a good chance the kernel won't
++	  detect the change.  Likewise if the media in a USB storage
++	  device is replaced.  When this happens it's almost certain to
++	  cause data corruption and maybe even crash your system.
++
++	  If you are unsure, say N here.
++
+ config USB_OTG
+ 	bool
+ 	depends on USB && EXPERIMENTAL
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index e8b447e06c54..12dd986bdffd 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -824,8 +824,9 @@ static int usb_resume_device(struct usb_device *udev)
+ 	struct usb_device_driver	*udriver;
+ 	int				status = 0;
+ 
+-	if (udev->state == USB_STATE_NOTATTACHED ||
+-			udev->state != USB_STATE_SUSPENDED)
++	if (udev->state == USB_STATE_NOTATTACHED)
++		goto done;
++	if (udev->state != USB_STATE_SUSPENDED && !udev->reset_resume)
+ 		goto done;
+ 
+ 	/* Can't resume it if it doesn't have a driver. */
+@@ -882,7 +883,7 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
+ }
+ 
+ /* Caller has locked intf's usb_device's pm_mutex */
+-static int usb_resume_interface(struct usb_interface *intf)
++static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
+ {
+ 	struct usb_driver	*driver;
+ 	int			status = 0;
+@@ -902,21 +903,21 @@ static int usb_resume_interface(struct usb_interface *intf)
+ 	}
+ 	driver = to_usb_driver(intf->dev.driver);
+ 
+-	if (driver->resume) {
++	if (reset_resume && driver->post_reset)
++		driver->post_reset(intf, reset_resume);
++	else if (driver->resume) {
+ 		status = driver->resume(intf);
+ 		if (status)
+ 			dev_err(&intf->dev, "%s error %d\n",
+ 					"resume", status);
+-		else
+-			mark_active(intf);
+-	} else {
++	} else
+ 		dev_warn(&intf->dev, "no resume for driver %s?\n",
+ 				driver->name);
+-		mark_active(intf);
+-	}
+ 
+ done:
+ 	// dev_dbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
++	if (status == 0)
++		mark_active(intf);
+ 	return status;
+ }
+ 
+@@ -1063,7 +1064,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 	if (status != 0) {
+ 		while (--i >= 0) {
+ 			intf = udev->actconfig->interface[i];
+-			usb_resume_interface(intf);
++			usb_resume_interface(intf, 0);
+ 		}
+ 
+ 		/* Try another autosuspend when the interfaces aren't busy */
+@@ -1162,20 +1163,21 @@ static int usb_resume_both(struct usb_device *udev)
+  		}
+ 	} else {
+ 
+-		/* Needed only for setting udev->dev.power.power_state.event
+-		 * and for possible debugging message. */
++		/* Needed for setting udev->dev.power.power_state.event,
++		 * for possible debugging message, and for reset_resume. */
+ 		status = usb_resume_device(udev);
+ 	}
+ 
+ 	if (status == 0 && udev->actconfig) {
+ 		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+ 			intf = udev->actconfig->interface[i];
+-			usb_resume_interface(intf);
++			usb_resume_interface(intf, udev->reset_resume);
+ 		}
+ 	}
+ 
+  done:
+ 	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
++	udev->reset_resume = 0;
+ 	return status;
+ }
+ 
+@@ -1510,8 +1512,15 @@ static int usb_resume(struct device *dev)
+ 	if (!is_usb_device(dev))	/* Ignore PM for interfaces */
+ 		return 0;
+ 	udev = to_usb_device(dev);
+-	if (udev->autoresume_disabled)
+-		return -EPERM;
++
++	/* If autoresume is disabled then we also want to prevent resume
++	 * during system wakeup.  However, a "persistent-device" reset-resume
++	 * after power loss counts as a wakeup event.  So allow a
++	 * reset-resume to occur if remote wakeup is enabled. */
++	if (udev->autoresume_disabled) {
++		if (!(udev->reset_resume && udev->do_remote_wakeup))
++			return -EPERM;
++	}
+ 	return usb_external_resume_device(udev);
+ }
+ 
+diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
+index 7cbf992adccd..d363b0ea7345 100644
+--- a/drivers/usb/core/generic.c
++++ b/drivers/usb/core/generic.c
+@@ -217,7 +217,10 @@ static int generic_resume(struct usb_device *udev)
+ {
+ 	int rc;
+ 
+-	rc = usb_port_resume(udev);
++	if (udev->reset_resume)
++		rc = usb_reset_suspended_device(udev);
++	else
++		rc = usb_port_resume(udev);
+ 
+ 	/* Root hubs don't have upstream ports to resume or reset,
+ 	 * so the line above won't do much for them.  We have to
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 77a6627b18d2..51d2d304568b 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -553,45 +553,121 @@ static int hub_hub_status(struct usb_hub *hub,
+ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
+ {
+ 	struct usb_device *hdev = hub->hdev;
+-	int ret;
++	int ret = 0;
+ 
+-	if (hdev->children[port1-1] && set_state) {
++	if (hdev->children[port1-1] && set_state)
+ 		usb_set_device_state(hdev->children[port1-1],
+ 				USB_STATE_NOTATTACHED);
+-	}
+-	ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
++	if (!hub->error)
++		ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
+ 	if (ret)
+ 		dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
+-			port1, ret);
+-
++				port1, ret);
+ 	return ret;
+ }
+ 
++/*
++ * Disable a port and mark a logical connnect-change event, so that some
++ * time later khubd will disconnect() any existing usb_device on the port
++ * and will re-enumerate if there actually is a device attached.
++ */
++static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
++{
++	dev_dbg(hub->intfdev, "logical disconnect on port %d\n", port1);
++	hub_port_disable(hub, port1, 1);
+ 
+-/* caller has locked the hub device */
+-static void hub_pre_reset(struct usb_interface *intf)
++	/* FIXME let caller ask to power down the port:
++	 *  - some devices won't enumerate without a VBUS power cycle
++	 *  - SRP saves power that way
++	 *  - ... new call, TBD ...
++	 * That's easy if this hub can switch power per-port, and
++	 * khubd reactivates the port later (timer, SRP, etc).
++	 * Powerdown must be optional, because of reset/DFU.
++	 */
++
++	set_bit(port1, hub->change_bits);
++ 	kick_khubd(hub);
++}
++
++static void disconnect_all_children(struct usb_hub *hub, int logical)
+ {
+-	struct usb_hub *hub = usb_get_intfdata(intf);
+ 	struct usb_device *hdev = hub->hdev;
+ 	int port1;
+ 
+ 	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
+-		if (hdev->children[port1 - 1]) {
+-			usb_disconnect(&hdev->children[port1 - 1]);
+-			if (hub->error == 0)
+-				hub_port_disable(hub, port1, 0);
++		if (hdev->children[port1-1]) {
++			if (logical)
++				hub_port_logical_disconnect(hub, port1);
++			else
++				usb_disconnect(&hdev->children[port1-1]);
++		}
++	}
++}
++
++#ifdef	CONFIG_USB_PERSIST
++
++#define USB_PERSIST	1
++
++/* For "persistent-device" resets we must mark the child devices for reset
++ * and turn off a possible connect-change status (so khubd won't disconnect
++ * them later).
++ */
++static void mark_children_for_reset_resume(struct usb_hub *hub)
++{
++	struct usb_device *hdev = hub->hdev;
++	int port1;
++
++	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
++		struct usb_device *child = hdev->children[port1-1];
++
++		if (child) {
++			child->reset_resume = 1;
++			clear_port_feature(hdev, port1,
++					USB_PORT_FEAT_C_CONNECTION);
+ 		}
+ 	}
++}
++
++#else
++
++#define USB_PERSIST	0
++
++static inline void mark_children_for_reset_resume(struct usb_hub *hub)
++{ }
++
++#endif	/* CONFIG_USB_PERSIST */
++
++/* caller has locked the hub device */
++static void hub_pre_reset(struct usb_interface *intf)
++{
++	struct usb_hub *hub = usb_get_intfdata(intf);
++
++	/* This routine doesn't run as part of a reset-resume, so it's safe
++	 * to disconnect all the drivers below the hub.
++	 */
++	disconnect_all_children(hub, 0);
+ 	hub_quiesce(hub);
+ }
+ 
+ /* caller has locked the hub device */
+-static void hub_post_reset(struct usb_interface *intf)
++static void hub_post_reset(struct usb_interface *intf, int reset_resume)
+ {
+ 	struct usb_hub *hub = usb_get_intfdata(intf);
+ 
+-	hub_activate(hub);
+ 	hub_power_on(hub);
++	if (reset_resume) {
++		if (USB_PERSIST)
++			mark_children_for_reset_resume(hub);
++		else {
++			/* Reset-resume doesn't call pre_reset, so we have to
++			 * disconnect the children here.  But we may not lock
++			 * the child devices, so we have to do a "logical"
++			 * disconnect.
++			 */
++			disconnect_all_children(hub, 1);
++		}
++	}
++	hub_activate(hub);
+ }
+ 
+ 
+@@ -1053,33 +1129,64 @@ void usb_set_device_state(struct usb_device *udev,
+ 
+ #ifdef	CONFIG_PM
+ 
++/**
++ * usb_reset_suspended_device - reset a suspended device instead of resuming it
++ * @udev: device to be reset instead of resumed
++ *
++ * If a host controller doesn't maintain VBUS suspend current during a
++ * system sleep or is reset when the system wakes up, all the USB
++ * power sessions below it will be broken.  This is especially troublesome
++ * for mass-storage devices containing mounted filesystems, since the
++ * device will appear to have disconnected and all the memory mappings
++ * to it will be lost.
++ *
++ * As an alternative, this routine attempts to recover power sessions for
++ * devices that are still present by resetting them instead of resuming
++ * them.  If all goes well, the devices will appear to persist across the
++ * the interruption of the power sessions.
++ *
++ * This facility is inherently dangerous.  Although usb_reset_device()
++ * makes every effort to insure that the same device is present after the
++ * reset as before, it cannot provide a 100% guarantee.  Furthermore it's
++ * quite possible for a device to remain unaltered but its media to be
++ * changed.  If the user replaces a flash memory card while the system is
++ * asleep, he will have only himself to blame when the filesystem on the
++ * new card is corrupted and the system crashes.
++ */
++int usb_reset_suspended_device(struct usb_device *udev)
++{
++	int rc = 0;
++
++	dev_dbg(&udev->dev, "usb %sresume\n", "reset-");
++
++	/* After we're done the device won't be suspended any more.
++	 * In addition, the reset won't work if udev->state is SUSPENDED.
++	 */
++	usb_set_device_state(udev, udev->actconfig
++			? USB_STATE_CONFIGURED
++			: USB_STATE_ADDRESS);
++
++	/* Root hubs don't need to be (and can't be) reset */
++	if (udev->parent)
++		rc = usb_reset_device(udev);
++	return rc;
++}
++
+ /**
+  * usb_root_hub_lost_power - called by HCD if the root hub lost Vbus power
+  * @rhdev: struct usb_device for the root hub
+  *
+  * The USB host controller driver calls this function when its root hub
+  * is resumed and Vbus power has been interrupted or the controller
+- * has been reset.  The routine marks all the children of the root hub
+- * as NOTATTACHED and marks logical connect-change events on their ports.
++ * has been reset.  The routine marks @rhdev as having lost power.  When
++ * the hub driver is resumed it will take notice; if CONFIG_USB_PERSIST
++ * is enabled then it will carry out power-session recovery, otherwise
++ * it will disconnect all the child devices.
+  */
+ void usb_root_hub_lost_power(struct usb_device *rhdev)
+ {
+-	struct usb_hub *hub;
+-	int port1;
+-	unsigned long flags;
+-
+ 	dev_warn(&rhdev->dev, "root hub lost power or was reset\n");
+-
+-	spin_lock_irqsave(&device_state_lock, flags);
+-	hub = hdev_to_hub(rhdev);
+-	for (port1 = 1; port1 <= rhdev->maxchild; ++port1) {
+-		if (rhdev->children[port1 - 1]) {
+-			recursively_mark_NOTATTACHED(
+-					rhdev->children[port1 - 1]);
+-			set_bit(port1, hub->change_bits);
+-		}
+-	}
+-	spin_unlock_irqrestore(&device_state_lock, flags);
++	rhdev->reset_resume = 1;
+ }
+ EXPORT_SYMBOL_GPL(usb_root_hub_lost_power);
+ 
+@@ -1513,29 +1620,6 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
+ 	return status;
+ }
+ 
+-/*
+- * Disable a port and mark a logical connnect-change event, so that some
+- * time later khubd will disconnect() any existing usb_device on the port
+- * and will re-enumerate if there actually is a device attached.
+- */
+-static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
+-{
+-	dev_dbg(hub->intfdev, "logical disconnect on port %d\n", port1);
+-	hub_port_disable(hub, port1, 1);
+-
+-	/* FIXME let caller ask to power down the port:
+-	 *  - some devices won't enumerate without a VBUS power cycle
+-	 *  - SRP saves power that way
+-	 *  - ... new call, TBD ...
+-	 * That's easy if this hub can switch power per-port, and
+-	 * khubd reactivates the port later (timer, SRP, etc).
+-	 * Powerdown must be optional, because of reset/DFU.
+-	 */
+-
+-	set_bit(port1, hub->change_bits);
+- 	kick_khubd(hub);
+-}
+-
+ #ifdef	CONFIG_PM
+ 
+ #ifdef	CONFIG_USB_SUSPEND
+@@ -3018,7 +3102,7 @@ int usb_reset_composite_device(struct usb_device *udev,
+ 					cintf->dev.driver) {
+ 				drv = to_usb_driver(cintf->dev.driver);
+ 				if (drv->post_reset)
+-					(drv->post_reset)(cintf);
++					(drv->post_reset)(cintf, 0);
+ 			}
+ 			if (cintf != iface)
+ 				up(&cintf->dev.sem);
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 6f361df374fc..1a4862886733 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -36,6 +36,7 @@ extern void usb_host_cleanup(void);
+ extern void usb_autosuspend_work(struct work_struct *work);
+ extern int usb_port_suspend(struct usb_device *dev);
+ extern int usb_port_resume(struct usb_device *dev);
++extern int usb_reset_suspended_device(struct usb_device *udev);
+ extern int usb_external_suspend_device(struct usb_device *udev,
+ 		pm_message_t msg);
+ extern int usb_external_resume_device(struct usb_device *udev);
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index df5dc186aef5..be4cd8fe4ce6 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -236,7 +236,7 @@ static void storage_pre_reset(struct usb_interface *iface)
+ 	mutex_lock(&us->dev_mutex);
+ }
+ 
+-static void storage_post_reset(struct usb_interface *iface)
++static void storage_post_reset(struct usb_interface *iface, int reset_resume)
+ {
+ 	struct us_data *us = usb_get_intfdata(iface);
+ 
+@@ -249,7 +249,11 @@ static void storage_post_reset(struct usb_interface *iface)
+ 
+ 	/* FIXME: Notify the subdrivers that they need to reinitialize
+ 	 * the device */
+-	mutex_unlock(&us->dev_mutex);
++
++	/* If this is a reset-resume then the pre_reset routine wasn't
++	 * called, so we don't need to unlock the mutex. */
++	if (!reset_resume)
++		mutex_unlock(&us->dev_mutex);
+ }
+ 
+ /*
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 56aa2ee21f1b..3d63e0c2dd70 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -403,6 +403,7 @@ struct usb_device {
+ 
+ 	unsigned auto_pm:1;		/* autosuspend/resume in progress */
+ 	unsigned do_remote_wakeup:1;	/* remote wakeup should be enabled */
++	unsigned reset_resume:1;	/* needs reset instead of resume */
+ 	unsigned autosuspend_disabled:1; /* autosuspend and autoresume */
+ 	unsigned autoresume_disabled:1;  /*  disabled by the user */
+ #endif
+@@ -819,7 +820,10 @@ struct usbdrv_wrap {
+  * @pre_reset: Called by usb_reset_composite_device() when the device
+  *	is about to be reset.
+  * @post_reset: Called by usb_reset_composite_device() after the device
+- *	has been reset.
++ *	has been reset, or in lieu of @resume following a reset-resume
++ *	(i.e., the device is reset instead of being resumed, as might
++ *	happen if power was lost).  The second argument tells which is
++ *	the reason.
+  * @id_table: USB drivers use ID table to support hotplugging.
+  *	Export this with MODULE_DEVICE_TABLE(usb,...).  This must be set
+  *	or your driver's probe function will never get called.
+@@ -861,7 +865,7 @@ struct usb_driver {
+ 	int (*resume) (struct usb_interface *intf);
+ 
+ 	void (*pre_reset) (struct usb_interface *intf);
+-	void (*post_reset) (struct usb_interface *intf);
++	void (*post_reset) (struct usb_interface *intf, int reset_resume);
+ 
+ 	const struct usb_device_id *id_table;
+ 

commit e8054854221d9d51e381c64d365404f4c1c30f50
+Author: Alan Stern 
+Date:   Fri May 4 11:55:11 2007 -0400
+
+    USB: make hub driver's release more robust
+    
+    This revised patch (as893c) improves the method used by the hub driver
+    to release its private data structure.  The current code is non-robust,
+    relying on a memory region not getting reused by another driver after
+    it has been freed.  The patch adds a reference count to the structure,
+    resolving the question of when to release it.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 9464eb504ae6..77a6627b18d2 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -34,6 +34,7 @@
+ struct usb_hub {
+ 	struct device		*intfdev;	/* the "interface" device */
+ 	struct usb_device	*hdev;
++	struct kref		kref;
+ 	struct urb		*urb;		/* for interrupt polling pipe */
+ 
+ 	/* buffer for urb ... with extra space in case of babble */
+@@ -66,6 +67,7 @@ struct usb_hub {
+ 	unsigned		limited_power:1;
+ 	unsigned		quiescing:1;
+ 	unsigned		activating:1;
++	unsigned		disconnected:1;
+ 
+ 	unsigned		has_indicators:1;
+ 	u8			indicator[USB_MAXCHILDREN];
+@@ -321,7 +323,7 @@ static void kick_khubd(struct usb_hub *hub)
+ 	to_usb_interface(hub->intfdev)->pm_usage_cnt = 1;
+ 
+ 	spin_lock_irqsave(&hub_event_lock, flags);
+-	if (list_empty(&hub->event_list)) {
++	if (!hub->disconnected & list_empty(&hub->event_list)) {
+ 		list_add_tail(&hub->event_list, &hub_event_list);
+ 		wake_up(&khubd_wait);
+ 	}
+@@ -330,6 +332,7 @@ static void kick_khubd(struct usb_hub *hub)
+ 
+ void usb_kick_khubd(struct usb_device *hdev)
+ {
++	/* FIXME: What if hdev isn't bound to the hub driver? */
+ 	kick_khubd(hdev_to_hub(hdev));
+ }
+ 
+@@ -845,43 +848,42 @@ static int hub_configure(struct usb_hub *hub,
+ 	return ret;
+ }
+ 
++static void hub_release(struct kref *kref)
++{
++	struct usb_hub *hub = container_of(kref, struct usb_hub, kref);
++
++	usb_put_intf(to_usb_interface(hub->intfdev));
++	kfree(hub);
++}
++
+ static unsigned highspeed_hubs;
+ 
+ static void hub_disconnect(struct usb_interface *intf)
+ {
+ 	struct usb_hub *hub = usb_get_intfdata (intf);
+-	struct usb_device *hdev;
++
++	/* Take the hub off the event list and don't let it be added again */
++	spin_lock_irq(&hub_event_lock);
++	list_del_init(&hub->event_list);
++	hub->disconnected = 1;
++	spin_unlock_irq(&hub_event_lock);
+ 
+ 	/* Disconnect all children and quiesce the hub */
+ 	hub->error = 0;
+ 	hub_pre_reset(intf);
+ 
+ 	usb_set_intfdata (intf, NULL);
+-	hdev = hub->hdev;
+ 
+-	if (hdev->speed == USB_SPEED_HIGH)
++	if (hub->hdev->speed == USB_SPEED_HIGH)
+ 		highspeed_hubs--;
+ 
+ 	usb_free_urb(hub->urb);
+-	hub->urb = NULL;
+-
+-	spin_lock_irq(&hub_event_lock);
+-	list_del_init(&hub->event_list);
+-	spin_unlock_irq(&hub_event_lock);
+-
+ 	kfree(hub->descriptor);
+-	hub->descriptor = NULL;
+-
+ 	kfree(hub->status);
+-	hub->status = NULL;
+-
+-	if (hub->buffer) {
+-		usb_buffer_free(hdev, sizeof(*hub->buffer), hub->buffer,
+-				hub->buffer_dma);
+-		hub->buffer = NULL;
+-	}
++	usb_buffer_free(hub->hdev, sizeof(*hub->buffer), hub->buffer,
++			hub->buffer_dma);
+ 
+-	kfree(hub);
++	kref_put(&hub->kref, hub_release);
+ }
+ 
+ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
+@@ -929,10 +931,12 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
+ 		return -ENOMEM;
+ 	}
+ 
++	kref_init(&hub->kref);
+ 	INIT_LIST_HEAD(&hub->event_list);
+ 	hub->intfdev = &intf->dev;
+ 	hub->hdev = hdev;
+ 	INIT_DELAYED_WORK(&hub->leds, led_work);
++	usb_get_intf(intf);
+ 
+ 	usb_set_intfdata (intf, hub);
+ 	intf->needs_remote_wakeup = 1;
+@@ -2534,10 +2538,12 @@ static void hub_events(void)
+ 		list_del_init(tmp);
+ 
+ 		hub = list_entry(tmp, struct usb_hub, event_list);
+-		hdev = hub->hdev;
+-		intf = to_usb_interface(hub->intfdev);
+-		hub_dev = &intf->dev;
++		kref_get(&hub->kref);
++		spin_unlock_irq(&hub_event_lock);
+ 
++		hdev = hub->hdev;
++		hub_dev = hub->intfdev;
++		intf = to_usb_interface(hub_dev);
+ 		dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n",
+ 				hdev->state, hub->descriptor
+ 					? hub->descriptor->bNbrPorts
+@@ -2546,13 +2552,10 @@ static void hub_events(void)
+ 				(u16) hub->change_bits[0],
+ 				(u16) hub->event_bits[0]);
+ 
+-		usb_get_intf(intf);
+-		spin_unlock_irq(&hub_event_lock);
+-
+ 		/* Lock the device, then check to see if we were
+ 		 * disconnected while waiting for the lock to succeed. */
+ 		usb_lock_device(hdev);
+-		if (hub != usb_get_intfdata(intf))
++		if (unlikely(hub->disconnected))
+ 			goto loop;
+ 
+ 		/* If the hub has died, clean up after it */
+@@ -2715,7 +2718,7 @@ static void hub_events(void)
+ 			usb_autopm_enable(intf);
+ loop:
+ 		usb_unlock_device(hdev);
+-		usb_put_intf(intf);
++		kref_put(&hub->kref, hub_release);
+ 
+         } /* end while (1) */
+ }

commit 06b84e8adcad8280d76a7c71e772c5cddba96d85
+Author: Alan Stern 
+Date:   Fri May 4 11:54:50 2007 -0400
+
+    USB: remove "locktree" routine from the hub driver
+    
+    This patch (as892) removes the "locktree" routine from the hub driver.
+    It currently is used in only one place, by a single kernel thread;
+    hence it isn't doing any good.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 702023075310..9464eb504ae6 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -982,49 +982,6 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
+ }
+ 
+ 
+-/* grab device/port lock, returning index of that port (zero based).
+- * protects the upstream link used by this device from concurrent
+- * tree operations like suspend, resume, reset, and disconnect, which
+- * apply to everything downstream of a given port.
+- */
+-static int locktree(struct usb_device *udev)
+-{
+-	int			t;
+-	struct usb_device	*hdev;
+-
+-	if (!udev)
+-		return -ENODEV;
+-
+-	/* root hub is always the first lock in the series */
+-	hdev = udev->parent;
+-	if (!hdev) {
+-		usb_lock_device(udev);
+-		return 0;
+-	}
+-
+-	/* on the path from root to us, lock everything from
+-	 * top down, dropping parent locks when not needed
+-	 */
+-	t = locktree(hdev);
+-	if (t < 0)
+-		return t;
+-
+-	/* everything is fail-fast once disconnect
+-	 * processing starts
+-	 */
+-	if (udev->state == USB_STATE_NOTATTACHED) {
+-		usb_unlock_device(hdev);
+-		return -ENODEV;
+-	}
+-
+-	/* when everyone grabs locks top->bottom,
+-	 * non-overlapping work may be concurrent
+-	 */
+-	usb_lock_device(udev);
+-	usb_unlock_device(hdev);
+-	return udev->portnum;
+-}
+-
+ static void recursively_mark_NOTATTACHED(struct usb_device *udev)
+ {
+ 	int i;
+@@ -2594,10 +2551,7 @@ static void hub_events(void)
+ 
+ 		/* Lock the device, then check to see if we were
+ 		 * disconnected while waiting for the lock to succeed. */
+-		if (locktree(hdev) < 0) {
+-			usb_put_intf(intf);
+-			continue;
+-		}
++		usb_lock_device(hdev);
+ 		if (hub != usb_get_intfdata(intf))
+ 			goto loop;
+ 

commit f3fd77cd2f4499f3e2ef9a1e6d5e4f4349d556c3
+Author: Alan Stern 
+Date:   Fri May 4 11:54:28 2007 -0400
+
+    USB: remove references to dev.power.power_state
+    
+    This revised patch (as891b) removes two unnecessary references to
+    intf->dev.power.power_state from usb-storage, and replaces a reference
+    to root_hub->dev.power.power_state with a check of hcd->state.  This
+    is in preparation for the removal of dev.power.power_state, which is
+    already deprecated.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index edf4300a3f7a..5cf6d5f9acbd 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -207,7 +207,8 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
+ 	 * We must ignore the FREEZE vs SUSPEND distinction here, because
+ 	 * otherwise the swsusp will save (and restore) garbage state.
+ 	 */
+-	if (hcd->self.root_hub->dev.power.power_state.event == PM_EVENT_ON)
++	if (!(hcd->state == HC_STATE_SUSPENDED ||
++			hcd->state == HC_STATE_HALT))
+ 		return -EBUSY;
+ 
+ 	if (hcd->driver->suspend) {
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 8e898e3d861e..df5dc186aef5 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -197,7 +197,6 @@ static int storage_suspend(struct usb_interface *iface, pm_message_t message)
+ 	US_DEBUGP("%s\n", __FUNCTION__);
+ 	if (us->suspend_resume_hook)
+ 		(us->suspend_resume_hook)(us, US_SUSPEND);
+-	iface->dev.power.power_state.event = message.event;
+ 
+ 	/* When runtime PM is working, we'll set a flag to indicate
+ 	 * whether we should autoresume when a SCSI request arrives. */
+@@ -215,7 +214,6 @@ static int storage_resume(struct usb_interface *iface)
+ 	US_DEBUGP("%s\n", __FUNCTION__);
+ 	if (us->suspend_resume_hook)
+ 		(us->suspend_resume_hook)(us, US_RESUME);
+-	iface->dev.power.power_state.event = PM_EVENT_ON;
+ 
+ 	mutex_unlock(&us->dev_mutex);
+ 	return 0;

commit 8adb4786789c25007f39b4d00dd03cc83bdcb896
+Author: Alan Stern 
+Date:   Fri May 4 11:53:30 2007 -0400
+
+    USB: don't unsuspend for a new connection
+    
+    This patch (as889) prevents the hub driver from trying to resume a
+    port when there is a new connection.  For one thing, the resume is not
+    needed -- the upcoming port reset will clear the suspend feature
+    automatically.  For another, on some systems the resume fails and
+    causes problems.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 8aea8559bec2..702023075310 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2426,19 +2426,6 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 		return;
+ 	}
+ 
+-#ifdef  CONFIG_USB_SUSPEND
+-	/* If something is connected, but the port is suspended, wake it up. */
+-	if (portstatus & USB_PORT_STAT_SUSPEND) {
+-		status = hub_port_resume(hub, port1, NULL);
+-		if (status < 0) {
+-			dev_dbg(hub_dev,
+-				"can't clear suspend on port %d; %d\n",
+-				port1, status);
+-			goto done;
+-		}
+-	}
+-#endif
+-
+ 	for (i = 0; i < SET_CONFIG_TRIES; i++) {
+ 		struct usb_device *udev;
+ 

commit b6f6436da0c6853eedad86f5075b139c1a3bcb5d
+Author: Alan Stern 
+Date:   Fri May 4 11:51:54 2007 -0400
+
+    USB: move bus_suspend and bus_resume method calls
+    
+    This patch (as885) moves the root-hub bus_suspend() and bus_resume()
+    method calls from the hub driver's suspend and resume methods into the
+    usb_generic driver methods, where they make just as much sense.
+    
+    Their old locations were not fully correct.  For example, in a kernel
+    compiled without CONFIG_USB_SUSPEND, if one were to do:
+    
+            echo -n 1-0:1.0 >/sys/bus/usb/drivers/hub/unbind
+    
+    to unbind the hub driver from a root hub, there would then be no way
+    to suspend that root hub.  Attempts to put the system to sleep would
+    fail; the USB controller driver would refuse to suspend because the
+    root hub was still active.
+    
+    The patch also makes a very slight change in the way devices with no
+    driver are handled during suspend.  Rather than doing a standard USB
+    port-suspend directly, now the suspend routine in usb_generic is
+    called.  In practice this should never affect anyone.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 63d47946e3db..e8b447e06c54 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -802,14 +802,13 @@ static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
+ 			udev->state == USB_STATE_SUSPENDED)
+ 		goto done;
+ 
+-	/* For devices that don't have a driver, we do a standard suspend. */
+-	if (udev->dev.driver == NULL) {
++	/* For devices that don't have a driver, we do a generic suspend. */
++	if (udev->dev.driver)
++		udriver = to_usb_device_driver(udev->dev.driver);
++	else {
+ 		udev->do_remote_wakeup = 0;
+-		status = usb_port_suspend(udev);
+-		goto done;
++		udriver = &usb_generic_driver;
+ 	}
+-
+-	udriver = to_usb_device_driver(udev->dev.driver);
+ 	status = udriver->suspend(udev, msg);
+ 
+ done:
+diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
+index e7ec9b6b7a93..7cbf992adccd 100644
+--- a/drivers/usb/core/generic.c
++++ b/drivers/usb/core/generic.c
+@@ -19,6 +19,7 @@
+ 
+ #include 
+ #include "usb.h"
++#include "hcd.h"
+ 
+ static inline const char *plural(int n)
+ {
+@@ -193,12 +194,46 @@ static void generic_disconnect(struct usb_device *udev)
+ 
+ static int generic_suspend(struct usb_device *udev, pm_message_t msg)
+ {
+-	return usb_port_suspend(udev);
++	int rc;
++
++	rc = usb_port_suspend(udev);
++
++	/* Root hubs don't have upstream ports to suspend,
++	 * so the line above won't do much for them.  We have to
++	 * shut down their downstream HC-to-USB interfaces manually,
++	 * by doing a bus (or "global") suspend.
++	 */
++	if (rc == 0 && !udev->parent) {
++		rc = hcd_bus_suspend(udev->bus);
++		if (rc) {
++			dev_dbg(&udev->dev, "'global' suspend %d\n", rc);
++			usb_port_resume(udev);
++		}
++	}
++	return rc;
+ }
+ 
+ static int generic_resume(struct usb_device *udev)
+ {
+-	return usb_port_resume(udev);
++	int rc;
++
++	rc = usb_port_resume(udev);
++
++	/* Root hubs don't have upstream ports to resume or reset,
++	 * so the line above won't do much for them.  We have to
++	 * start up their downstream HC-to-USB interfaces manually,
++	 * by doing a bus (or "global") resume.
++	 */
++	if (rc == 0 && !udev->parent) {
++		rc = hcd_bus_resume(udev->bus);
++		if (rc)
++			dev_dbg(&udev->dev, "'global' resume %d\n", rc);
++		else {
++			/* TRSMRCY = 10 msec */
++			msleep(10);
++		}
++	}
++	return rc;
+ }
+ 
+ #endif	/* CONFIG_PM */
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index a9cf8b30bccc..8aea8559bec2 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1916,7 +1916,6 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+ 	struct usb_hub		*hub = usb_get_intfdata (intf);
+ 	struct usb_device	*hdev = hub->hdev;
+ 	unsigned		port1;
+-	int			status = 0;
+ 
+ 	/* fail if children aren't already suspended */
+ 	for (port1 = 1; port1 <= hdev->maxchild; port1++) {
+@@ -1942,44 +1941,15 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+ 
+ 	/* stop khubd and related activity */
+ 	hub_quiesce(hub);
+-
+-	/* "global suspend" of the downstream HC-to-USB interface */
+-	if (!hdev->parent) {
+-		status = hcd_bus_suspend(hdev->bus);
+-		if (status != 0) {
+-			dev_dbg(&hdev->dev, "'global' suspend %d\n", status);
+-			hub_activate(hub);
+-		}
+-	}
+-	return status;
++	return 0;
+ }
+ 
+ static int hub_resume(struct usb_interface *intf)
+ {
+ 	struct usb_hub		*hub = usb_get_intfdata (intf);
+-	struct usb_device	*hdev = hub->hdev;
+-	int			status;
+ 
+ 	dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
+ 
+-	/* "global resume" of the downstream HC-to-USB interface */
+-	if (!hdev->parent) {
+-		struct usb_bus	*bus = hdev->bus;
+-		if (bus) {
+-			status = hcd_bus_resume (bus);
+-			if (status) {
+-				dev_dbg(&intf->dev, "'global' resume %d\n",
+-					status);
+-				return status;
+-			}
+-		} else
+-			return -EOPNOTSUPP;
+-		if (status == 0) {
+-			/* TRSMRCY = 10 msec */
+-			msleep(10);
+-		}
+-	}
+-
+ 	/* tell khubd to look for changes on this hub */
+ 	hub_activate(hub);
+ 	return 0;

commit 4d461095ef6967324bc5da5d65d23ad27fc604f9
+Author: Alan Stern 
+Date:   Fri May 4 11:51:25 2007 -0400
+
+    USB: Implement PM FREEZE and PRETHAW
+    
+    This patch (as884) finally implements the time-saving semantics
+    possible with the Power Management FREEZE and PRETHAW events.  Their
+    proper handling requires only that devices be quiesced, with
+    interrupts and DMA turned off; non-root USB devices don't actually
+    need to be put in a suspended state.  The patch checks and avoids
+    doing the suspend call when possible.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 38c3dd2a44e0..63d47946e3db 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1050,8 +1050,15 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 				break;
+ 		}
+ 	}
+-	if (status == 0)
++	if (status == 0) {
++
++		/* Non-root devices don't need to do anything for FREEZE
++		 * or PRETHAW. */
++		if (udev->parent && (msg.event == PM_EVENT_FREEZE ||
++				msg.event == PM_EVENT_PRETHAW))
++			goto done;
+ 		status = usb_suspend_device(udev, msg);
++	}
+ 
+ 	/* If the suspend failed, resume interfaces that did get suspended */
+ 	if (status != 0) {
+diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
+index 9bbcb20e2d94..e7ec9b6b7a93 100644
+--- a/drivers/usb/core/generic.c
++++ b/drivers/usb/core/generic.c
+@@ -193,10 +193,6 @@ static void generic_disconnect(struct usb_device *udev)
+ 
+ static int generic_suspend(struct usb_device *udev, pm_message_t msg)
+ {
+-	/* USB devices enter SUSPEND state through their hubs, but can be
+-	 * marked for FREEZE as soon as their children are already idled.
+-	 * But those semantics are useless, so we equate the two (sigh).
+-	 */
+ 	return usb_port_suspend(udev);
+ }
+ 

commit 784a6e1cc406b7ef48476a1f38b83fc551f5616f
+Author: Alan Stern 
+Date:   Fri May 4 11:49:57 2007 -0400
+
+    USB: interface PM state
+    
+    This patch (as880) strives to keep the PM core's idea of a USB
+    interface's power state in synch with usbcore's own idea.  In the end
+    this doesn't really matter, but it's better to be consistent.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 2619986e5300..38c3dd2a44e0 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -879,8 +879,6 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
+ 
+ done:
+ 	// dev_dbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
+-	if (status == 0)
+-		intf->dev.power.power_state.event = msg.event;
+ 	return status;
+ }
+ 
+@@ -920,8 +918,6 @@ static int usb_resume_interface(struct usb_interface *intf)
+ 
+ done:
+ 	// dev_dbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
+-	if (status == 0)
+-		intf->dev.power.power_state.event = PM_EVENT_ON;
+ 	return status;
+ }
+ 
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index bf2eb0dae2ec..6f361df374fc 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -100,11 +100,13 @@ static inline int is_usb_device_driver(struct device_driver *drv)
+ static inline void mark_active(struct usb_interface *f)
+ {
+ 	f->is_active = 1;
++	f->dev.power.power_state.event = PM_EVENT_ON;
+ }
+ 
+ static inline void mark_quiesced(struct usb_interface *f)
+ {
+ 	f->is_active = 0;
++	f->dev.power.power_state.event = PM_EVENT_SUSPEND;
+ }
+ 
+ static inline int is_active(const struct usb_interface *f)

commit 2fa45a4cffd0c4ab4e238e8ad3b4f9b0c10ac1f3
+Author: Alan Stern 
+Date:   Wed May 30 11:11:12 2007 -0400
+
+    USB HID: avoid flush_scheduled_work()
+    
+    This patch (as914) replaces a call to flush_scheduled_work() with
+    cancel_work_sync(), in order to help avoid potential deadlocks.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index d91b9dac6dff..093abb5c9879 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -956,7 +956,7 @@ static void hid_disconnect(struct usb_interface *intf)
+ 	usb_kill_urb(usbhid->urbctrl);
+ 
+ 	del_timer_sync(&usbhid->io_retry);
+-	flush_scheduled_work();
++	cancel_work_sync(&usbhid->reset_work);
+ 
+ 	if (hid->claimed & HID_CLAIMED_INPUT)
+ 		hidinput_disconnect(hid);

commit 6fd75b19483b2f6e6619602a535b4939e46921c1
+Author: Alan Stern 
+Date:   Fri May 4 11:57:00 2007 -0400
+
+    OHCI: Fix machine check in ohci_hub_status_data
+    
+    This patch (as901) fixes an oversight in ohci-hcd.  The
+    hub_status_data routine must not try to access the controller's
+    memory-mapped registers if the controller is in a low-power state;
+    such attempts will cause a crash on some architectures (such as PPC).
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index 216c9c9d4d6d..bb9cc595219e 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -417,6 +417,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ 	unsigned long	flags;
+ 
+ 	spin_lock_irqsave (&ohci->lock, flags);
++	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
++		goto done;
+ 
+ 	/* undocumented erratum seen on at least rev D */
+ 	if ((ohci->flags & OHCI_QUIRK_AMD756)

commit 615ae11b3b4af7a5adb0819ff11b3b764eb92268
+Author: Alan Stern 
+Date:   Fri Jun 8 15:23:27 2007 -0400
+
+    USB: Fix up bogus bInterval values in endpoint descriptors
+    
+    This patch (as904) adds code to check for endpoint descriptor bInterval
+    values outside the legal limits.  Illegal values are set to 32 ms, which
+    seems like a reasonable default.
+    
+    This fixes Bugzilla #8432.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
+index 2d4fd530e5e4..dd3482328ad2 100644
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -1,4 +1,5 @@
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -49,7 +50,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
+ 	unsigned char *buffer0 = buffer;
+ 	struct usb_endpoint_descriptor *d;
+ 	struct usb_host_endpoint *endpoint;
+-	int n, i;
++	int n, i, j;
+ 
+ 	d = (struct usb_endpoint_descriptor *) buffer;
+ 	buffer += d->bLength;
+@@ -84,6 +85,45 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
+ 	memcpy(&endpoint->desc, d, n);
+ 	INIT_LIST_HEAD(&endpoint->urb_list);
+ 
++	/* If the bInterval value is outside the legal range,
++	 * set it to a default value: 32 ms */
++	i = 0;		/* i = min, j = max, n = default */
++	j = 255;
++	if (usb_endpoint_xfer_int(d)) {
++		i = 1;
++		switch (to_usb_device(ddev)->speed) {
++		case USB_SPEED_HIGH:
++			n = 9;		/* 32 ms = 2^(9-1) uframes */
++			j = 16;
++			break;
++		default:		/* USB_SPEED_FULL or _LOW */
++			/* For low-speed, 10 ms is the official minimum.
++			 * But some "overclocked" devices might want faster
++			 * polling so we'll allow it. */
++			n = 32;
++			break;
++		}
++	} else if (usb_endpoint_xfer_isoc(d)) {
++		i = 1;
++		j = 16;
++		switch (to_usb_device(ddev)->speed) {
++		case USB_SPEED_HIGH:
++			n = 9;		/* 32 ms = 2^(9-1) uframes */
++			break;
++		default:		/* USB_SPEED_FULL */
++			n = 6;		/* 32 ms = 2^(6-1) frames */
++			break;
++		}
++	}
++	if (d->bInterval < i || d->bInterval > j) {
++		dev_warn(ddev, "config %d interface %d altsetting %d "
++		    "endpoint 0x%X has an invalid bInterval %d, "
++		    "changing to %d\n",
++		    cfgno, inum, asnum,
++		    d->bEndpointAddress, d->bInterval, n);
++		endpoint->desc.bInterval = n;
++	}
++
+ 	/* Skip over any Class Specific or Vendor Specific descriptors;
+ 	 * find the next endpoint or interface descriptor */
+ 	endpoint->extra = buffer;

commit d5d4db704b962773c03ee3beb3258b6450611e66
+Author: Alan Stern 
+Date:   Tue May 29 16:34:52 2007 -0400
+
+    USB: replace flush_workqueue with cancel_sync_work
+    
+    This patch (as912) replaces a couple of calls to flush_workqueue()
+    with cancel_sync_work() and cancel_rearming_delayed_work().  Using a
+    more directed approach allows us to avoid some nasty deadlocks.  The
+    prime example occurs when a first-level device (the parent is a root
+    hub) is removed while at the same time the root hub gets a remote
+    wakeup request.  khubd would try to flush the autosuspend workqueue
+    while holding the root-hub's lock, and the remote-wakeup workqueue
+    routine would be waiting to lock the root hub.
+    
+    The patch also reorganizes the power management portion of
+    usb_disconnect(), separating it out into its own routine.  The
+    autosuspend workqueue entry is cancelled immediately instead of
+    waiting for the device's release routine.  In addition,
+    synchronization with the autosuspend thread is carried out even for
+    root hubs (an oversight in the original code).
+    
+    Signed-off-by: Alan Stern 
+    Cc: Andrew Morton 
+    Cc: Greg KH 
+    Cc: Mark Lord 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index e277258df382..8969e42434b9 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1681,7 +1681,7 @@ void usb_remove_hcd(struct usb_hcd *hcd)
+ 	spin_unlock_irq (&hcd_root_hub_lock);
+ 
+ #ifdef CONFIG_PM
+-	flush_workqueue(ksuspend_usb_wq);
++	cancel_work_sync(&hcd->wakeup_work);
+ #endif
+ 
+ 	mutex_lock(&usb_bus_list_lock);
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index caaa46f2dec7..24f10a19dbdb 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1158,6 +1158,30 @@ static void release_address(struct usb_device *udev)
+ 	}
+ }
+ 
++#ifdef	CONFIG_USB_SUSPEND
++
++static void usb_stop_pm(struct usb_device *udev)
++{
++	/* Synchronize with the ksuspend thread to prevent any more
++	 * autosuspend requests from being submitted, and decrement
++	 * the parent's count of unsuspended children.
++	 */
++	usb_pm_lock(udev);
++	if (udev->parent && !udev->discon_suspended)
++		usb_autosuspend_device(udev->parent);
++	usb_pm_unlock(udev);
++
++	/* Stop any autosuspend requests already submitted */
++	cancel_rearming_delayed_work(&udev->autosuspend);
++}
++
++#else
++
++static inline void usb_stop_pm(struct usb_device *udev)
++{ }
++
++#endif
++
+ /**
+  * usb_disconnect - disconnect a device (usbcore-internal)
+  * @pdev: pointer to device being disconnected
+@@ -1224,13 +1248,7 @@ void usb_disconnect(struct usb_device **pdev)
+ 	*pdev = NULL;
+ 	spin_unlock_irq(&device_state_lock);
+ 
+-	/* Decrement the parent's count of unsuspended children */
+-	if (udev->parent) {
+-		usb_pm_lock(udev);
+-		if (!udev->discon_suspended)
+-			usb_autosuspend_device(udev->parent);
+-		usb_pm_unlock(udev);
+-	}
++	usb_stop_pm(udev);
+ 
+ 	put_device(&udev->dev);
+ }
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 80627b6a2bf9..4a6299bd0047 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -184,10 +184,6 @@ static void usb_release_dev(struct device *dev)
+ 
+ 	udev = to_usb_device(dev);
+ 
+-#ifdef	CONFIG_USB_SUSPEND
+-	cancel_delayed_work(&udev->autosuspend);
+-	flush_workqueue(ksuspend_usb_wq);
+-#endif
+ 	usb_destroy_configuration(udev);
+ 	usb_put_hcd(bus_to_hcd(udev->bus));
+ 	kfree(udev->product);

commit ae2d990eede0ef5938c210d48a177c044258ecd8
+Author: Alan Stern 
+Date:   Wed May 23 13:58:12 2007 -0700
+
+    HiSax: fix error checking for hisax_register()]
+    
+    This patch (as875) adds error-checking to the callers of hisax_register().
+    It also changes an error pathway in that routine, making it return an error
+    code rather than 0.
+    
+    This fixes Bugzilla #7960.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Karsten Keil 
+    Cc: Martin Bachem 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
+index da4196f21e0f..8d53a7fd2671 100644
+--- a/drivers/isdn/hisax/config.c
++++ b/drivers/isdn/hisax/config.c
+@@ -1551,7 +1551,7 @@ int hisax_register(struct hisax_d_if *hisax_d_if, struct hisax_b_if *b_if[],
+ 	if (retval == 0) { // yuck
+ 		cards[i].typ = 0;
+ 		nrcards--;
+-		return retval;
++		return -EINVAL;
+ 	}
+ 	cs = cards[i].cs;
+ 	hisax_d_if->cs = cs;
+diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c
+index 1f18f1993387..b1a26e02df02 100644
+--- a/drivers/isdn/hisax/hfc_usb.c
++++ b/drivers/isdn/hisax/hfc_usb.c
+@@ -485,7 +485,6 @@ fill_isoc_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe,
+ {
+ 	int k;
+ 
+-	spin_lock_init(&urb->lock);
+ 	urb->dev = dev;
+ 	urb->pipe = pipe;
+ 	urb->complete = complete;
+@@ -578,16 +577,14 @@ stop_isoc_chain(usb_fifo * fifo)
+ 			    "HFC-S USB: Stopping iso chain for fifo %i.%i",
+ 			    fifo->fifonum, i);
+ #endif
+-			usb_unlink_urb(fifo->iso[i].purb);
++			usb_kill_urb(fifo->iso[i].purb);
+ 			usb_free_urb(fifo->iso[i].purb);
+ 			fifo->iso[i].purb = NULL;
+ 		}
+ 	}
+-	if (fifo->urb) {
+-		usb_unlink_urb(fifo->urb);
+-		usb_free_urb(fifo->urb);
+-		fifo->urb = NULL;
+-	}
++	usb_kill_urb(fifo->urb);
++	usb_free_urb(fifo->urb);
++	fifo->urb = NULL;
+ 	fifo->active = 0;
+ }
+ 
+@@ -1305,7 +1302,11 @@ usb_init(hfcusb_data * hfc)
+ 	}
+ 	/* default Prot: EURO ISDN, should be a module_param */
+ 	hfc->protocol = 2;
+-	hisax_register(&hfc->d_if, p_b_if, "hfc_usb", hfc->protocol);
++	i = hisax_register(&hfc->d_if, p_b_if, "hfc_usb", hfc->protocol);
++	if (i) {
++		printk(KERN_INFO "HFC-S USB: hisax_register -> %d\n", i);
++		return i;
++	}
+ 
+ #ifdef CONFIG_HISAX_DEBUG
+ 	hfc_debug = debug;
+@@ -1626,11 +1627,9 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
+ #endif
+ 			/* init the chip and register the driver */
+ 			if (usb_init(context)) {
+-				if (context->ctrl_urb) {
+-					usb_unlink_urb(context->ctrl_urb);
+-					usb_free_urb(context->ctrl_urb);
+-					context->ctrl_urb = NULL;
+-				}
++				usb_kill_urb(context->ctrl_urb);
++				usb_free_urb(context->ctrl_urb);
++				context->ctrl_urb = NULL;
+ 				kfree(context);
+ 				return (-EIO);
+ 			}
+@@ -1682,21 +1681,15 @@ hfc_usb_disconnect(struct usb_interface
+ 				    i);
+ #endif
+ 			}
+-			if (context->fifos[i].urb) {
+-				usb_unlink_urb(context->fifos[i].urb);
+-				usb_free_urb(context->fifos[i].urb);
+-				context->fifos[i].urb = NULL;
+-			}
++			usb_kill_urb(context->fifos[i].urb);
++			usb_free_urb(context->fifos[i].urb);
++			context->fifos[i].urb = NULL;
+ 		}
+ 		context->fifos[i].active = 0;
+ 	}
+-	/* wait for all URBS to terminate */
+-	mdelay(10);
+-	if (context->ctrl_urb) {
+-		usb_unlink_urb(context->ctrl_urb);
+-		usb_free_urb(context->ctrl_urb);
+-		context->ctrl_urb = NULL;
+-	}
++	usb_kill_urb(context->ctrl_urb);
++	usb_free_urb(context->ctrl_urb);
++	context->ctrl_urb = NULL;
+ 	hisax_unregister(&context->d_if);
+ 	kfree(context);		/* free our structure again */
+ }				/* hfc_usb_disconnect */
+diff --git a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c
+index 9e088fce8c3a..7993e01f9fc5 100644
+--- a/drivers/isdn/hisax/hisax_fcpcipnp.c
++++ b/drivers/isdn/hisax/hisax_fcpcipnp.c
+@@ -859,7 +859,11 @@ new_adapter(void)
+ 	for (i = 0; i < 2; i++)
+ 		b_if[i] = &adapter->bcs[i].b_if;
+ 
+-	hisax_register(&adapter->isac.hisax_d_if, b_if, "fcpcipnp", protocol);
++	if (hisax_register(&adapter->isac.hisax_d_if, b_if, "fcpcipnp",
++			protocol) != 0) {
++		kfree(adapter);
++		adapter = NULL;
++	}
+ 
+ 	return adapter;
+ }
+diff --git a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c
+index bb3a28a53ff4..13751237bfcd 100644
+--- a/drivers/isdn/hisax/st5481_init.c
++++ b/drivers/isdn/hisax/st5481_init.c
+@@ -107,12 +107,17 @@ static int probe_st5481(struct usb_interface *intf,
+ 	for (i = 0; i < 2; i++)
+ 		b_if[i] = &adapter->bcs[i].b_if;
+ 
+-	hisax_register(&adapter->hisax_d_if, b_if, "st5481_usb", protocol);
++	if (hisax_register(&adapter->hisax_d_if, b_if, "st5481_usb",
++			protocol) != 0)
++		goto err_b1;
++
+ 	st5481_start(adapter);
+ 
+ 	usb_set_intfdata(intf, adapter);
+ 	return 0;
+ 
++ err_b1:
++	st5481_release_b(&adapter->bcs[1]);
+  err_b:
+ 	st5481_release_b(&adapter->bcs[0]);
+  err_d:
+diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c
+index ff1595122048..4ada66b8b679 100644
+--- a/drivers/isdn/hisax/st5481_usb.c
++++ b/drivers/isdn/hisax/st5481_usb.c
+@@ -407,7 +407,6 @@ fill_isoc_urb(struct urb *urb, struct usb_device *dev,
+ {
+ 	int k;
+ 
+-	spin_lock_init(&urb->lock);
+ 	urb->dev=dev;
+ 	urb->pipe=pipe;
+ 	urb->interval = 1;

commit d4b7d8e8024a33d9d1f916379eaee7aa945a7c48
+Author: Alan Stern 
+Date:   Tue May 22 11:48:17 2007 -0400
+
+    USB: fix ratelimit call semantics
+    
+    This patch (as910) fixes a ratelimit modification so that the
+    original error-handling path will be followed even when the log-rate
+    limitation kicks in.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 6a6e4f8c69ba..caaa46f2dec7 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2421,10 +2421,10 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 
+ 	if (portchange & USB_PORT_STAT_C_CONNECTION) {
+ 		status = hub_port_debounce(hub, port1);
+-		if (status < 0 && printk_ratelimit()) {
+-			dev_err (hub_dev,
+-				"connect-debounce failed, port %d disabled\n",
+-				port1);
++		if (status < 0) {
++			if (printk_ratelimit())
++				dev_err (hub_dev, "connect-debounce failed, "
++						"port %d disabled\n", port1);
+ 			goto done;
+ 		}
+ 		portstatus = status;

commit dd865571d7af06ba1285c2db85083649193cceab
+Author: Alan Stern 
+Date:   Tue May 22 11:38:19 2007 -0400
+
+    USB: handle errors in power/level attribute
+    
+    This patch (as906) improves the error handling for the USB power/level
+    attribute file.  If an error occurs, the original power-level settings
+    will be restored.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index e7c982377488..be37c863fdfb 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -232,12 +232,15 @@ set_level(struct device *dev, struct device_attribute *attr,
+ 	int len = count;
+ 	char *cp;
+ 	int rc = 0;
++	int old_autosuspend_disabled, old_autoresume_disabled;
+ 
+ 	cp = memchr(buf, '\n', count);
+ 	if (cp)
+ 		len = cp - buf;
+ 
+ 	usb_lock_device(udev);
++	old_autosuspend_disabled = udev->autosuspend_disabled;
++	old_autoresume_disabled = udev->autoresume_disabled;
+ 
+ 	/* Setting the flags without calling usb_pm_lock is a subject to
+ 	 * races, but who cares...
+@@ -263,6 +266,10 @@ set_level(struct device *dev, struct device_attribute *attr,
+ 	} else
+ 		rc = -EINVAL;
+ 
++	if (rc) {
++		udev->autosuspend_disabled = old_autosuspend_disabled;
++		udev->autoresume_disabled = old_autoresume_disabled;
++	}
+ 	usb_unlock_device(udev);
+ 	return (rc < 0 ? rc : count);
+ }

commit 7ed92f1a149dddc3cb537ccd7441e98adac12c3e
+Author: Alan Stern 
+Date:   Tue May 22 09:38:39 2007 -0400
+
+    USB: make the autosuspend workqueue thread freezable
+    
+    This patch (as881b) makes the ksuspend_usb_wq workqueue freezable.  We
+    don't want a rogue workqueue thread running around, unexpectedly
+    suspending or resuming USB devices in the middle of a system sleep
+    transition.
+    
+    This fixes Bugzilla #8498.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 18ddc5e67e39..80627b6a2bf9 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -205,7 +205,11 @@ struct device_type usb_device_type = {
+ 
+ static int ksuspend_usb_init(void)
+ {
+-	ksuspend_usb_wq = create_singlethread_workqueue("ksuspend_usbd");
++	/* This workqueue is supposed to be both freezable and
++	 * singlethreaded.  Its job doesn't justify running on more
++	 * than one CPU.
++	 */
++	ksuspend_usb_wq = create_freezeable_workqueue("ksuspend_usbd");
+ 	if (!ksuspend_usb_wq)
+ 		return -ENOMEM;
+ 	return 0;

commit 57a21c1b929450b1e020c0a03cca6fa7448f4222
+Author: Alan Stern 
+Date:   Tue May 15 17:40:37 2007 -0400
+
+    USB: don't try to kzalloc 0 bytes
+    
+    This patch (as907) prevents us from trying to allocate 0 bytes
+    when an interface has no endpoint descriptors.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
+index bfb3731d42db..2d4fd530e5e4 100644
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -185,10 +185,12 @@ static int usb_parse_interface(struct device *ddev, int cfgno,
+ 		num_ep = USB_MAXENDPOINTS;
+ 	}
+ 
+-	len = sizeof(struct usb_host_endpoint) * num_ep;
+-	alt->endpoint = kzalloc(len, GFP_KERNEL);
+-	if (!alt->endpoint)
+-		return -ENOMEM;
++	if (num_ep > 0) {	/* Can't allocate 0 bytes */
++		len = sizeof(struct usb_host_endpoint) * num_ep;
++		alt->endpoint = kzalloc(len, GFP_KERNEL);
++		if (!alt->endpoint)
++			return -ENOMEM;
++	}
+ 
+ 	/* Parse all the endpoint descriptors */
+ 	n = 0;

commit b89ee19ae6c0b5a0d9facca780b53959fbadd123
+Author: Alan Stern 
+Date:   Fri May 11 10:19:04 2007 -0400
+
+    USB: remove short initial timeout for device descriptor fetch
+    
+    This patch (as905) removes a micro-optimization from the hub port
+    initialization code.  Previously we had been using a short timeout on
+    the first attempt the read the device descriptor; now we will use the
+    standard timeout length.
+    
+    It's not clear that the short timeout ever provided any benefit.  And
+    now we know of one case where it actually hurts: The device can't meet
+    the short timeout and then it gets terminally confused.
+    
+    This fixes Bugzilla #8444.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index f6b74a678de5..6a6e4f8c69ba 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2201,14 +2201,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ 				continue;
+ 			}
+ 
+-			/* Use a short timeout the first time through,
+-			 * so that recalcitrant full-speed devices with
+-			 * 8- or 16-byte ep0-maxpackets won't slow things
+-			 * down tremendously by NAKing the unexpectedly
+-			 * early status stage.  Also, retry on all errors;
+-			 * some devices are flakey.
+-			 * 255 is for WUSB devices, we actually need to use 512.
+-			 * WUSB1.0[4.8.1].
++			/* Retry on all errors; some devices are flakey.
++			 * 255 is for WUSB devices, we actually need to use
++			 * 512 (WUSB1.0[4.8.1]).
+ 			 */
+ 			for (j = 0; j < 3; ++j) {
+ 				buf->bMaxPacketSize0 = 0;
+@@ -2216,7 +2211,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ 					USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+ 					USB_DT_DEVICE << 8, 0,
+ 					buf, GET_DESCRIPTOR_BUFSIZE,
+-					(i ? USB_CTRL_GET_TIMEOUT : 1000));
++					USB_CTRL_GET_TIMEOUT);
+ 				switch (buf->bMaxPacketSize0) {
+ 				case 8: case 16: case 32: case 64: case 255:
+ 					if (buf->bDescriptorType ==

commit 8d062b9a3516c6fbcf749bcc864fdb8b3def1caa
+Author: Alan Stern 
+Date:   Mon Apr 23 17:30:32 2007 -0400
+
+    USB: set the correct Interrupt interval in usb_bulk_msg
+    
+    This patch (as902) fixes a mistake I introduced into usb_bulk_msg().
+    usb_fill_int_urb() already does the bit-shifting calculation for
+    high-speed Interrupt intervals; it shouldn't be done twice.
+    
+    Signed-off-by: Alan Stern 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index b7434787db5f..f9fed34bf7d8 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -221,15 +221,10 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
+ 
+ 	if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+ 			USB_ENDPOINT_XFER_INT) {
+-		int interval;
+-
+-		if (usb_dev->speed == USB_SPEED_HIGH)
+-			interval = 1 << min(15, ep->desc.bInterval - 1);
+-		else
+-			interval = ep->desc.bInterval;
+ 		pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);
+ 		usb_fill_int_urb(urb, usb_dev, pipe, data, len,
+-				usb_api_blocking_completion, NULL, interval);
++				usb_api_blocking_completion, NULL,
++				ep->desc.bInterval);
+ 	} else
+ 		usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
+ 				usb_api_blocking_completion, NULL);

commit bf87ce5a06ed2cb13ad04f065706cf36ab021549
+Author: Alan Stern 
+Date:   Thu Apr 5 16:07:44 2007 -0400
+
+    USB: remove unneeded WARN_ON
+    
+    This patch (as883) removes an out-of-date WARN_ON from the main HCD
+    endpoint-disable routine.  The warning is triggered whenever an
+    endpoint is disabled while the root hub is suspended.  In the past
+    that may not have been legal, but it definitely is legal now.  Merely
+    unbinding a USB driver will do it.
+    
+    Furthermore, I've never seen any occurrences of this warning that
+    really did signal an actual bug or error condition.  At this point it
+    has outlived its purpose.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: David Brownell 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 40cf882293e6..9ad2970a095d 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1175,10 +1175,6 @@ void usb_hcd_endpoint_disable (struct usb_device *udev,
+ 	struct urb		*urb;
+ 
+ 	hcd = bus_to_hcd(udev->bus);
+-
+-	WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT &&
+-			udev->state != USB_STATE_NOTATTACHED);
+-
+ 	local_irq_disable ();
+ 
+ 	/* ep is already gone from udev->ep_{in,out}[]; no more submits */

commit ef7f6c7084b333c7524dcd297e0578d43733a2a2
+Author: Alan Stern 
+Date:   Thu Apr 5 16:03:49 2007 -0400
+
+    USB: more autosuspend timer stuff
+    
+    This patch (as879) ties up some loose ends from an earlier patch.
+    These are things I didn't think to include at the time but which
+    clearly belonged there.
+    
+            If an autosuspend fails because driver activity races with
+            the autosuspend call, restart the autosuspend timer.
+    
+            When a device is resumed by an external request, it counts
+            as device activity and should update the last_busy time so
+            that the next autoresume won't occur immediately.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index b9f7f90aef82..2619986e5300 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -983,7 +983,10 @@ static int autosuspend_check(struct usb_device *udev)
+ 
+ #else
+ 
+-#define autosuspend_check(udev)		0
++static inline int autosuspend_check(struct usb_device *udev)
++{
++	return 0;
++}
+ 
+ #endif	/* CONFIG_USB_SUSPEND */
+ 
+@@ -1041,7 +1044,6 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 		if (status < 0)
+ 			goto done;
+ 	}
+-	cancel_delayed_work(&udev->autosuspend);
+ 
+ 	/* Suspend all the interfaces and then udev itself */
+ 	if (udev->actconfig) {
+@@ -1062,9 +1064,16 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 			usb_resume_interface(intf);
+ 		}
+ 
++		/* Try another autosuspend when the interfaces aren't busy */
++		if (udev->auto_pm)
++			autosuspend_check(udev);
++
+ 	/* If the suspend succeeded, propagate it up the tree */
+-	} else if (parent)
+-		usb_autosuspend_device(parent);
++	} else {
++		cancel_delayed_work(&udev->autosuspend);
++		if (parent)
++			usb_autosuspend_device(parent);
++	}
+ 
+  done:
+ 	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+@@ -1475,6 +1484,7 @@ int usb_external_resume_device(struct usb_device *udev)
+ 	usb_pm_lock(udev);
+ 	udev->auto_pm = 0;
+ 	status = usb_resume_both(udev);
++	udev->last_busy = jiffies;
+ 	usb_pm_unlock(udev);
+ 
+ 	/* Now that the device is awake, we can start trying to autosuspend

commit 4fe5354f61cad4c0550285283c83c66c070c198e
+Author: Alan Stern 
+Date:   Thu Apr 5 16:06:53 2007 -0400
+
+    EHCI: fix problem with BIOS handoff
+    
+    This patch (as882) fixes a problem with the EHCI BIOS handoff.  On my
+    machine, the BIOS configures the controller and the handoff fails,
+    leaving the controller configured.  During resume-from-disk, this
+    confuses ehci-hcd into thinking that the controller has not been
+    tampered with.
+    
+    The problem is fixed by turning off the Configured Flag whenever a
+    BIOS handoff is attempted, whether it succeeds or not.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
+index 20861650905e..c225159ca3d3 100644
+--- a/drivers/usb/host/pci-quirks.c
++++ b/drivers/usb/host/pci-quirks.c
+@@ -44,6 +44,7 @@
+ #define EHCI_USBSTS		4		/* status register */
+ #define EHCI_USBSTS_HALTED	(1 << 12)	/* HCHalted bit */
+ #define EHCI_USBINTR		8		/* interrupt register */
++#define EHCI_CONFIGFLAG		0x40		/* configured flag register */
+ #define EHCI_USBLEGSUP		0		/* legacy support register */
+ #define EHCI_USBLEGSUP_BIOS	(1 << 16)	/* BIOS semaphore */
+ #define EHCI_USBLEGSUP_OS	(1 << 24)	/* OS semaphore */
+@@ -216,6 +217,7 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
+ 	u32	hcc_params, val;
+ 	u8	offset, cap_length;
+ 	int	count = 256/4;
++	int	tried_handoff = 0;
+ 
+ 	if (!mmio_resource_enabled(pdev, 0))
+ 		return;
+@@ -273,6 +275,7 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
+ 			 */
+ 			msec = 5000;
+ 			while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) {
++				tried_handoff = 1;
+ 				msleep(10);
+ 				msec -= 10;
+ 				pci_read_config_dword(pdev, offset, &cap);
+@@ -292,6 +295,12 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
+ 			pci_write_config_dword(pdev,
+ 					offset + EHCI_USBLEGCTLSTS,
+ 					0);
++
++			/* If the BIOS ever owned the controller then we
++			 * can't expect any power sessions to remain intact.
++			 */
++			if (tried_handoff)
++				writel(0, op_reg_base + EHCI_CONFIGFLAG);
+ 			break;
+ 		case 0:			/* illegal reserved capability */
+ 			cap = 0;

commit 09ff92fea2890c697a36d8b26f5a3ea725ef8fb4
+Author: Alan Stern 
+Date:   Mon May 21 09:55:04 2007 -0400
+
+    [SCSI] sd: fix refcounting regression in suspend/resume routines
+    
+    This patch (as909) fixes a couple of refcounting errors in the sd
+    driver's suspend and resume methods.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+index 00e46662296f..3d8c9cb24f91 100644
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -1789,7 +1789,7 @@ static void sd_shutdown(struct device *dev)
+ static int sd_suspend(struct device *dev, pm_message_t mesg)
+ {
+ 	struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
+-	int ret;
++	int ret = 0;
+ 
+ 	if (!sdkp)
+ 		return 0;	/* this can happen */
+@@ -1798,30 +1798,34 @@ static int sd_suspend(struct device *dev, pm_message_t mesg)
+ 		sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
+ 		ret = sd_sync_cache(sdkp);
+ 		if (ret)
+-			return ret;
++			goto done;
+ 	}
+ 
+ 	if (mesg.event == PM_EVENT_SUSPEND &&
+ 	    sdkp->device->manage_start_stop) {
+ 		sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
+ 		ret = sd_start_stop_device(sdkp, 0);
+-		if (ret)
+-			return ret;
+ 	}
+ 
+-	return 0;
++done:
++	scsi_disk_put(sdkp);
++	return ret;
+ }
+ 
+ static int sd_resume(struct device *dev)
+ {
+ 	struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
++	int ret = 0;
+ 
+ 	if (!sdkp->device->manage_start_stop)
+-		return 0;
++		goto done;
+ 
+ 	sd_printk(KERN_NOTICE, sdkp, "Starting disk\n");
++	ret = sd_start_stop_device(sdkp, 1);
+ 
+-	return sd_start_stop_device(sdkp, 1);
++done:
++	scsi_disk_put(sdkp);
++	return ret;
+ }
+ 
+ /**

commit 83f7d958eab2fbc6b159ee92bf1493924e1d0f72
+Author: Alan Stern 
+Date:   Wed Apr 25 15:15:43 2007 -0400
+
+    USB: add "busnum" attribute for USB devices
+    
+    This patch (as903) adds a "busnum" sysfs attribute for USB devices.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 2ea47a38aefa..e7c982377488 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -117,6 +117,16 @@ show_speed(struct device *dev, struct device_attribute *attr, char *buf)
+ }
+ static DEVICE_ATTR(speed, S_IRUGO, show_speed, NULL);
+ 
++static ssize_t
++show_busnum(struct device *dev, struct device_attribute *attr, char *buf)
++{
++	struct usb_device *udev;
++
++	udev = to_usb_device(dev);
++	return sprintf(buf, "%d\n", udev->bus->busnum);
++}
++static DEVICE_ATTR(busnum, S_IRUGO, show_busnum, NULL);
++
+ static ssize_t
+ show_devnum(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+@@ -347,6 +357,7 @@ static struct attribute *dev_attrs[] = {
+ 	&dev_attr_bNumConfigurations.attr,
+ 	&dev_attr_bMaxPacketSize0.attr,
+ 	&dev_attr_speed.attr,
++	&dev_attr_busnum.attr,
+ 	&dev_attr_devnum.attr,
+ 	&dev_attr_version.attr,
+ 	&dev_attr_maxchild.attr,

commit 8c9862e512f59ae3f41f83c109be12f93e37bb2d
+Author: Alan Stern 
+Date:   Wed Apr 11 12:06:16 2007 -0400
+
+    USB: fix signed jiffies issue in autosuspend logic
+    
+    This patch (as897) changes the autosuspend timer code to use the
+    standard types and macros in dealing with jiffies values.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 631f30582481..b9f7f90aef82 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -932,7 +932,7 @@ static int autosuspend_check(struct usb_device *udev)
+ {
+ 	int			i;
+ 	struct usb_interface	*intf;
+-	long			suspend_time;
++	unsigned long		suspend_time;
+ 
+ 	/* For autosuspend, fail fast if anything is in use or autosuspend
+ 	 * is disabled.  Also fail if any interfaces require remote wakeup
+@@ -964,11 +964,18 @@ static int autosuspend_check(struct usb_device *udev)
+ 	/* If everything is okay but the device hasn't been idle for long
+ 	 * enough, queue a delayed autosuspend request.
+ 	 */
+-	suspend_time -= jiffies;
+-	if (suspend_time > 0) {
+-		if (!timer_pending(&udev->autosuspend.timer))
++	if (time_after(suspend_time, jiffies)) {
++		if (!timer_pending(&udev->autosuspend.timer)) {
++
++			/* The value of jiffies may change between the
++			 * time_after() comparison above and the subtraction
++			 * below.  That's okay; the system behaves sanely
++			 * when a timer is registered for the present moment
++			 * or for the past.
++			 */
+ 			queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+-					suspend_time);
++					suspend_time - jiffies);
++			}
+ 		return -EAGAIN;
+ 	}
+ 	return 0;

commit 1941044aa9632aa8debbb94a3c8a5ed0ebddade8
+Author: Alan Stern 
+Date:   Tue Mar 27 13:33:59 2007 -0400
+
+    USB: add "last_busy" field for use in autosuspend
+    
+    This patch (as877) adds a "last_busy" field to struct usb_device, for
+    use by the autosuspend framework.  Now if an autosuspend call comes at
+    a time when the device isn't busy but hasn't yet been idle for long
+    enough, the timer can be set to exactly the desired value.  And we
+    will be ready to handle things like HID drivers, which can't maintain
+    a useful usage count and must rely on the time-of-last-use to decide
+    when to autosuspend.
+    
+    The patch also makes some related minor improvements:
+    
+            Move the calls to the autosuspend condition-checking routine
+            into usb_suspend_both(), which is the only place where it
+            really matters.
+    
+            If the autosuspend timer is already running, don't stop
+            and restart it.
+    
+            Replace immediate returns with gotos so that the optional
+            debugging ouput won't be bypassed.
+    
+            If autoresume is disabled but the device is already awake,
+            don't return an error for an autoresume call.
+    
+            Don't try to autoresume a device if it isn't suspended.
+            (Yes, this undercuts the previous change -- so sue me.)
+    
+            Don't duplicate existing code in the autosuspend work routine.
+    
+            Fix the kerneldoc in usb_autopm_put_interface(): If an
+            autoresume call fails, the usage counter is left unchanged.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 593386eb974d..631f30582481 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -932,6 +932,7 @@ static int autosuspend_check(struct usb_device *udev)
+ {
+ 	int			i;
+ 	struct usb_interface	*intf;
++	long			suspend_time;
+ 
+ 	/* For autosuspend, fail fast if anything is in use or autosuspend
+ 	 * is disabled.  Also fail if any interfaces require remote wakeup
+@@ -943,6 +944,7 @@ static int autosuspend_check(struct usb_device *udev)
+ 	if (udev->autosuspend_delay < 0 || udev->autosuspend_disabled)
+ 		return -EPERM;
+ 
++	suspend_time = udev->last_busy + udev->autosuspend_delay;
+ 	if (udev->actconfig) {
+ 		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+ 			intf = udev->actconfig->interface[i];
+@@ -958,6 +960,17 @@ static int autosuspend_check(struct usb_device *udev)
+ 			}
+ 		}
+ 	}
++
++	/* If everything is okay but the device hasn't been idle for long
++	 * enough, queue a delayed autosuspend request.
++	 */
++	suspend_time -= jiffies;
++	if (suspend_time > 0) {
++		if (!timer_pending(&udev->autosuspend.timer))
++			queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
++					suspend_time);
++		return -EAGAIN;
++	}
+ 	return 0;
+ }
+ 
+@@ -1010,19 +1023,18 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 	struct usb_interface	*intf;
+ 	struct usb_device	*parent = udev->parent;
+ 
+-	cancel_delayed_work(&udev->autosuspend);
+-	if (udev->state == USB_STATE_NOTATTACHED)
+-		return 0;
+-	if (udev->state == USB_STATE_SUSPENDED)
+-		return 0;
++	if (udev->state == USB_STATE_NOTATTACHED ||
++			udev->state == USB_STATE_SUSPENDED)
++		goto done;
+ 
+ 	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
+ 
+ 	if (udev->auto_pm) {
+ 		status = autosuspend_check(udev);
+ 		if (status < 0)
+-			return status;
++			goto done;
+ 	}
++	cancel_delayed_work(&udev->autosuspend);
+ 
+ 	/* Suspend all the interfaces and then udev itself */
+ 	if (udev->actconfig) {
+@@ -1047,6 +1059,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 	} else if (parent)
+ 		usb_autosuspend_device(parent);
+ 
++ done:
+ 	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+ 	return status;
+ }
+@@ -1086,14 +1099,18 @@ static int usb_resume_both(struct usb_device *udev)
+ 	struct usb_interface	*intf;
+ 	struct usb_device	*parent = udev->parent;
+ 
+-	if (udev->auto_pm && udev->autoresume_disabled)
+-		return -EPERM;
+ 	cancel_delayed_work(&udev->autosuspend);
+-	if (udev->state == USB_STATE_NOTATTACHED)
+-		return -ENODEV;
++	if (udev->state == USB_STATE_NOTATTACHED) {
++		status = -ENODEV;
++		goto done;
++	}
+ 
+ 	/* Propagate the resume up the tree, if necessary */
+ 	if (udev->state == USB_STATE_SUSPENDED) {
++		if (udev->auto_pm && udev->autoresume_disabled) {
++			status = -EPERM;
++			goto done;
++		}
+ 		if (parent) {
+ 			status = usb_autoresume_device(parent);
+ 			if (status == 0) {
+@@ -1139,24 +1156,13 @@ static int usb_resume_both(struct usb_device *udev)
+ 		}
+ 	}
+ 
++ done:
+ 	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+ 	return status;
+ }
+ 
+ #ifdef CONFIG_USB_SUSPEND
+ 
+-/* usb_autosuspend_work - callback routine to autosuspend a USB device */
+-void usb_autosuspend_work(struct work_struct *work)
+-{
+-	struct usb_device *udev =
+-		container_of(work, struct usb_device, autosuspend.work);
+-
+-	usb_pm_lock(udev);
+-	udev->auto_pm = 1;
+-	usb_suspend_both(udev, PMSG_SUSPEND);
+-	usb_pm_unlock(udev);
+-}
+-
+ /* Internal routine to adjust a device's usage counter and change
+  * its autosuspend state.
+  */
+@@ -1165,20 +1171,34 @@ static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt)
+ 	int	status = 0;
+ 
+ 	usb_pm_lock(udev);
++	udev->auto_pm = 1;
+ 	udev->pm_usage_cnt += inc_usage_cnt;
+ 	WARN_ON(udev->pm_usage_cnt < 0);
+ 	if (inc_usage_cnt >= 0 && udev->pm_usage_cnt > 0) {
+-		udev->auto_pm = 1;
+-		status = usb_resume_both(udev);
++		if (udev->state == USB_STATE_SUSPENDED)
++			status = usb_resume_both(udev);
+ 		if (status != 0)
+ 			udev->pm_usage_cnt -= inc_usage_cnt;
+-	} else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
+-		queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+-				udev->autosuspend_delay);
++		else if (inc_usage_cnt)
++			udev->last_busy = jiffies;
++	} else if (inc_usage_cnt <= 0 && udev->pm_usage_cnt <= 0) {
++		if (inc_usage_cnt)
++			udev->last_busy = jiffies;
++		status = usb_suspend_both(udev, PMSG_SUSPEND);
++	}
+ 	usb_pm_unlock(udev);
+ 	return status;
+ }
+ 
++/* usb_autosuspend_work - callback routine to autosuspend a USB device */
++void usb_autosuspend_work(struct work_struct *work)
++{
++	struct usb_device *udev =
++		container_of(work, struct usb_device, autosuspend.work);
++
++	usb_autopm_do_device(udev, 0);
++}
++
+ /**
+  * usb_autosuspend_device - delayed autosuspend of a USB device and its interfaces
+  * @udev: the usb_device to autosuspend
+@@ -1270,15 +1290,20 @@ static int usb_autopm_do_interface(struct usb_interface *intf,
+ 	if (intf->condition == USB_INTERFACE_UNBOUND)
+ 		status = -ENODEV;
+ 	else {
++		udev->auto_pm = 1;
+ 		intf->pm_usage_cnt += inc_usage_cnt;
+ 		if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) {
+-			udev->auto_pm = 1;
+-			status = usb_resume_both(udev);
++			if (udev->state == USB_STATE_SUSPENDED)
++				status = usb_resume_both(udev);
+ 			if (status != 0)
+ 				intf->pm_usage_cnt -= inc_usage_cnt;
+-		} else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
+-			queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+-					udev->autosuspend_delay);
++			else if (inc_usage_cnt)
++				udev->last_busy = jiffies;
++		} else if (inc_usage_cnt <= 0 && intf->pm_usage_cnt <= 0) {
++			if (inc_usage_cnt)
++				udev->last_busy = jiffies;
++			status = usb_suspend_both(udev, PMSG_SUSPEND);
++		}
+ 	}
+ 	usb_pm_unlock(udev);
+ 	return status;
+@@ -1337,11 +1362,14 @@ EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
+  * or @intf is unbound.  A typical example would be a character-device
+  * driver when its device file is opened.
+  *
+- * The routine increments @intf's usage counter.  So long as the counter
+- * is greater than 0, autosuspend will not be allowed for @intf or its
+- * usb_device.  When the driver is finished using @intf it should call
+- * usb_autopm_put_interface() to decrement the usage counter and queue
+- * a delayed autosuspend request (if the counter is <= 0).
++ *
++ * The routine increments @intf's usage counter.  (However if the
++ * autoresume fails then the counter is re-decremented.)  So long as the
++ * counter is greater than 0, autosuspend will not be allowed for @intf
++ * or its usb_device.  When the driver is finished using @intf it should
++ * call usb_autopm_put_interface() to decrement the usage counter and
++ * queue a delayed autosuspend request (if the counter is <= 0).
++ *
+  *
+  * Note that @intf->pm_usage_cnt is owned by the interface driver.  The
+  * core will not change its value other than the increment and decrement
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 8bc3ce6d9666..40cf882293e6 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1306,6 +1306,7 @@ static void hcd_resume_work(struct work_struct *work)
+ 	struct usb_device *udev = hcd->self.root_hub;
+ 
+ 	usb_lock_device(udev);
++	usb_mark_last_busy(udev);
+ 	usb_external_resume_device(udev);
+ 	usb_unlock_device(udev);
+ }
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 2a0b15e42bc7..bde29ab2b504 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1859,6 +1859,7 @@ static int remote_wakeup(struct usb_device *udev)
+ 	usb_lock_device(udev);
+ 	if (udev->state == USB_STATE_SUSPENDED) {
+ 		dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-");
++		usb_mark_last_busy(udev);
+ 		status = usb_external_resume_device(udev);
+ 	}
+ 	usb_unlock_device(udev);
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index f9e4445d5b53..cfbd2bb8fa2c 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -398,6 +398,7 @@ struct usb_device {
+ 	struct delayed_work autosuspend; /* for delayed autosuspends */
+ 	struct mutex pm_mutex;		/* protects PM operations */
+ 
++	unsigned long last_busy;	/* time of last use */
+ 	int autosuspend_delay;		/* in jiffies */
+ 
+ 	unsigned auto_pm:1;		/* autosuspend/resume in progress */
+@@ -443,6 +444,11 @@ static inline void usb_autopm_disable(struct usb_interface *intf)
+ 	usb_autopm_set_interface(intf);
+ }
+ 
++static inline void usb_mark_last_busy(struct usb_device *udev)
++{
++	udev->last_busy = jiffies;
++}
++
+ #else
+ 
+ static inline int usb_autopm_set_interface(struct usb_interface *intf)
+@@ -457,6 +463,8 @@ static inline void usb_autopm_enable(struct usb_interface *intf)
+ { }
+ static inline void usb_autopm_disable(struct usb_interface *intf)
+ { }
++static inline void usb_mark_last_busy(struct usb_device *udev)
++{ }
+ #endif
+ 
+ /*-------------------------------------------------------------------------*/

commit 2add5229d77a3de08015feef437653e02372162f
+Author: Alan Stern 
+Date:   Tue Mar 20 14:59:39 2007 -0400
+
+    USB: add power/level sysfs attribute
+    
+    This patch (as874) adds another piece to the user-visible part of the
+    USB autosuspend interface.  The new power/level sysfs attribute allows
+    users to force the device on (with autosuspend off), force the device
+    to sleep (with autoresume off), or return to normal automatic operation.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb
+index 00a84326325f..f9937add033d 100644
+--- a/Documentation/ABI/testing/sysfs-bus-usb
++++ b/Documentation/ABI/testing/sysfs-bus-usb
+@@ -13,3 +13,29 @@ Description:
+ 
+ 		The autosuspend delay for newly-created devices is set to
+ 		the value of the usbcore.autosuspend module parameter.
++
++What:		/sys/bus/usb/devices/.../power/level
++Date:		March 2007
++KernelVersion:	2.6.21
++Contact:	Alan Stern 
++Description:
++		Each USB device directory will contain a file named
++		power/level.  This file holds a power-level setting for
++		the device, one of "on", "auto", or "suspend".
++
++		"on" means that the device is not allowed to autosuspend,
++		although normal suspends for system sleep will still
++		be honored.  "auto" means the device will autosuspend
++		and autoresume in the usual manner, according to the
++		capabilities of its driver.  "suspend" means the device
++		is forced into a suspended state and it will not autoresume
++		in response to I/O requests.  However remote-wakeup requests
++		from the device may still be enabled (the remote-wakeup
++		setting is controlled separately by the power/wakeup
++		attribute).
++
++		During normal use, devices should be left in the "auto"
++		level.  The other levels are meant for administrative uses.
++		If you want to suspend a device immediately but leave it
++		free to wake up in response to I/O requests, you should
++		write "0" to power/autosuspend.
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 884179f1e163..9b6a60fafddb 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -872,8 +872,10 @@ static int usb_resume_device(struct usb_device *udev)
+ 
+ done:
+ 	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+-	if (status == 0)
++	if (status == 0) {
++		udev->autoresume_disabled = 0;
+ 		udev->dev.power.power_state.event = PM_EVENT_ON;
++	}
+ 	return status;
+ }
+ 
+@@ -970,7 +972,7 @@ static int autosuspend_check(struct usb_device *udev)
+ 	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
+ 	if (udev->pm_usage_cnt > 0)
+ 		return -EBUSY;
+-	if (udev->autosuspend_delay < 0)
++	if (udev->autosuspend_delay < 0 || udev->autosuspend_disabled)
+ 		return -EPERM;
+ 
+ 	if (udev->actconfig) {
+@@ -1116,6 +1118,8 @@ static int usb_resume_both(struct usb_device *udev)
+ 	struct usb_interface	*intf;
+ 	struct usb_device	*parent = udev->parent;
+ 
++	if (udev->auto_pm && udev->autoresume_disabled)
++		return -EPERM;
+ 	cancel_delayed_work(&udev->autosuspend);
+ 	if (udev->state == USB_STATE_NOTATTACHED)
+ 		return -ENODEV;
+@@ -1486,9 +1490,14 @@ static int usb_suspend(struct device *dev, pm_message_t message)
+ 
+ static int usb_resume(struct device *dev)
+ {
++	struct usb_device	*udev;
++
+ 	if (!is_usb_device(dev))	/* Ignore PM for interfaces */
+ 		return 0;
+-	return usb_external_resume_device(to_usb_device(dev));
++	udev = to_usb_device(dev);
++	if (udev->autoresume_disabled)
++		return -EPERM;
++	return usb_external_resume_device(udev);
+ }
+ 
+ #else
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index f08ec85a6d64..739f520908aa 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -42,7 +42,7 @@ static void usb_autosuspend_quirk(struct usb_device *udev)
+ {
+ #ifdef	CONFIG_USB_SUSPEND
+ 	/* disable autosuspend, but allow the user to re-enable it via sysfs */
+-	udev->autosuspend_delay = 0;
++	udev->autosuspend_disabled = 1;
+ #endif
+ }
+ 
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 731001f7d2c1..2ea47a38aefa 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -11,6 +11,7 @@
+ 
+ 
+ #include 
++#include 
+ #include 
+ #include "usb.h"
+ 
+@@ -184,9 +185,8 @@ set_autosuspend(struct device *dev, struct device_attribute *attr,
+ 	if (value >= 0)
+ 		usb_try_autosuspend_device(udev);
+ 	else {
+-		usb_lock_device(udev);
+-		usb_external_resume_device(udev);
+-		usb_unlock_device(udev);
++		if (usb_autoresume_device(udev) == 0)
++			usb_autosuspend_device(udev);
+ 	}
+ 	return count;
+ }
+@@ -194,21 +194,94 @@ set_autosuspend(struct device *dev, struct device_attribute *attr,
+ static DEVICE_ATTR(autosuspend, S_IRUGO | S_IWUSR,
+ 		show_autosuspend, set_autosuspend);
+ 
++static const char on_string[] = "on";
++static const char auto_string[] = "auto";
++static const char suspend_string[] = "suspend";
++
++static ssize_t
++show_level(struct device *dev, struct device_attribute *attr, char *buf)
++{
++	struct usb_device *udev = to_usb_device(dev);
++	const char *p = auto_string;
++
++	if (udev->state == USB_STATE_SUSPENDED) {
++		if (udev->autoresume_disabled)
++			p = suspend_string;
++	} else {
++		if (udev->autosuspend_disabled)
++			p = on_string;
++	}
++	return sprintf(buf, "%s\n", p);
++}
++
++static ssize_t
++set_level(struct device *dev, struct device_attribute *attr,
++		const char *buf, size_t count)
++{
++	struct usb_device *udev = to_usb_device(dev);
++	int len = count;
++	char *cp;
++	int rc = 0;
++
++	cp = memchr(buf, '\n', count);
++	if (cp)
++		len = cp - buf;
++
++	usb_lock_device(udev);
++
++	/* Setting the flags without calling usb_pm_lock is a subject to
++	 * races, but who cares...
++	 */
++	if (len == sizeof on_string - 1 &&
++			strncmp(buf, on_string, len) == 0) {
++		udev->autosuspend_disabled = 1;
++		udev->autoresume_disabled = 0;
++		rc = usb_external_resume_device(udev);
++
++	} else if (len == sizeof auto_string - 1 &&
++			strncmp(buf, auto_string, len) == 0) {
++		udev->autosuspend_disabled = 0;
++		udev->autoresume_disabled = 0;
++		rc = usb_external_resume_device(udev);
++
++	} else if (len == sizeof suspend_string - 1 &&
++			strncmp(buf, suspend_string, len) == 0) {
++		udev->autosuspend_disabled = 0;
++		udev->autoresume_disabled = 1;
++		rc = usb_external_suspend_device(udev, PMSG_SUSPEND);
++
++	} else
++		rc = -EINVAL;
++
++	usb_unlock_device(udev);
++	return (rc < 0 ? rc : count);
++}
++
++static DEVICE_ATTR(level, S_IRUGO | S_IWUSR, show_level, set_level);
++
+ static char power_group[] = "power";
+ 
+ static int add_power_attributes(struct device *dev)
+ {
+ 	int rc = 0;
+ 
+-	if (is_usb_device(dev))
++	if (is_usb_device(dev)) {
+ 		rc = sysfs_add_file_to_group(&dev->kobj,
+ 				&dev_attr_autosuspend.attr,
+ 				power_group);
++		if (rc == 0)
++			rc = sysfs_add_file_to_group(&dev->kobj,
++					&dev_attr_level.attr,
++					power_group);
++	}
+ 	return rc;
+ }
+ 
+ static void remove_power_attributes(struct device *dev)
+ {
++	sysfs_remove_file_from_group(&dev->kobj,
++			&dev_attr_level.attr,
++			power_group);
+ 	sysfs_remove_file_from_group(&dev->kobj,
+ 			&dev_attr_autosuspend.attr,
+ 			power_group);
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index cc24d089faa0..5e8e144afbae 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -398,6 +398,8 @@ struct usb_device {
+ 
+ 	unsigned auto_pm:1;		/* autosuspend/resume in progress */
+ 	unsigned do_remote_wakeup:1;	/* remote wakeup should be enabled */
++	unsigned autosuspend_disabled:1; /* autosuspend and autoresume */
++	unsigned autoresume_disabled:1;  /*  disabled by the user */
+ #endif
+ };
+ #define	to_usb_device(d) container_of(d, struct usb_device, dev)

commit 0cef7727c953056bb3ef9852a79d9658a1d8df4e
+Author: Alan Stern 
+Date:   Mon Mar 19 15:33:11 2007 -0400
+
+    UHCI: Add some WARN_ON()s
+    
+    This patch (as872) adds some WARN_ON()s to various error checks which
+    are never supposed to fail.  Unsettlingly, one of them has shown up in
+    a user's log!  Maybe making the warning more visible and having the
+    call-stack information available will help pinpoint the source of the
+    problem.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 19a0cc02b9a2..4aed305982ec 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -123,10 +123,14 @@ static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci)
+ 
+ static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td)
+ {
+-	if (!list_empty(&td->list))
++	if (!list_empty(&td->list)) {
+ 		dev_warn(uhci_dev(uhci), "td %p still in list!\n", td);
+-	if (!list_empty(&td->fl_list))
++		WARN_ON(1);
++	}
++	if (!list_empty(&td->fl_list)) {
+ 		dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td);
++		WARN_ON(1);
++	}
+ 
+ 	dma_pool_free(uhci->td_pool, td, td->dma_handle);
+ }
+@@ -291,8 +295,10 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci,
+ static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ {
+ 	WARN_ON(qh->state != QH_STATE_IDLE && qh->udev);
+-	if (!list_empty(&qh->queue))
++	if (!list_empty(&qh->queue)) {
+ 		dev_warn(uhci_dev(uhci), "qh %p list not empty!\n", qh);
++		WARN_ON(1);
++	}
+ 
+ 	list_del(&qh->node);
+ 	if (qh->udev) {
+@@ -740,9 +746,11 @@ static void uhci_free_urb_priv(struct uhci_hcd *uhci,
+ {
+ 	struct uhci_td *td, *tmp;
+ 
+-	if (!list_empty(&urbp->node))
++	if (!list_empty(&urbp->node)) {
+ 		dev_warn(uhci_dev(uhci), "urb %p still on QH's list!\n",
+ 				urbp->urb);
++		WARN_ON(1);
++	}
+ 
+ 	list_for_each_entry_safe(td, tmp, &urbp->td_list, list) {
+ 		uhci_remove_td_from_urbp(td);

commit e198a31489146bb723fef179e5d1d18c8225f246
+Author: Alan Stern 
+Date:   Thu Mar 15 15:54:30 2007 -0400
+
+    EHCI: add delay to bus_resume before accessing ports
+    
+    This patch (as870) adds a delay to ehci-hcd's bus_resume routine.
+    Apparently there are controllers and/or BIOSes out there which need
+    such a delay to get the ports back into their correct state.  This
+    fixes Bugzilla #8190.
+    
+    Signed-off-by: Alan Stern 
+    Cc: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 1813b7cac294..f4d301bc83b9 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -136,6 +136,10 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 	/* restore CMD_RUN, framelist size, and irq threshold */
+ 	ehci_writel(ehci, ehci->command, &ehci->regs->command);
+ 
++	/* Some controller/firmware combinations need a delay during which
++	 * they set up the port statuses.  See Bugzilla #8190. */
++	mdelay(8);
++
+ 	/* manually resume the ports we suspended during bus_suspend() */
+ 	i = HCS_N_PORTS (ehci->hcs_params);
+ 	while (i--) {

commit eaafbc3a8adab16babe2c20e54ad3ba40d1fbbc9
+Author: Alan Stern 
+Date:   Tue Mar 13 16:39:15 2007 -0400
+
+    USB: Allow autosuspend delay to equal 0
+    
+    This patch (as867) adds an entry for the new power/autosuspend
+    attribute in Documentation/ABI/testing, and it changes the behavior of
+    the delay value.  Now a delay of 0 means to autosuspend as soon as
+    possible, and negative values will prevent autosuspend.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb
+new file mode 100644
+index 000000000000..00a84326325f
+--- /dev/null
++++ b/Documentation/ABI/testing/sysfs-bus-usb
+@@ -0,0 +1,15 @@
++What:		/sys/bus/usb/devices/.../power/autosuspend
++Date:		March 2007
++KernelVersion:	2.6.21
++Contact:	Alan Stern 
++Description:
++		Each USB device directory will contain a file named
++		power/autosuspend.  This file holds the time (in seconds)
++		the device must be idle before it will be autosuspended.
++		0 means the device will be autosuspended as soon as
++		possible.  Negative values will prevent the device from
++		being autosuspended at all, and writing a negative value
++		will resume the device if it is already suspended.
++
++		The autosuspend delay for newly-created devices is set to
++		the value of the usbcore.autosuspend module parameter.
+diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
+index 12533a958c51..2017942e0966 100644
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -1792,7 +1792,7 @@ and is between 256 and 4096 characters. It is defined in the file
+ 			for newly-detected USB devices (default 2).  This
+ 			is the time required before an idle device will be
+ 			autosuspended.  Devices for which the delay is set
+-			to 0 won't be autosuspended at all.
++			to a negative value won't be autosuspended at all.
+ 
+ 	usbhid.mousepoll=
+ 			[USBHID] The interval which mice are to be polled at.
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index abea48de8766..884179f1e163 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -970,7 +970,7 @@ static int autosuspend_check(struct usb_device *udev)
+ 	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
+ 	if (udev->pm_usage_cnt > 0)
+ 		return -EBUSY;
+-	if (!udev->autosuspend_delay)
++	if (udev->autosuspend_delay < 0)
+ 		return -EPERM;
+ 
+ 	if (udev->actconfig) {
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 311d5df80386..731001f7d2c1 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -165,7 +165,7 @@ show_autosuspend(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+ 	struct usb_device *udev = to_usb_device(dev);
+ 
+-	return sprintf(buf, "%u\n", udev->autosuspend_delay / HZ);
++	return sprintf(buf, "%d\n", udev->autosuspend_delay / HZ);
+ }
+ 
+ static ssize_t
+@@ -173,17 +173,21 @@ set_autosuspend(struct device *dev, struct device_attribute *attr,
+ 		const char *buf, size_t count)
+ {
+ 	struct usb_device *udev = to_usb_device(dev);
+-	unsigned value, old;
++	int value;
+ 
+-	if (sscanf(buf, "%u", &value) != 1 || value >= INT_MAX/HZ)
++	if (sscanf(buf, "%d", &value) != 1 || value >= INT_MAX/HZ ||
++			value <= - INT_MAX/HZ)
+ 		return -EINVAL;
+ 	value *= HZ;
+ 
+-	old = udev->autosuspend_delay;
+ 	udev->autosuspend_delay = value;
+-	if (value > 0 && old == 0)
++	if (value >= 0)
+ 		usb_try_autosuspend_device(udev);
+-
++	else {
++		usb_lock_device(udev);
++		usb_external_resume_device(udev);
++		usb_unlock_device(udev);
++	}
+ 	return count;
+ }
+ 
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 138252e0a1cf..6f35dce8a95d 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -55,7 +55,7 @@ struct workqueue_struct *ksuspend_usb_wq;
+ #ifdef	CONFIG_USB_SUSPEND
+ static int usb_autosuspend_delay = 2;		/* Default delay value,
+ 						 * in seconds */
+-module_param_named(autosuspend, usb_autosuspend_delay, uint, 0644);
++module_param_named(autosuspend, usb_autosuspend_delay, int, 0644);
+ MODULE_PARM_DESC(autosuspend, "default autosuspend delay");
+ 
+ #else
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 87dc75a6cee1..cc24d089faa0 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -394,7 +394,7 @@ struct usb_device {
+ 	struct delayed_work autosuspend; /* for delayed autosuspends */
+ 	struct mutex pm_mutex;		/* protects PM operations */
+ 
+-	unsigned autosuspend_delay;	/* in jiffies */
++	int autosuspend_delay;		/* in jiffies */
+ 
+ 	unsigned auto_pm:1;		/* autosuspend/resume in progress */
+ 	unsigned do_remote_wakeup:1;	/* remote wakeup should be enabled */

commit 6b157c9bf3bace6eeb4a973da63923ef24995cce
+Author: Alan Stern 
+Date:   Tue Mar 13 16:37:30 2007 -0400
+
+    USB: separate autosuspend from external suspend
+    
+    This patch (as866) adds new entry points for external USB device
+    suspend and resume requests, as opposed to internally-generated
+    autosuspend or autoresume.  It also changes the existing
+    remote-wakeup code paths to use the new routines, since remote wakeup
+    is not the same as autoresume.
+    
+    As part of the change, it turns out to be necessary to do remote
+    wakeup of root hubs from a workqueue.  We had been using khubd, but it
+    does autoresume rather than an external resume.  Using the
+    ksuspend_usb_wq workqueue for this purpose seemed a logical choice.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 8c0a7de61228..abea48de8766 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1424,48 +1424,84 @@ void usb_autosuspend_work(struct work_struct *work)
+ 
+ #endif /* CONFIG_USB_SUSPEND */
+ 
+-static int usb_suspend(struct device *dev, pm_message_t message)
++/**
++ * usb_external_suspend_device - external suspend of a USB device and its interfaces
++ * @udev: the usb_device to suspend
++ * @msg: Power Management message describing this state transition
++ *
++ * This routine handles external suspend requests: ones not generated
++ * internally by a USB driver (autosuspend) but rather coming from the user
++ * (via sysfs) or the PM core (system sleep).  The suspend will be carried
++ * out regardless of @udev's usage counter or those of its interfaces,
++ * and regardless of whether or not remote wakeup is enabled.  Of course,
++ * interface drivers still have the option of failing the suspend (if
++ * there are unsuspended children, for example).
++ *
++ * The caller must hold @udev's device lock.
++ */
++int usb_external_suspend_device(struct usb_device *udev, pm_message_t msg)
+ {
+ 	int	status;
+ 
+-	if (is_usb_device(dev)) {
+-		struct usb_device *udev = to_usb_device(dev);
+-
+-		usb_pm_lock(udev);
+-		udev->auto_pm = 0;
+-		status = usb_suspend_both(udev, message);
+-		usb_pm_unlock(udev);
+-	} else
+-		status = 0;
++	usb_pm_lock(udev);
++	udev->auto_pm = 0;
++	status = usb_suspend_both(udev, msg);
++	usb_pm_unlock(udev);
+ 	return status;
+ }
+ 
+-static int usb_resume(struct device *dev)
++/**
++ * usb_external_resume_device - external resume of a USB device and its interfaces
++ * @udev: the usb_device to resume
++ *
++ * This routine handles external resume requests: ones not generated
++ * internally by a USB driver (autoresume) but rather coming from the user
++ * (via sysfs), the PM core (system resume), or the device itself (remote
++ * wakeup).  @udev's usage counter is unaffected.
++ *
++ * The caller must hold @udev's device lock.
++ */
++int usb_external_resume_device(struct usb_device *udev)
+ {
+ 	int	status;
+ 
+-	if (is_usb_device(dev)) {
+-		struct usb_device *udev = to_usb_device(dev);
+-
+-		usb_pm_lock(udev);
+-		udev->auto_pm = 0;
+-		status = usb_resume_both(udev);
+-		usb_pm_unlock(udev);
++	usb_pm_lock(udev);
++	udev->auto_pm = 0;
++	status = usb_resume_both(udev);
++	usb_pm_unlock(udev);
+ 
+-		/* Rebind drivers that had no suspend method? */
+-	} else
+-		status = 0;
++	/* Now that the device is awake, we can start trying to autosuspend
++	 * it again. */
++	if (status == 0)
++		usb_try_autosuspend_device(udev);
+ 	return status;
+ }
+ 
++static int usb_suspend(struct device *dev, pm_message_t message)
++{
++	if (!is_usb_device(dev))	/* Ignore PM for interfaces */
++		return 0;
++	return usb_external_suspend_device(to_usb_device(dev), message);
++}
++
++static int usb_resume(struct device *dev)
++{
++	if (!is_usb_device(dev))	/* Ignore PM for interfaces */
++		return 0;
++	return usb_external_resume_device(to_usb_device(dev));
++}
++
++#else
++
++#define usb_suspend	NULL
++#define usb_resume	NULL
++
+ #endif /* CONFIG_PM */
+ 
+ struct bus_type usb_bus_type = {
+ 	.name =		"usb",
+ 	.match =	usb_device_match,
+ 	.uevent =	usb_uevent,
+-#ifdef CONFIG_PM
+ 	.suspend =	usb_suspend,
+ 	.resume =	usb_resume,
+-#endif
+ };
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index af7aed11398b..8bc3ce6d9666 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -37,6 +37,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ 
+@@ -1298,14 +1299,25 @@ int hcd_bus_resume (struct usb_bus *bus)
+ 	return status;
+ }
+ 
++/* Workqueue routine for root-hub remote wakeup */
++static void hcd_resume_work(struct work_struct *work)
++{
++	struct usb_hcd *hcd = container_of(work, struct usb_hcd, wakeup_work);
++	struct usb_device *udev = hcd->self.root_hub;
++
++	usb_lock_device(udev);
++	usb_external_resume_device(udev);
++	usb_unlock_device(udev);
++}
++
+ /**
+  * usb_hcd_resume_root_hub - called by HCD to resume its root hub 
+  * @hcd: host controller for this root hub
+  *
+  * The USB host controller calls this function when its root hub is
+  * suspended (with the remote wakeup feature enabled) and a remote
+- * wakeup request is received.  It queues a request for khubd to
+- * resume the root hub (that is, manage its downstream ports again).
++ * wakeup request is received.  The routine submits a workqueue request
++ * to resume the root hub (that is, manage its downstream ports again).
+  */
+ void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
+ {
+@@ -1313,7 +1325,7 @@ void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
+ 
+ 	spin_lock_irqsave (&hcd_root_hub_lock, flags);
+ 	if (hcd->rh_registered)
+-		usb_resume_root_hub (hcd->self.root_hub);
++		queue_work(ksuspend_usb_wq, &hcd->wakeup_work);
+ 	spin_unlock_irqrestore (&hcd_root_hub_lock, flags);
+ }
+ EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub);
+@@ -1502,6 +1514,9 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
+ 	init_timer(&hcd->rh_timer);
+ 	hcd->rh_timer.function = rh_timer_func;
+ 	hcd->rh_timer.data = (unsigned long) hcd;
++#ifdef CONFIG_PM
++	INIT_WORK(&hcd->wakeup_work, hcd_resume_work);
++#endif
+ 
+ 	hcd->driver = driver;
+ 	hcd->product_desc = (driver->product_desc) ? driver->product_desc :
+@@ -1668,6 +1683,10 @@ void usb_remove_hcd(struct usb_hcd *hcd)
+ 	hcd->rh_registered = 0;
+ 	spin_unlock_irq (&hcd_root_hub_lock);
+ 
++#ifdef CONFIG_PM
++	flush_workqueue(ksuspend_usb_wq);
++#endif
++
+ 	mutex_lock(&usb_bus_list_lock);
+ 	usb_disconnect(&hcd->self.root_hub);
+ 	mutex_unlock(&usb_bus_list_lock);
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index 2a269ca20517..ef50fa494e47 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -68,6 +68,9 @@ struct usb_hcd {
+ 
+ 	struct timer_list	rh_timer;	/* drives root-hub polling */
+ 	struct urb		*status_urb;	/* the current status urb */
++#ifdef CONFIG_PM
++	struct work_struct	wakeup_work;	/* for remote wakeup */
++#endif
+ 
+ 	/*
+ 	 * hardware info/state
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 7a6028599d62..19abe81babd5 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1855,12 +1855,7 @@ static int remote_wakeup(struct usb_device *udev)
+ 	usb_lock_device(udev);
+ 	if (udev->state == USB_STATE_SUSPENDED) {
+ 		dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-");
+-		status = usb_autoresume_device(udev);
+-
+-		/* Give the interface drivers a chance to do something,
+-		 * then autosuspend the device again. */
+-		if (status == 0)
+-			usb_autosuspend_device(udev);
++		status = usb_external_resume_device(udev);
+ 	}
+ 	usb_unlock_device(udev);
+ 	return status;
+@@ -1984,13 +1979,6 @@ static inline int remote_wakeup(struct usb_device *udev)
+ #define hub_resume NULL
+ #endif
+ 
+-void usb_resume_root_hub(struct usb_device *hdev)
+-{
+-	struct usb_hub *hub = hdev_to_hub(hdev);
+-
+-	kick_khubd(hub);
+-}
+-
+ 
+ /* USB 2.0 spec, 7.1.7.3 / fig 7-29:
+  *
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 82338f497860..138252e0a1cf 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -49,7 +49,8 @@ const char *usbcore_name = "usbcore";
+ 
+ static int nousb;	/* Disable USB when built into kernel image */
+ 
+-struct workqueue_struct *ksuspend_usb_wq;	/* For autosuspend */
++/* Workqueue for autosuspend and for remote wakeup of root hubs */
++struct workqueue_struct *ksuspend_usb_wq;
+ 
+ #ifdef	CONFIG_USB_SUSPEND
+ static int usb_autosuspend_delay = 2;		/* Default delay value,
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index b98bc0d381c0..c94379e55f2d 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -21,7 +21,6 @@ extern char *usb_cache_string(struct usb_device *udev, int index);
+ extern int usb_set_configuration(struct usb_device *dev, int configuration);
+ 
+ extern void usb_kick_khubd(struct usb_device *dev);
+-extern void usb_resume_root_hub(struct usb_device *dev);
+ extern int usb_match_device(struct usb_device *dev,
+ 			    const struct usb_device_id *id);
+ 
+@@ -37,6 +36,9 @@ extern void usb_host_cleanup(void);
+ extern void usb_autosuspend_work(struct work_struct *work);
+ extern int usb_port_suspend(struct usb_device *dev);
+ extern int usb_port_resume(struct usb_device *dev);
++extern int usb_external_suspend_device(struct usb_device *udev,
++		pm_message_t msg);
++extern int usb_external_resume_device(struct usb_device *udev);
+ 
+ static inline void usb_pm_lock(struct usb_device *udev)
+ {

commit 1b42ae6d4355328dc4406b6f0188adcf8c566435
+Author: Alan Stern 
+Date:   Tue Mar 13 11:10:52 2007 -0400
+
+    USB: fix race in HCD removal
+    
+    This patch (as865) fixes a race in the HCD removal code discovered by
+    Milan Plzik.  Arrival of an interrupt after the root hub was
+    unregistered could cause the root-hub status timer to start up, even
+    after it was supposed to have been shut down.  The problem is fixed by
+    moving the del_timer_sync() call to after the HCD's stop() method, at
+    which time IRQ generation should be disabled.
+    
+    Cc: Milan Plzik 
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index b26c19e8d19f..af7aed11398b 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -544,6 +544,8 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
+ 	unsigned long	flags;
+ 	char		buffer[4];	/* Any root hubs with > 31 ports? */
+ 
++	if (unlikely(!hcd->rh_registered))
++		return;
+ 	if (!hcd->uses_new_polling && !hcd->status_urb)
+ 		return;
+ 
+@@ -1670,12 +1672,12 @@ void usb_remove_hcd(struct usb_hcd *hcd)
+ 	usb_disconnect(&hcd->self.root_hub);
+ 	mutex_unlock(&usb_bus_list_lock);
+ 
+-	hcd->poll_rh = 0;
+-	del_timer_sync(&hcd->rh_timer);
+-
+ 	hcd->driver->stop(hcd);
+ 	hcd->state = HC_STATE_HALT;
+ 
++	hcd->poll_rh = 0;
++	del_timer_sync(&hcd->rh_timer);
++
+ 	if (hcd->irq >= 0)
+ 		free_irq(hcd->irq, hcd);
+ 	usb_deregister_bus(&hcd->self);

commit 718efa64e30a5e9db0351d70c5a91969306a12d1
+Author: Alan Stern 
+Date:   Fri Mar 9 15:41:13 2007 -0500
+
+    usbcore: move usb_autosuspend_work
+    
+    This patch (as864) moves the work routine for USB autosuspend from one
+    source file to another.  This permits the removal of one whole global
+    symbol (!) and should smooth the way for more changes in the future.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index e6dd2b9210f6..8c0a7de61228 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1033,7 +1033,7 @@ static int autosuspend_check(struct usb_device *udev)
+  *
+  * This routine can run only in process context.
+  */
+-int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
++static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ {
+ 	int			status = 0;
+ 	int			i = 0;
+@@ -1109,7 +1109,7 @@ int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+  *
+  * This routine can run only in process context.
+  */
+-int usb_resume_both(struct usb_device *udev)
++static int usb_resume_both(struct usb_device *udev)
+ {
+ 	int			status = 0;
+ 	int			i;
+@@ -1173,6 +1173,18 @@ int usb_resume_both(struct usb_device *udev)
+ 
+ #ifdef CONFIG_USB_SUSPEND
+ 
++/* usb_autosuspend_work - callback routine to autosuspend a USB device */
++void usb_autosuspend_work(struct work_struct *work)
++{
++	struct usb_device *udev =
++		container_of(work, struct usb_device, autosuspend.work);
++
++	usb_pm_lock(udev);
++	udev->auto_pm = 1;
++	usb_suspend_both(udev, PMSG_SUSPEND);
++	usb_pm_unlock(udev);
++}
++
+ /* Internal routine to adjust a device's usage counter and change
+  * its autosuspend state.
+  */
+@@ -1405,6 +1417,11 @@ int usb_autopm_set_interface(struct usb_interface *intf)
+ }
+ EXPORT_SYMBOL_GPL(usb_autopm_set_interface);
+ 
++#else
++
++void usb_autosuspend_work(struct work_struct *work)
++{}
++
+ #endif /* CONFIG_USB_SUSPEND */
+ 
+ static int usb_suspend(struct device *dev, pm_message_t message)
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 54b42ce311c1..82338f497860 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -211,27 +211,6 @@ static void ksuspend_usb_cleanup(void)
+ 	destroy_workqueue(ksuspend_usb_wq);
+ }
+ 
+-#ifdef	CONFIG_USB_SUSPEND
+-
+-/* usb_autosuspend_work - callback routine to autosuspend a USB device */
+-static void usb_autosuspend_work(struct work_struct *work)
+-{
+-	struct usb_device *udev =
+-		container_of(work, struct usb_device, autosuspend.work);
+-
+-	usb_pm_lock(udev);
+-	udev->auto_pm = 1;
+-	usb_suspend_both(udev, PMSG_SUSPEND);
+-	usb_pm_unlock(udev);
+-}
+-
+-#else
+-
+-static void usb_autosuspend_work(struct work_struct *work)
+-{}
+-
+-#endif	/* CONFIG_USB_SUSPEND */
+-
+ #else
+ 
+ #define ksuspend_usb_init()	0
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 08b5a04e3755..b98bc0d381c0 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -34,8 +34,7 @@ extern void usb_host_cleanup(void);
+ 
+ #ifdef	CONFIG_PM
+ 
+-extern int usb_suspend_both(struct usb_device *udev, pm_message_t msg);
+-extern int usb_resume_both(struct usb_device *udev);
++extern void usb_autosuspend_work(struct work_struct *work);
+ extern int usb_port_suspend(struct usb_device *dev);
+ extern int usb_port_resume(struct usb_device *dev);
+ 
+@@ -51,11 +50,6 @@ static inline void usb_pm_unlock(struct usb_device *udev)
+ 
+ #else
+ 
+-#define usb_suspend_both(udev, msg)	0
+-static inline int usb_resume_both(struct usb_device *udev)
+-{
+-	return 0;
+-}
+ #define usb_port_suspend(dev)		0
+ #define usb_port_resume(dev)		0
+ static inline void usb_pm_lock(struct usb_device *udev) {}

commit 523ded71de0c5e66973335bf99a80edfda9f401b
+Author: Alan Stern 
+Date:   Thu Apr 26 00:12:04 2007 -0700
+
+    device_schedule_callback() needs a module reference
+    
+    This patch (as896b) fixes an oversight in the design of
+    device_schedule_callback().  It is necessary to acquire a reference to the
+    module owning the callback routine, to prevent the module from being
+    unloaded before the callback can run.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Satyam Sharma 
+    Cc: Neil Brown 
+    Cc: Cornelia Huck 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/base/core.c b/drivers/base/core.c
+index f69305c7269d..8aa090da1cd7 100644
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -480,9 +480,10 @@ void device_remove_bin_file(struct device *dev, struct bin_attribute *attr)
+ EXPORT_SYMBOL_GPL(device_remove_bin_file);
+ 
+ /**
+- * device_schedule_callback - helper to schedule a callback for a device
++ * device_schedule_callback_owner - helper to schedule a callback for a device
+  * @dev: device.
+  * @func: callback function to invoke later.
++ * @owner: module owning the callback routine
+  *
+  * Attribute methods must not unregister themselves or their parent device
+  * (which would amount to the same thing).  Attempts to do so will deadlock,
+@@ -493,20 +494,23 @@ EXPORT_SYMBOL_GPL(device_remove_bin_file);
+  * argument in the workqueue's process context.  @dev will be pinned until
+  * @func returns.
+  *
++ * This routine is usually called via the inline device_schedule_callback(),
++ * which automatically sets @owner to THIS_MODULE.
++ *
+  * Returns 0 if the request was submitted, -ENOMEM if storage could not
+- * be allocated.
++ * be allocated, -ENODEV if a reference to @owner isn't available.
+  *
+  * NOTE: This routine won't work if CONFIG_SYSFS isn't set!  It uses an
+  * underlying sysfs routine (since it is intended for use by attribute
+  * methods), and if sysfs isn't available you'll get nothing but -ENOSYS.
+  */
+-int device_schedule_callback(struct device *dev,
+-		void (*func)(struct device *))
++int device_schedule_callback_owner(struct device *dev,
++		void (*func)(struct device *), struct module *owner)
+ {
+ 	return sysfs_schedule_callback(&dev->kobj,
+-			(void (*)(void *)) func, dev);
++			(void (*)(void *)) func, dev, owner);
+ }
+-EXPORT_SYMBOL_GPL(device_schedule_callback);
++EXPORT_SYMBOL_GPL(device_schedule_callback_owner);
+ 
+ static void klist_children_get(struct klist_node *n)
+ {
+diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
+index fc4633378dc0..db0413a411d6 100644
+--- a/fs/sysfs/file.c
++++ b/fs/sysfs/file.c
+@@ -633,6 +633,7 @@ struct sysfs_schedule_callback_struct {
+ 	struct kobject 		*kobj;
+ 	void			(*func)(void *);
+ 	void			*data;
++	struct module		*owner;
+ 	struct work_struct	work;
+ };
+ 
+@@ -643,6 +644,7 @@ static void sysfs_schedule_callback_work(struct work_struct *work)
+ 
+ 	(ss->func)(ss->data);
+ 	kobject_put(ss->kobj);
++	module_put(ss->owner);
+ 	kfree(ss);
+ }
+ 
+@@ -651,6 +653,7 @@ static void sysfs_schedule_callback_work(struct work_struct *work)
+  * @kobj: object we're acting for.
+  * @func: callback function to invoke later.
+  * @data: argument to pass to @func.
++ * @owner: module owning the callback code
+  *
+  * sysfs attribute methods must not unregister themselves or their parent
+  * kobject (which would amount to the same thing).  Attempts to do so will
+@@ -663,20 +666,25 @@ static void sysfs_schedule_callback_work(struct work_struct *work)
+  * until @func returns.
+  *
+  * Returns 0 if the request was submitted, -ENOMEM if storage could not
+- * be allocated.
++ * be allocated, -ENODEV if a reference to @owner isn't available.
+  */
+ int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *),
+-		void *data)
++		void *data, struct module *owner)
+ {
+ 	struct sysfs_schedule_callback_struct *ss;
+ 
++	if (!try_module_get(owner))
++		return -ENODEV;
+ 	ss = kmalloc(sizeof(*ss), GFP_KERNEL);
+-	if (!ss)
++	if (!ss) {
++		module_put(owner);
+ 		return -ENOMEM;
++	}
+ 	kobject_get(kobj);
+ 	ss->kobj = kobj;
+ 	ss->func = func;
+ 	ss->data = data;
++	ss->owner = owner;
+ 	INIT_WORK(&ss->work, sysfs_schedule_callback_work);
+ 	schedule_work(&ss->work);
+ 	return 0;
+diff --git a/include/linux/device.h b/include/linux/device.h
+index af603a137690..8511d14071b3 100644
+--- a/include/linux/device.h
++++ b/include/linux/device.h
+@@ -367,8 +367,12 @@ extern int __must_check device_create_bin_file(struct device *dev,
+ 					       struct bin_attribute *attr);
+ extern void device_remove_bin_file(struct device *dev,
+ 				   struct bin_attribute *attr);
+-extern int device_schedule_callback(struct device *dev,
+-		void (*func)(struct device *));
++extern int device_schedule_callback_owner(struct device *dev,
++		void (*func)(struct device *), struct module *owner);
++
++/* This is a macro to avoid include problems with THIS_MODULE */
++#define device_schedule_callback(dev, func)			\
++	device_schedule_callback_owner(dev, func, THIS_MODULE)
+ 
+ /* device resource management */
+ typedef void (*dr_release_t)(struct device *dev, void *res);
+diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
+index fea9a6b3fb7b..7d5d1ec95c2e 100644
+--- a/include/linux/sysfs.h
++++ b/include/linux/sysfs.h
+@@ -80,7 +80,7 @@ struct sysfs_ops {
+ #ifdef CONFIG_SYSFS
+ 
+ extern int sysfs_schedule_callback(struct kobject *kobj,
+-		void (*func)(void *), void *data);
++		void (*func)(void *), void *data, struct module *owner);
+ 
+ extern int __must_check
+ sysfs_create_dir(struct kobject *, struct dentry *);
+@@ -137,7 +137,7 @@ extern int __must_check sysfs_init(void);
+ #else /* CONFIG_SYSFS */
+ 
+ static inline int sysfs_schedule_callback(struct kobject *kobj,
+-		void (*func)(void *), void *data)
++		void (*func)(void *), void *data, struct module *owner)
+ {
+ 	return -ENOSYS;
+ }

commit 44ec95425c1d9dce6e4638c29e4362cfb44814e7
+Author: Alan Stern 
+Date:   Tue Feb 20 11:01:57 2007 -0500
+
+    [SCSI] sg: cap reserved_size values at max_sectors
+    
+    This patch (as857) modifies the SG_GET_RESERVED_SIZE and
+    SG_SET_RESERVED_SIZE ioctls in the sg driver, capping the values at
+    the device's request_queue's max_sectors value.  This will permit
+    cdrecord to obtain a legal value for the maximum transfer length,
+    fixing Bugzilla #7026.
+    
+    The patch also caps the initial reserved_size value.  There's no
+    reason to have a reserved buffer larger than max_sectors, since it
+    would be impossible to use the extra space.
+    
+    The corresponding ioctls in the block layer are modified similarly,
+    and the initial value for the reserved_size is set as large as
+    possible.  This will effectively make it default to max_sectors.
+    Note that the actual value is meaningless anyway, since block devices
+    don't have a reserved buffer.
+    
+    Finally, the BLKSECTGET ioctl is added to sg, so that there will be a
+    uniform way for users to determine the actual max_sectors value for
+    any raw SCSI transport.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Jens Axboe 
+    Acked-by: Douglas Gilbert 
+    Signed-off-by: James Bottomley 
+
+diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
+index 38c293b987b7..cf8752abd61a 100644
+--- a/block/ll_rw_blk.c
++++ b/block/ll_rw_blk.c
+@@ -1925,6 +1925,8 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
+ 	blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS);
+ 	blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS);
+ 
++	q->sg_reserved_size = INT_MAX;
++
+ 	/*
+ 	 * all done
+ 	 */
+diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
+index 65c6a3cba6d6..e83f1dbf7c29 100644
+--- a/block/scsi_ioctl.c
++++ b/block/scsi_ioctl.c
+@@ -78,7 +78,9 @@ static int sg_set_timeout(request_queue_t *q, int __user *p)
+ 
+ static int sg_get_reserved_size(request_queue_t *q, int __user *p)
+ {
+-	return put_user(q->sg_reserved_size, p);
++	unsigned val = min(q->sg_reserved_size, q->max_sectors << 9);
++
++	return put_user(val, p);
+ }
+ 
+ static int sg_set_reserved_size(request_queue_t *q, int __user *p)
+diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
+index 81e3bc7b02a1..570977cf9efb 100644
+--- a/drivers/scsi/sg.c
++++ b/drivers/scsi/sg.c
+@@ -917,6 +917,8 @@ sg_ioctl(struct inode *inode, struct file *filp,
+ 			return result;
+                 if (val < 0)
+                         return -EINVAL;
++		val = min_t(int, val,
++				sdp->device->request_queue->max_sectors * 512);
+ 		if (val != sfp->reserve.bufflen) {
+ 			if (sg_res_in_use(sfp) || sfp->mmap_called)
+ 				return -EBUSY;
+@@ -925,7 +927,8 @@ sg_ioctl(struct inode *inode, struct file *filp,
+ 		}
+ 		return 0;
+ 	case SG_GET_RESERVED_SIZE:
+-		val = (int) sfp->reserve.bufflen;
++		val = min_t(int, sfp->reserve.bufflen,
++				sdp->device->request_queue->max_sectors * 512);
+ 		return put_user(val, ip);
+ 	case SG_SET_COMMAND_Q:
+ 		result = get_user(val, ip);
+@@ -1061,6 +1064,9 @@ sg_ioctl(struct inode *inode, struct file *filp,
+ 		if (sdp->detached)
+ 			return -ENODEV;
+ 		return scsi_ioctl(sdp->device, cmd_in, p);
++	case BLKSECTGET:
++		return put_user(sdp->device->request_queue->max_sectors * 512,
++				ip);
+ 	default:
+ 		if (read_only)
+ 			return -EPERM;	/* don't know so take safe approach */
+@@ -2339,6 +2345,7 @@ sg_add_sfp(Sg_device * sdp, int dev)
+ {
+ 	Sg_fd *sfp;
+ 	unsigned long iflags;
++	int bufflen;
+ 
+ 	sfp = kzalloc(sizeof(*sfp), GFP_ATOMIC | __GFP_NOWARN);
+ 	if (!sfp)
+@@ -2369,7 +2376,9 @@ sg_add_sfp(Sg_device * sdp, int dev)
+ 	if (unlikely(sg_big_buff != def_reserved_size))
+ 		sg_big_buff = def_reserved_size;
+ 
+-	sg_build_reserve(sfp, sg_big_buff);
++	bufflen = min_t(int, sg_big_buff,
++			sdp->device->request_queue->max_sectors * 512);
++	sg_build_reserve(sfp, bufflen);
+ 	SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp:   bufflen=%d, k_use_sg=%d\n",
+ 			   sfp->reserve.bufflen, sfp->reserve.k_use_sg));
+ 	return sfp;

commit 61e8b858abe38c1042135065c59f7d339194b50b
+Author: Alan Stern 
+Date:   Mon Apr 9 11:52:31 2007 -0400
+
+    EHCI: fix remote wakeup regression in 2.6.21-rc
+    
+    There is one significant difference between the behavior of root hubs
+    (as embodied in host controller hardware) and external hubs: When a
+    remote-wakeup signal is received, an external hub sends an interrupt
+    message at the _end_ of the resume sequence but a root hub generates
+    and interrupt at the _beginning_ of the resume sequence.  The host
+    system must poll for the end of the sequence.
+    
+    When ehci-hcd was converted to interrupt-driven operation instead of
+    using polling, the remaining need for this particular poll was
+    overlooked.  This patch (as894) fixes the problem.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index a74056488234..c7458f7e56cc 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -669,6 +669,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 			 */
+ 			ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
+ 			ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
++			mod_timer(&hcd->rh_timer, ehci->reset_done[i]);
+ 		}
+ 	}
+ 

commit 5e2a55f25d255a356bdaf2cb04c71b8d76c307a8
+Author: Alan Stern 
+Date:   Tue Mar 20 19:03:31 2007 +0100
+
+    USB HID: fix retry & reset logic
+    
+    The USB HID driver fails to reset its error-retry timeout when there
+    has been a long time interval between I/O errors with no successful URB
+    completions in the meantime.  As a result, the very next error would
+    trigger an immediate reset, even if it was a chance event occurring
+    long after the previous error.
+    
+    More USB keyboards and mice than one might expect end up getting I/O
+    errors. Almost always this results from hardware problems of one sort of
+    another. For example, people attach the device to a USB extension cable,
+    which degrades the signal.  Or they simply have poor quality cables to
+    begin with. Or they use a KVM switch which doesn't handle USB messages
+    correctly. Etc...
+    
+    There have been reports from several users in which these I/O
+    errors would occur more or less randomly, at intervals ranging from
+    seconds to minutes.  The error-handling code in hid-core.c was originally
+    meant for situations where a single outage would persist for a few hundred
+    ms (electromagnetic interference, for example).  It didn't work right when
+    these more sporadic errors occurred, because of a flaw in the logic
+    which this patch fixes.
+    
+    This patch (as873) fixes that oversight.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index 7c0fc11e972a..35a41e60f541 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -554,6 +554,11 @@ static void hid_io_error(struct hid_device *hid)
+ 	if (usb_get_intfdata(usbhid->intf) == NULL)
+ 		goto done;
+ 
++	/* If it has been a while since the last error, we'll assume
++	 * this a brand new error and reset the retry timeout. */
++	if (time_after(jiffies, usbhid->stop_retry + HZ/2))
++		usbhid->retry_delay = 0;
++
+ 	/* When an error occurs, retry at increasing intervals */
+ 	if (usbhid->retry_delay == 0) {
+ 		usbhid->retry_delay = 13;	/* Then 26, 52, 104, 104, ... */

commit e009f1b202219c62ea7e277adbb953d703dac983
+Author: Alan Stern 
+Date:   Mon Mar 19 15:31:42 2007 -0400
+
+    UHCI: Fix problem caused by lack of terminating QH
+    
+    This patch (as871) fixes a problem introduced by an earlier change.
+    It turns out that some systems really do need to have a terminating
+    skeleton QH present whenever FSBR is on.  I don't know any way to tell
+    which systems do need it and which don't; the easiest answer is to
+    have it there always.
+    
+    This fixes the NumLock-hang bug reported by Jiri Slaby.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
+index 8d24d3dc0a61..1497371583b9 100644
+--- a/drivers/usb/host/uhci-debug.c
++++ b/drivers/usb/host/uhci-debug.c
+@@ -145,7 +145,8 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space)
+ 	return out - buf;
+ }
+ 
+-static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
++static int uhci_show_qh(struct uhci_hcd *uhci,
++		struct uhci_qh *qh, char *buf, int len, int space)
+ {
+ 	char *out = buf;
+ 	int i, nurbs;
+@@ -190,6 +191,9 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
+ 
+ 	if (list_empty(&qh->queue)) {
+ 		out += sprintf(out, "%*s  queue is empty\n", space, "");
++		if (qh == uhci->skel_async_qh)
++			out += uhci_show_td(uhci->term_td, out,
++					len - (out - buf), 0);
+ 	} else {
+ 		struct urb_priv *urbp = list_entry(qh->queue.next,
+ 				struct urb_priv, node);
+@@ -343,6 +347,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
+ 	struct list_head *tmp, *head;
+ 	int nframes, nerrs;
+ 	__le32 link;
++	__le32 fsbr_link;
+ 
+ 	static const char * const qh_names[] = {
+ 		"unlink", "iso", "int128", "int64", "int32", "int16",
+@@ -424,21 +429,22 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
+ 
+ 	out += sprintf(out, "Skeleton QHs\n");
+ 
++	fsbr_link = 0;
+ 	for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
+ 		int cnt = 0;
+-		__le32 fsbr_link = 0;
+ 
+ 		qh = uhci->skelqh[i];
+ 		out += sprintf(out, "- skel_%s_qh\n", qh_names[i]); \
+-		out += uhci_show_qh(qh, out, len - (out - buf), 4);
++		out += uhci_show_qh(uhci, qh, out, len - (out - buf), 4);
+ 
+ 		/* Last QH is the Terminating QH, it's different */
+ 		if (i == SKEL_TERM) {
+ 			if (qh_element(qh) != LINK_TO_TD(uhci->term_td))
+ 				out += sprintf(out, "    skel_term_qh element is not set to term_td!\n");
+-			if (link == LINK_TO_QH(uhci->skel_term_qh))
+-				goto check_qh_link;
+-			continue;
++			link = fsbr_link;
++			if (!link)
++				link = LINK_TO_QH(uhci->skel_term_qh);
++			goto check_qh_link;
+ 		}
+ 
+ 		head = &qh->node;
+@@ -448,7 +454,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
+ 			qh = list_entry(tmp, struct uhci_qh, node);
+ 			tmp = tmp->next;
+ 			if (++cnt <= 10)
+-				out += uhci_show_qh(qh, out,
++				out += uhci_show_qh(uhci, qh, out,
+ 						len - (out - buf), 4);
+ 			if (!fsbr_link && qh->skel >= SKEL_FSBR)
+ 				fsbr_link = LINK_TO_QH(qh);
+@@ -463,8 +469,6 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
+ 			link = LINK_TO_QH(uhci->skel_async_qh);
+ 		else if (!uhci->fsbr_is_on)
+ 			;
+-		else if (fsbr_link)
+-			link = fsbr_link;
+ 		else
+ 			link = LINK_TO_QH(uhci->skel_term_qh);
+ check_qh_link:
+@@ -573,8 +577,8 @@ static const struct file_operations uhci_debug_operations = {
+ static inline void lprintk(char *buf)
+ {}
+ 
+-static inline int uhci_show_qh(struct uhci_qh *qh, char *buf,
+-		int len, int space)
++static inline int uhci_show_qh(struct uhci_hcd *uhci,
++		struct uhci_qh *qh, char *buf, int len, int space)
+ {
+ 	return 0;
+ }
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 44da4334f1d6..d22da26ff167 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -632,7 +632,8 @@ static int uhci_start(struct usb_hcd *hcd)
+ 	 */
+ 	for (i = SKEL_ISO + 1; i < SKEL_ASYNC; ++i)
+ 		uhci->skelqh[i]->link = LINK_TO_QH(uhci->skel_async_qh);
+-	uhci->skel_async_qh->link = uhci->skel_term_qh->link = UHCI_PTR_TERM;
++	uhci->skel_async_qh->link = UHCI_PTR_TERM;
++	uhci->skel_term_qh->link = LINK_TO_QH(uhci->skel_term_qh);
+ 
+ 	/* This dummy TD is to work around a bug in Intel PIIX controllers */
+ 	uhci_fill_td(uhci->term_td, 0, uhci_explen(0) |
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index f4ebdb3e488f..19a0cc02b9a2 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -45,43 +45,27 @@ static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci)
+  */
+ static void uhci_fsbr_on(struct uhci_hcd *uhci)
+ {
+-	struct uhci_qh *fsbr_qh, *lqh, *tqh;
++	struct uhci_qh *lqh;
+ 
++	/* The terminating skeleton QH always points back to the first
++	 * FSBR QH.  Make the last async QH point to the terminating
++	 * skeleton QH. */
+ 	uhci->fsbr_is_on = 1;
+ 	lqh = list_entry(uhci->skel_async_qh->node.prev,
+ 			struct uhci_qh, node);
+-
+-	/* Find the first FSBR QH.  Linear search through the list is
+-	 * acceptable because normally FSBR gets turned on as soon as
+-	 * one QH needs it. */
+-	fsbr_qh = NULL;
+-	list_for_each_entry_reverse(tqh, &uhci->skel_async_qh->node, node) {
+-		if (tqh->skel < SKEL_FSBR)
+-			break;
+-		fsbr_qh = tqh;
+-	}
+-
+-	/* No FSBR QH means we must insert the terminating skeleton QH */
+-	if (!fsbr_qh) {
+-		uhci->skel_term_qh->link = LINK_TO_QH(uhci->skel_term_qh);
+-		wmb();
+-		lqh->link = uhci->skel_term_qh->link;
+-
+-	/* Otherwise loop the last QH to the first FSBR QH */
+-	} else
+-		lqh->link = LINK_TO_QH(fsbr_qh);
++	lqh->link = LINK_TO_QH(uhci->skel_term_qh);
+ }
+ 
+ static void uhci_fsbr_off(struct uhci_hcd *uhci)
+ {
+ 	struct uhci_qh *lqh;
+ 
++	/* Remove the link from the last async QH to the terminating
++	 * skeleton QH. */
+ 	uhci->fsbr_is_on = 0;
+ 	lqh = list_entry(uhci->skel_async_qh->node.prev,
+ 			struct uhci_qh, node);
+-
+-	/* End the async list normally and unlink the terminating QH */
+-	lqh->link = uhci->skel_term_qh->link = UHCI_PTR_TERM;
++	lqh->link = UHCI_PTR_TERM;
+ }
+ 
+ static void uhci_add_fsbr(struct uhci_hcd *uhci, struct urb *urb)
+@@ -464,9 +448,8 @@ static void link_interrupt(struct uhci_hcd *uhci, struct uhci_qh *qh)
+  */
+ static void link_async(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ {
+-	struct uhci_qh *pqh, *lqh;
++	struct uhci_qh *pqh;
+ 	__le32 link_to_new_qh;
+-	__le32 *extra_link = &link_to_new_qh;
+ 
+ 	/* Find the predecessor QH for our new one and insert it in the list.
+ 	 * The list of QHs is expected to be short, so linear search won't
+@@ -476,31 +459,17 @@ static void link_async(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ 			break;
+ 	}
+ 	list_add(&qh->node, &pqh->node);
+-	qh->link = pqh->link;
+-
+-	link_to_new_qh = LINK_TO_QH(qh);
+-
+-	/* If this is now the first FSBR QH, take special action */
+-	if (uhci->fsbr_is_on && pqh->skel < SKEL_FSBR &&
+-			qh->skel >= SKEL_FSBR) {
+-		lqh = list_entry(uhci->skel_async_qh->node.prev,
+-				struct uhci_qh, node);
+-
+-		/* If the new QH is also the last one, we must unlink
+-		 * the terminating skeleton QH and make the new QH point
+-		 * back to itself. */
+-		if (qh == lqh) {
+-			qh->link = link_to_new_qh;
+-			extra_link = &uhci->skel_term_qh->link;
+-
+-		/* Otherwise the last QH must point to the new QH */
+-		} else
+-			extra_link = &lqh->link;
+-	}
+ 
+ 	/* Link it into the schedule */
++	qh->link = pqh->link;
+ 	wmb();
+-	*extra_link = pqh->link = link_to_new_qh;
++	link_to_new_qh = LINK_TO_QH(qh);
++	pqh->link = link_to_new_qh;
++
++	/* If this is now the first FSBR QH, link the terminating skeleton
++	 * QH to it. */
++	if (pqh->skel < SKEL_FSBR && qh->skel >= SKEL_FSBR)
++		uhci->skel_term_qh->link = link_to_new_qh;
+ }
+ 
+ /*
+@@ -561,31 +530,16 @@ static void unlink_interrupt(struct uhci_hcd *uhci, struct uhci_qh *qh)
+  */
+ static void unlink_async(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ {
+-	struct uhci_qh *pqh, *lqh;
++	struct uhci_qh *pqh;
+ 	__le32 link_to_next_qh = qh->link;
+ 
+ 	pqh = list_entry(qh->node.prev, struct uhci_qh, node);
+-
+-	/* If this is the first FSBQ QH, take special action */
+-	if (uhci->fsbr_is_on && pqh->skel < SKEL_FSBR &&
+-			qh->skel >= SKEL_FSBR) {
+-		lqh = list_entry(uhci->skel_async_qh->node.prev,
+-				struct uhci_qh, node);
+-
+-		/* If this QH is also the last one, we must link in
+-		 * the terminating skeleton QH. */
+-		if (qh == lqh) {
+-			link_to_next_qh = LINK_TO_QH(uhci->skel_term_qh);
+-			uhci->skel_term_qh->link = link_to_next_qh;
+-			wmb();
+-			qh->link = link_to_next_qh;
+-
+-		/* Otherwise the last QH must point to the new first FSBR QH */
+-		} else
+-			lqh->link = link_to_next_qh;
+-	}
+-
+ 	pqh->link = link_to_next_qh;
++
++	/* If this was the old first FSBR QH, link the terminating skeleton
++	 * QH to the next (new first FSBR) QH. */
++	if (pqh->skel < SKEL_FSBR && qh->skel >= SKEL_FSBR)
++		uhci->skel_term_qh->link = link_to_next_qh;
+ 	mb();
+ }
+ 
+@@ -1217,7 +1171,7 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
+ 
+ 				if (debug > 1 && errbuf) {
+ 					/* Print the chain for debugging */
+-					uhci_show_qh(urbp->qh, errbuf,
++					uhci_show_qh(uhci, urbp->qh, errbuf,
+ 							ERRBUF_LEN, 0);
+ 					lprintk(errbuf);
+ 				}

commit 5ec71db59ac07eeac89a54b35a90c181bbd3c445
+Author: Alan Stern 
+Date:   Fri Mar 16 15:53:07 2007 -0400
+
+    usblp: quirk flag and device entry for Seiko Epson M129C printer
+    
+    This patch (as872) adds a device table entry and a new quirk flag to
+    the usblp driver for the Seiko Epson Receipt printer.  This printer
+    returns Vendor-Specific values for bInterfaceClass and
+    bInterfaceSubClass, but the bInterfaceProtocol value is valid and it
+    works with usblp.  The new quirks flag tells the driver to ignore the
+    Class and SubClass values in the interface descriptor.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Vojtech Pavlik 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
+index 63e50a1f1396..6584cf00f7f3 100644
+--- a/drivers/usb/class/usblp.c
++++ b/drivers/usb/class/usblp.c
+@@ -202,6 +202,7 @@ struct quirk_printer_struct {
+ 
+ #define USBLP_QUIRK_BIDIR	0x1	/* reports bidir but requires unidirectional mode (no INs/reads) */
+ #define USBLP_QUIRK_USB_INIT	0x2	/* needs vendor USB init string */
++#define USBLP_QUIRK_BAD_CLASS	0x4	/* descriptor uses vendor-specific Class or SubClass */
+ 
+ static const struct quirk_printer_struct quirk_printers[] = {
+ 	{ 0x03f0, 0x0004, USBLP_QUIRK_BIDIR }, /* HP DeskJet 895C */
+@@ -218,6 +219,7 @@ static const struct quirk_printer_struct quirk_printers[] = {
+ 	{ 0x0409, 0xf0be, USBLP_QUIRK_BIDIR }, /* NEC Picty920 (HP OEM) */
+ 	{ 0x0409, 0xf1be, USBLP_QUIRK_BIDIR }, /* NEC Picty800 (HP OEM) */
+ 	{ 0x0482, 0x0010, USBLP_QUIRK_BIDIR }, /* Kyocera Mita FS 820, by zut  */
++	{ 0x04b8, 0x0202, USBLP_QUIRK_BAD_CLASS }, /* Seiko Epson Receipt Printer M129C */
+ 	{ 0, 0 }
+ };
+ 
+@@ -1048,7 +1050,8 @@ static int usblp_select_alts(struct usblp *usblp)
+ 		ifd = &if_alt->altsetting[i];
+ 
+ 		if (ifd->desc.bInterfaceClass != 7 || ifd->desc.bInterfaceSubClass != 1)
+-			continue;
++			if (!(usblp->quirks & USBLP_QUIRK_BAD_CLASS))
++				continue;
+ 
+ 		if (ifd->desc.bInterfaceProtocol < USBLP_FIRST_PROTOCOL ||
+ 		    ifd->desc.bInterfaceProtocol > USBLP_LAST_PROTOCOL)
+@@ -1232,6 +1235,7 @@ static struct usb_device_id usblp_ids [] = {
+ 	{ USB_INTERFACE_INFO(7, 1, 1) },
+ 	{ USB_INTERFACE_INFO(7, 1, 2) },
+ 	{ USB_INTERFACE_INFO(7, 1, 3) },
++	{ USB_DEVICE(0x04b8, 0x0202) },	/* Seiko Epson Receipt Printer M129C */
+ 	{ }						/* Terminating entry */
+ };
+ 

commit e7b0d26a86943370c04d6833c6edba2a72a6e240
+Author: Alan Stern 
+Date:   Thu Mar 15 15:51:28 2007 -0400
+
+    [PATCH] sysfs: reinstate exclusion between method calls and attribute unregistration
+    
+    This patch (as869) reinstates the mutual exclusion between sysfs
+    attribute method calls and attribute unregistration.  The
+    previously-reported deadlocks have been fixed, and this exclusion is
+    by far the simplest way to avoid races during driver unbinding.
+    
+    The check for orphaned read-buffers has been moved down slightly, so
+    that the remainder of a partially-read buffer will still be available
+    to userspace even after the attribute has been unregistered.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Hugh Dickins 
+    Cc: Cornelia Huck 
+    Cc: Oliver Neukum 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
+index 1bafdf6e171c..fc4633378dc0 100644
+--- a/fs/sysfs/file.c
++++ b/fs/sysfs/file.c
+@@ -168,12 +168,12 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+ 	ssize_t retval = 0;
+ 
+ 	down(&buffer->sem);
+-	if (buffer->orphaned) {
+-		retval = -ENODEV;
+-		goto out;
+-	}
+ 	if (buffer->needs_read_fill) {
+-		if ((retval = fill_read_buffer(file->f_path.dentry,buffer)))
++		if (buffer->orphaned)
++			retval = -ENODEV;
++		else
++			retval = fill_read_buffer(file->f_path.dentry,buffer);
++		if (retval)
+ 			goto out;
+ 	}
+ 	pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n",
+diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
+index ccb7d722c558..4de5c6b89918 100644
+--- a/fs/sysfs/inode.c
++++ b/fs/sysfs/inode.c
+@@ -222,13 +222,17 @@ const unsigned char * sysfs_get_name(struct sysfs_dirent *sd)
+ 
+ static inline void orphan_all_buffers(struct inode *node)
+ {
+-	struct sysfs_buffer_collection *set = node->i_private;
++	struct sysfs_buffer_collection *set;
+ 	struct sysfs_buffer *buf;
+ 
+ 	mutex_lock_nested(&node->i_mutex, I_MUTEX_CHILD);
+-	if (node->i_private) {
+-		list_for_each_entry(buf, &set->associates, associates)
++	set = node->i_private;
++	if (set) {
++		list_for_each_entry(buf, &set->associates, associates) {
++			down(&buf->sem);
+ 			buf->orphaned = 1;
++			up(&buf->sem);
++		}
+ 	}
+ 	mutex_unlock(&node->i_mutex);
+ }

commit d9a9cdfb078d755e648d53ec25b7370f84ee5729
+Author: Alan Stern 
+Date:   Thu Mar 15 15:50:34 2007 -0400
+
+    [PATCH] sysfs and driver core: add callback helper, used by SCSI and S390
+    
+    This patch (as868) adds a helper routine for device drivers that need
+    to set up a callback to perform some action in a different process's
+    context.  This is intended for use by attribute methods that want to
+    unregister themselves or their parent device.  Attribute method calls
+    are mutually exclusive with unregistration, so such actions cannot be
+    taken directly.
+    
+    Two attribute methods are converted to use the new helper routine: one
+    for SCSI device deletion and one for System/390 ccwgroup devices.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Hugh Dickins 
+    Cc: Cornelia Huck 
+    Cc: Oliver Neukum 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/base/core.c b/drivers/base/core.c
+index f191afe62b4d..ad0f4a2f25c4 100644
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -407,6 +407,35 @@ void device_remove_bin_file(struct device *dev, struct bin_attribute *attr)
+ }
+ EXPORT_SYMBOL_GPL(device_remove_bin_file);
+ 
++/**
++ * device_schedule_callback - helper to schedule a callback for a device
++ * @dev: device.
++ * @func: callback function to invoke later.
++ *
++ * Attribute methods must not unregister themselves or their parent device
++ * (which would amount to the same thing).  Attempts to do so will deadlock,
++ * since unregistration is mutually exclusive with driver callbacks.
++ *
++ * Instead methods can call this routine, which will attempt to allocate
++ * and schedule a workqueue request to call back @func with @dev as its
++ * argument in the workqueue's process context.  @dev will be pinned until
++ * @func returns.
++ *
++ * Returns 0 if the request was submitted, -ENOMEM if storage could not
++ * be allocated.
++ *
++ * NOTE: This routine won't work if CONFIG_SYSFS isn't set!  It uses an
++ * underlying sysfs routine (since it is intended for use by attribute
++ * methods), and if sysfs isn't available you'll get nothing but -ENOSYS.
++ */
++int device_schedule_callback(struct device *dev,
++		void (*func)(struct device *))
++{
++	return sysfs_schedule_callback(&dev->kobj,
++			(void (*)(void *)) func, dev);
++}
++EXPORT_SYMBOL_GPL(device_schedule_callback);
++
+ static void klist_children_get(struct klist_node *n)
+ {
+ 	struct device *dev = container_of(n, struct device, knode_parent);
+diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
+index d48e3ca4752c..5aeb68e732b0 100644
+--- a/drivers/s390/cio/ccwgroup.c
++++ b/drivers/s390/cio/ccwgroup.c
+@@ -71,19 +71,31 @@ __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
+  * Provide an 'ungroup' attribute so the user can remove group devices no
+  * longer needed or accidentially created. Saves memory :)
+  */
++static void ccwgroup_ungroup_callback(struct device *dev)
++{
++	struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
++
++	__ccwgroup_remove_symlinks(gdev);
++	device_unregister(dev);
++}
++
+ static ssize_t
+ ccwgroup_ungroup_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+ {
+ 	struct ccwgroup_device *gdev;
++	int rc;
+ 
+ 	gdev = to_ccwgroupdev(dev);
+ 
+ 	if (gdev->state != CCWGROUP_OFFLINE)
+ 		return -EINVAL;
+ 
+-	__ccwgroup_remove_symlinks(gdev);
+-	device_unregister(dev);
+-
++	/* Note that we cannot unregister the device from one of its
++	 * attribute methods, so we have to use this roundabout approach.
++	 */
++	rc = device_schedule_callback(dev, ccwgroup_ungroup_callback);
++	if (rc)
++		count = rc;
+ 	return count;
+ }
+ 
+diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
+index c275dcac3f18..939de0de18bc 100644
+--- a/drivers/scsi/scsi_sysfs.c
++++ b/drivers/scsi/scsi_sysfs.c
+@@ -452,10 +452,22 @@ store_rescan_field (struct device *dev, struct device_attribute *attr, const cha
+ }
+ static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field);
+ 
++static void sdev_store_delete_callback(struct device *dev)
++{
++	scsi_remove_device(to_scsi_device(dev));
++}
++
+ static ssize_t sdev_store_delete(struct device *dev, struct device_attribute *attr, const char *buf,
+ 				 size_t count)
+ {
+-	scsi_remove_device(to_scsi_device(dev));
++	int rc;
++
++	/* An attribute cannot be unregistered by one of its own methods,
++	 * so we have to use this roundabout approach.
++	 */
++	rc = device_schedule_callback(dev, sdev_store_delete_callback);
++	if (rc)
++		count = rc;
+ 	return count;
+ };
+ static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete);
+diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
+index 8d4d839a9d88..1bafdf6e171c 100644
+--- a/fs/sysfs/file.c
++++ b/fs/sysfs/file.c
+@@ -629,6 +629,60 @@ void sysfs_remove_file_from_group(struct kobject *kobj,
+ }
+ EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group);
+ 
++struct sysfs_schedule_callback_struct {
++	struct kobject 		*kobj;
++	void			(*func)(void *);
++	void			*data;
++	struct work_struct	work;
++};
++
++static void sysfs_schedule_callback_work(struct work_struct *work)
++{
++	struct sysfs_schedule_callback_struct *ss = container_of(work,
++			struct sysfs_schedule_callback_struct, work);
++
++	(ss->func)(ss->data);
++	kobject_put(ss->kobj);
++	kfree(ss);
++}
++
++/**
++ * sysfs_schedule_callback - helper to schedule a callback for a kobject
++ * @kobj: object we're acting for.
++ * @func: callback function to invoke later.
++ * @data: argument to pass to @func.
++ *
++ * sysfs attribute methods must not unregister themselves or their parent
++ * kobject (which would amount to the same thing).  Attempts to do so will
++ * deadlock, since unregistration is mutually exclusive with driver
++ * callbacks.
++ *
++ * Instead methods can call this routine, which will attempt to allocate
++ * and schedule a workqueue request to call back @func with @data as its
++ * argument in the workqueue's process context.  @kobj will be pinned
++ * until @func returns.
++ *
++ * Returns 0 if the request was submitted, -ENOMEM if storage could not
++ * be allocated.
++ */
++int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *),
++		void *data)
++{
++	struct sysfs_schedule_callback_struct *ss;
++
++	ss = kmalloc(sizeof(*ss), GFP_KERNEL);
++	if (!ss)
++		return -ENOMEM;
++	kobject_get(kobj);
++	ss->kobj = kobj;
++	ss->func = func;
++	ss->data = data;
++	INIT_WORK(&ss->work, sysfs_schedule_callback_work);
++	schedule_work(&ss->work);
++	return 0;
++}
++EXPORT_SYMBOL_GPL(sysfs_schedule_callback);
++
+ 
+ EXPORT_SYMBOL_GPL(sysfs_create_file);
+ EXPORT_SYMBOL_GPL(sysfs_remove_file);
+diff --git a/include/linux/device.h b/include/linux/device.h
+index 39a3199a826d..caad9bba9652 100644
+--- a/include/linux/device.h
++++ b/include/linux/device.h
+@@ -353,6 +353,8 @@ extern int __must_check device_create_bin_file(struct device *dev,
+ 					       struct bin_attribute *attr);
+ extern void device_remove_bin_file(struct device *dev,
+ 				   struct bin_attribute *attr);
++extern int device_schedule_callback(struct device *dev,
++		void (*func)(struct device *));
+ 
+ /* device resource management */
+ typedef void (*dr_release_t)(struct device *dev, void *res);
+diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
+index 523405e1e1f6..0544edda7168 100644
+--- a/include/linux/sysfs.h
++++ b/include/linux/sysfs.h
+@@ -78,6 +78,9 @@ struct sysfs_ops {
+ 
+ #ifdef CONFIG_SYSFS
+ 
++extern int sysfs_schedule_callback(struct kobject *kobj,
++		void (*func)(void *), void *data);
++
+ extern int __must_check
+ sysfs_create_dir(struct kobject *, struct dentry *);
+ 
+@@ -132,6 +135,12 @@ extern int __must_check sysfs_init(void);
+ 
+ #else /* CONFIG_SYSFS */
+ 
++static inline int sysfs_schedule_callback(struct kobject *kobj,
++		void (*func)(void *), void *data)
++{
++	return -ENOSYS;
++}
++
+ static inline int sysfs_create_dir(struct kobject * k, struct dentry *shadow)
+ {
+ 	return 0;

commit 88018158d1253ab4868a2f9204cc390c711fd9b9
+Author: Alan Stern 
+Date:   Mon Feb 26 17:16:06 2007 -0500
+
+    UHCI: fix port resume problem
+    
+    This patch (as863) fixes a problem encountered sometimes when resuming
+    a port on a UHCI controller.  The hardware may turn off the
+    Resume-Detect bit before turning off the Suspend bit, leading usbcore
+    to think that the port is still suspended and the resume has failed.
+    The patch makes uhci_finish_suspend() wait until both bits are safely
+    off.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
+index bacc25c53ba3..8e4427aebb14 100644
+--- a/drivers/usb/host/uhci-hub.c
++++ b/drivers/usb/host/uhci-hub.c
+@@ -33,6 +33,9 @@ static __u8 root_hub_hub_des[] =
+ /* status change bits:  nonzero writes will clear */
+ #define RWC_BITS	(USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC)
+ 
++/* suspend/resume bits: port suspended or port resuming */
++#define SUSPEND_BITS	(USBPORTSC_SUSP | USBPORTSC_RD)
++
+ /* A port that either is connected or has a changed-bit set will prevent
+  * us from AUTO_STOPPING.
+  */
+@@ -96,8 +99,8 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
+ 	int status;
+ 	int i;
+ 
+-	if (inw(port_addr) & (USBPORTSC_SUSP | USBPORTSC_RD)) {
+-		CLR_RH_PORTSTAT(USBPORTSC_SUSP | USBPORTSC_RD);
++	if (inw(port_addr) & SUSPEND_BITS) {
++		CLR_RH_PORTSTAT(SUSPEND_BITS);
+ 		if (test_bit(port, &uhci->resuming_ports))
+ 			set_bit(port, &uhci->port_c_suspend);
+ 
+@@ -107,7 +110,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
+ 		 * Experiments show that some controllers take longer, so
+ 		 * we'll poll for completion. */
+ 		for (i = 0; i < 10; ++i) {
+-			if (!(inw(port_addr) & USBPORTSC_RD))
++			if (!(inw(port_addr) & SUSPEND_BITS))
+ 				break;
+ 			udelay(1);
+ 		}
+@@ -289,7 +292,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+ 			wPortStatus |= USB_PORT_STAT_CONNECTION;
+ 		if (status & USBPORTSC_PE) {
+ 			wPortStatus |= USB_PORT_STAT_ENABLE;
+-			if (status & (USBPORTSC_SUSP | USBPORTSC_RD))
++			if (status & SUSPEND_BITS)
+ 				wPortStatus |= USB_PORT_STAT_SUSPEND;
+ 		}
+ 		if (status & USBPORTSC_OC)

commit 97b9eb91dc131a10342da1f604e5bd8b1316abdb
+Author: Alan Stern 
+Date:   Mon Feb 26 14:56:14 2007 -0500
+
+    USB: set the correct interval for interrupt URBs
+    
+    This patch (as862) fixes a couple of bugs in the way usbcore handles
+    intervals for interrupt URBs.  usb_interrupt_msg (and usb_bulk_msg for
+    backward compatibility) don't set the interval correctly for
+    high-speed devices.  proc_do_submiturb() doesn't set it correctly when
+    a bulk URB is submitted to an interrupt endpoint.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 274f14f1633e..36e7a843bf91 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -912,7 +912,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 	struct async *as;
+ 	struct usb_ctrlrequest *dr = NULL;
+ 	unsigned int u, totlen, isofrmlen;
+-	int ret, interval = 0, ifnum = -1;
++	int ret, ifnum = -1;
+ 
+ 	if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK|
+ 			   URB_NO_FSBR|URB_ZERO_PACKET))
+@@ -992,7 +992,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 		if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ 				!= USB_ENDPOINT_XFER_ISOC)
+ 			return -EINVAL;
+-		interval = 1 << min (15, ep->desc.bInterval - 1);
+ 		isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb->number_of_packets;
+ 		if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
+ 			return -ENOMEM;
+@@ -1021,10 +1020,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 		if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ 				!= USB_ENDPOINT_XFER_INT)
+ 			return -EINVAL;
+-		if (ps->dev->speed == USB_SPEED_HIGH)
+-			interval = 1 << min (15, ep->desc.bInterval - 1);
+-		else
+-			interval = ep->desc.bInterval;
+ 		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
+ 			return -EINVAL;
+ 		if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length))
+@@ -1053,7 +1048,11 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 	as->urb->setup_packet = (unsigned char*)dr;
+ 	as->urb->start_frame = uurb->start_frame;
+ 	as->urb->number_of_packets = uurb->number_of_packets;
+-	as->urb->interval = interval;
++	if (uurb->type == USBDEVFS_URB_TYPE_ISO ||
++			ps->dev->speed == USB_SPEED_HIGH)
++		as->urb->interval = 1 << min(15, ep->desc.bInterval - 1);
++	else
++		as->urb->interval = ep->desc.bInterval;
+         as->urb->context = as;
+         as->urb->complete = async_completed;
+ 	for (totlen = u = 0; u < uurb->number_of_packets; u++) {
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 2f17468b5c1e..217a3d6d0a06 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -221,10 +221,15 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
+ 
+ 	if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+ 			USB_ENDPOINT_XFER_INT) {
++		int interval;
++
++		if (usb_dev->speed == USB_SPEED_HIGH)
++			interval = 1 << min(15, ep->desc.bInterval - 1);
++		else
++			interval = ep->desc.bInterval;
+ 		pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);
+ 		usb_fill_int_urb(urb, usb_dev, pipe, data, len,
+-				usb_api_blocking_completion, NULL,
+-				ep->desc.bInterval);
++				usb_api_blocking_completion, NULL, interval);
+ 	} else
+ 		usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
+ 				usb_api_blocking_completion, NULL);

commit 19c262391c4741b012a5031fc438fb694e77c385
+Author: Alan Stern 
+Date:   Tue Feb 20 15:03:32 2007 -0500
+
+    USB: export autosuspend delay in sysfs
+    
+    This patch (as861) adds sysfs attributes to expose the autosuspend
+    delay value for each USB device.  If the user changes the delay from 0
+    (no autosuspend) to a positive value, an autosuspend is attempted.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index a420d72a0254..9e3e943f313c 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1224,6 +1224,26 @@ void usb_autosuspend_device(struct usb_device *udev)
+ 	//		__FUNCTION__, udev->pm_usage_cnt);
+ }
+ 
++/**
++ * usb_try_autosuspend_device - attempt an autosuspend of a USB device and its interfaces
++ * @udev: the usb_device to autosuspend
++ *
++ * This routine should be called when a core subsystem thinks @udev may
++ * be ready to autosuspend.
++ *
++ * @udev's usage counter left unchanged.  If it or any of the usage counters
++ * for an active interface is greater than 0, or autosuspend is not allowed
++ * for any other reason, no autosuspend request will be queued.
++ *
++ * This routine can run only in process context.
++ */
++void usb_try_autosuspend_device(struct usb_device *udev)
++{
++	usb_autopm_do_device(udev, 0);
++	// dev_dbg(&udev->dev, "%s: cnt %d\n",
++	// 		__FUNCTION__, udev->pm_usage_cnt);
++}
++
+ /**
+  * usb_autoresume_device - immediately autoresume a USB device and its interfaces
+  * @udev: the usb_device to autoresume
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index cad4fb323f6c..311d5df80386 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -158,6 +158,65 @@ show_quirks(struct device *dev, struct device_attribute *attr, char *buf)
+ }
+ static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL);
+ 
++#ifdef	CONFIG_USB_SUSPEND
++
++static ssize_t
++show_autosuspend(struct device *dev, struct device_attribute *attr, char *buf)
++{
++	struct usb_device *udev = to_usb_device(dev);
++
++	return sprintf(buf, "%u\n", udev->autosuspend_delay / HZ);
++}
++
++static ssize_t
++set_autosuspend(struct device *dev, struct device_attribute *attr,
++		const char *buf, size_t count)
++{
++	struct usb_device *udev = to_usb_device(dev);
++	unsigned value, old;
++
++	if (sscanf(buf, "%u", &value) != 1 || value >= INT_MAX/HZ)
++		return -EINVAL;
++	value *= HZ;
++
++	old = udev->autosuspend_delay;
++	udev->autosuspend_delay = value;
++	if (value > 0 && old == 0)
++		usb_try_autosuspend_device(udev);
++
++	return count;
++}
++
++static DEVICE_ATTR(autosuspend, S_IRUGO | S_IWUSR,
++		show_autosuspend, set_autosuspend);
++
++static char power_group[] = "power";
++
++static int add_power_attributes(struct device *dev)
++{
++	int rc = 0;
++
++	if (is_usb_device(dev))
++		rc = sysfs_add_file_to_group(&dev->kobj,
++				&dev_attr_autosuspend.attr,
++				power_group);
++	return rc;
++}
++
++static void remove_power_attributes(struct device *dev)
++{
++	sysfs_remove_file_from_group(&dev->kobj,
++			&dev_attr_autosuspend.attr,
++			power_group);
++}
++
++#else
++
++#define add_power_attributes(dev)	0
++#define remove_power_attributes(dev)	do {} while (0)
++
++#endif	/* CONFIG_USB_SUSPEND */
++
+ /* Descriptor fields */
+ #define usb_descriptor_attr_le16(field, format_string)			\
+ static ssize_t								\
+@@ -230,6 +289,10 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
+ 	if (retval)
+ 		return retval;
+ 
++	retval = add_power_attributes(dev);
++	if (retval)
++		goto error;
++
+ 	if (udev->manufacturer) {
+ 		retval = device_create_file(dev, &dev_attr_manufacturer);
+ 		if (retval)
+@@ -262,6 +325,7 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)
+ 	device_remove_file(dev, &dev_attr_manufacturer);
+ 	device_remove_file(dev, &dev_attr_product);
+ 	device_remove_file(dev, &dev_attr_serial);
++	remove_power_attributes(dev);
+ 	sysfs_remove_group(&dev->kobj, &dev_attr_grp);
+ }
+ 
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index b0a35f45b099..08b5a04e3755 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -66,11 +66,13 @@ static inline void usb_pm_unlock(struct usb_device *udev) {}
+ #ifdef CONFIG_USB_SUSPEND
+ 
+ extern void usb_autosuspend_device(struct usb_device *udev);
++extern void usb_try_autosuspend_device(struct usb_device *udev);
+ extern int usb_autoresume_device(struct usb_device *udev);
+ 
+ #else
+ 
+-#define usb_autosuspend_device(udev)	do {} while (0)
++#define usb_autosuspend_device(udev)		do {} while (0)
++#define usb_try_autosuspend_device(udev)	do {} while (0)
+ static inline int usb_autoresume_device(struct usb_device *udev)
+ {
+ 	return 0;

commit dfa87c824a9a5430008acd1ed2e8111ed164fcbe
+Author: Alan Stern 
+Date:   Tue Feb 20 15:02:44 2007 -0500
+
+    sysfs: allow attributes to be added to groups
+    
+    This patch (as860) adds two new sysfs routines:
+    sysfs_add_file_to_group() and sysfs_remove_file_from_group().
+    A later patch adds code that uses the new routines.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Maneesh Soni 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
+index 98b0910ad80c..8d4d839a9d88 100644
+--- a/fs/sysfs/file.c
++++ b/fs/sysfs/file.c
+@@ -501,6 +501,30 @@ int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
+ }
+ 
+ 
++/**
++ * sysfs_add_file_to_group - add an attribute file to a pre-existing group.
++ * @kobj: object we're acting for.
++ * @attr: attribute descriptor.
++ * @group: group name.
++ */
++int sysfs_add_file_to_group(struct kobject *kobj,
++		const struct attribute *attr, const char *group)
++{
++	struct dentry *dir;
++	int error;
++
++	dir = lookup_one_len(group, kobj->dentry, strlen(group));
++	if (IS_ERR(dir))
++		error = PTR_ERR(dir);
++	else {
++		error = sysfs_add_file(dir, attr, SYSFS_KOBJ_ATTR);
++		dput(dir);
++	}
++	return error;
++}
++EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
++
++
+ /**
+  * sysfs_update_file - update the modified timestamp on an object attribute.
+  * @kobj: object we're acting for.
+@@ -586,6 +610,26 @@ void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
+ }
+ 
+ 
++/**
++ * sysfs_remove_file_from_group - remove an attribute file from a group.
++ * @kobj: object we're acting for.
++ * @attr: attribute descriptor.
++ * @group: group name.
++ */
++void sysfs_remove_file_from_group(struct kobject *kobj,
++		const struct attribute *attr, const char *group)
++{
++	struct dentry *dir;
++
++	dir = lookup_one_len(group, kobj->dentry, strlen(group));
++	if (!IS_ERR(dir)) {
++		sysfs_hash_and_remove(dir, attr->name);
++		dput(dir);
++	}
++}
++EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group);
++
++
+ EXPORT_SYMBOL_GPL(sysfs_create_file);
+ EXPORT_SYMBOL_GPL(sysfs_remove_file);
+ EXPORT_SYMBOL_GPL(sysfs_update_file);
+diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
+index 192de3afa96b..f45450b295c0 100644
+--- a/include/linux/sysfs.h
++++ b/include/linux/sysfs.h
+@@ -126,6 +126,11 @@ void sysfs_remove_bin_file(struct kobject *kobj, struct bin_attribute *attr);
+ int __must_check sysfs_create_group(struct kobject *,
+ 					const struct attribute_group *);
+ void sysfs_remove_group(struct kobject *, const struct attribute_group *);
++int sysfs_add_file_to_group(struct kobject *kobj,
++		const struct attribute *attr, const char *group);
++void sysfs_remove_file_from_group(struct kobject *kobj,
++		const struct attribute *attr, const char *group);
++
+ void sysfs_notify(struct kobject * k, char *dir, char *attr);
+ 
+ 
+@@ -210,6 +215,18 @@ static inline void sysfs_remove_group(struct kobject * k, const struct attribute
+ 	;
+ }
+ 
++static inline int sysfs_add_file_to_group(struct kobject *kobj,
++		const struct attribute *attr, const char *group)
++{
++	return 0;
++}
++
++static inline void sysfs_remove_file_from_group(struct kobject *kobj,
++		const struct attribute *attr, const char *group);
++{
++	;
++}
++
+ static inline void sysfs_notify(struct kobject * k, char *dir, char *attr)
+ {
+ }

commit b5e795f8df42936590ba9c606edc715fe3593284
+Author: Alan Stern 
+Date:   Tue Feb 20 15:00:53 2007 -0500
+
+    USB: make autosuspend delay a module parameter
+    
+    This patch (as859) makes the default USB autosuspend delay a module
+    parameter of usbcore.  By setting the delay value at boot time, users
+    will be able to prevent the system from autosuspending devices which
+    for some reason can't handle it.
+    
+    The patch also stores the autosuspend delay as a per-device value.  A
+    later patch will allow the user to change the value, tailoring the
+    delay for each individual device.  A delay value of 0 will prevent
+    autosuspend.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
+index c479d30eeaa3..03eb5ed503f7 100644
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -1758,6 +1758,13 @@ and is between 256 and 4096 characters. It is defined in the file
+ 			Note that genuine overcurrent events won't be
+ 			reported either.
+ 
++	usbcore.autosuspend=
++			[USB] The autosuspend time delay (in seconds) used
++			for newly-detected USB devices (default 2).  This
++			is the time required before an idle device will be
++			autosuspended.  Devices for which the delay is set
++			to 0 won't be autosuspended at all.
++
+ 	usbhid.mousepoll=
+ 			[USBHID] The interval which mice are to be polled at.
+ 
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index f9196a0a9412..a420d72a0254 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -963,12 +963,16 @@ static int autosuspend_check(struct usb_device *udev)
+ 	int			i;
+ 	struct usb_interface	*intf;
+ 
+-	/* For autosuspend, fail fast if anything is in use.
+-	 * Also fail if any interfaces require remote wakeup but it
+-	 * isn't available. */
++	/* For autosuspend, fail fast if anything is in use or autosuspend
++	 * is disabled.  Also fail if any interfaces require remote wakeup
++	 * but it isn't available.
++	 */
+ 	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
+ 	if (udev->pm_usage_cnt > 0)
+ 		return -EBUSY;
++	if (!udev->autosuspend_delay)
++		return -EPERM;
++
+ 	if (udev->actconfig) {
+ 		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+ 			intf = udev->actconfig->interface[i];
+@@ -991,7 +995,7 @@ static int autosuspend_check(struct usb_device *udev)
+ 
+ #define autosuspend_check(udev)		0
+ 
+-#endif
++#endif	/* CONFIG_USB_SUSPEND */
+ 
+ /**
+  * usb_suspend_both - suspend a USB device and its interfaces
+@@ -1186,7 +1190,7 @@ static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt)
+ 			udev->pm_usage_cnt -= inc_usage_cnt;
+ 	} else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
+ 		queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+-				USB_AUTOSUSPEND_DELAY);
++				udev->autosuspend_delay);
+ 	usb_pm_unlock(udev);
+ 	return status;
+ }
+@@ -1270,7 +1274,7 @@ static int usb_autopm_do_interface(struct usb_interface *intf,
+ 				intf->pm_usage_cnt -= inc_usage_cnt;
+ 		} else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
+ 			queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+-					USB_AUTOSUSPEND_DELAY);
++					udev->autosuspend_delay);
+ 	}
+ 	usb_pm_unlock(udev);
+ 	return status;
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index ea0e48e9f611..0e5c646cb4f6 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -39,8 +39,10 @@ static const struct usb_device_id usb_quirk_list[] = {
+ 
+ static void usb_autosuspend_quirk(struct usb_device *udev)
+ {
+-	/* unbalanced resume to prevent autosuspends */
+-	usb_autoresume_device(udev);
++#ifdef	CONFIG_USB_SUSPEND
++	/* disable autosuspend, but allow the user to re-enable it via sysfs */
++	udev->autosuspend_delay = 0;
++#endif
+ }
+ 
+ static const struct usb_device_id *find_id(struct usb_device *udev)
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 3db721cd557a..54b42ce311c1 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -22,6 +22,7 @@
+  */
+ 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -50,6 +51,16 @@ static int nousb;	/* Disable USB when built into kernel image */
+ 
+ struct workqueue_struct *ksuspend_usb_wq;	/* For autosuspend */
+ 
++#ifdef	CONFIG_USB_SUSPEND
++static int usb_autosuspend_delay = 2;		/* Default delay value,
++						 * in seconds */
++module_param_named(autosuspend, usb_autosuspend_delay, uint, 0644);
++MODULE_PARM_DESC(autosuspend, "default autosuspend delay");
++
++#else
++#define usb_autosuspend_delay		0
++#endif
++
+ 
+ /**
+  * usb_ifnum_to_if - get the interface object with a given interface number
+@@ -306,6 +317,7 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
+ #ifdef	CONFIG_PM
+ 	mutex_init(&dev->pm_mutex);
+ 	INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work);
++	dev->autosuspend_delay = usb_autosuspend_delay * HZ;
+ #endif
+ 	return dev;
+ }
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 045cbd111887..b0a35f45b099 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -65,8 +65,6 @@ static inline void usb_pm_unlock(struct usb_device *udev) {}
+ 
+ #ifdef CONFIG_USB_SUSPEND
+ 
+-#define USB_AUTOSUSPEND_DELAY	(HZ*2)
+-
+ extern void usb_autosuspend_device(struct usb_device *udev);
+ extern int usb_autoresume_device(struct usb_device *udev);
+ 
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 37e522eba47f..87dc75a6cee1 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -389,10 +389,13 @@ struct usb_device {
+ 
+ 	int pm_usage_cnt;		/* usage counter for autosuspend */
+ 	u32 quirks;			/* quirks of the whole device */
++
+ #ifdef CONFIG_PM
+ 	struct delayed_work autosuspend; /* for delayed autosuspends */
+ 	struct mutex pm_mutex;		/* protects PM operations */
+ 
++	unsigned autosuspend_delay;	/* in jiffies */
++
+ 	unsigned auto_pm:1;		/* autosuspend/resume in progress */
+ 	unsigned do_remote_wakeup:1;	/* remote wakeup should be enabled */
+ #endif

commit aa084f3efe5fb7e9c0d5b54ce704f0de69bbf27c
+Author: Alan Stern 
+Date:   Tue Feb 20 14:59:59 2007 -0500
+
+    USB: minor cleanups for sysfs.c
+    
+    This patch (as858) makes some minor cleanups to sysfs.c in usbcore.
+    Unnecessary tests are removed and a few temp variables are added.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 8f5a764057cd..cad4fb323f6c 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -250,10 +250,7 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
+ 		goto error;
+ 	return 0;
+ error:
+-	usb_remove_ep_files(&udev->ep0);
+-	device_remove_file(dev, &dev_attr_manufacturer);
+-	device_remove_file(dev, &dev_attr_product);
+-	device_remove_file(dev, &dev_attr_serial);
++	usb_remove_sysfs_dev_files(udev);
+ 	return retval;
+ }
+ 
+@@ -262,14 +259,10 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)
+ 	struct device *dev = &udev->dev;
+ 
+ 	usb_remove_ep_files(&udev->ep0);
++	device_remove_file(dev, &dev_attr_manufacturer);
++	device_remove_file(dev, &dev_attr_product);
++	device_remove_file(dev, &dev_attr_serial);
+ 	sysfs_remove_group(&dev->kobj, &dev_attr_grp);
+-
+-	if (udev->manufacturer)
+-		device_remove_file(dev, &dev_attr_manufacturer);
+-	if (udev->product)
+-		device_remove_file(dev, &dev_attr_product);
+-	if (udev->serial)
+-		device_remove_file(dev, &dev_attr_serial);
+ }
+ 
+ /* Interface fields */
+@@ -373,33 +366,28 @@ static inline void usb_remove_intf_ep_files(struct usb_interface *intf)
+ 
+ int usb_create_sysfs_intf_files(struct usb_interface *intf)
+ {
++	struct device *dev = &intf->dev;
+ 	struct usb_device *udev = interface_to_usbdev(intf);
+ 	struct usb_host_interface *alt = intf->cur_altsetting;
+ 	int retval;
+ 
+-	retval = sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
++	retval = sysfs_create_group(&dev->kobj, &intf_attr_grp);
+ 	if (retval)
+-		goto error;
++		return retval;
+ 
+ 	if (alt->string == NULL)
+ 		alt->string = usb_cache_string(udev, alt->desc.iInterface);
+ 	if (alt->string)
+-		retval = device_create_file(&intf->dev, &dev_attr_interface);
++		retval = device_create_file(dev, &dev_attr_interface);
+ 	usb_create_intf_ep_files(intf, udev);
+ 	return 0;
+-error:
+-	if (alt->string)
+-		device_remove_file(&intf->dev, &dev_attr_interface);
+-	sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp);
+-	usb_remove_intf_ep_files(intf);
+-	return retval;
+ }
+ 
+ void usb_remove_sysfs_intf_files(struct usb_interface *intf)
+ {
+-	usb_remove_intf_ep_files(intf);
+-	sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp);
++	struct device *dev = &intf->dev;
+ 
+-	if (intf->cur_altsetting->string)
+-		device_remove_file(&intf->dev, &dev_attr_interface);
++	usb_remove_intf_ep_files(intf);
++	device_remove_file(dev, &dev_attr_interface);
++	sysfs_remove_group(&dev->kobj, &intf_attr_grp);
+ }

commit 17230acdc71137622ca7dfd789b3944c75d39404
+Author: Alan Stern 
+Date:   Mon Feb 19 15:52:45 2007 -0500
+
+    UHCI: Eliminate asynchronous skeleton Queue Headers
+    
+    This patch (as856) attempts to improve the performance of uhci-hcd by
+    removing the asynchronous skeleton Queue Headers.  They don't contain
+    any useful information but the controller has to read through them at
+    least once every millisecond, incurring a non-zero DMA overhead.
+    
+    Now all the asynchronous queues are combined, along with the period-1
+    interrupt queue, into a single list with a single skeleton QH.  The
+    start of the low-speed control, full-speed control, and bulk sublists
+    is determined by linear search.  Since there should rarely be more
+    than a couple of QHs in the list, the searches should incur a much
+    smaller total load than keeping the skeleton QHs.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
+index a0677133577b..8d24d3dc0a61 100644
+--- a/drivers/usb/host/uhci-debug.c
++++ b/drivers/usb/host/uhci-debug.c
+@@ -220,16 +220,6 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
+ 	return out - buf;
+ }
+ 
+-static const char * const qh_names[] = {
+-  "skel_unlink_qh", "skel_iso_qh",
+-  "skel_int128_qh", "skel_int64_qh",
+-  "skel_int32_qh", "skel_int16_qh",
+-  "skel_int8_qh", "skel_int4_qh",
+-  "skel_int2_qh", "skel_int1_qh",
+-  "skel_ls_control_qh", "skel_fs_control_qh",
+-  "skel_bulk_qh", "skel_term_qh"
+-};
+-
+ static int uhci_show_sc(int port, unsigned short status, char *buf, int len)
+ {
+ 	char *out = buf;
+@@ -352,6 +342,12 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
+ 	struct uhci_td *td;
+ 	struct list_head *tmp, *head;
+ 	int nframes, nerrs;
++	__le32 link;
++
++	static const char * const qh_names[] = {
++		"unlink", "iso", "int128", "int64", "int32", "int16",
++		"int8", "int4", "int2", "async", "term"
++	};
+ 
+ 	out += uhci_show_root_hub_state(uhci, out, len - (out - buf));
+ 	out += sprintf(out, "HC status\n");
+@@ -374,7 +370,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
+ 	nframes = 10;
+ 	nerrs = 0;
+ 	for (i = 0; i < UHCI_NUMFRAMES; ++i) {
+-		__le32 link, qh_dma;
++		__le32 qh_dma;
+ 
+ 		j = 0;
+ 		td = uhci->frame_cpu[i];
+@@ -430,23 +426,21 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
+ 
+ 	for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
+ 		int cnt = 0;
++		__le32 fsbr_link = 0;
+ 
+ 		qh = uhci->skelqh[i];
+-		out += sprintf(out, "- %s\n", qh_names[i]); \
++		out += sprintf(out, "- skel_%s_qh\n", qh_names[i]); \
+ 		out += uhci_show_qh(qh, out, len - (out - buf), 4);
+ 
+ 		/* Last QH is the Terminating QH, it's different */
+-		if (i == UHCI_NUM_SKELQH - 1) {
+-			if (qh->link != UHCI_PTR_TERM)
+-				out += sprintf(out, "    bandwidth reclamation on!\n");
+-
++		if (i == SKEL_TERM) {
+ 			if (qh_element(qh) != LINK_TO_TD(uhci->term_td))
+ 				out += sprintf(out, "    skel_term_qh element is not set to term_td!\n");
+-
++			if (link == LINK_TO_QH(uhci->skel_term_qh))
++				goto check_qh_link;
+ 			continue;
+ 		}
+ 
+-		j = (i < 9) ? 9 : i+1;		/* Next skeleton */
+ 		head = &qh->node;
+ 		tmp = head->next;
+ 
+@@ -456,14 +450,26 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
+ 			if (++cnt <= 10)
+ 				out += uhci_show_qh(qh, out,
+ 						len - (out - buf), 4);
++			if (!fsbr_link && qh->skel >= SKEL_FSBR)
++				fsbr_link = LINK_TO_QH(qh);
+ 		}
+ 		if ((cnt -= 10) > 0)
+ 			out += sprintf(out, "    Skipped %d QHs\n", cnt);
+ 
+-		if (i > 1 && i < UHCI_NUM_SKELQH - 1) {
+-			if (qh->link != LINK_TO_QH(uhci->skelqh[j]))
+-				out += sprintf(out, "    last QH not linked to next skeleton!\n");
+-		}
++		link = UHCI_PTR_TERM;
++		if (i <= SKEL_ISO)
++			;
++		else if (i < SKEL_ASYNC)
++			link = LINK_TO_QH(uhci->skel_async_qh);
++		else if (!uhci->fsbr_is_on)
++			;
++		else if (fsbr_link)
++			link = fsbr_link;
++		else
++			link = LINK_TO_QH(uhci->skel_term_qh);
++check_qh_link:
++		if (qh->link != link)
++			out += sprintf(out, "    last QH not linked to next skeleton!\n");
+ 	}
+ 
+ 	return out - buf;
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 1f0833ab294a..44da4334f1d6 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -13,7 +13,7 @@
+  * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
+  *               support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
+  * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
+- * (C) Copyright 2004-2006 Alan Stern, stern@rowland.harvard.edu
++ * (C) Copyright 2004-2007 Alan Stern, stern@rowland.harvard.edu
+  *
+  * Intel documents this fairly well, and as far as I know there
+  * are no royalties or anything like that, but even so there are
+@@ -107,10 +107,10 @@ static __le32 uhci_frame_skel_link(struct uhci_hcd *uhci, int frame)
+ 	 * interrupt QHs, which will help spread out bandwidth utilization.
+ 	 *
+ 	 * ffs (Find First bit Set) does exactly what we need:
+-	 * 1,3,5,...  => ffs = 0 => use skel_int2_qh = skelqh[8],
+-	 * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[7], etc.
++	 * 1,3,5,...  => ffs = 0 => use period-2 QH = skelqh[8],
++	 * 2,6,10,... => ffs = 1 => use period-4 QH = skelqh[7], etc.
+ 	 * ffs >= 7 => not on any high-period queue, so use
+-	 *	skel_int1_qh = skelqh[9].
++	 *	period-1 QH = skelqh[9].
+ 	 * Add in UHCI_NUMFRAMES to insure at least one bit is set.
+ 	 */
+ 	skelnum = 8 - (int) __ffs(frame | UHCI_NUMFRAMES);
+@@ -540,16 +540,18 @@ static void uhci_shutdown(struct pci_dev *pdev)
+  *
+  * The hardware doesn't really know any difference
+  * in the queues, but the order does matter for the
+- * protocols higher up. The order is:
++ * protocols higher up.  The order in which the queues
++ * are encountered by the hardware is:
+  *
+- *  - any isochronous events handled before any
++ *  - All isochronous events are handled before any
+  *    of the queues. We don't do that here, because
+  *    we'll create the actual TD entries on demand.
+- *  - The first queue is the interrupt queue.
+- *  - The second queue is the control queue, split into low- and full-speed
+- *  - The third queue is bulk queue.
+- *  - The fourth queue is the bandwidth reclamation queue, which loops back
+- *    to the full-speed control queue.
++ *  - The first queue is the high-period interrupt queue.
++ *  - The second queue is the period-1 interrupt and async
++ *    (low-speed control, full-speed control, then bulk) queue.
++ *  - The third queue is the terminating bandwidth reclamation queue,
++ *    which contains no members, loops back to itself, and is present
++ *    only when FSBR is on and there are no full-speed control or bulk QHs.
+  */
+ static int uhci_start(struct usb_hcd *hcd)
+ {
+@@ -626,30 +628,18 @@ static int uhci_start(struct usb_hcd *hcd)
+ 	}
+ 
+ 	/*
+-	 * 8 Interrupt queues; link all higher int queues to int1,
+-	 * then link int1 to control and control to bulk
++	 * 8 Interrupt queues; link all higher int queues to int1 = async
+ 	 */
+-	uhci->skel_int128_qh->link =
+-			uhci->skel_int64_qh->link =
+-			uhci->skel_int32_qh->link =
+-			uhci->skel_int16_qh->link =
+-			uhci->skel_int8_qh->link =
+-			uhci->skel_int4_qh->link =
+-			uhci->skel_int2_qh->link = LINK_TO_QH(
+-				uhci->skel_int1_qh);
+-
+-	uhci->skel_int1_qh->link = LINK_TO_QH(uhci->skel_ls_control_qh);
+-	uhci->skel_ls_control_qh->link = LINK_TO_QH(uhci->skel_fs_control_qh);
+-	uhci->skel_fs_control_qh->link = LINK_TO_QH(uhci->skel_bulk_qh);
+-	uhci->skel_bulk_qh->link = LINK_TO_QH(uhci->skel_term_qh);
++	for (i = SKEL_ISO + 1; i < SKEL_ASYNC; ++i)
++		uhci->skelqh[i]->link = LINK_TO_QH(uhci->skel_async_qh);
++	uhci->skel_async_qh->link = uhci->skel_term_qh->link = UHCI_PTR_TERM;
+ 
+ 	/* This dummy TD is to work around a bug in Intel PIIX controllers */
+ 	uhci_fill_td(uhci->term_td, 0, uhci_explen(0) |
+-		(0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0);
+-	uhci->term_td->link = LINK_TO_TD(uhci->term_td);
+-
+-	uhci->skel_term_qh->link = UHCI_PTR_TERM;
+-	uhci->skel_term_qh->element = LINK_TO_TD(uhci->term_td);
++			(0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0);
++	uhci->term_td->link = UHCI_PTR_TERM;
++	uhci->skel_async_qh->element = uhci->skel_term_qh->element =
++			LINK_TO_TD(uhci->term_td);
+ 
+ 	/*
+ 	 * Fill the frame list: make all entries point to the proper
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index a8c256b44d8e..1b3d23406ac4 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -135,7 +135,6 @@ struct uhci_qh {
+ 	struct usb_host_endpoint *hep;	/* Endpoint information */
+ 	struct usb_device *udev;
+ 	struct list_head queue;		/* Queue of urbps for this QH */
+-	struct uhci_qh *skel;		/* Skeleton for this QH */
+ 	struct uhci_td *dummy_td;	/* Dummy TD to end the queue */
+ 	struct uhci_td *post_td;	/* Last TD completed */
+ 
+@@ -151,6 +150,7 @@ struct uhci_qh {
+ 
+ 	int state;			/* QH_STATE_xxx; see above */
+ 	int type;			/* Queue type (control, bulk, etc) */
++	int skel;			/* Skeleton queue number */
+ 
+ 	unsigned int initial_toggle:1;	/* Endpoint's current toggle value */
+ 	unsigned int needs_fixup:1;	/* Must fix the TD toggle values */
+@@ -276,12 +276,13 @@ static inline u32 td_status(struct uhci_td *td) {
+ /*
+  * The UHCI driver uses QHs with Interrupt, Control and Bulk URBs for
+  * automatic queuing. To make it easy to insert entries into the schedule,
+- * we have a skeleton of QHs for each predefined Interrupt latency,
+- * low-speed control, full-speed control, bulk, and terminating QH
+- * (see explanation for the terminating QH below).
++ * we have a skeleton of QHs for each predefined Interrupt latency.
++ * Asynchronous QHs (low-speed control, full-speed control, and bulk)
++ * go onto the period-1 interrupt list, since they all get accessed on
++ * every frame.
+  *
+- * When we want to add a new QH, we add it to the end of the list for the
+- * skeleton QH.  For instance, the schedule list can look like this:
++ * When we want to add a new QH, we add it to the list starting from the
++ * appropriate skeleton QH.  For instance, the schedule can look like this:
+  *
+  * skel int128 QH
+  * dev 1 interrupt QH
+@@ -289,50 +290,47 @@ static inline u32 td_status(struct uhci_td *td) {
+  * skel int64 QH
+  * skel int32 QH
+  * ...
+- * skel int1 QH
+- * skel low-speed control QH
+- * dev 5 control QH
+- * skel full-speed control QH
+- * skel bulk QH
++ * skel int1 + async QH
++ * dev 5 low-speed control QH
+  * dev 1 bulk QH
+  * dev 2 bulk QH
+- * skel terminating QH
+  *
+- * The terminating QH is used for 2 reasons:
+- * - To place a terminating TD which is used to workaround a PIIX bug
+- *   (see Intel errata for explanation), and
+- * - To loop back to the full-speed control queue for full-speed bandwidth
+- *   reclamation.
++ * There is a special terminating QH used to keep full-speed bandwidth
++ * reclamation active when no full-speed control or bulk QHs are linked
++ * into the schedule.  It has an inactive TD (to work around a PIIX bug,
++ * see the Intel errata) and it points back to itself.
+  *
+- * There's a special skeleton QH for Isochronous QHs.  It never appears
+- * on the schedule, and Isochronous TDs go on the schedule before the
++ * There's a special skeleton QH for Isochronous QHs which never appears
++ * on the schedule.  Isochronous TDs go on the schedule before the
+  * the skeleton QHs.  The hardware accesses them directly rather than
+  * through their QH, which is used only for bookkeeping purposes.
+  * While the UHCI spec doesn't forbid the use of QHs for Isochronous,
+  * it doesn't use them either.  And the spec says that queues never
+  * advance on an error completion status, which makes them totally
+  * unsuitable for Isochronous transfers.
++ *
++ * There's also a special skeleton QH used for QHs which are in the process
++ * of unlinking and so may still be in use by the hardware.  It too never
++ * appears on the schedule.
+  */
+ 
+-#define UHCI_NUM_SKELQH		14
+-#define skel_unlink_qh		skelqh[0]
+-#define skel_iso_qh		skelqh[1]
+-#define skel_int128_qh		skelqh[2]
+-#define skel_int64_qh		skelqh[3]
+-#define skel_int32_qh		skelqh[4]
+-#define skel_int16_qh		skelqh[5]
+-#define skel_int8_qh		skelqh[6]
+-#define skel_int4_qh		skelqh[7]
+-#define skel_int2_qh		skelqh[8]
+-#define skel_int1_qh		skelqh[9]
+-#define skel_ls_control_qh	skelqh[10]
+-#define skel_fs_control_qh	skelqh[11]
+-#define skel_bulk_qh		skelqh[12]
+-#define skel_term_qh		skelqh[13]
+-
+-/* Find the skelqh entry corresponding to an interval exponent */
+-#define UHCI_SKEL_INDEX(exponent)	(9 - exponent)
+-
++#define UHCI_NUM_SKELQH		11
++#define SKEL_UNLINK		0
++#define skel_unlink_qh		skelqh[SKEL_UNLINK]
++#define SKEL_ISO		1
++#define skel_iso_qh		skelqh[SKEL_ISO]
++	/* int128, int64, ..., int1 = 2, 3, ..., 9 */
++#define SKEL_INDEX(exponent)	(9 - exponent)
++#define SKEL_ASYNC		9
++#define skel_async_qh		skelqh[SKEL_ASYNC]
++#define SKEL_TERM		10
++#define skel_term_qh		skelqh[SKEL_TERM]
++
++/* The following entries refer to sublists of skel_async_qh */
++#define SKEL_LS_CONTROL		20
++#define SKEL_FS_CONTROL		21
++#define SKEL_FSBR		SKEL_FS_CONTROL
++#define SKEL_BULK		22
+ 
+ /*
+  *	The UHCI controller and root hub
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index a0c6bf6128a3..f4ebdb3e488f 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -13,7 +13,7 @@
+  * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
+  *               support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
+  * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
+- * (C) Copyright 2004-2006 Alan Stern, stern@rowland.harvard.edu
++ * (C) Copyright 2004-2007 Alan Stern, stern@rowland.harvard.edu
+  */
+ 
+ 
+@@ -45,14 +45,43 @@ static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci)
+  */
+ static void uhci_fsbr_on(struct uhci_hcd *uhci)
+ {
++	struct uhci_qh *fsbr_qh, *lqh, *tqh;
++
+ 	uhci->fsbr_is_on = 1;
+-	uhci->skel_term_qh->link = LINK_TO_QH(uhci->skel_fs_control_qh);
++	lqh = list_entry(uhci->skel_async_qh->node.prev,
++			struct uhci_qh, node);
++
++	/* Find the first FSBR QH.  Linear search through the list is
++	 * acceptable because normally FSBR gets turned on as soon as
++	 * one QH needs it. */
++	fsbr_qh = NULL;
++	list_for_each_entry_reverse(tqh, &uhci->skel_async_qh->node, node) {
++		if (tqh->skel < SKEL_FSBR)
++			break;
++		fsbr_qh = tqh;
++	}
++
++	/* No FSBR QH means we must insert the terminating skeleton QH */
++	if (!fsbr_qh) {
++		uhci->skel_term_qh->link = LINK_TO_QH(uhci->skel_term_qh);
++		wmb();
++		lqh->link = uhci->skel_term_qh->link;
++
++	/* Otherwise loop the last QH to the first FSBR QH */
++	} else
++		lqh->link = LINK_TO_QH(fsbr_qh);
+ }
+ 
+ static void uhci_fsbr_off(struct uhci_hcd *uhci)
+ {
++	struct uhci_qh *lqh;
++
+ 	uhci->fsbr_is_on = 0;
+-	uhci->skel_term_qh->link = UHCI_PTR_TERM;
++	lqh = list_entry(uhci->skel_async_qh->node.prev,
++			struct uhci_qh, node);
++
++	/* End the async list normally and unlink the terminating QH */
++	lqh->link = uhci->skel_term_qh->link = UHCI_PTR_TERM;
+ }
+ 
+ static void uhci_add_fsbr(struct uhci_hcd *uhci, struct urb *urb)
+@@ -404,12 +433,81 @@ static void uhci_fixup_toggles(struct uhci_qh *qh, int skip_first)
+ }
+ 
+ /*
+- * Put a QH on the schedule in both hardware and software
++ * Link an Isochronous QH into its skeleton's list
+  */
+-static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
++static inline void link_iso(struct uhci_hcd *uhci, struct uhci_qh *qh)
++{
++	list_add_tail(&qh->node, &uhci->skel_iso_qh->node);
++
++	/* Isochronous QHs aren't linked by the hardware */
++}
++
++/*
++ * Link a high-period interrupt QH into the schedule at the end of its
++ * skeleton's list
++ */
++static void link_interrupt(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ {
+ 	struct uhci_qh *pqh;
+ 
++	list_add_tail(&qh->node, &uhci->skelqh[qh->skel]->node);
++
++	pqh = list_entry(qh->node.prev, struct uhci_qh, node);
++	qh->link = pqh->link;
++	wmb();
++	pqh->link = LINK_TO_QH(qh);
++}
++
++/*
++ * Link a period-1 interrupt or async QH into the schedule at the
++ * correct spot in the async skeleton's list, and update the FSBR link
++ */
++static void link_async(struct uhci_hcd *uhci, struct uhci_qh *qh)
++{
++	struct uhci_qh *pqh, *lqh;
++	__le32 link_to_new_qh;
++	__le32 *extra_link = &link_to_new_qh;
++
++	/* Find the predecessor QH for our new one and insert it in the list.
++	 * The list of QHs is expected to be short, so linear search won't
++	 * take too long. */
++	list_for_each_entry_reverse(pqh, &uhci->skel_async_qh->node, node) {
++		if (pqh->skel <= qh->skel)
++			break;
++	}
++	list_add(&qh->node, &pqh->node);
++	qh->link = pqh->link;
++
++	link_to_new_qh = LINK_TO_QH(qh);
++
++	/* If this is now the first FSBR QH, take special action */
++	if (uhci->fsbr_is_on && pqh->skel < SKEL_FSBR &&
++			qh->skel >= SKEL_FSBR) {
++		lqh = list_entry(uhci->skel_async_qh->node.prev,
++				struct uhci_qh, node);
++
++		/* If the new QH is also the last one, we must unlink
++		 * the terminating skeleton QH and make the new QH point
++		 * back to itself. */
++		if (qh == lqh) {
++			qh->link = link_to_new_qh;
++			extra_link = &uhci->skel_term_qh->link;
++
++		/* Otherwise the last QH must point to the new QH */
++		} else
++			extra_link = &lqh->link;
++	}
++
++	/* Link it into the schedule */
++	wmb();
++	*extra_link = pqh->link = link_to_new_qh;
++}
++
++/*
++ * Put a QH on the schedule in both hardware and software
++ */
++static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
++{
+ 	WARN_ON(list_empty(&qh->queue));
+ 
+ 	/* Set the element pointer if it isn't set already.
+@@ -431,18 +529,64 @@ static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ 		return;
+ 	qh->state = QH_STATE_ACTIVE;
+ 
+-	/* Move the QH from its old list to the end of the appropriate
++	/* Move the QH from its old list to the correct spot in the appropriate
+ 	 * skeleton's list */
+ 	if (qh == uhci->next_qh)
+ 		uhci->next_qh = list_entry(qh->node.next, struct uhci_qh,
+ 				node);
+-	list_move_tail(&qh->node, &qh->skel->node);
++	list_del(&qh->node);
++
++	if (qh->skel == SKEL_ISO)
++		link_iso(uhci, qh);
++	else if (qh->skel < SKEL_ASYNC)
++		link_interrupt(uhci, qh);
++	else
++		link_async(uhci, qh);
++}
++
++/*
++ * Unlink a high-period interrupt QH from the schedule
++ */
++static void unlink_interrupt(struct uhci_hcd *uhci, struct uhci_qh *qh)
++{
++	struct uhci_qh *pqh;
+ 
+-	/* Link it into the schedule */
+ 	pqh = list_entry(qh->node.prev, struct uhci_qh, node);
+-	qh->link = pqh->link;
+-	wmb();
+-	pqh->link = LINK_TO_QH(qh);
++	pqh->link = qh->link;
++	mb();
++}
++
++/*
++ * Unlink a period-1 interrupt or async QH from the schedule
++ */
++static void unlink_async(struct uhci_hcd *uhci, struct uhci_qh *qh)
++{
++	struct uhci_qh *pqh, *lqh;
++	__le32 link_to_next_qh = qh->link;
++
++	pqh = list_entry(qh->node.prev, struct uhci_qh, node);
++
++	/* If this is the first FSBQ QH, take special action */
++	if (uhci->fsbr_is_on && pqh->skel < SKEL_FSBR &&
++			qh->skel >= SKEL_FSBR) {
++		lqh = list_entry(uhci->skel_async_qh->node.prev,
++				struct uhci_qh, node);
++
++		/* If this QH is also the last one, we must link in
++		 * the terminating skeleton QH. */
++		if (qh == lqh) {
++			link_to_next_qh = LINK_TO_QH(uhci->skel_term_qh);
++			uhci->skel_term_qh->link = link_to_next_qh;
++			wmb();
++			qh->link = link_to_next_qh;
++
++		/* Otherwise the last QH must point to the new first FSBR QH */
++		} else
++			lqh->link = link_to_next_qh;
++	}
++
++	pqh->link = link_to_next_qh;
++	mb();
+ }
+ 
+ /*
+@@ -450,17 +594,18 @@ static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+  */
+ static void uhci_unlink_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ {
+-	struct uhci_qh *pqh;
+-
+ 	if (qh->state == QH_STATE_UNLINKING)
+ 		return;
+ 	WARN_ON(qh->state != QH_STATE_ACTIVE || !qh->udev);
+ 	qh->state = QH_STATE_UNLINKING;
+ 
+ 	/* Unlink the QH from the schedule and record when we did it */
+-	pqh = list_entry(qh->node.prev, struct uhci_qh, node);
+-	pqh->link = qh->link;
+-	mb();
++	if (qh->skel == SKEL_ISO)
++		;
++	else if (qh->skel < SKEL_ASYNC)
++		unlink_interrupt(uhci, qh);
++	else
++		unlink_async(uhci, qh);
+ 
+ 	uhci_get_current_frame_number(uhci);
+ 	qh->unlink_frame = uhci->frame_number;
+@@ -696,6 +841,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
+ 	dma_addr_t data = urb->transfer_dma;
+ 	__le32 *plink;
+ 	struct urb_priv *urbp = urb->hcpriv;
++	int skel;
+ 
+ 	/* The "pipe" thing contains the destination in bits 8--18 */
+ 	destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
+@@ -796,11 +942,13 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
+ 	 * isn't in the CONFIGURED state. */
+ 	if (urb->dev->speed == USB_SPEED_LOW ||
+ 			urb->dev->state != USB_STATE_CONFIGURED)
+-		qh->skel = uhci->skel_ls_control_qh;
++		skel = SKEL_LS_CONTROL;
+ 	else {
+-		qh->skel = uhci->skel_fs_control_qh;
++		skel = SKEL_FS_CONTROL;
+ 		uhci_add_fsbr(uhci, urb);
+ 	}
++	if (qh->state != QH_STATE_ACTIVE)
++		qh->skel = skel;
+ 
+ 	urb->actual_length = -8;	/* Account for the SETUP packet */
+ 	return 0;
+@@ -930,7 +1078,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
+ 	return -ENOMEM;
+ }
+ 
+-static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb,
++static int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb,
+ 		struct uhci_qh *qh)
+ {
+ 	int ret;
+@@ -939,7 +1087,8 @@ static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb,
+ 	if (urb->dev->speed == USB_SPEED_LOW)
+ 		return -EINVAL;
+ 
+-	qh->skel = uhci->skel_bulk_qh;
++	if (qh->state != QH_STATE_ACTIVE)
++		qh->skel = SKEL_BULK;
+ 	ret = uhci_submit_common(uhci, urb, qh);
+ 	if (ret == 0)
+ 		uhci_add_fsbr(uhci, urb);
+@@ -967,7 +1116,7 @@ static int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb,
+ 		if (exponent < 0)
+ 			return -EINVAL;
+ 		qh->period = 1 << exponent;
+-		qh->skel = uhci->skelqh[UHCI_SKEL_INDEX(exponent)];
++		qh->skel = SKEL_INDEX(exponent);
+ 
+ 		/* For now, interrupt phase is fixed by the layout
+ 		 * of the QH lists. */
+@@ -1215,7 +1364,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
+ 		qh->iso_status = 0;
+ 	}
+ 
+-	qh->skel = uhci->skel_iso_qh;
++	qh->skel = SKEL_ISO;
+ 	if (!qh->bandwidth_reserved)
+ 		uhci_reserve_bandwidth(uhci, qh);
+ 	return 0;

commit 28b9325e6ae45ffb5e99fedcafe00f25fcaacf06
+Author: Alan Stern 
+Date:   Mon Feb 19 15:51:51 2007 -0500
+
+    UHCI: Add macros for computing DMA values
+    
+    This patch (as855) adds some convenience macros to uhci-hcd, to help
+    simplify the code for computing hardware DMA pointers.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
+index 5d6c06bc4524..a0677133577b 100644
+--- a/drivers/usb/host/uhci-debug.c
++++ b/drivers/usb/host/uhci-debug.c
+@@ -196,7 +196,7 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
+ 		struct uhci_td *td = list_entry(urbp->td_list.next,
+ 				struct uhci_td, list);
+ 
+-		if (cpu_to_le32(td->dma_handle) != (element & ~UHCI_PTR_BITS))
++		if (element != LINK_TO_TD(td))
+ 			out += sprintf(out, "%*s Element != First TD\n",
+ 					space, "");
+ 		i = nurbs = 0;
+@@ -393,7 +393,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
+ 		do {
+ 			td = list_entry(tmp, struct uhci_td, fl_list);
+ 			tmp = tmp->next;
+-			if (cpu_to_le32(td->dma_handle) != link) {
++			if (link != LINK_TO_TD(td)) {
+ 				if (nframes > 0)
+ 					out += sprintf(out, "    link does "
+ 						"not match list entry!\n");
+@@ -440,7 +440,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
+ 			if (qh->link != UHCI_PTR_TERM)
+ 				out += sprintf(out, "    bandwidth reclamation on!\n");
+ 
+-			if (qh_element(qh) != cpu_to_le32(uhci->term_td->dma_handle))
++			if (qh_element(qh) != LINK_TO_TD(uhci->term_td))
+ 				out += sprintf(out, "    skel_term_qh element is not set to term_td!\n");
+ 
+ 			continue;
+@@ -461,8 +461,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
+ 			out += sprintf(out, "    Skipped %d QHs\n", cnt);
+ 
+ 		if (i > 1 && i < UHCI_NUM_SKELQH - 1) {
+-			if (qh->link !=
+-			    (cpu_to_le32(uhci->skelqh[j]->dma_handle) | UHCI_PTR_QH))
++			if (qh->link != LINK_TO_QH(uhci->skelqh[j]))
+ 				out += sprintf(out, "    last QH not linked to next skeleton!\n");
+ 		}
+ 	}
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index ded4df30a631..1f0833ab294a 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -116,7 +116,7 @@ static __le32 uhci_frame_skel_link(struct uhci_hcd *uhci, int frame)
+ 	skelnum = 8 - (int) __ffs(frame | UHCI_NUMFRAMES);
+ 	if (skelnum <= 1)
+ 		skelnum = 9;
+-	return UHCI_PTR_QH | cpu_to_le32(uhci->skelqh[skelnum]->dma_handle);
++	return LINK_TO_QH(uhci->skelqh[skelnum]);
+ }
+ 
+ #include "uhci-debug.c"
+@@ -635,25 +635,21 @@ static int uhci_start(struct usb_hcd *hcd)
+ 			uhci->skel_int16_qh->link =
+ 			uhci->skel_int8_qh->link =
+ 			uhci->skel_int4_qh->link =
+-			uhci->skel_int2_qh->link = UHCI_PTR_QH |
+-			cpu_to_le32(uhci->skel_int1_qh->dma_handle);
+-
+-	uhci->skel_int1_qh->link = UHCI_PTR_QH |
+-			cpu_to_le32(uhci->skel_ls_control_qh->dma_handle);
+-	uhci->skel_ls_control_qh->link = UHCI_PTR_QH |
+-			cpu_to_le32(uhci->skel_fs_control_qh->dma_handle);
+-	uhci->skel_fs_control_qh->link = UHCI_PTR_QH |
+-			cpu_to_le32(uhci->skel_bulk_qh->dma_handle);
+-	uhci->skel_bulk_qh->link = UHCI_PTR_QH |
+-			cpu_to_le32(uhci->skel_term_qh->dma_handle);
++			uhci->skel_int2_qh->link = LINK_TO_QH(
++				uhci->skel_int1_qh);
++
++	uhci->skel_int1_qh->link = LINK_TO_QH(uhci->skel_ls_control_qh);
++	uhci->skel_ls_control_qh->link = LINK_TO_QH(uhci->skel_fs_control_qh);
++	uhci->skel_fs_control_qh->link = LINK_TO_QH(uhci->skel_bulk_qh);
++	uhci->skel_bulk_qh->link = LINK_TO_QH(uhci->skel_term_qh);
+ 
+ 	/* This dummy TD is to work around a bug in Intel PIIX controllers */
+ 	uhci_fill_td(uhci->term_td, 0, uhci_explen(0) |
+ 		(0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0);
+-	uhci->term_td->link = cpu_to_le32(uhci->term_td->dma_handle);
++	uhci->term_td->link = LINK_TO_TD(uhci->term_td);
+ 
+ 	uhci->skel_term_qh->link = UHCI_PTR_TERM;
+-	uhci->skel_term_qh->element = cpu_to_le32(uhci->term_td->dma_handle);
++	uhci->skel_term_qh->element = LINK_TO_TD(uhci->term_td);
+ 
+ 	/*
+ 	 * Fill the frame list: make all entries point to the proper
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index 74469b5bcb61..a8c256b44d8e 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -129,6 +129,8 @@ struct uhci_qh {
+ 	__le32 element;			/* Queue element (TD) pointer */
+ 
+ 	/* Software fields */
++	dma_addr_t dma_handle;
++
+ 	struct list_head node;		/* Node in the list of QHs */
+ 	struct usb_host_endpoint *hep;	/* Endpoint information */
+ 	struct usb_device *udev;
+@@ -150,8 +152,6 @@ struct uhci_qh {
+ 	int state;			/* QH_STATE_xxx; see above */
+ 	int type;			/* Queue type (control, bulk, etc) */
+ 
+-	dma_addr_t dma_handle;
+-
+ 	unsigned int initial_toggle:1;	/* Endpoint's current toggle value */
+ 	unsigned int needs_fixup:1;	/* Must fix the TD toggle values */
+ 	unsigned int is_stopped:1;	/* Queue was stopped by error/unlink */
+@@ -171,6 +171,8 @@ static inline __le32 qh_element(struct uhci_qh *qh) {
+ 	return element;
+ }
+ 
++#define LINK_TO_QH(qh)		(UHCI_PTR_QH | cpu_to_le32((qh)->dma_handle))
++
+ 
+ /*
+  *	Transfer Descriptors
+@@ -264,6 +266,8 @@ static inline u32 td_status(struct uhci_td *td) {
+ 	return le32_to_cpu(status);
+ }
+ 
++#define LINK_TO_TD(td)		(cpu_to_le32((td)->dma_handle))
++
+ 
+ /*
+  *	Skeleton Queue Headers
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 68e66b33e726..a0c6bf6128a3 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -46,8 +46,7 @@ static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci)
+ static void uhci_fsbr_on(struct uhci_hcd *uhci)
+ {
+ 	uhci->fsbr_is_on = 1;
+-	uhci->skel_term_qh->link = cpu_to_le32(
+-			uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH;
++	uhci->skel_term_qh->link = LINK_TO_QH(uhci->skel_fs_control_qh);
+ }
+ 
+ static void uhci_fsbr_off(struct uhci_hcd *uhci)
+@@ -158,11 +157,11 @@ static inline void uhci_insert_td_in_frame_list(struct uhci_hcd *uhci,
+ 
+ 		td->link = ltd->link;
+ 		wmb();
+-		ltd->link = cpu_to_le32(td->dma_handle);
++		ltd->link = LINK_TO_TD(td);
+ 	} else {
+ 		td->link = uhci->frame[framenum];
+ 		wmb();
+-		uhci->frame[framenum] = cpu_to_le32(td->dma_handle);
++		uhci->frame[framenum] = LINK_TO_TD(td);
+ 		uhci->frame_cpu[framenum] = td;
+ 	}
+ }
+@@ -184,7 +183,7 @@ static inline void uhci_remove_td_from_frame_list(struct uhci_hcd *uhci,
+ 			struct uhci_td *ntd;
+ 
+ 			ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list);
+-			uhci->frame[td->frame] = cpu_to_le32(ntd->dma_handle);
++			uhci->frame[td->frame] = LINK_TO_TD(ntd);
+ 			uhci->frame_cpu[td->frame] = ntd;
+ 		}
+ 	} else {
+@@ -421,7 +420,7 @@ static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ 		struct uhci_td *td = list_entry(urbp->td_list.next,
+ 				struct uhci_td, list);
+ 
+-		qh->element = cpu_to_le32(td->dma_handle);
++		qh->element = LINK_TO_TD(td);
+ 	}
+ 
+ 	/* Treat the queue as if it has just advanced */
+@@ -443,7 +442,7 @@ static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ 	pqh = list_entry(qh->node.prev, struct uhci_qh, node);
+ 	qh->link = pqh->link;
+ 	wmb();
+-	pqh->link = UHCI_PTR_QH | cpu_to_le32(qh->dma_handle);
++	pqh->link = LINK_TO_QH(qh);
+ }
+ 
+ /*
+@@ -737,7 +736,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
+ 		td = uhci_alloc_td(uhci);
+ 		if (!td)
+ 			goto nomem;
+-		*plink = cpu_to_le32(td->dma_handle);
++		*plink = LINK_TO_TD(td);
+ 
+ 		/* Alternate Data0/1 (start with Data1) */
+ 		destination ^= TD_TOKEN_TOGGLE;
+@@ -757,7 +756,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
+ 	td = uhci_alloc_td(uhci);
+ 	if (!td)
+ 		goto nomem;
+-	*plink = cpu_to_le32(td->dma_handle);
++	*plink = LINK_TO_TD(td);
+ 
+ 	/*
+ 	 * It's IN if the pipe is an output pipe or we're not expecting
+@@ -784,7 +783,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
+ 	td = uhci_alloc_td(uhci);
+ 	if (!td)
+ 		goto nomem;
+-	*plink = cpu_to_le32(td->dma_handle);
++	*plink = LINK_TO_TD(td);
+ 
+ 	uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0);
+ 	wmb();
+@@ -860,7 +859,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
+ 			td = uhci_alloc_td(uhci);
+ 			if (!td)
+ 				goto nomem;
+-			*plink = cpu_to_le32(td->dma_handle);
++			*plink = LINK_TO_TD(td);
+ 		}
+ 		uhci_add_td_to_urbp(td, urbp);
+ 		uhci_fill_td(td, status,
+@@ -888,7 +887,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
+ 		td = uhci_alloc_td(uhci);
+ 		if (!td)
+ 			goto nomem;
+-		*plink = cpu_to_le32(td->dma_handle);
++		*plink = LINK_TO_TD(td);
+ 
+ 		uhci_add_td_to_urbp(td, urbp);
+ 		uhci_fill_td(td, status,
+@@ -914,7 +913,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
+ 	td = uhci_alloc_td(uhci);
+ 	if (!td)
+ 		goto nomem;
+-	*plink = cpu_to_le32(td->dma_handle);
++	*plink = LINK_TO_TD(td);
+ 
+ 	uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0);
+ 	wmb();
+@@ -1005,7 +1004,7 @@ static int uhci_fixup_short_transfer(struct uhci_hcd *uhci,
+ 		 * the queue at the status stage transaction, which is
+ 		 * the last TD. */
+ 		WARN_ON(list_empty(&urbp->td_list));
+-		qh->element = cpu_to_le32(td->dma_handle);
++		qh->element = LINK_TO_TD(td);
+ 		tmp = td->list.prev;
+ 		ret = -EINPROGRESS;
+ 
+@@ -1566,8 +1565,7 @@ static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ 	if (time_after(jiffies, qh->advance_jiffies + QH_WAIT_TIMEOUT)) {
+ 
+ 		/* Detect the Intel bug and work around it */
+-		if (qh->post_td && qh_element(qh) ==
+-				cpu_to_le32(qh->post_td->dma_handle)) {
++		if (qh->post_td && qh_element(qh) == LINK_TO_TD(qh->post_td)) {
+ 			qh->element = qh->post_td->link;
+ 			qh->advance_jiffies = jiffies;
+ 			ret = 1;

commit 3f141e2aed586c41c2666d49c70c1c1bbb6d6abd
+Author: Alan Stern 
+Date:   Thu Feb 8 16:40:43 2007 -0500
+
+    USB: unconfigure devices which have config 0
+    
+    Some USB devices do have a configuration 0, in contravention of the
+    USB spec.  Normally 0 is supposed to indicate that a device is
+    unconfigured.
+    
+    While we can't change what the device is doing, we can change usbcore.
+    This patch (as852) allows usb_set_configuration() to accept a config
+    value of -1 as indicating that the device should be unconfigured.  The
+    request actually sent to the device will still contain 0 as the value.
+    But even if the device does have a configuration 0, dev->actconfig
+    will be set to NULL and dev->state will be set to USB_STATE_ADDRESS.
+    
+    Without some sort of special-case handling like this, there is no way
+    to unconfigure these non-compliant devices.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 2087766f9e88..274f14f1633e 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -857,11 +857,11 @@ static int proc_setintf(struct dev_state *ps, void __user *arg)
+ 
+ static int proc_setconfig(struct dev_state *ps, void __user *arg)
+ {
+-	unsigned int u;
++	int u;
+ 	int status = 0;
+  	struct usb_host_config *actconfig;
+ 
+-	if (get_user(u, (unsigned int __user *)arg))
++	if (get_user(u, (int __user *)arg))
+ 		return -EFAULT;
+ 
+  	actconfig = ps->dev->actconfig;
+diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
+index b531a4fd30c2..9bbcb20e2d94 100644
+--- a/drivers/usb/core/generic.c
++++ b/drivers/usb/core/generic.c
+@@ -184,7 +184,7 @@ static void generic_disconnect(struct usb_device *udev)
+ 	/* if this is only an unbind, not a physical disconnect, then
+ 	 * unconfigure the device */
+ 	if (udev->actconfig)
+-		usb_set_configuration(udev, 0);
++		usb_set_configuration(udev, -1);
+ 
+ 	usb_remove_sysfs_dev_files(udev);
+ }
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 8aca3574c2b5..74edaea5665d 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1316,6 +1316,14 @@ static void release_interface(struct device *dev)
+  * use this kind of configurability; many devices only have one
+  * configuration.
+  *
++ * @configuration is the value of the configuration to be installed.
++ * According to the USB spec (e.g. section 9.1.1.5), configuration values
++ * must be non-zero; a value of zero indicates that the device in
++ * unconfigured.  However some devices erroneously use 0 as one of their
++ * configuration values.  To help manage such devices, this routine will
++ * accept @configuration = -1 as indicating the device should be put in
++ * an unconfigured state.
++ *
+  * USB device configurations may affect Linux interoperability,
+  * power consumption and the functionality available.  For example,
+  * the default configuration is limited to using 100mA of bus power,
+@@ -1347,10 +1355,15 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 	struct usb_interface **new_interfaces = NULL;
+ 	int n, nintf;
+ 
+-	for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
+-		if (dev->config[i].desc.bConfigurationValue == configuration) {
+-			cp = &dev->config[i];
+-			break;
++	if (configuration == -1)
++		configuration = 0;
++	else {
++		for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
++			if (dev->config[i].desc.bConfigurationValue ==
++					configuration) {
++				cp = &dev->config[i];
++				break;
++			}
+ 		}
+ 	}
+ 	if ((!cp && configuration != 0))
+@@ -1359,6 +1372,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 	/* The USB spec says configuration 0 means unconfigured.
+ 	 * But if a device includes a configuration numbered 0,
+ 	 * we will accept it as a correctly configured state.
++	 * Use -1 if you really want to unconfigure the device.
+ 	 */
+ 	if (cp && configuration == 0)
+ 		dev_warn(&dev->dev, "config 0 descriptor??\n");
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 4eaa0ee8e72f..0edfbafd702c 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -63,7 +63,7 @@ set_bConfigurationValue(struct device *dev, struct device_attribute *attr,
+ 	struct usb_device	*udev = to_usb_device(dev);
+ 	int			config, value;
+ 
+-	if (sscanf(buf, "%u", &config) != 1 || config > 255)
++	if (sscanf(buf, "%d", &config) != 1 || config < -1 || config > 255)
+ 		return -EINVAL;
+ 	usb_lock_device(udev);
+ 	value = usb_set_configuration(udev, config);

commit db90e7a15cb4a160610b4e58576f25539ca216e7
+Author: Alan Stern 
+Date:   Mon Feb 5 09:56:15 2007 -0500
+
+    USB: fix concurrent buffer access in the hub driver
+    
+    This patch (as849) fixes a bug in the USB hub driver.  A single
+    pre-allocated buffer is used for all port status reads, but nothing
+    guarantees exclusive use of the buffer.  A mutex is added to provide
+    this guarantee.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 7d6006573543..50c0db15304a 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -44,6 +44,7 @@ struct usb_hub {
+ 		struct usb_hub_status	hub;
+ 		struct usb_port_status	port;
+ 	}			*status;	/* buffer for status reports */
++	struct mutex		status_mutex;	/* for the status buffer */
+ 
+ 	int			error;		/* last reported error */
+ 	int			nerrors;	/* track consecutive errors */
+@@ -535,6 +536,7 @@ static int hub_hub_status(struct usb_hub *hub,
+ {
+ 	int ret;
+ 
++	mutex_lock(&hub->status_mutex);
+ 	ret = get_hub_status(hub->hdev, &hub->status->hub);
+ 	if (ret < 0)
+ 		dev_err (hub->intfdev,
+@@ -544,6 +546,7 @@ static int hub_hub_status(struct usb_hub *hub,
+ 		*change = le16_to_cpu(hub->status->hub.wHubChange); 
+ 		ret = 0;
+ 	}
++	mutex_unlock(&hub->status_mutex);
+ 	return ret;
+ }
+ 
+@@ -617,6 +620,7 @@ static int hub_configure(struct usb_hub *hub,
+ 		ret = -ENOMEM;
+ 		goto fail;
+ 	}
++	mutex_init(&hub->status_mutex);
+ 
+ 	hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL);
+ 	if (!hub->descriptor) {
+@@ -1396,6 +1400,7 @@ static int hub_port_status(struct usb_hub *hub, int port1,
+ {
+ 	int ret;
+ 
++	mutex_lock(&hub->status_mutex);
+ 	ret = get_port_status(hub->hdev, port1, &hub->status->port);
+ 	if (ret < 4) {
+ 		dev_err (hub->intfdev,
+@@ -1407,6 +1412,7 @@ static int hub_port_status(struct usb_hub *hub, int port1,
+ 		*change = le16_to_cpu(hub->status->port.wPortChange); 
+ 		ret = 0;
+ 	}
++	mutex_unlock(&hub->status_mutex);
+ 	return ret;
+ }
+ 

commit 8c774fe8a0284aff9e4c7ea43f5154fd46da325c
+Author: Alan Stern 
+Date:   Thu Feb 1 16:09:59 2007 -0500
+
+    EHCI: add debugging message to ehci_bus_suspend
+    
+    This patch (as848) adds a useful little debugging message to let us
+    know when ehci-hcd's bus_suspend method runs.  The other HCDs have
+    similar messages; now ehci-hcd doesn't need to feel left out.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 0d83c6df1a3b..9af529d22b3e 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -36,6 +36,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 	int			port;
+ 	int			mask;
+ 
++	ehci_dbg(ehci, "suspend root hub\n");
++
+ 	if (time_before (jiffies, ehci->next_statechange))
+ 		msleep(5);
+ 

commit 12f1ff8351e235661beb0314d9ae9417a4871688
+Author: Alan Stern 
+Date:   Thu Feb 1 16:08:41 2007 -0500
+
+    usbcore: small changes to hub driver's suspend method
+    
+    This patch (as847) makes some small changes to the hub driver's
+    suspend method:
+    
+            For root hubs, the status URB should be unlinked and other
+            activity stopped _before_ the bus_suspend method is called.
+    
+            The test for hdev->bus being NULL has been removed, since
+            it can never succeed.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 590ec82d0515..7d6006573543 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1904,6 +1904,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+ 	struct usb_hub		*hub = usb_get_intfdata (intf);
+ 	struct usb_device	*hdev = hub->hdev;
+ 	unsigned		port1;
++	int			status = 0;
+ 
+ 	/* fail if children aren't already suspended */
+ 	for (port1 = 1; port1 <= hdev->maxchild; port1++) {
+@@ -1927,24 +1928,18 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+ 
+ 	dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
+ 
++	/* stop khubd and related activity */
++	hub_quiesce(hub);
++
+ 	/* "global suspend" of the downstream HC-to-USB interface */
+ 	if (!hdev->parent) {
+-		struct usb_bus	*bus = hdev->bus;
+-		if (bus) {
+-			int	status = hcd_bus_suspend (bus);
+-
+-			if (status != 0) {
+-				dev_dbg(&hdev->dev, "'global' suspend %d\n",
+-					status);
+-				return status;
+-			}
+-		} else
+-			return -EOPNOTSUPP;
++		status = hcd_bus_suspend(hdev->bus);
++		if (status != 0) {
++			dev_dbg(&hdev->dev, "'global' suspend %d\n", status);
++			hub_activate(hub);
++		}
+ 	}
+-
+-	/* stop khubd and related activity */
+-	hub_quiesce(hub);
+-	return 0;
++	return status;
+ }
+ 
+ static int hub_resume(struct usb_interface *intf)

commit b544d7499cc47fc26e9dbacd7b9cabc67d2bdf2e
+Author: Alan Stern 
+Date:   Wed Jan 31 10:57:55 2007 -0500
+
+    USB: unusual_devs update for Sony P990i phone
+    
+    This patch (as846) adds the IGNORE_RESIDUE flag to the unusual_devs
+    entry for Sony-Ericsson's P990i phone.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Phil Dibowitz 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index f6c5f5fa2eeb..bab054b8d94f 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -1311,12 +1311,13 @@ UNUSUAL_DEV(  0x0fce, 0xd008, 0x0000, 0x0000,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_NO_WP_DETECT ),
+ 
+-/* Reported by Jan Mate  */
++/* Reported by Jan Mate 
++ * and by Soeren Sonnenburg  */
+ UNUSUAL_DEV(  0x0fce, 0xe030, 0x0000, 0x0000,
+ 		"Sony Ericsson",
+ 		"P990i",
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+-		US_FL_FIX_CAPACITY ),
++		US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ),
+ 
+ /* Reported by Emmanuel Vasilakis  */
+ UNUSUAL_DEV(  0x0fce, 0xe031, 0x0000, 0x0000,

commit 8903795a5275e0366acf961190c57074ad27f9bb
+Author: Alan Stern 
+Date:   Tue Feb 13 14:55:27 2007 -0500
+
+    EHCI: turn off remote wakeup during shutdown
+    
+    This patch (as850b) disables remote wakeup (and everything else!) on
+    all EHCI ports when the shutdown() method is called.  If remote wakeup
+    is left active then some systems will reboot instead of powering off.
+    This fixes Bugzilla #7828.
+    
+    Signed-off-by: Alan Stern 
+    Cc: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 185721dba42b..6bf909e1adf0 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -299,6 +299,19 @@ static void ehci_watchdog (unsigned long param)
+ 	spin_unlock_irqrestore (&ehci->lock, flags);
+ }
+ 
++/* On some systems, leaving remote wakeup enabled prevents system shutdown.
++ * The firmware seems to think that powering off is a wakeup event!
++ * This routine turns off remote wakeup and everything else, on all ports.
++ */
++static void ehci_turn_off_all_ports(struct ehci_hcd *ehci)
++{
++	int	port = HCS_N_PORTS(ehci->hcs_params);
++
++	while (port--)
++		ehci_writel(ehci, PORT_RWC_BITS,
++				&ehci->regs->port_status[port]);
++}
++
+ /* ehci_shutdown kick in for silicon on any bus (not just pci, etc).
+  * This forcibly disables dma and IRQs, helping kexec and other cases
+  * where the next system software may expect clean state.
+@@ -310,9 +323,13 @@ ehci_shutdown (struct usb_hcd *hcd)
+ 
+ 	ehci = hcd_to_ehci (hcd);
+ 	(void) ehci_halt (ehci);
++	ehci_turn_off_all_ports(ehci);
+ 
+ 	/* make BIOS/etc use companion controller during reboot */
+ 	ehci_writel(ehci, 0, &ehci->regs->configured_flag);
++
++	/* unblock posted writes */
++	ehci_readl(ehci, &ehci->regs->configured_flag);
+ }
+ 
+ static void ehci_port_power (struct ehci_hcd *ehci, int is_on)

commit 7c9d6f16f50d3aeb780e4f103a1ba8b35d9ae803
+Author: Alan Stern 
+Date:   Mon Jan 8 11:12:32 2007 -0500
+
+    [SCSI] SCSI core: better initialization for sdev->scsi_level
+    
+    This patch will affect the CDB in INQUIRY commands sent to LUNs above 0
+    when LUN-0 reports a scsi_level of 0; the LUN bits will no longer be set
+    in the second byte of the CDB.  This is as it should be.  Nevertheless,
+    it's possible that some wacky device might be adversely affected.  I doubt
+    anyone will complain...
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+index 7757e558d523..6905ffd135b3 100644
+--- a/drivers/scsi/scsi_scan.c
++++ b/drivers/scsi/scsi_scan.c
+@@ -385,6 +385,7 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
+ 	INIT_LIST_HEAD(&starget->siblings);
+ 	INIT_LIST_HEAD(&starget->devices);
+ 	starget->state = STARGET_RUNNING;
++	starget->scsi_level = SCSI_2;
+  retry:
+ 	spin_lock_irqsave(shost->host_lock, flags);
+ 
+diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
+index 259c90cfa367..c275dcac3f18 100644
+--- a/drivers/scsi/scsi_sysfs.c
++++ b/drivers/scsi/scsi_sysfs.c
+@@ -922,7 +922,7 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev)
+ 	snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE,
+ 		 "%d:%d:%d:%d", sdev->host->host_no,
+ 		 sdev->channel, sdev->id, sdev->lun);
+-	sdev->scsi_level = SCSI_2;
++	sdev->scsi_level = starget->scsi_level;
+ 	transport_setup_device(&sdev->sdev_gendev);
+ 	spin_lock_irqsave(shost->host_lock, flags);
+ 	list_add_tail(&sdev->same_target_siblings, &starget->devices);

commit 74feb53e8b5020e790e12c6331cbe885d276cc60
+Author: Alan Stern 
+Date:   Mon Jan 8 11:07:41 2007 -0500
+
+    [SCSI] scsi_proc.c: display sdev->scsi_level correctly
+    
+    This patch (as833) fixes the "SCSI revision" output for
+    /proc/scsi/scsi.  If the scsi_level value is 0 (UNKNOWN), we want it
+    to show up as "0", not "ffffffff".
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
+index 69d6e9b198c4..bb6f051beda8 100644
+--- a/drivers/scsi/scsi_proc.c
++++ b/drivers/scsi/scsi_proc.c
+@@ -179,9 +179,8 @@ static int proc_print_scsidevice(struct device *dev, void *data)
+ 	seq_printf(s, "\n");
+ 
+ 	seq_printf(s, "  Type:   %s ", scsi_device_type(sdev->type));
+-	seq_printf(s, "               ANSI"
+-		     " SCSI revision: %02x", (sdev->scsi_level - 1) ?
+-		     sdev->scsi_level - 1 : 1);
++	seq_printf(s, "               ANSI  SCSI revision: %02x",
++			sdev->scsi_level - (sdev->scsi_level > 1));
+ 	if (sdev->scsi_level == 2)
+ 		seq_printf(s, " CCS\n");
+ 	else

commit e423ee31db92d4e298c137814a4341e1cd05739e
+Author: Alan Stern 
+Date:   Fri Feb 16 01:46:38 2007 -0800
+
+    [SCSI] scsi_scan.c: handle bad inquiry responses
+    
+    A particular USB device has been reporting short inquiry lengths.  The
+    SCSI code cannot operate properly unless we get an inquiry length of
+    36 or above (because of the way we parse vendor and product), so
+    assume at least 36 bytes are valid even if the device reports fewer.
+    This is wrong, but it's no worse than what we're doing now (using the
+    garbage beyond the last reported valid byte).
+    
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+index a43b9ec3aefd..7757e558d523 100644
+--- a/drivers/scsi/scsi_scan.c
++++ b/drivers/scsi/scsi_scan.c
+@@ -654,6 +654,19 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result,
+ 	 * short INQUIRY), an abort here prevents any further use of the
+ 	 * device, including spin up.
+ 	 *
++	 * On the whole, the best approach seems to be to assume the first
++	 * 36 bytes are valid no matter what the device says.  That's
++	 * better than copying < 36 bytes to the inquiry-result buffer
++	 * and displaying garbage for the Vendor, Product, or Revision
++	 * strings.
++	 */
++	if (sdev->inquiry_len < 36) {
++		printk(KERN_INFO "scsi scan: INQUIRY result too short (%d),"
++				" using 36\n", sdev->inquiry_len);
++		sdev->inquiry_len = 36;
++	}
++
++	/*
+ 	 * Related to the above issue:
+ 	 *
+ 	 * XXX Devices (disk or all?) should be sent a TEST UNIT READY,

commit 1096f780d0b9d6bade2d42bf823e81db3e553abe
+Author: Alan Stern 
+Date:   Mon Jan 22 11:58:34 2007 -0500
+
+    usb-storage: use first bulk endpoints, not last
+    
+    According to the Bulk-Only spec, usb-storage is supposed to use the
+    _first_ bulk-in and bulk-out endpoints it finds, not the _last_.  And
+    while we're at it, we ought to test the direction of the interrupt
+    endpoint as well.  This patch (as842) makes both changes.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Matthew Dharm 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 70644506651f..7e7ec29782f1 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -731,26 +731,27 @@ static int get_pipes(struct us_data *us)
+ 	struct usb_endpoint_descriptor *ep_int = NULL;
+ 
+ 	/*
+-	 * Find the endpoints we need.
++	 * Find the first endpoint of each type we need.
+ 	 * We are expecting a minimum of 2 endpoints - in and out (bulk).
+-	 * An optional interrupt is OK (necessary for CBI protocol).
++	 * An optional interrupt-in is OK (necessary for CBI protocol).
+ 	 * We will ignore any others.
+ 	 */
+ 	for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
+ 		ep = &altsetting->endpoint[i].desc;
+ 
+-		/* Is it a BULK endpoint? */
+ 		if (usb_endpoint_xfer_bulk(ep)) {
+-			/* BULK in or out? */
+-			if (usb_endpoint_dir_in(ep))
+-				ep_in = ep;
+-			else
+-				ep_out = ep;
++			if (usb_endpoint_dir_in(ep)) {
++				if (!ep_in)
++					ep_in = ep;
++			} else {
++				if (!ep_out)
++					ep_out = ep;
++			}
+ 		}
+ 
+-		/* Is it an interrupt endpoint? */
+-		else if (usb_endpoint_xfer_int(ep)) {
+-			ep_int = ep;
++		else if (usb_endpoint_is_int_in(ep)) {
++			if (!ep_int)
++				ep_int = ep;
+ 		}
+ 	}
+ 

commit 629e4427aa817d5c9f11885420abf54b8f5967dc
+Author: Alan Stern 
+Date:   Mon Jan 22 16:08:53 2007 -0500
+
+    EHCI: fix interrupt-driven remote wakeup
+    
+    Now that port status change notifications are interrupt-driven,
+    ehci-hcd needs to tell usbcore when a remote-wakeup resume operation
+    is finished -- we can no longer rely on the core to poll and find
+    out.  This patch (as843) uses the root-hub status timer to force a
+    poll after the resume is complete.
+    
+    The patch also changes the test for detecting when the TDRSMDN resume
+    period has expired.  It's necessary to use time_after_eq() instead of
+    time_after(), since the polling is triggered precisely by a timer.
+    The same change is made for TDRSTR reset expiration, for consistency.
+    
+    Signed-off-by: Alan Stern 
+    Cc: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 3cfba69e0767..0d83c6df1a3b 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -379,8 +379,8 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ 			ehci->reset_done [i] = 0;
+ 		if ((temp & mask) != 0
+ 				|| ((temp & PORT_RESUME) != 0
+-					&& time_after (jiffies,
+-						ehci->reset_done [i]))) {
++					&& time_after_eq(jiffies,
++						ehci->reset_done[i]))) {
+ 			if (i < 7)
+ 			    buf [0] |= 1 << (i + 1);
+ 			else
+@@ -554,31 +554,45 @@ static int ehci_hub_control (
+ 			status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT;
+ 
+ 		/* whoever resumes must GetPortStatus to complete it!! */
+-		if ((temp & PORT_RESUME)
+-				&& time_after (jiffies,
+-					ehci->reset_done [wIndex])) {
+-			status |= 1 << USB_PORT_FEAT_C_SUSPEND;
+-			ehci->reset_done [wIndex] = 0;
++		if (temp & PORT_RESUME) {
+ 
+-			/* stop resume signaling */
+-			temp = ehci_readl(ehci, status_reg);
+-			ehci_writel(ehci,
++			/* Remote Wakeup received? */
++			if (!ehci->reset_done[wIndex]) {
++				/* resume signaling for 20 msec */
++				ehci->reset_done[wIndex] = jiffies
++						+ msecs_to_jiffies(20);
++				/* check the port again */
++				mod_timer(&ehci_to_hcd(ehci)->rh_timer,
++						ehci->reset_done[wIndex]);
++			}
++
++			/* resume completed? */
++			else if (time_after_eq(jiffies,
++					ehci->reset_done[wIndex])) {
++				status |= 1 << USB_PORT_FEAT_C_SUSPEND;
++				ehci->reset_done[wIndex] = 0;
++
++				/* stop resume signaling */
++				temp = ehci_readl(ehci, status_reg);
++				ehci_writel(ehci,
+ 					temp & ~(PORT_RWC_BITS | PORT_RESUME),
+ 					status_reg);
+-			retval = handshake(ehci, status_reg,
++				retval = handshake(ehci, status_reg,
+ 					   PORT_RESUME, 0, 2000 /* 2msec */);
+-			if (retval != 0) {
+-				ehci_err (ehci, "port %d resume error %d\n",
+-					wIndex + 1, retval);
+-				goto error;
++				if (retval != 0) {
++					ehci_err(ehci,
++						"port %d resume error %d\n",
++						wIndex + 1, retval);
++					goto error;
++				}
++				temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10));
+ 			}
+-			temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10));
+ 		}
+ 
+ 		/* whoever resets must GetPortStatus to complete it!! */
+ 		if ((temp & PORT_RESET)
+-				&& time_after (jiffies,
+-					ehci->reset_done [wIndex])) {
++				&& time_after_eq(jiffies,
++					ehci->reset_done[wIndex])) {
+ 			status |= 1 << USB_PORT_FEAT_C_RESET;
+ 			ehci->reset_done [wIndex] = 0;
+ 

commit 49631ca7f3e2fd05186028b453fa27f75b830de7
+Author: Alan Stern 
+Date:   Tue Jan 16 23:28:48 2007 -0800
+
+    USB: gadgetfs AIO tweaks
+    
+    This patch (as837) fixes several mistakes in the AIO interface of the
+    gadgetfs driver:
+    
+            The ki_retry method is not supposed to do a put on the kiocb.
+            The extra call to aio_put_req() causes memory corruption.
+            (Note: This call was removed before, by patch as691, and then
+            mysteriously re-introduced later.)
+    
+            Even if a read transfer is cancelled, we can and should send
+            to the user all the data that did manage to get transferred.
+    
+            Testing for AIO cancellation in the I/O completion handler
+            is both racy and (now) unnecessary.  aio_complete() does its
+            own checking, in a safe manner.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
+index 1c5e1ee7e36b..34296e79edcf 100644
+--- a/drivers/usb/gadget/inode.c
++++ b/drivers/usb/gadget/inode.c
+@@ -576,7 +576,6 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb)
+ 	}
+ 	kfree(priv->buf);
+ 	kfree(priv);
+-	aio_put_req(iocb);
+ 	return len;
+ }
+ 
+@@ -590,18 +589,17 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
+ 	spin_lock(&epdata->dev->lock);
+ 	priv->req = NULL;
+ 	priv->epdata = NULL;
+-	if (priv->iv == NULL
+-			|| unlikely(req->actual == 0)
+-			|| unlikely(kiocbIsCancelled(iocb))) {
++
++	/* if this was a write or a read returning no data then we
++	 * don't need to copy anything to userspace, so we can
++	 * complete the aio request immediately.
++	 */
++	if (priv->iv == NULL || unlikely(req->actual == 0)) {
+ 		kfree(req->buf);
+ 		kfree(priv);
+ 		iocb->private = NULL;
+ 		/* aio_complete() reports bytes-transferred _and_ faults */
+-		if (unlikely(kiocbIsCancelled(iocb)))
+-			aio_put_req(iocb);
+-		else
+-			aio_complete(iocb,
+-				req->actual ? req->actual : req->status,
++		aio_complete(iocb, req->actual ? req->actual : req->status,
+ 				req->status);
+ 	} else {
+ 		/* retry() won't report both; so we hide some faults */

commit 57e06c11372eccf5acebdd4664eb025fee76c561
+Author: Alan Stern 
+Date:   Tue Jan 16 11:59:45 2007 -0500
+
+    EHCI: force high-speed devices to run at full speed
+    
+    This patch (as710) adds a sysfs class-device attribute file named
+    "companion" for EHCI controllers.  The file contains a list of port
+    numbers that are dedicated to the companion controller; by writing a
+    port number to the file the user can force a high-speed device
+    attached directly to the computer to run at full speed.  (As far as I
+    know it is not possible to do this for a device attached to an
+    external hub.)  A port is removed from the file by writing the
+    negative of its port number.
+    
+    Several users have asked for this facility and it seems like a useful
+    thing to have.  Every now and then one runs across a device which
+    behaves much better at full speed than at high speed.
+    
+    Signed-off-by: Alan Stern 
+    Cc: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 9ec896218feb..92c62911f574 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -388,6 +388,7 @@ static void ehci_stop (struct usb_hcd *hcd)
+ 	/* let companion controllers work when we aren't */
+ 	ehci_writel(ehci, 0, &ehci->regs->configured_flag);
+ 
++	remove_companion_file(ehci);
+ 	remove_debug_files (ehci);
+ 
+ 	/* root hub is shut down separately (first, when possible) */
+@@ -563,6 +564,7 @@ static int ehci_run (struct usb_hcd *hcd)
+ 	 * since the class device isn't created that early.
+ 	 */
+ 	create_debug_files(ehci);
++	create_companion_file(ehci);
+ 
+ 	return 0;
+ }
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 076474d95dbf..3cfba69e0767 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -188,6 +188,103 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 
+ #endif	/* CONFIG_PM */
+ 
++/*-------------------------------------------------------------------------*/
++
++/* Display the ports dedicated to the companion controller */
++static ssize_t show_companion(struct class_device *class_dev, char *buf)
++{
++	struct ehci_hcd		*ehci;
++	int			nports, index, n;
++	int			count = PAGE_SIZE;
++	char			*ptr = buf;
++
++	ehci = hcd_to_ehci(bus_to_hcd(class_get_devdata(class_dev)));
++	nports = HCS_N_PORTS(ehci->hcs_params);
++
++	for (index = 0; index < nports; ++index) {
++		if (test_bit(index, &ehci->companion_ports)) {
++			n = scnprintf(ptr, count, "%d\n", index + 1);
++			ptr += n;
++			count -= n;
++		}
++	}
++	return ptr - buf;
++}
++
++/*
++ * Dedicate or undedicate a port to the companion controller.
++ * Syntax is "[-]portnum", where a leading '-' sign means
++ * return control of the port to the EHCI controller.
++ */
++static ssize_t store_companion(struct class_device *class_dev,
++		const char *buf, size_t count)
++{
++	struct ehci_hcd		*ehci;
++	int			portnum, new_owner, try;
++	u32 __iomem		*status_reg;
++	u32			port_status;
++
++	ehci = hcd_to_ehci(bus_to_hcd(class_get_devdata(class_dev)));
++	new_owner = PORT_OWNER;		/* Owned by companion */
++	if (sscanf(buf, "%d", &portnum) != 1)
++		return -EINVAL;
++	if (portnum < 0) {
++		portnum = - portnum;
++		new_owner = 0;		/* Owned by EHCI */
++	}
++	if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params))
++		return -ENOENT;
++	status_reg = &ehci->regs->port_status[--portnum];
++	if (new_owner)
++		set_bit(portnum, &ehci->companion_ports);
++	else
++		clear_bit(portnum, &ehci->companion_ports);
++
++	/*
++	 * The controller won't set the OWNER bit if the port is
++	 * enabled, so this loop will sometimes require at least two
++	 * iterations: one to disable the port and one to set OWNER.
++	 */
++
++	for (try = 4; try > 0; --try) {
++		spin_lock_irq(&ehci->lock);
++		port_status = ehci_readl(ehci, status_reg);
++		if ((port_status & PORT_OWNER) == new_owner
++				|| (port_status & (PORT_OWNER | PORT_CONNECT))
++					== 0)
++			try = 0;
++		else {
++			port_status ^= PORT_OWNER;
++			port_status &= ~(PORT_PE | PORT_RWC_BITS);
++			ehci_writel(ehci, port_status, status_reg);
++		}
++		spin_unlock_irq(&ehci->lock);
++		if (try > 1)
++			msleep(5);
++	}
++	return count;
++}
++static CLASS_DEVICE_ATTR(companion, 0644, show_companion, store_companion);
++
++static inline void create_companion_file(struct ehci_hcd *ehci)
++{
++	int	i;
++
++	/* with integrated TT there is no companion! */
++	if (!ehci_is_TDI(ehci))
++		i = class_device_create_file(ehci_to_hcd(ehci)->self.class_dev,
++				&class_device_attr_companion);
++}
++
++static inline void remove_companion_file(struct ehci_hcd *ehci)
++{
++	/* with integrated TT there is no companion! */
++	if (!ehci_is_TDI(ehci))
++		class_device_remove_file(ehci_to_hcd(ehci)->self.class_dev,
++				&class_device_attr_companion);
++}
++
++
+ /*-------------------------------------------------------------------------*/
+ 
+ static int check_reset_complete (
+@@ -504,6 +601,16 @@ static int ehci_hub_control (
+ 					ehci_readl(ehci, status_reg));
+ 		}
+ 
++		/* transfer dedicated ports to the companion hc */
++		if ((temp & PORT_CONNECT) &&
++				test_bit(wIndex, &ehci->companion_ports)) {
++			temp &= ~PORT_RWC_BITS;
++			temp |= PORT_OWNER;
++			ehci_writel(ehci, temp, status_reg);
++			ehci_dbg(ehci, "port %d --> companion\n", wIndex + 1);
++			temp = ehci_readl(ehci, status_reg);
++		}
++
+ 		/*
+ 		 * Even if OWNER is set, there's no harm letting khubd
+ 		 * see the wPortStatus values (they should all be 0 except
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index 3ce7249085d5..ec0da0343be4 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -74,7 +74,11 @@ struct ehci_hcd {			/* one per controller */
+ 
+ 	/* per root hub port */
+ 	unsigned long		reset_done [EHCI_MAX_ROOT_PORTS];
+-	unsigned long		bus_suspended;
++	/* bit vectors (one bit per port) */
++	unsigned long		bus_suspended;		/* which ports were
++			already suspended at the start of a bus suspend */
++	unsigned long		companion_ports;	/* which ports are
++			dedicated to the companion controller */
+ 
+ 	/* per-HC memory pools (could be per-bus, but ...) */
+ 	struct dma_pool		*qh_pool;	/* qh per active urb */

commit 625b5c9a0069ef1b61feb3ce599b39f1b04b5666
+Author: Alan Stern 
+Date:   Tue Jan 16 11:58:47 2007 -0500
+
+    EHCI: don't hide ports owned by the companion
+    
+    This patch (as709) changes the way ehci-hcd presents port status
+    values for ports owned by the companion controller.  It no longer
+    hides the information; in particular, it allows the core to see the
+    disconnect event that occurs when a full- or low-speed device is
+    switched over to the companion.  This is required for the next patch
+    in this series.
+    
+    Signed-off-by: Alan Stern 
+    Cc: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 12f881ff4b23..076474d95dbf 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -270,16 +270,14 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ 	spin_lock_irqsave (&ehci->lock, flags);
+ 	for (i = 0; i < ports; i++) {
+ 		temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
+-		if (temp & PORT_OWNER) {
+-			/* don't report this in GetPortStatus */
+-			if (temp & PORT_CSC) {
+-				temp &= ~PORT_RWC_BITS;
+-				temp |= PORT_CSC;
+-				ehci_writel(ehci, temp,
+-					    &ehci->regs->port_status [i]);
+-			}
+-			continue;
+-		}
++
++		/*
++		 * Return status information even for ports with OWNER set.
++		 * Otherwise khubd wouldn't see the disconnect event when a
++		 * high-speed device is switched over to the companion
++		 * controller by the user.
++		 */
++
+ 		if (!(temp & PORT_CONNECT))
+ 			ehci->reset_done [i] = 0;
+ 		if ((temp & mask) != 0
+@@ -377,8 +375,13 @@ static int ehci_hub_control (
+ 			goto error;
+ 		wIndex--;
+ 		temp = ehci_readl(ehci, status_reg);
+-		if (temp & PORT_OWNER)
+-			break;
++
++		/*
++		 * Even if OWNER is set, so the port is owned by the
++		 * companion controller, khubd needs to be able to clear
++		 * the port-change status bits (especially
++		 * USB_PORT_FEAT_C_CONNECTION).
++		 */
+ 
+ 		switch (wValue) {
+ 		case USB_PORT_FEAT_ENABLE:
+@@ -501,24 +504,27 @@ static int ehci_hub_control (
+ 					ehci_readl(ehci, status_reg));
+ 		}
+ 
+-		// don't show wPortStatus if it's owned by a companion hc
+-		if (!(temp & PORT_OWNER)) {
+-			if (temp & PORT_CONNECT) {
+-				status |= 1 << USB_PORT_FEAT_CONNECTION;
+-				// status may be from integrated TT
+-				status |= ehci_port_speed(ehci, temp);
+-			}
+-			if (temp & PORT_PE)
+-				status |= 1 << USB_PORT_FEAT_ENABLE;
+-			if (temp & (PORT_SUSPEND|PORT_RESUME))
+-				status |= 1 << USB_PORT_FEAT_SUSPEND;
+-			if (temp & PORT_OC)
+-				status |= 1 << USB_PORT_FEAT_OVER_CURRENT;
+-			if (temp & PORT_RESET)
+-				status |= 1 << USB_PORT_FEAT_RESET;
+-			if (temp & PORT_POWER)
+-				status |= 1 << USB_PORT_FEAT_POWER;
++		/*
++		 * Even if OWNER is set, there's no harm letting khubd
++		 * see the wPortStatus values (they should all be 0 except
++		 * for PORT_POWER anyway).
++		 */
++
++		if (temp & PORT_CONNECT) {
++			status |= 1 << USB_PORT_FEAT_CONNECTION;
++			// status may be from integrated TT
++			status |= ehci_port_speed(ehci, temp);
+ 		}
++		if (temp & PORT_PE)
++			status |= 1 << USB_PORT_FEAT_ENABLE;
++		if (temp & (PORT_SUSPEND|PORT_RESUME))
++			status |= 1 << USB_PORT_FEAT_SUSPEND;
++		if (temp & PORT_OC)
++			status |= 1 << USB_PORT_FEAT_OVER_CURRENT;
++		if (temp & PORT_RESET)
++			status |= 1 << USB_PORT_FEAT_RESET;
++		if (temp & PORT_POWER)
++			status |= 1 << USB_PORT_FEAT_POWER;
+ 
+ #ifndef	EHCI_VERBOSE_DEBUG
+ 	if (status & ~0xffff)	/* only if wPortChange is interesting */

commit e6316565e568b3b5733be10cfca3c27259bef499
+Author: Alan Stern 
+Date:   Tue Jan 16 11:58:00 2007 -0500
+
+    EHCI: local variable for port status register
+    
+    This patch (as708) introduces a local variable to hold the port
+    status-register address in ehci-hub.c.  There's not much improvement
+    in the object code, but it sure is a lot easier to read.
+    
+    Signed-off-by: Alan Stern 
+    Cc: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index df00fcbadfbc..12f881ff4b23 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -193,6 +193,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ static int check_reset_complete (
+ 	struct ehci_hcd	*ehci,
+ 	int		index,
++	u32 __iomem	*status_reg,
+ 	int		port_status
+ ) {
+ 	if (!(port_status & PORT_CONNECT)) {
+@@ -217,8 +218,7 @@ static int check_reset_complete (
+ 		// what happens if HCS_N_CC(params) == 0 ?
+ 		port_status |= PORT_OWNER;
+ 		port_status &= ~PORT_RWC_BITS;
+-		ehci_writel(ehci, port_status,
+-			    &ehci->regs->port_status [index]);
++		ehci_writel(ehci, port_status, status_reg);
+ 
+ 	} else
+ 		ehci_dbg (ehci, "port %d high speed\n", index + 1);
+@@ -347,6 +347,7 @@ static int ehci_hub_control (
+ ) {
+ 	struct ehci_hcd	*ehci = hcd_to_ehci (hcd);
+ 	int		ports = HCS_N_PORTS (ehci->hcs_params);
++	u32 __iomem	*status_reg = &ehci->regs->port_status[wIndex - 1];
+ 	u32		temp, status;
+ 	unsigned long	flags;
+ 	int		retval = 0;
+@@ -375,18 +376,17 @@ static int ehci_hub_control (
+ 		if (!wIndex || wIndex > ports)
+ 			goto error;
+ 		wIndex--;
+-		temp = ehci_readl(ehci, &ehci->regs->port_status [wIndex]);
++		temp = ehci_readl(ehci, status_reg);
+ 		if (temp & PORT_OWNER)
+ 			break;
+ 
+ 		switch (wValue) {
+ 		case USB_PORT_FEAT_ENABLE:
+-			ehci_writel(ehci, temp & ~PORT_PE,
+-				    &ehci->regs->port_status [wIndex]);
++			ehci_writel(ehci, temp & ~PORT_PE, status_reg);
+ 			break;
+ 		case USB_PORT_FEAT_C_ENABLE:
+ 			ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_PEC,
+-				    &ehci->regs->port_status [wIndex]);
++					status_reg);
+ 			break;
+ 		case USB_PORT_FEAT_SUSPEND:
+ 			if (temp & PORT_RESET)
+@@ -399,7 +399,7 @@ static int ehci_hub_control (
+ 				/* resume signaling for 20 msec */
+ 				temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
+ 				ehci_writel(ehci, temp | PORT_RESUME,
+-					    &ehci->regs->port_status [wIndex]);
++						status_reg);
+ 				ehci->reset_done [wIndex] = jiffies
+ 						+ msecs_to_jiffies (20);
+ 			}
+@@ -411,15 +411,15 @@ static int ehci_hub_control (
+ 			if (HCS_PPC (ehci->hcs_params))
+ 				ehci_writel(ehci,
+ 					  temp & ~(PORT_RWC_BITS | PORT_POWER),
+-					  &ehci->regs->port_status [wIndex]);
++					  status_reg);
+ 			break;
+ 		case USB_PORT_FEAT_C_CONNECTION:
+ 			ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_CSC,
+-				    &ehci->regs->port_status [wIndex]);
++					status_reg);
+ 			break;
+ 		case USB_PORT_FEAT_C_OVER_CURRENT:
+ 			ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_OCC,
+-				    &ehci->regs->port_status [wIndex]);
++					status_reg);
+ 			break;
+ 		case USB_PORT_FEAT_C_RESET:
+ 			/* GetPortStatus clears reset */
+@@ -443,7 +443,7 @@ static int ehci_hub_control (
+ 			goto error;
+ 		wIndex--;
+ 		status = 0;
+-		temp = ehci_readl(ehci, &ehci->regs->port_status [wIndex]);
++		temp = ehci_readl(ehci, status_reg);
+ 
+ 		// wPortChange bits
+ 		if (temp & PORT_CSC)
+@@ -461,13 +461,11 @@ static int ehci_hub_control (
+ 			ehci->reset_done [wIndex] = 0;
+ 
+ 			/* stop resume signaling */
+-			temp = ehci_readl(ehci,
+-					  &ehci->regs->port_status [wIndex]);
++			temp = ehci_readl(ehci, status_reg);
+ 			ehci_writel(ehci,
+-				    temp & ~(PORT_RWC_BITS | PORT_RESUME),
+-				    &ehci->regs->port_status [wIndex]);
+-			retval = handshake(ehci,
+-					   &ehci->regs->port_status [wIndex],
++					temp & ~(PORT_RWC_BITS | PORT_RESUME),
++					status_reg);
++			retval = handshake(ehci, status_reg,
+ 					   PORT_RESUME, 0, 2000 /* 2msec */);
+ 			if (retval != 0) {
+ 				ehci_err (ehci, "port %d resume error %d\n",
+@@ -486,12 +484,11 @@ static int ehci_hub_control (
+ 
+ 			/* force reset to complete */
+ 			ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_RESET),
+-				    &ehci->regs->port_status [wIndex]);
++					status_reg);
+ 			/* REVISIT:  some hardware needs 550+ usec to clear
+ 			 * this bit; seems too long to spin routinely...
+ 			 */
+-			retval = handshake(ehci,
+-					   &ehci->regs->port_status [wIndex],
++			retval = handshake(ehci, status_reg,
+ 					PORT_RESET, 0, 750);
+ 			if (retval != 0) {
+ 				ehci_err (ehci, "port %d reset error %d\n",
+@@ -500,9 +497,8 @@ static int ehci_hub_control (
+ 			}
+ 
+ 			/* see what we found out */
+-			temp = check_reset_complete (ehci, wIndex,
+-				ehci_readl(ehci,
+-					   &ehci->regs->port_status [wIndex]));
++			temp = check_reset_complete (ehci, wIndex, status_reg,
++					ehci_readl(ehci, status_reg));
+ 		}
+ 
+ 		// don't show wPortStatus if it's owned by a companion hc
+@@ -547,7 +543,7 @@ static int ehci_hub_control (
+ 		if (!wIndex || wIndex > ports)
+ 			goto error;
+ 		wIndex--;
+-		temp = ehci_readl(ehci, &ehci->regs->port_status [wIndex]);
++		temp = ehci_readl(ehci, status_reg);
+ 		if (temp & PORT_OWNER)
+ 			break;
+ 
+@@ -561,13 +557,12 @@ static int ehci_hub_control (
+ 				goto error;
+ 			if (device_may_wakeup(&hcd->self.root_hub->dev))
+ 				temp |= PORT_WAKE_BITS;
+-			ehci_writel(ehci, temp | PORT_SUSPEND,
+-				    &ehci->regs->port_status [wIndex]);
++			ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
+ 			break;
+ 		case USB_PORT_FEAT_POWER:
+ 			if (HCS_PPC (ehci->hcs_params))
+ 				ehci_writel(ehci, temp | PORT_POWER,
+-					    &ehci->regs->port_status [wIndex]);
++						status_reg);
+ 			break;
+ 		case USB_PORT_FEAT_RESET:
+ 			if (temp & PORT_RESUME)
+@@ -595,8 +590,7 @@ static int ehci_hub_control (
+ 				ehci->reset_done [wIndex] = jiffies
+ 						+ msecs_to_jiffies (50);
+ 			}
+-			ehci_writel(ehci, temp,
+-				    &ehci->regs->port_status [wIndex]);
++			ehci_writel(ehci, temp, status_reg);
+ 			break;
+ 
+ 		/* For downstream facing ports (these):  one hub port is put
+@@ -611,8 +605,7 @@ static int ehci_hub_control (
+ 			ehci_quiesce(ehci);
+ 			ehci_halt(ehci);
+ 			temp |= selector << 16;
+-			ehci_writel(ehci, temp,
+-				    &ehci->regs->port_status [wIndex]);
++			ehci_writel(ehci, temp, status_reg);
+ 			break;
+ 
+ 		default:

commit 896fbd7199035958013d106329843d8ae9618753
+Author: Alan Stern 
+Date:   Tue Jan 16 11:57:13 2007 -0500
+
+    usbcore: remove unused bandwith-related code
+    
+    This patch (as841) removes from usbcore a couple of support routines
+    meant to help with bandwidth allocation.  With the changes to uhci-hcd
+    in the previous patch, these routines are no longer used anywhere.
+    Also removed is the CONFIG_USB_BANDWIDTH option; it no longer does
+    anything and is no longer needed since the HCDs now handle bandwidth
+    issues correctly.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
+index 3e66b2a9974a..2fc0f88a3d86 100644
+--- a/drivers/usb/core/Kconfig
++++ b/drivers/usb/core/Kconfig
+@@ -33,19 +33,6 @@ config USB_DEVICEFS
+ 
+ 	  Most users want to say Y here.
+ 
+-config USB_BANDWIDTH
+-	bool "Enforce USB bandwidth allocation (EXPERIMENTAL)"
+-	depends on USB && EXPERIMENTAL
+-	help
+-	  If you say Y here, the USB subsystem enforces USB bandwidth
+-	  allocation and will prevent some device opens from succeeding
+-	  if they would cause USB bandwidth usage to go above 90% of
+-	  the bus bandwidth.
+-
+-	  If you say N here, these conditions will cause warning messages
+-	  about USB bandwidth usage to be logged and some devices or
+-	  drivers may not work correctly.
+-
+ config USB_DYNAMIC_MINORS
+ 	bool "Dynamic USB minor allocation (EXPERIMENTAL)"
+ 	depends on USB && EXPERIMENTAL
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 10064af65d17..b26c19e8d19f 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -45,8 +45,6 @@
+ #include "hub.h"
+ 
+ 
+-// #define USB_BANDWIDTH_MESSAGES
+-
+ /*-------------------------------------------------------------------------*/
+ 
+ /*
+@@ -891,136 +889,6 @@ long usb_calc_bus_time (int speed, int is_input, int isoc, int bytecount)
+ }
+ EXPORT_SYMBOL (usb_calc_bus_time);
+ 
+-/*
+- * usb_check_bandwidth():
+- *
+- * old_alloc is from host_controller->bandwidth_allocated in microseconds;
+- * bustime is from calc_bus_time(), but converted to microseconds.
+- *
+- * returns  if successful,
+- * or -ENOSPC if bandwidth request fails.
+- *
+- * FIXME:
+- * This initial implementation does not use Endpoint.bInterval
+- * in managing bandwidth allocation.
+- * It probably needs to be expanded to use Endpoint.bInterval.
+- * This can be done as a later enhancement (correction).
+- *
+- * This will also probably require some kind of
+- * frame allocation tracking...meaning, for example,
+- * that if multiple drivers request interrupts every 10 USB frames,
+- * they don't all have to be allocated at
+- * frame numbers N, N+10, N+20, etc.  Some of them could be at
+- * N+11, N+21, N+31, etc., and others at
+- * N+12, N+22, N+32, etc.
+- *
+- * Similarly for isochronous transfers...
+- *
+- * Individual HCDs can schedule more directly ... this logic
+- * is not correct for high speed transfers.
+- */
+-int usb_check_bandwidth (struct usb_device *dev, struct urb *urb)
+-{
+-	unsigned int	pipe = urb->pipe;
+-	long		bustime;
+-	int		is_in = usb_pipein (pipe);
+-	int		is_iso = usb_pipeisoc (pipe);
+-	int		old_alloc = dev->bus->bandwidth_allocated;
+-	int		new_alloc;
+-
+-
+-	bustime = NS_TO_US (usb_calc_bus_time (dev->speed, is_in, is_iso,
+-			usb_maxpacket (dev, pipe, !is_in)));
+-	if (is_iso)
+-		bustime /= urb->number_of_packets;
+-
+-	new_alloc = old_alloc + (int) bustime;
+-	if (new_alloc > FRAME_TIME_MAX_USECS_ALLOC) {
+-#ifdef	DEBUG
+-		char	*mode = 
+-#ifdef CONFIG_USB_BANDWIDTH
+-			"";
+-#else
+-			"would have ";
+-#endif
+-		dev_dbg (&dev->dev, "usb_check_bandwidth %sFAILED: %d + %ld = %d usec\n",
+-			mode, old_alloc, bustime, new_alloc);
+-#endif
+-#ifdef CONFIG_USB_BANDWIDTH
+-		bustime = -ENOSPC;	/* report error */
+-#endif
+-	}
+-
+-	return bustime;
+-}
+-EXPORT_SYMBOL (usb_check_bandwidth);
+-
+-
+-/**
+- * usb_claim_bandwidth - records bandwidth for a periodic transfer
+- * @dev: source/target of request
+- * @urb: request (urb->dev == dev)
+- * @bustime: bandwidth consumed, in (average) microseconds per frame
+- * @isoc: true iff the request is isochronous
+- *
+- * Bus bandwidth reservations are recorded purely for diagnostic purposes.
+- * HCDs are expected not to overcommit periodic bandwidth, and to record such
+- * reservations whenever endpoints are added to the periodic schedule.
+- *
+- * FIXME averaging per-frame is suboptimal.  Better to sum over the HCD's
+- * entire periodic schedule ... 32 frames for OHCI, 1024 for UHCI, settable
+- * for EHCI (256/512/1024 frames, default 1024) and have the bus expose how
+- * large its periodic schedule is.
+- */
+-void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb, int bustime, int isoc)
+-{
+-	dev->bus->bandwidth_allocated += bustime;
+-	if (isoc)
+-		dev->bus->bandwidth_isoc_reqs++;
+-	else
+-		dev->bus->bandwidth_int_reqs++;
+-	urb->bandwidth = bustime;
+-
+-#ifdef USB_BANDWIDTH_MESSAGES
+-	dev_dbg (&dev->dev, "bandwidth alloc increased by %d (%s) to %d for %d requesters\n",
+-		bustime,
+-		isoc ? "ISOC" : "INTR",
+-		dev->bus->bandwidth_allocated,
+-		dev->bus->bandwidth_int_reqs + dev->bus->bandwidth_isoc_reqs);
+-#endif
+-}
+-EXPORT_SYMBOL (usb_claim_bandwidth);
+-
+-
+-/**
+- * usb_release_bandwidth - reverses effect of usb_claim_bandwidth()
+- * @dev: source/target of request
+- * @urb: request (urb->dev == dev)
+- * @isoc: true iff the request is isochronous
+- *
+- * This records that previously allocated bandwidth has been released.
+- * Bandwidth is released when endpoints are removed from the host controller's
+- * periodic schedule.
+- */
+-void usb_release_bandwidth (struct usb_device *dev, struct urb *urb, int isoc)
+-{
+-	dev->bus->bandwidth_allocated -= urb->bandwidth;
+-	if (isoc)
+-		dev->bus->bandwidth_isoc_reqs--;
+-	else
+-		dev->bus->bandwidth_int_reqs--;
+-
+-#ifdef USB_BANDWIDTH_MESSAGES
+-	dev_dbg (&dev->dev, "bandwidth alloc reduced by %d (%s) to %d for %d requesters\n",
+-		urb->bandwidth,
+-		isoc ? "ISOC" : "INTR",
+-		dev->bus->bandwidth_allocated,
+-		dev->bus->bandwidth_int_reqs + dev->bus->bandwidth_isoc_reqs);
+-#endif
+-	urb->bandwidth = 0;
+-}
+-EXPORT_SYMBOL (usb_release_bandwidth);
+-
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+@@ -1034,11 +902,6 @@ static void urb_unlink (struct urb *urb)
+ {
+ 	unsigned long		flags;
+ 
+-	/* Release any periodic transfer bandwidth */
+-	if (urb->bandwidth)
+-		usb_release_bandwidth (urb->dev, urb,
+-			usb_pipeisoc (urb->pipe));
+-
+ 	/* clear all state linking urb to this dev (and hcd) */
+ 
+ 	spin_lock_irqsave (&hcd_data_lock, flags);
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index 8f8df0d4382e..2a269ca20517 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -308,10 +308,6 @@ extern void usb_destroy_configuration(struct usb_device *dev);
+ #define NS_TO_US(ns)	((ns + 500L) / 1000L)
+ 			/* convert & round nanoseconds to microseconds */
+ 
+-extern void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb,
+-		int bustime, int isoc);
+-extern void usb_release_bandwidth (struct usb_device *dev, struct urb *urb,
+-		int isoc);
+ 
+ /*
+  * Full/low speed bandwidth allocation constants/support.
+@@ -324,8 +320,6 @@ extern void usb_release_bandwidth (struct usb_device *dev, struct urb *urb,
+ #define FRAME_TIME_MAX_BITS_ALLOC	(90L * FRAME_TIME_BITS / 100L)
+ #define FRAME_TIME_MAX_USECS_ALLOC	(90L * FRAME_TIME_USECS / 100L)
+ 
+-extern int usb_check_bandwidth (struct usb_device *dev, struct urb *urb);
+-
+ /*
+  * Ceiling [nano/micro]seconds (typical) for that many bytes at high speed
+  * ISO is a bit less, no ACK ... from USB 2.0 spec, 5.11.3 (and needed
+diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
+index 9801d08edacf..a4fa3e66c307 100644
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -235,7 +235,6 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 
+ 	urb->status = -EINPROGRESS;
+ 	urb->actual_length = 0;
+-	urb->bandwidth = 0;
+ 
+ 	/* Lots of sanity checks, so HCDs can rely on clean data
+ 	 * and don't need to duplicate tests
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 1c56386de709..3b08ab39550f 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -1110,7 +1110,6 @@ struct urb
+ 	struct kref kref;		/* reference count of the URB */
+ 	spinlock_t lock;		/* lock for the URB */
+ 	void *hcpriv;			/* private data for host controller */
+-	int bandwidth;			/* bandwidth for INT/ISO request */
+ 	atomic_t use_count;		/* concurrent submissions counter */
+ 	u8 reject;			/* submissions will fail */
+ 

commit 3ca2a3211ee5078d49b04fe7149ff2a76473be51
+Author: Alan Stern 
+Date:   Tue Jan 16 11:56:32 2007 -0500
+
+    UHCI: fix bandwidth allocation
+    
+    This patch (as840) fixes the bandwidth allocation mechanism in
+    uhci-hcd.  It has never worked correctly.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
+index 3fbb5ba80249..5d6c06bc4524 100644
+--- a/drivers/usb/host/uhci-debug.c
++++ b/drivers/usb/host/uhci-debug.c
+@@ -168,9 +168,13 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
+ 			space, "", qh, qtype,
+ 			le32_to_cpu(qh->link), le32_to_cpu(element));
+ 	if (qh->type == USB_ENDPOINT_XFER_ISOC)
+-		out += sprintf(out, "%*s    period %d frame %x desc [%p]\n",
+-				space, "", qh->period, qh->iso_frame,
+-				qh->iso_packet_desc);
++		out += sprintf(out, "%*s    period %d phase %d load %d us, "
++				"frame %x desc [%p]\n",
++				space, "", qh->period, qh->phase, qh->load,
++				qh->iso_frame, qh->iso_packet_desc);
++	else if (qh->type == USB_ENDPOINT_XFER_INT)
++		out += sprintf(out, "%*s    period %d phase %d load %d us\n",
++				space, "", qh->period, qh->phase, qh->load);
+ 
+ 	if (element & UHCI_PTR_QH)
+ 		out += sprintf(out, "%*s  Element points to QH (bug?)\n", space, "");
+@@ -352,6 +356,17 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
+ 	out += uhci_show_root_hub_state(uhci, out, len - (out - buf));
+ 	out += sprintf(out, "HC status\n");
+ 	out += uhci_show_status(uhci, out, len - (out - buf));
++
++	out += sprintf(out, "Periodic load table\n");
++	for (i = 0; i < MAX_PHASE; ++i) {
++		out += sprintf(out, "\t%d", uhci->load[i]);
++		if (i % 8 == 7)
++			*out++ = '\n';
++	}
++	out += sprintf(out, "Total: %d, #INT: %d, #ISO: %d\n",
++			uhci->total_load,
++			uhci_to_hcd(uhci)->self.bandwidth_int_reqs,
++			uhci_to_hcd(uhci)->self.bandwidth_isoc_reqs);
+ 	if (debug <= 1)
+ 		return out - buf;
+ 
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index 108e3de2dc26..74469b5bcb61 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -83,6 +83,7 @@
+ #define UHCI_MAX_SOF_NUMBER	2047	/* in an SOF packet */
+ #define CAN_SCHEDULE_FRAMES	1000	/* how far in the future frames
+ 					 * can be scheduled */
++#define MAX_PHASE		32	/* Periodic scheduling length */
+ 
+ /* When no queues need Full-Speed Bandwidth Reclamation,
+  * delay this long before turning FSBR off */
+@@ -141,6 +142,8 @@ struct uhci_qh {
+ 	unsigned long advance_jiffies;	/* Time of last queue advance */
+ 	unsigned int unlink_frame;	/* When the QH was unlinked */
+ 	unsigned int period;		/* For Interrupt and Isochronous QHs */
++	short phase;			/* Between 0 and period-1 */
++	short load;			/* Periodic time requirement, in us */
+ 	unsigned int iso_frame;		/* Frame # for iso_packet_desc */
+ 	int iso_status;			/* Status for Isochronous URBs */
+ 
+@@ -153,6 +156,8 @@ struct uhci_qh {
+ 	unsigned int needs_fixup:1;	/* Must fix the TD toggle values */
+ 	unsigned int is_stopped:1;	/* Queue was stopped by error/unlink */
+ 	unsigned int wait_expired:1;	/* QH_WAIT_TIMEOUT has expired */
++	unsigned int bandwidth_reserved:1;	/* Periodic bandwidth has
++						 * been allocated */
+ } __attribute__((aligned(16)));
+ 
+ /*
+@@ -414,6 +419,9 @@ struct uhci_hcd {
+ 
+ 	wait_queue_head_t waitqh;		/* endpoint_disable waiters */
+ 	int num_waiting;			/* Number of waiters */
++
++	int total_load;				/* Sum of array values */
++	short load[MAX_PHASE];			/* Periodic allocations */
+ };
+ 
+ /* Convert between a usb_hcd pointer and the corresponding uhci_hcd */
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 5afcc5227284..2cbb239e63f8 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -261,6 +261,14 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci,
+ 		qh->udev = udev;
+ 		hep->hcpriv = qh;
+ 
++		if (qh->type == USB_ENDPOINT_XFER_INT ||
++				qh->type == USB_ENDPOINT_XFER_ISOC)
++			qh->load = usb_calc_bus_time(udev->speed,
++					usb_endpoint_dir_in(&hep->desc),
++					qh->type == USB_ENDPOINT_XFER_ISOC,
++					le16_to_cpu(hep->desc.wMaxPacketSize))
++				/ 1000 + 1;
++
+ 	} else {		/* Skeleton QH */
+ 		qh->state = QH_STATE_ACTIVE;
+ 		qh->type = -1;
+@@ -496,6 +504,121 @@ static void uhci_make_qh_idle(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ 		wake_up_all(&uhci->waitqh);
+ }
+ 
++/*
++ * Find the highest existing bandwidth load for a given phase and period.
++ */
++static int uhci_highest_load(struct uhci_hcd *uhci, int phase, int period)
++{
++	int highest_load = uhci->load[phase];
++
++	for (phase += period; phase < MAX_PHASE; phase += period)
++		highest_load = max_t(int, highest_load, uhci->load[phase]);
++	return highest_load;
++}
++
++/*
++ * Set qh->phase to the optimal phase for a periodic transfer and
++ * check whether the bandwidth requirement is acceptable.
++ */
++static int uhci_check_bandwidth(struct uhci_hcd *uhci, struct uhci_qh *qh)
++{
++	int minimax_load;
++
++	/* Find the optimal phase (unless it is already set) and get
++	 * its load value. */
++	if (qh->phase >= 0)
++		minimax_load = uhci_highest_load(uhci, qh->phase, qh->period);
++	else {
++		int phase, load;
++		int max_phase = min_t(int, MAX_PHASE, qh->period);
++
++		qh->phase = 0;
++		minimax_load = uhci_highest_load(uhci, qh->phase, qh->period);
++		for (phase = 1; phase < max_phase; ++phase) {
++			load = uhci_highest_load(uhci, phase, qh->period);
++			if (load < minimax_load) {
++				minimax_load = load;
++				qh->phase = phase;
++			}
++		}
++	}
++
++	/* Maximum allowable periodic bandwidth is 90%, or 900 us per frame */
++	if (minimax_load + qh->load > 900) {
++		dev_dbg(uhci_dev(uhci), "bandwidth allocation failed: "
++				"period %d, phase %d, %d + %d us\n",
++				qh->period, qh->phase, minimax_load, qh->load);
++		return -ENOSPC;
++	}
++	return 0;
++}
++
++/*
++ * Reserve a periodic QH's bandwidth in the schedule
++ */
++static void uhci_reserve_bandwidth(struct uhci_hcd *uhci, struct uhci_qh *qh)
++{
++	int i;
++	int load = qh->load;
++	char *p = "??";
++
++	for (i = qh->phase; i < MAX_PHASE; i += qh->period) {
++		uhci->load[i] += load;
++		uhci->total_load += load;
++	}
++	uhci_to_hcd(uhci)->self.bandwidth_allocated =
++			uhci->total_load / MAX_PHASE;
++	switch (qh->type) {
++	case USB_ENDPOINT_XFER_INT:
++		++uhci_to_hcd(uhci)->self.bandwidth_int_reqs;
++		p = "INT";
++		break;
++	case USB_ENDPOINT_XFER_ISOC:
++		++uhci_to_hcd(uhci)->self.bandwidth_isoc_reqs;
++		p = "ISO";
++		break;
++	}
++	qh->bandwidth_reserved = 1;
++	dev_dbg(uhci_dev(uhci),
++			"%s dev %d ep%02x-%s, period %d, phase %d, %d us\n",
++			"reserve", qh->udev->devnum,
++			qh->hep->desc.bEndpointAddress, p,
++			qh->period, qh->phase, load);
++}
++
++/*
++ * Release a periodic QH's bandwidth reservation
++ */
++static void uhci_release_bandwidth(struct uhci_hcd *uhci, struct uhci_qh *qh)
++{
++	int i;
++	int load = qh->load;
++	char *p = "??";
++
++	for (i = qh->phase; i < MAX_PHASE; i += qh->period) {
++		uhci->load[i] -= load;
++		uhci->total_load -= load;
++	}
++	uhci_to_hcd(uhci)->self.bandwidth_allocated =
++			uhci->total_load / MAX_PHASE;
++	switch (qh->type) {
++	case USB_ENDPOINT_XFER_INT:
++		--uhci_to_hcd(uhci)->self.bandwidth_int_reqs;
++		p = "INT";
++		break;
++	case USB_ENDPOINT_XFER_ISOC:
++		--uhci_to_hcd(uhci)->self.bandwidth_isoc_reqs;
++		p = "ISO";
++		break;
++	}
++	qh->bandwidth_reserved = 0;
++	dev_dbg(uhci_dev(uhci),
++			"%s dev %d ep%02x-%s, period %d, phase %d, %d us\n",
++			"release", qh->udev->devnum,
++			qh->hep->desc.bEndpointAddress, p,
++			qh->period, qh->phase, load);
++}
++
+ static inline struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci,
+ 		struct urb *urb)
+ {
+@@ -799,7 +922,6 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
+ 	wmb();
+ 	qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE);
+ 	qh->dummy_td = td;
+-	qh->period = urb->interval;
+ 
+ 	usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+ 			usb_pipeout(urb->pipe), toggle);
+@@ -830,28 +952,42 @@ static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb,
+ static int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb,
+ 		struct uhci_qh *qh)
+ {
+-	int exponent;
++	int ret;
+ 
+ 	/* USB 1.1 interrupt transfers only involve one packet per interval.
+ 	 * Drivers can submit URBs of any length, but longer ones will need
+ 	 * multiple intervals to complete.
+ 	 */
+ 
+-	/* Figure out which power-of-two queue to use */
+-	for (exponent = 7; exponent >= 0; --exponent) {
+-		if ((1 << exponent) <= urb->interval)
+-			break;
+-	}
+-	if (exponent < 0)
+-		return -EINVAL;
+-	urb->interval = 1 << exponent;
++	if (!qh->bandwidth_reserved) {
++		int exponent;
+ 
+-	if (qh->period == 0)
++		/* Figure out which power-of-two queue to use */
++		for (exponent = 7; exponent >= 0; --exponent) {
++			if ((1 << exponent) <= urb->interval)
++				break;
++		}
++		if (exponent < 0)
++			return -EINVAL;
++		qh->period = 1 << exponent;
+ 		qh->skel = uhci->skelqh[UHCI_SKEL_INDEX(exponent)];
+-	else if (qh->period != urb->interval)
+-		return -EINVAL;		/* Can't change the period */
+ 
+-	return uhci_submit_common(uhci, urb, qh);
++		/* For now, interrupt phase is fixed by the layout
++		 * of the QH lists. */
++		qh->phase = (qh->period / 2) & (MAX_PHASE - 1);
++		ret = uhci_check_bandwidth(uhci, qh);
++		if (ret)
++			return ret;
++	} else if (qh->period > urb->interval)
++		return -EINVAL;		/* Can't decrease the period */
++
++	ret = uhci_submit_common(uhci, urb, qh);
++	if (ret == 0) {
++		urb->interval = qh->period;
++		if (!qh->bandwidth_reserved)
++			uhci_reserve_bandwidth(uhci, qh);
++	}
++	return ret;
+ }
+ 
+ /*
+@@ -998,15 +1134,32 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
+ 		return -EFBIG;
+ 
+ 	/* Check the period and figure out the starting frame number */
+-	if (qh->period == 0) {
++	if (!qh->bandwidth_reserved) {
++		qh->period = urb->interval;
+ 		if (urb->transfer_flags & URB_ISO_ASAP) {
++			qh->phase = -1;		/* Find the best phase */
++			i = uhci_check_bandwidth(uhci, qh);
++			if (i)
++				return i;
++
++			/* Allow a little time to allocate the TDs */
+ 			uhci_get_current_frame_number(uhci);
+-			urb->start_frame = uhci->frame_number + 10;
++			frame = uhci->frame_number + 10;
++
++			/* Move forward to the first frame having the
++			 * correct phase */
++			urb->start_frame = frame + ((qh->phase - frame) &
++					(qh->period - 1));
+ 		} else {
+ 			i = urb->start_frame - uhci->last_iso_frame;
+ 			if (i <= 0 || i >= UHCI_NUMFRAMES)
+ 				return -EINVAL;
++			qh->phase = urb->start_frame & (qh->period - 1);
++			i = uhci_check_bandwidth(uhci, qh);
++			if (i)
++				return i;
+ 		}
++
+ 	} else if (qh->period != urb->interval) {
+ 		return -EINVAL;		/* Can't change the period */
+ 
+@@ -1052,9 +1205,6 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
+ 	/* Set the interrupt-on-completion flag on the last packet. */
+ 	td->status |= __constant_cpu_to_le32(TD_CTRL_IOC);
+ 
+-	qh->skel = uhci->skel_iso_qh;
+-	qh->period = urb->interval;
+-
+ 	/* Add the TDs to the frame list */
+ 	frame = urb->start_frame;
+ 	list_for_each_entry(td, &urbp->td_list, list) {
+@@ -1068,6 +1218,9 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
+ 		qh->iso_status = 0;
+ 	}
+ 
++	qh->skel = uhci->skel_iso_qh;
++	if (!qh->bandwidth_reserved)
++		uhci_reserve_bandwidth(uhci, qh);
+ 	return 0;
+ }
+ 
+@@ -1122,7 +1275,6 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd,
+ 	unsigned long flags;
+ 	struct urb_priv *urbp;
+ 	struct uhci_qh *qh;
+-	int bustime;
+ 
+ 	spin_lock_irqsave(&uhci->lock, flags);
+ 
+@@ -1152,35 +1304,11 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd,
+ 		ret = uhci_submit_bulk(uhci, urb, qh);
+ 		break;
+ 	case USB_ENDPOINT_XFER_INT:
+-		if (list_empty(&qh->queue)) {
+-			bustime = usb_check_bandwidth(urb->dev, urb);
+-			if (bustime < 0)
+-				ret = bustime;
+-			else {
+-				ret = uhci_submit_interrupt(uhci, urb, qh);
+-				if (ret == 0)
+-					usb_claim_bandwidth(urb->dev, urb, bustime, 0);
+-			}
+-		} else {	/* inherit from parent */
+-			struct urb_priv *eurbp;
+-
+-			eurbp = list_entry(qh->queue.prev, struct urb_priv,
+-					node);
+-			urb->bandwidth = eurbp->urb->bandwidth;
+-			ret = uhci_submit_interrupt(uhci, urb, qh);
+-		}
++		ret = uhci_submit_interrupt(uhci, urb, qh);
+ 		break;
+ 	case USB_ENDPOINT_XFER_ISOC:
+ 		urb->error_count = 0;
+-		bustime = usb_check_bandwidth(urb->dev, urb);
+-		if (bustime < 0) {
+-			ret = bustime;
+-			break;
+-		}
+-
+ 		ret = uhci_submit_isochronous(uhci, urb, qh);
+-		if (ret == 0)
+-			usb_claim_bandwidth(urb->dev, urb, bustime, 1);
+ 		break;
+ 	}
+ 	if (ret != 0)
+@@ -1277,24 +1405,6 @@ __acquires(uhci->lock)
+ 
+ 	uhci_free_urb_priv(uhci, urbp);
+ 
+-	switch (qh->type) {
+-	case USB_ENDPOINT_XFER_ISOC:
+-		/* Release bandwidth for Interrupt or Isoc. transfers */
+-		if (urb->bandwidth)
+-			usb_release_bandwidth(urb->dev, urb, 1);
+-		break;
+-	case USB_ENDPOINT_XFER_INT:
+-		/* Release bandwidth for Interrupt or Isoc. transfers */
+-		/* Make sure we don't release if we have a queued URB */
+-		if (list_empty(&qh->queue) && urb->bandwidth)
+-			usb_release_bandwidth(urb->dev, urb, 0);
+-		else
+-			/* bandwidth was passed on to queued URB, */
+-			/* so don't let usb_unlink_urb() release it */
+-			urb->bandwidth = 0;
+-		break;
+-	}
+-
+ 	spin_unlock(&uhci->lock);
+ 	usb_hcd_giveback_urb(uhci_to_hcd(uhci), urb);
+ 	spin_lock(&uhci->lock);
+@@ -1303,9 +1413,8 @@ __acquires(uhci->lock)
+ 	 * reserved bandwidth. */
+ 	if (list_empty(&qh->queue)) {
+ 		uhci_unlink_qh(uhci, qh);
+-
+-		/* Bandwidth stuff not yet implemented */
+-		qh->period = 0;
++		if (qh->bandwidth_reserved)
++			uhci_release_bandwidth(uhci, qh);
+ 	}
+ }
+ 

commit f3f4906516a084bbd9aa3da7592e6b029fe78f5b
+Author: Alan Stern 
+Date:   Mon Jan 8 16:18:05 2007 -0500
+
+    usb-storage: SCSI level fixes
+    
+    This patch (as835) removes from usb-storage the code which sets all
+    devices to a SCSI level of at least SCSI-2.  The original reasons for
+    doing this no longer apply, and in fact it prevents certain kinds of
+    ATA pass-thru commands from being used.
+    
+    The patch also marks CB and CBI devices that are SCSI-0 (legacy SCSI)
+    as being single-LUN, since the combined SCSI-over-USB transport
+    protocol has no way to convey LUN information to these devices.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Matthew Dharm 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index e1072d52d641..70234f5dbeeb 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -110,23 +110,6 @@ static int slave_configure(struct scsi_device *sdev)
+ 	 * the end, scatter-gather buffers follow page boundaries. */
+ 	blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
+ 
+-	/* Set the SCSI level to at least 2.  We'll leave it at 3 if that's
+-	 * what is originally reported.  We need this to avoid confusing
+-	 * the SCSI layer with devices that report 0 or 1, but need 10-byte
+-	 * commands (ala ATAPI devices behind certain bridges, or devices
+-	 * which simply have broken INQUIRY data).
+-	 *
+-	 * NOTE: This means /dev/sg programs (ala cdrecord) will get the
+-	 * actual information.  This seems to be the preference for
+-	 * programs like that.
+-	 *
+-	 * NOTE: This also means that /proc/scsi/scsi and sysfs may report
+-	 * the actual value or the modified one, depending on where the
+-	 * data comes from.
+-	 */
+-	if (sdev->scsi_level < SCSI_2)
+-		sdev->scsi_level = sdev->sdev_target->scsi_level = SCSI_2;
+-
+ 	/* Many devices have trouble transfering more than 32KB at a time,
+ 	 * while others have trouble with more than 64K. At this time we
+ 	 * are limiting both to 32K (64 sectores).
+@@ -176,7 +159,9 @@ static int slave_configure(struct scsi_device *sdev)
+ 		 * a Get-Max-LUN request, we won't lose much by setting the
+ 		 * revision level down to 2.  The only devices that would be
+ 		 * affected are those with sparse LUNs. */
+-		sdev->scsi_level = sdev->sdev_target->scsi_level = SCSI_2;
++		if (sdev->scsi_level > SCSI_2)
++			sdev->sdev_target->scsi_level =
++					sdev->scsi_level = SCSI_2;
+ 
+ 		/* USB-IDE bridges tend to report SK = 0x04 (Non-recoverable
+ 		 * Hardware Error) when any low-level error occurs,
+@@ -194,6 +179,16 @@ static int slave_configure(struct scsi_device *sdev)
+ 		sdev->use_10_for_ms = 1;
+ 	}
+ 
++	/* The CB and CBI transports have no way to pass LUN values
++	 * other than the bits in the second byte of a CDB.  But those
++	 * bits don't get set to the LUN value if the device reports
++	 * scsi_level == 0 (UNKNOWN).  Hence such devices must necessarily
++	 * be single-LUN.
++	 */
++	if ((us->protocol == US_PR_CB || us->protocol == US_PR_CBI) &&
++			sdev->scsi_level == SCSI_UNKNOWN)
++		us->max_lun = 0;
++
+ 	/* Some devices choke when they receive a PREVENT-ALLOW MEDIUM
+ 	 * REMOVAL command, so suppress those commands. */
+ 	if (us->flags & US_FL_NOT_LOCKABLE)

commit 85a975d0ce48dfa8dec5bf1bd970f8fd2c48af32
+Author: Alan Stern 
+Date:   Mon Jan 8 12:01:43 2007 -0500
+
+    UHCI: no dummy TDs for Iso QHs
+    
+    Isochronous queues don't need a dummy TD because the Queue Header
+    isn't managed by the hardware.  This patch (as836) removes the
+    unnecessary dummy TDs.
+    
+    The patch also fixes a long-standing typo in a comment (a "don't" was
+    missing -- potentially very confusing!).
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
+index b40bc1ac9b8c..3fbb5ba80249 100644
+--- a/drivers/usb/host/uhci-debug.c
++++ b/drivers/usb/host/uhci-debug.c
+@@ -208,7 +208,7 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
+ 					space, "", nurbs);
+ 	}
+ 
+-	if (qh->udev) {
++	if (qh->dummy_td) {
+ 		out += sprintf(out, "%*s  Dummy TD\n", space, "");
+ 		out += uhci_show_td(qh->dummy_td, out, len - (out - buf), 0);
+ 	}
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 30b88459ac7d..5afcc5227284 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -248,16 +248,18 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci,
+ 	INIT_LIST_HEAD(&qh->node);
+ 
+ 	if (udev) {		/* Normal QH */
+-		qh->dummy_td = uhci_alloc_td(uhci);
+-		if (!qh->dummy_td) {
+-			dma_pool_free(uhci->qh_pool, qh, dma_handle);
+-			return NULL;
++		qh->type = hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
++		if (qh->type != USB_ENDPOINT_XFER_ISOC) {
++			qh->dummy_td = uhci_alloc_td(uhci);
++			if (!qh->dummy_td) {
++				dma_pool_free(uhci->qh_pool, qh, dma_handle);
++				return NULL;
++			}
+ 		}
+ 		qh->state = QH_STATE_IDLE;
+ 		qh->hep = hep;
+ 		qh->udev = udev;
+ 		hep->hcpriv = qh;
+-		qh->type = hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+ 
+ 	} else {		/* Skeleton QH */
+ 		qh->state = QH_STATE_ACTIVE;
+@@ -275,7 +277,8 @@ static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ 	list_del(&qh->node);
+ 	if (qh->udev) {
+ 		qh->hep->hcpriv = NULL;
+-		uhci_free_td(uhci, qh->dummy_td);
++		if (qh->dummy_td)
++			uhci_free_td(uhci, qh->dummy_td);
+ 	}
+ 	dma_pool_free(uhci->qh_pool, qh, qh->dma_handle);
+ }
+@@ -327,7 +330,7 @@ static int uhci_cleanup_queue(struct uhci_hcd *uhci, struct uhci_qh *qh,
+ 		goto done;
+ 	qh->element = UHCI_PTR_TERM;
+ 
+-	/* Control pipes have to worry about toggles */
++	/* Control pipes don't have to worry about toggles */
+ 	if (qh->type == USB_ENDPOINT_XFER_CONTROL)
+ 		goto done;
+ 

commit f3fe239b67424d88104e32076aec902c0642925f
+Author: Alan Stern 
+Date:   Mon Jan 8 12:00:28 2007 -0500
+
+    UHCI: improved debugging checks for the frame list
+    
+    This patch (as768) improves the debugging checks for the uhci-hcd
+    frame list.  The number of entries displayed is limited to 10, and the
+    driver now checks for the correct Skeleton QH link value at the end of
+    each chain of Isochronous TDs.  The code to compute these link values
+    is now used in two spots, so it is moved into its own separate
+    subroutine.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
+index e345f15b7d87..b40bc1ac9b8c 100644
+--- a/drivers/usb/host/uhci-debug.c
++++ b/drivers/usb/host/uhci-debug.c
+@@ -347,6 +347,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
+ 	struct uhci_qh *qh;
+ 	struct uhci_td *td;
+ 	struct list_head *tmp, *head;
++	int nframes, nerrs;
+ 
+ 	out += uhci_show_root_hub_state(uhci, out, len - (out - buf));
+ 	out += sprintf(out, "HC status\n");
+@@ -355,23 +356,60 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
+ 		return out - buf;
+ 
+ 	out += sprintf(out, "Frame List\n");
++	nframes = 10;
++	nerrs = 0;
+ 	for (i = 0; i < UHCI_NUMFRAMES; ++i) {
++		__le32 link, qh_dma;
++
++		j = 0;
+ 		td = uhci->frame_cpu[i];
++		link = uhci->frame[i];
+ 		if (!td)
+-			continue;
++			goto check_link;
+ 
+-		out += sprintf(out, "- Frame %d\n", i); \
+-		if (td->dma_handle != (dma_addr_t)uhci->frame[i])
+-			out += sprintf(out, "    frame list does not match td->dma_handle!\n");
++		if (nframes > 0) {
++			out += sprintf(out, "- Frame %d -> (%08x)\n",
++					i, le32_to_cpu(link));
++			j = 1;
++		}
+ 
+ 		head = &td->fl_list;
+ 		tmp = head;
+ 		do {
+ 			td = list_entry(tmp, struct uhci_td, fl_list);
+ 			tmp = tmp->next;
+-			out += uhci_show_td(td, out, len - (out - buf), 4);
++			if (cpu_to_le32(td->dma_handle) != link) {
++				if (nframes > 0)
++					out += sprintf(out, "    link does "
++						"not match list entry!\n");
++				else
++					++nerrs;
++			}
++			if (nframes > 0)
++				out += uhci_show_td(td, out,
++						len - (out - buf), 4);
++			link = td->link;
+ 		} while (tmp != head);
++
++check_link:
++		qh_dma = uhci_frame_skel_link(uhci, i);
++		if (link != qh_dma) {
++			if (nframes > 0) {
++				if (!j) {
++					out += sprintf(out,
++						"- Frame %d -> (%08x)\n",
++						i, le32_to_cpu(link));
++					j = 1;
++				}
++				out += sprintf(out, "   link does not match "
++					"QH (%08x)!\n", le32_to_cpu(qh_dma));
++			} else
++				++nerrs;
++		}
++		nframes -= j;
+ 	}
++	if (nerrs > 0)
++		out += sprintf(out, "Skipped %d bad links\n", nerrs);
+ 
+ 	out += sprintf(out, "Skeleton QHs\n");
+ 
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index e0d4c2358b39..49b9d390b95f 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -92,6 +92,34 @@ static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state);
+ static void wakeup_rh(struct uhci_hcd *uhci);
+ static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
+ 
++/*
++ * Calculate the link pointer DMA value for the first Skeleton QH in a frame.
++ */
++static __le32 uhci_frame_skel_link(struct uhci_hcd *uhci, int frame)
++{
++	int skelnum;
++
++	/*
++	 * The interrupt queues will be interleaved as evenly as possible.
++	 * There's not much to be done about period-1 interrupts; they have
++	 * to occur in every frame.  But we can schedule period-2 interrupts
++	 * in odd-numbered frames, period-4 interrupts in frames congruent
++	 * to 2 (mod 4), and so on.  This way each frame only has two
++	 * interrupt QHs, which will help spread out bandwidth utilization.
++	 *
++	 * ffs (Find First bit Set) does exactly what we need:
++	 * 1,3,5,...  => ffs = 0 => use skel_int2_qh = skelqh[8],
++	 * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[7], etc.
++	 * ffs >= 7 => not on any high-period queue, so use
++	 *	skel_int1_qh = skelqh[9].
++	 * Add in UHCI_NUMFRAMES to insure at least one bit is set.
++	 */
++	skelnum = 8 - (int) __ffs(frame | UHCI_NUMFRAMES);
++	if (skelnum <= 1)
++		skelnum = 9;
++	return UHCI_PTR_QH | cpu_to_le32(uhci->skelqh[skelnum]->dma_handle);
++}
++
+ #include "uhci-debug.c"
+ #include "uhci-q.c"
+ #include "uhci-hub.c"
+@@ -631,32 +659,11 @@ static int uhci_start(struct usb_hcd *hcd)
+ 	/*
+ 	 * Fill the frame list: make all entries point to the proper
+ 	 * interrupt queue.
+-	 *
+-	 * The interrupt queues will be interleaved as evenly as possible.
+-	 * There's not much to be done about period-1 interrupts; they have
+-	 * to occur in every frame.  But we can schedule period-2 interrupts
+-	 * in odd-numbered frames, period-4 interrupts in frames congruent
+-	 * to 2 (mod 4), and so on.  This way each frame only has two
+-	 * interrupt QHs, which will help spread out bandwidth utilization.
+ 	 */
+ 	for (i = 0; i < UHCI_NUMFRAMES; i++) {
+-		int irq;
+-
+-		/*
+-		 * ffs (Find First bit Set) does exactly what we need:
+-		 * 1,3,5,...  => ffs = 0 => use skel_int2_qh = skelqh[8],
+-		 * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[7], etc.
+-		 * ffs >= 7 => not on any high-period queue, so use
+-		 *	skel_int1_qh = skelqh[9].
+-		 * Add UHCI_NUMFRAMES to insure at least one bit is set.
+-		 */
+-		irq = 8 - (int) __ffs(i + UHCI_NUMFRAMES);
+-		if (irq <= 1)
+-			irq = 9;
+ 
+ 		/* Only place we don't use the frame list routines */
+-		uhci->frame[i] = UHCI_PTR_QH |
+-				cpu_to_le32(uhci->skelqh[irq]->dma_handle);
++		uhci->frame[i] = uhci_frame_skel_link(uhci, i);
+ 	}
+ 
+ 	/*

commit 1737bf2c5e78e331ad0a30b8c34edd1016d043c0
+Author: Alan Stern 
+Date:   Fri Dec 15 16:04:52 2006 -0500
+
+    usbcore: remove unneeded error check
+    
+    This patch (as830) removes some unnecessary error checking.  According
+    to the kerneldoc, schedule_work() can't fail.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 149aa8bfb1fe..8aca3574c2b5 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1545,11 +1545,7 @@ int usb_driver_set_configuration(struct usb_device *udev, int config)
+ 	INIT_WORK(&req->work, driver_set_config_work);
+ 
+ 	usb_get_dev(udev);
+-	if (!schedule_work(&req->work)) {
+-		usb_put_dev(udev);
+-		kfree(req);
+-		return -EINVAL;
+-	}
++	schedule_work(&req->work);
+ 	return 0;
+ }
+ EXPORT_SYMBOL_GPL(usb_driver_set_configuration);

commit 25c77b329467d563ec1fa5c3efab0b13996ce810
+Author: Alan Stern 
+Date:   Fri Dec 15 16:08:13 2006 -0500
+
+    UHCI: support device_may_wakeup
+    
+    This patch (as831) adds device_may_wakeup() support to uhci-hcd; it
+    has been lacking for a long time.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index fecc8c971c17..e0d4c2358b39 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -257,7 +257,9 @@ __acquires(uhci->lock)
+ 	int_enable = USBINTR_RESUME;
+ 	if (remote_wakeup_is_broken(uhci))
+ 		egsm_enable = 0;
+-	if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable)
++	if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable ||
++			!device_may_wakeup(
++				&uhci_to_hcd(uhci)->self.root_hub->dev))
+ 		uhci->working_RD = int_enable = 0;
+ 
+ 	outw(int_enable, uhci->io_addr + USBINTR);

commit c80a70d53fa0ca47ad122cd75fe32b6f41c04eb1
+Author: Alan Stern 
+Date:   Fri Dec 15 16:06:25 2006 -0500
+
+    UHCI: make test for ASUS motherboard more specific
+    
+    Instead of matching all motherboards whose name contains "A7V8X" for a
+    remote-wakeup hardware bug, this patch (as829) matches only those
+    boards whose name is exactly equal to "A7V8X".  Later motherboards
+    don't seem to have the bug.
+    
+    (In fact, it's possible that only one motherboard in the world has the
+    bug.  With only one user reporting problems, it's hard to tell.)
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index acd101caeeeb..fecc8c971c17 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -209,24 +209,16 @@ static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
+ 
+ static int remote_wakeup_is_broken(struct uhci_hcd *uhci)
+ {
+-	static struct dmi_system_id broken_wakeup_table[] = {
+-		{
+-			.ident = "Asus A7V8X",
+-			.matches = {
+-				DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK"),
+-				DMI_MATCH(DMI_BOARD_NAME, "A7V8X"),
+-				DMI_MATCH(DMI_BOARD_VERSION, "REV 1.xx"),
+-			}
+-		},
+-		{ }
+-	};
+ 	int port;
++	char *sys_info;
++	static char bad_Asus_board[] = "A7V8X";
+ 
+ 	/* One of Asus's motherboards has a bug which causes it to
+ 	 * wake up immediately from suspend-to-RAM if any of the ports
+ 	 * are connected.  In such cases we will not set EGSM.
+ 	 */
+-	if (dmi_check_system(broken_wakeup_table)) {
++	sys_info = dmi_get_system_info(DMI_BOARD_NAME);
++	if (sys_info && !strcmp(sys_info, bad_Asus_board)) {
+ 		for (port = 0; port < uhci->rh_numports; ++port) {
+ 			if (inw(uhci->io_addr + USBPORTSC1 + port * 2) &
+ 					USBPORTSC_CCS)

commit 5f8364b7d63acdc2216ca0f7d0a8557c318479ea
+Author: Alan Stern 
+Date:   Tue Dec 5 16:29:55 2006 -0500
+
+    UHCI: module parameter to ignore overcurrent changes
+    
+    Certain boards seem to like to issue false overcurrent notifications,
+    for example on ports that don't have anything connected to them.  This
+    looks like a hardware error, at the level of noise to those ports'
+    overcurrent input signals (or non-debounced VBUS comparators).  This
+    surfaces to users as truly massive amounts of syslog spam from khubd
+    (which is appropriate for real hardware problems, except for the
+    volume from multiple ports).
+    
+    Using this new "ignore_oc" flag helps such systems work more sanely,
+    by preventing such indications from getting to khubd (and spamming
+    syslog).  The downside is of course that true overcurrent errors will
+    be masked; they'll appear as spontaneous disconnects, without the
+    diagnostics that will let users troubleshoot issues like
+    short-circuited cables.  In addition, controllers with no devices
+    attached will be forced to poll for new devices rather than relying on
+    interrupts, since each overcurrent event would generate a new
+    interrupt.
+    
+    This patch (as826) is essentially a copy of David Brownell's ignore_oc
+    patch for ehci-hcd, ported to uhci-hcd.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
+index ef69c75780bf..25d298517104 100644
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -1714,6 +1714,14 @@ and is between 256 and 4096 characters. It is defined in the file
+ 	uart6850=	[HW,OSS]
+ 			Format: ,
+ 
++	uhci-hcd.ignore_oc=
++			[USB] Ignore overcurrent events (default N).
++			Some badly-designed motherboards generate lots of
++			bogus events, for ports that aren't wired to
++			anything.  Set this parameter to avoid log spamming.
++			Note that genuine overcurrent events won't be
++			reported either.
++
+ 	usbhid.mousepoll=
+ 			[USBHID] The interval which mice are to be polled at.
+ 
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index e87692c31be4..acd101caeeeb 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -60,6 +60,11 @@ Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \
+ Alan Stern"
+ #define DRIVER_DESC "USB Universal Host Controller Interface driver"
+ 
++/* for flakey hardware, ignore overcurrent indicators */
++static int ignore_oc;
++module_param(ignore_oc, bool, S_IRUGO);
++MODULE_PARM_DESC(ignore_oc, "ignore hardware overcurrent indications");
++
+ /*
+  * debug = 0, no debugging messages
+  * debug = 1, dump failed URBs except for stalls
+@@ -169,6 +174,11 @@ static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
+ {
+ 	int port;
+ 
++	/* If we have to ignore overcurrent events then almost by definition
++	 * we can't depend on resume-detect interrupts. */
++	if (ignore_oc)
++		return 1;
++
+ 	switch (to_pci_dev(uhci_dev(uhci))->vendor) {
+ 	    default:
+ 		break;
+@@ -921,7 +931,8 @@ static int __init uhci_hcd_init(void)
+ {
+ 	int retval = -ENOMEM;
+ 
+-	printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION "\n");
++	printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION "%s\n",
++			ignore_oc ? ", overcurrent ignored" : "");
+ 
+ 	if (usb_disabled())
+ 		return -ENODEV;
+diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
+index f8347f1a10b6..bacc25c53ba3 100644
+--- a/drivers/usb/host/uhci-hub.c
++++ b/drivers/usb/host/uhci-hub.c
+@@ -52,10 +52,20 @@ static int any_ports_active(struct uhci_hcd *uhci)
+ static inline int get_hub_status_data(struct uhci_hcd *uhci, char *buf)
+ {
+ 	int port;
++	int mask = RWC_BITS;
++
++	/* Some boards (both VIA and Intel apparently) report bogus
++	 * overcurrent indications, causing massive log spam unless
++	 * we completely ignore them.  This doesn't seem to be a problem
++	 * with the chipset so much as with the way it is connected on
++	 * the motherboard; if the overcurrent input is left to float
++	 * then it may constantly register false positives. */
++	if (ignore_oc)
++		mask &= ~USBPORTSC_OCC;
+ 
+ 	*buf = 0;
+ 	for (port = 0; port < uhci->rh_numports; ++port) {
+-		if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & RWC_BITS) ||
++		if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & mask) ||
+ 				test_bit(port, &uhci->port_c_suspend))
+ 			*buf |= (1 << (port + 1));
+ 	}
+@@ -263,7 +273,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+ 			wPortChange |= USB_PORT_STAT_C_CONNECTION;
+ 		if (status & USBPORTSC_PEC)
+ 			wPortChange |= USB_PORT_STAT_C_ENABLE;
+-		if (status & USBPORTSC_OCC)
++		if ((status & USBPORTSC_OCC) && !ignore_oc)
+ 			wPortChange |= USB_PORT_STAT_C_OVERCURRENT;
+ 
+ 		if (test_bit(port, &uhci->port_c_suspend)) {

commit a120586873d3d64de93bd6d593d237e131994e58
+Author: Alan Stern 
+Date:   Wed Dec 6 20:32:37 2006 -0800
+
+    [PATCH] Allow NULL pointers in percpu_free
+    
+    The patch (as824b) makes percpu_free() ignore NULL arguments, as one would
+    expect for a deallocation routine.  (Note that free_percpu is #defined as
+    percpu_free in include/linux/percpu.h.) A few callers are updated to remove
+    now-unneeded tests for NULL.  A few other callers already seem to assume
+    that passing a NULL pointer to percpu_free() is okay!
+    
+    The patch also removes an unnecessary NULL check in percpu_depopulate().
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/i386/kernel/acpi/cstate.c b/arch/i386/kernel/acpi/cstate.c
+index 4664b55f623e..12e937c1ce4b 100644
+--- a/arch/i386/kernel/acpi/cstate.c
++++ b/arch/i386/kernel/acpi/cstate.c
+@@ -156,10 +156,8 @@ static int __init ffh_cstate_init(void)
+ 
+ static void __exit ffh_cstate_exit(void)
+ {
+-	if (cpu_cstate_entry) {
+-		free_percpu(cpu_cstate_entry);
+-		cpu_cstate_entry = NULL;
+-	}
++	free_percpu(cpu_cstate_entry);
++	cpu_cstate_entry = NULL;
+ }
+ 
+ arch_initcall(ffh_cstate_init);
+diff --git a/block/blktrace.c b/block/blktrace.c
+index 74e02c04b2da..d3679dd1d220 100644
+--- a/block/blktrace.c
++++ b/block/blktrace.c
+@@ -394,8 +394,7 @@ static int blk_trace_setup(request_queue_t *q, struct block_device *bdev,
+ 	if (bt) {
+ 		if (bt->dropped_file)
+ 			debugfs_remove(bt->dropped_file);
+-		if (bt->sequence)
+-			free_percpu(bt->sequence);
++		free_percpu(bt->sequence);
+ 		if (bt->rchan)
+ 			relay_close(bt->rchan);
+ 		kfree(bt);
+diff --git a/mm/allocpercpu.c b/mm/allocpercpu.c
+index eaa9abeea536..b2486cf887a0 100644
+--- a/mm/allocpercpu.c
++++ b/mm/allocpercpu.c
+@@ -17,10 +17,9 @@
+ void percpu_depopulate(void *__pdata, int cpu)
+ {
+ 	struct percpu_data *pdata = __percpu_disguise(__pdata);
+-	if (pdata->ptrs[cpu]) {
+-		kfree(pdata->ptrs[cpu]);
+-		pdata->ptrs[cpu] = NULL;
+-	}
++
++	kfree(pdata->ptrs[cpu]);
++	pdata->ptrs[cpu] = NULL;
+ }
+ EXPORT_SYMBOL_GPL(percpu_depopulate);
+ 
+@@ -123,6 +122,8 @@ EXPORT_SYMBOL_GPL(__percpu_alloc_mask);
+  */
+ void percpu_free(void *__pdata)
+ {
++	if (unlikely(!__pdata))
++		return;
+ 	__percpu_depopulate_mask(__pdata, &cpu_possible_map);
+ 	kfree(__percpu_disguise(__pdata));
+ }
+diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
+index 87c8f54872b7..e5cd83b2205d 100644
+--- a/net/ipv6/af_inet6.c
++++ b/net/ipv6/af_inet6.c
+@@ -720,10 +720,8 @@ snmp6_mib_free(void *ptr[2])
+ {
+ 	if (ptr == NULL)
+ 		return;
+-	if (ptr[0])
+-		free_percpu(ptr[0]);
+-	if (ptr[1])
+-		free_percpu(ptr[1]);
++	free_percpu(ptr[0]);
++	free_percpu(ptr[1]);
+ 	ptr[0] = ptr[1] = NULL;
+ }
+ 

commit 94fcda1f8ab5e0cacc381c5ca1cc9aa6ad523576
+Author: Alan Stern 
+Date:   Mon Nov 20 11:38:46 2006 -0500
+
+    usbcore: remove unused argument in autosuspend
+    
+    Thanks to several earlier patches, usb_autosuspend_device() and
+    usb_autoresume_device() are never called with a second argument other
+    than 1.  This patch (as819) removes the now-redundant argument.
+    
+    It also consolidates some common code between those two routines,
+    putting it into a new subroutine called usb_autopm_do_device().  And
+    it includes a sizable kerneldoc update for the affected functions.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index fed92be63b5e..3ed4cb2d56d9 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -561,7 +561,7 @@ static int usbdev_open(struct inode *inode, struct file *file)
+ 		dev = inode->i_private;
+ 	if (!dev)
+ 		goto out;
+-	ret = usb_autoresume_device(dev, 1);
++	ret = usb_autoresume_device(dev);
+ 	if (ret)
+ 		goto out;
+ 
+@@ -609,7 +609,7 @@ static int usbdev_release(struct inode *inode, struct file *file)
+ 			releaseintf(ps, ifnum);
+ 	}
+ 	destroy_all_async(ps);
+-	usb_autosuspend_device(dev, 1);
++	usb_autosuspend_device(dev);
+ 	usb_unlock_device(dev);
+ 	usb_put_dev(dev);
+ 	put_pid(ps->disc_pid);
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 0fa15bd62c48..d6eb5ce1dd1d 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -205,7 +205,7 @@ static int usb_probe_interface(struct device *dev)
+ 	if (id) {
+ 		dev_dbg(dev, "%s - got id\n", __FUNCTION__);
+ 
+-		error = usb_autoresume_device(udev, 1);
++		error = usb_autoresume_device(udev);
+ 		if (error)
+ 			return error;
+ 
+@@ -229,7 +229,7 @@ static int usb_probe_interface(struct device *dev)
+ 		} else
+ 			intf->condition = USB_INTERFACE_BOUND;
+ 
+-		usb_autosuspend_device(udev, 1);
++		usb_autosuspend_device(udev);
+ 	}
+ 
+ 	return error;
+@@ -247,7 +247,7 @@ static int usb_unbind_interface(struct device *dev)
+ 
+ 	/* Autoresume for set_interface call below */
+ 	udev = interface_to_usbdev(intf);
+-	error = usb_autoresume_device(udev, 1);
++	error = usb_autoresume_device(udev);
+ 
+ 	/* release all urbs for this interface */
+ 	usb_disable_interface(interface_to_usbdev(intf), intf);
+@@ -265,7 +265,7 @@ static int usb_unbind_interface(struct device *dev)
+ 	intf->needs_remote_wakeup = 0;
+ 
+ 	if (!error)
+-		usb_autosuspend_device(udev, 1);
++		usb_autosuspend_device(udev);
+ 
+ 	return 0;
+ }
+@@ -940,6 +940,8 @@ static int usb_resume_interface(struct usb_interface *intf)
+ 	return status;
+ }
+ 
++#ifdef	CONFIG_USB_SUSPEND
++
+ /* Internal routine to check whether we may autosuspend a device. */
+ static int autosuspend_check(struct usb_device *udev)
+ {
+@@ -970,6 +972,12 @@ static int autosuspend_check(struct usb_device *udev)
+ 	return 0;
+ }
+ 
++#else
++
++#define autosuspend_check(udev)		0
++
++#endif
++
+ /**
+  * usb_suspend_both - suspend a USB device and its interfaces
+  * @udev: the usb_device to suspend
+@@ -1048,7 +1056,7 @@ int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 
+ 	/* If the suspend succeeded, propagate it up the tree */
+ 	} else if (parent)
+-		usb_autosuspend_device(parent, 1);
++		usb_autosuspend_device(parent);
+ 
+ 	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+ 	return status;
+@@ -1096,11 +1104,11 @@ int usb_resume_both(struct usb_device *udev)
+ 	/* Propagate the resume up the tree, if necessary */
+ 	if (udev->state == USB_STATE_SUSPENDED) {
+ 		if (parent) {
+-			status = usb_autoresume_device(parent, 1);
++			status = usb_autoresume_device(parent);
+ 			if (status == 0) {
+ 				status = usb_resume_device(udev);
+ 				if (status) {
+-					usb_autosuspend_device(parent, 1);
++					usb_autosuspend_device(parent);
+ 
+ 					/* It's possible usb_resume_device()
+ 					 * failed after the port was
+@@ -1146,39 +1154,53 @@ int usb_resume_both(struct usb_device *udev)
+ 
+ #ifdef CONFIG_USB_SUSPEND
+ 
++/* Internal routine to adjust a device's usage counter and change
++ * its autosuspend state.
++ */
++static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt)
++{
++	int	status = 0;
++
++	usb_pm_lock(udev);
++	udev->pm_usage_cnt += inc_usage_cnt;
++	WARN_ON(udev->pm_usage_cnt < 0);
++	if (inc_usage_cnt >= 0 && udev->pm_usage_cnt > 0) {
++		udev->auto_pm = 1;
++		status = usb_resume_both(udev);
++		if (status != 0)
++			udev->pm_usage_cnt -= inc_usage_cnt;
++	} else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
++		queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
++				USB_AUTOSUSPEND_DELAY);
++	usb_pm_unlock(udev);
++	return status;
++}
++
+ /**
+  * usb_autosuspend_device - delayed autosuspend of a USB device and its interfaces
+  * @udev: the usb_device to autosuspend
+- * @dec_usage_cnt: flag to decrement @udev's PM-usage counter
+  *
+  * This routine should be called when a core subsystem is finished using
+  * @udev and wants to allow it to autosuspend.  Examples would be when
+  * @udev's device file in usbfs is closed or after a configuration change.
+  *
+- * @dec_usage_cnt should be 1 if the subsystem previously incremented
+- * @udev's usage counter (such as by passing 1 to usb_autoresume_device);
+- * otherwise it should be 0.
+- *
+- * If the usage counter for @udev or any of its active interfaces is greater
+- * than 0, the autosuspend request will not be queued.  (If an interface
+- * driver does not support autosuspend then its usage counter is permanently
+- * positive.)  Likewise, if an interface driver requires remote-wakeup
+- * capability during autosuspend but remote wakeup is disabled, the
+- * autosuspend will fail.
++ * @udev's usage counter is decremented.  If it or any of the usage counters
++ * for an active interface is greater than 0, no autosuspend request will be
++ * queued.  (If an interface driver does not support autosuspend then its
++ * usage counter is permanently positive.)  Furthermore, if an interface
++ * driver requires remote-wakeup capability during autosuspend but remote
++ * wakeup is disabled, the autosuspend will fail.
+  *
+  * Often the caller will hold @udev's device lock, but this is not
+  * necessary.
+  *
+  * This routine can run only in process context.
+  */
+-void usb_autosuspend_device(struct usb_device *udev, int dec_usage_cnt)
++void usb_autosuspend_device(struct usb_device *udev)
+ {
+-	usb_pm_lock(udev);
+-	udev->pm_usage_cnt -= dec_usage_cnt;
+-	if (autosuspend_check(udev) == 0)
+-		queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+-				USB_AUTOSUSPEND_DELAY);
+-	usb_pm_unlock(udev);
++	int	status;
++
++	status = usb_autopm_do_device(udev, -1);
+ 	// dev_dbg(&udev->dev, "%s: cnt %d\n",
+ 	//		__FUNCTION__, udev->pm_usage_cnt);
+ }
+@@ -1186,39 +1208,27 @@ void usb_autosuspend_device(struct usb_device *udev, int dec_usage_cnt)
+ /**
+  * usb_autoresume_device - immediately autoresume a USB device and its interfaces
+  * @udev: the usb_device to autoresume
+- * @inc_usage_cnt: flag to increment @udev's PM-usage counter
+  *
+  * This routine should be called when a core subsystem wants to use @udev
+- * and needs to guarantee that it is not suspended.  In addition, the
+- * caller can prevent @udev from being autosuspended subsequently.  (Note
+- * that this will not prevent suspend events originating in the PM core.)
+- * Examples would be when @udev's device file in usbfs is opened (autosuspend
+- * should be prevented until the file is closed) or when a remote-wakeup
+- * request is received (later autosuspends should not be prevented).
++ * and needs to guarantee that it is not suspended.  No autosuspend will
++ * occur until usb_autosuspend_device is called.  (Note that this will not
++ * prevent suspend events originating in the PM core.)  Examples would be
++ * when @udev's device file in usbfs is opened or when a remote-wakeup
++ * request is received.
+  *
+- * @inc_usage_cnt should be 1 to increment @udev's usage counter and prevent
+- * autosuspends.  This prevention will persist until the usage counter is
+- * decremented again (such as by passing 1 to usb_autosuspend_device).
+- * Otherwise @inc_usage_cnt should be 0 to leave the usage counter unchanged.
+- * Regardless, if the autoresume fails then the usage counter is not
+- * incremented.
++ * @udev's usage counter is incremented to prevent subsequent autosuspends.
++ * However if the autoresume fails then the usage counter is re-decremented.
+  *
+  * Often the caller will hold @udev's device lock, but this is not
+  * necessary (and attempting it might cause deadlock).
+  *
+  * This routine can run only in process context.
+  */
+-int usb_autoresume_device(struct usb_device *udev, int inc_usage_cnt)
++int usb_autoresume_device(struct usb_device *udev)
+ {
+ 	int	status;
+ 
+-	usb_pm_lock(udev);
+-	udev->pm_usage_cnt += inc_usage_cnt;
+-	udev->auto_pm = 1;
+-	status = usb_resume_both(udev);
+-	if (status != 0)
+-		udev->pm_usage_cnt -= inc_usage_cnt;
+-	usb_pm_unlock(udev);
++	status = usb_autopm_do_device(udev, 1);
+ 	// dev_dbg(&udev->dev, "%s: status %d cnt %d\n",
+ 	//		__FUNCTION__, status, udev->pm_usage_cnt);
+ 	return status;
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index e46d38b18249..0ce393eb3c4b 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1234,7 +1234,7 @@ void usb_disconnect(struct usb_device **pdev)
+ 	if (udev->parent) {
+ 		usb_pm_lock(udev);
+ 		if (!udev->discon_suspended)
+-			usb_autosuspend_device(udev->parent, 1);
++			usb_autosuspend_device(udev->parent);
+ 		usb_pm_unlock(udev);
+ 	}
+ 
+@@ -1368,7 +1368,7 @@ static int __usb_new_device(void *void_data)
+ 
+ 	/* Increment the parent's count of unsuspended children */
+ 	if (udev->parent)
+-		usb_autoresume_device(udev->parent, 1);
++		usb_autoresume_device(udev->parent);
+ 
+ exit:
+ 	module_put(THIS_MODULE);
+@@ -1881,12 +1881,12 @@ static int remote_wakeup(struct usb_device *udev)
+ 	usb_lock_device(udev);
+ 	if (udev->state == USB_STATE_SUSPENDED) {
+ 		dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-");
+-		status = usb_autoresume_device(udev, 1);
++		status = usb_autoresume_device(udev);
+ 
+ 		/* Give the interface drivers a chance to do something,
+ 		 * then autosuspend the device again. */
+ 		if (status == 0)
+-			usb_autosuspend_device(udev, 1);
++			usb_autosuspend_device(udev);
+ 	}
+ 	usb_unlock_device(udev);
+ 	return status;
+@@ -3099,7 +3099,7 @@ int usb_reset_composite_device(struct usb_device *udev,
+ 	}
+ 
+ 	/* Prevent autosuspend during the reset */
+-	usb_autoresume_device(udev, 1);
++	usb_autoresume_device(udev);
+ 
+ 	if (iface && iface->condition != USB_INTERFACE_BINDING)
+ 		iface = NULL;
+@@ -3142,7 +3142,7 @@ int usb_reset_composite_device(struct usb_device *udev,
+ 		}
+ 	}
+ 
+-	usb_autosuspend_device(udev, 1);
++	usb_autosuspend_device(udev);
+ 	return ret;
+ }
+ EXPORT_SYMBOL(usb_reset_composite_device);
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 5684d8722922..29b0fa9ff9d0 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1398,7 +1398,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 	}
+ 
+ 	/* Wake up the device so we can send it the Set-Config request */
+-	ret = usb_autoresume_device(dev, 1);
++	ret = usb_autoresume_device(dev);
+ 	if (ret)
+ 		goto free_interfaces;
+ 
+@@ -1421,7 +1421,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 	dev->actconfig = cp;
+ 	if (!cp) {
+ 		usb_set_device_state(dev, USB_STATE_ADDRESS);
+-		usb_autosuspend_device(dev, 1);
++		usb_autosuspend_device(dev);
+ 		goto free_interfaces;
+ 	}
+ 	usb_set_device_state(dev, USB_STATE_CONFIGURED);
+@@ -1490,7 +1490,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 		usb_create_sysfs_intf_files (intf);
+ 	}
+ 
+-	usb_autosuspend_device(dev, 1);
++	usb_autosuspend_device(dev);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 13322e33f912..17830a81be14 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -64,14 +64,13 @@ static inline void usb_pm_unlock(struct usb_device *udev) {}
+ 
+ #define USB_AUTOSUSPEND_DELAY	(HZ*2)
+ 
+-extern void usb_autosuspend_device(struct usb_device *udev, int dec_busy_cnt);
+-extern int usb_autoresume_device(struct usb_device *udev, int inc_busy_cnt);
++extern void usb_autosuspend_device(struct usb_device *udev);
++extern int usb_autoresume_device(struct usb_device *udev);
+ 
+ #else
+ 
+-#define usb_autosuspend_device(udev, dec_busy_cnt)	do {} while (0)
+-static inline int usb_autoresume_device(struct usb_device *udev,
+-		int inc_busy_cnt)
++#define usb_autosuspend_device(udev)	do {} while (0)
++static inline int usb_autoresume_device(struct usb_device *udev)
+ {
+ 	return 0;
+ }

commit ee49fb5dc89d34f1794ac9362fa97c1a640f7ddd
+Author: Alan Stern 
+Date:   Wed Nov 22 16:55:54 2006 -0500
+
+    USB: keep count of unsuspended children
+    
+    This patch (as818b) simplifies autosuspend processing by keeping track
+    of the number of unsuspended children of each USB hub.  This will
+    permit us to avoid a good deal of unnecessary work all the time; we
+    will no longer have to create a bunch of workqueue entries to carry
+    out autosuspend requests, only to have them fail because one of the
+    hub's children isn't suspended.
+    
+    The basic idea is simple.  There already is a usage counter in the
+    usb_device structure for preventing autosuspends.  The patch just
+    increments that counter for every unsuspended child.  There's only one
+    tricky part: When a device disconnects we need to remember whether it
+    was suspended at the time (leave the counter alone) or not (decrement
+    the counter).
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 40c1bf09b2b7..0fa15bd62c48 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1048,7 +1048,7 @@ int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 
+ 	/* If the suspend succeeded, propagate it up the tree */
+ 	} else if (parent)
+-		usb_autosuspend_device(parent, 0);
++		usb_autosuspend_device(parent, 1);
+ 
+ 	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+ 	return status;
+@@ -1096,9 +1096,25 @@ int usb_resume_both(struct usb_device *udev)
+ 	/* Propagate the resume up the tree, if necessary */
+ 	if (udev->state == USB_STATE_SUSPENDED) {
+ 		if (parent) {
+-			usb_pm_lock(parent);
+-			parent->auto_pm = 1;
+-			status = usb_resume_both(parent);
++			status = usb_autoresume_device(parent, 1);
++			if (status == 0) {
++				status = usb_resume_device(udev);
++				if (status) {
++					usb_autosuspend_device(parent, 1);
++
++					/* It's possible usb_resume_device()
++					 * failed after the port was
++					 * unsuspended, causing udev to be
++					 * logically disconnected.  We don't
++					 * want usb_disconnect() to autosuspend
++					 * the parent again, so tell it that
++					 * udev disconnected while still
++					 * suspended. */
++					if (udev->state ==
++							USB_STATE_NOTATTACHED)
++						udev->discon_suspended = 1;
++				}
++			}
+ 		} else {
+ 
+ 			/* We can't progagate beyond the USB subsystem,
+@@ -1107,11 +1123,9 @@ int usb_resume_both(struct usb_device *udev)
+ 			if (udev->dev.parent->power.power_state.event !=
+ 					PM_EVENT_ON)
+ 				status = -EHOSTUNREACH;
+-		}
+-		if (status == 0)
+-			status = usb_resume_device(udev);
+-		if (parent)
+-			usb_pm_unlock(parent);
++			else
++				status = usb_resume_device(udev);
++ 		}
+ 	} else {
+ 
+ 		/* Needed only for setting udev->dev.power.power_state.event
+@@ -1119,8 +1133,6 @@ int usb_resume_both(struct usb_device *udev)
+ 		status = usb_resume_device(udev);
+ 	}
+ 
+-	/* Now the parent won't suspend until we are finished */
+-
+ 	if (status == 0 && udev->actconfig) {
+ 		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+ 			intf = udev->actconfig->interface[i];
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 46df5e60764b..e46d38b18249 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1039,6 +1039,8 @@ static void recursively_mark_NOTATTACHED(struct usb_device *udev)
+ 		if (udev->children[i])
+ 			recursively_mark_NOTATTACHED(udev->children[i]);
+ 	}
++	if (udev->state == USB_STATE_SUSPENDED)
++		udev->discon_suspended = 1;
+ 	udev->state = USB_STATE_NOTATTACHED;
+ }
+ 
+@@ -1228,6 +1230,14 @@ void usb_disconnect(struct usb_device **pdev)
+ 	*pdev = NULL;
+ 	spin_unlock_irq(&device_state_lock);
+ 
++	/* Decrement the parent's count of unsuspended children */
++	if (udev->parent) {
++		usb_pm_lock(udev);
++		if (!udev->discon_suspended)
++			usb_autosuspend_device(udev->parent, 1);
++		usb_pm_unlock(udev);
++	}
++
+ 	put_device(&udev->dev);
+ }
+ 
+@@ -1356,6 +1366,10 @@ static int __usb_new_device(void *void_data)
+ 		goto fail;
+ 	}
+ 
++	/* Increment the parent's count of unsuspended children */
++	if (udev->parent)
++		usb_autoresume_device(udev->parent, 1);
++
+ exit:
+ 	module_put(THIS_MODULE);
+ 	return err;
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 5634a2d91ec0..0cd73edeef13 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -362,6 +362,7 @@ struct usb_device {
+ 	u8 portnum;			/* Parent port number (origin 1) */
+ 	u8 level;			/* Number of USB hub ancestors */
+ 
++	unsigned discon_suspended:1;	/* Disconnected while suspended */
+ 	unsigned have_langid:1;		/* whether string_langid is valid */
+ 	int string_langid;		/* language ID for strings */
+ 

commit d25450c68767481f7c9cc4823a6da8235db40be6
+Author: Alan Stern 
+Date:   Mon Nov 20 11:14:30 2006 -0500
+
+    USB hub: simplify remote-wakeup handling
+    
+    This patch (as817) simplifies the remote-wakeup processing in the hub
+    driver.  Now instead of using a specialized code path, it relies on
+    the standard USB resume routines.  The hub_port_resume() function does
+    an initial get_port_status() to see whether the port has already
+    resumed itself (as it does when a remote-wakeup request is sent).
+    This will slow down handling of other resume events slightly, but not
+    enough to matter.
+    
+    The patch also changes the hub_port_status() routine, making it return
+    an error if a short reply is received.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 55812a5ac661..46df5e60764b 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1409,10 +1409,12 @@ static int hub_port_status(struct usb_hub *hub, int port1,
+ 	int ret;
+ 
+ 	ret = get_port_status(hub->hdev, port1, &hub->status->port);
+-	if (ret < 0)
++	if (ret < 4) {
+ 		dev_err (hub->intfdev,
+ 			"%s failed (err = %d)\n", __FUNCTION__, ret);
+-	else {
++		if (ret >= 0)
++			ret = -EIO;
++	} else {
+ 		*status = le16_to_cpu(hub->status->port.wPortStatus);
+ 		*change = le16_to_cpu(hub->status->port.wPortChange); 
+ 		ret = 0;
+@@ -1760,6 +1762,12 @@ static int
+ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+ {
+ 	int	status;
++	u16	portchange, portstatus;
++
++	/* Skip the initial Clear-Suspend step for a remote wakeup */
++	status = hub_port_status(hub, port1, &portstatus, &portchange);
++	if (status == 0 && !(portstatus & USB_PORT_STAT_SUSPEND))
++		goto SuspendCleared;
+ 
+ 	// dev_dbg(hub->intfdev, "resume port %d\n", port1);
+ 
+@@ -1773,9 +1781,6 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+ 			"can't resume port %d, status %d\n",
+ 			port1, status);
+ 	} else {
+-		u16		devstatus;
+-		u16		portchange;
+-
+ 		/* drive resume for at least 20 msec */
+ 		if (udev)
+ 			dev_dbg(&udev->dev, "usb %sresume\n",
+@@ -1790,16 +1795,15 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+ 		 * stop resume signaling.  Then finish the resume
+ 		 * sequence.
+ 		 */
+-		devstatus = portchange = 0;
+-		status = hub_port_status(hub, port1,
+-				&devstatus, &portchange);
++		status = hub_port_status(hub, port1, &portstatus, &portchange);
++SuspendCleared:
+ 		if (status < 0
+-				|| (devstatus & LIVE_FLAGS) != LIVE_FLAGS
+-				|| (devstatus & USB_PORT_STAT_SUSPEND) != 0
++				|| (portstatus & LIVE_FLAGS) != LIVE_FLAGS
++				|| (portstatus & USB_PORT_STAT_SUSPEND) != 0
+ 				) {
+ 			dev_dbg(hub->intfdev,
+ 				"port %d status %04x.%04x after resume, %d\n",
+-				port1, portchange, devstatus, status);
++				port1, portchange, portstatus, status);
+ 			if (status >= 0)
+ 				status = -ENODEV;
+ 		} else {
+@@ -1860,23 +1864,16 @@ static int remote_wakeup(struct usb_device *udev)
+ {
+ 	int	status = 0;
+ 
+-	/* All this just to avoid sending a port-resume message
+-	 * to the parent hub! */
+-
+ 	usb_lock_device(udev);
+-	usb_pm_lock(udev);
+ 	if (udev->state == USB_STATE_SUSPENDED) {
+ 		dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-");
+-		/* TRSMRCY = 10 msec */
+-		msleep(10);
+-		status = finish_port_resume(udev);
++		status = usb_autoresume_device(udev, 1);
++
++		/* Give the interface drivers a chance to do something,
++		 * then autosuspend the device again. */
+ 		if (status == 0)
+-			udev->dev.power.power_state.event = PM_EVENT_ON;
++			usb_autosuspend_device(udev, 1);
+ 	}
+-	usb_pm_unlock(udev);
+-
+-	if (status == 0)
+-		usb_autoresume_device(udev, 0);
+ 	usb_unlock_device(udev);
+ 	return status;
+ }

commit ce3615879ae85373c03744b45b7c2d7ae5e29b2a
+Author: Alan Stern 
+Date:   Mon Nov 20 11:12:22 2006 -0500
+
+    USB: struct usb_device: change flag to bitflag
+    
+    This patch (as816) changes an existing flag in the usb_device
+    structure to a bitflag, preparing the way for more bitflags to come
+    in the future.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 7729c0744886..5684d8722922 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -764,7 +764,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
+ 			err = -EINVAL;
+ 			goto errout;
+ 		} else {
+-			dev->have_langid = -1;
++			dev->have_langid = 1;
+ 			dev->string_langid = tbuf[2] | (tbuf[3]<< 8);
+ 				/* always use the first langid listed */
+ 			dev_dbg (&dev->dev, "default language 0x%04x\n",
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 864c6c21c21e..5634a2d91ec0 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -362,7 +362,7 @@ struct usb_device {
+ 	u8 portnum;			/* Parent port number (origin 1) */
+ 	u8 level;			/* Number of USB hub ancestors */
+ 
+-	int have_langid;		/* whether string_langid is valid */
++	unsigned have_langid:1;		/* whether string_langid is valid */
+ 	int string_langid;		/* language ID for strings */
+ 
+ 	/* static strings from the device */

commit 1f9fc882d92f3ff390455836f98d7ddc36d4e4c3
+Author: Alan Stern 
+Date:   Mon Nov 20 11:06:59 2006 -0500
+
+    OHCI: make autostop conditional on CONFIG_PM
+    
+    Unlike UHCI, OHCI does not exert any DMA load on the system when no
+    devices are connected.  Consequently there is no advantage to doing
+    an autostop other than the power savings, so we shouldn't compile the
+    necessary code unless CONFIG_PM is enabled.
+    
+    This patch (as820) makes the root-hub suspend and resume routines
+    conditional on CONFIG_PM.  It also prevents autostop from activating
+    if the device_may_wakeup flag isn't set; some people use this flag to
+    alert the driver about Resume-Detect bugs in the hardware.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index 4c9492779ede..2441642cb7b4 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -56,7 +56,6 @@ static void finish_unlinks (struct ohci_hcd *, u16);
+ 
+ #ifdef	CONFIG_PM
+ static int ohci_restart(struct ohci_hcd *ohci);
+-#endif
+ 
+ static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop)
+ __releases(ohci->lock)
+@@ -187,7 +186,6 @@ __acquires(ohci->lock)
+ 		ohci_dbg (ohci, "lost power\n");
+ 		status = -EBUSY;
+ 	}
+-#ifdef	CONFIG_PM
+ 	if (status == -EBUSY) {
+ 		if (!autostopped) {
+ 			spin_unlock_irq (&ohci->lock);
+@@ -197,7 +195,6 @@ __acquires(ohci->lock)
+ 		}
+ 		return status;
+ 	}
+-#endif
+ 	if (status != -EINPROGRESS)
+ 		return status;
+ 	if (autostopped)
+@@ -291,8 +288,6 @@ __acquires(ohci->lock)
+ 	return 0;
+ }
+ 
+-#ifdef	CONFIG_PM
+-
+ static int ohci_bus_suspend (struct usb_hcd *hcd)
+ {
+ 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+@@ -330,6 +325,83 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
+ 	return rc;
+ }
+ 
++/* Carry out polling-, autostop-, and autoresume-related state changes */
++static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
++		int any_connected)
++{
++	int	poll_rh = 1;
++
++	switch (ohci->hc_control & OHCI_CTRL_HCFS) {
++
++	case OHCI_USB_OPER:
++		/* keep on polling until we know a device is connected
++		 * and RHSC is enabled */
++		if (!ohci->autostop) {
++			if (any_connected ||
++					!device_may_wakeup(&ohci_to_hcd(ohci)
++						->self.root_hub->dev)) {
++				if (ohci_readl(ohci, &ohci->regs->intrenable) &
++						OHCI_INTR_RHSC)
++					poll_rh = 0;
++			} else {
++				ohci->autostop = 1;
++				ohci->next_statechange = jiffies + HZ;
++			}
++
++		/* if no devices have been attached for one second, autostop */
++		} else {
++			if (changed || any_connected) {
++				ohci->autostop = 0;
++				ohci->next_statechange = jiffies +
++						STATECHANGE_DELAY;
++			} else if (time_after_eq(jiffies,
++						ohci->next_statechange)
++					&& !ohci->ed_rm_list
++					&& !(ohci->hc_control &
++						OHCI_SCHED_ENABLES)) {
++				ohci_rh_suspend(ohci, 1);
++			}
++		}
++		break;
++
++	/* if there is a port change, autostart or ask to be resumed */
++	case OHCI_USB_SUSPEND:
++	case OHCI_USB_RESUME:
++		if (changed) {
++			if (ohci->autostop)
++				ohci_rh_resume(ohci);
++			else
++				usb_hcd_resume_root_hub(ohci_to_hcd(ohci));
++		} else {
++			/* everything is idle, no need for polling */
++			poll_rh = 0;
++		}
++		break;
++	}
++	return poll_rh;
++}
++
++#else	/* CONFIG_PM */
++
++static inline int ohci_rh_resume(struct ohci_hcd *ohci)
++{
++	return 0;
++}
++
++/* Carry out polling-related state changes.
++ * autostop isn't used when CONFIG_PM is turned off.
++ */
++static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
++		int any_connected)
++{
++	int	poll_rh = 1;
++
++	/* keep on polling until RHSC is enabled */
++	if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC)
++		poll_rh = 0;
++	return poll_rh;
++}
++
+ #endif	/* CONFIG_PM */
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -382,55 +454,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ 		}
+ 	}
+ 
+-	hcd->poll_rh = 1;
+-
+-	/* carry out appropriate state changes */
+-	switch (ohci->hc_control & OHCI_CTRL_HCFS) {
+-
+-	case OHCI_USB_OPER:
+-		/* keep on polling until we know a device is connected
+-		 * and RHSC is enabled */
+-		if (!ohci->autostop) {
+-			if (any_connected) {
+-				if (ohci_readl(ohci, &ohci->regs->intrenable) &
+-						OHCI_INTR_RHSC)
+-					hcd->poll_rh = 0;
+-			} else {
+-				ohci->autostop = 1;
+-				ohci->next_statechange = jiffies + HZ;
+-			}
+-
+-		/* if no devices have been attached for one second, autostop */
+-		} else {
+-			if (changed || any_connected) {
+-				ohci->autostop = 0;
+-				ohci->next_statechange = jiffies +
+-						STATECHANGE_DELAY;
+-			} else if (device_may_wakeup(&hcd->self.root_hub->dev)
+-					&& time_after_eq(jiffies,
+-						ohci->next_statechange)
+-					&& !ohci->ed_rm_list
+-					&& !(ohci->hc_control &
+-						OHCI_SCHED_ENABLES)) {
+-				ohci_rh_suspend (ohci, 1);
+-			}
+-		}
+-		break;
+-
+-	/* if there is a port change, autostart or ask to be resumed */
+-	case OHCI_USB_SUSPEND:
+-	case OHCI_USB_RESUME:
+-		if (changed) {
+-			if (ohci->autostop)
+-				ohci_rh_resume (ohci);
+-			else
+-				usb_hcd_resume_root_hub (hcd);
+-		} else {
+-			/* everything is idle, no need for polling */
+-			hcd->poll_rh = 0;
+-		}
+-		break;
+-	}
++	hcd->poll_rh = ohci_root_hub_state_changes(ohci, changed,
++			any_connected);
+ 
+ done:
+ 	spin_unlock_irqrestore (&ohci->lock, flags);

commit 40f122f343797d02390c5a157372cac0c5b50bb7
+Author: Alan Stern 
+Date:   Thu Nov 9 14:44:33 2006 -0500
+
+    USB: Add autosuspend support to the hub driver
+    
+    This patch (as742b) adds autosuspend/autoresume support to the USB hub
+    driver.  The largest aspect of the change is that we no longer need a
+    special flag for root hubs that want to be resumed.  Now every hub is
+    autoresumed whenever khubd needs to access it.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index f6e692180587..55812a5ac661 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -65,7 +65,6 @@ struct usb_hub {
+ 	unsigned		limited_power:1;
+ 	unsigned		quiescing:1;
+ 	unsigned		activating:1;
+-	unsigned		resume_root_hub:1;
+ 
+ 	unsigned		has_indicators:1;
+ 	u8			indicator[USB_MAXCHILDREN];
+@@ -328,6 +327,9 @@ static void kick_khubd(struct usb_hub *hub)
+ {
+ 	unsigned long	flags;
+ 
++	/* Suppress autosuspend until khubd runs */
++	to_usb_interface(hub->intfdev)->pm_usage_cnt = 1;
++
+ 	spin_lock_irqsave(&hub_event_lock, flags);
+ 	if (list_empty(&hub->event_list)) {
+ 		list_add_tail(&hub->event_list, &hub_event_list);
+@@ -509,7 +511,6 @@ static void hub_quiesce(struct usb_hub *hub)
+ 	/* (nonblocking) khubd and related activity won't re-trigger */
+ 	hub->quiescing = 1;
+ 	hub->activating = 0;
+-	hub->resume_root_hub = 0;
+ 
+ 	/* (blocking) stop khubd and related activity */
+ 	usb_kill_urb(hub->urb);
+@@ -525,7 +526,7 @@ static void hub_activate(struct usb_hub *hub)
+ 
+ 	hub->quiescing = 0;
+ 	hub->activating = 1;
+-	hub->resume_root_hub = 0;
++
+ 	status = usb_submit_urb(hub->urb, GFP_NOIO);
+ 	if (status < 0)
+ 		dev_err(hub->intfdev, "activate --> %d\n", status);
+@@ -940,6 +941,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
+ 	INIT_WORK(&hub->leds, led_work, hub);
+ 
+ 	usb_set_intfdata (intf, hub);
++	intf->needs_remote_wakeup = 1;
+ 
+ 	if (hdev->speed == USB_SPEED_HIGH)
+ 		highspeed_hubs++;
+@@ -1938,6 +1940,8 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+ 		}
+ 	}
+ 
++	dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
++
+ 	/* "global suspend" of the downstream HC-to-USB interface */
+ 	if (!hdev->parent) {
+ 		struct usb_bus	*bus = hdev->bus;
+@@ -1960,10 +1964,12 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+ 
+ static int hub_resume(struct usb_interface *intf)
+ {
+-	struct usb_device	*hdev = interface_to_usbdev(intf);
+ 	struct usb_hub		*hub = usb_get_intfdata (intf);
++	struct usb_device	*hdev = hub->hdev;
+ 	int			status;
+ 
++	dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
++
+ 	/* "global resume" of the downstream HC-to-USB interface */
+ 	if (!hdev->parent) {
+ 		struct usb_bus	*bus = hdev->bus;
+@@ -2002,7 +2008,6 @@ void usb_resume_root_hub(struct usb_device *hdev)
+ {
+ 	struct usb_hub *hub = hdev_to_hub(hdev);
+ 
+-	hub->resume_root_hub = 1;
+ 	kick_khubd(hub);
+ }
+ 
+@@ -2639,16 +2644,13 @@ static void hub_events(void)
+ 		intf = to_usb_interface(hub->intfdev);
+ 		hub_dev = &intf->dev;
+ 
+-		i = hub->resume_root_hub;
+-
+-		dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x%s\n",
++		dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n",
+ 				hdev->state, hub->descriptor
+ 					? hub->descriptor->bNbrPorts
+ 					: 0,
+ 				/* NOTE: expects max 15 ports... */
+ 				(u16) hub->change_bits[0],
+-				(u16) hub->event_bits[0],
+-				i ? ", resume root" : "");
++				(u16) hub->event_bits[0]);
+ 
+ 		usb_get_intf(intf);
+ 		spin_unlock_irq(&hub_event_lock);
+@@ -2669,16 +2671,16 @@ static void hub_events(void)
+ 			goto loop;
+ 		}
+ 
+-		/* Is this is a root hub wanting to reactivate the downstream
+-		 * ports?  If so, be sure the interface resumes even if its
+-		 * stub "device" node was never suspended.
+-		 */
+-		if (i)
+-			usb_autoresume_device(hdev, 0);
++		/* Autoresume */
++		ret = usb_autopm_get_interface(intf);
++		if (ret) {
++			dev_dbg(hub_dev, "Can't autoresume: %d\n", ret);
++			goto loop;
++		}
+ 
+-		/* If this is an inactive or suspended hub, do nothing */
++		/* If this is an inactive hub, do nothing */
+ 		if (hub->quiescing)
+-			goto loop;
++			goto loop_autopm;
+ 
+ 		if (hub->error) {
+ 			dev_dbg (hub_dev, "resetting for error %d\n",
+@@ -2688,7 +2690,7 @@ static void hub_events(void)
+ 			if (ret) {
+ 				dev_dbg (hub_dev,
+ 					"error resetting hub: %d\n", ret);
+-				goto loop;
++				goto loop_autopm;
+ 			}
+ 
+ 			hub->nerrors = 0;
+@@ -2816,6 +2818,10 @@ static void hub_events(void)
+ 		if (!hdev->parent && !hub->busy_bits[0])
+ 			usb_enable_root_hub_irq(hdev->bus);
+ 
++loop_autopm:
++		/* Allow autosuspend if we're not going to run again */
++		if (list_empty(&hub->event_list))
++			usb_autopm_enable(intf);
+ loop:
+ 		usb_unlock_device(hdev);
+ 		usb_put_intf(intf);
+@@ -2857,6 +2863,7 @@ static struct usb_driver hub_driver = {
+ 	.post_reset =	hub_post_reset,
+ 	.ioctl =	hub_ioctl,
+ 	.id_table =	hub_id_table,
++	.supports_autosuspend =	1,
+ };
+ 
+ int usb_hub_init(void)

commit 8c03356a559ced6fa78931f498193f776d67e445
+Author: Alan Stern 
+Date:   Thu Nov 9 14:42:16 2006 -0500
+
+    EHCI: Fix root-hub and port suspend/resume problems
+    
+    This patch (as738b) fixes numerous problems in the controller/root-hub
+    suspend/resume/remote-wakeup support in ehci-hcd:
+    
+            The bus_resume() routine should wake up only the ports that
+            were suspended by bus_suspend().  Ports that were already
+            suspended should remain that way.
+    
+            The interrupt mask is used to detect loss of power in the
+            bus_resume() routine (if the mask is 0 then power was lost).
+            However bus_suspend() always sets the mask to 0.  Instead the
+            mask should retain its normal value, with port-change-detect
+            interrupts disabled if remote wakeup is turned off.
+    
+            The interrupt mask should be reset to its correct value at the
+            end of bus_resume() regardless of whether power was lost.
+    
+            bus_resume() reinitializes the operational registers if power
+            was lost.  However those registers are not in the aux power
+            well, hence they can lose their values whenever the controller
+            is put into D3.  They should always be reinitialized.
+    
+            When a port-change interrupt occurs and the root hub is
+            suspended, the interrupt handler should request a root-hub
+            resume instead of starting up the controller all by itself.
+    
+            There's no need for the interrupt handler to request a
+            root-hub resume every time a suspended port sends a
+            remote-wakeup request.
+    
+            The pci_resume() method doesn't need to check for connected
+            ports when deciding whether or not to reset the controller.
+            It can make that decision based on whether Vaux power was
+            maintained.
+    
+            Even when the controller does not need to be reset,
+            pci_resume() must undo the effect of pci_suspend() by
+            re-enabling the interrupt mask.
+    
+            If power was lost, pci_resume() must not call ehci_run().
+            At this point the root hub is still supposed to be suspended,
+            not running.  It's enough to rewrite the command register and
+            set the configured_flag.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index f2ceb5fdbeb7..025d33313681 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -619,9 +619,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 		unsigned	i = HCS_N_PORTS (ehci->hcs_params);
+ 
+ 		/* resume root hub? */
+-		status = readl (&ehci->regs->command);
+-		if (!(status & CMD_RUN))
+-			writel (status | CMD_RUN, &ehci->regs->command);
++		if (!(readl(&ehci->regs->command) & CMD_RUN))
++			usb_hcd_resume_root_hub(hcd);
+ 
+ 		while (i--) {
+ 			int pstatus = readl (&ehci->regs->port_status [i]);
+@@ -638,7 +637,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 			 */
+ 			ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
+ 			ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
+-			usb_hcd_resume_root_hub(hcd);
+ 		}
+ 	}
+ 
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 0a56dfa2745d..bfe5f307cba6 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -34,6 +34,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ {
+ 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+ 	int			port;
++	int			mask;
+ 
+ 	if (time_before (jiffies, ehci->next_statechange))
+ 		msleep(5);
+@@ -51,14 +52,25 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 		ehci->reclaim_ready = 1;
+ 	ehci_work(ehci);
+ 
+-	/* suspend any active/unsuspended ports, maybe allow wakeup */
++	/* Unlike other USB host controller types, EHCI doesn't have
++	 * any notion of "global" or bus-wide suspend.  The driver has
++	 * to manually suspend all the active unsuspended ports, and
++	 * then manually resume them in the bus_resume() routine.
++	 */
++	ehci->bus_suspended = 0;
+ 	while (port--) {
+ 		u32 __iomem	*reg = &ehci->regs->port_status [port];
+ 		u32		t1 = readl (reg) & ~PORT_RWC_BITS;
+ 		u32		t2 = t1;
+ 
+-		if ((t1 & PORT_PE) && !(t1 & PORT_OWNER))
++		/* keep track of which ports we suspend */
++		if ((t1 & PORT_PE) && !(t1 & PORT_OWNER) &&
++				!(t1 & PORT_SUSPEND)) {
+ 			t2 |= PORT_SUSPEND;
++			set_bit(port, &ehci->bus_suspended);
++		}
++
++		/* enable remote wakeup on all ports */
+ 		if (device_may_wakeup(&hcd->self.root_hub->dev))
+ 			t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E;
+ 		else
+@@ -76,6 +88,13 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 	ehci_halt (ehci);
+ 	hcd->state = HC_STATE_SUSPENDED;
+ 
++	/* allow remote wakeup */
++	mask = INTR_MASK;
++	if (!device_may_wakeup(&hcd->self.root_hub->dev))
++		mask &= ~STS_PCD;
++	writel(mask, &ehci->regs->intr_enable);
++	readl(&ehci->regs->intr_enable);
++
+ 	ehci->next_statechange = jiffies + msecs_to_jiffies(10);
+ 	spin_unlock_irq (&ehci->lock);
+ 	return 0;
+@@ -88,7 +107,6 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+ 	u32			temp;
+ 	int			i;
+-	int			intr_enable;
+ 
+ 	if (time_before (jiffies, ehci->next_statechange))
+ 		msleep(5);
+@@ -100,31 +118,30 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 	 * the last user of the controller, not reset/pm hardware keeping
+ 	 * state we gave to it.
+ 	 */
++	temp = readl(&ehci->regs->intr_enable);
++	ehci_dbg(ehci, "resume root hub%s\n", temp ? "" : " after power loss");
+ 
+-	/* re-init operational registers in case we lost power */
+-	if (readl (&ehci->regs->intr_enable) == 0) {
+-		/* at least some APM implementations will try to deliver
+-		 * IRQs right away, so delay them until we're ready.
+-		 */
+-		intr_enable = 1;
+-		writel (0, &ehci->regs->segment);
+-		writel (ehci->periodic_dma, &ehci->regs->frame_list);
+-		writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next);
+-	} else
+-		intr_enable = 0;
+-	ehci_dbg(ehci, "resume root hub%s\n",
+-			intr_enable ? " after power loss" : "");
++	/* at least some APM implementations will try to deliver
++	 * IRQs right away, so delay them until we're ready.
++	 */
++	writel(0, &ehci->regs->intr_enable);
++
++	/* re-init operational registers */
++	writel(0, &ehci->regs->segment);
++	writel(ehci->periodic_dma, &ehci->regs->frame_list);
++	writel((u32) ehci->async->qh_dma, &ehci->regs->async_next);
+ 
+ 	/* restore CMD_RUN, framelist size, and irq threshold */
+ 	writel (ehci->command, &ehci->regs->command);
+ 
+-	/* take ports out of suspend */
++	/* manually resume the ports we suspended during bus_suspend() */
+ 	i = HCS_N_PORTS (ehci->hcs_params);
+ 	while (i--) {
+ 		temp = readl (&ehci->regs->port_status [i]);
+ 		temp &= ~(PORT_RWC_BITS
+ 			| PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E);
+-		if (temp & PORT_SUSPEND) {
++		if (test_bit(i, &ehci->bus_suspended) &&
++				(temp & PORT_SUSPEND)) {
+ 			ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
+ 			temp |= PORT_RESUME;
+ 		}
+@@ -134,11 +151,12 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 	mdelay (20);
+ 	while (i--) {
+ 		temp = readl (&ehci->regs->port_status [i]);
+-		if ((temp & PORT_SUSPEND) == 0)
+-			continue;
+-		temp &= ~(PORT_RWC_BITS | PORT_RESUME);
+-		writel (temp, &ehci->regs->port_status [i]);
+-		ehci_vdbg (ehci, "resumed port %d\n", i + 1);
++		if (test_bit(i, &ehci->bus_suspended) &&
++				(temp & PORT_SUSPEND)) {
++			temp &= ~(PORT_RWC_BITS | PORT_RESUME);
++			writel (temp, &ehci->regs->port_status [i]);
++			ehci_vdbg (ehci, "resumed port %d\n", i + 1);
++		}
+ 	}
+ 	(void) readl (&ehci->regs->command);
+ 
+@@ -157,8 +175,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 	hcd->state = HC_STATE_RUNNING;
+ 
+ 	/* Now we can safely re-enable irqs */
+-	if (intr_enable)
+-		writel (INTR_MASK, &ehci->regs->intr_enable);
++	writel(INTR_MASK, &ehci->regs->intr_enable);
+ 
+ 	spin_unlock_irq (&ehci->lock);
+ 	return 0;
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index e51c1ed81ac4..4bc7970ba3ef 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -257,9 +257,7 @@ static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
+ static int ehci_pci_resume(struct usb_hcd *hcd)
+ {
+ 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
+-	unsigned		port;
+ 	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
+-	int			retval = -EINVAL;
+ 
+ 	// maybe restore FLADJ
+ 
+@@ -269,27 +267,19 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
+ 	/* Mark hardware accessible again as we are out of D3 state by now */
+ 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ 
+-	/* If CF is clear, we lost PCI Vaux power and need to restart.  */
+-	if (readl(&ehci->regs->configured_flag) != FLAG_CF)
+-		goto restart;
+-
+-	/* If any port is suspended (or owned by the companion),
+-	 * we know we can/must resume the HC (and mustn't reset it).
+-	 * We just defer that to the root hub code.
++	/* If CF is still set, we maintained PCI Vaux power.
++	 * Just undo the effect of ehci_pci_suspend().
+ 	 */
+-	for (port = HCS_N_PORTS(ehci->hcs_params); port > 0; ) {
+-		u32	status;
+-		port--;
+-		status = readl(&ehci->regs->port_status [port]);
+-		if (!(status & PORT_POWER))
+-			continue;
+-		if (status & (PORT_SUSPEND | PORT_RESUME | PORT_OWNER)) {
+-			usb_hcd_resume_root_hub(hcd);
+-			return 0;
+-		}
++	if (readl(&ehci->regs->configured_flag) == FLAG_CF) {
++		int	mask = INTR_MASK;
++
++		if (!device_may_wakeup(&hcd->self.root_hub->dev))
++			mask &= ~STS_PCD;
++		writel(mask, &ehci->regs->intr_enable);
++		readl(&ehci->regs->intr_enable);
++		return 0;
+ 	}
+ 
+-restart:
+ 	ehci_dbg(ehci, "lost power, restarting\n");
+ 	usb_root_hub_lost_power(hcd->self.root_hub);
+ 
+@@ -307,13 +297,15 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
+ 	ehci_work(ehci);
+ 	spin_unlock_irq(&ehci->lock);
+ 
+-	/* restart; khubd will disconnect devices */
+-	retval = ehci_run(hcd);
+-
+ 	/* here we "know" root ports should always stay powered */
+ 	ehci_port_power(ehci, 1);
+ 
+-	return retval;
++	writel(ehci->command, &ehci->regs->command);
++	writel(FLAG_CF, &ehci->regs->configured_flag);
++	readl(&ehci->regs->command);	/* unblock posted writes */
++
++	hcd->state = HC_STATE_SUSPENDED;
++	return 0;
+ }
+ #endif
+ 
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index bbc3082a73d7..74dbc6c8228f 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -74,6 +74,7 @@ struct ehci_hcd {			/* one per controller */
+ 
+ 	/* per root hub port */
+ 	unsigned long		reset_done [EHCI_MAX_ROOT_PORTS];
++	unsigned long		bus_suspended;
+ 
+ 	/* per-HC memory pools (could be per-bus, but ...) */
+ 	struct dma_pool		*qh_pool;	/* qh per active urb */

commit 1f26e28d3e32339ca683f087cd55a70e2befc333
+Author: Alan Stern 
+Date:   Thu Nov 16 10:16:00 2006 -0500
+
+    USB: net2280: don't send unwanted zero-length packets
+    
+    The net2280 driver is too eager to send zero-length packets when
+    IN tokens are received on ep0.  No such packet should be sent (the
+    driver should NAK) before the gadget driver has queued the proper
+    response.  Otherwise deferred responses are impossible.
+    
+    This patch (as823) makes net2280 avoid sending ZLPs for IN transfers
+    on ep0 until a response has been submitted, and avoids stalling when an
+    OUT packet is received before a request has been submitted for an OUT
+    transfer on ep0.
+    
+    Signed-off-by: Alan Stern 
+    Cc: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
+index 3acc896a5d4c..0b590831582c 100644
+--- a/drivers/usb/gadget/net2280.c
++++ b/drivers/usb/gadget/net2280.c
+@@ -1040,6 +1040,7 @@ net2280_queue (struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+ 
+ 	} /* else the irq handler advances the queue. */
+ 
++	ep->responded = 1;
+ 	if (req)
+ 		list_add_tail (&req->queue, &ep->queue);
+ done:
+@@ -2188,7 +2189,8 @@ static void handle_ep_small (struct net2280_ep *ep)
+ 					ep->stopped = 1;
+ 					set_halt (ep);
+ 					mode = 2;
+-				} else if (!req && !ep->stopped)
++				} else if (ep->responded &&
++						!req && !ep->stopped)
+ 					write_fifo (ep, NULL);
+ 			}
+ 		} else {
+@@ -2203,7 +2205,7 @@ static void handle_ep_small (struct net2280_ep *ep)
+ 			} else if (((t & (1 << DATA_OUT_PING_TOKEN_INTERRUPT))
+ 					&& req
+ 					&& req->req.actual == req->req.length)
+-					|| !req) {
++					|| (ep->responded && !req)) {
+ 				ep->dev->protocol_stall = 1;
+ 				set_halt (ep);
+ 				ep->stopped = 1;
+@@ -2469,6 +2471,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
+ 		/* we made the hardware handle most lowlevel requests;
+ 		 * everything else goes uplevel to the gadget code.
+ 		 */
++		ep->responded = 1;
+ 		switch (u.r.bRequest) {
+ 		case USB_REQ_GET_STATUS: {
+ 			struct net2280_ep	*e;
+@@ -2537,6 +2540,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
+ 				u.r.bRequestType, u.r.bRequest,
+ 				w_value, w_index, w_length,
+ 				readl (&ep->regs->ep_cfg));
++			ep->responded = 0;
+ 			spin_unlock (&dev->lock);
+ 			tmp = dev->driver->setup (&dev->gadget, &u.r);
+ 			spin_lock (&dev->lock);
+diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h
+index 957d6df34015..44ca139983d8 100644
+--- a/drivers/usb/gadget/net2280.h
++++ b/drivers/usb/gadget/net2280.h
+@@ -110,7 +110,8 @@ struct net2280_ep {
+ 						out_overflow : 1,
+ 						stopped : 1,
+ 						is_in : 1,
+-						is_iso : 1;
++						is_iso : 1,
++						responded : 1;
+ };
+ 
+ static inline void allow_status (struct net2280_ep *ep)

commit db063507b40664de33a61161c90358fe6fc9565a
+Author: Alan Stern 
+Date:   Mon Nov 13 15:02:04 2006 -0500
+
+    USB core: fix compiler warning about usb_autosuspend_work
+    
+    This patch (as821) fixes a compiler warning when CONFIG_PM isn't on
+    ("usb_autosuspend_work" defined but not used).
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index a83c2d5065c1..81cb52564e68 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -200,13 +200,6 @@ static void ksuspend_usb_cleanup(void)
+ 	destroy_workqueue(ksuspend_usb_wq);
+ }
+ 
+-#else
+-
+-#define ksuspend_usb_init()	0
+-#define ksuspend_usb_cleanup()	do {} while (0)
+-
+-#endif
+-
+ #ifdef	CONFIG_USB_SUSPEND
+ 
+ /* usb_autosuspend_work - callback routine to autosuspend a USB device */
+@@ -225,7 +218,14 @@ static void usb_autosuspend_work(void *_udev)
+ static void usb_autosuspend_work(void *_udev)
+ {}
+ 
+-#endif
++#endif	/* CONFIG_USB_SUSPEND */
++
++#else
++
++#define ksuspend_usb_init()	0
++#define ksuspend_usb_cleanup()	do {} while (0)
++
++#endif	/* CONFIG_PM */
+ 
+ /**
+  * usb_alloc_dev - usb device constructor (usbcore-internal)

commit 1b7be3c066ae9238996a7a861b39b0bfd5860735
+Author: Alan Stern 
+Date:   Mon Nov 6 12:05:00 2006 -0500
+
+    OHCI: change priority level of resume log message
+    
+    All the other root-hub suspend or resume log messages, in ohci-hcd or
+    any of the other host controller drivers, use the debug priority
+    level.  This patch (as815) makes the one single exception behave like
+    all the rest.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index dcf9eb601328..4c9492779ede 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -175,7 +175,7 @@ __acquires(ohci->lock)
+ 		break;
+ 	case OHCI_USB_RESUME:
+ 		/* HCFS changes sometime after INTR_RD */
+-		ohci_info(ohci, "%swakeup\n",
++		ohci_dbg(ohci, "%swakeup root hub\n",
+ 				autostopped ? "auto-" : "");
+ 		break;
+ 	case OHCI_USB_OPER:

commit 1bb5f66bb3b6c2fd7eec1cdfee9cf3f68ef83487
+Author: Alan Stern 
+Date:   Mon Nov 6 11:56:13 2006 -0500
+
+    USB: Move private hub declarations out of public header file
+    
+    This patch (as809b) moves the declaration of the hub driver's private
+    data structure from hub.h into the hub.c source file.  Lots of other
+    files import hub.h; they have no need to know about the details of the
+    hub driver's private data.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index c91745def9e7..c961a32f3176 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -31,6 +31,48 @@
+ #include "hcd.h"
+ #include "hub.h"
+ 
++struct usb_hub {
++	struct device		*intfdev;	/* the "interface" device */
++	struct usb_device	*hdev;
++	struct urb		*urb;		/* for interrupt polling pipe */
++
++	/* buffer for urb ... with extra space in case of babble */
++	char			(*buffer)[8];
++	dma_addr_t		buffer_dma;	/* DMA address for buffer */
++	union {
++		struct usb_hub_status	hub;
++		struct usb_port_status	port;
++	}			*status;	/* buffer for status reports */
++
++	int			error;		/* last reported error */
++	int			nerrors;	/* track consecutive errors */
++
++	struct list_head	event_list;	/* hubs w/data or errs ready */
++	unsigned long		event_bits[1];	/* status change bitmask */
++	unsigned long		change_bits[1];	/* ports with logical connect
++							status change */
++	unsigned long		busy_bits[1];	/* ports being reset or
++							resumed */
++#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
++#error event_bits[] is too short!
++#endif
++
++	struct usb_hub_descriptor *descriptor;	/* class descriptor */
++	struct usb_tt		tt;		/* Transaction Translator */
++
++	unsigned		mA_per_port;	/* current for each child */
++
++	unsigned		limited_power:1;
++	unsigned		quiescing:1;
++	unsigned		activating:1;
++	unsigned		resume_root_hub:1;
++
++	unsigned		has_indicators:1;
++	u8			indicator[USB_MAXCHILDREN];
++	struct work_struct	leds;
++};
++
++
+ /* Protect struct usb_device->state and ->children members
+  * Note: Both are also protected by ->dev.sem, except that ->state can
+  * change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */
+diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
+index 1b05994de4dc..cf9559c6c9b6 100644
+--- a/drivers/usb/core/hub.h
++++ b/drivers/usb/core/hub.h
+@@ -192,45 +192,4 @@ struct usb_tt_clear {
+ 
+ extern void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe);
+ 
+-struct usb_hub {
+-	struct device		*intfdev;	/* the "interface" device */
+-	struct usb_device	*hdev;
+-	struct urb		*urb;		/* for interrupt polling pipe */
+-
+-	/* buffer for urb ... with extra space in case of babble */
+-	char			(*buffer)[8];
+-	dma_addr_t		buffer_dma;	/* DMA address for buffer */
+-	union {
+-		struct usb_hub_status	hub;
+-		struct usb_port_status	port;
+-	}			*status;	/* buffer for status reports */
+-
+-	int			error;		/* last reported error */
+-	int			nerrors;	/* track consecutive errors */
+-
+-	struct list_head	event_list;	/* hubs w/data or errs ready */
+-	unsigned long		event_bits[1];	/* status change bitmask */
+-	unsigned long		change_bits[1];	/* ports with logical connect
+-							status change */
+-	unsigned long		busy_bits[1];	/* ports being reset or
+-							resumed */
+-#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
+-#error event_bits[] is too short!
+-#endif
+-
+-	struct usb_hub_descriptor *descriptor;	/* class descriptor */
+-	struct usb_tt		tt;		/* Transaction Translator */
+-
+-	unsigned		mA_per_port;	/* current for each child */
+-
+-	unsigned		limited_power:1;
+-	unsigned		quiescing:1;
+-	unsigned		activating:1;
+-	unsigned		resume_root_hub:1;
+-
+-	unsigned		has_indicators:1;
+-	u8			indicator[USB_MAXCHILDREN];
+-	struct work_struct	leds;
+-};
+-
+ #endif /* __LINUX_HUB_H */

commit 692a186c9d5f12d43cef28d40c25247dc4f302f0
+Author: Alan Stern 
+Date:   Mon Oct 30 17:07:51 2006 -0500
+
+    USB: expand autosuspend/autoresume API
+    
+    This patch (as814) adds usb_autopm_set_interface() to the autosuspend
+    API.  It also provides convenient wrapper routines,
+    usb_autopm_enable() and usb_autopm_disable(), for drivers that want
+    to specify directly whether autosuspend should be allowed.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index ca0e40ed2b72..204495fa6b3d 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1322,6 +1322,28 @@ int usb_autopm_get_interface(struct usb_interface *intf)
+ }
+ EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
+ 
++/**
++ * usb_autopm_set_interface - set a USB interface's autosuspend state
++ * @intf: the usb_interface whose state should be set
++ *
++ * This routine sets the autosuspend state of @intf's device according
++ * to @intf's usage counter, which the caller must have set previously.
++ * If the counter is <= 0, the device is autosuspended (if it isn't
++ * already suspended and if nothing else prevents the autosuspend).  If
++ * the counter is > 0, the device is autoresumed (if it isn't already
++ * awake).
++ */
++int usb_autopm_set_interface(struct usb_interface *intf)
++{
++	int	status;
++
++	status = usb_autopm_do_interface(intf, 0);
++	// dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
++	//		__FUNCTION__, status, intf->pm_usage_cnt);
++	return status;
++}
++EXPORT_SYMBOL_GPL(usb_autopm_set_interface);
++
+ #endif /* CONFIG_USB_SUSPEND */
+ 
+ static int usb_suspend(struct device *dev, pm_message_t message)
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index e732e024a141..864c6c21c21e 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -415,14 +415,37 @@ extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id);
+ 
+ /* USB autosuspend and autoresume */
+ #ifdef CONFIG_USB_SUSPEND
++extern int usb_autopm_set_interface(struct usb_interface *intf);
+ extern int usb_autopm_get_interface(struct usb_interface *intf);
+ extern void usb_autopm_put_interface(struct usb_interface *intf);
+ 
++static inline void usb_autopm_enable(struct usb_interface *intf)
++{
++	intf->pm_usage_cnt = 0;
++	usb_autopm_set_interface(intf);
++}
++
++static inline void usb_autopm_disable(struct usb_interface *intf)
++{
++	intf->pm_usage_cnt = 1;
++	usb_autopm_set_interface(intf);
++}
++
+ #else
+-#define usb_autopm_get_interface(intf)		0
+-#define usb_autopm_put_interface(intf)		do {} while (0)
+-#endif
+ 
++static inline int usb_autopm_set_interface(struct usb_interface *intf)
++{ return 0; }
++
++static inline int usb_autopm_get_interface(struct usb_interface *intf)
++{ return 0; }
++
++static inline void usb_autopm_put_interface(struct usb_interface *intf)
++{ }
++static inline void usb_autopm_enable(struct usb_interface *intf)
++{ }
++static inline void usb_autopm_disable(struct usb_interface *intf)
++{ }
++#endif
+ 
+ /*-------------------------------------------------------------------------*/
+ 

commit af4f76066d0fcb215ae389b8839d7ae37ce0e28b
+Author: Alan Stern 
+Date:   Mon Oct 30 17:06:45 2006 -0500
+
+    USB: autosuspend code consolidation
+    
+    This patch (as813) gathers together common code for USB interface
+    autosuspend/autoresume.
+    
+    It also adds some simple checking at the time an autosuspend request
+    is made, to see whether the request will fail.  This way we don't
+    add a workqueue entry when it would end up doing nothing.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 401d76f13419..ca0e40ed2b72 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -940,6 +940,36 @@ static int resume_interface(struct usb_interface *intf)
+ 	return status;
+ }
+ 
++/* Internal routine to check whether we may autosuspend a device. */
++static int autosuspend_check(struct usb_device *udev)
++{
++	int			i;
++	struct usb_interface	*intf;
++
++	/* For autosuspend, fail fast if anything is in use.
++	 * Also fail if any interfaces require remote wakeup but it
++	 * isn't available. */
++	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
++	if (udev->pm_usage_cnt > 0)
++		return -EBUSY;
++	if (udev->actconfig) {
++		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
++			intf = udev->actconfig->interface[i];
++			if (!is_active(intf))
++				continue;
++			if (intf->pm_usage_cnt > 0)
++				return -EBUSY;
++			if (intf->needs_remote_wakeup &&
++					!udev->do_remote_wakeup) {
++				dev_dbg(&udev->dev, "remote wakeup needed "
++						"for autosuspend\n");
++				return -EOPNOTSUPP;
++			}
++		}
++	}
++	return 0;
++}
++
+ /**
+  * usb_suspend_both - suspend a USB device and its interfaces
+  * @udev: the usb_device to suspend
+@@ -991,28 +1021,10 @@ int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 
+ 	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
+ 
+-	/* For autosuspend, fail fast if anything is in use.
+-	 * Also fail if any interfaces require remote wakeup but it
+-	 * isn't available. */
+ 	if (udev->auto_pm) {
+-		if (udev->pm_usage_cnt > 0)
+-			return -EBUSY;
+-		if (udev->actconfig) {
+-			for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
+-				intf = udev->actconfig->interface[i];
+-				if (!is_active(intf))
+-					continue;
+-				if (intf->pm_usage_cnt > 0)
+-					return -EBUSY;
+-				if (intf->needs_remote_wakeup &&
+-						!udev->do_remote_wakeup) {
+-					dev_dbg(&udev->dev,
+-	"remote wakeup needed for autosuspend\n");
+-					return -EOPNOTSUPP;
+-				}
+-			}
+-			i = 0;
+-		}
++		status = autosuspend_check(udev);
++		if (status < 0)
++			return status;
+ 	}
+ 
+ 	/* Suspend all the interfaces and then udev itself */
+@@ -1151,7 +1163,7 @@ void usb_autosuspend_device(struct usb_device *udev, int dec_usage_cnt)
+ {
+ 	usb_pm_lock(udev);
+ 	udev->pm_usage_cnt -= dec_usage_cnt;
+-	if (udev->pm_usage_cnt <= 0)
++	if (autosuspend_check(udev) == 0)
+ 		queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+ 				USB_AUTOSUSPEND_DELAY);
+ 	usb_pm_unlock(udev);
+@@ -1200,6 +1212,33 @@ int usb_autoresume_device(struct usb_device *udev, int inc_usage_cnt)
+ 	return status;
+ }
+ 
++/* Internal routine to adjust an interface's usage counter and change
++ * its device's autosuspend state.
++ */
++static int usb_autopm_do_interface(struct usb_interface *intf,
++		int inc_usage_cnt)
++{
++	struct usb_device	*udev = interface_to_usbdev(intf);
++	int			status = 0;
++
++	usb_pm_lock(udev);
++	if (intf->condition == USB_INTERFACE_UNBOUND)
++		status = -ENODEV;
++	else {
++		intf->pm_usage_cnt += inc_usage_cnt;
++		if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) {
++			udev->auto_pm = 1;
++			status = usb_resume_both(udev);
++			if (status != 0)
++				intf->pm_usage_cnt -= inc_usage_cnt;
++		} else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
++			queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
++					USB_AUTOSUSPEND_DELAY);
++	}
++	usb_pm_unlock(udev);
++	return status;
++}
++
+ /**
+  * usb_autopm_put_interface - decrement a USB interface's PM-usage counter
+  * @intf: the usb_interface whose counter should be decremented
+@@ -1233,17 +1272,11 @@ int usb_autoresume_device(struct usb_device *udev, int inc_usage_cnt)
+  */
+ void usb_autopm_put_interface(struct usb_interface *intf)
+ {
+-	struct usb_device	*udev = interface_to_usbdev(intf);
++	int	status;
+ 
+-	usb_pm_lock(udev);
+-	if (intf->condition != USB_INTERFACE_UNBOUND &&
+-			--intf->pm_usage_cnt <= 0) {
+-		queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+-				USB_AUTOSUSPEND_DELAY);
+-	}
+-	usb_pm_unlock(udev);
+-	// dev_dbg(&intf->dev, "%s: cnt %d\n",
+-	//		__FUNCTION__, intf->pm_usage_cnt);
++	status = usb_autopm_do_interface(intf, -1);
++	// dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
++	//		__FUNCTION__, status, intf->pm_usage_cnt);
+ }
+ EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
+ 
+@@ -1280,20 +1313,9 @@ EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
+  */
+ int usb_autopm_get_interface(struct usb_interface *intf)
+ {
+-	struct usb_device	*udev = interface_to_usbdev(intf);
+-	int			status;
++	int	status;
+ 
+-	usb_pm_lock(udev);
+-	if (intf->condition == USB_INTERFACE_UNBOUND)
+-		status = -ENODEV;
+-	else {
+-		++intf->pm_usage_cnt;
+-		udev->auto_pm = 1;
+-		status = usb_resume_both(udev);
+-		if (status != 0)
+-			--intf->pm_usage_cnt;
+-	}
+-	usb_pm_unlock(udev);
++	status = usb_autopm_do_interface(intf, 1);
+ 	// dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
+ 	//		__FUNCTION__, status, intf->pm_usage_cnt);
+ 	return status;

commit 565402baee99096da4d79209e450fe42d379a0ca
+Author: Alan Stern 
+Date:   Fri Oct 27 10:35:01 2006 -0400
+
+    USB: OHCI: remove stale testing code from root-hub resume
+    
+    This patch (as811) removes some stale testing code from the root-hub
+    resume routine in ohci-hcd.  It also adds a spin_lock_irq() call that
+    inadvertently got left out of an error pathway.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index 1e5ed3bb1a93..dcf9eb601328 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -204,18 +204,6 @@ __acquires(ohci->lock)
+ 		goto skip_resume;
+ 	spin_unlock_irq (&ohci->lock);
+ 
+-	temp = ohci->num_ports;
+-	while (temp--) {
+-		u32 stat = ohci_readl (ohci,
+-				       &ohci->regs->roothub.portstatus [temp]);
+-
+-		/* force global, not selective, resume */
+-		if (!(stat & RH_PS_PSS))
+-			continue;
+-		ohci_writel (ohci, RH_PS_POCI,
+-				&ohci->regs->roothub.portstatus [temp]);
+-	}
+-
+ 	/* Some controllers (lucent erratum) need extra-long delays */
+ 	msleep (20 /* usb 11.5.1.10 */ + 12 /* 32 msec counter */ + 1);
+ 
+@@ -223,6 +211,7 @@ __acquires(ohci->lock)
+ 	temp &= OHCI_CTRL_HCFS;
+ 	if (temp != OHCI_USB_RESUME) {
+ 		ohci_err (ohci, "controller won't resume\n");
++		spin_lock_irq(&ohci->lock);
+ 		return -EBUSY;
+ 	}
+ 

commit 052ac01aeb84d8427ba8ac3d70991ac01b009b59
+Author: Alan Stern 
+Date:   Fri Oct 27 10:33:11 2006 -0400
+
+    USB: OHCI: disable RHSC inside interrupt handler
+    
+    This patch (as808b) moves the Root Hub Status Change interrupt-disable
+    code in ohci-hcd back into the interrupt handler proper, to avoid the
+    chance of adverse interactions with mediocre hardware implementations.
+    
+    It also deletes the root-hub status timer from within the interrupt-enable
+    routine.  There's no need to poll for status any more once interrupts are
+    re-enabled.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index ea4714e557e4..a95275a401b1 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -729,6 +729,16 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
+ 		ohci->next_statechange = jiffies + STATECHANGE_DELAY;
+ 		ohci_writel(ohci, OHCI_INTR_RD | OHCI_INTR_RHSC,
+ 				®s->intrstatus);
++
++		/* NOTE: Vendors didn't always make the same implementation
++		 * choices for RHSC.  Many followed the spec; RHSC triggers
++		 * on an edge, like setting and maybe clearing a port status
++		 * change bit.  With others it's level-triggered, active
++		 * until khubd clears all the port status change bits.  We'll
++		 * always disable it here and rely on polling until khubd
++		 * re-enables it.
++		 */
++		ohci_writel(ohci, OHCI_INTR_RHSC, ®s->intrdisable);
+ 		usb_hcd_poll_rh_status(hcd);
+ 	}
+ 
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index 99357b99d133..1e5ed3bb1a93 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -41,7 +41,11 @@ static void ohci_rhsc_enable (struct usb_hcd *hcd)
+ {
+ 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+ 
+-	ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
++	spin_lock_irq(&ohci->lock);
++	if (!ohci->autostop)
++		del_timer(&hcd->rh_timer);	/* Prevent next poll */
++	ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
++	spin_unlock_irq(&ohci->lock);
+ }
+ 
+ #define OHCI_SCHED_ENABLES \
+@@ -348,7 +352,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ {
+ 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
+ 	int		i, changed = 0, length = 1;
+-	int		any_connected = 0, rhsc_enabled = 1;
++	int		any_connected = 0;
+ 	unsigned long	flags;
+ 
+ 	spin_lock_irqsave (&ohci->lock, flags);
+@@ -389,19 +393,6 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ 		}
+ 	}
+ 
+-	/* NOTE:  vendors didn't always make the same implementation
+-	 * choices for RHSC.  Sometimes it triggers on an edge (like
+-	 * setting and maybe clearing a port status change bit); and
+-	 * it's level-triggered on other silicon, active until khubd
+-	 * clears all active port status change bits.  If it's still
+-	 * set (level-triggered) we must disable it and rely on
+-	 * polling until khubd re-enables it.
+-	 */
+-	if (ohci_readl (ohci, &ohci->regs->intrstatus) & OHCI_INTR_RHSC) {
+-		ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable);
+-		(void) ohci_readl (ohci, &ohci->regs->intrdisable);
+-		rhsc_enabled = 0;
+-	}
+ 	hcd->poll_rh = 1;
+ 
+ 	/* carry out appropriate state changes */
+@@ -412,7 +403,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ 		 * and RHSC is enabled */
+ 		if (!ohci->autostop) {
+ 			if (any_connected) {
+-				if (rhsc_enabled)
++				if (ohci_readl(ohci, &ohci->regs->intrenable) &
++						OHCI_INTR_RHSC)
+ 					hcd->poll_rh = 0;
+ 			} else {
+ 				ohci->autostop = 1;

commit b1878440d46a0dc357ed5c9687c534e20955e940
+Author: Alan Stern 
+Date:   Tue Oct 24 12:02:31 2006 -0400
+
+    USB: ohci-hcd: fix compiler warning
+    
+    This patch (as806) fixes a compiler warning when ohci-hcd is built
+    with CONFIG_PM turned off.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index 6995ea36f2e8..99357b99d133 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -50,6 +50,10 @@ static void ohci_rhsc_enable (struct usb_hcd *hcd)
+ static void dl_done_list (struct ohci_hcd *);
+ static void finish_unlinks (struct ohci_hcd *, u16);
+ 
++#ifdef	CONFIG_PM
++static int ohci_restart(struct ohci_hcd *ohci);
++#endif
++
+ static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop)
+ __releases(ohci->lock)
+ __acquires(ohci->lock)
+@@ -132,8 +136,6 @@ static inline struct ed *find_head (struct ed *ed)
+ 	return ed;
+ }
+ 
+-static int ohci_restart (struct ohci_hcd *ohci);
+-
+ /* caller has locked the root hub */
+ static int ohci_rh_resume (struct ohci_hcd *ohci)
+ __releases(ohci->lock)

commit 93c8bf45e083b89dffe3a708363c15c1b220c723
+Author: Alan Stern 
+Date:   Wed Oct 18 16:41:51 2006 -0400
+
+    USB core: don't match interface descriptors for vendor-specific devices
+    
+    This patch (as804) makes USB driver matching ignore the interface
+    class, subclass, and protocol if the device class is Vendor Specific.
+    Drivers can override this policy by specifying a Vendor ID as part
+    of the match; then vendor-specific matches are allowed.
+    
+    Linus Walleij has reported a problem this patch fixes.  When a
+    particular mass-storage device is switched from mass-storage mode to
+    Media Transfer Protocol, the interface class remains set to mass-storage
+    and usb-storage binds to it erroneously, even though the device class
+    changes to Vendor-Specific.
+    
+    This may cause a problem for some drivers until their match records can
+    be updated to include Vendor IDs.  But if it does, then those records
+    were broken to begin with.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 113e484c763e..401d76f13419 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -408,6 +408,16 @@ static int usb_match_one_id(struct usb_interface *interface,
+ 	    (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
+ 		return 0;
+ 
++	/* The interface class, subclass, and protocol should never be
++	 * checked for a match if the device class is Vendor Specific,
++	 * unless the match record specifies the Vendor ID. */
++	if (dev->descriptor.bDeviceClass == USB_CLASS_VENDOR_SPEC &&
++			!(id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
++			(id->match_flags & (USB_DEVICE_ID_MATCH_INT_CLASS |
++				USB_DEVICE_ID_MATCH_INT_SUBCLASS |
++				USB_DEVICE_ID_MATCH_INT_PROTOCOL)))
++		return 0;
++
+ 	if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
+ 	    (id->bInterfaceClass != intf->desc.bInterfaceClass))
+ 		return 0;
+@@ -476,7 +486,17 @@ static int usb_match_one_id(struct usb_interface *interface,
+  * most general; they let drivers bind to any interface on a
+  * multiple-function device.  Use the USB_INTERFACE_INFO
+  * macro, or its siblings, to match class-per-interface style
+- * devices (as recorded in bDeviceClass).
++ * devices (as recorded in bInterfaceClass).
++ *
++ * Note that an entry created by USB_INTERFACE_INFO won't match
++ * any interface if the device class is set to Vendor-Specific.
++ * This is deliberate; according to the USB spec the meanings of
++ * the interface class/subclass/protocol for these devices are also
++ * vendor-specific, and hence matching against a standard product
++ * class wouldn't work anyway.  If you really want to use an
++ * interface-based match for such a device, create a match record
++ * that also specifies the vendor ID.  (Unforunately there isn't a
++ * standard macro for creating records like this.)
+  *
+  * Within those groups, remember that not all combinations are
+  * meaningful.  For example, don't give a product version range

commit 6d8fc4d28deaf828606c19fb743fbe94aeab4caf
+Author: Alan Stern 
+Date:   Wed Oct 18 12:35:24 2006 -0400
+
+    USB HID: Handle STALL on interrupt endpoint
+    
+    The USB HID driver doesn't include any code to handle a STALL on the
+    interrupt endpoint.  While this may be uncommon, it does happen
+    sometimes.  This patch (as805) adds a fix.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
+index 6d08a3bcc952..5de931cf4cfb 100644
+--- a/drivers/usb/input/hid-core.c
++++ b/drivers/usb/input/hid-core.c
+@@ -968,20 +968,29 @@ static void hid_retry_timeout(unsigned long _hid)
+ 		hid_io_error(hid);
+ }
+ 
+-/* Workqueue routine to reset the device */
++/* Workqueue routine to reset the device or clear a halt */
+ static void hid_reset(void *_hid)
+ {
+ 	struct hid_device *hid = (struct hid_device *) _hid;
+-	int rc_lock, rc;
+-
+-	dev_dbg(&hid->intf->dev, "resetting device\n");
+-	rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf);
+-	if (rc_lock >= 0) {
+-		rc = usb_reset_composite_device(hid->dev, hid->intf);
+-		if (rc_lock)
+-			usb_unlock_device(hid->dev);
++	int rc_lock, rc = 0;
++
++	if (test_bit(HID_CLEAR_HALT, &hid->iofl)) {
++		dev_dbg(&hid->intf->dev, "clear halt\n");
++		rc = usb_clear_halt(hid->dev, hid->urbin->pipe);
++		clear_bit(HID_CLEAR_HALT, &hid->iofl);
++		hid_start_in(hid);
++	}
++
++	else if (test_bit(HID_RESET_PENDING, &hid->iofl)) {
++		dev_dbg(&hid->intf->dev, "resetting device\n");
++		rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf);
++		if (rc_lock >= 0) {
++			rc = usb_reset_composite_device(hid->dev, hid->intf);
++			if (rc_lock)
++				usb_unlock_device(hid->dev);
++		}
++		clear_bit(HID_RESET_PENDING, &hid->iofl);
+ 	}
+-	clear_bit(HID_RESET_PENDING, &hid->iofl);
+ 
+ 	switch (rc) {
+ 	case 0:
+@@ -1023,9 +1032,8 @@ static void hid_io_error(struct hid_device *hid)
+ 
+ 		/* Retries failed, so do a port reset */
+ 		if (!test_and_set_bit(HID_RESET_PENDING, &hid->iofl)) {
+-			if (schedule_work(&hid->reset_work))
+-				goto done;
+-			clear_bit(HID_RESET_PENDING, &hid->iofl);
++			schedule_work(&hid->reset_work);
++			goto done;
+ 		}
+ 	}
+ 
+@@ -1049,6 +1057,11 @@ static void hid_irq_in(struct urb *urb)
+ 			hid->retry_delay = 0;
+ 			hid_input_report(HID_INPUT_REPORT, urb, 1);
+ 			break;
++		case -EPIPE:		/* stall */
++			clear_bit(HID_IN_RUNNING, &hid->iofl);
++			set_bit(HID_CLEAR_HALT, &hid->iofl);
++			schedule_work(&hid->reset_work);
++			return;
+ 		case -ECONNRESET:	/* unlink */
+ 		case -ENOENT:
+ 		case -ESHUTDOWN:	/* unplug */
+diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
+index 0e76e6dcac37..2a9bf07944c0 100644
+--- a/drivers/usb/input/hid.h
++++ b/drivers/usb/input/hid.h
+@@ -385,6 +385,7 @@ struct hid_control_fifo {
+ #define HID_IN_RUNNING		3
+ #define HID_RESET_PENDING	4
+ #define HID_SUSPENDED		5
++#define HID_CLEAR_HALT		6
+ 
+ struct hid_input {
+ 	struct list_head list;

commit 583ceada075597a5b6acab1140d61ac81586a2a6
+Author: Alan Stern 
+Date:   Tue Oct 24 12:04:22 2006 -0400
+
+    USB: OHCI: fix root-hub resume bug
+    
+    When a suspended OHCI controller sees a port's status change, it sets
+    both the Root-Hub-Status-Change and the Resume-Detect bits in the
+    Interrupt Status register.  Processing both these bits, the driver
+    tries to resume the root hub twice!
+    
+    This patch (as807) fixes the bug by ignoring RD if RHSC is set.  It
+    also prints a slightly more informative log message when a
+    remote-wakeup event occurs.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index 9be6b303e784..ea4714e557e4 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -715,13 +715,6 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
+ 		return IRQ_NOTMINE;
+ 	}
+ 
+-	if (ints & OHCI_INTR_RHSC) {
+-		ohci_vdbg (ohci, "rhsc\n");
+-		ohci->next_statechange = jiffies + STATECHANGE_DELAY;
+-		ohci_writel (ohci, OHCI_INTR_RHSC, ®s->intrstatus);
+-		usb_hcd_poll_rh_status(hcd);
+-	}
+-
+ 	if (ints & OHCI_INTR_UE) {
+ 		disable (ohci);
+ 		ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n");
+@@ -731,9 +724,21 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
+ 		ohci_usb_reset (ohci);
+ 	}
+ 
+-	if (ints & OHCI_INTR_RD) {
+-		ohci_vdbg (ohci, "resume detect\n");
+-		ohci_writel (ohci, OHCI_INTR_RD, ®s->intrstatus);
++	if (ints & OHCI_INTR_RHSC) {
++		ohci_vdbg(ohci, "rhsc\n");
++		ohci->next_statechange = jiffies + STATECHANGE_DELAY;
++		ohci_writel(ohci, OHCI_INTR_RD | OHCI_INTR_RHSC,
++				®s->intrstatus);
++		usb_hcd_poll_rh_status(hcd);
++	}
++
++	/* For connect and disconnect events, we expect the controller
++	 * to turn on RHSC along with RD.  But for remote wakeup events
++	 * this might not happen.
++	 */
++	else if (ints & OHCI_INTR_RD) {
++		ohci_vdbg(ohci, "resume detect\n");
++		ohci_writel(ohci, OHCI_INTR_RD, ®s->intrstatus);
+ 		hcd->poll_rh = 1;
+ 		if (ohci->autostop) {
+ 			spin_lock (&ohci->lock);
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index da09e7930c1b..6995ea36f2e8 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -169,7 +169,8 @@ __acquires(ohci->lock)
+ 		break;
+ 	case OHCI_USB_RESUME:
+ 		/* HCFS changes sometime after INTR_RD */
+-		ohci_info (ohci, "wakeup\n");
++		ohci_info(ohci, "%swakeup\n",
++				autostopped ? "auto-" : "");
+ 		break;
+ 	case OHCI_USB_OPER:
+ 		/* this can happen after resuming a swsusp snapshot */

commit 3da2495c0a92723d58cacaaff48dc60a29ddaae6
+Author: Alan Stern 
+Date:   Tue Nov 14 16:28:01 2006 -0500
+
+    OHCI: disallow autostop when wakeup is not available
+    
+    This patch (as822) prevents the OHCI autostop mechanism from kicking in
+    if the root hub is not able or not allowed to issue wakeup requests.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index 6f113596af66..da09e7930c1b 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -422,7 +422,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ 				ohci->autostop = 0;
+ 				ohci->next_statechange = jiffies +
+ 						STATECHANGE_DELAY;
+-			} else if (time_after_eq (jiffies,
++			} else if (device_may_wakeup(&hcd->self.root_hub->dev)
++					&& time_after_eq(jiffies,
+ 						ohci->next_statechange)
+ 					&& !ohci->ed_rm_list
+ 					&& !(ohci->hc_control &

commit b4d38e38e66f8e1b32a1b1c00e533175314c8d56
+Author: Alan Stern 
+Date:   Wed Oct 11 16:48:28 2006 -0400
+
+    [SCSI] Reduce polling in sd.c
+    
+    If a drive reports that no media is present, there's no point in
+    continuing to ask it about media status.  This patch (as696) cuts the
+    TUR polling short as soon as the drive reports no media instead of
+    going a full 3 iterations.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+index 84ff203ffedd..152f4ff4ed7e 100644
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -1051,6 +1051,14 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname)
+ 						      &sshdr, SD_TIMEOUT,
+ 						      SD_MAX_RETRIES);
+ 
++			/*
++			 * If the drive has indicated to us that it
++			 * doesn't have any media in it, don't bother
++			 * with any more polling.
++			 */
++			if (media_not_present(sdkp, &sshdr))
++				return;
++
+ 			if (the_result)
+ 				sense_valid = scsi_sense_valid(&sshdr);
+ 			retries++;
+@@ -1059,14 +1067,6 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname)
+ 			  ((driver_byte(the_result) & DRIVER_SENSE) &&
+ 			  sense_valid && sshdr.sense_key == UNIT_ATTENTION)));
+ 
+-		/*
+-		 * If the drive has indicated to us that it doesn't have
+-		 * any media in it, don't bother with any of the rest of
+-		 * this crap.
+-		 */
+-		if (media_not_present(sdkp, &sshdr))
+-			return;
+-
+ 		if ((driver_byte(the_result) & DRIVER_SENSE) == 0) {
+ 			/* no sense, TUR either succeeded or failed
+ 			 * with a status error */

commit 09123d230a294cd3b860f4ea042235b988277f0a
+Author: Alan Stern 
+Date:   Fri Nov 10 12:27:57 2006 -0800
+
+    [PATCH] SCSI core: always store >= 36 bytes of INQUIRY data
+    
+    This patch (as810c) copies a minimum of 36 bytes of INQUIRY data, even if
+    the device claims that not all of them are valid.  Often badly behaved
+    devices put plausible data in the Vendor, Product, and Revision strings but
+    set the Additional Length byte to a small value.  Using potentially valid
+    data is certainly better than allocating a short buffer and then reading
+    beyond the end of it, which is what we do now.
+    
+    Signed-off-by: Alan Stern 
+    Cc: James Bottomley 
+    Cc: Greg KH 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+index fd9e281c3bfe..94a274645f6f 100644
+--- a/drivers/scsi/scsi_scan.c
++++ b/drivers/scsi/scsi_scan.c
+@@ -631,12 +631,22 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
+ 	 * scanning run at their own risk, or supply a user level program
+ 	 * that can correctly scan.
+ 	 */
+-	sdev->inquiry = kmalloc(sdev->inquiry_len, GFP_ATOMIC);
+-	if (sdev->inquiry == NULL) {
++
++	/*
++	 * Copy at least 36 bytes of INQUIRY data, so that we don't
++	 * dereference unallocated memory when accessing the Vendor,
++	 * Product, and Revision strings.  Badly behaved devices may set
++	 * the INQUIRY Additional Length byte to a small value, indicating
++	 * these strings are invalid, but often they contain plausible data
++	 * nonetheless.  It doesn't matter if the device sent < 36 bytes
++	 * total, since scsi_probe_lun() initializes inq_result with 0s.
++	 */
++	sdev->inquiry = kmemdup(inq_result,
++				max_t(size_t, sdev->inquiry_len, 36),
++				GFP_ATOMIC);
++	if (sdev->inquiry == NULL)
+ 		return SCSI_SCAN_NO_RESPONSE;
+-	}
+ 
+-	memcpy(sdev->inquiry, inq_result, sdev->inquiry_len);
+ 	sdev->vendor = (char *) (sdev->inquiry + 8);
+ 	sdev->model = (char *) (sdev->inquiry + 16);
+ 	sdev->rev = (char *) (sdev->inquiry + 32);

commit 057647fc47b3a5fbcfa997041db3f483d506603c
+Author: Alan Stern 
+Date:   Sat Oct 28 10:38:58 2006 -0700
+
+    [PATCH] workqueue: update kerneldoc
+    
+    This patch (as812) changes the kerneldoc comments explaining the return
+    values from queue_work(), queue_delayed_work(), and
+    queue_delayed_work_on().  The updated comments explain more accurately the
+    meaning of the return code and avoid suggesting that a 0 value means the
+    routine was unsuccessful.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/kernel/workqueue.c b/kernel/workqueue.c
+index 3df9bfc7ff78..17c2f03d2c27 100644
+--- a/kernel/workqueue.c
++++ b/kernel/workqueue.c
+@@ -99,7 +99,7 @@ static void __queue_work(struct cpu_workqueue_struct *cwq,
+  * @wq: workqueue to use
+  * @work: work to queue
+  *
+- * Returns non-zero if it was successfully added.
++ * Returns 0 if @work was already on a queue, non-zero otherwise.
+  *
+  * We queue the work to the CPU it was submitted, but there is no
+  * guarantee that it will be processed by that CPU.
+@@ -138,7 +138,7 @@ static void delayed_work_timer_fn(unsigned long __data)
+  * @work: work to queue
+  * @delay: number of jiffies to wait before queueing
+  *
+- * Returns non-zero if it was successfully added.
++ * Returns 0 if @work was already on a queue, non-zero otherwise.
+  */
+ int fastcall queue_delayed_work(struct workqueue_struct *wq,
+ 			struct work_struct *work, unsigned long delay)
+@@ -169,7 +169,7 @@ EXPORT_SYMBOL_GPL(queue_delayed_work);
+  * @work: work to queue
+  * @delay: number of jiffies to wait before queueing
+  *
+- * Returns non-zero if it was successfully added.
++ * Returns 0 if @work was already on a queue, non-zero otherwise.
+  */
+ int queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
+ 			struct work_struct *work, unsigned long delay)

commit f70fa6296c2ec8f541f0a9b406ccc2d9d127d639
+Author: Alan Stern 
+Date:   Thu Oct 5 17:03:24 2006 -0400
+
+    Driver core: Don't ignore error returns from probing
+    
+    This patch (as797) fixes device_add() in the driver core.  It needs to
+    pay attention when the driver for a new device reports an error.
+    
+    At the same time, since bus_remove_device() undoes the effects of both
+    bus_add_device() and bus_attach_device(), it needs to check whether
+    the bus_attach_device step failed.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/base/bus.c b/drivers/base/bus.c
+index d516f7d5f168..d7c5ea246a0b 100644
+--- a/drivers/base/bus.c
++++ b/drivers/base/bus.c
+@@ -439,8 +439,10 @@ void bus_remove_device(struct device * dev)
+ 		sysfs_remove_link(&dev->kobj, "bus");
+ 		sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id);
+ 		device_remove_attrs(dev->bus, dev);
+-		dev->is_registered = 0;
+-		klist_del(&dev->knode_bus);
++		if (dev->is_registered) {
++			dev->is_registered = 0;
++			klist_del(&dev->knode_bus);
++		}
+ 		pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id);
+ 		device_release_driver(dev);
+ 		put_bus(dev->bus);
+diff --git a/drivers/base/core.c b/drivers/base/core.c
+index 41f3dca55cd0..68ad11af22b4 100644
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -479,7 +479,8 @@ int device_add(struct device *dev)
+ 	if ((error = bus_add_device(dev)))
+ 		goto BusError;
+ 	kobject_uevent(&dev->kobj, KOBJ_ADD);
+-	bus_attach_device(dev);
++	if ((error = bus_attach_device(dev)))
++		goto AttachError;
+ 	if (parent)
+ 		klist_add_tail(&dev->knode_parent, &parent->klist_children);
+ 
+@@ -498,6 +499,8 @@ int device_add(struct device *dev)
+  	kfree(class_name);
+ 	put_device(dev);
+ 	return error;
++ AttachError:
++	bus_remove_device(dev);
+  BusError:
+ 	device_pm_remove(dev);
+  PMError:

commit 3ccf25ce185d4798e66a91812a7622f7fe6987df
+Author: Alan Stern 
+Date:   Fri Oct 13 09:59:17 2006 -0400
+
+    USB: unusual_devs entry for Nokia 6234
+    
+    This patch (as803) adds an unusual_devs entry for the Nokia 6234
+    mobile phone.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 0093d9fd0234..802f3a35c51d 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -190,6 +190,13 @@ UNUSUAL_DEV(  0x0421, 0x047c, 0x0370, 0x0370,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_MAX_SECTORS_64 ),
+ 
++/* Reported by Alex Corcoles  */
++UNUSUAL_DEV(  0x0421, 0x0495, 0x0370, 0x0370,
++		"Nokia",
++		"6234",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_MAX_SECTORS_64 ),
++
+ /* Reported by Olaf Hering  from novell bug #105878 */
+ UNUSUAL_DEV(  0x0424, 0x0fdc, 0x0210, 0x0210,
+ 		"SMSC",

commit d5477c11111467e19787f00d3cab20fb48c2699e
+Author: Alan Stern 
+Date:   Tue Oct 10 11:56:26 2006 -0400
+
+    usbcore: fix endpoint device creation
+    
+    This patch (as800) straightens out the USB endpoint class device
+    creation routine, fixing a refcount bug in the process.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
+index 40ba76a17571..3b2d137912be 100644
+--- a/drivers/usb/core/endpoint.c
++++ b/drivers/usb/core/endpoint.c
+@@ -223,7 +223,7 @@ int usb_create_ep_files(struct device *parent,
+ 	ep_dev = kzalloc(sizeof(*ep_dev), GFP_KERNEL);
+ 	if (!ep_dev) {
+ 		retval = -ENOMEM;
+-		goto exit;
++		goto error_alloc;
+ 	}
+ 
+ 	/* fun calculation to determine the minor of this endpoint */
+@@ -241,33 +241,31 @@ int usb_create_ep_files(struct device *parent,
+ 
+ 	retval = device_register(&ep_dev->dev);
+ 	if (retval)
+-		goto error;
++		goto error_register;
+ 	retval = sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
+ 	if (retval)
+ 		goto error_group;
+ 
+-	endpoint->ep_dev = ep_dev;
+-
+ 	/* create the symlink to the old-style "ep_XX" directory */
+ 	sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress);
+-	retval = sysfs_create_link(&parent->kobj,
+-				   &endpoint->ep_dev->dev.kobj, name);
++	retval = sysfs_create_link(&parent->kobj, &ep_dev->dev.kobj, name);
+ 	if (retval)
+ 		goto error_link;
+-exit:
++	endpoint->ep_dev = ep_dev;
+ 	return retval;
+ 
+ error_link:
+ 	sysfs_remove_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
+-
+ error_group:
+ 	device_unregister(&ep_dev->dev);
+-	endpoint->ep_dev = NULL;
+ 	destroy_endpoint_class();
+ 	return retval;
+-error:
++
++error_register:
+ 	kfree(ep_dev);
++error_alloc:
+ 	destroy_endpoint_class();
++exit:
+ 	return retval;
+ }
+ 

commit c40fd5ea565587c05b0e2c49c02cad2c35fd85c6
+Author: Alan Stern 
+Date:   Tue Oct 10 11:55:47 2006 -0400
+
+    usbcore: fix refcount bug in endpoint removal
+    
+    This patch (as799) fixes a nasty refcount error in the USB endpoint class.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
+index 3ebb90149e93..40ba76a17571 100644
+--- a/drivers/usb/core/endpoint.c
++++ b/drivers/usb/core/endpoint.c
+@@ -282,8 +282,6 @@ void usb_remove_ep_files(struct usb_host_endpoint *endpoint)
+ 		sysfs_remove_group(&endpoint->ep_dev->dev.kobj, &ep_dev_attr_grp);
+ 		device_unregister(&endpoint->ep_dev->dev);
+ 		endpoint->ep_dev = NULL;
++		destroy_endpoint_class();
+ 	}
+-	destroy_endpoint_class();
+ }
+-
+-

commit b62df4516981745d4b5de01ceec1d65a9174a524
+Author: Alan Stern 
+Date:   Tue Oct 10 10:54:00 2006 -0400
+
+    UHCI: workaround for Asus motherboard
+    
+    This patch (as798) adds a workaround to uhci-hcd.  At least one Asus
+    motherboard is wired in such a way that any device attached to a
+    suspended UHCI controller will prevent the system from entering
+    suspend-to-RAM by immediately waking it up.  The only way around the
+    problem is to turn the controller off instead of suspending it.
+    
+    This fixes Bugzilla #6193.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 45ee6920a850..226bf3de8edd 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -40,6 +40,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ #include 
+@@ -196,12 +197,42 @@ static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
+ 	return 0;
+ }
+ 
++static int remote_wakeup_is_broken(struct uhci_hcd *uhci)
++{
++	static struct dmi_system_id broken_wakeup_table[] = {
++		{
++			.ident = "Asus A7V8X",
++			.matches = {
++				DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK"),
++				DMI_MATCH(DMI_BOARD_NAME, "A7V8X"),
++				DMI_MATCH(DMI_BOARD_VERSION, "REV 1.xx"),
++			}
++		},
++		{ }
++	};
++	int port;
++
++	/* One of Asus's motherboards has a bug which causes it to
++	 * wake up immediately from suspend-to-RAM if any of the ports
++	 * are connected.  In such cases we will not set EGSM.
++	 */
++	if (dmi_check_system(broken_wakeup_table)) {
++		for (port = 0; port < uhci->rh_numports; ++port) {
++			if (inw(uhci->io_addr + USBPORTSC1 + port * 2) &
++					USBPORTSC_CCS)
++				return 1;
++		}
++	}
++
++	return 0;
++}
++
+ static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state)
+ __releases(uhci->lock)
+ __acquires(uhci->lock)
+ {
+ 	int auto_stop;
+-	int int_enable;
++	int int_enable, egsm_enable;
+ 
+ 	auto_stop = (new_state == UHCI_RH_AUTO_STOPPED);
+ 	dev_dbg(&uhci_to_hcd(uhci)->self.root_hub->dev,
+@@ -217,15 +248,18 @@ __acquires(uhci->lock)
+ 	}
+ 
+ 	/* Enable resume-detect interrupts if they work.
+-	 * Then enter Global Suspend mode, still configured.
++	 * Then enter Global Suspend mode if _it_ works, still configured.
+ 	 */
++	egsm_enable = USBCMD_EGSM;
+ 	uhci->working_RD = 1;
+ 	int_enable = USBINTR_RESUME;
+-	if (resume_detect_interrupts_are_broken(uhci)) {
++	if (remote_wakeup_is_broken(uhci))
++		egsm_enable = 0;
++	if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable)
+ 		uhci->working_RD = int_enable = 0;
+-	}
++
+ 	outw(int_enable, uhci->io_addr + USBINTR);
+-	outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD);
++	outw(egsm_enable | USBCMD_CF, uhci->io_addr + USBCMD);
+ 	mb();
+ 	udelay(5);
+ 

commit e4a20daa7b44ab9805979eb716f6bb7532bc67b9
+Author: Alan Stern 
+Date:   Wed Oct 4 16:31:15 2006 -0400
+
+    USB: unusual_devs entry for Nokia 6131
+    
+    This patch (as796) adds an unusual_devs entry for the Nokia 6131, which
+    doesn't like large transfer sizes.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index c9a8d50106d1..0a846e4a101e 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -182,6 +182,13 @@ UNUSUAL_DEV(  0x0421, 0x044e, 0x0100, 0x0100,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
+ 
++/* Reported by Bardur Arantsson  */
++UNUSUAL_DEV(  0x0421, 0x047c, 0x0370, 0x0370,
++		"Nokia",
++		"6131",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_MAX_SECTORS_64 ),
++
+ /* Reported by Olaf Hering  from novell bug #105878 */
+ UNUSUAL_DEV(  0x0424, 0x0fdc, 0x0210, 0x0210,
+ 		"SMSC",

commit b4dfdbb3c707474a2254c5b4d7e62be31a4b7da9
+Author: Alan Stern 
+Date:   Wed Oct 4 02:17:06 2006 -0700
+
+    [PATCH] cpufreq: make the transition_notifier chain use SRCU
+    
+    This patch (as762) changes the cpufreq_transition_notifier_list from a
+    blocking_notifier_head to an srcu_notifier_head.  This will prevent errors
+    caused attempting to call down_read() to access the notifier chain at a
+    time when interrupts must remain disabled, during system suspend.
+    
+    It's not clear to me whether this is really necessary; perhaps the chain
+    could be made into an atomic_notifier.  However a couple of the callout
+    routines do use blocking operations, so this approach seems safer.
+    
+    The head of the notifier chain needs to be initialized before use; this is
+    done by an __init routine at core_initcall time.  If this turns out not to
+    be a good choice, it can easily be changed.
+    
+    Signed-off-by: Alan Stern 
+    Cc: "Paul E. McKenney" 
+    Cc: Jesse Brandeburg 
+    Cc: Dave Jones 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
+index 2caaf71d80c8..86e69b7f9122 100644
+--- a/drivers/cpufreq/cpufreq.c
++++ b/drivers/cpufreq/cpufreq.c
+@@ -52,8 +52,14 @@ static void handle_update(void *data);
+  * The mutex locks both lists.
+  */
+ static BLOCKING_NOTIFIER_HEAD(cpufreq_policy_notifier_list);
+-static BLOCKING_NOTIFIER_HEAD(cpufreq_transition_notifier_list);
++static struct srcu_notifier_head cpufreq_transition_notifier_list;
+ 
++static int __init init_cpufreq_transition_notifier_list(void)
++{
++	srcu_init_notifier_head(&cpufreq_transition_notifier_list);
++	return 0;
++}
++core_initcall(init_cpufreq_transition_notifier_list);
+ 
+ static LIST_HEAD(cpufreq_governor_list);
+ static DEFINE_MUTEX (cpufreq_governor_mutex);
+@@ -262,14 +268,14 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
+ 				freqs->old = policy->cur;
+ 			}
+ 		}
+-		blocking_notifier_call_chain(&cpufreq_transition_notifier_list,
++		srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
+ 				CPUFREQ_PRECHANGE, freqs);
+ 		adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
+ 		break;
+ 
+ 	case CPUFREQ_POSTCHANGE:
+ 		adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
+-		blocking_notifier_call_chain(&cpufreq_transition_notifier_list,
++		srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
+ 				CPUFREQ_POSTCHANGE, freqs);
+ 		if (likely(policy) && likely(policy->cpu == freqs->cpu))
+ 			policy->cur = freqs->new;
+@@ -1049,7 +1055,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg)
+ 		freqs.old = cpu_policy->cur;
+ 		freqs.new = cur_freq;
+ 
+-		blocking_notifier_call_chain(&cpufreq_transition_notifier_list,
++		srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
+ 				    CPUFREQ_SUSPENDCHANGE, &freqs);
+ 		adjust_jiffies(CPUFREQ_SUSPENDCHANGE, &freqs);
+ 
+@@ -1130,7 +1136,7 @@ static int cpufreq_resume(struct sys_device * sysdev)
+ 			freqs.old = cpu_policy->cur;
+ 			freqs.new = cur_freq;
+ 
+-			blocking_notifier_call_chain(
++			srcu_notifier_call_chain(
+ 					&cpufreq_transition_notifier_list,
+ 					CPUFREQ_RESUMECHANGE, &freqs);
+ 			adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs);
+@@ -1176,7 +1182,7 @@ int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list)
+ 
+ 	switch (list) {
+ 	case CPUFREQ_TRANSITION_NOTIFIER:
+-		ret = blocking_notifier_chain_register(
++		ret = srcu_notifier_chain_register(
+ 				&cpufreq_transition_notifier_list, nb);
+ 		break;
+ 	case CPUFREQ_POLICY_NOTIFIER:
+@@ -1208,7 +1214,7 @@ int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list)
+ 
+ 	switch (list) {
+ 	case CPUFREQ_TRANSITION_NOTIFIER:
+-		ret = blocking_notifier_chain_unregister(
++		ret = srcu_notifier_chain_unregister(
+ 				&cpufreq_transition_notifier_list, nb);
+ 		break;
+ 	case CPUFREQ_POLICY_NOTIFIER:

commit e6a92013ba458804161c0c5b6d134d82204dc233
+Author: Alan Stern 
+Date:   Wed Oct 4 02:17:05 2006 -0700
+
+    [PATCH] SRCU: report out-of-memory errors
+    
+    Currently the init_srcu_struct() routine has no way to report out-of-memory
+    errors.  This patch (as761) makes it return -ENOMEM when the per-cpu data
+    allocation fails.
+    
+    The patch also makes srcu_init_notifier_head() report a BUG if a notifier
+    head can't be initialized.  Perhaps it should return -ENOMEM instead, but
+    in the most likely cases where this might occur I don't think any recovery
+    is possible.  Notifier chains generally are not created dynamically.
+    
+    [akpm@osdl.org: avoid statement-with-side-effect in macro]
+    Signed-off-by: Alan Stern 
+    Acked-by: Paul E. McKenney 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/srcu.h b/include/linux/srcu.h
+index 8a45367b5f3a..aca0eee53930 100644
+--- a/include/linux/srcu.h
++++ b/include/linux/srcu.h
+@@ -43,7 +43,7 @@ struct srcu_struct {
+ #define srcu_barrier()
+ #endif /* #else #ifndef CONFIG_PREEMPT */
+ 
+-void init_srcu_struct(struct srcu_struct *sp);
++int init_srcu_struct(struct srcu_struct *sp);
+ void cleanup_srcu_struct(struct srcu_struct *sp);
+ int srcu_read_lock(struct srcu_struct *sp) __acquires(sp);
+ void srcu_read_unlock(struct srcu_struct *sp, int idx) __releases(sp);
+diff --git a/kernel/srcu.c b/kernel/srcu.c
+index 7e1979f624ba..3507cabe963b 100644
+--- a/kernel/srcu.c
++++ b/kernel/srcu.c
+@@ -42,11 +42,12 @@
+  * to any other function.  Each srcu_struct represents a separate domain
+  * of SRCU protection.
+  */
+-void init_srcu_struct(struct srcu_struct *sp)
++int init_srcu_struct(struct srcu_struct *sp)
+ {
+ 	sp->completed = 0;
+-	sp->per_cpu_ref = alloc_percpu(struct srcu_struct_array);
+ 	mutex_init(&sp->mutex);
++	sp->per_cpu_ref = alloc_percpu(struct srcu_struct_array);
++	return (sp->per_cpu_ref ? 0 : -ENOMEM);
+ }
+ 
+ /*
+diff --git a/kernel/sys.c b/kernel/sys.c
+index fd5c71006775..98489d82801b 100644
+--- a/kernel/sys.c
++++ b/kernel/sys.c
+@@ -517,7 +517,8 @@ EXPORT_SYMBOL_GPL(srcu_notifier_call_chain);
+ void srcu_init_notifier_head(struct srcu_notifier_head *nh)
+ {
+ 	mutex_init(&nh->mutex);
+-	init_srcu_struct(&nh->srcu);
++	if (init_srcu_struct(&nh->srcu) < 0)
++		BUG();
+ 	nh->head = NULL;
+ }
+ 

commit eabc069401bcf45bcc3f19e643017bf761780aa8
+Author: Alan Stern 
+Date:   Wed Oct 4 02:17:04 2006 -0700
+
+    [PATCH] Add SRCU-based notifier chains
+    
+    This patch (as751) adds a new type of notifier chain, based on the SRCU
+    (Sleepable Read-Copy Update) primitives recently added to the kernel.  An
+    SRCU notifier chain is much like a blocking notifier chain, in that it must
+    be called in process context and its callout routines are allowed to sleep.
+     The difference is that the chain's links are protected by the SRCU
+    mechanism rather than by an rw-semaphore, so calling the chain has
+    extremely low overhead: no memory barriers and no cache-line bouncing.  On
+    the other hand, unregistering from the chain is expensive and the chain
+    head requires special runtime initialization (plus cleanup if it is to be
+    deallocated).
+    
+    SRCU notifiers are appropriate for notifiers that will be called very
+    frequently and for which unregistration occurs very seldom.  The proposed
+    "task notifier" scheme qualifies, as may some of the network notifiers.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Paul E. McKenney 
+    Acked-by: Chandra Seetharaman 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/notifier.h b/include/linux/notifier.h
+index 7ff386a6ae87..10a43ed0527e 100644
+--- a/include/linux/notifier.h
++++ b/include/linux/notifier.h
+@@ -12,9 +12,10 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ /*
+- * Notifier chains are of three types:
++ * Notifier chains are of four types:
+  *
+  *	Atomic notifier chains: Chain callbacks run in interrupt/atomic
+  *		context. Callouts are not allowed to block.
+@@ -23,13 +24,27 @@
+  *	Raw notifier chains: There are no restrictions on callbacks,
+  *		registration, or unregistration.  All locking and protection
+  *		must be provided by the caller.
++ *	SRCU notifier chains: A variant of blocking notifier chains, with
++ *		the same restrictions.
+  *
+  * atomic_notifier_chain_register() may be called from an atomic context,
+- * but blocking_notifier_chain_register() must be called from a process
+- * context.  Ditto for the corresponding _unregister() routines.
++ * but blocking_notifier_chain_register() and srcu_notifier_chain_register()
++ * must be called from a process context.  Ditto for the corresponding
++ * _unregister() routines.
+  *
+- * atomic_notifier_chain_unregister() and blocking_notifier_chain_unregister()
+- * _must not_ be called from within the call chain.
++ * atomic_notifier_chain_unregister(), blocking_notifier_chain_unregister(),
++ * and srcu_notifier_chain_unregister() _must not_ be called from within
++ * the call chain.
++ *
++ * SRCU notifier chains are an alternative form of blocking notifier chains.
++ * They use SRCU (Sleepable Read-Copy Update) instead of rw-semaphores for
++ * protection of the chain links.  This means there is _very_ low overhead
++ * in srcu_notifier_call_chain(): no cache bounces and no memory barriers.
++ * As compensation, srcu_notifier_chain_unregister() is rather expensive.
++ * SRCU notifier chains should be used when the chain will be called very
++ * often but notifier_blocks will seldom be removed.  Also, SRCU notifier
++ * chains are slightly more difficult to use because they require special
++ * runtime initialization.
+  */
+ 
+ struct notifier_block {
+@@ -52,6 +67,12 @@ struct raw_notifier_head {
+ 	struct notifier_block *head;
+ };
+ 
++struct srcu_notifier_head {
++	struct mutex mutex;
++	struct srcu_struct srcu;
++	struct notifier_block *head;
++};
++
+ #define ATOMIC_INIT_NOTIFIER_HEAD(name) do {	\
+ 		spin_lock_init(&(name)->lock);	\
+ 		(name)->head = NULL;		\
+@@ -64,6 +85,11 @@ struct raw_notifier_head {
+ 		(name)->head = NULL;		\
+ 	} while (0)
+ 
++/* srcu_notifier_heads must be initialized and cleaned up dynamically */
++extern void srcu_init_notifier_head(struct srcu_notifier_head *nh);
++#define srcu_cleanup_notifier_head(name)	\
++		cleanup_srcu_struct(&(name)->srcu);
++
+ #define ATOMIC_NOTIFIER_INIT(name) {				\
+ 		.lock = __SPIN_LOCK_UNLOCKED(name.lock),	\
+ 		.head = NULL }
+@@ -72,6 +98,7 @@ struct raw_notifier_head {
+ 		.head = NULL }
+ #define RAW_NOTIFIER_INIT(name)	{				\
+ 		.head = NULL }
++/* srcu_notifier_heads cannot be initialized statically */
+ 
+ #define ATOMIC_NOTIFIER_HEAD(name)				\
+ 	struct atomic_notifier_head name =			\
+@@ -91,6 +118,8 @@ extern int blocking_notifier_chain_register(struct blocking_notifier_head *,
+ 		struct notifier_block *);
+ extern int raw_notifier_chain_register(struct raw_notifier_head *,
+ 		struct notifier_block *);
++extern int srcu_notifier_chain_register(struct srcu_notifier_head *,
++		struct notifier_block *);
+ 
+ extern int atomic_notifier_chain_unregister(struct atomic_notifier_head *,
+ 		struct notifier_block *);
+@@ -98,6 +127,8 @@ extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *,
+ 		struct notifier_block *);
+ extern int raw_notifier_chain_unregister(struct raw_notifier_head *,
+ 		struct notifier_block *);
++extern int srcu_notifier_chain_unregister(struct srcu_notifier_head *,
++		struct notifier_block *);
+ 
+ extern int atomic_notifier_call_chain(struct atomic_notifier_head *,
+ 		unsigned long val, void *v);
+@@ -105,6 +136,8 @@ extern int blocking_notifier_call_chain(struct blocking_notifier_head *,
+ 		unsigned long val, void *v);
+ extern int raw_notifier_call_chain(struct raw_notifier_head *,
+ 		unsigned long val, void *v);
++extern int srcu_notifier_call_chain(struct srcu_notifier_head *,
++		unsigned long val, void *v);
+ 
+ #define NOTIFY_DONE		0x0000		/* Don't care */
+ #define NOTIFY_OK		0x0001		/* Suits me */
+diff --git a/include/linux/srcu.h b/include/linux/srcu.h
+index 947fdab2ddb0..8a45367b5f3a 100644
+--- a/include/linux/srcu.h
++++ b/include/linux/srcu.h
+@@ -24,6 +24,9 @@
+  *
+  */
+ 
++#ifndef _LINUX_SRCU_H
++#define _LINUX_SRCU_H
++
+ struct srcu_struct_array {
+ 	int c[2];
+ };
+@@ -46,4 +49,5 @@ int srcu_read_lock(struct srcu_struct *sp) __acquires(sp);
+ void srcu_read_unlock(struct srcu_struct *sp, int idx) __releases(sp);
+ void synchronize_srcu(struct srcu_struct *sp);
+ long srcu_batches_completed(struct srcu_struct *sp);
+-void cleanup_srcu_struct(struct srcu_struct *sp);
++
++#endif
+diff --git a/kernel/sys.c b/kernel/sys.c
+index 2314867ae34f..fd5c71006775 100644
+--- a/kernel/sys.c
++++ b/kernel/sys.c
+@@ -153,7 +153,7 @@ static int __kprobes notifier_call_chain(struct notifier_block **nl,
+ 
+ /*
+  *	Atomic notifier chain routines.  Registration and unregistration
+- *	use a mutex, and call_chain is synchronized by RCU (no locks).
++ *	use a spinlock, and call_chain is synchronized by RCU (no locks).
+  */
+ 
+ /**
+@@ -401,6 +401,128 @@ int raw_notifier_call_chain(struct raw_notifier_head *nh,
+ 
+ EXPORT_SYMBOL_GPL(raw_notifier_call_chain);
+ 
++/*
++ *	SRCU notifier chain routines.    Registration and unregistration
++ *	use a mutex, and call_chain is synchronized by SRCU (no locks).
++ */
++
++/**
++ *	srcu_notifier_chain_register - Add notifier to an SRCU notifier chain
++ *	@nh: Pointer to head of the SRCU notifier chain
++ *	@n: New entry in notifier chain
++ *
++ *	Adds a notifier to an SRCU notifier chain.
++ *	Must be called in process context.
++ *
++ *	Currently always returns zero.
++ */
++
++int srcu_notifier_chain_register(struct srcu_notifier_head *nh,
++		struct notifier_block *n)
++{
++	int ret;
++
++	/*
++	 * This code gets used during boot-up, when task switching is
++	 * not yet working and interrupts must remain disabled.  At
++	 * such times we must not call mutex_lock().
++	 */
++	if (unlikely(system_state == SYSTEM_BOOTING))
++		return notifier_chain_register(&nh->head, n);
++
++	mutex_lock(&nh->mutex);
++	ret = notifier_chain_register(&nh->head, n);
++	mutex_unlock(&nh->mutex);
++	return ret;
++}
++
++EXPORT_SYMBOL_GPL(srcu_notifier_chain_register);
++
++/**
++ *	srcu_notifier_chain_unregister - Remove notifier from an SRCU notifier chain
++ *	@nh: Pointer to head of the SRCU notifier chain
++ *	@n: Entry to remove from notifier chain
++ *
++ *	Removes a notifier from an SRCU notifier chain.
++ *	Must be called from process context.
++ *
++ *	Returns zero on success or %-ENOENT on failure.
++ */
++int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh,
++		struct notifier_block *n)
++{
++	int ret;
++
++	/*
++	 * This code gets used during boot-up, when task switching is
++	 * not yet working and interrupts must remain disabled.  At
++	 * such times we must not call mutex_lock().
++	 */
++	if (unlikely(system_state == SYSTEM_BOOTING))
++		return notifier_chain_unregister(&nh->head, n);
++
++	mutex_lock(&nh->mutex);
++	ret = notifier_chain_unregister(&nh->head, n);
++	mutex_unlock(&nh->mutex);
++	synchronize_srcu(&nh->srcu);
++	return ret;
++}
++
++EXPORT_SYMBOL_GPL(srcu_notifier_chain_unregister);
++
++/**
++ *	srcu_notifier_call_chain - Call functions in an SRCU notifier chain
++ *	@nh: Pointer to head of the SRCU notifier chain
++ *	@val: Value passed unmodified to notifier function
++ *	@v: Pointer passed unmodified to notifier function
++ *
++ *	Calls each function in a notifier chain in turn.  The functions
++ *	run in a process context, so they are allowed to block.
++ *
++ *	If the return value of the notifier can be and'ed
++ *	with %NOTIFY_STOP_MASK then srcu_notifier_call_chain
++ *	will return immediately, with the return value of
++ *	the notifier function which halted execution.
++ *	Otherwise the return value is the return value
++ *	of the last notifier function called.
++ */
++
++int srcu_notifier_call_chain(struct srcu_notifier_head *nh,
++		unsigned long val, void *v)
++{
++	int ret;
++	int idx;
++
++	idx = srcu_read_lock(&nh->srcu);
++	ret = notifier_call_chain(&nh->head, val, v);
++	srcu_read_unlock(&nh->srcu, idx);
++	return ret;
++}
++
++EXPORT_SYMBOL_GPL(srcu_notifier_call_chain);
++
++/**
++ *	srcu_init_notifier_head - Initialize an SRCU notifier head
++ *	@nh: Pointer to head of the srcu notifier chain
++ *
++ *	Unlike other sorts of notifier heads, SRCU notifier heads require
++ *	dynamic initialization.  Be sure to call this routine before
++ *	calling any of the other SRCU notifier routines for this head.
++ *
++ *	If an SRCU notifier head is deallocated, it must first be cleaned
++ *	up by calling srcu_cleanup_notifier_head().  Otherwise the head's
++ *	per-cpu data (used by the SRCU mechanism) will leak.
++ */
++
++void srcu_init_notifier_head(struct srcu_notifier_head *nh)
++{
++	mutex_init(&nh->mutex);
++	init_srcu_struct(&nh->srcu);
++	nh->head = NULL;
++}
++
++EXPORT_SYMBOL_GPL(srcu_init_notifier_head);
++
+ /**
+  *	register_reboot_notifier - Register function to be called at reboot time
+  *	@nb: Info about notifier function to be called

commit c16a02d6f5fcfe05dc6fd40aa80a8e1d055300db
+Author: Alan Stern 
+Date:   Fri Sep 29 02:01:21 2006 -0700
+
+    [PATCH] Add section on function return values to CodingStyle
+    
+    This patch (as776) adds a new chapter to Documentation/CodingStyle,
+    explaining the circumstances under which a function should return 0 for
+    failure and non-zero for success as opposed to a negative error code for
+    failure and 0 for success.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle
+index 6d2412ec91ed..29c18966b050 100644
+--- a/Documentation/CodingStyle
++++ b/Documentation/CodingStyle
+@@ -532,6 +532,40 @@ appears outweighs the potential value of the hint that tells gcc to do
+ something it would have done anyway.
+ 
+ 
++		Chapter 16: Function return values and names
++
++Functions can return values of many different kinds, and one of the
++most common is a value indicating whether the function succeeded or
++failed.  Such a value can be represented as an error-code integer
++(-Exxx = failure, 0 = success) or a "succeeded" boolean (0 = failure,
++non-zero = success).
++
++Mixing up these two sorts of representations is a fertile source of
++difficult-to-find bugs.  If the C language included a strong distinction
++between integers and booleans then the compiler would find these mistakes
++for us... but it doesn't.  To help prevent such bugs, always follow this
++convention:
++
++	If the name of a function is an action or an imperative command,
++	the function should return an error-code integer.  If the name
++	is a predicate, the function should return a "succeeded" boolean.
++
++For example, "add work" is a command, and the add_work() function returns 0
++for success or -EBUSY for failure.  In the same way, "PCI device present" is
++a predicate, and the pci_dev_present() function returns 1 if it succeeds in
++finding a matching device or 0 if it doesn't.
++
++All EXPORTed functions must respect this convention, and so should all
++public functions.  Private (static) functions need not, but it is
++recommended that they do.
++
++Functions whose return value is the actual result of a computation, rather
++than an indication of whether the computation succeeded, are not subject to
++this rule.  Generally they indicate failure by returning some out-of-range
++result.  Typical examples would be functions that return pointers; they use
++NULL or the ERR_PTR mechanism to report failure.
++
++
+ 
+ 		Appendix I: References
+ 

commit 6174d0fd35f486f59b743630bdf088a9f9792d4d
+Author: Alan Stern 
+Date:   Tue Sep 26 14:51:48 2006 -0400
+
+    USB: g_file_storage: Set sense info Valid bit only when needed
+    
+    Strictly speaking, the Valid bit in SCSI sense data is supposed to
+    be set only when the Information field contains a valid number.  This
+    patch (as793) turns off the Valid bit when the Information field
+    hasn't been set.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index d472c9c29904..c83d3b6c68f2 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -567,6 +567,7 @@ struct lun {
+ 	unsigned int	ro : 1;
+ 	unsigned int	prevent_medium_removal : 1;
+ 	unsigned int	registered : 1;
++	unsigned int	info_valid : 1;
+ 
+ 	u32		sense_data;
+ 	u32		sense_data_info;
+@@ -1656,6 +1657,7 @@ static int do_read(struct fsg_dev *fsg)
+ 			curlun->sense_data =
+ 					SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
+ 			curlun->sense_data_info = file_offset >> 9;
++			curlun->info_valid = 1;
+ 			bh->inreq->length = 0;
+ 			bh->state = BUF_STATE_FULL;
+ 			break;
+@@ -1691,6 +1693,7 @@ static int do_read(struct fsg_dev *fsg)
+ 		if (nread < amount) {
+ 			curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
+ 			curlun->sense_data_info = file_offset >> 9;
++			curlun->info_valid = 1;
+ 			break;
+ 		}
+ 
+@@ -1785,6 +1788,7 @@ static int do_write(struct fsg_dev *fsg)
+ 				curlun->sense_data =
+ 					SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
+ 				curlun->sense_data_info = usb_offset >> 9;
++				curlun->info_valid = 1;
+ 				continue;
+ 			}
+ 			amount -= (amount & 511);
+@@ -1827,6 +1831,7 @@ static int do_write(struct fsg_dev *fsg)
+ 			if (bh->outreq->status != 0) {
+ 				curlun->sense_data = SS_COMMUNICATION_FAILURE;
+ 				curlun->sense_data_info = file_offset >> 9;
++				curlun->info_valid = 1;
+ 				break;
+ 			}
+ 
+@@ -1868,6 +1873,7 @@ static int do_write(struct fsg_dev *fsg)
+ 			if (nwritten < amount) {
+ 				curlun->sense_data = SS_WRITE_ERROR;
+ 				curlun->sense_data_info = file_offset >> 9;
++				curlun->info_valid = 1;
+ 				break;
+ 			}
+ 
+@@ -2010,6 +2016,7 @@ static int do_verify(struct fsg_dev *fsg)
+ 			curlun->sense_data =
+ 					SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
+ 			curlun->sense_data_info = file_offset >> 9;
++			curlun->info_valid = 1;
+ 			break;
+ 		}
+ 
+@@ -2036,6 +2043,7 @@ static int do_verify(struct fsg_dev *fsg)
+ 		if (nread == 0) {
+ 			curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
+ 			curlun->sense_data_info = file_offset >> 9;
++			curlun->info_valid = 1;
+ 			break;
+ 		}
+ 		file_offset += nread;
+@@ -2079,6 +2087,7 @@ static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
+ 	struct lun	*curlun = fsg->curlun;
+ 	u8		*buf = (u8 *) bh->buf;
+ 	u32		sd, sdinfo;
++	int		valid;
+ 
+ 	/*
+ 	 * From the SCSI-2 spec., section 7.9 (Unit attention condition):
+@@ -2106,15 +2115,18 @@ static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
+ 		fsg->bad_lun_okay = 1;
+ 		sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
+ 		sdinfo = 0;
++		valid = 0;
+ 	} else {
+ 		sd = curlun->sense_data;
+ 		sdinfo = curlun->sense_data_info;
++		valid = curlun->info_valid << 7;
+ 		curlun->sense_data = SS_NO_SENSE;
+ 		curlun->sense_data_info = 0;
++		curlun->info_valid = 0;
+ 	}
+ 
+ 	memset(buf, 0, 18);
+-	buf[0] = 0x80 | 0x70;			// Valid, current error
++	buf[0] = valid | 0x70;			// Valid, current error
+ 	buf[2] = SK(sd);
+ 	put_be32(&buf[3], sdinfo);		// Sense information
+ 	buf[7] = 18 - 8;			// Additional sense length
+@@ -2703,6 +2715,7 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size,
+ 		if (fsg->cmnd[0] != SC_REQUEST_SENSE) {
+ 			curlun->sense_data = SS_NO_SENSE;
+ 			curlun->sense_data_info = 0;
++			curlun->info_valid = 0;
+ 		}
+ 	} else {
+ 		fsg->curlun = curlun = NULL;
+@@ -3332,6 +3345,7 @@ static void handle_exception(struct fsg_dev *fsg)
+ 			curlun->sense_data = curlun->unit_attention_data =
+ 					SS_NO_SENSE;
+ 			curlun->sense_data_info = 0;
++			curlun->info_valid = 0;
+ 		}
+ 		fsg->state = FSG_STATE_IDLE;
+ 	}

commit e0318ebff4d96131bb3524308b845f642e64df81
+Author: Alan Stern 
+Date:   Tue Sep 26 14:50:20 2006 -0400
+
+    USB: fix autosuspend when CONFIG_PM isn't set
+    
+    This patch (as791b) fixes things up to avoid compiler warnings or
+    errors when CONFIG_USB_SUSPEND or CONFIG_PM isn't set.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index ee18d187ca17..113e484c763e 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -303,11 +303,11 @@ int usb_driver_claim_interface(struct usb_driver *driver,
+ 	dev->driver = &driver->drvwrap.driver;
+ 	usb_set_intfdata(iface, priv);
+ 
+-	mutex_lock_nested(&udev->pm_mutex, udev->level);
++	usb_pm_lock(udev);
+ 	iface->condition = USB_INTERFACE_BOUND;
+ 	mark_active(iface);
+ 	iface->pm_usage_cnt = !(driver->supports_autosuspend);
+-	mutex_unlock(&udev->pm_mutex);
++	usb_pm_unlock(udev);
+ 
+ 	/* if interface was already added, bind now; else let
+ 	 * the future device_add() bind it, bypassing probe()
+@@ -356,11 +356,11 @@ void usb_driver_release_interface(struct usb_driver *driver,
+ 	dev->driver = NULL;
+ 	usb_set_intfdata(iface, NULL);
+ 
+-	mutex_lock_nested(&udev->pm_mutex, udev->level);
++	usb_pm_lock(udev);
+ 	iface->condition = USB_INTERFACE_UNBOUND;
+ 	mark_quiesced(iface);
+ 	iface->needs_remote_wakeup = 0;
+-	mutex_unlock(&udev->pm_mutex);
++	usb_pm_unlock(udev);
+ }
+ EXPORT_SYMBOL(usb_driver_release_interface);
+ 
+@@ -789,7 +789,7 @@ EXPORT_SYMBOL_GPL_FUTURE(usb_deregister);
+ 
+ #ifdef CONFIG_PM
+ 
+-/* Caller has locked udev->pm_mutex */
++/* Caller has locked udev's pm_mutex */
+ static int suspend_device(struct usb_device *udev, pm_message_t msg)
+ {
+ 	struct usb_device_driver	*udriver;
+@@ -816,7 +816,7 @@ static int suspend_device(struct usb_device *udev, pm_message_t msg)
+ 	return status;
+ }
+ 
+-/* Caller has locked udev->pm_mutex */
++/* Caller has locked udev's pm_mutex */
+ static int resume_device(struct usb_device *udev)
+ {
+ 	struct usb_device_driver	*udriver;
+@@ -842,7 +842,7 @@ static int resume_device(struct usb_device *udev)
+ 	return status;
+ }
+ 
+-/* Caller has locked intf's usb_device's pm_mutex */
++/* Caller has locked intf's usb_device's pm mutex */
+ static int suspend_interface(struct usb_interface *intf, pm_message_t msg)
+ {
+ 	struct usb_driver	*driver;
+@@ -1064,7 +1064,7 @@ int usb_resume_both(struct usb_device *udev)
+ 	/* Propagate the resume up the tree, if necessary */
+ 	if (udev->state == USB_STATE_SUSPENDED) {
+ 		if (parent) {
+-			mutex_lock_nested(&parent->pm_mutex, parent->level);
++			usb_pm_lock(parent);
+ 			parent->auto_pm = 1;
+ 			status = usb_resume_both(parent);
+ 		} else {
+@@ -1079,7 +1079,7 @@ int usb_resume_both(struct usb_device *udev)
+ 		if (status == 0)
+ 			status = resume_device(udev);
+ 		if (parent)
+-			mutex_unlock(&parent->pm_mutex);
++			usb_pm_unlock(parent);
+ 	} else {
+ 
+ 		/* Needed only for setting udev->dev.power.power_state.event
+@@ -1129,12 +1129,12 @@ int usb_resume_both(struct usb_device *udev)
+  */
+ void usb_autosuspend_device(struct usb_device *udev, int dec_usage_cnt)
+ {
+-	mutex_lock_nested(&udev->pm_mutex, udev->level);
++	usb_pm_lock(udev);
+ 	udev->pm_usage_cnt -= dec_usage_cnt;
+ 	if (udev->pm_usage_cnt <= 0)
+ 		queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+ 				USB_AUTOSUSPEND_DELAY);
+-	mutex_unlock(&udev->pm_mutex);
++	usb_pm_unlock(udev);
+ 	// dev_dbg(&udev->dev, "%s: cnt %d\n",
+ 	//		__FUNCTION__, udev->pm_usage_cnt);
+ }
+@@ -1168,13 +1168,13 @@ int usb_autoresume_device(struct usb_device *udev, int inc_usage_cnt)
+ {
+ 	int	status;
+ 
+-	mutex_lock_nested(&udev->pm_mutex, udev->level);
++	usb_pm_lock(udev);
+ 	udev->pm_usage_cnt += inc_usage_cnt;
+ 	udev->auto_pm = 1;
+ 	status = usb_resume_both(udev);
+ 	if (status != 0)
+ 		udev->pm_usage_cnt -= inc_usage_cnt;
+-	mutex_unlock(&udev->pm_mutex);
++	usb_pm_unlock(udev);
+ 	// dev_dbg(&udev->dev, "%s: status %d cnt %d\n",
+ 	//		__FUNCTION__, status, udev->pm_usage_cnt);
+ 	return status;
+@@ -1215,13 +1215,13 @@ void usb_autopm_put_interface(struct usb_interface *intf)
+ {
+ 	struct usb_device	*udev = interface_to_usbdev(intf);
+ 
+-	mutex_lock_nested(&udev->pm_mutex, udev->level);
++	usb_pm_lock(udev);
+ 	if (intf->condition != USB_INTERFACE_UNBOUND &&
+ 			--intf->pm_usage_cnt <= 0) {
+ 		queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+ 				USB_AUTOSUSPEND_DELAY);
+ 	}
+-	mutex_unlock(&udev->pm_mutex);
++	usb_pm_unlock(udev);
+ 	// dev_dbg(&intf->dev, "%s: cnt %d\n",
+ 	//		__FUNCTION__, intf->pm_usage_cnt);
+ }
+@@ -1263,7 +1263,7 @@ int usb_autopm_get_interface(struct usb_interface *intf)
+ 	struct usb_device	*udev = interface_to_usbdev(intf);
+ 	int			status;
+ 
+-	mutex_lock_nested(&udev->pm_mutex, udev->level);
++	usb_pm_lock(udev);
+ 	if (intf->condition == USB_INTERFACE_UNBOUND)
+ 		status = -ENODEV;
+ 	else {
+@@ -1273,7 +1273,7 @@ int usb_autopm_get_interface(struct usb_interface *intf)
+ 		if (status != 0)
+ 			--intf->pm_usage_cnt;
+ 	}
+-	mutex_unlock(&udev->pm_mutex);
++	usb_pm_unlock(udev);
+ 	// dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
+ 	//		__FUNCTION__, status, intf->pm_usage_cnt);
+ 	return status;
+@@ -1289,10 +1289,10 @@ static int usb_suspend(struct device *dev, pm_message_t message)
+ 	if (is_usb_device(dev)) {
+ 		struct usb_device *udev = to_usb_device(dev);
+ 
+-		mutex_lock_nested(&udev->pm_mutex, udev->level);
++		usb_pm_lock(udev);
+ 		udev->auto_pm = 0;
+ 		status = usb_suspend_both(udev, message);
+-		mutex_unlock(&udev->pm_mutex);
++		usb_pm_unlock(udev);
+ 	} else
+ 		status = 0;
+ 	return status;
+@@ -1305,10 +1305,10 @@ static int usb_resume(struct device *dev)
+ 	if (is_usb_device(dev)) {
+ 		struct usb_device *udev = to_usb_device(dev);
+ 
+-		mutex_lock_nested(&udev->pm_mutex, udev->level);
++		usb_pm_lock(udev);
+ 		udev->auto_pm = 0;
+ 		status = usb_resume_both(udev);
+-		mutex_unlock(&udev->pm_mutex);
++		usb_pm_unlock(udev);
+ 
+ 		/* Rebind drivers that had no suspend method? */
+ 	} else
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 2a8cb3c2b19c..7676690a0386 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1779,7 +1779,7 @@ static int remote_wakeup(struct usb_device *udev)
+ 	 * to the parent hub! */
+ 
+ 	usb_lock_device(udev);
+-	mutex_lock_nested(&udev->pm_mutex, udev->level);
++	usb_pm_lock(udev);
+ 	if (udev->state == USB_STATE_SUSPENDED) {
+ 		dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-");
+ 		/* TRSMRCY = 10 msec */
+@@ -1788,7 +1788,7 @@ static int remote_wakeup(struct usb_device *udev)
+ 		if (status == 0)
+ 			udev->dev.power.power_state.event = PM_EVENT_ON;
+ 	}
+-	mutex_unlock(&udev->pm_mutex);
++	usb_pm_unlock(udev);
+ 
+ 	if (status == 0)
+ 		usb_autoresume_device(udev, 0);
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 239f8e5d247f..e4df9edf1bc0 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -214,10 +214,10 @@ static void usb_autosuspend_work(void *_udev)
+ {
+ 	struct usb_device	*udev = _udev;
+ 
+-	mutex_lock_nested(&udev->pm_mutex, udev->level);
++	usb_pm_lock(udev);
+ 	udev->auto_pm = 1;
+ 	usb_suspend_both(udev, PMSG_SUSPEND);
+-	mutex_unlock(&udev->pm_mutex);
++	usb_pm_unlock(udev);
+ }
+ 
+ #else
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index fb6eb41c374f..f69df137ec0e 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -36,6 +36,16 @@ extern int usb_resume_both(struct usb_device *udev);
+ extern int usb_port_suspend(struct usb_device *dev);
+ extern int usb_port_resume(struct usb_device *dev);
+ 
++static inline void usb_pm_lock(struct usb_device *udev)
++{
++	mutex_lock_nested(&udev->pm_mutex, udev->level);
++}
++
++static inline void usb_pm_unlock(struct usb_device *udev)
++{
++	mutex_unlock(&udev->pm_mutex);
++}
++
+ #else
+ 
+ #define usb_suspend_both(udev, msg)	0
+@@ -45,6 +55,8 @@ static inline int usb_resume_both(struct usb_device *udev)
+ }
+ #define usb_port_suspend(dev)		0
+ #define usb_port_resume(dev)		0
++static inline void usb_pm_lock(struct usb_device *udev) {}
++static inline void usb_pm_unlock(struct usb_device *udev) {}
+ 
+ #endif
+ 
+@@ -58,7 +70,11 @@ extern int usb_autoresume_device(struct usb_device *udev, int inc_busy_cnt);
+ #else
+ 
+ #define usb_autosuspend_device(udev, dec_busy_cnt)	do {} while (0)
+-#define usb_autoresume_device(udev, inc_busy_cnt)	0
++static inline int usb_autoresume_device(struct usb_device *udev,
++		int inc_busy_cnt)
++{
++	return 0;
++}
+ 
+ #endif
+ 
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 0da15b0b02be..190cc1b78fe2 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -380,10 +380,10 @@ struct usb_device {
+ 	int maxchild;			/* Number of ports if hub */
+ 	struct usb_device *children[USB_MAXCHILDREN];
+ 
++	int pm_usage_cnt;		/* usage counter for autosuspend */
+ #ifdef CONFIG_PM
+ 	struct work_struct autosuspend;	/* for delayed autosuspends */
+ 	struct mutex pm_mutex;		/* protects PM operations */
+-	int pm_usage_cnt;		/* usage counter for autosuspend */
+ 
+ 	unsigned auto_pm:1;		/* autosuspend/resume in progress */
+ 	unsigned do_remote_wakeup:1;	/* remote wakeup should be enabled */

commit 8d1a243ba5dda5c1a3cca5df8fb19ab8b138f074
+Author: Alan Stern 
+Date:   Tue Sep 26 14:46:16 2006 -0400
+
+    OHCI: add auto-stop support
+    
+    This patch (as790b) adds "autostop" support to ohci-hcd: the driver
+    will automatically stop the host controller when no devices have been
+    connected for at least one second.  This feature is useful when the
+    USB autosuspend facility isn't available, such as when
+    CONFIG_USB_SUSPEND hasn't been set.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index 1027aa04583d..d1d68c402251 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -715,17 +715,8 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
+ 		return IRQ_NOTMINE;
+ 	}
+ 
+-	/* NOTE:  vendors didn't always make the same implementation
+-	 * choices for RHSC.  Sometimes it triggers on an edge (like
+-	 * setting and maybe clearing a port status change bit); and
+-	 * it's level-triggered on other silicon, active until khubd
+-	 * clears all active port status change bits.  Poll by timer
+-	 * til it's fully debounced and the difference won't matter.
+-	 */
+ 	if (ints & OHCI_INTR_RHSC) {
+ 		ohci_vdbg (ohci, "rhsc\n");
+-		ohci_writel (ohci, OHCI_INTR_RHSC, ®s->intrdisable);
+-		hcd->poll_rh = 1;
+ 		ohci->next_statechange = jiffies + STATECHANGE_DELAY;
+ 		ohci_writel (ohci, OHCI_INTR_RHSC, ®s->intrstatus);
+ 		usb_hcd_poll_rh_status(hcd);
+@@ -743,13 +734,18 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
+ 	if (ints & OHCI_INTR_RD) {
+ 		ohci_vdbg (ohci, "resume detect\n");
+ 		ohci_writel (ohci, OHCI_INTR_RD, ®s->intrstatus);
+-		if (hcd->state != HC_STATE_QUIESCING)
++		hcd->poll_rh = 1;
++		if (ohci->autostop) {
++			spin_lock (&ohci->lock);
++			ohci_rh_resume (ohci);
++			spin_unlock (&ohci->lock);
++		} else
+ 			usb_hcd_resume_root_hub(hcd);
+ 	}
+ 
+ 	if (ints & OHCI_INTR_WDH) {
+ 		if (HC_IS_RUNNING(hcd->state))
+-			ohci_writel (ohci, OHCI_INTR_WDH, ®s->intrdisable);	
++			ohci_writel (ohci, OHCI_INTR_WDH, ®s->intrdisable);
+ 		spin_lock (&ohci->lock);
+ 		dl_done_list (ohci, ptregs);
+ 		spin_unlock (&ohci->lock);
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index ef4965450de5..f36cbd02736d 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -41,31 +41,20 @@ static void ohci_rhsc_enable (struct usb_hcd *hcd)
+ {
+ 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+ 
+-	hcd->poll_rh = 0;
+ 	ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
+ }
+ 
+-#ifdef	CONFIG_PM
+-
+ #define OHCI_SCHED_ENABLES \
+ 	(OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
+ 
+ static void dl_done_list (struct ohci_hcd *, struct pt_regs *);
+ static void finish_unlinks (struct ohci_hcd *, u16 , struct pt_regs *);
+-static int ohci_restart (struct ohci_hcd *ohci);
+ 
+-static int ohci_bus_suspend (struct usb_hcd *hcd)
++static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop)
++__releases(ohci->lock)
++__acquires(ohci->lock)
+ {
+-	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+ 	int			status = 0;
+-	unsigned long		flags;
+-
+-	spin_lock_irqsave (&ohci->lock, flags);
+-
+-	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) {
+-		spin_unlock_irqrestore (&ohci->lock, flags);
+-		return -ESHUTDOWN;
+-	}
+ 
+ 	ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
+ 	switch (ohci->hc_control & OHCI_CTRL_HCFS) {
+@@ -81,15 +70,16 @@ static int ohci_bus_suspend (struct usb_hcd *hcd)
+ 		ohci_dbg (ohci, "needs reinit!\n");
+ 		goto done;
+ 	case OHCI_USB_SUSPEND:
+-		ohci_dbg (ohci, "already suspended\n");
+-		goto done;
++		if (!ohci->autostop) {
++			ohci_dbg (ohci, "already suspended\n");
++			goto done;
++		}
+ 	}
+-	ohci_dbg (ohci, "suspend root hub\n");
++	ohci_dbg (ohci, "%s root hub\n",
++			autostop ? "auto-stop" : "suspend");
+ 
+ 	/* First stop any processing */
+-	if (ohci->hc_control & OHCI_SCHED_ENABLES) {
+-		int		limit;
+-
++	if (!autostop && (ohci->hc_control & OHCI_SCHED_ENABLES)) {
+ 		ohci->hc_control &= ~OHCI_SCHED_ENABLES;
+ 		ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
+ 		ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
+@@ -99,24 +89,17 @@ static int ohci_bus_suspend (struct usb_hcd *hcd)
+ 		 * then the last WDH could take 6+ msec
+ 		 */
+ 		ohci_dbg (ohci, "stopping schedules ...\n");
+-		limit = 2000;
+-		while (limit > 0) {
+-			udelay (250);
+-			limit =- 250;
+-			if (ohci_readl (ohci, &ohci->regs->intrstatus)
+-					& OHCI_INTR_SF)
+-				break;
+-		}
+-		dl_done_list (ohci, NULL);
+-		mdelay (7);
++		ohci->autostop = 0;
++		spin_unlock_irq (&ohci->lock);
++		msleep (8);
++		spin_lock_irq (&ohci->lock);
+ 	}
+ 	dl_done_list (ohci, NULL);
+ 	finish_unlinks (ohci, ohci_frame_no(ohci), NULL);
+-	ohci_writel (ohci, ohci_readl (ohci, &ohci->regs->intrstatus),
+-			&ohci->regs->intrstatus);
+ 
+ 	/* maybe resume can wake root hub */
+-	if (device_may_wakeup(&ohci_to_hcd(ohci)->self.root_hub->dev))
++	if (device_may_wakeup(&ohci_to_hcd(ohci)->self.root_hub->dev) ||
++			autostop)
+ 		ohci->hc_control |= OHCI_CTRL_RWE;
+ 	else {
+ 		ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable);
+@@ -132,13 +115,12 @@ static int ohci_bus_suspend (struct usb_hcd *hcd)
+ 	(void) ohci_readl (ohci, &ohci->regs->control);
+ 
+ 	/* no resumes until devices finish suspending */
+-	ohci->next_statechange = jiffies + msecs_to_jiffies (5);
+-
+-	/* no timer polling */
+-	hcd->poll_rh = 0;
++	if (!autostop) {
++		ohci->next_statechange = jiffies + msecs_to_jiffies (5);
++		ohci->autostop = 0;
++	}
+ 
+ done:
+-	spin_unlock_irqrestore (&ohci->lock, flags);
+ 	return status;
+ }
+ 
+@@ -151,24 +133,16 @@ static inline struct ed *find_head (struct ed *ed)
+ }
+ 
+ /* caller has locked the root hub */
+-static int ohci_bus_resume (struct usb_hcd *hcd)
++static int ohci_rh_resume (struct ohci_hcd *ohci)
++__releases(ohci->lock)
++__acquires(ohci->lock)
+ {
+-	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
++	struct usb_hcd		*hcd = ohci_to_hcd (ohci);
+ 	u32			temp, enables;
+ 	int			status = -EINPROGRESS;
+-	unsigned long		flags;
+-
+-	if (time_before (jiffies, ohci->next_statechange))
+-		msleep(5);
+-
+-	spin_lock_irqsave (&ohci->lock, flags);
+-
+-	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) {
+-		spin_unlock_irqrestore (&ohci->lock, flags);
+-		return -ESHUTDOWN;
+-	}
+-
++	int			autostopped = ohci->autostop;
+ 
++	ohci->autostop = 0;
+ 	ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
+ 
+ 	if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
+@@ -188,7 +162,8 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
+ 		ohci->hc_control |= OHCI_USB_RESUME;
+ 		ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
+ 		(void) ohci_readl (ohci, &ohci->regs->control);
+-		ohci_dbg (ohci, "resume root hub\n");
++		ohci_dbg (ohci, "%s root hub\n",
++				autostopped ? "auto-start" : "resume");
+ 		break;
+ 	case OHCI_USB_RESUME:
+ 		/* HCFS changes sometime after INTR_RD */
+@@ -203,16 +178,26 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
+ 		ohci_dbg (ohci, "lost power\n");
+ 		status = -EBUSY;
+ 	}
+-	spin_unlock_irqrestore (&ohci->lock, flags);
++#ifdef	CONFIG_PM
+ 	if (status == -EBUSY) {
+-		(void) ohci_init (ohci);
+-		return ohci_restart (ohci);
++		if (!autostopped) {
++			static int ohci_restart (struct ohci_hcd *ohci);
++
++			spin_unlock_irq (&ohci->lock);
++			(void) ohci_init (ohci);
++			status = ohci_restart (ohci);
++			spin_lock_irq (&ohci->lock);
++		}
++		return status;
+ 	}
++#endif
+ 	if (status != -EINPROGRESS)
+ 		return status;
++	if (autostopped)
++		goto skip_resume;
++	spin_unlock_irq (&ohci->lock);
+ 
+ 	temp = ohci->num_ports;
+-	enables = 0;
+ 	while (temp--) {
+ 		u32 stat = ohci_readl (ohci,
+ 				       &ohci->regs->roothub.portstatus [temp]);
+@@ -245,17 +230,21 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
+ 	/* Sometimes PCI D3 suspend trashes frame timings ... */
+ 	periodic_reinit (ohci);
+ 
++	/* the following code is executed with ohci->lock held and
++	 * irqs disabled if and only if autostopped is true
++	 */
++
++skip_resume:
+ 	/* interrupts might have been disabled */
+ 	ohci_writel (ohci, OHCI_INTR_INIT, &ohci->regs->intrenable);
+ 	if (ohci->ed_rm_list)
+ 		ohci_writel (ohci, OHCI_INTR_SF, &ohci->regs->intrenable);
+-	ohci_writel (ohci, ohci_readl (ohci, &ohci->regs->intrstatus),
+-			&ohci->regs->intrstatus);
+ 
+ 	/* Then re-enable operations */
+ 	ohci_writel (ohci, OHCI_USB_OPER, &ohci->regs->control);
+ 	(void) ohci_readl (ohci, &ohci->regs->control);
+-	msleep (3);
++	if (!autostopped)
++		msleep (3);
+ 
+ 	temp = ohci->hc_control;
+ 	temp &= OHCI_CTRL_RWC;
+@@ -265,7 +254,11 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
+ 	(void) ohci_readl (ohci, &ohci->regs->control);
+ 
+ 	/* TRSMRCY */
+-	msleep (10);
++	if (!autostopped) {
++		msleep (10);
++		spin_lock_irq (&ohci->lock);
++	}
++	/* now ohci->lock is always held and irqs are always disabled */
+ 
+ 	/* keep it alive for more than ~5x suspend + resume costs */
+ 	ohci->next_statechange = jiffies + STATECHANGE_DELAY;
+@@ -302,6 +295,45 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
+ 	return 0;
+ }
+ 
++#ifdef	CONFIG_PM
++
++static int ohci_bus_suspend (struct usb_hcd *hcd)
++{
++	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
++	int			rc;
++
++	spin_lock_irq (&ohci->lock);
++
++	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
++		rc = -ESHUTDOWN;
++	else
++		rc = ohci_rh_suspend (ohci, 0);
++	spin_unlock_irq (&ohci->lock);
++	return rc;
++}
++
++static int ohci_bus_resume (struct usb_hcd *hcd)
++{
++	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
++	int			rc;
++
++	if (time_before (jiffies, ohci->next_statechange))
++		msleep(5);
++
++	spin_lock_irq (&ohci->lock);
++
++	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
++		rc = -ESHUTDOWN;
++	else
++		rc = ohci_rh_resume (ohci);
++	spin_unlock_irq (&ohci->lock);
++
++	/* poll until we know a device is connected or we autostop */
++	if (rc == 0)
++		usb_hcd_poll_rh_status(hcd);
++	return rc;
++}
++
+ #endif	/* CONFIG_PM */
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -313,17 +345,11 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ {
+ 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
+ 	int		i, changed = 0, length = 1;
++	int		any_connected = 0, rhsc_enabled = 1;
+ 	unsigned long	flags;
+ 
+ 	spin_lock_irqsave (&ohci->lock, flags);
+ 
+-	/* handle autosuspended root:  finish resuming before
+-	 * letting khubd or root hub timer see state changes.
+-	 */
+-	if (unlikely((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER
+-		     || !HC_IS_RUNNING(hcd->state)))
+-		goto done;
+-
+ 	/* undocumented erratum seen on at least rev D */
+ 	if ((ohci->flags & OHCI_QUIRK_AMD756)
+ 			&& (roothub_a (ohci) & RH_A_NDP) > MAX_ROOT_PORTS) {
+@@ -347,6 +373,9 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ 	for (i = 0; i < ohci->num_ports; i++) {
+ 		u32	status = roothub_portstatus (ohci, i);
+ 
++		/* can't autostop if ports are connected */
++		any_connected |= (status & RH_PS_CCS);
++
+ 		if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
+ 				| RH_PS_OCIC | RH_PS_PRSC)) {
+ 			changed = 1;
+@@ -354,15 +383,69 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ 			    buf [0] |= 1 << (i + 1);
+ 			else
+ 			    buf [1] |= 1 << (i - 7);
+-			continue;
+ 		}
+ 	}
+ 
+-	/* after root hub changes, stop polling after debouncing
+-	 * for a while and maybe kicking in autosuspend
++	/* NOTE:  vendors didn't always make the same implementation
++	 * choices for RHSC.  Sometimes it triggers on an edge (like
++	 * setting and maybe clearing a port status change bit); and
++	 * it's level-triggered on other silicon, active until khubd
++	 * clears all active port status change bits.  If it's still
++	 * set (level-triggered) we must disable it and rely on
++	 * polling until khubd re-enables it.
+ 	 */
+-	if (changed)
+-		ohci->next_statechange = jiffies + STATECHANGE_DELAY;
++	if (ohci_readl (ohci, &ohci->regs->intrstatus) & OHCI_INTR_RHSC) {
++		ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable);
++		(void) ohci_readl (ohci, &ohci->regs->intrdisable);
++		rhsc_enabled = 0;
++	}
++	hcd->poll_rh = 1;
++
++	/* carry out appropriate state changes */
++	switch (ohci->hc_control & OHCI_CTRL_HCFS) {
++
++	case OHCI_USB_OPER:
++		/* keep on polling until we know a device is connected
++		 * and RHSC is enabled */
++		if (!ohci->autostop) {
++			if (any_connected) {
++				if (rhsc_enabled)
++					hcd->poll_rh = 0;
++			} else {
++				ohci->autostop = 1;
++				ohci->next_statechange = jiffies + HZ;
++			}
++
++		/* if no devices have been attached for one second, autostop */
++		} else {
++			if (changed || any_connected) {
++				ohci->autostop = 0;
++				ohci->next_statechange = jiffies +
++						STATECHANGE_DELAY;
++			} else if (time_after_eq (jiffies,
++						ohci->next_statechange)
++					&& !ohci->ed_rm_list
++					&& !(ohci->hc_control &
++						OHCI_SCHED_ENABLES)) {
++				ohci_rh_suspend (ohci, 1);
++			}
++		}
++		break;
++
++	/* if there is a port change, autostart or ask to be resumed */
++	case OHCI_USB_SUSPEND:
++	case OHCI_USB_RESUME:
++		if (changed) {
++			if (ohci->autostop)
++				ohci_rh_resume (ohci);
++			else
++				usb_hcd_resume_root_hub (hcd);
++		} else {
++			/* everything is idle, no need for polling */
++			hcd->poll_rh = 0;
++		}
++		break;
++	}
+ 
+ done:
+ 	spin_unlock_irqrestore (&ohci->lock, flags);
+diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
+index 93fdc3c35341..a2f42a2f47c6 100644
+--- a/drivers/usb/host/ohci.h
++++ b/drivers/usb/host/ohci.h
+@@ -388,6 +388,7 @@ struct ohci_hcd {
+ 	u32 			hc_control;	/* copy of hc control reg */
+ 	unsigned long		next_statechange;	/* suspend/resume */
+ 	u32			fminterval;		/* saved register */
++	unsigned		autostop:1;	/* rh auto stopping/stopped */
+ 
+ 	unsigned long		flags;		/* for HC bugs */
+ #define	OHCI_QUIRK_AMD756	0x01			/* erratum #4 */

commit 1f7e1a3b7e05c833229c4b6e9d3c96262df59e99
+Author: Alan Stern 
+Date:   Mon Sep 25 15:41:21 2006 -0400
+
+    OHCI: remove existing autosuspend code
+    
+    The autosuspend technique used by ohci-hcd doesn't mesh well with the
+    newer USB core autosuspend code.  This patch (as789) removes ohci-hcd's
+    autosuspend support.  Now the driver will be usable, but it won't
+    automatically go into a low-power state when no devices are connected.
+    That's for a later patch.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index 0b899339cac8..ef4965450de5 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -41,6 +41,7 @@ static void ohci_rhsc_enable (struct usb_hcd *hcd)
+ {
+ 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+ 
++	hcd->poll_rh = 0;
+ 	ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
+ }
+ 
+@@ -117,8 +118,10 @@ static int ohci_bus_suspend (struct usb_hcd *hcd)
+ 	/* maybe resume can wake root hub */
+ 	if (device_may_wakeup(&ohci_to_hcd(ohci)->self.root_hub->dev))
+ 		ohci->hc_control |= OHCI_CTRL_RWE;
+-	else
++	else {
++		ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable);
+ 		ohci->hc_control &= ~OHCI_CTRL_RWE;
++	}
+ 
+ 	/* Suspend hub ... this is the "global (to this bus) suspend" mode,
+ 	 * which doesn't imply ports will first be individually suspended.
+@@ -310,20 +313,16 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ {
+ 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
+ 	int		i, changed = 0, length = 1;
+-	int		can_suspend;
+ 	unsigned long	flags;
+ 
+-	can_suspend = device_may_wakeup(&hcd->self.root_hub->dev);
+ 	spin_lock_irqsave (&ohci->lock, flags);
+ 
+ 	/* handle autosuspended root:  finish resuming before
+ 	 * letting khubd or root hub timer see state changes.
+ 	 */
+ 	if (unlikely((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER
+-		     || !HC_IS_RUNNING(hcd->state))) {
+-		can_suspend = 0;
++		     || !HC_IS_RUNNING(hcd->state)))
+ 		goto done;
+-	}
+ 
+ 	/* undocumented erratum seen on at least rev D */
+ 	if ((ohci->flags & OHCI_QUIRK_AMD756)
+@@ -348,10 +347,6 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ 	for (i = 0; i < ohci->num_ports; i++) {
+ 		u32	status = roothub_portstatus (ohci, i);
+ 
+-		/* can't autosuspend with active ports */
+-		if ((status & RH_PS_PES) && !(status & RH_PS_PSS))
+-			can_suspend = 0;
+-
+ 		if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
+ 				| RH_PS_OCIC | RH_PS_PRSC)) {
+ 			changed = 1;
+@@ -366,42 +361,12 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ 	/* after root hub changes, stop polling after debouncing
+ 	 * for a while and maybe kicking in autosuspend
+ 	 */
+-	if (changed) {
++	if (changed)
+ 		ohci->next_statechange = jiffies + STATECHANGE_DELAY;
+-		can_suspend = 0;
+-	} else if (time_before (jiffies, ohci->next_statechange)) {
+-		can_suspend = 0;
+-	} else {
+-#ifdef	CONFIG_PM
+-		can_suspend = can_suspend
+-			&& !ohci->ed_rm_list
+-			&& ((OHCI_CTRL_HCFS | OHCI_SCHED_ENABLES)
+-					& ohci->hc_control)
+-				== OHCI_USB_OPER;
+-#endif
+-		if (hcd->uses_new_polling) {
+-			hcd->poll_rh = 0;
+-			/* use INTR_RHSC iff INTR_RD won't apply */
+-			if (!can_suspend)
+-				ohci_writel (ohci, OHCI_INTR_RHSC,
+-						&ohci->regs->intrenable);
+-		}
+-	}
+ 
+ done:
+ 	spin_unlock_irqrestore (&ohci->lock, flags);
+ 
+-#ifdef	CONFIG_PM
+-	/* save power by autosuspending idle root hubs;
+-	 * INTR_RD wakes us when there's work
+-	 */
+-	if (can_suspend && usb_trylock_device (hcd->self.root_hub) == 0) {
+-		ohci_vdbg (ohci, "autosuspend\n");
+-		(void) ohci_bus_suspend (hcd);
+-		usb_unlock_device (hcd->self.root_hub);
+-	}
+-#endif
+-
+ 	return changed ? length : 0;
+ }
+ 
+@@ -572,9 +537,6 @@ static int ohci_hub_control (
+ 			break;
+ 		case USB_PORT_FEAT_SUSPEND:
+ 			temp = RH_PS_POCI;
+-			if ((ohci->hc_control & OHCI_CTRL_HCFS)
+-					!= OHCI_USB_OPER)
+-				usb_hcd_resume_root_hub(hcd);
+ 			break;
+ 		case USB_PORT_FEAT_C_SUSPEND:
+ 			temp = RH_PS_PSSC;

commit d19ac7da72ab950c315d0da0aa03464587d88b53
+Author: Alan Stern 
+Date:   Mon Sep 25 15:41:12 2006 -0400
+
+    USB: allow both root-hub interrupts and polling
+    
+    Originally I didn't think any host controller driver would ever use
+    interrupts and polling at the same time, but it turns out ohci-hcd wants
+    to do exactly that.  This patch (as788) makes it possible.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 0d5cbf254e5e..37f9f5e7425d 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -836,8 +836,7 @@ void usb_enable_root_hub_irq (struct usb_bus *bus)
+ 	struct usb_hcd *hcd;
+ 
+ 	hcd = container_of (bus, struct usb_hcd, self);
+-	if (hcd->driver->hub_irq_enable && !hcd->poll_rh &&
+-			hcd->state != HC_STATE_HALT)
++	if (hcd->driver->hub_irq_enable && hcd->state != HC_STATE_HALT)
+ 		hcd->driver->hub_irq_enable (hcd);
+ }
+ 

commit 2de9eaefa7330b8e3d3fc5f31288cb1e826173a8
+Author: Alan Stern 
+Date:   Mon Sep 25 14:31:15 2006 -0400
+
+    USB: g_file_storage: fix "ignoring return value" warnings
+    
+    This patch (as792) fixes "ignoring return value" warnings in
+    file_storage.c.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index 8d7f1e84cd7b..d472c9c29904 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -3873,21 +3873,26 @@ static int __init fsg_bind(struct usb_gadget *gadget)
+ 	for (i = 0; i < fsg->nluns; ++i) {
+ 		curlun = &fsg->luns[i];
+ 		curlun->ro = mod_data.ro[i];
++		curlun->dev.release = lun_release;
+ 		curlun->dev.parent = &gadget->dev;
+ 		curlun->dev.driver = &fsg_driver.driver;
+ 		dev_set_drvdata(&curlun->dev, fsg);
+ 		snprintf(curlun->dev.bus_id, BUS_ID_SIZE,
+ 				"%s-lun%d", gadget->dev.bus_id, i);
+ 
+-		if ((rc = device_register(&curlun->dev)) != 0)
++		if ((rc = device_register(&curlun->dev)) != 0) {
+ 			INFO(fsg, "failed to register LUN%d: %d\n", i, rc);
+-		else {
+-			curlun->registered = 1;
+-			curlun->dev.release = lun_release;
+-			device_create_file(&curlun->dev, &dev_attr_ro);
+-			device_create_file(&curlun->dev, &dev_attr_file);
+-			kref_get(&fsg->ref);
++			goto out;
++		}
++		if ((rc = device_create_file(&curlun->dev,
++					&dev_attr_ro)) != 0 ||
++				(rc = device_create_file(&curlun->dev,
++					&dev_attr_file)) != 0) {
++			device_unregister(&curlun->dev);
++			goto out;
+ 		}
++		curlun->registered = 1;
++		kref_get(&fsg->ref);
+ 
+ 		if (mod_data.file[i] && *mod_data.file[i]) {
+ 			if ((rc = open_backing_file(curlun,

commit efd54a364121f61b2050b1df5ecb1b8329c4eaba
+Author: Alan Stern 
+Date:   Mon Sep 25 11:55:56 2006 -0400
+
+    USB: dummy-hcd: fix "warn-unused-result" messages
+    
+    This patch (as758) fixes the "warn-unused-result" messages in dummy-hcd.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index fdab97a27c08..4d2946e540cf 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -816,15 +816,14 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
+ 	dum->gadget.dev.driver = &driver->driver;
+ 	dev_dbg (udc_dev(dum), "binding gadget driver '%s'\n",
+ 			driver->driver.name);
+-	if ((retval = driver->bind (&dum->gadget)) != 0) {
+-		dum->driver = NULL;
+-		dum->gadget.dev.driver = NULL;
+-		return retval;
+-	}
++	if ((retval = driver->bind (&dum->gadget)) != 0)
++		goto err_bind_gadget;
+ 
+ 	driver->driver.bus = dum->gadget.dev.parent->bus;
+-	driver_register (&driver->driver);
+-	device_bind_driver (&dum->gadget.dev);
++	if ((retval = driver_register (&driver->driver)) != 0)
++		goto err_register;
++	if ((retval = device_bind_driver (&dum->gadget.dev)) != 0)
++		goto err_bind_driver;
+ 
+ 	/* khubd will enumerate this in a while */
+ 	spin_lock_irq (&dum->lock);
+@@ -834,6 +833,19 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
+ 
+ 	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
+ 	return 0;
++
++err_bind_driver:
++	driver_unregister (&driver->driver);
++err_register:
++	driver->unbind (&dum->gadget);
++	spin_lock_irq (&dum->lock);
++	dum->pullup = 0;
++	set_link_state (dum);
++	spin_unlock_irq (&dum->lock);
++err_bind_gadget:
++	dum->driver = NULL;
++	dum->gadget.dev.driver = NULL;
++	return retval;
+ }
+ EXPORT_SYMBOL (usb_gadget_register_driver);
+ 
+@@ -916,7 +928,9 @@ static int dummy_udc_probe (struct platform_device *pdev)
+ 	usb_get_hcd (dummy_to_hcd (dum));
+ 
+ 	platform_set_drvdata (pdev, dum);
+-	device_create_file (&dum->gadget.dev, &dev_attr_function);
++	rc = device_create_file (&dum->gadget.dev, &dev_attr_function);
++	if (rc < 0)
++		device_unregister (&dum->gadget.dev);
+ 	return rc;
+ }
+ 
+@@ -1864,8 +1878,7 @@ static int dummy_start (struct usb_hcd *hcd)
+ #endif
+ 
+ 	/* FIXME 'urbs' should be a per-device thing, maybe in usbcore */
+-	device_create_file (dummy_dev(dum), &dev_attr_urbs);
+-	return 0;
++	return device_create_file (dummy_dev(dum), &dev_attr_urbs);
+ }
+ 
+ static void dummy_stop (struct usb_hcd *hcd)

commit bd859281c09b4318153dc7222b5e9052aad83b61
+Author: Alan Stern 
+Date:   Tue Sep 19 10:14:07 2006 -0400
+
+    USB: create new workqueue thread for USB autosuspend
+    
+    This patch (as787) creates a new workqueue thread to handle delayed
+    USB autosuspend requests.  Previously the code used keventd.  However
+    it turns out that the hub driver's suspend routine calls
+    flush_scheduled_work(), making it a poor candidate for running in
+    keventd (the call immediately deadlocks).  The solution is to use a
+    new thread instead of keventd.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index c2aad6a4d49f..ee18d187ca17 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -24,6 +24,7 @@
+ 
+ #include 
+ #include 
++#include 
+ #include "hcd.h"
+ #include "usb.h"
+ 
+@@ -1131,7 +1132,7 @@ void usb_autosuspend_device(struct usb_device *udev, int dec_usage_cnt)
+ 	mutex_lock_nested(&udev->pm_mutex, udev->level);
+ 	udev->pm_usage_cnt -= dec_usage_cnt;
+ 	if (udev->pm_usage_cnt <= 0)
+-		schedule_delayed_work(&udev->autosuspend,
++		queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+ 				USB_AUTOSUSPEND_DELAY);
+ 	mutex_unlock(&udev->pm_mutex);
+ 	// dev_dbg(&udev->dev, "%s: cnt %d\n",
+@@ -1215,10 +1216,10 @@ void usb_autopm_put_interface(struct usb_interface *intf)
+ 	struct usb_device	*udev = interface_to_usbdev(intf);
+ 
+ 	mutex_lock_nested(&udev->pm_mutex, udev->level);
+-	if (intf->condition != USB_INTERFACE_UNBOUND) {
+-		if (--intf->pm_usage_cnt <= 0)
+-			schedule_delayed_work(&udev->autosuspend,
+-					USB_AUTOSUSPEND_DELAY);
++	if (intf->condition != USB_INTERFACE_UNBOUND &&
++			--intf->pm_usage_cnt <= 0) {
++		queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
++				USB_AUTOSUSPEND_DELAY);
+ 	}
+ 	mutex_unlock(&udev->pm_mutex);
+ 	// dev_dbg(&intf->dev, "%s: cnt %d\n",
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 60ef4ef0101a..239f8e5d247f 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -33,6 +33,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ #include 
+@@ -47,6 +48,8 @@ const char *usbcore_name = "usbcore";
+ 
+ static int nousb;	/* Disable USB when built into kernel image */
+ 
++struct workqueue_struct *ksuspend_usb_wq;	/* For autosuspend */
++
+ 
+ /**
+  * usb_ifnum_to_if - get the interface object with a given interface number
+@@ -170,9 +173,9 @@ static void usb_release_dev(struct device *dev)
+ 
+ 	udev = to_usb_device(dev);
+ 
+-#ifdef	CONFIG_PM
++#ifdef	CONFIG_USB_SUSPEND
+ 	cancel_delayed_work(&udev->autosuspend);
+-	flush_scheduled_work();
++	flush_workqueue(ksuspend_usb_wq);
+ #endif
+ 	usb_destroy_configuration(udev);
+ 	usb_put_hcd(bus_to_hcd(udev->bus));
+@@ -184,6 +187,28 @@ static void usb_release_dev(struct device *dev)
+ 
+ #ifdef	CONFIG_PM
+ 
++static int ksuspend_usb_init(void)
++{
++	ksuspend_usb_wq = create_singlethread_workqueue("ksuspend_usbd");
++	if (!ksuspend_usb_wq)
++		return -ENOMEM;
++	return 0;
++}
++
++static void ksuspend_usb_cleanup(void)
++{
++	destroy_workqueue(ksuspend_usb_wq);
++}
++
++#else
++
++#define ksuspend_usb_init()	0
++#define ksuspend_usb_cleanup()	do {} while (0)
++
++#endif
++
++#ifdef	CONFIG_USB_SUSPEND
++
+ /* usb_autosuspend_work - callback routine to autosuspend a USB device */
+ static void usb_autosuspend_work(void *_udev)
+ {
+@@ -195,6 +220,11 @@ static void usb_autosuspend_work(void *_udev)
+ 	mutex_unlock(&udev->pm_mutex);
+ }
+ 
++#else
++
++static void usb_autosuspend_work(void *_udev)
++{}
++
+ #endif
+ 
+ /**
+@@ -976,9 +1006,12 @@ static int __init usb_init(void)
+ 		return 0;
+ 	}
+ 
++	retval = ksuspend_usb_init();
++	if (retval)
++		goto out;
+ 	retval = bus_register(&usb_bus_type);
+ 	if (retval) 
+-		goto out;
++		goto bus_register_failed;
+ 	retval = usb_host_init();
+ 	if (retval)
+ 		goto host_init_failed;
+@@ -1014,6 +1047,8 @@ static int __init usb_init(void)
+ 	usb_host_cleanup();
+ host_init_failed:
+ 	bus_unregister(&usb_bus_type);
++bus_register_failed:
++	ksuspend_usb_cleanup();
+ out:
+ 	return retval;
+ }
+@@ -1035,6 +1070,7 @@ static void __exit usb_exit(void)
+ 	usb_hub_cleanup();
+ 	usb_host_cleanup();
+ 	bus_unregister(&usb_bus_type);
++	ksuspend_usb_cleanup();
+ }
+ 
+ subsys_initcall(usb_init);
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 0c09ecced6e1..fb6eb41c374f 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -62,6 +62,7 @@ extern int usb_autoresume_device(struct usb_device *udev, int inc_busy_cnt);
+ 
+ #endif
+ 
++extern struct workqueue_struct *ksuspend_usb_wq;
+ extern struct bus_type usb_bus_type;
+ extern struct usb_device_driver usb_generic_driver;
+ 

commit 7923811a46f7e29ae8052edf2461e6c6b8ec2415
+Author: Alan Stern 
+Date:   Thu Sep 28 12:11:56 2006 -0400
+
+    USB: unusual-devs entry for Nokia E60
+    
+    This patch (as794) adds an unusual_devs entry for the Nokia E60.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 40bf159f7d54..16baa105ed0a 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -152,6 +152,13 @@ UNUSUAL_DEV(  0x0421, 0x042e, 0x0100, 0x0100,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
+ 
++/* Reported by Jon Hart  */
++UNUSUAL_DEV(  0x0421, 0x0434, 0x0100, 0x0100,
++		"Nokia",
++		"E60",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ),
++
+ /* Reported by Sumedha Swamy  and
+  * Einar Th. Einarsson  */
+ UNUSUAL_DEV(  0x0421, 0x0444, 0x0100, 0x0100,

commit 353a4098c61272b33a02ec5802fb3859fec91a0e
+Author: Alan Stern 
+Date:   Tue Sep 19 10:07:58 2006 -0400
+
+    USB: force root hub resume after power loss
+    
+    This patch(as785) forces the PM core to resume a root hub after a
+    power loss during system sleep.  If the root hub had been suspended
+    before the system sleep then normally the PM core would not resume it
+    afterward.  Without this resume, various sorts of wakeup events (like
+    port change events) can get lost.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index c74baad19b16..00441cde4588 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1053,6 +1053,12 @@ void usb_root_hub_lost_power(struct usb_device *rhdev)
+ 	unsigned long flags;
+ 
+ 	dev_warn(&rhdev->dev, "root hub lost power or was reset\n");
++
++	/* Make sure no potential wakeup events get lost,
++	 * by forcing the root hub to be resumed.
++	 */
++	rhdev->dev.power.prev_state.event = PM_EVENT_ON;
++
+ 	spin_lock_irqsave(&device_state_lock, flags);
+ 	hub = hdev_to_hub(rhdev);
+ 	for (port1 = 1; port1 <= rhdev->maxchild; ++port1) {

commit 592fbbe4bc339399d363dd55f0391e0623400706
+Author: Alan Stern 
+Date:   Tue Sep 19 10:08:43 2006 -0400
+
+    USB: fix root-hub resume when CONFIG_USB_SUSPEND is not set
+    
+    This patch (as786) removes a redundant test and fixes a problem
+    involving repeated system sleeps when CONFIG_USB_SUSPEND is not set.
+    During the first wakeup, the root hub's dev.power.power_state.event
+    field doesn't get updated, causing it not to be suspended during the
+    second sleep transition.
+    
+    This takes care of the issue raised by Rafael J. Wysocki and Mattia
+    Dongili.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 2b2000ac05ab..0d063c8ca4b4 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1071,10 +1071,15 @@ int usb_resume_both(struct usb_device *udev)
+ 					PM_EVENT_ON)
+ 				status = -EHOSTUNREACH;
+ 		}
+-		if (status == 0 && udev->state == USB_STATE_SUSPENDED)
++		if (status == 0)
+ 			status = resume_device(udev);
+ 		if (parent)
+ 			mutex_unlock(&parent->pm_mutex);
++	} else {
++
++		/* Needed only for setting udev->dev.power.power_state.event
++		 * and for possible debugging message. */
++		status = resume_device(udev);
+ 	}
+ 
+ 	/* Now the parent won't suspend until we are finished */

commit 02c399ee45a54987c152fe5f627ed949bb55f187
+Author: Alan Stern 
+Date:   Wed Aug 30 15:47:11 2006 -0400
+
+    usbcore: remove usb_suspend_root_hub
+    
+    This patch (as740) removes the existing support for autosuspend of
+    root hubs.  That support fit in rather awkwardly with the rest of
+    usbcore and it was used only by ohci-hcd.  It won't be needed any more
+    since the hub driver will take care of autosuspending all hubs, root
+    or external.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 9dfc812de034..e86f62957085 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1431,50 +1431,6 @@ int hcd_bus_resume (struct usb_bus *bus)
+ 	return status;
+ }
+ 
+-/*
+- * usb_hcd_suspend_root_hub - HCD autosuspends downstream ports
+- * @hcd: host controller for this root hub
+- *
+- * This call arranges that usb_hcd_resume_root_hub() is safe to call later;
+- * that the HCD's root hub polling is deactivated; and that the root's hub
+- * driver is suspended.  HCDs may call this to autosuspend when their root
+- * hub's downstream ports are all inactive:  unpowered, disconnected,
+- * disabled, or suspended.
+- *
+- * The HCD will autoresume on device connect change detection (using SRP
+- * or a D+/D- pullup).  The HCD also autoresumes on remote wakeup signaling
+- * from any ports that are suspended (if that is enabled).  In most cases,
+- * overcurrent signaling (on powered ports) will also start autoresume.
+- *
+- * Always called with IRQs blocked.
+- */
+-void usb_hcd_suspend_root_hub (struct usb_hcd *hcd)
+-{
+-	struct urb	*urb;
+-
+-	spin_lock (&hcd_root_hub_lock);
+-	usb_suspend_root_hub (hcd->self.root_hub);
+-
+-	/* force status urb to complete/unlink while suspended */
+-	if (hcd->status_urb) {
+-		urb = hcd->status_urb;
+-		urb->status = -ECONNRESET;
+-		urb->hcpriv = NULL;
+-		urb->actual_length = 0;
+-
+-		del_timer (&hcd->rh_timer);
+-		hcd->poll_pending = 0;
+-		hcd->status_urb = NULL;
+-	} else
+-		urb = NULL;
+-	spin_unlock (&hcd_root_hub_lock);
+-	hcd->state = HC_STATE_SUSPENDED;
+-
+-	if (urb)
+-		usb_hcd_giveback_urb (hcd, urb, NULL);
+-}
+-EXPORT_SYMBOL_GPL(usb_hcd_suspend_root_hub);
+-
+ /**
+  * usb_hcd_resume_root_hub - called by HCD to resume its root hub 
+  * @hcd: host controller for this root hub
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index 7a2bcba2ae61..676877c15f81 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -368,17 +368,11 @@ extern int usb_find_interface_driver (struct usb_device *dev,
+ #define usb_endpoint_out(ep_dir)	(!((ep_dir) & USB_DIR_IN))
+ 
+ #ifdef CONFIG_PM
+-extern void usb_hcd_suspend_root_hub (struct usb_hcd *hcd);
+ extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
+ extern void usb_root_hub_lost_power (struct usb_device *rhdev);
+ extern int hcd_bus_suspend (struct usb_bus *bus);
+ extern int hcd_bus_resume (struct usb_bus *bus);
+ #else
+-static inline void usb_hcd_suspend_root_hub(struct usb_hcd *hcd)
+-{
+-	return;
+-}
+-
+ static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
+ {
+ 	return;
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index dee812bc6c43..7479bd329abb 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -452,18 +452,14 @@ static void hub_power_on(struct usb_hub *hub)
+ 	msleep(max(pgood_delay, (unsigned) 100));
+ }
+ 
+-static inline void __hub_quiesce(struct usb_hub *hub)
++static void hub_quiesce(struct usb_hub *hub)
+ {
+ 	/* (nonblocking) khubd and related activity won't re-trigger */
+ 	hub->quiescing = 1;
+ 	hub->activating = 0;
+ 	hub->resume_root_hub = 0;
+-}
+ 
+-static void hub_quiesce(struct usb_hub *hub)
+-{
+ 	/* (blocking) stop khubd and related activity */
+-	__hub_quiesce(hub);
+ 	usb_kill_urb(hub->urb);
+ 	if (hub->has_indicators)
+ 		cancel_delayed_work(&hub->leds);
+@@ -1914,18 +1910,6 @@ static inline int remote_wakeup(struct usb_device *udev)
+ #define hub_resume NULL
+ #endif
+ 
+-void usb_suspend_root_hub(struct usb_device *hdev)
+-{
+-	struct usb_hub *hub = hdev_to_hub(hdev);
+-
+-	/* This also makes any led blinker stop retriggering.  We're called
+-	 * from irq, so the blinker might still be scheduled.  Caller promises
+-	 * that the root hub status URB will be canceled.
+-	 */
+-	__hub_quiesce(hub);
+-	mark_quiesced(to_usb_interface(hub->intfdev));
+-}
+-
+ void usb_resume_root_hub(struct usb_device *hdev)
+ {
+ 	struct usb_hub *hub = hdev_to_hub(hdev);
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 10688ad73c6d..e8bc2e48913a 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -20,7 +20,6 @@ extern char *usb_cache_string(struct usb_device *udev, int index);
+ extern int usb_set_configuration(struct usb_device *dev, int configuration);
+ 
+ extern void usb_kick_khubd(struct usb_device *dev);
+-extern void usb_suspend_root_hub(struct usb_device *hdev);
+ extern void usb_resume_root_hub(struct usb_device *dev);
+ 
+ extern int  usb_hub_init(void);
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index f1b1ed086bde..0b899339cac8 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -135,9 +135,6 @@ static int ohci_bus_suspend (struct usb_hcd *hcd)
+ 	hcd->poll_rh = 0;
+ 
+ done:
+-	/* external suspend vs self autosuspend ... same effect */
+-	if (status == 0)
+-		usb_hcd_suspend_root_hub(hcd);
+ 	spin_unlock_irqrestore (&ohci->lock, flags);
+ 	return status;
+ }

commit 01d883d44a1ca8dc77486635d428cba63e7fdadf
+Author: Alan Stern 
+Date:   Wed Aug 30 15:47:18 2006 -0400
+
+    usbcore: non-hub-specific uses of autosuspend
+    
+    This patch (as741) makes the non-hub parts of usbcore actually use the
+    autosuspend facilities added by an earlier patch.
+    
+            Devices opened through usbfs are autoresumed and then
+            autosuspended upon close.
+    
+            Likewise for usb-skeleton.
+    
+            Devices are autoresumed for usb_set_configuration.
+    
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 43c08724a2d8..fd345ad810f8 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -558,10 +558,12 @@ static int usbdev_open(struct inode *inode, struct file *file)
+ 		dev = usbdev_lookup_minor(iminor(inode));
+ 	if (!dev)
+ 		dev = inode->i_private;
+-	if (!dev) {
+-		kfree(ps);
++	if (!dev)
+ 		goto out;
+-	}
++	ret = usb_autoresume_device(dev, 1);
++	if (ret)
++		goto out;
++
+ 	usb_get_dev(dev);
+ 	ret = 0;
+ 	ps->dev = dev;
+@@ -581,6 +583,8 @@ static int usbdev_open(struct inode *inode, struct file *file)
+ 	list_add_tail(&ps->list, &dev->filelist);
+ 	file->private_data = ps;
+  out:
++	if (ret)
++		kfree(ps);
+ 	mutex_unlock(&usbfs_mutex);
+ 	return ret;
+ }
+@@ -604,6 +608,7 @@ static int usbdev_release(struct inode *inode, struct file *file)
+ 			releaseintf(ps, ifnum);
+ 	}
+ 	destroy_all_async(ps);
++	usb_autosuspend_device(dev, 1);
+ 	usb_unlock_device(dev);
+ 	usb_put_dev(dev);
+ 	kfree(ps);
+diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
+index 5358e656477c..16332cc57946 100644
+--- a/drivers/usb/core/generic.c
++++ b/drivers/usb/core/generic.c
+@@ -172,14 +172,10 @@ static void generic_disconnect(struct usb_device *udev)
+ 
+ 	/* if this is only an unbind, not a physical disconnect, then
+ 	 * unconfigure the device */
+-	if (udev->state == USB_STATE_CONFIGURED)
++	if (udev->actconfig)
+ 		usb_set_configuration(udev, 0);
+ 
+ 	usb_remove_sysfs_dev_files(udev);
+-
+-	/* in case the call failed or the device was suspended */
+-	if (udev->state >= USB_STATE_CONFIGURED)
+-		usb_disable_device(udev, 0);
+ }
+ 
+ #ifdef	CONFIG_PM
+@@ -208,4 +204,5 @@ struct usb_device_driver usb_generic_driver = {
+ 	.suspend = generic_suspend,
+ 	.resume = generic_resume,
+ #endif
++	.supports_autosuspend = 1,
+ };
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 1580c81a0db7..28c6cf225780 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1366,9 +1366,6 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 	if (cp && configuration == 0)
+ 		dev_warn(&dev->dev, "config 0 descriptor??\n");
+ 
+-	if (dev->state == USB_STATE_SUSPENDED)
+-		return -EHOSTUNREACH;
+-
+ 	/* Allocate memory for new interfaces before doing anything else,
+ 	 * so that if we run out then nothing will have changed. */
+ 	n = nintf = 0;
+@@ -1403,6 +1400,11 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 					configuration, -i);
+ 	}
+ 
++	/* Wake up the device so we can send it the Set-Config request */
++	ret = usb_autoresume_device(dev, 1);
++	if (ret)
++		goto free_interfaces;
++
+ 	/* if it's already configured, clear out old state first.
+ 	 * getting rid of old interfaces means unbinding their drivers.
+ 	 */
+@@ -1422,6 +1424,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 	dev->actconfig = cp;
+ 	if (!cp) {
+ 		usb_set_device_state(dev, USB_STATE_ADDRESS);
++		usb_autosuspend_device(dev, 1);
+ 		goto free_interfaces;
+ 	}
+ 	usb_set_device_state(dev, USB_STATE_CONFIGURED);
+@@ -1490,6 +1493,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 		usb_create_sysfs_intf_files (intf);
+ 	}
+ 
++	usb_autosuspend_device(dev, 1);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
+index 9b542a6ba978..1b51d3187a95 100644
+--- a/drivers/usb/usb-skeleton.c
++++ b/drivers/usb/usb-skeleton.c
+@@ -90,6 +90,11 @@ static int skel_open(struct inode *inode, struct file *file)
+ 		goto exit;
+ 	}
+ 
++	/* prevent the device from being autosuspended */
++	retval = usb_autopm_get_interface(interface);
++	if (retval)
++		goto exit;
++
+ 	/* increment our usage count for the device */
+ 	kref_get(&dev->kref);
+ 
+@@ -108,6 +113,12 @@ static int skel_release(struct inode *inode, struct file *file)
+ 	if (dev == NULL)
+ 		return -ENODEV;
+ 
++	/* allow the device to be autosuspended */
++	mutex_lock(&dev->io_mutex);
++	if (dev->interface)
++		usb_autopm_put_interface(dev->interface);
++	mutex_unlock(&dev->io_mutex);
++
+ 	/* decrement the count on our device */
+ 	kref_put(&dev->kref, skel_delete);
+ 	return 0;

commit 645daaab0b6adc35c1838df2a82f9d729fdb1767
+Author: Alan Stern 
+Date:   Wed Aug 30 15:47:02 2006 -0400
+
+    usbcore: add autosuspend/autoresume infrastructure
+    
+    This patch (as739) adds the basic infrastructure for USB autosuspend
+    and autoresume.  The main features are:
+    
+            PM usage counters added to struct usb_device and struct
+            usb_interface, indicating whether it's okay to autosuspend
+            them or they are currently in use.
+    
+            Flag added to usb_device indicating whether the current
+            suspend/resume operation originated from outside or as an
+            autosuspend/autoresume.
+    
+            Flag added to usb_driver indicating whether the driver
+            supports autosuspend.  If not, no device bound to the driver
+            will be autosuspended.
+    
+            Mutex added to usb_device for protecting PM operations.
+            Unlike the device semaphore, the locking rule for the pm_mutex
+            is that you must acquire the locks going _up_ the device tree.
+    
+            New routines handling autosuspend/autoresume requests for
+            interfaces and devices.
+    
+            Suspend and resume requests are propagated up the device tree
+            (but not outside the USB subsystem).
+    
+            work_struct added to usb_device, for carrying out delayed
+            autosuspend requests.
+    
+            Autoresume added (and autosuspend prevented) during probe and
+            disconnect.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index a5d11461f5a9..2b2000ac05ab 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -157,12 +157,13 @@ static int usb_probe_device(struct device *dev)
+ 
+ 	udev = to_usb_device(dev);
+ 
+-	/* FIXME: resume a suspended device */
+-	if (udev->state == USB_STATE_SUSPENDED)
+-		return -EHOSTUNREACH;
+-
+ 	/* TODO: Add real matching code */
+ 
++	/* The device should always appear to be in use
++	 * unless the driver suports autosuspend.
++	 */
++	udev->pm_usage_cnt = !(udriver->supports_autosuspend);
++
+ 	error = udriver->probe(udev);
+ 	return error;
+ }
+@@ -182,6 +183,7 @@ static int usb_probe_interface(struct device *dev)
+ {
+ 	struct usb_driver *driver = to_usb_driver(dev->driver);
+ 	struct usb_interface *intf;
++	struct usb_device *udev;
+ 	const struct usb_device_id *id;
+ 	int error = -ENODEV;
+ 
+@@ -191,10 +193,7 @@ static int usb_probe_interface(struct device *dev)
+ 		return error;
+ 
+ 	intf = to_usb_interface(dev);
+-
+-	/* FIXME we'd much prefer to just resume it ... */
+-	if (interface_to_usbdev(intf)->state == USB_STATE_SUSPENDED)
+-		return -EHOSTUNREACH;
++	udev = interface_to_usbdev(intf);
+ 
+ 	id = usb_match_id(intf, driver->id_table);
+ 	if (!id)
+@@ -202,18 +201,31 @@ static int usb_probe_interface(struct device *dev)
+ 	if (id) {
+ 		dev_dbg(dev, "%s - got id\n", __FUNCTION__);
+ 
++		error = usb_autoresume_device(udev, 1);
++		if (error)
++			return error;
++
+ 		/* Interface "power state" doesn't correspond to any hardware
+ 		 * state whatsoever.  We use it to record when it's bound to
+ 		 * a driver that may start I/0:  it's not frozen/quiesced.
+ 		 */
+ 		mark_active(intf);
+ 		intf->condition = USB_INTERFACE_BINDING;
++
++		/* The interface should always appear to be in use
++		 * unless the driver suports autosuspend.
++		 */
++		intf->pm_usage_cnt = !(driver->supports_autosuspend);
++
+ 		error = driver->probe(intf, id);
+ 		if (error) {
+ 			mark_quiesced(intf);
++			intf->needs_remote_wakeup = 0;
+ 			intf->condition = USB_INTERFACE_UNBOUND;
+ 		} else
+ 			intf->condition = USB_INTERFACE_BOUND;
++
++		usb_autosuspend_device(udev, 1);
+ 	}
+ 
+ 	return error;
+@@ -224,9 +236,15 @@ static int usb_unbind_interface(struct device *dev)
+ {
+ 	struct usb_driver *driver = to_usb_driver(dev->driver);
+ 	struct usb_interface *intf = to_usb_interface(dev);
++	struct usb_device *udev;
++	int error;
+ 
+ 	intf->condition = USB_INTERFACE_UNBINDING;
+ 
++	/* Autoresume for set_interface call below */
++	udev = interface_to_usbdev(intf);
++	error = usb_autoresume_device(udev, 1);
++
+ 	/* release all urbs for this interface */
+ 	usb_disable_interface(interface_to_usbdev(intf), intf);
+ 
+@@ -237,8 +255,13 @@ static int usb_unbind_interface(struct device *dev)
+ 			intf->altsetting[0].desc.bInterfaceNumber,
+ 			0);
+ 	usb_set_intfdata(intf, NULL);
++
+ 	intf->condition = USB_INTERFACE_UNBOUND;
+ 	mark_quiesced(intf);
++	intf->needs_remote_wakeup = 0;
++
++	if (!error)
++		usb_autosuspend_device(udev, 1);
+ 
+ 	return 0;
+ }
+@@ -267,14 +290,19 @@ int usb_driver_claim_interface(struct usb_driver *driver,
+ 				struct usb_interface *iface, void* priv)
+ {
+ 	struct device *dev = &iface->dev;
++	struct usb_device *udev = interface_to_usbdev(iface);
+ 
+ 	if (dev->driver)
+ 		return -EBUSY;
+ 
+ 	dev->driver = &driver->drvwrap.driver;
+ 	usb_set_intfdata(iface, priv);
++
++	mutex_lock_nested(&udev->pm_mutex, udev->level);
+ 	iface->condition = USB_INTERFACE_BOUND;
+ 	mark_active(iface);
++	iface->pm_usage_cnt = !(driver->supports_autosuspend);
++	mutex_unlock(&udev->pm_mutex);
+ 
+ 	/* if interface was already added, bind now; else let
+ 	 * the future device_add() bind it, bypassing probe()
+@@ -304,6 +332,7 @@ void usb_driver_release_interface(struct usb_driver *driver,
+ 					struct usb_interface *iface)
+ {
+ 	struct device *dev = &iface->dev;
++	struct usb_device *udev = interface_to_usbdev(iface);
+ 
+ 	/* this should never happen, don't release something that's not ours */
+ 	if (!dev->driver || dev->driver != &driver->drvwrap.driver)
+@@ -321,8 +350,12 @@ void usb_driver_release_interface(struct usb_driver *driver,
+ 
+ 	dev->driver = NULL;
+ 	usb_set_intfdata(iface, NULL);
++
++	mutex_lock_nested(&udev->pm_mutex, udev->level);
+ 	iface->condition = USB_INTERFACE_UNBOUND;
+ 	mark_quiesced(iface);
++	iface->needs_remote_wakeup = 0;
++	mutex_unlock(&udev->pm_mutex);
+ }
+ EXPORT_SYMBOL(usb_driver_release_interface);
+ 
+@@ -751,7 +784,7 @@ EXPORT_SYMBOL_GPL_FUTURE(usb_deregister);
+ 
+ #ifdef CONFIG_PM
+ 
+-/* Caller has locked udev */
++/* Caller has locked udev->pm_mutex */
+ static int suspend_device(struct usb_device *udev, pm_message_t msg)
+ {
+ 	struct usb_device_driver	*udriver;
+@@ -763,6 +796,7 @@ static int suspend_device(struct usb_device *udev, pm_message_t msg)
+ 
+ 	/* For devices that don't have a driver, we do a standard suspend. */
+ 	if (udev->dev.driver == NULL) {
++		udev->do_remote_wakeup = 0;
+ 		status = usb_port_suspend(udev);
+ 		goto done;
+ 	}
+@@ -771,12 +805,13 @@ static int suspend_device(struct usb_device *udev, pm_message_t msg)
+ 	status = udriver->suspend(udev, msg);
+ 
+ done:
++	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+ 	if (status == 0)
+ 		udev->dev.power.power_state.event = msg.event;
+ 	return status;
+ }
+ 
+-/* Caller has locked udev */
++/* Caller has locked udev->pm_mutex */
+ static int resume_device(struct usb_device *udev)
+ {
+ 	struct usb_device_driver	*udriver;
+@@ -796,12 +831,13 @@ static int resume_device(struct usb_device *udev)
+ 	status = udriver->resume(udev);
+ 
+ done:
++	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+ 	if (status == 0)
+ 		udev->dev.power.power_state.event = PM_EVENT_ON;
+ 	return status;
+ }
+ 
+-/* Caller has locked intf's usb_device */
++/* Caller has locked intf's usb_device's pm_mutex */
+ static int suspend_interface(struct usb_interface *intf, pm_message_t msg)
+ {
+ 	struct usb_driver	*driver;
+@@ -812,31 +848,33 @@ static int suspend_interface(struct usb_interface *intf, pm_message_t msg)
+ 			!is_active(intf))
+ 		goto done;
+ 
+-	if (intf->dev.driver == NULL)		/* This can't happen */
++	if (intf->condition == USB_INTERFACE_UNBOUND)	/* This can't happen */
+ 		goto done;
+ 	driver = to_usb_driver(intf->dev.driver);
+ 
+ 	if (driver->suspend && driver->resume) {
+ 		status = driver->suspend(intf, msg);
+-		if (status)
++		if (status == 0)
++			mark_quiesced(intf);
++		else if (!interface_to_usbdev(intf)->auto_pm)
+ 			dev_err(&intf->dev, "%s error %d\n",
+ 					"suspend", status);
+-		else
+-			mark_quiesced(intf);
+ 	} else {
+ 		// FIXME else if there's no suspend method, disconnect...
++		// Not possible if auto_pm is set...
+ 		dev_warn(&intf->dev, "no suspend for driver %s?\n",
+ 				driver->name);
+ 		mark_quiesced(intf);
+ 	}
+ 
+ done:
++	// dev_dbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
+ 	if (status == 0)
+ 		intf->dev.power.power_state.event = msg.event;
+ 	return status;
+ }
+ 
+-/* Caller has locked intf's usb_device */
++/* Caller has locked intf's usb_device's pm_mutex */
+ static int resume_interface(struct usb_interface *intf)
+ {
+ 	struct usb_driver	*driver;
+@@ -846,8 +884,12 @@ static int resume_interface(struct usb_interface *intf)
+ 			is_active(intf))
+ 		goto done;
+ 
++	/* Don't let autoresume interfere with unbinding */
++	if (intf->condition == USB_INTERFACE_UNBINDING)
++		goto done;
++
+ 	/* Can't resume it if it doesn't have a driver. */
+-	if (intf->dev.driver == NULL) {
++	if (intf->condition == USB_INTERFACE_UNBOUND) {
+ 		status = -ENOTCONN;
+ 		goto done;
+ 	}
+@@ -867,18 +909,88 @@ static int resume_interface(struct usb_interface *intf)
+ 	}
+ 
+ done:
++	// dev_dbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
+ 	if (status == 0)
+ 		intf->dev.power.power_state.event = PM_EVENT_ON;
+ 	return status;
+ }
+ 
+-/* Caller has locked udev */
++/**
++ * usb_suspend_both - suspend a USB device and its interfaces
++ * @udev: the usb_device to suspend
++ * @msg: Power Management message describing this state transition
++ *
++ * This is the central routine for suspending USB devices.  It calls the
++ * suspend methods for all the interface drivers in @udev and then calls
++ * the suspend method for @udev itself.  If an error occurs at any stage,
++ * all the interfaces which were suspended are resumed so that they remain
++ * in the same state as the device.
++ *
++ * If an autosuspend is in progress (@udev->auto_pm is set), the routine
++ * checks first to make sure that neither the device itself or any of its
++ * active interfaces is in use (pm_usage_cnt is greater than 0).  If they
++ * are, the autosuspend fails.
++ *
++ * If the suspend succeeds, the routine recursively queues an autosuspend
++ * request for @udev's parent device, thereby propagating the change up
++ * the device tree.  If all of the parent's children are now suspended,
++ * the parent will autosuspend in turn.
++ *
++ * The suspend method calls are subject to mutual exclusion under control
++ * of @udev's pm_mutex.  Many of these calls are also under the protection
++ * of @udev's device lock (including all requests originating outside the
++ * USB subsystem), but autosuspend requests generated by a child device or
++ * interface driver may not be.  Usbcore will insure that the method calls
++ * do not arrive during bind, unbind, or reset operations.  However, drivers
++ * must be prepared to handle suspend calls arriving at unpredictable times.
++ * The only way to block such calls is to do an autoresume (preventing
++ * autosuspends) while holding @udev's device lock (preventing outside
++ * suspends).
++ *
++ * The caller must hold @udev->pm_mutex.
++ *
++ * This routine can run only in process context.
++ */
+ int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ {
+ 	int			status = 0;
+ 	int			i = 0;
+ 	struct usb_interface	*intf;
++	struct usb_device	*parent = udev->parent;
++
++	cancel_delayed_work(&udev->autosuspend);
++	if (udev->state == USB_STATE_NOTATTACHED)
++		return 0;
++	if (udev->state == USB_STATE_SUSPENDED)
++		return 0;
+ 
++	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
++
++	/* For autosuspend, fail fast if anything is in use.
++	 * Also fail if any interfaces require remote wakeup but it
++	 * isn't available. */
++	if (udev->auto_pm) {
++		if (udev->pm_usage_cnt > 0)
++			return -EBUSY;
++		if (udev->actconfig) {
++			for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
++				intf = udev->actconfig->interface[i];
++				if (!is_active(intf))
++					continue;
++				if (intf->pm_usage_cnt > 0)
++					return -EBUSY;
++				if (intf->needs_remote_wakeup &&
++						!udev->do_remote_wakeup) {
++					dev_dbg(&udev->dev,
++	"remote wakeup needed for autosuspend\n");
++					return -EOPNOTSUPP;
++				}
++			}
++			i = 0;
++		}
++	}
++
++	/* Suspend all the interfaces and then udev itself */
+ 	if (udev->actconfig) {
+ 		for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
+ 			intf = udev->actconfig->interface[i];
+@@ -896,40 +1008,282 @@ int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 			intf = udev->actconfig->interface[i];
+ 			resume_interface(intf);
+ 		}
+-	}
++
++	/* If the suspend succeeded, propagate it up the tree */
++	} else if (parent)
++		usb_autosuspend_device(parent, 0);
++
++	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+ 	return status;
+ }
+ 
+-/* Caller has locked udev */
++/**
++ * usb_resume_both - resume a USB device and its interfaces
++ * @udev: the usb_device to resume
++ *
++ * This is the central routine for resuming USB devices.  It calls the
++ * the resume method for @udev and then calls the resume methods for all
++ * the interface drivers in @udev.
++ *
++ * Before starting the resume, the routine calls itself recursively for
++ * the parent device of @udev, thereby propagating the change up the device
++ * tree and assuring that @udev will be able to resume.  If the parent is
++ * unable to resume successfully, the routine fails.
++ *
++ * The resume method calls are subject to mutual exclusion under control
++ * of @udev's pm_mutex.  Many of these calls are also under the protection
++ * of @udev's device lock (including all requests originating outside the
++ * USB subsystem), but autoresume requests generated by a child device or
++ * interface driver may not be.  Usbcore will insure that the method calls
++ * do not arrive during bind, unbind, or reset operations.  However, drivers
++ * must be prepared to handle resume calls arriving at unpredictable times.
++ * The only way to block such calls is to do an autoresume (preventing
++ * other autoresumes) while holding @udev's device lock (preventing outside
++ * resumes).
++ *
++ * The caller must hold @udev->pm_mutex.
++ *
++ * This routine can run only in process context.
++ */
+ int usb_resume_both(struct usb_device *udev)
+ {
+-	int			status;
++	int			status = 0;
+ 	int			i;
+ 	struct usb_interface	*intf;
++	struct usb_device	*parent = udev->parent;
++
++	cancel_delayed_work(&udev->autosuspend);
++	if (udev->state == USB_STATE_NOTATTACHED)
++		return -ENODEV;
+ 
+-	/* Can't resume if the parent is suspended */
+-	if (udev->parent && udev->parent->state == USB_STATE_SUSPENDED) {
+-		dev_warn(&udev->dev, "can't resume; parent is suspended\n");
+-		return -EHOSTUNREACH;
++	/* Propagate the resume up the tree, if necessary */
++	if (udev->state == USB_STATE_SUSPENDED) {
++		if (parent) {
++			mutex_lock_nested(&parent->pm_mutex, parent->level);
++			parent->auto_pm = 1;
++			status = usb_resume_both(parent);
++		} else {
++
++			/* We can't progagate beyond the USB subsystem,
++			 * so if a root hub's controller is suspended
++			 * then we're stuck. */
++			if (udev->dev.parent->power.power_state.event !=
++					PM_EVENT_ON)
++				status = -EHOSTUNREACH;
++		}
++		if (status == 0 && udev->state == USB_STATE_SUSPENDED)
++			status = resume_device(udev);
++		if (parent)
++			mutex_unlock(&parent->pm_mutex);
+ 	}
+ 
+-	status = resume_device(udev);
++	/* Now the parent won't suspend until we are finished */
++
+ 	if (status == 0 && udev->actconfig) {
+ 		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+ 			intf = udev->actconfig->interface[i];
+ 			resume_interface(intf);
+ 		}
+ 	}
++
++	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
++	return status;
++}
++
++#ifdef CONFIG_USB_SUSPEND
++
++/**
++ * usb_autosuspend_device - delayed autosuspend of a USB device and its interfaces
++ * @udev - the usb_device to autosuspend
++ * @dec_usage_cnt - flag to decrement @udev's PM-usage counter
++ *
++ * This routine should be called when a core subsystem is finished using
++ * @udev and wants to allow it to autosuspend.  Examples would be when
++ * @udev's device file in usbfs is closed or after a configuration change.
++ *
++ * @dec_usage_cnt should be 1 if the subsystem previously incremented
++ * @udev's usage counter (such as by passing 1 to usb_autoresume_device);
++ * otherwise it should be 0.
++ *
++ * If the usage counter for @udev or any of its active interfaces is greater
++ * than 0, the autosuspend request will not be queued.  (If an interface
++ * driver does not support autosuspend then its usage counter is permanently
++ * positive.)  Likewise, if an interface driver requires remote-wakeup
++ * capability during autosuspend but remote wakeup is disabled, the
++ * autosuspend will fail.
++ *
++ * Often the caller will hold @udev's device lock, but this is not
++ * necessary.
++ *
++ * This routine can run only in process context.
++ */
++void usb_autosuspend_device(struct usb_device *udev, int dec_usage_cnt)
++{
++	mutex_lock_nested(&udev->pm_mutex, udev->level);
++	udev->pm_usage_cnt -= dec_usage_cnt;
++	if (udev->pm_usage_cnt <= 0)
++		schedule_delayed_work(&udev->autosuspend,
++				USB_AUTOSUSPEND_DELAY);
++	mutex_unlock(&udev->pm_mutex);
++	// dev_dbg(&udev->dev, "%s: cnt %d\n",
++	//		__FUNCTION__, udev->pm_usage_cnt);
++}
++
++/**
++ * usb_autoresume_device - immediately autoresume a USB device and its interfaces
++ * @udev - the usb_device to autoresume
++ * @inc_usage_cnt - flag to increment @udev's PM-usage counter
++ *
++ * This routine should be called when a core subsystem wants to use @udev
++ * and needs to guarantee that it is not suspended.  In addition, the
++ * caller can prevent @udev from being autosuspended subsequently.  (Note
++ * that this will not prevent suspend events originating in the PM core.)
++ * Examples would be when @udev's device file in usbfs is opened (autosuspend
++ * should be prevented until the file is closed) or when a remote-wakeup
++ * request is received (later autosuspends should not be prevented).
++ *
++ * @inc_usage_cnt should be 1 to increment @udev's usage counter and prevent
++ * autosuspends.  This prevention will persist until the usage counter is
++ * decremented again (such as by passing 1 to usb_autosuspend_device).
++ * Otherwise @inc_usage_cnt should be 0 to leave the usage counter unchanged.
++ * Regardless, if the autoresume fails then the usage counter is not
++ * incremented.
++ *
++ * Often the caller will hold @udev's device lock, but this is not
++ * necessary (and attempting it might cause deadlock).
++ *
++ * This routine can run only in process context.
++ */
++int usb_autoresume_device(struct usb_device *udev, int inc_usage_cnt)
++{
++	int	status;
++
++	mutex_lock_nested(&udev->pm_mutex, udev->level);
++	udev->pm_usage_cnt += inc_usage_cnt;
++	udev->auto_pm = 1;
++	status = usb_resume_both(udev);
++	if (status != 0)
++		udev->pm_usage_cnt -= inc_usage_cnt;
++	mutex_unlock(&udev->pm_mutex);
++	// dev_dbg(&udev->dev, "%s: status %d cnt %d\n",
++	//		__FUNCTION__, status, udev->pm_usage_cnt);
++	return status;
++}
++
++/**
++ * usb_autopm_put_interface - decrement a USB interface's PM-usage counter
++ * @intf - the usb_interface whose counter should be decremented
++ *
++ * This routine should be called by an interface driver when it is
++ * finished using @intf and wants to allow it to autosuspend.  A typical
++ * example would be a character-device driver when its device file is
++ * closed.
++ *
++ * The routine decrements @intf's usage counter.  When the counter reaches
++ * 0, a delayed autosuspend request for @intf's device is queued.  When
++ * the delay expires, if @intf->pm_usage_cnt is still <= 0 along with all
++ * the other usage counters for the sibling interfaces and @intf's
++ * usb_device, the device and all its interfaces will be autosuspended.
++ *
++ * Note that @intf->pm_usage_cnt is owned by the interface driver.  The
++ * core will not change its value other than the increment and decrement
++ * in usb_autopm_get_interface and usb_autopm_put_interface.  The driver
++ * may use this simple counter-oriented discipline or may set the value
++ * any way it likes.
++ *
++ * If the driver has set @intf->needs_remote_wakeup then autosuspend will
++ * take place only if the device's remote-wakeup facility is enabled.
++ *
++ * Suspend method calls queued by this routine can arrive at any time
++ * while @intf is resumed and its usage counter is equal to 0.  They are
++ * not protected by the usb_device's lock but only by its pm_mutex.
++ * Drivers must provide their own synchronization.
++ *
++ * This routine can run only in process context.
++ */
++void usb_autopm_put_interface(struct usb_interface *intf)
++{
++	struct usb_device	*udev = interface_to_usbdev(intf);
++
++	mutex_lock_nested(&udev->pm_mutex, udev->level);
++	if (intf->condition != USB_INTERFACE_UNBOUND) {
++		if (--intf->pm_usage_cnt <= 0)
++			schedule_delayed_work(&udev->autosuspend,
++					USB_AUTOSUSPEND_DELAY);
++	}
++	mutex_unlock(&udev->pm_mutex);
++	// dev_dbg(&intf->dev, "%s: cnt %d\n",
++	//		__FUNCTION__, intf->pm_usage_cnt);
++}
++EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
++
++/**
++ * usb_autopm_get_interface - increment a USB interface's PM-usage counter
++ * @intf - the usb_interface whose counter should be incremented
++ *
++ * This routine should be called by an interface driver when it wants to
++ * use @intf and needs to guarantee that it is not suspended.  In addition,
++ * the routine prevents @intf from being autosuspended subsequently.  (Note
++ * that this will not prevent suspend events originating in the PM core.)
++ * This prevention will persist until usb_autopm_put_interface() is called
++ * or @intf is unbound.  A typical example would be a character-device
++ * driver when its device file is opened.
++ *
++ * The routine increments @intf's usage counter.  So long as the counter
++ * is greater than 0, autosuspend will not be allowed for @intf or its
++ * usb_device.  When the driver is finished using @intf it should call
++ * usb_autopm_put_interface() to decrement the usage counter and queue
++ * a delayed autosuspend request (if the counter is <= 0).
++ *
++ * Note that @intf->pm_usage_cnt is owned by the interface driver.  The
++ * core will not change its value other than the increment and decrement
++ * in usb_autopm_get_interface and usb_autopm_put_interface.  The driver
++ * may use this simple counter-oriented discipline or may set the value
++ * any way it likes.
++ *
++ * Resume method calls generated by this routine can arrive at any time
++ * while @intf is suspended.  They are not protected by the usb_device's
++ * lock but only by its pm_mutex.  Drivers must provide their own
++ * synchronization.
++ *
++ * This routine can run only in process context.
++ */
++int usb_autopm_get_interface(struct usb_interface *intf)
++{
++	struct usb_device	*udev = interface_to_usbdev(intf);
++	int			status;
++
++	mutex_lock_nested(&udev->pm_mutex, udev->level);
++	if (intf->condition == USB_INTERFACE_UNBOUND)
++		status = -ENODEV;
++	else {
++		++intf->pm_usage_cnt;
++		udev->auto_pm = 1;
++		status = usb_resume_both(udev);
++		if (status != 0)
++			--intf->pm_usage_cnt;
++	}
++	mutex_unlock(&udev->pm_mutex);
++	// dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
++	//		__FUNCTION__, status, intf->pm_usage_cnt);
+ 	return status;
+ }
++EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
++
++#endif /* CONFIG_USB_SUSPEND */
+ 
+ static int usb_suspend(struct device *dev, pm_message_t message)
+ {
+ 	int	status;
+ 
+-	if (is_usb_device(dev))
+-		status = usb_suspend_both(to_usb_device(dev), message);
+-	else
++	if (is_usb_device(dev)) {
++		struct usb_device *udev = to_usb_device(dev);
++
++		mutex_lock_nested(&udev->pm_mutex, udev->level);
++		udev->auto_pm = 0;
++		status = usb_suspend_both(udev, message);
++		mutex_unlock(&udev->pm_mutex);
++	} else
+ 		status = 0;
+ 	return status;
+ }
+@@ -939,7 +1293,12 @@ static int usb_resume(struct device *dev)
+ 	int	status;
+ 
+ 	if (is_usb_device(dev)) {
+-		status = usb_resume_both(to_usb_device(dev));
++		struct usb_device *udev = to_usb_device(dev);
++
++		mutex_lock_nested(&udev->pm_mutex, udev->level);
++		udev->auto_pm = 0;
++		status = usb_resume_both(udev);
++		mutex_unlock(&udev->pm_mutex);
+ 
+ 		/* Rebind drivers that had no suspend method? */
+ 	} else
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 78e910b2046c..dee812bc6c43 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1017,19 +1017,22 @@ void usb_set_device_state(struct usb_device *udev,
+ 	if (udev->state == USB_STATE_NOTATTACHED)
+ 		;	/* do nothing */
+ 	else if (new_state != USB_STATE_NOTATTACHED) {
+-		udev->state = new_state;
+ 
+ 		/* root hub wakeup capabilities are managed out-of-band
+ 		 * and may involve silicon errata ... ignore them here.
+ 		 */
+ 		if (udev->parent) {
+-			if (new_state == USB_STATE_CONFIGURED)
++			if (udev->state == USB_STATE_SUSPENDED
++					|| new_state == USB_STATE_SUSPENDED)
++				;	/* No change to wakeup settings */
++			else if (new_state == USB_STATE_CONFIGURED)
+ 				device_init_wakeup(&udev->dev,
+ 					(udev->actconfig->desc.bmAttributes
+ 					 & USB_CONFIG_ATT_WAKEUP));
+-			else if (new_state != USB_STATE_SUSPENDED)
++			else
+ 				device_init_wakeup(&udev->dev, 0);
+ 		}
++		udev->state = new_state;
+ 	} else
+ 		recursively_mark_NOTATTACHED(udev);
+ 	spin_unlock_irqrestore(&device_state_lock, flags);
+@@ -1507,7 +1510,7 @@ static int hub_port_suspend(struct usb_hub *hub, int port1,
+ 	 * NOTE:  OTG devices may issue remote wakeup (or SRP) even when
+ 	 * we don't explicitly enable it here.
+ 	 */
+-	if (device_may_wakeup(&udev->dev)) {
++	if (udev->do_remote_wakeup) {
+ 		status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ 				USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
+ 				USB_DEVICE_REMOTE_WAKEUP, 0,
+@@ -1533,7 +1536,8 @@ static int hub_port_suspend(struct usb_hub *hub, int port1,
+ 				USB_CTRL_SET_TIMEOUT);
+ 	} else {
+ 		/* device has up to 10 msec to fully suspend */
+-		dev_dbg(&udev->dev, "usb suspend\n");
++		dev_dbg(&udev->dev, "usb %ssuspend\n",
++				udev->auto_pm ? "auto-" : "");
+ 		usb_set_device_state(udev, USB_STATE_SUSPENDED);
+ 		msleep(10);
+ 	}
+@@ -1573,7 +1577,8 @@ static int __usb_port_suspend (struct usb_device *udev, int port1)
+ 		status = hub_port_suspend(hdev_to_hub(udev->parent), port1,
+ 				udev);
+ 	else {
+-		dev_dbg(&udev->dev, "usb suspend\n");
++		dev_dbg(&udev->dev, "usb %ssuspend\n",
++				udev->auto_pm ? "auto-" : "");
+ 		usb_set_device_state(udev, USB_STATE_SUSPENDED);
+ 	}
+ 	return status;
+@@ -1687,7 +1692,8 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+ 
+ 		/* drive resume for at least 20 msec */
+ 		if (udev)
+-			dev_dbg(&udev->dev, "RESUME\n");
++			dev_dbg(&udev->dev, "usb %sresume\n",
++					udev->auto_pm ? "auto-" : "");
+ 		msleep(25);
+ 
+ #define LIVE_FLAGS	( USB_PORT_STAT_POWER \
+@@ -1754,8 +1760,11 @@ int usb_port_resume(struct usb_device *udev)
+ 		// NOTE this fails if parent is also suspended...
+ 		status = hub_port_resume(hdev_to_hub(udev->parent),
+ 				udev->portnum, udev);
+-	} else
++	} else {
++		dev_dbg(&udev->dev, "usb %sresume\n",
++				udev->auto_pm ? "auto-" : "");
+ 		status = finish_port_resume(udev);
++	}
+ 	if (status < 0)
+ 		dev_dbg(&udev->dev, "can't resume, status %d\n", status);
+ 	return status;
+@@ -1765,19 +1774,23 @@ static int remote_wakeup(struct usb_device *udev)
+ {
+ 	int	status = 0;
+ 
+-	/* don't repeat RESUME sequence if this device
+-	 * was already woken up by some other task
+-	 */
++	/* All this just to avoid sending a port-resume message
++	 * to the parent hub! */
++
+ 	usb_lock_device(udev);
++	mutex_lock_nested(&udev->pm_mutex, udev->level);
+ 	if (udev->state == USB_STATE_SUSPENDED) {
+-		dev_dbg(&udev->dev, "RESUME (wakeup)\n");
++		dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-");
+ 		/* TRSMRCY = 10 msec */
+ 		msleep(10);
+ 		status = finish_port_resume(udev);
++		if (status == 0)
++			udev->dev.power.power_state.event = PM_EVENT_ON;
+ 	}
++	mutex_unlock(&udev->pm_mutex);
+ 
+ 	if (status == 0)
+-		usb_resume_both(udev);
++		usb_autoresume_device(udev, 0);
+ 	usb_unlock_device(udev);
+ 	return status;
+ }
+@@ -1834,7 +1847,9 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+ 					== PM_EVENT_ON
+ #endif
+ 				) {
+-			dev_dbg(&intf->dev, "port %d nyet suspended\n", port1);
++			if (!hdev->auto_pm)
++				dev_dbg(&intf->dev, "port %d nyet suspended\n",
++						port1);
+ 			return -EBUSY;
+ 		}
+ 	}
+@@ -2587,7 +2602,7 @@ static void hub_events(void)
+ 		 * stub "device" node was never suspended.
+ 		 */
+ 		if (i)
+-			usb_resume_both(hdev);
++			usb_autoresume_device(hdev, 0);
+ 
+ 		/* If this is an inactive or suspended hub, do nothing */
+ 		if (hub->quiescing)
+@@ -2993,6 +3008,9 @@ int usb_reset_composite_device(struct usb_device *udev,
+ 		return -EINVAL;
+ 	}
+ 
++	/* Prevent autosuspend during the reset */
++	usb_autoresume_device(udev, 1);
++
+ 	if (iface && iface->condition != USB_INTERFACE_BINDING)
+ 		iface = NULL;
+ 
+@@ -3034,6 +3052,7 @@ int usb_reset_composite_device(struct usb_device *udev,
+ 		}
+ 	}
+ 
++	usb_autosuspend_device(udev, 1);
+ 	return ret;
+ }
+ EXPORT_SYMBOL(usb_reset_composite_device);
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index b0c0a993338f..6b029cdb8671 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -168,6 +168,10 @@ static void usb_release_dev(struct device *dev)
+ 
+ 	udev = to_usb_device(dev);
+ 
++#ifdef	CONFIG_PM
++	cancel_delayed_work(&udev->autosuspend);
++	flush_scheduled_work();
++#endif
+ 	usb_destroy_configuration(udev);
+ 	usb_put_hcd(bus_to_hcd(udev->bus));
+ 	kfree(udev->product);
+@@ -176,6 +180,21 @@ static void usb_release_dev(struct device *dev)
+ 	kfree(udev);
+ }
+ 
++#ifdef	CONFIG_PM
++
++/* usb_autosuspend_work - callback routine to autosuspend a USB device */
++static void usb_autosuspend_work(void *_udev)
++{
++	struct usb_device	*udev = _udev;
++
++	mutex_lock_nested(&udev->pm_mutex, udev->level);
++	udev->auto_pm = 1;
++	usb_suspend_both(udev, PMSG_SUSPEND);
++	mutex_unlock(&udev->pm_mutex);
++}
++
++#endif
++
+ /**
+  * usb_alloc_dev - usb device constructor (usbcore-internal)
+  * @parent: hub to which device is connected; null to allocate a root hub
+@@ -251,6 +270,10 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
+ 	dev->parent = parent;
+ 	INIT_LIST_HEAD(&dev->filelist);
+ 
++#ifdef	CONFIG_PM
++	mutex_init(&dev->pm_mutex);
++	INIT_WORK(&dev->autosuspend, usb_autosuspend_work, dev);
++#endif
+ 	return dev;
+ }
+ 
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 5162cb370215..10688ad73c6d 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -49,6 +49,20 @@ static inline int usb_resume_both(struct usb_device *udev)
+ 
+ #endif
+ 
++#ifdef CONFIG_USB_SUSPEND
++
++#define USB_AUTOSUSPEND_DELAY	(HZ*2)
++
++extern void usb_autosuspend_device(struct usb_device *udev, int dec_busy_cnt);
++extern int usb_autoresume_device(struct usb_device *udev, int inc_busy_cnt);
++
++#else
++
++#define usb_autosuspend_device(udev, dec_busy_cnt)	do {} while (0)
++#define usb_autoresume_device(udev, inc_busy_cnt)	0
++
++#endif
++
+ extern struct bus_type usb_bus_type;
+ extern struct usb_device_driver usb_generic_driver;
+ 
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index df5c93eb3ce9..0da15b0b02be 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -19,6 +19,7 @@
+ #include 		/* for struct file_operations */
+ #include 	/* for struct completion */
+ #include 	/* for current && schedule_timeout */
++#include 	/* for struct mutex */
+ 
+ struct usb_device;
+ struct usb_driver;
+@@ -103,8 +104,12 @@ enum usb_interface_condition {
+  * @condition: binding state of the interface: not bound, binding
+  *	(in probe()), bound to a driver, or unbinding (in disconnect())
+  * @is_active: flag set when the interface is bound and not suspended.
++ * @needs_remote_wakeup: flag set when the driver requires remote-wakeup
++ *	capability during autosuspend.
+  * @dev: driver model's view of this device
+  * @class_dev: driver model's class view of this device.
++ * @pm_usage_cnt: PM usage counter for this interface; autosuspend is not
++ *	allowed unless the counter is 0.
+  *
+  * USB device drivers attach to interfaces on a physical device.  Each
+  * interface encapsulates a single high level function, such as feeding
+@@ -144,9 +149,11 @@ struct usb_interface {
+ 					 * bound to */
+ 	enum usb_interface_condition condition;		/* state of binding */
+ 	unsigned is_active:1;		/* the interface is not suspended */
++	unsigned needs_remote_wakeup:1;	/* driver requires remote wakeup */
+ 
+ 	struct device dev;		/* interface specific device info */
+ 	struct class_device *class_dev;
++	int pm_usage_cnt;		/* usage counter for autosuspend */
+ };
+ #define	to_usb_interface(d) container_of(d, struct usb_interface, dev)
+ #define	interface_to_usbdev(intf) \
+@@ -372,6 +379,15 @@ struct usb_device {
+ 
+ 	int maxchild;			/* Number of ports if hub */
+ 	struct usb_device *children[USB_MAXCHILDREN];
++
++#ifdef CONFIG_PM
++	struct work_struct autosuspend;	/* for delayed autosuspends */
++	struct mutex pm_mutex;		/* protects PM operations */
++	int pm_usage_cnt;		/* usage counter for autosuspend */
++
++	unsigned auto_pm:1;		/* autosuspend/resume in progress */
++	unsigned do_remote_wakeup:1;	/* remote wakeup should be enabled */
++#endif
+ };
+ #define	to_usb_device(d) container_of(d, struct usb_device, dev)
+ 
+@@ -392,6 +408,17 @@ extern int usb_reset_composite_device(struct usb_device *dev,
+ 
+ extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id);
+ 
++/* USB autosuspend and autoresume */
++#ifdef CONFIG_USB_SUSPEND
++extern int usb_autopm_get_interface(struct usb_interface *intf);
++extern void usb_autopm_put_interface(struct usb_interface *intf);
++
++#else
++#define usb_autopm_get_interface(intf)		0
++#define usb_autopm_put_interface(intf)		do {} while (0)
++#endif
++
++
+ /*-------------------------------------------------------------------------*/
+ 
+ /* for drivers using iso endpoints */
+@@ -593,6 +620,8 @@ struct usbdrv_wrap {
+  * @drvwrap: Driver-model core structure wrapper.
+  * @no_dynamic_id: if set to 1, the USB core will not allow dynamic ids to be
+  *	added to this driver by preventing the sysfs file from being created.
++ * @supports_autosuspend: if set to 0, the USB core will not allow autosuspend
++ *	for interfaces bound to this driver.
+  *
+  * USB interface drivers must provide a name, probe() and disconnect()
+  * methods, and an id_table.  Other driver fields are optional.
+@@ -631,6 +660,7 @@ struct usb_driver {
+ 	struct usb_dynids dynids;
+ 	struct usbdrv_wrap drvwrap;
+ 	unsigned int no_dynamic_id:1;
++	unsigned int supports_autosuspend:1;
+ };
+ #define	to_usb_driver(d) container_of(d, struct usb_driver, drvwrap.driver)
+ 
+@@ -648,6 +678,8 @@ struct usb_driver {
+  * @suspend: Called when the device is going to be suspended by the system.
+  * @resume: Called when the device is being resumed by the system.
+  * @drvwrap: Driver-model core structure wrapper.
++ * @supports_autosuspend: if set to 0, the USB core will not allow autosuspend
++ *	for devices bound to this driver.
+  *
+  * USB drivers must provide all the fields listed above except drvwrap.
+  */
+@@ -660,6 +692,7 @@ struct usb_device_driver {
+ 	int (*suspend) (struct usb_device *udev, pm_message_t message);
+ 	int (*resume) (struct usb_device *udev);
+ 	struct usbdrv_wrap drvwrap;
++	unsigned int supports_autosuspend:1;
+ };
+ #define	to_usb_device_driver(d) container_of(d, struct usb_device_driver, \
+ 		drvwrap.driver)

commit b6956ffa595db97656d5901ca8fec77ef272d41a
+Author: Alan Stern 
+Date:   Wed Aug 30 15:46:48 2006 -0400
+
+    usbcore: store each usb_device's level in the tree
+    
+    This patch (as778) adds a field to struct usb_device to store the
+    device's level in the USB tree.  In itself this number isn't really
+    important.  But the overhead is very low, and in a later patch it will
+    be used for preventing bogus warnings from the lockdep checker.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index f5adce049b35..78e910b2046c 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2414,6 +2414,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 		usb_set_device_state(udev, USB_STATE_POWERED);
+ 		udev->speed = USB_SPEED_UNKNOWN;
+  		udev->bus_mA = hub->mA_per_port;
++		udev->level = hdev->level + 1;
+ 
+ 		/* set the address */
+ 		choose_address(udev);
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index c66303285a45..df5c93eb3ce9 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -348,6 +348,7 @@ struct usb_device {
+ 
+ 	unsigned short bus_mA;		/* Current available from the bus */
+ 	u8 portnum;			/* Parent port number (origin 1) */
++	u8 level;			/* Number of USB hub ancestors */
+ 
+ 	int have_langid;		/* whether string_langid is valid */
+ 	int string_langid;		/* language ID for strings */

commit 4d6cd48380c4d361cc8ec34359df22377d85d202
+Author: Alan Stern 
+Date:   Wed Aug 30 11:35:21 2006 -0400
+
+    usbmon: don't call mon_dmapeek if DMA isn't being used
+    
+    This patch (as755b) fixes a bug in usbmon.  Rather than assuming all
+    USB host controllers use DMA, the code will check the usb_bus data
+    structure.  If DMA isn't used, we don't want to try peeking into a
+    non-existent DMA buffer!
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c
+index e0ed36cdfd8b..394bbf2f68d4 100644
+--- a/drivers/usb/mon/mon_main.c
++++ b/drivers/usb/mon/mon_main.c
+@@ -301,6 +301,7 @@ static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus)
+ 	 */
+ 	mbus->u_bus = ubus;
+ 	ubus->mon_bus = mbus;
++	mbus->uses_dma = ubus->uses_dma;
+ 
+ 	rc = snprintf(name, NAMESZ, "%dt", ubus->busnum);
+ 	if (rc <= 0 || rc >= NAMESZ)
+diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
+index 775e374a960c..7a2346c53284 100644
+--- a/drivers/usb/mon/mon_text.c
++++ b/drivers/usb/mon/mon_text.c
+@@ -75,13 +75,13 @@ static void mon_text_ctor(void *, kmem_cache_t *, unsigned long);
+  */
+ 
+ static inline char mon_text_get_setup(struct mon_event_text *ep,
+-    struct urb *urb, char ev_type)
++    struct urb *urb, char ev_type, struct mon_bus *mbus)
+ {
+ 
+ 	if (!usb_pipecontrol(urb->pipe) || ev_type != 'S')
+ 		return '-';
+ 
+-	if (urb->transfer_flags & URB_NO_SETUP_DMA_MAP)
++	if (mbus->uses_dma && (urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
+ 		return mon_dmapeek(ep->setup, urb->setup_dma, SETUP_MAX);
+ 	if (urb->setup_packet == NULL)
+ 		return 'Z';	/* '0' would be not as pretty. */
+@@ -91,7 +91,7 @@ static inline char mon_text_get_setup(struct mon_event_text *ep,
+ }
+ 
+ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
+-    int len, char ev_type)
++    int len, char ev_type, struct mon_bus *mbus)
+ {
+ 	int pipe = urb->pipe;
+ 
+@@ -117,7 +117,7 @@ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
+ 	 * contain non-NULL garbage in case the upper level promised to
+ 	 * set DMA for the HCD.
+ 	 */
+-	if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)
++	if (mbus->uses_dma && (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
+ 		return mon_dmapeek(ep->data, urb->transfer_dma, len);
+ 
+ 	if (urb->transfer_buffer == NULL)
+@@ -161,8 +161,9 @@ static void mon_text_event(struct mon_reader_text *rp, struct urb *urb,
+ 	/* Collecting status makes debugging sense for submits, too */
+ 	ep->status = urb->status;
+ 
+-	ep->setup_flag = mon_text_get_setup(ep, urb, ev_type);
+-	ep->data_flag = mon_text_get_data(ep, urb, ep->length, ev_type);
++	ep->setup_flag = mon_text_get_setup(ep, urb, ev_type, rp->r.m_bus);
++	ep->data_flag = mon_text_get_data(ep, urb, ep->length, ev_type,
++			rp->r.m_bus);
+ 
+ 	rp->nevents++;
+ 	list_add_tail(&ep->e_link, &rp->e_list);
+diff --git a/drivers/usb/mon/usb_mon.h b/drivers/usb/mon/usb_mon.h
+index 50efc8ee7c21..ab9d02d5df77 100644
+--- a/drivers/usb/mon/usb_mon.h
++++ b/drivers/usb/mon/usb_mon.h
+@@ -20,6 +20,7 @@ struct mon_bus {
+ 	struct dentry *dent_s;		/* Debugging file */
+ 	struct dentry *dent_t;		/* Text interface file */
+ 	struct usb_bus *u_bus;
++	int uses_dma;
+ 
+ 	/* Ref */
+ 	int nreaders;			/* Under mon_lock AND mbus->lock */

commit 1720058343fa43a1a25bfad9e62ea06e7e9743b6
+Author: Alan Stern 
+Date:   Wed Aug 30 11:32:52 2006 -0400
+
+    usbcore: trim down usb_bus structure
+    
+    As part of the ongoing program to flatten out the HCD bus-glue layer,
+    this patch (as771b) eliminates the hcpriv, release, and kref fields
+    from struct usb_bus.  hcpriv and release were not being used for
+    anything worthwhile, and kref has been moved into the enclosing
+    usb_hcd structure.
+    
+    Along with those changes, the patch gets rid of usb_bus_get and
+    usb_bus_put, replacing them with usb_get_hcd and usb_put_hcd.
+    
+    The one interesting aspect is that the dev_set_drvdata call was
+    removed from usb_put_hcd, where it clearly doesn't belong.  This means
+    the driver private data won't get reset to NULL.  It shouldn't cause
+    any problems, since the private data is undefined when no driver is
+    bound.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
+index f4f4ef0f377a..840442a25b61 100644
+--- a/drivers/usb/core/buffer.c
++++ b/drivers/usb/core/buffer.c
+@@ -104,7 +104,7 @@ void *hcd_buffer_alloc (
+ 	dma_addr_t		*dma
+ )
+ {
+-	struct usb_hcd		*hcd = bus->hcpriv;
++	struct usb_hcd		*hcd = bus_to_hcd(bus);
+ 	int 			i;
+ 
+ 	/* some USB hosts just use PIO */
+@@ -127,7 +127,7 @@ void hcd_buffer_free (
+ 	dma_addr_t		dma
+ )
+ {
+-	struct usb_hcd		*hcd = bus->hcpriv;
++	struct usb_hcd		*hcd = bus_to_hcd(bus);
+ 	int 			i;
+ 
+ 	if (!addr)
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 0cc14206920a..9dfc812de034 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -664,31 +664,6 @@ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-/* exported only within usbcore */
+-struct usb_bus *usb_bus_get(struct usb_bus *bus)
+-{
+-	if (bus)
+-		kref_get(&bus->kref);
+-	return bus;
+-}
+-
+-static void usb_host_release(struct kref *kref)
+-{
+-	struct usb_bus *bus = container_of(kref, struct usb_bus, kref);
+-
+-	if (bus->release)
+-		bus->release(bus);
+-}
+-
+-/* exported only within usbcore */
+-void usb_bus_put(struct usb_bus *bus)
+-{
+-	if (bus)
+-		kref_put(&bus->kref, usb_host_release);
+-}
+-
+-/*-------------------------------------------------------------------------*/
+-
+ static struct class *usb_host_class;
+ 
+ int usb_host_init(void)
+@@ -720,15 +695,12 @@ static void usb_bus_init (struct usb_bus *bus)
+ 	bus->devnum_next = 1;
+ 
+ 	bus->root_hub = NULL;
+-	bus->hcpriv = NULL;
+ 	bus->busnum = -1;
+ 	bus->bandwidth_allocated = 0;
+ 	bus->bandwidth_int_reqs  = 0;
+ 	bus->bandwidth_isoc_reqs = 0;
+ 
+ 	INIT_LIST_HEAD (&bus->bus_list);
+-
+-	kref_init(&bus->kref);
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -1081,7 +1053,7 @@ static void urb_unlink (struct urb *urb)
+ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+ {
+ 	int			status;
+-	struct usb_hcd		*hcd = urb->dev->bus->hcpriv;
++	struct usb_hcd		*hcd = bus_to_hcd(urb->dev->bus);
+ 	struct usb_host_endpoint *ep;
+ 	unsigned long		flags;
+ 
+@@ -1189,7 +1161,8 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+ /* called in any context */
+ int usb_hcd_get_frame_number (struct usb_device *udev)
+ {
+-	struct usb_hcd	*hcd = (struct usb_hcd *)udev->bus->hcpriv;
++	struct usb_hcd	*hcd = bus_to_hcd(udev->bus);
++
+ 	if (!HC_IS_RUNNING (hcd->state))
+ 		return -ESHUTDOWN;
+ 	return hcd->driver->get_frame_number (hcd);
+@@ -1262,7 +1235,7 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
+ 	spin_lock (&hcd_data_lock);
+ 
+ 	sys = &urb->dev->dev;
+-	hcd = urb->dev->bus->hcpriv;
++	hcd = bus_to_hcd(urb->dev->bus);
+ 	if (hcd == NULL) {
+ 		retval = -ENODEV;
+ 		goto done;
+@@ -1333,7 +1306,7 @@ void usb_hcd_endpoint_disable (struct usb_device *udev,
+ 	struct usb_hcd		*hcd;
+ 	struct urb		*urb;
+ 
+-	hcd = udev->bus->hcpriv;
++	hcd = bus_to_hcd(udev->bus);
+ 
+ 	WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT &&
+ 			udev->state != USB_STATE_NOTATTACHED);
+@@ -1673,14 +1646,6 @@ EXPORT_SYMBOL_GPL (usb_hc_died);
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-static void hcd_release (struct usb_bus *bus)
+-{
+-	struct usb_hcd *hcd;
+-
+-	hcd = container_of(bus, struct usb_hcd, self);
+-	kfree(hcd);
+-}
+-
+ /**
+  * usb_create_hcd - create and initialize an HCD structure
+  * @driver: HC driver that will use this hcd
+@@ -1705,10 +1670,9 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
+ 		return NULL;
+ 	}
+ 	dev_set_drvdata(dev, hcd);
++	kref_init(&hcd->kref);
+ 
+ 	usb_bus_init(&hcd->self);
+-	hcd->self.hcpriv = hcd;
+-	hcd->self.release = &hcd_release;
+ 	hcd->self.controller = dev;
+ 	hcd->self.bus_name = bus_name;
+ 	hcd->self.uses_dma = (dev->dma_mask != NULL);
+@@ -1725,10 +1689,25 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
+ }
+ EXPORT_SYMBOL (usb_create_hcd);
+ 
++static void hcd_release (struct kref *kref)
++{
++	struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref);
++
++	kfree(hcd);
++}
++
++struct usb_hcd *usb_get_hcd (struct usb_hcd *hcd)
++{
++	if (hcd)
++		kref_get (&hcd->kref);
++	return hcd;
++}
++EXPORT_SYMBOL (usb_get_hcd);
++
+ void usb_put_hcd (struct usb_hcd *hcd)
+ {
+-	dev_set_drvdata(hcd->self.controller, NULL);
+-	usb_bus_put(&hcd->self);
++	if (hcd)
++		kref_put (&hcd->kref, hcd_release);
+ }
+ EXPORT_SYMBOL (usb_put_hcd);
+ 
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index 83e229914797..7a2bcba2ae61 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -55,12 +55,13 @@
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-struct usb_hcd {	/* usb_bus.hcpriv points to this */
++struct usb_hcd {
+ 
+ 	/*
+ 	 * housekeeping
+ 	 */
+ 	struct usb_bus		self;		/* hcd is-a bus */
++	struct kref		kref;		/* reference counter */
+ 
+ 	const char		*product_desc;	/* product/vendor string */
+ 	char			irq_descr[24];	/* driver + bus # */
+@@ -129,8 +130,10 @@ static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd)
+ 	return &hcd->self;
+ }
+ 
+-
+-// urb.hcpriv is really hardware-specific
++static inline struct usb_hcd *bus_to_hcd (struct usb_bus *bus)
++{
++	return container_of(bus, struct usb_hcd, self);
++}
+ 
+ struct hcd_timeout {	/* timeouts we allocate */
+ 	struct list_head	timeout_list;
+@@ -210,6 +213,7 @@ extern int usb_hcd_get_frame_number (struct usb_device *udev);
+ 
+ extern struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
+ 		struct device *dev, char *bus_name);
++extern struct usb_hcd *usb_get_hcd (struct usb_hcd *hcd);
+ extern void usb_put_hcd (struct usb_hcd *hcd);
+ extern int usb_add_hcd(struct usb_hcd *hcd,
+ 		unsigned int irqnum, unsigned long irqflags);
+@@ -356,9 +360,6 @@ extern struct list_head usb_bus_list;
+ extern struct mutex usb_bus_list_lock;
+ extern wait_queue_head_t usb_kill_urb_queue;
+ 
+-extern struct usb_bus *usb_bus_get (struct usb_bus *bus);
+-extern void usb_bus_put (struct usb_bus *bus);
+-
+ extern void usb_enable_root_hub_irq (struct usb_bus *bus);
+ 
+ extern int usb_find_interface_driver (struct usb_device *dev,
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 7ab9d29215f8..b0c0a993338f 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -169,7 +169,7 @@ static void usb_release_dev(struct device *dev)
+ 	udev = to_usb_device(dev);
+ 
+ 	usb_destroy_configuration(udev);
+-	usb_bus_put(udev->bus);
++	usb_put_hcd(bus_to_hcd(udev->bus));
+ 	kfree(udev->product);
+ 	kfree(udev->manufacturer);
+ 	kfree(udev->serial);
+@@ -197,8 +197,7 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
+ 	if (!dev)
+ 		return NULL;
+ 
+-	bus = usb_bus_get(bus);
+-	if (!bus) {
++	if (!usb_get_hcd(bus_to_hcd(bus))) {
+ 		kfree(dev);
+ 		return NULL;
+ 	}
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index 7d1c22c34957..fdab97a27c08 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -889,11 +889,9 @@ EXPORT_SYMBOL (net2280_set_fifo_mode);
+ static void
+ dummy_gadget_release (struct device *dev)
+ {
+-#if 0		/* usb_bus_put isn't EXPORTed! */
+ 	struct dummy	*dum = gadget_dev_to_dummy (dev);
+ 
+-	usb_bus_put (&dummy_to_hcd (dum)->self);
+-#endif
++	usb_put_hcd (dummy_to_hcd (dum));
+ }
+ 
+ static int dummy_udc_probe (struct platform_device *pdev)
+@@ -915,9 +913,7 @@ static int dummy_udc_probe (struct platform_device *pdev)
+ 	if (rc < 0)
+ 		return rc;
+ 
+-#if 0		/* usb_bus_get isn't EXPORTed! */
+-	usb_bus_get (&dummy_to_hcd (dum)->self);
+-#endif
++	usb_get_hcd (dummy_to_hcd (dum));
+ 
+ 	platform_set_drvdata (pdev, dum);
+ 	device_create_file (&dum->gadget.dev, &dev_attr_function);
+diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
+index 65ac9fef3a7c..215ce6d06394 100644
+--- a/drivers/usb/host/ehci-dbg.c
++++ b/drivers/usb/host/ehci-dbg.c
+@@ -451,7 +451,7 @@ show_async (struct class_device *class_dev, char *buf)
+ 	*buf = 0;
+ 
+ 	bus = class_get_devdata(class_dev);
+-	hcd = bus->hcpriv;
++	hcd = bus_to_hcd(bus);
+ 	ehci = hcd_to_ehci (hcd);
+ 	next = buf;
+ 	size = PAGE_SIZE;
+@@ -497,7 +497,7 @@ show_periodic (struct class_device *class_dev, char *buf)
+ 	seen_count = 0;
+ 
+ 	bus = class_get_devdata(class_dev);
+-	hcd = bus->hcpriv;
++	hcd = bus_to_hcd(bus);
+ 	ehci = hcd_to_ehci (hcd);
+ 	next = buf;
+ 	size = PAGE_SIZE;
+@@ -634,7 +634,7 @@ show_registers (struct class_device *class_dev, char *buf)
+ 	static char		label [] = "";
+ 
+ 	bus = class_get_devdata(class_dev);
+-	hcd = bus->hcpriv;
++	hcd = bus_to_hcd(bus);
+ 	ehci = hcd_to_ehci (hcd);
+ 	next = buf;
+ 	size = PAGE_SIZE;
+diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
+index da52609a9290..534d07dcb824 100644
+--- a/drivers/usb/host/ohci-dbg.c
++++ b/drivers/usb/host/ohci-dbg.c
+@@ -477,7 +477,7 @@ show_async (struct class_device *class_dev, char *buf)
+ 	unsigned long		flags;
+ 
+ 	bus = class_get_devdata(class_dev);
+-	hcd = bus->hcpriv;
++	hcd = bus_to_hcd(bus);
+ 	ohci = hcd_to_ohci(hcd);
+ 
+ 	/* display control and bulk lists together, for simplicity */
+@@ -510,7 +510,7 @@ show_periodic (struct class_device *class_dev, char *buf)
+ 	seen_count = 0;
+ 
+ 	bus = class_get_devdata(class_dev);
+-	hcd = bus->hcpriv;
++	hcd = bus_to_hcd(bus);
+ 	ohci = hcd_to_ohci(hcd);
+ 	next = buf;
+ 	size = PAGE_SIZE;
+@@ -607,7 +607,7 @@ show_registers (struct class_device *class_dev, char *buf)
+ 	u32			rdata;
+ 
+ 	bus = class_get_devdata(class_dev);
+-	hcd = bus->hcpriv;
++	hcd = bus_to_hcd(bus);
+ 	ohci = hcd_to_ohci(hcd);
+ 	regs = ohci->regs;
+ 	next = buf;
+diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c
+index 275a66f83058..e0ed36cdfd8b 100644
+--- a/drivers/usb/mon/mon_main.c
++++ b/drivers/usb/mon/mon_main.c
+@@ -265,7 +265,6 @@ static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus)
+ 	ubus->mon_bus = NULL;
+ 	mbus->u_bus = NULL;
+ 	mb();
+-	// usb_bus_put(ubus);
+ }
+ 
+ /*
+@@ -297,10 +296,9 @@ static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus)
+ 	INIT_LIST_HEAD(&mbus->r_list);
+ 
+ 	/*
+-	 * This usb_bus_get here is superfluous, because we receive
+-	 * a notification if usb_bus is about to be removed.
++	 * We don't need to take a reference to ubus, because we receive
++	 * a notification if the bus is about to be removed.
+ 	 */
+-	// usb_bus_get(ubus);
+ 	mbus->u_bus = ubus;
+ 	ubus->mon_bus = mbus;
+ 
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 09661759621f..c66303285a45 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -280,7 +280,6 @@ struct usb_bus {
+ 	struct usb_devmap devmap;	/* device address allocation map */
+ 	struct usb_device *root_hub;	/* Root hub */
+ 	struct list_head bus_list;	/* list of busses */
+-	void *hcpriv;                   /* Host Controller private data */
+ 
+ 	int bandwidth_allocated;	/* on this bus: how much of the time
+ 					 * reserved for periodic (intr/iso)
+@@ -295,8 +294,6 @@ struct usb_bus {
+ 	struct dentry *usbfs_dentry;	/* usbfs dentry entry for the bus */
+ 
+ 	struct class_device *class_dev;	/* class device for this bus */
+-	struct kref kref;		/* reference counting for this bus */
+-	void (*release)(struct usb_bus *bus);
+ 
+ #if defined(CONFIG_USB_MON)
+ 	struct mon_bus *mon_bus;	/* non-null when associated */

commit dd990f16a39d4e615c0b70a0ab50b79b32bfb16d
+Author: Alan Stern 
+Date:   Wed Aug 30 11:29:56 2006 -0400
+
+    usbcore: Add flag for whether a host controller uses DMA
+    
+    This patch (as770b) introduces a new field to usb_bus: a flag
+    indicating whether or not the host controller uses DMA.  This serves
+    to encapsulate the computation.  It also means we will have only one
+    spot to update if the DMA API changes.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 2102c4deec1e..0cc14206920a 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1152,7 +1152,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+ 	/* lower level hcd code should use *_dma exclusively,
+ 	 * unless it uses pio or talks to another transport.
+ 	 */
+-	if (hcd->self.controller->dma_mask) {
++	if (hcd->self.uses_dma) {
+ 		if (usb_pipecontrol (urb->pipe)
+ 			&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
+ 			urb->setup_dma = dma_map_single (
+@@ -1585,8 +1585,9 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs
+ 	at_root_hub = (urb->dev == hcd->self.root_hub);
+ 	urb_unlink (urb);
+ 
+-	/* lower level hcd code should use *_dma exclusively */
+-	if (hcd->self.controller->dma_mask && !at_root_hub) {
++	/* lower level hcd code should use *_dma exclusively if the
++	 * host controller does DMA */
++	if (hcd->self.uses_dma && !at_root_hub) {
+ 		if (usb_pipecontrol (urb->pipe)
+ 			&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
+ 			dma_unmap_single (hcd->self.controller, urb->setup_dma,
+@@ -1710,6 +1711,7 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
+ 	hcd->self.release = &hcd_release;
+ 	hcd->self.controller = dev;
+ 	hcd->self.bus_name = bus_name;
++	hcd->self.uses_dma = (dev->dma_mask != NULL);
+ 
+ 	init_timer(&hcd->rh_timer);
+ 	hcd->rh_timer.function = rh_timer_func;
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 4709033f8fa7..09661759621f 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -269,6 +269,7 @@ struct usb_bus {
+ 	struct device *controller;	/* host/master side hardware */
+ 	int busnum;			/* Bus number (in order of reg) */
+ 	char *bus_name;			/* stable id (PCI slot_name etc) */
++	u8 uses_dma;			/* Does the host controller use DMA? */
+ 	u8 otg_port;			/* 0, or number of OTG/HNP port */
+ 	unsigned is_b_host:1;		/* true during some HNP roleswitches */
+ 	unsigned b_hnp_enable:1;	/* OTG: did A-Host enable HNP? */

commit a6d2bb9ff919b4685bd684620ec7a1ffa8bf2349
+Author: Alan Stern 
+Date:   Wed Aug 30 11:27:36 2006 -0400
+
+    USB: remove struct usb_operations
+    
+    All of the currently-supported USB host controller drivers use the HCD
+    bus-glue framework.  As part of the program for flattening out the glue
+    layer, this patch (as769) removes the usb_operations structure.  All
+    function calls now go directly to the HCD routines (slightly renamed
+    to remain within the "usb_" namespace).
+    
+    The patch also removes usb_alloc_bus(), because it's not useful in the
+    HCD framework and it wasn't referenced anywhere.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index ea20a3a5a9b9..2102c4deec1e 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -731,30 +731,6 @@ static void usb_bus_init (struct usb_bus *bus)
+ 	kref_init(&bus->kref);
+ }
+ 
+-/**
+- * usb_alloc_bus - creates a new USB host controller structure
+- * @op: pointer to a struct usb_operations that this bus structure should use
+- * Context: !in_interrupt()
+- *
+- * Creates a USB host controller bus structure with the specified 
+- * usb_operations and initializes all the necessary internal objects.
+- *
+- * If no memory is available, NULL is returned.
+- *
+- * The caller should call usb_put_bus() when it is finished with the structure.
+- */
+-struct usb_bus *usb_alloc_bus (struct usb_operations *op)
+-{
+-	struct usb_bus *bus;
+-
+-	bus = kzalloc (sizeof *bus, GFP_KERNEL);
+-	if (!bus)
+-		return NULL;
+-	usb_bus_init (bus);
+-	bus->op = op;
+-	return bus;
+-}
+-
+ /*-------------------------------------------------------------------------*/
+ 
+ /**
+@@ -1102,7 +1078,7 @@ static void urb_unlink (struct urb *urb)
+  * expects usb_submit_urb() to have sanity checked and conditioned all
+  * inputs in the urb
+  */
+-static int hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
++int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+ {
+ 	int			status;
+ 	struct usb_hcd		*hcd = urb->dev->bus->hcpriv;
+@@ -1211,7 +1187,7 @@ static int hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+ /*-------------------------------------------------------------------------*/
+ 
+ /* called in any context */
+-static int hcd_get_frame_number (struct usb_device *udev)
++int usb_hcd_get_frame_number (struct usb_device *udev)
+ {
+ 	struct usb_hcd	*hcd = (struct usb_hcd *)udev->bus->hcpriv;
+ 	if (!HC_IS_RUNNING (hcd->state))
+@@ -1253,7 +1229,7 @@ unlink1 (struct usb_hcd *hcd, struct urb *urb)
+  * caller guarantees urb won't be recycled till both unlink()
+  * and the urb's completion function return
+  */
+-static int hcd_unlink_urb (struct urb *urb, int status)
++int usb_hcd_unlink_urb (struct urb *urb, int status)
+ {
+ 	struct usb_host_endpoint	*ep;
+ 	struct usb_hcd			*hcd = NULL;
+@@ -1351,8 +1327,8 @@ static int hcd_unlink_urb (struct urb *urb, int status)
+  * example:  a qh stored in ep->hcpriv, holding state related to endpoint
+  * type, maxpacket size, toggle, halt status, and scheduling.
+  */
+-static void
+-hcd_endpoint_disable (struct usb_device *udev, struct usb_host_endpoint *ep)
++void usb_hcd_endpoint_disable (struct usb_device *udev,
++		struct usb_host_endpoint *ep)
+ {
+ 	struct usb_hcd		*hcd;
+ 	struct urb		*urb;
+@@ -1589,20 +1565,6 @@ EXPORT_SYMBOL (usb_bus_start_enum);
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-/*
+- * usb_hcd_operations - adapts usb_bus framework to HCD framework (bus glue)
+- */
+-static struct usb_operations usb_hcd_operations = {
+-	.get_frame_number =	hcd_get_frame_number,
+-	.submit_urb =		hcd_submit_urb,
+-	.unlink_urb =		hcd_unlink_urb,
+-	.buffer_alloc =		hcd_buffer_alloc,
+-	.buffer_free =		hcd_buffer_free,
+-	.disable =		hcd_endpoint_disable,
+-};
+-
+-/*-------------------------------------------------------------------------*/
+-
+ /**
+  * usb_hcd_giveback_urb - return URB from HCD to device driver
+  * @hcd: host controller returning the URB
+@@ -1744,7 +1706,6 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
+ 	dev_set_drvdata(dev, hcd);
+ 
+ 	usb_bus_init(&hcd->self);
+-	hcd->self.op = &usb_hcd_operations;
+ 	hcd->self.hcpriv = hcd;
+ 	hcd->self.release = &hcd_release;
+ 	hcd->self.controller = dev;
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index fc71a08a1af4..83e229914797 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -139,28 +139,6 @@ struct hcd_timeout {	/* timeouts we allocate */
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-/*
+- * FIXME usb_operations should vanish or become hc_driver,
+- * when usb_bus and usb_hcd become the same thing.
+- */
+-
+-struct usb_operations {
+-	int (*get_frame_number) (struct usb_device *usb_dev);
+-	int (*submit_urb) (struct urb *urb, gfp_t mem_flags);
+-	int (*unlink_urb) (struct urb *urb, int status);
+-
+-	/* allocate dma-consistent buffer for URB_DMA_NOMAPPING */
+-	void *(*buffer_alloc)(struct usb_bus *bus, size_t size,
+-			gfp_t mem_flags,
+-			dma_addr_t *dma);
+-	void (*buffer_free)(struct usb_bus *bus, size_t size,
+-			void *addr, dma_addr_t dma);
+-
+-	void (*disable)(struct usb_device *udev,
+-			struct usb_host_endpoint *ep);
+-};
+-
+-/* each driver provides one of these, and hardware init support */
+ 
+ struct pt_regs;
+ 
+@@ -222,7 +200,13 @@ struct hc_driver {
+ 		/* Needed only if port-change IRQs are level-triggered */
+ };
+ 
+-extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs);
++extern int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags);
++extern int usb_hcd_unlink_urb (struct urb *urb, int status);
++extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb,
++		struct pt_regs *regs);
++extern void usb_hcd_endpoint_disable (struct usb_device *udev,
++		struct usb_host_endpoint *ep);
++extern int usb_hcd_get_frame_number (struct usb_device *udev);
+ 
+ extern struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
+ 		struct device *dev, char *bus_name);
+@@ -361,8 +345,6 @@ extern long usb_calc_bus_time (int speed, int is_input,
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-extern struct usb_bus *usb_alloc_bus (struct usb_operations *);
+-
+ extern void usb_set_device_state(struct usb_device *udev,
+ 		enum usb_device_state new_state);
+ 
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 333b22c68aa4..1580c81a0db7 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -984,8 +984,8 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr)
+ 		ep = dev->ep_in[epnum];
+ 		dev->ep_in[epnum] = NULL;
+ 	}
+-	if (ep && dev->bus && dev->bus->op && dev->bus->op->disable)
+-		dev->bus->op->disable(dev, ep);
++	if (ep && dev->bus)
++		usb_hcd_endpoint_disable(dev, ep);
+ }
+ 
+ /**
+diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
+index 9864988377c7..576919927f53 100644
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -221,7 +221,6 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ {
+ 	int			pipe, temp, max;
+ 	struct usb_device	*dev;
+-	struct usb_operations	*op;
+ 	int			is_out;
+ 
+ 	if (!urb || urb->hcpriv || !urb->complete)
+@@ -233,8 +232,6 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 	if (dev->bus->controller->power.power_state.event != PM_EVENT_ON
+ 			|| dev->state == USB_STATE_SUSPENDED)
+ 		return -EHOSTUNREACH;
+-	if (!(op = dev->bus->op) || !op->submit_urb)
+-		return -ENODEV;
+ 
+ 	urb->status = -EINPROGRESS;
+ 	urb->actual_length = 0;
+@@ -376,7 +373,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 		urb->interval = temp;
+ 	}
+ 
+-	return op->submit_urb (urb, mem_flags);
++	return usb_hcd_submit_urb (urb, mem_flags);
+ }
+ 
+ /*-------------------------------------------------------------------*/
+@@ -440,9 +437,9 @@ int usb_unlink_urb(struct urb *urb)
+ {
+ 	if (!urb)
+ 		return -EINVAL;
+-	if (!(urb->dev && urb->dev->bus && urb->dev->bus->op))
++	if (!(urb->dev && urb->dev->bus))
+ 		return -ENODEV;
+-	return urb->dev->bus->op->unlink_urb(urb, -ECONNRESET);
++	return usb_hcd_unlink_urb(urb, -ECONNRESET);
+ }
+ 
+ /**
+@@ -468,13 +465,13 @@ int usb_unlink_urb(struct urb *urb)
+ void usb_kill_urb(struct urb *urb)
+ {
+ 	might_sleep();
+-	if (!(urb && urb->dev && urb->dev->bus && urb->dev->bus->op))
++	if (!(urb && urb->dev && urb->dev->bus))
+ 		return;
+ 	spin_lock_irq(&urb->lock);
+ 	++urb->reject;
+ 	spin_unlock_irq(&urb->lock);
+ 
+-	urb->dev->bus->op->unlink_urb(urb, -ENOENT);
++	usb_hcd_unlink_urb(urb, -ENOENT);
+ 	wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0);
+ 
+ 	spin_lock_irq(&urb->lock);
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 4eb98eb3804f..7ab9d29215f8 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -480,7 +480,7 @@ struct usb_device *usb_find_device(u16 vendor_id, u16 product_id)
+  */
+ int usb_get_current_frame_number(struct usb_device *dev)
+ {
+-	return dev->bus->op->get_frame_number (dev);
++	return usb_hcd_get_frame_number (dev);
+ }
+ 
+ /**
+@@ -677,9 +677,9 @@ void *usb_buffer_alloc (
+ 	dma_addr_t *dma
+ )
+ {
+-	if (!dev || !dev->bus || !dev->bus->op || !dev->bus->op->buffer_alloc)
++	if (!dev || !dev->bus)
+ 		return NULL;
+-	return dev->bus->op->buffer_alloc (dev->bus, size, mem_flags, dma);
++	return hcd_buffer_alloc (dev->bus, size, mem_flags, dma);
+ }
+ 
+ /**
+@@ -700,11 +700,11 @@ void usb_buffer_free (
+ 	dma_addr_t dma
+ )
+ {
+-	if (!dev || !dev->bus || !dev->bus->op || !dev->bus->op->buffer_free)
++	if (!dev || !dev->bus)
+ 		return;
+ 	if (!addr)
+ 		return;
+-	dev->bus->op->buffer_free (dev->bus, size, addr, dma);
++	hcd_buffer_free (dev->bus, size, addr, dma);
+ }
+ 
+ /**
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index f104efa04d79..4709033f8fa7 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -257,8 +257,6 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,
+ 
+ /* ----------------------------------------------------------------------- */
+ 
+-struct usb_operations;
+-
+ /* USB device number allocation bitmap */
+ struct usb_devmap {
+ 	unsigned long devicemap[128 / (8*sizeof(unsigned long))];
+@@ -279,7 +277,6 @@ struct usb_bus {
+ 					 * round-robin allocation */
+ 
+ 	struct usb_devmap devmap;	/* device address allocation map */
+-	struct usb_operations *op;	/* Operations (specific to the HC) */
+ 	struct usb_device *root_hub;	/* Root hub */
+ 	struct list_head bus_list;	/* list of busses */
+ 	void *hcpriv;                   /* Host Controller private data */
+@@ -1051,7 +1048,6 @@ extern int usb_submit_urb(struct urb *urb, gfp_t mem_flags);
+ extern int usb_unlink_urb(struct urb *urb);
+ extern void usb_kill_urb(struct urb *urb);
+ 
+-#define HAVE_USB_BUFFERS
+ void *usb_buffer_alloc (struct usb_device *dev, size_t size,
+ 	gfp_t mem_flags, dma_addr_t *dma);
+ void usb_buffer_free (struct usb_device *dev, size_t size,

commit 088dc270e1da03744d977cbd9edd4311af142348
+Author: Alan Stern 
+Date:   Mon Aug 21 12:08:19 2006 -0400
+
+    usbcore: help drivers to change device configs
+    
+    It's generally a bad idea for USB interface drivers to try to change a
+    device's configuration, and usbcore doesn't provide any way for them
+    to do it.  However in a few exceptional circumstances it can make
+    sense.  This patch (as767) adds a roundabout mechanism to help drivers
+    that may need it.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 49cfd7928a1c..333b22c68aa4 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1493,6 +1493,65 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 	return 0;
+ }
+ 
++struct set_config_request {
++	struct usb_device	*udev;
++	int			config;
++	struct work_struct	work;
++};
++
++/* Worker routine for usb_driver_set_configuration() */
++static void driver_set_config_work(void *_req)
++{
++	struct set_config_request *req = _req;
++
++	usb_lock_device(req->udev);
++	usb_set_configuration(req->udev, req->config);
++	usb_unlock_device(req->udev);
++	usb_put_dev(req->udev);
++	kfree(req);
++}
++
++/**
++ * usb_driver_set_configuration - Provide a way for drivers to change device configurations
++ * @udev: the device whose configuration is being updated
++ * @config: the configuration being chosen.
++ * Context: In process context, must be able to sleep
++ *
++ * Device interface drivers are not allowed to change device configurations.
++ * This is because changing configurations will destroy the interface the
++ * driver is bound to and create new ones; it would be like a floppy-disk
++ * driver telling the computer to replace the floppy-disk drive with a
++ * tape drive!
++ *
++ * Still, in certain specialized circumstances the need may arise.  This
++ * routine gets around the normal restrictions by using a work thread to
++ * submit the change-config request.
++ *
++ * Returns 0 if the request was succesfully queued, error code otherwise.
++ * The caller has no way to know whether the queued request will eventually
++ * succeed.
++ */
++int usb_driver_set_configuration(struct usb_device *udev, int config)
++{
++	struct set_config_request *req;
++
++	req = kmalloc(sizeof(*req), GFP_KERNEL);
++	if (!req)
++		return -ENOMEM;
++	req->udev = udev;
++	req->config = config;
++	INIT_WORK(&req->work, driver_set_config_work, req);
++
++	usb_get_dev(udev);
++	if (!schedule_work(&req->work)) {
++		usb_put_dev(udev);
++		kfree(req);
++		return -EINVAL;
++	}
++	return 0;
++}
++EXPORT_SYMBOL_GPL(usb_driver_set_configuration);
++
+ // synchronous request completion model
+ EXPORT_SYMBOL(usb_control_msg);
+ EXPORT_SYMBOL(usb_bulk_msg);
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 26d8a5f36896..f104efa04d79 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -1099,6 +1099,9 @@ extern int usb_clear_halt(struct usb_device *dev, int pipe);
+ extern int usb_reset_configuration(struct usb_device *dev);
+ extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
+ 
++/* this request isn't really synchronous, but it belongs with the others */
++extern int usb_driver_set_configuration(struct usb_device *udev, int config);
++
+ /*
+  * timeouts, in milliseconds, used for sending/receiving control messages
+  * they typically complete within a few frames (msec) after they're issued

commit 3a3416b12f1fbd607bc137a57c924a628aa5485c
+Author: Alan Stern 
+Date:   Mon Aug 21 12:00:53 2006 -0400
+
+    usb-storage: fix for UFI LUN detection
+    
+    The UFI specification doesn't permit devices to indicate non-existent
+    LUNs in the manner prescribed by the SCSI spec.  This patch (as773)
+    sets a special flag so that the SCSI scanner will recognize these
+    devices and treat them specially.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Matthew Dharm 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index a4b7df9ff8c1..e1072d52d641 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -72,12 +72,27 @@ static const char* host_info(struct Scsi_Host *host)
+ 
+ static int slave_alloc (struct scsi_device *sdev)
+ {
++	struct us_data *us = host_to_us(sdev->host);
++
+ 	/*
+ 	 * Set the INQUIRY transfer length to 36.  We don't use any of
+ 	 * the extra data and many devices choke if asked for more or
+ 	 * less than 36 bytes.
+ 	 */
+ 	sdev->inquiry_len = 36;
++
++	/*
++	 * The UFI spec treates the Peripheral Qualifier bits in an
++	 * INQUIRY result as reserved and requires devices to set them
++	 * to 0.  However the SCSI spec requires these bits to be set
++	 * to 3 to indicate when a LUN is not present.
++	 *
++	 * Let the scanning code know if this target merely sets
++	 * Peripheral Device Type to 0x1f to indicate no LUN.
++	 */
++	if (us->subclass == US_SC_UFI)
++		sdev->sdev_target->pdt_1f_for_no_lun = 1;
++
+ 	return 0;
+ }
+ 

commit d5cbad4b8b37acfde3e63d31b92561b87288ad0f
+Author: Alan Stern 
+Date:   Fri Aug 11 16:52:39 2006 -0400
+
+    usbcore: khubd and busy-port handling
+    
+    We don't want khubd to start interfering in the device-resume process
+    merely because the PORT_STATUS_C_SUSPEND feature happens to be set.
+    Ports need to be marked as busy while a resume is taking place.
+    
+    In addition, so long as ports are marked as busy, khubd won't be able to
+    clear their various status-change features.  On an interrupt-driven root
+    hub this could lead to an interrupt storm.  Root hub IRQs should not be
+    re-enabled until the busy_bits value is equal to 0.
+    
+    This patch (as765) fixes these two potential problems.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 3924dd080bea..bdf5be099650 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1658,6 +1658,8 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+ 
+ 	// dev_dbg(hub->intfdev, "resume port %d\n", port1);
+ 
++	set_bit(port1, hub->busy_bits);
++
+ 	/* see 7.1.7.7; affects power usage, but not budgeting */
+ 	status = clear_port_feature(hub->hdev,
+ 			port1, USB_PORT_FEAT_SUSPEND);
+@@ -1707,6 +1709,10 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+ 	if (status < 0)
+ 		hub_port_logical_disconnect(hub, port1);
+ 
++	clear_bit(port1, hub->busy_bits);
++	if (!hub->hdev->parent && !hub->busy_bits[0])
++		usb_enable_root_hub_irq(hub->hdev->bus);
++
+ 	return status;
+ }
+ 
+@@ -2690,7 +2696,7 @@ static void hub_events(void)
+ 
+ 		/* If this is a root hub, tell the HCD it's okay to
+ 		 * re-enable port-change interrupts now. */
+-		if (!hdev->parent)
++		if (!hdev->parent && !hub->busy_bits[0])
+ 			usb_enable_root_hub_irq(hdev->bus);
+ 
+ loop:
+@@ -2865,6 +2871,9 @@ int usb_reset_device(struct usb_device *udev)
+ 			break;
+ 	}
+ 	clear_bit(port1, parent_hub->busy_bits);
++	if (!parent_hdev->parent && !parent_hub->busy_bits[0])
++		usb_enable_root_hub_irq(parent_hdev->bus);
++
+ 	if (ret < 0)
+ 		goto re_enumerate;
+  
+diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
+index 29d5f45a8456..0f8e82a4d480 100644
+--- a/drivers/usb/core/hub.h
++++ b/drivers/usb/core/hub.h
+@@ -212,7 +212,8 @@ struct usb_hub {
+ 	unsigned long		event_bits[1];	/* status change bitmask */
+ 	unsigned long		change_bits[1];	/* ports with logical connect
+ 							status change */
+-	unsigned long		busy_bits[1];	/* ports being reset */
++	unsigned long		busy_bits[1];	/* ports being reset or
++							resumed */
+ #if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
+ #error event_bits[] is too short!
+ #endif

commit 455b25fb209c8241e2163b491228b28667d82c1c
+Author: Alan Stern 
+Date:   Fri Aug 11 16:01:45 2006 -0400
+
+    usbcore: make hcd_endpoint_disable wait for queue to drain
+    
+    The inconsistent lock state problem in usbcore (the one that shows up
+    when an HCD is unloaded) comes down to two inter-related problems:
+    
+            usb_rh_urb_dequeue() isn't set up to be called with interrupts
+            disabled.
+    
+            hcd_endpoint_disable() doesn't wait for all URBs on the
+            endpoint's queue to complete.
+    
+    The two problems are related because the one type of URB that isn't
+    likely to be complete when hcd_endpoint_disable() returns is a root-hub
+    URB.  Right now usb_rh_urb_dequeue() waits for them to complete, and it
+    assumes interrupts are enabled so it can wait.  But
+    hcd_endpoint_disable() calls it with interrupts disabled.
+    
+    Now, it should be legal to unlink root-hub URBs with interrupts
+    disabled.  The solution is to move the waiting into
+    hcd_endpoint_disable(), where it belongs.  This patch (as754) does that.
+    
+    It turns out to be completely safe to replace the del_timer_sync() with
+    a simple del_timer().  It doesn't matter if the timer routine is
+    running; hcd_root_hub_lock will synchronize the two threads and the
+    status URB will complete with an unlink error, as it should.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index dc9628c58933..ea20a3a5a9b9 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -633,31 +633,20 @@ static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-/* Asynchronous unlinks of root-hub control URBs are legal, but they
+- * don't do anything.  Status URB unlinks must be made in process context
+- * with interrupts enabled.
++/* Unlinks of root-hub control URBs are legal, but they don't do anything
++ * since these URBs always execute synchronously.
+  */
+ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
+ {
+-	if (usb_pipeendpoint(urb->pipe) == 0) {	/* Control URB */
+-		if (in_interrupt())
+-			return 0;		/* nothing to do */
+-
+-		spin_lock_irq(&urb->lock);	/* from usb_kill_urb */
+-		++urb->reject;
+-		spin_unlock_irq(&urb->lock);
+-
+-		wait_event(usb_kill_urb_queue,
+-				atomic_read(&urb->use_count) == 0);
++	unsigned long	flags;
+ 
+-		spin_lock_irq(&urb->lock);
+-		--urb->reject;
+-		spin_unlock_irq(&urb->lock);
++	if (usb_pipeendpoint(urb->pipe) == 0) {	/* Control URB */
++		;	/* Do nothing */
+ 
+ 	} else {				/* Status URB */
+ 		if (!hcd->uses_new_polling)
+-			del_timer_sync (&hcd->rh_timer);
+-		local_irq_disable ();
++			del_timer (&hcd->rh_timer);
++		local_irq_save (flags);
+ 		spin_lock (&hcd_root_hub_lock);
+ 		if (urb == hcd->status_urb) {
+ 			hcd->status_urb = NULL;
+@@ -667,7 +656,7 @@ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
+ 		spin_unlock (&hcd_root_hub_lock);
+ 		if (urb)
+ 			usb_hcd_giveback_urb (hcd, urb, NULL);
+-		local_irq_enable ();
++		local_irq_restore (flags);
+ 	}
+ 
+ 	return 0;
+@@ -1355,7 +1344,8 @@ static int hcd_unlink_urb (struct urb *urb, int status)
+ /*-------------------------------------------------------------------------*/
+ 
+ /* disables the endpoint: cancels any pending urbs, then synchronizes with
+- * the hcd to make sure all endpoint state is gone from hardware. use for
++ * the hcd to make sure all endpoint state is gone from hardware, and then
++ * waits until the endpoint's queue is completely drained. use for
+  * set_configuration, set_interface, driver removal, physical disconnect.
+  *
+  * example:  a qh stored in ep->hcpriv, holding state related to endpoint
+@@ -1374,22 +1364,13 @@ hcd_endpoint_disable (struct usb_device *udev, struct usb_host_endpoint *ep)
+ 
+ 	local_irq_disable ();
+ 
+-	/* FIXME move most of this into message.c as part of its
+-	 * endpoint disable logic
+-	 */
+-
+ 	/* ep is already gone from udev->ep_{in,out}[]; no more submits */
+ rescan:
+ 	spin_lock (&hcd_data_lock);
+ 	list_for_each_entry (urb, &ep->urb_list, urb_list) {
+ 		int	tmp;
+ 
+-		/* another cpu may be in hcd, spinning on hcd_data_lock
+-		 * to giveback() this urb.  the races here should be
+-		 * small, but a full fix needs a new "can't submit"
+-		 * urb state.
+-		 * FIXME urb->reject should allow that...
+-		 */
++		/* the urb may already have been unlinked */
+ 		if (urb->status != -EINPROGRESS)
+ 			continue;
+ 		usb_get_urb (urb);
+@@ -1431,6 +1412,30 @@ hcd_endpoint_disable (struct usb_device *udev, struct usb_host_endpoint *ep)
+ 	might_sleep ();
+ 	if (hcd->driver->endpoint_disable)
+ 		hcd->driver->endpoint_disable (hcd, ep);
++
++	/* Wait until the endpoint queue is completely empty.  Most HCDs
++	 * will have done this already in their endpoint_disable method,
++	 * but some might not.  And there could be root-hub control URBs
++	 * still pending since they aren't affected by the HCDs'
++	 * endpoint_disable methods.
++	 */
++	while (!list_empty (&ep->urb_list)) {
++		spin_lock_irq (&hcd_data_lock);
++
++		/* The list may have changed while we acquired the spinlock */
++		urb = NULL;
++		if (!list_empty (&ep->urb_list)) {
++			urb = list_entry (ep->urb_list.prev, struct urb,
++					urb_list);
++			usb_get_urb (urb);
++		}
++		spin_unlock_irq (&hcd_data_lock);
++
++		if (urb) {
++			usb_kill_urb (urb);
++			usb_put_urb (urb);
++		}
++	}
+ }
+ 
+ /*-------------------------------------------------------------------------*/

commit de06a3b842b31b31220637c869f112cfbc1a5ef6
+Author: Alan Stern 
+Date:   Fri Aug 11 11:33:58 2006 -0400
+
+    UHCI: increase Resume-Detect-off delay
+    
+    The UHCI controller in my laptop takes longer to turn off the
+    Resume-Detect bit than the 4 us allowed by uhci-hcd.  Presumably other
+    computers will have the same problem.
+    
+    This patch (as752) increases the maximum delay to 10 us, which should be
+    plenty, and uses polling to avoid penalizing systems which can turn the
+    bit off more quickly.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
+index c545ef92fe29..16fb72eb6fc9 100644
+--- a/drivers/usb/host/uhci-hub.c
++++ b/drivers/usb/host/uhci-hub.c
+@@ -84,6 +84,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
+ 		unsigned long port_addr)
+ {
+ 	int status;
++	int i;
+ 
+ 	if (inw(port_addr) & (USBPORTSC_SUSP | USBPORTSC_RD)) {
+ 		CLR_RH_PORTSTAT(USBPORTSC_SUSP | USBPORTSC_RD);
+@@ -92,9 +93,14 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
+ 
+ 		/* The controller won't actually turn off the RD bit until
+ 		 * it has had a chance to send a low-speed EOP sequence,
+-		 * which takes 3 bit times (= 2 microseconds).  We'll delay
+-		 * slightly longer for good luck. */
+-		udelay(4);
++		 * which is supposed to take 3 bit times (= 2 microseconds).
++		 * Experiments show that some controllers take longer, so
++		 * we'll poll for completion. */
++		for (i = 0; i < 10; ++i) {
++			if (!(inw(port_addr) & USBPORTSC_RD))
++				break;
++			udelay(1);
++		}
+ 	}
+ 	clear_bit(port, &uhci->resuming_ports);
+ }

commit d388dab7b562b76525761f89702246686747ba30
+Author: Alan Stern 
+Date:   Sat Jul 1 22:14:24 2006 -0400
+
+    hub driver: improve use of #ifdef
+    
+    This patch (as736) makes the hub driver more readable by improving the
+    usage of "#ifdef CONFIG_PM" and "#ifdef CONFIG_USB_SUSPEND".
+    
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index a310c7cede99..64e80b964b87 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1041,7 +1041,7 @@ void usb_set_device_state(struct usb_device *udev,
+ }
+ 
+ 
+-#ifdef CONFIG_PM
++#ifdef	CONFIG_PM
+ 
+ /**
+  * usb_root_hub_lost_power - called by HCD if the root hub lost Vbus power
+@@ -1072,7 +1072,7 @@ void usb_root_hub_lost_power(struct usb_device *rhdev)
+ }
+ EXPORT_SYMBOL_GPL(usb_root_hub_lost_power);
+ 
+-#endif
++#endif	/* CONFIG_PM */
+ 
+ static void choose_address(struct usb_device *udev)
+ {
+@@ -1471,6 +1471,7 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
+  	kick_khubd(hub);
+ }
+ 
++#ifdef	CONFIG_PM
+ 
+ #ifdef	CONFIG_USB_SUSPEND
+ 
+@@ -1569,8 +1570,6 @@ static int __usb_port_suspend (struct usb_device *udev, int port1)
+ 	return status;
+ }
+ 
+-#endif
+-
+ /*
+  * usb_port_suspend - suspend a usb device's upstream port
+  * @udev: device that's no longer in active use
+@@ -1593,11 +1592,7 @@ static int __usb_port_suspend (struct usb_device *udev, int port1)
+  */
+ int usb_port_suspend(struct usb_device *udev)
+ {
+-#ifdef	CONFIG_USB_SUSPEND
+ 	return __usb_port_suspend(udev, udev->portnum);
+-#else
+-	return 0;
+-#endif
+ }
+ 
+ /*
+@@ -1661,8 +1656,6 @@ static int finish_port_resume(struct usb_device *udev)
+ 	return status;
+ }
+ 
+-#ifdef	CONFIG_USB_SUSPEND
+-
+ static int
+ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+ {
+@@ -1722,8 +1715,6 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+ 	return status;
+ }
+ 
+-#endif
+-
+ /*
+  * usb_port_resume - re-activate a suspended usb device's upstream port
+  * @udev: device to re-activate
+@@ -1739,17 +1730,15 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+  */
+ int usb_port_resume(struct usb_device *udev)
+ {
+-	int	status = 0;
++	int	status;
+ 
+ 	/* we change the device's upstream USB link,
+ 	 * but root hubs have no upstream USB link.
+ 	 */
+ 	if (udev->parent) {
+-#ifdef	CONFIG_USB_SUSPEND
+ 		// NOTE this fails if parent is also suspended...
+ 		status = hub_port_resume(hdev_to_hub(udev->parent),
+ 				udev->portnum, udev);
+-#endif
+ 	} else
+ 		status = finish_port_resume(udev);
+ 	if (status < 0)
+@@ -1761,8 +1750,6 @@ static int remote_wakeup(struct usb_device *udev)
+ {
+ 	int	status = 0;
+ 
+-#ifdef	CONFIG_USB_SUSPEND
+-
+ 	/* don't repeat RESUME sequence if this device
+ 	 * was already woken up by some other task
+ 	 */
+@@ -1777,10 +1764,42 @@ static int remote_wakeup(struct usb_device *udev)
+ 	if (status == 0)
+ 		usb_resume_both(udev);
+ 	usb_unlock_device(udev);
+-#endif
+ 	return status;
+ }
+ 
++#else	/* CONFIG_USB_SUSPEND */
++
++/* When CONFIG_USB_SUSPEND isn't set, we never suspend or resume any ports. */
++
++int usb_port_suspend(struct usb_device *udev)
++{
++	return 0;
++}
++
++static inline int
++finish_port_resume(struct usb_device *udev)
++{
++	return 0;
++}
++
++static inline int
++hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
++{
++	return 0;
++}
++
++int usb_port_resume(struct usb_device *udev)
++{
++	return 0;
++}
++
++static inline int remote_wakeup(struct usb_device *udev)
++{
++	return 0;
++}
++
++#endif
++
+ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+ {
+ 	struct usb_hub		*hub = usb_get_intfdata (intf);
+@@ -1854,6 +1873,15 @@ static int hub_resume(struct usb_interface *intf)
+ 	return 0;
+ }
+ 
++#else	/* CONFIG_PM */
++
++static inline int remote_wakeup(struct usb_device *udev)
++{
++	return 0;
++}
++
++#endif
++
+ void usb_suspend_root_hub(struct usb_device *hdev)
+ {
+ 	struct usb_hub *hub = hdev_to_hub(hdev);
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 74df0db954c9..98675fb1bc4c 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -30,11 +30,22 @@ extern void usb_major_cleanup(void);
+ extern int usb_host_init(void);
+ extern void usb_host_cleanup(void);
+ 
++#ifdef	CONFIG_PM
++
+ extern int usb_suspend_both(struct usb_device *udev, pm_message_t msg);
+ extern int usb_resume_both(struct usb_device *udev);
+ extern int usb_port_suspend(struct usb_device *dev);
+ extern int usb_port_resume(struct usb_device *dev);
+ 
++#else
++
++#define usb_suspend_both(udev, msg)	0
++#define usb_resume_both(udev)		0
++#define usb_port_suspend(dev)		0
++#define usb_port_resume(dev)		0
++
++#endif
++
+ extern struct bus_type usb_bus_type;
+ extern struct usb_device_driver usb_generic_driver;
+ 

commit 1c5df7e705671f11a71112eb3a1f9765cd1719f9
+Author: Alan Stern 
+Date:   Sat Jul 1 22:13:50 2006 -0400
+
+    usbcore: suspending devices with no driver
+    
+    Since usb_generic can be unbound from a USB device, we need to be able
+    to handle the possibility that a suspend or resume request arrives for a
+    device with no driver.  This patch (as735) arranges things so that
+    resume requests will fail and suspend requests will use the standard USB
+    port-suspend code.  Attempts to suspend or resume an unbound interface
+    are handled similarly (although the error caused by trying to resume an
+    unbound interface is dropped by the calling routine).
+    
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index affbfb53eb5e..a5d11461f5a9 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -761,8 +761,12 @@ static int suspend_device(struct usb_device *udev, pm_message_t msg)
+ 			udev->state == USB_STATE_SUSPENDED)
+ 		goto done;
+ 
+-	if (udev->dev.driver == NULL)
++	/* For devices that don't have a driver, we do a standard suspend. */
++	if (udev->dev.driver == NULL) {
++		status = usb_port_suspend(udev);
+ 		goto done;
++	}
++
+ 	udriver = to_usb_device_driver(udev->dev.driver);
+ 	status = udriver->suspend(udev, msg);
+ 
+@@ -782,8 +786,12 @@ static int resume_device(struct usb_device *udev)
+ 			udev->state != USB_STATE_SUSPENDED)
+ 		goto done;
+ 
+-	if (udev->dev.driver == NULL)
++	/* Can't resume it if it doesn't have a driver. */
++	if (udev->dev.driver == NULL) {
++		status = -ENOTCONN;
+ 		goto done;
++	}
++
+ 	udriver = to_usb_device_driver(udev->dev.driver);
+ 	status = udriver->resume(udev);
+ 
+@@ -804,7 +812,7 @@ static int suspend_interface(struct usb_interface *intf, pm_message_t msg)
+ 			!is_active(intf))
+ 		goto done;
+ 
+-	if (intf->dev.driver == NULL)
++	if (intf->dev.driver == NULL)		/* This can't happen */
+ 		goto done;
+ 	driver = to_usb_driver(intf->dev.driver);
+ 
+@@ -838,8 +846,11 @@ static int resume_interface(struct usb_interface *intf)
+ 			is_active(intf))
+ 		goto done;
+ 
+-	if (intf->dev.driver == NULL)
++	/* Can't resume it if it doesn't have a driver. */
++	if (intf->dev.driver == NULL) {
++		status = -ENOTCONN;
+ 		goto done;
++	}
+ 	driver = to_usb_driver(intf->dev.driver);
+ 
+ 	if (driver->resume) {

commit 114b368c07964caa3f4e1fa575b16e87fa11936c
+Author: Alan Stern 
+Date:   Sat Jul 1 22:13:04 2006 -0400
+
+    usbcore: fix up device and power state tests
+    
+    This patch (as734) rationalizes the various tests of device state and
+    power states.  There are duplications and mistaken tests in several
+    places.
+    
+    Perhaps the most interesting challenge is where the hub driver tests to
+    see that all the child devices are suspended before allowing itself to
+    be suspended.  When CONFIG_USB_SUSPEND is set the test is
+    straightforward, since we expect that the children _will_ be suspended.
+    But when CONFIG_USB_SUSPEND isn't set, it's not so clear what should be
+    done.  The code compromises by checking the child's
+    power.power_state.event field.
+    
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 92ecc4eb1e88..affbfb53eb5e 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -757,11 +757,13 @@ static int suspend_device(struct usb_device *udev, pm_message_t msg)
+ 	struct usb_device_driver	*udriver;
+ 	int				status = 0;
+ 
++	if (udev->state == USB_STATE_NOTATTACHED ||
++			udev->state == USB_STATE_SUSPENDED)
++		goto done;
++
+ 	if (udev->dev.driver == NULL)
+ 		goto done;
+ 	udriver = to_usb_device_driver(udev->dev.driver);
+-	if (udev->dev.power.power_state.event == msg.event)
+-		goto done;
+ 	status = udriver->suspend(udev, msg);
+ 
+ done:
+@@ -776,14 +778,13 @@ static int resume_device(struct usb_device *udev)
+ 	struct usb_device_driver	*udriver;
+ 	int				status = 0;
+ 
+-	if (udev->dev.power.power_state.event == PM_EVENT_ON)
++	if (udev->state == USB_STATE_NOTATTACHED ||
++			udev->state != USB_STATE_SUSPENDED)
+ 		goto done;
+ 
+ 	if (udev->dev.driver == NULL)
+ 		goto done;
+ 	udriver = to_usb_device_driver(udev->dev.driver);
+-	if (udev->state == USB_STATE_NOTATTACHED)
+-		goto done;
+ 	status = udriver->resume(udev);
+ 
+ done:
+@@ -798,14 +799,14 @@ static int suspend_interface(struct usb_interface *intf, pm_message_t msg)
+ 	struct usb_driver	*driver;
+ 	int			status = 0;
+ 
+-	if (intf->dev.driver == NULL)
++	/* with no hardware, USB interfaces only use FREEZE and ON states */
++	if (interface_to_usbdev(intf)->state == USB_STATE_NOTATTACHED ||
++			!is_active(intf))
+ 		goto done;
+ 
+-	driver = to_usb_driver(intf->dev.driver);
+-
+-	/* with no hardware, USB interfaces only use FREEZE and ON states */
+-	if (!is_active(intf))
++	if (intf->dev.driver == NULL)
+ 		goto done;
++	driver = to_usb_driver(intf->dev.driver);
+ 
+ 	if (driver->suspend && driver->resume) {
+ 		status = driver->suspend(intf, msg);
+@@ -831,25 +832,16 @@ static int suspend_interface(struct usb_interface *intf, pm_message_t msg)
+ static int resume_interface(struct usb_interface *intf)
+ {
+ 	struct usb_driver	*driver;
+-	struct usb_device	*udev;
+ 	int			status = 0;
+ 
+-	if (intf->dev.power.power_state.event == PM_EVENT_ON)
++	if (interface_to_usbdev(intf)->state == USB_STATE_NOTATTACHED ||
++			is_active(intf))
+ 		goto done;
+ 
+ 	if (intf->dev.driver == NULL)
+ 		goto done;
+-
+ 	driver = to_usb_driver(intf->dev.driver);
+ 
+-	udev = interface_to_usbdev(intf);
+-	if (udev->state == USB_STATE_NOTATTACHED)
+-		goto done;
+-
+-	/* if driver was suspended, it has a resume method;
+-	 * however, sysfs can wrongly mark things as suspended
+-	 * (on the "no suspend method" FIXME path above)
+-	 */
+ 	if (driver->resume) {
+ 		status = driver->resume(intf);
+ 		if (status)
+@@ -904,6 +896,12 @@ int usb_resume_both(struct usb_device *udev)
+ 	int			i;
+ 	struct usb_interface	*intf;
+ 
++	/* Can't resume if the parent is suspended */
++	if (udev->parent && udev->parent->state == USB_STATE_SUSPENDED) {
++		dev_warn(&udev->dev, "can't resume; parent is suspended\n");
++		return -EHOSTUNREACH;
++	}
++
+ 	status = resume_device(udev);
+ 	if (status == 0 && udev->actconfig) {
+ 		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
+index b6dacd7551d2..5358e656477c 100644
+--- a/drivers/usb/core/generic.c
++++ b/drivers/usb/core/generic.c
+@@ -195,9 +195,6 @@ static int generic_suspend(struct usb_device *udev, pm_message_t msg)
+ 
+ static int generic_resume(struct usb_device *udev)
+ {
+-	if (udev->state == USB_STATE_NOTATTACHED)
+-		return 0;
+-
+ 	return usb_port_resume(udev);
+ }
+ 
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 7af53db4d76f..a310c7cede99 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1556,26 +1556,6 @@ static int __usb_port_suspend (struct usb_device *udev, int port1)
+ 	if (port1 < 0)
+ 		return port1;
+ 
+-	if (udev->state == USB_STATE_SUSPENDED
+-			|| udev->state == USB_STATE_NOTATTACHED) {
+-		return 0;
+-	}
+-
+-	/* all interfaces must already be suspended */
+-	if (udev->actconfig) {
+-		int	i;
+-
+-		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+-			struct usb_interface	*intf;
+-
+-			intf = udev->actconfig->interface[i];
+-			if (is_active(intf)) {
+-				dev_dbg(&intf->dev, "nyet suspended\n");
+-				return -EBUSY;
+-			}
+-		}
+-	}
+-
+ 	/* we change the device's upstream USB link,
+ 	 * but root hubs have no upstream USB link.
+ 	 */
+@@ -1614,8 +1594,6 @@ static int __usb_port_suspend (struct usb_device *udev, int port1)
+ int usb_port_suspend(struct usb_device *udev)
+ {
+ #ifdef	CONFIG_USB_SUSPEND
+-	if (udev->state == USB_STATE_NOTATTACHED)
+-		return -ENODEV;
+ 	return __usb_port_suspend(udev, udev->portnum);
+ #else
+ 	return 0;
+@@ -1761,24 +1739,17 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+  */
+ int usb_port_resume(struct usb_device *udev)
+ {
+-	int	status;
+-
+-	if (udev->state == USB_STATE_NOTATTACHED)
+-		return -ENODEV;
++	int	status = 0;
+ 
+ 	/* we change the device's upstream USB link,
+ 	 * but root hubs have no upstream USB link.
+ 	 */
+ 	if (udev->parent) {
+ #ifdef	CONFIG_USB_SUSPEND
+-		if (udev->state == USB_STATE_SUSPENDED) {
+-			// NOTE swsusp may bork us, device state being wrong...
+-			// NOTE this fails if parent is also suspended...
+-			status = hub_port_resume(hdev_to_hub(udev->parent),
+-					udev->portnum, udev);
+-		} else
++		// NOTE this fails if parent is also suspended...
++		status = hub_port_resume(hdev_to_hub(udev->parent),
++				udev->portnum, udev);
+ #endif
+-			status = 0;
+ 	} else
+ 		status = finish_port_resume(udev);
+ 	if (status < 0)
+@@ -1821,12 +1792,14 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+ 		struct usb_device	*udev;
+ 
+ 		udev = hdev->children [port1-1];
+-		if (udev && (udev->dev.power.power_state.event
+-					== PM_EVENT_ON
++		if (udev && msg.event == PM_EVENT_SUSPEND &&
+ #ifdef	CONFIG_USB_SUSPEND
+-				|| udev->state != USB_STATE_SUSPENDED
++				udev->state != USB_STATE_SUSPENDED
++#else
++				udev->dev.power.power_state.event
++					== PM_EVENT_ON
+ #endif
+-				)) {
++				) {
+ 			dev_dbg(&intf->dev, "port %d nyet suspended\n", port1);
+ 			return -EBUSY;
+ 		}

commit 2bf4086d7a7722b470aa24e1be725cc58619c6fe
+Author: Alan Stern 
+Date:   Sat Jul 1 22:12:19 2006 -0400
+
+    usbcore: set device and power states properly
+    
+    This patch (as733) fixes up the places where device states and power
+    states are set in usbcore.  Right now things are duplicated or missing;
+    this should straighten things out.
+    
+    The idea is that udev->state is USB_STATE_SUSPENDED exactly when the
+    device's upstream port has been suspended, whereas
+    udev->dev.power.power_state.event reflects the result of the last call
+    to the suspend/resume routines (which might not actually change the
+    device state, especially if CONFIG_USB_SUSPEND isn't set).
+    
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index eefc98584eac..92ecc4eb1e88 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -755,48 +755,57 @@ EXPORT_SYMBOL_GPL_FUTURE(usb_deregister);
+ static int suspend_device(struct usb_device *udev, pm_message_t msg)
+ {
+ 	struct usb_device_driver	*udriver;
++	int				status = 0;
+ 
+ 	if (udev->dev.driver == NULL)
+-		return 0;
++		goto done;
+ 	udriver = to_usb_device_driver(udev->dev.driver);
+ 	if (udev->dev.power.power_state.event == msg.event)
+-		return 0;
+-	return udriver->suspend(udev, msg);
++		goto done;
++	status = udriver->suspend(udev, msg);
++
++done:
++	if (status == 0)
++		udev->dev.power.power_state.event = msg.event;
++	return status;
+ }
+ 
+ /* Caller has locked udev */
+ static int resume_device(struct usb_device *udev)
+ {
+ 	struct usb_device_driver	*udriver;
++	int				status = 0;
+ 
+ 	if (udev->dev.power.power_state.event == PM_EVENT_ON)
+-		return 0;
+-
+-	/* mark things as "on" immediately, no matter what errors crop up */
+-	udev->dev.power.power_state.event = PM_EVENT_ON;
++		goto done;
+ 
+ 	if (udev->dev.driver == NULL)
+-		return 0;
++		goto done;
+ 	udriver = to_usb_device_driver(udev->dev.driver);
+ 	if (udev->state == USB_STATE_NOTATTACHED)
+-		return 0;
+-	return udriver->resume(udev);
++		goto done;
++	status = udriver->resume(udev);
++
++done:
++	if (status == 0)
++		udev->dev.power.power_state.event = PM_EVENT_ON;
++	return status;
+ }
+ 
+ /* Caller has locked intf's usb_device */
+ static int suspend_interface(struct usb_interface *intf, pm_message_t msg)
+ {
+ 	struct usb_driver	*driver;
+-	int			status;
++	int			status = 0;
+ 
+ 	if (intf->dev.driver == NULL)
+-		return 0;
++		goto done;
+ 
+ 	driver = to_usb_driver(intf->dev.driver);
+ 
+ 	/* with no hardware, USB interfaces only use FREEZE and ON states */
+ 	if (!is_active(intf))
+-		return 0;
++		goto done;
+ 
+ 	if (driver->suspend && driver->resume) {
+ 		status = driver->suspend(intf, msg);
+@@ -810,8 +819,11 @@ static int suspend_interface(struct usb_interface *intf, pm_message_t msg)
+ 		dev_warn(&intf->dev, "no suspend for driver %s?\n",
+ 				driver->name);
+ 		mark_quiesced(intf);
+-		status = 0;
+ 	}
++
++done:
++	if (status == 0)
++		intf->dev.power.power_state.event = msg.event;
+ 	return status;
+ }
+ 
+@@ -820,24 +832,19 @@ static int resume_interface(struct usb_interface *intf)
+ {
+ 	struct usb_driver	*driver;
+ 	struct usb_device	*udev;
+-	int			status;
++	int			status = 0;
+ 
+ 	if (intf->dev.power.power_state.event == PM_EVENT_ON)
+-		return 0;
+-
+-	/* mark things as "on" immediately, no matter what errors crop up */
+-	intf->dev.power.power_state.event = PM_EVENT_ON;
++		goto done;
+ 
+-	if (intf->dev.driver == NULL) {
+-		intf->dev.power.power_state.event = PM_EVENT_FREEZE;
+-		return 0;
+-	}
++	if (intf->dev.driver == NULL)
++		goto done;
+ 
+ 	driver = to_usb_driver(intf->dev.driver);
+ 
+ 	udev = interface_to_usbdev(intf);
+ 	if (udev->state == USB_STATE_NOTATTACHED)
+-		return 0;
++		goto done;
+ 
+ 	/* if driver was suspended, it has a resume method;
+ 	 * however, sysfs can wrongly mark things as suspended
+@@ -845,15 +852,21 @@ static int resume_interface(struct usb_interface *intf)
+ 	 */
+ 	if (driver->resume) {
+ 		status = driver->resume(intf);
+-		if (status) {
++		if (status)
+ 			dev_err(&intf->dev, "%s error %d\n",
+ 					"resume", status);
+-			mark_quiesced(intf);
+-		}
+-	} else
++		else
++			mark_active(intf);
++	} else {
+ 		dev_warn(&intf->dev, "no resume for driver %s?\n",
+ 				driver->name);
+-	return 0;
++		mark_active(intf);
++	}
++
++done:
++	if (status == 0)
++		intf->dev.power.power_state.event = PM_EVENT_ON;
++	return status;
+ }
+ 
+ /* Caller has locked udev */
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index a39112041e69..7af53db4d76f 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1582,9 +1582,10 @@ static int __usb_port_suspend (struct usb_device *udev, int port1)
+ 	if (udev->parent)
+ 		status = hub_port_suspend(hdev_to_hub(udev->parent), port1,
+ 				udev);
+-
+-	if (status == 0)
+-		udev->dev.power.power_state = PMSG_SUSPEND;
++	else {
++		dev_dbg(&udev->dev, "usb suspend\n");
++		usb_set_device_state(udev, USB_STATE_SUSPENDED);
++	}
+ 	return status;
+ }
+ 
+@@ -1617,8 +1618,6 @@ int usb_port_suspend(struct usb_device *udev)
+ 		return -ENODEV;
+ 	return __usb_port_suspend(udev, udev->portnum);
+ #else
+-	/* NOTE:  udev->state unchanged, it's not lying ... */
+-	udev->dev.power.power_state = PMSG_SUSPEND;
+ 	return 0;
+ #endif
+ }
+@@ -1647,7 +1646,6 @@ static int finish_port_resume(struct usb_device *udev)
+ 	usb_set_device_state(udev, udev->actconfig
+ 			? USB_STATE_CONFIGURED
+ 			: USB_STATE_ADDRESS);
+-	udev->dev.power.power_state = PMSG_ON;
+ 
+  	/* 10.5.4.5 says be sure devices in the tree are still there.
+  	 * For now let's assume the device didn't go crazy on resume,

commit 4d064c080265a41324d108fccc26b72106d43db3
+Author: Alan Stern 
+Date:   Sat Jul 1 22:11:44 2006 -0400
+
+    usbcore: track whether interfaces are suspended
+    
+    Currently we rely on intf->dev.power.power_state.event for tracking
+    whether intf is suspended.  This is not a reliable technique because
+    that value is owned by the PM core, not by usbcore.  This patch (as718b)
+    adds a new flag so that we can accurately tell which interfaces are
+    suspended and which aren't.
+    
+    At first one might think these flags aren't needed, since interfaces
+    will be suspended along with their devices.  It turns out there are a
+    couple of intermediate situations where that's not quite true, such as
+    while processing a remote-wakeup request.
+    
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index cc42972b6bb0..74df0db954c9 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -59,17 +59,17 @@ static inline int is_usb_device_driver(struct device_driver *drv)
+ 
+ static inline void mark_active(struct usb_interface *f)
+ {
+-	f->dev.power.power_state.event = PM_EVENT_ON;
++	f->is_active = 1;
+ }
+ 
+ static inline void mark_quiesced(struct usb_interface *f)
+ {
+-	f->dev.power.power_state.event = PM_EVENT_FREEZE;
++	f->is_active = 0;
+ }
+ 
+ static inline int is_active(struct usb_interface *f)
+ {
+-	return f->dev.power.power_state.event == PM_EVENT_ON;
++	return f->is_active;
+ }
+ 
+ 
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index b4ccce6d0982..e22f4b386605 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -102,6 +102,7 @@ enum usb_interface_condition {
+  *	number from the USB core by calling usb_register_dev().
+  * @condition: binding state of the interface: not bound, binding
+  *	(in probe()), bound to a driver, or unbinding (in disconnect())
++ * @is_active: flag set when the interface is bound and not suspended.
+  * @dev: driver model's view of this device
+  * @class_dev: driver model's class view of this device.
+  *
+@@ -142,6 +143,8 @@ struct usb_interface {
+ 	int minor;			/* minor number this interface is
+ 					 * bound to */
+ 	enum usb_interface_condition condition;		/* state of binding */
++	unsigned is_active:1;		/* the interface is not suspended */
++
+ 	struct device dev;		/* interface specific device info */
+ 	struct class_device *class_dev;
+ };

commit a8e7c5653562f88c0f5f53eac0a890c012655789
+Author: Alan Stern 
+Date:   Sat Jul 1 22:11:02 2006 -0400
+
+    usbcore: resume device resume recursion
+    
+    This patch (as717b) removes the existing recursion in hub resume code:
+    Resuming a hub will no longer automatically resume the devices attached
+    to the hub.
+    
+    At the same time, it adds one level of recursion: Suspending a USB
+    device will automatically suspend all the device's interfaces.  Failure
+    at an intermediate stage will cause all the already-suspended interfaces
+    to be resumed. Attempts to suspend or resume an interface by itself will
+    do nothing, although they won't return an error.  Thus the regular
+    system-suspend and system-resume procedures should continue to work as
+    before; only runtime PM will be affected.
+    
+    The patch also removes the code that tests state of the interfaces
+    before suspending a device.  It's no longer needed, since everything
+    gets suspended together.
+    
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index b0db1583c522..eefc98584eac 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -783,7 +783,7 @@ static int resume_device(struct usb_device *udev)
+ 	return udriver->resume(udev);
+ }
+ 
+-/* Caller has locked intf */
++/* Caller has locked intf's usb_device */
+ static int suspend_interface(struct usb_interface *intf, pm_message_t msg)
+ {
+ 	struct usb_driver	*driver;
+@@ -815,7 +815,7 @@ static int suspend_interface(struct usb_interface *intf, pm_message_t msg)
+ 	return status;
+ }
+ 
+-/* Caller has locked intf */
++/* Caller has locked intf's usb_device */
+ static int resume_interface(struct usb_interface *intf)
+ {
+ 	struct usb_driver	*driver;
+@@ -856,14 +856,59 @@ static int resume_interface(struct usb_interface *intf)
+ 	return 0;
+ }
+ 
++/* Caller has locked udev */
++int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
++{
++	int			status = 0;
++	int			i = 0;
++	struct usb_interface	*intf;
++
++	if (udev->actconfig) {
++		for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
++			intf = udev->actconfig->interface[i];
++			status = suspend_interface(intf, msg);
++			if (status != 0)
++				break;
++		}
++	}
++	if (status == 0)
++		status = suspend_device(udev, msg);
++
++	/* If the suspend failed, resume interfaces that did get suspended */
++	if (status != 0) {
++		while (--i >= 0) {
++			intf = udev->actconfig->interface[i];
++			resume_interface(intf);
++		}
++	}
++	return status;
++}
++
++/* Caller has locked udev */
++int usb_resume_both(struct usb_device *udev)
++{
++	int			status;
++	int			i;
++	struct usb_interface	*intf;
++
++	status = resume_device(udev);
++	if (status == 0 && udev->actconfig) {
++		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
++			intf = udev->actconfig->interface[i];
++			resume_interface(intf);
++		}
++	}
++	return status;
++}
++
+ static int usb_suspend(struct device *dev, pm_message_t message)
+ {
+ 	int	status;
+ 
+ 	if (is_usb_device(dev))
+-		status = suspend_device(to_usb_device(dev), message);
++		status = usb_suspend_both(to_usb_device(dev), message);
+ 	else
+-		status = suspend_interface(to_usb_interface(dev), message);
++		status = 0;
+ 	return status;
+ }
+ 
+@@ -871,10 +916,12 @@ static int usb_resume(struct device *dev)
+ {
+ 	int	status;
+ 
+-	if (is_usb_device(dev))
+-		status = resume_device(to_usb_device(dev));
+-	else
+-		status = resume_interface(to_usb_interface(dev));
++	if (is_usb_device(dev)) {
++		status = usb_resume_both(to_usb_device(dev));
++
++		/* Rebind drivers that had no suspend method? */
++	} else
++		status = 0;
+ 	return status;
+ }
+ 
+diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
+index 1522195de715..b6dacd7551d2 100644
+--- a/drivers/usb/core/generic.c
++++ b/drivers/usb/core/generic.c
+@@ -184,22 +184,8 @@ static void generic_disconnect(struct usb_device *udev)
+ 
+ #ifdef	CONFIG_PM
+ 
+-static int verify_suspended(struct device *dev, void *unused)
+-{
+-	if (dev->driver == NULL)
+-		return 0;
+-	return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0;
+-}
+-
+ static int generic_suspend(struct usb_device *udev, pm_message_t msg)
+ {
+-	int	status;
+-
+-	/* rule out bogus requests through sysfs */
+-	status = device_for_each_child(&udev->dev, NULL, verify_suspended);
+-	if (status)
+-		return status;
+-
+ 	/* USB devices enter SUSPEND state through their hubs, but can be
+ 	 * marked for FREEZE as soon as their children are already idled.
+ 	 * But those semantics are useless, so we equate the two (sigh).
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index a372332440b2..a39112041e69 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1662,9 +1662,6 @@ static int finish_port_resume(struct usb_device *udev)
+ 			"gone after usb resume? status %d\n",
+ 			status);
+ 	else if (udev->actconfig) {
+-		unsigned	i;
+-		int		(*resume)(struct device *);
+-
+ 		le16_to_cpus(&devstatus);
+ 		if ((devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP))
+ 				&& udev->parent) {
+@@ -1675,24 +1672,9 @@ static int finish_port_resume(struct usb_device *udev)
+ 					USB_DEVICE_REMOTE_WAKEUP, 0,
+ 					NULL, 0,
+ 					USB_CTRL_SET_TIMEOUT);
+-			if (status) {
++			if (status)
+ 				dev_dbg(&udev->dev, "disable remote "
+ 					"wakeup, status %d\n", status);
+-				status = 0;
+-			}
+-		}
+-
+-		/* resume interface drivers; if this is a hub, it
+-		 * may have a child resume event to deal with soon
+-		 */
+-		resume = udev->dev.bus->resume;
+-		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+-			struct device *dev =
+-					&udev->actconfig->interface[i]->dev;
+-
+-			down(&dev->sem);
+-			(void) resume(dev);
+-			up(&dev->sem);
+ 		}
+ 		status = 0;
+ 
+@@ -1802,15 +1784,7 @@ int usb_port_resume(struct usb_device *udev)
+ 	} else
+ 		status = finish_port_resume(udev);
+ 	if (status < 0)
+-		dev_dbg(&udev->dev, "can't resume, status %d\n",
+-			status);
+-
+-	/* rebind drivers that had no suspend() */
+-	if (status == 0) {
+-		usb_unlock_device(udev);
+-		bus_rescan_devices(&usb_bus_type);
+-		usb_lock_device(udev);
+-	}
++		dev_dbg(&udev->dev, "can't resume, status %d\n", status);
+ 	return status;
+ }
+ 
+@@ -1830,6 +1804,9 @@ static int remote_wakeup(struct usb_device *udev)
+ 		msleep(10);
+ 		status = finish_port_resume(udev);
+ 	}
++
++	if (status == 0)
++		usb_resume_both(udev);
+ 	usb_unlock_device(udev);
+ #endif
+ 	return status;
+@@ -1901,51 +1878,8 @@ static int hub_resume(struct usb_interface *intf)
+ 		}
+ 	}
+ 
++	/* tell khubd to look for changes on this hub */
+ 	hub_activate(hub);
+-
+-	/* REVISIT:  this recursion probably shouldn't exist.  Remove
+-	 * this code sometime, after retesting with different root and
+-	 * external hubs.
+-	 */
+-#ifdef	CONFIG_USB_SUSPEND
+-	{
+-	unsigned		port1;
+-
+-	for (port1 = 1; port1 <= hdev->maxchild; port1++) {
+-		struct usb_device	*udev;
+-		u16			portstat, portchange;
+-
+-		udev = hdev->children [port1-1];
+-		status = hub_port_status(hub, port1, &portstat, &portchange);
+-		if (status == 0) {
+-			if (portchange & USB_PORT_STAT_C_SUSPEND) {
+-				clear_port_feature(hdev, port1,
+-					USB_PORT_FEAT_C_SUSPEND);
+-				portchange &= ~USB_PORT_STAT_C_SUSPEND;
+-			}
+-
+-			/* let khubd handle disconnects etc */
+-			if (portchange)
+-				continue;
+-		}
+-
+-		if (!udev || status < 0)
+-			continue;
+-		usb_lock_device(udev);
+-		if (portstat & USB_PORT_STAT_SUSPEND)
+-			status = hub_port_resume(hub, port1, udev);
+-		else {
+-			status = finish_port_resume(udev);
+-			if (status < 0) {
+-				dev_dbg(&intf->dev, "resume port %d --> %d\n",
+-					port1, status);
+-				hub_port_logical_disconnect(hub, port1);
+-			}
+-		}
+-		usb_unlock_device(udev);
+-	}
+-	}
+-#endif
+ 	return 0;
+ }
+ 
+@@ -2602,17 +2536,6 @@ static void hub_events(void)
+ 		usb_get_intf(intf);
+ 		spin_unlock_irq(&hub_event_lock);
+ 
+-		/* Is this is a root hub wanting to reactivate the downstream
+-		 * ports?  If so, be sure the interface resumes even if its
+-		 * stub "device" node was never suspended.
+-		 */
+-		if (i) {
+-			dpm_runtime_resume(&hdev->dev);
+-			dpm_runtime_resume(&intf->dev);
+-			usb_put_intf(intf);
+-			continue;
+-		}
+-
+ 		/* Lock the device, then check to see if we were
+ 		 * disconnected while waiting for the lock to succeed. */
+ 		if (locktree(hdev) < 0) {
+@@ -2629,6 +2552,13 @@ static void hub_events(void)
+ 			goto loop;
+ 		}
+ 
++		/* Is this is a root hub wanting to reactivate the downstream
++		 * ports?  If so, be sure the interface resumes even if its
++		 * stub "device" node was never suspended.
++		 */
++		if (i)
++			usb_resume_both(hdev);
++
+ 		/* If this is an inactive or suspended hub, do nothing */
+ 		if (hub->quiescing)
+ 			goto loop;
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 1d25ccac7832..cc42972b6bb0 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -30,6 +30,8 @@ extern void usb_major_cleanup(void);
+ extern int usb_host_init(void);
+ extern void usb_host_cleanup(void);
+ 
++extern int usb_suspend_both(struct usb_device *udev, pm_message_t msg);
++extern int usb_resume_both(struct usb_device *udev);
+ extern int usb_port_suspend(struct usb_device *dev);
+ extern int usb_port_resume(struct usb_device *dev);
+ 

commit 1cc8a25d5b680ff656927ffa9b66fae6b415b1d3
+Author: Alan Stern 
+Date:   Sat Jul 1 22:10:15 2006 -0400
+
+    usbcore: split suspend/resume for device and interfaces
+    
+    This patch (as716b) splits up the core suspend and resume routines into
+    two parts each: one for handling devices and one for handling
+    interfaces.  The behavior of the parts should be the same as in the old
+    unified code.
+    
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index a62de0a85406..b0db1583c522 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -751,81 +751,89 @@ EXPORT_SYMBOL_GPL_FUTURE(usb_deregister);
+ 
+ #ifdef CONFIG_PM
+ 
+-static int usb_suspend(struct device *dev, pm_message_t message)
++/* Caller has locked udev */
++static int suspend_device(struct usb_device *udev, pm_message_t msg)
+ {
+-	struct usb_device		*udev;
+ 	struct usb_device_driver	*udriver;
+-	struct usb_interface		*intf;
+-	struct usb_driver		*driver;
+-	int				status;
+ 
+-	if (is_usb_device(dev)) {
+-		if (dev->driver == NULL)
+-			return 0;
+-		udev = to_usb_device(dev);
+-		udriver = to_usb_device_driver(dev->driver);
+-		if (dev->power.power_state.event == message.event)
+-			return 0;
+-		return udriver->suspend(udev, message);
+-	}
++	if (udev->dev.driver == NULL)
++		return 0;
++	udriver = to_usb_device_driver(udev->dev.driver);
++	if (udev->dev.power.power_state.event == msg.event)
++		return 0;
++	return udriver->suspend(udev, msg);
++}
++
++/* Caller has locked udev */
++static int resume_device(struct usb_device *udev)
++{
++	struct usb_device_driver	*udriver;
+ 
+-	if (dev->driver == NULL)
++	if (udev->dev.power.power_state.event == PM_EVENT_ON)
+ 		return 0;
+ 
+-	intf = to_usb_interface(dev);
+-	driver = to_usb_driver(dev->driver);
++	/* mark things as "on" immediately, no matter what errors crop up */
++	udev->dev.power.power_state.event = PM_EVENT_ON;
++
++	if (udev->dev.driver == NULL)
++		return 0;
++	udriver = to_usb_device_driver(udev->dev.driver);
++	if (udev->state == USB_STATE_NOTATTACHED)
++		return 0;
++	return udriver->resume(udev);
++}
++
++/* Caller has locked intf */
++static int suspend_interface(struct usb_interface *intf, pm_message_t msg)
++{
++	struct usb_driver	*driver;
++	int			status;
++
++	if (intf->dev.driver == NULL)
++		return 0;
++
++	driver = to_usb_driver(intf->dev.driver);
+ 
+ 	/* with no hardware, USB interfaces only use FREEZE and ON states */
+ 	if (!is_active(intf))
+ 		return 0;
+ 
+ 	if (driver->suspend && driver->resume) {
+-		status = driver->suspend(intf, message);
++		status = driver->suspend(intf, msg);
+ 		if (status)
+-			dev_err(dev, "%s error %d\n", "suspend", status);
++			dev_err(&intf->dev, "%s error %d\n",
++					"suspend", status);
+ 		else
+ 			mark_quiesced(intf);
+ 	} else {
+ 		// FIXME else if there's no suspend method, disconnect...
+-		dev_warn(dev, "no suspend for driver %s?\n", driver->name);
++		dev_warn(&intf->dev, "no suspend for driver %s?\n",
++				driver->name);
+ 		mark_quiesced(intf);
+ 		status = 0;
+ 	}
+ 	return status;
+ }
+ 
+-static int usb_resume(struct device *dev)
++/* Caller has locked intf */
++static int resume_interface(struct usb_interface *intf)
+ {
+-	struct usb_device		*udev;
+-	struct usb_device_driver	*udriver;
+-	struct usb_interface		*intf;
+-	struct usb_driver		*driver;
+-	int				status;
++	struct usb_driver	*driver;
++	struct usb_device	*udev;
++	int			status;
+ 
+-	if (dev->power.power_state.event == PM_EVENT_ON)
++	if (intf->dev.power.power_state.event == PM_EVENT_ON)
+ 		return 0;
+ 
+ 	/* mark things as "on" immediately, no matter what errors crop up */
+-	dev->power.power_state.event = PM_EVENT_ON;
++	intf->dev.power.power_state.event = PM_EVENT_ON;
+ 
+-	/* devices resume through their hubs */
+-	if (is_usb_device(dev)) {
+-		if (dev->driver == NULL)
+-			return 0;
+-		udev = to_usb_device(dev);
+-		udriver = to_usb_device_driver(dev->driver);
+-		if (udev->state == USB_STATE_NOTATTACHED)
+-			return 0;
+-		return udriver->resume(udev);
+-	}
+-
+-	if (dev->driver == NULL) {
+-		dev->power.power_state.event = PM_EVENT_FREEZE;
++	if (intf->dev.driver == NULL) {
++		intf->dev.power.power_state.event = PM_EVENT_FREEZE;
+ 		return 0;
+ 	}
+ 
+-	intf = to_usb_interface(dev);
+-	driver = to_usb_driver(dev->driver);
++	driver = to_usb_driver(intf->dev.driver);
+ 
+ 	udev = interface_to_usbdev(intf);
+ 	if (udev->state == USB_STATE_NOTATTACHED)
+@@ -838,14 +846,38 @@ static int usb_resume(struct device *dev)
+ 	if (driver->resume) {
+ 		status = driver->resume(intf);
+ 		if (status) {
+-			dev_err(dev, "%s error %d\n", "resume", status);
++			dev_err(&intf->dev, "%s error %d\n",
++					"resume", status);
+ 			mark_quiesced(intf);
+ 		}
+ 	} else
+-		dev_warn(dev, "no resume for driver %s?\n", driver->name);
++		dev_warn(&intf->dev, "no resume for driver %s?\n",
++				driver->name);
+ 	return 0;
+ }
+ 
++static int usb_suspend(struct device *dev, pm_message_t message)
++{
++	int	status;
++
++	if (is_usb_device(dev))
++		status = suspend_device(to_usb_device(dev), message);
++	else
++		status = suspend_interface(to_usb_interface(dev), message);
++	return status;
++}
++
++static int usb_resume(struct device *dev)
++{
++	int	status;
++
++	if (is_usb_device(dev))
++		status = resume_device(to_usb_device(dev));
++	else
++		status = resume_interface(to_usb_interface(dev));
++	return status;
++}
++
+ #endif /* CONFIG_PM */
+ 
+ struct bus_type usb_bus_type = {

commit 782da727b0d59e93c84a627948b1535a3db90392
+Author: Alan Stern 
+Date:   Sat Jul 1 22:09:35 2006 -0400
+
+    usbcore: make usb_generic a usb_device_driver
+    
+    This patch (as714b) makes usb_generic into a usb_device_driver capable
+    of being probed and unbound, just like other drivers.  A fair amount of
+    the work that used to get done during discovery or removal of a USB
+    device have been moved to the probe and disconnect methods of
+    usb_generic: creating the sysfs attributes and selecting an initial
+    configuration.  However the normal behavior should continue to be the
+    same as before.
+    
+    We will now have the possibility of creating other USB device drivers,
+    They will assist with exporting devices to remote systems
+    (USB-over-TCPIP) or to paravirtual guest operating systems.
+    
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 0d4b5dcee3ab..a62de0a85406 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -530,9 +530,10 @@ static int usb_uevent(struct device *dev, char **envp, int num_envp,
+ 	/* driver is often null here; dev_dbg() would oops */
+ 	pr_debug ("usb %s: uevent\n", dev->bus_id);
+ 
+-	if (is_usb_device(dev))
+-		return 0;
+-	else {
++	if (is_usb_device(dev)) {
++		usb_dev = to_usb_device(dev);
++		alt = NULL;
++	} else {
+ 		intf = to_usb_interface(dev);
+ 		usb_dev = interface_to_usbdev(intf);
+ 		alt = intf->cur_altsetting;
+@@ -579,15 +580,17 @@ static int usb_uevent(struct device *dev, char **envp, int num_envp,
+ 			   usb_dev->descriptor.bDeviceProtocol))
+ 		return -ENOMEM;
+ 
+-	if (add_uevent_var(envp, num_envp, &i,
++	if (!is_usb_device(dev)) {
++
++		if (add_uevent_var(envp, num_envp, &i,
+ 			   buffer, buffer_size, &length,
+ 			   "INTERFACE=%d/%d/%d",
+ 			   alt->desc.bInterfaceClass,
+ 			   alt->desc.bInterfaceSubClass,
+ 			   alt->desc.bInterfaceProtocol))
+-		return -ENOMEM;
++			return -ENOMEM;
+ 
+-	if (add_uevent_var(envp, num_envp, &i,
++		if (add_uevent_var(envp, num_envp, &i,
+ 			   buffer, buffer_size, &length,
+ 			   "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
+ 			   le16_to_cpu(usb_dev->descriptor.idVendor),
+@@ -599,7 +602,8 @@ static int usb_uevent(struct device *dev, char **envp, int num_envp,
+ 			   alt->desc.bInterfaceClass,
+ 			   alt->desc.bInterfaceSubClass,
+ 			   alt->desc.bInterfaceProtocol))
+-		return -ENOMEM;
++			return -ENOMEM;
++	}
+ 
+ 	envp[i] = NULL;
+ 
+@@ -747,31 +751,22 @@ EXPORT_SYMBOL_GPL_FUTURE(usb_deregister);
+ 
+ #ifdef CONFIG_PM
+ 
+-static int verify_suspended(struct device *dev, void *unused)
++static int usb_suspend(struct device *dev, pm_message_t message)
+ {
+-	if (dev->driver == NULL)
+-		return 0;
+-	return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0;
+-}
++	struct usb_device		*udev;
++	struct usb_device_driver	*udriver;
++	struct usb_interface		*intf;
++	struct usb_driver		*driver;
++	int				status;
+ 
+-static int usb_generic_suspend(struct device *dev, pm_message_t message)
+-{
+-	struct usb_interface	*intf;
+-	struct usb_driver	*driver;
+-	int			status;
+-
+-	/* USB devices enter SUSPEND state through their hubs, but can be
+-	 * marked for FREEZE as soon as their children are already idled.
+-	 * But those semantics are useless, so we equate the two (sigh).
+-	 */
+ 	if (is_usb_device(dev)) {
++		if (dev->driver == NULL)
++			return 0;
++		udev = to_usb_device(dev);
++		udriver = to_usb_device_driver(dev->driver);
+ 		if (dev->power.power_state.event == message.event)
+ 			return 0;
+-		/* we need to rule out bogus requests through sysfs */
+-		status = device_for_each_child(dev, NULL, verify_suspended);
+-		if (status)
+-			return status;
+- 		return usb_port_suspend(to_usb_device(dev));
++		return udriver->suspend(udev, message);
+ 	}
+ 
+ 	if (dev->driver == NULL)
+@@ -799,12 +794,13 @@ static int usb_generic_suspend(struct device *dev, pm_message_t message)
+ 	return status;
+ }
+ 
+-static int usb_generic_resume(struct device *dev)
++static int usb_resume(struct device *dev)
+ {
+-	struct usb_interface	*intf;
+-	struct usb_driver	*driver;
+-	struct usb_device	*udev;
+-	int			status;
++	struct usb_device		*udev;
++	struct usb_device_driver	*udriver;
++	struct usb_interface		*intf;
++	struct usb_driver		*driver;
++	int				status;
+ 
+ 	if (dev->power.power_state.event == PM_EVENT_ON)
+ 		return 0;
+@@ -814,10 +810,13 @@ static int usb_generic_resume(struct device *dev)
+ 
+ 	/* devices resume through their hubs */
+ 	if (is_usb_device(dev)) {
++		if (dev->driver == NULL)
++			return 0;
+ 		udev = to_usb_device(dev);
++		udriver = to_usb_device_driver(dev->driver);
+ 		if (udev->state == USB_STATE_NOTATTACHED)
+ 			return 0;
+-		return usb_port_resume(udev);
++		return udriver->resume(udev);
+ 	}
+ 
+ 	if (dev->driver == NULL) {
+@@ -854,7 +853,7 @@ struct bus_type usb_bus_type = {
+ 	.match =	usb_device_match,
+ 	.uevent =	usb_uevent,
+ #ifdef CONFIG_PM
+-	.suspend =	usb_generic_suspend,
+-	.resume =	usb_generic_resume,
++	.suspend =	usb_suspend,
++	.resume =	usb_resume,
+ #endif
+ };
+diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
+index fa6f34a12b4b..1522195de715 100644
+--- a/drivers/usb/core/generic.c
++++ b/drivers/usb/core/generic.c
+@@ -21,24 +21,208 @@
+ #include 
+ #include "usb.h"
+ 
++static inline const char *plural(int n)
++{
++	return (n == 1 ? "" : "s");
++}
++
++static int choose_configuration(struct usb_device *udev)
++{
++	int i;
++	int num_configs;
++	int insufficient_power = 0;
++	struct usb_host_config *c, *best;
++
++	best = NULL;
++	c = udev->config;
++	num_configs = udev->descriptor.bNumConfigurations;
++	for (i = 0; i < num_configs; (i++, c++)) {
++		struct usb_interface_descriptor	*desc = NULL;
++
++		/* It's possible that a config has no interfaces! */
++		if (c->desc.bNumInterfaces > 0)
++			desc = &c->intf_cache[0]->altsetting->desc;
++
++		/*
++		 * HP's USB bus-powered keyboard has only one configuration
++		 * and it claims to be self-powered; other devices may have
++		 * similar errors in their descriptors.  If the next test
++		 * were allowed to execute, such configurations would always
++		 * be rejected and the devices would not work as expected.
++		 * In the meantime, we run the risk of selecting a config
++		 * that requires external power at a time when that power
++		 * isn't available.  It seems to be the lesser of two evils.
++		 *
++		 * Bugzilla #6448 reports a device that appears to crash
++		 * when it receives a GET_DEVICE_STATUS request!  We don't
++		 * have any other way to tell whether a device is self-powered,
++		 * but since we don't use that information anywhere but here,
++		 * the call has been removed.
++		 *
++		 * Maybe the GET_DEVICE_STATUS call and the test below can
++		 * be reinstated when device firmwares become more reliable.
++		 * Don't hold your breath.
++		 */
++#if 0
++		/* Rule out self-powered configs for a bus-powered device */
++		if (bus_powered && (c->desc.bmAttributes &
++					USB_CONFIG_ATT_SELFPOWER))
++			continue;
++#endif
++
++		/*
++		 * The next test may not be as effective as it should be.
++		 * Some hubs have errors in their descriptor, claiming
++		 * to be self-powered when they are really bus-powered.
++		 * We will overestimate the amount of current such hubs
++		 * make available for each port.
++		 *
++		 * This is a fairly benign sort of failure.  It won't
++		 * cause us to reject configurations that we should have
++		 * accepted.
++		 */
++
++		/* Rule out configs that draw too much bus current */
++		if (c->desc.bMaxPower * 2 > udev->bus_mA) {
++			insufficient_power++;
++			continue;
++		}
++
++		/* If the first config's first interface is COMM/2/0xff
++		 * (MSFT RNDIS), rule it out unless Linux has host-side
++		 * RNDIS support. */
++		if (i == 0 && desc
++				&& desc->bInterfaceClass == USB_CLASS_COMM
++				&& desc->bInterfaceSubClass == 2
++				&& desc->bInterfaceProtocol == 0xff) {
++#ifndef CONFIG_USB_NET_RNDIS_HOST
++			continue;
++#else
++			best = c;
++#endif
++		}
++
++		/* From the remaining configs, choose the first one whose
++		 * first interface is for a non-vendor-specific class.
++		 * Reason: Linux is more likely to have a class driver
++		 * than a vendor-specific driver. */
++		else if (udev->descriptor.bDeviceClass !=
++						USB_CLASS_VENDOR_SPEC &&
++				(!desc || desc->bInterfaceClass !=
++						USB_CLASS_VENDOR_SPEC)) {
++			best = c;
++			break;
++		}
++
++		/* If all the remaining configs are vendor-specific,
++		 * choose the first one. */
++		else if (!best)
++			best = c;
++	}
++
++	if (insufficient_power > 0)
++		dev_info(&udev->dev, "rejected %d configuration%s "
++			"due to insufficient available bus power\n",
++			insufficient_power, plural(insufficient_power));
++
++	if (best) {
++		i = best->desc.bConfigurationValue;
++		dev_info(&udev->dev,
++			"configuration #%d chosen from %d choice%s\n",
++			i, num_configs, plural(num_configs));
++	} else {
++		i = -1;
++		dev_warn(&udev->dev,
++			"no configuration chosen from %d choice%s\n",
++			num_configs, plural(num_configs));
++	}
++	return i;
++}
++
+ static int generic_probe(struct usb_device *udev)
+ {
++	int err, c;
++
++	/* put device-specific files into sysfs */
++	usb_create_sysfs_dev_files(udev);
++
++	/* Choose and set the configuration.  This registers the interfaces
++	 * with the driver core and lets interface drivers bind to them.
++	 */
++	c = choose_configuration(udev);
++	if (c >= 0) {
++		err = usb_set_configuration(udev, c);
++		if (err) {
++			dev_err(&udev->dev, "can't set config #%d, error %d\n",
++					c, err);
++			/* This need not be fatal.  The user can try to
++			 * set other configurations. */
++		}
++	}
++
++	/* USB device state == configured ... usable */
++	usb_notify_add_device(udev);
++
+ 	return 0;
+ }
++
+ static void generic_disconnect(struct usb_device *udev)
+ {
++	usb_notify_remove_device(udev);
++
+ 	/* if this is only an unbind, not a physical disconnect, then
+ 	 * unconfigure the device */
+ 	if (udev->state == USB_STATE_CONFIGURED)
+ 		usb_set_configuration(udev, 0);
+ 
++	usb_remove_sysfs_dev_files(udev);
++
+ 	/* in case the call failed or the device was suspended */
+ 	if (udev->state >= USB_STATE_CONFIGURED)
+ 		usb_disable_device(udev, 0);
+ }
+ 
++#ifdef	CONFIG_PM
++
++static int verify_suspended(struct device *dev, void *unused)
++{
++	if (dev->driver == NULL)
++		return 0;
++	return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0;
++}
++
++static int generic_suspend(struct usb_device *udev, pm_message_t msg)
++{
++	int	status;
++
++	/* rule out bogus requests through sysfs */
++	status = device_for_each_child(&udev->dev, NULL, verify_suspended);
++	if (status)
++		return status;
++
++	/* USB devices enter SUSPEND state through their hubs, but can be
++	 * marked for FREEZE as soon as their children are already idled.
++	 * But those semantics are useless, so we equate the two (sigh).
++	 */
++	return usb_port_suspend(udev);
++}
++
++static int generic_resume(struct usb_device *udev)
++{
++	if (udev->state == USB_STATE_NOTATTACHED)
++		return 0;
++
++	return usb_port_resume(udev);
++}
++
++#endif	/* CONFIG_PM */
++
+ struct usb_device_driver usb_generic_driver = {
+ 	.name =	"usb",
+ 	.probe = generic_probe,
+ 	.disconnect = generic_disconnect,
++#ifdef	CONFIG_PM
++	.suspend = generic_suspend,
++	.resume = generic_resume,
++#endif
+ };
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index b00514d9a605..a372332440b2 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1148,144 +1148,28 @@ void usb_disconnect(struct usb_device **pdev)
+ 	 * cleaning up all state associated with the current configuration
+ 	 * so that the hardware is now fully quiesced.
+ 	 */
++	dev_dbg (&udev->dev, "unregistering device\n");
+ 	usb_disable_device(udev, 0);
+ 
+-	usb_notify_remove_device(udev);
++	usb_unlock_device(udev);
++
++	/* Unregister the device.  The device driver is responsible
++	 * for removing the device files from usbfs and sysfs and for
++	 * de-configuring the device.
++	 */
++	device_del(&udev->dev);
+ 
+-	/* Free the device number, remove the /proc/bus/usb entry and
+-	 * the sysfs attributes, and delete the parent's children[]
++	/* Free the device number and delete the parent's children[]
+ 	 * (or root_hub) pointer.
+ 	 */
+-	dev_dbg (&udev->dev, "unregistering device\n");
+ 	release_address(udev);
+-	usb_remove_sysfs_dev_files(udev);
+ 
+ 	/* Avoid races with recursively_mark_NOTATTACHED() */
+ 	spin_lock_irq(&device_state_lock);
+ 	*pdev = NULL;
+ 	spin_unlock_irq(&device_state_lock);
+ 
+-	usb_unlock_device(udev);
+-
+-	device_unregister(&udev->dev);
+-}
+-
+-static inline const char *plural(int n)
+-{
+-	return (n == 1 ? "" : "s");
+-}
+-
+-static int choose_configuration(struct usb_device *udev)
+-{
+-	int i;
+-	int num_configs;
+-	int insufficient_power = 0;
+-	struct usb_host_config *c, *best;
+-
+-	best = NULL;
+-	c = udev->config;
+-	num_configs = udev->descriptor.bNumConfigurations;
+-	for (i = 0; i < num_configs; (i++, c++)) {
+-		struct usb_interface_descriptor	*desc = NULL;
+-
+-		/* It's possible that a config has no interfaces! */
+-		if (c->desc.bNumInterfaces > 0)
+-			desc = &c->intf_cache[0]->altsetting->desc;
+-
+-		/*
+-		 * HP's USB bus-powered keyboard has only one configuration
+-		 * and it claims to be self-powered; other devices may have
+-		 * similar errors in their descriptors.  If the next test
+-		 * were allowed to execute, such configurations would always
+-		 * be rejected and the devices would not work as expected.
+-		 * In the meantime, we run the risk of selecting a config
+-		 * that requires external power at a time when that power
+-		 * isn't available.  It seems to be the lesser of two evils.
+-		 *
+-		 * Bugzilla #6448 reports a device that appears to crash
+-		 * when it receives a GET_DEVICE_STATUS request!  We don't
+-		 * have any other way to tell whether a device is self-powered,
+-		 * but since we don't use that information anywhere but here,
+-		 * the call has been removed.
+-		 *
+-		 * Maybe the GET_DEVICE_STATUS call and the test below can
+-		 * be reinstated when device firmwares become more reliable.
+-		 * Don't hold your breath.
+-		 */
+-#if 0
+-		/* Rule out self-powered configs for a bus-powered device */
+-		if (bus_powered && (c->desc.bmAttributes &
+-					USB_CONFIG_ATT_SELFPOWER))
+-			continue;
+-#endif
+-
+-		/*
+-		 * The next test may not be as effective as it should be.
+-		 * Some hubs have errors in their descriptor, claiming
+-		 * to be self-powered when they are really bus-powered.
+-		 * We will overestimate the amount of current such hubs
+-		 * make available for each port.
+-		 *
+-		 * This is a fairly benign sort of failure.  It won't
+-		 * cause us to reject configurations that we should have
+-		 * accepted.
+-		 */
+-
+-		/* Rule out configs that draw too much bus current */
+-		if (c->desc.bMaxPower * 2 > udev->bus_mA) {
+-			insufficient_power++;
+-			continue;
+-		}
+-
+-		/* If the first config's first interface is COMM/2/0xff
+-		 * (MSFT RNDIS), rule it out unless Linux has host-side
+-		 * RNDIS support. */
+-		if (i == 0 && desc
+-				&& desc->bInterfaceClass == USB_CLASS_COMM
+-				&& desc->bInterfaceSubClass == 2
+-				&& desc->bInterfaceProtocol == 0xff) {
+-#ifndef CONFIG_USB_NET_RNDIS_HOST
+-			continue;
+-#else
+-			best = c;
+-#endif
+-		}
+-
+-		/* From the remaining configs, choose the first one whose
+-		 * first interface is for a non-vendor-specific class.
+-		 * Reason: Linux is more likely to have a class driver
+-		 * than a vendor-specific driver. */
+-		else if (udev->descriptor.bDeviceClass !=
+-						USB_CLASS_VENDOR_SPEC &&
+-				(!desc || desc->bInterfaceClass !=
+-						USB_CLASS_VENDOR_SPEC)) {
+-			best = c;
+-			break;
+-		}
+-
+-		/* If all the remaining configs are vendor-specific,
+-		 * choose the first one. */
+-		else if (!best)
+-			best = c;
+-	}
+-
+-	if (insufficient_power > 0)
+-		dev_info(&udev->dev, "rejected %d configuration%s "
+-			"due to insufficient available bus power\n",
+-			insufficient_power, plural(insufficient_power));
+-
+-	if (best) {
+-		i = best->desc.bConfigurationValue;
+-		dev_info(&udev->dev,
+-			"configuration #%d chosen from %d choice%s\n",
+-			i, num_configs, plural(num_configs));
+-	} else {
+-		i = -1;
+-		dev_warn(&udev->dev,
+-			"no configuration chosen from %d choice%s\n",
+-			num_configs, plural(num_configs));
+-	}
+-	return i;
++	put_device(&udev->dev);
+ }
+ 
+ #ifdef DEBUG
+@@ -1328,7 +1212,6 @@ static inline void show_string(struct usb_device *udev, char *id, char *string)
+ int usb_new_device(struct usb_device *udev)
+ {
+ 	int err;
+-	int c;
+ 
+ 	err = usb_get_configuration(udev);
+ 	if (err < 0) {
+@@ -1418,34 +1301,15 @@ int usb_new_device(struct usb_device *udev)
+ 	}
+ #endif
+ 
+-	/* put device-specific files into sysfs */
++	/* Register the device.  The device driver is responsible
++	 * for adding the device files to usbfs and sysfs and for
++	 * configuring the device.
++	 */
+ 	err = device_add (&udev->dev);
+ 	if (err) {
+ 		dev_err(&udev->dev, "can't device_add, error %d\n", err);
+ 		goto fail;
+ 	}
+-	usb_create_sysfs_dev_files (udev);
+-
+-	usb_lock_device(udev);
+-
+-	/* choose and set the configuration. that registers the interfaces
+-	 * with the driver core, and lets usb device drivers bind to them.
+-	 */
+-	c = choose_configuration(udev);
+-	if (c >= 0) {
+-		err = usb_set_configuration(udev, c);
+-		if (err) {
+-			dev_err(&udev->dev, "can't set config #%d, error %d\n",
+-					c, err);
+-			/* This need not be fatal.  The user can try to
+-			 * set other configurations. */
+-		}
+-	}
+-
+-	/* USB device state == configured ... usable */
+-	usb_notify_add_device(udev);
+-
+-	usb_unlock_device(udev);
+ 
+ 	return 0;
+ 
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 6dfbc284369b..9ebfc0fe819d 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -205,7 +205,6 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
+ 	device_initialize(&dev->dev);
+ 	dev->dev.bus = &usb_bus_type;
+ 	dev->dev.dma_mask = bus->controller->dma_mask;
+-	dev->dev.driver = &usb_generic_driver.drvwrap.driver;
+ 	dev->dev.release = usb_release_dev;
+ 	dev->state = USB_STATE_ATTACHED;
+ 

commit 8bb54ab573ecd1b4fe2ed66416a8d99a86e65316
+Author: Alan Stern 
+Date:   Sat Jul 1 22:08:49 2006 -0400
+
+    usbcore: add usb_device_driver definition
+    
+    This patch (as732) adds a usb_device_driver structure, for representing
+    drivers that manage an entire USB device as opposed to just an
+    interface.  Support routines like usb_register_device_driver,
+    usb_deregister_device_driver, usb_probe_device, and usb_unbind_device
+    are also added.
+    
+    Unlike an earlier version of this patch, the new code is type-safe.  To
+    accomplish this, the existing struct driver embedded in struct
+    usb_driver had to be wrapped in an intermediate wrapper.  This enables
+    the core to tell at runtime whether a particular struct driver belongs
+    to a device driver or to an interface driver.
+    
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 8dcf2cd0c569..0d4b5dcee3ab 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -84,7 +84,7 @@ static int usb_create_newid_file(struct usb_driver *usb_drv)
+ 		goto exit;
+ 
+ 	if (usb_drv->probe != NULL)
+-		error = sysfs_create_file(&usb_drv->driver.kobj,
++		error = sysfs_create_file(&usb_drv->drvwrap.driver.kobj,
+ 					  &driver_attr_new_id.attr);
+ exit:
+ 	return error;
+@@ -96,7 +96,7 @@ static void usb_remove_newid_file(struct usb_driver *usb_drv)
+ 		return;
+ 
+ 	if (usb_drv->probe != NULL)
+-		sysfs_remove_file(&usb_drv->driver.kobj,
++		sysfs_remove_file(&usb_drv->drvwrap.driver.kobj,
+ 				  &driver_attr_new_id.attr);
+ }
+ 
+@@ -143,18 +143,55 @@ static const struct usb_device_id *usb_match_dynamic_id(struct usb_interface *in
+ }
+ 
+ 
+-/* called from driver core with usb_bus_type.subsys writelock */
++/* called from driver core with dev locked */
++static int usb_probe_device(struct device *dev)
++{
++	struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);
++	struct usb_device *udev;
++	int error = -ENODEV;
++
++	dev_dbg(dev, "%s\n", __FUNCTION__);
++
++	if (!is_usb_device(dev))	/* Sanity check */
++		return error;
++
++	udev = to_usb_device(dev);
++
++	/* FIXME: resume a suspended device */
++	if (udev->state == USB_STATE_SUSPENDED)
++		return -EHOSTUNREACH;
++
++	/* TODO: Add real matching code */
++
++	error = udriver->probe(udev);
++	return error;
++}
++
++/* called from driver core with dev locked */
++static int usb_unbind_device(struct device *dev)
++{
++	struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);
++
++	udriver->disconnect(to_usb_device(dev));
++	return 0;
++}
++
++
++/* called from driver core with dev locked */
+ static int usb_probe_interface(struct device *dev)
+ {
+-	struct usb_interface * intf = to_usb_interface(dev);
+-	struct usb_driver * driver = to_usb_driver(dev->driver);
++	struct usb_driver *driver = to_usb_driver(dev->driver);
++	struct usb_interface *intf;
+ 	const struct usb_device_id *id;
+ 	int error = -ENODEV;
+ 
+ 	dev_dbg(dev, "%s\n", __FUNCTION__);
+ 
+-	if (!driver->probe)
++	if (is_usb_device(dev))		/* Sanity check */
+ 		return error;
++
++	intf = to_usb_interface(dev);
++
+ 	/* FIXME we'd much prefer to just resume it ... */
+ 	if (interface_to_usbdev(intf)->state == USB_STATE_SUSPENDED)
+ 		return -EHOSTUNREACH;
+@@ -182,19 +219,18 @@ static int usb_probe_interface(struct device *dev)
+ 	return error;
+ }
+ 
+-/* called from driver core with usb_bus_type.subsys writelock */
++/* called from driver core with dev locked */
+ static int usb_unbind_interface(struct device *dev)
+ {
++	struct usb_driver *driver = to_usb_driver(dev->driver);
+ 	struct usb_interface *intf = to_usb_interface(dev);
+-	struct usb_driver *driver = to_usb_driver(intf->dev.driver);
+ 
+ 	intf->condition = USB_INTERFACE_UNBINDING;
+ 
+ 	/* release all urbs for this interface */
+ 	usb_disable_interface(interface_to_usbdev(intf), intf);
+ 
+-	if (driver && driver->disconnect)
+-		driver->disconnect(intf);
++	driver->disconnect(intf);
+ 
+ 	/* reset other interface state */
+ 	usb_set_interface(interface_to_usbdev(intf),
+@@ -235,7 +271,7 @@ int usb_driver_claim_interface(struct usb_driver *driver,
+ 	if (dev->driver)
+ 		return -EBUSY;
+ 
+-	dev->driver = &driver->driver;
++	dev->driver = &driver->drvwrap.driver;
+ 	usb_set_intfdata(iface, priv);
+ 	iface->condition = USB_INTERFACE_BOUND;
+ 	mark_active(iface);
+@@ -270,7 +306,7 @@ void usb_driver_release_interface(struct usb_driver *driver,
+ 	struct device *dev = &iface->dev;
+ 
+ 	/* this should never happen, don't release something that's not ours */
+-	if (!dev->driver || dev->driver != &driver->driver)
++	if (!dev->driver || dev->driver != &driver->drvwrap.driver)
+ 		return;
+ 
+ 	/* don't release from within disconnect() */
+@@ -433,24 +469,37 @@ EXPORT_SYMBOL_GPL_FUTURE(usb_match_id);
+ 
+ int usb_device_match(struct device *dev, struct device_driver *drv)
+ {
+-	struct usb_interface *intf;
+-	struct usb_driver *usb_drv;
+-	const struct usb_device_id *id;
+-
+-	/* check for generic driver, which we don't match any device with */
+-	if (drv == &usb_generic_driver)
+-		return 0;
++	/* devices and interfaces are handled separately */
++	if (is_usb_device(dev)) {
+ 
+-	intf = to_usb_interface(dev);
+-	usb_drv = to_usb_driver(drv);
++		/* interface drivers never match devices */
++		if (!is_usb_device_driver(drv))
++			return 0;
+ 
+-	id = usb_match_id(intf, usb_drv->id_table);
+-	if (id)
++		/* TODO: Add real matching code */
+ 		return 1;
+ 
+-	id = usb_match_dynamic_id(intf, usb_drv);
+-	if (id)
+-		return 1;
++	} else {
++		struct usb_interface *intf;
++		struct usb_driver *usb_drv;
++		const struct usb_device_id *id;
++
++		/* device drivers never match interfaces */
++		if (is_usb_device_driver(drv))
++			return 0;
++
++		intf = to_usb_interface(dev);
++		usb_drv = to_usb_driver(drv);
++
++		id = usb_match_id(intf, usb_drv->id_table);
++		if (id)
++			return 1;
++
++		id = usb_match_dynamic_id(intf, usb_drv);
++		if (id)
++			return 1;
++	}
++
+ 	return 0;
+ }
+ 
+@@ -481,14 +530,13 @@ static int usb_uevent(struct device *dev, char **envp, int num_envp,
+ 	/* driver is often null here; dev_dbg() would oops */
+ 	pr_debug ("usb %s: uevent\n", dev->bus_id);
+ 
+-	/* Must check driver_data here, as on remove driver is always NULL */
+-	if ((dev->driver == &usb_generic_driver) ||
+-	    (dev->driver_data == &usb_generic_driver_data))
++	if (is_usb_device(dev))
+ 		return 0;
+-
+-	intf = to_usb_interface(dev);
+-	usb_dev = interface_to_usbdev (intf);
+-	alt = intf->cur_altsetting;
++	else {
++		intf = to_usb_interface(dev);
++		usb_dev = interface_to_usbdev(intf);
++		alt = intf->cur_altsetting;
++	}
+ 
+ 	if (usb_dev->devnum < 0) {
+ 		pr_debug ("usb %s: already deleted?\n", dev->bus_id);
+@@ -569,13 +617,71 @@ static int usb_uevent(struct device *dev, char **envp,
+ #endif	/* CONFIG_HOTPLUG */
+ 
+ /**
+- * usb_register_driver - register a USB driver
+- * @new_driver: USB operations for the driver
++ * usb_register_device_driver - register a USB device (not interface) driver
++ * @new_udriver: USB operations for the device driver
+  * @owner: module owner of this driver.
+  *
+- * Registers a USB driver with the USB core.  The list of unattached
+- * interfaces will be rescanned whenever a new driver is added, allowing
+- * the new driver to attach to any recognized devices.
++ * Registers a USB device driver with the USB core.  The list of
++ * unattached devices will be rescanned whenever a new driver is
++ * added, allowing the new driver to attach to any recognized devices.
++ * Returns a negative error code on failure and 0 on success.
++ */
++int usb_register_device_driver(struct usb_device_driver *new_udriver,
++		struct module *owner)
++{
++	int retval = 0;
++
++	if (usb_disabled())
++		return -ENODEV;
++
++	new_udriver->drvwrap.for_devices = 1;
++	new_udriver->drvwrap.driver.name = (char *) new_udriver->name;
++	new_udriver->drvwrap.driver.bus = &usb_bus_type;
++	new_udriver->drvwrap.driver.probe = usb_probe_device;
++	new_udriver->drvwrap.driver.remove = usb_unbind_device;
++	new_udriver->drvwrap.driver.owner = owner;
++
++	retval = driver_register(&new_udriver->drvwrap.driver);
++
++	if (!retval) {
++		pr_info("%s: registered new device driver %s\n",
++			usbcore_name, new_udriver->name);
++		usbfs_update_special();
++	} else {
++		printk(KERN_ERR "%s: error %d registering device "
++			"	driver %s\n",
++			usbcore_name, retval, new_udriver->name);
++	}
++
++	return retval;
++}
++EXPORT_SYMBOL_GPL(usb_register_device_driver);
++
++/**
++ * usb_deregister_device_driver - unregister a USB device (not interface) driver
++ * @udriver: USB operations of the device driver to unregister
++ * Context: must be able to sleep
++ *
++ * Unlinks the specified driver from the internal USB driver list.
++ */
++void usb_deregister_device_driver(struct usb_device_driver *udriver)
++{
++	pr_info("%s: deregistering device driver %s\n",
++			usbcore_name, udriver->name);
++
++	driver_unregister(&udriver->drvwrap.driver);
++	usbfs_update_special();
++}
++EXPORT_SYMBOL_GPL(usb_deregister_device_driver);
++
++/**
++ * usb_register_driver - register a USB interface driver
++ * @new_driver: USB operations for the interface driver
++ * @owner: module owner of this driver.
++ *
++ * Registers a USB interface driver with the USB core.  The list of
++ * unattached interfaces will be rescanned whenever a new driver is
++ * added, allowing the new driver to attach to any recognized interfaces.
+  * Returns a negative error code on failure and 0 on success.
+  *
+  * NOTE: if you want your driver to use the USB major number, you must call
+@@ -589,23 +695,25 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner)
+ 	if (usb_disabled())
+ 		return -ENODEV;
+ 
+-	new_driver->driver.name = (char *)new_driver->name;
+-	new_driver->driver.bus = &usb_bus_type;
+-	new_driver->driver.probe = usb_probe_interface;
+-	new_driver->driver.remove = usb_unbind_interface;
+-	new_driver->driver.owner = owner;
++	new_driver->drvwrap.for_devices = 0;
++	new_driver->drvwrap.driver.name = (char *) new_driver->name;
++	new_driver->drvwrap.driver.bus = &usb_bus_type;
++	new_driver->drvwrap.driver.probe = usb_probe_interface;
++	new_driver->drvwrap.driver.remove = usb_unbind_interface;
++	new_driver->drvwrap.driver.owner = owner;
+ 	spin_lock_init(&new_driver->dynids.lock);
+ 	INIT_LIST_HEAD(&new_driver->dynids.list);
+ 
+-	retval = driver_register(&new_driver->driver);
++	retval = driver_register(&new_driver->drvwrap.driver);
+ 
+ 	if (!retval) {
+-		pr_info("%s: registered new driver %s\n",
++		pr_info("%s: registered new interface driver %s\n",
+ 			usbcore_name, new_driver->name);
+ 		usbfs_update_special();
+ 		usb_create_newid_file(new_driver);
+ 	} else {
+-		printk(KERN_ERR "%s: error %d registering driver %s\n",
++		printk(KERN_ERR "%s: error %d registering interface "
++			"	driver %s\n",
+ 			usbcore_name, retval, new_driver->name);
+ 	}
+ 
+@@ -614,8 +722,8 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner)
+ EXPORT_SYMBOL_GPL_FUTURE(usb_register_driver);
+ 
+ /**
+- * usb_deregister - unregister a USB driver
+- * @driver: USB operations of the driver to unregister
++ * usb_deregister - unregister a USB interface driver
++ * @driver: USB operations of the interface driver to unregister
+  * Context: must be able to sleep
+  *
+  * Unlinks the specified driver from the internal USB driver list.
+@@ -626,11 +734,12 @@ EXPORT_SYMBOL_GPL_FUTURE(usb_register_driver);
+  */
+ void usb_deregister(struct usb_driver *driver)
+ {
+-	pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name);
++	pr_info("%s: deregistering interface driver %s\n",
++			usbcore_name, driver->name);
+ 
+ 	usb_remove_newid_file(driver);
+ 	usb_free_dynids(driver);
+-	driver_unregister(&driver->driver);
++	driver_unregister(&driver->drvwrap.driver);
+ 
+ 	usbfs_update_special();
+ }
+@@ -655,7 +764,7 @@ static int usb_generic_suspend(struct device *dev, pm_message_t message)
+ 	 * marked for FREEZE as soon as their children are already idled.
+ 	 * But those semantics are useless, so we equate the two (sigh).
+ 	 */
+-	if (dev->driver == &usb_generic_driver) {
++	if (is_usb_device(dev)) {
+ 		if (dev->power.power_state.event == message.event)
+ 			return 0;
+ 		/* we need to rule out bogus requests through sysfs */
+@@ -665,8 +774,7 @@ static int usb_generic_suspend(struct device *dev, pm_message_t message)
+  		return usb_port_suspend(to_usb_device(dev));
+ 	}
+ 
+-	if ((dev->driver == NULL) ||
+-	    (dev->driver_data == &usb_generic_driver_data))
++	if (dev->driver == NULL)
+ 		return 0;
+ 
+ 	intf = to_usb_interface(dev);
+@@ -705,15 +813,14 @@ static int usb_generic_resume(struct device *dev)
+ 	dev->power.power_state.event = PM_EVENT_ON;
+ 
+ 	/* devices resume through their hubs */
+-	if (dev->driver == &usb_generic_driver) {
++	if (is_usb_device(dev)) {
+ 		udev = to_usb_device(dev);
+ 		if (udev->state == USB_STATE_NOTATTACHED)
+ 			return 0;
+ 		return usb_port_resume(udev);
+ 	}
+ 
+-	if ((dev->driver == NULL) ||
+-	    (dev->driver_data == &usb_generic_driver_data)) {
++	if (dev->driver == NULL) {
+ 		dev->power.power_state.event = PM_EVENT_FREEZE;
+ 		return 0;
+ 	}
+diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
+index 7bab9769b34f..fa6f34a12b4b 100644
+--- a/drivers/usb/core/generic.c
++++ b/drivers/usb/core/generic.c
+@@ -21,14 +21,12 @@
+ #include 
+ #include "usb.h"
+ 
+-static int generic_probe(struct device *dev)
++static int generic_probe(struct usb_device *udev)
+ {
+ 	return 0;
+ }
+-static int generic_remove(struct device *dev)
++static void generic_disconnect(struct usb_device *udev)
+ {
+-	struct usb_device *udev = to_usb_device(dev);
+-
+ 	/* if this is only an unbind, not a physical disconnect, then
+ 	 * unconfigure the device */
+ 	if (udev->state == USB_STATE_CONFIGURED)
+@@ -37,17 +35,10 @@ static int generic_remove(struct device *dev)
+ 	/* in case the call failed or the device was suspended */
+ 	if (udev->state >= USB_STATE_CONFIGURED)
+ 		usb_disable_device(udev, 0);
+-	return 0;
+ }
+ 
+-struct device_driver usb_generic_driver = {
+-	.owner = THIS_MODULE,
++struct usb_device_driver usb_generic_driver = {
+ 	.name =	"usb",
+-	.bus = &usb_bus_type,
+ 	.probe = generic_probe,
+-	.remove = generic_remove,
++	.disconnect = generic_disconnect,
+ };
+-
+-/* Fun hack to determine if the struct device is a
+- * usb device or a usb interface. */
+-int usb_generic_driver_data;
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 0b8c67bcde60..6dfbc284369b 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -123,7 +123,7 @@ static int __find_interface(struct device * dev, void * data)
+ 	struct usb_interface *intf;
+ 
+ 	/* can't look at usb devices, only interfaces */
+-	if (dev->driver == &usb_generic_driver)
++	if (is_usb_device(dev))
+ 		return 0;
+ 
+ 	intf = to_usb_interface(dev);
+@@ -149,7 +149,8 @@ struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)
+ 
+ 	argb.minor = minor;
+ 	argb.interface = NULL;
+-	driver_for_each_device(&drv->driver, NULL, &argb, __find_interface);
++	driver_for_each_device(&drv->drvwrap.driver, NULL, &argb,
++			__find_interface);
+ 	return argb.interface;
+ }
+ 
+@@ -204,11 +205,13 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
+ 	device_initialize(&dev->dev);
+ 	dev->dev.bus = &usb_bus_type;
+ 	dev->dev.dma_mask = bus->controller->dma_mask;
+-	dev->dev.driver_data = &usb_generic_driver_data;
+-	dev->dev.driver = &usb_generic_driver;
++	dev->dev.driver = &usb_generic_driver.drvwrap.driver;
+ 	dev->dev.release = usb_release_dev;
+ 	dev->state = USB_STATE_ATTACHED;
+ 
++	/* This magic assignment distinguishes devices from interfaces */
++	dev->dev.platform_data = &usb_generic_driver;
++
+ 	INIT_LIST_HEAD(&dev->ep0.urb_list);
+ 	dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;
+ 	dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;
+@@ -838,7 +841,7 @@ static int __init usb_init(void)
+ 	retval = usb_hub_init();
+ 	if (retval)
+ 		goto hub_init_failed;
+-	retval = driver_register(&usb_generic_driver);
++	retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE);
+ 	if (!retval)
+ 		goto out;
+ 
+@@ -868,7 +871,7 @@ static void __exit usb_exit(void)
+ 	if (nousb)
+ 		return;
+ 
+-	driver_unregister(&usb_generic_driver);
++	usb_deregister_device_driver(&usb_generic_driver);
+ 	usb_major_cleanup();
+ 	usbfs_cleanup();
+ 	usb_deregister(&usbfs_driver);
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 82d397a6f773..1d25ccac7832 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -34,8 +34,24 @@ extern int usb_port_suspend(struct usb_device *dev);
+ extern int usb_port_resume(struct usb_device *dev);
+ 
+ extern struct bus_type usb_bus_type;
+-extern struct device_driver usb_generic_driver;
+-extern int usb_generic_driver_data;
++extern struct usb_device_driver usb_generic_driver;
++
++/* Here's how we tell apart devices and interfaces.  Luckily there's
++ * no such thing as a platform USB device, so we can steal the use
++ * of the platform_data field. */
++
++static inline int is_usb_device(struct device *dev)
++{
++	return dev->platform_data == &usb_generic_driver;
++}
++
++/* Do the same for device drivers and interface drivers. */
++
++static inline int is_usb_device_driver(struct device_driver *drv)
++{
++	return container_of(drv, struct usbdrv_wrap, driver)->
++			for_devices;
++}
+ 
+ /* Interfaces and their "power state" are owned by usbcore */
+ 
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index d2bd0c8e0154..b4ccce6d0982 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -540,7 +540,17 @@ struct usb_dynids {
+ };
+ 
+ /**
+- * struct usb_driver - identifies USB driver to usbcore
++ * struct usbdrv_wrap - wrapper for driver-model structure
++ * @driver: The driver-model core driver structure.
++ * @for_devices: Non-zero for device drivers, 0 for interface drivers.
++ */
++struct usbdrv_wrap {
++	struct device_driver driver;
++	int for_devices;
++};
++
++/**
++ * struct usb_driver - identifies USB interface driver to usbcore
+  * @name: The driver name should be unique among USB drivers,
+  *	and should normally be the same as the module name.
+  * @probe: Called to see if the driver is willing to manage a particular
+@@ -567,12 +577,12 @@ struct usb_dynids {
+  *	or your driver's probe function will never get called.
+  * @dynids: used internally to hold the list of dynamically added device
+  *	ids for this driver.
+- * @driver: the driver model core driver structure.
++ * @drvwrap: Driver-model core structure wrapper.
+  * @no_dynamic_id: if set to 1, the USB core will not allow dynamic ids to be
+  *	added to this driver by preventing the sysfs file from being created.
+  *
+- * USB drivers must provide a name, probe() and disconnect() methods,
+- * and an id_table.  Other driver fields are optional.
++ * USB interface drivers must provide a name, probe() and disconnect()
++ * methods, and an id_table.  Other driver fields are optional.
+  *
+  * The id_table is used in hotplugging.  It holds a set of descriptors,
+  * and specialized data may be associated with each entry.  That table
+@@ -606,10 +616,40 @@ struct usb_driver {
+ 	const struct usb_device_id *id_table;
+ 
+ 	struct usb_dynids dynids;
+-	struct device_driver driver;
++	struct usbdrv_wrap drvwrap;
+ 	unsigned int no_dynamic_id:1;
+ };
+-#define	to_usb_driver(d) container_of(d, struct usb_driver, driver)
++#define	to_usb_driver(d) container_of(d, struct usb_driver, drvwrap.driver)
++
++/**
++ * struct usb_device_driver - identifies USB device driver to usbcore
++ * @name: The driver name should be unique among USB drivers,
++ *	and should normally be the same as the module name.
++ * @probe: Called to see if the driver is willing to manage a particular
++ *	device.  If it is, probe returns zero and uses dev_set_drvdata()
++ *	to associate driver-specific data with the device.  If unwilling
++ *	to manage the device, return a negative errno value.
++ * @disconnect: Called when the device is no longer accessible, usually
++ *	because it has been (or is being) disconnected or the driver's
++ *	module is being unloaded.
++ * @suspend: Called when the device is going to be suspended by the system.
++ * @resume: Called when the device is being resumed by the system.
++ * @drvwrap: Driver-model core structure wrapper.
++ *
++ * USB drivers must provide all the fields listed above except drvwrap.
++ */
++struct usb_device_driver {
++	const char *name;
++
++	int (*probe) (struct usb_device *udev);
++	void (*disconnect) (struct usb_device *udev);
++
++	int (*suspend) (struct usb_device *udev, pm_message_t message);
++	int (*resume) (struct usb_device *udev);
++	struct usbdrv_wrap drvwrap;
++};
++#define	to_usb_device_driver(d) container_of(d, struct usb_device_driver, \
++		drvwrap.driver)
+ 
+ extern struct bus_type usb_bus_type;
+ 
+@@ -633,13 +673,17 @@ struct usb_class_driver {
+  * use these in module_init()/module_exit()
+  * and don't forget MODULE_DEVICE_TABLE(usb, ...)
+  */
+-int usb_register_driver(struct usb_driver *, struct module *);
++extern int usb_register_driver(struct usb_driver *, struct module *);
+ static inline int usb_register(struct usb_driver *driver)
+ {
+ 	return usb_register_driver(driver, THIS_MODULE);
+ }
+ extern void usb_deregister(struct usb_driver *);
+ 
++extern int usb_register_device_driver(struct usb_device_driver *,
++			struct module *);
++extern void usb_deregister_device_driver(struct usb_device_driver *);
++
+ extern int usb_register_dev(struct usb_interface *intf,
+ 			    struct usb_class_driver *class_driver);
+ extern void usb_deregister_dev(struct usb_interface *intf,

commit 36e56a34586783c7986ce09d39db80b27c95ce24
+Author: Alan Stern 
+Date:   Sat Jul 1 22:08:06 2006 -0400
+
+    usbcore: move code among source files
+    
+    This revised patch (as713b) moves a few routines among source files in
+    usbcore.  Some driver-related code in usb.c (claiming interfaces and
+    matching IDs) is moved to driver.c, where it belongs.  Also the
+    usb_generic stuff in driver.c is moved to a new source file: generic.c.
+    (That's the reason for revising the patch.)  Although not very big now,
+    it will get bigger in a later patch.
+    
+    None of the code has been changed; it has only been re-arranged.
+    
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
+index ec510922af63..34e9bac319b4 100644
+--- a/drivers/usb/core/Makefile
++++ b/drivers/usb/core/Makefile
+@@ -4,7 +4,7 @@
+ 
+ usbcore-objs	:= usb.o hub.o hcd.o urb.o message.o driver.o \
+ 			config.o file.o buffer.o sysfs.o endpoint.o \
+-			devio.o notify.o
++			devio.o notify.o generic.o
+ 
+ ifeq ($(CONFIG_PCI),y)
+ 	usbcore-objs	+= hcd-pci.o
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index ec8906501415..8dcf2cd0c569 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -17,7 +17,8 @@
+  *
+  * NOTE! This is not actually a driver at all, rather this is
+  * just a collection of helper routines that implement the
+- * generic USB things that the real drivers can use..
++ * matching, probing, releasing, suspending and resuming for
++ * real drivers.
+  *
+  */
+ 
+@@ -34,38 +35,6 @@ struct usb_dynid {
+ 	struct usb_device_id id;
+ };
+ 
+-
+-static int generic_probe(struct device *dev)
+-{
+-	return 0;
+-}
+-static int generic_remove(struct device *dev)
+-{
+-	struct usb_device *udev = to_usb_device(dev);
+-
+-	/* if this is only an unbind, not a physical disconnect, then
+-	 * unconfigure the device */
+-	if (udev->state == USB_STATE_CONFIGURED)
+-		usb_set_configuration(udev, 0);
+-
+-	/* in case the call failed or the device was suspended */
+-	if (udev->state >= USB_STATE_CONFIGURED)
+-		usb_disable_device(udev, 0);
+-	return 0;
+-}
+-
+-struct device_driver usb_generic_driver = {
+-	.owner = THIS_MODULE,
+-	.name =	"usb",
+-	.bus = &usb_bus_type,
+-	.probe = generic_probe,
+-	.remove = generic_remove,
+-};
+-
+-/* Fun hack to determine if the struct device is a
+- * usb device or a usb interface. */
+-int usb_generic_driver_data;
+-
+ #ifdef CONFIG_HOTPLUG
+ 
+ /*
+@@ -238,6 +207,89 @@ static int usb_unbind_interface(struct device *dev)
+ 	return 0;
+ }
+ 
++/**
++ * usb_driver_claim_interface - bind a driver to an interface
++ * @driver: the driver to be bound
++ * @iface: the interface to which it will be bound; must be in the
++ *	usb device's active configuration
++ * @priv: driver data associated with that interface
++ *
++ * This is used by usb device drivers that need to claim more than one
++ * interface on a device when probing (audio and acm are current examples).
++ * No device driver should directly modify internal usb_interface or
++ * usb_device structure members.
++ *
++ * Few drivers should need to use this routine, since the most natural
++ * way to bind to an interface is to return the private data from
++ * the driver's probe() method.
++ *
++ * Callers must own the device lock and the driver model's usb_bus_type.subsys
++ * writelock.  So driver probe() entries don't need extra locking,
++ * but other call contexts may need to explicitly claim those locks.
++ */
++int usb_driver_claim_interface(struct usb_driver *driver,
++				struct usb_interface *iface, void* priv)
++{
++	struct device *dev = &iface->dev;
++
++	if (dev->driver)
++		return -EBUSY;
++
++	dev->driver = &driver->driver;
++	usb_set_intfdata(iface, priv);
++	iface->condition = USB_INTERFACE_BOUND;
++	mark_active(iface);
++
++	/* if interface was already added, bind now; else let
++	 * the future device_add() bind it, bypassing probe()
++	 */
++	if (device_is_registered(dev))
++		device_bind_driver(dev);
++
++	return 0;
++}
++EXPORT_SYMBOL(usb_driver_claim_interface);
++
++/**
++ * usb_driver_release_interface - unbind a driver from an interface
++ * @driver: the driver to be unbound
++ * @iface: the interface from which it will be unbound
++ *
++ * This can be used by drivers to release an interface without waiting
++ * for their disconnect() methods to be called.  In typical cases this
++ * also causes the driver disconnect() method to be called.
++ *
++ * This call is synchronous, and may not be used in an interrupt context.
++ * Callers must own the device lock and the driver model's usb_bus_type.subsys
++ * writelock.  So driver disconnect() entries don't need extra locking,
++ * but other call contexts may need to explicitly claim those locks.
++ */
++void usb_driver_release_interface(struct usb_driver *driver,
++					struct usb_interface *iface)
++{
++	struct device *dev = &iface->dev;
++
++	/* this should never happen, don't release something that's not ours */
++	if (!dev->driver || dev->driver != &driver->driver)
++		return;
++
++	/* don't release from within disconnect() */
++	if (iface->condition != USB_INTERFACE_BOUND)
++		return;
++
++	/* don't release if the interface hasn't been added yet */
++	if (device_is_registered(dev)) {
++		iface->condition = USB_INTERFACE_UNBINDING;
++		device_release_driver(dev);
++	}
++
++	dev->driver = NULL;
++	usb_set_intfdata(iface, NULL);
++	iface->condition = USB_INTERFACE_UNBOUND;
++	mark_quiesced(iface);
++}
++EXPORT_SYMBOL(usb_driver_release_interface);
++
+ /* returns 0 if no match, 1 if match */
+ static int usb_match_one_id(struct usb_interface *interface,
+ 			    const struct usb_device_id *id)
+@@ -402,6 +454,120 @@ int usb_device_match(struct device *dev, struct device_driver *drv)
+ 	return 0;
+ }
+ 
++#ifdef	CONFIG_HOTPLUG
++
++/*
++ * This sends an uevent to userspace, typically helping to load driver
++ * or other modules, configure the device, and more.  Drivers can provide
++ * a MODULE_DEVICE_TABLE to help with module loading subtasks.
++ *
++ * We're called either from khubd (the typical case) or from root hub
++ * (init, kapmd, modprobe, rmmod, etc), but the agents need to handle
++ * delays in event delivery.  Use sysfs (and DEVPATH) to make sure the
++ * device (and this configuration!) are still present.
++ */
++static int usb_uevent(struct device *dev, char **envp, int num_envp,
++		      char *buffer, int buffer_size)
++{
++	struct usb_interface *intf;
++	struct usb_device *usb_dev;
++	struct usb_host_interface *alt;
++	int i = 0;
++	int length = 0;
++
++	if (!dev)
++		return -ENODEV;
++
++	/* driver is often null here; dev_dbg() would oops */
++	pr_debug ("usb %s: uevent\n", dev->bus_id);
++
++	/* Must check driver_data here, as on remove driver is always NULL */
++	if ((dev->driver == &usb_generic_driver) ||
++	    (dev->driver_data == &usb_generic_driver_data))
++		return 0;
++
++	intf = to_usb_interface(dev);
++	usb_dev = interface_to_usbdev (intf);
++	alt = intf->cur_altsetting;
++
++	if (usb_dev->devnum < 0) {
++		pr_debug ("usb %s: already deleted?\n", dev->bus_id);
++		return -ENODEV;
++	}
++	if (!usb_dev->bus) {
++		pr_debug ("usb %s: bus removed?\n", dev->bus_id);
++		return -ENODEV;
++	}
++
++#ifdef	CONFIG_USB_DEVICEFS
++	/* If this is available, userspace programs can directly read
++	 * all the device descriptors we don't tell them about.  Or
++	 * even act as usermode drivers.
++	 *
++	 * FIXME reduce hardwired intelligence here
++	 */
++	if (add_uevent_var(envp, num_envp, &i,
++			   buffer, buffer_size, &length,
++			   "DEVICE=/proc/bus/usb/%03d/%03d",
++			   usb_dev->bus->busnum, usb_dev->devnum))
++		return -ENOMEM;
++#endif
++
++	/* per-device configurations are common */
++	if (add_uevent_var(envp, num_envp, &i,
++			   buffer, buffer_size, &length,
++			   "PRODUCT=%x/%x/%x",
++			   le16_to_cpu(usb_dev->descriptor.idVendor),
++			   le16_to_cpu(usb_dev->descriptor.idProduct),
++			   le16_to_cpu(usb_dev->descriptor.bcdDevice)))
++		return -ENOMEM;
++
++	/* class-based driver binding models */
++	if (add_uevent_var(envp, num_envp, &i,
++			   buffer, buffer_size, &length,
++			   "TYPE=%d/%d/%d",
++			   usb_dev->descriptor.bDeviceClass,
++			   usb_dev->descriptor.bDeviceSubClass,
++			   usb_dev->descriptor.bDeviceProtocol))
++		return -ENOMEM;
++
++	if (add_uevent_var(envp, num_envp, &i,
++			   buffer, buffer_size, &length,
++			   "INTERFACE=%d/%d/%d",
++			   alt->desc.bInterfaceClass,
++			   alt->desc.bInterfaceSubClass,
++			   alt->desc.bInterfaceProtocol))
++		return -ENOMEM;
++
++	if (add_uevent_var(envp, num_envp, &i,
++			   buffer, buffer_size, &length,
++			   "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
++			   le16_to_cpu(usb_dev->descriptor.idVendor),
++			   le16_to_cpu(usb_dev->descriptor.idProduct),
++			   le16_to_cpu(usb_dev->descriptor.bcdDevice),
++			   usb_dev->descriptor.bDeviceClass,
++			   usb_dev->descriptor.bDeviceSubClass,
++			   usb_dev->descriptor.bDeviceProtocol,
++			   alt->desc.bInterfaceClass,
++			   alt->desc.bInterfaceSubClass,
++			   alt->desc.bInterfaceProtocol))
++		return -ENOMEM;
++
++	envp[i] = NULL;
++
++	return 0;
++}
++
++#else
++
++static int usb_uevent(struct device *dev, char **envp,
++			int num_envp, char *buffer, int buffer_size)
++{
++	return -ENODEV;
++}
++
++#endif	/* CONFIG_HOTPLUG */
++
+ /**
+  * usb_register_driver - register a USB driver
+  * @new_driver: USB operations for the driver
+@@ -469,3 +635,119 @@ void usb_deregister(struct usb_driver *driver)
+ 	usbfs_update_special();
+ }
+ EXPORT_SYMBOL_GPL_FUTURE(usb_deregister);
++
++#ifdef CONFIG_PM
++
++static int verify_suspended(struct device *dev, void *unused)
++{
++	if (dev->driver == NULL)
++		return 0;
++	return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0;
++}
++
++static int usb_generic_suspend(struct device *dev, pm_message_t message)
++{
++	struct usb_interface	*intf;
++	struct usb_driver	*driver;
++	int			status;
++
++	/* USB devices enter SUSPEND state through their hubs, but can be
++	 * marked for FREEZE as soon as their children are already idled.
++	 * But those semantics are useless, so we equate the two (sigh).
++	 */
++	if (dev->driver == &usb_generic_driver) {
++		if (dev->power.power_state.event == message.event)
++			return 0;
++		/* we need to rule out bogus requests through sysfs */
++		status = device_for_each_child(dev, NULL, verify_suspended);
++		if (status)
++			return status;
++ 		return usb_port_suspend(to_usb_device(dev));
++	}
++
++	if ((dev->driver == NULL) ||
++	    (dev->driver_data == &usb_generic_driver_data))
++		return 0;
++
++	intf = to_usb_interface(dev);
++	driver = to_usb_driver(dev->driver);
++
++	/* with no hardware, USB interfaces only use FREEZE and ON states */
++	if (!is_active(intf))
++		return 0;
++
++	if (driver->suspend && driver->resume) {
++		status = driver->suspend(intf, message);
++		if (status)
++			dev_err(dev, "%s error %d\n", "suspend", status);
++		else
++			mark_quiesced(intf);
++	} else {
++		// FIXME else if there's no suspend method, disconnect...
++		dev_warn(dev, "no suspend for driver %s?\n", driver->name);
++		mark_quiesced(intf);
++		status = 0;
++	}
++	return status;
++}
++
++static int usb_generic_resume(struct device *dev)
++{
++	struct usb_interface	*intf;
++	struct usb_driver	*driver;
++	struct usb_device	*udev;
++	int			status;
++
++	if (dev->power.power_state.event == PM_EVENT_ON)
++		return 0;
++
++	/* mark things as "on" immediately, no matter what errors crop up */
++	dev->power.power_state.event = PM_EVENT_ON;
++
++	/* devices resume through their hubs */
++	if (dev->driver == &usb_generic_driver) {
++		udev = to_usb_device(dev);
++		if (udev->state == USB_STATE_NOTATTACHED)
++			return 0;
++		return usb_port_resume(udev);
++	}
++
++	if ((dev->driver == NULL) ||
++	    (dev->driver_data == &usb_generic_driver_data)) {
++		dev->power.power_state.event = PM_EVENT_FREEZE;
++		return 0;
++	}
++
++	intf = to_usb_interface(dev);
++	driver = to_usb_driver(dev->driver);
++
++	udev = interface_to_usbdev(intf);
++	if (udev->state == USB_STATE_NOTATTACHED)
++		return 0;
++
++	/* if driver was suspended, it has a resume method;
++	 * however, sysfs can wrongly mark things as suspended
++	 * (on the "no suspend method" FIXME path above)
++	 */
++	if (driver->resume) {
++		status = driver->resume(intf);
++		if (status) {
++			dev_err(dev, "%s error %d\n", "resume", status);
++			mark_quiesced(intf);
++		}
++	} else
++		dev_warn(dev, "no resume for driver %s?\n", driver->name);
++	return 0;
++}
++
++#endif /* CONFIG_PM */
++
++struct bus_type usb_bus_type = {
++	.name =		"usb",
++	.match =	usb_device_match,
++	.uevent =	usb_uevent,
++#ifdef CONFIG_PM
++	.suspend =	usb_generic_suspend,
++	.resume =	usb_generic_resume,
++#endif
++};
+diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
+new file mode 100644
+index 000000000000..7bab9769b34f
+--- /dev/null
++++ b/drivers/usb/core/generic.c
+@@ -0,0 +1,53 @@
++/*
++ * drivers/usb/generic.c - generic driver for USB devices (not interfaces)
++ *
++ * (C) Copyright 2005 Greg Kroah-Hartman 
++ *
++ * based on drivers/usb/usb.c which had the following copyrights:
++ *	(C) Copyright Linus Torvalds 1999
++ *	(C) Copyright Johannes Erdfelt 1999-2001
++ *	(C) Copyright Andreas Gal 1999
++ *	(C) Copyright Gregory P. Smith 1999
++ *	(C) Copyright Deti Fliegl 1999 (new USB architecture)
++ *	(C) Copyright Randy Dunlap 2000
++ *	(C) Copyright David Brownell 2000-2004
++ *	(C) Copyright Yggdrasil Computing, Inc. 2000
++ *		(usb_device_id matching changes by Adam J. Richter)
++ *	(C) Copyright Greg Kroah-Hartman 2002-2003
++ *
++ */
++
++#include 
++#include 
++#include "usb.h"
++
++static int generic_probe(struct device *dev)
++{
++	return 0;
++}
++static int generic_remove(struct device *dev)
++{
++	struct usb_device *udev = to_usb_device(dev);
++
++	/* if this is only an unbind, not a physical disconnect, then
++	 * unconfigure the device */
++	if (udev->state == USB_STATE_CONFIGURED)
++		usb_set_configuration(udev, 0);
++
++	/* in case the call failed or the device was suspended */
++	if (udev->state >= USB_STATE_CONFIGURED)
++		usb_disable_device(udev, 0);
++	return 0;
++}
++
++struct device_driver usb_generic_driver = {
++	.owner = THIS_MODULE,
++	.name =	"usb",
++	.bus = &usb_bus_type,
++	.probe = generic_probe,
++	.remove = generic_remove,
++};
++
++/* Fun hack to determine if the struct device is a
++ * usb device or a usb interface. */
++int usb_generic_driver_data;
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index b28a31b20308..0b8c67bcde60 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -112,87 +112,6 @@ struct usb_host_interface *usb_altnum_to_altsetting(struct usb_interface *intf,
+ 	return NULL;
+ }
+ 
+-/**
+- * usb_driver_claim_interface - bind a driver to an interface
+- * @driver: the driver to be bound
+- * @iface: the interface to which it will be bound; must be in the
+- *	usb device's active configuration
+- * @priv: driver data associated with that interface
+- *
+- * This is used by usb device drivers that need to claim more than one
+- * interface on a device when probing (audio and acm are current examples).
+- * No device driver should directly modify internal usb_interface or
+- * usb_device structure members.
+- *
+- * Few drivers should need to use this routine, since the most natural
+- * way to bind to an interface is to return the private data from
+- * the driver's probe() method.
+- *
+- * Callers must own the device lock and the driver model's usb_bus_type.subsys
+- * writelock.  So driver probe() entries don't need extra locking,
+- * but other call contexts may need to explicitly claim those locks.
+- */
+-int usb_driver_claim_interface(struct usb_driver *driver,
+-				struct usb_interface *iface, void* priv)
+-{
+-	struct device *dev = &iface->dev;
+-
+-	if (dev->driver)
+-		return -EBUSY;
+-
+-	dev->driver = &driver->driver;
+-	usb_set_intfdata(iface, priv);
+-	iface->condition = USB_INTERFACE_BOUND;
+-	mark_active(iface);
+-
+-	/* if interface was already added, bind now; else let
+-	 * the future device_add() bind it, bypassing probe()
+-	 */
+-	if (device_is_registered(dev))
+-		device_bind_driver(dev);
+-
+-	return 0;
+-}
+-
+-/**
+- * usb_driver_release_interface - unbind a driver from an interface
+- * @driver: the driver to be unbound
+- * @iface: the interface from which it will be unbound
+- *
+- * This can be used by drivers to release an interface without waiting
+- * for their disconnect() methods to be called.  In typical cases this
+- * also causes the driver disconnect() method to be called.
+- *
+- * This call is synchronous, and may not be used in an interrupt context.
+- * Callers must own the device lock and the driver model's usb_bus_type.subsys
+- * writelock.  So driver disconnect() entries don't need extra locking,
+- * but other call contexts may need to explicitly claim those locks.
+- */
+-void usb_driver_release_interface(struct usb_driver *driver,
+-					struct usb_interface *iface)
+-{
+-	struct device *dev = &iface->dev;
+-
+-	/* this should never happen, don't release something that's not ours */
+-	if (!dev->driver || dev->driver != &driver->driver)
+-		return;
+-
+-	/* don't release from within disconnect() */
+-	if (iface->condition != USB_INTERFACE_BOUND)
+-		return;
+-
+-	/* don't release if the interface hasn't been added yet */
+-	if (device_is_registered(dev)) {
+-		iface->condition = USB_INTERFACE_UNBINDING;
+-		device_release_driver(dev);
+-	}
+-
+-	dev->driver = NULL;
+-	usb_set_intfdata(iface, NULL);
+-	iface->condition = USB_INTERFACE_UNBOUND;
+-	mark_quiesced(iface);
+-}
+-
+ struct find_interface_arg {
+ 	int minor;
+ 	struct usb_interface *interface;
+@@ -234,120 +153,6 @@ struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)
+ 	return argb.interface;
+ }
+ 
+-#ifdef	CONFIG_HOTPLUG
+-
+-/*
+- * This sends an uevent to userspace, typically helping to load driver
+- * or other modules, configure the device, and more.  Drivers can provide
+- * a MODULE_DEVICE_TABLE to help with module loading subtasks.
+- *
+- * We're called either from khubd (the typical case) or from root hub
+- * (init, kapmd, modprobe, rmmod, etc), but the agents need to handle
+- * delays in event delivery.  Use sysfs (and DEVPATH) to make sure the
+- * device (and this configuration!) are still present.
+- */
+-static int usb_uevent(struct device *dev, char **envp, int num_envp,
+-		      char *buffer, int buffer_size)
+-{
+-	struct usb_interface *intf;
+-	struct usb_device *usb_dev;
+-	struct usb_host_interface *alt;
+-	int i = 0;
+-	int length = 0;
+-
+-	if (!dev)
+-		return -ENODEV;
+-
+-	/* driver is often null here; dev_dbg() would oops */
+-	pr_debug ("usb %s: uevent\n", dev->bus_id);
+-
+-	/* Must check driver_data here, as on remove driver is always NULL */
+-	if ((dev->driver == &usb_generic_driver) || 
+-	    (dev->driver_data == &usb_generic_driver_data))
+-		return 0;
+-
+-	intf = to_usb_interface(dev);
+-	usb_dev = interface_to_usbdev (intf);
+-	alt = intf->cur_altsetting;
+-
+-	if (usb_dev->devnum < 0) {
+-		pr_debug ("usb %s: already deleted?\n", dev->bus_id);
+-		return -ENODEV;
+-	}
+-	if (!usb_dev->bus) {
+-		pr_debug ("usb %s: bus removed?\n", dev->bus_id);
+-		return -ENODEV;
+-	}
+-
+-#ifdef	CONFIG_USB_DEVICEFS
+-	/* If this is available, userspace programs can directly read
+-	 * all the device descriptors we don't tell them about.  Or
+-	 * even act as usermode drivers.
+-	 *
+-	 * FIXME reduce hardwired intelligence here
+-	 */
+-	if (add_uevent_var(envp, num_envp, &i,
+-			   buffer, buffer_size, &length,
+-			   "DEVICE=/proc/bus/usb/%03d/%03d",
+-			   usb_dev->bus->busnum, usb_dev->devnum))
+-		return -ENOMEM;
+-#endif
+-
+-	/* per-device configurations are common */
+-	if (add_uevent_var(envp, num_envp, &i,
+-			   buffer, buffer_size, &length,
+-			   "PRODUCT=%x/%x/%x",
+-			   le16_to_cpu(usb_dev->descriptor.idVendor),
+-			   le16_to_cpu(usb_dev->descriptor.idProduct),
+-			   le16_to_cpu(usb_dev->descriptor.bcdDevice)))
+-		return -ENOMEM;
+-
+-	/* class-based driver binding models */
+-	if (add_uevent_var(envp, num_envp, &i,
+-			   buffer, buffer_size, &length,
+-			   "TYPE=%d/%d/%d",
+-			   usb_dev->descriptor.bDeviceClass,
+-			   usb_dev->descriptor.bDeviceSubClass,
+-			   usb_dev->descriptor.bDeviceProtocol))
+-		return -ENOMEM;
+-
+-	if (add_uevent_var(envp, num_envp, &i,
+-			   buffer, buffer_size, &length,
+-			   "INTERFACE=%d/%d/%d",
+-			   alt->desc.bInterfaceClass,
+-			   alt->desc.bInterfaceSubClass,
+-			   alt->desc.bInterfaceProtocol))
+-		return -ENOMEM;
+-
+-	if (add_uevent_var(envp, num_envp, &i,
+-			   buffer, buffer_size, &length,
+-			   "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
+-			   le16_to_cpu(usb_dev->descriptor.idVendor),
+-			   le16_to_cpu(usb_dev->descriptor.idProduct),
+-			   le16_to_cpu(usb_dev->descriptor.bcdDevice),
+-			   usb_dev->descriptor.bDeviceClass,
+-			   usb_dev->descriptor.bDeviceSubClass,
+-			   usb_dev->descriptor.bDeviceProtocol,
+-			   alt->desc.bInterfaceClass,
+-			   alt->desc.bInterfaceSubClass,
+-			   alt->desc.bInterfaceProtocol))
+-		return -ENOMEM;
+-
+-	envp[i] = NULL;
+-
+-	return 0;
+-}
+-
+-#else
+-
+-static int usb_uevent(struct device *dev, char **envp,
+-			int num_envp, char *buffer, int buffer_size)
+-{
+-	return -ENODEV;
+-}
+-
+-#endif	/* CONFIG_HOTPLUG */
+-
+ /**
+  * usb_release_dev - free a usb device structure when all users of it are finished.
+  * @dev: device that's been disconnected
+@@ -990,116 +795,6 @@ void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe,
+ 			usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
+ }
+ 
+-static int verify_suspended(struct device *dev, void *unused)
+-{
+-	if (dev->driver == NULL)
+-		return 0;
+-	return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0;
+-}
+-
+-static int usb_generic_suspend(struct device *dev, pm_message_t message)
+-{
+-	struct usb_interface	*intf;
+-	struct usb_driver	*driver;
+-	int			status;
+-
+-	/* USB devices enter SUSPEND state through their hubs, but can be
+-	 * marked for FREEZE as soon as their children are already idled.
+-	 * But those semantics are useless, so we equate the two (sigh).
+-	 */
+-	if (dev->driver == &usb_generic_driver) {
+-		if (dev->power.power_state.event == message.event)
+-			return 0;
+-		/* we need to rule out bogus requests through sysfs */
+-		status = device_for_each_child(dev, NULL, verify_suspended);
+-		if (status)
+-			return status;
+- 		return usb_port_suspend(to_usb_device(dev));
+-	}
+-
+-	if ((dev->driver == NULL) ||
+-	    (dev->driver_data == &usb_generic_driver_data))
+-		return 0;
+-
+-	intf = to_usb_interface(dev);
+-	driver = to_usb_driver(dev->driver);
+-
+-	/* with no hardware, USB interfaces only use FREEZE and ON states */
+-	if (!is_active(intf))
+-		return 0;
+-
+-	if (driver->suspend && driver->resume) {
+-		status = driver->suspend(intf, message);
+-		if (status)
+-			dev_err(dev, "%s error %d\n", "suspend", status);
+-		else
+-			mark_quiesced(intf);
+-	} else {
+-		// FIXME else if there's no suspend method, disconnect...
+-		dev_warn(dev, "no suspend for driver %s?\n", driver->name);
+-		mark_quiesced(intf);
+-		status = 0;
+-	}
+-	return status;
+-}
+-
+-static int usb_generic_resume(struct device *dev)
+-{
+-	struct usb_interface	*intf;
+-	struct usb_driver	*driver;
+-	struct usb_device	*udev;
+-	int			status;
+-
+-	if (dev->power.power_state.event == PM_EVENT_ON)
+-		return 0;
+-
+-	/* mark things as "on" immediately, no matter what errors crop up */
+-	dev->power.power_state.event = PM_EVENT_ON;
+-
+-	/* devices resume through their hubs */
+-	if (dev->driver == &usb_generic_driver) {
+-		udev = to_usb_device(dev);
+-		if (udev->state == USB_STATE_NOTATTACHED)
+-			return 0;
+-		return usb_port_resume(udev);
+-	}
+-
+-	if ((dev->driver == NULL) ||
+-	    (dev->driver_data == &usb_generic_driver_data)) {
+-		dev->power.power_state.event = PM_EVENT_FREEZE;
+-		return 0;
+-	}
+-
+-	intf = to_usb_interface(dev);
+-	driver = to_usb_driver(dev->driver);
+-
+-	udev = interface_to_usbdev(intf);
+-	if (udev->state == USB_STATE_NOTATTACHED)
+-		return 0;
+-
+-	/* if driver was suspended, it has a resume method;
+-	 * however, sysfs can wrongly mark things as suspended
+-	 * (on the "no suspend method" FIXME path above)
+-	 */
+-	if (driver->resume) {
+-		status = driver->resume(intf);
+-		if (status) {
+-			dev_err(dev, "%s error %d\n", "resume", status);
+-			mark_quiesced(intf);
+-		}
+-	} else
+-		dev_warn(dev, "no resume for driver %s?\n", driver->name);
+-	return 0;
+-}
+-
+-struct bus_type usb_bus_type = {
+-	.name =		"usb",
+-	.match =	usb_device_match,
+-	.uevent =	usb_uevent,
+-	.suspend =	usb_generic_suspend,
+-	.resume =	usb_generic_resume,
+-};
+-
+ /* format to disable USB on kernel command line is: nousb */
+ __module_param_call("", nousb, param_set_bool, param_get_bool, &nousb, 0444);
+ 
+@@ -1203,8 +898,6 @@ EXPORT_SYMBOL(usb_hub_tt_clear_buffer);
+ 
+ EXPORT_SYMBOL(usb_lock_device_for_reset);
+ 
+-EXPORT_SYMBOL(usb_driver_claim_interface);
+-EXPORT_SYMBOL(usb_driver_release_interface);
+ EXPORT_SYMBOL(usb_find_interface);
+ EXPORT_SYMBOL(usb_ifnum_to_if);
+ EXPORT_SYMBOL(usb_altnum_to_altsetting);
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 5a4eff5eec86..82d397a6f773 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -33,9 +33,9 @@ extern void usb_host_cleanup(void);
+ extern int usb_port_suspend(struct usb_device *dev);
+ extern int usb_port_resume(struct usb_device *dev);
+ 
++extern struct bus_type usb_bus_type;
+ extern struct device_driver usb_generic_driver;
+ extern int usb_generic_driver_data;
+-extern int usb_device_match(struct device *dev, struct device_driver *drv);
+ 
+ /* Interfaces and their "power state" are owned by usbcore */
+ 

commit 140d8f687457c40a66af362838fac0d7893e7df5
+Author: Alan Stern 
+Date:   Sat Jul 1 22:07:21 2006 -0400
+
+    usbcore: rename usb_suspend_device to usb_port_suspend
+    
+    This revised patch (as715b) renames usb_suspend_device to
+    usb_port_suspend, usb_resume_device to usb_port_resume, and
+    finish_device_resume to finish_port_resume.  There was no objection to
+    the original version of the patch so this should be okay to apply.
+    
+    The revision was needed only because I have re-arranged the order of the
+    earlier patches.
+    
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 26c8cb5f3e67..b00514d9a605 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1407,9 +1407,9 @@ int usb_new_device(struct usb_device *udev)
+ 		 * (Includes HNP test device.)
+ 		 */
+ 		if (udev->bus->b_hnp_enable || udev->bus->is_b_host) {
+-			static int __usb_suspend_device(struct usb_device *,
++			static int __usb_port_suspend(struct usb_device *,
+ 						int port1);
+-			err = __usb_suspend_device(udev, udev->bus->otg_port);
++			err = __usb_port_suspend(udev, udev->bus->otg_port);
+ 			if (err < 0)
+ 				dev_dbg(&udev->dev, "HNP fail, %d\n", err);
+ 		}
+@@ -1684,7 +1684,7 @@ static int hub_port_suspend(struct usb_hub *hub, int port1,
+  * the root hub for their bus goes into global suspend ... so we don't
+  * (falsely) update the device power state to say it suspended.
+  */
+-static int __usb_suspend_device (struct usb_device *udev, int port1)
++static int __usb_port_suspend (struct usb_device *udev, int port1)
+ {
+ 	int	status = 0;
+ 
+@@ -1712,8 +1712,8 @@ static int __usb_suspend_device (struct usb_device *udev, int port1)
+ 		}
+ 	}
+ 
+-	/* we only change a device's upstream USB link.
+-	 * root hubs have no upstream USB link.
++	/* we change the device's upstream USB link,
++	 * but root hubs have no upstream USB link.
+ 	 */
+ 	if (udev->parent)
+ 		status = hub_port_suspend(hdev_to_hub(udev->parent), port1,
+@@ -1727,14 +1727,14 @@ static int __usb_suspend_device (struct usb_device *udev, int port1)
+ #endif
+ 
+ /*
+- * usb_suspend_device - suspend a usb device
++ * usb_port_suspend - suspend a usb device's upstream port
+  * @udev: device that's no longer in active use
+  * Context: must be able to sleep; device not locked; pm locks held
+  *
+  * Suspends a USB device that isn't in active use, conserving power.
+  * Devices may wake out of a suspend, if anything important happens,
+  * using the remote wakeup mechanism.  They may also be taken out of
+- * suspend by the host, using usb_resume_device().  It's also routine
++ * suspend by the host, using usb_port_resume().  It's also routine
+  * to disconnect devices while they are suspended.
+  *
+  * This only affects the USB hardware for a device; its interfaces
+@@ -1746,12 +1746,12 @@ static int __usb_suspend_device (struct usb_device *udev, int port1)
+  *
+  * Returns 0 on success, else negative errno.
+  */
+-int usb_suspend_device(struct usb_device *udev)
++int usb_port_suspend(struct usb_device *udev)
+ {
+ #ifdef	CONFIG_USB_SUSPEND
+ 	if (udev->state == USB_STATE_NOTATTACHED)
+ 		return -ENODEV;
+-	return __usb_suspend_device(udev, udev->portnum);
++	return __usb_port_suspend(udev, udev->portnum);
+ #else
+ 	/* NOTE:  udev->state unchanged, it's not lying ... */
+ 	udev->dev.power.power_state = PMSG_SUSPEND;
+@@ -1767,7 +1767,7 @@ int usb_suspend_device(struct usb_device *udev)
+  * resume (by host) or remote wakeup (by device) ... now see what changed
+  * in the tree that's rooted at this device.
+  */
+-static int finish_device_resume(struct usb_device *udev)
++static int finish_port_resume(struct usb_device *udev)
+ {
+ 	int	status;
+ 	u16	devstatus;
+@@ -1891,7 +1891,7 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+ 			/* TRSMRCY = 10 msec */
+ 			msleep(10);
+ 			if (udev)
+-				status = finish_device_resume(udev);
++				status = finish_port_resume(udev);
+ 		}
+ 	}
+ 	if (status < 0)
+@@ -1903,7 +1903,7 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+ #endif
+ 
+ /*
+- * usb_resume_device - re-activate a suspended usb device
++ * usb_port_resume - re-activate a suspended usb device's upstream port
+  * @udev: device to re-activate
+  * Context: must be able to sleep; device not locked; pm locks held
+  *
+@@ -1915,14 +1915,16 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+  *
+  * Returns 0 on success, else negative errno.
+  */
+-int usb_resume_device(struct usb_device *udev)
++int usb_port_resume(struct usb_device *udev)
+ {
+ 	int	status;
+ 
+ 	if (udev->state == USB_STATE_NOTATTACHED)
+ 		return -ENODEV;
+ 
+-	/* selective resume of one downstream hub-to-device port */
++	/* we change the device's upstream USB link,
++	 * but root hubs have no upstream USB link.
++	 */
+ 	if (udev->parent) {
+ #ifdef	CONFIG_USB_SUSPEND
+ 		if (udev->state == USB_STATE_SUSPENDED) {
+@@ -1934,7 +1936,7 @@ int usb_resume_device(struct usb_device *udev)
+ #endif
+ 			status = 0;
+ 	} else
+-		status = finish_device_resume(udev);
++		status = finish_port_resume(udev);
+ 	if (status < 0)
+ 		dev_dbg(&udev->dev, "can't resume, status %d\n",
+ 			status);
+@@ -1962,7 +1964,7 @@ static int remote_wakeup(struct usb_device *udev)
+ 		dev_dbg(&udev->dev, "RESUME (wakeup)\n");
+ 		/* TRSMRCY = 10 msec */
+ 		msleep(10);
+-		status = finish_device_resume(udev);
++		status = finish_port_resume(udev);
+ 	}
+ 	usb_unlock_device(udev);
+ #endif
+@@ -2069,7 +2071,7 @@ static int hub_resume(struct usb_interface *intf)
+ 		if (portstat & USB_PORT_STAT_SUSPEND)
+ 			status = hub_port_resume(hub, port1, udev);
+ 		else {
+-			status = finish_device_resume(udev);
++			status = finish_port_resume(udev);
+ 			if (status < 0) {
+ 				dev_dbg(&intf->dev, "resume port %d --> %d\n",
+ 					port1, status);
+@@ -3128,6 +3130,7 @@ int usb_reset_device(struct usb_device *udev)
+ 	hub_port_logical_disconnect(parent_hub, port1);
+ 	return -ENODEV;
+ }
++EXPORT_SYMBOL(usb_reset_device);
+ 
+ /**
+  * usb_reset_composite_device - warn interface drivers and perform a USB port reset
+@@ -3206,3 +3209,4 @@ int usb_reset_composite_device(struct usb_device *udev,
+ 
+ 	return ret;
+ }
++EXPORT_SYMBOL(usb_reset_composite_device);
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index ab766e0fe4ef..b28a31b20308 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -1014,7 +1014,7 @@ static int usb_generic_suspend(struct device *dev, pm_message_t message)
+ 		status = device_for_each_child(dev, NULL, verify_suspended);
+ 		if (status)
+ 			return status;
+- 		return usb_suspend_device (to_usb_device(dev));
++ 		return usb_port_suspend(to_usb_device(dev));
+ 	}
+ 
+ 	if ((dev->driver == NULL) ||
+@@ -1061,7 +1061,7 @@ static int usb_generic_resume(struct device *dev)
+ 		udev = to_usb_device(dev);
+ 		if (udev->state == USB_STATE_NOTATTACHED)
+ 			return 0;
+-		return usb_resume_device (to_usb_device(dev));
++		return usb_port_resume(udev);
+ 	}
+ 
+ 	if ((dev->driver == NULL) ||
+@@ -1209,9 +1209,6 @@ EXPORT_SYMBOL(usb_find_interface);
+ EXPORT_SYMBOL(usb_ifnum_to_if);
+ EXPORT_SYMBOL(usb_altnum_to_altsetting);
+ 
+-EXPORT_SYMBOL(usb_reset_device);
+-EXPORT_SYMBOL(usb_reset_composite_device);
+-
+ EXPORT_SYMBOL(__usb_get_extra_descriptor);
+ 
+ EXPORT_SYMBOL(usb_find_device);
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 1217fbbe5829..5a4eff5eec86 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -30,8 +30,8 @@ extern void usb_major_cleanup(void);
+ extern int usb_host_init(void);
+ extern void usb_host_cleanup(void);
+ 
+-extern int usb_suspend_device(struct usb_device *dev);
+-extern int usb_resume_device(struct usb_device *dev);
++extern int usb_port_suspend(struct usb_device *dev);
++extern int usb_port_resume(struct usb_device *dev);
+ 
+ extern struct device_driver usb_generic_driver;
+ extern int usb_generic_driver_data;

commit 121e287cb554f3d3402c85a1950d852691b08f5c
+Author: Alan Stern 
+Date:   Sat Jul 1 22:06:36 2006 -0400
+
+    usb-skeleton: don't submit URBs after disconnection
+    
+    This patch (as712b) is a slight revision of one submitted earlier.  It
+    fixes the usb-skeleton example driver so that it won't try to submit
+    URBs after skel_disconnect() has returned.  This could cause errors, if
+    the driver was unbound and then a different driver was bound to the
+    device.  It also fixes a couple of small bugs in the skel_write()
+    routine.
+    
+    The revised patch uses a slightly different test, suggested by Dave
+    Brownell, for determining whether to free a transfer buffer.  It's a
+    little clearer than the earlier version.
+    
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
+index b362039792b3..33f0e81c58d3 100644
+--- a/drivers/usb/usb-skeleton.c
++++ b/drivers/usb/usb-skeleton.c
+@@ -1,5 +1,5 @@
+ /*
+- * USB Skeleton driver - 2.0
++ * USB Skeleton driver - 2.1
+  *
+  * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
+  *
+@@ -8,8 +8,7 @@
+  *	published by the Free Software Foundation, version 2.
+  *
+  * This driver is based on the 2.6.3 version of drivers/usb/usb-skeleton.c 
+- * but has been rewritten to be easy to read and use, as no locks are now
+- * needed anymore.
++ * but has been rewritten to be easier to read and use.
+  *
+  */
+ 
+@@ -21,6 +20,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ 
+ /* Define these values to match your devices */
+@@ -52,6 +52,7 @@ struct usb_skel {
+ 	__u8			bulk_in_endpointAddr;	/* the address of the bulk in endpoint */
+ 	__u8			bulk_out_endpointAddr;	/* the address of the bulk out endpoint */
+ 	struct kref		kref;
++	struct mutex		io_mutex;		/* synchronize I/O with disconnect */
+ };
+ #define to_skel_dev(d) container_of(d, struct usb_skel, kref)
+ 
+@@ -119,7 +120,13 @@ static ssize_t skel_read(struct file *file, char *buffer, size_t count, loff_t *
+ 	int bytes_read;
+ 
+ 	dev = (struct usb_skel *)file->private_data;
+-	
++
++	mutex_lock(&dev->io_mutex);
++	if (!dev->interface) {		/* disconnect() was called */
++		retval = -ENODEV;
++		goto exit;
++	}
++
+ 	/* do a blocking bulk read to get data from the device */
+ 	retval = usb_bulk_msg(dev->udev,
+ 			      usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),
+@@ -135,6 +142,8 @@ static ssize_t skel_read(struct file *file, char *buffer, size_t count, loff_t *
+ 			retval = bytes_read;
+ 	}
+ 
++exit:
++	mutex_unlock(&dev->io_mutex);
+ 	return retval;
+ }
+ 
+@@ -179,6 +188,12 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
+ 		goto exit;
+ 	}
+ 
++	mutex_lock(&dev->io_mutex);
++	if (!dev->interface) {		/* disconnect() was called */
++		retval = -ENODEV;
++		goto error;
++	}
++
+ 	/* create a urb, and a buffer for it, and copy the data to the urb */
+ 	urb = usb_alloc_urb(0, GFP_KERNEL);
+ 	if (!urb) {
+@@ -213,13 +228,18 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
+ 	/* release our reference to this urb, the USB core will eventually free it entirely */
+ 	usb_free_urb(urb);
+ 
+-exit:
++	mutex_unlock(&dev->io_mutex);
+ 	return writesize;
+ 
+ error:
+-	usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma);
+-	usb_free_urb(urb);
++	if (urb) {
++		usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma);
++		usb_free_urb(urb);
++	}
++	mutex_unlock(&dev->io_mutex);
+ 	up(&dev->limit_sem);
++
++exit:
+ 	return retval;
+ }
+ 
+@@ -258,6 +278,7 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
+ 	}
+ 	kref_init(&dev->kref);
+ 	sema_init(&dev->limit_sem, WRITES_IN_FLIGHT);
++	mutex_init(&dev->io_mutex);
+ 
+ 	dev->udev = usb_get_dev(interface_to_usbdev(interface));
+ 	dev->interface = interface;
+@@ -334,6 +355,11 @@ static void skel_disconnect(struct usb_interface *interface)
+ 	/* give back our minor */
+ 	usb_deregister_dev(interface, &skel_class);
+ 
++	/* prevent more I/O from starting */
++	mutex_lock(&dev->io_mutex);
++	dev->interface = NULL;
++	mutex_unlock(&dev->io_mutex);
++
+ 	unlock_kernel();
+ 
+ 	/* decrement our usage count */

commit 349710c3a79c0405911b8b604953f0c665e17756
+Author: Alan Stern 
+Date:   Sat Jul 1 22:05:56 2006 -0400
+
+    usbfs: detect device unregistration
+    
+    This patch (as711b) is a revised version of an earlier submission.  It
+    modifies the usbfs code to detect when a device has been unregistered from
+    usbfs, even if the device is still connected.  Although this can't happen
+    now, it will be able to happen after the upcoming changes to usb_generic.
+    
+    Nobody objected to this patch when it was submitted before, so it should
+    be okay to apply this version.  The revision is merely to take into
+    account the changes introduced by as723, which touches the same driver.
+    
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index d8b0476237f3..e84f19d4089c 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -90,9 +90,10 @@ MODULE_PARM_DESC (usbfs_snoop, "true to log all usbfs traffic");
+ 
+ #define	MAX_USBFS_BUFFER_SIZE	16384
+ 
+-static inline int connected (struct usb_device *dev)
++static inline int connected (struct dev_state *ps)
+ {
+-	return dev->state != USB_STATE_NOTATTACHED;
++	return (!list_empty(&ps->list) &&
++			ps->dev->state != USB_STATE_NOTATTACHED);
+ }
+ 
+ static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig)
+@@ -130,7 +131,7 @@ static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, l
+ 
+ 	pos = *ppos;
+ 	usb_lock_device(dev);
+-	if (!connected(dev)) {
++	if (!connected(ps)) {
+ 		ret = -ENODEV;
+ 		goto err;
+ 	} else if (pos < 0) {
+@@ -1326,7 +1327,7 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
+ 		}
+ 	}
+ 
+-	if (!connected(ps->dev)) {
++	if (!connected(ps)) {
+ 		kfree(buf);
+ 		return -ENODEV;
+ 	}
+@@ -1425,7 +1426,7 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
+ 	if (!(file->f_mode & FMODE_WRITE))
+ 		return -EPERM;
+ 	usb_lock_device(dev);
+-	if (!connected(dev)) {
++	if (!connected(ps)) {
+ 		usb_unlock_device(dev);
+ 		return -ENODEV;
+ 	}
+@@ -1566,7 +1567,7 @@ static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wai
+ 	poll_wait(file, &ps->wait, wait);
+ 	if (file->f_mode & FMODE_WRITE && !list_empty(&ps->async_completed))
+ 		mask |= POLLOUT | POLLWRNORM;
+-	if (!connected(ps->dev))
++	if (!connected(ps))
+ 		mask |= POLLERR | POLLHUP;
+ 	return mask;
+ }

commit 4a2a8a2cce86b9d001378cc25acb5c61e6ca7d63
+Author: Alan Stern 
+Date:   Sat Jul 1 22:05:01 2006 -0400
+
+    usbfs: private mutex for open, release, and remove
+    
+    The usbfs code doesn't provide sufficient mutual exclusion among open,
+    release, and remove.  Release vs. remove is okay because they both
+    acquire the device lock, but open is not exclusive with either one.  All
+    three routines modify the udev->filelist linked list, so they must not
+    run concurrently.
+    
+    Apparently someone gave this a minimum amount of thought in the past by
+    explicitly acquiring the BKL at the start of the usbdev_open routine.
+    Oddly enough, there's a comment pointing out that locking is unnecessary
+    because chrdev_open already has acquired the BKL.
+    
+    But this ignores the point that the files in /proc/bus/usb/* are not
+    char device files; they are regular files and so they don't get any
+    special locking.  Furthermore it's necessary to acquire the same lock in
+    the release and remove routines, which the code does not do.
+    
+    Yet another problem arises because the same file_operations structure is
+    accessible through both the /proc/bus/usb/* and /dev/usb/usbdev* file
+    nodes.  Even when one of them has been removed, it's still possible for
+    userspace to open the other.  So simple locking around the individual
+    remove routines is insufficient; we need to lock the entire
+    usb_notify_remove_device notifier chain.
+    
+    Rather than rely on the BKL, this patch (as723) introduces a new private
+    mutex for the purpose.  Holding the BKL while invoking a notifier chain
+    doesn't seem like a good idea.
+    
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 32e03000420c..d8b0476237f3 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -59,6 +59,9 @@
+ #define USB_DEVICE_MAX			USB_MAXBUS * 128
+ static struct class *usb_device_class;
+ 
++/* Mutual exclusion for removal, open, and release */
++DEFINE_MUTEX(usbfs_mutex);
++
+ struct async {
+ 	struct list_head asynclist;
+ 	struct dev_state *ps;
+@@ -541,15 +544,13 @@ static int usbdev_open(struct inode *inode, struct file *file)
+ 	struct dev_state *ps;
+ 	int ret;
+ 
+-	/* 
+-	 * no locking necessary here, as chrdev_open has the kernel lock
+-	 * (still acquire the kernel lock for safety)
+-	 */
++	/* Protect against simultaneous removal or release */
++	mutex_lock(&usbfs_mutex);
++
+ 	ret = -ENOMEM;
+ 	if (!(ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL)))
+-		goto out_nolock;
++		goto out;
+ 
+-	lock_kernel();
+ 	ret = -ENOENT;
+ 	/* check if we are called from a real node or usbfs */
+ 	if (imajor(inode) == USB_DEVICE_MAJOR)
+@@ -579,9 +580,8 @@ static int usbdev_open(struct inode *inode, struct file *file)
+ 	list_add_tail(&ps->list, &dev->filelist);
+ 	file->private_data = ps;
+  out:
+-	unlock_kernel();
+- out_nolock:
+-        return ret;
++	mutex_unlock(&usbfs_mutex);
++	return ret;
+ }
+ 
+ static int usbdev_release(struct inode *inode, struct file *file)
+@@ -591,7 +591,12 @@ static int usbdev_release(struct inode *inode, struct file *file)
+ 	unsigned int ifnum;
+ 
+ 	usb_lock_device(dev);
++
++	/* Protect against simultaneous open */
++	mutex_lock(&usbfs_mutex);
+ 	list_del_init(&ps->list);
++	mutex_unlock(&usbfs_mutex);
++
+ 	for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed);
+ 			ifnum++) {
+ 		if (test_bit(ifnum, &ps->ifclaimed))
+@@ -600,9 +605,8 @@ static int usbdev_release(struct inode *inode, struct file *file)
+ 	destroy_all_async(ps);
+ 	usb_unlock_device(dev);
+ 	usb_put_dev(dev);
+-	ps->dev = NULL;
+ 	kfree(ps);
+-        return 0;
++	return 0;
+ }
+ 
+ static int proc_control(struct dev_state *ps, void __user *arg)
+diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c
+index b042676af0a5..6b36897ca151 100644
+--- a/drivers/usb/core/notify.c
++++ b/drivers/usb/core/notify.c
+@@ -50,8 +50,11 @@ void usb_notify_add_device(struct usb_device *udev)
+ 
+ void usb_notify_remove_device(struct usb_device *udev)
+ {
++	/* Protect against simultaneous usbfs open */
++	mutex_lock(&usbfs_mutex);
+ 	blocking_notifier_call_chain(&usb_notifier_list,
+ 			USB_DEVICE_REMOVE, udev);
++	mutex_unlock(&usbfs_mutex);
+ }
+ 
+ void usb_notify_add_bus(struct usb_bus *ubus)
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 49f69236b420..1217fbbe5829 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -59,6 +59,7 @@ static inline int is_active(struct usb_interface *f)
+ extern const char *usbcore_name;
+ 
+ /* usbfs stuff */
++extern struct mutex usbfs_mutex;
+ extern struct usb_driver usbfs_driver;
+ extern struct file_operations usbfs_devices_fops;
+ extern struct file_operations usbfs_device_file_operations;

commit b6eb2d84d2bb01e9fcc46a032a3429b4747b1c47
+Author: Alan Stern 
+Date:   Thu Jul 6 15:37:42 2006 -0400
+
+    usbcore: add configuration_string to attribute group
+    
+    This patch (as737b) does a very small cleanup of core/sysfs.c by adding
+    the configuration_string attribute file to the existing attribute group
+    instead of treating it separately.  It doesn't need this separate
+    treatment because unlike the other device string attributes, it changes
+    along with the active configuration.
+    
+    The patch also fixes a simple typo (which, oddly enough, doesn't seem to
+    bother the compiler).
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index dec973affb0f..cd2286246f6a 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -60,7 +60,7 @@ static ssize_t
+ set_bConfigurationValue (struct device *dev, struct device_attribute *attr,
+ 		const char *buf, size_t count)
+ {
+-	struct usb_device	*udev = udev = to_usb_device (dev);
++	struct usb_device	*udev = to_usb_device (dev);
+ 	int			config, value;
+ 
+ 	if (sscanf (buf, "%u", &config) != 1 || config > 255)
+@@ -186,6 +186,7 @@ usb_descriptor_attr (bMaxPacketSize0, "%d\n")
+ 
+ static struct attribute *dev_attrs[] = {
+ 	/* current configuration's attributes */
++	&dev_attr_configuration.attr,
+ 	&dev_attr_bNumInterfaces.attr,
+ 	&dev_attr_bConfigurationValue.attr,
+ 	&dev_attr_bmAttributes.attr,
+@@ -221,7 +222,6 @@ void usb_create_sysfs_dev_files (struct usb_device *udev)
+ 		device_create_file (dev, &dev_attr_product);
+ 	if (udev->serial)
+ 		device_create_file (dev, &dev_attr_serial);
+-	device_create_file (dev, &dev_attr_configuration);
+ 	usb_create_ep_files(dev, &udev->ep0, udev);
+ }
+ 
+@@ -238,7 +238,6 @@ void usb_remove_sysfs_dev_files (struct usb_device *udev)
+ 		device_remove_file(dev, &dev_attr_product);
+ 	if (udev->serial)
+ 		device_remove_file(dev, &dev_attr_serial);
+-	device_remove_file (dev, &dev_attr_configuration);
+ }
+ 
+ /* Interface fields */

commit b97b196c9d351a501ed89fc836e4e2fe71ff93c9
+Author: Alan Stern 
+Date:   Thu Sep 14 15:18:54 2006 -0400
+
+    USB: unusual_devs entry for Lacie DVD+-RW
+    
+    This patch (as781) adds an entry to unusual_devs.h for the Lacie DVD+-RW
+    drive.  Apparently its USB interface has requirements similar to the
+    Genesys Logic interface; it doesn't like data to be sent too soon after
+    a command.
+    
+    This fixes Bugzilla #6817.
+    
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Phil Dibowitz 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index b130e170b4a8..4b06ac34430f 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -631,6 +631,13 @@ UNUSUAL_DEV(  0x0595, 0x4343, 0x0000, 0x2210,
+ 		"Digital Camera EX-20 DSC",
+ 		US_SC_8070, US_PR_DEVICE, NULL, 0 ),
+ 
++/* Reported by  */
++UNUSUAL_DEV(  0x059f, 0x0643, 0x0000, 0x0000,
++		"LaCie",
++		"DVD+-RW",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_GO_SLOW ),
++
+ /* Submitted by Joel Bourquard 
+  * Some versions of this device need the SubClass and Protocol overrides
+  * while others don't.

commit 7e9f4b2d3e21e87c26025810413ef1592834e63b
+Author: Alan Stern 
+Date:   Mon Sep 18 16:28:06 2006 -0400
+
+    Driver core: Don't call put methods while holding a spinlock
+    
+    The klist utility routines currently call _put methods while holding a
+    spinlock.  This is of course illegal; a put routine could try to
+    unregister a device and hence need to sleep.
+    
+    No problems have arisen until now because in many cases klist removals
+    were done synchronously, so the _put methods were never actually used.
+    In other cases we may simply have been lucky.
+    
+    This patch (as784) reworks the klist routines so that _put methods are
+    called only _after_ the klist's spinlock has been released.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/lib/klist.c b/lib/klist.c
+index 9c94f0b163a1..120bd175aa78 100644
+--- a/lib/klist.c
++++ b/lib/klist.c
+@@ -123,12 +123,10 @@ EXPORT_SYMBOL_GPL(klist_add_tail);
+ static void klist_release(struct kref * kref)
+ {
+ 	struct klist_node * n = container_of(kref, struct klist_node, n_ref);
+-	void (*put)(struct klist_node *) = n->n_klist->put;
++
+ 	list_del(&n->n_node);
+ 	complete(&n->n_removed);
+ 	n->n_klist = NULL;
+-	if (put)
+-		put(n);
+ }
+ 
+ static int klist_dec_and_del(struct klist_node * n)
+@@ -145,10 +143,14 @@ static int klist_dec_and_del(struct klist_node * n)
+ void klist_del(struct klist_node * n)
+ {
+ 	struct klist * k = n->n_klist;
++	void (*put)(struct klist_node *) = k->put;
+ 
+ 	spin_lock(&k->k_lock);
+-	klist_dec_and_del(n);
++	if (!klist_dec_and_del(n))
++		put = NULL;
+ 	spin_unlock(&k->k_lock);
++	if (put)
++		put(n);
+ }
+ 
+ EXPORT_SYMBOL_GPL(klist_del);
+@@ -161,10 +163,7 @@ EXPORT_SYMBOL_GPL(klist_del);
+ 
+ void klist_remove(struct klist_node * n)
+ {
+-	struct klist * k = n->n_klist;
+-	spin_lock(&k->k_lock);
+-	klist_dec_and_del(n);
+-	spin_unlock(&k->k_lock);
++	klist_del(n);
+ 	wait_for_completion(&n->n_removed);
+ }
+ 
+@@ -260,12 +259,15 @@ static struct klist_node * to_klist_node(struct list_head * n)
+ struct klist_node * klist_next(struct klist_iter * i)
+ {
+ 	struct list_head * next;
++	struct klist_node * lnode = i->i_cur;
+ 	struct klist_node * knode = NULL;
++	void (*put)(struct klist_node *) = i->i_klist->put;
+ 
+ 	spin_lock(&i->i_klist->k_lock);
+-	if (i->i_cur) {
+-		next = i->i_cur->n_node.next;
+-		klist_dec_and_del(i->i_cur);
++	if (lnode) {
++		next = lnode->n_node.next;
++		if (!klist_dec_and_del(lnode))
++			put = NULL;
+ 	} else
+ 		next = i->i_head->next;
+ 
+@@ -275,6 +277,8 @@ struct klist_node * klist_next(struct klist_iter * i)
+ 	}
+ 	i->i_cur = knode;
+ 	spin_unlock(&i->i_klist->k_lock);
++	if (put && lnode)
++		put(lnode);
+ 	return knode;
+ }
+ 

commit 81107bf531d2524afbcd61f3b4ad57a71295d591
+Author: Alan Stern 
+Date:   Mon Sep 18 16:24:28 2006 -0400
+
+    Driver core: Remove unneeded routines from driver core
+    
+    This patch (as783) simplifies the driver core slightly by removing four
+    unnecessary _get and _put methods.
+    
+    It is vital that when a driver is removed from its bus's klist of
+    registered drivers, or when a device is removed from a driver's klist
+    of bound devices, that the klist updates complete synchronously.
+    Otherwise the kernel might try binding an unregistered driver to a
+    newly-registered device, or adding a device to the klist for a new
+    driver before it has been removed from the old driver's klist.
+    
+    Since the removals must be synchronous, they don't need to update any
+    reference counts.  Hence the _get and _put methods can be dispensed
+    with.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/base/bus.c b/drivers/base/bus.c
+index 636af538a2b5..12173d16bea7 100644
+--- a/drivers/base/bus.c
++++ b/drivers/base/bus.c
+@@ -696,22 +696,6 @@ static void klist_devices_put(struct klist_node *n)
+ 	put_device(dev);
+ }
+ 
+-static void klist_drivers_get(struct klist_node *n)
+-{
+-	struct device_driver *drv = container_of(n, struct device_driver,
+-						 knode_bus);
+-
+-	get_driver(drv);
+-}
+-
+-static void klist_drivers_put(struct klist_node *n)
+-{
+-	struct device_driver *drv = container_of(n, struct device_driver,
+-						 knode_bus);
+-
+-	put_driver(drv);
+-}
+-
+ /**
+  *	bus_register - register a bus with the system.
+  *	@bus:	bus.
+@@ -747,7 +731,7 @@ int bus_register(struct bus_type * bus)
+ 		goto bus_drivers_fail;
+ 
+ 	klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put);
+-	klist_init(&bus->klist_drivers, klist_drivers_get, klist_drivers_put);
++	klist_init(&bus->klist_drivers, NULL, NULL);
+ 	bus_add_attrs(bus);
+ 
+ 	pr_debug("bus type '%s' registered\n", bus->name);
+diff --git a/drivers/base/driver.c b/drivers/base/driver.c
+index 562600dd540a..1214cbd17d86 100644
+--- a/drivers/base/driver.c
++++ b/drivers/base/driver.c
+@@ -142,20 +142,6 @@ void put_driver(struct device_driver * drv)
+ 	kobject_put(&drv->kobj);
+ }
+ 
+-static void klist_devices_get(struct klist_node *n)
+-{
+-	struct device *dev = container_of(n, struct device, knode_driver);
+-
+-	get_device(dev);
+-}
+-
+-static void klist_devices_put(struct klist_node *n)
+-{
+-	struct device *dev = container_of(n, struct device, knode_driver);
+-
+-	put_device(dev);
+-}
+-
+ /**
+  *	driver_register - register driver with bus
+  *	@drv:	driver to register
+@@ -175,7 +161,7 @@ int driver_register(struct device_driver * drv)
+ 	    (drv->bus->shutdown && drv->shutdown)) {
+ 		printk(KERN_WARNING "Driver '%s' needs updating - please use bus_type methods\n", drv->name);
+ 	}
+-	klist_init(&drv->klist_devices, klist_devices_get, klist_devices_put);
++	klist_init(&drv->klist_devices, NULL, NULL);
+ 	init_completion(&drv->unloaded);
+ 	return bus_add_driver(drv);
+ }

commit f2eaae197f4590c4d96f31b09b0ee9067421a95c
+Author: Alan Stern 
+Date:   Mon Sep 18 16:22:34 2006 -0400
+
+    Driver core: Fix potential deadlock in driver core
+    
+    There is a potential deadlock in the driver core.  It boils down to
+    the fact that bus_remove_device() calls klist_remove() instead of
+    klist_del(), thereby waiting until the reference count of the
+    klist_node in the bus's klist of devices drops to 0.  The refcount
+    can't reach 0 so long as a modprobe process is trying to bind a new
+    driver to the device being removed, by calling __driver_attach().  The
+    problem is that __driver_attach() tries to acquire the device's
+    parent's semaphore, but the caller of bus_remove_device() is quite
+    likely to own that semaphore already.
+    
+    It isn't sufficient just to replace klist_remove() with klist_del().
+    Doing so runs the risk that the device would remain on the bus's klist
+    of devices for some time, and so could be bound to another driver even
+    after it was unregistered.  What's needed is a new way to distinguish
+    whether or not a device is registered, based on a criterion other than
+    whether its klist_node is linked into the bus's klist of devices.  That
+    way driver binding can fail when the device is unregistered, even if
+    it is still linked into the klist.
+    
+    This patch (as782) implements the solution, by adding a new bitflag to
+    indiate when a struct device is registered, by testing the flag before
+    allowing a driver to bind a device, and by changing the definition of
+    the device_is_registered() inline.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/base/bus.c b/drivers/base/bus.c
+index aa685a20b649..636af538a2b5 100644
+--- a/drivers/base/bus.c
++++ b/drivers/base/bus.c
+@@ -392,6 +392,7 @@ int bus_add_device(struct device * dev)
+  *	bus_attach_device - add device to bus
+  *	@dev:	device tried to attach to a driver
+  *
++ *	- Add device to bus's list of devices.
+  *	- Try to attach to driver.
+  */
+ int bus_attach_device(struct device * dev)
+@@ -400,11 +401,13 @@ int bus_attach_device(struct device * dev)
+ 	int ret = 0;
+ 
+ 	if (bus) {
++		dev->is_registered = 1;
+ 		ret = device_attach(dev);
+ 		if (ret >= 0) {
+ 			klist_add_tail(&dev->knode_bus, &bus->klist_devices);
+ 			ret = 0;
+-		}
++		} else
++			dev->is_registered = 0;
+ 	}
+ 	return ret;
+ }
+@@ -425,7 +428,8 @@ void bus_remove_device(struct device * dev)
+ 		sysfs_remove_link(&dev->kobj, "bus");
+ 		sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id);
+ 		device_remove_attrs(dev->bus, dev);
+-		klist_remove(&dev->knode_bus);
++		dev->is_registered = 0;
++		klist_del(&dev->knode_bus);
+ 		pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id);
+ 		device_release_driver(dev);
+ 		put_bus(dev->bus);
+diff --git a/drivers/base/dd.c b/drivers/base/dd.c
+index 319a73be4180..b5f43c3e44fa 100644
+--- a/drivers/base/dd.c
++++ b/drivers/base/dd.c
+@@ -162,6 +162,8 @@ int driver_probe_device(struct device_driver * drv, struct device * dev)
+ 	struct task_struct *probe_task;
+ 	int ret = 0;
+ 
++	if (!device_is_registered(dev))
++		return -ENODEV;
+ 	if (drv->bus->match && !drv->bus->match(dev, drv))
+ 		goto done;
+ 
+diff --git a/include/linux/device.h b/include/linux/device.h
+index 74246efba931..662e6a10144e 100644
+--- a/include/linux/device.h
++++ b/include/linux/device.h
+@@ -329,6 +329,7 @@ struct device {
+ 
+ 	struct kobject kobj;
+ 	char	bus_id[BUS_ID_SIZE];	/* position on parent bus */
++	unsigned		is_registered:1;
+ 	struct device_attribute uevent_attr;
+ 	struct device_attribute *devt_attr;
+ 
+@@ -381,7 +382,7 @@ dev_set_drvdata (struct device *dev, void *data)
+ 
+ static inline int device_is_registered(struct device *dev)
+ {
+-	return klist_node_attached(&dev->knode_bus);
++	return dev->is_registered;
+ }
+ 
+ /*

commit e5b3cd42960a10c1bc3701d4f00767463c88ec9d
+Author: Alan Stern 
+Date:   Mon Aug 21 15:53:25 2006 -0400
+
+    [SCSI] SCSI: sanitize INQUIRY strings
+    
+    Sanitize the Vendor, Product, and Revision strings contained in an
+    INQUIRY result by setting all non-graphic or non-ASCII characters to ' '.
+    Since the standard disallows such characters, this will affect
+    only non-compliant devices.
+    
+    To help maintain backward compatibility, NUL characters are treated
+    specially.  They are taken as string terminators; they and all the
+    following characters are set to ' '.  If some valid characters get
+    erased as a result... well, we weren't seeing them before so we haven't
+    lost anything.
+    
+    The primary purpose of this change is to allow blacklist entries to
+    match devices with illegal Vendor or Product strings.
+    
+    In addition, the patch updates a couple of function prototypes, giving
+    inq_result its correct type (unsigned char *).
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+index a24d3461fc78..31d05ab0b2fc 100644
+--- a/drivers/scsi/scsi_scan.c
++++ b/drivers/scsi/scsi_scan.c
+@@ -396,6 +396,32 @@ void scsi_target_reap(struct scsi_target *starget)
+ 	return;
+ }
+ 
++/**
++ * sanitize_inquiry_string - remove non-graphical chars from an INQUIRY result string
++ * @s: INQUIRY result string to sanitize
++ * @len: length of the string
++ *
++ * Description:
++ *	The SCSI spec says that INQUIRY vendor, product, and revision
++ *	strings must consist entirely of graphic ASCII characters,
++ *	padded on the right with spaces.  Since not all devices obey
++ *	this rule, we will replace non-graphic or non-ASCII characters
++ *	with spaces.  Exception: a NUL character is interpreted as a
++ *	string terminator, so all the following characters are set to
++ *	spaces.
++ **/
++static void sanitize_inquiry_string(unsigned char *s, int len)
++{
++	int terminated = 0;
++
++	for (; len > 0; (--len, ++s)) {
++		if (*s == 0)
++			terminated = 1;
++		if (terminated || *s < 0x20 || *s > 0x7e)
++			*s = ' ';
++	}
++}
++
+ /**
+  * scsi_probe_lun - probe a single LUN using a SCSI INQUIRY
+  * @sdev:	scsi_device to probe
+@@ -410,7 +436,7 @@ void scsi_target_reap(struct scsi_target *starget)
+  *     INQUIRY data is in @inq_result; the scsi_level and INQUIRY length
+  *     are copied to the scsi_device any flags value is stored in *@bflags.
+  **/
+-static int scsi_probe_lun(struct scsi_device *sdev, char *inq_result,
++static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result,
+ 			  int result_len, int *bflags)
+ {
+ 	unsigned char scsi_cmd[MAX_COMMAND_SIZE];
+@@ -469,7 +495,11 @@ static int scsi_probe_lun(struct scsi_device *sdev, char *inq_result,
+ 	}
+ 
+ 	if (result == 0) {
+-		response_len = (unsigned char) inq_result[4] + 5;
++		sanitize_inquiry_string(&inq_result[8], 8);
++		sanitize_inquiry_string(&inq_result[16], 16);
++		sanitize_inquiry_string(&inq_result[32], 4);
++
++		response_len = inq_result[4] + 5;
+ 		if (response_len > 255)
+ 			response_len = first_inquiry_len;	/* sanity */
+ 
+@@ -575,7 +605,8 @@ static int scsi_probe_lun(struct scsi_device *sdev, char *inq_result,
+  *     SCSI_SCAN_NO_RESPONSE: could not allocate or setup a scsi_device
+  *     SCSI_SCAN_LUN_PRESENT: a new scsi_device was allocated and initialized
+  **/
+-static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags)
++static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
++		int *bflags)
+ {
+ 	/*
+ 	 * XXX do not save the inquiry, since it can change underneath us,

commit db59b464f8708cdba857f16b183cff0b7466d6b5
+Author: Alan Stern 
+Date:   Thu Aug 31 14:18:39 2006 -0400
+
+    uhci-hcd: fix list access bug
+    
+    When skipping to the last TD of an URB, go to the _last_ entry in the
+    list instead of the _first_ entry (as780).  This fixes Bugzilla #6747
+    and possibly others.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 026dad06f82b..431e8f31f1a9 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -372,7 +372,7 @@ static void uhci_fixup_toggles(struct uhci_qh *qh, int skip_first)
+ 		 * need to change any toggles in this URB */
+ 		td = list_entry(urbp->td_list.next, struct uhci_td, list);
+ 		if (toggle > 1 || uhci_toggle(td_token(td)) == toggle) {
+-			td = list_entry(urbp->td_list.next, struct uhci_td,
++			td = list_entry(urbp->td_list.prev, struct uhci_td,
+ 					list);
+ 			toggle = uhci_toggle(td_token(td)) ^ 1;
+ 

commit 7ceb932f489e86b555258e5f7d7f061f9c1863eb
+Author: Alan Stern 
+Date:   Mon Aug 21 11:58:50 2006 -0400
+
+    UHCI: don't stop at an Iso error
+    
+    Unlike other sorts of endpoint queues, Isochronous queues don't stop
+    when an error is encountered.  This patch (as772) fixes the scanning
+    routine in uhci-hcd, to make it keep on going when it finds an Iso
+    error.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 66c3f61bc9d1..026dad06f82b 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -1348,7 +1348,7 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh,
+ 		}
+ 
+ 		uhci_giveback_urb(uhci, qh, urb, regs);
+-		if (status < 0)
++		if (status < 0 && qh->type != USB_ENDPOINT_XFER_ISOC)
+ 			break;
+ 	}
+ 

commit 94918ff68a7c78fdd3241d13e18444ef80b8ff4a
+Author: Alan Stern 
+Date:   Mon Aug 14 11:40:46 2006 -0400
+
+    [PATCH] unusual_devs update for UCR-61S2B
+    
+    The existing unusual_devs entry for the UCR-61S2B appears to have too
+    wide a revision range.  It matches at least one device that doesn't
+    respond to the initialization sequence.  Perhaps the sequence needs to
+    be updated, or perhaps something else can be done.  For now, this patch
+    (as764) restricts the range to include only the revision mentioned in
+    the original comment.
+    
+    This resolves (for now!) Bugzilla entry #6950.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index fd158e063c06..4a803d69fa36 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -1261,7 +1261,7 @@ UNUSUAL_DEV(  0x0fce, 0xd008, 0x0000, 0x0000,
+  * Tested on hardware version 1.10.
+  * Entry is needed only for the initializer function override.
+  */
+-UNUSUAL_DEV(  0x1019, 0x0c55, 0x0000, 0x9999,
++UNUSUAL_DEV(  0x1019, 0x0c55, 0x0110, 0x0110,
+ 		"Desknote",
+ 		"UCR-61S2B",
+ 		US_SC_DEVICE, US_PR_DEVICE, usb_stor_ucr61s2b_init,

commit f443ddf1057776ed99d5006bbbefb018fcf7ce3a
+Author: Alan Stern 
+Date:   Mon Jul 31 10:16:24 2006 -0400
+
+    USB: UHCI: Don't test the Short Packet Detect bit
+    
+    Apparently some UHCI controllers change the value of the Short Packet
+    Detect (SPD) bit in the TD status word -- presumably when they receive a
+    short packet.  This patch (as759) changes uhci-hcd to avoid assuming
+    that the bit is unchanged; in fact, the driver no longer looks at SPD at
+    all.
+    
+    This fixes the second problem reported in Bugzilla #6752.
+    
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index c9d72ac0a1d7..66c3f61bc9d1 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -943,7 +943,9 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
+ 			/* We received a short packet */
+ 			if (urb->transfer_flags & URB_SHORT_NOT_OK)
+ 				ret = -EREMOTEIO;
+-			else if (ctrlstat & TD_CTRL_SPD)
++
++			/* Fixup needed only if this isn't the URB's last TD */
++			else if (&td->list != urbp->td_list.prev)
+ 				ret = 1;
+ 		}
+ 

commit de1caa475120c716ff33d344b5ffefc288ed77c7
+Author: Alan Stern 
+Date:   Mon Jul 31 10:10:28 2006 -0400
+
+    USB: unusual_devs entry for Nokia 3250
+    
+    Here is another unusual_devs entry (as760) for another Nokia device,
+    this time the 3250.
+    
+    From: Mario Rettig 
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Phil Dibowitz 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 0f0874fffe50..2793f9a912b4 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -145,6 +145,13 @@ UNUSUAL_DEV(  0x0420, 0x0001, 0x0100, 0x0100,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_IGNORE_RESIDUE ),
+ 
++/* Reported by Mario Rettig  */
++UNUSUAL_DEV(  0x0421, 0x042e, 0x0100, 0x0100,
++		"Nokia",
++		"Nokia 3250",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
++
+ /* Reported by Sumedha Swamy  and
+  * Einar Th. Einarsson  */
+ UNUSUAL_DEV(  0x0421, 0x0444, 0x0100, 0x0100,

commit b4dbda1a22d236842b75be4e2679a96a4fd72632
+Author: Alan Stern 
+Date:   Fri Jul 28 17:07:34 2006 -0400
+
+    USB: dummy-hcd: disable interrupts during req->complete
+    
+    This patch (as756) fixes a bug in dummy-hcd found by the lockdep
+    checker.  In one of the code paths, the driver did not disable
+    interrupts before calling a request completion routine.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index 4be47195bd38..7d1c22c34957 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -609,7 +609,8 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req)
+ 	if (!dum->driver)
+ 		return -ESHUTDOWN;
+ 
+-	spin_lock_irqsave (&dum->lock, flags);
++	local_irq_save (flags);
++	spin_lock (&dum->lock);
+ 	list_for_each_entry (req, &ep->queue, queue) {
+ 		if (&req->req == _req) {
+ 			list_del_init (&req->queue);
+@@ -618,7 +619,7 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req)
+ 			break;
+ 		}
+ 	}
+-	spin_unlock_irqrestore (&dum->lock, flags);
++	spin_unlock (&dum->lock);
+ 
+ 	if (retval == 0) {
+ 		dev_dbg (udc_dev(dum),
+@@ -626,6 +627,7 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req)
+ 				req, _ep->name, _req->length, _req->buf);
+ 		_req->complete (_ep, _req);
+ 	}
++	local_irq_restore (flags);
+ 	return retval;
+ }
+ 

commit 57b01b1e393b8b874421fb77d4f078b8ce725e63
+Author: Alan Stern 
+Date:   Mon Jul 10 11:51:12 2006 -0400
+
+    [PATCH] USB: unusual_devs entry for Nokia E61
+    
+    This patch (as748) adds an unusual_devs entry for the Nokia E61 mobile
+    phone.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 91ad1a4123e2..4150b5825559 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -155,6 +155,13 @@ UNUSUAL_DEV(  0x0421, 0x0446, 0x0100, 0x0100,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
+ 
++/* Reported by Matthew Bloch  */
++UNUSUAL_DEV(  0x0421, 0x044e, 0x0100, 0x0100,
++		"Nokia",
++		"E61",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
++
+ /* Reported by Olaf Hering  from novell bug #105878 */
+ UNUSUAL_DEV(  0x0424, 0x0fdc, 0x0210, 0x0210,
+ 		"SMSC",

commit 9a01355e1779356a69d80d917aef009eda44284a
+Author: Alan Stern 
+Date:   Fri Jul 7 13:45:13 2006 -0400
+
+    [PATCH] USB: unusual_devs entry for Nokia N91
+    
+    This patch (as745) adds an unusual_devs entry for the Nokia N91, just like
+    the entry for the N80 added a couple of weeks ago.  Apparently Nokia isn't
+    using very good firmware these days...
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index b6a0eb8dc7e2..91ad1a4123e2 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -139,6 +139,14 @@ UNUSUAL_DEV(  0x0420, 0x0001, 0x0100, 0x0100,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_IGNORE_RESIDUE ),
+ 
++/* Reported by Sumedha Swamy  and
++ * Einar Th. Einarsson  */
++UNUSUAL_DEV(  0x0421, 0x0444, 0x0100, 0x0100,
++		"Nokia",
++		"N91",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
++
+ /* Reported by Jiri Slaby  and
+  * Rene C. Castberg  */
+ UNUSUAL_DEV(  0x0421, 0x0446, 0x0100, 0x0100,

commit 20307949469269ceea6262aaa306dcb55cf43b25
+Author: Alan Stern 
+Date:   Wed Jun 28 11:20:41 2006 -0400
+
+    [PATCH] usbcore: fixes for hub_port_resume
+    
+    This patch (as731) makes a couple of small fixes to the hub_port_resume
+    routine:
+    
+            Don't return status >= 0 when an error occurs;
+    
+            Clear the port-change-suspend status indicator after
+            resuming a device.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 41531bba4321..26c8cb5f3e67 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1882,7 +1882,12 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+ 			dev_dbg(hub->intfdev,
+ 				"port %d status %04x.%04x after resume, %d\n",
+ 				port1, portchange, devstatus, status);
++			if (status >= 0)
++				status = -ENODEV;
+ 		} else {
++			if (portchange & USB_PORT_STAT_C_SUSPEND)
++				clear_port_feature(hub->hdev, port1,
++						USB_PORT_FEAT_C_SUSPEND);
+ 			/* TRSMRCY = 10 msec */
+ 			msleep(10);
+ 			if (udev)

commit b40b7a905ce57608ca93c5032d5ab1f5508d2f11
+Author: Alan Stern 
+Date:   Mon Jun 19 15:12:38 2006 -0400
+
+    [PATCH] USB hub: don't return status > 0 from resume
+    
+    finish_device_resume() in the hub driver isn't careful always to return
+    a negative code in all the error pathways.  It also doesn't return 0 in
+    all the success pathways.  This patch (as724) fixes the behavior.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 875596e98e42..41531bba4321 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1790,7 +1790,10 @@ static int finish_device_resume(struct usb_device *udev)
+ 	 * and device drivers will know about any resume quirks.
+ 	 */
+ 	status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
+-	if (status < 2)
++	if (status >= 0)
++		status = (status == 2 ? 0 : -ENODEV);
++
++	if (status)
+ 		dev_dbg(&udev->dev,
+ 			"gone after usb resume? status %d\n",
+ 			status);

commit eecd11ed47c8c9bd8e7e3dff35baccae18dd0d84
+Author: Alan Stern 
+Date:   Mon Jun 19 14:50:15 2006 -0400
+
+    [PATCH] usb-storage: fix race between reset and disconnect
+    
+    My recent patch converting usb-storage to use
+    usb_reset_composite_device() added a bug, a race between reset and
+    disconnect.  It was necessary to drop the private lock while executing a
+    reset, and if a disconnect occurs at that time it will cause a crash.
+    
+    This patch (as722) fixes the problem by explicitly checking for an early
+    termination after executing each command.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 1185acac4b21..04c3bec81201 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -373,8 +373,12 @@ static int usb_stor_control_thread(void * __us)
+ 		/* lock access to the state */
+ 		scsi_lock(host);
+ 
++		/* did the command already complete because of a disconnect? */
++		if (!us->srb)
++			;		/* nothing to do */
++
+ 		/* indicate that the command is done */
+-		if (us->srb->result != DID_ABORT << 16) {
++		else if (us->srb->result != DID_ABORT << 16) {
+ 			US_DEBUGP("scsi cmd done, result=0x%x\n", 
+ 				   us->srb->result);
+ 			us->srb->scsi_done(us->srb);
+@@ -836,32 +840,34 @@ static void dissociate_dev(struct us_data *us)
+  * the host */
+ static void quiesce_and_remove_host(struct us_data *us)
+ {
++	struct Scsi_Host *host = us_to_host(us);
++
+ 	/* Prevent new USB transfers, stop the current command, and
+ 	 * interrupt a SCSI-scan or device-reset delay */
++	scsi_lock(host);
+ 	set_bit(US_FLIDX_DISCONNECTING, &us->flags);
++	scsi_unlock(host);
+ 	usb_stor_stop_transport(us);
+ 	wake_up(&us->delay_wait);
+ 
+ 	/* It doesn't matter if the SCSI-scanning thread is still running.
+ 	 * The thread will exit when it sees the DISCONNECTING flag. */
+ 
+-	/* Wait for the current command to finish, then remove the host */
+-	mutex_lock(&us->dev_mutex);
+-	mutex_unlock(&us->dev_mutex);
+-
+ 	/* queuecommand won't accept any new commands and the control
+ 	 * thread won't execute a previously-queued command.  If there
+ 	 * is such a command pending, complete it with an error. */
++	mutex_lock(&us->dev_mutex);
+ 	if (us->srb) {
+ 		us->srb->result = DID_NO_CONNECT << 16;
+-		scsi_lock(us_to_host(us));
++		scsi_lock(host);
+ 		us->srb->scsi_done(us->srb);
+ 		us->srb = NULL;
+-		scsi_unlock(us_to_host(us));
++		scsi_unlock(host);
+ 	}
++	mutex_unlock(&us->dev_mutex);
+ 
+ 	/* Now we own no commands so it's safe to remove the SCSI host */
+-	scsi_remove_host(us_to_host(us));
++	scsi_remove_host(host);
+ }
+ 
+ /* Second stage of disconnect processing: deallocate all resources */

commit d6b7d3b62069be60d5b13358bac8670dacdd7a81
+Author: Alan Stern 
+Date:   Mon Jul 10 04:44:47 2006 -0700
+
+    [PATCH] usb-storage: wait for URB to complete
+    
+    We all failed to notice that Franck's recent update to usb-storage allowed
+    an URB to complete after its context data was no longer valid.  This patch
+    (as746) makes the driver wait for the URB to complete whenever there's a
+    timeout.
+    
+    Although timeouts in usb-storage are relatively uncommon, they do occur.
+    Without this patch the code in 2.6.18-rc1 will fault within an interrupt
+    handler, which is not nice at all.
+    
+    Signed-off-by: Alan Stern 
+    Cc: Greg KH 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+index eb7188b3565c..d6acc92a4ae3 100644
+--- a/drivers/usb/storage/transport.c
++++ b/drivers/usb/storage/transport.c
+@@ -180,7 +180,7 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)
+ 	if (timeleft <= 0) {
+ 		US_DEBUGP("%s -- cancelling URB\n",
+ 			  timeleft == 0 ? "Timeout" : "Signal");
+-		usb_unlink_urb(us->current_urb);
++		usb_kill_urb(us->current_urb);
+ 	}
+ 
+ 	/* return the URB status */

commit 9ea7290902abcf22f796e9aeae4dc2e71d3f7e67
+Author: Alan Stern 
+Date:   Fri Jun 23 14:25:34 2006 -0400
+
+    [SCSI] SCSI core: Allow QUIESCE -> CANCEL sdev transition
+    
+    We have to be able to remove SCSI devices even when they are suspended, so
+    QUIESCE -> CANCEL must be a legal state transition.  This patch (as727)
+    adds the transition to the state machine.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index 4c4add53d69b..68e0d7dbe6ce 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -2026,6 +2026,7 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state)
+ 		switch (oldstate) {
+ 		case SDEV_CREATED:
+ 		case SDEV_RUNNING:
++		case SDEV_QUIESCE:
+ 		case SDEV_OFFLINE:
+ 		case SDEV_BLOCK:
+ 			break;

commit bbb1747d4e44ce49acc73daa8d66e5f6bd546f1b
+Author: Alan Stern 
+Date:   Sun Jun 25 05:47:15 2006 -0700
+
+    [PATCH] Allow raw_notifier callouts to unregister themselves
+    
+    Since raw_notifier chains don't benefit from any centralized locking
+    protections, they shouldn't suffer from the associated limitations.  Under
+    some circumstances it might make sense for a raw_notifier callout routine
+    to unregister itself from the notifier chain.  This patch (as678) changes
+    the notifier core to allow for such things.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/kernel/sys.c b/kernel/sys.c
+index 90930b28d2ca..7e0927bad713 100644
+--- a/kernel/sys.c
++++ b/kernel/sys.c
+@@ -137,14 +137,15 @@ static int __kprobes notifier_call_chain(struct notifier_block **nl,
+ 		unsigned long val, void *v)
+ {
+ 	int ret = NOTIFY_DONE;
+-	struct notifier_block *nb;
++	struct notifier_block *nb, *next_nb;
+ 
+ 	nb = rcu_dereference(*nl);
+ 	while (nb) {
++		next_nb = rcu_dereference(nb->next);
+ 		ret = nb->notifier_call(nb, val, v);
+ 		if ((ret & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK)
+ 			break;
+-		nb = rcu_dereference(nb->next);
++		nb = next_nb;
+ 	}
+ 	return ret;
+ }

commit d5681fe8110e1169902df37a8fd8bd01c2b7810e
+Author: Alan Stern 
+Date:   Tue Jun 13 09:59:32 2006 -0400
+
+    [PATCH] USB: unusual_devs entry for Nokia N80
+    
+    Here is a patch (as720) adding an unusual_devs entry for the Nokia N80
+    mobile phone.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 3ec17689b81c..543244d421c1 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -133,6 +133,14 @@ UNUSUAL_DEV(  0x0420, 0x0001, 0x0100, 0x0100,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_IGNORE_RESIDUE ),
+ 
++/* Reported by Jiri Slaby  and
++ * Rene C. Castberg  */
++UNUSUAL_DEV(  0x0421, 0x0446, 0x0100, 0x0100,
++		"Nokia",
++		"N80",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
++
+ /* Reported by Olaf Hering  from novell bug #105878 */
+ UNUSUAL_DEV(  0x0424, 0x0fdc, 0x0210, 0x0210,
+ 		"SMSC",

commit c5e3b741a3fec6077a480aa65ded29d79ded8898
+Author: Alan Stern 
+Date:   Mon Jun 5 12:28:57 2006 -0400
+
+    [PATCH] UHCI: Improve FSBR-off timing
+    
+    This patch (as707) improves the FSBR operation in uhci-hcd by turning it
+    off more quickly when it isn't needed.  FSBR puts a noticeable load on a
+    computer's PCI bus, so it should be disabled as soon as possible when it
+    isn't in use.  The patch leaves it running for only 10 ms after the last
+    URB stops using it, on the theory that this should be long enough for a
+    driver to submit another URB if it wants keep FSBR going.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 025b969f95e8..7b48567622ef 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -497,9 +497,9 @@ static int uhci_start(struct usb_hcd *hcd)
+ 	hcd->uses_new_polling = 1;
+ 
+ 	spin_lock_init(&uhci->lock);
+-
++	setup_timer(&uhci->fsbr_timer, uhci_fsbr_timeout,
++			(unsigned long) uhci);
+ 	INIT_LIST_HEAD(&uhci->idle_qh_list);
+-
+ 	init_waitqueue_head(&uhci->waitqh);
+ 
+ 	if (DEBUG_CONFIGURED) {
+@@ -675,6 +675,7 @@ static void uhci_stop(struct usb_hcd *hcd)
+ 	uhci_scan_schedule(uhci, NULL);
+ 	spin_unlock_irq(&uhci->lock);
+ 
++	del_timer_sync(&uhci->fsbr_timer);
+ 	release_uhci(uhci);
+ }
+ 
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index 619d704f4e8f..108e3de2dc26 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -86,7 +86,7 @@
+ 
+ /* When no queues need Full-Speed Bandwidth Reclamation,
+  * delay this long before turning FSBR off */
+-#define FSBR_OFF_DELAY		msecs_to_jiffies(400)
++#define FSBR_OFF_DELAY		msecs_to_jiffies(10)
+ 
+ /* If a queue hasn't advanced after this much time, assume it is stuck */
+ #define QH_WAIT_TIMEOUT		msecs_to_jiffies(200)
+@@ -382,8 +382,6 @@ struct uhci_hcd {
+ 	__le32 *frame;
+ 	void **frame_cpu;		/* CPU's frame list */
+ 
+-	unsigned long fsbr_jiffies;	/* Time when FSBR was last wanted */
+-
+ 	enum uhci_rh_state rh_state;
+ 	unsigned long auto_stop_time;		/* When to AUTO_STOP */
+ 
+@@ -400,6 +398,10 @@ struct uhci_hcd {
+ 						   need to be polled */
+ 	unsigned int is_initialized:1;		/* Data structure is usable */
+ 	unsigned int fsbr_is_on:1;		/* FSBR is turned on */
++	unsigned int fsbr_is_wanted:1;		/* Does any URB want FSBR? */
++	unsigned int fsbr_expiring:1;		/* FSBR is timing out */
++
++	struct timer_list fsbr_timer;		/* For turning off FBSR */
+ 
+ 	/* Support for port suspend/resume/reset */
+ 	unsigned long port_c_suspend;		/* Bit-arrays of ports */
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index b173d914d748..c9d72ac0a1d7 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -64,16 +64,30 @@ static void uhci_add_fsbr(struct uhci_hcd *uhci, struct urb *urb)
+ 		urbp->fsbr = 1;
+ }
+ 
+-static void uhci_qh_wants_fsbr(struct uhci_hcd *uhci, struct uhci_qh *qh)
++static void uhci_urbp_wants_fsbr(struct uhci_hcd *uhci, struct urb_priv *urbp)
+ {
+-	struct urb_priv *urbp =
+-			list_entry(qh->queue.next, struct urb_priv, node);
+-
+ 	if (urbp->fsbr) {
+-		uhci->fsbr_jiffies = jiffies;
++		uhci->fsbr_is_wanted = 1;
+ 		if (!uhci->fsbr_is_on)
+ 			uhci_fsbr_on(uhci);
++		else if (uhci->fsbr_expiring) {
++			uhci->fsbr_expiring = 0;
++			del_timer(&uhci->fsbr_timer);
++		}
++	}
++}
++
++static void uhci_fsbr_timeout(unsigned long _uhci)
++{
++	struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci;
++	unsigned long flags;
++
++	spin_lock_irqsave(&uhci->lock, flags);
++	if (uhci->fsbr_expiring) {
++		uhci->fsbr_expiring = 0;
++		uhci_fsbr_off(uhci);
+ 	}
++	spin_unlock_irqrestore(&uhci->lock, flags);
+ }
+ 
+ 
+@@ -287,7 +301,7 @@ static int uhci_cleanup_queue(struct uhci_hcd *uhci, struct uhci_qh *qh,
+ 	if (qh->type == USB_ENDPOINT_XFER_ISOC) {
+ 		ret = (uhci->frame_number + uhci->is_stopped !=
+ 				qh->unlink_frame);
+-		return ret;
++		goto done;
+ 	}
+ 
+ 	/* If the URB isn't first on its queue, adjust the link pointer
+@@ -304,24 +318,26 @@ static int uhci_cleanup_queue(struct uhci_hcd *uhci, struct uhci_qh *qh,
+ 		td = list_entry(urbp->td_list.prev, struct uhci_td,
+ 				list);
+ 		ptd->link = td->link;
+-		return ret;
++		goto done;
+ 	}
+ 
+ 	/* If the QH element pointer is UHCI_PTR_TERM then then currently
+ 	 * executing URB has already been unlinked, so this one isn't it. */
+ 	if (qh_element(qh) == UHCI_PTR_TERM)
+-		return ret;
++		goto done;
+ 	qh->element = UHCI_PTR_TERM;
+ 
+ 	/* Control pipes have to worry about toggles */
+ 	if (qh->type == USB_ENDPOINT_XFER_CONTROL)
+-		return ret;
++		goto done;
+ 
+ 	/* Save the next toggle value */
+ 	WARN_ON(list_empty(&urbp->td_list));
+ 	td = list_entry(urbp->td_list.next, struct uhci_td, list);
+ 	qh->needs_fixup = 1;
+ 	qh->initial_toggle = uhci_toggle(td_token(td));
++
++done:
+ 	return ret;
+ }
+ 
+@@ -1175,7 +1191,7 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd,
+ 	 * queue isn't stopped. */
+ 	if (qh->queue.next == &urbp->node && !qh->is_stopped) {
+ 		uhci_activate_qh(uhci, qh);
+-		uhci_qh_wants_fsbr(uhci, qh);
++		uhci_urbp_wants_fsbr(uhci, urbp);
+ 	}
+ 	goto done;
+ 
+@@ -1404,7 +1420,7 @@ static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ 	unsigned status;
+ 
+ 	if (qh->type == USB_ENDPOINT_XFER_ISOC)
+-		return ret;
++		goto done;
+ 
+ 	/* Treat an UNLINKING queue as though it hasn't advanced.
+ 	 * This is okay because reactivation will treat it as though
+@@ -1427,21 +1443,24 @@ static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ 			/* We're okay, the queue has advanced */
+ 			qh->wait_expired = 0;
+ 			qh->advance_jiffies = jiffies;
+-			return ret;
++			goto done;
+ 		}
+ 		ret = 0;
+ 	}
+ 
+ 	/* The queue hasn't advanced; check for timeout */
+-	if (!qh->wait_expired && time_after(jiffies,
+-			qh->advance_jiffies + QH_WAIT_TIMEOUT)) {
++	if (qh->wait_expired)
++		goto done;
++
++	if (time_after(jiffies, qh->advance_jiffies + QH_WAIT_TIMEOUT)) {
+ 
+ 		/* Detect the Intel bug and work around it */
+ 		if (qh->post_td && qh_element(qh) ==
+ 				cpu_to_le32(qh->post_td->dma_handle)) {
+ 			qh->element = qh->post_td->link;
+ 			qh->advance_jiffies = jiffies;
+-			return 1;
++			ret = 1;
++			goto done;
+ 		}
+ 
+ 		qh->wait_expired = 1;
+@@ -1452,7 +1471,14 @@ static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ 		 * starts moving again. */
+ 		if (urbp && urbp->fsbr && !(status & TD_CTRL_IOC))
+ 			uhci_unlink_qh(uhci, qh);
++
++	} else {
++		/* Unmoving but not-yet-expired queues keep FSBR alive */
++		if (urbp)
++			uhci_urbp_wants_fsbr(uhci, urbp);
+ 	}
++
++done:
+ 	return ret;
+ }
+ 
+@@ -1472,6 +1498,7 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs)
+ 	uhci->scan_in_progress = 1;
+ rescan:
+ 	uhci->need_rescan = 0;
++	uhci->fsbr_is_wanted = 0;
+ 
+ 	uhci_clear_next_interrupt(uhci);
+ 	uhci_get_current_frame_number(uhci);
+@@ -1487,8 +1514,10 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs)
+ 
+ 			if (uhci_advance_check(uhci, qh)) {
+ 				uhci_scan_qh(uhci, qh, regs);
+-				if (qh->state == QH_STATE_ACTIVE)
+-					uhci_qh_wants_fsbr(uhci, qh);
++				if (qh->state == QH_STATE_ACTIVE) {
++					uhci_urbp_wants_fsbr(uhci,
++	list_entry(qh->queue.next, struct urb_priv, node));
++				}
+ 			}
+ 		}
+ 	}
+@@ -1498,9 +1527,11 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs)
+ 		goto rescan;
+ 	uhci->scan_in_progress = 0;
+ 
+-	if (uhci->fsbr_is_on && time_after(jiffies,
+-			uhci->fsbr_jiffies + FSBR_OFF_DELAY))
+-		uhci_fsbr_off(uhci);
++	if (uhci->fsbr_is_on && !uhci->fsbr_is_wanted &&
++			!uhci->fsbr_expiring) {
++		uhci->fsbr_expiring = 1;
++		mod_timer(&uhci->fsbr_timer, jiffies + FSBR_OFF_DELAY);
++	}
+ 
+ 	if (list_empty(&uhci->skel_unlink_qh->node))
+ 		uhci_clear_next_interrupt(uhci);

commit e323de46e83b6df2f330651907ac823f8d53308a
+Author: Alan Stern 
+Date:   Mon Jun 5 12:21:30 2006 -0400
+
+    [PATCH] UHCI: remove hc_inaccessible flag
+    
+    This patch (as706) removes the private hc_inaccessible flag from
+    uhci-hcd.  It's not needed because it conveys exactly the same
+    information as the generic HCD_FLAG_HW_ACCESSIBLE bit.
+    
+    In its place goes a new flag recording whether the controller is dead.
+    The new code allows a complete device reset to resurrect a dead
+    controller (although usbcore doesn't yet implement such a facility).
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index dc9ed29c6175..025b969f95e8 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -110,17 +110,23 @@ static void finish_reset(struct uhci_hcd *uhci)
+ 	uhci->is_stopped = UHCI_IS_STOPPED;
+ 	uhci_to_hcd(uhci)->state = HC_STATE_HALT;
+ 	uhci_to_hcd(uhci)->poll_rh = 0;
++
++	uhci->dead = 0;		/* Full reset resurrects the controller */
+ }
+ 
+ /*
+  * Last rites for a defunct/nonfunctional controller
+  * or one we don't want to use any more.
+  */
+-static void hc_died(struct uhci_hcd *uhci)
++static void uhci_hc_died(struct uhci_hcd *uhci)
+ {
++	uhci_get_current_frame_number(uhci);
+ 	uhci_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr);
+ 	finish_reset(uhci);
+-	uhci->hc_inaccessible = 1;
++	uhci->dead = 1;
++
++	/* The current frame may already be partway finished */
++	++uhci->frame_number;
+ }
+ 
+ /*
+@@ -234,7 +240,7 @@ __acquires(uhci->lock)
+ 		spin_unlock_irq(&uhci->lock);
+ 		msleep(1);
+ 		spin_lock_irq(&uhci->lock);
+-		if (uhci->hc_inaccessible)	/* Died */
++		if (uhci->dead)
+ 			return;
+ 	}
+ 	if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH))
+@@ -287,7 +293,7 @@ __acquires(uhci->lock)
+ 		spin_unlock_irq(&uhci->lock);
+ 		msleep(20);
+ 		spin_lock_irq(&uhci->lock);
+-		if (uhci->hc_inaccessible)	/* Died */
++		if (uhci->dead)
+ 			return;
+ 
+ 		/* End Global Resume and wait for EOP to be sent */
+@@ -339,7 +345,7 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
+ 							errbuf, ERRBUF_LEN);
+ 					lprintk(errbuf);
+ 				}
+-				hc_died(uhci);
++				uhci_hc_died(uhci);
+ 
+ 				/* Force a callback in case there are
+ 				 * pending unlinks */
+@@ -462,7 +468,7 @@ static void uhci_shutdown(struct pci_dev *pdev)
+ {
+ 	struct usb_hcd *hcd = (struct usb_hcd *) pci_get_drvdata(pdev);
+ 
+-	hc_died(hcd_to_uhci(hcd));
++	uhci_hc_died(hcd_to_uhci(hcd));
+ }
+ 
+ /*
+@@ -664,8 +670,8 @@ static void uhci_stop(struct usb_hcd *hcd)
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 
+ 	spin_lock_irq(&uhci->lock);
+-	if (!uhci->hc_inaccessible)
+-		hc_died(uhci);
++	if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) && !uhci->dead)
++		uhci_hc_died(uhci);
+ 	uhci_scan_schedule(uhci, NULL);
+ 	spin_unlock_irq(&uhci->lock);
+ 
+@@ -681,7 +687,7 @@ static int uhci_rh_suspend(struct usb_hcd *hcd)
+ 	spin_lock_irq(&uhci->lock);
+ 	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
+ 		rc = -ESHUTDOWN;
+-	else if (!uhci->hc_inaccessible)
++	else if (!uhci->dead)
+ 		suspend_rh(uhci, UHCI_RH_SUSPENDED);
+ 	spin_unlock_irq(&uhci->lock);
+ 	return rc;
+@@ -696,7 +702,7 @@ static int uhci_rh_resume(struct usb_hcd *hcd)
+ 	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+ 		dev_warn(&hcd->self.root_hub->dev, "HC isn't running!\n");
+ 		rc = -ESHUTDOWN;
+-	} else if (!uhci->hc_inaccessible)
++	} else if (!uhci->dead)
+ 		wakeup_rh(uhci);
+ 	spin_unlock_irq(&uhci->lock);
+ 	return rc;
+@@ -710,8 +716,8 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
+ 	dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
+ 
+ 	spin_lock_irq(&uhci->lock);
+-	if (uhci->hc_inaccessible)	/* Dead or already suspended */
+-		goto done;
++	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
++		goto done_okay;		/* Already suspended or dead */
+ 
+ 	if (uhci->rh_state > UHCI_RH_SUSPENDED) {
+ 		dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n");
+@@ -724,12 +730,12 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
+ 	 */
+ 	pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0);
+ 	mb();
+-	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+-	uhci->hc_inaccessible = 1;
+ 	hcd->poll_rh = 0;
+ 
+ 	/* FIXME: Enable non-PME# remote wakeup? */
+ 
++done_okay:
++	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ done:
+ 	spin_unlock_irq(&uhci->lock);
+ 	return rc;
+@@ -742,25 +748,22 @@ static int uhci_resume(struct usb_hcd *hcd)
+ 	dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
+ 
+ 	/* Since we aren't in D3 any more, it's safe to set this flag
+-	 * even if the controller was dead.  It might not even be dead
+-	 * any more, if the firmware or quirks code has reset it.
++	 * even if the controller was dead.
+ 	 */
+ 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ 	mb();
+ 
+-	if (uhci->rh_state == UHCI_RH_RESET)	/* Dead */
+-		return 0;
+-
+ 	spin_lock_irq(&uhci->lock);
+ 
+ 	/* FIXME: Disable non-PME# remote wakeup? */
+ 
+-	uhci->hc_inaccessible = 0;
+-
+-	/* The BIOS may have changed the controller settings during a
+-	 * system wakeup.  Check it and reconfigure to avoid problems.
++	/* The firmware or a boot kernel may have changed the controller
++	 * settings during a system wakeup.  Check it and reconfigure
++	 * to avoid problems.
+ 	 */
+ 	check_and_reset_hc(uhci);
++
++	/* If the controller was dead before, it's back alive now */
+ 	configure_hc(uhci);
+ 
+ 	if (uhci->rh_state == UHCI_RH_RESET) {
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index 469b4268b850..619d704f4e8f 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -395,7 +395,7 @@ struct uhci_hcd {
+ 
+ 	unsigned int scan_in_progress:1;	/* Schedule scan is running */
+ 	unsigned int need_rescan:1;		/* Redo the schedule scan */
+-	unsigned int hc_inaccessible:1;		/* HC is suspended or dead */
++	unsigned int dead:1;			/* Controller has died */
+ 	unsigned int working_RD:1;		/* Suspended root hub doesn't
+ 						   need to be polled */
+ 	unsigned int is_initialized:1;		/* Data structure is usable */
+diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
+index f53c116e0dfd..c545ef92fe29 100644
+--- a/drivers/usb/host/uhci-hub.c
++++ b/drivers/usb/host/uhci-hub.c
+@@ -171,7 +171,7 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
+ 	spin_lock_irqsave(&uhci->lock, flags);
+ 
+ 	uhci_scan_schedule(uhci, NULL);
+-	if (uhci->hc_inaccessible)
++	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
+ 		goto done;
+ 	uhci_check_ports(uhci);
+ 
+@@ -227,7 +227,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+ 	u16 wPortChange, wPortStatus;
+ 	unsigned long flags;
+ 
+-	if (uhci->hc_inaccessible)
++	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
+ 		return -ETIMEDOUT;
+ 
+ 	spin_lock_irqsave(&uhci->lock, flags);

commit ae671813affd947d2f21ff8e3cd329e466ee85b2
+Author: Alan Stern 
+Date:   Tue Jun 6 15:19:17 2006 -0400
+
+    [PATCH] usb-storage: unusual_devs entry for Nikon DSC D70s
+    
+    This patch (as704) adds an unusual_devs entry for the Nikon DSC D70s,
+    which uses a different Product ID from the D70.  It also moves the entry
+    for the DSC E2000 up in the list, to preserve the numerical ordering.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 9f72000a0064..3ec17689b81c 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -216,6 +216,14 @@ UNUSUAL_DEV(  0x04a4, 0x0004, 0x0001, 0x0001,
+ 		"DVD-CAM DZ-MV100A Camcorder",
+ 		US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN),
+ 
++/* Patch for Nikon coolpix 2000
++ * Submitted by Fabien Cosse */
++UNUSUAL_DEV(  0x04b0, 0x0301, 0x0010, 0x0010,
++		"NIKON",
++		"NIKON DSC E2000",
++		US_SC_DEVICE, US_PR_DEVICE,NULL,
++		US_FL_NOT_LOCKABLE ),
++
+ /* Reported by Andreas Bockhold  */
+ UNUSUAL_DEV(  0x04b0, 0x0405, 0x0100, 0x0100,
+ 		"NIKON",
+@@ -223,13 +231,12 @@ UNUSUAL_DEV(  0x04b0, 0x0405, 0x0100, 0x0100,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_FIX_CAPACITY),
+ 
+-/* Patch for Nikon coolpix 2000
+- * Submitted by Fabien Cosse */
+-UNUSUAL_DEV(  0x04b0, 0x0301, 0x0010, 0x0010,
++/* Reported by Jamie Kitson  */
++UNUSUAL_DEV(  0x04b0, 0x040d, 0x0100, 0x0100,
+ 		"NIKON",
+-		"NIKON DSC E2000",
+-		US_SC_DEVICE, US_PR_DEVICE,NULL,
+-		US_FL_NOT_LOCKABLE ),
++		"NIKON DSC D70s",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_FIX_CAPACITY),
+ 
+ /* BENQ DC5330
+  * Reported by Manuel Fombuena  and

commit 6ad07129a8ed2e13dcd7e6313c201c32bcf7cc32
+Author: Alan Stern 
+Date:   Thu Jun 1 13:59:16 2006 -0400
+
+    [PATCH] usbcore: recovery from Set-Configuration failure
+    
+    This patch (as703) improves the error handling when a Set-Configuration
+    request fails.  The old interfaces are all unregistered before the
+    request is sent, and if the request fails then we don't know what config
+    the device is using.  So it makes no sense to leave actconfig pointing
+    to the old configuration with its invalid interfaces.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index b2f608b0538d..8569600f3130 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1411,15 +1411,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 				return ret;
+ 			}
+ 		}
+-	}
+ 
+-	/* if it's already configured, clear out old state first.
+-	 * getting rid of old interfaces means unbinding their drivers.
+-	 */
+-	if (dev->state != USB_STATE_ADDRESS)
+-		usb_disable_device (dev, 1);	// Skip ep0
+-
+-	if (cp) {
+ 		i = dev->bus_mA - cp->desc.bMaxPower * 2;
+ 		if (i < 0)
+ 			dev_warn(&dev->dev, "new config #%d exceeds power "
+@@ -1427,84 +1419,91 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 					configuration, -i);
+ 	}
+ 
++	/* if it's already configured, clear out old state first.
++	 * getting rid of old interfaces means unbinding their drivers.
++	 */
++	if (dev->state != USB_STATE_ADDRESS)
++		usb_disable_device (dev, 1);	// Skip ep0
++
+ 	if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ 			USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
+-			NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0)
+-		goto free_interfaces;
++			NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0) {
++
++		/* All the old state is gone, so what else can we do?
++		 * The device is probably useless now anyway.
++		 */
++		cp = NULL;
++	}
+ 
+ 	dev->actconfig = cp;
+-	if (!cp)
++	if (!cp) {
+ 		usb_set_device_state(dev, USB_STATE_ADDRESS);
+-	else {
+-		usb_set_device_state(dev, USB_STATE_CONFIGURED);
++		goto free_interfaces;
++	}
++	usb_set_device_state(dev, USB_STATE_CONFIGURED);
+ 
+-		/* Initialize the new interface structures and the
+-		 * hc/hcd/usbcore interface/endpoint state.
+-		 */
+-		for (i = 0; i < nintf; ++i) {
+-			struct usb_interface_cache *intfc;
+-			struct usb_interface *intf;
+-			struct usb_host_interface *alt;
+-
+-			cp->interface[i] = intf = new_interfaces[i];
+-			intfc = cp->intf_cache[i];
+-			intf->altsetting = intfc->altsetting;
+-			intf->num_altsetting = intfc->num_altsetting;
+-			kref_get(&intfc->ref);
+-
+-			alt = usb_altnum_to_altsetting(intf, 0);
+-
+-			/* No altsetting 0?  We'll assume the first altsetting.
+-			 * We could use a GetInterface call, but if a device is
+-			 * so non-compliant that it doesn't have altsetting 0
+-			 * then I wouldn't trust its reply anyway.
+-			 */
+-			if (!alt)
+-				alt = &intf->altsetting[0];
+-
+-			intf->cur_altsetting = alt;
+-			usb_enable_interface(dev, intf);
+-			intf->dev.parent = &dev->dev;
+-			intf->dev.driver = NULL;
+-			intf->dev.bus = &usb_bus_type;
+-			intf->dev.dma_mask = dev->dev.dma_mask;
+-			intf->dev.release = release_interface;
+-			device_initialize (&intf->dev);
+-			mark_quiesced(intf);
+-			sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
+-				 dev->bus->busnum, dev->devpath,
+-				 configuration,
+-				 alt->desc.bInterfaceNumber);
+-		}
+-		kfree(new_interfaces);
++	/* Initialize the new interface structures and the
++	 * hc/hcd/usbcore interface/endpoint state.
++	 */
++	for (i = 0; i < nintf; ++i) {
++		struct usb_interface_cache *intfc;
++		struct usb_interface *intf;
++		struct usb_host_interface *alt;
+ 
+-		if (cp->string == NULL)
+-			cp->string = usb_cache_string(dev,
+-					cp->desc.iConfiguration);
++		cp->interface[i] = intf = new_interfaces[i];
++		intfc = cp->intf_cache[i];
++		intf->altsetting = intfc->altsetting;
++		intf->num_altsetting = intfc->num_altsetting;
++		kref_get(&intfc->ref);
+ 
+-		/* Now that all the interfaces are set up, register them
+-		 * to trigger binding of drivers to interfaces.  probe()
+-		 * routines may install different altsettings and may
+-		 * claim() any interfaces not yet bound.  Many class drivers
+-		 * need that: CDC, audio, video, etc.
++		alt = usb_altnum_to_altsetting(intf, 0);
++
++		/* No altsetting 0?  We'll assume the first altsetting.
++		 * We could use a GetInterface call, but if a device is
++		 * so non-compliant that it doesn't have altsetting 0
++		 * then I wouldn't trust its reply anyway.
+ 		 */
+-		for (i = 0; i < nintf; ++i) {
+-			struct usb_interface *intf = cp->interface[i];
+-
+-			dev_dbg (&dev->dev,
+-				"adding %s (config #%d, interface %d)\n",
+-				intf->dev.bus_id, configuration,
+-				intf->cur_altsetting->desc.bInterfaceNumber);
+-			ret = device_add (&intf->dev);
+-			if (ret != 0) {
+-				dev_err(&dev->dev,
+-					"device_add(%s) --> %d\n",
+-					intf->dev.bus_id,
+-					ret);
+-				continue;
+-			}
+-			usb_create_sysfs_intf_files (intf);
++		if (!alt)
++			alt = &intf->altsetting[0];
++
++		intf->cur_altsetting = alt;
++		usb_enable_interface(dev, intf);
++		intf->dev.parent = &dev->dev;
++		intf->dev.driver = NULL;
++		intf->dev.bus = &usb_bus_type;
++		intf->dev.dma_mask = dev->dev.dma_mask;
++		intf->dev.release = release_interface;
++		device_initialize (&intf->dev);
++		mark_quiesced(intf);
++		sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
++			 dev->bus->busnum, dev->devpath,
++			 configuration, alt->desc.bInterfaceNumber);
++	}
++	kfree(new_interfaces);
++
++	if (cp->string == NULL)
++		cp->string = usb_cache_string(dev, cp->desc.iConfiguration);
++
++	/* Now that all the interfaces are set up, register them
++	 * to trigger binding of drivers to interfaces.  probe()
++	 * routines may install different altsettings and may
++	 * claim() any interfaces not yet bound.  Many class drivers
++	 * need that: CDC, audio, video, etc.
++	 */
++	for (i = 0; i < nintf; ++i) {
++		struct usb_interface *intf = cp->interface[i];
++
++		dev_dbg (&dev->dev,
++			"adding %s (config #%d, interface %d)\n",
++			intf->dev.bus_id, configuration,
++			intf->cur_altsetting->desc.bInterfaceNumber);
++		ret = device_add (&intf->dev);
++		if (ret != 0) {
++			dev_err(&dev->dev, "device_add(%s) --> %d\n",
++				intf->dev.bus_id, ret);
++			continue;
+ 		}
++		usb_create_sysfs_intf_files (intf);
+ 	}
+ 
+ 	return 0;

commit df9a1f482d1252045210f50048911e2efba61e62
+Author: Alan Stern 
+Date:   Thu Jun 1 13:55:28 2006 -0400
+
+    [PATCH] usbhid: use usb_reset_composite_device
+    
+    This patch (as702) makes usbhid use the new usb_reset_composite_device
+    API.  Now HID interfaces can coexist with other interfaces on the same
+    device, and a reset can safely be requested by any of the drivers.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
+index c6051beeabdc..17b6e6ab3703 100644
+--- a/drivers/usb/input/hid-core.c
++++ b/drivers/usb/input/hid-core.c
+@@ -944,21 +944,28 @@ static void hid_reset(void *_hid)
+ 	dev_dbg(&hid->intf->dev, "resetting device\n");
+ 	rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf);
+ 	if (rc_lock >= 0) {
+-		rc = usb_reset_device(hid->dev);
++		rc = usb_reset_composite_device(hid->dev, hid->intf);
+ 		if (rc_lock)
+ 			usb_unlock_device(hid->dev);
+ 	}
+ 	clear_bit(HID_RESET_PENDING, &hid->iofl);
+ 
+-	if (rc == 0) {
+-		hid->retry_delay = 0;
+-		if (hid_start_in(hid))
++	switch (rc) {
++	case 0:
++		if (!test_bit(HID_IN_RUNNING, &hid->iofl))
+ 			hid_io_error(hid);
+-	} else if (!(rc == -ENODEV || rc == -EHOSTUNREACH || rc == -EINTR))
++		break;
++	default:
+ 		err("can't reset device, %s-%s/input%d, status %d",
+ 				hid->dev->bus->bus_name,
+ 				hid->dev->devpath,
+ 				hid->ifnum, rc);
++		/* FALLTHROUGH */
++	case -EHOSTUNREACH:
++	case -ENODEV:
++	case -EINTR:
++		break;
++	}
+ }
+ 
+ /* Main I/O error handler */
+@@ -2063,11 +2070,29 @@ static int hid_resume(struct usb_interface *intf)
+ 	int status;
+ 
+ 	clear_bit(HID_SUSPENDED, &hid->iofl);
++	hid->retry_delay = 0;
+ 	status = hid_start_in(hid);
+ 	dev_dbg(&intf->dev, "resume status %d\n", status);
+ 	return status;
+ }
+ 
++/* Treat USB reset pretty much the same as suspend/resume */
++static void hid_pre_reset(struct usb_interface *intf)
++{
++	/* FIXME: What if the interface is already suspended? */
++	hid_suspend(intf, PMSG_ON);
++}
++
++static void hid_post_reset(struct usb_interface *intf)
++{
++	struct usb_device *dev = interface_to_usbdev (intf);
++
++	hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0);
++	/* FIXME: Any more reinitialization needed? */
++
++	hid_resume(intf);
++}
++
+ static struct usb_device_id hid_usb_ids [] = {
+ 	{ .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
+ 		.bInterfaceClass = USB_INTERFACE_CLASS_HID },
+@@ -2082,6 +2107,8 @@ static struct usb_driver hid_driver = {
+ 	.disconnect =	hid_disconnect,
+ 	.suspend =	hid_suspend,
+ 	.resume =	hid_resume,
++	.pre_reset =	hid_pre_reset,
++	.post_reset =	hid_post_reset,
+ 	.id_table =	hid_usb_ids,
+ };
+ 

commit 47104b0dd32cec467574822b0dc3517b3de3f0ad
+Author: Alan Stern 
+Date:   Thu Jun 1 13:52:56 2006 -0400
+
+    [PATCH] usb-storage: use usb_reset_composite_device
+    
+    This patch (as701) modifies usb-storage to take advantage of the new
+    usb_reset_composite_device() API.  Now we will be able to safely request
+    port resets even if other drivers are bound to a mass-storage device.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index 5f11e19eaae3..5715291ba540 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -286,11 +286,7 @@ static int bus_reset(struct scsi_cmnd *srb)
+ 	int result;
+ 
+ 	US_DEBUGP("%s called\n", __FUNCTION__);
+-
+-	mutex_lock(&(us->dev_mutex));
+ 	result = usb_stor_port_reset(us);
+-	mutex_unlock(&us->dev_mutex);
+-
+ 	return result < 0 ? FAILED : SUCCESS;
+ }
+ 
+diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+index 038f4582ca0b..19b25c5cafd4 100644
+--- a/drivers/usb/storage/transport.c
++++ b/drivers/usb/storage/transport.c
+@@ -703,16 +703,19 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 	 * device reset. */
+   Handle_Errors:
+ 
+-	/* Let the SCSI layer know we are doing a reset, set the
+-	 * RESETTING bit, and clear the ABORTING bit so that the reset
+-	 * may proceed. */
++	/* Set the RESETTING bit, and clear the ABORTING bit so that
++	 * the reset may proceed. */
+ 	scsi_lock(us_to_host(us));
+-	usb_stor_report_bus_reset(us);
+ 	set_bit(US_FLIDX_RESETTING, &us->flags);
+ 	clear_bit(US_FLIDX_ABORTING, &us->flags);
+ 	scsi_unlock(us_to_host(us));
+ 
++	/* We must release the device lock because the pre_reset routine
++	 * will want to acquire it. */
++	mutex_unlock(&us->dev_mutex);
+ 	result = usb_stor_port_reset(us);
++	mutex_lock(&us->dev_mutex);
++
+ 	if (result < 0) {
+ 		scsi_lock(us_to_host(us));
+ 		usb_stor_report_device_reset(us);
+@@ -1196,31 +1199,30 @@ int usb_stor_Bulk_reset(struct us_data *us)
+ 				 0, us->ifnum, NULL, 0);
+ }
+ 
+-/* Issue a USB port reset to the device.  But don't do anything if
+- * there's more than one interface in the device, so that other users
+- * are not affected. */
++/* Issue a USB port reset to the device.  The caller must not hold
++ * us->dev_mutex.
++ */
+ int usb_stor_port_reset(struct us_data *us)
+ {
+-	int result, rc;
++	int result, rc_lock;
+ 
+-	if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
+-		result = -EIO;
+-		US_DEBUGP("No reset during disconnect\n");
+-	} else if (us->pusb_dev->actconfig->desc.bNumInterfaces != 1) {
+-		result = -EBUSY;
+-		US_DEBUGP("Refusing to reset a multi-interface device\n");
+-	} else {
+-		result = rc =
+-			usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf);
+-		if (result < 0) {
+-			US_DEBUGP("unable to lock device for reset: %d\n",
+-					result);
++	result = rc_lock =
++		usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf);
++	if (result < 0)
++		US_DEBUGP("unable to lock device for reset: %d\n", result);
++	else {
++		/* Were we disconnected while waiting for the lock? */
++		if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
++			result = -EIO;
++			US_DEBUGP("No reset during disconnect\n");
+ 		} else {
+-			result = usb_reset_device(us->pusb_dev);
+-			if (rc)
+-				usb_unlock_device(us->pusb_dev);
+-			US_DEBUGP("usb_reset_device returns %d\n", result);
++			result = usb_reset_composite_device(
++					us->pusb_dev, us->pusb_intf);
++			US_DEBUGP("usb_reset_composite_device returns %d\n",
++					result);
+ 		}
++		if (rc_lock)
++			usb_unlock_device(us->pusb_dev);
+ 	}
+ 	return result;
+ }
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 0142fe82f6b8..e232c7c89909 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -220,6 +220,37 @@ static int storage_resume(struct usb_interface *iface)
+ 
+ #endif /* CONFIG_PM */
+ 
++/*
++ * The next two routines get called just before and just after
++ * a USB port reset, whether from this driver or a different one.
++ */
++
++static void storage_pre_reset(struct usb_interface *iface)
++{
++	struct us_data *us = usb_get_intfdata(iface);
++
++	US_DEBUGP("%s\n", __FUNCTION__);
++
++	/* Make sure no command runs during the reset */
++	mutex_lock(&us->dev_mutex);
++}
++
++static void storage_post_reset(struct usb_interface *iface)
++{
++	struct us_data *us = usb_get_intfdata(iface);
++
++	US_DEBUGP("%s\n", __FUNCTION__);
++
++	/* Report the reset to the SCSI core */
++	scsi_lock(us_to_host(us));
++	usb_stor_report_bus_reset(us);
++	scsi_unlock(us_to_host(us));
++
++	/* FIXME: Notify the subdrivers that they need to reinitialize
++	 * the device */
++	mutex_unlock(&us->dev_mutex);
++}
++
+ /*
+  * fill_inquiry_response takes an unsigned char array (which must
+  * be at least 36 characters) and populates the vendor name,
+@@ -1002,6 +1033,8 @@ static struct usb_driver usb_storage_driver = {
+ 	.suspend =	storage_suspend,
+ 	.resume =	storage_resume,
+ #endif
++	.pre_reset =	storage_pre_reset,
++	.post_reset =	storage_post_reset,
+ 	.id_table =	storage_usb_ids,
+ };
+ 

commit 7de18d8bf4b470752e799e219b38b6dff4b49993
+Author: Alan Stern 
+Date:   Thu Jun 1 13:37:24 2006 -0400
+
+    [PATCH] USB hub: use usb_reset_composite_device
+    
+    This patch (as700) modifies the hub driver to take advantage of the new
+    usb_reset_composite_device API.  The existing code had special-case
+    calls stuck into usb_reset_device, just before and after the reset.
+    With the new version there's no need for special-case stuff; it all
+    happens naturally in the form of pre_reset and post_reset notifications.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 37c67d7e8b84..e1731ff8af4d 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -525,15 +525,16 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
+ 
+ 
+ /* caller has locked the hub device */
+-static void hub_pre_reset(struct usb_hub *hub, int disable_ports)
++static void hub_pre_reset(struct usb_interface *intf)
+ {
++	struct usb_hub *hub = usb_get_intfdata(intf);
+ 	struct usb_device *hdev = hub->hdev;
+ 	int port1;
+ 
+ 	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
+ 		if (hdev->children[port1 - 1]) {
+ 			usb_disconnect(&hdev->children[port1 - 1]);
+-			if (disable_ports)
++			if (hub->error == 0)
+ 				hub_port_disable(hub, port1, 0);
+ 		}
+ 	}
+@@ -541,8 +542,10 @@ static void hub_pre_reset(struct usb_hub *hub, int disable_ports)
+ }
+ 
+ /* caller has locked the hub device */
+-static void hub_post_reset(struct usb_hub *hub)
++static void hub_post_reset(struct usb_interface *intf)
+ {
++	struct usb_hub *hub = usb_get_intfdata(intf);
++
+ 	hub_activate(hub);
+ 	hub_power_on(hub);
+ }
+@@ -802,15 +805,16 @@ static void hub_disconnect(struct usb_interface *intf)
+ 	struct usb_hub *hub = usb_get_intfdata (intf);
+ 	struct usb_device *hdev;
+ 
++	/* Disconnect all children and quiesce the hub */
++	hub->error = 0;
++	hub_pre_reset(intf);
++
+ 	usb_set_intfdata (intf, NULL);
+ 	hdev = hub->hdev;
+ 
+ 	if (hdev->speed == USB_SPEED_HIGH)
+ 		highspeed_hubs--;
+ 
+-	/* Disconnect all children and quiesce the hub */
+-	hub_pre_reset(hub, 1);
+-
+ 	usb_free_urb(hub->urb);
+ 	hub->urb = NULL;
+ 
+@@ -2747,7 +2751,8 @@ static void hub_events(void)
+ 
+ 		/* If the hub has died, clean up after it */
+ 		if (hdev->state == USB_STATE_NOTATTACHED) {
+-			hub_pre_reset(hub, 0);
++			hub->error = -ENODEV;
++			hub_pre_reset(intf);
+ 			goto loop;
+ 		}
+ 
+@@ -2759,7 +2764,7 @@ static void hub_events(void)
+ 			dev_dbg (hub_dev, "resetting for error %d\n",
+ 				hub->error);
+ 
+-			ret = usb_reset_device(hdev);
++			ret = usb_reset_composite_device(hdev, intf);
+ 			if (ret) {
+ 				dev_dbg (hub_dev,
+ 					"error resetting hub: %d\n", ret);
+@@ -2928,6 +2933,8 @@ static struct usb_driver hub_driver = {
+ 	.disconnect =	hub_disconnect,
+ 	.suspend =	hub_suspend,
+ 	.resume =	hub_resume,
++	.pre_reset =	hub_pre_reset,
++	.post_reset =	hub_post_reset,
+ 	.ioctl =	hub_ioctl,
+ 	.id_table =	hub_id_table,
+ };
+@@ -3033,7 +3040,6 @@ int usb_reset_device(struct usb_device *udev)
+ 	struct usb_device		*parent_hdev = udev->parent;
+ 	struct usb_hub			*parent_hub;
+ 	struct usb_device_descriptor	descriptor = udev->descriptor;
+-	struct usb_hub			*hub = NULL;
+ 	int 				i, ret = 0;
+ 	int				port1 = udev->portnum;
+ 
+@@ -3051,14 +3057,6 @@ int usb_reset_device(struct usb_device *udev)
+ 	}
+ 	parent_hub = hdev_to_hub(parent_hdev);
+ 
+-	/* If we're resetting an active hub, take some special actions */
+-	if (udev->actconfig && udev->actconfig->desc.bNumInterfaces > 0 &&
+-			udev->actconfig->interface[0]->dev.driver ==
+-				&hub_driver.driver &&
+-			(hub = hdev_to_hub(udev)) != NULL) {
+-		hub_pre_reset(hub, 0);
+-	}
+-
+ 	set_bit(port1, parent_hub->busy_bits);
+ 	for (i = 0; i < SET_CONFIG_TRIES; ++i) {
+ 
+@@ -3117,8 +3115,6 @@ int usb_reset_device(struct usb_device *udev)
+ 	}
+ 
+ done:
+-	if (hub)
+-		hub_post_reset(hub);
+ 	return 0;
+  
+ re_enumerate:

commit 79efa097e75018a2918155f343f0e08e61ee8a8c
+Author: Alan Stern 
+Date:   Thu Jun 1 13:33:42 2006 -0400
+
+    [PATCH] usbcore: port reset for composite devices
+    
+    This patch (as699) adds usb_reset_composite_device(), a routine for
+    sending a USB port reset to a device with multiple interfaces owned by
+    different drivers.  Drivers are notified about impending and completed
+    resets through two new methods in the usb_driver structure.
+    
+    The patch modifieds the usbfs ioctl code to make it use the new routine
+    instead of usb_reset_device().  Follow-up patches will modify the hub,
+    usb-storage, and usbhid drivers so they can utilize this new API.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index b04ede772f2c..df3fb57d71e6 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -823,8 +823,7 @@ static int proc_connectinfo(struct dev_state *ps, void __user *arg)
+ 
+ static int proc_resetdevice(struct dev_state *ps)
+ {
+-	return usb_reset_device(ps->dev);
+-
++	return usb_reset_composite_device(ps->dev, NULL);
+ }
+ 
+ static int proc_setintf(struct dev_state *ps, void __user *arg)
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index f41c08946a52..37c67d7e8b84 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -3007,9 +3007,9 @@ static int config_descriptors_changed(struct usb_device *udev)
+  * usb_reset_device - perform a USB port reset to reinitialize a device
+  * @udev: device to reset (not in SUSPENDED or NOTATTACHED state)
+  *
+- * WARNING - don't reset any device unless drivers for all of its
+- * interfaces are expecting that reset!  Maybe some driver->reset()
+- * method should eventually help ensure sufficient cooperation.
++ * WARNING - don't use this routine to reset a composite device
++ * (one with multiple interfaces owned by separate drivers)!
++ * Use usb_reset_composite_device() instead.
+  *
+  * Do a port reset, reassign the device's address, and establish its
+  * former operating configuration.  If the reset fails, or the device's
+@@ -3125,3 +3125,81 @@ int usb_reset_device(struct usb_device *udev)
+ 	hub_port_logical_disconnect(parent_hub, port1);
+ 	return -ENODEV;
+ }
++
++/**
++ * usb_reset_composite_device - warn interface drivers and perform a USB port reset
++ * @udev: device to reset (not in SUSPENDED or NOTATTACHED state)
++ * @iface: interface bound to the driver making the request (optional)
++ *
++ * Warns all drivers bound to registered interfaces (using their pre_reset
++ * method), performs the port reset, and then lets the drivers know that
++ * the reset is over (using their post_reset method).
++ *
++ * Return value is the same as for usb_reset_device().
++ *
++ * The caller must own the device lock.  For example, it's safe to use
++ * this from a driver probe() routine after downloading new firmware.
++ * For calls that might not occur during probe(), drivers should lock
++ * the device using usb_lock_device_for_reset().
++ *
++ * The interface locks are acquired during the pre_reset stage and released
++ * during the post_reset stage.  However if iface is not NULL and is
++ * currently being probed, we assume that the caller already owns its
++ * lock.
++ */
++int usb_reset_composite_device(struct usb_device *udev,
++		struct usb_interface *iface)
++{
++	int ret;
++	struct usb_host_config *config = udev->actconfig;
++
++	if (udev->state == USB_STATE_NOTATTACHED ||
++			udev->state == USB_STATE_SUSPENDED) {
++		dev_dbg(&udev->dev, "device reset not allowed in state %d\n",
++				udev->state);
++		return -EINVAL;
++	}
++
++	if (iface && iface->condition != USB_INTERFACE_BINDING)
++		iface = NULL;
++
++	if (config) {
++		int i;
++		struct usb_interface *cintf;
++		struct usb_driver *drv;
++
++		for (i = 0; i < config->desc.bNumInterfaces; ++i) {
++			cintf = config->interface[i];
++			if (cintf != iface)
++				down(&cintf->dev.sem);
++			if (device_is_registered(&cintf->dev) &&
++					cintf->dev.driver) {
++				drv = to_usb_driver(cintf->dev.driver);
++				if (drv->pre_reset)
++					(drv->pre_reset)(cintf);
++			}
++		}
++	}
++
++	ret = usb_reset_device(udev);
++
++	if (config) {
++		int i;
++		struct usb_interface *cintf;
++		struct usb_driver *drv;
++
++		for (i = config->desc.bNumInterfaces - 1; i >= 0; --i) {
++			cintf = config->interface[i];
++			if (device_is_registered(&cintf->dev) &&
++					cintf->dev.driver) {
++				drv = to_usb_driver(cintf->dev.driver);
++				if (drv->post_reset)
++					(drv->post_reset)(cintf);
++			}
++			if (cintf != iface)
++				up(&cintf->dev.sem);
++		}
++	}
++
++	return ret;
++}
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index b7fdc1cd134a..515310751303 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -1207,6 +1207,7 @@ EXPORT_SYMBOL(usb_ifnum_to_if);
+ EXPORT_SYMBOL(usb_altnum_to_altsetting);
+ 
+ EXPORT_SYMBOL(usb_reset_device);
++EXPORT_SYMBOL(usb_reset_composite_device);
+ 
+ EXPORT_SYMBOL(__usb_get_extra_descriptor);
+ 
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 317ec9f28bce..5ad30cefe7b2 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -386,6 +386,8 @@ extern int usb_lock_device_for_reset(struct usb_device *udev,
+ 
+ /* USB port reset for device reinitialization */
+ extern int usb_reset_device(struct usb_device *dev);
++extern int usb_reset_composite_device(struct usb_device *dev,
++		struct usb_interface *iface);
+ 
+ extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id);
+ 
+@@ -554,6 +556,10 @@ struct usb_dynids {
+  *	do (or don't) show up otherwise in the filesystem.
+  * @suspend: Called when the device is going to be suspended by the system.
+  * @resume: Called when the device is being resumed by the system.
++ * @pre_reset: Called by usb_reset_composite_device() when the device
++ *	is about to be reset.
++ * @post_reset: Called by usb_reset_composite_device() after the device
++ *	has been reset.
+  * @id_table: USB drivers use ID table to support hotplugging.
+  *	Export this with MODULE_DEVICE_TABLE(usb,...).  This must be set
+  *	or your driver's probe function will never get called.
+@@ -592,6 +598,9 @@ struct usb_driver {
+ 	int (*suspend) (struct usb_interface *intf, pm_message_t message);
+ 	int (*resume) (struct usb_interface *intf);
+ 
++	void (*pre_reset) (struct usb_interface *intf);
++	void (*post_reset) (struct usb_interface *intf);
++
+ 	const struct usb_device_id *id_table;
+ 
+ 	struct usb_dynids dynids;

commit 633a7ecf89587879161179ac4f5a03722626866f
+Author: Alan Stern 
+Date:   Tue May 30 10:21:14 2006 -0400
+
+    [PATCH] usbhid: Remove unneeded blacklist entries
+    
+    Now that usbhid automatically applies HID_QUIRK_NOGET to keyboards and
+    mice, we no longer need the blacklist entries that were present for no
+    other purpose.  This patch (as698) removes them.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Vojtech Pavlik 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
+index 061002fc66fc..c6051beeabdc 100644
+--- a/drivers/usb/input/hid-core.c
++++ b/drivers/usb/input/hid-core.c
+@@ -1374,9 +1374,6 @@ void hid_close(struct hid_device *hid)
+ 
+ #define USB_VENDOR_ID_PANJIT		0x134c
+ 
+-#define USB_VENDOR_ID_SILVERCREST	0x062a
+-#define USB_DEVICE_ID_SILVERCREST_KB	0x0201
+-
+ /*
+  * Initialize all reports
+  */
+@@ -1461,9 +1458,6 @@ void hid_init_reports(struct hid_device *hid)
+ #define USB_VENDOR_ID_ONTRAK		0x0a07
+ #define USB_DEVICE_ID_ONTRAK_ADU100	0x0064
+ 
+-#define USB_VENDOR_ID_TANGTOP		0x0d3d
+-#define USB_DEVICE_ID_TANGTOP_USBPS2	0x0001
+-
+ #define USB_VENDOR_ID_ESSENTIAL_REALITY	0x0d7f
+ #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
+ 
+@@ -1520,12 +1514,6 @@ void hid_init_reports(struct hid_device *hid)
+ #define USB_DEVICE_ID_MCC_PMD1024LS	0x0076
+ #define USB_DEVICE_ID_MCC_PMD1208LS	0x007a
+ 
+-#define USB_VENDOR_ID_CHICONY		0x04f2
+-#define USB_DEVICE_ID_CHICONY_USBHUB_KB	0x0100
+-
+-#define USB_VENDOR_ID_BTC		0x046e
+-#define USB_DEVICE_ID_BTC_KEYBOARD	0x5303
+-
+ #define USB_VENDOR_ID_VERNIER		0x08f7
+ #define USB_DEVICE_ID_VERNIER_LABPRO	0x0001
+ #define USB_DEVICE_ID_VERNIER_GOTEMP	0x0002
+@@ -1554,15 +1542,6 @@ void hid_init_reports(struct hid_device *hid)
+ #define USB_VENDOR_ID_CHERRY		0x046a
+ #define USB_DEVICE_ID_CHERRY_CYMOTION	0x0023
+ 
+-#define USB_VENDOR_ID_HP		0x03f0
+-#define USB_DEVICE_ID_HP_USBHUB_KB	0x020c
+-
+-#define USB_VENDOR_ID_IBM		0x04b3
+-#define USB_DEVICE_ID_IBM_USBHUB_KB	0x3005
+-
+-#define USB_VENDOR_ID_CREATIVELABS	0x062a
+-#define USB_DEVICE_ID_CREATIVELABS_SILVERCREST	0x0201
+-
+ #define USB_VENDOR_ID_YEALINK		0x6993
+ #define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K	0xb001
+ /*
+@@ -1683,14 +1662,7 @@ static const struct hid_blacklist {
+ 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
+-	{ USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_KEYBOARD, HID_QUIRK_NOGET},
+-	{ USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_USBHUB_KB, HID_QUIRK_NOGET},
+-	{ USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVELABS_SILVERCREST, HID_QUIRK_NOGET },
+-	{ USB_VENDOR_ID_HP, USB_DEVICE_ID_HP_USBHUB_KB, HID_QUIRK_NOGET },
+-	{ USB_VENDOR_ID_IBM, USB_DEVICE_ID_IBM_USBHUB_KB, HID_QUIRK_NOGET },
+-	{ USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
+-	{ USB_VENDOR_ID_SILVERCREST, USB_DEVICE_ID_SILVERCREST_KB, HID_QUIRK_NOGET },
+ 
+ 	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL },
+ 	{ USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 },

commit 9da2150f59e885d88b9eabe0a677f0fa4962f7b4
+Author: Alan Stern 
+Date:   Mon May 22 16:47:13 2006 -0400
+
+    [PATCH] usbtest: report errors in iso tests
+    
+    This patch (as693b) makes the usbtest driver report errors in the
+    isochronous bulk transfer tests instead of always returning 0.  As an
+    arbitrary cutoff, an error is returned if more than 10% of the packet
+    transfers fail.  It also stops a test immediately upon receiving an URB
+    submission error.
+    
+    For a test harness, it's especially important to report when errors occur!
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
+index b42ae6bfb12b..81ba14c73dc7 100644
+--- a/drivers/usb/misc/usbtest.c
++++ b/drivers/usb/misc/usbtest.c
+@@ -1337,7 +1337,9 @@ struct iso_context {
+ 	unsigned		pending;
+ 	spinlock_t		lock;
+ 	struct completion	done;
++	int			submit_error;
+ 	unsigned long		errors;
++	unsigned long		packet_count;
+ 	struct usbtest_dev	*dev;
+ };
+ 
+@@ -1348,10 +1350,14 @@ static void iso_callback (struct urb *urb, struct pt_regs *regs)
+ 	spin_lock(&ctx->lock);
+ 	ctx->count--;
+ 
++	ctx->packet_count += urb->number_of_packets;
+ 	if (urb->error_count > 0)
+ 		ctx->errors += urb->error_count;
++	else if (urb->status != 0)
++		ctx->errors += urb->number_of_packets;
+ 
+-	if (urb->status == 0 && ctx->count > (ctx->pending - 1)) {
++	if (urb->status == 0 && ctx->count > (ctx->pending - 1)
++			&& !ctx->submit_error) {
+ 		int status = usb_submit_urb (urb, GFP_ATOMIC);
+ 		switch (status) {
+ 		case 0:
+@@ -1362,6 +1368,8 @@ static void iso_callback (struct urb *urb, struct pt_regs *regs)
+ 					status);
+ 			/* FALLTHROUGH */
+ 		case -ENODEV:			/* disconnected */
++		case -ESHUTDOWN:		/* endpoint disabled */
++			ctx->submit_error = 1;
+ 			break;
+ 		}
+ 	}
+@@ -1371,8 +1379,8 @@ static void iso_callback (struct urb *urb, struct pt_regs *regs)
+ 	if (ctx->pending == 0) {
+ 		if (ctx->errors)
+ 			dev_dbg (&ctx->dev->intf->dev,
+-				"iso test, %lu errors\n",
+-				ctx->errors);
++				"iso test, %lu errors out of %lu\n",
++				ctx->errors, ctx->packet_count);
+ 		complete (&ctx->done);
+ 	}
+ done:
+@@ -1433,15 +1441,14 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param,
+ 	struct usb_device	*udev;
+ 	unsigned		i;
+ 	unsigned long		packets = 0;
+-	int			status;
++	int			status = 0;
+ 	struct urb		*urbs[10];	/* FIXME no limit */
+ 
+ 	if (param->sglen > 10)
+ 		return -EDOM;
+ 
++	memset(&context, 0, sizeof context);
+ 	context.count = param->iterations * param->sglen;
+-	context.pending = param->sglen;
+-	context.errors = 0;
+ 	context.dev = dev;
+ 	init_completion (&context.done);
+ 	spin_lock_init (&context.lock);
+@@ -1473,6 +1480,7 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param,
+ 
+ 	spin_lock_irq (&context.lock);
+ 	for (i = 0; i < param->sglen; i++) {
++		++context.pending;
+ 		status = usb_submit_urb (urbs [i], SLAB_ATOMIC);
+ 		if (status < 0) {
+ 			ERROR (dev, "submit iso[%d], error %d\n", i, status);
+@@ -1483,12 +1491,26 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param,
+ 
+ 			simple_free_urb (urbs [i]);
+ 			context.pending--;
++			context.submit_error = 1;
++			break;
+ 		}
+ 	}
+ 	spin_unlock_irq (&context.lock);
+ 
+ 	wait_for_completion (&context.done);
+-	return 0;
++
++	/*
++	 * Isochronous transfers are expected to fail sometimes.  As an
++	 * arbitrary limit, we will report an error if any submissions
++	 * fail or if the transfer failure rate is > 10%.
++	 */
++	if (status != 0)
++		;
++	else if (context.submit_error)
++		status = -EACCES;
++	else if (context.errors > context.packet_count / 10)
++		status = -EIO;
++	return status;
+ 
+ fail:
+ 	for (i = 0; i < param->sglen; i++) {

commit 0ae4ea8092e1277cfca07cade7eaba5f594076c1
+Author: Alan Stern 
+Date:   Mon May 22 12:27:38 2006 -0400
+
+    [PATCH] gadgetfs: fix memory leaks
+    
+    This patch (as692) fixes a few memory leaks in some unimportant error
+    pathways of the gadgetfs driver.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
+index 57bf24810f9b..aef0722b8f17 100644
+--- a/drivers/usb/gadget/inode.c
++++ b/drivers/usb/gadget/inode.c
+@@ -1038,7 +1038,7 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
+ 		/* ep0 can't deliver events when STATE_SETUP */
+ 		for (i = 0; i < n; i++) {
+ 			if (dev->event [i].type == GADGETFS_SETUP) {
+-				len = n = i + 1;
++				len = i + 1;
+ 				len *= sizeof (struct usb_gadgetfs_event);
+ 				n = 0;
+ 				break;
+@@ -1586,13 +1586,13 @@ gadgetfs_create_file (struct super_block *sb, char const *name,
+ static int activate_ep_files (struct dev_data *dev)
+ {
+ 	struct usb_ep	*ep;
++	struct ep_data	*data;
+ 
+ 	gadget_for_each_ep (ep, dev->gadget) {
+-		struct ep_data	*data;
+ 
+ 		data = kzalloc(sizeof(*data), GFP_KERNEL);
+ 		if (!data)
+-			goto enomem;
++			goto enomem0;
+ 		data->state = STATE_EP_DISABLED;
+ 		init_MUTEX (&data->lock);
+ 		init_waitqueue_head (&data->wait);
+@@ -1607,21 +1607,23 @@ static int activate_ep_files (struct dev_data *dev)
+ 
+ 		data->req = usb_ep_alloc_request (ep, GFP_KERNEL);
+ 		if (!data->req)
+-			goto enomem;
++			goto enomem1;
+ 
+ 		data->inode = gadgetfs_create_file (dev->sb, data->name,
+ 				data, &ep_config_operations,
+ 				&data->dentry);
+-		if (!data->inode) {
+-			usb_ep_free_request(ep, data->req);
+-			kfree (data);
+-			goto enomem;
+-		}
++		if (!data->inode)
++			goto enomem2;
+ 		list_add_tail (&data->epfiles, &dev->epfiles);
+ 	}
+ 	return 0;
+ 
+-enomem:
++enomem2:
++	usb_ep_free_request (ep, data->req);
++enomem1:
++	put_dev (dev);
++	kfree (data);
++enomem0:
+ 	DBG (dev, "%s enomem\n", __FUNCTION__);
+ 	destroy_ep_files (dev);
+ 	return -ENOMEM;
+@@ -1792,7 +1794,7 @@ static struct usb_gadget_driver probe_driver = {
+  *
+  * After initialization, the device stays active for as long as that
+  * $CHIP file is open.  Events may then be read from that descriptor,
+- * such configuration notifications.  More complex drivers will handle
++ * such as configuration notifications.  More complex drivers will handle
+  * some control requests in user space.
+  */
+ 
+@@ -2032,12 +2034,10 @@ gadgetfs_fill_super (struct super_block *sb, void *opts, int silent)
+ 			NULL, &simple_dir_operations,
+ 			S_IFDIR | S_IRUGO | S_IXUGO);
+ 	if (!inode)
+-		return -ENOMEM;
++		goto enomem0;
+ 	inode->i_op = &simple_dir_inode_operations;
+-	if (!(d = d_alloc_root (inode))) {
+-		iput (inode);
+-		return -ENOMEM;
+-	}
++	if (!(d = d_alloc_root (inode)))
++		goto enomem1;
+ 	sb->s_root = d;
+ 
+ 	/* the ep0 file is named after the controller we expect;
+@@ -2045,21 +2045,28 @@ gadgetfs_fill_super (struct super_block *sb, void *opts, int silent)
+ 	 */
+ 	dev = dev_new ();
+ 	if (!dev)
+-		return -ENOMEM;
++		goto enomem2;
+ 
+ 	dev->sb = sb;
+-	if (!(inode = gadgetfs_create_file (sb, CHIP,
++	if (!gadgetfs_create_file (sb, CHIP,
+ 				dev, &dev_init_operations,
+-				&dev->dentry))) {
+-		put_dev(dev);
+-		return -ENOMEM;
+-	}
++				&dev->dentry))
++		goto enomem3;
+ 
+ 	/* other endpoint files are available after hardware setup,
+ 	 * from binding to a controller.
+ 	 */
+ 	the_device = dev;
+ 	return 0;
++
++enomem3:
++	put_dev (dev);
++enomem2:
++	dput (d);
++enomem1:
++	iput (inode);
++enomem0:
++	return -ENOMEM;
+ }
+ 
+ /* "mount -t gadgetfs path /dev/gadget" ends up here */

commit 83196b52053068f0240371ad2efd9d6ad685bbeb
+Author: Alan Stern 
+Date:   Mon May 22 12:26:31 2006 -0400
+
+    [PATCH] gadgetfs: fix AIO interface bugs
+    
+    This patch (as691) fixes a few errors in the AIO interface for the
+    gadgetfs driver.  Now requests will complete properly instead of hanging.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
+index 0eb010a3f5bc..57bf24810f9b 100644
+--- a/drivers/usb/gadget/inode.c
++++ b/drivers/usb/gadget/inode.c
+@@ -528,7 +528,7 @@ struct kiocb_priv {
+ 	struct usb_request	*req;
+ 	struct ep_data		*epdata;
+ 	void			*buf;
+-	char __user		*ubuf;
++	char __user		*ubuf;		/* NULL for writes */
+ 	unsigned		actual;
+ };
+ 
+@@ -566,7 +566,6 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb)
+ 		status = priv->actual;
+ 	kfree(priv->buf);
+ 	kfree(priv);
+-	aio_put_req(iocb);
+ 	return status;
+ }
+ 
+@@ -580,8 +579,8 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
+ 	spin_lock(&epdata->dev->lock);
+ 	priv->req = NULL;
+ 	priv->epdata = NULL;
+-	if (NULL == iocb->ki_retry
+-			|| unlikely(0 == req->actual)
++	if (priv->ubuf == NULL
++			|| unlikely(req->actual == 0)
+ 			|| unlikely(kiocbIsCancelled(iocb))) {
+ 		kfree(req->buf);
+ 		kfree(priv);
+@@ -618,7 +617,7 @@ ep_aio_rwtail(
+ 	char __user	*ubuf
+ )
+ {
+-	struct kiocb_priv	*priv = (void *) &iocb->private;
++	struct kiocb_priv	*priv;
+ 	struct usb_request	*req;
+ 	ssize_t			value;
+ 
+@@ -670,7 +669,7 @@ ep_aio_rwtail(
+ 		kfree(priv);
+ 		put_ep(epdata);
+ 	} else
+-		value = -EIOCBQUEUED;
++		value = (ubuf ? -EIOCBRETRY : -EIOCBQUEUED);
+ 	return value;
+ }
+ 

commit c8155cc5d839838f8425dbea568fc537337176a7
+Author: Alan Stern 
+Date:   Fri May 19 16:52:35 2006 -0400
+
+    [PATCH] UHCI: remove ISO TDs as they are used
+    
+    This patch (as690) does the same thing for ISO TDs as as680 did for
+    non-ISO TDs: free them as they are used rather than all at once when an
+    URB is complete.  At the same time it fixes a minor buglet (I'm not
+    aware of it ever affecting anyone): An ISO TD should be retired when its
+    frame is over, regardless of whether or not the hardware has marked it
+    inactive.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
+index ab8ba8220ad1..6637a0e49978 100644
+--- a/drivers/usb/host/uhci-debug.c
++++ b/drivers/usb/host/uhci-debug.c
+@@ -127,7 +127,8 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space)
+ 
+ 	i = nactive = ninactive = 0;
+ 	list_for_each_entry(td, &urbp->td_list, list) {
+-		if (++i <= 10 || debug > 2) {
++		if (urbp->qh->type != USB_ENDPOINT_XFER_ISOC &&
++				(++i <= 10 || debug > 2)) {
+ 			out += sprintf(out, "%*s%d: ", space + 2, "", i);
+ 			out += uhci_show_td(td, out, len - (out - buf), 0);
+ 		} else {
+@@ -168,8 +169,9 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
+ 			space, "", qh, qtype,
+ 			le32_to_cpu(qh->link), le32_to_cpu(element));
+ 	if (qh->type == USB_ENDPOINT_XFER_ISOC)
+-		out += sprintf(out, "%*s    period %d\n",
+-				space, "", qh->period);
++		out += sprintf(out, "%*s    period %d frame %x desc [%p]\n",
++				space, "", qh->period, qh->iso_frame,
++				qh->iso_packet_desc);
+ 
+ 	if (element & UHCI_PTR_QH)
+ 		out += sprintf(out, "%*s  Element points to QH (bug?)\n", space, "");
+@@ -331,8 +333,10 @@ static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len)
+ 	out += sprintf(out, "  sof       =       %02x\n", sof);
+ 	out += uhci_show_sc(1, portsc1, out, len - (out - buf));
+ 	out += uhci_show_sc(2, portsc2, out, len - (out - buf));
+-	out += sprintf(out, "Most recent frame: %x\n",
+-			uhci->frame_number);
++	out += sprintf(out, "Most recent frame: %x (%d)   "
++			"Last ISO frame: %x (%d)\n",
++			uhci->frame_number, uhci->frame_number & 1023,
++			uhci->last_iso_frame, uhci->last_iso_frame & 1023);
+ 
+ 	return out - buf;
+ }
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index eaac6ddf03a0..469b4268b850 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -128,8 +128,6 @@ struct uhci_qh {
+ 	__le32 element;			/* Queue element (TD) pointer */
+ 
+ 	/* Software fields */
+-	dma_addr_t dma_handle;
+-
+ 	struct list_head node;		/* Node in the list of QHs */
+ 	struct usb_host_endpoint *hep;	/* Endpoint information */
+ 	struct usb_device *udev;
+@@ -138,13 +136,19 @@ struct uhci_qh {
+ 	struct uhci_td *dummy_td;	/* Dummy TD to end the queue */
+ 	struct uhci_td *post_td;	/* Last TD completed */
+ 
++	struct usb_iso_packet_descriptor *iso_packet_desc;
++					/* Next urb->iso_frame_desc entry */
+ 	unsigned long advance_jiffies;	/* Time of last queue advance */
+ 	unsigned int unlink_frame;	/* When the QH was unlinked */
+ 	unsigned int period;		/* For Interrupt and Isochronous QHs */
++	unsigned int iso_frame;		/* Frame # for iso_packet_desc */
++	int iso_status;			/* Status for Isochronous URBs */
+ 
+ 	int state;			/* QH_STATE_xxx; see above */
+ 	int type;			/* Queue type (control, bulk, etc) */
+ 
++	dma_addr_t dma_handle;
++
+ 	unsigned int initial_toggle:1;	/* Endpoint's current toggle value */
+ 	unsigned int needs_fixup:1;	/* Must fix the TD toggle values */
+ 	unsigned int is_stopped:1;	/* Queue was stopped by error/unlink */
+@@ -386,6 +390,8 @@ struct uhci_hcd {
+ 	unsigned int frame_number;		/* As of last check */
+ 	unsigned int is_stopped;
+ #define UHCI_IS_STOPPED		9999		/* Larger than a frame # */
++	unsigned int last_iso_frame;		/* Frame of last scan */
++	unsigned int cur_iso_frame;		/* Frame for current scan */
+ 
+ 	unsigned int scan_in_progress:1;	/* Schedule scan is running */
+ 	unsigned int need_rescan:1;		/* Redo the schedule scan */
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 7acc23473c63..cbbaa4c1740f 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -184,6 +184,24 @@ static inline void uhci_remove_td_from_frame_list(struct uhci_hcd *uhci,
+ 	td->frame = -1;
+ }
+ 
++static inline void uhci_remove_tds_from_frame(struct uhci_hcd *uhci,
++		unsigned int framenum)
++{
++	struct uhci_td *ftd, *ltd;
++
++	framenum &= (UHCI_NUMFRAMES - 1);
++
++	ftd = uhci->frame_cpu[framenum];
++	if (ftd) {
++		ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list);
++		uhci->frame[framenum] = ltd->link;
++		uhci->frame_cpu[framenum] = NULL;
++
++		while (!list_empty(&ftd->fl_list))
++			list_del_init(ftd->fl_list.prev);
++	}
++}
++
+ /*
+  * Remove all the TDs for an Isochronous URB from the frame list
+  */
+@@ -523,7 +541,6 @@ static int uhci_map_status(int status, int dir_out)
+ 		return -ENOSR;
+ 	if (status & TD_CTRL_STALLED)			/* Stalled */
+ 		return -EPIPE;
+-	WARN_ON(status & TD_CTRL_ACTIVE);		/* Active */
+ 	return 0;
+ }
+ 
+@@ -960,12 +977,12 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
+ 		return -EFBIG;
+ 
+ 	/* Check the period and figure out the starting frame number */
+-	uhci_get_current_frame_number(uhci);
+ 	if (qh->period == 0) {
+ 		if (urb->transfer_flags & URB_ISO_ASAP) {
++			uhci_get_current_frame_number(uhci);
+ 			urb->start_frame = uhci->frame_number + 10;
+ 		} else {
+-			i = urb->start_frame - uhci->frame_number;
++			i = urb->start_frame - uhci->last_iso_frame;
+ 			if (i <= 0 || i >= UHCI_NUMFRAMES)
+ 				return -EINVAL;
+ 		}
+@@ -974,7 +991,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
+ 
+ 	} else {	/* Pick up where the last URB leaves off */
+ 		if (list_empty(&qh->queue)) {
+-			frame = uhci->frame_number + 10;
++			frame = qh->iso_frame;
+ 		} else {
+ 			struct urb *lurb;
+ 
+@@ -986,11 +1003,12 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
+ 		}
+ 		if (urb->transfer_flags & URB_ISO_ASAP)
+ 			urb->start_frame = frame;
+-		/* FIXME: Sanity check */
++		else if (urb->start_frame != frame)
++			return -EINVAL;
+ 	}
+ 
+ 	/* Make sure we won't have to go too far into the future */
+-	if (uhci_frame_before_eq(uhci->frame_number + UHCI_NUMFRAMES,
++	if (uhci_frame_before_eq(uhci->last_iso_frame + UHCI_NUMFRAMES,
+ 			urb->start_frame + urb->number_of_packets *
+ 				urb->interval))
+ 		return -EFBIG;
+@@ -1020,7 +1038,13 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
+ 	frame = urb->start_frame;
+ 	list_for_each_entry(td, &urbp->td_list, list) {
+ 		uhci_insert_td_in_frame_list(uhci, td, frame);
+-		frame += urb->interval;
++		frame += qh->period;
++	}
++
++	if (list_empty(&qh->queue)) {
++		qh->iso_packet_desc = &urb->iso_frame_desc[0];
++		qh->iso_frame = urb->start_frame;
++		qh->iso_status = 0;
+ 	}
+ 
+ 	return 0;
+@@ -1028,37 +1052,44 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
+ 
+ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb)
+ {
+-	struct uhci_td *td;
+-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+-	int status;
+-	int i, ret = 0;
+-
+-	urb->actual_length = urb->error_count = 0;
++	struct uhci_td *td, *tmp;
++	struct urb_priv *urbp = urb->hcpriv;
++	struct uhci_qh *qh = urbp->qh;
+ 
+-	i = 0;
+-	list_for_each_entry(td, &urbp->td_list, list) {
++	list_for_each_entry_safe(td, tmp, &urbp->td_list, list) {
++		unsigned int ctrlstat;
++		int status;
+ 		int actlength;
+-		unsigned int ctrlstat = td_status(td);
+ 
+-		if (ctrlstat & TD_CTRL_ACTIVE)
++		if (uhci_frame_before_eq(uhci->cur_iso_frame, qh->iso_frame))
+ 			return -EINPROGRESS;
+ 
+-		actlength = uhci_actual_length(ctrlstat);
+-		urb->iso_frame_desc[i].actual_length = actlength;
+-		urb->actual_length += actlength;
++		uhci_remove_tds_from_frame(uhci, qh->iso_frame);
++
++		ctrlstat = td_status(td);
++		if (ctrlstat & TD_CTRL_ACTIVE) {
++			status = -EXDEV;	/* TD was added too late? */
++		} else {
++			status = uhci_map_status(uhci_status_bits(ctrlstat),
++					usb_pipeout(urb->pipe));
++			actlength = uhci_actual_length(ctrlstat);
++
++			urb->actual_length += actlength;
++			qh->iso_packet_desc->actual_length = actlength;
++			qh->iso_packet_desc->status = status;
++		}
+ 
+-		status = uhci_map_status(uhci_status_bits(ctrlstat),
+-				usb_pipeout(urb->pipe));
+-		urb->iso_frame_desc[i].status = status;
+ 		if (status) {
+ 			urb->error_count++;
+-			ret = status;
++			qh->iso_status = status;
+ 		}
+ 
+-		i++;
++		uhci_remove_td_from_urbp(td);
++		uhci_free_td(uhci, td);
++		qh->iso_frame += qh->period;
++		++qh->iso_packet_desc;
+ 	}
+-
+-	return ret;
++	return qh->iso_status;
+ }
+ 
+ static int uhci_urb_enqueue(struct usb_hcd *hcd,
+@@ -1119,6 +1150,7 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd,
+ 		}
+ 		break;
+ 	case USB_ENDPOINT_XFER_ISOC:
++		urb->error_count = 0;
+ 		bustime = usb_check_bandwidth(urb->dev, urb);
+ 		if (bustime < 0) {
+ 			ret = bustime;
+@@ -1200,9 +1232,18 @@ __acquires(uhci->lock)
+ {
+ 	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
+ 
+-	/* Isochronous TDs get unlinked directly from the frame list */
+-	if (qh->type == USB_ENDPOINT_XFER_ISOC)
+-		uhci_unlink_isochronous_tds(uhci, urb);
++	/* When giving back the first URB in an Isochronous queue,
++	 * reinitialize the QH's iso-related members for the next URB. */
++	if (qh->type == USB_ENDPOINT_XFER_ISOC &&
++			urbp->node.prev == &qh->queue &&
++			urbp->node.next != &qh->queue) {
++		struct urb *nurb = list_entry(urbp->node.next,
++				struct urb_priv, node)->urb;
++
++		qh->iso_packet_desc = &nurb->iso_frame_desc[0];
++		qh->iso_frame = nurb->start_frame;
++		qh->iso_status = 0;
++	}
+ 
+ 	/* Take the URB off the QH's queue.  If the queue is now empty,
+ 	 * this is a perfect time for a toggle fixup. */
+@@ -1434,6 +1475,7 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs)
+ 
+ 	uhci_clear_next_interrupt(uhci);
+ 	uhci_get_current_frame_number(uhci);
++	uhci->cur_iso_frame = uhci->frame_number;
+ 
+ 	/* Go through all the QH queues and process the URBs in each one */
+ 	for (i = 0; i < UHCI_NUM_SKELQH - 1; ++i) {
+@@ -1451,6 +1493,7 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs)
+ 		}
+ 	}
+ 
++	uhci->last_iso_frame = uhci->cur_iso_frame;
+ 	if (uhci->need_rescan)
+ 		goto rescan;
+ 	uhci->scan_in_progress = 0;

commit caf3827a65af476c71eaeb79636869a4ab128d48
+Author: Alan Stern 
+Date:   Fri May 19 16:44:55 2006 -0400
+
+    [PATCH] UHCI: store the period in the queue header
+    
+    This patch (as689) stores the period for periodic transfers (interrupt
+    and ISO) in the queue header.  This is necessary for proper bandwidth
+    tracking (not yet implemented).  It also makes the scheduling of ISO
+    transfers a bit more rigorous, with checks for out-of-bounds frame
+    numbers.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
+index ecef5880cfd9..ab8ba8220ad1 100644
+--- a/drivers/usb/host/uhci-debug.c
++++ b/drivers/usb/host/uhci-debug.c
+@@ -153,7 +153,7 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
+ 	char *qtype;
+ 
+ 	/* Try to make sure there's enough memory */
+-	if (len < 80 * 6)
++	if (len < 80 * 7)
+ 		return 0;
+ 
+ 	switch (qh->type) {
+@@ -167,6 +167,9 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
+ 	out += sprintf(out, "%*s[%p] %s QH link (%08x) element (%08x)\n",
+ 			space, "", qh, qtype,
+ 			le32_to_cpu(qh->link), le32_to_cpu(element));
++	if (qh->type == USB_ENDPOINT_XFER_ISOC)
++		out += sprintf(out, "%*s    period %d\n",
++				space, "", qh->period);
+ 
+ 	if (element & UHCI_PTR_QH)
+ 		out += sprintf(out, "%*s  Element points to QH (bug?)\n", space, "");
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index c87ceaa178b6..eaac6ddf03a0 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -140,6 +140,8 @@ struct uhci_qh {
+ 
+ 	unsigned long advance_jiffies;	/* Time of last queue advance */
+ 	unsigned int unlink_frame;	/* When the QH was unlinked */
++	unsigned int period;		/* For Interrupt and Isochronous QHs */
++
+ 	int state;			/* QH_STATE_xxx; see above */
+ 	int type;			/* Queue type (control, bulk, etc) */
+ 
+@@ -315,38 +317,8 @@ static inline u32 td_status(struct uhci_td *td) {
+ #define skel_bulk_qh		skelqh[12]
+ #define skel_term_qh		skelqh[13]
+ 
+-/*
+- * Search tree for determining where  fits in the skelqh[]
+- * skeleton.
+- *
+- * An interrupt request should be placed into the slowest skelqh[]
+- * which meets the interval/period/frequency requirement.
+- * An interrupt request is allowed to be faster than  but not slower.
+- *
+- * For a given , this function returns the appropriate/matching
+- * skelqh[] index value.
+- */
+-static inline int __interval_to_skel(int interval)
+-{
+-	if (interval < 16) {
+-		if (interval < 4) {
+-			if (interval < 2)
+-				return 9;	/* int1 for 0-1 ms */
+-			return 8;		/* int2 for 2-3 ms */
+-		}
+-		if (interval < 8)
+-			return 7;		/* int4 for 4-7 ms */
+-		return 6;			/* int8 for 8-15 ms */
+-	}
+-	if (interval < 64) {
+-		if (interval < 32)
+-			return 5;		/* int16 for 16-31 ms */
+-		return 4;			/* int32 for 32-63 ms */
+-	}
+-	if (interval < 128)
+-		return 3;			/* int64 for 64-127 ms */
+-	return 2;				/* int128 for 128-255 ms (Max.) */
+-}
++/* Find the skelqh entry corresponding to an interval exponent */
++#define UHCI_SKEL_INDEX(exponent)	(9 - exponent)
+ 
+ 
+ /*
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 96ce4c87c871..7acc23473c63 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -763,6 +763,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
+ 	wmb();
+ 	qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE);
+ 	qh->dummy_td = td;
++	qh->period = urb->interval;
+ 
+ 	usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+ 			usb_pipeout(urb->pipe), toggle);
+@@ -790,14 +791,30 @@ static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb,
+ 	return ret;
+ }
+ 
+-static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb,
++static int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb,
+ 		struct uhci_qh *qh)
+ {
++	int exponent;
++
+ 	/* USB 1.1 interrupt transfers only involve one packet per interval.
+ 	 * Drivers can submit URBs of any length, but longer ones will need
+ 	 * multiple intervals to complete.
+ 	 */
+-	qh->skel = uhci->skelqh[__interval_to_skel(urb->interval)];
++
++	/* Figure out which power-of-two queue to use */
++	for (exponent = 7; exponent >= 0; --exponent) {
++		if ((1 << exponent) <= urb->interval)
++			break;
++	}
++	if (exponent < 0)
++		return -EINVAL;
++	urb->interval = 1 << exponent;
++
++	if (qh->period == 0)
++		qh->skel = uhci->skelqh[UHCI_SKEL_INDEX(exponent)];
++	else if (qh->period != urb->interval)
++		return -EINVAL;		/* Can't change the period */
++
+ 	return uhci_submit_common(uhci, urb, qh);
+ }
+ 
+@@ -937,31 +954,50 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
+ 	unsigned long destination, status;
+ 	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
+ 
+-	if (urb->number_of_packets > 900)	/* 900? Why? */
++	/* Values must not be too big (could overflow below) */
++	if (urb->interval >= UHCI_NUMFRAMES ||
++			urb->number_of_packets >= UHCI_NUMFRAMES)
+ 		return -EFBIG;
+ 
+-	status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
+-	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
++	/* Check the period and figure out the starting frame number */
++	uhci_get_current_frame_number(uhci);
++	if (qh->period == 0) {
++		if (urb->transfer_flags & URB_ISO_ASAP) {
++			urb->start_frame = uhci->frame_number + 10;
++		} else {
++			i = urb->start_frame - uhci->frame_number;
++			if (i <= 0 || i >= UHCI_NUMFRAMES)
++				return -EINVAL;
++		}
++	} else if (qh->period != urb->interval) {
++		return -EINVAL;		/* Can't change the period */
+ 
+-	/* Figure out the starting frame number */
+-	if (urb->transfer_flags & URB_ISO_ASAP) {
++	} else {	/* Pick up where the last URB leaves off */
+ 		if (list_empty(&qh->queue)) {
+-			uhci_get_current_frame_number(uhci);
+-			urb->start_frame = (uhci->frame_number + 10);
+-
+-		} else {		/* Go right after the last one */
+-			struct urb *last_urb;
++			frame = uhci->frame_number + 10;
++		} else {
++			struct urb *lurb;
+ 
+-			last_urb = list_entry(qh->queue.prev,
++			lurb = list_entry(qh->queue.prev,
+ 					struct urb_priv, node)->urb;
+-			urb->start_frame = (last_urb->start_frame +
+-					last_urb->number_of_packets *
+-					last_urb->interval);
++			frame = lurb->start_frame +
++					lurb->number_of_packets *
++					lurb->interval;
+ 		}
+-	} else {
++		if (urb->transfer_flags & URB_ISO_ASAP)
++			urb->start_frame = frame;
+ 		/* FIXME: Sanity check */
+ 	}
+ 
++	/* Make sure we won't have to go too far into the future */
++	if (uhci_frame_before_eq(uhci->frame_number + UHCI_NUMFRAMES,
++			urb->start_frame + urb->number_of_packets *
++				urb->interval))
++		return -EFBIG;
++
++	status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
++	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
++
+ 	for (i = 0; i < urb->number_of_packets; i++) {
+ 		td = uhci_alloc_td(uhci);
+ 		if (!td)
+@@ -978,6 +1014,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
+ 	td->status |= __constant_cpu_to_le32(TD_CTRL_IOC);
+ 
+ 	qh->skel = uhci->skel_iso_qh;
++	qh->period = urb->interval;
+ 
+ 	/* Add the TDs to the frame list */
+ 	frame = urb->start_frame;
+@@ -1206,6 +1243,7 @@ __acquires(uhci->lock)
+ 		uhci_unlink_qh(uhci, qh);
+ 
+ 		/* Bandwidth stuff not yet implemented */
++		qh->period = 0;
+ 	}
+ }
+ 

commit 10b8e47d6b32bfba22874354c62770cb4e42aa6c
+Author: Alan Stern 
+Date:   Fri May 19 16:39:52 2006 -0400
+
+    [PATCH] UHCI: fix race in ISO dequeuing
+    
+    This patch (as688) fixes a small race in uhci-hcd.  Because ISO queues
+    aren't controlled by queue headers, they can't be unlinked.  Only
+    individual URBs can.  So whenever multiple ISO URBs are dequeued, it's
+    necessary to make sure the hardware is done with each one.  We can't
+    assume that dequeuing the first URB will suffice to unlink the entire
+    queue.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 76b0a9e95a7a..96ce4c87c871 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -194,7 +194,6 @@ static void uhci_unlink_isochronous_tds(struct uhci_hcd *uhci, struct urb *urb)
+ 
+ 	list_for_each_entry(td, &urbp->td_list, list)
+ 		uhci_remove_td_from_frame_list(uhci, td);
+-	wmb();
+ }
+ 
+ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci,
+@@ -253,17 +252,25 @@ static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+  * When a queue is stopped and a dequeued URB is given back, adjust
+  * the previous TD link (if the URB isn't first on the queue) or
+  * save its toggle value (if it is first and is currently executing).
++ *
++ * Returns 0 if the URB should not yet be given back, 1 otherwise.
+  */
+-static void uhci_cleanup_queue(struct uhci_qh *qh,
++static int uhci_cleanup_queue(struct uhci_hcd *uhci, struct uhci_qh *qh,
+ 		struct urb *urb)
+ {
+ 	struct urb_priv *urbp = urb->hcpriv;
+ 	struct uhci_td *td;
++	int ret = 1;
+ 
+ 	/* Isochronous pipes don't use toggles and their TD link pointers
+-	 * get adjusted during uhci_urb_dequeue(). */
+-	if (qh->type == USB_ENDPOINT_XFER_ISOC)
+-		return;
++	 * get adjusted during uhci_urb_dequeue().  But since their queues
++	 * cannot truly be stopped, we have to watch out for dequeues
++	 * occurring after the nominal unlink frame. */
++	if (qh->type == USB_ENDPOINT_XFER_ISOC) {
++		ret = (uhci->frame_number + uhci->is_stopped !=
++				qh->unlink_frame);
++		return ret;
++	}
+ 
+ 	/* If the URB isn't first on its queue, adjust the link pointer
+ 	 * of the last TD in the previous URB.  The toggle doesn't need
+@@ -279,24 +286,25 @@ static void uhci_cleanup_queue(struct uhci_qh *qh,
+ 		td = list_entry(urbp->td_list.prev, struct uhci_td,
+ 				list);
+ 		ptd->link = td->link;
+-		return;
++		return ret;
+ 	}
+ 
+ 	/* If the QH element pointer is UHCI_PTR_TERM then then currently
+ 	 * executing URB has already been unlinked, so this one isn't it. */
+ 	if (qh_element(qh) == UHCI_PTR_TERM)
+-		return;
++		return ret;
+ 	qh->element = UHCI_PTR_TERM;
+ 
+ 	/* Control pipes have to worry about toggles */
+ 	if (qh->type == USB_ENDPOINT_XFER_CONTROL)
+-		return;
++		return ret;
+ 
+ 	/* Save the next toggle value */
+ 	WARN_ON(list_empty(&urbp->td_list));
+ 	td = list_entry(urbp->td_list.next, struct uhci_td, list);
+ 	qh->needs_fixup = 1;
+ 	qh->initial_toggle = uhci_toggle(td_token(td));
++	return ret;
+ }
+ 
+ /*
+@@ -953,7 +961,6 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
+ 	} else {
+ 		/* FIXME: Sanity check */
+ 	}
+-	urb->start_frame &= (UHCI_NUMFRAMES - 1);
+ 
+ 	for (i = 0; i < urb->number_of_packets; i++) {
+ 		td = uhci_alloc_td(uhci);
+@@ -1120,16 +1127,26 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 	unsigned long flags;
+ 	struct urb_priv *urbp;
++	struct uhci_qh *qh;
+ 
+ 	spin_lock_irqsave(&uhci->lock, flags);
+ 	urbp = urb->hcpriv;
+ 	if (!urbp)			/* URB was never linked! */
+ 		goto done;
++	qh = urbp->qh;
+ 
+ 	/* Remove Isochronous TDs from the frame list ASAP */
+-	if (urbp->qh->type == USB_ENDPOINT_XFER_ISOC)
++	if (qh->type == USB_ENDPOINT_XFER_ISOC) {
+ 		uhci_unlink_isochronous_tds(uhci, urb);
+-	uhci_unlink_qh(uhci, urbp->qh);
++		mb();
++
++		/* If the URB has already started, update the QH unlink time */
++		uhci_get_current_frame_number(uhci);
++		if (uhci_frame_before_eq(urb->start_frame, uhci->frame_number))
++			qh->unlink_frame = uhci->frame_number;
++	}
++
++	uhci_unlink_qh(uhci, qh);
+ 
+ done:
+ 	spin_unlock_irqrestore(&uhci->lock, flags);
+@@ -1250,7 +1267,14 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh,
+ 	list_for_each_entry(urbp, &qh->queue, node) {
+ 		urb = urbp->urb;
+ 		if (urb->status != -EINPROGRESS) {
+-			uhci_cleanup_queue(qh, urb);
++
++			/* Fix up the TD links and save the toggles for
++			 * non-Isochronous queues.  For Isochronous queues,
++			 * test for too-recent dequeues. */
++			if (!uhci_cleanup_queue(uhci, qh, urb)) {
++				qh->is_stopped = 0;
++				return;
++			}
+ 			uhci_giveback_urb(uhci, qh, urb, regs);
+ 			goto restart;
+ 		}

commit c433472658b4df11bd3590a59be79194a1ff43ae
+Author: Alan Stern 
+Date:   Fri May 19 16:34:57 2006 -0400
+
+    [PATCH] UHCI: use integer-sized frame numbers
+    
+    This patch (as687) changes uhci-hcd to keep track of frame numbers as
+    full-sized integers rather than 11-bit values.  This makes them a lot
+    easier to handle and makes it possible to schedule beyond a 2-second
+    window, should anyone ever want to do so.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
+index 081c592fe8b1..ecef5880cfd9 100644
+--- a/drivers/usb/host/uhci-debug.c
++++ b/drivers/usb/host/uhci-debug.c
+@@ -289,7 +289,7 @@ static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len)
+ 	unsigned short portsc1, portsc2;
+ 
+ 	/* Try to make sure there's enough memory */
+-	if (len < 80 * 6)
++	if (len < 80 * 9)
+ 		return 0;
+ 
+ 	usbcmd    = inw(io_addr + 0);
+@@ -328,6 +328,8 @@ static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len)
+ 	out += sprintf(out, "  sof       =       %02x\n", sof);
+ 	out += uhci_show_sc(1, portsc1, out, len - (out - buf));
+ 	out += uhci_show_sc(2, portsc2, out, len - (out - buf));
++	out += sprintf(out, "Most recent frame: %x\n",
++			uhci->frame_number);
+ 
+ 	return out - buf;
+ }
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 395402eec5ef..5e75ad6dc29f 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -13,7 +13,7 @@
+  * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
+  *               support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
+  * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
+- * (C) Copyright 2004-2005 Alan Stern, stern@rowland.harvard.edu
++ * (C) Copyright 2004-2006 Alan Stern, stern@rowland.harvard.edu
+  *
+  * Intel documents this fairly well, and as far as I know there
+  * are no royalties or anything like that, but even so there are
+@@ -31,7 +31,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ #include 
+ #include 
+ #include 
+@@ -146,7 +145,8 @@ static void configure_hc(struct uhci_hcd *uhci)
+ 	outl(uhci->frame_dma_handle, uhci->io_addr + USBFLBASEADD);
+ 
+ 	/* Set the current frame number */
+-	outw(uhci->frame_number, uhci->io_addr + USBFRNUM);
++	outw(uhci->frame_number & UHCI_MAX_SOF_NUMBER,
++			uhci->io_addr + USBFRNUM);
+ 
+ 	/* Mark controller as not halted before we enable interrupts */
+ 	uhci_to_hcd(uhci)->state = HC_STATE_SUSPENDED;
+@@ -239,7 +239,6 @@ __acquires(uhci->lock)
+ 		dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n");
+ 
+ 	uhci_get_current_frame_number(uhci);
+-	smp_wmb();
+ 
+ 	uhci->rh_state = new_state;
+ 	uhci->is_stopped = UHCI_IS_STOPPED;
+@@ -253,7 +252,6 @@ static void start_rh(struct uhci_hcd *uhci)
+ {
+ 	uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;
+ 	uhci->is_stopped = 0;
+-	smp_wmb();
+ 
+ 	/* Mark it configured and running with a 64-byte max packet.
+ 	 * All interrupts are enabled, even though RESUME won't do anything.
+@@ -360,12 +358,21 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
+ 
+ /*
+  * Store the current frame number in uhci->frame_number if the controller
+- * is runnning
++ * is runnning.  Expand from 11 bits (of which we use only 10) to a
++ * full-sized integer.
++ *
++ * Like many other parts of the driver, this code relies on being polled
++ * more than once per second as long as the controller is running.
+  */
+ static void uhci_get_current_frame_number(struct uhci_hcd *uhci)
+ {
+-	if (!uhci->is_stopped)
+-		uhci->frame_number = inw(uhci->io_addr + USBFRNUM);
++	if (!uhci->is_stopped) {
++		unsigned delta;
++
++		delta = (inw(uhci->io_addr + USBFRNUM) - uhci->frame_number) &
++				(UHCI_NUMFRAMES - 1);
++		uhci->frame_number += delta;
++	}
+ }
+ 
+ /*
+@@ -798,18 +805,15 @@ static void uhci_hcd_endpoint_disable(struct usb_hcd *hcd,
+ static int uhci_hcd_get_frame_number(struct usb_hcd *hcd)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+-	unsigned long flags;
+-	int is_stopped;
+-	int frame_number;
++	unsigned frame_number;
++	unsigned delta;
+ 
+ 	/* Minimize latency by avoiding the spinlock */
+-	local_irq_save(flags);
+-	is_stopped = uhci->is_stopped;
+-	smp_rmb();
+-	frame_number = (is_stopped ? uhci->frame_number :
+-			inw(uhci->io_addr + USBFRNUM));
+-	local_irq_restore(flags);
+-	return frame_number;
++	frame_number = uhci->frame_number;
++	barrier();
++	delta = (inw(uhci->io_addr + USBFRNUM) - frame_number) &
++			(UHCI_NUMFRAMES - 1);
++	return frame_number + delta;
+ }
+ 
+ static const char hcd_name[] = "uhci_hcd";
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index 04938e64799f..c87ceaa178b6 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -448,6 +448,9 @@ static inline struct usb_hcd *uhci_to_hcd(struct uhci_hcd *uhci)
+ 
+ #define uhci_dev(u)	(uhci_to_hcd(u)->self.controller)
+ 
++/* Utility macro for comparing frame numbers */
++#define uhci_frame_before_eq(f1, f2)	(0 <= (int) ((f2) - (f1)))
++
+ 
+ /*
+  *	Private per-URB data

commit b761d9d867bcc29e8de3e62d1d72b27e75078ca6
+Author: Alan Stern 
+Date:   Fri May 12 11:41:59 2006 -0400
+
+    [PATCH] UHCI: Work around old Intel bug
+    
+    Some old Intel UHCI controllers have a bug that has shown up in a few
+    systems (the PIIX3 "Neptune" chip set).  Until now there has not been
+    any simple way to work around the bug, but the lastest changes in
+    uhci-hcd have made it easy.  This patch (as684) adds the work-around.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 2be84b3b40fe..76b0a9e95a7a 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -13,7 +13,7 @@
+  * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
+  *               support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
+  * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
+- * (C) Copyright 2004-2005 Alan Stern, stern@rowland.harvard.edu
++ * (C) Copyright 2004-2006 Alan Stern, stern@rowland.harvard.edu
+  */
+ 
+ 
+@@ -1287,6 +1287,11 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh,
+  * Check for queues that have made some forward progress.
+  * Returns 0 if the queue is not Isochronous, is ACTIVE, and
+  * has not advanced since last examined; 1 otherwise.
++ *
++ * Early Intel controllers have a bug which causes qh->element sometimes
++ * not to advance when a TD completes successfully.  The queue remains
++ * stuck on the inactive completed TD.  We detect such cases and advance
++ * the element pointer by hand.
+  */
+ static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ {
+@@ -1327,6 +1332,15 @@ static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ 	/* The queue hasn't advanced; check for timeout */
+ 	if (!qh->wait_expired && time_after(jiffies,
+ 			qh->advance_jiffies + QH_WAIT_TIMEOUT)) {
++
++		/* Detect the Intel bug and work around it */
++		if (qh->post_td && qh_element(qh) ==
++				cpu_to_le32(qh->post_td->dma_handle)) {
++			qh->element = qh->post_td->link;
++			qh->advance_jiffies = jiffies;
++			return 1;
++		}
++
+ 		qh->wait_expired = 1;
+ 
+ 		/* If the current URB wants FSBR, unlink it temporarily

commit 84afddd7ac58adad00cb0e50d0af25fcf825668b
+Author: Alan Stern 
+Date:   Fri May 12 11:35:45 2006 -0400
+
+    [PATCH] UHCI: Reimplement FSBR
+    
+    This patch (as683) re-implements Full-Speed Bandwidth Reclamation (FSBR)
+    properly.  It keeps track of which endpoint queues have advanced, and
+    when none have advanced for a sufficiently long time, FSBR is turned
+    off.  The next TD on each of the non-moving queues is modified to
+    generate an interrupt on completion, so that FSBR can be re-enabled as
+    soon as the hardware starts to make some progress.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
+index 6bbd33db9358..081c592fe8b1 100644
+--- a/drivers/usb/host/uhci-debug.c
++++ b/drivers/usb/host/uhci-debug.c
+@@ -274,7 +274,8 @@ static int uhci_show_root_hub_state(struct uhci_hcd *uhci, char *buf, int len)
+ 	    default:
+ 		rh_state = "?";			break;
+ 	}
+-	out += sprintf(out, "Root-hub state: %s\n", rh_state);
++	out += sprintf(out, "Root-hub state: %s   FSBR: %d\n",
++			rh_state, uhci->fsbr_is_on);
+ 	return out - buf;
+ }
+ 
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index fb4c1a8cadf4..395402eec5ef 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -88,15 +88,6 @@ static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state);
+ static void wakeup_rh(struct uhci_hcd *uhci);
+ static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
+ 
+-/* If a transfer is still active after this much time, turn off FSBR */
+-#define IDLE_TIMEOUT	msecs_to_jiffies(50)
+-#define FSBR_DELAY	msecs_to_jiffies(50)
+-
+-/* When we timeout an idle transfer for FSBR, we'll switch it over to */
+-/* depth first traversal. We'll do it in groups of this number of TDs */
+-/* to make sure it doesn't hog all of the bandwidth */
+-#define DEPTH_INTERVAL 5
+-
+ #include "uhci-debug.c"
+ #include "uhci-q.c"
+ #include "uhci-hub.c"
+@@ -255,6 +246,7 @@ __acquires(uhci->lock)
+ 	uhci_to_hcd(uhci)->poll_rh = !int_enable;
+ 
+ 	uhci_scan_schedule(uhci, NULL);
++	uhci_fsbr_off(uhci);
+ }
+ 
+ static void start_rh(struct uhci_hcd *uhci)
+@@ -487,9 +479,6 @@ static int uhci_start(struct usb_hcd *hcd)
+ 
+ 	hcd->uses_new_polling = 1;
+ 
+-	uhci->fsbr = 0;
+-	uhci->fsbrtimeout = 0;
+-
+ 	spin_lock_init(&uhci->lock);
+ 
+ 	INIT_LIST_HEAD(&uhci->idle_qh_list);
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index 90ef7fbbf2fb..04938e64799f 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -84,6 +84,13 @@
+ #define CAN_SCHEDULE_FRAMES	1000	/* how far in the future frames
+ 					 * can be scheduled */
+ 
++/* When no queues need Full-Speed Bandwidth Reclamation,
++ * delay this long before turning FSBR off */
++#define FSBR_OFF_DELAY		msecs_to_jiffies(400)
++
++/* If a queue hasn't advanced after this much time, assume it is stuck */
++#define QH_WAIT_TIMEOUT		msecs_to_jiffies(200)
++
+ 
+ /*
+  *	Queue Headers
+@@ -131,6 +138,7 @@ struct uhci_qh {
+ 	struct uhci_td *dummy_td;	/* Dummy TD to end the queue */
+ 	struct uhci_td *post_td;	/* Last TD completed */
+ 
++	unsigned long advance_jiffies;	/* Time of last queue advance */
+ 	unsigned int unlink_frame;	/* When the QH was unlinked */
+ 	int state;			/* QH_STATE_xxx; see above */
+ 	int type;			/* Queue type (control, bulk, etc) */
+@@ -138,6 +146,7 @@ struct uhci_qh {
+ 	unsigned int initial_toggle:1;	/* Endpoint's current toggle value */
+ 	unsigned int needs_fixup:1;	/* Must fix the TD toggle values */
+ 	unsigned int is_stopped:1;	/* Queue was stopped by error/unlink */
++	unsigned int wait_expired:1;	/* QH_WAIT_TIMEOUT has expired */
+ } __attribute__((aligned(16)));
+ 
+ /*
+@@ -397,8 +406,7 @@ struct uhci_hcd {
+ 	__le32 *frame;
+ 	void **frame_cpu;		/* CPU's frame list */
+ 
+-	int fsbr;			/* Full-speed bandwidth reclamation */
+-	unsigned long fsbrtimeout;	/* FSBR delay */
++	unsigned long fsbr_jiffies;	/* Time when FSBR was last wanted */
+ 
+ 	enum uhci_rh_state rh_state;
+ 	unsigned long auto_stop_time;		/* When to AUTO_STOP */
+@@ -413,6 +421,7 @@ struct uhci_hcd {
+ 	unsigned int working_RD:1;		/* Suspended root hub doesn't
+ 						   need to be polled */
+ 	unsigned int is_initialized:1;		/* Data structure is usable */
++	unsigned int fsbr_is_on:1;		/* FSBR is turned on */
+ 
+ 	/* Support for port suspend/resume/reset */
+ 	unsigned long port_c_suspend;		/* Bit-arrays of ports */
+@@ -451,7 +460,7 @@ struct urb_priv {
+ 	struct uhci_qh *qh;		/* QH for this URB */
+ 	struct list_head td_list;
+ 
+-	unsigned fsbr : 1;		/* URB turned on FSBR */
++	unsigned fsbr:1;		/* URB wants FSBR */
+ };
+ 
+ 
+diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
+index c8451d9578f1..f53c116e0dfd 100644
+--- a/drivers/usb/host/uhci-hub.c
++++ b/drivers/usb/host/uhci-hub.c
+@@ -173,7 +173,6 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
+ 	uhci_scan_schedule(uhci, NULL);
+ 	if (uhci->hc_inaccessible)
+ 		goto done;
+-	check_fsbr(uhci);
+ 	uhci_check_ports(uhci);
+ 
+ 	status = get_hub_status_data(uhci, buf);
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 12af6fb05a30..2be84b3b40fe 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -37,6 +37,46 @@ static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci)
+ 	uhci->term_td->status &= ~cpu_to_le32(TD_CTRL_IOC);
+ }
+ 
++
++/*
++ * Full-Speed Bandwidth Reclamation (FSBR).
++ * We turn on FSBR whenever a queue that wants it is advancing,
++ * and leave it on for a short time thereafter.
++ */
++static void uhci_fsbr_on(struct uhci_hcd *uhci)
++{
++	uhci->fsbr_is_on = 1;
++	uhci->skel_term_qh->link = cpu_to_le32(
++			uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH;
++}
++
++static void uhci_fsbr_off(struct uhci_hcd *uhci)
++{
++	uhci->fsbr_is_on = 0;
++	uhci->skel_term_qh->link = UHCI_PTR_TERM;
++}
++
++static void uhci_add_fsbr(struct uhci_hcd *uhci, struct urb *urb)
++{
++	struct urb_priv *urbp = urb->hcpriv;
++
++	if (!(urb->transfer_flags & URB_NO_FSBR))
++		urbp->fsbr = 1;
++}
++
++static void uhci_qh_wants_fsbr(struct uhci_hcd *uhci, struct uhci_qh *qh)
++{
++	struct urb_priv *urbp =
++			list_entry(qh->queue.next, struct urb_priv, node);
++
++	if (urbp->fsbr) {
++		uhci->fsbr_jiffies = jiffies;
++		if (!uhci->fsbr_is_on)
++			uhci_fsbr_on(uhci);
++	}
++}
++
++
+ static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci)
+ {
+ 	dma_addr_t dma_handle;
+@@ -331,6 +371,10 @@ static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ 		qh->element = cpu_to_le32(td->dma_handle);
+ 	}
+ 
++	/* Treat the queue as if it has just advanced */
++	qh->wait_expired = 0;
++	qh->advance_jiffies = jiffies;
++
+ 	if (qh->state == QH_STATE_ACTIVE)
+ 		return;
+ 	qh->state = QH_STATE_ACTIVE;
+@@ -445,28 +489,6 @@ static void uhci_free_urb_priv(struct uhci_hcd *uhci,
+ 	kmem_cache_free(uhci_up_cachep, urbp);
+ }
+ 
+-static void uhci_inc_fsbr(struct uhci_hcd *uhci, struct urb *urb)
+-{
+-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+-
+-	if ((!(urb->transfer_flags & URB_NO_FSBR)) && !urbp->fsbr) {
+-		urbp->fsbr = 1;
+-		if (!uhci->fsbr++ && !uhci->fsbrtimeout)
+-			uhci->skel_term_qh->link = cpu_to_le32(uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH;
+-	}
+-}
+-
+-static void uhci_dec_fsbr(struct uhci_hcd *uhci, struct urb *urb)
+-{
+-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+-
+-	if ((!(urb->transfer_flags & URB_NO_FSBR)) && urbp->fsbr) {
+-		urbp->fsbr = 0;
+-		if (!--uhci->fsbr)
+-			uhci->fsbrtimeout = jiffies + FSBR_DELAY;
+-	}
+-}
+-
+ /*
+  * Map status to standard result codes
+  *
+@@ -613,7 +635,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
+ 		qh->skel = uhci->skel_ls_control_qh;
+ 	else {
+ 		qh->skel = uhci->skel_fs_control_qh;
+-		uhci_inc_fsbr(uhci, urb);
++		uhci_add_fsbr(uhci, urb);
+ 	}
+ 
+ 	urb->actual_length = -8;	/* Account for the SETUP packet */
+@@ -756,7 +778,7 @@ static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb,
+ 	qh->skel = uhci->skel_bulk_qh;
+ 	ret = uhci_submit_common(uhci, urb, qh);
+ 	if (ret == 0)
+-		uhci_inc_fsbr(uhci, urb);
++		uhci_add_fsbr(uhci, urb);
+ 	return ret;
+ }
+ 
+@@ -1075,8 +1097,10 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd,
+ 	 * the QH is new and idle or else it's unlinked and waiting to
+ 	 * become idle, so we can activate it right away.  But only if the
+ 	 * queue isn't stopped. */
+-	if (qh->queue.next == &urbp->node && !qh->is_stopped)
++	if (qh->queue.next == &urbp->node && !qh->is_stopped) {
+ 		uhci_activate_qh(uhci, qh);
++		uhci_qh_wants_fsbr(uhci, qh);
++	}
+ 	goto done;
+ 
+ err_submit_failed:
+@@ -1135,7 +1159,6 @@ __acquires(uhci->lock)
+ 		qh->needs_fixup = 0;
+ 	}
+ 
+-	uhci_dec_fsbr(uhci, urb);	/* Safe since it checks */
+ 	uhci_free_urb_priv(uhci, urbp);
+ 
+ 	switch (qh->type) {
+@@ -1239,6 +1262,18 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh,
+ 	if (!list_empty(&qh->queue)) {
+ 		if (qh->needs_fixup)
+ 			uhci_fixup_toggles(qh, 0);
++
++		/* If the first URB on the queue wants FSBR but its time
++		 * limit has expired, set the next TD to interrupt on
++		 * completion before reactivating the QH. */
++		urbp = list_entry(qh->queue.next, struct urb_priv, node);
++		if (urbp->fsbr && qh->wait_expired) {
++			struct uhci_td *td = list_entry(urbp->td_list.next,
++					struct uhci_td, list);
++
++			td->status |= __cpu_to_le32(TD_CTRL_IOC);
++		}
++
+ 		uhci_activate_qh(uhci, qh);
+ 	}
+ 
+@@ -1248,6 +1283,62 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh,
+ 		uhci_make_qh_idle(uhci, qh);
+ }
+ 
++/*
++ * Check for queues that have made some forward progress.
++ * Returns 0 if the queue is not Isochronous, is ACTIVE, and
++ * has not advanced since last examined; 1 otherwise.
++ */
++static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh)
++{
++	struct urb_priv *urbp = NULL;
++	struct uhci_td *td;
++	int ret = 1;
++	unsigned status;
++
++	if (qh->type == USB_ENDPOINT_XFER_ISOC)
++		return ret;
++
++	/* Treat an UNLINKING queue as though it hasn't advanced.
++	 * This is okay because reactivation will treat it as though
++	 * it has advanced, and if it is going to become IDLE then
++	 * this doesn't matter anyway.  Furthermore it's possible
++	 * for an UNLINKING queue not to have any URBs at all, or
++	 * for its first URB not to have any TDs (if it was dequeued
++	 * just as it completed).  So it's not easy in any case to
++	 * test whether such queues have advanced. */
++	if (qh->state != QH_STATE_ACTIVE) {
++		urbp = NULL;
++		status = 0;
++
++	} else {
++		urbp = list_entry(qh->queue.next, struct urb_priv, node);
++		td = list_entry(urbp->td_list.next, struct uhci_td, list);
++		status = td_status(td);
++		if (!(status & TD_CTRL_ACTIVE)) {
++
++			/* We're okay, the queue has advanced */
++			qh->wait_expired = 0;
++			qh->advance_jiffies = jiffies;
++			return ret;
++		}
++		ret = 0;
++	}
++
++	/* The queue hasn't advanced; check for timeout */
++	if (!qh->wait_expired && time_after(jiffies,
++			qh->advance_jiffies + QH_WAIT_TIMEOUT)) {
++		qh->wait_expired = 1;
++
++		/* If the current URB wants FSBR, unlink it temporarily
++		 * so that we can safely set the next TD to interrupt on
++		 * completion.  That way we'll know as soon as the queue
++		 * starts moving again. */
++		if (urbp && urbp->fsbr && !(status & TD_CTRL_IOC))
++			uhci_unlink_qh(uhci, qh);
++	}
++	return ret;
++}
++
+ /*
+  * Process events in the schedule, but only in one thread at a time
+  */
+@@ -1262,7 +1353,7 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs)
+ 		return;
+ 	}
+ 	uhci->scan_in_progress = 1;
+- rescan:
++rescan:
+ 	uhci->need_rescan = 0;
+ 
+ 	uhci_clear_next_interrupt(uhci);
+@@ -1275,7 +1366,12 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs)
+ 		while ((qh = uhci->next_qh) != uhci->skelqh[i]) {
+ 			uhci->next_qh = list_entry(qh->node.next,
+ 					struct uhci_qh, node);
+-			uhci_scan_qh(uhci, qh, regs);
++
++			if (uhci_advance_check(uhci, qh)) {
++				uhci_scan_qh(uhci, qh, regs);
++				if (qh->state == QH_STATE_ACTIVE)
++					uhci_qh_wants_fsbr(uhci, qh);
++			}
+ 		}
+ 	}
+ 
+@@ -1283,20 +1379,12 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs)
+ 		goto rescan;
+ 	uhci->scan_in_progress = 0;
+ 
++	if (uhci->fsbr_is_on && time_after(jiffies,
++			uhci->fsbr_jiffies + FSBR_OFF_DELAY))
++		uhci_fsbr_off(uhci);
++
+ 	if (list_empty(&uhci->skel_unlink_qh->node))
+ 		uhci_clear_next_interrupt(uhci);
+ 	else
+ 		uhci_set_next_interrupt(uhci);
+ }
+-
+-static void check_fsbr(struct uhci_hcd *uhci)
+-{
+-	/* For now, don't scan URBs for FSBR timeouts.
+-	 * Add it back in later... */
+-
+-	/* Really disable FSBR */
+-	if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) {
+-		uhci->fsbrtimeout = 0;
+-		uhci->skel_term_qh->link = UHCI_PTR_TERM;
+-	}
+-}

commit 04538a255ac8b404c20cbf15867c9829254c470f
+Author: Alan Stern 
+Date:   Fri May 12 11:29:04 2006 -0400
+
+    [PATCH] UHCI: Eliminate the TD-removal list
+    
+    This patch (as682) gets rid of the TD-removal list in uhci-hcd.  It is
+    no longer needed because now TDs are not freed until we know the
+    hardware isn't using them.  It also simplifies the code for adding and
+    removing TDs to/from URBs.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index d225e11f4055..fb4c1a8cadf4 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -492,7 +492,6 @@ static int uhci_start(struct usb_hcd *hcd)
+ 
+ 	spin_lock_init(&uhci->lock);
+ 
+-	INIT_LIST_HEAD(&uhci->td_remove_list);
+ 	INIT_LIST_HEAD(&uhci->idle_qh_list);
+ 
+ 	init_waitqueue_head(&uhci->waitqh);
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index 3093ca250942..90ef7fbbf2fb 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -228,7 +228,6 @@ struct uhci_td {
+ 	dma_addr_t dma_handle;
+ 
+ 	struct list_head list;
+-	struct list_head remove_list;
+ 
+ 	int frame;			/* for iso: what frame? */
+ 	struct list_head fl_list;
+@@ -420,10 +419,6 @@ struct uhci_hcd {
+ 	unsigned long resuming_ports;
+ 	unsigned long ports_timeout;		/* Time to stop signalling */
+ 
+-	/* List of TDs that are done, but waiting to be freed (race) */
+-	struct list_head td_remove_list;
+-	unsigned int td_remove_age;		/* Age in frames */
+-
+ 	struct list_head idle_qh_list;		/* Where the idle QHs live */
+ 
+ 	int rh_numports;			/* Number of root-hub ports */
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 64b6c74789fd..12af6fb05a30 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -16,7 +16,6 @@
+  * (C) Copyright 2004-2005 Alan Stern, stern@rowland.harvard.edu
+  */
+ 
+-static void uhci_free_pending_tds(struct uhci_hcd *uhci);
+ 
+ /*
+  * Technically, updating td->status here is a race, but it's not really a
+@@ -51,7 +50,6 @@ static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci)
+ 	td->frame = -1;
+ 
+ 	INIT_LIST_HEAD(&td->list);
+-	INIT_LIST_HEAD(&td->remove_list);
+ 	INIT_LIST_HEAD(&td->fl_list);
+ 
+ 	return td;
+@@ -61,8 +59,6 @@ static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td)
+ {
+ 	if (!list_empty(&td->list))
+ 		dev_warn(uhci_dev(uhci), "td %p still in list!\n", td);
+-	if (!list_empty(&td->remove_list))
+-		dev_warn(uhci_dev(uhci), "td %p still in remove_list!\n", td);
+ 	if (!list_empty(&td->fl_list))
+ 		dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td);
+ 
+@@ -77,6 +73,16 @@ static inline void uhci_fill_td(struct uhci_td *td, u32 status,
+ 	td->buffer = cpu_to_le32(buffer);
+ }
+ 
++static void uhci_add_td_to_urbp(struct uhci_td *td, struct urb_priv *urbp)
++{
++	list_add_tail(&td->list, &urbp->td_list);
++}
++
++static void uhci_remove_td_from_urbp(struct uhci_td *td)
++{
++	list_del_init(&td->list);
++}
++
+ /*
+  * We insert Isochronous URBs directly into the frame list at the beginning
+  */
+@@ -421,21 +427,6 @@ static inline struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci,
+ 	return urbp;
+ }
+ 
+-static void uhci_add_td_to_urb(struct urb *urb, struct uhci_td *td)
+-{
+-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+-
+-	list_add_tail(&td->list, &urbp->td_list);
+-}
+-
+-static void uhci_remove_td_from_urb(struct uhci_td *td)
+-{
+-	if (list_empty(&td->list))
+-		return;
+-
+-	list_del_init(&td->list);
+-}
+-
+ static void uhci_free_urb_priv(struct uhci_hcd *uhci,
+ 		struct urb_priv *urbp)
+ {
+@@ -445,20 +436,9 @@ static void uhci_free_urb_priv(struct uhci_hcd *uhci,
+ 		dev_warn(uhci_dev(uhci), "urb %p still on QH's list!\n",
+ 				urbp->urb);
+ 
+-	uhci_get_current_frame_number(uhci);
+-	if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age) {
+-		uhci_free_pending_tds(uhci);
+-		uhci->td_remove_age = uhci->frame_number;
+-	}
+-
+-	/* Check to see if the remove list is empty. Set the IOC bit */
+-	/* to force an interrupt so we can remove the TDs. */
+-	if (list_empty(&uhci->td_remove_list))
+-		uhci_set_next_interrupt(uhci);
+-
+ 	list_for_each_entry_safe(td, tmp, &urbp->td_list, list) {
+-		uhci_remove_td_from_urb(td);
+-		list_add(&td->remove_list, &uhci->td_remove_list);
++		uhci_remove_td_from_urbp(td);
++		uhci_free_td(uhci, td);
+ 	}
+ 
+ 	urbp->urb->hcpriv = NULL;
+@@ -529,6 +509,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
+ 	int len = urb->transfer_buffer_length;
+ 	dma_addr_t data = urb->transfer_dma;
+ 	__le32 *plink;
++	struct urb_priv *urbp = urb->hcpriv;
+ 
+ 	/* The "pipe" thing contains the destination in bits 8--18 */
+ 	destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
+@@ -542,7 +523,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
+ 	 * Build the TD for the control request setup packet
+ 	 */
+ 	td = qh->dummy_td;
+-	uhci_add_td_to_urb(urb, td);
++	uhci_add_td_to_urbp(td, urbp);
+ 	uhci_fill_td(td, status, destination | uhci_explen(8),
+ 			urb->setup_dma);
+ 	plink = &td->link;
+@@ -574,7 +555,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
+ 		/* Alternate Data0/1 (start with Data1) */
+ 		destination ^= TD_TOKEN_TOGGLE;
+ 	
+-		uhci_add_td_to_urb(urb, td);
++		uhci_add_td_to_urbp(td, urbp);
+ 		uhci_fill_td(td, status, destination | uhci_explen(pktsze),
+ 				data);
+ 		plink = &td->link;
+@@ -605,7 +586,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
+ 
+ 	status &= ~TD_CTRL_SPD;
+ 
+-	uhci_add_td_to_urb(urb, td);
++	uhci_add_td_to_urbp(td, urbp);
+ 	uhci_fill_td(td, status | TD_CTRL_IOC,
+ 			destination | uhci_explen(0), 0);
+ 	plink = &td->link;
+@@ -640,7 +621,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
+ 
+ nomem:
+ 	/* Remove the dummy TD from the td_list so it doesn't get freed */
+-	uhci_remove_td_from_urb(qh->dummy_td);
++	uhci_remove_td_from_urbp(qh->dummy_td);
+ 	return -ENOMEM;
+ }
+ 
+@@ -656,6 +637,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
+ 	int len = urb->transfer_buffer_length;
+ 	dma_addr_t data = urb->transfer_dma;
+ 	__le32 *plink;
++	struct urb_priv *urbp = urb->hcpriv;
+ 	unsigned int toggle;
+ 
+ 	if (len < 0)
+@@ -693,7 +675,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
+ 				goto nomem;
+ 			*plink = cpu_to_le32(td->dma_handle);
+ 		}
+-		uhci_add_td_to_urb(urb, td);
++		uhci_add_td_to_urbp(td, urbp);
+ 		uhci_fill_td(td, status,
+ 				destination | uhci_explen(pktsze) |
+ 					(toggle << TD_TOKEN_TOGGLE_SHIFT),
+@@ -721,7 +703,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
+ 			goto nomem;
+ 		*plink = cpu_to_le32(td->dma_handle);
+ 
+-		uhci_add_td_to_urb(urb, td);
++		uhci_add_td_to_urbp(td, urbp);
+ 		uhci_fill_td(td, status,
+ 				destination | uhci_explen(0) |
+ 					(toggle << TD_TOKEN_TOGGLE_SHIFT),
+@@ -758,7 +740,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
+ 
+ nomem:
+ 	/* Remove the dummy TD from the td_list so it doesn't get freed */
+-	uhci_remove_td_from_urb(qh->dummy_td);
++	uhci_remove_td_from_urbp(qh->dummy_td);
+ 	return -ENOMEM;
+ }
+ 
+@@ -830,8 +812,8 @@ static int uhci_fixup_short_transfer(struct uhci_hcd *uhci,
+ 		td = list_entry(tmp, struct uhci_td, list);
+ 		tmp = tmp->prev;
+ 
+-		uhci_remove_td_from_urb(td);
+-		list_add(&td->remove_list, &uhci->td_remove_list);
++		uhci_remove_td_from_urbp(td);
++		uhci_free_td(uhci, td);
+ 	}
+ 	return ret;
+ }
+@@ -885,10 +867,9 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
+ 				ret = 1;
+ 		}
+ 
+-		uhci_remove_td_from_urb(td);
++		uhci_remove_td_from_urbp(td);
+ 		if (qh->post_td)
+-			list_add(&qh->post_td->remove_list,
+-					&uhci->td_remove_list);
++			uhci_free_td(uhci, qh->post_td);
+ 		qh->post_td = td;
+ 
+ 		if (ret != 0)
+@@ -957,7 +938,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
+ 		if (!td)
+ 			return -ENOMEM;
+ 
+-		uhci_add_td_to_urb(urb, td);
++		uhci_add_td_to_urbp(td, urbp);
+ 		uhci_fill_td(td, status, destination |
+ 				uhci_explen(urb->iso_frame_desc[i].length),
+ 				urb->transfer_dma +
+@@ -1267,17 +1248,6 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh,
+ 		uhci_make_qh_idle(uhci, qh);
+ }
+ 
+-static void uhci_free_pending_tds(struct uhci_hcd *uhci)
+-{
+-	struct uhci_td *td, *tmp;
+-
+-	list_for_each_entry_safe(td, tmp, &uhci->td_remove_list, remove_list) {
+-		list_del_init(&td->remove_list);
+-
+-		uhci_free_td(uhci, td);
+-	}
+-}
+-
+ /*
+  * Process events in the schedule, but only in one thread at a time
+  */
+@@ -1298,9 +1268,6 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs)
+ 	uhci_clear_next_interrupt(uhci);
+ 	uhci_get_current_frame_number(uhci);
+ 
+-	if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age)
+-		uhci_free_pending_tds(uhci);
+-
+ 	/* Go through all the QH queues and process the URBs in each one */
+ 	for (i = 0; i < UHCI_NUM_SKELQH - 1; ++i) {
+ 		uhci->next_qh = list_entry(uhci->skelqh[i]->node.next,
+@@ -1316,12 +1283,7 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs)
+ 		goto rescan;
+ 	uhci->scan_in_progress = 0;
+ 
+-	/* If the controller is stopped, we can finish these off right now */
+-	if (uhci->is_stopped)
+-		uhci_free_pending_tds(uhci);
+-
+-	if (list_empty(&uhci->td_remove_list) &&
+-			list_empty(&uhci->skel_unlink_qh->node))
++	if (list_empty(&uhci->skel_unlink_qh->node))
+ 		uhci_clear_next_interrupt(uhci);
+ 	else
+ 		uhci_set_next_interrupt(uhci);

commit a0b458b64b2a3a4cb806dd5cd889bbf6c7e9d686
+Author: Alan Stern 
+Date:   Fri May 12 11:23:19 2006 -0400
+
+    [PATCH] UHCI: Move code for cleaning up unlinked URBs
+    
+    This patch (as681) moves some code for cleaning up after unlinked URBs
+    out of the general completion pathway into the unlinking pathway.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 888938d78230..64b6c74789fd 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -204,25 +204,49 @@ static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ }
+ 
+ /*
+- * When the currently executing URB is dequeued, save its current toggle value
++ * When a queue is stopped and a dequeued URB is given back, adjust
++ * the previous TD link (if the URB isn't first on the queue) or
++ * save its toggle value (if it is first and is currently executing).
+  */
+-static void uhci_save_toggle(struct uhci_qh *qh, struct urb *urb)
++static void uhci_cleanup_queue(struct uhci_qh *qh,
++		struct urb *urb)
+ {
+-	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
++	struct urb_priv *urbp = urb->hcpriv;
+ 	struct uhci_td *td;
+ 
++	/* Isochronous pipes don't use toggles and their TD link pointers
++	 * get adjusted during uhci_urb_dequeue(). */
++	if (qh->type == USB_ENDPOINT_XFER_ISOC)
++		return;
++
++	/* If the URB isn't first on its queue, adjust the link pointer
++	 * of the last TD in the previous URB.  The toggle doesn't need
++	 * to be saved since this URB can't be executing yet. */
++	if (qh->queue.next != &urbp->node) {
++		struct urb_priv *purbp;
++		struct uhci_td *ptd;
++
++		purbp = list_entry(urbp->node.prev, struct urb_priv, node);
++		WARN_ON(list_empty(&purbp->td_list));
++		ptd = list_entry(purbp->td_list.prev, struct uhci_td,
++				list);
++		td = list_entry(urbp->td_list.prev, struct uhci_td,
++				list);
++		ptd->link = td->link;
++		return;
++	}
++
+ 	/* If the QH element pointer is UHCI_PTR_TERM then then currently
+ 	 * executing URB has already been unlinked, so this one isn't it. */
+-	if (qh_element(qh) == UHCI_PTR_TERM ||
+-				qh->queue.next != &urbp->node)
++	if (qh_element(qh) == UHCI_PTR_TERM)
+ 		return;
+ 	qh->element = UHCI_PTR_TERM;
+ 
+-	/* Only bulk and interrupt pipes have to worry about toggles */
+-	if (!(qh->type == USB_ENDPOINT_XFER_BULK ||
+-			qh->type == USB_ENDPOINT_XFER_INT))
++	/* Control pipes have to worry about toggles */
++	if (qh->type == USB_ENDPOINT_XFER_CONTROL)
+ 		return;
+ 
++	/* Save the next toggle value */
+ 	WARN_ON(list_empty(&urbp->td_list));
+ 	td = list_entry(urbp->td_list.next, struct uhci_td, list);
+ 	qh->needs_fixup = 1;
+@@ -1121,21 +1145,6 @@ __acquires(uhci->lock)
+ 	if (qh->type == USB_ENDPOINT_XFER_ISOC)
+ 		uhci_unlink_isochronous_tds(uhci, urb);
+ 
+-	/* If the URB isn't first on its queue, adjust the link pointer
+-	 * of the last TD in the previous URB. */
+-	else if (qh->queue.next != &urbp->node) {
+-		struct urb_priv *purbp;
+-		struct uhci_td *ptd, *ltd;
+-
+-		purbp = list_entry(urbp->node.prev, struct urb_priv, node);
+-		WARN_ON(list_empty(&purbp->td_list));
+-		ptd = list_entry(purbp->td_list.prev, struct uhci_td,
+-				list);
+-		ltd = list_entry(urbp->td_list.prev, struct uhci_td,
+-				list);
+-		ptd->link = ltd->link;
+-	}
+-
+ 	/* Take the URB off the QH's queue.  If the queue is now empty,
+ 	 * this is a perfect time for a toggle fixup. */
+ 	list_del_init(&urbp->node);
+@@ -1237,7 +1246,7 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh,
+ 	list_for_each_entry(urbp, &qh->queue, node) {
+ 		urb = urbp->urb;
+ 		if (urb->status != -EINPROGRESS) {
+-			uhci_save_toggle(qh, urb);
++			uhci_cleanup_queue(qh, urb);
+ 			uhci_giveback_urb(uhci, qh, urb, regs);
+ 			goto restart;
+ 		}

commit 59e29ed91cff90b27d393c7a3d3ac9c3fcaea7dd
+Author: Alan Stern 
+Date:   Fri May 12 11:19:19 2006 -0400
+
+    [PATCH] UHCI: Remove non-iso TDs as they are used
+    
+    This patch (as680) frees non-isochronous TDs as they are used, rather
+    than all at once when an URB is complete.  Although not a terribly
+    important change in itself, it opens the door to a later enhancement
+    that will reduce storage requirements by allocating only a limited
+    number of TDs at any time for each endpoint queue.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
+index 28c1c51ec475..6bbd33db9358 100644
+--- a/drivers/usb/host/uhci-debug.c
++++ b/drivers/usb/host/uhci-debug.c
+@@ -119,6 +119,7 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space)
+ 	}
+ 
+ 	out += sprintf(out, "%s%s", ptype, (urbp->fsbr ? " FSBR" : ""));
++	out += sprintf(out, " Actlen=%d", urbp->urb->actual_length);
+ 
+ 	if (urbp->urb->status != -EINPROGRESS)
+ 		out += sprintf(out, " Status=%d", urbp->urb->status);
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index 8e5778650493..3093ca250942 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -129,6 +129,7 @@ struct uhci_qh {
+ 	struct list_head queue;		/* Queue of urbps for this QH */
+ 	struct uhci_qh *skel;		/* Skeleton for this QH */
+ 	struct uhci_td *dummy_td;	/* Dummy TD to end the queue */
++	struct uhci_td *post_td;	/* Last TD completed */
+ 
+ 	unsigned int unlink_frame;	/* When the QH was unlinked */
+ 	int state;			/* QH_STATE_xxx; see above */
+@@ -136,7 +137,7 @@ struct uhci_qh {
+ 
+ 	unsigned int initial_toggle:1;	/* Endpoint's current toggle value */
+ 	unsigned int needs_fixup:1;	/* Must fix the TD toggle values */
+-	unsigned int is_stopped:1;	/* Queue was stopped by an error */
++	unsigned int is_stopped:1;	/* Queue was stopped by error/unlink */
+ } __attribute__((aligned(16)));
+ 
+ /*
+@@ -456,8 +457,6 @@ struct urb_priv {
+ 	struct list_head td_list;
+ 
+ 	unsigned fsbr : 1;		/* URB turned on FSBR */
+-	unsigned short_transfer : 1;	/* URB got a short transfer, no
+-					 * need to rescan */
+ };
+ 
+ 
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 30e36031fe21..888938d78230 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -161,6 +161,7 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci,
+ 	if (!qh)
+ 		return NULL;
+ 
++	memset(qh, 0, sizeof(*qh));
+ 	qh->dma_handle = dma_handle;
+ 
+ 	qh->element = UHCI_PTR_TERM;
+@@ -183,7 +184,6 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci,
+ 
+ 	} else {		/* Skeleton QH */
+ 		qh->state = QH_STATE_ACTIVE;
+-		qh->udev = NULL;
+ 		qh->type = -1;
+ 	}
+ 	return qh;
+@@ -223,16 +223,10 @@ static void uhci_save_toggle(struct uhci_qh *qh, struct urb *urb)
+ 			qh->type == USB_ENDPOINT_XFER_INT))
+ 		return;
+ 
+-	/* Find the first active TD; that's the device's toggle state */
+-	list_for_each_entry(td, &urbp->td_list, list) {
+-		if (td_status(td) & TD_CTRL_ACTIVE) {
+-			qh->needs_fixup = 1;
+-			qh->initial_toggle = uhci_toggle(td_token(td));
+-			return;
+-		}
+-	}
+-
+-	WARN_ON(1);
++	WARN_ON(list_empty(&urbp->td_list));
++	td = list_entry(urbp->td_list.next, struct uhci_td, list);
++	qh->needs_fixup = 1;
++	qh->initial_toggle = uhci_toggle(td_token(td));
+ }
+ 
+ /*
+@@ -372,6 +366,12 @@ static void uhci_make_qh_idle(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ 	list_move(&qh->node, &uhci->idle_qh_list);
+ 	qh->state = QH_STATE_IDLE;
+ 
++	/* Now that the QH is idle, its post_td isn't being used */
++	if (qh->post_td) {
++		uhci_free_td(uhci, qh->post_td);
++		qh->post_td = NULL;
++	}
++
+ 	/* If anyone is waiting for a QH to become idle, wake them up */
+ 	if (uhci->num_waiting)
+ 		wake_up_all(&uhci->waitqh);
+@@ -610,6 +610,8 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
+ 		qh->skel = uhci->skel_fs_control_qh;
+ 		uhci_inc_fsbr(uhci, urb);
+ 	}
++
++	urb->actual_length = -8;	/* Account for the SETUP packet */
+ 	return 0;
+ 
+ nomem:
+@@ -767,34 +769,46 @@ static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb,
+  * Fix up the data structures following a short transfer
+  */
+ static int uhci_fixup_short_transfer(struct uhci_hcd *uhci,
+-		struct uhci_qh *qh, struct urb_priv *urbp,
+-		struct uhci_td *short_td)
++		struct uhci_qh *qh, struct urb_priv *urbp)
+ {
+ 	struct uhci_td *td;
+-	int ret = 0;
++	struct list_head *tmp;
++	int ret;
+ 
+ 	td = list_entry(urbp->td_list.prev, struct uhci_td, list);
+ 	if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
+-		urbp->short_transfer = 1;
+ 
+ 		/* When a control transfer is short, we have to restart
+ 		 * the queue at the status stage transaction, which is
+ 		 * the last TD. */
++		WARN_ON(list_empty(&urbp->td_list));
+ 		qh->element = cpu_to_le32(td->dma_handle);
++		tmp = td->list.prev;
+ 		ret = -EINPROGRESS;
+ 
+-	} else if (!urbp->short_transfer) {
+-		urbp->short_transfer = 1;
++	} else {
+ 
+ 		/* When a bulk/interrupt transfer is short, we have to
+ 		 * fix up the toggles of the following URBs on the queue
+ 		 * before restarting the queue at the next URB. */
+-		qh->initial_toggle = uhci_toggle(td_token(short_td)) ^ 1;
++		qh->initial_toggle = uhci_toggle(td_token(qh->post_td)) ^ 1;
+ 		uhci_fixup_toggles(qh, 1);
+ 
++		if (list_empty(&urbp->td_list))
++			td = qh->post_td;
+ 		qh->element = td->link;
++		tmp = urbp->td_list.prev;
++		ret = 0;
+ 	}
+ 
++	/* Remove all the TDs we skipped over, from tmp back to the start */
++	while (tmp != &urbp->td_list) {
++		td = list_entry(tmp, struct uhci_td, list);
++		tmp = tmp->prev;
++
++		uhci_remove_td_from_urb(td);
++		list_add(&td->remove_list, &uhci->td_remove_list);
++	}
+ 	return ret;
+ }
+ 
+@@ -805,29 +819,14 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
+ {
+ 	struct urb_priv *urbp = urb->hcpriv;
+ 	struct uhci_qh *qh = urbp->qh;
+-	struct uhci_td *td;
+-	struct list_head *tmp;
++	struct uhci_td *td, *tmp;
+ 	unsigned status;
+ 	int ret = 0;
+ 
+-	tmp = urbp->td_list.next;
+-
+-	if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
+-		if (urbp->short_transfer)
+-			tmp = urbp->td_list.prev;
+-		else
+-			urb->actual_length = -8;	/* SETUP packet */
+-	} else
+-		urb->actual_length = 0;
+-
+-
+-	while (tmp != &urbp->td_list) {
++	list_for_each_entry_safe(td, tmp, &urbp->td_list, list) {
+ 		unsigned int ctrlstat;
+ 		int len;
+ 
+-		td = list_entry(tmp, struct uhci_td, list);
+-		tmp = tmp->next;
+-
+ 		ctrlstat = td_status(td);
+ 		status = uhci_status_bits(ctrlstat);
+ 		if (status & TD_CTRL_ACTIVE)
+@@ -862,6 +861,12 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
+ 				ret = 1;
+ 		}
+ 
++		uhci_remove_td_from_urb(td);
++		if (qh->post_td)
++			list_add(&qh->post_td->remove_list,
++					&uhci->td_remove_list);
++		qh->post_td = td;
++
+ 		if (ret != 0)
+ 			goto err;
+ 	}
+@@ -882,7 +887,7 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
+ 				(ret == -EREMOTEIO);
+ 
+ 	} else		/* Short packet received */
+-		ret = uhci_fixup_short_transfer(uhci, qh, urbp, td);
++		ret = uhci_fixup_short_transfer(uhci, qh, urbp);
+ 	return ret;
+ }
+ 
+@@ -1123,6 +1128,7 @@ __acquires(uhci->lock)
+ 		struct uhci_td *ptd, *ltd;
+ 
+ 		purbp = list_entry(urbp->node.prev, struct urb_priv, node);
++		WARN_ON(list_empty(&purbp->td_list));
+ 		ptd = list_entry(purbp->td_list.prev, struct uhci_td,
+ 				list);
+ 		ltd = list_entry(urbp->td_list.prev, struct uhci_td,

commit b1869000a60b0c72022811f24110a52d3e300b1e
+Author: Alan Stern 
+Date:   Fri May 12 11:14:25 2006 -0400
+
+    [PATCH] UHCI: Common result routine for Control/Bulk/Interrupt
+    
+    This patch (as679) combines the result routine for Control URBs with the
+    routine for Bulk/Interrupt URBs.  Along the way I eliminated the
+    debugging printouts for Control transfers unless the debugging level is
+    set higher than 1.  I also eliminated a long-unused (#ifdef'ed-out)
+    section that works around some buggy old APC BackUPS devices.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 693e92c1bd9e..30e36031fe21 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -618,134 +618,6 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
+ 	return -ENOMEM;
+ }
+ 
+-/*
+- * If control-IN transfer was short, the status packet wasn't sent.
+- * This routine changes the element pointer in the QH to point at the
+- * status TD.  It's safe to do this even while the QH is live, because
+- * the hardware only updates the element pointer following a successful
+- * transfer.  The inactive TD for the short packet won't cause an update,
+- * so the pointer won't get overwritten.  The next time the controller
+- * sees this QH, it will send the status packet.
+- */
+-static int usb_control_retrigger_status(struct uhci_hcd *uhci, struct urb *urb)
+-{
+-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+-	struct uhci_td *td;
+-
+-	urbp->short_transfer = 1;
+-
+-	td = list_entry(urbp->td_list.prev, struct uhci_td, list);
+-	urbp->qh->element = cpu_to_le32(td->dma_handle);
+-
+-	return -EINPROGRESS;
+-}
+-
+-
+-static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
+-{
+-	struct list_head *tmp, *head;
+-	struct urb_priv *urbp = urb->hcpriv;
+-	struct uhci_td *td;
+-	unsigned int status;
+-	int ret = 0;
+-
+-	head = &urbp->td_list;
+-	if (urbp->short_transfer) {
+-		tmp = head->prev;
+-		goto status_stage;
+-	}
+-
+-	urb->actual_length = 0;
+-
+-	tmp = head->next;
+-	td = list_entry(tmp, struct uhci_td, list);
+-
+-	/* The first TD is the SETUP stage, check the status, but skip */
+-	/*  the count */
+-	status = uhci_status_bits(td_status(td));
+-	if (status & TD_CTRL_ACTIVE)
+-		return -EINPROGRESS;
+-
+-	if (status)
+-		goto td_error;
+-
+-	/* The rest of the TDs (but the last) are data */
+-	tmp = tmp->next;
+-	while (tmp != head && tmp->next != head) {
+-		unsigned int ctrlstat;
+-
+-		td = list_entry(tmp, struct uhci_td, list);
+-		tmp = tmp->next;
+-
+-		ctrlstat = td_status(td);
+-		status = uhci_status_bits(ctrlstat);
+-		if (status & TD_CTRL_ACTIVE)
+-			return -EINPROGRESS;
+-
+-		urb->actual_length += uhci_actual_length(ctrlstat);
+-
+-		if (status)
+-			goto td_error;
+-
+-		/* Check to see if we received a short packet */
+-		if (uhci_actual_length(ctrlstat) <
+-				uhci_expected_length(td_token(td))) {
+-			if (urb->transfer_flags & URB_SHORT_NOT_OK) {
+-				ret = -EREMOTEIO;
+-				goto err;
+-			}
+-
+-			return usb_control_retrigger_status(uhci, urb);
+-		}
+-	}
+-
+-status_stage:
+-	td = list_entry(tmp, struct uhci_td, list);
+-
+-	/* Control status stage */
+-	status = td_status(td);
+-
+-#ifdef I_HAVE_BUGGY_APC_BACKUPS
+-	/* APC BackUPS Pro kludge */
+-	/* It tries to send all of the descriptor instead of the amount */
+-	/*  we requested */
+-	if (status & TD_CTRL_IOC &&	/* IOC is masked out by uhci_status_bits */
+-	    status & TD_CTRL_ACTIVE &&
+-	    status & TD_CTRL_NAK)
+-		return 0;
+-#endif
+-
+-	status = uhci_status_bits(status);
+-	if (status & TD_CTRL_ACTIVE)
+-		return -EINPROGRESS;
+-
+-	if (status)
+-		goto td_error;
+-
+-	return 0;
+-
+-td_error:
+-	ret = uhci_map_status(status, uhci_packetout(td_token(td)));
+-
+-err:
+-	if ((debug == 1 && ret != -EPIPE) || debug > 1) {
+-		/* Some debugging code */
+-		dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n",
+-				__FUNCTION__, status);
+-
+-		if (errbuf) {
+-			/* Print the chain for debugging purposes */
+-			uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
+-			lprintk(errbuf);
+-		}
+-	}
+-
+-	/* Note that the queue has stopped */
+-	urbp->qh->element = UHCI_PTR_TERM;
+-	urbp->qh->is_stopped = 1;
+-	return ret;
+-}
+-
+ /*
+  * Common submit for bulk and interrupt
+  */
+@@ -864,86 +736,6 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
+ 	return -ENOMEM;
+ }
+ 
+-/*
+- * Common result for bulk and interrupt
+- */
+-static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
+-{
+-	struct urb_priv *urbp = urb->hcpriv;
+-	struct uhci_td *td;
+-	unsigned int status = 0;
+-	int ret = 0;
+-
+-	urb->actual_length = 0;
+-
+-	list_for_each_entry(td, &urbp->td_list, list) {
+-		unsigned int ctrlstat = td_status(td);
+-
+-		status = uhci_status_bits(ctrlstat);
+-		if (status & TD_CTRL_ACTIVE)
+-			return -EINPROGRESS;
+-
+-		urb->actual_length += uhci_actual_length(ctrlstat);
+-
+-		if (status)
+-			goto td_error;
+-
+-		if (uhci_actual_length(ctrlstat) <
+-				uhci_expected_length(td_token(td))) {
+-			if (urb->transfer_flags & URB_SHORT_NOT_OK) {
+-				ret = -EREMOTEIO;
+-				goto err;
+-			}
+-
+-			/*
+-			 * This URB stopped short of its end.  We have to
+-			 * fix up the toggles of the following URBs on the
+-			 * queue and restart the queue.
+-			 *
+-			 * Do this only the first time we encounter the
+-			 * short URB.
+-			 */
+-			if (!urbp->short_transfer) {
+-				urbp->short_transfer = 1;
+-				urbp->qh->initial_toggle =
+-						uhci_toggle(td_token(td)) ^ 1;
+-				uhci_fixup_toggles(urbp->qh, 1);
+-
+-				td = list_entry(urbp->td_list.prev,
+-						struct uhci_td, list);
+-				urbp->qh->element = td->link;
+-			}
+-			break;
+-		}
+-	}
+-
+-	return 0;
+-
+-td_error:
+-	ret = uhci_map_status(status, uhci_packetout(td_token(td)));
+-
+-	if ((debug == 1 && ret != -EPIPE) || debug > 1) {
+-		/* Some debugging code */
+-		dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n",
+-				__FUNCTION__, status);
+-
+-		if (debug > 1 && errbuf) {
+-			/* Print the chain for debugging purposes */
+-			uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
+-			lprintk(errbuf);
+-		}
+-	}
+-err:
+-
+-	/* Note that the queue has stopped and save the next toggle value */
+-	urbp->qh->element = UHCI_PTR_TERM;
+-	urbp->qh->is_stopped = 1;
+-	urbp->qh->needs_fixup = 1;
+-	urbp->qh->initial_toggle = uhci_toggle(td_token(td)) ^
+-			(ret == -EREMOTEIO);
+-	return ret;
+-}
+-
+ static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb,
+ 		struct uhci_qh *qh)
+ {
+@@ -971,6 +763,129 @@ static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb,
+ 	return uhci_submit_common(uhci, urb, qh);
+ }
+ 
++/*
++ * Fix up the data structures following a short transfer
++ */
++static int uhci_fixup_short_transfer(struct uhci_hcd *uhci,
++		struct uhci_qh *qh, struct urb_priv *urbp,
++		struct uhci_td *short_td)
++{
++	struct uhci_td *td;
++	int ret = 0;
++
++	td = list_entry(urbp->td_list.prev, struct uhci_td, list);
++	if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
++		urbp->short_transfer = 1;
++
++		/* When a control transfer is short, we have to restart
++		 * the queue at the status stage transaction, which is
++		 * the last TD. */
++		qh->element = cpu_to_le32(td->dma_handle);
++		ret = -EINPROGRESS;
++
++	} else if (!urbp->short_transfer) {
++		urbp->short_transfer = 1;
++
++		/* When a bulk/interrupt transfer is short, we have to
++		 * fix up the toggles of the following URBs on the queue
++		 * before restarting the queue at the next URB. */
++		qh->initial_toggle = uhci_toggle(td_token(short_td)) ^ 1;
++		uhci_fixup_toggles(qh, 1);
++
++		qh->element = td->link;
++	}
++
++	return ret;
++}
++
++/*
++ * Common result for control, bulk, and interrupt
++ */
++static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
++{
++	struct urb_priv *urbp = urb->hcpriv;
++	struct uhci_qh *qh = urbp->qh;
++	struct uhci_td *td;
++	struct list_head *tmp;
++	unsigned status;
++	int ret = 0;
++
++	tmp = urbp->td_list.next;
++
++	if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
++		if (urbp->short_transfer)
++			tmp = urbp->td_list.prev;
++		else
++			urb->actual_length = -8;	/* SETUP packet */
++	} else
++		urb->actual_length = 0;
++
++
++	while (tmp != &urbp->td_list) {
++		unsigned int ctrlstat;
++		int len;
++
++		td = list_entry(tmp, struct uhci_td, list);
++		tmp = tmp->next;
++
++		ctrlstat = td_status(td);
++		status = uhci_status_bits(ctrlstat);
++		if (status & TD_CTRL_ACTIVE)
++			return -EINPROGRESS;
++
++		len = uhci_actual_length(ctrlstat);
++		urb->actual_length += len;
++
++		if (status) {
++			ret = uhci_map_status(status,
++					uhci_packetout(td_token(td)));
++			if ((debug == 1 && ret != -EPIPE) || debug > 1) {
++				/* Some debugging code */
++				dev_dbg(uhci_dev(uhci),
++						"%s: failed with status %x\n",
++						__FUNCTION__, status);
++
++				if (debug > 1 && errbuf) {
++					/* Print the chain for debugging */
++					uhci_show_qh(urbp->qh, errbuf,
++							ERRBUF_LEN, 0);
++					lprintk(errbuf);
++				}
++			}
++
++		} else if (len < uhci_expected_length(td_token(td))) {
++
++			/* We received a short packet */
++			if (urb->transfer_flags & URB_SHORT_NOT_OK)
++				ret = -EREMOTEIO;
++			else if (ctrlstat & TD_CTRL_SPD)
++				ret = 1;
++		}
++
++		if (ret != 0)
++			goto err;
++	}
++	return ret;
++
++err:
++	if (ret < 0) {
++		/* In case a control transfer gets an error
++		 * during the setup stage */
++		urb->actual_length = max(urb->actual_length, 0);
++
++		/* Note that the queue has stopped and save
++		 * the next toggle value */
++		qh->element = UHCI_PTR_TERM;
++		qh->is_stopped = 1;
++		qh->needs_fixup = (qh->type != USB_ENDPOINT_XFER_CONTROL);
++		qh->initial_toggle = uhci_toggle(td_token(td)) ^
++				(ret == -EREMOTEIO);
++
++	} else		/* Short packet received */
++		ret = uhci_fixup_short_transfer(uhci, qh, urbp, td);
++	return ret;
++}
++
+ /*
+  * Isochronous transfers
+  */
+@@ -1276,17 +1191,10 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh,
+ 		urbp = list_entry(qh->queue.next, struct urb_priv, node);
+ 		urb = urbp->urb;
+ 
+-		switch (qh->type) {
+-		case USB_ENDPOINT_XFER_CONTROL:
+-			status = uhci_result_control(uhci, urb);
+-			break;
+-		case USB_ENDPOINT_XFER_ISOC:
++		if (qh->type == USB_ENDPOINT_XFER_ISOC)
+ 			status = uhci_result_isochronous(uhci, urb);
+-			break;
+-		default:	/* USB_ENDPOINT_XFER_BULK or _INT */
++		else
+ 			status = uhci_result_common(uhci, urb);
+-			break;
+-		}
+ 		if (status == -EINPROGRESS)
+ 			break;
+ 

commit 0f28b55db543001d360e4319bfc3f2c4e28ba05f
+Author: Alan Stern 
+Date:   Mon May 15 14:49:04 2006 -0400
+
+    [PATCH] usbhid: automatically set HID_QUIRK_NOGET for keyboards and mice
+    
+    It seems to be relatively common for USB keyboards and mice to dislike
+    being polled for reports.  Since there's no need to poll a keyboard or
+    a mouse, this patch (as685) automatically sets the HID_QUIRK_NOGET flag
+    for devices that advertise themselves as either sort of device with boot
+    protocol support.
+    
+    This won't cure all the problems since some devices don't support the
+    boot protocol, but it's simple and easy and it should fix quite a few
+    problems.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
+index bb1f5211ff9d..061002fc66fc 100644
+--- a/drivers/usb/input/hid-core.c
++++ b/drivers/usb/input/hid-core.c
+@@ -1797,6 +1797,14 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
+ 			(hid_blacklist[n].idProduct == le16_to_cpu(dev->descriptor.idProduct)))
+ 				quirks = hid_blacklist[n].quirks;
+ 
++	/* Many keyboards and mice don't like to be polled for reports,
++	 * so we will always set the HID_QUIRK_NOGET flag for them. */
++	if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT) {
++		if (interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_KEYBOARD ||
++			interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE)
++				quirks |= HID_QUIRK_NOGET;
++	}
++
+ 	if (quirks & HID_QUIRK_IGNORE)
+ 		return NULL;
+ 
+diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
+index 7efbfff8adde..778e575de352 100644
+--- a/drivers/usb/input/hid.h
++++ b/drivers/usb/input/hid.h
+@@ -40,6 +40,14 @@
+ 
+ #define USB_INTERFACE_CLASS_HID		3
+ 
++/*
++ * USB HID interface subclass and protocol codes
++ */
++
++#define USB_INTERFACE_SUBCLASS_BOOT	1
++#define USB_INTERFACE_PROTOCOL_KEYBOARD	1
++#define USB_INTERFACE_PROTOCOL_MOUSE	2
++
+ /*
+  * HID class requests
+  */

commit 2775562ad2af2fc131ef7987166db6e42217528f
+Author: Alan Stern 
+Date:   Fri May 5 16:32:02 2006 -0400
+
+    [PATCH] USB: UHCI: fix obscure bug in enqueue()
+    
+    This patch (as676) fixes a small bug in uhci-hcd's enqueue routine.  When
+    an URB is unlinked or gets an error and the completion handler queues
+    another URB for the same endpoint, the queue shouldn't be allowed to start
+    up again until the handler returns.  Not even if the new URB is the only
+    one on its queue.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 8639e9035931..693e92c1bd9e 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -1148,8 +1148,9 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd,
+ 
+ 	/* If the new URB is the first and only one on this QH then either
+ 	 * the QH is new and idle or else it's unlinked and waiting to
+-	 * become idle, so we can activate it right away. */
+-	if (qh->queue.next == &urbp->node)
++	 * become idle, so we can activate it right away.  But only if the
++	 * queue isn't stopped. */
++	if (qh->queue.next == &urbp->node && !qh->is_stopped)
+ 		uhci_activate_qh(uhci, qh);
+ 	goto done;
+ 
+@@ -1293,27 +1294,32 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh,
+ 		if (urb->status == -EINPROGRESS)	/* Not dequeued */
+ 			urb->status = status;
+ 		else
+-			status = -ECONNRESET;
++			status = ECONNRESET;		/* Not -ECONNRESET */
+ 		spin_unlock(&urb->lock);
+ 
+ 		/* Dequeued but completed URBs can't be given back unless
+ 		 * the QH is stopped or has finished unlinking. */
+-		if (status == -ECONNRESET &&
+-				!(qh->is_stopped || QH_FINISHED_UNLINKING(qh)))
+-			return;
++		if (status == ECONNRESET) {
++			if (QH_FINISHED_UNLINKING(qh))
++				qh->is_stopped = 1;
++			else if (!qh->is_stopped)
++				return;
++		}
+ 
+ 		uhci_giveback_urb(uhci, qh, urb, regs);
+-		if (qh->is_stopped)
++		if (status < 0)
+ 			break;
+ 	}
+ 
+ 	/* If the QH is neither stopped nor finished unlinking (normal case),
+ 	 * our work here is done. */
+- restart:
+-	if (!(qh->is_stopped || QH_FINISHED_UNLINKING(qh)))
++	if (QH_FINISHED_UNLINKING(qh))
++		qh->is_stopped = 1;
++	else if (!qh->is_stopped)
+ 		return;
+ 
+ 	/* Otherwise give back each of the dequeued URBs */
++restart:
+ 	list_for_each_entry(urbp, &qh->queue, node) {
+ 		urb = urbp->urb;
+ 		if (urb->status != -EINPROGRESS) {

commit 4de7d2c231a8624a47417977be0768c5b5257c4f
+Author: Alan Stern 
+Date:   Fri May 5 16:26:58 2006 -0400
+
+    [PATCH] USB: UHCI: store the endpoint type in the QH structure
+    
+    This patch (as675) simplifies uhci-hcd slightly by storing each endpoint's
+    type in the corresponding Queue Header structure.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
+index e1239319655c..28c1c51ec475 100644
+--- a/drivers/usb/host/uhci-debug.c
++++ b/drivers/usb/host/uhci-debug.c
+@@ -98,6 +98,7 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space)
+ 	char *out = buf;
+ 	struct uhci_td *td;
+ 	int i, nactive, ninactive;
++	char *ptype;
+ 
+ 	if (len < 200)
+ 		return 0;
+@@ -110,13 +111,14 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space)
+ 			(usb_pipein(urbp->urb->pipe) ? "IN" : "OUT"));
+ 
+ 	switch (usb_pipetype(urbp->urb->pipe)) {
+-	case PIPE_ISOCHRONOUS: out += sprintf(out, "ISO"); break;
+-	case PIPE_INTERRUPT: out += sprintf(out, "INT"); break;
+-	case PIPE_BULK: out += sprintf(out, "BLK"); break;
+-	case PIPE_CONTROL: out += sprintf(out, "CTL"); break;
++	case PIPE_ISOCHRONOUS: ptype = "ISO"; break;
++	case PIPE_INTERRUPT: ptype = "INT"; break;
++	case PIPE_BULK: ptype = "BLK"; break;
++	default:
++	case PIPE_CONTROL: ptype = "CTL"; break;
+ 	}
+ 
+-	out += sprintf(out, "%s", (urbp->fsbr ? " FSBR" : ""));
++	out += sprintf(out, "%s%s", ptype, (urbp->fsbr ? " FSBR" : ""));
+ 
+ 	if (urbp->urb->status != -EINPROGRESS)
+ 		out += sprintf(out, " Status=%d", urbp->urb->status);
+@@ -147,13 +149,23 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
+ 	char *out = buf;
+ 	int i, nurbs;
+ 	__le32 element = qh_element(qh);
++	char *qtype;
+ 
+ 	/* Try to make sure there's enough memory */
+ 	if (len < 80 * 6)
+ 		return 0;
+ 
+-	out += sprintf(out, "%*s[%p] link (%08x) element (%08x)\n", space, "",
+-			qh, le32_to_cpu(qh->link), le32_to_cpu(element));
++	switch (qh->type) {
++	case USB_ENDPOINT_XFER_ISOC: qtype = "ISO"; break;
++	case USB_ENDPOINT_XFER_INT: qtype = "INT"; break;
++	case USB_ENDPOINT_XFER_BULK: qtype = "BLK"; break;
++	case USB_ENDPOINT_XFER_CONTROL: qtype = "CTL"; break;
++	default: qtype = "Skel" ; break;
++	}
++
++	out += sprintf(out, "%*s[%p] %s QH link (%08x) element (%08x)\n",
++			space, "", qh, qtype,
++			le32_to_cpu(qh->link), le32_to_cpu(element));
+ 
+ 	if (element & UHCI_PTR_QH)
+ 		out += sprintf(out, "%*s  Element points to QH (bug?)\n", space, "");
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index d5c8f4d92823..8e5778650493 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -132,6 +132,7 @@ struct uhci_qh {
+ 
+ 	unsigned int unlink_frame;	/* When the QH was unlinked */
+ 	int state;			/* QH_STATE_xxx; see above */
++	int type;			/* Queue type (control, bulk, etc) */
+ 
+ 	unsigned int initial_toggle:1;	/* Endpoint's current toggle value */
+ 	unsigned int needs_fixup:1;	/* Must fix the TD toggle values */
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index a06d84c19e13..8639e9035931 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -179,10 +179,12 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci,
+ 		qh->hep = hep;
+ 		qh->udev = udev;
+ 		hep->hcpriv = qh;
++		qh->type = hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+ 
+ 	} else {		/* Skeleton QH */
+ 		qh->state = QH_STATE_ACTIVE;
+ 		qh->udev = NULL;
++		qh->type = -1;
+ 	}
+ 	return qh;
+ }
+@@ -217,8 +219,8 @@ static void uhci_save_toggle(struct uhci_qh *qh, struct urb *urb)
+ 	qh->element = UHCI_PTR_TERM;
+ 
+ 	/* Only bulk and interrupt pipes have to worry about toggles */
+-	if (!(usb_pipetype(urb->pipe) == PIPE_BULK ||
+-			usb_pipetype(urb->pipe) == PIPE_INTERRUPT))
++	if (!(qh->type == USB_ENDPOINT_XFER_BULK ||
++			qh->type == USB_ENDPOINT_XFER_INT))
+ 		return;
+ 
+ 	/* Find the first active TD; that's the device's toggle state */
+@@ -1099,14 +1101,14 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd,
+ 	}
+ 	urbp->qh = qh;
+ 
+-	switch (usb_pipetype(urb->pipe)) {
+-	case PIPE_CONTROL:
++	switch (qh->type) {
++	case USB_ENDPOINT_XFER_CONTROL:
+ 		ret = uhci_submit_control(uhci, urb, qh);
+ 		break;
+-	case PIPE_BULK:
++	case USB_ENDPOINT_XFER_BULK:
+ 		ret = uhci_submit_bulk(uhci, urb, qh);
+ 		break;
+-	case PIPE_INTERRUPT:
++	case USB_ENDPOINT_XFER_INT:
+ 		if (list_empty(&qh->queue)) {
+ 			bustime = usb_check_bandwidth(urb->dev, urb);
+ 			if (bustime < 0)
+@@ -1125,7 +1127,7 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd,
+ 			ret = uhci_submit_interrupt(uhci, urb, qh);
+ 		}
+ 		break;
+-	case PIPE_ISOCHRONOUS:
++	case USB_ENDPOINT_XFER_ISOC:
+ 		bustime = usb_check_bandwidth(urb->dev, urb);
+ 		if (bustime < 0) {
+ 			ret = bustime;
+@@ -1175,7 +1177,7 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
+ 		goto done;
+ 
+ 	/* Remove Isochronous TDs from the frame list ASAP */
+-	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
++	if (urbp->qh->type == USB_ENDPOINT_XFER_ISOC)
+ 		uhci_unlink_isochronous_tds(uhci, urb);
+ 	uhci_unlink_qh(uhci, urbp->qh);
+ 
+@@ -1195,7 +1197,7 @@ __acquires(uhci->lock)
+ 	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
+ 
+ 	/* Isochronous TDs get unlinked directly from the frame list */
+-	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
++	if (qh->type == USB_ENDPOINT_XFER_ISOC)
+ 		uhci_unlink_isochronous_tds(uhci, urb);
+ 
+ 	/* If the URB isn't first on its queue, adjust the link pointer
+@@ -1224,13 +1226,13 @@ __acquires(uhci->lock)
+ 	uhci_dec_fsbr(uhci, urb);	/* Safe since it checks */
+ 	uhci_free_urb_priv(uhci, urbp);
+ 
+-	switch (usb_pipetype(urb->pipe)) {
+-	case PIPE_ISOCHRONOUS:
++	switch (qh->type) {
++	case USB_ENDPOINT_XFER_ISOC:
+ 		/* Release bandwidth for Interrupt or Isoc. transfers */
+ 		if (urb->bandwidth)
+ 			usb_release_bandwidth(urb->dev, urb, 1);
+ 		break;
+-	case PIPE_INTERRUPT:
++	case USB_ENDPOINT_XFER_INT:
+ 		/* Release bandwidth for Interrupt or Isoc. transfers */
+ 		/* Make sure we don't release if we have a queued URB */
+ 		if (list_empty(&qh->queue) && urb->bandwidth)
+@@ -1273,14 +1275,14 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh,
+ 		urbp = list_entry(qh->queue.next, struct urb_priv, node);
+ 		urb = urbp->urb;
+ 
+-		switch (usb_pipetype(urb->pipe)) {
+-		case PIPE_CONTROL:
++		switch (qh->type) {
++		case USB_ENDPOINT_XFER_CONTROL:
+ 			status = uhci_result_control(uhci, urb);
+ 			break;
+-		case PIPE_ISOCHRONOUS:
++		case USB_ENDPOINT_XFER_ISOC:
+ 			status = uhci_result_isochronous(uhci, urb);
+ 			break;
+-		default:	/* PIPE_BULK or PIPE_INTERRUPT */
++		default:	/* USB_ENDPOINT_XFER_BULK or _INT */
+ 			status = uhci_result_common(uhci, urb);
+ 			break;
+ 		}

commit 2d61bde7a0e630e1906e6478b6b2a7aeaaa8f8da
+Author: Alan Stern 
+Date:   Fri May 5 16:23:42 2006 -0400
+
+    [PATCH] USB: net2280: add a shutdown routine
+    
+    The net2280 board has an annoying habit of surviving soft reboots with
+    interrupts enabled.  This patch (as674) adds a shutdown routine to the
+    driver so that the board can be put in a quiescent state.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
+index 020d3c42b1af..1facdea56a8a 100644
+--- a/drivers/usb/gadget/net2280.c
++++ b/drivers/usb/gadget/net2280.c
+@@ -2966,6 +2966,22 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
+ 	return retval;
+ }
+ 
++/* make sure the board is quiescent; otherwise it will continue
++ * generating IRQs across the upcoming reboot.
++ */
++
++static void net2280_shutdown (struct pci_dev *pdev)
++{
++	struct net2280		*dev = pci_get_drvdata (pdev);
++
++	/* disable IRQs */
++	writel (0, &dev->regs->pciirqenb0);
++	writel (0, &dev->regs->pciirqenb1);
++
++	/* disable the pullup so the host will think we're gone */
++	writel (0, &dev->usb->usbctl);
++}
++
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+@@ -2995,6 +3011,7 @@ static struct pci_driver net2280_pci_driver = {
+ 
+ 	.probe =	net2280_probe,
+ 	.remove =	net2280_remove,
++	.shutdown =	net2280_shutdown,
+ 
+ 	/* FIXME add power management support */
+ };

commit 4489a5712b086621a6c3f669057d2996245cd3fb
+Author: Alan Stern 
+Date:   Thu Apr 27 15:54:22 2006 -0400
+
+    [PATCH] USB: usbcore: always turn on hub port power
+    
+    Some hubs claim not to support port-power switching, and right now the
+    hub driver believes them and does not enable power to their ports.
+    However it turns out that even though they don't actually switch power,
+    they do ignore all events on a port until told to turn on the power!
+    This problem has been reported by several users.
+    
+    This revised patch (as672b) makes the hub driver always try to turn on
+    port power to all hubs, regardless of what the hub descriptor says.  It
+    also adds a comment explaining the need for this.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 90b8d43c6b33..1b1846e6473b 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -432,15 +432,22 @@ static void hub_power_on(struct usb_hub *hub)
+ {
+ 	int port1;
+ 	unsigned pgood_delay = hub->descriptor->bPwrOn2PwrGood * 2;
+-	u16 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
+-
+-	/* if hub supports power switching, enable power on each port */
+-	if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2) {
++	u16 wHubCharacteristics =
++			le16_to_cpu(hub->descriptor->wHubCharacteristics);
++
++	/* Enable power on each port.  Some hubs have reserved values
++	 * of LPSM (> 2) in their descriptors, even though they are
++	 * USB 2.0 hubs.  Some hubs do not implement port-power switching
++	 * but only emulate it.  In all cases, the ports won't work
++	 * unless we send these messages to the hub.
++	 */
++	if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2)
+ 		dev_dbg(hub->intfdev, "enabling power on all ports\n");
+-		for (port1 = 1; port1 <= hub->descriptor->bNbrPorts; port1++)
+-			set_port_feature(hub->hdev, port1,
+-					USB_PORT_FEAT_POWER);
+-	}
++	else
++		dev_dbg(hub->intfdev, "trying to enable port power on "
++				"non-switchable hub\n");
++	for (port1 = 1; port1 <= hub->descriptor->bNbrPorts; port1++)
++		set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER);
+ 
+ 	/* Wait at least 100 msec for power to become stable */
+ 	msleep(max(pgood_delay, (unsigned) 100));

commit 3e95637a48820ff8bedb33e6439def96ccff1de5
+Author: Alan Stern 
+Date:   Fri Jun 16 17:10:48 2006 -0400
+
+    [PATCH] Driver Core: Make dev_info and friends print the bus name if there is no driver
+    
+    This patch (as721) makes dev_info and related macros print the device's
+    bus name if the device doesn't have a driver, instead of printing just a
+    blank.  If the device isn't on a bus either... well, then it does leave
+    a blank space.  But it will be easier for someone else to change if they
+    want.
+    
+    Cc: Matthew Wilcox 
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/base/core.c b/drivers/base/core.c
+index a979bc3f49a9..d0f84ff78776 100644
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -29,6 +29,22 @@ int (*platform_notify_remove)(struct device * dev) = NULL;
+  * sysfs bindings for devices.
+  */
+ 
++/**
++ * dev_driver_string - Return a device's driver name, if at all possible
++ * @dev: struct device to get the name of
++ *
++ * Will return the device's driver's name if it is bound to a device.  If
++ * the device is not bound to a device, it will return the name of the bus
++ * it is attached to.  If it is not attached to a bus either, an empty
++ * string will be returned.
++ */
++const char *dev_driver_string(struct device *dev)
++{
++	return dev->driver ? dev->driver->name :
++			(dev->bus ? dev->bus->name : "");
++}
++EXPORT_SYMBOL_GPL(dev_driver_string);
++
+ #define to_dev(obj) container_of(obj, struct device, kobj)
+ #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
+ 
+diff --git a/include/linux/device.h b/include/linux/device.h
+index b473f4278910..1e5f30da98bc 100644
+--- a/include/linux/device.h
++++ b/include/linux/device.h
+@@ -416,8 +416,9 @@ extern int firmware_register(struct subsystem *);
+ extern void firmware_unregister(struct subsystem *);
+ 
+ /* debugging and troubleshooting/diagnostic helpers. */
++extern const char *dev_driver_string(struct device *dev);
+ #define dev_printk(level, dev, format, arg...)	\
+-	printk(level "%s %s: " format , (dev)->driver ? (dev)->driver->name : "" , (dev)->bus_id , ## arg)
++	printk(level "%s %s: " format , dev_driver_string(dev) , (dev)->bus_id , ## arg)
+ 
+ #ifdef DEBUG
+ #define dev_dbg(dev, format, arg...)		\

commit f07d5b946510a54937a75a3654941e855ffdc4c2
+Author: Alan Stern 
+Date:   Tue May 9 15:23:03 2006 -0700
+
+    [NET]: Make netdev_chain a raw notifier.
+    
+    From: Alan Stern 
+    
+    This chain does it's own locking via the RTNL semaphore, and
+    can also run recursively so adding a new mutex here was causing
+    deadlocks.
+    
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/core/dev.c b/net/core/dev.c
+index 9ab3cfa58466..ced57430f6d8 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -193,7 +193,7 @@ static inline struct hlist_head *dev_index_hash(int ifindex)
+  *	Our notifier list
+  */
+ 
+-static BLOCKING_NOTIFIER_HEAD(netdev_chain);
++static RAW_NOTIFIER_HEAD(netdev_chain);
+ 
+ /*
+  *	Device drivers call our routines to queue packets here. We empty the
+@@ -736,7 +736,7 @@ int dev_change_name(struct net_device *dev, char *newname)
+ 	if (!err) {
+ 		hlist_del(&dev->name_hlist);
+ 		hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name));
+-		blocking_notifier_call_chain(&netdev_chain,
++		raw_notifier_call_chain(&netdev_chain,
+ 				NETDEV_CHANGENAME, dev);
+ 	}
+ 
+@@ -751,7 +751,7 @@ int dev_change_name(struct net_device *dev, char *newname)
+  */
+ void netdev_features_change(struct net_device *dev)
+ {
+-	blocking_notifier_call_chain(&netdev_chain, NETDEV_FEAT_CHANGE, dev);
++	raw_notifier_call_chain(&netdev_chain, NETDEV_FEAT_CHANGE, dev);
+ }
+ EXPORT_SYMBOL(netdev_features_change);
+ 
+@@ -766,7 +766,7 @@ EXPORT_SYMBOL(netdev_features_change);
+ void netdev_state_change(struct net_device *dev)
+ {
+ 	if (dev->flags & IFF_UP) {
+-		blocking_notifier_call_chain(&netdev_chain,
++		raw_notifier_call_chain(&netdev_chain,
+ 				NETDEV_CHANGE, dev);
+ 		rtmsg_ifinfo(RTM_NEWLINK, dev, 0);
+ 	}
+@@ -864,7 +864,7 @@ int dev_open(struct net_device *dev)
+ 		/*
+ 		 *	... and announce new interface.
+ 		 */
+-		blocking_notifier_call_chain(&netdev_chain, NETDEV_UP, dev);
++		raw_notifier_call_chain(&netdev_chain, NETDEV_UP, dev);
+ 	}
+ 	return ret;
+ }
+@@ -887,7 +887,7 @@ int dev_close(struct net_device *dev)
+ 	 *	Tell people we are going down, so that they can
+ 	 *	prepare to death, when device is still operating.
+ 	 */
+-	blocking_notifier_call_chain(&netdev_chain, NETDEV_GOING_DOWN, dev);
++	raw_notifier_call_chain(&netdev_chain, NETDEV_GOING_DOWN, dev);
+ 
+ 	dev_deactivate(dev);
+ 
+@@ -924,7 +924,7 @@ int dev_close(struct net_device *dev)
+ 	/*
+ 	 * Tell people we are down
+ 	 */
+-	blocking_notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev);
++	raw_notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev);
+ 
+ 	return 0;
+ }
+@@ -955,7 +955,7 @@ int register_netdevice_notifier(struct notifier_block *nb)
+ 	int err;
+ 
+ 	rtnl_lock();
+-	err = blocking_notifier_chain_register(&netdev_chain, nb);
++	err = raw_notifier_chain_register(&netdev_chain, nb);
+ 	if (!err) {
+ 		for (dev = dev_base; dev; dev = dev->next) {
+ 			nb->notifier_call(nb, NETDEV_REGISTER, dev);
+@@ -983,7 +983,7 @@ int unregister_netdevice_notifier(struct notifier_block *nb)
+ 	int err;
+ 
+ 	rtnl_lock();
+-	err = blocking_notifier_chain_unregister(&netdev_chain, nb);
++	err = raw_notifier_chain_unregister(&netdev_chain, nb);
+ 	rtnl_unlock();
+ 	return err;
+ }
+@@ -994,12 +994,12 @@ int unregister_netdevice_notifier(struct notifier_block *nb)
+  *      @v:   pointer passed unmodified to notifier function
+  *
+  *	Call all network notifier blocks.  Parameters and return value
+- *	are as for blocking_notifier_call_chain().
++ *	are as for raw_notifier_call_chain().
+  */
+ 
+ int call_netdevice_notifiers(unsigned long val, void *v)
+ {
+-	return blocking_notifier_call_chain(&netdev_chain, val, v);
++	return raw_notifier_call_chain(&netdev_chain, val, v);
+ }
+ 
+ /* When > 0 there are consumers of rx skb time stamps */
+@@ -2308,7 +2308,7 @@ int dev_change_flags(struct net_device *dev, unsigned flags)
+ 	if (dev->flags & IFF_UP &&
+ 	    ((old_flags ^ dev->flags) &~ (IFF_UP | IFF_PROMISC | IFF_ALLMULTI |
+ 					  IFF_VOLATILE)))
+-		blocking_notifier_call_chain(&netdev_chain,
++		raw_notifier_call_chain(&netdev_chain,
+ 				NETDEV_CHANGE, dev);
+ 
+ 	if ((flags ^ dev->gflags) & IFF_PROMISC) {
+@@ -2353,7 +2353,7 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
+ 	else
+ 		dev->mtu = new_mtu;
+ 	if (!err && dev->flags & IFF_UP)
+-		blocking_notifier_call_chain(&netdev_chain,
++		raw_notifier_call_chain(&netdev_chain,
+ 				NETDEV_CHANGEMTU, dev);
+ 	return err;
+ }
+@@ -2370,7 +2370,7 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa)
+ 		return -ENODEV;
+ 	err = dev->set_mac_address(dev, sa);
+ 	if (!err)
+-		blocking_notifier_call_chain(&netdev_chain,
++		raw_notifier_call_chain(&netdev_chain,
+ 				NETDEV_CHANGEADDR, dev);
+ 	return err;
+ }
+@@ -2427,7 +2427,7 @@ static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
+ 				return -EINVAL;
+ 			memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data,
+ 			       min(sizeof ifr->ifr_hwaddr.sa_data, (size_t) dev->addr_len));
+-			blocking_notifier_call_chain(&netdev_chain,
++			raw_notifier_call_chain(&netdev_chain,
+ 					    NETDEV_CHANGEADDR, dev);
+ 			return 0;
+ 
+@@ -2882,7 +2882,7 @@ int register_netdevice(struct net_device *dev)
+ 	write_unlock_bh(&dev_base_lock);
+ 
+ 	/* Notify protocols, that a new device appeared. */
+-	blocking_notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
++	raw_notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
+ 
+ 	/* Finish registration after unlock */
+ 	net_set_todo(dev);
+@@ -2961,7 +2961,7 @@ static void netdev_wait_allrefs(struct net_device *dev)
+ 			rtnl_lock();
+ 
+ 			/* Rebroadcast unregister notification */
+-			blocking_notifier_call_chain(&netdev_chain,
++			raw_notifier_call_chain(&netdev_chain,
+ 					    NETDEV_UNREGISTER, dev);
+ 
+ 			if (test_bit(__LINK_STATE_LINKWATCH_PENDING,
+@@ -3216,7 +3216,7 @@ int unregister_netdevice(struct net_device *dev)
+ 	/* Notify protocols, that we are about to destroy
+ 	   this device. They should clean all the things.
+ 	*/
+-	blocking_notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
++	raw_notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
+ 	
+ 	/*
+ 	 *	Flush the multicast chain

commit 436f5762bcd4929825a0725d4bc78337e6fc0d8f
+Author: Alan Stern 
+Date:   Tue May 2 15:22:41 2006 -0400
+
+    [PATCH] USB: usbcore: don't check the device's power source
+    
+    The choose_configuration() routine contains code the determine the
+    device's power source, so that configurations requiring external power
+    can be ruled out if the device is running on bus power.  Unfortunately
+    it turns out that some devices have errors in their config descriptors
+    and other devices don't like the GET_DEVICE_STATUS request.
+    
+    Since that information wasn't used for anything else, this patch (as673)
+    removes the code, leaving only a comment.  It fixes bugzilla entry
+    #6448.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 0c87f73f2933..90b8d43c6b33 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1168,19 +1168,9 @@ static inline const char *plural(int n)
+ static int choose_configuration(struct usb_device *udev)
+ {
+ 	int i;
+-	u16 devstatus;
+-	int bus_powered;
+ 	int num_configs;
+ 	struct usb_host_config *c, *best;
+ 
+-	/* If this fails, assume the device is bus-powered */
+-	devstatus = 0;
+-	usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
+-	le16_to_cpus(&devstatus);
+-	bus_powered = ((devstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0);
+-	dev_dbg(&udev->dev, "device is %s-powered\n",
+-			bus_powered ? "bus" : "self");
+-
+ 	best = NULL;
+ 	c = udev->config;
+ 	num_configs = udev->descriptor.bNumConfigurations;
+@@ -1197,6 +1187,19 @@ static int choose_configuration(struct usb_device *udev)
+ 		 * similar errors in their descriptors.  If the next test
+ 		 * were allowed to execute, such configurations would always
+ 		 * be rejected and the devices would not work as expected.
++		 * In the meantime, we run the risk of selecting a config
++		 * that requires external power at a time when that power
++		 * isn't available.  It seems to be the lesser of two evils.
++		 *
++		 * Bugzilla #6448 reports a device that appears to crash
++		 * when it receives a GET_DEVICE_STATUS request!  We don't
++		 * have any other way to tell whether a device is self-powered,
++		 * but since we don't use that information anywhere but here,
++		 * the call has been removed.
++		 *
++		 * Maybe the GET_DEVICE_STATUS call and the test below can
++		 * be reinstated when device firmwares become more reliable.
++		 * Don't hold your breath.
+ 		 */
+ #if 0
+ 		/* Rule out self-powered configs for a bus-powered device */

commit 9fb81ce63671f9743517f628dac935269f2581a9
+Author: Alan Stern 
+Date:   Fri Apr 14 16:46:28 2006 -0400
+
+    [PATCH] USB: net2280: set driver data before it is used
+    
+    This patch (as671) fixes a bug in the error pathway for the net2280
+    probe routine.  A failure during probe will cause the driver to call
+    pci_get_drvdata before the corresponding pci_set_drvdata has been set.
+    The patch also does a kzalloc conversion.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
+index b2d507f16b85..0b9293493957 100644
+--- a/drivers/usb/gadget/net2280.c
++++ b/drivers/usb/gadget/net2280.c
+@@ -2833,13 +2833,13 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
+ 	}
+ 
+ 	/* alloc, and start init */
+-	dev = kmalloc (sizeof *dev, SLAB_KERNEL);
++	dev = kzalloc (sizeof *dev, SLAB_KERNEL);
+ 	if (dev == NULL){
+ 		retval = -ENOMEM;
+ 		goto done;
+ 	}
+ 
+-	memset (dev, 0, sizeof *dev);
++	pci_set_drvdata (pdev, dev);
+ 	spin_lock_init (&dev->lock);
+ 	dev->pdev = pdev;
+ 	dev->gadget.ops = &net2280_ops;
+@@ -2952,7 +2952,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
+ 	dev->chiprev = get_idx_reg (dev->regs, REG_CHIPREV) & 0xffff;
+ 
+ 	/* done */
+-	pci_set_drvdata (pdev, dev);
+ 	INFO (dev, "%s\n", driver_desc);
+ 	INFO (dev, "irq %s, pci mem %p, chip rev %04x\n",
+ 			bufp, base, dev->chiprev);

commit 658ad5e001a17be5fadaa8d57d1aa7f7c62628c1
+Author: Alan Stern 
+Date:   Fri Apr 14 16:44:11 2006 -0400
+
+    [PATCH] USB: net2280: check for shared IRQs
+    
+    This patch (as670) adds a check for whether a shared IRQ was actually
+    generated by the net2280 device.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
+index c842b194cf0f..b2d507f16b85 100644
+--- a/drivers/usb/gadget/net2280.c
++++ b/drivers/usb/gadget/net2280.c
+@@ -2742,6 +2742,10 @@ static irqreturn_t net2280_irq (int irq, void *_dev, struct pt_regs * r)
+ {
+ 	struct net2280		*dev = _dev;
+ 
++	/* shared interrupt, not ours */
++	if (!(readl(&dev->regs->irqstat0) & (1 << INTA_ASSERTED)))
++		return IRQ_NONE;
++
+ 	spin_lock (&dev->lock);
+ 
+ 	/* handle disconnect, dma, and more */

commit 317e83b842ba39776054219ae29844127876416a
+Author: Alan Stern 
+Date:   Fri Apr 14 16:42:03 2006 -0400
+
+    [PATCH] USB: net2280: send 0-length packets for ep0
+    
+    This patch (as669) fixes a bug in the net2280 driver.  Now it will
+    properly send zero-length packets on ep0 until the control status stage
+    occurs.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
+index 2d5cededcbd7..c842b194cf0f 100644
+--- a/drivers/usb/gadget/net2280.c
++++ b/drivers/usb/gadget/net2280.c
+@@ -2280,9 +2280,7 @@ static void handle_ep_small (struct net2280_ep *ep)
+ 		/* if we wrote it all, we're usually done */
+ 		if (req->req.actual == req->req.length) {
+ 			if (ep->num == 0) {
+-				/* wait for control status */
+-				if (mode != 2)
+-					req = NULL;
++				/* send zlps until the status stage */
+ 			} else if (!req->req.zero || len != ep->ep.maxpacket)
+ 				mode = 2;
+ 		}

commit a29fccd7993a3d411674e148cb0759a017be3e21
+Author: Alan Stern 
+Date:   Fri Apr 14 16:40:00 2006 -0400
+
+    [PATCH] USB: net2280: Handle STALLs for 0-length control-IN requests
+    
+    This patch (as668) fixes a typo in net2280.  The handler for 0-length
+    control-IN requests should check that the endpoint _isn't_ halted before
+    sending a 0-length packet.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
+index 6a4b93ad1082..2d5cededcbd7 100644
+--- a/drivers/usb/gadget/net2280.c
++++ b/drivers/usb/gadget/net2280.c
+@@ -2166,7 +2166,7 @@ static void handle_ep_small (struct net2280_ep *ep)
+ 					ep->stopped = 1;
+ 					set_halt (ep);
+ 					mode = 2;
+-				} else if (!req && ep->stopped)
++				} else if (!req && !ep->stopped)
+ 					write_fifo (ep, NULL);
+ 			}
+ 		} else {

commit 0f836ca4c122f4ef096110d652a6326fe34e6961
+Author: Alan Stern 
+Date:   Fri Mar 31 11:52:25 2006 -0500
+
+    [PATCH] driver core: safely unbind drivers for devices not on a bus
+    
+    This patch (as667) changes the __device_release_driver() routine to
+    prevent it from crashing when it runs across a device not on any bus.
+    This seems logical, inasmuch as the corresponding bus_add_device()
+    routine has an explicit check allowing it to accept such devices.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/base/dd.c b/drivers/base/dd.c
+index 730a9ce0a14a..889c71111239 100644
+--- a/drivers/base/dd.c
++++ b/drivers/base/dd.c
+@@ -209,7 +209,7 @@ static void __device_release_driver(struct device * dev)
+ 		sysfs_remove_link(&dev->kobj, "driver");
+ 		klist_remove(&dev->knode_driver);
+ 
+-		if (dev->bus->remove)
++		if (dev->bus && dev->bus->remove)
+ 			dev->bus->remove(dev);
+ 		else if (drv->remove)
+ 			drv->remove(dev);

commit 8e32640672bdcb01e0d83f087f09dd65fcbc3275
+Author: Alan Stern 
+Date:   Tue Apr 4 14:47:44 2006 -0400
+
+    [PATCH] USB: UHCI: don't track suspended ports
+    
+    Someone recently posted a bug report where it turned out that uhci-hcd
+    was disagreeing with the UHCI controller over whether or not a port was
+    suspended: The driver thought it wasn't and the hardware thought it was.
+    This patch (as665) fixes the problem and simplifies the driver by
+    removing the internal state-tracking completely.  Now the driver just
+    asks the hardware whether a port is suspended.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 3d511690c9b7..c0c4db78b590 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -115,8 +115,7 @@ static void finish_reset(struct uhci_hcd *uhci)
+ 	for (port = 0; port < uhci->rh_numports; ++port)
+ 		outw(0, uhci->io_addr + USBPORTSC1 + (port * 2));
+ 
+-	uhci->port_c_suspend = uhci->suspended_ports =
+-			uhci->resuming_ports = 0;
++	uhci->port_c_suspend = uhci->resuming_ports = 0;
+ 	uhci->rh_state = UHCI_RH_RESET;
+ 	uhci->is_stopped = UHCI_IS_STOPPED;
+ 	uhci_to_hcd(uhci)->state = HC_STATE_HALT;
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index 4a69c7eb09bd..d5c8f4d92823 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -415,7 +415,6 @@ struct uhci_hcd {
+ 
+ 	/* Support for port suspend/resume/reset */
+ 	unsigned long port_c_suspend;		/* Bit-arrays of ports */
+-	unsigned long suspended_ports;
+ 	unsigned long resuming_ports;
+ 	unsigned long ports_timeout;		/* Time to stop signalling */
+ 
+diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
+index 152971d16769..c8451d9578f1 100644
+--- a/drivers/usb/host/uhci-hub.c
++++ b/drivers/usb/host/uhci-hub.c
+@@ -85,11 +85,10 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
+ {
+ 	int status;
+ 
+-	if (test_bit(port, &uhci->suspended_ports)) {
++	if (inw(port_addr) & (USBPORTSC_SUSP | USBPORTSC_RD)) {
+ 		CLR_RH_PORTSTAT(USBPORTSC_SUSP | USBPORTSC_RD);
+-		clear_bit(port, &uhci->suspended_ports);
+-		clear_bit(port, &uhci->resuming_ports);
+-		set_bit(port, &uhci->port_c_suspend);
++		if (test_bit(port, &uhci->resuming_ports))
++			set_bit(port, &uhci->port_c_suspend);
+ 
+ 		/* The controller won't actually turn off the RD bit until
+ 		 * it has had a chance to send a low-speed EOP sequence,
+@@ -97,6 +96,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
+ 		 * slightly longer for good luck. */
+ 		udelay(4);
+ 	}
++	clear_bit(port, &uhci->resuming_ports);
+ }
+ 
+ /* Wait for the UHCI controller in HP's iLO2 server management chip.
+@@ -265,8 +265,6 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+ 			wPortChange |= USB_PORT_STAT_C_SUSPEND;
+ 			lstatus |= 1;
+ 		}
+-		if (test_bit(port, &uhci->suspended_ports))
+-			lstatus |= 2;
+ 		if (test_bit(port, &uhci->resuming_ports))
+ 			lstatus |= 4;
+ 
+@@ -309,7 +307,6 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+ 
+ 		switch (wValue) {
+ 		case USB_PORT_FEAT_SUSPEND:
+-			set_bit(port, &uhci->suspended_ports);
+ 			SET_RH_PORTSTAT(USBPORTSC_SUSP);
+ 			OK(0);
+ 		case USB_PORT_FEAT_RESET:
+@@ -343,8 +340,11 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+ 			CLR_RH_PORTSTAT(USBPORTSC_PEC);
+ 			OK(0);
+ 		case USB_PORT_FEAT_SUSPEND:
+-			if (test_bit(port, &uhci->suspended_ports) &&
+-					!test_and_set_bit(port,
++			if (!(inw(port_addr) & USBPORTSC_SUSP)) {
++
++				/* Make certain the port isn't suspended */
++				uhci_finish_suspend(uhci, port, port_addr);
++			} else if (!test_and_set_bit(port,
+ 						&uhci->resuming_ports)) {
+ 				SET_RH_PORTSTAT(USBPORTSC_RD);
+ 

commit aafe5bd6ec341edfaf3233d272febbb8862a7251
+Author: Alan Stern 
+Date:   Fri Mar 31 11:46:43 2006 -0500
+
+    [PATCH] USB: g_file_storage: use module_param_array_named macro
+    
+    Randy Dunlap pointed out that there now is a module_param_array_named
+    macro available.  This patch (as666) updates g_file_storage to make use of
+    it.  It also adds a comment listing the specifications documents used in
+    the design of the driver's SCSI operation (at Pat LaVarre's request).
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index b6d920f349ea..6f887478b148 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -114,6 +114,14 @@
+  * setting are not allowed when the medium is loaded.
+  *
+  * This gadget driver is heavily based on "Gadget Zero" by David Brownell.
++ * The driver's SCSI command interface was based on the "Information
++ * technology - Small Computer System Interface - 2" document from
++ * X3T9.2 Project 375D, Revision 10L, 7-SEP-93, available at
++ * .  The single exception
++ * is opcode 0x23 (READ FORMAT CAPACITIES), which was based on the
++ * "Universal Serial Bus Mass Storage Class UFI Command Specification"
++ * document, Revision 1.0, December 14, 1998, available at
++ * .
+  */
+ 
+ 
+@@ -340,11 +348,9 @@ MODULE_LICENSE("Dual BSD/GPL");
+ 
+ #define MAX_LUNS	8
+ 
+-	/* Arggh!  There should be a module_param_array_named macro! */
+-static char		*file[MAX_LUNS];
+-static int		ro[MAX_LUNS];
+-
+ static struct {
++	char		*file[MAX_LUNS];
++	int		ro[MAX_LUNS];
+ 	int		num_filenames;
+ 	int		num_ros;
+ 	unsigned int	nluns;
+@@ -376,10 +382,11 @@ static struct {
+ 	};
+ 
+ 
+-module_param_array(file, charp, &mod_data.num_filenames, S_IRUGO);
++module_param_array_named(file, mod_data.file, charp, &mod_data.num_filenames,
++		S_IRUGO);
+ MODULE_PARM_DESC(file, "names of backing files or devices");
+ 
+-module_param_array(ro, bool, &mod_data.num_ros, S_IRUGO);
++module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO);
+ MODULE_PARM_DESC(ro, "true to force read-only");
+ 
+ module_param_named(luns, mod_data.nluns, uint, S_IRUGO);
+@@ -3868,7 +3875,7 @@ static int __init fsg_bind(struct usb_gadget *gadget)
+ 
+ 	for (i = 0; i < fsg->nluns; ++i) {
+ 		curlun = &fsg->luns[i];
+-		curlun->ro = ro[i];
++		curlun->ro = mod_data.ro[i];
+ 		curlun->dev.parent = &gadget->dev;
+ 		curlun->dev.driver = &fsg_driver.driver;
+ 		dev_set_drvdata(&curlun->dev, fsg);
+@@ -3885,8 +3892,9 @@ static int __init fsg_bind(struct usb_gadget *gadget)
+ 			kref_get(&fsg->ref);
+ 		}
+ 
+-		if (file[i] && *file[i]) {
+-			if ((rc = open_backing_file(curlun, file[i])) != 0)
++		if (mod_data.file[i] && *mod_data.file[i]) {
++			if ((rc = open_backing_file(curlun,
++					mod_data.file[i])) != 0)
+ 				goto out;
+ 		} else if (!mod_data.removable) {
+ 			ERROR(fsg, "no file given for LUN%d\n", i);

commit 14cd5f8e85e90c9dead2393377b9a2c23131e0ce
+Author: Alan Stern 
+Date:   Thu Mar 23 15:07:25 2006 -0500
+
+    [PATCH] USB: g_file_storage: add comment about buffer allocation
+    
+    This patch (as664) adds a comment to file_storage.c, noting that the
+    driver is slightly non-portable because it assumes that a buffer
+    allocated for a bulk-in endpoint will also be useable for a bulk-out
+    endpoint.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index eb2821542b7c..b6d920f349ea 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -71,6 +71,12 @@
+  * requirement amounts to two 16K buffers, size configurable by a parameter.
+  * Support is included for both full-speed and high-speed operation.
+  *
++ * Note that the driver is slightly non-portable in that it assumes a
++ * single memory/DMA buffer will be useable for bulk-in, bulk-out, and
++ * interrupt-in endpoints.  With most device controllers this isn't an
++ * issue, but there may be some with hardware restrictions that prevent
++ * a buffer from being used by more than one endpoint.
++ *
+  * Module options:
+  *
+  *	file=filename[,filename...]
+@@ -3956,6 +3962,9 @@ static int __init fsg_bind(struct usb_gadget *gadget)
+ 	for (i = 0; i < NUM_BUFFERS; ++i) {
+ 		struct fsg_buffhd	*bh = &fsg->buffhds[i];
+ 
++		/* Allocate for the bulk-in endpoint.  We assume that
++		 * the buffer will also work with the bulk-out (and
++		 * interrupt-in) endpoint. */
+ 		bh->buf = usb_ep_alloc_buffer(fsg->bulk_in, mod_data.buflen,
+ 				&bh->dma, GFP_KERNEL);
+ 		if (!bh->buf)

commit 70ffe6e14d7c5db84b92841471ce6fd0200010cd
+Author: Alan Stern 
+Date:   Thu Mar 23 15:05:16 2006 -0500
+
+    [PATCH] USB: g_file_storage: Set short_not_ok for bulk-out transfers
+    
+    I'm told that some UDC hardware may work better if it knows that
+    receiving a short packet should always cause an error.  Accordingly,
+    this patch (as663) sets the short_not_ok flag for bulk-out transfers in
+    g_file_storage.  Oddly enough, there are no circumstances where that
+    driver can legally receive a shorter-than-expected bulk-out packet.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index cf3be299e353..eb2821542b7c 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -1795,6 +1795,7 @@ static int do_write(struct fsg_dev *fsg)
+ 			 * the bulk-out maxpacket size */
+ 			bh->outreq->length = bh->bulk_out_intended_length =
+ 					amount;
++			bh->outreq->short_not_ok = 1;
+ 			start_transfer(fsg, fsg->bulk_out, bh->outreq,
+ 					&bh->outreq_busy, &bh->state);
+ 			fsg->next_buffhd_to_fill = bh->next;
+@@ -2398,6 +2399,7 @@ static int throw_away_data(struct fsg_dev *fsg)
+ 			 * the bulk-out maxpacket size */
+ 			bh->outreq->length = bh->bulk_out_intended_length =
+ 					amount;
++			bh->outreq->short_not_ok = 1;
+ 			start_transfer(fsg, fsg->bulk_out, bh->outreq,
+ 					&bh->outreq_busy, &bh->state);
+ 			fsg->next_buffhd_to_fill = bh->next;
+@@ -3029,6 +3031,7 @@ static int get_next_command(struct fsg_dev *fsg)
+ 
+ 		/* Queue a request to read a Bulk-only CBW */
+ 		set_bulk_out_req_length(fsg, bh, USB_BULK_CB_WRAP_LEN);
++		bh->outreq->short_not_ok = 1;
+ 		start_transfer(fsg, fsg->bulk_out, bh->outreq,
+ 				&bh->outreq_busy, &bh->state);
+ 

commit e041c683412d5bf44dc2b109053e3b837b71742d
+Author: Alan Stern 
+Date:   Mon Mar 27 01:16:30 2006 -0800
+
+    [PATCH] Notifier chain update: API changes
+    
+    The kernel's implementation of notifier chains is unsafe.  There is no
+    protection against entries being added to or removed from a chain while the
+    chain is in use.  The issues were discussed in this thread:
+    
+        http://marc.theaimsgroup.com/?l=linux-kernel&m=113018709002036&w=2
+    
+    We noticed that notifier chains in the kernel fall into two basic usage
+    classes:
+    
+            "Blocking" chains are always called from a process context
+            and the callout routines are allowed to sleep;
+    
+            "Atomic" chains can be called from an atomic context and
+            the callout routines are not allowed to sleep.
+    
+    We decided to codify this distinction and make it part of the API.  Therefore
+    this set of patches introduces three new, parallel APIs: one for blocking
+    notifiers, one for atomic notifiers, and one for "raw" notifiers (which is
+    really just the old API under a new name).  New kinds of data structures are
+    used for the heads of the chains, and new routines are defined for
+    registration, unregistration, and calling a chain.  The three APIs are
+    explained in include/linux/notifier.h and their implementation is in
+    kernel/sys.c.
+    
+    With atomic and blocking chains, the implementation guarantees that the chain
+    links will not be corrupted and that chain callers will not get messed up by
+    entries being added or removed.  For raw chains the implementation provides no
+    guarantees at all; users of this API must provide their own protections.  (The
+    idea was that situations may come up where the assumptions of the atomic and
+    blocking APIs are not appropriate, so it should be possible for users to
+    handle these things in their own way.)
+    
+    There are some limitations, which should not be too hard to live with.  For
+    atomic/blocking chains, registration and unregistration must always be done in
+    a process context since the chain is protected by a mutex/rwsem.  Also, a
+    callout routine for a non-raw chain must not try to register or unregister
+    entries on its own chain.  (This did happen in a couple of places and the code
+    had to be changed to avoid it.)
+    
+    Since atomic chains may be called from within an NMI handler, they cannot use
+    spinlocks for synchronization.  Instead we use RCU.  The overhead falls almost
+    entirely in the unregister routine, which is okay since unregistration is much
+    less frequent that calling a chain.
+    
+    Here is the list of chains that we adjusted and their classifications.  None
+    of them use the raw API, so for the moment it is only a placeholder.
+    
+      ATOMIC CHAINS
+      -------------
+    arch/i386/kernel/traps.c:               i386die_chain
+    arch/ia64/kernel/traps.c:               ia64die_chain
+    arch/powerpc/kernel/traps.c:            powerpc_die_chain
+    arch/sparc64/kernel/traps.c:            sparc64die_chain
+    arch/x86_64/kernel/traps.c:             die_chain
+    drivers/char/ipmi/ipmi_si_intf.c:       xaction_notifier_list
+    kernel/panic.c:                         panic_notifier_list
+    kernel/profile.c:                       task_free_notifier
+    net/bluetooth/hci_core.c:               hci_notifier
+    net/ipv4/netfilter/ip_conntrack_core.c: ip_conntrack_chain
+    net/ipv4/netfilter/ip_conntrack_core.c: ip_conntrack_expect_chain
+    net/ipv6/addrconf.c:                    inet6addr_chain
+    net/netfilter/nf_conntrack_core.c:      nf_conntrack_chain
+    net/netfilter/nf_conntrack_core.c:      nf_conntrack_expect_chain
+    net/netlink/af_netlink.c:               netlink_chain
+    
+      BLOCKING CHAINS
+      ---------------
+    arch/powerpc/platforms/pseries/reconfig.c:      pSeries_reconfig_chain
+    arch/s390/kernel/process.c:             idle_chain
+    arch/x86_64/kernel/process.c            idle_notifier
+    drivers/base/memory.c:                  memory_chain
+    drivers/cpufreq/cpufreq.c               cpufreq_policy_notifier_list
+    drivers/cpufreq/cpufreq.c               cpufreq_transition_notifier_list
+    drivers/macintosh/adb.c:                adb_client_list
+    drivers/macintosh/via-pmu.c             sleep_notifier_list
+    drivers/macintosh/via-pmu68k.c          sleep_notifier_list
+    drivers/macintosh/windfarm_core.c       wf_client_list
+    drivers/usb/core/notify.c               usb_notifier_list
+    drivers/video/fbmem.c                   fb_notifier_list
+    kernel/cpu.c                            cpu_chain
+    kernel/module.c                         module_notify_list
+    kernel/profile.c                        munmap_notifier
+    kernel/profile.c                        task_exit_notifier
+    kernel/sys.c                            reboot_notifier_list
+    net/core/dev.c                          netdev_chain
+    net/decnet/dn_dev.c:                    dnaddr_chain
+    net/ipv4/devinet.c:                     inetaddr_chain
+    
+    It's possible that some of these classifications are wrong.  If they are,
+    please let us know or submit a patch to fix them.  Note that any chain that
+    gets called very frequently should be atomic, because the rwsem read-locking
+    used for blocking chains is very likely to incur cache misses on SMP systems.
+    (However, if the chain's callout routines may sleep then the chain cannot be
+    atomic.)
+    
+    The patch set was written by Alan Stern and Chandra Seetharaman, incorporating
+    material written by Keith Owens and suggestions from Paul McKenney and Andrew
+    Morton.
+    
+    [jes@sgi.com: restructure the notifier chain initialization macros]
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Chandra Seetharaman 
+    Signed-off-by: Jes Sorensen 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
+index 9402624453c2..dd8769670596 100644
+--- a/arch/alpha/kernel/setup.c
++++ b/arch/alpha/kernel/setup.c
+@@ -43,7 +43,7 @@
+ #include 
+ #include 
+ 
+-extern struct notifier_block *panic_notifier_list;
++extern struct atomic_notifier_head panic_notifier_list;
+ static int alpha_panic_event(struct notifier_block *, unsigned long, void *);
+ static struct notifier_block alpha_panic_block = {
+ 	alpha_panic_event,
+@@ -500,7 +500,8 @@ setup_arch(char **cmdline_p)
+ 	}
+ 
+ 	/* Register a call for panic conditions. */
+-	notifier_chain_register(&panic_notifier_list, &alpha_panic_block);
++	atomic_notifier_chain_register(&panic_notifier_list,
++			&alpha_panic_block);
+ 
+ #ifdef CONFIG_ALPHA_GENERIC
+ 	/* Assume that we've booted from SRM if we haven't booted from MILO.
+diff --git a/arch/arm/mach-omap1/board-netstar.c b/arch/arm/mach-omap1/board-netstar.c
+index 60d5f8a3339c..7520e602d7a2 100644
+--- a/arch/arm/mach-omap1/board-netstar.c
++++ b/arch/arm/mach-omap1/board-netstar.c
+@@ -141,7 +141,7 @@ static int __init netstar_late_init(void)
+ 	/* TODO: Setup front panel switch here */
+ 
+ 	/* Setup panic notifier */
+-	notifier_chain_register(&panic_notifier_list, &panic_block);
++	atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
+ 
+ 	return 0;
+ }
+diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
+index bfd5fdd1a875..52e4a9d69642 100644
+--- a/arch/arm/mach-omap1/board-voiceblue.c
++++ b/arch/arm/mach-omap1/board-voiceblue.c
+@@ -235,7 +235,7 @@ static struct notifier_block panic_block = {
+ static int __init voiceblue_setup(void)
+ {
+ 	/* Setup panic notifier */
+-	notifier_chain_register(&panic_notifier_list, &panic_block);
++	atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
+ 
+ 	return 0;
+ }
+diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
+index 4624f8ca2459..6b63a5aa1e46 100644
+--- a/arch/i386/kernel/traps.c
++++ b/arch/i386/kernel/traps.c
+@@ -92,22 +92,21 @@ asmlinkage void spurious_interrupt_bug(void);
+ asmlinkage void machine_check(void);
+ 
+ static int kstack_depth_to_print = 24;
+-struct notifier_block *i386die_chain;
+-static DEFINE_SPINLOCK(die_notifier_lock);
++ATOMIC_NOTIFIER_HEAD(i386die_chain);
+ 
+ int register_die_notifier(struct notifier_block *nb)
+ {
+-	int err = 0;
+-	unsigned long flags;
+-
+ 	vmalloc_sync_all();
+-	spin_lock_irqsave(&die_notifier_lock, flags);
+-	err = notifier_chain_register(&i386die_chain, nb);
+-	spin_unlock_irqrestore(&die_notifier_lock, flags);
+-	return err;
++	return atomic_notifier_chain_register(&i386die_chain, nb);
+ }
+ EXPORT_SYMBOL(register_die_notifier);
+ 
++int unregister_die_notifier(struct notifier_block *nb)
++{
++	return atomic_notifier_chain_unregister(&i386die_chain, nb);
++}
++EXPORT_SYMBOL(unregister_die_notifier);
++
+ static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
+ {
+ 	return	p > (void *)tinfo &&
+diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
+index dabd6c32641e..7c1ddc8ac443 100644
+--- a/arch/ia64/kernel/traps.c
++++ b/arch/ia64/kernel/traps.c
+@@ -30,19 +30,19 @@ extern spinlock_t timerlist_lock;
+ fpswa_interface_t *fpswa_interface;
+ EXPORT_SYMBOL(fpswa_interface);
+ 
+-struct notifier_block *ia64die_chain;
++ATOMIC_NOTIFIER_HEAD(ia64die_chain);
+ 
+ int
+ register_die_notifier(struct notifier_block *nb)
+ {
+-	return notifier_chain_register(&ia64die_chain, nb);
++	return atomic_notifier_chain_register(&ia64die_chain, nb);
+ }
+ EXPORT_SYMBOL_GPL(register_die_notifier);
+ 
+ int
+ unregister_die_notifier(struct notifier_block *nb)
+ {
+-	return notifier_chain_unregister(&ia64die_chain, nb);
++	return atomic_notifier_chain_unregister(&ia64die_chain, nb);
+ }
+ EXPORT_SYMBOL_GPL(unregister_die_notifier);
+ 
+diff --git a/arch/mips/lasat/setup.c b/arch/mips/lasat/setup.c
+index 83eb08b7a072..e9e9a89c6741 100644
+--- a/arch/mips/lasat/setup.c
++++ b/arch/mips/lasat/setup.c
+@@ -165,7 +165,8 @@ void __init plat_setup(void)
+ 
+ 	/* Set up panic notifier */
+ 	for (i = 0; i < sizeof(lasat_panic_block) / sizeof(struct notifier_block); i++)
+-		notifier_chain_register(&panic_notifier_list, &lasat_panic_block[i]);
++		atomic_notifier_chain_register(&panic_notifier_list,
++				&lasat_panic_block[i]);
+ 
+ 	lasat_reboot_setup();
+ 
+diff --git a/arch/mips/sgi-ip22/ip22-reset.c b/arch/mips/sgi-ip22/ip22-reset.c
+index 92a3b3c15ed3..a9c58e067b53 100644
+--- a/arch/mips/sgi-ip22/ip22-reset.c
++++ b/arch/mips/sgi-ip22/ip22-reset.c
+@@ -238,7 +238,7 @@ static int __init reboot_setup(void)
+ 	request_irq(SGI_PANEL_IRQ, panel_int, 0, "Front Panel", NULL);
+ 	init_timer(&blink_timer);
+ 	blink_timer.function = blink_timeout;
+-	notifier_chain_register(&panic_notifier_list, &panic_block);
++	atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
+ 
+ 	return 0;
+ }
+diff --git a/arch/mips/sgi-ip32/ip32-reset.c b/arch/mips/sgi-ip32/ip32-reset.c
+index 0c948008b023..ab9d9cef089e 100644
+--- a/arch/mips/sgi-ip32/ip32-reset.c
++++ b/arch/mips/sgi-ip32/ip32-reset.c
+@@ -193,7 +193,7 @@ static __init int ip32_reboot_setup(void)
+ 
+ 	init_timer(&blink_timer);
+ 	blink_timer.function = blink_timeout;
+-	notifier_chain_register(&panic_notifier_list, &panic_block);
++	atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
+ 
+ 	request_irq(MACEISA_RTC_IRQ, ip32_rtc_int, 0, "rtc", NULL);
+ 
+diff --git a/arch/parisc/kernel/pdc_chassis.c b/arch/parisc/kernel/pdc_chassis.c
+index 2a01fe1bdc98..0cea6958f427 100644
+--- a/arch/parisc/kernel/pdc_chassis.c
++++ b/arch/parisc/kernel/pdc_chassis.c
+@@ -150,7 +150,8 @@ void __init parisc_pdc_chassis_init(void)
+ 
+ 		if (handle) {
+ 			/* initialize panic notifier chain */
+-			notifier_chain_register(&panic_notifier_list, &pdc_chassis_panic_block);
++			atomic_notifier_chain_register(&panic_notifier_list,
++					&pdc_chassis_panic_block);
+ 
+ 			/* initialize reboot notifier chain */
+ 			register_reboot_notifier(&pdc_chassis_reboot_block);
+diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
+index 2f3fdad35594..e20c1fae3423 100644
+--- a/arch/powerpc/kernel/setup_64.c
++++ b/arch/powerpc/kernel/setup_64.c
+@@ -579,7 +579,8 @@ void __init setup_arch(char **cmdline_p)
+ 	panic_timeout = 180;
+ 
+ 	if (ppc_md.panic)
+-		notifier_chain_register(&panic_notifier_list, &ppc64_panic_block);
++		atomic_notifier_chain_register(&panic_notifier_list,
++				&ppc64_panic_block);
+ 
+ 	init_mm.start_code = PAGE_OFFSET;
+ 	init_mm.end_code = (unsigned long) _etext;
+diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
+index 98660aedeeb7..9763faab6739 100644
+--- a/arch/powerpc/kernel/traps.c
++++ b/arch/powerpc/kernel/traps.c
+@@ -74,19 +74,19 @@ EXPORT_SYMBOL(__debugger_dabr_match);
+ EXPORT_SYMBOL(__debugger_fault_handler);
+ #endif
+ 
+-struct notifier_block *powerpc_die_chain;
+-static DEFINE_SPINLOCK(die_notifier_lock);
++ATOMIC_NOTIFIER_HEAD(powerpc_die_chain);
+ 
+ int register_die_notifier(struct notifier_block *nb)
+ {
+-	int err = 0;
+-	unsigned long flags;
++	return atomic_notifier_chain_register(&powerpc_die_chain, nb);
++}
++EXPORT_SYMBOL(register_die_notifier);
+ 
+-	spin_lock_irqsave(&die_notifier_lock, flags);
+-	err = notifier_chain_register(&powerpc_die_chain, nb);
+-	spin_unlock_irqrestore(&die_notifier_lock, flags);
+-	return err;
++int unregister_die_notifier(struct notifier_block *nb)
++{
++	return atomic_notifier_chain_unregister(&powerpc_die_chain, nb);
+ }
++EXPORT_SYMBOL(unregister_die_notifier);
+ 
+ /*
+  * Trap & Exception support
+diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
+index 86cfa6ecdcf3..5ad90676567a 100644
+--- a/arch/powerpc/platforms/pseries/reconfig.c
++++ b/arch/powerpc/platforms/pseries/reconfig.c
+@@ -94,16 +94,16 @@ static struct device_node *derive_parent(const char *path)
+ 	return parent;
+ }
+ 
+-static struct notifier_block *pSeries_reconfig_chain;
++static BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain);
+ 
+ int pSeries_reconfig_notifier_register(struct notifier_block *nb)
+ {
+-	return notifier_chain_register(&pSeries_reconfig_chain, nb);
++	return blocking_notifier_chain_register(&pSeries_reconfig_chain, nb);
+ }
+ 
+ void pSeries_reconfig_notifier_unregister(struct notifier_block *nb)
+ {
+-	notifier_chain_unregister(&pSeries_reconfig_chain, nb);
++	blocking_notifier_chain_unregister(&pSeries_reconfig_chain, nb);
+ }
+ 
+ static int pSeries_reconfig_add_node(const char *path, struct property *proplist)
+@@ -131,7 +131,7 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist
+ 		goto out_err;
+ 	}
+ 
+-	err = notifier_call_chain(&pSeries_reconfig_chain,
++	err = blocking_notifier_call_chain(&pSeries_reconfig_chain,
+ 				  PSERIES_RECONFIG_ADD, np);
+ 	if (err == NOTIFY_BAD) {
+ 		printk(KERN_ERR "Failed to add device node %s\n", path);
+@@ -171,7 +171,7 @@ static int pSeries_reconfig_remove_node(struct device_node *np)
+ 
+ 	remove_node_proc_entries(np);
+ 
+-	notifier_call_chain(&pSeries_reconfig_chain,
++	blocking_notifier_call_chain(&pSeries_reconfig_chain,
+ 			    PSERIES_RECONFIG_REMOVE, np);
+ 	of_detach_node(np);
+ 
+diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c
+index a0fc628ffb1e..d95c05d9824d 100644
+--- a/arch/ppc/platforms/prep_setup.c
++++ b/arch/ppc/platforms/prep_setup.c
+@@ -736,7 +736,7 @@ ibm_statusled_progress(char *s, unsigned short hex)
+ 		hex = 0xfff;
+ 		if (!notifier_installed) {
+ 			++notifier_installed;
+-			notifier_chain_register(&panic_notifier_list,
++			atomic_notifier_chain_register(&panic_notifier_list,
+ 						&ibm_statusled_block);
+ 		}
+ 	}
+diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
+index 99182a415fe7..4a0f5a1551ea 100644
+--- a/arch/s390/kernel/process.c
++++ b/arch/s390/kernel/process.c
+@@ -76,17 +76,17 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
+ /*
+  * Need to know about CPUs going idle?
+  */
+-static struct notifier_block *idle_chain;
++static ATOMIC_NOTIFIER_HEAD(idle_chain);
+ 
+ int register_idle_notifier(struct notifier_block *nb)
+ {
+-	return notifier_chain_register(&idle_chain, nb);
++	return atomic_notifier_chain_register(&idle_chain, nb);
+ }
+ EXPORT_SYMBOL(register_idle_notifier);
+ 
+ int unregister_idle_notifier(struct notifier_block *nb)
+ {
+-	return notifier_chain_unregister(&idle_chain, nb);
++	return atomic_notifier_chain_unregister(&idle_chain, nb);
+ }
+ EXPORT_SYMBOL(unregister_idle_notifier);
+ 
+@@ -95,7 +95,7 @@ void do_monitor_call(struct pt_regs *regs, long interruption_code)
+ 	/* disable monitor call class 0 */
+ 	__ctl_clear_bit(8, 15);
+ 
+-	notifier_call_chain(&idle_chain, CPU_NOT_IDLE,
++	atomic_notifier_call_chain(&idle_chain, CPU_NOT_IDLE,
+ 			    (void *)(long) smp_processor_id());
+ }
+ 
+@@ -116,7 +116,8 @@ static void default_idle(void)
+ 		return;
+ 	}
+ 
+-	rc = notifier_call_chain(&idle_chain, CPU_IDLE, (void *)(long) cpu);
++	rc = atomic_notifier_call_chain(&idle_chain,
++			CPU_IDLE, (void *)(long) cpu);
+ 	if (rc != NOTIFY_OK && rc != NOTIFY_DONE)
+ 		BUG();
+ 	if (rc != NOTIFY_OK) {
+diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
+index df612e4f75f9..ff090bb9734b 100644
+--- a/arch/sparc64/kernel/traps.c
++++ b/arch/sparc64/kernel/traps.c
+@@ -43,18 +43,19 @@
+ #include 
+ #endif
+ 
+-struct notifier_block *sparc64die_chain;
+-static DEFINE_SPINLOCK(die_notifier_lock);
++ATOMIC_NOTIFIER_HEAD(sparc64die_chain);
+ 
+ int register_die_notifier(struct notifier_block *nb)
+ {
+-	int err = 0;
+-	unsigned long flags;
+-	spin_lock_irqsave(&die_notifier_lock, flags);
+-	err = notifier_chain_register(&sparc64die_chain, nb);
+-	spin_unlock_irqrestore(&die_notifier_lock, flags);
+-	return err;
++	return atomic_notifier_chain_register(&sparc64die_chain, nb);
+ }
++EXPORT_SYMBOL(register_die_notifier);
++
++int unregister_die_notifier(struct notifier_block *nb)
++{
++	return atomic_notifier_chain_unregister(&sparc64die_chain, nb);
++}
++EXPORT_SYMBOL(unregister_die_notifier);
+ 
+ /* When an irrecoverable trap occurs at tl > 0, the trap entry
+  * code logs the trap state registers at every level in the trap
+diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
+index 54388d10bcf9..1488816588ea 100644
+--- a/arch/um/drivers/mconsole_kern.c
++++ b/arch/um/drivers/mconsole_kern.c
+@@ -762,7 +762,8 @@ static struct notifier_block panic_exit_notifier = {
+ 
+ static int add_notifier(void)
+ {
+-	notifier_chain_register(&panic_notifier_list, &panic_exit_notifier);
++	atomic_notifier_chain_register(&panic_notifier_list,
++			&panic_exit_notifier);
+ 	return(0);
+ }
+ 
+diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
+index bb1c87211ac1..7d51dd7201c3 100644
+--- a/arch/um/kernel/um_arch.c
++++ b/arch/um/kernel/um_arch.c
+@@ -477,7 +477,8 @@ static struct notifier_block panic_exit_notifier = {
+ 
+ void __init setup_arch(char **cmdline_p)
+ {
+-	notifier_chain_register(&panic_notifier_list, &panic_exit_notifier);
++	atomic_notifier_chain_register(&panic_notifier_list,
++			&panic_exit_notifier);
+ 	paging_init();
+         strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
+  	*cmdline_p = command_line;
+diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
+index 0370720515f1..70dd8e5c6889 100644
+--- a/arch/x86_64/kernel/process.c
++++ b/arch/x86_64/kernel/process.c
+@@ -66,24 +66,17 @@ EXPORT_SYMBOL(boot_option_idle_override);
+ void (*pm_idle)(void);
+ static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
+ 
+-static struct notifier_block *idle_notifier;
+-static DEFINE_SPINLOCK(idle_notifier_lock);
++static ATOMIC_NOTIFIER_HEAD(idle_notifier);
+ 
+ void idle_notifier_register(struct notifier_block *n)
+ {
+-	unsigned long flags;
+-	spin_lock_irqsave(&idle_notifier_lock, flags);
+-	notifier_chain_register(&idle_notifier, n);
+-	spin_unlock_irqrestore(&idle_notifier_lock, flags);
++	atomic_notifier_chain_register(&idle_notifier, n);
+ }
+ EXPORT_SYMBOL_GPL(idle_notifier_register);
+ 
+ void idle_notifier_unregister(struct notifier_block *n)
+ {
+-	unsigned long flags;
+-	spin_lock_irqsave(&idle_notifier_lock, flags);
+-	notifier_chain_unregister(&idle_notifier, n);
+-	spin_unlock_irqrestore(&idle_notifier_lock, flags);
++	atomic_notifier_chain_unregister(&idle_notifier, n);
+ }
+ EXPORT_SYMBOL(idle_notifier_unregister);
+ 
+@@ -93,13 +86,13 @@ static DEFINE_PER_CPU(enum idle_state, idle_state) = CPU_NOT_IDLE;
+ void enter_idle(void)
+ {
+ 	__get_cpu_var(idle_state) = CPU_IDLE;
+-	notifier_call_chain(&idle_notifier, IDLE_START, NULL);
++	atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL);
+ }
+ 
+ static void __exit_idle(void)
+ {
+ 	__get_cpu_var(idle_state) = CPU_NOT_IDLE;
+-	notifier_call_chain(&idle_notifier, IDLE_END, NULL);
++	atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL);
+ }
+ 
+ /* Called from interrupts to signify idle end */
+diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
+index 7b148309c529..edaa9fe654dc 100644
+--- a/arch/x86_64/kernel/traps.c
++++ b/arch/x86_64/kernel/traps.c
+@@ -69,20 +69,20 @@ asmlinkage void alignment_check(void);
+ asmlinkage void machine_check(void);
+ asmlinkage void spurious_interrupt_bug(void);
+ 
+-struct notifier_block *die_chain;
+-static DEFINE_SPINLOCK(die_notifier_lock);
++ATOMIC_NOTIFIER_HEAD(die_chain);
+ 
+ int register_die_notifier(struct notifier_block *nb)
+ {
+-	int err = 0;
+-	unsigned long flags;
+-
+ 	vmalloc_sync_all();
+-	spin_lock_irqsave(&die_notifier_lock, flags);
+-	err = notifier_chain_register(&die_chain, nb);
+-	spin_unlock_irqrestore(&die_notifier_lock, flags);
+-	return err;
++	return atomic_notifier_chain_register(&die_chain, nb);
++}
++EXPORT_SYMBOL(register_die_notifier);
++
++int unregister_die_notifier(struct notifier_block *nb)
++{
++	return atomic_notifier_chain_unregister(&die_chain, nb);
+ }
++EXPORT_SYMBOL(unregister_die_notifier);
+ 
+ static inline void conditional_sti(struct pt_regs *regs)
+ {
+diff --git a/arch/xtensa/platform-iss/setup.c b/arch/xtensa/platform-iss/setup.c
+index 2e6dcbf0cc04..23790a5610e2 100644
+--- a/arch/xtensa/platform-iss/setup.c
++++ b/arch/xtensa/platform-iss/setup.c
+@@ -108,5 +108,5 @@ static struct notifier_block iss_panic_block = {
+ 
+ void __init platform_setup(char **p_cmdline)
+ {
+-	notifier_chain_register(&panic_notifier_list, &iss_panic_block);
++	atomic_notifier_chain_register(&panic_notifier_list, &iss_panic_block);
+ }
+diff --git a/drivers/base/memory.c b/drivers/base/memory.c
+index 105a0d61eb1f..dd547af4681a 100644
+--- a/drivers/base/memory.c
++++ b/drivers/base/memory.c
+@@ -47,16 +47,16 @@ static struct kset_uevent_ops memory_uevent_ops = {
+ 	.uevent		= memory_uevent,
+ };
+ 
+-static struct notifier_block *memory_chain;
++static BLOCKING_NOTIFIER_HEAD(memory_chain);
+ 
+ int register_memory_notifier(struct notifier_block *nb)
+ {
+-        return notifier_chain_register(&memory_chain, nb);
++        return blocking_notifier_chain_register(&memory_chain, nb);
+ }
+ 
+ void unregister_memory_notifier(struct notifier_block *nb)
+ {
+-        notifier_chain_unregister(&memory_chain, nb);
++        blocking_notifier_chain_unregister(&memory_chain, nb);
+ }
+ 
+ /*
+@@ -140,7 +140,7 @@ static ssize_t show_mem_state(struct sys_device *dev, char *buf)
+ 
+ static inline int memory_notify(unsigned long val, void *v)
+ {
+-	return notifier_call_chain(&memory_chain, val, v);
++	return blocking_notifier_call_chain(&memory_chain, val, v);
+ }
+ 
+ /*
+diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
+index b8fb87c6c29f..40eb005b9d77 100644
+--- a/drivers/char/ipmi/ipmi_msghandler.c
++++ b/drivers/char/ipmi/ipmi_msghandler.c
+@@ -3744,7 +3744,7 @@ static int ipmi_init_msghandler(void)
+ 	ipmi_timer.expires = jiffies + IPMI_TIMEOUT_JIFFIES;
+ 	add_timer(&ipmi_timer);
+ 
+-	notifier_chain_register(&panic_notifier_list, &panic_block);
++	atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
+ 
+ 	initialized = 1;
+ 
+@@ -3764,7 +3764,7 @@ static __exit void cleanup_ipmi(void)
+ 	if (!initialized)
+ 		return;
+ 
+-	notifier_chain_unregister(&panic_notifier_list, &panic_block);
++	atomic_notifier_chain_unregister(&panic_notifier_list, &panic_block);
+ 
+ 	/* This can't be called if any interfaces exist, so no worry about
+ 	   shutting down the interfaces. */
+diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
+index 12f858dc9994..35fbd4d8ed4b 100644
+--- a/drivers/char/ipmi/ipmi_si_intf.c
++++ b/drivers/char/ipmi/ipmi_si_intf.c
+@@ -237,10 +237,10 @@ struct smi_info
+ 
+ static int try_smi_init(struct smi_info *smi);
+ 
+-static struct notifier_block *xaction_notifier_list;
++static ATOMIC_NOTIFIER_HEAD(xaction_notifier_list);
+ static int register_xaction_notifier(struct notifier_block * nb)
+ {
+-	return notifier_chain_register(&xaction_notifier_list, nb);
++	return atomic_notifier_chain_register(&xaction_notifier_list, nb);
+ }
+ 
+ static void si_restart_short_timer(struct smi_info *smi_info);
+@@ -302,7 +302,8 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info)
+ 		do_gettimeofday(&t);
+ 		printk("**Start2: %d.%9.9d\n", t.tv_sec, t.tv_usec);
+ #endif
+-		err = notifier_call_chain(&xaction_notifier_list, 0, smi_info);
++		err = atomic_notifier_call_chain(&xaction_notifier_list,
++				0, smi_info);
+ 		if (err & NOTIFY_STOP_MASK) {
+ 			rv = SI_SM_CALL_WITHOUT_DELAY;
+ 			goto out;
+diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
+index 616539310d9a..7ece9f3c8f70 100644
+--- a/drivers/char/ipmi/ipmi_watchdog.c
++++ b/drivers/char/ipmi/ipmi_watchdog.c
+@@ -1158,7 +1158,8 @@ static int __init ipmi_wdog_init(void)
+ 	}
+ 
+ 	register_reboot_notifier(&wdog_reboot_notifier);
+-	notifier_chain_register(&panic_notifier_list, &wdog_panic_notifier);
++	atomic_notifier_chain_register(&panic_notifier_list,
++			&wdog_panic_notifier);
+ 
+ 	printk(KERN_INFO PFX "driver initialized\n");
+ 
+@@ -1176,7 +1177,8 @@ static __exit void ipmi_unregister_watchdog(void)
+ 		release_nmi(&ipmi_nmi_handler);
+ #endif
+ 
+-	notifier_chain_unregister(&panic_notifier_list, &wdog_panic_notifier);
++	atomic_notifier_chain_unregister(&panic_notifier_list,
++			&wdog_panic_notifier);
+ 	unregister_reboot_notifier(&wdog_reboot_notifier);
+ 
+ 	if (! watchdog_user)
+diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
+index aed80e6aec6d..9b6ae7dc8b8a 100644
+--- a/drivers/cpufreq/cpufreq.c
++++ b/drivers/cpufreq/cpufreq.c
+@@ -52,9 +52,8 @@ static void handle_update(void *data);
+  * changes to devices when the CPU clock speed changes.
+  * The mutex locks both lists.
+  */
+-static struct notifier_block *cpufreq_policy_notifier_list;
+-static struct notifier_block *cpufreq_transition_notifier_list;
+-static DECLARE_RWSEM (cpufreq_notifier_rwsem);
++static BLOCKING_NOTIFIER_HEAD(cpufreq_policy_notifier_list);
++static BLOCKING_NOTIFIER_HEAD(cpufreq_transition_notifier_list);
+ 
+ 
+ static LIST_HEAD(cpufreq_governor_list);
+@@ -247,8 +246,6 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
+ 	dprintk("notification %u of frequency transition to %u kHz\n",
+ 		state, freqs->new);
+ 
+-	down_read(&cpufreq_notifier_rwsem);
+-
+ 	policy = cpufreq_cpu_data[freqs->cpu];
+ 	switch (state) {
+ 
+@@ -266,20 +263,19 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
+ 				freqs->old = policy->cur;
+ 			}
+ 		}
+-		notifier_call_chain(&cpufreq_transition_notifier_list,
+-					CPUFREQ_PRECHANGE, freqs);
++		blocking_notifier_call_chain(&cpufreq_transition_notifier_list,
++				CPUFREQ_PRECHANGE, freqs);
+ 		adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
+ 		break;
+ 
+ 	case CPUFREQ_POSTCHANGE:
+ 		adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
+-		notifier_call_chain(&cpufreq_transition_notifier_list,
+-					CPUFREQ_POSTCHANGE, freqs);
++		blocking_notifier_call_chain(&cpufreq_transition_notifier_list,
++				CPUFREQ_POSTCHANGE, freqs);
+ 		if (likely(policy) && likely(policy->cpu == freqs->cpu))
+ 			policy->cur = freqs->new;
+ 		break;
+ 	}
+-	up_read(&cpufreq_notifier_rwsem);
+ }
+ EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
+ 
+@@ -1007,7 +1003,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg)
+ 		freqs.old = cpu_policy->cur;
+ 		freqs.new = cur_freq;
+ 
+-		notifier_call_chain(&cpufreq_transition_notifier_list,
++		blocking_notifier_call_chain(&cpufreq_transition_notifier_list,
+ 				    CPUFREQ_SUSPENDCHANGE, &freqs);
+ 		adjust_jiffies(CPUFREQ_SUSPENDCHANGE, &freqs);
+ 
+@@ -1088,7 +1084,8 @@ static int cpufreq_resume(struct sys_device * sysdev)
+ 			freqs.old = cpu_policy->cur;
+ 			freqs.new = cur_freq;
+ 
+-			notifier_call_chain(&cpufreq_transition_notifier_list,
++			blocking_notifier_call_chain(
++					&cpufreq_transition_notifier_list,
+ 					CPUFREQ_RESUMECHANGE, &freqs);
+ 			adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs);
+ 
+@@ -1125,24 +1122,24 @@ static struct sysdev_driver cpufreq_sysdev_driver = {
+  *      changes in cpufreq policy.
+  *
+  *	This function may sleep, and has the same return conditions as
+- *	notifier_chain_register.
++ *	blocking_notifier_chain_register.
+  */
+ int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list)
+ {
+ 	int ret;
+ 
+-	down_write(&cpufreq_notifier_rwsem);
+ 	switch (list) {
+ 	case CPUFREQ_TRANSITION_NOTIFIER:
+-		ret = notifier_chain_register(&cpufreq_transition_notifier_list, nb);
++		ret = blocking_notifier_chain_register(
++				&cpufreq_transition_notifier_list, nb);
+ 		break;
+ 	case CPUFREQ_POLICY_NOTIFIER:
+-		ret = notifier_chain_register(&cpufreq_policy_notifier_list, nb);
++		ret = blocking_notifier_chain_register(
++				&cpufreq_policy_notifier_list, nb);
+ 		break;
+ 	default:
+ 		ret = -EINVAL;
+ 	}
+-	up_write(&cpufreq_notifier_rwsem);
+ 
+ 	return ret;
+ }
+@@ -1157,24 +1154,24 @@ EXPORT_SYMBOL(cpufreq_register_notifier);
+  *	Remove a driver from the CPU frequency notifier list.
+  *
+  *	This function may sleep, and has the same return conditions as
+- *	notifier_chain_unregister.
++ *	blocking_notifier_chain_unregister.
+  */
+ int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list)
+ {
+ 	int ret;
+ 
+-	down_write(&cpufreq_notifier_rwsem);
+ 	switch (list) {
+ 	case CPUFREQ_TRANSITION_NOTIFIER:
+-		ret = notifier_chain_unregister(&cpufreq_transition_notifier_list, nb);
++		ret = blocking_notifier_chain_unregister(
++				&cpufreq_transition_notifier_list, nb);
+ 		break;
+ 	case CPUFREQ_POLICY_NOTIFIER:
+-		ret = notifier_chain_unregister(&cpufreq_policy_notifier_list, nb);
++		ret = blocking_notifier_chain_unregister(
++				&cpufreq_policy_notifier_list, nb);
+ 		break;
+ 	default:
+ 		ret = -EINVAL;
+ 	}
+-	up_write(&cpufreq_notifier_rwsem);
+ 
+ 	return ret;
+ }
+@@ -1346,29 +1343,23 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli
+ 	if (ret)
+ 		goto error_out;
+ 
+-	down_read(&cpufreq_notifier_rwsem);
+-
+ 	/* adjust if necessary - all reasons */
+-	notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_ADJUST,
+-			    policy);
++	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
++			CPUFREQ_ADJUST, policy);
+ 
+ 	/* adjust if necessary - hardware incompatibility*/
+-	notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_INCOMPATIBLE,
+-			    policy);
++	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
++			CPUFREQ_INCOMPATIBLE, policy);
+ 
+ 	/* verify the cpu speed can be set within this limit,
+ 	   which might be different to the first one */
+ 	ret = cpufreq_driver->verify(policy);
+-	if (ret) {
+-		up_read(&cpufreq_notifier_rwsem);
++	if (ret)
+ 		goto error_out;
+-	}
+ 
+ 	/* notification of the new policy */
+-	notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_NOTIFY,
+-			    policy);
+-
+-	up_read(&cpufreq_notifier_rwsem);
++	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
++			CPUFREQ_NOTIFY, policy);
+ 
+ 	data->min = policy->min;
+ 	data->max = policy->max;
+diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c
+index d6543fc4a923..339f405ff708 100644
+--- a/drivers/firmware/dcdbas.c
++++ b/drivers/firmware/dcdbas.c
+@@ -484,26 +484,15 @@ static void dcdbas_host_control(void)
+ static int dcdbas_reboot_notify(struct notifier_block *nb, unsigned long code,
+ 				void *unused)
+ {
+-	static unsigned int notify_cnt = 0;
+-
+ 	switch (code) {
+ 	case SYS_DOWN:
+ 	case SYS_HALT:
+ 	case SYS_POWER_OFF:
+ 		if (host_control_on_shutdown) {
+ 			/* firmware is going to perform host control action */
+-			if (++notify_cnt == 2) {
+-				printk(KERN_WARNING
+-				       "Please wait for shutdown "
+-				       "action to complete...\n");
+-				dcdbas_host_control();
+-			}
+-			/*
+-			 * register again and initiate the host control
+-			 * action on the second notification to allow
+-			 * everyone that registered to be notified
+-			 */
+-			register_reboot_notifier(nb);
++			printk(KERN_WARNING "Please wait for shutdown "
++			       "action to complete...\n");
++			dcdbas_host_control();
+ 		}
+ 		break;
+ 	}
+@@ -514,7 +503,7 @@ static int dcdbas_reboot_notify(struct notifier_block *nb, unsigned long code,
+ static struct notifier_block dcdbas_reboot_nb = {
+ 	.notifier_call = dcdbas_reboot_notify,
+ 	.next = NULL,
+-	.priority = 0
++	.priority = INT_MIN
+ };
+ 
+ static DCDBAS_BIN_ATTR_RW(smi_data);
+diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
+index d2ead1776c16..34fcabac5fdb 100644
+--- a/drivers/macintosh/adb.c
++++ b/drivers/macintosh/adb.c
+@@ -80,7 +80,7 @@ static struct adb_driver *adb_driver_list[] = {
+ static struct class *adb_dev_class;
+ 
+ struct adb_driver *adb_controller;
+-struct notifier_block *adb_client_list = NULL;
++BLOCKING_NOTIFIER_HEAD(adb_client_list);
+ static int adb_got_sleep;
+ static int adb_inited;
+ static pid_t adb_probe_task_pid;
+@@ -354,7 +354,8 @@ adb_notify_sleep(struct pmu_sleep_notifier *self, int when)
+ 		/* Stop autopoll */
+ 		if (adb_controller->autopoll)
+ 			adb_controller->autopoll(0);
+-		ret = notifier_call_chain(&adb_client_list, ADB_MSG_POWERDOWN, NULL);
++		ret = blocking_notifier_call_chain(&adb_client_list,
++				ADB_MSG_POWERDOWN, NULL);
+ 		if (ret & NOTIFY_STOP_MASK) {
+ 			up(&adb_probe_mutex);
+ 			return PBOOK_SLEEP_REFUSE;
+@@ -391,7 +392,8 @@ do_adb_reset_bus(void)
+ 	if (adb_controller->autopoll)
+ 		adb_controller->autopoll(0);
+ 
+-	nret = notifier_call_chain(&adb_client_list, ADB_MSG_PRE_RESET, NULL);
++	nret = blocking_notifier_call_chain(&adb_client_list,
++			ADB_MSG_PRE_RESET, NULL);
+ 	if (nret & NOTIFY_STOP_MASK) {
+ 		if (adb_controller->autopoll)
+ 			adb_controller->autopoll(autopoll_devs);
+@@ -426,7 +428,8 @@ do_adb_reset_bus(void)
+ 	}
+ 	up(&adb_handler_sem);
+ 
+-	nret = notifier_call_chain(&adb_client_list, ADB_MSG_POST_RESET, NULL);
++	nret = blocking_notifier_call_chain(&adb_client_list,
++			ADB_MSG_POST_RESET, NULL);
+ 	if (nret & NOTIFY_STOP_MASK)
+ 		return -EBUSY;
+ 	
+diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
+index c0b46bceb5df..f5779a73184d 100644
+--- a/drivers/macintosh/adbhid.c
++++ b/drivers/macintosh/adbhid.c
+@@ -1214,7 +1214,8 @@ static int __init adbhid_init(void)
+ 
+ 	adbhid_probe();
+ 
+-	notifier_chain_register(&adb_client_list, &adbhid_adb_notifier);
++	blocking_notifier_chain_register(&adb_client_list,
++			&adbhid_adb_notifier);
+ 
+ 	return 0;
+ }
+diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
+index 4f5f3abc9cb3..0b5ff553e39a 100644
+--- a/drivers/macintosh/via-pmu.c
++++ b/drivers/macintosh/via-pmu.c
+@@ -187,7 +187,7 @@ extern int disable_kernel_backlight;
+ 
+ int __fake_sleep;
+ int asleep;
+-struct notifier_block *sleep_notifier_list;
++BLOCKING_NOTIFIER_HEAD(sleep_notifier_list);
+ 
+ #ifdef CONFIG_ADB
+ static int adb_dev_map = 0;
+diff --git a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c
+index f08e52f2107b..35b70323e7e3 100644
+--- a/drivers/macintosh/via-pmu68k.c
++++ b/drivers/macintosh/via-pmu68k.c
+@@ -102,7 +102,7 @@ static int pmu_kind = PMU_UNKNOWN;
+ static int pmu_fully_inited = 0;
+ 
+ int asleep;
+-struct notifier_block *sleep_notifier_list;
++BLOCKING_NOTIFIER_HEAD(sleep_notifier_list);
+ 
+ static int pmu_probe(void);
+ static int pmu_init(void);
+@@ -913,7 +913,8 @@ int powerbook_sleep(void)
+ 	struct adb_request sleep_req;
+ 
+ 	/* Notify device drivers */
+-	ret = notifier_call_chain(&sleep_notifier_list, PBOOK_SLEEP, NULL);
++	ret = blocking_notifier_call_chain(&sleep_notifier_list,
++			PBOOK_SLEEP, NULL);
+ 	if (ret & NOTIFY_STOP_MASK)
+ 		return -EBUSY;
+ 
+@@ -984,7 +985,7 @@ int powerbook_sleep(void)
+ 			enable_irq(i);
+ 
+ 	/* Notify drivers */
+-	notifier_call_chain(&sleep_notifier_list, PBOOK_WAKE, NULL);
++	blocking_notifier_call_chain(&sleep_notifier_list, PBOOK_WAKE, NULL);
+ 
+ 	/* reenable ADB autopoll */
+ 	pmu_adb_autopoll(adb_dev_map);
+diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c
+index 6c0ba04bc57a..ab3faa702d58 100644
+--- a/drivers/macintosh/windfarm_core.c
++++ b/drivers/macintosh/windfarm_core.c
+@@ -52,7 +52,7 @@
+ static LIST_HEAD(wf_controls);
+ static LIST_HEAD(wf_sensors);
+ static DEFINE_MUTEX(wf_lock);
+-static struct notifier_block *wf_client_list;
++static BLOCKING_NOTIFIER_HEAD(wf_client_list);
+ static int wf_client_count;
+ static unsigned int wf_overtemp;
+ static unsigned int wf_overtemp_counter;
+@@ -68,7 +68,7 @@ static struct platform_device wf_platform_device = {
+ 
+ static inline void wf_notify(int event, void *param)
+ {
+-	notifier_call_chain(&wf_client_list, event, param);
++	blocking_notifier_call_chain(&wf_client_list, event, param);
+ }
+ 
+ int wf_critical_overtemp(void)
+@@ -398,7 +398,7 @@ int wf_register_client(struct notifier_block *nb)
+ 	struct wf_sensor *sr;
+ 
+ 	mutex_lock(&wf_lock);
+-	rc = notifier_chain_register(&wf_client_list, nb);
++	rc = blocking_notifier_chain_register(&wf_client_list, nb);
+ 	if (rc != 0)
+ 		goto bail;
+ 	wf_client_count++;
+@@ -417,7 +417,7 @@ EXPORT_SYMBOL_GPL(wf_register_client);
+ int wf_unregister_client(struct notifier_block *nb)
+ {
+ 	mutex_lock(&wf_lock);
+-	notifier_chain_unregister(&wf_client_list, nb);
++	blocking_notifier_chain_unregister(&wf_client_list, nb);
+ 	wf_client_count++;
+ 	if (wf_client_count == 0)
+ 		wf_stop_thread();
+diff --git a/drivers/misc/ibmasm/heartbeat.c b/drivers/misc/ibmasm/heartbeat.c
+index f295401fac21..7fd7a43e38de 100644
+--- a/drivers/misc/ibmasm/heartbeat.c
++++ b/drivers/misc/ibmasm/heartbeat.c
+@@ -52,12 +52,13 @@ static struct notifier_block panic_notifier = { panic_happened, NULL, 1 };
+ 
+ void ibmasm_register_panic_notifier(void)
+ {
+-	notifier_chain_register(&panic_notifier_list, &panic_notifier);
++	atomic_notifier_chain_register(&panic_notifier_list, &panic_notifier);
+ }
+ 
+ void ibmasm_unregister_panic_notifier(void)
+ {
+-	notifier_chain_unregister(&panic_notifier_list, &panic_notifier);
++	atomic_notifier_chain_unregister(&panic_notifier_list,
++			&panic_notifier);
+ }
+ 
+ 
+diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
+index 2d0ac169a86c..f13a539dc169 100644
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -3159,7 +3159,7 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave
+  * bond_netdev_event: handle netdev notifier chain events.
+  *
+  * This function receives events for the netdev chain.  The caller (an
+- * ioctl handler calling notifier_call_chain) holds the necessary
++ * ioctl handler calling blocking_notifier_call_chain) holds the necessary
+  * locks for us to safely manipulate the slave devices (RTNL lock,
+  * dev_probe_lock).
+  */
+diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
+index 3627a2d7f79f..298f2ddb2c17 100644
+--- a/drivers/parisc/led.c
++++ b/drivers/parisc/led.c
+@@ -499,11 +499,16 @@ static int led_halt(struct notifier_block *, unsigned long, void *);
+ static struct notifier_block led_notifier = {
+ 	.notifier_call = led_halt,
+ };
++static int notifier_disabled = 0;
+ 
+ static int led_halt(struct notifier_block *nb, unsigned long event, void *buf) 
+ {
+ 	char *txt;
+-	
++
++	if (notifier_disabled)
++		return NOTIFY_OK;
++
++	notifier_disabled = 1;
+ 	switch (event) {
+ 	case SYS_RESTART:	txt = "SYSTEM RESTART";
+ 				break;
+@@ -527,7 +532,6 @@ static int led_halt(struct notifier_block *nb, unsigned long event, void *buf)
+ 		if (led_func_ptr)
+ 			led_func_ptr(0xff); /* turn all LEDs ON */
+ 	
+-	unregister_reboot_notifier(&led_notifier);
+ 	return NOTIFY_OK;
+ }
+ 
+@@ -758,6 +762,12 @@ int __init led_init(void)
+ 	return 1;
+ }
+ 
++static void __exit led_exit(void)
++{
++	unregister_reboot_notifier(&led_notifier);
++	return;
++}
++
+ #ifdef CONFIG_PROC_FS
+ module_init(led_create_procfs)
+ #endif
+diff --git a/drivers/parisc/power.c b/drivers/parisc/power.c
+index 54b2b7f20b96..0bcab83b4080 100644
+--- a/drivers/parisc/power.c
++++ b/drivers/parisc/power.c
+@@ -251,7 +251,8 @@ static int __init power_init(void)
+ 	}
+ 
+ 	/* Register a call for panic conditions. */
+-	notifier_chain_register(&panic_notifier_list, &parisc_panic_block);
++	atomic_notifier_chain_register(&panic_notifier_list,
++			&parisc_panic_block);
+ 
+ 	tasklet_enable(&power_tasklet);
+ 
+@@ -264,7 +265,8 @@ static void __exit power_exit(void)
+ 		return;
+ 
+ 	tasklet_disable(&power_tasklet);
+-	notifier_chain_unregister(&panic_notifier_list, &parisc_panic_block);
++	atomic_notifier_chain_unregister(&panic_notifier_list,
++			&parisc_panic_block);
+ 	power_tasklet.func = NULL;
+ 	pdc_soft_power_button(0);
+ }
+diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
+index 62e3cda859af..7f7013e80a88 100644
+--- a/drivers/scsi/gdth.c
++++ b/drivers/scsi/gdth.c
+@@ -671,7 +671,7 @@ static struct file_operations gdth_fops = {
+ static struct notifier_block gdth_notifier = {
+     gdth_halt, NULL, 0
+ };
+-
++static int notifier_disabled = 0;
+ 
+ static void gdth_delay(int milliseconds)
+ {
+@@ -4595,13 +4595,13 @@ static int __init gdth_detect(struct scsi_host_template *shtp)
+         add_timer(&gdth_timer);
+ #endif
+         major = register_chrdev(0,"gdth",&gdth_fops);
++        notifier_disabled = 0;
+         register_reboot_notifier(&gdth_notifier);
+     }
+     gdth_polling = FALSE;
+     return gdth_ctr_vcount;
+ }
+ 
+-
+ static int gdth_release(struct Scsi_Host *shp)
+ {
+     int hanum;
+@@ -5632,10 +5632,14 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
+     char            cmnd[MAX_COMMAND_SIZE];   
+ #endif
+ 
++    if (notifier_disabled)
++    	return NOTIFY_OK;
++
+     TRACE2(("gdth_halt() event %d\n",(int)event));
+     if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
+         return NOTIFY_DONE;
+ 
++    notifier_disabled = 1;
+     printk("GDT-HA: Flushing all host drives .. ");
+     for (hanum = 0; hanum < gdth_ctr_count; ++hanum) {
+         gdth_flush(hanum);
+@@ -5679,7 +5683,6 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
+ #ifdef GDTH_STATISTICS
+     del_timer(&gdth_timer);
+ #endif
+-    unregister_reboot_notifier(&gdth_notifier);
+     return NOTIFY_OK;
+ }
+ 
+diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c
+index 4b55285de9a0..fe0ed54fa0ae 100644
+--- a/drivers/usb/core/notify.c
++++ b/drivers/usb/core/notify.c
+@@ -16,57 +16,7 @@
+ #include 
+ #include "usb.h"
+ 
+-
+-static struct notifier_block *usb_notifier_list;
+-static DEFINE_MUTEX(usb_notifier_lock);
+-
+-static void usb_notifier_chain_register(struct notifier_block **list,
+-					struct notifier_block *n)
+-{
+-	mutex_lock(&usb_notifier_lock);
+-	while (*list) {
+-		if (n->priority > (*list)->priority)
+-			break;
+-		list = &((*list)->next);
+-	}
+-	n->next = *list;
+-	*list = n;
+-	mutex_unlock(&usb_notifier_lock);
+-}
+-
+-static void usb_notifier_chain_unregister(struct notifier_block **nl,
+-				   struct notifier_block *n)
+-{
+-	mutex_lock(&usb_notifier_lock);
+-	while ((*nl)!=NULL) {
+-		if ((*nl)==n) {
+-			*nl = n->next;
+-			goto exit;
+-		}
+-		nl=&((*nl)->next);
+-	}
+-exit:
+-	mutex_unlock(&usb_notifier_lock);
+-}
+-
+-static int usb_notifier_call_chain(struct notifier_block **n,
+-				   unsigned long val, void *v)
+-{
+-	int ret=NOTIFY_DONE;
+-	struct notifier_block *nb = *n;
+-
+-	mutex_lock(&usb_notifier_lock);
+-	while (nb) {
+-		ret = nb->notifier_call(nb,val,v);
+-		if (ret&NOTIFY_STOP_MASK) {
+-			goto exit;
+-		}
+-		nb = nb->next;
+-	}
+-exit:
+-	mutex_unlock(&usb_notifier_lock);
+-	return ret;
+-}
++static BLOCKING_NOTIFIER_HEAD(usb_notifier_list);
+ 
+ /**
+  * usb_register_notify - register a notifier callback whenever a usb change happens
+@@ -76,7 +26,7 @@ static int usb_notifier_call_chain(struct notifier_block **n,
+  */
+ void usb_register_notify(struct notifier_block *nb)
+ {
+-	usb_notifier_chain_register(&usb_notifier_list, nb);
++	blocking_notifier_chain_register(&usb_notifier_list, nb);
+ }
+ EXPORT_SYMBOL_GPL(usb_register_notify);
+ 
+@@ -89,27 +39,28 @@ EXPORT_SYMBOL_GPL(usb_register_notify);
+  */
+ void usb_unregister_notify(struct notifier_block *nb)
+ {
+-	usb_notifier_chain_unregister(&usb_notifier_list, nb);
++	blocking_notifier_chain_unregister(&usb_notifier_list, nb);
+ }
+ EXPORT_SYMBOL_GPL(usb_unregister_notify);
+ 
+ 
+ void usb_notify_add_device(struct usb_device *udev)
+ {
+-	usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_ADD, udev);
++	blocking_notifier_call_chain(&usb_notifier_list, USB_DEVICE_ADD, udev);
+ }
+ 
+ void usb_notify_remove_device(struct usb_device *udev)
+ {
+-	usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_REMOVE, udev);
++	blocking_notifier_call_chain(&usb_notifier_list,
++			USB_DEVICE_REMOVE, udev);
+ }
+ 
+ void usb_notify_add_bus(struct usb_bus *ubus)
+ {
+-	usb_notifier_call_chain(&usb_notifier_list, USB_BUS_ADD, ubus);
++	blocking_notifier_call_chain(&usb_notifier_list, USB_BUS_ADD, ubus);
+ }
+ 
+ void usb_notify_remove_bus(struct usb_bus *ubus)
+ {
+-	usb_notifier_call_chain(&usb_notifier_list, USB_BUS_REMOVE, ubus);
++	blocking_notifier_call_chain(&usb_notifier_list, USB_BUS_REMOVE, ubus);
+ }
+diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
+index 07d882b14396..b1a8dca76430 100644
+--- a/drivers/video/fbmem.c
++++ b/drivers/video/fbmem.c
+@@ -55,7 +55,7 @@
+ 
+ #define FBPIXMAPSIZE	(1024 * 8)
+ 
+-static struct notifier_block *fb_notifier_list;
++static BLOCKING_NOTIFIER_HEAD(fb_notifier_list);
+ struct fb_info *registered_fb[FB_MAX];
+ int num_registered_fb;
+ 
+@@ -784,7 +784,7 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
+ 
+ 		    event.info = info;
+ 		    event.data = &mode1;
+-		    ret = notifier_call_chain(&fb_notifier_list,
++		    ret = blocking_notifier_call_chain(&fb_notifier_list,
+ 					      FB_EVENT_MODE_DELETE, &event);
+ 		}
+ 
+@@ -830,8 +830,8 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
+ 
+ 				info->flags &= ~FBINFO_MISC_USEREVENT;
+ 				event.info = info;
+-				notifier_call_chain(&fb_notifier_list, evnt,
+-						    &event);
++				blocking_notifier_call_chain(&fb_notifier_list,
++						evnt, &event);
+ 			}
+ 		}
+ 	}
+@@ -854,7 +854,8 @@ fb_blank(struct fb_info *info, int blank)
+ 
+ 		event.info = info;
+ 		event.data = ␣
+-		notifier_call_chain(&fb_notifier_list, FB_EVENT_BLANK, &event);
++		blocking_notifier_call_chain(&fb_notifier_list,
++				FB_EVENT_BLANK, &event);
+ 	}
+ 
+  	return ret;
+@@ -925,7 +926,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ 		con2fb.framebuffer = -1;
+ 		event.info = info;
+ 		event.data = &con2fb;
+-		notifier_call_chain(&fb_notifier_list,
++		blocking_notifier_call_chain(&fb_notifier_list,
+ 				    FB_EVENT_GET_CONSOLE_MAP, &event);
+ 		return copy_to_user(argp, &con2fb,
+ 				    sizeof(con2fb)) ? -EFAULT : 0;
+@@ -944,7 +945,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ 		    return -EINVAL;
+ 		event.info = info;
+ 		event.data = &con2fb;
+-		return notifier_call_chain(&fb_notifier_list,
++		return blocking_notifier_call_chain(&fb_notifier_list,
+ 					   FB_EVENT_SET_CONSOLE_MAP,
+ 					   &event);
+ 	case FBIOBLANK:
+@@ -1324,7 +1325,7 @@ register_framebuffer(struct fb_info *fb_info)
+ 	devfs_mk_cdev(MKDEV(FB_MAJOR, i),
+ 			S_IFCHR | S_IRUGO | S_IWUGO, "fb/%d", i);
+ 	event.info = fb_info;
+-	notifier_call_chain(&fb_notifier_list,
++	blocking_notifier_call_chain(&fb_notifier_list,
+ 			    FB_EVENT_FB_REGISTERED, &event);
+ 	return 0;
+ }
+@@ -1366,7 +1367,7 @@ unregister_framebuffer(struct fb_info *fb_info)
+  */
+ int fb_register_client(struct notifier_block *nb)
+ {
+-	return notifier_chain_register(&fb_notifier_list, nb);
++	return blocking_notifier_chain_register(&fb_notifier_list, nb);
+ }
+ 
+ /**
+@@ -1375,7 +1376,7 @@ int fb_register_client(struct notifier_block *nb)
+  */
+ int fb_unregister_client(struct notifier_block *nb)
+ {
+-	return notifier_chain_unregister(&fb_notifier_list, nb);
++	return blocking_notifier_chain_unregister(&fb_notifier_list, nb);
+ }
+ 
+ /**
+@@ -1393,11 +1394,13 @@ void fb_set_suspend(struct fb_info *info, int state)
+ 
+ 	event.info = info;
+ 	if (state) {
+-		notifier_call_chain(&fb_notifier_list, FB_EVENT_SUSPEND, &event);
++		blocking_notifier_call_chain(&fb_notifier_list,
++				FB_EVENT_SUSPEND, &event);
+ 		info->state = FBINFO_STATE_SUSPENDED;
+ 	} else {
+ 		info->state = FBINFO_STATE_RUNNING;
+-		notifier_call_chain(&fb_notifier_list, FB_EVENT_RESUME, &event);
++		blocking_notifier_call_chain(&fb_notifier_list,
++				FB_EVENT_RESUME, &event);
+ 	}
+ }
+ 
+@@ -1469,7 +1472,7 @@ int fb_new_modelist(struct fb_info *info)
+ 
+ 	if (!list_empty(&info->modelist)) {
+ 		event.info = info;
+-		err = notifier_call_chain(&fb_notifier_list,
++		err = blocking_notifier_call_chain(&fb_notifier_list,
+ 					   FB_EVENT_NEW_MODELIST,
+ 					   &event);
+ 	}
+@@ -1495,7 +1498,7 @@ int fb_con_duit(struct fb_info *info, int event, void *data)
+ 	evnt.info = info;
+ 	evnt.data = data;
+ 
+-	return notifier_call_chain(&fb_notifier_list, event, &evnt);
++	return blocking_notifier_call_chain(&fb_notifier_list, event, &evnt);
+ }
+ EXPORT_SYMBOL(fb_con_duit);
+ 
+diff --git a/include/asm-i386/kdebug.h b/include/asm-i386/kdebug.h
+index 316138e89910..96d0828ce096 100644
+--- a/include/asm-i386/kdebug.h
++++ b/include/asm-i386/kdebug.h
+@@ -17,11 +17,9 @@ struct die_args {
+ 	int signr;
+ };
+ 
+-/* Note - you should never unregister because that can race with NMIs.
+-   If you really want to do it first unregister - then synchronize_sched - then free.
+-  */
+-int register_die_notifier(struct notifier_block *nb);
+-extern struct notifier_block *i386die_chain;
++extern int register_die_notifier(struct notifier_block *);
++extern int unregister_die_notifier(struct notifier_block *);
++extern struct atomic_notifier_head i386die_chain;
+ 
+ 
+ /* Grossly misnamed. */
+@@ -51,7 +49,7 @@ static inline int notify_die(enum die_val val, const char *str,
+ 		.trapnr = trap,
+ 		.signr = sig
+ 	};
+-	return notifier_call_chain(&i386die_chain, val, &args);
++	return atomic_notifier_call_chain(&i386die_chain, val, &args);
+ }
+ 
+ #endif
+diff --git a/include/asm-ia64/kdebug.h b/include/asm-ia64/kdebug.h
+index 8b01a083dde6..218c458ab60c 100644
+--- a/include/asm-ia64/kdebug.h
++++ b/include/asm-ia64/kdebug.h
+@@ -40,7 +40,7 @@ struct die_args {
+ 
+ extern int register_die_notifier(struct notifier_block *);
+ extern int unregister_die_notifier(struct notifier_block *);
+-extern struct notifier_block *ia64die_chain;
++extern struct atomic_notifier_head ia64die_chain;
+ 
+ enum die_val {
+ 	DIE_BREAK = 1,
+@@ -81,7 +81,7 @@ static inline int notify_die(enum die_val val, char *str, struct pt_regs *regs,
+ 		.signr  = sig
+ 	};
+ 
+-	return notifier_call_chain(&ia64die_chain, val, &args);
++	return atomic_notifier_call_chain(&ia64die_chain, val, &args);
+ }
+ 
+ #endif
+diff --git a/include/asm-powerpc/kdebug.h b/include/asm-powerpc/kdebug.h
+index 7c16265568e0..c01786ab5fa6 100644
+--- a/include/asm-powerpc/kdebug.h
++++ b/include/asm-powerpc/kdebug.h
+@@ -16,13 +16,9 @@ struct die_args {
+ 	int signr;
+ };
+ 
+-/*
+-   Note - you should never unregister because that can race with NMIs.
+-   If you really want to do it first unregister - then synchronize_sched -
+-   then free.
+- */
+-int register_die_notifier(struct notifier_block *nb);
+-extern struct notifier_block *powerpc_die_chain;
++extern int register_die_notifier(struct notifier_block *);
++extern int unregister_die_notifier(struct notifier_block *);
++extern struct atomic_notifier_head powerpc_die_chain;
+ 
+ /* Grossly misnamed. */
+ enum die_val {
+@@ -37,7 +33,7 @@ enum die_val {
+ static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,long err,int trap, int sig)
+ {
+ 	struct die_args args = { .regs=regs, .str=str, .err=err, .trapnr=trap,.signr=sig };
+-	return notifier_call_chain(&powerpc_die_chain, val, &args);
++	return atomic_notifier_call_chain(&powerpc_die_chain, val, &args);
+ }
+ 
+ #endif /* __KERNEL__ */
+diff --git a/include/asm-sparc64/kdebug.h b/include/asm-sparc64/kdebug.h
+index 6321f5a0198d..4040d127ac3e 100644
+--- a/include/asm-sparc64/kdebug.h
++++ b/include/asm-sparc64/kdebug.h
+@@ -15,12 +15,9 @@ struct die_args {
+ 	int signr;
+ };
+ 
+-/* Note - you should never unregister because that can race with NMIs.
+- * If you really want to do it first unregister - then synchronize_sched
+- * - then free.
+- */
+-int register_die_notifier(struct notifier_block *nb);
+-extern struct notifier_block *sparc64die_chain;
++extern int register_die_notifier(struct notifier_block *);
++extern int unregister_die_notifier(struct notifier_block *);
++extern struct atomic_notifier_head sparc64die_chain;
+ 
+ extern void bad_trap(struct pt_regs *, long);
+ 
+@@ -46,7 +43,7 @@ static inline int notify_die(enum die_val val,char *str, struct pt_regs *regs,
+ 				 .trapnr	= trap,
+ 				 .signr		= sig };
+ 
+-	return notifier_call_chain(&sparc64die_chain, val, &args);
++	return atomic_notifier_call_chain(&sparc64die_chain, val, &args);
+ }
+ 
+ #endif
+diff --git a/include/asm-x86_64/kdebug.h b/include/asm-x86_64/kdebug.h
+index b9ed4c0c8783..cf795631d9b4 100644
+--- a/include/asm-x86_64/kdebug.h
++++ b/include/asm-x86_64/kdebug.h
+@@ -5,21 +5,20 @@
+ 
+ struct pt_regs;
+ 
+-struct die_args { 
++struct die_args {
+ 	struct pt_regs *regs;
+ 	const char *str;
+-	long err; 
++	long err;
+ 	int trapnr;
+ 	int signr;
+-}; 
++};
++
++extern int register_die_notifier(struct notifier_block *);
++extern int unregister_die_notifier(struct notifier_block *);
++extern struct atomic_notifier_head die_chain;
+ 
+-/* Note - you should never unregister because that can race with NMIs.
+-   If you really want to do it first unregister - then synchronize_sched - then free.
+-  */
+-int register_die_notifier(struct notifier_block *nb);
+-extern struct notifier_block *die_chain;
+ /* Grossly misnamed. */
+-enum die_val { 
++enum die_val {
+ 	DIE_OOPS = 1,
+ 	DIE_INT3,
+ 	DIE_DEBUG,
+@@ -33,8 +32,8 @@ enum die_val {
+ 	DIE_CALL,
+ 	DIE_NMI_IPI,
+ 	DIE_PAGE_FAULT,
+-}; 
+-	
++};
++
+ static inline int notify_die(enum die_val val, const char *str,
+ 			struct pt_regs *regs, long err, int trap, int sig)
+ {
+@@ -45,7 +44,7 @@ static inline int notify_die(enum die_val val, const char *str,
+ 		.trapnr = trap,
+ 		.signr = sig
+ 	};
+-	return notifier_call_chain(&die_chain, val, &args); 
++	return atomic_notifier_call_chain(&die_chain, val, &args);
+ } 
+ 
+ extern int printk_address(unsigned long address);
+diff --git a/include/linux/adb.h b/include/linux/adb.h
+index e9fdc63483c7..b7305b178279 100644
+--- a/include/linux/adb.h
++++ b/include/linux/adb.h
+@@ -85,7 +85,7 @@ enum adb_message {
+     ADB_MSG_POST_RESET	/* Called after resetting the bus (re-do init & register) */
+ };
+ extern struct adb_driver *adb_controller;
+-extern struct notifier_block *adb_client_list;
++extern struct blocking_notifier_head adb_client_list;
+ 
+ int adb_request(struct adb_request *req, void (*done)(struct adb_request *),
+ 		int flags, int nbytes, ...);
+diff --git a/include/linux/kernel.h b/include/linux/kernel.h
+index 03d6cfaa5b8a..a3720f973ea5 100644
+--- a/include/linux/kernel.h
++++ b/include/linux/kernel.h
+@@ -87,7 +87,7 @@ extern int cond_resched(void);
+ 		(__x < 0) ? -__x : __x;		\
+ 	})
+ 
+-extern struct notifier_block *panic_notifier_list;
++extern struct atomic_notifier_head panic_notifier_list;
+ extern long (*panic_blink)(long time);
+ NORET_TYPE void panic(const char * fmt, ...)
+ 	__attribute__ ((NORET_AND format (printf, 1, 2)));
+diff --git a/include/linux/memory.h b/include/linux/memory.h
+index e251dc43d0f5..8f04143ca363 100644
+--- a/include/linux/memory.h
++++ b/include/linux/memory.h
+@@ -77,7 +77,6 @@ extern int remove_memory_block(unsigned long, struct mem_section *, int);
+ 
+ #define CONFIG_MEM_BLOCK_SIZE	(PAGES_PER_SECTION<
++#include 
++#include 
+ 
+-struct notifier_block
+-{
+-	int (*notifier_call)(struct notifier_block *self, unsigned long, void *);
++/*
++ * Notifier chains are of three types:
++ *
++ *	Atomic notifier chains: Chain callbacks run in interrupt/atomic
++ *		context. Callouts are not allowed to block.
++ *	Blocking notifier chains: Chain callbacks run in process context.
++ *		Callouts are allowed to block.
++ *	Raw notifier chains: There are no restrictions on callbacks,
++ *		registration, or unregistration.  All locking and protection
++ *		must be provided by the caller.
++ *
++ * atomic_notifier_chain_register() may be called from an atomic context,
++ * but blocking_notifier_chain_register() must be called from a process
++ * context.  Ditto for the corresponding _unregister() routines.
++ *
++ * atomic_notifier_chain_unregister() and blocking_notifier_chain_unregister()
++ * _must not_ be called from within the call chain.
++ */
++
++struct notifier_block {
++	int (*notifier_call)(struct notifier_block *, unsigned long, void *);
+ 	struct notifier_block *next;
+ 	int priority;
+ };
+ 
++struct atomic_notifier_head {
++	spinlock_t lock;
++	struct notifier_block *head;
++};
++
++struct blocking_notifier_head {
++	struct rw_semaphore rwsem;
++	struct notifier_block *head;
++};
++
++struct raw_notifier_head {
++	struct notifier_block *head;
++};
++
++#define ATOMIC_INIT_NOTIFIER_HEAD(name) do {	\
++		spin_lock_init(&(name)->lock);	\
++		(name)->head = NULL;		\
++	} while (0)
++#define BLOCKING_INIT_NOTIFIER_HEAD(name) do {	\
++		init_rwsem(&(name)->rwsem);	\
++		(name)->head = NULL;		\
++	} while (0)
++#define RAW_INIT_NOTIFIER_HEAD(name) do {	\
++		(name)->head = NULL;		\
++	} while (0)
++
++#define ATOMIC_NOTIFIER_INIT(name) {				\
++		.lock = SPIN_LOCK_UNLOCKED,			\
++		.head = NULL }
++#define BLOCKING_NOTIFIER_INIT(name) {				\
++		.rwsem = __RWSEM_INITIALIZER((name).rwsem),	\
++		.head = NULL }
++#define RAW_NOTIFIER_INIT(name)	{				\
++		.head = NULL }
++
++#define ATOMIC_NOTIFIER_HEAD(name)				\
++	struct atomic_notifier_head name =			\
++		ATOMIC_NOTIFIER_INIT(name)
++#define BLOCKING_NOTIFIER_HEAD(name)				\
++	struct blocking_notifier_head name =			\
++		BLOCKING_NOTIFIER_INIT(name)
++#define RAW_NOTIFIER_HEAD(name)					\
++	struct raw_notifier_head name =				\
++		RAW_NOTIFIER_INIT(name)
+ 
+ #ifdef __KERNEL__
+ 
+-extern int notifier_chain_register(struct notifier_block **list, struct notifier_block *n);
+-extern int notifier_chain_unregister(struct notifier_block **nl, struct notifier_block *n);
+-extern int notifier_call_chain(struct notifier_block **n, unsigned long val, void *v);
++extern int atomic_notifier_chain_register(struct atomic_notifier_head *,
++		struct notifier_block *);
++extern int blocking_notifier_chain_register(struct blocking_notifier_head *,
++		struct notifier_block *);
++extern int raw_notifier_chain_register(struct raw_notifier_head *,
++		struct notifier_block *);
++
++extern int atomic_notifier_chain_unregister(struct atomic_notifier_head *,
++		struct notifier_block *);
++extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *,
++		struct notifier_block *);
++extern int raw_notifier_chain_unregister(struct raw_notifier_head *,
++		struct notifier_block *);
++
++extern int atomic_notifier_call_chain(struct atomic_notifier_head *,
++		unsigned long val, void *v);
++extern int blocking_notifier_call_chain(struct blocking_notifier_head *,
++		unsigned long val, void *v);
++extern int raw_notifier_call_chain(struct raw_notifier_head *,
++		unsigned long val, void *v);
+ 
+ #define NOTIFY_DONE		0x0000		/* Don't care */
+ #define NOTIFY_OK		0x0001		/* Suits me */
+ #define NOTIFY_STOP_MASK	0x8000		/* Don't call further */
+-#define NOTIFY_BAD		(NOTIFY_STOP_MASK|0x0002)	/* Bad/Veto action	*/
++#define NOTIFY_BAD		(NOTIFY_STOP_MASK|0x0002)
++						/* Bad/Veto action */
+ /*
+  * Clean way to return from the notifier and stop further calls.
+  */
+diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
+index b6f0905a4ee2..916013ca4a5c 100644
+--- a/include/net/netfilter/nf_conntrack.h
++++ b/include/net/netfilter/nf_conntrack.h
+@@ -300,29 +300,30 @@ DECLARE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache);
+ 
+ #define CONNTRACK_ECACHE(x)	(__get_cpu_var(nf_conntrack_ecache).x)
+ 
+-extern struct notifier_block *nf_conntrack_chain;
+-extern struct notifier_block *nf_conntrack_expect_chain;
++extern struct atomic_notifier_head nf_conntrack_chain;
++extern struct atomic_notifier_head nf_conntrack_expect_chain;
+ 
+ static inline int nf_conntrack_register_notifier(struct notifier_block *nb)
+ {
+-	return notifier_chain_register(&nf_conntrack_chain, nb);
++	return atomic_notifier_chain_register(&nf_conntrack_chain, nb);
+ }
+ 
+ static inline int nf_conntrack_unregister_notifier(struct notifier_block *nb)
+ {
+-	return notifier_chain_unregister(&nf_conntrack_chain, nb);
++	return atomic_notifier_chain_unregister(&nf_conntrack_chain, nb);
+ }
+ 
+ static inline int
+ nf_conntrack_expect_register_notifier(struct notifier_block *nb)
+ {
+-	return notifier_chain_register(&nf_conntrack_expect_chain, nb);
++	return atomic_notifier_chain_register(&nf_conntrack_expect_chain, nb);
+ }
+ 
+ static inline int
+ nf_conntrack_expect_unregister_notifier(struct notifier_block *nb)
+ {
+-	return notifier_chain_unregister(&nf_conntrack_expect_chain, nb);
++	return atomic_notifier_chain_unregister(&nf_conntrack_expect_chain,
++			nb);
+ }
+ 
+ extern void nf_ct_deliver_cached_events(const struct nf_conn *ct);
+@@ -347,14 +348,14 @@ static inline void nf_conntrack_event(enum ip_conntrack_events event,
+ 				      struct nf_conn *ct)
+ {
+ 	if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct))
+-		notifier_call_chain(&nf_conntrack_chain, event, ct);
++		atomic_notifier_call_chain(&nf_conntrack_chain, event, ct);
+ }
+ 
+ static inline void
+ nf_conntrack_expect_event(enum ip_conntrack_expect_events event,
+ 			  struct nf_conntrack_expect *exp)
+ {
+-	notifier_call_chain(&nf_conntrack_expect_chain, event, exp);
++	atomic_notifier_call_chain(&nf_conntrack_expect_chain, event, exp);
+ }
+ #else /* CONFIG_NF_CONNTRACK_EVENTS */
+ static inline void nf_conntrack_event_cache(enum ip_conntrack_events event,
+diff --git a/kernel/cpu.c b/kernel/cpu.c
+index 8be22bd80933..fe2b8d0bfe4c 100644
+--- a/kernel/cpu.c
++++ b/kernel/cpu.c
+@@ -18,7 +18,7 @@
+ /* This protects CPUs going up and down... */
+ static DECLARE_MUTEX(cpucontrol);
+ 
+-static struct notifier_block *cpu_chain;
++static BLOCKING_NOTIFIER_HEAD(cpu_chain);
+ 
+ #ifdef CONFIG_HOTPLUG_CPU
+ static struct task_struct *lock_cpu_hotplug_owner;
+@@ -71,21 +71,13 @@ EXPORT_SYMBOL_GPL(lock_cpu_hotplug_interruptible);
+ /* Need to know about CPUs going up/down? */
+ int register_cpu_notifier(struct notifier_block *nb)
+ {
+-	int ret;
+-
+-	if ((ret = lock_cpu_hotplug_interruptible()) != 0)
+-		return ret;
+-	ret = notifier_chain_register(&cpu_chain, nb);
+-	unlock_cpu_hotplug();
+-	return ret;
++	return blocking_notifier_chain_register(&cpu_chain, nb);
+ }
+ EXPORT_SYMBOL(register_cpu_notifier);
+ 
+ void unregister_cpu_notifier(struct notifier_block *nb)
+ {
+-	lock_cpu_hotplug();
+-	notifier_chain_unregister(&cpu_chain, nb);
+-	unlock_cpu_hotplug();
++	blocking_notifier_chain_unregister(&cpu_chain, nb);
+ }
+ EXPORT_SYMBOL(unregister_cpu_notifier);
+ 
+@@ -141,7 +133,7 @@ int cpu_down(unsigned int cpu)
+ 		goto out;
+ 	}
+ 
+-	err = notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE,
++	err = blocking_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE,
+ 						(void *)(long)cpu);
+ 	if (err == NOTIFY_BAD) {
+ 		printk("%s: attempt to take down CPU %u failed\n",
+@@ -159,7 +151,7 @@ int cpu_down(unsigned int cpu)
+ 	p = __stop_machine_run(take_cpu_down, NULL, cpu);
+ 	if (IS_ERR(p)) {
+ 		/* CPU didn't die: tell everyone.  Can't complain. */
+-		if (notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED,
++		if (blocking_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED,
+ 				(void *)(long)cpu) == NOTIFY_BAD)
+ 			BUG();
+ 
+@@ -182,8 +174,8 @@ int cpu_down(unsigned int cpu)
+ 	put_cpu();
+ 
+ 	/* CPU is completely dead: tell everyone.  Too late to complain. */
+-	if (notifier_call_chain(&cpu_chain, CPU_DEAD, (void *)(long)cpu)
+-	    == NOTIFY_BAD)
++	if (blocking_notifier_call_chain(&cpu_chain, CPU_DEAD,
++			(void *)(long)cpu) == NOTIFY_BAD)
+ 		BUG();
+ 
+ 	check_for_tasks(cpu);
+@@ -211,7 +203,7 @@ int __devinit cpu_up(unsigned int cpu)
+ 		goto out;
+ 	}
+ 
+-	ret = notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu);
++	ret = blocking_notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu);
+ 	if (ret == NOTIFY_BAD) {
+ 		printk("%s: attempt to bring up CPU %u failed\n",
+ 				__FUNCTION__, cpu);
+@@ -226,11 +218,12 @@ int __devinit cpu_up(unsigned int cpu)
+ 	BUG_ON(!cpu_online(cpu));
+ 
+ 	/* Now call notifier in preparation. */
+-	notifier_call_chain(&cpu_chain, CPU_ONLINE, hcpu);
++	blocking_notifier_call_chain(&cpu_chain, CPU_ONLINE, hcpu);
+ 
+ out_notify:
+ 	if (ret != 0)
+-		notifier_call_chain(&cpu_chain, CPU_UP_CANCELED, hcpu);
++		blocking_notifier_call_chain(&cpu_chain,
++				CPU_UP_CANCELED, hcpu);
+ out:
+ 	unlock_cpu_hotplug();
+ 	return ret;
+diff --git a/kernel/module.c b/kernel/module.c
+index ddfe45ac2fd1..4fafd58038a0 100644
+--- a/kernel/module.c
++++ b/kernel/module.c
+@@ -64,26 +64,17 @@ static DEFINE_SPINLOCK(modlist_lock);
+ static DEFINE_MUTEX(module_mutex);
+ static LIST_HEAD(modules);
+ 
+-static DEFINE_MUTEX(notify_mutex);
+-static struct notifier_block * module_notify_list;
++static BLOCKING_NOTIFIER_HEAD(module_notify_list);
+ 
+ int register_module_notifier(struct notifier_block * nb)
+ {
+-	int err;
+-	mutex_lock(¬ify_mutex);
+-	err = notifier_chain_register(&module_notify_list, nb);
+-	mutex_unlock(¬ify_mutex);
+-	return err;
++	return blocking_notifier_chain_register(&module_notify_list, nb);
+ }
+ EXPORT_SYMBOL(register_module_notifier);
+ 
+ int unregister_module_notifier(struct notifier_block * nb)
+ {
+-	int err;
+-	mutex_lock(¬ify_mutex);
+-	err = notifier_chain_unregister(&module_notify_list, nb);
+-	mutex_unlock(¬ify_mutex);
+-	return err;
++	return blocking_notifier_chain_unregister(&module_notify_list, nb);
+ }
+ EXPORT_SYMBOL(unregister_module_notifier);
+ 
+@@ -1816,9 +1807,8 @@ sys_init_module(void __user *umod,
+ 	/* Drop lock so they can recurse */
+ 	mutex_unlock(&module_mutex);
+ 
+-	mutex_lock(¬ify_mutex);
+-	notifier_call_chain(&module_notify_list, MODULE_STATE_COMING, mod);
+-	mutex_unlock(¬ify_mutex);
++	blocking_notifier_call_chain(&module_notify_list,
++			MODULE_STATE_COMING, mod);
+ 
+ 	/* Start the module */
+ 	if (mod->init != NULL)
+diff --git a/kernel/panic.c b/kernel/panic.c
+index acd95adddb93..f895c7c01d5b 100644
+--- a/kernel/panic.c
++++ b/kernel/panic.c
+@@ -29,7 +29,7 @@ static DEFINE_SPINLOCK(pause_on_oops_lock);
+ int panic_timeout;
+ EXPORT_SYMBOL(panic_timeout);
+ 
+-struct notifier_block *panic_notifier_list;
++ATOMIC_NOTIFIER_HEAD(panic_notifier_list);
+ 
+ EXPORT_SYMBOL(panic_notifier_list);
+ 
+@@ -97,7 +97,7 @@ NORET_TYPE void panic(const char * fmt, ...)
+ 	smp_send_stop();
+ #endif
+ 
+-	notifier_call_chain(&panic_notifier_list, 0, buf);
++	atomic_notifier_call_chain(&panic_notifier_list, 0, buf);
+ 
+ 	if (!panic_blink)
+ 		panic_blink = no_blink;
+diff --git a/kernel/profile.c b/kernel/profile.c
+index ad81f799a9b4..5a730fdb1a2c 100644
+--- a/kernel/profile.c
++++ b/kernel/profile.c
+@@ -87,72 +87,52 @@ void __init profile_init(void)
+  
+ #ifdef CONFIG_PROFILING
+  
+-static DECLARE_RWSEM(profile_rwsem);
+-static DEFINE_RWLOCK(handoff_lock);
+-static struct notifier_block * task_exit_notifier;
+-static struct notifier_block * task_free_notifier;
+-static struct notifier_block * munmap_notifier;
++static BLOCKING_NOTIFIER_HEAD(task_exit_notifier);
++static ATOMIC_NOTIFIER_HEAD(task_free_notifier);
++static BLOCKING_NOTIFIER_HEAD(munmap_notifier);
+  
+ void profile_task_exit(struct task_struct * task)
+ {
+-	down_read(&profile_rwsem);
+-	notifier_call_chain(&task_exit_notifier, 0, task);
+-	up_read(&profile_rwsem);
++	blocking_notifier_call_chain(&task_exit_notifier, 0, task);
+ }
+  
+ int profile_handoff_task(struct task_struct * task)
+ {
+ 	int ret;
+-	read_lock(&handoff_lock);
+-	ret = notifier_call_chain(&task_free_notifier, 0, task);
+-	read_unlock(&handoff_lock);
++	ret = atomic_notifier_call_chain(&task_free_notifier, 0, task);
+ 	return (ret == NOTIFY_OK) ? 1 : 0;
+ }
+ 
+ void profile_munmap(unsigned long addr)
+ {
+-	down_read(&profile_rwsem);
+-	notifier_call_chain(&munmap_notifier, 0, (void *)addr);
+-	up_read(&profile_rwsem);
++	blocking_notifier_call_chain(&munmap_notifier, 0, (void *)addr);
+ }
+ 
+ int task_handoff_register(struct notifier_block * n)
+ {
+-	int err = -EINVAL;
+-
+-	write_lock(&handoff_lock);
+-	err = notifier_chain_register(&task_free_notifier, n);
+-	write_unlock(&handoff_lock);
+-	return err;
++	return atomic_notifier_chain_register(&task_free_notifier, n);
+ }
+ 
+ int task_handoff_unregister(struct notifier_block * n)
+ {
+-	int err = -EINVAL;
+-
+-	write_lock(&handoff_lock);
+-	err = notifier_chain_unregister(&task_free_notifier, n);
+-	write_unlock(&handoff_lock);
+-	return err;
++	return atomic_notifier_chain_unregister(&task_free_notifier, n);
+ }
+ 
+ int profile_event_register(enum profile_type type, struct notifier_block * n)
+ {
+ 	int err = -EINVAL;
+  
+-	down_write(&profile_rwsem);
+- 
+ 	switch (type) {
+ 		case PROFILE_TASK_EXIT:
+-			err = notifier_chain_register(&task_exit_notifier, n);
++			err = blocking_notifier_chain_register(
++					&task_exit_notifier, n);
+ 			break;
+ 		case PROFILE_MUNMAP:
+-			err = notifier_chain_register(&munmap_notifier, n);
++			err = blocking_notifier_chain_register(
++					&munmap_notifier, n);
+ 			break;
+ 	}
+  
+-	up_write(&profile_rwsem);
+- 
+ 	return err;
+ }
+ 
+@@ -161,18 +141,17 @@ int profile_event_unregister(enum profile_type type, struct notifier_block * n)
+ {
+ 	int err = -EINVAL;
+  
+-	down_write(&profile_rwsem);
+- 
+ 	switch (type) {
+ 		case PROFILE_TASK_EXIT:
+-			err = notifier_chain_unregister(&task_exit_notifier, n);
++			err = blocking_notifier_chain_unregister(
++					&task_exit_notifier, n);
+ 			break;
+ 		case PROFILE_MUNMAP:
+-			err = notifier_chain_unregister(&munmap_notifier, n);
++			err = blocking_notifier_chain_unregister(
++					&munmap_notifier, n);
+ 			break;
+ 	}
+ 
+-	up_write(&profile_rwsem);
+ 	return err;
+ }
+ 
+diff --git a/kernel/softlockup.c b/kernel/softlockup.c
+index d9b3d5847ed8..ced91e1ff564 100644
+--- a/kernel/softlockup.c
++++ b/kernel/softlockup.c
+@@ -152,5 +152,5 @@ __init void spawn_softlockup_task(void)
+ 	cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
+ 	register_cpu_notifier(&cpu_nfb);
+ 
+-	notifier_chain_register(&panic_notifier_list, &panic_block);
++	atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
+ }
+diff --git a/kernel/sys.c b/kernel/sys.c
+index 38bc73ede2ba..c93d37f71aef 100644
+--- a/kernel/sys.c
++++ b/kernel/sys.c
+@@ -95,99 +95,304 @@ int cad_pid = 1;
+  *	and the like. 
+  */
+ 
+-static struct notifier_block *reboot_notifier_list;
+-static DEFINE_RWLOCK(notifier_lock);
++static BLOCKING_NOTIFIER_HEAD(reboot_notifier_list);
++
++/*
++ *	Notifier chain core routines.  The exported routines below
++ *	are layered on top of these, with appropriate locking added.
++ */
++
++static int notifier_chain_register(struct notifier_block **nl,
++		struct notifier_block *n)
++{
++	while ((*nl) != NULL) {
++		if (n->priority > (*nl)->priority)
++			break;
++		nl = &((*nl)->next);
++	}
++	n->next = *nl;
++	rcu_assign_pointer(*nl, n);
++	return 0;
++}
++
++static int notifier_chain_unregister(struct notifier_block **nl,
++		struct notifier_block *n)
++{
++	while ((*nl) != NULL) {
++		if ((*nl) == n) {
++			rcu_assign_pointer(*nl, n->next);
++			return 0;
++		}
++		nl = &((*nl)->next);
++	}
++	return -ENOENT;
++}
++
++static int __kprobes notifier_call_chain(struct notifier_block **nl,
++		unsigned long val, void *v)
++{
++	int ret = NOTIFY_DONE;
++	struct notifier_block *nb;
++
++	nb = rcu_dereference(*nl);
++	while (nb) {
++		ret = nb->notifier_call(nb, val, v);
++		if ((ret & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK)
++			break;
++		nb = rcu_dereference(nb->next);
++	}
++	return ret;
++}
++
++/*
++ *	Atomic notifier chain routines.  Registration and unregistration
++ *	use a mutex, and call_chain is synchronized by RCU (no locks).
++ */
+ 
+ /**
+- *	notifier_chain_register	- Add notifier to a notifier chain
+- *	@list: Pointer to root list pointer
++ *	atomic_notifier_chain_register - Add notifier to an atomic notifier chain
++ *	@nh: Pointer to head of the atomic notifier chain
+  *	@n: New entry in notifier chain
+  *
+- *	Adds a notifier to a notifier chain.
++ *	Adds a notifier to an atomic notifier chain.
+  *
+  *	Currently always returns zero.
+  */
++
++int atomic_notifier_chain_register(struct atomic_notifier_head *nh,
++		struct notifier_block *n)
++{
++	unsigned long flags;
++	int ret;
++
++	spin_lock_irqsave(&nh->lock, flags);
++	ret = notifier_chain_register(&nh->head, n);
++	spin_unlock_irqrestore(&nh->lock, flags);
++	return ret;
++}
++
++EXPORT_SYMBOL_GPL(atomic_notifier_chain_register);
++
++/**
++ *	atomic_notifier_chain_unregister - Remove notifier from an atomic notifier chain
++ *	@nh: Pointer to head of the atomic notifier chain
++ *	@n: Entry to remove from notifier chain
++ *
++ *	Removes a notifier from an atomic notifier chain.
++ *
++ *	Returns zero on success or %-ENOENT on failure.
++ */
++int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
++		struct notifier_block *n)
++{
++	unsigned long flags;
++	int ret;
++
++	spin_lock_irqsave(&nh->lock, flags);
++	ret = notifier_chain_unregister(&nh->head, n);
++	spin_unlock_irqrestore(&nh->lock, flags);
++	synchronize_rcu();
++	return ret;
++}
++
++EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister);
++
++/**
++ *	atomic_notifier_call_chain - Call functions in an atomic notifier chain
++ *	@nh: Pointer to head of the atomic notifier chain
++ *	@val: Value passed unmodified to notifier function
++ *	@v: Pointer passed unmodified to notifier function
++ *
++ *	Calls each function in a notifier chain in turn.  The functions
++ *	run in an atomic context, so they must not block.
++ *	This routine uses RCU to synchronize with changes to the chain.
++ *
++ *	If the return value of the notifier can be and'ed
++ *	with %NOTIFY_STOP_MASK then atomic_notifier_call_chain
++ *	will return immediately, with the return value of
++ *	the notifier function which halted execution.
++ *	Otherwise the return value is the return value
++ *	of the last notifier function called.
++ */
+  
+-int notifier_chain_register(struct notifier_block **list, struct notifier_block *n)
++int atomic_notifier_call_chain(struct atomic_notifier_head *nh,
++		unsigned long val, void *v)
+ {
+-	write_lock(¬ifier_lock);
+-	while(*list)
+-	{
+-		if(n->priority > (*list)->priority)
+-			break;
+-		list= &((*list)->next);
+-	}
+-	n->next = *list;
+-	*list=n;
+-	write_unlock(¬ifier_lock);
+-	return 0;
++	int ret;
++
++	rcu_read_lock();
++	ret = notifier_call_chain(&nh->head, val, v);
++	rcu_read_unlock();
++	return ret;
+ }
+ 
+-EXPORT_SYMBOL(notifier_chain_register);
++EXPORT_SYMBOL_GPL(atomic_notifier_call_chain);
++
++/*
++ *	Blocking notifier chain routines.  All access to the chain is
++ *	synchronized by an rwsem.
++ */
+ 
+ /**
+- *	notifier_chain_unregister - Remove notifier from a notifier chain
+- *	@nl: Pointer to root list pointer
++ *	blocking_notifier_chain_register - Add notifier to a blocking notifier chain
++ *	@nh: Pointer to head of the blocking notifier chain
+  *	@n: New entry in notifier chain
+  *
+- *	Removes a notifier from a notifier chain.
++ *	Adds a notifier to a blocking notifier chain.
++ *	Must be called in process context.
+  *
+- *	Returns zero on success, or %-ENOENT on failure.
++ *	Currently always returns zero.
+  */
+  
+-int notifier_chain_unregister(struct notifier_block **nl, struct notifier_block *n)
++int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
++		struct notifier_block *n)
+ {
+-	write_lock(¬ifier_lock);
+-	while((*nl)!=NULL)
+-	{
+-		if((*nl)==n)
+-		{
+-			*nl=n->next;
+-			write_unlock(¬ifier_lock);
+-			return 0;
+-		}
+-		nl=&((*nl)->next);
+-	}
+-	write_unlock(¬ifier_lock);
+-	return -ENOENT;
++	int ret;
++
++	/*
++	 * This code gets used during boot-up, when task switching is
++	 * not yet working and interrupts must remain disabled.  At
++	 * such times we must not call down_write().
++	 */
++	if (unlikely(system_state == SYSTEM_BOOTING))
++		return notifier_chain_register(&nh->head, n);
++
++	down_write(&nh->rwsem);
++	ret = notifier_chain_register(&nh->head, n);
++	up_write(&nh->rwsem);
++	return ret;
+ }
+ 
+-EXPORT_SYMBOL(notifier_chain_unregister);
++EXPORT_SYMBOL_GPL(blocking_notifier_chain_register);
+ 
+ /**
+- *	notifier_call_chain - Call functions in a notifier chain
+- *	@n: Pointer to root pointer of notifier chain
++ *	blocking_notifier_chain_unregister - Remove notifier from a blocking notifier chain
++ *	@nh: Pointer to head of the blocking notifier chain
++ *	@n: Entry to remove from notifier chain
++ *
++ *	Removes a notifier from a blocking notifier chain.
++ *	Must be called from process context.
++ *
++ *	Returns zero on success or %-ENOENT on failure.
++ */
++int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
++		struct notifier_block *n)
++{
++	int ret;
++
++	/*
++	 * This code gets used during boot-up, when task switching is
++	 * not yet working and interrupts must remain disabled.  At
++	 * such times we must not call down_write().
++	 */
++	if (unlikely(system_state == SYSTEM_BOOTING))
++		return notifier_chain_unregister(&nh->head, n);
++
++	down_write(&nh->rwsem);
++	ret = notifier_chain_unregister(&nh->head, n);
++	up_write(&nh->rwsem);
++	return ret;
++}
++
++EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister);
++
++/**
++ *	blocking_notifier_call_chain - Call functions in a blocking notifier chain
++ *	@nh: Pointer to head of the blocking notifier chain
+  *	@val: Value passed unmodified to notifier function
+  *	@v: Pointer passed unmodified to notifier function
+  *
+- *	Calls each function in a notifier chain in turn.
++ *	Calls each function in a notifier chain in turn.  The functions
++ *	run in a process context, so they are allowed to block.
+  *
+- *	If the return value of the notifier can be and'd
+- *	with %NOTIFY_STOP_MASK, then notifier_call_chain
++ *	If the return value of the notifier can be and'ed
++ *	with %NOTIFY_STOP_MASK then blocking_notifier_call_chain
+  *	will return immediately, with the return value of
+  *	the notifier function which halted execution.
+- *	Otherwise, the return value is the return value
++ *	Otherwise the return value is the return value
+  *	of the last notifier function called.
+  */
+  
+-int __kprobes notifier_call_chain(struct notifier_block **n, unsigned long val, void *v)
++int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
++		unsigned long val, void *v)
+ {
+-	int ret=NOTIFY_DONE;
+-	struct notifier_block *nb = *n;
++	int ret;
+ 
+-	while(nb)
+-	{
+-		ret=nb->notifier_call(nb,val,v);
+-		if(ret&NOTIFY_STOP_MASK)
+-		{
+-			return ret;
+-		}
+-		nb=nb->next;
+-	}
++	down_read(&nh->rwsem);
++	ret = notifier_call_chain(&nh->head, val, v);
++	up_read(&nh->rwsem);
+ 	return ret;
+ }
+ 
+-EXPORT_SYMBOL(notifier_call_chain);
++EXPORT_SYMBOL_GPL(blocking_notifier_call_chain);
++
++/*
++ *	Raw notifier chain routines.  There is no protection;
++ *	the caller must provide it.  Use at your own risk!
++ */
++
++/**
++ *	raw_notifier_chain_register - Add notifier to a raw notifier chain
++ *	@nh: Pointer to head of the raw notifier chain
++ *	@n: New entry in notifier chain
++ *
++ *	Adds a notifier to a raw notifier chain.
++ *	All locking must be provided by the caller.
++ *
++ *	Currently always returns zero.
++ */
++
++int raw_notifier_chain_register(struct raw_notifier_head *nh,
++		struct notifier_block *n)
++{
++	return notifier_chain_register(&nh->head, n);
++}
++
++EXPORT_SYMBOL_GPL(raw_notifier_chain_register);
++
++/**
++ *	raw_notifier_chain_unregister - Remove notifier from a raw notifier chain
++ *	@nh: Pointer to head of the raw notifier chain
++ *	@n: Entry to remove from notifier chain
++ *
++ *	Removes a notifier from a raw notifier chain.
++ *	All locking must be provided by the caller.
++ *
++ *	Returns zero on success or %-ENOENT on failure.
++ */
++int raw_notifier_chain_unregister(struct raw_notifier_head *nh,
++		struct notifier_block *n)
++{
++	return notifier_chain_unregister(&nh->head, n);
++}
++
++EXPORT_SYMBOL_GPL(raw_notifier_chain_unregister);
++
++/**
++ *	raw_notifier_call_chain - Call functions in a raw notifier chain
++ *	@nh: Pointer to head of the raw notifier chain
++ *	@val: Value passed unmodified to notifier function
++ *	@v: Pointer passed unmodified to notifier function
++ *
++ *	Calls each function in a notifier chain in turn.  The functions
++ *	run in an undefined context.
++ *	All locking must be provided by the caller.
++ *
++ *	If the return value of the notifier can be and'ed
++ *	with %NOTIFY_STOP_MASK then raw_notifier_call_chain
++ *	will return immediately, with the return value of
++ *	the notifier function which halted execution.
++ *	Otherwise the return value is the return value
++ *	of the last notifier function called.
++ */
++
++int raw_notifier_call_chain(struct raw_notifier_head *nh,
++		unsigned long val, void *v)
++{
++	return notifier_call_chain(&nh->head, val, v);
++}
++
++EXPORT_SYMBOL_GPL(raw_notifier_call_chain);
+ 
+ /**
+  *	register_reboot_notifier - Register function to be called at reboot time
+@@ -196,13 +401,13 @@ EXPORT_SYMBOL(notifier_call_chain);
+  *	Registers a function with the list of functions
+  *	to be called at reboot time.
+  *
+- *	Currently always returns zero, as notifier_chain_register
++ *	Currently always returns zero, as blocking_notifier_chain_register
+  *	always returns zero.
+  */
+  
+ int register_reboot_notifier(struct notifier_block * nb)
+ {
+-	return notifier_chain_register(&reboot_notifier_list, nb);
++	return blocking_notifier_chain_register(&reboot_notifier_list, nb);
+ }
+ 
+ EXPORT_SYMBOL(register_reboot_notifier);
+@@ -219,7 +424,7 @@ EXPORT_SYMBOL(register_reboot_notifier);
+  
+ int unregister_reboot_notifier(struct notifier_block * nb)
+ {
+-	return notifier_chain_unregister(&reboot_notifier_list, nb);
++	return blocking_notifier_chain_unregister(&reboot_notifier_list, nb);
+ }
+ 
+ EXPORT_SYMBOL(unregister_reboot_notifier);
+@@ -380,7 +585,7 @@ EXPORT_SYMBOL_GPL(emergency_restart);
+ 
+ void kernel_restart_prepare(char *cmd)
+ {
+-	notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
++	blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
+ 	system_state = SYSTEM_RESTART;
+ 	device_shutdown();
+ }
+@@ -430,7 +635,7 @@ EXPORT_SYMBOL_GPL(kernel_kexec);
+ 
+ void kernel_shutdown_prepare(enum system_states state)
+ {
+-	notifier_call_chain(&reboot_notifier_list,
++	blocking_notifier_call_chain(&reboot_notifier_list,
+ 		(state == SYSTEM_HALT)?SYS_HALT:SYS_POWER_OFF, NULL);
+ 	system_state = state;
+ 	device_shutdown();
+diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
+index 9106354c781e..a49a6975092d 100644
+--- a/net/bluetooth/hci_core.c
++++ b/net/bluetooth/hci_core.c
+@@ -73,23 +73,23 @@ DEFINE_RWLOCK(hci_cb_list_lock);
+ struct hci_proto *hci_proto[HCI_MAX_PROTO];
+ 
+ /* HCI notifiers list */
+-static struct notifier_block *hci_notifier;
++static ATOMIC_NOTIFIER_HEAD(hci_notifier);
+ 
+ /* ---- HCI notifications ---- */
+ 
+ int hci_register_notifier(struct notifier_block *nb)
+ {
+-	return notifier_chain_register(&hci_notifier, nb);
++	return atomic_notifier_chain_register(&hci_notifier, nb);
+ }
+ 
+ int hci_unregister_notifier(struct notifier_block *nb)
+ {
+-	return notifier_chain_unregister(&hci_notifier, nb);
++	return atomic_notifier_chain_unregister(&hci_notifier, nb);
+ }
+ 
+ static void hci_notify(struct hci_dev *hdev, int event)
+ {
+-	notifier_call_chain(&hci_notifier, event, hdev);
++	atomic_notifier_call_chain(&hci_notifier, event, hdev);
+ }
+ 
+ /* ---- HCI requests ---- */
+diff --git a/net/core/dev.c b/net/core/dev.c
+index 8e1dc3051222..a3ab11f34153 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -193,7 +193,7 @@ static inline struct hlist_head *dev_index_hash(int ifindex)
+  *	Our notifier list
+  */
+ 
+-static struct notifier_block *netdev_chain;
++static BLOCKING_NOTIFIER_HEAD(netdev_chain);
+ 
+ /*
+  *	Device drivers call our routines to queue packets here. We empty the
+@@ -736,7 +736,8 @@ int dev_change_name(struct net_device *dev, char *newname)
+ 	if (!err) {
+ 		hlist_del(&dev->name_hlist);
+ 		hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name));
+-		notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);
++		blocking_notifier_call_chain(&netdev_chain,
++				NETDEV_CHANGENAME, dev);
+ 	}
+ 
+ 	return err;
+@@ -750,7 +751,7 @@ int dev_change_name(struct net_device *dev, char *newname)
+  */
+ void netdev_features_change(struct net_device *dev)
+ {
+-	notifier_call_chain(&netdev_chain, NETDEV_FEAT_CHANGE, dev);
++	blocking_notifier_call_chain(&netdev_chain, NETDEV_FEAT_CHANGE, dev);
+ }
+ EXPORT_SYMBOL(netdev_features_change);
+ 
+@@ -765,7 +766,8 @@ EXPORT_SYMBOL(netdev_features_change);
+ void netdev_state_change(struct net_device *dev)
+ {
+ 	if (dev->flags & IFF_UP) {
+-		notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev);
++		blocking_notifier_call_chain(&netdev_chain,
++				NETDEV_CHANGE, dev);
+ 		rtmsg_ifinfo(RTM_NEWLINK, dev, 0);
+ 	}
+ }
+@@ -862,7 +864,7 @@ int dev_open(struct net_device *dev)
+ 		/*
+ 		 *	... and announce new interface.
+ 		 */
+-		notifier_call_chain(&netdev_chain, NETDEV_UP, dev);
++		blocking_notifier_call_chain(&netdev_chain, NETDEV_UP, dev);
+ 	}
+ 	return ret;
+ }
+@@ -885,7 +887,7 @@ int dev_close(struct net_device *dev)
+ 	 *	Tell people we are going down, so that they can
+ 	 *	prepare to death, when device is still operating.
+ 	 */
+-	notifier_call_chain(&netdev_chain, NETDEV_GOING_DOWN, dev);
++	blocking_notifier_call_chain(&netdev_chain, NETDEV_GOING_DOWN, dev);
+ 
+ 	dev_deactivate(dev);
+ 
+@@ -922,7 +924,7 @@ int dev_close(struct net_device *dev)
+ 	/*
+ 	 * Tell people we are down
+ 	 */
+-	notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev);
++	blocking_notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev);
+ 
+ 	return 0;
+ }
+@@ -953,7 +955,7 @@ int register_netdevice_notifier(struct notifier_block *nb)
+ 	int err;
+ 
+ 	rtnl_lock();
+-	err = notifier_chain_register(&netdev_chain, nb);
++	err = blocking_notifier_chain_register(&netdev_chain, nb);
+ 	if (!err) {
+ 		for (dev = dev_base; dev; dev = dev->next) {
+ 			nb->notifier_call(nb, NETDEV_REGISTER, dev);
+@@ -981,7 +983,7 @@ int unregister_netdevice_notifier(struct notifier_block *nb)
+ 	int err;
+ 
+ 	rtnl_lock();
+-	err = notifier_chain_unregister(&netdev_chain, nb);
++	err = blocking_notifier_chain_unregister(&netdev_chain, nb);
+ 	rtnl_unlock();
+ 	return err;
+ }
+@@ -992,12 +994,12 @@ int unregister_netdevice_notifier(struct notifier_block *nb)
+  *      @v:   pointer passed unmodified to notifier function
+  *
+  *	Call all network notifier blocks.  Parameters and return value
+- *	are as for notifier_call_chain().
++ *	are as for blocking_notifier_call_chain().
+  */
+ 
+ int call_netdevice_notifiers(unsigned long val, void *v)
+ {
+-	return notifier_call_chain(&netdev_chain, val, v);
++	return blocking_notifier_call_chain(&netdev_chain, val, v);
+ }
+ 
+ /* When > 0 there are consumers of rx skb time stamps */
+@@ -2242,7 +2244,8 @@ int dev_change_flags(struct net_device *dev, unsigned flags)
+ 	if (dev->flags & IFF_UP &&
+ 	    ((old_flags ^ dev->flags) &~ (IFF_UP | IFF_PROMISC | IFF_ALLMULTI |
+ 					  IFF_VOLATILE)))
+-		notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev);
++		blocking_notifier_call_chain(&netdev_chain,
++				NETDEV_CHANGE, dev);
+ 
+ 	if ((flags ^ dev->gflags) & IFF_PROMISC) {
+ 		int inc = (flags & IFF_PROMISC) ? +1 : -1;
+@@ -2286,8 +2289,8 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
+ 	else
+ 		dev->mtu = new_mtu;
+ 	if (!err && dev->flags & IFF_UP)
+-		notifier_call_chain(&netdev_chain,
+-				    NETDEV_CHANGEMTU, dev);
++		blocking_notifier_call_chain(&netdev_chain,
++				NETDEV_CHANGEMTU, dev);
+ 	return err;
+ }
+ 
+@@ -2303,7 +2306,8 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa)
+ 		return -ENODEV;
+ 	err = dev->set_mac_address(dev, sa);
+ 	if (!err)
+-		notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev);
++		blocking_notifier_call_chain(&netdev_chain,
++				NETDEV_CHANGEADDR, dev);
+ 	return err;
+ }
+ 
+@@ -2359,7 +2363,7 @@ static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
+ 				return -EINVAL;
+ 			memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data,
+ 			       min(sizeof ifr->ifr_hwaddr.sa_data, (size_t) dev->addr_len));
+-			notifier_call_chain(&netdev_chain,
++			blocking_notifier_call_chain(&netdev_chain,
+ 					    NETDEV_CHANGEADDR, dev);
+ 			return 0;
+ 
+@@ -2813,7 +2817,7 @@ int register_netdevice(struct net_device *dev)
+ 	write_unlock_bh(&dev_base_lock);
+ 
+ 	/* Notify protocols, that a new device appeared. */
+-	notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
++	blocking_notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
+ 
+ 	/* Finish registration after unlock */
+ 	net_set_todo(dev);
+@@ -2892,7 +2896,7 @@ static void netdev_wait_allrefs(struct net_device *dev)
+ 			rtnl_lock();
+ 
+ 			/* Rebroadcast unregister notification */
+-			notifier_call_chain(&netdev_chain,
++			blocking_notifier_call_chain(&netdev_chain,
+ 					    NETDEV_UNREGISTER, dev);
+ 
+ 			if (test_bit(__LINK_STATE_LINKWATCH_PENDING,
+@@ -3148,7 +3152,7 @@ int unregister_netdevice(struct net_device *dev)
+ 	/* Notify protocols, that we are about to destroy
+ 	   this device. They should clean all the things.
+ 	*/
+-	notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
++	blocking_notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
+ 	
+ 	/*
+ 	 *	Flush the multicast chain
+diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
+index cc7b9d9255ef..d2ae9893ca17 100644
+--- a/net/decnet/dn_dev.c
++++ b/net/decnet/dn_dev.c
+@@ -68,7 +68,7 @@ __le16 decnet_address = 0;
+ 
+ static DEFINE_RWLOCK(dndev_lock);
+ static struct net_device *decnet_default_device;
+-static struct notifier_block *dnaddr_chain;
++static BLOCKING_NOTIFIER_HEAD(dnaddr_chain);
+ 
+ static struct dn_dev *dn_dev_create(struct net_device *dev, int *err);
+ static void dn_dev_delete(struct net_device *dev);
+@@ -446,7 +446,7 @@ static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr **ifap, int de
+ 	}
+ 
+ 	rtmsg_ifa(RTM_DELADDR, ifa1);
+-	notifier_call_chain(&dnaddr_chain, NETDEV_DOWN, ifa1);
++	blocking_notifier_call_chain(&dnaddr_chain, NETDEV_DOWN, ifa1);
+ 	if (destroy) {
+ 		dn_dev_free_ifa(ifa1);
+ 
+@@ -481,7 +481,7 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa)
+ 	dn_db->ifa_list = ifa;
+ 
+ 	rtmsg_ifa(RTM_NEWADDR, ifa);
+-	notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa);
++	blocking_notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa);
+ 
+ 	return 0;
+ }
+@@ -1285,12 +1285,12 @@ void dn_dev_devices_on(void)
+ 
+ int register_dnaddr_notifier(struct notifier_block *nb)
+ {
+-	return notifier_chain_register(&dnaddr_chain, nb);
++	return blocking_notifier_chain_register(&dnaddr_chain, nb);
+ }
+ 
+ int unregister_dnaddr_notifier(struct notifier_block *nb)
+ {
+-	return notifier_chain_unregister(&dnaddr_chain, nb);
++	return blocking_notifier_chain_unregister(&dnaddr_chain, nb);
+ }
+ 
+ #ifdef CONFIG_PROC_FS
+diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
+index 44fdf1413e2c..81c2f7885292 100644
+--- a/net/ipv4/devinet.c
++++ b/net/ipv4/devinet.c
+@@ -81,7 +81,7 @@ static struct ipv4_devconf ipv4_devconf_dflt = {
+ 
+ static void rtmsg_ifa(int event, struct in_ifaddr *);
+ 
+-static struct notifier_block *inetaddr_chain;
++static BLOCKING_NOTIFIER_HEAD(inetaddr_chain);
+ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
+ 			 int destroy);
+ #ifdef CONFIG_SYSCTL
+@@ -267,7 +267,8 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
+ 				*ifap1 = ifa->ifa_next;
+ 
+ 				rtmsg_ifa(RTM_DELADDR, ifa);
+-				notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa);
++				blocking_notifier_call_chain(&inetaddr_chain,
++						NETDEV_DOWN, ifa);
+ 				inet_free_ifa(ifa);
+ 			} else {
+ 				promote = ifa;
+@@ -291,7 +292,7 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
+ 	   So that, this order is correct.
+ 	 */
+ 	rtmsg_ifa(RTM_DELADDR, ifa1);
+-	notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1);
++	blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1);
+ 
+ 	if (promote) {
+ 
+@@ -303,7 +304,8 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
+ 
+ 		promote->ifa_flags &= ~IFA_F_SECONDARY;
+ 		rtmsg_ifa(RTM_NEWADDR, promote);
+-		notifier_call_chain(&inetaddr_chain, NETDEV_UP, promote);
++		blocking_notifier_call_chain(&inetaddr_chain,
++				NETDEV_UP, promote);
+ 		for (ifa = promote->ifa_next; ifa; ifa = ifa->ifa_next) {
+ 			if (ifa1->ifa_mask != ifa->ifa_mask ||
+ 			    !inet_ifa_match(ifa1->ifa_address, ifa))
+@@ -366,7 +368,7 @@ static int inet_insert_ifa(struct in_ifaddr *ifa)
+ 	   Notifier will trigger FIB update, so that
+ 	   listeners of netlink will know about new ifaddr */
+ 	rtmsg_ifa(RTM_NEWADDR, ifa);
+-	notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa);
++	blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa);
+ 
+ 	return 0;
+ }
+@@ -938,12 +940,12 @@ u32 inet_confirm_addr(const struct net_device *dev, u32 dst, u32 local, int scop
+ 
+ int register_inetaddr_notifier(struct notifier_block *nb)
+ {
+-	return notifier_chain_register(&inetaddr_chain, nb);
++	return blocking_notifier_chain_register(&inetaddr_chain, nb);
+ }
+ 
+ int unregister_inetaddr_notifier(struct notifier_block *nb)
+ {
+-	return notifier_chain_unregister(&inetaddr_chain, nb);
++	return blocking_notifier_chain_unregister(&inetaddr_chain, nb);
+ }
+ 
+ /* Rename ifa_labels for a device name change. Make some effort to preserve existing
+diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
+index 9e34034729a6..ceaabc18202b 100644
+--- a/net/ipv4/netfilter/ip_conntrack_core.c
++++ b/net/ipv4/netfilter/ip_conntrack_core.c
+@@ -80,8 +80,8 @@ static int ip_conntrack_vmalloc;
+ static unsigned int ip_conntrack_next_id;
+ static unsigned int ip_conntrack_expect_next_id;
+ #ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
+-struct notifier_block *ip_conntrack_chain;
+-struct notifier_block *ip_conntrack_expect_chain;
++ATOMIC_NOTIFIER_HEAD(ip_conntrack_chain);
++ATOMIC_NOTIFIER_HEAD(ip_conntrack_expect_chain);
+ 
+ DEFINE_PER_CPU(struct ip_conntrack_ecache, ip_conntrack_ecache);
+ 
+@@ -92,7 +92,7 @@ __ip_ct_deliver_cached_events(struct ip_conntrack_ecache *ecache)
+ {
+ 	DEBUGP("ecache: delivering events for %p\n", ecache->ct);
+ 	if (is_confirmed(ecache->ct) && !is_dying(ecache->ct) && ecache->events)
+-		notifier_call_chain(&ip_conntrack_chain, ecache->events,
++		atomic_notifier_call_chain(&ip_conntrack_chain, ecache->events,
+ 				    ecache->ct);
+ 	ecache->events = 0;
+ 	ip_conntrack_put(ecache->ct);
+diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
+index 01c62a0d3742..445006ee4522 100644
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -143,7 +143,7 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev,
+ 				struct prefix_info *pinfo);
+ static int ipv6_chk_same_addr(const struct in6_addr *addr, struct net_device *dev);
+ 
+-static struct notifier_block *inet6addr_chain;
++static ATOMIC_NOTIFIER_HEAD(inet6addr_chain);
+ 
+ struct ipv6_devconf ipv6_devconf = {
+ 	.forwarding		= 0,
+@@ -593,7 +593,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
+ 	read_unlock_bh(&addrconf_lock);
+ 
+ 	if (likely(err == 0))
+-		notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa);
++		atomic_notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa);
+ 	else {
+ 		kfree(ifa);
+ 		ifa = ERR_PTR(err);
+@@ -688,7 +688,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
+ 
+ 	ipv6_ifa_notify(RTM_DELADDR, ifp);
+ 
+-	notifier_call_chain(&inet6addr_chain,NETDEV_DOWN,ifp);
++	atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifp);
+ 
+ 	addrconf_del_timer(ifp);
+ 
+@@ -3767,12 +3767,12 @@ static void addrconf_sysctl_unregister(struct ipv6_devconf *p)
+ 
+ int register_inet6addr_notifier(struct notifier_block *nb)
+ {
+-        return notifier_chain_register(&inet6addr_chain, nb);
++        return atomic_notifier_chain_register(&inet6addr_chain, nb);
+ }
+ 
+ int unregister_inet6addr_notifier(struct notifier_block *nb)
+ {
+-        return notifier_chain_unregister(&inet6addr_chain,nb);
++        return atomic_notifier_chain_unregister(&inet6addr_chain,nb);
+ }
+ 
+ /*
+diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
+index 0ae281d9bfc3..56389c83557c 100644
+--- a/net/netfilter/nf_conntrack_core.c
++++ b/net/netfilter/nf_conntrack_core.c
+@@ -90,8 +90,8 @@ static int nf_conntrack_vmalloc;
+ static unsigned int nf_conntrack_next_id;
+ static unsigned int nf_conntrack_expect_next_id;
+ #ifdef CONFIG_NF_CONNTRACK_EVENTS
+-struct notifier_block *nf_conntrack_chain;
+-struct notifier_block *nf_conntrack_expect_chain;
++ATOMIC_NOTIFIER_HEAD(nf_conntrack_chain);
++ATOMIC_NOTIFIER_HEAD(nf_conntrack_expect_chain);
+ 
+ DEFINE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache);
+ 
+@@ -103,7 +103,7 @@ __nf_ct_deliver_cached_events(struct nf_conntrack_ecache *ecache)
+ 	DEBUGP("ecache: delivering events for %p\n", ecache->ct);
+ 	if (nf_ct_is_confirmed(ecache->ct) && !nf_ct_is_dying(ecache->ct)
+ 	    && ecache->events)
+-		notifier_call_chain(&nf_conntrack_chain, ecache->events,
++		atomic_notifier_call_chain(&nf_conntrack_chain, ecache->events,
+ 				    ecache->ct);
+ 
+ 	ecache->events = 0;
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
+index d00a9034cb5f..2a233ffcf618 100644
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -123,7 +123,7 @@ static void netlink_destroy_callback(struct netlink_callback *cb);
+ static DEFINE_RWLOCK(nl_table_lock);
+ static atomic_t nl_table_users = ATOMIC_INIT(0);
+ 
+-static struct notifier_block *netlink_chain;
++static ATOMIC_NOTIFIER_HEAD(netlink_chain);
+ 
+ static u32 netlink_group_mask(u32 group)
+ {
+@@ -469,7 +469,8 @@ static int netlink_release(struct socket *sock)
+ 						.protocol = sk->sk_protocol,
+ 						.pid = nlk->pid,
+ 					  };
+-		notifier_call_chain(&netlink_chain, NETLINK_URELEASE, &n);
++		atomic_notifier_call_chain(&netlink_chain,
++				NETLINK_URELEASE, &n);
+ 	}	
+ 
+ 	if (nlk->module)
+@@ -1695,12 +1696,12 @@ static struct file_operations netlink_seq_fops = {
+ 
+ int netlink_register_notifier(struct notifier_block *nb)
+ {
+-	return notifier_chain_register(&netlink_chain, nb);
++	return atomic_notifier_chain_register(&netlink_chain, nb);
+ }
+ 
+ int netlink_unregister_notifier(struct notifier_block *nb)
+ {
+-	return notifier_chain_unregister(&netlink_chain, nb);
++	return atomic_notifier_chain_unregister(&netlink_chain, nb);
+ }
+                 
+ static const struct proto_ops netlink_ops = {

commit b89b7ea05a8f71426bd36ed12e6cd73179d0f720
+Author: Alan Stern 
+Date:   Thu Feb 23 17:12:51 2006 -0500
+
+    [PATCH] PCI: Move pci_dev_put outside a spinlock
+    
+    This patch (as659) fixes a might_sleep problem in the PCI core, by moving
+    a call to pci_dev_put() outside the scope of a spinlock.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/pci/search.c b/drivers/pci/search.c
+index 05fa91a31c62..ce7dd6e7be60 100644
+--- a/drivers/pci/search.c
++++ b/drivers/pci/search.c
+@@ -246,9 +246,9 @@ pci_get_subsys(unsigned int vendor, unsigned int device,
+ 	}
+ 	dev = NULL;
+ exit:
+-	pci_dev_put(from);
+ 	dev = pci_dev_get(dev);
+ 	spin_unlock(&pci_bus_lock);
++	pci_dev_put(from);
+ 	return dev;
+ }
+ 
+@@ -339,9 +339,9 @@ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from)
+ 	}
+ 	dev = NULL;
+ exit:
+-	pci_dev_put(from);
+ 	dev = pci_dev_get(dev);
+ 	spin_unlock(&pci_bus_lock);
++	pci_dev_put(from);
+ 	return dev;
+ }
+ 

commit 6aa35675bbc370e5f11baae7e01a9ab255d8030c
+Author: Alan Stern 
+Date:   Wed Mar 8 15:14:09 2006 -0500
+
+    [PATCH] USB: usbcore: Don't assume a USB configuration includes any interfaces
+    
+    In a couple of places, usbcore assumes that a USB device configuration
+    will have a nonzero number of interfaces.  Having no interfaces may or
+    may not be allowed by the USB spec; in any event we shouldn't die if we
+    encounter such a thing.  This patch (as662) removes the assumptions.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 7dd28f8e1cea..8e65f7a237e4 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1179,8 +1179,11 @@ static int choose_configuration(struct usb_device *udev)
+ 	c = udev->config;
+ 	num_configs = udev->descriptor.bNumConfigurations;
+ 	for (i = 0; i < num_configs; (i++, c++)) {
+-		struct usb_interface_descriptor	*desc =
+-				&c->intf_cache[0]->altsetting->desc;
++		struct usb_interface_descriptor	*desc = NULL;
++
++		/* It's possible that a config has no interfaces! */
++		if (c->desc.bNumInterfaces > 0)
++			desc = &c->intf_cache[0]->altsetting->desc;
+ 
+ 		/*
+ 		 * HP's USB bus-powered keyboard has only one configuration
+@@ -1215,7 +1218,8 @@ static int choose_configuration(struct usb_device *udev)
+ 		/* If the first config's first interface is COMM/2/0xff
+ 		 * (MSFT RNDIS), rule it out unless Linux has host-side
+ 		 * RNDIS support. */
+-		if (i == 0 && desc->bInterfaceClass == USB_CLASS_COMM
++		if (i == 0 && desc
++				&& desc->bInterfaceClass == USB_CLASS_COMM
+ 				&& desc->bInterfaceSubClass == 2
+ 				&& desc->bInterfaceProtocol == 0xff) {
+ #ifndef CONFIG_USB_NET_RNDIS
+@@ -1231,8 +1235,8 @@ static int choose_configuration(struct usb_device *udev)
+ 		 * than a vendor-specific driver. */
+ 		else if (udev->descriptor.bDeviceClass !=
+ 						USB_CLASS_VENDOR_SPEC &&
+-				desc->bInterfaceClass !=
+-						USB_CLASS_VENDOR_SPEC) {
++				(!desc || desc->bInterfaceClass !=
++						USB_CLASS_VENDOR_SPEC)) {
+ 			best = c;
+ 			break;
+ 		}
+@@ -3024,7 +3028,7 @@ int usb_reset_device(struct usb_device *udev)
+ 	parent_hub = hdev_to_hub(parent_hdev);
+ 
+ 	/* If we're resetting an active hub, take some special actions */
+-	if (udev->actconfig &&
++	if (udev->actconfig && udev->actconfig->desc.bNumInterfaces > 0 &&
+ 			udev->actconfig->interface[0]->dev.driver ==
+ 				&hub_driver.driver &&
+ 			(hub = hdev_to_hub(udev)) != NULL) {

commit ae55717584431761b70215d3d574c13fe97093f2
+Author: Alan Stern 
+Date:   Tue Feb 28 10:16:12 2006 -0500
+
+    [PATCH] USB: UHCI: Increase port-reset completion delay for HP controllers
+    
+    This patch (as657) increases the port-reset completion delay in uhci-hcd
+    for HP's embedded controllers.  Unlike other UHCI controllers, the HP
+    chips can take as long as 250 us to carry out the processing associated
+    with finishing a port reset.
+    
+    This fixes Novell bug #148761.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
+index a71e48a66805..152971d16769 100644
+--- a/drivers/usb/host/uhci-hub.c
++++ b/drivers/usb/host/uhci-hub.c
+@@ -99,6 +99,21 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
+ 	}
+ }
+ 
++/* Wait for the UHCI controller in HP's iLO2 server management chip.
++ * It can take up to 250 us to finish a reset and set the CSC bit.
++ */
++static void wait_for_HP(unsigned long port_addr)
++{
++	int i;
++
++	for (i = 10; i < 250; i += 10) {
++		if (inw(port_addr) & USBPORTSC_CSC)
++			return;
++		udelay(10);
++	}
++	/* Log a warning? */
++}
++
+ static void uhci_check_ports(struct uhci_hcd *uhci)
+ {
+ 	unsigned int port;
+@@ -113,6 +128,12 @@ static void uhci_check_ports(struct uhci_hcd *uhci)
+ 				CLR_RH_PORTSTAT(USBPORTSC_PR);
+ 				udelay(10);
+ 
++				/* HP's server management chip requires
++				 * a longer delay. */
++				if (to_pci_dev(uhci_dev(uhci))->vendor ==
++						PCI_VENDOR_ID_HP)
++					wait_for_HP(port_addr);
++
+ 				/* If the port was enabled before, turning
+ 				 * reset on caused a port enable change.
+ 				 * Turning reset off causes a port connect

commit 43c5d5aaafef56618a6efbcab7f91615da1a8659
+Author: Alan Stern 
+Date:   Wed Feb 1 10:47:11 2006 -0500
+
+    [PATCH] usbcore: fix compile error with CONFIG_USB_SUSPEND=n
+    
+    This patch (as647) fixes a small error introduced by a recent change to
+    the USB core suspend/resume code.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index f1d64d4bbf5f..7dd28f8e1cea 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1892,8 +1892,8 @@ int usb_resume_device(struct usb_device *udev)
+ 			status = hub_port_resume(hdev_to_hub(udev->parent),
+ 					udev->portnum, udev);
+ 		} else
+-			status = 0;
+ #endif
++			status = 0;
+ 	} else
+ 		status = finish_device_resume(udev);
+ 	if (status < 0)

commit 6a8e87b23ff4a979bde5451a242466a4b3f9fe7d
+Author: Alan Stern 
+Date:   Thu Jan 19 10:46:27 2006 -0500
+
+    [PATCH] USB core and HCDs: don't put_device while atomic
+    
+    This patch (as640) removes several put_device and the corresponding
+    get_device calls from the USB core and HCDs.  Some of the puts were done
+    in atomic contexts, and none of them are needed since the core now
+    guarantees that every endpoint will be disabled and every URB completed
+    before a USB device is released.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index a98d978d76e2..fbd938d4ea58 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1105,7 +1105,6 @@ static void urb_unlink (struct urb *urb)
+ 	spin_lock_irqsave (&hcd_data_lock, flags);
+ 	list_del_init (&urb->urb_list);
+ 	spin_unlock_irqrestore (&hcd_data_lock, flags);
+-	usb_put_dev (urb->dev);
+ }
+ 
+ 
+@@ -1145,7 +1144,6 @@ static int hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+ 	case HC_STATE_RUNNING:
+ 	case HC_STATE_RESUMING:
+ doit:
+-		usb_get_dev (urb->dev);
+ 		list_add_tail (&urb->urb_list, &ep->urb_list);
+ 		status = 0;
+ 		break;
+diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
+index 91c2ab43cbcc..ec7eb3f4f867 100644
+--- a/drivers/usb/host/ehci-mem.c
++++ b/drivers/usb/host/ehci-mem.c
+@@ -75,7 +75,6 @@ static void qh_destroy (struct kref *kref)
+ 	}
+ 	if (qh->dummy)
+ 		ehci_qtd_free (ehci, qh->dummy);
+-	usb_put_dev (qh->dev);
+ 	dma_pool_free (ehci->qh_pool, qh, qh->qh_dma);
+ }
+ 
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 5ada7cd5698b..e469221e7ec3 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -702,7 +702,7 @@ qh_make (
+ 	}
+ 
+ 	/* support for tt scheduling, and access to toggles */
+-	qh->dev = usb_get_dev (urb->dev);
++	qh->dev = urb->dev;
+ 
+ 	/* using TT? */
+ 	switch (urb->dev->speed) {
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 88419c6823a8..90d6900a37f4 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -1399,7 +1399,7 @@ itd_complete (
+ 	 */
+ 
+ 	/* give urb back to the driver ... can be out-of-order */
+-	dev = usb_get_dev (urb->dev);
++	dev = urb->dev;
+ 	ehci_urb_done (ehci, urb, regs);
+ 	urb = NULL;
+ 
+@@ -1418,7 +1418,6 @@ itd_complete (
+ 			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
+ 	}
+ 	iso_stream_put (ehci, stream);
+-	usb_put_dev (dev);
+ 
+ 	return 1;
+ }
+@@ -1765,7 +1764,7 @@ sitd_complete (
+ 	 */
+ 
+ 	/* give urb back to the driver */
+-	dev = usb_get_dev (urb->dev);
++	dev = urb->dev;
+ 	ehci_urb_done (ehci, urb, regs);
+ 	urb = NULL;
+ 
+@@ -1784,7 +1783,6 @@ sitd_complete (
+ 			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
+ 	}
+ 	iso_stream_put (ehci, stream);
+-	usb_put_dev (dev);
+ 
+ 	return 1;
+ }
+diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
+index 972ce04889f8..fea5dcbec7c4 100644
+--- a/drivers/usb/host/isp116x-hcd.c
++++ b/drivers/usb/host/isp116x-hcd.c
+@@ -724,7 +724,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
+ 		ep = hep->hcpriv;
+ 	else {
+ 		INIT_LIST_HEAD(&ep->schedule);
+-		ep->udev = usb_get_dev(udev);
++		ep->udev = udev;
+ 		ep->epnum = epnum;
+ 		ep->maxpacket = usb_maxpacket(udev, urb->pipe, is_out);
+ 		usb_settoggle(udev, epnum, is_out, 0);
+@@ -891,7 +891,6 @@ static void isp116x_endpoint_disable(struct usb_hcd *hcd,
+ 	if (!list_empty(&hep->urb_list))
+ 		WARN("ep %p not empty?\n", ep);
+ 
+-	usb_put_dev(ep->udev);
+ 	kfree(ep);
+ 	hep->hcpriv = NULL;
+ }
+diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
+index 517360b77d8e..a92343052751 100644
+--- a/drivers/usb/host/sl811-hcd.c
++++ b/drivers/usb/host/sl811-hcd.c
+@@ -853,7 +853,7 @@ static int sl811h_urb_enqueue(
+ 
+ 	} else {
+ 		INIT_LIST_HEAD(&ep->schedule);
+-		ep->udev = usb_get_dev(udev);
++		ep->udev = udev;
+ 		ep->epnum = epnum;
+ 		ep->maxpacket = usb_maxpacket(udev, urb->pipe, is_out);
+ 		ep->defctrl = SL11H_HCTLMASK_ARM | SL11H_HCTLMASK_ENABLE;
+@@ -1052,7 +1052,6 @@ sl811h_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep)
+ 	if (!list_empty(&hep->urb_list))
+ 		WARN("ep %p not empty?\n", ep);
+ 
+-	usb_put_dev(ep->udev);
+ 	kfree(ep);
+ 	hep->hcpriv = NULL;
+ }
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 5d2f9575ab4f..a06d84c19e13 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -179,7 +179,6 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci,
+ 		qh->hep = hep;
+ 		qh->udev = udev;
+ 		hep->hcpriv = qh;
+-		usb_get_dev(udev);
+ 
+ 	} else {		/* Skeleton QH */
+ 		qh->state = QH_STATE_ACTIVE;
+@@ -197,7 +196,6 @@ static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ 	list_del(&qh->node);
+ 	if (qh->udev) {
+ 		qh->hep->hcpriv = NULL;
+-		usb_put_dev(qh->udev);
+ 		uhci_free_td(uhci, qh->dummy_td);
+ 	}
+ 	dma_pool_free(uhci->qh_pool, qh, qh->dma_handle);

commit 1393adb2ebb00a2cd54b293cd7ee71e3376f4e9f
+Author: Alan Stern 
+Date:   Tue Jan 31 10:02:55 2006 -0500
+
+    [PATCH] uhci-hcd: fix mistaken usage of list_prepare_entry
+    
+    A recent update to the uhci-hcd driver invoked the list_prepare_entry
+    macro incorrectly.  This patch (as646) corrects it.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 0c1b12091c48..5d2f9575ab4f 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -259,7 +259,7 @@ static void uhci_fixup_toggles(struct uhci_qh *qh, int skip_first)
+ 	/* Fix up the toggle for the URBs in the queue.  Normally this
+ 	 * loop won't run more than once: When an error or short transfer
+ 	 * occurs, the queue usually gets emptied. */
+-	list_prepare_entry(urbp, &qh->queue, node);
++	urbp = list_prepare_entry(urbp, &qh->queue, node);
+ 	list_for_each_entry_continue(urbp, &qh->queue, node) {
+ 
+ 		/* If the first TD has the right toggle value, we don't

commit dbf4fcad62467ce1bd6966292b6850fc7a210e0b
+Author: Alan Stern 
+Date:   Tue Dec 20 09:58:08 2005 -0500
+
+    [PATCH] UHCI: Don't log short transfers
+    
+    Even when the URB_SHORT_NOT_OK flag is set, a short transfer shouldn't
+    generate a debugging log message.  Especially not one with the confusing
+    claim that the transfer "failed with status 0".  This patch (as627)
+    fixes that behavior in uhci-hcd.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 5d6c4f75d0d8..0c1b12091c48 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -922,7 +922,6 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
+ td_error:
+ 	ret = uhci_map_status(status, uhci_packetout(td_token(td)));
+ 
+-err:
+ 	if ((debug == 1 && ret != -EPIPE) || debug > 1) {
+ 		/* Some debugging code */
+ 		dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n",
+@@ -934,6 +933,7 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
+ 			lprintk(errbuf);
+ 		}
+ 	}
++err:
+ 
+ 	/* Note that the queue has stopped and save the next toggle value */
+ 	urbp->qh->element = UHCI_PTR_TERM;

commit 8d402e1ae03656c1ad215514f8885ef4793f0948
+Author: Alan Stern 
+Date:   Sat Dec 17 18:03:37 2005 -0500
+
+    [PATCH] UHCI: improve debugging code
+    
+    This patch (as626) makes some improvements to the debugging code in
+    uhci-hcd.  The main change is that now the code won't get compiled if
+    CONFIG_USB_DEBUG isn't set.  But there are other changes too, like
+    adding a missing .owner field and printing a debugging dump if the
+    controller dies.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
+index f2f5f8ce1715..e1239319655c 100644
+--- a/drivers/usb/host/uhci-debug.c
++++ b/drivers/usb/host/uhci-debug.c
+@@ -17,10 +17,13 @@
+ 
+ #include "uhci-hcd.h"
+ 
+-static struct dentry *uhci_debugfs_root = NULL;
++#define uhci_debug_operations (* (struct file_operations *) NULL)
++static struct dentry *uhci_debugfs_root;
++
++#ifdef DEBUG
+ 
+ /* Handle REALLY large printks so we don't overflow buffers */
+-static inline void lprintk(char *buf)
++static void lprintk(char *buf)
+ {
+ 	char *p;
+ 
+@@ -196,7 +199,6 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
+ 	return out - buf;
+ }
+ 
+-#ifdef CONFIG_PROC_FS
+ static const char * const qh_names[] = {
+   "skel_unlink_qh", "skel_iso_qh",
+   "skel_int128_qh", "skel_int64_qh",
+@@ -393,12 +395,13 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
+ 	return out - buf;
+ }
+ 
++#ifdef CONFIG_DEBUG_FS
++
+ #define MAX_OUTPUT	(64 * 1024)
+ 
+ struct uhci_debug {
+ 	int size;
+ 	char *data;
+-	struct uhci_hcd *uhci;
+ };
+ 
+ static int uhci_debug_open(struct inode *inode, struct file *file)
+@@ -419,8 +422,10 @@ static int uhci_debug_open(struct inode *inode, struct file *file)
+ 		goto out;
+ 	}
+ 
++	up->size = 0;
+ 	spin_lock_irqsave(&uhci->lock, flags);
+-	up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT);
++	if (uhci->is_initialized)
++		up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT);
+ 	spin_unlock_irqrestore(&uhci->lock, flags);
+ 
+ 	file->private_data = up;
+@@ -472,15 +477,32 @@ static int uhci_debug_release(struct inode *inode, struct file *file)
+ 	return 0;
+ }
+ 
++#undef uhci_debug_operations
+ static struct file_operations uhci_debug_operations = {
++	.owner =	THIS_MODULE,
+ 	.open =		uhci_debug_open,
+ 	.llseek =	uhci_debug_lseek,
+ 	.read =		uhci_debug_read,
+ 	.release =	uhci_debug_release,
+ };
+ 
+-#else	/* CONFIG_DEBUG_FS */
++#endif	/* CONFIG_DEBUG_FS */
+ 
+-#define uhci_debug_operations (* (struct file_operations *) NULL)
++#else	/* DEBUG */
++
++static inline void lprintk(char *buf)
++{}
++
++static inline int uhci_show_qh(struct uhci_qh *qh, char *buf,
++		int len, int space)
++{
++	return 0;
++}
++
++static inline int uhci_sprint_schedule(struct uhci_hcd *uhci,
++		char *buf, int len)
++{
++	return 0;
++}
+ 
+ #endif
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 9865f303d3fc..4edb8330c440 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -68,12 +68,16 @@ Alan Stern"
+  * debug = 3, show all TDs in URBs when dumping
+  */
+ #ifdef DEBUG
++#define DEBUG_CONFIGURED	1
+ static int debug = 1;
+-#else
+-static int debug = 0;
+-#endif
+ module_param(debug, int, S_IRUGO | S_IWUSR);
+ MODULE_PARM_DESC(debug, "Debug level");
++
++#else
++#define DEBUG_CONFIGURED	0
++#define debug			0
++#endif
++
+ static char *errbuf;
+ #define ERRBUF_LEN    (32 * 1024)
+ 
+@@ -338,6 +342,12 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
+ 				dev_err(uhci_dev(uhci),
+ 					"host controller halted, "
+ 					"very bad!\n");
++				if (debug > 1 && errbuf) {
++					/* Print the schedule for debugging */
++					uhci_sprint_schedule(uhci,
++							errbuf, ERRBUF_LEN);
++					lprintk(errbuf);
++				}
+ 				hc_died(uhci);
+ 
+ 				/* Force a callback in case there are
+@@ -376,6 +386,14 @@ static void release_uhci(struct uhci_hcd *uhci)
+ {
+ 	int i;
+ 
++	if (DEBUG_CONFIGURED) {
++		spin_lock_irq(&uhci->lock);
++		uhci->is_initialized = 0;
++		spin_unlock_irq(&uhci->lock);
++
++		debugfs_remove(uhci->dentry);
++	}
++
+ 	for (i = 0; i < UHCI_NUM_SKELQH; i++)
+ 		uhci_free_qh(uhci, uhci->skelqh[i]);
+ 
+@@ -390,8 +408,6 @@ static void release_uhci(struct uhci_hcd *uhci)
+ 	dma_free_coherent(uhci_dev(uhci),
+ 			UHCI_NUMFRAMES * sizeof(*uhci->frame),
+ 			uhci->frame, uhci->frame_dma_handle);
+-
+-	debugfs_remove(uhci->dentry);
+ }
+ 
+ static int uhci_reset(struct usb_hcd *hcd)
+@@ -474,17 +490,6 @@ static int uhci_start(struct usb_hcd *hcd)
+ 
+ 	hcd->uses_new_polling = 1;
+ 
+-	dentry = debugfs_create_file(hcd->self.bus_name,
+-			S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, uhci,
+-			&uhci_debug_operations);
+-	if (!dentry) {
+-		dev_err(uhci_dev(uhci),
+-				"couldn't create uhci debugfs entry\n");
+-		retval = -ENOMEM;
+-		goto err_create_debug_entry;
+-	}
+-	uhci->dentry = dentry;
+-
+ 	uhci->fsbr = 0;
+ 	uhci->fsbrtimeout = 0;
+ 
+@@ -495,6 +500,19 @@ static int uhci_start(struct usb_hcd *hcd)
+ 
+ 	init_waitqueue_head(&uhci->waitqh);
+ 
++	if (DEBUG_CONFIGURED) {
++		dentry = debugfs_create_file(hcd->self.bus_name,
++				S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root,
++				uhci, &uhci_debug_operations);
++		if (!dentry) {
++			dev_err(uhci_dev(uhci), "couldn't create uhci "
++					"debugfs entry\n");
++			retval = -ENOMEM;
++			goto err_create_debug_entry;
++		}
++		uhci->dentry = dentry;
++	}
++
+ 	uhci->frame = dma_alloc_coherent(uhci_dev(uhci),
+ 			UHCI_NUMFRAMES * sizeof(*uhci->frame),
+ 			&uhci->frame_dma_handle, 0);
+@@ -609,6 +627,7 @@ static int uhci_start(struct usb_hcd *hcd)
+ 	mb();
+ 
+ 	configure_hc(uhci);
++	uhci->is_initialized = 1;
+ 	start_rh(uhci);
+ 	return 0;
+ 
+@@ -872,16 +891,15 @@ static int __init uhci_hcd_init(void)
+ 	if (usb_disabled())
+ 		return -ENODEV;
+ 
+-	if (debug) {
++	if (DEBUG_CONFIGURED) {
+ 		errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL);
+ 		if (!errbuf)
+ 			goto errbuf_failed;
++		uhci_debugfs_root = debugfs_create_dir("uhci", NULL);
++		if (!uhci_debugfs_root)
++			goto debug_failed;
+ 	}
+ 
+-	uhci_debugfs_root = debugfs_create_dir("uhci", NULL);
+-	if (!uhci_debugfs_root)
+-		goto debug_failed;
+-
+ 	uhci_up_cachep = kmem_cache_create("uhci_urb_priv",
+ 		sizeof(struct urb_priv), 0, 0, NULL, NULL);
+ 	if (!uhci_up_cachep)
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index 7e96bef2e88f..4a69c7eb09bd 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -411,6 +411,7 @@ struct uhci_hcd {
+ 	unsigned int hc_inaccessible:1;		/* HC is suspended or dead */
+ 	unsigned int working_RD:1;		/* Suspended root hub doesn't
+ 						   need to be polled */
++	unsigned int is_initialized:1;		/* Data structure is usable */
+ 
+ 	/* Support for port suspend/resume/reset */
+ 	unsigned long port_c_suspend;		/* Bit-arrays of ports */
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 44bba9a6d196..5d6c4f75d0d8 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -736,7 +736,6 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
+ 		if (errbuf) {
+ 			/* Print the chain for debugging purposes */
+ 			uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
+-
+ 			lprintk(errbuf);
+ 		}
+ 	}
+@@ -924,26 +923,17 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
+ 	ret = uhci_map_status(status, uhci_packetout(td_token(td)));
+ 
+ err:
+-	/* 
+-	 * Enable this chunk of code if you want to see some more debugging.
+-	 * But be careful, it has the tendancy to starve out khubd and prevent
+-	 * disconnects from happening successfully if you have a slow debug
+-	 * log interface (like a serial console.
+-	 */
+-#if 0
+ 	if ((debug == 1 && ret != -EPIPE) || debug > 1) {
+ 		/* Some debugging code */
+ 		dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n",
+ 				__FUNCTION__, status);
+ 
+-		if (errbuf) {
++		if (debug > 1 && errbuf) {
+ 			/* Print the chain for debugging purposes */
+ 			uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
+-
+ 			lprintk(errbuf);
+ 		}
+ 	}
+-#endif
+ 
+ 	/* Note that the queue has stopped and save the next toggle value */
+ 	urbp->qh->element = UHCI_PTR_TERM;

commit 0ed8fee1c1d38a62e981025ba40b5eba30c4ce2a
+Author: Alan Stern 
+Date:   Sat Dec 17 18:02:38 2005 -0500
+
+    [PATCH] UHCI: remove main list of URBs
+    
+    As part of reorienting uhci-hcd away from URBs and toward endpoint
+    queues, this patch (as625) eliminates the driver's main list of URBs.
+    The list wsa used mainly in checking for URB completions; now the driver
+    goes through the list of active endpoints and checks the members of the
+    queues.
+    
+    As a side effect, I had to remove the code that looks for FSBR timeouts.
+    For now, FSBR will remain on so long as any URBs on a full-speed control
+    or bulk queue request it, even if the queue isn't advancing.  A later
+    patch can add more intelligent handling.  This isn't a huge drawback;
+    it's pretty rare for an URB to get stuck for more than a fraction of a
+    second.  (And it will help the people trying to use those insane HP USB
+    devices.)
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
+index 6814783adf91..f2f5f8ce1715 100644
+--- a/drivers/usb/host/uhci-debug.c
++++ b/drivers/usb/host/uhci-debug.c
+@@ -114,7 +114,6 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space)
+ 	}
+ 
+ 	out += sprintf(out, "%s", (urbp->fsbr ? " FSBR" : ""));
+-	out += sprintf(out, "%s", (urbp->fsbr_timeout ? " FSBR_TO" : ""));
+ 
+ 	if (urbp->urb->status != -EINPROGRESS)
+ 		out += sprintf(out, " Status=%d", urbp->urb->status);
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 1ff4b8806372..9865f303d3fc 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -491,8 +491,6 @@ static int uhci_start(struct usb_hcd *hcd)
+ 	spin_lock_init(&uhci->lock);
+ 
+ 	INIT_LIST_HEAD(&uhci->td_remove_list);
+-	INIT_LIST_HEAD(&uhci->urb_list);
+-	INIT_LIST_HEAD(&uhci->complete_list);
+ 	INIT_LIST_HEAD(&uhci->idle_qh_list);
+ 
+ 	init_waitqueue_head(&uhci->waitqh);
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index c057956667b5..7e96bef2e88f 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -132,6 +132,10 @@ struct uhci_qh {
+ 
+ 	unsigned int unlink_frame;	/* When the QH was unlinked */
+ 	int state;			/* QH_STATE_xxx; see above */
++
++	unsigned int initial_toggle:1;	/* Endpoint's current toggle value */
++	unsigned int needs_fixup:1;	/* Must fix the TD toggle values */
++	unsigned int is_stopped:1;	/* Queue was stopped by an error */
+ } __attribute__((aligned(16)));
+ 
+ /*
+@@ -384,6 +388,7 @@ struct uhci_hcd {
+ 
+ 	struct uhci_td *term_td;	/* Terminating TD, see UHCI bug */
+ 	struct uhci_qh *skelqh[UHCI_NUM_SKELQH];	/* Skeleton QHs */
++	struct uhci_qh *next_qh;	/* Next QH to scan */
+ 
+ 	spinlock_t lock;
+ 
+@@ -413,16 +418,10 @@ struct uhci_hcd {
+ 	unsigned long resuming_ports;
+ 	unsigned long ports_timeout;		/* Time to stop signalling */
+ 
+-	/* Main list of URBs currently controlled by this HC */
+-	struct list_head urb_list;
+-
+ 	/* List of TDs that are done, but waiting to be freed (race) */
+ 	struct list_head td_remove_list;
+ 	unsigned int td_remove_age;		/* Age in frames */
+ 
+-	/* List of URBs awaiting completion callback */
+-	struct list_head complete_list;
+-
+ 	struct list_head idle_qh_list;		/* Where the idle QHs live */
+ 
+ 	int rh_numports;			/* Number of root-hub ports */
+@@ -448,7 +447,6 @@ static inline struct usb_hcd *uhci_to_hcd(struct uhci_hcd *uhci)
+  *	Private per-URB data
+  */
+ struct urb_priv {
+-	struct list_head urb_list;
+ 	struct list_head node;		/* Node in the QH's urbp list */
+ 
+ 	struct urb *urb;
+@@ -456,10 +454,7 @@ struct urb_priv {
+ 	struct uhci_qh *qh;		/* QH for this URB */
+ 	struct list_head td_list;
+ 
+-	unsigned long fsbrtime;		/* In jiffies */
+-
+ 	unsigned fsbr : 1;		/* URB turned on FSBR */
+-	unsigned fsbr_timeout : 1;	/* URB timed out on FSBR */
+ 	unsigned short_transfer : 1;	/* URB got a short transfer, no
+ 					 * need to rescan */
+ };
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index c4194182dcc4..44bba9a6d196 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -151,53 +151,6 @@ static void uhci_unlink_isochronous_tds(struct uhci_hcd *uhci, struct urb *urb)
+ 	wmb();
+ }
+ 
+-/*
+- * Remove an URB's TDs from the hardware schedule
+- */
+-static void uhci_remove_tds_from_schedule(struct uhci_hcd *uhci,
+-		struct urb *urb, int status)
+-{
+-	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
+-
+-	/* Isochronous TDs get unlinked directly from the frame list */
+-	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+-		uhci_unlink_isochronous_tds(uhci, urb);
+-		return;
+-	}
+-
+-	/* If the URB isn't first on its queue, adjust the link pointer
+-	 * of the last TD in the previous URB. */
+-	if (urbp->node.prev != &urbp->qh->queue) {
+-		struct urb_priv *purbp;
+-		struct uhci_td *ptd, *ltd;
+-
+-		if (status == -EINPROGRESS)
+-			status = 0;
+-		purbp = list_entry(urbp->node.prev, struct urb_priv, node);
+-		ptd = list_entry(purbp->td_list.prev, struct uhci_td,
+-				list);
+-		ltd = list_entry(urbp->td_list.prev, struct uhci_td,
+-				list);
+-		ptd->link = ltd->link;
+-	}
+-
+-	/* If the URB completed with an error, then the QH element certainly
+-	 * points to one of the URB's TDs.  If it completed normally then
+-	 * the QH element has certainly moved on to the next URB.  And if
+-	 * the URB is still in progress then it must have been dequeued.
+-	 * The QH element either hasn't reached it yet or is somewhere in
+-	 * the middle.  If the URB wasn't first we can assume that it
+-	 * hasn't started yet (see above): Otherwise all the preceding URBs
+-	 * would have completed and been removed from the queue, so this one
+-	 * _would_ be first.
+-	 *
+-	 * If the QH element is inside this URB, clear it.  It will be
+-	 * set properly when the QH is activated.
+-	 */
+-	if (status < 0)
+-		urbp->qh->element = UHCI_PTR_TERM;
+-}
+-
+ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci,
+ 		struct usb_device *udev, struct usb_host_endpoint *hep)
+ {
+@@ -250,6 +203,90 @@ static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ 	dma_pool_free(uhci->qh_pool, qh, qh->dma_handle);
+ }
+ 
++/*
++ * When the currently executing URB is dequeued, save its current toggle value
++ */
++static void uhci_save_toggle(struct uhci_qh *qh, struct urb *urb)
++{
++	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
++	struct uhci_td *td;
++
++	/* If the QH element pointer is UHCI_PTR_TERM then then currently
++	 * executing URB has already been unlinked, so this one isn't it. */
++	if (qh_element(qh) == UHCI_PTR_TERM ||
++				qh->queue.next != &urbp->node)
++		return;
++	qh->element = UHCI_PTR_TERM;
++
++	/* Only bulk and interrupt pipes have to worry about toggles */
++	if (!(usb_pipetype(urb->pipe) == PIPE_BULK ||
++			usb_pipetype(urb->pipe) == PIPE_INTERRUPT))
++		return;
++
++	/* Find the first active TD; that's the device's toggle state */
++	list_for_each_entry(td, &urbp->td_list, list) {
++		if (td_status(td) & TD_CTRL_ACTIVE) {
++			qh->needs_fixup = 1;
++			qh->initial_toggle = uhci_toggle(td_token(td));
++			return;
++		}
++	}
++
++	WARN_ON(1);
++}
++
++/*
++ * Fix up the data toggles for URBs in a queue, when one of them
++ * terminates early (short transfer, error, or dequeued).
++ */
++static void uhci_fixup_toggles(struct uhci_qh *qh, int skip_first)
++{
++	struct urb_priv *urbp = NULL;
++	struct uhci_td *td;
++	unsigned int toggle = qh->initial_toggle;
++	unsigned int pipe;
++
++	/* Fixups for a short transfer start with the second URB in the
++	 * queue (the short URB is the first). */
++	if (skip_first)
++		urbp = list_entry(qh->queue.next, struct urb_priv, node);
++
++	/* When starting with the first URB, if the QH element pointer is
++	 * still valid then we know the URB's toggles are okay. */
++	else if (qh_element(qh) != UHCI_PTR_TERM)
++		toggle = 2;
++
++	/* Fix up the toggle for the URBs in the queue.  Normally this
++	 * loop won't run more than once: When an error or short transfer
++	 * occurs, the queue usually gets emptied. */
++	list_prepare_entry(urbp, &qh->queue, node);
++	list_for_each_entry_continue(urbp, &qh->queue, node) {
++
++		/* If the first TD has the right toggle value, we don't
++		 * need to change any toggles in this URB */
++		td = list_entry(urbp->td_list.next, struct uhci_td, list);
++		if (toggle > 1 || uhci_toggle(td_token(td)) == toggle) {
++			td = list_entry(urbp->td_list.next, struct uhci_td,
++					list);
++			toggle = uhci_toggle(td_token(td)) ^ 1;
++
++		/* Otherwise all the toggles in the URB have to be switched */
++		} else {
++			list_for_each_entry(td, &urbp->td_list, list) {
++				td->token ^= __constant_cpu_to_le32(
++							TD_TOKEN_TOGGLE);
++				toggle ^= 1;
++			}
++		}
++	}
++
++	wmb();
++	pipe = list_entry(qh->queue.next, struct urb_priv, node)->urb->pipe;
++	usb_settoggle(qh->udev, usb_pipeendpoint(pipe),
++			usb_pipeout(pipe), toggle);
++	qh->needs_fixup = 0;
++}
++
+ /*
+  * Put a QH on the schedule in both hardware and software
+  */
+@@ -276,6 +313,9 @@ static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ 
+ 	/* Move the QH from its old list to the end of the appropriate
+ 	 * skeleton's list */
++	if (qh == uhci->next_qh)
++		uhci->next_qh = list_entry(qh->node.next, struct uhci_qh,
++				node);
+ 	list_move_tail(&qh->node, &qh->skel->node);
+ 
+ 	/* Link it into the schedule */
+@@ -310,6 +350,9 @@ static void uhci_unlink_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ 		uhci_set_next_interrupt(uhci);
+ 
+ 	/* Move the QH from its old list to the end of the unlinking list */
++	if (qh == uhci->next_qh)
++		uhci->next_qh = list_entry(qh->node.next, struct uhci_qh,
++				node);
+ 	list_move_tail(&qh->node, &uhci->skel_unlink_qh->node);
+ }
+ 
+@@ -323,6 +366,9 @@ static void uhci_make_qh_idle(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ {
+ 	WARN_ON(qh->state == QH_STATE_ACTIVE);
+ 
++	if (qh == uhci->next_qh)
++		uhci->next_qh = list_entry(qh->node.next, struct uhci_qh,
++				node);
+ 	list_move(&qh->node, &uhci->idle_qh_list);
+ 	qh->state = QH_STATE_IDLE;
+ 
+@@ -344,11 +390,9 @@ static inline struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci,
+ 
+ 	urbp->urb = urb;
+ 	urb->hcpriv = urbp;
+-	urbp->fsbrtime = jiffies;
+ 	
+ 	INIT_LIST_HEAD(&urbp->node);
+ 	INIT_LIST_HEAD(&urbp->td_list);
+-	INIT_LIST_HEAD(&urbp->urb_list);
+ 
+ 	return urbp;
+ }
+@@ -373,9 +417,6 @@ static void uhci_free_urb_priv(struct uhci_hcd *uhci,
+ {
+ 	struct uhci_td *td, *tmp;
+ 
+-	if (!list_empty(&urbp->urb_list))
+-		dev_warn(uhci_dev(uhci), "urb %p still on uhci->urb_list!\n",
+-				urbp->urb);
+ 	if (!list_empty(&urbp->node))
+ 		dev_warn(uhci_dev(uhci), "urb %p still on QH's list!\n",
+ 				urbp->urb);
+@@ -452,71 +493,6 @@ static int uhci_map_status(int status, int dir_out)
+ 	return 0;
+ }
+ 
+-/*
+- * Fix up the data toggles for URBs in a queue, when one of them
+- * terminates early (short transfer, error, or dequeued).
+- */
+-static void uhci_fixup_toggles(struct urb *urb)
+-{
+-	struct list_head *head;
+-	struct uhci_td *td;
+-	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
+-	int prevactive = 0;
+-	unsigned int toggle = 0;
+-	struct urb_priv *turbp, *list_end;
+-
+-	/*
+-	 * We need to find out what the last successful toggle was so
+-	 * we can update the data toggles for the following transfers.
+-	 *
+-	 * There are 2 ways the last successful completed TD is found:
+-	 *
+-	 * 1) The TD is NOT active and the actual length < expected length
+-	 * 2) The TD is NOT active and it's the last TD in the chain
+-	 *
+-	 * and a third way the first uncompleted TD is found:
+-	 *
+-	 * 3) The TD is active and the previous TD is NOT active
+-	 */
+-	head = &urbp->td_list;
+-	list_for_each_entry(td, head, list) {
+-		unsigned int ctrlstat = td_status(td);
+-
+-		if (!(ctrlstat & TD_CTRL_ACTIVE) &&
+-				(uhci_actual_length(ctrlstat) <
+-				 uhci_expected_length(td_token(td)) ||
+-				td->list.next == head))
+-			toggle = uhci_toggle(td_token(td)) ^ 1;
+-		else if ((ctrlstat & TD_CTRL_ACTIVE) && !prevactive)
+-			toggle = uhci_toggle(td_token(td));
+-
+-		prevactive = ctrlstat & TD_CTRL_ACTIVE;
+-	}
+-
+-	/*
+-	 * Fix up the toggle for the following URBs in the queue.
+-	 *
+-	 * We can stop as soon as we find an URB with toggles set correctly,
+-	 * because then all the following URBs will be correct also.
+-	 */
+-	list_end = list_entry(&urbp->qh->queue, struct urb_priv, node);
+-	turbp = urbp;
+-	while ((turbp = list_entry(turbp->node.next, struct urb_priv, node))
+-			!= list_end) {
+-		td = list_entry(turbp->td_list.next, struct uhci_td, list);
+-		if (uhci_toggle(td_token(td)) == toggle)
+-			return;
+-
+-		list_for_each_entry(td, &turbp->td_list, list) {
+-			td->token ^= __constant_cpu_to_le32(TD_TOKEN_TOGGLE);
+-			toggle ^= 1;
+-		}
+-	}
+-
+-	usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+-			usb_pipeout(urb->pipe), toggle);
+-}
+-
+ /*
+  * Control transfers
+  */
+@@ -765,6 +741,9 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
+ 		}
+ 	}
+ 
++	/* Note that the queue has stopped */
++	urbp->qh->element = UHCI_PTR_TERM;
++	urbp->qh->is_stopped = 1;
+ 	return ret;
+ }
+ 
+@@ -927,7 +906,10 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
+ 			 */
+ 			if (!urbp->short_transfer) {
+ 				urbp->short_transfer = 1;
+-				uhci_fixup_toggles(urb);
++				urbp->qh->initial_toggle =
++						uhci_toggle(td_token(td)) ^ 1;
++				uhci_fixup_toggles(urbp->qh, 1);
++
+ 				td = list_entry(urbp->td_list.prev,
+ 						struct uhci_td, list);
+ 				urbp->qh->element = td->link;
+@@ -962,6 +944,13 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
+ 		}
+ 	}
+ #endif
++
++	/* Note that the queue has stopped and save the next toggle value */
++	urbp->qh->element = UHCI_PTR_TERM;
++	urbp->qh->is_stopped = 1;
++	urbp->qh->needs_fixup = 1;
++	urbp->qh->initial_toggle = uhci_toggle(td_token(td)) ^
++			(ret == -EREMOTEIO);
+ 	return ret;
+ }
+ 
+@@ -995,76 +984,39 @@ static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb,
+ /*
+  * Isochronous transfers
+  */
+-static int isochronous_find_limits(struct uhci_hcd *uhci, struct urb *urb, unsigned int *start, unsigned int *end)
+-{
+-	struct urb *last_urb = NULL;
+-	struct urb_priv *up;
+-	int ret = 0;
+-
+-	list_for_each_entry(up, &uhci->urb_list, urb_list) {
+-		struct urb *u = up->urb;
+-
+-		/* look for pending URBs with identical pipe handle */
+-		if ((urb->pipe == u->pipe) && (urb->dev == u->dev) &&
+-		    (u->status == -EINPROGRESS) && (u != urb)) {
+-			if (!last_urb)
+-				*start = u->start_frame;
+-			last_urb = u;
+-		}
+-	}
+-
+-	if (last_urb) {
+-		*end = (last_urb->start_frame + last_urb->number_of_packets *
+-				last_urb->interval) & (UHCI_NUMFRAMES-1);
+-		ret = 0;
+-	} else
+-		ret = -1;	/* no previous urb found */
+-
+-	return ret;
+-}
+-
+-static int isochronous_find_start(struct uhci_hcd *uhci, struct urb *urb)
++static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
++		struct uhci_qh *qh)
+ {
+-	int limits;
+-	unsigned int start = 0, end = 0;
++	struct uhci_td *td = NULL;	/* Since urb->number_of_packets > 0 */
++	int i, frame;
++	unsigned long destination, status;
++	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
+ 
+ 	if (urb->number_of_packets > 900)	/* 900? Why? */
+ 		return -EFBIG;
+ 
+-	limits = isochronous_find_limits(uhci, urb, &start, &end);
++	status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
++	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
+ 
++	/* Figure out the starting frame number */
+ 	if (urb->transfer_flags & URB_ISO_ASAP) {
+-		if (limits) {
++		if (list_empty(&qh->queue)) {
+ 			uhci_get_current_frame_number(uhci);
+-			urb->start_frame = (uhci->frame_number + 10)
+-					& (UHCI_NUMFRAMES - 1);
+-		} else
+-			urb->start_frame = end;
++			urb->start_frame = (uhci->frame_number + 10);
++
++		} else {		/* Go right after the last one */
++			struct urb *last_urb;
++
++			last_urb = list_entry(qh->queue.prev,
++					struct urb_priv, node)->urb;
++			urb->start_frame = (last_urb->start_frame +
++					last_urb->number_of_packets *
++					last_urb->interval);
++		}
+ 	} else {
+-		urb->start_frame &= (UHCI_NUMFRAMES - 1);
+ 		/* FIXME: Sanity check */
+ 	}
+-
+-	return 0;
+-}
+-
+-/*
+- * Isochronous transfers
+- */
+-static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
+-		struct uhci_qh *qh)
+-{
+-	struct uhci_td *td = NULL;	/* Since urb->number_of_packets > 0 */
+-	int i, ret, frame;
+-	unsigned long destination, status;
+-	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
+-
+-	status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
+-	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
+-
+-	ret = isochronous_find_start(uhci, urb);
+-	if (ret)
+-		return ret;
++	urb->start_frame &= (UHCI_NUMFRAMES - 1);
+ 
+ 	for (i = 0; i < urb->number_of_packets; i++) {
+ 		td = uhci_alloc_td(uhci);
+@@ -1203,7 +1155,6 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd,
+ 	/* Add this URB to the QH */
+ 	urbp->qh = qh;
+ 	list_add_tail(&urbp->node, &qh->queue);
+-	list_add_tail(&urbp->urb_list, &uhci->urb_list);
+ 
+ 	/* If the new URB is the first and only one on this QH then either
+ 	 * the QH is new and idle or else it's unlinked and waiting to
+@@ -1224,49 +1175,66 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd,
+ 	return ret;
+ }
+ 
++static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
++{
++	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++	unsigned long flags;
++	struct urb_priv *urbp;
++
++	spin_lock_irqsave(&uhci->lock, flags);
++	urbp = urb->hcpriv;
++	if (!urbp)			/* URB was never linked! */
++		goto done;
++
++	/* Remove Isochronous TDs from the frame list ASAP */
++	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
++		uhci_unlink_isochronous_tds(uhci, urb);
++	uhci_unlink_qh(uhci, urbp->qh);
++
++done:
++	spin_unlock_irqrestore(&uhci->lock, flags);
++	return 0;
++}
++
+ /*
+- * Return the result of a transfer
++ * Finish unlinking an URB and give it back
+  */
+-static void uhci_transfer_result(struct uhci_hcd *uhci, struct urb *urb)
++static void uhci_giveback_urb(struct uhci_hcd *uhci, struct uhci_qh *qh,
++		struct urb *urb, struct pt_regs *regs)
++__releases(uhci->lock)
++__acquires(uhci->lock)
+ {
+-	int status;
+-	int okay_to_giveback = 0;
+ 	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
+ 
+-	switch (usb_pipetype(urb->pipe)) {
+-	case PIPE_CONTROL:
+-		status = uhci_result_control(uhci, urb);
+-		break;
+-	case PIPE_ISOCHRONOUS:
+-		status = uhci_result_isochronous(uhci, urb);
+-		break;
+-	default:	/* PIPE_BULK or PIPE_INTERRUPT */
+-		status = uhci_result_common(uhci, urb);
+-		break;
+-	}
++	/* Isochronous TDs get unlinked directly from the frame list */
++	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
++		uhci_unlink_isochronous_tds(uhci, urb);
+ 
+-	spin_lock(&urb->lock);
+-	if (urb->status == -EINPROGRESS) {	/* Not yet dequeued */
+-		if (status != -EINPROGRESS) {	/* URB has completed */
+-			urb->status = status;
++	/* If the URB isn't first on its queue, adjust the link pointer
++	 * of the last TD in the previous URB. */
++	else if (qh->queue.next != &urbp->node) {
++		struct urb_priv *purbp;
++		struct uhci_td *ptd, *ltd;
+ 
+-			/* If the URB got a real error (as opposed to
+-			 * simply being dequeued), we don't have to
+-			 * unlink the QH.  Fix this later... */
+-			if (status < 0)
+-				uhci_unlink_qh(uhci, urbp->qh);
+-			else
+-				okay_to_giveback = 1;
+-		}
+-	} else {				/* Already dequeued */
+-		if (urbp->qh->state == QH_STATE_UNLINKING &&
+-				uhci->frame_number + uhci->is_stopped !=
+-				urbp->qh->unlink_frame)
+-			okay_to_giveback = 1;
++		purbp = list_entry(urbp->node.prev, struct urb_priv, node);
++		ptd = list_entry(purbp->td_list.prev, struct uhci_td,
++				list);
++		ltd = list_entry(urbp->td_list.prev, struct uhci_td,
++				list);
++		ptd->link = ltd->link;
+ 	}
+-	spin_unlock(&urb->lock);
+-	if (!okay_to_giveback)
+-		return;
++
++	/* Take the URB off the QH's queue.  If the queue is now empty,
++	 * this is a perfect time for a toggle fixup. */
++	list_del_init(&urbp->node);
++	if (list_empty(&qh->queue) && qh->needs_fixup) {
++		usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
++				usb_pipeout(urb->pipe), qh->initial_toggle);
++		qh->needs_fixup = 0;
++	}
++
++	uhci_dec_fsbr(uhci, urb);	/* Safe since it checks */
++	uhci_free_urb_priv(uhci, urbp);
+ 
+ 	switch (usb_pipetype(urb->pipe)) {
+ 	case PIPE_ISOCHRONOUS:
+@@ -1277,122 +1245,107 @@ static void uhci_transfer_result(struct uhci_hcd *uhci, struct urb *urb)
+ 	case PIPE_INTERRUPT:
+ 		/* Release bandwidth for Interrupt or Isoc. transfers */
+ 		/* Make sure we don't release if we have a queued URB */
+-		if (list_empty(&urbp->qh->queue) && urb->bandwidth)
++		if (list_empty(&qh->queue) && urb->bandwidth)
+ 			usb_release_bandwidth(urb->dev, urb, 0);
+ 		else
+ 			/* bandwidth was passed on to queued URB, */
+ 			/* so don't let usb_unlink_urb() release it */
+ 			urb->bandwidth = 0;
+-		/* Falls through */
+-	case PIPE_BULK:
+-		if (status < 0)
+-			uhci_fixup_toggles(urb);
+-		break;
+-	default:	/* PIPE_CONTROL */
+ 		break;
+ 	}
+ 
+-	/* Take the URB's TDs off the hardware schedule */
+-	uhci_remove_tds_from_schedule(uhci, urb, status);
+-
+-	/* Take the URB off the QH's queue and see if the QH is now unused */
+-	list_del_init(&urbp->node);
+-	if (list_empty(&urbp->qh->queue))
+-		uhci_unlink_qh(uhci, urbp->qh);
++	spin_unlock(&uhci->lock);
++	usb_hcd_giveback_urb(uhci_to_hcd(uhci), urb, regs);
++	spin_lock(&uhci->lock);
+ 
+-	uhci_dec_fsbr(uhci, urb);	/* Safe since it checks */
++	/* If the queue is now empty, we can unlink the QH and give up its
++	 * reserved bandwidth. */
++	if (list_empty(&qh->queue)) {
++		uhci_unlink_qh(uhci, qh);
+ 
+-	/* Queue it for giving back */
+-	list_move_tail(&urbp->urb_list, &uhci->complete_list);
++		/* Bandwidth stuff not yet implemented */
++	}
+ }
+ 
+ /*
+- * Check out the QHs waiting to be fully unlinked
++ * Scan the URBs in a QH's queue
+  */
+-static void uhci_scan_unlinking_qhs(struct uhci_hcd *uhci)
+-{
+-	struct uhci_qh *qh, *tmp;
++#define QH_FINISHED_UNLINKING(qh)			\
++		(qh->state == QH_STATE_UNLINKING &&	\
++		uhci->frame_number + uhci->is_stopped != qh->unlink_frame)
+ 
+-	list_for_each_entry_safe(qh, tmp, &uhci->skel_unlink_qh->node, node) {
+-
+-		/* If the queue is empty and the QH is fully unlinked then
+-		 * it can become IDLE. */
+-		if (list_empty(&qh->queue)) {
+-			if (uhci->frame_number + uhci->is_stopped !=
+-					qh->unlink_frame)
+-				uhci_make_qh_idle(uhci, qh);
+-
+-		/* If none of the QH's URBs have been dequeued then the QH
+-		 * should be re-activated. */
+-		} else {
+-			struct urb_priv *urbp;
+-			int any_dequeued = 0;
+-
+-			list_for_each_entry(urbp, &qh->queue, node) {
+-				if (urbp->urb->status != -EINPROGRESS) {
+-					any_dequeued = 1;
+-					break;
+-				}
+-			}
+-			if (!any_dequeued)
+-				uhci_activate_qh(uhci, qh);
+-		}
+-	}
+-}
+-
+-static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
++static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh,
++		struct pt_regs *regs)
+ {
+-	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+-	unsigned long flags;
+ 	struct urb_priv *urbp;
++	struct urb *urb;
++	int status;
+ 
+-	spin_lock_irqsave(&uhci->lock, flags);
+-	urbp = urb->hcpriv;
+-	if (!urbp)			/* URB was never linked! */
+-		goto done;
++	while (!list_empty(&qh->queue)) {
++		urbp = list_entry(qh->queue.next, struct urb_priv, node);
++		urb = urbp->urb;
+ 
+-	/* Remove Isochronous TDs from the frame list ASAP */
+-	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
+-		uhci_unlink_isochronous_tds(uhci, urb);
+-	uhci_unlink_qh(uhci, urbp->qh);
++		switch (usb_pipetype(urb->pipe)) {
++		case PIPE_CONTROL:
++			status = uhci_result_control(uhci, urb);
++			break;
++		case PIPE_ISOCHRONOUS:
++			status = uhci_result_isochronous(uhci, urb);
++			break;
++		default:	/* PIPE_BULK or PIPE_INTERRUPT */
++			status = uhci_result_common(uhci, urb);
++			break;
++		}
++		if (status == -EINPROGRESS)
++			break;
+ 
+-done:
+-	spin_unlock_irqrestore(&uhci->lock, flags);
+-	return 0;
+-}
++		spin_lock(&urb->lock);
++		if (urb->status == -EINPROGRESS)	/* Not dequeued */
++			urb->status = status;
++		else
++			status = -ECONNRESET;
++		spin_unlock(&urb->lock);
+ 
+-static int uhci_fsbr_timeout(struct uhci_hcd *uhci, struct urb *urb)
+-{
+-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+-	struct list_head *head;
+-	struct uhci_td *td;
+-	int count = 0;
++		/* Dequeued but completed URBs can't be given back unless
++		 * the QH is stopped or has finished unlinking. */
++		if (status == -ECONNRESET &&
++				!(qh->is_stopped || QH_FINISHED_UNLINKING(qh)))
++			return;
+ 
+-	uhci_dec_fsbr(uhci, urb);
++		uhci_giveback_urb(uhci, qh, urb, regs);
++		if (qh->is_stopped)
++			break;
++	}
+ 
+-	urbp->fsbr_timeout = 1;
++	/* If the QH is neither stopped nor finished unlinking (normal case),
++	 * our work here is done. */
++ restart:
++	if (!(qh->is_stopped || QH_FINISHED_UNLINKING(qh)))
++		return;
+ 
+-	/*
+-	 * Ideally we would want to fix qh->element as well, but it's
+-	 * read/write by the HC, so that can introduce a race. It's not
+-	 * really worth the hassle
+-	 */
++	/* Otherwise give back each of the dequeued URBs */
++	list_for_each_entry(urbp, &qh->queue, node) {
++		urb = urbp->urb;
++		if (urb->status != -EINPROGRESS) {
++			uhci_save_toggle(qh, urb);
++			uhci_giveback_urb(uhci, qh, urb, regs);
++			goto restart;
++		}
++	}
++	qh->is_stopped = 0;
+ 
+-	head = &urbp->td_list;
+-	list_for_each_entry(td, head, list) {
+-		/*
+-		 * Make sure we don't do the last one (since it'll have the
+-		 * TERM bit set) as well as we skip every so many TDs to
+-		 * make sure it doesn't hog the bandwidth
+-		 */
+-		if (td->list.next != head && (count % DEPTH_INTERVAL) ==
+-				(DEPTH_INTERVAL - 1))
+-			td->link |= UHCI_PTR_DEPTH;
+-
+-		count++;
++	/* There are no more dequeued URBs.  If there are still URBs on the
++	 * queue, the QH can now be re-activated. */
++	if (!list_empty(&qh->queue)) {
++		if (qh->needs_fixup)
++			uhci_fixup_toggles(qh, 0);
++		uhci_activate_qh(uhci, qh);
+ 	}
+ 
+-	return 0;
++	/* The queue is empty.  The QH can become idle if it is fully
++	 * unlinked. */
++	else if (QH_FINISHED_UNLINKING(qh))
++		uhci_make_qh_idle(uhci, qh);
+ }
+ 
+ static void uhci_free_pending_tds(struct uhci_hcd *uhci)
+@@ -1406,36 +1359,13 @@ static void uhci_free_pending_tds(struct uhci_hcd *uhci)
+ 	}
+ }
+ 
+-static void
+-uhci_finish_urb(struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs)
+-__releases(uhci->lock)
+-__acquires(uhci->lock)
+-{
+-	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+-
+-	uhci_free_urb_priv(uhci, (struct urb_priv *) (urb->hcpriv));
+-
+-	spin_unlock(&uhci->lock);
+-	usb_hcd_giveback_urb(hcd, urb, regs);
+-	spin_lock(&uhci->lock);
+-}
+-
+-static void uhci_finish_completion(struct uhci_hcd *uhci, struct pt_regs *regs)
+-{
+-	struct urb_priv *urbp, *tmp;
+-
+-	list_for_each_entry_safe(urbp, tmp, &uhci->complete_list, urb_list) {
+-		struct urb *urb = urbp->urb;
+-
+-		list_del_init(&urbp->urb_list);
+-		uhci_finish_urb(uhci_to_hcd(uhci), urb, regs);
+-	}
+-}
+-
+-/* Process events in the schedule, but only in one thread at a time */
++/*
++ * Process events in the schedule, but only in one thread at a time
++ */
+ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs)
+ {
+-	struct urb_priv *urbp, *tmp;
++	int i;
++	struct uhci_qh *qh;
+ 
+ 	/* Don't allow re-entrant calls */
+ 	if (uhci->scan_in_progress) {
+@@ -1452,26 +1382,24 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs)
+ 	if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age)
+ 		uhci_free_pending_tds(uhci);
+ 
+-	/* Walk the list of pending URBs to see which ones completed
+-	 * (must be _safe because uhci_transfer_result() dequeues URBs) */
+-	list_for_each_entry_safe(urbp, tmp, &uhci->urb_list, urb_list) {
+-		struct urb *urb = urbp->urb;
+-
+-		/* Checks the status and does all of the magic necessary */
+-		uhci_transfer_result(uhci, urb);
++	/* Go through all the QH queues and process the URBs in each one */
++	for (i = 0; i < UHCI_NUM_SKELQH - 1; ++i) {
++		uhci->next_qh = list_entry(uhci->skelqh[i]->node.next,
++				struct uhci_qh, node);
++		while ((qh = uhci->next_qh) != uhci->skelqh[i]) {
++			uhci->next_qh = list_entry(qh->node.next,
++					struct uhci_qh, node);
++			uhci_scan_qh(uhci, qh, regs);
++		}
+ 	}
+-	uhci_finish_completion(uhci, regs);
+-
+-	/* If the controller is stopped, we can finish these off right now */
+-	if (uhci->is_stopped)
+-		uhci_free_pending_tds(uhci);
+ 
+ 	if (uhci->need_rescan)
+ 		goto rescan;
+ 	uhci->scan_in_progress = 0;
+ 
+-	/* Check out the QHs waiting for unlinking */
+-	uhci_scan_unlinking_qhs(uhci);
++	/* If the controller is stopped, we can finish these off right now */
++	if (uhci->is_stopped)
++		uhci_free_pending_tds(uhci);
+ 
+ 	if (list_empty(&uhci->td_remove_list) &&
+ 			list_empty(&uhci->skel_unlink_qh->node))
+@@ -1482,19 +1410,8 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs)
+ 
+ static void check_fsbr(struct uhci_hcd *uhci)
+ {
+-	struct urb_priv *up;
+-
+-	list_for_each_entry(up, &uhci->urb_list, urb_list) {
+-		struct urb *u = up->urb;
+-
+-		spin_lock(&u->lock);
+-
+-		/* Check if the FSBR timed out */
+-		if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT))
+-			uhci_fsbr_timeout(uhci, u);
+-
+-		spin_unlock(&u->lock);
+-	}
++	/* For now, don't scan URBs for FSBR timeouts.
++	 * Add it back in later... */
+ 
+ 	/* Really disable FSBR */
+ 	if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) {

commit af0bb5998abe8ed28ee354dd4c71689cacdc91e9
+Author: Alan Stern 
+Date:   Sat Dec 17 18:00:12 2005 -0500
+
+    [PATCH] UHCI: use dummy TDs
+    
+    This patch (as624) fixes a hardware race in uhci-hcd by adding a dummy
+    TD to the end of each endpoint's queue.  Without the dummy the host
+    controller will effectively turn off the queue when it reaches the end,
+    which happens asynchronously.  This leads to a potential problem when
+    new transfer descriptors are added to the end of the queue; they may
+    never get used.
+    
+    With a dummy TD present the controller never turns off the queue;
+    instead it just stops at the dummy and leaves the queue on but inactive.
+    When new TDs are added to the end of the queue, the first new one gets
+    written over the dummy.  Thus there's never any question about whether
+    the queue is running or needs to be restarted.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
+index 3faccbd68547..6814783adf91 100644
+--- a/drivers/usb/host/uhci-debug.c
++++ b/drivers/usb/host/uhci-debug.c
+@@ -189,6 +189,11 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
+ 					space, "", nurbs);
+ 	}
+ 
++	if (qh->udev) {
++		out += sprintf(out, "%*s  Dummy TD\n", space, "");
++		out += uhci_show_td(qh->dummy_td, out, len - (out - buf), 0);
++	}
++
+ 	return out - buf;
+ }
+ 
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index 7a9481c09a05..c057956667b5 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -128,6 +128,7 @@ struct uhci_qh {
+ 	struct usb_device *udev;
+ 	struct list_head queue;		/* Queue of urbps for this QH */
+ 	struct uhci_qh *skel;		/* Skeleton for this QH */
++	struct uhci_td *dummy_td;	/* Dummy TD to end the queue */
+ 
+ 	unsigned int unlink_frame;	/* When the QH was unlinked */
+ 	int state;			/* QH_STATE_xxx; see above */
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index b1b551a3d14e..c4194182dcc4 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -48,10 +48,6 @@ static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci)
+ 		return NULL;
+ 
+ 	td->dma_handle = dma_handle;
+-
+-	td->link = UHCI_PTR_TERM;
+-	td->buffer = 0;
+-
+ 	td->frame = -1;
+ 
+ 	INIT_LIST_HEAD(&td->list);
+@@ -221,6 +217,11 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci,
+ 	INIT_LIST_HEAD(&qh->node);
+ 
+ 	if (udev) {		/* Normal QH */
++		qh->dummy_td = uhci_alloc_td(uhci);
++		if (!qh->dummy_td) {
++			dma_pool_free(uhci->qh_pool, qh, dma_handle);
++			return NULL;
++		}
+ 		qh->state = QH_STATE_IDLE;
+ 		qh->hep = hep;
+ 		qh->udev = udev;
+@@ -244,6 +245,7 @@ static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ 	if (qh->udev) {
+ 		qh->hep->hcpriv = NULL;
+ 		usb_put_dev(qh->udev);
++		uhci_free_td(uhci, qh->dummy_td);
+ 	}
+ 	dma_pool_free(uhci->qh_pool, qh, qh->dma_handle);
+ }
+@@ -531,22 +533,20 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
+ 	/* The "pipe" thing contains the destination in bits 8--18 */
+ 	destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
+ 
+-	/* 3 errors */
+-	status = TD_CTRL_ACTIVE | uhci_maxerr(3);
++	/* 3 errors, dummy TD remains inactive */
++	status = uhci_maxerr(3);
+ 	if (urb->dev->speed == USB_SPEED_LOW)
+ 		status |= TD_CTRL_LS;
+ 
+ 	/*
+ 	 * Build the TD for the control request setup packet
+ 	 */
+-	td = uhci_alloc_td(uhci);
+-	if (!td)
+-		return -ENOMEM;
+-
++	td = qh->dummy_td;
+ 	uhci_add_td_to_urb(urb, td);
+ 	uhci_fill_td(td, status, destination | uhci_explen(8),
+ 			urb->setup_dma);
+ 	plink = &td->link;
++	status |= TD_CTRL_ACTIVE;
+ 
+ 	/*
+ 	 * If direction is "send", change the packet ID from SETUP (0x2D)
+@@ -568,7 +568,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
+ 
+ 		td = uhci_alloc_td(uhci);
+ 		if (!td)
+-			return -ENOMEM;
++			goto nomem;
+ 		*plink = cpu_to_le32(td->dma_handle);
+ 
+ 		/* Alternate Data0/1 (start with Data1) */
+@@ -588,7 +588,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
+ 	 */
+ 	td = uhci_alloc_td(uhci);
+ 	if (!td)
+-		return -ENOMEM;
++		goto nomem;
+ 	*plink = cpu_to_le32(td->dma_handle);
+ 
+ 	/*
+@@ -608,6 +608,20 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
+ 	uhci_add_td_to_urb(urb, td);
+ 	uhci_fill_td(td, status | TD_CTRL_IOC,
+ 			destination | uhci_explen(0), 0);
++	plink = &td->link;
++
++	/*
++	 * Build the new dummy TD and activate the old one
++	 */
++	td = uhci_alloc_td(uhci);
++	if (!td)
++		goto nomem;
++	*plink = cpu_to_le32(td->dma_handle);
++
++	uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0);
++	wmb();
++	qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE);
++	qh->dummy_td = td;
+ 
+ 	/* Low-speed transfers get a different queue, and won't hog the bus.
+ 	 * Also, some devices enumerate better without FSBR; the easiest way
+@@ -620,8 +634,12 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
+ 		qh->skel = uhci->skel_fs_control_qh;
+ 		uhci_inc_fsbr(uhci, urb);
+ 	}
+-
+ 	return 0;
++
++nomem:
++	/* Remove the dummy TD from the td_list so it doesn't get freed */
++	uhci_remove_td_from_urb(qh->dummy_td);
++	return -ENOMEM;
+ }
+ 
+ /*
+@@ -761,16 +779,19 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
+ 	int maxsze = le16_to_cpu(qh->hep->desc.wMaxPacketSize);
+ 	int len = urb->transfer_buffer_length;
+ 	dma_addr_t data = urb->transfer_dma;
+-	__le32 *plink, fake_link;
++	__le32 *plink;
++	unsigned int toggle;
+ 
+ 	if (len < 0)
+ 		return -EINVAL;
+ 
+ 	/* The "pipe" thing contains the destination in bits 8--18 */
+ 	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
++	toggle = usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
++			 usb_pipeout(urb->pipe));
+ 
+-	/* 3 errors */
+-	status = TD_CTRL_ACTIVE | uhci_maxerr(3);
++	/* 3 errors, dummy TD remains inactive */
++	status = uhci_maxerr(3);
+ 	if (urb->dev->speed == USB_SPEED_LOW)
+ 		status |= TD_CTRL_LS;
+ 	if (usb_pipein(urb->pipe))
+@@ -779,7 +800,8 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
+ 	/*
+ 	 * Build the DATA TDs
+ 	 */
+-	plink = &fake_link;
++	plink = NULL;
++	td = qh->dummy_td;
+ 	do {	/* Allow zero length packets */
+ 		int pktsze = maxsze;
+ 
+@@ -789,24 +811,23 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
+ 				status &= ~TD_CTRL_SPD;
+ 		}
+ 
+-		td = uhci_alloc_td(uhci);
+-		if (!td)
+-			return -ENOMEM;
+-		*plink = cpu_to_le32(td->dma_handle);
+-
++		if (plink) {
++			td = uhci_alloc_td(uhci);
++			if (!td)
++				goto nomem;
++			*plink = cpu_to_le32(td->dma_handle);
++		}
+ 		uhci_add_td_to_urb(urb, td);
+ 		uhci_fill_td(td, status,
+-			destination | uhci_explen(pktsze) |
+-			(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+-			 usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
+-			data);
++				destination | uhci_explen(pktsze) |
++					(toggle << TD_TOKEN_TOGGLE_SHIFT),
++				data);
+ 		plink = &td->link;
++		status |= TD_CTRL_ACTIVE;
+ 
+ 		data += pktsze;
+ 		len -= maxsze;
+-
+-		usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+-			usb_pipeout(urb->pipe));
++		toggle ^= 1;
+ 	} while (len > 0);
+ 
+ 	/*
+@@ -821,17 +842,17 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
+ 			urb->transfer_buffer_length > 0) {
+ 		td = uhci_alloc_td(uhci);
+ 		if (!td)
+-			return -ENOMEM;
++			goto nomem;
+ 		*plink = cpu_to_le32(td->dma_handle);
+ 
+ 		uhci_add_td_to_urb(urb, td);
+-		uhci_fill_td(td, status, destination | uhci_explen(0) |
+-			(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+-			 usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
+-			data);
++		uhci_fill_td(td, status,
++				destination | uhci_explen(0) |
++					(toggle << TD_TOKEN_TOGGLE_SHIFT),
++				data);
++		plink = &td->link;
+ 
+-		usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+-			usb_pipeout(urb->pipe));
++		toggle ^= 1;
+ 	}
+ 
+ 	/* Set the interrupt-on-completion flag on the last packet.
+@@ -842,7 +863,27 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
+ 	 * flag setting. */
+ 	td->status |= __constant_cpu_to_le32(TD_CTRL_IOC);
+ 
++	/*
++	 * Build the new dummy TD and activate the old one
++	 */
++	td = uhci_alloc_td(uhci);
++	if (!td)
++		goto nomem;
++	*plink = cpu_to_le32(td->dma_handle);
++
++	uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0);
++	wmb();
++	qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE);
++	qh->dummy_td = td;
++
++	usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
++			usb_pipeout(urb->pipe), toggle);
+ 	return 0;
++
++nomem:
++	/* Remove the dummy TD from the td_list so it doesn't get freed */
++	uhci_remove_td_from_urb(qh->dummy_td);
++	return -ENOMEM;
+ }
+ 
+ /*
+@@ -1169,31 +1210,6 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd,
+ 	 * become idle, so we can activate it right away. */
+ 	if (qh->queue.next == &urbp->node)
+ 		uhci_activate_qh(uhci, qh);
+-
+-	/* If the QH is already active, we have a race with the hardware.
+-	 * This won't get fixed until dummy TDs are added. */
+-	else if (qh->state == QH_STATE_ACTIVE) {
+-
+-		/* If the URB isn't first on its queue, adjust the link pointer
+-		 * of the last TD in the previous URB. */
+-		if (urbp->node.prev != &urbp->qh->queue) {
+-			struct urb_priv *purbp = list_entry(urbp->node.prev,
+-					struct urb_priv, node);
+-			struct uhci_td *ptd = list_entry(purbp->td_list.prev,
+-					struct uhci_td, list);
+-			struct uhci_td *td = list_entry(urbp->td_list.next,
+-					struct uhci_td, list);
+-
+-			ptd->link = cpu_to_le32(td->dma_handle);
+-
+-		}
+-		if (qh_element(qh) == UHCI_PTR_TERM) {
+-			struct uhci_td *td = list_entry(urbp->td_list.next,
+-					struct uhci_td, list);
+-
+-			qh->element = cpu_to_le32(td->dma_handle);
+-		}
+-	}
+ 	goto done;
+ 
+ err_submit_failed:

commit dccf4a48d47120a42382ba526f1a0848c13ba2a4
+Author: Alan Stern 
+Date:   Sat Dec 17 17:58:46 2005 -0500
+
+    [PATCH] UHCI: use one QH per endpoint, not per URB
+    
+    This patch (as623) changes the uhci-hcd driver to make it use one QH per
+    device endpoint, instead of a QH per URB as it does now.  Numerous areas
+    of the code are affected by this.  For example, the distinction between
+    "queued" URBs and non-"queued" URBs no longer exists; all URBs belong to
+    a queue and some just happen to be at the queue's head.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
+index 5832953086f8..3faccbd68547 100644
+--- a/drivers/usb/host/uhci-debug.c
++++ b/drivers/usb/host/uhci-debug.c
+@@ -90,13 +90,60 @@ static int uhci_show_td(struct uhci_td *td, char *buf, int len, int space)
+ 	return out - buf;
+ }
+ 
+-static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
++static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space)
+ {
+ 	char *out = buf;
+-	struct urb_priv *urbp;
+-	struct list_head *head, *tmp;
+ 	struct uhci_td *td;
+-	int i = 0, checked = 0, prevactive = 0;
++	int i, nactive, ninactive;
++
++	if (len < 200)
++		return 0;
++
++	out += sprintf(out, "urb_priv [%p] ", urbp);
++	out += sprintf(out, "urb [%p] ", urbp->urb);
++	out += sprintf(out, "qh [%p] ", urbp->qh);
++	out += sprintf(out, "Dev=%d ", usb_pipedevice(urbp->urb->pipe));
++	out += sprintf(out, "EP=%x(%s) ", usb_pipeendpoint(urbp->urb->pipe),
++			(usb_pipein(urbp->urb->pipe) ? "IN" : "OUT"));
++
++	switch (usb_pipetype(urbp->urb->pipe)) {
++	case PIPE_ISOCHRONOUS: out += sprintf(out, "ISO"); break;
++	case PIPE_INTERRUPT: out += sprintf(out, "INT"); break;
++	case PIPE_BULK: out += sprintf(out, "BLK"); break;
++	case PIPE_CONTROL: out += sprintf(out, "CTL"); break;
++	}
++
++	out += sprintf(out, "%s", (urbp->fsbr ? " FSBR" : ""));
++	out += sprintf(out, "%s", (urbp->fsbr_timeout ? " FSBR_TO" : ""));
++
++	if (urbp->urb->status != -EINPROGRESS)
++		out += sprintf(out, " Status=%d", urbp->urb->status);
++	out += sprintf(out, "\n");
++
++	i = nactive = ninactive = 0;
++	list_for_each_entry(td, &urbp->td_list, list) {
++		if (++i <= 10 || debug > 2) {
++			out += sprintf(out, "%*s%d: ", space + 2, "", i);
++			out += uhci_show_td(td, out, len - (out - buf), 0);
++		} else {
++			if (td_status(td) & TD_CTRL_ACTIVE)
++				++nactive;
++			else
++				++ninactive;
++		}
++	}
++	if (nactive + ninactive > 0)
++		out += sprintf(out, "%*s[skipped %d inactive and %d active "
++				"TDs]\n",
++				space, "", ninactive, nactive);
++
++	return out - buf;
++}
++
++static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
++{
++	char *out = buf;
++	int i, nurbs;
+ 	__le32 element = qh_element(qh);
+ 
+ 	/* Try to make sure there's enough memory */
+@@ -118,86 +165,36 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
+ 	if (!(element & ~(UHCI_PTR_QH | UHCI_PTR_DEPTH)))
+ 		out += sprintf(out, "%*s  Element is NULL (bug?)\n", space, "");
+ 
+-	if (!qh->urbp) {
+-		out += sprintf(out, "%*s  urbp == NULL\n", space, "");
+-		goto out;
+-	}
+-
+-	urbp = qh->urbp;
+-
+-	head = &urbp->td_list;
+-	tmp = head->next;
+-
+-	td = list_entry(tmp, struct uhci_td, list);
+-
+-	if (cpu_to_le32(td->dma_handle) != (element & ~UHCI_PTR_BITS))
+-		out += sprintf(out, "%*s Element != First TD\n", space, "");
+-
+-	while (tmp != head) {
+-		struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
+-
+-		tmp = tmp->next;
+-
+-		out += sprintf(out, "%*s%d: ", space + 2, "", i++);
+-		out += uhci_show_td(td, out, len - (out - buf), 0);
+-
+-		if (i > 10 && !checked && prevactive && tmp != head &&
+-		    debug <= 2) {
+-			struct list_head *ntmp = tmp;
+-			struct uhci_td *ntd = td;
+-			int active = 1, ni = i;
+-
+-			checked = 1;
+-
+-			while (ntmp != head && ntmp->next != head && active) {
+-				ntd = list_entry(ntmp, struct uhci_td, list);
+-
+-				ntmp = ntmp->next;
+-
+-				active = td_status(ntd) & TD_CTRL_ACTIVE;
+-
+-				ni++;
+-			}
+-
+-			if (active && ni > i) {
+-				out += sprintf(out, "%*s[skipped %d active TDs]\n", space, "", ni - i);
+-				tmp = ntmp;
+-				td = ntd;
+-				i = ni;
+-			}
++	if (list_empty(&qh->queue)) {
++		out += sprintf(out, "%*s  queue is empty\n", space, "");
++	} else {
++		struct urb_priv *urbp = list_entry(qh->queue.next,
++				struct urb_priv, node);
++		struct uhci_td *td = list_entry(urbp->td_list.next,
++				struct uhci_td, list);
++
++		if (cpu_to_le32(td->dma_handle) != (element & ~UHCI_PTR_BITS))
++			out += sprintf(out, "%*s Element != First TD\n",
++					space, "");
++		i = nurbs = 0;
++		list_for_each_entry(urbp, &qh->queue, node) {
++			if (++i <= 10)
++				out += uhci_show_urbp(urbp, out,
++						len - (out - buf), space + 2);
++			else
++				++nurbs;
+ 		}
+-
+-		prevactive = td_status(td) & TD_CTRL_ACTIVE;
+-	}
+-
+-	if (list_empty(&urbp->queue_list) || urbp->queued)
+-		goto out;
+-
+-	out += sprintf(out, "%*sQueued QHs:\n", -space, "--");
+-
+-	head = &urbp->queue_list;
+-	tmp = head->next;
+-
+-	while (tmp != head) {
+-		struct urb_priv *nurbp = list_entry(tmp, struct urb_priv,
+-						queue_list);
+-		tmp = tmp->next;
+-
+-		out += uhci_show_qh(nurbp->qh, out, len - (out - buf), space);
++		if (nurbs > 0)
++			out += sprintf(out, "%*s Skipped %d URBs\n",
++					space, "", nurbs);
+ 	}
+ 
+-out:
+ 	return out - buf;
+ }
+ 
+-#define show_frame_num()	\
+-	if (!shown) {		\
+-	  shown = 1;		\
+-	  out += sprintf(out, "- Frame %d\n", i); \
+-	}
+-
+ #ifdef CONFIG_PROC_FS
+ static const char * const qh_names[] = {
++  "skel_unlink_qh", "skel_iso_qh",
+   "skel_int128_qh", "skel_int64_qh",
+   "skel_int32_qh", "skel_int16_qh",
+   "skel_int8_qh", "skel_int4_qh",
+@@ -206,12 +203,6 @@ static const char * const qh_names[] = {
+   "skel_bulk_qh", "skel_term_qh"
+ };
+ 
+-#define show_qh_name()		\
+-	if (!shown) {		\
+-	  shown = 1;		\
+-	  out += sprintf(out, "- %s\n", qh_names[i]); \
+-	}
+-
+ static int uhci_show_sc(int port, unsigned short status, char *buf, int len)
+ {
+ 	char *out = buf;
+@@ -321,139 +312,29 @@ static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len)
+ 	return out - buf;
+ }
+ 
+-static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, char *buf, int len)
+-{
+-	struct list_head *tmp;
+-	char *out = buf;
+-	int count = 0;
+-
+-	if (len < 200)
+-		return 0;
+-
+-	out += sprintf(out, "urb_priv [%p] ", urbp);
+-	out += sprintf(out, "urb [%p] ", urbp->urb);
+-	out += sprintf(out, "qh [%p] ", urbp->qh);
+-	out += sprintf(out, "Dev=%d ", usb_pipedevice(urbp->urb->pipe));
+-	out += sprintf(out, "EP=%x(%s) ", usb_pipeendpoint(urbp->urb->pipe), (usb_pipein(urbp->urb->pipe) ? "IN" : "OUT"));
+-
+-	switch (usb_pipetype(urbp->urb->pipe)) {
+-	case PIPE_ISOCHRONOUS: out += sprintf(out, "ISO "); break;
+-	case PIPE_INTERRUPT: out += sprintf(out, "INT "); break;
+-	case PIPE_BULK: out += sprintf(out, "BLK "); break;
+-	case PIPE_CONTROL: out += sprintf(out, "CTL "); break;
+-	}
+-
+-	out += sprintf(out, "%s", (urbp->fsbr ? "FSBR " : ""));
+-	out += sprintf(out, "%s", (urbp->fsbr_timeout ? "FSBR_TO " : ""));
+-
+-	if (urbp->urb->status != -EINPROGRESS)
+-		out += sprintf(out, "Status=%d ", urbp->urb->status);
+-	//out += sprintf(out, "FSBRtime=%lx ",urbp->fsbrtime);
+-
+-	count = 0;
+-	list_for_each(tmp, &urbp->td_list)
+-		count++;
+-	out += sprintf(out, "TDs=%d ",count);
+-
+-	if (urbp->queued)
+-		out += sprintf(out, "queued\n");
+-	else {
+-		count = 0;
+-		list_for_each(tmp, &urbp->queue_list)
+-			count++;
+-		out += sprintf(out, "queued URBs=%d\n", count);
+-	}
+-
+-	return out - buf;
+-}
+-
+-static int uhci_show_lists(struct uhci_hcd *uhci, char *buf, int len)
+-{
+-	char *out = buf;
+-	struct list_head *head, *tmp;
+-	int count;
+-
+-	out += sprintf(out, "Main list URBs:");
+-	if (list_empty(&uhci->urb_list))
+-		out += sprintf(out, " Empty\n");
+-	else {
+-		out += sprintf(out, "\n");
+-		count = 0;
+-		head = &uhci->urb_list;
+-		tmp = head->next;
+-		while (tmp != head) {
+-			struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list);
+-
+-			out += sprintf(out, "  %d: ", ++count);
+-			out += uhci_show_urbp(uhci, urbp, out, len - (out - buf));
+-			tmp = tmp->next;
+-		}
+-	}
+-
+-	out += sprintf(out, "Remove list URBs:");
+-	if (list_empty(&uhci->urb_remove_list))
+-		out += sprintf(out, " Empty\n");
+-	else {
+-		out += sprintf(out, "\n");
+-		count = 0;
+-		head = &uhci->urb_remove_list;
+-		tmp = head->next;
+-		while (tmp != head) {
+-			struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list);
+-
+-			out += sprintf(out, "  %d: ", ++count);
+-			out += uhci_show_urbp(uhci, urbp, out, len - (out - buf));
+-			tmp = tmp->next;
+-		}
+-	}
+-
+-	out += sprintf(out, "Complete list URBs:");
+-	if (list_empty(&uhci->complete_list))
+-		out += sprintf(out, " Empty\n");
+-	else {
+-		out += sprintf(out, "\n");
+-		count = 0;
+-		head = &uhci->complete_list;
+-		tmp = head->next;
+-		while (tmp != head) {
+-			struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list);
+-
+-			out += sprintf(out, "  %d: ", ++count);
+-			out += uhci_show_urbp(uhci, urbp, out, len - (out - buf));
+-			tmp = tmp->next;
+-		}
+-	}
+-
+-	return out - buf;
+-}
+-
+ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
+ {
+-	unsigned long flags;
+ 	char *out = buf;
+ 	int i, j;
+ 	struct uhci_qh *qh;
+ 	struct uhci_td *td;
+ 	struct list_head *tmp, *head;
+ 
+-	spin_lock_irqsave(&uhci->lock, flags);
+-
+ 	out += uhci_show_root_hub_state(uhci, out, len - (out - buf));
+ 	out += sprintf(out, "HC status\n");
+ 	out += uhci_show_status(uhci, out, len - (out - buf));
++	if (debug <= 1)
++		return out - buf;
+ 
+ 	out += sprintf(out, "Frame List\n");
+ 	for (i = 0; i < UHCI_NUMFRAMES; ++i) {
+-		int shown = 0;
+ 		td = uhci->frame_cpu[i];
+ 		if (!td)
+ 			continue;
+ 
+-		if (td->dma_handle != (dma_addr_t)uhci->frame[i]) {
+-			show_frame_num();
++		out += sprintf(out, "- Frame %d\n", i); \
++		if (td->dma_handle != (dma_addr_t)uhci->frame[i])
+ 			out += sprintf(out, "    frame list does not match td->dma_handle!\n");
+-		}
+-		show_frame_num();
+ 
+ 		head = &td->fl_list;
+ 		tmp = head;
+@@ -467,14 +348,11 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
+ 	out += sprintf(out, "Skeleton QHs\n");
+ 
+ 	for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
+-		int shown = 0;
++		int cnt = 0;
+ 
+ 		qh = uhci->skelqh[i];
+-
+-		if (debug > 1) {
+-			show_qh_name();
+-			out += uhci_show_qh(qh, out, len - (out - buf), 4);
+-		}
++		out += sprintf(out, "- %s\n", qh_names[i]); \
++		out += uhci_show_qh(qh, out, len - (out - buf), 4);
+ 
+ 		/* Last QH is the Terminating QH, it's different */
+ 		if (i == UHCI_NUM_SKELQH - 1) {
+@@ -487,44 +365,27 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
+ 			continue;
+ 		}
+ 
+-		j = (i < 7) ? 7 : i+1;		/* Next skeleton */
+-		if (list_empty(&qh->list)) {
+-			if (i < UHCI_NUM_SKELQH - 1) {
+-				if (qh->link !=
+-				    (cpu_to_le32(uhci->skelqh[j]->dma_handle) | UHCI_PTR_QH)) {
+-					show_qh_name();
+-					out += sprintf(out, "    skeleton QH not linked to next skeleton QH!\n");
+-				}
+-			}
+-
+-			continue;
+-		}
+-
+-		show_qh_name();
+-
+-		head = &qh->list;
++		j = (i < 9) ? 9 : i+1;		/* Next skeleton */
++		head = &qh->node;
+ 		tmp = head->next;
+ 
+ 		while (tmp != head) {
+-			qh = list_entry(tmp, struct uhci_qh, list);
+-
++			qh = list_entry(tmp, struct uhci_qh, node);
+ 			tmp = tmp->next;
+-
+-			out += uhci_show_qh(qh, out, len - (out - buf), 4);
++			if (++cnt <= 10)
++				out += uhci_show_qh(qh, out,
++						len - (out - buf), 4);
+ 		}
++		if ((cnt -= 10) > 0)
++			out += sprintf(out, "    Skipped %d QHs\n", cnt);
+ 
+-		if (i < UHCI_NUM_SKELQH - 1) {
++		if (i > 1 && i < UHCI_NUM_SKELQH - 1) {
+ 			if (qh->link !=
+ 			    (cpu_to_le32(uhci->skelqh[j]->dma_handle) | UHCI_PTR_QH))
+ 				out += sprintf(out, "    last QH not linked to next skeleton!\n");
+ 		}
+ 	}
+ 
+-	if (debug > 2)
+-		out += uhci_show_lists(uhci, out, len - (out - buf));
+-
+-	spin_unlock_irqrestore(&uhci->lock, flags);
+-
+ 	return out - buf;
+ }
+ 
+@@ -541,6 +402,7 @@ static int uhci_debug_open(struct inode *inode, struct file *file)
+ 	struct uhci_hcd *uhci = inode->u.generic_ip;
+ 	struct uhci_debug *up;
+ 	int ret = -ENOMEM;
++	unsigned long flags;
+ 
+ 	lock_kernel();
+ 	up = kmalloc(sizeof(*up), GFP_KERNEL);
+@@ -553,7 +415,9 @@ static int uhci_debug_open(struct inode *inode, struct file *file)
+ 		goto out;
+ 	}
+ 
++	spin_lock_irqsave(&uhci->lock, flags);
+ 	up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT);
++	spin_unlock_irqrestore(&uhci->lock, flags);
+ 
+ 	file->private_data = up;
+ 
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index dfe121d35887..1ff4b8806372 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -54,7 +54,7 @@
+ /*
+  * Version Information
+  */
+-#define DRIVER_VERSION "v2.3"
++#define DRIVER_VERSION "v3.0"
+ #define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, \
+ Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \
+ Alan Stern"
+@@ -489,15 +489,11 @@ static int uhci_start(struct usb_hcd *hcd)
+ 	uhci->fsbrtimeout = 0;
+ 
+ 	spin_lock_init(&uhci->lock);
+-	INIT_LIST_HEAD(&uhci->qh_remove_list);
+ 
+ 	INIT_LIST_HEAD(&uhci->td_remove_list);
+-
+-	INIT_LIST_HEAD(&uhci->urb_remove_list);
+-
+ 	INIT_LIST_HEAD(&uhci->urb_list);
+-
+ 	INIT_LIST_HEAD(&uhci->complete_list);
++	INIT_LIST_HEAD(&uhci->idle_qh_list);
+ 
+ 	init_waitqueue_head(&uhci->waitqh);
+ 
+@@ -540,7 +536,7 @@ static int uhci_start(struct usb_hcd *hcd)
+ 	}
+ 
+ 	for (i = 0; i < UHCI_NUM_SKELQH; i++) {
+-		uhci->skelqh[i] = uhci_alloc_qh(uhci);
++		uhci->skelqh[i] = uhci_alloc_qh(uhci, NULL, NULL);
+ 		if (!uhci->skelqh[i]) {
+ 			dev_err(uhci_dev(uhci), "unable to allocate QH\n");
+ 			goto err_alloc_skelqh;
+@@ -557,13 +553,17 @@ static int uhci_start(struct usb_hcd *hcd)
+ 			uhci->skel_int16_qh->link =
+ 			uhci->skel_int8_qh->link =
+ 			uhci->skel_int4_qh->link =
+-			uhci->skel_int2_qh->link =
+-			cpu_to_le32(uhci->skel_int1_qh->dma_handle) | UHCI_PTR_QH;
+-	uhci->skel_int1_qh->link = cpu_to_le32(uhci->skel_ls_control_qh->dma_handle) | UHCI_PTR_QH;
+-
+-	uhci->skel_ls_control_qh->link = cpu_to_le32(uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH;
+-	uhci->skel_fs_control_qh->link = cpu_to_le32(uhci->skel_bulk_qh->dma_handle) | UHCI_PTR_QH;
+-	uhci->skel_bulk_qh->link = cpu_to_le32(uhci->skel_term_qh->dma_handle) | UHCI_PTR_QH;
++			uhci->skel_int2_qh->link = UHCI_PTR_QH |
++			cpu_to_le32(uhci->skel_int1_qh->dma_handle);
++
++	uhci->skel_int1_qh->link = UHCI_PTR_QH |
++			cpu_to_le32(uhci->skel_ls_control_qh->dma_handle);
++	uhci->skel_ls_control_qh->link = UHCI_PTR_QH |
++			cpu_to_le32(uhci->skel_fs_control_qh->dma_handle);
++	uhci->skel_fs_control_qh->link = UHCI_PTR_QH |
++			cpu_to_le32(uhci->skel_bulk_qh->dma_handle);
++	uhci->skel_bulk_qh->link = UHCI_PTR_QH |
++			cpu_to_le32(uhci->skel_term_qh->dma_handle);
+ 
+ 	/* This dummy TD is to work around a bug in Intel PIIX controllers */
+ 	uhci_fill_td(uhci->term_td, 0, uhci_explen(0) |
+@@ -589,15 +589,15 @@ static int uhci_start(struct usb_hcd *hcd)
+ 
+ 		/*
+ 		 * ffs (Find First bit Set) does exactly what we need:
+-		 * 1,3,5,...  => ffs = 0 => use skel_int2_qh = skelqh[6],
+-		 * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[5], etc.
+-		 * ffs > 6 => not on any high-period queue, so use
+-		 *	skel_int1_qh = skelqh[7].
++		 * 1,3,5,...  => ffs = 0 => use skel_int2_qh = skelqh[8],
++		 * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[7], etc.
++		 * ffs >= 7 => not on any high-period queue, so use
++		 *	skel_int1_qh = skelqh[9].
+ 		 * Add UHCI_NUMFRAMES to insure at least one bit is set.
+ 		 */
+-		irq = 6 - (int) __ffs(i + UHCI_NUMFRAMES);
+-		if (irq < 0)
+-			irq = 7;
++		irq = 8 - (int) __ffs(i + UHCI_NUMFRAMES);
++		if (irq <= 1)
++			irq = 9;
+ 
+ 		/* Only place we don't use the frame list routines */
+ 		uhci->frame[i] = UHCI_PTR_QH |
+@@ -767,13 +767,30 @@ static int uhci_resume(struct usb_hcd *hcd)
+ }
+ #endif
+ 
+-/* Wait until all the URBs for a particular device/endpoint are gone */
++/* Wait until a particular device/endpoint's QH is idle, and free it */
+ static void uhci_hcd_endpoint_disable(struct usb_hcd *hcd,
+-		struct usb_host_endpoint *ep)
++		struct usb_host_endpoint *hep)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++	struct uhci_qh *qh;
++
++	spin_lock_irq(&uhci->lock);
++	qh = (struct uhci_qh *) hep->hcpriv;
++	if (qh == NULL)
++		goto done;
+ 
+-	wait_event_interruptible(uhci->waitqh, list_empty(&ep->urb_list));
++	while (qh->state != QH_STATE_IDLE) {
++		++uhci->num_waiting;
++		spin_unlock_irq(&uhci->lock);
++		wait_event_interruptible(uhci->waitqh,
++				qh->state == QH_STATE_IDLE);
++		spin_lock_irq(&uhci->lock);
++		--uhci->num_waiting;
++	}
++
++	uhci_free_qh(uhci, qh);
++done:
++	spin_unlock_irq(&uhci->lock);
+ }
+ 
+ static int uhci_hcd_get_frame_number(struct usb_hcd *hcd)
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index 8b4b887a7d41..7a9481c09a05 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -28,8 +28,9 @@
+ #define   USBSTS_USBINT		0x0001	/* Interrupt due to IOC */
+ #define   USBSTS_ERROR		0x0002	/* Interrupt due to error */
+ #define   USBSTS_RD		0x0004	/* Resume Detect */
+-#define   USBSTS_HSE		0x0008	/* Host System Error - basically PCI problems */
+-#define   USBSTS_HCPE		0x0010	/* Host Controller Process Error - the scripts were buggy */
++#define   USBSTS_HSE		0x0008	/* Host System Error: PCI problems */
++#define   USBSTS_HCPE		0x0010	/* Host Controller Process Error:
++					 * the schedule is buggy */
+ #define   USBSTS_HCH		0x0020	/* HC Halted */
+ 
+ /* Interrupt enable register */
+@@ -47,7 +48,8 @@
+ /* USB port status and control registers */
+ #define USBPORTSC1	16
+ #define USBPORTSC2	18
+-#define   USBPORTSC_CCS		0x0001	/* Current Connect Status ("device present") */
++#define   USBPORTSC_CCS		0x0001	/* Current Connect Status
++					 * ("device present") */
+ #define   USBPORTSC_CSC		0x0002	/* Connect Status Change */
+ #define   USBPORTSC_PE		0x0004	/* Port Enable */
+ #define   USBPORTSC_PEC		0x0008	/* Port Enable Change */
+@@ -71,15 +73,16 @@
+ #define   USBLEGSUP_RWC		0x8f00	/* the R/WC bits */
+ #define   USBLEGSUP_RO		0x5040	/* R/O and reserved bits */
+ 
+-#define UHCI_PTR_BITS		cpu_to_le32(0x000F)
+-#define UHCI_PTR_TERM		cpu_to_le32(0x0001)
+-#define UHCI_PTR_QH		cpu_to_le32(0x0002)
+-#define UHCI_PTR_DEPTH		cpu_to_le32(0x0004)
+-#define UHCI_PTR_BREADTH	cpu_to_le32(0x0000)
++#define UHCI_PTR_BITS		__constant_cpu_to_le32(0x000F)
++#define UHCI_PTR_TERM		__constant_cpu_to_le32(0x0001)
++#define UHCI_PTR_QH		__constant_cpu_to_le32(0x0002)
++#define UHCI_PTR_DEPTH		__constant_cpu_to_le32(0x0004)
++#define UHCI_PTR_BREADTH	__constant_cpu_to_le32(0x0000)
+ 
+ #define UHCI_NUMFRAMES		1024	/* in the frame list [array] */
+ #define UHCI_MAX_SOF_NUMBER	2047	/* in an SOF packet */
+-#define CAN_SCHEDULE_FRAMES	1000	/* how far future frames can be scheduled */
++#define CAN_SCHEDULE_FRAMES	1000	/* how far in the future frames
++					 * can be scheduled */
+ 
+ 
+ /*
+@@ -87,38 +90,54 @@
+  */
+ 
+ /*
+- * One role of a QH is to hold a queue of TDs for some endpoint.  Each QH is
+- * used with one URB, and qh->element (updated by the HC) is either:
+- *   - the next unprocessed TD for the URB, or
+- *   - UHCI_PTR_TERM (when there's no more traffic for this endpoint), or
+- *   - the QH for the next URB queued to the same endpoint.
++ * One role of a QH is to hold a queue of TDs for some endpoint.  One QH goes
++ * with each endpoint, and qh->element (updated by the HC) is either:
++ *   - the next unprocessed TD in the endpoint's queue, or
++ *   - UHCI_PTR_TERM (when there's no more traffic for this endpoint).
+  *
+  * The other role of a QH is to serve as a "skeleton" framelist entry, so we
+  * can easily splice a QH for some endpoint into the schedule at the right
+  * place.  Then qh->element is UHCI_PTR_TERM.
+  *
+- * In the frame list, qh->link maintains a list of QHs seen by the HC:
++ * In the schedule, qh->link maintains a list of QHs seen by the HC:
+  *     skel1 --> ep1-qh --> ep2-qh --> ... --> skel2 --> ...
++ *
++ * qh->node is the software equivalent of qh->link.  The differences
++ * are that the software list is doubly-linked and QHs in the UNLINKING
++ * state are on the software list but not the hardware schedule.
++ *
++ * For bookkeeping purposes we maintain QHs even for Isochronous endpoints,
++ * but they never get added to the hardware schedule.
+  */
++#define QH_STATE_IDLE		1	/* QH is not being used */
++#define QH_STATE_UNLINKING	2	/* QH has been removed from the
++					 * schedule but the hardware may
++					 * still be using it */
++#define QH_STATE_ACTIVE		3	/* QH is on the schedule */
++
+ struct uhci_qh {
+ 	/* Hardware fields */
+-	__le32 link;			/* Next queue */
+-	__le32 element;			/* Queue element pointer */
++	__le32 link;			/* Next QH in the schedule */
++	__le32 element;			/* Queue element (TD) pointer */
+ 
+ 	/* Software fields */
+ 	dma_addr_t dma_handle;
+ 
+-	struct urb_priv *urbp;
++	struct list_head node;		/* Node in the list of QHs */
++	struct usb_host_endpoint *hep;	/* Endpoint information */
++	struct usb_device *udev;
++	struct list_head queue;		/* Queue of urbps for this QH */
++	struct uhci_qh *skel;		/* Skeleton for this QH */
+ 
+-	struct list_head list;
+-	struct list_head remove_list;
++	unsigned int unlink_frame;	/* When the QH was unlinked */
++	int state;			/* QH_STATE_xxx; see above */
+ } __attribute__((aligned(16)));
+ 
+ /*
+  * We need a special accessor for the element pointer because it is
+  * subject to asynchronous updates by the controller.
+  */
+-static __le32 inline qh_element(struct uhci_qh *qh) {
++static inline __le32 qh_element(struct uhci_qh *qh) {
+ 	__le32 element = qh->element;
+ 
+ 	barrier();
+@@ -149,11 +168,13 @@ static __le32 inline qh_element(struct uhci_qh *qh) {
+ #define TD_CTRL_ACTLEN_MASK	0x7FF	/* actual length, encoded as n - 1 */
+ 
+ #define TD_CTRL_ANY_ERROR	(TD_CTRL_STALLED | TD_CTRL_DBUFERR | \
+-				 TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF)
++				 TD_CTRL_BABBLE | TD_CTRL_CRCTIME | \
++				 TD_CTRL_BITSTUFF)
+ 
+ #define uhci_maxerr(err)		((err) << TD_CTRL_C_ERR_SHIFT)
+ #define uhci_status_bits(ctrl_sts)	((ctrl_sts) & 0xF60000)
+-#define uhci_actual_length(ctrl_sts)	(((ctrl_sts) + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */
++#define uhci_actual_length(ctrl_sts)	(((ctrl_sts) + 1) & \
++			TD_CTRL_ACTLEN_MASK)	/* 1-based */
+ 
+ /*
+  * for TD : (a.k.a. Token)
+@@ -163,7 +184,7 @@ static __le32 inline qh_element(struct uhci_qh *qh) {
+ #define TD_TOKEN_TOGGLE_SHIFT	19
+ #define TD_TOKEN_TOGGLE		(1 << 19)
+ #define TD_TOKEN_EXPLEN_SHIFT	21
+-#define TD_TOKEN_EXPLEN_MASK	0x7FF		/* expected length, encoded as n - 1 */
++#define TD_TOKEN_EXPLEN_MASK	0x7FF	/* expected length, encoded as n-1 */
+ #define TD_TOKEN_PID_MASK	0xFF
+ 
+ #define uhci_explen(len)	((((len) - 1) & TD_TOKEN_EXPLEN_MASK) << \
+@@ -187,7 +208,7 @@ static __le32 inline qh_element(struct uhci_qh *qh) {
+  * sw space after the TD entry.
+  *
+  * td->link points to either another TD (not necessarily for the same urb or
+- * even the same endpoint), or nothing (PTR_TERM), or a QH (for queued urbs).
++ * even the same endpoint), or nothing (PTR_TERM), or a QH.
+  */
+ struct uhci_td {
+ 	/* Hardware fields */
+@@ -210,7 +231,7 @@ struct uhci_td {
+  * We need a special accessor for the control/status word because it is
+  * subject to asynchronous updates by the controller.
+  */
+-static u32 inline td_status(struct uhci_td *td) {
++static inline u32 td_status(struct uhci_td *td) {
+ 	__le32 status = td->status;
+ 
+ 	barrier();
+@@ -223,17 +244,14 @@ static u32 inline td_status(struct uhci_td *td) {
+  */
+ 
+ /*
+- * The UHCI driver places Interrupt, Control and Bulk into QHs both
+- * to group together TDs for one transfer, and also to facilitate queuing
+- * of URBs. To make it easy to insert entries into the schedule, we have
+- * a skeleton of QHs for each predefined Interrupt latency, low-speed
+- * control, full-speed control and terminating QH (see explanation for
+- * the terminating QH below).
++ * The UHCI driver uses QHs with Interrupt, Control and Bulk URBs for
++ * automatic queuing. To make it easy to insert entries into the schedule,
++ * we have a skeleton of QHs for each predefined Interrupt latency,
++ * low-speed control, full-speed control, bulk, and terminating QH
++ * (see explanation for the terminating QH below).
+  *
+  * When we want to add a new QH, we add it to the end of the list for the
+- * skeleton QH.
+- *
+- * For instance, the queue can look like this:
++ * skeleton QH.  For instance, the schedule list can look like this:
+  *
+  * skel int128 QH
+  * dev 1 interrupt QH
+@@ -256,26 +274,31 @@ static u32 inline td_status(struct uhci_td *td) {
+  * - To loop back to the full-speed control queue for full-speed bandwidth
+  *   reclamation.
+  *
+- * Isochronous transfers are stored before the start of the skeleton
+- * schedule and don't use QHs. While the UHCI spec doesn't forbid the
+- * use of QHs for Isochronous, it doesn't use them either. And the spec
+- * says that queues never advance on an error completion status, which
+- * makes them totally unsuitable for Isochronous transfers.
++ * There's a special skeleton QH for Isochronous QHs.  It never appears
++ * on the schedule, and Isochronous TDs go on the schedule before the
++ * the skeleton QHs.  The hardware accesses them directly rather than
++ * through their QH, which is used only for bookkeeping purposes.
++ * While the UHCI spec doesn't forbid the use of QHs for Isochronous,
++ * it doesn't use them either.  And the spec says that queues never
++ * advance on an error completion status, which makes them totally
++ * unsuitable for Isochronous transfers.
+  */
+ 
+-#define UHCI_NUM_SKELQH		12
+-#define skel_int128_qh		skelqh[0]
+-#define skel_int64_qh		skelqh[1]
+-#define skel_int32_qh		skelqh[2]
+-#define skel_int16_qh		skelqh[3]
+-#define skel_int8_qh		skelqh[4]
+-#define skel_int4_qh		skelqh[5]
+-#define skel_int2_qh		skelqh[6]
+-#define skel_int1_qh		skelqh[7]
+-#define skel_ls_control_qh	skelqh[8]
+-#define skel_fs_control_qh	skelqh[9]
+-#define skel_bulk_qh		skelqh[10]
+-#define skel_term_qh		skelqh[11]
++#define UHCI_NUM_SKELQH		14
++#define skel_unlink_qh		skelqh[0]
++#define skel_iso_qh		skelqh[1]
++#define skel_int128_qh		skelqh[2]
++#define skel_int64_qh		skelqh[3]
++#define skel_int32_qh		skelqh[4]
++#define skel_int16_qh		skelqh[5]
++#define skel_int8_qh		skelqh[6]
++#define skel_int4_qh		skelqh[7]
++#define skel_int2_qh		skelqh[8]
++#define skel_int1_qh		skelqh[9]
++#define skel_ls_control_qh	skelqh[10]
++#define skel_fs_control_qh	skelqh[11]
++#define skel_bulk_qh		skelqh[12]
++#define skel_term_qh		skelqh[13]
+ 
+ /*
+  * Search tree for determining where  fits in the skelqh[]
+@@ -293,21 +316,21 @@ static inline int __interval_to_skel(int interval)
+ 	if (interval < 16) {
+ 		if (interval < 4) {
+ 			if (interval < 2)
+-				return 7;	/* int1 for 0-1 ms */
+-			return 6;		/* int2 for 2-3 ms */
++				return 9;	/* int1 for 0-1 ms */
++			return 8;		/* int2 for 2-3 ms */
+ 		}
+ 		if (interval < 8)
+-			return 5;		/* int4 for 4-7 ms */
+-		return 4;			/* int8 for 8-15 ms */
++			return 7;		/* int4 for 4-7 ms */
++		return 6;			/* int8 for 8-15 ms */
+ 	}
+ 	if (interval < 64) {
+ 		if (interval < 32)
+-			return 3;		/* int16 for 16-31 ms */
+-		return 2;			/* int32 for 32-63 ms */
++			return 5;		/* int16 for 16-31 ms */
++		return 4;			/* int32 for 32-63 ms */
+ 	}
+ 	if (interval < 128)
+-		return 1;			/* int64 for 64-127 ms */
+-	return 0;				/* int128 for 128-255 ms (Max.) */
++		return 3;			/* int64 for 64-127 ms */
++	return 2;				/* int128 for 128-255 ms (Max.) */
+ }
+ 
+ 
+@@ -363,12 +386,12 @@ struct uhci_hcd {
+ 
+ 	spinlock_t lock;
+ 
+-	dma_addr_t frame_dma_handle;		/* Hardware frame list */
++	dma_addr_t frame_dma_handle;	/* Hardware frame list */
+ 	__le32 *frame;
+-	void **frame_cpu;			/* CPU's frame list */
++	void **frame_cpu;		/* CPU's frame list */
+ 
+-	int fsbr;				/* Full-speed bandwidth reclamation */
+-	unsigned long fsbrtimeout;		/* FSBR delay */
++	int fsbr;			/* Full-speed bandwidth reclamation */
++	unsigned long fsbrtimeout;	/* FSBR delay */
+ 
+ 	enum uhci_rh_state rh_state;
+ 	unsigned long auto_stop_time;		/* When to AUTO_STOP */
+@@ -392,24 +415,19 @@ struct uhci_hcd {
+ 	/* Main list of URBs currently controlled by this HC */
+ 	struct list_head urb_list;
+ 
+-	/* List of QHs that are done, but waiting to be unlinked (race) */
+-	struct list_head qh_remove_list;
+-	unsigned int qh_remove_age;		/* Age in frames */
+-
+ 	/* List of TDs that are done, but waiting to be freed (race) */
+ 	struct list_head td_remove_list;
+ 	unsigned int td_remove_age;		/* Age in frames */
+ 
+-	/* List of asynchronously unlinked URBs */
+-	struct list_head urb_remove_list;
+-	unsigned int urb_remove_age;		/* Age in frames */
+-
+ 	/* List of URBs awaiting completion callback */
+ 	struct list_head complete_list;
+ 
++	struct list_head idle_qh_list;		/* Where the idle QHs live */
++
+ 	int rh_numports;			/* Number of root-hub ports */
+ 
+ 	wait_queue_head_t waitqh;		/* endpoint_disable waiters */
++	int num_waiting;			/* Number of waiters */
+ };
+ 
+ /* Convert between a usb_hcd pointer and the corresponding uhci_hcd */
+@@ -430,22 +448,19 @@ static inline struct usb_hcd *uhci_to_hcd(struct uhci_hcd *uhci)
+  */
+ struct urb_priv {
+ 	struct list_head urb_list;
++	struct list_head node;		/* Node in the QH's urbp list */
+ 
+ 	struct urb *urb;
+ 
+ 	struct uhci_qh *qh;		/* QH for this URB */
+ 	struct list_head td_list;
+ 
+-	unsigned fsbr : 1;		/* URB turned on FSBR */
+-	unsigned fsbr_timeout : 1;	/* URB timed out on FSBR */
+-	unsigned queued : 1;		/* QH was queued (not linked in) */
+-	unsigned short_control_packet : 1;	/* If we get a short packet during */
+-						/*  a control transfer, retrigger */
+-						/*  the status phase */
+-
+ 	unsigned long fsbrtime;		/* In jiffies */
+ 
+-	struct list_head queue_list;
++	unsigned fsbr : 1;		/* URB turned on FSBR */
++	unsigned fsbr_timeout : 1;	/* URB timed out on FSBR */
++	unsigned short_transfer : 1;	/* URB got a short transfer, no
++					 * need to rescan */
+ };
+ 
+ 
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 782398045f9f..b1b551a3d14e 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -13,13 +13,9 @@
+  * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
+  *               support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
+  * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
+- * (C) Copyright 2004 Alan Stern, stern@rowland.harvard.edu
++ * (C) Copyright 2004-2005 Alan Stern, stern@rowland.harvard.edu
+  */
+ 
+-static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb);
+-static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb);
+-static void uhci_remove_pending_urbps(struct uhci_hcd *uhci);
+-static void uhci_free_pending_qhs(struct uhci_hcd *uhci);
+ static void uhci_free_pending_tds(struct uhci_hcd *uhci);
+ 
+ /*
+@@ -30,7 +26,7 @@ static void uhci_free_pending_tds(struct uhci_hcd *uhci);
+  * games with the FSBR code to make sure we get the correct order in all
+  * the cases. I don't think it's worth the effort
+  */
+-static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci)
++static void uhci_set_next_interrupt(struct uhci_hcd *uhci)
+ {
+ 	if (uhci->is_stopped)
+ 		mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);
+@@ -42,12 +38,6 @@ static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci)
+ 	uhci->term_td->status &= ~cpu_to_le32(TD_CTRL_IOC);
+ }
+ 
+-static inline void uhci_moveto_complete(struct uhci_hcd *uhci, 
+-					struct urb_priv *urbp)
+-{
+-	list_move_tail(&urbp->urb_list, &uhci->complete_list);
+-}
+-
+ static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci)
+ {
+ 	dma_addr_t dma_handle;
+@@ -71,6 +61,18 @@ static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci)
+ 	return td;
+ }
+ 
++static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td)
++{
++	if (!list_empty(&td->list))
++		dev_warn(uhci_dev(uhci), "td %p still in list!\n", td);
++	if (!list_empty(&td->remove_list))
++		dev_warn(uhci_dev(uhci), "td %p still in remove_list!\n", td);
++	if (!list_empty(&td->fl_list))
++		dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td);
++
++	dma_pool_free(uhci->td_pool, td, td->dma_handle);
++}
++
+ static inline void uhci_fill_td(struct uhci_td *td, u32 status,
+ 		u32 token, u32 buffer)
+ {
+@@ -82,7 +84,8 @@ static inline void uhci_fill_td(struct uhci_td *td, u32 status,
+ /*
+  * We insert Isochronous URBs directly into the frame list at the beginning
+  */
+-static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td, unsigned framenum)
++static inline void uhci_insert_td_in_frame_list(struct uhci_hcd *uhci,
++		struct uhci_td *td, unsigned framenum)
+ {
+ 	framenum &= (UHCI_NUMFRAMES - 1);
+ 
+@@ -108,7 +111,7 @@ static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td,
+ 	}
+ }
+ 
+-static inline void uhci_remove_td_frame_list(struct uhci_hcd *uhci,
++static inline void uhci_remove_td_from_frame_list(struct uhci_hcd *uhci,
+ 		struct uhci_td *td)
+ {
+ 	/* If it's not inserted, don't remove it */
+@@ -139,48 +142,68 @@ static inline void uhci_remove_td_frame_list(struct uhci_hcd *uhci,
+ 	td->frame = -1;
+ }
+ 
+-static void unlink_isochronous_tds(struct uhci_hcd *uhci, struct urb *urb)
++/*
++ * Remove all the TDs for an Isochronous URB from the frame list
++ */
++static void uhci_unlink_isochronous_tds(struct uhci_hcd *uhci, struct urb *urb)
+ {
+ 	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
+ 	struct uhci_td *td;
+ 
+ 	list_for_each_entry(td, &urbp->td_list, list)
+-		uhci_remove_td_frame_list(uhci, td);
++		uhci_remove_td_from_frame_list(uhci, td);
+ 	wmb();
+ }
+ 
+ /*
+- * Inserts a td list into qh.
++ * Remove an URB's TDs from the hardware schedule
+  */
+-static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, __le32 breadth)
++static void uhci_remove_tds_from_schedule(struct uhci_hcd *uhci,
++		struct urb *urb, int status)
+ {
+-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+-	struct uhci_td *td;
+-	__le32 *plink;
++	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
+ 
+-	/* Ordering isn't important here yet since the QH hasn't been */
+-	/* inserted into the schedule yet */
+-	plink = &qh->element;
+-	list_for_each_entry(td, &urbp->td_list, list) {
+-		*plink = cpu_to_le32(td->dma_handle) | breadth;
+-		plink = &td->link;
++	/* Isochronous TDs get unlinked directly from the frame list */
++	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
++		uhci_unlink_isochronous_tds(uhci, urb);
++		return;
+ 	}
+-	*plink = UHCI_PTR_TERM;
+-}
+ 
+-static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td)
+-{
+-	if (!list_empty(&td->list))
+-		dev_warn(uhci_dev(uhci), "td %p still in list!\n", td);
+-	if (!list_empty(&td->remove_list))
+-		dev_warn(uhci_dev(uhci), "td %p still in remove_list!\n", td);
+-	if (!list_empty(&td->fl_list))
+-		dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td);
++	/* If the URB isn't first on its queue, adjust the link pointer
++	 * of the last TD in the previous URB. */
++	if (urbp->node.prev != &urbp->qh->queue) {
++		struct urb_priv *purbp;
++		struct uhci_td *ptd, *ltd;
++
++		if (status == -EINPROGRESS)
++			status = 0;
++		purbp = list_entry(urbp->node.prev, struct urb_priv, node);
++		ptd = list_entry(purbp->td_list.prev, struct uhci_td,
++				list);
++		ltd = list_entry(urbp->td_list.prev, struct uhci_td,
++				list);
++		ptd->link = ltd->link;
++	}
+ 
+-	dma_pool_free(uhci->td_pool, td, td->dma_handle);
++	/* If the URB completed with an error, then the QH element certainly
++	 * points to one of the URB's TDs.  If it completed normally then
++	 * the QH element has certainly moved on to the next URB.  And if
++	 * the URB is still in progress then it must have been dequeued.
++	 * The QH element either hasn't reached it yet or is somewhere in
++	 * the middle.  If the URB wasn't first we can assume that it
++	 * hasn't started yet (see above): Otherwise all the preceding URBs
++	 * would have completed and been removed from the queue, so this one
++	 * _would_ be first.
++	 *
++	 * If the QH element is inside this URB, clear it.  It will be
++	 * set properly when the QH is activated.
++	 */
++	if (status < 0)
++		urbp->qh->element = UHCI_PTR_TERM;
+ }
+ 
+-static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci)
++static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci,
++		struct usb_device *udev, struct usb_host_endpoint *hep)
+ {
+ 	dma_addr_t dma_handle;
+ 	struct uhci_qh *qh;
+@@ -194,256 +217,120 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci)
+ 	qh->element = UHCI_PTR_TERM;
+ 	qh->link = UHCI_PTR_TERM;
+ 
+-	qh->urbp = NULL;
++	INIT_LIST_HEAD(&qh->queue);
++	INIT_LIST_HEAD(&qh->node);
+ 
+-	INIT_LIST_HEAD(&qh->list);
+-	INIT_LIST_HEAD(&qh->remove_list);
++	if (udev) {		/* Normal QH */
++		qh->state = QH_STATE_IDLE;
++		qh->hep = hep;
++		qh->udev = udev;
++		hep->hcpriv = qh;
++		usb_get_dev(udev);
+ 
++	} else {		/* Skeleton QH */
++		qh->state = QH_STATE_ACTIVE;
++		qh->udev = NULL;
++	}
+ 	return qh;
+ }
+ 
+ static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ {
+-	if (!list_empty(&qh->list))
++	WARN_ON(qh->state != QH_STATE_IDLE && qh->udev);
++	if (!list_empty(&qh->queue))
+ 		dev_warn(uhci_dev(uhci), "qh %p list not empty!\n", qh);
+-	if (!list_empty(&qh->remove_list))
+-		dev_warn(uhci_dev(uhci), "qh %p still in remove_list!\n", qh);
+ 
++	list_del(&qh->node);
++	if (qh->udev) {
++		qh->hep->hcpriv = NULL;
++		usb_put_dev(qh->udev);
++	}
+ 	dma_pool_free(uhci->qh_pool, qh, qh->dma_handle);
+ }
+ 
+ /*
+- * Append this urb's qh after the last qh in skelqh->list
+- *
+- * Note that urb_priv.queue_list doesn't have a separate queue head;
+- * it's a ring with every element "live".
++ * Put a QH on the schedule in both hardware and software
+  */
+-static void uhci_insert_qh(struct uhci_hcd *uhci, struct uhci_qh *skelqh, struct urb *urb)
++static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ {
+-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+-	struct urb_priv *turbp;
+-	struct uhci_qh *lqh;
++	struct uhci_qh *pqh;
+ 
+-	/* Grab the last QH */
+-	lqh = list_entry(skelqh->list.prev, struct uhci_qh, list);
++	WARN_ON(list_empty(&qh->queue));
+ 
+-	/* Point to the next skelqh */
+-	urbp->qh->link = lqh->link;
+-	wmb();				/* Ordering is important */
++	/* Set the element pointer if it isn't set already.
++	 * This isn't needed for Isochronous queues, but it doesn't hurt. */
++	if (qh_element(qh) == UHCI_PTR_TERM) {
++		struct urb_priv *urbp = list_entry(qh->queue.next,
++				struct urb_priv, node);
++		struct uhci_td *td = list_entry(urbp->td_list.next,
++				struct uhci_td, list);
+ 
+-	/*
+-	 * Patch QHs for previous endpoint's queued URBs?  HC goes
+-	 * here next, not to the next skelqh it now points to.
+-	 *
+-	 *    lqh --> td ... --> qh ... --> td --> qh ... --> td
+-	 *     |                 |                 |
+-	 *     v                 v                 v
+-	 *     +<----------------+-----------------+
+-	 *     v
+-	 *    newqh --> td ... --> td
+-	 *     |
+-	 *     v
+-	 *    ...
+-	 *
+-	 * The HC could see (and use!) any of these as we write them.
+-	 */
+-	lqh->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH;
+-	if (lqh->urbp) {
+-		list_for_each_entry(turbp, &lqh->urbp->queue_list, queue_list)
+-			turbp->qh->link = lqh->link;
++		qh->element = cpu_to_le32(td->dma_handle);
+ 	}
+ 
+-	list_add_tail(&urbp->qh->list, &skelqh->list);
++	if (qh->state == QH_STATE_ACTIVE)
++		return;
++	qh->state = QH_STATE_ACTIVE;
++
++	/* Move the QH from its old list to the end of the appropriate
++	 * skeleton's list */
++	list_move_tail(&qh->node, &qh->skel->node);
++
++	/* Link it into the schedule */
++	pqh = list_entry(qh->node.prev, struct uhci_qh, node);
++	qh->link = pqh->link;
++	wmb();
++	pqh->link = UHCI_PTR_QH | cpu_to_le32(qh->dma_handle);
+ }
+ 
+ /*
+- * Start removal of QH from schedule; it finishes next frame.
+- * TDs should be unlinked before this is called.
++ * Take a QH off the hardware schedule
+  */
+-static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
++static void uhci_unlink_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ {
+ 	struct uhci_qh *pqh;
+-	__le32 newlink;
+ 
+-	if (!qh)
++	if (qh->state == QH_STATE_UNLINKING)
+ 		return;
++	WARN_ON(qh->state != QH_STATE_ACTIVE || !qh->udev);
++	qh->state = QH_STATE_UNLINKING;
+ 
+-	/*
+-	 * Only go through the hoops if it's actually linked in
+-	 */
+-	if (!list_empty(&qh->list)) {
+-
+-		/* If our queue is nonempty, make the next URB the head */
+-		if (!list_empty(&qh->urbp->queue_list)) {
+-			struct urb_priv *nurbp;
+-
+-			nurbp = list_entry(qh->urbp->queue_list.next,
+-					struct urb_priv, queue_list);
+-			nurbp->queued = 0;
+-			list_add(&nurbp->qh->list, &qh->list);
+-			newlink = cpu_to_le32(nurbp->qh->dma_handle) | UHCI_PTR_QH;
+-		} else
+-			newlink = qh->link;
+-
+-		/* Fix up the previous QH's queue to link to either
+-		 * the new head of this queue or the start of the
+-		 * next endpoint's queue. */
+-		pqh = list_entry(qh->list.prev, struct uhci_qh, list);
+-		pqh->link = newlink;
+-		if (pqh->urbp) {
+-			struct urb_priv *turbp;
+-
+-			list_for_each_entry(turbp, &pqh->urbp->queue_list,
+-					queue_list)
+-				turbp->qh->link = newlink;
+-		}
+-		wmb();
+-
+-		/* Leave qh->link in case the HC is on the QH now, it will */
+-		/* continue the rest of the schedule */
+-		qh->element = UHCI_PTR_TERM;
+-
+-		list_del_init(&qh->list);
+-	}
+-
+-	list_del_init(&qh->urbp->queue_list);
+-	qh->urbp = NULL;
++	/* Unlink the QH from the schedule and record when we did it */
++	pqh = list_entry(qh->node.prev, struct uhci_qh, node);
++	pqh->link = qh->link;
++	mb();
+ 
+ 	uhci_get_current_frame_number(uhci);
+-	if (uhci->frame_number + uhci->is_stopped != uhci->qh_remove_age) {
+-		uhci_free_pending_qhs(uhci);
+-		uhci->qh_remove_age = uhci->frame_number;
+-	}
++	qh->unlink_frame = uhci->frame_number;
+ 
+-	/* Check to see if the remove list is empty. Set the IOC bit */
+-	/* to force an interrupt so we can remove the QH */
+-	if (list_empty(&uhci->qh_remove_list))
++	/* Force an interrupt so we know when the QH is fully unlinked */
++	if (list_empty(&uhci->skel_unlink_qh->node))
+ 		uhci_set_next_interrupt(uhci);
+ 
+-	list_add(&qh->remove_list, &uhci->qh_remove_list);
++	/* Move the QH from its old list to the end of the unlinking list */
++	list_move_tail(&qh->node, &uhci->skel_unlink_qh->node);
+ }
+ 
+-static int uhci_fixup_toggle(struct urb *urb, unsigned int toggle)
+-{
+-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+-	struct uhci_td *td;
+-
+-	list_for_each_entry(td, &urbp->td_list, list) {
+-		if (toggle)
+-			td->token |= cpu_to_le32(TD_TOKEN_TOGGLE);
+-		else
+-			td->token &= ~cpu_to_le32(TD_TOKEN_TOGGLE);
+-
+-		toggle ^= 1;
+-	}
+-
+-	return toggle;
+-}
+-
+-/* This function will append one URB's QH to another URB's QH. This is for */
+-/* queuing interrupt, control or bulk transfers */
+-static void uhci_append_queued_urb(struct uhci_hcd *uhci, struct urb *eurb, struct urb *urb)
+-{
+-	struct urb_priv *eurbp, *urbp, *furbp, *lurbp;
+-	struct uhci_td *lltd;
+-
+-	eurbp = eurb->hcpriv;
+-	urbp = urb->hcpriv;
+-
+-	/* Find the first URB in the queue */
+-	furbp = eurbp;
+-	if (eurbp->queued) {
+-		list_for_each_entry(furbp, &eurbp->queue_list, queue_list)
+-			if (!furbp->queued)
+-				break;
+-	}
+-
+-	lurbp = list_entry(furbp->queue_list.prev, struct urb_priv, queue_list);
+-
+-	lltd = list_entry(lurbp->td_list.prev, struct uhci_td, list);
+-
+-	/* Control transfers always start with toggle 0 */
+-	if (!usb_pipecontrol(urb->pipe))
+-		usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+-				usb_pipeout(urb->pipe),
+-				uhci_fixup_toggle(urb,
+-					uhci_toggle(td_token(lltd)) ^ 1));
+-
+-	/* All qhs in the queue need to link to the next queue */
+-	urbp->qh->link = eurbp->qh->link;
+-
+-	wmb();			/* Make sure we flush everything */
+-
+-	lltd->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH;
+-
+-	list_add_tail(&urbp->queue_list, &furbp->queue_list);
+-
+-	urbp->queued = 1;
+-}
+-
+-static void uhci_delete_queued_urb(struct uhci_hcd *uhci, struct urb *urb)
++/*
++ * When we and the controller are through with a QH, it becomes IDLE.
++ * This happens when a QH has been off the schedule (on the unlinking
++ * list) for more than one frame, or when an error occurs while adding
++ * the first URB onto a new QH.
++ */
++static void uhci_make_qh_idle(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ {
+-	struct urb_priv *urbp, *nurbp, *purbp, *turbp;
+-	struct uhci_td *pltd;
+-	unsigned int toggle;
+-
+-	urbp = urb->hcpriv;
+-
+-	if (list_empty(&urbp->queue_list))
+-		return;
+-
+-	nurbp = list_entry(urbp->queue_list.next, struct urb_priv, queue_list);
+-
+-	/*
+-	 * Fix up the toggle for the following URBs in the queue.
+-	 * Only needed for bulk and interrupt: control and isochronous
+-	 * endpoints don't propagate toggles between messages.
+-	 */
+-	if (usb_pipebulk(urb->pipe) || usb_pipeint(urb->pipe)) {
+-		if (!urbp->queued)
+-			/* We just set the toggle in uhci_unlink_generic */
+-			toggle = usb_gettoggle(urb->dev,
+-					usb_pipeendpoint(urb->pipe),
+-					usb_pipeout(urb->pipe));
+-		else {
+-			/* If we're in the middle of the queue, grab the */
+-			/* toggle from the TD previous to us */
+-			purbp = list_entry(urbp->queue_list.prev,
+-					struct urb_priv, queue_list);
+-			pltd = list_entry(purbp->td_list.prev,
+-					struct uhci_td, list);
+-			toggle = uhci_toggle(td_token(pltd)) ^ 1;
+-		}
+-
+-		list_for_each_entry(turbp, &urbp->queue_list, queue_list) {
+-			if (!turbp->queued)
+-				break;
+-			toggle = uhci_fixup_toggle(turbp->urb, toggle);
+-		}
++	WARN_ON(qh->state == QH_STATE_ACTIVE);
+ 
+-		usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+-				usb_pipeout(urb->pipe), toggle);
+-	}
+-
+-	if (urbp->queued) {
+-		/* We're somewhere in the middle (or end).  The case where
+-		 * we're at the head is handled in uhci_remove_qh(). */
+-		purbp = list_entry(urbp->queue_list.prev, struct urb_priv,
+-				queue_list);
+-
+-		pltd = list_entry(purbp->td_list.prev, struct uhci_td, list);
+-		if (nurbp->queued)
+-			pltd->link = cpu_to_le32(nurbp->qh->dma_handle) | UHCI_PTR_QH;
+-		else
+-			/* The next URB happens to be the beginning, so */
+-			/*  we're the last, end the chain */
+-			pltd->link = UHCI_PTR_TERM;
+-	}
++	list_move(&qh->node, &uhci->idle_qh_list);
++	qh->state = QH_STATE_IDLE;
+ 
+-	/* urbp->queue_list is handled in uhci_remove_qh() */
++	/* If anyone is waiting for a QH to become idle, wake them up */
++	if (uhci->num_waiting)
++		wake_up_all(&uhci->waitqh);
+ }
+ 
+-static struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
++static inline struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci,
++		struct urb *urb)
+ {
+ 	struct urb_priv *urbp;
+ 
+@@ -453,17 +340,14 @@ static struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, struct urb *u
+ 
+ 	memset((void *)urbp, 0, sizeof(*urbp));
+ 
+-	urbp->fsbrtime = jiffies;
+ 	urbp->urb = urb;
++	urb->hcpriv = urbp;
++	urbp->fsbrtime = jiffies;
+ 	
++	INIT_LIST_HEAD(&urbp->node);
+ 	INIT_LIST_HEAD(&urbp->td_list);
+-	INIT_LIST_HEAD(&urbp->queue_list);
+ 	INIT_LIST_HEAD(&urbp->urb_list);
+ 
+-	list_add_tail(&urbp->urb_list, &uhci->urb_list);
+-
+-	urb->hcpriv = urbp;
+-
+ 	return urbp;
+ }
+ 
+@@ -482,18 +366,17 @@ static void uhci_remove_td_from_urb(struct uhci_td *td)
+ 	list_del_init(&td->list);
+ }
+ 
+-static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
++static void uhci_free_urb_priv(struct uhci_hcd *uhci,
++		struct urb_priv *urbp)
+ {
+ 	struct uhci_td *td, *tmp;
+-	struct urb_priv *urbp;
+-
+-	urbp = (struct urb_priv *)urb->hcpriv;
+-	if (!urbp)
+-		return;
+ 
+ 	if (!list_empty(&urbp->urb_list))
+-		dev_warn(uhci_dev(uhci), "urb %p still on uhci->urb_list "
+-				"or uhci->remove_list!\n", urb);
++		dev_warn(uhci_dev(uhci), "urb %p still on uhci->urb_list!\n",
++				urbp->urb);
++	if (!list_empty(&urbp->node))
++		dev_warn(uhci_dev(uhci), "urb %p still on QH's list!\n",
++				urbp->urb);
+ 
+ 	uhci_get_current_frame_number(uhci);
+ 	if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age) {
+@@ -502,7 +385,7 @@ static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
+ 	}
+ 
+ 	/* Check to see if the remove list is empty. Set the IOC bit */
+-	/* to force an interrupt so we can remove the TDs*/
++	/* to force an interrupt so we can remove the TDs. */
+ 	if (list_empty(&uhci->td_remove_list))
+ 		uhci_set_next_interrupt(uhci);
+ 
+@@ -511,7 +394,7 @@ static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
+ 		list_add(&td->remove_list, &uhci->td_remove_list);
+ 	}
+ 
+-	urb->hcpriv = NULL;
++	urbp->urb->hcpriv = NULL;
+ 	kmem_cache_free(uhci_up_cachep, urbp);
+ }
+ 
+@@ -567,18 +450,83 @@ static int uhci_map_status(int status, int dir_out)
+ 	return 0;
+ }
+ 
++/*
++ * Fix up the data toggles for URBs in a queue, when one of them
++ * terminates early (short transfer, error, or dequeued).
++ */
++static void uhci_fixup_toggles(struct urb *urb)
++{
++	struct list_head *head;
++	struct uhci_td *td;
++	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
++	int prevactive = 0;
++	unsigned int toggle = 0;
++	struct urb_priv *turbp, *list_end;
++
++	/*
++	 * We need to find out what the last successful toggle was so
++	 * we can update the data toggles for the following transfers.
++	 *
++	 * There are 2 ways the last successful completed TD is found:
++	 *
++	 * 1) The TD is NOT active and the actual length < expected length
++	 * 2) The TD is NOT active and it's the last TD in the chain
++	 *
++	 * and a third way the first uncompleted TD is found:
++	 *
++	 * 3) The TD is active and the previous TD is NOT active
++	 */
++	head = &urbp->td_list;
++	list_for_each_entry(td, head, list) {
++		unsigned int ctrlstat = td_status(td);
++
++		if (!(ctrlstat & TD_CTRL_ACTIVE) &&
++				(uhci_actual_length(ctrlstat) <
++				 uhci_expected_length(td_token(td)) ||
++				td->list.next == head))
++			toggle = uhci_toggle(td_token(td)) ^ 1;
++		else if ((ctrlstat & TD_CTRL_ACTIVE) && !prevactive)
++			toggle = uhci_toggle(td_token(td));
++
++		prevactive = ctrlstat & TD_CTRL_ACTIVE;
++	}
++
++	/*
++	 * Fix up the toggle for the following URBs in the queue.
++	 *
++	 * We can stop as soon as we find an URB with toggles set correctly,
++	 * because then all the following URBs will be correct also.
++	 */
++	list_end = list_entry(&urbp->qh->queue, struct urb_priv, node);
++	turbp = urbp;
++	while ((turbp = list_entry(turbp->node.next, struct urb_priv, node))
++			!= list_end) {
++		td = list_entry(turbp->td_list.next, struct uhci_td, list);
++		if (uhci_toggle(td_token(td)) == toggle)
++			return;
++
++		list_for_each_entry(td, &turbp->td_list, list) {
++			td->token ^= __constant_cpu_to_le32(TD_TOKEN_TOGGLE);
++			toggle ^= 1;
++		}
++	}
++
++	usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
++			usb_pipeout(urb->pipe), toggle);
++}
++
+ /*
+  * Control transfers
+  */
+-static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb)
++static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
++		struct uhci_qh *qh)
+ {
+-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+ 	struct uhci_td *td;
+-	struct uhci_qh *qh, *skelqh;
+ 	unsigned long destination, status;
+-	int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
++	int maxsze = le16_to_cpu(qh->hep->desc.wMaxPacketSize);
+ 	int len = urb->transfer_buffer_length;
+ 	dma_addr_t data = urb->transfer_dma;
++	__le32 *plink;
+ 
+ 	/* The "pipe" thing contains the destination in bits 8--18 */
+ 	destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
+@@ -597,7 +545,8 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
+ 
+ 	uhci_add_td_to_urb(urb, td);
+ 	uhci_fill_td(td, status, destination | uhci_explen(8),
+-		urb->setup_dma);
++			urb->setup_dma);
++	plink = &td->link;
+ 
+ 	/*
+ 	 * If direction is "send", change the packet ID from SETUP (0x2D)
+@@ -615,21 +564,20 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
+ 	 * Build the DATA TDs
+ 	 */
+ 	while (len > 0) {
+-		int pktsze = len;
+-
+-		if (pktsze > maxsze)
+-			pktsze = maxsze;
++		int pktsze = min(len, maxsze);
+ 
+ 		td = uhci_alloc_td(uhci);
+ 		if (!td)
+ 			return -ENOMEM;
++		*plink = cpu_to_le32(td->dma_handle);
+ 
+ 		/* Alternate Data0/1 (start with Data1) */
+ 		destination ^= TD_TOKEN_TOGGLE;
+ 	
+ 		uhci_add_td_to_urb(urb, td);
+ 		uhci_fill_td(td, status, destination | uhci_explen(pktsze),
+-			data);
++				data);
++		plink = &td->link;
+ 
+ 		data += pktsze;
+ 		len -= pktsze;
+@@ -641,6 +589,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
+ 	td = uhci_alloc_td(uhci);
+ 	if (!td)
+ 		return -ENOMEM;
++	*plink = cpu_to_le32(td->dma_handle);
+ 
+ 	/*
+ 	 * It's IN if the pipe is an output pipe or we're not expecting
+@@ -658,16 +607,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
+ 
+ 	uhci_add_td_to_urb(urb, td);
+ 	uhci_fill_td(td, status | TD_CTRL_IOC,
+-		destination | uhci_explen(0), 0);
+-
+-	qh = uhci_alloc_qh(uhci);
+-	if (!qh)
+-		return -ENOMEM;
+-
+-	urbp->qh = qh;
+-	qh->urbp = urbp;
+-
+-	uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH);
++			destination | uhci_explen(0), 0);
+ 
+ 	/* Low-speed transfers get a different queue, and won't hog the bus.
+ 	 * Also, some devices enumerate better without FSBR; the easiest way
+@@ -675,18 +615,13 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
+ 	 * isn't in the CONFIGURED state. */
+ 	if (urb->dev->speed == USB_SPEED_LOW ||
+ 			urb->dev->state != USB_STATE_CONFIGURED)
+-		skelqh = uhci->skel_ls_control_qh;
++		qh->skel = uhci->skel_ls_control_qh;
+ 	else {
+-		skelqh = uhci->skel_fs_control_qh;
++		qh->skel = uhci->skel_fs_control_qh;
+ 		uhci_inc_fsbr(uhci, urb);
+ 	}
+ 
+-	if (eurb)
+-		uhci_append_queued_urb(uhci, eurb, urb);
+-	else
+-		uhci_insert_qh(uhci, skelqh, urb);
+-
+-	return -EINPROGRESS;
++	return 0;
+ }
+ 
+ /*
+@@ -703,7 +638,7 @@ static int usb_control_retrigger_status(struct uhci_hcd *uhci, struct urb *urb)
+ 	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+ 	struct uhci_td *td;
+ 
+-	urbp->short_control_packet = 1;
++	urbp->short_transfer = 1;
+ 
+ 	td = list_entry(urbp->td_list.prev, struct uhci_td, list);
+ 	urbp->qh->element = cpu_to_le32(td->dma_handle);
+@@ -720,16 +655,14 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
+ 	unsigned int status;
+ 	int ret = 0;
+ 
+-	if (list_empty(&urbp->td_list))
+-		return -EINVAL;
+-
+ 	head = &urbp->td_list;
+-
+-	if (urbp->short_control_packet) {
++	if (urbp->short_transfer) {
+ 		tmp = head->prev;
+ 		goto status_stage;
+ 	}
+ 
++	urb->actual_length = 0;
++
+ 	tmp = head->next;
+ 	td = list_entry(tmp, struct uhci_td, list);
+ 
+@@ -742,8 +675,6 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
+ 	if (status)
+ 		goto td_error;
+ 
+-	urb->actual_length = 0;
+-
+ 	/* The rest of the TDs (but the last) are data */
+ 	tmp = tmp->next;
+ 	while (tmp != head && tmp->next != head) {
+@@ -770,10 +701,7 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
+ 				goto err;
+ 			}
+ 
+-			if (uhci_packetid(td_token(td)) == USB_PID_IN)
+-				return usb_control_retrigger_status(uhci, urb);
+-			else
+-				return 0;
++			return usb_control_retrigger_status(uhci, urb);
+ 		}
+ 	}
+ 
+@@ -825,15 +753,15 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
+ /*
+  * Common submit for bulk and interrupt
+  */
+-static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb, struct uhci_qh *skelqh)
++static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
++		struct uhci_qh *qh)
+ {
+ 	struct uhci_td *td;
+-	struct uhci_qh *qh;
+ 	unsigned long destination, status;
+-	int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
++	int maxsze = le16_to_cpu(qh->hep->desc.wMaxPacketSize);
+ 	int len = urb->transfer_buffer_length;
+-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+ 	dma_addr_t data = urb->transfer_dma;
++	__le32 *plink, fake_link;
+ 
+ 	if (len < 0)
+ 		return -EINVAL;
+@@ -841,7 +769,8 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb
+ 	/* The "pipe" thing contains the destination in bits 8--18 */
+ 	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
+ 
+-	status = uhci_maxerr(3) | TD_CTRL_ACTIVE;
++	/* 3 errors */
++	status = TD_CTRL_ACTIVE | uhci_maxerr(3);
+ 	if (urb->dev->speed == USB_SPEED_LOW)
+ 		status |= TD_CTRL_LS;
+ 	if (usb_pipein(urb->pipe))
+@@ -850,10 +779,11 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb
+ 	/*
+ 	 * Build the DATA TDs
+ 	 */
++	plink = &fake_link;
+ 	do {	/* Allow zero length packets */
+ 		int pktsze = maxsze;
+ 
+-		if (pktsze >= len) {
++		if (len <= pktsze) {		/* The last packet */
+ 			pktsze = len;
+ 			if (!(urb->transfer_flags & URB_SHORT_NOT_OK))
+ 				status &= ~TD_CTRL_SPD;
+@@ -862,12 +792,15 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb
+ 		td = uhci_alloc_td(uhci);
+ 		if (!td)
+ 			return -ENOMEM;
++		*plink = cpu_to_le32(td->dma_handle);
+ 
+ 		uhci_add_td_to_urb(urb, td);
+-		uhci_fill_td(td, status, destination | uhci_explen(pktsze) |
++		uhci_fill_td(td, status,
++			destination | uhci_explen(pktsze) |
+ 			(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+ 			 usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
+ 			data);
++		plink = &td->link;
+ 
+ 		data += pktsze;
+ 		len -= maxsze;
+@@ -883,11 +816,13 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb
+ 	 * however, if transfer_length == 0, the zero packet was already
+ 	 * prepared above.
+ 	 */
+-	if (usb_pipeout(urb->pipe) && (urb->transfer_flags & URB_ZERO_PACKET) &&
+-	    !len && urb->transfer_buffer_length) {
++	if ((urb->transfer_flags & URB_ZERO_PACKET) &&
++			usb_pipeout(urb->pipe) && len == 0 &&
++			urb->transfer_buffer_length > 0) {
+ 		td = uhci_alloc_td(uhci);
+ 		if (!td)
+ 			return -ENOMEM;
++		*plink = cpu_to_le32(td->dma_handle);
+ 
+ 		uhci_add_td_to_urb(urb, td);
+ 		uhci_fill_td(td, status, destination | uhci_explen(0) |
+@@ -905,24 +840,9 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb
+ 	 * fast side but not enough to justify delaying an interrupt
+ 	 * more than 2 or 3 URBs, so we will ignore the URB_NO_INTERRUPT
+ 	 * flag setting. */
+-	td->status |= cpu_to_le32(TD_CTRL_IOC);
+-
+-	qh = uhci_alloc_qh(uhci);
+-	if (!qh)
+-		return -ENOMEM;
+-
+-	urbp->qh = qh;
+-	qh->urbp = urbp;
++	td->status |= __constant_cpu_to_le32(TD_CTRL_IOC);
+ 
+-	/* Always breadth first */
+-	uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH);
+-
+-	if (eurb)
+-		uhci_append_queued_urb(uhci, eurb, urb);
+-	else
+-		uhci_insert_qh(uhci, skelqh, urb);
+-
+-	return -EINPROGRESS;
++	return 0;
+ }
+ 
+ /*
+@@ -954,8 +874,24 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
+ 			if (urb->transfer_flags & URB_SHORT_NOT_OK) {
+ 				ret = -EREMOTEIO;
+ 				goto err;
+-			} else
+-				return 0;
++			}
++
++			/*
++			 * This URB stopped short of its end.  We have to
++			 * fix up the toggles of the following URBs on the
++			 * queue and restart the queue.
++			 *
++			 * Do this only the first time we encounter the
++			 * short URB.
++			 */
++			if (!urbp->short_transfer) {
++				urbp->short_transfer = 1;
++				uhci_fixup_toggles(urb);
++				td = list_entry(urbp->td_list.prev,
++						struct uhci_td, list);
++				urbp->qh->element = td->link;
++			}
++			break;
+ 		}
+ 	}
+ 
+@@ -988,7 +924,8 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
+ 	return ret;
+ }
+ 
+-static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb)
++static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb,
++		struct uhci_qh *qh)
+ {
+ 	int ret;
+ 
+@@ -996,21 +933,22 @@ static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, struc
+ 	if (urb->dev->speed == USB_SPEED_LOW)
+ 		return -EINVAL;
+ 
+-	ret = uhci_submit_common(uhci, urb, eurb, uhci->skel_bulk_qh);
+-	if (ret == -EINPROGRESS)
++	qh->skel = uhci->skel_bulk_qh;
++	ret = uhci_submit_common(uhci, urb, qh);
++	if (ret == 0)
+ 		uhci_inc_fsbr(uhci, urb);
+-
+ 	return ret;
+ }
+ 
+-static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb)
++static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb,
++		struct uhci_qh *qh)
+ {
+-	/* USB 1.1 interrupt transfers only involve one packet per interval;
+-	 * that's the uhci_submit_common() "breadth first" policy.  Drivers
+-	 * can submit urbs of any length, but longer ones might need many
+-	 * intervals to complete.
++	/* USB 1.1 interrupt transfers only involve one packet per interval.
++	 * Drivers can submit URBs of any length, but longer ones will need
++	 * multiple intervals to complete.
+ 	 */
+-	return uhci_submit_common(uhci, urb, eurb, uhci->skelqh[__interval_to_skel(urb->interval)]);
++	qh->skel = uhci->skelqh[__interval_to_skel(urb->interval)];
++	return uhci_submit_common(uhci, urb, qh);
+ }
+ 
+ /*
+@@ -1072,11 +1010,12 @@ static int isochronous_find_start(struct uhci_hcd *uhci, struct urb *urb)
+ /*
+  * Isochronous transfers
+  */
+-static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
++static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
++		struct uhci_qh *qh)
+ {
+-	struct uhci_td *td;
++	struct uhci_td *td = NULL;	/* Since urb->number_of_packets > 0 */
+ 	int i, ret, frame;
+-	int status, destination;
++	unsigned long destination, status;
+ 	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
+ 
+ 	status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
+@@ -1092,20 +1031,25 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
+ 			return -ENOMEM;
+ 
+ 		uhci_add_td_to_urb(urb, td);
+-		uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length),
+-			urb->transfer_dma + urb->iso_frame_desc[i].offset);
+-
+-		if (i + 1 >= urb->number_of_packets)
+-			td->status |= cpu_to_le32(TD_CTRL_IOC);
++		uhci_fill_td(td, status, destination |
++				uhci_explen(urb->iso_frame_desc[i].length),
++				urb->transfer_dma +
++					urb->iso_frame_desc[i].offset);
+ 	}
+ 
++	/* Set the interrupt-on-completion flag on the last packet. */
++	td->status |= __constant_cpu_to_le32(TD_CTRL_IOC);
++
++	qh->skel = uhci->skel_iso_qh;
++
++	/* Add the TDs to the frame list */
+ 	frame = urb->start_frame;
+ 	list_for_each_entry(td, &urbp->td_list, list) {
+-		uhci_insert_td_frame_list(uhci, td, frame);
++		uhci_insert_td_in_frame_list(uhci, td, frame);
+ 		frame += urb->interval;
+ 	}
+ 
+-	return -EINPROGRESS;
++	return 0;
+ }
+ 
+ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb)
+@@ -1139,80 +1083,67 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb)
+ 
+ 		i++;
+ 	}
+-	unlink_isochronous_tds(uhci, urb);
+ 
+ 	return ret;
+ }
+ 
+-static struct urb *uhci_find_urb_ep(struct uhci_hcd *uhci, struct urb *urb)
+-{
+-	struct urb_priv *up;
+-
+-	/* We don't match Isoc transfers since they are special */
+-	if (usb_pipeisoc(urb->pipe))
+-		return NULL;
+-
+-	list_for_each_entry(up, &uhci->urb_list, urb_list) {
+-		struct urb *u = up->urb;
+-
+-		if (u->dev == urb->dev && u->status == -EINPROGRESS) {
+-			/* For control, ignore the direction */
+-			if (usb_pipecontrol(urb->pipe) &&
+-			    (u->pipe & ~USB_DIR_IN) == (urb->pipe & ~USB_DIR_IN))
+-				return u;
+-			else if (u->pipe == urb->pipe)
+-				return u;
+-		}
+-	}
+-
+-	return NULL;
+-}
+-
+ static int uhci_urb_enqueue(struct usb_hcd *hcd,
+-		struct usb_host_endpoint *ep,
++		struct usb_host_endpoint *hep,
+ 		struct urb *urb, gfp_t mem_flags)
+ {
+ 	int ret;
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 	unsigned long flags;
+-	struct urb *eurb;
++	struct urb_priv *urbp;
++	struct uhci_qh *qh;
+ 	int bustime;
+ 
+ 	spin_lock_irqsave(&uhci->lock, flags);
+ 
+ 	ret = urb->status;
+ 	if (ret != -EINPROGRESS)		/* URB already unlinked! */
+-		goto out;
++		goto done;
+ 
+-	eurb = uhci_find_urb_ep(uhci, urb);
++	ret = -ENOMEM;
++	urbp = uhci_alloc_urb_priv(uhci, urb);
++	if (!urbp)
++		goto done;
+ 
+-	if (!uhci_alloc_urb_priv(uhci, urb)) {
+-		ret = -ENOMEM;
+-		goto out;
++	if (hep->hcpriv)
++		qh = (struct uhci_qh *) hep->hcpriv;
++	else {
++		qh = uhci_alloc_qh(uhci, urb->dev, hep);
++		if (!qh)
++			goto err_no_qh;
+ 	}
++	urbp->qh = qh;
+ 
+ 	switch (usb_pipetype(urb->pipe)) {
+ 	case PIPE_CONTROL:
+-		ret = uhci_submit_control(uhci, urb, eurb);
++		ret = uhci_submit_control(uhci, urb, qh);
++		break;
++	case PIPE_BULK:
++		ret = uhci_submit_bulk(uhci, urb, qh);
+ 		break;
+ 	case PIPE_INTERRUPT:
+-		if (!eurb) {
++		if (list_empty(&qh->queue)) {
+ 			bustime = usb_check_bandwidth(urb->dev, urb);
+ 			if (bustime < 0)
+ 				ret = bustime;
+ 			else {
+-				ret = uhci_submit_interrupt(uhci, urb, eurb);
+-				if (ret == -EINPROGRESS)
++				ret = uhci_submit_interrupt(uhci, urb, qh);
++				if (ret == 0)
+ 					usb_claim_bandwidth(urb->dev, urb, bustime, 0);
+ 			}
+ 		} else {	/* inherit from parent */
+-			urb->bandwidth = eurb->bandwidth;
+-			ret = uhci_submit_interrupt(uhci, urb, eurb);
++			struct urb_priv *eurbp;
++
++			eurbp = list_entry(qh->queue.prev, struct urb_priv,
++					node);
++			urb->bandwidth = eurbp->urb->bandwidth;
++			ret = uhci_submit_interrupt(uhci, urb, qh);
+ 		}
+ 		break;
+-	case PIPE_BULK:
+-		ret = uhci_submit_bulk(uhci, urb, eurb);
+-		break;
+ 	case PIPE_ISOCHRONOUS:
+ 		bustime = usb_check_bandwidth(urb->dev, urb);
+ 		if (bustime < 0) {
+@@ -1220,22 +1151,59 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd,
+ 			break;
+ 		}
+ 
+-		ret = uhci_submit_isochronous(uhci, urb);
+-		if (ret == -EINPROGRESS)
++		ret = uhci_submit_isochronous(uhci, urb, qh);
++		if (ret == 0)
+ 			usb_claim_bandwidth(urb->dev, urb, bustime, 1);
+ 		break;
+ 	}
++	if (ret != 0)
++		goto err_submit_failed;
+ 
+-	if (ret != -EINPROGRESS) {
+-		/* Submit failed, so delete it from the urb_list */
+-		struct urb_priv *urbp = urb->hcpriv;
++	/* Add this URB to the QH */
++	urbp->qh = qh;
++	list_add_tail(&urbp->node, &qh->queue);
++	list_add_tail(&urbp->urb_list, &uhci->urb_list);
+ 
+-		list_del_init(&urbp->urb_list);
+-		uhci_destroy_urb_priv(uhci, urb);
+-	} else
+-		ret = 0;
++	/* If the new URB is the first and only one on this QH then either
++	 * the QH is new and idle or else it's unlinked and waiting to
++	 * become idle, so we can activate it right away. */
++	if (qh->queue.next == &urbp->node)
++		uhci_activate_qh(uhci, qh);
++
++	/* If the QH is already active, we have a race with the hardware.
++	 * This won't get fixed until dummy TDs are added. */
++	else if (qh->state == QH_STATE_ACTIVE) {
++
++		/* If the URB isn't first on its queue, adjust the link pointer
++		 * of the last TD in the previous URB. */
++		if (urbp->node.prev != &urbp->qh->queue) {
++			struct urb_priv *purbp = list_entry(urbp->node.prev,
++					struct urb_priv, node);
++			struct uhci_td *ptd = list_entry(purbp->td_list.prev,
++					struct uhci_td, list);
++			struct uhci_td *td = list_entry(urbp->td_list.next,
++					struct uhci_td, list);
++
++			ptd->link = cpu_to_le32(td->dma_handle);
++
++		}
++		if (qh_element(qh) == UHCI_PTR_TERM) {
++			struct uhci_td *td = list_entry(urbp->td_list.next,
++					struct uhci_td, list);
++
++			qh->element = cpu_to_le32(td->dma_handle);
++		}
++	}
++	goto done;
++
++err_submit_failed:
++	if (qh->state == QH_STATE_IDLE)
++		uhci_make_qh_idle(uhci, qh);	/* Reclaim unused QH */
+ 
+-out:
++err_no_qh:
++	uhci_free_urb_priv(uhci, urbp);
++
++done:
+ 	spin_unlock_irqrestore(&uhci->lock, flags);
+ 	return ret;
+ }
+@@ -1245,119 +1213,115 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd,
+  */
+ static void uhci_transfer_result(struct uhci_hcd *uhci, struct urb *urb)
+ {
+-	int ret = -EINPROGRESS;
+-	struct urb_priv *urbp;
+-
+-	spin_lock(&urb->lock);
+-
+-	urbp = (struct urb_priv *)urb->hcpriv;
+-
+-	if (urb->status != -EINPROGRESS)	/* URB already dequeued */
+-		goto out;
++	int status;
++	int okay_to_giveback = 0;
++	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
+ 
+ 	switch (usb_pipetype(urb->pipe)) {
+ 	case PIPE_CONTROL:
+-		ret = uhci_result_control(uhci, urb);
+-		break;
+-	case PIPE_BULK:
+-	case PIPE_INTERRUPT:
+-		ret = uhci_result_common(uhci, urb);
++		status = uhci_result_control(uhci, urb);
+ 		break;
+ 	case PIPE_ISOCHRONOUS:
+-		ret = uhci_result_isochronous(uhci, urb);
++		status = uhci_result_isochronous(uhci, urb);
++		break;
++	default:	/* PIPE_BULK or PIPE_INTERRUPT */
++		status = uhci_result_common(uhci, urb);
+ 		break;
+ 	}
+ 
+-	if (ret == -EINPROGRESS)
+-		goto out;
+-	urb->status = ret;
++	spin_lock(&urb->lock);
++	if (urb->status == -EINPROGRESS) {	/* Not yet dequeued */
++		if (status != -EINPROGRESS) {	/* URB has completed */
++			urb->status = status;
++
++			/* If the URB got a real error (as opposed to
++			 * simply being dequeued), we don't have to
++			 * unlink the QH.  Fix this later... */
++			if (status < 0)
++				uhci_unlink_qh(uhci, urbp->qh);
++			else
++				okay_to_giveback = 1;
++		}
++	} else {				/* Already dequeued */
++		if (urbp->qh->state == QH_STATE_UNLINKING &&
++				uhci->frame_number + uhci->is_stopped !=
++				urbp->qh->unlink_frame)
++			okay_to_giveback = 1;
++	}
++	spin_unlock(&urb->lock);
++	if (!okay_to_giveback)
++		return;
+ 
+ 	switch (usb_pipetype(urb->pipe)) {
+-	case PIPE_CONTROL:
+-	case PIPE_BULK:
+ 	case PIPE_ISOCHRONOUS:
+ 		/* Release bandwidth for Interrupt or Isoc. transfers */
+ 		if (urb->bandwidth)
+ 			usb_release_bandwidth(urb->dev, urb, 1);
+-		uhci_unlink_generic(uhci, urb);
+ 		break;
+ 	case PIPE_INTERRUPT:
+ 		/* Release bandwidth for Interrupt or Isoc. transfers */
+ 		/* Make sure we don't release if we have a queued URB */
+-		if (list_empty(&urbp->queue_list) && urb->bandwidth)
++		if (list_empty(&urbp->qh->queue) && urb->bandwidth)
+ 			usb_release_bandwidth(urb->dev, urb, 0);
+ 		else
+ 			/* bandwidth was passed on to queued URB, */
+ 			/* so don't let usb_unlink_urb() release it */
+ 			urb->bandwidth = 0;
+-		uhci_unlink_generic(uhci, urb);
++		/* Falls through */
++	case PIPE_BULK:
++		if (status < 0)
++			uhci_fixup_toggles(urb);
++		break;
++	default:	/* PIPE_CONTROL */
+ 		break;
+-	default:
+-		dev_info(uhci_dev(uhci), "%s: unknown pipe type %d "
+-				"for urb %p\n",
+-				__FUNCTION__, usb_pipetype(urb->pipe), urb);
+ 	}
+ 
+-	/* Move it from uhci->urb_list to uhci->complete_list */
+-	uhci_moveto_complete(uhci, urbp);
++	/* Take the URB's TDs off the hardware schedule */
++	uhci_remove_tds_from_schedule(uhci, urb, status);
+ 
+-out:
+-	spin_unlock(&urb->lock);
+-}
+-
+-static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb)
+-{
+-	struct list_head *head;
+-	struct uhci_td *td;
+-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+-	int prevactive = 0;
++	/* Take the URB off the QH's queue and see if the QH is now unused */
++	list_del_init(&urbp->node);
++	if (list_empty(&urbp->qh->queue))
++		uhci_unlink_qh(uhci, urbp->qh);
+ 
+ 	uhci_dec_fsbr(uhci, urb);	/* Safe since it checks */
+ 
+-	/*
+-	 * Now we need to find out what the last successful toggle was
+-	 * so we can update the local data toggle for the next transfer
+-	 *
+-	 * There are 2 ways the last successful completed TD is found:
+-	 *
+-	 * 1) The TD is NOT active and the actual length < expected length
+-	 * 2) The TD is NOT active and it's the last TD in the chain
+-	 *
+-	 * and a third way the first uncompleted TD is found:
+-	 *
+-	 * 3) The TD is active and the previous TD is NOT active
+-	 *
+-	 * Control and Isochronous ignore the toggle, so this is safe
+-	 * for all types
+-	 *
+-	 * FIXME: The toggle fixups won't be 100% reliable until we
+-	 * change over to using a single queue for each endpoint and
+-	 * stop the queue before unlinking.
+-	 */
+-	head = &urbp->td_list;
+-	list_for_each_entry(td, head, list) {
+-		unsigned int ctrlstat = td_status(td);
++	/* Queue it for giving back */
++	list_move_tail(&urbp->urb_list, &uhci->complete_list);
++}
+ 
+-		if (!(ctrlstat & TD_CTRL_ACTIVE) &&
+-				(uhci_actual_length(ctrlstat) <
+-				 uhci_expected_length(td_token(td)) ||
+-				td->list.next == head))
+-			usb_settoggle(urb->dev, uhci_endpoint(td_token(td)),
+-				uhci_packetout(td_token(td)),
+-				uhci_toggle(td_token(td)) ^ 1);
+-		else if ((ctrlstat & TD_CTRL_ACTIVE) && !prevactive)
+-			usb_settoggle(urb->dev, uhci_endpoint(td_token(td)),
+-				uhci_packetout(td_token(td)),
+-				uhci_toggle(td_token(td)));
++/*
++ * Check out the QHs waiting to be fully unlinked
++ */
++static void uhci_scan_unlinking_qhs(struct uhci_hcd *uhci)
++{
++	struct uhci_qh *qh, *tmp;
+ 
+-		prevactive = ctrlstat & TD_CTRL_ACTIVE;
+-	}
++	list_for_each_entry_safe(qh, tmp, &uhci->skel_unlink_qh->node, node) {
+ 
+-	uhci_delete_queued_urb(uhci, urb);
++		/* If the queue is empty and the QH is fully unlinked then
++		 * it can become IDLE. */
++		if (list_empty(&qh->queue)) {
++			if (uhci->frame_number + uhci->is_stopped !=
++					qh->unlink_frame)
++				uhci_make_qh_idle(uhci, qh);
+ 
+-	/* The interrupt loop will reclaim the QHs */
+-	uhci_remove_qh(uhci, urbp->qh);
+-	urbp->qh = NULL;
++		/* If none of the QH's URBs have been dequeued then the QH
++		 * should be re-activated. */
++		} else {
++			struct urb_priv *urbp;
++			int any_dequeued = 0;
++
++			list_for_each_entry(urbp, &qh->queue, node) {
++				if (urbp->urb->status != -EINPROGRESS) {
++					any_dequeued = 1;
++					break;
++				}
++			}
++			if (!any_dequeued)
++				uhci_activate_qh(uhci, qh);
++		}
++	}
+ }
+ 
+ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
+@@ -1370,22 +1334,11 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
+ 	urbp = urb->hcpriv;
+ 	if (!urbp)			/* URB was never linked! */
+ 		goto done;
+-	list_del_init(&urbp->urb_list);
+ 
++	/* Remove Isochronous TDs from the frame list ASAP */
+ 	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
+-		unlink_isochronous_tds(uhci, urb);
+-	uhci_unlink_generic(uhci, urb);
+-
+-	uhci_get_current_frame_number(uhci);
+-	if (uhci->frame_number + uhci->is_stopped != uhci->urb_remove_age) {
+-		uhci_remove_pending_urbps(uhci);
+-		uhci->urb_remove_age = uhci->frame_number;
+-	}
+-
+-	/* If we're the first, set the next interrupt bit */
+-	if (list_empty(&uhci->urb_remove_list))
+-		uhci_set_next_interrupt(uhci);
+-	list_add_tail(&urbp->urb_list, &uhci->urb_remove_list);
++		uhci_unlink_isochronous_tds(uhci, urb);
++	uhci_unlink_qh(uhci, urbp->qh);
+ 
+ done:
+ 	spin_unlock_irqrestore(&uhci->lock, flags);
+@@ -1426,17 +1379,6 @@ static int uhci_fsbr_timeout(struct uhci_hcd *uhci, struct urb *urb)
+ 	return 0;
+ }
+ 
+-static void uhci_free_pending_qhs(struct uhci_hcd *uhci)
+-{
+-	struct uhci_qh *qh, *tmp;
+-
+-	list_for_each_entry_safe(qh, tmp, &uhci->qh_remove_list, remove_list) {
+-		list_del_init(&qh->remove_list);
+-
+-		uhci_free_qh(uhci, qh);
+-	}
+-}
+-
+ static void uhci_free_pending_tds(struct uhci_hcd *uhci)
+ {
+ 	struct uhci_td *td, *tmp;
+@@ -1455,7 +1397,7 @@ __acquires(uhci->lock)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 
+-	uhci_destroy_urb_priv(uhci, urb);
++	uhci_free_urb_priv(uhci, (struct urb_priv *) (urb->hcpriv));
+ 
+ 	spin_unlock(&uhci->lock);
+ 	usb_hcd_giveback_urb(hcd, urb, regs);
+@@ -1474,13 +1416,6 @@ static void uhci_finish_completion(struct uhci_hcd *uhci, struct pt_regs *regs)
+ 	}
+ }
+ 
+-static void uhci_remove_pending_urbps(struct uhci_hcd *uhci)
+-{
+-
+-	/* Splice the urb_remove_list onto the end of the complete_list */
+-	list_splice_init(&uhci->urb_remove_list, uhci->complete_list.prev);
+-}
+-
+ /* Process events in the schedule, but only in one thread at a time */
+ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs)
+ {
+@@ -1498,12 +1433,8 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs)
+ 	uhci_clear_next_interrupt(uhci);
+ 	uhci_get_current_frame_number(uhci);
+ 
+-	if (uhci->frame_number + uhci->is_stopped != uhci->qh_remove_age)
+-		uhci_free_pending_qhs(uhci);
+ 	if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age)
+ 		uhci_free_pending_tds(uhci);
+-	if (uhci->frame_number + uhci->is_stopped != uhci->urb_remove_age)
+-		uhci_remove_pending_urbps(uhci);
+ 
+ 	/* Walk the list of pending URBs to see which ones completed
+ 	 * (must be _safe because uhci_transfer_result() dequeues URBs) */
+@@ -1516,25 +1447,21 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs)
+ 	uhci_finish_completion(uhci, regs);
+ 
+ 	/* If the controller is stopped, we can finish these off right now */
+-	if (uhci->is_stopped) {
+-		uhci_free_pending_qhs(uhci);
++	if (uhci->is_stopped)
+ 		uhci_free_pending_tds(uhci);
+-		uhci_remove_pending_urbps(uhci);
+-	}
+ 
+ 	if (uhci->need_rescan)
+ 		goto rescan;
+ 	uhci->scan_in_progress = 0;
+ 
+-	if (list_empty(&uhci->urb_remove_list) &&
+-	    list_empty(&uhci->td_remove_list) &&
+-	    list_empty(&uhci->qh_remove_list))
++	/* Check out the QHs waiting for unlinking */
++	uhci_scan_unlinking_qhs(uhci);
++
++	if (list_empty(&uhci->td_remove_list) &&
++			list_empty(&uhci->skel_unlink_qh->node))
+ 		uhci_clear_next_interrupt(uhci);
+ 	else
+ 		uhci_set_next_interrupt(uhci);
+-
+-	/* Wake up anyone waiting for an URB to complete */
+-	wake_up_all(&uhci->waitqh);
+ }
+ 
+ static void check_fsbr(struct uhci_hcd *uhci)

commit aef4e266964bc15861b5835c1f5b9d2ebc155c2a
+Author: Alan Stern 
+Date:   Tue Jan 31 12:58:38 2006 -0500
+
+    [PATCH] usbhid: add error handling
+    
+    This patch (as628c) adds error handling to the USB HID core.  When an
+    error is reported for an interrupt URB, the driver will do delayed
+    retries, at increasing intervals, for up to one second.  If that doesn't
+    work, it will try to reset the device.  Testing by users has shown that
+    both the retries and the resets end up getting used.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
+index f187a719f17e..6b8a51cad375 100644
+--- a/drivers/usb/input/hid-core.c
++++ b/drivers/usb/input/hid-core.c
+@@ -902,6 +902,99 @@ static int hid_input_report(int type, struct urb *urb, int interrupt, struct pt_
+ 	return 0;
+ }
+ 
++/*
++ * Input submission and I/O error handler.
++ */
++
++static void hid_io_error(struct hid_device *hid);
++
++/* Start up the input URB */
++static int hid_start_in(struct hid_device *hid)
++{
++	unsigned long flags;
++	int rc = 0;
++
++	spin_lock_irqsave(&hid->inlock, flags);
++	if (hid->open > 0 && !test_bit(HID_SUSPENDED, &hid->iofl) &&
++			!test_and_set_bit(HID_IN_RUNNING, &hid->iofl)) {
++		rc = usb_submit_urb(hid->urbin, GFP_ATOMIC);
++		if (rc != 0)
++			clear_bit(HID_IN_RUNNING, &hid->iofl);
++	}
++	spin_unlock_irqrestore(&hid->inlock, flags);
++	return rc;
++}
++
++/* I/O retry timer routine */
++static void hid_retry_timeout(unsigned long _hid)
++{
++	struct hid_device *hid = (struct hid_device *) _hid;
++
++	dev_dbg(&hid->intf->dev, "retrying intr urb\n");
++	if (hid_start_in(hid))
++		hid_io_error(hid);
++}
++
++/* Workqueue routine to reset the device */
++static void hid_reset(void *_hid)
++{
++	struct hid_device *hid = (struct hid_device *) _hid;
++	int rc_lock, rc;
++
++	dev_dbg(&hid->intf->dev, "resetting device\n");
++	rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf);
++	if (rc_lock >= 0) {
++		rc = usb_reset_device(hid->dev);
++		if (rc_lock)
++			usb_unlock_device(hid->dev);
++	}
++	clear_bit(HID_RESET_PENDING, &hid->iofl);
++
++	if (rc == 0) {
++		hid->retry_delay = 0;
++		if (hid_start_in(hid))
++			hid_io_error(hid);
++	} else if (!(rc == -ENODEV || rc == -EHOSTUNREACH || rc == -EINTR))
++		err("can't reset device, %s-%s/input%d, status %d",
++				hid->dev->bus->bus_name,
++				hid->dev->devpath,
++				hid->ifnum, rc);
++}
++
++/* Main I/O error handler */
++static void hid_io_error(struct hid_device *hid)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&hid->inlock, flags);
++
++	/* Stop when disconnected */
++	if (usb_get_intfdata(hid->intf) == NULL)
++		goto done;
++
++	/* When an error occurs, retry at increasing intervals */
++	if (hid->retry_delay == 0) {
++		hid->retry_delay = 13;	/* Then 26, 52, 104, 104, ... */
++		hid->stop_retry = jiffies + msecs_to_jiffies(1000);
++	} else if (hid->retry_delay < 100)
++		hid->retry_delay *= 2;
++
++	if (time_after(jiffies, hid->stop_retry)) {
++
++		/* Retries failed, so do a port reset */
++		if (!test_and_set_bit(HID_RESET_PENDING, &hid->iofl)) {
++			if (schedule_work(&hid->reset_work))
++				goto done;
++			clear_bit(HID_RESET_PENDING, &hid->iofl);
++		}
++	}
++
++	mod_timer(&hid->io_retry,
++			jiffies + msecs_to_jiffies(hid->retry_delay));
++done:
++	spin_unlock_irqrestore(&hid->inlock, flags);
++}
++
+ /*
+  * Input interrupt completion handler.
+  */
+@@ -913,25 +1006,35 @@ static void hid_irq_in(struct urb *urb, struct pt_regs *regs)
+ 
+ 	switch (urb->status) {
+ 		case 0:			/* success */
++			hid->retry_delay = 0;
+ 			hid_input_report(HID_INPUT_REPORT, urb, 1, regs);
+ 			break;
+ 		case -ECONNRESET:	/* unlink */
+ 		case -ENOENT:
+-		case -EPERM:
+ 		case -ESHUTDOWN:	/* unplug */
+-		case -EILSEQ:		/* unplug timeout on uhci */
++			clear_bit(HID_IN_RUNNING, &hid->iofl);
+ 			return;
++		case -EILSEQ:		/* protocol error or unplug */
++		case -EPROTO:		/* protocol error or unplug */
+ 		case -ETIMEDOUT:	/* NAK */
+-			break;
++			clear_bit(HID_IN_RUNNING, &hid->iofl);
++			hid_io_error(hid);
++			return;
+ 		default:		/* error */
+ 			warn("input irq status %d received", urb->status);
+ 	}
+ 
+ 	status = usb_submit_urb(urb, SLAB_ATOMIC);
+-	if (status)
+-		err("can't resubmit intr, %s-%s/input%d, status %d",
+-				hid->dev->bus->bus_name, hid->dev->devpath,
+-				hid->ifnum, status);
++	if (status) {
++		clear_bit(HID_IN_RUNNING, &hid->iofl);
++		if (status != -EPERM) {
++			err("can't resubmit intr, %s-%s/input%d, status %d",
++					hid->dev->bus->bus_name,
++					hid->dev->devpath,
++					hid->ifnum, status);
++			hid_io_error(hid);
++		}
++	}
+ }
+ 
+ /*
+@@ -1093,8 +1196,9 @@ static void hid_irq_out(struct urb *urb, struct pt_regs *regs)
+ 		case 0:			/* success */
+ 			break;
+ 		case -ESHUTDOWN:	/* unplug */
+-		case -EILSEQ:		/* unplug timeout on uhci */
+ 			unplug = 1;
++		case -EILSEQ:		/* protocol error or unplug */
++		case -EPROTO:		/* protocol error or unplug */
+ 		case -ECONNRESET:	/* unlink */
+ 		case -ENOENT:
+ 			break;
+@@ -1141,8 +1245,9 @@ static void hid_ctrl(struct urb *urb, struct pt_regs *regs)
+ 				hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, 0, regs);
+ 			break;
+ 		case -ESHUTDOWN:	/* unplug */
+-		case -EILSEQ:		/* unplug timectrl on uhci */
+ 			unplug = 1;
++		case -EILSEQ:		/* protocol error or unplug */
++		case -EPROTO:		/* protocol error or unplug */
+ 		case -ECONNRESET:	/* unlink */
+ 		case -ENOENT:
+ 		case -EPIPE:		/* report not available */
+@@ -1255,14 +1360,9 @@ static int hid_get_class_descriptor(struct usb_device *dev, int ifnum,
+ 
+ int hid_open(struct hid_device *hid)
+ {
+-	if (hid->open++)
+-		return 0;
+-
+-	hid->urbin->dev = hid->dev;
+-
+-	if (usb_submit_urb(hid->urbin, GFP_KERNEL))
+-		return -EIO;
+-
++	++hid->open;
++	if (hid_start_in(hid))
++		hid_io_error(hid);
+ 	return 0;
+ }
+ 
+@@ -1787,6 +1887,10 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
+ 
+ 	init_waitqueue_head(&hid->wait);
+ 
++	INIT_WORK(&hid->reset_work, hid_reset, hid);
++	setup_timer(&hid->io_retry, hid_retry_timeout, (unsigned long) hid);
++
++	spin_lock_init(&hid->inlock);
+ 	spin_lock_init(&hid->outlock);
+ 	spin_lock_init(&hid->ctrllock);
+ 
+@@ -1855,11 +1959,16 @@ static void hid_disconnect(struct usb_interface *intf)
+ 	if (!hid)
+ 		return;
+ 
++	spin_lock_irq(&hid->inlock);	/* Sync with error handler */
+ 	usb_set_intfdata(intf, NULL);
++	spin_unlock_irq(&hid->inlock);
+ 	usb_kill_urb(hid->urbin);
+ 	usb_kill_urb(hid->urbout);
+ 	usb_kill_urb(hid->urbctrl);
+ 
++	del_timer_sync(&hid->io_retry);
++	flush_scheduled_work();
++
+ 	if (hid->claimed & HID_CLAIMED_INPUT)
+ 		hidinput_disconnect(hid);
+ 	if (hid->claimed & HID_CLAIMED_HIDDEV)
+@@ -1934,6 +2043,10 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
+ {
+ 	struct hid_device *hid = usb_get_intfdata (intf);
+ 
++	spin_lock_irq(&hid->inlock);	/* Sync with error handler */
++	set_bit(HID_SUSPENDED, &hid->iofl);
++	spin_unlock_irq(&hid->inlock);
++	del_timer(&hid->io_retry);
+ 	usb_kill_urb(hid->urbin);
+ 	dev_dbg(&intf->dev, "suspend\n");
+ 	return 0;
+@@ -1944,10 +2057,8 @@ static int hid_resume(struct usb_interface *intf)
+ 	struct hid_device *hid = usb_get_intfdata (intf);
+ 	int status;
+ 
+-	if (hid->open)
+-		status = usb_submit_urb(hid->urbin, GFP_NOIO);
+-	else
+-		status = 0;
++	clear_bit(HID_SUSPENDED, &hid->iofl);
++	status = hid_start_in(hid);
+ 	dev_dbg(&intf->dev, "resume status %d\n", status);
+ 	return status;
+ }
+diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
+index 8b0d4346ce9c..4e1b784fe527 100644
+--- a/drivers/usb/input/hid.h
++++ b/drivers/usb/input/hid.h
+@@ -31,6 +31,8 @@
+ #include 
+ #include 
+ #include 
++#include 
++#include 
+ 
+ /*
+  * USB HID (Human Interface Device) interface class code
+@@ -370,6 +372,9 @@ struct hid_control_fifo {
+ 
+ #define HID_CTRL_RUNNING	1
+ #define HID_OUT_RUNNING		2
++#define HID_IN_RUNNING		3
++#define HID_RESET_PENDING	4
++#define HID_SUSPENDED		5
+ 
+ struct hid_input {
+ 	struct list_head list;
+@@ -393,12 +398,17 @@ struct hid_device {							/* device report descriptor */
+ 	int ifnum;							/* USB interface number */
+ 
+ 	unsigned long iofl;						/* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
++	struct timer_list io_retry;					/* Retry timer */
++	unsigned long stop_retry;					/* Time to give up, in jiffies */
++	unsigned int retry_delay;					/* Delay length in ms */
++	struct work_struct reset_work;					/* Task context for resets */
+ 
+ 	unsigned int bufsize;						/* URB buffer size */
+ 
+ 	struct urb *urbin;						/* Input URB */
+ 	char *inbuf;							/* Input buffer */
+ 	dma_addr_t inbuf_dma;						/* Input buffer dma */
++	spinlock_t inlock;						/* Input fifo spinlock */
+ 
+ 	struct urb *urbctrl;						/* Control URB */
+ 	struct usb_ctrlrequest *cr;					/* Control request struct */

commit 754501b324fc3c42522a46d3ace205e7a6a50e77
+Author: Alan Stern 
+Date:   Thu Feb 23 10:19:25 2006 -0500
+
+    [PATCH] USB: unusual_devs entry for Lyra RCA RD1080
+    
+    This patch (as656) adds an unusual_devs.h entry for the Lyra RCA RD1080
+    MP3 player.  Its card-reader firmware has the common
+    report-one-too-many-sectors bug.  This fixes Novell bug #152175.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index e71c5ca1a07b..31ca92056c27 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -753,6 +753,13 @@ UNUSUAL_DEV(  0x0693, 0x0005, 0x0100, 0x0100,
+ 		"Flashgate",
+ 		US_SC_SCSI, US_PR_BULK, NULL, 0 ), 
+ 
++/* Reported by David Hamilton  */
++UNUSUAL_DEV(  0x069b, 0x3004, 0x0001, 0x0001,
++		"Thomson Multimedia Inc.",
++		"RCA RD1080 MP3 Player",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_FIX_CAPACITY ),
++
+ UNUSUAL_DEV(  0x0781, 0x0001, 0x0200, 0x0200, 
+ 		"Sandisk",
+ 		"ImageMate SDDR-05a",

commit 1bfc5d9d5eb8e1a2efacc306bc55c248ed259a8e
+Author: Alan Stern 
+Date:   Thu Feb 9 15:26:18 2006 -0500
+
+    [SCSI] Recognize missing LUNs for non-standard devices
+    
+    Some non-standard SCSI targets or protocols, such as USB UFI, report "no
+    LUN present" by setting the Peripheral Device Type to 0x1f and the
+    Peripheral Qualifier to 0 (not 3 as the standard requires) in the INQUIRY
+    response.  This patch (as650b) adds a new target flag and code to
+    accomodate such targets.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+index 803c7b9690c5..94b86d5b1469 100644
+--- a/drivers/scsi/scsi_scan.c
++++ b/drivers/scsi/scsi_scan.c
+@@ -853,6 +853,19 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
+ 		goto out_free_result;
+ 	}
+ 
++	/*
++	 * Non-standard SCSI targets may set the PDT to 0x1f (unknown or
++	 * no device type) instead of using the Peripheral Qualifier to
++	 * indicate that no LUN is present.  For example, USB UFI does this.
++	 */
++	if (starget->pdt_1f_for_no_lun && (result[0] & 0x1f) == 0x1f) {
++		SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO
++					"scsi scan: peripheral device type"
++					" of 31, no device added\n"));
++		res = SCSI_SCAN_TARGET_PRESENT;
++		goto out_free_result;
++	}
++
+ 	res = scsi_add_lun(sdev, result, &bflags);
+ 	if (res == SCSI_SCAN_LUN_PRESENT) {
+ 		if (bflags & BLIST_KEY) {
+diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
+index cde84b39bb65..8d77da932d2c 100644
+--- a/include/scsi/scsi_device.h
++++ b/include/scsi/scsi_device.h
+@@ -167,7 +167,10 @@ struct scsi_target {
+ 	unsigned int		channel;
+ 	unsigned int		id; /* target id ... replace
+ 				     * scsi_device.id eventually */
+-	unsigned long		create:1; /* signal that it needs to be added */
++	unsigned int		create:1; /* signal that it needs to be added */
++	unsigned int		pdt_1f_for_no_lun;	/* PDT = 0x1f */
++						/* means no lun present */
++
+ 	char			scsi_level;
+ 	void 			*hostdata; /* available to low-level driver */
+ 	unsigned long		starget_data[0]; /* for the transport */

commit 982db2a127b29c9e1f5896d2ba691e84446cc858
+Author: Alan Stern 
+Date:   Mon Feb 13 10:16:04 2006 -0500
+
+    [PATCH] USB: unusual_devs.h entry: iAUDIO M5
+    
+    Another unusual_devs.h entry (as652).
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 1d8a739ccc96..7e1cb03c2ed7 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -1098,6 +1098,13 @@ UNUSUAL_DEV(  0x0dda, 0x0301, 0x0012, 0x0012,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_IGNORE_RESIDUE ),
+ 
++/* Reported by Jim McCloskey  */
++UNUSUAL_DEV( 0x0e21, 0x0520, 0x0100, 0x0100,
++		"Cowon Systems",
++		"iAUDIO M5",
++		US_SC_DEVICE, US_PR_BULK, NULL,
++		0 ),
++
+ /* Submitted by Antoine Mairesse  */
+ UNUSUAL_DEV( 0x0ed1, 0x6660, 0x0100, 0x0300,
+ 		"USB",

commit 1d614a4b0d2613d83f7bf0978e213ba29aebc44f
+Author: Alan Stern 
+Date:   Mon Feb 13 10:15:22 2006 -0500
+
+    [PATCH] USB: unusual_devs.h entry: TrekStor i.Beat
+    
+    A new unusual_devs.h entry (as651).
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 6e326159c2dd..1d8a739ccc96 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -106,6 +106,13 @@ UNUSUAL_DEV(  0x0411, 0x001c, 0x0113, 0x0113,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_FIX_INQUIRY ),
+ 
++/* Reported by Christian Leber  */
++UNUSUAL_DEV(  0x0419, 0xaaf5, 0x0100, 0x0100,
++		"TrekStor",
++		"i.Beat 115 2.0",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_IGNORE_RESIDUE | US_FL_NOT_LOCKABLE ),
++
+ /* Reported by Stefan Werner  */
+ UNUSUAL_DEV(  0x0419, 0xaaf6, 0x0100, 0x0100,
+ 		"TrekStor",

commit ba3e93ad3c6e511f68c1b3e46954feff6cdd5a62
+Author: Alan Stern 
+Date:   Mon Jan 30 10:19:43 2006 -0500
+
+    [PATCH] usb-storage: unusual_devs entry
+    
+    Here is a new entry for unusual_devs.h (as630).
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index c5d6d84b9b2b..6e326159c2dd 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -946,6 +946,12 @@ UNUSUAL_DEV(  0x084d, 0x0011, 0x0110, 0x0110,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_BULK32),
+ 
++/* Submitted by Jan De Luyck  */
++UNUSUAL_DEV(  0x08bd, 0x1100, 0x0000, 0x0000,
++		"CITIZEN",
++		"X1DE-USB",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_SINGLE_LUN),
+ 
+ /* Entry needed for flags. Moreover, all devices with this ID use
+  * bulk-only transport, but _some_ falsely report Control/Bulk instead.

commit a2149bce2535047371a1309f032f0320b05db791
+Author: Alan Stern 
+Date:   Thu Feb 2 09:52:45 2006 -0500
+
+    [PATCH] usb-storage: new unusual_devs entry
+    
+    This patch (as631) for unusual_devs.h fixes bugzilla entry 5913.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Phil Dibowitz 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index ee958f986eb8..c5d6d84b9b2b 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -1162,6 +1162,13 @@ UNUSUAL_DEV(  0x55aa, 0xa103, 0x0000, 0x9999,
+ 		US_FL_SINGLE_LUN),
+ #endif
+ 
++/* Reported by Andrew Simmons  */
++UNUSUAL_DEV(  0xed06, 0x4500, 0x0001, 0x0001,
++		"DataStor",
++		"USB4500 FW1.04",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_FIX_CAPACITY),
++
+ /* Control/Bulk transport for all SubClass values */
+ USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR),
+ USUAL_DEV(US_SC_8020, US_PR_CB, USB_US_TYPE_STOR),

commit 979063692726fa40863345fb1b62daf2f795ddc0
+Author: Alan Stern 
+Date:   Tue Jan 3 10:30:31 2006 -0500
+
+    [PATCH] USB: gadgetfs: set "zero" flag for short control-IN response
+    
+    This patch (as622) makes gadgetfs set the "zero" flag for control-IN
+    responses, when the length of the response is shorter than the length of
+    the request.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
+index 9a4edc5657aa..0aab7d24c768 100644
+--- a/drivers/usb/gadget/inode.c
++++ b/drivers/usb/gadget/inode.c
+@@ -135,6 +135,7 @@ struct dev_data {
+ 					setup_out_ready : 1,
+ 					setup_out_error : 1,
+ 					setup_abort : 1;
++	unsigned			setup_wLength;
+ 
+ 	/* the rest is basically write-once */
+ 	struct usb_config_descriptor	*config, *hs_config;
+@@ -942,6 +943,7 @@ static int setup_req (struct usb_ep *ep, struct usb_request *req, u16 len)
+ 	}
+ 	req->complete = ep0_complete;
+ 	req->length = len;
++	req->zero = 0;
+ 	return 0;
+ }
+ 
+@@ -1161,10 +1163,13 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
+ 				spin_unlock_irq (&dev->lock);
+ 				if (copy_from_user (dev->req->buf, buf, len))
+ 					retval = -EFAULT;
+-				else
++				else {
++					if (len < dev->setup_wLength)
++						dev->req->zero = 1;
+ 					retval = usb_ep_queue (
+ 						dev->gadget->ep0, dev->req,
+ 						GFP_KERNEL);
++				}
+ 				if (retval < 0) {
+ 					spin_lock_irq (&dev->lock);
+ 					clean_req (dev->gadget->ep0, dev->req);
+@@ -1483,6 +1488,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
+ delegate:
+ 			dev->setup_in = (ctrl->bRequestType & USB_DIR_IN)
+ 						? 1 : 0;
++			dev->setup_wLength = w_length;
+ 			dev->setup_out_ready = 0;
+ 			dev->setup_out_error = 0;
+ 			value = 0;

commit 630aa3cfd5f0bae9547fe7dff175d7323d60140d
+Author: Alan Stern 
+Date:   Mon Jan 23 17:17:21 2006 -0500
+
+    [PATCH] USB: UHCI: No FSBR until device is configured
+    
+    Some USB devices don't enumerate well with FSBR turned on.  This patch
+    keeps devices on the low-speed part of the schedule (which doesn't use
+    FSBR) until they have been fully configured.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index b6076004a437..782398045f9f 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -672,9 +672,9 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
+ 	/* Low-speed transfers get a different queue, and won't hog the bus.
+ 	 * Also, some devices enumerate better without FSBR; the easiest way
+ 	 * to do that is to put URBs on the low-speed queue while the device
+-	 * is in the DEFAULT state. */
++	 * isn't in the CONFIGURED state. */
+ 	if (urb->dev->speed == USB_SPEED_LOW ||
+-			urb->dev->state == USB_STATE_DEFAULT)
++			urb->dev->state != USB_STATE_CONFIGURED)
+ 		skelqh = uhci->skel_ls_control_qh;
+ 	else {
+ 		skelqh = uhci->skel_fs_control_qh;

commit bf74ad5bc41727d5f2f1c6bedb2c1fac394de731
+Author: Alan Stern 
+Date:   Thu Nov 17 16:54:12 2005 -0500
+
+    [PATCH] Hold the device's parent's lock during probe and remove
+    
+    This patch (as604) makes the driver core hold a device's parent's lock
+    as well as the device's lock during calls to the probe and remove
+    methods in a driver.  This facility is needed by USB device drivers,
+    owing to the peculiar way USB devices work:
+    
+            A device provides multiple interfaces, and drivers are bound
+            to interfaces rather than to devices;
+    
+            Nevertheless a reset, reset-configuration, suspend, or resume
+            affects the entire device and requires the caller to hold the
+            lock for the device, not just a lock for one of the interfaces.
+    
+    Since a USB driver's probe method is always called with the interface
+    lock held, the locking order rules (always lock parent before child)
+    prevent these methods from acquiring the device lock.  The solution
+    provided here is to call all probe and remove methods, for all devices
+    (not just USB), with the parent lock already acquired.
+    
+    Although currently only the USB subsystem requires these changes, people
+    have mentioned in prior discussion that the overhead of acquiring an
+    extra semaphore in all the prove/remove sequences is not overly large.
+    
+    Up to now, the USB core has been using its own set of private
+    semaphores.  A followup patch will remove them, relying entirely on the
+    device semaphores provided by the driver core.
+    
+    The code paths affected by this patch are:
+    
+            device_add and device_del: The USB core already holds the parent
+            lock, so no actual change is needed.
+    
+            driver_register and driver_unregister: The driver core will now
+            lock both the parent and the device before probing or removing.
+    
+            driver_bind and driver_unbind (in sysfs): These routines will
+            now lock both the parent and the device before binding or
+            unbinding.
+    
+            bus_rescan_devices: The helper routine will lock the parent
+            before probing a device.
+    
+    I have not tested this patch for conflicts with other subsystems.  As
+    far as I can see, the only possibility of conflict would lie in the
+    bus_rescan_devices pathway, and it seems pretty remote.  Nevertheless,
+    it would be good for this to get a lot of testing in -mm.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/base/bus.c b/drivers/base/bus.c
+index fa601b085eba..e3f915a24891 100644
+--- a/drivers/base/bus.c
++++ b/drivers/base/bus.c
+@@ -152,7 +152,11 @@ static ssize_t driver_unbind(struct device_driver *drv,
+ 
+ 	dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
+ 	if (dev && dev->driver == drv) {
++		if (dev->parent)	/* Needed for USB */
++			down(&dev->parent->sem);
+ 		device_release_driver(dev);
++		if (dev->parent)
++			up(&dev->parent->sem);
+ 		err = count;
+ 	}
+ 	put_device(dev);
+@@ -175,9 +179,13 @@ static ssize_t driver_bind(struct device_driver *drv,
+ 
+ 	dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
+ 	if (dev && dev->driver == NULL) {
++		if (dev->parent)	/* Needed for USB */
++			down(&dev->parent->sem);
+ 		down(&dev->sem);
+ 		err = driver_probe_device(drv, dev);
+ 		up(&dev->sem);
++		if (dev->parent)
++			up(&dev->parent->sem);
+ 	}
+ 	put_device(dev);
+ 	put_bus(bus);
+@@ -484,8 +492,13 @@ void bus_remove_driver(struct device_driver * drv)
+ /* Helper for bus_rescan_devices's iter */
+ static int bus_rescan_devices_helper(struct device *dev, void *data)
+ {
+-	if (!dev->driver)
++	if (!dev->driver) {
++		if (dev->parent)	/* Needed for USB */
++			down(&dev->parent->sem);
+ 		device_attach(dev);
++		if (dev->parent)
++			up(&dev->parent->sem);
++	}
+ 	return 0;
+ }
+ 
+diff --git a/drivers/base/dd.c b/drivers/base/dd.c
+index 3b419c9a1e7e..2b905016664d 100644
+--- a/drivers/base/dd.c
++++ b/drivers/base/dd.c
+@@ -65,7 +65,8 @@ void device_bind_driver(struct device * dev)
+  *	This function returns 1 if a match is found, an error if one
+  *	occurs (that is not -ENODEV or -ENXIO), and 0 otherwise.
+  *
+- *	This function must be called with @dev->sem held.
++ *	This function must be called with @dev->sem held.  When called
++ *	for a USB interface, @dev->parent->sem must be held as well.
+  */
+ int driver_probe_device(struct device_driver * drv, struct device * dev)
+ {
+@@ -123,6 +124,8 @@ static int __device_attach(struct device_driver * drv, void * data)
+  *
+  *	Returns 1 if the device was bound to a driver;
+  *	0 if no matching device was found; error code otherwise.
++ *
++ *	When called for a USB interface, @dev->parent->sem must be held.
+  */
+ int device_attach(struct device * dev)
+ {
+@@ -152,10 +155,14 @@ static int __driver_attach(struct device * dev, void * data)
+ 	 * is an error.
+ 	 */
+ 
++	if (dev->parent)	/* Needed for USB */
++		down(&dev->parent->sem);
+ 	down(&dev->sem);
+ 	if (!dev->driver)
+ 		driver_probe_device(drv, dev);
+ 	up(&dev->sem);
++	if (dev->parent)
++		up(&dev->parent->sem);
+ 
+ 	return 0;
+ }
+@@ -181,6 +188,8 @@ void driver_attach(struct device_driver * drv)
+  *	Manually detach device from driver.
+  *
+  *	__device_release_driver() must be called with @dev->sem held.
++ *	When called for a USB interface, @dev->parent->sem must be held
++ *	as well.
+  */
+ 
+ static void __device_release_driver(struct device * dev)
+@@ -233,10 +242,14 @@ void driver_detach(struct device_driver * drv)
+ 		get_device(dev);
+ 		spin_unlock(&drv->klist_devices.k_lock);
+ 
++		if (dev->parent)	/* Needed for USB */
++			down(&dev->parent->sem);
+ 		down(&dev->sem);
+ 		if (dev->driver == drv)
+ 			__device_release_driver(dev);
+ 		up(&dev->sem);
++		if (dev->parent)
++			up(&dev->parent->sem);
+ 		put_device(dev);
+ 	}
+ }

commit f3d34ed48c80903544b509031fee64838d29f35f
+Author: Alan Stern 
+Date:   Tue Dec 13 10:32:13 2005 -0500
+
+    [PATCH] USB: fix local variable clash
+    
+    This patch (as621) fixes a local variable conflict I accidently
+    introduced into usb_set_configuration.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 99ab774d4fdb..319de03944e7 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1387,11 +1387,11 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 	if (dev->state != USB_STATE_ADDRESS)
+ 		usb_disable_device (dev, 1);	// Skip ep0
+ 
+-	n = dev->bus_mA - cp->desc.bMaxPower * 2;
+-	if (n < 0)
++	i = dev->bus_mA - cp->desc.bMaxPower * 2;
++	if (i < 0)
+ 		dev_warn(&dev->dev, "new config #%d exceeds power "
+ 				"limit by %dmA\n",
+-				configuration, -n);
++				configuration, -i);
+ 
+ 	if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ 			USB_REQ_SET_CONFIGURATION, 0, configuration, 0,

commit 687f5f3428157bea4940dd967fd7b4e59c1b13b4
+Author: Alan Stern 
+Date:   Wed Nov 30 17:16:19 2005 -0500
+
+    [PATCH] USB: UHCI: edit some comments
+    
+    This patch (as615b) edits a large number of comments in the uhci-hcd code,
+    mainly removing excess apostrophes.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
+index cab02e15bfee..5832953086f8 100644
+--- a/drivers/usb/host/uhci-debug.c
++++ b/drivers/usb/host/uhci-debug.c
+@@ -2,8 +2,8 @@
+  * UHCI-specific debugging code. Invaluable when something
+  * goes wrong, but don't get in my face.
+  *
+- * Kernel visible pointers are surrounded in []'s and bus
+- * visible pointers are surrounded in ()'s
++ * Kernel visible pointers are surrounded in []s and bus
++ * visible pointers are surrounded in ()s
+  *
+  * (C) Copyright 1999 Linus Torvalds
+  * (C) Copyright 1999-2001 Johannes Erdfelt
+@@ -19,7 +19,7 @@
+ 
+ static struct dentry *uhci_debugfs_root = NULL;
+ 
+-/* Handle REALLY large printk's so we don't overflow buffers */
++/* Handle REALLY large printks so we don't overflow buffers */
+ static inline void lprintk(char *buf)
+ {
+ 	char *p;
+@@ -160,7 +160,7 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
+ 			}
+ 
+ 			if (active && ni > i) {
+-				out += sprintf(out, "%*s[skipped %d active TD's]\n", space, "", ni - i);
++				out += sprintf(out, "%*s[skipped %d active TDs]\n", space, "", ni - i);
+ 				tmp = ntmp;
+ 				td = ntd;
+ 				i = ni;
+@@ -173,7 +173,7 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
+ 	if (list_empty(&urbp->queue_list) || urbp->queued)
+ 		goto out;
+ 
+-	out += sprintf(out, "%*sQueued QH's:\n", -space, "--");
++	out += sprintf(out, "%*sQueued QHs:\n", -space, "--");
+ 
+ 	head = &urbp->queue_list;
+ 	tmp = head->next;
+@@ -464,7 +464,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
+ 		} while (tmp != head);
+ 	}
+ 
+-	out += sprintf(out, "Skeleton QH's\n");
++	out += sprintf(out, "Skeleton QHs\n");
+ 
+ 	for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
+ 		int shown = 0;
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 120ca64fe3f7..dfe121d35887 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -62,10 +62,10 @@ Alan Stern"
+ 
+ /*
+  * debug = 0, no debugging messages
+- * debug = 1, dump failed URB's except for stalls
+- * debug = 2, dump all failed URB's (including stalls)
++ * debug = 1, dump failed URBs except for stalls
++ * debug = 2, dump all failed URBs (including stalls)
+  *            show all queues in /debug/uhci/[pci_addr]
+- * debug = 3, show all TD's in URB's when dumping
++ * debug = 3, show all TDs in URBs when dumping
+  */
+ #ifdef DEBUG
+ static int debug = 1;
+@@ -88,7 +88,7 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
+ #define FSBR_DELAY	msecs_to_jiffies(50)
+ 
+ /* When we timeout an idle transfer for FSBR, we'll switch it over to */
+-/* depth first traversal. We'll do it in groups of this number of TD's */
++/* depth first traversal. We'll do it in groups of this number of TDs */
+ /* to make sure it doesn't hog all of the bandwidth */
+ #define DEPTH_INTERVAL 5
+ 
+@@ -728,8 +728,9 @@ static int uhci_resume(struct usb_hcd *hcd)
+ 
+ 	dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
+ 
+-	/* We aren't in D3 state anymore, we do that even if dead as I
+-	 * really don't want to keep a stale HCD_FLAG_HW_ACCESSIBLE=0
++	/* Since we aren't in D3 any more, it's safe to set this flag
++	 * even if the controller was dead.  It might not even be dead
++	 * any more, if the firmware or quirks code has reset it.
+ 	 */
+ 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ 	mb();
+@@ -879,7 +880,7 @@ static int __init uhci_hcd_init(void)
+ 
+ init_failed:
+ 	if (kmem_cache_destroy(uhci_up_cachep))
+-		warn("not all urb_priv's were freed!");
++		warn("not all urb_privs were freed!");
+ 
+ up_failed:
+ 	debugfs_remove(uhci_debugfs_root);
+@@ -897,7 +898,7 @@ static void __exit uhci_hcd_cleanup(void)
+ 	pci_unregister_driver(&uhci_pci_driver);
+ 	
+ 	if (kmem_cache_destroy(uhci_up_cachep))
+-		warn("not all urb_priv's were freed!");
++		warn("not all urb_privs were freed!");
+ 
+ 	debugfs_remove(uhci_debugfs_root);
+ 	kfree(errbuf);
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index e43282e4e806..8b4b887a7d41 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -223,10 +223,10 @@ static u32 inline td_status(struct uhci_td *td) {
+  */
+ 
+ /*
+- * The UHCI driver places Interrupt, Control and Bulk into QH's both
+- * to group together TD's for one transfer, and also to faciliate queuing
+- * of URB's. To make it easy to insert entries into the schedule, we have
+- * a skeleton of QH's for each predefined Interrupt latency, low-speed
++ * The UHCI driver places Interrupt, Control and Bulk into QHs both
++ * to group together TDs for one transfer, and also to facilitate queuing
++ * of URBs. To make it easy to insert entries into the schedule, we have
++ * a skeleton of QHs for each predefined Interrupt latency, low-speed
+  * control, full-speed control and terminating QH (see explanation for
+  * the terminating QH below).
+  *
+@@ -257,8 +257,8 @@ static u32 inline td_status(struct uhci_td *td) {
+  *   reclamation.
+  *
+  * Isochronous transfers are stored before the start of the skeleton
+- * schedule and don't use QH's. While the UHCI spec doesn't forbid the
+- * use of QH's for Isochronous, it doesn't use them either. And the spec
++ * schedule and don't use QHs. While the UHCI spec doesn't forbid the
++ * use of QHs for Isochronous, it doesn't use them either. And the spec
+  * says that queues never advance on an error completion status, which
+  * makes them totally unsuitable for Isochronous transfers.
+  */
+@@ -359,7 +359,7 @@ struct uhci_hcd {
+ 	struct dma_pool *td_pool;
+ 
+ 	struct uhci_td *term_td;	/* Terminating TD, see UHCI bug */
+-	struct uhci_qh *skelqh[UHCI_NUM_SKELQH];	/* Skeleton QH's */
++	struct uhci_qh *skelqh[UHCI_NUM_SKELQH];	/* Skeleton QHs */
+ 
+ 	spinlock_t lock;
+ 
+@@ -389,22 +389,22 @@ struct uhci_hcd {
+ 	unsigned long resuming_ports;
+ 	unsigned long ports_timeout;		/* Time to stop signalling */
+ 
+-	/* Main list of URB's currently controlled by this HC */
++	/* Main list of URBs currently controlled by this HC */
+ 	struct list_head urb_list;
+ 
+-	/* List of QH's that are done, but waiting to be unlinked (race) */
++	/* List of QHs that are done, but waiting to be unlinked (race) */
+ 	struct list_head qh_remove_list;
+ 	unsigned int qh_remove_age;		/* Age in frames */
+ 
+-	/* List of TD's that are done, but waiting to be freed (race) */
++	/* List of TDs that are done, but waiting to be freed (race) */
+ 	struct list_head td_remove_list;
+ 	unsigned int td_remove_age;		/* Age in frames */
+ 
+-	/* List of asynchronously unlinked URB's */
++	/* List of asynchronously unlinked URBs */
+ 	struct list_head urb_remove_list;
+ 	unsigned int urb_remove_age;		/* Age in frames */
+ 
+-	/* List of URB's awaiting completion callback */
++	/* List of URBs awaiting completion callback */
+ 	struct list_head complete_list;
+ 
+ 	int rh_numports;			/* Number of root-hub ports */
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index ace9d15f85d2..b6076004a437 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -80,7 +80,7 @@ static inline void uhci_fill_td(struct uhci_td *td, u32 status,
+ }
+ 
+ /*
+- * We insert Isochronous URB's directly into the frame list at the beginning
++ * We insert Isochronous URBs directly into the frame list at the beginning
+  */
+ static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td, unsigned framenum)
+ {
+@@ -369,7 +369,7 @@ static void uhci_append_queued_urb(struct uhci_hcd *uhci, struct urb *eurb, stru
+ 				uhci_fixup_toggle(urb,
+ 					uhci_toggle(td_token(lltd)) ^ 1));
+ 
+-	/* All qh's in the queue need to link to the next queue */
++	/* All qhs in the queue need to link to the next queue */
+ 	urbp->qh->link = eurbp->qh->link;
+ 
+ 	wmb();			/* Make sure we flush everything */
+@@ -502,7 +502,7 @@ static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
+ 	}
+ 
+ 	/* Check to see if the remove list is empty. Set the IOC bit */
+-	/* to force an interrupt so we can remove the TD's*/
++	/* to force an interrupt so we can remove the TDs*/
+ 	if (list_empty(&uhci->td_remove_list))
+ 		uhci_set_next_interrupt(uhci);
+ 
+@@ -612,7 +612,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
+ 	}
+ 
+ 	/*
+-	 * Build the DATA TD's
++	 * Build the DATA TDs
+ 	 */
+ 	while (len > 0) {
+ 		int pktsze = len;
+@@ -744,7 +744,7 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
+ 
+ 	urb->actual_length = 0;
+ 
+-	/* The rest of the TD's (but the last) are data */
++	/* The rest of the TDs (but the last) are data */
+ 	tmp = tmp->next;
+ 	while (tmp != head && tmp->next != head) {
+ 		unsigned int ctrlstat;
+@@ -848,7 +848,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb
+ 		status |= TD_CTRL_SPD;
+ 
+ 	/*
+-	 * Build the DATA TD's
++	 * Build the DATA TDs
+ 	 */
+ 	do {	/* Allow zero length packets */
+ 		int pktsze = maxsze;
+@@ -1025,7 +1025,7 @@ static int isochronous_find_limits(struct uhci_hcd *uhci, struct urb *urb, unsig
+ 	list_for_each_entry(up, &uhci->urb_list, urb_list) {
+ 		struct urb *u = up->urb;
+ 
+-		/* look for pending URB's with identical pipe handle */
++		/* look for pending URBs with identical pipe handle */
+ 		if ((urb->pipe == u->pipe) && (urb->dev == u->dev) &&
+ 		    (u->status == -EINPROGRESS) && (u != urb)) {
+ 			if (!last_urb)
+@@ -1355,7 +1355,7 @@ static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb)
+ 
+ 	uhci_delete_queued_urb(uhci, urb);
+ 
+-	/* The interrupt loop will reclaim the QH's */
++	/* The interrupt loop will reclaim the QHs */
+ 	uhci_remove_qh(uhci, urbp->qh);
+ 	urbp->qh = NULL;
+ }
+@@ -1413,7 +1413,7 @@ static int uhci_fsbr_timeout(struct uhci_hcd *uhci, struct urb *urb)
+ 	list_for_each_entry(td, head, list) {
+ 		/*
+ 		 * Make sure we don't do the last one (since it'll have the
+-		 * TERM bit set) as well as we skip every so many TD's to
++		 * TERM bit set) as well as we skip every so many TDs to
+ 		 * make sure it doesn't hog the bandwidth
+ 		 */
+ 		if (td->list.next != head && (count % DEPTH_INTERVAL) ==

commit fa3465689f93331834a831bbe98e3863701e1068
+Author: Alan Stern 
+Date:   Wed Nov 30 11:57:51 2005 -0500
+
+    [PATCH] USB: UHCI: change uhci_explen macro
+    
+    This patch (as616) changed the uhci_explen macro in uhci-hcd.h so that
+    it now accepts the desired length, rather than length - 1 with special
+    handling for 0.  This also fixes a minor bug that would show up only
+    when a driver submits a 0-length bulk URB.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 071fab6b6475..120ca64fe3f7 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -566,7 +566,7 @@ static int uhci_start(struct usb_hcd *hcd)
+ 	uhci->skel_bulk_qh->link = cpu_to_le32(uhci->skel_term_qh->dma_handle) | UHCI_PTR_QH;
+ 
+ 	/* This dummy TD is to work around a bug in Intel PIIX controllers */
+-	uhci_fill_td(uhci->term_td, 0, (UHCI_NULL_DATA_SIZE << 21) |
++	uhci_fill_td(uhci->term_td, 0, uhci_explen(0) |
+ 		(0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0);
+ 	uhci->term_td->link = cpu_to_le32(uhci->term_td->dma_handle);
+ 
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index e576db57a926..e43282e4e806 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -71,8 +71,6 @@
+ #define   USBLEGSUP_RWC		0x8f00	/* the R/WC bits */
+ #define   USBLEGSUP_RO		0x5040	/* R/O and reserved bits */
+ 
+-#define UHCI_NULL_DATA_SIZE	0x7FF	/* for UHCI controller TD */
+-
+ #define UHCI_PTR_BITS		cpu_to_le32(0x000F)
+ #define UHCI_PTR_TERM		cpu_to_le32(0x0001)
+ #define UHCI_PTR_QH		cpu_to_le32(0x0002)
+@@ -168,9 +166,11 @@ static __le32 inline qh_element(struct uhci_qh *qh) {
+ #define TD_TOKEN_EXPLEN_MASK	0x7FF		/* expected length, encoded as n - 1 */
+ #define TD_TOKEN_PID_MASK	0xFF
+ 
+-#define uhci_explen(len)	((len) << TD_TOKEN_EXPLEN_SHIFT)
++#define uhci_explen(len)	((((len) - 1) & TD_TOKEN_EXPLEN_MASK) << \
++					TD_TOKEN_EXPLEN_SHIFT)
+ 
+-#define uhci_expected_length(token) ((((token) >> 21) + 1) & TD_TOKEN_EXPLEN_MASK)
++#define uhci_expected_length(token) ((((token) >> TD_TOKEN_EXPLEN_SHIFT) + \
++					1) & TD_TOKEN_EXPLEN_MASK)
+ #define uhci_toggle(token)	(((token) >> TD_TOKEN_TOGGLE_SHIFT) & 1)
+ #define uhci_endpoint(token)	(((token) >> 15) & 0xf)
+ #define uhci_devaddr(token)	(((token) >> TD_TOKEN_DEVADDR_SHIFT) & 0x7f)
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 7e46887d9e12..ace9d15f85d2 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -596,7 +596,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
+ 		return -ENOMEM;
+ 
+ 	uhci_add_td_to_urb(urb, td);
+-	uhci_fill_td(td, status, destination | uhci_explen(7),
++	uhci_fill_td(td, status, destination | uhci_explen(8),
+ 		urb->setup_dma);
+ 
+ 	/*
+@@ -628,7 +628,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
+ 		destination ^= TD_TOKEN_TOGGLE;
+ 	
+ 		uhci_add_td_to_urb(urb, td);
+-		uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1),
++		uhci_fill_td(td, status, destination | uhci_explen(pktsze),
+ 			data);
+ 
+ 		data += pktsze;
+@@ -658,7 +658,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
+ 
+ 	uhci_add_td_to_urb(urb, td);
+ 	uhci_fill_td(td, status | TD_CTRL_IOC,
+-		destination | uhci_explen(UHCI_NULL_DATA_SIZE), 0);
++		destination | uhci_explen(0), 0);
+ 
+ 	qh = uhci_alloc_qh(uhci);
+ 	if (!qh)
+@@ -864,7 +864,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb
+ 			return -ENOMEM;
+ 
+ 		uhci_add_td_to_urb(urb, td);
+-		uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1) |
++		uhci_fill_td(td, status, destination | uhci_explen(pktsze) |
+ 			(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+ 			 usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
+ 			data);
+@@ -890,7 +890,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb
+ 			return -ENOMEM;
+ 
+ 		uhci_add_td_to_urb(urb, td);
+-		uhci_fill_td(td, status, destination | uhci_explen(UHCI_NULL_DATA_SIZE) |
++		uhci_fill_td(td, status, destination | uhci_explen(0) |
+ 			(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+ 			 usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
+ 			data);
+@@ -1092,7 +1092,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
+ 			return -ENOMEM;
+ 
+ 		uhci_add_td_to_urb(urb, td);
+-		uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length - 1),
++		uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length),
+ 			urb->transfer_dma + urb->iso_frame_desc[i].offset);
+ 
+ 		if (i + 1 >= urb->number_of_packets)

commit 2425e9fe67cb5e66c173c4f604ddd8a5970d89e9
+Author: Alan Stern 
+Date:   Tue Nov 29 12:13:31 2005 -0500
+
+    [PATCH] USB: Don't assume root-hub resume succeeds
+    
+    This patch (as614) makes a small change to the part of the hub driver
+    responsible for remote wakeup of root hubs.  When these wakeups occur
+    the driver is suspended, and in case the resume fails the driver should
+    remain suspended -- it shouldn't try to proceed with its normal
+    processing.
+    
+    This will hardly ever matter in normal use, but it did crop up while I
+    was debugging a different problem.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index a523c8f20b5d..650d5ee5871b 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2697,6 +2697,8 @@ static void hub_events(void)
+ 		if (i) {
+ 			dpm_runtime_resume(&hdev->dev);
+ 			dpm_runtime_resume(&intf->dev);
++			usb_put_intf(intf);
++			continue;
+ 		}
+ 
+ 		/* Lock the device, then check to see if we were

commit 3cf0a22e8b1b3f44288db773d315e72e89d51c4c
+Author: Alan Stern 
+Date:   Tue Nov 29 12:08:15 2005 -0500
+
+    [PATCH] USB Gadget: dummy_hcd: updates to hcd->state
+    
+    This patch (as613) moves the updates to hcd->state in the dummy_hcd
+    driver to where they now belong.  It also uses the new
+    HC_FLAG_HW_ACCESSIBLE flag in a way that simulates a real PCI
+    controller, and it adds checks for attempts to resume the bus while the
+    controller is suspended or to suspend the controller while the bus is
+    active.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index 4932b07b316d..ce0d4b412dfe 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -1576,7 +1576,7 @@ static int dummy_hub_status (struct usb_hcd *hcd, char *buf)
+ 	dum = hcd_to_dummy (hcd);
+ 
+ 	spin_lock_irqsave (&dum->lock, flags);
+-	if (hcd->state != HC_STATE_RUNNING)
++	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
+ 		goto done;
+ 
+ 	if (dum->resuming && time_after_eq (jiffies, dum->re_timeout)) {
+@@ -1623,7 +1623,7 @@ static int dummy_hub_control (
+ 	int		retval = 0;
+ 	unsigned long	flags;
+ 
+-	if (hcd->state != HC_STATE_RUNNING)
++	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
+ 		return -ETIMEDOUT;
+ 
+ 	dum = hcd_to_dummy (hcd);
+@@ -1756,9 +1756,12 @@ static int dummy_bus_suspend (struct usb_hcd *hcd)
+ {
+ 	struct dummy *dum = hcd_to_dummy (hcd);
+ 
++	dev_dbg (&hcd->self.root_hub->dev, "%s\n", __FUNCTION__);
++
+ 	spin_lock_irq (&dum->lock);
+ 	dum->rh_state = DUMMY_RH_SUSPENDED;
+ 	set_link_state (dum);
++	hcd->state = HC_STATE_SUSPENDED;
+ 	spin_unlock_irq (&dum->lock);
+ 	return 0;
+ }
+@@ -1766,14 +1769,23 @@ static int dummy_bus_suspend (struct usb_hcd *hcd)
+ static int dummy_bus_resume (struct usb_hcd *hcd)
+ {
+ 	struct dummy *dum = hcd_to_dummy (hcd);
++	int rc = 0;
++
++	dev_dbg (&hcd->self.root_hub->dev, "%s\n", __FUNCTION__);
+ 
+ 	spin_lock_irq (&dum->lock);
+-	dum->rh_state = DUMMY_RH_RUNNING;
+-	set_link_state (dum);
+-	if (!list_empty(&dum->urbp_list))
+-		mod_timer (&dum->timer, jiffies);
++	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
++		dev_warn (&hcd->self.root_hub->dev, "HC isn't running!\n");
++		rc = -ENODEV;
++	} else {
++		dum->rh_state = DUMMY_RH_RUNNING;
++		set_link_state (dum);
++		if (!list_empty(&dum->urbp_list))
++			mod_timer (&dum->timer, jiffies);
++		hcd->state = HC_STATE_RUNNING;
++	}
+ 	spin_unlock_irq (&dum->lock);
+-	return 0;
++	return rc;
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -1933,12 +1945,19 @@ static int dummy_hcd_remove (struct platform_device *pdev)
+ static int dummy_hcd_suspend (struct platform_device *pdev, pm_message_t state)
+ {
+ 	struct usb_hcd		*hcd;
++	struct dummy		*dum;
++	int			rc = 0;
+ 
+ 	dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
+-	hcd = platform_get_drvdata (pdev);
+ 
+-	hcd->state = HC_STATE_SUSPENDED;
+-	return 0;
++	hcd = platform_get_drvdata (pdev);
++	dum = hcd_to_dummy (hcd);
++	if (dum->rh_state == DUMMY_RH_RUNNING) {
++		dev_warn(&pdev->dev, "Root hub isn't suspended!\n");
++		rc = -EBUSY;
++	} else
++		clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
++	return rc;
+ }
+ 
+ static int dummy_hcd_resume (struct platform_device *pdev)
+@@ -1946,9 +1965,9 @@ static int dummy_hcd_resume (struct platform_device *pdev)
+ 	struct usb_hcd		*hcd;
+ 
+ 	dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
+-	hcd = platform_get_drvdata (pdev);
+-	hcd->state = HC_STATE_RUNNING;
+ 
++	hcd = platform_get_drvdata (pdev);
++	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ 	usb_hcd_poll_rh_status (hcd);
+ 	return 0;
+ }

commit a21d4fed4b00eaf7e7c3b2e2b25de24f540bfa66
+Author: Alan Stern 
+Date:   Tue Nov 29 12:04:24 2005 -0500
+
+    [PATCH] USB Gadget: file_storage: remove "volatile" declarations
+    
+    This patch (as612) removes the "volatile" declarations from the
+    file-storage gadget.  It turns out that they aren't needed for anything
+    much; adding a few memory barriers does a sufficient job.
+    
+    The patch also removes a wait_queue.  Not much point having a queue when
+    only one task is ever going to be on it!
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index f6c49b717d3f..0cea9782d7d4 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -239,7 +239,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ 
+ #include 
+ #include 
+@@ -251,7 +250,7 @@
+ 
+ #define DRIVER_DESC		"File-backed Storage Gadget"
+ #define DRIVER_NAME		"g_file_storage"
+-#define DRIVER_VERSION		"20 October 2004"
++#define DRIVER_VERSION		"28 November 2005"
+ 
+ static const char longname[] = DRIVER_DESC;
+ static const char shortname[] = DRIVER_NAME;
+@@ -588,7 +587,7 @@ enum fsg_buffer_state {
+ struct fsg_buffhd {
+ 	void				*buf;
+ 	dma_addr_t			dma;
+-	volatile enum fsg_buffer_state	state;
++	enum fsg_buffer_state		state;
+ 	struct fsg_buffhd		*next;
+ 
+ 	/* The NetChip 2280 is faster, and handles some protocol faults
+@@ -597,9 +596,9 @@ struct fsg_buffhd {
+ 	unsigned int			bulk_out_intended_length;
+ 
+ 	struct usb_request		*inreq;
+-	volatile int			inreq_busy;
++	int				inreq_busy;
+ 	struct usb_request		*outreq;
+-	volatile int			outreq_busy;
++	int				outreq_busy;
+ };
+ 
+ enum fsg_state {
+@@ -637,11 +636,11 @@ struct fsg_dev {
+ 
+ 	struct usb_ep		*ep0;		// Handy copy of gadget->ep0
+ 	struct usb_request	*ep0req;	// For control responses
+-	volatile unsigned int	ep0_req_tag;
++	unsigned int		ep0_req_tag;
+ 	const char		*ep0req_name;
+ 
+ 	struct usb_request	*intreq;	// For interrupt responses
+-	volatile int		intreq_busy;
++	int			intreq_busy;
+ 	struct fsg_buffhd	*intr_buffhd;
+ 
+  	unsigned int		bulk_out_maxpacket;
+@@ -671,7 +670,6 @@ struct fsg_dev {
+ 	struct fsg_buffhd	*next_buffhd_to_drain;
+ 	struct fsg_buffhd	buffhds[NUM_BUFFERS];
+ 
+-	wait_queue_head_t	thread_wqh;
+ 	int			thread_wakeup_needed;
+ 	struct completion	thread_notifier;
+ 	struct task_struct	*thread_task;
+@@ -1076,11 +1074,13 @@ static int populate_config_buf(struct usb_gadget *gadget,
+ 
+ /* These routines may be called in process context or in_irq */
+ 
++/* Caller must hold fsg->lock */
+ static void wakeup_thread(struct fsg_dev *fsg)
+ {
+ 	/* Tell the main thread that something has happened */
+ 	fsg->thread_wakeup_needed = 1;
+-	wake_up_all(&fsg->thread_wqh);
++	if (fsg->thread_task)
++		wake_up_process(fsg->thread_task);
+ }
+ 
+ 
+@@ -1167,11 +1167,12 @@ static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)
+ 		usb_ep_fifo_flush(ep);
+ 
+ 	/* Hold the lock while we update the request and buffer states */
++	smp_wmb();
+ 	spin_lock(&fsg->lock);
+ 	bh->inreq_busy = 0;
+ 	bh->state = BUF_STATE_EMPTY;
+-	spin_unlock(&fsg->lock);
+ 	wakeup_thread(fsg);
++	spin_unlock(&fsg->lock);
+ }
+ 
+ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
+@@ -1188,11 +1189,12 @@ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
+ 		usb_ep_fifo_flush(ep);
+ 
+ 	/* Hold the lock while we update the request and buffer states */
++	smp_wmb();
+ 	spin_lock(&fsg->lock);
+ 	bh->outreq_busy = 0;
+ 	bh->state = BUF_STATE_FULL;
+-	spin_unlock(&fsg->lock);
+ 	wakeup_thread(fsg);
++	spin_unlock(&fsg->lock);
+ }
+ 
+ 
+@@ -1209,11 +1211,12 @@ static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
+ 		usb_ep_fifo_flush(ep);
+ 
+ 	/* Hold the lock while we update the request and buffer states */
++	smp_wmb();
+ 	spin_lock(&fsg->lock);
+ 	fsg->intreq_busy = 0;
+ 	bh->state = BUF_STATE_EMPTY;
+-	spin_unlock(&fsg->lock);
+ 	wakeup_thread(fsg);
++	spin_unlock(&fsg->lock);
+ }
+ 
+ #else
+@@ -1264,8 +1267,8 @@ static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
+ 	fsg->cbbuf_cmnd_size = req->actual;
+ 	memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size);
+ 
+-	spin_unlock(&fsg->lock);
+ 	wakeup_thread(fsg);
++	spin_unlock(&fsg->lock);
+ }
+ 
+ #else
+@@ -1517,8 +1520,8 @@ static int fsg_setup(struct usb_gadget *gadget,
+ 
+ /* Use this for bulk or interrupt transfers, not ep0 */
+ static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
+-		struct usb_request *req, volatile int *pbusy,
+-		volatile enum fsg_buffer_state *state)
++		struct usb_request *req, int *pbusy,
++		enum fsg_buffer_state *state)
+ {
+ 	int	rc;
+ 
+@@ -1526,8 +1529,11 @@ static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
+ 		dump_msg(fsg, "bulk-in", req->buf, req->length);
+ 	else if (ep == fsg->intr_in)
+ 		dump_msg(fsg, "intr-in", req->buf, req->length);
++
++	spin_lock_irq(&fsg->lock);
+ 	*pbusy = 1;
+ 	*state = BUF_STATE_BUSY;
++	spin_unlock_irq(&fsg->lock);
+ 	rc = usb_ep_queue(ep, req, GFP_KERNEL);
+ 	if (rc != 0) {
+ 		*pbusy = 0;
+@@ -1547,14 +1553,23 @@ static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
+ 
+ static int sleep_thread(struct fsg_dev *fsg)
+ {
+-	int	rc;
++	int	rc = 0;
+ 
+ 	/* Wait until a signal arrives or we are woken up */
+-	rc = wait_event_interruptible(fsg->thread_wqh,
+-			fsg->thread_wakeup_needed);
++	for (;;) {
++		try_to_freeze();
++		set_current_state(TASK_INTERRUPTIBLE);
++		if (signal_pending(current)) {
++			rc = -EINTR;
++			break;
++		}
++		if (fsg->thread_wakeup_needed)
++			break;
++		schedule();
++	}
++	__set_current_state(TASK_RUNNING);
+ 	fsg->thread_wakeup_needed = 0;
+-	try_to_freeze();
+-	return (rc ? -EINTR : 0);
++	return rc;
+ }
+ 
+ 
+@@ -1791,6 +1806,7 @@ static int do_write(struct fsg_dev *fsg)
+ 		if (bh->state == BUF_STATE_EMPTY && !get_some_more)
+ 			break;			// We stopped early
+ 		if (bh->state == BUF_STATE_FULL) {
++			smp_rmb();
+ 			fsg->next_buffhd_to_drain = bh->next;
+ 			bh->state = BUF_STATE_EMPTY;
+ 
+@@ -2359,6 +2375,7 @@ static int throw_away_data(struct fsg_dev *fsg)
+ 
+ 		/* Throw away the data in a filled buffer */
+ 		if (bh->state == BUF_STATE_FULL) {
++			smp_rmb();
+ 			bh->state = BUF_STATE_EMPTY;
+ 			fsg->next_buffhd_to_drain = bh->next;
+ 
+@@ -3024,6 +3041,7 @@ static int get_next_command(struct fsg_dev *fsg)
+ 			if ((rc = sleep_thread(fsg)) != 0)
+ 				return rc;
+ 			}
++		smp_rmb();
+ 		rc = received_cbw(fsg, bh);
+ 		bh->state = BUF_STATE_EMPTY;
+ 
+@@ -4072,7 +4090,6 @@ static int __init fsg_alloc(void)
+ 	spin_lock_init(&fsg->lock);
+ 	init_rwsem(&fsg->filesem);
+ 	kref_init(&fsg->ref);
+-	init_waitqueue_head(&fsg->thread_wqh);
+ 	init_completion(&fsg->thread_notifier);
+ 
+ 	the_fsg = fsg;

commit 12c3da346eb81b6a281031f62eda3bca993dff5a
+Author: Alan Stern 
+Date:   Wed Nov 23 12:09:52 2005 -0500
+
+    [PATCH] USB: Store port number in usb_device
+    
+    This patch (as610) adds a field to struct usb_device to store the device's
+    port number.  This allows us to remove several loops in the hub driver
+    (searching for a particular device among all the entries in the parent's
+    array of children).
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index b311005ff1a6..a523c8f20b5d 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -946,24 +946,21 @@ static int locktree(struct usb_device *udev)
+ 	t = locktree(hdev);
+ 	if (t < 0)
+ 		return t;
+-	for (t = 0; t < hdev->maxchild; t++) {
+-		if (hdev->children[t] == udev) {
+-			/* everything is fail-fast once disconnect
+-			 * processing starts
+-			 */
+-			if (udev->state == USB_STATE_NOTATTACHED)
+-				break;
+ 
+-			/* when everyone grabs locks top->bottom,
+-			 * non-overlapping work may be concurrent
+-			 */
+-			usb_lock_device(udev);
+-			usb_unlock_device(hdev);
+-			return t + 1;
+-		}
++	/* everything is fail-fast once disconnect
++	 * processing starts
++	 */
++	if (udev->state == USB_STATE_NOTATTACHED) {
++		usb_unlock_device(hdev);
++		return -ENODEV;
+ 	}
++
++	/* when everyone grabs locks top->bottom,
++	 * non-overlapping work may be concurrent
++	 */
++	usb_lock_device(udev);
+ 	usb_unlock_device(hdev);
+-	return -ENODEV;
++	return udev->portnum;
+ }
+ 
+ static void recursively_mark_NOTATTACHED(struct usb_device *udev)
+@@ -1335,15 +1332,9 @@ int usb_new_device(struct usb_device *udev)
+ 					le16_to_cpu(udev->config[0].desc.wTotalLength),
+ 					USB_DT_OTG, (void **) &desc) == 0) {
+ 			if (desc->bmAttributes & USB_OTG_HNP) {
+-				unsigned		port1;
++				unsigned		port1 = udev->portnum;
+ 				struct usb_device	*root = udev->parent;
+ 				
+-				for (port1 = 1; port1 <= root->maxchild;
+-						port1++) {
+-					if (root->children[port1-1] == udev)
+-						break;
+-				}
+-
+ 				dev_info(&udev->dev,
+ 					"Dual-Role OTG device on %sHNP port\n",
+ 					(port1 == bus->otg_port)
+@@ -1720,22 +1711,9 @@ static int __usb_suspend_device (struct usb_device *udev, int port1)
+ int usb_suspend_device(struct usb_device *udev)
+ {
+ #ifdef	CONFIG_USB_SUSPEND
+-	int	port1;
+-
+ 	if (udev->state == USB_STATE_NOTATTACHED)
+ 		return -ENODEV;
+-	if (!udev->parent)
+-		port1 = 0;
+-	else {
+-		for (port1 = udev->parent->maxchild; port1 > 0; --port1) {
+-			if (udev->parent->children[port1-1] == udev)
+-				break;
+-		}
+-		if (port1 == 0)
+-			return -ENODEV;
+-	}
+-
+-	return __usb_suspend_device(udev, port1);
++	return __usb_suspend_device(udev, udev->portnum);
+ #else
+ 	/* NOTE:  udev->state unchanged, it's not lying ... */
+ 	udev->dev.power.power_state = PMSG_SUSPEND;
+@@ -1893,20 +1871,10 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+  */
+ int usb_resume_device(struct usb_device *udev)
+ {
+-	int	port1, status;
++	int	status;
+ 
+ 	if (udev->state == USB_STATE_NOTATTACHED)
+ 		return -ENODEV;
+-	if (!udev->parent)
+-		port1 = 0;
+-	else {
+-		for (port1 = udev->parent->maxchild; port1 > 0; --port1) {
+-			if (udev->parent->children[port1-1] == udev)
+-				break;
+-		}
+-		if (port1 == 0)
+-			return -ENODEV;
+-	}
+ 
+ #ifdef	CONFIG_USB_SUSPEND
+ 	/* selective resume of one downstream hub-to-device port */
+@@ -1915,7 +1883,7 @@ int usb_resume_device(struct usb_device *udev)
+ 			// NOTE swsusp may bork us, device state being wrong...
+ 			// NOTE this fails if parent is also suspended...
+ 			status = hub_port_resume(hdev_to_hub(udev->parent),
+-					port1, udev);
++					udev->portnum, udev);
+ 		} else
+ 			status = 0;
+ 	} else
+@@ -3029,7 +2997,8 @@ int usb_reset_device(struct usb_device *udev)
+ 	struct usb_hub			*parent_hub;
+ 	struct usb_device_descriptor	descriptor = udev->descriptor;
+ 	struct usb_hub			*hub = NULL;
+-	int 				i, ret = 0, port1 = -1;
++	int 				i, ret = 0;
++	int				port1 = udev->portnum;
+ 
+ 	if (udev->state == USB_STATE_NOTATTACHED ||
+ 			udev->state == USB_STATE_SUSPENDED) {
+@@ -3043,18 +3012,6 @@ int usb_reset_device(struct usb_device *udev)
+ 		dev_dbg(&udev->dev, "%s for root hub!\n", __FUNCTION__);
+ 		return -EISDIR;
+ 	}
+-
+-	for (i = 0; i < parent_hdev->maxchild; i++)
+-		if (parent_hdev->children[i] == udev) {
+-			port1 = i + 1;
+-			break;
+-		}
+-
+-	if (port1 < 0) {
+-		/* If this ever happens, it's very bad */
+-		dev_err(&udev->dev, "Can't locate device's port!\n");
+-		return -ENOENT;
+-	}
+ 	parent_hub = hdev_to_hub(parent_hdev);
+ 
+ 	/* If we're resetting an active hub, take some special actions */
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index fcfda21be499..39e6b61b898a 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -439,6 +439,7 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
+ 		/* hub driver sets up TT records */
+ 	}
+ 
++	dev->portnum = port1;
+ 	dev->bus = bus;
+ 	dev->parent = parent;
+ 	INIT_LIST_HEAD(&dev->filelist);
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 27575e678a7c..e59d1bd52d4f 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -348,6 +348,7 @@ struct usb_device {
+ 	char **rawdescriptors;		/* Raw descriptors for each config */
+ 
+ 	unsigned short bus_mA;		/* Current available from the bus */
++	u8 portnum;			/* Parent port number (origin 1) */
+ 
+ 	int have_langid;		/* whether string_langid is valid */
+ 	int string_langid;		/* language ID for strings */

commit 55c527187c9d78f840b284d596a0b298bc1493af
+Author: Alan Stern 
+Date:   Wed Nov 23 12:03:12 2005 -0500
+
+    [PATCH] USB: Consider power budget when choosing configuration
+    
+    This patch (as609) changes the way we keep track of power budgeting for
+    USB hubs and devices, and it updates the choose_configuration routine to
+    take this information into account.  (This is something we should have
+    been doing all along.)  A new field in struct usb_device holds the amount
+    of bus current available from the upstream port, and the usb_hub structure
+    keeps track of the current available for each downstream port.
+    
+    Two new rules for configuration selection are added:
+    
+            Don't select a self-powered configuration when only bus power
+            is available.
+    
+            Don't select a configuration requiring more bus power than is
+            available.
+    
+    However the first rule is #if-ed out, because I found that the internal
+    hub in my HP USB keyboard claims that its only configuration is
+    self-powered.  The rule would prevent the configuration from being chosen,
+    leaving the hub & keyboard unconfigured.  Since similar descriptor errors
+    may turn out to be fairly common, it seemed wise not to include a rule
+    that would break automatic configuration unnecessarily for such devices.
+    
+    The second rule may also trigger unnecessarily, although this should be
+    less common.  More likely it will annoy people by sometimes failing to
+    accept configurations that should never have been chosen in the first
+    place.
+    
+    The patch also changes usbcore's reaction when no configuration is
+    suitable.  Instead of raising an error and rejecting the device, now
+    the core will simply leave the device unconfigured.  People can always
+    work around such problems by installing configurations manually through
+    sysfs.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index d16a0e8a7d72..0018bbc4de34 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1825,8 +1825,6 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ 		retval = -ENOMEM;
+ 		goto err_allocate_root_hub;
+ 	}
+-	rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH :
+-			USB_SPEED_FULL;
+ 
+ 	/* Although in principle hcd->driver->start() might need to use rhdev,
+ 	 * none of the current drivers do.
+@@ -1844,6 +1842,9 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ 		dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");
+ 	hcd->remote_wakeup = hcd->can_wakeup;
+ 
++	rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH :
++			USB_SPEED_FULL;
++	rhdev->bus_mA = min(500u, hcd->power_budget);
+ 	if ((retval = register_root_hub(rhdev, hcd)) != 0)
+ 		goto err_register_root_hub;
+ 
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 895ac829b9cf..b311005ff1a6 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -702,26 +702,40 @@ static int hub_configure(struct usb_hub *hub,
+ 	 * and battery-powered root hubs (may provide just 8 mA).
+ 	 */
+ 	ret = usb_get_status(hdev, USB_RECIP_DEVICE, 0, &hubstatus);
+-	if (ret < 0) {
++	if (ret < 2) {
+ 		message = "can't get hub status";
+ 		goto fail;
+ 	}
+ 	le16_to_cpus(&hubstatus);
+ 	if (hdev == hdev->bus->root_hub) {
+-		struct usb_hcd *hcd =
+-				container_of(hdev->bus, struct usb_hcd, self);
+-
+-		hub->power_budget = min(500u, hcd->power_budget) / 2;
++		if (hdev->bus_mA == 0 || hdev->bus_mA >= 500)
++			hub->mA_per_port = 500;
++		else {
++			hub->mA_per_port = hdev->bus_mA;
++			hub->limited_power = 1;
++		}
+ 	} else if ((hubstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0) {
+ 		dev_dbg(hub_dev, "hub controller current requirement: %dmA\n",
+ 			hub->descriptor->bHubContrCurrent);
+-		hub->power_budget = (501 - hub->descriptor->bHubContrCurrent)
+-					/ 2;
++		hub->limited_power = 1;
++		if (hdev->maxchild > 0) {
++			int remaining = hdev->bus_mA -
++					hub->descriptor->bHubContrCurrent;
++
++			if (remaining < hdev->maxchild * 100)
++				dev_warn(hub_dev,
++					"insufficient power available "
++					"to use all downstream ports\n");
++			hub->mA_per_port = 100;		/* 7.2.1.1 */
++		}
++	} else {	/* Self-powered external hub */
++		/* FIXME: What about battery-powered external hubs that
++		 * provide less current per port? */
++		hub->mA_per_port = 500;
+ 	}
+-	if (hub->power_budget)
+-		dev_dbg(hub_dev, "%dmA bus power budget for children\n",
+-			hub->power_budget * 2);
+-
++	if (hub->mA_per_port < 500)
++		dev_dbg(hub_dev, "%umA bus power budget for each child\n",
++				hub->mA_per_port);
+ 
+ 	ret = hub_hub_status(hub, &hubstatus, &hubchange);
+ 	if (ret < 0) {
+@@ -1136,45 +1150,107 @@ void usb_disconnect(struct usb_device **pdev)
+ 	device_unregister(&udev->dev);
+ }
+ 
++static inline const char *plural(int n)
++{
++	return (n == 1 ? "" : "s");
++}
++
+ static int choose_configuration(struct usb_device *udev)
+ {
+-	int c, i;
++	int i;
++	u16 devstatus;
++	int bus_powered;
++	int num_configs;
++	struct usb_host_config *c, *best;
++
++	/* If this fails, assume the device is bus-powered */
++	devstatus = 0;
++	usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
++	le16_to_cpus(&devstatus);
++	bus_powered = ((devstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0);
++	dev_dbg(&udev->dev, "device is %s-powered\n",
++			bus_powered ? "bus" : "self");
++
++	best = NULL;
++	c = udev->config;
++	num_configs = udev->descriptor.bNumConfigurations;
++	for (i = 0; i < num_configs; (i++, c++)) {
++		struct usb_interface_descriptor	*desc =
++				&c->intf_cache[0]->altsetting->desc;
++
++		/*
++		 * HP's USB bus-powered keyboard has only one configuration
++		 * and it claims to be self-powered; other devices may have
++		 * similar errors in their descriptors.  If the next test
++		 * were allowed to execute, such configurations would always
++		 * be rejected and the devices would not work as expected.
++		 */
++#if 0
++		/* Rule out self-powered configs for a bus-powered device */
++		if (bus_powered && (c->desc.bmAttributes &
++					USB_CONFIG_ATT_SELFPOWER))
++			continue;
++#endif
+ 
+-	/* NOTE: this should interact with hub power budgeting */
++		/*
++		 * The next test may not be as effective as it should be.
++		 * Some hubs have errors in their descriptor, claiming
++		 * to be self-powered when they are really bus-powered.
++		 * We will overestimate the amount of current such hubs
++		 * make available for each port.
++		 *
++		 * This is a fairly benign sort of failure.  It won't
++		 * cause us to reject configurations that we should have
++		 * accepted.
++		 */
+ 
+-	c = udev->config[0].desc.bConfigurationValue;
+-	if (udev->descriptor.bNumConfigurations != 1) {
+-		for (i = 0; i < udev->descriptor.bNumConfigurations; i++) {
+-			struct usb_interface_descriptor	*desc;
++		/* Rule out configs that draw too much bus current */
++		if (c->desc.bMaxPower * 2 > udev->bus_mA)
++			continue;
+ 
+-			/* heuristic:  Linux is more likely to have class
+-			 * drivers, so avoid vendor-specific interfaces.
+-			 */
+-			desc = &udev->config[i].intf_cache[0]
+-					->altsetting->desc;
+-			if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC)
+-				continue;
+-			/* COMM/2/all is CDC ACM, except 0xff is MSFT RNDIS.
+-			 * MSFT needs this to be the first config; never use
+-			 * it as the default unless Linux has host-side RNDIS.
+-			 * A second config would ideally be CDC-Ethernet, but
+-			 * may instead be the "vendor specific" CDC subset
+-			 * long used by ARM Linux for sa1100 or pxa255.
+-			 */
+-			if (desc->bInterfaceClass == USB_CLASS_COMM
+-					&& desc->bInterfaceSubClass == 2
+-					&& desc->bInterfaceProtocol == 0xff) {
+-				c = udev->config[1].desc.bConfigurationValue;
+-				continue;
+-			}
+-			c = udev->config[i].desc.bConfigurationValue;
++		/* If the first config's first interface is COMM/2/0xff
++		 * (MSFT RNDIS), rule it out unless Linux has host-side
++		 * RNDIS support. */
++		if (i == 0 && desc->bInterfaceClass == USB_CLASS_COMM
++				&& desc->bInterfaceSubClass == 2
++				&& desc->bInterfaceProtocol == 0xff) {
++#ifndef CONFIG_USB_NET_RNDIS
++			continue;
++#else
++			best = c;
++#endif
++		}
++
++		/* From the remaining configs, choose the first one whose
++		 * first interface is for a non-vendor-specific class.
++		 * Reason: Linux is more likely to have a class driver
++		 * than a vendor-specific driver. */
++		else if (udev->descriptor.bDeviceClass !=
++						USB_CLASS_VENDOR_SPEC &&
++				desc->bInterfaceClass !=
++						USB_CLASS_VENDOR_SPEC) {
++			best = c;
+ 			break;
+ 		}
++
++		/* If all the remaining configs are vendor-specific,
++		 * choose the first one. */
++		else if (!best)
++			best = c;
++	}
++
++	if (best) {
++		i = best->desc.bConfigurationValue;
+ 		dev_info(&udev->dev,
+-			"configuration #%d chosen from %d choices\n",
+-			c, udev->descriptor.bNumConfigurations);
++			"configuration #%d chosen from %d choice%s\n",
++			i, num_configs, plural(num_configs));
++	} else {
++		i = -1;
++		dev_warn(&udev->dev,
++			"no configuration chosen from %d choice%s\n",
++			num_configs, plural(num_configs));
+ 	}
+-	return c;
++	return i;
+ }
+ 
+ #ifdef DEBUG
+@@ -1327,17 +1403,13 @@ int usb_new_device(struct usb_device *udev)
+ 	 * with the driver core, and lets usb device drivers bind to them.
+ 	 */
+ 	c = choose_configuration(udev);
+-	if (c < 0)
+-		dev_warn(&udev->dev,
+-				"can't choose an initial configuration\n");
+-	else {
++	if (c >= 0) {
+ 		err = usb_set_configuration(udev, c);
+ 		if (err) {
+ 			dev_err(&udev->dev, "can't set config #%d, error %d\n",
+ 					c, err);
+-			usb_remove_sysfs_dev_files(udev);
+-			device_del(&udev->dev);
+-			goto fail;
++			/* This need not be fatal.  The user can try to
++			 * set other configurations. */
+ 		}
+ 	}
+ 
+@@ -1702,7 +1774,7 @@ static int finish_device_resume(struct usb_device *udev)
+ 	 * and device drivers will know about any resume quirks.
+ 	 */
+ 	status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
+-	if (status < 0)
++	if (status < 2)
+ 		dev_dbg(&udev->dev,
+ 			"gone after usb resume? status %d\n",
+ 			status);
+@@ -1711,7 +1783,7 @@ static int finish_device_resume(struct usb_device *udev)
+ 		int		(*resume)(struct device *);
+ 
+ 		le16_to_cpus(&devstatus);
+-		if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)
++		if ((devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP))
+ 				&& udev->parent) {
+ 			status = usb_control_msg(udev,
+ 					usb_sndctrlpipe(udev, 0),
+@@ -2374,39 +2446,36 @@ hub_power_remaining (struct usb_hub *hub)
+ {
+ 	struct usb_device *hdev = hub->hdev;
+ 	int remaining;
+-	unsigned i;
++	int port1;
+ 
+-	remaining = hub->power_budget;
+-	if (!remaining)		/* self-powered */
++	if (!hub->limited_power)
+ 		return 0;
+ 
+-	for (i = 0; i < hdev->maxchild; i++) {
+-		struct usb_device	*udev = hdev->children[i];
+-		int			delta, ceiling;
++	remaining = hdev->bus_mA - hub->descriptor->bHubContrCurrent;
++	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
++		struct usb_device	*udev = hdev->children[port1 - 1];
++		int			delta;
+ 
+ 		if (!udev)
+ 			continue;
+ 
+-		/* 100mA per-port ceiling, or 8mA for OTG ports */
+-		if (i != (udev->bus->otg_port - 1) || hdev->parent)
+-			ceiling = 50;
+-		else
+-			ceiling = 4;
+-
++		/* Unconfigured devices may not use more than 100mA,
++		 * or 8mA for OTG ports */
+ 		if (udev->actconfig)
+-			delta = udev->actconfig->desc.bMaxPower;
++			delta = udev->actconfig->desc.bMaxPower * 2;
++		else if (port1 != udev->bus->otg_port || hdev->parent)
++			delta = 100;
+ 		else
+-			delta = ceiling;
+-		// dev_dbg(&udev->dev, "budgeted %dmA\n", 2 * delta);
+-		if (delta > ceiling)
+-			dev_warn(&udev->dev, "%dmA over %dmA budget!\n",
+-				2 * (delta - ceiling), 2 * ceiling);
++			delta = 8;
++		if (delta > hub->mA_per_port)
++			dev_warn(&udev->dev, "%dmA is over %umA budget "
++					"for port %d!\n",
++					delta, hub->mA_per_port, port1);
+ 		remaining -= delta;
+ 	}
+ 	if (remaining < 0) {
+-		dev_warn(hub->intfdev,
+-			"%dmA over power budget!\n",
+-			-2 * remaining);
++		dev_warn(hub->intfdev, "%dmA over power budget!\n",
++			- remaining);
+ 		remaining = 0;
+ 	}
+ 	return remaining;
+@@ -2501,7 +2570,8 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 
+ 		usb_set_device_state(udev, USB_STATE_POWERED);
+ 		udev->speed = USB_SPEED_UNKNOWN;
+- 
++ 		udev->bus_mA = hub->mA_per_port;
++
+ 		/* set the address */
+ 		choose_address(udev);
+ 		if (udev->devnum <= 0) {
+@@ -2521,16 +2591,16 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 		 * on the parent.
+ 		 */
+ 		if (udev->descriptor.bDeviceClass == USB_CLASS_HUB
+-				&& hub->power_budget) {
++				&& udev->bus_mA <= 100) {
+ 			u16	devstat;
+ 
+ 			status = usb_get_status(udev, USB_RECIP_DEVICE, 0,
+ 					&devstat);
+-			if (status < 0) {
++			if (status < 2) {
+ 				dev_dbg(&udev->dev, "get status %d ?\n", status);
+ 				goto loop_disable;
+ 			}
+-			cpu_to_le16s(&devstat);
++			le16_to_cpus(&devstat);
+ 			if ((devstat & (1 << USB_DEVICE_SELF_POWERED)) == 0) {
+ 				dev_err(&udev->dev,
+ 					"can't connect bus-powered hub "
+@@ -2583,9 +2653,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 
+ 		status = hub_power_remaining(hub);
+ 		if (status)
+-			dev_dbg(hub_dev,
+-				"%dmA power budget left\n",
+-				2 * status);
++			dev_dbg(hub_dev, "%dmA power budget left\n", status);
+ 
+ 		return;
+ 
+@@ -2797,6 +2865,11 @@ static void hub_events(void)
+ 			if (hubchange & HUB_CHANGE_LOCAL_POWER) {
+ 				dev_dbg (hub_dev, "power change\n");
+ 				clear_hub_feature(hdev, C_HUB_LOCAL_POWER);
++				if (hubstatus & HUB_STATUS_LOCAL_POWER)
++					/* FIXME: Is this always true? */
++					hub->limited_power = 0;
++				else
++					hub->limited_power = 1;
+ 			}
+ 			if (hubchange & HUB_CHANGE_OVERCURRENT) {
+ 				dev_dbg (hub_dev, "overcurrent change\n");
+diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
+index bf23f8978024..29d5f45a8456 100644
+--- a/drivers/usb/core/hub.h
++++ b/drivers/usb/core/hub.h
+@@ -220,8 +220,9 @@ struct usb_hub {
+ 	struct usb_hub_descriptor *descriptor;	/* class descriptor */
+ 	struct usb_tt		tt;		/* Transaction Translator */
+ 
+-	u8			power_budget;	/* in 2mA units; or zero */
++	unsigned		mA_per_port;	/* current for each child */
+ 
++	unsigned		limited_power:1;
+ 	unsigned		quiescing:1;
+ 	unsigned		activating:1;
+ 	unsigned		resume_root_hub:1;
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index fe74f99ca5f4..99ab774d4fdb 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1387,6 +1387,12 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 	if (dev->state != USB_STATE_ADDRESS)
+ 		usb_disable_device (dev, 1);	// Skip ep0
+ 
++	n = dev->bus_mA - cp->desc.bMaxPower * 2;
++	if (n < 0)
++		dev_warn(&dev->dev, "new config #%d exceeds power "
++				"limit by %dmA\n",
++				configuration, -n);
++
+ 	if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ 			USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
+ 			NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0)
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 46dc0421d19e..27575e678a7c 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -347,6 +347,8 @@ struct usb_device {
+ 
+ 	char **rawdescriptors;		/* Raw descriptors for each config */
+ 
++	unsigned short bus_mA;		/* Current available from the bus */
++
+ 	int have_langid;		/* whether string_langid is valid */
+ 	int string_langid;		/* language ID for strings */
+ 

commit 4bf0ba861442d289eebfad8ea9ce365ab04fd582
+Author: Alan Stern 
+Date:   Mon Nov 21 11:58:07 2005 -0500
+
+    [PATCH] USB: Fix locking for USB suspend/resume
+    
+    The earlier USB locking updates didn't touch the suspend/resume
+    routines.  They need updating as well, since now the caller holds the
+    device semaphore.  This patch (as608) makes the necessary changes.  It
+    also adds a line to store the correct power state when a device is
+    resumed, something which was unaccountably missing.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 02601f412f9d..895ac829b9cf 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1648,15 +1648,22 @@ static int __usb_suspend_device (struct usb_device *udev, int port1)
+ int usb_suspend_device(struct usb_device *udev)
+ {
+ #ifdef	CONFIG_USB_SUSPEND
+-	int	port1, status;
++	int	port1;
+ 
+-	port1 = locktree(udev);
+-	if (port1 < 0)
+-		return port1;
++	if (udev->state == USB_STATE_NOTATTACHED)
++		return -ENODEV;
++	if (!udev->parent)
++		port1 = 0;
++	else {
++		for (port1 = udev->parent->maxchild; port1 > 0; --port1) {
++			if (udev->parent->children[port1-1] == udev)
++				break;
++		}
++		if (port1 == 0)
++			return -ENODEV;
++	}
+ 
+-	status = __usb_suspend_device(udev, port1);
+-	usb_unlock_device(udev);
+-	return status;
++	return __usb_suspend_device(udev, port1);
+ #else
+ 	/* NOTE:  udev->state unchanged, it's not lying ... */
+ 	udev->dev.power.power_state = PMSG_SUSPEND;
+@@ -1688,6 +1695,7 @@ static int finish_device_resume(struct usb_device *udev)
+ 	usb_set_device_state(udev, udev->actconfig
+ 			? USB_STATE_CONFIGURED
+ 			: USB_STATE_ADDRESS);
++	udev->dev.power.power_state = PMSG_ON;
+ 
+  	/* 10.5.4.5 says be sure devices in the tree are still there.
+  	 * For now let's assume the device didn't go crazy on resume,
+@@ -1723,8 +1731,14 @@ static int finish_device_resume(struct usb_device *udev)
+ 		 * may have a child resume event to deal with soon
+ 		 */
+ 		resume = udev->dev.bus->resume;
+-		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++)
+-			(void) resume(&udev->actconfig->interface[i]->dev);
++		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
++			struct device *dev =
++					&udev->actconfig->interface[i]->dev;
++
++			down(&dev->sem);
++			(void) resume(dev);
++			up(&dev->sem);
++		}
+ 		status = 0;
+ 
+ 	} else if (udev->devnum <= 0) {
+@@ -1809,9 +1823,18 @@ int usb_resume_device(struct usb_device *udev)
+ {
+ 	int	port1, status;
+ 
+-	port1 = locktree(udev);
+-	if (port1 < 0)
+-		return port1;
++	if (udev->state == USB_STATE_NOTATTACHED)
++		return -ENODEV;
++	if (!udev->parent)
++		port1 = 0;
++	else {
++		for (port1 = udev->parent->maxchild; port1 > 0; --port1) {
++			if (udev->parent->children[port1-1] == udev)
++				break;
++		}
++		if (port1 == 0)
++			return -ENODEV;
++	}
+ 
+ #ifdef	CONFIG_USB_SUSPEND
+ 	/* selective resume of one downstream hub-to-device port */
+@@ -1830,11 +1853,12 @@ int usb_resume_device(struct usb_device *udev)
+ 		dev_dbg(&udev->dev, "can't resume, status %d\n",
+ 			status);
+ 
+-	usb_unlock_device(udev);
+-
+ 	/* rebind drivers that had no suspend() */
+-	if (status == 0)
++	if (status == 0) {
++		usb_unlock_device(udev);
+ 		bus_rescan_devices(&usb_bus_type);
++		usb_lock_device(udev);
++	}
+ 	return status;
+ }
+ 

commit 7d069b7d80933004282c48edbe62526e4cb0aecc
+Author: Alan Stern 
+Date:   Fri Nov 18 12:06:34 2005 -0500
+
+    [PATCH] USB: Disconnect children during hub unbind
+    
+    This patch (as606b) is an updated version of my earlier patch to
+    disconnect children from a hub device when the hub driver is unbound.
+    Thanks to the changes in the driver core locking, we now know that the
+    entire hub device (and not just the interface) is locked whenever the
+    hub driver's disconnect method runs.  Hence it is safe to disconnect the
+    child device structures immediately instead of deferring the job.
+    
+    The earlier version of the patch neglected to disable the hub's ports.
+    We don't want to forget that; otherwise we'd end up with live devices
+    using addresses that have been recycled.  This update adds the necessary
+    code.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index dd3bcfb2bcb6..02601f412f9d 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -515,6 +515,31 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
+ 	return ret;
+ }
+ 
++
++/* caller has locked the hub device */
++static void hub_pre_reset(struct usb_hub *hub, int disable_ports)
++{
++	struct usb_device *hdev = hub->hdev;
++	int port1;
++
++	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
++		if (hdev->children[port1 - 1]) {
++			usb_disconnect(&hdev->children[port1 - 1]);
++			if (disable_ports)
++				hub_port_disable(hub, port1, 0);
++		}
++	}
++	hub_quiesce(hub);
++}
++
++/* caller has locked the hub device */
++static void hub_post_reset(struct usb_hub *hub)
++{
++	hub_activate(hub);
++	hub_power_on(hub);
++}
++
++
+ static int hub_configure(struct usb_hub *hub,
+ 	struct usb_endpoint_descriptor *endpoint)
+ {
+@@ -750,29 +775,10 @@ static int hub_configure(struct usb_hub *hub,
+ 
+ static unsigned highspeed_hubs;
+ 
+-/* Called after the hub driver is unbound from a hub with children */
+-static void hub_remove_children_work(void *__hub)
+-{
+-	struct usb_hub		*hub = __hub;
+-	struct usb_device	*hdev = hub->hdev;
+-	int			i;
+-
+-	kfree(hub);
+-
+-	usb_lock_device(hdev);
+-	for (i = 0; i < hdev->maxchild; ++i) {
+-		if (hdev->children[i])
+-			usb_disconnect(&hdev->children[i]);
+-	}
+-	usb_unlock_device(hdev);
+-	usb_put_dev(hdev);
+-}
+-
+ static void hub_disconnect(struct usb_interface *intf)
+ {
+ 	struct usb_hub *hub = usb_get_intfdata (intf);
+ 	struct usb_device *hdev;
+-	int n, port1;
+ 
+ 	usb_set_intfdata (intf, NULL);
+ 	hdev = hub->hdev;
+@@ -780,7 +786,9 @@ static void hub_disconnect(struct usb_interface *intf)
+ 	if (hdev->speed == USB_SPEED_HIGH)
+ 		highspeed_hubs--;
+ 
+-	hub_quiesce(hub);
++	/* Disconnect all children and quiesce the hub */
++	hub_pre_reset(hub, 1);
++
+ 	usb_free_urb(hub->urb);
+ 	hub->urb = NULL;
+ 
+@@ -800,27 +808,7 @@ static void hub_disconnect(struct usb_interface *intf)
+ 		hub->buffer = NULL;
+ 	}
+ 
+-	/* If there are any children then this is an unbind only, not a
+-	 * physical disconnection.  The active ports must be disabled
+-	 * and later on we must call usb_disconnect().  We can't call
+-	 * it now because we may not hold the hub's device lock.
+-	 */
+-	n = 0;
+-	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
+-		if (hdev->children[port1 - 1]) {
+-			++n;
+-			hub_port_disable(hub, port1, 1);
+-		}
+-	}
+-
+-	if (n == 0)
+-		kfree(hub);
+-	else {
+-		/* Reuse the hub->leds work_struct for our own purposes */
+-		INIT_WORK(&hub->leds, hub_remove_children_work, hub);
+-		schedule_work(&hub->leds);
+-		usb_get_dev(hdev);
+-	}
++	kfree(hub);
+ }
+ 
+ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
+@@ -917,26 +905,6 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
+ 	}
+ }
+ 
+-/* caller has locked the hub device */
+-static void hub_pre_reset(struct usb_hub *hub)
+-{
+-	struct usb_device *hdev = hub->hdev;
+-	int i;
+-
+-	for (i = 0; i < hdev->maxchild; ++i) {
+-		if (hdev->children[i])
+-			usb_disconnect(&hdev->children[i]);
+-	}
+-	hub_quiesce(hub);
+-}
+-
+-/* caller has locked the hub device */
+-static void hub_post_reset(struct usb_hub *hub)
+-{
+-	hub_activate(hub);
+-	hub_power_on(hub);
+-}
+-
+ 
+ /* grab device/port lock, returning index of that port (zero based).
+  * protects the upstream link used by this device from concurrent
+@@ -2682,7 +2650,7 @@ static void hub_events(void)
+ 
+ 		/* If the hub has died, clean up after it */
+ 		if (hdev->state == USB_STATE_NOTATTACHED) {
+-			hub_pre_reset(hub);
++			hub_pre_reset(hub, 0);
+ 			goto loop;
+ 		}
+ 
+@@ -2997,7 +2965,7 @@ int usb_reset_device(struct usb_device *udev)
+ 			udev->actconfig->interface[0]->dev.driver ==
+ 				&hub_driver.driver &&
+ 			(hub = hdev_to_hub(udev)) != NULL) {
+-		hub_pre_reset(hub);
++		hub_pre_reset(hub, 0);
+ 	}
+ 
+ 	set_bit(port1, parent_hub->busy_bits);

commit 9ad3d6ccf5eee285e233dbaf186369b8d477a666
+Author: Alan Stern 
+Date:   Thu Nov 17 17:10:32 2005 -0500
+
+    [PATCH] USB: Remove USB private semaphore
+    
+    This patch (as605) removes the private udev->serialize semaphore,
+    relying instead on the locking provided by the embedded struct device's
+    semaphore.  The changes are confined to the core, except that the
+    usb_trylock_device routine now uses the return convention of
+    down_trylock rather than down_read_trylock (they return opposite values
+    for no good reason).
+    
+    A couple of other associated changes are included as well:
+    
+            Now that we aren't concerned about HCDs that avoid using the
+            hcd glue layer, usb_disconnect no longer needs to acquire the
+            usb_bus_lock -- that can be done by usb_remove_hcd where it
+            belongs.
+    
+            Devices aren't locked over the same scope of code in
+            usb_new_device and hub_port_connect_change as they used to be.
+            This shouldn't cause any trouble.
+    
+    Along with the preceding driver core patch, this needs a lot of testing.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
+index 83e815d3cd52..55bc563a3256 100644
+--- a/drivers/usb/core/devices.c
++++ b/drivers/usb/core/devices.c
+@@ -545,10 +545,10 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, loff_t *ski
+ 		struct usb_device *childdev = usbdev->children[chix];
+ 
+ 		if (childdev) {
+-			down(&childdev->serialize);
++			usb_lock_device(childdev);
+ 			ret = usb_device_dump(buffer, nbytes, skip_bytes, file_offset, childdev,
+ 					bus, level + 1, chix, ++cnt);
+-			up(&childdev->serialize);
++			usb_unlock_device(childdev);
+ 			if (ret == -EFAULT)
+ 				return total_written;
+ 			total_written += ret;
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 3a73170e95dd..2b68998fe4b3 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -1349,9 +1349,7 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
+ 	/* let kernel drivers try to (re)bind to the interface */
+ 	case USBDEVFS_CONNECT:
+ 		usb_unlock_device(ps->dev);
+-		usb_lock_all_devices();
+ 		bus_rescan_devices(intf->dev.bus);
+-		usb_unlock_all_devices();
+ 		usb_lock_device(ps->dev);
+ 		break;
+ 
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index bb139f06bcd6..076462c8ba2a 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -432,9 +432,7 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner)
+ 	spin_lock_init(&new_driver->dynids.lock);
+ 	INIT_LIST_HEAD(&new_driver->dynids.list);
+ 
+-	usb_lock_all_devices();
+ 	retval = driver_register(&new_driver->driver);
+-	usb_unlock_all_devices();
+ 
+ 	if (!retval) {
+ 		pr_info("%s: registered new driver %s\n",
+@@ -465,11 +463,9 @@ void usb_deregister(struct usb_driver *driver)
+ {
+ 	pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name);
+ 
+-	usb_lock_all_devices();
+ 	usb_remove_newid_file(driver);
+ 	usb_free_dynids(driver);
+ 	driver_unregister(&driver->driver);
+-	usb_unlock_all_devices();
+ 
+ 	usbfs_update_special();
+ }
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index da24c31ee00d..d16a0e8a7d72 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -857,9 +857,7 @@ static int register_root_hub (struct usb_device *usb_dev,
+ 		return (retval < 0) ? retval : -EMSGSIZE;
+ 	}
+ 
+-	usb_lock_device (usb_dev);
+ 	retval = usb_new_device (usb_dev);
+-	usb_unlock_device (usb_dev);
+ 	if (retval) {
+ 		usb_dev->bus->root_hub = NULL;
+ 		dev_err (parent_dev, "can't register root hub for %s, %d\n",
+@@ -1891,7 +1889,10 @@ void usb_remove_hcd(struct usb_hcd *hcd)
+ 	spin_lock_irq (&hcd_root_hub_lock);
+ 	hcd->rh_registered = 0;
+ 	spin_unlock_irq (&hcd_root_hub_lock);
++
++	down(&usb_bus_list_lock);
+ 	usb_disconnect(&hcd->self.root_hub);
++	up(&usb_bus_list_lock);
+ 
+ 	hcd->poll_rh = 0;
+ 	del_timer_sync(&hcd->rh_timer);
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 40c6c50c6bd9..dd3bcfb2bcb6 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -32,7 +32,7 @@
+ #include "hub.h"
+ 
+ /* Protect struct usb_device->state and ->children members
+- * Note: Both are also protected by ->serialize, except that ->state can
++ * Note: Both are also protected by ->dev.sem, except that ->state can
+  * change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */
+ static DEFINE_SPINLOCK(device_state_lock);
+ 
+@@ -975,8 +975,8 @@ static int locktree(struct usb_device *udev)
+ 			/* when everyone grabs locks top->bottom,
+ 			 * non-overlapping work may be concurrent
+ 			 */
+-			down(&udev->serialize);
+-			up(&hdev->serialize);
++			usb_lock_device(udev);
++			usb_unlock_device(hdev);
+ 			return t + 1;
+ 		}
+ 	}
+@@ -1132,16 +1132,10 @@ void usb_disconnect(struct usb_device **pdev)
+ 	 * this quiesces everyting except pending urbs.
+ 	 */
+ 	usb_set_device_state(udev, USB_STATE_NOTATTACHED);
+-
+-	/* lock the bus list on behalf of HCDs unregistering their root hubs */
+-	if (!udev->parent) {
+-		down(&usb_bus_list_lock);
+-		usb_lock_device(udev);
+-	} else
+-		down(&udev->serialize);
+-
+ 	dev_info (&udev->dev, "USB disconnect, address %d\n", udev->devnum);
+ 
++	usb_lock_device(udev);
++
+ 	/* Free up all the children before we remove this device */
+ 	for (i = 0; i < USB_MAXCHILDREN; i++) {
+ 		if (udev->children[i])
+@@ -1169,11 +1163,7 @@ void usb_disconnect(struct usb_device **pdev)
+ 	*pdev = NULL;
+ 	spin_unlock_irq(&device_state_lock);
+ 
+-	if (!udev->parent) {
+-		usb_unlock_device(udev);
+-		up(&usb_bus_list_lock);
+-	} else
+-		up(&udev->serialize);
++	usb_unlock_device(udev);
+ 
+ 	device_unregister(&udev->dev);
+ }
+@@ -1243,8 +1233,8 @@ static inline void show_string(struct usb_device *udev, char *id, char *string)
+  *
+  * This is called with devices which have been enumerated, but not yet
+  * configured.  The device descriptor is available, but not descriptors
+- * for any device configuration.  The caller must have locked udev and
+- * either the parent hub (if udev is a normal device) or else the
++ * for any device configuration.  The caller must have locked either
++ * the parent hub (if udev is a normal device) or else the
+  * usb_bus_list_lock (if udev is a root hub).  The parent's pointer to
+  * udev has already been installed, but udev is not yet visible through
+  * sysfs or other filesystem code.
+@@ -1254,8 +1244,7 @@ static inline void show_string(struct usb_device *udev, char *id, char *string)
+  *
+  * This call is synchronous, and may not be used in an interrupt context.
+  *
+- * Only the hub driver should ever call this; root hub registration
+- * uses it indirectly.
++ * Only the hub driver or root-hub registrar should ever call this.
+  */
+ int usb_new_device(struct usb_device *udev)
+ {
+@@ -1364,6 +1353,8 @@ int usb_new_device(struct usb_device *udev)
+ 	}
+ 	usb_create_sysfs_dev_files (udev);
+ 
++	usb_lock_device(udev);
++
+ 	/* choose and set the configuration. that registers the interfaces
+ 	 * with the driver core, and lets usb device drivers bind to them.
+ 	 */
+@@ -1385,6 +1376,8 @@ int usb_new_device(struct usb_device *udev)
+ 	/* USB device state == configured ... usable */
+ 	usb_notify_add_device(udev);
+ 
++	usb_unlock_device(udev);
++
+ 	return 0;
+ 
+ fail:
+@@ -1872,11 +1865,8 @@ int usb_resume_device(struct usb_device *udev)
+ 	usb_unlock_device(udev);
+ 
+ 	/* rebind drivers that had no suspend() */
+-	if (status == 0) {
+-		usb_lock_all_devices();
++	if (status == 0)
+ 		bus_rescan_devices(&usb_bus_type);
+-		usb_unlock_all_devices();
+-	}
+ 	return status;
+ }
+ 
+@@ -1889,14 +1879,14 @@ static int remote_wakeup(struct usb_device *udev)
+ 	/* don't repeat RESUME sequence if this device
+ 	 * was already woken up by some other task
+ 	 */
+-	down(&udev->serialize);
++	usb_lock_device(udev);
+ 	if (udev->state == USB_STATE_SUSPENDED) {
+ 		dev_dbg(&udev->dev, "RESUME (wakeup)\n");
+ 		/* TRSMRCY = 10 msec */
+ 		msleep(10);
+ 		status = finish_device_resume(udev);
+ 	}
+-	up(&udev->serialize);
++	usb_unlock_device(udev);
+ #endif
+ 	return status;
+ }
+@@ -1997,7 +1987,7 @@ static int hub_resume(struct usb_interface *intf)
+ 
+ 		if (!udev || status < 0)
+ 			continue;
+-		down (&udev->serialize);
++		usb_lock_device(udev);
+ 		if (portstat & USB_PORT_STAT_SUSPEND)
+ 			status = hub_port_resume(hub, port1, udev);
+ 		else {
+@@ -2008,7 +1998,7 @@ static int hub_resume(struct usb_interface *intf)
+ 				hub_port_logical_disconnect(hub, port1);
+ 			}
+ 		}
+-		up(&udev->serialize);
++		usb_unlock_device(udev);
+ 	}
+ 	}
+ #endif
+@@ -2573,7 +2563,6 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 		 * udev becomes globally accessible, although presumably
+ 		 * no one will look at it until hdev is unlocked.
+ 		 */
+-		down (&udev->serialize);
+ 		status = 0;
+ 
+ 		/* We mustn't add new devices if the parent hub has
+@@ -2597,7 +2586,6 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 			}
+ 		}
+ 
+-		up (&udev->serialize);
+ 		if (status)
+ 			goto loop_disable;
+ 
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 294e9f127477..fcfda21be499 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -32,7 +32,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ #include 
+ 
+ #include 
+@@ -49,8 +48,6 @@ const char *usbcore_name = "usbcore";
+ static int nousb;	/* Disable USB when built into kernel image */
+ 			/* Not honored on modular build */
+ 
+-static DECLARE_RWSEM(usb_all_devices_rwsem);
+-
+ 
+ /**
+  * usb_ifnum_to_if - get the interface object with a given interface number
+@@ -446,8 +443,6 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
+ 	dev->parent = parent;
+ 	INIT_LIST_HEAD(&dev->filelist);
+ 
+-	init_MUTEX(&dev->serialize);
+-
+ 	return dev;
+ }
+ 
+@@ -520,75 +515,20 @@ void usb_put_intf(struct usb_interface *intf)
+ 
+ /*			USB device locking
+  *
+- * Although locking USB devices should be straightforward, it is
+- * complicated by the way the driver-model core works.  When a new USB
+- * driver is registered or unregistered, the core will automatically
+- * probe or disconnect all matching interfaces on all USB devices while
+- * holding the USB subsystem writelock.  There's no good way for us to
+- * tell which devices will be used or to lock them beforehand; our only
+- * option is to effectively lock all the USB devices.
+- *
+- * We do that by using a private rw-semaphore, usb_all_devices_rwsem.
+- * When locking an individual device you must first acquire the rwsem's
+- * readlock.  When a driver is registered or unregistered the writelock
+- * must be held.  These actions are encapsulated in the subroutines
+- * below, so all a driver needs to do is call usb_lock_device() and
+- * usb_unlock_device().
++ * USB devices and interfaces are locked using the semaphore in their
++ * embedded struct device.  The hub driver guarantees that whenever a
++ * device is connected or disconnected, drivers are called with the
++ * USB device locked as well as their particular interface.
+  *
+  * Complications arise when several devices are to be locked at the same
+  * time.  Only hub-aware drivers that are part of usbcore ever have to
+- * do this; nobody else needs to worry about it.  The problem is that
+- * usb_lock_device() must not be called to lock a second device since it
+- * would acquire the rwsem's readlock reentrantly, leading to deadlock if
+- * another thread was waiting for the writelock.  The solution is simple:
+- *
+- *	When locking more than one device, call usb_lock_device()
+- *	to lock the first one.  Lock the others by calling
+- *	down(&udev->serialize) directly.
+- *
+- *	When unlocking multiple devices, use up(&udev->serialize)
+- *	to unlock all but the last one.  Unlock the last one by
+- *	calling usb_unlock_device().
++ * do this; nobody else needs to worry about it.  The rule for locking
++ * is simple:
+  *
+  *	When locking both a device and its parent, always lock the
+  *	the parent first.
+  */
+ 
+-/**
+- * usb_lock_device - acquire the lock for a usb device structure
+- * @udev: device that's being locked
+- *
+- * Use this routine when you don't hold any other device locks;
+- * to acquire nested inner locks call down(&udev->serialize) directly.
+- * This is necessary for proper interaction with usb_lock_all_devices().
+- */
+-void usb_lock_device(struct usb_device *udev)
+-{
+-	down_read(&usb_all_devices_rwsem);
+-	down(&udev->serialize);
+-}
+-
+-/**
+- * usb_trylock_device - attempt to acquire the lock for a usb device structure
+- * @udev: device that's being locked
+- *
+- * Don't use this routine if you already hold a device lock;
+- * use down_trylock(&udev->serialize) instead.
+- * This is necessary for proper interaction with usb_lock_all_devices().
+- *
+- * Returns 1 if successful, 0 if contention.
+- */
+-int usb_trylock_device(struct usb_device *udev)
+-{
+-	if (!down_read_trylock(&usb_all_devices_rwsem))
+-		return 0;
+-	if (down_trylock(&udev->serialize)) {
+-		up_read(&usb_all_devices_rwsem);
+-		return 0;
+-	}
+-	return 1;
+-}
+-
+ /**
+  * usb_lock_device_for_reset - cautiously acquire the lock for a
+  *	usb device structure
+@@ -627,7 +567,7 @@ int usb_lock_device_for_reset(struct usb_device *udev,
+ 		}
+ 	}
+ 
+-	while (!usb_trylock_device(udev)) {
++	while (usb_trylock_device(udev) != 0) {
+ 
+ 		/* If we can't acquire the lock after waiting one second,
+ 		 * we're probably deadlocked */
+@@ -645,39 +585,6 @@ int usb_lock_device_for_reset(struct usb_device *udev,
+ 	return 1;
+ }
+ 
+-/**
+- * usb_unlock_device - release the lock for a usb device structure
+- * @udev: device that's being unlocked
+- *
+- * Use this routine when releasing the only device lock you hold;
+- * to release inner nested locks call up(&udev->serialize) directly.
+- * This is necessary for proper interaction with usb_lock_all_devices().
+- */
+-void usb_unlock_device(struct usb_device *udev)
+-{
+-	up(&udev->serialize);
+-	up_read(&usb_all_devices_rwsem);
+-}
+-
+-/**
+- * usb_lock_all_devices - acquire the lock for all usb device structures
+- *
+- * This is necessary when registering a new driver or probing a bus,
+- * since the driver-model core may try to use any usb_device.
+- */
+-void usb_lock_all_devices(void)
+-{
+-	down_write(&usb_all_devices_rwsem);
+-}
+-
+-/**
+- * usb_unlock_all_devices - release the lock for all usb device structures
+- */
+-void usb_unlock_all_devices(void)
+-{
+-	up_write(&usb_all_devices_rwsem);
+-}
+-
+ 
+ static struct usb_device *match_device(struct usb_device *dev,
+ 				       u16 vendor_id, u16 product_id)
+@@ -700,10 +607,10 @@ static struct usb_device *match_device(struct usb_device *dev,
+ 	/* look through all of the children of this device */
+ 	for (child = 0; child < dev->maxchild; ++child) {
+ 		if (dev->children[child]) {
+-			down(&dev->children[child]->serialize);
++			usb_lock_device(dev->children[child]);
+ 			ret_dev = match_device(dev->children[child],
+ 					       vendor_id, product_id);
+-			up(&dev->children[child]->serialize);
++			usb_unlock_device(dev->children[child]);
+ 			if (ret_dev)
+ 				goto exit;
+ 		}
+@@ -1300,10 +1207,7 @@ EXPORT_SYMBOL(usb_put_dev);
+ EXPORT_SYMBOL(usb_get_dev);
+ EXPORT_SYMBOL(usb_hub_tt_clear_buffer);
+ 
+-EXPORT_SYMBOL(usb_lock_device);
+-EXPORT_SYMBOL(usb_trylock_device);
+ EXPORT_SYMBOL(usb_lock_device_for_reset);
+-EXPORT_SYMBOL(usb_unlock_device);
+ 
+ EXPORT_SYMBOL(usb_driver_claim_interface);
+ EXPORT_SYMBOL(usb_driver_release_interface);
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 98e85fb4d3b7..4647e1ebc68d 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -16,9 +16,6 @@ extern int usb_get_device_descriptor(struct usb_device *dev,
+ extern char *usb_cache_string(struct usb_device *udev, int index);
+ extern int usb_set_configuration(struct usb_device *dev, int configuration);
+ 
+-extern void usb_lock_all_devices(void);
+-extern void usb_unlock_all_devices(void);
+-
+ extern void usb_kick_khubd(struct usb_device *dev);
+ extern void usb_suspend_root_hub(struct usb_device *hdev);
+ extern void usb_resume_root_hub(struct usb_device *dev);
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index 72e3b12a1926..4b2226d77b34 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -372,7 +372,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ 					& ohci->hc_control)
+ 				== OHCI_USB_OPER
+ 			&& time_after (jiffies, ohci->next_statechange)
+-			&& usb_trylock_device (hcd->self.root_hub)
++			&& usb_trylock_device (hcd->self.root_hub) == 0
+ 			) {
+ 		ohci_vdbg (ohci, "autosuspend\n");
+ 		(void) ohci_bus_suspend (hcd);
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 2714814ab66c..46dc0421d19e 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -329,8 +329,6 @@ struct usb_device {
+ 	struct usb_tt	*tt; 		/* low/full speed dev, highspeed hub */
+ 	int		ttport;		/* device port on that tt hub */
+ 
+-	struct semaphore serialize;
+-
+ 	unsigned int toggle[2];		/* one bit for each endpoint
+ 					 * ([0] = IN, [1] = OUT) */
+ 
+@@ -377,11 +375,12 @@ struct usb_device {
+ extern struct usb_device *usb_get_dev(struct usb_device *dev);
+ extern void usb_put_dev(struct usb_device *dev);
+ 
+-extern void usb_lock_device(struct usb_device *udev);
+-extern int usb_trylock_device(struct usb_device *udev);
++/* USB device locking */
++#define usb_lock_device(udev)		down(&(udev)->dev.sem)
++#define usb_unlock_device(udev)		up(&(udev)->dev.sem)
++#define usb_trylock_device(udev)	down_trylock(&(udev)->dev.sem)
+ extern int usb_lock_device_for_reset(struct usb_device *udev,
+ 		struct usb_interface *iface);
+-extern void usb_unlock_device(struct usb_device *udev);
+ 
+ /* USB port reset for device reinitialization */
+ extern int usb_reset_device(struct usb_device *dev);

commit 1c50c317e2e7f15427149cbc216a63366468710e
+Author: Alan Stern 
+Date:   Mon Nov 14 11:45:38 2005 -0500
+
+    [PATCH] USB: central handling for host controllers that were reset during suspend/resume
+    
+    This patch (as515b) adds a routine to usbcore to simplify handling of
+    host controllers that lost power or were reset during suspend/resume.
+    The new core routine marks all the child devices of the root hub as
+    NOTATTACHED and tells khubd to disconnect the device structures as soon
+    as possible.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index c8a1b350e2cf..591b5aad1a18 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -380,6 +380,7 @@ extern int usb_find_interface_driver (struct usb_device *dev,
+ #ifdef CONFIG_PM
+ extern void usb_hcd_suspend_root_hub (struct usb_hcd *hcd);
+ extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
++extern void usb_root_hub_lost_power (struct usb_device *rhdev);
+ extern int hcd_bus_suspend (struct usb_bus *bus);
+ extern int hcd_bus_resume (struct usb_bus *bus);
+ #else
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index f78bd124d290..5faf7edd73cb 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1039,6 +1039,39 @@ void usb_set_device_state(struct usb_device *udev,
+ EXPORT_SYMBOL(usb_set_device_state);
+ 
+ 
++#ifdef CONFIG_PM
++
++/**
++ * usb_root_hub_lost_power - called by HCD if the root hub lost Vbus power
++ * @rhdev: struct usb_device for the root hub
++ *
++ * The USB host controller driver calls this function when its root hub
++ * is resumed and Vbus power has been interrupted or the controller
++ * has been reset.  The routine marks all the children of the root hub
++ * as NOTATTACHED and marks logical connect-change events on their ports.
++ */
++void usb_root_hub_lost_power(struct usb_device *rhdev)
++{
++	struct usb_hub *hub;
++	int port1;
++	unsigned long flags;
++
++	dev_warn(&rhdev->dev, "root hub lost power or was reset\n");
++	spin_lock_irqsave(&device_state_lock, flags);
++	hub = hdev_to_hub(rhdev);
++	for (port1 = 1; port1 <= rhdev->maxchild; ++port1) {
++		if (rhdev->children[port1 - 1]) {
++			recursively_mark_NOTATTACHED(
++					rhdev->children[port1 - 1]);
++			set_bit(port1, hub->change_bits);
++		}
++	}
++	spin_unlock_irqrestore(&device_state_lock, flags);
++}
++EXPORT_SYMBOL_GPL(usb_root_hub_lost_power);
++
++#endif
++
+ static void choose_address(struct usb_device *udev)
+ {
+ 	int		devnum;
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index ac088bc72f1c..08ca0f849dab 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -278,7 +278,6 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
+ {
+ 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
+ 	unsigned		port;
+-	struct usb_device	*root = hcd->self.root_hub;
+ 	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
+ 	int			retval = -EINVAL;
+ 
+@@ -312,13 +311,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
+ 
+ restart:
+ 	ehci_dbg(ehci, "lost power, restarting\n");
+-	for (port = HCS_N_PORTS(ehci->hcs_params); port > 0; ) {
+-		port--;
+-		if (!root->children [port])
+-			continue;
+-		usb_set_device_state(root->children[port],
+-					USB_STATE_NOTATTACHED);
+-	}
++	usb_root_hub_lost_power(hcd->self.root_hub);
+ 
+ 	/* Else reset, to cope with power loss or flush-to-storage
+ 	 * style "resume" having let BIOS kick in during reboot.
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index e3af3ac4416a..a4b12404ae08 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -795,7 +795,6 @@ static int ohci_restart (struct ohci_hcd *ohci)
+ 	int temp;
+ 	int i;
+ 	struct urb_priv *priv;
+-	struct usb_device *root = ohci_to_hcd(ohci)->self.root_hub;
+ 
+ 	/* mark any devices gone, so they do nothing till khubd disconnects.
+ 	 * recycle any "live" eds/tds (and urbs) right away.
+@@ -804,11 +803,7 @@ static int ohci_restart (struct ohci_hcd *ohci)
+ 	 */ 
+ 	spin_lock_irq(&ohci->lock);
+ 	disable (ohci);
+-	for (i = 0; i < root->maxchild; i++) {
+-		if (root->children [i])
+-			usb_set_device_state (root->children[i],
+-				USB_STATE_NOTATTACHED);
+-	}
++	usb_root_hub_lost_power(ohci_to_hcd(ohci)->self.root_hub);
+ 	if (!list_empty (&ohci->pending))
+ 		ohci_dbg(ohci, "abort schedule...\n");
+ 	list_for_each_entry (priv, &ohci->pending, pending) {
+diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
+index 3a9cd4607962..517360b77d8e 100644
+--- a/drivers/usb/host/sl811-hcd.c
++++ b/drivers/usb/host/sl811-hcd.c
+@@ -1803,6 +1803,7 @@ sl811h_resume(struct platform_device *dev)
+ 			|| !device_can_wakeup(&hcd->self.root_hub->dev)) {
+ 		sl811->port1 = 0;
+ 		port_power(sl811, 1);
++		usb_root_hub_lost_power(hcd->self.root_hub);
+ 		return 0;
+ 	}
+ 
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 1c0394cb3c89..071fab6b6475 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -748,8 +748,12 @@ static int uhci_resume(struct usb_hcd *hcd)
+ 	check_and_reset_hc(uhci);
+ 	configure_hc(uhci);
+ 
+-	if (uhci->rh_state == UHCI_RH_RESET)
++	if (uhci->rh_state == UHCI_RH_RESET) {
++
++		/* The controller had to be reset */
++		usb_root_hub_lost_power(hcd->self.root_hub);
+ 		suspend_rh(uhci, UHCI_RH_SUSPENDED);
++	}
+ 
+ 	spin_unlock_irq(&uhci->lock);
+ 

commit 8364d6b0be2dbbf162c6aea79615b5025a0d67c2
+Author: Alan Stern 
+Date:   Mon Nov 14 12:16:30 2005 -0500
+
+    [PATCH] USB: dummy_hcd: rename variables
+    
+    The recent platform_device update has reintroduced into dummy_hcd.c the
+    dreaded dev->dev syndrome.  This harkens back to when an earlier version
+    of that driver included the unforgettable line:
+    
+            dev->dev.dev.driver_data = dev;
+    
+    This patch (as602) renames the platform_device variables to "pdev", in
+    the hope of reducing confusion.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index c655d46c8aed..4932b07b316d 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -896,7 +896,7 @@ dummy_gadget_release (struct device *dev)
+ #endif
+ }
+ 
+-static int dummy_udc_probe (struct platform_device *dev)
++static int dummy_udc_probe (struct platform_device *pdev)
+ {
+ 	struct dummy	*dum = the_controller;
+ 	int		rc;
+@@ -909,7 +909,7 @@ static int dummy_udc_probe (struct platform_device *dev)
+ 	dum->gadget.is_otg = (dummy_to_hcd(dum)->self.otg_port != 0);
+ 
+ 	strcpy (dum->gadget.dev.bus_id, "gadget");
+-	dum->gadget.dev.parent = &dev->dev;
++	dum->gadget.dev.parent = &pdev->dev;
+ 	dum->gadget.dev.release = dummy_gadget_release;
+ 	rc = device_register (&dum->gadget.dev);
+ 	if (rc < 0)
+@@ -919,47 +919,47 @@ static int dummy_udc_probe (struct platform_device *dev)
+ 	usb_bus_get (&dummy_to_hcd (dum)->self);
+ #endif
+ 
+-	platform_set_drvdata (dev, dum);
++	platform_set_drvdata (pdev, dum);
+ 	device_create_file (&dum->gadget.dev, &dev_attr_function);
+ 	return rc;
+ }
+ 
+-static int dummy_udc_remove (struct platform_device *dev)
++static int dummy_udc_remove (struct platform_device *pdev)
+ {
+-	struct dummy	*dum = platform_get_drvdata (dev);
++	struct dummy	*dum = platform_get_drvdata (pdev);
+ 
+-	platform_set_drvdata (dev, NULL);
++	platform_set_drvdata (pdev, NULL);
+ 	device_remove_file (&dum->gadget.dev, &dev_attr_function);
+ 	device_unregister (&dum->gadget.dev);
+ 	return 0;
+ }
+ 
+-static int dummy_udc_suspend (struct platform_device *dev, pm_message_t state)
++static int dummy_udc_suspend (struct platform_device *pdev, pm_message_t state)
+ {
+-	struct dummy	*dum = platform_get_drvdata(dev);
++	struct dummy	*dum = platform_get_drvdata(pdev);
+ 
+-	dev_dbg (&dev->dev, "%s\n", __FUNCTION__);
++	dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
+ 	spin_lock_irq (&dum->lock);
+ 	dum->udc_suspended = 1;
+ 	set_link_state (dum);
+ 	spin_unlock_irq (&dum->lock);
+ 
+-	dev->dev.power.power_state = state;
++	pdev->dev.power.power_state = state;
+ 	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
+ 	return 0;
+ }
+ 
+-static int dummy_udc_resume (struct platform_device *dev)
++static int dummy_udc_resume (struct platform_device *pdev)
+ {
+-	struct dummy	*dum = platform_get_drvdata(dev);
++	struct dummy	*dum = platform_get_drvdata(pdev);
+ 
+-	dev_dbg (&dev->dev, "%s\n", __FUNCTION__);
++	dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
+ 	spin_lock_irq (&dum->lock);
+ 	dum->udc_suspended = 0;
+ 	set_link_state (dum);
+ 	spin_unlock_irq (&dum->lock);
+ 
+-	dev->dev.power.power_state = PMSG_ON;
++	pdev->dev.power.power_state = PMSG_ON;
+ 	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
+ 	return 0;
+ }
+@@ -1899,14 +1899,14 @@ static const struct hc_driver dummy_hcd = {
+ 	.bus_resume =		dummy_bus_resume,
+ };
+ 
+-static int dummy_hcd_probe (struct platform_device *dev)
++static int dummy_hcd_probe(struct platform_device *pdev)
+ {
+ 	struct usb_hcd		*hcd;
+ 	int			retval;
+ 
+-	dev_info(&dev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
++	dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
+ 
+-	hcd = usb_create_hcd (&dummy_hcd, &dev->dev, dev->dev.bus_id);
++	hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, pdev->dev.bus_id);
+ 	if (!hcd)
+ 		return -ENOMEM;
+ 	the_controller = hcd_to_dummy (hcd);
+@@ -1919,34 +1919,34 @@ static int dummy_hcd_probe (struct platform_device *dev)
+ 	return retval;
+ }
+ 
+-static int dummy_hcd_remove (struct platform_device *dev)
++static int dummy_hcd_remove (struct platform_device *pdev)
+ {
+ 	struct usb_hcd		*hcd;
+ 
+-	hcd = platform_get_drvdata (dev);
++	hcd = platform_get_drvdata (pdev);
+ 	usb_remove_hcd (hcd);
+ 	usb_put_hcd (hcd);
+ 	the_controller = NULL;
+ 	return 0;
+ }
+ 
+-static int dummy_hcd_suspend (struct platform_device *dev, pm_message_t state)
++static int dummy_hcd_suspend (struct platform_device *pdev, pm_message_t state)
+ {
+ 	struct usb_hcd		*hcd;
+ 
+-	dev_dbg (&dev->dev, "%s\n", __FUNCTION__);
+-	hcd = platform_get_drvdata (dev);
++	dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
++	hcd = platform_get_drvdata (pdev);
+ 
+ 	hcd->state = HC_STATE_SUSPENDED;
+ 	return 0;
+ }
+ 
+-static int dummy_hcd_resume (struct platform_device *dev)
++static int dummy_hcd_resume (struct platform_device *pdev)
+ {
+ 	struct usb_hcd		*hcd;
+ 
+-	dev_dbg (&dev->dev, "%s\n", __FUNCTION__);
+-	hcd = platform_get_drvdata (dev);
++	dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
++	hcd = platform_get_drvdata (pdev);
+ 	hcd->state = HC_STATE_RUNNING;
+ 
+ 	usb_hcd_poll_rh_status (hcd);

commit 87c4252a35310fdbb2aabb880a39b83f83cadf62
+Author: Alan Stern 
+Date:   Wed Nov 9 16:59:56 2005 -0500
+
+    [PATCH] USB: file-storage gadget: Add reference count for children
+    
+    This patch (as601) adds a proper reference count to the file-storage
+    gadget's main data structure, to keep track of references held by child
+    devices (LUNs in this case).  Before this, the driver would wait for
+    each child to be released before unbinding.
+    
+    While there's nothing really wrong with that (you can't create a hang by
+    doing "rmmod g_file_storage 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index ea09aaa3cab6..f6f0b2aa1145 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -224,6 +224,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -631,6 +632,9 @@ struct fsg_dev {
+ 	/* filesem protects: backing files in use */
+ 	struct rw_semaphore	filesem;
+ 
++	/* reference counting: wait until all LUNs are released */
++	struct kref		ref;
++
+ 	struct usb_ep		*ep0;		// Handy copy of gadget->ep0
+ 	struct usb_request	*ep0req;	// For control responses
+ 	volatile unsigned int	ep0_req_tag;
+@@ -694,7 +698,6 @@ struct fsg_dev {
+ 	unsigned int		nluns;
+ 	struct lun		*luns;
+ 	struct lun		*curlun;
+-	struct completion	lun_released;
+ };
+ 
+ typedef void (*fsg_routine_t)(struct fsg_dev *);
+@@ -3642,11 +3645,19 @@ static DEVICE_ATTR(file, 0444, show_file, NULL);
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++static void fsg_release(struct kref *ref)
++{
++	struct fsg_dev	*fsg = container_of(ref, struct fsg_dev, ref);
++
++	kfree(fsg->luns);
++	kfree(fsg);
++}
++
+ static void lun_release(struct device *dev)
+ {
+ 	struct fsg_dev	*fsg = (struct fsg_dev *) dev_get_drvdata(dev);
+ 
+-	complete(&fsg->lun_released);
++	kref_put(&fsg->ref, fsg_release);
+ }
+ 
+ static void fsg_unbind(struct usb_gadget *gadget)
+@@ -3660,14 +3671,12 @@ static void fsg_unbind(struct usb_gadget *gadget)
+ 	clear_bit(REGISTERED, &fsg->atomic_bitflags);
+ 
+ 	/* Unregister the sysfs attribute files and the LUNs */
+-	init_completion(&fsg->lun_released);
+ 	for (i = 0; i < fsg->nluns; ++i) {
+ 		curlun = &fsg->luns[i];
+ 		if (curlun->registered) {
+ 			device_remove_file(&curlun->dev, &dev_attr_ro);
+ 			device_remove_file(&curlun->dev, &dev_attr_file);
+ 			device_unregister(&curlun->dev);
+-			wait_for_completion(&fsg->lun_released);
+ 			curlun->registered = 0;
+ 		}
+ 	}
+@@ -3846,6 +3855,7 @@ static int __init fsg_bind(struct usb_gadget *gadget)
+ 			curlun->dev.release = lun_release;
+ 			device_create_file(&curlun->dev, &dev_attr_ro);
+ 			device_create_file(&curlun->dev, &dev_attr_file);
++			kref_get(&fsg->ref);
+ 		}
+ 
+ 		if (file[i] && *file[i]) {
+@@ -4061,6 +4071,7 @@ static int __init fsg_alloc(void)
+ 		return -ENOMEM;
+ 	spin_lock_init(&fsg->lock);
+ 	init_rwsem(&fsg->filesem);
++	kref_init(&fsg->ref);
+ 	init_waitqueue_head(&fsg->thread_wqh);
+ 	init_completion(&fsg->thread_notifier);
+ 
+@@ -4069,13 +4080,6 @@ static int __init fsg_alloc(void)
+ }
+ 
+ 
+-static void fsg_free(struct fsg_dev *fsg)
+-{
+-	kfree(fsg->luns);
+-	kfree(fsg);
+-}
+-
+-
+ static int __init fsg_init(void)
+ {
+ 	int		rc;
+@@ -4085,7 +4089,7 @@ static int __init fsg_init(void)
+ 		return rc;
+ 	fsg = the_fsg;
+ 	if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0)
+-		fsg_free(fsg);
++		kref_put(&fsg->ref, fsg_release);
+ 	return rc;
+ }
+ module_init(fsg_init);
+@@ -4103,6 +4107,6 @@ static void __exit fsg_cleanup(void)
+ 	wait_for_completion(&fsg->thread_notifier);
+ 
+ 	close_all_backing_files(fsg);
+-	fsg_free(fsg);
++	kref_put(&fsg->ref, fsg_release);
+ }
+ module_exit(fsg_cleanup);

commit 6912354a895fcd234155273fe8838a0d83259a9b
+Author: Alan Stern 
+Date:   Thu Nov 3 11:44:49 2005 -0500
+
+    [PATCH] USB: EHCI: fix conflation of buf == 0 with len == 0
+    
+    When the ehci-hcd driver prepares a control URB, it tests for a
+    zero-length data stage by looking at the transfer_dma value instead of
+    the transfer_buffer_length.  (In fact it does this even for non-control
+    URBs, which is an additional aspect of the same bug.)
+    
+    However, under certain circumstances it's possible for transfer_dma to
+    be 0 while transfer_buffer_length is non-zero.  This can happen when a
+    freshly allocated page (mapped to address 0 and marked Copy-On-Write,
+    but never written to) is used as the source buffer for an OUT transfer.
+    This patch (as598) fixes the problem.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index bf03ec0d8ee2..9b13bf2fa98d 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -514,18 +514,18 @@ qh_urb_transaction (
+ 		qtd->urb = urb;
+ 		qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
+ 		list_add_tail (&qtd->qtd_list, head);
++
++		/* for zero length DATA stages, STATUS is always IN */
++		if (len == 0)
++			token |= (1 /* "in" */ << 8);
+ 	} 
+ 
+ 	/*
+ 	 * data transfer stage:  buffer setup
+ 	 */
+-	if (likely (len > 0))
+-		buf = urb->transfer_dma;
+-	else
+-		buf = 0;
++	buf = urb->transfer_dma;
+ 
+-	/* for zero length DATA stages, STATUS is always IN */
+-	if (!buf || is_input)
++	if (is_input)
+ 		token |= (1 /* "in" */ << 8);
+ 	/* else it's already initted to "out" pid (0 << 8) */
+ 
+@@ -572,7 +572,7 @@ qh_urb_transaction (
+ 	 * control requests may need a terminating data "status" ack;
+ 	 * bulk ones may need a terminating short packet (zero length).
+ 	 */
+-	if (likely (buf != 0)) {
++	if (likely (urb->transfer_buffer_length != 0)) {
+ 		int	one_more = 0;
+ 
+ 		if (usb_pipecontrol (urb->pipe)) {

commit 5a9191ff683ce4ebfd2c6a15e2989f5b1f420321
+Author: Alan Stern 
+Date:   Wed Dec 21 14:28:11 2005 -0800
+
+    [PATCH] usbcore: allow suspend/resume even if drivers don't support it
+    
+    This patch (as618) changes usbcore to prevent derailing the
+    suspend/resume sequence when a USB driver doesn't include support for
+    it.  This is a workaround rather than a true fix; the core needs to be
+    changed so that URB submissions from suspended drivers can be refused
+    and outstanding URBs cancelled.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index e197ce9353de..e80ef9467825 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -1432,7 +1432,8 @@ static int usb_generic_suspend(struct device *dev, pm_message_t message)
+ 			mark_quiesced(intf);
+ 	} else {
+ 		// FIXME else if there's no suspend method, disconnect...
+-		dev_warn(dev, "no %s?\n", "suspend");
++		dev_warn(dev, "no suspend for driver %s?\n", driver->name);
++		mark_quiesced(intf);
+ 		status = 0;
+ 	}
+ 	return status;
+@@ -1460,8 +1461,10 @@ static int usb_generic_resume(struct device *dev)
+ 	}
+ 
+ 	if ((dev->driver == NULL) ||
+-	    (dev->driver_data == &usb_generic_driver_data))
++	    (dev->driver_data == &usb_generic_driver_data)) {
++		dev->power.power_state.event = PM_EVENT_FREEZE;
+ 		return 0;
++	}
+ 
+ 	intf = to_usb_interface(dev);
+ 	driver = to_usb_driver(dev->driver);
+@@ -1481,7 +1484,7 @@ static int usb_generic_resume(struct device *dev)
+ 			mark_quiesced(intf);
+ 		}
+ 	} else
+-		dev_warn(dev, "no %s?\n", "resume");
++		dev_warn(dev, "no resume for driver %s?\n", driver->name);
+ 	return 0;
+ }
+ 

commit 42245e65f356ed54fdf7a1f9a0095e0bc40f73a3
+Author: Alan Stern 
+Date:   Fri Dec 16 11:09:01 2005 -0800
+
+    [PATCH] UHCI: add missing memory barriers
+    
+    This patch (as617) adds a couple of memory barriers that Ben H. forgot in
+    his recent suspend/resume fix.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index ed550132db0b..79efaf7d86a3 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -717,6 +717,7 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
+ 	 * at the source, so we must turn off PIRQ.
+ 	 */
+ 	pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0);
++	mb();
+ 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ 	uhci->hc_inaccessible = 1;
+ 	hcd->poll_rh = 0;
+@@ -738,6 +739,7 @@ static int uhci_resume(struct usb_hcd *hcd)
+ 	 * really don't want to keep a stale HCD_FLAG_HW_ACCESSIBLE=0
+ 	 */
+ 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
++	mb();
+ 
+ 	if (uhci->rh_state == UHCI_RH_RESET)	/* Dead */
+ 		return 0;

commit 38d76df2f5483478dee803cb6e39da5e506a6643
+Author: Alan Stern 
+Date:   Fri Dec 9 11:34:45 2005 -0500
+
+    [SCSI] sd: Always do write-protect check
+    
+    Since nobody has offered an explanation for why the sd driver makes a
+    write-protect check only for devices with removable media, I'm submitting
+    this patch to get rid of the removable-media test.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+index 8613a1317712..d82795455efb 100644
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -1509,9 +1509,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
+ 	 */
+ 	if (sdkp->media_present) {
+ 		sd_read_capacity(sdkp, disk->disk_name, buffer);
+-		if (sdp->removable)
+-			sd_read_write_protect_flag(sdkp, disk->disk_name,
+-						   buffer);
++		sd_read_write_protect_flag(sdkp, disk->disk_name, buffer);
+ 		sd_read_cache_type(sdkp, disk->disk_name, buffer);
+ 	}
+ 		

commit 620948a01c71060a32611bc2f792f58a88cf28b1
+Author: Alan Stern 
+Date:   Mon Nov 28 15:22:55 2005 -0500
+
+    [PATCH] USB: documentation update
+    
+    This patch (as611) fixes a minor mistake and misspelling in the USB
+    documentation.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/usb/error-codes.txt b/Documentation/usb/error-codes.txt
+index 1e36f1661cd0..867f4c38f356 100644
+--- a/Documentation/usb/error-codes.txt
++++ b/Documentation/usb/error-codes.txt
+@@ -46,8 +46,9 @@ USB-specific:
+ 
+ -EMSGSIZE	(a) endpoint maxpacket size is zero; it is not usable
+ 		    in the current interface altsetting.
+-		(b) ISO packet is biger than endpoint maxpacket
+-		(c) requested data transfer size is invalid (negative)
++		(b) ISO packet is larger than the endpoint maxpacket.
++		(c) requested data transfer length is invalid: negative
++		    or too large for the host controller.
+ 
+ -ENOSPC		This request would overcommit the usb bandwidth reserved
+ 		for periodic transfers (interrupt, isochronous).

commit e0f39591cc178026607fcbbe9a53be435fe8285d
+Author: Alan Stern 
+Date:   Mon Nov 28 13:43:44 2005 -0800
+
+    [PATCH] Workaround for gcc 2.96 (undefined references)
+    
+      LD      .tmp_vmlinux1
+    mm/built-in.o(.text+0x100d6): In function `copy_page_range':
+    : undefined reference to `__pud_alloc'
+    mm/built-in.o(.text+0x1010b): In function `copy_page_range':
+    : undefined reference to `__pmd_alloc'
+    mm/built-in.o(.text+0x11ef4): In function `__handle_mm_fault':
+    : undefined reference to `__pud_alloc'
+    fs/built-in.o(.text+0xc930): In function `install_arg_page':
+    : undefined reference to `__pud_alloc'
+    make: *** [.tmp_vmlinux1] Error 1
+    
+    Those missing references in mm/memory.c arise from this code in
+    include/linux/mm.h, combined with the fact that __PGTABLE_PMD_FOLDED and
+    __PGTABLE_PUD_FOLDED are both set and __ARCH_HAS_4LEVEL_HACK is not:
+    
+    /*
+     * The following ifdef needed to get the 4level-fixup.h header to work.
+     * Remove it when 4level-fixup.h has been removed.
+     */
+    #if defined(CONFIG_MMU) && !defined(__ARCH_HAS_4LEVEL_HACK)
+    static inline pud_t *pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address)
+    {
+            return (unlikely(pgd_none(*pgd)) && __pud_alloc(mm, pgd, address))?
+                    NULL: pud_offset(pgd, address);
+    }
+    
+    static inline pmd_t *pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address)
+    {
+            return (unlikely(pud_none(*pud)) && __pmd_alloc(mm, pud, address))?
+                    NULL: pmd_offset(pud, address);
+    }
+    #endif /* CONFIG_MMU && !__ARCH_HAS_4LEVEL_HACK */
+    
+    With my configuration the pgd_none and pud_none routines are inlines
+    returning a constant 0.  Apparently the old compiler avoids generating
+    calls to __pud_alloc and __pmd_alloc but still lists them as undefined
+    references in the module's symbol table.
+    
+    I don't know which change caused this problem.  I think it was added
+    somewhere between 2.6.14 and 2.6.15-rc1, because I remember building
+    several 2.6.14-rc kernels without difficulty.  However I can't point to an
+    individual culprit.
+    
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/mm/memory.c b/mm/memory.c
+index b57fbc636058..9ab206b829a2 100644
+--- a/mm/memory.c
++++ b/mm/memory.c
+@@ -2160,6 +2160,12 @@ int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address)
+ 	spin_unlock(&mm->page_table_lock);
+ 	return 0;
+ }
++#else
++/* Workaround for gcc 2.96 */
++int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address)
++{
++	return 0;
++}
+ #endif /* __PAGETABLE_PUD_FOLDED */
+ 
+ #ifndef __PAGETABLE_PMD_FOLDED
+@@ -2188,6 +2194,12 @@ int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address)
+ 	spin_unlock(&mm->page_table_lock);
+ 	return 0;
+ }
++#else
++/* Workaround for gcc 2.96 */
++int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address)
++{
++	return 0;
++}
+ #endif /* __PAGETABLE_PMD_FOLDED */
+ 
+ int make_pages_present(unsigned long addr, unsigned long end)

commit 2b08c8d0468866f86da97f836c6ac14338cb81a9
+Author: Alan Stern 
+Date:   Wed Nov 23 15:43:50 2005 -0800
+
+    [PATCH] Small fixes to driver core
+    
+    This patch (as603) makes a few small fixes to the driver core:
+    
+    Change spin_lock_irq for a klist lock to spin_lock;
+    
+    Fix reference count leaks;
+    
+    Minor spelling and formatting changes.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by Patrick Mochel 
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/base/bus.c b/drivers/base/bus.c
+index 03204bfd17af..fa601b085eba 100644
+--- a/drivers/base/bus.c
++++ b/drivers/base/bus.c
+@@ -133,7 +133,7 @@ static struct kobj_type ktype_bus = {
+ decl_subsys(bus, &ktype_bus, NULL);
+ 
+ 
+-/* Manually detach a device from it's associated driver. */
++/* Manually detach a device from its associated driver. */
+ static int driver_helper(struct device *dev, void *data)
+ {
+ 	const char *name = data;
+@@ -151,14 +151,13 @@ static ssize_t driver_unbind(struct device_driver *drv,
+ 	int err = -ENODEV;
+ 
+ 	dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
+-	if ((dev) &&
+-	    (dev->driver == drv)) {
++	if (dev && dev->driver == drv) {
+ 		device_release_driver(dev);
+ 		err = count;
+ 	}
+-	if (err)
+-		return err;
+-	return count;
++	put_device(dev);
++	put_bus(bus);
++	return err;
+ }
+ static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind);
+ 
+@@ -175,16 +174,14 @@ static ssize_t driver_bind(struct device_driver *drv,
+ 	int err = -ENODEV;
+ 
+ 	dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
+-	if ((dev) &&
+-	    (dev->driver == NULL)) {
++	if (dev && dev->driver == NULL) {
+ 		down(&dev->sem);
+ 		err = driver_probe_device(drv, dev);
+ 		up(&dev->sem);
+-		put_device(dev);
+ 	}
+-	if (err)
+-		return err;
+-	return count;
++	put_device(dev);
++	put_bus(bus);
++	return err;
+ }
+ static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind);
+ 
+diff --git a/drivers/base/dd.c b/drivers/base/dd.c
+index 3565e9795301..3b419c9a1e7e 100644
+--- a/drivers/base/dd.c
++++ b/drivers/base/dd.c
+@@ -62,7 +62,6 @@ void device_bind_driver(struct device * dev)
+  *	because we don't know the format of the ID structures, nor what
+  *	is to be considered a match and what is not.
+  *
+- *
+  *	This function returns 1 if a match is found, an error if one
+  *	occurs (that is not -ENODEV or -ENXIO), and 0 otherwise.
+  *
+@@ -158,7 +157,6 @@ static int __driver_attach(struct device * dev, void * data)
+ 		driver_probe_device(drv, dev);
+ 	up(&dev->sem);
+ 
+-
+ 	return 0;
+ }
+ 
+@@ -225,15 +223,15 @@ void driver_detach(struct device_driver * drv)
+ 	struct device * dev;
+ 
+ 	for (;;) {
+-		spin_lock_irq(&drv->klist_devices.k_lock);
++		spin_lock(&drv->klist_devices.k_lock);
+ 		if (list_empty(&drv->klist_devices.k_list)) {
+-			spin_unlock_irq(&drv->klist_devices.k_lock);
++			spin_unlock(&drv->klist_devices.k_lock);
+ 			break;
+ 		}
+ 		dev = list_entry(drv->klist_devices.k_list.prev,
+ 				struct device, knode_driver.n_node);
+ 		get_device(dev);
+-		spin_unlock_irq(&drv->klist_devices.k_lock);
++		spin_unlock(&drv->klist_devices.k_lock);
+ 
+ 		down(&dev->sem);
+ 		if (dev->driver == drv)

commit 2ef8919830a262f10fb5e4a685e95f71a64bce6c
+Author: Alan Stern 
+Date:   Tue Nov 8 15:51:55 2005 -0500
+
+    [SCSI] Fix refcount leak in scsi_report_lun_scan
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+index 7eb3a2d40dc5..27bcc8fb8cbc 100644
+--- a/drivers/scsi/scsi_scan.c
++++ b/drivers/scsi/scsi_scan.c
+@@ -1074,6 +1074,7 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
+ 	struct scsi_sense_hdr sshdr;
+ 	struct scsi_device *sdev;
+ 	struct Scsi_Host *shost = dev_to_shost(&starget->dev);
++	int ret = 0;
+ 
+ 	/*
+ 	 * Only support SCSI-3 and up devices if BLIST_NOREPORTLUN is not set.
+@@ -1169,8 +1170,8 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
+ 		/*
+ 		 * The device probably does not support a REPORT LUN command
+ 		 */
+-		kfree(lun_data);
+-		return 1;
++		ret = 1;
++		goto out_err;
+ 	}
+ 
+ 	/*
+@@ -1238,6 +1239,7 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
+ 		}
+ 	}
+ 
++ out_err:
+ 	kfree(lun_data);
+  out:
+ 	scsi_device_put(sdev);
+@@ -1246,7 +1248,7 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
+ 		 * the sdev we used didn't appear in the report luns scan
+ 		 */
+ 		scsi_destroy_sdev(sdev);
+-	return 0;
++	return ret;
+ }
+ 
+ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,

commit 39b7f1e25a412b0ef31e516cfc2fa4f40235f263
+Author: Alan Stern 
+Date:   Fri Nov 4 14:44:41 2005 -0500
+
+    [SCSI] sd: Fix refcounting
+    
+    Currently the driver takes a reference only for requests coming by way
+    of the gendisk, not for requests coming by way of the struct device or
+    struct scsi_device.  Such requests can arrive in the rescan, flush,
+    and shutdown pathways.
+    
+    The patch also makes the scsi_disk keep a reference to the underlying
+    scsi_device, and it erases the scsi_device's pointer to the scsi_disk
+    when the scsi_device is removed (since the pointer should no longer be
+    used).
+    
+    This resolves Bugzilla entry #5237.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+index 9de8e186cb69..bb5b242ac6b4 100644
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -177,24 +177,38 @@ static inline struct scsi_disk *scsi_disk(struct gendisk *disk)
+ 	return container_of(disk->private_data, struct scsi_disk, driver);
+ }
+ 
+-static struct scsi_disk *scsi_disk_get(struct gendisk *disk)
++static struct scsi_disk *__scsi_disk_get(struct gendisk *disk)
+ {
+ 	struct scsi_disk *sdkp = NULL;
+ 
++	if (disk->private_data) {
++		sdkp = scsi_disk(disk);
++		if (scsi_device_get(sdkp->device) == 0)
++			kref_get(&sdkp->kref);
++		else
++			sdkp = NULL;
++	}
++	return sdkp;
++}
++
++static struct scsi_disk *scsi_disk_get(struct gendisk *disk)
++{
++	struct scsi_disk *sdkp;
++
+ 	down(&sd_ref_sem);
+-	if (disk->private_data == NULL)
+-		goto out;
+-	sdkp = scsi_disk(disk);
+-	kref_get(&sdkp->kref);
+-	if (scsi_device_get(sdkp->device))
+-		goto out_put;
++	sdkp = __scsi_disk_get(disk);
+ 	up(&sd_ref_sem);
+ 	return sdkp;
++}
+ 
+- out_put:
+-	kref_put(&sdkp->kref, scsi_disk_release);
+-	sdkp = NULL;
+- out:
++static struct scsi_disk *scsi_disk_get_from_dev(struct device *dev)
++{
++	struct scsi_disk *sdkp;
++
++	down(&sd_ref_sem);
++	sdkp = dev_get_drvdata(dev);
++	if (sdkp)
++		sdkp = __scsi_disk_get(sdkp->disk);
+ 	up(&sd_ref_sem);
+ 	return sdkp;
+ }
+@@ -716,16 +730,17 @@ static int sd_sync_cache(struct scsi_device *sdp)
+ 
+ static int sd_issue_flush(struct device *dev, sector_t *error_sector)
+ {
++	int ret = 0;
+ 	struct scsi_device *sdp = to_scsi_device(dev);
+-	struct scsi_disk *sdkp = dev_get_drvdata(dev);
++	struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
+ 
+ 	if (!sdkp)
+                return -ENODEV;
+ 
+-	if (!sdkp->WCE)
+-		return 0;
+-
+-	return sd_sync_cache(sdp);
++	if (sdkp->WCE)
++		ret = sd_sync_cache(sdp);
++	scsi_disk_put(sdkp);
++	return ret;
+ }
+ 
+ static void sd_end_flush(request_queue_t *q, struct request *flush_rq)
+@@ -754,23 +769,30 @@ static void sd_end_flush(request_queue_t *q, struct request *flush_rq)
+ static int sd_prepare_flush(request_queue_t *q, struct request *rq)
+ {
+ 	struct scsi_device *sdev = q->queuedata;
+-	struct scsi_disk *sdkp = dev_get_drvdata(&sdev->sdev_gendev);
+-
+-	if (sdkp->WCE) {
+-		memset(rq->cmd, 0, sizeof(rq->cmd));
+-		rq->flags |= REQ_BLOCK_PC | REQ_SOFTBARRIER;
+-		rq->timeout = SD_TIMEOUT;
+-		rq->cmd[0] = SYNCHRONIZE_CACHE;
+-		return 1;
++	struct scsi_disk *sdkp = scsi_disk_get_from_dev(&sdev->sdev_gendev);
++	int ret = 0;
++
++	if (sdkp) {
++		if (sdkp->WCE) {
++			memset(rq->cmd, 0, sizeof(rq->cmd));
++			rq->flags |= REQ_BLOCK_PC | REQ_SOFTBARRIER;
++			rq->timeout = SD_TIMEOUT;
++			rq->cmd[0] = SYNCHRONIZE_CACHE;
++			ret = 1;
++		}
++		scsi_disk_put(sdkp);
+ 	}
+-
+-	return 0;
++	return ret;
+ }
+ 
+ static void sd_rescan(struct device *dev)
+ {
+-	struct scsi_disk *sdkp = dev_get_drvdata(dev);
+-	sd_revalidate_disk(sdkp->disk);
++	struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
++
++	if (sdkp) {
++		sd_revalidate_disk(sdkp->disk);
++		scsi_disk_put(sdkp);
++	}
+ }
+ 
+ 
+@@ -1561,6 +1583,7 @@ static int sd_probe(struct device *dev)
+ 	if (error)
+ 		goto out_put;
+ 
++	get_device(&sdp->sdev_gendev);
+ 	sdkp->device = sdp;
+ 	sdkp->driver = &sd_template;
+ 	sdkp->disk = gd;
+@@ -1637,7 +1660,9 @@ static int sd_remove(struct device *dev)
+ 
+ 	del_gendisk(sdkp->disk);
+ 	sd_shutdown(dev);
++
+ 	down(&sd_ref_sem);
++	dev_set_drvdata(dev, NULL);
+ 	kref_put(&sdkp->kref, scsi_disk_release);
+ 	up(&sd_ref_sem);
+ 
+@@ -1663,8 +1688,8 @@ static void scsi_disk_release(struct kref *kref)
+ 	spin_unlock(&sd_index_lock);
+ 
+ 	disk->private_data = NULL;
+-
+ 	put_disk(disk);
++	put_device(&sdkp->device->sdev_gendev);
+ 
+ 	kfree(sdkp);
+ }
+@@ -1677,18 +1702,18 @@ static void scsi_disk_release(struct kref *kref)
+ static void sd_shutdown(struct device *dev)
+ {
+ 	struct scsi_device *sdp = to_scsi_device(dev);
+-	struct scsi_disk *sdkp = dev_get_drvdata(dev);
++	struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
+ 
+ 	if (!sdkp)
+ 		return;         /* this can happen */
+ 
+-	if (!sdkp->WCE)
+-		return;
+-
+-	printk(KERN_NOTICE "Synchronizing SCSI cache for disk %s: \n",
+-			sdkp->disk->disk_name);
+-	sd_sync_cache(sdp);
+-}	
++	if (sdkp->WCE) {
++		printk(KERN_NOTICE "Synchronizing SCSI cache for disk %s: \n",
++				sdkp->disk->disk_name);
++		sd_sync_cache(sdp);
++	}
++	scsi_disk_put(sdkp);
++}
+ 
+ /**
+  *	init_sd - entry point for this driver (both when built in or when

commit 61e1a9ea4b425eb8c3b4965c35fe953bd881728f
+Author: Alan Stern 
+Date:   Sun Oct 30 15:01:40 2005 -0800
+
+    [PATCH] Add kthread_stop_sem()
+    
+    Enhance the kthread API by adding kthread_stop_sem, for use in stopping
+    threads that spend their idle time waiting on a semaphore.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/kthread.h b/include/linux/kthread.h
+index 3fa786448db3..ebdd41fd1082 100644
+--- a/include/linux/kthread.h
++++ b/include/linux/kthread.h
+@@ -69,6 +69,18 @@ void kthread_bind(struct task_struct *k, unsigned int cpu);
+  * was never called. */
+ int kthread_stop(struct task_struct *k);
+ 
++/**
++ * kthread_stop_sem: stop a thread created by kthread_create().
++ * @k: thread created by kthread_create().
++ * @s: semaphore that @k waits on while idle.
++ *
++ * Does essentially the same thing as kthread_stop() above, but wakes
++ * @k by calling up(@s).
++ *
++ * Returns the result of threadfn(), or -EINTR if wake_up_process()
++ * was never called. */
++int kthread_stop_sem(struct task_struct *k, struct semaphore *s);
++
+ /**
+  * kthread_should_stop: should this kthread return now?
+  *
+diff --git a/kernel/kthread.c b/kernel/kthread.c
+index f50f174e92da..e75950a1092c 100644
+--- a/kernel/kthread.c
++++ b/kernel/kthread.c
+@@ -164,6 +164,12 @@ void kthread_bind(struct task_struct *k, unsigned int cpu)
+ EXPORT_SYMBOL(kthread_bind);
+ 
+ int kthread_stop(struct task_struct *k)
++{
++	return kthread_stop_sem(k, NULL);
++}
++EXPORT_SYMBOL(kthread_stop);
++
++int kthread_stop_sem(struct task_struct *k, struct semaphore *s)
+ {
+ 	int ret;
+ 
+@@ -178,7 +184,10 @@ int kthread_stop(struct task_struct *k)
+ 
+ 	/* Now set kthread_should_stop() to true, and wake it up. */
+ 	kthread_stop_info.k = k;
+-	wake_up_process(k);
++	if (s)
++		up(s);
++	else
++		wake_up_process(k);
+ 	put_task_struct(k);
+ 
+ 	/* Once it dies, reset stop ptr, gather result and we're done. */
+@@ -189,7 +198,7 @@ int kthread_stop(struct task_struct *k)
+ 
+ 	return ret;
+ }
+-EXPORT_SYMBOL(kthread_stop);
++EXPORT_SYMBOL(kthread_stop_sem);
+ 
+ static __init int helper_init(void)
+ {

commit 4f62efe67f077db17dad03a1d4c9665000a3eb45
+Author: Alan Stern 
+Date:   Mon Oct 24 16:24:14 2005 -0400
+
+    [PATCH] usbcore: Fix handling of sysfs strings and other attributes
+    
+    This patch (as592) makes a few small improvements to the way device
+    strings are handled, and it fixes some bugs in a couple of other sysfs
+    attribute routines.  (Look at show_configuration_string() to see what I
+    mean.)
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
+index 63f374e62db2..993019500cc3 100644
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -112,8 +112,12 @@ void usb_release_interface_cache(struct kref *ref)
+ 	struct usb_interface_cache *intfc = ref_to_usb_interface_cache(ref);
+ 	int j;
+ 
+-	for (j = 0; j < intfc->num_altsetting; j++)
+-		kfree(intfc->altsetting[j].endpoint);
++	for (j = 0; j < intfc->num_altsetting; j++) {
++		struct usb_host_interface *alt = &intfc->altsetting[j];
++
++		kfree(alt->endpoint);
++		kfree(alt->string);
++	}
+ 	kfree(intfc);
+ }
+ 
+@@ -420,8 +424,6 @@ void usb_destroy_configuration(struct usb_device *dev)
+ 		struct usb_host_config *cf = &dev->config[c];
+ 
+ 		kfree(cf->string);
+-		cf->string = NULL;
+-
+ 		for (i = 0; i < cf->desc.bNumInterfaces; i++) {
+ 			if (cf->intf_cache[i])
+ 				kref_put(&cf->intf_cache[i]->ref, 
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 8ba5854e5387..1bacb374b007 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1204,21 +1204,6 @@ static inline void show_string(struct usb_device *udev, char *id, char *string)
+ {}
+ #endif
+ 
+-static void get_string(struct usb_device *udev, char **string, int index)
+-{
+-	char *buf;
+-
+-	if (!index)
+-		return;
+-	buf = kmalloc(256, GFP_KERNEL);
+-	if (!buf)
+-		return;
+-	if (usb_string(udev, index, buf, 256) > 0)
+-		*string = buf;
+-	else
+-		kfree(buf);
+-}
+-
+ 
+ #ifdef	CONFIG_USB_OTG
+ #include "otg_whitelist.h"
+@@ -1257,9 +1242,10 @@ int usb_new_device(struct usb_device *udev)
+ 	}
+ 
+ 	/* read the standard strings and cache them if present */
+-	get_string(udev, &udev->product, udev->descriptor.iProduct);
+-	get_string(udev, &udev->manufacturer, udev->descriptor.iManufacturer);
+-	get_string(udev, &udev->serial, udev->descriptor.iSerialNumber);
++	udev->product = usb_cache_string(udev, udev->descriptor.iProduct);
++	udev->manufacturer = usb_cache_string(udev,
++			udev->descriptor.iManufacturer);
++	udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber);
+ 
+ 	/* Tell the world! */
+ 	dev_dbg(&udev->dev, "new device strings: Mfr=%d, Product=%d, "
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 3519f317898e..644a3d4f12aa 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -787,6 +787,31 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
+ 	return err;
+ }
+ 
++/**
++ * usb_cache_string - read a string descriptor and cache it for later use
++ * @udev: the device whose string descriptor is being read
++ * @index: the descriptor index
++ *
++ * Returns a pointer to a kmalloc'ed buffer containing the descriptor string,
++ * or NULL if the index is 0 or the string could not be read.
++ */
++char *usb_cache_string(struct usb_device *udev, int index)
++{
++	char *buf;
++	char *smallbuf = NULL;
++	int len;
++
++	if (index > 0 && (buf = kmalloc(256, GFP_KERNEL)) != NULL) {
++		if ((len = usb_string(udev, index, buf, 256)) > 0) {
++			if ((smallbuf = kmalloc(++len, GFP_KERNEL)) == NULL)
++				return buf;
++			memcpy(smallbuf, buf, len);
++		}
++		kfree(buf);
++	}
++	return smallbuf;
++}
++
+ /*
+  * usb_get_device_descriptor - (re)reads the device descriptor (usbcore)
+  * @dev: the device whose device descriptor is being updated
+@@ -1008,8 +1033,6 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
+ 			dev_dbg (&dev->dev, "unregistering interface %s\n",
+ 				interface->dev.bus_id);
+ 			usb_remove_sysfs_intf_files(interface);
+-			kfree(interface->cur_altsetting->string);
+-			interface->cur_altsetting->string = NULL;
+ 			device_del (&interface->dev);
+ 		}
+ 
+@@ -1422,12 +1445,9 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 		}
+ 		kfree(new_interfaces);
+ 
+-		if ((cp->desc.iConfiguration) &&
+-		    (cp->string == NULL)) {
+-			cp->string = kmalloc(256, GFP_KERNEL);
+-			if (cp->string)
+-				usb_string(dev, cp->desc.iConfiguration, cp->string, 256);
+-		}
++		if (cp->string == NULL)
++			cp->string = usb_cache_string(dev,
++					cp->desc.iConfiguration);
+ 
+ 		/* Now that all the interfaces are set up, register them
+ 		 * to trigger binding of drivers to interfaces.  probe()
+@@ -1437,13 +1457,12 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 		 */
+ 		for (i = 0; i < nintf; ++i) {
+ 			struct usb_interface *intf = cp->interface[i];
+-			struct usb_interface_descriptor *desc;
++			struct usb_host_interface *alt = intf->cur_altsetting;
+ 
+-			desc = &intf->altsetting [0].desc;
+ 			dev_dbg (&dev->dev,
+ 				"adding %s (config #%d, interface %d)\n",
+ 				intf->dev.bus_id, configuration,
+-				desc->bInterfaceNumber);
++				alt->desc.bInterfaceNumber);
+ 			ret = device_add (&intf->dev);
+ 			if (ret != 0) {
+ 				dev_err(&dev->dev,
+@@ -1452,13 +1471,6 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 					ret);
+ 				continue;
+ 			}
+-			if ((intf->cur_altsetting->desc.iInterface) &&
+-			    (intf->cur_altsetting->string == NULL)) {
+-				intf->cur_altsetting->string = kmalloc(256, GFP_KERNEL);
+-				if (intf->cur_altsetting->string)
+-					usb_string(dev, intf->cur_altsetting->desc.iInterface,
+-						   intf->cur_altsetting->string, 256);
+-			}
+ 			usb_create_sysfs_intf_files (intf);
+ 		}
+ 	}
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 4cca77cf0c48..edd83e014452 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -249,18 +249,12 @@ static ssize_t show_configuration_string(struct device *dev,
+ {
+ 	struct usb_device *udev;
+ 	struct usb_host_config *actconfig;
+-	int len;
+ 
+ 	udev = to_usb_device (dev);
+ 	actconfig = udev->actconfig;
+ 	if ((!actconfig) || (!actconfig->string))
+ 		return 0;
+-	len = sprintf(buf, actconfig->string, PAGE_SIZE);
+-	if (len < 0)
+-		return 0;
+-	buf[len] = '\n';
+-	buf[len+1] = 0;
+-	return len+1;
++	return sprintf(buf, "%s\n", actconfig->string);
+ }
+ static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL);
+ 
+@@ -291,15 +285,9 @@ static ssize_t  show_##name(struct device *dev,				\
+ 		struct device_attribute *attr, char *buf)		\
+ {									\
+ 	struct usb_device *udev;					\
+-	int len;							\
+ 									\
+ 	udev = to_usb_device (dev);					\
+-	len = snprintf(buf, 256, "%s", udev->name);			\
+-	if (len < 0)							\
+-		return 0;						\
+-	buf[len] = '\n';						\
+-	buf[len+1] = 0;							\
+-	return len+1;							\
++	return sprintf(buf, "%s\n", udev->name);			\
+ }									\
+ static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
+ 
+@@ -449,11 +437,11 @@ void usb_remove_sysfs_dev_files (struct usb_device *udev)
+ 	usb_remove_ep_files(&udev->ep0);
+ 	sysfs_remove_group(&dev->kobj, &dev_attr_grp);
+ 
+-	if (udev->descriptor.iManufacturer)
++	if (udev->manufacturer)
+ 		device_remove_file(dev, &dev_attr_manufacturer);
+-	if (udev->descriptor.iProduct)
++	if (udev->product)
+ 		device_remove_file(dev, &dev_attr_product);
+-	if (udev->descriptor.iSerialNumber)
++	if (udev->serial)
+ 		device_remove_file(dev, &dev_attr_serial);
+ 	device_remove_file (dev, &dev_attr_configuration);
+ }
+@@ -535,7 +523,8 @@ static struct attribute_group intf_attr_grp = {
+ 	.attrs = intf_attrs,
+ };
+ 
+-static inline void usb_create_intf_ep_files(struct usb_interface *intf)
++static inline void usb_create_intf_ep_files(struct usb_interface *intf,
++		struct usb_device *udev)
+ {
+ 	struct usb_host_interface *iface_desc;
+ 	int i;
+@@ -543,7 +532,7 @@ static inline void usb_create_intf_ep_files(struct usb_interface *intf)
+ 	iface_desc = intf->cur_altsetting;
+ 	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i)
+ 		usb_create_ep_files(&intf->dev.kobj, &iface_desc->endpoint[i],
+-				interface_to_usbdev(intf));
++				udev);
+ }
+ 
+ static inline void usb_remove_intf_ep_files(struct usb_interface *intf)
+@@ -558,11 +547,16 @@ static inline void usb_remove_intf_ep_files(struct usb_interface *intf)
+ 
+ void usb_create_sysfs_intf_files (struct usb_interface *intf)
+ {
++	struct usb_device *udev = interface_to_usbdev(intf);
++	struct usb_host_interface *alt = intf->cur_altsetting;
++
+ 	sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
+ 
+-	if (intf->cur_altsetting->string)
++	if (alt->string == NULL)
++		alt->string = usb_cache_string(udev, alt->desc.iInterface);
++	if (alt->string)
+ 		device_create_file(&intf->dev, &dev_attr_interface);
+-	usb_create_intf_ep_files(intf);
++	usb_create_intf_ep_files(intf, udev);
+ }
+ 
+ void usb_remove_sysfs_intf_files (struct usb_interface *intf)
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 888dbe443695..1c4a68499dce 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -13,6 +13,7 @@ extern void usb_disable_device (struct usb_device *dev, int skip_ep0);
+ 
+ extern int usb_get_device_descriptor(struct usb_device *dev,
+ 		unsigned int size);
++extern char *usb_cache_string(struct usb_device *udev, int index);
+ extern int usb_set_configuration(struct usb_device *dev, int configuration);
+ 
+ extern void usb_lock_all_devices(void);
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index c500d6b5a16d..748d04385256 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -231,7 +231,7 @@ struct usb_interface_cache {
+ struct usb_host_config {
+ 	struct usb_config_descriptor	desc;
+ 
+-	char *string;
++	char *string;		/* iConfiguration string, if present */
+ 	/* the interfaces associated with this configuration,
+ 	 * stored in no particular order */
+ 	struct usb_interface *interface[USB_MAXINTERFACES];
+@@ -351,9 +351,11 @@ struct usb_device {
+ 	int have_langid;		/* whether string_langid is valid */
+ 	int string_langid;		/* language ID for strings */
+ 
+-	char *product;
+-	char *manufacturer;
+-	char *serial;			/* static strings from the device */
++	/* static strings from the device */
++	char *product;			/* iProduct string, if present */
++	char *manufacturer;		/* iManufacturer string, if present */
++	char *serial;			/* iSerialNumber string, if present */
++
+ 	struct list_head filelist;
+ 	struct class_device *class_dev;
+ 	struct dentry *usbfs_dentry;	/* usbfs dentry entry for the device */

commit 16f16d117c1eb99451e4c73c87546eef05c66790
+Author: Alan Stern 
+Date:   Mon Oct 24 15:41:19 2005 -0400
+
+    [PATCH] USB: Fix maxpacket length for ep0 on root hubs
+    
+    This patch (as591) fixes a rather innocuous bug that has been around for
+    quite a long time: Virtual root hubs should have a maxpacket length of
+    64 for endpoint 0.  I didn't realize it was wrong until I started
+    looking through the endpoint attribute files.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 61ef9943757e..6c7ca5b08cd6 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -130,7 +130,7 @@ static const u8 usb2_rh_dev_descriptor [18] = {
+ 	0x09,	    /*  __u8  bDeviceClass; HUB_CLASSCODE */
+ 	0x00,	    /*  __u8  bDeviceSubClass; */
+ 	0x01,       /*  __u8  bDeviceProtocol; [ usb 2.0 single TT ]*/
+-	0x08,       /*  __u8  bMaxPacketSize0; 8 Bytes */
++	0x40,       /*  __u8  bMaxPacketSize0; 64 Bytes */
+ 
+ 	0x00, 0x00, /*  __le16 idVendor; */
+  	0x00, 0x00, /*  __le16 idProduct; */
+@@ -153,7 +153,7 @@ static const u8 usb11_rh_dev_descriptor [18] = {
+ 	0x09,	    /*  __u8  bDeviceClass; HUB_CLASSCODE */
+ 	0x00,	    /*  __u8  bDeviceSubClass; */
+ 	0x00,       /*  __u8  bDeviceProtocol; [ low/full speeds only ] */
+-	0x08,       /*  __u8  bMaxPacketSize0; 8 Bytes */
++	0x40,       /*  __u8  bMaxPacketSize0; 64 Bytes */
+ 
+ 	0x00, 0x00, /*  __le16 idVendor; */
+  	0x00, 0x00, /*  __le16 idProduct; */

commit 0a1ef3b5a765a6f20e7b8caf295aad3276243966
+Author: Alan Stern 
+Date:   Mon Oct 24 15:38:24 2005 -0400
+
+    [PATCH] usbcore: Use kzalloc instead of kmalloc/memset
+    
+    This patch (as590) fixes up all the remaining places where usbcore can
+    use kzalloc rather than kmalloc/memset.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
+index 99595e07b653..63f374e62db2 100644
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -188,10 +188,9 @@ static int usb_parse_interface(struct device *ddev, int cfgno,
+ 	}
+ 
+ 	len = sizeof(struct usb_host_endpoint) * num_ep;
+-	alt->endpoint = kmalloc(len, GFP_KERNEL);
++	alt->endpoint = kzalloc(len, GFP_KERNEL);
+ 	if (!alt->endpoint)
+ 		return -ENOMEM;
+-	memset(alt->endpoint, 0, len);
+ 
+ 	/* Parse all the endpoint descriptors */
+ 	n = 0;
+@@ -353,10 +352,9 @@ static int usb_parse_configuration(struct device *ddev, int cfgidx,
+ 		}
+ 
+ 		len = sizeof(*intfc) + sizeof(struct usb_host_interface) * j;
+-		config->intf_cache[i] = intfc = kmalloc(len, GFP_KERNEL);
++		config->intf_cache[i] = intfc = kzalloc(len, GFP_KERNEL);
+ 		if (!intfc)
+ 			return -ENOMEM;
+-		memset(intfc, 0, len);
+ 		kref_init(&intfc->ref);
+ 	}
+ 
+@@ -459,16 +457,14 @@ int usb_get_configuration(struct usb_device *dev)
+ 	}
+ 
+ 	length = ncfg * sizeof(struct usb_host_config);
+-	dev->config = kmalloc(length, GFP_KERNEL);
++	dev->config = kzalloc(length, GFP_KERNEL);
+ 	if (!dev->config)
+ 		goto err2;
+-	memset(dev->config, 0, length);
+ 
+ 	length = ncfg * sizeof(char *);
+-	dev->rawdescriptors = kmalloc(length, GFP_KERNEL);
++	dev->rawdescriptors = kzalloc(length, GFP_KERNEL);
+ 	if (!dev->rawdescriptors)
+ 		goto err2;
+-	memset(dev->rawdescriptors, 0, length);
+ 
+ 	buffer = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL);
+ 	if (!buffer)
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index ffb2e242b100..942cd437dc48 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -210,10 +210,10 @@ static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, l
+ static struct async *alloc_async(unsigned int numisoframes)
+ {
+         unsigned int assize = sizeof(struct async) + numisoframes * sizeof(struct usb_iso_packet_descriptor);
+-        struct async *as = kmalloc(assize, GFP_KERNEL);
++        struct async *as = kzalloc(assize, GFP_KERNEL);
++
+         if (!as)
+                 return NULL;
+-        memset(as, 0, assize);
+ 	as->urb = usb_alloc_urb(numisoframes, GFP_KERNEL);
+ 	if (!as->urb) {
+ 		kfree(as);
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index e8f2b8d8f14d..61ef9943757e 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -744,10 +744,9 @@ struct usb_bus *usb_alloc_bus (struct usb_operations *op)
+ {
+ 	struct usb_bus *bus;
+ 
+-	bus = kmalloc (sizeof *bus, GFP_KERNEL);
++	bus = kzalloc (sizeof *bus, GFP_KERNEL);
+ 	if (!bus)
+ 		return NULL;
+-	memset(bus, 0, sizeof(struct usb_bus));
+ 	usb_bus_init (bus);
+ 	bus->op = op;
+ 	return bus;
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 6a2ebd89916f..8ba5854e5387 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -865,14 +865,12 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
+ 	/* We found a hub */
+ 	dev_info (&intf->dev, "USB hub found\n");
+ 
+-	hub = kmalloc(sizeof(*hub), GFP_KERNEL);
++	hub = kzalloc(sizeof(*hub), GFP_KERNEL);
+ 	if (!hub) {
+ 		dev_dbg (&intf->dev, "couldn't kmalloc hub struct\n");
+ 		return -ENOMEM;
+ 	}
+ 
+-	memset(hub, 0, sizeof(*hub));
+-
+ 	INIT_LIST_HEAD(&hub->event_list);
+ 	hub->intfdev = &intf->dev;
+ 	hub->hdev = hdev;
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 5ad0d5e28119..3519f317898e 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1350,7 +1350,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 		}
+ 
+ 		for (; n < nintf; ++n) {
+-			new_interfaces[n] = kmalloc(
++			new_interfaces[n] = kzalloc(
+ 					sizeof(struct usb_interface),
+ 					GFP_KERNEL);
+ 			if (!new_interfaces[n]) {
+@@ -1391,7 +1391,6 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 			struct usb_host_interface *alt;
+ 
+ 			cp->interface[i] = intf = new_interfaces[i];
+-			memset(intf, 0, sizeof(*intf));
+ 			intfc = cp->intf_cache[i];
+ 			intf->altsetting = intfc->altsetting;
+ 			intf->num_altsetting = intfc->num_altsetting;
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 4eca4904938f..0eefff7bcb3c 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -704,12 +704,10 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
+ {
+ 	struct usb_device *dev;
+ 
+-	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
++	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ 	if (!dev)
+ 		return NULL;
+ 
+-	memset(dev, 0, sizeof(*dev));
+-
+ 	bus = usb_bus_get(bus);
+ 	if (!bus) {
+ 		kfree(dev);

commit b724ae77969fd832be71419dca74bece9af287ff
+Author: Alan Stern 
+Date:   Mon Oct 24 15:36:00 2005 -0400
+
+    [PATCH] usbcore: Wrap lines before column 80
+    
+    I can't stand text lines that wrap-around in my 80-column windows.  This
+    patch (as589) makes cosmetic changes to a couple of source files.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index f18317fb49ee..4cca77cf0c48 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -221,7 +221,8 @@ static void usb_remove_ep_files(struct usb_host_endpoint *endpoint)
+ 
+ /* Active configuration fields */
+ #define usb_actconfig_show(field, multiplier, format_string)		\
+-static ssize_t  show_##field (struct device *dev, struct device_attribute *attr, char *buf)		\
++static ssize_t  show_##field (struct device *dev,			\
++		struct device_attribute *attr, char *buf)		\
+ {									\
+ 	struct usb_device *udev;					\
+ 	struct usb_host_config *actconfig;				\
+@@ -243,7 +244,8 @@ usb_actconfig_attr (bNumInterfaces, 1, "%2d\n")
+ usb_actconfig_attr (bmAttributes, 1, "%2x\n")
+ usb_actconfig_attr (bMaxPower, 2, "%3dmA\n")
+ 
+-static ssize_t show_configuration_string(struct device *dev, struct device_attribute *attr, char *buf)
++static ssize_t show_configuration_string(struct device *dev,
++		struct device_attribute *attr, char *buf)
+ {
+ 	struct usb_device *udev;
+ 	struct usb_host_config *actconfig;
+@@ -266,7 +268,8 @@ static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL);
+ usb_actconfig_show(bConfigurationValue, 1, "%u\n");
+ 
+ static ssize_t
+-set_bConfigurationValue (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++set_bConfigurationValue (struct device *dev, struct device_attribute *attr,
++		const char *buf, size_t count)
+ {
+ 	struct usb_device	*udev = udev = to_usb_device (dev);
+ 	int			config, value;
+@@ -284,7 +287,8 @@ static DEVICE_ATTR(bConfigurationValue, S_IRUGO | S_IWUSR,
+ 
+ /* String fields */
+ #define usb_string_attr(name)						\
+-static ssize_t  show_##name(struct device *dev, struct device_attribute *attr, char *buf)		\
++static ssize_t  show_##name(struct device *dev,				\
++		struct device_attribute *attr, char *buf)		\
+ {									\
+ 	struct usb_device *udev;					\
+ 	int len;							\
+@@ -364,7 +368,8 @@ static DEVICE_ATTR(maxchild, S_IRUGO, show_maxchild, NULL);
+ /* Descriptor fields */
+ #define usb_descriptor_attr_le16(field, format_string)			\
+ static ssize_t								\
+-show_##field (struct device *dev, struct device_attribute *attr, char *buf)				\
++show_##field (struct device *dev, struct device_attribute *attr,	\
++		char *buf)						\
+ {									\
+ 	struct usb_device *udev;					\
+ 									\
+@@ -380,7 +385,8 @@ usb_descriptor_attr_le16(bcdDevice, "%04x\n")
+ 
+ #define usb_descriptor_attr(field, format_string)			\
+ static ssize_t								\
+-show_##field (struct device *dev, struct device_attribute *attr, char *buf)				\
++show_##field (struct device *dev, struct device_attribute *attr,	\
++		char *buf)						\
+ {									\
+ 	struct usb_device *udev;					\
+ 									\
+@@ -455,11 +461,13 @@ void usb_remove_sysfs_dev_files (struct usb_device *udev)
+ /* Interface fields */
+ #define usb_intf_attr(field, format_string)				\
+ static ssize_t								\
+-show_##field (struct device *dev, struct device_attribute *attr, char *buf)				\
++show_##field (struct device *dev, struct device_attribute *attr,	\
++		char *buf)						\
+ {									\
+ 	struct usb_interface *intf = to_usb_interface (dev);		\
+ 									\
+-	return sprintf (buf, format_string, intf->cur_altsetting->desc.field); \
++	return sprintf (buf, format_string,				\
++			intf->cur_altsetting->desc.field); 		\
+ }									\
+ static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
+ 
+@@ -470,7 +478,8 @@ usb_intf_attr (bInterfaceClass, "%02x\n")
+ usb_intf_attr (bInterfaceSubClass, "%02x\n")
+ usb_intf_attr (bInterfaceProtocol, "%02x\n")
+ 
+-static ssize_t show_interface_string(struct device *dev, struct device_attribute *attr, char *buf)
++static ssize_t show_interface_string(struct device *dev,
++		struct device_attribute *attr, char *buf)
+ {
+ 	struct usb_interface *intf;
+ 	struct usb_device *udev;
+@@ -487,7 +496,8 @@ static ssize_t show_interface_string(struct device *dev, struct device_attribute
+ }
+ static DEVICE_ATTR(interface, S_IRUGO, show_interface_string, NULL);
+ 
+-static ssize_t show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
++static ssize_t show_modalias(struct device *dev,
++		struct device_attribute *attr, char *buf)
+ {
+ 	struct usb_interface *intf;
+ 	struct usb_device *udev;
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 465ff4585ca5..c500d6b5a16d 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -137,7 +137,8 @@ struct usb_interface {
+ 					 * active alternate setting */
+ 	unsigned num_altsetting;	/* number of alternate settings */
+ 
+-	int minor;			/* minor number this interface is bound to */
++	int minor;			/* minor number this interface is
++					 * bound to */
+ 	enum usb_interface_condition condition;		/* state of binding */
+ 	struct device dev;		/* interface specific device info */
+ 	struct class_device *class_dev;
+@@ -249,7 +250,7 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,
+ 	__usb_get_extra_descriptor((ifpoint)->extra,(ifpoint)->extralen,\
+ 		type,(void**)ptr)
+ 
+-/* -------------------------------------------------------------------------- */
++/* ----------------------------------------------------------------------- */
+ 
+ struct usb_operations;
+ 
+@@ -269,7 +270,8 @@ struct usb_bus {
+ 	unsigned is_b_host:1;		/* true during some HNP roleswitches */
+ 	unsigned b_hnp_enable:1;	/* OTG: did A-Host enable HNP? */
+ 
+-	int devnum_next;		/* Next open device number in round-robin allocation */
++	int devnum_next;		/* Next open device number in
++					 * round-robin allocation */
+ 
+ 	struct usb_devmap devmap;	/* device address allocation map */
+ 	struct usb_operations *op;	/* Operations (specific to the HC) */
+@@ -290,15 +292,16 @@ struct usb_bus {
+ 	struct dentry *usbfs_dentry;	/* usbfs dentry entry for the bus */
+ 
+ 	struct class_device *class_dev;	/* class device for this bus */
+-	struct kref kref;		/* handles reference counting this bus */
+-	void (*release)(struct usb_bus *bus);	/* function to destroy this bus's memory */
++	struct kref kref;		/* reference counting for this bus */
++	void (*release)(struct usb_bus *bus);
++
+ #if defined(CONFIG_USB_MON)
+ 	struct mon_bus *mon_bus;	/* non-null when associated */
+ 	int monitored;			/* non-zero when monitored */
+ #endif
+ };
+ 
+-/* -------------------------------------------------------------------------- */
++/* ----------------------------------------------------------------------- */
+ 
+ /* This is arbitrary.
+  * From USB 2.0 spec Table 11-13, offset 7, a hub can
+@@ -327,7 +330,8 @@ struct usb_device {
+ 
+ 	struct semaphore serialize;
+ 
+-	unsigned int toggle[2];		/* one bit for each endpoint ([0] = IN, [1] = OUT) */
++	unsigned int toggle[2];		/* one bit for each endpoint
++					 * ([0] = IN, [1] = OUT) */
+ 
+ 	struct usb_device *parent;	/* our hub, unless we're the root */
+ 	struct usb_bus *bus;		/* Bus we're part of */
+@@ -344,7 +348,7 @@ struct usb_device {
+ 
+ 	char **rawdescriptors;		/* Raw descriptors for each config */
+ 
+-	int have_langid;		/* whether string_langid is valid yet */
++	int have_langid;		/* whether string_langid is valid */
+ 	int string_langid;		/* language ID for strings */
+ 
+ 	char *product;
+@@ -441,22 +445,31 @@ extern struct usb_host_interface *usb_altnum_to_altsetting(
+  * USB 2.0 root hubs (EHCI host controllers) will get one path ID if they are
+  * high speed, and a different one if they are full or low speed.
+  */
+-static inline int usb_make_path (struct usb_device *dev, char *buf, size_t size)
++static inline int usb_make_path (struct usb_device *dev, char *buf,
++		size_t size)
+ {
+ 	int actual;
+-	actual = snprintf (buf, size, "usb-%s-%s", dev->bus->bus_name, dev->devpath);
++	actual = snprintf (buf, size, "usb-%s-%s", dev->bus->bus_name,
++			dev->devpath);
+ 	return (actual >= (int)size) ? -1 : actual;
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-#define USB_DEVICE_ID_MATCH_DEVICE		(USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT)
+-#define USB_DEVICE_ID_MATCH_DEV_RANGE		(USB_DEVICE_ID_MATCH_DEV_LO | USB_DEVICE_ID_MATCH_DEV_HI)
+-#define USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION	(USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_DEV_RANGE)
++#define USB_DEVICE_ID_MATCH_DEVICE \
++		(USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT)
++#define USB_DEVICE_ID_MATCH_DEV_RANGE \
++		(USB_DEVICE_ID_MATCH_DEV_LO | USB_DEVICE_ID_MATCH_DEV_HI)
++#define USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION \
++		(USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_DEV_RANGE)
+ #define USB_DEVICE_ID_MATCH_DEV_INFO \
+-	(USB_DEVICE_ID_MATCH_DEV_CLASS | USB_DEVICE_ID_MATCH_DEV_SUBCLASS | USB_DEVICE_ID_MATCH_DEV_PROTOCOL)
++		(USB_DEVICE_ID_MATCH_DEV_CLASS | \
++		USB_DEVICE_ID_MATCH_DEV_SUBCLASS | \
++		USB_DEVICE_ID_MATCH_DEV_PROTOCOL)
+ #define USB_DEVICE_ID_MATCH_INT_INFO \
+-	(USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS | USB_DEVICE_ID_MATCH_INT_PROTOCOL)
++		(USB_DEVICE_ID_MATCH_INT_CLASS | \
++		USB_DEVICE_ID_MATCH_INT_SUBCLASS | \
++		USB_DEVICE_ID_MATCH_INT_PROTOCOL)
+ 
+ /**
+  * USB_DEVICE - macro used to describe a specific usb device
+@@ -467,9 +480,11 @@ static inline int usb_make_path (struct usb_device *dev, char *buf, size_t size)
+  * specific device.
+  */
+ #define USB_DEVICE(vend,prod) \
+-	.match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = (vend), .idProduct = (prod)
++	.match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = (vend), \
++			.idProduct = (prod)
+ /**
+- * USB_DEVICE_VER - macro used to describe a specific usb device with a version range
++ * USB_DEVICE_VER - macro used to describe a specific usb device with a
++ *		version range
+  * @vend: the 16 bit USB Vendor ID
+  * @prod: the 16 bit USB Product ID
+  * @lo: the bcdDevice_lo value
+@@ -479,7 +494,9 @@ static inline int usb_make_path (struct usb_device *dev, char *buf, size_t size)
+  * specific device, with a version range.
+  */
+ #define USB_DEVICE_VER(vend,prod,lo,hi) \
+-	.match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, .idVendor = (vend), .idProduct = (prod), .bcdDevice_lo = (lo), .bcdDevice_hi = (hi)
++	.match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, \
++	.idVendor = (vend), .idProduct = (prod), \
++	.bcdDevice_lo = (lo), .bcdDevice_hi = (hi)
+ 
+ /**
+  * USB_DEVICE_INFO - macro used to describe a class of usb devices
+@@ -491,7 +508,8 @@ static inline int usb_make_path (struct usb_device *dev, char *buf, size_t size)
+  * specific class of devices.
+  */
+ #define USB_DEVICE_INFO(cl,sc,pr) \
+-	.match_flags = USB_DEVICE_ID_MATCH_DEV_INFO, .bDeviceClass = (cl), .bDeviceSubClass = (sc), .bDeviceProtocol = (pr)
++	.match_flags = USB_DEVICE_ID_MATCH_DEV_INFO, .bDeviceClass = (cl), \
++	.bDeviceSubClass = (sc), .bDeviceProtocol = (pr)
+ 
+ /**
+  * USB_INTERFACE_INFO - macro used to describe a class of usb interfaces 
+@@ -503,9 +521,10 @@ static inline int usb_make_path (struct usb_device *dev, char *buf, size_t size)
+  * specific class of interfaces.
+  */
+ #define USB_INTERFACE_INFO(cl,sc,pr) \
+-	.match_flags = USB_DEVICE_ID_MATCH_INT_INFO, .bInterfaceClass = (cl), .bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)
++	.match_flags = USB_DEVICE_ID_MATCH_INT_INFO, .bInterfaceClass = (cl), \
++	.bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)
+ 
+-/* -------------------------------------------------------------------------- */
++/* ----------------------------------------------------------------------- */
+ 
+ /**
+  * struct usb_driver - identifies USB driver to usbcore
+@@ -558,7 +577,8 @@ struct usb_driver {
+ 
+ 	void (*disconnect) (struct usb_interface *intf);
+ 
+-	int (*ioctl) (struct usb_interface *intf, unsigned int code, void *buf);
++	int (*ioctl) (struct usb_interface *intf, unsigned int code,
++			void *buf);
+ 
+ 	int (*suspend) (struct usb_interface *intf, pm_message_t message);
+ 	int (*resume) (struct usb_interface *intf);
+@@ -601,7 +621,7 @@ extern void usb_deregister_dev(struct usb_interface *intf,
+ 
+ extern int usb_disabled(void);
+ 
+-/* -------------------------------------------------------------------------- */
++/* ----------------------------------------------------------------------- */
+ 
+ /*
+  * URB support, for asynchronous request completions
+@@ -611,12 +631,14 @@ extern int usb_disabled(void);
+  * urb->transfer_flags:
+  */
+ #define URB_SHORT_NOT_OK	0x0001	/* report short reads as errors */
+-#define URB_ISO_ASAP		0x0002	/* iso-only, urb->start_frame ignored */
++#define URB_ISO_ASAP		0x0002	/* iso-only, urb->start_frame
++					 * ignored */
+ #define URB_NO_TRANSFER_DMA_MAP	0x0004	/* urb->transfer_dma valid on submit */
+ #define URB_NO_SETUP_DMA_MAP	0x0008	/* urb->setup_dma valid on submit */
+ #define URB_NO_FSBR		0x0020	/* UHCI-specific */
+-#define URB_ZERO_PACKET		0x0040	/* Finish bulk OUTs with short packet */
+-#define URB_NO_INTERRUPT	0x0080	/* HINT: no non-error interrupt needed */
++#define URB_ZERO_PACKET		0x0040	/* Finish bulk OUT with short packet */
++#define URB_NO_INTERRUPT	0x0080	/* HINT: no non-error interrupt
++					 * needed */
+ 
+ struct usb_iso_packet_descriptor {
+ 	unsigned int offset;
+@@ -804,7 +826,8 @@ struct urb
+ 	u8 reject;			/* submissions will fail */
+ 
+ 	/* public, documented fields in the urb that can be used by drivers */
+-	struct list_head urb_list;	/* list head for use by the urb owner */
++	struct list_head urb_list;	/* list head for use by the urb's
++					 * current owner */
+ 	struct usb_device *dev; 	/* (in) pointer to associated device */
+ 	unsigned int pipe;		/* (in) pipe information */
+ 	int status;			/* (return) non-ISO status */
+@@ -817,14 +840,16 @@ struct urb
+ 	dma_addr_t setup_dma;		/* (in) dma addr for setup_packet */
+ 	int start_frame;		/* (modify) start frame (ISO) */
+ 	int number_of_packets;		/* (in) number of ISO packets */
+-	int interval;			/* (modify) transfer interval (INT/ISO) */
++	int interval;			/* (modify) transfer interval
++					 * (INT/ISO) */
+ 	int error_count;		/* (return) number of ISO errors */
+ 	void *context;			/* (in) context for completion */
+ 	usb_complete_t complete;	/* (in) completion routine */
+-	struct usb_iso_packet_descriptor iso_frame_desc[0];	/* (in) ISO ONLY */
++	struct usb_iso_packet_descriptor iso_frame_desc[0];
++					/* (in) ISO ONLY */
+ };
+ 
+-/* -------------------------------------------------------------------------- */
++/* ----------------------------------------------------------------------- */
+ 
+ /**
+  * usb_fill_control_urb - initializes a control urb
+@@ -1049,7 +1074,7 @@ void usb_sg_cancel (struct usb_sg_request *io);
+ void usb_sg_wait (struct usb_sg_request *io);
+ 
+ 
+-/* -------------------------------------------------------------------------- */
++/* ----------------------------------------------------------------------- */
+ 
+ /*
+  * For various legacy reasons, Linux has a small cookie that's paired with
+@@ -1090,23 +1115,34 @@ void usb_sg_wait (struct usb_sg_request *io);
+ /* The D0/D1 toggle bits ... USE WITH CAUTION (they're almost hcd-internal) */
+ #define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1)
+ #define	usb_dotoggle(dev, ep, out)  ((dev)->toggle[out] ^= (1 << (ep)))
+-#define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << (ep))) | ((bit) << (ep)))
++#define usb_settoggle(dev, ep, out, bit) \
++		((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << (ep))) | \
++		 ((bit) << (ep)))
+ 
+ 
+-static inline unsigned int __create_pipe(struct usb_device *dev, unsigned int endpoint)
++static inline unsigned int __create_pipe(struct usb_device *dev,
++		unsigned int endpoint)
+ {
+ 	return (dev->devnum << 8) | (endpoint << 15);
+ }
+ 
+ /* Create various pipes... */
+-#define usb_sndctrlpipe(dev,endpoint)	((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint))
+-#define usb_rcvctrlpipe(dev,endpoint)	((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
+-#define usb_sndisocpipe(dev,endpoint)	((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint))
+-#define usb_rcvisocpipe(dev,endpoint)	((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
+-#define usb_sndbulkpipe(dev,endpoint)	((PIPE_BULK << 30) | __create_pipe(dev,endpoint))
+-#define usb_rcvbulkpipe(dev,endpoint)	((PIPE_BULK << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
+-#define usb_sndintpipe(dev,endpoint)	((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint))
+-#define usb_rcvintpipe(dev,endpoint)	((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
++#define usb_sndctrlpipe(dev,endpoint)	\
++	((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint))
++#define usb_rcvctrlpipe(dev,endpoint)	\
++	((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
++#define usb_sndisocpipe(dev,endpoint)	\
++	((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint))
++#define usb_rcvisocpipe(dev,endpoint)	\
++	((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
++#define usb_sndbulkpipe(dev,endpoint)	\
++	((PIPE_BULK << 30) | __create_pipe(dev,endpoint))
++#define usb_rcvbulkpipe(dev,endpoint)	\
++	((PIPE_BULK << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
++#define usb_sndintpipe(dev,endpoint)	\
++	((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint))
++#define usb_rcvintpipe(dev,endpoint)	\
++	((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+@@ -1130,7 +1166,7 @@ usb_maxpacket(struct usb_device *udev, int pipe, int is_out)
+ 	return le16_to_cpu(ep->desc.wMaxPacketSize);
+ }
+ 
+-/* -------------------------------------------------------------------------- */
++/* ----------------------------------------------------------------------- */
+ 
+ /* Events from the usb core */
+ #define USB_DEVICE_ADD		0x0001
+@@ -1141,14 +1177,18 @@ extern void usb_register_notify(struct notifier_block *nb);
+ extern void usb_unregister_notify(struct notifier_block *nb);
+ 
+ #ifdef DEBUG
+-#define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , __FILE__ , ## arg)
++#define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , \
++	__FILE__ , ## arg)
+ #else
+ #define dbg(format, arg...) do {} while (0)
+ #endif
+ 
+-#define err(format, arg...) printk(KERN_ERR "%s: " format "\n" , __FILE__ , ## arg)
+-#define info(format, arg...) printk(KERN_INFO "%s: " format "\n" , __FILE__ , ## arg)
+-#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n" , __FILE__ , ## arg)
++#define err(format, arg...) printk(KERN_ERR "%s: " format "\n" , \
++	__FILE__ , ## arg)
++#define info(format, arg...) printk(KERN_INFO "%s: " format "\n" , \
++	__FILE__ , ## arg)
++#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n" , \
++	__FILE__ , ## arg)
+ 
+ 
+ #endif  /* __KERNEL__ */

commit 0e6c8e8db508fcb292836b23d039649c5de29090
+Author: Alan Stern 
+Date:   Mon Oct 24 15:33:03 2005 -0400
+
+    [PATCH] usbcore: endpoint attributes track altsetting changes
+    
+    This patch (as588) fixes the way endpoint attribute files are registered
+    and unregistered.  Now they will correctly track along with altsetting
+    changes.  This fixes bugzilla entry #5467.
+    
+    In a separate but related change, when a usb_reset_configuration call
+    fails, the device state is not changed to USB_STATE_ADDRESS.  In the
+    first place, failure means that we don't know what the state is, not
+    that we know the device is unconfigured.  In the second place, doing
+    this can potentially lead to a memory leak, since usbcore might not
+    realize there still is a current configuration that needs to be
+    destroyed.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 574d0d4b3401..5ad0d5e28119 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1149,6 +1149,8 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
+ 	 */
+ 
+ 	/* prevent submissions using previous endpoint settings */
++	if (device_is_registered(&iface->dev))
++		usb_remove_sysfs_intf_files(iface);
+ 	usb_disable_interface(dev, iface);
+ 
+ 	iface->cur_altsetting = alt;
+@@ -1184,6 +1186,8 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
+ 	 * (Likewise, EP0 never "halts" on well designed devices.)
+ 	 */
+ 	usb_enable_interface(dev, iface);
++	if (device_is_registered(&iface->dev))
++		usb_create_sysfs_intf_files(iface);
+ 
+ 	return 0;
+ }
+@@ -1233,10 +1237,8 @@ int usb_reset_configuration(struct usb_device *dev)
+ 			USB_REQ_SET_CONFIGURATION, 0,
+ 			config->desc.bConfigurationValue, 0,
+ 			NULL, 0, USB_CTRL_SET_TIMEOUT);
+-	if (retval < 0) {
+-		usb_set_device_state(dev, USB_STATE_ADDRESS);
++	if (retval < 0)
+ 		return retval;
+-	}
+ 
+ 	dev->toggle[0] = dev->toggle[1] = 0;
+ 
+@@ -1245,6 +1247,8 @@ int usb_reset_configuration(struct usb_device *dev)
+ 		struct usb_interface *intf = config->interface[i];
+ 		struct usb_host_interface *alt;
+ 
++		if (device_is_registered(&intf->dev))
++			usb_remove_sysfs_intf_files(intf);
+ 		alt = usb_altnum_to_altsetting(intf, 0);
+ 
+ 		/* No altsetting 0?  We'll assume the first altsetting.
+@@ -1257,6 +1261,8 @@ int usb_reset_configuration(struct usb_device *dev)
+ 
+ 		intf->cur_altsetting = alt;
+ 		usb_enable_interface(dev, intf);
++		if (device_is_registered(&intf->dev))
++			usb_create_sysfs_intf_files(intf);
+ 	}
+ 	return 0;
+ }

commit be69e5b1900a19a545becda822b18d6f09168ba5
+Author: Alan Stern 
+Date:   Tue Oct 25 15:56:06 2005 -0400
+
+    [PATCH] usbcore: Improve endpoint sysfs file handling
+    
+    This revised patch (as587b) improves the implementation of USB endpoint
+    sysfs files.  Instead of storing a whole bunch of attributes for every
+    single endpoint, each endpoint now gets its own kobject and they can
+    share a static list of attributes.  The number of extra fields added to
+    struct usb_host_endpoint has been reduced from 4 to 1.
+    
+    The bEndpointAddress field is retained even though it is redundant (it
+    repeats the same information as the attributes' directory name).  The
+    code avoids calling kobject_register, to prevent generating unwanted
+    hotplug events.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 4bdbc9df6e03..f18317fb49ee 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -23,43 +23,56 @@
+ #include "usb.h"
+ 
+ /* endpoint stuff */
+-struct endpoint_attribute {
+-	struct device_attribute dev_attr;
+-	struct usb_endpoint_descriptor *endpoint;
++struct ep_object {
++	struct usb_endpoint_descriptor *desc;
+ 	struct usb_device *udev;
++	struct kobject kobj;
+ };
+-#define to_endpoint_attr(_dev_attr) \
+-	container_of(_dev_attr, struct endpoint_attribute, dev_attr)
+-
+-#define usb_ep_attr(field, format_string)					\
+-static ssize_t show_ep_##field(struct device *dev, struct device_attribute *attr,	\
+-			    char *buf)						\
+-{										\
+-	struct endpoint_attribute *endpoint_attr = to_endpoint_attr(attr);	\
+-										\
+-	return sprintf(buf, format_string, endpoint_attr->endpoint->field);	\
+-}
++#define to_ep_object(_kobj) \
++	container_of(_kobj, struct ep_object, kobj)
++
++struct ep_attribute {
++	struct attribute attr;
++	ssize_t (*show)(struct usb_device *,
++			struct usb_endpoint_descriptor *, char *);
++};
++#define to_ep_attribute(_attr) \
++	container_of(_attr, struct ep_attribute, attr)
++
++#define EP_ATTR(_name)						\
++struct ep_attribute ep_##_name = {				\
++	.attr = {.name = #_name, .owner = THIS_MODULE,		\
++			.mode = S_IRUGO},			\
++	.show = show_ep_##_name}
++
++#define usb_ep_attr(field, format_string)			\
++static ssize_t show_ep_##field(struct usb_device *udev,		\
++		struct usb_endpoint_descriptor *desc, 		\
++		char *buf)					\
++{								\
++	return sprintf(buf, format_string, desc->field);	\
++}								\
++static EP_ATTR(field);
++
+ usb_ep_attr(bLength, "%02x\n")
+-usb_ep_attr(bDescriptorType, "%02x\n")
+ usb_ep_attr(bEndpointAddress, "%02x\n")
+ usb_ep_attr(bmAttributes, "%02x\n")
+ usb_ep_attr(bInterval, "%02x\n")
+ 
+-static ssize_t show_ep_wMaxPacketSize(struct device *dev,
+-				      struct device_attribute *attr, char *buf)
++static ssize_t show_ep_wMaxPacketSize(struct usb_device *udev,
++		struct usb_endpoint_descriptor *desc, char *buf)
+ {
+-	struct endpoint_attribute *endpoint_attr = to_endpoint_attr(attr);
+-
+ 	return sprintf(buf, "%04x\n",
+-		      le16_to_cpu(endpoint_attr->endpoint->wMaxPacketSize) & 0x07ff);
++			le16_to_cpu(desc->wMaxPacketSize) & 0x07ff);
+ }
++static EP_ATTR(wMaxPacketSize);
+ 
+-static ssize_t show_ep_type(struct device *dev, struct device_attribute *attr, char *buf)
++static ssize_t show_ep_type(struct usb_device *udev,
++		struct usb_endpoint_descriptor *desc, char *buf)
+ {
+-	struct endpoint_attribute *endpoint_attr = to_endpoint_attr(attr);
+ 	char *type = "unknown";
+ 
+-	switch (endpoint_attr->endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
++	switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+ 	case USB_ENDPOINT_XFER_CONTROL:
+ 		type = "Control";
+ 		break;
+@@ -75,35 +88,34 @@ static ssize_t show_ep_type(struct device *dev, struct device_attribute *attr, c
+ 	}
+ 	return sprintf(buf, "%s\n", type);
+ }
++static EP_ATTR(type);
+ 
+-static ssize_t show_ep_interval(struct device *dev, struct device_attribute *attr, char *buf)
++static ssize_t show_ep_interval(struct usb_device *udev,
++		struct usb_endpoint_descriptor *desc, char *buf)
+ {
+-	struct endpoint_attribute *endpoint_attr = to_endpoint_attr(attr);
+-	struct usb_device *udev = endpoint_attr->udev;
+-	struct usb_endpoint_descriptor *endpoint = endpoint_attr->endpoint;
+ 	char unit;
+ 	unsigned interval = 0;
+ 	unsigned in;
+ 
+-	in = (endpoint->bEndpointAddress & USB_DIR_IN);
++	in = (desc->bEndpointAddress & USB_DIR_IN);
+ 
+-	switch (endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
++	switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+ 	case USB_ENDPOINT_XFER_CONTROL:
+ 		if (udev->speed == USB_SPEED_HIGH) 	/* uframes per NAK */
+-			interval = endpoint->bInterval;
++			interval = desc->bInterval;
+ 		break;
+ 	case USB_ENDPOINT_XFER_ISOC:
+-		interval = 1 << (endpoint->bInterval - 1);
++		interval = 1 << (desc->bInterval - 1);
+ 		break;
+ 	case USB_ENDPOINT_XFER_BULK:
+-		if (udev->speed == USB_SPEED_HIGH && !in)	/* uframes per NAK */
+-			interval = endpoint->bInterval;
++		if (udev->speed == USB_SPEED_HIGH && !in) /* uframes per NAK */
++			interval = desc->bInterval;
+ 		break;
+ 	case USB_ENDPOINT_XFER_INT:
+-		if (udev->speed == USB_SPEED_HIGH) {
+-			interval = 1 << (endpoint->bInterval - 1);
+-		} else
+-			interval = endpoint->bInterval;
++		if (udev->speed == USB_SPEED_HIGH)
++			interval = 1 << (desc->bInterval - 1);
++		else
++			interval = desc->bInterval;
+ 		break;
+ 	}
+ 	interval *= (udev->speed == USB_SPEED_HIGH) ? 125 : 1000;
+@@ -116,78 +128,95 @@ static ssize_t show_ep_interval(struct device *dev, struct device_attribute *att
+ 
+ 	return sprintf(buf, "%d%cs\n", interval, unit);
+ }
++static EP_ATTR(interval);
+ 
+-static ssize_t show_ep_direction(struct device *dev, struct device_attribute *attr, char *buf)
++static ssize_t show_ep_direction(struct usb_device *udev,
++		struct usb_endpoint_descriptor *desc, char *buf)
+ {
+-	struct endpoint_attribute *endpoint_attr = to_endpoint_attr(attr);
+ 	char *direction;
+ 
+-	if ((endpoint_attr->endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+-	    USB_ENDPOINT_XFER_CONTROL)
++	if ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
++			USB_ENDPOINT_XFER_CONTROL)
+ 		direction = "both";
+-	else if (endpoint_attr->endpoint->bEndpointAddress & USB_DIR_IN)
++	else if (desc->bEndpointAddress & USB_DIR_IN)
+ 		direction = "in";
+ 	else
+ 		direction = "out";
+ 	return sprintf(buf, "%s\n", direction);
+ }
++static EP_ATTR(direction);
++
++static struct attribute *ep_attrs[] = {
++	&ep_bLength.attr,
++	&ep_bEndpointAddress.attr,
++	&ep_bmAttributes.attr,
++	&ep_bInterval.attr,
++	&ep_wMaxPacketSize.attr,
++	&ep_type.attr,
++	&ep_interval.attr,
++	&ep_direction.attr,
++	NULL,
++};
+ 
+-static struct endpoint_attribute *create_ep_attr(struct usb_endpoint_descriptor *endpoint,
+-						 struct usb_device *udev, char *name,
+-		ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf))
++static void ep_object_release(struct kobject *kobj)
+ {
+-	struct endpoint_attribute *ep_attr;
+-
+-	ep_attr = kzalloc(sizeof(*ep_attr), GFP_KERNEL);
+-	if (ep_attr) {
+-		ep_attr->endpoint = endpoint;
+-		ep_attr->udev = udev;
+-		ep_attr->dev_attr.attr.name = name;
+-		ep_attr->dev_attr.attr.mode = 0444;
+-		ep_attr->dev_attr.attr.owner = THIS_MODULE;
+-		ep_attr->dev_attr.show = show;
+-	}
+-	return ep_attr;
++	kfree(to_ep_object(kobj));
+ }
+ 
+-static void usb_create_ep_files(struct kobject *kobj, struct usb_host_endpoint *endpoint, struct usb_device *udev)
++static ssize_t ep_object_show(struct kobject *kobj, struct attribute *attr,
++		char *buf)
+ {
+-	struct usb_endpoint_descriptor *ep;
+-
+-	ep = &endpoint->desc;
+-
+-	endpoint->attrs = kzalloc(sizeof(struct attribute *) * 10, GFP_KERNEL);
+-	endpoint->attrs[0] = &(create_ep_attr(ep, udev, "direction", show_ep_direction)->dev_attr.attr);
+-	endpoint->attrs[1] = &(create_ep_attr(ep, udev, "type", show_ep_type)->dev_attr.attr);
+-	endpoint->attrs[2] = &(create_ep_attr(ep, udev, "bLength", show_ep_bLength)->dev_attr.attr);
+-	endpoint->attrs[3] = &(create_ep_attr(ep, udev, "bDescriptorType", show_ep_bDescriptorType)->dev_attr.attr);
+-	endpoint->attrs[4] = &(create_ep_attr(ep, udev, "bEndpointAddress", show_ep_bEndpointAddress)->dev_attr.attr);
+-	endpoint->attrs[5] = &(create_ep_attr(ep, udev, "bmAttributes", show_ep_bmAttributes)->dev_attr.attr);
+-	endpoint->attrs[6] = &(create_ep_attr(ep, udev, "wMaxPacketSize", show_ep_wMaxPacketSize)->dev_attr.attr);
+-	endpoint->attrs[7] = &(create_ep_attr(ep, udev, "bInterval", show_ep_bInterval)->dev_attr.attr);
+-	endpoint->attrs[8] = &(create_ep_attr(ep, udev, "interval", show_ep_interval)->dev_attr.attr);
+-	endpoint->attrs[9] = NULL;
+-	endpoint->num_attrs = 9;
+-
+-	endpoint->attr_group = kzalloc(sizeof(*endpoint->attr_group), GFP_KERNEL);
+-	endpoint->attr_name = kzalloc(10, GFP_KERNEL);
+-	sprintf(endpoint->attr_name, "ep_%02x", endpoint->desc.bEndpointAddress);
+-
+-	endpoint->attr_group->attrs = endpoint->attrs;
+-	endpoint->attr_group->name = endpoint->attr_name;
+-	sysfs_create_group(kobj, endpoint->attr_group);
++	struct ep_object *ep_obj = to_ep_object(kobj);
++	struct ep_attribute *ep_attr = to_ep_attribute(attr);
++
++	return (ep_attr->show)(ep_obj->udev, ep_obj->desc, buf);
+ }
+ 
+-static void usb_remove_ep_files(struct kobject *kobj, struct usb_host_endpoint *endpoint)
++static struct sysfs_ops ep_object_sysfs_ops = {
++	.show =			ep_object_show,
++};
++
++static struct kobj_type ep_object_ktype = {
++	.release =		ep_object_release,
++	.sysfs_ops =		&ep_object_sysfs_ops,
++	.default_attrs =	ep_attrs,
++};
++
++static void usb_create_ep_files(struct kobject *parent,
++		struct usb_host_endpoint *endpoint,
++		struct usb_device *udev)
+ {
+-	int i;
++	struct ep_object *ep_obj;
++	struct kobject *kobj;
++
++	ep_obj = kzalloc(sizeof(struct ep_object), GFP_KERNEL);
++	if (!ep_obj)
++		return;
+ 
+-	sysfs_remove_group(kobj, endpoint->attr_group);
+-	kfree(endpoint->attr_group);
+-	kfree(endpoint->attr_name);
+-	for (i = 0; i < endpoint->num_attrs; ++i)
+-		kfree(endpoint->attrs[i]);
+-	kfree(endpoint->attrs);
++	ep_obj->desc = &endpoint->desc;
++	ep_obj->udev = udev;
++
++	kobj = &ep_obj->kobj;
++	kobject_set_name(kobj, "ep_%02x", endpoint->desc.bEndpointAddress);
++	kobj->parent = parent;
++	kobj->ktype = &ep_object_ktype;
++
++	/* Don't use kobject_register, because it generates a hotplug event */
++	kobject_init(kobj);
++	if (kobject_add(kobj) == 0)
++		endpoint->kobj = kobj;
++	else
++		kobject_put(kobj);
++}
++
++static void usb_remove_ep_files(struct usb_host_endpoint *endpoint)
++{
++
++	if (endpoint->kobj) {
++		kobject_del(endpoint->kobj);
++		kobject_put(endpoint->kobj);
++		endpoint->kobj = NULL;
++	}
+ }
+ 
+ /* Active configuration fields */
+@@ -411,7 +440,7 @@ void usb_remove_sysfs_dev_files (struct usb_device *udev)
+ {
+ 	struct device *dev = &udev->dev;
+ 
+-	usb_remove_ep_files(&dev->kobj, &udev->ep0);
++	usb_remove_ep_files(&udev->ep0);
+ 	sysfs_remove_group(&dev->kobj, &dev_attr_grp);
+ 
+ 	if (udev->descriptor.iManufacturer)
+@@ -496,7 +525,7 @@ static struct attribute_group intf_attr_grp = {
+ 	.attrs = intf_attrs,
+ };
+ 
+-static void usb_create_intf_ep_files(struct usb_interface *intf)
++static inline void usb_create_intf_ep_files(struct usb_interface *intf)
+ {
+ 	struct usb_host_interface *iface_desc;
+ 	int i;
+@@ -504,17 +533,17 @@ static void usb_create_intf_ep_files(struct usb_interface *intf)
+ 	iface_desc = intf->cur_altsetting;
+ 	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i)
+ 		usb_create_ep_files(&intf->dev.kobj, &iface_desc->endpoint[i],
+-				    interface_to_usbdev(intf));
++				interface_to_usbdev(intf));
+ }
+ 
+-static void usb_remove_intf_ep_files(struct usb_interface *intf)
++static inline void usb_remove_intf_ep_files(struct usb_interface *intf)
+ {
+ 	struct usb_host_interface *iface_desc;
+ 	int i;
+ 
+ 	iface_desc = intf->cur_altsetting;
+ 	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i)
+-		usb_remove_ep_files(&intf->dev.kobj, &iface_desc->endpoint[i]);
++		usb_remove_ep_files(&iface_desc->endpoint[i]);
+ }
+ 
+ void usb_create_sysfs_intf_files (struct usb_interface *intf)
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index a2d923fd54f9..465ff4585ca5 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -57,10 +57,7 @@ struct usb_host_endpoint {
+ 	struct usb_endpoint_descriptor	desc;
+ 	struct list_head		urb_list;
+ 	void				*hcpriv;
+-	char 				*attr_name;
+-	struct attribute_group		*attr_group;
+-	struct attribute 		**attrs;
+-	int				num_attrs;
++	struct kobject			*kobj;	/* For sysfs info */
+ 
+ 	unsigned char *extra;   /* Extra descriptors */
+ 	int extralen;

commit 3f13e66e219238e025ff561d69826da9342c3f4a
+Author: Alan Stern 
+Date:   Sun Oct 23 19:43:36 2005 -0700
+
+    [PATCH] PATCH: usb-storage: use kthread API
+    
+    This patch is originally from Alan Stern (as569).  It has been rediffed
+    against a current tree.
+    
+    This patch converts usb-storage to use the kthread API for creating its
+    control and scanning threads.  The new code doesn't use kthread_stop
+    because the threads need (or will need in the future) to exit
+    asynchronously.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Matthew Dharm 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index c1a902691bc6..3847ebed2aa4 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -54,6 +54,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ #include 
+@@ -310,22 +311,7 @@ static int usb_stor_control_thread(void * __us)
+ 	struct us_data *us = (struct us_data *)__us;
+ 	struct Scsi_Host *host = us_to_host(us);
+ 
+-	lock_kernel();
+-
+-	/*
+-	 * This thread doesn't need any user-level access,
+-	 * so get rid of all our resources.
+-	 */
+-	daemonize("usb-storage");
+ 	current->flags |= PF_NOFREEZE;
+-	unlock_kernel();
+-
+-	/* acquire a reference to the host, so it won't be deallocated
+-	 * until we're ready to exit */
+-	scsi_host_get(host);
+-
+-	/* signal that we've started the thread */
+-	complete(&(us->notify));
+ 
+ 	for(;;) {
+ 		US_DEBUGP("*** thread sleeping.\n");
+@@ -768,6 +754,7 @@ static int get_pipes(struct us_data *us)
+ static int usb_stor_acquire_resources(struct us_data *us)
+ {
+ 	int p;
++	struct task_struct *th;
+ 
+ 	us->current_urb = usb_alloc_urb(0, GFP_KERNEL);
+ 	if (!us->current_urb) {
+@@ -784,17 +771,19 @@ static int usb_stor_acquire_resources(struct us_data *us)
+ 	}
+ 
+ 	/* Start up our control thread */
+-	p = kernel_thread(usb_stor_control_thread, us, CLONE_VM);
+-	if (p < 0) {
++	th = kthread_create(usb_stor_control_thread, us, "usb-storage");
++	if (IS_ERR(th)) {
+ 		printk(KERN_WARNING USB_STORAGE 
+ 		       "Unable to start control thread\n");
+-		return p;
++		return PTR_ERR(th);
+ 	}
+-	us->pid = p;
+-	atomic_inc(&total_threads);
+ 
+-	/* Wait for the thread to start */
+-	wait_for_completion(&(us->notify));
++	/* Take a reference to the host for the control thread and
++	 * count it among all the threads we have launched.  Then
++	 * start it up. */
++	scsi_host_get(us_to_host(us));
++	atomic_inc(&total_threads);
++	wake_up_process(th);
+ 
+ 	return 0;
+ }
+@@ -890,21 +879,6 @@ static int usb_stor_scan_thread(void * __us)
+ {
+ 	struct us_data *us = (struct us_data *)__us;
+ 
+-	/*
+-	 * This thread doesn't need any user-level access,
+-	 * so get rid of all our resources.
+-	 */
+-	lock_kernel();
+-	daemonize("usb-stor-scan");
+-	unlock_kernel();
+-
+-	/* Acquire a reference to the host, so it won't be deallocated
+-	 * until we're ready to exit */
+-	scsi_host_get(us_to_host(us));
+-
+-	/* Signal that we've started the thread */
+-	complete(&(us->notify));
+-
+ 	printk(KERN_DEBUG
+ 		"usb-storage: device found at %d\n", us->pusb_dev->devnum);
+ 
+@@ -949,6 +923,7 @@ static int storage_probe(struct usb_interface *intf,
+ 	struct us_data *us;
+ 	const int id_index = id - storage_usb_ids; 
+ 	int result;
++	struct task_struct *th;
+ 
+ 	US_DEBUGP("USB Mass Storage device detected\n");
+ 
+@@ -1029,17 +1004,21 @@ static int storage_probe(struct usb_interface *intf,
+ 	}
+ 
+ 	/* Start up the thread for delayed SCSI-device scanning */
+-	result = kernel_thread(usb_stor_scan_thread, us, CLONE_VM);
+-	if (result < 0) {
++	th = kthread_create(usb_stor_scan_thread, us, "usb-stor-scan");
++	if (IS_ERR(th)) {
+ 		printk(KERN_WARNING USB_STORAGE 
+ 		       "Unable to start the device-scanning thread\n");
+ 		quiesce_and_remove_host(us);
++		result = PTR_ERR(th);
+ 		goto BadDevice;
+ 	}
+-	atomic_inc(&total_threads);
+ 
+-	/* Wait for the thread to start */
+-	wait_for_completion(&(us->notify));
++	/* Take a reference to the host for the scanning thread and
++	 * count it among all the threads we have launched.  Then
++	 * start it up. */
++	scsi_host_get(us_to_host(us));
++	atomic_inc(&total_threads);
++	wake_up_process(th);
+ 
+ 	return 0;
+ 
+diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
+index dfa4dc71dd3e..98b09711a739 100644
+--- a/drivers/usb/storage/usb.h
++++ b/drivers/usb/storage/usb.h
+@@ -161,9 +161,6 @@ struct us_data {
+ 	struct scsi_cmnd	*srb;		 /* current srb		*/
+ 	unsigned int		tag;		 /* current dCBWTag	*/
+ 
+-	/* thread information */
+-	int			pid;		 /* control thread	 */
+-
+ 	/* control and bulk communications data */
+ 	struct urb		*current_urb;	 /* USB requests	 */
+ 	struct usb_ctrlrequest	*cr;		 /* control requests	 */

commit ce2596df79ddbac605a290f4c7cf011cb40524fc
+Author: Alan Stern 
+Date:   Sun Oct 23 19:41:39 2005 -0700
+
+    [PATCH] PATCH: usb-storage: implement minimal PM
+    
+    This patch from Alan Stern started as as568.  It has been rediffed against
+    a current tree.
+    
+    This patch adds minimal suspend/resume support to usb-storage.  Just enough
+    for it to qualify as PM-aware.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Matthew Dharm 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index eb901817b7d2..c1a902691bc6 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -111,11 +111,6 @@ static atomic_t total_threads = ATOMIC_INIT(0);
+ static DECLARE_COMPLETION(threads_gone);
+ 
+ 
+-static int storage_probe(struct usb_interface *iface,
+-			 const struct usb_device_id *id);
+-
+-static void storage_disconnect(struct usb_interface *iface);
+-
+ /* The entries in this table, except for final ones here
+  * (USB_MASS_STORAGE_CLASS and the empty entry), correspond,
+  * line for line with the entries of us_unsuaul_dev_list[].
+@@ -233,13 +228,40 @@ static struct us_unusual_dev us_unusual_dev_list[] = {
+ 	{ NULL }
+ };
+ 
+-static struct usb_driver usb_storage_driver = {
+-	.owner =	THIS_MODULE,
+-	.name =		"usb-storage",
+-	.probe =	storage_probe,
+-	.disconnect =	storage_disconnect,
+-	.id_table =	storage_usb_ids,
+-};
++
++#ifdef CONFIG_PM	/* Minimal support for suspend and resume */
++
++static int storage_suspend(struct usb_interface *iface, pm_message_t message)
++{
++	struct us_data *us = usb_get_intfdata(iface);
++
++	/* Wait until no command is running */
++	down(&us->dev_semaphore);
++
++	US_DEBUGP("%s\n", __FUNCTION__);
++	iface->dev.power.power_state.event = message.event;
++
++	/* When runtime PM is working, we'll set a flag to indicate
++	 * whether we should autoresume when a SCSI request arrives. */
++
++	up(&us->dev_semaphore);
++	return 0;
++}
++
++static int storage_resume(struct usb_interface *iface)
++{
++	struct us_data *us = usb_get_intfdata(iface);
++
++	down(&us->dev_semaphore);
++
++	US_DEBUGP("%s\n", __FUNCTION__);
++	iface->dev.power.power_state.event = PM_EVENT_ON;
++
++	up(&us->dev_semaphore);
++	return 0;
++}
++
++#endif /* CONFIG_PM */
+ 
+ /*
+  * fill_inquiry_response takes an unsigned char array (which must
+@@ -1042,6 +1064,18 @@ static void storage_disconnect(struct usb_interface *intf)
+  * Initialization and registration
+  ***********************************************************************/
+ 
++static struct usb_driver usb_storage_driver = {
++	.owner =	THIS_MODULE,
++	.name =		"usb-storage",
++	.probe =	storage_probe,
++	.disconnect =	storage_disconnect,
++#ifdef CONFIG_PM
++	.suspend =	storage_suspend,
++	.resume =	storage_resume,
++#endif
++	.id_table =	storage_usb_ids,
++};
++
+ static int __init usb_stor_init(void)
+ {
+ 	int retval;

commit bbafa4668f37f5093a3ae2a8b0cbe327e24e12da
+Author: Alan Stern 
+Date:   Sun Oct 23 19:40:22 2005 -0700
+
+    [PATCH] PATCH: usb-storage: allocate separate sense buffer
+    
+    This patch is from Alan Stern (as560).  It has been rediffed against a
+    current tree.
+    
+    This patch allocates a separate buffer for usb-storage to use when
+    auto-sensing.  Up to now we have been using the sense buffer embedded in a
+    scsi_cmnd struct, which is dangerous on hosts that (a) don't do
+    cache-coherent DMA or (b) have DMA alignment restrictions.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Matthew Dharm 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+index e89e945fc4a7..7ca896a342e3 100644
+--- a/drivers/usb/storage/transport.c
++++ b/drivers/usb/storage/transport.c
+@@ -636,11 +636,11 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 
+ 		/* use the new buffer we have */
+ 		old_request_buffer = srb->request_buffer;
+-		srb->request_buffer = srb->sense_buffer;
++		srb->request_buffer = us->sensebuf;
+ 
+ 		/* set the buffer length for transfer */
+ 		old_request_bufflen = srb->request_bufflen;
+-		srb->request_bufflen = 18;
++		srb->request_bufflen = US_SENSE_SIZE;
+ 
+ 		/* set up for no scatter-gather use */
+ 		old_sg = srb->use_sg;
+@@ -652,6 +652,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 		temp_result = us->transport(us->srb, us);
+ 
+ 		/* let's clean up right away */
++		memcpy(srb->sense_buffer, us->sensebuf, US_SENSE_SIZE);
+ 		srb->resid = old_resid;
+ 		srb->request_buffer = old_request_buffer;
+ 		srb->request_bufflen = old_request_bufflen;
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 92ee079d9172..eb901817b7d2 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -467,6 +467,12 @@ static int associate_dev(struct us_data *us, struct usb_interface *intf)
+ 		US_DEBUGP("I/O buffer allocation failed\n");
+ 		return -ENOMEM;
+ 	}
++
++	us->sensebuf = kmalloc(US_SENSE_SIZE, GFP_KERNEL);
++	if (!us->sensebuf) {
++		US_DEBUGP("Sense buffer allocation failed\n");
++		return -ENOMEM;
++	}
+ 	return 0;
+ }
+ 
+@@ -800,6 +806,8 @@ static void dissociate_dev(struct us_data *us)
+ {
+ 	US_DEBUGP("-- %s\n", __FUNCTION__);
+ 
++	kfree(us->sensebuf);
++
+ 	/* Free the device-related DMA-mapped buffers */
+ 	if (us->cr)
+ 		usb_buffer_free(us->pusb_dev, sizeof(*us->cr), us->cr,
+diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
+index a195adae57b6..dfa4dc71dd3e 100644
+--- a/drivers/usb/storage/usb.h
++++ b/drivers/usb/storage/usb.h
+@@ -117,6 +117,7 @@ enum { US_DO_ALL_FLAGS };
+  */
+ 
+ #define US_IOBUF_SIZE		64	/* Size of the DMA-mapped I/O buffer */
++#define US_SENSE_SIZE		18	/* Size of the autosense data buffer */
+ 
+ typedef int (*trans_cmnd)(struct scsi_cmnd *, struct us_data*);
+ typedef int (*trans_reset)(struct us_data*);
+@@ -168,6 +169,7 @@ struct us_data {
+ 	struct usb_ctrlrequest	*cr;		 /* control requests	 */
+ 	struct usb_sg_request	current_sg;	 /* scatter-gather req.  */
+ 	unsigned char		*iobuf;		 /* I/O buffer		 */
++	unsigned char		*sensebuf;	 /* sense data buffer	 */
+ 	dma_addr_t		cr_dma;		 /* buffer DMA addresses */
+ 	dma_addr_t		iobuf_dma;
+ 

commit b876aef7f890d8c59a45b78858a36cf60fddf522
+Author: Alan Stern 
+Date:   Sun Oct 23 19:38:56 2005 -0700
+
+    [PATCH] PATCH: usb-storage: move GetMaxLUN later in time
+    
+    This patch is originally from Alan Stern (as557).  It has been re-diffed
+    against a current tree, and I also corrected a minor merging error.
+    
+    Some time ago we introduced a delay before device scanning, because many
+    devices do not like to receive SCSI commands right after enumeration.
+    Now it turns out there's a device that doesn't like to receive
+    Get-Max-LUN right after enumeration either.  Accordingly this patch
+    delays the Get-Max-LUN request until the beginning of the scanning
+    procedure.  This fixes Bugzilla entry #5010.
+    
+    Three things are worth noting.  First, I removed the locking code from
+    usb_stor_acquire_resources.  It's not needed, because the locking is to
+    protect against disconnect events and acquire_resources is only called
+    during probe (so the disconnect routine can't be called).  Second, I
+    initialized to 0 the buffer used for the Get-Max-LUN response.  It's not
+    really necessary, but it will prevent random values from showing up in
+    the debugging log when the request fails.  Third, I added a test against
+    the SINGLE_LUN flag.  This will allow us to use the flag to indicate
+    Bulk-only devices that can't handle Get-Max-LUN.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Matthew Dharm 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+index c1ba5301ebfc..e89e945fc4a7 100644
+--- a/drivers/usb/storage/transport.c
++++ b/drivers/usb/storage/transport.c
+@@ -923,6 +923,7 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
+ 	int result;
+ 
+ 	/* issue the command */
++	us->iobuf[0] = 0;
+ 	result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
+ 				 US_BULK_GET_MAX_LUN, 
+ 				 USB_DIR_IN | USB_TYPE_CLASS | 
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 5164900e40c1..92ee079d9172 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -747,25 +747,13 @@ static int usb_stor_acquire_resources(struct us_data *us)
+ 		return -ENOMEM;
+ 	}
+ 
+-	/* Lock the device while we carry out the next two operations */
+-	down(&us->dev_semaphore);
+-
+-	/* For bulk-only devices, determine the max LUN value */
+-	if (us->protocol == US_PR_BULK) {
+-		p = usb_stor_Bulk_max_lun(us);
+-		if (p < 0) {
+-			up(&us->dev_semaphore);
+-			return p;
+-		}
+-		us->max_lun = p;
+-	}
+-
+ 	/* Just before we start our control thread, initialize
+ 	 * the device if it needs initialization */
+-	if (us->unusual_dev->initFunction)
+-		us->unusual_dev->initFunction(us);
+-
+-	up(&us->dev_semaphore);
++	if (us->unusual_dev->initFunction) {
++		p = us->unusual_dev->initFunction(us);
++		if (p)
++			return p;
++	}
+ 
+ 	/* Start up our control thread */
+ 	p = kernel_thread(usb_stor_control_thread, us, CLONE_VM);
+@@ -904,6 +892,14 @@ static int usb_stor_scan_thread(void * __us)
+ 
+ 	/* If the device is still connected, perform the scanning */
+ 	if (!test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
++
++		/* For bulk-only devices, determine the max LUN value */
++		if (us->protocol == US_PR_BULK &&
++				!(us->flags & US_FL_SINGLE_LUN)) {
++			down(&us->dev_semaphore);
++			us->max_lun = usb_stor_Bulk_max_lun(us);
++			up(&us->dev_semaphore);
++		}
+ 		scsi_scan_host(us_to_host(us));
+ 		printk(KERN_DEBUG "usb-storage: device scan complete\n");
+ 

commit 423e489d704d05c6e8c2927fb1854db85914912a
+Author: Alan Stern 
+Date:   Wed Oct 19 13:06:13 2005 -0400
+
+    [PATCH] hid-core: Add Clear-Halt on the Interrupt-in endpoint
+    
+    This patch (as577) adds a Clear-Halt call on the Interrupt-in endpoint
+    during input device configuration.  Without it my HP USB keyboard doesn't
+    work.
+    
+    Vojtech says it's worth trying, since it might help with some recalcitrant
+    devices.  On the other hand, it might interfere with others.  I'm
+    submitting it so that it can get tested by a range of users.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
+index f7fcce731f54..79ddce4555ab 100644
+--- a/drivers/usb/input/hid-core.c
++++ b/drivers/usb/input/hid-core.c
+@@ -1784,6 +1784,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
+ 	hid->urbctrl->transfer_dma = hid->ctrlbuf_dma;
+ 	hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
+ 
++	/* May be needed for some devices */
++	usb_clear_halt(hid->dev, hid->urbin->pipe);
++
+ 	return hid;
+ 
+ fail:

commit 478a3bab8c87a9ba4a4ba338314e32bb0c378e62
+Author: Alan Stern 
+Date:   Wed Oct 19 12:52:02 2005 -0400
+
+    [PATCH] USB: Always do usb-handoff
+    
+    This revised patch (as586b) makes usb-handoff permanently true and no
+    longer a kernel boot parameter.  It also removes the piix3_usb quirk code;
+    that was nothing more than an early version of the USB handoff code
+    (written at a time when Intel's PIIX3 was about the only motherboard with
+    USB support).  And it adds identifiers for the three PCI USB controller
+    classes to pci_ids.h.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
+index 971589a9752d..90766b75d1b7 100644
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -1517,8 +1517,6 @@ running once the system is up.
+ 	uart6850=	[HW,OSS]
+ 			Format: ,
+ 
+-	usb-handoff	[HW] Enable early USB BIOS -> OS handoff
+-
+ 	usbhid.mousepoll=
+ 			[USBHID] The interval which mice are to be polled at.
+ 
+diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
+index f7411ca48835..b7fd3f644e1e 100644
+--- a/drivers/usb/host/pci-quirks.c
++++ b/drivers/usb/host/pci-quirks.c
+@@ -23,33 +23,6 @@
+ #include 
+ 
+ 
+-/*
+- * PIIX3 USB: We have to disable USB interrupts that are
+- * hardwired to PIRQD# and may be shared with an
+- * external device.
+- *
+- * Legacy Support Register (LEGSUP):
+- *     bit13:  USB PIRQ Enable (USBPIRQDEN),
+- *     bit4:   Trap/SMI On IRQ Enable (USBSMIEN).
+- *
+- * We mask out all r/wc bits, too.
+- */
+-static void __devinit quirk_piix3_usb(struct pci_dev *dev)
+-{
+-	u16 legsup;
+-
+-	pci_read_config_word(dev, 0xc0, &legsup);
+-	legsup &= 0x50ef;
+-	pci_write_config_word(dev, 0xc0, legsup);
+-}
+-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371SB_2,	quirk_piix3_usb );
+-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371AB_2,	quirk_piix3_usb );
+-
+-
+-/* FIXME these should be the guts of hcd->reset() methods; resolve all
+- * the differences between this version and the HCD's version.
+- */
+-
+ #define UHCI_USBLEGSUP		0xc0		/* legacy support */
+ #define UHCI_USBCMD		0		/* command register */
+ #define UHCI_USBINTR		4		/* interrupt register */
+@@ -83,13 +56,6 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371AB_2,	qui
+ #define EHCI_USBLEGCTLSTS	4		/* legacy control/status */
+ #define EHCI_USBLEGCTLSTS_SOOE	(1 << 13)	/* SMI on ownership change */
+ 
+-int usb_early_handoff __devinitdata = 0;
+-static int __init usb_handoff_early(char *str)
+-{
+-	usb_early_handoff = 1;
+-	return 0;
+-}
+-__setup("usb-handoff", usb_handoff_early);
+ 
+ /*
+  * Make sure the controller is completely inactive, unable to
+@@ -320,17 +286,11 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
+ 
+ static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
+ {
+-	if (!usb_early_handoff)
+-		return;
+-
+-	if (pdev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x00)) { /* UHCI */
++	if (pdev->class == PCI_CLASS_SERIAL_USB_UHCI)
+ 		quirk_usb_handoff_uhci(pdev);
+-	} else if (pdev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x10)) { /* OHCI */
++	else if (pdev->class == PCI_CLASS_SERIAL_USB_OHCI)
+ 		quirk_usb_handoff_ohci(pdev);
+-	} else if (pdev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x20)) { /* EHCI */
++	else if (pdev->class == PCI_CLASS_SERIAL_USB_EHCI)
+ 		quirk_usb_disable_ehci(pdev);
+-	}
+-
+-	return;
+ }
+ DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff);
+diff --git a/include/asm-i386/mach-summit/mach_mpparse.h b/include/asm-i386/mach-summit/mach_mpparse.h
+index 2b9e6d55bef1..1cce2b924a80 100644
+--- a/include/asm-i386/mach-summit/mach_mpparse.h
++++ b/include/asm-i386/mach-summit/mach_mpparse.h
+@@ -22,7 +22,6 @@ static inline void mpc_oem_pci_bus(struct mpc_config_bus *m,
+ {
+ }
+ 
+-extern int usb_early_handoff;
+ static inline int mps_oem_check(struct mp_config_table *mpc, char *oem, 
+ 		char *productid)
+ {
+@@ -32,7 +31,6 @@ static inline int mps_oem_check(struct mp_config_table *mpc, char *oem,
+ 			 || !strncmp(productid, "RUTHLESS SMP", 12))){
+ 		use_cyclone = 1; /*enable cyclone-timer*/
+ 		setup_summit();
+-		usb_early_handoff = 1;
+ 		return 1;
+ 	}
+ 	return 0;
+@@ -46,7 +44,6 @@ static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+ 	     || !strncmp(oem_table_id, "EXA", 3))){
+ 		use_cyclone = 1; /*enable cyclone-timer*/
+ 		setup_summit();
+-		usb_early_handoff = 1;
+ 		return 1;
+ 	}
+ 	return 0;
+diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
+index 7d300f7469e3..467a096c3b81 100644
+--- a/include/linux/pci_ids.h
++++ b/include/linux/pci_ids.h
+@@ -96,6 +96,9 @@
+ #define PCI_CLASS_SERIAL_ACCESS		0x0c01
+ #define PCI_CLASS_SERIAL_SSA		0x0c02
+ #define PCI_CLASS_SERIAL_USB		0x0c03
++#define PCI_CLASS_SERIAL_USB_UHCI	0x0c0300
++#define PCI_CLASS_SERIAL_USB_OHCI	0x0c0310
++#define PCI_CLASS_SERIAL_USB_EHCI	0x0c0320
+ #define PCI_CLASS_SERIAL_FIBER		0x0c04
+ #define PCI_CLASS_SERIAL_SMBUS		0x0c05
+ 

commit 3e8a556a02d5aa16375d4d74aad0f67cd844c047
+Author: Alan Stern 
+Date:   Tue Oct 18 10:08:31 2005 -0400
+
+    [PATCH] Missing transfer_flags setting in usbtest
+    
+    This patch (as582) adds a missing transfer_flags setting to the usbtest
+    driver.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
+index d055196533af..90a96257d6ce 100644
+--- a/drivers/usb/misc/usbtest.c
++++ b/drivers/usb/misc/usbtest.c
+@@ -983,6 +983,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
+ 		reqp->number = i % NUM_SUBCASES;
+ 		reqp->expected = expected;
+ 		u->setup_packet = (char *) &reqp->setup;
++		u->transfer_flags |= URB_NO_SETUP_DMA_MAP;
+ 
+ 		u->context = &context;
+ 		u->complete = ctrl_complete;

commit f37be9b9be3ebc02d2d075d7f53f7802f3e005db
+Author: Alan Stern 
+Date:   Mon Oct 17 10:42:06 2005 -0400
+
+    [PATCH] Fix hcd->state assignments in uhci-hcd
+    
+    This patch (as581) changes the assignments to hcd->state in the uhci-hcd
+    driver.  It fixes part of bugzilla entry #5227.  The problem was revealed
+    by David's large suite of USB suspend/resume patches; this patch should go
+    to Linus at the same time those do.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 72cd1576d20c..d33ce3982a5f 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -161,8 +161,8 @@ static void configure_hc(struct uhci_hcd *uhci)
+ 	/* Set the current frame number */
+ 	outw(uhci->frame_number, uhci->io_addr + USBFRNUM);
+ 
+-	/* Mark controller as running before we enable interrupts */
+-	uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;
++	/* Mark controller as not halted before we enable interrupts */
++	uhci_to_hcd(uhci)->state = HC_STATE_SUSPENDED;
+ 	mb();
+ 
+ 	/* Enable PIRQ */
+@@ -263,6 +263,7 @@ __acquires(uhci->lock)
+ 
+ static void start_rh(struct uhci_hcd *uhci)
+ {
++	uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;
+ 	uhci->is_stopped = 0;
+ 	smp_wmb();
+ 
+@@ -708,7 +709,6 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
+ 
+ 	if (uhci->rh_state > UHCI_RH_SUSPENDED) {
+ 		dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n");
+-		hcd->state = HC_STATE_RUNNING;
+ 		rc = -EBUSY;
+ 		goto done;
+ 	};

commit b81d34363c0b17c47f4ef63d5888c4f47f315d29
+Author: Alan Stern 
+Date:   Thu Oct 13 17:00:24 2005 -0400
+
+    [PATCH] UHCI: Improve handling of iso TDs
+    
+    The uhci-hcd driver is fairly lax about the way it handles isochronous
+    transfers.  This patch (as579) improves it in three respects:
+    
+            TDs for a new URB aren't added to the schedule until all of
+            them have been allocated.  This way there's no risk of the
+            controller executing some of them when an allocation fails.
+    
+            TDs for an unlinked URB are removed from the schedule as soon
+            as the URB is unlinked, rather than waiting until the URB is
+            given back.  This way there's no risk of the controller still
+            executing a TD after the URB completes.
+    
+            The urb->error_count values are now reported correctly.
+            Although since they aren't used in any drivers except for
+            debug messages in the system log, probably nobody cares.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 51de06bc438d..7e46887d9e12 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -108,13 +108,16 @@ static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td,
+ 	}
+ }
+ 
+-static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td)
++static inline void uhci_remove_td_frame_list(struct uhci_hcd *uhci,
++		struct uhci_td *td)
+ {
+ 	/* If it's not inserted, don't remove it */
+-	if (td->frame == -1 && list_empty(&td->fl_list))
++	if (td->frame == -1) {
++		WARN_ON(!list_empty(&td->fl_list));
+ 		return;
++	}
+ 
+-	if (td->frame != -1 && uhci->frame_cpu[td->frame] == td) {
++	if (uhci->frame_cpu[td->frame] == td) {
+ 		if (list_empty(&td->fl_list)) {
+ 			uhci->frame[td->frame] = td->link;
+ 			uhci->frame_cpu[td->frame] = NULL;
+@@ -132,13 +135,20 @@ static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td)
+ 		ptd->link = td->link;
+ 	}
+ 
+-	wmb();
+-	td->link = UHCI_PTR_TERM;
+-
+ 	list_del_init(&td->fl_list);
+ 	td->frame = -1;
+ }
+ 
++static void unlink_isochronous_tds(struct uhci_hcd *uhci, struct urb *urb)
++{
++	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
++	struct uhci_td *td;
++
++	list_for_each_entry(td, &urbp->td_list, list)
++		uhci_remove_td_frame_list(uhci, td);
++	wmb();
++}
++
+ /*
+  * Inserts a td list into qh.
+  */
+@@ -498,7 +508,6 @@ static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
+ 
+ 	list_for_each_entry_safe(td, tmp, &urbp->td_list, list) {
+ 		uhci_remove_td_from_urb(td);
+-		uhci_remove_td(uhci, td);
+ 		list_add(&td->remove_list, &uhci->td_remove_list);
+ 	}
+ 
+@@ -1068,6 +1077,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
+ 	struct uhci_td *td;
+ 	int i, ret, frame;
+ 	int status, destination;
++	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
+ 
+ 	status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
+ 	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
+@@ -1076,11 +1086,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
+ 	if (ret)
+ 		return ret;
+ 
+-	frame = urb->start_frame;
+-	for (i = 0; i < urb->number_of_packets; i++, frame += urb->interval) {
+-		if (!urb->iso_frame_desc[i].length)
+-			continue;
+-
++	for (i = 0; i < urb->number_of_packets; i++) {
+ 		td = uhci_alloc_td(uhci);
+ 		if (!td)
+ 			return -ENOMEM;
+@@ -1091,8 +1097,12 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
+ 
+ 		if (i + 1 >= urb->number_of_packets)
+ 			td->status |= cpu_to_le32(TD_CTRL_IOC);
++	}
+ 
++	frame = urb->start_frame;
++	list_for_each_entry(td, &urbp->td_list, list) {
+ 		uhci_insert_td_frame_list(uhci, td, frame);
++		frame += urb->interval;
+ 	}
+ 
+ 	return -EINPROGRESS;
+@@ -1105,7 +1115,7 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb)
+ 	int status;
+ 	int i, ret = 0;
+ 
+-	urb->actual_length = 0;
++	urb->actual_length = urb->error_count = 0;
+ 
+ 	i = 0;
+ 	list_for_each_entry(td, &urbp->td_list, list) {
+@@ -1129,6 +1139,7 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb)
+ 
+ 		i++;
+ 	}
++	unlink_isochronous_tds(uhci, urb);
+ 
+ 	return ret;
+ }
+@@ -1361,6 +1372,8 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
+ 		goto done;
+ 	list_del_init(&urbp->urb_list);
+ 
++	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
++		unlink_isochronous_tds(uhci, urb);
+ 	uhci_unlink_generic(uhci, urb);
+ 
+ 	uhci_get_current_frame_number(uhci);

commit 0c0382e32d46f606951010b202382be14d180a17
+Author: Alan Stern 
+Date:   Thu Oct 13 17:08:02 2005 -0400
+
+    [PATCH] USB: Rename hcd->hub_suspend to hcd->bus_suspend
+    
+    This patch (as580) is perhaps the only result from the long discussion I
+    had with David about his changes to the root-hub suspend/resume code.  It
+    renames the hub_suspend and hub_resume methods in struct usb_hcd to
+    bus_suspend and bus_resume.  These are more descriptive names, since the
+    methods really do suspend or resume an entire USB bus, and less likely to
+    be confused with the hub_suspend and hub_resume routines in hub.c.
+    
+    It also takes David's advice about removing the layer of bus glue, where
+    those methods are called.  And it implements a related change that David
+    made to the other HCDs but forgot to put into dummy_hcd.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index b7bb8dd1894a..9ad3912a5ed7 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1433,16 +1433,16 @@ hcd_endpoint_disable (struct usb_device *udev, struct usb_host_endpoint *ep)
+ 
+ #ifdef	CONFIG_PM
+ 
+-static int hcd_hub_suspend (struct usb_bus *bus)
++int hcd_bus_suspend (struct usb_bus *bus)
+ {
+ 	struct usb_hcd		*hcd;
+ 	int			status;
+ 
+ 	hcd = container_of (bus, struct usb_hcd, self);
+-	if (!hcd->driver->hub_suspend)
++	if (!hcd->driver->bus_suspend)
+ 		return -ENOENT;
+ 	hcd->state = HC_STATE_QUIESCING;
+-	status = hcd->driver->hub_suspend (hcd);
++	status = hcd->driver->bus_suspend (hcd);
+ 	if (status == 0)
+ 		hcd->state = HC_STATE_SUSPENDED;
+ 	else
+@@ -1451,18 +1451,18 @@ static int hcd_hub_suspend (struct usb_bus *bus)
+ 	return status;
+ }
+ 
+-static int hcd_hub_resume (struct usb_bus *bus)
++int hcd_bus_resume (struct usb_bus *bus)
+ {
+ 	struct usb_hcd		*hcd;
+ 	int			status;
+ 
+ 	hcd = container_of (bus, struct usb_hcd, self);
+-	if (!hcd->driver->hub_resume)
++	if (!hcd->driver->bus_resume)
+ 		return -ENOENT;
+ 	if (hcd->state == HC_STATE_RUNNING)
+ 		return 0;
+ 	hcd->state = HC_STATE_RESUMING;
+-	status = hcd->driver->hub_resume (hcd);
++	status = hcd->driver->bus_resume (hcd);
+ 	if (status == 0)
+ 		hcd->state = HC_STATE_RUNNING;
+ 	else {
+@@ -1590,10 +1590,6 @@ static struct usb_operations usb_hcd_operations = {
+ 	.buffer_alloc =		hcd_buffer_alloc,
+ 	.buffer_free =		hcd_buffer_free,
+ 	.disable =		hcd_endpoint_disable,
+-#ifdef	CONFIG_PM
+-	.hub_suspend =		hcd_hub_suspend,
+-	.hub_resume =		hcd_hub_resume,
+-#endif
+ };
+ 
+ /*-------------------------------------------------------------------------*/
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index 74757fc1a99f..d8f0d29a45b7 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -154,10 +154,6 @@ struct usb_operations {
+ 
+ 	void (*disable)(struct usb_device *udev,
+ 			struct usb_host_endpoint *ep);
+-
+-	/* global suspend/resume of bus */
+-	int (*hub_suspend)(struct usb_bus *);
+-	int (*hub_resume)(struct usb_bus *);
+ };
+ 
+ /* each driver provides one of these, and hardware init support */
+@@ -212,8 +208,8 @@ struct hc_driver {
+ 	int		(*hub_control) (struct usb_hcd *hcd,
+ 				u16 typeReq, u16 wValue, u16 wIndex,
+ 				char *buf, u16 wLength);
+-	int		(*hub_suspend)(struct usb_hcd *);
+-	int		(*hub_resume)(struct usb_hcd *);
++	int		(*bus_suspend)(struct usb_hcd *);
++	int		(*bus_resume)(struct usb_hcd *);
+ 	int		(*start_port_reset)(struct usb_hcd *, unsigned port_num);
+ 	void		(*hub_irq_enable)(struct usb_hcd *);
+ 		/* Needed only if port-change IRQs are level-triggered */
+@@ -379,6 +375,21 @@ extern int usb_find_interface_driver (struct usb_device *dev,
+ 
+ #define usb_endpoint_out(ep_dir)	(!((ep_dir) & USB_DIR_IN))
+ 
++#ifdef CONFIG_PM
++extern int hcd_bus_suspend (struct usb_bus *bus);
++extern int hcd_bus_resume (struct usb_bus *bus);
++#else
++static inline int hcd_bus_suspend(struct usb_bus *bus)
++{
++	return 0;
++}
++
++static inline int hcd_bus_resume (struct usb_bus *bus)
++{
++	return 0;
++}
++#endif /* CONFIG_PM */
++
+ /*
+  * USB device fs stuff
+  */
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index e2802bf18095..273e6ccca213 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1917,8 +1917,8 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+ 	/* "global suspend" of the downstream HC-to-USB interface */
+ 	if (!hdev->parent) {
+ 		struct usb_bus	*bus = hdev->bus;
+-		if (bus && bus->op->hub_suspend) {
+-			int	status = bus->op->hub_suspend (bus);
++		if (bus) {
++			int	status = hcd_bus_suspend (bus);
+ 
+ 			if (status != 0) {
+ 				dev_dbg(&hdev->dev, "'global' suspend %d\n",
+@@ -1943,8 +1943,8 @@ static int hub_resume(struct usb_interface *intf)
+ 	/* "global resume" of the downstream HC-to-USB interface */
+ 	if (!hdev->parent) {
+ 		struct usb_bus	*bus = hdev->bus;
+-		if (bus && bus->op->hub_resume) {
+-			status = bus->op->hub_resume (bus);
++		if (bus) {
++			status = hcd_bus_resume (bus);
+ 			if (status) {
+ 				dev_dbg(&intf->dev, "'global' resume %d\n",
+ 					status);
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index 503201764f6b..c605aaeed636 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -1751,7 +1751,7 @@ static int dummy_hub_control (
+ 	return retval;
+ }
+ 
+-static int dummy_hub_suspend (struct usb_hcd *hcd)
++static int dummy_bus_suspend (struct usb_hcd *hcd)
+ {
+ 	struct dummy *dum = hcd_to_dummy (hcd);
+ 
+@@ -1762,7 +1762,7 @@ static int dummy_hub_suspend (struct usb_hcd *hcd)
+ 	return 0;
+ }
+ 
+-static int dummy_hub_resume (struct usb_hcd *hcd)
++static int dummy_bus_resume (struct usb_hcd *hcd)
+ {
+ 	struct dummy *dum = hcd_to_dummy (hcd);
+ 
+@@ -1894,8 +1894,8 @@ static const struct hc_driver dummy_hcd = {
+ 
+ 	.hub_status_data = 	dummy_hub_status,
+ 	.hub_control = 		dummy_hub_control,
+-	.hub_suspend =		dummy_hub_suspend,
+-	.hub_resume =		dummy_hub_resume,
++	.bus_suspend =		dummy_bus_suspend,
++	.bus_resume =		dummy_bus_resume,
+ };
+ 
+ static int dummy_hcd_probe (struct device *dev)
+@@ -1936,13 +1936,6 @@ static int dummy_hcd_suspend (struct device *dev, pm_message_t state)
+ 	dev_dbg (dev, "%s\n", __FUNCTION__);
+ 	hcd = dev_get_drvdata (dev);
+ 
+-#ifndef CONFIG_USB_SUSPEND
+-	/* Otherwise this would never happen */
+-	usb_lock_device (hcd->self.root_hub);
+-	dummy_hub_suspend (hcd);
+-	usb_unlock_device (hcd->self.root_hub);
+-#endif
+-
+ 	hcd->state = HC_STATE_SUSPENDED;
+ 	return 0;
+ }
+@@ -1955,13 +1948,6 @@ static int dummy_hcd_resume (struct device *dev)
+ 	hcd = dev_get_drvdata (dev);
+ 	hcd->state = HC_STATE_RUNNING;
+ 
+-#ifndef CONFIG_USB_SUSPEND
+-	/* Otherwise this would never happen */
+-	usb_lock_device (hcd->self.root_hub);
+-	dummy_hub_resume (hcd);
+-	usb_unlock_device (hcd->self.root_hub);
+-#endif
+-
+ 	usb_hcd_poll_rh_status (hcd);
+ 	return 0;
+ }
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 18d3f2270316..88cb4ada686e 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -30,7 +30,7 @@
+ 
+ #ifdef	CONFIG_PM
+ 
+-static int ehci_hub_suspend (struct usb_hcd *hcd)
++static int ehci_bus_suspend (struct usb_hcd *hcd)
+ {
+ 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+ 	int			port;
+@@ -83,7 +83,7 @@ static int ehci_hub_suspend (struct usb_hcd *hcd)
+ 
+ 
+ /* caller has locked the root hub, and should reset/reinit on error */
+-static int ehci_hub_resume (struct usb_hcd *hcd)
++static int ehci_bus_resume (struct usb_hcd *hcd)
+ {
+ 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+ 	u32			temp;
+@@ -159,8 +159,8 @@ static int ehci_hub_resume (struct usb_hcd *hcd)
+ 
+ #else
+ 
+-#define ehci_hub_suspend	NULL
+-#define ehci_hub_resume		NULL
++#define ehci_bus_suspend	NULL
++#define ehci_bus_resume		NULL
+ 
+ #endif	/* CONFIG_PM */
+ 
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index 66ebf75b2037..8bbc8dfe19f3 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -363,8 +363,8 @@ static const struct hc_driver ehci_pci_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ehci_hub_status_data,
+ 	.hub_control =		ehci_hub_control,
+-	.hub_suspend =		ehci_hub_suspend,
+-	.hub_resume =		ehci_hub_resume,
++	.bus_suspend =		ehci_bus_suspend,
++	.bus_resume =		ehci_bus_resume,
+ };
+ 
+ /*-------------------------------------------------------------------------*/
+diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
+index f68220fc53fd..ddb8fc591466 100644
+--- a/drivers/usb/host/isp116x-hcd.c
++++ b/drivers/usb/host/isp116x-hcd.c
+@@ -1160,7 +1160,7 @@ static int isp116x_hub_control(struct usb_hcd *hcd,
+ 
+ #ifdef	CONFIG_PM
+ 
+-static int isp116x_hub_suspend(struct usb_hcd *hcd)
++static int isp116x_bus_suspend(struct usb_hcd *hcd)
+ {
+ 	struct isp116x *isp116x = hcd_to_isp116x(hcd);
+ 	unsigned long flags;
+@@ -1200,7 +1200,7 @@ static int isp116x_hub_suspend(struct usb_hcd *hcd)
+ 	return ret;
+ }
+ 
+-static int isp116x_hub_resume(struct usb_hcd *hcd)
++static int isp116x_bus_resume(struct usb_hcd *hcd)
+ {
+ 	struct isp116x *isp116x = hcd_to_isp116x(hcd);
+ 	u32 val;
+@@ -1266,8 +1266,8 @@ static int isp116x_hub_resume(struct usb_hcd *hcd)
+ 
+ #else
+ 
+-#define	isp116x_hub_suspend	NULL
+-#define	isp116x_hub_resume	NULL
++#define	isp116x_bus_suspend	NULL
++#define	isp116x_bus_resume	NULL
+ 
+ #endif
+ 
+@@ -1626,8 +1626,8 @@ static struct hc_driver isp116x_hc_driver = {
+ 
+ 	.hub_status_data = isp116x_hub_status_data,
+ 	.hub_control = isp116x_hub_control,
+-	.hub_suspend = isp116x_hub_suspend,
+-	.hub_resume = isp116x_hub_resume,
++	.bus_suspend = isp116x_bus_suspend,
++	.bus_resume = isp116x_bus_resume,
+ };
+ 
+ /*----------------------------------------------------------------*/
+diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
+index 550d67a554f6..ac463c493035 100644
+--- a/drivers/usb/host/ohci-au1xxx.c
++++ b/drivers/usb/host/ohci-au1xxx.c
+@@ -215,8 +215,8 @@ static const struct hc_driver ohci_au1xxx_hc_driver = {
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+ #ifdef	CONFIG_PM
+-	.hub_suspend =		ohci_hub_suspend,
+-	.hub_resume =		ohci_hub_resume,
++	.bus_suspend =		ohci_bus_suspend,
++	.bus_resume =		ohci_bus_resume,
+ #endif
+ 	.start_port_reset =	ohci_start_port_reset,
+ };
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index 39a60e731ec2..e01e77bc324b 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -45,7 +45,7 @@ static void dl_done_list (struct ohci_hcd *, struct pt_regs *);
+ static void finish_unlinks (struct ohci_hcd *, u16 , struct pt_regs *);
+ static int ohci_restart (struct ohci_hcd *ohci);
+ 
+-static int ohci_hub_suspend (struct usb_hcd *hcd)
++static int ohci_bus_suspend (struct usb_hcd *hcd)
+ {
+ 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+ 	int			status = 0;
+@@ -135,7 +135,7 @@ static inline struct ed *find_head (struct ed *ed)
+ }
+ 
+ /* caller has locked the root hub */
+-static int ohci_hub_resume (struct usb_hcd *hcd)
++static int ohci_bus_resume (struct usb_hcd *hcd)
+ {
+ 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+ 	u32			temp, enables;
+@@ -362,7 +362,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
+ 			&& usb_trylock_device (hcd->self.root_hub)
+ 			) {
+ 		ohci_vdbg (ohci, "autosuspend\n");
+-		(void) ohci_hub_suspend (hcd);
++		(void) ohci_bus_suspend (hcd);
+ 		usb_unlock_device (hcd->self.root_hub);
+ 	}
+ #endif
+diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c
+index 71d975ae78bd..e2ed55b69f86 100644
+--- a/drivers/usb/host/ohci-lh7a404.c
++++ b/drivers/usb/host/ohci-lh7a404.c
+@@ -194,8 +194,8 @@ static const struct hc_driver ohci_lh7a404_hc_driver = {
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+ #ifdef	CONFIG_PM
+-	.hub_suspend =		ohci_hub_suspend,
+-	.hub_resume =		ohci_hub_resume,
++	.bus_suspend =		ohci_bus_suspend,
++	.bus_resume =		ohci_bus_resume,
+ #endif
+ 	.start_port_reset =	ohci_start_port_reset,
+ };
+diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
+index b3498b9b965f..982cdca22516 100644
+--- a/drivers/usb/host/ohci-omap.c
++++ b/drivers/usb/host/ohci-omap.c
+@@ -421,8 +421,8 @@ static const struct hc_driver ohci_omap_hc_driver = {
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+ #ifdef	CONFIG_PM
+-	.hub_suspend =		ohci_hub_suspend,
+-	.hub_resume =		ohci_hub_resume,
++	.bus_suspend =		ohci_bus_suspend,
++	.bus_resume =		ohci_bus_resume,
+ #endif
+ 	.start_port_reset =	ohci_start_port_reset,
+ };
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index 99a0ad41aec5..a8dde8b75691 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -195,8 +195,8 @@ static const struct hc_driver ohci_pci_hc_driver = {
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+ #ifdef	CONFIG_PM
+-	.hub_suspend =		ohci_hub_suspend,
+-	.hub_resume =		ohci_hub_resume,
++	.bus_suspend =		ohci_bus_suspend,
++	.bus_resume =		ohci_bus_resume,
+ #endif
+ 	.start_port_reset =	ohci_start_port_reset,
+ };
+diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
+index ec20710e99fe..228845eb7eab 100644
+--- a/drivers/usb/host/ohci-ppc-soc.c
++++ b/drivers/usb/host/ohci-ppc-soc.c
+@@ -164,8 +164,8 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = {
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+ #ifdef	CONFIG_PM
+-	.hub_suspend =		ohci_hub_suspend,
+-	.hub_resume =		ohci_hub_resume,
++	.bus_suspend =		ohci_bus_suspend,
++	.bus_resume =		ohci_bus_resume,
+ #endif
+ 	.start_port_reset =	ohci_start_port_reset,
+ };
+diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
+index 2e7b48502a3d..d287dcccd415 100644
+--- a/drivers/usb/host/ohci-pxa27x.c
++++ b/drivers/usb/host/ohci-pxa27x.c
+@@ -279,8 +279,8 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+ #ifdef  CONFIG_PM
+-	.hub_suspend =		ohci_hub_suspend,
+-	.hub_resume =		ohci_hub_resume,
++	.bus_suspend =		ohci_bus_suspend,
++	.bus_resume =		ohci_bus_resume,
+ #endif
+ 	.start_port_reset =	ohci_start_port_reset,
+ };
+diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
+index 922e2a6f46ef..3225d455f459 100644
+--- a/drivers/usb/host/ohci-s3c2410.c
++++ b/drivers/usb/host/ohci-s3c2410.c
+@@ -449,8 +449,8 @@ static const struct hc_driver ohci_s3c2410_hc_driver = {
+ 	.hub_status_data =	ohci_s3c2410_hub_status_data,
+ 	.hub_control =		ohci_s3c2410_hub_control,
+ #ifdef	CONFIG_PM
+-	.hub_suspend =		ohci_hub_suspend,
+-	.hub_resume =		ohci_hub_resume,
++	.bus_suspend =		ohci_bus_suspend,
++	.bus_resume =		ohci_bus_resume,
+ #endif
+ 	.start_port_reset =	ohci_start_port_reset,
+ };
+diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
+index 13324b7f9c59..fb3221ebbb29 100644
+--- a/drivers/usb/host/ohci-sa1111.c
++++ b/drivers/usb/host/ohci-sa1111.c
+@@ -236,8 +236,8 @@ static const struct hc_driver ohci_sa1111_hc_driver = {
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+ #ifdef	CONFIG_PM
+-	.hub_suspend =		ohci_hub_suspend,
+-	.hub_resume =		ohci_hub_resume,
++	.bus_suspend =		ohci_bus_suspend,
++	.bus_resume =		ohci_bus_resume,
+ #endif
+ 	.start_port_reset =	ohci_start_port_reset,
+ };
+diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
+index b5e7a478bc01..1e47c1f86e70 100644
+--- a/drivers/usb/host/sl811-hcd.c
++++ b/drivers/usb/host/sl811-hcd.c
+@@ -1363,7 +1363,7 @@ sl811h_hub_control(
+ #ifdef	CONFIG_PM
+ 
+ static int
+-sl811h_hub_suspend(struct usb_hcd *hcd)
++sl811h_bus_suspend(struct usb_hcd *hcd)
+ {
+ 	// SOFs off
+ 	DBG("%s\n", __FUNCTION__);
+@@ -1371,7 +1371,7 @@ sl811h_hub_suspend(struct usb_hcd *hcd)
+ }
+ 
+ static int
+-sl811h_hub_resume(struct usb_hcd *hcd)
++sl811h_bus_resume(struct usb_hcd *hcd)
+ {
+ 	// SOFs on
+ 	DBG("%s\n", __FUNCTION__);
+@@ -1380,8 +1380,8 @@ sl811h_hub_resume(struct usb_hcd *hcd)
+ 
+ #else
+ 
+-#define	sl811h_hub_suspend	NULL
+-#define	sl811h_hub_resume	NULL
++#define	sl811h_bus_suspend	NULL
++#define	sl811h_bus_resume	NULL
+ 
+ #endif
+ 
+@@ -1623,8 +1623,8 @@ static struct hc_driver sl811h_hc_driver = {
+ 	 */
+ 	.hub_status_data =	sl811h_hub_status_data,
+ 	.hub_control =		sl811h_hub_control,
+-	.hub_suspend =		sl811h_hub_suspend,
+-	.hub_resume =		sl811h_hub_resume,
++	.bus_suspend =		sl811h_bus_suspend,
++	.bus_resume =		sl811h_bus_resume,
+ };
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -1791,7 +1791,7 @@ sl811h_suspend(struct device *dev, pm_message_t state)
+ 	int		retval = 0;
+ 
+ 	if (state.event == PM_EVENT_FREEZE)
+-		retval = sl811h_hub_suspend(hcd);
++		retval = sl811h_bus_suspend(hcd);
+ 	else if (state.event == PM_EVENT_SUSPEND)
+ 		port_power(sl811, 0);
+ 	if (retval == 0)
+@@ -1816,7 +1816,7 @@ sl811h_resume(struct device *dev)
+ 	}
+ 
+ 	dev->power.power_state = PMSG_ON;
+-	return sl811h_hub_resume(hcd);
++	return sl811h_bus_resume(hcd);
+ }
+ 
+ #else
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 6df555e3d97c..72cd1576d20c 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -804,8 +804,8 @@ static const struct hc_driver uhci_driver = {
+ #ifdef CONFIG_PM
+ 	.suspend =		uhci_suspend,
+ 	.resume =		uhci_resume,
+-	.hub_suspend =		uhci_rh_suspend,
+-	.hub_resume =		uhci_rh_resume,
++	.bus_suspend =		uhci_rh_suspend,
++	.bus_resume =		uhci_rh_resume,
+ #endif
+ 	.stop =			uhci_stop,
+ 

commit bb200f6eac6372839921be1fe87c1f5c292a7bd6
+Author: Alan Stern 
+Date:   Mon Oct 3 16:36:29 2005 -0400
+
+    [PATCH] UHCI: unify BIOS handoff and driver reset code
+    
+    This patch (as574) updates the PCI BIOS usb-handoff code for UHCI
+    controllers, making it work like the reset routines in uhci-hcd.  This
+    allows uhci-hcd to drop its own routines in favor of the new ones
+    (code-sharing).
+    
+    Once the patch is merged we can turn the usb-handoff option on
+    permanently, as far as UHCI is concerned.  OHCI and EHCI may still have
+    some issues.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
+index 49f7381a6fd3..f7411ca48835 100644
+--- a/drivers/usb/host/pci-quirks.c
++++ b/drivers/usb/host/pci-quirks.c
+@@ -9,6 +9,12 @@
+  */
+ 
+ #include 
++#ifdef CONFIG_USB_DEBUG
++#define DEBUG
++#else
++#undef DEBUG
++#endif
++
+ #include 
+ #include 
+ #include 
+@@ -46,13 +52,14 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371AB_2,	qui
+ 
+ #define UHCI_USBLEGSUP		0xc0		/* legacy support */
+ #define UHCI_USBCMD		0		/* command register */
+-#define UHCI_USBSTS		2		/* status register */
+ #define UHCI_USBINTR		4		/* interrupt register */
+-#define UHCI_USBLEGSUP_DEFAULT	0x2000		/* only PIRQ enable set */
+-#define UHCI_USBCMD_RUN		(1 << 0)	/* RUN/STOP bit */
+-#define UHCI_USBCMD_GRESET	(1 << 2)	/* Global reset */
+-#define UHCI_USBCMD_CONFIGURE	(1 << 6)	/* config semaphore */
+-#define UHCI_USBSTS_HALTED	(1 << 5)	/* HCHalted bit */
++#define UHCI_USBLEGSUP_RWC	0x8f00		/* the R/WC bits */
++#define UHCI_USBLEGSUP_RO	0x5040		/* R/O and reserved bits */
++#define UHCI_USBCMD_RUN		0x0001		/* RUN/STOP bit */
++#define UHCI_USBCMD_HCRESET	0x0002		/* Host Controller reset */
++#define UHCI_USBCMD_EGSM	0x0008		/* Global Suspend Mode */
++#define UHCI_USBCMD_CONFIGURE	0x0040		/* Config Flag */
++#define UHCI_USBINTR_RESUME	0x0002		/* Resume interrupt enable */
+ 
+ #define OHCI_CONTROL		0x04
+ #define OHCI_CMDSTATUS		0x08
+@@ -84,57 +91,100 @@ static int __init usb_handoff_early(char *str)
+ }
+ __setup("usb-handoff", usb_handoff_early);
+ 
+-static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev)
++/*
++ * Make sure the controller is completely inactive, unable to
++ * generate interrupts or do DMA.
++ */
++void uhci_reset_hc(struct pci_dev *pdev, unsigned long base)
+ {
+-	unsigned long base = 0;
+-	int wait_time, delta;
+-	u16 val, sts;
+-	int i;
++	/* Turn off PIRQ enable and SMI enable.  (This also turns off the
++	 * BIOS's USB Legacy Support.)  Turn off all the R/WC bits too.
++	 */
++	pci_write_config_word(pdev, UHCI_USBLEGSUP, UHCI_USBLEGSUP_RWC);
+ 
+-	for (i = 0; i < PCI_ROM_RESOURCE; i++)
+-		if ((pci_resource_flags(pdev, i) & IORESOURCE_IO)) {
+-			base = pci_resource_start(pdev, i);
+-			break;
+-		}
++	/* Reset the HC - this will force us to get a
++	 * new notification of any already connected
++	 * ports due to the virtual disconnect that it
++	 * implies.
++	 */
++	outw(UHCI_USBCMD_HCRESET, base + UHCI_USBCMD);
++	mb();
++	udelay(5);
++	if (inw(base + UHCI_USBCMD) & UHCI_USBCMD_HCRESET)
++		dev_warn(&pdev->dev, "HCRESET not completed yet!\n");
++
++	/* Just to be safe, disable interrupt requests and
++	 * make sure the controller is stopped.
++	 */
++	outw(0, base + UHCI_USBINTR);
++	outw(0, base + UHCI_USBCMD);
++}
++EXPORT_SYMBOL_GPL(uhci_reset_hc);
+ 
+-	if (!base)
+-		return;
++/*
++ * Initialize a controller that was newly discovered or has just been
++ * resumed.  In either case we can't be sure of its previous state.
++ *
++ * Returns: 1 if the controller was reset, 0 otherwise.
++ */
++int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base)
++{
++	u16 legsup;
++	unsigned int cmd, intr;
+ 
+ 	/*
+-	 * stop controller
++	 * When restarting a suspended controller, we expect all the
++	 * settings to be the same as we left them:
++	 *
++	 *	PIRQ and SMI disabled, no R/W bits set in USBLEGSUP;
++	 *	Controller is stopped and configured with EGSM set;
++	 *	No interrupts enabled except possibly Resume Detect.
++	 *
++	 * If any of these conditions are violated we do a complete reset.
+ 	 */
+-	sts = inw(base + UHCI_USBSTS);
+-	val = inw(base + UHCI_USBCMD);
+-	val &= ~(u16)(UHCI_USBCMD_RUN | UHCI_USBCMD_CONFIGURE);
+-	outw(val, base + UHCI_USBCMD);
++	pci_read_config_word(pdev, UHCI_USBLEGSUP, &legsup);
++	if (legsup & ~(UHCI_USBLEGSUP_RO | UHCI_USBLEGSUP_RWC)) {
++		dev_dbg(&pdev->dev, "%s: legsup = 0x%04x\n",
++				__FUNCTION__, legsup);
++		goto reset_needed;
++	}
+ 
+-	/*
+-	 * wait while it stops if it was running
+-	 */
+-	if ((sts & UHCI_USBSTS_HALTED) == 0)
+-	{
+-		wait_time = 1000;
+-		delta = 100;
++	cmd = inw(base + UHCI_USBCMD);
++	if ((cmd & UHCI_USBCMD_RUN) || !(cmd & UHCI_USBCMD_CONFIGURE) ||
++			!(cmd & UHCI_USBCMD_EGSM)) {
++		dev_dbg(&pdev->dev, "%s: cmd = 0x%04x\n",
++				__FUNCTION__, cmd);
++		goto reset_needed;
++	}
+ 
+-		do {
+-			outw(0x1f, base + UHCI_USBSTS);
+-			udelay(delta);
+-			wait_time -= delta;
+-			val = inw(base + UHCI_USBSTS);
+-			if (val & UHCI_USBSTS_HALTED)
+-				break;
+-		} while (wait_time > 0);
++	intr = inw(base + UHCI_USBINTR);
++	if (intr & (~UHCI_USBINTR_RESUME)) {
++		dev_dbg(&pdev->dev, "%s: intr = 0x%04x\n",
++				__FUNCTION__, intr);
++		goto reset_needed;
+ 	}
++	return 0;
+ 
+-	/*
+-	 * disable interrupts & legacy support
+-	 */
+-	outw(0, base + UHCI_USBINTR);
+-	outw(0x1f, base + UHCI_USBSTS);
+-	pci_read_config_word(pdev, UHCI_USBLEGSUP, &val);
+-	if (val & 0xbf)
+-		pci_write_config_word(pdev, UHCI_USBLEGSUP, UHCI_USBLEGSUP_DEFAULT);
++reset_needed:
++	dev_dbg(&pdev->dev, "Performing full reset\n");
++	uhci_reset_hc(pdev, base);
++	return 1;
++}
++EXPORT_SYMBOL_GPL(uhci_check_and_reset_hc);
++
++static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev)
++{
++	unsigned long base = 0;
++	int i;
++
++	for (i = 0; i < PCI_ROM_RESOURCE; i++)
++		if ((pci_resource_flags(pdev, i) & IORESOURCE_IO)) {
++			base = pci_resource_start(pdev, i);
++			break;
++		}
+ 
++	if (base)
++		uhci_check_and_reset_hc(pdev, base);
+ }
+ 
+ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 34c9dbc6a156..6df555e3d97c 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -101,37 +101,16 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
+ #include "uhci-q.c"
+ #include "uhci-hub.c"
+ 
++extern void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
++extern int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
++
+ /*
+- * Make sure the controller is completely inactive, unable to
+- * generate interrupts or do DMA.
++ * Finish up a host controller reset and update the recorded state.
+  */
+-static void reset_hc(struct uhci_hcd *uhci)
++static void finish_reset(struct uhci_hcd *uhci)
+ {
+ 	int port;
+ 
+-	/* Turn off PIRQ enable and SMI enable.  (This also turns off the
+-	 * BIOS's USB Legacy Support.)  Turn off all the R/WC bits too.
+-	 */
+-	pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
+-			USBLEGSUP_RWC);
+-
+-	/* Reset the HC - this will force us to get a
+-	 * new notification of any already connected
+-	 * ports due to the virtual disconnect that it
+-	 * implies.
+-	 */
+-	outw(USBCMD_HCRESET, uhci->io_addr + USBCMD);
+-	mb();
+-	udelay(5);
+-	if (inw(uhci->io_addr + USBCMD) & USBCMD_HCRESET)
+-		dev_warn(uhci_dev(uhci), "HCRESET not completed yet!\n");
+-
+-	/* Just to be safe, disable interrupt requests and
+-	 * make sure the controller is stopped.
+-	 */
+-	outw(0, uhci->io_addr + USBINTR);
+-	outw(0, uhci->io_addr + USBCMD);
+-
+ 	/* HCRESET doesn't affect the Suspend, Reset, and Resume Detect
+ 	 * bits in the port status and control registers.
+ 	 * We have to clear them by hand.
+@@ -153,7 +132,8 @@ static void reset_hc(struct uhci_hcd *uhci)
+  */
+ static void hc_died(struct uhci_hcd *uhci)
+ {
+-	reset_hc(uhci);
++	uhci_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr);
++	finish_reset(uhci);
+ 	uhci->hc_inaccessible = 1;
+ }
+ 
+@@ -163,44 +143,8 @@ static void hc_died(struct uhci_hcd *uhci)
+  */
+ static void check_and_reset_hc(struct uhci_hcd *uhci)
+ {
+-	u16 legsup;
+-	unsigned int cmd, intr;
+-
+-	/*
+-	 * When restarting a suspended controller, we expect all the
+-	 * settings to be the same as we left them:
+-	 *
+-	 *	PIRQ and SMI disabled, no R/W bits set in USBLEGSUP;
+-	 *	Controller is stopped and configured with EGSM set;
+-	 *	No interrupts enabled except possibly Resume Detect.
+-	 *
+-	 * If any of these conditions are violated we do a complete reset.
+-	 */
+-	pci_read_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, &legsup);
+-	if (legsup & ~(USBLEGSUP_RO | USBLEGSUP_RWC)) {
+-		dev_dbg(uhci_dev(uhci), "%s: legsup = 0x%04x\n",
+-				__FUNCTION__, legsup);
+-		goto reset_needed;
+-	}
+-
+-	cmd = inw(uhci->io_addr + USBCMD);
+-	if ((cmd & USBCMD_RS) || !(cmd & USBCMD_CF) || !(cmd & USBCMD_EGSM)) {
+-		dev_dbg(uhci_dev(uhci), "%s: cmd = 0x%04x\n",
+-				__FUNCTION__, cmd);
+-		goto reset_needed;
+-	}
+-
+-	intr = inw(uhci->io_addr + USBINTR);
+-	if (intr & (~USBINTR_RESUME)) {
+-		dev_dbg(uhci_dev(uhci), "%s: intr = 0x%04x\n",
+-				__FUNCTION__, intr);
+-		goto reset_needed;
+-	}
+-	return;
+-
+-reset_needed:
+-	dev_dbg(uhci_dev(uhci), "Performing full reset\n");
+-	reset_hc(uhci);
++	if (uhci_check_and_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr))
++		finish_reset(uhci);
+ }
+ 
+ /*
+@@ -714,7 +658,7 @@ static void uhci_stop(struct usb_hcd *hcd)
+ 
+ 	spin_lock_irq(&uhci->lock);
+ 	if (!uhci->hc_inaccessible)
+-		reset_hc(uhci);
++		hc_died(uhci);
+ 	uhci_scan_schedule(uhci, NULL);
+ 	spin_unlock_irq(&uhci->lock);
+ 

commit a922c68732725866c88457026cf06a7620846506
+Author: Alan Stern 
+Date:   Thu Oct 6 16:38:45 2005 -0400
+
+    [PATCH] g_file_storage: fix obscure race condition
+    
+    This patch (as575) fixes an unlikely race in the g_file_storage driver.
+    The problem can occur only when the driver is unbound before its
+    initialization routine has finished.
+    
+    I also took the opportunity to replace kmalloc/memset with kzalloc.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index 241c570e541c..86a6aeb9ed76 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -3823,12 +3823,11 @@ static int __init fsg_bind(struct usb_gadget *gadget)
+ 
+ 	/* Create the LUNs, open their backing files, and register the
+ 	 * LUN devices in sysfs. */
+-	fsg->luns = kmalloc(i * sizeof(struct lun), GFP_KERNEL);
++	fsg->luns = kzalloc(i * sizeof(struct lun), GFP_KERNEL);
+ 	if (!fsg->luns) {
+ 		rc = -ENOMEM;
+ 		goto out;
+ 	}
+-	memset(fsg->luns, 0, i * sizeof(struct lun));
+ 	fsg->nluns = i;
+ 
+ 	for (i = 0; i < fsg->nluns; ++i) {
+@@ -3989,6 +3988,11 @@ static int __init fsg_bind(struct usb_gadget *gadget)
+ 			mod_data.removable, mod_data.can_stall,
+ 			mod_data.buflen);
+ 	DBG(fsg, "I/O thread pid: %d\n", fsg->thread_task->pid);
++
++	set_bit(REGISTERED, &fsg->atomic_bitflags);
++
++	/* Tell the thread to start working */
++	wake_up_process(fsg->thread_task);
+ 	return 0;
+ 
+ autoconf_fail:
+@@ -4051,10 +4055,9 @@ static int __init fsg_alloc(void)
+ {
+ 	struct fsg_dev		*fsg;
+ 
+-	fsg = kmalloc(sizeof *fsg, GFP_KERNEL);
++	fsg = kzalloc(sizeof *fsg, GFP_KERNEL);
+ 	if (!fsg)
+ 		return -ENOMEM;
+-	memset(fsg, 0, sizeof *fsg);
+ 	spin_lock_init(&fsg->lock);
+ 	init_rwsem(&fsg->filesem);
+ 	init_waitqueue_head(&fsg->thread_wqh);
+@@ -4080,15 +4083,9 @@ static int __init fsg_init(void)
+ 	if ((rc = fsg_alloc()) != 0)
+ 		return rc;
+ 	fsg = the_fsg;
+-	if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0) {
++	if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0)
+ 		fsg_free(fsg);
+-		return rc;
+-	}
+-	set_bit(REGISTERED, &fsg->atomic_bitflags);
+-
+-	/* Tell the thread to start working */
+-	wake_up_process(fsg->thread_task);
+-	return 0;
++	return rc;
+ }
+ module_init(fsg_init);
+ 

commit 22efcf4adec4262e0f49e6225f6cd070e4a85d20
+Author: Alan Stern 
+Date:   Mon Sep 26 16:12:02 2005 -0400
+
+    [PATCH] USB: File-Storage gadget: use the kthread API
+    
+    This patch (as566) converts the File-Storage gadget over to the kthread
+    API.  The new code doesn't use kthread_stop because the control thread
+    needs to terminate asynchronously when it receives a signal.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+    
+     drivers/usb/gadget/file_storage.c |   32 +++++++++++++-------------------
+     1 file changed, 13 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index a41d9d4baee3..241c570e541c 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -224,6 +224,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -669,7 +670,6 @@ struct fsg_dev {
+ 	wait_queue_head_t	thread_wqh;
+ 	int			thread_wakeup_needed;
+ 	struct completion	thread_notifier;
+-	int			thread_pid;
+ 	struct task_struct	*thread_task;
+ 	sigset_t		thread_signal_mask;
+ 
+@@ -1084,7 +1084,6 @@ static void wakeup_thread(struct fsg_dev *fsg)
+ static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state)
+ {
+ 	unsigned long		flags;
+-	struct task_struct	*thread_task;
+ 
+ 	/* Do nothing if a higher-priority exception is already in progress.
+ 	 * If a lower-or-equal priority exception is in progress, preempt it
+@@ -1093,9 +1092,9 @@ static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state)
+ 	if (fsg->state <= new_state) {
+ 		fsg->exception_req_tag = fsg->ep0_req_tag;
+ 		fsg->state = new_state;
+-		thread_task = fsg->thread_task;
+-		if (thread_task)
+-			send_sig_info(SIGUSR1, SEND_SIG_FORCED, thread_task);
++		if (fsg->thread_task)
++			send_sig_info(SIGUSR1, SEND_SIG_FORCED,
++					fsg->thread_task);
+ 	}
+ 	spin_unlock_irqrestore(&fsg->lock, flags);
+ }
+@@ -3383,11 +3382,6 @@ static int fsg_main_thread(void *fsg_)
+ {
+ 	struct fsg_dev		*fsg = (struct fsg_dev *) fsg_;
+ 
+-	fsg->thread_task = current;
+-
+-	/* Release all our userspace resources */
+-	daemonize("file-storage-gadget");
+-
+ 	/* Allow the thread to be killed by a signal, but set the signal mask
+ 	 * to block everything but INT, TERM, KILL, and USR1. */
+ 	siginitsetinv(&fsg->thread_signal_mask, sigmask(SIGINT) |
+@@ -3400,9 +3394,6 @@ static int fsg_main_thread(void *fsg_)
+ 	 * that expects a __user pointer and it will work okay. */
+ 	set_fs(get_ds());
+ 
+-	/* Wait for the gadget registration to finish up */
+-	wait_for_completion(&fsg->thread_notifier);
+-
+ 	/* The main loop */
+ 	while (fsg->state != FSG_STATE_TERMINATED) {
+ 		if (exception_in_progress(fsg) || signal_pending(current)) {
+@@ -3440,8 +3431,9 @@ static int fsg_main_thread(void *fsg_)
+ 		spin_unlock_irq(&fsg->lock);
+ 		}
+ 
++	spin_lock_irq(&fsg->lock);
+ 	fsg->thread_task = NULL;
+-	flush_signals(current);
++	spin_unlock_irq(&fsg->lock);
+ 
+ 	/* In case we are exiting because of a signal, unregister the
+ 	 * gadget driver and close the backing file. */
+@@ -3959,10 +3951,12 @@ static int __init fsg_bind(struct usb_gadget *gadget)
+ 		sprintf(&serial[i], "%02X", c);
+ 	}
+ 
+-	if ((rc = kernel_thread(fsg_main_thread, fsg, (CLONE_VM | CLONE_FS |
+-			CLONE_FILES))) < 0)
++	fsg->thread_task = kthread_create(fsg_main_thread, fsg,
++			"file-storage-gadget");
++	if (IS_ERR(fsg->thread_task)) {
++		rc = PTR_ERR(fsg->thread_task);
+ 		goto out;
+-	fsg->thread_pid = rc;
++	}
+ 
+ 	INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
+ 	INFO(fsg, "Number of LUNs=%d\n", fsg->nluns);
+@@ -3994,7 +3988,7 @@ static int __init fsg_bind(struct usb_gadget *gadget)
+ 	DBG(fsg, "removable=%d, stall=%d, buflen=%u\n",
+ 			mod_data.removable, mod_data.can_stall,
+ 			mod_data.buflen);
+-	DBG(fsg, "I/O thread pid: %d\n", fsg->thread_pid);
++	DBG(fsg, "I/O thread pid: %d\n", fsg->thread_task->pid);
+ 	return 0;
+ 
+ autoconf_fail:
+@@ -4093,7 +4087,7 @@ static int __init fsg_init(void)
+ 	set_bit(REGISTERED, &fsg->atomic_bitflags);
+ 
+ 	/* Tell the thread to start working */
+-	complete(&fsg->thread_notifier);
++	wake_up_process(fsg->thread_task);
+ 	return 0;
+ }
+ module_init(fsg_init);

commit 8b262bd25580e165710e8a27df19cd60c2ef58a3
+Author: Alan Stern 
+Date:   Mon Sep 26 16:31:15 2005 -0400
+
+    [PATCH] USB: UHCI: Spruce up some comments
+    
+    This patch (as570) changes some comments in the uhci-hcd header file and
+    removes an unused declaration (something I forgot to erase in an earlier
+    patch).
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+    
+     drivers/usb/host/uhci-hcd.h |   91 +++++++++++++++++++++++---------------------
+     1 file changed, 49 insertions(+), 42 deletions(-)
+
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index b04d99df0a0e..e576db57a926 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -7,6 +7,7 @@
+ #define usb_packetid(pipe)	(usb_pipein(pipe) ? USB_PID_IN : USB_PID_OUT)
+ #define PIPE_DEVEP_MASK		0x0007ff00
+ 
++
+ /*
+  * Universal Host Controller Interface data structures and defines
+  */
+@@ -82,15 +83,10 @@
+ #define UHCI_MAX_SOF_NUMBER	2047	/* in an SOF packet */
+ #define CAN_SCHEDULE_FRAMES	1000	/* how far future frames can be scheduled */
+ 
+-struct uhci_frame_list {
+-	__le32 frame[UHCI_NUMFRAMES];
+-
+-	void *frame_cpu[UHCI_NUMFRAMES];
+ 
+-	dma_addr_t dma_handle;
+-};
+-
+-struct urb_priv;
++/*
++ *	Queue Headers
++ */
+ 
+ /*
+  * One role of a QH is to hold a queue of TDs for some endpoint.  Each QH is
+@@ -116,13 +112,13 @@ struct uhci_qh {
+ 
+ 	struct urb_priv *urbp;
+ 
+-	struct list_head list;		/* P: uhci->frame_list_lock */
+-	struct list_head remove_list;	/* P: uhci->remove_list_lock */
++	struct list_head list;
++	struct list_head remove_list;
+ } __attribute__((aligned(16)));
+ 
+ /*
+  * We need a special accessor for the element pointer because it is
+- * subject to asynchronous updates by the controller
++ * subject to asynchronous updates by the controller.
+  */
+ static __le32 inline qh_element(struct uhci_qh *qh) {
+ 	__le32 element = qh->element;
+@@ -131,6 +127,11 @@ static __le32 inline qh_element(struct uhci_qh *qh) {
+ 	return element;
+ }
+ 
++
++/*
++ *	Transfer Descriptors
++ */
++
+ /*
+  * for TD :
+  */
+@@ -183,17 +184,10 @@ static __le32 inline qh_element(struct uhci_qh *qh) {
+  *
+  * That's silly, the hardware doesn't care. The hardware only cares that
+  * the hardware words are 16-byte aligned, and we can have any amount of
+- * sw space after the TD entry as far as I can tell.
+- *
+- * But let's just go with the documentation, at least for 32-bit machines.
+- * On 64-bit machines we probably want to take advantage of the fact that
+- * hw doesn't really care about the size of the sw-only area.
+- *
+- * Alas, not anymore, we have more than 4 words for software, woops.
+- * Everything still works tho, surprise! -jerdfelt
++ * sw space after the TD entry.
+  *
+  * td->link points to either another TD (not necessarily for the same urb or
+- * even the same endpoint), or nothing (PTR_TERM), or a QH (for queued urbs)
++ * even the same endpoint), or nothing (PTR_TERM), or a QH (for queued urbs).
+  */
+ struct uhci_td {
+ 	/* Hardware fields */
+@@ -205,16 +199,16 @@ struct uhci_td {
+ 	/* Software fields */
+ 	dma_addr_t dma_handle;
+ 
+-	struct list_head list;		/* P: urb->lock */
+-	struct list_head remove_list;	/* P: uhci->td_remove_list_lock */
++	struct list_head list;
++	struct list_head remove_list;
+ 
+ 	int frame;			/* for iso: what frame? */
+-	struct list_head fl_list;	/* P: uhci->frame_list_lock */
++	struct list_head fl_list;
+ } __attribute__((aligned(16)));
+ 
+ /*
+  * We need a special accessor for the control/status word because it is
+- * subject to asynchronous updates by the controller
++ * subject to asynchronous updates by the controller.
+  */
+ static u32 inline td_status(struct uhci_td *td) {
+ 	__le32 status = td->status;
+@@ -224,6 +218,10 @@ static u32 inline td_status(struct uhci_td *td) {
+ }
+ 
+ 
++/*
++ *	Skeleton Queue Headers
++ */
++
+ /*
+  * The UHCI driver places Interrupt, Control and Bulk into QH's both
+  * to group together TD's for one transfer, and also to faciliate queuing
+@@ -254,15 +252,15 @@ static u32 inline td_status(struct uhci_td *td) {
+  *
+  * The terminating QH is used for 2 reasons:
+  * - To place a terminating TD which is used to workaround a PIIX bug
+- *   (see Intel errata for explanation)
++ *   (see Intel errata for explanation), and
+  * - To loop back to the full-speed control queue for full-speed bandwidth
+- *   reclamation
++ *   reclamation.
+  *
+  * Isochronous transfers are stored before the start of the skeleton
+  * schedule and don't use QH's. While the UHCI spec doesn't forbid the
+- * use of QH's for Isochronous, it doesn't use them either. Since we don't
+- * need to use them either, we follow the spec diagrams in hope that it'll
+- * be more compatible with future UHCI implementations.
++ * use of QH's for Isochronous, it doesn't use them either. And the spec
++ * says that queues never advance on an error completion status, which
++ * makes them totally unsuitable for Isochronous transfers.
+  */
+ 
+ #define UHCI_NUM_SKELQH		12
+@@ -312,8 +310,13 @@ static inline int __interval_to_skel(int interval)
+ 	return 0;				/* int128 for 128-255 ms (Max.) */
+ }
+ 
++
++/*
++ *	The UHCI controller and root hub
++ */
++
+ /*
+- * States for the root hub.
++ * States for the root hub:
+  *
+  * To prevent "bouncing" in the presence of electrical noise,
+  * when there are no devices attached we delay for 1 second in the
+@@ -324,7 +327,7 @@ static inline int __interval_to_skel(int interval)
+  */
+ enum uhci_rh_state {
+ 	/* In the following states the HC must be halted.
+-	 * These two must come first */
++	 * These two must come first. */
+ 	UHCI_RH_RESET,
+ 	UHCI_RH_SUSPENDED,
+ 
+@@ -336,13 +339,13 @@ enum uhci_rh_state {
+ 	UHCI_RH_SUSPENDING,
+ 
+ 	/* In the following states it's an error if the HC is halted.
+-	 * These two must come last */
++	 * These two must come last. */
+ 	UHCI_RH_RUNNING,		/* The normal state */
+ 	UHCI_RH_RUNNING_NODEVS,		/* Running with no devices attached */
+ };
+ 
+ /*
+- * This describes the full uhci information.
++ * The full UHCI controller information:
+  */
+ struct uhci_hcd {
+ 
+@@ -361,7 +364,7 @@ struct uhci_hcd {
+ 	spinlock_t lock;
+ 
+ 	dma_addr_t frame_dma_handle;		/* Hardware frame list */
+-	__le32 *frame;				/* P: uhci->lock */
++	__le32 *frame;
+ 	void **frame_cpu;			/* CPU's frame list */
+ 
+ 	int fsbr;				/* Full-speed bandwidth reclamation */
+@@ -387,22 +390,22 @@ struct uhci_hcd {
+ 	unsigned long ports_timeout;		/* Time to stop signalling */
+ 
+ 	/* Main list of URB's currently controlled by this HC */
+-	struct list_head urb_list;		/* P: uhci->lock */
++	struct list_head urb_list;
+ 
+ 	/* List of QH's that are done, but waiting to be unlinked (race) */
+-	struct list_head qh_remove_list;	/* P: uhci->lock */
++	struct list_head qh_remove_list;
+ 	unsigned int qh_remove_age;		/* Age in frames */
+ 
+ 	/* List of TD's that are done, but waiting to be freed (race) */
+-	struct list_head td_remove_list;	/* P: uhci->lock */
++	struct list_head td_remove_list;
+ 	unsigned int td_remove_age;		/* Age in frames */
+ 
+ 	/* List of asynchronously unlinked URB's */
+-	struct list_head urb_remove_list;	/* P: uhci->lock */
++	struct list_head urb_remove_list;
+ 	unsigned int urb_remove_age;		/* Age in frames */
+ 
+ 	/* List of URB's awaiting completion callback */
+-	struct list_head complete_list;		/* P: uhci->lock */
++	struct list_head complete_list;
+ 
+ 	int rh_numports;			/* Number of root-hub ports */
+ 
+@@ -421,13 +424,17 @@ static inline struct usb_hcd *uhci_to_hcd(struct uhci_hcd *uhci)
+ 
+ #define uhci_dev(u)	(uhci_to_hcd(u)->self.controller)
+ 
++
++/*
++ *	Private per-URB data
++ */
+ struct urb_priv {
+ 	struct list_head urb_list;
+ 
+ 	struct urb *urb;
+ 
+ 	struct uhci_qh *qh;		/* QH for this URB */
+-	struct list_head td_list;	/* P: urb->lock */
++	struct list_head td_list;
+ 
+ 	unsigned fsbr : 1;		/* URB turned on FSBR */
+ 	unsigned fsbr_timeout : 1;	/* URB timed out on FSBR */
+@@ -438,9 +445,10 @@ struct urb_priv {
+ 
+ 	unsigned long fsbrtime;		/* In jiffies */
+ 
+-	struct list_head queue_list;	/* P: uhci->frame_list_lock */
++	struct list_head queue_list;
+ };
+ 
++
+ /*
+  * Locking in uhci.c
+  *
+@@ -460,6 +468,5 @@ struct urb_priv {
+ 
+ #define PCI_VENDOR_ID_GENESYS		0x17a0
+ #define PCI_DEVICE_ID_GL880S_UHCI	0x8083
+-#define PCI_DEVICE_ID_GL880S_EHCI	0x8084
+ 
+ #endif

commit d09d36a91c70cb3cc609d693bf6a7e7a266ff9e6
+Author: Alan Stern 
+Date:   Mon Sep 26 16:22:45 2005 -0400
+
+    [PATCH] USB: usb_bulk_message() handles interrupts endpoints
+    
+    Because there is no bulk_interrupt_message() routine and no
+    USBDEVFS_INTERRUPT ioctl, people have been forced to abuse the
+    usb_bulk_message() routine and USBDEVFS_BULK by using them for interrupt
+    transfers as well as bulk transfers.
+    
+    This patch (as567) formalizes this practice and adds code to
+    usb_bulk_message() for detecting when the target is really an interrupt
+    endpoint.  If it is, the routine submits an interrupt URB (using the
+    default interval) instead of a bulk URB.  In theory this should help HCDs
+    that don't like it when people try to mix transfer types, queuing both
+    periodic and non-periodic types for the same endpoint.
+    
+    Not fully tested -- I don't have any programs that use USBDEVFS_BULK for
+    interrupt transfers -- but it compiles okay and normal bulk messages work
+    as well as before.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+    
+     drivers/usb/core/message.c |   24 ++++++++++++++++++++----
+     1 file changed, 20 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index ebf59ea99263..574d0d4b3401 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -187,21 +187,37 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u
+  *      If a thread in your driver uses this call, make sure your disconnect()
+  *      method can wait for it to complete.  Since you don't have a handle on
+  *      the URB used, you can't cancel the request.
++ *
++ *	Because there is no usb_interrupt_msg() and no USBDEVFS_INTERRUPT
++ *	ioctl, users are forced to abuse this routine by using it to submit
++ *	URBs for interrupt endpoints.  We will take the liberty of creating
++ *	an interrupt URB (with the default interval) if the target is an
++ *	interrupt endpoint.
+  */
+ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, 
+ 			void *data, int len, int *actual_length, int timeout)
+ {
+ 	struct urb *urb;
++	struct usb_host_endpoint *ep;
+ 
+-	if (len < 0)
++	ep = (usb_pipein(pipe) ? usb_dev->ep_in : usb_dev->ep_out)
++			[usb_pipeendpoint(pipe)];
++	if (!ep || len < 0)
+ 		return -EINVAL;
+ 
+-	urb=usb_alloc_urb(0, GFP_KERNEL);
++	urb = usb_alloc_urb(0, GFP_KERNEL);
+ 	if (!urb)
+ 		return -ENOMEM;
+ 
+-	usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
+-			  usb_api_blocking_completion, NULL);
++	if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
++			USB_ENDPOINT_XFER_INT) {
++		pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);
++		usb_fill_int_urb(urb, usb_dev, pipe, data, len,
++				usb_api_blocking_completion, NULL,
++				ep->desc.bInterval);
++	} else
++		usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
++				usb_api_blocking_completion, NULL);
+ 
+ 	return usb_start_wait_urb(urb, timeout, actual_length);
+ }

commit a1d59ce842a35b552f22868404e4e7c923242257
+Author: Alan Stern 
+Date:   Fri Sep 16 14:22:51 2005 -0400
+
+    [PATCH] USB: UHCI: Split apart the physical and logical framelist arrays
+    
+    This patch (as563) splits the physical and logical framelist arrays in
+    uhci-hcd into two separate pieces.  This will allow slightly better memory
+    utilization, since each piece is no larger than a single page whereas
+    before the whole thing was a little bigger than two pages.  It also allows
+    the logical array to be allocated in non-DMA-coherent memory.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
+index 04eddd7995c3..151154df37fa 100644
+--- a/drivers/usb/host/uhci-debug.c
++++ b/drivers/usb/host/uhci-debug.c
+@@ -445,11 +445,11 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
+ 	out += sprintf(out, "Frame List\n");
+ 	for (i = 0; i < UHCI_NUMFRAMES; ++i) {
+ 		int shown = 0;
+-		td = uhci->fl->frame_cpu[i];
++		td = uhci->frame_cpu[i];
+ 		if (!td)
+ 			continue;
+ 
+-		if (td->dma_handle != (dma_addr_t)uhci->fl->frame[i]) {
++		if (td->dma_handle != (dma_addr_t)uhci->frame[i]) {
+ 			show_frame_num();
+ 			out += sprintf(out, "    frame list does not match td->dma_handle!\n");
+ 		}
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 17de9ee910f6..b44094fcd779 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -212,7 +212,7 @@ static void configure_hc(struct uhci_hcd *uhci)
+ 	outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF);
+ 
+ 	/* Store the frame list base address */
+-	outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD);
++	outl(uhci->frame_dma_handle, uhci->io_addr + USBFLBASEADD);
+ 
+ 	/* Set the current frame number */
+ 	outw(uhci->frame_number, uhci->io_addr + USBFRNUM);
+@@ -445,8 +445,11 @@ static void release_uhci(struct uhci_hcd *uhci)
+ 
+ 	dma_pool_destroy(uhci->td_pool);
+ 
+-	dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
+-			uhci->fl, uhci->fl->dma_handle);
++	kfree(uhci->frame_cpu);
++
++	dma_free_coherent(uhci_dev(uhci),
++			UHCI_NUMFRAMES * sizeof(*uhci->frame),
++			uhci->frame, uhci->frame_dma_handle);
+ 
+ 	debugfs_remove(uhci->dentry);
+ }
+@@ -527,7 +530,6 @@ static int uhci_start(struct usb_hcd *hcd)
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 	int retval = -EBUSY;
+ 	int i;
+-	dma_addr_t dma_handle;
+ 	struct dentry *dentry;
+ 
+ 	hcd->uses_new_polling = 1;
+@@ -561,17 +563,23 @@ static int uhci_start(struct usb_hcd *hcd)
+ 
+ 	init_waitqueue_head(&uhci->waitqh);
+ 
+-	uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
+-			&dma_handle, 0);
+-	if (!uhci->fl) {
++	uhci->frame = dma_alloc_coherent(uhci_dev(uhci),
++			UHCI_NUMFRAMES * sizeof(*uhci->frame),
++			&uhci->frame_dma_handle, 0);
++	if (!uhci->frame) {
+ 		dev_err(uhci_dev(uhci), "unable to allocate "
+ 				"consistent memory for frame list\n");
+-		goto err_alloc_fl;
++		goto err_alloc_frame;
+ 	}
++	memset(uhci->frame, 0, UHCI_NUMFRAMES * sizeof(*uhci->frame));
+ 
+-	memset((void *)uhci->fl, 0, sizeof(*uhci->fl));
+-
+-	uhci->fl->dma_handle = dma_handle;
++	uhci->frame_cpu = kcalloc(UHCI_NUMFRAMES, sizeof(*uhci->frame_cpu),
++			GFP_KERNEL);
++	if (!uhci->frame_cpu) {
++		dev_err(uhci_dev(uhci), "unable to allocate "
++				"memory for frame pointers\n");
++		goto err_alloc_frame_cpu;
++	}
+ 
+ 	uhci->td_pool = dma_pool_create("uhci_td", uhci_dev(uhci),
+ 			sizeof(struct uhci_td), 16, 0);
+@@ -654,7 +662,7 @@ static int uhci_start(struct usb_hcd *hcd)
+ 			irq = 7;
+ 
+ 		/* Only place we don't use the frame list routines */
+-		uhci->fl->frame[i] = UHCI_PTR_QH |
++		uhci->frame[i] = UHCI_PTR_QH |
+ 				cpu_to_le32(uhci->skelqh[irq]->dma_handle);
+ 	}
+ 
+@@ -686,10 +694,14 @@ static int uhci_start(struct usb_hcd *hcd)
+ 	dma_pool_destroy(uhci->td_pool);
+ 
+ err_create_td_pool:
+-	dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
+-			uhci->fl, uhci->fl->dma_handle);
++	kfree(uhci->frame_cpu);
++
++err_alloc_frame_cpu:
++	dma_free_coherent(uhci_dev(uhci),
++			UHCI_NUMFRAMES * sizeof(*uhci->frame),
++			uhci->frame, uhci->frame_dma_handle);
+ 
+-err_alloc_fl:
++err_alloc_frame:
+ 	debugfs_remove(uhci->dentry);
+ 
+ err_create_debug_entry:
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index 1c161b4f5bcf..b04d99df0a0e 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -359,7 +359,11 @@ struct uhci_hcd {
+ 	struct uhci_qh *skelqh[UHCI_NUM_SKELQH];	/* Skeleton QH's */
+ 
+ 	spinlock_t lock;
+-	struct uhci_frame_list *fl;		/* P: uhci->lock */
++
++	dma_addr_t frame_dma_handle;		/* Hardware frame list */
++	__le32 *frame;				/* P: uhci->lock */
++	void **frame_cpu;			/* CPU's frame list */
++
+ 	int fsbr;				/* Full-speed bandwidth reclamation */
+ 	unsigned long fsbrtimeout;		/* FSBR delay */
+ 
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index d54038211ca6..51de06bc438d 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -89,10 +89,10 @@ static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td,
+ 	td->frame = framenum;
+ 
+ 	/* Is there a TD already mapped there? */
+-	if (uhci->fl->frame_cpu[framenum]) {
++	if (uhci->frame_cpu[framenum]) {
+ 		struct uhci_td *ftd, *ltd;
+ 
+-		ftd = uhci->fl->frame_cpu[framenum];
++		ftd = uhci->frame_cpu[framenum];
+ 		ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list);
+ 
+ 		list_add_tail(&td->fl_list, &ftd->fl_list);
+@@ -101,10 +101,10 @@ static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td,
+ 		wmb();
+ 		ltd->link = cpu_to_le32(td->dma_handle);
+ 	} else {
+-		td->link = uhci->fl->frame[framenum];
++		td->link = uhci->frame[framenum];
+ 		wmb();
+-		uhci->fl->frame[framenum] = cpu_to_le32(td->dma_handle);
+-		uhci->fl->frame_cpu[framenum] = td;
++		uhci->frame[framenum] = cpu_to_le32(td->dma_handle);
++		uhci->frame_cpu[framenum] = td;
+ 	}
+ }
+ 
+@@ -114,16 +114,16 @@ static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td)
+ 	if (td->frame == -1 && list_empty(&td->fl_list))
+ 		return;
+ 
+-	if (td->frame != -1 && uhci->fl->frame_cpu[td->frame] == td) {
++	if (td->frame != -1 && uhci->frame_cpu[td->frame] == td) {
+ 		if (list_empty(&td->fl_list)) {
+-			uhci->fl->frame[td->frame] = td->link;
+-			uhci->fl->frame_cpu[td->frame] = NULL;
++			uhci->frame[td->frame] = td->link;
++			uhci->frame_cpu[td->frame] = NULL;
+ 		} else {
+ 			struct uhci_td *ntd;
+ 
+ 			ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list);
+-			uhci->fl->frame[td->frame] = cpu_to_le32(ntd->dma_handle);
+-			uhci->fl->frame_cpu[td->frame] = ntd;
++			uhci->frame[td->frame] = cpu_to_le32(ntd->dma_handle);
++			uhci->frame_cpu[td->frame] = ntd;
+ 		}
+ 	} else {
+ 		struct uhci_td *ptd;

commit 8b4cd42134fbd3c9a9a5c3467d31717798219b1b
+Author: Alan Stern 
+Date:   Fri Sep 16 14:17:45 2005 -0400
+
+    [PATCH] USB: UHCI: Remove unused fields and unneeded tests for NULL
+    
+    This patch (as562) removes from the uhci-hcd driver a few unused fields
+    and some unnecessary tests against NULL and assignments to NULL.  In fact
+    it wasn't until fairly recently that the tests became unnecessary.
+    Before last winter it was possible that the driver's stop() routine would
+    get called even if the start() routine returned an error, but now that
+    can't happen.  Hence there's no longer any need to check for partial
+    initialization.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
+index 4538a98b6f9d..04eddd7995c3 100644
+--- a/drivers/usb/host/uhci-debug.c
++++ b/drivers/usb/host/uhci-debug.c
+@@ -348,7 +348,6 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, char *bu
+ 
+ 	if (urbp->urb->status != -EINPROGRESS)
+ 		out += sprintf(out, "Status=%d ", urbp->urb->status);
+-	//out += sprintf(out, "Inserttime=%lx ",urbp->inserttime);
+ 	//out += sprintf(out, "FSBRtime=%lx ",urbp->fsbrtime);
+ 
+ 	count = 0;
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 0c024898cbea..17de9ee910f6 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -437,36 +437,18 @@ static void release_uhci(struct uhci_hcd *uhci)
+ 	int i;
+ 
+ 	for (i = 0; i < UHCI_NUM_SKELQH; i++)
+-		if (uhci->skelqh[i]) {
+-			uhci_free_qh(uhci, uhci->skelqh[i]);
+-			uhci->skelqh[i] = NULL;
+-		}
++		uhci_free_qh(uhci, uhci->skelqh[i]);
+ 
+-	if (uhci->term_td) {
+-		uhci_free_td(uhci, uhci->term_td);
+-		uhci->term_td = NULL;
+-	}
++	uhci_free_td(uhci, uhci->term_td);
+ 
+-	if (uhci->qh_pool) {
+-		dma_pool_destroy(uhci->qh_pool);
+-		uhci->qh_pool = NULL;
+-	}
++	dma_pool_destroy(uhci->qh_pool);
+ 
+-	if (uhci->td_pool) {
+-		dma_pool_destroy(uhci->td_pool);
+-		uhci->td_pool = NULL;
+-	}
++	dma_pool_destroy(uhci->td_pool);
+ 
+-	if (uhci->fl) {
+-		dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
+-				uhci->fl, uhci->fl->dma_handle);
+-		uhci->fl = NULL;
+-	}
++	dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
++			uhci->fl, uhci->fl->dma_handle);
+ 
+-	if (uhci->dentry) {
+-		debugfs_remove(uhci->dentry);
+-		uhci->dentry = NULL;
+-	}
++	debugfs_remove(uhci->dentry);
+ }
+ 
+ static int uhci_reset(struct usb_hcd *hcd)
+@@ -690,31 +672,25 @@ static int uhci_start(struct usb_hcd *hcd)
+  * error exits:
+  */
+ err_alloc_skelqh:
+-	for (i = 0; i < UHCI_NUM_SKELQH; i++)
+-		if (uhci->skelqh[i]) {
++	for (i = 0; i < UHCI_NUM_SKELQH; i++) {
++		if (uhci->skelqh[i])
+ 			uhci_free_qh(uhci, uhci->skelqh[i]);
+-			uhci->skelqh[i] = NULL;
+-		}
++	}
+ 
+ 	uhci_free_td(uhci, uhci->term_td);
+-	uhci->term_td = NULL;
+ 
+ err_alloc_term_td:
+ 	dma_pool_destroy(uhci->qh_pool);
+-	uhci->qh_pool = NULL;
+ 
+ err_create_qh_pool:
+ 	dma_pool_destroy(uhci->td_pool);
+-	uhci->td_pool = NULL;
+ 
+ err_create_td_pool:
+ 	dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
+ 			uhci->fl, uhci->fl->dma_handle);
+-	uhci->fl = NULL;
+ 
+ err_alloc_fl:
+ 	debugfs_remove(uhci->dentry);
+-	uhci->dentry = NULL;
+ 
+ err_create_debug_entry:
+ 	return retval;
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index 282f40b75881..1c161b4f5bcf 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -205,8 +205,6 @@ struct uhci_td {
+ 	/* Software fields */
+ 	dma_addr_t dma_handle;
+ 
+-	struct urb *urb;
+-
+ 	struct list_head list;		/* P: urb->lock */
+ 	struct list_head remove_list;	/* P: uhci->td_remove_list_lock */
+ 
+@@ -434,7 +432,6 @@ struct urb_priv {
+ 						/*  a control transfer, retrigger */
+ 						/*  the status phase */
+ 
+-	unsigned long inserttime;	/* In jiffies */
+ 	unsigned long fsbrtime;		/* In jiffies */
+ 
+ 	struct list_head queue_list;	/* P: uhci->frame_list_lock */
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 4e0fbe2c1a9a..d54038211ca6 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -443,7 +443,6 @@ static struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, struct urb *u
+ 
+ 	memset((void *)urbp, 0, sizeof(*urbp));
+ 
+-	urbp->inserttime = jiffies;
+ 	urbp->fsbrtime = jiffies;
+ 	urbp->urb = urb;
+ 	
+@@ -462,8 +461,6 @@ static void uhci_add_td_to_urb(struct urb *urb, struct uhci_td *td)
+ {
+ 	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+ 
+-	td->urb = urb;
+-
+ 	list_add_tail(&td->list, &urbp->td_list);
+ }
+ 
+@@ -473,8 +470,6 @@ static void uhci_remove_td_from_urb(struct uhci_td *td)
+ 		return;
+ 
+ 	list_del_init(&td->list);
+-
+-	td->urb = NULL;
+ }
+ 
+ static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)

commit d1209d049bbc3df66650f8417637be4f7b57b604
+Author: Alan Stern 
+Date:   Wed Oct 19 21:23:51 2005 -0700
+
+    [PATCH] Threads shouldn't inherit PF_NOFREEZE
+    
+    The PF_NOFREEZE process flag should not be inherited when a thread is
+    forked.  This patch (as585) removes the flag from the child.
+    
+    This problem is starting to show up more and more as drivers turn to the
+    kthread API instead of using kernel_thread().  As a result, their kernel
+    threads are now children of the kthread worker instead of modprobe, and
+    they inherit the PF_NOFREEZE flag.  This can cause problems during system
+    suspend; the kernel threads are not getting frozen as they ought to be.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: Pavel Machek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/kernel/fork.c b/kernel/fork.c
+index 533ce27f4b2c..280bd44ac441 100644
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -848,7 +848,7 @@ static inline void copy_flags(unsigned long clone_flags, struct task_struct *p)
+ {
+ 	unsigned long new_flags = p->flags;
+ 
+-	new_flags &= ~PF_SUPERPRIV;
++	new_flags &= ~(PF_SUPERPRIV | PF_NOFREEZE);
+ 	new_flags |= PF_FORKNOEXEC;
+ 	if (!(clone_flags & CLONE_PTRACE))
+ 		p->ptrace = 0;

commit 7c72ce81870ded9365f4bc5caa98ef1591dd18dd
+Author: Alan Stern 
+Date:   Fri Oct 14 11:23:27 2005 -0400
+
+    [SCSI] Fix leak of Scsi_Cmnds
+    
+    When a request is deferred in scsi_init_io because the sg table could not
+    be allocated, the associated scsi_cmnd is not released and the request is
+    not marked with REQ_DONTPREP.  When the command is retried, if
+    scsi_prep_fn decides to kill it then the scsi_cmnd will never be released.
+    
+    This patch (as573) changes scsi_init_io so that it calls scsi_put_command
+    before deferring a request.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index dc9c772bc874..0074f28c37b2 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -97,7 +97,6 @@ int scsi_insert_special_req(struct scsi_request *sreq, int at_head)
+ }
+ 
+ static void scsi_run_queue(struct request_queue *q);
+-static void scsi_release_buffers(struct scsi_cmnd *cmd);
+ 
+ /*
+  * Function:	scsi_unprep_request()
+@@ -1040,8 +1039,10 @@ static int scsi_init_io(struct scsi_cmnd *cmd)
+ 	 * if sg table allocation fails, requeue request later.
+ 	 */
+ 	sgpnt = scsi_alloc_sgtable(cmd, GFP_ATOMIC);
+-	if (unlikely(!sgpnt))
++	if (unlikely(!sgpnt)) {
++		scsi_unprep_request(req);
+ 		return BLKPREP_DEFER;
++	}
+ 
+ 	cmd->request_buffer = (char *) sgpnt;
+ 	cmd->request_bufflen = req->nr_sectors << 9;
+@@ -1245,8 +1246,8 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
+ 		 */
+ 		ret = scsi_init_io(cmd);
+ 		switch(ret) {
++			/* For BLKPREP_KILL/DEFER the cmd was released */
+ 		case BLKPREP_KILL:
+-			/* BLKPREP_KILL return also releases the command */
+ 			goto kill;
+ 		case BLKPREP_DEFER:
+ 			goto defer;

commit 0fc084eaffe0a9a82a0c94da9ee9f7060ade8b04
+Author: Alan Stern 
+Date:   Thu Sep 22 00:49:51 2005 -0700
+
+    [PATCH] USB: Update Documentation/usb/URB.txt
+    
+    This patch (as564) updates Documentation/usb/URB.txt, bringing it roughly
+    up to the current level.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/Documentation/usb/URB.txt b/Documentation/usb/URB.txt
+index d59b95cc6f1b..a49e5f2c2b46 100644
+--- a/Documentation/usb/URB.txt
++++ b/Documentation/usb/URB.txt
+@@ -1,5 +1,6 @@
+ Revised: 2000-Dec-05.
+ Again:   2002-Jul-06
++Again:   2005-Sep-19
+ 
+     NOTE:
+ 
+@@ -18,8 +19,8 @@ called USB Request Block, or URB for short.
+   and deliver the data and status back. 
+ 
+ - Execution of an URB is inherently an asynchronous operation, i.e. the 
+-  usb_submit_urb(urb) call returns immediately after it has successfully queued 
+-  the requested action. 
++  usb_submit_urb(urb) call returns immediately after it has successfully
++  queued the requested action.
+ 
+ - Transfers for one URB can be canceled with usb_unlink_urb(urb) at any time. 
+ 
+@@ -94,8 +95,9 @@ To free an URB, use
+ 
+ 	void usb_free_urb(struct urb *urb)
+ 
+-You may not free an urb that you've submitted, but which hasn't yet been
+-returned to you in a completion callback.
++You may free an urb that you've submitted, but which hasn't yet been
++returned to you in a completion callback.  It will automatically be
++deallocated when it is no longer in use.
+ 
+ 
+ 1.4. What has to be filled in?
+@@ -145,30 +147,36 @@ to get seamless ISO streaming.
+ 
+ 1.6. How to cancel an already running URB?
+ 
+-For an URB which you've submitted, but which hasn't been returned to
+-your driver by the host controller, call
++There are two ways to cancel an URB you've submitted but which hasn't
++been returned to your driver yet.  For an asynchronous cancel, call
+ 
+ 	int usb_unlink_urb(struct urb *urb)
+ 
+ It removes the urb from the internal list and frees all allocated
+-HW descriptors. The status is changed to reflect unlinking. After 
+-usb_unlink_urb() returns with that status code, you can free the URB
+-with usb_free_urb().
++HW descriptors. The status is changed to reflect unlinking.  Note
++that the URB will not normally have finished when usb_unlink_urb()
++returns; you must still wait for the completion handler to be called.
+ 
+-There is also an asynchronous unlink mode.  To use this, set the
+-the URB_ASYNC_UNLINK flag in urb->transfer flags before calling
+-usb_unlink_urb().  When using async unlinking, the URB will not
+-normally be unlinked when usb_unlink_urb() returns.  Instead, wait
+-for the completion handler to be called.
++To cancel an URB synchronously, call
++
++	void usb_kill_urb(struct urb *urb)
++
++It does everything usb_unlink_urb does, and in addition it waits
++until after the URB has been returned and the completion handler
++has finished.  It also marks the URB as temporarily unusable, so
++that if the completion handler or anyone else tries to resubmit it
++they will get a -EPERM error.  Thus you can be sure that when
++usb_kill_urb() returns, the URB is totally idle.
+ 
+ 
+ 1.7. What about the completion handler?
+ 
+ The handler is of the following type:
+ 
+-	typedef void (*usb_complete_t)(struct urb *);
++	typedef void (*usb_complete_t)(struct urb *, struct pt_regs *)
+ 
+-i.e. it gets just the URB that caused the completion call.
++I.e., it gets the URB that caused the completion call, plus the
++register values at the time of the corresponding interrupt (if any).
+ In the completion handler, you should have a look at urb->status to
+ detect any USB errors. Since the context parameter is included in the URB,
+ you can pass information to the completion handler. 
+@@ -176,17 +184,11 @@ you can pass information to the completion handler.
+ Note that even when an error (or unlink) is reported, data may have been
+ transferred.  That's because USB transfers are packetized; it might take
+ sixteen packets to transfer your 1KByte buffer, and ten of them might
+-have transferred succesfully before the completion is called.
++have transferred succesfully before the completion was called.
+ 
+ 
+ NOTE:  ***** WARNING *****
+-Don't use urb->dev field in your completion handler; it's cleared
+-as part of giving urbs back to drivers.  (Addressing an issue with
+-ownership of periodic URBs, which was otherwise ambiguous.) Instead,
+-use urb->context to hold all the data your driver needs.
+-
+-NOTE:  ***** WARNING *****
+-Also, NEVER SLEEP IN A COMPLETION HANDLER.  These are normally called
++NEVER SLEEP IN A COMPLETION HANDLER.  These are normally called
+ during hardware interrupt processing.  If you can, defer substantial
+ work to a tasklet (bottom half) to keep system latencies low.  You'll
+ probably need to use spinlocks to protect data structures you manipulate
+@@ -229,24 +231,10 @@ ISO data with some other event stream.
+ Interrupt transfers, like isochronous transfers, are periodic, and happen
+ in intervals that are powers of two (1, 2, 4 etc) units.  Units are frames
+ for full and low speed devices, and microframes for high speed ones.
+-
+-Currently, after you submit one interrupt URB, that urb is owned by the
+-host controller driver until you cancel it with usb_unlink_urb().  You
+-may unlink interrupt urbs in their completion handlers, if you need to.
+-
+-After a transfer completion is called, the URB is automagically resubmitted.
+-THIS BEHAVIOR IS EXPECTED TO BE REMOVED!!
+-
+-Interrupt transfers may only send (or receive) the "maxpacket" value for
+-the given interrupt endpoint; if you need more data, you will need to
+-copy that data out of (or into) another buffer.  Similarly, you can't
+-queue interrupt transfers.
+-THESE RESTRICTIONS ARE EXPECTED TO BE REMOVED!!
+-
+-Note that this automagic resubmission model does make it awkward to use
+-interrupt OUT transfers.  The portable solution involves unlinking those
+-OUT urbs after the data is transferred, and perhaps submitting a final
+-URB for a short packet.
+-
+ The usb_submit_urb() call modifies urb->interval to the implemented interval
+ value that is less than or equal to the requested interval value.
++
++In Linux 2.6, unlike earlier versions, interrupt URBs are not automagically
++restarted when they complete.  They end when the completion handler is
++called, just like other URBs.  If you want an interrupt URB to be restarted,
++your completion handler must resubmit it.

commit a64358db1253b35d508a411e80a3ad23b859ec88
+Author: Alan Stern 
+Date:   Tue Jul 26 10:27:10 2005 -0400
+
+    [SCSI] SCSI scanning and removal fixes
+    
+    This patch (as545) fixes the list traversals in __scsi_remove_target and
+    scsi_forget_host.  In each case the existing code list_for_each_entry_safe
+    in an _unsafe_ manner, because the list was not protected from outside
+    modification while the iteration was running.
+    
+    The new scsi_forget_host routine takes the moderately controversial step
+    of iterating over devices for removal rather than iterating over targets.
+    This makes more sense to me because the current scheme treats targets as
+    second-class citizens, created and removed on demand, rather than as
+    objects corresponding to actual hardware.  (Also I couldn't figure out any
+    safe way to iterate over the target list, since it's not so easy to tell
+    when a target has already been removed.)
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+index b86f170fa8ed..fcf9f6cbb142 100644
+--- a/drivers/scsi/scsi_scan.c
++++ b/drivers/scsi/scsi_scan.c
+@@ -1466,23 +1466,17 @@ EXPORT_SYMBOL(scsi_scan_single_target);
+ 
+ void scsi_forget_host(struct Scsi_Host *shost)
+ {
+-	struct scsi_target *starget, *tmp;
++	struct scsi_device *sdev;
+ 	unsigned long flags;
+ 
+-	/*
+-	 * Ok, this look a bit strange.  We always look for the first device
+-	 * on the list as scsi_remove_device removes them from it - thus we
+-	 * also have to release the lock.
+-	 * We don't need to get another reference to the device before
+-	 * releasing the lock as we already own the reference from
+-	 * scsi_register_device that's release in scsi_remove_device.  And
+-	 * after that we don't look at sdev anymore.
+-	 */
++ restart:
+ 	spin_lock_irqsave(shost->host_lock, flags);
+-	list_for_each_entry_safe(starget, tmp, &shost->__targets, siblings) {
++	list_for_each_entry(sdev, &shost->__devices, siblings) {
++		if (sdev->sdev_state == SDEV_DEL)
++			continue;
+ 		spin_unlock_irqrestore(shost->host_lock, flags);
+-		scsi_remove_target(&starget->dev);
+-		spin_lock_irqsave(shost->host_lock, flags);
++		__scsi_remove_device(sdev);
++		goto restart;
+ 	}
+ 	spin_unlock_irqrestore(shost->host_lock, flags);
+ }
+diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
+index 83f87c41b18d..1e47b7eddef4 100644
+--- a/drivers/scsi/scsi_sysfs.c
++++ b/drivers/scsi/scsi_sysfs.c
+@@ -719,17 +719,20 @@ void __scsi_remove_target(struct scsi_target *starget)
+ {
+ 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ 	unsigned long flags;
+-	struct scsi_device *sdev, *tmp;
++	struct scsi_device *sdev;
+ 
+ 	spin_lock_irqsave(shost->host_lock, flags);
+ 	starget->reap_ref++;
+-	list_for_each_entry_safe(sdev, tmp, &shost->__devices, siblings) {
++ restart:
++	list_for_each_entry(sdev, &shost->__devices, siblings) {
+ 		if (sdev->channel != starget->channel ||
+-		    sdev->id != starget->id)
++		    sdev->id != starget->id ||
++		    sdev->sdev_state == SDEV_DEL)
+ 			continue;
+ 		spin_unlock_irqrestore(shost->host_lock, flags);
+ 		scsi_remove_device(sdev);
+ 		spin_lock_irqsave(shost->host_lock, flags);
++		goto restart;
+ 	}
+ 	spin_unlock_irqrestore(shost->host_lock, flags);
+ 	scsi_target_reap(starget);

commit b95be99d52ce4f9db9ff0bd5f10e9e2066da6d2e
+Author: Alan Stern 
+Date:   Thu Sep 15 13:52:51 2005 -0400
+
+    [SCSI] fix oops in scsi_release_buffers()
+    
+    I found one other thing that needs to be fixed.  The call to
+    scsi_release_buffers in scsi_unprep_request causes an oops, because the
+    sgtable has already been freed in scsi_io_completion.  The following patch
+    is needed.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index 0c6924eecf59..f065cbc1a6e5 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -118,7 +118,6 @@ static void scsi_unprep_request(struct request *req)
+ 	req->flags &= ~REQ_DONTPREP;
+ 	req->special = (req->flags & REQ_SPECIAL) ? cmd->sc_request : NULL;
+ 
+-	scsi_release_buffers(cmd);
+ 	scsi_put_command(cmd);
+ }
+ 
+@@ -1512,7 +1511,6 @@ static void scsi_request_fn(struct request_queue *q)
+ 	 * cases (host limits or settings) should run the queue at some
+ 	 * later time.
+ 	 */
+-	scsi_unprep_request(req);
+ 	spin_lock_irq(q->queue_lock);
+ 	blk_requeue_request(q, req);
+ 	sdev->device_busy--;

commit 541950027f8b7c96a639bc16e48930c590f1b98a
+Author: Alan Stern 
+Date:   Thu Sep 15 21:52:51 2005 -0400
+
+    [SCSI] fix use after potential free in scsi_remove_device
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
+index b8052d5206cc..83f87c41b18d 100644
+--- a/drivers/scsi/scsi_sysfs.c
++++ b/drivers/scsi/scsi_sysfs.c
+@@ -707,9 +707,11 @@ void __scsi_remove_device(struct scsi_device *sdev)
+  **/
+ void scsi_remove_device(struct scsi_device *sdev)
+ {
+-	down(&sdev->host->scan_mutex);
++	struct Scsi_Host *shost = sdev->host;
++
++	down(&shost->scan_mutex);
+ 	__scsi_remove_device(sdev);
+-	up(&sdev->host->scan_mutex);
++	up(&shost->scan_mutex);
+ }
+ EXPORT_SYMBOL(scsi_remove_device);
+ 

commit 1f09df8bfe358994fcb5f3dc4f890694c4069621
+Author: Alan Stern 
+Date:   Mon Sep 5 13:59:51 2005 -0400
+
+    [PATCH] USB UHCI: remove the FSBR kernel timer
+    
+    This patch (as558) removes from the UHCI driver a kernel timer used for
+    checking Full Speed Bandwidth Reclamation (FSBR).  The checking can be
+    done during normal root-hub polling; it doesn't need a separate timer.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 0d5d2545bf07..0c024898cbea 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -97,14 +97,9 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
+ /* to make sure it doesn't hog all of the bandwidth */
+ #define DEPTH_INTERVAL 5
+ 
+-static inline void restart_timer(struct uhci_hcd *uhci)
+-{
+-	mod_timer(&uhci->stall_timer, jiffies + msecs_to_jiffies(100));
+-}
+-
+-#include "uhci-hub.c"
+ #include "uhci-debug.c"
+ #include "uhci-q.c"
++#include "uhci-hub.c"
+ 
+ /*
+  * Make sure the controller is completely inactive, unable to
+@@ -160,7 +155,6 @@ static void hc_died(struct uhci_hcd *uhci)
+ {
+ 	reset_hc(uhci);
+ 	uhci->hc_inaccessible = 1;
+-	del_timer(&uhci->stall_timer);
+ }
+ 
+ /*
+@@ -287,8 +281,11 @@ __acquires(uhci->lock)
+ 	/* Enable resume-detect interrupts if they work.
+ 	 * Then enter Global Suspend mode, still configured.
+ 	 */
+-	int_enable = (resume_detect_interrupts_are_broken(uhci) ?
+-			0 : USBINTR_RESUME);
++	uhci->working_RD = 1;
++	int_enable = USBINTR_RESUME;
++	if (resume_detect_interrupts_are_broken(uhci)) {
++		uhci->working_RD = int_enable = 0;
++	}
+ 	outw(int_enable, uhci->io_addr + USBINTR);
+ 	outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD);
+ 	mb();
+@@ -315,7 +312,6 @@ __acquires(uhci->lock)
+ 
+ 	uhci->rh_state = new_state;
+ 	uhci->is_stopped = UHCI_IS_STOPPED;
+-	del_timer(&uhci->stall_timer);
+ 	uhci_to_hcd(uhci)->poll_rh = !int_enable;
+ 
+ 	uhci_scan_schedule(uhci, NULL);
+@@ -335,7 +331,6 @@ static void start_rh(struct uhci_hcd *uhci)
+ 	mb();
+ 	uhci->rh_state = UHCI_RH_RUNNING;
+ 	uhci_to_hcd(uhci)->poll_rh = 1;
+-	restart_timer(uhci);
+ }
+ 
+ static void wakeup_rh(struct uhci_hcd *uhci)
+@@ -374,20 +369,6 @@ __acquires(uhci->lock)
+ 	mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);
+ }
+ 
+-static void stall_callback(unsigned long _uhci)
+-{
+-	struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&uhci->lock, flags);
+-	uhci_scan_schedule(uhci, NULL);
+-	check_fsbr(uhci);
+-
+-	if (!uhci->is_stopped)
+-		restart_timer(uhci);
+-	spin_unlock_irqrestore(&uhci->lock, flags);
+-}
+-
+ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+@@ -418,8 +399,10 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
+ 					"host controller halted, "
+ 					"very bad!\n");
+ 				hc_died(uhci);
+-				spin_unlock_irqrestore(&uhci->lock, flags);
+-				return IRQ_HANDLED;
++
++				/* Force a callback in case there are
++				 * pending unlinks */
++				mod_timer(&hcd->rh_timer, jiffies);
+ 			}
+ 			spin_unlock_irqrestore(&uhci->lock, flags);
+ 		}
+@@ -427,10 +410,11 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
+ 
+ 	if (status & USBSTS_RD)
+ 		usb_hcd_poll_rh_status(hcd);
+-
+-	spin_lock_irqsave(&uhci->lock, flags);
+-	uhci_scan_schedule(uhci, regs);
+-	spin_unlock_irqrestore(&uhci->lock, flags);
++	else {
++		spin_lock_irqsave(&uhci->lock, flags);
++		uhci_scan_schedule(uhci, regs);
++		spin_unlock_irqrestore(&uhci->lock, flags);
++	}
+ 
+ 	return IRQ_HANDLED;
+ }
+@@ -595,10 +579,6 @@ static int uhci_start(struct usb_hcd *hcd)
+ 
+ 	init_waitqueue_head(&uhci->waitqh);
+ 
+-	init_timer(&uhci->stall_timer);
+-	uhci->stall_timer.function = stall_callback;
+-	uhci->stall_timer.data = (unsigned long) uhci;
+-
+ 	uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
+ 			&dma_handle, 0);
+ 	if (!uhci->fl) {
+@@ -745,11 +725,11 @@ static void uhci_stop(struct usb_hcd *hcd)
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 
+ 	spin_lock_irq(&uhci->lock);
+-	reset_hc(uhci);
++	if (!uhci->hc_inaccessible)
++		reset_hc(uhci);
+ 	uhci_scan_schedule(uhci, NULL);
+ 	spin_unlock_irq(&uhci->lock);
+ 
+-	del_timer_sync(&uhci->stall_timer);
+ 	release_uhci(uhci);
+ }
+ 
+@@ -811,13 +791,12 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
+ 	 */
+ 	pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0);
+ 	uhci->hc_inaccessible = 1;
++	hcd->poll_rh = 0;
+ 
+ 	/* FIXME: Enable non-PME# remote wakeup? */
+ 
+ done:
+ 	spin_unlock_irq(&uhci->lock);
+-	if (rc == 0)
+-		del_timer_sync(&hcd->rh_timer);
+ 	return rc;
+ }
+ 
+@@ -850,8 +829,11 @@ static int uhci_resume(struct usb_hcd *hcd)
+ 
+ 	spin_unlock_irq(&uhci->lock);
+ 
+-	if (hcd->poll_rh)
++	if (!uhci->working_RD) {
++		/* Suspended root hub needs to be polled */
++		hcd->poll_rh = 1;
+ 		usb_hcd_poll_rh_status(hcd);
++	}
+ 	return 0;
+ }
+ #endif
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index bf9c5f9b508b..282f40b75881 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -345,9 +345,6 @@ enum uhci_rh_state {
+ 
+ /*
+  * This describes the full uhci information.
+- *
+- * Note how the "proper" USB information is just
+- * a subset of what the full implementation needs.
+  */
+ struct uhci_hcd {
+ 
+@@ -360,8 +357,6 @@ struct uhci_hcd {
+ 	struct dma_pool *qh_pool;
+ 	struct dma_pool *td_pool;
+ 
+-	struct usb_bus *bus;
+-
+ 	struct uhci_td *term_td;	/* Terminating TD, see UHCI bug */
+ 	struct uhci_qh *skelqh[UHCI_NUM_SKELQH];	/* Skeleton QH's */
+ 
+@@ -380,6 +375,8 @@ struct uhci_hcd {
+ 	unsigned int scan_in_progress:1;	/* Schedule scan is running */
+ 	unsigned int need_rescan:1;		/* Redo the schedule scan */
+ 	unsigned int hc_inaccessible:1;		/* HC is suspended or dead */
++	unsigned int working_RD:1;		/* Suspended root hub doesn't
++						   need to be polled */
+ 
+ 	/* Support for port suspend/resume/reset */
+ 	unsigned long port_c_suspend;		/* Bit-arrays of ports */
+@@ -405,9 +402,7 @@ struct uhci_hcd {
+ 	/* List of URB's awaiting completion callback */
+ 	struct list_head complete_list;		/* P: uhci->lock */
+ 
+-	int rh_numports;
+-
+-	struct timer_list stall_timer;
++	int rh_numports;			/* Number of root-hub ports */
+ 
+ 	wait_queue_head_t waitqh;		/* endpoint_disable waiters */
+ };
+diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
+index 4eace2b19ddb..a71e48a66805 100644
+--- a/drivers/usb/host/uhci-hub.c
++++ b/drivers/usb/host/uhci-hub.c
+@@ -145,15 +145,16 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 	unsigned long flags;
+-	int status;
++	int status = 0;
+ 
+ 	spin_lock_irqsave(&uhci->lock, flags);
+-	if (uhci->hc_inaccessible) {
+-		status = 0;
+-		goto done;
+-	}
+ 
++	uhci_scan_schedule(uhci, NULL);
++	if (uhci->hc_inaccessible)
++		goto done;
++	check_fsbr(uhci);
+ 	uhci_check_ports(uhci);
++
+ 	status = get_hub_status_data(uhci, buf);
+ 
+ 	switch (uhci->rh_state) {
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index bbb36cd6ed61..ea0d168a8c67 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -33,7 +33,7 @@ static void uhci_free_pending_tds(struct uhci_hcd *uhci);
+ static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci)
+ {
+ 	if (uhci->is_stopped)
+-		mod_timer(&uhci->stall_timer, jiffies);
++		mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);
+ 	uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); 
+ }
+ 

commit f1a15606d5be8490a122f1c94c554bd0f07d8d26
+Author: Alan Stern 
+Date:   Mon Sep 5 13:55:23 2005 -0400
+
+    [PATCH] usbcore: small changes to HCD glue layer
+    
+    This patch (as549) introduces two small changes in the HCD glue layer.
+    The first simply removes a redundant test.  The second allows root-hub
+    polling to continue for a single iteration after a host controller dies;
+    this is needed for the patch that follows.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 12ecdb03ee5f..1017a97a418b 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1606,7 +1606,7 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs * r)
+ 		return IRQ_NONE;
+ 
+ 	hcd->saw_irq = 1;
+-	if (hcd->state != start && hcd->state == HC_STATE_HALT)
++	if (hcd->state == HC_STATE_HALT)
+ 		usb_hc_died (hcd);
+ 	return IRQ_HANDLED;
+ }
+@@ -1630,7 +1630,6 @@ void usb_hc_died (struct usb_hcd *hcd)
+ 	spin_lock_irqsave (&hcd_root_hub_lock, flags);
+ 	if (hcd->rh_registered) {
+ 		hcd->poll_rh = 0;
+-		del_timer(&hcd->rh_timer);
+ 
+ 		/* make khubd clean up old urbs and devices */
+ 		usb_set_device_state (hcd->self.root_hub,

commit b70d37bf61f278f9d9adf17c52af6b2d0ae7800c
+Author: Alan Stern 
+Date:   Tue Jul 26 10:30:40 2005 -0400
+
+    [SCSI] Fix module removal/device add race
+    
+    This patch (as546) fixes an oops-causing failure to check the return code
+    from scsi_device_get.  The call can return an error if the LLD is being
+    unloaded from memory.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+index 76577fae60fa..a0975c78b968 100644
+--- a/drivers/scsi/scsi_scan.c
++++ b/drivers/scsi/scsi_scan.c
+@@ -870,8 +870,12 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
+  out_free_sdev:
+ 	if (res == SCSI_SCAN_LUN_PRESENT) {
+ 		if (sdevp) {
+-			scsi_device_get(sdev);
+-			*sdevp = sdev;
++			if (scsi_device_get(sdev) == 0) {
++				*sdevp = sdev;
++			} else {
++				__scsi_remove_device(sdev);
++				res = SCSI_SCAN_NO_RESPONSE;
++			}
+ 		}
+ 	} else {
+ 		if (sdev->host->hostt->slave_destroy)

commit 903f4fed858a7b56b260cbd55d174fe54d188fb7
+Author: Alan Stern 
+Date:   Tue Jul 26 10:20:53 2005 -0400
+
+    [SCSI] fix callers of scsi_remove_device() who already hold the scan muted
+    
+    This patch (as544) adds a private entry point to scsi_remove_device, for
+    use when callers already own the scan_mutex.  The appropriate callers are
+    modified to use the new entry point.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
+index ee6de1768e53..d05f778d31a8 100644
+--- a/drivers/scsi/scsi_priv.h
++++ b/drivers/scsi/scsi_priv.h
+@@ -124,6 +124,7 @@ extern void scsi_sysfs_unregister(void);
+ extern void scsi_sysfs_device_initialize(struct scsi_device *);
+ extern int scsi_sysfs_target_initialize(struct scsi_device *);
+ extern struct scsi_transport_template blank_transport_template;
++extern void __scsi_remove_device(struct scsi_device *);
+ 
+ extern struct bus_type scsi_bus_type;
+ 
+diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
+index dae59d1da07a..b8052d5206cc 100644
+--- a/drivers/scsi/scsi_sysfs.c
++++ b/drivers/scsi/scsi_sysfs.c
+@@ -653,7 +653,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
+ 			error = attr_add(&sdev->sdev_gendev,
+ 					sdev->host->hostt->sdev_attrs[i]);
+ 			if (error) {
+-				scsi_remove_device(sdev);
++				__scsi_remove_device(sdev);
+ 				goto out;
+ 			}
+ 		}
+@@ -667,7 +667,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
+ 							scsi_sysfs_sdev_attrs[i]);
+ 			error = device_create_file(&sdev->sdev_gendev, attr);
+ 			if (error) {
+-				scsi_remove_device(sdev);
++				__scsi_remove_device(sdev);
+ 				goto out;
+ 			}
+ 		}
+@@ -687,17 +687,10 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
+ 	return error;
+ }
+ 
+-/**
+- * scsi_remove_device - unregister a device from the scsi bus
+- * @sdev:	scsi_device to unregister
+- **/
+-void scsi_remove_device(struct scsi_device *sdev)
++void __scsi_remove_device(struct scsi_device *sdev)
+ {
+-	struct Scsi_Host *shost = sdev->host;
+-
+-	down(&shost->scan_mutex);
+ 	if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0)
+-		goto out;
++		return;
+ 
+ 	class_device_unregister(&sdev->sdev_classdev);
+ 	device_del(&sdev->sdev_gendev);
+@@ -706,8 +699,17 @@ void scsi_remove_device(struct scsi_device *sdev)
+ 		sdev->host->hostt->slave_destroy(sdev);
+ 	transport_unregister_device(&sdev->sdev_gendev);
+ 	put_device(&sdev->sdev_gendev);
+-out:
+-	up(&shost->scan_mutex);
++}
++
++/**
++ * scsi_remove_device - unregister a device from the scsi bus
++ * @sdev:	scsi_device to unregister
++ **/
++void scsi_remove_device(struct scsi_device *sdev)
++{
++	down(&sdev->host->scan_mutex);
++	__scsi_remove_device(sdev);
++	up(&sdev->host->scan_mutex);
+ }
+ EXPORT_SYMBOL(scsi_remove_device);
+ 

commit e517d3133f62c27b211f305a6dbd6f6ccac0db1b
+Author: Alan Stern 
+Date:   Tue Jul 26 10:18:45 2005 -0400
+
+    [SCSI] add missing scan mutex to scsi_scan_target()
+    
+    This patch (as543) adds a private entry point to scsi_scan_target, for use
+    when the caller already owns the scan_mutex, and updates the kerneldoc for
+    that routine (which was badly out-of-date).  It converts scsi_scan_channel
+    to use the new entry point.  Lastly, it modifies scsi_get_host_dev to make
+    it acquire the scan_mutex, necessary since the routine adds a new
+    scsi_device even if it doesn't do any actual scanning.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+index 19c9a232a754..76577fae60fa 100644
+--- a/drivers/scsi/scsi_scan.c
++++ b/drivers/scsi/scsi_scan.c
+@@ -1276,27 +1276,8 @@ void scsi_rescan_device(struct device *dev)
+ }
+ EXPORT_SYMBOL(scsi_rescan_device);
+ 
+-/**
+- * scsi_scan_target - scan a target id, possibly including all LUNs on the
+- *     target.
+- * @sdevsca:	Scsi_Device handle for scanning
+- * @shost:	host to scan
+- * @channel:	channel to scan
+- * @id:		target id to scan
+- *
+- * Description:
+- *     Scan the target id on @shost, @channel, and @id. Scan at least LUN
+- *     0, and possibly all LUNs on the target id.
+- *
+- *     Use the pre-allocated @sdevscan as a handle for the scanning. This
+- *     function sets sdevscan->host, sdevscan->id and sdevscan->lun; the
+- *     scanning functions modify sdevscan->lun.
+- *
+- *     First try a REPORT LUN scan, if that does not scan the target, do a
+- *     sequential scan of LUNs on the target id.
+- **/
+-void scsi_scan_target(struct device *parent, unsigned int channel,
+-		      unsigned int id, unsigned int lun, int rescan)
++static void __scsi_scan_target(struct device *parent, unsigned int channel,
++		unsigned int id, unsigned int lun, int rescan)
+ {
+ 	struct Scsi_Host *shost = dev_to_shost(parent);
+ 	int bflags = 0;
+@@ -1310,9 +1291,7 @@ void scsi_scan_target(struct device *parent, unsigned int channel,
+ 		 */
+ 		return;
+ 
+-
+ 	starget = scsi_alloc_target(parent, channel, id);
+-
+ 	if (!starget)
+ 		return;
+ 
+@@ -1358,6 +1337,33 @@ void scsi_scan_target(struct device *parent, unsigned int channel,
+ 
+ 	put_device(&starget->dev);
+ }
++
++/**
++ * scsi_scan_target - scan a target id, possibly including all LUNs on the
++ *     target.
++ * @parent:	host to scan
++ * @channel:	channel to scan
++ * @id:		target id to scan
++ * @lun:	Specific LUN to scan or SCAN_WILD_CARD
++ * @rescan:	passed to LUN scanning routines
++ *
++ * Description:
++ *     Scan the target id on @parent, @channel, and @id. Scan at least LUN 0,
++ *     and possibly all LUNs on the target id.
++ *
++ *     First try a REPORT LUN scan, if that does not scan the target, do a
++ *     sequential scan of LUNs on the target id.
++ **/
++void scsi_scan_target(struct device *parent, unsigned int channel,
++		      unsigned int id, unsigned int lun, int rescan)
++{
++	struct Scsi_Host *shost = dev_to_shost(parent);
++
++	down(&shost->scan_mutex);
++	if (scsi_host_scan_allowed(shost))
++		__scsi_scan_target(parent, channel, id, lun, rescan);
++	up(&shost->scan_mutex);
++}
+ EXPORT_SYMBOL(scsi_scan_target);
+ 
+ static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel,
+@@ -1383,10 +1389,12 @@ static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel,
+ 				order_id = shost->max_id - id - 1;
+ 			else
+ 				order_id = id;
+-			scsi_scan_target(&shost->shost_gendev, channel, order_id, lun, rescan);
++			__scsi_scan_target(&shost->shost_gendev, channel,
++					order_id, lun, rescan);
+ 		}
+ 	else
+-		scsi_scan_target(&shost->shost_gendev, channel, id, lun, rescan);
++		__scsi_scan_target(&shost->shost_gendev, channel,
++				id, lun, rescan);
+ }
+ 
+ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
+@@ -1484,12 +1492,15 @@ void scsi_forget_host(struct Scsi_Host *shost)
+  */
+ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)
+ {
+-	struct scsi_device *sdev;
++	struct scsi_device *sdev = NULL;
+ 	struct scsi_target *starget;
+ 
++	down(&shost->scan_mutex);
++	if (!scsi_host_scan_allowed(shost))
++		goto out;
+ 	starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id);
+ 	if (!starget)
+-		return NULL;
++		goto out;
+ 
+ 	sdev = scsi_alloc_sdev(starget, 0, NULL);
+ 	if (sdev) {
+@@ -1497,6 +1508,8 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)
+ 		sdev->borken = 0;
+ 	}
+ 	put_device(&starget->dev);
++ out:
++	up(&shost->scan_mutex);
+ 	return sdev;
+ }
+ EXPORT_SYMBOL(scsi_get_host_dev);

commit 3b4d7f79164853e10342d707e32307e0c8054982
+Author: Alan Stern 
+Date:   Thu Aug 11 15:50:32 2005 -0400
+
+    [PATCH] USB: Support unbinding of the usb_generic driver
+    
+    This patch (as556) adds support for unbinding the usb_generic "driver".
+    That driver only binds to USB devices, as opposed to interfaces, and it
+    does nothing much besides marking which struct device's go with an
+    overall USB device plus providing suspend/resume methods.  Now that
+    users can unbind drivers at will using the sysfs "unbind" attribute, we
+    need a rational way of dealing with USB devices that are no longer under
+    full control of the USB stack.  The patch handles this by unconfiguring
+    the device, thereby removing all the interfaces and their associated
+    drivers and children.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 109f7558167a..087af73a59dd 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -65,6 +65,16 @@ static int generic_probe (struct device *dev)
+ }
+ static int generic_remove (struct device *dev)
+ {
++	struct usb_device *udev = to_usb_device(dev);
++
++	/* if this is only an unbind, not a physical disconnect, then
++	 * unconfigure the device */
++	if (udev->state == USB_STATE_CONFIGURED)
++		usb_set_configuration(udev, 0);
++
++	/* in case the call failed or the device was suspended */
++	if (udev->state >= USB_STATE_CONFIGURED)
++		usb_disable_device(udev, 0);
+ 	return 0;
+ }
+ 

commit 3ea15966ed59f2bc20928c7b0496b4585f6de206
+Author: Alan Stern 
+Date:   Thu Aug 11 10:15:39 2005 -0400
+
+    [PATCH] USB: Add timeout to usb_lock_device_for_reset
+    
+    This patch (as555) modifies the already-awkward
+    usb_lock_device_for_reset routine in usbcore by adding a timeout.  The
+    whole point of the routine is that the caller wants to acquire some
+    semaphores in the wrong order; protecting against the possibility of
+    deadlock by timing out seems only prudent.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index bc966dbc6021..109f7558167a 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -912,7 +912,7 @@ int usb_trylock_device(struct usb_device *udev)
+  * is neither BINDING nor BOUND.  Rather than sleeping to wait for the
+  * lock, the routine polls repeatedly.  This is to prevent deadlock with
+  * disconnect; in some drivers (such as usb-storage) the disconnect()
+- * callback will block waiting for a device reset to complete.
++ * or suspend() method will block waiting for a device reset to complete.
+  *
+  * Returns a negative error code for failure, otherwise 1 or 0 to indicate
+  * that the device will or will not have to be unlocked.  (0 can be
+@@ -922,6 +922,8 @@ int usb_trylock_device(struct usb_device *udev)
+ int usb_lock_device_for_reset(struct usb_device *udev,
+ 		struct usb_interface *iface)
+ {
++	unsigned long jiffies_expire = jiffies + HZ;
++
+ 	if (udev->state == USB_STATE_NOTATTACHED)
+ 		return -ENODEV;
+ 	if (udev->state == USB_STATE_SUSPENDED)
+@@ -938,6 +940,12 @@ int usb_lock_device_for_reset(struct usb_device *udev,
+ 	}
+ 
+ 	while (!usb_trylock_device(udev)) {
++
++		/* If we can't acquire the lock after waiting one second,
++		 * we're probably deadlocked */
++		if (time_after(jiffies, jiffies_expire))
++			return -EBUSY;
++
+ 		msleep(15);
+ 		if (udev->state == USB_STATE_NOTATTACHED)
+ 			return -ENODEV;

commit bf193d3cd2a3b73f2df74f57106114867946c09c
+Author: Alan Stern 
+Date:   Wed Aug 10 17:12:31 2005 -0400
+
+    [PATCH] USB: Disconnect children when unbinding the hub driver
+    
+    This patch (as554) makes the hub driver disconnect any child USB devices
+    when it is unbound from a hub.  Normally this will never happen, but
+    there are a few oddball ways to unbind the hub driver while leaving the
+    children intact.  For example, the new "unbind" sysfs attribute can be
+    used for this purpose.
+    
+    Given that unbinding hubs with children is now safe, the patch also
+    removes the code that prevented people from doing so using usbfs.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 56c082f34927..b4265aa7d45e 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -1238,7 +1238,6 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg)
+ 	int			retval = 0;
+ 	struct usb_interface    *intf = NULL;
+ 	struct usb_driver       *driver = NULL;
+-	int			i;
+ 
+ 	/* get input parameters and alloc buffer */
+ 	if (copy_from_user(&ctrl, arg, sizeof (ctrl)))
+@@ -1270,15 +1269,6 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg)
+ 	/* disconnect kernel driver from interface */
+ 	case USBDEVFS_DISCONNECT:
+ 
+-		/* don't allow the user to unbind the hub driver from
+-		 * a hub with children to manage */
+-		for (i = 0; i < ps->dev->maxchild; ++i) {
+-			if (ps->dev->children[i])
+-				retval = -EBUSY;
+-		}
+-		if (retval)
+-			break;
+-
+ 		down_write(&usb_bus_type.subsys.rwsem);
+ 		if (intf->dev.driver) {
+ 			driver = to_usb_driver(intf->dev.driver);
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 4a4b41f2665a..9f54e8330f78 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -729,10 +729,29 @@ static int hub_configure(struct usb_hub *hub,
+ 
+ static unsigned highspeed_hubs;
+ 
++/* Called after the hub driver is unbound from a hub with children */
++static void hub_remove_children_work(void *__hub)
++{
++	struct usb_hub		*hub = __hub;
++	struct usb_device	*hdev = hub->hdev;
++	int			i;
++
++	kfree(hub);
++
++	usb_lock_device(hdev);
++	for (i = 0; i < hdev->maxchild; ++i) {
++		if (hdev->children[i])
++			usb_disconnect(&hdev->children[i]);
++	}
++	usb_unlock_device(hdev);
++	usb_put_dev(hdev);
++}
++
+ static void hub_disconnect(struct usb_interface *intf)
+ {
+ 	struct usb_hub *hub = usb_get_intfdata (intf);
+ 	struct usb_device *hdev;
++	int n, port1;
+ 
+ 	usb_set_intfdata (intf, NULL);
+ 	hdev = hub->hdev;
+@@ -760,8 +779,27 @@ static void hub_disconnect(struct usb_interface *intf)
+ 		hub->buffer = NULL;
+ 	}
+ 
+-	/* Free the memory */
+-	kfree(hub);
++	/* If there are any children then this is an unbind only, not a
++	 * physical disconnection.  The active ports must be disabled
++	 * and later on we must call usb_disconnect().  We can't call
++	 * it now because we may not hold the hub's device lock.
++	 */
++	n = 0;
++	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
++		if (hdev->children[port1 - 1]) {
++			++n;
++			hub_port_disable(hub, port1, 1);
++		}
++	}
++
++	if (n == 0)
++		kfree(hub);
++	else {
++		/* Reuse the hub->leds work_struct for our own purposes */
++		INIT_WORK(&hub->leds, hub_remove_children_work, hub);
++		schedule_work(&hub->leds);
++		usb_get_dev(hdev);
++	}
+ }
+ 
+ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)

commit 8b28c7526a302bbfa618f7eab4ef961edd68c9a0
+Author: Alan Stern 
+Date:   Wed Aug 10 17:04:13 2005 -0400
+
+    [PATCH] USB: Code motion in the hub driver
+    
+    This patch (as553) merely moves some code and deletes an unneeded test in
+    the hub driver.  This is in preparation for the patch that follows.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index a220a5e7f4a5..4a4b41f2665a 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -492,6 +492,23 @@ static int hub_hub_status(struct usb_hub *hub,
+ 	return ret;
+ }
+ 
++static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
++{
++	struct usb_device *hdev = hub->hdev;
++	int ret;
++
++	if (hdev->children[port1-1] && set_state) {
++		usb_set_device_state(hdev->children[port1-1],
++				USB_STATE_NOTATTACHED);
++	}
++	ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
++	if (ret)
++		dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
++			port1, ret);
++
++	return ret;
++}
++
+ static int hub_configure(struct usb_hub *hub,
+ 	struct usb_endpoint_descriptor *endpoint)
+ {
+@@ -717,15 +734,12 @@ static void hub_disconnect(struct usb_interface *intf)
+ 	struct usb_hub *hub = usb_get_intfdata (intf);
+ 	struct usb_device *hdev;
+ 
+-	if (!hub)
+-		return;
++	usb_set_intfdata (intf, NULL);
+ 	hdev = hub->hdev;
+ 
+ 	if (hdev->speed == USB_SPEED_HIGH)
+ 		highspeed_hubs--;
+ 
+-	usb_set_intfdata (intf, NULL);
+-
+ 	hub_quiesce(hub);
+ 	usb_free_urb(hub->urb);
+ 	hub->urb = NULL;
+@@ -1430,23 +1444,6 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
+ 	return status;
+ }
+ 
+-static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
+-{
+-	struct usb_device *hdev = hub->hdev;
+-	int ret;
+-
+-	if (hdev->children[port1-1] && set_state) {
+-		usb_set_device_state(hdev->children[port1-1],
+-				USB_STATE_NOTATTACHED);
+-	}
+-	ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
+-	if (ret)
+-		dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
+-			port1, ret);
+-
+-	return ret;
+-}
+-
+ /*
+  * Disable a port and mark a logical connnect-change event, so that some
+  * time later khubd will disconnect() any existing usb_device on the port

commit b375a0495fd622037560c73c05f23ae6f127bb0c
+Author: Alan Stern 
+Date:   Fri Jul 29 16:11:07 2005 -0400
+
+    [PATCH] USB: URB_ASYNC_UNLINK flag removed from the kernel
+    
+    29 July 2005, Cambridge, MA:
+    
+    This afternoon Alan Stern submitted a patch to remove the URB_ASYNC_UNLINK
+    flag from the Linux kernel.  Mr. Stern explained, "This flag is a relic
+    from an earlier, less-well-designed system.  For over a year it hasn't
+    been used for anything other than printing warning messages."
+    
+    An anonymous spokesman for the Linux kernel development community
+    commented, "This is exactly the sort of thing we see happening all the
+    time.  As the kernel evolves, support for old techniques and old code can
+    be jettisoned and replaced by newer, better approaches.  Proprietary
+    operating systems do not have the freedom or flexibility to change so
+    quickly."
+    
+    Mr. Stern, a staff member at Harvard University's Rowland Institute who
+    works on Linux only as a hobby, noted that the patch (labelled as548) did
+    not update two files, keyspan.c and option.c, in the USB drivers' "serial"
+    subdirectory.  "Those files need more extensive changes," he remarked.
+    "They examine the status field of several URBs at times when they're not
+    supposed to.  That will need to be fixed before the URB_ASYNC_UNLINK flag
+    is removed."
+    
+    Greg Kroah-Hartman, the kernel maintainer responsible for overseeing all
+    of Linux's USB drivers, did not respond to our inquiries or return our
+    calls.  His only comment was "Applied, thanks."
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/block/ub.c b/drivers/block/ub.c
+index 57d3279a8815..aa0bf7ee008d 100644
+--- a/drivers/block/ub.c
++++ b/drivers/block/ub.c
+@@ -1010,7 +1010,7 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+ 	sc->last_pipe = sc->send_bulk_pipe;
+ 	usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->send_bulk_pipe,
+ 	    bcb, US_BULK_CB_WRAP_LEN, ub_urb_complete, sc);
+-	sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
++	sc->work_urb.transfer_flags = 0;
+ 
+ 	/* Fill what we shouldn't be filling, because usb-storage did so. */
+ 	sc->work_urb.actual_length = 0;
+@@ -1395,7 +1395,7 @@ static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+ 	usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe,
+ 	    page_address(sg->page) + sg->offset, sg->length,
+ 	    ub_urb_complete, sc);
+-	sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
++	sc->work_urb.transfer_flags = 0;
+ 	sc->work_urb.actual_length = 0;
+ 	sc->work_urb.error_count = 0;
+ 	sc->work_urb.status = 0;
+@@ -1442,7 +1442,7 @@ static int __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+ 	sc->last_pipe = sc->recv_bulk_pipe;
+ 	usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->recv_bulk_pipe,
+ 	    &sc->work_bcs, US_BULK_CS_WRAP_LEN, ub_urb_complete, sc);
+-	sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
++	sc->work_urb.transfer_flags = 0;
+ 	sc->work_urb.actual_length = 0;
+ 	sc->work_urb.error_count = 0;
+ 	sc->work_urb.status = 0;
+@@ -1563,7 +1563,7 @@ static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
+ 
+ 	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
+ 	    (unsigned char*) cr, NULL, 0, ub_urb_complete, sc);
+-	sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
++	sc->work_urb.transfer_flags = 0;
+ 	sc->work_urb.actual_length = 0;
+ 	sc->work_urb.error_count = 0;
+ 	sc->work_urb.status = 0;
+diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
+index 46e0022d3258..6c766fdc51a6 100644
+--- a/drivers/net/irda/irda-usb.c
++++ b/drivers/net/irda/irda-usb.c
+@@ -267,7 +267,7 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self)
+                       frame, IRDA_USB_SPEED_MTU,
+                       speed_bulk_callback, self);
+ 	urb->transfer_buffer_length = USB_IRDA_HEADER;
+-	urb->transfer_flags = URB_ASYNC_UNLINK;
++	urb->transfer_flags = 0;
+ 
+ 	/* Irq disabled -> GFP_ATOMIC */
+ 	if ((ret = usb_submit_urb(urb, GFP_ATOMIC))) {
+@@ -401,15 +401,12 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
+                       skb->data, IRDA_SKB_MAX_MTU,
+                       write_bulk_callback, skb);
+ 	urb->transfer_buffer_length = skb->len;
+-	/* Note : unlink *must* be Asynchronous because of the code in 
+-	 * irda_usb_net_timeout() -> call in irq - Jean II */
+-	urb->transfer_flags = URB_ASYNC_UNLINK;
+ 	/* This flag (URB_ZERO_PACKET) indicates that what we send is not
+ 	 * a continuous stream of data but separate packets.
+ 	 * In this case, the USB layer will insert an empty USB frame (TD)
+ 	 * after each of our packets that is exact multiple of the frame size.
+ 	 * This is how the dongle will detect the end of packet - Jean II */
+-	urb->transfer_flags |= URB_ZERO_PACKET;
++	urb->transfer_flags = URB_ZERO_PACKET;
+ 
+ 	/* Generate min turn time. FIXME: can we do better than this? */
+ 	/* Trying to a turnaround time at this level is trying to measure
+@@ -630,8 +627,6 @@ static void irda_usb_net_timeout(struct net_device *netdev)
+ 			 * in completion handler, because urb->status will
+ 			 * be -ENOENT. We will fix that at the next watchdog,
+ 			 * leaving more time to USB to recover...
+-			 * Also, we are in interrupt, so we need to have
+-			 * URB_ASYNC_UNLINK to work properly...
+ 			 * Jean II */
+ 			done = 1;
+ 			break;
+@@ -1008,9 +1003,7 @@ static int irda_usb_net_close(struct net_device *netdev)
+ 		}
+ 	}
+ 	/* Cancel Tx and speed URB - need to be synchronous to avoid races */
+-	self->tx_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
+ 	usb_kill_urb(self->tx_urb);
+-	self->speed_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
+ 	usb_kill_urb(self->speed_urb);
+ 
+ 	/* Stop and remove instance of IrLAP */
+@@ -1521,9 +1514,7 @@ static void irda_usb_disconnect(struct usb_interface *intf)
+ 			usb_kill_urb(self->rx_urb[i]);
+ 		/* Cancel Tx and speed URB.
+ 		 * Toggle flags to make sure it's synchronous. */
+-		self->tx_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
+ 		usb_kill_urb(self->tx_urb);
+-		self->speed_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
+ 		usb_kill_urb(self->speed_urb);
+ 	}
+ 
+diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
+index 8e184e2641cb..79861ee12a29 100644
+--- a/drivers/usb/atm/cxacru.c
++++ b/drivers/usb/atm/cxacru.c
+@@ -715,13 +715,11 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
+ 			usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD),
+ 			instance->rcv_buf, PAGE_SIZE,
+ 			cxacru_blocking_completion, &instance->rcv_done, 1);
+-	instance->rcv_urb->transfer_flags |= URB_ASYNC_UNLINK;
+ 
+ 	usb_fill_int_urb(instance->snd_urb,
+ 			usb_dev, usb_sndintpipe(usb_dev, CXACRU_EP_CMD),
+ 			instance->snd_buf, PAGE_SIZE,
+ 			cxacru_blocking_completion, &instance->snd_done, 4);
+-	instance->snd_urb->transfer_flags |= URB_ASYNC_UNLINK;
+ 
+ 	init_MUTEX(&instance->cm_serialize);
+ 
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 88d1b376f67c..74197249c245 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -48,7 +48,6 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
+ 
+ 	init_completion(&done); 	
+ 	urb->context = &done;
+-	urb->transfer_flags |= URB_ASYNC_UNLINK;
+ 	urb->actual_length = 0;
+ 	status = usb_submit_urb(urb, GFP_NOIO);
+ 
+@@ -357,8 +356,7 @@ int usb_sg_init (
+ 	if (!io->urbs)
+ 		goto nomem;
+ 
+-	urb_flags = URB_ASYNC_UNLINK | URB_NO_TRANSFER_DMA_MAP
+-			| URB_NO_INTERRUPT;
++	urb_flags = URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT;
+ 	if (usb_pipein (pipe))
+ 		urb_flags |= URB_SHORT_NOT_OK;
+ 
+diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
+index c0feee25ff0a..c846fefb7386 100644
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -309,9 +309,8 @@ int usb_submit_urb(struct urb *urb, unsigned mem_flags)
+ 	unsigned int	allowed;
+ 
+ 	/* enforce simple/standard policy */
+-	allowed = URB_ASYNC_UNLINK;	// affects later unlinks
+-	allowed |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
+-	allowed |= URB_NO_INTERRUPT;
++	allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP |
++			URB_NO_INTERRUPT);
+ 	switch (temp) {
+ 	case PIPE_BULK:
+ 		if (is_out)
+@@ -400,14 +399,8 @@ int usb_submit_urb(struct urb *urb, unsigned mem_flags)
+  * canceled (rather than any other code) and will quickly be removed
+  * from host controller data structures.
+  *
+- * In the past, clearing the URB_ASYNC_UNLINK transfer flag for the
+- * URB indicated that the request was synchronous.  This usage is now
+- * deprecated; if the flag is clear the call will be forwarded to
+- * usb_kill_urb() and the return value will be 0.  In the future, drivers
+- * should call usb_kill_urb() directly for synchronous unlinking.
+- *
+- * When the URB_ASYNC_UNLINK transfer flag for the URB is set, this
+- * request is asynchronous.  Success is indicated by returning -EINPROGRESS,
++ * This request is always asynchronous.
++ * Success is indicated by returning -EINPROGRESS,
+  * at which time the URB will normally have been unlinked but not yet
+  * given back to the device driver.  When it is called, the completion
+  * function will see urb->status == -ECONNRESET.  Failure is indicated
+@@ -453,17 +446,6 @@ int usb_unlink_urb(struct urb *urb)
+ {
+ 	if (!urb)
+ 		return -EINVAL;
+-	if (!(urb->transfer_flags & URB_ASYNC_UNLINK)) {
+-#ifdef CONFIG_DEBUG_KERNEL
+-		if (printk_ratelimit()) {
+-			printk(KERN_NOTICE "usb_unlink_urb() is deprecated for "
+-				"synchronous unlinks.  Use usb_kill_urb() instead.\n");
+-			WARN_ON(1);
+-		}
+-#endif
+-		usb_kill_urb(urb);
+-		return 0;
+-	}
+ 	if (!(urb->dev && urb->dev->bus && urb->dev->bus->op))
+ 		return -ENODEV;
+ 	return urb->dev->bus->op->unlink_urb(urb, -ECONNRESET);
+diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
+index 719c0316cc39..1ab95d24c5e2 100644
+--- a/drivers/usb/input/hid-core.c
++++ b/drivers/usb/input/hid-core.c
+@@ -1688,7 +1688,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
+ 			usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, 0,
+ 					 hid_irq_in, hid, interval);
+ 			hid->urbin->transfer_dma = hid->inbuf_dma;
+-			hid->urbin->transfer_flags |=(URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK);
++			hid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ 		} else {
+ 			if (hid->urbout)
+ 				continue;
+@@ -1698,7 +1698,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
+ 			usb_fill_int_urb(hid->urbout, dev, pipe, hid->outbuf, 0,
+ 					 hid_irq_out, hid, interval);
+ 			hid->urbout->transfer_dma = hid->outbuf_dma;
+-			hid->urbout->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK);
++			hid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ 		}
+ 	}
+ 
+@@ -1750,7 +1750,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
+ 			     hid->ctrlbuf, 1, hid_ctrl, hid);
+ 	hid->urbctrl->setup_dma = hid->cr_dma;
+ 	hid->urbctrl->transfer_dma = hid->ctrlbuf_dma;
+-	hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP | URB_ASYNC_UNLINK);
++	hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
+ 
+ 	return hid;
+ 
+diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
+index 6f7994f5a714..ae4681f9f0ea 100644
+--- a/drivers/usb/misc/auerswald.c
++++ b/drivers/usb/misc/auerswald.c
+@@ -426,7 +426,7 @@ static int auerchain_submit_urb (pauerchain_t acp, struct urb * urb)
+ 
+ /* cancel an urb which is submitted to the chain
+    the result is 0 if the urb is cancelled, or -EINPROGRESS if
+-   URB_ASYNC_UNLINK is set and the function is successfully started.
++   the function is successfully started.
+ */
+ static int auerchain_unlink_urb (pauerchain_t acp, struct urb * urb)
+ {
+@@ -515,7 +515,6 @@ static void auerchain_unlink_all (pauerchain_t acp)
+         acep = acp->active;
+         if (acep) {
+                 urbp = acep->urbp;
+-                urbp->transfer_flags &= ~URB_ASYNC_UNLINK;
+                 dbg ("unlink active urb");
+                 usb_kill_urb (urbp);
+         }
+diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
+index 2fd12264fd53..d63ce6c030f3 100644
+--- a/drivers/usb/misc/sisusbvga/sisusb.c
++++ b/drivers/usb/misc/sisusbvga/sisusb.c
+@@ -229,7 +229,7 @@ sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe,
+ 	usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
+ 		sisusb_bulk_completeout, &sisusb->urbout_context[index]);
+ 
+-	urb->transfer_flags |= (tflags | URB_ASYNC_UNLINK);
++	urb->transfer_flags |= tflags;
+ 	urb->actual_length = 0;
+ 
+ 	if ((urb->transfer_dma = transfer_dma))
+@@ -295,7 +295,7 @@ sisusb_bulkin_msg(struct sisusb_usb_data *sisusb, unsigned int pipe, void *data,
+ 	usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
+ 			sisusb_bulk_completein, sisusb);
+ 
+-	urb->transfer_flags |= (tflags | URB_ASYNC_UNLINK);
++	urb->transfer_flags |= tflags;
+ 	urb->actual_length = 0;
+ 
+ 	if ((urb->transfer_dma = transfer_dma))
+diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
+index fd7fb98e4b20..54799eb0bc60 100644
+--- a/drivers/usb/misc/usbtest.c
++++ b/drivers/usb/misc/usbtest.c
+@@ -986,7 +986,6 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
+ 
+ 		u->context = &context;
+ 		u->complete = ctrl_complete;
+-		u->transfer_flags |= URB_ASYNC_UNLINK;
+ 	}
+ 
+ 	/* queue the urbs */
+@@ -1052,7 +1051,6 @@ static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async)
+ 	urb = simple_alloc_urb (testdev_to_usbdev (dev), pipe, size);
+ 	if (!urb)
+ 		return -ENOMEM;
+-	urb->transfer_flags |= URB_ASYNC_UNLINK;
+ 	urb->context = &completion;
+ 	urb->complete = unlink1_callback;
+ 
+diff --git a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c
+index c8be912f24e1..37ef365a2472 100644
+--- a/drivers/usb/net/catc.c
++++ b/drivers/usb/net/catc.c
+@@ -383,7 +383,6 @@ static void catc_tx_done(struct urb *urb, struct pt_regs *regs)
+ 
+ 	if (urb->status == -ECONNRESET) {
+ 		dbg("Tx Reset.");
+-		urb->transfer_flags &= ~URB_ASYNC_UNLINK;
+ 		urb->status = 0;
+ 		catc->netdev->trans_start = jiffies;
+ 		catc->stats.tx_errors++;
+@@ -445,7 +444,6 @@ static void catc_tx_timeout(struct net_device *netdev)
+ 	struct catc *catc = netdev_priv(netdev);
+ 
+ 	warn("Transmit timed out.");
+-	catc->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
+ 	usb_unlink_urb(catc->tx_urb);
+ }
+ 
+diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
+index 7ffa99b9760f..e04b0ce3611a 100644
+--- a/drivers/usb/net/kaweth.c
++++ b/drivers/usb/net/kaweth.c
+@@ -787,7 +787,6 @@ static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net)
+ 		      kaweth_usb_transmit_complete,
+ 		      kaweth);
+ 	kaweth->end = 0;
+-	kaweth->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
+ 
+ 	if((res = usb_submit_urb(kaweth->tx_urb, GFP_ATOMIC)))
+ 	{
+diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
+index fcd6d3ccef44..7484d34780fc 100644
+--- a/drivers/usb/net/pegasus.c
++++ b/drivers/usb/net/pegasus.c
+@@ -825,7 +825,6 @@ static void pegasus_tx_timeout(struct net_device *net)
+ 	pegasus_t *pegasus = netdev_priv(net);
+ 	if (netif_msg_timer(pegasus))
+ 		printk(KERN_WARNING "%s: tx timeout\n", net->name);
+-	pegasus->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
+ 	usb_unlink_urb(pegasus->tx_urb);
+ 	pegasus->stats.tx_errors++;
+ }
+diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
+index 59ab40ebb394..c3d4e3589e30 100644
+--- a/drivers/usb/net/rtl8150.c
++++ b/drivers/usb/net/rtl8150.c
+@@ -653,7 +653,6 @@ static void rtl8150_tx_timeout(struct net_device *netdev)
+ {
+ 	rtl8150_t *dev = netdev_priv(netdev);
+ 	warn("%s: Tx timeout.", netdev->name);
+-	dev->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
+ 	usb_unlink_urb(dev->tx_urb);
+ 	dev->stats.tx_errors++;
+ }
+diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
+index 4682696450db..3c6eef4168e5 100644
+--- a/drivers/usb/net/usbnet.c
++++ b/drivers/usb/net/usbnet.c
+@@ -2987,7 +2987,6 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, unsigned flags)
+ 
+ 	usb_fill_bulk_urb (urb, dev->udev, dev->in,
+ 		skb->data, size, rx_complete, skb);
+-	urb->transfer_flags |= URB_ASYNC_UNLINK;
+ 
+ 	spin_lock_irqsave (&dev->rxq.lock, lockflags);
+ 
+@@ -3561,7 +3560,6 @@ static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
+ 
+ 	usb_fill_bulk_urb (urb, dev->udev, dev->out,
+ 			skb->data, skb->len, tx_complete, skb);
+-	urb->transfer_flags |= URB_ASYNC_UNLINK;
+ 
+ 	/* don't assume the hardware handles USB_ZERO_PACKET
+ 	 * NOTE:  strictly conforming cdc-ether devices should expect
+diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c
+index fc013978837e..c4e479ee926a 100644
+--- a/drivers/usb/net/zd1201.c
++++ b/drivers/usb/net/zd1201.c
+@@ -847,7 +847,6 @@ static void zd1201_tx_timeout(struct net_device *dev)
+ 		return;
+ 	dev_warn(&zd->usb->dev, "%s: TX timeout, shooting down urb\n",
+ 	    dev->name);
+-	zd->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
+ 	usb_unlink_urb(zd->tx_urb);
+ 	zd->stats.tx_errors++;
+ 	/* Restart the timeout to quiet the watchdog: */
+diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+index e42875152c34..c1ba5301ebfc 100644
+--- a/drivers/usb/storage/transport.c
++++ b/drivers/usb/storage/transport.c
+@@ -96,8 +96,8 @@
+  * or before the URB_ACTIVE bit was set.  If so, it's essential to cancel
+  * the URB if it hasn't been cancelled already (i.e., if the URB_ACTIVE bit
+  * is still set).  Either way, the function must then wait for the URB to
+- * finish.  Note that because the URB_ASYNC_UNLINK flag is set, the URB can
+- * still be in progress even after a call to usb_unlink_urb() returns.
++ * finish.  Note that the URB can still be in progress even after a call to
++ * usb_unlink_urb() returns.
+  *
+  * The idea is that (1) once the ABORTING or DISCONNECTING bit is set,
+  * either the stop_transport() function or the submitting function
+@@ -158,8 +158,7 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)
+ 	 * hasn't been mapped for DMA.  Yes, this is clunky, but it's
+ 	 * easier than always having the caller tell us whether the
+ 	 * transfer buffer has already been mapped. */
+-	us->current_urb->transfer_flags =
+-			URB_ASYNC_UNLINK | URB_NO_SETUP_DMA_MAP;
++	us->current_urb->transfer_flags = URB_NO_SETUP_DMA_MAP;
+ 	if (us->current_urb->transfer_buffer == us->iobuf)
+ 		us->current_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ 	us->current_urb->transfer_dma = us->iobuf_dma;
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 434e35120c65..4dbe580f9335 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -616,7 +616,6 @@ extern int usb_disabled(void);
+ #define URB_ISO_ASAP		0x0002	/* iso-only, urb->start_frame ignored */
+ #define URB_NO_TRANSFER_DMA_MAP	0x0004	/* urb->transfer_dma valid on submit */
+ #define URB_NO_SETUP_DMA_MAP	0x0008	/* urb->setup_dma valid on submit */
+-#define URB_ASYNC_UNLINK	0x0010	/* usb_unlink_urb() returns asap */
+ #define URB_NO_FSBR		0x0020	/* UHCI-specific */
+ #define URB_ZERO_PACKET		0x0040	/* Finish bulk OUTs with short packet */
+ #define URB_NO_INTERRUPT	0x0080	/* HINT: no non-error interrupt needed */
+@@ -724,13 +723,7 @@ typedef void (*usb_complete_t)(struct urb *, struct pt_regs *);
+  * Initialization:
+  *
+  * All URBs submitted must initialize the dev, pipe, transfer_flags (may be
+- * zero), and complete fields.
+- * The URB_ASYNC_UNLINK transfer flag affects later invocations of
+- * the usb_unlink_urb() routine.  Note: Failure to set URB_ASYNC_UNLINK
+- * with usb_unlink_urb() is deprecated.  For synchronous unlinks use
+- * usb_kill_urb() instead.
+- *
+- * All URBs must also initialize 
++ * zero), and complete fields.  All URBs must also initialize
+  * transfer_buffer and transfer_buffer_length.  They may provide the
+  * URB_SHORT_NOT_OK transfer flag, indicating that short reads are
+  * to be treated as errors; that flag is invalid for write requests.
+diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
+index 5aa5fe651a8a..bfbec5876659 100644
+--- a/sound/usb/usbaudio.c
++++ b/sound/usb/usbaudio.c
+@@ -735,10 +735,9 @@ static int deactivate_urbs(snd_usb_substream_t *subs, int force, int can_sleep)
+ 		if (test_bit(i, &subs->active_mask)) {
+ 			if (! test_and_set_bit(i, &subs->unlink_mask)) {
+ 				struct urb *u = subs->dataurb[i].urb;
+-				if (async) {
+-					u->transfer_flags |= URB_ASYNC_UNLINK;
++				if (async)
+ 					usb_unlink_urb(u);
+-				} else
++				else
+ 					usb_kill_urb(u);
+ 			}
+ 		}
+@@ -748,10 +747,9 @@ static int deactivate_urbs(snd_usb_substream_t *subs, int force, int can_sleep)
+ 			if (test_bit(i+16, &subs->active_mask)) {
+  				if (! test_and_set_bit(i+16, &subs->unlink_mask)) {
+ 					struct urb *u = subs->syncurb[i].urb;
+-					if (async) {
+-						u->transfer_flags |= URB_ASYNC_UNLINK;
++					if (async)
+ 						usb_unlink_urb(u);
+-					} else
++					else
+ 						usb_kill_urb(u);
+ 				}
+ 			}

commit fad21bdf56a25e1cb3e92bba33349de368e8f0b0
+Author: Alan Stern 
+Date:   Wed Aug 10 15:15:57 2005 -0400
+
+    [PATCH] USB: Fix regression in core/devio.c
+    
+    This patch (as551) fixes another little problem recently added to the
+    USB core.  Someone didn't fix the type of the first argument to
+    unregister_chrdev_region.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index d12bc5e84a1a..56c082f34927 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -76,6 +76,8 @@ MODULE_PARM_DESC (usbfs_snoop, "true to log all usbfs traffic");
+ 			dev_info( dev , format , ## arg);	\
+ 	} while (0)
+ 
++#define USB_DEVICE_DEV		MKDEV(USB_DEVICE_MAJOR, 0)
++
+ 
+ #define	MAX_USBFS_BUFFER_SIZE	16384
+ 
+@@ -1530,18 +1532,17 @@ int __init usbdev_init(void)
+ {
+ 	int retval;
+ 
+-	retval = register_chrdev_region(MKDEV(USB_DEVICE_MAJOR, 0),
+-				        USB_DEVICE_MAX, "usb_device");
++	retval = register_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX,
++			"usb_device");
+ 	if (retval) {
+ 		err("unable to register minors for usb_device");
+ 		goto out;
+ 	}
+ 	cdev_init(&usb_device_cdev, &usbfs_device_file_operations);
+-	retval = cdev_add(&usb_device_cdev,
+-			  MKDEV(USB_DEVICE_MAJOR, 0), USB_DEVICE_MAX);
++	retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX);
+ 	if (retval) {
+ 		err("unable to get usb_device major %d", USB_DEVICE_MAJOR);
+-		unregister_chrdev_region(USB_DEVICE_MAJOR, USB_DEVICE_MAX);
++		unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
+ 		goto out;
+ 	}
+ 	usb_device_class = class_create(THIS_MODULE, "usb_device");
+@@ -1550,7 +1551,7 @@ int __init usbdev_init(void)
+ 		retval = PTR_ERR(usb_device_class);
+ 		usb_device_class = NULL;
+ 		cdev_del(&usb_device_cdev);
+-		unregister_chrdev_region(USB_DEVICE_MAJOR, USB_DEVICE_MAX);
++		unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
+ 	}
+ 
+ out:
+@@ -1561,6 +1562,6 @@ void usbdev_cleanup(void)
+ {
+ 	class_destroy(usb_device_class);
+ 	cdev_del(&usb_device_cdev);
+-	unregister_chrdev_region(USB_DEVICE_MAJOR, USB_DEVICE_MAX);
++	unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
+ }
+ 

commit 11f3859b1e85dd408756c72e228cfb5aa7230c87
+Author: Alan Stern 
+Date:   Wed Aug 10 15:18:44 2005 -0400
+
+    [PATCH] PCI: Fix regression in pci_enable_device_bars
+    
+    This patch (as552) fixes yet another small problem recently added.  If an
+    attempt to put a PCI device back into D0 fails because the device doesn't
+    support PCI PM, it shouldn't count as error.  Without this patch the UHCI
+    controllers on my Intel motherboard don't work.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
+index afee2de3f323..3dcb83d7eb25 100644
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -445,7 +445,7 @@ pci_enable_device_bars(struct pci_dev *dev, int bars)
+ 	int err;
+ 
+ 	err = pci_set_power_state(dev, PCI_D0);
+-	if (err)
++	if (err < 0 && err != -EIO)
+ 		return err;
+ 	err = pcibios_enable_device(dev, bars);
+ 	if (err < 0)

commit 4451e472627881e3e2240b224f127c99be500f91
+Author: Alan Stern 
+Date:   Tue Jul 12 10:45:17 2005 -0400
+
+    [SCSI] sd: pause in sd_spinup_disk for slow USB devices
+    
+    This patch adds a delay tailored for USB flash devices that are slow to
+    initialize their firmware.  The symptom is a repeated Unit Attention with
+    ASC=0x28 (Not Ready to Ready transition).  The patch will wait for up to 5
+    seconds for such devices to become ready.  Normal devices won't send the
+    repeated Unit Attention sense key and hence won't trigger the patch.
+    
+    This fixes a problem with James Roberts-Thomson's USB device, and I've
+    seen several reports of other devices exhibiting the same symptoms --
+    presumably they will be helped as well.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+index 0410e1bf109a..41ba0809f791 100644
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -984,7 +984,7 @@ static void
+ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname,
+ 	       struct scsi_request *SRpnt, unsigned char *buffer) {
+ 	unsigned char cmd[10];
+-	unsigned long spintime_value = 0;
++	unsigned long spintime_expire = 0;
+ 	int retries, spintime;
+ 	unsigned int the_result;
+ 	struct scsi_sense_hdr sshdr;
+@@ -1071,12 +1071,27 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname,
+ 				scsi_wait_req(SRpnt, (void *)cmd, 
+ 					      (void *) buffer, 0/*512*/, 
+ 					      SD_TIMEOUT, SD_MAX_RETRIES);
+-				spintime_value = jiffies;
++				spintime_expire = jiffies + 100 * HZ;
++				spintime = 1;
+ 			}
+-			spintime = 1;
+ 			/* Wait 1 second for next try */
+ 			msleep(1000);
+ 			printk(".");
++
++		/*
++		 * Wait for USB flash devices with slow firmware.
++		 * Yes, this sense key/ASC combination shouldn't
++		 * occur here.  It's characteristic of these devices.
++		 */
++		} else if (sense_valid &&
++				sshdr.sense_key == UNIT_ATTENTION &&
++				sshdr.asc == 0x28) {
++			if (!spintime) {
++				spintime_expire = jiffies + 5 * HZ;
++				spintime = 1;
++			}
++			/* Wait 1 second for next try */
++			msleep(1000);
+ 		} else {
+ 			/* we don't understand the sense code, so it's
+ 			 * probably pointless to loop */
+@@ -1088,8 +1103,7 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname,
+ 			break;
+ 		}
+ 				
+-	} while (spintime &&
+-		 time_after(spintime_value + 100 * HZ, jiffies));
++	} while (spintime && time_before_eq(jiffies, spintime_expire));
+ 
+ 	if (spintime) {
+ 		if (scsi_status_is_good(the_result))

commit e47373ec1c9aab9ee134f4e2b8249957e9f4c7ef
+Author: Alan Stern 
+Date:   Wed Mar 30 15:05:45 2005 -0500
+
+    [SCSI] return success after retries in scsi_eh_tur
+    
+    The problem lies in the way the error handler uses TEST UNIT READY to
+    tell whether error recovery has succeeded.  The scsi_eh_tur function
+    gives up after one round of retrying; after that it decides that more
+    error recovery is needed.
+    
+    However TUR is liable to report sense data indicating a retry is needed
+    when in fact error recovery has succeeded.  A typical example might be
+    SK=2, ASC=4, ASCQ=1 (Logical unit in process of becoming ready).  The mere
+    fact that we were able to get a sensible reply to the TUR should indicate
+    that the device is working well enough to stop error recovery.
+    
+    I ran across a case back in January where this happened.  A CD-ROM drive
+    timed out the INQUIRY command, and a device reset fixed the blockage.
+    But then the drive kept responding with 2/4/1 -- because it was spinning
+    up I suppose -- until the error handler gave up and placed it offline.
+    If the initial INQUIRY had received the 2/4/1 instead, everything would
+    have worked okay.  It doesn't seem reasonable for things to fail just
+    because the error handler had started running.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
+index e9c451ba71fc..688bce740786 100644
+--- a/drivers/scsi/scsi_error.c
++++ b/drivers/scsi/scsi_error.c
+@@ -776,9 +776,11 @@ static int scsi_eh_tur(struct scsi_cmnd *scmd)
+ 		__FUNCTION__, scmd, rtn));
+ 	if (rtn == SUCCESS)
+ 		return 0;
+-	else if (rtn == NEEDS_RETRY)
++	else if (rtn == NEEDS_RETRY) {
+ 		if (retry_cnt--)
+ 			goto retry_tur;
++		return 0;
++	}
+ 	return 1;
+ }
+ 

commit 86d30741e480f40676c2173e1153368a4846da48
+Author: Alan Stern 
+Date:   Fri Jul 29 12:17:16 2005 -0700
+
+    [PATCH] USB: Usbcore: Don't try to delete unregistered interfaces
+    
+    This patch handles a rarely-encountered failure mode in usbcore.  It's
+    legal for device_add to fail (although now it happens even more rarely
+    than before since failure to bind a driver is no longer fatal).  So when
+    we destroy the interfaces in a configuration, we shouldn't try to delete
+    ones which weren't successfully registered.  Also, failure to register an
+    interface shouldn't be fatal either -- I think; you may disagree about
+    this part of the patch.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index a428ef479bd7..88d1b376f67c 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -985,8 +985,10 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
+ 		for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
+ 			struct usb_interface	*interface;
+ 
+-			/* remove this interface */
++			/* remove this interface if it has been registered */
+ 			interface = dev->actconfig->interface[i];
++			if (!klist_node_attached(&interface->dev.knode_bus))
++				continue;
+ 			dev_dbg (&dev->dev, "unregistering interface %s\n",
+ 				interface->dev.bus_id);
+ 			usb_remove_sysfs_intf_files(interface);
+@@ -1439,7 +1441,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
+ 		}
+ 	}
+ 
+-	return ret;
++	return 0;
+ }
+ 
+ // synchronous request completion model

commit fe0410c7f43e133e156e54e3156392e800bedc21
+Author: Alan Stern 
+Date:   Fri Jul 29 12:16:58 2005 -0700
+
+    [PATCH] USB: usbfs: Don't leak uninitialized data
+    
+    This patch fixes an information leak in the usbfs snoop facility:
+    uninitialized data from __get_free_page can be returned to userspace and
+    written to the system log.  It also improves the snoop output by printing
+    the wLength value.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 787c27a63c51..f86bf1454e21 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -569,8 +569,11 @@ static int proc_control(struct dev_state *ps, void __user *arg)
+ 			free_page((unsigned long)tbuf);
+ 			return -EINVAL;
+ 		}
+-		snoop(&dev->dev, "control read: bRequest=%02x bRrequestType=%02x wValue=%04x wIndex=%04x\n", 
+-			ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, ctrl.wIndex);
++		snoop(&dev->dev, "control read: bRequest=%02x "
++				"bRrequestType=%02x wValue=%04x "
++				"wIndex=%04x wLength=%04x\n",
++			ctrl.bRequest, ctrl.bRequestType, ctrl.wValue,
++				ctrl.wIndex, ctrl.wLength);
+ 
+ 		usb_unlock_device(dev);
+ 		i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType,
+@@ -579,11 +582,11 @@ static int proc_control(struct dev_state *ps, void __user *arg)
+ 		if ((i > 0) && ctrl.wLength) {
+ 			if (usbfs_snoop) {
+ 				dev_info(&dev->dev, "control read: data ");
+-				for (j = 0; j < ctrl.wLength; ++j)
++				for (j = 0; j < i; ++j)
+ 					printk ("%02x ", (unsigned char)(tbuf)[j]);
+ 				printk("\n");
+ 			}
+-			if (copy_to_user(ctrl.data, tbuf, ctrl.wLength)) {
++			if (copy_to_user(ctrl.data, tbuf, i)) {
+ 				free_page((unsigned long)tbuf);
+ 				return -EFAULT;
+ 			}
+@@ -595,8 +598,11 @@ static int proc_control(struct dev_state *ps, void __user *arg)
+ 				return -EFAULT;
+ 			}
+ 		}
+-		snoop(&dev->dev, "control write: bRequest=%02x bRrequestType=%02x wValue=%04x wIndex=%04x\n", 
+-			ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, ctrl.wIndex);
++		snoop(&dev->dev, "control write: bRequest=%02x "
++				"bRrequestType=%02x wValue=%04x "
++				"wIndex=%04x wLength=%04x\n",
++			ctrl.bRequest, ctrl.bRequestType, ctrl.wValue,
++				ctrl.wIndex, ctrl.wLength);
+ 		if (usbfs_snoop) {
+ 			dev_info(&dev->dev, "control write: data: ");
+ 			for (j = 0; j < ctrl.wLength; ++j)

commit b24b1033451fcc87087a692fc47ca45daebd51ac
+Author: Alan Stern 
+Date:   Wed Jul 27 11:43:46 2005 -0700
+
+    [PATCH] scsi_scan: check return code from scsi_sysfs_add_sdev
+    
+    Adds a missing check for an error return code from scsi_sysfs_add_sdev.
+    This resolves entry #4863 in the OSDL bugzilla.  Although in that bug
+    report the failure occurred because of a confusion over scanning vs.
+    rescanning, in general add_sdev can fail for a number of reasons (the
+    simplest being insufficient memory) and the caller should cope properly.
+    
+    Signed-off-by: Alan Stern 
+    Cc: James Bottomley 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+index ad3a5b142468..2d3c4ac475f2 100644
+--- a/drivers/scsi/scsi_scan.c
++++ b/drivers/scsi/scsi_scan.c
+@@ -756,7 +756,8 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags)
+ 	 * register it and tell the rest of the kernel
+ 	 * about it.
+ 	 */
+-	scsi_sysfs_add_sdev(sdev);
++	if (scsi_sysfs_add_sdev(sdev) != 0)
++		return SCSI_SCAN_NO_RESPONSE;
+ 
+ 	return SCSI_SCAN_LUN_PRESENT;
+ }

commit 0ed0c0c48c508578c30aa58f755ca0d692636906
+Author: Alan Stern 
+Date:   Wed Jun 15 15:49:48 2005 -0400
+
+    [PATCH] USB: usbcore: inverted test for resuming interfaces
+    
+    This one-liner fixes a test for interfaces that are already resumed.
+    
+    It would be nice if this could get into 2.6.12, but it's not critical
+    since it only affects people doing selective (runtime) suspend/resume.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 63ee3d97b6a9..32ff32181852 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1733,7 +1733,7 @@ static int finish_port_resume(struct usb_device *udev)
+ 			struct usb_driver	*driver;
+ 
+ 			intf = udev->actconfig->interface[i];
+-			if (intf->dev.power.power_state == PMSG_SUSPEND)
++			if (intf->dev.power.power_state == PMSG_ON)
+ 				continue;
+ 			if (!intf->dev.driver) {
+ 				/* FIXME maybe force to alt 0 */

commit e07fefa6b212f43c40fdbc1a62de690d91a4b617
+Author: Alan Stern 
+Date:   Tue May 31 16:33:21 2005 -0400
+
+    [PATCH] USB UHCI: Detect invalid ports
+    
+    This patch changes the way uhci-hcd detects valid ports.  The
+    specification doesn't mention any way to find out how many ports a
+    controller has, so the driver has to use some heuristics, reading the port
+    status and control register and deciding whether the value makes sense.
+    With this patch the driver will recognize a typical failure mode (all bits
+    set to one) for nonexistent ports and won't assume there are always at
+    least 2 ports -- such an assumption seems silly if the heuristics have
+    already shown that the ports don't exist.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index fdf54295da73..0d5d2545bf07 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -495,24 +495,24 @@ static int uhci_reset(struct usb_hcd *hcd)
+ 
+ 	/* The UHCI spec says devices must have 2 ports, and goes on to say
+ 	 * they may have more but gives no way to determine how many there
+-	 * are.  However, according to the UHCI spec, Bit 7 of the port
++	 * are.  However according to the UHCI spec, Bit 7 of the port
+ 	 * status and control register is always set to 1.  So we try to
+-	 * use this to our advantage.
++	 * use this to our advantage.  Another common failure mode when
++	 * a nonexistent register is addressed is to return all ones, so
++	 * we test for that also.
+ 	 */
+ 	for (port = 0; port < (io_size - USBPORTSC1) / 2; port++) {
+ 		unsigned int portstatus;
+ 
+ 		portstatus = inw(uhci->io_addr + USBPORTSC1 + (port * 2));
+-		if (!(portstatus & 0x0080))
++		if (!(portstatus & 0x0080) || portstatus == 0xffff)
+ 			break;
+ 	}
+ 	if (debug)
+ 		dev_info(uhci_dev(uhci), "detected %d ports\n", port);
+ 
+-	/* Anything less than 2 or greater than 7 is weird,
+-	 * so we'll ignore it.
+-	 */
+-	if (port < 2 || port > UHCI_RH_MAXCHILD) {
++	/* Anything greater than 7 is weird so we'll ignore it. */
++	if (port > UHCI_RH_MAXCHILD) {
+ 		dev_info(uhci_dev(uhci), "port count misdetected? "
+ 				"forcing to 2 ports\n");
+ 		port = 2;

commit 391eca9d8892a940ff8dbfee2ca78942e05c2d37
+Author: Alan Stern 
+Date:   Tue May 10 15:34:16 2005 -0400
+
+    [PATCH] USB: dummy_hcd: add suspend/resume support
+    
+    This patch adds support to dummy_hcd for suspending and resuming the root
+    hub and the emulated platform devices.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index c78c64ae87af..4d692670f288 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -65,7 +65,7 @@
+ 
+ 
+ #define DRIVER_DESC	"USB Host+Gadget Emulator"
+-#define DRIVER_VERSION	"17 Dec 2004"
++#define DRIVER_VERSION	"02 May 2005"
+ 
+ static const char	driver_name [] = "dummy_hcd";
+ static const char	driver_desc [] = "USB Host+Gadget Emulator";
+@@ -150,6 +150,13 @@ struct urbp {
+ 	struct list_head	urbp_list;
+ };
+ 
++
++enum dummy_rh_state {
++	DUMMY_RH_RESET,
++	DUMMY_RH_SUSPENDED,
++	DUMMY_RH_RUNNING
++};
++
+ struct dummy {
+ 	spinlock_t			lock;
+ 
+@@ -163,6 +170,7 @@ struct dummy {
+ 	struct dummy_request		fifo_req;
+ 	u8				fifo_buf [FIFO_SIZE];
+ 	u16				devstatus;
++	unsigned			udc_suspended:1;
+ 	unsigned			pullup:1;
+ 	unsigned			active:1;
+ 	unsigned			old_active:1;
+@@ -170,6 +178,7 @@ struct dummy {
+ 	/*
+ 	 * MASTER/HOST side support
+ 	 */
++	enum dummy_rh_state		rh_state;
+ 	struct timer_list		timer;
+ 	u32				port_status;
+ 	u32				old_status;
+@@ -262,7 +271,9 @@ set_link_state (struct dummy *dum)
+ 	dum->active = 0;
+ 	if ((dum->port_status & USB_PORT_STAT_POWER) == 0)
+ 		dum->port_status = 0;
+-	else if (!dum->pullup) {
++
++	/* UDC suspend must cause a disconnect */
++	else if (!dum->pullup || dum->udc_suspended) {
+ 		dum->port_status &= ~(USB_PORT_STAT_CONNECTION |
+ 					USB_PORT_STAT_ENABLE |
+ 					USB_PORT_STAT_LOW_SPEED |
+@@ -276,7 +287,8 @@ set_link_state (struct dummy *dum)
+ 			dum->port_status |= (USB_PORT_STAT_C_CONNECTION << 16);
+ 		if ((dum->port_status & USB_PORT_STAT_ENABLE) == 0)
+ 			dum->port_status &= ~USB_PORT_STAT_SUSPEND;
+-		else if ((dum->port_status & USB_PORT_STAT_SUSPEND) == 0)
++		else if ((dum->port_status & USB_PORT_STAT_SUSPEND) == 0 &&
++				dum->rh_state != DUMMY_RH_SUSPENDED)
+ 			dum->active = 1;
+ 	}
+ 
+@@ -675,11 +687,16 @@ static int dummy_wakeup (struct usb_gadget *_gadget)
+ 	struct dummy	*dum;
+ 
+ 	dum = gadget_to_dummy (_gadget);
+-	if (!(dum->port_status & USB_PORT_STAT_SUSPEND)
+-			|| !(dum->devstatus &
+-				( (1 << USB_DEVICE_B_HNP_ENABLE)
++	if (!(dum->devstatus &	( (1 << USB_DEVICE_B_HNP_ENABLE)
+ 				| (1 << USB_DEVICE_REMOTE_WAKEUP))))
+ 		return -EINVAL;
++	if ((dum->port_status & USB_PORT_STAT_CONNECTION) == 0)
++		return -ENOLINK;
++	if ((dum->port_status & USB_PORT_STAT_SUSPEND) == 0 &&
++			 dum->rh_state != DUMMY_RH_SUSPENDED)
++		return -EIO;
++
++	/* FIXME: What if the root hub is suspended but the port isn't? */
+ 
+ 	/* hub notices our request, issues downstream resume, etc */
+ 	dum->resuming = 1;
+@@ -917,11 +934,50 @@ static int dummy_udc_remove (struct device *dev)
+ 	return 0;
+ }
+ 
++static int dummy_udc_suspend (struct device *dev, pm_message_t state,
++		u32 level)
++{
++	struct dummy	*dum = dev_get_drvdata(dev);
++
++	if (level != SUSPEND_DISABLE)
++		return 0;
++
++	dev_dbg (dev, "%s\n", __FUNCTION__);
++	spin_lock_irq (&dum->lock);
++	dum->udc_suspended = 1;
++	set_link_state (dum);
++	spin_unlock_irq (&dum->lock);
++
++	dev->power.power_state = state;
++	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
++	return 0;
++}
++
++static int dummy_udc_resume (struct device *dev, u32 level)
++{
++	struct dummy	*dum = dev_get_drvdata(dev);
++
++	if (level != RESUME_ENABLE)
++		return 0;
++
++	dev_dbg (dev, "%s\n", __FUNCTION__);
++	spin_lock_irq (&dum->lock);
++	dum->udc_suspended = 0;
++	set_link_state (dum);
++	spin_unlock_irq (&dum->lock);
++
++	dev->power.power_state = PMSG_ON;
++	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
++	return 0;
++}
++
+ static struct device_driver dummy_udc_driver = {
+ 	.name		= (char *) gadget_name,
+ 	.bus		= &platform_bus_type,
+ 	.probe		= dummy_udc_probe,
+ 	.remove		= dummy_udc_remove,
++	.suspend	= dummy_udc_suspend,
++	.resume		= dummy_udc_resume,
+ };
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -980,7 +1036,16 @@ static int dummy_urb_enqueue (
+ 
+ static int dummy_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
+ {
+-	/* giveback happens automatically in timer callback */
++	struct dummy	*dum;
++	unsigned long	flags;
++
++	/* giveback happens automatically in timer callback,
++	 * so make sure the callback happens */
++	dum = hcd_to_dummy (hcd);
++	spin_lock_irqsave (&dum->lock, flags);
++	if (dum->rh_state != DUMMY_RH_RUNNING && !list_empty(&dum->urbp_list))
++		mod_timer (&dum->timer, jiffies);
++	spin_unlock_irqrestore (&dum->lock, flags);
+ 	return 0;
+ }
+ 
+@@ -1222,7 +1287,8 @@ static void dummy_timer (unsigned long _dum)
+ 		if (urb->status != -EINPROGRESS) {
+ 			/* likely it was just unlinked */
+ 			goto return_urb;
+-		}
++		} else if (dum->rh_state != DUMMY_RH_RUNNING)
++			continue;
+ 		type = usb_pipetype (urb->pipe);
+ 
+ 		/* used up this frame's non-periodic bandwidth?
+@@ -1486,12 +1552,12 @@ static void dummy_timer (unsigned long _dum)
+ 		goto restart;
+ 	}
+ 
+-	/* want a 1 msec delay here */
+-	if (!list_empty (&dum->urbp_list))
+-		mod_timer (&dum->timer, jiffies + msecs_to_jiffies(1));
+-	else {
++	if (list_empty (&dum->urbp_list)) {
+ 		usb_put_dev (dum->udev);
+ 		dum->udev = NULL;
++	} else if (dum->rh_state == DUMMY_RH_RUNNING) {
++		/* want a 1 msec delay here */
++		mod_timer (&dum->timer, jiffies + msecs_to_jiffies(1));
+ 	}
+ 
+ 	spin_unlock_irqrestore (&dum->lock, flags);
+@@ -1510,11 +1576,13 @@ static int dummy_hub_status (struct usb_hcd *hcd, char *buf)
+ {
+ 	struct dummy		*dum;
+ 	unsigned long		flags;
+-	int			retval;
++	int			retval = 0;
+ 
+ 	dum = hcd_to_dummy (hcd);
+ 
+ 	spin_lock_irqsave (&dum->lock, flags);
++	if (hcd->state != HC_STATE_RUNNING)
++		goto done;
+ 
+ 	if (dum->resuming && time_after_eq (jiffies, dum->re_timeout)) {
+ 		dum->port_status |= (USB_PORT_STAT_C_SUSPEND << 16);
+@@ -1522,14 +1590,15 @@ static int dummy_hub_status (struct usb_hcd *hcd, char *buf)
+ 		set_link_state (dum);
+ 	}
+ 
+-	if (!(dum->port_status & PORT_C_MASK))
+-		retval = 0;
+-	else {
++	if ((dum->port_status & PORT_C_MASK) != 0) {
+ 		*buf = (1 << 1);
+ 		dev_dbg (dummy_dev(dum), "port status 0x%08x has changes\n",
+-			dum->port_status);
++				dum->port_status);
+ 		retval = 1;
++		if (dum->rh_state == DUMMY_RH_SUSPENDED)
++			usb_hcd_resume_root_hub (hcd);
+ 	}
++done:
+ 	spin_unlock_irqrestore (&dum->lock, flags);
+ 	return retval;
+ }
+@@ -1559,6 +1628,9 @@ static int dummy_hub_control (
+ 	int		retval = 0;
+ 	unsigned long	flags;
+ 
++	if (hcd->state != HC_STATE_RUNNING)
++		return -ETIMEDOUT;
++
+ 	dum = hcd_to_dummy (hcd);
+ 	spin_lock_irqsave (&dum->lock, flags);
+ 	switch (typeReq) {
+@@ -1658,6 +1730,7 @@ static int dummy_hub_control (
+ 			dum->port_status &= ~(USB_PORT_STAT_ENABLE
+ 					| USB_PORT_STAT_LOW_SPEED
+ 					| USB_PORT_STAT_HIGH_SPEED);
++			dum->devstatus = 0;
+ 			/* 50msec reset signaling */
+ 			dum->re_timeout = jiffies + msecs_to_jiffies(50);
+ 			/* FALLS THROUGH */
+@@ -1684,6 +1757,29 @@ static int dummy_hub_control (
+ 	return retval;
+ }
+ 
++static int dummy_hub_suspend (struct usb_hcd *hcd)
++{
++	struct dummy *dum = hcd_to_dummy (hcd);
++
++	spin_lock_irq (&dum->lock);
++	dum->rh_state = DUMMY_RH_SUSPENDED;
++	set_link_state (dum);
++	spin_unlock_irq (&dum->lock);
++	return 0;
++}
++
++static int dummy_hub_resume (struct usb_hcd *hcd)
++{
++	struct dummy *dum = hcd_to_dummy (hcd);
++
++	spin_lock_irq (&dum->lock);
++	dum->rh_state = DUMMY_RH_RUNNING;
++	set_link_state (dum);
++	if (!list_empty(&dum->urbp_list))
++		mod_timer (&dum->timer, jiffies);
++	spin_unlock_irq (&dum->lock);
++	return 0;
++}
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+@@ -1751,6 +1847,7 @@ static int dummy_start (struct usb_hcd *hcd)
+ 	init_timer (&dum->timer);
+ 	dum->timer.function = dummy_timer;
+ 	dum->timer.data = (unsigned long) dum;
++	dum->rh_state = DUMMY_RH_RUNNING;
+ 
+ 	INIT_LIST_HEAD (&dum->urbp_list);
+ 
+@@ -1803,6 +1900,8 @@ static const struct hc_driver dummy_hcd = {
+ 
+ 	.hub_status_data = 	dummy_hub_status,
+ 	.hub_control = 		dummy_hub_control,
++	.hub_suspend =		dummy_hub_suspend,
++	.hub_resume =		dummy_hub_resume,
+ };
+ 
+ static int dummy_hcd_probe (struct device *dev)
+@@ -1836,11 +1935,57 @@ static int dummy_hcd_remove (struct device *dev)
+ 	return 0;
+ }
+ 
++static int dummy_hcd_suspend (struct device *dev, pm_message_t state,
++		u32 level)
++{
++	struct usb_hcd		*hcd;
++
++	if (level != SUSPEND_DISABLE)
++		return 0;
++
++	dev_dbg (dev, "%s\n", __FUNCTION__);
++	hcd = dev_get_drvdata (dev);
++
++#ifndef CONFIG_USB_SUSPEND
++	/* Otherwise this would never happen */
++	usb_lock_device (hcd->self.root_hub);
++	dummy_hub_suspend (hcd);
++	usb_unlock_device (hcd->self.root_hub);
++#endif
++
++	hcd->state = HC_STATE_SUSPENDED;
++	return 0;
++}
++
++static int dummy_hcd_resume (struct device *dev, u32 level)
++{
++	struct usb_hcd		*hcd;
++
++	if (level != RESUME_ENABLE)
++		return 0;
++
++	dev_dbg (dev, "%s\n", __FUNCTION__);
++	hcd = dev_get_drvdata (dev);
++	hcd->state = HC_STATE_RUNNING;
++
++#ifndef CONFIG_USB_SUSPEND
++	/* Otherwise this would never happen */
++	usb_lock_device (hcd->self.root_hub);
++	dummy_hub_resume (hcd);
++	usb_unlock_device (hcd->self.root_hub);
++#endif
++
++	usb_hcd_poll_rh_status (hcd);
++	return 0;
++}
++
+ static struct device_driver dummy_hcd_driver = {
+ 	.name		= (char *) driver_name,
+ 	.bus		= &platform_bus_type,
+ 	.probe		= dummy_hcd_probe,
+ 	.remove		= dummy_hcd_remove,
++	.suspend	= dummy_hcd_suspend,
++	.resume		= dummy_hcd_resume,
+ };
+ 
+ /*-------------------------------------------------------------------------*/

commit cc095b0b5b653dca3e106710a72ba28b5bb7456b
+Author: Alan Stern 
+Date:   Tue May 10 15:28:38 2005 -0400
+
+    [PATCH] USB: dummy_hcd: sparse cleanups
+    
+    This patch fixes the byte-ordering issue for setup packets in the
+    dummy_hcd driver and cleans up a few things that sparse -Wbitwise
+    dislikes.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index f9540adf2a4f..c78c64ae87af 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -734,7 +734,7 @@ show_function (struct device *dev, struct device_attribute *attr, char *buf)
+ 		return 0;
+ 	return scnprintf (buf, PAGE_SIZE, "%s\n", dum->driver->function);
+ }
+-DEVICE_ATTR (function, S_IRUGO, show_function, NULL);
++static DEVICE_ATTR (function, S_IRUGO, show_function, NULL);
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+@@ -857,6 +857,9 @@ EXPORT_SYMBOL (usb_gadget_unregister_driver);
+ 
+ #undef is_enabled
+ 
++/* just declare this in any driver that really need it */
++extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode);
++
+ int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode)
+ {
+ 	return -ENOSYS;
+@@ -1122,7 +1125,6 @@ static int periodic_bytes (struct dummy *dum, struct dummy_ep *ep)
+ 
+ 		/* high bandwidth mode */
+ 		tmp = le16_to_cpu(ep->desc->wMaxPacketSize);
+-		tmp = le16_to_cpu (tmp);
+ 		tmp = (tmp >> 11) & 0x03;
+ 		tmp *= 8 /* applies to entire frame */;
+ 		limit += limit * tmp;
+@@ -1265,9 +1267,14 @@ static void dummy_timer (unsigned long _dum)
+ 			struct usb_ctrlrequest		setup;
+ 			int				value = 1;
+ 			struct dummy_ep			*ep2;
++			unsigned			w_index;
++			unsigned			w_value;
+ 
+ 			setup = *(struct usb_ctrlrequest*) urb->setup_packet;
+-			if (setup.wLength != urb->transfer_buffer_length) {
++			w_index = le16_to_cpu(setup.wIndex);
++			w_value = le16_to_cpu(setup.wValue);
++			if (le16_to_cpu(setup.wLength) !=
++					urb->transfer_buffer_length) {
+ 				maybe_set_status (urb, -EOVERFLOW);
+ 				goto return_urb;
+ 			}
+@@ -1297,16 +1304,16 @@ static void dummy_timer (unsigned long _dum)
+ 			case USB_REQ_SET_ADDRESS:
+ 				if (setup.bRequestType != Dev_Request)
+ 					break;
+-				dum->address = setup.wValue;
++				dum->address = w_value;
+ 				maybe_set_status (urb, 0);
+ 				dev_dbg (udc_dev(dum), "set_address = %d\n",
+-						setup.wValue);
++						w_value);
+ 				value = 0;
+ 				break;
+ 			case USB_REQ_SET_FEATURE:
+ 				if (setup.bRequestType == Dev_Request) {
+ 					value = 0;
+-					switch (setup.wValue) {
++					switch (w_value) {
+ 					case USB_DEVICE_REMOTE_WAKEUP:
+ 						break;
+ 					case USB_DEVICE_B_HNP_ENABLE:
+@@ -1324,14 +1331,13 @@ static void dummy_timer (unsigned long _dum)
+ 					}
+ 					if (value == 0) {
+ 						dum->devstatus |=
+-							(1 << setup.wValue);
++							(1 << w_value);
+ 						maybe_set_status (urb, 0);
+ 					}
+ 
+ 				} else if (setup.bRequestType == Ep_Request) {
+ 					// endpoint halt
+-					ep2 = find_endpoint (dum,
+-							setup.wIndex);
++					ep2 = find_endpoint (dum, w_index);
+ 					if (!ep2) {
+ 						value = -EOPNOTSUPP;
+ 						break;
+@@ -1343,7 +1349,7 @@ static void dummy_timer (unsigned long _dum)
+ 				break;
+ 			case USB_REQ_CLEAR_FEATURE:
+ 				if (setup.bRequestType == Dev_Request) {
+-					switch (setup.wValue) {
++					switch (w_value) {
+ 					case USB_DEVICE_REMOTE_WAKEUP:
+ 						dum->devstatus &= ~(1 <<
+ 							USB_DEVICE_REMOTE_WAKEUP);
+@@ -1356,8 +1362,7 @@ static void dummy_timer (unsigned long _dum)
+ 					}
+ 				} else if (setup.bRequestType == Ep_Request) {
+ 					// endpoint halt
+-					ep2 = find_endpoint (dum,
+-							setup.wIndex);
++					ep2 = find_endpoint (dum, w_index);
+ 					if (!ep2) {
+ 						value = -EOPNOTSUPP;
+ 						break;
+@@ -1383,7 +1388,7 @@ static void dummy_timer (unsigned long _dum)
+ 					if (urb->transfer_buffer_length > 0) {
+ 						if (setup.bRequestType ==
+ 								Ep_InRequest) {
+-	ep2 = find_endpoint (dum, setup.wIndex);
++	ep2 = find_endpoint (dum, w_index);
+ 	if (!ep2) {
+ 		value = -EOPNOTSUPP;
+ 		break;
+@@ -1535,7 +1540,8 @@ hub_descriptor (struct usb_hub_descriptor *desc)
+ 	memset (desc, 0, sizeof *desc);
+ 	desc->bDescriptorType = 0x29;
+ 	desc->bDescLength = 9;
+-	desc->wHubCharacteristics = __constant_cpu_to_le16 (0x0001);
++	desc->wHubCharacteristics = (__force __u16)
++			(__constant_cpu_to_le16 (0x0001));
+ 	desc->bNbrPorts = 1;
+ 	desc->bitmap [0] = 0xff;
+ 	desc->bitmap [1] = 0xff;
+@@ -1581,7 +1587,7 @@ static int dummy_hub_control (
+ 		hub_descriptor ((struct usb_hub_descriptor *) buf);
+ 		break;
+ 	case GetHubStatus:
+-		*(u32 *) buf = __constant_cpu_to_le32 (0);
++		*(__le32 *) buf = __constant_cpu_to_le32 (0);
+ 		break;
+ 	case GetPortStatus:
+ 		if (wIndex != 1)
+@@ -1621,8 +1627,8 @@ static int dummy_hub_control (
+ 			}
+ 		}
+ 		set_link_state (dum);
+-		((u16 *) buf)[0] = cpu_to_le16 (dum->port_status);
+-		((u16 *) buf)[1] = cpu_to_le16 (dum->port_status >> 16);
++		((__le16 *) buf)[0] = cpu_to_le16 (dum->port_status);
++		((__le16 *) buf)[1] = cpu_to_le16 (dum->port_status >> 16);
+ 		break;
+ 	case SetHubFeature:
+ 		retval = -EPIPE;

commit 685eb93f086eb15d9fb1e82c7400fd750f564640
+Author: Alan Stern 
+Date:   Tue May 3 16:27:26 2005 -0400
+
+    [PATCH] USB dummy_hcd: Use root-hub interrupts instead of polling
+    
+    This patch makes the dummy_hcd driver use emulated root-hub interrupts
+    instead of polling.  It's in the spirit of similar changes being made to
+    the other HCDs.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index 2d6d22951326..73d2f24050ab 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -684,6 +684,7 @@ static int dummy_wakeup (struct usb_gadget *_gadget)
+ 	/* hub notices our request, issues downstream resume, etc */
+ 	dum->resuming = 1;
+ 	dum->re_timeout = jiffies + msecs_to_jiffies(20);
++	mod_timer (&dummy_to_hcd (dum)->rh_timer, dum->re_timeout);
+ 	return 0;
+ }
+ 
+@@ -709,6 +710,8 @@ static int dummy_pullup (struct usb_gadget *_gadget, int value)
+ 	dum->pullup = (value != 0);
+ 	set_link_state (dum);
+ 	spin_unlock_irqrestore (&dum->lock, flags);
++
++	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
+ 	return 0;
+ }
+ 
+@@ -811,6 +814,8 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
+ 	dum->pullup = 1;
+ 	set_link_state (dum);
+ 	spin_unlock_irq (&dum->lock);
++
++	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
+ 	return 0;
+ }
+ EXPORT_SYMBOL (usb_gadget_register_driver);
+@@ -845,6 +850,7 @@ usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
+ 	set_link_state (dum);
+ 	spin_unlock_irqrestore (&dum->lock, flags);
+ 
++	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
+ 	return 0;
+ }
+ EXPORT_SYMBOL (usb_gadget_unregister_driver);
+@@ -1669,6 +1675,9 @@ static int dummy_hub_control (
+ 		retval = -EPIPE;
+ 	}
+ 	spin_unlock_irqrestore (&dum->lock, flags);
++
++	if ((dum->port_status & PORT_C_MASK) != 0)
++		usb_hcd_poll_rh_status (hcd);
+ 	return retval;
+ }
+ 
+@@ -1745,6 +1754,7 @@ static int dummy_start (struct usb_hcd *hcd)
+ 	/* only show a low-power port: just 8mA */
+ 	hcd->power_budget = 8;
+ 	hcd->state = HC_STATE_RUNNING;
++	hcd->uses_new_polling = 1;
+ 
+ #ifdef CONFIG_USB_OTG
+ 	hcd->self.otg_port = 1;

commit f1c39fad7d1bbea31744138cd3a532ff346cd4ab
+Author: Alan Stern 
+Date:   Tue May 3 16:24:04 2005 -0400
+
+    [PATCH] USB dummy_hcd: Centralize link state computations
+    
+    This patch adds to the dummy_hcd driver a new routine for keeping track of
+    all changes in the state of the emulated USB link.  The logic is now kept
+    in one spot instead of spread around, and it's easier to verify and
+    update the code.  The behavior of the port features has been corrected in
+    a few respects as well (for instance, if the POWER feature is clear then
+    none of the other features can be set).
+    
+    Also added is support for the (relatively new) _connect() and
+    _disconnect() calls of the Gadget API.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index dc0e3233b0e9..2d6d22951326 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -163,12 +163,16 @@ struct dummy {
+ 	struct dummy_request		fifo_req;
+ 	u8				fifo_buf [FIFO_SIZE];
+ 	u16				devstatus;
++	unsigned			pullup:1;
++	unsigned			active:1;
++	unsigned			old_active:1;
+ 
+ 	/*
+ 	 * MASTER/HOST side support
+ 	 */
+ 	struct timer_list		timer;
+ 	u32				port_status;
++	u32				old_status;
+ 	unsigned			resuming:1;
+ 	unsigned long			re_timeout;
+ 
+@@ -215,6 +219,98 @@ static struct dummy			*the_controller;
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++/* SLAVE/GADGET SIDE UTILITY ROUTINES */
++
++/* called with spinlock held */
++static void nuke (struct dummy *dum, struct dummy_ep *ep)
++{
++	while (!list_empty (&ep->queue)) {
++		struct dummy_request	*req;
++
++		req = list_entry (ep->queue.next, struct dummy_request, queue);
++		list_del_init (&req->queue);
++		req->req.status = -ESHUTDOWN;
++
++		spin_unlock (&dum->lock);
++		req->req.complete (&ep->ep, &req->req);
++		spin_lock (&dum->lock);
++	}
++}
++
++/* caller must hold lock */
++static void
++stop_activity (struct dummy *dum)
++{
++	struct dummy_ep	*ep;
++
++	/* prevent any more requests */
++	dum->address = 0;
++
++	/* The timer is left running so that outstanding URBs can fail */
++
++	/* nuke any pending requests first, so driver i/o is quiesced */
++	list_for_each_entry (ep, &dum->gadget.ep_list, ep.ep_list)
++		nuke (dum, ep);
++
++	/* driver now does any non-usb quiescing necessary */
++}
++
++/* caller must hold lock */
++static void
++set_link_state (struct dummy *dum)
++{
++	dum->active = 0;
++	if ((dum->port_status & USB_PORT_STAT_POWER) == 0)
++		dum->port_status = 0;
++	else if (!dum->pullup) {
++		dum->port_status &= ~(USB_PORT_STAT_CONNECTION |
++					USB_PORT_STAT_ENABLE |
++					USB_PORT_STAT_LOW_SPEED |
++					USB_PORT_STAT_HIGH_SPEED |
++					USB_PORT_STAT_SUSPEND);
++		if ((dum->old_status & USB_PORT_STAT_CONNECTION) != 0)
++			dum->port_status |= (USB_PORT_STAT_C_CONNECTION << 16);
++	} else {
++		dum->port_status |= USB_PORT_STAT_CONNECTION;
++		if ((dum->old_status & USB_PORT_STAT_CONNECTION) == 0)
++			dum->port_status |= (USB_PORT_STAT_C_CONNECTION << 16);
++		if ((dum->port_status & USB_PORT_STAT_ENABLE) == 0)
++			dum->port_status &= ~USB_PORT_STAT_SUSPEND;
++		else if ((dum->port_status & USB_PORT_STAT_SUSPEND) == 0)
++			dum->active = 1;
++	}
++
++	if ((dum->port_status & USB_PORT_STAT_ENABLE) == 0 || dum->active)
++		dum->resuming = 0;
++
++	if ((dum->port_status & USB_PORT_STAT_CONNECTION) == 0 ||
++			(dum->port_status & USB_PORT_STAT_RESET) != 0) {
++		if ((dum->old_status & USB_PORT_STAT_CONNECTION) != 0 &&
++				(dum->old_status & USB_PORT_STAT_RESET) == 0 &&
++				dum->driver) {
++			stop_activity (dum);
++			spin_unlock (&dum->lock);
++			dum->driver->disconnect (&dum->gadget);
++			spin_lock (&dum->lock);
++		}
++	} else if (dum->active != dum->old_active) {
++		if (dum->old_active && dum->driver->suspend) {
++			spin_unlock (&dum->lock);
++			dum->driver->suspend (&dum->gadget);
++			spin_lock (&dum->lock);
++		} else if (!dum->old_active && dum->driver->resume) {
++			spin_unlock (&dum->lock);
++			dum->driver->resume (&dum->gadget);
++			spin_lock (&dum->lock);
++		}
++	}
++
++	dum->old_status = dum->port_status;
++	dum->old_active = dum->active;
++}
++
++/*-------------------------------------------------------------------------*/
++
+ /* SLAVE/GADGET SIDE DRIVER
+  *
+  * This only tracks gadget state.  All the work is done when the host
+@@ -339,22 +435,6 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
+ 	return retval;
+ }
+ 
+-/* called with spinlock held */
+-static void nuke (struct dummy *dum, struct dummy_ep *ep)
+-{
+-	while (!list_empty (&ep->queue)) {
+-		struct dummy_request	*req;
+-
+-		req = list_entry (ep->queue.next, struct dummy_request, queue);
+-		list_del_init (&req->queue);
+-		req->req.status = -ESHUTDOWN;
+-
+-		spin_unlock (&dum->lock);
+-		req->req.complete (&ep->ep, &req->req);
+-		spin_lock (&dum->lock);
+-	}
+-}
+-
+ static int dummy_disable (struct usb_ep *_ep)
+ {
+ 	struct dummy_ep		*ep;
+@@ -603,7 +683,7 @@ static int dummy_wakeup (struct usb_gadget *_gadget)
+ 
+ 	/* hub notices our request, issues downstream resume, etc */
+ 	dum->resuming = 1;
+-	dum->port_status |= (USB_PORT_STAT_C_SUSPEND << 16);
++	dum->re_timeout = jiffies + msecs_to_jiffies(20);
+ 	return 0;
+ }
+ 
+@@ -619,10 +699,24 @@ static int dummy_set_selfpowered (struct usb_gadget *_gadget, int value)
+ 	return 0;
+ }
+ 
++static int dummy_pullup (struct usb_gadget *_gadget, int value)
++{
++	struct dummy	*dum;
++	unsigned long	flags;
++
++	dum = gadget_to_dummy (_gadget);
++	spin_lock_irqsave (&dum->lock, flags);
++	dum->pullup = (value != 0);
++	set_link_state (dum);
++	spin_unlock_irqrestore (&dum->lock, flags);
++	return 0;
++}
++
+ static const struct usb_gadget_ops dummy_ops = {
+ 	.get_frame	= dummy_g_get_frame,
+ 	.wakeup		= dummy_wakeup,
+ 	.set_selfpowered = dummy_set_selfpowered,
++	.pullup		= dummy_pullup,
+ };
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -675,7 +769,6 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
+ 	 */
+ 
+ 	dum->devstatus = 0;
+-	dum->resuming = 0;
+ 
+ 	INIT_LIST_HEAD (&dum->gadget.ep_list);
+ 	for (i = 0; i < DUMMY_ENDPOINTS; i++) {
+@@ -714,35 +807,14 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
+ 	device_bind_driver (&dum->gadget.dev);
+ 
+ 	/* khubd will enumerate this in a while */
+-	dum->port_status |= USB_PORT_STAT_CONNECTION
+-		| (USB_PORT_STAT_C_CONNECTION << 16);
++	spin_lock_irq (&dum->lock);
++	dum->pullup = 1;
++	set_link_state (dum);
++	spin_unlock_irq (&dum->lock);
+ 	return 0;
+ }
+ EXPORT_SYMBOL (usb_gadget_register_driver);
+ 
+-/* caller must hold lock */
+-static void
+-stop_activity (struct dummy *dum, struct usb_gadget_driver *driver)
+-{
+-	struct dummy_ep	*ep;
+-
+-	/* prevent any more requests */
+-	dum->address = 0;
+-
+-	/* The timer is left running so that outstanding URBs can fail */
+-
+-	/* nuke any pending requests first, so driver i/o is quiesced */
+-	list_for_each_entry (ep, &dum->gadget.ep_list, ep.ep_list)
+-		nuke (dum, ep);
+-
+-	/* driver now does any non-usb quiescing necessary */
+-	if (driver) {
+-		spin_unlock (&dum->lock);
+-		driver->disconnect (&dum->gadget);
+-		spin_lock (&dum->lock);
+-	}
+-}
+-
+ int
+ usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
+ {
+@@ -758,10 +830,8 @@ usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
+ 			driver->driver.name);
+ 
+ 	spin_lock_irqsave (&dum->lock, flags);
+-	stop_activity (dum, driver);
+-	dum->port_status &= ~(USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE |
+-			USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED);
+-	dum->port_status |= (USB_PORT_STAT_C_CONNECTION << 16);
++	dum->pullup = 0;
++	set_link_state (dum);
+ 	spin_unlock_irqrestore (&dum->lock, flags);
+ 
+ 	driver->unbind (&dum->gadget);
+@@ -770,6 +840,11 @@ usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
+ 	device_release_driver (&dum->gadget.dev);
+ 	driver_unregister (&driver->driver);
+ 
++	spin_lock_irqsave (&dum->lock, flags);
++	dum->pullup = 0;
++	set_link_state (dum);
++	spin_unlock_irqrestore (&dum->lock, flags);
++
+ 	return 0;
+ }
+ EXPORT_SYMBOL (usb_gadget_unregister_driver);
+@@ -1432,6 +1507,13 @@ static int dummy_hub_status (struct usb_hcd *hcd, char *buf)
+ 	dum = hcd_to_dummy (hcd);
+ 
+ 	spin_lock_irqsave (&dum->lock, flags);
++
++	if (dum->resuming && time_after_eq (jiffies, dum->re_timeout)) {
++		dum->port_status |= (USB_PORT_STAT_C_SUSPEND << 16);
++		dum->port_status &= ~USB_PORT_STAT_SUSPEND;
++		set_link_state (dum);
++	}
++
+ 	if (!(dum->port_status & PORT_C_MASK))
+ 		retval = 0;
+ 	else {
+@@ -1480,16 +1562,16 @@ static int dummy_hub_control (
+ 				/* 20msec resume signaling */
+ 				dum->resuming = 1;
+ 				dum->re_timeout = jiffies +
+-							msecs_to_jiffies(20);
++						msecs_to_jiffies(20);
+ 			}
+ 			break;
+ 		case USB_PORT_FEAT_POWER:
+-			dum->port_status = 0;
+-			dum->resuming = 0;
+-			stop_activity(dum, dum->driver);
+-			break;
++			if (dum->port_status & USB_PORT_STAT_POWER)
++				dev_dbg (dummy_dev(dum), "power-off\n");
++			/* FALLS THROUGH */
+ 		default:
+ 			dum->port_status &= ~(1 << wValue);
++			set_link_state (dum);
+ 		}
+ 		break;
+ 	case GetHubDescriptor:
+@@ -1505,23 +1587,16 @@ static int dummy_hub_control (
+ 		/* whoever resets or resumes must GetPortStatus to
+ 		 * complete it!!
+ 		 */
+-		if (dum->resuming && time_after (jiffies, dum->re_timeout)) {
++		if (dum->resuming &&
++				time_after_eq (jiffies, dum->re_timeout)) {
+ 			dum->port_status |= (USB_PORT_STAT_C_SUSPEND << 16);
+ 			dum->port_status &= ~USB_PORT_STAT_SUSPEND;
+-			dum->resuming = 0;
+-			dum->re_timeout = 0;
+-			if (dum->driver && dum->driver->resume) {
+-				spin_unlock (&dum->lock);
+-				dum->driver->resume (&dum->gadget);
+-				spin_lock (&dum->lock);
+-			}
+ 		}
+-		if ((dum->port_status & USB_PORT_STAT_RESET) != 0
+-				&& time_after (jiffies, dum->re_timeout)) {
++		if ((dum->port_status & USB_PORT_STAT_RESET) != 0 &&
++				time_after_eq (jiffies, dum->re_timeout)) {
+ 			dum->port_status |= (USB_PORT_STAT_C_RESET << 16);
+ 			dum->port_status &= ~USB_PORT_STAT_RESET;
+-			dum->re_timeout = 0;
+-			if (dum->driver) {
++			if (dum->pullup) {
+ 				dum->port_status |= USB_PORT_STAT_ENABLE;
+ 				/* give it the best speed we agree on */
+ 				dum->gadget.speed = dum->driver->speed;
+@@ -1542,6 +1617,7 @@ static int dummy_hub_control (
+ 				}
+ 			}
+ 		}
++		set_link_state (dum);
+ 		((u16 *) buf)[0] = cpu_to_le16 (dum->port_status);
+ 		((u16 *) buf)[1] = cpu_to_le16 (dum->port_status >> 16);
+ 		break;
+@@ -1551,42 +1627,36 @@ static int dummy_hub_control (
+ 	case SetPortFeature:
+ 		switch (wValue) {
+ 		case USB_PORT_FEAT_SUSPEND:
+-			if ((dum->port_status & USB_PORT_STAT_SUSPEND)
+-					== 0) {
++			if (dum->active) {
+ 				dum->port_status |= USB_PORT_STAT_SUSPEND;
+-				if (dum->driver && dum->driver->suspend) {
+-					spin_unlock (&dum->lock);
+-					dum->driver->suspend (&dum->gadget);
+-					spin_lock (&dum->lock);
+-					/* HNP would happen here; for now we
+-					 * assume b_bus_req is always true.
+-					 */
+-					if (((1 << USB_DEVICE_B_HNP_ENABLE)
+-							& dum->devstatus) != 0)
+-						dev_dbg (dummy_dev(dum),
++
++				/* HNP would happen here; for now we
++				 * assume b_bus_req is always true.
++				 */
++				set_link_state (dum);
++				if (((1 << USB_DEVICE_B_HNP_ENABLE)
++						& dum->devstatus) != 0)
++					dev_dbg (dummy_dev(dum),
+ 							"no HNP yet!\n");
+-				}
+ 			}
+ 			break;
++		case USB_PORT_FEAT_POWER:
++			dum->port_status |= USB_PORT_STAT_POWER;
++			set_link_state (dum);
++			break;
+ 		case USB_PORT_FEAT_RESET:
+-			/* if it's already running, disconnect first */
+-			if (dum->port_status & USB_PORT_STAT_ENABLE) {
+-				dum->port_status &= ~(USB_PORT_STAT_ENABLE
+-						| USB_PORT_STAT_LOW_SPEED
+-						| USB_PORT_STAT_HIGH_SPEED);
+-				if (dum->driver) {
+-					dev_dbg (udc_dev(dum),
+-							"disconnect\n");
+-					stop_activity (dum, dum->driver);
+-				}
+-
+-				/* FIXME test that code path! */
+-			}
++			/* if it's already enabled, disable */
++			dum->port_status &= ~(USB_PORT_STAT_ENABLE
++					| USB_PORT_STAT_LOW_SPEED
++					| USB_PORT_STAT_HIGH_SPEED);
+ 			/* 50msec reset signaling */
+ 			dum->re_timeout = jiffies + msecs_to_jiffies(50);
+-			/* FALLTHROUGH */
++			/* FALLS THROUGH */
+ 		default:
+-			dum->port_status |= (1 << wValue);
++			if ((dum->port_status & USB_PORT_STAT_POWER) != 0) {
++				dum->port_status |= (1 << wValue);
++				set_link_state (dum);
++			}
+ 		}
+ 		break;
+ 

commit d9b762510c186584a6be0d3ece03e8a4b2ac13a8
+Author: Alan Stern 
+Date:   Tue May 3 16:15:43 2005 -0400
+
+    [PATCH] USB dummy_hcd: Use separate pdevs for HC and UDC
+    
+    This patch makes the dummy_hcd driver create separate platform devices for
+    the emulated host controller and emulated device controller.  This gives a
+    more accurate simulation and will permit testing of situations where only
+    one of the two devices is suspended.
+    
+    This also changes the name of the host controller platform device to match
+    the name of the driver.  That way the normal platform bus probe mechanism
+    will handle binding the driver to the device.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index ffedf4d1b747..dc0e3233b0e9 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -141,6 +141,8 @@ static const char *const ep_name [] = {
+ };
+ #define DUMMY_ENDPOINTS	(sizeof(ep_name)/sizeof(char *))
+ 
++/*-------------------------------------------------------------------------*/
++
+ #define FIFO_SIZE		64
+ 
+ struct urbp {
+@@ -189,6 +191,11 @@ static inline struct device *dummy_dev (struct dummy *dum)
+ 	return dummy_to_hcd(dum)->self.controller;
+ }
+ 
++static inline struct device *udc_dev (struct dummy *dum)
++{
++	return dum->gadget.dev.parent;
++}
++
+ static inline struct dummy *ep_to_dummy (struct dummy_ep *ep)
+ {
+ 	return container_of (ep->gadget, struct dummy, gadget);
+@@ -208,19 +215,6 @@ static struct dummy			*the_controller;
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-/*
+- * This "hardware" may look a bit odd in diagnostics since it's got both
+- * host and device sides; and it binds different drivers to each side.
+- */
+-static struct platform_device		the_pdev;
+-
+-static struct device_driver dummy_driver = {
+-	.name		= (char *) driver_name,
+-	.bus		= &platform_bus_type,
+-};
+-
+-/*-------------------------------------------------------------------------*/
+-
+ /* SLAVE/GADGET SIDE DRIVER
+  *
+  * This only tracks gadget state.  All the work is done when the host
+@@ -324,7 +318,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
+ 	_ep->maxpacket = max;
+ 	ep->desc = desc;
+ 
+-	dev_dbg (dummy_dev(dum), "enabled %s (ep%d%s-%s) maxpacket %d\n",
++	dev_dbg (udc_dev(dum), "enabled %s (ep%d%s-%s) maxpacket %d\n",
+ 		_ep->name,
+ 		desc->bEndpointAddress & 0x0f,
+ 		(desc->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
+@@ -379,7 +373,7 @@ static int dummy_disable (struct usb_ep *_ep)
+ 	nuke (dum, ep);
+ 	spin_unlock_irqrestore (&dum->lock, flags);
+ 
+-	dev_dbg (dummy_dev(dum), "disabled %s\n", _ep->name);
++	dev_dbg (udc_dev(dum), "disabled %s\n", _ep->name);
+ 	return retval;
+ }
+ 
+@@ -474,7 +468,7 @@ dummy_queue (struct usb_ep *_ep, struct usb_request *_req, int mem_flags)
+ 		return -ESHUTDOWN;
+ 
+ #if 0
+-	dev_dbg (dummy_dev(dum), "ep %p queue req %p to %s, len %d buf %p\n",
++	dev_dbg (udc_dev(dum), "ep %p queue req %p to %s, len %d buf %p\n",
+ 			ep, _req, _ep->name, _req->length, _req->buf);
+ #endif
+ 
+@@ -537,7 +531,7 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req)
+ 	spin_unlock_irqrestore (&dum->lock, flags);
+ 
+ 	if (retval == 0) {
+-		dev_dbg (dummy_dev(dum),
++		dev_dbg (udc_dev(dum),
+ 				"dequeued req %p from %s, len %d buf %p\n",
+ 				req, _ep->name, _req->length, _req->buf);
+ 		_req->complete (_ep, _req);
+@@ -661,38 +655,6 @@ DEVICE_ATTR (function, S_IRUGO, show_function, NULL);
+  * for each driver that registers:  just add to a big root hub.
+  */
+ 
+-/* This doesn't need to do anything because the udc device structure is
+- * stored inside the hcd and will be deallocated along with it. */
+-static void
+-dummy_udc_release (struct device *dev) {}
+-
+-/* This doesn't need to do anything because the pdev structure is
+- * statically allocated. */
+-static void
+-dummy_pdev_release (struct device *dev) {}
+-
+-static int
+-dummy_register_udc (struct dummy *dum)
+-{
+-	int		rc;
+-
+-	strcpy (dum->gadget.dev.bus_id, "udc");
+-	dum->gadget.dev.parent = dummy_dev(dum);
+-	dum->gadget.dev.release = dummy_udc_release;
+-
+-	rc = device_register (&dum->gadget.dev);
+-	if (rc == 0)
+-		device_create_file (&dum->gadget.dev, &dev_attr_function);
+-	return rc;
+-}
+-
+-static void
+-dummy_unregister_udc (struct dummy *dum)
+-{
+-	device_remove_file (&dum->gadget.dev, &dev_attr_function);
+-	device_unregister (&dum->gadget.dev);
+-}
+-
+ int
+ usb_gadget_register_driver (struct usb_gadget_driver *driver)
+ {
+@@ -711,12 +673,6 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
+ 	 * SLAVE side init ... the layer above hardware, which
+ 	 * can't enumerate without help from the driver we're binding.
+ 	 */
+-	dum->gadget.name = gadget_name;
+-	dum->gadget.ops = &dummy_ops;
+-	dum->gadget.is_dualspeed = 1;
+-
+-	/* maybe claim OTG support, though we won't complete HNP */
+-	dum->gadget.is_otg = (dummy_to_hcd(dum)->self.otg_port != 0);
+ 
+ 	dum->devstatus = 0;
+ 	dum->resuming = 0;
+@@ -745,7 +701,7 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
+ 
+ 	dum->driver = driver;
+ 	dum->gadget.dev.driver = &driver->driver;
+-	dev_dbg (dummy_dev(dum), "binding gadget driver '%s'\n",
++	dev_dbg (udc_dev(dum), "binding gadget driver '%s'\n",
+ 			driver->driver.name);
+ 	if ((retval = driver->bind (&dum->gadget)) != 0) {
+ 		dum->driver = NULL;
+@@ -798,7 +754,7 @@ usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
+ 	if (!driver || driver != dum->driver)
+ 		return -EINVAL;
+ 
+-	dev_dbg (dummy_dev(dum), "unregister gadget driver '%s'\n",
++	dev_dbg (udc_dev(dum), "unregister gadget driver '%s'\n",
+ 			driver->driver.name);
+ 
+ 	spin_lock_irqsave (&dum->lock, flags);
+@@ -826,6 +782,64 @@ int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode)
+ }
+ EXPORT_SYMBOL (net2280_set_fifo_mode);
+ 
++
++/* The gadget structure is stored inside the hcd structure and will be
++ * released along with it. */
++static void
++dummy_gadget_release (struct device *dev)
++{
++#if 0		/* usb_bus_put isn't EXPORTed! */
++	struct dummy	*dum = gadget_dev_to_dummy (dev);
++
++	usb_bus_put (&dummy_to_hcd (dum)->self);
++#endif
++}
++
++static int dummy_udc_probe (struct device *dev)
++{
++	struct dummy	*dum = the_controller;
++	int		rc;
++
++	dum->gadget.name = gadget_name;
++	dum->gadget.ops = &dummy_ops;
++	dum->gadget.is_dualspeed = 1;
++
++	/* maybe claim OTG support, though we won't complete HNP */
++	dum->gadget.is_otg = (dummy_to_hcd(dum)->self.otg_port != 0);
++
++	strcpy (dum->gadget.dev.bus_id, "gadget");
++	dum->gadget.dev.parent = dev;
++	dum->gadget.dev.release = dummy_gadget_release;
++	rc = device_register (&dum->gadget.dev);
++	if (rc < 0)
++		return rc;
++
++#if 0		/* usb_bus_get isn't EXPORTed! */
++	usb_bus_get (&dummy_to_hcd (dum)->self);
++#endif
++
++	dev_set_drvdata (dev, dum);
++	device_create_file (&dum->gadget.dev, &dev_attr_function);
++	return rc;
++}
++
++static int dummy_udc_remove (struct device *dev)
++{
++	struct dummy	*dum = dev_get_drvdata (dev);
++
++	dev_set_drvdata (dev, NULL);
++	device_remove_file (&dum->gadget.dev, &dev_attr_function);
++	device_unregister (&dum->gadget.dev);
++	return 0;
++}
++
++static struct device_driver dummy_udc_driver = {
++	.name		= (char *) gadget_name,
++	.bus		= &platform_bus_type,
++	.probe		= dummy_udc_probe,
++	.remove		= dummy_udc_remove,
++};
++
+ /*-------------------------------------------------------------------------*/
+ 
+ /* MASTER/HOST SIDE DRIVER
+@@ -1184,7 +1198,7 @@ static void dummy_timer (unsigned long _dum)
+ 			list_for_each_entry (req, &ep->queue, queue) {
+ 				list_del_init (&req->queue);
+ 				req->req.status = -EOVERFLOW;
+-				dev_dbg (dummy_dev(dum), "stale req = %p\n",
++				dev_dbg (udc_dev(dum), "stale req = %p\n",
+ 						req);
+ 
+ 				spin_unlock (&dum->lock);
+@@ -1207,7 +1221,7 @@ static void dummy_timer (unsigned long _dum)
+ 					break;
+ 				dum->address = setup.wValue;
+ 				maybe_set_status (urb, 0);
+-				dev_dbg (dummy_dev(dum), "set_address = %d\n",
++				dev_dbg (udc_dev(dum), "set_address = %d\n",
+ 						setup.wValue);
+ 				value = 0;
+ 				break;
+@@ -1333,7 +1347,7 @@ static void dummy_timer (unsigned long _dum)
+ 
+ 			if (value < 0) {
+ 				if (value != -EOPNOTSUPP)
+-					dev_dbg (dummy_dev(dum),
++					dev_dbg (udc_dev(dum),
+ 						"setup --> %d\n",
+ 						value);
+ 				maybe_set_status (urb, -EPIPE);
+@@ -1561,7 +1575,7 @@ static int dummy_hub_control (
+ 						| USB_PORT_STAT_LOW_SPEED
+ 						| USB_PORT_STAT_HIGH_SPEED);
+ 				if (dum->driver) {
+-					dev_dbg (dummy_dev(dum),
++					dev_dbg (udc_dev(dum),
+ 							"disconnect\n");
+ 					stop_activity (dum, dum->driver);
+ 				}
+@@ -1643,7 +1657,6 @@ static DEVICE_ATTR (urbs, S_IRUGO, show_urbs, NULL);
+ static int dummy_start (struct usb_hcd *hcd)
+ {
+ 	struct dummy		*dum;
+-	int			retval;
+ 
+ 	dum = hcd_to_dummy (hcd);
+ 
+@@ -1659,9 +1672,6 @@ static int dummy_start (struct usb_hcd *hcd)
+ 
+ 	INIT_LIST_HEAD (&dum->urbp_list);
+ 
+-	if ((retval = dummy_register_udc (dum)) != 0)
+-		return retval;
+-
+ 	/* only show a low-power port: just 8mA */
+ 	hcd->power_budget = 8;
+ 	hcd->state = HC_STATE_RUNNING;
+@@ -1682,10 +1692,7 @@ static void dummy_stop (struct usb_hcd *hcd)
+ 	dum = hcd_to_dummy (hcd);
+ 
+ 	device_remove_file (dummy_dev(dum), &dev_attr_urbs);
+-
+ 	usb_gadget_unregister_driver (dum->driver);
+-	dummy_unregister_udc (dum);
+-
+ 	dev_info (dummy_dev(dum), "stopped\n");
+ }
+ 
+@@ -1715,7 +1722,7 @@ static const struct hc_driver dummy_hcd = {
+ 	.hub_control = 		dummy_hub_control,
+ };
+ 
+-static int dummy_probe (struct device *dev)
++static int dummy_hcd_probe (struct device *dev)
+ {
+ 	struct usb_hcd		*hcd;
+ 	int			retval;
+@@ -1735,7 +1742,7 @@ static int dummy_probe (struct device *dev)
+ 	return retval;
+ }
+ 
+-static void dummy_remove (struct device *dev)
++static int dummy_hcd_remove (struct device *dev)
+ {
+ 	struct usb_hcd		*hcd;
+ 
+@@ -1743,35 +1750,41 @@ static void dummy_remove (struct device *dev)
+ 	usb_remove_hcd (hcd);
+ 	usb_put_hcd (hcd);
+ 	the_controller = NULL;
++	return 0;
+ }
+ 
+-/*-------------------------------------------------------------------------*/
+-
+-static int dummy_pdev_detect (void)
+-{
+-	int			retval;
+-
+-	retval = driver_register (&dummy_driver);
+-	if (retval < 0)
+-		return retval;
++static struct device_driver dummy_hcd_driver = {
++	.name		= (char *) driver_name,
++	.bus		= &platform_bus_type,
++	.probe		= dummy_hcd_probe,
++	.remove		= dummy_hcd_remove,
++};
+ 
+-	the_pdev.name = "hc";
+-	the_pdev.dev.driver = &dummy_driver;
+-	the_pdev.dev.release = dummy_pdev_release;
++/*-------------------------------------------------------------------------*/
+ 
+-	retval = platform_device_register (&the_pdev);
+-	if (retval < 0)
+-		driver_unregister (&dummy_driver);
+-	return retval;
+-}
++/* These don't need to do anything because the pdev structures are
++ * statically allocated. */
++static void
++dummy_udc_release (struct device *dev) {}
+ 
+-static void dummy_pdev_remove (void)
+-{
+-	platform_device_unregister (&the_pdev);
+-	driver_unregister (&dummy_driver);
+-}
++static void
++dummy_hcd_release (struct device *dev) {}
++
++static struct platform_device		the_udc_pdev = {
++	.name		= (char *) gadget_name,
++	.id		= -1,
++	.dev		= {
++		.release	= dummy_udc_release,
++	},
++};
+ 
+-/*-------------------------------------------------------------------------*/
++static struct platform_device		the_hcd_pdev = {
++	.name		= (char *) driver_name,
++	.id		= -1,
++	.dev		= {
++		.release	= dummy_hcd_release,
++	},
++};
+ 
+ static int __init init (void)
+ {
+@@ -1779,17 +1792,39 @@ static int __init init (void)
+ 
+ 	if (usb_disabled ())
+ 		return -ENODEV;
+-	if ((retval = dummy_pdev_detect ()) != 0)
++
++	retval = driver_register (&dummy_hcd_driver);
++	if (retval < 0)
+ 		return retval;
+-	if ((retval = dummy_probe (&the_pdev.dev)) != 0)
+-		dummy_pdev_remove ();
++
++	retval = driver_register (&dummy_udc_driver);
++	if (retval < 0)
++		goto err_register_udc_driver;
++
++	retval = platform_device_register (&the_hcd_pdev);
++	if (retval < 0)
++		goto err_register_hcd;
++
++	retval = platform_device_register (&the_udc_pdev);
++	if (retval < 0)
++		goto err_register_udc;
++	return retval;
++
++err_register_udc:
++	platform_device_unregister (&the_hcd_pdev);
++err_register_hcd:
++	driver_unregister (&dummy_udc_driver);
++err_register_udc_driver:
++	driver_unregister (&dummy_hcd_driver);
+ 	return retval;
+ }
+ module_init (init);
+ 
+ static void __exit cleanup (void)
+ {
+-	dummy_remove (&the_pdev.dev);
+-	dummy_pdev_remove ();
++	platform_device_unregister (&the_udc_pdev);
++	platform_device_unregister (&the_hcd_pdev);
++	driver_unregister (&dummy_udc_driver);
++	driver_unregister (&dummy_hcd_driver);
+ }
+ module_exit (cleanup);

commit c2db8b5e5692a6f35913a829607ee6efde3c7cbd
+Author: Alan Stern 
+Date:   Fri Apr 29 16:30:48 2005 -0400
+
+    [PATCH] USB: dummy_hcd: USB_PORT_FEAT changed to USB_PORT_STAT
+    
+    This patch makes some cosmetic changes to dummy_hcd:
+    
+            Minor alterations of comments and whitespace.
+    
+            Replace USB_PORT_FEAT_xxx with USB_PORT_STAT_xxx.  This is
+            appropriate as the values are stored in a status variable
+            and they aren't feature indices.  Also it allows the
+            elimination of a bunch of awkward bit shift operations.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index e9b95df5b23d..ffedf4d1b747 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -601,7 +601,7 @@ static int dummy_wakeup (struct usb_gadget *_gadget)
+ 	struct dummy	*dum;
+ 
+ 	dum = gadget_to_dummy (_gadget);
+-	if (!(dum->port_status & (1 << USB_PORT_FEAT_SUSPEND))
++	if (!(dum->port_status & USB_PORT_STAT_SUSPEND)
+ 			|| !(dum->devstatus &
+ 				( (1 << USB_DEVICE_B_HNP_ENABLE)
+ 				| (1 << USB_DEVICE_REMOTE_WAKEUP))))
+@@ -609,7 +609,7 @@ static int dummy_wakeup (struct usb_gadget *_gadget)
+ 
+ 	/* hub notices our request, issues downstream resume, etc */
+ 	dum->resuming = 1;
+-	dum->port_status |= (1 << USB_PORT_FEAT_C_SUSPEND);
++	dum->port_status |= (USB_PORT_STAT_C_SUSPEND << 16);
+ 	return 0;
+ }
+ 
+@@ -661,15 +661,15 @@ DEVICE_ATTR (function, S_IRUGO, show_function, NULL);
+  * for each driver that registers:  just add to a big root hub.
+  */
+ 
++/* This doesn't need to do anything because the udc device structure is
++ * stored inside the hcd and will be deallocated along with it. */
+ static void
+-dummy_udc_release (struct device *dev)
+-{
+-}
++dummy_udc_release (struct device *dev) {}
+ 
++/* This doesn't need to do anything because the pdev structure is
++ * statically allocated. */
+ static void
+-dummy_pdev_release (struct device *dev)
+-{
+-}
++dummy_pdev_release (struct device *dev) {}
+ 
+ static int
+ dummy_register_udc (struct dummy *dum)
+@@ -753,15 +753,13 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
+ 		return retval;
+ 	}
+ 
+-	// FIXME: Check these calls for errors and re-order
+ 	driver->driver.bus = dum->gadget.dev.parent->bus;
+ 	driver_register (&driver->driver);
+-
+ 	device_bind_driver (&dum->gadget.dev);
+ 
+ 	/* khubd will enumerate this in a while */
+ 	dum->port_status |= USB_PORT_STAT_CONNECTION
+-		| (1 << USB_PORT_FEAT_C_CONNECTION);
++		| (USB_PORT_STAT_C_CONNECTION << 16);
+ 	return 0;
+ }
+ EXPORT_SYMBOL (usb_gadget_register_driver);
+@@ -807,14 +805,13 @@ usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
+ 	stop_activity (dum, driver);
+ 	dum->port_status &= ~(USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE |
+ 			USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED);
+-	dum->port_status |= (1 << USB_PORT_FEAT_C_CONNECTION);
++	dum->port_status |= (USB_PORT_STAT_C_CONNECTION << 16);
+ 	spin_unlock_irqrestore (&dum->lock, flags);
+ 
+ 	driver->unbind (&dum->gadget);
+ 	dum->driver = NULL;
+ 
+ 	device_release_driver (&dum->gadget.dev);
+-
+ 	driver_unregister (&driver->driver);
+ 
+ 	return 0;
+@@ -1406,11 +1403,11 @@ static void dummy_timer (unsigned long _dum)
+ /*-------------------------------------------------------------------------*/
+ 
+ #define PORT_C_MASK \
+-	 ((1 << USB_PORT_FEAT_C_CONNECTION) \
+-	| (1 << USB_PORT_FEAT_C_ENABLE) \
+-	| (1 << USB_PORT_FEAT_C_SUSPEND) \
+-	| (1 << USB_PORT_FEAT_C_OVER_CURRENT) \
+-	| (1 << USB_PORT_FEAT_C_RESET))
++	((USB_PORT_STAT_C_CONNECTION \
++	| USB_PORT_STAT_C_ENABLE \
++	| USB_PORT_STAT_C_SUSPEND \
++	| USB_PORT_STAT_C_OVERCURRENT \
++	| USB_PORT_STAT_C_RESET) << 16)
+ 
+ static int dummy_hub_status (struct usb_hcd *hcd, char *buf)
+ {
+@@ -1465,7 +1462,7 @@ static int dummy_hub_control (
+ 	case ClearPortFeature:
+ 		switch (wValue) {
+ 		case USB_PORT_FEAT_SUSPEND:
+-			if (dum->port_status & (1 << USB_PORT_FEAT_SUSPEND)) {
++			if (dum->port_status & USB_PORT_STAT_SUSPEND) {
+ 				/* 20msec resume signaling */
+ 				dum->resuming = 1;
+ 				dum->re_timeout = jiffies +
+@@ -1495,8 +1492,8 @@ static int dummy_hub_control (
+ 		 * complete it!!
+ 		 */
+ 		if (dum->resuming && time_after (jiffies, dum->re_timeout)) {
+-			dum->port_status |= (1 << USB_PORT_FEAT_C_SUSPEND);
+-			dum->port_status &= ~(1 << USB_PORT_FEAT_SUSPEND);
++			dum->port_status |= (USB_PORT_STAT_C_SUSPEND << 16);
++			dum->port_status &= ~USB_PORT_STAT_SUSPEND;
+ 			dum->resuming = 0;
+ 			dum->re_timeout = 0;
+ 			if (dum->driver && dum->driver->resume) {
+@@ -1505,10 +1502,10 @@ static int dummy_hub_control (
+ 				spin_lock (&dum->lock);
+ 			}
+ 		}
+-		if ((dum->port_status & (1 << USB_PORT_FEAT_RESET)) != 0
++		if ((dum->port_status & USB_PORT_STAT_RESET) != 0
+ 				&& time_after (jiffies, dum->re_timeout)) {
+-			dum->port_status |= (1 << USB_PORT_FEAT_C_RESET);
+-			dum->port_status &= ~(1 << USB_PORT_FEAT_RESET);
++			dum->port_status |= (USB_PORT_STAT_C_RESET << 16);
++			dum->port_status &= ~USB_PORT_STAT_RESET;
+ 			dum->re_timeout = 0;
+ 			if (dum->driver) {
+ 				dum->port_status |= USB_PORT_STAT_ENABLE;
+@@ -1540,10 +1537,9 @@ static int dummy_hub_control (
+ 	case SetPortFeature:
+ 		switch (wValue) {
+ 		case USB_PORT_FEAT_SUSPEND:
+-			if ((dum->port_status & (1 << USB_PORT_FEAT_SUSPEND))
++			if ((dum->port_status & USB_PORT_STAT_SUSPEND)
+ 					== 0) {
+-				dum->port_status |=
+-						(1 << USB_PORT_FEAT_SUSPEND);
++				dum->port_status |= USB_PORT_STAT_SUSPEND;
+ 				if (dum->driver && dum->driver->suspend) {
+ 					spin_unlock (&dum->lock);
+ 					dum->driver->suspend (&dum->gadget);

commit 5742b0c95026c817d9c266174ca39a909e8d38ca
+Author: Alan Stern 
+Date:   Mon May 2 11:25:17 2005 -0400
+
+    [PATCH] USB dummy_hcd: Partial OTG emulation
+    
+    Partial OTG support for dummy_hcd, mostly as a framework for further work.
+    It emulates the new OTG flags in the host and peripheral frameworks, if
+    that option is configured.  But it's incomplete:
+    
+      - Resetting the peripheral needs to clear the OTG state bits;
+        a second enumeration won't work correctly.
+    
+      - This stops modeling HNP right when roles should switch the first time.
+        It should probably disconnect, then set the usb_bus.is_b_host and
+        usb_gadget.is_a_peripheral flags; then it'd enumerate almost normally,
+        except for the role reversal.  Roles could then switch a second time,
+        back to "normal" (with those flags cleared).
+    
+      - SRP should be modeled as "resume from port-unpowered", which is
+        a state that usbcore doesn't yet use.
+    
+    HNP can be triggered by enabling the OTG whitelist and configuring a
+    gadget driver that's not in that list; or by configuring Gadget Zero
+    to identify itself as the HNP test device.
+    
+    Sent-by: David Brownell 
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index 1918d10f7569..e9b95df5b23d 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -601,8 +601,10 @@ static int dummy_wakeup (struct usb_gadget *_gadget)
+ 	struct dummy	*dum;
+ 
+ 	dum = gadget_to_dummy (_gadget);
+-	if ((dum->devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) == 0
+-			|| !(dum->port_status & (1 << USB_PORT_FEAT_SUSPEND)))
++	if (!(dum->port_status & (1 << USB_PORT_FEAT_SUSPEND))
++			|| !(dum->devstatus &
++				( (1 << USB_DEVICE_B_HNP_ENABLE)
++				| (1 << USB_DEVICE_REMOTE_WAKEUP))))
+ 		return -EINVAL;
+ 
+ 	/* hub notices our request, issues downstream resume, etc */
+@@ -713,6 +715,9 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
+ 	dum->gadget.ops = &dummy_ops;
+ 	dum->gadget.is_dualspeed = 1;
+ 
++	/* maybe claim OTG support, though we won't complete HNP */
++	dum->gadget.is_otg = (dummy_to_hcd(dum)->self.otg_port != 0);
++
+ 	dum->devstatus = 0;
+ 	dum->resuming = 0;
+ 
+@@ -1215,6 +1220,16 @@ static void dummy_timer (unsigned long _dum)
+ 					switch (setup.wValue) {
+ 					case USB_DEVICE_REMOTE_WAKEUP:
+ 						break;
++					case USB_DEVICE_B_HNP_ENABLE:
++						dum->gadget.b_hnp_enable = 1;
++						break;
++					case USB_DEVICE_A_HNP_SUPPORT:
++						dum->gadget.a_hnp_support = 1;
++						break;
++					case USB_DEVICE_A_ALT_HNP_SUPPORT:
++						dum->gadget.a_alt_hnp_support
++							= 1;
++						break;
+ 					default:
+ 						value = -EOPNOTSUPP;
+ 					}
+@@ -1533,6 +1548,13 @@ static int dummy_hub_control (
+ 					spin_unlock (&dum->lock);
+ 					dum->driver->suspend (&dum->gadget);
+ 					spin_lock (&dum->lock);
++					/* HNP would happen here; for now we
++					 * assume b_bus_req is always true.
++					 */
++					if (((1 << USB_DEVICE_B_HNP_ENABLE)
++							& dum->devstatus) != 0)
++						dev_dbg (dummy_dev(dum),
++							"no HNP yet!\n");
+ 				}
+ 			}
+ 			break;
+@@ -1648,6 +1670,10 @@ static int dummy_start (struct usb_hcd *hcd)
+ 	hcd->power_budget = 8;
+ 	hcd->state = HC_STATE_RUNNING;
+ 
++#ifdef CONFIG_USB_OTG
++	hcd->self.otg_port = 1;
++#endif
++
+ 	/* FIXME 'urbs' should be a per-device thing, maybe in usbcore */
+ 	device_create_file (dummy_dev(dum), &dev_attr_urbs);
+ 	return 0;

commit 247f3105636caa9d1d8a4c3dfb755de42633bc80
+Author: Alan Stern 
+Date:   Mon Apr 25 11:28:04 2005 -0400
+
+    [PATCH] USB HCDs: no longer need to register root hub
+    
+    This patch changes the host controller drivers; they no longer need to
+    register their root hubs because usbcore will take care of it for them.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index 9d37fc771b27..1918d10f7569 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -1625,7 +1625,6 @@ static DEVICE_ATTR (urbs, S_IRUGO, show_urbs, NULL);
+ static int dummy_start (struct usb_hcd *hcd)
+ {
+ 	struct dummy		*dum;
+-	struct usb_device	*root;
+ 	int			retval;
+ 
+ 	dum = hcd_to_dummy (hcd);
+@@ -1642,35 +1641,16 @@ static int dummy_start (struct usb_hcd *hcd)
+ 
+ 	INIT_LIST_HEAD (&dum->urbp_list);
+ 
+-	root = usb_alloc_dev (NULL, &hcd->self, 0);
+-	if (!root)
+-		return -ENOMEM;
++	if ((retval = dummy_register_udc (dum)) != 0)
++		return retval;
+ 
+ 	/* only show a low-power port: just 8mA */
+ 	hcd->power_budget = 8;
+-
+-	/* root hub enters addressed state... */
+ 	hcd->state = HC_STATE_RUNNING;
+-	root->speed = USB_SPEED_HIGH;
+-
+-	/* ...then configured, so khubd sees us. */
+-	if ((retval = usb_hcd_register_root_hub (root, hcd)) != 0) {
+-		goto err1;
+-	}
+-
+-	if ((retval = dummy_register_udc (dum)) != 0)
+-		goto err2;
+ 
+ 	/* FIXME 'urbs' should be a per-device thing, maybe in usbcore */
+ 	device_create_file (dummy_dev(dum), &dev_attr_urbs);
+ 	return 0;
+-
+- err2:
+-	usb_disconnect (&hcd->self.root_hub);
+- err1:
+-	usb_put_dev (root);
+-	hcd->state = HC_STATE_QUIESCING;
+-	return retval;
+ }
+ 
+ static void dummy_stop (struct usb_hcd *hcd)
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index bc69bd7acebe..527abc693b17 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -492,8 +492,6 @@ static int ehci_start (struct usb_hcd *hcd)
+ {
+ 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+ 	u32			temp;
+-	struct usb_device	*udev;
+-	struct usb_bus		*bus;
+ 	int			retval;
+ 	u32			hcc_params;
+ 	u8                      sbrn = 0;
+@@ -631,17 +629,6 @@ static int ehci_start (struct usb_hcd *hcd)
+ 
+ 	/* set async sleep time = 10 us ... ? */
+ 
+-	/* wire up the root hub */
+-	bus = hcd_to_bus (hcd);
+-	udev = first ? usb_alloc_dev (NULL, bus, 0) : bus->root_hub;
+-	if (!udev) {
+-done2:
+-		ehci_mem_cleanup (ehci);
+-		return -ENOMEM;
+-	}
+-	udev->speed = USB_SPEED_HIGH;
+-	udev->state = first ? USB_STATE_ATTACHED : USB_STATE_CONFIGURED;
+-
+ 	/*
+ 	 * Start, enabling full USB 2.0 functionality ... usb 1.1 devices
+ 	 * are explicitly handed to companion controller(s), so no TT is
+@@ -664,24 +651,6 @@ static int ehci_start (struct usb_hcd *hcd)
+ 		first ? "initialized" : "restarted",
+ 		temp >> 8, temp & 0xff, DRIVER_VERSION);
+ 
+-	/*
+-	 * From here on, khubd concurrently accesses the root
+-	 * hub; drivers will be talking to enumerated devices.
+-	 * (On restart paths, khubd already knows about the root
+-	 * hub and could find work as soon as we wrote FLAG_CF.)
+-	 *
+-	 * Before this point the HC was idle/ready.  After, khubd
+-	 * and device drivers may start it running.
+-	 */
+-	if (first && usb_hcd_register_root_hub (udev, hcd) != 0) {
+-		if (hcd->state == HC_STATE_RUNNING)
+-			ehci_quiesce (ehci);
+-		ehci_reset (ehci);
+-		usb_put_dev (udev); 
+-		retval = -ENODEV;
+-		goto done2;
+-	}
+-
+ 	writel (INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */
+ 
+ 	if (first)
+diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
+index 1183988fdf54..ff0a168e8eed 100644
+--- a/drivers/usb/host/isp116x-hcd.c
++++ b/drivers/usb/host/isp116x-hcd.c
+@@ -1547,7 +1547,6 @@ static int isp116x_start(struct usb_hcd *hcd)
+ {
+ 	struct isp116x *isp116x = hcd_to_isp116x(hcd);
+ 	struct isp116x_platform_data *board = isp116x->board;
+-	struct usb_device *udev;
+ 	u32 val;
+ 	unsigned long flags;
+ 
+@@ -1609,24 +1608,9 @@ static int isp116x_start(struct usb_hcd *hcd)
+ 	isp116x->rhstatus = isp116x_read_reg32(isp116x, HCRHSTATUS);
+ 
+ 	isp116x_write_reg32(isp116x, HCFMINTVL, 0x27782edf);
+-	spin_unlock_irqrestore(&isp116x->lock, flags);
+-
+-	udev = usb_alloc_dev(NULL, &hcd->self, 0);
+-	if (!udev) {
+-		isp116x_stop(hcd);
+-		return -ENOMEM;
+-	}
+ 
+-	udev->speed = USB_SPEED_FULL;
+ 	hcd->state = HC_STATE_RUNNING;
+ 
+-	if (usb_hcd_register_root_hub(udev, hcd) != 0) {
+-		isp116x_stop(hcd);
+-		usb_put_dev(udev);
+-		return -ENODEV;
+-	}
+-
+-	spin_lock_irqsave(&isp116x->lock, flags);
+ 	/* Set up interrupts */
+ 	isp116x->intenb = HCINT_MIE | HCINT_RHSC | HCINT_UE;
+ 	if (board->remote_wakeup_enable)
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index 0da996191251..13cd2177b557 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -505,13 +505,10 @@ static int ohci_init (struct ohci_hcd *ohci)
+ /* Start an OHCI controller, set the BUS operational
+  * resets USB and controller
+  * enable interrupts 
+- * connect the virtual root hub
+  */
+ static int ohci_run (struct ohci_hcd *ohci)
+ {
+   	u32			mask, temp;
+-  	struct usb_device	*udev;
+-  	struct usb_bus		*bus;
+ 	int			first = ohci->fminterval == 0;
+ 
+ 	disable (ohci);
+@@ -672,36 +669,13 @@ static int ohci_run (struct ohci_hcd *ohci)
+ 
+ 	// POTPGT delay is bits 24-31, in 2 ms units.
+ 	mdelay ((temp >> 23) & 0x1fe);
+-	bus = &ohci_to_hcd(ohci)->self;
+ 	ohci_to_hcd(ohci)->state = HC_STATE_RUNNING;
+ 
+ 	ohci_dump (ohci, 1);
+ 
+-	udev = bus->root_hub;
+-	if (udev) {
+-		return 0;
+-	}
+- 
+-	/* connect the virtual root hub */
+-	udev = usb_alloc_dev (NULL, bus, 0);
+-	if (!udev) {
+-		disable (ohci);
+-		ohci->hc_control &= ~OHCI_CTRL_HCFS;
+-		ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
+-		return -ENOMEM;
+-	}
+-
+-	udev->speed = USB_SPEED_FULL;
+-	if (usb_hcd_register_root_hub (udev, ohci_to_hcd(ohci)) != 0) {
+-		usb_put_dev (udev);
+-		disable (ohci);
+-		ohci->hc_control &= ~OHCI_CTRL_HCFS;
+-		ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
+-		return -ENODEV;
+-	}
++	if (ohci_to_hcd(ohci)->self.root_hub == NULL)
++		create_debug_files (ohci);
+ 
+-	register_reboot_notifier (&ohci->reboot_notifier);
+-	create_debug_files (ohci);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
+index 1f2d00fe983a..6c3f910bc307 100644
+--- a/drivers/usb/host/sl811-hcd.c
++++ b/drivers/usb/host/sl811-hcd.c
+@@ -1563,15 +1563,8 @@ static int
+ sl811h_start(struct usb_hcd *hcd)
+ {
+ 	struct sl811		*sl811 = hcd_to_sl811(hcd);
+-	struct usb_device	*udev;
+ 
+ 	/* chip has been reset, VBUS power is off */
+-
+-	udev = usb_alloc_dev(NULL, &hcd->self, 0);
+-	if (!udev)
+-		return -ENOMEM;
+-
+-	udev->speed = USB_SPEED_FULL;
+ 	hcd->state = HC_STATE_RUNNING;
+ 
+ 	if (sl811->board) {
+@@ -1579,12 +1572,6 @@ sl811h_start(struct usb_hcd *hcd)
+ 		hcd->power_budget = sl811->board->power * 2;
+ 	}
+ 
+-	if (usb_hcd_register_root_hub(udev, hcd) != 0) {
+-		usb_put_dev(udev);
+-		sl811h_stop(hcd);
+-		return -ENODEV;
+-	}
+-
+ 	/* enable power and interupts */
+ 	port_power(sl811, 1);
+ 
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 6b87bd74b046..fdf54295da73 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -562,7 +562,6 @@ static int uhci_start(struct usb_hcd *hcd)
+ 	int retval = -EBUSY;
+ 	int i;
+ 	dma_addr_t dma_handle;
+-	struct usb_device *udev;
+ 	struct dentry *dentry;
+ 
+ 	hcd->uses_new_polling = 1;
+@@ -626,14 +625,6 @@ static int uhci_start(struct usb_hcd *hcd)
+ 		goto err_create_qh_pool;
+ 	}
+ 
+-	/* Initialize the root hub */
+-
+-	udev = usb_alloc_dev(NULL, &hcd->self, 0);
+-	if (!udev) {
+-		dev_err(uhci_dev(uhci), "unable to allocate root hub\n");
+-		goto err_alloc_root_hub;
+-	}
+-
+ 	uhci->term_td = uhci_alloc_td(uhci);
+ 	if (!uhci->term_td) {
+ 		dev_err(uhci_dev(uhci), "unable to allocate terminating TD\n");
+@@ -713,24 +704,11 @@ static int uhci_start(struct usb_hcd *hcd)
+ 
+ 	configure_hc(uhci);
+ 	start_rh(uhci);
+-
+-	udev->speed = USB_SPEED_FULL;
+-
+-	if (usb_hcd_register_root_hub(udev, hcd) != 0) {
+-		dev_err(uhci_dev(uhci), "unable to start root hub\n");
+-		retval = -ENOMEM;
+-		goto err_start_root_hub;
+-	}
+-
+ 	return 0;
+ 
+ /*
+  * error exits:
+  */
+-err_start_root_hub:
+-	reset_hc(uhci);
+-	del_timer_sync(&uhci->stall_timer);
+-
+ err_alloc_skelqh:
+ 	for (i = 0; i < UHCI_NUM_SKELQH; i++)
+ 		if (uhci->skelqh[i]) {
+@@ -742,9 +720,6 @@ static int uhci_start(struct usb_hcd *hcd)
+ 	uhci->term_td = NULL;
+ 
+ err_alloc_term_td:
+-	usb_put_dev(udev);
+-
+-err_alloc_root_hub:
+ 	dma_pool_destroy(uhci->qh_pool);
+ 	uhci->qh_pool = NULL;
+ 

commit 8ec8d20b21f00a36343ca0ebd6c6be9421724a1e
+Author: Alan Stern 
+Date:   Mon Apr 25 11:25:17 2005 -0400
+
+    [PATCH] usbcore: register root hub in usb_add_hcd
+    
+    This patch makes usbcore automatically allocate and register the root hub
+    device for a new host controller when the controller is registered.  This
+    way the HCDs don't all have to include the same boilerplate code.  As a
+    pleasant side benefit, the register_root_hub routine can now be made
+    static and not EXPORTed.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 1180c157b717..83e732a0d64a 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -832,30 +832,22 @@ static void usb_deregister_bus (struct usb_bus *bus)
+ }
+ 
+ /**
+- * usb_hcd_register_root_hub - called by HCD to register its root hub 
++ * register_root_hub - called by usb_add_hcd() to register a root hub
+  * @usb_dev: the usb root hub device to be registered.
+  * @hcd: host controller for this root hub
+  *
+- * The USB host controller calls this function to register the root hub
+- * properly with the USB subsystem.  It sets up the device properly in
+- * the device tree and stores the root_hub pointer in the bus structure,
+- * then calls usb_new_device() to register the usb device.  It also
+- * assigns the root hub's USB address (always 1).
++ * This function registers the root hub with the USB subsystem.  It sets up
++ * the device properly in the device tree and stores the root_hub pointer
++ * in the bus structure, then calls usb_new_device() to register the usb
++ * device.  It also assigns the root hub's USB address (always 1).
+  */
+-int usb_hcd_register_root_hub (struct usb_device *usb_dev, struct usb_hcd *hcd)
++static int register_root_hub (struct usb_device *usb_dev,
++		struct usb_hcd *hcd)
+ {
+ 	struct device *parent_dev = hcd->self.controller;
+ 	const int devnum = 1;
+ 	int retval;
+ 
+-	/* hcd->driver->start() reported can_wakeup, probably with
+-	 * assistance from board's boot firmware.
+-	 * NOTE:  normal devices won't enable wakeup by default.
+-	 */
+-	if (hcd->can_wakeup)
+-		dev_dbg (parent_dev, "supports USB remote wakeup\n");
+-	hcd->remote_wakeup = hcd->can_wakeup;
+-
+ 	usb_dev->devnum = devnum;
+ 	usb_dev->bus->devnum_next = devnum + 1;
+ 	memset (&usb_dev->bus->devmap.devicemap, 0,
+@@ -898,7 +890,6 @@ int usb_hcd_register_root_hub (struct usb_device *usb_dev, struct usb_hcd *hcd)
+ 
+ 	return retval;
+ }
+-EXPORT_SYMBOL_GPL(usb_hcd_register_root_hub);
+ 
+ void usb_enable_root_hub_irq (struct usb_bus *bus)
+ {
+@@ -1724,7 +1715,8 @@ EXPORT_SYMBOL (usb_put_hcd);
+ int usb_add_hcd(struct usb_hcd *hcd,
+ 		unsigned int irqnum, unsigned long irqflags)
+ {
+-	int	retval;
++	int retval;
++	struct usb_device *rhdev;
+ 
+ 	dev_info(hcd->self.controller, "%s\n", hcd->product_desc);
+ 
+@@ -1740,7 +1732,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ 	}
+ 
+ 	if ((retval = usb_register_bus(&hcd->self)) < 0)
+-		goto err1;
++		goto err_register_bus;
+ 
+ 	if (hcd->driver->irq) {
+ 		char	buf[8], *bufp = buf;
+@@ -1757,7 +1749,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ 				hcd->irq_descr, hcd)) != 0) {
+ 			dev_err(hcd->self.controller,
+ 					"request interrupt %s failed\n", bufp);
+-			goto err2;
++			goto err_request_irq;
+ 		}
+ 		hcd->irq = irqnum;
+ 		dev_info(hcd->self.controller, "irq %s, %s 0x%08llx\n", bufp,
+@@ -1773,21 +1765,55 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ 					(unsigned long long)hcd->rsrc_start);
+ 	}
+ 
++	/* Allocate the root hub before calling hcd->driver->start(),
++	 * but don't register it until afterward so that the hardware
++	 * is running.
++	 */
++	if ((rhdev = usb_alloc_dev(NULL, &hcd->self, 0)) == NULL) {
++		dev_err(hcd->self.controller, "unable to allocate root hub\n");
++		retval = -ENOMEM;
++		goto err_allocate_root_hub;
++	}
++	rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH :
++			USB_SPEED_FULL;
++
++	/* Although in principle hcd->driver->start() might need to use rhdev,
++	 * none of the current drivers do.
++	 */
+ 	if ((retval = hcd->driver->start(hcd)) < 0) {
+ 		dev_err(hcd->self.controller, "startup error %d\n", retval);
+-		goto err3;
++		goto err_hcd_driver_start;
+ 	}
+ 
++	/* hcd->driver->start() reported can_wakeup, probably with
++	 * assistance from board's boot firmware.
++	 * NOTE:  normal devices won't enable wakeup by default.
++	 */
++	if (hcd->can_wakeup)
++		dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");
++	hcd->remote_wakeup = hcd->can_wakeup;
++
++	if ((retval = register_root_hub(rhdev, hcd)) != 0)
++		goto err_register_root_hub;
++
+ 	if (hcd->uses_new_polling && hcd->poll_rh)
+ 		usb_hcd_poll_rh_status(hcd);
+ 	return retval;
+ 
+- err3:
++ err_register_root_hub:
++	hcd->driver->stop(hcd);
++
++ err_hcd_driver_start:
++	usb_put_dev(rhdev);
++
++ err_allocate_root_hub:
+ 	if (hcd->irq >= 0)
+ 		free_irq(irqnum, hcd);
+- err2:
++
++ err_request_irq:
+ 	usb_deregister_bus(&hcd->self);
+- err1:
++
++ err_register_bus:
+ 	hcd_buffer_destroy(hcd);
+ 	return retval;
+ } 
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index 3837f68bb7b3..8dc13cde2f73 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -353,9 +353,6 @@ extern long usb_calc_bus_time (int speed, int is_input,
+ 
+ extern struct usb_bus *usb_alloc_bus (struct usb_operations *);
+ 
+-extern int usb_hcd_register_root_hub (struct usb_device *usb_dev,
+-		struct usb_hcd *hcd);
+-
+ extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
+ 
+ extern void usb_set_device_state(struct usb_device *udev,

commit bc96c0ad1ed0c938fefc0423aa99f086c5a2a1ea
+Author: Alan Stern 
+Date:   Mon Apr 25 11:21:31 2005 -0400
+
+    [PATCH] ohci-omap, sl811, dummy: remove hub_set_power_budget
+    
+    This patch changes the HCDs that used the old hub_set_power_budget call,
+    making them use the new hcd->power_budget field instead.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index c039d2fbe7ab..9d37fc771b27 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -1646,6 +1646,9 @@ static int dummy_start (struct usb_hcd *hcd)
+ 	if (!root)
+ 		return -ENOMEM;
+ 
++	/* only show a low-power port: just 8mA */
++	hcd->power_budget = 8;
++
+ 	/* root hub enters addressed state... */
+ 	hcd->state = HC_STATE_RUNNING;
+ 	root->speed = USB_SPEED_HIGH;
+@@ -1655,9 +1658,6 @@ static int dummy_start (struct usb_hcd *hcd)
+ 		goto err1;
+ 	}
+ 
+-	/* only show a low-power port: just 8mA */
+-	hub_set_power_budget (root, 8);
+-
+ 	if ((retval = dummy_register_udc (dum)) != 0)
+ 		goto err2;
+ 
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index 32120042ab65..0da996191251 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -699,8 +699,6 @@ static int ohci_run (struct ohci_hcd *ohci)
+ 		ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
+ 		return -ENODEV;
+ 	}
+-	if (ohci->power_budget)
+-		hub_set_power_budget(udev, ohci->power_budget);
+ 
+ 	register_reboot_notifier (&ohci->reboot_notifier);
+ 	create_debug_files (ohci);
+diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
+index 8aab5907afe9..b62d69937694 100644
+--- a/drivers/usb/host/ohci-omap.c
++++ b/drivers/usb/host/ohci-omap.c
+@@ -181,7 +181,7 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
+ 	if (config->otg) {
+ 		ohci_to_hcd(ohci)->self.otg_port = config->otg;
+ 		/* default/minimum OTG power budget:  8 mA */
+-		ohci->power_budget = 8;
++		ohci_to_hcd(ohci)->power_budget = 8;
+ 	}
+ 
+ 	/* boards can use OTG transceivers in non-OTG modes */
+@@ -230,7 +230,7 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
+ 
+ 		/* TPS2045 switch for internal transceiver (port 1) */
+ 		if (machine_is_omap_osk()) {
+-			ohci->power_budget = 250;
++			ohci_to_hcd(ohci)->power_budget = 250;
+ 
+ 			rh &= ~RH_A_NOCP;
+ 
+diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
+index 3dbc7c0eed43..71cdd2262860 100644
+--- a/drivers/usb/host/ohci.h
++++ b/drivers/usb/host/ohci.h
+@@ -371,7 +371,6 @@ struct ohci_hcd {
+ 	 * other external transceivers should be software-transparent 
+ 	 */
+ 	struct otg_transceiver	*transceiver;
+-	unsigned		power_budget;
+ 
+ 	/*
+ 	 * memory management for queue data structures
+diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
+index 99d43f758ad0..1f2d00fe983a 100644
+--- a/drivers/usb/host/sl811-hcd.c
++++ b/drivers/usb/host/sl811-hcd.c
+@@ -1574,8 +1574,10 @@ sl811h_start(struct usb_hcd *hcd)
+ 	udev->speed = USB_SPEED_FULL;
+ 	hcd->state = HC_STATE_RUNNING;
+ 
+-	if (sl811->board)
++	if (sl811->board) {
+ 		hcd->can_wakeup = sl811->board->can_wakeup;
++		hcd->power_budget = sl811->board->power * 2;
++	}
+ 
+ 	if (usb_hcd_register_root_hub(udev, hcd) != 0) {
+ 		usb_put_dev(udev);
+@@ -1583,9 +1585,6 @@ sl811h_start(struct usb_hcd *hcd)
+ 		return -ENODEV;
+ 	}
+ 
+-	if (sl811->board && sl811->board->power)
+-		hub_set_power_budget(udev, sl811->board->power * 2);
+-
+ 	/* enable power and interupts */
+ 	port_power(sl811, 1);
+ 

commit 2532178a68b5ce4e421d50ea1b1dcc0a1359f19d
+Author: Alan Stern 
+Date:   Mon Apr 25 11:14:31 2005 -0400
+
+    [PATCH] UHCI: Don't store device pointer in QH or TD
+    
+    This patch simplifies the uhci-hcd driver by removing the device pointer
+    currently stored in the QH and TD structures.  Those pointers weren't
+    being used for anything other than to increment the device's reference
+    count, which is unnecessary since the device is used only when an URB
+    completes, and outstanding URBs take their own reference to the device.
+    As a useful side effect, this change means that uhci-hcd no longer needs
+    to have the root-hub device available in the start routine.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 53ba8a56592e..6b87bd74b046 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -634,14 +634,14 @@ static int uhci_start(struct usb_hcd *hcd)
+ 		goto err_alloc_root_hub;
+ 	}
+ 
+-	uhci->term_td = uhci_alloc_td(uhci, udev);
++	uhci->term_td = uhci_alloc_td(uhci);
+ 	if (!uhci->term_td) {
+ 		dev_err(uhci_dev(uhci), "unable to allocate terminating TD\n");
+ 		goto err_alloc_term_td;
+ 	}
+ 
+ 	for (i = 0; i < UHCI_NUM_SKELQH; i++) {
+-		uhci->skelqh[i] = uhci_alloc_qh(uhci, udev);
++		uhci->skelqh[i] = uhci_alloc_qh(uhci);
+ 		if (!uhci->skelqh[i]) {
+ 			dev_err(uhci_dev(uhci), "unable to allocate QH\n");
+ 			goto err_alloc_skelqh;
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index d7c67b73eb7a..bf9c5f9b508b 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -114,7 +114,6 @@ struct uhci_qh {
+ 	/* Software fields */
+ 	dma_addr_t dma_handle;
+ 
+-	struct usb_device *dev;
+ 	struct urb_priv *urbp;
+ 
+ 	struct list_head list;		/* P: uhci->frame_list_lock */
+@@ -206,7 +205,6 @@ struct uhci_td {
+ 	/* Software fields */
+ 	dma_addr_t dma_handle;
+ 
+-	struct usb_device *dev;
+ 	struct urb *urb;
+ 
+ 	struct list_head list;		/* P: urb->lock */
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 77f264851e98..5f18084a116d 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -48,7 +48,7 @@ static inline void uhci_moveto_complete(struct uhci_hcd *uhci,
+ 	list_move_tail(&urbp->urb_list, &uhci->complete_list);
+ }
+ 
+-static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci, struct usb_device *dev)
++static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci)
+ {
+ 	dma_addr_t dma_handle;
+ 	struct uhci_td *td;
+@@ -63,14 +63,11 @@ static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci, struct usb_device *d
+ 	td->buffer = 0;
+ 
+ 	td->frame = -1;
+-	td->dev = dev;
+ 
+ 	INIT_LIST_HEAD(&td->list);
+ 	INIT_LIST_HEAD(&td->remove_list);
+ 	INIT_LIST_HEAD(&td->fl_list);
+ 
+-	usb_get_dev(dev);
+-
+ 	return td;
+ }
+ 
+@@ -170,13 +167,10 @@ static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td)
+ 	if (!list_empty(&td->fl_list))
+ 		dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td);
+ 
+-	if (td->dev)
+-		usb_put_dev(td->dev);
+-
+ 	dma_pool_free(uhci->td_pool, td, td->dma_handle);
+ }
+ 
+-static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, struct usb_device *dev)
++static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci)
+ {
+ 	dma_addr_t dma_handle;
+ 	struct uhci_qh *qh;
+@@ -190,14 +184,11 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, struct usb_device *d
+ 	qh->element = UHCI_PTR_TERM;
+ 	qh->link = UHCI_PTR_TERM;
+ 
+-	qh->dev = dev;
+ 	qh->urbp = NULL;
+ 
+ 	INIT_LIST_HEAD(&qh->list);
+ 	INIT_LIST_HEAD(&qh->remove_list);
+ 
+-	usb_get_dev(dev);
+-
+ 	return qh;
+ }
+ 
+@@ -208,9 +199,6 @@ static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+ 	if (!list_empty(&qh->remove_list))
+ 		dev_warn(uhci_dev(uhci), "qh %p still in remove_list!\n", qh);
+ 
+-	if (qh->dev)
+-		usb_put_dev(qh->dev);
+-
+ 	dma_pool_free(uhci->qh_pool, qh, qh->dma_handle);
+ }
+ 
+@@ -599,7 +587,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
+ 	/*
+ 	 * Build the TD for the control request setup packet
+ 	 */
+-	td = uhci_alloc_td(uhci, urb->dev);
++	td = uhci_alloc_td(uhci);
+ 	if (!td)
+ 		return -ENOMEM;
+ 
+@@ -628,7 +616,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
+ 		if (pktsze > maxsze)
+ 			pktsze = maxsze;
+ 
+-		td = uhci_alloc_td(uhci, urb->dev);
++		td = uhci_alloc_td(uhci);
+ 		if (!td)
+ 			return -ENOMEM;
+ 
+@@ -646,7 +634,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
+ 	/*
+ 	 * Build the final TD for control status 
+ 	 */
+-	td = uhci_alloc_td(uhci, urb->dev);
++	td = uhci_alloc_td(uhci);
+ 	if (!td)
+ 		return -ENOMEM;
+ 
+@@ -668,7 +656,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
+ 	uhci_fill_td(td, status | TD_CTRL_IOC,
+ 		destination | uhci_explen(UHCI_NULL_DATA_SIZE), 0);
+ 
+-	qh = uhci_alloc_qh(uhci, urb->dev);
++	qh = uhci_alloc_qh(uhci);
+ 	if (!qh)
+ 		return -ENOMEM;
+ 
+@@ -867,7 +855,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb
+ 				status &= ~TD_CTRL_SPD;
+ 		}
+ 
+-		td = uhci_alloc_td(uhci, urb->dev);
++		td = uhci_alloc_td(uhci);
+ 		if (!td)
+ 			return -ENOMEM;
+ 
+@@ -893,7 +881,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb
+ 	 */
+ 	if (usb_pipeout(urb->pipe) && (urb->transfer_flags & URB_ZERO_PACKET) &&
+ 	    !len && urb->transfer_buffer_length) {
+-		td = uhci_alloc_td(uhci, urb->dev);
++		td = uhci_alloc_td(uhci);
+ 		if (!td)
+ 			return -ENOMEM;
+ 
+@@ -915,7 +903,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb
+ 	 * flag setting. */
+ 	td->status |= cpu_to_le32(TD_CTRL_IOC);
+ 
+-	qh = uhci_alloc_qh(uhci, urb->dev);
++	qh = uhci_alloc_qh(uhci);
+ 	if (!qh)
+ 		return -ENOMEM;
+ 
+@@ -1098,7 +1086,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
+ 		if (!urb->iso_frame_desc[i].length)
+ 			continue;
+ 
+-		td = uhci_alloc_td(uhci, urb->dev);
++		td = uhci_alloc_td(uhci);
+ 		if (!td)
+ 			return -ENOMEM;
+ 

commit 7d35b9298539d2818c51fe9070b08cf9876016f4
+Author: Alan Stern 
+Date:   Mon Apr 25 11:18:32 2005 -0400
+
+    [PATCH] usbcore: Remove hub_set_power_budget
+    
+    This patch removes the hub_set_power_budget routine, which was used by a
+    couple of HCDs to indicate that the root hub was running on battery power.
+    In its place is a new field added to struct usb_hcd, which HCDs can set
+    before the root hub is registered.  Special-case code in the hub driver
+    knows to look at this field when configuring a root hub.
+    
+    Signed-off-by: Alan Stern 
+    Acked-by: David Brownell 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index ac5752778e39..3837f68bb7b3 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -87,6 +87,7 @@ struct usb_hcd {	/* usb_bus.hcpriv points to this */
+ 	void __iomem		*regs;		/* device memory/io */
+ 	u64			rsrc_start;	/* memory/io resource start */
+ 	u64			rsrc_len;	/* memory/io resource length */
++	unsigned		power_budget;	/* in mA, 0 = no limit */
+ 
+ #define HCD_BUFFER_POOLS	4
+ 	struct dma_pool		*pool [HCD_BUFFER_POOLS];
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 6d1a330d577b..63ee3d97b6a9 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -643,15 +643,21 @@ static int hub_configure(struct usb_hub *hub,
+ 		message = "can't get hub status";
+ 		goto fail;
+ 	}
+-	cpu_to_le16s(&hubstatus);
+-	if ((hubstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0) {
++	le16_to_cpus(&hubstatus);
++	if (hdev == hdev->bus->root_hub) {
++		struct usb_hcd *hcd =
++				container_of(hdev->bus, struct usb_hcd, self);
++
++		hub->power_budget = min(500u, hcd->power_budget) / 2;
++	} else if ((hubstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0) {
+ 		dev_dbg(hub_dev, "hub controller current requirement: %dmA\n",
+ 			hub->descriptor->bHubContrCurrent);
+ 		hub->power_budget = (501 - hub->descriptor->bHubContrCurrent)
+ 					/ 2;
++	}
++	if (hub->power_budget)
+ 		dev_dbg(hub_dev, "%dmA bus power budget for children\n",
+ 			hub->power_budget * 2);
+-	}
+ 
+ 
+ 	ret = hub_hub_status(hub, &hubstatus, &hubchange);
+diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
+index d114b847d56f..53bf5649621e 100644
+--- a/drivers/usb/core/hub.h
++++ b/drivers/usb/core/hub.h
+@@ -224,15 +224,4 @@ struct usb_hub {
+ 	struct work_struct	leds;
+ };
+ 
+-/* use this for low-powered root hubs */
+-static inline void
+-hub_set_power_budget (struct usb_device *hubdev, unsigned mA)
+-{
+-	struct usb_hub	*hub;
+-
+-	hub = (struct usb_hub *)
+-		usb_get_intfdata (hubdev->actconfig->interface[0]);
+-	hub->power_budget = min(mA,(unsigned)500)/2;
+-}
+-
+ #endif /* __LINUX_HUB_H */

commit d5926ae7a827bdd06b588ffbc56fd4525cd9214a
+Author: Alan Stern 
+Date:   Thu Apr 21 15:56:37 2005 -0400
+
+    [PATCH] usbcore support for root-hub IRQ instead of polling
+    
+    This is a revised version of an earlier patch to add support to usbcore
+    for driving root hubs by interrupts rather than polling.
+    
+    There's a temporary flag added to struct usb_hcd, marking devices whose
+    drivers are aware of the new mechanism.  By default that flag doesn't get
+    set so drivers will continue to see the same polling behavior as before.
+    This way we can convert the HCDs one by one to use interrupt-based event
+    reporting, and the temporary flag can be removed when they're all done.
+    
+    Also included is a small change to the hcd_disable_endpoint routine.
+    Although endpoints normally shouldn't be disabled while a controller is
+    suspended, it's legal to do so when the controller's driver is being
+    rmmod'ed.
+    
+    Lastly the patch adds a new callback, .hub_irq_enable, for use by HCDs
+    where the root hub's port-change interrupts are level-triggered rather
+    than edge-triggered.  The callback is invoked each time khubd has finished
+    processing a root hub, to let the HCD know that the interrupt can safely
+    be re-enabled.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 0da23732e807..1180c157b717 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -519,119 +519,120 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
+ /*-------------------------------------------------------------------------*/
+ 
+ /*
+- * Root Hub interrupt transfers are synthesized with a timer.
+- * Completions are called in_interrupt() but not in_irq().
++ * Root Hub interrupt transfers are polled using a timer if the
++ * driver requests it; otherwise the driver is responsible for
++ * calling usb_hcd_poll_rh_status() when an event occurs.
+  *
+- * Note: some root hubs (including common UHCI based designs) can't
+- * correctly issue port change IRQs.  They're the ones that _need_ a
+- * timer; most other root hubs don't.  Some systems could save a
+- * lot of battery power by eliminating these root hub timer IRQs.
++ * Completions are called in_interrupt(), but they may or may not
++ * be in_irq().
+  */
++void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
++{
++	struct urb	*urb;
++	int		length;
++	unsigned long	flags;
++	char		buffer[4];	/* Any root hubs with > 31 ports? */
+ 
+-static void rh_report_status (unsigned long ptr);
++	if (!hcd->uses_new_polling && !hcd->status_urb)
++		return;
+ 
+-static int rh_status_urb (struct usb_hcd *hcd, struct urb *urb) 
+-{
+-	int	len = 1 + (urb->dev->maxchild / 8);
++	length = hcd->driver->hub_status_data(hcd, buffer);
++	if (length > 0) {
+ 
+-	/* rh_timer protected by hcd_data_lock */
+-	if (hcd->rh_timer.data || urb->transfer_buffer_length < len) {
+-		dev_dbg (hcd->self.controller,
+-				"not queuing rh status urb, stat %d\n",
+-				urb->status);
+-		return -EINVAL;
++		/* try to complete the status urb */
++		local_irq_save (flags);
++		spin_lock(&hcd_root_hub_lock);
++		urb = hcd->status_urb;
++		if (urb) {
++			spin_lock(&urb->lock);
++			if (urb->status == -EINPROGRESS) {
++				hcd->poll_pending = 0;
++				hcd->status_urb = NULL;
++				urb->status = 0;
++				urb->hcpriv = NULL;
++				urb->actual_length = length;
++				memcpy(urb->transfer_buffer, buffer, length);
++			} else		/* urb has been unlinked */
++				length = 0;
++			spin_unlock(&urb->lock);
++		} else
++			length = 0;
++		spin_unlock(&hcd_root_hub_lock);
++
++		/* local irqs are always blocked in completions */
++		if (length > 0)
++			usb_hcd_giveback_urb (hcd, urb, NULL);
++		else
++			hcd->poll_pending = 1;
++		local_irq_restore (flags);
+ 	}
+ 
+-	init_timer (&hcd->rh_timer);
+-	hcd->rh_timer.function = rh_report_status;
+-	hcd->rh_timer.data = (unsigned long) urb;
+-	/* USB 2.0 spec says 256msec; this is close enough */
+-	hcd->rh_timer.expires = jiffies + HZ/4;
+-	add_timer (&hcd->rh_timer);
+-	urb->hcpriv = hcd;	/* nonzero to indicate it's queued */
+-	return 0;
++	/* The USB 2.0 spec says 256 ms.  This is close enough and won't
++	 * exceed that limit if HZ is 100. */
++	if (hcd->uses_new_polling ? hcd->poll_rh :
++			(length == 0 && hcd->status_urb != NULL))
++		mod_timer (&hcd->rh_timer, jiffies + msecs_to_jiffies(250));
+ }
++EXPORT_SYMBOL_GPL(usb_hcd_poll_rh_status);
+ 
+ /* timer callback */
++static void rh_timer_func (unsigned long _hcd)
++{
++	usb_hcd_poll_rh_status((struct usb_hcd *) _hcd);
++}
++
++/*-------------------------------------------------------------------------*/
+ 
+-static void rh_report_status (unsigned long ptr)
++static int rh_queue_status (struct usb_hcd *hcd, struct urb *urb)
+ {
+-	struct urb	*urb;
+-	struct usb_hcd	*hcd;
+-	int		length = 0;
++	int		retval;
+ 	unsigned long	flags;
++	int		len = 1 + (urb->dev->maxchild / 8);
+ 
+-	urb = (struct urb *) ptr;
+-	local_irq_save (flags);
+-	spin_lock (&urb->lock);
++	spin_lock_irqsave (&hcd_root_hub_lock, flags);
++	if (urb->status != -EINPROGRESS)	/* already unlinked */
++		retval = urb->status;
++	else if (hcd->status_urb || urb->transfer_buffer_length < len) {
++		dev_dbg (hcd->self.controller, "not queuing rh status urb\n");
++		retval = -EINVAL;
++	} else {
++		hcd->status_urb = urb;
++		urb->hcpriv = hcd;	/* indicate it's queued */
+ 
+-	/* do nothing if the urb's been unlinked */
+-	if (!urb->dev
+-			|| urb->status != -EINPROGRESS
+-			|| (hcd = urb->dev->bus->hcpriv) == NULL) {
+-		spin_unlock (&urb->lock);
+-		local_irq_restore (flags);
+-		return;
+-	}
++		if (!hcd->uses_new_polling)
++			mod_timer (&hcd->rh_timer, jiffies +
++					msecs_to_jiffies(250));
+ 
+-	/* complete the status urb, or retrigger the timer */
+-	spin_lock (&hcd_data_lock);
+-	if (urb->dev->state == USB_STATE_CONFIGURED) {
+-		length = hcd->driver->hub_status_data (
+-					hcd, urb->transfer_buffer);
+-		if (length > 0) {
+-			hcd->rh_timer.data = 0;
+-			urb->actual_length = length;
+-			urb->status = 0;
+-			urb->hcpriv = NULL;
+-		} else
+-			mod_timer (&hcd->rh_timer, jiffies + HZ/4);
++		/* If a status change has already occurred, report it ASAP */
++		else if (hcd->poll_pending)
++			mod_timer (&hcd->rh_timer, jiffies);
++		retval = 0;
+ 	}
+-	spin_unlock (&hcd_data_lock);
+-	spin_unlock (&urb->lock);
+-
+-	/* local irqs are always blocked in completions */
+-	if (length > 0)
+-		usb_hcd_giveback_urb (hcd, urb, NULL);
+-	local_irq_restore (flags);
++	spin_unlock_irqrestore (&hcd_root_hub_lock, flags);
++	return retval;
+ }
+ 
+-/*-------------------------------------------------------------------------*/
+-
+ static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb)
+ {
+-	if (usb_pipeint (urb->pipe)) {
+-		int		retval;
+-		unsigned long	flags;
+-
+-		spin_lock_irqsave (&hcd_data_lock, flags);
+-		retval = rh_status_urb (hcd, urb);
+-		spin_unlock_irqrestore (&hcd_data_lock, flags);
+-		return retval;
+-	}
++	if (usb_pipeint (urb->pipe))
++		return rh_queue_status (hcd, urb);
+ 	if (usb_pipecontrol (urb->pipe))
+ 		return rh_call_control (hcd, urb);
+-	else
+-		return -EINVAL;
++	return -EINVAL;
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++/* Asynchronous unlinks of root-hub control URBs are legal, but they
++ * don't do anything.  Status URB unlinks must be made in process context
++ * with interrupts enabled.
++ */
+ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
+ {
+-	unsigned long	flags;
+-
+-	/* note:  always a synchronous unlink */
+-	if ((unsigned long) urb == hcd->rh_timer.data) {
+-		del_timer_sync (&hcd->rh_timer);
+-		hcd->rh_timer.data = 0;
+-
+-		local_irq_save (flags);
+-		urb->hcpriv = NULL;
+-		usb_hcd_giveback_urb (hcd, urb, NULL);
+-		local_irq_restore (flags);
++	if (usb_pipeendpoint(urb->pipe) == 0) {	/* Control URB */
++		if (in_interrupt())
++			return 0;		/* nothing to do */
+ 
+-	} else if (usb_pipeendpoint(urb->pipe) == 0) {
+ 		spin_lock_irq(&urb->lock);	/* from usb_kill_urb */
+ 		++urb->reject;
+ 		spin_unlock_irq(&urb->lock);
+@@ -642,8 +643,22 @@ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
+ 		spin_lock_irq(&urb->lock);
+ 		--urb->reject;
+ 		spin_unlock_irq(&urb->lock);
+-	} else
+-		return -EINVAL;
++
++	} else {				/* Status URB */
++		if (!hcd->uses_new_polling)
++			del_timer_sync (&hcd->rh_timer);
++		local_irq_disable ();
++		spin_lock (&hcd_root_hub_lock);
++		if (urb == hcd->status_urb) {
++			hcd->status_urb = NULL;
++			urb->hcpriv = NULL;
++		} else
++			urb = NULL;		/* wasn't fully queued */
++		spin_unlock (&hcd_root_hub_lock);
++		if (urb)
++			usb_hcd_giveback_urb (hcd, urb, NULL);
++		local_irq_enable ();
++	}
+ 
+ 	return 0;
+ }
+@@ -885,6 +900,16 @@ int usb_hcd_register_root_hub (struct usb_device *usb_dev, struct usb_hcd *hcd)
+ }
+ EXPORT_SYMBOL_GPL(usb_hcd_register_root_hub);
+ 
++void usb_enable_root_hub_irq (struct usb_bus *bus)
++{
++	struct usb_hcd *hcd;
++
++	hcd = container_of (bus, struct usb_hcd, self);
++	if (hcd->driver->hub_irq_enable && !hcd->poll_rh &&
++			hcd->state != HC_STATE_HALT)
++		hcd->driver->hub_irq_enable (hcd);
++}
++
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+@@ -1348,7 +1373,8 @@ hcd_endpoint_disable (struct usb_device *udev, struct usb_host_endpoint *ep)
+ 
+ 	hcd = udev->bus->hcpriv;
+ 
+-	WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT);
++	WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT &&
++			udev->state != USB_STATE_NOTATTACHED);
+ 
+ 	local_irq_disable ();
+ 
+@@ -1612,6 +1638,8 @@ void usb_hc_died (struct usb_hcd *hcd)
+ 
+ 	spin_lock_irqsave (&hcd_root_hub_lock, flags);
+ 	if (hcd->rh_registered) {
++		hcd->poll_rh = 0;
++		del_timer(&hcd->rh_timer);
+ 
+ 		/* make khubd clean up old urbs and devices */
+ 		usb_set_device_state (hcd->self.root_hub,
+@@ -1665,6 +1693,8 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
+ 	hcd->self.bus_name = bus_name;
+ 
+ 	init_timer(&hcd->rh_timer);
++	hcd->rh_timer.function = rh_timer_func;
++	hcd->rh_timer.data = (unsigned long) hcd;
+ 
+ 	hcd->driver = driver;
+ 	hcd->product_desc = (driver->product_desc) ? driver->product_desc :
+@@ -1748,6 +1778,8 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ 		goto err3;
+ 	}
+ 
++	if (hcd->uses_new_polling && hcd->poll_rh)
++		usb_hcd_poll_rh_status(hcd);
+ 	return retval;
+ 
+  err3:
+@@ -1782,6 +1814,9 @@ void usb_remove_hcd(struct usb_hcd *hcd)
+ 	spin_unlock_irq (&hcd_root_hub_lock);
+ 	usb_disconnect(&hcd->self.root_hub);
+ 
++	hcd->poll_rh = 0;
++	del_timer_sync(&hcd->rh_timer);
++
+ 	hcd->driver->stop(hcd);
+ 	hcd->state = HC_STATE_HALT;
+ 
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index 325a51656c3f..ac5752778e39 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -65,7 +65,8 @@ struct usb_hcd {	/* usb_bus.hcpriv points to this */
+ 	const char		*product_desc;	/* product/vendor string */
+ 	char			irq_descr[24];	/* driver + bus # */
+ 
+-	struct timer_list	rh_timer;	/* drives root hub */
++	struct timer_list	rh_timer;	/* drives root-hub polling */
++	struct urb		*status_urb;	/* the current status urb */
+ 
+ 	/*
+ 	 * hardware info/state
+@@ -76,6 +77,12 @@ struct usb_hcd {	/* usb_bus.hcpriv points to this */
+ 	unsigned		remote_wakeup:1;/* sw should use wakeup? */
+ 	unsigned		rh_registered:1;/* is root hub registered? */
+ 
++	/* The next flag is a stopgap, to be removed when all the HCDs
++	 * support the new root-hub polling mechanism. */
++	unsigned		uses_new_polling:1;
++	unsigned		poll_rh:1;	/* poll for rh status? */
++	unsigned		poll_pending:1;	/* status has changed? */
++
+ 	int			irq;		/* irq allocated */
+ 	void __iomem		*regs;		/* device memory/io */
+ 	u64			rsrc_start;	/* memory/io resource start */
+@@ -207,6 +214,8 @@ struct hc_driver {
+ 	int		(*hub_suspend)(struct usb_hcd *);
+ 	int		(*hub_resume)(struct usb_hcd *);
+ 	int		(*start_port_reset)(struct usb_hcd *, unsigned port_num);
++	void		(*hub_irq_enable)(struct usb_hcd *);
++		/* Needed only if port-change IRQs are level-triggered */
+ };
+ 
+ extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs);
+@@ -243,7 +252,9 @@ void hcd_buffer_free (struct usb_bus *bus, size_t size,
+ 
+ /* generic bus glue, needed for host controllers that don't use PCI */
+ extern irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs *r);
++
+ extern void usb_hc_died (struct usb_hcd *hcd);
++extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd);
+ 
+ /* -------------------------------------------------------------------------- */
+ 
+@@ -360,6 +371,8 @@ extern wait_queue_head_t usb_kill_urb_queue;
+ extern struct usb_bus *usb_bus_get (struct usb_bus *bus);
+ extern void usb_bus_put (struct usb_bus *bus);
+ 
++extern void usb_enable_root_hub_irq (struct usb_bus *bus);
++
+ extern int usb_find_interface_driver (struct usb_device *dev,
+ 	struct usb_interface *interface);
+ 
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index a8d879a85d04..6d1a330d577b 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2787,6 +2787,11 @@ static void hub_events(void)
+ 
+ 		hub->activating = 0;
+ 
++		/* If this is a root hub, tell the HCD it's okay to
++		 * re-enable port-change interrupts now. */
++		if (!hdev->parent)
++			usb_enable_root_hub_irq(hdev->bus);
++
+ loop:
+ 		usb_unlock_device(hdev);
+ 		usb_put_intf(intf);

commit 02597d2deec2a3de0e2b52c1f83904b65626a0d5
+Author: Alan Stern 
+Date:   Thu Apr 28 14:51:27 2005 -0400
+
+    [PATCH] USB UHCI: Add shutdown method
+    
+    After all the discussion you might not be interested in this still, but
+    nevertheless here it is.  This patch adds a shutdown method to the
+    uhci-hcd driver.  Its prerequisite is the patch you wrote adding shutdown
+    support for PCI.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index cec070fa8c83..53ba8a56592e 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -154,6 +154,7 @@ static void reset_hc(struct uhci_hcd *uhci)
+ 
+ /*
+  * Last rites for a defunct/nonfunctional controller
++ * or one we don't want to use any more.
+  */
+ static void hc_died(struct uhci_hcd *uhci)
+ {
+@@ -525,6 +526,20 @@ static int uhci_reset(struct usb_hcd *hcd)
+ 	return 0;
+ }
+ 
++/* Make sure the controller is quiescent and that we're not using it
++ * any more.  This is mainly for the benefit of programs which, like kexec,
++ * expect the hardware to be idle: not doing DMA or generating IRQs.
++ *
++ * This routine may be called in a damaged or failing kernel.  Hence we
++ * do not acquire the spinlock before shutting down the controller.
++ */
++static void uhci_shutdown(struct pci_dev *pdev)
++{
++	struct usb_hcd *hcd = (struct usb_hcd *) pci_get_drvdata(pdev);
++
++	hc_died(hcd_to_uhci(hcd));
++}
++
+ /*
+  * Allocate a frame list, and then setup the skeleton
+  *
+@@ -939,6 +954,7 @@ static struct pci_driver uhci_pci_driver = {
+ 
+ 	.probe =	usb_hcd_pci_probe,
+ 	.remove =	usb_hcd_pci_remove,
++	.shutdown =	uhci_shutdown,
+ 
+ #ifdef	CONFIG_PM
+ 	.suspend =	usb_hcd_pci_suspend,

commit c074b416b94c0aa4a371f24bf6cc13d8cf1fab59
+Author: Alan Stern 
+Date:   Fri Apr 22 14:39:12 2005 -0400
+
+    [PATCH] USB UHCI: improved reset handling
+    
+    This patch improves the strategy uhci-hcd uses for performing controller
+    resets and checking whether they are needed.
+    
+            The HCRESET command doesn't affect the Suspend, Resume,
+            or Reset bits in the port status & control registers, so
+            the driver must clear them by itself.  This means the
+            code to figure out how many ports there are has to be moved
+            to an earlier spot in the driver.
+    
+            The R/WC bits in the USBLEGSUP register can be set by the
+            hardware even in the absence of BIOS meddling with legacy
+            support features.  Hence it's not a good idea to check them
+            while trying to determine whether the BIOS has altered the
+            controller's state.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 25a718eb1d0f..cec070fa8c83 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -112,6 +112,8 @@ static inline void restart_timer(struct uhci_hcd *uhci)
+  */
+ static void reset_hc(struct uhci_hcd *uhci)
+ {
++	int port;
++
+ 	/* Turn off PIRQ enable and SMI enable.  (This also turns off the
+ 	 * BIOS's USB Legacy Support.)  Turn off all the R/WC bits too.
+ 	 */
+@@ -135,6 +137,13 @@ static void reset_hc(struct uhci_hcd *uhci)
+ 	outw(0, uhci->io_addr + USBINTR);
+ 	outw(0, uhci->io_addr + USBCMD);
+ 
++	/* HCRESET doesn't affect the Suspend, Reset, and Resume Detect
++	 * bits in the port status and control registers.
++	 * We have to clear them by hand.
++	 */
++	for (port = 0; port < uhci->rh_numports; ++port)
++		outw(0, uhci->io_addr + USBPORTSC1 + (port * 2));
++
+ 	uhci->port_c_suspend = uhci->suspended_ports =
+ 			uhci->resuming_ports = 0;
+ 	uhci->rh_state = UHCI_RH_RESET;
+@@ -166,14 +175,14 @@ static void check_and_reset_hc(struct uhci_hcd *uhci)
+ 	 * When restarting a suspended controller, we expect all the
+ 	 * settings to be the same as we left them:
+ 	 *
+-	 *	PIRQ and SMI disabled, no R/WC bits set in USBLEGSUP;
++	 *	PIRQ and SMI disabled, no R/W bits set in USBLEGSUP;
+ 	 *	Controller is stopped and configured with EGSM set;
+ 	 *	No interrupts enabled except possibly Resume Detect.
+ 	 *
+ 	 * If any of these conditions are violated we do a complete reset.
+ 	 */
+ 	pci_read_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, &legsup);
+-	if (legsup & ~USBLEGSUP_RO) {
++	if (legsup & ~(USBLEGSUP_RO | USBLEGSUP_RWC)) {
+ 		dev_dbg(uhci_dev(uhci), "%s: legsup = 0x%04x\n",
+ 				__FUNCTION__, legsup);
+ 		goto reset_needed;
+@@ -478,9 +487,37 @@ static void release_uhci(struct uhci_hcd *uhci)
+ static int uhci_reset(struct usb_hcd *hcd)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++	unsigned io_size = (unsigned) hcd->rsrc_len;
++	int port;
+ 
+ 	uhci->io_addr = (unsigned long) hcd->rsrc_start;
+ 
++	/* The UHCI spec says devices must have 2 ports, and goes on to say
++	 * they may have more but gives no way to determine how many there
++	 * are.  However, according to the UHCI spec, Bit 7 of the port
++	 * status and control register is always set to 1.  So we try to
++	 * use this to our advantage.
++	 */
++	for (port = 0; port < (io_size - USBPORTSC1) / 2; port++) {
++		unsigned int portstatus;
++
++		portstatus = inw(uhci->io_addr + USBPORTSC1 + (port * 2));
++		if (!(portstatus & 0x0080))
++			break;
++	}
++	if (debug)
++		dev_info(uhci_dev(uhci), "detected %d ports\n", port);
++
++	/* Anything less than 2 or greater than 7 is weird,
++	 * so we'll ignore it.
++	 */
++	if (port < 2 || port > UHCI_RH_MAXCHILD) {
++		dev_info(uhci_dev(uhci), "port count misdetected? "
++				"forcing to 2 ports\n");
++		port = 2;
++	}
++	uhci->rh_numports = port;
++
+ 	/* Kick BIOS off this hardware and reset if the controller
+ 	 * isn't already safely quiescent.
+ 	 */
+@@ -508,13 +545,11 @@ static int uhci_start(struct usb_hcd *hcd)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 	int retval = -EBUSY;
+-	int i, port;
+-	unsigned io_size;
++	int i;
+ 	dma_addr_t dma_handle;
+ 	struct usb_device *udev;
+ 	struct dentry *dentry;
+ 
+-	io_size = (unsigned) hcd->rsrc_len;
+ 	hcd->uses_new_polling = 1;
+ 	if (pci_find_capability(to_pci_dev(uhci_dev(uhci)), PCI_CAP_ID_PM))
+ 		hcd->can_wakeup = 1;		/* Assume it supports PME# */
+@@ -578,30 +613,6 @@ static int uhci_start(struct usb_hcd *hcd)
+ 
+ 	/* Initialize the root hub */
+ 
+-	/* UHCI specs says devices must have 2 ports, but goes on to say */
+-	/*  they may have more but give no way to determine how many they */
+-	/*  have. However, according to the UHCI spec, Bit 7 is always set */
+-	/*  to 1. So we try to use this to our advantage */
+-	for (port = 0; port < (io_size - 0x10) / 2; port++) {
+-		unsigned int portstatus;
+-
+-		portstatus = inw(uhci->io_addr + 0x10 + (port * 2));
+-		if (!(portstatus & 0x0080))
+-			break;
+-	}
+-	if (debug)
+-		dev_info(uhci_dev(uhci), "detected %d ports\n", port);
+-
+-	/* This is experimental so anything less than 2 or greater than 8 is */
+-	/*  something weird and we'll ignore it */
+-	if (port < 2 || port > UHCI_RH_MAXCHILD) {
+-		dev_info(uhci_dev(uhci), "port count misdetected? "
+-				"forcing to 2 ports\n");
+-		port = 2;
+-	}
+-
+-	uhci->rh_numports = port;
+-
+ 	udev = usb_alloc_dev(NULL, &hcd->self, 0);
+ 	if (!udev) {
+ 		dev_err(uhci_dev(uhci), "unable to allocate root hub\n");

commit 6c1b445c226dd82d0961725dec8051b95003723a
+Author: Alan Stern 
+Date:   Thu Apr 21 16:04:58 2005 -0400
+
+    [PATCH] USB UHCI: Use root-hub IRQs while suspended
+    
+    This patch, which has as478b as a prerequisite, enables the uhci-hcd
+    driver to take advantage of root-hub IRQs rather than polling during the
+    time it is suspended.  (Unfortunately the hardware doesn't support
+    port-change interrupts while the controller is running.)  It also turns
+    off the driver's private timer while the controller is suspended, as it
+    isn't needed then.  The combined elimination of polling interrupts and
+    timer interrupts ought to be enough to allow some systems to save a
+    noticeable amount of power while they are otherwise idle.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 82e608a4bbd0..25a718eb1d0f 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -84,6 +84,8 @@ static char *errbuf;
+ 
+ static kmem_cache_t *uhci_up_cachep;	/* urb_priv */
+ 
++static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state);
++static void wakeup_rh(struct uhci_hcd *uhci);
+ static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
+ 
+ /* If a transfer is still active after this much time, turn off FSBR */
+@@ -133,12 +135,12 @@ static void reset_hc(struct uhci_hcd *uhci)
+ 	outw(0, uhci->io_addr + USBINTR);
+ 	outw(0, uhci->io_addr + USBCMD);
+ 
+-	uhci->resume_detect = 0;
+ 	uhci->port_c_suspend = uhci->suspended_ports =
+ 			uhci->resuming_ports = 0;
+ 	uhci->rh_state = UHCI_RH_RESET;
+ 	uhci->is_stopped = UHCI_IS_STOPPED;
+ 	uhci_to_hcd(uhci)->state = HC_STATE_HALT;
++	uhci_to_hcd(uhci)->poll_rh = 0;
+ }
+ 
+ /*
+@@ -148,6 +150,7 @@ static void hc_died(struct uhci_hcd *uhci)
+ {
+ 	reset_hc(uhci);
+ 	uhci->hc_inaccessible = 1;
++	del_timer(&uhci->stall_timer);
+ }
+ 
+ /*
+@@ -302,14 +305,14 @@ __acquires(uhci->lock)
+ 
+ 	uhci->rh_state = new_state;
+ 	uhci->is_stopped = UHCI_IS_STOPPED;
+-	uhci->resume_detect = 0;
++	del_timer(&uhci->stall_timer);
++	uhci_to_hcd(uhci)->poll_rh = !int_enable;
+ 
+ 	uhci_scan_schedule(uhci, NULL);
+ }
+ 
+ static void start_rh(struct uhci_hcd *uhci)
+ {
+-	uhci->rh_state = UHCI_RH_RUNNING;
+ 	uhci->is_stopped = 0;
+ 	smp_wmb();
+ 
+@@ -320,6 +323,9 @@ static void start_rh(struct uhci_hcd *uhci)
+ 	outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP,
+ 			uhci->io_addr + USBINTR);
+ 	mb();
++	uhci->rh_state = UHCI_RH_RUNNING;
++	uhci_to_hcd(uhci)->poll_rh = 1;
++	restart_timer(uhci);
+ }
+ 
+ static void wakeup_rh(struct uhci_hcd *uhci)
+@@ -353,36 +359,9 @@ __acquires(uhci->lock)
+ 	}
+ 
+ 	start_rh(uhci);
+-}
+-
+-static void rh_state_transitions(struct uhci_hcd *uhci)
+-{
+-	switch (uhci->rh_state) {
+-	    case UHCI_RH_RUNNING:
+-		/* are any devices attached? */
+-		if (!any_ports_active(uhci)) {
+-			uhci->rh_state = UHCI_RH_RUNNING_NODEVS;
+-			uhci->auto_stop_time = jiffies + HZ;
+-		}
+-		break;
+ 
+-	    case UHCI_RH_RUNNING_NODEVS:
+-		/* auto-stop if nothing connected for 1 second */
+-		if (any_ports_active(uhci))
+-			uhci->rh_state = UHCI_RH_RUNNING;
+-		else if (time_after_eq(jiffies, uhci->auto_stop_time))
+-			suspend_rh(uhci, UHCI_RH_AUTO_STOPPED);
+-		break;
+-
+-	    case UHCI_RH_AUTO_STOPPED:
+-		/* wakeup if requested by a device */
+-		if (uhci->resume_detect)
+-			wakeup_rh(uhci);
+-		break;
+-
+-	    default:
+-		break;
+-	}
++	/* Restart root hub polling */
++	mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);
+ }
+ 
+ static void stall_callback(unsigned long _uhci)
+@@ -394,14 +373,8 @@ static void stall_callback(unsigned long _uhci)
+ 	uhci_scan_schedule(uhci, NULL);
+ 	check_fsbr(uhci);
+ 
+-	/* Poll for and perform state transitions */
+-	if (!uhci->hc_inaccessible) {
+-		rh_state_transitions(uhci);
+-		if (uhci->suspended_ports)
+-			uhci_check_ports(uhci);
+-	}
+-
+-	restart_timer(uhci);
++	if (!uhci->is_stopped)
++		restart_timer(uhci);
+ 	spin_unlock_irqrestore(&uhci->lock, flags);
+ }
+ 
+@@ -443,7 +416,7 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
+ 	}
+ 
+ 	if (status & USBSTS_RD)
+-		uhci->resume_detect = 1;
++		usb_hcd_poll_rh_status(hcd);
+ 
+ 	spin_lock_irqsave(&uhci->lock, flags);
+ 	uhci_scan_schedule(uhci, regs);
+@@ -542,6 +515,7 @@ static int uhci_start(struct usb_hcd *hcd)
+ 	struct dentry *dentry;
+ 
+ 	io_size = (unsigned) hcd->rsrc_len;
++	hcd->uses_new_polling = 1;
+ 	if (pci_find_capability(to_pci_dev(uhci_dev(uhci)), PCI_CAP_ID_PM))
+ 		hcd->can_wakeup = 1;		/* Assume it supports PME# */
+ 
+@@ -714,8 +688,6 @@ static int uhci_start(struct usb_hcd *hcd)
+ 	configure_hc(uhci);
+ 	start_rh(uhci);
+ 
+-	restart_timer(uhci);
+-
+ 	udev->speed = USB_SPEED_FULL;
+ 
+ 	if (usb_hcd_register_root_hub(udev, hcd) != 0) {
+@@ -730,8 +702,8 @@ static int uhci_start(struct usb_hcd *hcd)
+  * error exits:
+  */
+ err_start_root_hub:
+-	del_timer_sync(&uhci->stall_timer);
+ 	reset_hc(uhci);
++	del_timer_sync(&uhci->stall_timer);
+ 
+ err_alloc_skelqh:
+ 	for (i = 0; i < UHCI_NUM_SKELQH; i++)
+@@ -771,13 +743,12 @@ static void uhci_stop(struct usb_hcd *hcd)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 
+-	del_timer_sync(&uhci->stall_timer);
+-
+ 	spin_lock_irq(&uhci->lock);
+ 	reset_hc(uhci);
+ 	uhci_scan_schedule(uhci, NULL);
+ 	spin_unlock_irq(&uhci->lock);
+-	
++
++	del_timer_sync(&uhci->stall_timer);
+ 	release_uhci(uhci);
+ }
+ 
+@@ -844,6 +815,8 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
+ 
+ done:
+ 	spin_unlock_irq(&uhci->lock);
++	if (rc == 0)
++		del_timer_sync(&hcd->rh_timer);
+ 	return rc;
+ }
+ 
+@@ -875,6 +848,9 @@ static int uhci_resume(struct usb_hcd *hcd)
+ 		suspend_rh(uhci, UHCI_RH_SUSPENDED);
+ 
+ 	spin_unlock_irq(&uhci->lock);
++
++	if (hcd->poll_rh)
++		usb_hcd_poll_rh_status(hcd);
+ 	return 0;
+ }
+ #endif
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index 827df5e06800..d7c67b73eb7a 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -327,18 +327,19 @@ static inline int __interval_to_skel(int interval)
+  * driver learns to autosuspend.)
+  */
+ enum uhci_rh_state {
+-	/* In the next 4 states the HC must be halted */
+-	UHCI_RH_RESET,			/* These two must come first */
++	/* In the following states the HC must be halted.
++	 * These two must come first */
++	UHCI_RH_RESET,
+ 	UHCI_RH_SUSPENDED,
+ 
+ 	UHCI_RH_AUTO_STOPPED,
+ 	UHCI_RH_RESUMING,
+ 
+-	/* In the next state the HC changes from running to halted, so it
+-	 * can legally appear either way */
++	/* In this state the HC changes from running to halted,
++	 * so it can legally appear either way. */
+ 	UHCI_RH_SUSPENDING,
+ 
+-	/* In the next two states it's an error if the HC is halted.
++	/* In the following states it's an error if the HC is halted.
+ 	 * These two must come last */
+ 	UHCI_RH_RUNNING,		/* The normal state */
+ 	UHCI_RH_RUNNING_NODEVS,		/* Running with no devices attached */
+@@ -380,7 +381,6 @@ struct uhci_hcd {
+ 
+ 	unsigned int scan_in_progress:1;	/* Schedule scan is running */
+ 	unsigned int need_rescan:1;		/* Redo the schedule scan */
+-	unsigned int resume_detect:1;		/* Need a Global Resume */
+ 	unsigned int hc_inaccessible:1;		/* HC is suspended or dead */
+ 
+ 	/* Support for port suspend/resume/reset */
+diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
+index 13652de52203..4eace2b19ddb 100644
+--- a/drivers/usb/host/uhci-hub.c
++++ b/drivers/usb/host/uhci-hub.c
+@@ -49,22 +49,16 @@ static int any_ports_active(struct uhci_hcd *uhci)
+ 	return 0;
+ }
+ 
+-static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
++static inline int get_hub_status_data(struct uhci_hcd *uhci, char *buf)
+ {
+-	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 	int port;
+ 
+-	if (uhci->hc_inaccessible)
+-		return 0;
+-
+ 	*buf = 0;
+ 	for (port = 0; port < uhci->rh_numports; ++port) {
+ 		if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & RWC_BITS) ||
+ 				test_bit(port, &uhci->port_c_suspend))
+ 			*buf |= (1 << (port + 1));
+ 	}
+-	if (*buf && uhci->is_stopped)
+-		uhci->resume_detect = 1;
+ 	return !!*buf;
+ }
+ 
+@@ -134,6 +128,11 @@ static void uhci_check_ports(struct uhci_hcd *uhci)
+ 				set_bit(port, &uhci->resuming_ports);
+ 				uhci->ports_timeout = jiffies +
+ 						msecs_to_jiffies(20);
++
++				/* Make sure we see the port again
++				 * after the resuming period is over. */
++				mod_timer(&uhci_to_hcd(uhci)->rh_timer,
++						uhci->ports_timeout);
+ 			} else if (time_after_eq(jiffies,
+ 						uhci->ports_timeout)) {
+ 				uhci_finish_suspend(uhci, port, port_addr);
+@@ -142,6 +141,60 @@ static void uhci_check_ports(struct uhci_hcd *uhci)
+ 	}
+ }
+ 
++static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
++{
++	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++	unsigned long flags;
++	int status;
++
++	spin_lock_irqsave(&uhci->lock, flags);
++	if (uhci->hc_inaccessible) {
++		status = 0;
++		goto done;
++	}
++
++	uhci_check_ports(uhci);
++	status = get_hub_status_data(uhci, buf);
++
++	switch (uhci->rh_state) {
++	    case UHCI_RH_SUSPENDING:
++	    case UHCI_RH_SUSPENDED:
++		/* if port change, ask to be resumed */
++		if (status)
++			usb_hcd_resume_root_hub(hcd);
++		break;
++
++	    case UHCI_RH_AUTO_STOPPED:
++		/* if port change, auto start */
++		if (status)
++			wakeup_rh(uhci);
++		break;
++
++	    case UHCI_RH_RUNNING:
++		/* are any devices attached? */
++		if (!any_ports_active(uhci)) {
++			uhci->rh_state = UHCI_RH_RUNNING_NODEVS;
++			uhci->auto_stop_time = jiffies + HZ;
++		}
++		break;
++
++	    case UHCI_RH_RUNNING_NODEVS:
++		/* auto-stop if nothing connected for 1 second */
++		if (any_ports_active(uhci))
++			uhci->rh_state = UHCI_RH_RUNNING;
++		else if (time_after_eq(jiffies, uhci->auto_stop_time))
++			suspend_rh(uhci, UHCI_RH_AUTO_STOPPED);
++		break;
++
++	    default:
++		break;
++	}
++
++done:
++	spin_unlock_irqrestore(&uhci->lock, flags);
++	return status;
++}
++
+ /* size of returned buffer is part of USB spec */
+ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+ 			u16 wIndex, char *buf, u16 wLength)
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index f5c75885f7be..77f264851e98 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -32,6 +32,8 @@ static void uhci_free_pending_tds(struct uhci_hcd *uhci);
+  */
+ static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci)
+ {
++	if (uhci->is_stopped)
++		mod_timer(&uhci->stall_timer, jiffies);
+ 	uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); 
+ }
+ 
+@@ -1497,6 +1499,7 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs)
+  rescan:
+ 	uhci->need_rescan = 0;
+ 
++	uhci_clear_next_interrupt(uhci);
+ 	uhci_get_current_frame_number(uhci);
+ 
+ 	if (uhci->frame_number + uhci->is_stopped != uhci->qh_remove_age)

commit 4daaa87c8f19c5f1978470e9e91b74d9e0fb0f8e
+Author: Alan Stern 
+Date:   Sat Apr 9 17:30:08 2005 -0400
+
+    [PATCH] USB UHCI: Fix up loose ends
+    
+    This patch tidies up a few loose ends left by the preceding patches.
+    It indicates the controller supports remote wakeup whenever the PM
+    capability is present -- which shouldn't cause any harm if the
+    assumption turns out to be wrong.  It refuses to suspend the
+    controller if the root hub is still active, and it refuses to resume
+    the root hub if the controller is suspended.  It adds checks for a
+    dead controller in several spots, and it adds memory barriers as
+    needed to insure that I/O operations are completed before moving on.
+    
+    Actually I'm not certain the last part is being done correctly.  With
+    code like this:
+    
+            outw(..., ...);
+            mb();
+            udelay(5);
+    
+    do we know for certain that the outw() will complete _before_ the
+    delay begins?  If not, how should this be written?
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 730ba3a621ae..82e608a4bbd0 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -13,18 +13,13 @@
+  * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
+  *               support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
+  * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
+- * (C) Copyright 2004 Alan Stern, stern@rowland.harvard.edu
++ * (C) Copyright 2004-2005 Alan Stern, stern@rowland.harvard.edu
+  *
+  * Intel documents this fairly well, and as far as I know there
+  * are no royalties or anything like that, but even so there are
+  * people who decided that they want to do the same thing in a
+  * completely different way.
+  *
+- * WARNING! The USB documentation is downright evil. Most of it
+- * is just crap, written by a committee. You're better off ignoring
+- * most of it, the important stuff is:
+- *  - the low-level protocol (fairly simple but lots of small details)
+- *  - working around the horridness of the rest
+  */
+ 
+ #include 
+@@ -146,6 +141,15 @@ static void reset_hc(struct uhci_hcd *uhci)
+ 	uhci_to_hcd(uhci)->state = HC_STATE_HALT;
+ }
+ 
++/*
++ * Last rites for a defunct/nonfunctional controller
++ */
++static void hc_died(struct uhci_hcd *uhci)
++{
++	reset_hc(uhci);
++	uhci->hc_inaccessible = 1;
++}
++
+ /*
+  * Initialize a controller that was newly discovered or has just been
+  * resumed.  In either case we can't be sure of its previous state.
+@@ -287,6 +291,8 @@ __acquires(uhci->lock)
+ 		spin_unlock_irq(&uhci->lock);
+ 		msleep(1);
+ 		spin_lock_irq(&uhci->lock);
++		if (uhci->hc_inaccessible)	/* Died */
++			return;
+ 	}
+ 	if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH))
+ 		dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n");
+@@ -335,6 +341,8 @@ __acquires(uhci->lock)
+ 		spin_unlock_irq(&uhci->lock);
+ 		msleep(20);
+ 		spin_lock_irq(&uhci->lock);
++		if (uhci->hc_inaccessible)	/* Died */
++			return;
+ 
+ 		/* End Global Resume and wait for EOP to be sent */
+ 		outw(USBCMD_CF, uhci->io_addr + USBCMD);
+@@ -387,9 +395,11 @@ static void stall_callback(unsigned long _uhci)
+ 	check_fsbr(uhci);
+ 
+ 	/* Poll for and perform state transitions */
+-	rh_state_transitions(uhci);
+-	if (uhci->suspended_ports && !uhci->hc_inaccessible)
+-		uhci_check_ports(uhci);
++	if (!uhci->hc_inaccessible) {
++		rh_state_transitions(uhci);
++		if (uhci->suspended_ports)
++			uhci_check_ports(uhci);
++	}
+ 
+ 	restart_timer(uhci);
+ 	spin_unlock_irqrestore(&uhci->lock, flags);
+@@ -399,6 +409,7 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 	unsigned short status;
++	unsigned long flags;
+ 
+ 	/*
+ 	 * Read the interrupt status, and write it back to clear the
+@@ -417,20 +428,26 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
+ 		if (status & USBSTS_HCPE)
+ 			dev_err(uhci_dev(uhci), "host controller process "
+ 					"error, something bad happened!\n");
+-		if ((status & USBSTS_HCH) &&
+-				uhci->rh_state >= UHCI_RH_RUNNING) {
+-			dev_err(uhci_dev(uhci), "host controller halted, "
++		if (status & USBSTS_HCH) {
++			spin_lock_irqsave(&uhci->lock, flags);
++			if (uhci->rh_state >= UHCI_RH_RUNNING) {
++				dev_err(uhci_dev(uhci),
++					"host controller halted, "
+ 					"very bad!\n");
+-			/* FIXME: Reset the controller, fix the offending TD */
++				hc_died(uhci);
++				spin_unlock_irqrestore(&uhci->lock, flags);
++				return IRQ_HANDLED;
++			}
++			spin_unlock_irqrestore(&uhci->lock, flags);
+ 		}
+ 	}
+ 
+ 	if (status & USBSTS_RD)
+ 		uhci->resume_detect = 1;
+ 
+-	spin_lock(&uhci->lock);
++	spin_lock_irqsave(&uhci->lock, flags);
+ 	uhci_scan_schedule(uhci, regs);
+-	spin_unlock(&uhci->lock);
++	spin_unlock_irqrestore(&uhci->lock, flags);
+ 
+ 	return IRQ_HANDLED;
+ }
+@@ -525,10 +542,15 @@ static int uhci_start(struct usb_hcd *hcd)
+ 	struct dentry *dentry;
+ 
+ 	io_size = (unsigned) hcd->rsrc_len;
++	if (pci_find_capability(to_pci_dev(uhci_dev(uhci)), PCI_CAP_ID_PM))
++		hcd->can_wakeup = 1;		/* Assume it supports PME# */
+ 
+-	dentry = debugfs_create_file(hcd->self.bus_name, S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, uhci, &uhci_debug_operations);
++	dentry = debugfs_create_file(hcd->self.bus_name,
++			S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, uhci,
++			&uhci_debug_operations);
+ 	if (!dentry) {
+-		dev_err(uhci_dev(uhci), "couldn't create uhci debugfs entry\n");
++		dev_err(uhci_dev(uhci),
++				"couldn't create uhci debugfs entry\n");
+ 		retval = -ENOMEM;
+ 		goto err_create_debug_entry;
+ 	}
+@@ -765,7 +787,8 @@ static int uhci_rh_suspend(struct usb_hcd *hcd)
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 
+ 	spin_lock_irq(&uhci->lock);
+-	suspend_rh(uhci, UHCI_RH_SUSPENDED);
++	if (!uhci->hc_inaccessible)		/* Not dead */
++		suspend_rh(uhci, UHCI_RH_SUSPENDED);
+ 	spin_unlock_irq(&uhci->lock);
+ 	return 0;
+ }
+@@ -773,26 +796,44 @@ static int uhci_rh_suspend(struct usb_hcd *hcd)
+ static int uhci_rh_resume(struct usb_hcd *hcd)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++	int rc = 0;
+ 
+ 	spin_lock_irq(&uhci->lock);
+-	wakeup_rh(uhci);
++	if (uhci->hc_inaccessible) {
++		if (uhci->rh_state == UHCI_RH_SUSPENDED) {
++			dev_warn(uhci_dev(uhci), "HC isn't running!\n");
++			rc = -ENODEV;
++		}
++		/* Otherwise the HC is dead */
++	} else
++		wakeup_rh(uhci);
+ 	spin_unlock_irq(&uhci->lock);
+-	return 0;
++	return rc;
+ }
+ 
+ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++	int rc = 0;
+ 
+ 	dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
+ 
+ 	spin_lock_irq(&uhci->lock);
++	if (uhci->hc_inaccessible)	/* Dead or already suspended */
++		goto done;
+ 
+ #ifndef CONFIG_USB_SUSPEND
+ 	/* Otherwise this would never happen */
+ 	suspend_rh(uhci, UHCI_RH_SUSPENDED);
+ #endif
+ 
++	if (uhci->rh_state > UHCI_RH_SUSPENDED) {
++		dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n");
++		hcd->state = HC_STATE_RUNNING;
++		rc = -EBUSY;
++		goto done;
++	};
++
+ 	/* All PCI host controllers are required to disable IRQ generation
+ 	 * at the source, so we must turn off PIRQ.
+ 	 */
+@@ -801,8 +842,9 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
+ 
+ 	/* FIXME: Enable non-PME# remote wakeup? */
+ 
++done:
+ 	spin_unlock_irq(&uhci->lock);
+-	return 0;
++	return rc;
+ }
+ 
+ static int uhci_resume(struct usb_hcd *hcd)
+@@ -811,6 +853,8 @@ static int uhci_resume(struct usb_hcd *hcd)
+ 
+ 	dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
+ 
++	if (uhci->rh_state == UHCI_RH_RESET)	/* Dead */
++		return 0;
+ 	spin_lock_irq(&uhci->lock);
+ 
+ 	/* FIXME: Disable non-PME# remote wakeup? */

commit a8bed8b6be75bc5a46aa599ab360d5f1db291c8f
+Author: Alan Stern 
+Date:   Sat Apr 9 17:29:00 2005 -0400
+
+    [PATCH] USB UHCI: Add root-hub suspend/resume support
+    
+    This patch implements (finally!) separate suspend and resume routines
+    for the root hub and the controller in the UHCI driver.  It also
+    changes the sequence used to reset the controller during initial
+    probing, so as to preserve the existing state during a Resume-From-Disk.
+    (This new sequence is what should be used in the PCI Quirks code for
+    early USB handoffs, incidentally.)  Lastly it adds a notion of the
+    controller being "inaccessible" while in a PCI low-power state, when
+    normal I/O operations shouldn't be allowed.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 57b36dcea5d0..730ba3a621ae 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -109,28 +109,113 @@ static inline void restart_timer(struct uhci_hcd *uhci)
+ #include "uhci-debug.c"
+ #include "uhci-q.c"
+ 
++/*
++ * Make sure the controller is completely inactive, unable to
++ * generate interrupts or do DMA.
++ */
+ static void reset_hc(struct uhci_hcd *uhci)
+ {
+-	unsigned long io_addr = uhci->io_addr;
++	/* Turn off PIRQ enable and SMI enable.  (This also turns off the
++	 * BIOS's USB Legacy Support.)  Turn off all the R/WC bits too.
++	 */
++	pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
++			USBLEGSUP_RWC);
+ 
+-	/* Turn off PIRQ, SMI, and all interrupts.  This also turns off
+-	 * the BIOS's USB Legacy Support.
++	/* Reset the HC - this will force us to get a
++	 * new notification of any already connected
++	 * ports due to the virtual disconnect that it
++	 * implies.
+ 	 */
+-	pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0);
+-	outw(0, uhci->io_addr + USBINTR);
++	outw(USBCMD_HCRESET, uhci->io_addr + USBCMD);
++	mb();
++	udelay(5);
++	if (inw(uhci->io_addr + USBCMD) & USBCMD_HCRESET)
++		dev_warn(uhci_dev(uhci), "HCRESET not completed yet!\n");
+ 
+-	/* Global reset for 50ms */
+-	outw(USBCMD_GRESET, io_addr + USBCMD);
+-	msleep(50);
+-	outw(0, io_addr + USBCMD);
++	/* Just to be safe, disable interrupt requests and
++	 * make sure the controller is stopped.
++	 */
++	outw(0, uhci->io_addr + USBINTR);
++	outw(0, uhci->io_addr + USBCMD);
+ 
+-	/* Another 10ms delay */
+-	msleep(10);
+ 	uhci->resume_detect = 0;
+-	uhci->is_stopped = UHCI_IS_STOPPED;
++	uhci->port_c_suspend = uhci->suspended_ports =
++			uhci->resuming_ports = 0;
+ 	uhci->rh_state = UHCI_RH_RESET;
++	uhci->is_stopped = UHCI_IS_STOPPED;
++	uhci_to_hcd(uhci)->state = HC_STATE_HALT;
+ }
+ 
++/*
++ * Initialize a controller that was newly discovered or has just been
++ * resumed.  In either case we can't be sure of its previous state.
++ */
++static void check_and_reset_hc(struct uhci_hcd *uhci)
++{
++	u16 legsup;
++	unsigned int cmd, intr;
++
++	/*
++	 * When restarting a suspended controller, we expect all the
++	 * settings to be the same as we left them:
++	 *
++	 *	PIRQ and SMI disabled, no R/WC bits set in USBLEGSUP;
++	 *	Controller is stopped and configured with EGSM set;
++	 *	No interrupts enabled except possibly Resume Detect.
++	 *
++	 * If any of these conditions are violated we do a complete reset.
++	 */
++	pci_read_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, &legsup);
++	if (legsup & ~USBLEGSUP_RO) {
++		dev_dbg(uhci_dev(uhci), "%s: legsup = 0x%04x\n",
++				__FUNCTION__, legsup);
++		goto reset_needed;
++	}
++
++	cmd = inw(uhci->io_addr + USBCMD);
++	if ((cmd & USBCMD_RS) || !(cmd & USBCMD_CF) || !(cmd & USBCMD_EGSM)) {
++		dev_dbg(uhci_dev(uhci), "%s: cmd = 0x%04x\n",
++				__FUNCTION__, cmd);
++		goto reset_needed;
++	}
++
++	intr = inw(uhci->io_addr + USBINTR);
++	if (intr & (~USBINTR_RESUME)) {
++		dev_dbg(uhci_dev(uhci), "%s: intr = 0x%04x\n",
++				__FUNCTION__, intr);
++		goto reset_needed;
++	}
++	return;
++
++reset_needed:
++	dev_dbg(uhci_dev(uhci), "Performing full reset\n");
++	reset_hc(uhci);
++}
++
++/*
++ * Store the basic register settings needed by the controller.
++ */
++static void configure_hc(struct uhci_hcd *uhci)
++{
++	/* Set the frame length to the default: 1 ms exactly */
++	outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF);
++
++	/* Store the frame list base address */
++	outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD);
++
++	/* Set the current frame number */
++	outw(uhci->frame_number, uhci->io_addr + USBFRNUM);
++
++	/* Mark controller as running before we enable interrupts */
++	uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;
++	mb();
++
++	/* Enable PIRQ */
++	pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
++			USBLEGSUP_DEFAULT);
++}
++
++
+ static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
+ {
+ 	int port;
+@@ -163,7 +248,7 @@ static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
+ 	return 0;
+ }
+ 
+-static void suspend_hc(struct uhci_hcd *uhci, enum uhci_rh_state new_state)
++static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state)
+ __releases(uhci->lock)
+ __acquires(uhci->lock)
+ {
+@@ -189,6 +274,7 @@ __acquires(uhci->lock)
+ 			0 : USBINTR_RESUME);
+ 	outw(int_enable, uhci->io_addr + USBINTR);
+ 	outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD);
++	mb();
+ 	udelay(5);
+ 
+ 	/* If we're auto-stopping then no devices have been attached
+@@ -215,7 +301,22 @@ __acquires(uhci->lock)
+ 	uhci_scan_schedule(uhci, NULL);
+ }
+ 
+-static void wakeup_hc(struct uhci_hcd *uhci)
++static void start_rh(struct uhci_hcd *uhci)
++{
++	uhci->rh_state = UHCI_RH_RUNNING;
++	uhci->is_stopped = 0;
++	smp_wmb();
++
++	/* Mark it configured and running with a 64-byte max packet.
++	 * All interrupts are enabled, even though RESUME won't do anything.
++	 */
++	outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, uhci->io_addr + USBCMD);
++	outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP,
++			uhci->io_addr + USBINTR);
++	mb();
++}
++
++static void wakeup_rh(struct uhci_hcd *uhci)
+ __releases(uhci->lock)
+ __acquires(uhci->lock)
+ {
+@@ -237,62 +338,13 @@ __acquires(uhci->lock)
+ 
+ 		/* End Global Resume and wait for EOP to be sent */
+ 		outw(USBCMD_CF, uhci->io_addr + USBCMD);
++		mb();
+ 		udelay(4);
+ 		if (inw(uhci->io_addr + USBCMD) & USBCMD_FGR)
+ 			dev_warn(uhci_dev(uhci), "FGR not stopped yet!\n");
+ 	}
+ 
+-	uhci->rh_state = UHCI_RH_RUNNING;
+-	uhci->is_stopped = 0;
+-	smp_wmb();
+-
+-	/* Mark it configured and running with a 64-byte max packet.
+-	 * All interrupts are enabled, even though RD won't do anything.
+-	 */
+-	outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, uhci->io_addr + USBCMD);
+-	outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP,
+-			uhci->io_addr + USBINTR);
+-}
+-
+-static int start_hc(struct uhci_hcd *uhci)
+-{
+-	unsigned long io_addr = uhci->io_addr;
+-	int timeout = 10;
+-
+-	/*
+-	 * Reset the HC - this will force us to get a
+-	 * new notification of any already connected
+-	 * ports due to the virtual disconnect that it
+-	 * implies.
+-	 */
+-	outw(USBCMD_HCRESET, io_addr + USBCMD);
+-	while (inw(io_addr + USBCMD) & USBCMD_HCRESET) {
+-		if (--timeout < 0) {
+-			dev_err(uhci_dev(uhci), "USBCMD_HCRESET timed out!\n");
+-			return -ETIMEDOUT;
+-		}
+-		msleep(1);
+-	}
+-
+-	/* Mark controller as running before we enable interrupts */
+-	uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;
+-
+-	/* Turn on PIRQ and all interrupts */
+-	pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
+-			USBLEGSUP_DEFAULT);
+-	outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP,
+-		io_addr + USBINTR);
+-
+-	/* Start at frame 0 */
+-	outw(0, io_addr + USBFRNUM);
+-	outl(uhci->fl->dma_handle, io_addr + USBFLBASEADD);
+-
+-	/* Run and mark it configured with a 64-byte max packet */
+-	uhci->rh_state = UHCI_RH_RUNNING;
+-	outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD);
+-	uhci->is_stopped = 0;
+-
+-	return 0;
++	start_rh(uhci);
+ }
+ 
+ static void rh_state_transitions(struct uhci_hcd *uhci)
+@@ -311,13 +363,13 @@ static void rh_state_transitions(struct uhci_hcd *uhci)
+ 		if (any_ports_active(uhci))
+ 			uhci->rh_state = UHCI_RH_RUNNING;
+ 		else if (time_after_eq(jiffies, uhci->auto_stop_time))
+-			suspend_hc(uhci, UHCI_RH_AUTO_STOPPED);
++			suspend_rh(uhci, UHCI_RH_AUTO_STOPPED);
+ 		break;
+ 
+ 	    case UHCI_RH_AUTO_STOPPED:
+ 		/* wakeup if requested by a device */
+ 		if (uhci->resume_detect)
+-			wakeup_hc(uhci);
++			wakeup_rh(uhci);
+ 		break;
+ 
+ 	    default:
+@@ -336,7 +388,7 @@ static void stall_callback(unsigned long _uhci)
+ 
+ 	/* Poll for and perform state transitions */
+ 	rh_state_transitions(uhci);
+-	if (unlikely(uhci->suspended_ports))
++	if (uhci->suspended_ports && !uhci->hc_inaccessible)
+ 		uhci_check_ports(uhci);
+ 
+ 	restart_timer(uhci);
+@@ -346,7 +398,6 @@ static void stall_callback(unsigned long _uhci)
+ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+-	unsigned long io_addr = uhci->io_addr;
+ 	unsigned short status;
+ 
+ 	/*
+@@ -354,10 +405,10 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
+ 	 * interrupt cause.  Contrary to the UHCI specification, the
+ 	 * "HC Halted" status bit is persistent: it is RO, not R/WC.
+ 	 */
+-	status = inw(io_addr + USBSTS);
++	status = inw(uhci->io_addr + USBSTS);
+ 	if (!(status & ~USBSTS_HCH))	/* shared interrupt, not mine */
+ 		return IRQ_NONE;
+-	outw(status, io_addr + USBSTS);		/* Clear it */
++	outw(status, uhci->io_addr + USBSTS);		/* Clear it */
+ 
+ 	if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) {
+ 		if (status & USBSTS_HSE)
+@@ -440,10 +491,10 @@ static int uhci_reset(struct usb_hcd *hcd)
+ 
+ 	uhci->io_addr = (unsigned long) hcd->rsrc_start;
+ 
+-	/* Kick BIOS off this hardware and reset, so we won't get
+-	 * interrupts from any previous setup.
++	/* Kick BIOS off this hardware and reset if the controller
++	 * isn't already safely quiescent.
+ 	 */
+-	reset_hc(uhci);
++	check_and_reset_hc(uhci);
+ 	return 0;
+ }
+ 
+@@ -634,11 +685,12 @@ static int uhci_start(struct usb_hcd *hcd)
+ 
+ 	/*
+ 	 * Some architectures require a full mb() to enforce completion of
+-	 * the memory writes above before the I/O transfers in start_hc().
++	 * the memory writes above before the I/O transfers in configure_hc().
+ 	 */
+ 	mb();
+-	if ((retval = start_hc(uhci)) != 0)
+-		goto err_alloc_skelqh;
++
++	configure_hc(uhci);
++	start_rh(uhci);
+ 
+ 	restart_timer(uhci);
+ 
+@@ -656,9 +708,8 @@ static int uhci_start(struct usb_hcd *hcd)
+  * error exits:
+  */
+ err_start_root_hub:
+-	reset_hc(uhci);
+-
+ 	del_timer_sync(&uhci->stall_timer);
++	reset_hc(uhci);
+ 
+ err_alloc_skelqh:
+ 	for (i = 0; i < UHCI_NUM_SKELQH; i++)
+@@ -699,9 +750,9 @@ static void uhci_stop(struct usb_hcd *hcd)
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 
+ 	del_timer_sync(&uhci->stall_timer);
+-	reset_hc(uhci);
+ 
+ 	spin_lock_irq(&uhci->lock);
++	reset_hc(uhci);
+ 	uhci_scan_schedule(uhci, NULL);
+ 	spin_unlock_irq(&uhci->lock);
+ 	
+@@ -709,12 +760,47 @@ static void uhci_stop(struct usb_hcd *hcd)
+ }
+ 
+ #ifdef CONFIG_PM
++static int uhci_rh_suspend(struct usb_hcd *hcd)
++{
++	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++
++	spin_lock_irq(&uhci->lock);
++	suspend_rh(uhci, UHCI_RH_SUSPENDED);
++	spin_unlock_irq(&uhci->lock);
++	return 0;
++}
++
++static int uhci_rh_resume(struct usb_hcd *hcd)
++{
++	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++
++	spin_lock_irq(&uhci->lock);
++	wakeup_rh(uhci);
++	spin_unlock_irq(&uhci->lock);
++	return 0;
++}
++
+ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 
++	dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
++
+ 	spin_lock_irq(&uhci->lock);
+-	suspend_hc(uhci, UHCI_RH_SUSPENDED);
++
++#ifndef CONFIG_USB_SUSPEND
++	/* Otherwise this would never happen */
++	suspend_rh(uhci, UHCI_RH_SUSPENDED);
++#endif
++
++	/* All PCI host controllers are required to disable IRQ generation
++	 * at the source, so we must turn off PIRQ.
++	 */
++	pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0);
++	uhci->hc_inaccessible = 1;
++
++	/* FIXME: Enable non-PME# remote wakeup? */
++
+ 	spin_unlock_irq(&uhci->lock);
+ 	return 0;
+ }
+@@ -723,28 +809,28 @@ static int uhci_resume(struct usb_hcd *hcd)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 
++	dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
++
+ 	spin_lock_irq(&uhci->lock);
+-	if (uhci->rh_state == UHCI_RH_SUSPENDED) {
+ 
+-		/*
+-		 * Some systems don't maintain the UHCI register values
+-		 * during a PM suspend/resume cycle, so reinitialize
+-		 * the Frame Number, Framelist Base Address, Interrupt
+-		 * Enable, and Legacy Support registers.
+-		 */
+-		pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
+-				0);
+-		outw(uhci->frame_number, uhci->io_addr + USBFRNUM);
+-		outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD);
+-		outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC |
+-				USBINTR_SP, uhci->io_addr + USBINTR);
+-		pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
+-				USBLEGSUP_DEFAULT);
+-		wakeup_hc(uhci);
+-	}
+-	spin_unlock_irq(&uhci->lock);
++	/* FIXME: Disable non-PME# remote wakeup? */
++
++	uhci->hc_inaccessible = 0;
++
++	/* The BIOS may have changed the controller settings during a
++	 * system wakeup.  Check it and reconfigure to avoid problems.
++	 */
++	check_and_reset_hc(uhci);
++	configure_hc(uhci);
++
++#ifndef CONFIG_USB_SUSPEND
++	/* Otherwise this would never happen */
++	wakeup_rh(uhci);
++#endif
++	if (uhci->rh_state == UHCI_RH_RESET)
++		suspend_rh(uhci, UHCI_RH_SUSPENDED);
+ 
+-	hcd->state = HC_STATE_RUNNING;
++	spin_unlock_irq(&uhci->lock);
+ 	return 0;
+ }
+ #endif
+@@ -792,6 +878,8 @@ static const struct hc_driver uhci_driver = {
+ #ifdef CONFIG_PM
+ 	.suspend =		uhci_suspend,
+ 	.resume =		uhci_resume,
++	.hub_suspend =		uhci_rh_suspend,
++	.hub_resume =		uhci_rh_resume,
+ #endif
+ 	.stop =			uhci_stop,
+ 
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index 4bac57c74ec2..827df5e06800 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -41,6 +41,7 @@
+ #define USBFRNUM	6
+ #define USBFLBASEADD	8
+ #define USBSOF		12
++#define   USBSOF_DEFAULT	64	/* Frame length is exactly 1 ms */
+ 
+ /* USB port status and control registers */
+ #define USBPORTSC1	16
+@@ -66,6 +67,8 @@
+ /* Legacy support register */
+ #define USBLEGSUP		0xc0
+ #define   USBLEGSUP_DEFAULT	0x2000	/* only PIRQ enable set */
++#define   USBLEGSUP_RWC		0x8f00	/* the R/WC bits */
++#define   USBLEGSUP_RO		0x5040	/* R/O and reserved bits */
+ 
+ #define UHCI_NULL_DATA_SIZE	0x7FF	/* for UHCI controller TD */
+ 
+@@ -325,8 +328,9 @@ static inline int __interval_to_skel(int interval)
+  */
+ enum uhci_rh_state {
+ 	/* In the next 4 states the HC must be halted */
+-	UHCI_RH_RESET,
++	UHCI_RH_RESET,			/* These two must come first */
+ 	UHCI_RH_SUSPENDED,
++
+ 	UHCI_RH_AUTO_STOPPED,
+ 	UHCI_RH_RESUMING,
+ 
+@@ -334,7 +338,8 @@ enum uhci_rh_state {
+ 	 * can legally appear either way */
+ 	UHCI_RH_SUSPENDING,
+ 
+-	/* In the next two states it's an error if the HC is halted */
++	/* In the next two states it's an error if the HC is halted.
++	 * These two must come last */
+ 	UHCI_RH_RUNNING,		/* The normal state */
+ 	UHCI_RH_RUNNING_NODEVS,		/* Running with no devices attached */
+ };
+@@ -376,6 +381,7 @@ struct uhci_hcd {
+ 	unsigned int scan_in_progress:1;	/* Schedule scan is running */
+ 	unsigned int need_rescan:1;		/* Redo the schedule scan */
+ 	unsigned int resume_detect:1;		/* Need a Global Resume */
++	unsigned int hc_inaccessible:1;		/* HC is suspended or dead */
+ 
+ 	/* Support for port suspend/resume/reset */
+ 	unsigned long port_c_suspend;		/* Bit-arrays of ports */
+diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
+index fc34fee2ab07..13652de52203 100644
+--- a/drivers/usb/host/uhci-hub.c
++++ b/drivers/usb/host/uhci-hub.c
+@@ -54,6 +54,9 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 	int port;
+ 
++	if (uhci->hc_inaccessible)
++		return 0;
++
+ 	*buf = 0;
+ 	for (port = 0; port < uhci->rh_numports; ++port) {
+ 		if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & RWC_BITS) ||
+@@ -150,6 +153,9 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+ 	u16 wPortChange, wPortStatus;
+ 	unsigned long flags;
+ 
++	if (uhci->hc_inaccessible)
++		return -ETIMEDOUT;
++
+ 	spin_lock_irqsave(&uhci->lock, flags);
+ 	switch (typeReq) {
+ 

commit c8f4fe4358c5e0a79b4bd47b814d19f1d1d06f21
+Author: Alan Stern 
+Date:   Sat Apr 9 17:27:32 2005 -0400
+
+    [PATCH] USB UHCI: Add root hub states
+    
+    This patch starts making some serious changes to the UHCI driver.
+    There's a set of private states for the root hub, and the internal
+    routines for suspending and resuming work completely differently, with
+    transitions based on the new states.  Now the driver distinguishes
+    between a privately auto-stopped state and a publicly suspended state,
+    and it will properly suspend controllers with broken resume-detect
+    interrupts instead of resetting them.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
+index 24c73c5a3435..4538a98b6f9d 100644
+--- a/drivers/usb/host/uhci-debug.c
++++ b/drivers/usb/host/uhci-debug.c
+@@ -237,6 +237,37 @@ static int uhci_show_sc(int port, unsigned short status, char *buf, int len)
+ 	return out - buf;
+ }
+ 
++static int uhci_show_root_hub_state(struct uhci_hcd *uhci, char *buf, int len)
++{
++	char *out = buf;
++	char *rh_state;
++
++	/* Try to make sure there's enough memory */
++	if (len < 60)
++		return 0;
++
++	switch (uhci->rh_state) {
++	    case UHCI_RH_RESET:
++		rh_state = "reset";		break;
++	    case UHCI_RH_SUSPENDED:
++		rh_state = "suspended";		break;
++	    case UHCI_RH_AUTO_STOPPED:
++		rh_state = "auto-stopped";	break;
++	    case UHCI_RH_RESUMING:
++		rh_state = "resuming";		break;
++	    case UHCI_RH_SUSPENDING:
++		rh_state = "suspending";	break;
++	    case UHCI_RH_RUNNING:
++		rh_state = "running";		break;
++	    case UHCI_RH_RUNNING_NODEVS:
++		rh_state = "running, no devs";	break;
++	    default:
++		rh_state = "?";			break;
++	}
++	out += sprintf(out, "Root-hub state: %s\n", rh_state);
++	return out - buf;
++}
++
+ static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len)
+ {
+ 	char *out = buf;
+@@ -408,6 +439,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
+ 
+ 	spin_lock_irqsave(&uhci->lock, flags);
+ 
++	out += uhci_show_root_hub_state(uhci, out, len - (out - buf));
+ 	out += sprintf(out, "HC status\n");
+ 	out += uhci_show_status(uhci, out, len - (out - buf));
+ 
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index c17bd7ebc021..57b36dcea5d0 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -64,7 +64,7 @@
+ /*
+  * Version Information
+  */
+-#define DRIVER_VERSION "v2.2"
++#define DRIVER_VERSION "v2.3"
+ #define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, \
+ Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \
+ Alan Stern"
+@@ -109,33 +109,6 @@ static inline void restart_timer(struct uhci_hcd *uhci)
+ #include "uhci-debug.c"
+ #include "uhci-q.c"
+ 
+-static int suspend_allowed(struct uhci_hcd *uhci)
+-{
+-	unsigned long io_addr = uhci->io_addr;
+-	int i;
+-
+-	if (to_pci_dev(uhci_dev(uhci))->vendor != PCI_VENDOR_ID_INTEL)
+-		return 1;
+-
+-	/* Some of Intel's USB controllers have a bug that causes false
+-	 * resume indications if any port has an over current condition.
+-	 * To prevent problems, we will not allow a global suspend if
+-	 * any ports are OC.
+-	 *
+-	 * Some motherboards using Intel's chipsets (but not using all
+-	 * the USB ports) appear to hardwire the over current inputs active
+-	 * to disable the USB ports.
+-	 */
+-
+-	/* check for over current condition on any port */
+-	for (i = 0; i < uhci->rh_numports; i++) {
+-		if (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_OC)
+-			return 0;
+-	}
+-
+-	return 1;
+-}
+-
+ static void reset_hc(struct uhci_hcd *uhci)
+ {
+ 	unsigned long io_addr = uhci->io_addr;
+@@ -147,7 +120,6 @@ static void reset_hc(struct uhci_hcd *uhci)
+ 	outw(0, uhci->io_addr + USBINTR);
+ 
+ 	/* Global reset for 50ms */
+-	uhci->state = UHCI_RESET;
+ 	outw(USBCMD_GRESET, io_addr + USBCMD);
+ 	msleep(50);
+ 	outw(0, io_addr + USBCMD);
+@@ -156,63 +128,130 @@ static void reset_hc(struct uhci_hcd *uhci)
+ 	msleep(10);
+ 	uhci->resume_detect = 0;
+ 	uhci->is_stopped = UHCI_IS_STOPPED;
++	uhci->rh_state = UHCI_RH_RESET;
+ }
+ 
+-static void suspend_hc(struct uhci_hcd *uhci)
++static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
+ {
+-	unsigned long io_addr = uhci->io_addr;
++	int port;
+ 
+-	dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
+-	uhci->state = UHCI_SUSPENDED;
+-	uhci->resume_detect = 0;
+-	outw(USBCMD_EGSM, io_addr + USBCMD);
++	switch (to_pci_dev(uhci_dev(uhci))->vendor) {
++	    default:
++		break;
++
++	    case PCI_VENDOR_ID_GENESYS:
++		/* Genesys Logic's GL880S controllers don't generate
++		 * resume-detect interrupts.
++		 */
++		return 1;
++
++	    case PCI_VENDOR_ID_INTEL:
++		/* Some of Intel's USB controllers have a bug that causes
++		 * resume-detect interrupts if any port has an over-current
++		 * condition.  To make matters worse, some motherboards
++		 * hardwire unused USB ports' over-current inputs active!
++		 * To prevent problems, we will not enable resume-detect
++		 * interrupts if any ports are OC.
++		 */
++		for (port = 0; port < uhci->rh_numports; ++port) {
++			if (inw(uhci->io_addr + USBPORTSC1 + port * 2) &
++					USBPORTSC_OC)
++				return 1;
++		}
++		break;
++	}
++	return 0;
++}
++
++static void suspend_hc(struct uhci_hcd *uhci, enum uhci_rh_state new_state)
++__releases(uhci->lock)
++__acquires(uhci->lock)
++{
++	int auto_stop;
++	int int_enable;
++
++	auto_stop = (new_state == UHCI_RH_AUTO_STOPPED);
++	dev_dbg(uhci_dev(uhci), "%s%s\n", __FUNCTION__,
++			(auto_stop ? " (auto-stop)" : ""));
++
++	/* If we get a suspend request when we're already auto-stopped
++	 * then there's nothing to do.
++	 */
++	if (uhci->rh_state == UHCI_RH_AUTO_STOPPED) {
++		uhci->rh_state = new_state;
++		return;
++	}
++
++	/* Enable resume-detect interrupts if they work.
++	 * Then enter Global Suspend mode, still configured.
++	 */
++	int_enable = (resume_detect_interrupts_are_broken(uhci) ?
++			0 : USBINTR_RESUME);
++	outw(int_enable, uhci->io_addr + USBINTR);
++	outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD);
++	udelay(5);
++
++	/* If we're auto-stopping then no devices have been attached
++	 * for a while, so there shouldn't be any active URBs and the
++	 * controller should stop after a few microseconds.  Otherwise
++	 * we will give the controller one frame to stop.
++	 */
++	if (!auto_stop && !(inw(uhci->io_addr + USBSTS) & USBSTS_HCH)) {
++		uhci->rh_state = UHCI_RH_SUSPENDING;
++		spin_unlock_irq(&uhci->lock);
++		msleep(1);
++		spin_lock_irq(&uhci->lock);
++	}
++	if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH))
++		dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n");
+ 
+-	/* FIXME: Wait for the controller to actually stop */
+ 	uhci_get_current_frame_number(uhci);
++	smp_wmb();
++
++	uhci->rh_state = new_state;
+ 	uhci->is_stopped = UHCI_IS_STOPPED;
++	uhci->resume_detect = 0;
+ 
+ 	uhci_scan_schedule(uhci, NULL);
+ }
+ 
+ static void wakeup_hc(struct uhci_hcd *uhci)
++__releases(uhci->lock)
++__acquires(uhci->lock)
+ {
+-	unsigned long io_addr = uhci->io_addr;
++	dev_dbg(uhci_dev(uhci), "%s%s\n", __FUNCTION__,
++			uhci->rh_state == UHCI_RH_AUTO_STOPPED ?
++				" (auto-start)" : "");
+ 
+-	switch (uhci->state) {
+-		case UHCI_SUSPENDED:		/* Start the resume */
+-			dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
+-
+-			/* Global resume for >= 20ms */
+-			outw(USBCMD_FGR | USBCMD_EGSM, io_addr + USBCMD);
+-			uhci->state = UHCI_RESUMING_1;
+-			uhci->state_end = jiffies + msecs_to_jiffies(20);
+-			uhci->is_stopped = 0;
+-			break;
++	/* If we are auto-stopped then no devices are attached so there's
++	 * no need for wakeup signals.  Otherwise we send Global Resume
++	 * for 20 ms.
++	 */
++	if (uhci->rh_state == UHCI_RH_SUSPENDED) {
++		uhci->rh_state = UHCI_RH_RESUMING;
++		outw(USBCMD_FGR | USBCMD_EGSM | USBCMD_CF,
++				uhci->io_addr + USBCMD);
++		spin_unlock_irq(&uhci->lock);
++		msleep(20);
++		spin_lock_irq(&uhci->lock);
+ 
+-		case UHCI_RESUMING_1:		/* End global resume */
+-			uhci->state = UHCI_RESUMING_2;
+-			outw(0, io_addr + USBCMD);
+-			/* Falls through */
+-
+-		case UHCI_RESUMING_2:		/* Wait for EOP to be sent */
+-			if (inw(io_addr + USBCMD) & USBCMD_FGR)
+-				break;
+-
+-			/* Run for at least 1 second, and
+-			 * mark it configured with a 64-byte max packet */
+-			uhci->state = UHCI_RUNNING_GRACE;
+-			uhci->state_end = jiffies + HZ;
+-			outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP,
+-					io_addr + USBCMD);
+-			break;
++		/* End Global Resume and wait for EOP to be sent */
++		outw(USBCMD_CF, uhci->io_addr + USBCMD);
++		udelay(4);
++		if (inw(uhci->io_addr + USBCMD) & USBCMD_FGR)
++			dev_warn(uhci_dev(uhci), "FGR not stopped yet!\n");
++	}
+ 
+-		case UHCI_RUNNING_GRACE:	/* Now allowed to suspend */
+-			uhci->state = UHCI_RUNNING;
+-			break;
++	uhci->rh_state = UHCI_RH_RUNNING;
++	uhci->is_stopped = 0;
++	smp_wmb();
+ 
+-		default:
+-			break;
+-	}
++	/* Mark it configured and running with a 64-byte max packet.
++	 * All interrupts are enabled, even though RD won't do anything.
++	 */
++	outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, uhci->io_addr + USBCMD);
++	outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP,
++			uhci->io_addr + USBINTR);
+ }
+ 
+ static int start_hc(struct uhci_hcd *uhci)
+@@ -249,49 +288,40 @@ static int start_hc(struct uhci_hcd *uhci)
+ 	outl(uhci->fl->dma_handle, io_addr + USBFLBASEADD);
+ 
+ 	/* Run and mark it configured with a 64-byte max packet */
+-	uhci->state = UHCI_RUNNING_GRACE;
+-	uhci->state_end = jiffies + HZ;
++	uhci->rh_state = UHCI_RH_RUNNING;
+ 	outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD);
+ 	uhci->is_stopped = 0;
+ 
+ 	return 0;
+ }
+ 
+-static void hc_state_transitions(struct uhci_hcd *uhci)
++static void rh_state_transitions(struct uhci_hcd *uhci)
+ {
+-	switch (uhci->state) {
+-		case UHCI_RUNNING:
+-
+-			/* global suspend if nothing connected for 1 second */
+-			if (!any_ports_active(uhci) && suspend_allowed(uhci)) {
+-				uhci->state = UHCI_SUSPENDING_GRACE;
+-				uhci->state_end = jiffies + HZ;
+-			}
+-			break;
+-
+-		case UHCI_SUSPENDING_GRACE:
+-			if (any_ports_active(uhci))
+-				uhci->state = UHCI_RUNNING;
+-			else if (time_after_eq(jiffies, uhci->state_end))
+-				suspend_hc(uhci);
+-			break;
+-
+-		case UHCI_SUSPENDED:
+-
+-			/* wakeup if requested by a device */
+-			if (uhci->resume_detect)
+-				wakeup_hc(uhci);
+-			break;
+-
+-		case UHCI_RESUMING_1:
+-		case UHCI_RESUMING_2:
+-		case UHCI_RUNNING_GRACE:
+-			if (time_after_eq(jiffies, uhci->state_end))
+-				wakeup_hc(uhci);
+-			break;
+-
+-		default:
+-			break;
++	switch (uhci->rh_state) {
++	    case UHCI_RH_RUNNING:
++		/* are any devices attached? */
++		if (!any_ports_active(uhci)) {
++			uhci->rh_state = UHCI_RH_RUNNING_NODEVS;
++			uhci->auto_stop_time = jiffies + HZ;
++		}
++		break;
++
++	    case UHCI_RH_RUNNING_NODEVS:
++		/* auto-stop if nothing connected for 1 second */
++		if (any_ports_active(uhci))
++			uhci->rh_state = UHCI_RH_RUNNING;
++		else if (time_after_eq(jiffies, uhci->auto_stop_time))
++			suspend_hc(uhci, UHCI_RH_AUTO_STOPPED);
++		break;
++
++	    case UHCI_RH_AUTO_STOPPED:
++		/* wakeup if requested by a device */
++		if (uhci->resume_detect)
++			wakeup_hc(uhci);
++		break;
++
++	    default:
++		break;
+ 	}
+ }
+ 
+@@ -305,8 +335,8 @@ static void stall_callback(unsigned long _uhci)
+ 	check_fsbr(uhci);
+ 
+ 	/* Poll for and perform state transitions */
+-	hc_state_transitions(uhci);
+-	if (unlikely(uhci->suspended_ports && uhci->state != UHCI_SUSPENDED))
++	rh_state_transitions(uhci);
++	if (unlikely(uhci->suspended_ports))
+ 		uhci_check_ports(uhci);
+ 
+ 	restart_timer(uhci);
+@@ -336,7 +366,8 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
+ 		if (status & USBSTS_HCPE)
+ 			dev_err(uhci_dev(uhci), "host controller process "
+ 					"error, something bad happened!\n");
+-		if ((status & USBSTS_HCH) && uhci->state > 0) {
++		if ((status & USBSTS_HCH) &&
++				uhci->rh_state >= UHCI_RH_RUNNING) {
+ 			dev_err(uhci_dev(uhci), "host controller halted, "
+ 					"very bad!\n");
+ 			/* FIXME: Reset the controller, fix the offending TD */
+@@ -683,17 +714,7 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 
+ 	spin_lock_irq(&uhci->lock);
+-
+-	/* Don't try to suspend broken motherboards, reset instead */
+-	if (suspend_allowed(uhci))
+-		suspend_hc(uhci);
+-	else {
+-		spin_unlock_irq(&uhci->lock);
+-		reset_hc(uhci);
+-		spin_lock_irq(&uhci->lock);
+-		uhci_scan_schedule(uhci, NULL);
+-	}
+-
++	suspend_hc(uhci, UHCI_RH_SUSPENDED);
+ 	spin_unlock_irq(&uhci->lock);
+ 	return 0;
+ }
+@@ -701,13 +722,9 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
+ static int uhci_resume(struct usb_hcd *hcd)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+-	int rc;
+-
+-	pci_set_master(to_pci_dev(uhci_dev(uhci)));
+ 
+ 	spin_lock_irq(&uhci->lock);
+-
+-	if (uhci->state == UHCI_SUSPENDED) {
++	if (uhci->rh_state == UHCI_RH_SUSPENDED) {
+ 
+ 		/*
+ 		 * Some systems don't maintain the UHCI register values
+@@ -721,19 +738,13 @@ static int uhci_resume(struct usb_hcd *hcd)
+ 		outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD);
+ 		outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC |
+ 				USBINTR_SP, uhci->io_addr + USBINTR);
+-		uhci->resume_detect = 1;
+ 		pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
+ 				USBLEGSUP_DEFAULT);
+-	} else {
+-		spin_unlock_irq(&uhci->lock);
+-		reset_hc(uhci);
+-		if ((rc = start_hc(uhci)) != 0)
+-			return rc;
+-		spin_lock_irq(&uhci->lock);
++		wakeup_hc(uhci);
+ 	}
+-	hcd->state = HC_STATE_RUNNING;
+-
+ 	spin_unlock_irq(&uhci->lock);
++
++	hcd->state = HC_STATE_RUNNING;
+ 	return 0;
+ }
+ #endif
+@@ -750,13 +761,15 @@ static void uhci_hcd_endpoint_disable(struct usb_hcd *hcd,
+ static int uhci_hcd_get_frame_number(struct usb_hcd *hcd)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+-	int frame_number;
+ 	unsigned long flags;
++	int is_stopped;
++	int frame_number;
+ 
+ 	/* Minimize latency by avoiding the spinlock */
+ 	local_irq_save(flags);
+-	rmb();
+-	frame_number = (uhci->is_stopped ? uhci->frame_number :
++	is_stopped = uhci->is_stopped;
++	smp_rmb();
++	frame_number = (is_stopped ? uhci->frame_number :
+ 			inw(uhci->io_addr + USBFRNUM));
+ 	local_irq_restore(flags);
+ 	return frame_number;
+diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
+index 02255d69e1fe..4bac57c74ec2 100644
+--- a/drivers/usb/host/uhci-hcd.h
++++ b/drivers/usb/host/uhci-hcd.h
+@@ -314,26 +314,29 @@ static inline int __interval_to_skel(int interval)
+ }
+ 
+ /*
+- * Device states for the host controller.
++ * States for the root hub.
+  *
+  * To prevent "bouncing" in the presence of electrical noise,
+- * we insist on a 1-second "grace" period, before switching to
+- * the RUNNING or SUSPENDED states, during which the state is
+- * not allowed to change.
+- *
+- * The resume process is divided into substates in order to avoid
+- * potentially length delays during the timer handler.
+- *
+- * States in which the host controller is halted must have values <= 0.
++ * when there are no devices attached we delay for 1 second in the
++ * RUNNING_NODEVS state before switching to the AUTO_STOPPED state.
++ * 
++ * (Note that the AUTO_STOPPED state won't be necessary once the hub
++ * driver learns to autosuspend.)
+  */
+-enum uhci_state {
+-	UHCI_RESET,
+-	UHCI_RUNNING_GRACE,		/* Before RUNNING */
+-	UHCI_RUNNING,			/* The normal state */
+-	UHCI_SUSPENDING_GRACE,		/* Before SUSPENDED */
+-	UHCI_SUSPENDED = -10,		/* When no devices are attached */
+-	UHCI_RESUMING_1,
+-	UHCI_RESUMING_2
++enum uhci_rh_state {
++	/* In the next 4 states the HC must be halted */
++	UHCI_RH_RESET,
++	UHCI_RH_SUSPENDED,
++	UHCI_RH_AUTO_STOPPED,
++	UHCI_RH_RESUMING,
++
++	/* In the next state the HC changes from running to halted, so it
++	 * can legally appear either way */
++	UHCI_RH_SUSPENDING,
++
++	/* In the next two states it's an error if the HC is halted */
++	UHCI_RH_RUNNING,		/* The normal state */
++	UHCI_RH_RUNNING_NODEVS,		/* Running with no devices attached */
+ };
+ 
+ /*
+@@ -363,8 +366,9 @@ struct uhci_hcd {
+ 	int fsbr;				/* Full-speed bandwidth reclamation */
+ 	unsigned long fsbrtimeout;		/* FSBR delay */
+ 
+-	enum uhci_state state;			/* FIXME: needs a spinlock */
+-	unsigned long state_end;		/* Time of next transition */
++	enum uhci_rh_state rh_state;
++	unsigned long auto_stop_time;		/* When to AUTO_STOP */
++
+ 	unsigned int frame_number;		/* As of last check */
+ 	unsigned int is_stopped;
+ #define UHCI_IS_STOPPED		9999		/* Larger than a frame # */
+@@ -451,4 +455,11 @@ struct urb_priv {
+  * #2 urb->lock
+  */
+ 
++
++/* Some special IDs */
++
++#define PCI_VENDOR_ID_GENESYS		0x17a0
++#define PCI_DEVICE_ID_GL880S_UHCI	0x8083
++#define PCI_DEVICE_ID_GL880S_EHCI	0x8084
++
+ #endif
+diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
+index ddb19cbf4b75..fc34fee2ab07 100644
+--- a/drivers/usb/host/uhci-hub.c
++++ b/drivers/usb/host/uhci-hub.c
+@@ -60,7 +60,7 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
+ 				test_bit(port, &uhci->port_c_suspend))
+ 			*buf |= (1 << (port + 1));
+ 	}
+-	if (*buf && uhci->state == UHCI_SUSPENDED)
++	if (*buf && uhci->is_stopped)
+ 		uhci->resume_detect = 1;
+ 	return !!*buf;
+ }

commit f5946f8220a866dcdb8edc6abe23c1443e252425
+Author: Alan Stern 
+Date:   Sat Apr 9 17:26:00 2005 -0400
+
+    [PATCH] USB UHCI: Minor improvements
+    
+    This patch makes a few small improvements in the UHCI driver.  Some
+    code is moved between different source files and a more useful pointer
+    is passed to a callback routine.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 8b6c87ef486b..c17bd7ebc021 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -100,22 +100,15 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
+ /* to make sure it doesn't hog all of the bandwidth */
+ #define DEPTH_INTERVAL 5
+ 
++static inline void restart_timer(struct uhci_hcd *uhci)
++{
++	mod_timer(&uhci->stall_timer, jiffies + msecs_to_jiffies(100));
++}
++
+ #include "uhci-hub.c"
+ #include "uhci-debug.c"
+ #include "uhci-q.c"
+ 
+-static int ports_active(struct uhci_hcd *uhci)
+-{
+-	unsigned long io_addr = uhci->io_addr;
+-	int connection = 0;
+-	int i;
+-
+-	for (i = 0; i < uhci->rh_numports; i++)
+-		connection |= (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_CCS);
+-
+-	return connection;
+-}
+-
+ static int suspend_allowed(struct uhci_hcd *uhci)
+ {
+ 	unsigned long io_addr = uhci->io_addr;
+@@ -270,14 +263,14 @@ static void hc_state_transitions(struct uhci_hcd *uhci)
+ 		case UHCI_RUNNING:
+ 
+ 			/* global suspend if nothing connected for 1 second */
+-			if (!ports_active(uhci) && suspend_allowed(uhci)) {
++			if (!any_ports_active(uhci) && suspend_allowed(uhci)) {
+ 				uhci->state = UHCI_SUSPENDING_GRACE;
+ 				uhci->state_end = jiffies + HZ;
+ 			}
+ 			break;
+ 
+ 		case UHCI_SUSPENDING_GRACE:
+-			if (ports_active(uhci))
++			if (any_ports_active(uhci))
+ 				uhci->state = UHCI_RUNNING;
+ 			else if (time_after_eq(jiffies, uhci->state_end))
+ 				suspend_hc(uhci);
+@@ -302,58 +295,24 @@ static void hc_state_transitions(struct uhci_hcd *uhci)
+ 	}
+ }
+ 
+-static int init_stall_timer(struct usb_hcd *hcd);
+-
+-static void stall_callback(unsigned long ptr)
++static void stall_callback(unsigned long _uhci)
+ {
+-	struct usb_hcd *hcd = (struct usb_hcd *)ptr;
+-	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+-	struct urb_priv *up;
++	struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci;
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&uhci->lock, flags);
+ 	uhci_scan_schedule(uhci, NULL);
+-
+-	list_for_each_entry(up, &uhci->urb_list, urb_list) {
+-		struct urb *u = up->urb;
+-
+-		spin_lock(&u->lock);
+-
+-		/* Check if the FSBR timed out */
+-		if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT))
+-			uhci_fsbr_timeout(uhci, u);
+-
+-		spin_unlock(&u->lock);
+-	}
+-
+-	/* Really disable FSBR */
+-	if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) {
+-		uhci->fsbrtimeout = 0;
+-		uhci->skel_term_qh->link = UHCI_PTR_TERM;
+-	}
++	check_fsbr(uhci);
+ 
+ 	/* Poll for and perform state transitions */
+ 	hc_state_transitions(uhci);
+ 	if (unlikely(uhci->suspended_ports && uhci->state != UHCI_SUSPENDED))
+ 		uhci_check_ports(uhci);
+ 
+-	init_stall_timer(hcd);
++	restart_timer(uhci);
+ 	spin_unlock_irqrestore(&uhci->lock, flags);
+ }
+ 
+-static int init_stall_timer(struct usb_hcd *hcd)
+-{
+-	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+-
+-	init_timer(&uhci->stall_timer);
+-	uhci->stall_timer.function = stall_callback;
+-	uhci->stall_timer.data = (unsigned long)hcd;
+-	uhci->stall_timer.expires = jiffies + msecs_to_jiffies(100);
+-	add_timer(&uhci->stall_timer);
+-
+-	return 0;
+-}
+-
+ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+@@ -509,6 +468,10 @@ static int uhci_start(struct usb_hcd *hcd)
+ 
+ 	init_waitqueue_head(&uhci->waitqh);
+ 
++	init_timer(&uhci->stall_timer);
++	uhci->stall_timer.function = stall_callback;
++	uhci->stall_timer.data = (unsigned long) uhci;
++
+ 	uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
+ 			&dma_handle, 0);
+ 	if (!uhci->fl) {
+@@ -646,7 +609,7 @@ static int uhci_start(struct usb_hcd *hcd)
+ 	if ((retval = start_hc(uhci)) != 0)
+ 		goto err_alloc_skelqh;
+ 
+-	init_stall_timer(hcd);
++	restart_timer(uhci);
+ 
+ 	udev->speed = USB_SPEED_FULL;
+ 
+diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
+index 4c45ba8390f8..ddb19cbf4b75 100644
+--- a/drivers/usb/host/uhci-hub.c
++++ b/drivers/usb/host/uhci-hub.c
+@@ -33,6 +33,22 @@ static __u8 root_hub_hub_des[] =
+ /* status change bits:  nonzero writes will clear */
+ #define RWC_BITS	(USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC)
+ 
++/* A port that either is connected or has a changed-bit set will prevent
++ * us from AUTO_STOPPING.
++ */
++static int any_ports_active(struct uhci_hcd *uhci)
++{
++	int port;
++
++	for (port = 0; port < uhci->rh_numports; ++port) {
++		if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) &
++				(USBPORTSC_CCS | RWC_BITS)) ||
++				test_bit(port, &uhci->port_c_suspend))
++			return 1;
++	}
++	return 0;
++}
++
+ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 2a7c19501f24..f5c75885f7be 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -1537,3 +1537,26 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs)
+ 	/* Wake up anyone waiting for an URB to complete */
+ 	wake_up_all(&uhci->waitqh);
+ }
++
++static void check_fsbr(struct uhci_hcd *uhci)
++{
++	struct urb_priv *up;
++
++	list_for_each_entry(up, &uhci->urb_list, urb_list) {
++		struct urb *u = up->urb;
++
++		spin_lock(&u->lock);
++
++		/* Check if the FSBR timed out */
++		if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT))
++			uhci_fsbr_timeout(uhci, u);
++
++		spin_unlock(&u->lock);
++	}
++
++	/* Really disable FSBR */
++	if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) {
++		uhci->fsbrtimeout = 0;
++		uhci->skel_term_qh->link = UHCI_PTR_TERM;
++	}
++}

commit 014e73c99aa408f3766afe8d11a1caa3a708b736
+Author: Alan Stern 
+Date:   Sat Apr 9 17:24:42 2005 -0400
+
+    [PATCH] USB UHCI: subroutine reordering
+    
+    This patch moves a few subroutines around in the uhci-hcd source file.
+    Nothing else is changed.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index 49bd83ee0c75..8b6c87ef486b 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -90,7 +90,6 @@ static char *errbuf;
+ static kmem_cache_t *uhci_up_cachep;	/* urb_priv */
+ 
+ static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
+-static void hc_state_transitions(struct uhci_hcd *uhci);
+ 
+ /* If a transfer is still active after this much time, turn off FSBR */
+ #define IDLE_TIMEOUT	msecs_to_jiffies(50)
+@@ -105,96 +104,43 @@ static void hc_state_transitions(struct uhci_hcd *uhci);
+ #include "uhci-debug.c"
+ #include "uhci-q.c"
+ 
+-static int init_stall_timer(struct usb_hcd *hcd);
+-
+-static void stall_callback(unsigned long ptr)
+-{
+-	struct usb_hcd *hcd = (struct usb_hcd *)ptr;
+-	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+-	struct urb_priv *up;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&uhci->lock, flags);
+-	uhci_scan_schedule(uhci, NULL);
+-
+-	list_for_each_entry(up, &uhci->urb_list, urb_list) {
+-		struct urb *u = up->urb;
+-
+-		spin_lock(&u->lock);
+-
+-		/* Check if the FSBR timed out */
+-		if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT))
+-			uhci_fsbr_timeout(uhci, u);
+-
+-		spin_unlock(&u->lock);
+-	}
+-
+-	/* Really disable FSBR */
+-	if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) {
+-		uhci->fsbrtimeout = 0;
+-		uhci->skel_term_qh->link = UHCI_PTR_TERM;
+-	}
+-
+-	/* Poll for and perform state transitions */
+-	hc_state_transitions(uhci);
+-	if (unlikely(uhci->suspended_ports && uhci->state != UHCI_SUSPENDED))
+-		uhci_check_ports(uhci);
+-
+-	init_stall_timer(hcd);
+-	spin_unlock_irqrestore(&uhci->lock, flags);
+-}
+-
+-static int init_stall_timer(struct usb_hcd *hcd)
++static int ports_active(struct uhci_hcd *uhci)
+ {
+-	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++	unsigned long io_addr = uhci->io_addr;
++	int connection = 0;
++	int i;
+ 
+-	init_timer(&uhci->stall_timer);
+-	uhci->stall_timer.function = stall_callback;
+-	uhci->stall_timer.data = (unsigned long)hcd;
+-	uhci->stall_timer.expires = jiffies + msecs_to_jiffies(100);
+-	add_timer(&uhci->stall_timer);
++	for (i = 0; i < uhci->rh_numports; i++)
++		connection |= (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_CCS);
+ 
+-	return 0;
++	return connection;
+ }
+ 
+-static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
++static int suspend_allowed(struct uhci_hcd *uhci)
+ {
+-	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 	unsigned long io_addr = uhci->io_addr;
+-	unsigned short status;
++	int i;
+ 
+-	/*
+-	 * Read the interrupt status, and write it back to clear the
+-	 * interrupt cause.  Contrary to the UHCI specification, the
+-	 * "HC Halted" status bit is persistent: it is RO, not R/WC.
++	if (to_pci_dev(uhci_dev(uhci))->vendor != PCI_VENDOR_ID_INTEL)
++		return 1;
++
++	/* Some of Intel's USB controllers have a bug that causes false
++	 * resume indications if any port has an over current condition.
++	 * To prevent problems, we will not allow a global suspend if
++	 * any ports are OC.
++	 *
++	 * Some motherboards using Intel's chipsets (but not using all
++	 * the USB ports) appear to hardwire the over current inputs active
++	 * to disable the USB ports.
+ 	 */
+-	status = inw(io_addr + USBSTS);
+-	if (!(status & ~USBSTS_HCH))	/* shared interrupt, not mine */
+-		return IRQ_NONE;
+-	outw(status, io_addr + USBSTS);		/* Clear it */
+ 
+-	if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) {
+-		if (status & USBSTS_HSE)
+-			dev_err(uhci_dev(uhci), "host system error, "
+-					"PCI problems?\n");
+-		if (status & USBSTS_HCPE)
+-			dev_err(uhci_dev(uhci), "host controller process "
+-					"error, something bad happened!\n");
+-		if ((status & USBSTS_HCH) && uhci->state > 0) {
+-			dev_err(uhci_dev(uhci), "host controller halted, "
+-					"very bad!\n");
+-			/* FIXME: Reset the controller, fix the offending TD */
+-		}
++	/* check for over current condition on any port */
++	for (i = 0; i < uhci->rh_numports; i++) {
++		if (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_OC)
++			return 0;
+ 	}
+ 
+-	if (status & USBSTS_RD)
+-		uhci->resume_detect = 1;
+-
+-	spin_lock(&uhci->lock);
+-	uhci_scan_schedule(uhci, regs);
+-	spin_unlock(&uhci->lock);
+-
+-	return IRQ_HANDLED;
++	return 1;
+ }
+ 
+ static void reset_hc(struct uhci_hcd *uhci)
+@@ -276,43 +222,46 @@ static void wakeup_hc(struct uhci_hcd *uhci)
+ 	}
+ }
+ 
+-static int ports_active(struct uhci_hcd *uhci)
++static int start_hc(struct uhci_hcd *uhci)
+ {
+ 	unsigned long io_addr = uhci->io_addr;
+-	int connection = 0;
+-	int i;
+-
+-	for (i = 0; i < uhci->rh_numports; i++)
+-		connection |= (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_CCS);
++	int timeout = 10;
+ 
+-	return connection;
+-}
++	/*
++	 * Reset the HC - this will force us to get a
++	 * new notification of any already connected
++	 * ports due to the virtual disconnect that it
++	 * implies.
++	 */
++	outw(USBCMD_HCRESET, io_addr + USBCMD);
++	while (inw(io_addr + USBCMD) & USBCMD_HCRESET) {
++		if (--timeout < 0) {
++			dev_err(uhci_dev(uhci), "USBCMD_HCRESET timed out!\n");
++			return -ETIMEDOUT;
++		}
++		msleep(1);
++	}
+ 
+-static int suspend_allowed(struct uhci_hcd *uhci)
+-{
+-	unsigned long io_addr = uhci->io_addr;
+-	int i;
++	/* Mark controller as running before we enable interrupts */
++	uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;
+ 
+-	if (to_pci_dev(uhci_dev(uhci))->vendor != PCI_VENDOR_ID_INTEL)
+-		return 1;
++	/* Turn on PIRQ and all interrupts */
++	pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
++			USBLEGSUP_DEFAULT);
++	outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP,
++		io_addr + USBINTR);
+ 
+-	/* Some of Intel's USB controllers have a bug that causes false
+-	 * resume indications if any port has an over current condition.
+-	 * To prevent problems, we will not allow a global suspend if
+-	 * any ports are OC.
+-	 *
+-	 * Some motherboards using Intel's chipsets (but not using all
+-	 * the USB ports) appear to hardwire the over current inputs active
+-	 * to disable the USB ports.
+-	 */
++	/* Start at frame 0 */
++	outw(0, io_addr + USBFRNUM);
++	outl(uhci->fl->dma_handle, io_addr + USBFLBASEADD);
+ 
+-	/* check for over current condition on any port */
+-	for (i = 0; i < uhci->rh_numports; i++) {
+-		if (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_OC)
+-			return 0;
+-	}
++	/* Run and mark it configured with a 64-byte max packet */
++	uhci->state = UHCI_RUNNING_GRACE;
++	uhci->state_end = jiffies + HZ;
++	outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD);
++	uhci->is_stopped = 0;
+ 
+-	return 1;
++	return 0;
+ }
+ 
+ static void hc_state_transitions(struct uhci_hcd *uhci)
+@@ -353,56 +302,106 @@ static void hc_state_transitions(struct uhci_hcd *uhci)
+ 	}
+ }
+ 
+-/*
+- * Store the current frame number in uhci->frame_number if the controller
+- * is runnning
+- */
+-static void uhci_get_current_frame_number(struct uhci_hcd *uhci)
++static int init_stall_timer(struct usb_hcd *hcd);
++
++static void stall_callback(unsigned long ptr)
+ {
+-	if (!uhci->is_stopped)
+-		uhci->frame_number = inw(uhci->io_addr + USBFRNUM);
++	struct usb_hcd *hcd = (struct usb_hcd *)ptr;
++	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++	struct urb_priv *up;
++	unsigned long flags;
++
++	spin_lock_irqsave(&uhci->lock, flags);
++	uhci_scan_schedule(uhci, NULL);
++
++	list_for_each_entry(up, &uhci->urb_list, urb_list) {
++		struct urb *u = up->urb;
++
++		spin_lock(&u->lock);
++
++		/* Check if the FSBR timed out */
++		if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT))
++			uhci_fsbr_timeout(uhci, u);
++
++		spin_unlock(&u->lock);
++	}
++
++	/* Really disable FSBR */
++	if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) {
++		uhci->fsbrtimeout = 0;
++		uhci->skel_term_qh->link = UHCI_PTR_TERM;
++	}
++
++	/* Poll for and perform state transitions */
++	hc_state_transitions(uhci);
++	if (unlikely(uhci->suspended_ports && uhci->state != UHCI_SUSPENDED))
++		uhci_check_ports(uhci);
++
++	init_stall_timer(hcd);
++	spin_unlock_irqrestore(&uhci->lock, flags);
+ }
+ 
+-static int start_hc(struct uhci_hcd *uhci)
++static int init_stall_timer(struct usb_hcd *hcd)
+ {
++	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++
++	init_timer(&uhci->stall_timer);
++	uhci->stall_timer.function = stall_callback;
++	uhci->stall_timer.data = (unsigned long)hcd;
++	uhci->stall_timer.expires = jiffies + msecs_to_jiffies(100);
++	add_timer(&uhci->stall_timer);
++
++	return 0;
++}
++
++static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
++{
++	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 	unsigned long io_addr = uhci->io_addr;
+-	int timeout = 10;
++	unsigned short status;
+ 
+ 	/*
+-	 * Reset the HC - this will force us to get a
+-	 * new notification of any already connected
+-	 * ports due to the virtual disconnect that it
+-	 * implies.
++	 * Read the interrupt status, and write it back to clear the
++	 * interrupt cause.  Contrary to the UHCI specification, the
++	 * "HC Halted" status bit is persistent: it is RO, not R/WC.
+ 	 */
+-	outw(USBCMD_HCRESET, io_addr + USBCMD);
+-	while (inw(io_addr + USBCMD) & USBCMD_HCRESET) {
+-		if (--timeout < 0) {
+-			dev_err(uhci_dev(uhci), "USBCMD_HCRESET timed out!\n");
+-			return -ETIMEDOUT;
++	status = inw(io_addr + USBSTS);
++	if (!(status & ~USBSTS_HCH))	/* shared interrupt, not mine */
++		return IRQ_NONE;
++	outw(status, io_addr + USBSTS);		/* Clear it */
++
++	if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) {
++		if (status & USBSTS_HSE)
++			dev_err(uhci_dev(uhci), "host system error, "
++					"PCI problems?\n");
++		if (status & USBSTS_HCPE)
++			dev_err(uhci_dev(uhci), "host controller process "
++					"error, something bad happened!\n");
++		if ((status & USBSTS_HCH) && uhci->state > 0) {
++			dev_err(uhci_dev(uhci), "host controller halted, "
++					"very bad!\n");
++			/* FIXME: Reset the controller, fix the offending TD */
+ 		}
+-		msleep(1);
+ 	}
+ 
+-	/* Mark controller as running before we enable interrupts */
+-	uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;
+-
+-	/* Turn on PIRQ and all interrupts */
+-	pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
+-			USBLEGSUP_DEFAULT);
+-	outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP,
+-		io_addr + USBINTR);
++	if (status & USBSTS_RD)
++		uhci->resume_detect = 1;
+ 
+-	/* Start at frame 0 */
+-	outw(0, io_addr + USBFRNUM);
+-	outl(uhci->fl->dma_handle, io_addr + USBFLBASEADD);
++	spin_lock(&uhci->lock);
++	uhci_scan_schedule(uhci, regs);
++	spin_unlock(&uhci->lock);
+ 
+-	/* Run and mark it configured with a 64-byte max packet */
+-	uhci->state = UHCI_RUNNING_GRACE;
+-	uhci->state_end = jiffies + HZ;
+-	outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD);
+-	uhci->is_stopped = 0;
++	return IRQ_HANDLED;
++}
+ 
+-	return 0;
++/*
++ * Store the current frame number in uhci->frame_number if the controller
++ * is runnning
++ */
++static void uhci_get_current_frame_number(struct uhci_hcd *uhci)
++{
++	if (!uhci->is_stopped)
++		uhci->frame_number = inw(uhci->io_addr + USBFRNUM);
+ }
+ 
+ /*

commit d794ac7ae3613c2abfb678617ac7d74c8ff0099c
+Author: Alan Stern 
+Date:   Mon Apr 18 12:43:25 2005 -0400
+
+    [PATCH] USB: g_file_storage: export "stall" parameter
+    
+    This patch changes the g_file_storage driver to make the "stall" module
+    parameter generally available; currently it is available only if the
+    testing version of the module has been configured.  It also fixes a typo
+    in a comment -- thanks, Pat!
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index 507a24924177..f5ce45c4b2a3 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -81,6 +81,10 @@
+  *	removable		Default false, boolean for removable media
+  *	luns=N			Default N = number of filenames, number of
+  *					LUNs to support
++ *	stall			Default determined according to the type of
++ *					USB device controller (usually true),
++ *					boolean to permit the driver to halt
++ *					bulk endpoints
+  *	transport=XXX		Default BBB, transport name (CB, CBI, or BBB)
+  *	protocol=YYY		Default SCSI, protocol name (RBC, 8020 or
+  *					ATAPI, QIC, UFI, 8070, or SCSI;
+@@ -91,14 +95,10 @@
+  *	buflen=N		Default N=16384, buffer size used (will be
+  *					rounded down to a multiple of
+  *					PAGE_CACHE_SIZE)
+- *	stall			Default determined according to the type of
+- *					USB device controller (usually true),
+- *					boolean to permit the driver to halt
+- *					bulk endpoints
+  *
+  * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro",
+- * "removable", and "luns" options are available; default values are used
+- * for everything else.
++ * "removable", "luns", and "stall" options are available; default values
++ * are used for everything else.
+  *
+  * The pathnames of the backing files and the ro settings are available in
+  * the attribute files "file" and "ro" in the lun subdirectory of the
+@@ -342,14 +342,15 @@ static struct {
+ 	int		num_ros;
+ 	unsigned int	nluns;
+ 
++	int		removable;
++	int		can_stall;
++
+ 	char		*transport_parm;
+ 	char		*protocol_parm;
+-	int		removable;
+ 	unsigned short	vendor;
+ 	unsigned short	product;
+ 	unsigned short	release;
+ 	unsigned int	buflen;
+-	int		can_stall;
+ 
+ 	int		transport_type;
+ 	char		*transport_name;
+@@ -360,11 +361,11 @@ static struct {
+ 	.transport_parm		= "BBB",
+ 	.protocol_parm		= "SCSI",
+ 	.removable		= 0,
++	.can_stall		= 1,
+ 	.vendor			= DRIVER_VENDOR_ID,
+ 	.product		= DRIVER_PRODUCT_ID,
+ 	.release		= 0xffff,	// Use controller chip type
+ 	.buflen			= 16384,
+-	.can_stall		= 1,
+ 	};
+ 
+ 
+@@ -380,6 +381,9 @@ MODULE_PARM_DESC(luns, "number of LUNs");
+ module_param_named(removable, mod_data.removable, bool, S_IRUGO);
+ MODULE_PARM_DESC(removable, "true to simulate removable media");
+ 
++module_param_named(stall, mod_data.can_stall, bool, S_IRUGO);
++MODULE_PARM_DESC(stall, "false to prevent bulk stalls");
++
+ 
+ /* In the non-TEST version, only the module parameters listed above
+  * are available. */
+@@ -404,9 +408,6 @@ MODULE_PARM_DESC(release, "USB release number");
+ module_param_named(buflen, mod_data.buflen, uint, S_IRUGO);
+ MODULE_PARM_DESC(buflen, "I/O buffer size");
+ 
+-module_param_named(stall, mod_data.can_stall, bool, S_IRUGO);
+-MODULE_PARM_DESC(stall, "false to prevent bulk stalls");
+-
+ #endif /* CONFIG_USB_FILE_STORAGE_TEST */
+ 
+ 
+@@ -2657,7 +2658,7 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size,
+ 		}
+ 	}
+ 
+-	/* Check that the LUN values are oonsistent */
++	/* Check that the LUN values are consistent */
+ 	if (transport_is_bbb()) {
+ 		if (fsg->lun != lun)
+ 			DBG(fsg, "using LUN %d from CBW, "

commit 76f4af8efc72b6091d230cbe718cedca06d2d79e
+Author: Alan Stern 
+Date:   Tue Apr 5 11:56:54 2005 -0400
+
+    [PATCH] USB: g_file_storage: Consolidate min()s
+    
+    This patch simplifies the g_file_storage driver by consolidating a bunch
+    of min() calculations at a single spot.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index a9be85103d23..507a24924177 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -1312,7 +1312,7 @@ static int class_setup_req(struct fsg_dev *fsg,
+ 			}
+ 			VDBG(fsg, "get max LUN\n");
+ 			*(u8 *) req->buf = fsg->nluns - 1;
+-			value = min(w_length, (u16) 1);
++			value = 1;
+ 			break;
+ 		}
+ 	}
+@@ -1360,7 +1360,6 @@ static int standard_setup_req(struct fsg_dev *fsg,
+ 	int			value = -EOPNOTSUPP;
+ 	u16			w_index = ctrl->wIndex;
+ 	u16			w_value = ctrl->wValue;
+-	u16			w_length = ctrl->wLength;
+ 
+ 	/* Usually this just stores reply data in the pre-allocated ep0 buffer,
+ 	 * but config change events will also reconfigure hardware. */
+@@ -1374,7 +1373,7 @@ static int standard_setup_req(struct fsg_dev *fsg,
+ 
+ 		case USB_DT_DEVICE:
+ 			VDBG(fsg, "get device descriptor\n");
+-			value = min(w_length, (u16) sizeof device_desc);
++			value = sizeof device_desc;
+ 			memcpy(req->buf, &device_desc, value);
+ 			break;
+ #ifdef CONFIG_USB_GADGET_DUALSPEED
+@@ -1382,7 +1381,7 @@ static int standard_setup_req(struct fsg_dev *fsg,
+ 			VDBG(fsg, "get device qualifier\n");
+ 			if (!fsg->gadget->is_dualspeed)
+ 				break;
+-			value = min(w_length, (u16) sizeof dev_qualifier);
++			value = sizeof dev_qualifier;
+ 			memcpy(req->buf, &dev_qualifier, value);
+ 			break;
+ 
+@@ -1401,8 +1400,6 @@ static int standard_setup_req(struct fsg_dev *fsg,
+ 					req->buf,
+ 					w_value >> 8,
+ 					w_value & 0xff);
+-			if (value >= 0)
+-				value = min(w_length, (u16) value);
+ 			break;
+ 
+ 		case USB_DT_STRING:
+@@ -1411,8 +1408,6 @@ static int standard_setup_req(struct fsg_dev *fsg,
+ 			/* wIndex == language code */
+ 			value = usb_gadget_get_string(&stringtab,
+ 					w_value & 0xff, req->buf);
+-			if (value >= 0)
+-				value = min(w_length, (u16) value);
+ 			break;
+ 		}
+ 		break;
+@@ -1438,7 +1433,7 @@ static int standard_setup_req(struct fsg_dev *fsg,
+ 			break;
+ 		VDBG(fsg, "get configuration\n");
+ 		*(u8 *) req->buf = fsg->config;
+-		value = min(w_length, (u16) 1);
++		value = 1;
+ 		break;
+ 
+ 	case USB_REQ_SET_INTERFACE:
+@@ -1466,14 +1461,14 @@ static int standard_setup_req(struct fsg_dev *fsg,
+ 		}
+ 		VDBG(fsg, "get interface\n");
+ 		*(u8 *) req->buf = 0;
+-		value = min(w_length, (u16) 1);
++		value = 1;
+ 		break;
+ 
+ 	default:
+ 		VDBG(fsg,
+ 			"unknown control req %02x.%02x v%04x i%04x l%u\n",
+ 			ctrl->bRequestType, ctrl->bRequest,
+-			w_value, w_index, w_length);
++			w_value, w_index, ctrl->wLength);
+ 	}
+ 
+ 	return value;
+@@ -1485,6 +1480,7 @@ static int fsg_setup(struct usb_gadget *gadget,
+ {
+ 	struct fsg_dev		*fsg = get_gadget_data(gadget);
+ 	int			rc;
++	int			w_length = ctrl->wLength;
+ 
+ 	++fsg->ep0_req_tag;		// Record arrival of a new request
+ 	fsg->ep0req->context = NULL;
+@@ -1498,8 +1494,9 @@ static int fsg_setup(struct usb_gadget *gadget,
+ 
+ 	/* Respond with data/status or defer until later? */
+ 	if (rc >= 0 && rc != DELAYED_STATUS) {
++		rc = min(rc, w_length);
+ 		fsg->ep0req->length = rc;
+-		fsg->ep0req->zero = (rc < ctrl->wLength &&
++		fsg->ep0req->zero = (rc < w_length &&
+ 				(rc % gadget->ep0->maxpacket) == 0);
+ 		fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ?
+ 				"ep0-in" : "ep0-out");

commit f409661877a25d11c2495bcd879807f17c286684
+Author: Alan Stern 
+Date:   Fri May 6 15:41:08 2005 -0400
+
+    [PATCH] usbcore: Don't call device_release_driver recursively
+    
+    This patch fixes usb_driver_release_interface() to make it avoid calling
+    device_release_driver() recursively, i.e., when invoked from within the
+    disconnect routine for the same device.  The patch applies to your
+    "driver" tree.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 66678763c24d..a3c42203213a 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -322,9 +322,15 @@ void usb_driver_release_interface(struct usb_driver *driver,
+ 	if (!dev->driver || dev->driver != &driver->driver)
+ 		return;
+ 
+-	/* don't disconnect from disconnect(), or before dev_add() */
+-	if (!klist_node_attached(&dev->knode_driver) && !klist_node_attached(&dev->knode_bus))
++	/* don't release from within disconnect() */
++	if (iface->condition != USB_INTERFACE_BOUND)
++		return;
++
++	/* release only after device_add() */
++	if (klist_node_attached(&dev->knode_bus)) {
++		iface->condition = USB_INTERFACE_UNBINDING;
+ 		device_release_driver(dev);
++	}
+ 
+ 	dev->driver = NULL;
+ 	usb_set_intfdata(iface, NULL);

commit c95a6b057b108c2b7add35cba1354f9af921349e
+Author: Alan Stern 
+Date:   Fri May 6 15:38:33 2005 -0400
+
+    [PATCH] driver core: Fix races in driver_detach()
+    
+    This patch is intended for your "driver" tree.  It fixes several subtle
+    races in driver_detach() and device_release_driver() in the driver-model
+    core.
+    
+    The major change is to use klist_remove() rather than klist_del() when
+    taking a device off its driver's list.  There's no other way to guarantee
+    that the list pointers will be updated before some other driver binds to
+    the device.  For this to work driver_detach() can't use a klist iterator,
+    so the loop over the devices must be written out in full.  In addition the
+    patch protects against the possibility that, when a driver and a device
+    are unregistered at the same time, one may be unloaded from memory before
+    the other is finished using it.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/base/dd.c b/drivers/base/dd.c
+index 8510918109e0..eab2030c506d 100644
+--- a/drivers/base/dd.c
++++ b/drivers/base/dd.c
+@@ -177,41 +177,66 @@ void driver_attach(struct device_driver * drv)
+  *	@dev:	device.
+  *
+  *	Manually detach device from driver.
+- *	Note that this is called without incrementing the bus
+- *	reference count nor taking the bus's rwsem. Be sure that
+- *	those are accounted for before calling this function.
++ *
++ *	__device_release_driver() must be called with @dev->sem held.
+  */
+-void device_release_driver(struct device * dev)
++
++static void __device_release_driver(struct device * dev)
+ {
+ 	struct device_driver * drv;
+ 
+-	down(&dev->sem);
+-	if (dev->driver) {
+-		drv = dev->driver;
++	drv = dev->driver;
++	if (drv) {
++		get_driver(drv);
+ 		sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
+ 		sysfs_remove_link(&dev->kobj, "driver");
+-		klist_del(&dev->knode_driver);
++		klist_remove(&dev->knode_driver);
+ 
+ 		if (drv->remove)
+ 			drv->remove(dev);
+ 		dev->driver = NULL;
++		put_driver(drv);
+ 	}
+-	up(&dev->sem);
+ }
+ 
+-static int __remove_driver(struct device * dev, void * unused)
++void device_release_driver(struct device * dev)
+ {
+-	device_release_driver(dev);
+-	return 0;
++	/*
++	 * If anyone calls device_release_driver() recursively from
++	 * within their ->remove callback for the same device, they
++	 * will deadlock right here.
++	 */
++	down(&dev->sem);
++	__device_release_driver(dev);
++	up(&dev->sem);
+ }
+ 
++
+ /**
+  * driver_detach - detach driver from all devices it controls.
+  * @drv: driver.
+  */
+ void driver_detach(struct device_driver * drv)
+ {
+-	driver_for_each_device(drv, NULL, NULL, __remove_driver);
++	struct device * dev;
++
++	for (;;) {
++		spin_lock_irq(&drv->klist_devices.k_lock);
++		if (list_empty(&drv->klist_devices.k_list)) {
++			spin_unlock_irq(&drv->klist_devices.k_lock);
++			break;
++		}
++		dev = list_entry(drv->klist_devices.k_list.prev,
++				struct device, knode_driver.n_node);
++		get_device(dev);
++		spin_unlock_irq(&drv->klist_devices.k_lock);
++
++		down(&dev->sem);
++		if (dev->driver == drv)
++			__device_release_driver(dev);
++		up(&dev->sem);
++		put_device(dev);
++	}
+ }
+ 
+ 

commit 8835f6657316162a8937d3f26ccd8f5886ba3845
+Author: Alan Stern 
+Date:   Mon Apr 18 17:39:30 2005 -0700
+
+    [PATCH] USB: USB API documentation modification
+    
+    In response to complaints about excessive latency in the uhci-hcd driver
+    I'm planning to convert it to a top-half/bottom-half design.  It turns out
+    that to do this, the USB API has to be modified slightly since the driver
+    will not be able to meet one of the guarantees in the current API.  This
+    patch changes some kerneldoc, specifying the weaker guarantee.
+    
+    Signed-off-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
+index dc838f81742c..16972159a57a 100644
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -420,12 +420,16 @@ int usb_submit_urb(struct urb *urb, int mem_flags)
+  *
+  * Host Controller Drivers (HCDs) place all the URBs for a particular
+  * endpoint in a queue.  Normally the queue advances as the controller
+- * hardware processes each request.  But when an URB terminates with any
+- * fault (such as an error, or being unlinked) its queue stops, at least
+- * until that URB's completion routine returns.  It is guaranteed that
+- * the queue will not restart until all its unlinked URBs have been fully
+- * retired, with their completion routines run, even if that's not until
+- * some time after the original completion handler returns.
++ * hardware processes each request.  But when an URB terminates with an
++ * error its queue stops, at least until that URB's completion routine
++ * returns.  It is guaranteed that the queue will not restart until all
++ * its unlinked URBs have been fully retired, with their completion
++ * routines run, even if that's not until some time after the original
++ * completion handler returns.  Normally the same behavior and guarantees
++ * apply when an URB terminates because it was unlinked; however if an
++ * URB is unlinked before the hardware has started to execute it, then
++ * its queue is not guaranteed to stop until all the preceding URBs have
++ * completed.
+  *
+  * This means that USB device drivers can safely build deep queues for
+  * large or complex transfers, and clean them up reliably after any sort

\ No newline at end of file diff --git a/detail/20.html b/detail/20.html new file mode 100644 index 0000000..0d8351c --- /dev/null +++ b/detail/20.html @@ -0,0 +1,7861 @@ +

Patches contributed by Unknown (cs.sunysb.edu)


commit fe0fc013cd8bbd2f4737c1b2694b37dd7fe459cb
+Author: Erez Zadok 
+Date:   Mon Jan 4 18:17:02 2010 -0500
+
+    ecryptfs: fix interpose/interpolate typos in comments
+    
+    Signed-off-by: Erez Zadok 
+    Acked-by: Dustin Kirkland 
+    Signed-off-by: Tyler Hicks 
+
+diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
+index 567bc4b9f70a..ea2f92101dfe 100644
+--- a/fs/ecryptfs/main.c
++++ b/fs/ecryptfs/main.c
+@@ -585,8 +585,8 @@ static int ecryptfs_read_super(struct super_block *sb, const char *dev_name)
+  *                        with as much information as it can before needing
+  *                        the lower filesystem.
+  * ecryptfs_read_super(): this accesses the lower filesystem and uses
+- *                        ecryptfs_interpolate to perform most of the linking
+- * ecryptfs_interpolate(): links the lower filesystem into ecryptfs
++ *                        ecryptfs_interpose to perform most of the linking
++ * ecryptfs_interpose(): links the lower filesystem into ecryptfs (inode.c)
+  */
+ static int ecryptfs_get_sb(struct file_system_type *fs_type, int flags,
+ 			const char *dev_name, void *raw_data,

commit 3469b57329f80db5a41cf42d1c8f7690269f57e7
+Author: Erez Zadok 
+Date:   Sun Dec 6 18:51:15 2009 -0500
+
+    ecryptfs: pass matching flags to interpose as defined and used there
+    
+    ecryptfs_interpose checks if one of the flags passed is
+    ECRYPTFS_INTERPOSE_FLAG_D_ADD, defined as 0x00000001 in ecryptfs_kernel.h.
+    But the only user of ecryptfs_interpose to pass a non-zero flag to it, has
+    hard-coded the value as "1". This could spell trouble if any of these values
+    changes in the future.
+    
+    Signed-off-by: Erez Zadok 
+    Cc: Dustin Kirkland 
+    Cc: Al Viro 
+    Signed-off-by: Tyler Hicks 
+
+diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
+index e03415293625..4a430ab4115c 100644
+--- a/fs/ecryptfs/inode.c
++++ b/fs/ecryptfs/inode.c
+@@ -282,7 +282,8 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
+ 		goto out;
+ 	}
+ 	rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry,
+-				ecryptfs_dir_inode->i_sb, 1);
++				ecryptfs_dir_inode->i_sb,
++				ECRYPTFS_INTERPOSE_FLAG_D_ADD);
+ 	if (rc) {
+ 		printk(KERN_ERR "%s: Error interposing; rc = [%d]\n",
+ 		       __func__, rc);

commit c44a66d674688f1e1d0b2f6f56bd9c6a1b061cae
+Author: Erez Zadok 
+Date:   Sun Dec 6 18:05:30 2009 -0500
+
+    ecryptfs: remove unnecessary d_drop calls in ecryptfs_link
+    
+    Unnecessary because it would unhash perfectly valid dentries, causing them
+    to have to be re-looked up the next time they're needed, which presumably is
+    right after.
+    
+    Signed-off-by: Aseem Rastogi 
+    Signed-off-by: Shrikar archak 
+    Signed-off-by: Erez Zadok 
+    Cc: Saumitra Bhanage 
+    Cc: Al Viro 
+    Signed-off-by: Tyler Hicks 
+
+diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
+index 764dc777b268..e03415293625 100644
+--- a/fs/ecryptfs/inode.c
++++ b/fs/ecryptfs/inode.c
+@@ -463,9 +463,6 @@ static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir,
+ 	unlock_dir(lower_dir_dentry);
+ 	dput(lower_new_dentry);
+ 	dput(lower_old_dentry);
+-	d_drop(lower_old_dentry);
+-	d_drop(new_dentry);
+-	d_drop(old_dentry);
+ 	return rc;
+ }
+ 

commit 0d132f7364694da8f7cafd49e2fc2721b73e96e4
+Author: Erez Zadok 
+Date:   Sat Dec 5 21:17:09 2009 -0500
+
+    ecryptfs: don't ignore return value from lock_rename
+    
+    Signed-off-by: Erez Zadok 
+    Cc: Dustin Kirkland 
+    Cc: Andrew Morton 
+    Cc: Al Viro 
+    Signed-off-by: Tyler Hicks 
+
+diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
+index 5726d7adaf5b..764dc777b268 100644
+--- a/fs/ecryptfs/inode.c
++++ b/fs/ecryptfs/inode.c
+@@ -614,6 +614,7 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 	struct dentry *lower_new_dentry;
+ 	struct dentry *lower_old_dir_dentry;
+ 	struct dentry *lower_new_dir_dentry;
++	struct dentry *trap = NULL;
+ 
+ 	lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
+ 	lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
+@@ -621,7 +622,17 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 	dget(lower_new_dentry);
+ 	lower_old_dir_dentry = dget_parent(lower_old_dentry);
+ 	lower_new_dir_dentry = dget_parent(lower_new_dentry);
+-	lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
++	trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
++	/* source should not be ancestor of target */
++	if (trap == lower_old_dentry) {
++		rc = -EINVAL;
++		goto out_lock;
++	}
++	/* target should not be ancestor of source */
++	if (trap == lower_new_dentry) {
++		rc = -ENOTEMPTY;
++		goto out_lock;
++	}
+ 	rc = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
+ 			lower_new_dir_dentry->d_inode, lower_new_dentry);
+ 	if (rc)

commit e27759d7a333d1f25d628c4f7caf845c51be51c2
+Author: Erez Zadok 
+Date:   Thu Dec 3 13:35:27 2009 -0500
+
+    ecryptfs: initialize private persistent file before dereferencing pointer
+    
+    Ecryptfs_open dereferences a pointer to the private lower file (the one
+    stored in the ecryptfs inode), without checking if the pointer is NULL.
+    Right afterward, it initializes that pointer if it is NULL.  Swap order of
+    statements to first initialize.  Bug discovered by Duckjin Kang.
+    
+    Signed-off-by: Duckjin Kang 
+    Signed-off-by: Erez Zadok 
+    Cc: Dustin Kirkland 
+    Cc: Al Viro 
+    Cc: 
+    Signed-off-by: Tyler Hicks 
+
+diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
+index 3efc7fdc3c39..dde7bb48bb5f 100644
+--- a/fs/ecryptfs/file.c
++++ b/fs/ecryptfs/file.c
+@@ -191,13 +191,6 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
+ 				      | ECRYPTFS_ENCRYPTED);
+ 	}
+ 	mutex_unlock(&crypt_stat->cs_mutex);
+-	if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_RDONLY)
+-	    && !(file->f_flags & O_RDONLY)) {
+-		rc = -EPERM;
+-		printk(KERN_WARNING "%s: Lower persistent file is RO; eCryptfs "
+-		       "file must hence be opened RO\n", __func__);
+-		goto out;
+-	}
+ 	if (!ecryptfs_inode_to_private(inode)->lower_file) {
+ 		rc = ecryptfs_init_persistent_file(ecryptfs_dentry);
+ 		if (rc) {
+@@ -208,6 +201,13 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
+ 			goto out;
+ 		}
+ 	}
++	if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_RDONLY)
++	    && !(file->f_flags & O_RDONLY)) {
++		rc = -EPERM;
++		printk(KERN_WARNING "%s: Lower persistent file is RO; eCryptfs "
++		       "file must hence be opened RO\n", __func__);
++		goto out;
++	}
+ 	ecryptfs_set_file_lower(
+ 		file, ecryptfs_inode_to_private(inode)->lower_file);
+ 	if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {

commit 1b8ab8159ef8f818f870a1d2e3b6953d80eefd3f
+Author: Erez Zadok 
+Date:   Thu Dec 3 21:56:09 2009 -0500
+
+    VFS/fsstack: handle 32-bit smp + preempt + large files in fsstack_copy_inode_size
+    
+    Copy the inode size and blocks from one inode to another correctly on 32-bit
+    systems with CONFIG_SMP, CONFIG_PREEMPT, or CONFIG_LBDAF.  Use proper inode
+    spinlocks only when i_size/i_blocks cannot fit in one 32-bit word.
+    
+    Signed-off-by: Hugh Dickins 
+    Signed-off-by: Erez Zadok 
+    Signed-off-by: Al Viro 
+
+diff --git a/fs/stack.c b/fs/stack.c
+index 0e20e43ad740..4a6f7f440658 100644
+--- a/fs/stack.c
++++ b/fs/stack.c
+@@ -7,10 +7,58 @@
+  * This function cannot be inlined since i_size_{read,write} is rather
+  * heavy-weight on 32-bit systems
+  */
+-void fsstack_copy_inode_size(struct inode *dst, const struct inode *src)
++void fsstack_copy_inode_size(struct inode *dst, struct inode *src)
+ {
+-	i_size_write(dst, i_size_read((struct inode *)src));
+-	dst->i_blocks = src->i_blocks;
++	loff_t i_size;
++	blkcnt_t i_blocks;
++
++	/*
++	 * i_size_read() includes its own seqlocking and protection from
++	 * preemption (see include/linux/fs.h): we need nothing extra for
++	 * that here, and prefer to avoid nesting locks than attempt to keep
++	 * i_size and i_blocks in sync together.
++	 */
++	i_size = i_size_read(src);
++
++	/*
++	 * But if CONFIG_LBDAF (on 32-bit), we ought to make an effort to
++	 * keep the two halves of i_blocks in sync despite SMP or PREEMPT -
++	 * though stat's generic_fillattr() doesn't bother, and we won't be
++	 * applying quotas (where i_blocks does become important) at the
++	 * upper level.
++	 *
++	 * We don't actually know what locking is used at the lower level;
++	 * but if it's a filesystem that supports quotas, it will be using
++	 * i_lock as in inode_add_bytes().  tmpfs uses other locking, and
++	 * its 32-bit is (just) able to exceed 2TB i_size with the aid of
++	 * holes; but its i_blocks cannot carry into the upper long without
++	 * almost 2TB swap - let's ignore that case.
++	 */
++	if (sizeof(i_blocks) > sizeof(long))
++		spin_lock(&src->i_lock);
++	i_blocks = src->i_blocks;
++	if (sizeof(i_blocks) > sizeof(long))
++		spin_unlock(&src->i_lock);
++
++	/*
++	 * If CONFIG_SMP or CONFIG_PREEMPT on 32-bit, it's vital for
++	 * fsstack_copy_inode_size() to hold some lock around
++	 * i_size_write(), otherwise i_size_read() may spin forever (see
++	 * include/linux/fs.h).  We don't necessarily hold i_mutex when this
++	 * is called, so take i_lock for that case.
++	 *
++	 * And if CONFIG_LBADF (on 32-bit), continue our effort to keep the
++	 * two halves of i_blocks in sync despite SMP or PREEMPT: use i_lock
++	 * for that case too, and do both at once by combining the tests.
++	 *
++	 * There is none of this locking overhead in the 64-bit case.
++	 */
++	if (sizeof(i_size) > sizeof(long) || sizeof(i_blocks) > sizeof(long))
++		spin_lock(&dst->i_lock);
++	i_size_write(dst, i_size);
++	dst->i_blocks = i_blocks;
++	if (sizeof(i_size) > sizeof(long) || sizeof(i_blocks) > sizeof(long))
++		spin_unlock(&dst->i_lock);
+ }
+ EXPORT_SYMBOL_GPL(fsstack_copy_inode_size);
+ 
+diff --git a/include/linux/fs_stack.h b/include/linux/fs_stack.h
+index aa60311900dd..da317c7163ab 100644
+--- a/include/linux/fs_stack.h
++++ b/include/linux/fs_stack.h
+@@ -9,7 +9,7 @@
+ 
+ /* externs for fs/stack.c */
+ extern void fsstack_copy_attr_all(struct inode *dest, const struct inode *src);
+-extern void fsstack_copy_inode_size(struct inode *dst, const struct inode *src);
++extern void fsstack_copy_inode_size(struct inode *dst, struct inode *src);
+ 
+ /* inlines */
+ static inline void fsstack_copy_attr_atime(struct inode *dest,

commit 9afa2fb6c13501e5b3536d15344fce4e5442c469
+Author: Erez Zadok 
+Date:   Wed Dec 2 19:51:54 2009 -0500
+
+    fsstack/ecryptfs: remove unused get_nlinks param to fsstack_copy_attr_all
+    
+    This get_nlinks parameter was never used by the only mainline user,
+    ecryptfs; and it has never been used by unionfs or wrapfs either.
+    
+    Acked-by: Dustin Kirkland 
+    Acked-by: Tyler Hicks 
+    Signed-off-by: Erez Zadok 
+    Signed-off-by: Al Viro 
+
+diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c
+index 2dda5ade75bc..8f006a0d6076 100644
+--- a/fs/ecryptfs/dentry.c
++++ b/fs/ecryptfs/dentry.c
+@@ -62,7 +62,7 @@ static int ecryptfs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
+ 		struct inode *lower_inode =
+ 			ecryptfs_inode_to_lower(dentry->d_inode);
+ 
+-		fsstack_copy_attr_all(dentry->d_inode, lower_inode, NULL);
++		fsstack_copy_attr_all(dentry->d_inode, lower_inode);
+ 	}
+ out:
+ 	return rc;
+diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
+index 056fed62d0de..429ca0b3ba08 100644
+--- a/fs/ecryptfs/inode.c
++++ b/fs/ecryptfs/inode.c
+@@ -626,9 +626,9 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 			lower_new_dir_dentry->d_inode, lower_new_dentry);
+ 	if (rc)
+ 		goto out_lock;
+-	fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode, NULL);
++	fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
+ 	if (new_dir != old_dir)
+-		fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode, NULL);
++		fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);
+ out_lock:
+ 	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
+ 	dput(lower_new_dentry->d_parent);
+@@ -967,7 +967,7 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
+ 	rc = notify_change(lower_dentry, ia);
+ 	mutex_unlock(&lower_dentry->d_inode->i_mutex);
+ out:
+-	fsstack_copy_attr_all(inode, lower_inode, NULL);
++	fsstack_copy_attr_all(inode, lower_inode);
+ 	return rc;
+ }
+ 
+diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
+index 101fe4c7b1ee..567bc4b9f70a 100644
+--- a/fs/ecryptfs/main.c
++++ b/fs/ecryptfs/main.c
+@@ -189,7 +189,7 @@ int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry,
+ 		init_special_inode(inode, lower_inode->i_mode,
+ 				   lower_inode->i_rdev);
+ 	dentry->d_op = &ecryptfs_dops;
+-	fsstack_copy_attr_all(inode, lower_inode, NULL);
++	fsstack_copy_attr_all(inode, lower_inode);
+ 	/* This size will be overwritten for real files w/ headers and
+ 	 * other metadata */
+ 	fsstack_copy_inode_size(inode, lower_inode);
+diff --git a/fs/stack.c b/fs/stack.c
+index 67716f6a1a4a..0e20e43ad740 100644
+--- a/fs/stack.c
++++ b/fs/stack.c
+@@ -14,11 +14,8 @@ void fsstack_copy_inode_size(struct inode *dst, const struct inode *src)
+ }
+ EXPORT_SYMBOL_GPL(fsstack_copy_inode_size);
+ 
+-/* copy all attributes; get_nlinks is optional way to override the i_nlink
+- * copying
+- */
+-void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
+-				int (*get_nlinks)(struct inode *))
++/* copy all attributes */
++void fsstack_copy_attr_all(struct inode *dest, const struct inode *src)
+ {
+ 	dest->i_mode = src->i_mode;
+ 	dest->i_uid = src->i_uid;
+@@ -29,14 +26,6 @@ void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
+ 	dest->i_ctime = src->i_ctime;
+ 	dest->i_blkbits = src->i_blkbits;
+ 	dest->i_flags = src->i_flags;
+-
+-	/*
+-	 * Update the nlinks AFTER updating the above fields, because the
+-	 * get_links callback may depend on them.
+-	 */
+-	if (!get_nlinks)
+-		dest->i_nlink = src->i_nlink;
+-	else
+-		dest->i_nlink = (*get_nlinks)(dest);
++	dest->i_nlink = src->i_nlink;
+ }
+ EXPORT_SYMBOL_GPL(fsstack_copy_attr_all);
+diff --git a/include/linux/fs_stack.h b/include/linux/fs_stack.h
+index bb516ceeefc9..aa60311900dd 100644
+--- a/include/linux/fs_stack.h
++++ b/include/linux/fs_stack.h
+@@ -8,9 +8,7 @@
+ #include 
+ 
+ /* externs for fs/stack.c */
+-extern void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
+-				int (*get_nlinks)(struct inode *));
+-
++extern void fsstack_copy_attr_all(struct inode *dest, const struct inode *src);
+ extern void fsstack_copy_inode_size(struct inode *dst, const struct inode *src);
+ 
+ /* inlines */

commit aa81a7c7120ad9a4f8b677b7c204bb12b2b0e145
+Author: Erez Zadok 
+Date:   Thu Feb 7 00:13:25 2008 -0800
+
+    VFS: factor out three helpers for FIBMAP/FIONBIO/FIOASYNC file ioctls
+    
+    Factor out file-specific ioctl code into smaller helper functions, away from
+    file_ioctl().  This helps code readability and also reduces indentation inside
+    case statements.
+    
+    Signed-off-by: Erez Zadok 
+    Cc: Christoph Hellwig 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/ioctl.c b/fs/ioctl.c
+index e6500cd12258..683002fefa55 100644
+--- a/fs/ioctl.c
++++ b/fs/ioctl.c
+@@ -52,32 +52,34 @@ long vfs_ioctl(struct file *filp, unsigned int cmd,
+ 	return error;
+ }
+ 
++static int ioctl_fibmap(struct file *filp, int __user *p)
++{
++	struct address_space *mapping = filp->f_mapping;
++	int res, block;
++
++	/* do we support this mess? */
++	if (!mapping->a_ops->bmap)
++		return -EINVAL;
++	if (!capable(CAP_SYS_RAWIO))
++		return -EPERM;
++	res = get_user(block, p);
++	if (res)
++		return res;
++	lock_kernel();
++	res = mapping->a_ops->bmap(mapping, block);
++	unlock_kernel();
++	return put_user(res, p);
++}
++
+ static int file_ioctl(struct file *filp, unsigned int cmd,
+ 		unsigned long arg)
+ {
+-	int error;
+-	int block;
+ 	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	int __user *p = (int __user *)arg;
+ 
+ 	switch (cmd) {
+ 	case FIBMAP:
+-	{
+-		struct address_space *mapping = filp->f_mapping;
+-		int res;
+-		/* do we support this mess? */
+-		if (!mapping->a_ops->bmap)
+-			return -EINVAL;
+-		if (!capable(CAP_SYS_RAWIO))
+-			return -EPERM;
+-		error = get_user(block, p);
+-		if (error)
+-			return error;
+-		lock_kernel();
+-		res = mapping->a_ops->bmap(mapping, block);
+-		unlock_kernel();
+-		return put_user(res, p);
+-	}
++		return ioctl_fibmap(filp, p);
+ 	case FIGETBSZ:
+ 		return put_user(inode->i_sb->s_blocksize, p);
+ 	case FIONREAD:
+@@ -87,6 +89,57 @@ static int file_ioctl(struct file *filp, unsigned int cmd,
+ 	return vfs_ioctl(filp, cmd, arg);
+ }
+ 
++static int ioctl_fionbio(struct file *filp, int __user *argp)
++{
++	unsigned int flag;
++	int on, error;
++
++	error = get_user(on, argp);
++	if (error)
++		return error;
++	flag = O_NONBLOCK;
++#ifdef __sparc__
++	/* SunOS compatibility item. */
++	if (O_NONBLOCK != O_NDELAY)
++		flag |= O_NDELAY;
++#endif
++	if (on)
++		filp->f_flags |= flag;
++	else
++		filp->f_flags &= ~flag;
++	return error;
++}
++
++static int ioctl_fioasync(unsigned int fd, struct file *filp,
++			  int __user *argp)
++{
++	unsigned int flag;
++	int on, error;
++
++	error = get_user(on, argp);
++	if (error)
++		return error;
++	flag = on ? FASYNC : 0;
++
++	/* Did FASYNC state change ? */
++	if ((flag ^ filp->f_flags) & FASYNC) {
++		if (filp->f_op && filp->f_op->fasync) {
++			lock_kernel();
++			error = filp->f_op->fasync(fd, filp, on);
++			unlock_kernel();
++		} else
++			error = -ENOTTY;
++	}
++	if (error)
++		return error;
++
++	if (on)
++		filp->f_flags |= FASYNC;
++	else
++		filp->f_flags &= ~FASYNC;
++	return error;
++}
++
+ /*
+  * When you add any new common ioctls to the switches above and below
+  * please update compat_sys_ioctl() too.
+@@ -97,8 +150,8 @@ static int file_ioctl(struct file *filp, unsigned int cmd,
+ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
+ 	     unsigned long arg)
+ {
+-	unsigned int flag;
+-	int on, error = 0;
++	int error = 0;
++	int __user *argp = (int __user *)arg;
+ 
+ 	switch (cmd) {
+ 	case FIOCLEX:
+@@ -110,43 +163,11 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
+ 		break;
+ 
+ 	case FIONBIO:
+-		error = get_user(on, (int __user *)arg);
+-		if (error)
+-			break;
+-		flag = O_NONBLOCK;
+-#ifdef __sparc__
+-		/* SunOS compatibility item. */
+-		if (O_NONBLOCK != O_NDELAY)
+-			flag |= O_NDELAY;
+-#endif
+-		if (on)
+-			filp->f_flags |= flag;
+-		else
+-			filp->f_flags &= ~flag;
++		error = ioctl_fionbio(filp, argp);
+ 		break;
+ 
+ 	case FIOASYNC:
+-		error = get_user(on, (int __user *)arg);
+-		if (error)
+-			break;
+-		flag = on ? FASYNC : 0;
+-
+-		/* Did FASYNC state change ? */
+-		if ((flag ^ filp->f_flags) & FASYNC) {
+-			if (filp->f_op && filp->f_op->fasync) {
+-				lock_kernel();
+-				error = filp->f_op->fasync(fd, filp, on);
+-				unlock_kernel();
+-			} else
+-				error = -ENOTTY;
+-		}
+-		if (error != 0)
+-			break;
+-
+-		if (on)
+-			filp->f_flags |= FASYNC;
+-		else
+-			filp->f_flags &= ~FASYNC;
++		error = ioctl_fioasync(fd, filp, argp);
+ 		break;
+ 
+ 	case FIOQSIZE:

commit deb21db7788b97a2bccdefe605433ef97f482689
+Author: Erez Zadok 
+Date:   Thu Feb 7 00:13:25 2008 -0800
+
+    VFS: swap do_ioctl and vfs_ioctl names
+    
+    Rename old vfs_ioctl to do_ioctl, because the comment above it clearly
+    indicates that it is an internal function not to be exported to modules;
+    therefore it should have a more traditional do_XXX name.  The new do_ioctl
+    is exported in fs.h but not to modules.
+    
+    Rename the old do_ioctl to vfs_ioctl because the names vfs_XXX should
+    preferably be reserved to callable VFS functions which modules may call, as
+    many other vfs_XXX functions already do.  Export the new vfs_ioctl to GPL
+    modules so others can use it (including Unionfs and eCryptfs).  Add DocBook
+    for new vfs_ioctl.
+    
+    [akpm@linux-foundation.org: fix build]
+    Signed-off-by: Erez Zadok 
+    Cc: Christoph Hellwig 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
+index ffdc022cae64..614bd75b5a4a 100644
+--- a/fs/compat_ioctl.c
++++ b/fs/compat_ioctl.c
+@@ -2986,7 +2986,7 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd,
+ 	}
+ 
+  do_ioctl:
+-	error = vfs_ioctl(filp, fd, cmd, arg);
++	error = do_vfs_ioctl(filp, fd, cmd, arg);
+  out_fput:
+ 	fput_light(filp, fput_needed);
+  out:
+diff --git a/fs/ioctl.c b/fs/ioctl.c
+index 652cacf433ff..e6500cd12258 100644
+--- a/fs/ioctl.c
++++ b/fs/ioctl.c
+@@ -16,8 +16,20 @@
+ 
+ #include 
+ 
+-static long do_ioctl(struct file *filp, unsigned int cmd,
+-		unsigned long arg)
++/**
++ * vfs_ioctl - call filesystem specific ioctl methods
++ * @filp: [in]     open file to invoke ioctl method on
++ * @cmd:  [in]     ioctl command to execute
++ * @arg:  [in/out] command-specific argument for ioctl
++ *
++ * Invokes filesystem specific ->unlocked_ioctl, if one exists; otherwise
++ * invokes * filesystem specific ->ioctl method.  If neither method exists,
++ * returns -ENOTTY.
++ *
++ * Returns 0 on success, -errno on error.
++ */
++long vfs_ioctl(struct file *filp, unsigned int cmd,
++	       unsigned long arg)
+ {
+ 	int error = -ENOTTY;
+ 
+@@ -72,18 +84,18 @@ static int file_ioctl(struct file *filp, unsigned int cmd,
+ 		return put_user(i_size_read(inode) - filp->f_pos, p);
+ 	}
+ 
+-	return do_ioctl(filp, cmd, arg);
++	return vfs_ioctl(filp, cmd, arg);
+ }
+ 
+ /*
+  * When you add any new common ioctls to the switches above and below
+  * please update compat_sys_ioctl() too.
+  *
+- * vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
++ * do_vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
+  * It's just a simple helper for sys_ioctl and compat_sys_ioctl.
+  */
+-int vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
+-	      unsigned long arg)
++int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
++	     unsigned long arg)
+ {
+ 	unsigned int flag;
+ 	int on, error = 0;
+@@ -152,7 +164,7 @@ int vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
+ 		if (S_ISREG(filp->f_path.dentry->d_inode->i_mode))
+ 			error = file_ioctl(filp, cmd, arg);
+ 		else
+-			error = do_ioctl(filp, cmd, arg);
++			error = vfs_ioctl(filp, cmd, arg);
+ 		break;
+ 	}
+ 	return error;
+@@ -172,7 +184,7 @@ asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+ 	if (error)
+ 		goto out_fput;
+ 
+-	error = vfs_ioctl(filp, fd, cmd, arg);
++	error = do_vfs_ioctl(filp, fd, cmd, arg);
+  out_fput:
+ 	fput_light(filp, fput_needed);
+  out:
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 109734bf6377..2925f7011ece 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -1941,7 +1941,9 @@ extern int vfs_stat_fd(int dfd, char __user *, struct kstat *);
+ extern int vfs_lstat_fd(int dfd, char __user *, struct kstat *);
+ extern int vfs_fstat(unsigned int, struct kstat *);
+ 
+-extern int vfs_ioctl(struct file *, unsigned int, unsigned int, unsigned long);
++extern long vfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
++extern int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
++		    unsigned long arg);
+ 
+ extern void get_filesystem(struct file_system_type *fs);
+ extern void put_filesystem(struct file_system_type *fs);

commit c9845ff1df5ba007b576c26c4f1e7ca43b7c7e87
+Author: Erez Zadok 
+Date:   Thu Feb 7 00:13:23 2008 -0800
+
+    VFS: apply coding standards to fs/ioctl.c
+    
+    Signed-off-by: Erez Zadok 
+    Cc: Christoph Hellwig 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/ioctl.c b/fs/ioctl.c
+index c2a773e8620b..652cacf433ff 100644
+--- a/fs/ioctl.c
++++ b/fs/ioctl.c
+@@ -12,8 +12,8 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+-#include 
+ #include 
+ 
+ static long do_ioctl(struct file *filp, unsigned int cmd,
+@@ -45,31 +45,31 @@ static int file_ioctl(struct file *filp, unsigned int cmd,
+ {
+ 	int error;
+ 	int block;
+-	struct inode * inode = filp->f_path.dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	int __user *p = (int __user *)arg;
+ 
+ 	switch (cmd) {
+-		case FIBMAP:
+-		{
+-			struct address_space *mapping = filp->f_mapping;
+-			int res;
+-			/* do we support this mess? */
+-			if (!mapping->a_ops->bmap)
+-				return -EINVAL;
+-			if (!capable(CAP_SYS_RAWIO))
+-				return -EPERM;
+-			if ((error = get_user(block, p)) != 0)
+-				return error;
+-
+-			lock_kernel();
+-			res = mapping->a_ops->bmap(mapping, block);
+-			unlock_kernel();
+-			return put_user(res, p);
+-		}
+-		case FIGETBSZ:
+-			return put_user(inode->i_sb->s_blocksize, p);
+-		case FIONREAD:
+-			return put_user(i_size_read(inode) - filp->f_pos, p);
++	case FIBMAP:
++	{
++		struct address_space *mapping = filp->f_mapping;
++		int res;
++		/* do we support this mess? */
++		if (!mapping->a_ops->bmap)
++			return -EINVAL;
++		if (!capable(CAP_SYS_RAWIO))
++			return -EPERM;
++		error = get_user(block, p);
++		if (error)
++			return error;
++		lock_kernel();
++		res = mapping->a_ops->bmap(mapping, block);
++		unlock_kernel();
++		return put_user(res, p);
++	}
++	case FIGETBSZ:
++		return put_user(inode->i_sb->s_blocksize, p);
++	case FIONREAD:
++		return put_user(i_size_read(inode) - filp->f_pos, p);
+ 	}
+ 
+ 	return do_ioctl(filp, cmd, arg);
+@@ -82,81 +82,85 @@ static int file_ioctl(struct file *filp, unsigned int cmd,
+  * vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
+  * It's just a simple helper for sys_ioctl and compat_sys_ioctl.
+  */
+-int vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, unsigned long arg)
++int vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
++	      unsigned long arg)
+ {
+ 	unsigned int flag;
+ 	int on, error = 0;
+ 
+ 	switch (cmd) {
+-		case FIOCLEX:
+-			set_close_on_exec(fd, 1);
+-			break;
++	case FIOCLEX:
++		set_close_on_exec(fd, 1);
++		break;
+ 
+-		case FIONCLEX:
+-			set_close_on_exec(fd, 0);
+-			break;
++	case FIONCLEX:
++		set_close_on_exec(fd, 0);
++		break;
+ 
+-		case FIONBIO:
+-			if ((error = get_user(on, (int __user *)arg)) != 0)
+-				break;
+-			flag = O_NONBLOCK;
++	case FIONBIO:
++		error = get_user(on, (int __user *)arg);
++		if (error)
++			break;
++		flag = O_NONBLOCK;
+ #ifdef __sparc__
+-			/* SunOS compatibility item. */
+-			if(O_NONBLOCK != O_NDELAY)
+-				flag |= O_NDELAY;
++		/* SunOS compatibility item. */
++		if (O_NONBLOCK != O_NDELAY)
++			flag |= O_NDELAY;
+ #endif
+-			if (on)
+-				filp->f_flags |= flag;
+-			else
+-				filp->f_flags &= ~flag;
++		if (on)
++			filp->f_flags |= flag;
++		else
++			filp->f_flags &= ~flag;
++		break;
++
++	case FIOASYNC:
++		error = get_user(on, (int __user *)arg);
++		if (error)
+ 			break;
+-
+-		case FIOASYNC:
+-			if ((error = get_user(on, (int __user *)arg)) != 0)
+-				break;
+-			flag = on ? FASYNC : 0;
+-
+-			/* Did FASYNC state change ? */
+-			if ((flag ^ filp->f_flags) & FASYNC) {
+-				if (filp->f_op && filp->f_op->fasync) {
+-					lock_kernel();
+-					error = filp->f_op->fasync(fd, filp, on);
+-					unlock_kernel();
+-				}
+-				else error = -ENOTTY;
+-			}
+-			if (error != 0)
+-				break;
+-
+-			if (on)
+-				filp->f_flags |= FASYNC;
+-			else
+-				filp->f_flags &= ~FASYNC;
+-			break;
+-
+-		case FIOQSIZE:
+-			if (S_ISDIR(filp->f_path.dentry->d_inode->i_mode) ||
+-			    S_ISREG(filp->f_path.dentry->d_inode->i_mode) ||
+-			    S_ISLNK(filp->f_path.dentry->d_inode->i_mode)) {
+-				loff_t res = inode_get_bytes(filp->f_path.dentry->d_inode);
+-				error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0;
+-			}
+-			else
++		flag = on ? FASYNC : 0;
++
++		/* Did FASYNC state change ? */
++		if ((flag ^ filp->f_flags) & FASYNC) {
++			if (filp->f_op && filp->f_op->fasync) {
++				lock_kernel();
++				error = filp->f_op->fasync(fd, filp, on);
++				unlock_kernel();
++			} else
+ 				error = -ENOTTY;
++		}
++		if (error != 0)
+ 			break;
+-		default:
+-			if (S_ISREG(filp->f_path.dentry->d_inode->i_mode))
+-				error = file_ioctl(filp, cmd, arg);
+-			else
+-				error = do_ioctl(filp, cmd, arg);
+-			break;
++
++		if (on)
++			filp->f_flags |= FASYNC;
++		else
++			filp->f_flags &= ~FASYNC;
++		break;
++
++	case FIOQSIZE:
++		if (S_ISDIR(filp->f_path.dentry->d_inode->i_mode) ||
++		    S_ISREG(filp->f_path.dentry->d_inode->i_mode) ||
++		    S_ISLNK(filp->f_path.dentry->d_inode->i_mode)) {
++			loff_t res =
++				inode_get_bytes(filp->f_path.dentry->d_inode);
++			error = copy_to_user((loff_t __user *)arg, &res,
++					     sizeof(res)) ? -EFAULT : 0;
++		} else
++			error = -ENOTTY;
++		break;
++	default:
++		if (S_ISREG(filp->f_path.dentry->d_inode->i_mode))
++			error = file_ioctl(filp, cmd, arg);
++		else
++			error = do_ioctl(filp, cmd, arg);
++		break;
+ 	}
+ 	return error;
+ }
+ 
+ asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+ {
+-	struct file * filp;
++	struct file *filp;
+ 	int error = -EBADF;
+ 	int fput_needed;
+ 

commit f79c20f52532d38fd0aee7ef64e138cc1613c484
+Author: Josef 'Jeff' Sipek 
+Date:   Thu Jul 19 01:48:22 2007 -0700
+
+    fs: remove path_walk export
+    
+    Signed-off-by: Josef 'Jeff' Sipek 
+    Cc: Al Viro 
+    Acked-by: Christoph Hellwig 
+    Cc: Trond Myklebust 
+    Cc: Neil Brown 
+    Cc: Michael Halcrow 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/namei.c b/fs/namei.c
+index b9fdda8c0930..a83160acd748 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -1024,7 +1024,7 @@ static int fastcall link_path_walk(const char *name, struct nameidata *nd)
+ 	return result;
+ }
+ 
+-int fastcall path_walk(const char * name, struct nameidata *nd)
++static int fastcall path_walk(const char * name, struct nameidata *nd)
+ {
+ 	current->total_link_count = 0;
+ 	return link_path_walk(name, nd);
+@@ -2809,7 +2809,6 @@ EXPORT_SYMBOL(page_symlink_inode_operations);
+ EXPORT_SYMBOL(path_lookup);
+ EXPORT_SYMBOL(vfs_path_lookup);
+ EXPORT_SYMBOL(path_release);
+-EXPORT_SYMBOL(path_walk);
+ EXPORT_SYMBOL(permission);
+ EXPORT_SYMBOL(vfs_permission);
+ EXPORT_SYMBOL(file_permission);
+diff --git a/include/linux/namei.h b/include/linux/namei.h
+index 18ea81265068..6c38efbd810f 100644
+--- a/include/linux/namei.h
++++ b/include/linux/namei.h
+@@ -71,7 +71,6 @@ extern int FASTCALL(__user_walk_fd(int dfd, const char __user *, unsigned, struc
+ extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *));
+ extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
+ 			   const char *, unsigned int, struct nameidata *);
+-extern int FASTCALL(path_walk(const char *, struct nameidata *));
+ extern void path_release(struct nameidata *);
+ extern void path_release_on_umount(struct nameidata *);
+ 

commit c4a7808fc3d7a346d5d12e0d69d76d66d821488b
+Author: Josef 'Jeff' Sipek 
+Date:   Thu Jul 19 01:48:22 2007 -0700
+
+    fs: mark link_path_walk static
+    
+    Signed-off-by: Josef 'Jeff' Sipek 
+    Cc: Al Viro 
+    Acked-by: Christoph Hellwig 
+    Cc: Trond Myklebust 
+    Cc: Neil Brown 
+    Cc: Michael Halcrow 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/namei.c b/fs/namei.c
+index 3bdb29615a9d..b9fdda8c0930 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -107,6 +107,8 @@
+  * any extra contention...
+  */
+ 
++static int fastcall link_path_walk(const char *name, struct nameidata *nd);
++
+ /* In order to reduce some races, while at the same time doing additional
+  * checking and hopefully speeding things up, we copy filenames to the
+  * kernel data space before using them..
+@@ -998,7 +1000,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
+  * Retry the whole path once, forcing real lookup requests
+  * instead of relying on the dcache.
+  */
+-int fastcall link_path_walk(const char *name, struct nameidata *nd)
++static int fastcall link_path_walk(const char *name, struct nameidata *nd)
+ {
+ 	struct nameidata save = *nd;
+ 	int result;
+diff --git a/include/linux/namei.h b/include/linux/namei.h
+index 2e21af0989d9..18ea81265068 100644
+--- a/include/linux/namei.h
++++ b/include/linux/namei.h
+@@ -72,7 +72,6 @@ extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *));
+ extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
+ 			   const char *, unsigned int, struct nameidata *);
+ extern int FASTCALL(path_walk(const char *, struct nameidata *));
+-extern int FASTCALL(link_path_walk(const char *, struct nameidata *));
+ extern void path_release(struct nameidata *);
+ extern void path_release_on_umount(struct nameidata *);
+ 

commit 16b6287a5286e872abece4f42a6eb5899157a836
+Author: Josef 'Jeff' Sipek 
+Date:   Thu Jul 19 01:48:21 2007 -0700
+
+    nfsctl: use vfs_path_lookup
+    
+    use vfs_path_lookup instead of open-coding the necessary functionality.
+    
+    Signed-off-by: Josef 'Jeff' Sipek 
+    Acked-by: NeilBrown 
+    Cc: Al Viro 
+    Acked-by: Christoph Hellwig 
+    Cc: Trond Myklebust 
+    Cc: Michael Halcrow 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsctl.c b/fs/nfsctl.c
+index c043136a82ca..51f1b31acbf6 100644
+--- a/fs/nfsctl.c
++++ b/fs/nfsctl.c
+@@ -23,19 +23,15 @@
+ static struct file *do_open(char *name, int flags)
+ {
+ 	struct nameidata nd;
++	struct vfsmount *mnt;
+ 	int error;
+ 
+-	nd.mnt = do_kern_mount("nfsd", 0, "nfsd", NULL);
++	mnt = do_kern_mount("nfsd", 0, "nfsd", NULL);
++	if (IS_ERR(mnt))
++		return (struct file *)mnt;
+ 
+-	if (IS_ERR(nd.mnt))
+-		return (struct file *)nd.mnt;
+-
+-	nd.dentry = dget(nd.mnt->mnt_root);
+-	nd.last_type = LAST_ROOT;
+-	nd.flags = 0;
+-	nd.depth = 0;
+-
+-	error = path_walk(name, &nd);
++	error = vfs_path_lookup(mnt->mnt_root, mnt, name, 0, &nd);
++	mntput(mnt);	/* drop do_kern_mount reference */
+ 	if (error)
+ 		return ERR_PTR(error);
+ 

commit 4ac4efc1f5575a268417f80ef4059aee383f8331
+Author: Josef 'Jeff' Sipek 
+Date:   Thu Jul 19 01:48:20 2007 -0700
+
+    sunrpc: use vfs_path_lookup
+    
+    use vfs_path_lookup instead of open-coding the necessary functionality.
+    
+    Signed-off-by: Josef 'Jeff' Sipek 
+    Acked-by: Trond Myklebust 
+    Cc: Al Viro 
+    Acked-by: Christoph Hellwig 
+    Cc: Neil Brown 
+    Cc: Michael Halcrow 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
+index e787b6a43eee..5b2b6fb244f2 100644
+--- a/net/sunrpc/rpc_pipe.c
++++ b/net/sunrpc/rpc_pipe.c
+@@ -460,21 +460,19 @@ static struct dentry_operations rpc_dentry_operations = {
+ static int
+ rpc_lookup_parent(char *path, struct nameidata *nd)
+ {
++	struct vfsmount *mnt;
++
+ 	if (path[0] == '\0')
+ 		return -ENOENT;
+-	nd->mnt = rpc_get_mount();
+-	if (IS_ERR(nd->mnt)) {
++
++	mnt = rpc_get_mount();
++	if (IS_ERR(mnt)) {
+ 		printk(KERN_WARNING "%s: %s failed to mount "
+ 			       "pseudofilesystem \n", __FILE__, __FUNCTION__);
+-		return PTR_ERR(nd->mnt);
++		return PTR_ERR(mnt);
+ 	}
+-	mntget(nd->mnt);
+-	nd->dentry = dget(rpc_mount->mnt_root);
+-	nd->last_type = LAST_ROOT;
+-	nd->flags = LOOKUP_PARENT;
+-	nd->depth = 0;
+ 
+-	if (path_walk(path, nd)) {
++	if (vfs_path_lookup(mnt->mnt_root, mnt, path, LOOKUP_PARENT, nd)) {
+ 		printk(KERN_WARNING "%s: %s failed to find path %s\n",
+ 				__FILE__, __FUNCTION__, path);
+ 		rpc_put_mount();

commit 16f1820028d660d9da9c03b2ae7e98253c11795b
+Author: Josef 'Jeff' Sipek 
+Date:   Thu Jul 19 01:48:18 2007 -0700
+
+    fs: introduce vfs_path_lookup
+    
+    Stackable file systems, among others, frequently need to lookup paths or
+    path components starting from an arbitrary point in the namespace
+    (identified by a dentry and a vfsmount).  Currently, such file systems use
+    lookup_one_len, which is frowned upon [1] as it does not pass the lookup
+    intent along; not passing a lookup intent, for example, can trigger BUG_ON's
+    when stacking on top of NFSv4.
+    
+    The first patch introduces a new lookup function to allow lookup starting
+    from an arbitrary point in the namespace.  This approach has been suggested
+    by Christoph Hellwig [2].
+    
+    The second patch changes sunrpc to use vfs_path_lookup.
+    
+    The third patch changes nfsctl.c to use vfs_path_lookup.
+    
+    The fourth patch marks link_path_walk static.
+    
+    The fifth, and last patch, unexports path_walk because it is no longer
+    unnecessary to call it directly, and using the new vfs_path_lookup is
+    cleaner.
+    
+    For example, the following snippet of code, looks up "some/path/component"
+    in a directory pointed to by parent_{dentry,vfsmnt}:
+    
+    err = vfs_path_lookup(parent_dentry, parent_vfsmnt,
+                          "some/path/component", 0, &nd);
+    if (!err) {
+            /* exits */
+    
+            ...
+    
+            /* once done, release the references */
+            path_release(&nd);
+    } else if (err == -ENOENT) {
+            /* doesn't exist */
+    } else {
+            /* other error */
+    }
+    
+    VFS functions such as lookup_create can be used on the nameidata structure
+    to pass the create intent to the file system.
+    
+    Signed-off-by: Josef 'Jeff' Sipek 
+    Cc: Al Viro 
+    Acked-by: Christoph Hellwig 
+    Cc: Trond Myklebust 
+    Cc: Neil Brown 
+    Cc: Michael Halcrow 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/namei.c b/fs/namei.c
+index defaa47c11d4..3bdb29615a9d 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -1172,6 +1172,37 @@ int fastcall path_lookup(const char *name, unsigned int flags,
+ 	return do_path_lookup(AT_FDCWD, name, flags, nd);
+ }
+ 
++/**
++ * vfs_path_lookup - lookup a file path relative to a dentry-vfsmount pair
++ * @dentry:  pointer to dentry of the base directory
++ * @mnt: pointer to vfs mount of the base directory
++ * @name: pointer to file name
++ * @flags: lookup flags
++ * @nd: pointer to nameidata
++ */
++int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
++		    const char *name, unsigned int flags,
++		    struct nameidata *nd)
++{
++	int retval;
++
++	/* same as do_path_lookup */
++	nd->last_type = LAST_ROOT;
++	nd->flags = flags;
++	nd->depth = 0;
++
++	nd->mnt = mntget(mnt);
++	nd->dentry = dget(dentry);
++
++	retval = path_walk(name, nd);
++	if (unlikely(!retval && !audit_dummy_context() && nd->dentry &&
++				nd->dentry->d_inode))
++		audit_inode(name, nd->dentry->d_inode);
++
++	return retval;
++
++}
++
+ static int __path_lookup_intent_open(int dfd, const char *name,
+ 		unsigned int lookup_flags, struct nameidata *nd,
+ 		int open_flags, int create_mode)
+@@ -2774,6 +2805,7 @@ EXPORT_SYMBOL(__page_symlink);
+ EXPORT_SYMBOL(page_symlink);
+ EXPORT_SYMBOL(page_symlink_inode_operations);
+ EXPORT_SYMBOL(path_lookup);
++EXPORT_SYMBOL(vfs_path_lookup);
+ EXPORT_SYMBOL(path_release);
+ EXPORT_SYMBOL(path_walk);
+ EXPORT_SYMBOL(permission);
+diff --git a/include/linux/namei.h b/include/linux/namei.h
+index b7dd24917f0d..2e21af0989d9 100644
+--- a/include/linux/namei.h
++++ b/include/linux/namei.h
+@@ -69,6 +69,8 @@ extern int FASTCALL(__user_walk_fd(int dfd, const char __user *, unsigned, struc
+ #define user_path_walk_link(name,nd) \
+ 	__user_walk_fd(AT_FDCWD, name, 0, nd)
+ extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *));
++extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
++			   const char *, unsigned int, struct nameidata *);
+ extern int FASTCALL(path_walk(const char *, struct nameidata *));
+ extern int FASTCALL(link_path_walk(const char *, struct nameidata *));
+ extern void path_release(struct nameidata *);

commit 5d91192e667ae34733b9daf6dd5f1d4496d2f441
+Author: Josef 'Jeff' Sipek 
+Date:   Tue Jul 17 04:04:54 2007 -0700
+
+    eCryptfs: Move ecryptfs docs into Documentation/filesystems/
+    
+    Signed-off-by: Josef 'Jeff' Sipek 
+    Acked-by: Michael Halcrow 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/Documentation/ecryptfs.txt b/Documentation/filesystems/ecryptfs.txt
+similarity index 100%
+rename from Documentation/ecryptfs.txt
+rename to Documentation/filesystems/ecryptfs.txt

commit c2b38989cf2b0c003a9cf57efc833ab16d33901e
+Author: Josef 'Jeff' Sipek 
+Date:   Thu May 24 12:21:43 2007 -0400
+
+    Documentation: Fix up docs still talking about i_sem
+    
+    .. it got changed to 'i_mutex' some time ago.
+    
+    Signed-off-by: Josef 'Jeff' Sipek 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/Documentation/filesystems/directory-locking b/Documentation/filesystems/directory-locking
+index d7099a9266fb..ff7b611abf33 100644
+--- a/Documentation/filesystems/directory-locking
++++ b/Documentation/filesystems/directory-locking
+@@ -1,5 +1,6 @@
+ 	Locking scheme used for directory operations is based on two
+-kinds of locks - per-inode (->i_sem) and per-filesystem (->s_vfs_rename_sem).
++kinds of locks - per-inode (->i_mutex) and per-filesystem
++(->s_vfs_rename_mutex).
+ 
+ 	For our purposes all operations fall in 5 classes:
+ 
+@@ -63,7 +64,7 @@ objects - A < B iff A is an ancestor of B.
+ attempt to acquire some lock and already holds at least one lock.  Let's
+ consider the set of contended locks.  First of all, filesystem lock is
+ not contended, since any process blocked on it is not holding any locks.
+-Thus all processes are blocked on ->i_sem.
++Thus all processes are blocked on ->i_mutex.
+ 
+ 	Non-directory objects are not contended due to (3).  Thus link
+ creation can't be a part of deadlock - it can't be blocked on source
+diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting
+index 5531694059ab..dac45c92d872 100644
+--- a/Documentation/filesystems/porting
++++ b/Documentation/filesystems/porting
+@@ -107,7 +107,7 @@ free to drop it...
+ ---
+ [informational]
+ 
+-->link() callers hold ->i_sem on the object we are linking to.  Some of your
++->link() callers hold ->i_mutex on the object we are linking to.  Some of your
+ problems might be over...
+ 
+ ---
+@@ -130,9 +130,9 @@ went in - and hadn't been documented ;-/).  Just remove it from fs_flags
+ ---
+ [mandatory]
+ 
+-->setattr() is called without BKL now.  Caller _always_ holds ->i_sem, so
+-watch for ->i_sem-grabbing code that might be used by your ->setattr().
+-Callers of notify_change() need ->i_sem now.
++->setattr() is called without BKL now.  Caller _always_ holds ->i_mutex, so
++watch for ->i_mutex-grabbing code that might be used by your ->setattr().
++Callers of notify_change() need ->i_mutex now.
+ 
+ ---
+ [recommended]

commit 2dfdd266b9a2f2d93a3fdbee89969f6ea9ec5377
+Author: Josef 'Jeff' Sipek 
+Date:   Wed May 9 02:33:41 2007 -0700
+
+    fs: use path_walk in do_path_lookup
+    
+    Since path_walk sets the total_link_count to 0 and calls link_path_walk, we
+    can just call path_walk directly.
+    
+    Signed-off-by: Josef 'Jeff' Sipek 
+    Acked-by: Christoph Hellwig 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/namei.c b/fs/namei.c
+index 19f178ec5744..b3780e3fc88e 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -1152,8 +1152,8 @@ static int fastcall do_path_lookup(int dfd, const char *name,
+ 
+ 		fput_light(file, fput_needed);
+ 	}
+-	current->total_link_count = 0;
+-	retval = link_path_walk(name, nd);
++
++	retval = path_walk(name, nd);
+ out:
+ 	if (unlikely(!retval && !audit_dummy_context() && nd->dentry &&
+ 				nd->dentry->d_inode))

commit 62ce39c531860aee6c12128c629b0a82f656a306
+Author: Josef 'Jeff' Sipek 
+Date:   Wed May 9 02:33:41 2007 -0700
+
+    fs: fix indentation in do_path_lookup
+    
+    Signed-off-by: Josef 'Jeff' Sipek 
+    Acked-by: Christoph Hellwig 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/namei.c b/fs/namei.c
+index 856b2f5da51d..19f178ec5744 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -1155,11 +1155,9 @@ static int fastcall do_path_lookup(int dfd, const char *name,
+ 	current->total_link_count = 0;
+ 	retval = link_path_walk(name, nd);
+ out:
+-	if (likely(retval == 0)) {
+-		if (unlikely(!audit_dummy_context() && nd && nd->dentry &&
++	if (unlikely(!retval && !audit_dummy_context() && nd->dentry &&
+ 				nd->dentry->d_inode))
+ 		audit_inode(name, nd->dentry->d_inode);
+-	}
+ out_fail:
+ 	return retval;
+ 

commit 2396a22e0989df6038996506bfbf7a57f116c299
+Author: Josef 'Jeff' Sipek 
+Date:   Mon May 7 00:33:18 2007 -0700
+
+    [NET] net/core: Fix error handling
+    
+    Upon failure to register "ptype" procfs entry, "softnet_stat" was not
+    removed, and an incorrect attempt was made to remove the "ptype" entry.
+    
+    Signed-off-by: Josef 'Jeff' Sipek 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/core/dev.c b/net/core/dev.c
+index f27d4ab181e6..4317c1be4d3f 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -2377,9 +2377,9 @@ static int __init dev_proc_init(void)
+ out:
+ 	return rc;
+ out_softnet:
+-	proc_net_remove("softnet_stat");
+-out_dev2:
+ 	proc_net_remove("ptype");
++out_dev2:
++	proc_net_remove("softnet_stat");
+ out_dev:
+ 	proc_net_remove("dev");
+ 	goto out;

commit a6e6df25ec6751f4f73784398ab7d43cf9d2019f
+Author: Erez Zadok 
+Date:   Sun Feb 18 23:57:45 2007 -0500
+
+    [PATCH] fs/stack.c: Copy i_nlink after all other attributes are copied
+    
+    A user-specified get_nlinks may depend on other inode attributes.
+    
+    Cc: Michael Halcrow 
+    Signed-off-by: Erez Zadok 
+    Signed-off-by: Josef 'Jeff' Sipek 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/stack.c b/fs/stack.c
+index 8ffb880d2f46..67716f6a1a4a 100644
+--- a/fs/stack.c
++++ b/fs/stack.c
+@@ -20,11 +20,6 @@ EXPORT_SYMBOL_GPL(fsstack_copy_inode_size);
+ void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
+ 				int (*get_nlinks)(struct inode *))
+ {
+-	if (!get_nlinks)
+-		dest->i_nlink = src->i_nlink;
+-	else
+-		dest->i_nlink = (*get_nlinks)(dest);
+-
+ 	dest->i_mode = src->i_mode;
+ 	dest->i_uid = src->i_uid;
+ 	dest->i_gid = src->i_gid;
+@@ -34,5 +29,14 @@ void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
+ 	dest->i_ctime = src->i_ctime;
+ 	dest->i_blkbits = src->i_blkbits;
+ 	dest->i_flags = src->i_flags;
++
++	/*
++	 * Update the nlinks AFTER updating the above fields, because the
++	 * get_links callback may depend on them.
++	 */
++	if (!get_nlinks)
++		dest->i_nlink = src->i_nlink;
++	else
++		dest->i_nlink = (*get_nlinks)(dest);
+ }
+ EXPORT_SYMBOL_GPL(fsstack_copy_attr_all);

commit b0957f1a3a7687bfaf5b0bfe402b50985ea2f06b
+Author: Josef 'Jeff' Sipek 
+Date:   Tue Feb 13 13:26:23 2007 +0100
+
+    [PATCH] x86-64: Fix preprocessor condition
+    
+    Old code was legal standard C, but apparently not sparse-C.
+    
+    Signed-off-by: Josef 'Jeff' Sipek 
+    Signed-off-by: Andi Kleen 
+
+diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
+index f5d84bb7c948..de2cd9a2303a 100644
+--- a/include/asm-x86_64/io.h
++++ b/include/asm-x86_64/io.h
+@@ -100,7 +100,7 @@ __OUTS(l)
+ 
+ #define IO_SPACE_LIMIT 0xffff
+ 
+-#if defined(__KERNEL__) && __x86_64__
++#if defined(__KERNEL__) && defined(__x86_64__)
+ 
+ #include 
+ 

commit ee9b6d61a2a43c5952eb43283f8db284a4e70b8a
+Author: Josef 'Jeff' Sipek 
+Date:   Mon Feb 12 00:55:41 2007 -0800
+
+    [PATCH] Mark struct super_operations const
+    
+    This patch is inspired by Arjan's "Patch series to mark struct
+    file_operations and struct inode_operations const".
+    
+    Compile tested with gcc & sparse.
+    
+    Signed-off-by: Josef 'Jeff' Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
+index 63320d4e15d2..0ec42f665457 100644
+--- a/fs/9p/vfs_super.c
++++ b/fs/9p/vfs_super.c
+@@ -45,7 +45,7 @@
+ #include "fid.h"
+ 
+ static void v9fs_clear_inode(struct inode *);
+-static struct super_operations v9fs_super_ops;
++static const struct super_operations v9fs_super_ops;
+ 
+ /**
+  * v9fs_clear_inode - release an inode
+@@ -263,7 +263,7 @@ v9fs_umount_begin(struct vfsmount *vfsmnt, int flags)
+ 		v9fs_session_cancel(v9ses);
+ }
+ 
+-static struct super_operations v9fs_super_ops = {
++static const struct super_operations v9fs_super_ops = {
+ 	.statfs = simple_statfs,
+ 	.clear_inode = v9fs_clear_inode,
+ 	.show_options = v9fs_show_options,
+diff --git a/fs/adfs/super.c b/fs/adfs/super.c
+index 5023351a7afe..2e5f2c8371ee 100644
+--- a/fs/adfs/super.c
++++ b/fs/adfs/super.c
+@@ -254,7 +254,7 @@ static void destroy_inodecache(void)
+ 	kmem_cache_destroy(adfs_inode_cachep);
+ }
+ 
+-static struct super_operations adfs_sops = {
++static const struct super_operations adfs_sops = {
+ 	.alloc_inode	= adfs_alloc_inode,
+ 	.destroy_inode	= adfs_destroy_inode,
+ 	.write_inode	= adfs_write_inode,
+diff --git a/fs/affs/super.c b/fs/affs/super.c
+index 3de93e799949..a324045d8554 100644
+--- a/fs/affs/super.c
++++ b/fs/affs/super.c
+@@ -112,7 +112,7 @@ static void destroy_inodecache(void)
+ 	kmem_cache_destroy(affs_inode_cachep);
+ }
+ 
+-static struct super_operations affs_sops = {
++static const struct super_operations affs_sops = {
+ 	.alloc_inode	= affs_alloc_inode,
+ 	.destroy_inode	= affs_destroy_inode,
+ 	.read_inode	= affs_read_inode,
+diff --git a/fs/afs/super.c b/fs/afs/super.c
+index 18d9b77ba40f..eb7e32349da3 100644
+--- a/fs/afs/super.c
++++ b/fs/afs/super.c
+@@ -56,7 +56,7 @@ struct file_system_type afs_fs_type = {
+ 	.fs_flags	= FS_BINARY_MOUNTDATA,
+ };
+ 
+-static struct super_operations afs_super_ops = {
++static const struct super_operations afs_super_ops = {
+ 	.statfs		= simple_statfs,
+ 	.alloc_inode	= afs_alloc_inode,
+ 	.drop_inode	= generic_delete_inode,
+diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
+index f968d1342808..aa0b61ff8270 100644
+--- a/fs/autofs/inode.c
++++ b/fs/autofs/inode.c
+@@ -52,7 +52,7 @@ void autofs_kill_sb(struct super_block *sb)
+ 
+ static void autofs_read_inode(struct inode *inode);
+ 
+-static struct super_operations autofs_sops = {
++static const struct super_operations autofs_sops = {
+ 	.read_inode	= autofs_read_inode,
+ 	.statfs		= simple_statfs,
+ };
+diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
+index e8f6c5ad3e90..5e458e096ef6 100644
+--- a/fs/autofs4/inode.c
++++ b/fs/autofs4/inode.c
+@@ -196,7 +196,7 @@ static int autofs4_show_options(struct seq_file *m, struct vfsmount *mnt)
+ 	return 0;
+ }
+ 
+-static struct super_operations autofs4_sops = {
++static const struct super_operations autofs4_sops = {
+ 	.statfs		= simple_statfs,
+ 	.show_options	= autofs4_show_options,
+ };
+diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
+index 134c99941a63..93d6219243ad 100644
+--- a/fs/bfs/inode.c
++++ b/fs/bfs/inode.c
+@@ -270,7 +270,7 @@ static void destroy_inodecache(void)
+ 	kmem_cache_destroy(bfs_inode_cachep);
+ }
+ 
+-static struct super_operations bfs_sops = {
++static const struct super_operations bfs_sops = {
+ 	.alloc_inode	= bfs_alloc_inode,
+ 	.destroy_inode	= bfs_destroy_inode,
+ 	.read_inode	= bfs_read_inode,
+diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
+index c2e08252af35..e6f57990b121 100644
+--- a/fs/binfmt_misc.c
++++ b/fs/binfmt_misc.c
+@@ -719,7 +719,7 @@ static const struct file_operations bm_status_operations = {
+ 
+ /* Superblock handling */
+ 
+-static struct super_operations s_ops = {
++static const struct super_operations s_ops = {
+ 	.statfs		= simple_statfs,
+ 	.clear_inode	= bm_clear_inode,
+ };
+diff --git a/fs/block_dev.c b/fs/block_dev.c
+index fc7028b685f2..0c59b703e9d5 100644
+--- a/fs/block_dev.c
++++ b/fs/block_dev.c
+@@ -489,7 +489,7 @@ static void bdev_clear_inode(struct inode *inode)
+ 	spin_unlock(&bdev_lock);
+ }
+ 
+-static struct super_operations bdev_sops = {
++static const struct super_operations bdev_sops = {
+ 	.statfs = simple_statfs,
+ 	.alloc_inode = bdev_alloc_inode,
+ 	.destroy_inode = bdev_destroy_inode,
+diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
+index 481e84f5f361..e8287c4c6eb3 100644
+--- a/fs/cifs/cifsfs.c
++++ b/fs/cifs/cifsfs.c
+@@ -64,7 +64,7 @@ extern struct task_struct * oplockThread; /* remove sparse warning */
+ struct task_struct * oplockThread = NULL;
+ extern struct task_struct * dnotifyThread; /* remove sparse warning */
+ struct task_struct * dnotifyThread = NULL;
+-static struct super_operations cifs_super_ops; 
++static const struct super_operations cifs_super_ops;
+ unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
+ module_param(CIFSMaxBufSize, int, 0);
+ MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048");
+@@ -453,7 +453,7 @@ static int cifs_remount(struct super_block *sb, int *flags, char *data)
+ 	return 0;
+ }
+ 
+-static struct super_operations cifs_super_ops = {
++static const struct super_operations cifs_super_ops = {
+ 	.read_inode = cifs_read_inode,
+ 	.put_super = cifs_put_super,
+ 	.statfs = cifs_statfs,
+diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
+index ab9e20a863f3..01ae24af9cfd 100644
+--- a/fs/cifs/cifsfs.h
++++ b/fs/cifs/cifsfs.h
+@@ -36,7 +36,7 @@ extern const struct address_space_operations cifs_addr_ops;
+ extern const struct address_space_operations cifs_addr_ops_smallbuf;
+ 
+ /* Functions related to super block operations */
+-/* extern struct super_operations cifs_super_ops;*/
++/* extern const struct super_operations cifs_super_ops;*/
+ extern void cifs_read_inode(struct inode *);
+ extern void cifs_delete_inode(struct inode *);
+ /* extern void cifs_write_inode(struct inode *); *//* BB not needed yet */
+diff --git a/fs/coda/inode.c b/fs/coda/inode.c
+index 1562515efdb5..614175a3b02e 100644
+--- a/fs/coda/inode.c
++++ b/fs/coda/inode.c
+@@ -90,7 +90,7 @@ static int coda_remount(struct super_block *sb, int *flags, char *data)
+ }
+ 
+ /* exported operations */
+-static struct super_operations coda_super_operations =
++static const struct super_operations coda_super_operations =
+ {
+ 	.alloc_inode	= coda_alloc_inode,
+ 	.destroy_inode	= coda_destroy_inode,
+diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c
+index ed678529ebb2..6f573004cd7d 100644
+--- a/fs/configfs/mount.c
++++ b/fs/configfs/mount.c
+@@ -41,7 +41,7 @@ struct super_block * configfs_sb = NULL;
+ struct kmem_cache *configfs_dir_cachep;
+ static int configfs_mnt_count = 0;
+ 
+-static struct super_operations configfs_ops = {
++static const struct super_operations configfs_ops = {
+ 	.statfs		= simple_statfs,
+ 	.drop_inode	= generic_delete_inode,
+ };
+diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
+index 0367d200a2de..facd0c89be8f 100644
+--- a/fs/cramfs/inode.c
++++ b/fs/cramfs/inode.c
+@@ -27,7 +27,7 @@
+ 
+ #include 
+ 
+-static struct super_operations cramfs_ops;
++static const struct super_operations cramfs_ops;
+ static const struct inode_operations cramfs_dir_inode_operations;
+ static const struct file_operations cramfs_directory_operations;
+ static const struct address_space_operations cramfs_aops;
+@@ -522,7 +522,7 @@ static const struct inode_operations cramfs_dir_inode_operations = {
+ 	.lookup		= cramfs_lookup,
+ };
+ 
+-static struct super_operations cramfs_ops = {
++static const struct super_operations cramfs_ops = {
+ 	.put_super	= cramfs_put_super,
+ 	.remount_fs	= cramfs_remount,
+ 	.statfs		= cramfs_statfs,
+diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
+index 5f7b5a6025bf..643e57b622bd 100644
+--- a/fs/devpts/inode.c
++++ b/fs/devpts/inode.c
+@@ -91,7 +91,7 @@ static int devpts_remount(struct super_block *sb, int *flags, char *data)
+ 	return 0;
+ }
+ 
+-static struct super_operations devpts_sops = {
++static const struct super_operations devpts_sops = {
+ 	.statfs		= simple_statfs,
+ 	.remount_fs	= devpts_remount,
+ };
+diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
+index 275445d17162..b3609b7cdf11 100644
+--- a/fs/ecryptfs/ecryptfs_kernel.h
++++ b/fs/ecryptfs/ecryptfs_kernel.h
+@@ -449,7 +449,7 @@ extern const struct file_operations ecryptfs_dir_fops;
+ extern const struct inode_operations ecryptfs_main_iops;
+ extern const struct inode_operations ecryptfs_dir_iops;
+ extern const struct inode_operations ecryptfs_symlink_iops;
+-extern struct super_operations ecryptfs_sops;
++extern const struct super_operations ecryptfs_sops;
+ extern struct dentry_operations ecryptfs_dops;
+ extern struct address_space_operations ecryptfs_aops;
+ extern int ecryptfs_verbosity;
+diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c
+index eaa5daaf106e..7b3f0cc09a6f 100644
+--- a/fs/ecryptfs/super.c
++++ b/fs/ecryptfs/super.c
+@@ -168,7 +168,7 @@ static int ecryptfs_show_options(struct seq_file *m, struct vfsmount *mnt)
+ 	return rc;
+ }
+ 
+-struct super_operations ecryptfs_sops = {
++const struct super_operations ecryptfs_sops = {
+ 	.alloc_inode = ecryptfs_alloc_inode,
+ 	.destroy_inode = ecryptfs_destroy_inode,
+ 	.drop_inode = generic_delete_inode,
+diff --git a/fs/efs/super.c b/fs/efs/super.c
+index dfebf21289f4..c2235e46edcd 100644
+--- a/fs/efs/super.c
++++ b/fs/efs/super.c
+@@ -105,7 +105,7 @@ static int efs_remount(struct super_block *sb, int *flags, char *data)
+ 	return 0;
+ }
+ 
+-static struct super_operations efs_superblock_operations = {
++static const struct super_operations efs_superblock_operations = {
+ 	.alloc_inode	= efs_alloc_inode,
+ 	.destroy_inode	= efs_destroy_inode,
+ 	.read_inode	= efs_read_inode,
+diff --git a/fs/ext2/super.c b/fs/ext2/super.c
+index daaa243eee9b..a046a419d8af 100644
+--- a/fs/ext2/super.c
++++ b/fs/ext2/super.c
+@@ -231,7 +231,7 @@ static ssize_t ext2_quota_read(struct super_block *sb, int type, char *data, siz
+ static ssize_t ext2_quota_write(struct super_block *sb, int type, const char *data, size_t len, loff_t off);
+ #endif
+ 
+-static struct super_operations ext2_sops = {
++static const struct super_operations ext2_sops = {
+ 	.alloc_inode	= ext2_alloc_inode,
+ 	.destroy_inode	= ext2_destroy_inode,
+ 	.read_inode	= ext2_read_inode,
+diff --git a/fs/ext3/super.c b/fs/ext3/super.c
+index a0623a84a4b2..4a4fcd6868c7 100644
+--- a/fs/ext3/super.c
++++ b/fs/ext3/super.c
+@@ -639,7 +639,7 @@ static struct quotactl_ops ext3_qctl_operations = {
+ };
+ #endif
+ 
+-static struct super_operations ext3_sops = {
++static const struct super_operations ext3_sops = {
+ 	.alloc_inode	= ext3_alloc_inode,
+ 	.destroy_inode	= ext3_destroy_inode,
+ 	.read_inode	= ext3_read_inode,
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index c63a18b574dd..61c4718e4a53 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -690,7 +690,7 @@ static struct quotactl_ops ext4_qctl_operations = {
+ };
+ #endif
+ 
+-static struct super_operations ext4_sops = {
++static const struct super_operations ext4_sops = {
+ 	.alloc_inode	= ext4_alloc_inode,
+ 	.destroy_inode	= ext4_destroy_inode,
+ 	.read_inode	= ext4_read_inode,
+diff --git a/fs/fat/inode.c b/fs/fat/inode.c
+index f268fec6ed0a..761073544217 100644
+--- a/fs/fat/inode.c
++++ b/fs/fat/inode.c
+@@ -618,7 +618,7 @@ int fat_sync_inode(struct inode *inode)
+ EXPORT_SYMBOL_GPL(fat_sync_inode);
+ 
+ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt);
+-static struct super_operations fat_sops = {
++static const struct super_operations fat_sops = {
+ 	.alloc_inode	= fat_alloc_inode,
+ 	.destroy_inode	= fat_destroy_inode,
+ 	.write_inode	= fat_write_inode,
+diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
+index ac28b0835ffc..647d600f0bc8 100644
+--- a/fs/freevxfs/vxfs_super.c
++++ b/fs/freevxfs/vxfs_super.c
+@@ -59,7 +59,7 @@ static void		vxfs_put_super(struct super_block *);
+ static int		vxfs_statfs(struct dentry *, struct kstatfs *);
+ static int		vxfs_remount(struct super_block *, int *, char *);
+ 
+-static struct super_operations vxfs_super_ops = {
++static const struct super_operations vxfs_super_ops = {
+ 	.read_inode =		vxfs_read_inode,
+ 	.clear_inode =		vxfs_clear_inode,
+ 	.put_super =		vxfs_put_super,
+diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
+index 220255110d76..5ab8e50e7808 100644
+--- a/fs/fuse/inode.c
++++ b/fs/fuse/inode.c
+@@ -446,7 +446,7 @@ static struct inode *get_root_inode(struct super_block *sb, unsigned mode)
+ 	return fuse_iget(sb, 1, 0, &attr);
+ }
+ 
+-static struct super_operations fuse_super_operations = {
++static const struct super_operations fuse_super_operations = {
+ 	.alloc_inode    = fuse_alloc_inode,
+ 	.destroy_inode  = fuse_destroy_inode,
+ 	.read_inode	= fuse_read_inode,
+diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c
+index 47369d011214..b89999d3a767 100644
+--- a/fs/gfs2/ops_super.c
++++ b/fs/gfs2/ops_super.c
+@@ -468,7 +468,7 @@ static void gfs2_destroy_inode(struct inode *inode)
+ 	kmem_cache_free(gfs2_inode_cachep, inode);
+ }
+ 
+-struct super_operations gfs2_super_ops = {
++const struct super_operations gfs2_super_ops = {
+ 	.alloc_inode		= gfs2_alloc_inode,
+ 	.destroy_inode		= gfs2_destroy_inode,
+ 	.write_inode		= gfs2_write_inode,
+diff --git a/fs/gfs2/ops_super.h b/fs/gfs2/ops_super.h
+index 9de73f042f78..442a274c6272 100644
+--- a/fs/gfs2/ops_super.h
++++ b/fs/gfs2/ops_super.h
+@@ -12,6 +12,6 @@
+ 
+ #include 
+ 
+-extern struct super_operations gfs2_super_ops;
++extern const struct super_operations gfs2_super_ops;
+ 
+ #endif /* __OPS_SUPER_DOT_H__ */
+diff --git a/fs/hfs/super.c b/fs/hfs/super.c
+index a36987966004..623f509f1d47 100644
+--- a/fs/hfs/super.c
++++ b/fs/hfs/super.c
+@@ -154,7 +154,7 @@ static void hfs_destroy_inode(struct inode *inode)
+ 	kmem_cache_free(hfs_inode_cachep, HFS_I(inode));
+ }
+ 
+-static struct super_operations hfs_super_operations = {
++static const struct super_operations hfs_super_operations = {
+ 	.alloc_inode	= hfs_alloc_inode,
+ 	.destroy_inode	= hfs_destroy_inode,
+ 	.write_inode	= hfs_write_inode,
+diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
+index 0f513c6bf843..5a282f64c637 100644
+--- a/fs/hfsplus/super.c
++++ b/fs/hfsplus/super.c
+@@ -260,7 +260,7 @@ static int hfsplus_remount(struct super_block *sb, int *flags, char *data)
+ 	return 0;
+ }
+ 
+-static struct super_operations hfsplus_sops = {
++static const struct super_operations hfsplus_sops = {
+ 	.alloc_inode	= hfsplus_alloc_inode,
+ 	.destroy_inode	= hfsplus_destroy_inode,
+ 	.read_inode	= hfsplus_read_inode,
+diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
+index fec208db5e46..e965eb11d76f 100644
+--- a/fs/hostfs/hostfs_kern.c
++++ b/fs/hostfs/hostfs_kern.c
+@@ -309,7 +309,7 @@ static void hostfs_read_inode(struct inode *inode)
+ 	read_inode(inode);
+ }
+ 
+-static struct super_operations hostfs_sbops = {
++static const struct super_operations hostfs_sbops = {
+ 	.alloc_inode	= hostfs_alloc_inode,
+ 	.drop_inode	= generic_delete_inode,
+ 	.delete_inode   = hostfs_delete_inode,
+diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
+index d4abc1a1d566..e0174e338526 100644
+--- a/fs/hpfs/super.c
++++ b/fs/hpfs/super.c
+@@ -426,7 +426,7 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
+ 
+ /* Super operations */
+ 
+-static struct super_operations hpfs_sops =
++static const struct super_operations hpfs_sops =
+ {
+ 	.alloc_inode	= hpfs_alloc_inode,
+ 	.destroy_inode	= hpfs_destroy_inode,
+diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c
+index bd7116816314..affb7412125e 100644
+--- a/fs/hppfs/hppfs_kern.c
++++ b/fs/hppfs/hppfs_kern.c
+@@ -43,7 +43,7 @@ static inline struct hppfs_inode_info *HPPFS_I(struct inode *inode)
+ 
+ #define HPPFS_SUPER_MAGIC 0xb00000ee
+ 
+-static struct super_operations hppfs_sbops;
++static const struct super_operations hppfs_sbops;
+ 
+ static int is_pid(struct dentry *dentry)
+ {
+@@ -649,7 +649,7 @@ static void hppfs_destroy_inode(struct inode *inode)
+ 	kfree(HPPFS_I(inode));
+ }
+ 
+-static struct super_operations hppfs_sbops = {
++static const struct super_operations hppfs_sbops = {
+ 	.alloc_inode	= hppfs_alloc_inode,
+ 	.destroy_inode	= hppfs_destroy_inode,
+ 	.read_inode	= hppfs_read_inode,
+diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
+index 26ba81fc7fab..8c718a3d413f 100644
+--- a/fs/hugetlbfs/inode.c
++++ b/fs/hugetlbfs/inode.c
+@@ -33,7 +33,7 @@
+ /* some random number */
+ #define HUGETLBFS_MAGIC	0x958458f6
+ 
+-static struct super_operations hugetlbfs_ops;
++static const struct super_operations hugetlbfs_ops;
+ static const struct address_space_operations hugetlbfs_aops;
+ const struct file_operations hugetlbfs_file_operations;
+ static const struct inode_operations hugetlbfs_dir_inode_operations;
+@@ -580,7 +580,7 @@ static const struct inode_operations hugetlbfs_inode_operations = {
+ 	.setattr	= hugetlbfs_setattr,
+ };
+ 
+-static struct super_operations hugetlbfs_ops = {
++static const struct super_operations hugetlbfs_ops = {
+ 	.alloc_inode    = hugetlbfs_alloc_inode,
+ 	.destroy_inode  = hugetlbfs_destroy_inode,
+ 	.statfs		= hugetlbfs_statfs,
+diff --git a/fs/inode.c b/fs/inode.c
+index 5e32432a7608..5abb097ab1b0 100644
+--- a/fs/inode.c
++++ b/fs/inode.c
+@@ -1000,7 +1000,7 @@ EXPORT_SYMBOL(remove_inode_hash);
+  */
+ void generic_delete_inode(struct inode *inode)
+ {
+-	struct super_operations *op = inode->i_sb->s_op;
++	const struct super_operations *op = inode->i_sb->s_op;
+ 
+ 	list_del_init(&inode->i_list);
+ 	list_del_init(&inode->i_sb_list);
+@@ -1093,7 +1093,7 @@ EXPORT_SYMBOL_GPL(generic_drop_inode);
+  */
+ static inline void iput_final(struct inode *inode)
+ {
+-	struct super_operations *op = inode->i_sb->s_op;
++	const struct super_operations *op = inode->i_sb->s_op;
+ 	void (*drop)(struct inode *) = generic_drop_inode;
+ 
+ 	if (op && op->drop_inode)
+@@ -1113,7 +1113,7 @@ static inline void iput_final(struct inode *inode)
+ void iput(struct inode *inode)
+ {
+ 	if (inode) {
+-		struct super_operations *op = inode->i_sb->s_op;
++		const struct super_operations *op = inode->i_sb->s_op;
+ 
+ 		BUG_ON(inode->i_state == I_CLEAR);
+ 
+diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
+index ea55b6c469ec..64a96cdfe3a4 100644
+--- a/fs/isofs/inode.c
++++ b/fs/isofs/inode.c
+@@ -106,7 +106,7 @@ static int isofs_remount(struct super_block *sb, int *flags, char *data)
+ 	return 0;
+ }
+ 
+-static struct super_operations isofs_sops = {
++static const struct super_operations isofs_sops = {
+ 	.alloc_inode	= isofs_alloc_inode,
+ 	.destroy_inode	= isofs_destroy_inode,
+ 	.read_inode	= isofs_read_inode,
+diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
+index fe3347defe6c..9602b925da08 100644
+--- a/fs/jffs/inode-v23.c
++++ b/fs/jffs/inode-v23.c
+@@ -54,7 +54,7 @@
+ 
+ static int jffs_remove(struct inode *dir, struct dentry *dentry, int type);
+ 
+-static struct super_operations jffs_ops;
++static const struct super_operations jffs_ops;
+ static const struct file_operations jffs_file_operations;
+ static const struct inode_operations jffs_file_inode_operations;
+ static const struct file_operations jffs_dir_operations;
+@@ -1774,7 +1774,7 @@ static int jffs_remount(struct super_block *sb, int *flags, char *data)
+ 	return 0;
+ }
+ 
+-static struct super_operations jffs_ops =
++static const struct super_operations jffs_ops =
+ {
+ 	.read_inode	= jffs_read_inode,
+ 	.delete_inode 	= jffs_delete_inode,
+diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
+index 08a0e6c49e61..cc7e8e71ad46 100644
+--- a/fs/jffs2/super.c
++++ b/fs/jffs2/super.c
+@@ -66,7 +66,7 @@ static int jffs2_sync_fs(struct super_block *sb, int wait)
+ 	return 0;
+ }
+ 
+-static struct super_operations jffs2_super_operations =
++static const struct super_operations jffs2_super_operations =
+ {
+ 	.alloc_inode =	jffs2_alloc_inode,
+ 	.destroy_inode =jffs2_destroy_inode,
+diff --git a/fs/jfs/super.c b/fs/jfs/super.c
+index 846ac8f34513..52d73d54a931 100644
+--- a/fs/jfs/super.c
++++ b/fs/jfs/super.c
+@@ -46,7 +46,7 @@ MODULE_LICENSE("GPL");
+ 
+ static struct kmem_cache * jfs_inode_cachep;
+ 
+-static struct super_operations jfs_super_operations;
++static const struct super_operations jfs_super_operations;
+ static struct export_operations jfs_export_operations;
+ static struct file_system_type jfs_fs_type;
+ 
+@@ -716,7 +716,7 @@ static ssize_t jfs_quota_write(struct super_block *sb, int type,
+ 
+ #endif
+ 
+-static struct super_operations jfs_super_operations = {
++static const struct super_operations jfs_super_operations = {
+ 	.alloc_inode	= jfs_alloc_inode,
+ 	.destroy_inode	= jfs_destroy_inode,
+ 	.read_inode	= jfs_read_inode,
+diff --git a/fs/libfs.c b/fs/libfs.c
+index 0f4ee02e0b16..7d487047dbb8 100644
+--- a/fs/libfs.c
++++ b/fs/libfs.c
+@@ -195,11 +195,11 @@ const struct inode_operations simple_dir_inode_operations = {
+  * will never be mountable)
+  */
+ int get_sb_pseudo(struct file_system_type *fs_type, char *name,
+-	struct super_operations *ops, unsigned long magic,
++	const struct super_operations *ops, unsigned long magic,
+ 	struct vfsmount *mnt)
+ {
+ 	struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
+-	static struct super_operations default_ops = {.statfs = simple_statfs};
++	static const struct super_operations default_ops = {.statfs = simple_statfs};
+ 	struct dentry *dentry;
+ 	struct inode *root;
+ 	struct qstr d_name = {.name = name, .len = strlen(name)};
+diff --git a/fs/minix/inode.c b/fs/minix/inode.c
+index e56822bff948..92e383af3709 100644
+--- a/fs/minix/inode.c
++++ b/fs/minix/inode.c
+@@ -95,7 +95,7 @@ static void destroy_inodecache(void)
+ 	kmem_cache_destroy(minix_inode_cachep);
+ }
+ 
+-static struct super_operations minix_sops = {
++static const struct super_operations minix_sops = {
+ 	.alloc_inode	= minix_alloc_inode,
+ 	.destroy_inode	= minix_destroy_inode,
+ 	.read_inode	= minix_read_inode,
+diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
+index 730433f3d237..14939ddf74f1 100644
+--- a/fs/ncpfs/inode.c
++++ b/fs/ncpfs/inode.c
+@@ -90,7 +90,7 @@ static int ncp_remount(struct super_block *sb, int *flags, char* data)
+ 	return 0;
+ }
+ 
+-static struct super_operations ncp_sops =
++static const struct super_operations ncp_sops =
+ {
+ 	.alloc_inode	= ncp_alloc_inode,
+ 	.destroy_inode	= ncp_destroy_inode,
+diff --git a/fs/nfs/super.c b/fs/nfs/super.c
+index 76b980097621..baa28860ad27 100644
+--- a/fs/nfs/super.c
++++ b/fs/nfs/super.c
+@@ -82,7 +82,7 @@ struct file_system_type nfs_xdev_fs_type = {
+ 	.fs_flags	= FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
+ };
+ 
+-static struct super_operations nfs_sops = {
++static const struct super_operations nfs_sops = {
+ 	.alloc_inode	= nfs_alloc_inode,
+ 	.destroy_inode	= nfs_destroy_inode,
+ 	.write_inode	= nfs_write_inode,
+@@ -126,7 +126,7 @@ struct file_system_type nfs4_referral_fs_type = {
+ 	.fs_flags	= FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
+ };
+ 
+-static struct super_operations nfs4_sops = {
++static const struct super_operations nfs4_sops = {
+ 	.alloc_inode	= nfs_alloc_inode,
+ 	.destroy_inode	= nfs_destroy_inode,
+ 	.write_inode	= nfs_write_inode,
+diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
+index babf94d90def..1594c90b7164 100644
+--- a/fs/ntfs/super.c
++++ b/fs/ntfs/super.c
+@@ -2699,7 +2699,7 @@ static int ntfs_statfs(struct dentry *dentry, struct kstatfs *sfs)
+ /**
+  * The complete super operations.
+  */
+-static struct super_operations ntfs_sops = {
++static const struct super_operations ntfs_sops = {
+ 	.alloc_inode	= ntfs_alloc_big_inode,	  /* VFS: Allocate new inode. */
+ 	.destroy_inode	= ntfs_destroy_big_inode, /* VFS: Deallocate inode. */
+ #ifdef NTFS_RW
+diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c
+index 84b33ffb42f1..de952eba29a9 100644
+--- a/fs/ocfs2/dlm/dlmfs.c
++++ b/fs/ocfs2/dlm/dlmfs.c
+@@ -61,7 +61,7 @@
+ #define MLOG_MASK_PREFIX ML_DLMFS
+ #include "cluster/masklog.h"
+ 
+-static struct super_operations dlmfs_ops;
++static const struct super_operations dlmfs_ops;
+ static const struct file_operations dlmfs_file_operations;
+ static const struct inode_operations dlmfs_dir_inode_operations;
+ static const struct inode_operations dlmfs_root_inode_operations;
+@@ -560,7 +560,7 @@ static const struct inode_operations dlmfs_root_inode_operations = {
+ 	.rmdir		= simple_rmdir,
+ };
+ 
+-static struct super_operations dlmfs_ops = {
++static const struct super_operations dlmfs_ops = {
+ 	.statfs		= simple_statfs,
+ 	.alloc_inode	= dlmfs_alloc_inode,
+ 	.destroy_inode	= dlmfs_destroy_inode,
+diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
+index 6e300a88a47e..6534f92424dd 100644
+--- a/fs/ocfs2/super.c
++++ b/fs/ocfs2/super.c
+@@ -116,7 +116,7 @@ static void ocfs2_destroy_inode(struct inode *inode);
+ 
+ static unsigned long long ocfs2_max_file_offset(unsigned int blockshift);
+ 
+-static struct super_operations ocfs2_sops = {
++static const struct super_operations ocfs2_sops = {
+ 	.statfs		= ocfs2_statfs,
+ 	.alloc_inode	= ocfs2_alloc_inode,
+ 	.destroy_inode	= ocfs2_destroy_inode,
+diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
+index 327807b86fa1..bde1c164417d 100644
+--- a/fs/openpromfs/inode.c
++++ b/fs/openpromfs/inode.c
+@@ -364,7 +364,7 @@ static int openprom_remount(struct super_block *sb, int *flags, char *data)
+ 	return 0;
+ }
+ 
+-static struct super_operations openprom_sops = { 
++static const struct super_operations openprom_sops = {
+ 	.alloc_inode	= openprom_alloc_inode,
+ 	.destroy_inode	= openprom_destroy_inode,
+ 	.read_inode	= openprom_read_inode,
+diff --git a/fs/proc/inode.c b/fs/proc/inode.c
+index e26945ba685b..f6722be37dde 100644
+--- a/fs/proc/inode.c
++++ b/fs/proc/inode.c
+@@ -132,7 +132,7 @@ static int proc_remount(struct super_block *sb, int *flags, char *data)
+ 	return 0;
+ }
+ 
+-static struct super_operations proc_sops = { 
++static const struct super_operations proc_sops = {
+ 	.alloc_inode	= proc_alloc_inode,
+ 	.destroy_inode	= proc_destroy_inode,
+ 	.read_inode	= proc_read_inode,
+diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
+index c047dc654d5c..83bc8e7824cd 100644
+--- a/fs/qnx4/inode.c
++++ b/fs/qnx4/inode.c
+@@ -30,7 +30,7 @@
+ #define QNX4_VERSION  4
+ #define QNX4_BMNAME   ".bitmap"
+ 
+-static struct super_operations qnx4_sops;
++static const struct super_operations qnx4_sops;
+ 
+ #ifdef CONFIG_QNX4FS_RW
+ 
+@@ -129,7 +129,7 @@ static void qnx4_read_inode(struct inode *);
+ static int qnx4_remount(struct super_block *sb, int *flags, char *data);
+ static int qnx4_statfs(struct dentry *, struct kstatfs *);
+ 
+-static struct super_operations qnx4_sops =
++static const struct super_operations qnx4_sops =
+ {
+ 	.alloc_inode	= qnx4_alloc_inode,
+ 	.destroy_inode	= qnx4_destroy_inode,
+diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
+index 7a96b1d662a2..ff1f7639707b 100644
+--- a/fs/ramfs/inode.c
++++ b/fs/ramfs/inode.c
+@@ -40,7 +40,7 @@
+ /* some random number */
+ #define RAMFS_MAGIC	0x858458f6
+ 
+-static struct super_operations ramfs_ops;
++static const struct super_operations ramfs_ops;
+ static const struct inode_operations ramfs_dir_inode_operations;
+ 
+ static struct backing_dev_info ramfs_backing_dev_info = {
+@@ -155,7 +155,7 @@ static const struct inode_operations ramfs_dir_inode_operations = {
+ 	.rename		= simple_rename,
+ };
+ 
+-static struct super_operations ramfs_ops = {
++static const struct super_operations ramfs_ops = {
+ 	.statfs		= simple_statfs,
+ 	.drop_inode	= generic_delete_inode,
+ };
+diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
+index 58ad4551a7c1..f13a7f164dc6 100644
+--- a/fs/reiserfs/super.c
++++ b/fs/reiserfs/super.c
+@@ -593,7 +593,7 @@ static ssize_t reiserfs_quota_read(struct super_block *, int, char *, size_t,
+ 				   loff_t);
+ #endif
+ 
+-static struct super_operations reiserfs_sops = {
++static const struct super_operations reiserfs_sops = {
+ 	.alloc_inode = reiserfs_alloc_inode,
+ 	.destroy_inode = reiserfs_destroy_inode,
+ 	.write_inode = reiserfs_write_inode,
+diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c
+index 1e712cc1693b..fd601014813e 100644
+--- a/fs/romfs/inode.c
++++ b/fs/romfs/inode.c
+@@ -110,7 +110,7 @@ romfs_checksum(void *data, int size)
+ 	return sum;
+ }
+ 
+-static struct super_operations romfs_ops;
++static const struct super_operations romfs_ops;
+ 
+ static int romfs_fill_super(struct super_block *s, void *data, int silent)
+ {
+@@ -598,7 +598,7 @@ static int romfs_remount(struct super_block *sb, int *flags, char *data)
+ 	return 0;
+ }
+ 
+-static struct super_operations romfs_ops = {
++static const struct super_operations romfs_ops = {
+ 	.alloc_inode	= romfs_alloc_inode,
+ 	.destroy_inode	= romfs_destroy_inode,
+ 	.read_inode	= romfs_read_inode,
+diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
+index 84dfe3f3482e..5faba4f1c9ab 100644
+--- a/fs/smbfs/inode.c
++++ b/fs/smbfs/inode.c
+@@ -98,7 +98,7 @@ static int smb_remount(struct super_block *sb, int *flags, char *data)
+ 	return 0;
+ }
+ 
+-static struct super_operations smb_sops =
++static const struct super_operations smb_sops =
+ {
+ 	.alloc_inode	= smb_alloc_inode,
+ 	.destroy_inode	= smb_destroy_inode,
+diff --git a/fs/super.c b/fs/super.c
+index 3e7458c2bb76..60b1e50cbf53 100644
+--- a/fs/super.c
++++ b/fs/super.c
+@@ -285,7 +285,7 @@ int fsync_super(struct super_block *sb)
+  */
+ void generic_shutdown_super(struct super_block *sb)
+ {
+-	struct super_operations *sop = sb->s_op;
++	const struct super_operations *sop = sb->s_op;
+ 
+ 	if (sb->s_root) {
+ 		shrink_dcache_for_umount(sb);
+diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
+index f6a87a824883..23a48a38e6af 100644
+--- a/fs/sysfs/mount.c
++++ b/fs/sysfs/mount.c
+@@ -21,7 +21,7 @@ struct kmem_cache *sysfs_dir_cachep;
+ 
+ static void sysfs_clear_inode(struct inode *inode);
+ 
+-static struct super_operations sysfs_ops = {
++static const struct super_operations sysfs_ops = {
+ 	.statfs		= simple_statfs,
+ 	.drop_inode	= sysfs_delete_inode,
+ 	.clear_inode	= sysfs_clear_inode,
+diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
+index 13dd75c4bc85..9311cac186fe 100644
+--- a/fs/sysv/inode.c
++++ b/fs/sysv/inode.c
+@@ -327,7 +327,7 @@ static void init_once(void *p, struct kmem_cache *cachep, unsigned long flags)
+ 		inode_init_once(&si->vfs_inode);
+ }
+ 
+-struct super_operations sysv_sops = {
++const struct super_operations sysv_sops = {
+ 	.alloc_inode	= sysv_alloc_inode,
+ 	.destroy_inode	= sysv_destroy_inode,
+ 	.read_inode	= sysv_read_inode,
+diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h
+index a320edcf541e..5b4fedf17cc4 100644
+--- a/fs/sysv/sysv.h
++++ b/fs/sysv/sysv.h
+@@ -165,7 +165,7 @@ extern const struct inode_operations sysv_fast_symlink_inode_operations;
+ extern const struct file_operations sysv_file_operations;
+ extern const struct file_operations sysv_dir_operations;
+ extern const struct address_space_operations sysv_aops;
+-extern struct super_operations sysv_sops;
++extern const struct super_operations sysv_sops;
+ extern struct dentry_operations sysv_dentry_operations;
+ 
+ 
+diff --git a/fs/udf/super.c b/fs/udf/super.c
+index 1dbc2955f02e..8672b88f7ff2 100644
+--- a/fs/udf/super.c
++++ b/fs/udf/super.c
+@@ -160,7 +160,7 @@ static void destroy_inodecache(void)
+ }
+ 
+ /* Superblock operations */
+-static struct super_operations udf_sb_ops = {
++static const struct super_operations udf_sb_ops = {
+ 	.alloc_inode		= udf_alloc_inode,
+ 	.destroy_inode		= udf_destroy_inode,
+ 	.write_inode		= udf_write_inode,
+diff --git a/fs/ufs/super.c b/fs/ufs/super.c
+index cf74548aa85a..b5a6461ec66b 100644
+--- a/fs/ufs/super.c
++++ b/fs/ufs/super.c
+@@ -213,7 +213,7 @@ static void ufs_print_cylinder_stuff(struct super_block *sb,
+ #  define ufs_print_cylinder_stuff(sb, cg) /**/
+ #endif /* CONFIG_UFS_DEBUG */
+ 
+-static struct super_operations ufs_super_ops;
++static const struct super_operations ufs_super_ops;
+ 
+ static char error_buf[1024];
+ 
+@@ -1264,7 +1264,7 @@ static ssize_t ufs_quota_read(struct super_block *, int, char *,size_t, loff_t);
+ static ssize_t ufs_quota_write(struct super_block *, int, const char *, size_t, loff_t);
+ #endif
+ 
+-static struct super_operations ufs_super_ops = {
++static const struct super_operations ufs_super_ops = {
+ 	.alloc_inode	= ufs_alloc_inode,
+ 	.destroy_inode	= ufs_destroy_inode,
+ 	.read_inode	= ufs_read_inode,
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index bab891bb2270..86ec3f4a7da6 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -907,7 +907,7 @@ struct super_block {
+ 	unsigned char		s_dirt;
+ 	unsigned long long	s_maxbytes;	/* Max file size */
+ 	struct file_system_type	*s_type;
+-	struct super_operations	*s_op;
++	const struct super_operations	*s_op;
+ 	struct dquot_operations	*dq_op;
+  	struct quotactl_ops	*s_qcop;
+ 	struct export_operations *s_export_op;
+@@ -1383,7 +1383,7 @@ struct super_block *sget(struct file_system_type *type,
+ 			int (*set)(struct super_block *,void *),
+ 			void *data);
+ extern int get_sb_pseudo(struct file_system_type *, char *,
+-	struct super_operations *ops, unsigned long,
++	const struct super_operations *ops, unsigned long,
+ 	struct vfsmount *mnt);
+ extern int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb);
+ int __put_super(struct super_block *sb);

commit e678fb0d523c118fc2f903d62cb54c89b6b68185
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:49 2006 -0800
+
+    [PATCH] xfs: change uses of f_{dentry,vfsmnt} to use f_path
+    
+    Change all the uses of f_{dentry,vfsmnt} to f_path.{dentry,mnt} in the xfs
+    filesystem.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
+index d93d8dd1958d..d26f5cd2ba70 100644
+--- a/fs/xfs/linux-2.6/xfs_file.c
++++ b/fs/xfs/linux-2.6/xfs_file.c
+@@ -55,7 +55,7 @@ __xfs_file_read(
+ 	loff_t			pos)
+ {
+ 	struct file		*file = iocb->ki_filp;
+-	bhv_vnode_t		*vp = vn_from_inode(file->f_dentry->d_inode);
++	bhv_vnode_t		*vp = vn_from_inode(file->f_path.dentry->d_inode);
+ 
+ 	BUG_ON(iocb->ki_pos != pos);
+ 	if (unlikely(file->f_flags & O_DIRECT))
+@@ -131,7 +131,7 @@ xfs_file_sendfile(
+ 	read_actor_t		actor,
+ 	void			*target)
+ {
+-	return bhv_vop_sendfile(vn_from_inode(filp->f_dentry->d_inode),
++	return bhv_vop_sendfile(vn_from_inode(filp->f_path.dentry->d_inode),
+ 				filp, pos, 0, count, actor, target, NULL);
+ }
+ 
+@@ -143,7 +143,7 @@ xfs_file_sendfile_invis(
+ 	read_actor_t		actor,
+ 	void			*target)
+ {
+-	return bhv_vop_sendfile(vn_from_inode(filp->f_dentry->d_inode),
++	return bhv_vop_sendfile(vn_from_inode(filp->f_path.dentry->d_inode),
+ 				filp, pos, IO_INVIS, count, actor, target, NULL);
+ }
+ 
+@@ -155,7 +155,7 @@ xfs_file_splice_read(
+ 	size_t			len,
+ 	unsigned int		flags)
+ {
+-	return bhv_vop_splice_read(vn_from_inode(infilp->f_dentry->d_inode),
++	return bhv_vop_splice_read(vn_from_inode(infilp->f_path.dentry->d_inode),
+ 				   infilp, ppos, pipe, len, flags, 0, NULL);
+ }
+ 
+@@ -167,7 +167,7 @@ xfs_file_splice_read_invis(
+ 	size_t			len,
+ 	unsigned int		flags)
+ {
+-	return bhv_vop_splice_read(vn_from_inode(infilp->f_dentry->d_inode),
++	return bhv_vop_splice_read(vn_from_inode(infilp->f_path.dentry->d_inode),
+ 				   infilp, ppos, pipe, len, flags, IO_INVIS,
+ 				   NULL);
+ }
+@@ -180,7 +180,7 @@ xfs_file_splice_write(
+ 	size_t			len,
+ 	unsigned int		flags)
+ {
+-	return bhv_vop_splice_write(vn_from_inode(outfilp->f_dentry->d_inode),
++	return bhv_vop_splice_write(vn_from_inode(outfilp->f_path.dentry->d_inode),
+ 				    pipe, outfilp, ppos, len, flags, 0, NULL);
+ }
+ 
+@@ -192,7 +192,7 @@ xfs_file_splice_write_invis(
+ 	size_t			len,
+ 	unsigned int		flags)
+ {
+-	return bhv_vop_splice_write(vn_from_inode(outfilp->f_dentry->d_inode),
++	return bhv_vop_splice_write(vn_from_inode(outfilp->f_path.dentry->d_inode),
+ 				    pipe, outfilp, ppos, len, flags, IO_INVIS,
+ 				    NULL);
+ }
+@@ -212,7 +212,7 @@ xfs_file_close(
+ 	struct file	*filp,
+ 	fl_owner_t	id)
+ {
+-	return -bhv_vop_close(vn_from_inode(filp->f_dentry->d_inode), 0,
++	return -bhv_vop_close(vn_from_inode(filp->f_path.dentry->d_inode), 0,
+ 				file_count(filp) > 1 ? L_FALSE : L_TRUE, NULL);
+ }
+ 
+@@ -251,7 +251,7 @@ xfs_vm_nopage(
+ 	unsigned long		address,
+ 	int			*type)
+ {
+-	struct inode	*inode = area->vm_file->f_dentry->d_inode;
++	struct inode	*inode = area->vm_file->f_path.dentry->d_inode;
+ 	bhv_vnode_t	*vp = vn_from_inode(inode);
+ 
+ 	ASSERT_ALWAYS(vp->v_vfsp->vfs_flag & VFS_DMI);
+@@ -268,7 +268,7 @@ xfs_file_readdir(
+ 	filldir_t	filldir)
+ {
+ 	int		error = 0;
+-	bhv_vnode_t	*vp = vn_from_inode(filp->f_dentry->d_inode);
++	bhv_vnode_t	*vp = vn_from_inode(filp->f_path.dentry->d_inode);
+ 	uio_t		uio;
+ 	iovec_t		iov;
+ 	int		eof = 0;
+@@ -345,7 +345,7 @@ xfs_file_mmap(
+ 	vma->vm_ops = &xfs_file_vm_ops;
+ 
+ #ifdef CONFIG_XFS_DMAPI
+-	if (vn_from_inode(filp->f_dentry->d_inode)->v_vfsp->vfs_flag & VFS_DMI)
++	if (vn_from_inode(filp->f_path.dentry->d_inode)->v_vfsp->vfs_flag & VFS_DMI)
+ 		vma->vm_ops = &xfs_dmapi_file_vm_ops;
+ #endif /* CONFIG_XFS_DMAPI */
+ 
+@@ -360,7 +360,7 @@ xfs_file_ioctl(
+ 	unsigned long	p)
+ {
+ 	int		error;
+-	struct inode	*inode = filp->f_dentry->d_inode;
++	struct inode	*inode = filp->f_path.dentry->d_inode;
+ 	bhv_vnode_t	*vp = vn_from_inode(inode);
+ 
+ 	error = bhv_vop_ioctl(vp, inode, filp, 0, cmd, (void __user *)p);
+@@ -382,7 +382,7 @@ xfs_file_ioctl_invis(
+ 	unsigned long	p)
+ {
+ 	int		error;
+-	struct inode	*inode = filp->f_dentry->d_inode;
++	struct inode	*inode = filp->f_path.dentry->d_inode;
+ 	bhv_vnode_t	*vp = vn_from_inode(inode);
+ 
+ 	error = bhv_vop_ioctl(vp, inode, filp, IO_INVIS, cmd, (void __user *)p);
+@@ -404,7 +404,7 @@ xfs_vm_mprotect(
+ 	struct vm_area_struct *vma,
+ 	unsigned int	newflags)
+ {
+-	bhv_vnode_t	*vp = vn_from_inode(vma->vm_file->f_dentry->d_inode);
++	bhv_vnode_t	*vp = vn_from_inode(vma->vm_file->f_path.dentry->d_inode);
+ 	int		error = 0;
+ 
+ 	if (vp->v_vfsp->vfs_flag & VFS_DMI) {
+diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
+index 74d094829a4d..f011c9cd0d62 100644
+--- a/fs/xfs/linux-2.6/xfs_ioctl.c
++++ b/fs/xfs/linux-2.6/xfs_ioctl.c
+@@ -107,9 +107,9 @@ xfs_find_handle(
+ 		if (!file)
+ 		    return -EBADF;
+ 
+-		ASSERT(file->f_dentry);
+-		ASSERT(file->f_dentry->d_inode);
+-		inode = igrab(file->f_dentry->d_inode);
++		ASSERT(file->f_path.dentry);
++		ASSERT(file->f_path.dentry->d_inode);
++		inode = igrab(file->f_path.dentry->d_inode);
+ 		fput(file);
+ 		break;
+ 	}
+@@ -333,10 +333,10 @@ xfs_open_by_handle(
+ 	}
+ 
+ 	/* Ensure umount returns EBUSY on umounts while this file is open. */
+-	mntget(parfilp->f_vfsmnt);
++	mntget(parfilp->f_path.mnt);
+ 
+ 	/* Create file pointer. */
+-	filp = dentry_open(dentry, parfilp->f_vfsmnt, hreq.oflags);
++	filp = dentry_open(dentry, parfilp->f_path.mnt, hreq.oflags);
+ 	if (IS_ERR(filp)) {
+ 		put_unused_fd(new_fd);
+ 		return -XFS_ERROR(-PTR_ERR(filp));
+diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c
+index 270db0f3861d..b83cebc165f1 100644
+--- a/fs/xfs/linux-2.6/xfs_ioctl32.c
++++ b/fs/xfs/linux-2.6/xfs_ioctl32.c
+@@ -112,7 +112,7 @@ xfs_compat_ioctl(
+ 	unsigned	cmd,
+ 	unsigned long	arg)
+ {
+-	struct inode	*inode = file->f_dentry->d_inode;
++	struct inode	*inode = file->f_path.dentry->d_inode;
+ 	bhv_vnode_t	*vp = vn_from_inode(inode);
+ 	int		error;
+ 
+diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
+index fa842f1c9fa2..65e79b471d49 100644
+--- a/fs/xfs/linux-2.6/xfs_lrw.c
++++ b/fs/xfs/linux-2.6/xfs_lrw.c
+@@ -805,7 +805,7 @@ xfs_write(
+ 	     !capable(CAP_FSETID)) {
+ 		error = xfs_write_clear_setuid(xip);
+ 		if (likely(!error))
+-			error = -remove_suid(file->f_dentry);
++			error = -remove_suid(file->f_path.dentry);
+ 		if (unlikely(error)) {
+ 			xfs_iunlock(xip, iolock);
+ 			goto out_unlock_mutex;
+diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
+index 80562b60fb95..50d0faea371d 100644
+--- a/fs/xfs/xfs_dfrag.c
++++ b/fs/xfs/xfs_dfrag.c
+@@ -71,7 +71,7 @@ xfs_swapext(
+ 
+ 	/* Pull information for the target fd */
+ 	if (((fp = fget((int)sxp->sx_fdtarget)) == NULL) ||
+-	    ((vp = vn_from_inode(fp->f_dentry->d_inode)) == NULL))  {
++	    ((vp = vn_from_inode(fp->f_path.dentry->d_inode)) == NULL))  {
+ 		error = XFS_ERROR(EINVAL);
+ 		goto error0;
+ 	}
+@@ -83,7 +83,7 @@ xfs_swapext(
+ 	}
+ 
+ 	if (((tfp = fget((int)sxp->sx_fdtmp)) == NULL) ||
+-	    ((tvp = vn_from_inode(tfp->f_dentry->d_inode)) == NULL)) {
++	    ((tvp = vn_from_inode(tfp->f_path.dentry->d_inode)) == NULL)) {
+ 		error = XFS_ERROR(EINVAL);
+ 		goto error0;
+ 	}

commit bd243a4b4b028d65a8178db5b57f8ed2cfc9707d
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:48 2006 -0800
+
+    [PATCH] ecryptfs: change uses of f_{dentry, vfsmnt} to use f_path
+    
+    Change all the uses of f_{dentry,vfsmnt} to f_path.{dentry,mnt} in the
+    ecryptfs filesystem.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
+index c48e4590b110..c5a2e5298f15 100644
+--- a/fs/ecryptfs/file.c
++++ b/fs/ecryptfs/file.c
+@@ -76,7 +76,7 @@ static loff_t ecryptfs_llseek(struct file *file, loff_t offset, int origin)
+ 	}
+ 	ecryptfs_printk(KERN_DEBUG, "new_end_pos = [0x%.16x]\n", new_end_pos);
+ 	if (expanding_file) {
+-		rc = ecryptfs_truncate(file->f_dentry, new_end_pos);
++		rc = ecryptfs_truncate(file->f_path.dentry, new_end_pos);
+ 		if (rc) {
+ 			rv = rc;
+ 			ecryptfs_printk(KERN_ERR, "Error on attempt to "
+@@ -117,8 +117,8 @@ static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb,
+ 	if (-EIOCBQUEUED == rc)
+ 		rc = wait_on_sync_kiocb(iocb);
+ 	if (rc >= 0) {
+-		lower_dentry = ecryptfs_dentry_to_lower(file->f_dentry);
+-		lower_vfsmount = ecryptfs_dentry_to_lower_mnt(file->f_dentry);
++		lower_dentry = ecryptfs_dentry_to_lower(file->f_path.dentry);
++		lower_vfsmount = ecryptfs_dentry_to_lower_mnt(file->f_path.dentry);
+ 		touch_atime(lower_vfsmount, lower_dentry);
+ 	}
+ 	return rc;
+@@ -177,10 +177,10 @@ static int ecryptfs_readdir(struct file *file, void *dirent, filldir_t filldir)
+ 
+ 	lower_file = ecryptfs_file_to_lower(file);
+ 	lower_file->f_pos = file->f_pos;
+-	inode = file->f_dentry->d_inode;
++	inode = file->f_path.dentry->d_inode;
+ 	memset(&buf, 0, sizeof(buf));
+ 	buf.dirent = dirent;
+-	buf.dentry = file->f_dentry;
++	buf.dentry = file->f_path.dentry;
+ 	buf.filldir = filldir;
+ retry:
+ 	buf.filldir_called = 0;
+@@ -193,7 +193,7 @@ static int ecryptfs_readdir(struct file *file, void *dirent, filldir_t filldir)
+ 		goto retry;
+ 	file->f_pos = lower_file->f_pos;
+ 	if (rc >= 0)
+-		fsstack_copy_attr_atime(inode, lower_file->f_dentry->d_inode);
++		fsstack_copy_attr_atime(inode, lower_file->f_path.dentry->d_inode);
+ 	return rc;
+ }
+ 
+@@ -240,7 +240,7 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
+ 	int rc = 0;
+ 	struct ecryptfs_crypt_stat *crypt_stat = NULL;
+ 	struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
+-	struct dentry *ecryptfs_dentry = file->f_dentry;
++	struct dentry *ecryptfs_dentry = file->f_path.dentry;
+ 	/* Private value of ecryptfs_dentry allocated in
+ 	 * ecryptfs_lookup() */
+ 	struct dentry *lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
+diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
+index c07a937b21ac..11f5e5076aef 100644
+--- a/fs/ecryptfs/inode.c
++++ b/fs/ecryptfs/inode.c
+@@ -155,7 +155,7 @@ static int grow_file(struct dentry *ecryptfs_dentry, struct file *lower_file,
+ 	struct ecryptfs_file_info tmp_file_info;
+ 
+ 	memset(&fake_file, 0, sizeof(fake_file));
+-	fake_file.f_dentry = ecryptfs_dentry;
++	fake_file.f_path.dentry = ecryptfs_dentry;
+ 	memset(&tmp_file_info, 0, sizeof(tmp_file_info));
+ 	ecryptfs_set_file_private(&fake_file, &tmp_file_info);
+ 	ecryptfs_set_file_lower(&fake_file, lower_file);
+@@ -754,7 +754,7 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
+ 	 * the file in the underlying filesystem so that the
+ 	 * truncation has an effect there as well. */
+ 	memset(&fake_ecryptfs_file, 0, sizeof(fake_ecryptfs_file));
+-	fake_ecryptfs_file.f_dentry = dentry;
++	fake_ecryptfs_file.f_path.dentry = dentry;
+ 	/* Released at out_free: label */
+ 	ecryptfs_set_file_private(&fake_ecryptfs_file,
+ 				  kmem_cache_alloc(ecryptfs_file_info_cache,
+diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
+index 924dd90a4cf5..06843d24f239 100644
+--- a/fs/ecryptfs/mmap.c
++++ b/fs/ecryptfs/mmap.c
+@@ -51,7 +51,7 @@ static struct page *ecryptfs_get1page(struct file *file, int index)
+ 	struct inode *inode;
+ 	struct address_space *mapping;
+ 
+-	dentry = file->f_dentry;
++	dentry = file->f_path.dentry;
+ 	inode = dentry->d_inode;
+ 	mapping = inode->i_mapping;
+ 	page = read_cache_page(mapping, index,
+@@ -84,7 +84,7 @@ int write_zeros(struct file *file, pgoff_t index, int start, int num_zeros);
+ int ecryptfs_fill_zeros(struct file *file, loff_t new_length)
+ {
+ 	int rc = 0;
+-	struct dentry *dentry = file->f_dentry;
++	struct dentry *dentry = file->f_path.dentry;
+ 	struct inode *inode = dentry->d_inode;
+ 	pgoff_t old_end_page_index = 0;
+ 	pgoff_t index = old_end_page_index;
+@@ -218,7 +218,7 @@ int ecryptfs_do_readpage(struct file *file, struct page *page,
+ 	char *lower_page_data;
+ 	const struct address_space_operations *lower_a_ops;
+ 
+-	dentry = file->f_dentry;
++	dentry = file->f_path.dentry;
+ 	lower_file = ecryptfs_file_to_lower(file);
+ 	lower_dentry = ecryptfs_dentry_to_lower(dentry);
+ 	inode = dentry->d_inode;
+@@ -275,9 +275,9 @@ static int ecryptfs_readpage(struct file *file, struct page *page)
+ 	int rc = 0;
+ 	struct ecryptfs_crypt_stat *crypt_stat;
+ 
+-	BUG_ON(!(file && file->f_dentry && file->f_dentry->d_inode));
+-	crypt_stat =
+-		&ecryptfs_inode_to_private(file->f_dentry->d_inode)->crypt_stat;
++	BUG_ON(!(file && file->f_path.dentry && file->f_path.dentry->d_inode));
++	crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode)
++			->crypt_stat;
+ 	if (!crypt_stat
+ 	    || !ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED)
+ 	    || ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE)) {
+@@ -638,8 +638,8 @@ static int ecryptfs_commit_write(struct file *file, struct page *page,
+ 	lower_inode = ecryptfs_inode_to_lower(inode);
+ 	lower_file = ecryptfs_file_to_lower(file);
+ 	mutex_lock(&lower_inode->i_mutex);
+-	crypt_stat =
+-		&ecryptfs_inode_to_private(file->f_dentry->d_inode)->crypt_stat;
++	crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode)
++				->crypt_stat;
+ 	if (ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE)) {
+ 		ecryptfs_printk(KERN_DEBUG, "ECRYPTFS_NEW_FILE flag set in "
+ 			"crypt_stat at memory location [%p]\n", crypt_stat);

commit e6a002964cf376c2acb1d67c4741044dcd3b1622
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:48 2006 -0800
+
+    [PATCH] cifs: change uses of f_{dentry, vfsmnt} to use f_path
+    
+    Change all the uses of f_{dentry,vfsmnt} to f_path.{dentry,mnt} in the cifs
+    filesystem.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
+index 71bc87a37fc1..10c90294cd18 100644
+--- a/fs/cifs/cifsfs.c
++++ b/fs/cifs/cifsfs.c
+@@ -498,7 +498,7 @@ cifs_get_sb(struct file_system_type *fs_type,
+ static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
+ 				   unsigned long nr_segs, loff_t pos)
+ {
+-	struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
++	struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode;
+ 	ssize_t written;
+ 
+ 	written = generic_file_aio_write(iocb, iov, nr_segs, pos);
+@@ -511,7 +511,7 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
+ {
+ 	/* origin == SEEK_END => we must revalidate the cached file length */
+ 	if (origin == SEEK_END) {
+-		int retval = cifs_revalidate(file->f_dentry);
++		int retval = cifs_revalidate(file->f_path.dentry);
+ 		if (retval < 0)
+ 			return (loff_t)retval;
+ 	}
+diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
+index d91a3d44e9e3..da12b482ebe5 100644
+--- a/fs/cifs/fcntl.c
++++ b/fs/cifs/fcntl.c
+@@ -83,10 +83,10 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
+ 		return 0;
+ 
+ 	xid = GetXid();
+-	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
++	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
+ 	pTcon = cifs_sb->tcon;
+ 
+-	full_path = build_path_from_dentry(file->f_dentry);
++	full_path = build_path_from_dentry(file->f_path.dentry);
+ 
+ 	if(full_path == NULL) {
+ 		rc = -ENOMEM;
+diff --git a/fs/cifs/file.c b/fs/cifs/file.c
+index 2436ed8fc840..1aa95a50cac2 100644
+--- a/fs/cifs/file.c
++++ b/fs/cifs/file.c
+@@ -122,34 +122,34 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
+ 	/* if not oplocked, invalidate inode pages if mtime or file
+ 	   size changed */
+ 	temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
+-	if (timespec_equal(&file->f_dentry->d_inode->i_mtime, &temp) && 
+-			   (file->f_dentry->d_inode->i_size == 
++	if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) &&
++			   (file->f_path.dentry->d_inode->i_size ==
+ 			    (loff_t)le64_to_cpu(buf->EndOfFile))) {
+ 		cFYI(1, ("inode unchanged on server"));
+ 	} else {
+-		if (file->f_dentry->d_inode->i_mapping) {
++		if (file->f_path.dentry->d_inode->i_mapping) {
+ 		/* BB no need to lock inode until after invalidate
+ 		   since namei code should already have it locked? */
+-			filemap_write_and_wait(file->f_dentry->d_inode->i_mapping);
++			filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping);
+ 		}
+ 		cFYI(1, ("invalidating remote inode since open detected it "
+ 			 "changed"));
+-		invalidate_remote_inode(file->f_dentry->d_inode);
++		invalidate_remote_inode(file->f_path.dentry->d_inode);
+ 	}
+ 
+ client_can_cache:
+ 	if (pTcon->ses->capabilities & CAP_UNIX)
+-		rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
++		rc = cifs_get_inode_info_unix(&file->f_path.dentry->d_inode,
+ 			full_path, inode->i_sb, xid);
+ 	else
+-		rc = cifs_get_inode_info(&file->f_dentry->d_inode,
++		rc = cifs_get_inode_info(&file->f_path.dentry->d_inode,
+ 			full_path, buf, inode->i_sb, xid);
+ 
+ 	if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) {
+ 		pCifsInode->clientCanCacheAll = TRUE;
+ 		pCifsInode->clientCanCacheRead = TRUE;
+ 		cFYI(1, ("Exclusive Oplock granted on inode %p",
+-			 file->f_dentry->d_inode));
++			 file->f_path.dentry->d_inode));
+ 	} else if ((*oplock & 0xF) == OPLOCK_READ)
+ 		pCifsInode->clientCanCacheRead = TRUE;
+ 
+@@ -178,7 +178,7 @@ int cifs_open(struct inode *inode, struct file *file)
+ 
+ 	if (file->f_flags & O_CREAT) {
+ 		/* search inode for this file and fill in file->private_data */
+-		pCifsInode = CIFS_I(file->f_dentry->d_inode);
++		pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
+ 		read_lock(&GlobalSMBSeslock);
+ 		list_for_each(tmp, &pCifsInode->openFileList) {
+ 			pCifsFile = list_entry(tmp, struct cifsFileInfo,
+@@ -206,7 +206,7 @@ int cifs_open(struct inode *inode, struct file *file)
+ 		}
+ 	}
+ 
+-	full_path = build_path_from_dentry(file->f_dentry);
++	full_path = build_path_from_dentry(file->f_path.dentry);
+ 	if (full_path == NULL) {
+ 		FreeXid(xid);
+ 		return -ENOMEM;
+@@ -291,7 +291,7 @@ int cifs_open(struct inode *inode, struct file *file)
+ 	write_lock(&GlobalSMBSeslock);
+ 	list_add(&pCifsFile->tlist, &pTcon->openFileList);
+ 
+-	pCifsInode = CIFS_I(file->f_dentry->d_inode);
++	pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
+ 	if (pCifsInode) {
+ 		rc = cifs_open_inode_helper(inode, file, pCifsInode,
+ 					    pCifsFile, pTcon,
+@@ -366,7 +366,7 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
+ 		return 0;
+ 	}
+ 
+-	if (file->f_dentry == NULL) {
++	if (file->f_path.dentry == NULL) {
+ 		up(&pCifsFile->fh_sem);
+ 		cFYI(1, ("failed file reopen, no valid name if dentry freed"));
+ 		FreeXid(xid);
+@@ -378,7 +378,7 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
+    those that already have the rename sem can end up causing writepage
+    to get called and if the server was down that means we end up here,
+    and we can never tell if the caller already has the rename_sem */
+-	full_path = build_path_from_dentry(file->f_dentry);
++	full_path = build_path_from_dentry(file->f_path.dentry);
+ 	if (full_path == NULL) {
+ 		up(&pCifsFile->fh_sem);
+ 		FreeXid(xid);
+@@ -444,7 +444,7 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
+ 				pCifsInode->clientCanCacheAll = TRUE;
+ 				pCifsInode->clientCanCacheRead = TRUE;
+ 				cFYI(1, ("Exclusive Oplock granted on inode %p",
+-					 file->f_dentry->d_inode));
++					 file->f_path.dentry->d_inode));
+ 			} else if ((oplock & 0xF) == OPLOCK_READ) {
+ 				pCifsInode->clientCanCacheRead = TRUE;
+ 				pCifsInode->clientCanCacheAll = FALSE;
+@@ -551,7 +551,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
+ 
+ 	if (pCFileStruct) {
+ 		struct cifsTconInfo *pTcon;
+-		struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_dentry->d_sb);
++		struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
+ 
+ 		pTcon = cifs_sb->tcon;
+ 
+@@ -664,7 +664,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
+ 	} else
+ 		cFYI(1, ("Unknown type of lock"));
+ 
+-	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
++	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
+ 	pTcon = cifs_sb->tcon;
+ 
+ 	if (file->private_data == NULL) {
+@@ -791,10 +791,10 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
+ 	int xid, long_op;
+ 	struct cifsFileInfo *open_file;
+ 
+-	if (file->f_dentry == NULL)
++	if (file->f_path.dentry == NULL)
+ 		return -EBADF;
+ 
+-	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
++	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
+ 	if (cifs_sb == NULL)
+ 		return -EBADF;
+ 
+@@ -802,7 +802,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
+ 
+ 	/* cFYI(1,
+ 	   (" write %d bytes to offset %lld of %s", write_size,
+-	   *poffset, file->f_dentry->d_name.name)); */
++	   *poffset, file->f_path.dentry->d_name.name)); */
+ 
+ 	if (file->private_data == NULL)
+ 		return -EBADF;
+@@ -810,12 +810,12 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
+ 		open_file = (struct cifsFileInfo *) file->private_data;
+ 	
+ 	xid = GetXid();
+-	if (file->f_dentry->d_inode == NULL) {
++	if (file->f_path.dentry->d_inode == NULL) {
+ 		FreeXid(xid);
+ 		return -EBADF;
+ 	}
+ 
+-	if (*poffset > file->f_dentry->d_inode->i_size)
++	if (*poffset > file->f_path.dentry->d_inode->i_size)
+ 		long_op = 2; /* writes past end of file can take a long time */
+ 	else
+ 		long_op = 1;
+@@ -840,8 +840,8 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
+ 					return -EBADF;
+ 			}
+ 			if (open_file->invalidHandle) {
+-				if ((file->f_dentry == NULL) ||
+-				    (file->f_dentry->d_inode == NULL)) {
++				if ((file->f_path.dentry == NULL) ||
++				    (file->f_path.dentry->d_inode == NULL)) {
+ 					FreeXid(xid);
+ 					return total_written;
+ 				}
+@@ -849,7 +849,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
+ 				   filemap_fdatawait from here so tell
+ 				   reopen_file not to flush data to server
+ 				   now */
+-				rc = cifs_reopen_file(file->f_dentry->d_inode,
++				rc = cifs_reopen_file(file->f_path.dentry->d_inode,
+ 					file, FALSE);
+ 				if (rc != 0)
+ 					break;
+@@ -878,17 +878,17 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
+ 	cifs_stats_bytes_written(pTcon, total_written);
+ 
+ 	/* since the write may have blocked check these pointers again */
+-	if (file->f_dentry) {
+-		if (file->f_dentry->d_inode) {
+-			struct inode *inode = file->f_dentry->d_inode;
++	if (file->f_path.dentry) {
++		if (file->f_path.dentry->d_inode) {
++			struct inode *inode = file->f_path.dentry->d_inode;
+ 			inode->i_ctime = inode->i_mtime =
+ 				current_fs_time(inode->i_sb);
+ 			if (total_written > 0) {
+-				if (*poffset > file->f_dentry->d_inode->i_size)
+-					i_size_write(file->f_dentry->d_inode,
++				if (*poffset > file->f_path.dentry->d_inode->i_size)
++					i_size_write(file->f_path.dentry->d_inode,
+ 					*poffset);
+ 			}
+-			mark_inode_dirty_sync(file->f_dentry->d_inode);
++			mark_inode_dirty_sync(file->f_path.dentry->d_inode);
+ 		}
+ 	}
+ 	FreeXid(xid);
+@@ -906,17 +906,17 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
+ 	int xid, long_op;
+ 	struct cifsFileInfo *open_file;
+ 
+-	if (file->f_dentry == NULL)
++	if (file->f_path.dentry == NULL)
+ 		return -EBADF;
+ 
+-	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
++	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
+ 	if (cifs_sb == NULL)
+ 		return -EBADF;
+ 
+ 	pTcon = cifs_sb->tcon;
+ 
+ 	cFYI(1,("write %zd bytes to offset %lld of %s", write_size,
+-	   *poffset, file->f_dentry->d_name.name));
++	   *poffset, file->f_path.dentry->d_name.name));
+ 
+ 	if (file->private_data == NULL)
+ 		return -EBADF;
+@@ -924,12 +924,12 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
+ 		open_file = (struct cifsFileInfo *)file->private_data;
+ 	
+ 	xid = GetXid();
+-	if (file->f_dentry->d_inode == NULL) {
++	if (file->f_path.dentry->d_inode == NULL) {
+ 		FreeXid(xid);
+ 		return -EBADF;
+ 	}
+ 
+-	if (*poffset > file->f_dentry->d_inode->i_size)
++	if (*poffset > file->f_path.dentry->d_inode->i_size)
+ 		long_op = 2; /* writes past end of file can take a long time */
+ 	else
+ 		long_op = 1;
+@@ -955,8 +955,8 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
+ 					return -EBADF;
+ 			}
+ 			if (open_file->invalidHandle) {
+-				if ((file->f_dentry == NULL) ||
+-				   (file->f_dentry->d_inode == NULL)) {
++				if ((file->f_path.dentry == NULL) ||
++				   (file->f_path.dentry->d_inode == NULL)) {
+ 					FreeXid(xid);
+ 					return total_written;
+ 				}
+@@ -964,7 +964,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
+ 				   filemap_fdatawait from here so tell
+ 				   reopen_file not to flush data to 
+ 				   server now */
+-				rc = cifs_reopen_file(file->f_dentry->d_inode,
++				rc = cifs_reopen_file(file->f_path.dentry->d_inode,
+ 					file, FALSE);
+ 				if (rc != 0)
+ 					break;
+@@ -1011,16 +1011,16 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
+ 	cifs_stats_bytes_written(pTcon, total_written);
+ 
+ 	/* since the write may have blocked check these pointers again */
+-	if (file->f_dentry) {
+-		if (file->f_dentry->d_inode) {
+-			file->f_dentry->d_inode->i_ctime = 
+-			file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
++	if (file->f_path.dentry) {
++		if (file->f_path.dentry->d_inode) {
++			file->f_path.dentry->d_inode->i_ctime =
++			file->f_path.dentry->d_inode->i_mtime = CURRENT_TIME;
+ 			if (total_written > 0) {
+-				if (*poffset > file->f_dentry->d_inode->i_size)
+-					i_size_write(file->f_dentry->d_inode, 
++				if (*poffset > file->f_path.dentry->d_inode->i_size)
++					i_size_write(file->f_path.dentry->d_inode,
+ 						     *poffset);
+ 			}
+-			mark_inode_dirty_sync(file->f_dentry->d_inode);
++			mark_inode_dirty_sync(file->f_path.dentry->d_inode);
+ 		}
+ 	}
+ 	FreeXid(xid);
+@@ -1384,7 +1384,7 @@ static int cifs_commit_write(struct file *file, struct page *page,
+ 				if ((open_file->invalidHandle) && 
+ 				    (!open_file->closePend)) {
+ 					rc = cifs_reopen_file(
+-						file->f_dentry->d_inode, file);
++						file->f_path.dentry->d_inode, file);
+ 					if (rc != 0)
+ 						break;
+ 				}
+@@ -1434,7 +1434,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
+ {
+ 	int xid;
+ 	int rc = 0;
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 
+ 	xid = GetXid();
+ 
+@@ -1482,7 +1482,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
+  */
+ int cifs_flush(struct file *file, fl_owner_t id)
+ {
+-	struct inode * inode = file->f_dentry->d_inode;
++	struct inode * inode = file->f_path.dentry->d_inode;
+ 	int rc = 0;
+ 
+ 	/* Rather than do the steps manually:
+@@ -1519,7 +1519,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
+ 	struct smb_com_read_rsp *pSMBr;
+ 
+ 	xid = GetXid();
+-	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
++	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
+ 	pTcon = cifs_sb->tcon;
+ 
+ 	if (file->private_data == NULL) {
+@@ -1542,7 +1542,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
+ 			int buf_type = CIFS_NO_BUFFER;
+ 			if ((open_file->invalidHandle) && 
+ 			    (!open_file->closePend)) {
+-				rc = cifs_reopen_file(file->f_dentry->d_inode,
++				rc = cifs_reopen_file(file->f_path.dentry->d_inode,
+ 					file, TRUE);
+ 				if (rc != 0)
+ 					break;
+@@ -1601,7 +1601,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
+ 	int buf_type = CIFS_NO_BUFFER;
+ 
+ 	xid = GetXid();
+-	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
++	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
+ 	pTcon = cifs_sb->tcon;
+ 
+ 	if (file->private_data == NULL) {
+@@ -1629,7 +1629,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
+ 		while (rc == -EAGAIN) {
+ 			if ((open_file->invalidHandle) && 
+ 			    (!open_file->closePend)) {
+-				rc = cifs_reopen_file(file->f_dentry->d_inode,
++				rc = cifs_reopen_file(file->f_path.dentry->d_inode,
+ 					file, TRUE);
+ 				if (rc != 0)
+ 					break;
+@@ -1658,7 +1658,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
+ 
+ int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
+ {
+-	struct dentry *dentry = file->f_dentry;
++	struct dentry *dentry = file->f_path.dentry;
+ 	int rc, xid;
+ 
+ 	xid = GetXid();
+@@ -1744,7 +1744,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
+ 		return -EBADF;
+ 	}
+ 	open_file = (struct cifsFileInfo *)file->private_data;
+-	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
++	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
+ 	pTcon = cifs_sb->tcon;
+ 
+ 	pagevec_init(&lru_pvec, 0);
+@@ -1786,7 +1786,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
+ 		while (rc == -EAGAIN) {
+ 			if ((open_file->invalidHandle) && 
+ 			    (!open_file->closePend)) {
+-				rc = cifs_reopen_file(file->f_dentry->d_inode,
++				rc = cifs_reopen_file(file->f_path.dentry->d_inode,
+ 					file, TRUE);
+ 				if (rc != 0)
+ 					break;
+@@ -1880,8 +1880,8 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
+ 	else
+ 		cFYI(1, ("Bytes read %d",rc));
+                                                                                                                            
+-	file->f_dentry->d_inode->i_atime =
+-		current_fs_time(file->f_dentry->d_inode->i_sb);
++	file->f_path.dentry->d_inode->i_atime =
++		current_fs_time(file->f_path.dentry->d_inode->i_sb);
+                                                                                                                            
+ 	if (PAGE_CACHE_SIZE > rc)
+ 		memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
+diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
+index ed18c3965f7b..99dfb5337e31 100644
+--- a/fs/cifs/readdir.c
++++ b/fs/cifs/readdir.c
+@@ -68,30 +68,30 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
+ 	int rc = 0;
+ 
+ 	cFYI(1, ("For %s", qstring->name));
+-	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
++	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
+ 	pTcon = cifs_sb->tcon;
+ 
+ 	qstring->hash = full_name_hash(qstring->name, qstring->len);
+-	tmp_dentry = d_lookup(file->f_dentry, qstring);
++	tmp_dentry = d_lookup(file->f_path.dentry, qstring);
+ 	if (tmp_dentry) {
+ 		cFYI(0, ("existing dentry with inode 0x%p", tmp_dentry->d_inode));
+ 		*ptmp_inode = tmp_dentry->d_inode;
+ /* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/
+ 		if(*ptmp_inode == NULL) {
+-			*ptmp_inode = new_inode(file->f_dentry->d_sb);
++			*ptmp_inode = new_inode(file->f_path.dentry->d_sb);
+ 			if(*ptmp_inode == NULL)
+ 				return rc;
+ 			rc = 1;
+ 		}
+ 	} else {
+-		tmp_dentry = d_alloc(file->f_dentry, qstring);
++		tmp_dentry = d_alloc(file->f_path.dentry, qstring);
+ 		if(tmp_dentry == NULL) {
+ 			cERROR(1,("Failed allocating dentry"));
+ 			*ptmp_inode = NULL;
+ 			return rc;
+ 		}
+ 
+-		*ptmp_inode = new_inode(file->f_dentry->d_sb);
++		*ptmp_inode = new_inode(file->f_path.dentry->d_sb);
+ 		if (pTcon->nocase)
+ 			tmp_dentry->d_op = &cifs_ci_dentry_ops;
+ 		else
+@@ -432,10 +432,10 @@ static int initiate_cifs_search(const int xid, struct file *file)
+ 	cifsFile->invalidHandle = TRUE;
+ 	cifsFile->srch_inf.endOfSearch = FALSE;
+ 
+-	if(file->f_dentry == NULL)
++	if(file->f_path.dentry == NULL)
+ 		return -ENOENT;
+ 
+-	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
++	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
+ 	if(cifs_sb == NULL)
+ 		return -EINVAL;
+ 
+@@ -443,7 +443,7 @@ static int initiate_cifs_search(const int xid, struct file *file)
+ 	if(pTcon == NULL)
+ 		return -EINVAL;
+ 
+-	full_path = build_path_from_dentry(file->f_dentry);
++	full_path = build_path_from_dentry(file->f_path.dentry);
+ 
+ 	if(full_path == NULL) {
+ 		return -ENOMEM;
+@@ -609,10 +609,10 @@ static int is_dir_changed(struct file * file)
+ 	struct inode * inode;
+ 	struct cifsInodeInfo *cifsInfo;
+ 
+-	if(file->f_dentry == NULL)
++	if(file->f_path.dentry == NULL)
+ 		return 0;
+ 
+-	inode = file->f_dentry->d_inode;
++	inode = file->f_path.dentry->d_inode;
+ 
+ 	if(inode == NULL)
+ 		return 0;
+@@ -839,7 +839,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
+ 	if((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL))
+ 		return -ENOENT;
+ 
+-	if(file->f_dentry == NULL)
++	if(file->f_path.dentry == NULL)
+ 		return -ENOENT;
+ 
+ 	rc = cifs_entry_is_dot(pfindEntry,pCifsF);
+@@ -847,7 +847,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
+ 	if(rc != 0) 
+ 		return 0;
+ 
+-	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
++	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
+ 
+ 	qstring.name = scratch_buf;
+ 	rc = cifs_get_name_from_search_buf(&qstring,pfindEntry,
+@@ -985,12 +985,12 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
+ 
+ 	xid = GetXid();
+ 
+-	if(file->f_dentry == NULL) {
++	if(file->f_path.dentry == NULL) {
+ 		FreeXid(xid);
+ 		return -EIO;
+ 	}
+ 
+-	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
++	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
+ 	pTcon = cifs_sb->tcon;
+ 	if(pTcon == NULL)
+ 		return -EINVAL;
+@@ -998,7 +998,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
+ 	switch ((int) file->f_pos) {
+ 	case 0:
+ 		if (filldir(direntry, ".", 1, file->f_pos,
+-		     file->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
++		     file->f_path.dentry->d_inode->i_ino, DT_DIR) < 0) {
+ 			cERROR(1, ("Filldir for current dir failed"));
+ 			rc = -ENOMEM;
+ 			break;
+@@ -1006,7 +1006,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
+ 		file->f_pos++;
+ 	case 1:
+ 		if (filldir(direntry, "..", 2, file->f_pos,
+-		     file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
++		     file->f_path.dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
+ 			cERROR(1, ("Filldir for parent dir failed"));
+ 			rc = -ENOMEM;
+ 			break;

commit 867fa491a2722cee6964a30dfda86e0e02dcb400
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:47 2006 -0800
+
+    [PATCH] configfs: change uses of f_{dentry, vfsmnt} to use f_path
+    
+    Change all the uses of f_{dentry,vfsmnt} to f_path.{dentry,mnt} in the
+    configfs filesystem.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
+index c398861f78a5..1814ba446809 100644
+--- a/fs/configfs/dir.c
++++ b/fs/configfs/dir.c
+@@ -980,7 +980,7 @@ int configfs_rename_dir(struct config_item * item, const char *new_name)
+ 
+ static int configfs_dir_open(struct inode *inode, struct file *file)
+ {
+-	struct dentry * dentry = file->f_dentry;
++	struct dentry * dentry = file->f_path.dentry;
+ 	struct configfs_dirent * parent_sd = dentry->d_fsdata;
+ 
+ 	mutex_lock(&dentry->d_inode->i_mutex);
+@@ -993,7 +993,7 @@ static int configfs_dir_open(struct inode *inode, struct file *file)
+ 
+ static int configfs_dir_close(struct inode *inode, struct file *file)
+ {
+-	struct dentry * dentry = file->f_dentry;
++	struct dentry * dentry = file->f_path.dentry;
+ 	struct configfs_dirent * cursor = file->private_data;
+ 
+ 	mutex_lock(&dentry->d_inode->i_mutex);
+@@ -1013,7 +1013,7 @@ static inline unsigned char dt_type(struct configfs_dirent *sd)
+ 
+ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
+ {
+-	struct dentry *dentry = filp->f_dentry;
++	struct dentry *dentry = filp->f_path.dentry;
+ 	struct configfs_dirent * parent_sd = dentry->d_fsdata;
+ 	struct configfs_dirent *cursor = filp->private_data;
+ 	struct list_head *p, *q = &cursor->s_sibling;
+@@ -1070,7 +1070,7 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir
+ 
+ static loff_t configfs_dir_lseek(struct file * file, loff_t offset, int origin)
+ {
+-	struct dentry * dentry = file->f_dentry;
++	struct dentry * dentry = file->f_path.dentry;
+ 
+ 	mutex_lock(&dentry->d_inode->i_mutex);
+ 	switch (origin) {
+@@ -1080,7 +1080,7 @@ static loff_t configfs_dir_lseek(struct file * file, loff_t offset, int origin)
+ 			if (offset >= 0)
+ 				break;
+ 		default:
+-			mutex_unlock(&file->f_dentry->d_inode->i_mutex);
++			mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
+ 			return -EINVAL;
+ 	}
+ 	if (offset != file->f_pos) {
+diff --git a/fs/configfs/file.c b/fs/configfs/file.c
+index cf33fac68c84..2a7cb086e80c 100644
+--- a/fs/configfs/file.c
++++ b/fs/configfs/file.c
+@@ -134,7 +134,7 @@ configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *pp
+ 
+ 	down(&buffer->sem);
+ 	if (buffer->needs_read_fill) {
+-		if ((retval = fill_read_buffer(file->f_dentry,buffer)))
++		if ((retval = fill_read_buffer(file->f_path.dentry,buffer)))
+ 			goto out;
+ 	}
+ 	pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n",
+@@ -222,7 +222,7 @@ configfs_write_file(struct file *file, const char __user *buf, size_t count, lof
+ 	down(&buffer->sem);
+ 	len = fill_write_buffer(buffer, buf, count);
+ 	if (len > 0)
+-		len = flush_write_buffer(file->f_dentry, buffer, count);
++		len = flush_write_buffer(file->f_path.dentry, buffer, count);
+ 	if (len > 0)
+ 		*ppos += len;
+ 	up(&buffer->sem);
+@@ -231,8 +231,8 @@ configfs_write_file(struct file *file, const char __user *buf, size_t count, lof
+ 
+ static int check_perm(struct inode * inode, struct file * file)
+ {
+-	struct config_item *item = configfs_get_config_item(file->f_dentry->d_parent);
+-	struct configfs_attribute * attr = to_attr(file->f_dentry);
++	struct config_item *item = configfs_get_config_item(file->f_path.dentry->d_parent);
++	struct configfs_attribute * attr = to_attr(file->f_path.dentry);
+ 	struct configfs_buffer * buffer;
+ 	struct configfs_item_operations * ops = NULL;
+ 	int error = 0;
+@@ -305,8 +305,8 @@ static int configfs_open_file(struct inode * inode, struct file * filp)
+ 
+ static int configfs_release(struct inode * inode, struct file * filp)
+ {
+-	struct config_item * item = to_item(filp->f_dentry->d_parent);
+-	struct configfs_attribute * attr = to_attr(filp->f_dentry);
++	struct config_item * item = to_item(filp->f_path.dentry->d_parent);
++	struct configfs_attribute * attr = to_attr(filp->f_path.dentry);
+ 	struct module * owner = attr->ca_owner;
+ 	struct configfs_buffer * buffer = filp->private_data;
+ 

commit a4669ed8ed982dab494c5d4f2b32921e5a6531d8
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:46 2006 -0800
+
+    [PATCH] autofs4: change uses of f_{dentry, vfsmnt} to use f_path
+    
+    Change all the uses of f_{dentry,vfsmnt} to f_path.{dentry,mnt} in the autofs4
+    filesystem.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
+index b13f32c8aeee..216b1a364ccb 100644
+--- a/fs/autofs4/autofs_i.h
++++ b/fs/autofs4/autofs_i.h
+@@ -150,7 +150,8 @@ static inline int autofs4_ispending(struct dentry *dentry)
+ 
+ static inline void autofs4_copy_atime(struct file *src, struct file *dst)
+ {
+-	dst->f_dentry->d_inode->i_atime = src->f_dentry->d_inode->i_atime;
++	dst->f_path.dentry->d_inode->i_atime =
++		src->f_path.dentry->d_inode->i_atime;
+ 	return;
+ }
+ 
+diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
+index c1493524da4d..8d05b9f7578d 100644
+--- a/fs/autofs4/root.c
++++ b/fs/autofs4/root.c
+@@ -74,7 +74,7 @@ struct inode_operations autofs4_dir_inode_operations = {
+ static int autofs4_root_readdir(struct file *file, void *dirent,
+ 				filldir_t filldir)
+ {
+-	struct autofs_sb_info *sbi = autofs4_sbi(file->f_dentry->d_sb);
++	struct autofs_sb_info *sbi = autofs4_sbi(file->f_path.dentry->d_sb);
+ 	int oz_mode = autofs4_oz_mode(sbi);
+ 
+ 	DPRINTK("called, filp->f_pos = %lld", file->f_pos);
+@@ -95,8 +95,8 @@ static int autofs4_root_readdir(struct file *file, void *dirent,
+ 
+ static int autofs4_dir_open(struct inode *inode, struct file *file)
+ {
+-	struct dentry *dentry = file->f_dentry;
+-	struct vfsmount *mnt = file->f_vfsmnt;
++	struct dentry *dentry = file->f_path.dentry;
++	struct vfsmount *mnt = file->f_path.mnt;
+ 	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+ 	struct dentry *cursor;
+ 	int status;
+@@ -172,7 +172,7 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
+ 
+ static int autofs4_dir_close(struct inode *inode, struct file *file)
+ {
+-	struct dentry *dentry = file->f_dentry;
++	struct dentry *dentry = file->f_path.dentry;
+ 	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+ 	struct dentry *cursor = file->private_data;
+ 	int status = 0;
+@@ -204,7 +204,7 @@ static int autofs4_dir_close(struct inode *inode, struct file *file)
+ 
+ static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldir)
+ {
+-	struct dentry *dentry = file->f_dentry;
++	struct dentry *dentry = file->f_path.dentry;
+ 	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+ 	struct dentry *cursor = file->private_data;
+ 	int status;
+@@ -858,14 +858,14 @@ static int autofs4_root_ioctl(struct inode *inode, struct file *filp,
+ 		return autofs4_ask_reghost(sbi, p);
+ 
+ 	case AUTOFS_IOC_ASKUMOUNT:
+-		return autofs4_ask_umount(filp->f_vfsmnt, p);
++		return autofs4_ask_umount(filp->f_path.mnt, p);
+ 
+ 	/* return a single thing to expire */
+ 	case AUTOFS_IOC_EXPIRE:
+-		return autofs4_expire_run(inode->i_sb,filp->f_vfsmnt,sbi, p);
++		return autofs4_expire_run(inode->i_sb,filp->f_path.mnt,sbi, p);
+ 	/* same as above, but can send multiple expires through pipe */
+ 	case AUTOFS_IOC_EXPIRE_MULTI:
+-		return autofs4_expire_multi(inode->i_sb,filp->f_vfsmnt,sbi, p);
++		return autofs4_expire_multi(inode->i_sb,filp->f_path.mnt,sbi, p);
+ 
+ 	default:
+ 		return -ENOSYS;

commit 81ed19b076f518e793283ccbd004fd0888877201
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:46 2006 -0800
+
+    [PATCH] autofs: change uses of f_{dentry, vfsmnt} to use f_path
+    
+    Change all the uses of f_{dentry,vfsmnt} to f_path.{dentry,mnt} in the autofs
+    filesystem.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/autofs/root.c b/fs/autofs/root.c
+index 368a1c33a3c8..e698c51d2b02 100644
+--- a/fs/autofs/root.c
++++ b/fs/autofs/root.c
+@@ -45,7 +45,7 @@ static int autofs_root_readdir(struct file *filp, void *dirent, filldir_t filldi
+ 	struct autofs_dir_ent *ent = NULL;
+ 	struct autofs_dirhash *dirhash;
+ 	struct autofs_sb_info *sbi;
+-	struct inode * inode = filp->f_dentry->d_inode;
++	struct inode * inode = filp->f_path.dentry->d_inode;
+ 	off_t onr, nr;
+ 
+ 	lock_kernel();
+@@ -557,7 +557,7 @@ static int autofs_root_ioctl(struct inode *inode, struct file *filp,
+ 	case AUTOFS_IOC_SETTIMEOUT:
+ 		return autofs_get_set_timeout(sbi, argp);
+ 	case AUTOFS_IOC_EXPIRE:
+-		return autofs_expire_run(inode->i_sb, sbi, filp->f_vfsmnt,
++		return autofs_expire_run(inode->i_sb, sbi, filp->f_path.mnt,
+ 					 argp);
+ 	default:
+ 		return -ENOSYS;

commit 010596cc311131421c7be3a73ee7174bda16d322
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:45 2006 -0800
+
+    [PATCH] affs: change uses of f_{dentry, vfsmnt} to use f_path
+    
+    Change all the uses of f_{dentry,vfsmnt} to f_path.{dentry,mnt} in the affs
+    filesystem.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/affs/dir.c b/fs/affs/dir.c
+index 5d9649fa1814..cad3ee340063 100644
+--- a/fs/affs/dir.c
++++ b/fs/affs/dir.c
+@@ -41,7 +41,7 @@ struct inode_operations affs_dir_inode_operations = {
+ static int
+ affs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ {
+-	struct inode		*inode = filp->f_dentry->d_inode;
++	struct inode		*inode = filp->f_path.dentry->d_inode;
+ 	struct super_block	*sb = inode->i_sb;
+ 	struct buffer_head	*dir_bh;
+ 	struct buffer_head	*fh_bh;
+@@ -71,7 +71,7 @@ affs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ 		stored++;
+ 	}
+ 	if (f_pos == 1) {
+-		if (filldir(dirent, "..", 2, f_pos, parent_ino(filp->f_dentry), DT_DIR) < 0)
++		if (filldir(dirent, "..", 2, f_pos, parent_ino(filp->f_path.dentry), DT_DIR) < 0)
+ 			return stored;
+ 		filp->f_pos = f_pos = 2;
+ 		stored++;

commit d6f787bceeab37cd6b0823872efe01b2a20effb5
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:45 2006 -0800
+
+    [PATCH] 9p: change uses of f_{dentry,vfsmnt} to use f_path
+    
+    Change all the uses of f_{dentry,vfsmnt} to f_path.{dentry,mnt} in the 9p
+    filesystem.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
+index 9dfd259a70b4..cc24abf232d5 100644
+--- a/fs/9p/vfs_addr.c
++++ b/fs/9p/vfs_addr.c
+@@ -54,7 +54,7 @@ static int v9fs_vfs_readpage(struct file *filp, struct page *page)
+ 	int retval = -EIO;
+ 	loff_t offset = page_offset(page);
+ 	int count = PAGE_CACHE_SIZE;
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
+ 	int rsize = v9ses->maxdata - V9FS_IOHDRSZ;
+ 	struct v9fs_fid *v9f = filp->private_data;
+diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
+index 905c882f4e2f..3129688143ea 100644
+--- a/fs/9p/vfs_dir.c
++++ b/fs/9p/vfs_dir.c
+@@ -71,7 +71,7 @@ static inline int dt_type(struct v9fs_stat *mistat)
+ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ {
+ 	struct v9fs_fcall *fcall = NULL;
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
+ 	struct v9fs_fid *file = filp->private_data;
+ 	unsigned int i, n, s;
+@@ -80,7 +80,7 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ 	struct v9fs_stat stat;
+ 	int over = 0;
+ 
+-	dprintk(DEBUG_VFS, "name %s\n", filp->f_dentry->d_name.name);
++	dprintk(DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name);
+ 
+ 	fid = file->fid;
+ 
+diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
+index 79e6f9cd7340..e86a07151280 100644
+--- a/fs/9p/vfs_file.c
++++ b/fs/9p/vfs_file.c
+@@ -60,7 +60,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
+ 
+ 	dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file);
+ 
+-	vfid = v9fs_fid_lookup(file->f_dentry);
++	vfid = v9fs_fid_lookup(file->f_path.dentry);
+ 	if (!vfid) {
+ 		dprintk(DEBUG_ERROR, "Couldn't resolve fid from dentry\n");
+ 		return -EBADF;
+@@ -133,7 +133,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
+ static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl)
+ {
+ 	int res = 0;
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 
+ 	dprintk(DEBUG_VFS, "filp: %p lock: %p\n", filp, fl);
+ 
+@@ -161,7 +161,7 @@ static ssize_t
+ v9fs_file_read(struct file *filp, char __user * data, size_t count,
+ 	       loff_t * offset)
+ {
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
+ 	struct v9fs_fid *v9f = filp->private_data;
+ 	struct v9fs_fcall *fcall = NULL;
+@@ -225,7 +225,7 @@ static ssize_t
+ v9fs_file_write(struct file *filp, const char __user * data,
+ 		size_t count, loff_t * offset)
+ {
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
+ 	struct v9fs_fid *v9fid = filp->private_data;
+ 	struct v9fs_fcall *fcall;

commit d3ac7f892b7d07d61d0895caa4f6e190e43112f8
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:44 2006 -0800
+
+    [PATCH] mm: change uses of f_{dentry,vfsmnt} to use f_path
+    
+    Change all the uses of f_{dentry,vfsmnt} to f_path.{dentry,mnt} in linux/mm/.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/mm/fadvise.c b/mm/fadvise.c
+index 168c78a121bb..0df4c899e979 100644
+--- a/mm/fadvise.c
++++ b/mm/fadvise.c
+@@ -38,7 +38,7 @@ asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
+ 	if (!file)
+ 		return -EBADF;
+ 
+-	if (S_ISFIFO(file->f_dentry->d_inode->i_mode)) {
++	if (S_ISFIFO(file->f_path.dentry->d_inode->i_mode)) {
+ 		ret = -ESPIPE;
+ 		goto out;
+ 	}
+diff --git a/mm/filemap.c b/mm/filemap.c
+index af7e2f5caea9..606432f71b3a 100644
+--- a/mm/filemap.c
++++ b/mm/filemap.c
+@@ -2269,7 +2269,7 @@ __generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
+ 	if (count == 0)
+ 		goto out;
+ 
+-	err = remove_suid(file->f_dentry);
++	err = remove_suid(file->f_path.dentry);
+ 	if (err)
+ 		goto out;
+ 
+diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
+index b4fd0d7c9bfb..8d667617f558 100644
+--- a/mm/filemap_xip.c
++++ b/mm/filemap_xip.c
+@@ -379,7 +379,7 @@ xip_file_write(struct file *filp, const char __user *buf, size_t len,
+ 	if (count == 0)
+ 		goto out_backing;
+ 
+-	ret = remove_suid(filp->f_dentry);
++	ret = remove_suid(filp->f_path.dentry);
+ 	if (ret)
+ 		goto out_backing;
+ 
+diff --git a/mm/mmap.c b/mm/mmap.c
+index 7be110e98d4c..9717337293c3 100644
+--- a/mm/mmap.c
++++ b/mm/mmap.c
+@@ -188,7 +188,7 @@ static void __remove_shared_vm_struct(struct vm_area_struct *vma,
+ 		struct file *file, struct address_space *mapping)
+ {
+ 	if (vma->vm_flags & VM_DENYWRITE)
+-		atomic_inc(&file->f_dentry->d_inode->i_writecount);
++		atomic_inc(&file->f_path.dentry->d_inode->i_writecount);
+ 	if (vma->vm_flags & VM_SHARED)
+ 		mapping->i_mmap_writable--;
+ 
+@@ -399,7 +399,7 @@ static inline void __vma_link_file(struct vm_area_struct *vma)
+ 		struct address_space *mapping = file->f_mapping;
+ 
+ 		if (vma->vm_flags & VM_DENYWRITE)
+-			atomic_dec(&file->f_dentry->d_inode->i_writecount);
++			atomic_dec(&file->f_path.dentry->d_inode->i_writecount);
+ 		if (vma->vm_flags & VM_SHARED)
+ 			mapping->i_mmap_writable++;
+ 
+@@ -907,7 +907,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
+ 	 *  mounted, in which case we dont add PROT_EXEC.)
+ 	 */
+ 	if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC))
+-		if (!(file && (file->f_vfsmnt->mnt_flags & MNT_NOEXEC)))
++		if (!(file && (file->f_path.mnt->mnt_flags & MNT_NOEXEC)))
+ 			prot |= PROT_EXEC;
+ 
+ 	if (!len)
+@@ -960,7 +960,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
+ 			return -EAGAIN;
+ 	}
+ 
+-	inode = file ? file->f_dentry->d_inode : NULL;
++	inode = file ? file->f_path.dentry->d_inode : NULL;
+ 
+ 	if (file) {
+ 		switch (flags & MAP_TYPE) {
+@@ -989,7 +989,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
+ 		case MAP_PRIVATE:
+ 			if (!(file->f_mode & FMODE_READ))
+ 				return -EACCES;
+-			if (file->f_vfsmnt->mnt_flags & MNT_NOEXEC) {
++			if (file->f_path.mnt->mnt_flags & MNT_NOEXEC) {
+ 				if (vm_flags & VM_EXEC)
+ 					return -EPERM;
+ 				vm_flags &= ~VM_MAYEXEC;
+diff --git a/mm/shmem.c b/mm/shmem.c
+index c820b4f77b8d..4bb28d218eb5 100644
+--- a/mm/shmem.c
++++ b/mm/shmem.c
+@@ -1225,7 +1225,7 @@ static int shmem_getpage(struct inode *inode, unsigned long idx,
+ 
+ struct page *shmem_nopage(struct vm_area_struct *vma, unsigned long address, int *type)
+ {
+-	struct inode *inode = vma->vm_file->f_dentry->d_inode;
++	struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
+ 	struct page *page = NULL;
+ 	unsigned long idx;
+ 	int error;
+@@ -1248,7 +1248,7 @@ static int shmem_populate(struct vm_area_struct *vma,
+ 	unsigned long addr, unsigned long len,
+ 	pgprot_t prot, unsigned long pgoff, int nonblock)
+ {
+-	struct inode *inode = vma->vm_file->f_dentry->d_inode;
++	struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
+ 	struct mm_struct *mm = vma->vm_mm;
+ 	enum sgp_type sgp = nonblock? SGP_QUICK: SGP_CACHE;
+ 	unsigned long size;
+@@ -1293,14 +1293,14 @@ static int shmem_populate(struct vm_area_struct *vma,
+ #ifdef CONFIG_NUMA
+ int shmem_set_policy(struct vm_area_struct *vma, struct mempolicy *new)
+ {
+-	struct inode *i = vma->vm_file->f_dentry->d_inode;
++	struct inode *i = vma->vm_file->f_path.dentry->d_inode;
+ 	return mpol_set_shared_policy(&SHMEM_I(i)->policy, vma, new);
+ }
+ 
+ struct mempolicy *
+ shmem_get_policy(struct vm_area_struct *vma, unsigned long addr)
+ {
+-	struct inode *i = vma->vm_file->f_dentry->d_inode;
++	struct inode *i = vma->vm_file->f_path.dentry->d_inode;
+ 	unsigned long idx;
+ 
+ 	idx = ((addr - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
+@@ -1310,7 +1310,7 @@ shmem_get_policy(struct vm_area_struct *vma, unsigned long addr)
+ 
+ int shmem_lock(struct file *file, int lock, struct user_struct *user)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	struct shmem_inode_info *info = SHMEM_I(inode);
+ 	int retval = -ENOMEM;
+ 
+@@ -1422,7 +1422,7 @@ shmem_prepare_write(struct file *file, struct page *page, unsigned offset, unsig
+ static ssize_t
+ shmem_file_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+ {
+-	struct inode	*inode = file->f_dentry->d_inode;
++	struct inode	*inode = file->f_path.dentry->d_inode;
+ 	loff_t		pos;
+ 	unsigned long	written;
+ 	ssize_t		err;
+@@ -1442,7 +1442,7 @@ shmem_file_write(struct file *file, const char __user *buf, size_t count, loff_t
+ 	if (err || !count)
+ 		goto out;
+ 
+-	err = remove_suid(file->f_dentry);
++	err = remove_suid(file->f_path.dentry);
+ 	if (err)
+ 		goto out;
+ 
+@@ -1524,7 +1524,7 @@ shmem_file_write(struct file *file, const char __user *buf, size_t count, loff_t
+ 
+ static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_t *desc, read_actor_t actor)
+ {
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct address_space *mapping = inode->i_mapping;
+ 	unsigned long index, offset;
+ 
+@@ -2493,8 +2493,8 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
+ 	d_instantiate(dentry, inode);
+ 	inode->i_size = size;
+ 	inode->i_nlink = 0;	/* It is unlinked */
+-	file->f_vfsmnt = mntget(shm_mnt);
+-	file->f_dentry = dentry;
++	file->f_path.mnt = mntget(shm_mnt);
++	file->f_path.dentry = dentry;
+ 	file->f_mapping = inode->i_mapping;
+ 	file->f_op = &shmem_file_operations;
+ 	file->f_mode = FMODE_WRITE | FMODE_READ;
+diff --git a/mm/swapfile.c b/mm/swapfile.c
+index c5431072f422..b9fc0e5de6d5 100644
+--- a/mm/swapfile.c
++++ b/mm/swapfile.c
+@@ -1357,10 +1357,10 @@ static int swap_show(struct seq_file *swap, void *v)
+ 	}
+ 
+ 	file = ptr->swap_file;
+-	len = seq_path(swap, file->f_vfsmnt, file->f_dentry, " \t\n\\");
++	len = seq_path(swap, file->f_path.mnt, file->f_path.dentry, " \t\n\\");
+ 	seq_printf(swap, "%*s%s\t%u\t%u\t%d\n",
+ 		       len < 40 ? 40 - len : 1, " ",
+-		       S_ISBLK(file->f_dentry->d_inode->i_mode) ?
++		       S_ISBLK(file->f_path.dentry->d_inode->i_mode) ?
+ 				"partition" : "file\t",
+ 		       ptr->pages << (PAGE_SHIFT - 10),
+ 		       ptr->inuse_pages << (PAGE_SHIFT - 10),

commit f3a43f3f64bff8e205c3702f6b4804d66e306848
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:43 2006 -0800
+
+    [PATCH] kernel: change uses of f_{dentry, vfsmnt} to use f_path
+    
+    Change all the uses of f_{dentry,vfsmnt} to f_path.{dentry,mnt} in
+    linux/kernel/.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/kernel/acct.c b/kernel/acct.c
+index 69a40c9777a2..70d0d88e5554 100644
+--- a/kernel/acct.c
++++ b/kernel/acct.c
+@@ -118,7 +118,7 @@ static int check_free_space(struct file *file)
+ 	spin_unlock(&acct_globals.lock);
+ 
+ 	/* May block */
+-	if (vfs_statfs(file->f_dentry, &sbuf))
++	if (vfs_statfs(file->f_path.dentry, &sbuf))
+ 		return res;
+ 	suspend = sbuf.f_blocks * SUSPEND;
+ 	resume = sbuf.f_blocks * RESUME;
+@@ -194,7 +194,7 @@ static void acct_file_reopen(struct file *file)
+ 		add_timer(&acct_globals.timer);
+ 	}
+ 	if (old_acct) {
+-		mnt_unpin(old_acct->f_vfsmnt);
++		mnt_unpin(old_acct->f_path.mnt);
+ 		spin_unlock(&acct_globals.lock);
+ 		do_acct_process(old_acct);
+ 		filp_close(old_acct, NULL);
+@@ -212,7 +212,7 @@ static int acct_on(char *name)
+ 	if (IS_ERR(file))
+ 		return PTR_ERR(file);
+ 
+-	if (!S_ISREG(file->f_dentry->d_inode->i_mode)) {
++	if (!S_ISREG(file->f_path.dentry->d_inode->i_mode)) {
+ 		filp_close(file, NULL);
+ 		return -EACCES;
+ 	}
+@@ -229,11 +229,11 @@ static int acct_on(char *name)
+ 	}
+ 
+ 	spin_lock(&acct_globals.lock);
+-	mnt_pin(file->f_vfsmnt);
++	mnt_pin(file->f_path.mnt);
+ 	acct_file_reopen(file);
+ 	spin_unlock(&acct_globals.lock);
+ 
+-	mntput(file->f_vfsmnt);	/* it's pinned, now give up active reference */
++	mntput(file->f_path.mnt); /* it's pinned, now give up active reference */
+ 
+ 	return 0;
+ }
+@@ -283,7 +283,7 @@ asmlinkage long sys_acct(const char __user *name)
+ void acct_auto_close_mnt(struct vfsmount *m)
+ {
+ 	spin_lock(&acct_globals.lock);
+-	if (acct_globals.file && acct_globals.file->f_vfsmnt == m)
++	if (acct_globals.file && acct_globals.file->f_path.mnt == m)
+ 		acct_file_reopen(NULL);
+ 	spin_unlock(&acct_globals.lock);
+ }
+@@ -299,7 +299,7 @@ void acct_auto_close(struct super_block *sb)
+ {
+ 	spin_lock(&acct_globals.lock);
+ 	if (acct_globals.file &&
+-	    acct_globals.file->f_vfsmnt->mnt_sb == sb) {
++	    acct_globals.file->f_path.mnt->mnt_sb == sb) {
+ 		acct_file_reopen(NULL);
+ 	}
+ 	spin_unlock(&acct_globals.lock);
+diff --git a/kernel/fork.c b/kernel/fork.c
+index f387a1393ca5..597707819327 100644
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -252,7 +252,7 @@ static inline int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
+ 		anon_vma_link(tmp);
+ 		file = tmp->vm_file;
+ 		if (file) {
+-			struct inode *inode = file->f_dentry->d_inode;
++			struct inode *inode = file->f_path.dentry->d_inode;
+ 			get_file(file);
+ 			if (tmp->vm_flags & VM_DENYWRITE)
+ 				atomic_dec(&inode->i_writecount);
+diff --git a/kernel/futex.c b/kernel/futex.c
+index 95989a3b4168..5a737de857d3 100644
+--- a/kernel/futex.c
++++ b/kernel/futex.c
+@@ -166,7 +166,7 @@ static inline int match_futex(union futex_key *key1, union futex_key *key2)
+ /*
+  * Get parameters which are the keys for a futex.
+  *
+- * For shared mappings, it's (page->index, vma->vm_file->f_dentry->d_inode,
++ * For shared mappings, it's (page->index, vma->vm_file->f_path.dentry->d_inode,
+  * offset_within_page).  For private mappings, it's (uaddr, current->mm).
+  * We can usually work out the index without swapping in the page.
+  *
+@@ -223,7 +223,7 @@ static int get_futex_key(u32 __user *uaddr, union futex_key *key)
+ 	/*
+ 	 * Linear file mappings are also simple.
+ 	 */
+-	key->shared.inode = vma->vm_file->f_dentry->d_inode;
++	key->shared.inode = vma->vm_file->f_path.dentry->d_inode;
+ 	key->both.offset++; /* Bit 0 of offset indicates inode-based key. */
+ 	if (likely(!(vma->vm_flags & VM_NONLINEAR))) {
+ 		key->shared.pgoff = (((address - vma->vm_start) >> PAGE_SHIFT)
+@@ -1528,9 +1528,9 @@ static int futex_fd(u32 __user *uaddr, int signal)
+ 		goto out;
+ 	}
+ 	filp->f_op = &futex_fops;
+-	filp->f_vfsmnt = mntget(futex_mnt);
+-	filp->f_dentry = dget(futex_mnt->mnt_root);
+-	filp->f_mapping = filp->f_dentry->d_inode->i_mapping;
++	filp->f_path.mnt = mntget(futex_mnt);
++	filp->f_path.dentry = dget(futex_mnt->mnt_root);
++	filp->f_mapping = filp->f_path.dentry->d_inode->i_mapping;
+ 
+ 	if (signal) {
+ 		err = __f_setown(filp, task_pid(current), PIDTYPE_PID, 1);
+diff --git a/kernel/relay.c b/kernel/relay.c
+index 75a3a9a7efc2..818e514729cf 100644
+--- a/kernel/relay.c
++++ b/kernel/relay.c
+@@ -959,7 +959,7 @@ static inline ssize_t relay_file_read_subbufs(struct file *filp,
+ 	if (!desc->count)
+ 		return 0;
+ 
+-	mutex_lock(&filp->f_dentry->d_inode->i_mutex);
++	mutex_lock(&filp->f_path.dentry->d_inode->i_mutex);
+ 	do {
+ 		if (!relay_file_read_avail(buf, *ppos))
+ 			break;
+@@ -979,7 +979,7 @@ static inline ssize_t relay_file_read_subbufs(struct file *filp,
+ 			*ppos = relay_file_read_end_pos(buf, read_start, ret);
+ 		}
+ 	} while (desc->count && ret);
+-	mutex_unlock(&filp->f_dentry->d_inode->i_mutex);
++	mutex_unlock(&filp->f_path.dentry->d_inode->i_mutex);
+ 
+ 	return desc->written;
+ }
+diff --git a/kernel/sysctl.c b/kernel/sysctl.c
+index 8e9f00fd6d18..9846db93a595 100644
+--- a/kernel/sysctl.c
++++ b/kernel/sysctl.c
+@@ -1614,7 +1614,7 @@ static ssize_t do_rw_proc(int write, struct file * file, char __user * buf,
+ 			  size_t count, loff_t *ppos)
+ {
+ 	int op;
+-	struct proc_dir_entry *de = PDE(file->f_dentry->d_inode);
++	struct proc_dir_entry *de = PDE(file->f_path.dentry->d_inode);
+ 	struct ctl_table *table;
+ 	size_t res;
+ 	ssize_t error = -ENOTDIR;

commit c941192aafe053ae445fb22f5d89bd34794c5442
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:43 2006 -0800
+
+    [PATCH] x86_64: change uses of f_{dentry, vfsmnt} to use f_path
+    
+    Change all the uses of f_{dentry,vfsmnt} to f_path.{dentry,mnt} in the x86_64
+    arch code.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/x86_64/ia32/ia32_aout.c b/arch/x86_64/ia32/ia32_aout.c
+index 396d3c100011..be87df506f39 100644
+--- a/arch/x86_64/ia32/ia32_aout.c
++++ b/arch/x86_64/ia32/ia32_aout.c
+@@ -272,7 +272,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+ 	if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
+ 	     N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||
+ 	    N_TRSIZE(ex) || N_DRSIZE(ex) ||
+-	    i_size_read(bprm->file->f_dentry->d_inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
++	    i_size_read(bprm->file->f_path.dentry->d_inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
+ 		return -ENOEXEC;
+ 	}
+ 
+@@ -357,7 +357,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+ 		{
+ 			printk(KERN_WARNING 
+ 			       "fd_offset is not page aligned. Please convert program: %s\n",
+-			       bprm->file->f_dentry->d_name.name);
++			       bprm->file->f_path.dentry->d_name.name);
+ 			error_time = jiffies;
+ 		}
+ #endif
+@@ -440,7 +440,7 @@ static int load_aout_library(struct file *file)
+ 	int retval;
+ 	struct exec ex;
+ 
+-	inode = file->f_dentry->d_inode;
++	inode = file->f_path.dentry->d_inode;
+ 
+ 	retval = -ENOEXEC;
+ 	error = kernel_read(file, 0, (char *) &ex, sizeof(ex));
+@@ -471,7 +471,7 @@ static int load_aout_library(struct file *file)
+ 		{
+ 			printk(KERN_WARNING 
+ 			       "N_TXTOFF is not page aligned. Please convert library: %s\n",
+-			       file->f_dentry->d_name.name);
++			       file->f_path.dentry->d_name.name);
+ 			error_time = jiffies;
+ 		}
+ #endif

commit aab4c5a51cd6defc374ba1961c996781656d5283
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:42 2006 -0800
+
+    [PATCH] i386: change uses of f_{dentry, vfsmnt} to use f_path
+    
+    Change all the uses of f_{dentry,vfsmnt} to f_path.{dentry,mnt} in the i386
+    arch code.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c
+index db6dd20c3589..51130b39cd2e 100644
+--- a/arch/i386/kernel/cpuid.c
++++ b/arch/i386/kernel/cpuid.c
+@@ -116,7 +116,7 @@ static ssize_t cpuid_read(struct file *file, char __user *buf,
+ 	char __user *tmp = buf;
+ 	u32 data[4];
+ 	u32 reg = *ppos;
+-	int cpu = iminor(file->f_dentry->d_inode);
++	int cpu = iminor(file->f_path.dentry->d_inode);
+ 
+ 	if (count % 16)
+ 		return -EINVAL;	/* Invalid chunk size */
+@@ -134,7 +134,7 @@ static ssize_t cpuid_read(struct file *file, char __user *buf,
+ 
+ static int cpuid_open(struct inode *inode, struct file *file)
+ {
+-	unsigned int cpu = iminor(file->f_dentry->d_inode);
++	unsigned int cpu = iminor(file->f_path.dentry->d_inode);
+ 	struct cpuinfo_x86 *c = &(cpu_data)[cpu];
+ 
+ 	if (cpu >= NR_CPUS || !cpu_online(cpu))
+diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c
+index 1d1a56cae340..4a472a17d1c6 100644
+--- a/arch/i386/kernel/msr.c
++++ b/arch/i386/kernel/msr.c
+@@ -172,7 +172,7 @@ static ssize_t msr_read(struct file *file, char __user * buf,
+ 	u32 __user *tmp = (u32 __user *) buf;
+ 	u32 data[2];
+ 	u32 reg = *ppos;
+-	int cpu = iminor(file->f_dentry->d_inode);
++	int cpu = iminor(file->f_path.dentry->d_inode);
+ 	int err;
+ 
+ 	if (count % 8)
+@@ -196,7 +196,7 @@ static ssize_t msr_write(struct file *file, const char __user *buf,
+ 	const u32 __user *tmp = (const u32 __user *)buf;
+ 	u32 data[2];
+ 	u32 reg = *ppos;
+-	int cpu = iminor(file->f_dentry->d_inode);
++	int cpu = iminor(file->f_path.dentry->d_inode);
+ 	int err;
+ 
+ 	if (count % 8)
+@@ -216,7 +216,7 @@ static ssize_t msr_write(struct file *file, const char __user *buf,
+ 
+ static int msr_open(struct inode *inode, struct file *file)
+ {
+-	unsigned int cpu = iminor(file->f_dentry->d_inode);
++	unsigned int cpu = iminor(file->f_path.dentry->d_inode);
+ 	struct cpuinfo_x86 *c = &(cpu_data)[cpu];
+ 
+ 	if (cpu >= NR_CPUS || !cpu_online(cpu))

commit 20d29372d3facfd078b4c7703637b951914d6759
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:41 2006 -0800
+
+    [PATCH] ntfs: change uses of f_{dentry, vfsmnt} to use f_path
+    
+    Change all the uses of f_{dentry,vfsmnt} to f_path.{dentry,mnt} in the ntfs
+    filesystem code.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c
+index 85c36b8ca452..8296c29ae3b8 100644
+--- a/fs/ntfs/dir.c
++++ b/fs/ntfs/dir.c
+@@ -1101,7 +1101,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ {
+ 	s64 ia_pos, ia_start, prev_ia_pos, bmp_pos;
+ 	loff_t fpos, i_size;
+-	struct inode *bmp_vi, *vdir = filp->f_dentry->d_inode;
++	struct inode *bmp_vi, *vdir = filp->f_path.dentry->d_inode;
+ 	struct super_block *sb = vdir->i_sb;
+ 	ntfs_inode *ndir = NTFS_I(vdir);
+ 	ntfs_volume *vol = NTFS_SB(sb);
+@@ -1136,9 +1136,9 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ 	if (fpos == 1) {
+ 		ntfs_debug("Calling filldir for .. with len 2, fpos 0x1, "
+ 				"inode 0x%lx, DT_DIR.",
+-				(unsigned long)parent_ino(filp->f_dentry));
++				(unsigned long)parent_ino(filp->f_path.dentry));
+ 		rc = filldir(dirent, "..", 2, fpos,
+-				parent_ino(filp->f_dentry), DT_DIR);
++				parent_ino(filp->f_path.dentry), DT_DIR);
+ 		if (rc)
+ 			goto done;
+ 		fpos++;
+diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
+index ae2fe0016d2c..076c9420c257 100644
+--- a/fs/ntfs/file.c
++++ b/fs/ntfs/file.c
+@@ -2162,7 +2162,7 @@ static ssize_t ntfs_file_aio_write_nolock(struct kiocb *iocb,
+ 		goto out;
+ 	if (!count)
+ 		goto out;
+-	err = remove_suid(file->f_dentry);
++	err = remove_suid(file->f_path.dentry);
+ 	if (err)
+ 		goto out;
+ 	file_update_time(file);

commit 7eaa36e2d470ed63bf0c4e4dd8b09cc4a9e1c481
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:41 2006 -0800
+
+    [PATCH] nfsd: change uses of f_{dentry, vfsmnt} to use f_path
+    
+    Change all the uses of f_{dentry,vfsmnt} to f_path.{dentry,mnt} in the nfs
+    server code.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 640c92b2a9f7..b7179bd45a1e 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1310,7 +1310,7 @@ static inline void
+ nfs4_file_downgrade(struct file *filp, unsigned int share_access)
+ {
+ 	if (share_access & NFS4_SHARE_ACCESS_WRITE) {
+-		put_write_access(filp->f_dentry->d_inode);
++		put_write_access(filp->f_path.dentry->d_inode);
+ 		filp->f_mode = (filp->f_mode | FMODE_READ) & ~FMODE_WRITE;
+ 	}
+ }
+@@ -1623,7 +1623,7 @@ static __be32
+ nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_stateid *stp, struct nfsd4_open *open)
+ {
+ 	struct file *filp = stp->st_vfs_file;
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	unsigned int share_access, new_writer;
+ 	__be32 status;
+ 
+@@ -1965,7 +1965,7 @@ search_close_lru(u32 st_id, int flags)
+ static inline int
+ nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp)
+ {
+-	return fhp->fh_dentry->d_inode != stp->st_vfs_file->f_dentry->d_inode;
++	return fhp->fh_dentry->d_inode != stp->st_vfs_file->f_path.dentry->d_inode;
+ }
+ 
+ static int
+@@ -2862,7 +2862,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
+ 	 * only the dentry:inode set.
+ 	 */
+ 	memset(&file, 0, sizeof (struct file));
+-	file.f_dentry = current_fh->fh_dentry;
++	file.f_path.dentry = current_fh->fh_dentry;
+ 
+ 	status = nfs_ok;
+ 	if (posix_test_lock(&file, &file_lock, &conflock)) {
+@@ -2952,7 +2952,7 @@ static int
+ check_for_locks(struct file *filp, struct nfs4_stateowner *lowner)
+ {
+ 	struct file_lock **flpp;
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	int status = 0;
+ 
+ 	lock_kernel();
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index 39aed901514b..eedf2e3990a9 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -111,7 +111,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
+ 
+ static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
+ {
+-	ino_t ino =  file->f_dentry->d_inode->i_ino;
++	ino_t ino =  file->f_path.dentry->d_inode->i_ino;
+ 	char *data;
+ 	ssize_t rv;
+ 
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index bb4d926e4487..d610edde9386 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -736,10 +736,10 @@ static int
+ nfsd_sync(struct file *filp)
+ {
+         int err;
+-	struct inode *inode = filp->f_dentry->d_inode;
+-	dprintk("nfsd: sync file %s\n", filp->f_dentry->d_name.name);
++	struct inode *inode = filp->f_path.dentry->d_inode;
++	dprintk("nfsd: sync file %s\n", filp->f_path.dentry->d_name.name);
+ 	mutex_lock(&inode->i_mutex);
+-	err=nfsd_dosync(filp, filp->f_dentry, filp->f_op);
++	err=nfsd_dosync(filp, filp->f_path.dentry, filp->f_op);
+ 	mutex_unlock(&inode->i_mutex);
+ 
+ 	return err;
+@@ -845,7 +845,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+ 	int		host_err;
+ 
+ 	err = nfserr_perm;
+-	inode = file->f_dentry->d_inode;
++	inode = file->f_path.dentry->d_inode;
+ #ifdef MSNFS
+ 	if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
+ 		(!lock_may_read(inode, offset, *count)))
+@@ -883,7 +883,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+ 		nfsdstats.io_read += host_err;
+ 		*count = host_err;
+ 		err = 0;
+-		fsnotify_access(file->f_dentry);
++		fsnotify_access(file->f_path.dentry);
+ 	} else 
+ 		err = nfserrno(host_err);
+ out:
+@@ -917,11 +917,11 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+ 	err = nfserr_perm;
+ 
+ 	if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
+-		(!lock_may_write(file->f_dentry->d_inode, offset, cnt)))
++		(!lock_may_write(file->f_path.dentry->d_inode, offset, cnt)))
+ 		goto out;
+ #endif
+ 
+-	dentry = file->f_dentry;
++	dentry = file->f_path.dentry;
+ 	inode = dentry->d_inode;
+ 	exp   = fhp->fh_export;
+ 
+@@ -950,7 +950,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+ 	set_fs(oldfs);
+ 	if (host_err >= 0) {
+ 		nfsdstats.io_write += cnt;
+-		fsnotify_modify(file->f_dentry);
++		fsnotify_modify(file->f_path.dentry);
+ 	}
+ 
+ 	/* clear setuid/setgid flag after write */

commit 01cce933d8b524d9312f5098c70fa1b6ac190572
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:40 2006 -0800
+
+    [PATCH] nfs: change uses of f_{dentry,vfsmnt} to use f_path
+    
+    Change all the uses of f_{dentry,vfsmnt} to f_path.{dentry,mnt} in the nfs
+    client code.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
+index b34cd16f472f..dee3d6c0f194 100644
+--- a/fs/nfs/dir.c
++++ b/fs/nfs/dir.c
+@@ -172,7 +172,7 @@ static
+ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
+ {
+ 	struct file	*file = desc->file;
+-	struct inode	*inode = file->f_dentry->d_inode;
++	struct inode	*inode = file->f_path.dentry->d_inode;
+ 	struct rpc_cred	*cred = nfs_file_cred(file);
+ 	unsigned long	timestamp;
+ 	int		error;
+@@ -183,7 +183,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
+ 
+  again:
+ 	timestamp = jiffies;
+-	error = NFS_PROTO(inode)->readdir(file->f_dentry, cred, desc->entry->cookie, page,
++	error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, desc->entry->cookie, page,
+ 					  NFS_SERVER(inode)->dtsize, desc->plus);
+ 	if (error < 0) {
+ 		/* We requested READDIRPLUS, but the server doesn't grok it */
+@@ -308,7 +308,7 @@ int find_dirent_index(nfs_readdir_descriptor_t *desc)
+ static inline
+ int find_dirent_page(nfs_readdir_descriptor_t *desc)
+ {
+-	struct inode	*inode = desc->file->f_dentry->d_inode;
++	struct inode	*inode = desc->file->f_path.dentry->d_inode;
+ 	struct page	*page;
+ 	int		status;
+ 
+@@ -464,7 +464,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
+ 		     filldir_t filldir)
+ {
+ 	struct file	*file = desc->file;
+-	struct inode	*inode = file->f_dentry->d_inode;
++	struct inode	*inode = file->f_path.dentry->d_inode;
+ 	struct rpc_cred	*cred = nfs_file_cred(file);
+ 	struct page	*page = NULL;
+ 	int		status;
+@@ -477,7 +477,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
+ 		status = -ENOMEM;
+ 		goto out;
+ 	}
+-	desc->error = NFS_PROTO(inode)->readdir(file->f_dentry, cred, *desc->dir_cookie,
++	desc->error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, *desc->dir_cookie,
+ 						page,
+ 						NFS_SERVER(inode)->dtsize,
+ 						desc->plus);
+@@ -516,7 +516,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
+  */
+ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ {
+-	struct dentry	*dentry = filp->f_dentry;
++	struct dentry	*dentry = filp->f_path.dentry;
+ 	struct inode	*inode = dentry->d_inode;
+ 	nfs_readdir_descriptor_t my_desc,
+ 			*desc = &my_desc;
+@@ -599,7 +599,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ 
+ loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin)
+ {
+-	mutex_lock(&filp->f_dentry->d_inode->i_mutex);
++	mutex_lock(&filp->f_path.dentry->d_inode->i_mutex);
+ 	switch (origin) {
+ 		case 1:
+ 			offset += filp->f_pos;
+@@ -615,7 +615,7 @@ loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin)
+ 		((struct nfs_open_context *)filp->private_data)->dir_cookie = 0;
+ 	}
+ out:
+-	mutex_unlock(&filp->f_dentry->d_inode->i_mutex);
++	mutex_unlock(&filp->f_path.dentry->d_inode->i_mutex);
+ 	return offset;
+ }
+ 
+@@ -1102,7 +1102,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
+ 
+ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc)
+ {
+-	struct dentry *parent = desc->file->f_dentry;
++	struct dentry *parent = desc->file->f_path.dentry;
+ 	struct inode *dir = parent->d_inode;
+ 	struct nfs_entry *entry = desc->entry;
+ 	struct dentry *dentry, *alias;
+diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
+index f9d678f4ae06..bd21d7fde650 100644
+--- a/fs/nfs/direct.c
++++ b/fs/nfs/direct.c
+@@ -116,7 +116,7 @@ static inline int put_dreq(struct nfs_direct_req *dreq)
+ ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t pos, unsigned long nr_segs)
+ {
+ 	dprintk("NFS: nfs_direct_IO (%s) off/no(%Ld/%lu) EINVAL\n",
+-			iocb->ki_filp->f_dentry->d_name.name,
++			iocb->ki_filp->f_path.dentry->d_name.name,
+ 			(long long) pos, nr_segs);
+ 
+ 	return -EINVAL;
+@@ -734,8 +734,8 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov,
+ 	size_t count = iov[0].iov_len;
+ 
+ 	dprintk("nfs: direct read(%s/%s, %lu@%Ld)\n",
+-		file->f_dentry->d_parent->d_name.name,
+-		file->f_dentry->d_name.name,
++		file->f_path.dentry->d_parent->d_name.name,
++		file->f_path.dentry->d_name.name,
+ 		(unsigned long) count, (long long) pos);
+ 
+ 	if (nr_segs != 1)
+@@ -798,8 +798,8 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
+ 	size_t count = iov[0].iov_len;
+ 
+ 	dfprintk(VFS, "nfs: direct write(%s/%s, %lu@%Ld)\n",
+-		file->f_dentry->d_parent->d_name.name,
+-		file->f_dentry->d_name.name,
++		file->f_path.dentry->d_parent->d_name.name,
++		file->f_path.dentry->d_name.name,
+ 		(unsigned long) count, (long long) pos);
+ 
+ 	if (nr_segs != 1)
+diff --git a/fs/nfs/file.c b/fs/nfs/file.c
+index 8e28bffc35a0..0dd6be346aa7 100644
+--- a/fs/nfs/file.c
++++ b/fs/nfs/file.c
+@@ -176,7 +176,7 @@ static int
+ nfs_file_flush(struct file *file, fl_owner_t id)
+ {
+ 	struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data;
+-	struct inode	*inode = file->f_dentry->d_inode;
++	struct inode	*inode = file->f_path.dentry->d_inode;
+ 	int		status;
+ 
+ 	dfprintk(VFS, "nfs: flush(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino);
+@@ -201,7 +201,7 @@ static ssize_t
+ nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
+ 		unsigned long nr_segs, loff_t pos)
+ {
+-	struct dentry * dentry = iocb->ki_filp->f_dentry;
++	struct dentry * dentry = iocb->ki_filp->f_path.dentry;
+ 	struct inode * inode = dentry->d_inode;
+ 	ssize_t result;
+ 	size_t count = iov_length(iov, nr_segs);
+@@ -226,7 +226,7 @@ static ssize_t
+ nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count,
+ 		read_actor_t actor, void *target)
+ {
+-	struct dentry *dentry = filp->f_dentry;
++	struct dentry *dentry = filp->f_path.dentry;
+ 	struct inode *inode = dentry->d_inode;
+ 	ssize_t res;
+ 
+@@ -243,7 +243,7 @@ nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count,
+ static int
+ nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
+ {
+-	struct dentry *dentry = file->f_dentry;
++	struct dentry *dentry = file->f_path.dentry;
+ 	struct inode *inode = dentry->d_inode;
+ 	int	status;
+ 
+@@ -343,7 +343,7 @@ const struct address_space_operations nfs_file_aops = {
+ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
+ 				unsigned long nr_segs, loff_t pos)
+ {
+-	struct dentry * dentry = iocb->ki_filp->f_dentry;
++	struct dentry * dentry = iocb->ki_filp->f_path.dentry;
+ 	struct inode * inode = dentry->d_inode;
+ 	ssize_t result;
+ 	size_t count = iov_length(iov, nr_segs);
+@@ -535,8 +535,8 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
+ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
+ {
+ 	dprintk("NFS: nfs_flock(f=%s/%ld, t=%x, fl=%x)\n",
+-			filp->f_dentry->d_inode->i_sb->s_id,
+-			filp->f_dentry->d_inode->i_ino,
++			filp->f_path.dentry->d_inode->i_sb->s_id,
++			filp->f_path.dentry->d_inode->i_ino,
+ 			fl->fl_type, fl->fl_flags);
+ 
+ 	/*
+diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
+index 82ad7110a1c0..9d4a6b2d1996 100644
+--- a/fs/nfs/idmap.c
++++ b/fs/nfs/idmap.c
+@@ -377,7 +377,7 @@ idmap_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg,
+ static ssize_t
+ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
+ {
+-        struct rpc_inode *rpci = RPC_I(filp->f_dentry->d_inode);
++        struct rpc_inode *rpci = RPC_I(filp->f_path.dentry->d_inode);
+ 	struct idmap *idmap = (struct idmap *)rpci->private;
+ 	struct idmap_msg im_in, *im = &idmap->idmap_im;
+ 	struct idmap_hashtable *h;
+diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
+index 36680d1061b0..63e470279309 100644
+--- a/fs/nfs/inode.c
++++ b/fs/nfs/inode.c
+@@ -496,7 +496,7 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
+  */
+ static void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
+ {
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct nfs_inode *nfsi = NFS_I(inode);
+ 
+ 	filp->private_data = get_nfs_open_context(ctx);
+@@ -528,7 +528,7 @@ struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_c
+ 
+ static void nfs_file_clear_open_context(struct file *filp)
+ {
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct nfs_open_context *ctx = (struct nfs_open_context *)filp->private_data;
+ 
+ 	if (ctx) {
+@@ -551,7 +551,7 @@ int nfs_open(struct inode *inode, struct file *filp)
+ 	cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
+ 	if (IS_ERR(cred))
+ 		return PTR_ERR(cred);
+-	ctx = alloc_nfs_open_context(filp->f_vfsmnt, filp->f_dentry, cred);
++	ctx = alloc_nfs_open_context(filp->f_path.mnt, filp->f_path.dentry, cred);
+ 	put_rpccred(cred);
+ 	if (ctx == NULL)
+ 		return -ENOMEM;
+diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
+index 510ae524f3fd..acd8fe9762d3 100644
+--- a/fs/nfs/nfs3proc.c
++++ b/fs/nfs/nfs3proc.c
+@@ -841,7 +841,7 @@ static void nfs3_proc_commit_setup(struct nfs_write_data *data, int how)
+ static int
+ nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
+ {
+-	return nlmclnt_proc(filp->f_dentry->d_inode, cmd, fl);
++	return nlmclnt_proc(filp->f_path.dentry->d_inode, cmd, fl);
+ }
+ 
+ const struct nfs_rpc_ops nfs_v3_clientops = {
+diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
+index 10f5e80ca157..560536ad74a4 100644
+--- a/fs/nfs/proc.c
++++ b/fs/nfs/proc.c
+@@ -651,7 +651,7 @@ nfs_proc_commit_setup(struct nfs_write_data *data, int how)
+ static int
+ nfs_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
+ {
+-	return nlmclnt_proc(filp->f_dentry->d_inode, cmd, fl);
++	return nlmclnt_proc(filp->f_path.dentry->d_inode, cmd, fl);
+ }
+ 
+ 
+diff --git a/fs/nfs/write.c b/fs/nfs/write.c
+index 594eb16879ef..345492e78643 100644
+--- a/fs/nfs/write.c
++++ b/fs/nfs/write.c
+@@ -754,8 +754,8 @@ int nfs_updatepage(struct file *file, struct page *page,
+ 	nfs_inc_stats(inode, NFSIOS_VFSUPDATEPAGE);
+ 
+ 	dprintk("NFS:      nfs_updatepage(%s/%s %d@%Ld)\n",
+-		file->f_dentry->d_parent->d_name.name,
+-		file->f_dentry->d_name.name, count,
++		file->f_path.dentry->d_parent->d_name.name,
++		file->f_path.dentry->d_name.name, count,
+ 		(long long)(page_offset(page) +offset));
+ 
+ 	/* If we're not using byte range locks, and we know the page

commit 2485822d51f8b338d289abe00eb7ce5249794a08
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:40 2006 -0800
+
+    [PATCH] isofs: change uses of f_{dentry, vfsmnt} to use f_path
+    
+    Change all the uses of f_{dentry,vfsmnt} to f_path.{dentry,mnt} in the isofs
+    filesystem.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/isofs/compress.c b/fs/isofs/compress.c
+index 731816332b12..6bbbdb53581d 100644
+--- a/fs/isofs/compress.c
++++ b/fs/isofs/compress.c
+@@ -42,7 +42,7 @@ static struct semaphore zisofs_zlib_semaphore;
+  */
+ static int zisofs_readpage(struct file *file, struct page *page)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	struct address_space *mapping = inode->i_mapping;
+ 	unsigned int maxpage, xpage, fpage, blockindex;
+ 	unsigned long offset;
+diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
+index 27e276987fd2..4af2548f97a9 100644
+--- a/fs/isofs/dir.c
++++ b/fs/isofs/dir.c
+@@ -183,7 +183,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
+ 
+ 		/* Handle the case of the '..' directory */
+ 		if (de->name_len[0] == 1 && de->name[0] == 1) {
+-			inode_number = parent_ino(filp->f_dentry);
++			inode_number = parent_ino(filp->f_path.dentry);
+ 			if (filldir(dirent, "..", 2, filp->f_pos, inode_number, DT_DIR) < 0)
+ 				break;
+ 			filp->f_pos += de_len;
+@@ -255,8 +255,7 @@ static int isofs_readdir(struct file *filp,
+ 	int result;
+ 	char * tmpname;
+ 	struct iso_directory_record * tmpde;
+-	struct inode *inode = filp->f_dentry->d_inode;
+-
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 
+ 	tmpname = (char *)__get_free_page(GFP_KERNEL);
+ 	if (tmpname == NULL)

commit dba32306099d6155b773ebe8fc5bcfab60d075d6
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:39 2006 -0800
+
+    [PATCH] fat: change uses of f_{dentry,vfsmnt} to use f_path
+    
+    Change all the uses of f_{dentry,vfsmnt} to f_path.{dentry,mnt} in the fat
+    filesystem.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/fat/dir.c b/fs/fat/dir.c
+index 69c439f44387..c16af246d245 100644
+--- a/fs/fat/dir.c
++++ b/fs/fat/dir.c
+@@ -579,7 +579,7 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent,
+ 	if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME))
+ 		inum = inode->i_ino;
+ 	else if (!memcmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) {
+-		inum = parent_ino(filp->f_dentry);
++		inum = parent_ino(filp->f_path.dentry);
+ 	} else {
+ 		loff_t i_pos = fat_make_i_pos(sb, bh, de);
+ 		struct inode *tmp = fat_iget(sb, i_pos);
+@@ -643,7 +643,7 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent,
+ 
+ static int fat_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ {
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	return __fat_readdir(inode, filp, dirent, filldir, 0, 0);
+ }
+ 
+@@ -782,7 +782,7 @@ static long fat_compat_dir_ioctl(struct file *file, unsigned cmd,
+ 
+ 	set_fs(KERNEL_DS);
+ 	lock_kernel();
+-	ret = fat_dir_ioctl(file->f_dentry->d_inode, file,
++	ret = fat_dir_ioctl(file->f_path.dentry->d_inode, file,
+ 			    cmd, (unsigned long) &d);
+ 	unlock_kernel();
+ 	set_fs(oldfs);
+diff --git a/fs/fat/file.c b/fs/fat/file.c
+index 0aa813d944a6..c1237b70c1fe 100644
+--- a/fs/fat/file.c
++++ b/fs/fat/file.c
+@@ -92,7 +92,7 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp,
+ 		}
+ 
+ 		/* This MUST be done before doing anything irreversible... */
+-		err = notify_change(filp->f_dentry, &ia);
++		err = notify_change(filp->f_path.dentry, &ia);
+ 		if (err)
+ 			goto up;
+ 

commit 9d549890e69156800878a486f832e92d8f3d7c97
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:38 2006 -0800
+
+    [PATCH] ext4: change uses of f_{dentry, vfsmnt} to use f_path
+    
+    Change all the uses of f_{dentry,vfsmnt} to f_path.{dentry,mnt} in the ext4
+    filesystem.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
+index f2ed3e7fb9f5..da80368b66f0 100644
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -103,7 +103,7 @@ static int ext4_readdir(struct file * filp,
+ 	struct ext4_dir_entry_2 *de;
+ 	struct super_block *sb;
+ 	int err;
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	int ret = 0;
+ 
+ 	sb = inode->i_sb;
+@@ -122,7 +122,7 @@ static int ext4_readdir(struct file * filp,
+ 		 * We don't set the inode dirty flag since it's not
+ 		 * critical that it get flushed back to the disk.
+ 		 */
+-		EXT4_I(filp->f_dentry->d_inode)->i_flags &= ~EXT4_INDEX_FL;
++		EXT4_I(filp->f_path.dentry->d_inode)->i_flags &= ~EXT4_INDEX_FL;
+ 	}
+ #endif
+ 	stored = 0;
+@@ -402,7 +402,7 @@ static int call_filldir(struct file * filp, void * dirent,
+ {
+ 	struct dir_private_info *info = filp->private_data;
+ 	loff_t	curr_pos;
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct super_block * sb;
+ 	int error;
+ 
+@@ -432,7 +432,7 @@ static int ext4_dx_readdir(struct file * filp,
+ 			 void * dirent, filldir_t filldir)
+ {
+ 	struct dir_private_info *info = filp->private_data;
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct fname *fname;
+ 	int	ret;
+ 
+diff --git a/fs/ext4/file.c b/fs/ext4/file.c
+index 0b622c0624b7..3bbc24b58785 100644
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -52,7 +52,7 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
+ 		unsigned long nr_segs, loff_t pos)
+ {
+ 	struct file *file = iocb->ki_filp;
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	ssize_t ret;
+ 	int err;
+ 
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index 22a737c306c7..500567dd53b6 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -256,7 +256,7 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+ #ifdef CONFIG_COMPAT
+ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	int ret;
+ 
+ 	/* These are just misnamed, they actually get/put from/to user an int */
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 859990eac504..e5a74a5ac261 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -602,7 +602,7 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
+ 
+ 	dxtrace(printk("In htree_fill_tree, start hash: %x:%x\n", start_hash,
+ 		       start_minor_hash));
+-	dir = dir_file->f_dentry->d_inode;
++	dir = dir_file->f_path.dentry->d_inode;
+ 	if (!(EXT4_I(dir)->i_flags & EXT4_INDEX_FL)) {
+ 		hinfo.hash_version = EXT4_SB(dir->i_sb)->s_def_hash_version;
+ 		hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed;
+@@ -613,7 +613,7 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
+ 	}
+ 	hinfo.hash = start_hash;
+ 	hinfo.minor_hash = 0;
+-	frame = dx_probe(NULL, dir_file->f_dentry->d_inode, &hinfo, frames, &err);
++	frame = dx_probe(NULL, dir_file->f_path.dentry->d_inode, &hinfo, frames, &err);
+ 	if (!frame)
+ 		return err;
+ 

commit fe21a69389165b9641a8d0b89e00a71c4e5f5d59
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:38 2006 -0800
+
+    [PATCH] ext3: change uses of f_{dentry, vfsmnt} to use f_path
+    
+    Change all the uses of f_{dentry,vfsmnt} to f_path.{dentry,mnt} in the ext3
+    filesystem.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c
+index 5a9313ecd4ef..665adee99b31 100644
+--- a/fs/ext3/dir.c
++++ b/fs/ext3/dir.c
+@@ -103,7 +103,7 @@ static int ext3_readdir(struct file * filp,
+ 	struct ext3_dir_entry_2 *de;
+ 	struct super_block *sb;
+ 	int err;
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	int ret = 0;
+ 
+ 	sb = inode->i_sb;
+@@ -122,7 +122,7 @@ static int ext3_readdir(struct file * filp,
+ 		 * We don't set the inode dirty flag since it's not
+ 		 * critical that it get flushed back to the disk.
+ 		 */
+-		EXT3_I(filp->f_dentry->d_inode)->i_flags &= ~EXT3_INDEX_FL;
++		EXT3_I(filp->f_path.dentry->d_inode)->i_flags &= ~EXT3_INDEX_FL;
+ 	}
+ #endif
+ 	stored = 0;
+@@ -402,7 +402,7 @@ static int call_filldir(struct file * filp, void * dirent,
+ {
+ 	struct dir_private_info *info = filp->private_data;
+ 	loff_t	curr_pos;
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct super_block * sb;
+ 	int error;
+ 
+@@ -432,7 +432,7 @@ static int ext3_dx_readdir(struct file * filp,
+ 			 void * dirent, filldir_t filldir)
+ {
+ 	struct dir_private_info *info = filp->private_data;
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct fname *fname;
+ 	int	ret;
+ 
+diff --git a/fs/ext3/file.c b/fs/ext3/file.c
+index e96c388047e0..881f6365c41a 100644
+--- a/fs/ext3/file.c
++++ b/fs/ext3/file.c
+@@ -52,7 +52,7 @@ ext3_file_write(struct kiocb *iocb, const struct iovec *iov,
+ 		unsigned long nr_segs, loff_t pos)
+ {
+ 	struct file *file = iocb->ki_filp;
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	ssize_t ret;
+ 	int err;
+ 
+diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c
+index 12daa6869572..9b8090d94e6c 100644
+--- a/fs/ext3/ioctl.c
++++ b/fs/ext3/ioctl.c
+@@ -257,7 +257,7 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+ #ifdef CONFIG_COMPAT
+ long ext3_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	int ret;
+ 
+ 	/* These are just misnamed, they actually get/put from/to user an int */
+diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
+index 60d2f9dbdb00..4df39c4315e1 100644
+--- a/fs/ext3/namei.c
++++ b/fs/ext3/namei.c
+@@ -602,7 +602,7 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash,
+ 
+ 	dxtrace(printk("In htree_fill_tree, start hash: %x:%x\n", start_hash,
+ 		       start_minor_hash));
+-	dir = dir_file->f_dentry->d_inode;
++	dir = dir_file->f_path.dentry->d_inode;
+ 	if (!(EXT3_I(dir)->i_flags & EXT3_INDEX_FL)) {
+ 		hinfo.hash_version = EXT3_SB(dir->i_sb)->s_def_hash_version;
+ 		hinfo.seed = EXT3_SB(dir->i_sb)->s_hash_seed;
+@@ -613,7 +613,7 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash,
+ 	}
+ 	hinfo.hash = start_hash;
+ 	hinfo.minor_hash = 0;
+-	frame = dx_probe(NULL, dir_file->f_dentry->d_inode, &hinfo, frames, &err);
++	frame = dx_probe(NULL, dir_file->f_path.dentry->d_inode, &hinfo, frames, &err);
+ 	if (!frame)
+ 		return err;
+ 

commit c29c6934304a05781c9bd1611bd98870689f34e7
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:37 2006 -0800
+
+    [PATCH] ext2: change uses of f_{dentry, vfsmnt} to use f_path
+    
+    Change all the uses of f_{dentry,vfsmnt} to f_path.{dentry,mnt} in the ext2
+    filesystem.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
+index 3e7a84a1e509..0b02ba9642d2 100644
+--- a/fs/ext2/dir.c
++++ b/fs/ext2/dir.c
+@@ -248,7 +248,7 @@ static int
+ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
+ {
+ 	loff_t pos = filp->f_pos;
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct super_block *sb = inode->i_sb;
+ 	unsigned int offset = pos & ~PAGE_CACHE_MASK;
+ 	unsigned long n = pos >> PAGE_CACHE_SHIFT;
+diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
+index e3cf8c81507f..4b099d310712 100644
+--- a/fs/ext2/ioctl.c
++++ b/fs/ext2/ioctl.c
+@@ -90,7 +90,7 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+ #ifdef CONFIG_COMPAT
+ long ext2_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	int ret;
+ 
+ 	/* These are just misnamed, they actually get/put from/to user an int */

commit 2fddfeefeed703b7638af97aa3048f82a2d53b03
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:36 2006 -0800
+
+    [PATCH] proc: change uses of f_{dentry, vfsmnt} to use f_path
+    
+    Change all the uses of f_{dentry,vfsmnt} to f_path.{dentry,mnt} in the proc
+    filesystem code.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/proc/base.c b/fs/proc/base.c
+index b859fc749c07..a71f1755bb57 100644
+--- a/fs/proc/base.c
++++ b/fs/proc/base.c
+@@ -472,7 +472,7 @@ static struct file_operations proc_mountstats_operations = {
+ static ssize_t proc_info_read(struct file * file, char __user * buf,
+ 			  size_t count, loff_t *ppos)
+ {
+-	struct inode * inode = file->f_dentry->d_inode;
++	struct inode * inode = file->f_path.dentry->d_inode;
+ 	unsigned long page;
+ 	ssize_t length;
+ 	struct task_struct *task = get_proc_task(inode);
+@@ -512,7 +512,7 @@ static int mem_open(struct inode* inode, struct file* file)
+ static ssize_t mem_read(struct file * file, char __user * buf,
+ 			size_t count, loff_t *ppos)
+ {
+-	struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
++	struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
+ 	char *page;
+ 	unsigned long src = *ppos;
+ 	int ret = -ESRCH;
+@@ -584,7 +584,7 @@ static ssize_t mem_write(struct file * file, const char * buf,
+ {
+ 	int copied;
+ 	char *page;
+-	struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
++	struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
+ 	unsigned long dst = *ppos;
+ 
+ 	copied = -ESRCH;
+@@ -654,7 +654,7 @@ static struct file_operations proc_mem_operations = {
+ static ssize_t oom_adjust_read(struct file *file, char __user *buf,
+ 				size_t count, loff_t *ppos)
+ {
+-	struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
++	struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
+ 	char buffer[PROC_NUMBUF];
+ 	size_t len;
+ 	int oom_adjust;
+@@ -694,7 +694,7 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf,
+ 		return -EINVAL;
+ 	if (*end == '\n')
+ 		end++;
+-	task = get_proc_task(file->f_dentry->d_inode);
++	task = get_proc_task(file->f_path.dentry->d_inode);
+ 	if (!task)
+ 		return -ESRCH;
+ 	if (oom_adjust < task->oomkilladj && !capable(CAP_SYS_RESOURCE)) {
+@@ -718,7 +718,7 @@ static struct file_operations proc_oom_adjust_operations = {
+ static ssize_t proc_loginuid_read(struct file * file, char __user * buf,
+ 				  size_t count, loff_t *ppos)
+ {
+-	struct inode * inode = file->f_dentry->d_inode;
++	struct inode * inode = file->f_path.dentry->d_inode;
+ 	struct task_struct *task = get_proc_task(inode);
+ 	ssize_t length;
+ 	char tmpbuf[TMPBUFLEN];
+@@ -734,7 +734,7 @@ static ssize_t proc_loginuid_read(struct file * file, char __user * buf,
+ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
+ 				   size_t count, loff_t *ppos)
+ {
+-	struct inode * inode = file->f_dentry->d_inode;
++	struct inode * inode = file->f_path.dentry->d_inode;
+ 	char *page, *tmp;
+ 	ssize_t length;
+ 	uid_t loginuid;
+@@ -1078,7 +1078,7 @@ static int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
+ 	char *name, int len,
+ 	instantiate_t instantiate, struct task_struct *task, void *ptr)
+ {
+-	struct dentry *child, *dir = filp->f_dentry;
++	struct dentry *child, *dir = filp->f_path.dentry;
+ 	struct inode *inode;
+ 	struct qstr qname;
+ 	ino_t ino = 0;
+@@ -1157,8 +1157,8 @@ static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsm
+ 		spin_lock(&files->file_lock);
+ 		file = fcheck_files(files, fd);
+ 		if (file) {
+-			*mnt = mntget(file->f_vfsmnt);
+-			*dentry = dget(file->f_dentry);
++			*mnt = mntget(file->f_path.mnt);
++			*dentry = dget(file->f_path.dentry);
+ 			spin_unlock(&files->file_lock);
+ 			put_files_struct(files);
+ 			return 0;
+@@ -1293,7 +1293,7 @@ static int proc_fd_fill_cache(struct file *filp, void *dirent, filldir_t filldir
+ 
+ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
+ {
+-	struct dentry *dentry = filp->f_dentry;
++	struct dentry *dentry = filp->f_path.dentry;
+ 	struct inode *inode = dentry->d_inode;
+ 	struct task_struct *p = get_proc_task(inode);
+ 	unsigned int fd, tid, ino;
+@@ -1440,7 +1440,7 @@ static int proc_pident_readdir(struct file *filp,
+ {
+ 	int i;
+ 	int pid;
+-	struct dentry *dentry = filp->f_dentry;
++	struct dentry *dentry = filp->f_path.dentry;
+ 	struct inode *inode = dentry->d_inode;
+ 	struct task_struct *task = get_proc_task(inode);
+ 	struct pid_entry *p, *last;
+@@ -1496,7 +1496,7 @@ static int proc_pident_readdir(struct file *filp,
+ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
+ 				  size_t count, loff_t *ppos)
+ {
+-	struct inode * inode = file->f_dentry->d_inode;
++	struct inode * inode = file->f_path.dentry->d_inode;
+ 	unsigned long page;
+ 	ssize_t length;
+ 	struct task_struct *task = get_proc_task(inode);
+@@ -1512,7 +1512,7 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
+ 		goto out;
+ 
+ 	length = security_getprocattr(task,
+-				      (char*)file->f_dentry->d_name.name,
++				      (char*)file->f_path.dentry->d_name.name,
+ 				      (void*)page, count);
+ 	if (length >= 0)
+ 		length = simple_read_from_buffer(buf, count, ppos, (char *)page, length);
+@@ -1526,7 +1526,7 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
+ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
+ 				   size_t count, loff_t *ppos)
+ {
+-	struct inode * inode = file->f_dentry->d_inode;
++	struct inode * inode = file->f_path.dentry->d_inode;
+ 	char *page;
+ 	ssize_t length;
+ 	struct task_struct *task = get_proc_task(inode);
+@@ -1552,7 +1552,7 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
+ 		goto out_free;
+ 
+ 	length = security_setprocattr(task,
+-				      (char*)file->f_dentry->d_name.name,
++				      (char*)file->f_path.dentry->d_name.name,
+ 				      (void*)page, count);
+ out_free:
+ 	free_page((unsigned long) page);
+@@ -1994,7 +1994,7 @@ static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldi
+ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
+ {
+ 	unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY;
+-	struct task_struct *reaper = get_proc_task(filp->f_dentry->d_inode);
++	struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode);
+ 	struct task_struct *task;
+ 	int tgid;
+ 
+@@ -2235,7 +2235,7 @@ static int proc_task_fill_cache(struct file *filp, void *dirent, filldir_t filld
+ /* for the /proc/TGID/task/ directories */
+ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldir)
+ {
+-	struct dentry *dentry = filp->f_dentry;
++	struct dentry *dentry = filp->f_path.dentry;
+ 	struct inode *inode = dentry->d_inode;
+ 	struct task_struct *leader = get_proc_task(inode);
+ 	struct task_struct *task;
+diff --git a/fs/proc/generic.c b/fs/proc/generic.c
+index 4ba03009cf72..853cb877d5f3 100644
+--- a/fs/proc/generic.c
++++ b/fs/proc/generic.c
+@@ -52,7 +52,7 @@ static ssize_t
+ proc_file_read(struct file *file, char __user *buf, size_t nbytes,
+ 	       loff_t *ppos)
+ {
+-	struct inode * inode = file->f_dentry->d_inode;
++	struct inode * inode = file->f_path.dentry->d_inode;
+ 	char 	*page;
+ 	ssize_t	retval=0;
+ 	int	eof=0;
+@@ -203,7 +203,7 @@ static ssize_t
+ proc_file_write(struct file *file, const char __user *buffer,
+ 		size_t count, loff_t *ppos)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	struct proc_dir_entry * dp;
+ 	
+ 	dp = PDE(inode);
+@@ -432,7 +432,7 @@ int proc_readdir(struct file * filp,
+ 	struct proc_dir_entry * de;
+ 	unsigned int ino;
+ 	int i;
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	int ret = 0;
+ 
+ 	lock_kernel();
+@@ -453,7 +453,7 @@ int proc_readdir(struct file * filp,
+ 			/* fall through */
+ 		case 1:
+ 			if (filldir(dirent, "..", 2, i,
+-				    parent_ino(filp->f_dentry),
++				    parent_ino(filp->f_path.dentry),
+ 				    DT_DIR) < 0)
+ 				goto out;
+ 			i++;
+@@ -558,7 +558,7 @@ static void proc_kill_inodes(struct proc_dir_entry *de)
+ 	file_list_lock();
+ 	list_for_each(p, &sb->s_files) {
+ 		struct file * filp = list_entry(p, struct file, f_u.fu_list);
+-		struct dentry * dentry = filp->f_dentry;
++		struct dentry * dentry = filp->f_path.dentry;
+ 		struct inode * inode;
+ 		const struct file_operations *fops;
+ 
+diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c
+index d7dbdf9e0f49..5ec67257e5f9 100644
+--- a/fs/proc/nommu.c
++++ b/fs/proc/nommu.c
+@@ -46,7 +46,7 @@ int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma)
+ 	file = vma->vm_file;
+ 
+ 	if (file) {
+-		struct inode *inode = vma->vm_file->f_dentry->d_inode;
++		struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
+ 		dev = inode->i_sb->s_dev;
+ 		ino = inode->i_ino;
+ 	}
+@@ -67,7 +67,7 @@ int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma)
+ 		if (len < 1)
+ 			len = 1;
+ 		seq_printf(m, "%*c", len, ' ');
+-		seq_path(m, file->f_vfsmnt, file->f_dentry, "");
++		seq_path(m, file->f_path.mnt, file->f_path.dentry, "");
+ 	}
+ 
+ 	seq_putc(m, '\n');
+diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
+index 6b769afac55a..55ade0d15621 100644
+--- a/fs/proc/task_mmu.c
++++ b/fs/proc/task_mmu.c
+@@ -94,8 +94,8 @@ int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfsmount *
+ 	}
+ 
+ 	if (vma) {
+-		*mnt = mntget(vma->vm_file->f_vfsmnt);
+-		*dentry = dget(vma->vm_file->f_dentry);
++		*mnt = mntget(vma->vm_file->f_path.mnt);
++		*dentry = dget(vma->vm_file->f_path.dentry);
+ 		result = 0;
+ 	}
+ 
+@@ -135,7 +135,7 @@ static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats
+ 	int len;
+ 
+ 	if (file) {
+-		struct inode *inode = vma->vm_file->f_dentry->d_inode;
++		struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
+ 		dev = inode->i_sb->s_dev;
+ 		ino = inode->i_ino;
+ 	}
+@@ -156,7 +156,7 @@ static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats
+ 	 */
+ 	if (file) {
+ 		pad_len_spaces(m, len);
+-		seq_path(m, file->f_vfsmnt, file->f_dentry, "\n");
++		seq_path(m, file->f_path.mnt, file->f_path.dentry, "\n");
+ 	} else {
+ 		const char *name = arch_vma_name(vma);
+ 		if (!name) {
+diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
+index 091aa8e48e02..fcc5caf93f55 100644
+--- a/fs/proc/task_nommu.c
++++ b/fs/proc/task_nommu.c
+@@ -126,8 +126,8 @@ int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfsmount *
+ 	}
+ 
+ 	if (vma) {
+-		*mnt = mntget(vma->vm_file->f_vfsmnt);
+-		*dentry = dget(vma->vm_file->f_dentry);
++		*mnt = mntget(vma->vm_file->f_path.mnt);
++		*dentry = dget(vma->vm_file->f_path.dentry);
+ 		result = 0;
+ 	}
+ 

commit f427f5d5d6b0eb729505a2d9c0a6cad22734a74c
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:36 2006 -0800
+
+    [PATCH] sysfs: change uses of f_{dentry, vfsmnt} to use f_path
+    
+    Change all the uses of f_{dentry,vfsmnt} to f_path.{dentry,mnt} in the sysfs
+    filesystem code.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
+index 98022e41cda1..e8f540d38d48 100644
+--- a/fs/sysfs/bin.c
++++ b/fs/sysfs/bin.c
+@@ -35,7 +35,7 @@ static ssize_t
+ read(struct file * file, char __user * userbuf, size_t count, loff_t * off)
+ {
+ 	char *buffer = file->private_data;
+-	struct dentry *dentry = file->f_dentry;
++	struct dentry *dentry = file->f_path.dentry;
+ 	int size = dentry->d_inode->i_size;
+ 	loff_t offs = *off;
+ 	int ret;
+@@ -81,7 +81,7 @@ static ssize_t write(struct file * file, const char __user * userbuf,
+ 		     size_t count, loff_t * off)
+ {
+ 	char *buffer = file->private_data;
+-	struct dentry *dentry = file->f_dentry;
++	struct dentry *dentry = file->f_path.dentry;
+ 	int size = dentry->d_inode->i_size;
+ 	loff_t offs = *off;
+ 
+@@ -105,7 +105,7 @@ static ssize_t write(struct file * file, const char __user * userbuf,
+ 
+ static int mmap(struct file *file, struct vm_area_struct *vma)
+ {
+-	struct dentry *dentry = file->f_dentry;
++	struct dentry *dentry = file->f_path.dentry;
+ 	struct bin_attribute *attr = to_bin_attr(dentry);
+ 	struct kobject *kobj = to_kobj(dentry->d_parent);
+ 
+@@ -117,8 +117,8 @@ static int mmap(struct file *file, struct vm_area_struct *vma)
+ 
+ static int open(struct inode * inode, struct file * file)
+ {
+-	struct kobject *kobj = sysfs_get_kobject(file->f_dentry->d_parent);
+-	struct bin_attribute * attr = to_bin_attr(file->f_dentry);
++	struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent);
++	struct bin_attribute * attr = to_bin_attr(file->f_path.dentry);
+ 	int error = -EINVAL;
+ 
+ 	if (!kobj || !attr)
+@@ -153,8 +153,8 @@ static int open(struct inode * inode, struct file * file)
+ 
+ static int release(struct inode * inode, struct file * file)
+ {
+-	struct kobject * kobj = to_kobj(file->f_dentry->d_parent);
+-	struct bin_attribute * attr = to_bin_attr(file->f_dentry);
++	struct kobject * kobj = to_kobj(file->f_path.dentry->d_parent);
++	struct bin_attribute * attr = to_bin_attr(file->f_path.dentry);
+ 	u8 * buffer = file->private_data;
+ 
+ 	if (kobj) 
+diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
+index a5782e8c7f07..511edef8b321 100644
+--- a/fs/sysfs/dir.c
++++ b/fs/sysfs/dir.c
+@@ -419,7 +419,7 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent)
+ 
+ static int sysfs_dir_open(struct inode *inode, struct file *file)
+ {
+-	struct dentry * dentry = file->f_dentry;
++	struct dentry * dentry = file->f_path.dentry;
+ 	struct sysfs_dirent * parent_sd = dentry->d_fsdata;
+ 
+ 	mutex_lock(&dentry->d_inode->i_mutex);
+@@ -432,7 +432,7 @@ static int sysfs_dir_open(struct inode *inode, struct file *file)
+ 
+ static int sysfs_dir_close(struct inode *inode, struct file *file)
+ {
+-	struct dentry * dentry = file->f_dentry;
++	struct dentry * dentry = file->f_path.dentry;
+ 	struct sysfs_dirent * cursor = file->private_data;
+ 
+ 	mutex_lock(&dentry->d_inode->i_mutex);
+@@ -452,7 +452,7 @@ static inline unsigned char dt_type(struct sysfs_dirent *sd)
+ 
+ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
+ {
+-	struct dentry *dentry = filp->f_dentry;
++	struct dentry *dentry = filp->f_path.dentry;
+ 	struct sysfs_dirent * parent_sd = dentry->d_fsdata;
+ 	struct sysfs_dirent *cursor = filp->private_data;
+ 	struct list_head *p, *q = &cursor->s_sibling;
+@@ -509,7 +509,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
+ 
+ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin)
+ {
+-	struct dentry * dentry = file->f_dentry;
++	struct dentry * dentry = file->f_path.dentry;
+ 
+ 	mutex_lock(&dentry->d_inode->i_mutex);
+ 	switch (origin) {
+@@ -519,7 +519,7 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin)
+ 			if (offset >= 0)
+ 				break;
+ 		default:
+-			mutex_unlock(&file->f_dentry->d_inode->i_mutex);
++			mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
+ 			return -EINVAL;
+ 	}
+ 	if (offset != file->f_pos) {
+diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
+index 95c165101c98..9cfe53e1e00d 100644
+--- a/fs/sysfs/file.c
++++ b/fs/sysfs/file.c
+@@ -154,7 +154,7 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+ 
+ 	down(&buffer->sem);
+ 	if (buffer->needs_read_fill) {
+-		if ((retval = fill_read_buffer(file->f_dentry,buffer)))
++		if ((retval = fill_read_buffer(file->f_path.dentry,buffer)))
+ 			goto out;
+ 	}
+ 	pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n",
+@@ -245,7 +245,7 @@ sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t
+ 	down(&buffer->sem);
+ 	len = fill_write_buffer(buffer, buf, count);
+ 	if (len > 0)
+-		len = flush_write_buffer(file->f_dentry, buffer, len);
++		len = flush_write_buffer(file->f_path.dentry, buffer, len);
+ 	if (len > 0)
+ 		*ppos += len;
+ 	up(&buffer->sem);
+@@ -254,8 +254,8 @@ sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t
+ 
+ static int check_perm(struct inode * inode, struct file * file)
+ {
+-	struct kobject *kobj = sysfs_get_kobject(file->f_dentry->d_parent);
+-	struct attribute * attr = to_attr(file->f_dentry);
++	struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent);
++	struct attribute * attr = to_attr(file->f_path.dentry);
+ 	struct sysfs_buffer * buffer;
+ 	struct sysfs_ops * ops = NULL;
+ 	int error = 0;
+@@ -337,8 +337,8 @@ static int sysfs_open_file(struct inode * inode, struct file * filp)
+ 
+ static int sysfs_release(struct inode * inode, struct file * filp)
+ {
+-	struct kobject * kobj = to_kobj(filp->f_dentry->d_parent);
+-	struct attribute * attr = to_attr(filp->f_dentry);
++	struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent);
++	struct attribute * attr = to_attr(filp->f_path.dentry);
+ 	struct module * owner = attr->owner;
+ 	struct sysfs_buffer * buffer = filp->private_data;
+ 
+@@ -372,8 +372,8 @@ static int sysfs_release(struct inode * inode, struct file * filp)
+ static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
+ {
+ 	struct sysfs_buffer * buffer = filp->private_data;
+-	struct kobject * kobj = to_kobj(filp->f_dentry->d_parent);
+-	struct sysfs_dirent * sd = filp->f_dentry->d_fsdata;
++	struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent);
++	struct sysfs_dirent * sd = filp->f_path.dentry->d_fsdata;
+ 	int res = 0;
+ 
+ 	poll_wait(filp, &kobj->poll, wait);

commit 0f7fc9e4d03987fe29f6dd4aa67e4c56eb7ecb05
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:35 2006 -0800
+
+    [PATCH] VFS: change struct file to use struct path
+    
+    This patch changes struct file to use struct path instead of having
+    independent pointers to struct dentry and struct vfsmount, and converts all
+    users of f_{dentry,vfsmnt} in fs/ to use f_path.{dentry,mnt}.
+    
+    Additionally, it adds two #define's to make the transition easier for users of
+    the f_dentry and f_vfsmnt.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
+index 517e111bb7ef..813a887cd2b3 100644
+--- a/fs/binfmt_aout.c
++++ b/fs/binfmt_aout.c
+@@ -274,7 +274,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+ 	if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
+ 	     N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||
+ 	    N_TRSIZE(ex) || N_DRSIZE(ex) ||
+-	    i_size_read(bprm->file->f_dentry->d_inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
++	    i_size_read(bprm->file->f_path.dentry->d_inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
+ 		return -ENOEXEC;
+ 	}
+ 
+@@ -389,7 +389,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+ 		{
+ 			printk(KERN_WARNING 
+ 			       "fd_offset is not page aligned. Please convert program: %s\n",
+-			       bprm->file->f_dentry->d_name.name);
++			       bprm->file->f_path.dentry->d_name.name);
+ 			error_time = jiffies;
+ 		}
+ 
+@@ -469,7 +469,7 @@ static int load_aout_library(struct file *file)
+ 	int retval;
+ 	struct exec ex;
+ 
+-	inode = file->f_dentry->d_inode;
++	inode = file->f_path.dentry->d_inode;
+ 
+ 	retval = -ENOEXEC;
+ 	error = kernel_read(file, 0, (char *) &ex, sizeof(ex));
+@@ -506,7 +506,7 @@ static int load_aout_library(struct file *file)
+ 		{
+ 			printk(KERN_WARNING 
+ 			       "N_TXTOFF is not page aligned. Please convert library: %s\n",
+-			       file->f_dentry->d_name.name);
++			       file->f_path.dentry->d_name.name);
+ 			error_time = jiffies;
+ 		}
+ 		down_write(¤t->mm->mmap_sem);
+diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
+index be5869d34999..c6dbb4a7ec78 100644
+--- a/fs/binfmt_elf.c
++++ b/fs/binfmt_elf.c
+@@ -1190,7 +1190,7 @@ static int maydump(struct vm_area_struct *vma)
+ 
+ 	/* Dump shared memory only if mapped from an anonymous file. */
+ 	if (vma->vm_flags & VM_SHARED)
+-		return vma->vm_file->f_dentry->d_inode->i_nlink == 0;
++		return vma->vm_file->f_path.dentry->d_inode->i_nlink == 0;
+ 
+ 	/* If it hasn't been written to, don't write it out */
+ 	if (!vma->anon_vma)
+diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
+index ed9a61c6beb3..9f0b7efc3df5 100644
+--- a/fs/binfmt_elf_fdpic.c
++++ b/fs/binfmt_elf_fdpic.c
+@@ -855,7 +855,7 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
+ 
+ dynamic_error:
+ 	printk("ELF FDPIC %s with invalid DYNAMIC section (inode=%lu)\n",
+-	       what, file->f_dentry->d_inode->i_ino);
++	       what, file->f_path.dentry->d_inode->i_ino);
+ 	return -ELIBBAD;
+ }
+ 
+@@ -1186,7 +1186,7 @@ static int maydump(struct vm_area_struct *vma)
+ 
+ 	/* Dump shared memory only if mapped from an anonymous file. */
+ 	if (vma->vm_flags & VM_SHARED) {
+-		if (vma->vm_file->f_dentry->d_inode->i_nlink == 0) {
++		if (vma->vm_file->f_path.dentry->d_inode->i_nlink == 0) {
+ 			kdcore("%08lx: %08lx: no (share)", vma->vm_start, vma->vm_flags);
+ 			return 1;
+ 		}
+diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
+index a62fd4018a20..ae8595d49856 100644
+--- a/fs/binfmt_flat.c
++++ b/fs/binfmt_flat.c
+@@ -429,7 +429,7 @@ static int load_flat_file(struct linux_binprm * bprm,
+ 	int ret;
+ 
+ 	hdr = ((struct flat_hdr *) bprm->buf);		/* exec-header */
+-	inode = bprm->file->f_dentry->d_inode;
++	inode = bprm->file->f_path.dentry->d_inode;
+ 
+ 	text_len  = ntohl(hdr->data_start);
+ 	data_len  = ntohl(hdr->data_end) - ntohl(hdr->data_start);
+diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
+index 1713c48fef54..00687ea62738 100644
+--- a/fs/binfmt_misc.c
++++ b/fs/binfmt_misc.c
+@@ -542,7 +542,7 @@ static void kill_node(Node *e)
+ static ssize_t
+ bm_entry_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos)
+ {
+-	Node *e = file->f_dentry->d_inode->i_private;
++	Node *e = file->f_path.dentry->d_inode->i_private;
+ 	loff_t pos = *ppos;
+ 	ssize_t res;
+ 	char *page;
+@@ -576,7 +576,7 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
+ 				size_t count, loff_t *ppos)
+ {
+ 	struct dentry *root;
+-	Node *e = file->f_dentry->d_inode->i_private;
++	Node *e = file->f_path.dentry->d_inode->i_private;
+ 	int res = parse_command(buffer, count);
+ 
+ 	switch (res) {
+@@ -584,7 +584,7 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
+ 			break;
+ 		case 2: set_bit(Enabled, &e->flags);
+ 			break;
+-		case 3: root = dget(file->f_vfsmnt->mnt_sb->s_root);
++		case 3: root = dget(file->f_path.mnt->mnt_sb->s_root);
+ 			mutex_lock(&root->d_inode->i_mutex);
+ 
+ 			kill_node(e);
+@@ -610,7 +610,7 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer,
+ 	Node *e;
+ 	struct inode *inode;
+ 	struct dentry *root, *dentry;
+-	struct super_block *sb = file->f_vfsmnt->mnt_sb;
++	struct super_block *sb = file->f_path.mnt->mnt_sb;
+ 	int err = 0;
+ 
+ 	e = create_entry(buffer, count);
+@@ -699,7 +699,7 @@ static ssize_t bm_status_write(struct file * file, const char __user * buffer,
+ 	switch (res) {
+ 		case 1: enabled = 0; break;
+ 		case 2: enabled = 1; break;
+-		case 3: root = dget(file->f_vfsmnt->mnt_sb->s_root);
++		case 3: root = dget(file->f_path.mnt->mnt_sb->s_root);
+ 			mutex_lock(&root->d_inode->i_mutex);
+ 
+ 			while (!list_empty(&entries))
+diff --git a/fs/block_dev.c b/fs/block_dev.c
+index f3c3a44dd8b6..197f93921847 100644
+--- a/fs/block_dev.c
++++ b/fs/block_dev.c
+@@ -190,7 +190,7 @@ static int blkdev_commit_write(struct file *file, struct page *page, unsigned fr
+ 
+ /*
+  * private llseek:
+- * for a block special file file->f_dentry->d_inode->i_size is zero
++ * for a block special file file->f_path.dentry->d_inode->i_size is zero
+  * so we compute the size by hand (just as in block_read/write above)
+  */
+ static loff_t block_llseek(struct file *file, loff_t offset, int origin)
+@@ -1013,7 +1013,7 @@ static int __blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags,
+ 	struct dentry fake_dentry = {};
+ 	fake_file.f_mode = mode;
+ 	fake_file.f_flags = flags;
+-	fake_file.f_dentry = &fake_dentry;
++	fake_file.f_path.dentry = &fake_dentry;
+ 	fake_dentry.d_inode = bdev->bd_inode;
+ 
+ 	return do_open(bdev, &fake_file, for_part);
+diff --git a/fs/compat.c b/fs/compat.c
+index a7e3f162fb15..b766964a625c 100644
+--- a/fs/compat.c
++++ b/fs/compat.c
+@@ -232,7 +232,7 @@ asmlinkage long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user
+ 	file = fget(fd);
+ 	if (!file)
+ 		goto out;
+-	error = vfs_statfs(file->f_dentry, &tmp);
++	error = vfs_statfs(file->f_path.dentry, &tmp);
+ 	if (!error)
+ 		error = put_compat_statfs(buf, &tmp);
+ 	fput(file);
+@@ -303,7 +303,7 @@ asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct c
+ 	file = fget(fd);
+ 	if (!file)
+ 		goto out;
+-	error = vfs_statfs(file->f_dentry, &tmp);
++	error = vfs_statfs(file->f_path.dentry, &tmp);
+ 	if (!error)
+ 		error = put_compat_statfs64(buf, &tmp);
+ 	fput(file);
+@@ -365,7 +365,7 @@ static void compat_ioctl_error(struct file *filp, unsigned int fd,
+ 	/* find the name of the device. */
+ 	path = (char *)__get_free_page(GFP_KERNEL);
+ 	if (path) {
+-		fn = d_path(filp->f_dentry, filp->f_vfsmnt, path, PAGE_SIZE);
++		fn = d_path(filp->f_path.dentry, filp->f_path.mnt, path, PAGE_SIZE);
+ 		if (IS_ERR(fn))
+ 			fn = "?";
+ 	}
+@@ -416,7 +416,7 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd,
+ 	case FIBMAP:
+ 	case FIGETBSZ:
+ 	case FIONREAD:
+-		if (S_ISREG(filp->f_dentry->d_inode->i_mode))
++		if (S_ISREG(filp->f_path.dentry->d_inode->i_mode))
+ 			break;
+ 		/*FALL THROUGH*/
+ 
+@@ -438,7 +438,7 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd,
+ 			goto found_handler;
+ 	}
+ 
+-	if (S_ISSOCK(filp->f_dentry->d_inode->i_mode) &&
++	if (S_ISSOCK(filp->f_path.dentry->d_inode->i_mode) &&
+ 	    cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
+ 		error = siocdevprivate_ioctl(fd, cmd, arg);
+ 	} else {
+@@ -1259,7 +1259,7 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
+ 	if (iov != iovstack)
+ 		kfree(iov);
+ 	if ((ret + (type == READ)) > 0) {
+-		struct dentry *dentry = file->f_dentry;
++		struct dentry *dentry = file->f_path.dentry;
+ 		if (type == READ)
+ 			fsnotify_access(dentry);
+ 		else
+diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
+index bcc3caf5d820..c81c958b3e1d 100644
+--- a/fs/compat_ioctl.c
++++ b/fs/compat_ioctl.c
+@@ -1177,7 +1177,7 @@ static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long ar
+ static int vt_check(struct file *file)
+ {
+ 	struct tty_struct *tty;
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	
+ 	if (file->f_op->ioctl != tty_ioctl)
+ 		return -EINVAL;
+diff --git a/fs/dnotify.c b/fs/dnotify.c
+index 1f26a2b9eee1..936409fcd939 100644
+--- a/fs/dnotify.c
++++ b/fs/dnotify.c
+@@ -42,7 +42,7 @@ void dnotify_flush(struct file *filp, fl_owner_t id)
+ 	struct dnotify_struct **prev;
+ 	struct inode *inode;
+ 
+-	inode = filp->f_dentry->d_inode;
++	inode = filp->f_path.dentry->d_inode;
+ 	if (!S_ISDIR(inode->i_mode))
+ 		return;
+ 	spin_lock(&inode->i_lock);
+@@ -74,7 +74,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
+ 	}
+ 	if (!dir_notify_enable)
+ 		return -EINVAL;
+-	inode = filp->f_dentry->d_inode;
++	inode = filp->f_path.dentry->d_inode;
+ 	if (!S_ISDIR(inode->i_mode))
+ 		return -ENOTDIR;
+ 	dn = kmem_cache_alloc(dn_cache, GFP_KERNEL);
+diff --git a/fs/dquot.c b/fs/dquot.c
+index 89066b19124d..0952cc474d9a 100644
+--- a/fs/dquot.c
++++ b/fs/dquot.c
+@@ -694,9 +694,9 @@ static void add_dquot_ref(struct super_block *sb, int type)
+ 	file_list_lock();
+ 	list_for_each(p, &sb->s_files) {
+ 		struct file *filp = list_entry(p, struct file, f_u.fu_list);
+-		struct inode *inode = filp->f_dentry->d_inode;
++		struct inode *inode = filp->f_path.dentry->d_inode;
+ 		if (filp->f_mode & FMODE_WRITE && dqinit_needed(inode, type)) {
+-			struct dentry *dentry = dget(filp->f_dentry);
++			struct dentry *dentry = dget(filp->f_path.dentry);
+ 			file_list_unlock();
+ 			sb->dq_op->initialize(inode, type);
+ 			dput(dentry);
+diff --git a/fs/eventpoll.c b/fs/eventpoll.c
+index 88a6f8d0b88e..3ae644e7e860 100644
+--- a/fs/eventpoll.c
++++ b/fs/eventpoll.c
+@@ -795,8 +795,8 @@ static int ep_getfd(int *efd, struct inode **einode, struct file **efile,
+ 		goto eexit_4;
+ 	dentry->d_op = &eventpollfs_dentry_operations;
+ 	d_add(dentry, inode);
+-	file->f_vfsmnt = mntget(eventpoll_mnt);
+-	file->f_dentry = dentry;
++	file->f_path.mnt = mntget(eventpoll_mnt);
++	file->f_path.dentry = dentry;
+ 	file->f_mapping = inode->i_mapping;
+ 
+ 	file->f_pos = 0;
+diff --git a/fs/exec.c b/fs/exec.c
+index add0e03c3ea9..60433e2254a4 100644
+--- a/fs/exec.c
++++ b/fs/exec.c
+@@ -912,7 +912,7 @@ EXPORT_SYMBOL(flush_old_exec);
+ int prepare_binprm(struct linux_binprm *bprm)
+ {
+ 	int mode;
+-	struct inode * inode = bprm->file->f_dentry->d_inode;
++	struct inode * inode = bprm->file->f_path.dentry->d_inode;
+ 	int retval;
+ 
+ 	mode = inode->i_mode;
+@@ -922,7 +922,7 @@ int prepare_binprm(struct linux_binprm *bprm)
+ 	bprm->e_uid = current->euid;
+ 	bprm->e_gid = current->egid;
+ 
+-	if(!(bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID)) {
++	if(!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) {
+ 		/* Set-uid? */
+ 		if (mode & S_ISUID) {
+ 			current->personality &= ~PER_CLEAR_ON_SETID;
+@@ -1519,10 +1519,10 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
+ 				 0600);
+ 	if (IS_ERR(file))
+ 		goto fail_unlock;
+-	inode = file->f_dentry->d_inode;
++	inode = file->f_path.dentry->d_inode;
+ 	if (inode->i_nlink > 1)
+ 		goto close_fail;	/* multiple links - don't dump */
+-	if (!ispipe && d_unhashed(file->f_dentry))
++	if (!ispipe && d_unhashed(file->f_path.dentry))
+ 		goto close_fail;
+ 
+ 	/* AK: actually i see no reason to not allow this for named pipes etc.,
+@@ -1533,7 +1533,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
+ 		goto close_fail;
+ 	if (!file->f_op->write)
+ 		goto close_fail;
+-	if (!ispipe && do_truncate(file->f_dentry, 0, 0, file) != 0)
++	if (!ispipe && do_truncate(file->f_path.dentry, 0, 0, file) != 0)
+ 		goto close_fail;
+ 
+ 	retval = binfmt->core_dump(signr, regs, file);
+diff --git a/fs/fcntl.c b/fs/fcntl.c
+index 4740d35e52cd..2bdaef35da54 100644
+--- a/fs/fcntl.c
++++ b/fs/fcntl.c
+@@ -204,7 +204,7 @@ asmlinkage long sys_dup(unsigned int fildes)
+ 
+ static int setfl(int fd, struct file * filp, unsigned long arg)
+ {
+-	struct inode * inode = filp->f_dentry->d_inode;
++	struct inode * inode = filp->f_path.dentry->d_inode;
+ 	int error = 0;
+ 
+ 	/*
+diff --git a/fs/file_table.c b/fs/file_table.c
+index 24f25a057d9c..4c17a18d8c10 100644
+--- a/fs/file_table.c
++++ b/fs/file_table.c
+@@ -152,8 +152,8 @@ EXPORT_SYMBOL(fput);
+  */
+ void fastcall __fput(struct file *file)
+ {
+-	struct dentry *dentry = file->f_dentry;
+-	struct vfsmount *mnt = file->f_vfsmnt;
++	struct dentry *dentry = file->f_path.dentry;
++	struct vfsmount *mnt = file->f_path.mnt;
+ 	struct inode *inode = dentry->d_inode;
+ 
+ 	might_sleep();
+@@ -176,8 +176,8 @@ void fastcall __fput(struct file *file)
+ 		put_write_access(inode);
+ 	put_pid(file->f_owner.pid);
+ 	file_kill(file);
+-	file->f_dentry = NULL;
+-	file->f_vfsmnt = NULL;
++	file->f_path.dentry = NULL;
++	file->f_path.mnt = NULL;
+ 	file_free(file);
+ 	dput(dentry);
+ 	mntput(mnt);
+@@ -271,7 +271,7 @@ int fs_may_remount_ro(struct super_block *sb)
+ 	file_list_lock();
+ 	list_for_each(p, &sb->s_files) {
+ 		struct file *file = list_entry(p, struct file, f_u.fu_list);
+-		struct inode *inode = file->f_dentry->d_inode;
++		struct inode *inode = file->f_path.dentry->d_inode;
+ 
+ 		/* File with pending delete? */
+ 		if (inode->i_nlink == 0)
+diff --git a/fs/inode.c b/fs/inode.c
+index 9ecccab7326d..d00de182ecb9 100644
+--- a/fs/inode.c
++++ b/fs/inode.c
+@@ -1200,7 +1200,7 @@ EXPORT_SYMBOL(touch_atime);
+ 
+ void file_update_time(struct file *file)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	struct timespec now;
+ 	int sync_it = 0;
+ 
+diff --git a/fs/inotify_user.c b/fs/inotify_user.c
+index e1956e6f116c..55f6da55b7c0 100644
+--- a/fs/inotify_user.c
++++ b/fs/inotify_user.c
+@@ -570,9 +570,9 @@ asmlinkage long sys_inotify_init(void)
+ 	dev->ih = ih;
+ 
+ 	filp->f_op = &inotify_fops;
+-	filp->f_vfsmnt = mntget(inotify_mnt);
+-	filp->f_dentry = dget(inotify_mnt->mnt_root);
+-	filp->f_mapping = filp->f_dentry->d_inode->i_mapping;
++	filp->f_path.mnt = mntget(inotify_mnt);
++	filp->f_path.dentry = dget(inotify_mnt->mnt_root);
++	filp->f_mapping = filp->f_path.dentry->d_inode->i_mapping;
+ 	filp->f_mode = FMODE_READ;
+ 	filp->f_flags = O_RDONLY;
+ 	filp->private_data = dev;
+diff --git a/fs/ioctl.c b/fs/ioctl.c
+index 4b7660b09ac0..ff61772ceedd 100644
+--- a/fs/ioctl.c
++++ b/fs/ioctl.c
+@@ -31,7 +31,7 @@ static long do_ioctl(struct file *filp, unsigned int cmd,
+ 		goto out;
+ 	} else if (filp->f_op->ioctl) {
+ 		lock_kernel();
+-		error = filp->f_op->ioctl(filp->f_dentry->d_inode,
++		error = filp->f_op->ioctl(filp->f_path.dentry->d_inode,
+ 					  filp, cmd, arg);
+ 		unlock_kernel();
+ 	}
+@@ -45,7 +45,7 @@ static int file_ioctl(struct file *filp, unsigned int cmd,
+ {
+ 	int error;
+ 	int block;
+-	struct inode * inode = filp->f_dentry->d_inode;
++	struct inode * inode = filp->f_path.dentry->d_inode;
+ 	int __user *p = (int __user *)arg;
+ 
+ 	switch (cmd) {
+@@ -137,17 +137,17 @@ int vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, unsigned lon
+ 			break;
+ 
+ 		case FIOQSIZE:
+-			if (S_ISDIR(filp->f_dentry->d_inode->i_mode) ||
+-			    S_ISREG(filp->f_dentry->d_inode->i_mode) ||
+-			    S_ISLNK(filp->f_dentry->d_inode->i_mode)) {
+-				loff_t res = inode_get_bytes(filp->f_dentry->d_inode);
++			if (S_ISDIR(filp->f_path.dentry->d_inode->i_mode) ||
++			    S_ISREG(filp->f_path.dentry->d_inode->i_mode) ||
++			    S_ISLNK(filp->f_path.dentry->d_inode->i_mode)) {
++				loff_t res = inode_get_bytes(filp->f_path.dentry->d_inode);
+ 				error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0;
+ 			}
+ 			else
+ 				error = -ENOTTY;
+ 			break;
+ 		default:
+-			if (S_ISREG(filp->f_dentry->d_inode->i_mode))
++			if (S_ISREG(filp->f_path.dentry->d_inode->i_mode))
+ 				error = file_ioctl(filp, cmd, arg);
+ 			else
+ 				error = do_ioctl(filp, cmd, arg);
+diff --git a/fs/libfs.c b/fs/libfs.c
+index bd08e0e64a8c..503898d5c4a7 100644
+--- a/fs/libfs.c
++++ b/fs/libfs.c
+@@ -63,7 +63,7 @@ int dcache_dir_open(struct inode *inode, struct file *file)
+ {
+ 	static struct qstr cursor_name = {.len = 1, .name = "."};
+ 
+-	file->private_data = d_alloc(file->f_dentry, &cursor_name);
++	file->private_data = d_alloc(file->f_path.dentry, &cursor_name);
+ 
+ 	return file->private_data ? 0 : -ENOMEM;
+ }
+@@ -76,7 +76,7 @@ int dcache_dir_close(struct inode *inode, struct file *file)
+ 
+ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin)
+ {
+-	mutex_lock(&file->f_dentry->d_inode->i_mutex);
++	mutex_lock(&file->f_path.dentry->d_inode->i_mutex);
+ 	switch (origin) {
+ 		case 1:
+ 			offset += file->f_pos;
+@@ -84,7 +84,7 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin)
+ 			if (offset >= 0)
+ 				break;
+ 		default:
+-			mutex_unlock(&file->f_dentry->d_inode->i_mutex);
++			mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
+ 			return -EINVAL;
+ 	}
+ 	if (offset != file->f_pos) {
+@@ -96,8 +96,8 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin)
+ 
+ 			spin_lock(&dcache_lock);
+ 			list_del(&cursor->d_u.d_child);
+-			p = file->f_dentry->d_subdirs.next;
+-			while (n && p != &file->f_dentry->d_subdirs) {
++			p = file->f_path.dentry->d_subdirs.next;
++			while (n && p != &file->f_path.dentry->d_subdirs) {
+ 				struct dentry *next;
+ 				next = list_entry(p, struct dentry, d_u.d_child);
+ 				if (!d_unhashed(next) && next->d_inode)
+@@ -108,7 +108,7 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin)
+ 			spin_unlock(&dcache_lock);
+ 		}
+ 	}
+-	mutex_unlock(&file->f_dentry->d_inode->i_mutex);
++	mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
+ 	return offset;
+ }
+ 
+@@ -126,7 +126,7 @@ static inline unsigned char dt_type(struct inode *inode)
+ 
+ int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
+ {
+-	struct dentry *dentry = filp->f_dentry;
++	struct dentry *dentry = filp->f_path.dentry;
+ 	struct dentry *cursor = filp->private_data;
+ 	struct list_head *p, *q = &cursor->d_u.d_child;
+ 	ino_t ino;
+diff --git a/fs/locks.c b/fs/locks.c
+index 1cb0c57fedbd..52a81005dab4 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -321,7 +321,7 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl,
+ 		start = filp->f_pos;
+ 		break;
+ 	case SEEK_END:
+-		start = i_size_read(filp->f_dentry->d_inode);
++		start = i_size_read(filp->f_path.dentry->d_inode);
+ 		break;
+ 	default:
+ 		return -EINVAL;
+@@ -371,7 +371,7 @@ static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl,
+ 		start = filp->f_pos;
+ 		break;
+ 	case SEEK_END:
+-		start = i_size_read(filp->f_dentry->d_inode);
++		start = i_size_read(filp->f_path.dentry->d_inode);
+ 		break;
+ 	default:
+ 		return -EINVAL;
+@@ -672,7 +672,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl,
+ 	struct file_lock *cfl;
+ 
+ 	lock_kernel();
+-	for (cfl = filp->f_dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) {
++	for (cfl = filp->f_path.dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) {
+ 		if (!IS_POSIX(cfl))
+ 			continue;
+ 		if (posix_locks_conflict(cfl, fl))
+@@ -734,7 +734,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
+ {
+ 	struct file_lock *new_fl = NULL;
+ 	struct file_lock **before;
+-	struct inode * inode = filp->f_dentry->d_inode;
++	struct inode * inode = filp->f_path.dentry->d_inode;
+ 	int error = 0;
+ 	int found = 0;
+ 
+@@ -1018,7 +1018,7 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request
+  */
+ int posix_lock_file(struct file *filp, struct file_lock *fl)
+ {
+-	return __posix_lock_file_conf(filp->f_dentry->d_inode, fl, NULL);
++	return __posix_lock_file_conf(filp->f_path.dentry->d_inode, fl, NULL);
+ }
+ EXPORT_SYMBOL(posix_lock_file);
+ 
+@@ -1033,7 +1033,7 @@ EXPORT_SYMBOL(posix_lock_file);
+ int posix_lock_file_conf(struct file *filp, struct file_lock *fl,
+ 			struct file_lock *conflock)
+ {
+-	return __posix_lock_file_conf(filp->f_dentry->d_inode, fl, conflock);
++	return __posix_lock_file_conf(filp->f_path.dentry->d_inode, fl, conflock);
+ }
+ EXPORT_SYMBOL(posix_lock_file_conf);
+ 
+@@ -1333,8 +1333,8 @@ int fcntl_getlease(struct file *filp)
+ 	int type = F_UNLCK;
+ 
+ 	lock_kernel();
+-	time_out_leases(filp->f_dentry->d_inode);
+-	for (fl = filp->f_dentry->d_inode->i_flock; fl && IS_LEASE(fl);
++	time_out_leases(filp->f_path.dentry->d_inode);
++	for (fl = filp->f_path.dentry->d_inode->i_flock; fl && IS_LEASE(fl);
+ 			fl = fl->fl_next) {
+ 		if (fl->fl_file == filp) {
+ 			type = fl->fl_type & ~F_INPROGRESS;
+@@ -1359,7 +1359,7 @@ int fcntl_getlease(struct file *filp)
+ static int __setlease(struct file *filp, long arg, struct file_lock **flp)
+ {
+ 	struct file_lock *fl, **before, **my_before = NULL, *lease;
+-	struct dentry *dentry = filp->f_dentry;
++	struct dentry *dentry = filp->f_path.dentry;
+ 	struct inode *inode = dentry->d_inode;
+ 	int error, rdlease_count = 0, wrlease_count = 0;
+ 
+@@ -1448,7 +1448,7 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp)
+ 
+ int setlease(struct file *filp, long arg, struct file_lock **lease)
+ {
+-	struct dentry *dentry = filp->f_dentry;
++	struct dentry *dentry = filp->f_path.dentry;
+ 	struct inode *inode = dentry->d_inode;
+ 	int error;
+ 
+@@ -1482,7 +1482,7 @@ EXPORT_SYMBOL(setlease);
+ int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
+ {
+ 	struct file_lock fl, *flp = &fl;
+-	struct dentry *dentry = filp->f_dentry;
++	struct dentry *dentry = filp->f_path.dentry;
+ 	struct inode *inode = dentry->d_inode;
+ 	int error;
+ 
+@@ -1692,7 +1692,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
+ 	if (copy_from_user(&flock, l, sizeof(flock)))
+ 		goto out;
+ 
+-	inode = filp->f_dentry->d_inode;
++	inode = filp->f_path.dentry->d_inode;
+ 
+ 	/* Don't allow mandatory locks on files that may be memory mapped
+ 	 * and shared.
+@@ -1835,7 +1835,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
+ 	if (copy_from_user(&flock, l, sizeof(flock)))
+ 		goto out;
+ 
+-	inode = filp->f_dentry->d_inode;
++	inode = filp->f_path.dentry->d_inode;
+ 
+ 	/* Don't allow mandatory locks on files that may be memory mapped
+ 	 * and shared.
+@@ -1922,7 +1922,7 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)
+ 	 * posix_lock_file().  Another process could be setting a lock on this
+ 	 * file at the same time, but we wouldn't remove that lock anyway.
+ 	 */
+-	if (!filp->f_dentry->d_inode->i_flock)
++	if (!filp->f_path.dentry->d_inode->i_flock)
+ 		return;
+ 
+ 	lock.fl_type = F_UNLCK;
+@@ -1951,7 +1951,7 @@ EXPORT_SYMBOL(locks_remove_posix);
+  */
+ void locks_remove_flock(struct file *filp)
+ {
+-	struct inode * inode = filp->f_dentry->d_inode; 
++	struct inode * inode = filp->f_path.dentry->d_inode;
+ 	struct file_lock *fl;
+ 	struct file_lock **before;
+ 
+@@ -2020,7 +2020,7 @@ static void lock_get_status(char* out, struct file_lock *fl, int id, char *pfx)
+ 	struct inode *inode = NULL;
+ 
+ 	if (fl->fl_file != NULL)
+-		inode = fl->fl_file->f_dentry->d_inode;
++		inode = fl->fl_file->f_path.dentry->d_inode;
+ 
+ 	out += sprintf(out, "%d:%s ", id, pfx);
+ 	if (IS_POSIX(fl)) {
+diff --git a/fs/namei.c b/fs/namei.c
+index 8c2db88bb20d..e4f108f08230 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -297,7 +297,7 @@ int vfs_permission(struct nameidata *nd, int mask)
+  */
+ int file_permission(struct file *file, int mask)
+ {
+-	return permission(file->f_dentry->d_inode, mask, NULL);
++	return permission(file->f_path.dentry->d_inode, mask, NULL);
+ }
+ 
+ /*
+@@ -333,7 +333,7 @@ int get_write_access(struct inode * inode)
+ 
+ int deny_write_access(struct file * file)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 
+ 	spin_lock(&inode->i_lock);
+ 	if (atomic_read(&inode->i_writecount) > 0) {
+@@ -368,7 +368,7 @@ void path_release_on_umount(struct nameidata *nd)
+  */
+ void release_open_intent(struct nameidata *nd)
+ {
+-	if (nd->intent.open.file->f_dentry == NULL)
++	if (nd->intent.open.file->f_path.dentry == NULL)
+ 		put_filp(nd->intent.open.file);
+ 	else
+ 		fput(nd->intent.open.file);
+@@ -1138,7 +1138,7 @@ static int fastcall do_path_lookup(int dfd, const char *name,
+ 		if (!file)
+ 			goto out_fail;
+ 
+-		dentry = file->f_dentry;
++		dentry = file->f_path.dentry;
+ 
+ 		retval = -ENOTDIR;
+ 		if (!S_ISDIR(dentry->d_inode->i_mode))
+@@ -1148,7 +1148,7 @@ static int fastcall do_path_lookup(int dfd, const char *name,
+ 		if (retval)
+ 			goto fput_fail;
+ 
+-		nd->mnt = mntget(file->f_vfsmnt);
++		nd->mnt = mntget(file->f_path.mnt);
+ 		nd->dentry = dget(dentry);
+ 
+ 		fput_light(file, fput_needed);
+diff --git a/fs/open.c b/fs/open.c
+index 3b56192816ca..0d94319e8681 100644
+--- a/fs/open.c
++++ b/fs/open.c
+@@ -165,7 +165,7 @@ asmlinkage long sys_fstatfs(unsigned int fd, struct statfs __user * buf)
+ 	file = fget(fd);
+ 	if (!file)
+ 		goto out;
+-	error = vfs_statfs_native(file->f_dentry, &tmp);
++	error = vfs_statfs_native(file->f_path.dentry, &tmp);
+ 	if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
+ 		error = -EFAULT;
+ 	fput(file);
+@@ -186,7 +186,7 @@ asmlinkage long sys_fstatfs64(unsigned int fd, size_t sz, struct statfs64 __user
+ 	file = fget(fd);
+ 	if (!file)
+ 		goto out;
+-	error = vfs_statfs64(file->f_dentry, &tmp);
++	error = vfs_statfs64(file->f_path.dentry, &tmp);
+ 	if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
+ 		error = -EFAULT;
+ 	fput(file);
+@@ -302,7 +302,7 @@ static long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
+ 	if (file->f_flags & O_LARGEFILE)
+ 		small = 0;
+ 
+-	dentry = file->f_dentry;
++	dentry = file->f_path.dentry;
+ 	inode = dentry->d_inode;
+ 	error = -EINVAL;
+ 	if (!S_ISREG(inode->i_mode) || !(file->f_mode & FMODE_WRITE))
+@@ -448,8 +448,8 @@ asmlinkage long sys_fchdir(unsigned int fd)
+ 	if (!file)
+ 		goto out;
+ 
+-	dentry = file->f_dentry;
+-	mnt = file->f_vfsmnt;
++	dentry = file->f_path.dentry;
++	mnt = file->f_path.mnt;
+ 	inode = dentry->d_inode;
+ 
+ 	error = -ENOTDIR;
+@@ -503,7 +503,7 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
+ 	if (!file)
+ 		goto out;
+ 
+-	dentry = file->f_dentry;
++	dentry = file->f_path.dentry;
+ 	inode = dentry->d_inode;
+ 
+ 	audit_inode(NULL, inode);
+@@ -662,7 +662,7 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group)
+ 	if (!file)
+ 		goto out;
+ 
+-	dentry = file->f_dentry;
++	dentry = file->f_path.dentry;
+ 	audit_inode(NULL, dentry->d_inode);
+ 	error = chown_common(dentry, user, group);
+ 	fput(file);
+@@ -688,8 +688,8 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
+ 	}
+ 
+ 	f->f_mapping = inode->i_mapping;
+-	f->f_dentry = dentry;
+-	f->f_vfsmnt = mnt;
++	f->f_path.dentry = dentry;
++	f->f_path.mnt = mnt;
+ 	f->f_pos = 0;
+ 	f->f_op = fops_get(inode->i_fop);
+ 	file_move(f, &inode->i_sb->s_files);
+@@ -723,8 +723,8 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
+ 	if (f->f_mode & FMODE_WRITE)
+ 		put_write_access(inode);
+ 	file_kill(f);
+-	f->f_dentry = NULL;
+-	f->f_vfsmnt = NULL;
++	f->f_path.dentry = NULL;
++	f->f_path.mnt = NULL;
+ cleanup_file:
+ 	put_filp(f);
+ 	dput(dentry);
+@@ -822,7 +822,7 @@ struct file *nameidata_to_filp(struct nameidata *nd, int flags)
+ 	/* Pick up the filp from the open intent */
+ 	filp = nd->intent.open.file;
+ 	/* Has the filesystem initialised the file for us? */
+-	if (filp->f_dentry == NULL)
++	if (filp->f_path.dentry == NULL)
+ 		filp = __dentry_open(nd->dentry, nd->mnt, flags, filp, NULL);
+ 	else
+ 		path_release(nd);
+@@ -965,7 +965,7 @@ long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
+ 				put_unused_fd(fd);
+ 				fd = PTR_ERR(f);
+ 			} else {
+-				fsnotify_open(f->f_dentry);
++				fsnotify_open(f->f_path.dentry);
+ 				fd_install(fd, f);
+ 			}
+ 		}
+diff --git a/fs/pipe.c b/fs/pipe.c
+index ae36b89b1a37..f8b6bdcb879a 100644
+--- a/fs/pipe.c
++++ b/fs/pipe.c
+@@ -222,7 +222,7 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov,
+ 	   unsigned long nr_segs, loff_t pos)
+ {
+ 	struct file *filp = iocb->ki_filp;
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct pipe_inode_info *pipe;
+ 	int do_wakeup;
+ 	ssize_t ret;
+@@ -335,7 +335,7 @@ pipe_write(struct kiocb *iocb, const struct iovec *_iov,
+ 	    unsigned long nr_segs, loff_t ppos)
+ {
+ 	struct file *filp = iocb->ki_filp;
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct pipe_inode_info *pipe;
+ 	ssize_t ret;
+ 	int do_wakeup;
+@@ -520,7 +520,7 @@ static int
+ pipe_ioctl(struct inode *pino, struct file *filp,
+ 	   unsigned int cmd, unsigned long arg)
+ {
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct pipe_inode_info *pipe;
+ 	int count, buf, nrbufs;
+ 
+@@ -548,7 +548,7 @@ static unsigned int
+ pipe_poll(struct file *filp, poll_table *wait)
+ {
+ 	unsigned int mask;
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct pipe_inode_info *pipe = inode->i_pipe;
+ 	int nrbufs;
+ 
+@@ -601,7 +601,7 @@ pipe_release(struct inode *inode, int decr, int decw)
+ static int
+ pipe_read_fasync(int fd, struct file *filp, int on)
+ {
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	int retval;
+ 
+ 	mutex_lock(&inode->i_mutex);
+@@ -618,7 +618,7 @@ pipe_read_fasync(int fd, struct file *filp, int on)
+ static int
+ pipe_write_fasync(int fd, struct file *filp, int on)
+ {
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	int retval;
+ 
+ 	mutex_lock(&inode->i_mutex);
+@@ -635,7 +635,7 @@ pipe_write_fasync(int fd, struct file *filp, int on)
+ static int
+ pipe_rdwr_fasync(int fd, struct file *filp, int on)
+ {
+-	struct inode *inode = filp->f_dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct pipe_inode_info *pipe = inode->i_pipe;
+ 	int retval;
+ 
+@@ -914,8 +914,8 @@ struct file *create_write_pipe(void)
+ 	 */
+ 	dentry->d_flags &= ~DCACHE_UNHASHED;
+ 	d_instantiate(dentry, inode);
+-	f->f_vfsmnt = mntget(pipe_mnt);
+-	f->f_dentry = dentry;
++	f->f_path.mnt = mntget(pipe_mnt);
++	f->f_path.dentry = dentry;
+ 	f->f_mapping = inode->i_mapping;
+ 
+ 	f->f_flags = O_WRONLY;
+@@ -935,8 +935,8 @@ struct file *create_write_pipe(void)
+ 
+ void free_write_pipe(struct file *f)
+ {
+-	mntput(f->f_vfsmnt);
+-	dput(f->f_dentry);
++	mntput(f->f_path.mnt);
++	dput(f->f_path.dentry);
+ 	put_filp(f);
+ }
+ 
+@@ -947,9 +947,9 @@ struct file *create_read_pipe(struct file *wrf)
+ 		return ERR_PTR(-ENFILE);
+ 
+ 	/* Grab pipe from the writer */
+-	f->f_vfsmnt = mntget(wrf->f_vfsmnt);
+-	f->f_dentry = dget(wrf->f_dentry);
+-	f->f_mapping = wrf->f_dentry->d_inode->i_mapping;
++	f->f_path.mnt = mntget(wrf->f_path.mnt);
++	f->f_path.dentry = dget(wrf->f_path.dentry);
++	f->f_mapping = wrf->f_path.dentry->d_inode->i_mapping;
+ 
+ 	f->f_pos = 0;
+ 	f->f_flags = O_RDONLY;
+diff --git a/fs/read_write.c b/fs/read_write.c
+index f792000a28e6..1d3dda4fa70c 100644
+--- a/fs/read_write.c
++++ b/fs/read_write.c
+@@ -64,13 +64,13 @@ loff_t remote_llseek(struct file *file, loff_t offset, int origin)
+ 	lock_kernel();
+ 	switch (origin) {
+ 		case 2:
+-			offset += i_size_read(file->f_dentry->d_inode);
++			offset += i_size_read(file->f_path.dentry->d_inode);
+ 			break;
+ 		case 1:
+ 			offset += file->f_pos;
+ 	}
+ 	retval = -EINVAL;
+-	if (offset>=0 && offset<=file->f_dentry->d_inode->i_sb->s_maxbytes) {
++	if (offset>=0 && offset<=file->f_path.dentry->d_inode->i_sb->s_maxbytes) {
+ 		if (offset != file->f_pos) {
+ 			file->f_pos = offset;
+ 			file->f_version = 0;
+@@ -95,7 +95,7 @@ loff_t default_llseek(struct file *file, loff_t offset, int origin)
+ 	lock_kernel();
+ 	switch (origin) {
+ 		case 2:
+-			offset += i_size_read(file->f_dentry->d_inode);
++			offset += i_size_read(file->f_path.dentry->d_inode);
+ 			break;
+ 		case 1:
+ 			offset += file->f_pos;
+@@ -203,7 +203,7 @@ int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count
+ 	if (unlikely((pos < 0) || (loff_t) (pos + count) < 0))
+ 		goto Einval;
+ 
+-	inode = file->f_dentry->d_inode;
++	inode = file->f_path.dentry->d_inode;
+ 	if (unlikely(inode->i_flock && MANDATORY_LOCK(inode))) {
+ 		int retval = locks_mandatory_area(
+ 			read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE,
+@@ -273,7 +273,7 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
+ 			else
+ 				ret = do_sync_read(file, buf, count, pos);
+ 			if (ret > 0) {
+-				fsnotify_access(file->f_dentry);
++				fsnotify_access(file->f_path.dentry);
+ 				current->rchar += ret;
+ 			}
+ 			current->syscr++;
+@@ -331,7 +331,7 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_
+ 			else
+ 				ret = do_sync_write(file, buf, count, pos);
+ 			if (ret > 0) {
+-				fsnotify_modify(file->f_dentry);
++				fsnotify_modify(file->f_path.dentry);
+ 				current->wchar += ret;
+ 			}
+ 			current->syscw++;
+@@ -628,9 +628,9 @@ static ssize_t do_readv_writev(int type, struct file *file,
+ 		kfree(iov);
+ 	if ((ret + (type == READ)) > 0) {
+ 		if (type == READ)
+-			fsnotify_access(file->f_dentry);
++			fsnotify_access(file->f_path.dentry);
+ 		else
+-			fsnotify_modify(file->f_dentry);
++			fsnotify_modify(file->f_path.dentry);
+ 	}
+ 	return ret;
+ }
+@@ -722,7 +722,7 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
+ 	if (!(in_file->f_mode & FMODE_READ))
+ 		goto fput_in;
+ 	retval = -EINVAL;
+-	in_inode = in_file->f_dentry->d_inode;
++	in_inode = in_file->f_path.dentry->d_inode;
+ 	if (!in_inode)
+ 		goto fput_in;
+ 	if (!in_file->f_op || !in_file->f_op->sendfile)
+@@ -754,7 +754,7 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
+ 	retval = -EINVAL;
+ 	if (!out_file->f_op || !out_file->f_op->sendpage)
+ 		goto fput_out;
+-	out_inode = out_file->f_dentry->d_inode;
++	out_inode = out_file->f_path.dentry->d_inode;
+ 	retval = rw_verify_area(WRITE, out_file, &out_file->f_pos, count);
+ 	if (retval < 0)
+ 		goto fput_out;
+diff --git a/fs/readdir.c b/fs/readdir.c
+index bff3ee58e2f8..f39f5b313252 100644
+--- a/fs/readdir.c
++++ b/fs/readdir.c
+@@ -21,7 +21,7 @@
+ 
+ int vfs_readdir(struct file *file, filldir_t filler, void *buf)
+ {
+-	struct inode *inode = file->f_dentry->d_inode;
++	struct inode *inode = file->f_path.dentry->d_inode;
+ 	int res = -ENOTDIR;
+ 	if (!file->f_op || !file->f_op->readdir)
+ 		goto out;
+diff --git a/fs/seq_file.c b/fs/seq_file.c
+index 10690aa401c7..0ac22af7afe5 100644
+--- a/fs/seq_file.c
++++ b/fs/seq_file.c
+@@ -269,7 +269,7 @@ EXPORT_SYMBOL(seq_lseek);
+ /**
+  *	seq_release -	free the structures associated with sequential file.
+  *	@file: file in question
+- *	@inode: file->f_dentry->d_inode
++ *	@inode: file->f_path.dentry->d_inode
+  *
+  *	Frees the structures associated with sequential file; can be used
+  *	as ->f_op->release() if you don't have private data to destroy.
+diff --git a/fs/splice.c b/fs/splice.c
+index da74583a00ee..bbd0aeb3f68e 100644
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -844,7 +844,7 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out,
+ 	ssize_t ret;
+ 	int err;
+ 
+-	err = remove_suid(out->f_dentry);
++	err = remove_suid(out->f_path.dentry);
+ 	if (unlikely(err))
+ 		return err;
+ 
+@@ -890,10 +890,10 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
+ 	ssize_t ret;
+ 	int err;
+ 
+-	err = should_remove_suid(out->f_dentry);
++	err = should_remove_suid(out->f_path.dentry);
+ 	if (unlikely(err)) {
+ 		mutex_lock(&inode->i_mutex);
+-		err = __remove_suid(out->f_dentry, err);
++		err = __remove_suid(out->f_path.dentry, err);
+ 		mutex_unlock(&inode->i_mutex);
+ 		if (err)
+ 			return err;
+@@ -1008,7 +1008,7 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
+ 	 * randomly drop data for eg socket -> socket splicing. Use the
+ 	 * piped splicing for that!
+ 	 */
+-	i_mode = in->f_dentry->d_inode->i_mode;
++	i_mode = in->f_path.dentry->d_inode->i_mode;
+ 	if (unlikely(!S_ISREG(i_mode) && !S_ISBLK(i_mode)))
+ 		return -EINVAL;
+ 
+@@ -1132,7 +1132,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
+ 	loff_t offset, *off;
+ 	long ret;
+ 
+-	pipe = pipe_info(in->f_dentry->d_inode);
++	pipe = pipe_info(in->f_path.dentry->d_inode);
+ 	if (pipe) {
+ 		if (off_in)
+ 			return -ESPIPE;
+@@ -1153,7 +1153,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
+ 		return ret;
+ 	}
+ 
+-	pipe = pipe_info(out->f_dentry->d_inode);
++	pipe = pipe_info(out->f_path.dentry->d_inode);
+ 	if (pipe) {
+ 		if (off_out)
+ 			return -ESPIPE;
+@@ -1321,7 +1321,7 @@ static long do_vmsplice(struct file *file, const struct iovec __user *iov,
+ 		.ops = &user_page_pipe_buf_ops,
+ 	};
+ 
+-	pipe = pipe_info(file->f_dentry->d_inode);
++	pipe = pipe_info(file->f_path.dentry->d_inode);
+ 	if (!pipe)
+ 		return -EBADF;
+ 	if (unlikely(nr_segs > UIO_MAXIOV))
+@@ -1549,8 +1549,8 @@ static int link_pipe(struct pipe_inode_info *ipipe,
+ static long do_tee(struct file *in, struct file *out, size_t len,
+ 		   unsigned int flags)
+ {
+-	struct pipe_inode_info *ipipe = pipe_info(in->f_dentry->d_inode);
+-	struct pipe_inode_info *opipe = pipe_info(out->f_dentry->d_inode);
++	struct pipe_inode_info *ipipe = pipe_info(in->f_path.dentry->d_inode);
++	struct pipe_inode_info *opipe = pipe_info(out->f_path.dentry->d_inode);
+ 	int ret = -EINVAL;
+ 
+ 	/*
+diff --git a/fs/stat.c b/fs/stat.c
+index a0ebfc7f8a64..38a8cb2a28de 100644
+--- a/fs/stat.c
++++ b/fs/stat.c
+@@ -102,7 +102,7 @@ int vfs_fstat(unsigned int fd, struct kstat *stat)
+ 	int error = -EBADF;
+ 
+ 	if (f) {
+-		error = vfs_getattr(f->f_vfsmnt, f->f_dentry, stat);
++		error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, stat);
+ 		fput(f);
+ 	}
+ 	return error;
+diff --git a/fs/super.c b/fs/super.c
+index 84c320f6ad7e..f961e0307997 100644
+--- a/fs/super.c
++++ b/fs/super.c
+@@ -570,7 +570,7 @@ static void mark_files_ro(struct super_block *sb)
+ 
+ 	file_list_lock();
+ 	list_for_each_entry(f, &sb->s_files, f_u.fu_list) {
+-		if (S_ISREG(f->f_dentry->d_inode->i_mode) && file_count(f))
++		if (S_ISREG(f->f_path.dentry->d_inode->i_mode) && file_count(f))
+ 			f->f_mode &= ~FMODE_WRITE;
+ 	}
+ 	file_list_unlock();
+diff --git a/fs/sync.c b/fs/sync.c
+index 865f32be386e..d0feff61e6aa 100644
+--- a/fs/sync.c
++++ b/fs/sync.c
+@@ -94,7 +94,7 @@ long do_fsync(struct file *file, int datasync)
+ 	 * livelocks in fsync_buffers_list().
+ 	 */
+ 	mutex_lock(&mapping->host->i_mutex);
+-	err = file->f_op->fsync(file, file->f_dentry, datasync);
++	err = file->f_op->fsync(file, file->f_path.dentry, datasync);
+ 	if (!ret)
+ 		ret = err;
+ 	mutex_unlock(&mapping->host->i_mutex);
+@@ -223,7 +223,7 @@ asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes,
+ 	if (!file)
+ 		goto out;
+ 
+-	i_mode = file->f_dentry->d_inode->i_mode;
++	i_mode = file->f_path.dentry->d_inode->i_mode;
+ 	ret = -ESPIPE;
+ 	if (!S_ISREG(i_mode) && !S_ISBLK(i_mode) && !S_ISDIR(i_mode) &&
+ 			!S_ISLNK(i_mode))
+diff --git a/fs/xattr.c b/fs/xattr.c
+index 0901bdc2ce24..38646132ab0e 100644
+--- a/fs/xattr.c
++++ b/fs/xattr.c
+@@ -268,7 +268,7 @@ sys_fsetxattr(int fd, char __user *name, void __user *value,
+ 	f = fget(fd);
+ 	if (!f)
+ 		return error;
+-	dentry = f->f_dentry;
++	dentry = f->f_path.dentry;
+ 	audit_inode(NULL, dentry->d_inode);
+ 	error = setxattr(dentry, name, value, size, flags);
+ 	fput(f);
+@@ -351,7 +351,7 @@ sys_fgetxattr(int fd, char __user *name, void __user *value, size_t size)
+ 	f = fget(fd);
+ 	if (!f)
+ 		return error;
+-	error = getxattr(f->f_dentry, name, value, size);
++	error = getxattr(f->f_path.dentry, name, value, size);
+ 	fput(f);
+ 	return error;
+ }
+@@ -423,7 +423,7 @@ sys_flistxattr(int fd, char __user *list, size_t size)
+ 	f = fget(fd);
+ 	if (!f)
+ 		return error;
+-	error = listxattr(f->f_dentry, list, size);
++	error = listxattr(f->f_path.dentry, list, size);
+ 	fput(f);
+ 	return error;
+ }
+@@ -484,7 +484,7 @@ sys_fremovexattr(int fd, char __user *name)
+ 	f = fget(fd);
+ 	if (!f)
+ 		return error;
+-	dentry = f->f_dentry;
++	dentry = f->f_path.dentry;
+ 	audit_inode(NULL, dentry->d_inode);
+ 	error = removexattr(dentry, name);
+ 	fput(f);
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 45f2cabb8c75..adce6e1d70c2 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -269,6 +269,7 @@ extern int dir_notify_enable;
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -711,8 +712,9 @@ struct file {
+ 		struct list_head	fu_list;
+ 		struct rcu_head 	fu_rcuhead;
+ 	} f_u;
+-	struct dentry		*f_dentry;
+-	struct vfsmount         *f_vfsmnt;
++	struct path		f_path;
++#define f_dentry	f_path.dentry
++#define f_vfsmnt	f_path.mnt
+ 	const struct file_operations	*f_op;
+ 	atomic_t		f_count;
+ 	unsigned int 		f_flags;
+@@ -1224,7 +1226,7 @@ extern void touch_atime(struct vfsmount *mnt, struct dentry *dentry);
+ static inline void file_accessed(struct file *file)
+ {
+ 	if (!(file->f_flags & O_NOATIME))
+-		touch_atime(file->f_vfsmnt, file->f_dentry);
++		touch_atime(file->f_path.mnt, file->f_path.dentry);
+ }
+ 
+ int sync_inode(struct inode *inode, struct writeback_control *wbc);
+@@ -1615,7 +1617,7 @@ static inline void put_write_access(struct inode * inode)
+ static inline void allow_write_access(struct file *file)
+ {
+ 	if (file)
+-		atomic_inc(&file->f_dentry->d_inode->i_writecount);
++		atomic_inc(&file->f_path.dentry->d_inode->i_writecount);
+ }
+ extern int do_pipe(int *);
+ extern struct file *create_read_pipe(struct file *f);
+diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
+index d4f219ffaa5d..dfc4e4f68da4 100644
+--- a/include/linux/fsnotify.h
++++ b/include/linux/fsnotify.h
+@@ -164,7 +164,7 @@ static inline void fsnotify_open(struct dentry *dentry)
+  */
+ static inline void fsnotify_close(struct file *file)
+ {
+-	struct dentry *dentry = file->f_dentry;
++	struct dentry *dentry = file->f_path.dentry;
+ 	struct inode *inode = dentry->d_inode;
+ 	const char *name = dentry->d_name.name;
+ 	mode_t mode = file->f_mode;

commit b65d34fd465f19fbe2f32f2205a9a06ca7c2bdeb
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:34 2006 -0800
+
+    [PATCH] struct path: make eCryptfs a user of struct path
+    
+    Convert eCryptfs dentry-vfsmount pairs in dentry private data to struct
+    path.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Cc: Michael Halcrow 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
+index 424137fb5898..afb64bdbe6ad 100644
+--- a/fs/ecryptfs/ecryptfs_kernel.h
++++ b/fs/ecryptfs/ecryptfs_kernel.h
+@@ -29,6 +29,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ 
+ /* Version verification for shared data structures w/ userspace */
+@@ -228,8 +229,7 @@ struct ecryptfs_inode_info {
+ /* dentry private data. Each dentry must keep track of a lower
+  * vfsmount too. */
+ struct ecryptfs_dentry_info {
+-	struct dentry *wdi_dentry;
+-	struct vfsmount *lower_mnt;
++	struct path lower_path;
+ 	struct ecryptfs_crypt_stat *crypt_stat;
+ };
+ 
+@@ -356,26 +356,26 @@ ecryptfs_set_dentry_private(struct dentry *dentry,
+ static inline struct dentry *
+ ecryptfs_dentry_to_lower(struct dentry *dentry)
+ {
+-	return ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->wdi_dentry;
++	return ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path.dentry;
+ }
+ 
+ static inline void
+ ecryptfs_set_dentry_lower(struct dentry *dentry, struct dentry *lower_dentry)
+ {
+-	((struct ecryptfs_dentry_info *)dentry->d_fsdata)->wdi_dentry =
++	((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path.dentry =
+ 		lower_dentry;
+ }
+ 
+ static inline struct vfsmount *
+ ecryptfs_dentry_to_lower_mnt(struct dentry *dentry)
+ {
+-	return ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_mnt;
++	return ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path.mnt;
+ }
+ 
+ static inline void
+ ecryptfs_set_dentry_lower_mnt(struct dentry *dentry, struct vfsmount *lower_mnt)
+ {
+-	((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_mnt =
++	((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path.mnt =
+ 		lower_mnt;
+ }
+ 

commit 346f20ff6020ffa11d40b789069079c56a444ae6
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:34 2006 -0800
+
+    [PATCH] struct path: move struct path from fs/namei.c into include/linux
+    
+    Moved struct path from fs/namei.c to include/linux/namei.h.  This allows many
+    places in the VFS, as well as any stackable filesystem to easily keep track of
+    dentry-vfsmount pairs.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Cc: Al Viro 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/namei.c b/fs/namei.c
+index db1bca26d88c..8c2db88bb20d 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -572,11 +572,6 @@ static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *l
+ 	return PTR_ERR(link);
+ }
+ 
+-struct path {
+-	struct vfsmount *mnt;
+-	struct dentry *dentry;
+-};
+-
+ static inline void dput_path(struct path *path, struct nameidata *nd)
+ {
+ 	dput(path->dentry);
+diff --git a/include/linux/namei.h b/include/linux/namei.h
+index f5f19606effb..d39a5a67e979 100644
+--- a/include/linux/namei.h
++++ b/include/linux/namei.h
+@@ -29,6 +29,11 @@ struct nameidata {
+ 	} intent;
+ };
+ 
++struct path {
++	struct vfsmount *mnt;
++	struct dentry *dentry;
++};
++
+ /*
+  * Type of the last component on LOOKUP_PARENT
+  */

commit c922d5f7f5457da9e9b5a26dd53e2dcef6ca2f7d
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:33 2006 -0800
+
+    [PATCH] struct path: rename DM's struct path
+    
+    Rename DM's struct path to struct dm_path to prevent name collision between it
+    and struct path from fs/namei.c.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Acked-by: Alasdair G Kergon 
+    Cc: 
+    Cc: Al Viro 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/dm-emc.c b/drivers/md/dm-emc.c
+index 2b2d45d7baaa..265c467854da 100644
+--- a/drivers/md/dm-emc.c
++++ b/drivers/md/dm-emc.c
+@@ -40,7 +40,7 @@ static inline void free_bio(struct bio *bio)
+ 
+ static int emc_endio(struct bio *bio, unsigned int bytes_done, int error)
+ {
+-	struct path *path = bio->bi_private;
++	struct dm_path *path = bio->bi_private;
+ 
+ 	if (bio->bi_size)
+ 		return 1;
+@@ -61,7 +61,7 @@ static int emc_endio(struct bio *bio, unsigned int bytes_done, int error)
+ 	return 0;
+ }
+ 
+-static struct bio *get_failover_bio(struct path *path, unsigned data_size)
++static struct bio *get_failover_bio(struct dm_path *path, unsigned data_size)
+ {
+ 	struct bio *bio;
+ 	struct page *page;
+@@ -96,7 +96,7 @@ static struct bio *get_failover_bio(struct path *path, unsigned data_size)
+ }
+ 
+ static struct request *get_failover_req(struct emc_handler *h,
+-					struct bio *bio, struct path *path)
++					struct bio *bio, struct dm_path *path)
+ {
+ 	struct request *rq;
+ 	struct block_device *bdev = bio->bi_bdev;
+@@ -133,7 +133,7 @@ static struct request *get_failover_req(struct emc_handler *h,
+ }
+ 
+ static struct request *emc_trespass_get(struct emc_handler *h,
+-					struct path *path)
++					struct dm_path *path)
+ {
+ 	struct bio *bio;
+ 	struct request *rq;
+@@ -191,7 +191,7 @@ static struct request *emc_trespass_get(struct emc_handler *h,
+ }
+ 
+ static void emc_pg_init(struct hw_handler *hwh, unsigned bypassed,
+-			struct path *path)
++			struct dm_path *path)
+ {
+ 	struct request *rq;
+ 	struct request_queue *q = bdev_get_queue(path->dev->bdev);
+diff --git a/drivers/md/dm-hw-handler.h b/drivers/md/dm-hw-handler.h
+index 15f5629e231a..32eff28e4adc 100644
+--- a/drivers/md/dm-hw-handler.h
++++ b/drivers/md/dm-hw-handler.h
+@@ -32,7 +32,7 @@ struct hw_handler_type {
+ 	void (*destroy) (struct hw_handler *hwh);
+ 
+ 	void (*pg_init) (struct hw_handler *hwh, unsigned bypassed,
+-			 struct path *path);
++			 struct dm_path *path);
+ 	unsigned (*error) (struct hw_handler *hwh, struct bio *bio);
+ 	int (*status) (struct hw_handler *hwh, status_type_t type,
+ 		       char *result, unsigned int maxlen);
+diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
+index cf8bf052138e..e9dfe2c98059 100644
+--- a/drivers/md/dm-mpath.c
++++ b/drivers/md/dm-mpath.c
+@@ -31,7 +31,7 @@ struct pgpath {
+ 	struct priority_group *pg;	/* Owning PG */
+ 	unsigned fail_count;		/* Cumulative failure count */
+ 
+-	struct path path;
++	struct dm_path path;
+ };
+ 
+ #define path_to_pgpath(__pgp) container_of((__pgp), struct pgpath, path)
+@@ -229,7 +229,7 @@ static void __switch_pg(struct multipath *m, struct pgpath *pgpath)
+ 
+ static int __choose_path_in_pg(struct multipath *m, struct priority_group *pg)
+ {
+-	struct path *path;
++	struct dm_path *path;
+ 
+ 	path = pg->ps.type->select_path(&pg->ps, &m->repeat_count);
+ 	if (!path)
+@@ -957,7 +957,7 @@ static int bypass_pg_num(struct multipath *m, const char *pgstr, int bypassed)
+ /*
+  * pg_init must call this when it has completed its initialisation
+  */
+-void dm_pg_init_complete(struct path *path, unsigned err_flags)
++void dm_pg_init_complete(struct dm_path *path, unsigned err_flags)
+ {
+ 	struct pgpath *pgpath = path_to_pgpath(path);
+ 	struct priority_group *pg = pgpath->pg;
+diff --git a/drivers/md/dm-mpath.h b/drivers/md/dm-mpath.h
+index 8a4bf2b6d52e..b9cdcbb3ed59 100644
+--- a/drivers/md/dm-mpath.h
++++ b/drivers/md/dm-mpath.h
+@@ -11,7 +11,7 @@
+ 
+ struct dm_dev;
+ 
+-struct path {
++struct dm_path {
+ 	struct dm_dev *dev;	/* Read-only */
+ 	unsigned is_active;	/* Read-only */
+ 
+@@ -20,6 +20,6 @@ struct path {
+ };
+ 
+ /* Callback for hwh_pg_init_fn to use when complete */
+-void dm_pg_init_complete(struct path *path, unsigned err_flags);
++void dm_pg_init_complete(struct dm_path *path, unsigned err_flags);
+ 
+ #endif
+diff --git a/drivers/md/dm-path-selector.h b/drivers/md/dm-path-selector.h
+index 732d06a84f85..27357b85d73d 100644
+--- a/drivers/md/dm-path-selector.h
++++ b/drivers/md/dm-path-selector.h
+@@ -44,7 +44,7 @@ struct path_selector_type {
+ 	 * Add an opaque path object, along with some selector specific
+ 	 * path args (eg, path priority).
+ 	 */
+-	int (*add_path) (struct path_selector *ps, struct path *path,
++	int (*add_path) (struct path_selector *ps, struct dm_path *path,
+ 			 int argc, char **argv, char **error);
+ 
+ 	/*
+@@ -55,27 +55,27 @@ struct path_selector_type {
+ 	 * calling the function again.  0 means don't call it again unless
+ 	 * the path fails.
+ 	 */
+-	struct path *(*select_path) (struct path_selector *ps,
++	struct dm_path *(*select_path) (struct path_selector *ps,
+ 				     unsigned *repeat_count);
+ 
+ 	/*
+ 	 * Notify the selector that a path has failed.
+ 	 */
+-	void (*fail_path) (struct path_selector *ps, struct path *p);
++	void (*fail_path) (struct path_selector *ps, struct dm_path *p);
+ 
+ 	/*
+ 	 * Ask selector to reinstate a path.
+ 	 */
+-	int (*reinstate_path) (struct path_selector *ps, struct path *p);
++	int (*reinstate_path) (struct path_selector *ps, struct dm_path *p);
+ 
+ 	/*
+ 	 * Table content based on parameters added in ps_add_path_fn
+ 	 * or path selector status
+ 	 */
+-	int (*status) (struct path_selector *ps, struct path *path,
++	int (*status) (struct path_selector *ps, struct dm_path *path,
+ 		       status_type_t type, char *result, unsigned int maxlen);
+ 
+-	int (*end_io) (struct path_selector *ps, struct path *path);
++	int (*end_io) (struct path_selector *ps, struct dm_path *path);
+ };
+ 
+ /* Register a path selector */
+diff --git a/drivers/md/dm-round-robin.c b/drivers/md/dm-round-robin.c
+index 6f9fcd4db9b5..a348a97b65af 100644
+--- a/drivers/md/dm-round-robin.c
++++ b/drivers/md/dm-round-robin.c
+@@ -21,7 +21,7 @@
+  *---------------------------------------------------------------*/
+ struct path_info {
+ 	struct list_head list;
+-	struct path *path;
++	struct dm_path *path;
+ 	unsigned repeat_count;
+ };
+ 
+@@ -80,7 +80,7 @@ static void rr_destroy(struct path_selector *ps)
+ 	ps->context = NULL;
+ }
+ 
+-static int rr_status(struct path_selector *ps, struct path *path,
++static int rr_status(struct path_selector *ps, struct dm_path *path,
+ 		     status_type_t type, char *result, unsigned int maxlen)
+ {
+ 	struct path_info *pi;
+@@ -106,7 +106,7 @@ static int rr_status(struct path_selector *ps, struct path *path,
+  * Called during initialisation to register each path with an
+  * optional repeat_count.
+  */
+-static int rr_add_path(struct path_selector *ps, struct path *path,
++static int rr_add_path(struct path_selector *ps, struct dm_path *path,
+ 		       int argc, char **argv, char **error)
+ {
+ 	struct selector *s = (struct selector *) ps->context;
+@@ -141,7 +141,7 @@ static int rr_add_path(struct path_selector *ps, struct path *path,
+ 	return 0;
+ }
+ 
+-static void rr_fail_path(struct path_selector *ps, struct path *p)
++static void rr_fail_path(struct path_selector *ps, struct dm_path *p)
+ {
+ 	struct selector *s = (struct selector *) ps->context;
+ 	struct path_info *pi = p->pscontext;
+@@ -149,7 +149,7 @@ static void rr_fail_path(struct path_selector *ps, struct path *p)
+ 	list_move(&pi->list, &s->invalid_paths);
+ }
+ 
+-static int rr_reinstate_path(struct path_selector *ps, struct path *p)
++static int rr_reinstate_path(struct path_selector *ps, struct dm_path *p)
+ {
+ 	struct selector *s = (struct selector *) ps->context;
+ 	struct path_info *pi = p->pscontext;
+@@ -159,7 +159,7 @@ static int rr_reinstate_path(struct path_selector *ps, struct path *p)
+ 	return 0;
+ }
+ 
+-static struct path *rr_select_path(struct path_selector *ps,
++static struct dm_path *rr_select_path(struct path_selector *ps,
+ 				   unsigned *repeat_count)
+ {
+ 	struct selector *s = (struct selector *) ps->context;

commit fec6d055da71fb02a76f9c2c12427fa79974018b
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:32 2006 -0800
+
+    [PATCH] struct path: rename Reiserfs's struct path
+    
+    Rename Reiserfs's struct path to struct treepath to prevent name collision
+    between it and struct path from fs/namei.c.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Cc: 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
+index e3d466a228d4..b286ccb08587 100644
+--- a/fs/reiserfs/bitmap.c
++++ b/fs/reiserfs/bitmap.c
+@@ -708,7 +708,7 @@ static void oid_groups(reiserfs_blocknr_hint_t * hint)
+  */
+ static int get_left_neighbor(reiserfs_blocknr_hint_t * hint)
+ {
+-	struct path *path;
++	struct treepath *path;
+ 	struct buffer_head *bh;
+ 	struct item_head *ih;
+ 	int pos_in_item;
+diff --git a/fs/reiserfs/fix_node.c b/fs/reiserfs/fix_node.c
+index 6d0e554daa9d..0ee35c6c9b72 100644
+--- a/fs/reiserfs/fix_node.c
++++ b/fs/reiserfs/fix_node.c
+@@ -957,7 +957,7 @@ static int get_far_parent(struct tree_balance *p_s_tb,
+ {
+ 	struct buffer_head *p_s_parent;
+ 	INITIALIZE_PATH(s_path_to_neighbor_father);
+-	struct path *p_s_path = p_s_tb->tb_path;
++	struct treepath *p_s_path = p_s_tb->tb_path;
+ 	struct cpu_key s_lr_father_key;
+ 	int n_counter,
+ 	    n_position = INT_MAX,
+@@ -1074,7 +1074,7 @@ static int get_far_parent(struct tree_balance *p_s_tb,
+  */
+ static int get_parents(struct tree_balance *p_s_tb, int n_h)
+ {
+-	struct path *p_s_path = p_s_tb->tb_path;
++	struct treepath *p_s_path = p_s_tb->tb_path;
+ 	int n_position,
+ 	    n_ret_value,
+ 	    n_path_offset = PATH_H_PATH_OFFSET(p_s_tb->tb_path, n_h);
+@@ -1885,7 +1885,7 @@ static int check_balance(int mode,
+ static int get_direct_parent(struct tree_balance *p_s_tb, int n_h)
+ {
+ 	struct buffer_head *p_s_bh;
+-	struct path *p_s_path = p_s_tb->tb_path;
++	struct treepath *p_s_path = p_s_tb->tb_path;
+ 	int n_position,
+ 	    n_path_offset = PATH_H_PATH_OFFSET(p_s_tb->tb_path, n_h);
+ 
+diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
+index 254239e6f9e3..f3d1c4a77979 100644
+--- a/fs/reiserfs/inode.c
++++ b/fs/reiserfs/inode.c
+@@ -207,7 +207,7 @@ static int file_capable(struct inode *inode, long block)
+ }
+ 
+ /*static*/ int restart_transaction(struct reiserfs_transaction_handle *th,
+-				   struct inode *inode, struct path *path)
++				   struct inode *inode, struct treepath *path)
+ {
+ 	struct super_block *s = th->t_super;
+ 	int len = th->t_blocks_allocated;
+@@ -570,7 +570,7 @@ static inline int _allocate_block(struct reiserfs_transaction_handle *th,
+ 				  long block,
+ 				  struct inode *inode,
+ 				  b_blocknr_t * allocated_block_nr,
+-				  struct path *path, int flags)
++				  struct treepath *path, int flags)
+ {
+ 	BUG_ON(!th->t_trans_id);
+ 
+@@ -1107,7 +1107,7 @@ static inline ulong to_fake_used_blocks(struct inode *inode, int sd_size)
+ //
+ 
+ // called by read_locked_inode
+-static void init_inode(struct inode *inode, struct path *path)
++static void init_inode(struct inode *inode, struct treepath *path)
+ {
+ 	struct buffer_head *bh;
+ 	struct item_head *ih;
+@@ -1284,7 +1284,7 @@ static void inode2sd_v1(void *sd, struct inode *inode, loff_t size)
+ /* NOTE, you must prepare the buffer head before sending it here,
+ ** and then log it after the call
+ */
+-static void update_stat_data(struct path *path, struct inode *inode,
++static void update_stat_data(struct treepath *path, struct inode *inode,
+ 			     loff_t size)
+ {
+ 	struct buffer_head *bh;
+@@ -1653,7 +1653,7 @@ int reiserfs_write_inode(struct inode *inode, int do_sync)
+    containing "." and ".." entries */
+ static int reiserfs_new_directory(struct reiserfs_transaction_handle *th,
+ 				  struct inode *inode,
+-				  struct item_head *ih, struct path *path,
++				  struct item_head *ih, struct treepath *path,
+ 				  struct inode *dir)
+ {
+ 	struct super_block *sb = th->t_super;
+@@ -1712,7 +1712,7 @@ static int reiserfs_new_directory(struct reiserfs_transaction_handle *th,
+    containing the body of symlink */
+ static int reiserfs_new_symlink(struct reiserfs_transaction_handle *th, struct inode *inode,	/* Inode of symlink */
+ 				struct item_head *ih,
+-				struct path *path, const char *symname,
++				struct treepath *path, const char *symname,
+ 				int item_len)
+ {
+ 	struct super_block *sb = th->t_super;
+diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
+index abde1edc2235..23f5cd5bbf56 100644
+--- a/fs/reiserfs/namei.c
++++ b/fs/reiserfs/namei.c
+@@ -54,7 +54,7 @@ static int bin_search_in_dir_item(struct reiserfs_dir_entry *de, loff_t off)
+ 
+ // comment?  maybe something like set de to point to what the path points to?
+ static inline void set_de_item_location(struct reiserfs_dir_entry *de,
+-					struct path *path)
++					struct treepath *path)
+ {
+ 	de->de_bh = get_last_bh(path);
+ 	de->de_ih = get_ih(path);
+@@ -113,7 +113,7 @@ entry position in the item
+ 
+ /* The function is NOT SCHEDULE-SAFE! */
+ int search_by_entry_key(struct super_block *sb, const struct cpu_key *key,
+-			struct path *path, struct reiserfs_dir_entry *de)
++			struct treepath *path, struct reiserfs_dir_entry *de)
+ {
+ 	int retval;
+ 
+@@ -282,7 +282,7 @@ static int linear_search_in_dir_item(struct cpu_key *key,
+ // may return NAME_FOUND, NAME_FOUND_INVISIBLE, NAME_NOT_FOUND
+ // FIXME: should add something like IOERROR
+ static int reiserfs_find_entry(struct inode *dir, const char *name, int namelen,
+-			       struct path *path_to_entry,
++			       struct treepath *path_to_entry,
+ 			       struct reiserfs_dir_entry *de)
+ {
+ 	struct cpu_key key_to_search;
+diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
+index 5240abe1a709..47e7027ea39f 100644
+--- a/fs/reiserfs/stree.c
++++ b/fs/reiserfs/stree.c
+@@ -244,7 +244,7 @@ static const struct reiserfs_key MAX_KEY = {
+    of the path, and going upwards.  We must check the path's validity at each step.  If the key is not in
+    the path, there is no delimiting key in the tree (buffer is first or last buffer in tree), and in this
+    case we return a special key, either MIN_KEY or MAX_KEY. */
+-static inline const struct reiserfs_key *get_lkey(const struct path
++static inline const struct reiserfs_key *get_lkey(const struct treepath
+ 						  *p_s_chk_path,
+ 						  const struct super_block
+ 						  *p_s_sb)
+@@ -290,7 +290,7 @@ static inline const struct reiserfs_key *get_lkey(const struct path
+ }
+ 
+ /* Get delimiting key of the buffer at the path and its right neighbor. */
+-inline const struct reiserfs_key *get_rkey(const struct path *p_s_chk_path,
++inline const struct reiserfs_key *get_rkey(const struct treepath *p_s_chk_path,
+ 					   const struct super_block *p_s_sb)
+ {
+ 	int n_position, n_path_offset = p_s_chk_path->path_length;
+@@ -337,7 +337,7 @@ inline const struct reiserfs_key *get_rkey(const struct path *p_s_chk_path,
+    the path.  These delimiting keys are stored at least one level above that buffer in the tree. If the
+    buffer is the first or last node in the tree order then one of the delimiting keys may be absent, and in
+    this case get_lkey and get_rkey return a special key which is MIN_KEY or MAX_KEY. */
+-static inline int key_in_buffer(struct path *p_s_chk_path,	/* Path which should be checked.  */
++static inline int key_in_buffer(struct treepath *p_s_chk_path,	/* Path which should be checked.  */
+ 				const struct cpu_key *p_s_key,	/* Key which should be checked.   */
+ 				struct super_block *p_s_sb	/* Super block pointer.           */
+     )
+@@ -374,7 +374,7 @@ inline void decrement_bcount(struct buffer_head *p_s_bh)
+ }
+ 
+ /* Decrement b_count field of the all buffers in the path. */
+-void decrement_counters_in_path(struct path *p_s_search_path)
++void decrement_counters_in_path(struct treepath *p_s_search_path)
+ {
+ 	int n_path_offset = p_s_search_path->path_length;
+ 
+@@ -391,7 +391,7 @@ void decrement_counters_in_path(struct path *p_s_search_path)
+ 	p_s_search_path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
+ }
+ 
+-int reiserfs_check_path(struct path *p)
++int reiserfs_check_path(struct treepath *p)
+ {
+ 	RFALSE(p->path_length != ILLEGAL_PATH_ELEMENT_OFFSET,
+ 	       "path not properly relsed");
+@@ -403,7 +403,7 @@ int reiserfs_check_path(struct path *p)
+ **
+ ** only called from fix_nodes()
+ */
+-void pathrelse_and_restore(struct super_block *s, struct path *p_s_search_path)
++void pathrelse_and_restore(struct super_block *s, struct treepath *p_s_search_path)
+ {
+ 	int n_path_offset = p_s_search_path->path_length;
+ 
+@@ -421,7 +421,7 @@ void pathrelse_and_restore(struct super_block *s, struct path *p_s_search_path)
+ }
+ 
+ /* Release all buffers in the path. */
+-void pathrelse(struct path *p_s_search_path)
++void pathrelse(struct treepath *p_s_search_path)
+ {
+ 	int n_path_offset = p_s_search_path->path_length;
+ 
+@@ -602,7 +602,7 @@ static void search_by_key_reada(struct super_block *s,
+    correctness of the bottom of the path */
+ /* The function is NOT SCHEDULE-SAFE! */
+ int search_by_key(struct super_block *p_s_sb, const struct cpu_key *p_s_key,	/* Key to search. */
+-		  struct path *p_s_search_path,	/* This structure was
++		  struct treepath *p_s_search_path,/* This structure was
+ 						   allocated and initialized
+ 						   by the calling
+ 						   function. It is filled up
+@@ -813,7 +813,7 @@ int search_by_key(struct super_block *p_s_sb, const struct cpu_key *p_s_key,	/*
+ /* The function is NOT SCHEDULE-SAFE! */
+ int search_for_position_by_key(struct super_block *p_s_sb,	/* Pointer to the super block.          */
+ 			       const struct cpu_key *p_cpu_key,	/* Key to search (cpu variable)         */
+-			       struct path *p_s_search_path	/* Filled up by this function.          */
++			       struct treepath *p_s_search_path	/* Filled up by this function.          */
+     )
+ {
+ 	struct item_head *p_le_ih;	/* pointer to on-disk structure */
+@@ -884,7 +884,7 @@ int search_for_position_by_key(struct super_block *p_s_sb,	/* Pointer to the sup
+ }
+ 
+ /* Compare given item and item pointed to by the path. */
+-int comp_items(const struct item_head *stored_ih, const struct path *p_s_path)
++int comp_items(const struct item_head *stored_ih, const struct treepath *p_s_path)
+ {
+ 	struct buffer_head *p_s_bh;
+ 	struct item_head *ih;
+@@ -911,7 +911,7 @@ int comp_items(const struct item_head *stored_ih, const struct path *p_s_path)
+ #define block_in_use(bh) (buffer_locked(bh) || (held_by_others(bh)))
+ 
+ // prepare for delete or cut of direct item
+-static inline int prepare_for_direct_item(struct path *path,
++static inline int prepare_for_direct_item(struct treepath *path,
+ 					  struct item_head *le_ih,
+ 					  struct inode *inode,
+ 					  loff_t new_file_length, int *cut_size)
+@@ -952,7 +952,7 @@ static inline int prepare_for_direct_item(struct path *path,
+ 	return M_CUT;		/* Cut from this item. */
+ }
+ 
+-static inline int prepare_for_direntry_item(struct path *path,
++static inline int prepare_for_direntry_item(struct treepath *path,
+ 					    struct item_head *le_ih,
+ 					    struct inode *inode,
+ 					    loff_t new_file_length,
+@@ -987,7 +987,7 @@ static inline int prepare_for_direntry_item(struct path *path,
+     In case of file truncate calculate whether this item must be deleted/truncated or last
+     unformatted node of this item will be converted to a direct item.
+     This function returns a determination of what balance mode the calling function should employ. */
+-static char prepare_for_delete_or_cut(struct reiserfs_transaction_handle *th, struct inode *inode, struct path *p_s_path, const struct cpu_key *p_s_item_key, int *p_n_removed,	/* Number of unformatted nodes which were removed
++static char prepare_for_delete_or_cut(struct reiserfs_transaction_handle *th, struct inode *inode, struct treepath *p_s_path, const struct cpu_key *p_s_item_key, int *p_n_removed,	/* Number of unformatted nodes which were removed
+ 																						   from end of the file. */
+ 				      int *p_n_cut_size, unsigned long long n_new_file_length	/* MAX_KEY_OFFSET in case of delete. */
+     )
+@@ -1125,7 +1125,7 @@ static int calc_deleted_bytes_number(struct tree_balance *p_s_tb, char c_mode)
+ static void init_tb_struct(struct reiserfs_transaction_handle *th,
+ 			   struct tree_balance *p_s_tb,
+ 			   struct super_block *p_s_sb,
+-			   struct path *p_s_path, int n_size)
++			   struct treepath *p_s_path, int n_size)
+ {
+ 
+ 	BUG_ON(!th->t_trans_id);
+@@ -1176,7 +1176,7 @@ char head2type(struct item_head *ih)
+ #endif
+ 
+ /* Delete object item. */
+-int reiserfs_delete_item(struct reiserfs_transaction_handle *th, struct path *p_s_path,	/* Path to the deleted item. */
++int reiserfs_delete_item(struct reiserfs_transaction_handle *th, struct treepath *p_s_path,	/* Path to the deleted item. */
+ 			 const struct cpu_key *p_s_item_key,	/* Key to search for the deleted item.  */
+ 			 struct inode *p_s_inode,	/* inode is here just to update i_blocks and quotas */
+ 			 struct buffer_head *p_s_un_bh)
+@@ -1468,7 +1468,7 @@ static void unmap_buffers(struct page *page, loff_t pos)
+ static int maybe_indirect_to_direct(struct reiserfs_transaction_handle *th,
+ 				    struct inode *p_s_inode,
+ 				    struct page *page,
+-				    struct path *p_s_path,
++				    struct treepath *p_s_path,
+ 				    const struct cpu_key *p_s_item_key,
+ 				    loff_t n_new_file_size, char *p_c_mode)
+ {
+@@ -1503,7 +1503,7 @@ static int maybe_indirect_to_direct(struct reiserfs_transaction_handle *th,
+    pointer being converted. Therefore we have to delete inserted
+    direct item(s) */
+ static void indirect_to_direct_roll_back(struct reiserfs_transaction_handle *th,
+-					 struct inode *inode, struct path *path)
++					 struct inode *inode, struct treepath *path)
+ {
+ 	struct cpu_key tail_key;
+ 	int tail_len;
+@@ -1545,7 +1545,7 @@ static void indirect_to_direct_roll_back(struct reiserfs_transaction_handle *th,
+ 
+ /* (Truncate or cut entry) or delete object item. Returns < 0 on failure */
+ int reiserfs_cut_from_item(struct reiserfs_transaction_handle *th,
+-			   struct path *p_s_path,
++			   struct treepath *p_s_path,
+ 			   struct cpu_key *p_s_item_key,
+ 			   struct inode *p_s_inode,
+ 			   struct page *page, loff_t n_new_file_size)
+@@ -1920,7 +1920,7 @@ int reiserfs_do_truncate(struct reiserfs_transaction_handle *th, struct inode *p
+ 
+ #ifdef CONFIG_REISERFS_CHECK
+ // this makes sure, that we __append__, not overwrite or add holes
+-static void check_research_for_paste(struct path *path,
++static void check_research_for_paste(struct treepath *path,
+ 				     const struct cpu_key *p_s_key)
+ {
+ 	struct item_head *found_ih = get_ih(path);
+@@ -1954,7 +1954,7 @@ static void check_research_for_paste(struct path *path,
+ #endif				/* config reiserfs check */
+ 
+ /* Paste bytes to the existing item. Returns bytes number pasted into the item. */
+-int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct path *p_s_search_path,	/* Path to the pasted item.          */
++int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct treepath *p_s_search_path,	/* Path to the pasted item.          */
+ 			     const struct cpu_key *p_s_key,	/* Key to search for the needed item. */
+ 			     struct inode *inode,	/* Inode item belongs to */
+ 			     const char *p_c_body,	/* Pointer to the bytes to paste.    */
+@@ -2036,7 +2036,7 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct path
+ }
+ 
+ /* Insert new item into the buffer at the path. */
+-int reiserfs_insert_item(struct reiserfs_transaction_handle *th, struct path *p_s_path,	/* Path to the inserteded item.         */
++int reiserfs_insert_item(struct reiserfs_transaction_handle *th, struct treepath *p_s_path,	/* Path to the inserteded item.         */
+ 			 const struct cpu_key *key, struct item_head *p_s_ih,	/* Pointer to the item header to insert. */
+ 			 struct inode *inode, const char *p_c_body)
+ {				/* Pointer to the bytes to insert.      */
+diff --git a/fs/reiserfs/tail_conversion.c b/fs/reiserfs/tail_conversion.c
+index 36f108fc1cf5..f8121a1147e8 100644
+--- a/fs/reiserfs/tail_conversion.c
++++ b/fs/reiserfs/tail_conversion.c
+@@ -15,7 +15,7 @@
+ /* path points to first direct item of the file regarless of how many of
+    them are there */
+ int direct2indirect(struct reiserfs_transaction_handle *th, struct inode *inode,
+-		    struct path *path, struct buffer_head *unbh,
++		    struct treepath *path, struct buffer_head *unbh,
+ 		    loff_t tail_offset)
+ {
+ 	struct super_block *sb = inode->i_sb;
+@@ -171,7 +171,7 @@ void reiserfs_unmap_buffer(struct buffer_head *bh)
+    what we expect from it (number of cut bytes). But when tail remains
+    in the unformatted node, we set mode to SKIP_BALANCING and unlock
+    inode */
+-int indirect2direct(struct reiserfs_transaction_handle *th, struct inode *p_s_inode, struct page *page, struct path *p_s_path,	/* path to the indirect item. */
++int indirect2direct(struct reiserfs_transaction_handle *th, struct inode *p_s_inode, struct page *page, struct treepath *p_s_path,	/* path to the indirect item. */
+ 		    const struct cpu_key *p_s_item_key,	/* Key to look for unformatted node pointer to be cut. */
+ 		    loff_t n_new_file_size,	/* New file size. */
+ 		    char *p_c_mode)
+diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
+index d0e4dce33ad5..c3fc6caaad3f 100644
+--- a/include/linux/reiserfs_fs.h
++++ b/include/linux/reiserfs_fs.h
+@@ -1159,7 +1159,7 @@ znodes are the way! */
+ #define PATH_READA	0x1	/* do read ahead */
+ #define PATH_READA_BACK 0x2	/* read backwards */
+ 
+-struct path {
++struct treepath {
+ 	int path_length;	/* Length of the array above.   */
+ 	int reada;
+ 	struct path_element path_elements[EXTENDED_MAX_HEIGHT];	/* Array of the path elements.  */
+@@ -1169,7 +1169,7 @@ struct path {
+ #define pos_in_item(path) ((path)->pos_in_item)
+ 
+ #define INITIALIZE_PATH(var) \
+-struct path var = {.path_length = ILLEGAL_PATH_ELEMENT_OFFSET, .reada = 0,}
++struct treepath var = {.path_length = ILLEGAL_PATH_ELEMENT_OFFSET, .reada = 0,}
+ 
+ /* Get path element by path and path position. */
+ #define PATH_OFFSET_PELEMENT(p_s_path,n_offset)  ((p_s_path)->path_elements +(n_offset))
+@@ -1327,7 +1327,7 @@ struct tree_balance {
+ 	int need_balance_dirty;
+ 	struct super_block *tb_sb;
+ 	struct reiserfs_transaction_handle *transaction_handle;
+-	struct path *tb_path;
++	struct treepath *tb_path;
+ 	struct buffer_head *L[MAX_HEIGHT];	/* array of left neighbors of nodes in the path */
+ 	struct buffer_head *R[MAX_HEIGHT];	/* array of right neighbors of nodes in the path */
+ 	struct buffer_head *FL[MAX_HEIGHT];	/* array of fathers of the left  neighbors      */
+@@ -1793,41 +1793,41 @@ static inline void copy_key(struct reiserfs_key *to,
+ 	memcpy(to, from, KEY_SIZE);
+ }
+ 
+-int comp_items(const struct item_head *stored_ih, const struct path *p_s_path);
+-const struct reiserfs_key *get_rkey(const struct path *p_s_chk_path,
++int comp_items(const struct item_head *stored_ih, const struct treepath *p_s_path);
++const struct reiserfs_key *get_rkey(const struct treepath *p_s_chk_path,
+ 				    const struct super_block *p_s_sb);
+ int search_by_key(struct super_block *, const struct cpu_key *,
+-		  struct path *, int);
++		  struct treepath *, int);
+ #define search_item(s,key,path) search_by_key (s, key, path, DISK_LEAF_NODE_LEVEL)
+ int search_for_position_by_key(struct super_block *p_s_sb,
+ 			       const struct cpu_key *p_s_cpu_key,
+-			       struct path *p_s_search_path);
++			       struct treepath *p_s_search_path);
+ extern void decrement_bcount(struct buffer_head *p_s_bh);
+-void decrement_counters_in_path(struct path *p_s_search_path);
+-void pathrelse(struct path *p_s_search_path);
+-int reiserfs_check_path(struct path *p);
+-void pathrelse_and_restore(struct super_block *s, struct path *p_s_search_path);
++void decrement_counters_in_path(struct treepath *p_s_search_path);
++void pathrelse(struct treepath *p_s_search_path);
++int reiserfs_check_path(struct treepath *p);
++void pathrelse_and_restore(struct super_block *s, struct treepath *p_s_search_path);
+ 
+ int reiserfs_insert_item(struct reiserfs_transaction_handle *th,
+-			 struct path *path,
++			 struct treepath *path,
+ 			 const struct cpu_key *key,
+ 			 struct item_head *ih,
+ 			 struct inode *inode, const char *body);
+ 
+ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th,
+-			     struct path *path,
++			     struct treepath *path,
+ 			     const struct cpu_key *key,
+ 			     struct inode *inode,
+ 			     const char *body, int paste_size);
+ 
+ int reiserfs_cut_from_item(struct reiserfs_transaction_handle *th,
+-			   struct path *path,
++			   struct treepath *path,
+ 			   struct cpu_key *key,
+ 			   struct inode *inode,
+ 			   struct page *page, loff_t new_file_size);
+ 
+ int reiserfs_delete_item(struct reiserfs_transaction_handle *th,
+-			 struct path *path,
++			 struct treepath *path,
+ 			 const struct cpu_key *key,
+ 			 struct inode *inode, struct buffer_head *p_s_un_bh);
+ 
+@@ -1858,7 +1858,7 @@ void padd_item(char *item, int total_length, int length);
+ #define GET_BLOCK_NO_DANGLE   16	/* don't leave any transactions running */
+ 
+ int restart_transaction(struct reiserfs_transaction_handle *th,
+-			struct inode *inode, struct path *path);
++			struct inode *inode, struct treepath *path);
+ void reiserfs_read_locked_inode(struct inode *inode,
+ 				struct reiserfs_iget_args *args);
+ int reiserfs_find_actor(struct inode *inode, void *p);
+@@ -1905,7 +1905,7 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr);
+ /* namei.c */
+ void set_de_name_and_namelen(struct reiserfs_dir_entry *de);
+ int search_by_entry_key(struct super_block *sb, const struct cpu_key *key,
+-			struct path *path, struct reiserfs_dir_entry *de);
++			struct treepath *path, struct reiserfs_dir_entry *de);
+ struct dentry *reiserfs_get_parent(struct dentry *);
+ /* procfs.c */
+ 
+@@ -1956,9 +1956,9 @@ extern const struct file_operations reiserfs_dir_operations;
+ 
+ /* tail_conversion.c */
+ int direct2indirect(struct reiserfs_transaction_handle *, struct inode *,
+-		    struct path *, struct buffer_head *, loff_t);
++		    struct treepath *, struct buffer_head *, loff_t);
+ int indirect2direct(struct reiserfs_transaction_handle *, struct inode *,
+-		    struct page *, struct path *, const struct cpu_key *,
++		    struct page *, struct treepath *, const struct cpu_key *,
+ 		    loff_t, char *);
+ void reiserfs_unmap_buffer(struct buffer_head *);
+ 
+@@ -2045,7 +2045,7 @@ struct __reiserfs_blocknr_hint {
+ 	struct inode *inode;	/* inode passed to allocator, if we allocate unf. nodes */
+ 	long block;		/* file offset, in blocks */
+ 	struct in_core_key key;
+-	struct path *path;	/* search path, used by allocator to deternine search_start by
++	struct treepath *path;	/* search path, used by allocator to deternine search_start by
+ 				 * various ways */
+ 	struct reiserfs_transaction_handle *th;	/* transaction handle is needed to log super blocks and
+ 						 * bitmap blocks changes  */
+@@ -2101,7 +2101,7 @@ static inline int reiserfs_new_form_blocknrs(struct tree_balance *tb,
+ static inline int reiserfs_new_unf_blocknrs(struct reiserfs_transaction_handle
+ 					    *th, struct inode *inode,
+ 					    b_blocknr_t * new_blocknrs,
+-					    struct path *path, long block)
++					    struct treepath *path, long block)
+ {
+ 	reiserfs_blocknr_hint_t hint = {
+ 		.th = th,
+@@ -2118,7 +2118,7 @@ static inline int reiserfs_new_unf_blocknrs(struct reiserfs_transaction_handle
+ static inline int reiserfs_new_unf_blocknrs2(struct reiserfs_transaction_handle
+ 					     *th, struct inode *inode,
+ 					     b_blocknr_t * new_blocknrs,
+-					     struct path *path, long block)
++					     struct treepath *path, long block)
+ {
+ 	reiserfs_blocknr_hint_t hint = {
+ 		.th = th,

commit 0cc72dc7f050188d8d7344b1dd688cbc68d3cd30
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:31 2006 -0800
+
+    [PATCH] eCryptfs: Use fsstack's generic copy inode attr functions
+    
+    Replace eCryptfs specific code & calls with the more generic fsstack
+    equivalents and remove the eCryptfs specific functions.
+    
+    Signed-off-by: Josef "Jeff" Sipek 
+    Cc: Michael Halcrow 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c
+index 52d1e36dc746..329efcd3d8c9 100644
+--- a/fs/ecryptfs/dentry.c
++++ b/fs/ecryptfs/dentry.c
+@@ -25,6 +25,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include "ecryptfs_kernel.h"
+ 
+ /**
+@@ -61,7 +62,7 @@ static int ecryptfs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
+ 		struct inode *lower_inode =
+ 			ecryptfs_inode_to_lower(dentry->d_inode);
+ 
+-		ecryptfs_copy_attr_all(dentry->d_inode, lower_inode);
++		fsstack_copy_attr_all(dentry->d_inode, lower_inode, NULL);
+ 	}
+ out:
+ 	return rc;
+diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
+index f992533d1692..424137fb5898 100644
+--- a/fs/ecryptfs/ecryptfs_kernel.h
++++ b/fs/ecryptfs/ecryptfs_kernel.h
+@@ -28,6 +28,7 @@
+ 
+ #include 
+ #include 
++#include 
+ #include 
+ 
+ /* Version verification for shared data structures w/ userspace */
+@@ -413,9 +414,6 @@ int ecryptfs_encode_filename(struct ecryptfs_crypt_stat *crypt_stat,
+ 			     const char *name, int length,
+ 			     char **encoded_name);
+ struct dentry *ecryptfs_lower_dentry(struct dentry *this_dentry);
+-void ecryptfs_copy_attr_atime(struct inode *dest, const struct inode *src);
+-void ecryptfs_copy_attr_all(struct inode *dest, const struct inode *src);
+-void ecryptfs_copy_inode_size(struct inode *dst, const struct inode *src);
+ void ecryptfs_dump_hex(char *data, int bytes);
+ int virt_to_scatterlist(const void *addr, int size, struct scatterlist *sg,
+ 			int sg_size);
+diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
+index 42099e779a56..c48e4590b110 100644
+--- a/fs/ecryptfs/file.c
++++ b/fs/ecryptfs/file.c
+@@ -30,6 +30,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include "ecryptfs_kernel.h"
+ 
+ /**
+@@ -192,7 +193,7 @@ static int ecryptfs_readdir(struct file *file, void *dirent, filldir_t filldir)
+ 		goto retry;
+ 	file->f_pos = lower_file->f_pos;
+ 	if (rc >= 0)
+-		ecryptfs_copy_attr_atime(inode, lower_file->f_dentry->d_inode);
++		fsstack_copy_attr_atime(inode, lower_file->f_dentry->d_inode);
+ 	return rc;
+ }
+ 
+diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
+index 8a1945a84c36..c07a937b21ac 100644
+--- a/fs/ecryptfs/inode.c
++++ b/fs/ecryptfs/inode.c
+@@ -30,6 +30,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include "ecryptfs_kernel.h"
+ 
+ static struct dentry *lock_parent(struct dentry *dentry)
+@@ -53,48 +54,6 @@ static void unlock_dir(struct dentry *dir)
+ 	dput(dir);
+ }
+ 
+-void ecryptfs_copy_inode_size(struct inode *dst, const struct inode *src)
+-{
+-	i_size_write(dst, i_size_read((struct inode *)src));
+-	dst->i_blocks = src->i_blocks;
+-}
+-
+-void ecryptfs_copy_attr_atime(struct inode *dest, const struct inode *src)
+-{
+-	dest->i_atime = src->i_atime;
+-}
+-
+-static void ecryptfs_copy_attr_times(struct inode *dest,
+-				     const struct inode *src)
+-{
+-	dest->i_atime = src->i_atime;
+-	dest->i_mtime = src->i_mtime;
+-	dest->i_ctime = src->i_ctime;
+-}
+-
+-static void ecryptfs_copy_attr_timesizes(struct inode *dest,
+-					 const struct inode *src)
+-{
+-	dest->i_atime = src->i_atime;
+-	dest->i_mtime = src->i_mtime;
+-	dest->i_ctime = src->i_ctime;
+-	ecryptfs_copy_inode_size(dest, src);
+-}
+-
+-void ecryptfs_copy_attr_all(struct inode *dest, const struct inode *src)
+-{
+-	dest->i_mode = src->i_mode;
+-	dest->i_nlink = src->i_nlink;
+-	dest->i_uid = src->i_uid;
+-	dest->i_gid = src->i_gid;
+-	dest->i_rdev = src->i_rdev;
+-	dest->i_atime = src->i_atime;
+-	dest->i_mtime = src->i_mtime;
+-	dest->i_ctime = src->i_ctime;
+-	dest->i_blkbits = src->i_blkbits;
+-	dest->i_flags = src->i_flags;
+-}
+-
+ /**
+  * ecryptfs_create_underlying_file
+  * @lower_dir_inode: inode of the parent in the lower fs of the new file
+@@ -171,8 +130,8 @@ ecryptfs_do_create(struct inode *directory_inode,
+ 		ecryptfs_printk(KERN_ERR, "Failure in ecryptfs_interpose\n");
+ 		goto out_lock;
+ 	}
+-	ecryptfs_copy_attr_timesizes(directory_inode,
+-				     lower_dir_dentry->d_inode);
++	fsstack_copy_attr_times(directory_inode, lower_dir_dentry->d_inode);
++	fsstack_copy_inode_size(directory_inode, lower_dir_dentry->d_inode);
+ out_lock:
+ 	unlock_dir(lower_dir_dentry);
+ out:
+@@ -365,7 +324,7 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
+        		"d_name.name = [%s]\n", lower_dentry,
+ 		lower_dentry->d_name.name);
+ 	lower_inode = lower_dentry->d_inode;
+-	ecryptfs_copy_attr_atime(dir, lower_dir_dentry->d_inode);
++	fsstack_copy_attr_atime(dir, lower_dir_dentry->d_inode);
+ 	BUG_ON(!atomic_read(&lower_dentry->d_count));
+ 	ecryptfs_set_dentry_private(dentry,
+ 				    kmem_cache_alloc(ecryptfs_dentry_info_cache,
+@@ -462,7 +421,8 @@ static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir,
+ 	rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb, 0);
+ 	if (rc)
+ 		goto out_lock;
+-	ecryptfs_copy_attr_timesizes(dir, lower_new_dentry->d_inode);
++	fsstack_copy_attr_times(dir, lower_new_dentry->d_inode);
++	fsstack_copy_inode_size(dir, lower_new_dentry->d_inode);
+ 	old_dentry->d_inode->i_nlink =
+ 		ecryptfs_inode_to_lower(old_dentry->d_inode)->i_nlink;
+ 	i_size_write(new_dentry->d_inode, file_size_save);
+@@ -488,7 +448,7 @@ static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry)
+ 		printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc);
+ 		goto out_unlock;
+ 	}
+-	ecryptfs_copy_attr_times(dir, lower_dir_inode);
++	fsstack_copy_attr_times(dir, lower_dir_inode);
+ 	dentry->d_inode->i_nlink =
+ 		ecryptfs_inode_to_lower(dentry->d_inode)->i_nlink;
+ 	dentry->d_inode->i_ctime = dir->i_ctime;
+@@ -527,7 +487,8 @@ static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry,
+ 	rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
+ 	if (rc)
+ 		goto out_lock;
+-	ecryptfs_copy_attr_timesizes(dir, lower_dir_dentry->d_inode);
++	fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
++	fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
+ out_lock:
+ 	unlock_dir(lower_dir_dentry);
+ 	dput(lower_dentry);
+@@ -550,7 +511,8 @@ static int ecryptfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+ 	rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
+ 	if (rc)
+ 		goto out;
+-	ecryptfs_copy_attr_timesizes(dir, lower_dir_dentry->d_inode);
++	fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
++	fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
+ 	dir->i_nlink = lower_dir_dentry->d_inode->i_nlink;
+ out:
+ 	unlock_dir(lower_dir_dentry);
+@@ -573,7 +535,7 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
+ 	dput(lower_dentry);
+ 	if (!rc)
+ 		d_delete(lower_dentry);
+-	ecryptfs_copy_attr_times(dir, lower_dir_dentry->d_inode);
++	fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
+ 	dir->i_nlink = lower_dir_dentry->d_inode->i_nlink;
+ 	unlock_dir(lower_dir_dentry);
+ 	if (!rc)
+@@ -597,7 +559,8 @@ ecryptfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+ 	rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
+ 	if (rc)
+ 		goto out;
+-	ecryptfs_copy_attr_timesizes(dir, lower_dir_dentry->d_inode);
++	fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
++	fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
+ out:
+ 	unlock_dir(lower_dir_dentry);
+ 	if (!dentry->d_inode)
+@@ -626,9 +589,9 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 			lower_new_dir_dentry->d_inode, lower_new_dentry);
+ 	if (rc)
+ 		goto out_lock;
+-	ecryptfs_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
++	fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode, NULL);
+ 	if (new_dir != old_dir)
+-		ecryptfs_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);
++		fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode, NULL);
+ out_lock:
+ 	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
+ 	dput(lower_new_dentry->d_parent);
+@@ -684,8 +647,8 @@ ecryptfs_readlink(struct dentry *dentry, char __user * buf, int bufsiz)
+ 				rc = -EFAULT;
+ 		}
+ 		kfree(decoded_name);
+-		ecryptfs_copy_attr_atime(dentry->d_inode,
+-					 lower_dentry->d_inode);
++		fsstack_copy_attr_atime(dentry->d_inode,
++					lower_dentry->d_inode);
+ 	}
+ out_free_lower_buf:
+ 	kfree(lower_buf);
+@@ -915,7 +878,7 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
+ 	}
+ 	rc = notify_change(lower_dentry, ia);
+ out:
+-	ecryptfs_copy_attr_all(inode, lower_inode);
++	fsstack_copy_attr_all(inode, lower_inode, NULL);
+ 	return rc;
+ }
+ 
+diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
+index 3ede12b25933..d0541ae8faba 100644
+--- a/fs/ecryptfs/main.c
++++ b/fs/ecryptfs/main.c
+@@ -35,6 +35,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include "ecryptfs_kernel.h"
+ 
+ /**
+@@ -112,10 +113,10 @@ int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry,
+ 		d_add(dentry, inode);
+ 	else
+ 		d_instantiate(dentry, inode);
+-	ecryptfs_copy_attr_all(inode, lower_inode);
++	fsstack_copy_attr_all(inode, lower_inode, NULL);
+ 	/* This size will be overwritten for real files w/ headers and
+ 	 * other metadata */
+-	ecryptfs_copy_inode_size(inode, lower_inode);
++	fsstack_copy_inode_size(inode, lower_inode);
+ out:
+ 	return rc;
+ }

commit 42cf11939becc717bd125d121a1a23415106a099
+Author: Josef "Jeff" Sipek 
+Date:   Fri Dec 8 02:36:31 2006 -0800
+
+    [PATCH] fsstack: Introduce fsstack_copy_{attr,inode}_*
+    
+    Introduce several fsstack_copy_* functions which allow stackable filesystems
+    (such as eCryptfs and Unionfs) to easily copy over (currently only) inode
+    attributes.  This prevents code duplication and allows for code reuse.
+    
+    [akpm@osdl.org: Remove unneeded wrapper]
+    [bunk@stusta.de: fs/stack.c should #include ]
+    Signed-off-by: Josef "Jeff" Sipek 
+    Cc: Michael Halcrow 
+    Signed-off-by: Adrian Bunk 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/Makefile b/fs/Makefile
+index 9a5ce9323bfd..b9ffa63f77fc 100644
+--- a/fs/Makefile
++++ b/fs/Makefile
+@@ -10,7 +10,8 @@ obj-y :=	open.o read_write.o file_table.o super.o \
+ 		ioctl.o readdir.o select.o fifo.o locks.o dcache.o inode.o \
+ 		attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \
+ 		seq_file.o xattr.o libfs.o fs-writeback.o \
+-		pnode.o drop_caches.o splice.o sync.o utimes.o
++		pnode.o drop_caches.o splice.o sync.o utimes.o \
++		stack.o
+ 
+ ifeq ($(CONFIG_BLOCK),y)
+ obj-y +=	buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o
+diff --git a/fs/stack.c b/fs/stack.c
+new file mode 100644
+index 000000000000..5ddbc34535f9
+--- /dev/null
++++ b/fs/stack.c
+@@ -0,0 +1,40 @@
++#include 
++#include 
++#include 
++
++/* does _NOT_ require i_mutex to be held.
++ *
++ * This function cannot be inlined since i_size_{read,write} is rather
++ * heavy-weight on 32-bit systems
++ */
++void fsstack_copy_inode_size(struct inode *dst, const struct inode *src)
++{
++	i_size_write(dst, i_size_read((struct inode *)src));
++	dst->i_blocks = src->i_blocks;
++}
++EXPORT_SYMBOL_GPL(fsstack_copy_inode_size);
++
++/* copy all attributes; get_nlinks is optional way to override the i_nlink
++ * copying
++ */
++void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
++				int (*get_nlinks)(struct inode *))
++{
++	if (!get_nlinks)
++		dest->i_nlink = src->i_nlink;
++	else
++		dest->i_nlink = (*get_nlinks)(dest);
++
++	dest->i_mode = src->i_mode;
++	dest->i_uid = src->i_uid;
++	dest->i_gid = src->i_gid;
++	dest->i_rdev = src->i_rdev;
++	dest->i_atime = src->i_atime;
++	dest->i_mtime = src->i_mtime;
++	dest->i_ctime = src->i_ctime;
++	dest->i_blkbits = src->i_blkbits;
++	dest->i_flags = src->i_flags;
++
++	fsstack_copy_inode_size(dest, src);
++}
++EXPORT_SYMBOL_GPL(fsstack_copy_attr_all);
+diff --git a/include/linux/fs_stack.h b/include/linux/fs_stack.h
+new file mode 100644
+index 000000000000..bb516ceeefc9
+--- /dev/null
++++ b/include/linux/fs_stack.h
+@@ -0,0 +1,31 @@
++#ifndef _LINUX_FS_STACK_H
++#define _LINUX_FS_STACK_H
++
++/* This file defines generic functions used primarily by stackable
++ * filesystems; none of these functions require i_mutex to be held.
++ */
++
++#include 
++
++/* externs for fs/stack.c */
++extern void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
++				int (*get_nlinks)(struct inode *));
++
++extern void fsstack_copy_inode_size(struct inode *dst, const struct inode *src);
++
++/* inlines */
++static inline void fsstack_copy_attr_atime(struct inode *dest,
++					   const struct inode *src)
++{
++	dest->i_atime = src->i_atime;
++}
++
++static inline void fsstack_copy_attr_times(struct inode *dest,
++					   const struct inode *src)
++{
++	dest->i_atime = src->i_atime;
++	dest->i_mtime = src->i_mtime;
++	dest->i_ctime = src->i_ctime;
++}
++
++#endif /* _LINUX_FS_STACK_H */

commit 152194aaa6266d71dfee57882a23def339ef17a4
+Author: Avishay Traeger 
+Date:   Sun Jan 8 01:00:58 2006 -0800
+
+    [PATCH] set_page_count() macro safety
+    
+    Fix set_page_count() macro to handle complex arguments.
+    
+    Signed-off-by: Avishay Traeger 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/mm.h b/include/linux/mm.h
+index 83c651f25188..7ff54242c5d7 100644
+--- a/include/linux/mm.h
++++ b/include/linux/mm.h
+@@ -308,7 +308,7 @@ struct page {
+  */
+ #define get_page_testone(p)	atomic_inc_and_test(&(p)->_count)
+ 
+-#define set_page_count(p,v) 	atomic_set(&(p)->_count, v - 1)
++#define set_page_count(p,v) 	atomic_set(&(p)->_count, (v) - 1)
+ #define __put_page(p)		atomic_dec(&(p)->_count)
+ 
+ extern void FASTCALL(__page_cache_release(struct page *));

\ No newline at end of file diff --git a/detail/21.html b/detail/21.html new file mode 100644 index 0000000..ed76278 --- /dev/null +++ b/detail/21.html @@ -0,0 +1,1671 @@ +

Patches contributed by Concordia University Wisconsin


commit aef6a62d8b517f7472105971d5e221ef55a320be
+Author: Greg Dietsche 
+Date:   Mon Feb 27 12:25:33 2012 -0600
+
+    iwlegacy: remove unused enum il4965_calib_enabled_state
+    
+    Remove the enum il4965_calib_enabled_state because it is not used.
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h
+index d0de922cb937..5f5017767b99 100644
+--- a/drivers/net/wireless/iwlegacy/common.h
++++ b/drivers/net/wireless/iwlegacy/common.h
+@@ -956,11 +956,6 @@ enum il4965_chain_noise_state {
+ 	IL_CHAIN_NOISE_DONE,
+ };
+ 
+-enum il4965_calib_enabled_state {
+-	IL_CALIB_DISABLED = 0,	/* must be 0 */
+-	IL_CALIB_ENABLED = 1,
+-};
+-
+ enum ucode_type {
+ 	UCODE_NONE = 0,
+ 	UCODE_INIT,

commit d7b6b6a64301d6b0c632c8b9563a27aeeb09e967
+Author: Greg Dietsche 
+Date:   Mon Feb 27 12:25:32 2012 -0600
+
+    iwlegacy: remove enum iw_calib and related code
+    
+    Remove the enum il_calib. It defined one identifier: IL_CALIB_MAX.
+    Remove the function il4965_calib_free_results. It was doing nothing
+    because IL_CALIB_MAX is zero. Next, remove calib_results from the
+    il_priv structure and also remove the associated return
+    type/struct il_calib_result.
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/iwlegacy/4965-calib.c b/drivers/net/wireless/iwlegacy/4965-calib.c
+index 47c20e3d5605..e78bdefb8952 100644
+--- a/drivers/net/wireless/iwlegacy/4965-calib.c
++++ b/drivers/net/wireless/iwlegacy/4965-calib.c
+@@ -79,18 +79,6 @@ struct stats_general_data {
+ 	u32 beacon_energy_c;
+ };
+ 
+-void
+-il4965_calib_free_results(struct il_priv *il)
+-{
+-	int i;
+-
+-	for (i = 0; i < IL_CALIB_MAX; i++) {
+-		kfree(il->calib_results[i].buf);
+-		il->calib_results[i].buf = NULL;
+-		il->calib_results[i].buf_len = 0;
+-	}
+-}
+-
+ /*****************************************************************************
+  * RUNTIME calibrations framework
+  *****************************************************************************/
+diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
+index 2329033e23d7..7b54dbb338be 100644
+--- a/drivers/net/wireless/iwlegacy/4965-mac.c
++++ b/drivers/net/wireless/iwlegacy/4965-mac.c
+@@ -6347,7 +6347,6 @@ il4965_init_drv(struct il_priv *il)
+ static void
+ il4965_uninit_drv(struct il_priv *il)
+ {
+-	il4965_calib_free_results(il);
+ 	il_free_geos(il);
+ 	il_free_channel_map(il);
+ 	kfree(il->scan_cmd);
+diff --git a/drivers/net/wireless/iwlegacy/4965.h b/drivers/net/wireless/iwlegacy/4965.h
+index 208a4564d063..1db677689cfe 100644
+--- a/drivers/net/wireless/iwlegacy/4965.h
++++ b/drivers/net/wireless/iwlegacy/4965.h
+@@ -927,7 +927,6 @@ void il4965_chain_noise_calibration(struct il_priv *il, void *stat_resp);
+ void il4965_sensitivity_calibration(struct il_priv *il, void *resp);
+ void il4965_init_sensitivity(struct il_priv *il);
+ void il4965_reset_run_time_calib(struct il_priv *il);
+-void il4965_calib_free_results(struct il_priv *il);
+ 
+ /* Debug */
+ #ifdef CONFIG_IWLEGACY_DEBUGFS
+diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h
+index 6ed9871f1c4b..d0de922cb937 100644
+--- a/drivers/net/wireless/iwlegacy/common.h
++++ b/drivers/net/wireless/iwlegacy/common.h
+@@ -961,21 +961,6 @@ enum il4965_calib_enabled_state {
+ 	IL_CALIB_ENABLED = 1,
+ };
+ 
+-/*
+- * enum il_calib
+- * defines the order in which results of initial calibrations
+- * should be sent to the runtime uCode
+- */
+-enum il_calib {
+-	IL_CALIB_MAX,
+-};
+-
+-/* Opaque calibration results */
+-struct il_calib_result {
+-	void *buf;
+-	size_t buf_len;
+-};
+-
+ enum ucode_type {
+ 	UCODE_NONE = 0,
+ 	UCODE_INIT,
+@@ -1195,9 +1180,6 @@ struct il_priv {
+ 	s32 temperature;	/* degrees Kelvin */
+ 	s32 last_temperature;
+ 
+-	/* init calibration results */
+-	struct il_calib_result calib_results[IL_CALIB_MAX];
+-
+ 	/* Scan related variables */
+ 	unsigned long scan_start;
+ 	unsigned long scan_start_tsf;

commit 08db1ab7fa4cab08c1e24f373439d472d054a921
+Author: Greg Dietsche 
+Date:   Mon Feb 27 12:25:31 2012 -0600
+
+    iwlegacy: Kconfig: Change Debug Option to be more clear
+    
+    Since the menuconfig system doesn't indent the debug options
+    for the 3945 /4965, add some text to make it clear which
+    debug options are being configured.
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/iwlegacy/Kconfig b/drivers/net/wireless/iwlegacy/Kconfig
+index 4d81b80b16e6..fb919727b8bb 100644
+--- a/drivers/net/wireless/iwlegacy/Kconfig
++++ b/drivers/net/wireless/iwlegacy/Kconfig
+@@ -60,7 +60,7 @@ config IWL3945
+ 	  say M here and read .  The
+ 	  module will be called iwl3945.
+ 
+-menu "Debugging Options"
++menu "iwl3945 / iwl4965 Debugging Options"
+ 	depends on IWLEGACY
+ 
+ config IWLEGACY_DEBUG

commit 649921499c7116d5283b02ec432ff42229aefccd
+Author: Greg Dietsche 
+Date:   Mon Feb 27 12:25:30 2012 -0600
+
+    iwlegacy: Kconfig: Move Debugging Options
+    
+    Move the debug options so they appear below the 3945 / 4965 options.
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/iwlegacy/Kconfig b/drivers/net/wireless/iwlegacy/Kconfig
+index 05bd375cb845..4d81b80b16e6 100644
+--- a/drivers/net/wireless/iwlegacy/Kconfig
++++ b/drivers/net/wireless/iwlegacy/Kconfig
+@@ -6,45 +6,6 @@ config IWLEGACY
+ 	select LEDS_TRIGGERS
+ 	select MAC80211_LEDS
+ 
+-menu "Debugging Options"
+-	depends on IWLEGACY
+-
+-config IWLEGACY_DEBUG
+-	bool "Enable full debugging output in iwlegacy (iwl 3945/4965) drivers"
+-	depends on IWLEGACY
+-	---help---
+-	  This option will enable debug tracing output for the iwlegacy
+-	  drivers.
+-
+-	  This will result in the kernel module being ~100k larger.  You can
+-	  control which debug output is sent to the kernel log by setting the
+-	  value in
+-
+-		/sys/class/net/wlan0/device/debug_level
+-
+-	  This entry will only exist if this option is enabled.
+-
+-	  To set a value, simply echo an 8-byte hex value to the same file:
+-
+-		  % echo 0x43fff > /sys/class/net/wlan0/device/debug_level
+-
+-	  You can find the list of debug mask values in:
+-		  drivers/net/wireless/iwlegacy/common.h
+-
+-	  If this is your first time using this driver, you should say Y here
+-	  as the debug information can assist others in helping you resolve
+-	  any problems you may encounter.
+-
+-config IWLEGACY_DEBUGFS
+-        bool "iwlegacy (iwl 3945/4965) debugfs support"
+-        depends on IWLEGACY && MAC80211_DEBUGFS
+-        ---help---
+-	  Enable creation of debugfs files for the iwlegacy drivers. This
+-	  is a low-impact option that allows getting insight into the
+-	  driver's state at runtime.
+-
+-endmenu
+-
+ config IWL4965
+ 	tristate "Intel Wireless WiFi 4965AGN (iwl4965)"
+ 	depends on PCI && MAC80211
+@@ -98,3 +59,42 @@ config IWL3945
+ 	  inserted in and removed from the running kernel whenever you want),
+ 	  say M here and read .  The
+ 	  module will be called iwl3945.
++
++menu "Debugging Options"
++	depends on IWLEGACY
++
++config IWLEGACY_DEBUG
++	bool "Enable full debugging output in iwlegacy (iwl 3945/4965) drivers"
++	depends on IWLEGACY
++	---help---
++	  This option will enable debug tracing output for the iwlegacy
++	  drivers.
++
++	  This will result in the kernel module being ~100k larger.  You can
++	  control which debug output is sent to the kernel log by setting the
++	  value in
++
++		/sys/class/net/wlan0/device/debug_level
++
++	  This entry will only exist if this option is enabled.
++
++	  To set a value, simply echo an 8-byte hex value to the same file:
++
++		  % echo 0x43fff > /sys/class/net/wlan0/device/debug_level
++
++	  You can find the list of debug mask values in:
++		  drivers/net/wireless/iwlegacy/common.h
++
++	  If this is your first time using this driver, you should say Y here
++	  as the debug information can assist others in helping you resolve
++	  any problems you may encounter.
++
++config IWLEGACY_DEBUGFS
++        bool "iwlegacy (iwl 3945/4965) debugfs support"
++        depends on IWLEGACY && MAC80211_DEBUGFS
++        ---help---
++	  Enable creation of debugfs files for the iwlegacy drivers. This
++	  is a low-impact option that allows getting insight into the
++	  driver's state at runtime.
++
++endmenu

commit 42f1c01b79d54a00012c553b95fc7fe266d82394
+Author: Greg Dietsche 
+Date:   Fri Jan 20 17:10:35 2012 -0600
+
+    coccicheck: change handling of C={1,2} when M= is set
+    
+    This patch reverts a portion of d0bc1fb4 so that coccicheck will
+    work properly when C=1 or C=2.
+    
+    Reported-and-tested-by: Brice Goglin 
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: Julia Lawall 
+    Signed-off-by: Michal Marek 
+
+diff --git a/scripts/coccicheck b/scripts/coccicheck
+index 3c2776466d87..823e972149e5 100755
+--- a/scripts/coccicheck
++++ b/scripts/coccicheck
+@@ -9,15 +9,10 @@ if [ "$C" = "1" -o "$C" = "2" ]; then
+ #    FLAGS="-ignore_unknown_options -very_quiet"
+ #    OPTIONS=$*
+ 
+-    if [ "$KBUILD_EXTMOD" = "" ] ; then
+-        # Workaround for Coccinelle < 0.2.3
+-        FLAGS="-I $srctree/include -very_quiet"
+-        shift $(( $# - 1 ))
+-        OPTIONS=$1
+-    else
+-	echo M= is not currently supported when C=1 or C=2
+-	exit 1
+-    fi
++# Workaround for Coccinelle < 0.2.3
++	FLAGS="-I $srctree/include -very_quiet"
++	shift $(( $# - 1 ))
++	OPTIONS=$1
+ else
+     ONLINE=0
+     FLAGS="-very_quiet"

commit 28aa41fb8d555b120edefd7fdf879b156a1c9f3a
+Author: Greg Dietsche 
+Date:   Sun Jan 15 14:44:34 2012 -0600
+
+    staging: android: ram_console use kmemdup instead of kmalloc
+    
+    Replace kmalloc + memcpy will kmemdup in ram_console_late_init
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/android/ram_console.c b/drivers/staging/android/ram_console.c
+index 6d4d67924f22..0cb3f3c227fc 100644
+--- a/drivers/staging/android/ram_console.c
++++ b/drivers/staging/android/ram_console.c
+@@ -411,15 +411,14 @@ static int __init ram_console_late_init(void)
+ 	if (ram_console_old_log == NULL)
+ 		return 0;
+ #ifdef CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT
+-	ram_console_old_log = kmalloc(ram_console_old_log_size, GFP_KERNEL);
++	ram_console_old_log = kmemdup(ram_console_old_log_init_buffer,
++					ram_console_old_log_size, GFP_KERNEL);
+ 	if (ram_console_old_log == NULL) {
+ 		printk(KERN_ERR
+ 		       "ram_console: failed to allocate buffer for old log\n");
+ 		ram_console_old_log_size = 0;
+ 		return 0;
+ 	}
+-	memcpy(ram_console_old_log,
+-	       ram_console_old_log_init_buffer, ram_console_old_log_size);
+ #endif
+ 	entry = create_proc_entry("last_kmsg", S_IFREG | S_IRUGO, NULL);
+ 	if (!entry) {

commit 65b2576c9d3970e5c19aad5d2b56372ba56186a9
+Author: Greg Dietsche 
+Date:   Fri Jan 20 17:10:35 2012 -0600
+
+    coccicheck: change handling of C={1,2} when M= is set
+    
+    This patch reverts a portion of d0bc1fb4 so that coccicheck will
+    work properly when C=1 or C=2.
+    
+    Reported-and-tested-by: Brice Goglin 
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: Julia Lawall 
+    Signed-off-by: Michal Marek 
+
+diff --git a/scripts/coccicheck b/scripts/coccicheck
+index 3c2776466d87..823e972149e5 100755
+--- a/scripts/coccicheck
++++ b/scripts/coccicheck
+@@ -9,15 +9,10 @@ if [ "$C" = "1" -o "$C" = "2" ]; then
+ #    FLAGS="-ignore_unknown_options -very_quiet"
+ #    OPTIONS=$*
+ 
+-    if [ "$KBUILD_EXTMOD" = "" ] ; then
+-        # Workaround for Coccinelle < 0.2.3
+-        FLAGS="-I $srctree/include -very_quiet"
+-        shift $(( $# - 1 ))
+-        OPTIONS=$1
+-    else
+-	echo M= is not currently supported when C=1 or C=2
+-	exit 1
+-    fi
++# Workaround for Coccinelle < 0.2.3
++	FLAGS="-I $srctree/include -very_quiet"
++	shift $(( $# - 1 ))
++	OPTIONS=$1
+ else
+     ONLINE=0
+     FLAGS="-very_quiet"

commit f95ab20972cfefa8ee5428d6c3afd4cb8eacabf4
+Author: Greg Dietsche 
+Date:   Sat Nov 5 20:59:44 2011 -0500
+
+    coccinelle.txt: update documentation to include M= option
+    
+    Adding documentation for the new M= option which limits Coccinelle
+    to a specific set of directories.
+    
+    Signed-off-by: Greg Dietsche 
+    Acked-by: Julia Lawall 
+    Signed-off-by: Michal Marek 
+
+diff --git a/Documentation/coccinelle.txt b/Documentation/coccinelle.txt
+index 96b690348ba1..cf44eb6499b4 100644
+--- a/Documentation/coccinelle.txt
++++ b/Documentation/coccinelle.txt
+@@ -102,9 +102,15 @@ or
+ 	make coccicheck COCCI= MODE=report
+ 
+ 
+- Using Coccinelle on (modified) files
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ Controlling Which Files are Processed by Coccinelle
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++By default the entire kernel source tree is checked.
++
++To apply Coccinelle to a specific directory, M= can be used.
++For example, to check drivers/net/wireless/ one may write:
+ 
++    make coccicheck M=drivers/net/wireless/
++    
+ To apply Coccinelle on a file basis, instead of a directory basis, the
+ following command may be used:
+ 

commit d0bc1fb4672b978b608400a5112249cdbc28f9ae
+Author: Greg Dietsche 
+Date:   Sat Nov 5 20:59:43 2011 -0500
+
+    coccicheck: add M= option to control which dir is processed
+    
+    Examples:
+            make coccicheck M=drivers/net/wireless/
+            make coccicheck SUBDIRS=drivers/net/wireless/
+    
+    Version 2:
+            fix patch file names when using M=
+            tell coccinelle where the include files are
+    
+    Version 3:
+            Add second include option to support out of tree development
+            Fix error message
+    
+    Signed-off-by: Greg Dietsche 
+    Acked-by: Julia Lawall 
+    Signed-off-by: Michal Marek 
+
+diff --git a/scripts/coccicheck b/scripts/coccicheck
+index 1bb1a1bd2daa..3c2776466d87 100755
+--- a/scripts/coccicheck
++++ b/scripts/coccicheck
+@@ -9,14 +9,23 @@ if [ "$C" = "1" -o "$C" = "2" ]; then
+ #    FLAGS="-ignore_unknown_options -very_quiet"
+ #    OPTIONS=$*
+ 
+-# Workaround for Coccinelle < 0.2.3
+-    FLAGS="-I $srctree/include -very_quiet"
+-    shift $(( $# - 1 ))
+-    OPTIONS=$1
++    if [ "$KBUILD_EXTMOD" = "" ] ; then
++        # Workaround for Coccinelle < 0.2.3
++        FLAGS="-I $srctree/include -very_quiet"
++        shift $(( $# - 1 ))
++        OPTIONS=$1
++    else
++	echo M= is not currently supported when C=1 or C=2
++	exit 1
++    fi
+ else
+     ONLINE=0
+     FLAGS="-very_quiet"
+-    OPTIONS="-dir $srctree"
++    if [ "$KBUILD_EXTMOD" = "" ] ; then
++        OPTIONS="-dir $srctree"
++    else
++        OPTIONS="-dir $KBUILD_EXTMOD -patch $srctree -I $srctree/include -I $KBUILD_EXTMOD/include"
++    fi
+ fi
+ 
+ if [ ! -x "$SPATCH" ]; then

commit 9b5e2f463ac6f53789bd5ce43d2bb4b4c01e8607
+Author: Greg Dietsche 
+Date:   Tue Sep 6 19:11:35 2011 -0500
+
+    iwlegacy: debugfs_ops should depend on CONFIG_IWLEGACY_DEBUGFS
+    
+    Only setup structs related to debugfs_ops when CONFIG_IWLEGACY_DEBUGFS is set.
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: Stanislaw Gruszka 
+
+diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c
+index 7367dbb75ec6..863664f9ba8b 100644
+--- a/drivers/net/wireless/iwlegacy/3945.c
++++ b/drivers/net/wireless/iwlegacy/3945.c
+@@ -2671,11 +2671,13 @@ static struct il_lib_ops il3945_lib = {
+ 	.send_tx_power = il3945_send_tx_power,
+ 	.is_valid_rtc_data_addr = il3945_hw_valid_rtc_data_addr,
+ 
++#ifdef CONFIG_IWLEGACY_DEBUGFS
+ 	.debugfs_ops = {
+ 			.rx_stats_read = il3945_ucode_rx_stats_read,
+ 			.tx_stats_read = il3945_ucode_tx_stats_read,
+ 			.general_stats_read = il3945_ucode_general_stats_read,
+ 			},
++#endif
+ };
+ 
+ static const struct il_legacy_ops il3945_legacy_ops = {
+diff --git a/drivers/net/wireless/iwlegacy/3945.h b/drivers/net/wireless/iwlegacy/3945.h
+index 00d3336fd16b..2b2895c544d7 100644
+--- a/drivers/net/wireless/iwlegacy/3945.h
++++ b/drivers/net/wireless/iwlegacy/3945.h
+@@ -621,27 +621,6 @@ ssize_t il3945_ucode_tx_stats_read(struct file *file, char __user *user_buf,
+ ssize_t il3945_ucode_general_stats_read(struct file *file,
+ 					char __user *user_buf, size_t count,
+ 					loff_t *ppos);
+-#else
+-static ssize_t
+-il3945_ucode_rx_stats_read(struct file *file, char __user *user_buf,
+-			   size_t count, loff_t *ppos)
+-{
+-	return 0;
+-}
+-
+-static ssize_t
+-il3945_ucode_tx_stats_read(struct file *file, char __user *user_buf,
+-			   size_t count, loff_t *ppos)
+-{
+-	return 0;
+-}
+-
+-static ssize_t
+-il3945_ucode_general_stats_read(struct file *file, char __user *user_buf,
+-				size_t count, loff_t *ppos)
+-{
+-	return 0;
+-}
+ #endif
+ 
+ #endif
+diff --git a/drivers/net/wireless/iwlegacy/4965.c b/drivers/net/wireless/iwlegacy/4965.c
+index ac80a0069124..84c54dccf195 100644
+--- a/drivers/net/wireless/iwlegacy/4965.c
++++ b/drivers/net/wireless/iwlegacy/4965.c
+@@ -2333,11 +2333,13 @@ static struct il_lib_ops il4965_lib = {
+ 	.temp_ops = {
+ 		     .temperature = il4965_temperature_calib,
+ 		     },
++#ifdef CONFIG_IWLEGACY_DEBUGFS
+ 	.debugfs_ops = {
+ 			.rx_stats_read = il4965_ucode_rx_stats_read,
+ 			.tx_stats_read = il4965_ucode_tx_stats_read,
+ 			.general_stats_read = il4965_ucode_general_stats_read,
+ 			},
++#endif
+ };
+ 
+ static const struct il_legacy_ops il4965_legacy_ops = {
+diff --git a/drivers/net/wireless/iwlegacy/4965.h b/drivers/net/wireless/iwlegacy/4965.h
+index ded8b922a44e..74472314bc37 100644
+--- a/drivers/net/wireless/iwlegacy/4965.h
++++ b/drivers/net/wireless/iwlegacy/4965.h
+@@ -956,27 +956,6 @@ ssize_t il4965_ucode_tx_stats_read(struct file *file, char __user *user_buf,
+ ssize_t il4965_ucode_general_stats_read(struct file *file,
+ 					char __user *user_buf, size_t count,
+ 					loff_t *ppos);
+-#else
+-static ssize_t
+-il4965_ucode_rx_stats_read(struct file *file, char __user *user_buf,
+-			   size_t count, loff_t *ppos)
+-{
+-	return 0;
+-}
+-
+-static ssize_t
+-il4965_ucode_tx_stats_read(struct file *file, char __user *user_buf,
+-			   size_t count, loff_t *ppos)
+-{
+-	return 0;
+-}
+-
+-static ssize_t
+-il4965_ucode_general_stats_read(struct file *file, char __user *user_buf,
+-				size_t count, loff_t *ppos)
+-{
+-	return 0;
+-}
+ #endif
+ 
+ /****************************/
+diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h
+index d0975ab8b908..1bc0b02f559c 100644
+--- a/drivers/net/wireless/iwlegacy/common.h
++++ b/drivers/net/wireless/iwlegacy/common.h
+@@ -1631,6 +1631,7 @@ struct il_apm_ops {
+ 	void (*config) (struct il_priv *il);
+ };
+ 
++#ifdef CONFIG_IWLEGACY_DEBUGFS
+ struct il_debugfs_ops {
+ 	ssize_t(*rx_stats_read) (struct file *file, char __user *user_buf,
+ 				 size_t count, loff_t *ppos);
+@@ -1640,6 +1641,7 @@ struct il_debugfs_ops {
+ 				      char __user *user_buf, size_t count,
+ 				      loff_t *ppos);
+ };
++#endif
+ 
+ struct il_temp_ops {
+ 	void (*temperature) (struct il_priv *il);
+@@ -1683,7 +1685,9 @@ struct il_lib_ops {
+ 	/* temperature */
+ 	struct il_temp_ops temp_ops;
+ 
++#ifdef CONFIG_IWLEGACY_DEBUGFS
+ 	struct il_debugfs_ops debugfs_ops;
++#endif
+ 
+ };
+ 

commit e3a2c775336641663b1c38dfa7dd8a1c1210ae23
+Author: Greg Dietsche 
+Date:   Tue Sep 6 18:25:32 2011 -0500
+
+    iwlegacy: 4965-rs: cleanup il4965_rs_sta_dbgfs_rate_scale_data_read
+    
+    1) remove ret local var and return the result directly
+    2) remove il since it is not used
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: Stanislaw Gruszka 
+
+diff --git a/drivers/net/wireless/iwlegacy/4965-rs.c b/drivers/net/wireless/iwlegacy/4965-rs.c
+index 162c778773ec..467d0cb14ecd 100644
+--- a/drivers/net/wireless/iwlegacy/4965-rs.c
++++ b/drivers/net/wireless/iwlegacy/4965-rs.c
+@@ -2769,14 +2769,9 @@ il4965_rs_sta_dbgfs_rate_scale_data_read(struct file *file,
+ {
+ 	char buff[120];
+ 	int desc = 0;
+-	ssize_t ret;
+-
+ 	struct il_lq_sta *lq_sta = file->private_data;
+-	struct il_priv *il;
+ 	struct il_scale_tbl_info *tbl = &lq_sta->lq_info[lq_sta->active_tbl];
+ 
+-	il = lq_sta->drv;
+-
+ 	if (is_Ht(tbl->lq_type))
+ 		desc +=
+ 		    sprintf(buff + desc, "Bit Rate= %d Mb/s\n",
+@@ -2786,8 +2781,7 @@ il4965_rs_sta_dbgfs_rate_scale_data_read(struct file *file,
+ 		    sprintf(buff + desc, "Bit Rate= %d Mb/s\n",
+ 			    il_rates[lq_sta->last_txrate_idx].ieee >> 1);
+ 
+-	ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
+-	return ret;
++	return simple_read_from_buffer(user_buf, count, ppos, buff, desc);
+ }
+ 
+ static const struct file_operations rs_sta_dbgfs_rate_scale_data_ops = {

commit a741b99577c3fa359208c9ff14aede77bc0d0e02
+Author: Greg Dietsche 
+Date:   Tue Sep 6 17:49:07 2011 -0500
+
+    iwlegacy: 4965-rs: don't return rate from il4965_rs_update_rate_tbl
+    
+    1) don't return rate from il4965_rs_update_rate_tbl
+    2) fix up il4965_rs_rate_scale_perform
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: Stanislaw Gruszka 
+
+diff --git a/drivers/net/wireless/iwlegacy/4965-rs.c b/drivers/net/wireless/iwlegacy/4965-rs.c
+index 52006376febd..162c778773ec 100644
+--- a/drivers/net/wireless/iwlegacy/4965-rs.c
++++ b/drivers/net/wireless/iwlegacy/4965-rs.c
+@@ -1731,9 +1731,8 @@ il4965_rs_stay_in_table(struct il_lq_sta *lq_sta, bool force_search)
+ 
+ /*
+  * setup rate table in uCode
+- * return rate_n_flags as used in the table
+  */
+-static u32
++static void
+ il4965_rs_update_rate_tbl(struct il_priv *il, struct il_rxon_context *ctx,
+ 			  struct il_lq_sta *lq_sta,
+ 			  struct il_scale_tbl_info *tbl, int idx, u8 is_green)
+@@ -1744,8 +1743,6 @@ il4965_rs_update_rate_tbl(struct il_priv *il, struct il_rxon_context *ctx,
+ 	rate = il4965_rate_n_flags_from_tbl(il, tbl, idx, is_green);
+ 	il4965_rs_fill_link_cmd(il, lq_sta, rate);
+ 	il_send_lq_cmd(il, ctx, &lq_sta->lq, CMD_ASYNC, false);
+-
+-	return rate;
+ }
+ 
+ /*
+@@ -1774,7 +1771,6 @@ il4965_rs_rate_scale_perform(struct il_priv *il, struct sk_buff *skb,
+ 	u8 update_lq = 0;
+ 	struct il_scale_tbl_info *tbl, *tbl1;
+ 	u16 rate_scale_idx_msk = 0;
+-	u32 rate;
+ 	u8 is_green = 0;
+ 	u8 active_tbl = 0;
+ 	u8 done_search = 0;
+@@ -1858,8 +1854,7 @@ il4965_rs_rate_scale_perform(struct il_priv *il, struct sk_buff *skb,
+ 			tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+ 			/* get "active" rate info */
+ 			idx = il4965_hwrate_to_plcp_idx(tbl->current_rate);
+-			rate =
+-			    il4965_rs_update_rate_tbl(il, ctx, lq_sta, tbl, idx,
++			il4965_rs_update_rate_tbl(il, ctx, lq_sta, tbl, idx,
+ 						      is_green);
+ 		}
+ 		return;
+@@ -2062,8 +2057,7 @@ il4965_rs_rate_scale_perform(struct il_priv *il, struct sk_buff *skb,
+ lq_update:
+ 	/* Replace uCode's rate table for the destination station. */
+ 	if (update_lq)
+-		rate =
+-		    il4965_rs_update_rate_tbl(il, ctx, lq_sta, tbl, idx,
++		il4965_rs_update_rate_tbl(il, ctx, lq_sta, tbl, idx,
+ 					      is_green);
+ 
+ 	/* Should we stay with this modulation mode,

commit 3e4b0655207452be0a1d82425f19ed4a081cf48b
+Author: Greg Dietsche 
+Date:   Tue Sep 6 18:12:05 2011 -0500
+
+    iwlegacy: 4965-rs: il4965_rs_alloc_sta: remove lq_sta local var
+    
+    remove the lq_sta local variable and return the
+    result directly in il4965_rs_alloc_sta
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: Stanislaw Gruszka 
+
+diff --git a/drivers/net/wireless/iwlegacy/4965-rs.c b/drivers/net/wireless/iwlegacy/4965-rs.c
+index 2ec808e40c96..52006376febd 100644
+--- a/drivers/net/wireless/iwlegacy/4965-rs.c
++++ b/drivers/net/wireless/iwlegacy/4965-rs.c
+@@ -2295,7 +2295,6 @@ il4965_rs_get_rate(void *il_r, struct ieee80211_sta *sta, void *il_sta,
+ static void *
+ il4965_rs_alloc_sta(void *il_rate, struct ieee80211_sta *sta, gfp_t gfp)
+ {
+-	struct il_lq_sta *lq_sta;
+ 	struct il_station_priv *sta_priv =
+ 	    (struct il_station_priv *)sta->drv_priv;
+ 	struct il_priv *il;
+@@ -2303,9 +2302,7 @@ il4965_rs_alloc_sta(void *il_rate, struct ieee80211_sta *sta, gfp_t gfp)
+ 	il = (struct il_priv *)il_rate;
+ 	D_RATE("create station rate scale win\n");
+ 
+-	lq_sta = &sta_priv->lq_sta;
+-
+-	return lq_sta;
++	return &sta_priv->lq_sta;
+ }
+ 
+ /*

commit 144c0961b47ab07812ec1440adea6d4218b9a6a6
+Author: Greg Dietsche 
+Date:   Tue Sep 6 18:31:13 2011 -0500
+
+    iwlegacy: 4965-rs: remove unnecessary null check for sta and lq_sta
+    
+    both sta and lq_sta are guaranteed to be not null in the calling
+    function so we don't need to check them here.
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: Stanislaw Gruszka 
+
+diff --git a/drivers/net/wireless/iwlegacy/4965-rs.c b/drivers/net/wireless/iwlegacy/4965-rs.c
+index b0946a1ee37d..2ec808e40c96 100644
+--- a/drivers/net/wireless/iwlegacy/4965-rs.c
++++ b/drivers/net/wireless/iwlegacy/4965-rs.c
+@@ -1793,9 +1793,6 @@ il4965_rs_rate_scale_perform(struct il_priv *il, struct sk_buff *skb,
+ 	    (info->flags & IEEE80211_TX_CTL_NO_ACK))
+ 		return;
+ 
+-	if (!sta || !lq_sta)
+-		return;
+-
+ 	lq_sta->supp_rates = sta->supp_rates[lq_sta->band];
+ 
+ 	tid = il4965_rs_tl_add_packet(lq_sta, hdr);

commit da6134d2537363775c73e96186c0d5eb9b2c6b1c
+Author: Greg Dietsche 
+Date:   Tue Sep 6 17:38:34 2011 -0500
+
+    iwlegacy: 4965-rs: remove null check on sta in il4965_rs_tx_status
+    
+    the null check on sta in il4965_rs_tx_status is not necessary
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: Stanislaw Gruszka 
+
+diff --git a/drivers/net/wireless/iwlegacy/4965-rs.c b/drivers/net/wireless/iwlegacy/4965-rs.c
+index 93c3a4d9b9b5..b0946a1ee37d 100644
+--- a/drivers/net/wireless/iwlegacy/4965-rs.c
++++ b/drivers/net/wireless/iwlegacy/4965-rs.c
+@@ -991,7 +991,7 @@ il4965_rs_tx_status(void *il_r, struct ieee80211_supported_band *sband,
+ 	lq_sta->last_rate_n_flags = tx_rate;
+ done:
+ 	/* See if there's a better rate or modulation mode to try. */
+-	if (sta && sta->supp_rates[sband->band])
++	if (sta->supp_rates[sband->band])
+ 		il4965_rs_rate_scale_perform(il, skb, sta, lq_sta);
+ }
+ 

commit 730b4c2102902a0061bb01a3d3fa1b6461973849
+Author: Greg Dietsche 
+Date:   Tue Sep 6 17:33:51 2011 -0500
+
+    iwlegacy: 4965: remove vif null check in request_scan
+    
+    remove null check on vif in il4965_request_scan
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: Stanislaw Gruszka 
+
+diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
+index 8d2f6162d6e8..4aaef4135564 100644
+--- a/drivers/net/wireless/iwlegacy/4965-mac.c
++++ b/drivers/net/wireless/iwlegacy/4965-mac.c
+@@ -850,8 +850,7 @@ il4965_request_scan(struct il_priv *il, struct ieee80211_vif *vif)
+ 
+ 	lockdep_assert_held(&il->mutex);
+ 
+-	if (vif)
+-		ctx = il_rxon_ctx_from_vif(vif);
++	ctx = il_rxon_ctx_from_vif(vif);
+ 
+ 	if (!il->scan_cmd) {
+ 		il->scan_cmd =

commit dd44eb9e13131f7b1fda65518b24fd3dfcf3a114
+Author: Greg Dietsche 
+Date:   Sun Aug 28 08:32:10 2011 -0500
+
+    iwlegacy: change IL_ERR to D_HT in iwl4965_rs_tl_turn_on_agg_for_tid
+    
+    This message should be a debug message and not an error.
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: Stanislaw Gruszka 
+
+diff --git a/drivers/net/wireless/iwlegacy/4965-rs.c b/drivers/net/wireless/iwlegacy/4965-rs.c
+index 4bc5a1845821..93c3a4d9b9b5 100644
+--- a/drivers/net/wireless/iwlegacy/4965-rs.c
++++ b/drivers/net/wireless/iwlegacy/4965-rs.c
+@@ -371,10 +371,10 @@ il4965_rs_tl_turn_on_agg_for_tid(struct il_priv *il, struct il_lq_sta *lq_data,
+ 			IL_ERR("Fail start Tx agg on tid: %d\n", tid);
+ 			ieee80211_stop_tx_ba_session(sta, tid);
+ 		}
+-	} else {
+-		IL_ERR("Aggregation not enabled for tid %d "
+-		       "because load = %u\n", tid, load);
+-	}
++	} else
++		D_HT("Aggregation not enabled for tid %d because load = %u\n",
++		     tid, load);
++
+ 	return ret;
+ }
+ 

commit 53611e05263ca2101a29736920fdf86ccad0e93b
+Author: Greg Dietsche 
+Date:   Sun Aug 28 08:26:16 2011 -0500
+
+    iwlegacy: change IL_WARN to D_HT in il4965_tx_agg_start
+    
+    This message should be a debug message and not a warning.
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: Stanislaw Gruszka 
+
+diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
+index 21a1381c9748..8d2f6162d6e8 100644
+--- a/drivers/net/wireless/iwlegacy/4965-mac.c
++++ b/drivers/net/wireless/iwlegacy/4965-mac.c
+@@ -2252,7 +2252,7 @@ il4965_tx_agg_start(struct il_priv *il, struct ieee80211_vif *vif,
+ 	if (unlikely(tx_fifo < 0))
+ 		return tx_fifo;
+ 
+-	IL_WARN("%s on ra = %pM tid = %d\n", __func__, sta->addr, tid);
++	D_HT("%s on ra = %pM tid = %d\n", __func__, sta->addr, tid);
+ 
+ 	sta_id = il_sta_id(sta);
+ 	if (sta_id == IL_INVALID_STATION) {

commit a76011e2cbb6915f60488477311e0f269cee6496
+Author: Greg Dietsche 
+Date:   Wed Sep 28 17:54:04 2011 -0500
+
+    iwlagn: iwl-agn-rs: remove unnecessary null check for sta and lq_sta
+    
+    both sta and lq_sta are guaranteed to be not null in the
+    calling function so we don't need to check them here.
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: Wey-Yi Guy 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+index c14f8d6fd7d8..7d6a3bf64950 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
++++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+@@ -2273,9 +2273,6 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
+ 	    info->flags & IEEE80211_TX_CTL_NO_ACK)
+ 		return;
+ 
+-	if (!sta || !lq_sta)
+-		return;
+-
+ 	lq_sta->supp_rates = sta->supp_rates[lq_sta->band];
+ 
+ 	tid = rs_tl_add_packet(lq_sta, hdr);

commit 2fa8b6a0e42570690a48a56cb65778211e3cc9cc
+Author: Greg Dietsche 
+Date:   Sun Aug 28 08:22:38 2011 -0500
+
+    iwlwifi: iwl-agn-rs.c: remove old comment
+    
+    this comment refers to some code that was removed.
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: Wey-Yi Guy 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+index 356762f21d2f..ffee15ba06a8 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
++++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+@@ -2214,7 +2214,6 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)
+ 
+ /*
+  * setup rate table in uCode
+- * return rate_n_flags as used in the table
+  */
+ static void rs_update_rate_tbl(struct iwl_priv *priv,
+ 			       struct iwl_rxon_context *ctx,

commit d3690f8b713f9710e68214ca38fb8b07b587a2a7
+Author: Greg Dietsche 
+Date:   Thu Jun 16 11:42:07 2011 -0500
+
+    m68k/math-emu: Remove unnecessary code
+    
+    Remove unnecessary code that matches this coccinelle pattern
+    
+            if (...)
+                    return ret;
+            return ret;
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: Geert Uytterhoeven 
+
+diff --git a/arch/m68k/math-emu/fp_log.c b/arch/m68k/math-emu/fp_log.c
+index 367ecee2f981..3384a5244fbd 100644
+--- a/arch/m68k/math-emu/fp_log.c
++++ b/arch/m68k/math-emu/fp_log.c
+@@ -105,9 +105,6 @@ fp_fetoxm1(struct fp_ext *dest, struct fp_ext *src)
+ 
+ 	fp_monadic_check(dest, src);
+ 
+-	if (IS_ZERO(dest))
+-		return dest;
+-
+ 	return dest;
+ }
+ 

commit dbfe89877741726c30efb41f0132e247a78c3681
+Author: Greg Dietsche 
+Date:   Fri Jul 29 16:46:16 2011 +0100
+
+    frv: remove unnecessary code
+    
+    remove unnecessary code that matches this coccinelle pattern
+    
+            if (...)
+                    return ret;
+            return ret;
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: David Howells 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/frv/mm/pgalloc.c b/arch/frv/mm/pgalloc.c
+index c42c83d507bc..4fb63a36bd52 100644
+--- a/arch/frv/mm/pgalloc.c
++++ b/arch/frv/mm/pgalloc.c
+@@ -133,13 +133,7 @@ void pgd_dtor(void *pgd)
+ 
+ pgd_t *pgd_alloc(struct mm_struct *mm)
+ {
+-	pgd_t *pgd;
+-
+-	pgd = quicklist_alloc(0, GFP_KERNEL, pgd_ctor);
+-	if (!pgd)
+-		return pgd;
+-
+-	return pgd;
++	return quicklist_alloc(0, GFP_KERNEL, pgd_ctor);
+ }
+ 
+ void pgd_free(struct mm_struct *mm, pgd_t *pgd)

commit 3735edf9fd8bfa6e31025a7cc73447516278000b
+Author: Greg Dietsche 
+Date:   Thu Jun 16 13:33:35 2011 -0300
+
+    [media] dvb: remove unnecessary code
+    
+    remove unnecessary code that matches this coccinelle pattern
+            if (...)
+                    return ret;
+            return ret;
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb/frontends/cx24116.c
+index 95c6465b87a1..ccd05255d527 100644
+--- a/drivers/media/dvb/frontends/cx24116.c
++++ b/drivers/media/dvb/frontends/cx24116.c
+@@ -1452,11 +1452,7 @@ static int cx24116_set_frontend(struct dvb_frontend *fe,
+ 	cmd.args[0x00] = CMD_BANDWIDTH;
+ 	cmd.args[0x01] = 0x00;
+ 	cmd.len = 0x02;
+-	ret = cx24116_cmd_execute(fe, &cmd);
+-	if (ret != 0)
+-		return ret;
+-
+-	return ret;
++	return cx24116_cmd_execute(fe, &cmd);
+ }
+ 
+ static int cx24116_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *params,

commit 47db477e46fa12eec40597b365ef1fad1cf17842
+Author: Greg Dietsche 
+Date:   Thu Jun 16 11:39:21 2011 -0500
+
+    ata: remove unnecessary code
+    
+    Compile tested.
+    remove unnecessary code that matches this coccinelle pattern
+            if (...)
+                    return ret;
+            return ret;
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: Jeff Garzik 
+
+diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c
+index 91949d997555..54145edf50e8 100644
+--- a/drivers/ata/pata_acpi.c
++++ b/drivers/ata/pata_acpi.c
+@@ -195,8 +195,6 @@ static int pacpi_port_start(struct ata_port *ap)
+ 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ 	struct pata_acpi *acpi;
+ 
+-	int ret;
+-
+ 	if (ap->acpi_handle == NULL)
+ 		return -ENODEV;
+ 
+@@ -205,11 +203,7 @@ static int pacpi_port_start(struct ata_port *ap)
+ 		return -ENOMEM;
+ 	acpi->mask[0] = pacpi_discover_modes(ap, &ap->link.device[0]);
+ 	acpi->mask[1] = pacpi_discover_modes(ap, &ap->link.device[1]);
+-	ret = ata_bmdma_port_start(ap);
+-	if (ret < 0)
+-		return ret;
+-
+-	return ret;
++	return ata_bmdma_port_start(ap);
+ }
+ 
+ static struct scsi_host_template pacpi_sht = {

commit a6c23905ff0d6bbddf590ef0838489ee0f6c74ac
+Author: Greg Dietsche 
+Date:   Thu Jun 30 20:10:53 2011 -0500
+
+    x86, smpboot: Mark the names[] array in __inquire_remote_apic() as const
+    
+    This array is read-only. Make it explicit by marking as const.
+    
+    Signed-off-by: Greg Dietsche 
+    Link: http://lkml.kernel.org/r/1309482653-23648-1-git-send-email-Gregory.Dietsche@cuw.edu
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
+index a3c430bdfb60..e02653a2e4f7 100644
+--- a/arch/x86/kernel/smpboot.c
++++ b/arch/x86/kernel/smpboot.c
+@@ -425,7 +425,7 @@ static void impress_friends(void)
+ void __inquire_remote_apic(int apicid)
+ {
+ 	unsigned i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 };
+-	char *names[] = { "ID", "VERSION", "SPIV" };
++	const char * const names[] = { "ID", "VERSION", "SPIV" };
+ 	int timeout;
+ 	u32 status;
+ 

commit 3e878b8d54e0fc12df363ee8e4a638c8147aac98
+Author: Greg Dietsche 
+Date:   Fri Jul 1 16:16:19 2011 -0700
+
+    net: rds: fix const array syntax
+    
+    Correct the syntax so that both array and pointer are const.
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/rds/tcp_stats.c b/net/rds/tcp_stats.c
+index d5898d03cd68..f8a7954f1f59 100644
+--- a/net/rds/tcp_stats.c
++++ b/net/rds/tcp_stats.c
+@@ -40,7 +40,7 @@
+ DEFINE_PER_CPU(struct rds_tcp_statistics, rds_tcp_stats)
+ 	____cacheline_aligned;
+ 
+-static const char const *rds_tcp_stat_names[] = {
++static const char * const rds_tcp_stat_names[] = {
+ 	"tcp_data_ready_calls",
+ 	"tcp_write_space_calls",
+ 	"tcp_sndbuf_full",

commit b756828609ee8cb1320effc371cfafde6a6246fe
+Author: Greg Dietsche 
+Date:   Thu Jun 30 18:42:50 2011 -0500
+
+    gitignore: ignore debian build directory
+    
+    Have git ignore the Debian directory created when running:
+            make deb-pkg
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: Michal Marek 
+
+diff --git a/.gitignore b/.gitignore
+index 9dacde0a4b2d..57af07cf7e68 100644
+--- a/.gitignore
++++ b/.gitignore
+@@ -45,6 +45,11 @@ modules.builtin
+ /Module.markers
+ /Module.symvers
+ 
++#
++# Debian directory (make deb-pkg)
++#
++/debian/
++
+ #
+ # git files that we don't want to ignore even it they are dot-files
+ #

commit c5274ab09747d0ef829f9b8f040756758e5de55c
+Author: Greg Dietsche 
+Date:   Mon Jun 13 13:11:47 2011 -0500
+
+    staging: remove unnecessary code
+    
+    Compile tested.
+    remove unnecessary code that matches this coccinelle pattern
+            if (...)
+                    return ret;
+            return ret;
+    
+    Signed-off-by: Greg Dietsche 
+    Acked-by: Franky Lin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/bcm/Misc.c b/drivers/staging/bcm/Misc.c
+index c5003b62234c..c5b3a3666bc7 100644
+--- a/drivers/staging/bcm/Misc.c
++++ b/drivers/staging/bcm/Misc.c
+@@ -1447,16 +1447,10 @@ static void convertEndian(B_UINT8 rwFlag, PUINT puiBuffer, UINT uiByteCount)
+ 
+ int rdm(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize)
+ {
+-	INT uiRetVal =0;
+-
+-	uiRetVal = Adapter->interface_rdm(Adapter->pvInterfaceAdapter,
++	return Adapter->interface_rdm(Adapter->pvInterfaceAdapter,
+ 			uiAddress, pucBuff, sSize);
+-
+-	if(uiRetVal < 0)
+-		return uiRetVal;
+-
+-	return uiRetVal;
+ }
++
+ int wrm(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize)
+ {
+ 	int iRetVal;
+diff --git a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
+index 63e2173937e5..afafa577aadc 100644
+--- a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
++++ b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
+@@ -4164,13 +4164,7 @@ s32 wl_cfg80211_down(void)
+ 
+ static s32 wl_dongle_probecap(struct wl_priv *wl)
+ {
+-	s32 err = 0;
+-
+-	err = wl_update_wiphybands(wl);
+-	if (unlikely(err))
+-		return err;
+-
+-	return err;
++	return wl_update_wiphybands(wl);
+ }
+ 
+ static void *wl_read_prof(struct wl_priv *wl, s32 item)
+diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
+index e7e72b8d8cde..15a209f5b486 100644
+--- a/drivers/staging/comedi/comedi_fops.c
++++ b/drivers/staging/comedi/comedi_fops.c
+@@ -1291,10 +1291,10 @@ static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg,
+ 		s->lock = file;
+ 	spin_unlock_irqrestore(&s->spin_lock, flags);
+ 
++#if 0
+ 	if (ret < 0)
+ 		return ret;
+ 
+-#if 0
+ 	if (s->lock_f)
+ 		ret = s->lock_f(dev, s);
+ #endif
+diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
+index 1d09bfa2edf5..6637698e119a 100644
+--- a/drivers/staging/comedi/drivers/usbdux.c
++++ b/drivers/staging/comedi/drivers/usbdux.c
+@@ -1935,11 +1935,8 @@ static int usbdux_pwm_cancel(struct comedi_device *dev,
+ 	dev_dbg(&this_usbduxsub->interface->dev,
+ 		"comedi %d: sending pwm off command to the usb device.\n",
+ 		dev->minor);
+-	res = send_dux_commands(this_usbduxsub, SENDPWMOFF);
+-	if (res < 0)
+-		return res;
+ 
+-	return res;
++	return send_dux_commands(this_usbduxsub, SENDPWMOFF);
+ }
+ 
+ static void usbduxsub_pwm_irq(struct urb *urb)
+diff --git a/drivers/staging/tm6000/tm6000-cards.c b/drivers/staging/tm6000/tm6000-cards.c
+index a69c82e11991..9c516cde8047 100644
+--- a/drivers/staging/tm6000/tm6000-cards.c
++++ b/drivers/staging/tm6000/tm6000-cards.c
+@@ -994,11 +994,7 @@ static int fill_board_specific_data(struct tm6000_core *dev)
+ 	if (rc < 0)
+ 		return rc;
+ 
+-	rc = v4l2_device_register(&dev->udev->dev, &dev->v4l2_dev);
+-	if (rc < 0)
+-		return rc;
+-
+-	return rc;
++	return v4l2_device_register(&dev->udev->dev, &dev->v4l2_dev);
+ }
+ 
+ 

commit c4dc4d108ace27cc0c594b67bd6bd945deaac8c2
+Author: Greg Dietsche 
+Date:   Thu Jun 16 07:09:30 2011 +0000
+
+    e1000: remove unnecessary code
+    
+    Compile tested.
+    remove unnecessary code that matches this coccinelle pattern
+            if (...)
+                    return ret;
+            return ret;
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
+index 7501d977d992..1698622af434 100644
+--- a/drivers/net/e1000/e1000_hw.c
++++ b/drivers/net/e1000/e1000_hw.c
+@@ -3080,7 +3080,6 @@ s32 e1000_phy_hw_reset(struct e1000_hw *hw)
+ {
+ 	u32 ctrl, ctrl_ext;
+ 	u32 led_ctrl;
+-	s32 ret_val;
+ 
+ 	e_dbg("e1000_phy_hw_reset");
+ 
+@@ -3126,11 +3125,7 @@ s32 e1000_phy_hw_reset(struct e1000_hw *hw)
+ 	}
+ 
+ 	/* Wait for FW to finish PHY configuration. */
+-	ret_val = e1000_get_phy_cfg_done(hw);
+-	if (ret_val != E1000_SUCCESS)
+-		return ret_val;
+-
+-	return ret_val;
++	return e1000_get_phy_cfg_done(hw);
+ }
+ 
+ /**

commit 0a3f084179731f6755462aa7fec677f8e1f0580a
+Author: Greg Dietsche 
+Date:   Thu Jun 16 07:04:30 2011 +0000
+
+    net: icplus: remove unnecessary code
+    
+    Compile tested.
+    remove unnecessary code that matches this coccinelle pattern
+            if (...)
+                    return ret;
+            return ret;
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
+index 9a09e24c30bc..d4cbc2922b23 100644
+--- a/drivers/net/phy/icplus.c
++++ b/drivers/net/phy/icplus.c
+@@ -109,11 +109,7 @@ static int ip1001_config_init(struct phy_device *phydev)
+ 	value = phy_read(phydev, 16);
+ 	value |= 0x3;
+ 
+-	err = phy_write(phydev, 16, value);
+-	if (err < 0)
+-		return err;
+-
+-	return err;
++	return phy_write(phydev, 16, value);
+ }
+ 
+ static int ip175c_read_status(struct phy_device *phydev)

commit 96bf8bd1c953c3b9d89eac9f13dfdbf5e580060f
+Author: Greg Dietsche 
+Date:   Mon Jun 13 09:40:38 2011 -0500
+
+    savage: remove unnecessary if statement
+    
+    the code always returns ret regardless, so if(ret) check is unnecessary.
+    
+    v2: fixed up the spelling.
+    
+    Signed-off-by: Greg Dietsche 
+    Reviewed-by: Nicolas Kaiser 
+    Signed-off-by: Dave Airlie 
+
+diff --git a/drivers/gpu/drm/savage/savage_bci.c b/drivers/gpu/drm/savage/savage_bci.c
+index bf5f83ea14fe..cb1ee4e0050a 100644
+--- a/drivers/gpu/drm/savage/savage_bci.c
++++ b/drivers/gpu/drm/savage/savage_bci.c
+@@ -647,9 +647,6 @@ int savage_driver_firstopen(struct drm_device *dev)
+ 	ret = drm_addmap(dev, aperture_base, SAVAGE_APERTURE_SIZE,
+ 			 _DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING,
+ 			 &dev_priv->aperture);
+-	if (ret)
+-		return ret;
+-
+ 	return ret;
+ }
+ 

commit 485868266150022a139b74ba4daf0da9ad86c1c0
+Author: Greg Dietsche 
+Date:   Sun Jun 5 19:30:11 2011 -0500
+
+    iwlwifi: remove unecessary if statement
+    
+    the code always returns ret regardless, so if(ret) check is unecessary.
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+index c8f6da83179b..a7c66c4e5f2a 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
++++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+@@ -178,9 +178,6 @@ static int iwlagn_send_rxon_assoc(struct iwl_priv *priv,
+ 
+ 	ret = iwl_send_cmd_pdu_async(priv, ctx->rxon_assoc_cmd,
+ 				     sizeof(rxon_assoc), &rxon_assoc, NULL);
+-	if (ret)
+-		return ret;
+-
+ 	return ret;
+ }
+ 

commit bca6b39979dfe0b2d14a3ca35e2930f5d9c8e3f5
+Author: Greg Dietsche 
+Date:   Mon Jun 6 15:53:01 2011 -0500
+
+    ASoC: wm8940: remove unnecessary if statements
+    
+    removing unnecessary if(ret) checks
+    
+    This updated patch corrects a minor spelling problem in the commit message
+    and resolves two other (similar) issues found in wm8940.c by Jonathan Cameron.
+    
+    Signed-off-by: Greg Dietsche 
+    Acked-by: Jonathan Cameron 
+    Acked-by: Liam Girdwood 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
+index 25580e3ee7c4..056daa0010f9 100644
+--- a/sound/soc/codecs/wm8940.c
++++ b/sound/soc/codecs/wm8940.c
+@@ -297,8 +297,6 @@ static int wm8940_add_widgets(struct snd_soc_codec *codec)
+ 	if (ret)
+ 		goto error_ret;
+ 	ret = snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
+-	if (ret)
+-		goto error_ret;
+ 
+ error_ret:
+ 	return ret;
+@@ -683,8 +681,6 @@ static int wm8940_resume(struct snd_soc_codec *codec)
+ 		}
+ 	}
+ 	ret = wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+-	if (ret)
+-		goto error_ret;
+ 
+ error_ret:
+ 	return ret;
+@@ -730,9 +726,6 @@ static int wm8940_probe(struct snd_soc_codec *codec)
+ 	if (ret)
+ 		return ret;
+ 	ret = wm8940_add_widgets(codec);
+-	if (ret)
+-		return ret;
+-
+ 	return ret;
+ }
+ 

commit 324dd96d2b022595b9fc8f24305b3ab770cc63b9
+Author: Greg Dietsche 
+Date:   Sun Jun 5 14:44:13 2011 +0000
+
+    qlge: remove unecessary if statement
+    
+    the code always returns 'status' regardless, so if(status) check is unecessary.
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c
+index 19b00fa0eaf0..9b67bfea035f 100644
+--- a/drivers/net/qlge/qlge_ethtool.c
++++ b/drivers/net/qlge/qlge_ethtool.c
+@@ -650,8 +650,6 @@ static int ql_set_pauseparam(struct net_device *netdev,
+ 		return -EINVAL;
+ 
+ 	status = ql_mb_set_port_cfg(qdev);
+-	if (status)
+-		return status;
+ 	return status;
+ }
+ 

commit 0c34861e7c66435ab0986509ec20055c402f29d8
+Author: Greg Dietsche 
+Date:   Thu Jun 2 22:24:06 2011 -0500
+
+    iwlegacy: add missing null check
+    
+    lq_sta has other null checks in this function.
+    assuming they are correct, this additional null check
+    should be added too.
+    
+    Incorporating suggestion from Gustavo Padovan.
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-rs.c b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c
+index 24d149909ba3..9b65153bdd01 100644
+--- a/drivers/net/wireless/iwlegacy/iwl-4965-rs.c
++++ b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c
+@@ -2275,6 +2275,9 @@ iwl4965_rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
+ 	if (rate_control_send_low(sta, priv_sta, txrc))
+ 		return;
+ 
++	if (!lq_sta)
++		return;
++
+ 	rate_idx  = lq_sta->last_txrate_idx;
+ 
+ 	if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) {

commit 5c30c76ee616fffb47cbd9810bfd0a99ce4ddb38
+Author: Greg Dietsche 
+Date:   Thu Jun 2 21:06:09 2011 -0500
+
+    iwlegacy: propagate error return value
+    
+    propogate the return value from iwl4965_get_tx_atten_grp instead
+    of implicitly returning -EINVAL in the error case.
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/iwlegacy/iwl-4965.c b/drivers/net/wireless/iwlegacy/iwl-4965.c
+index 06dcee5c51aa..79e7ce643f71 100644
+--- a/drivers/net/wireless/iwlegacy/iwl-4965.c
++++ b/drivers/net/wireless/iwlegacy/iwl-4965.c
+@@ -915,7 +915,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
+ 	if (txatten_grp < 0) {
+ 		IWL_ERR(priv, "Can't find txatten group for channel %d.\n",
+ 			  channel);
+-		return -EINVAL;
++		return txatten_grp;
+ 	}
+ 
+ 	IWL_DEBUG_TXPOWER(priv, "channel %d belongs to txatten group %d\n",

commit 8e638188b2b84ef9bb9ccbb87b92dda9d0a77bcb
+Author: Greg Dietsche 
+Date:   Thu Jun 2 21:06:08 2011 -0500
+
+    iwlegacy: return -EINVAL instead of -1
+    
+    Cleanup the code to return -EINVAL instead of -1
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/iwlegacy/iwl-4965.c b/drivers/net/wireless/iwlegacy/iwl-4965.c
+index ffda05ca20fd..06dcee5c51aa 100644
+--- a/drivers/net/wireless/iwlegacy/iwl-4965.c
++++ b/drivers/net/wireless/iwlegacy/iwl-4965.c
+@@ -496,7 +496,7 @@ static s32 iwl4965_get_tx_atten_grp(u16 channel)
+ 	    channel <= CALIB_IWL_TX_ATTEN_GR4_LCH)
+ 		return CALIB_CH_GROUP_4;
+ 
+-	return -1;
++	return -EINVAL;
+ }
+ 
+ static u32 iwl4965_get_sub_band(const struct iwl_priv *priv, u32 channel)

commit 04975f3fc390974059ad06ac4162db7a6668a18d
+Author: Greg Dietsche 
+Date:   Thu Jun 2 21:06:07 2011 -0500
+
+    iwlegacy: remove unecessary if statement
+    
+    the code always returns ret regardless, so if(ret) check is unecessary.
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/iwlegacy/iwl-4965.c b/drivers/net/wireless/iwlegacy/iwl-4965.c
+index f5433c74b845..ffda05ca20fd 100644
+--- a/drivers/net/wireless/iwlegacy/iwl-4965.c
++++ b/drivers/net/wireless/iwlegacy/iwl-4965.c
+@@ -1185,8 +1185,6 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv,
+ 
+ 	ret = iwl_legacy_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC,
+ 				     sizeof(rxon_assoc), &rxon_assoc, NULL);
+-	if (ret)
+-		return ret;
+ 
+ 	return ret;
+ }

commit e5a042ea30c1772df9ed3dbe1538520e091ad25f
+Author: Greg Dietsche 
+Date:   Thu Jun 2 21:06:06 2011 -0500
+
+    iwlegacy: remove unreachable code
+    
+    return; at the end of the function is unecessary.
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/iwlegacy/iwl-eeprom.c b/drivers/net/wireless/iwlegacy/iwl-eeprom.c
+index cb346d1a9ffa..5bf3f49b74ab 100644
+--- a/drivers/net/wireless/iwlegacy/iwl-eeprom.c
++++ b/drivers/net/wireless/iwlegacy/iwl-eeprom.c
+@@ -316,7 +316,6 @@ static void iwl_legacy_init_band_reference(const struct iwl_priv *priv,
+ 		break;
+ 	default:
+ 		BUG();
+-		return;
+ 	}
+ }
+ 

commit 304b0b572c66bcd89df13e856db16503609c1a24
+Author: Greg Dietsche 
+Date:   Sun May 8 22:51:43 2011 -0500
+
+    usb: fix warning in usbtest module v2
+    
+    On amd64 unsigned is not as wide as pointer and this causes a compiler
+    warning. Switching to unsigned long corrects the problem.
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
+index 7e0bb2af8e63..c5676202d74a 100644
+--- a/drivers/usb/misc/usbtest.c
++++ b/drivers/usb/misc/usbtest.c
+@@ -268,9 +268,9 @@ static inline void simple_fill_buf(struct urb *urb)
+ 	}
+ }
+ 
+-static inline unsigned buffer_offset(void *buf)
++static inline unsigned long buffer_offset(void *buf)
+ {
+-	return (unsigned)buf & (ARCH_KMALLOC_MINALIGN - 1);
++	return (unsigned long)buf & (ARCH_KMALLOC_MINALIGN - 1);
+ }
+ 
+ static int check_guard_bytes(struct usbtest_dev *tdev, struct urb *urb)
+@@ -329,7 +329,7 @@ static int simple_check_buf(struct usbtest_dev *tdev, struct urb *urb)
+ 
+ static void simple_free_urb(struct urb *urb)
+ {
+-	unsigned offset = buffer_offset(urb->transfer_buffer);
++	unsigned long offset = buffer_offset(urb->transfer_buffer);
+ 
+ 	if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)
+ 		usb_free_coherent(

commit d713680f2a7a91864e3722420222952f30a0346e
+Author: Greg Dietsche 
+Date:   Sat Apr 30 15:03:20 2011 -0500
+
+    staging: lirc: fixed coding style
+    
+    fixed a few minor coding style issues reported by checkpatch.pl
+    
+    Signed-off-by: Greg Dietsche 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/lirc/lirc_parallel.c b/drivers/staging/lirc/lirc_parallel.c
+index 832522c290cb..50724c4e2484 100644
+--- a/drivers/staging/lirc/lirc_parallel.c
++++ b/drivers/staging/lirc/lirc_parallel.c
+@@ -568,17 +568,17 @@ static void set_use_dec(void *data)
+ }
+ 
+ static struct lirc_driver driver = {
+-       .name		= LIRC_DRIVER_NAME,
+-       .minor		= -1,
+-       .code_length	= 1,
+-       .sample_rate	= 0,
+-       .data		= NULL,
+-       .add_to_buf	= NULL,
+-       .set_use_inc	= set_use_inc,
+-       .set_use_dec	= set_use_dec,
+-       .fops		= &lirc_fops,
+-       .dev		= NULL,
+-       .owner		= THIS_MODULE,
++	.name		= LIRC_DRIVER_NAME,
++	.minor		= -1,
++	.code_length	= 1,
++	.sample_rate	= 0,
++	.data		= NULL,
++	.add_to_buf	= NULL,
++	.set_use_inc	= set_use_inc,
++	.set_use_dec	= set_use_dec,
++	.fops		= &lirc_fops,
++	.dev		= NULL,
++	.owner		= THIS_MODULE,
+ };
+ 
+ static struct platform_device *lirc_parallel_dev;
+@@ -594,7 +594,7 @@ static int __devexit lirc_parallel_remove(struct platform_device *dev)
+ }
+ 
+ static int lirc_parallel_suspend(struct platform_device *dev,
+-                                 pm_message_t state)
++					pm_message_t state)
+ {
+ 	return 0;
+ }
+@@ -647,7 +647,8 @@ static int __init lirc_parallel_init(void)
+ 
+ 	result = platform_driver_register(&lirc_parallel_driver);
+ 	if (result) {
+-		printk("platform_driver_register returned %d\n", result);
++		printk(KERN_NOTICE "platform_driver_register"
++					" returned %d\n", result);
+ 		return result;
+ 	}
+ 
+diff --git a/drivers/staging/lirc/lirc_sir.c b/drivers/staging/lirc/lirc_sir.c
+index 76be7b8c6209..a7b46f24f24e 100644
+--- a/drivers/staging/lirc/lirc_sir.c
++++ b/drivers/staging/lirc/lirc_sir.c
+@@ -143,9 +143,9 @@ static unsigned int duty_cycle = 50;   /* duty cycle of 50% */
+ #endif
+ #ifndef LIRC_PORT
+ /* for external dongles, default to com1 */
+-#if defined(LIRC_SIR_ACTISYS_ACT200L) || \
+-    defined(LIRC_SIR_ACTISYS_ACT220L) || \
+-    defined(LIRC_SIR_TEKRAM)
++#if defined(LIRC_SIR_ACTISYS_ACT200L)         || \
++	    defined(LIRC_SIR_ACTISYS_ACT220L) || \
++	    defined(LIRC_SIR_TEKRAM)
+ #define LIRC_PORT 0x3f8
+ #else
+ /* onboard sir ports are typically com3 */
+@@ -467,7 +467,7 @@ static const struct file_operations lirc_fops = {
+ 
+ static int set_use_inc(void *data)
+ {
+-       return 0;
++	return 0;
+ }
+ 
+ static void set_use_dec(void *data)
+@@ -475,17 +475,17 @@ static void set_use_dec(void *data)
+ }
+ 
+ static struct lirc_driver driver = {
+-       .name		= LIRC_DRIVER_NAME,
+-       .minor		= -1,
+-       .code_length	= 1,
+-       .sample_rate	= 0,
+-       .data		= NULL,
+-       .add_to_buf	= NULL,
+-       .set_use_inc	= set_use_inc,
+-       .set_use_dec	= set_use_dec,
+-       .fops		= &lirc_fops,
+-       .dev		= NULL,
+-       .owner		= THIS_MODULE,
++	.name		= LIRC_DRIVER_NAME,
++	.minor		= -1,
++	.code_length	= 1,
++	.sample_rate	= 0,
++	.data		= NULL,
++	.add_to_buf	= NULL,
++	.set_use_inc	= set_use_inc,
++	.set_use_dec	= set_use_dec,
++	.fops		= &lirc_fops,
++	.dev		= NULL,
++	.owner		= THIS_MODULE,
+ };
+ 
+ 

\ No newline at end of file diff --git a/detail/22.html b/detail/22.html new file mode 100644 index 0000000..188a43a --- /dev/null +++ b/detail/22.html @@ -0,0 +1,2098 @@ +

Patches contributed by University of Maine System


commit 3143906c2770778d89b730e0342b745d1b4a8303
+Author: Vince Weaver 
+Date:   Thu Aug 1 14:30:43 2019 -0400
+
+    perf.data documentation: Clarify HEADER_SAMPLE_TOPOLOGY format
+    
+    The perf.data file format documentation for HEADER_SAMPLE_TOPOLOGY
+    specifies the layout in a confusing manner that doesn't match the rest
+    of the document.  This patch attempts to describe things consistent with
+    the rest of the file.
+    
+    Signed-off-by: Vince Weaver 
+    Acked-by: Jiri Olsa 
+    Cc: Adrian Hunter 
+    Cc: Alexander Shishkin 
+    Cc: Andi Kleen 
+    Cc: Chong Jiang 
+    Cc: Namhyung Kim 
+    Cc: Peter Zijlstra 
+    Cc: Simon Que 
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.21.1908011425240.14303@macbook-air
+    Signed-off-by: Arnaldo Carvalho de Melo 
+
+diff --git a/tools/perf/Documentation/perf.data-file-format.txt b/tools/perf/Documentation/perf.data-file-format.txt
+index d030c87ed9f5..b0152e1095c5 100644
+--- a/tools/perf/Documentation/perf.data-file-format.txt
++++ b/tools/perf/Documentation/perf.data-file-format.txt
+@@ -298,16 +298,21 @@ Physical memory map and its node assignments.
+ 
+ The format of data in MEM_TOPOLOGY is as follows:
+ 
+-   0 - version          | for future changes
+-   8 - block_size_bytes | /sys/devices/system/memory/block_size_bytes
+-  16 - count            | number of nodes
+-
+-For each node we store map of physical indexes:
+-
+-  32 - node id          | node index
+-  40 - size             | size of bitmap
+-  48 - bitmap           | bitmap of memory indexes that belongs to node
+-                        | /sys/devices/system/node/node/memory
++	u64 version;            // Currently 1
++	u64 block_size_bytes;   // /sys/devices/system/memory/block_size_bytes
++	u64 count;              // number of nodes
++
++struct memory_node {
++        u64 node_id;            // node index
++        u64 size;               // size of bitmap
++        struct bitmap {
++		/* size of bitmap again */
++                u64 bitmapsize;
++		/* bitmap of memory indexes that belongs to node     */
++		/* /sys/devices/system/node/node/memory */
++                u64 entries[(bitmapsize/64)+1];
++        }
++}[count];
+ 
+ The MEM_TOPOLOGY can be displayed with following command:
+ 

commit 2e9a06dda10aea81a17c623f08534dac6735434a
+Author: Vince Weaver 
+Date:   Thu Jul 25 11:57:43 2019 -0400
+
+    perf tools: Fix perf.data documentation units for memory size
+    
+    The perf.data-file-format documentation incorrectly says the
+    HEADER_TOTAL_MEM results are in bytes.  The results are in kilobytes
+    (perf reads the value from /proc/meminfo)
+    
+    Signed-off-by: Vince Weaver 
+    Cc: Alexander Shishkin 
+    Cc: Jiri Olsa 
+    Cc: Namhyung Kim 
+    Cc: Peter Zijlstra 
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.21.1907251155500.22624@macbook-air
+    Signed-off-by: Arnaldo Carvalho de Melo 
+
+diff --git a/tools/perf/Documentation/perf.data-file-format.txt b/tools/perf/Documentation/perf.data-file-format.txt
+index 5f54feb19977..d030c87ed9f5 100644
+--- a/tools/perf/Documentation/perf.data-file-format.txt
++++ b/tools/perf/Documentation/perf.data-file-format.txt
+@@ -126,7 +126,7 @@ vendor,family,model,stepping. For example: GenuineIntel,6,69,1
+ 
+ 	HEADER_TOTAL_MEM = 10,
+ 
+-An uint64_t with the total memory in bytes.
++An uint64_t with the total memory in kilobytes.
+ 
+ 	HEADER_CMDLINE = 11,
+ 

commit 7622236ceb167aa3857395f9bdaf871442aa467e
+Author: Vince Weaver 
+Date:   Tue Jul 23 11:06:01 2019 -0400
+
+    perf header: Fix divide by zero error if f_header.attr_size==0
+    
+    So I have been having lots of trouble with hand-crafted perf.data files
+    causing segfaults and the like, so I have started fuzzing the perf tool.
+    
+    First issue found:
+    
+    If f_header.attr_size is 0 in the perf.data file, then perf will crash
+    with a divide-by-zero error.
+    
+    Committer note:
+    
+    Added a pr_err() to tell the user why the command failed.
+    
+    Signed-off-by: Vince Weaver 
+    Cc: Alexander Shishkin 
+    Cc: Jiri Olsa 
+    Cc: Namhyung Kim 
+    Cc: Peter Zijlstra 
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.21.1907231100440.14532@macbook-air
+    Signed-off-by: Arnaldo Carvalho de Melo 
+
+diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
+index 20111f8da5cb..47877f0f6667 100644
+--- a/tools/perf/util/header.c
++++ b/tools/perf/util/header.c
+@@ -3559,6 +3559,13 @@ int perf_session__read_header(struct perf_session *session)
+ 			   data->file.path);
+ 	}
+ 
++	if (f_header.attr_size == 0) {
++		pr_err("ERROR: The %s file's attr size field is 0 which is unexpected.\n"
++		       "Was the 'perf record' command properly terminated?\n",
++		       data->file.path);
++		return -EINVAL;
++	}
++
+ 	nr_attrs = f_header.attrs.size / f_header.attr_size;
+ 	lseek(fd, f_header.attrs.offset, SEEK_SET);
+ 

commit 33b88e708e7dfa58dc896da2a98f5719d2eb315c
+Author: Vince Weaver 
+Date:   Tue May 2 14:08:50 2017 -0400
+
+    perf/x86: Fix Broadwell-EP DRAM RAPL events
+    
+    It appears as though the Broadwell-EP DRAM units share the special
+    units quirk with Haswell-EP/KNL.
+    
+    Without this patch, you get really high results (a single DRAM using 20W
+    of power).
+    
+    The powercap driver in drivers/powercap/intel_rapl.c already has this
+    change.
+    
+    Signed-off-by: Vince Weaver 
+    Cc: Alexander Shishkin 
+    Cc: Arnaldo Carvalho de Melo 
+    Cc: Jiri Olsa 
+    Cc: Kan Liang 
+    Cc: Linus Torvalds 
+    Cc: Peter Zijlstra 
+    Cc: Stephane Eranian 
+    Cc: Stephane Eranian 
+    Cc: Thomas Gleixner 
+    Cc: linux-kernel@vger.kernel.org
+    Cc: 
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/x86/events/intel/rapl.c b/arch/x86/events/intel/rapl.c
+index 9d05c7e67f60..a45e2114a846 100644
+--- a/arch/x86/events/intel/rapl.c
++++ b/arch/x86/events/intel/rapl.c
+@@ -761,7 +761,7 @@ static const struct x86_cpu_id rapl_cpu_match[] __initconst = {
+ 
+ 	X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_CORE,   hsw_rapl_init),
+ 	X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_GT3E,   hsw_rapl_init),
+-	X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_X,	  hsw_rapl_init),
++	X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_X,	  hsx_rapl_init),
+ 	X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_XEON_D, hsw_rapl_init),
+ 
+ 	X86_RAPL_MODEL_MATCH(INTEL_FAM6_XEON_PHI_KNL, knl_rapl_init),

commit 9cc2617de5b9222abb39cd02e90d57dfea99c6d7
+Author: Vince Weaver 
+Date:   Wed Dec 9 11:34:45 2015 -0500
+
+    perf/x86/amd: Remove l1-dcache-stores event for AMD
+    
+    This is a long standing bug with the l1-dcache-stores generic event on
+    AMD machines.  My perf_event testsuite has been complaining about this
+    for years and I'm finally getting around to trying to get it fixed.
+    
+    The data_cache_refills:system event does not make sense for l1-dcache-stores.
+    Maybe this was a typo and it was meant to be for l1-dcache-store-misses?
+    
+    In any case, the values returned are nowhere near correct for l1-dcache-stores
+    and in fact the umask values for the event have completely changed with
+    fam15h so it makes even less sense than ever.  So just remove it.
+    
+    Signed-off-by: Vince Weaver 
+    Signed-off-by: Peter Zijlstra (Intel) 
+    Cc: Arnaldo Carvalho de Melo 
+    Cc: Jiri Olsa 
+    Cc: Linus Torvalds 
+    Cc: Peter Zijlstra 
+    Cc: Stephane Eranian 
+    Cc: Thomas Gleixner 
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.20.1512091134350.24311@vincent-weaver-1.umelst.maine.edu
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c
+index 1cee5d2d7ece..05e76bf65781 100644
+--- a/arch/x86/kernel/cpu/perf_event_amd.c
++++ b/arch/x86/kernel/cpu/perf_event_amd.c
+@@ -18,7 +18,7 @@ static __initconst const u64 amd_hw_cache_event_ids
+ 		[ C(RESULT_MISS)   ] = 0x0141, /* Data Cache Misses          */
+ 	},
+ 	[ C(OP_WRITE) ] = {
+-		[ C(RESULT_ACCESS) ] = 0x0142, /* Data Cache Refills :system */
++		[ C(RESULT_ACCESS) ] = 0,
+ 		[ C(RESULT_MISS)   ] = 0,
+ 	},
+ 	[ C(OP_PREFETCH) ] = {

commit 1996388e9f4e3444db8273bc08d25164d2967c21
+Author: Vince Weaver 
+Date:   Mon Jul 14 15:33:25 2014 -0400
+
+    perf/x86/intel: Use proper dTLB-load-misses event on IvyBridge
+    
+    This was discussed back in February:
+    
+            https://lkml.org/lkml/2014/2/18/956
+    
+    But I never saw a patch come out of it.
+    
+    On IvyBridge we share the SandyBridge cache event tables, but the
+    dTLB-load-miss event is not compatible.  Patch it up after
+    the fact to the proper DTLB_LOAD_MISSES.DEMAND_LD_MISS_CAUSES_A_WALK
+    
+    Signed-off-by: Vince Weaver 
+    Signed-off-by: Peter Zijlstra 
+    Cc: Arnaldo Carvalho de Melo 
+    Cc: Linus Torvalds 
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.11.1407141528200.17214@vincent-weaver-1.umelst.maine.edu
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
+index 07846d738bdb..c206815b9556 100644
+--- a/arch/x86/kernel/cpu/perf_event_intel.c
++++ b/arch/x86/kernel/cpu/perf_event_intel.c
+@@ -2474,6 +2474,9 @@ __init int intel_pmu_init(void)
+ 	case 62: /* IvyBridge EP */
+ 		memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,
+ 		       sizeof(hw_cache_event_ids));
++		/* dTLB-load-misses on IVB is different than SNB */
++		hw_cache_event_ids[C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = 0x8108; /* DTLB_LOAD_MISSES.DEMAND_LD_MISS_CAUSES_A_WALK */
++
+ 		memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs,
+ 		       sizeof(hw_cache_extra_regs));
+ 

commit cc56d673a9902aecd1c03bea6479eaff6de6967a
+Author: Vince Weaver 
+Date:   Thu Jun 19 14:40:09 2014 -0400
+
+    powerpc, perf: Use common PMU interrupt disabled code
+    
+    Transition to using the new generic PERF_PMU_CAP_NO_INTERRUPT method for
+    failing a sampling event when no PMU interrupt is available.
+    
+    Signed-off-by: Vince Weaver 
+    Signed-off-by: Peter Zijlstra 
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.10.1406191435440.27913@vincent-weaver-1.umelst.maine.edu
+    Cc: Benjamin Herrenschmidt 
+    Cc: Cody P Schafer 
+    Cc: Michael Ellerman 
+    Cc: Paul Mackerras 
+    Cc: linux-kernel@vger.kernel.org
+    Cc: linuxppc-dev@lists.ozlabs.org
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/powerpc/perf/hv-24x7.c b/arch/powerpc/perf/hv-24x7.c
+index e0766b82e165..66d0f179650f 100644
+--- a/arch/powerpc/perf/hv-24x7.c
++++ b/arch/powerpc/perf/hv-24x7.c
+@@ -387,8 +387,7 @@ static int h_24x7_event_init(struct perf_event *event)
+ 	    event->attr.exclude_hv     ||
+ 	    event->attr.exclude_idle   ||
+ 	    event->attr.exclude_host   ||
+-	    event->attr.exclude_guest  ||
+-	    is_sampling_event(event)) /* no sampling */
++	    event->attr.exclude_guest)
+ 		return -EINVAL;
+ 
+ 	/* no branch sampling */
+@@ -513,6 +512,9 @@ static int hv_24x7_init(void)
+ 	if (!hv_page_cache)
+ 		return -ENOMEM;
+ 
++	/* sampling not supported */
++	h_24x7_pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
++
+ 	r = perf_pmu_register(&h_24x7_pmu, h_24x7_pmu.name, -1);
+ 	if (r)
+ 		return r;
+diff --git a/arch/powerpc/perf/hv-gpci.c b/arch/powerpc/perf/hv-gpci.c
+index c9d399a2df82..15fc76c93022 100644
+--- a/arch/powerpc/perf/hv-gpci.c
++++ b/arch/powerpc/perf/hv-gpci.c
+@@ -210,8 +210,7 @@ static int h_gpci_event_init(struct perf_event *event)
+ 	    event->attr.exclude_hv     ||
+ 	    event->attr.exclude_idle   ||
+ 	    event->attr.exclude_host   ||
+-	    event->attr.exclude_guest  ||
+-	    is_sampling_event(event)) /* no sampling */
++	    event->attr.exclude_guest)
+ 		return -EINVAL;
+ 
+ 	/* no branch sampling */
+@@ -284,6 +283,9 @@ static int hv_gpci_init(void)
+ 		return -ENODEV;
+ 	}
+ 
++	/* sampling not supported */
++	h_gpci_pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
++
+ 	r = perf_pmu_register(&h_gpci_pmu, h_gpci_pmu.name, -1);
+ 	if (r)
+ 		return r;

commit a10d60c08cc3bbea9195e2b36440f557373623eb
+Author: Vince Weaver 
+Date:   Sun Jun 15 02:06:15 2014 -0400
+
+    sh, perf: Use common PMU interrupt disabled code
+    
+    Transition to using the new generic PERF_PMU_CAP_NO_INTERRUPT method for
+    failing a sampling event when no PMU interrupt is available.
+    
+    Signed-off-by: Vince Weaver 
+    Signed-off-by: Peter Zijlstra 
+    Cc: Arnaldo Carvalho de Melo 
+    Cc: Paul Mackerras 
+    Cc: linux-sh@vger.kernel.org
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.10.1406150205300.16738@vincent-weaver-1.umelst.maine.edu
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/sh/kernel/perf_event.c b/arch/sh/kernel/perf_event.c
+index 02331672b6db..7cfd7f153966 100644
+--- a/arch/sh/kernel/perf_event.c
++++ b/arch/sh/kernel/perf_event.c
+@@ -128,14 +128,6 @@ static int __hw_perf_event_init(struct perf_event *event)
+ 	if (!sh_pmu_initialized())
+ 		return -ENODEV;
+ 
+-	/*
+-	 * All of the on-chip counters are "limited", in that they have
+-	 * no interrupts, and are therefore unable to do sampling without
+-	 * further work and timer assistance.
+-	 */
+-	if (hwc->sample_period)
+-		return -EINVAL;
+-
+ 	/*
+ 	 * See if we need to reserve the counter.
+ 	 *
+@@ -392,6 +384,13 @@ int register_sh_pmu(struct sh_pmu *_pmu)
+ 
+ 	pr_info("Performance Events: %s support registered\n", _pmu->name);
+ 
++	/*
++	 * All of the on-chip counters are "limited", in that they have
++	 * no interrupts, and are therefore unable to do sampling without
++	 * further work and timer assistance.
++	 */
++	pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
++
+ 	WARN_ON(_pmu->num_events > MAX_HWEVENTS);
+ 
+ 	perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);

commit 97b1198fece06d495270222bcf5fde4c8cb0b5b0
+Author: Vince Weaver 
+Date:   Sun Jun 15 02:05:23 2014 -0400
+
+    s390, perf: Use common PMU interrupt disabled code
+    
+    Transition to using the new generic PERF_PMU_CAP_NO_INTERRUPT method for
+    failing a sampling event when no PMU interrupt is available.
+    
+    Signed-off-by: Vince Weaver 
+    Signed-off-by: Peter Zijlstra 
+    Cc: Heiko Carstens 
+    Cc: Hendrik Brueckner 
+    Cc: Martin Schwidefsky 
+    Cc: Paul Gortmaker 
+    Cc: Thomas Huth 
+    Cc: linux390@de.ibm.com
+    Cc: linux-s390@vger.kernel.org
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.10.1406150204290.16738@vincent-weaver-1.umelst.maine.edu
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c
+index ea75d011a6fc..d3194de7ae1e 100644
+--- a/arch/s390/kernel/perf_cpum_cf.c
++++ b/arch/s390/kernel/perf_cpum_cf.c
+@@ -411,12 +411,6 @@ static int cpumf_pmu_event_init(struct perf_event *event)
+ 	case PERF_TYPE_HARDWARE:
+ 	case PERF_TYPE_HW_CACHE:
+ 	case PERF_TYPE_RAW:
+-		/* The CPU measurement counter facility does not have overflow
+-		 * interrupts to do sampling.  Sampling must be provided by
+-		 * external means, for example, by timers.
+-		 */
+-		if (is_sampling_event(event))
+-			return -ENOENT;
+ 		err = __hw_perf_event_init(event);
+ 		break;
+ 	default:
+@@ -681,6 +675,12 @@ static int __init cpumf_pmu_init(void)
+ 		goto out;
+ 	}
+ 
++	/* The CPU measurement counter facility does not have overflow
++	 * interrupts to do sampling.  Sampling must be provided by
++	 * external means, for example, by timers.
++	 */
++	cpumf_pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
++
+ 	cpumf_pmu.attr_groups = cpumf_cf_event_group();
+ 	rc = perf_pmu_register(&cpumf_pmu, "cpum_cf", PERF_TYPE_RAW);
+ 	if (rc) {

commit 1b92722fafe2003e49ec904f33c0020ade36bd16
+Author: Vince Weaver 
+Date:   Sun Jun 15 02:03:13 2014 -0400
+
+    metag, perf: Use common PMU interrupt disabled code
+    
+    Transition to using the new generic PERF_PMU_CAP_NO_INTERRUPT method for
+    failing a sampling event when no PMU interrupt is available.
+    
+    Signed-off-by: Vince Weaver 
+    Acked-by: James Hogan 
+    Signed-off-by: Peter Zijlstra 
+    Cc: Arnaldo Carvalho de Melo 
+    Cc: Paul Mackerras 
+    Cc: linux-metag@vger.kernel.org
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.10.1406150202050.16738@vincent-weaver-1.umelst.maine.edu
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/metag/kernel/perf/perf_event.c b/arch/metag/kernel/perf/perf_event.c
+index 5cc4d4dcf3cf..02c08737f6aa 100644
+--- a/arch/metag/kernel/perf/perf_event.c
++++ b/arch/metag/kernel/perf/perf_event.c
+@@ -567,16 +567,6 @@ static int _hw_perf_event_init(struct perf_event *event)
+ 	if (mapping == -1)
+ 		return -EINVAL;
+ 
+-	/*
+-	 * Early cores have "limited" counters - they have no overflow
+-	 * interrupts - and so are unable to do sampling without extra work
+-	 * and timer assistance.
+-	 */
+-	if (metag_pmu->max_period == 0) {
+-		if (hwc->sample_period)
+-			return -EINVAL;
+-	}
+-
+ 	/*
+ 	 * Don't assign an index until the event is placed into the hardware.
+ 	 * -1 signifies that we're still deciding where to put it. On SMP
+@@ -866,6 +856,15 @@ static int __init init_hw_perf_events(void)
+ 	pr_info("enabled with %s PMU driver, %d counters available\n",
+ 			metag_pmu->name, metag_pmu->max_events);
+ 
++	/*
++	 * Early cores have "limited" counters - they have no overflow
++	 * interrupts - and so are unable to do sampling without extra work
++	 * and timer assistance.
++	 */
++	if (metag_pmu->max_period == 0) {
++		metag_pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
++	}
++
+ 	/* Initialise the active events and reservation mutex */
+ 	atomic_set(&metag_pmu->active_events, 0);
+ 	mutex_init(&metag_pmu->reserve_mutex);

commit 6e316f9c19a088586fd9ae058f9ea35b271571f3
+Author: Vince Weaver 
+Date:   Sun Jun 15 02:01:58 2014 -0400
+
+    blackfin, perf: Use common PMU interrupt disabled code
+    
+    Transition to using the new generic PERF_PMU_CAP_NO_INTERRUPT method for
+    failing a sampling event when no PMU interrupt is available.
+    
+    Signed-off-by: Vince Weaver 
+    Signed-off-by: Peter Zijlstra 
+    Cc: Arnaldo Carvalho de Melo 
+    Cc: Paul Mackerras 
+    Cc: Steven Miao 
+    Cc: adi-buildroot-devel@lists.sourceforge.net
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.10.1406150200360.16738@vincent-weaver-1.umelst.maine.edu
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/blackfin/kernel/perf_event.c b/arch/blackfin/kernel/perf_event.c
+index 974e55496db3..ea2032013cc2 100644
+--- a/arch/blackfin/kernel/perf_event.c
++++ b/arch/blackfin/kernel/perf_event.c
+@@ -389,14 +389,6 @@ static int bfin_pmu_event_init(struct perf_event *event)
+ 	if (attr->exclude_hv || attr->exclude_idle)
+ 		return -EPERM;
+ 
+-	/*
+-	 * All of the on-chip counters are "limited", in that they have
+-	 * no interrupts, and are therefore unable to do sampling without
+-	 * further work and timer assistance.
+-	 */
+-	if (hwc->sample_period)
+-		return -EINVAL;
+-
+ 	ret = 0;
+ 	switch (attr->type) {
+ 	case PERF_TYPE_RAW:
+@@ -490,6 +482,13 @@ static int __init bfin_pmu_init(void)
+ {
+ 	int ret;
+ 
++	/*
++	 * All of the on-chip counters are "limited", in that they have
++	 * no interrupts, and are therefore unable to do sampling without
++	 * further work and timer assistance.
++	 */
++	pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
++
+ 	ret = perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
+ 	if (!ret)
+ 		perf_cpu_notifier(bfin_pmu_notifier);

commit 2cc9e588b0ff80c209c59a3e369c73e591535ba8
+Author: Vince Weaver 
+Date:   Sun Jun 15 02:00:18 2014 -0400
+
+    arc, perf: Use common PMU interrupt disabled code
+    
+    Transition to using the new generic PERF_PMU_CAP_NO_INTERRUPT method for
+    failing a sampling event when no PMU interrupt is available.
+    
+    Signed-off-by: Vince Weaver 
+    Acked-by: Vineet Gupta 
+    Signed-off-by: Peter Zijlstra 
+    Cc: Arnaldo Carvalho de Melo 
+    Cc: Grant Likely 
+    Cc: Paul Mackerras 
+    Cc: Rob Herring 
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.10.1406150159280.16738@vincent-weaver-1.umelst.maine.edu
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/arc/kernel/perf_event.c b/arch/arc/kernel/perf_event.c
+index 63177e4cb66d..b9a5685a990e 100644
+--- a/arch/arc/kernel/perf_event.c
++++ b/arch/arc/kernel/perf_event.c
+@@ -99,10 +99,6 @@ static int arc_pmu_event_init(struct perf_event *event)
+ 	struct hw_perf_event *hwc = &event->hw;
+ 	int ret;
+ 
+-	/* ARC 700 PMU does not support sampling events */
+-	if (is_sampling_event(event))
+-		return -ENOENT;
+-
+ 	switch (event->attr.type) {
+ 	case PERF_TYPE_HARDWARE:
+ 		if (event->attr.config >= PERF_COUNT_HW_MAX)
+@@ -298,6 +294,9 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
+ 		.read		= arc_pmu_read,
+ 	};
+ 
++	/* ARC 700 PMU does not support sampling events */
++	arc_pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
++
+ 	ret = perf_pmu_register(&arc_pmu->pmu, pdev->name, PERF_TYPE_RAW);
+ 
+ 	return ret;

commit c184c980de30dc5f6fec4b281928aa6743708da9
+Author: Vince Weaver 
+Date:   Fri May 16 17:18:07 2014 -0400
+
+    perf/x86: Use common PMU interrupt disabled code
+    
+    Make the x86 perf code use the new common PMU interrupt disabled code.
+    
+    Typically most x86 machines have working PMU interrupts, although
+    some older p6-class machines had this problem.
+    
+    Signed-off-by: Vince Weaver 
+    Signed-off-by: Peter Zijlstra 
+    Cc: Arnaldo Carvalho de Melo 
+    Cc: Linus Torvalds 
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.10.1405161715560.11099@vincent-weaver-1.umelst.maine.edu
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
+index 32029e35f2b9..2bdfbff8a4f6 100644
+--- a/arch/x86/kernel/cpu/perf_event.c
++++ b/arch/x86/kernel/cpu/perf_event.c
+@@ -303,15 +303,6 @@ int x86_setup_perfctr(struct perf_event *event)
+ 		hwc->sample_period = x86_pmu.max_period;
+ 		hwc->last_period = hwc->sample_period;
+ 		local64_set(&hwc->period_left, hwc->sample_period);
+-	} else {
+-		/*
+-		 * If we have a PMU initialized but no APIC
+-		 * interrupts, we cannot sample hardware
+-		 * events (user-space has to fall back and
+-		 * sample via a hrtimer based software event):
+-		 */
+-		if (!x86_pmu.apic)
+-			return -EOPNOTSUPP;
+ 	}
+ 
+ 	if (attr->type == PERF_TYPE_RAW)
+@@ -1367,6 +1358,15 @@ static void __init pmu_check_apic(void)
+ 	x86_pmu.apic = 0;
+ 	pr_info("no APIC, boot with the \"lapic\" boot parameter to force-enable it.\n");
+ 	pr_info("no hardware sampling interrupt available.\n");
++
++	/*
++	 * If we have a PMU initialized but no APIC
++	 * interrupts, we cannot sample hardware
++	 * events (user-space has to fall back and
++	 * sample via a hrtimer based software event):
++	 */
++	pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
++
+ }
+ 
+ static struct attribute_group x86_pmu_format_group = {

commit edcb4d3c36a6429caa03ddfeab4cbb153c7002b2
+Author: Vince Weaver 
+Date:   Fri May 16 17:15:49 2014 -0400
+
+    perf/ARM: Use common PMU interrupt disabled code
+    
+    Make the ARM perf code use the new common PMU interrupt disabled code.
+    
+    This allows perf to work on ARM machines without a working PMU
+    interrupt (for example, raspberry pi).
+    
+    Acked-by: Will Deacon 
+    Signed-off-by: Vince Weaver 
+    [peterz: applied changes suggested by Will]
+    Signed-off-by: Peter Zijlstra 
+    Cc: Arnaldo Carvalho de Melo 
+    Cc: Grant Likely 
+    Cc: Linus Torvalds 
+    Cc: Paul Mackerras 
+    Cc: Rob Herring 
+    Cc: Russell King 
+    Cc: Will Deacon 
+    Cc: devicetree@vger.kernel.org
+    Cc: linux-arm-kernel@lists.infradead.org
+    Cc: linux-kernel@vger.kernel.org
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.10.1405161712190.11099@vincent-weaver-1.umelst.maine.edu
+    [ Small readability tweaks to the code. ]
+    Signed-off-by: Ingo Molnar 
+    
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
+index a6bc431cde70..4238bcba9d60 100644
+--- a/arch/arm/kernel/perf_event.c
++++ b/arch/arm/kernel/perf_event.c
+@@ -410,7 +410,7 @@ __hw_perf_event_init(struct perf_event *event)
+ 	 */
+ 	hwc->config_base	    |= (unsigned long)mapping;
+ 
+-	if (!hwc->sample_period) {
++	if (!is_sampling_event(event)) {
+ 		/*
+ 		 * For non-sampling runs, limit the sample_period to half
+ 		 * of the counter width. That way, the new counter value
+diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c
+index 51798d7854ac..bbdbffd06cf7 100644
+--- a/arch/arm/kernel/perf_event_cpu.c
++++ b/arch/arm/kernel/perf_event_cpu.c
+@@ -126,8 +126,8 @@ static int cpu_pmu_request_irq(struct arm_pmu *cpu_pmu, irq_handler_t handler)
+ 
+ 	irqs = min(pmu_device->num_resources, num_possible_cpus());
+ 	if (irqs < 1) {
+-		pr_err("no irqs for PMUs defined\n");
+-		return -ENODEV;
++		printk_once("perf/ARM: No irqs for PMU defined, sampling events not supported\n");
++		return 0;
+ 	}
+ 
+ 	irq = platform_get_irq(pmu_device, 0);
+@@ -191,6 +191,10 @@ static void cpu_pmu_init(struct arm_pmu *cpu_pmu)
+ 	/* Ensure the PMU has sane values out of reset. */
+ 	if (cpu_pmu->reset)
+ 		on_each_cpu(cpu_pmu->reset, cpu_pmu, 1);
++
++	/* If no interrupts available, set the corresponding capability flag */
++	if (!platform_get_irq(cpu_pmu->plat_device, 0))
++		cpu_pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
+ }
+ 
+ /*

commit 53b25335dd60981ad608da7890420898a34469a6
+Author: Vince Weaver 
+Date:   Fri May 16 17:12:12 2014 -0400
+
+    perf: Disable sampled events if no PMU interrupt
+    
+    Add common code to generate -ENOTSUPP at event creation time if an
+    architecture attempts to create a sampled event and
+    PERF_PMU_NO_INTERRUPT is set.
+    
+    This adds a new pmu->capabilities flag.  Initially we only support
+    PERF_PMU_NO_INTERRUPT (to indicate a PMU has no support for generating
+    hardware interrupts) but there are other capabilities that can be
+    added later.
+    
+    Signed-off-by: Vince Weaver 
+    Acked-by: Will Deacon 
+    [peterz: rename to PERF_PMU_CAP_* and moved the pmu::capabilities word into a hole]
+    Signed-off-by: Peter Zijlstra 
+    Cc: Arnaldo Carvalho de Melo 
+    Cc: Linus Torvalds 
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.10.1405161708060.11099@vincent-weaver-1.umelst.maine.edu
+    Signed-off-by: Ingo Molnar 
+    
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
+index af6dcf1d9e47..267c8f37012c 100644
+--- a/include/linux/perf_event.h
++++ b/include/linux/perf_event.h
+@@ -166,6 +166,11 @@ struct perf_event;
+  */
+ #define PERF_EVENT_TXN 0x1
+ 
++/**
++ * pmu::capabilities flags
++ */
++#define PERF_PMU_CAP_NO_INTERRUPT		0x01
++
+ /**
+  * struct pmu - generic performance monitoring unit
+  */
+@@ -178,6 +183,11 @@ struct pmu {
+ 	const char			*name;
+ 	int				type;
+ 
++	/*
++	 * various common per-pmu feature flags
++	 */
++	int				capabilities;
++
+ 	int * __percpu			pmu_disable_count;
+ 	struct perf_cpu_context * __percpu pmu_cpu_context;
+ 	int				task_ctx_nr;
+diff --git a/kernel/events/core.c b/kernel/events/core.c
+index a62d142ad498..e9ef0c6646af 100644
+--- a/kernel/events/core.c
++++ b/kernel/events/core.c
+@@ -7120,6 +7120,13 @@ SYSCALL_DEFINE5(perf_event_open,
+ 		}
+ 	}
+ 
++	if (is_sampling_event(event)) {
++		if (event->pmu->capabilities & PERF_PMU_CAP_NO_INTERRUPT) {
++			err = -ENOTSUPP;
++			goto err_alloc;
++		}
++	}
++
+ 	account_event(event);
+ 
+ 	/*

commit e69af4657e7764d03ad555f0b583d9c4217bcefa
+Author: Vince Weaver 
+Date:   Wed Apr 2 00:49:55 2014 -0400
+
+    perf/x86: Enable DRAM RAPL support on Intel Haswell
+    
+    It turns out all Haswell processors (including the Desktop
+    variant)  support RAPL DRAM readings in addition to package,
+    pp0, and pp1.
+    
+    I've confirmed RAPL DRAM readings on my model 60 Haswell
+    desktop.
+    
+    See the 4th-gen-core-family-desktop-vol-2-datasheet.pdf
+    available from the Intel website for confirmation.
+    
+    Signed-off-by: Vince Weaver 
+    Cc: Peter Zijlstra 
+    Cc: Paul Mackerras 
+    Cc: Arnaldo Carvalho de Melo 
+    Cc: Stephane Eranian 
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.10.1404020045290.17889@vincent-weaver-1.um.maine.edu
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/x86/kernel/cpu/perf_event_intel_rapl.c b/arch/x86/kernel/cpu/perf_event_intel_rapl.c
+index 5ad35ad94d0f..3cec947e3b98 100644
+--- a/arch/x86/kernel/cpu/perf_event_intel_rapl.c
++++ b/arch/x86/kernel/cpu/perf_event_intel_rapl.c
+@@ -59,7 +59,7 @@
+ #define INTEL_RAPL_PKG		0x2	/* pseudo-encoding */
+ #define RAPL_IDX_RAM_NRG_STAT	2	/* DRAM */
+ #define INTEL_RAPL_RAM		0x3	/* pseudo-encoding */
+-#define RAPL_IDX_PP1_NRG_STAT	3	/* DRAM */
++#define RAPL_IDX_PP1_NRG_STAT	3	/* gpu */
+ #define INTEL_RAPL_PP1		0x4	/* pseudo-encoding */
+ 
+ /* Clients have PP0, PKG */
+@@ -72,6 +72,12 @@
+ 			 1<config
+  * any other bit is reserved
+@@ -425,6 +431,24 @@ static struct attribute *rapl_events_cln_attr[] = {
+ 	NULL,
+ };
+ 
++static struct attribute *rapl_events_hsw_attr[] = {
++	EVENT_PTR(rapl_cores),
++	EVENT_PTR(rapl_pkg),
++	EVENT_PTR(rapl_gpu),
++	EVENT_PTR(rapl_ram),
++
++	EVENT_PTR(rapl_cores_unit),
++	EVENT_PTR(rapl_pkg_unit),
++	EVENT_PTR(rapl_gpu_unit),
++	EVENT_PTR(rapl_ram_unit),
++
++	EVENT_PTR(rapl_cores_scale),
++	EVENT_PTR(rapl_pkg_scale),
++	EVENT_PTR(rapl_gpu_scale),
++	EVENT_PTR(rapl_ram_scale),
++	NULL,
++};
++
+ static struct attribute_group rapl_pmu_events_group = {
+ 	.name = "events",
+ 	.attrs = NULL, /* patched at runtime */
+@@ -631,11 +655,14 @@ static int __init rapl_pmu_init(void)
+ 	switch (boot_cpu_data.x86_model) {
+ 	case 42: /* Sandy Bridge */
+ 	case 58: /* Ivy Bridge */
+-	case 60: /* Haswell */
+-	case 69: /* Haswell-Celeron */
+ 		rapl_cntr_mask = RAPL_IDX_CLN;
+ 		rapl_pmu_events_group.attrs = rapl_events_cln_attr;
+ 		break;
++	case 60: /* Haswell */
++	case 69: /* Haswell-Celeron */
++		rapl_cntr_mask = RAPL_IDX_HSW;
++		rapl_pmu_events_group.attrs = rapl_events_hsw_attr;
++		break;
+ 	case 45: /* Sandy Bridge-EP */
+ 	case 62: /* IvyTown */
+ 		rapl_cntr_mask = RAPL_IDX_SRV;

commit 14ac652b67fe08b0dca78995a4298aad38345a31
+Author: Vince Weaver 
+Date:   Tue Dec 31 16:54:16 2013 -0500
+
+    ARM: bcm2835: perf_event support for Raspberry-Pi
+    
+    The following patch enables performance counter support on Raspberry-Pi.
+    
+    We have this working on the 2708 based rasp-pi kernels by manually putting
+    the device registration in the platform files.
+    
+    This change does things properly in a device tree.  The boot messages look
+    proper, but my rasp-pi hangs somewhere in USB enabling when running a
+    stock 3.13-rc6 kernel so I have been unable to fully test this change.
+    
+    I also understand that the rasp-pi 1176 pmu support is missing the
+    overflow interrupt.  I'm not sure if that's true of all 2835
+    implementations.  If not, then this patch will need to be changed a bit.
+    
+    Signed-off-by: Vince Weaver 
+    [swarren, fixed DT node sort order]
+    Signed-off-by: Stephen Warren 
+
+diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi
+index b021c96d3ba1..beb8659813b2 100644
+--- a/arch/arm/boot/dts/bcm2835.dtsi
++++ b/arch/arm/boot/dts/bcm2835.dtsi
+@@ -113,6 +113,10 @@ usb {
+ 			reg = <0x7e980000 0x10000>;
+ 			interrupts = <1 9>;
+ 		};
++
++		arm-pmu {
++			compatible = "arm,arm1176-pmu";
++		};
+ 	};
+ 
+ 	clocks {

commit 88fee52e58ca14d8465b614774ed0bf08e1a7790
+Author: Vince Weaver 
+Date:   Mon Dec 30 15:39:45 2013 -0500
+
+    perf list: Fix checking for supported events on older kernels
+    
+    "perf list" listing of hardware events doesn't work on older ARM devices.
+    The change enabling event detection:
+    
+     commit b41f1cec91c37eeea6fdb15effbfa24ea0a5536b
+     Author: Namhyung Kim 
+     Date:   Tue Aug 27 11:41:53 2013 +0900
+    
+         perf list: Skip unsupported events
+    
+    uses the following code in tools/perf/util/parse-events.c:
+    
+            struct perf_event_attr attr = {
+                    .type = type,
+                    .config = config,
+                    .disabled = 1,
+                    .exclude_kernel = 1,
+            };
+    
+    On ARM machines pre-dating the Cortex-A15 this doesn't work, as these
+    machines don't support .exclude_kernel.  So starting with 3.12 "perf
+    list" does not report any hardware events at all on older machines (seen
+    on Rasp-Pi, Pandaboard, Beagleboard, etc).
+    
+    This version of the patch makes changes suggested by Namhyung Kim to
+    check for EACCESS and retry (instead of just dropping the
+    exclude_kernel) so we can properly handle machines where
+    /proc/sys/kernel/perf_event_paranoid is set to 2.
+    
+    Reported-by: Chad Paradis 
+    Signed-off-by: Vince Weaver 
+    Acked-by: Namhyung Kim 
+    Cc: Chad Paradis 
+    Cc: Ingo Molnar 
+    Cc: Namhyung Kim 
+    Cc: Paul Mackerras 
+    Cc: Peter Zijlstra 
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.10.1312301536150.28814@vincent-weaver-1.um.maine.edu
+    Signed-off-by: Arnaldo Carvalho de Melo 
+
+diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
+index d248fca6d7ed..1e15df10a88c 100644
+--- a/tools/perf/util/parse-events.c
++++ b/tools/perf/util/parse-events.c
+@@ -1091,12 +1091,12 @@ int is_valid_tracepoint(const char *event_string)
+ static bool is_event_supported(u8 type, unsigned config)
+ {
+ 	bool ret = true;
++	int open_return;
+ 	struct perf_evsel *evsel;
+ 	struct perf_event_attr attr = {
+ 		.type = type,
+ 		.config = config,
+ 		.disabled = 1,
+-		.exclude_kernel = 1,
+ 	};
+ 	struct {
+ 		struct thread_map map;
+@@ -1108,7 +1108,20 @@ static bool is_event_supported(u8 type, unsigned config)
+ 
+ 	evsel = perf_evsel__new(&attr);
+ 	if (evsel) {
+-		ret = perf_evsel__open(evsel, NULL, &tmap.map) >= 0;
++		open_return = perf_evsel__open(evsel, NULL, &tmap.map);
++		ret = open_return >= 0;
++
++		if (open_return == -EACCES) {
++			/*
++			 * This happens if the paranoid value
++			 * /proc/sys/kernel/perf_event_paranoid is set to 2
++			 * Re-run with exclude_kernel set; we don't do that
++			 * by default as some ARM machines do not support it.
++			 *
++			 */
++			evsel->attr.exclude_kernel = 1;
++			ret = perf_evsel__open(evsel, NULL, &tmap.map) >= 0;
++		}
+ 		perf_evsel__delete(evsel);
+ 	}
+ 

commit 0022cedd4a7d8a87841351e2b018bb6794cf2e67
+Author: Vince Weaver 
+Date:   Fri Nov 15 12:39:45 2013 -0500
+
+    perf/trace: Properly use u64 to hold event_id
+    
+    The 64-bit attr.config value for perf trace events was being copied into
+    an "int" before doing a comparison, meaning the top 32 bits were
+    being truncated.
+    
+    As far as I can tell this didn't cause any errors, but it did mean
+    it was possible to create valid aliases for all the tracepoint ids
+    which I don't think was intended.  (For example, 0xffffffff00000018
+    and 0x18 both enable the same tracepoint).
+    
+    Signed-off-by: Vince Weaver 
+    Signed-off-by: Peter Zijlstra 
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.10.1311151236100.11932@vincent-weaver-1.um.maine.edu
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c
+index 630889f68b1d..e854f420e033 100644
+--- a/kernel/trace/trace_event_perf.c
++++ b/kernel/trace/trace_event_perf.c
+@@ -179,7 +179,7 @@ static int perf_trace_event_init(struct ftrace_event_call *tp_event,
+ int perf_trace_init(struct perf_event *p_event)
+ {
+ 	struct ftrace_event_call *tp_event;
+-	int event_id = p_event->attr.config;
++	u64 event_id = p_event->attr.config;
+ 	int ret = -EINVAL;
+ 
+ 	mutex_lock(&event_mutex);

commit a8e0108cac181a7b141dacaa99ea52efaf9b5f07
+Author: Vince Weaver 
+Date:   Tue Sep 17 14:53:41 2013 -0400
+
+    perf: Fix UAPI export of PERF_EVENT_IOC_ID
+    
+    Without the following patch I have problems compiling code using
+    the new PERF_EVENT_IOC_ID ioctl().  It looks like u64 was used
+    instead of __u64
+    
+    Signed-off-by: Vince Weaver 
+    Acked-by: Peter Zijlstra 
+    Cc: Arnaldo Carvalho de Melo 
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.10.1309171450380.11444@vincent-weaver-1.um.maine.edu
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
+index ca1d90bcb74d..40a1fb807396 100644
+--- a/include/uapi/linux/perf_event.h
++++ b/include/uapi/linux/perf_event.h
+@@ -324,7 +324,7 @@ struct perf_event_attr {
+ #define PERF_EVENT_IOC_PERIOD		_IOW('$', 4, __u64)
+ #define PERF_EVENT_IOC_SET_OUTPUT	_IO ('$', 5)
+ #define PERF_EVENT_IOC_SET_FILTER	_IOW('$', 6, char *)
+-#define PERF_EVENT_IOC_ID		_IOR('$', 7, u64 *)
++#define PERF_EVENT_IOC_ID		_IOR('$', 7, __u64 *)
+ 
+ enum perf_event_ioc_flags {
+ 	PERF_IOC_FLAG_GROUP		= 1U << 0,

commit 274481de6cb69abdb49403ff32abb63c23743413
+Author: Vince Weaver 
+Date:   Fri Aug 23 15:51:03 2013 -0400
+
+    perf: Export struct perf_branch_entry to userspace
+    
+    If PERF_SAMPLE_BRANCH_STACK is enabled then samples are returned
+    with the format { u64 from, to, flags } but the flags layout
+    is not specified.
+    
+    This field has the type struct perf_branch_entry; move this
+    definition into include/uapi/linux/perf_event.h so users can
+    access these fields.
+    
+    This is similar to the existing inclusion of perf_mem_data_src in
+    the include/uapi/linux/perf_event.h file.
+    
+    Signed-off-by: Vince Weaver 
+    Acked-by: Stephane Eranian 
+    Signed-off-by: Peter Zijlstra 
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.10.1308231544420.1889@vincent-weaver-1.um.maine.edu
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
+index c43f6eabad5b..4019d82c3d03 100644
+--- a/include/linux/perf_event.h
++++ b/include/linux/perf_event.h
+@@ -63,30 +63,6 @@ struct perf_raw_record {
+ 	void				*data;
+ };
+ 
+-/*
+- * single taken branch record layout:
+- *
+- *      from: source instruction (may not always be a branch insn)
+- *        to: branch target
+- *   mispred: branch target was mispredicted
+- * predicted: branch target was predicted
+- *
+- * support for mispred, predicted is optional. In case it
+- * is not supported mispred = predicted = 0.
+- *
+- *     in_tx: running in a hardware transaction
+- *     abort: aborting a hardware transaction
+- */
+-struct perf_branch_entry {
+-	__u64	from;
+-	__u64	to;
+-	__u64	mispred:1,  /* target mispredicted */
+-		predicted:1,/* target predicted */
+-		in_tx:1,    /* in transaction */
+-		abort:1,    /* transaction abort */
+-		reserved:60;
+-};
+-
+ /*
+  * branch stack layout:
+  *  nr: number of taken branches stored in entries[]
+diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
+index a77f43af72b8..408b8c730731 100644
+--- a/include/uapi/linux/perf_event.h
++++ b/include/uapi/linux/perf_event.h
+@@ -757,4 +757,28 @@ union perf_mem_data_src {
+ #define PERF_MEM_S(a, s) \
+ 	(((u64)PERF_MEM_##a##_##s) << PERF_MEM_##a##_SHIFT)
+ 
++/*
++ * single taken branch record layout:
++ *
++ *      from: source instruction (may not always be a branch insn)
++ *        to: branch target
++ *   mispred: branch target was mispredicted
++ * predicted: branch target was predicted
++ *
++ * support for mispred, predicted is optional. In case it
++ * is not supported mispred = predicted = 0.
++ *
++ *     in_tx: running in a hardware transaction
++ *     abort: aborting a hardware transaction
++ */
++struct perf_branch_entry {
++	__u64	from;
++	__u64	to;
++	__u64	mispred:1,  /* target mispredicted */
++		predicted:1,/* target predicted */
++		in_tx:1,    /* in transaction */
++		abort:1,    /* transaction abort */
++		reserved:60;
++};
++
+ #endif /* _UAPI_LINUX_PERF_EVENT_H */

commit c9601247f8f3fdc18aed7ed7e490e8dfcd07f122
+Author: Vince Weaver 
+Date:   Fri Aug 2 10:47:34 2013 -0400
+
+    perf/x86: Fix intel QPI uncore event definitions
+    
+    John McCalpin reports that the "drs_data" and "ncb_data" QPI
+    uncore events are missing the "extra bit" and always return zero
+    values unless the bit is properly set.
+    
+    More details from him:
+    
+     According to the Xeon E5-2600 Product Family Uncore Performance
+     Monitoring Guide, Table 2-94, about 1/2 of the QPI Link Layer events
+     (including the ones that "perf" calls "drs_data" and "ncb_data") require
+     that the "extra bit" be set.
+    
+     This was confusing for a while -- a note at the bottom of page 94 says
+     that the "extra bit" is bit 16 of the control register.
+     Unfortunately, Table 2-86 clearly says that bit 16 is reserved and must
+     be zero.  Looking around a bit, I found that bit 21 appears to be the
+     correct "extra bit", and further investigation shows that "perf" actually
+     agrees with me:
+            [root@c560-003.stampede]# cat /sys/bus/event_source/devices/uncore_qpi_0/format/event
+            config:0-7,21
+    
+     So the command
+            # perf -e "uncore_qpi_0/event=drs_data/"
+     Is the same as
+            # perf -e "uncore_qpi_0/event=0x02,umask=0x08/"
+     While it should be
+            # perf -e "uncore_qpi_0/event=0x102,umask=0x08/"
+    
+     I confirmed that this last version gives results that agree with the
+     amount of data that I expected the STREAM benchmark to move across the QPI
+     link in the second (cross-chip) test of the original script.
+    
+    Reported-by: John McCalpin 
+    Signed-off-by: Vince Weaver 
+    Cc: zheng.z.yan@intel.com
+    Cc: Peter Zijlstra 
+    Cc: Arnaldo Carvalho de Melo 
+    Cc: Paul Mackerras 
+    Cc: 
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.10.1308021037280.26119@vincent-weaver-1.um.maine.edu
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
+index cad791dbde95..1fb6c72717bd 100644
+--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c
++++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
+@@ -314,8 +314,8 @@ static struct uncore_event_desc snbep_uncore_imc_events[] = {
+ static struct uncore_event_desc snbep_uncore_qpi_events[] = {
+ 	INTEL_UNCORE_EVENT_DESC(clockticks,       "event=0x14"),
+ 	INTEL_UNCORE_EVENT_DESC(txl_flits_active, "event=0x00,umask=0x06"),
+-	INTEL_UNCORE_EVENT_DESC(drs_data,         "event=0x02,umask=0x08"),
+-	INTEL_UNCORE_EVENT_DESC(ncb_data,         "event=0x03,umask=0x04"),
++	INTEL_UNCORE_EVENT_DESC(drs_data,         "event=0x102,umask=0x08"),
++	INTEL_UNCORE_EVENT_DESC(ncb_data,         "event=0x103,umask=0x04"),
+ 	{ /* end: all zeroes */ },
+ };
+ 

commit 9a6bc14350b130427725f33e371e86212fa56c85
+Author: Vince Weaver 
+Date:   Mon Apr 29 15:52:27 2013 -0400
+
+    perf/x86/intel: Add support for IvyBridge model 58 Uncore
+    
+    According to Intel Vol3b 18.9, the IvyBridge model 58 uncore is
+    the same as that of SandyBridge.
+    
+    I've done some simple tests and with this patch things seem to
+    work on my mac-mini.
+    
+    Signed-off-by: Vince Weaver 
+    Cc: Peter Zijlstra 
+    Cc: Paul Mackerras 
+    Cc: Arnaldo Carvalho de Melo 
+    Cc: Stephane Eranian 
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.02.1304291549320.15827@vincent-weaver-1.um.maine.edu
+    Cc: 
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
+index 0d5ec6d6d335..22ebaa89af10 100644
+--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c
++++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
+@@ -2853,6 +2853,7 @@ static int __init uncore_cpu_init(void)
+ 		msr_uncores = nhm_msr_uncores;
+ 		break;
+ 	case 42: /* Sandy Bridge */
++	case 58: /* Ivy Bridge */
+ 		if (snb_uncore_cbox.num_boxes > max_cores)
+ 			snb_uncore_cbox.num_boxes = max_cores;
+ 		msr_uncores = snb_msr_uncores;

commit 80e217e9ca98a99d6ee95c8f4473b7ebf6d1b8ca
+Author: Vince Weaver 
+Date:   Mon Apr 29 15:49:28 2013 -0400
+
+    perf/x86/intel: Fix typo in perf_event_intel_uncore.c
+    
+    Sandy Bridge was misspelled.  Either that or the Intel marketing
+    names are getting even more obscure.
+    
+    Signed-off-by: Vince Weaver 
+    Cc: Peter Zijlstra 
+    Cc: Paul Mackerras 
+    Cc: Arnaldo Carvalho de Melo 
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.02.1304291546590.15827@vincent-weaver-1.um.maine.edu
+    [ Haha ]
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
+index b43200dbfe7e..0d5ec6d6d335 100644
+--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c
++++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
+@@ -2857,7 +2857,7 @@ static int __init uncore_cpu_init(void)
+ 			snb_uncore_cbox.num_boxes = max_cores;
+ 		msr_uncores = snb_msr_uncores;
+ 		break;
+-	case 45: /* Sandy Birdge-EP */
++	case 45: /* Sandy Bridge-EP */
+ 		if (snbep_uncore_cbox.num_boxes > max_cores)
+ 			snbep_uncore_cbox.num_boxes = max_cores;
+ 		msr_uncores = snbep_msr_uncores;

commit b878e7fb22ea48b0585bbbbef249f7efc6d42748
+Author: Vince Weaver 
+Date:   Tue Jan 8 14:44:25 2013 -0500
+
+    perf: Missing field in PERF_RECORD_SAMPLE documentation
+    
+    While trying to write a perf_event/mmap test for my perf_event
+    test-suite I came across a missing field description in the
+    PERF_RECORD_SAMPLE documentation in perf_event.h
+    
+    Signed-off-by: Vince Weaver 
+    Cc: Ingo Molnar 
+    Cc: Paul Mackerras 
+    Cc: Peter Zijlstra 
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.02.1301081439300.24507@vincent-weaver-1.um.maine.edu
+    Signed-off-by: Arnaldo Carvalho de Melo 
+
+diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
+index 4f63c05d27c9..9fa9c622a7f4 100644
+--- a/include/uapi/linux/perf_event.h
++++ b/include/uapi/linux/perf_event.h
+@@ -579,7 +579,8 @@ enum perf_event_type {
+ 	 *	{ u32			size;
+ 	 *	  char                  data[size];}&& PERF_SAMPLE_RAW
+ 	 *
+-	 *	{ u64 from, to, flags } lbr[nr];} && PERF_SAMPLE_BRANCH_STACK
++	 *	{ u64                   nr;
++	 *        { u64 from, to, flags } lbr[nr];} && PERF_SAMPLE_BRANCH_STACK
+ 	 *
+ 	 * 	{ u64			abi; # enum perf_sample_regs_abi
+ 	 * 	  u64			regs[weight(mask)]; } && PERF_SAMPLE_REGS_USER

commit e4074b3049f99c6ad6e1a33e6d93d8ec0652e2c1
+Author: Vince Weaver 
+Date:   Wed Oct 17 13:05:45 2012 -0400
+
+    perf/x86: Enable overflow on Intel KNC with a custom knc_pmu_handle_irq()
+    
+    Although based on the Intel P6 design, the interrupt mechnanism
+    for KNC more closely resembles the Intel architectural
+    perfmon one.
+    
+    We can't just re-use that code though, because KNC has different
+    MSR numbers for the status and ack registers.
+    
+    In this case we just cut-and paste from perf_event_intel.c
+    with some minor changes, as it looks like it would not be
+    worth the trouble to change that code to be MSR-configurable.
+    
+    Signed-off-by: Vince Weaver 
+    Cc: Peter Zijlstra 
+    Cc: Paul Mackerras 
+    Cc: Arnaldo Carvalho de Melo 
+    Cc: eranian@gmail.com
+    Cc: Meadows Lawrence F 
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.02.1210171304410.23243@vincent-weaver-1.um.maine.edu
+    [ Small stylistic edits. ]
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/x86/kernel/cpu/perf_event_knc.c b/arch/x86/kernel/cpu/perf_event_knc.c
+index f3a2af41552d..4b7731bf23a8 100644
+--- a/arch/x86/kernel/cpu/perf_event_knc.c
++++ b/arch/x86/kernel/cpu/perf_event_knc.c
+@@ -3,6 +3,8 @@
+ #include 
+ #include 
+ 
++#include 
++
+ #include "perf_event.h"
+ 
+ static const u64 knc_perfmon_event_map[] =
+@@ -193,6 +195,80 @@ static void knc_pmu_enable_event(struct perf_event *event)
+ 	(void)wrmsrl_safe(hwc->config_base + hwc->idx, val);
+ }
+ 
++static inline u64 knc_pmu_get_status(void)
++{
++	u64 status;
++
++	rdmsrl(MSR_KNC_IA32_PERF_GLOBAL_STATUS, status);
++
++	return status;
++}
++
++static inline void knc_pmu_ack_status(u64 ack)
++{
++	wrmsrl(MSR_KNC_IA32_PERF_GLOBAL_OVF_CONTROL, ack);
++}
++
++static int knc_pmu_handle_irq(struct pt_regs *regs)
++{
++	struct perf_sample_data data;
++	struct cpu_hw_events *cpuc;
++	int handled = 0;
++	int bit, loops;
++	u64 status;
++
++	cpuc = &__get_cpu_var(cpu_hw_events);
++
++	knc_pmu_disable_all();
++
++	status = knc_pmu_get_status();
++	if (!status) {
++		knc_pmu_enable_all(0);
++		return handled;
++	}
++
++	loops = 0;
++again:
++	knc_pmu_ack_status(status);
++	if (++loops > 100) {
++		WARN_ONCE(1, "perf: irq loop stuck!\n");
++		perf_event_print_debug();
++		goto done;
++	}
++
++	inc_irq_stat(apic_perf_irqs);
++
++	for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) {
++		struct perf_event *event = cpuc->events[bit];
++
++		handled++;
++
++		if (!test_bit(bit, cpuc->active_mask))
++			continue;
++
++		if (!intel_pmu_save_and_restart(event))
++			continue;
++
++		perf_sample_data_init(&data, 0, event->hw.last_period);
++
++		if (perf_event_overflow(event, &data, regs))
++			x86_pmu_stop(event, 0);
++	}
++
++	/*
++	 * Repeat if there is more work to be done:
++	 */
++	status = knc_pmu_get_status();
++	if (status)
++		goto again;
++
++done:
++	knc_pmu_enable_all(0);
++
++	return handled;
++}
++
++
+ PMU_FORMAT_ATTR(event,	"config:0-7"	);
+ PMU_FORMAT_ATTR(umask,	"config:8-15"	);
+ PMU_FORMAT_ATTR(edge,	"config:18"	);
+@@ -210,7 +286,7 @@ static struct attribute *intel_knc_formats_attr[] = {
+ 
+ static __initconst struct x86_pmu knc_pmu = {
+ 	.name			= "knc",
+-	.handle_irq		= x86_pmu_handle_irq,
++	.handle_irq		= knc_pmu_handle_irq,
+ 	.disable_all		= knc_pmu_disable_all,
+ 	.enable_all		= knc_pmu_enable_all,
+ 	.enable			= knc_pmu_enable_event,

commit 7d011962afbaa6e572cd8e0dbb7abf773e166e64
+Author: Vince Weaver 
+Date:   Wed Oct 17 13:04:33 2012 -0400
+
+    perf/x86: Remove cpuc->enable check on Intl KNC event enable/disable
+    
+    x86_pmu.enable() is called from x86_pmu_enable() with
+    cpuc->enabled set to 0.  This means we weren't re-enabling the
+    counters after a context switch.
+    
+    This patch just removes the check, as it should't be necessary
+    (and the equivelent x86_ generic code does not have the checks).
+    
+    The origin of this problem is the KNC driver being based on the
+    P6 one.   The P6 driver also has this issue, but works anyway
+    due to various lucky accidents.
+    
+    Signed-off-by: Vince Weaver 
+    Cc: Peter Zijlstra 
+    Cc: Paul Mackerras 
+    Cc: Arnaldo Carvalho de Melo 
+    Cc: eranian@gmail.com
+    Cc: Meadows
+    Cc: Lawrence F 
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.02.1210171303290.23243@vincent-weaver-1.um.maine.edu
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/x86/kernel/cpu/perf_event_knc.c b/arch/x86/kernel/cpu/perf_event_knc.c
+index 73bcfbdedd50..f3a2af41552d 100644
+--- a/arch/x86/kernel/cpu/perf_event_knc.c
++++ b/arch/x86/kernel/cpu/perf_event_knc.c
+@@ -173,26 +173,22 @@ static void knc_pmu_enable_all(int added)
+ static inline void
+ knc_pmu_disable_event(struct perf_event *event)
+ {
+-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+ 	struct hw_perf_event *hwc = &event->hw;
+ 	u64 val;
+ 
+ 	val = hwc->config;
+-	if (cpuc->enabled)
+-		val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
++	val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
+ 
+ 	(void)wrmsrl_safe(hwc->config_base + hwc->idx, val);
+ }
+ 
+ static void knc_pmu_enable_event(struct perf_event *event)
+ {
+-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+ 	struct hw_perf_event *hwc = &event->hw;
+ 	u64 val;
+ 
+ 	val = hwc->config;
+-	if (cpuc->enabled)
+-		val |= ARCH_PERFMON_EVENTSEL_ENABLE;
++	val |= ARCH_PERFMON_EVENTSEL_ENABLE;
+ 
+ 	(void)wrmsrl_safe(hwc->config_base + hwc->idx, val);
+ }

commit ae5ba47a990a18c869d66916fd72fb334c45cf91
+Author: Vince Weaver 
+Date:   Wed Oct 17 13:03:21 2012 -0400
+
+    perf/x86: Make Intel KNC use full 40-bit width of counters
+    
+    Early versions of Intel KNC chips have a bug where bits above 32
+    were not properly set.  We worked around this by only using the
+    bottom 32 bits (out of 40 that should be available).
+    
+    It turns out this workaround breaks overflow handling.
+    
+    The buggy silicon will in theory never be used in production
+    systems, so remove this workaround so we get proper overflow
+    support.
+    
+    Signed-off-by: Vince Weaver 
+    Cc: Peter Zijlstra 
+    Cc: Paul Mackerras 
+    Cc: Arnaldo Carvalho de Melo 
+    Cc: eranian@gmail.com
+    Cc: Meadows Lawrence F 
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.02.1210171302140.23243@vincent-weaver-1.um.maine.edu
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/x86/kernel/cpu/perf_event_knc.c b/arch/x86/kernel/cpu/perf_event_knc.c
+index 7c46bfdbc373..73bcfbdedd50 100644
+--- a/arch/x86/kernel/cpu/perf_event_knc.c
++++ b/arch/x86/kernel/cpu/perf_event_knc.c
+@@ -226,12 +226,11 @@ static __initconst struct x86_pmu knc_pmu = {
+ 	.event_map		= knc_pmu_event_map,
+ 	.max_events             = ARRAY_SIZE(knc_perfmon_event_map),
+ 	.apic			= 1,
+-	.max_period		= (1ULL << 31) - 1,
++	.max_period		= (1ULL << 39) - 1,
+ 	.version		= 0,
+ 	.num_counters		= 2,
+-	/* in theory 40 bits, early silicon is buggy though */
+-	.cntval_bits		= 32,
+-	.cntval_mask		= (1ULL << 32) - 1,
++	.cntval_bits		= 40,
++	.cntval_mask		= (1ULL << 40) - 1,
+ 	.get_event_constraints	= x86_get_event_constraints,
+ 	.event_constraints	= knc_event_constraints,
+ 	.format_attrs		= intel_knc_formats_attr,

commit 58e9eaf06f5476cb2192ec1d012674ce5e79dd21
+Author: Vince Weaver 
+Date:   Fri Oct 19 17:33:38 2012 -0400
+
+    perf/x86: Remove P6 cpuc->enabled check
+    
+    Between 2.6.33 and 2.6.34 the PMU code was made modular.
+    
+    The x86_pmu_enable() call was extended to disable cpuc->enabled
+    and iterate the counters, enabling one at a time, before calling
+    enable_all() at the end, followed by re-enabling cpuc->enabled.
+    
+    Since cpuc->enabled was set to 0, that change effectively caused
+    the "val |= ARCH_PERFMON_EVENTSEL_ENABLE;" code in p6_pmu_enable_event()
+    and p6_pmu_disable_event() to be dead code that was never called.
+    
+    This change removes this code (which was confusing) and adds some
+    extra commentary to make it more clear what is going on.
+    
+    Signed-off-by: Vince Weaver 
+    Signed-off-by: Peter Zijlstra 
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.02.1210191732000.14552@vincent-weaver-1.um.maine.edu
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c
+index 9582fcbcd8ec..7d0270bd793e 100644
+--- a/arch/x86/kernel/cpu/perf_event_p6.c
++++ b/arch/x86/kernel/cpu/perf_event_p6.c
+@@ -157,25 +157,25 @@ static void p6_pmu_enable_all(int added)
+ static inline void
+ p6_pmu_disable_event(struct perf_event *event)
+ {
+-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+ 	struct hw_perf_event *hwc = &event->hw;
+ 	u64 val = P6_NOP_EVENT;
+ 
+-	if (cpuc->enabled)
+-		val |= ARCH_PERFMON_EVENTSEL_ENABLE;
+-
+ 	(void)wrmsrl_safe(hwc->config_base, val);
+ }
+ 
+ static void p6_pmu_enable_event(struct perf_event *event)
+ {
+-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+ 	struct hw_perf_event *hwc = &event->hw;
+ 	u64 val;
+ 
+ 	val = hwc->config;
+-	if (cpuc->enabled)
+-		val |= ARCH_PERFMON_EVENTSEL_ENABLE;
++
++	/*
++	 * p6 only has a global event enable, set on PerfEvtSel0
++	 * We "disable" events by programming P6_NOP_EVENT
++	 * and we rely on p6_pmu_enable_all() being called
++	 * to actually enable the events.
++	 */
+ 
+ 	(void)wrmsrl_safe(hwc->config_base, val);
+ }

commit e09df47885d767e418902067ce1885aafa3b27db
+Author: Vince Weaver 
+Date:   Fri Oct 19 17:31:54 2012 -0400
+
+    perf/x86: Update/fix generic events on P6 PMU
+    
+    This patch updates the generic events on p6, including some new
+    extended cache events.
+    
+    Values for these events were taken from the equivelant PAPI
+    predefined events.
+    
+    Tested on a Pentium II.
+    
+    Signed-off-by: Vince Weaver 
+    Signed-off-by: Peter Zijlstra 
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.02.1210191730080.14552@vincent-weaver-1.um.maine.edu
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c
+index 0ff5f7fb64cd..9582fcbcd8ec 100644
+--- a/arch/x86/kernel/cpu/perf_event_p6.c
++++ b/arch/x86/kernel/cpu/perf_event_p6.c
+@@ -8,13 +8,106 @@
+  */
+ static const u64 p6_perfmon_event_map[] =
+ {
+-  [PERF_COUNT_HW_CPU_CYCLES]		= 0x0079,
+-  [PERF_COUNT_HW_INSTRUCTIONS]		= 0x00c0,
+-  [PERF_COUNT_HW_CACHE_REFERENCES]	= 0x0f2e,
+-  [PERF_COUNT_HW_CACHE_MISSES]		= 0x012e,
+-  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= 0x00c4,
+-  [PERF_COUNT_HW_BRANCH_MISSES]		= 0x00c5,
+-  [PERF_COUNT_HW_BUS_CYCLES]		= 0x0062,
++  [PERF_COUNT_HW_CPU_CYCLES]		= 0x0079,	/* CPU_CLK_UNHALTED */
++  [PERF_COUNT_HW_INSTRUCTIONS]		= 0x00c0,	/* INST_RETIRED     */
++  [PERF_COUNT_HW_CACHE_REFERENCES]	= 0x0f2e,	/* L2_RQSTS:M:E:S:I */
++  [PERF_COUNT_HW_CACHE_MISSES]		= 0x012e,	/* L2_RQSTS:I       */
++  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= 0x00c4,	/* BR_INST_RETIRED  */
++  [PERF_COUNT_HW_BRANCH_MISSES]		= 0x00c5,	/* BR_MISS_PRED_RETIRED */
++  [PERF_COUNT_HW_BUS_CYCLES]		= 0x0062,	/* BUS_DRDY_CLOCKS  */
++  [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x00a2,	/* RESOURCE_STALLS  */
++
++};
++
++static __initconst u64 p6_hw_cache_event_ids
++				[PERF_COUNT_HW_CACHE_MAX]
++				[PERF_COUNT_HW_CACHE_OP_MAX]
++				[PERF_COUNT_HW_CACHE_RESULT_MAX] =
++{
++ [ C(L1D) ] = {
++	[ C(OP_READ) ] = {
++		[ C(RESULT_ACCESS) ] = 0x0043,	/* DATA_MEM_REFS       */
++                [ C(RESULT_MISS)   ] = 0x0045,	/* DCU_LINES_IN        */
++	},
++	[ C(OP_WRITE) ] = {
++		[ C(RESULT_ACCESS) ] = 0,
++		[ C(RESULT_MISS)   ] = 0x0f29,	/* L2_LD:M:E:S:I       */
++	},
++        [ C(OP_PREFETCH) ] = {
++		[ C(RESULT_ACCESS) ] = 0,
++		[ C(RESULT_MISS)   ] = 0,
++        },
++ },
++ [ C(L1I ) ] = {
++	[ C(OP_READ) ] = {
++		[ C(RESULT_ACCESS) ] = 0x0080,	/* IFU_IFETCH         */
++		[ C(RESULT_MISS)   ] = 0x0f28,	/* L2_IFETCH:M:E:S:I  */
++	},
++	[ C(OP_WRITE) ] = {
++		[ C(RESULT_ACCESS) ] = -1,
++		[ C(RESULT_MISS)   ] = -1,
++	},
++	[ C(OP_PREFETCH) ] = {
++		[ C(RESULT_ACCESS) ] = 0,
++		[ C(RESULT_MISS)   ] = 0,
++	},
++ },
++ [ C(LL  ) ] = {
++	[ C(OP_READ) ] = {
++		[ C(RESULT_ACCESS) ] = 0,
++		[ C(RESULT_MISS)   ] = 0,
++	},
++	[ C(OP_WRITE) ] = {
++		[ C(RESULT_ACCESS) ] = 0,
++		[ C(RESULT_MISS)   ] = 0x0025,	/* L2_M_LINES_INM     */
++	},
++	[ C(OP_PREFETCH) ] = {
++		[ C(RESULT_ACCESS) ] = 0,
++		[ C(RESULT_MISS)   ] = 0,
++	},
++ },
++ [ C(DTLB) ] = {
++	[ C(OP_READ) ] = {
++		[ C(RESULT_ACCESS) ] = 0x0043,	/* DATA_MEM_REFS      */
++		[ C(RESULT_MISS)   ] = 0,
++	},
++	[ C(OP_WRITE) ] = {
++		[ C(RESULT_ACCESS) ] = 0,
++		[ C(RESULT_MISS)   ] = 0,
++	},
++	[ C(OP_PREFETCH) ] = {
++		[ C(RESULT_ACCESS) ] = 0,
++		[ C(RESULT_MISS)   ] = 0,
++	},
++ },
++ [ C(ITLB) ] = {
++	[ C(OP_READ) ] = {
++		[ C(RESULT_ACCESS) ] = 0x0080,	/* IFU_IFETCH         */
++		[ C(RESULT_MISS)   ] = 0x0085,	/* ITLB_MISS          */
++	},
++	[ C(OP_WRITE) ] = {
++		[ C(RESULT_ACCESS) ] = -1,
++		[ C(RESULT_MISS)   ] = -1,
++	},
++	[ C(OP_PREFETCH) ] = {
++		[ C(RESULT_ACCESS) ] = -1,
++		[ C(RESULT_MISS)   ] = -1,
++	},
++ },
++ [ C(BPU ) ] = {
++	[ C(OP_READ) ] = {
++		[ C(RESULT_ACCESS) ] = 0x00c4,	/* BR_INST_RETIRED      */
++		[ C(RESULT_MISS)   ] = 0x00c5,	/* BR_MISS_PRED_RETIRED */
++        },
++	[ C(OP_WRITE) ] = {
++		[ C(RESULT_ACCESS) ] = -1,
++		[ C(RESULT_MISS)   ] = -1,
++	},
++	[ C(OP_PREFETCH) ] = {
++		[ C(RESULT_ACCESS) ] = -1,
++		[ C(RESULT_MISS)   ] = -1,
++	},
++ },
+ };
+ 
+ static u64 p6_pmu_event_map(int hw_event)
+@@ -158,5 +251,9 @@ __init int p6_pmu_init(void)
+ 
+ 	x86_pmu = p6_pmu;
+ 
++	memcpy(hw_cache_event_ids, p6_hw_cache_event_ids,
++		sizeof(hw_cache_event_ids));
++
++
+ 	return 0;
+ }

commit 7991c9ca40d3127dd2ffa3a9c1e33f7d4005495a
+Author: Vince Weaver 
+Date:   Fri Oct 19 17:30:01 2012 -0400
+
+    perf/x86: Fix P6 FP_ASSIST event constraint
+    
+    According to Intel SDM Volume 3B, FP_ASSIST is limited to Counter 1 only,
+    not Counter 0.
+    
+    Tested on a Pentium II.
+    
+    Signed-off-by: Vince Weaver 
+    Signed-off-by: Peter Zijlstra 
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.02.1210191728570.14552@vincent-weaver-1.um.maine.edu
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c
+index e4dd0f7a0453..0ff5f7fb64cd 100644
+--- a/arch/x86/kernel/cpu/perf_event_p6.c
++++ b/arch/x86/kernel/cpu/perf_event_p6.c
+@@ -34,7 +34,7 @@ static struct event_constraint p6_event_constraints[] =
+ {
+ 	INTEL_EVENT_CONSTRAINT(0xc1, 0x1),	/* FLOPS */
+ 	INTEL_EVENT_CONSTRAINT(0x10, 0x1),	/* FP_COMP_OPS_EXE */
+-	INTEL_EVENT_CONSTRAINT(0x11, 0x1),	/* FP_ASSIST */
++	INTEL_EVENT_CONSTRAINT(0x11, 0x2),	/* FP_ASSIST */
+ 	INTEL_EVENT_CONSTRAINT(0x12, 0x2),	/* MUL */
+ 	INTEL_EVENT_CONSTRAINT(0x13, 0x2),	/* DIV */
+ 	INTEL_EVENT_CONSTRAINT(0x14, 0x1),	/* CYCLES_DIV_BUSY */

commit e717bf4e4fe8adc519f25c4ff93ee50ed0a36710
+Author: Vince Weaver 
+Date:   Wed Sep 26 14:12:52 2012 -0400
+
+    perf/x86: Add support for Intel Xeon-Phi Knights Corner PMU
+    
+    The following patch adds perf_event support for the Xeon-Phi
+    PMU, as documented in the "Intel Xeon Phi Coprocessor (codename:
+    Knights Corner) Performance Monitoring Units" manual.
+    
+    Even though it is a co-processor, a Phi runs a full Linux
+    environment and can support performance counters.
+    
+    This is just barebones support, it does not add support for
+    interesting new features such as the SPFLT intruction that
+    allows starting/stopping events without entering the kernel.
+    
+    The PMU internally is just like that of an original Pentium, but
+    a "P6-like" MSR interface is provided.  The interface is
+    different enough from a real P6 that it's not easy (or
+    practical) to re-use the code in  perf_event_p6.c
+    
+    Acked-by: Lawrence F Meadows 
+    Acked-by: Cyrill Gorcunov 
+    Signed-off-by: Vince Weaver 
+    Acked-by: Peter Zijlstra 
+    Cc: Paul Mackerras 
+    Cc: Arnaldo Carvalho de Melo 
+    Cc: eranian@gmail.com
+    Cc: Lawrence F 
+    Link: http://lkml.kernel.org/r/alpine.DEB.2.02.1209261405320.8398@vincent-weaver-1.um.maine.edu
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
+index 957ec87385af..07f96cb5cdb9 100644
+--- a/arch/x86/include/asm/msr-index.h
++++ b/arch/x86/include/asm/msr-index.h
+@@ -121,6 +121,11 @@
+ #define MSR_P6_EVNTSEL0			0x00000186
+ #define MSR_P6_EVNTSEL1			0x00000187
+ 
++#define MSR_KNC_PERFCTR0               0x00000020
++#define MSR_KNC_PERFCTR1               0x00000021
++#define MSR_KNC_EVNTSEL0               0x00000028
++#define MSR_KNC_EVNTSEL1               0x00000029
++
+ /* AMD64 MSRs. Not complete. See the architecture manual for a more
+    complete list. */
+ 
+diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
+index d30a6a9a0121..a0e067d3d96c 100644
+--- a/arch/x86/kernel/cpu/Makefile
++++ b/arch/x86/kernel/cpu/Makefile
+@@ -32,7 +32,7 @@ obj-$(CONFIG_PERF_EVENTS)		+= perf_event.o
+ 
+ ifdef CONFIG_PERF_EVENTS
+ obj-$(CONFIG_CPU_SUP_AMD)		+= perf_event_amd.o
+-obj-$(CONFIG_CPU_SUP_INTEL)		+= perf_event_p6.o perf_event_p4.o
++obj-$(CONFIG_CPU_SUP_INTEL)		+= perf_event_p6.o perf_event_knc.o perf_event_p4.o
+ obj-$(CONFIG_CPU_SUP_INTEL)		+= perf_event_intel_lbr.o perf_event_intel_ds.o perf_event_intel.o
+ obj-$(CONFIG_CPU_SUP_INTEL)		+= perf_event_intel_uncore.o
+ endif
+diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
+index 8b6defe7eefc..271d25700297 100644
+--- a/arch/x86/kernel/cpu/perf_event.h
++++ b/arch/x86/kernel/cpu/perf_event.h
+@@ -626,6 +626,8 @@ int p4_pmu_init(void);
+ 
+ int p6_pmu_init(void);
+ 
++int knc_pmu_init(void);
++
+ #else /* CONFIG_CPU_SUP_INTEL */
+ 
+ static inline void reserve_ds_buffers(void)
+diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
+index 6bca492b8547..324bb523d9d9 100644
+--- a/arch/x86/kernel/cpu/perf_event_intel.c
++++ b/arch/x86/kernel/cpu/perf_event_intel.c
+@@ -1906,6 +1906,8 @@ __init int intel_pmu_init(void)
+ 		switch (boot_cpu_data.x86) {
+ 		case 0x6:
+ 			return p6_pmu_init();
++		case 0xb:
++			return knc_pmu_init();
+ 		case 0xf:
+ 			return p4_pmu_init();
+ 		}
+diff --git a/arch/x86/kernel/cpu/perf_event_knc.c b/arch/x86/kernel/cpu/perf_event_knc.c
+new file mode 100644
+index 000000000000..7c46bfdbc373
+--- /dev/null
++++ b/arch/x86/kernel/cpu/perf_event_knc.c
+@@ -0,0 +1,248 @@
++/* Driver for Intel Xeon Phi "Knights Corner" PMU */
++
++#include 
++#include 
++
++#include "perf_event.h"
++
++static const u64 knc_perfmon_event_map[] =
++{
++  [PERF_COUNT_HW_CPU_CYCLES]		= 0x002a,
++  [PERF_COUNT_HW_INSTRUCTIONS]		= 0x0016,
++  [PERF_COUNT_HW_CACHE_REFERENCES]	= 0x0028,
++  [PERF_COUNT_HW_CACHE_MISSES]		= 0x0029,
++  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= 0x0012,
++  [PERF_COUNT_HW_BRANCH_MISSES]		= 0x002b,
++};
++
++static __initconst u64 knc_hw_cache_event_ids
++				[PERF_COUNT_HW_CACHE_MAX]
++				[PERF_COUNT_HW_CACHE_OP_MAX]
++				[PERF_COUNT_HW_CACHE_RESULT_MAX] =
++{
++ [ C(L1D) ] = {
++	[ C(OP_READ) ] = {
++		/* On Xeon Phi event "0" is a valid DATA_READ          */
++		/*   (L1 Data Cache Reads) Instruction.                */
++		/* We code this as ARCH_PERFMON_EVENTSEL_INT as this   */
++		/* bit will always be set in x86_pmu_hw_config().      */
++		[ C(RESULT_ACCESS) ] = ARCH_PERFMON_EVENTSEL_INT,
++						/* DATA_READ           */
++		[ C(RESULT_MISS)   ] = 0x0003,	/* DATA_READ_MISS      */
++	},
++	[ C(OP_WRITE) ] = {
++		[ C(RESULT_ACCESS) ] = 0x0001,	/* DATA_WRITE          */
++		[ C(RESULT_MISS)   ] = 0x0004,	/* DATA_WRITE_MISS     */
++	},
++	[ C(OP_PREFETCH) ] = {
++		[ C(RESULT_ACCESS) ] = 0x0011,	/* L1_DATA_PF1         */
++		[ C(RESULT_MISS)   ] = 0x001c,	/* L1_DATA_PF1_MISS    */
++	},
++ },
++ [ C(L1I ) ] = {
++	[ C(OP_READ) ] = {
++		[ C(RESULT_ACCESS) ] = 0x000c,	/* CODE_READ          */
++		[ C(RESULT_MISS)   ] = 0x000e,	/* CODE_CACHE_MISS    */
++	},
++	[ C(OP_WRITE) ] = {
++		[ C(RESULT_ACCESS) ] = -1,
++		[ C(RESULT_MISS)   ] = -1,
++	},
++	[ C(OP_PREFETCH) ] = {
++		[ C(RESULT_ACCESS) ] = 0x0,
++		[ C(RESULT_MISS)   ] = 0x0,
++	},
++ },
++ [ C(LL  ) ] = {
++	[ C(OP_READ) ] = {
++		[ C(RESULT_ACCESS) ] = 0,
++		[ C(RESULT_MISS)   ] = 0x10cb,	/* L2_READ_MISS */
++	},
++	[ C(OP_WRITE) ] = {
++		[ C(RESULT_ACCESS) ] = 0x10cc,	/* L2_WRITE_HIT */
++		[ C(RESULT_MISS)   ] = 0,
++	},
++	[ C(OP_PREFETCH) ] = {
++		[ C(RESULT_ACCESS) ] = 0x10fc,	/* L2_DATA_PF2      */
++		[ C(RESULT_MISS)   ] = 0x10fe,	/* L2_DATA_PF2_MISS */
++	},
++ },
++ [ C(DTLB) ] = {
++	[ C(OP_READ) ] = {
++		[ C(RESULT_ACCESS) ] = ARCH_PERFMON_EVENTSEL_INT,
++						/* DATA_READ */
++						/* see note on L1 OP_READ */
++		[ C(RESULT_MISS)   ] = 0x0002,	/* DATA_PAGE_WALK */
++	},
++	[ C(OP_WRITE) ] = {
++		[ C(RESULT_ACCESS) ] = 0x0001,	/* DATA_WRITE */
++		[ C(RESULT_MISS)   ] = 0x0002,	/* DATA_PAGE_WALK */
++	},
++	[ C(OP_PREFETCH) ] = {
++		[ C(RESULT_ACCESS) ] = 0x0,
++		[ C(RESULT_MISS)   ] = 0x0,
++	},
++ },
++ [ C(ITLB) ] = {
++	[ C(OP_READ) ] = {
++		[ C(RESULT_ACCESS) ] = 0x000c,	/* CODE_READ */
++		[ C(RESULT_MISS)   ] = 0x000d,	/* CODE_PAGE_WALK */
++	},
++	[ C(OP_WRITE) ] = {
++		[ C(RESULT_ACCESS) ] = -1,
++		[ C(RESULT_MISS)   ] = -1,
++	},
++	[ C(OP_PREFETCH) ] = {
++		[ C(RESULT_ACCESS) ] = -1,
++		[ C(RESULT_MISS)   ] = -1,
++	},
++ },
++ [ C(BPU ) ] = {
++	[ C(OP_READ) ] = {
++		[ C(RESULT_ACCESS) ] = 0x0012,	/* BRANCHES */
++		[ C(RESULT_MISS)   ] = 0x002b,	/* BRANCHES_MISPREDICTED */
++	},
++	[ C(OP_WRITE) ] = {
++		[ C(RESULT_ACCESS) ] = -1,
++		[ C(RESULT_MISS)   ] = -1,
++	},
++	[ C(OP_PREFETCH) ] = {
++		[ C(RESULT_ACCESS) ] = -1,
++		[ C(RESULT_MISS)   ] = -1,
++	},
++ },
++};
++
++
++static u64 knc_pmu_event_map(int hw_event)
++{
++	return knc_perfmon_event_map[hw_event];
++}
++
++static struct event_constraint knc_event_constraints[] =
++{
++	INTEL_EVENT_CONSTRAINT(0xc3, 0x1),	/* HWP_L2HIT */
++	INTEL_EVENT_CONSTRAINT(0xc4, 0x1),	/* HWP_L2MISS */
++	INTEL_EVENT_CONSTRAINT(0xc8, 0x1),	/* L2_READ_HIT_E */
++	INTEL_EVENT_CONSTRAINT(0xc9, 0x1),	/* L2_READ_HIT_M */
++	INTEL_EVENT_CONSTRAINT(0xca, 0x1),	/* L2_READ_HIT_S */
++	INTEL_EVENT_CONSTRAINT(0xcb, 0x1),	/* L2_READ_MISS */
++	INTEL_EVENT_CONSTRAINT(0xcc, 0x1),	/* L2_WRITE_HIT */
++	INTEL_EVENT_CONSTRAINT(0xce, 0x1),	/* L2_STRONGLY_ORDERED_STREAMING_VSTORES_MISS */
++	INTEL_EVENT_CONSTRAINT(0xcf, 0x1),	/* L2_WEAKLY_ORDERED_STREAMING_VSTORE_MISS */
++	INTEL_EVENT_CONSTRAINT(0xd7, 0x1),	/* L2_VICTIM_REQ_WITH_DATA */
++	INTEL_EVENT_CONSTRAINT(0xe3, 0x1),	/* SNP_HITM_BUNIT */
++	INTEL_EVENT_CONSTRAINT(0xe6, 0x1),	/* SNP_HIT_L2 */
++	INTEL_EVENT_CONSTRAINT(0xe7, 0x1),	/* SNP_HITM_L2 */
++	INTEL_EVENT_CONSTRAINT(0xf1, 0x1),	/* L2_DATA_READ_MISS_CACHE_FILL */
++	INTEL_EVENT_CONSTRAINT(0xf2, 0x1),	/* L2_DATA_WRITE_MISS_CACHE_FILL */
++	INTEL_EVENT_CONSTRAINT(0xf6, 0x1),	/* L2_DATA_READ_MISS_MEM_FILL */
++	INTEL_EVENT_CONSTRAINT(0xf7, 0x1),	/* L2_DATA_WRITE_MISS_MEM_FILL */
++	INTEL_EVENT_CONSTRAINT(0xfc, 0x1),	/* L2_DATA_PF2 */
++	INTEL_EVENT_CONSTRAINT(0xfd, 0x1),	/* L2_DATA_PF2_DROP */
++	INTEL_EVENT_CONSTRAINT(0xfe, 0x1),	/* L2_DATA_PF2_MISS */
++	INTEL_EVENT_CONSTRAINT(0xff, 0x1),	/* L2_DATA_HIT_INFLIGHT_PF2 */
++	EVENT_CONSTRAINT_END
++};
++
++#define MSR_KNC_IA32_PERF_GLOBAL_STATUS		0x0000002d
++#define MSR_KNC_IA32_PERF_GLOBAL_OVF_CONTROL	0x0000002e
++#define MSR_KNC_IA32_PERF_GLOBAL_CTRL		0x0000002f
++
++#define KNC_ENABLE_COUNTER0			0x00000001
++#define KNC_ENABLE_COUNTER1			0x00000002
++
++static void knc_pmu_disable_all(void)
++{
++	u64 val;
++
++	rdmsrl(MSR_KNC_IA32_PERF_GLOBAL_CTRL, val);
++	val &= ~(KNC_ENABLE_COUNTER0|KNC_ENABLE_COUNTER1);
++	wrmsrl(MSR_KNC_IA32_PERF_GLOBAL_CTRL, val);
++}
++
++static void knc_pmu_enable_all(int added)
++{
++	u64 val;
++
++	rdmsrl(MSR_KNC_IA32_PERF_GLOBAL_CTRL, val);
++	val |= (KNC_ENABLE_COUNTER0|KNC_ENABLE_COUNTER1);
++	wrmsrl(MSR_KNC_IA32_PERF_GLOBAL_CTRL, val);
++}
++
++static inline void
++knc_pmu_disable_event(struct perf_event *event)
++{
++	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
++	struct hw_perf_event *hwc = &event->hw;
++	u64 val;
++
++	val = hwc->config;
++	if (cpuc->enabled)
++		val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
++
++	(void)wrmsrl_safe(hwc->config_base + hwc->idx, val);
++}
++
++static void knc_pmu_enable_event(struct perf_event *event)
++{
++	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
++	struct hw_perf_event *hwc = &event->hw;
++	u64 val;
++
++	val = hwc->config;
++	if (cpuc->enabled)
++		val |= ARCH_PERFMON_EVENTSEL_ENABLE;
++
++	(void)wrmsrl_safe(hwc->config_base + hwc->idx, val);
++}
++
++PMU_FORMAT_ATTR(event,	"config:0-7"	);
++PMU_FORMAT_ATTR(umask,	"config:8-15"	);
++PMU_FORMAT_ATTR(edge,	"config:18"	);
++PMU_FORMAT_ATTR(inv,	"config:23"	);
++PMU_FORMAT_ATTR(cmask,	"config:24-31"	);
++
++static struct attribute *intel_knc_formats_attr[] = {
++	&format_attr_event.attr,
++	&format_attr_umask.attr,
++	&format_attr_edge.attr,
++	&format_attr_inv.attr,
++	&format_attr_cmask.attr,
++	NULL,
++};
++
++static __initconst struct x86_pmu knc_pmu = {
++	.name			= "knc",
++	.handle_irq		= x86_pmu_handle_irq,
++	.disable_all		= knc_pmu_disable_all,
++	.enable_all		= knc_pmu_enable_all,
++	.enable			= knc_pmu_enable_event,
++	.disable		= knc_pmu_disable_event,
++	.hw_config		= x86_pmu_hw_config,
++	.schedule_events	= x86_schedule_events,
++	.eventsel		= MSR_KNC_EVNTSEL0,
++	.perfctr		= MSR_KNC_PERFCTR0,
++	.event_map		= knc_pmu_event_map,
++	.max_events             = ARRAY_SIZE(knc_perfmon_event_map),
++	.apic			= 1,
++	.max_period		= (1ULL << 31) - 1,
++	.version		= 0,
++	.num_counters		= 2,
++	/* in theory 40 bits, early silicon is buggy though */
++	.cntval_bits		= 32,
++	.cntval_mask		= (1ULL << 32) - 1,
++	.get_event_constraints	= x86_get_event_constraints,
++	.event_constraints	= knc_event_constraints,
++	.format_attrs		= intel_knc_formats_attr,
++};
++
++__init int knc_pmu_init(void)
++{
++	x86_pmu = knc_pmu;
++
++	memcpy(hw_cache_event_ids, knc_hw_cache_event_ids, 
++		sizeof(hw_cache_event_ids));
++
++	return 0;
++}
+diff --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c
+index 966512b2cacf..2e8caf03f593 100644
+--- a/arch/x86/kernel/cpu/perfctr-watchdog.c
++++ b/arch/x86/kernel/cpu/perfctr-watchdog.c
+@@ -56,6 +56,8 @@ static inline unsigned int nmi_perfctr_msr_to_bit(unsigned int msr)
+ 		switch (boot_cpu_data.x86) {
+ 		case 6:
+ 			return msr - MSR_P6_PERFCTR0;
++		case 11:
++			return msr - MSR_KNC_PERFCTR0;
+ 		case 15:
+ 			return msr - MSR_P4_BPU_PERFCTR0;
+ 		}
+@@ -82,6 +84,8 @@ static inline unsigned int nmi_evntsel_msr_to_bit(unsigned int msr)
+ 		switch (boot_cpu_data.x86) {
+ 		case 6:
+ 			return msr - MSR_P6_EVNTSEL0;
++		case 11:
++			return msr - MSR_KNC_EVNTSEL0;
+ 		case 15:
+ 			return msr - MSR_P4_BSU_ESCR0;
+ 		}

\ No newline at end of file diff --git a/detail/24.html b/detail/24.html new file mode 100644 index 0000000..4026988 --- /dev/null +++ b/detail/24.html @@ -0,0 +1,3489 @@ +

Patches contributed by Columbia University


commit 3783e1721b650588938d28e4a084a1c9748361c8
+Author: Kele Huang 
+Date:   Sat Dec 24 01:02:33 2022 -0500
+
+    mm: fix comment of page table counter
+    
+    Commit af5b0f6a09e42 ("mm: consolidate page table accounting")
+    consolidates page table accounting to a single counter in struct mm_struct
+    {} as mm->pgtables_bytes.  So the meanning of this counter should be the
+    size of all page tables now.
+    
+    Link: https://lkml.kernel.org/r/20221224060233.417827-1-kele.huang@columbia.edu
+    Signed-off-by: Kele Huang 
+    Cc: Arnd Bergmann 
+    Cc: Colin Cross 
+    Cc: David Hildenbrand 
+    Cc: Hugh Dickins 
+    Cc: Liam Howlett 
+    Cc: Matthew Wilcox (Oracle) 
+    Cc: Pasha Tatashin 
+    Cc: Peter Xu 
+    Cc: Vlastimil Babka 
+    Cc: Yu Zhao 
+    Signed-off-by: Andrew Morton 
+
+diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
+index 1118e381fcdc..10b6eb311ede 100644
+--- a/include/linux/mm_types.h
++++ b/include/linux/mm_types.h
+@@ -647,7 +647,7 @@ struct mm_struct {
+ 		atomic_t mm_count;
+ 
+ #ifdef CONFIG_MMU
+-		atomic_long_t pgtables_bytes;	/* PTE page table pages */
++		atomic_long_t pgtables_bytes;	/* size of all page tables */
+ #endif
+ 		int map_count;			/* number of VMAs */
+ 

commit c51acdb78f92719127995c0fe41108df0552edc3
+Author: Tal Zussman 
+Date:   Fri Dec 31 02:57:50 2021 -0500
+
+    fs: Remove FIXME comment in generic_write_checks()
+    
+    This patch removes an unnecessary comment that had to do with block special
+    files from `generic_write_checks()`.
+    
+    The comment, originally added in Linux v2.4.14.9, was to clarify that we only
+    set `pos` to the file size when the file was opened with `O_APPEND` if the file
+    wasn't a block special file. Prior to Linux v2.4, block special files had a
+    different `write()` function which was unified into a generic `write()` function
+    in Linux v2.4. This generic `write()` function called `generic_write_checks()`.
+    For more details, see this earlier conversation:
+    https://lore.kernel.org/linux-fsdevel/Yc4Czk5A+p5p2Y4W@mit.edu/
+    
+    Currently, block special devices have their own `write_iter()` function and no
+    longer share the same `generic_write_checks()`, therefore rendering the comment
+    irrelevant.
+    
+    Signed-off-by: Tal Zussman 
+    Co-authored-by: Xijiao Li 
+    Co-authored-by: Hans Montero 
+    Suggested-by: Theodore Ts'o 
+    Signed-off-by: Al Viro 
+
+diff --git a/fs/read_write.c b/fs/read_write.c
+index 0074afa7ecb3..0173dc7183c9 100644
+--- a/fs/read_write.c
++++ b/fs/read_write.c
+@@ -1637,7 +1637,6 @@ ssize_t generic_write_checks(struct kiocb *iocb, struct iov_iter *from)
+ 	if (!iov_iter_count(from))
+ 		return 0;
+ 
+-	/* FIXME: this is for backwards compatibility with 2.4 */
+ 	if (iocb->ki_flags & IOCB_APPEND)
+ 		iocb->ki_pos = i_size_read(inode);
+ 

commit b19a888c1e9bdf12e0d8dd9aeb887ca7de91c8a5
+Author: Tal Zussman 
+Date:   Thu Nov 12 19:51:56 2020 -0500
+
+    sched/core: Fix typos in comments
+    
+    Signed-off-by: Tal Zussman 
+    Signed-off-by: Peter Zijlstra (Intel) 
+    Link: https://lkml.kernel.org/r/20201113005156.GA8408@charmander
+
+diff --git a/kernel/sched/core.c b/kernel/sched/core.c
+index 28d541a3c74d..a9e6d630eb83 100644
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -97,7 +97,7 @@ int sysctl_sched_rt_runtime = 950000;
+  *
+  * Normal scheduling state is serialized by rq->lock. __schedule() takes the
+  * local CPU's rq->lock, it optionally removes the task from the runqueue and
+- * always looks at the local rq data structures to find the most elegible task
++ * always looks at the local rq data structures to find the most eligible task
+  * to run next.
+  *
+  * Task enqueue is also under rq->lock, possibly taken from another CPU.
+@@ -518,7 +518,7 @@ static bool __wake_q_add(struct wake_q_head *head, struct task_struct *task)
+ 
+ 	/*
+ 	 * Atomically grab the task, if ->wake_q is !nil already it means
+-	 * its already queued (either by us or someone else) and will get the
++	 * it's already queued (either by us or someone else) and will get the
+ 	 * wakeup due to that.
+ 	 *
+ 	 * In order to ensure that a pending wakeup will observe our pending
+@@ -769,7 +769,7 @@ bool sched_can_stop_tick(struct rq *rq)
+ 		return false;
+ 
+ 	/*
+-	 * If there are more than one RR tasks, we need the tick to effect the
++	 * If there are more than one RR tasks, we need the tick to affect the
+ 	 * actual RR behaviour.
+ 	 */
+ 	if (rq->rt.rr_nr_running) {
+@@ -1187,14 +1187,14 @@ static inline void uclamp_rq_dec_id(struct rq *rq, struct task_struct *p,
+ 	 * accounting was performed at enqueue time and we can just return
+ 	 * here.
+ 	 *
+-	 * Need to be careful of the following enqeueue/dequeue ordering
++	 * Need to be careful of the following enqueue/dequeue ordering
+ 	 * problem too
+ 	 *
+ 	 *	enqueue(taskA)
+ 	 *	// sched_uclamp_used gets enabled
+ 	 *	enqueue(taskB)
+ 	 *	dequeue(taskA)
+-	 *	// Must not decrement bukcet->tasks here
++	 *	// Must not decrement bucket->tasks here
+ 	 *	dequeue(taskB)
+ 	 *
+ 	 * where we could end up with stale data in uc_se and
+@@ -2924,7 +2924,7 @@ static void ttwu_do_wakeup(struct rq *rq, struct task_struct *p, int wake_flags,
+ #ifdef CONFIG_SMP
+ 	if (p->sched_class->task_woken) {
+ 		/*
+-		 * Our task @p is fully woken up and running; so its safe to
++		 * Our task @p is fully woken up and running; so it's safe to
+ 		 * drop the rq->lock, hereafter rq is only used for statistics.
+ 		 */
+ 		rq_unpin_lock(rq, rf);
+@@ -3411,7 +3411,7 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
+ 
+ 	/*
+ 	 * If the owning (remote) CPU is still in the middle of schedule() with
+-	 * this task as prev, wait until its done referencing the task.
++	 * this task as prev, wait until it's done referencing the task.
+ 	 *
+ 	 * Pairs with the smp_store_release() in finish_task().
+ 	 *
+@@ -3816,7 +3816,7 @@ void wake_up_new_task(struct task_struct *p)
+ #ifdef CONFIG_SMP
+ 	if (p->sched_class->task_woken) {
+ 		/*
+-		 * Nothing relies on rq->lock after this, so its fine to
++		 * Nothing relies on rq->lock after this, so it's fine to
+ 		 * drop it.
+ 		 */
+ 		rq_unpin_lock(rq, &rf);
+@@ -4343,7 +4343,7 @@ unsigned long nr_iowait_cpu(int cpu)
+ }
+ 
+ /*
+- * IO-wait accounting, and how its mostly bollocks (on SMP).
++ * IO-wait accounting, and how it's mostly bollocks (on SMP).
+  *
+  * The idea behind IO-wait account is to account the idle time that we could
+  * have spend running if it were not for IO. That is, if we were to improve the
+@@ -4838,7 +4838,7 @@ pick_next_task(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
+ 	/*
+ 	 * Optimization: we know that if all tasks are in the fair class we can
+ 	 * call that function directly, but only if the @prev task wasn't of a
+-	 * higher scheduling class, because otherwise those loose the
++	 * higher scheduling class, because otherwise those lose the
+ 	 * opportunity to pull in more work from other CPUs.
+ 	 */
+ 	if (likely(prev->sched_class <= &fair_sched_class &&
+@@ -5361,7 +5361,7 @@ void rt_mutex_setprio(struct task_struct *p, struct task_struct *pi_task)
+ 	 * right. rt_mutex_slowunlock()+rt_mutex_postunlock() work together to
+ 	 * ensure a task is de-boosted (pi_task is set to NULL) before the
+ 	 * task is allowed to run again (and can exit). This ensures the pointer
+-	 * points to a blocked task -- which guaratees the task is present.
++	 * points to a blocked task -- which guarantees the task is present.
+ 	 */
+ 	p->pi_top_task = pi_task;
+ 
+@@ -5479,7 +5479,7 @@ void set_user_nice(struct task_struct *p, long nice)
+ 	/*
+ 	 * The RT priorities are set via sched_setscheduler(), but we still
+ 	 * allow the 'normal' nice value to be set - but as expected
+-	 * it wont have any effect on scheduling until the task is
++	 * it won't have any effect on scheduling until the task is
+ 	 * SCHED_DEADLINE, SCHED_FIFO or SCHED_RR:
+ 	 */
+ 	if (task_has_dl_policy(p) || task_has_rt_policy(p)) {
+@@ -6668,7 +6668,7 @@ EXPORT_SYMBOL(__cond_resched_lock);
+  *
+  * The scheduler is at all times free to pick the calling task as the most
+  * eligible task to run, if removing the yield() call from your code breaks
+- * it, its already broken.
++ * it, it's already broken.
+  *
+  * Typical broken usage is:
+  *
+@@ -7042,7 +7042,7 @@ void init_idle(struct task_struct *idle, int cpu)
+ 
+ #ifdef CONFIG_SMP
+ 	/*
+-	 * Its possible that init_idle() gets called multiple times on a task,
++	 * It's possible that init_idle() gets called multiple times on a task,
+ 	 * in that case do_set_cpus_allowed() will not do the right thing.
+ 	 *
+ 	 * And since this is boot we can forgo the serialization.
+@@ -8225,7 +8225,7 @@ static int cpu_cgroup_can_attach(struct cgroup_taskset *tset)
+ 			return -EINVAL;
+ #endif
+ 		/*
+-		 * Serialize against wake_up_new_task() such that if its
++		 * Serialize against wake_up_new_task() such that if it's
+ 		 * running, we're sure to observe its full state.
+ 		 */
+ 		raw_spin_lock_irq(&task->pi_lock);

commit 8d0dd23c6c78d140ed2132f523592ddb4cea839f
+Author: Tal Zussman 
+Date:   Thu Nov 12 16:56:57 2020 -0500
+
+    syscalls: Fix file comments for syscalls implemented in kernel/sys.c
+    
+    The relevant syscalls were previously moved from kernel/timer.c to kernel/sys.c,
+    but the comments weren't updated to reflect this change.
+    
+    Fixing these comments messes up the alphabetical ordering of syscalls by
+    filename. This could be fixed by merging the two groups of kernel/sys.c syscalls,
+    but that would require reordering the syscalls and renumbering them to maintain
+    the numerical order in unistd.h.
+    
+    Signed-off-by: Tal Zussman 
+    Link: https://lore.kernel.org/r/20201112215657.GA4539@charmander'
+    Signed-off-by: Arnd Bergmann 
+
+diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
+index 37bea07c12f2..629870fbb2c9 100644
+--- a/include/linux/syscalls.h
++++ b/include/linux/syscalls.h
+@@ -744,7 +744,7 @@ asmlinkage long sys_settimeofday(struct __kernel_old_timeval __user *tv,
+ asmlinkage long sys_adjtimex(struct __kernel_timex __user *txc_p);
+ asmlinkage long sys_adjtimex_time32(struct old_timex32 __user *txc_p);
+ 
+-/* kernel/timer.c */
++/* kernel/sys.c */
+ asmlinkage long sys_getpid(void);
+ asmlinkage long sys_getppid(void);
+ asmlinkage long sys_getuid(void);
+diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
+index 2056318988f7..fc48c64700eb 100644
+--- a/include/uapi/asm-generic/unistd.h
++++ b/include/uapi/asm-generic/unistd.h
+@@ -517,7 +517,7 @@ __SC_COMP(__NR_settimeofday, sys_settimeofday, compat_sys_settimeofday)
+ __SC_3264(__NR_adjtimex, sys_adjtimex_time32, sys_adjtimex)
+ #endif
+ 
+-/* kernel/timer.c */
++/* kernel/sys.c */
+ #define __NR_getpid 172
+ __SYSCALL(__NR_getpid, sys_getpid)
+ #define __NR_getppid 173

commit 8d404c4c246137531f94dfee352f350d59d0e5a7
+Author: Christoffer Dall 
+Date:   Wed Mar 16 15:38:53 2016 +0100
+
+    KVM: arm64: Rewrite system register accessors to read/write functions
+    
+    Currently we access the system registers array via the vcpu_sys_reg()
+    macro.  However, we are about to change the behavior to some times
+    modify the register file directly, so let's change this to two
+    primitives:
+    
+     * Accessor macros vcpu_write_sys_reg() and vcpu_read_sys_reg()
+     * Direct array access macro __vcpu_sys_reg()
+    
+    The accessor macros should be used in places where the code needs to
+    access the currently loaded VCPU's state as observed by the guest.  For
+    example, when trapping on cache related registers, a write to a system
+    register should go directly to the VCPU version of the register.
+    
+    The direct array access macro can be used in places where the VCPU is
+    known to never be running (for example userspace access) or for
+    registers which are never context switched (for example all the PMU
+    system registers).
+    
+    This rewrites all users of vcpu_sys_regs to one of the macros described
+    above.
+    
+    No functional change.
+    
+    Acked-by: Marc Zyngier 
+    Reviewed-by: Andrew Jones 
+    Signed-off-by: Christoffer Dall 
+    Signed-off-by: Marc Zyngier 
+
+diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
+index 3cc535591bdf..d313aaae5c38 100644
+--- a/arch/arm64/include/asm/kvm_emulate.h
++++ b/arch/arm64/include/asm/kvm_emulate.h
+@@ -290,15 +290,18 @@ static inline int kvm_vcpu_sys_get_rt(struct kvm_vcpu *vcpu)
+ 
+ static inline unsigned long kvm_vcpu_get_mpidr_aff(struct kvm_vcpu *vcpu)
+ {
+-	return vcpu_sys_reg(vcpu, MPIDR_EL1) & MPIDR_HWID_BITMASK;
++	return vcpu_read_sys_reg(vcpu, MPIDR_EL1) & MPIDR_HWID_BITMASK;
+ }
+ 
+ static inline void kvm_vcpu_set_be(struct kvm_vcpu *vcpu)
+ {
+-	if (vcpu_mode_is_32bit(vcpu))
++	if (vcpu_mode_is_32bit(vcpu)) {
+ 		*vcpu_cpsr(vcpu) |= COMPAT_PSR_E_BIT;
+-	else
+-		vcpu_sys_reg(vcpu, SCTLR_EL1) |= (1 << 25);
++	} else {
++		u64 sctlr = vcpu_read_sys_reg(vcpu, SCTLR_EL1);
++		sctlr |= (1 << 25);
++		vcpu_write_sys_reg(vcpu, SCTLR_EL1, sctlr);
++	}
+ }
+ 
+ static inline bool kvm_vcpu_is_be(struct kvm_vcpu *vcpu)
+@@ -306,7 +309,7 @@ static inline bool kvm_vcpu_is_be(struct kvm_vcpu *vcpu)
+ 	if (vcpu_mode_is_32bit(vcpu))
+ 		return !!(*vcpu_cpsr(vcpu) & COMPAT_PSR_E_BIT);
+ 
+-	return !!(vcpu_sys_reg(vcpu, SCTLR_EL1) & (1 << 25));
++	return !!(vcpu_read_sys_reg(vcpu, SCTLR_EL1) & (1 << 25));
+ }
+ 
+ static inline unsigned long vcpu_data_guest_to_host(struct kvm_vcpu *vcpu,
+diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
+index 9001fd0890c9..179bb9d5760b 100644
+--- a/arch/arm64/include/asm/kvm_host.h
++++ b/arch/arm64/include/asm/kvm_host.h
+@@ -287,7 +287,18 @@ struct kvm_vcpu_arch {
+ };
+ 
+ #define vcpu_gp_regs(v)		(&(v)->arch.ctxt.gp_regs)
+-#define vcpu_sys_reg(v,r)	((v)->arch.ctxt.sys_regs[(r)])
++
++/*
++ * Only use __vcpu_sys_reg if you know you want the memory backed version of a
++ * register, and not the one most recently accessed by a running VCPU.  For
++ * example, for userspace access or for system registers that are never context
++ * switched, but only emulated.
++ */
++#define __vcpu_sys_reg(v,r)	((v)->arch.ctxt.sys_regs[(r)])
++
++#define vcpu_read_sys_reg(v,r)	__vcpu_sys_reg(v,r)
++#define vcpu_write_sys_reg(v,n,r)	do { __vcpu_sys_reg(v,r) = n; } while (0)
++
+ /*
+  * CP14 and CP15 live in the same array, as they are backed by the
+  * same system registers.
+diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
+index 7faed6e48b46..cffa34e23718 100644
+--- a/arch/arm64/include/asm/kvm_mmu.h
++++ b/arch/arm64/include/asm/kvm_mmu.h
+@@ -249,7 +249,7 @@ struct kvm;
+ 
+ static inline bool vcpu_has_cache_enabled(struct kvm_vcpu *vcpu)
+ {
+-	return (vcpu_sys_reg(vcpu, SCTLR_EL1) & 0b101) == 0b101;
++	return (vcpu_read_sys_reg(vcpu, SCTLR_EL1) & 0b101) == 0b101;
+ }
+ 
+ static inline void __clean_dcache_guest_page(kvm_pfn_t pfn, unsigned long size)
+diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c
+index feedb877cff8..a1f4ebdfe6d3 100644
+--- a/arch/arm64/kvm/debug.c
++++ b/arch/arm64/kvm/debug.c
+@@ -46,7 +46,9 @@ static DEFINE_PER_CPU(u32, mdcr_el2);
+  */
+ static void save_guest_debug_regs(struct kvm_vcpu *vcpu)
+ {
+-	vcpu->arch.guest_debug_preserved.mdscr_el1 = vcpu_sys_reg(vcpu, MDSCR_EL1);
++	u64 val = vcpu_read_sys_reg(vcpu, MDSCR_EL1);
++
++	vcpu->arch.guest_debug_preserved.mdscr_el1 = val;
+ 
+ 	trace_kvm_arm_set_dreg32("Saved MDSCR_EL1",
+ 				vcpu->arch.guest_debug_preserved.mdscr_el1);
+@@ -54,10 +56,12 @@ static void save_guest_debug_regs(struct kvm_vcpu *vcpu)
+ 
+ static void restore_guest_debug_regs(struct kvm_vcpu *vcpu)
+ {
+-	vcpu_sys_reg(vcpu, MDSCR_EL1) = vcpu->arch.guest_debug_preserved.mdscr_el1;
++	u64 val = vcpu->arch.guest_debug_preserved.mdscr_el1;
++
++	vcpu_write_sys_reg(vcpu, val, MDSCR_EL1);
+ 
+ 	trace_kvm_arm_set_dreg32("Restored MDSCR_EL1",
+-				vcpu_sys_reg(vcpu, MDSCR_EL1));
++				vcpu_read_sys_reg(vcpu, MDSCR_EL1));
+ }
+ 
+ /**
+@@ -108,6 +112,7 @@ void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu)
+ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
+ {
+ 	bool trap_debug = !(vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY);
++	unsigned long mdscr;
+ 
+ 	trace_kvm_arm_setup_debug(vcpu, vcpu->guest_debug);
+ 
+@@ -152,9 +157,13 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
+ 		 */
+ 		if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) {
+ 			*vcpu_cpsr(vcpu) |=  DBG_SPSR_SS;
+-			vcpu_sys_reg(vcpu, MDSCR_EL1) |= DBG_MDSCR_SS;
++			mdscr = vcpu_read_sys_reg(vcpu, MDSCR_EL1);
++			mdscr |= DBG_MDSCR_SS;
++			vcpu_write_sys_reg(vcpu, mdscr, MDSCR_EL1);
+ 		} else {
+-			vcpu_sys_reg(vcpu, MDSCR_EL1) &= ~DBG_MDSCR_SS;
++			mdscr = vcpu_read_sys_reg(vcpu, MDSCR_EL1);
++			mdscr &= ~DBG_MDSCR_SS;
++			vcpu_write_sys_reg(vcpu, mdscr, MDSCR_EL1);
+ 		}
+ 
+ 		trace_kvm_arm_set_dreg32("SPSR_EL2", *vcpu_cpsr(vcpu));
+@@ -170,7 +179,9 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
+ 		 */
+ 		if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW) {
+ 			/* Enable breakpoints/watchpoints */
+-			vcpu_sys_reg(vcpu, MDSCR_EL1) |= DBG_MDSCR_MDE;
++			mdscr = vcpu_read_sys_reg(vcpu, MDSCR_EL1);
++			mdscr |= DBG_MDSCR_MDE;
++			vcpu_write_sys_reg(vcpu, mdscr, MDSCR_EL1);
+ 
+ 			vcpu->arch.debug_ptr = &vcpu->arch.external_debug_state;
+ 			vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
+@@ -194,12 +205,11 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
+ 		vcpu->arch.mdcr_el2 |= MDCR_EL2_TDA;
+ 
+ 	/* If KDE or MDE are set, perform a full save/restore cycle. */
+-	if ((vcpu_sys_reg(vcpu, MDSCR_EL1) & DBG_MDSCR_KDE) ||
+-	    (vcpu_sys_reg(vcpu, MDSCR_EL1) & DBG_MDSCR_MDE))
++	if (vcpu_read_sys_reg(vcpu, MDSCR_EL1) & (DBG_MDSCR_KDE | DBG_MDSCR_MDE))
+ 		vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
+ 
+ 	trace_kvm_arm_set_dreg32("MDCR_EL2", vcpu->arch.mdcr_el2);
+-	trace_kvm_arm_set_dreg32("MDSCR_EL1", vcpu_sys_reg(vcpu, MDSCR_EL1));
++	trace_kvm_arm_set_dreg32("MDSCR_EL1", vcpu_read_sys_reg(vcpu, MDSCR_EL1));
+ }
+ 
+ void kvm_arm_clear_debug(struct kvm_vcpu *vcpu)
+diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c
+index 30a3f58cdb7b..63dba401fc7d 100644
+--- a/arch/arm64/kvm/inject_fault.c
++++ b/arch/arm64/kvm/inject_fault.c
+@@ -58,7 +58,7 @@ static u64 get_except_vector(struct kvm_vcpu *vcpu, enum exception_type type)
+ 		exc_offset = LOWER_EL_AArch32_VECTOR;
+ 	}
+ 
+-	return vcpu_sys_reg(vcpu, VBAR_EL1) + exc_offset + type;
++	return vcpu_read_sys_reg(vcpu, VBAR_EL1) + exc_offset + type;
+ }
+ 
+ static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr)
+@@ -73,7 +73,7 @@ static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr
+ 	*vcpu_cpsr(vcpu) = PSTATE_FAULT_BITS_64;
+ 	*vcpu_spsr(vcpu) = cpsr;
+ 
+-	vcpu_sys_reg(vcpu, FAR_EL1) = addr;
++	vcpu_write_sys_reg(vcpu, addr, FAR_EL1);
+ 
+ 	/*
+ 	 * Build an {i,d}abort, depending on the level and the
+@@ -94,7 +94,7 @@ static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr
+ 	if (!is_iabt)
+ 		esr |= ESR_ELx_EC_DABT_LOW << ESR_ELx_EC_SHIFT;
+ 
+-	vcpu_sys_reg(vcpu, ESR_EL1) = esr | ESR_ELx_FSC_EXTABT;
++	vcpu_write_sys_reg(vcpu, esr | ESR_ELx_FSC_EXTABT, ESR_EL1);
+ }
+ 
+ static void inject_undef64(struct kvm_vcpu *vcpu)
+@@ -115,7 +115,7 @@ static void inject_undef64(struct kvm_vcpu *vcpu)
+ 	if (kvm_vcpu_trap_il_is32bit(vcpu))
+ 		esr |= ESR_ELx_IL;
+ 
+-	vcpu_sys_reg(vcpu, ESR_EL1) = esr;
++	vcpu_write_sys_reg(vcpu, esr, ESR_EL1);
+ }
+ 
+ /**
+diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
+index 691f81c31018..7514db002430 100644
+--- a/arch/arm64/kvm/sys_regs.c
++++ b/arch/arm64/kvm/sys_regs.c
+@@ -133,14 +133,14 @@ static bool access_vm_reg(struct kvm_vcpu *vcpu,
+ 	if (!p->is_aarch32 || !p->is_32bit) {
+ 		val = p->regval;
+ 	} else {
+-		val = vcpu_sys_reg(vcpu, reg);
++		val = vcpu_read_sys_reg(vcpu, reg);
+ 		if (r->reg % 2)
+ 			val = (p->regval << 32) | (u64)lower_32_bits(val);
+ 		else
+ 			val = ((u64)upper_32_bits(val) << 32) |
+ 				lower_32_bits(p->regval);
+ 	}
+-	vcpu_sys_reg(vcpu, reg) = val;
++	vcpu_write_sys_reg(vcpu, val, reg);
+ 
+ 	kvm_toggle_cache(vcpu, was_enabled);
+ 	return true;
+@@ -249,10 +249,10 @@ static bool trap_debug_regs(struct kvm_vcpu *vcpu,
+ 			    const struct sys_reg_desc *r)
+ {
+ 	if (p->is_write) {
+-		vcpu_sys_reg(vcpu, r->reg) = p->regval;
++		vcpu_write_sys_reg(vcpu, p->regval, r->reg);
+ 		vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
+ 	} else {
+-		p->regval = vcpu_sys_reg(vcpu, r->reg);
++		p->regval = vcpu_read_sys_reg(vcpu, r->reg);
+ 	}
+ 
+ 	trace_trap_reg(__func__, r->reg, p->is_write, p->regval);
+@@ -465,7 +465,8 @@ static void reset_wcr(struct kvm_vcpu *vcpu,
+ 
+ static void reset_amair_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
+ {
+-	vcpu_sys_reg(vcpu, AMAIR_EL1) = read_sysreg(amair_el1);
++	u64 amair = read_sysreg(amair_el1);
++	vcpu_write_sys_reg(vcpu, amair, AMAIR_EL1);
+ }
+ 
+ static void reset_mpidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
+@@ -482,7 +483,7 @@ static void reset_mpidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
+ 	mpidr = (vcpu->vcpu_id & 0x0f) << MPIDR_LEVEL_SHIFT(0);
+ 	mpidr |= ((vcpu->vcpu_id >> 4) & 0xff) << MPIDR_LEVEL_SHIFT(1);
+ 	mpidr |= ((vcpu->vcpu_id >> 12) & 0xff) << MPIDR_LEVEL_SHIFT(2);
+-	vcpu_sys_reg(vcpu, MPIDR_EL1) = (1ULL << 31) | mpidr;
++	vcpu_write_sys_reg(vcpu, (1ULL << 31) | mpidr, MPIDR_EL1);
+ }
+ 
+ static void reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
+@@ -496,12 +497,12 @@ static void reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
+ 	 */
+ 	val = ((pmcr & ~ARMV8_PMU_PMCR_MASK)
+ 	       | (ARMV8_PMU_PMCR_MASK & 0xdecafbad)) & (~ARMV8_PMU_PMCR_E);
+-	vcpu_sys_reg(vcpu, PMCR_EL0) = val;
++	__vcpu_sys_reg(vcpu, PMCR_EL0) = val;
+ }
+ 
+ static bool check_pmu_access_disabled(struct kvm_vcpu *vcpu, u64 flags)
+ {
+-	u64 reg = vcpu_sys_reg(vcpu, PMUSERENR_EL0);
++	u64 reg = __vcpu_sys_reg(vcpu, PMUSERENR_EL0);
+ 	bool enabled = (reg & flags) || vcpu_mode_priv(vcpu);
+ 
+ 	if (!enabled)
+@@ -543,14 +544,14 @@ static bool access_pmcr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+ 
+ 	if (p->is_write) {
+ 		/* Only update writeable bits of PMCR */
+-		val = vcpu_sys_reg(vcpu, PMCR_EL0);
++		val = __vcpu_sys_reg(vcpu, PMCR_EL0);
+ 		val &= ~ARMV8_PMU_PMCR_MASK;
+ 		val |= p->regval & ARMV8_PMU_PMCR_MASK;
+-		vcpu_sys_reg(vcpu, PMCR_EL0) = val;
++		__vcpu_sys_reg(vcpu, PMCR_EL0) = val;
+ 		kvm_pmu_handle_pmcr(vcpu, val);
+ 	} else {
+ 		/* PMCR.P & PMCR.C are RAZ */
+-		val = vcpu_sys_reg(vcpu, PMCR_EL0)
++		val = __vcpu_sys_reg(vcpu, PMCR_EL0)
+ 		      & ~(ARMV8_PMU_PMCR_P | ARMV8_PMU_PMCR_C);
+ 		p->regval = val;
+ 	}
+@@ -568,10 +569,10 @@ static bool access_pmselr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+ 		return false;
+ 
+ 	if (p->is_write)
+-		vcpu_sys_reg(vcpu, PMSELR_EL0) = p->regval;
++		__vcpu_sys_reg(vcpu, PMSELR_EL0) = p->regval;
+ 	else
+ 		/* return PMSELR.SEL field */
+-		p->regval = vcpu_sys_reg(vcpu, PMSELR_EL0)
++		p->regval = __vcpu_sys_reg(vcpu, PMSELR_EL0)
+ 			    & ARMV8_PMU_COUNTER_MASK;
+ 
+ 	return true;
+@@ -604,7 +605,7 @@ static bool pmu_counter_idx_valid(struct kvm_vcpu *vcpu, u64 idx)
+ {
+ 	u64 pmcr, val;
+ 
+-	pmcr = vcpu_sys_reg(vcpu, PMCR_EL0);
++	pmcr = __vcpu_sys_reg(vcpu, PMCR_EL0);
+ 	val = (pmcr >> ARMV8_PMU_PMCR_N_SHIFT) & ARMV8_PMU_PMCR_N_MASK;
+ 	if (idx >= val && idx != ARMV8_PMU_CYCLE_IDX) {
+ 		kvm_inject_undefined(vcpu);
+@@ -629,7 +630,7 @@ static bool access_pmu_evcntr(struct kvm_vcpu *vcpu,
+ 			if (pmu_access_event_counter_el0_disabled(vcpu))
+ 				return false;
+ 
+-			idx = vcpu_sys_reg(vcpu, PMSELR_EL0)
++			idx = __vcpu_sys_reg(vcpu, PMSELR_EL0)
+ 			      & ARMV8_PMU_COUNTER_MASK;
+ 		} else if (r->Op2 == 0) {
+ 			/* PMCCNTR_EL0 */
+@@ -684,7 +685,7 @@ static bool access_pmu_evtyper(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+ 
+ 	if (r->CRn == 9 && r->CRm == 13 && r->Op2 == 1) {
+ 		/* PMXEVTYPER_EL0 */
+-		idx = vcpu_sys_reg(vcpu, PMSELR_EL0) & ARMV8_PMU_COUNTER_MASK;
++		idx = __vcpu_sys_reg(vcpu, PMSELR_EL0) & ARMV8_PMU_COUNTER_MASK;
+ 		reg = PMEVTYPER0_EL0 + idx;
+ 	} else if (r->CRn == 14 && (r->CRm & 12) == 12) {
+ 		idx = ((r->CRm & 3) << 3) | (r->Op2 & 7);
+@@ -702,9 +703,9 @@ static bool access_pmu_evtyper(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+ 
+ 	if (p->is_write) {
+ 		kvm_pmu_set_counter_event_type(vcpu, p->regval, idx);
+-		vcpu_sys_reg(vcpu, reg) = p->regval & ARMV8_PMU_EVTYPE_MASK;
++		__vcpu_sys_reg(vcpu, reg) = p->regval & ARMV8_PMU_EVTYPE_MASK;
+ 	} else {
+-		p->regval = vcpu_sys_reg(vcpu, reg) & ARMV8_PMU_EVTYPE_MASK;
++		p->regval = __vcpu_sys_reg(vcpu, reg) & ARMV8_PMU_EVTYPE_MASK;
+ 	}
+ 
+ 	return true;
+@@ -726,15 +727,15 @@ static bool access_pmcnten(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+ 		val = p->regval & mask;
+ 		if (r->Op2 & 0x1) {
+ 			/* accessing PMCNTENSET_EL0 */
+-			vcpu_sys_reg(vcpu, PMCNTENSET_EL0) |= val;
++			__vcpu_sys_reg(vcpu, PMCNTENSET_EL0) |= val;
+ 			kvm_pmu_enable_counter(vcpu, val);
+ 		} else {
+ 			/* accessing PMCNTENCLR_EL0 */
+-			vcpu_sys_reg(vcpu, PMCNTENSET_EL0) &= ~val;
++			__vcpu_sys_reg(vcpu, PMCNTENSET_EL0) &= ~val;
+ 			kvm_pmu_disable_counter(vcpu, val);
+ 		}
+ 	} else {
+-		p->regval = vcpu_sys_reg(vcpu, PMCNTENSET_EL0) & mask;
++		p->regval = __vcpu_sys_reg(vcpu, PMCNTENSET_EL0) & mask;
+ 	}
+ 
+ 	return true;
+@@ -758,12 +759,12 @@ static bool access_pminten(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+ 
+ 		if (r->Op2 & 0x1)
+ 			/* accessing PMINTENSET_EL1 */
+-			vcpu_sys_reg(vcpu, PMINTENSET_EL1) |= val;
++			__vcpu_sys_reg(vcpu, PMINTENSET_EL1) |= val;
+ 		else
+ 			/* accessing PMINTENCLR_EL1 */
+-			vcpu_sys_reg(vcpu, PMINTENSET_EL1) &= ~val;
++			__vcpu_sys_reg(vcpu, PMINTENSET_EL1) &= ~val;
+ 	} else {
+-		p->regval = vcpu_sys_reg(vcpu, PMINTENSET_EL1) & mask;
++		p->regval = __vcpu_sys_reg(vcpu, PMINTENSET_EL1) & mask;
+ 	}
+ 
+ 	return true;
+@@ -783,12 +784,12 @@ static bool access_pmovs(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+ 	if (p->is_write) {
+ 		if (r->CRm & 0x2)
+ 			/* accessing PMOVSSET_EL0 */
+-			vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= (p->regval & mask);
++			__vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= (p->regval & mask);
+ 		else
+ 			/* accessing PMOVSCLR_EL0 */
+-			vcpu_sys_reg(vcpu, PMOVSSET_EL0) &= ~(p->regval & mask);
++			__vcpu_sys_reg(vcpu, PMOVSSET_EL0) &= ~(p->regval & mask);
+ 	} else {
+-		p->regval = vcpu_sys_reg(vcpu, PMOVSSET_EL0) & mask;
++		p->regval = __vcpu_sys_reg(vcpu, PMOVSSET_EL0) & mask;
+ 	}
+ 
+ 	return true;
+@@ -825,10 +826,10 @@ static bool access_pmuserenr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+ 			return false;
+ 		}
+ 
+-		vcpu_sys_reg(vcpu, PMUSERENR_EL0) = p->regval
+-						    & ARMV8_PMU_USERENR_MASK;
++		__vcpu_sys_reg(vcpu, PMUSERENR_EL0) =
++			       p->regval & ARMV8_PMU_USERENR_MASK;
+ 	} else {
+-		p->regval = vcpu_sys_reg(vcpu, PMUSERENR_EL0)
++		p->regval = __vcpu_sys_reg(vcpu, PMUSERENR_EL0)
+ 			    & ARMV8_PMU_USERENR_MASK;
+ 	}
+ 
+@@ -2230,7 +2231,7 @@ int kvm_arm_sys_reg_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg
+ 	if (r->get_user)
+ 		return (r->get_user)(vcpu, r, reg, uaddr);
+ 
+-	return reg_to_user(uaddr, &vcpu_sys_reg(vcpu, r->reg), reg->id);
++	return reg_to_user(uaddr, &__vcpu_sys_reg(vcpu, r->reg), reg->id);
+ }
+ 
+ int kvm_arm_sys_reg_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+@@ -2251,7 +2252,7 @@ int kvm_arm_sys_reg_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg
+ 	if (r->set_user)
+ 		return (r->set_user)(vcpu, r, reg, uaddr);
+ 
+-	return reg_from_user(&vcpu_sys_reg(vcpu, r->reg), uaddr, reg->id);
++	return reg_from_user(&__vcpu_sys_reg(vcpu, r->reg), uaddr, reg->id);
+ }
+ 
+ static unsigned int num_demux_regs(void)
+@@ -2457,6 +2458,6 @@ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu)
+ 	reset_sys_reg_descs(vcpu, table, num);
+ 
+ 	for (num = 1; num < NR_SYS_REGS; num++)
+-		if (vcpu_sys_reg(vcpu, num) == 0x4242424242424242)
+-			panic("Didn't reset vcpu_sys_reg(%zi)", num);
++		if (__vcpu_sys_reg(vcpu, num) == 0x4242424242424242)
++			panic("Didn't reset __vcpu_sys_reg(%zi)", num);
+ }
+diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h
+index 060f5348ef25..cd710f8b63e0 100644
+--- a/arch/arm64/kvm/sys_regs.h
++++ b/arch/arm64/kvm/sys_regs.h
+@@ -89,14 +89,14 @@ static inline void reset_unknown(struct kvm_vcpu *vcpu,
+ {
+ 	BUG_ON(!r->reg);
+ 	BUG_ON(r->reg >= NR_SYS_REGS);
+-	vcpu_sys_reg(vcpu, r->reg) = 0x1de7ec7edbadc0deULL;
++	__vcpu_sys_reg(vcpu, r->reg) = 0x1de7ec7edbadc0deULL;
+ }
+ 
+ static inline void reset_val(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
+ {
+ 	BUG_ON(!r->reg);
+ 	BUG_ON(r->reg >= NR_SYS_REGS);
+-	vcpu_sys_reg(vcpu, r->reg) = r->val;
++	__vcpu_sys_reg(vcpu, r->reg) = r->val;
+ }
+ 
+ static inline int cmp_sys_reg(const struct sys_reg_desc *i1,
+diff --git a/arch/arm64/kvm/sys_regs_generic_v8.c b/arch/arm64/kvm/sys_regs_generic_v8.c
+index 969ade1d333d..ddb8497d18d6 100644
+--- a/arch/arm64/kvm/sys_regs_generic_v8.c
++++ b/arch/arm64/kvm/sys_regs_generic_v8.c
+@@ -38,13 +38,13 @@ static bool access_actlr(struct kvm_vcpu *vcpu,
+ 	if (p->is_write)
+ 		return ignore_write(vcpu, p);
+ 
+-	p->regval = vcpu_sys_reg(vcpu, ACTLR_EL1);
++	p->regval = vcpu_read_sys_reg(vcpu, ACTLR_EL1);
+ 	return true;
+ }
+ 
+ static void reset_actlr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
+ {
+-	vcpu_sys_reg(vcpu, ACTLR_EL1) = read_sysreg(actlr_el1);
++	__vcpu_sys_reg(vcpu, ACTLR_EL1) = read_sysreg(actlr_el1);
+ }
+ 
+ /*
+diff --git a/virt/kvm/arm/pmu.c b/virt/kvm/arm/pmu.c
+index 8a9c42366db7..1c5b76c46e26 100644
+--- a/virt/kvm/arm/pmu.c
++++ b/virt/kvm/arm/pmu.c
+@@ -37,7 +37,7 @@ u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx)
+ 
+ 	reg = (select_idx == ARMV8_PMU_CYCLE_IDX)
+ 	      ? PMCCNTR_EL0 : PMEVCNTR0_EL0 + select_idx;
+-	counter = vcpu_sys_reg(vcpu, reg);
++	counter = __vcpu_sys_reg(vcpu, reg);
+ 
+ 	/* The real counter value is equal to the value of counter register plus
+ 	 * the value perf event counts.
+@@ -61,7 +61,7 @@ void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val)
+ 
+ 	reg = (select_idx == ARMV8_PMU_CYCLE_IDX)
+ 	      ? PMCCNTR_EL0 : PMEVCNTR0_EL0 + select_idx;
+-	vcpu_sys_reg(vcpu, reg) += (s64)val - kvm_pmu_get_counter_value(vcpu, select_idx);
++	__vcpu_sys_reg(vcpu, reg) += (s64)val - kvm_pmu_get_counter_value(vcpu, select_idx);
+ }
+ 
+ /**
+@@ -78,7 +78,7 @@ static void kvm_pmu_stop_counter(struct kvm_vcpu *vcpu, struct kvm_pmc *pmc)
+ 		counter = kvm_pmu_get_counter_value(vcpu, pmc->idx);
+ 		reg = (pmc->idx == ARMV8_PMU_CYCLE_IDX)
+ 		       ? PMCCNTR_EL0 : PMEVCNTR0_EL0 + pmc->idx;
+-		vcpu_sys_reg(vcpu, reg) = counter;
++		__vcpu_sys_reg(vcpu, reg) = counter;
+ 		perf_event_disable(pmc->perf_event);
+ 		perf_event_release_kernel(pmc->perf_event);
+ 		pmc->perf_event = NULL;
+@@ -125,7 +125,7 @@ void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu)
+ 
+ u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu)
+ {
+-	u64 val = vcpu_sys_reg(vcpu, PMCR_EL0) >> ARMV8_PMU_PMCR_N_SHIFT;
++	u64 val = __vcpu_sys_reg(vcpu, PMCR_EL0) >> ARMV8_PMU_PMCR_N_SHIFT;
+ 
+ 	val &= ARMV8_PMU_PMCR_N_MASK;
+ 	if (val == 0)
+@@ -147,7 +147,7 @@ void kvm_pmu_enable_counter(struct kvm_vcpu *vcpu, u64 val)
+ 	struct kvm_pmu *pmu = &vcpu->arch.pmu;
+ 	struct kvm_pmc *pmc;
+ 
+-	if (!(vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_E) || !val)
++	if (!(__vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_E) || !val)
+ 		return;
+ 
+ 	for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++) {
+@@ -193,10 +193,10 @@ static u64 kvm_pmu_overflow_status(struct kvm_vcpu *vcpu)
+ {
+ 	u64 reg = 0;
+ 
+-	if ((vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_E)) {
+-		reg = vcpu_sys_reg(vcpu, PMOVSSET_EL0);
+-		reg &= vcpu_sys_reg(vcpu, PMCNTENSET_EL0);
+-		reg &= vcpu_sys_reg(vcpu, PMINTENSET_EL1);
++	if ((__vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_E)) {
++		reg = __vcpu_sys_reg(vcpu, PMOVSSET_EL0);
++		reg &= __vcpu_sys_reg(vcpu, PMCNTENSET_EL0);
++		reg &= __vcpu_sys_reg(vcpu, PMINTENSET_EL1);
+ 		reg &= kvm_pmu_valid_counter_mask(vcpu);
+ 	}
+ 
+@@ -295,7 +295,7 @@ static void kvm_pmu_perf_overflow(struct perf_event *perf_event,
+ 	struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc);
+ 	int idx = pmc->idx;
+ 
+-	vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= BIT(idx);
++	__vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= BIT(idx);
+ 
+ 	if (kvm_pmu_overflow_status(vcpu)) {
+ 		kvm_make_request(KVM_REQ_IRQ_PENDING, vcpu);
+@@ -316,19 +316,19 @@ void kvm_pmu_software_increment(struct kvm_vcpu *vcpu, u64 val)
+ 	if (val == 0)
+ 		return;
+ 
+-	enable = vcpu_sys_reg(vcpu, PMCNTENSET_EL0);
++	enable = __vcpu_sys_reg(vcpu, PMCNTENSET_EL0);
+ 	for (i = 0; i < ARMV8_PMU_CYCLE_IDX; i++) {
+ 		if (!(val & BIT(i)))
+ 			continue;
+-		type = vcpu_sys_reg(vcpu, PMEVTYPER0_EL0 + i)
++		type = __vcpu_sys_reg(vcpu, PMEVTYPER0_EL0 + i)
+ 		       & ARMV8_PMU_EVTYPE_EVENT;
+ 		if ((type == ARMV8_PMUV3_PERFCTR_SW_INCR)
+ 		    && (enable & BIT(i))) {
+-			reg = vcpu_sys_reg(vcpu, PMEVCNTR0_EL0 + i) + 1;
++			reg = __vcpu_sys_reg(vcpu, PMEVCNTR0_EL0 + i) + 1;
+ 			reg = lower_32_bits(reg);
+-			vcpu_sys_reg(vcpu, PMEVCNTR0_EL0 + i) = reg;
++			__vcpu_sys_reg(vcpu, PMEVCNTR0_EL0 + i) = reg;
+ 			if (!reg)
+-				vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= BIT(i);
++				__vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= BIT(i);
+ 		}
+ 	}
+ }
+@@ -348,7 +348,7 @@ void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val)
+ 	mask = kvm_pmu_valid_counter_mask(vcpu);
+ 	if (val & ARMV8_PMU_PMCR_E) {
+ 		kvm_pmu_enable_counter(vcpu,
+-				vcpu_sys_reg(vcpu, PMCNTENSET_EL0) & mask);
++		       __vcpu_sys_reg(vcpu, PMCNTENSET_EL0) & mask);
+ 	} else {
+ 		kvm_pmu_disable_counter(vcpu, mask);
+ 	}
+@@ -369,8 +369,8 @@ void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val)
+ 
+ static bool kvm_pmu_counter_is_enabled(struct kvm_vcpu *vcpu, u64 select_idx)
+ {
+-	return (vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_E) &&
+-	       (vcpu_sys_reg(vcpu, PMCNTENSET_EL0) & BIT(select_idx));
++	return (__vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_E) &&
++	       (__vcpu_sys_reg(vcpu, PMCNTENSET_EL0) & BIT(select_idx));
+ }
+ 
+ /**

commit 35a84dec00a707aed97c1ff9ebb1cd1eb67c7052
+Author: Shih-Wei Li 
+Date:   Thu Aug 3 11:45:21 2017 +0200
+
+    KVM: arm64: Move HCR_INT_OVERRIDE to default HCR_EL2 guest flag
+    
+    We always set the IMO and FMO bits in the HCR_EL2 when running the
+    guest, regardless if we use the vgic or not.  By moving these flags to
+    HCR_GUEST_FLAGS we can avoid one of the extra save/restore operations of
+    HCR_EL2 in the world switch code, and we can also soon get rid of the
+    other one.
+    
+    This is safe, because even though the IMO and FMO bits control both
+    taking the interrupts to EL2 and remapping ICC_*_EL1 to ICV_*_EL1 when
+    executed at EL1, as long as we ensure that these bits are clear when
+    running the EL1 host, we're OK, because we reset the HCR_EL2 to only
+    have the HCR_RW bit set when returning to EL1 on non-VHE systems.
+    
+    Reviewed-by: Marc Zyngier 
+    Signed-off-by: Shih-Wei Li 
+    Signed-off-by: Christoffer Dall 
+    Signed-off-by: Marc Zyngier 
+
+diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
+index 1b438c334463..6dd285e979c9 100644
+--- a/arch/arm64/include/asm/kvm_arm.h
++++ b/arch/arm64/include/asm/kvm_arm.h
+@@ -83,9 +83,9 @@
+  */
+ #define HCR_GUEST_FLAGS (HCR_TSC | HCR_TSW | HCR_TWE | HCR_TWI | HCR_VM | \
+ 			 HCR_TVM | HCR_BSU_IS | HCR_FB | HCR_TAC | \
+-			 HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW | HCR_TLOR)
++			 HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW | HCR_TLOR | \
++			 HCR_FMO | HCR_IMO)
+ #define HCR_VIRT_EXCP_MASK (HCR_VSE | HCR_VI | HCR_VF)
+-#define HCR_INT_OVERRIDE   (HCR_FMO | HCR_IMO)
+ #define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)
+ 
+ /* TCR_EL2 Registers bits */
+diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
+index 579d9a263853..4117717548b0 100644
+--- a/arch/arm64/kvm/hyp/switch.c
++++ b/arch/arm64/kvm/hyp/switch.c
+@@ -174,8 +174,6 @@ static void __hyp_text __vgic_save_state(struct kvm_vcpu *vcpu)
+ 		__vgic_v3_save_state(vcpu);
+ 	else
+ 		__vgic_v2_save_state(vcpu);
+-
+-	write_sysreg(read_sysreg(hcr_el2) & ~HCR_INT_OVERRIDE, hcr_el2);
+ }
+ 
+ static void __hyp_text __vgic_restore_state(struct kvm_vcpu *vcpu)
+@@ -183,7 +181,6 @@ static void __hyp_text __vgic_restore_state(struct kvm_vcpu *vcpu)
+ 	u64 val;
+ 
+ 	val = read_sysreg(hcr_el2);
+-	val |= 	HCR_INT_OVERRIDE;
+ 	val |= vcpu->arch.irq_lines;
+ 	write_sysreg(val, hcr_el2);
+ 

commit f6769581e90ba2535b3e587fe15b74f6cbc4aaab
+Author: Shih-Wei Li 
+Date:   Wed Oct 19 18:12:34 2016 +0000
+
+    KVM: arm/arm64: vgic: Avoid flushing vgic state when there's no pending IRQ
+    
+    We do not need to flush vgic states in each world switch unless
+    there is pending IRQ queued to the vgic's ap list. We can thus reduce
+    the overhead by not grabbing the spinlock and not making the extra
+    function call to vgic_flush_lr_state.
+    
+    Note: list_empty is a single atomic read (uses READ_ONCE) and can
+    therefore check if a list is empty or not without the need to take the
+    spinlock protecting the list.
+    
+    Reviewed-by: Marc Zyngier 
+    Signed-off-by: Shih-Wei Li 
+    Signed-off-by: Christoffer Dall 
+
+diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
+index 2ac0def57424..104329139f24 100644
+--- a/virt/kvm/arm/vgic/vgic.c
++++ b/virt/kvm/arm/vgic/vgic.c
+@@ -637,12 +637,17 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
+ /* Sync back the hardware VGIC state into our emulation after a guest's run. */
+ void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
+ {
++	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
++
+ 	if (unlikely(!vgic_initialized(vcpu->kvm)))
+ 		return;
+ 
+ 	vgic_process_maintenance_interrupt(vcpu);
+ 	vgic_fold_lr_state(vcpu);
+ 	vgic_prune_ap_list(vcpu);
++
++	/* Make sure we can fast-path in flush_hwstate */
++	vgic_cpu->used_lrs = 0;
+ }
+ 
+ /* Flush our emulation state into the GIC hardware before entering the guest. */
+@@ -651,6 +656,18 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
+ 	if (unlikely(!vgic_initialized(vcpu->kvm)))
+ 		return;
+ 
++	/*
++	 * If there are no virtual interrupts active or pending for this
++	 * VCPU, then there is no work to do and we can bail out without
++	 * taking any lock.  There is a potential race with someone injecting
++	 * interrupts to the VCPU, but it is a benign race as the VCPU will
++	 * either observe the new interrupt before or after doing this check,
++	 * and introducing additional synchronization mechanism doesn't change
++	 * this.
++	 */
++	if (list_empty(&vcpu->arch.vgic_cpu.ap_list_head))
++		return;
++
+ 	spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
+ 	vgic_flush_lr_state(vcpu);
+ 	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);

commit 328e566479449194979d64685ae6d74c989599bb
+Author: Christoffer Dall 
+Date:   Thu Mar 24 11:21:04 2016 +0100
+
+    KVM: arm/arm64: vgic: Defer touching GICH_VMCR to vcpu_load/put
+    
+    We don't have to save/restore the VMCR on every entry to/from the guest,
+    since on GICv2 we can access the control interface from EL1 and on VHE
+    systems with GICv3 we can access the control interface from KVM running
+    in EL2.
+    
+    GICv3 systems without VHE becomes the rare case, which has to
+    save/restore the register on each round trip.
+    
+    Note that userspace accesses may see out-of-date values if the VCPU is
+    running while accessing the VGIC state via the KVM device API, but this
+    is already the case and it is up to userspace to quiesce the CPUs before
+    reading the CPU registers from the GIC for an up-to-date view.
+    
+    Reviewed-by: Marc Zyngier 
+    Signed-off-by: Christoffer Dall 
+    Signed-off-by: Christoffer Dall 
+
+diff --git a/arch/arm/include/asm/kvm_asm.h b/arch/arm/include/asm/kvm_asm.h
+index 8ef05381984b..dd16044b34b6 100644
+--- a/arch/arm/include/asm/kvm_asm.h
++++ b/arch/arm/include/asm/kvm_asm.h
+@@ -75,7 +75,10 @@ extern void __init_stage2_translation(void);
+ extern void __kvm_hyp_reset(unsigned long);
+ 
+ extern u64 __vgic_v3_get_ich_vtr_el2(void);
++extern u64 __vgic_v3_read_vmcr(void);
++extern void __vgic_v3_write_vmcr(u32 vmcr);
+ extern void __vgic_v3_init_lrs(void);
++
+ #endif
+ 
+ #endif /* __ARM_KVM_ASM_H__ */
+diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
+index 96dba7cd8be7..46fd37578693 100644
+--- a/arch/arm/kvm/arm.c
++++ b/arch/arm/kvm/arm.c
+@@ -351,15 +351,14 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+ 	vcpu->arch.host_cpu_context = this_cpu_ptr(kvm_host_cpu_state);
+ 
+ 	kvm_arm_set_running_vcpu(vcpu);
++
++	kvm_vgic_load(vcpu);
+ }
+ 
+ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
+ {
+-	/*
+-	 * The arch-generic KVM code expects the cpu field of a vcpu to be -1
+-	 * if the vcpu is no longer assigned to a cpu.  This is used for the
+-	 * optimized make_all_cpus_request path.
+-	 */
++	kvm_vgic_put(vcpu);
++
+ 	vcpu->cpu = -1;
+ 
+ 	kvm_arm_set_running_vcpu(NULL);
+@@ -633,7 +632,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
+ 		 * non-preemptible context.
+ 		 */
+ 		preempt_disable();
++
+ 		kvm_pmu_flush_hwstate(vcpu);
++
+ 		kvm_timer_flush_hwstate(vcpu);
+ 		kvm_vgic_flush_hwstate(vcpu);
+ 
+diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
+index ec3553eb9349..49f99cd02613 100644
+--- a/arch/arm64/include/asm/kvm_asm.h
++++ b/arch/arm64/include/asm/kvm_asm.h
+@@ -59,6 +59,8 @@ extern void __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu);
+ extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
+ 
+ extern u64 __vgic_v3_get_ich_vtr_el2(void);
++extern u64 __vgic_v3_read_vmcr(void);
++extern void __vgic_v3_write_vmcr(u32 vmcr);
+ extern void __vgic_v3_init_lrs(void);
+ 
+ extern u32 __kvm_get_mdcr_el2(void);
+diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
+index b72dd2ad5f44..f7a2e31eb4c1 100644
+--- a/include/kvm/arm_vgic.h
++++ b/include/kvm/arm_vgic.h
+@@ -306,6 +306,9 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
+ 
+ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
+ 
++void kvm_vgic_load(struct kvm_vcpu *vcpu);
++void kvm_vgic_put(struct kvm_vcpu *vcpu);
++
+ #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
+ #define vgic_initialized(k)	((k)->arch.vgic.initialized)
+ #define vgic_ready(k)		((k)->arch.vgic.ready)
+diff --git a/virt/kvm/arm/hyp/vgic-v2-sr.c b/virt/kvm/arm/hyp/vgic-v2-sr.c
+index c8aeb7b91ec8..d3d3b9b0c2c3 100644
+--- a/virt/kvm/arm/hyp/vgic-v2-sr.c
++++ b/virt/kvm/arm/hyp/vgic-v2-sr.c
+@@ -114,8 +114,6 @@ void __hyp_text __vgic_v2_save_state(struct kvm_vcpu *vcpu)
+ 	if (!base)
+ 		return;
+ 
+-	cpu_if->vgic_vmcr = readl_relaxed(base + GICH_VMCR);
+-
+ 	if (vcpu->arch.vgic_cpu.live_lrs) {
+ 		cpu_if->vgic_apr = readl_relaxed(base + GICH_APR);
+ 
+@@ -165,7 +163,6 @@ void __hyp_text __vgic_v2_restore_state(struct kvm_vcpu *vcpu)
+ 		}
+ 	}
+ 
+-	writel_relaxed(cpu_if->vgic_vmcr, base + GICH_VMCR);
+ 	vcpu->arch.vgic_cpu.live_lrs = live_lrs;
+ }
+ 
+diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
+index 3947095cc0a1..e51ee7edf953 100644
+--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
++++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
+@@ -159,8 +159,6 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
+ 	if (!cpu_if->vgic_sre)
+ 		dsb(st);
+ 
+-	cpu_if->vgic_vmcr  = read_gicreg(ICH_VMCR_EL2);
+-
+ 	if (vcpu->arch.vgic_cpu.live_lrs) {
+ 		int i;
+ 		u32 max_lr_idx, nr_pri_bits;
+@@ -261,8 +259,6 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
+ 			live_lrs |= (1 << i);
+ 	}
+ 
+-	write_gicreg(cpu_if->vgic_vmcr, ICH_VMCR_EL2);
+-
+ 	if (live_lrs) {
+ 		write_gicreg(cpu_if->vgic_hcr, ICH_HCR_EL2);
+ 
+@@ -326,3 +322,13 @@ u64 __hyp_text __vgic_v3_get_ich_vtr_el2(void)
+ {
+ 	return read_gicreg(ICH_VTR_EL2);
+ }
++
++u64 __hyp_text __vgic_v3_read_vmcr(void)
++{
++	return read_gicreg(ICH_VMCR_EL2);
++}
++
++void __hyp_text __vgic_v3_write_vmcr(u32 vmcr)
++{
++	write_gicreg(vmcr, ICH_VMCR_EL2);
++}
+diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
+index 276139a24e6f..e8e973b72ca5 100644
+--- a/virt/kvm/arm/vgic/vgic-init.c
++++ b/virt/kvm/arm/vgic/vgic-init.c
+@@ -262,6 +262,18 @@ int vgic_init(struct kvm *kvm)
+ 	vgic_debug_init(kvm);
+ 
+ 	dist->initialized = true;
++
++	/*
++	 * If we're initializing GICv2 on-demand when first running the VCPU
++	 * then we need to load the VGIC state onto the CPU.  We can detect
++	 * this easily by checking if we are in between vcpu_load and vcpu_put
++	 * when we just initialized the VGIC.
++	 */
++	preempt_disable();
++	vcpu = kvm_arm_get_running_vcpu();
++	if (vcpu)
++		kvm_vgic_load(vcpu);
++	preempt_enable();
+ out:
+ 	return ret;
+ }
+diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
+index b834ecdf3225..2f241e026c8f 100644
+--- a/virt/kvm/arm/vgic/vgic-v2.c
++++ b/virt/kvm/arm/vgic/vgic-v2.c
+@@ -184,6 +184,7 @@ void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr)
+ 
+ void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+ {
++	struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
+ 	u32 vmcr;
+ 
+ 	vmcr  = (vmcrp->ctlr << GICH_VMCR_CTRL_SHIFT) & GICH_VMCR_CTRL_MASK;
+@@ -194,12 +195,15 @@ void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+ 	vmcr |= (vmcrp->pmr << GICH_VMCR_PRIMASK_SHIFT) &
+ 		GICH_VMCR_PRIMASK_MASK;
+ 
+-	vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr = vmcr;
++	cpu_if->vgic_vmcr = vmcr;
+ }
+ 
+ void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+ {
+-	u32 vmcr = vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr;
++	struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
++	u32 vmcr;
++
++	vmcr = cpu_if->vgic_vmcr;
+ 
+ 	vmcrp->ctlr = (vmcr & GICH_VMCR_CTRL_MASK) >>
+ 			GICH_VMCR_CTRL_SHIFT;
+@@ -375,3 +379,19 @@ int vgic_v2_probe(const struct gic_kvm_info *info)
+ 
+ 	return ret;
+ }
++
++void vgic_v2_load(struct kvm_vcpu *vcpu)
++{
++	struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
++	struct vgic_dist *vgic = &vcpu->kvm->arch.vgic;
++
++	writel_relaxed(cpu_if->vgic_vmcr, vgic->vctrl_base + GICH_VMCR);
++}
++
++void vgic_v2_put(struct kvm_vcpu *vcpu)
++{
++	struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
++	struct vgic_dist *vgic = &vcpu->kvm->arch.vgic;
++
++	cpu_if->vgic_vmcr = readl_relaxed(vgic->vctrl_base + GICH_VMCR);
++}
+diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
+index be0f4c3e0142..99213d744e4f 100644
+--- a/virt/kvm/arm/vgic/vgic-v3.c
++++ b/virt/kvm/arm/vgic/vgic-v3.c
+@@ -173,6 +173,7 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
+ 
+ void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+ {
++	struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
+ 	u32 vmcr;
+ 
+ 	/*
+@@ -188,12 +189,15 @@ void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+ 	vmcr |= (vmcrp->grpen0 << ICH_VMCR_ENG0_SHIFT) & ICH_VMCR_ENG0_MASK;
+ 	vmcr |= (vmcrp->grpen1 << ICH_VMCR_ENG1_SHIFT) & ICH_VMCR_ENG1_MASK;
+ 
+-	vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr = vmcr;
++	cpu_if->vgic_vmcr = vmcr;
+ }
+ 
+ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+ {
+-	u32 vmcr = vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr;
++	struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
++	u32 vmcr;
++
++	vmcr = cpu_if->vgic_vmcr;
+ 
+ 	/*
+ 	 * Ignore the FIQen bit, because GIC emulation always implies
+@@ -386,3 +390,17 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
+ 
+ 	return 0;
+ }
++
++void vgic_v3_load(struct kvm_vcpu *vcpu)
++{
++	struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
++
++	kvm_call_hyp(__vgic_v3_write_vmcr, cpu_if->vgic_vmcr);
++}
++
++void vgic_v3_put(struct kvm_vcpu *vcpu)
++{
++	struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
++
++	cpu_if->vgic_vmcr = kvm_call_hyp(__vgic_v3_read_vmcr);
++}
+diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
+index 654dfd40e449..2ac0def57424 100644
+--- a/virt/kvm/arm/vgic/vgic.c
++++ b/virt/kvm/arm/vgic/vgic.c
+@@ -656,6 +656,28 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
+ 	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
+ }
+ 
++void kvm_vgic_load(struct kvm_vcpu *vcpu)
++{
++	if (unlikely(!vgic_initialized(vcpu->kvm)))
++		return;
++
++	if (kvm_vgic_global_state.type == VGIC_V2)
++		vgic_v2_load(vcpu);
++	else
++		vgic_v3_load(vcpu);
++}
++
++void kvm_vgic_put(struct kvm_vcpu *vcpu)
++{
++	if (unlikely(!vgic_initialized(vcpu->kvm)))
++		return;
++
++	if (kvm_vgic_global_state.type == VGIC_V2)
++		vgic_v2_put(vcpu);
++	else
++		vgic_v3_put(vcpu);
++}
++
+ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
+ {
+ 	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
+index db28f7cadab2..9afb4557c7e8 100644
+--- a/virt/kvm/arm/vgic/vgic.h
++++ b/virt/kvm/arm/vgic/vgic.h
+@@ -130,6 +130,9 @@ int vgic_v2_map_resources(struct kvm *kvm);
+ int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
+ 			     enum vgic_type);
+ 
++void vgic_v2_load(struct kvm_vcpu *vcpu);
++void vgic_v2_put(struct kvm_vcpu *vcpu);
++
+ static inline void vgic_get_irq_kref(struct vgic_irq *irq)
+ {
+ 	if (irq->intid < VGIC_MIN_LPI)
+@@ -150,6 +153,9 @@ int vgic_v3_probe(const struct gic_kvm_info *info);
+ int vgic_v3_map_resources(struct kvm *kvm);
+ int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
+ 
++void vgic_v3_load(struct kvm_vcpu *vcpu);
++void vgic_v3_put(struct kvm_vcpu *vcpu);
++
+ int vgic_register_its_iodevs(struct kvm *kvm);
+ bool vgic_has_its(struct kvm *kvm);
+ int kvm_vgic_register_its_device(void);

commit 370a0ec1819990f8e2a93df7cc9c0146980ed45f
+Author: Jintack Lim 
+Date:   Mon Mar 6 05:42:37 2017 -0800
+
+    KVM: arm/arm64: Let vcpu thread modify its own active state
+    
+    Currently, if a vcpu thread tries to change the active state of an
+    interrupt which is already on the same vcpu's AP list, it will loop
+    forever. Since the VGIC mmio handler is called after a vcpu has
+    already synced back the LR state to the struct vgic_irq, we can just
+    let it proceed safely.
+    
+    Cc: stable@vger.kernel.org
+    Reviewed-by: Marc Zyngier 
+    Signed-off-by: Jintack Lim 
+    Signed-off-by: Christoffer Dall 
+    Signed-off-by: Marc Zyngier 
+
+diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
+index 3654b4c835ef..2a5db1352722 100644
+--- a/virt/kvm/arm/vgic/vgic-mmio.c
++++ b/virt/kvm/arm/vgic/vgic-mmio.c
+@@ -180,21 +180,37 @@ unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
+ static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
+ 				    bool new_active_state)
+ {
++	struct kvm_vcpu *requester_vcpu;
+ 	spin_lock(&irq->irq_lock);
++
++	/*
++	 * The vcpu parameter here can mean multiple things depending on how
++	 * this function is called; when handling a trap from the kernel it
++	 * depends on the GIC version, and these functions are also called as
++	 * part of save/restore from userspace.
++	 *
++	 * Therefore, we have to figure out the requester in a reliable way.
++	 *
++	 * When accessing VGIC state from user space, the requester_vcpu is
++	 * NULL, which is fine, because we guarantee that no VCPUs are running
++	 * when accessing VGIC state from user space so irq->vcpu->cpu is
++	 * always -1.
++	 */
++	requester_vcpu = kvm_arm_get_running_vcpu();
++
+ 	/*
+ 	 * If this virtual IRQ was written into a list register, we
+ 	 * have to make sure the CPU that runs the VCPU thread has
+-	 * synced back LR state to the struct vgic_irq.  We can only
+-	 * know this for sure, when either this irq is not assigned to
+-	 * anyone's AP list anymore, or the VCPU thread is not
+-	 * running on any CPUs.
++	 * synced back the LR state to the struct vgic_irq.
+ 	 *
+-	 * In the opposite case, we know the VCPU thread may be on its
+-	 * way back from the guest and still has to sync back this
+-	 * IRQ, so we release and re-acquire the spin_lock to let the
+-	 * other thread sync back the IRQ.
++	 * As long as the conditions below are true, we know the VCPU thread
++	 * may be on its way back from the guest (we kicked the VCPU thread in
++	 * vgic_change_active_prepare)  and still has to sync back this IRQ,
++	 * so we release and re-acquire the spin_lock to let the other thread
++	 * sync back the IRQ.
+ 	 */
+ 	while (irq->vcpu && /* IRQ may have state in an LR somewhere */
++	       irq->vcpu != requester_vcpu && /* Current thread is not the VCPU thread */
+ 	       irq->vcpu->cpu != -1) /* VCPU thread is running */
+ 		cond_resched_lock(&irq->irq_lock);
+ 

commit 7b6b46311a8562fb3a9e035ed6ffab6d49c28886
+Author: Jintack Lim 
+Date:   Fri Feb 3 10:20:08 2017 -0500
+
+    KVM: arm/arm64: Emulate the EL1 phys timer registers
+    
+    Emulate read and write operations to CNTP_TVAL, CNTP_CVAL and CNTP_CTL.
+    Now VMs are able to use the EL1 physical timer.
+    
+    Signed-off-by: Jintack Lim 
+    Reviewed-by: Christoffer Dall 
+    Signed-off-by: Marc Zyngier 
+
+diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
+index 1cd3464ff88d..0e26f8c2b56f 100644
+--- a/arch/arm64/kvm/sys_regs.c
++++ b/arch/arm64/kvm/sys_regs.c
+@@ -824,7 +824,14 @@ static bool access_cntp_tval(struct kvm_vcpu *vcpu,
+ 		struct sys_reg_params *p,
+ 		const struct sys_reg_desc *r)
+ {
+-	kvm_inject_undefined(vcpu);
++	struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
++	u64 now = kvm_phys_timer_read();
++
++	if (p->is_write)
++		ptimer->cnt_cval = p->regval + now;
++	else
++		p->regval = ptimer->cnt_cval - now;
++
+ 	return true;
+ }
+ 
+@@ -832,7 +839,25 @@ static bool access_cntp_ctl(struct kvm_vcpu *vcpu,
+ 		struct sys_reg_params *p,
+ 		const struct sys_reg_desc *r)
+ {
+-	kvm_inject_undefined(vcpu);
++	struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
++
++	if (p->is_write) {
++		/* ISTATUS bit is read-only */
++		ptimer->cnt_ctl = p->regval & ~ARCH_TIMER_CTRL_IT_STAT;
++	} else {
++		u64 now = kvm_phys_timer_read();
++
++		p->regval = ptimer->cnt_ctl;
++		/*
++		 * Set ISTATUS bit if it's expired.
++		 * Note that according to ARMv8 ARM Issue A.k, ISTATUS bit is
++		 * UNKNOWN when ENABLE bit is 0, so we chose to set ISTATUS bit
++		 * regardless of ENABLE bit for our implementation convenience.
++		 */
++		if (ptimer->cnt_cval <= now)
++			p->regval |= ARCH_TIMER_CTRL_IT_STAT;
++	}
++
+ 	return true;
+ }
+ 
+@@ -840,7 +865,13 @@ static bool access_cntp_cval(struct kvm_vcpu *vcpu,
+ 		struct sys_reg_params *p,
+ 		const struct sys_reg_desc *r)
+ {
+-	kvm_inject_undefined(vcpu);
++	struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
++
++	if (p->is_write)
++		ptimer->cnt_cval = p->regval;
++	else
++		p->regval = ptimer->cnt_cval;
++
+ 	return true;
+ }
+ 
+diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
+index f1d2fba0b9c6..fe797d6ef89d 100644
+--- a/include/kvm/arm_arch_timer.h
++++ b/include/kvm/arm_arch_timer.h
+@@ -72,6 +72,8 @@ bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx);
+ void kvm_timer_schedule(struct kvm_vcpu *vcpu);
+ void kvm_timer_unschedule(struct kvm_vcpu *vcpu);
+ 
++u64 kvm_phys_timer_read(void);
++
+ void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu);
+ 
+ void kvm_timer_init_vhe(void);
+diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
+index 33257b560f74..35d7100e0815 100644
+--- a/virt/kvm/arm/arch_timer.c
++++ b/virt/kvm/arm/arch_timer.c
+@@ -40,7 +40,7 @@ void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu)
+ 	vcpu_vtimer(vcpu)->active_cleared_last = false;
+ }
+ 
+-static u64 kvm_phys_timer_read(void)
++u64 kvm_phys_timer_read(void)
+ {
+ 	return timecounter->cc->read(timecounter->cc);
+ }

commit c9a3c58f01fb0af78b512ab4515d16f3ef1a03f1
+Author: Jintack Lim 
+Date:   Fri Feb 3 10:20:07 2017 -0500
+
+    KVM: arm64: Add the EL1 physical timer access handler
+    
+    KVM traps on the EL1 phys timer accesses from VMs, but it doesn't handle
+    those traps. This results in terminating VMs. Instead, set a handler for
+    the EL1 phys timer access, and inject an undefined exception as an
+    intermediate step.
+    
+    Signed-off-by: Jintack Lim 
+    Reviewed-by: Christoffer Dall 
+    Signed-off-by: Marc Zyngier 
+
+diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
+index caa47ce7e006..1cd3464ff88d 100644
+--- a/arch/arm64/kvm/sys_regs.c
++++ b/arch/arm64/kvm/sys_regs.c
+@@ -820,6 +820,30 @@ static bool access_pmuserenr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+ 	  CRm((0b1100 | (((n) >> 3) & 0x3))), Op2(((n) & 0x7)),		\
+ 	  access_pmu_evtyper, reset_unknown, (PMEVTYPER0_EL0 + n), }
+ 
++static bool access_cntp_tval(struct kvm_vcpu *vcpu,
++		struct sys_reg_params *p,
++		const struct sys_reg_desc *r)
++{
++	kvm_inject_undefined(vcpu);
++	return true;
++}
++
++static bool access_cntp_ctl(struct kvm_vcpu *vcpu,
++		struct sys_reg_params *p,
++		const struct sys_reg_desc *r)
++{
++	kvm_inject_undefined(vcpu);
++	return true;
++}
++
++static bool access_cntp_cval(struct kvm_vcpu *vcpu,
++		struct sys_reg_params *p,
++		const struct sys_reg_desc *r)
++{
++	kvm_inject_undefined(vcpu);
++	return true;
++}
++
+ /*
+  * Architected system registers.
+  * Important: Must be sorted ascending by Op0, Op1, CRn, CRm, Op2
+@@ -1029,6 +1053,16 @@ static const struct sys_reg_desc sys_reg_descs[] = {
+ 	{ Op0(0b11), Op1(0b011), CRn(0b1101), CRm(0b0000), Op2(0b011),
+ 	  NULL, reset_unknown, TPIDRRO_EL0 },
+ 
++	/* CNTP_TVAL_EL0 */
++	{ Op0(0b11), Op1(0b011), CRn(0b1110), CRm(0b0010), Op2(0b000),
++	  access_cntp_tval },
++	/* CNTP_CTL_EL0 */
++	{ Op0(0b11), Op1(0b011), CRn(0b1110), CRm(0b0010), Op2(0b001),
++	  access_cntp_ctl },
++	/* CNTP_CVAL_EL0 */
++	{ Op0(0b11), Op1(0b011), CRn(0b1110), CRm(0b0010), Op2(0b010),
++	  access_cntp_cval },
++
+ 	/* PMEVCNTRn_EL0 */
+ 	PMU_PMEVCNTR_EL0(0),
+ 	PMU_PMEVCNTR_EL0(1),

commit f242adaf0c7e8376e9f54ffd6ef088df84577893
+Author: Jintack Lim 
+Date:   Fri Feb 3 10:20:06 2017 -0500
+
+    KVM: arm/arm64: Set up a background timer for the physical timer emulation
+    
+    Set a background timer for the EL1 physical timer emulation while VMs
+    are running, so that VMs get the physical timer interrupts in a timely
+    manner.
+    
+    Schedule the background timer on entry to the VM and cancel it on exit.
+    This would not have any performance impact to the guest OSes that
+    currently use the virtual timer since the physical timer is always not
+    enabled.
+    
+    Signed-off-by: Jintack Lim 
+    Reviewed-by: Christoffer Dall 
+    Signed-off-by: Marc Zyngier 
+
+diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
+index 0ea745290871..33257b560f74 100644
+--- a/virt/kvm/arm/arch_timer.c
++++ b/virt/kvm/arm/arch_timer.c
+@@ -229,6 +229,22 @@ static int kvm_timer_update_state(struct kvm_vcpu *vcpu)
+ 	return 0;
+ }
+ 
++/* Schedule the background timer for the emulated timer. */
++static void kvm_timer_emulate(struct kvm_vcpu *vcpu,
++			      struct arch_timer_context *timer_ctx)
++{
++	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
++
++	if (kvm_timer_should_fire(timer_ctx))
++		return;
++
++	if (!kvm_timer_irq_can_fire(timer_ctx))
++		return;
++
++	/*  The timer has not yet expired, schedule a background timer */
++	timer_arm(timer, kvm_timer_compute_delta(timer_ctx));
++}
++
+ /*
+  * Schedule the background timer before calling kvm_vcpu_block, so that this
+  * thread is removed from its waitqueue and made runnable when there's a timer
+@@ -286,6 +302,9 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
+ 	if (kvm_timer_update_state(vcpu))
+ 		return;
+ 
++	/* Set the background timer for the physical timer emulation. */
++	kvm_timer_emulate(vcpu, vcpu_ptimer(vcpu));
++
+ 	/*
+ 	* If we enter the guest with the virtual input level to the VGIC
+ 	* asserted, then we have already told the VGIC what we need to, and
+@@ -348,7 +367,11 @@ void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu)
+ {
+ 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+ 
+-	BUG_ON(timer_is_armed(timer));
++	/*
++	 * This is to cancel the background timer for the physical timer
++	 * emulation if it is set.
++	 */
++	timer_disarm(timer);
+ 
+ 	/*
+ 	 * The guest could have modified the timer registers or the timer

commit fb280e97576a91c01b2a1712dba31024748b3084
+Author: Jintack Lim 
+Date:   Fri Feb 3 10:20:05 2017 -0500
+
+    KVM: arm/arm64: Set a background timer to the earliest timer expiration
+    
+    When scheduling a background timer, consider both of the virtual and
+    physical timer and pick the earliest expiration time.
+    
+    Signed-off-by: Jintack Lim 
+    Reviewed-by: Christoffer Dall 
+    Signed-off-by: Marc Zyngier 
+
+diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
+index 0ecd6cf362fc..21c493a9e5c9 100644
+--- a/arch/arm/kvm/arm.c
++++ b/arch/arm/kvm/arm.c
+@@ -300,7 +300,8 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
+ 
+ int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
+ {
+-	return kvm_timer_should_fire(vcpu_vtimer(vcpu));
++	return kvm_timer_should_fire(vcpu_vtimer(vcpu)) ||
++	       kvm_timer_should_fire(vcpu_ptimer(vcpu));
+ }
+ 
+ void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu)
+diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
+index 7f9a66419991..0ea745290871 100644
+--- a/virt/kvm/arm/arch_timer.c
++++ b/virt/kvm/arm/arch_timer.c
+@@ -118,6 +118,35 @@ static u64 kvm_timer_compute_delta(struct arch_timer_context *timer_ctx)
+ 	return 0;
+ }
+ 
++static bool kvm_timer_irq_can_fire(struct arch_timer_context *timer_ctx)
++{
++	return !(timer_ctx->cnt_ctl & ARCH_TIMER_CTRL_IT_MASK) &&
++		(timer_ctx->cnt_ctl & ARCH_TIMER_CTRL_ENABLE);
++}
++
++/*
++ * Returns the earliest expiration time in ns among guest timers.
++ * Note that it will return 0 if none of timers can fire.
++ */
++static u64 kvm_timer_earliest_exp(struct kvm_vcpu *vcpu)
++{
++	u64 min_virt = ULLONG_MAX, min_phys = ULLONG_MAX;
++	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
++	struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
++
++	if (kvm_timer_irq_can_fire(vtimer))
++		min_virt = kvm_timer_compute_delta(vtimer);
++
++	if (kvm_timer_irq_can_fire(ptimer))
++		min_phys = kvm_timer_compute_delta(ptimer);
++
++	/* If none of timers can fire, then return 0 */
++	if ((min_virt == ULLONG_MAX) && (min_phys == ULLONG_MAX))
++		return 0;
++
++	return min(min_virt, min_phys);
++}
++
+ static enum hrtimer_restart kvm_timer_expire(struct hrtimer *hrt)
+ {
+ 	struct arch_timer_cpu *timer;
+@@ -132,7 +161,7 @@ static enum hrtimer_restart kvm_timer_expire(struct hrtimer *hrt)
+ 	 * PoV (NTP on the host may have forced it to expire
+ 	 * early). If we should have slept longer, restart it.
+ 	 */
+-	ns = kvm_timer_compute_delta(vcpu_vtimer(vcpu));
++	ns = kvm_timer_earliest_exp(vcpu);
+ 	if (unlikely(ns)) {
+ 		hrtimer_forward_now(hrt, ns_to_ktime(ns));
+ 		return HRTIMER_RESTART;
+@@ -142,12 +171,6 @@ static enum hrtimer_restart kvm_timer_expire(struct hrtimer *hrt)
+ 	return HRTIMER_NORESTART;
+ }
+ 
+-static bool kvm_timer_irq_can_fire(struct arch_timer_context *timer_ctx)
+-{
+-	return !(timer_ctx->cnt_ctl & ARCH_TIMER_CTRL_IT_MASK) &&
+-		(timer_ctx->cnt_ctl & ARCH_TIMER_CTRL_ENABLE);
+-}
+-
+ bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx)
+ {
+ 	u64 cval, now;
+@@ -215,26 +238,30 @@ void kvm_timer_schedule(struct kvm_vcpu *vcpu)
+ {
+ 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+ 	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
++	struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
+ 
+ 	BUG_ON(timer_is_armed(timer));
+ 
+ 	/*
+-	 * No need to schedule a background timer if the guest timer has
++	 * No need to schedule a background timer if any guest timer has
+ 	 * already expired, because kvm_vcpu_block will return before putting
+ 	 * the thread to sleep.
+ 	 */
+-	if (kvm_timer_should_fire(vtimer))
++	if (kvm_timer_should_fire(vtimer) || kvm_timer_should_fire(ptimer))
+ 		return;
+ 
+ 	/*
+-	 * If the timer is not capable of raising interrupts (disabled or
++	 * If both timers are not capable of raising interrupts (disabled or
+ 	 * masked), then there's no more work for us to do.
+ 	 */
+-	if (!kvm_timer_irq_can_fire(vtimer))
++	if (!kvm_timer_irq_can_fire(vtimer) && !kvm_timer_irq_can_fire(ptimer))
+ 		return;
+ 
+-	/*  The timer has not yet expired, schedule a background timer */
+-	timer_arm(timer, kvm_timer_compute_delta(vtimer));
++	/*
++	 * The guest timers have not yet expired, schedule a background timer.
++	 * Set the earliest expiration time among the guest timers.
++	 */
++	timer_arm(timer, kvm_timer_earliest_exp(vcpu));
+ }
+ 
+ void kvm_timer_unschedule(struct kvm_vcpu *vcpu)

commit 58e0c9732a31afdef488a41fd1edba065124f442
+Author: Jintack Lim 
+Date:   Fri Feb 3 10:20:04 2017 -0500
+
+    KVM: arm/arm64: Update the physical timer interrupt level
+    
+    Now that we maintain the EL1 physical timer register states of VMs,
+    update the physical timer interrupt level along with the virtual one.
+    
+    Signed-off-by: Jintack Lim 
+    Acked-by: Christoffer Dall 
+    Signed-off-by: Marc Zyngier 
+
+diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
+index dbd0af19d27e..7f9a66419991 100644
+--- a/virt/kvm/arm/arch_timer.c
++++ b/virt/kvm/arm/arch_timer.c
+@@ -186,6 +186,7 @@ static int kvm_timer_update_state(struct kvm_vcpu *vcpu)
+ {
+ 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+ 	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
++	struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
+ 
+ 	/*
+ 	 * If userspace modified the timer registers via SET_ONE_REG before
+@@ -199,6 +200,9 @@ static int kvm_timer_update_state(struct kvm_vcpu *vcpu)
+ 	if (kvm_timer_should_fire(vtimer) != vtimer->irq.level)
+ 		kvm_timer_update_irq(vcpu, !vtimer->irq.level, vtimer);
+ 
++	if (kvm_timer_should_fire(ptimer) != ptimer->irq.level)
++		kvm_timer_update_irq(vcpu, !ptimer->irq.level, ptimer);
++
+ 	return 0;
+ }
+ 

commit a91d18551e7b35e34a04b6fd199ca8568e7e9315
+Author: Jintack Lim 
+Date:   Fri Feb 3 10:20:03 2017 -0500
+
+    KVM: arm/arm64: Initialize the emulated EL1 physical timer
+    
+    Initialize the emulated EL1 physical timer with the default irq number.
+    
+    Signed-off-by: Jintack Lim 
+    Reviewed-by: Christoffer Dall 
+    Signed-off-by: Marc Zyngier 
+
+diff --git a/arch/arm/kvm/reset.c b/arch/arm/kvm/reset.c
+index 4b5e802e57d1..1da8b2d14550 100644
+--- a/arch/arm/kvm/reset.c
++++ b/arch/arm/kvm/reset.c
+@@ -37,6 +37,11 @@ static struct kvm_regs cortexa_regs_reset = {
+ 	.usr_regs.ARM_cpsr = SVC_MODE | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT,
+ };
+ 
++static const struct kvm_irq_level cortexa_ptimer_irq = {
++	{ .irq = 30 },
++	.level = 1,
++};
++
+ static const struct kvm_irq_level cortexa_vtimer_irq = {
+ 	{ .irq = 27 },
+ 	.level = 1,
+@@ -58,6 +63,7 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
+ {
+ 	struct kvm_regs *reset_regs;
+ 	const struct kvm_irq_level *cpu_vtimer_irq;
++	const struct kvm_irq_level *cpu_ptimer_irq;
+ 
+ 	switch (vcpu->arch.target) {
+ 	case KVM_ARM_TARGET_CORTEX_A7:
+@@ -65,6 +71,7 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
+ 		reset_regs = &cortexa_regs_reset;
+ 		vcpu->arch.midr = read_cpuid_id();
+ 		cpu_vtimer_irq = &cortexa_vtimer_irq;
++		cpu_ptimer_irq = &cortexa_ptimer_irq;
+ 		break;
+ 	default:
+ 		return -ENODEV;
+@@ -77,5 +84,5 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
+ 	kvm_reset_coprocs(vcpu);
+ 
+ 	/* Reset arch_timer context */
+-	return kvm_timer_vcpu_reset(vcpu, cpu_vtimer_irq);
++	return kvm_timer_vcpu_reset(vcpu, cpu_vtimer_irq, cpu_ptimer_irq);
+ }
+diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
+index e95d4f68bf54..d9e9697de1b2 100644
+--- a/arch/arm64/kvm/reset.c
++++ b/arch/arm64/kvm/reset.c
+@@ -46,6 +46,11 @@ static const struct kvm_regs default_regs_reset32 = {
+ 			COMPAT_PSR_I_BIT | COMPAT_PSR_F_BIT),
+ };
+ 
++static const struct kvm_irq_level default_ptimer_irq = {
++	.irq	= 30,
++	.level	= 1,
++};
++
+ static const struct kvm_irq_level default_vtimer_irq = {
+ 	.irq	= 27,
+ 	.level	= 1,
+@@ -104,6 +109,7 @@ int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext)
+ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
+ {
+ 	const struct kvm_irq_level *cpu_vtimer_irq;
++	const struct kvm_irq_level *cpu_ptimer_irq;
+ 	const struct kvm_regs *cpu_reset;
+ 
+ 	switch (vcpu->arch.target) {
+@@ -117,6 +123,7 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
+ 		}
+ 
+ 		cpu_vtimer_irq = &default_vtimer_irq;
++		cpu_ptimer_irq = &default_ptimer_irq;
+ 		break;
+ 	}
+ 
+@@ -130,5 +137,5 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
+ 	kvm_pmu_vcpu_reset(vcpu);
+ 
+ 	/* Reset timer */
+-	return kvm_timer_vcpu_reset(vcpu, cpu_vtimer_irq);
++	return kvm_timer_vcpu_reset(vcpu, cpu_vtimer_irq, cpu_ptimer_irq);
+ }
+diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
+index 6445a3d9a6e2..f1d2fba0b9c6 100644
+--- a/include/kvm/arm_arch_timer.h
++++ b/include/kvm/arm_arch_timer.h
+@@ -58,7 +58,8 @@ struct arch_timer_cpu {
+ int kvm_timer_hyp_init(void);
+ int kvm_timer_enable(struct kvm_vcpu *vcpu);
+ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
+-			 const struct kvm_irq_level *irq);
++			 const struct kvm_irq_level *virt_irq,
++			 const struct kvm_irq_level *phys_irq);
+ void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu);
+ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu);
+ void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu);
+diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
+index 5261f98ae686..dbd0af19d27e 100644
+--- a/virt/kvm/arm/arch_timer.c
++++ b/virt/kvm/arm/arch_timer.c
+@@ -327,9 +327,11 @@ void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu)
+ }
+ 
+ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
+-			 const struct kvm_irq_level *irq)
++			 const struct kvm_irq_level *virt_irq,
++			 const struct kvm_irq_level *phys_irq)
+ {
+ 	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
++	struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
+ 
+ 	/*
+ 	 * The vcpu timer irq number cannot be determined in
+@@ -337,7 +339,8 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
+ 	 * kvm_vcpu_set_target(). To handle this, we determine
+ 	 * vcpu timer irq number when the vcpu is reset.
+ 	 */
+-	vtimer->irq.irq = irq->irq;
++	vtimer->irq.irq = virt_irq->irq;
++	ptimer->irq.irq = phys_irq->irq;
+ 
+ 	/*
+ 	 * The bits in CNTV_CTL are architecturally reset to UNKNOWN for ARMv8
+@@ -346,6 +349,7 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
+ 	 * the ARMv7 architecture.
+ 	 */
+ 	vtimer->cnt_ctl = 0;
++	ptimer->cnt_ctl = 0;
+ 	kvm_timer_update_state(vcpu);
+ 
+ 	return 0;
+@@ -376,6 +380,7 @@ void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
+ 
+ 	/* Synchronize cntvoff across all vtimers of a VM. */
+ 	update_vtimer_cntvoff(vcpu, kvm_phys_timer_read());
++	vcpu_ptimer(vcpu)->cntvoff = 0;
+ 
+ 	INIT_WORK(&timer->expired, kvm_timer_inject_irq_work);
+ 	hrtimer_init(&timer->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);

commit 009a5701bb2d166073f75643bc9237fe014c6bf5
+Author: Jintack Lim 
+Date:   Fri Feb 3 10:20:02 2017 -0500
+
+    KVM: arm/arm64: Add the EL1 physical timer context
+    
+    Add the EL1 physical timer context.
+    
+    Signed-off-by: Jintack Lim 
+    Acked-by: Christoffer Dall 
+    Signed-off-by: Marc Zyngier 
+
+diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
+index f46fa3b62b06..6445a3d9a6e2 100644
+--- a/include/kvm/arm_arch_timer.h
++++ b/include/kvm/arm_arch_timer.h
+@@ -40,6 +40,7 @@ struct arch_timer_context {
+ 
+ struct arch_timer_cpu {
+ 	struct arch_timer_context	vtimer;
++	struct arch_timer_context	ptimer;
+ 
+ 	/* Background timer used when the guest is not running */
+ 	struct hrtimer			timer;
+@@ -75,4 +76,5 @@ void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu);
+ void kvm_timer_init_vhe(void);
+ 
+ #define vcpu_vtimer(v)	(&(v)->arch.timer_cpu.vtimer)
++#define vcpu_ptimer(v)	(&(v)->arch.timer_cpu.ptimer)
+ #endif

commit 9171fa2e0951b0cb6c443e0dce2c4620de3b1dfe
+Author: Jintack Lim 
+Date:   Fri Feb 3 10:20:01 2017 -0500
+
+    KVM: arm/arm64: Decouple kvm timer functions from virtual timer
+    
+    Now that we have a separate structure for timer context, make functions
+    generic so that they can work with any timer context, not just the
+    virtual timer context.  This does not change the virtual timer
+    functionality.
+    
+    Signed-off-by: Jintack Lim 
+    Acked-by: Marc Zyngier 
+    Acked-by: Christoffer Dall 
+    Signed-off-by: Marc Zyngier 
+
+diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
+index f93f2171a48b..0ecd6cf362fc 100644
+--- a/arch/arm/kvm/arm.c
++++ b/arch/arm/kvm/arm.c
+@@ -300,7 +300,7 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
+ 
+ int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
+ {
+-	return kvm_timer_should_fire(vcpu);
++	return kvm_timer_should_fire(vcpu_vtimer(vcpu));
+ }
+ 
+ void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu)
+diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
+index 2c8560b4642a..f46fa3b62b06 100644
+--- a/include/kvm/arm_arch_timer.h
++++ b/include/kvm/arm_arch_timer.h
+@@ -66,7 +66,7 @@ void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu);
+ u64 kvm_arm_timer_get_reg(struct kvm_vcpu *, u64 regid);
+ int kvm_arm_timer_set_reg(struct kvm_vcpu *, u64 regid, u64 value);
+ 
+-bool kvm_timer_should_fire(struct kvm_vcpu *vcpu);
++bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx);
+ void kvm_timer_schedule(struct kvm_vcpu *vcpu);
+ void kvm_timer_unschedule(struct kvm_vcpu *vcpu);
+ 
+diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
+index 5004a679b125..5261f98ae686 100644
+--- a/virt/kvm/arm/arch_timer.c
++++ b/virt/kvm/arm/arch_timer.c
+@@ -98,13 +98,12 @@ static void kvm_timer_inject_irq_work(struct work_struct *work)
+ 	kvm_vcpu_kick(vcpu);
+ }
+ 
+-static u64 kvm_timer_compute_delta(struct kvm_vcpu *vcpu)
++static u64 kvm_timer_compute_delta(struct arch_timer_context *timer_ctx)
+ {
+ 	u64 cval, now;
+-	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+ 
+-	cval = vtimer->cnt_cval;
+-	now = kvm_phys_timer_read() - vtimer->cntvoff;
++	cval = timer_ctx->cnt_cval;
++	now = kvm_phys_timer_read() - timer_ctx->cntvoff;
+ 
+ 	if (now < cval) {
+ 		u64 ns;
+@@ -133,7 +132,7 @@ static enum hrtimer_restart kvm_timer_expire(struct hrtimer *hrt)
+ 	 * PoV (NTP on the host may have forced it to expire
+ 	 * early). If we should have slept longer, restart it.
+ 	 */
+-	ns = kvm_timer_compute_delta(vcpu);
++	ns = kvm_timer_compute_delta(vcpu_vtimer(vcpu));
+ 	if (unlikely(ns)) {
+ 		hrtimer_forward_now(hrt, ns_to_ktime(ns));
+ 		return HRTIMER_RESTART;
+@@ -143,43 +142,39 @@ static enum hrtimer_restart kvm_timer_expire(struct hrtimer *hrt)
+ 	return HRTIMER_NORESTART;
+ }
+ 
+-static bool kvm_timer_irq_can_fire(struct kvm_vcpu *vcpu)
++static bool kvm_timer_irq_can_fire(struct arch_timer_context *timer_ctx)
+ {
+-	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+-
+-	return !(vtimer->cnt_ctl & ARCH_TIMER_CTRL_IT_MASK) &&
+-		(vtimer->cnt_ctl & ARCH_TIMER_CTRL_ENABLE);
++	return !(timer_ctx->cnt_ctl & ARCH_TIMER_CTRL_IT_MASK) &&
++		(timer_ctx->cnt_ctl & ARCH_TIMER_CTRL_ENABLE);
+ }
+ 
+-bool kvm_timer_should_fire(struct kvm_vcpu *vcpu)
++bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx)
+ {
+-	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+ 	u64 cval, now;
+ 
+-	if (!kvm_timer_irq_can_fire(vcpu))
++	if (!kvm_timer_irq_can_fire(timer_ctx))
+ 		return false;
+ 
+-	cval = vtimer->cnt_cval;
+-	now = kvm_phys_timer_read() - vtimer->cntvoff;
++	cval = timer_ctx->cnt_cval;
++	now = kvm_phys_timer_read() - timer_ctx->cntvoff;
+ 
+ 	return cval <= now;
+ }
+ 
+-static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level)
++static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level,
++				 struct arch_timer_context *timer_ctx)
+ {
+ 	int ret;
+-	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+ 
+ 	BUG_ON(!vgic_initialized(vcpu->kvm));
+ 
+-	vtimer->active_cleared_last = false;
+-	vtimer->irq.level = new_level;
+-	trace_kvm_timer_update_irq(vcpu->vcpu_id, vtimer->irq.irq,
+-				   vtimer->irq.level);
++	timer_ctx->active_cleared_last = false;
++	timer_ctx->irq.level = new_level;
++	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer_ctx->irq.irq,
++				   timer_ctx->irq.level);
+ 
+-	ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id,
+-					 vtimer->irq.irq,
+-					 vtimer->irq.level);
++	ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id, timer_ctx->irq.irq,
++				  timer_ctx->irq.level);
+ 	WARN_ON(ret);
+ }
+ 
+@@ -201,8 +196,8 @@ static int kvm_timer_update_state(struct kvm_vcpu *vcpu)
+ 	if (!vgic_initialized(vcpu->kvm) || !timer->enabled)
+ 		return -ENODEV;
+ 
+-	if (kvm_timer_should_fire(vcpu) != vtimer->irq.level)
+-		kvm_timer_update_irq(vcpu, !vtimer->irq.level);
++	if (kvm_timer_should_fire(vtimer) != vtimer->irq.level)
++		kvm_timer_update_irq(vcpu, !vtimer->irq.level, vtimer);
+ 
+ 	return 0;
+ }
+@@ -215,6 +210,7 @@ static int kvm_timer_update_state(struct kvm_vcpu *vcpu)
+ void kvm_timer_schedule(struct kvm_vcpu *vcpu)
+ {
+ 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
++	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+ 
+ 	BUG_ON(timer_is_armed(timer));
+ 
+@@ -223,18 +219,18 @@ void kvm_timer_schedule(struct kvm_vcpu *vcpu)
+ 	 * already expired, because kvm_vcpu_block will return before putting
+ 	 * the thread to sleep.
+ 	 */
+-	if (kvm_timer_should_fire(vcpu))
++	if (kvm_timer_should_fire(vtimer))
+ 		return;
+ 
+ 	/*
+ 	 * If the timer is not capable of raising interrupts (disabled or
+ 	 * masked), then there's no more work for us to do.
+ 	 */
+-	if (!kvm_timer_irq_can_fire(vcpu))
++	if (!kvm_timer_irq_can_fire(vtimer))
+ 		return;
+ 
+ 	/*  The timer has not yet expired, schedule a background timer */
+-	timer_arm(timer, kvm_timer_compute_delta(vcpu));
++	timer_arm(timer, kvm_timer_compute_delta(vtimer));
+ }
+ 
+ void kvm_timer_unschedule(struct kvm_vcpu *vcpu)

commit 90de943a430028ee389b22bf4a7ae5867c32ce0c
+Author: Jintack Lim 
+Date:   Fri Feb 3 10:20:00 2017 -0500
+
+    KVM: arm/arm64: Move cntvoff to each timer context
+    
+    Make cntvoff per each timer context. This is helpful to abstract kvm
+    timer functions to work with timer context without considering timer
+    types (e.g. physical timer or virtual timer).
+    
+    This also would pave the way for ever doing adjustments of the cntvoff
+    on a per-CPU basis if that should ever make sense.
+    
+    Signed-off-by: Jintack Lim 
+    Signed-off-by: Christoffer Dall 
+    Signed-off-by: Marc Zyngier 
+
+diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
+index d5423ab15ed5..cc495d799c67 100644
+--- a/arch/arm/include/asm/kvm_host.h
++++ b/arch/arm/include/asm/kvm_host.h
+@@ -60,9 +60,6 @@ struct kvm_arch {
+ 	/* The last vcpu id that ran on each physical CPU */
+ 	int __percpu *last_vcpu_ran;
+ 
+-	/* Timer */
+-	struct arch_timer_kvm	timer;
+-
+ 	/*
+ 	 * Anything that is not used directly from assembly code goes
+ 	 * here.
+diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
+index 9d7446456e0c..f93f2171a48b 100644
+--- a/arch/arm/kvm/arm.c
++++ b/arch/arm/kvm/arm.c
+@@ -135,7 +135,6 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
+ 		goto out_free_stage2_pgd;
+ 
+ 	kvm_vgic_early_init(kvm);
+-	kvm_timer_init(kvm);
+ 
+ 	/* Mark the initial VMID generation invalid */
+ 	kvm->arch.vmid_gen = 0;
+diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
+index e5050388e062..4a758cba1262 100644
+--- a/arch/arm64/include/asm/kvm_host.h
++++ b/arch/arm64/include/asm/kvm_host.h
+@@ -70,9 +70,6 @@ struct kvm_arch {
+ 
+ 	/* Interrupt controller */
+ 	struct vgic_dist	vgic;
+-
+-	/* Timer */
+-	struct arch_timer_kvm	timer;
+ };
+ 
+ #define KVM_NR_MEM_OBJS     40
+diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
+index daad3c133b9f..2c8560b4642a 100644
+--- a/include/kvm/arm_arch_timer.h
++++ b/include/kvm/arm_arch_timer.h
+@@ -23,11 +23,6 @@
+ #include 
+ #include 
+ 
+-struct arch_timer_kvm {
+-	/* Virtual offset */
+-	u64			cntvoff;
+-};
+-
+ struct arch_timer_context {
+ 	/* Registers: control register, timer value */
+ 	u32				cnt_ctl;
+@@ -38,6 +33,9 @@ struct arch_timer_context {
+ 
+ 	/* Active IRQ state caching */
+ 	bool				active_cleared_last;
++
++	/* Virtual offset */
++	u64			cntvoff;
+ };
+ 
+ struct arch_timer_cpu {
+@@ -58,7 +56,6 @@ struct arch_timer_cpu {
+ 
+ int kvm_timer_hyp_init(void);
+ int kvm_timer_enable(struct kvm_vcpu *vcpu);
+-void kvm_timer_init(struct kvm *kvm);
+ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
+ 			 const struct kvm_irq_level *irq);
+ void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu);
+diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
+index d3556b3ca694..5004a679b125 100644
+--- a/virt/kvm/arm/arch_timer.c
++++ b/virt/kvm/arm/arch_timer.c
+@@ -101,9 +101,10 @@ static void kvm_timer_inject_irq_work(struct work_struct *work)
+ static u64 kvm_timer_compute_delta(struct kvm_vcpu *vcpu)
+ {
+ 	u64 cval, now;
++	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+ 
+-	cval = vcpu_vtimer(vcpu)->cnt_cval;
+-	now = kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff;
++	cval = vtimer->cnt_cval;
++	now = kvm_phys_timer_read() - vtimer->cntvoff;
+ 
+ 	if (now < cval) {
+ 		u64 ns;
+@@ -159,7 +160,7 @@ bool kvm_timer_should_fire(struct kvm_vcpu *vcpu)
+ 		return false;
+ 
+ 	cval = vtimer->cnt_cval;
+-	now = kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff;
++	now = kvm_phys_timer_read() - vtimer->cntvoff;
+ 
+ 	return cval <= now;
+ }
+@@ -354,10 +355,32 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
+ 	return 0;
+ }
+ 
++/* Make the updates of cntvoff for all vtimer contexts atomic */
++static void update_vtimer_cntvoff(struct kvm_vcpu *vcpu, u64 cntvoff)
++{
++	int i;
++	struct kvm *kvm = vcpu->kvm;
++	struct kvm_vcpu *tmp;
++
++	mutex_lock(&kvm->lock);
++	kvm_for_each_vcpu(i, tmp, kvm)
++		vcpu_vtimer(tmp)->cntvoff = cntvoff;
++
++	/*
++	 * When called from the vcpu create path, the CPU being created is not
++	 * included in the loop above, so we just set it here as well.
++	 */
++	vcpu_vtimer(vcpu)->cntvoff = cntvoff;
++	mutex_unlock(&kvm->lock);
++}
++
+ void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
+ {
+ 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+ 
++	/* Synchronize cntvoff across all vtimers of a VM. */
++	update_vtimer_cntvoff(vcpu, kvm_phys_timer_read());
++
+ 	INIT_WORK(&timer->expired, kvm_timer_inject_irq_work);
+ 	hrtimer_init(&timer->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+ 	timer->timer.function = kvm_timer_expire;
+@@ -377,7 +400,7 @@ int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
+ 		vtimer->cnt_ctl = value;
+ 		break;
+ 	case KVM_REG_ARM_TIMER_CNT:
+-		vcpu->kvm->arch.timer.cntvoff = kvm_phys_timer_read() - value;
++		update_vtimer_cntvoff(vcpu, kvm_phys_timer_read() - value);
+ 		break;
+ 	case KVM_REG_ARM_TIMER_CVAL:
+ 		vtimer->cnt_cval = value;
+@@ -398,7 +421,7 @@ u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid)
+ 	case KVM_REG_ARM_TIMER_CTL:
+ 		return vtimer->cnt_ctl;
+ 	case KVM_REG_ARM_TIMER_CNT:
+-		return kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff;
++		return kvm_phys_timer_read() - vtimer->cntvoff;
+ 	case KVM_REG_ARM_TIMER_CVAL:
+ 		return vtimer->cnt_cval;
+ 	}
+@@ -510,11 +533,6 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
+ 	return 0;
+ }
+ 
+-void kvm_timer_init(struct kvm *kvm)
+-{
+-	kvm->arch.timer.cntvoff = kvm_phys_timer_read();
+-}
+-
+ /*
+  * On VHE system, we only need to configure trap on physical timer and counter
+  * accesses in EL0 and EL1 once, not for every world switch.
+diff --git a/virt/kvm/arm/hyp/timer-sr.c b/virt/kvm/arm/hyp/timer-sr.c
+index 0cf08953e81c..4734915ab71f 100644
+--- a/virt/kvm/arm/hyp/timer-sr.c
++++ b/virt/kvm/arm/hyp/timer-sr.c
+@@ -53,7 +53,6 @@ void __hyp_text __timer_save_state(struct kvm_vcpu *vcpu)
+ 
+ void __hyp_text __timer_restore_state(struct kvm_vcpu *vcpu)
+ {
+-	struct kvm *kvm = kern_hyp_va(vcpu->kvm);
+ 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+ 	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+ 	u64 val;
+@@ -71,7 +70,7 @@ void __hyp_text __timer_restore_state(struct kvm_vcpu *vcpu)
+ 	}
+ 
+ 	if (timer->enabled) {
+-		write_sysreg(kvm->arch.timer.cntvoff, cntvoff_el2);
++		write_sysreg(vtimer->cntvoff, cntvoff_el2);
+ 		write_sysreg_el0(vtimer->cnt_cval, cntv_cval);
+ 		isb();
+ 		write_sysreg_el0(vtimer->cnt_ctl, cntv_ctl);

commit fbb4aeec5fc2ab47615b2a0cbabc503e1eef4c60
+Author: Jintack Lim 
+Date:   Fri Feb 3 10:19:59 2017 -0500
+
+    KVM: arm/arm64: Abstract virtual timer context into separate structure
+    
+    Abstract virtual timer context into a separate structure and change all
+    callers referring to timer registers, irq state and so on. No change in
+    functionality.
+    
+    This is about to become very handy when adding the EL1 physical timer.
+    
+    Signed-off-by: Jintack Lim 
+    Acked-by: Christoffer Dall 
+    Acked-by: Marc Zyngier 
+    Signed-off-by: Marc Zyngier 
+
+diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
+index 5c970ce67949..daad3c133b9f 100644
+--- a/include/kvm/arm_arch_timer.h
++++ b/include/kvm/arm_arch_timer.h
+@@ -28,15 +28,20 @@ struct arch_timer_kvm {
+ 	u64			cntvoff;
+ };
+ 
+-struct arch_timer_cpu {
++struct arch_timer_context {
+ 	/* Registers: control register, timer value */
+-	u32				cntv_ctl;	/* Saved/restored */
+-	u64				cntv_cval;	/* Saved/restored */
++	u32				cnt_ctl;
++	u64				cnt_cval;
++
++	/* Timer IRQ */
++	struct kvm_irq_level		irq;
++
++	/* Active IRQ state caching */
++	bool				active_cleared_last;
++};
+ 
+-	/*
+-	 * Anything that is not used directly from assembly code goes
+-	 * here.
+-	 */
++struct arch_timer_cpu {
++	struct arch_timer_context	vtimer;
+ 
+ 	/* Background timer used when the guest is not running */
+ 	struct hrtimer			timer;
+@@ -47,12 +52,6 @@ struct arch_timer_cpu {
+ 	/* Background timer active */
+ 	bool				armed;
+ 
+-	/* Timer IRQ */
+-	struct kvm_irq_level		irq;
+-
+-	/* Active IRQ state caching */
+-	bool				active_cleared_last;
+-
+ 	/* Is the timer enabled */
+ 	bool			enabled;
+ };
+@@ -77,4 +76,6 @@ void kvm_timer_unschedule(struct kvm_vcpu *vcpu);
+ void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu);
+ 
+ void kvm_timer_init_vhe(void);
++
++#define vcpu_vtimer(v)	(&(v)->arch.timer_cpu.vtimer)
+ #endif
+diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
+index 91ecf48f7fe2..d3556b3ca694 100644
+--- a/virt/kvm/arm/arch_timer.c
++++ b/virt/kvm/arm/arch_timer.c
+@@ -37,7 +37,7 @@ static u32 host_vtimer_irq_flags;
+ 
+ void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu)
+ {
+-	vcpu->arch.timer_cpu.active_cleared_last = false;
++	vcpu_vtimer(vcpu)->active_cleared_last = false;
+ }
+ 
+ static u64 kvm_phys_timer_read(void)
+@@ -102,7 +102,7 @@ static u64 kvm_timer_compute_delta(struct kvm_vcpu *vcpu)
+ {
+ 	u64 cval, now;
+ 
+-	cval = vcpu->arch.timer_cpu.cntv_cval;
++	cval = vcpu_vtimer(vcpu)->cnt_cval;
+ 	now = kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff;
+ 
+ 	if (now < cval) {
+@@ -144,21 +144,21 @@ static enum hrtimer_restart kvm_timer_expire(struct hrtimer *hrt)
+ 
+ static bool kvm_timer_irq_can_fire(struct kvm_vcpu *vcpu)
+ {
+-	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
++	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+ 
+-	return !(timer->cntv_ctl & ARCH_TIMER_CTRL_IT_MASK) &&
+-		(timer->cntv_ctl & ARCH_TIMER_CTRL_ENABLE);
++	return !(vtimer->cnt_ctl & ARCH_TIMER_CTRL_IT_MASK) &&
++		(vtimer->cnt_ctl & ARCH_TIMER_CTRL_ENABLE);
+ }
+ 
+ bool kvm_timer_should_fire(struct kvm_vcpu *vcpu)
+ {
+-	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
++	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+ 	u64 cval, now;
+ 
+ 	if (!kvm_timer_irq_can_fire(vcpu))
+ 		return false;
+ 
+-	cval = timer->cntv_cval;
++	cval = vtimer->cnt_cval;
+ 	now = kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff;
+ 
+ 	return cval <= now;
+@@ -167,18 +167,18 @@ bool kvm_timer_should_fire(struct kvm_vcpu *vcpu)
+ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level)
+ {
+ 	int ret;
+-	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
++	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+ 
+ 	BUG_ON(!vgic_initialized(vcpu->kvm));
+ 
+-	timer->active_cleared_last = false;
+-	timer->irq.level = new_level;
+-	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->irq.irq,
+-				   timer->irq.level);
++	vtimer->active_cleared_last = false;
++	vtimer->irq.level = new_level;
++	trace_kvm_timer_update_irq(vcpu->vcpu_id, vtimer->irq.irq,
++				   vtimer->irq.level);
+ 
+ 	ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id,
+-					 timer->irq.irq,
+-					 timer->irq.level);
++					 vtimer->irq.irq,
++					 vtimer->irq.level);
+ 	WARN_ON(ret);
+ }
+ 
+@@ -189,18 +189,19 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level)
+ static int kvm_timer_update_state(struct kvm_vcpu *vcpu)
+ {
+ 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
++	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+ 
+ 	/*
+ 	 * If userspace modified the timer registers via SET_ONE_REG before
+-	 * the vgic was initialized, we mustn't set the timer->irq.level value
++	 * the vgic was initialized, we mustn't set the vtimer->irq.level value
+ 	 * because the guest would never see the interrupt.  Instead wait
+ 	 * until we call this function from kvm_timer_flush_hwstate.
+ 	 */
+ 	if (!vgic_initialized(vcpu->kvm) || !timer->enabled)
+ 		return -ENODEV;
+ 
+-	if (kvm_timer_should_fire(vcpu) != timer->irq.level)
+-		kvm_timer_update_irq(vcpu, !timer->irq.level);
++	if (kvm_timer_should_fire(vcpu) != vtimer->irq.level)
++		kvm_timer_update_irq(vcpu, !vtimer->irq.level);
+ 
+ 	return 0;
+ }
+@@ -250,7 +251,7 @@ void kvm_timer_unschedule(struct kvm_vcpu *vcpu)
+  */
+ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
+ {
+-	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
++	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+ 	bool phys_active;
+ 	int ret;
+ 
+@@ -274,8 +275,8 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
+ 	* to ensure that hardware interrupts from the timer triggers a guest
+ 	* exit.
+ 	*/
+-	phys_active = timer->irq.level ||
+-			kvm_vgic_map_is_active(vcpu, timer->irq.irq);
++	phys_active = vtimer->irq.level ||
++			kvm_vgic_map_is_active(vcpu, vtimer->irq.irq);
+ 
+ 	/*
+ 	 * We want to avoid hitting the (re)distributor as much as
+@@ -297,7 +298,7 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
+ 	 * - cached value is "active clear"
+ 	 * - value to be programmed is "active clear"
+ 	 */
+-	if (timer->active_cleared_last && !phys_active)
++	if (vtimer->active_cleared_last && !phys_active)
+ 		return;
+ 
+ 	ret = irq_set_irqchip_state(host_vtimer_irq,
+@@ -305,7 +306,7 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
+ 				    phys_active);
+ 	WARN_ON(ret);
+ 
+-	timer->active_cleared_last = !phys_active;
++	vtimer->active_cleared_last = !phys_active;
+ }
+ 
+ /**
+@@ -331,7 +332,7 @@ void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu)
+ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
+ 			 const struct kvm_irq_level *irq)
+ {
+-	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
++	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+ 
+ 	/*
+ 	 * The vcpu timer irq number cannot be determined in
+@@ -339,7 +340,7 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
+ 	 * kvm_vcpu_set_target(). To handle this, we determine
+ 	 * vcpu timer irq number when the vcpu is reset.
+ 	 */
+-	timer->irq.irq = irq->irq;
++	vtimer->irq.irq = irq->irq;
+ 
+ 	/*
+ 	 * The bits in CNTV_CTL are architecturally reset to UNKNOWN for ARMv8
+@@ -347,7 +348,7 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
+ 	 * resets the timer to be disabled and unmasked and is compliant with
+ 	 * the ARMv7 architecture.
+ 	 */
+-	timer->cntv_ctl = 0;
++	vtimer->cnt_ctl = 0;
+ 	kvm_timer_update_state(vcpu);
+ 
+ 	return 0;
+@@ -369,17 +370,17 @@ static void kvm_timer_init_interrupt(void *info)
+ 
+ int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
+ {
+-	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
++	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+ 
+ 	switch (regid) {
+ 	case KVM_REG_ARM_TIMER_CTL:
+-		timer->cntv_ctl = value;
++		vtimer->cnt_ctl = value;
+ 		break;
+ 	case KVM_REG_ARM_TIMER_CNT:
+ 		vcpu->kvm->arch.timer.cntvoff = kvm_phys_timer_read() - value;
+ 		break;
+ 	case KVM_REG_ARM_TIMER_CVAL:
+-		timer->cntv_cval = value;
++		vtimer->cnt_cval = value;
+ 		break;
+ 	default:
+ 		return -1;
+@@ -391,15 +392,15 @@ int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
+ 
+ u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid)
+ {
+-	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
++	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+ 
+ 	switch (regid) {
+ 	case KVM_REG_ARM_TIMER_CTL:
+-		return timer->cntv_ctl;
++		return vtimer->cnt_ctl;
+ 	case KVM_REG_ARM_TIMER_CNT:
+ 		return kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff;
+ 	case KVM_REG_ARM_TIMER_CVAL:
+-		return timer->cntv_cval;
++		return vtimer->cnt_cval;
+ 	}
+ 	return (u64)-1;
+ }
+@@ -463,14 +464,16 @@ int kvm_timer_hyp_init(void)
+ void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
+ {
+ 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
++	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+ 
+ 	timer_disarm(timer);
+-	kvm_vgic_unmap_phys_irq(vcpu, timer->irq.irq);
++	kvm_vgic_unmap_phys_irq(vcpu, vtimer->irq.irq);
+ }
+ 
+ int kvm_timer_enable(struct kvm_vcpu *vcpu)
+ {
+ 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
++	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+ 	struct irq_desc *desc;
+ 	struct irq_data *data;
+ 	int phys_irq;
+@@ -498,7 +501,7 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
+ 	 * Tell the VGIC that the virtual interrupt is tied to a
+ 	 * physical interrupt. We do that once per VCPU.
+ 	 */
+-	ret = kvm_vgic_map_phys_irq(vcpu, timer->irq.irq, phys_irq);
++	ret = kvm_vgic_map_phys_irq(vcpu, vtimer->irq.irq, phys_irq);
+ 	if (ret)
+ 		return ret;
+ 
+diff --git a/virt/kvm/arm/hyp/timer-sr.c b/virt/kvm/arm/hyp/timer-sr.c
+index 63e28dd18bb0..0cf08953e81c 100644
+--- a/virt/kvm/arm/hyp/timer-sr.c
++++ b/virt/kvm/arm/hyp/timer-sr.c
+@@ -25,11 +25,12 @@
+ void __hyp_text __timer_save_state(struct kvm_vcpu *vcpu)
+ {
+ 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
++	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+ 	u64 val;
+ 
+ 	if (timer->enabled) {
+-		timer->cntv_ctl = read_sysreg_el0(cntv_ctl);
+-		timer->cntv_cval = read_sysreg_el0(cntv_cval);
++		vtimer->cnt_ctl = read_sysreg_el0(cntv_ctl);
++		vtimer->cnt_cval = read_sysreg_el0(cntv_cval);
+ 	}
+ 
+ 	/* Disable the virtual timer */
+@@ -54,6 +55,7 @@ void __hyp_text __timer_restore_state(struct kvm_vcpu *vcpu)
+ {
+ 	struct kvm *kvm = kern_hyp_va(vcpu->kvm);
+ 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
++	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+ 	u64 val;
+ 
+ 	/* Those bits are already configured at boot on VHE-system */
+@@ -70,8 +72,8 @@ void __hyp_text __timer_restore_state(struct kvm_vcpu *vcpu)
+ 
+ 	if (timer->enabled) {
+ 		write_sysreg(kvm->arch.timer.cntvoff, cntvoff_el2);
+-		write_sysreg_el0(timer->cntv_cval, cntv_cval);
++		write_sysreg_el0(vtimer->cnt_cval, cntv_cval);
+ 		isb();
+-		write_sysreg_el0(timer->cntv_ctl, cntv_ctl);
++		write_sysreg_el0(vtimer->cnt_ctl, cntv_ctl);
+ 	}
+ }

commit 488f94d7212b00a2ec72fb886b155f1b04c5aa98
+Author: Jintack Lim 
+Date:   Thu Dec 1 14:32:05 2016 -0500
+
+    KVM: arm64: Access CNTHCTL_EL2 bit fields correctly on VHE systems
+    
+    Current KVM world switch code is unintentionally setting wrong bits to
+    CNTHCTL_EL2 when E2H == 1, which may allow guest OS to access physical
+    timer.  Bit positions of CNTHCTL_EL2 are changing depending on
+    HCR_EL2.E2H bit.  EL1PCEN and EL1PCTEN are 1st and 0th bits when E2H is
+    not set, but they are 11th and 10th bits respectively when E2H is set.
+    
+    In fact, on VHE we only need to set those bits once, not for every world
+    switch. This is because the host kernel runs in EL2 with HCR_EL2.TGE ==
+    1, which makes those bits have no effect for the host kernel execution.
+    So we just set those bits once for guests, and that's it.
+    
+    Signed-off-by: Jintack Lim 
+    Reviewed-by: Marc Zyngier 
+    Signed-off-by: Marc Zyngier 
+
+diff --git a/arch/arm/include/asm/virt.h b/arch/arm/include/asm/virt.h
+index a2e75b84e2ae..6dae1956c74d 100644
+--- a/arch/arm/include/asm/virt.h
++++ b/arch/arm/include/asm/virt.h
+@@ -80,6 +80,11 @@ static inline bool is_kernel_in_hyp_mode(void)
+ 	return false;
+ }
+ 
++static inline bool has_vhe(void)
++{
++	return false;
++}
++
+ /* The section containing the hypervisor idmap text */
+ extern char __hyp_idmap_text_start[];
+ extern char __hyp_idmap_text_end[];
+diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
+index 11676787ad49..9d7446456e0c 100644
+--- a/arch/arm/kvm/arm.c
++++ b/arch/arm/kvm/arm.c
+@@ -1099,6 +1099,9 @@ static void cpu_init_hyp_mode(void *dummy)
+ 	__cpu_init_hyp_mode(pgd_ptr, hyp_stack_ptr, vector_ptr);
+ 	__cpu_init_stage2();
+ 
++	if (is_kernel_in_hyp_mode())
++		kvm_timer_init_vhe();
++
+ 	kvm_arm_init_debug();
+ }
+ 
+diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
+index fea10736b11f..439f6b5d31f6 100644
+--- a/arch/arm64/include/asm/virt.h
++++ b/arch/arm64/include/asm/virt.h
+@@ -47,6 +47,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ /*
+  * __boot_cpu_mode records what mode CPUs were booted in.
+@@ -80,6 +81,14 @@ static inline bool is_kernel_in_hyp_mode(void)
+ 	return read_sysreg(CurrentEL) == CurrentEL_EL2;
+ }
+ 
++static inline bool has_vhe(void)
++{
++	if (cpus_have_const_cap(ARM64_HAS_VIRT_HOST_EXTN))
++		return true;
++
++	return false;
++}
++
+ #ifdef CONFIG_ARM64_VHE
+ extern void verify_cpu_run_el(void);
+ #else
+diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
+index b717ed9d2b75..5c970ce67949 100644
+--- a/include/kvm/arm_arch_timer.h
++++ b/include/kvm/arm_arch_timer.h
+@@ -76,4 +76,5 @@ void kvm_timer_unschedule(struct kvm_vcpu *vcpu);
+ 
+ void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu);
+ 
++void kvm_timer_init_vhe(void);
+ #endif
+diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
+index a7fe6062b65a..6a084cd57b88 100644
+--- a/virt/kvm/arm/arch_timer.c
++++ b/virt/kvm/arm/arch_timer.c
+@@ -24,6 +24,7 @@
+ 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ #include 
+@@ -509,3 +510,25 @@ void kvm_timer_init(struct kvm *kvm)
+ {
+ 	kvm->arch.timer.cntvoff = kvm_phys_timer_read();
+ }
++
++/*
++ * On VHE system, we only need to configure trap on physical timer and counter
++ * accesses in EL0 and EL1 once, not for every world switch.
++ * The host kernel runs at EL2 with HCR_EL2.TGE == 1,
++ * and this makes those bits have no effect for the host kernel execution.
++ */
++void kvm_timer_init_vhe(void)
++{
++	/* When HCR_EL2.E2H ==1, EL1PCEN and EL1PCTEN are shifted by 10 */
++	u32 cnthctl_shift = 10;
++	u64 val;
++
++	/*
++	 * Disallow physical timer access for the guest.
++	 * Physical counter access is allowed.
++	 */
++	val = read_sysreg(cnthctl_el2);
++	val &= ~(CNTHCTL_EL1PCEN << cnthctl_shift);
++	val |= (CNTHCTL_EL1PCTEN << cnthctl_shift);
++	write_sysreg(val, cnthctl_el2);
++}
+diff --git a/virt/kvm/arm/hyp/timer-sr.c b/virt/kvm/arm/hyp/timer-sr.c
+index 798866a8d875..63e28dd18bb0 100644
+--- a/virt/kvm/arm/hyp/timer-sr.c
++++ b/virt/kvm/arm/hyp/timer-sr.c
+@@ -35,10 +35,16 @@ void __hyp_text __timer_save_state(struct kvm_vcpu *vcpu)
+ 	/* Disable the virtual timer */
+ 	write_sysreg_el0(0, cntv_ctl);
+ 
+-	/* Allow physical timer/counter access for the host */
+-	val = read_sysreg(cnthctl_el2);
+-	val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN;
+-	write_sysreg(val, cnthctl_el2);
++	/*
++	 * We don't need to do this for VHE since the host kernel runs in EL2
++	 * with HCR_EL2.TGE ==1, which makes those bits have no impact.
++	 */
++	if (!has_vhe()) {
++		/* Allow physical timer/counter access for the host */
++		val = read_sysreg(cnthctl_el2);
++		val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN;
++		write_sysreg(val, cnthctl_el2);
++	}
+ 
+ 	/* Clear cntvoff for the host */
+ 	write_sysreg(0, cntvoff_el2);
+@@ -50,14 +56,17 @@ void __hyp_text __timer_restore_state(struct kvm_vcpu *vcpu)
+ 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+ 	u64 val;
+ 
+-	/*
+-	 * Disallow physical timer access for the guest
+-	 * Physical counter access is allowed
+-	 */
+-	val = read_sysreg(cnthctl_el2);
+-	val &= ~CNTHCTL_EL1PCEN;
+-	val |= CNTHCTL_EL1PCTEN;
+-	write_sysreg(val, cnthctl_el2);
++	/* Those bits are already configured at boot on VHE-system */
++	if (!has_vhe()) {
++		/*
++		 * Disallow physical timer access for the guest
++		 * Physical counter access is allowed
++		 */
++		val = read_sysreg(cnthctl_el2);
++		val &= ~CNTHCTL_EL1PCEN;
++		val |= CNTHCTL_EL1PCTEN;
++		write_sysreg(val, cnthctl_el2);
++	}
+ 
+ 	if (timer->enabled) {
+ 		write_sysreg(kvm->arch.timer.cntvoff, cntvoff_el2);

commit 1650ac49c2a0fb8188a2c8eac36537640ed57892
+Author: Jintack 
+Date:   Mon Nov 28 21:13:02 2016 -0500
+
+    arm64: head.S: Fix CNTHCTL_EL2 access on VHE system
+    
+    Bit positions of CNTHCTL_EL2 are changing depending on HCR_EL2.E2H bit.
+    EL1PCEN and EL1PCTEN are 1st and 0th bits when E2H is not set, but they
+    are 11th and 10th bits respectively when E2H is set.  Current code is
+    unintentionally setting wrong bits to CNTHCTL_EL2 with E2H set.
+    
+    In fact, we don't need to set those two bits, which allow EL1 and EL0 to
+    access physical timer and counter respectively, if E2H and TGE are set
+    for the host kernel. They will be configured later as necessary. First,
+    we don't need to configure those bits for EL1, since the host kernel
+    runs in EL2.  It is a hypervisor's responsibility to configure them
+    before entering a VM, which runs in EL0 and EL1. Second, EL0 accesses
+    are configured in the later stage of boot process.
+    
+    Signed-off-by: Jintack Lim 
+    Acked-by: Marc Zyngier 
+    Signed-off-by: Catalin Marinas 
+
+diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
+index 7ee6d74101cf..4b1abac3485a 100644
+--- a/arch/arm64/kernel/head.S
++++ b/arch/arm64/kernel/head.S
+@@ -525,10 +525,21 @@ set_hcr:
+ 	msr	hcr_el2, x0
+ 	isb
+ 
+-	/* Generic timers. */
++	/*
++	 * Allow Non-secure EL1 and EL0 to access physical timer and counter.
++	 * This is not necessary for VHE, since the host kernel runs in EL2,
++	 * and EL0 accesses are configured in the later stage of boot process.
++	 * Note that when HCR_EL2.E2H == 1, CNTHCTL_EL2 has the same bit layout
++	 * as CNTKCTL_EL1, and CNTKCTL_EL1 accessing instructions are redefined
++	 * to access CNTHCTL_EL2. This allows the kernel designed to run at EL1
++	 * to transparently mess with the EL0 bits via CNTKCTL_EL1 access in
++	 * EL2.
++	 */
++	cbnz	x2, 1f
+ 	mrs	x0, cnthctl_el2
+ 	orr	x0, x0, #3			// Enable EL1 physical timers
+ 	msr	cnthctl_el2, x0
++1:
+ 	msr	cntvoff_el2, xzr		// Clear virtual offset
+ 
+ #ifdef CONFIG_ARM_GIC_V3

commit d42c79701a3ee5c38fbbc82f98a140420bd40134
+Author: Shih-Wei Li 
+Date:   Thu Oct 27 15:08:13 2016 +0000
+
+    KVM: arm/arm64: vgic: Kick VCPUs when queueing already pending IRQs
+    
+    In cases like IPI, we could be queueing an interrupt for a VCPU
+    that is already running and is not about to exit, because the
+    VCPU has entered the VM with the interrupt pending and would
+    not trap on EOI'ing that interrupt. This could result to delays
+    in interrupt deliveries or even loss of interrupts.
+    To guarantee prompt interrupt injection, here we have to try to
+    kick the VCPU.
+    
+    Signed-off-by: Shih-Wei Li 
+    Reviewed-by: Christoffer Dall 
+    Signed-off-by: Marc Zyngier 
+
+diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
+index 2893d5ba523a..6440b56ec90e 100644
+--- a/virt/kvm/arm/vgic/vgic.c
++++ b/virt/kvm/arm/vgic/vgic.c
+@@ -273,6 +273,18 @@ bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq)
+ 		 * no more work for us to do.
+ 		 */
+ 		spin_unlock(&irq->irq_lock);
++
++		/*
++		 * We have to kick the VCPU here, because we could be
++		 * queueing an edge-triggered interrupt for which we
++		 * get no EOI maintenance interrupt. In that case,
++		 * while the IRQ is already on the VCPU's AP list, the
++		 * VCPU could have EOI'ed the original interrupt and
++		 * won't see this one until it exits for some other
++		 * reason.
++		 */
++		if (vcpu)
++			kvm_vcpu_kick(vcpu);
+ 		return false;
+ 	}
+ 

commit df759217386fcff9c5e45547d1578270fd592a1b
+Author: Christoffer Dall 
+Date:   Tue Apr 23 14:26:31 2013 -0700
+
+    KVM: ARM: Fix spelling in error message
+    
+    s/unkown/unknown/
+    
+    Signed-off-by: Christoffer Dall 
+
+diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
+index 26ad17310a1e..3d74a0be47db 100644
+--- a/arch/arm/kvm/handle_exit.c
++++ b/arch/arm/kvm/handle_exit.c
+@@ -115,7 +115,7 @@ static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu)
+ 
+ 	if (hsr_ec >= ARRAY_SIZE(arm_exit_handlers) ||
+ 	    !arm_exit_handlers[hsr_ec]) {
+-		kvm_err("Unkown exception class: hsr: %#08x\n",
++		kvm_err("Unknown exception class: hsr: %#08x\n",
+ 			(unsigned int)kvm_vcpu_get_hsr(vcpu));
+ 		BUG();
+ 	}

commit aa404ddf952fa59c07575529ce93435538a3aebe
+Author: Christoffer Dall 
+Date:   Mon Apr 22 18:57:46 2013 -0700
+
+    KVM: ARM: Fix API documentation for ONE_REG encoding
+    
+    Unless I'm mistaken, the size field was encoded 4 bits off and a wrong
+    value was used for 64-bit FP registers.
+    
+    Signed-off-by: Christoffer Dall 
+
+diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
+index c09d1832e935..59fd9e6a5366 100644
+--- a/Documentation/virtual/kvm/api.txt
++++ b/Documentation/virtual/kvm/api.txt
+@@ -1814,22 +1814,22 @@ ARM registers are mapped using the lower 32 bits.  The upper 16 of that
+ is the register group type, or coprocessor number:
+ 
+ ARM core registers have the following id bit patterns:
+-  0x4002 0000 0010 
++  0x4020 0000 0010 
+ 
+ ARM 32-bit CP15 registers have the following id bit patterns:
+-  0x4002 0000 000F     
++  0x4020 0000 000F     
+ 
+ ARM 64-bit CP15 registers have the following id bit patterns:
+-  0x4003 0000 000F     
++  0x4030 0000 000F     
+ 
+ ARM CCSIDR registers are demultiplexed by CSSELR value:
+-  0x4002 0000 0011 00 
++  0x4020 0000 0011 00 
+ 
+ ARM 32-bit VFP control registers have the following id bit patterns:
+-  0x4002 0000 0012 1 
++  0x4020 0000 0012 1 
+ 
+ ARM 64-bit FP registers have the following id bit patterns:
+-  0x4002 0000 0012 0 
++  0x4030 0000 0012 0 
+ 
+ 4.69 KVM_GET_ONE_REG
+ 

commit c088f8f0088decf0ce172a6bb4a6f5742cc54c15
+Author: Christoffer Dall 
+Date:   Thu Feb 21 11:26:10 2013 -0800
+
+    KVM: ARM: Reintroduce trace_kvm_hvc
+    
+    This one got lost in the move to handle_exit, so let's reintroduce it
+    using an accessor to the immediate value field like the other ones.
+    
+    Signed-off-by: Christoffer Dall 
+
+diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h
+index e14268c77af0..9cb2fe17cf3a 100644
+--- a/arch/arm/include/asm/kvm_emulate.h
++++ b/arch/arm/include/asm/kvm_emulate.h
+@@ -158,4 +158,9 @@ static inline u8 kvm_vcpu_trap_get_fault(struct kvm_vcpu *vcpu)
+ 	return kvm_vcpu_get_hsr(vcpu) & HSR_FSC_TYPE;
+ }
+ 
++static inline u32 kvm_vcpu_hvc_get_imm(struct kvm_vcpu *vcpu)
++{
++	return kvm_vcpu_get_hsr(vcpu) & HSR_HVC_IMM_MASK;
++}
++
+ #endif /* __ARM_KVM_EMULATE_H__ */
+diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
+index f1cc3a8a9c7e..301301808c4e 100644
+--- a/arch/arm/kvm/handle_exit.c
++++ b/arch/arm/kvm/handle_exit.c
+@@ -23,6 +23,8 @@
+ #include 
+ #include 
+ 
++#include "trace.h"
++
+ typedef int (*exit_handle_fn)(struct kvm_vcpu *, struct kvm_run *);
+ 
+ static int handle_svc_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run)
+@@ -35,6 +37,9 @@ static int handle_svc_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run)
+ 
+ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
+ {
++	trace_kvm_hvc(*vcpu_pc(vcpu), *vcpu_reg(vcpu, 0),
++		      kvm_vcpu_hvc_get_imm(vcpu));
++
+ 	if (kvm_psci_call(vcpu))
+ 		return 1;
+ 

commit 86ce85352f0da7e1431ad8efcb04323819a620e7
+Author: Christoffer Dall 
+Date:   Sun Jan 20 18:28:08 2013 -0500
+
+    KVM: ARM: Inject IRQs and FIQs from userspace
+    
+    All interrupt injection is now based on the VM ioctl KVM_IRQ_LINE.  This
+    works semantically well for the GIC as we in fact raise/lower a line on
+    a machine component (the gic).  The IOCTL uses the follwing struct.
+    
+    struct kvm_irq_level {
+            union {
+                    __u32 irq;     /* GSI */
+                    __s32 status;  /* not used for KVM_IRQ_LEVEL */
+            };
+            __u32 level;           /* 0 or 1 */
+    };
+    
+    ARM can signal an interrupt either at the CPU level, or at the in-kernel irqchip
+    (GIC), and for in-kernel irqchip can tell the GIC to use PPIs designated for
+    specific cpus.  The irq field is interpreted like this:
+    
+      bits:  | 31 ... 24 | 23  ... 16 | 15    ...    0 |
+      field: | irq_type  | vcpu_index |   irq_number   |
+    
+    The irq_type field has the following values:
+    - irq_type[0]: out-of-kernel GIC: irq_number 0 is IRQ, irq_number 1 is FIQ
+    - irq_type[1]: in-kernel GIC: SPI, irq_number between 32 and 1019 (incl.)
+                   (the vcpu_index field is ignored)
+    - irq_type[2]: in-kernel GIC: PPI, irq_number between 16 and 31 (incl.)
+    
+    The irq_number thus corresponds to the irq ID in as in the GICv2 specs.
+    
+    This is documented in Documentation/kvm/api.txt.
+    
+    Reviewed-by: Will Deacon 
+    Reviewed-by: Marcelo Tosatti 
+    Signed-off-by: Christoffer Dall 
+
+diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
+index 4237c27ea612..505049299298 100644
+--- a/Documentation/virtual/kvm/api.txt
++++ b/Documentation/virtual/kvm/api.txt
+@@ -615,15 +615,32 @@ created.
+ 4.25 KVM_IRQ_LINE
+ 
+ Capability: KVM_CAP_IRQCHIP
+-Architectures: x86, ia64
++Architectures: x86, ia64, arm
+ Type: vm ioctl
+ Parameters: struct kvm_irq_level
+ Returns: 0 on success, -1 on error
+ 
+ Sets the level of a GSI input to the interrupt controller model in the kernel.
+-Requires that an interrupt controller model has been previously created with
+-KVM_CREATE_IRQCHIP.  Note that edge-triggered interrupts require the level
+-to be set to 1 and then back to 0.
++On some architectures it is required that an interrupt controller model has
++been previously created with KVM_CREATE_IRQCHIP.  Note that edge-triggered
++interrupts require the level to be set to 1 and then back to 0.
++
++ARM can signal an interrupt either at the CPU level, or at the in-kernel irqchip
++(GIC), and for in-kernel irqchip can tell the GIC to use PPIs designated for
++specific cpus.  The irq field is interpreted like this:
++
++  bits:  | 31 ... 24 | 23  ... 16 | 15    ...    0 |
++  field: | irq_type  | vcpu_index |     irq_id     |
++
++The irq_type field has the following values:
++- irq_type[0]: out-of-kernel GIC: irq_id 0 is IRQ, irq_id 1 is FIQ
++- irq_type[1]: in-kernel GIC: SPI, irq_id between 32 and 1019 (incl.)
++               (the vcpu_index field is ignored)
++- irq_type[2]: in-kernel GIC: PPI, irq_id between 16 and 31 (incl.)
++
++(The irq_id field thus corresponds nicely to the IRQ ID in the ARM GIC specs)
++
++In both cases, level is used to raise/lower the line.
+ 
+ struct kvm_irq_level {
+ 	union {
+diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h
+index 8875b3f605a7..d64b5250ad4e 100644
+--- a/arch/arm/include/asm/kvm_arm.h
++++ b/arch/arm/include/asm/kvm_arm.h
+@@ -68,6 +68,7 @@
+ #define HCR_GUEST_MASK (HCR_TSC | HCR_TSW | HCR_TWI | HCR_VM | HCR_BSU_IS | \
+ 			HCR_FB | HCR_TAC | HCR_AMO | HCR_IMO | HCR_FMO | \
+ 			HCR_SWIO | HCR_TIDCP)
++#define HCR_VIRT_EXCP_MASK (HCR_VA | HCR_VI | HCR_VF)
+ 
+ /* Hyp System Control Register (HSCTLR) bits */
+ #define HSCTLR_TE	(1 << 30)
+diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
+index 1083327b5fcd..53f45f146875 100644
+--- a/arch/arm/include/uapi/asm/kvm.h
++++ b/arch/arm/include/uapi/asm/kvm.h
+@@ -23,6 +23,7 @@
+ #include 
+ 
+ #define __KVM_HAVE_GUEST_DEBUG
++#define __KVM_HAVE_IRQ_LINE
+ 
+ #define KVM_REG_SIZE(id)						\
+ 	(1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
+@@ -103,4 +104,24 @@ struct kvm_arch_memory_slot {
+ #define KVM_REG_ARM_CORE		(0x0010 << KVM_REG_ARM_COPROC_SHIFT)
+ #define KVM_REG_ARM_CORE_REG(name)	(offsetof(struct kvm_regs, name) / 4)
+ 
++/* KVM_IRQ_LINE irq field index values */
++#define KVM_ARM_IRQ_TYPE_SHIFT		24
++#define KVM_ARM_IRQ_TYPE_MASK		0xff
++#define KVM_ARM_IRQ_VCPU_SHIFT		16
++#define KVM_ARM_IRQ_VCPU_MASK		0xff
++#define KVM_ARM_IRQ_NUM_SHIFT		0
++#define KVM_ARM_IRQ_NUM_MASK		0xffff
++
++/* irq_type field */
++#define KVM_ARM_IRQ_TYPE_CPU		0
++#define KVM_ARM_IRQ_TYPE_SPI		1
++#define KVM_ARM_IRQ_TYPE_PPI		2
++
++/* out-of-kernel GIC cpu interrupt injection irq_number field */
++#define KVM_ARM_IRQ_CPU_IRQ		0
++#define KVM_ARM_IRQ_CPU_FIQ		1
++
++/* Highest supported SPI, from VGIC_NR_IRQS */
++#define KVM_ARM_IRQ_GIC_MAX		127
++
+ #endif /* __ARM_KVM_H__ */
+diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
+index d810afb6cb84..2101152c3a4b 100644
+--- a/arch/arm/kvm/arm.c
++++ b/arch/arm/kvm/arm.c
+@@ -24,6 +24,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ 
+ #define CREATE_TRACE_POINTS
+@@ -284,6 +285,7 @@ void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
+ 
+ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+ {
++	vcpu->cpu = cpu;
+ }
+ 
+ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
+@@ -319,6 +321,69 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
+ 	return -EINVAL;
+ }
+ 
++static int vcpu_interrupt_line(struct kvm_vcpu *vcpu, int number, bool level)
++{
++	int bit_index;
++	bool set;
++	unsigned long *ptr;
++
++	if (number == KVM_ARM_IRQ_CPU_IRQ)
++		bit_index = __ffs(HCR_VI);
++	else /* KVM_ARM_IRQ_CPU_FIQ */
++		bit_index = __ffs(HCR_VF);
++
++	ptr = (unsigned long *)&vcpu->arch.irq_lines;
++	if (level)
++		set = test_and_set_bit(bit_index, ptr);
++	else
++		set = test_and_clear_bit(bit_index, ptr);
++
++	/*
++	 * If we didn't change anything, no need to wake up or kick other CPUs
++	 */
++	if (set == level)
++		return 0;
++
++	/*
++	 * The vcpu irq_lines field was updated, wake up sleeping VCPUs and
++	 * trigger a world-switch round on the running physical CPU to set the
++	 * virtual IRQ/FIQ fields in the HCR appropriately.
++	 */
++	kvm_vcpu_kick(vcpu);
++
++	return 0;
++}
++
++int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level)
++{
++	u32 irq = irq_level->irq;
++	unsigned int irq_type, vcpu_idx, irq_num;
++	int nrcpus = atomic_read(&kvm->online_vcpus);
++	struct kvm_vcpu *vcpu = NULL;
++	bool level = irq_level->level;
++
++	irq_type = (irq >> KVM_ARM_IRQ_TYPE_SHIFT) & KVM_ARM_IRQ_TYPE_MASK;
++	vcpu_idx = (irq >> KVM_ARM_IRQ_VCPU_SHIFT) & KVM_ARM_IRQ_VCPU_MASK;
++	irq_num = (irq >> KVM_ARM_IRQ_NUM_SHIFT) & KVM_ARM_IRQ_NUM_MASK;
++
++	trace_kvm_irq_line(irq_type, vcpu_idx, irq_num, irq_level->level);
++
++	if (irq_type != KVM_ARM_IRQ_TYPE_CPU)
++		return -EINVAL;
++
++	if (vcpu_idx >= nrcpus)
++		return -EINVAL;
++
++	vcpu = kvm_get_vcpu(kvm, vcpu_idx);
++	if (!vcpu)
++		return -EINVAL;
++
++	if (irq_num > KVM_ARM_IRQ_CPU_FIQ)
++		return -EINVAL;
++
++	return vcpu_interrupt_line(vcpu, irq_num, level);
++}
++
+ long kvm_arch_vcpu_ioctl(struct file *filp,
+ 			 unsigned int ioctl, unsigned long arg)
+ {
+diff --git a/arch/arm/kvm/trace.h b/arch/arm/kvm/trace.h
+index 862b2cc12fbe..105d1f79909a 100644
+--- a/arch/arm/kvm/trace.h
++++ b/arch/arm/kvm/trace.h
+@@ -39,6 +39,31 @@ TRACE_EVENT(kvm_exit,
+ 	TP_printk("PC: 0x%08lx", __entry->vcpu_pc)
+ );
+ 
++TRACE_EVENT(kvm_irq_line,
++	TP_PROTO(unsigned int type, int vcpu_idx, int irq_num, int level),
++	TP_ARGS(type, vcpu_idx, irq_num, level),
++
++	TP_STRUCT__entry(
++		__field(	unsigned int,	type		)
++		__field(	int,		vcpu_idx	)
++		__field(	int,		irq_num		)
++		__field(	int,		level		)
++	),
++
++	TP_fast_assign(
++		__entry->type		= type;
++		__entry->vcpu_idx	= vcpu_idx;
++		__entry->irq_num	= irq_num;
++		__entry->level		= level;
++	),
++
++	TP_printk("Inject %s interrupt (%d), vcpu->idx: %d, num: %d, level: %d",
++		  (__entry->type == KVM_ARM_IRQ_TYPE_CPU) ? "CPU" :
++		  (__entry->type == KVM_ARM_IRQ_TYPE_PPI) ? "VGIC PPI" :
++		  (__entry->type == KVM_ARM_IRQ_TYPE_SPI) ? "VGIC SPI" : "UNKNOWN",
++		  __entry->type, __entry->vcpu_idx, __entry->irq_num, __entry->level)
++);
++
+ TRACE_EVENT(kvm_unmap_hva,
+ 	TP_PROTO(unsigned long hva),
+ 	TP_ARGS(hva),
+diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
+index 24978d525c6e..dc63665e73ad 100644
+--- a/include/uapi/linux/kvm.h
++++ b/include/uapi/linux/kvm.h
+@@ -115,6 +115,7 @@ struct kvm_irq_level {
+ 	 * ACPI gsi notion of irq.
+ 	 * For IA-64 (APIC model) IOAPIC0: irq 0-23; IOAPIC1: irq 24-47..
+ 	 * For X86 (standard AT mode) PIC0/1: irq 0-15. IOAPIC0: 0-23..
++	 * For ARM: See Documentation/virtual/kvm/api.txt
+ 	 */
+ 	union {
+ 		__u32 irq;

commit ad4b3fb7ff9940bcdb1e4cd62bd189d10fa636ba
+Author: Christoffer Dall 
+Date:   Fri Dec 21 13:03:50 2012 -0500
+
+    mm: Fix PageHead when !CONFIG_PAGEFLAGS_EXTENDED
+    
+    Unfortunately with !CONFIG_PAGEFLAGS_EXTENDED, (!PageHead) is false, and
+    (PageHead) is true, for tail pages.  If this is indeed the intended
+    behavior, which I doubt because it breaks cache cleaning on some ARM
+    systems, then the nomenclature is highly problematic.
+    
+    This patch makes sure PageHead is only true for head pages and PageTail
+    is only true for tail pages, and neither is true for non-compound pages.
+    
+    [ This buglet seems ancient - seems to have been introduced back in Apr
+      2008 in commit 6a1e7f777f61: "pageflags: convert to the use of new
+      macros".  And the reason nobody noticed is because the PageHead()
+      tests are almost all about just sanity-checking, and only used on
+      pages that are actual page heads.  The fact that the old code returned
+      true for tail pages too was thus not really noticeable.   - Linus ]
+    
+    Signed-off-by: Christoffer Dall 
+    Acked-by:  Andrea Arcangeli 
+    Cc: Andrew Morton 
+    Cc: Will Deacon 
+    Cc: Steve Capper 
+    Cc: Christoph Lameter 
+    Cc: stable@kernel.org  # 2.6.26+
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
+index b5d13841604e..70473da47b3f 100644
+--- a/include/linux/page-flags.h
++++ b/include/linux/page-flags.h
+@@ -362,7 +362,7 @@ static inline void ClearPageCompound(struct page *page)
+  * pages on the LRU and/or pagecache.
+  */
+ TESTPAGEFLAG(Compound, compound)
+-__PAGEFLAG(Head, compound)
++__SETPAGEFLAG(Head, compound)  __CLEARPAGEFLAG(Head, compound)
+ 
+ /*
+  * PG_reclaim is used in combination with PG_compound to mark the
+@@ -374,8 +374,14 @@ __PAGEFLAG(Head, compound)
+  * PG_compound & PG_reclaim	=> Tail page
+  * PG_compound & ~PG_reclaim	=> Head page
+  */
++#define PG_head_mask ((1L << PG_compound))
+ #define PG_head_tail_mask ((1L << PG_compound) | (1L << PG_reclaim))
+ 
++static inline int PageHead(struct page *page)
++{
++	return ((page->flags & PG_head_tail_mask) == PG_head_mask);
++}
++
+ static inline int PageTail(struct page *page)
+ {
+ 	return ((page->flags & PG_head_tail_mask) == PG_head_tail_mask);

commit e19f247a3dbd85485ec13174817ae9c2478fe541
+Author: Oren Laadan 
+Date:   Sun Jan 8 01:03:58 2006 -0800
+
+    [PATCH] setpgid: should work for sub-threads
+    
+    setsid() does not work unless the calling process is a
+    thread_group_leader().
+    
+    'man setpgid' does not tell anything about that, so I consider this
+    behaviour is a bug.
+    
+    Signed-off-by: Oren Laadan 
+    Cc: Oleg Nesterov 
+    Cc: Roland McGrath 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/kernel/exit.c b/kernel/exit.c
+index a80824f6108b..caceabf3f230 100644
+--- a/kernel/exit.c
++++ b/kernel/exit.c
+@@ -257,7 +257,7 @@ static inline void reparent_to_init(void)
+ 
+ void __set_special_pids(pid_t session, pid_t pgrp)
+ {
+-	struct task_struct *curr = current;
++	struct task_struct *curr = current->group_leader;
+ 
+ 	if (curr->signal->session != session) {
+ 		detach_pid(curr, PIDTYPE_SID);
+diff --git a/kernel/sys.c b/kernel/sys.c
+index 43e557211d8d..f497bf56ada1 100644
+--- a/kernel/sys.c
++++ b/kernel/sys.c
+@@ -1215,24 +1215,22 @@ asmlinkage long sys_getsid(pid_t pid)
+ 
+ asmlinkage long sys_setsid(void)
+ {
++	struct task_struct *group_leader = current->group_leader;
+ 	struct pid *pid;
+ 	int err = -EPERM;
+ 
+-	if (!thread_group_leader(current))
+-		return -EINVAL;
+-
+ 	down(&tty_sem);
+ 	write_lock_irq(&tasklist_lock);
+ 
+-	pid = find_pid(PIDTYPE_PGID, current->pid);
++	pid = find_pid(PIDTYPE_PGID, group_leader->pid);
+ 	if (pid)
+ 		goto out;
+ 
+-	current->signal->leader = 1;
+-	__set_special_pids(current->pid, current->pid);
+-	current->signal->tty = NULL;
+-	current->signal->tty_old_pgrp = 0;
+-	err = process_group(current);
++	group_leader->signal->leader = 1;
++	__set_special_pids(group_leader->pid, group_leader->pid);
++	group_leader->signal->tty = NULL;
++	group_leader->signal->tty_old_pgrp = 0;
++	err = process_group(group_leader);
+ out:
+ 	write_unlock_irq(&tasklist_lock);
+ 	up(&tty_sem);

commit 9a5d3023e626a0baf86ac6b892c983b3db13f22b
+Author: Oren Laadan 
+Date:   Sun Jan 8 01:03:51 2006 -0800
+
+    [PATCH] fork: fix race in setting child's pgrp and tty
+    
+    In fork, child should recopy parent's pgrp/tty after it has tasklist_lock.
+    Otherwise following a setpgid() on the parent, *after* copy_signal(), the
+    child will own a stale pgrp (which may be reused); (eg.  if copy_mm()
+    sleeps a long while due to memory pressure).  Similar issue for the tty.
+    
+    Signed-off-by: Oren Laadan 
+    Cc: Oleg Nesterov 
+    Cc: Roland McGrath 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/kernel/fork.c b/kernel/fork.c
+index 7992ee759d89..4bc0bd8ef176 100644
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -811,9 +811,6 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts
+ 	sig->it_prof_expires = cputime_zero;
+ 	sig->it_prof_incr = cputime_zero;
+ 
+-	sig->tty = current->signal->tty;
+-	sig->pgrp = process_group(current);
+-	sig->session = current->signal->session;
+ 	sig->leader = 0;	/* session leadership doesn't inherit */
+ 	sig->tty_old_pgrp = 0;
+ 
+@@ -1136,15 +1133,15 @@ static task_t *copy_process(unsigned long clone_flags,
+ 	attach_pid(p, PIDTYPE_PID, p->pid);
+ 	attach_pid(p, PIDTYPE_TGID, p->tgid);
+ 	if (thread_group_leader(p)) {
++		p->signal->tty = current->signal->tty;
++		p->signal->pgrp = process_group(current);
++		p->signal->session = current->signal->session;
+ 		attach_pid(p, PIDTYPE_PGID, process_group(p));
+ 		attach_pid(p, PIDTYPE_SID, p->signal->session);
+ 		if (p->pid)
+ 			__get_cpu_var(process_counts)++;
+ 	}
+ 
+-	if (!current->signal->tty && p->signal->tty)
+-		p->signal->tty = NULL;
+-
+ 	nr_threads++;
+ 	total_forks++;
+ 	write_unlock_irq(&tasklist_lock);

\ No newline at end of file diff --git a/detail/25.html b/detail/25.html new file mode 100644 index 0000000..367efb4 --- /dev/null +++ b/detail/25.html @@ -0,0 +1,4424 @@ +

Patches contributed by University of Adelaide


commit 53bacfbbb2ddd981287b58a511c8b8f5df179886
+Author: Jonathan Woithe 
+Date:   Sun Aug 8 00:17:05 2010 +0930
+
+    ALSA: hda - Fix missing stream for second ADC on Realtek ALC260 HDA codec
+    
+    I discovered tonight that ALSA no longer sets up a stream for the second ADC
+    provided by the Realtek ALC260 HDA codec.  At some point alc_build_pcms()
+    started using stream_analog_alt_capture when constructing the second ADC
+    stream, but patch_alc260() was never updated accordingly.  I have no idea
+    when this regression occurred.  The trivial patch to patch_alc260() given
+    below fixes the problem as far as I can tell.  The patch is against 2.6.35.
+    
+    Signed-off-by: Jonathan Woithe 
+    Cc: 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 2891571e7647..6b00a2369e97 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -7042,6 +7042,7 @@ static int patch_alc260(struct hda_codec *codec)
+ 
+ 	spec->stream_analog_playback = &alc260_pcm_analog_playback;
+ 	spec->stream_analog_capture = &alc260_pcm_analog_capture;
++	spec->stream_analog_alt_capture = &alc260_pcm_analog_capture;
+ 
+ 	spec->stream_digital_playback = &alc260_pcm_digital_playback;
+ 	spec->stream_digital_capture = &alc260_pcm_digital_capture;

commit 3b1c37cab3765b87efbd4ed40301ceaf72b9f5c2
+Author: Jonathan Woithe 
+Date:   Wed Dec 23 09:19:42 2009 +1030
+
+    fujitu-laptop: fix tests of acpi_evaluate_integer() return value
+    
+    Fix tests on return value from acpi_evaluate_integer().  Based on a patch by
+    Roel Kluin  and incorporating suggestions from Len
+    Brown .
+    
+    Signed-off-by: Roel Kluin 
+    Signed-off-by: Jonathan Woithe 
+    Signed-off-by: Len Brown 
+
+diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c
+index bcd4ba8be7db..3c2d0384b43b 100644
+--- a/drivers/platform/x86/fujitsu-laptop.c
++++ b/drivers/platform/x86/fujitsu-laptop.c
+@@ -376,8 +376,8 @@ static int get_lcd_level(void)
+ 
+ 	status =
+ 	    acpi_evaluate_integer(fujitsu->acpi_handle, "GBLL", NULL, &state);
+-	if (status < 0)
+-		return status;
++	if (ACPI_FAILURE(status))
++		return 0;
+ 
+ 	fujitsu->brightness_level = state & 0x0fffffff;
+ 
+@@ -398,8 +398,8 @@ static int get_max_brightness(void)
+ 
+ 	status =
+ 	    acpi_evaluate_integer(fujitsu->acpi_handle, "RBLL", NULL, &state);
+-	if (status < 0)
+-		return status;
++	if (ACPI_FAILURE(status))
++		return -1;
+ 
+ 	fujitsu->max_brightness = state;
+ 

commit 2906206350b7e13e2047467cc29a0a2d78d71cb2
+Author: Jonathan Woithe 
+Date:   Thu Oct 8 13:19:12 2009 +0930
+
+    fujitsu-laptop: address missed led-class ifdef fixup
+    
+    A follow-up 2.6.32-rc1's
+    
+    1e384cb0f9a940f2a431d1708f963987e61d71e3
+    "fujitsu-laptop: support led-class as module"
+    
+    It's a trivial fix for one of the CONFIG_LEDS_CLASS ifdefs
+    which was somehow missed in the original patch.
+    
+    Signed-off-by: Jonathan Woithe 
+    Signed-off-by: Len Brown 
+
+diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c
+index f35aee5c2149..bcd4ba8be7db 100644
+--- a/drivers/platform/x86/fujitsu-laptop.c
++++ b/drivers/platform/x86/fujitsu-laptop.c
+@@ -944,7 +944,7 @@ static int acpi_fujitsu_hotkey_remove(struct acpi_device *device, int type)
+ 	struct fujitsu_hotkey_t *fujitsu_hotkey = acpi_driver_data(device);
+ 	struct input_dev *input = fujitsu_hotkey->input;
+ 
+-#ifdef CONFIG_LEDS_CLASS
++#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
+ 	if (fujitsu_hotkey->logolamp_registered)
+ 		led_classdev_unregister(&logolamp_led);
+ 

commit 84a6ce267296dabdf427ea4aff73dc58164863bb
+Author: Jonathan Woithe 
+Date:   Fri Jul 31 18:16:59 2009 +0930
+
+    fujitsu-laptop: increment driver version
+    
+    Increment driver version to reflect the changes from this patch series.
+    
+    Signed-off-by: Jonathan Woithe 
+    Signed-off-by: Len Brown 
+
+diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c
+index b87a5a2084a9..1ed3513a62a2 100644
+--- a/drivers/platform/x86/fujitsu-laptop.c
++++ b/drivers/platform/x86/fujitsu-laptop.c
+@@ -70,7 +70,7 @@
+ #include 
+ #endif
+ 
+-#define FUJITSU_DRIVER_VERSION "0.5.0"
++#define FUJITSU_DRIVER_VERSION "0.6.0"
+ 
+ #define FUJITSU_LCD_N_LEVELS 8
+ 

commit c1b5310a957c47d1c66bb53035c6ba6aa20a150f
+Author: Jonathan Woithe 
+Date:   Thu Aug 27 18:45:33 2009 -0400
+
+    fujitsu-laptop: fix config corner case
+    
+    This patch is a trivial fix for a config corner case, ensuring that
+    fujitsu-laptop doesn't get compiled into the kernel when the led class
+    is a module.
+    
+    Signed-off-by: Alan Jenkins 
+    Signed-off-by: Jonathan Woithe 
+    Signed-off-by: Len Brown 
+
+diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
+index 77c6097ced80..0b5a85b8048f 100644
+--- a/drivers/platform/x86/Kconfig
++++ b/drivers/platform/x86/Kconfig
+@@ -99,6 +99,7 @@ config FUJITSU_LAPTOP
+ 	depends on ACPI
+ 	depends on INPUT
+ 	depends on BACKLIGHT_CLASS_DEVICE
++	depends on LEDS_CLASS || LEDS_CLASS=n
+ 	---help---
+ 	  This is a driver for laptops built by Fujitsu:
+ 

commit 0e6a66e9cf231140d2e49064d48162728edb7746
+Author: Jonathan Woithe 
+Date:   Thu Oct 9 13:44:40 2008 +0930
+
+    fujitsu-laptop: better handling of P8010 hotkey
+    
+    This patch (mostly from Peter Gruber) improves the handling of the hotkeys
+    for P8010 laptops by passing more accurate input events back to userspace.
+    This is needed because the P8010 labels these buttons quite differently to
+    earlier laptops.  As part of this, a P8010-specific DMI callback check has
+    been implemented.  Finally there's some minor whitespace cleanups from
+    running the source through Lindent.
+    
+    Signed-off-by: Peter Gruber 
+    Signed-off-by: Jonathan Woithe 
+    Signed-off-by: Len Brown 
+
+diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c
+index 3e56203e4947..f861db072777 100644
+--- a/drivers/misc/fujitsu-laptop.c
++++ b/drivers/misc/fujitsu-laptop.c
+@@ -44,8 +44,9 @@
+  * Hotkeys present on certain Fujitsu laptops (eg: the S6xxx series) are
+  * also supported by this driver.
+  *
+- * This driver has been tested on a Fujitsu Lifebook S6410 and S7020.  It
+- * should work on most P-series and S-series Lifebooks, but YMMV.
++ * This driver has been tested on a Fujitsu Lifebook S6410, S7020 and
++ * P8010.  It should work on most P-series and S-series Lifebooks, but
++ * YMMV.
+  *
+  * The module parameter use_alt_lcd_levels switches between different ACPI
+  * brightness controls which are used by different Fujitsu laptops.  In most
+@@ -65,7 +66,7 @@
+ #include 
+ #include 
+ 
+-#define FUJITSU_DRIVER_VERSION "0.4.2"
++#define FUJITSU_DRIVER_VERSION "0.4.3"
+ 
+ #define FUJITSU_LCD_N_LEVELS 8
+ 
+@@ -83,10 +84,10 @@
+ #define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS     0x87
+ 
+ /* Hotkey details */
+-#define LOCK_KEY	0x410	/* codes for the keys in the GIRB register */
+-#define DISPLAY_KEY	0x411	/* keys are mapped to KEY_SCREENLOCK (the key with the key symbol) */
+-#define ENERGY_KEY	0x412	/* KEY_MEDIA (the key with the laptop symbol, KEY_EMAIL (E key)) */
+-#define REST_KEY	0x413	/* KEY_SUSPEND (R key) */
++#define KEY1_CODE	0x410	/* codes for the keys in the GIRB register */
++#define KEY2_CODE	0x411
++#define KEY3_CODE	0x412
++#define KEY4_CODE	0x413
+ 
+ #define MAX_HOTKEY_RINGBUFFER_SIZE 100
+ #define RINGBUFFERSIZE 40
+@@ -123,6 +124,7 @@ struct fujitsu_t {
+ 	char phys[32];
+ 	struct backlight_device *bl_device;
+ 	struct platform_device *pf_device;
++	int keycode1, keycode2, keycode3, keycode4;
+ 
+ 	unsigned int max_brightness;
+ 	unsigned int brightness_changed;
+@@ -430,7 +432,7 @@ static struct platform_driver fujitsupf_driver = {
+ 		   }
+ };
+ 
+-static int dmi_check_cb_s6410(const struct dmi_system_id *id)
++static void dmi_check_cb_common(const struct dmi_system_id *id)
+ {
+ 	acpi_handle handle;
+ 	int have_blnf;
+@@ -452,24 +454,40 @@ static int dmi_check_cb_s6410(const struct dmi_system_id *id)
+ 			    "auto-detecting disable_adjust\n");
+ 		disable_brightness_adjust = have_blnf ? 0 : 1;
+ 	}
++}
++
++static int dmi_check_cb_s6410(const struct dmi_system_id *id)
++{
++	dmi_check_cb_common(id);
++	fujitsu->keycode1 = KEY_SCREENLOCK;	/* "Lock" */
++	fujitsu->keycode2 = KEY_HELP;	/* "Mobility Center" */
++	return 0;
++}
++
++static int dmi_check_cb_p8010(const struct dmi_system_id *id)
++{
++	dmi_check_cb_common(id);
++	fujitsu->keycode1 = KEY_HELP;	/* "Support" */
++	fujitsu->keycode3 = KEY_SWITCHVIDEOMODE;	/* "Presentation" */
++	fujitsu->keycode4 = KEY_WWW;	/* "Internet" */
+ 	return 0;
+ }
+ 
+ static struct dmi_system_id __initdata fujitsu_dmi_table[] = {
+ 	{
+-	 .ident = "Fujitsu Siemens",
++	 .ident = "Fujitsu Siemens S6410",
+ 	 .matches = {
+ 		     DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+ 		     DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6410"),
+ 		     },
+ 	 .callback = dmi_check_cb_s6410},
+ 	{
+-	 .ident = "FUJITSU LifeBook P8010",
++	 .ident = "Fujitsu LifeBook P8010",
+ 	 .matches = {
+ 		     DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ 		     DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P8010"),
+-		    },
+-	 .callback = dmi_check_cb_s6410},
++		     },
++	 .callback = dmi_check_cb_p8010},
+ 	{}
+ };
+ 
+@@ -547,7 +565,6 @@ static int acpi_fujitsu_add(struct acpi_device *device)
+ 	}
+ 
+ 	/* do config (detect defaults) */
+-	dmi_check_system(fujitsu_dmi_table);
+ 	use_alt_lcd_levels = use_alt_lcd_levels == 1 ? 1 : 0;
+ 	disable_brightness_keys = disable_brightness_keys == 1 ? 1 : 0;
+ 	disable_brightness_adjust = disable_brightness_adjust == 1 ? 1 : 0;
+@@ -623,17 +640,17 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data)
+ 			keycode = 0;
+ 			if (disable_brightness_keys != 1) {
+ 				if (oldb == 0) {
+-					acpi_bus_generate_proc_event(fujitsu->
+-						dev,
+-						ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS,
+-						0);
++					acpi_bus_generate_proc_event
++					    (fujitsu->dev,
++					     ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS,
++					     0);
+ 					keycode = KEY_BRIGHTNESSDOWN;
+ 				} else if (oldb ==
+ 					   (fujitsu->max_brightness) - 1) {
+-					acpi_bus_generate_proc_event(fujitsu->
+-						dev,
+-						ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS,
+-						0);
++					acpi_bus_generate_proc_event
++					    (fujitsu->dev,
++					     ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS,
++					     0);
+ 					keycode = KEY_BRIGHTNESSUP;
+ 				}
+ 			}
+@@ -646,8 +663,7 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data)
+ 			}
+ 			if (disable_brightness_keys != 1) {
+ 				acpi_bus_generate_proc_event(fujitsu->dev,
+-					ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS,
+-					0);
++					ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS, 0);
+ 				keycode = KEY_BRIGHTNESSUP;
+ 			}
+ 		} else if (oldb > newb) {
+@@ -659,8 +675,7 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data)
+ 			}
+ 			if (disable_brightness_keys != 1) {
+ 				acpi_bus_generate_proc_event(fujitsu->dev,
+-					ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS,
+-					0);
++					ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS, 0);
+ 				keycode = KEY_BRIGHTNESSDOWN;
+ 			}
+ 		} else {
+@@ -742,10 +757,10 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
+ 	input->id.product = 0x06;
+ 	input->dev.parent = &device->dev;
+ 	input->evbit[0] = BIT(EV_KEY);
+-	set_bit(KEY_SCREENLOCK, input->keybit);
+-	set_bit(KEY_MEDIA, input->keybit);
+-	set_bit(KEY_EMAIL, input->keybit);
+-	set_bit(KEY_SUSPEND, input->keybit);
++	set_bit(fujitsu->keycode1, input->keybit);
++	set_bit(fujitsu->keycode2, input->keybit);
++	set_bit(fujitsu->keycode3, input->keybit);
++	set_bit(fujitsu->keycode4, input->keybit);
+ 	set_bit(KEY_UNKNOWN, input->keybit);
+ 
+ 	error = input_register_device(input);
+@@ -833,24 +848,24 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
+ 				    irb);
+ 
+ 			switch (irb & 0x4ff) {
+-			case LOCK_KEY:
+-				keycode = KEY_SCREENLOCK;
++			case KEY1_CODE:
++				keycode = fujitsu->keycode1;
+ 				break;
+-			case DISPLAY_KEY:
+-				keycode = KEY_MEDIA;
++			case KEY2_CODE:
++				keycode = fujitsu->keycode2;
+ 				break;
+-			case ENERGY_KEY:
+-				keycode = KEY_EMAIL;
++			case KEY3_CODE:
++				keycode = fujitsu->keycode3;
+ 				break;
+-			case REST_KEY:
+-				keycode = KEY_SUSPEND;
++			case KEY4_CODE:
++				keycode = fujitsu->keycode4;
+ 				break;
+ 			case 0:
+ 				keycode = 0;
+ 				break;
+ 			default:
+ 				vdbg_printk(FUJLAPTOP_DBG_WARN,
+-					"Unknown GIRB result [%x]\n", irb);
++					    "Unknown GIRB result [%x]\n", irb);
+ 				keycode = -1;
+ 				break;
+ 			}
+@@ -859,12 +874,12 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
+ 					"Push keycode into ringbuffer [%d]\n",
+ 					keycode);
+ 				status = kfifo_put(fujitsu_hotkey->fifo,
+-						(unsigned char *)&keycode,
+-						sizeof(keycode));
++						   (unsigned char *)&keycode,
++						   sizeof(keycode));
+ 				if (status != sizeof(keycode)) {
+ 					vdbg_printk(FUJLAPTOP_DBG_WARN,
+-						"Could not push keycode [0x%x]\n",
+-						keycode);
++					    "Could not push keycode [0x%x]\n",
++					    keycode);
+ 				} else {
+ 					input_report_key(input, keycode, 1);
+ 					input_sync(input);
+@@ -879,8 +894,8 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
+ 					input_report_key(input, keycode_r, 0);
+ 					input_sync(input);
+ 					vdbg_printk(FUJLAPTOP_DBG_TRACE,
+-						    "Pop keycode from ringbuffer [%d]\n",
+-						    keycode_r);
++					  "Pop keycode from ringbuffer [%d]\n",
++					  keycode_r);
+ 				}
+ 			}
+ 		}
+@@ -943,6 +958,11 @@ static int __init fujitsu_init(void)
+ 	if (!fujitsu)
+ 		return -ENOMEM;
+ 	memset(fujitsu, 0, sizeof(struct fujitsu_t));
++	fujitsu->keycode1 = KEY_PROG1;
++	fujitsu->keycode2 = KEY_PROG2;
++	fujitsu->keycode3 = KEY_PROG3;
++	fujitsu->keycode4 = KEY_PROG4;
++	dmi_check_system(fujitsu_dmi_table);
+ 
+ 	result = acpi_bus_register_driver(&acpi_fujitsu_driver);
+ 	if (result < 0) {
+@@ -1076,15 +1096,14 @@ MODULE_DESCRIPTION("Fujitsu laptop extras support");
+ MODULE_VERSION(FUJITSU_DRIVER_VERSION);
+ MODULE_LICENSE("GPL");
+ 
+-MODULE_ALIAS
+-    ("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*");
+-MODULE_ALIAS
+-    ("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*");
++MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*");
++MODULE_ALIAS("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*");
+ 
+ static struct pnp_device_id pnp_ids[] = {
+-	{ .id = "FUJ02bf" },
+-	{ .id = "FUJ02B1" },
+-	{ .id = "FUJ02E3" },
+-	{ .id = "" }
++	{.id = "FUJ02bf"},
++	{.id = "FUJ02B1"},
++	{.id = "FUJ02E3"},
++	{.id = ""}
+ };
++
+ MODULE_DEVICE_TABLE(pnp, pnp_ids);

commit d8196a93b1ce9a5abb410f39f9375912c9e53675
+Author: Jonathan Woithe 
+Date:   Fri Aug 29 11:06:21 2008 +0930
+
+    fujitsu-laptop: fix regression for P8010 in 2.6.27-rc
+    
+    The following patch (based on a patch from Stephen Gildea) fixes a
+    regression with the LCD brightness keys on Fujitsu P8010 laptops which was
+    observed with the 2.6.27-rc series (basically they stopped working due to
+    changes within the fujitsu-laptop and video modules).  Please apply to
+    2.6.27-rc and acpi git.
+    
+    A more complete solution for this laptop will be included in an upcoming
+    patch, hopefully for 2.6.28.  In the meantime this restores most
+    functionality for P8010 users.
+    
+    Signed-off-by: Stephen Gildea 
+    Signed-off-by: Jonathan Woithe 
+    Signed-off-by: Andi Kleen 
+
+diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c
+index 7a1ef6c262de..3e56203e4947 100644
+--- a/drivers/misc/fujitsu-laptop.c
++++ b/drivers/misc/fujitsu-laptop.c
+@@ -463,6 +463,13 @@ static struct dmi_system_id __initdata fujitsu_dmi_table[] = {
+ 		     DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6410"),
+ 		     },
+ 	 .callback = dmi_check_cb_s6410},
++	{
++	 .ident = "FUJITSU LifeBook P8010",
++	 .matches = {
++		     DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
++		     DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P8010"),
++		    },
++	 .callback = dmi_check_cb_s6410},
+ 	{}
+ };
+ 

commit 20b937343e55c16e37b1a4ad2176760b4a11002c
+Author: Jonathan Woithe 
+Date:   Wed Jun 11 10:14:56 2008 +0930
+
+    Fujitsu-laptop update
+    
+    Add additional capabilities to the Fujitsu-laptop driver.
+    
+     * Brightness hotkey actions are sent to userspace. This can be disabled
+       using a module parameter if it causes issues with models which handle
+       these keys transparently in the BIOS.
+    
+     * Actions of additional hotkeys found on some Fujitsu models (eg: the
+       suspend key and the dedicated "power on passphrase" keys) are broadcast
+       to userspace.
+    
+     * An alternative brightness control method used by some Fujitsu models
+       (for example, the S6410) is now supported, enabling software brightness
+       controls on models using this method.
+    
+     * DMI-based module aliases are configured for the S6410 and S7020.
+    
+     * The current LCD brightness after booting should now be reflected in the
+       standard backlight interface sysfs file (previously it was always set to
+       0).  The platform brightness sysfs interface has always been fine.
+    
+    Thanks go to Peter Gruber who provided a significant portion of this code
+    and tested various iterations of the patch on his S6410.
+    
+    Signed-off-by: Peter Gruber 
+    Signed-off-by: Jonathan Woithe 
+    Signed-off-by: Len Brown 
+    Signed-off-by: Andi Kleen 
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 2bfde0326300..ec5c8ee30907 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -1792,6 +1792,12 @@ P:	David Howells
+ M:	dhowells@redhat.com
+ S:	Maintained
+ 
++FUJITSU LAPTOP EXTRAS
++P:	Jonathan Woithe
++M:	jwoithe@physics.adelaide.edu.au
++L:	linux-acpi@vger.kernel.org
++S:	Maintained
++
+ FUSE: FILESYSTEM IN USERSPACE
+ P:	Miklos Szeredi
+ M:	miklos@szeredi.hu
+diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
+index 7fce0da86548..0551d95a749a 100644
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -185,11 +185,22 @@ config FUJITSU_LAPTOP
+ 
+ 	    * P2xxx/P5xxx/S6xxx/S7xxx series Lifebooks
+ 	    * Possibly other Fujitsu laptop models
++	    * Tested with S6410 and S7020
+ 
+-	  It adds support for LCD brightness control.
++	  It adds support for LCD brightness control and some hotkeys.
+ 
+ 	  If you have a Fujitsu laptop, say Y or M here.
+ 
++config FUJITSU_LAPTOP_DEBUG
++	bool "Verbose debug mode for Fujitsu Laptop Extras"
++	depends on FUJITSU_LAPTOP
++	default n
++	---help---
++	  Enables extra debug output from the fujitsu extras driver, at the
++	  expense of a slight increase in driver size.
++
++	  If you are not sure, say N here.
++
+ config TC1100_WMI
+ 	tristate "HP Compaq TC1100 Tablet WMI Extras (EXPERIMENTAL)"
+ 	depends on X86 && !X86_64
+diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c
+index 6d14e8fe1537..7a1ef6c262de 100644
+--- a/drivers/misc/fujitsu-laptop.c
++++ b/drivers/misc/fujitsu-laptop.c
+@@ -1,12 +1,14 @@
+ /*-*-linux-c-*-*/
+ 
+ /*
+-  Copyright (C) 2007 Jonathan Woithe 
++  Copyright (C) 2007,2008 Jonathan Woithe 
++  Copyright (C) 2008 Peter Gruber 
+   Based on earlier work:
+     Copyright (C) 2003 Shane Spencer 
+     Adrian Yee 
+ 
+-  Templated from msi-laptop.c which is copyright by its respective authors.
++  Templated from msi-laptop.c and thinkpad_acpi.c which is copyright
++  by its respective authors.
+ 
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+@@ -39,8 +41,17 @@
+  * registers itself in the Linux backlight control subsystem and is
+  * available to userspace under /sys/class/backlight/fujitsu-laptop/.
+  *
+- * This driver has been tested on a Fujitsu Lifebook S7020.  It should
+- * work on most P-series and S-series Lifebooks, but YMMV.
++ * Hotkeys present on certain Fujitsu laptops (eg: the S6xxx series) are
++ * also supported by this driver.
++ *
++ * This driver has been tested on a Fujitsu Lifebook S6410 and S7020.  It
++ * should work on most P-series and S-series Lifebooks, but YMMV.
++ *
++ * The module parameter use_alt_lcd_levels switches between different ACPI
++ * brightness controls which are used by different Fujitsu laptops.  In most
++ * cases the correct method is automatically detected. "use_alt_lcd_levels=1"
++ * is applicable for a Fujitsu Lifebook S6410 if autodetection fails.
++ *
+  */
+ 
+ #include 
+@@ -49,30 +60,105 @@
+ #include 
+ #include 
+ #include 
++#include 
++#include 
++#include 
+ #include 
+ 
+-#define FUJITSU_DRIVER_VERSION "0.3"
++#define FUJITSU_DRIVER_VERSION "0.4.2"
+ 
+ #define FUJITSU_LCD_N_LEVELS 8
+ 
+ #define ACPI_FUJITSU_CLASS              "fujitsu"
+ #define ACPI_FUJITSU_HID                "FUJ02B1"
+-#define ACPI_FUJITSU_DRIVER_NAME        "Fujitsu laptop FUJ02B1 ACPI extras driver"
++#define ACPI_FUJITSU_DRIVER_NAME	"Fujitsu laptop FUJ02B1 ACPI brightness driver"
+ #define ACPI_FUJITSU_DEVICE_NAME        "Fujitsu FUJ02B1"
+-
++#define ACPI_FUJITSU_HOTKEY_HID 	"FUJ02E3"
++#define ACPI_FUJITSU_HOTKEY_DRIVER_NAME "Fujitsu laptop FUJ02E3 ACPI hotkeys driver"
++#define ACPI_FUJITSU_HOTKEY_DEVICE_NAME "Fujitsu FUJ02E3"
++
++#define ACPI_FUJITSU_NOTIFY_CODE1     0x80
++
++#define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS     0x86
++#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS     0x87
++
++/* Hotkey details */
++#define LOCK_KEY	0x410	/* codes for the keys in the GIRB register */
++#define DISPLAY_KEY	0x411	/* keys are mapped to KEY_SCREENLOCK (the key with the key symbol) */
++#define ENERGY_KEY	0x412	/* KEY_MEDIA (the key with the laptop symbol, KEY_EMAIL (E key)) */
++#define REST_KEY	0x413	/* KEY_SUSPEND (R key) */
++
++#define MAX_HOTKEY_RINGBUFFER_SIZE 100
++#define RINGBUFFERSIZE 40
++
++/* Debugging */
++#define FUJLAPTOP_LOG	   ACPI_FUJITSU_HID ": "
++#define FUJLAPTOP_ERR	   KERN_ERR FUJLAPTOP_LOG
++#define FUJLAPTOP_NOTICE   KERN_NOTICE FUJLAPTOP_LOG
++#define FUJLAPTOP_INFO	   KERN_INFO FUJLAPTOP_LOG
++#define FUJLAPTOP_DEBUG    KERN_DEBUG FUJLAPTOP_LOG
++
++#define FUJLAPTOP_DBG_ALL	  0xffff
++#define FUJLAPTOP_DBG_ERROR	  0x0001
++#define FUJLAPTOP_DBG_WARN	  0x0002
++#define FUJLAPTOP_DBG_INFO	  0x0004
++#define FUJLAPTOP_DBG_TRACE	  0x0008
++
++#define dbg_printk(a_dbg_level, format, arg...) \
++	do { if (dbg_level & a_dbg_level) \
++		printk(FUJLAPTOP_DEBUG "%s: " format, __func__ , ## arg); \
++	} while (0)
++#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG
++#define vdbg_printk(a_dbg_level, format, arg...) \
++	dbg_printk(a_dbg_level, format, ## arg)
++#else
++#define vdbg_printk(a_dbg_level, format, arg...)
++#endif
++
++/* Device controlling the backlight and associated keys */
+ struct fujitsu_t {
+ 	acpi_handle acpi_handle;
++	struct acpi_device *dev;
++	struct input_dev *input;
++	char phys[32];
+ 	struct backlight_device *bl_device;
+ 	struct platform_device *pf_device;
+ 
+-	unsigned long fuj02b1_state;
++	unsigned int max_brightness;
+ 	unsigned int brightness_changed;
+ 	unsigned int brightness_level;
+ };
+ 
+ static struct fujitsu_t *fujitsu;
++static int use_alt_lcd_levels = -1;
++static int disable_brightness_keys = -1;
++static int disable_brightness_adjust = -1;
++
++/* Device used to access other hotkeys on the laptop */
++struct fujitsu_hotkey_t {
++	acpi_handle acpi_handle;
++	struct acpi_device *dev;
++	struct input_dev *input;
++	char phys[32];
++	struct platform_device *pf_device;
++	struct kfifo *fifo;
++	spinlock_t fifo_lock;
++
++	unsigned int irb;	/* info about the pressed buttons */
++};
+ 
+-/* Hardware access */
++static struct fujitsu_hotkey_t *fujitsu_hotkey;
++
++static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
++				       void *data);
++
++#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG
++static u32 dbg_level = 0x03;
++#endif
++
++static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data);
++
++/* Hardware access for LCD brightness control */
+ 
+ static int set_lcd_level(int level)
+ {
+@@ -81,7 +167,10 @@ static int set_lcd_level(int level)
+ 	struct acpi_object_list arg_list = { 1, &arg0 };
+ 	acpi_handle handle = NULL;
+ 
+-	if (level < 0 || level >= FUJITSU_LCD_N_LEVELS)
++	vdbg_printk(FUJLAPTOP_DBG_TRACE, "set lcd level via SBLL [%d]\n",
++		    level);
++
++	if (level < 0 || level >= fujitsu->max_brightness)
+ 		return -EINVAL;
+ 
+ 	if (!fujitsu)
+@@ -89,7 +178,38 @@ static int set_lcd_level(int level)
+ 
+ 	status = acpi_get_handle(fujitsu->acpi_handle, "SBLL", &handle);
+ 	if (ACPI_FAILURE(status)) {
+-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SBLL not present\n"));
++		vdbg_printk(FUJLAPTOP_DBG_ERROR, "SBLL not present\n");
++		return -ENODEV;
++	}
++
++	arg0.integer.value = level;
++
++	status = acpi_evaluate_object(handle, NULL, &arg_list, NULL);
++	if (ACPI_FAILURE(status))
++		return -ENODEV;
++
++	return 0;
++}
++
++static int set_lcd_level_alt(int level)
++{
++	acpi_status status = AE_OK;
++	union acpi_object arg0 = { ACPI_TYPE_INTEGER };
++	struct acpi_object_list arg_list = { 1, &arg0 };
++	acpi_handle handle = NULL;
++
++	vdbg_printk(FUJLAPTOP_DBG_TRACE, "set lcd level via SBL2 [%d]\n",
++		    level);
++
++	if (level < 0 || level >= fujitsu->max_brightness)
++		return -EINVAL;
++
++	if (!fujitsu)
++		return -EINVAL;
++
++	status = acpi_get_handle(fujitsu->acpi_handle, "SBL2", &handle);
++	if (ACPI_FAILURE(status)) {
++		vdbg_printk(FUJLAPTOP_DBG_ERROR, "SBL2 not present\n");
+ 		return -ENODEV;
+ 	}
+ 
+@@ -107,13 +227,52 @@ static int get_lcd_level(void)
+ 	unsigned long state = 0;
+ 	acpi_status status = AE_OK;
+ 
+-	// Get the Brightness
++	vdbg_printk(FUJLAPTOP_DBG_TRACE, "get lcd level via GBLL\n");
++
+ 	status =
+ 	    acpi_evaluate_integer(fujitsu->acpi_handle, "GBLL", NULL, &state);
+ 	if (status < 0)
+ 		return status;
+ 
+-	fujitsu->fuj02b1_state = state;
++	fujitsu->brightness_level = state & 0x0fffffff;
++
++	if (state & 0x80000000)
++		fujitsu->brightness_changed = 1;
++	else
++		fujitsu->brightness_changed = 0;
++
++	return fujitsu->brightness_level;
++}
++
++static int get_max_brightness(void)
++{
++	unsigned long state = 0;
++	acpi_status status = AE_OK;
++
++	vdbg_printk(FUJLAPTOP_DBG_TRACE, "get max lcd level via RBLL\n");
++
++	status =
++	    acpi_evaluate_integer(fujitsu->acpi_handle, "RBLL", NULL, &state);
++	if (status < 0)
++		return status;
++
++	fujitsu->max_brightness = state;
++
++	return fujitsu->max_brightness;
++}
++
++static int get_lcd_level_alt(void)
++{
++	unsigned long state = 0;
++	acpi_status status = AE_OK;
++
++	vdbg_printk(FUJLAPTOP_DBG_TRACE, "get lcd level via GBLS\n");
++
++	status =
++	    acpi_evaluate_integer(fujitsu->acpi_handle, "GBLS", NULL, &state);
++	if (status < 0)
++		return status;
++
+ 	fujitsu->brightness_level = state & 0x0fffffff;
+ 
+ 	if (state & 0x80000000)
+@@ -128,12 +287,18 @@ static int get_lcd_level(void)
+ 
+ static int bl_get_brightness(struct backlight_device *b)
+ {
+-	return get_lcd_level();
++	if (use_alt_lcd_levels)
++		return get_lcd_level_alt();
++	else
++		return get_lcd_level();
+ }
+ 
+ static int bl_update_status(struct backlight_device *b)
+ {
+-	return set_lcd_level(b->props.brightness);
++	if (use_alt_lcd_levels)
++		return set_lcd_level_alt(b->props.brightness);
++	else
++		return set_lcd_level(b->props.brightness);
+ }
+ 
+ static struct backlight_ops fujitsubl_ops = {
+@@ -141,7 +306,35 @@ static struct backlight_ops fujitsubl_ops = {
+ 	.update_status = bl_update_status,
+ };
+ 
+-/* Platform device */
++/* Platform LCD brightness device */
++
++static ssize_t
++show_max_brightness(struct device *dev,
++		    struct device_attribute *attr, char *buf)
++{
++
++	int ret;
++
++	ret = get_max_brightness();
++	if (ret < 0)
++		return ret;
++
++	return sprintf(buf, "%i\n", ret);
++}
++
++static ssize_t
++show_brightness_changed(struct device *dev,
++			struct device_attribute *attr, char *buf)
++{
++
++	int ret;
++
++	ret = fujitsu->brightness_changed;
++	if (ret < 0)
++		return ret;
++
++	return sprintf(buf, "%i\n", ret);
++}
+ 
+ static ssize_t show_lcd_level(struct device *dev,
+ 			      struct device_attribute *attr, char *buf)
+@@ -149,7 +342,10 @@ static ssize_t show_lcd_level(struct device *dev,
+ 
+ 	int ret;
+ 
+-	ret = get_lcd_level();
++	if (use_alt_lcd_levels)
++		ret = get_lcd_level_alt();
++	else
++		ret = get_lcd_level();
+ 	if (ret < 0)
+ 		return ret;
+ 
+@@ -164,19 +360,61 @@ static ssize_t store_lcd_level(struct device *dev,
+ 	int level, ret;
+ 
+ 	if (sscanf(buf, "%i", &level) != 1
+-	    || (level < 0 || level >= FUJITSU_LCD_N_LEVELS))
++	    || (level < 0 || level >= fujitsu->max_brightness))
+ 		return -EINVAL;
+ 
+-	ret = set_lcd_level(level);
++	if (use_alt_lcd_levels)
++		ret = set_lcd_level_alt(level);
++	else
++		ret = set_lcd_level(level);
++	if (ret < 0)
++		return ret;
++
++	if (use_alt_lcd_levels)
++		ret = get_lcd_level_alt();
++	else
++		ret = get_lcd_level();
+ 	if (ret < 0)
+ 		return ret;
+ 
+ 	return count;
+ }
+ 
++/* Hardware access for hotkey device */
++
++static int get_irb(void)
++{
++	unsigned long state = 0;
++	acpi_status status = AE_OK;
++
++	vdbg_printk(FUJLAPTOP_DBG_TRACE, "Get irb\n");
++
++	status =
++	    acpi_evaluate_integer(fujitsu_hotkey->acpi_handle, "GIRB", NULL,
++				  &state);
++	if (status < 0)
++		return status;
++
++	fujitsu_hotkey->irb = state;
++
++	return fujitsu_hotkey->irb;
++}
++
++static ssize_t
++ignore_store(struct device *dev,
++	     struct device_attribute *attr, const char *buf, size_t count)
++{
++	return count;
++}
++
++static DEVICE_ATTR(max_brightness, 0444, show_max_brightness, ignore_store);
++static DEVICE_ATTR(brightness_changed, 0444, show_brightness_changed,
++		   ignore_store);
+ static DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level);
+ 
+ static struct attribute *fujitsupf_attributes[] = {
++	&dev_attr_brightness_changed.attr,
++	&dev_attr_max_brightness.attr,
+ 	&dev_attr_lcd_level.attr,
+ 	NULL
+ };
+@@ -192,14 +430,52 @@ static struct platform_driver fujitsupf_driver = {
+ 		   }
+ };
+ 
+-/* ACPI device */
++static int dmi_check_cb_s6410(const struct dmi_system_id *id)
++{
++	acpi_handle handle;
++	int have_blnf;
++	printk(KERN_INFO "fujitsu-laptop: Identified laptop model '%s'.\n",
++	       id->ident);
++	have_blnf = ACPI_SUCCESS
++	    (acpi_get_handle(NULL, "\\_SB.PCI0.GFX0.LCD.BLNF", &handle));
++	if (use_alt_lcd_levels == -1) {
++		vdbg_printk(FUJLAPTOP_DBG_TRACE, "auto-detecting usealt\n");
++		use_alt_lcd_levels = 1;
++	}
++	if (disable_brightness_keys == -1) {
++		vdbg_printk(FUJLAPTOP_DBG_TRACE,
++			    "auto-detecting disable_keys\n");
++		disable_brightness_keys = have_blnf ? 1 : 0;
++	}
++	if (disable_brightness_adjust == -1) {
++		vdbg_printk(FUJLAPTOP_DBG_TRACE,
++			    "auto-detecting disable_adjust\n");
++		disable_brightness_adjust = have_blnf ? 0 : 1;
++	}
++	return 0;
++}
++
++static struct dmi_system_id __initdata fujitsu_dmi_table[] = {
++	{
++	 .ident = "Fujitsu Siemens",
++	 .matches = {
++		     DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
++		     DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6410"),
++		     },
++	 .callback = dmi_check_cb_s6410},
++	{}
++};
++
++/* ACPI device for LCD brightness control */
+ 
+ static int acpi_fujitsu_add(struct acpi_device *device)
+ {
++	acpi_status status;
++	acpi_handle handle;
+ 	int result = 0;
+ 	int state = 0;
+-
+-	ACPI_FUNCTION_TRACE("acpi_fujitsu_add");
++	struct input_dev *input;
++	int error;
+ 
+ 	if (!device)
+ 		return -EINVAL;
+@@ -209,10 +485,42 @@ static int acpi_fujitsu_add(struct acpi_device *device)
+ 	sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS);
+ 	acpi_driver_data(device) = fujitsu;
+ 
++	status = acpi_install_notify_handler(device->handle,
++					     ACPI_DEVICE_NOTIFY,
++					     acpi_fujitsu_notify, fujitsu);
++
++	if (ACPI_FAILURE(status)) {
++		printk(KERN_ERR "Error installing notify handler\n");
++		error = -ENODEV;
++		goto err_stop;
++	}
++
++	fujitsu->input = input = input_allocate_device();
++	if (!input) {
++		error = -ENOMEM;
++		goto err_uninstall_notify;
++	}
++
++	snprintf(fujitsu->phys, sizeof(fujitsu->phys),
++		 "%s/video/input0", acpi_device_hid(device));
++
++	input->name = acpi_device_name(device);
++	input->phys = fujitsu->phys;
++	input->id.bustype = BUS_HOST;
++	input->id.product = 0x06;
++	input->dev.parent = &device->dev;
++	input->evbit[0] = BIT(EV_KEY);
++	set_bit(KEY_BRIGHTNESSUP, input->keybit);
++	set_bit(KEY_BRIGHTNESSDOWN, input->keybit);
++	set_bit(KEY_UNKNOWN, input->keybit);
++
++	error = input_register_device(input);
++	if (error)
++		goto err_free_input_dev;
++
+ 	result = acpi_bus_get_power(fujitsu->acpi_handle, &state);
+ 	if (result) {
+-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+-				  "Error reading power state\n"));
++		printk(KERN_ERR "Error reading power state\n");
+ 		goto end;
+ 	}
+ 
+@@ -220,22 +528,373 @@ static int acpi_fujitsu_add(struct acpi_device *device)
+ 	       acpi_device_name(device), acpi_device_bid(device),
+ 	       !device->power.state ? "on" : "off");
+ 
+-      end:
++	fujitsu->dev = device;
++
++	if (ACPI_SUCCESS
++	    (acpi_get_handle(device->handle, METHOD_NAME__INI, &handle))) {
++		vdbg_printk(FUJLAPTOP_DBG_INFO, "Invoking _INI\n");
++		if (ACPI_FAILURE
++		    (acpi_evaluate_object
++		     (device->handle, METHOD_NAME__INI, NULL, NULL)))
++			printk(KERN_ERR "_INI Method failed\n");
++	}
++
++	/* do config (detect defaults) */
++	dmi_check_system(fujitsu_dmi_table);
++	use_alt_lcd_levels = use_alt_lcd_levels == 1 ? 1 : 0;
++	disable_brightness_keys = disable_brightness_keys == 1 ? 1 : 0;
++	disable_brightness_adjust = disable_brightness_adjust == 1 ? 1 : 0;
++	vdbg_printk(FUJLAPTOP_DBG_INFO,
++		    "config: [alt interface: %d], [key disable: %d], [adjust disable: %d]\n",
++		    use_alt_lcd_levels, disable_brightness_keys,
++		    disable_brightness_adjust);
++
++	if (get_max_brightness() <= 0)
++		fujitsu->max_brightness = FUJITSU_LCD_N_LEVELS;
++	if (use_alt_lcd_levels)
++		get_lcd_level_alt();
++	else
++		get_lcd_level();
++
++	return result;
++
++end:
++err_free_input_dev:
++	input_free_device(input);
++err_uninstall_notify:
++	acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
++				   acpi_fujitsu_notify);
++err_stop:
+ 
+ 	return result;
+ }
+ 
+ static int acpi_fujitsu_remove(struct acpi_device *device, int type)
+ {
+-	ACPI_FUNCTION_TRACE("acpi_fujitsu_remove");
++	acpi_status status;
++	struct fujitsu_t *fujitsu = NULL;
+ 
+ 	if (!device || !acpi_driver_data(device))
+ 		return -EINVAL;
++
++	fujitsu = acpi_driver_data(device);
++
++	status = acpi_remove_notify_handler(fujitsu->acpi_handle,
++					    ACPI_DEVICE_NOTIFY,
++					    acpi_fujitsu_notify);
++
++	if (!device || !acpi_driver_data(device))
++		return -EINVAL;
++
+ 	fujitsu->acpi_handle = NULL;
+ 
+ 	return 0;
+ }
+ 
++/* Brightness notify */
++
++static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data)
++{
++	struct input_dev *input;
++	int keycode;
++	int oldb, newb;
++
++	input = fujitsu->input;
++
++	switch (event) {
++	case ACPI_FUJITSU_NOTIFY_CODE1:
++		keycode = 0;
++		oldb = fujitsu->brightness_level;
++		get_lcd_level();  /* the alt version always yields changed */
++		newb = fujitsu->brightness_level;
++
++		vdbg_printk(FUJLAPTOP_DBG_TRACE,
++			    "brightness button event [%i -> %i (%i)]\n",
++			    oldb, newb, fujitsu->brightness_changed);
++
++		if (oldb == newb && fujitsu->brightness_changed) {
++			keycode = 0;
++			if (disable_brightness_keys != 1) {
++				if (oldb == 0) {
++					acpi_bus_generate_proc_event(fujitsu->
++						dev,
++						ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS,
++						0);
++					keycode = KEY_BRIGHTNESSDOWN;
++				} else if (oldb ==
++					   (fujitsu->max_brightness) - 1) {
++					acpi_bus_generate_proc_event(fujitsu->
++						dev,
++						ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS,
++						0);
++					keycode = KEY_BRIGHTNESSUP;
++				}
++			}
++		} else if (oldb < newb) {
++			if (disable_brightness_adjust != 1) {
++				if (use_alt_lcd_levels)
++					set_lcd_level_alt(newb);
++				else
++					set_lcd_level(newb);
++			}
++			if (disable_brightness_keys != 1) {
++				acpi_bus_generate_proc_event(fujitsu->dev,
++					ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS,
++					0);
++				keycode = KEY_BRIGHTNESSUP;
++			}
++		} else if (oldb > newb) {
++			if (disable_brightness_adjust != 1) {
++				if (use_alt_lcd_levels)
++					set_lcd_level_alt(newb);
++				else
++					set_lcd_level(newb);
++			}
++			if (disable_brightness_keys != 1) {
++				acpi_bus_generate_proc_event(fujitsu->dev,
++					ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS,
++					0);
++				keycode = KEY_BRIGHTNESSDOWN;
++			}
++		} else {
++			keycode = KEY_UNKNOWN;
++		}
++		break;
++	default:
++		keycode = KEY_UNKNOWN;
++		vdbg_printk(FUJLAPTOP_DBG_WARN,
++			    "unsupported event [0x%x]\n", event);
++		break;
++	}
++
++	if (keycode != 0) {
++		input_report_key(input, keycode, 1);
++		input_sync(input);
++		input_report_key(input, keycode, 0);
++		input_sync(input);
++	}
++
++	return;
++}
++
++/* ACPI device for hotkey handling */
++
++static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
++{
++	acpi_status status;
++	acpi_handle handle;
++	int result = 0;
++	int state = 0;
++	struct input_dev *input;
++	int error;
++	int i;
++
++	if (!device)
++		return -EINVAL;
++
++	fujitsu_hotkey->acpi_handle = device->handle;
++	sprintf(acpi_device_name(device), "%s",
++		ACPI_FUJITSU_HOTKEY_DEVICE_NAME);
++	sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS);
++	acpi_driver_data(device) = fujitsu_hotkey;
++
++	status = acpi_install_notify_handler(device->handle,
++					     ACPI_DEVICE_NOTIFY,
++					     acpi_fujitsu_hotkey_notify,
++					     fujitsu_hotkey);
++
++	if (ACPI_FAILURE(status)) {
++		printk(KERN_ERR "Error installing notify handler\n");
++		error = -ENODEV;
++		goto err_stop;
++	}
++
++	/* kfifo */
++	spin_lock_init(&fujitsu_hotkey->fifo_lock);
++	fujitsu_hotkey->fifo =
++	    kfifo_alloc(RINGBUFFERSIZE * sizeof(int), GFP_KERNEL,
++			&fujitsu_hotkey->fifo_lock);
++	if (IS_ERR(fujitsu_hotkey->fifo)) {
++		printk(KERN_ERR "kfifo_alloc failed\n");
++		error = PTR_ERR(fujitsu_hotkey->fifo);
++		goto err_stop;
++	}
++
++	fujitsu_hotkey->input = input = input_allocate_device();
++	if (!input) {
++		error = -ENOMEM;
++		goto err_uninstall_notify;
++	}
++
++	snprintf(fujitsu_hotkey->phys, sizeof(fujitsu_hotkey->phys),
++		 "%s/video/input0", acpi_device_hid(device));
++
++	input->name = acpi_device_name(device);
++	input->phys = fujitsu_hotkey->phys;
++	input->id.bustype = BUS_HOST;
++	input->id.product = 0x06;
++	input->dev.parent = &device->dev;
++	input->evbit[0] = BIT(EV_KEY);
++	set_bit(KEY_SCREENLOCK, input->keybit);
++	set_bit(KEY_MEDIA, input->keybit);
++	set_bit(KEY_EMAIL, input->keybit);
++	set_bit(KEY_SUSPEND, input->keybit);
++	set_bit(KEY_UNKNOWN, input->keybit);
++
++	error = input_register_device(input);
++	if (error)
++		goto err_free_input_dev;
++
++	result = acpi_bus_get_power(fujitsu_hotkey->acpi_handle, &state);
++	if (result) {
++		printk(KERN_ERR "Error reading power state\n");
++		goto end;
++	}
++
++	printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
++	       acpi_device_name(device), acpi_device_bid(device),
++	       !device->power.state ? "on" : "off");
++
++	fujitsu_hotkey->dev = device;
++
++	if (ACPI_SUCCESS
++	    (acpi_get_handle(device->handle, METHOD_NAME__INI, &handle))) {
++		vdbg_printk(FUJLAPTOP_DBG_INFO, "Invoking _INI\n");
++		if (ACPI_FAILURE
++		    (acpi_evaluate_object
++		     (device->handle, METHOD_NAME__INI, NULL, NULL)))
++			printk(KERN_ERR "_INI Method failed\n");
++	}
++
++	i = 0;			/* Discard hotkey ringbuffer */
++	while (get_irb() != 0 && (i++) < MAX_HOTKEY_RINGBUFFER_SIZE) ;
++	vdbg_printk(FUJLAPTOP_DBG_INFO, "Discarded %i ringbuffer entries\n", i);
++
++	return result;
++
++end:
++err_free_input_dev:
++	input_free_device(input);
++err_uninstall_notify:
++	acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
++				   acpi_fujitsu_hotkey_notify);
++	kfifo_free(fujitsu_hotkey->fifo);
++err_stop:
++
++	return result;
++}
++
++static int acpi_fujitsu_hotkey_remove(struct acpi_device *device, int type)
++{
++	acpi_status status;
++	struct fujitsu_hotkey_t *fujitsu_hotkey = NULL;
++
++	if (!device || !acpi_driver_data(device))
++		return -EINVAL;
++
++	fujitsu_hotkey = acpi_driver_data(device);
++
++	status = acpi_remove_notify_handler(fujitsu_hotkey->acpi_handle,
++					    ACPI_DEVICE_NOTIFY,
++					    acpi_fujitsu_hotkey_notify);
++
++	fujitsu_hotkey->acpi_handle = NULL;
++
++	kfifo_free(fujitsu_hotkey->fifo);
++
++	return 0;
++}
++
++static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
++				       void *data)
++{
++	struct input_dev *input;
++	int keycode, keycode_r;
++	unsigned int irb = 1;
++	int i, status;
++
++	input = fujitsu_hotkey->input;
++
++	vdbg_printk(FUJLAPTOP_DBG_TRACE, "Hotkey event\n");
++
++	switch (event) {
++	case ACPI_FUJITSU_NOTIFY_CODE1:
++		i = 0;
++		while ((irb = get_irb()) != 0
++		       && (i++) < MAX_HOTKEY_RINGBUFFER_SIZE) {
++			vdbg_printk(FUJLAPTOP_DBG_TRACE, "GIRB result [%x]\n",
++				    irb);
++
++			switch (irb & 0x4ff) {
++			case LOCK_KEY:
++				keycode = KEY_SCREENLOCK;
++				break;
++			case DISPLAY_KEY:
++				keycode = KEY_MEDIA;
++				break;
++			case ENERGY_KEY:
++				keycode = KEY_EMAIL;
++				break;
++			case REST_KEY:
++				keycode = KEY_SUSPEND;
++				break;
++			case 0:
++				keycode = 0;
++				break;
++			default:
++				vdbg_printk(FUJLAPTOP_DBG_WARN,
++					"Unknown GIRB result [%x]\n", irb);
++				keycode = -1;
++				break;
++			}
++			if (keycode > 0) {
++				vdbg_printk(FUJLAPTOP_DBG_TRACE,
++					"Push keycode into ringbuffer [%d]\n",
++					keycode);
++				status = kfifo_put(fujitsu_hotkey->fifo,
++						(unsigned char *)&keycode,
++						sizeof(keycode));
++				if (status != sizeof(keycode)) {
++					vdbg_printk(FUJLAPTOP_DBG_WARN,
++						"Could not push keycode [0x%x]\n",
++						keycode);
++				} else {
++					input_report_key(input, keycode, 1);
++					input_sync(input);
++				}
++			} else if (keycode == 0) {
++				while ((status =
++					kfifo_get
++					(fujitsu_hotkey->fifo, (unsigned char *)
++					 &keycode_r,
++					 sizeof
++					 (keycode_r))) == sizeof(keycode_r)) {
++					input_report_key(input, keycode_r, 0);
++					input_sync(input);
++					vdbg_printk(FUJLAPTOP_DBG_TRACE,
++						    "Pop keycode from ringbuffer [%d]\n",
++						    keycode_r);
++				}
++			}
++		}
++
++		break;
++	default:
++		keycode = KEY_UNKNOWN;
++		vdbg_printk(FUJLAPTOP_DBG_WARN,
++			    "Unsupported event [0x%x]\n", event);
++		input_report_key(input, keycode, 1);
++		input_sync(input);
++		input_report_key(input, keycode, 0);
++		input_sync(input);
++		break;
++	}
++
++	return;
++}
++
++/* Initialization */
++
+ static const struct acpi_device_id fujitsu_device_ids[] = {
+ 	{ACPI_FUJITSU_HID, 0},
+ 	{"", 0},
+@@ -251,11 +910,24 @@ static struct acpi_driver acpi_fujitsu_driver = {
+ 		},
+ };
+ 
+-/* Initialization */
++static const struct acpi_device_id fujitsu_hotkey_device_ids[] = {
++	{ACPI_FUJITSU_HOTKEY_HID, 0},
++	{"", 0},
++};
++
++static struct acpi_driver acpi_fujitsu_hotkey_driver = {
++	.name = ACPI_FUJITSU_HOTKEY_DRIVER_NAME,
++	.class = ACPI_FUJITSU_CLASS,
++	.ids = fujitsu_hotkey_device_ids,
++	.ops = {
++		.add = acpi_fujitsu_hotkey_add,
++		.remove = acpi_fujitsu_hotkey_remove,
++		},
++};
+ 
+ static int __init fujitsu_init(void)
+ {
+-	int ret, result;
++	int ret, result, max_brightness;
+ 
+ 	if (acpi_disabled)
+ 		return -ENODEV;
+@@ -271,19 +943,6 @@ static int __init fujitsu_init(void)
+ 		goto fail_acpi;
+ 	}
+ 
+-	/* Register backlight stuff */
+-
+-	fujitsu->bl_device =
+-	    backlight_device_register("fujitsu-laptop", NULL, NULL,
+-				      &fujitsubl_ops);
+-	if (IS_ERR(fujitsu->bl_device))
+-		return PTR_ERR(fujitsu->bl_device);
+-
+-	fujitsu->bl_device->props.max_brightness = FUJITSU_LCD_N_LEVELS - 1;
+-	ret = platform_driver_register(&fujitsupf_driver);
+-	if (ret)
+-		goto fail_backlight;
+-
+ 	/* Register platform stuff */
+ 
+ 	fujitsu->pf_device = platform_device_alloc("fujitsu-laptop", -1);
+@@ -302,28 +961,68 @@ static int __init fujitsu_init(void)
+ 	if (ret)
+ 		goto fail_platform_device2;
+ 
++	/* Register backlight stuff */
++
++	fujitsu->bl_device =
++	    backlight_device_register("fujitsu-laptop", NULL, NULL,
++				      &fujitsubl_ops);
++	if (IS_ERR(fujitsu->bl_device))
++		return PTR_ERR(fujitsu->bl_device);
++
++	max_brightness = fujitsu->max_brightness;
++
++	fujitsu->bl_device->props.max_brightness = max_brightness - 1;
++	fujitsu->bl_device->props.brightness = fujitsu->brightness_level;
++
++	ret = platform_driver_register(&fujitsupf_driver);
++	if (ret)
++		goto fail_backlight;
++
++	/* Register hotkey driver */
++
++	fujitsu_hotkey = kmalloc(sizeof(struct fujitsu_hotkey_t), GFP_KERNEL);
++	if (!fujitsu_hotkey) {
++		ret = -ENOMEM;
++		goto fail_hotkey;
++	}
++	memset(fujitsu_hotkey, 0, sizeof(struct fujitsu_hotkey_t));
++
++	result = acpi_bus_register_driver(&acpi_fujitsu_hotkey_driver);
++	if (result < 0) {
++		ret = -ENODEV;
++		goto fail_hotkey1;
++	}
++
+ 	printk(KERN_INFO "fujitsu-laptop: driver " FUJITSU_DRIVER_VERSION
+ 	       " successfully loaded.\n");
+ 
+ 	return 0;
+ 
+-      fail_platform_device2:
++fail_hotkey1:
+ 
+-	platform_device_del(fujitsu->pf_device);
+-
+-      fail_platform_device1:
+-
+-	platform_device_put(fujitsu->pf_device);
++	kfree(fujitsu_hotkey);
+ 
+-      fail_platform_driver:
++fail_hotkey:
+ 
+ 	platform_driver_unregister(&fujitsupf_driver);
+ 
+-      fail_backlight:
++fail_backlight:
+ 
+ 	backlight_device_unregister(fujitsu->bl_device);
+ 
+-      fail_acpi:
++fail_platform_device2:
++
++	platform_device_del(fujitsu->pf_device);
++
++fail_platform_device1:
++
++	platform_device_put(fujitsu->pf_device);
++
++fail_platform_driver:
++
++	acpi_bus_unregister_driver(&acpi_fujitsu_driver);
++
++fail_acpi:
+ 
+ 	kfree(fujitsu);
+ 
+@@ -342,19 +1041,43 @@ static void __exit fujitsu_cleanup(void)
+ 
+ 	kfree(fujitsu);
+ 
++	acpi_bus_unregister_driver(&acpi_fujitsu_hotkey_driver);
++
++	kfree(fujitsu_hotkey);
++
+ 	printk(KERN_INFO "fujitsu-laptop: driver unloaded.\n");
+ }
+ 
+ module_init(fujitsu_init);
+ module_exit(fujitsu_cleanup);
+ 
+-MODULE_AUTHOR("Jonathan Woithe");
++module_param(use_alt_lcd_levels, uint, 0644);
++MODULE_PARM_DESC(use_alt_lcd_levels,
++		 "Use alternative interface for lcd_levels (needed for Lifebook s6410).");
++module_param(disable_brightness_keys, uint, 0644);
++MODULE_PARM_DESC(disable_brightness_keys,
++		 "Disable brightness keys (eg. if they are already handled by the generic ACPI_VIDEO device).");
++module_param(disable_brightness_adjust, uint, 0644);
++MODULE_PARM_DESC(disable_brightness_adjust, "Disable brightness adjustment .");
++#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG
++module_param_named(debug, dbg_level, uint, 0644);
++MODULE_PARM_DESC(debug, "Sets debug level bit-mask");
++#endif
++
++MODULE_AUTHOR("Jonathan Woithe, Peter Gruber");
+ MODULE_DESCRIPTION("Fujitsu laptop extras support");
+ MODULE_VERSION(FUJITSU_DRIVER_VERSION);
+ MODULE_LICENSE("GPL");
+ 
++MODULE_ALIAS
++    ("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*");
++MODULE_ALIAS
++    ("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*");
++
+ static struct pnp_device_id pnp_ids[] = {
+ 	{ .id = "FUJ02bf" },
++	{ .id = "FUJ02B1" },
++	{ .id = "FUJ02E3" },
+ 	{ .id = "" }
+ };
+ MODULE_DEVICE_TABLE(pnp, pnp_ids);

commit aa27a44395c3d35bc16e52f1e709e0fb2a3709e4
+Author: Jonathan Woithe 
+Date:   Fri Feb 8 12:44:17 2008 +0100
+
+    [ALSA] hda-codec - remove duplicate controls in alc268 test mixer
+    
+    I've just noticed that there are a handful of duplicate controls in the
+    ALC268 test model mixer.  This patch (against alsa-driver 1.0.16) removes
+    them.
+    
+    Signed-off-by: Jonathan Woithe 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 85ea3f82de19..e4a7c50e9f73 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -9840,11 +9840,6 @@ static struct hda_input_mux alc268_capture_source = {
+ 
+ #ifdef CONFIG_SND_DEBUG
+ static struct snd_kcontrol_new alc268_test_mixer[] = {
+-	HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
+-	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
+-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+-
+ 	/* Volume widgets */
+ 	HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+ 	HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x03, 0x0, HDA_OUTPUT),

commit 86c53bd26b431767438c65f89863471be177f0f7
+Author: Jonathan Woithe 
+Date:   Tue Jan 8 12:33:19 2008 +0100
+
+    [ALSA] hda-codec - Add test model for ALC268
+    
+    This implements a test model for the ALC268.  It depends on the feature
+    added by alc260-test-eapd-0.2.diff.  This patch also adds a mention of
+    the ALC260 test model to ALSA-Configuration.txt since this seems to have
+    been missed.
+    
+    Signed-off-by: Jonathan Woithe 
+    Signed-off-by: Takashi Iwai 
+    Signed-off-by: Jaroslav Kysela 
+
+diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
+index afdb6ffeae55..22aee1a5dd6e 100644
+--- a/Documentation/sound/alsa/ALSA-Configuration.txt
++++ b/Documentation/sound/alsa/ALSA-Configuration.txt
+@@ -801,6 +801,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
+ 	  will		Will laptops (PB V7900)
+ 	  replacer	Replacer 672V
+ 	  basic		fixed pin assignment (old default model)
++	  test		for testing/debugging purpose, almost all controls can
++			adjusted.  Appearing only when compiled with
++			$CONFIG_SND_DEBUG=y
+ 	  auto		auto-config reading BIOS (default)
+ 
+ 	ALC262
+@@ -821,6 +824,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
+ 	  3stack	3-stack model
+ 	  toshiba	Toshiba A205
+ 	  acer		Acer laptops
++	  test		for testing/debugging purpose, almost all controls can
++			adjusted.  Appearing only when compiled with
++			$CONFIG_SND_DEBUG=y
+ 	  auto		auto-config reading BIOS (default)
+ 
+ 	ALC662
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 0a64d24e7fda..1b2ad52bc908 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -106,6 +106,9 @@ enum {
+ 	ALC268_3ST,
+ 	ALC268_TOSHIBA,
+ 	ALC268_ACER,
++#ifdef CONFIG_SND_DEBUG
++	ALC268_TEST,
++#endif
+ 	ALC268_AUTO,
+ 	ALC268_MODEL_LAST /* last tag */
+ };
+@@ -9366,6 +9369,60 @@ static struct hda_input_mux alc268_capture_source = {
+ 	},
+ };
+ 
++#ifdef CONFIG_SND_DEBUG
++static struct snd_kcontrol_new alc268_test_mixer[] = {
++	HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
++	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
++	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
++	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
++
++	/* Volume widgets */
++	HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x02, 0x0, HDA_OUTPUT),
++	HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x03, 0x0, HDA_OUTPUT),
++	HDA_BIND_MUTE_MONO("Mono sum Playback Switch", 0x0e, 1, 2, HDA_INPUT),
++	HDA_BIND_MUTE("LINE-OUT sum Playback Switch", 0x0f, 2, HDA_INPUT),
++	HDA_BIND_MUTE("HP-OUT sum Playback Switch", 0x10, 2, HDA_INPUT),
++	HDA_BIND_MUTE("LINE-OUT Playback Switch", 0x14, 2, HDA_OUTPUT),
++	HDA_BIND_MUTE("HP-OUT Playback Switch", 0x15, 2, HDA_OUTPUT),
++	HDA_BIND_MUTE("Mono Playback Switch", 0x16, 2, HDA_OUTPUT),
++	HDA_CODEC_VOLUME("MIC1 Capture Volume", 0x18, 0x0, HDA_INPUT),
++	HDA_BIND_MUTE("MIC1 Capture Switch", 0x18, 2, HDA_OUTPUT),
++	HDA_CODEC_VOLUME("MIC2 Capture Volume", 0x19, 0x0, HDA_INPUT),
++	HDA_CODEC_VOLUME("LINE1 Capture Volume", 0x1a, 0x0, HDA_INPUT),
++	HDA_BIND_MUTE("LINE1 Capture Switch", 0x1a, 2, HDA_OUTPUT),
++	HDA_CODEC_VOLUME("PCBEEP Playback Volume", 0x1d, 0x0, HDA_INPUT),
++	HDA_CODEC_VOLUME("PCM-IN1 Capture Volume", 0x23, 0x0, HDA_OUTPUT),
++	HDA_BIND_MUTE("PCM-IN1 Capture Switch", 0x23, 2, HDA_OUTPUT),
++	HDA_CODEC_VOLUME("PCM-IN2 Capture Volume", 0x24, 0x0, HDA_OUTPUT),
++	HDA_BIND_MUTE("PCM-IN2 Capture Switch", 0x24, 2, HDA_OUTPUT),
++
++	/* Modes for retasking pin widgets */
++	ALC_PIN_MODE("LINE-OUT pin mode", 0x14, ALC_PIN_DIR_INOUT),
++	ALC_PIN_MODE("HP-OUT pin mode", 0x15, ALC_PIN_DIR_INOUT),
++	ALC_PIN_MODE("MIC1 pin mode", 0x18, ALC_PIN_DIR_INOUT),
++	ALC_PIN_MODE("LINE1 pin mode", 0x1a, ALC_PIN_DIR_INOUT),
++
++	/* Controls for GPIO pins, assuming they are configured as outputs */
++	ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
++	ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
++	ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
++	ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
++
++	/* Switches to allow the digital SPDIF output pin to be enabled.
++	 * The ALC268 does not have an SPDIF input.
++	 */
++	ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x06, 0x01),
++
++	/* A switch allowing EAPD to be enabled.  Some laptops seem to use
++	 * this output to turn on an external amplifier.
++	 */
++	ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02),
++	ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02),
++
++	{ } /* end */
++};
++#endif
++
+ /* create input playback/capture controls for the given pin */
+ static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid,
+ 				    const char *ctlname, int idx)
+@@ -9578,6 +9635,9 @@ static const char *alc268_models[ALC268_MODEL_LAST] = {
+ 	[ALC268_3ST]		= "3stack",
+ 	[ALC268_TOSHIBA]	= "toshiba",
+ 	[ALC268_ACER]		= "acer",
++#ifdef CONFIG_SND_DEBUG
++	[ALC268_TEST]		= "test",
++#endif
+ 	[ALC268_AUTO]		= "auto",
+ };
+ 
+@@ -9636,6 +9696,22 @@ static struct alc_config_preset alc268_presets[] = {
+ 		.unsol_event = alc268_acer_unsol_event,
+ 		.init_hook = alc268_acer_init_hook,
+ 	},
++#ifdef CONFIG_SND_DEBUG
++	[ALC268_TEST] = {
++		.mixers = { alc268_test_mixer, alc268_capture_mixer },
++		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
++				alc268_volume_init_verbs },
++		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
++		.dac_nids = alc268_dac_nids,
++		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
++		.adc_nids = alc268_adc_nids_alt,
++		.hp_nid = 0x03,
++		.dig_out_nid = ALC268_DIGOUT_NID,
++		.num_channel_mode = ARRAY_SIZE(alc268_modes),
++		.channel_mode = alc268_modes,
++		.input_mux = &alc268_capture_source,
++	},
++#endif
+ };
+ 
+ static int patch_alc268(struct hda_codec *codec)

commit f8225f6d1f68c3d0a0fe844dc40a11cd432a853b
+Author: Jonathan Woithe 
+Date:   Tue Jan 8 12:16:54 2008 +0100
+
+    [ALSA] hda-codec - Add EAPD controls for ALC260 test model
+    
+    This implements a switch control for the EAPD signal output by the ALC26x
+    chips.  Since some laptops may utilise this to activate useful things it
+    is handy to have a control for this in the ALC26x test models.  The patch
+    includes the control in the ALC260 test model.
+    
+    Signed-off-by: Jonathan Woithe 
+    Signed-off-by: Takashi Iwai 
+    Signed-off-by: Jaroslav Kysela 
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 617f3ee304b1..0a64d24e7fda 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -608,6 +608,59 @@ static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol,
+ 	  .private_value = nid | (mask<<16) }
+ #endif   /* CONFIG_SND_DEBUG */
+ 
++/* A switch control to allow the enabling EAPD digital outputs on the ALC26x.
++ * Again, this is only used in the ALC26x test models to help identify when
++ * the EAPD line must be asserted for features to work.
++ */
++#ifdef CONFIG_SND_DEBUG
++#define alc_eapd_ctrl_info	snd_ctl_boolean_mono_info
++
++static int alc_eapd_ctrl_get(struct snd_kcontrol *kcontrol,
++			      struct snd_ctl_elem_value *ucontrol)
++{
++	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
++	hda_nid_t nid = kcontrol->private_value & 0xffff;
++	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
++	long *valp = ucontrol->value.integer.value;
++	unsigned int val = snd_hda_codec_read(codec, nid, 0,
++					      AC_VERB_GET_EAPD_BTLENABLE, 0x00);
++
++	*valp = (val & mask) != 0;
++	return 0;
++}
++
++static int alc_eapd_ctrl_put(struct snd_kcontrol *kcontrol,
++			      struct snd_ctl_elem_value *ucontrol)
++{
++	int change;
++	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
++	hda_nid_t nid = kcontrol->private_value & 0xffff;
++	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
++	long val = *ucontrol->value.integer.value;
++	unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
++						    AC_VERB_GET_EAPD_BTLENABLE,
++						    0x00);
++
++	/* Set/unset the masked control bit(s) as needed */
++	change = (!val ? 0 : mask) != (ctrl_data & mask);
++	if (!val)
++		ctrl_data &= ~mask;
++	else
++		ctrl_data |= mask;
++	snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
++				  ctrl_data);
++
++	return change;
++}
++
++#define ALC_EAPD_CTRL_SWITCH(xname, nid, mask) \
++	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
++	  .info = alc_eapd_ctrl_info, \
++	  .get = alc_eapd_ctrl_get, \
++	  .put = alc_eapd_ctrl_put, \
++	  .private_value = nid | (mask<<16) }
++#endif   /* CONFIG_SND_DEBUG */
++
+ /*
+  * set up from the preset table
+  */
+@@ -4332,6 +4385,12 @@ static struct snd_kcontrol_new alc260_test_mixer[] = {
+ 	ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x03, 0x01),
+ 	ALC_SPDIF_CTRL_SWITCH("SPDIF Capture Switch", 0x06, 0x01),
+ 
++	/* A switch allowing EAPD to be enabled.  Some laptops seem to use
++	 * this output to turn on an external amplifier.
++	 */
++	ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02),
++	ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02),
++
+ 	{ } /* end */
+ };
+ static struct hda_verb alc260_test_init_verbs[] = {

commit d0482533c73a8685f7ce0951a10280cfd58b8825
+Author: Jonathan Woithe 
+Date:   Wed Aug 29 15:58:19 2007 +0930
+
+    fujitsu-laptop: create Fujitsu laptop platform specific driver
+    
+    Signed-off-by: Jonathan Woithe 
+    Signed-off-by: Len Brown 
+
+diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
+index a26655881e6a..df89367032c3 100644
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -111,6 +111,21 @@ config ASUS_LAPTOP
+ 
+ 	  If you have an ACPI-compatible ASUS laptop, say Y or M here.
+ 
++config FUJITSU_LAPTOP
++        tristate "Fujitsu Laptop Extras"
++        depends on X86
++        depends on ACPI
++        depends on BACKLIGHT_CLASS_DEVICE
++        ---help---
++	  This is a driver for laptops built by Fujitsu:
++
++	    * P2xxx/P5xxx/S6xxx/S7xxx series Lifebooks
++	    * Possibly other Fujitsu laptop models
++
++	  It adds support for LCD brightness control.
++
++	  If you have a Fujitsu laptop, say Y or M here.
++
+ config MSI_LAPTOP
+         tristate "MSI Laptop Extras"
+         depends on X86
+diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
+index b5ce0e3dba86..be90d483d2f9 100644
+--- a/drivers/misc/Makefile
++++ b/drivers/misc/Makefile
+@@ -14,4 +14,5 @@ obj-$(CONFIG_PHANTOM)		+= phantom.o
+ obj-$(CONFIG_SGI_IOC4)		+= ioc4.o
+ obj-$(CONFIG_SONY_LAPTOP)	+= sony-laptop.o
+ obj-$(CONFIG_THINKPAD_ACPI)	+= thinkpad_acpi.o
++obj-$(CONFIG_FUJITSU_LAPTOP)	+= fujitsu-laptop.o
+ obj-$(CONFIG_EEPROM_93CX6)	+= eeprom_93cx6.o
+diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c
+new file mode 100644
+index 000000000000..d366a6cc1fd9
+--- /dev/null
++++ b/drivers/misc/fujitsu-laptop.c
+@@ -0,0 +1,358 @@
++/*-*-linux-c-*-*/
++
++/*
++  Copyright (C) 2007 Jonathan Woithe 
++  Based on earlier work:
++    Copyright (C) 2003 Shane Spencer 
++    Adrian Yee 
++
++  Templated from msi-laptop.c which is copyright by its respective authors.
++
++  This program is free software; you can redistribute it and/or modify
++  it under the terms of the GNU General Public License as published by
++  the Free Software Foundation; either version 2 of the License, or
++  (at your option) any later version.
++
++  This program is distributed in the hope that it will be useful, but
++  WITHOUT ANY WARRANTY; without even the implied warranty of
++  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++  General Public License for more details.
++
++  You should have received a copy of the GNU General Public License
++  along with this program; if not, write to the Free Software
++  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
++  02110-1301, USA.
++ */
++
++/*
++ * fujitsu-laptop.c - Fujitsu laptop support, providing access to additional
++ * features made available on a range of Fujitsu laptops including the
++ * P2xxx/P5xxx/S6xxx/S7xxx series.
++ *
++ * This driver exports a few files in /sys/devices/platform/fujitsu-laptop/;
++ * others may be added at a later date.
++ *
++ *   lcd_level - Screen brightness: contains a single integer in the
++ *   range 0..7. (rw)
++ *
++ * In addition to these platform device attributes the driver
++ * registers itself in the Linux backlight control subsystem and is
++ * available to userspace under /sys/class/backlight/fujitsu-laptop/.
++ *
++ * This driver has been tested on a Fujitsu Lifebook S7020.  It should
++ * work on most P-series and S-series Lifebooks, but YMMV.
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#define FUJITSU_DRIVER_VERSION "0.3"
++
++#define FUJITSU_LCD_N_LEVELS 8
++
++#define ACPI_FUJITSU_CLASS              "fujitsu"
++#define ACPI_FUJITSU_HID                "FUJ02B1"
++#define ACPI_FUJITSU_DRIVER_NAME        "Fujitsu laptop FUJ02B1 ACPI extras driver"
++#define ACPI_FUJITSU_DEVICE_NAME        "Fujitsu FUJ02B1"
++
++struct fujitsu_t {
++	acpi_handle acpi_handle;
++	struct backlight_device *bl_device;
++	struct platform_device *pf_device;
++
++	unsigned long fuj02b1_state;
++	unsigned int brightness_changed;
++	unsigned int brightness_level;
++};
++
++static struct fujitsu_t *fujitsu;
++
++/* Hardware access */
++
++static int set_lcd_level(int level)
++{
++	acpi_status status = AE_OK;
++	union acpi_object arg0 = { ACPI_TYPE_INTEGER };
++	struct acpi_object_list arg_list = { 1, &arg0 };
++	acpi_handle handle = NULL;
++
++	if (level < 0 || level >= FUJITSU_LCD_N_LEVELS)
++		return -EINVAL;
++
++	if (!fujitsu)
++		return -EINVAL;
++
++	status = acpi_get_handle(fujitsu->acpi_handle, "SBLL", &handle);
++	if (ACPI_FAILURE(status)) {
++		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SBLL not present\n"));
++		return -ENODEV;
++	}
++
++	arg0.integer.value = level;
++
++	status = acpi_evaluate_object(handle, NULL, &arg_list, NULL);
++	if (ACPI_FAILURE(status))
++		return -ENODEV;
++
++	return 0;
++}
++
++static int get_lcd_level(void)
++{
++	unsigned long state = 0;
++	acpi_status status = AE_OK;
++
++	// Get the Brightness
++	status =
++	    acpi_evaluate_integer(fujitsu->acpi_handle, "GBLL", NULL, &state);
++	if (status < 0)
++		return status;
++
++	fujitsu->fuj02b1_state = state;
++	fujitsu->brightness_level = state & 0x0fffffff;
++
++	if (state & 0x80000000)
++		fujitsu->brightness_changed = 1;
++	else
++		fujitsu->brightness_changed = 0;
++
++	if (status < 0)
++		return status;
++
++	return fujitsu->brightness_level;
++}
++
++/* Backlight device stuff */
++
++static int bl_get_brightness(struct backlight_device *b)
++{
++	return get_lcd_level();
++}
++
++static int bl_update_status(struct backlight_device *b)
++{
++	return set_lcd_level(b->props.brightness);
++}
++
++static struct backlight_ops fujitsubl_ops = {
++	.get_brightness = bl_get_brightness,
++	.update_status = bl_update_status,
++};
++
++/* Platform device */
++
++static ssize_t show_lcd_level(struct device *dev,
++			      struct device_attribute *attr, char *buf)
++{
++
++	int ret;
++
++	ret = get_lcd_level();
++	if (ret < 0)
++		return ret;
++
++	return sprintf(buf, "%i\n", ret);
++}
++
++static ssize_t store_lcd_level(struct device *dev,
++			       struct device_attribute *attr, const char *buf,
++			       size_t count)
++{
++
++	int level, ret;
++
++	if (sscanf(buf, "%i", &level) != 1
++	    || (level < 0 || level >= FUJITSU_LCD_N_LEVELS))
++		return -EINVAL;
++
++	ret = set_lcd_level(level);
++	if (ret < 0)
++		return ret;
++
++	return count;
++}
++
++static DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level);
++
++static struct attribute *fujitsupf_attributes[] = {
++	&dev_attr_lcd_level.attr,
++	NULL
++};
++
++static struct attribute_group fujitsupf_attribute_group = {
++	.attrs = fujitsupf_attributes
++};
++
++static struct platform_driver fujitsupf_driver = {
++	.driver = {
++		   .name = "fujitsu-laptop",
++		   .owner = THIS_MODULE,
++		   }
++};
++
++/* ACPI device */
++
++int acpi_fujitsu_add(struct acpi_device *device)
++{
++	int result = 0;
++	int state = 0;
++
++	ACPI_FUNCTION_TRACE("acpi_fujitsu_add");
++
++	if (!device)
++		return -EINVAL;
++
++	fujitsu->acpi_handle = device->handle;
++	sprintf(acpi_device_name(device), "%s", ACPI_FUJITSU_DEVICE_NAME);
++	sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS);
++	acpi_driver_data(device) = fujitsu;
++
++	result = acpi_bus_get_power(fujitsu->acpi_handle, &state);
++	if (result) {
++		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
++				  "Error reading power state\n"));
++		goto end;
++	}
++
++	printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
++	       acpi_device_name(device), acpi_device_bid(device),
++	       !device->power.state ? "on" : "off");
++
++      end:
++
++	return result;
++}
++
++int acpi_fujitsu_remove(struct acpi_device *device, int type)
++{
++	ACPI_FUNCTION_TRACE("acpi_fujitsu_remove");
++
++	if (!device || !acpi_driver_data(device))
++		return -EINVAL;
++	fujitsu->acpi_handle = 0;
++
++	return 0;
++}
++
++static const struct acpi_device_id fujitsu_device_ids[] = {
++	{ACPI_FUJITSU_HID, 0},
++	{"", 0},
++};
++
++static struct acpi_driver acpi_fujitsu_driver = {
++	.name = ACPI_FUJITSU_DRIVER_NAME,
++	.class = ACPI_FUJITSU_CLASS,
++	.ids = fujitsu_device_ids,
++	.ops = {
++		.add = acpi_fujitsu_add,
++		.remove = acpi_fujitsu_remove,
++		},
++};
++
++/* Initialization */
++
++static int __init fujitsu_init(void)
++{
++	int ret, result;
++
++	if (acpi_disabled)
++		return -ENODEV;
++
++	fujitsu = kmalloc(sizeof(struct fujitsu_t), GFP_KERNEL);
++	if (!fujitsu)
++		return -ENOMEM;
++	memset(fujitsu, 0, sizeof(struct fujitsu_t));
++
++	result = acpi_bus_register_driver(&acpi_fujitsu_driver);
++	if (result < 0) {
++		ret = -ENODEV;
++		goto fail_acpi;
++	}
++
++	/* Register backlight stuff */
++
++	fujitsu->bl_device =
++	    backlight_device_register("fujitsu-laptop", NULL, NULL,
++				      &fujitsubl_ops);
++	if (IS_ERR(fujitsu->bl_device))
++		return PTR_ERR(fujitsu->bl_device);
++
++	fujitsu->bl_device->props.max_brightness = FUJITSU_LCD_N_LEVELS - 1;
++	ret = platform_driver_register(&fujitsupf_driver);
++	if (ret)
++		goto fail_backlight;
++
++	/* Register platform stuff */
++
++	fujitsu->pf_device = platform_device_alloc("fujitsu-laptop", -1);
++	if (!fujitsu->pf_device) {
++		ret = -ENOMEM;
++		goto fail_platform_driver;
++	}
++
++	ret = platform_device_add(fujitsu->pf_device);
++	if (ret)
++		goto fail_platform_device1;
++
++	ret =
++	    sysfs_create_group(&fujitsu->pf_device->dev.kobj,
++			       &fujitsupf_attribute_group);
++	if (ret)
++		goto fail_platform_device2;
++
++	printk(KERN_INFO "fujitsu-laptop: driver " FUJITSU_DRIVER_VERSION
++	       " successfully loaded.\n");
++
++	return 0;
++
++      fail_platform_device2:
++
++	platform_device_del(fujitsu->pf_device);
++
++      fail_platform_device1:
++
++	platform_device_put(fujitsu->pf_device);
++
++      fail_platform_driver:
++
++	platform_driver_unregister(&fujitsupf_driver);
++
++      fail_backlight:
++
++	backlight_device_unregister(fujitsu->bl_device);
++
++      fail_acpi:
++
++	kfree(fujitsu);
++
++	return ret;
++}
++
++static void __exit fujitsu_cleanup(void)
++{
++	sysfs_remove_group(&fujitsu->pf_device->dev.kobj,
++			   &fujitsupf_attribute_group);
++	platform_device_unregister(fujitsu->pf_device);
++	platform_driver_unregister(&fujitsupf_driver);
++	backlight_device_unregister(fujitsu->bl_device);
++
++	acpi_bus_unregister_driver(&acpi_fujitsu_driver);
++
++	kfree(fujitsu);
++
++	printk(KERN_INFO "fujitsu-laptop: driver unloaded.\n");
++}
++
++module_init(fujitsu_init);
++module_exit(fujitsu_cleanup);
++
++MODULE_AUTHOR("Jonathan Woithe");
++MODULE_DESCRIPTION("Fujitsu laptop extras support");
++MODULE_VERSION(FUJITSU_DRIVER_VERSION);
++MODULE_LICENSE("GPL");

commit cb90ab5b424e711390c2ef6f0882b615b042dcb6
+Author: Jonathan Woithe 
+Date:   Wed Aug 29 15:58:19 2007 +0930
+
+    msi-laptop: replace ',' with ';'
+    
+    Signed-off-by: Jonathan Woithe 
+    Signed-off-by: Len Brown 
+
+diff --git a/drivers/misc/msi-laptop.c b/drivers/misc/msi-laptop.c
+index 932a415197b3..349be934db7c 100644
+--- a/drivers/misc/msi-laptop.c
++++ b/drivers/misc/msi-laptop.c
+@@ -353,7 +353,7 @@ static int __init msi_init(void)
+ 	if (IS_ERR(msibl_device))
+ 		return PTR_ERR(msibl_device);
+ 
+-	msibl_device->props.max_brightness = MSI_LCD_LEVEL_MAX-1,
++	msibl_device->props.max_brightness = MSI_LCD_LEVEL_MAX-1;
+ 
+ 	ret = platform_driver_register(&msipf_driver);
+ 	if (ret)

commit bd869485993f73c303b565da5548bb4e77063c54
+Author: Jonathan Woithe 
+Date:   Tue Nov 28 11:35:52 2006 +0100
+
+    [ALSA] hda-codec - Make internal speaker work on Acer C20x tablets
+    
+    The following patch creates a new 'Mono speaker' control in alsamixer
+    when the Realtek 'acer' model is used with hda_intel.  This is needed so
+    the internal mono speaker (when present) can be controlled.
+    This new control won't do anything in Acer laptops which are not fitted with
+    a mono speaker. Acer models which are known to have a mono speaker are the
+    C20x tablet series but there may be others.  I guess we could define a new
+    model specifically for Acers with mono speakers but this seems a bit silly
+    given that such a model will be identical to the normal 'acer' model except
+    for this added control.
+    This patch also adds the C20x tablets to the list of PCI ids associated with
+    the 'acer' model.  This means that owners of C20x machines will no longer
+    have to supply 'model=acer' when loading hda_intel.
+    
+    Signed-off-by: Jonathan Woithe 
+    Signed-off-by: Takashi Iwai 
+    Signed-off-by: Jaroslav Kysela 
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 415a6db4c909..a1b6c9661d45 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -3271,11 +3271,20 @@ static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
+  * and the output jack.  If this turns out to be the case for all such
+  * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT
+  * to ALC_PIN_DIR_INOUT_NOMICBIAS.
++ *
++ * The C20x Tablet series have a mono internal speaker which is controlled
++ * via the chip's Mono sum widget and pin complex, so include the necessary
++ * controls for such models.  On models without a "mono speaker" the control
++ * won't do anything.
+  */
+ static struct snd_kcontrol_new alc260_acer_mixer[] = {
+ 	HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
+ 	HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
+ 	ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
++	HDA_CODEC_VOLUME_MONO("Mono Speaker Playback Volume", 0x0a, 1, 0x0,
++			      HDA_OUTPUT),
++	HDA_BIND_MUTE_MONO("Mono Speaker Playback Switch", 0x0a, 1, 2,
++			   HDA_INPUT),
+ 	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
+ 	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
+ 	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
+@@ -3590,11 +3599,11 @@ static struct hda_verb alc260_acer_init_verbs[] = {
+ 	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
+ 	/* Line In jack is connected to Line1 pin */
+ 	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
++	/* Some Acers (eg: C20x Tablets) use Mono pin for internal speaker */
++	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ 	/* Ensure all other unused pins are disabled and muted. */
+ 	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
+ 	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
+-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ 	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
+ 	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ 	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
+@@ -3622,6 +3631,8 @@ static struct hda_verb alc260_acer_init_verbs[] = {
+ 
+ 	/* Unmute Line-out pin widget amp left and right (no equiv mixer ctrl) */
+ 	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
++	/* Unmute mono pin widget amp output (no equiv mixer ctrl) */
++	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ 	/* Unmute Mic1 and Line1 pin widget input buffers since they start as
+ 	 * inputs. If the pin mode is changed by the user the pin mode control
+ 	 * will take care of enabling the pin's input/output buffers as needed.
+@@ -4122,6 +4133,7 @@ static const char *alc260_models[ALC260_MODEL_LAST] = {
+ };
+ 
+ static struct snd_pci_quirk alc260_cfg_tbl[] = {
++	SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER),
+ 	SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER),
+ 	SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013),
+ 	SND_PCI_QUIRK(0x103c, 0x3011, "HP", ALC260_HP),

commit a1e8d2da03b3a1017aab01d49666ec9b67927de5
+Author: Jonathan Woithe 
+Date:   Tue Mar 28 12:47:09 2006 +0200
+
+    [ALSA] HDA/Realtek: multiple input mux definitions and pin mode additions
+    
+    The following patch relative to CVS from 20060324 adds the following
+    features to the Realtek HDA codec.
+    
+    1) Define two new pin modes: ALC_PIN_DIR_IN_NOMICBIAS and
+       ALC_PIN_DIR_INOUT_NOMICBIAS.  These can be used with jack mode switch
+       definitions in mixers to prevent the user being offered the mic bias
+       options if the hardware doesn't support it.
+    
+    2) Add the ability to have different input mux definitions for different
+       ADCs.  This is needed because the ALC260 chip uses different mux layouts
+       for the two onboard ADCs.  A new field (num_mux_defs) was added to the
+       alc_spec and alc_config_preset structures to support this.
+    
+    3) Adjust numerous comments to make them consistent with the above changes.
+    
+    4) Utilise the new multi-mux definition functionality for the ALC260 fujitsu
+       model to allow recording of the mixer output.
+    
+    5) Utilise the new multi-mux definition functionality for the ALC260 test
+       model to make the mux selections a little less confusing.
+    
+    6) Allow the headphone jack of the ALC260 acer model to be retasked in
+       the mixer.
+    
+    6) Utilise the new multi-mux definition functionality for the ALC260 acer
+       model to give access to the mixer output and the retasked headphone
+       jack.
+    
+    At this stage the *_NOMICBIAS modes are not used.  We have reports that the
+    "Line" jack of at least some Acer models doesn't pass the bias out, and we
+    also know that NIDs 0x0f and 0x10 don't seem to accept the mic bias requests
+    at all.  However, I feel we need to collect more evidence on both counts
+    before committing to the use of *_NOMICBIAS.  In the case of the Acers, it's
+    not clear whether this issue (probably caused by the inclusion of DC
+    blocking capacitors) affects all Acer models or just a small number.  With
+    the issue with NIDs 0x0f and 0x10 it's unclear whether this is a hardware
+    bug which will be addressed in later chip revisions or if it's an
+    intentional restriction.  The datasheet makes no mention of the restriction
+    so at this stage I'm inclined to consider it a hardware bug.  Comments in
+    the source reflect this reasoning.
+    
+    On a similar theme, the headphone jack of the Fujitsu S7020 also doesn't
+    appear to pass mic bias voltage.  I'm still investigating this however.
+    
+    With the ability to retask the headphone jack, owners of ALC260-based Acer
+    laptops should now be able to record 4 channels of audio if they desire. The
+    multiple mux definitions allow this jack to be presented from both ADCs
+    (since this mux input is one of those which differs between the muxes).
+    
+    This patch has been tested on a Fujitsu S7020 laptop and appears to behave
+    itself both for the "test" and "fujitsu" models.  Definitions using only a
+    single mux specification also work.  Other ALC chips should be fine but I
+    cannot test these myself.  The "auto" modes should also continue to function
+    but again I have not verified this.
+    
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 6b45635b3ea3..66bbdb60f50b 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -132,6 +132,7 @@ struct alc_spec {
+ 	hda_nid_t dig_in_nid;		/* digital-in NID; optional */
+ 
+ 	/* capture source */
++	unsigned int num_mux_defs;
+ 	const struct hda_input_mux *input_mux;
+ 	unsigned int cur_mux[3];
+ 
+@@ -173,6 +174,7 @@ struct alc_config_preset {
+ 	hda_nid_t dig_in_nid;
+ 	unsigned int num_channel_mode;
+ 	const struct hda_channel_mode *channel_mode;
++	unsigned int num_mux_defs;
+ 	const struct hda_input_mux *input_mux;
+ 	void (*unsol_event)(struct hda_codec *, unsigned int);
+ 	void (*init_hook)(struct hda_codec *);
+@@ -186,7 +188,10 @@ static int alc_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
+ {
+ 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ 	struct alc_spec *spec = codec->spec;
+-	return snd_hda_input_mux_info(spec->input_mux, uinfo);
++	unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id);
++	if (mux_idx >= spec->num_mux_defs)
++		mux_idx = 0;
++	return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo);
+ }
+ 
+ static int alc_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+@@ -204,7 +209,8 @@ static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
+ 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ 	struct alc_spec *spec = codec->spec;
+ 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+-	return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
++	unsigned int mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
++	return snd_hda_input_mux_put(codec, &spec->input_mux[mux_idx], ucontrol,
+ 				     spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
+ }
+ 
+@@ -246,7 +252,8 @@ static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va
+  * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these
+  * are requested.  Therefore order this list so that this behaviour will not
+  * cause problems when mixer clients move through the enum sequentially.
+- * NIDs 0x0f and 0x10 have been observed to have this behaviour.
++ * NIDs 0x0f and 0x10 have been observed to have this behaviour as of
++ * March 2006.
+  */
+ static char *alc_pin_mode_names[] = {
+ 	"Mic 50pc bias", "Mic 80pc bias",
+@@ -256,19 +263,27 @@ static unsigned char alc_pin_mode_values[] = {
+ 	PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP,
+ };
+ /* The control can present all 5 options, or it can limit the options based
+- * in the pin being assumed to be exclusively an input or an output pin.
++ * in the pin being assumed to be exclusively an input or an output pin.  In
++ * addition, "input" pins may or may not process the mic bias option
++ * depending on actual widget capability (NIDs 0x0f and 0x10 don't seem to
++ * accept requests for bias as of chip versions up to March 2006) and/or
++ * wiring in the computer.
+  */
+-#define ALC_PIN_DIR_IN    0x00
+-#define ALC_PIN_DIR_OUT   0x01
+-#define ALC_PIN_DIR_INOUT 0x02
++#define ALC_PIN_DIR_IN              0x00
++#define ALC_PIN_DIR_OUT             0x01
++#define ALC_PIN_DIR_INOUT           0x02
++#define ALC_PIN_DIR_IN_NOMICBIAS    0x03
++#define ALC_PIN_DIR_INOUT_NOMICBIAS 0x04
+ 
+-/* Info about the pin modes supported by the three different pin directions. 
++/* Info about the pin modes supported by the different pin direction modes. 
+  * For each direction the minimum and maximum values are given.
+  */
+-static signed char alc_pin_mode_dir_info[3][2] = {
++static signed char alc_pin_mode_dir_info[5][2] = {
+ 	{ 0, 2 },    /* ALC_PIN_DIR_IN */
+ 	{ 3, 4 },    /* ALC_PIN_DIR_OUT */
+ 	{ 0, 4 },    /* ALC_PIN_DIR_INOUT */
++	{ 2, 2 },    /* ALC_PIN_DIR_IN_NOMICBIAS */
++	{ 2, 4 },    /* ALC_PIN_DIR_INOUT_NOMICBIAS */
+ };
+ #define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0])
+ #define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1])
+@@ -330,9 +345,10 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
+ 		 * input modes.
+ 		 *
+ 		 * Dynamically switching the input/output buffers probably
+-		 * reduces noise slightly, particularly on input.  However,
+-		 * havingboth input and output buffers enabled
+-		 * simultaneously doesn't seem to be problematic.
++		 * reduces noise slightly (particularly on input) so we'll
++		 * do it.  However, having both input and output buffers
++		 * enabled simultaneously doesn't seem to be problematic if
++		 * this turns out to be necessary in the future.
+ 		 */
+ 		if (val <= 2) {
+ 			snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE,
+@@ -484,6 +500,9 @@ static void setup_preset(struct alc_spec *spec, const struct alc_config_preset *
+ 	spec->multiout.dig_out_nid = preset->dig_out_nid;
+ 	spec->multiout.hp_nid = preset->hp_nid;
+ 	
++	spec->num_mux_defs = preset->num_mux_defs;
++	if (! spec->num_mux_defs)
++		spec->num_mux_defs = 1;
+ 	spec->input_mux = preset->input_mux;
+ 
+ 	spec->num_adc_nids = preset->num_adc_nids;
+@@ -2686,6 +2705,7 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
+ 
+ 	spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs;
+ 
++	spec->num_mux_defs = 1;
+ 	spec->input_mux = &spec->private_imux;
+ 
+ 	return 1;
+@@ -2815,30 +2835,56 @@ static struct hda_input_mux alc260_capture_source = {
+ };
+ 
+ /* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack,
+- * headphone jack and the internal CD lines.
++ * headphone jack and the internal CD lines since these are the only pins at
++ * which audio can appear.  For flexibility, also allow the option of
++ * recording the mixer output on the second ADC (ADC0 doesn't have a
++ * connection to the mixer output).
+  */
+-static struct hda_input_mux alc260_fujitsu_capture_source = {
+-	.num_items = 3,
+-	.items = {
+-		{ "Mic/Line", 0x0 },
+-		{ "CD", 0x4 },
+-		{ "Headphone", 0x2 },
++static struct hda_input_mux alc260_fujitsu_capture_sources[2] = {
++	{
++		.num_items = 3,
++		.items = {
++			{ "Mic/Line", 0x0 },
++			{ "CD", 0x4 },
++			{ "Headphone", 0x2 },
++		},
+ 	},
++	{
++		.num_items = 4,
++		.items = {
++			{ "Mic/Line", 0x0 },
++			{ "CD", 0x4 },
++			{ "Headphone", 0x2 },
++			{ "Mixer", 0x5 },
++		},
++	},
++
+ };
+ 
+-/* Acer TravelMate(/Extensa/Aspire) notebooks have similar configutation to
+- * the Fujitsu S702x, but jacks are marked differently. We won't allow
+- * retasking the Headphone jack, so it won't be available here.
++/* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to
++ * the Fujitsu S702x, but jacks are marked differently.
+  */
+-static struct hda_input_mux alc260_acer_capture_source = {
+-	.num_items = 3,
+-	.items = {
+-		{ "Mic", 0x0 },
+-		{ "Line", 0x2 },
+-		{ "CD", 0x4 },
++static struct hda_input_mux alc260_acer_capture_sources[2] = {
++	{
++		.num_items = 4,
++		.items = {
++			{ "Mic", 0x0 },
++			{ "Line", 0x2 },
++			{ "CD", 0x4 },
++			{ "Headphone", 0x5 },
++		},
++	},
++	{
++		.num_items = 5,
++		.items = {
++			{ "Mic", 0x0 },
++			{ "Line", 0x2 },
++			{ "CD", 0x4 },
++			{ "Headphone", 0x6 },
++			{ "Mixer", 0x5 },
++		},
+ 	},
+ };
+-
+ /*
+  * This is just place-holder, so there's something for alc_build_pcms to look
+  * at when it calculates the maximum number of channels. ALC260 has no mixer
+@@ -2899,6 +2945,9 @@ static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
+ 	{ } /* end */
+ };
+ 
++/* Fujitsu S702x series laptops.  ALC260 pin usage: Mic/Line jack = 0x12, 
++ * HP jack = 0x14, CD audio =  0x16, internal speaker = 0x10.
++ */
+ static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
+ 	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
+ 	HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),
+@@ -2915,9 +2964,28 @@ static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
+ 	{ } /* end */
+ };
+ 
++/* Mixer for Acer TravelMate(/Extensa/Aspire) notebooks.  Note that current
++ * versions of the ALC260 don't act on requests to enable mic bias from NID
++ * 0x0f (used to drive the headphone jack in these laptops).  The ALC260
++ * datasheet doesn't mention this restriction.  At this stage it's not clear
++ * whether this behaviour is intentional or is a hardware bug in chip
++ * revisions available in early 2006.  Therefore for now allow the
++ * "Headphone Jack Mode" control to span all choices, but if it turns out
++ * that the lack of mic bias for this NID is intentional we could change the
++ * mode from ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
++ *
++ * In addition, Acer TravelMate(/Extensa/Aspire) notebooks in early 2006
++ * don't appear to make the mic bias available from the "line" jack, even
++ * though the NID used for this jack (0x14) can supply it.  The theory is
++ * that perhaps Acer have included blocking capacitors between the ALC260
++ * and the output jack.  If this turns out to be the case for all such
++ * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT
++ * to ALC_PIN_DIR_INOUT_NOMICBIAS.
++ */
+ static struct snd_kcontrol_new alc260_acer_mixer[] = {
+ 	HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
+ 	HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
++	ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
+ 	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
+ 	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
+ 	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
+@@ -3131,7 +3199,8 @@ static struct hda_verb alc260_hp_3013_init_verbs[] = {
+ };
+ 
+ /* Initialisation sequence for ALC260 as configured in Fujitsu S702x
+- * laptops.
++ * laptops.  ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD
++ * audio = 0x16, internal speaker = 0x10.
+  */
+ static struct hda_verb alc260_fujitsu_init_verbs[] = {
+ 	/* Disable all GPIOs */
+@@ -3278,10 +3347,10 @@ static struct hda_verb alc260_acer_init_verbs[] = {
+ 	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
+ 
+ 	/* Do similar with the second ADC: mute capture input amp and
+-	 * set ADC connection to line (on line1 pin)
++	 * set ADC connection to mic to match ALSA's default state.
+ 	 */
+ 	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+-	{0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
++	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
+ 
+ 	/* Mute all inputs to mixer widget (even unconnected ones) */
+ 	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
+@@ -3306,26 +3375,35 @@ static hda_nid_t alc260_test_dac_nids[1] = {
+ static hda_nid_t alc260_test_adc_nids[2] = {
+ 	0x04, 0x05,
+ };
+-/* This is a bit messy since the two input muxes in the ALC260 have slight
+- * variations in their signal assignments.  The ideal way to deal with this
+- * is to extend alc_spec.input_mux to allow a different input MUX for each
+- * ADC.  For the purposes of the test model it's sufficient to just list
+- * both options for affected signal indices.  The separate input mux
+- * functionality only needs to be considered if a model comes along which
+- * actually uses signals 0x5, 0x6 and 0x7 for something which makes sense to
+- * record.
++/* For testing the ALC260, each input MUX needs its own definition since
++ * the signal assignments are different.  This assumes that the first ADC 
++ * is NID 0x04.
+  */
+-static struct hda_input_mux alc260_test_capture_source = {
+-	.num_items = 8,
+-	.items = {
+-		{ "MIC1 pin", 0x0 },
+-		{ "MIC2 pin", 0x1 },
+-		{ "LINE1 pin", 0x2 },
+-		{ "LINE2 pin", 0x3 },
+-		{ "CD pin", 0x4 },
+-		{ "LINE-OUT pin (cap1), Mixer (cap2)", 0x5 },
+-		{ "HP-OUT pin (cap1), LINE-OUT pin (cap2)", 0x6 },
+-		{ "HP-OUT pin (cap2 only)", 0x7 },
++static struct hda_input_mux alc260_test_capture_sources[2] = {
++	{
++		.num_items = 7,
++		.items = {
++			{ "MIC1 pin", 0x0 },
++			{ "MIC2 pin", 0x1 },
++			{ "LINE1 pin", 0x2 },
++			{ "LINE2 pin", 0x3 },
++			{ "CD pin", 0x4 },
++			{ "LINE-OUT pin", 0x5 },
++			{ "HP-OUT pin", 0x6 },
++		},
++        },
++	{
++		.num_items = 8,
++		.items = {
++			{ "MIC1 pin", 0x0 },
++			{ "MIC2 pin", 0x1 },
++			{ "LINE1 pin", 0x2 },
++			{ "LINE2 pin", 0x3 },
++			{ "CD pin", 0x4 },
++			{ "Mixer", 0x5 },
++			{ "LINE-OUT pin", 0x6 },
++			{ "HP-OUT pin", 0x7 },
++		},
+         },
+ };
+ static struct snd_kcontrol_new alc260_test_mixer[] = {
+@@ -3337,7 +3415,17 @@ static struct snd_kcontrol_new alc260_test_mixer[] = {
+ 	HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT),
+ 	HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT),
+ 
+-	/* Modes for retasking pin widgets */
++	/* Modes for retasking pin widgets
++	 * Note: the ALC260 doesn't seem to act on requests to enable mic
++         * bias from NIDs 0x0f and 0x10.  The ALC260 datasheet doesn't
++         * mention this restriction.  At this stage it's not clear whether
++         * this behaviour is intentional or is a hardware bug in chip
++         * revisions available at least up until early 2006.  Therefore for
++         * now allow the "HP-OUT" and "LINE-OUT" Mode controls to span all
++         * choices, but if it turns out that the lack of mic bias for these
++         * NIDs is intentional we could change their modes from
++         * ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
++	 */
+ 	ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT),
+ 	ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT),
+ 	ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT),
+@@ -3699,6 +3787,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
+ 
+ 	spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs;
+ 
++	spec->num_mux_defs = 1;
+ 	spec->input_mux = &spec->private_imux;
+ 
+ 	/* check whether NID 0x04 is valid */
+@@ -3804,7 +3893,8 @@ static struct alc_config_preset alc260_presets[] = {
+ 		.adc_nids = alc260_dual_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc260_modes),
+ 		.channel_mode = alc260_modes,
+-		.input_mux = &alc260_fujitsu_capture_source,
++		.num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources),
++		.input_mux = alc260_fujitsu_capture_sources,
+ 	},
+ 	[ALC260_ACER] = {
+ 		.mixers = { alc260_acer_mixer,
+@@ -3816,7 +3906,8 @@ static struct alc_config_preset alc260_presets[] = {
+ 		.adc_nids = alc260_dual_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc260_modes),
+ 		.channel_mode = alc260_modes,
+-		.input_mux = &alc260_acer_capture_source,
++		.num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources),
++		.input_mux = alc260_acer_capture_sources,
+ 	},
+ #ifdef CONFIG_SND_DEBUG
+ 	[ALC260_TEST] = {
+@@ -3829,7 +3920,8 @@ static struct alc_config_preset alc260_presets[] = {
+ 		.adc_nids = alc260_test_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc260_modes),
+ 		.channel_mode = alc260_modes,
+-		.input_mux = &alc260_test_capture_source,
++		.num_mux_defs = ARRAY_SIZE(alc260_test_capture_sources),
++		.input_mux = alc260_test_capture_sources,
+ 	},
+ #endif
+ };
+@@ -3921,7 +4013,6 @@ static struct hda_input_mux alc882_capture_source = {
+ 		{ "CD", 0x4 },
+ 	},
+ };
+-
+ #define alc882_mux_enum_info alc_mux_enum_info
+ #define alc882_mux_enum_get alc_mux_enum_get
+ 
+@@ -4823,6 +4914,7 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
+ 		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ 
+ 	spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs;
++	spec->num_mux_defs = 1;
+ 	spec->input_mux = &spec->private_imux;
+ 
+ 	return 1;
+@@ -5499,6 +5591,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
+ 
+ 	spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs;
+ 
++	spec->num_mux_defs = 1;
+ 	spec->input_mux = &spec->private_imux;
+ 
+ 	spec->adc_nids = alc861_adc_nids;

commit 92621f130e60da865de2f5aa6d3dec2ee844b803
+Author: Jonathan Woithe 
+Date:   Tue Feb 28 11:47:47 2006 +0100
+
+    [ALSA] HDA/ALC260: 7/7 - add SPDIF enable to test model
+    
+    Modules: HDA Codec driver
+    
+    This patch adds mixer controls to the 'test' ALC260 model which allow the
+    user to selectively enable or disable the SPDIF output pins.  This should
+    assist people identify digital outputs on machines which bring them to the
+    outside world.
+    
+    Note that while the patch *should* work, I cannot personally verify it since
+    my laptop doesn't bring the SPDIF lines out.
+    
+    As for the GPIO switches added in patch 4, these controls are currently
+    only compiled in if debug mode is selected.
+    
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index c8b0ec814375..219ddf0b8d43 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -395,6 +395,60 @@ static int alc_gpio_data_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
+ 	  .private_value = nid | (mask<<16) }
+ #endif   /* CONFIG_SND_DEBUG */
+ 
++/* A switch control to allow the enabling of the digital IO pins on the
++ * ALC260.  This is incredibly simplistic; the intention of this control is
++ * to provide something in the test model allowing digital outputs to be
++ * identified if present.  If models are found which can utilise these
++ * outputs a more complete mixer control can be devised for those models if
++ * necessary.
++ */
++#ifdef CONFIG_SND_DEBUG
++static int alc_spdif_ctrl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
++{
++	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
++	uinfo->count = 1;
++	uinfo->value.integer.min = 0;
++	uinfo->value.integer.max = 1;
++	return 0;
++}                                
++static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
++{
++	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
++	hda_nid_t nid = kcontrol->private_value & 0xffff;
++	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
++	long *valp = ucontrol->value.integer.value;
++	unsigned int val = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_DIGI_CONVERT,0x00);
++
++	*valp = (val & mask) != 0;
++	return 0;
++}
++static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
++{
++	signed int change;
++	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
++	hda_nid_t nid = kcontrol->private_value & 0xffff;
++	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
++	long val = *ucontrol->value.integer.value;
++	unsigned int ctrl_data = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_DIGI_CONVERT,0x00);
++
++	/* Set/unset the masked control bit(s) as needed */
++	change = (val==0?0:mask) != (ctrl_data & mask);
++	if (val==0)
++		ctrl_data &= ~mask;
++	else
++		ctrl_data |= mask;
++	snd_hda_codec_write(codec,nid,0,AC_VERB_SET_DIGI_CONVERT_1,ctrl_data);
++
++	return change;
++}
++#define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \
++	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
++	  .info = alc_spdif_ctrl_info, \
++	  .get = alc_spdif_ctrl_get, \
++	  .put = alc_spdif_ctrl_put, \
++	  .private_value = nid | (mask<<16) }
++#endif   /* CONFIG_SND_DEBUG */
++
+ /*
+  * set up from the preset table
+  */
+@@ -3048,6 +3102,13 @@ static struct snd_kcontrol_new alc260_test_mixer[] = {
+ 	ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
+ 	ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
+ 
++	/* Switches to allow the digital IO pins to be enabled.  The datasheet
++	 * is ambigious as to which NID is which; testing on laptops which
++	 * make this output available should provide clarification. 
++	 */
++	ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x03, 0x01),
++	ALC_SPDIF_CTRL_SWITCH("SPDIF Capture Switch", 0x06, 0x01),
++
+ 	{ } /* end */
+ };
+ static struct hda_verb alc260_test_init_verbs[] = {
+@@ -3064,7 +3125,12 @@ static struct hda_verb alc260_test_init_verbs[] = {
+ 	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ 	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ 
+-	/* Disable digital (SPDIF) pins for now */
++	/* Disable digital (SPDIF) pins initially, but users can enable
++	 * them via a mixer switch.  In the case of SPDIF-out, this initverb
++	 * payload also sets the generation to 0, output to be in "consumer"
++	 * PCM format, copyright asserted, no pre-emphasis and no validity
++	 * control.
++	 */
+ 	{0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
+ 	{0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
+ 

commit f7ace40d14c46dca9a12ab753677adc17b1b906c
+Author: Jonathan Woithe 
+Date:   Tue Feb 28 11:46:14 2006 +0100
+
+    [ALSA] HDA/ALC260: 6/7 - Fujitsu/test model tweaks
+    
+    Modules: HDA Codec driver
+    
+    This patch is janitorial - it cleans up a number of cosmetic issues with
+    the 'fujitsu' and 'test' models.  Issues addressed:
+    
+     * spaces instead of tabs used for some indents,
+    
+     * clarified/corrected selected comments.
+    
+    Unlike a patch from earlier this week, this keeps both ADCs connected to
+    the mic1 pin widget by default.  I believe this is the better default, since
+    some laptops don't bring the line1 widget to the outside world.  Most (if
+    not all) do bring mic1 out though, so it seems to me that this default
+    should remain in place.
+    
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 104d2a37f45a..c8b0ec814375 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -2819,28 +2819,28 @@ static struct hda_verb alc260_fujitsu_init_verbs[] = {
+ 	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ 	/* Headphone/Line-out jack connects to Line1 pin; make it an output */
+ 	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+-        /* Mic/Line-in jack is connected to mic1 pin, so make it an input */
+-        {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+-        /* Ensure all other unused pins are disabled and muted.
+-	 * Note: trying to set widget 0x15 to anything blocks all audio
+-	 * output for some reason, so just leave that at the default.
+-	 */
+-        {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
+-        {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	/* Mic/Line-in jack is connected to mic1 pin, so make it an input */
++	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
++	/* Ensure all other unused pins are disabled and muted. */
++	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
++	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ 	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
+-        {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ 	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
+-        {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+-        /* Disable digital (SPDIF) pins */
+-        {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
+-        {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
++	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
++	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++
++	/* Disable digital (SPDIF) pins */
++	{0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
++	{0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
+ 
+-        /* Ensure Line1 pin widget takes its input from the OUT1 sum bus 
+-         * when acting as an output.
+-         */
+-        {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
++	/* Ensure Line1 pin widget takes its input from the OUT1 sum bus 
++	 * when acting as an output.
++	 */
++	{0x0d, AC_VERB_SET_CONNECT_SEL, 0},
+ 
+-        /* Start with output sum widgets muted and their output gains at min */
++	/* Start with output sum widgets muted and their output gains at min */
+ 	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ 	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ 	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+@@ -2851,42 +2851,42 @@ static struct hda_verb alc260_fujitsu_init_verbs[] = {
+ 	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ 	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ 
+-        /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */
+-        {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+-        /* Unmute Line1 pin widget output buffer since it starts as an output.
+-         * If the pin mode is changed by the user the pin mode control will
+-         * take care of enabling the pin's input/output buffers as needed.
+-         * Therefore there's no need to enable the input buffer at this
+-         * stage.
++	/* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */
++	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
++	/* Unmute Line1 pin widget output buffer since it starts as an output.
++	 * If the pin mode is changed by the user the pin mode control will
++	 * take care of enabling the pin's input/output buffers as needed.
++	 * Therefore there's no need to enable the input buffer at this
++	 * stage.
+ 	 */
+-        {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
++	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ 	/* Unmute input buffer of pin widget used for Line-in (no equiv 
+ 	 * mixer ctrl)
+ 	 */
+-        {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+-
+-        /* Mute capture amp left and right */
+-        {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+-        /* Set ADC connection select to match default mixer setting - line 
+-         * in (on mic1 pin)
+-         */
+-        {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
+-
+-        /* Do the same for the second ADC: mute capture input amp and
+-         * set ADC connection to line in
+-         */
+-        {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+-        {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
+-
+-        /* Mute all inputs to mixer widget (even unconnected ones) */
+-        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
+-        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
+-        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
+-        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
+-        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
+-        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
+-        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
+-        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
++	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
++
++	/* Mute capture amp left and right */
++	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	/* Set ADC connection select to match default mixer setting - line 
++	 * in (on mic1 pin)
++	 */
++	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
++
++	/* Do the same for the second ADC: mute capture input amp and
++	 * set ADC connection to line in (on mic1 pin)
++	 */
++	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
++
++	/* Mute all inputs to mixer widget (even unconnected ones) */
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
+ 
+ 	{ }
+ };
+@@ -3068,7 +3068,7 @@ static struct hda_verb alc260_test_init_verbs[] = {
+ 	{0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
+ 	{0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
+ 
+-	/* Ensure mic1, mic2, line1 and line2 pin widget take input from the 
++	/* Ensure mic1, mic2, line1 and line2 pin widgets take input from the 
+ 	 * OUT1 sum bus when acting as an output.
+ 	 */
+ 	{0x0b, AC_VERB_SET_CONNECT_SEL, 0},
+@@ -3103,13 +3103,13 @@ static struct hda_verb alc260_test_init_verbs[] = {
+ 
+ 	/* Mute capture amp left and right */
+ 	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+-	/* Set ADC connection select to match default mixer setting - line 
+-	 * in (on mic1 pin)
++	/* Set ADC connection select to match default mixer setting (mic1
++	 * pin)
+ 	 */
+ 	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
+ 
+ 	/* Do the same for the second ADC: mute capture input amp and
+-	 * set ADC connection to line in
++	 * set ADC connection to mic1 pin
+ 	 */
+ 	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ 	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},

commit 0bfc90e95946ac420e2de049707232ce18ddeba9
+Author: Jonathan Woithe 
+Date:   Tue Feb 28 11:45:11 2006 +0100
+
+    [ALSA] HDA/ALC260: 5/7 - add 'acer' model
+    
+    Modules: HDA Codec driver
+    
+    This patch adds a new 'acer' model.  It is based on work by Rimas and many
+    other dedicated Acer owners over the past few weeks (see bug number
+    1618) - kudos to them. This adds support for a variety of Acer laptops,
+    although we are still in the process of collecting pci/subsystem IDs to add.
+    There are still some potentially outstanding issues: there are reports that
+    the CD control might not yet be functional for example.  However, the time
+    is probably right to get a 'first cut' into the kernel which can be refined
+    as more test reports come in.
+    
+    From the reports by various Acer owners, this code allows them to record
+    from internal mics and external jacks.  Playback also seems to work to all
+    external jacks and the internal speaker.  The 'beep' control doesn't appear
+    functional at the moment.
+    
+    This patch depends on the changes made in patch 3/7.
+    
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 4f6dea23d8b2..104d2a37f45a 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -64,6 +64,7 @@ enum {
+ 	ALC260_HP,
+ 	ALC260_HP_3013,
+ 	ALC260_FUJITSU_S702X,
++	ALC260_ACER,
+ #ifdef CONFIG_SND_DEBUG
+ 	ALC260_TEST,
+ #endif
+@@ -2504,6 +2505,19 @@ static struct hda_input_mux alc260_fujitsu_capture_source = {
+ 	},
+ };
+ 
++/* Acer TravelMate(/Extensa/Aspire) notebooks have similar configutation to
++ * the Fujitsu S702x, but jacks are marked differently. We won't allow
++ * retasking the Headphone jack, so it won't be available here.
++ */
++static struct hda_input_mux alc260_acer_capture_source = {
++	.num_items = 3,
++	.items = {
++		{ "Mic", 0x0 },
++		{ "Line", 0x2 },
++		{ "CD", 0x4 },
++	},
++};
++
+ /*
+  * This is just place-holder, so there's something for alc_build_pcms to look
+  * at when it calculates the maximum number of channels. ALC260 has no mixer
+@@ -2521,6 +2535,7 @@ static struct hda_channel_mode alc260_modes[1] = {
+  * HP: base_output + input + capture_alt
+  * HP_3013: hp_3013 + input + capture
+  * fujitsu: fujitsu + capture
++ * acer: acer + capture
+  */
+ 
+ static struct snd_kcontrol_new alc260_base_output_mixer[] = {
+@@ -2579,6 +2594,22 @@ static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
+ 	{ } /* end */
+ };
+ 
++static struct snd_kcontrol_new alc260_acer_mixer[] = {
++	HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
++	HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
++	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
++	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
++	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
++	HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
++	ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
++	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
++	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
++	ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
++	HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
++	HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
++	{ } /* end */
++};
++
+ /* capture mixer elements */
+ static struct snd_kcontrol_new alc260_capture_mixer[] = {
+ 	HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
+@@ -2860,6 +2891,90 @@ static struct hda_verb alc260_fujitsu_init_verbs[] = {
+ 	{ }
+ };
+ 
++/* Initialisation sequence for ALC260 as configured in Acer TravelMate and
++ * similar laptops (adapted from Fujitsu init verbs).
++ */
++static struct hda_verb alc260_acer_init_verbs[] = {
++	/* On TravelMate laptops, GPIO 0 enables the internal speaker and
++	 * the headphone jack.  Turn this on and rely on the standard mute
++	 * methods whenever the user wants to turn these outputs off.
++	 */
++	{0x01, AC_VERB_SET_GPIO_MASK, 0x01},
++	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
++	{0x01, AC_VERB_SET_GPIO_DATA, 0x01},
++	/* Internal speaker/Headphone jack is connected to Line-out pin */
++	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
++	/* Internal microphone/Mic jack is connected to Mic1 pin */
++	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
++	/* Line In jack is connected to Line1 pin */
++	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
++	/* Ensure all other unused pins are disabled and muted. */
++	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
++	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
++	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
++	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
++	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	/* Disable digital (SPDIF) pins */
++	{0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
++	{0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
++
++	/* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum 
++	 * bus when acting as outputs.
++	 */
++	{0x0b, AC_VERB_SET_CONNECT_SEL, 0},
++	{0x0d, AC_VERB_SET_CONNECT_SEL, 0},
++
++	/* Start with output sum widgets muted and their output gains at min */
++	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
++	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
++	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
++	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
++	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
++	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
++
++	/* Unmute Line-out pin widget amp left and right (no equiv mixer ctrl) */
++	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
++	/* Unmute Mic1 and Line1 pin widget input buffers since they start as
++	 * inputs. If the pin mode is changed by the user the pin mode control
++	 * will take care of enabling the pin's input/output buffers as needed.
++	 * Therefore there's no need to enable the input buffer at this
++	 * stage.
++	 */
++	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
++	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
++
++	/* Mute capture amp left and right */
++	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	/* Set ADC connection select to match default mixer setting - mic
++	 * (on mic1 pin)
++	 */
++	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
++
++	/* Do similar with the second ADC: mute capture input amp and
++	 * set ADC connection to line (on line1 pin)
++	 */
++	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	{0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
++
++	/* Mute all inputs to mixer widget (even unconnected ones) */
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
++
++	{ }
++};
++
+ /* Test configuration for debugging, modelled after the ALC880 test
+  * configuration.
+  */
+@@ -3296,6 +3411,8 @@ static struct hda_board_config alc260_cfg_tbl[] = {
+ 	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3016, .config = ALC260_HP },
+ 	{ .modelname = "fujitsu", .config = ALC260_FUJITSU_S702X },
+ 	{ .pci_subvendor = 0x10cf, .pci_subdevice = 0x1326, .config = ALC260_FUJITSU_S702X },
++	{ .modelname = "acer", .config = ALC260_ACER },
++	{ .pci_subvendor = 0x1025, .pci_subdevice = 0x008f, .config = ALC260_ACER },
+ #ifdef CONFIG_SND_DEBUG
+ 	{ .modelname = "test", .config = ALC260_TEST },
+ #endif
+@@ -3356,6 +3473,18 @@ static struct alc_config_preset alc260_presets[] = {
+ 		.channel_mode = alc260_modes,
+ 		.input_mux = &alc260_fujitsu_capture_source,
+ 	},
++	[ALC260_ACER] = {
++		.mixers = { alc260_acer_mixer,
++			    alc260_capture_mixer },
++		.init_verbs = { alc260_acer_init_verbs },
++		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
++		.dac_nids = alc260_dac_nids,
++		.num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
++		.adc_nids = alc260_dual_adc_nids,
++		.num_channel_mode = ARRAY_SIZE(alc260_modes),
++		.channel_mode = alc260_modes,
++		.input_mux = &alc260_acer_capture_source,
++	},
+ #ifdef CONFIG_SND_DEBUG
+ 	[ALC260_TEST] = {
+ 		.mixers = { alc260_test_mixer,

commit 5c8f858d71054960f08c46703a3f0fb36a752079
+Author: Jonathan Woithe 
+Date:   Tue Feb 28 11:43:27 2006 +0100
+
+    [ALSA] HDA/ALC260: 4/7 - add GPIO switches to test model
+    
+    Modules: HDA Codec driver
+    
+    This patch adds 'test' model mixer switches for the GPIO controls found on
+    the ALC260.  It has been found that some laptops (eg: Acer) can use these to
+    enable particular controls, so it would be useful to have access to these
+    via the 'test' model.  It will make testing new models easy, especially if
+    certain outputs cannot be made to work any other way.
+    
+    This patch *should* work, but because the GPIO pins don't do anything in
+    my laptop I cannot personally verify that all this works as expected.
+    
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 80ba6c753c33..4f6dea23d8b2 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -342,6 +342,58 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
+ 	  .put = alc_pin_mode_put, \
+ 	  .private_value = nid | (dir<<16) }
+ 
++/* A switch control for ALC260 GPIO pins.  Multiple GPIOs can be ganged
++ * together using a mask with more than one bit set.  This control is
++ * currently used only by the ALC260 test model.  At this stage they are not
++ * needed for any "production" models.
++ */
++#ifdef CONFIG_SND_DEBUG
++static int alc_gpio_data_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
++{
++	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
++	uinfo->count = 1;
++	uinfo->value.integer.min = 0;
++	uinfo->value.integer.max = 1;
++	return 0;
++}                                
++static int alc_gpio_data_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
++{
++	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
++	hda_nid_t nid = kcontrol->private_value & 0xffff;
++	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
++	long *valp = ucontrol->value.integer.value;
++	unsigned int val = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_GPIO_DATA,0x00);
++
++	*valp = (val & mask) != 0;
++	return 0;
++}
++static int alc_gpio_data_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
++{
++	signed int change;
++	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
++	hda_nid_t nid = kcontrol->private_value & 0xffff;
++	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
++	long val = *ucontrol->value.integer.value;
++	unsigned int gpio_data = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_GPIO_DATA,0x00);
++
++	/* Set/unset the masked GPIO bit(s) as needed */
++	change = (val==0?0:mask) != (gpio_data & mask);
++	if (val==0)
++		gpio_data &= ~mask;
++	else
++		gpio_data |= mask;
++	snd_hda_codec_write(codec,nid,0,AC_VERB_SET_GPIO_DATA,gpio_data);
++
++	return change;
++}
++#define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \
++	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
++	  .info = alc_gpio_data_info, \
++	  .get = alc_gpio_data_get, \
++	  .put = alc_gpio_data_put, \
++	  .private_value = nid | (mask<<16) }
++#endif   /* CONFIG_SND_DEBUG */
++
+ /*
+  * set up from the preset table
+  */
+@@ -2874,11 +2926,21 @@ static struct snd_kcontrol_new alc260_test_mixer[] = {
+ 	HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT),
+ 	HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT),
+ 	HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT),
++
++	/* Controls for GPIO pins, assuming they are configured as outputs */
++	ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
++	ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
++	ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
++	ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
++
+ 	{ } /* end */
+ };
+ static struct hda_verb alc260_test_init_verbs[] = {
+-	/* Disable all GPIOs */
+-	{0x01, AC_VERB_SET_GPIO_MASK, 0},
++	/* Enable all GPIOs as outputs with an initial value of 0 */
++	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f},
++	{0x01, AC_VERB_SET_GPIO_DATA, 0x00},
++	{0x01, AC_VERB_SET_GPIO_MASK, 0x0f},
++
+ 	/* Enable retasking pins as output, initially without power amp */
+ 	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ 	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},

commit d57fdac0691d500d5c697e452f769335b22a75e3
+Author: Jonathan Woithe 
+Date:   Tue Feb 28 11:38:35 2006 +0100
+
+    [ALSA] HDA/ALC260: 3/7 - generalise some structures
+    
+    Modules: HDA Codec driver
+    
+    This patch generalises a structure added for the 'fujitsu' model but which
+    is potentially useful for other models as well.  It turns the
+    'alc260_fujitsu_adc_nids' array into 'alc260_dual_adc_nids'; for other
+    models which decide to utilise the dual ADC functionality there's really
+    no reason why they need to define their own list of ADC nids.
+    
+    The 'fujitsu' model preset is adjusted accordingly.
+    
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 600d0a037842..80ba6c753c33 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -2419,7 +2419,10 @@ static hda_nid_t alc260_hp_adc_nids[2] = {
+ 	0x05, 0x04
+ };
+ 
+-static hda_nid_t alc260_fujitsu_adc_nids[2] = {
++/* NIDs used when simultaneous access to both ADCs makes sense.  Note that
++ * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC.
++ */
++static hda_nid_t alc260_dual_adc_nids[2] = {
+ 	/* ADC0, ADC1 */
+ 	0x04, 0x05
+ };
+@@ -3285,8 +3288,8 @@ static struct alc_config_preset alc260_presets[] = {
+ 		.init_verbs = { alc260_fujitsu_init_verbs },
+ 		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
+ 		.dac_nids = alc260_dac_nids,
+-		.num_adc_nids = ARRAY_SIZE(alc260_fujitsu_adc_nids),
+-		.adc_nids = alc260_fujitsu_adc_nids,
++		.num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
++		.adc_nids = alc260_dual_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc260_modes),
+ 		.channel_mode = alc260_modes,
+ 		.input_mux = &alc260_fujitsu_capture_source,

commit cdcd9268a1b03c6695ea07983ce029b2b4a099d8
+Author: Jonathan Woithe 
+Date:   Tue Feb 28 11:36:42 2006 +0100
+
+    [ALSA] HDA/ALC260: 2/7 - switch pin buffer enables
+    
+    Modules: HDA Codec driver
+    
+    This patch adds functionality which switches the input/output buffer enables
+    of retasking pins when the user changes their mode with the mode control.
+    This probably reduces noise *slightly* for recording compared to the case
+    where both input and output buffers were enabled simultaneously.
+    
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index b34d2448d172..600d0a037842 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -306,9 +306,32 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
+ 		val = alc_pin_mode_min(dir);
+ 
+ 	change = pinctl != alc_pin_mode_values[val];
+-	if (change)
++	if (change) {
++		/* Set pin mode to that requested */
+ 		snd_hda_codec_write(codec,nid,0,AC_VERB_SET_PIN_WIDGET_CONTROL,
+ 			alc_pin_mode_values[val]);
++
++		/* Also enable the retasking pin's input/output as required 
++		 * for the requested pin mode.  Enum values of 2 or less are
++		 * input modes.
++		 *
++		 * Dynamically switching the input/output buffers probably
++		 * reduces noise slightly, particularly on input.  However,
++		 * havingboth input and output buffers enabled
++		 * simultaneously doesn't seem to be problematic.
++		 */
++		if (val <= 2) {
++			snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE,
++				AMP_OUT_MUTE);
++			snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE,
++				AMP_IN_UNMUTE(0));
++		} else {
++			snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE,
++				AMP_IN_MUTE(0));
++			snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE,
++				AMP_OUT_UNMUTE);
++		}
++	}
+ 	return change;
+ }
+ 
+@@ -2744,14 +2767,16 @@ static struct hda_verb alc260_fujitsu_init_verbs[] = {
+ 
+         /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */
+         {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+-        /* Unmute Line1 pin widget amp left and right (no equiv mixer ctrl) */
++        /* Unmute Line1 pin widget output buffer since it starts as an output.
++         * If the pin mode is changed by the user the pin mode control will
++         * take care of enabling the pin's input/output buffers as needed.
++         * Therefore there's no need to enable the input buffer at this
++         * stage.
++	 */
+         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+-        /* Unmute Line1 pin widget input for when this pin is used as input
+-         * (no equiv mixer ctrl).  Having input and output unmuted doesn't
+-         * seem to cause a problem.
+-         */
+-        {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+-	/* Unmute pin widget used for Line-in (no equiv mixer ctrl) */
++	/* Unmute input buffer of pin widget used for Line-in (no equiv 
++	 * mixer ctrl)
++	 */
+         {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ 
+         /* Mute capture amp left and right */
+@@ -2882,7 +2907,11 @@ static struct hda_verb alc260_test_init_verbs[] = {
+ 	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ 	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ 
+-	/* Unmute retasking pin widget output amp left/right (no mixer ctrl) */
++	/* Unmute retasking pin widget output buffers since the default
++	 * state appears to be output.  As the pin mode is changed by the
++	 * user the pin mode control will take care of enabling the pin's
++	 * input/output buffers as needed.
++	 */
+ 	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ 	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+@@ -2892,17 +2921,6 @@ static struct hda_verb alc260_test_init_verbs[] = {
+ 	/* Also unmute the mono-out pin widget */
+ 	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ 
+-	/* Also unmute the retasking pin input amps.  Having the input and
+-	 * output amps unmuted at the same time doesn't appear to cause any
+-	 * trouble.
+-	 */
+-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+-	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+-	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+-
+ 	/* Mute capture amp left and right */
+ 	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ 	/* Set ADC connection select to match default mixer setting - line 

commit 17e7aec680a252ec0cea6d886d3983319af43ac4
+Author: Jonathan Woithe 
+Date:   Tue Feb 28 11:35:18 2006 +0100
+
+    [ALSA] HDA/ALC260: 1/7 - Fix test model input mux label
+    
+    Modules: HDA Codec driver
+    
+    This patch fixes input mux labels used for the ALC260 'test' model.  This is
+    needed to avoid confusion which comes about because the two ADCs in the
+    ALC260 have slightly different mappings for their input selectors. Since
+    this is just the test model it's sufficient to simply report both options
+    where they exist.  If a model comes along for which this becomes an issue,
+    the ALC260 input mux code will have to be extended to allow different mux
+    layouts for different ADCs.
+    
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index ea4200a4ee42..b34d2448d172 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -2414,8 +2414,8 @@ static struct hda_input_mux alc260_capture_source = {
+ 	},
+ };
+ 
+-/* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack
+- * and the internal CD lines.
++/* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack,
++ * headphone jack and the internal CD lines.
+  */
+ static struct hda_input_mux alc260_fujitsu_capture_source = {
+ 	.num_items = 3,
+@@ -2790,16 +2790,26 @@ static hda_nid_t alc260_test_dac_nids[1] = {
+ static hda_nid_t alc260_test_adc_nids[2] = {
+ 	0x04, 0x05,
+ };
++/* This is a bit messy since the two input muxes in the ALC260 have slight
++ * variations in their signal assignments.  The ideal way to deal with this
++ * is to extend alc_spec.input_mux to allow a different input MUX for each
++ * ADC.  For the purposes of the test model it's sufficient to just list
++ * both options for affected signal indices.  The separate input mux
++ * functionality only needs to be considered if a model comes along which
++ * actually uses signals 0x5, 0x6 and 0x7 for something which makes sense to
++ * record.
++ */
+ static struct hda_input_mux alc260_test_capture_source = {
+-	.num_items = 7,
++	.num_items = 8,
+ 	.items = {
+ 		{ "MIC1 pin", 0x0 },
+ 		{ "MIC2 pin", 0x1 },
+ 		{ "LINE1 pin", 0x2 },
+ 		{ "LINE2 pin", 0x3 },
+ 		{ "CD pin", 0x4 },
+-		{ "LINE-OUT pin", 0x5 },
+-		{ "HP-OUT pin", 0x6 },
++		{ "LINE-OUT pin (cap1), Mixer (cap2)", 0x5 },
++		{ "HP-OUT pin (cap1), LINE-OUT pin (cap2)", 0x6 },
++		{ "HP-OUT pin (cap2 only)", 0x7 },
+         },
+ };
+ static struct snd_kcontrol_new alc260_test_mixer[] = {

commit 7cf51e48315d87b4c1cf600d611894f45f661142
+Author: Jonathan Woithe 
+Date:   Thu Feb 9 12:01:26 2006 +0100
+
+    [ALSA] hda: ALC260 test model implementation
+    
+    Modules: HDA Codec driver
+    
+    The following patch adds a 'test' ALC260 model specification to the
+    patch_realtek.c driver if CONFIG_SND_DEBUG is set.  This is similar to the
+    'test' ALC880 model in that it sets up mixer controls for almost everything
+    to make it easier for people to test their laptop/soundcard when working out
+    what pin widgets are connected to which real-world devices.
+    
+    This patch assumes my previous patch (adding the second PCM to the ALC260)
+    has previously been applied since it uses infrastructure added by that
+    patch.
+    
+    In developing this patch it was found that not all retasking pins accept all
+    the modes - in particular, some ignore the VREFxx variants.  The pin mode
+    control has therefore been tweaked to prevent this becoming a problem in
+    mixer applications.
+    
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 8ec2db2e9b60..ea4200a4ee42 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -6,6 +6,7 @@
+  * Copyright (c) 2004 Kailang Yang 
+  *                    PeiSen Hou 
+  *                    Takashi Iwai 
++ *                    Jonathan Woithe 
+  *
+  *  This driver is free software; you can redistribute it and/or modify
+  *  it under the terms of the GNU General Public License as published by
+@@ -63,6 +64,9 @@ enum {
+ 	ALC260_HP,
+ 	ALC260_HP_3013,
+ 	ALC260_FUJITSU_S702X,
++#ifdef CONFIG_SND_DEBUG
++	ALC260_TEST,
++#endif
+ 	ALC260_AUTO,
+ 	ALC260_MODEL_LAST /* last tag */
+ };
+@@ -223,13 +227,19 @@ static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va
+  * instead of "%" to avoid consequences of accidently treating the % as 
+  * being part of a format specifier.  Maximum allowed length of a value is
+  * 63 characters plus NULL terminator.
++ *
++ * Note: some retasking pin complexes seem to ignore requests for input
++ * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these
++ * are requested.  Therefore order this list so that this behaviour will not
++ * cause problems when mixer clients move through the enum sequentially.
++ * NIDs 0x0f and 0x10 have been observed to have this behaviour.
+  */
+ static char *alc_pin_mode_names[] = {
+-	"Line in", "Mic 80pc bias", "Mic 50pc bias",
+-	"Line out", "Headphone out",
++	"Mic 50pc bias", "Mic 80pc bias",
++	"Line in", "Line out", "Headphone out",
+ };
+ static unsigned char alc_pin_mode_values[] = {
+-	PIN_IN, PIN_VREF80, PIN_VREF50, PIN_OUT, PIN_HP,
++	PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP,
+ };
+ /* The control can present all 5 options, or it can limit the options based
+  * in the pin being assumed to be exclusively an input or an output pin.
+@@ -2770,6 +2780,146 @@ static struct hda_verb alc260_fujitsu_init_verbs[] = {
+ 	{ }
+ };
+ 
++/* Test configuration for debugging, modelled after the ALC880 test
++ * configuration.
++ */
++#ifdef CONFIG_SND_DEBUG
++static hda_nid_t alc260_test_dac_nids[1] = {
++	0x02,
++};
++static hda_nid_t alc260_test_adc_nids[2] = {
++	0x04, 0x05,
++};
++static struct hda_input_mux alc260_test_capture_source = {
++	.num_items = 7,
++	.items = {
++		{ "MIC1 pin", 0x0 },
++		{ "MIC2 pin", 0x1 },
++		{ "LINE1 pin", 0x2 },
++		{ "LINE2 pin", 0x3 },
++		{ "CD pin", 0x4 },
++		{ "LINE-OUT pin", 0x5 },
++		{ "HP-OUT pin", 0x6 },
++        },
++};
++static struct snd_kcontrol_new alc260_test_mixer[] = {
++	/* Output driver widgets */
++	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
++	HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
++	HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x09, 0x0, HDA_OUTPUT),
++	HDA_BIND_MUTE("LOUT2 Playback Switch", 0x09, 2, HDA_INPUT),
++	HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT),
++	HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT),
++
++	/* Modes for retasking pin widgets */
++	ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT),
++	ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT),
++	ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT),
++	ALC_PIN_MODE("LINE1 pin mode", 0x14, ALC_PIN_DIR_INOUT),
++	ALC_PIN_MODE("MIC2 pin mode", 0x13, ALC_PIN_DIR_INOUT),
++	ALC_PIN_MODE("MIC1 pin mode", 0x12, ALC_PIN_DIR_INOUT),
++
++	/* Loopback mixer controls */
++	HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x07, 0x00, HDA_INPUT),
++	HDA_CODEC_MUTE("MIC1 Playback Switch", 0x07, 0x00, HDA_INPUT),
++	HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x07, 0x01, HDA_INPUT),
++	HDA_CODEC_MUTE("MIC2 Playback Switch", 0x07, 0x01, HDA_INPUT),
++	HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x07, 0x02, HDA_INPUT),
++	HDA_CODEC_MUTE("LINE1 Playback Switch", 0x07, 0x02, HDA_INPUT),
++	HDA_CODEC_VOLUME("LINE2 Playback Volume", 0x07, 0x03, HDA_INPUT),
++	HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT),
++	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
++	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
++	HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
++	HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
++	HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT),
++	HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT),
++	HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT),
++	HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT),
++	{ } /* end */
++};
++static struct hda_verb alc260_test_init_verbs[] = {
++	/* Disable all GPIOs */
++	{0x01, AC_VERB_SET_GPIO_MASK, 0},
++	/* Enable retasking pins as output, initially without power amp */
++	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
++	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
++	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
++	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
++	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
++	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
++
++	/* Disable digital (SPDIF) pins for now */
++	{0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
++	{0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
++
++	/* Ensure mic1, mic2, line1 and line2 pin widget take input from the 
++	 * OUT1 sum bus when acting as an output.
++	 */
++	{0x0b, AC_VERB_SET_CONNECT_SEL, 0},
++	{0x0c, AC_VERB_SET_CONNECT_SEL, 0},
++	{0x0d, AC_VERB_SET_CONNECT_SEL, 0},
++	{0x0e, AC_VERB_SET_CONNECT_SEL, 0},
++
++	/* Start with output sum widgets muted and their output gains at min */
++	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
++	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
++	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
++	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
++	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
++	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
++
++	/* Unmute retasking pin widget output amp left/right (no mixer ctrl) */
++	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
++	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
++	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
++	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
++	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
++	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
++	/* Also unmute the mono-out pin widget */
++	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
++
++	/* Also unmute the retasking pin input amps.  Having the input and
++	 * output amps unmuted at the same time doesn't appear to cause any
++	 * trouble.
++	 */
++	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
++	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
++	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
++	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
++	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
++	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
++
++	/* Mute capture amp left and right */
++	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	/* Set ADC connection select to match default mixer setting - line 
++	 * in (on mic1 pin)
++	 */
++	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
++
++	/* Do the same for the second ADC: mute capture input amp and
++	 * set ADC connection to line in
++	 */
++	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
++
++	/* Mute all inputs to mixer widget (even unconnected ones) */
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
++
++	{ }
++};
++#endif
++
+ static struct hda_pcm_stream alc260_pcm_analog_playback = {
+ 	.substreams = 1,
+ 	.channels_min = 2,
+@@ -3053,6 +3203,9 @@ static struct hda_board_config alc260_cfg_tbl[] = {
+ 	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3016, .config = ALC260_HP },
+ 	{ .modelname = "fujitsu", .config = ALC260_FUJITSU_S702X },
+ 	{ .pci_subvendor = 0x10cf, .pci_subdevice = 0x1326, .config = ALC260_FUJITSU_S702X },
++#ifdef CONFIG_SND_DEBUG
++	{ .modelname = "test", .config = ALC260_TEST },
++#endif
+ 	{ .modelname = "auto", .config = ALC260_AUTO },
+ 	{}
+ };
+@@ -3110,6 +3263,20 @@ static struct alc_config_preset alc260_presets[] = {
+ 		.channel_mode = alc260_modes,
+ 		.input_mux = &alc260_fujitsu_capture_source,
+ 	},
++#ifdef CONFIG_SND_DEBUG
++	[ALC260_TEST] = {
++		.mixers = { alc260_test_mixer,
++			    alc260_capture_mixer },
++		.init_verbs = { alc260_test_init_verbs },
++		.num_dacs = ARRAY_SIZE(alc260_test_dac_nids),
++		.dac_nids = alc260_test_dac_nids,
++		.num_adc_nids = ARRAY_SIZE(alc260_test_adc_nids),
++		.adc_nids = alc260_test_adc_nids,
++		.num_channel_mode = ARRAY_SIZE(alc260_modes),
++		.channel_mode = alc260_modes,
++		.input_mux = &alc260_test_capture_source,
++	},
++#endif
+ };
+ 
+ static int patch_alc260(struct hda_codec *codec)

commit 4c5186ed6b25278df595edf2d355ee87b00c4426
+Author: Jonathan Woithe 
+Date:   Thu Feb 9 11:53:48 2006 +0100
+
+    [ALSA] hda: add PCM for 2nd ADC on ALC260
+    
+    Modules: HDA Codec driver
+    
+    The following patch against alsa 1.0.11rc3 creates a PCM device (pcm1c) for
+    the second ADC present on the ALC260 codec used by the hda driver.  It also
+    defines a new mixer control allowing the mode of retasking pins to be set;
+    this means a user can (for example) designate the headphone jack to be a
+    second input. With this patch in place it is possible to do 4 channel
+    recording on laptops equipped with an ALC260 codec assuming both a stereo
+    line-in jack is provided in addition to a headphone jack.
+    
+    Mixer controls are provided to allow the headphone jack to be switched as
+    an input.  In addition, an (input only) mode control is configured for
+    the line-in jack to allow a bias voltage to be requested (VREF80 or VREF50)
+    so headsets based on condensor microphones have a chance of working.
+    
+    This patch has been tested on a Fujitsu S7020 laptop and as such these
+    features are currently only configured for the 'fujitsu' model.
+    
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index b76755264730..c8fc6269b03c 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -132,7 +132,7 @@ struct alc_spec {
+ 	int num_channel_mode;
+ 
+ 	/* PCM information */
+-	struct hda_pcm pcm_rec[2];	/* used in alc_build_pcms() */
++	struct hda_pcm pcm_rec[3];	/* used in alc_build_pcms() */
+ 
+ 	/* dynamic controls, init_verbs and input_mux */
+ 	struct auto_pin_cfg autocfg;
+@@ -218,56 +218,96 @@ static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va
+ 				   spec->num_channel_mode, &spec->multiout.max_channels);
+ }
+ 
+-
+ /*
+- * Control of pin widget settings via the mixer.  Only boolean settings are
+- * supported, so VrefEn can't be controlled using these functions as they
+- * stand.
++ * Control the mode of pin widget settings via the mixer.  "pc" is used
++ * instead of "%" to avoid consequences of accidently treating the % as 
++ * being part of a format specifier.  Maximum allowed length of a value is
++ * 63 characters plus NULL terminator.
++ */
++static char *alc_pin_mode_names[] = {
++	"Line in", "Mic 80pc bias", "Mic 50pc bias",
++	"Line out", "Headphone out",
++};
++static unsigned char alc_pin_mode_values[] = {
++	PIN_IN, PIN_VREF80, PIN_VREF50, PIN_OUT, PIN_HP,
++};
++/* The control can present all 5 options, or it can limit the options based
++ * in the pin being assumed to be exclusively an input or an output pin.
+  */
+-static int alc_pinctl_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
++#define ALC_PIN_DIR_IN    0x00
++#define ALC_PIN_DIR_OUT   0x01
++#define ALC_PIN_DIR_INOUT 0x02
++
++/* Info about the pin modes supported by the three different pin directions. 
++ * For each direction the minimum and maximum values are given.
++ */
++static signed char alc_pin_mode_dir_info[3][2] = {
++	{ 0, 2 },    /* ALC_PIN_DIR_IN */
++	{ 3, 4 },    /* ALC_PIN_DIR_OUT */
++	{ 0, 4 },    /* ALC_PIN_DIR_INOUT */
++};
++#define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0])
++#define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1])
++#define alc_pin_mode_n_items(_dir) \
++	(alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1)
++
++static int alc_pin_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+ {
+-	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
++	unsigned int item_num = uinfo->value.enumerated.item;
++	unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
++
++	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ 	uinfo->count = 1;
+-	uinfo->value.integer.min = 0;
+-	uinfo->value.integer.max = 1;
++	uinfo->value.enumerated.items = alc_pin_mode_n_items(dir);
++
++	if (item_numalc_pin_mode_max(dir))
++		item_num = alc_pin_mode_min(dir);
++	strcpy(uinfo->value.enumerated.name, alc_pin_mode_names[item_num]);
+ 	return 0;
+ }
+ 
+-static int alc_pinctl_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
++static int alc_pin_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+ {
++	unsigned int i;
+ 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ 	hda_nid_t nid = kcontrol->private_value & 0xffff;
+-	long mask = (kcontrol->private_value >> 16) & 0xff;
++	unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
+ 	long *valp = ucontrol->value.integer.value;
++	unsigned int pinctl = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_PIN_WIDGET_CONTROL,0x00);
+ 
+-	*valp = 0;
+-	if (snd_hda_codec_read(codec,nid,0,AC_VERB_GET_PIN_WIDGET_CONTROL,0x00) & mask)
+-		*valp = 1;
++	/* Find enumerated value for current pinctl setting */
++	i = alc_pin_mode_min(dir);
++	while (alc_pin_mode_values[i]!=pinctl && i<=alc_pin_mode_max(dir))
++		i++;
++	*valp = i<=alc_pin_mode_max(dir)?i:alc_pin_mode_min(dir);
+ 	return 0;
+ }
+ 
+-static int alc_pinctl_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
++static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+ {
++	signed int change;
+ 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ 	hda_nid_t nid = kcontrol->private_value & 0xffff;
+-	long mask = (kcontrol->private_value >> 16) & 0xff;
+-	long *valp = ucontrol->value.integer.value;
++	unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
++	long val = *ucontrol->value.integer.value;
+ 	unsigned int pinctl = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_PIN_WIDGET_CONTROL,0x00);
+-	int change = ((pinctl & mask)!=0) != *valp;
+ 
++	if (valalc_pin_mode_max(dir)) 
++		val = alc_pin_mode_min(dir);
++
++	change = pinctl != alc_pin_mode_values[val];
+ 	if (change)
+ 		snd_hda_codec_write(codec,nid,0,AC_VERB_SET_PIN_WIDGET_CONTROL,
+-			*valp?(pinctl|mask):(pinctl&~mask));
++			alc_pin_mode_values[val]);
+ 	return change;
+ }
+ 
+-#define ALC_PINCTL_SWITCH(xname, nid, mask) \
++#define ALC_PIN_MODE(xname, nid, dir) \
+ 	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
+-	  .info = alc_pinctl_switch_info, \
+-	  .get = alc_pinctl_switch_get, \
+-	  .put = alc_pinctl_switch_put, \
+-	  .private_value = (nid) | (mask<<16) }
+-
++	  .info = alc_pin_mode_info, \
++	  .get = alc_pin_mode_get, \
++	  .put = alc_pin_mode_put, \
++	  .private_value = nid | (dir<<16) }
+ 
+ /*
+  * set up from the preset table
+@@ -1250,6 +1290,13 @@ static struct hda_pcm_stream alc880_pcm_digital_capture = {
+ 	/* NID is set in alc_build_pcms */
+ };
+ 
++/* Used by alc_build_pcms to flag that a PCM has no playback stream */
++static struct hda_pcm_stream alc_pcm_null_playback = {
++	.substreams = 0,
++	.channels_min = 0,
++	.channels_max = 0,
++};
++
+ static int alc_build_pcms(struct hda_codec *codec)
+ {
+ 	struct alc_spec *spec = codec->spec;
+@@ -1280,6 +1327,23 @@ static int alc_build_pcms(struct hda_codec *codec)
+ 		}
+ 	}
+ 
++	/* If the use of more than one ADC is requested for the current
++	 * model, configure a second analog capture-only PCM.
++	 */
++	if (spec->num_adc_nids > 1) {
++		codec->num_pcms++;
++		info++;
++		info->name = spec->stream_name_analog;
++		/* No playback stream for second PCM */
++		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = alc_pcm_null_playback;
++		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
++		if (spec->stream_analog_capture) {
++			snd_assert(spec->adc_nids, return -EINVAL);
++			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
++			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[1];
++		}
++	}
++
+ 	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
+ 		codec->num_pcms++;
+ 		info++;
+@@ -2322,6 +2386,11 @@ static hda_nid_t alc260_hp_adc_nids[2] = {
+ 	0x05, 0x04
+ };
+ 
++static hda_nid_t alc260_fujitsu_adc_nids[2] = {
++	/* ADC0, ADC1 */
++	0x04, 0x05
++};
++
+ #define ALC260_DIGOUT_NID	0x03
+ #define ALC260_DIGIN_NID	0x06
+ 
+@@ -2339,10 +2408,11 @@ static struct hda_input_mux alc260_capture_source = {
+  * and the internal CD lines.
+  */
+ static struct hda_input_mux alc260_fujitsu_capture_source = {
+-	.num_items = 2,
++	.num_items = 3,
+ 	.items = {
+ 		{ "Mic/Line", 0x0 },
+ 		{ "CD", 0x4 },
++		{ "Headphone", 0x2 },
+ 	},
+ };
+ 
+@@ -2408,11 +2478,12 @@ static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
+ static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
+ 	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
+ 	HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),
+-	ALC_PINCTL_SWITCH("Headphone Amp Switch", 0x14, PIN_HP_AMP),
++	ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
+ 	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
+ 	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
+ 	HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT),
+ 	HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT),
++	ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN),
+ 	HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
+ 	HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
+ 	HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT),
+@@ -2645,6 +2716,11 @@ static struct hda_verb alc260_fujitsu_init_verbs[] = {
+         {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
+         {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
+ 
++        /* Ensure Line1 pin widget takes its input from the OUT1 sum bus 
++         * when acting as an output.
++         */
++        {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
++
+         /* Start with mixer outputs muted */
+         {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+         {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+@@ -2654,14 +2730,27 @@ static struct hda_verb alc260_fujitsu_init_verbs[] = {
+         {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+         /* Unmute Line1 pin widget amp left and right (no equiv mixer ctrl) */
+         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
++        /* Unmute Line1 pin widget input for when this pin is used as input
++         * (no equiv mixer ctrl).  Having input and output unmuted doesn't
++         * seem to cause a problem.
++         */
++        {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ 	/* Unmute pin widget used for Line-in (no equiv mixer ctrl) */
+         {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ 
+         /* Mute capture amp left and right */
+         {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+-        /* Set ADC connection select to line in (on mic1 pin) */
++        /* Set ADC connection select to match default mixer setting - line 
++         * in (on mic1 pin)
++         */
+         {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
+ 
++        /* Do the same for the second ADC: mute capture input amp and
++         * set ADC connection to line in
++         */
++        {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++        {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
++
+         /* Mute all inputs to mixer widget (even unconnected ones) */
+         {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
+         {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
+@@ -3009,8 +3098,8 @@ static struct alc_config_preset alc260_presets[] = {
+ 		.init_verbs = { alc260_fujitsu_init_verbs },
+ 		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
+ 		.dac_nids = alc260_dac_nids,
+-		.num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
+-		.adc_nids = alc260_adc_nids,
++		.num_adc_nids = ARRAY_SIZE(alc260_fujitsu_adc_nids),
++		.adc_nids = alc260_fujitsu_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc260_modes),
+ 		.channel_mode = alc260_modes,
+ 		.input_mux = &alc260_fujitsu_capture_source,

commit fd56f2db9385a651d31fe86eb4cc6cacbb0c5a63
+Author: Jonathan Woithe 
+Date:   Tue Jan 24 10:35:46 2006 +0100
+
+    [ALSA] hda-codec - Fix init verb of ALC260
+    
+    Modules: HDA Codec driver
+    
+    Fixed the wrong widget id for line-2 selector in the init verb
+    of ALC260.
+    
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 543980d89b83..043513b94b1c 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -2475,7 +2475,7 @@ static struct hda_verb alc260_init_verbs[] = {
+ 	/* LINE-2 is used for line-out in rear */
+ 	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ 	/* select line-out */
+-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
++	{0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
+ 	/* LINE-OUT pin */
+ 	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ 	/* enable HP */

commit a9430dd8fc232cfddcfaedde1a6a915e241366a8
+Author: Jonathan Woithe 
+Date:   Fri Sep 16 19:12:48 2005 +0200
+
+    [ALSA] hda-codec - A new model for Fujitsu S7020
+    
+    Modules: HDA Codec driver
+    
+    Added a new model 'fujitsu' to ALC260 config for Fujitsu S7020.
+    
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 7327deb6df9f..48356ab04579 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -57,6 +57,7 @@ enum {
+ enum {
+ 	ALC260_BASIC,
+ 	ALC260_HP,
++	ALC260_FUJITSU_S702x,
+ 	ALC260_MODEL_LAST /* last tag */
+ };
+ 
+@@ -72,6 +73,7 @@ enum {
+ #define PIN_VREF50	0x21
+ #define PIN_OUT		0x40
+ #define PIN_HP		0xc0
++#define PIN_HP_AMP	0x80
+ 
+ struct alc_spec {
+ 	/* codec parameterization */
+@@ -284,6 +286,54 @@ static int alc_bind_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u
+ 
+ #define ALC_BIND_MUTE(xname,nid,indices,dir) ALC_BIND_MUTE_MONO(xname,nid,3,indices,dir)
+ 
++/*
++ * Control of pin widget settings via the mixer.  Only boolean settings are
++ * supported, so VrefEn can't be controlled using these functions as they
++ * stand.
++ */
++static int alc_pinctl_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
++{
++	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
++	uinfo->count = 1;
++	uinfo->value.integer.min = 0;
++	uinfo->value.integer.max = 1;
++	return 0;
++}
++
++static int alc_pinctl_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
++{
++	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
++	hda_nid_t nid = kcontrol->private_value & 0xffff;
++	long mask = (kcontrol->private_value >> 16) & 0xff;
++	long *valp = ucontrol->value.integer.value;
++
++	*valp = 0;
++	if (snd_hda_codec_read(codec,nid,0,AC_VERB_GET_PIN_WIDGET_CONTROL,0x00) & mask)
++		*valp = 1;
++	return 0;
++}
++
++static int alc_pinctl_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
++{
++	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
++	hda_nid_t nid = kcontrol->private_value & 0xffff;
++	long mask = (kcontrol->private_value >> 16) & 0xff;
++	long *valp = ucontrol->value.integer.value;
++	unsigned int pinctl = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_PIN_WIDGET_CONTROL,0x00);
++	int change = ((pinctl & mask)!=0) != *valp;
++
++	if (change)
++		snd_hda_codec_write(codec,nid,0,AC_VERB_SET_PIN_WIDGET_CONTROL,
++			*valp?(pinctl|mask):(pinctl&~mask));
++	return change;
++}
++
++#define ALC_PINCTL_SWITCH(xname, nid, mask) \
++	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
++	  .info = alc_pinctl_switch_info, \
++	  .get = alc_pinctl_switch_get, \
++	  .put = alc_pinctl_switch_put, \
++	  .private_value = (nid) | (mask<<16) }
+ 
+ /*
+  * ALC880 3-stack model
+@@ -2205,6 +2255,17 @@ static struct hda_input_mux alc260_capture_source = {
+ 	},
+ };
+ 
++/* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack
++ * and the internal CD lines.
++ */
++static struct hda_input_mux alc260_fujitsu_capture_source = {
++	.num_items = 2,
++	.items = {
++		{ "Mic/Line", 0x0 },
++		{ "CD", 0x4 },
++	},
++};
++
+ /*
+  * This is just place-holder, so there's something for alc_build_pcms to look
+  * at when it calculates the maximum number of channels. ALC260 has no mixer
+@@ -2271,6 +2332,30 @@ static snd_kcontrol_new_t alc260_hp_mixer[] = {
+ 	{ } /* end */
+ };
+ 
++static snd_kcontrol_new_t alc260_fujitsu_mixer[] = {
++	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
++	ALC_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),
++	ALC_PINCTL_SWITCH("Headphone Amp Switch", 0x14, PIN_HP_AMP),
++	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
++	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
++	HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT),
++	HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT),
++	HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
++	HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
++	HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT),
++	ALC_BIND_MUTE("Internal Speaker Playback Switch", 0x09, 2, HDA_INPUT),
++	HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
++	HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
++	{
++		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++		.name = "Capture Source",
++		.info = alc_mux_enum_info,
++		.get = alc_mux_enum_get,
++		.put = alc_mux_enum_put,
++	},
++	{ } /* end */
++};
++
+ static struct hda_verb alc260_init_verbs[] = {
+ 	/* Line In pin widget for input */
+ 	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+@@ -2332,6 +2417,60 @@ static struct hda_verb alc260_init_verbs[] = {
+ 	{ }
+ };
+ 
++/* Initialisation sequence for ALC260 as configured in Fujitsu S702x
++ * laptops.
++ */
++static struct hda_verb alc260_fujitsu_init_verbs[] = {
++	/* Disable all GPIOs */
++	{0x01, AC_VERB_SET_GPIO_MASK, 0},
++	/* Internal speaker is connected to headphone pin */
++	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
++	/* Headphone/Line-out jack connects to Line1 pin; make it an output */
++	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
++        /* Mic/Line-in jack is connected to mic1 pin, so make it an input */
++        {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
++        /* Ensure all other unused pins are disabled and muted.
++	 * Note: trying to set widget 0x15 to anything blocks all audio
++	 * output for some reason, so just leave that at the default.
++	 */
++        {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
++        {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
++        {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
++        {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++        /* Disable digital (SPDIF) pins */
++        {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
++        {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
++
++        /* Start with mixer outputs muted */
++        {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++        {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++        {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++
++        /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */
++        {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
++        /* Unmute Line1 pin widget amp left and right (no equiv mixer ctrl) */
++        {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
++	/* Unmute pin widget used for Line-in (no equiv mixer ctrl) */
++        {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
++
++        /* Mute capture amp left and right */
++        {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++        /* Set ADC connection select to line in (on mic1 pin) */
++        {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
++
++        /* Mute all inputs to mixer widget (even unconnected ones) */
++        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
++        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
++        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
++        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
++        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
++        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
++        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
++        {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
++};
++
+ static struct hda_pcm_stream alc260_pcm_analog_playback = {
+ 	.substreams = 1,
+ 	.channels_min = 2,
+@@ -2347,6 +2486,8 @@ static struct hda_pcm_stream alc260_pcm_analog_capture = {
+ static struct hda_board_config alc260_cfg_tbl[] = {
+ 	{ .modelname = "hp", .config = ALC260_HP },
+ 	{ .pci_subvendor = 0x103c, .config = ALC260_HP },
++	{ .modelname = "fujitsu", .config = ALC260_FUJITSU_S702x },
++	{ .pci_subvendor = 0x10cf, .pci_subdevice = 0x1326, .config = ALC260_FUJITSU_S702x },
+ 	{}
+ };
+ 
+@@ -2373,14 +2514,23 @@ static int patch_alc260(struct hda_codec *codec)
+ 		spec->mixers[spec->num_mixers] = alc260_hp_mixer;
+ 		spec->num_mixers++;
+ 		break;
++	case ALC260_FUJITSU_S702x:
++		spec->mixers[spec->num_mixers] = alc260_fujitsu_mixer;
++		spec->num_mixers++;
++		break;
+ 	default:
+ 		spec->mixers[spec->num_mixers] = alc260_base_mixer;
+ 		spec->num_mixers++;
+ 		break;
+ 	}
+ 
+-	spec->init_verbs[0] = alc260_init_verbs;
+-	spec->num_init_verbs = 1;
++	if (board_config != ALC260_FUJITSU_S702x) {
++		spec->init_verbs[0] = alc260_init_verbs;
++		spec->num_init_verbs = 1;
++	} else {
++		spec->init_verbs[0] = alc260_fujitsu_init_verbs;
++		spec->num_init_verbs = 1;
++	}
+ 
+ 	spec->channel_mode = alc260_modes;
+ 	spec->num_channel_mode = ARRAY_SIZE(alc260_modes);
+@@ -2393,7 +2543,11 @@ static int patch_alc260(struct hda_codec *codec)
+ 	spec->multiout.num_dacs = ARRAY_SIZE(alc260_dac_nids);
+ 	spec->multiout.dac_nids = alc260_dac_nids;
+ 
+-	spec->input_mux = &alc260_capture_source;
++	if (board_config != ALC260_FUJITSU_S702x) {
++		spec->input_mux = &alc260_capture_source;
++	} else {
++		spec->input_mux = &alc260_fujitsu_capture_source;
++	}
+ 	switch (board_config) {
+ 	case ALC260_HP:
+ 		spec->num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids);

\ No newline at end of file diff --git a/detail/27.html b/detail/27.html new file mode 100644 index 0000000..bef7f86 --- /dev/null +++ b/detail/27.html @@ -0,0 +1,4292 @@ +

Patches contributed by Georgia Institute of Technology


commit fe1c97d008f86f672f0e9265f180c22451ca3b9f
+Author: David Ward 
+Date:   Mon May 10 05:30:39 2021 -0400
+
+    drm/amd/display: Initialize attribute for hdcp_srm sysfs file
+    
+    It is stored in dynamically allocated memory, so sysfs_bin_attr_init() must
+    be called to initialize it. (Note: "initialization" only sets the .attr.key
+    member in this struct; it does not change the value of any other members.)
+    
+    Otherwise, when CONFIG_DEBUG_LOCK_ALLOC=y this message appears during boot:
+    
+        BUG: key ffff9248900cd148 has not been registered!
+    
+    Fixes: 9037246bb2da ("drm/amd/display: Add sysfs interface for set/get srm")
+    Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1586
+    Reported-by: Mikhail Gavrilov 
+    Signed-off-by: David Ward 
+    Signed-off-by: Alex Deucher 
+    Cc: stable@vger.kernel.org
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
+index 616f5b1ea3a8..666796a0067c 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
+@@ -650,6 +650,7 @@ struct hdcp_workqueue *hdcp_create_workqueue(struct amdgpu_device *adev, struct
+ 
+ 	/* File created at /sys/class/drm/card0/device/hdcp_srm*/
+ 	hdcp_work[0].attr = data_attr;
++	sysfs_bin_attr_init(&hdcp_work[0].attr);
+ 
+ 	if (sysfs_create_bin_file(&adev->dev->kobj, &hdcp_work[0].attr))
+ 		DRM_WARN("Failed to create device file hdcp_srm");

commit 29b25b7067a4fa92afd379ebd7c16b9cbed5e0c0
+Author: David Ward 
+Date:   Mon May 10 05:30:39 2021 -0400
+
+    drm/amd/display: Initialize attribute for hdcp_srm sysfs file
+    
+    It is stored in dynamically allocated memory, so sysfs_bin_attr_init() must
+    be called to initialize it. (Note: "initialization" only sets the .attr.key
+    member in this struct; it does not change the value of any other members.)
+    
+    Otherwise, when CONFIG_DEBUG_LOCK_ALLOC=y this message appears during boot:
+    
+        BUG: key ffff9248900cd148 has not been registered!
+    
+    Fixes: 9037246bb2da ("drm/amd/display: Add sysfs interface for set/get srm")
+    Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1586
+    Reported-by: Mikhail Gavrilov 
+    Signed-off-by: David Ward 
+    Signed-off-by: Alex Deucher 
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
+index 616f5b1ea3a8..666796a0067c 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
+@@ -650,6 +650,7 @@ struct hdcp_workqueue *hdcp_create_workqueue(struct amdgpu_device *adev, struct
+ 
+ 	/* File created at /sys/class/drm/card0/device/hdcp_srm*/
+ 	hdcp_work[0].attr = data_attr;
++	sysfs_bin_attr_init(&hdcp_work[0].attr);
+ 
+ 	if (sysfs_create_bin_file(&adev->dev->kobj, &hdcp_work[0].attr))
+ 		DRM_WARN("Failed to create device file hdcp_srm");

commit aa2f9c12821e6a4ba1df4fb34a3dbc6a2a1ee7fe
+Author: David Ward 
+Date:   Sun Apr 18 09:46:58 2021 -0400
+
+    ASoC: rt286: Generalize support for ALC3263 codec
+    
+    The ALC3263 codec on the XPS 13 9343 is also found on the Latitude 13 7350
+    and Venue 11 Pro 7140. They require the same handling for the combo jack to
+    work with a headset: GPIO pin 6 must be set.
+    
+    The HDA driver always sets this pin on the ALC3263, which it distinguishes
+    by the codec vendor/device ID 0x10ec0288 and PCI subsystem vendor ID 0x1028
+    (Dell). The ASoC driver does not use PCI, so adapt this check to use DMI to
+    determine if Dell is the system vendor.
+    
+    BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=150601
+    BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=205961
+    Signed-off-by: David Ward 
+    Reviewed-by: Pierre-Louis Bossart 
+    Link: https://lore.kernel.org/r/20210418134658.4333-6-david.ward@gatech.edu
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c
+index 45e4a48ef5bf..802f4851c3df 100644
+--- a/sound/soc/codecs/rt286.c
++++ b/sound/soc/codecs/rt286.c
+@@ -1125,12 +1125,11 @@ static const struct dmi_system_id force_combo_jack_table[] = {
+ 	{ }
+ };
+ 
+-static const struct dmi_system_id dmi_dell_dino[] = {
++static const struct dmi_system_id dmi_dell[] = {
+ 	{
+-		.ident = "Dell Dino",
++		.ident = "Dell",
+ 		.matches = {
+ 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+-			DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9343")
+ 		}
+ 	},
+ 	{ }
+@@ -1141,7 +1140,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
+ {
+ 	struct rt286_platform_data *pdata = dev_get_platdata(&i2c->dev);
+ 	struct rt286_priv *rt286;
+-	int i, ret, val;
++	int i, ret, vendor_id;
+ 
+ 	rt286 = devm_kzalloc(&i2c->dev,	sizeof(*rt286),
+ 				GFP_KERNEL);
+@@ -1157,14 +1156,15 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
+ 	}
+ 
+ 	ret = regmap_read(rt286->regmap,
+-		RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &val);
++		RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &vendor_id);
+ 	if (ret != 0) {
+ 		dev_err(&i2c->dev, "I2C error %d\n", ret);
+ 		return ret;
+ 	}
+-	if (val != RT286_VENDOR_ID && val != RT288_VENDOR_ID) {
++	if (vendor_id != RT286_VENDOR_ID && vendor_id != RT288_VENDOR_ID) {
+ 		dev_err(&i2c->dev,
+-			"Device with ID register %#x is not rt286\n", val);
++			"Device with ID register %#x is not rt286\n",
++			vendor_id);
+ 		return -ENODEV;
+ 	}
+ 
+@@ -1188,8 +1188,8 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
+ 	if (pdata)
+ 		rt286->pdata = *pdata;
+ 
+-	if (dmi_check_system(force_combo_jack_table) ||
+-		dmi_check_system(dmi_dell_dino))
++	if ((vendor_id == RT288_VENDOR_ID && dmi_check_system(dmi_dell)) ||
++		dmi_check_system(force_combo_jack_table))
+ 		rt286->pdata.cbj_en = true;
+ 
+ 	regmap_write(rt286->regmap, RT286_SET_AUDIO_POWER, AC_PWRST_D3);
+@@ -1228,7 +1228,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
+ 	regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL3, 0xf777, 0x4737);
+ 	regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL4, 0x00ff, 0x003f);
+ 
+-	if (dmi_check_system(dmi_dell_dino)) {
++	if (vendor_id == RT288_VENDOR_ID && dmi_check_system(dmi_dell)) {
+ 		regmap_update_bits(rt286->regmap,
+ 			RT286_SET_GPIO_MASK, 0x40, 0x40);
+ 		regmap_update_bits(rt286->regmap,

commit f3bd4dde9f048fa711e98626c8c3bc4d1eae3436
+Author: David Ward 
+Date:   Sun Apr 18 09:46:56 2021 -0400
+
+    ASoC: rt298: Configure combo jack for headphones
+    
+    During jack detection, the combo jack is configured for a CTIA headset, and
+    then for an OMTP headset, while sensing the mic connection. If a mic is not
+    found in either case, the combo jack should be re-configured for headphones
+    only. This is consistent with the HDA driver behavior.
+    
+    Signed-off-by: David Ward 
+    Reviewed-by: Pierre-Louis Bossart 
+    Link: https://lore.kernel.org/r/20210418134658.4333-4-david.ward@gatech.edu
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c
+index 32cc9b6287d2..c592c40a7ab3 100644
+--- a/sound/soc/codecs/rt298.c
++++ b/sound/soc/codecs/rt298.c
+@@ -267,11 +267,16 @@ static int rt298_jack_detect(struct rt298_priv *rt298, bool *hp, bool *mic)
+ 				msleep(300);
+ 				regmap_read(rt298->regmap,
+ 					RT298_CBJ_CTRL2, &val);
+-				if (0x0070 == (val & 0x0070))
++				if (0x0070 == (val & 0x0070)) {
+ 					*mic = true;
+-				else
++				} else {
+ 					*mic = false;
++					regmap_update_bits(rt298->regmap,
++						RT298_CBJ_CTRL1,
++						0xfcc0, 0xc400);
++				}
+ 			}
++
+ 			regmap_update_bits(rt298->regmap,
+ 				RT298_DC_GAIN, 0x200, 0x0);
+ 

commit b15c3ea7e0d2c53b33adc8ca0896de378d6df853
+Author: David Ward 
+Date:   Sun Apr 18 09:46:55 2021 -0400
+
+    ASoC: rt286: Configure combo jack for headphones
+    
+    During jack detection, the combo jack is configured for a CTIA headset, and
+    then for an OMTP headset, while sensing the mic connection. If a mic is not
+    found in either case, the combo jack should be re-configured for headphones
+    only. This is consistent with the HDA driver behavior.
+    
+    Signed-off-by: David Ward 
+    Reviewed-by: Pierre-Louis Bossart 
+    Link: https://lore.kernel.org/r/20210418134658.4333-3-david.ward@gatech.edu
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c
+index e16e7237156f..45e4a48ef5bf 100644
+--- a/sound/soc/codecs/rt286.c
++++ b/sound/soc/codecs/rt286.c
+@@ -255,11 +255,16 @@ static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic)
+ 				msleep(300);
+ 				regmap_read(rt286->regmap,
+ 					RT286_CBJ_CTRL2, &val);
+-				if (0x0070 == (val & 0x0070))
++				if (0x0070 == (val & 0x0070)) {
+ 					*mic = true;
+-				else
++				} else {
+ 					*mic = false;
++					regmap_update_bits(rt286->regmap,
++						RT286_CBJ_CTRL1,
++						0xfcc0, 0xc400);
++				}
+ 			}
++
+ 			regmap_update_bits(rt286->regmap,
+ 				RT286_DC_GAIN, 0x200, 0x0);
+ 

commit cd8499d5c03ba260e3191e90236d0e5f6b147563
+Author: David Ward 
+Date:   Sun Apr 18 09:46:57 2021 -0400
+
+    ASoC: rt286: Make RT286_SET_GPIO_* readable and writable
+    
+    The GPIO configuration cannot be applied if the registers are inaccessible.
+    This prevented the headset mic from working on the Dell XPS 13 9343.
+    
+    BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=114171
+    Signed-off-by: David Ward 
+    Link: https://lore.kernel.org/r/20210418134658.4333-5-david.ward@gatech.edu
+    Reviewed-by: Pierre-Louis Bossart 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c
+index f9b29782b62a..e16e7237156f 100644
+--- a/sound/soc/codecs/rt286.c
++++ b/sound/soc/codecs/rt286.c
+@@ -171,6 +171,9 @@ static bool rt286_readable_register(struct device *dev, unsigned int reg)
+ 	case RT286_PROC_COEF:
+ 	case RT286_SET_AMP_GAIN_ADC_IN1:
+ 	case RT286_SET_AMP_GAIN_ADC_IN2:
++	case RT286_SET_GPIO_MASK:
++	case RT286_SET_GPIO_DIRECTION:
++	case RT286_SET_GPIO_DATA:
+ 	case RT286_SET_POWER(RT286_DAC_OUT1):
+ 	case RT286_SET_POWER(RT286_DAC_OUT2):
+ 	case RT286_SET_POWER(RT286_ADC_IN1):

commit dfa7b01dbdc9723ced606425b47005bb583a8778
+Author: David Ward 
+Date:   Sun Apr 18 09:46:54 2021 -0400
+
+    ASoC: rt286: Fix upper byte in DMIC2 configuration
+    
+    This HDA verb sets the upper byte of the Configuration Default register, so
+    only an 8-bit value should be used. For the rt298, the same fix was applied
+    in commit f8f2dc4a7127 ("ASoC: rt298: fix wrong setting of gpio2_en").
+    
+    Signed-off-by: David Ward 
+    Link: https://lore.kernel.org/r/20210418134658.4333-2-david.ward@gatech.edu
+    Reviewed-by: Pierre-Louis Bossart 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c
+index 8abe232ca4a4..f9b29782b62a 100644
+--- a/sound/soc/codecs/rt286.c
++++ b/sound/soc/codecs/rt286.c
+@@ -1204,7 +1204,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
+ 	mdelay(10);
+ 
+ 	if (!rt286->pdata.gpio2_en)
+-		regmap_write(rt286->regmap, RT286_SET_DMIC2_DEFAULT, 0x4000);
++		regmap_write(rt286->regmap, RT286_SET_DMIC2_DEFAULT, 0x40);
+ 	else
+ 		regmap_write(rt286->regmap, RT286_SET_DMIC2_DEFAULT, 0);
+ 

commit 9c68ed09fe11cdd45cd84f8dcf634c2ca4075a52
+Author: Anish Bhatt 
+Date:   Sun Oct 18 22:51:41 2015 -0700
+
+    rtl8188eu : BIT() macro cleanup
+    
+    Use the BIT(x) macro directly instead using multiple
+    BITX defines.
+    
+    Signed-off-by: Anish Bhatt 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c
+index 7b99ea91a9e6..685ce98620f1 100644
+--- a/drivers/staging/rtl8188eu/core/rtw_efuse.c
++++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c
+@@ -396,7 +396,7 @@ u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_e
+ 
+ 	memset((void *)tmpdata, 0xff, PGPKT_DATA_SIZE);
+ 
+-	if (!(word_en&BIT0)) {
++	if (!(word_en & BIT(0))) {
+ 		tmpaddr = start_addr;
+ 		efuse_OneByteWrite(pAdapter, start_addr++, data[0]);
+ 		efuse_OneByteWrite(pAdapter, start_addr++, data[1]);
+@@ -404,9 +404,9 @@ u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_e
+ 		efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[0]);
+ 		efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[1]);
+ 		if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1]))
+-			badworden &= (~BIT0);
++			badworden &= (~BIT(0));
+ 	}
+-	if (!(word_en&BIT1)) {
++	if (!(word_en & BIT(1))) {
+ 		tmpaddr = start_addr;
+ 		efuse_OneByteWrite(pAdapter, start_addr++, data[2]);
+ 		efuse_OneByteWrite(pAdapter, start_addr++, data[3]);
+@@ -414,9 +414,9 @@ u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_e
+ 		efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[2]);
+ 		efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[3]);
+ 		if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3]))
+-			badworden &= (~BIT1);
++			badworden &= (~BIT(1));
+ 	}
+-	if (!(word_en&BIT2)) {
++	if (!(word_en & BIT(2))) {
+ 		tmpaddr = start_addr;
+ 		efuse_OneByteWrite(pAdapter, start_addr++, data[4]);
+ 		efuse_OneByteWrite(pAdapter, start_addr++, data[5]);
+@@ -424,9 +424,9 @@ u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_e
+ 		efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[4]);
+ 		efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[5]);
+ 		if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5]))
+-			badworden &= (~BIT2);
++			badworden &= (~BIT(2));
+ 	}
+-	if (!(word_en&BIT3)) {
++	if (!(word_en & BIT(3))) {
+ 		tmpaddr = start_addr;
+ 		efuse_OneByteWrite(pAdapter, start_addr++, data[6]);
+ 		efuse_OneByteWrite(pAdapter, start_addr++, data[7]);
+@@ -434,7 +434,7 @@ u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_e
+ 		efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[6]);
+ 		efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[7]);
+ 		if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7]))
+-			badworden &= (~BIT3);
++			badworden &= (~BIT(3));
+ 	}
+ 	return badworden;
+ }
+@@ -738,18 +738,18 @@ static bool wordEnMatched(struct pgpkt *pTargetPkt, struct pgpkt *pCurPkt,
+ 	u8 match_word_en = 0x0F;	/*  default all words are disabled */
+ 
+ 	/*  check if the same words are enabled both target and current PG packet */
+-	if (((pTargetPkt->word_en & BIT0) == 0) &&
+-	    ((pCurPkt->word_en & BIT0) == 0))
+-		match_word_en &= ~BIT0;				/*  enable word 0 */
+-	if (((pTargetPkt->word_en & BIT1) == 0) &&
+-	    ((pCurPkt->word_en & BIT1) == 0))
+-		match_word_en &= ~BIT1;				/*  enable word 1 */
+-	if (((pTargetPkt->word_en & BIT2) == 0) &&
+-	    ((pCurPkt->word_en & BIT2) == 0))
+-		match_word_en &= ~BIT2;				/*  enable word 2 */
+-	if (((pTargetPkt->word_en & BIT3) == 0) &&
+-	    ((pCurPkt->word_en & BIT3) == 0))
+-		match_word_en &= ~BIT3;				/*  enable word 3 */
++	if (((pTargetPkt->word_en & BIT(0)) == 0) &&
++	    ((pCurPkt->word_en & BIT(0)) == 0))
++		match_word_en &= ~BIT(0);				/*  enable word 0 */
++	if (((pTargetPkt->word_en & BIT(1)) == 0) &&
++	    ((pCurPkt->word_en & BIT(1)) == 0))
++		match_word_en &= ~BIT(1);				/*  enable word 1 */
++	if (((pTargetPkt->word_en & BIT(2)) == 0) &&
++	    ((pCurPkt->word_en & BIT(2)) == 0))
++		match_word_en &= ~BIT(2);				/*  enable word 2 */
++	if (((pTargetPkt->word_en & BIT(3)) == 0) &&
++	    ((pCurPkt->word_en & BIT(3)) == 0))
++		match_word_en &= ~BIT(3);				/*  enable word 3 */
+ 
+ 	*pWden = match_word_en;
+ 
+@@ -961,19 +961,19 @@ u8 efuse_OneByteWrite(struct adapter *pAdapter, u16 addr, u8 data)
+  */
+ void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata)
+ {
+-	if (!(word_en&BIT(0))) {
++	if (!(word_en & BIT(0))) {
+ 		targetdata[0] = sourdata[0];
+ 		targetdata[1] = sourdata[1];
+ 	}
+-	if (!(word_en&BIT(1))) {
++	if (!(word_en & BIT(1))) {
+ 		targetdata[2] = sourdata[2];
+ 		targetdata[3] = sourdata[3];
+ 	}
+-	if (!(word_en&BIT(2))) {
++	if (!(word_en & BIT(2))) {
+ 		targetdata[4] = sourdata[4];
+ 		targetdata[5] = sourdata[5];
+ 	}
+-	if (!(word_en&BIT(3))) {
++	if (!(word_en & BIT(3))) {
+ 		targetdata[6] = sourdata[6];
+ 		targetdata[7] = sourdata[7];
+ 	}
+diff --git a/drivers/staging/rtl8188eu/hal/bb_cfg.c b/drivers/staging/rtl8188eu/hal/bb_cfg.c
+index 4eb982bdbfc0..264d7e366246 100644
+--- a/drivers/staging/rtl8188eu/hal/bb_cfg.c
++++ b/drivers/staging/rtl8188eu/hal/bb_cfg.c
+@@ -705,7 +705,7 @@ bool rtl88eu_phy_bb_config(struct adapter *adapt)
+ 
+ 	/*  Enable BB and RF */
+ 	regval = usb_read16(adapt, REG_SYS_FUNC_EN);
+-	usb_write16(adapt, REG_SYS_FUNC_EN, (u16)(regval|BIT13|BIT0|BIT1));
++	usb_write16(adapt, REG_SYS_FUNC_EN, (u16)(regval | BIT(13) | BIT(0) | BIT(1)));
+ 
+ 	usb_write8(adapt, REG_RF_CTRL, RF_EN|RF_RSTB|RF_SDMRSTB);
+ 
+diff --git a/drivers/staging/rtl8188eu/hal/odm.c b/drivers/staging/rtl8188eu/hal/odm.c
+index 46be4de50629..2c25d3b02036 100644
+--- a/drivers/staging/rtl8188eu/hal/odm.c
++++ b/drivers/staging/rtl8188eu/hal/odm.c
+@@ -437,7 +437,7 @@ void odm_CommonInfoSelfInit(struct odm_dm_struct *pDM_Odm)
+ {
+ 	struct adapter *adapter = pDM_Odm->Adapter;
+ 
+-	pDM_Odm->bCckHighPower = (bool)phy_query_bb_reg(adapter, 0x824, BIT9);
++	pDM_Odm->bCckHighPower = (bool)phy_query_bb_reg(adapter, 0x824, BIT(9));
+ 	pDM_Odm->RFPathRxEnable = (u8)phy_query_bb_reg(adapter, 0xc04, 0x0F);
+ 
+ 	ODM_InitDebugSetting(pDM_Odm);
+@@ -736,8 +736,8 @@ void odm_FalseAlarmCounterStatistics(struct odm_dm_struct *pDM_Odm)
+ 		return;
+ 
+ 	/* hold ofdm counter */
+-	phy_set_bb_reg(adapter, ODM_REG_OFDM_FA_HOLDC_11N, BIT31, 1); /* hold page C counter */
+-	phy_set_bb_reg(adapter, ODM_REG_OFDM_FA_RSTD_11N, BIT31, 1); /* hold page D counter */
++	phy_set_bb_reg(adapter, ODM_REG_OFDM_FA_HOLDC_11N, BIT(31), 1); /* hold page C counter */
++	phy_set_bb_reg(adapter, ODM_REG_OFDM_FA_RSTD_11N, BIT(31), 1); /* hold page D counter */
+ 
+ 	ret_value = phy_query_bb_reg(adapter, ODM_REG_OFDM_FA_TYPE1_11N, bMaskDWord);
+ 	FalseAlmCnt->Cnt_Fast_Fsync = (ret_value&0xffff);
+@@ -760,8 +760,8 @@ void odm_FalseAlarmCounterStatistics(struct odm_dm_struct *pDM_Odm)
+ 	FalseAlmCnt->Cnt_BW_USC = (ret_value & 0xffff0000)>>16;
+ 
+ 	/* hold cck counter */
+-	phy_set_bb_reg(adapter, ODM_REG_CCK_FA_RST_11N, BIT12, 1);
+-	phy_set_bb_reg(adapter, ODM_REG_CCK_FA_RST_11N, BIT14, 1);
++	phy_set_bb_reg(adapter, ODM_REG_CCK_FA_RST_11N, BIT(12), 1);
++	phy_set_bb_reg(adapter, ODM_REG_CCK_FA_RST_11N, BIT(14), 1);
+ 
+ 	ret_value = phy_query_bb_reg(adapter, ODM_REG_CCK_FA_LSB_11N, bMaskByte0);
+ 	FalseAlmCnt->Cnt_Cck_fail = ret_value;
+@@ -853,7 +853,7 @@ void ODM_RF_Saving(struct odm_dm_struct *pDM_Odm, u8 bForceInNormal)
+ 	}
+ 	if (pDM_PSTable->initialize == 0) {
+ 		pDM_PSTable->Reg874 = (phy_query_bb_reg(adapter, 0x874, bMaskDWord)&0x1CC000)>>14;
+-		pDM_PSTable->RegC70 = (phy_query_bb_reg(adapter, 0xc70, bMaskDWord)&BIT3)>>3;
++		pDM_PSTable->RegC70 = (phy_query_bb_reg(adapter, 0xc70, bMaskDWord) & BIT(3))>>3;
+ 		pDM_PSTable->Reg85C = (phy_query_bb_reg(adapter, 0x85c, bMaskDWord)&0xFF000000)>>24;
+ 		pDM_PSTable->RegA74 = (phy_query_bb_reg(adapter, 0xa74, bMaskDWord)&0xF000)>>12;
+ 		pDM_PSTable->initialize = 1;
+@@ -882,18 +882,18 @@ void ODM_RF_Saving(struct odm_dm_struct *pDM_Odm, u8 bForceInNormal)
+ 	if (pDM_PSTable->PreRFState != pDM_PSTable->CurRFState) {
+ 		if (pDM_PSTable->CurRFState == RF_Save) {
+ 			phy_set_bb_reg(adapter, 0x874, 0x1C0000, 0x2); /* Reg874[20:18]=3'b010 */
+-			phy_set_bb_reg(adapter, 0xc70, BIT3, 0); /* RegC70[3]=1'b0 */
++			phy_set_bb_reg(adapter, 0xc70, BIT(3), 0); /* RegC70[3]=1'b0 */
+ 			phy_set_bb_reg(adapter, 0x85c, 0xFF000000, 0x63); /* Reg85C[31:24]=0x63 */
+ 			phy_set_bb_reg(adapter, 0x874, 0xC000, 0x2); /* Reg874[15:14]=2'b10 */
+ 			phy_set_bb_reg(adapter, 0xa74, 0xF000, 0x3); /* RegA75[7:4]=0x3 */
+-			phy_set_bb_reg(adapter, 0x818, BIT28, 0x0); /* Reg818[28]=1'b0 */
+-			phy_set_bb_reg(adapter, 0x818, BIT28, 0x1); /* Reg818[28]=1'b1 */
++			phy_set_bb_reg(adapter, 0x818, BIT(28), 0x0); /* Reg818[28]=1'b0 */
++			phy_set_bb_reg(adapter, 0x818, BIT(28), 0x1); /* Reg818[28]=1'b1 */
+ 		} else {
+ 			phy_set_bb_reg(adapter, 0x874, 0x1CC000, pDM_PSTable->Reg874);
+-			phy_set_bb_reg(adapter, 0xc70, BIT3, pDM_PSTable->RegC70);
++			phy_set_bb_reg(adapter, 0xc70, BIT(3), pDM_PSTable->RegC70);
+ 			phy_set_bb_reg(adapter, 0x85c, 0xFF000000, pDM_PSTable->Reg85C);
+ 			phy_set_bb_reg(adapter, 0xa74, 0xF000, pDM_PSTable->RegA74);
+-			phy_set_bb_reg(adapter, 0x818, BIT28, 0x0);
++			phy_set_bb_reg(adapter, 0x818, BIT(28), 0x0);
+ 		}
+ 		pDM_PSTable->PreRFState = pDM_PSTable->CurRFState;
+ 	}
+@@ -1229,7 +1229,7 @@ void odm_TXPowerTrackingCheckCE(struct odm_dm_struct *pDM_Odm)
+ 		return;
+ 
+ 	if (!pDM_Odm->RFCalibrateInfo.TM_Trigger) {		/* at least delay 1 sec */
+-		phy_set_rf_reg(Adapter, RF_PATH_A, RF_T_METER_88E, BIT17 | BIT16, 0x03);
++		phy_set_rf_reg(Adapter, RF_PATH_A, RF_T_METER_88E, BIT(17) | BIT(16), 0x03);
+ 
+ 		pDM_Odm->RFCalibrateInfo.TM_Trigger = 1;
+ 		return;
+diff --git a/drivers/staging/rtl8188eu/hal/odm_HWConfig.c b/drivers/staging/rtl8188eu/hal/odm_HWConfig.c
+index 36afe45d1c9a..3dd6cff873d9 100644
+--- a/drivers/staging/rtl8188eu/hal/odm_HWConfig.c
++++ b/drivers/staging/rtl8188eu/hal/odm_HWConfig.c
+@@ -362,7 +362,7 @@ static void odm_Process_RSSIForDM(struct odm_dm_struct *dm_odm,
+ 				}
+ 			}
+ 
+-			pEntry->rssi_stat.PacketMap = (pEntry->rssi_stat.PacketMap<<1) | BIT0;
++			pEntry->rssi_stat.PacketMap = (pEntry->rssi_stat.PacketMap<<1) | BIT(0);
+ 
+ 		} else {
+ 			RSSI_Ave = pPhyInfo->RxPWDBAll;
+@@ -391,7 +391,7 @@ static void odm_Process_RSSIForDM(struct odm_dm_struct *dm_odm,
+ 			pEntry->rssi_stat.ValidBit++;
+ 
+ 		for (i = 0; i < pEntry->rssi_stat.ValidBit; i++)
+-			OFDM_pkt += (u8)(pEntry->rssi_stat.PacketMap>>i)&BIT0;
++			OFDM_pkt += (u8)(pEntry->rssi_stat.PacketMap>>i) & BIT(0);
+ 
+ 		if (pEntry->rssi_stat.ValidBit == 64) {
+ 			Weighting = ((OFDM_pkt<<4) > 64) ? 64 : (OFDM_pkt<<4);
+diff --git a/drivers/staging/rtl8188eu/hal/odm_RTL8188E.c b/drivers/staging/rtl8188eu/hal/odm_RTL8188E.c
+index d3c6873925ba..0be6c051e804 100644
+--- a/drivers/staging/rtl8188eu/hal/odm_RTL8188E.c
++++ b/drivers/staging/rtl8188eu/hal/odm_RTL8188E.c
+@@ -28,26 +28,26 @@ static void dm_rx_hw_antena_div_init(struct odm_dm_struct *dm_odm)
+ 
+ 	if (*(dm_odm->mp_mode) == 1) {
+ 		dm_odm->AntDivType = CGCS_RX_SW_ANTDIV;
+-		phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT7, 0);
+-		phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT31, 1);
++		phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 0);
++		phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(31), 1);
+ 		return;
+ 	}
+ 
+ 	/* MAC Setting */
+ 	value32 = phy_query_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord);
+ 	phy_set_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord,
+-		       value32|(BIT23|BIT25));
++		       value32|(BIT(23) | BIT(25)));
+ 	/* Pin Settings */
+-	phy_set_bb_reg(adapter, ODM_REG_PIN_CTRL_11N, BIT9|BIT8, 0);
+-	phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, BIT10, 0);
+-	phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT22, 1);
+-	phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT31, 1);
++	phy_set_bb_reg(adapter, ODM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);
++	phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, BIT(10), 0);
++	phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(22), 1);
++	phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(31), 1);
+ 	/* OFDM Settings */
+ 	phy_set_bb_reg(adapter, ODM_REG_ANTDIV_PARA1_11N, bMaskDWord,
+ 		       0x000000a0);
+ 	/* CCK Settings */
+-	phy_set_bb_reg(adapter, ODM_REG_BB_PWR_SAV4_11N, BIT7, 1);
+-	phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT4, 1);
++	phy_set_bb_reg(adapter, ODM_REG_BB_PWR_SAV4_11N, BIT(7), 1);
++	phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1);
+ 	rtl88eu_dm_update_rx_idle_ant(dm_odm, MAIN_ANT);
+ 	phy_set_bb_reg(adapter, ODM_REG_ANT_MAPPING1_11N, 0xFFFF, 0x0201);
+ }
+@@ -59,37 +59,37 @@ static void dm_trx_hw_antenna_div_init(struct odm_dm_struct *dm_odm)
+ 
+ 	if (*(dm_odm->mp_mode) == 1) {
+ 		dm_odm->AntDivType = CGCS_RX_SW_ANTDIV;
+-		phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT7, 0);
++		phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 0);
+ 		phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
+-			       BIT5|BIT4|BIT3, 0);
++			       BIT(5) | BIT(4) | BIT(3), 0);
+ 		return;
+ 	}
+ 
+ 	/* MAC Setting */
+ 	value32 = phy_query_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord);
+ 	phy_set_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord,
+-		       value32|(BIT23|BIT25));
++		       value32|(BIT(23) | BIT(25)));
+ 	/* Pin Settings */
+-	phy_set_bb_reg(adapter, ODM_REG_PIN_CTRL_11N, BIT9|BIT8, 0);
+-	phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, BIT10, 0);
+-	phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT22, 0);
+-	phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT31, 1);
++	phy_set_bb_reg(adapter, ODM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);
++	phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, BIT(10), 0);
++	phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(22), 0);
++	phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(31), 1);
+ 	/* OFDM Settings */
+ 	phy_set_bb_reg(adapter, ODM_REG_ANTDIV_PARA1_11N, bMaskDWord,
+ 		       0x000000a0);
+ 	/* CCK Settings */
+-	phy_set_bb_reg(adapter, ODM_REG_BB_PWR_SAV4_11N, BIT7, 1);
+-	phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT4, 1);
++	phy_set_bb_reg(adapter, ODM_REG_BB_PWR_SAV4_11N, BIT(7), 1);
++	phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1);
+ 	/* Tx Settings */
+-	phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N, BIT21, 0);
++	phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N, BIT(21), 0);
+ 	rtl88eu_dm_update_rx_idle_ant(dm_odm, MAIN_ANT);
+ 
+ 	/* antenna mapping table */
+ 	if (!dm_odm->bIsMPChip) { /* testchip */
+ 		phy_set_bb_reg(adapter, ODM_REG_RX_DEFUALT_A_11N,
+-			       BIT10|BIT9|BIT8, 1);
++			       BIT(10) | BIT(9) | BIT(8), 1);
+ 		phy_set_bb_reg(adapter, ODM_REG_RX_DEFUALT_A_11N,
+-			       BIT13|BIT12|BIT11, 2);
++			       BIT(13) | BIT(12) | BIT(11), 2);
+ 	} else { /* MPchip */
+ 		phy_set_bb_reg(adapter, ODM_REG_ANT_MAPPING1_11N, bMaskDWord,
+ 			       0x0201);
+@@ -118,40 +118,40 @@ static void dm_fast_training_init(struct odm_dm_struct *dm_odm)
+ 
+ 	/* MAC Setting */
+ 	value32 = phy_query_bb_reg(adapter, 0x4c, bMaskDWord);
+-	phy_set_bb_reg(adapter, 0x4c, bMaskDWord, value32|(BIT23|BIT25));
++	phy_set_bb_reg(adapter, 0x4c, bMaskDWord, value32|(BIT(23) | BIT(25)));
+ 	value32 = phy_query_bb_reg(adapter,  0x7B4, bMaskDWord);
+-	phy_set_bb_reg(adapter, 0x7b4, bMaskDWord, value32|(BIT16|BIT17));
++	phy_set_bb_reg(adapter, 0x7b4, bMaskDWord, value32|(BIT(16) | BIT(17)));
+ 
+ 	/* Match MAC ADDR */
+ 	phy_set_bb_reg(adapter, 0x7b4, 0xFFFF, 0);
+ 	phy_set_bb_reg(adapter, 0x7b0, bMaskDWord, 0);
+ 
+-	phy_set_bb_reg(adapter, 0x870, BIT9|BIT8, 0);
+-	phy_set_bb_reg(adapter, 0x864, BIT10, 0);
+-	phy_set_bb_reg(adapter, 0xb2c, BIT22, 0);
+-	phy_set_bb_reg(adapter, 0xb2c, BIT31, 1);
++	phy_set_bb_reg(adapter, 0x870, BIT(9) | BIT(8), 0);
++	phy_set_bb_reg(adapter, 0x864, BIT(10), 0);
++	phy_set_bb_reg(adapter, 0xb2c, BIT(22), 0);
++	phy_set_bb_reg(adapter, 0xb2c, BIT(31), 1);
+ 	phy_set_bb_reg(adapter, 0xca4, bMaskDWord, 0x000000a0);
+ 
+ 	/* antenna mapping table */
+ 	if (AntCombination == 2) {
+ 		if (!dm_odm->bIsMPChip) { /* testchip */
+-			phy_set_bb_reg(adapter, 0x858, BIT10|BIT9|BIT8, 1);
+-			phy_set_bb_reg(adapter, 0x858, BIT13|BIT12|BIT11, 2);
++			phy_set_bb_reg(adapter, 0x858, BIT(10) | BIT(9) | BIT(8), 1);
++			phy_set_bb_reg(adapter, 0x858, BIT(13) | BIT(12) | BIT(11), 2);
+ 		} else { /* MPchip */
+ 			phy_set_bb_reg(adapter, 0x914, bMaskByte0, 1);
+ 			phy_set_bb_reg(adapter, 0x914, bMaskByte1, 2);
+ 		}
+ 	} else if (AntCombination == 7) {
+ 		if (!dm_odm->bIsMPChip) { /* testchip */
+-			phy_set_bb_reg(adapter, 0x858, BIT10|BIT9|BIT8, 0);
+-			phy_set_bb_reg(adapter, 0x858, BIT13|BIT12|BIT11, 1);
+-			phy_set_bb_reg(adapter, 0x878, BIT16, 0);
+-			phy_set_bb_reg(adapter, 0x858, BIT15|BIT14, 2);
+-			phy_set_bb_reg(adapter, 0x878, BIT19|BIT18|BIT17, 3);
+-			phy_set_bb_reg(adapter, 0x878, BIT22|BIT21|BIT20, 4);
+-			phy_set_bb_reg(adapter, 0x878, BIT25|BIT24|BIT23, 5);
+-			phy_set_bb_reg(adapter, 0x878, BIT28|BIT27|BIT26, 6);
+-			phy_set_bb_reg(adapter, 0x878, BIT31|BIT30|BIT29, 7);
++			phy_set_bb_reg(adapter, 0x858, BIT(10) | BIT(9) | BIT(8), 0);
++			phy_set_bb_reg(adapter, 0x858, BIT(13) | BIT(12) | BIT(11), 1);
++			phy_set_bb_reg(adapter, 0x878, BIT(16), 0);
++			phy_set_bb_reg(adapter, 0x858, BIT(15) | BIT(14), 2);
++			phy_set_bb_reg(adapter, 0x878, BIT(19) | BIT(18) | BIT(17), 3);
++			phy_set_bb_reg(adapter, 0x878, BIT(22) | BIT(21) | BIT(20), 4);
++			phy_set_bb_reg(adapter, 0x878, BIT(25) | BIT(24) | BIT(23), 5);
++			phy_set_bb_reg(adapter, 0x878, BIT(28) | BIT(27) | BIT(26), 6);
++			phy_set_bb_reg(adapter, 0x878, BIT(31) | BIT(30) | BIT(29), 7);
+ 		} else { /* MPchip */
+ 			phy_set_bb_reg(adapter, 0x914, bMaskByte0, 0);
+ 			phy_set_bb_reg(adapter, 0x914, bMaskByte1, 1);
+@@ -165,13 +165,13 @@ static void dm_fast_training_init(struct odm_dm_struct *dm_odm)
+ 	}
+ 
+ 	/* Default Ant Setting when no fast training */
+-	phy_set_bb_reg(adapter, 0x80c, BIT21, 1);
+-	phy_set_bb_reg(adapter, 0x864, BIT5|BIT4|BIT3, 0);
+-	phy_set_bb_reg(adapter, 0x864, BIT8|BIT7|BIT6, 1);
++	phy_set_bb_reg(adapter, 0x80c, BIT(21), 1);
++	phy_set_bb_reg(adapter, 0x864, BIT(5) | BIT(4) | BIT(3), 0);
++	phy_set_bb_reg(adapter, 0x864, BIT(8) | BIT(7) | BIT(6), 1);
+ 
+ 	/* Enter Traing state */
+-	phy_set_bb_reg(adapter, 0x864, BIT2|BIT1|BIT0, (AntCombination-1));
+-	phy_set_bb_reg(adapter, 0xc50, BIT7, 1);
++	phy_set_bb_reg(adapter, 0x864, BIT(2) | BIT(1) | BIT(0), (AntCombination-1));
++	phy_set_bb_reg(adapter, 0xc50, BIT(7), 1);
+ }
+ 
+ void rtl88eu_dm_antenna_div_init(struct odm_dm_struct *dm_odm)
+@@ -205,18 +205,18 @@ void rtl88eu_dm_update_rx_idle_ant(struct odm_dm_struct *dm_odm, u8 ant)
+ 
+ 		if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) {
+ 			phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
+-				       BIT5|BIT4|BIT3, default_ant);
++				       BIT(5) | BIT(4) | BIT(3), default_ant);
+ 			phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
+-				       BIT8|BIT7|BIT6, optional_ant);
++				       BIT(8) | BIT(7) | BIT(6), optional_ant);
+ 			phy_set_bb_reg(adapter, ODM_REG_ANTSEL_CTRL_11N,
+-				       BIT14|BIT13|BIT12, default_ant);
++				       BIT(14) | BIT(13) | BIT(12), default_ant);
+ 			phy_set_bb_reg(adapter, ODM_REG_RESP_TX_11N,
+-				       BIT6|BIT7, default_ant);
++				       BIT(6) | BIT(7), default_ant);
+ 		} else if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV) {
+ 			phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
+-				       BIT5|BIT4|BIT3, default_ant);
++				       BIT(5) | BIT(4) | BIT(3), default_ant);
+ 			phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
+-				       BIT8|BIT7|BIT6, optional_ant);
++				       BIT(8) | BIT(7) | BIT(6), optional_ant);
+ 		}
+ 	}
+ 	dm_fat_tbl->RxIdleAnt = ant;
+@@ -231,9 +231,9 @@ static void update_tx_ant_88eu(struct odm_dm_struct *dm_odm, u8 ant, u32 mac_id)
+ 		target_ant = MAIN_ANT_CG_TRX;
+ 	else
+ 		target_ant = AUX_ANT_CG_TRX;
+-	dm_fat_tbl->antsel_a[mac_id] = target_ant&BIT0;
+-	dm_fat_tbl->antsel_b[mac_id] = (target_ant&BIT1)>>1;
+-	dm_fat_tbl->antsel_c[mac_id] = (target_ant&BIT2)>>2;
++	dm_fat_tbl->antsel_a[mac_id] = target_ant & BIT(0);
++	dm_fat_tbl->antsel_b[mac_id] = (target_ant & BIT(1))>>1;
++	dm_fat_tbl->antsel_c[mac_id] = (target_ant & BIT(2))>>2;
+ }
+ 
+ void rtl88eu_dm_set_tx_ant_by_tx_info(struct odm_dm_struct *dm_odm,
+@@ -344,12 +344,12 @@ void rtl88eu_dm_antenna_diversity(struct odm_dm_struct *dm_odm)
+ 		if (dm_fat_tbl->bBecomeLinked) {
+ 			ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
+ 				     ("Need to Turn off HW AntDiv\n"));
+-			phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT7, 0);
++			phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 0);
+ 			phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA1_11N,
+-				       BIT15, 0);
++				       BIT(15), 0);
+ 			if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
+ 				phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N,
+-					       BIT21, 0);
++					       BIT(21), 0);
+ 			dm_fat_tbl->bBecomeLinked = dm_odm->bLinked;
+ 		}
+ 		return;
+@@ -357,12 +357,12 @@ void rtl88eu_dm_antenna_diversity(struct odm_dm_struct *dm_odm)
+ 		if (!dm_fat_tbl->bBecomeLinked) {
+ 			ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
+ 				     ("Need to Turn on HW AntDiv\n"));
+-			phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT7, 1);
++			phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 1);
+ 			phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA1_11N,
+-				       BIT15, 1);
++				       BIT(15), 1);
+ 			if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
+ 				phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N,
+-					       BIT21, 1);
++					       BIT(21), 1);
+ 			dm_fat_tbl->bBecomeLinked = dm_odm->bLinked;
+ 		}
+ 	}
+diff --git a/drivers/staging/rtl8188eu/hal/phy.c b/drivers/staging/rtl8188eu/hal/phy.c
+index 2eafa503f343..bb3c7773d74f 100644
+--- a/drivers/staging/rtl8188eu/hal/phy.c
++++ b/drivers/staging/rtl8188eu/hal/phy.c
+@@ -97,9 +97,9 @@ static u32 rf_serial_read(struct adapter *adapt,
+ 	udelay(10);
+ 
+ 	if (rfpath == RF_PATH_A)
+-		rfpi_enable = (u8)phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter1, BIT8);
++		rfpi_enable = (u8)phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter1, BIT(8));
+ 	else if (rfpath == RF_PATH_B)
+-		rfpi_enable = (u8)phy_query_bb_reg(adapt, rFPGA0_XB_HSSIParameter1, BIT8);
++		rfpi_enable = (u8)phy_query_bb_reg(adapt, rFPGA0_XB_HSSIParameter1, BIT(8));
+ 
+ 	if (rfpi_enable)
+ 		ret = phy_query_bb_reg(adapt, phyreg->rfLSSIReadBackPi,
+@@ -293,7 +293,7 @@ static void phy_set_bw_mode_callback(struct adapter *adapt)
+ 		    (hal_data->nCur40MhzPrimeSC>>1));
+ 		phy_set_bb_reg(adapt, rOFDM1_LSTF, 0xC00,
+ 			       hal_data->nCur40MhzPrimeSC);
+-		phy_set_bb_reg(adapt, 0x818, (BIT26 | BIT27),
++		phy_set_bb_reg(adapt, 0x818, (BIT(26) | BIT(27)),
+ 		   (hal_data->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
+ 		break;
+ 	default:
+@@ -652,7 +652,7 @@ static u8 phy_path_a_iqk(struct adapter *adapt, bool config_pathb)
+ 	reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
+ 	reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
+ 
+-	if (!(reg_eac & BIT28) &&
++	if (!(reg_eac & BIT(28)) &&
+ 	    (((reg_e94 & 0x03FF0000)>>16) != 0x142) &&
+ 	    (((reg_e9c & 0x03FF0000)>>16) != 0x42))
+ 		result |= 0x01;
+@@ -705,7 +705,7 @@ static u8 phy_path_a_rx_iqk(struct adapter *adapt, bool configPathB)
+ 	reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
+ 	reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
+ 
+-	if (!(reg_eac & BIT28) &&
++	if (!(reg_eac & BIT(28)) &&
+ 	    (((reg_e94 & 0x03FF0000)>>16) != 0x142) &&
+ 	    (((reg_e9c & 0x03FF0000)>>16) != 0x42))
+ 		result |= 0x01;
+@@ -753,7 +753,7 @@ static u8 phy_path_a_rx_iqk(struct adapter *adapt, bool configPathB)
+ 	phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
+ 	phy_set_rf_reg(adapt, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x180);
+ 
+-	if (!(reg_eac & BIT27) && /* if Tx is OK, check whether Rx is OK */
++	if (!(reg_eac & BIT(27)) && /* if Tx is OK, check whether Rx is OK */
+ 	    (((reg_ea4 & 0x03FF0000)>>16) != 0x132) &&
+ 	    (((reg_eac & 0x03FF0000)>>16) != 0x36))
+ 		result |= 0x02;
+@@ -783,14 +783,14 @@ static u8 phy_path_b_iqk(struct adapter *adapt)
+ 	regec4 = phy_query_bb_reg(adapt, rRx_Power_Before_IQK_B_2, bMaskDWord);
+ 	regecc = phy_query_bb_reg(adapt, rRx_Power_After_IQK_B_2, bMaskDWord);
+ 
+-	if (!(regeac & BIT31) &&
++	if (!(regeac & BIT(31)) &&
+ 	    (((regeb4 & 0x03FF0000)>>16) != 0x142) &&
+ 	    (((regebc & 0x03FF0000)>>16) != 0x42))
+ 		result |= 0x01;
+ 	else
+ 		return result;
+ 
+-	if (!(regeac & BIT30) &&
++	if (!(regeac & BIT(30)) &&
+ 	    (((regec4 & 0x03FF0000)>>16) != 0x132) &&
+ 	    (((regecc & 0x03FF0000)>>16) != 0x36))
+ 		result |= 0x02;
+@@ -959,9 +959,9 @@ static void mac_setting_calibration(struct adapter *adapt, u32 *mac_reg, u32 *ba
+ 	usb_write8(adapt, mac_reg[i], 0x3F);
+ 
+ 	for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++) {
+-		usb_write8(adapt, mac_reg[i], (u8)(backup[i]&(~BIT3)));
++		usb_write8(adapt, mac_reg[i], (u8)(backup[i]&(~BIT(3))));
+ 	}
+-	usb_write8(adapt, mac_reg[i], (u8)(backup[i]&(~BIT5)));
++	usb_write8(adapt, mac_reg[i], (u8)(backup[i]&(~BIT(5))));
+ }
+ 
+ static void path_a_standby(struct adapter *adapt)
+@@ -1117,15 +1117,15 @@ static void phy_iq_calibrate(struct adapter *adapt, s32 result[][8],
+ 	}
+ 
+ 	/* BB setting */
+-	phy_set_bb_reg(adapt, rFPGA0_RFMOD, BIT24, 0x00);
++	phy_set_bb_reg(adapt, rFPGA0_RFMOD, BIT(24), 0x00);
+ 	phy_set_bb_reg(adapt, rOFDM0_TRxPathEnable, bMaskDWord, 0x03a05600);
+ 	phy_set_bb_reg(adapt, rOFDM0_TRMuxPar, bMaskDWord, 0x000800e4);
+ 	phy_set_bb_reg(adapt, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22204000);
+ 
+-	phy_set_bb_reg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT10, 0x01);
+-	phy_set_bb_reg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT26, 0x01);
+-	phy_set_bb_reg(adapt, rFPGA0_XA_RFInterfaceOE, BIT10, 0x00);
+-	phy_set_bb_reg(adapt, rFPGA0_XB_RFInterfaceOE, BIT10, 0x00);
++	phy_set_bb_reg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT(10), 0x01);
++	phy_set_bb_reg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT(26), 0x01);
++	phy_set_bb_reg(adapt, rFPGA0_XA_RFInterfaceOE, BIT(10), 0x00);
++	phy_set_bb_reg(adapt, rFPGA0_XB_RFInterfaceOE, BIT(10), 0x00);
+ 
+ 	if (is2t) {
+ 		phy_set_bb_reg(adapt, rFPGA0_XA_LSSIParameter, bMaskDWord,
+diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
+index d5281409168d..2d88c5a44439 100644
+--- a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
++++ b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
+@@ -149,7 +149,7 @@ void rtl8188e_Add_RateATid(struct adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi
+ 
+ 	init_rate = get_highest_rate_idx(bitmap&0x0fffffff)&0x3f;
+ 
+-	shortGIrate = (arg&BIT(5)) ? true : false;
++	shortGIrate = (arg & BIT(5)) ? true : false;
+ 
+ 	if (shortGIrate)
+ 		init_rate |= BIT(6);
+@@ -577,23 +577,23 @@ void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus)
+ 		/*  Do not set TSF again here or vWiFi beacon DMA INT will not work. */
+ 
+ 		/* Set REG_CR bit 8. DMA beacon by SW. */
+-		haldata->RegCR_1 |= BIT0;
++		haldata->RegCR_1 |= BIT(0);
+ 		usb_write8(adapt,  REG_CR+1, haldata->RegCR_1);
+ 
+ 		/*  Disable Hw protection for a time which revserd for Hw sending beacon. */
+ 		/*  Fix download reserved page packet fail that access collision with the protection time. */
+ 		/*  2010.05.11. Added by tynli. */
+ 		usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL)&(~BIT(3)));
+-		usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL)|BIT(4));
++		usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL) | BIT(4));
+ 
+-		if (haldata->RegFwHwTxQCtrl&BIT6) {
++		if (haldata->RegFwHwTxQCtrl & BIT(6)) {
+ 			DBG_88E("HalDownloadRSVDPage(): There is an Adapter is sending beacon.\n");
+ 			bSendBeacon = true;
+ 		}
+ 
+ 		/*  Set FWHW_TXQ_CTRL 0x422[6]=0 to tell Hw the packet is not a real beacon frame. */
+-		usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl&(~BIT6)));
+-		haldata->RegFwHwTxQCtrl &= (~BIT6);
++		usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl&(~BIT(6))));
++		haldata->RegFwHwTxQCtrl &= (~BIT(6));
+ 
+ 		/*  Clear beacon valid check bit. */
+ 		rtw_hal_set_hwreg(adapt, HW_VAR_BCN_VALID, NULL);
+@@ -626,7 +626,7 @@ void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus)
+ 		/*  */
+ 
+ 		/*  Enable Bcn */
+-		usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL)|BIT(3));
++		usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL) | BIT(3));
+ 		usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL)&(~BIT(4)));
+ 
+ 		/*  To make sure that if there exists an adapter which would like to send beacon. */
+@@ -635,8 +635,8 @@ void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus)
+ 		/*  the beacon cannot be sent by HW. */
+ 		/*  2010.06.23. Added by tynli. */
+ 		if (bSendBeacon) {
+-			usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl|BIT6));
+-			haldata->RegFwHwTxQCtrl |= BIT6;
++			usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl | BIT(6)));
++			haldata->RegFwHwTxQCtrl |= BIT(6);
+ 		}
+ 
+ 		/*  Update RSVD page location H2C to Fw. */
+@@ -647,7 +647,7 @@ void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus)
+ 
+ 		/*  Do not enable HW DMA BCN or it will cause Pcie interface hang by timing issue. 2011.11.24. by tynli. */
+ 		/*  Clear CR[8] or beacon packet will not be send to TxBuf anymore. */
+-		haldata->RegCR_1 &= (~BIT0);
++		haldata->RegCR_1 &= (~BIT(0));
+ 		usb_write8(adapt,  REG_CR+1, haldata->RegCR_1);
+ 	}
+ }
+diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
+index a6295ca6a73e..29353bf1884e 100644
+--- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
++++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
+@@ -106,8 +106,8 @@ void _8051Reset88E(struct adapter *padapter)
+ 	u8 u1bTmp;
+ 
+ 	u1bTmp = usb_read8(padapter, REG_SYS_FUNC_EN+1);
+-	usb_write8(padapter, REG_SYS_FUNC_EN+1, u1bTmp&(~BIT2));
+-	usb_write8(padapter, REG_SYS_FUNC_EN+1, u1bTmp|(BIT2));
++	usb_write8(padapter, REG_SYS_FUNC_EN+1, u1bTmp&(~BIT(2)));
++	usb_write8(padapter, REG_SYS_FUNC_EN+1, u1bTmp|(BIT(2)));
+ 	DBG_88E("=====> _8051Reset88E(): 8051 reset success .\n");
+ }
+ 
+@@ -184,10 +184,10 @@ static void hal_notch_filter_8188e(struct adapter *adapter, bool enable)
+ {
+ 	if (enable) {
+ 		DBG_88E("Enable notch filter\n");
+-		usb_write8(adapter, rOFDM0_RxDSP+1, usb_read8(adapter, rOFDM0_RxDSP+1) | BIT1);
++		usb_write8(adapter, rOFDM0_RxDSP+1, usb_read8(adapter, rOFDM0_RxDSP+1) | BIT(1));
+ 	} else {
+ 		DBG_88E("Disable notch filter\n");
+-		usb_write8(adapter, rOFDM0_RxDSP+1, usb_read8(adapter, rOFDM0_RxDSP+1) & ~BIT1);
++		usb_write8(adapter, rOFDM0_RxDSP+1, usb_read8(adapter, rOFDM0_RxDSP+1) & ~BIT(1));
+ 	}
+ }
+ void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc)
+@@ -372,7 +372,7 @@ static void Hal_ReadPowerValueFromPROM_8188E(struct txpowerinfo24g *pwrInfo24G,
+ 					pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_24G_HT20_DIFF;
+ 				} else {
+ 					pwrInfo24G->BW20_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0xf0)>>4;
+-					if (pwrInfo24G->BW20_Diff[rfPath][TxCount] & BIT3)		/* 4bit sign number to 8 bit sign number */
++					if (pwrInfo24G->BW20_Diff[rfPath][TxCount] & BIT(3))		/* 4bit sign number to 8 bit sign number */
+ 						pwrInfo24G->BW20_Diff[rfPath][TxCount] |= 0xF0;
+ 				}
+ 
+@@ -380,7 +380,7 @@ static void Hal_ReadPowerValueFromPROM_8188E(struct txpowerinfo24g *pwrInfo24G,
+ 					pwrInfo24G->OFDM_Diff[rfPath][TxCount] =	EEPROM_DEFAULT_24G_OFDM_DIFF;
+ 				} else {
+ 					pwrInfo24G->OFDM_Diff[rfPath][TxCount] =	(PROMContent[eeAddr]&0x0f);
+-					if (pwrInfo24G->OFDM_Diff[rfPath][TxCount] & BIT3)		/* 4bit sign number to 8 bit sign number */
++					if (pwrInfo24G->OFDM_Diff[rfPath][TxCount] & BIT(3))		/* 4bit sign number to 8 bit sign number */
+ 						pwrInfo24G->OFDM_Diff[rfPath][TxCount] |= 0xF0;
+ 				}
+ 				pwrInfo24G->CCK_Diff[rfPath][TxCount] = 0;
+@@ -390,7 +390,7 @@ static void Hal_ReadPowerValueFromPROM_8188E(struct txpowerinfo24g *pwrInfo24G,
+ 					pwrInfo24G->BW40_Diff[rfPath][TxCount] =	EEPROM_DEFAULT_DIFF;
+ 				} else {
+ 					pwrInfo24G->BW40_Diff[rfPath][TxCount] =	(PROMContent[eeAddr]&0xf0)>>4;
+-					if (pwrInfo24G->BW40_Diff[rfPath][TxCount] & BIT3)		/* 4bit sign number to 8 bit sign number */
++					if (pwrInfo24G->BW40_Diff[rfPath][TxCount] & BIT(3))		/* 4bit sign number to 8 bit sign number */
+ 						pwrInfo24G->BW40_Diff[rfPath][TxCount] |= 0xF0;
+ 				}
+ 
+@@ -398,7 +398,7 @@ static void Hal_ReadPowerValueFromPROM_8188E(struct txpowerinfo24g *pwrInfo24G,
+ 					pwrInfo24G->BW20_Diff[rfPath][TxCount] =	EEPROM_DEFAULT_DIFF;
+ 				} else {
+ 					pwrInfo24G->BW20_Diff[rfPath][TxCount] =	(PROMContent[eeAddr]&0x0f);
+-					if (pwrInfo24G->BW20_Diff[rfPath][TxCount] & BIT3)		/* 4bit sign number to 8 bit sign number */
++					if (pwrInfo24G->BW20_Diff[rfPath][TxCount] & BIT(3))		/* 4bit sign number to 8 bit sign number */
+ 						pwrInfo24G->BW20_Diff[rfPath][TxCount] |= 0xF0;
+ 				}
+ 				eeAddr++;
+@@ -407,7 +407,7 @@ static void Hal_ReadPowerValueFromPROM_8188E(struct txpowerinfo24g *pwrInfo24G,
+ 					pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
+ 				} else {
+ 					pwrInfo24G->OFDM_Diff[rfPath][TxCount] =	(PROMContent[eeAddr]&0xf0)>>4;
+-					if (pwrInfo24G->OFDM_Diff[rfPath][TxCount] & BIT3)		/* 4bit sign number to 8 bit sign number */
++					if (pwrInfo24G->OFDM_Diff[rfPath][TxCount] & BIT(3))		/* 4bit sign number to 8 bit sign number */
+ 						pwrInfo24G->OFDM_Diff[rfPath][TxCount] |= 0xF0;
+ 				}
+ 
+@@ -415,7 +415,7 @@ static void Hal_ReadPowerValueFromPROM_8188E(struct txpowerinfo24g *pwrInfo24G,
+ 					pwrInfo24G->CCK_Diff[rfPath][TxCount] =	EEPROM_DEFAULT_DIFF;
+ 				} else {
+ 					pwrInfo24G->CCK_Diff[rfPath][TxCount] =	(PROMContent[eeAddr]&0x0f);
+-					if (pwrInfo24G->CCK_Diff[rfPath][TxCount] & BIT3)		/* 4bit sign number to 8 bit sign number */
++					if (pwrInfo24G->CCK_Diff[rfPath][TxCount] & BIT(3))		/* 4bit sign number to 8 bit sign number */
+ 						pwrInfo24G->CCK_Diff[rfPath][TxCount] |= 0xF0;
+ 				}
+ 				eeAddr++;
+@@ -485,13 +485,13 @@ void Hal_ReadPowerSavingMode88E(struct adapter *padapter, u8 *hwinfo, bool AutoL
+ 		/* hw power down mode selection , 0:rf-off / 1:power down */
+ 
+ 		if (padapter->registrypriv.hwpdn_mode == 2)
+-			padapter->pwrctrlpriv.bHWPowerdown = (hwinfo[EEPROM_RF_FEATURE_OPTION_88E] & BIT4);
++			padapter->pwrctrlpriv.bHWPowerdown = (hwinfo[EEPROM_RF_FEATURE_OPTION_88E] & BIT(4));
+ 		else
+ 			padapter->pwrctrlpriv.bHWPowerdown = padapter->registrypriv.hwpdn_mode;
+ 
+ 		/*  decide hw if support remote wakeup function */
+ 		/*  if hw supported, 8051 (SIE) will generate WeakUP signal(D+/D- toggle) when autoresume */
+-		padapter->pwrctrlpriv.bSupportRemoteWakeup = (hwinfo[EEPROM_USB_OPTIONAL_FUNCTION0] & BIT1) ? true : false;
++		padapter->pwrctrlpriv.bSupportRemoteWakeup = (hwinfo[EEPROM_USB_OPTIONAL_FUNCTION0] & BIT(1)) ? true : false;
+ 
+ 		DBG_88E("%s...bHWPwrPindetect(%x)-bHWPowerdown(%x) , bSupportRemoteWakeup(%x)\n", __func__,
+ 		padapter->pwrctrlpriv.bHWPwrPindetect, padapter->pwrctrlpriv.bHWPowerdown , padapter->pwrctrlpriv.bSupportRemoteWakeup);
+diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c
+index 81d691ddd6c6..564cf53bff1b 100644
+--- a/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c
++++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c
+@@ -36,7 +36,7 @@ void SwLedOn(struct adapter *padapter, struct LED_871x *pLed)
+ 	if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
+ 		return;
+ 	LedCfg = usb_read8(padapter, REG_LEDCFG2);
+-	usb_write8(padapter, REG_LEDCFG2, (LedCfg&0xf0)|BIT5|BIT6); /*  SW control led0 on. */
++	usb_write8(padapter, REG_LEDCFG2, (LedCfg&0xf0) | BIT(5) | BIT(6)); /*  SW control led0 on. */
+ 	pLed->bLedOn = true;
+ }
+ 
+@@ -55,12 +55,12 @@ void SwLedOff(struct adapter *padapter, struct LED_871x *pLed)
+ 	if (pHalData->bLedOpenDrain) {
+ 			/*  Open-drain arrangement for controlling the LED) */
+ 		LedCfg &= 0x90; /*  Set to software control. */
+-		usb_write8(padapter, REG_LEDCFG2, (LedCfg|BIT3));
++		usb_write8(padapter, REG_LEDCFG2, (LedCfg | BIT(3)));
+ 		LedCfg = usb_read8(padapter, REG_MAC_PINMUX_CFG);
+ 		LedCfg &= 0xFE;
+ 		usb_write8(padapter, REG_MAC_PINMUX_CFG, LedCfg);
+ 	} else {
+-		usb_write8(padapter, REG_LEDCFG2, (LedCfg|BIT3|BIT5|BIT6));
++		usb_write8(padapter, REG_LEDCFG2, (LedCfg | BIT(3) | BIT(5) | BIT(6)));
+ 	}
+ exit:
+ 	pLed->bLedOn = false;
+diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c
+index 1ef878fd997b..7e72259f0e40 100644
+--- a/drivers/staging/rtl8188eu/hal/usb_halinit.c
++++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c
+@@ -607,7 +607,7 @@ static void _InitBeaconParameters(struct adapter *Adapter)
+ static void _BeaconFunctionEnable(struct adapter *Adapter,
+ 				  bool Enable, bool Linked)
+ {
+-	usb_write8(Adapter, REG_BCN_CTRL, (BIT4 | BIT3 | BIT1));
++	usb_write8(Adapter, REG_BCN_CTRL, (BIT(4) | BIT(3) | BIT(1)));
+ 
+ 	usb_write8(Adapter, REG_RD_CTRL+1, 0x6F);
+ }
+@@ -632,8 +632,8 @@ static void _InitAntenna_Selection(struct adapter *Adapter)
+ 		return;
+ 	DBG_88E("==>  %s ....\n", __func__);
+ 
+-	usb_write32(Adapter, REG_LEDCFG0, usb_read32(Adapter, REG_LEDCFG0)|BIT23);
+-	phy_set_bb_reg(Adapter, rFPGA0_XAB_RFParameter, BIT13, 0x01);
++	usb_write32(Adapter, REG_LEDCFG0, usb_read32(Adapter, REG_LEDCFG0) | BIT(23));
++	phy_set_bb_reg(Adapter, rFPGA0_XAB_RFParameter, BIT(13), 0x01);
+ 
+ 	if (phy_query_bb_reg(Adapter, rFPGA0_XA_RFInterfaceOE, 0x300) == Antenna_A)
+ 		haldata->CurAntenna = Antenna_A;
+@@ -664,13 +664,13 @@ enum rt_rf_power_state RfOnOffDetect(struct adapter *adapt)
+ 
+ 	if (adapt->pwrctrlpriv.bHWPowerdown) {
+ 		val8 = usb_read8(adapt, REG_HSISR);
+-		DBG_88E("pwrdown, 0x5c(BIT7)=%02x\n", val8);
+-		rfpowerstate = (val8 & BIT7) ? rf_off : rf_on;
++		DBG_88E("pwrdown, 0x5c(BIT(7))=%02x\n", val8);
++		rfpowerstate = (val8 & BIT(7)) ? rf_off : rf_on;
+ 	} else { /*  rf on/off */
+-		usb_write8(adapt, REG_MAC_PINMUX_CFG, usb_read8(adapt, REG_MAC_PINMUX_CFG)&~(BIT3));
++		usb_write8(adapt, REG_MAC_PINMUX_CFG, usb_read8(adapt, REG_MAC_PINMUX_CFG)&~(BIT(3)));
+ 		val8 = usb_read8(adapt, REG_GPIO_IO_SEL);
+ 		DBG_88E("GPIO_IN=%02x\n", val8);
+-		rfpowerstate = (val8 & BIT3) ? rf_on : rf_off;
++		rfpowerstate = (val8 & BIT(3)) ? rf_on : rf_off;
+ 	}
+ 	return rfpowerstate;
+ }	/*  HalDetectPwrDownMode */
+@@ -805,7 +805,7 @@ static u32 rtl8188eu_hal_init(struct adapter *Adapter)
+ 	/* Enable TX Report */
+ 	/* Enable Tx Report Timer */
+ 	value8 = usb_read8(Adapter, REG_TX_RPT_CTRL);
+-	usb_write8(Adapter,  REG_TX_RPT_CTRL, (value8|BIT1|BIT0));
++	usb_write8(Adapter,  REG_TX_RPT_CTRL, (value8 | BIT(1) | BIT(0)));
+ 	/* Set MAX RPT MACID */
+ 	usb_write8(Adapter,  REG_TX_RPT_CTRL+1, 2);/* FOR sta mode ,0: bc/mc ,1:AP */
+ 	/* Tx RPT Timer. Unit: 32us */
+@@ -898,7 +898,7 @@ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_LCK);
+ 	usb_write8(Adapter, REG_USB_HRPWM, 0);
+ 
+ 	/* ack for xmit mgmt frames. */
+-	usb_write32(Adapter, REG_FWHW_TXQ_CTRL, usb_read32(Adapter, REG_FWHW_TXQ_CTRL)|BIT(12));
++	usb_write32(Adapter, REG_FWHW_TXQ_CTRL, usb_read32(Adapter, REG_FWHW_TXQ_CTRL) | BIT(12));
+ 
+ exit:
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_END);
+@@ -918,7 +918,7 @@ static void CardDisableRTL8188EU(struct adapter *Adapter)
+ 
+ 	/* Stop Tx Report Timer. 0x4EC[Bit1]=b'0 */
+ 	val8 = usb_read8(Adapter, REG_TX_RPT_CTRL);
+-	usb_write8(Adapter, REG_TX_RPT_CTRL, val8&(~BIT1));
++	usb_write8(Adapter, REG_TX_RPT_CTRL, val8&(~BIT(1)));
+ 
+ 	/*  stop rx */
+ 	usb_write8(Adapter, REG_CR, 0x0);
+@@ -944,7 +944,7 @@ static void CardDisableRTL8188EU(struct adapter *Adapter)
+ 	/* YJ,add,111212 */
+ 	/* Disable 32k */
+ 	val8 = usb_read8(Adapter, REG_32K_CTRL);
+-	usb_write8(Adapter, REG_32K_CTRL, val8&(~BIT0));
++	usb_write8(Adapter, REG_32K_CTRL, val8&(~BIT(0)));
+ 
+ 	/*  Card disable power action flow */
+ 	rtl88eu_pwrseqcmdparsing(Adapter, PWR_CUT_ALL_MSK,
+@@ -953,9 +953,9 @@ static void CardDisableRTL8188EU(struct adapter *Adapter)
+ 
+ 	/*  Reset MCU IO Wrapper */
+ 	val8 = usb_read8(Adapter, REG_RSV_CTRL+1);
+-	usb_write8(Adapter, REG_RSV_CTRL+1, (val8&(~BIT3)));
++	usb_write8(Adapter, REG_RSV_CTRL+1, (val8&(~BIT(3))));
+ 	val8 = usb_read8(Adapter, REG_RSV_CTRL+1);
+-	usb_write8(Adapter, REG_RSV_CTRL+1, val8|BIT3);
++	usb_write8(Adapter, REG_RSV_CTRL+1, val8 | BIT(3));
+ 
+ 	/* YJ,test add, 111207. For Power Consumption. */
+ 	val8 = usb_read8(Adapter, GPIO_IN);
+@@ -1171,10 +1171,10 @@ static void ResumeTxBeacon(struct adapter *adapt)
+ 	/*  2010.03.01. Marked by tynli. No need to call workitem beacause we record the value */
+ 	/*  which should be read from register to a global variable. */
+ 
+-	usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl) | BIT6);
+-	haldata->RegFwHwTxQCtrl |= BIT6;
++	usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl) | BIT(6));
++	haldata->RegFwHwTxQCtrl |= BIT(6);
+ 	usb_write8(adapt, REG_TBTT_PROHIBIT+1, 0xff);
+-	haldata->RegReg542 |= BIT0;
++	haldata->RegReg542 |= BIT(0);
+ 	usb_write8(adapt, REG_TBTT_PROHIBIT+2, haldata->RegReg542);
+ }
+ 
+@@ -1185,10 +1185,10 @@ static void StopTxBeacon(struct adapter *adapt)
+ 	/*  2010.03.01. Marked by tynli. No need to call workitem beacause we record the value */
+ 	/*  which should be read from register to a global variable. */
+ 
+-	usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl) & (~BIT6));
+-	haldata->RegFwHwTxQCtrl &= (~BIT6);
++	usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl) & (~BIT(6)));
++	haldata->RegFwHwTxQCtrl &= (~BIT(6));
+ 	usb_write8(adapt, REG_TBTT_PROHIBIT+1, 0x64);
+-	haldata->RegReg542 &= ~(BIT0);
++	haldata->RegReg542 &= ~(BIT(0));
+ 	usb_write8(adapt, REG_TBTT_PROHIBIT+2, haldata->RegReg542);
+ 
+ 	 /* todo: CheckFwRsvdPageContent(Adapter);  2010.06.23. Added by tynli. */
+@@ -1200,7 +1200,7 @@ static void hw_var_set_opmode(struct adapter *Adapter, u8 variable, u8 *val)
+ 	u8 mode = *((u8 *)val);
+ 
+ 	/*  disable Port0 TSF update */
+-	usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)|BIT(4));
++	usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) | BIT(4));
+ 
+ 	/*  set net_type */
+ 	val8 = usb_read8(Adapter, MSR)&0x0c;
+@@ -1378,7 +1378,7 @@ static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val)
+ 			usb_write32(Adapter, REG_TSFTR+4, tsf>>32);
+ 
+ 			/* enable related TSF function */
+-			usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)|BIT(3));
++			usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) | BIT(3));
+ 
+ 			if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE))
+ 				ResumeTxBeacon(Adapter);
+@@ -1403,10 +1403,10 @@ static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val)
+ 		usb_write16(Adapter, REG_RXFLTMAP2, 0x00);
+ 
+ 		/* reset TSF */
+-		usb_write8(Adapter, REG_DUAL_TSF_RST, (BIT(0)|BIT(1)));
++		usb_write8(Adapter, REG_DUAL_TSF_RST, (BIT(0) | BIT(1)));
+ 
+ 		/* disable update TSF */
+-		usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)|BIT(4));
++		usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) | BIT(4));
+ 		break;
+ 	case HW_VAR_MLME_SITESURVEY:
+ 		if (*((u8 *)val)) { /* under sitesurvey */
+@@ -1418,7 +1418,7 @@ static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val)
+ 			usb_write16(Adapter, REG_RXFLTMAP2, 0x00);
+ 
+ 			/* disable update TSF */
+-			usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)|BIT(4));
++			usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) | BIT(4));
+ 		} else { /* sitesurvey done */
+ 			struct mlme_ext_priv	*pmlmeext = &Adapter->mlmeextpriv;
+ 			struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+@@ -1578,7 +1578,7 @@ static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val)
+ 		}
+ 		break;
+ 	case HW_VAR_CAM_INVALID_ALL:
+-		usb_write32(Adapter, RWCAM, BIT(31)|BIT(30));
++		usb_write32(Adapter, RWCAM, BIT(31) | BIT(30));
+ 		break;
+ 	case HW_VAR_CAM_WRITE:
+ 		{
+@@ -1795,7 +1795,7 @@ static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val)
+ 		break;
+ 	case HW_VAR_BCN_VALID:
+ 		/* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2, write 1 to clear, Clear by sw */
+-		usb_write8(Adapter, REG_TDECTRL+2, usb_read8(Adapter, REG_TDECTRL+2) | BIT0);
++		usb_write8(Adapter, REG_TDECTRL+2, usb_read8(Adapter, REG_TDECTRL+2) | BIT(0));
+ 		break;
+ 	default:
+ 		break;
+@@ -1815,7 +1815,7 @@ static void GetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val)
+ 		break;
+ 	case HW_VAR_BCN_VALID:
+ 		/* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2 */
+-		val[0] = (BIT0 & usb_read8(Adapter, REG_TDECTRL+2)) ? true : false;
++		val[0] = (BIT(0) & usb_read8(Adapter, REG_TDECTRL+2)) ? true : false;
+ 		break;
+ 	case HW_VAR_DM_FLAG:
+ 		val[0] = podmpriv->SupportAbility;
+@@ -2052,7 +2052,7 @@ static void SetBeaconRelatedRegisters8188EUsb(struct adapter *adapt)
+ 
+ 	ResumeTxBeacon(adapt);
+ 
+-	usb_write8(adapt, bcn_ctrl_reg, usb_read8(adapt, bcn_ctrl_reg)|BIT(1));
++	usb_write8(adapt, bcn_ctrl_reg, usb_read8(adapt, bcn_ctrl_reg) | BIT(1));
+ }
+ 
+ static void rtl8188eu_init_default_value(struct adapter *adapt)
+diff --git a/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h b/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h
+index 20e6b40fc35c..e058162fe2ba 100644
+--- a/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h
++++ b/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h
+@@ -87,13 +87,13 @@ enum rf_radio_path {
+ 
+ enum wireless_mode {
+ 	WIRELESS_MODE_UNKNOWN = 0x00,
+-	WIRELESS_MODE_A			= BIT2,
+-	WIRELESS_MODE_B			= BIT0,
+-	WIRELESS_MODE_G			= BIT1,
+-	WIRELESS_MODE_AUTO		= BIT5,
+-	WIRELESS_MODE_N_24G		= BIT3,
+-	WIRELESS_MODE_N_5G		= BIT4,
+-	WIRELESS_MODE_AC		= BIT6
++	WIRELESS_MODE_A			= BIT(2),
++	WIRELESS_MODE_B			= BIT(0),
++	WIRELESS_MODE_G			= BIT(1),
++	WIRELESS_MODE_AUTO		= BIT(5),
++	WIRELESS_MODE_N_24G		= BIT(3),
++	WIRELESS_MODE_N_5G		= BIT(4),
++	WIRELESS_MODE_AC		= BIT(6)
+ };
+ 
+ enum phy_rate_tx_offset_area {
+diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h
+index e73c6341248e..1b1c10292456 100644
+--- a/drivers/staging/rtl8188eu/include/hal_intf.h
++++ b/drivers/staging/rtl8188eu/include/hal_intf.h
+@@ -25,10 +25,10 @@
+ #include 
+ 
+ enum RTL871X_HCI_TYPE {
+-	RTW_PCIE	= BIT0,
+-	RTW_USB		= BIT1,
+-	RTW_SDIO	= BIT2,
+-	RTW_GSPI	= BIT3,
++	RTW_PCIE	= BIT(0),
++	RTW_USB		= BIT(1),
++	RTW_SDIO	= BIT(2),
++	RTW_GSPI	= BIT(3),
+ };
+ 
+ enum _CHIP_TYPE {
+@@ -226,10 +226,10 @@ enum rt_eeprom_type {
+ };
+ 
+ #define RF_CHANGE_BY_INIT	0
+-#define RF_CHANGE_BY_IPS	BIT28
+-#define RF_CHANGE_BY_PS		BIT29
+-#define RF_CHANGE_BY_HW		BIT30
+-#define RF_CHANGE_BY_SW		BIT31
++#define RF_CHANGE_BY_IPS	BIT(28)
++#define RF_CHANGE_BY_PS		BIT(29)
++#define RF_CHANGE_BY_HW		BIT(30)
++#define RF_CHANGE_BY_SW		BIT(31)
+ 
+ enum hardware_type {
+ 	HARDWARE_TYPE_RTL8188EU,
+diff --git a/drivers/staging/rtl8188eu/include/odm.h b/drivers/staging/rtl8188eu/include/odm.h
+index 73ef9c7596c1..bc970caf7eda 100644
+--- a/drivers/staging/rtl8188eu/include/odm.h
++++ b/drivers/staging/rtl8188eu/include/odm.h
+@@ -414,31 +414,31 @@ enum odm_common_info_def {
+ 
+ enum odm_ability_def {
+ 	/*  BB ODM section BIT 0-15 */
+-	ODM_BB_DIG			= BIT0,
+-	ODM_BB_RA_MASK			= BIT1,
+-	ODM_BB_DYNAMIC_TXPWR		= BIT2,
+-	ODM_BB_FA_CNT			= BIT3,
+-	ODM_BB_RSSI_MONITOR		= BIT4,
+-	ODM_BB_CCK_PD			= BIT5,
+-	ODM_BB_ANT_DIV			= BIT6,
+-	ODM_BB_PWR_SAVE			= BIT7,
+-	ODM_BB_PWR_TRA			= BIT8,
+-	ODM_BB_RATE_ADAPTIVE		= BIT9,
+-	ODM_BB_PATH_DIV			= BIT10,
+-	ODM_BB_PSD			= BIT11,
+-	ODM_BB_RXHP			= BIT12,
++	ODM_BB_DIG			= BIT(0),
++	ODM_BB_RA_MASK			= BIT(1),
++	ODM_BB_DYNAMIC_TXPWR		= BIT(2),
++	ODM_BB_FA_CNT			= BIT(3),
++	ODM_BB_RSSI_MONITOR		= BIT(4),
++	ODM_BB_CCK_PD			= BIT(5),
++	ODM_BB_ANT_DIV			= BIT(6),
++	ODM_BB_PWR_SAVE			= BIT(7),
++	ODM_BB_PWR_TRA			= BIT(8),
++	ODM_BB_RATE_ADAPTIVE		= BIT(9),
++	ODM_BB_PATH_DIV			= BIT(10),
++	ODM_BB_PSD			= BIT(11),
++	ODM_BB_RXHP			= BIT(12),
+ 
+ 	/*  MAC DM section BIT 16-23 */
+-	ODM_MAC_EDCA_TURBO		= BIT16,
+-	ODM_MAC_EARLY_MODE		= BIT17,
++	ODM_MAC_EDCA_TURBO		= BIT(16),
++	ODM_MAC_EARLY_MODE		= BIT(17),
+ 
+ 	/*  RF ODM section BIT 24-31 */
+-	ODM_RF_TX_PWR_TRACK		= BIT24,
+-	ODM_RF_RX_GAIN_TRACK		= BIT25,
+-	ODM_RF_CALIBRATION		= BIT26,
++	ODM_RF_TX_PWR_TRACK		= BIT(24),
++	ODM_RF_RX_GAIN_TRACK		= BIT(25),
++	ODM_RF_CALIBRATION		= BIT(26),
+ };
+ 
+-#define ODM_RTL8188E		BIT4
++#define ODM_RTL8188E		BIT(4)
+ 
+ /* ODM_CMNINFO_CUT_VER */
+ enum odm_cut_version {
+@@ -460,14 +460,14 @@ enum odm_fab_Version {
+ /*  ODM_CMNINFO_RF_TYPE */
+ /*  For example 1T2R (A+AB = BIT0|BIT4|BIT5) */
+ enum odm_rf_path {
+-	ODM_RF_TX_A	=	BIT0,
+-	ODM_RF_TX_B	=	BIT1,
+-	ODM_RF_TX_C	=	BIT2,
+-	ODM_RF_TX_D	=	BIT3,
+-	ODM_RF_RX_A	=	BIT4,
+-	ODM_RF_RX_B	=	BIT5,
+-	ODM_RF_RX_C	=	BIT6,
+-	ODM_RF_RX_D	=	BIT7,
++	ODM_RF_TX_A	=	BIT(0),
++	ODM_RF_TX_B	=	BIT(1),
++	ODM_RF_TX_C	=	BIT(2),
++	ODM_RF_TX_D	=	BIT(3),
++	ODM_RF_RX_A	=	BIT(4),
++	ODM_RF_RX_B	=	BIT(5),
++	ODM_RF_RX_C	=	BIT(6),
++	ODM_RF_RX_D	=	BIT(7),
+ };
+ 
+ enum odm_rf_type {
+@@ -498,33 +498,33 @@ enum odm_bt_coexist {
+ 
+ /*  ODM_CMNINFO_OP_MODE */
+ enum odm_operation_mode {
+-	ODM_NO_LINK		= BIT0,
+-	ODM_LINK		= BIT1,
+-	ODM_SCAN		= BIT2,
+-	ODM_POWERSAVE		= BIT3,
+-	ODM_AP_MODE		= BIT4,
+-	ODM_CLIENT_MODE		= BIT5,
+-	ODM_AD_HOC		= BIT6,
+-	ODM_WIFI_DIRECT		= BIT7,
+-	ODM_WIFI_DISPLAY	= BIT8,
++	ODM_NO_LINK		= BIT(0),
++	ODM_LINK		= BIT(1),
++	ODM_SCAN		= BIT(2),
++	ODM_POWERSAVE		= BIT(3),
++	ODM_AP_MODE		= BIT(4),
++	ODM_CLIENT_MODE		= BIT(5),
++	ODM_AD_HOC		= BIT(6),
++	ODM_WIFI_DIRECT		= BIT(7),
++	ODM_WIFI_DISPLAY	= BIT(8),
+ };
+ 
+ /*  ODM_CMNINFO_WM_MODE */
+ enum odm_wireless_mode {
+ 	ODM_WM_UNKNOW	= 0x0,
+-	ODM_WM_B	= BIT0,
+-	ODM_WM_G	= BIT1,
+-	ODM_WM_A	= BIT2,
+-	ODM_WM_N24G	= BIT3,
+-	ODM_WM_N5G	= BIT4,
+-	ODM_WM_AUTO	= BIT5,
+-	ODM_WM_AC	= BIT6,
++	ODM_WM_B	= BIT(0),
++	ODM_WM_G	= BIT(1),
++	ODM_WM_A	= BIT(2),
++	ODM_WM_N24G	= BIT(3),
++	ODM_WM_N5G	= BIT(4),
++	ODM_WM_AUTO	= BIT(5),
++	ODM_WM_AC	= BIT(6),
+ };
+ 
+ /*  ODM_CMNINFO_BAND */
+ enum odm_band_type {
+-	ODM_BAND_2_4G	= BIT0,
+-	ODM_BAND_5G	= BIT1,
++	ODM_BAND_2_4G	= BIT(0),
++	ODM_BAND_5G	= BIT(1),
+ };
+ 
+ /*  ODM_CMNINFO_SEC_CHNL_OFFSET */
+diff --git a/drivers/staging/rtl8188eu/include/odm_debug.h b/drivers/staging/rtl8188eu/include/odm_debug.h
+index 914f831a5b77..e9390963d6ff 100644
+--- a/drivers/staging/rtl8188eu/include/odm_debug.h
++++ b/drivers/staging/rtl8188eu/include/odm_debug.h
+@@ -57,30 +57,30 @@
+ 
+ /*  Define the tracing components */
+ /* BB Functions */
+-#define ODM_COMP_DIG					BIT0
+-#define ODM_COMP_RA_MASK				BIT1
+-#define ODM_COMP_DYNAMIC_TXPWR				BIT2
+-#define ODM_COMP_FA_CNT					BIT3
+-#define ODM_COMP_RSSI_MONITOR				BIT4
+-#define ODM_COMP_CCK_PD					BIT5
+-#define ODM_COMP_ANT_DIV				BIT6
+-#define ODM_COMP_PWR_SAVE				BIT7
+-#define ODM_COMP_PWR_TRA				BIT8
+-#define ODM_COMP_RATE_ADAPTIVE				BIT9
+-#define ODM_COMP_PATH_DIV				BIT10
+-#define ODM_COMP_PSD					BIT11
+-#define ODM_COMP_DYNAMIC_PRICCA				BIT12
+-#define ODM_COMP_RXHP					BIT13
++#define ODM_COMP_DIG					BIT(0)
++#define ODM_COMP_RA_MASK				BIT(1)
++#define ODM_COMP_DYNAMIC_TXPWR				BIT(2)
++#define ODM_COMP_FA_CNT					BIT(3)
++#define ODM_COMP_RSSI_MONITOR				BIT(4)
++#define ODM_COMP_CCK_PD					BIT(5)
++#define ODM_COMP_ANT_DIV				BIT(6)
++#define ODM_COMP_PWR_SAVE				BIT(7)
++#define ODM_COMP_PWR_TRA				BIT(8)
++#define ODM_COMP_RATE_ADAPTIVE				BIT(9)
++#define ODM_COMP_PATH_DIV				BIT(10)
++#define ODM_COMP_PSD					BIT(11)
++#define ODM_COMP_DYNAMIC_PRICCA				BIT(12)
++#define ODM_COMP_RXHP					BIT(13)
+ /* MAC Functions */
+-#define ODM_COMP_EDCA_TURBO				BIT16
+-#define ODM_COMP_EARLY_MODE				BIT17
++#define ODM_COMP_EDCA_TURBO				BIT(16)
++#define ODM_COMP_EARLY_MODE				BIT(17)
+ /* RF Functions */
+-#define ODM_COMP_TX_PWR_TRACK				BIT24
+-#define ODM_COMP_RX_GAIN_TRACK				BIT25
+-#define ODM_COMP_CALIBRATION				BIT26
++#define ODM_COMP_TX_PWR_TRACK				BIT(24)
++#define ODM_COMP_RX_GAIN_TRACK				BIT(25)
++#define ODM_COMP_CALIBRATION				BIT(26)
+ /* Common Functions */
+-#define ODM_COMP_COMMON					BIT30
+-#define ODM_COMP_INIT					BIT31
++#define ODM_COMP_COMMON					BIT(30)
++#define ODM_COMP_INIT					BIT(31)
+ 
+ /*------------------------Export Marco Definition---------------------------*/
+ #define RT_PRINTK(fmt, args...)				\
+diff --git a/drivers/staging/rtl8188eu/include/odm_reg.h b/drivers/staging/rtl8188eu/include/odm_reg.h
+index 89bc46bc71b0..7f10b695cf9d 100644
+--- a/drivers/staging/rtl8188eu/include/odm_reg.h
++++ b/drivers/staging/rtl8188eu/include/odm_reg.h
+@@ -112,7 +112,7 @@
+ /*  Bitmap Definition */
+ /*  */
+ 
+-#define	BIT_FA_RESET					BIT0
++#define	BIT_FA_RESET					BIT(0)
+ 
+ 
+ 
+diff --git a/drivers/staging/rtl8188eu/include/osdep_service.h b/drivers/staging/rtl8188eu/include/osdep_service.h
+index 96505a6dbe2c..e24fe8cc3d0b 100644
+--- a/drivers/staging/rtl8188eu/include/osdep_service.h
++++ b/drivers/staging/rtl8188eu/include/osdep_service.h
+@@ -75,45 +75,6 @@ static inline int rtw_netif_queue_stopped(struct net_device *pnetdev)
+ 		netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 3));
+ }
+ 
+-
+-#define BIT0	0x00000001
+-#define BIT1	0x00000002
+-#define BIT2	0x00000004
+-#define BIT3	0x00000008
+-#define BIT4	0x00000010
+-#define BIT5	0x00000020
+-#define BIT6	0x00000040
+-#define BIT7	0x00000080
+-#define BIT8	0x00000100
+-#define BIT9	0x00000200
+-#define BIT10	0x00000400
+-#define BIT11	0x00000800
+-#define BIT12	0x00001000
+-#define BIT13	0x00002000
+-#define BIT14	0x00004000
+-#define BIT15	0x00008000
+-#define BIT16	0x00010000
+-#define BIT17	0x00020000
+-#define BIT18	0x00040000
+-#define BIT19	0x00080000
+-#define BIT20	0x00100000
+-#define BIT21	0x00200000
+-#define BIT22	0x00400000
+-#define BIT23	0x00800000
+-#define BIT24	0x01000000
+-#define BIT25	0x02000000
+-#define BIT26	0x04000000
+-#define BIT27	0x08000000
+-#define BIT28	0x10000000
+-#define BIT29	0x20000000
+-#define BIT30	0x40000000
+-#define BIT31	0x80000000
+-#define BIT32	0x0100000000
+-#define BIT33	0x0200000000
+-#define BIT34	0x0400000000
+-#define BIT35	0x0800000000
+-#define BIT36	0x1000000000
+-
+ int RTW_STATUS_CODE(int error_code);
+ 
+ #define rtw_update_mem_stat(flag, sz) do {} while (0)
+diff --git a/drivers/staging/rtl8188eu/include/pwrseq.h b/drivers/staging/rtl8188eu/include/pwrseq.h
+index 43db92dcb8b3..8c876c6c7a4f 100644
+--- a/drivers/staging/rtl8188eu/include/pwrseq.h
++++ b/drivers/staging/rtl8188eu/include/pwrseq.h
+@@ -65,31 +65,31 @@
+ 	 * comment here
+ 	 */								\
+ 	{0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT1, BIT1},			\
++	PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), BIT(1)},		\
+ 	/* wait till 0x04[17] = 1    power ready*/	\
+ 	{0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0|BIT1, 0},			\
++	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0) | BIT(1), 0},		\
+ 	/* 0x02[1:0] = 0	reset BB*/				\
+ 	{0x0026, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, BIT7},			\
++	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)},		\
+ 	/*0x24[23] = 2b'01 schmit trigger */				\
+ 	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, 0},			\
++	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0},			\
+ 	/* 0x04[15] = 0 disable HWPDN (control by DRV)*/		\
+ 	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4|BIT3, 0},			\
++	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4) | BIT(3), 0},		\
+ 	/*0x04[12:11] = 2b'00 disable WL suspend*/			\
+ 	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, BIT0},			\
++	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)},		\
+ 	/*0x04[8] = 1 polling until return 0*/				\
+ 	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT0, 0},			\
++	PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(0), 0},			\
+ 	/*wait till 0x04[8] = 0*/					\
+ 	{0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, 0},			\
++	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0},			\
+ 	/*LDO normal mode*/						\
+ 	{0x0074, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, BIT4},			\
++	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)},		\
+ 	/*SDIO Driving*/
+ 
+ #define RTL8188E_TRANS_ACT_TO_CARDEMU					\
+@@ -102,13 +102,13 @@
+ 	PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0},			\
+ 	/*0x1F[7:0] = 0 turn off RF*/					\
+ 	{0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, BIT4},			\
++	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)},		\
+ 	/*LDO Sleep mode*/						\
+ 	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, BIT1},			\
++	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)},		\
+ 	/*0x04[9] = 1 turn off MAC by HW state machine*/		\
+ 	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT1, 0},			\
++	PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), 0},			\
+ 	/*wait till 0x04[9] = 0 polling until return 0 to disable*/
+ 
+ #define RTL8188E_TRANS_CARDEMU_TO_SUS					\
+@@ -119,28 +119,28 @@
+ 	 */								\
+ 	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,			\
+ 	PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC,		\
+-	PWR_CMD_WRITE, BIT3|BIT4, BIT3},				\
++	PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3)},			\
+ 	/* 0x04[12:11] = 2b'01enable WL suspend */			\
+ 	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3|BIT4, BIT3|BIT4},		\
++	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3) | BIT(4)}, \
+ 	/* 0x04[12:11] = 2b'11enable WL suspend for PCIe */		\
+ 	{0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,			\
+ 	PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC,		\
+-	PWR_CMD_WRITE, 0xFF, BIT7},					\
++	PWR_CMD_WRITE, 0xFF, BIT(7)},					\
+ 	/* 0x04[31:30] = 2b'10 enable enable bandgap mbias in suspend */\
+ 	{0x0041, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,			\
+ 	PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC,		\
+-	PWR_CMD_WRITE, BIT4, 0},					\
++	PWR_CMD_WRITE, BIT(4), 0},					\
+ 	/*Clear SIC_EN register 0x40[12] = 1'b0 */			\
+ 	{0xfe10, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,			\
+ 	PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC,		\
+-	PWR_CMD_WRITE, BIT4, BIT4},					\
++	PWR_CMD_WRITE, BIT(4), BIT(4)},					\
+ 	/*Set USB suspend enable local register  0xfe10[4]=1 */		\
+ 	{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+-	PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT0, BIT0},			\
++	PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0)},		\
+ 	/*Set SDIO suspend local register*/				\
+ 	{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+-	PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT1, 0},			\
++	PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), 0},			\
+ 	/*wait power state to suspend*/
+ 
+ #define RTL8188E_TRANS_SUS_TO_CARDEMU					\
+@@ -150,13 +150,13 @@
+ 	 * comments here
+ 	 */								\
+ 	{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+-	PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT0, 0},			\
++	PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0},			\
+ 	/*Set SDIO suspend local register*/				\
+ 	{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+-	PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT1, BIT1},		\
++	PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1)},		\
+ 	/*wait power state to suspend*/					\
+ 	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3|BIT4, 0},			\
++	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3) | BIT(4), 0},		\
+ 	/*0x04[12:11] = 2b'01enable WL suspend*/
+ 
+ #define RTL8188E_TRANS_CARDEMU_TO_CARDDIS				\
+@@ -166,11 +166,11 @@
+ 	 * comments here
+ 	 */								\
+ 	{0x0026, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, BIT7},			\
++	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)},		\
+ 	/*0x24[23] = 2b'01 schmit trigger */				\
+ 	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,			\
+ 	PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC,		\
+-	PWR_CMD_WRITE, BIT3|BIT4, BIT3},				\
++	PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3)},			\
+ 	/*0x04[12:11] = 2b'01 enable WL suspend*/			\
+ 	{0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,			\
+ 	PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC,		\
+@@ -178,16 +178,16 @@
+ 	/* 0x04[31:30] = 2b'10 enable enable bandgap mbias in suspend */\
+ 	{0x0041, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,			\
+ 	PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC,		\
+-	PWR_CMD_WRITE, BIT4, 0},					\
++	PWR_CMD_WRITE, BIT(4), 0},					\
+ 	/*Clear SIC_EN register 0x40[12] = 1'b0 */			\
+ 	{0xfe10, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, BIT4},			\
++	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)},		\
+ 	/*Set USB suspend enable local register  0xfe10[4]=1 */		\
+ 	{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+-	PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT0, BIT0},			\
++	PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0)},		\
+ 	/*Set SDIO suspend local register*/				\
+ 	{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+-	PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT1, 0},			\
++	PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), 0},			\
+ 	/*wait power state to suspend*/
+ 
+ #define RTL8188E_TRANS_CARDDIS_TO_CARDEMU				\
+@@ -197,13 +197,13 @@
+ 	 * comments here
+ 	 */								\
+ 	{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+-	PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT0, 0},			\
++	PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0},			\
+ 	/*Set SDIO suspend local register*/				\
+ 	{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+-	PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT1, BIT1},		\
++	PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1)},		\
+ 	/*wait power state to suspend*/					\
+ 	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3|BIT4, 0},			\
++	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3) | BIT(4), 0},		\
+ 	/*0x04[12:11] = 2b'01enable WL suspend*/
+ 
+ #define RTL8188E_TRANS_CARDEMU_TO_PDN					\
+@@ -213,10 +213,10 @@
+ 	 * comments here
+ 	 */								\
+ 	{0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, 0},			\
++	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0},			\
+ 	/* 0x04[16] = 0*/						\
+ 	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, BIT7},			\
++	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)},		\
+ 	/* 0x04[15] = 1*/
+ 
+ #define RTL8188E_TRANS_PDN_TO_CARDEMU					\
+@@ -226,7 +226,7 @@
+ 	 * comments here
+ 	 */								\
+ 	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, 0},			\
++	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0},			\
+ 	/* 0x04[15] = 0*/
+ 
+ /* This is used by driver for LPSRadioOff Procedure, not for FW LPS Step */
+@@ -251,7 +251,7 @@
+ 	PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},			\
+ 	/*Should be zero if no packet is transmitting*/			\
+ 	{0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, 0},			\
++	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0},			\
+ 	/*CCK and OFDM are disabled,and clock are gated*/		\
+ 	{0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+ 	PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0,				\
+@@ -259,9 +259,9 @@
+ 	{0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+ 	PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x3F},/*Reset MAC TRX*/	\
+ 	{0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, 0},/*check if removed later*/\
++	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0},/*check if removed later*/\
+ 	{0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT5, BIT5},			\
++	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), BIT(5)},		\
+ 	/*Respond TxOK to scheduler*/
+ 
+ 
+@@ -280,22 +280,22 @@
+ 	{0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+ 	PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS}, /*Delay*/	\
+ 	{0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, 0},			\
++	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0},			\
+ 	/* 0x08[4] = 0 switch TSF to 40M */				\
+ 	{0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT7, 0},			\
++	PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(7), 0},			\
+ 	/* Polling 0x109[7]=0  TSF in 40M */				\
+ 	{0x0029, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT6|BIT7, 0},			\
++	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(6) | BIT(7), 0},		\
+ 	/* 0x29[7:6] = 2b'00  enable BB clock */			\
+ 	{0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, BIT1},			\
++	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)},		\
+ 	/* 0x101[1] = 1 */						\
+ 	{0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+ 	PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF},			\
+ 	/* 0x100[7:0] = 0xFF enable WMAC TRX */				\
+ 	{0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+-	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1|BIT0, BIT1|BIT0},		\
++	PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1) | BIT(0), BIT(1) | BIT(0)}, \
+ 	/* 0x02[1:0] = 2b'11 enable BB macro */				\
+ 	{0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+ 	PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0}, /*.	0x522 = 0*/
+diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_spec.h b/drivers/staging/rtl8188eu/include/rtl8188e_spec.h
+index e99179a794af..beeee4a6b0bc 100644
+--- a/drivers/staging/rtl8188eu/include/rtl8188e_spec.h
++++ b/drivers/staging/rtl8188eu/include/rtl8188e_spec.h
+@@ -19,39 +19,6 @@
+ #ifndef __RTL8188E_SPEC_H__
+ #define __RTL8188E_SPEC_H__
+ 
+-#define BIT0	0x00000001
+-#define BIT1	0x00000002
+-#define BIT2	0x00000004
+-#define BIT3	0x00000008
+-#define BIT4	0x00000010
+-#define BIT5	0x00000020
+-#define BIT6	0x00000040
+-#define BIT7	0x00000080
+-#define BIT8	0x00000100
+-#define BIT9	0x00000200
+-#define BIT10	0x00000400
+-#define BIT11	0x00000800
+-#define BIT12	0x00001000
+-#define BIT13	0x00002000
+-#define BIT14	0x00004000
+-#define BIT15	0x00008000
+-#define BIT16	0x00010000
+-#define BIT17	0x00020000
+-#define BIT18	0x00040000
+-#define BIT19	0x00080000
+-#define BIT20	0x00100000
+-#define BIT21	0x00200000
+-#define BIT22	0x00400000
+-#define BIT23	0x00800000
+-#define BIT24	0x01000000
+-#define BIT25	0x02000000
+-#define BIT26	0x04000000
+-#define BIT27	0x08000000
+-#define BIT28	0x10000000
+-#define BIT29	0x20000000
+-#define BIT30	0x40000000
+-#define BIT31	0x80000000
+-
+ /*        8192C Regsiter offset definition */
+ 
+ #define		HAL_PS_TIMER_INT_DELAY	50	/*   50 microseconds */
+@@ -477,14 +444,14 @@
+ #define	MAX_MSS_DENSITY_1T		0x0A
+ 
+ /*  EEPROM enable when set 1 */
+-#define	CmdEEPROM_En			BIT5
++#define	CmdEEPROM_En			BIT(5)
+ /*  System EEPROM select, 0: boot from E-FUSE, 1: The EEPROM used is 9346 */
+-#define	CmdEERPOMSEL			BIT4
+-#define	Cmd9346CR_9356SEL		BIT4
++#define	CmdEERPOMSEL			BIT(4)
++#define	Cmd9346CR_9356SEL		BIT(4)
+ 
+ /*        8192C GPIO MUX Configuration Register (offset 0x40, 4 byte) */
+ #define	GPIOSEL_GPIO			0
+-#define	GPIOSEL_ENBT			BIT5
++#define	GPIOSEL_ENBT			BIT(5)
+ 
+ /*        8192C GPIO PIN Control Register (offset 0x44, 4 byte) */
+ /*  GPIO pins input value */
+@@ -497,18 +464,18 @@
+ #define	GPIO_MOD			(REG_GPIO_PIN_CTRL+3)
+ 
+ /* 8723/8188E Host System Interrupt Mask Register (offset 0x58, 32 byte) */
+-#define	HSIMR_GPIO12_0_INT_EN		BIT0
+-#define	HSIMR_SPS_OCP_INT_EN		BIT5
+-#define	HSIMR_RON_INT_EN		BIT6
+-#define	HSIMR_PDN_INT_EN		BIT7
+-#define	HSIMR_GPIO9_INT_EN		BIT25
++#define	HSIMR_GPIO12_0_INT_EN		BIT(0)
++#define	HSIMR_SPS_OCP_INT_EN		BIT(5)
++#define	HSIMR_RON_INT_EN		BIT(6)
++#define	HSIMR_PDN_INT_EN		BIT(7)
++#define	HSIMR_GPIO9_INT_EN		BIT(25)
+ 
+ /* 8723/8188E Host System Interrupt Status Register (offset 0x5C, 32 byte) */
+-#define	HSISR_GPIO12_0_INT		BIT0
+-#define	HSISR_SPS_OCP_INT		BIT5
+-#define	HSISR_RON_INT_EN		BIT6
+-#define	HSISR_PDNINT			BIT7
+-#define	HSISR_GPIO9_INT			BIT25
++#define	HSISR_GPIO12_0_INT		BIT(0)
++#define	HSISR_SPS_OCP_INT		BIT(5)
++#define	HSISR_RON_INT_EN		BIT(6)
++#define	HSISR_PDNINT			BIT(7)
++#define	HSISR_GPIO9_INT			BIT(25)
+ 
+ /*   8192C (MSR) Media Status Register	(Offset 0x4C, 8 bits) */
+ /*
+@@ -533,51 +500,51 @@ Default: 00b.
+ 
+ /*  88E Driver Initialization Offload REG_FDHM0(Offset 0x88, 8 bits) */
+ /* IOL config for REG_FDHM0(Reg0x88) */
+-#define CMD_INIT_LLT			BIT0
+-#define CMD_READ_EFUSE_MAP		BIT1
+-#define CMD_EFUSE_PATCH			BIT2
+-#define CMD_IOCONFIG			BIT3
+-#define CMD_INIT_LLT_ERR		BIT4
+-#define CMD_READ_EFUSE_MAP_ERR		BIT5
+-#define CMD_EFUSE_PATCH_ERR		BIT6
+-#define CMD_IOCONFIG_ERR		BIT7
++#define CMD_INIT_LLT			BIT(0)
++#define CMD_READ_EFUSE_MAP		BIT(1)
++#define CMD_EFUSE_PATCH			BIT(2)
++#define CMD_IOCONFIG			BIT(3)
++#define CMD_INIT_LLT_ERR		BIT(4)
++#define CMD_READ_EFUSE_MAP_ERR		BIT(5)
++#define CMD_EFUSE_PATCH_ERR		BIT(6)
++#define CMD_IOCONFIG_ERR		BIT(7)
+ 
+ /*  6. Adaptive Control Registers  (Offset: 0x0160 - 0x01CF) */
+ /*  8192C Response Rate Set Register	(offset 0x181, 24bits) */
+-#define	RRSR_1M				BIT0
+-#define	RRSR_2M				BIT1
+-#define	RRSR_5_5M			BIT2
+-#define	RRSR_11M			BIT3
+-#define	RRSR_6M				BIT4
+-#define	RRSR_9M				BIT5
+-#define	RRSR_12M			BIT6
+-#define	RRSR_18M			BIT7
+-#define	RRSR_24M			BIT8
+-#define	RRSR_36M			BIT9
+-#define	RRSR_48M			BIT10
+-#define	RRSR_54M			BIT11
+-#define	RRSR_MCS0			BIT12
+-#define	RRSR_MCS1			BIT13
+-#define	RRSR_MCS2			BIT14
+-#define	RRSR_MCS3			BIT15
+-#define	RRSR_MCS4			BIT16
+-#define	RRSR_MCS5			BIT17
+-#define	RRSR_MCS6			BIT18
+-#define	RRSR_MCS7			BIT19
++#define	RRSR_1M				BIT(0)
++#define	RRSR_2M				BIT(1)
++#define	RRSR_5_5M			BIT(2)
++#define	RRSR_11M			BIT(3)
++#define	RRSR_6M				BIT(4)
++#define	RRSR_9M				BIT(5)
++#define	RRSR_12M			BIT(6)
++#define	RRSR_18M			BIT(7)
++#define	RRSR_24M			BIT(8)
++#define	RRSR_36M			BIT(9)
++#define	RRSR_48M			BIT(10)
++#define	RRSR_54M			BIT(11)
++#define	RRSR_MCS0			BIT(12)
++#define	RRSR_MCS1			BIT(13)
++#define	RRSR_MCS2			BIT(14)
++#define	RRSR_MCS3			BIT(15)
++#define	RRSR_MCS4			BIT(16)
++#define	RRSR_MCS5			BIT(17)
++#define	RRSR_MCS6			BIT(18)
++#define	RRSR_MCS7			BIT(19)
+ 
+ /*  8192C Response Rate Set Register	(offset 0x1BF, 8bits) */
+ /*  WOL bit information */
+-#define	HAL92C_WOL_PTK_UPDATE_EVENT	BIT0
+-#define	HAL92C_WOL_GTK_UPDATE_EVENT	BIT1
++#define	HAL92C_WOL_PTK_UPDATE_EVENT	BIT(0)
++#define	HAL92C_WOL_GTK_UPDATE_EVENT	BIT(1)
+ 
+ /*        8192C BW_OPMODE bits		(Offset 0x203, 8bit) */
+-#define	BW_OPMODE_20MHZ			BIT2
+-#define	BW_OPMODE_5G			BIT1
++#define	BW_OPMODE_20MHZ			BIT(2)
++#define	BW_OPMODE_5G			BIT(1)
+ 
+ /*        8192C CAM Config Setting (offset 0x250, 1 byte) */
+-#define	CAM_VALID			BIT15
++#define	CAM_VALID			BIT(15)
+ #define	CAM_NOTVALID			0x0000
+-#define	CAM_USEDK			BIT5
++#define	CAM_USEDK			BIT(5)
+ 
+ #define	CAM_CONTENT_COUNT		8
+ 
+@@ -594,69 +561,69 @@ Default: 00b.
+ #define	CAM_CONFIG_USEDK		true
+ #define	CAM_CONFIG_NO_USEDK		false
+ 
+-#define	CAM_WRITE			BIT16
++#define	CAM_WRITE			BIT(16)
+ #define	CAM_READ			0x00000000
+-#define	CAM_POLLINIG			BIT31
++#define	CAM_POLLINIG			BIT(31)
+ 
+ #define	SCR_UseDK			0x01
+ #define	SCR_TxSecEnable			0x02
+ #define	SCR_RxSecEnable			0x04
+ 
+ /*  10. Power Save Control Registers	 (Offset: 0x0260 - 0x02DF) */
+-#define	WOW_PMEN			BIT0 /*  Power management Enable. */
+-#define	WOW_WOMEN			BIT1 /*  WoW function on or off. */
+-#define	WOW_MAGIC			BIT2 /*  Magic packet */
+-#define	WOW_UWF				BIT3 /*  Unicast Wakeup frame. */
++#define	WOW_PMEN			BIT(0) /*  Power management Enable. */
++#define	WOW_WOMEN			BIT(1) /*  WoW function on or off. */
++#define	WOW_MAGIC			BIT(2) /*  Magic packet */
++#define	WOW_UWF				BIT(3) /*  Unicast Wakeup frame. */
+ 
+ /*  12. Host Interrupt Status Registers	 (Offset: 0x0300 - 0x030F) */
+ /*        8188 IMR/ISR bits */
+ #define	IMR_DISABLED_88E		0x0
+ /*  IMR DW0(0x0060-0063) Bit 0-31 */
+-#define	IMR_TXCCK_88E			BIT30	/*  TXRPT interrupt when CCX bit of the packet is set */
+-#define	IMR_PSTIMEOUT_88E		BIT29	/*  Power Save Time Out Interrupt */
+-#define	IMR_GTINT4_88E			BIT28	/*  When GTIMER4 expires, this bit is set to 1 */
+-#define	IMR_GTINT3_88E			BIT27	/*  When GTIMER3 expires, this bit is set to 1 */
+-#define	IMR_TBDER_88E			BIT26	/*  Transmit Beacon0 Error */
+-#define	IMR_TBDOK_88E			BIT25	/*  Transmit Beacon0 OK */
+-#define	IMR_TSF_BIT32_TOGGLE_88E	BIT24	/*  TSF Timer BIT32 toggle indication interrupt */
+-#define	IMR_BCNDMAINT0_88E		BIT20	/*  Beacon DMA Interrupt 0 */
+-#define	IMR_BCNDERR0_88E		BIT16	/*  Beacon Queue DMA Error 0 */
+-#define	IMR_HSISR_IND_ON_INT_88E	BIT15	/*  HSISR Indicator (HSIMR & HSISR is true, this bit is set to 1) */
+-#define	IMR_BCNDMAINT_E_88E		BIT14	/*  Beacon DMA Interrupt Extension for Win7 */
+-#define	IMR_ATIMEND_88E			BIT12	/*  CTWidnow End or ATIM Window End */
+-#define	IMR_HISR1_IND_INT_88E		BIT11	/*  HISR1 Indicator (HISR1 & HIMR1 is true, this bit is set to 1) */
+-#define	IMR_C2HCMD_88E			BIT10	/*  CPU to Host Command INT Status, Write 1 clear */
+-#define	IMR_CPWM2_88E			BIT9	/*  CPU power Mode exchange INT Status, Write 1 clear */
+-#define	IMR_CPWM_88E			BIT8	/*  CPU power Mode exchange INT Status, Write 1 clear */
+-#define	IMR_HIGHDOK_88E			BIT7	/*  High Queue DMA OK */
+-#define	IMR_MGNTDOK_88E			BIT6	/*  Management Queue DMA OK */
+-#define	IMR_BKDOK_88E			BIT5	/*  AC_BK DMA OK */
+-#define	IMR_BEDOK_88E			BIT4	/*  AC_BE DMA OK */
+-#define	IMR_VIDOK_88E			BIT3	/*  AC_VI DMA OK */
+-#define	IMR_VODOK_88E			BIT2	/*  AC_VO DMA OK */
+-#define	IMR_RDU_88E			BIT1	/*  Rx Descriptor Unavailable */
+-#define	IMR_ROK_88E			BIT0	/*  Receive DMA OK */
++#define	IMR_TXCCK_88E			BIT(30)	/*  TXRPT interrupt when CCX bit of the packet is set */
++#define	IMR_PSTIMEOUT_88E		BIT(29)	/*  Power Save Time Out Interrupt */
++#define	IMR_GTINT4_88E			BIT(28)	/*  When GTIMER4 expires, this bit is set to 1 */
++#define	IMR_GTINT3_88E			BIT(27)	/*  When GTIMER3 expires, this bit is set to 1 */
++#define	IMR_TBDER_88E			BIT(26)	/*  Transmit Beacon0 Error */
++#define	IMR_TBDOK_88E			BIT(25)	/*  Transmit Beacon0 OK */
++#define	IMR_TSF_BIT32_TOGGLE_88E	BIT(24)	/*  TSF Timer BIT32 toggle indication interrupt */
++#define	IMR_BCNDMAINT0_88E		BIT(20)	/*  Beacon DMA Interrupt 0 */
++#define	IMR_BCNDERR0_88E		BIT(16)	/*  Beacon Queue DMA Error 0 */
++#define	IMR_HSISR_IND_ON_INT_88E	BIT(15)	/*  HSISR Indicator (HSIMR & HSISR is true, this bit is set to 1) */
++#define	IMR_BCNDMAINT_E_88E		BIT(14)	/*  Beacon DMA Interrupt Extension for Win7 */
++#define	IMR_ATIMEND_88E			BIT(12)	/*  CTWidnow End or ATIM Window End */
++#define	IMR_HISR1_IND_INT_88E		BIT(11)	/*  HISR1 Indicator (HISR1 & HIMR1 is true, this bit is set to 1) */
++#define	IMR_C2HCMD_88E			BIT(10)	/*  CPU to Host Command INT Status, Write 1 clear */
++#define	IMR_CPWM2_88E			BIT(9)	/*  CPU power Mode exchange INT Status, Write 1 clear */
++#define	IMR_CPWM_88E			BIT(8)	/*  CPU power Mode exchange INT Status, Write 1 clear */
++#define	IMR_HIGHDOK_88E			BIT(7)	/*  High Queue DMA OK */
++#define	IMR_MGNTDOK_88E			BIT(6)	/*  Management Queue DMA OK */
++#define	IMR_BKDOK_88E			BIT(5)	/*  AC_BK DMA OK */
++#define	IMR_BEDOK_88E			BIT(4)	/*  AC_BE DMA OK */
++#define	IMR_VIDOK_88E			BIT(3)	/*  AC_VI DMA OK */
++#define	IMR_VODOK_88E			BIT(2)	/*  AC_VO DMA OK */
++#define	IMR_RDU_88E			BIT(1)	/*  Rx Descriptor Unavailable */
++#define	IMR_ROK_88E			BIT(0)	/*  Receive DMA OK */
+ 
+ /*  IMR DW1(0x00B4-00B7) Bit 0-31 */
+-#define	IMR_BCNDMAINT7_88E		BIT27	/*  Beacon DMA Interrupt 7 */
+-#define	IMR_BCNDMAINT6_88E		BIT26	/*  Beacon DMA Interrupt 6 */
+-#define	IMR_BCNDMAINT5_88E		BIT25	/*  Beacon DMA Interrupt 5 */
+-#define	IMR_BCNDMAINT4_88E		BIT24	/*  Beacon DMA Interrupt 4 */
+-#define	IMR_BCNDMAINT3_88E		BIT23	/*  Beacon DMA Interrupt 3 */
+-#define	IMR_BCNDMAINT2_88E		BIT22	/*  Beacon DMA Interrupt 2 */
+-#define	IMR_BCNDMAINT1_88E		BIT21	/*  Beacon DMA Interrupt 1 */
+-#define	IMR_BCNDERR7_88E		BIT20	/*  Beacon DMA Error Int 7 */
+-#define	IMR_BCNDERR6_88E		BIT19	/*  Beacon DMA Error Int 6 */
+-#define	IMR_BCNDERR5_88E		BIT18	/*  Beacon DMA Error Int 5 */
+-#define	IMR_BCNDERR4_88E		BIT17	/*  Beacon DMA Error Int 4 */
+-#define	IMR_BCNDERR3_88E		BIT16	/*  Beacon DMA Error Int 3 */
+-#define	IMR_BCNDERR2_88E		BIT15	/*  Beacon DMA Error Int 2 */
+-#define	IMR_BCNDERR1_88E		BIT14	/*  Beacon DMA Error Int 1 */
+-#define	IMR_ATIMEND_E_88E		BIT13	/*  ATIM Window End Ext for Win7 */
+-#define	IMR_TXERR_88E			BIT11	/*  Tx Err Flag Int Status, write 1 clear. */
+-#define	IMR_RXERR_88E			BIT10	/*  Rx Err Flag INT Status, Write 1 clear */
+-#define	IMR_TXFOVW_88E			BIT9	/*  Transmit FIFO Overflow */
+-#define	IMR_RXFOVW_88E			BIT8	/*  Receive FIFO Overflow */
++#define	IMR_BCNDMAINT7_88E		BIT(27)	/*  Beacon DMA Interrupt 7 */
++#define	IMR_BCNDMAINT6_88E		BIT(26)	/*  Beacon DMA Interrupt 6 */
++#define	IMR_BCNDMAINT5_88E		BIT(25)	/*  Beacon DMA Interrupt 5 */
++#define	IMR_BCNDMAINT4_88E		BIT(24)	/*  Beacon DMA Interrupt 4 */
++#define	IMR_BCNDMAINT3_88E		BIT(23)	/*  Beacon DMA Interrupt 3 */
++#define	IMR_BCNDMAINT2_88E		BIT(22)	/*  Beacon DMA Interrupt 2 */
++#define	IMR_BCNDMAINT1_88E		BIT(21)	/*  Beacon DMA Interrupt 1 */
++#define	IMR_BCNDERR7_88E		BIT(20)	/*  Beacon DMA Error Int 7 */
++#define	IMR_BCNDERR6_88E		BIT(19)	/*  Beacon DMA Error Int 6 */
++#define	IMR_BCNDERR5_88E		BIT(18)	/*  Beacon DMA Error Int 5 */
++#define	IMR_BCNDERR4_88E		BIT(17)	/*  Beacon DMA Error Int 4 */
++#define	IMR_BCNDERR3_88E		BIT(16)	/*  Beacon DMA Error Int 3 */
++#define	IMR_BCNDERR2_88E		BIT(15)	/*  Beacon DMA Error Int 2 */
++#define	IMR_BCNDERR1_88E		BIT(14)	/*  Beacon DMA Error Int 1 */
++#define	IMR_ATIMEND_E_88E		BIT(13)	/*  ATIM Window End Ext for Win7 */
++#define	IMR_TXERR_88E			BIT(11)	/*  Tx Err Flag Int Status, write 1 clear. */
++#define	IMR_RXERR_88E			BIT(10)	/*  Rx Err Flag INT Status, Write 1 clear */
++#define	IMR_TXFOVW_88E			BIT(9)	/*  Transmit FIFO Overflow */
++#define	IMR_RXFOVW_88E			BIT(8)	/*  Receive FIFO Overflow */
+ 
+ #define	HAL_NIC_UNPLUG_ISR		0xFFFFFFFF	/*  The value when the NIC is unplugged for PCI. */
+ 
+@@ -692,40 +659,40 @@ Current IOREG MAP
+ /*	the correct arragement is VO - Bit0, VI - Bit1, BE - Bit2,
+  *	and BK - Bit3. */
+ /*	8723 and 88E may be not correct either in the earlier version. */
+-#define		StopBecon			BIT6
+-#define		StopHigh			BIT5
+-#define		StopMgt				BIT4
+-#define		StopBK				BIT3
+-#define		StopBE				BIT2
+-#define		StopVI				BIT1
+-#define		StopVO				BIT0
++#define		StopBecon			BIT(6)
++#define		StopHigh			BIT(5)
++#define		StopMgt				BIT(4)
++#define		StopBK				BIT(3)
++#define		StopBE				BIT(2)
++#define		StopVI				BIT(1)
++#define		StopVO				BIT(0)
+ 
+ /*        8192C (RCR) Receive Configuration Register(Offset 0x608, 32 bits) */
+-#define	RCR_APPFCS		BIT31	/* WMAC append FCS after payload */
+-#define	RCR_APP_MIC		BIT30
+-#define	RCR_APP_PHYSTS		BIT28
+-#define	RCR_APP_ICV		BIT29
+-#define	RCR_APP_PHYST_RXFF	BIT28
+-#define	RCR_APP_BA_SSN		BIT27	/* Accept BA SSN */
+-#define	RCR_ENMBID		BIT24	/* Enable Multiple BssId. */
+-#define	RCR_LSIGEN		BIT23
+-#define	RCR_MFBEN		BIT22
+-#define	RCR_HTC_LOC_CTRL	BIT14   /* MFC<--HTC=1 MFC-->HTC=0 */
+-#define	RCR_AMF			BIT13	/* Accept management type frame */
+-#define	RCR_ACF			BIT12	/* Accept control type frame */
+-#define	RCR_ADF			BIT11	/* Accept data type frame */
+-#define	RCR_AICV		BIT9	/* Accept ICV error packet */
+-#define	RCR_ACRC32		BIT8	/* Accept CRC32 error packet */
+-#define	RCR_CBSSID_BCN		BIT7	/* Accept BSSID match packet
++#define	RCR_APPFCS		BIT(31)	/* WMAC append FCS after payload */
++#define	RCR_APP_MIC		BIT(30)
++#define	RCR_APP_PHYSTS		BIT(28)
++#define	RCR_APP_ICV		BIT(29)
++#define	RCR_APP_PHYST_RXFF	BIT(28)
++#define	RCR_APP_BA_SSN		BIT(27)	/* Accept BA SSN */
++#define	RCR_ENMBID		BIT(24)	/* Enable Multiple BssId. */
++#define	RCR_LSIGEN		BIT(23)
++#define	RCR_MFBEN		BIT(22)
++#define	RCR_HTC_LOC_CTRL	BIT(14)   /* MFC<--HTC=1 MFC-->HTC=0 */
++#define	RCR_AMF			BIT(13)	/* Accept management type frame */
++#define	RCR_ACF			BIT(12)	/* Accept control type frame */
++#define	RCR_ADF			BIT(11)	/* Accept data type frame */
++#define	RCR_AICV		BIT(9)	/* Accept ICV error packet */
++#define	RCR_ACRC32		BIT(8)	/* Accept CRC32 error packet */
++#define	RCR_CBSSID_BCN		BIT(7)	/* Accept BSSID match packet
+ 					 * (Rx beacon, probe rsp) */
+-#define	RCR_CBSSID_DATA		BIT6	/* Accept BSSID match (Data)*/
++#define	RCR_CBSSID_DATA		BIT(6)	/* Accept BSSID match (Data)*/
+ #define	RCR_CBSSID		RCR_CBSSID_DATA	/* Accept BSSID match */
+-#define	RCR_APWRMGT		BIT5	/* Accept power management pkt*/
+-#define	RCR_ADD3		BIT4	/* Accept address 3 match pkt */
+-#define	RCR_AB			BIT3	/* Accept broadcast packet */
+-#define	RCR_AM			BIT2	/* Accept multicast packet */
+-#define	RCR_APM			BIT1	/* Accept physical match pkt */
+-#define	RCR_AAP			BIT0	/* Accept all unicast packet */
++#define	RCR_APWRMGT		BIT(5)	/* Accept power management pkt*/
++#define	RCR_ADD3		BIT(4)	/* Accept address 3 match pkt */
++#define	RCR_AB			BIT(3)	/* Accept broadcast packet */
++#define	RCR_AM			BIT(2)	/* Accept multicast packet */
++#define	RCR_APM			BIT(1)	/* Accept physical match pkt */
++#define	RCR_AAP			BIT(0)	/* Accept all unicast packet */
+ #define	RCR_MXDMA_OFFSET	8
+ #define	RCR_FIFO_OFFSET		13
+ 
+@@ -1193,56 +1160,56 @@ Current IOREG MAP
+ #define SDIO_HIMR_DISABLED			0
+ 
+ /*  RTL8188E SDIO Host Interrupt Mask Register */
+-#define SDIO_HIMR_RX_REQUEST_MSK		BIT0
+-#define SDIO_HIMR_AVAL_MSK			BIT1
+-#define SDIO_HIMR_TXERR_MSK			BIT2
+-#define SDIO_HIMR_RXERR_MSK			BIT3
+-#define SDIO_HIMR_TXFOVW_MSK			BIT4
+-#define SDIO_HIMR_RXFOVW_MSK			BIT5
+-#define SDIO_HIMR_TXBCNOK_MSK			BIT6
+-#define SDIO_HIMR_TXBCNERR_MSK			BIT7
+-#define SDIO_HIMR_BCNERLY_INT_MSK		BIT16
+-#define SDIO_HIMR_C2HCMD_MSK			BIT17
+-#define SDIO_HIMR_CPWM1_MSK			BIT18
+-#define SDIO_HIMR_CPWM2_MSK			BIT19
+-#define SDIO_HIMR_HSISR_IND_MSK			BIT20
+-#define SDIO_HIMR_GTINT3_IND_MSK		BIT21
+-#define SDIO_HIMR_GTINT4_IND_MSK		BIT22
+-#define SDIO_HIMR_PSTIMEOUT_MSK			BIT23
+-#define SDIO_HIMR_OCPINT_MSK			BIT24
+-#define SDIO_HIMR_ATIMEND_MSK			BIT25
+-#define SDIO_HIMR_ATIMEND_E_MSK			BIT26
+-#define SDIO_HIMR_CTWEND_MSK			BIT27
++#define SDIO_HIMR_RX_REQUEST_MSK		BIT(0)
++#define SDIO_HIMR_AVAL_MSK			BIT(1)
++#define SDIO_HIMR_TXERR_MSK			BIT(2)
++#define SDIO_HIMR_RXERR_MSK			BIT(3)
++#define SDIO_HIMR_TXFOVW_MSK			BIT(4)
++#define SDIO_HIMR_RXFOVW_MSK			BIT(5)
++#define SDIO_HIMR_TXBCNOK_MSK			BIT(6)
++#define SDIO_HIMR_TXBCNERR_MSK			BIT(7)
++#define SDIO_HIMR_BCNERLY_INT_MSK		BIT(16)
++#define SDIO_HIMR_C2HCMD_MSK			BIT(17)
++#define SDIO_HIMR_CPWM1_MSK			BIT(18)
++#define SDIO_HIMR_CPWM2_MSK			BIT(19)
++#define SDIO_HIMR_HSISR_IND_MSK			BIT(20)
++#define SDIO_HIMR_GTINT3_IND_MSK		BIT(21)
++#define SDIO_HIMR_GTINT4_IND_MSK		BIT(22)
++#define SDIO_HIMR_PSTIMEOUT_MSK			BIT(23)
++#define SDIO_HIMR_OCPINT_MSK			BIT(24)
++#define SDIO_HIMR_ATIMEND_MSK			BIT(25)
++#define SDIO_HIMR_ATIMEND_E_MSK			BIT(26)
++#define SDIO_HIMR_CTWEND_MSK			BIT(27)
+ 
+ /* RTL8188E SDIO Specific */
+-#define	SDIO_HIMR_MCU_ERR_MSK			BIT28
+-#define	SDIO_HIMR_TSF_BIT32_TOGGLE_MSK		BIT29
++#define	SDIO_HIMR_MCU_ERR_MSK			BIT(28)
++#define	SDIO_HIMR_TSF_BIT32_TOGGLE_MSK		BIT(29)
+ 
+ /*  SDIO Host Interrupt Service Routine */
+-#define SDIO_HISR_RX_REQUEST			BIT0
+-#define SDIO_HISR_AVAL				BIT1
+-#define SDIO_HISR_TXERR				BIT2
+-#define SDIO_HISR_RXERR				BIT3
+-#define SDIO_HISR_TXFOVW			BIT4
+-#define SDIO_HISR_RXFOVW			BIT5
+-#define SDIO_HISR_TXBCNOK			BIT6
+-#define SDIO_HISR_TXBCNERR			BIT7
+-#define SDIO_HISR_BCNERLY_INT			BIT16
+-#define SDIO_HISR_C2HCMD			BIT17
+-#define SDIO_HISR_CPWM1				BIT18
+-#define SDIO_HISR_CPWM2				BIT19
+-#define SDIO_HISR_HSISR_IND			BIT20
+-#define SDIO_HISR_GTINT3_IND			BIT21
+-#define SDIO_HISR_GTINT4_IND			BIT22
+-#define SDIO_HISR_PSTIME			BIT23
+-#define SDIO_HISR_OCPINT			BIT24
+-#define SDIO_HISR_ATIMEND			BIT25
+-#define SDIO_HISR_ATIMEND_E			BIT26
+-#define SDIO_HISR_CTWEND			BIT27
++#define SDIO_HISR_RX_REQUEST			BIT(0)
++#define SDIO_HISR_AVAL				BIT(1)
++#define SDIO_HISR_TXERR				BIT(2)
++#define SDIO_HISR_RXERR				BIT(3)
++#define SDIO_HISR_TXFOVW			BIT(4)
++#define SDIO_HISR_RXFOVW			BIT(5)
++#define SDIO_HISR_TXBCNOK			BIT(6)
++#define SDIO_HISR_TXBCNERR			BIT(7)
++#define SDIO_HISR_BCNERLY_INT			BIT(16)
++#define SDIO_HISR_C2HCMD			BIT(17)
++#define SDIO_HISR_CPWM1				BIT(18)
++#define SDIO_HISR_CPWM2				BIT(19)
++#define SDIO_HISR_HSISR_IND			BIT(20)
++#define SDIO_HISR_GTINT3_IND			BIT(21)
++#define SDIO_HISR_GTINT4_IND			BIT(22)
++#define SDIO_HISR_PSTIME			BIT(23)
++#define SDIO_HISR_OCPINT			BIT(24)
++#define SDIO_HISR_ATIMEND			BIT(25)
++#define SDIO_HISR_ATIMEND_E			BIT(26)
++#define SDIO_HISR_CTWEND			BIT(27)
+ 
+ /* RTL8188E SDIO Specific */
+-#define	SDIO_HISR_MCU_ERR			BIT28
+-#define	SDIO_HISR_TSF_BIT32_TOGGLE		BIT29
++#define	SDIO_HISR_MCU_ERR			BIT(28)
++#define	SDIO_HISR_TSF_BIT32_TOGGLE		BIT(29)
+ 
+ #define MASK_SDIO_HISR_CLEAR				\
+ 	(SDIO_HISR_TXERR | SDIO_HISR_RXERR | SDIO_HISR_TXFOVW |\
+@@ -1252,8 +1219,8 @@ Current IOREG MAP
+ 	 SDIO_HISR_PSTIMEOUT | SDIO_HISR_OCPINT)
+ 
+ /*  SDIO HCI Suspend Control Register */
+-#define HCI_RESUME_PWR_RDY		BIT1
+-#define HCI_SUS_CTRL			BIT0
++#define HCI_RESUME_PWR_RDY		BIT(1)
++#define HCI_SUS_CTRL			BIT(0)
+ 
+ /*  SDIO Tx FIFO related */
+ /*  The number of Tx FIFO free page */
+@@ -1287,33 +1254,33 @@ Current IOREG MAP
+ 
+ /* 2REG_MULTI_FUNC_CTRL(For RTL8723 Only) */
+ /*  Enable GPIO[9] as WiFi HW PDn source */
+-#define	WL_HWPDN_EN				BIT0
++#define	WL_HWPDN_EN				BIT(0)
+ /*  WiFi HW PDn polarity control */
+-#define	WL_HWPDN_SL				BIT1
++#define	WL_HWPDN_SL				BIT(1)
+ /*  WiFi function enable */
+-#define	WL_FUNC_EN				BIT2
++#define	WL_FUNC_EN				BIT(2)
+ /*  Enable GPIO[9] as WiFi RF HW PDn source */
+-#define	WL_HWROF_EN				BIT3
++#define	WL_HWROF_EN				BIT(3)
+ /*  Enable GPIO[11] as BT HW PDn source */
+-#define	BT_HWPDN_EN				BIT16
++#define	BT_HWPDN_EN				BIT(16)
+ /*  BT HW PDn polarity control */
+-#define	BT_HWPDN_SL				BIT17
++#define	BT_HWPDN_SL				BIT(17)
+ /*  BT function enable */
+-#define	BT_FUNC_EN				BIT18
++#define	BT_FUNC_EN				BIT(18)
+ /*  Enable GPIO[11] as BT/GPS RF HW PDn source */
+-#define	BT_HWROF_EN				BIT19
++#define	BT_HWROF_EN				BIT(19)
+ /*  Enable GPIO[10] as GPS HW PDn source */
+-#define	GPS_HWPDN_EN				BIT20
++#define	GPS_HWPDN_EN				BIT(20)
+ /*  GPS HW PDn polarity control */
+-#define	GPS_HWPDN_SL				BIT21
++#define	GPS_HWPDN_SL				BIT(21)
+ /*  GPS function enable */
+-#define	GPS_FUNC_EN				BIT22
++#define	GPS_FUNC_EN				BIT(22)
+ 
+ /* 3 REG_LIFECTRL_CTRL */
+-#define	HAL92C_EN_PKT_LIFE_TIME_BK		BIT3
+-#define	HAL92C_EN_PKT_LIFE_TIME_BE		BIT2
+-#define	HAL92C_EN_PKT_LIFE_TIME_VI		BIT1
+-#define	HAL92C_EN_PKT_LIFE_TIME_VO		BIT0
++#define	HAL92C_EN_PKT_LIFE_TIME_BK		BIT(3)
++#define	HAL92C_EN_PKT_LIFE_TIME_BE		BIT(2)
++#define	HAL92C_EN_PKT_LIFE_TIME_VI		BIT(1)
++#define	HAL92C_EN_PKT_LIFE_TIME_VO		BIT(0)
+ 
+ #define	HAL92C_MSDU_LIFE_TIME_UNIT		128	/*  in us */
+ 
+@@ -1323,7 +1290,7 @@ Current IOREG MAP
+ #define POLLING_LLT_THRESHOLD			20
+ #define POLLING_READY_TIMEOUT_COUNT		1000
+ /*  GPIO BIT */
+-#define	HAL_8192C_HW_GPIO_WPS_BIT		BIT2
++#define	HAL_8192C_HW_GPIO_WPS_BIT		BIT(2)
+ 
+ /*	8192C EEPROM/EFUSE share register definition. */
+ 
+diff --git a/drivers/staging/rtl8188eu/include/rtw_sreset.h b/drivers/staging/rtl8188eu/include/rtw_sreset.h
+index 580e850511a7..3a62ed010875 100644
+--- a/drivers/staging/rtl8188eu/include/rtw_sreset.h
++++ b/drivers/staging/rtl8188eu/include/rtw_sreset.h
+@@ -30,13 +30,13 @@ struct sreset_priv {
+ #include 
+ 
+ #define	WIFI_STATUS_SUCCESS		0
+-#define	USB_VEN_REQ_CMD_FAIL	BIT0
+-#define	USB_READ_PORT_FAIL		BIT1
+-#define	USB_WRITE_PORT_FAIL		BIT2
+-#define	WIFI_MAC_TXDMA_ERROR	BIT3
+-#define   WIFI_TX_HANG				BIT4
+-#define	WIFI_RX_HANG				BIT5
+-#define		WIFI_IF_NOT_EXIST			BIT6
++#define	USB_VEN_REQ_CMD_FAIL		BIT(0)
++#define	USB_READ_PORT_FAIL		BIT(1)
++#define	USB_WRITE_PORT_FAIL		BIT(2)
++#define	WIFI_MAC_TXDMA_ERROR		BIT(3)
++#define   WIFI_TX_HANG			BIT(4)
++#define	WIFI_RX_HANG			BIT(5)
++#define		WIFI_IF_NOT_EXIST	BIT(6)
+ 
+ void sreset_init_value(struct adapter *padapter);
+ u8 sreset_get_wifi_status(struct adapter *padapter);

commit 56b3152e5e8b0501ff9ef100b772df8ecb3efd82
+Author: Anish Bhatt 
+Date:   Mon Oct 12 21:02:36 2015 -0700
+
+    rtl8192u: BIT() macro cleanup
+    
+    Use the BIT(x) macro directly instead using multiple
+    BITX defines.
+    
+    Signed-off-by: Anish Bhatt 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h
+index d481a26c25ae..967ef9a98fc0 100644
+--- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h
++++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h
+@@ -415,7 +415,7 @@ typedef struct ieee_param {
+ /* QOS control */
+ #define IEEE80211_QCTL_TID              0x000F
+ 
+-#define	FC_QOS_BIT					BIT7
++#define	FC_QOS_BIT					BIT(7)
+ #define IsDataFrame(pdu)			( ((pdu[0] & 0x0C)==0x08) ? true : false )
+ #define	IsLegacyDataFrame(pdu)	(IsDataFrame(pdu) && (!(pdu[0]&FC_QOS_BIT)) )
+ //added by wb. Is this right?
+@@ -1565,10 +1565,10 @@ typedef struct _RT_POWER_SAVE_CONTROL {
+ } RT_POWER_SAVE_CONTROL, *PRT_POWER_SAVE_CONTROL;
+ 
+ typedef u32 RT_RF_CHANGE_SOURCE;
+-#define RF_CHANGE_BY_SW BIT31
+-#define RF_CHANGE_BY_HW BIT30
+-#define RF_CHANGE_BY_PS BIT29
+-#define RF_CHANGE_BY_IPS BIT28
++#define RF_CHANGE_BY_SW		BIT(31)
++#define RF_CHANGE_BY_HW		BIT(30)
++#define RF_CHANGE_BY_PS		BIT(29)
++#define RF_CHANGE_BY_IPS	BIT(28)
+ #define RF_CHANGE_BY_INIT	0	// Do not change the RFOff reason. Defined by Bruce, 2008-01-17.
+ 
+ typedef enum
+diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_Qos.h b/drivers/staging/rtl8192u/ieee80211/rtl819x_Qos.h
+index 9fbce912a74b..49c23c720f78 100644
+--- a/drivers/staging/rtl8192u/ieee80211/rtl819x_Qos.h
++++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_Qos.h
+@@ -1,39 +1,6 @@
+ #ifndef __INC_QOS_TYPE_H
+ #define __INC_QOS_TYPE_H
+ 
+-#define BIT0                    0x00000001
+-#define BIT1                    0x00000002
+-#define BIT2                    0x00000004
+-#define BIT3                    0x00000008
+-#define BIT4                    0x00000010
+-#define BIT5                    0x00000020
+-#define BIT6                    0x00000040
+-#define BIT7                    0x00000080
+-#define BIT8                    0x00000100
+-#define BIT9                    0x00000200
+-#define BIT10                   0x00000400
+-#define BIT11                   0x00000800
+-#define BIT12                   0x00001000
+-#define BIT13                   0x00002000
+-#define BIT14                   0x00004000
+-#define BIT15                   0x00008000
+-#define BIT16                   0x00010000
+-#define BIT17                   0x00020000
+-#define BIT18                   0x00040000
+-#define BIT19                   0x00080000
+-#define BIT20                   0x00100000
+-#define BIT21                   0x00200000
+-#define BIT22                   0x00400000
+-#define BIT23                   0x00800000
+-#define BIT24                   0x01000000
+-#define BIT25                   0x02000000
+-#define BIT26                   0x04000000
+-#define BIT27                   0x08000000
+-#define BIT28                   0x10000000
+-#define BIT29                   0x20000000
+-#define BIT30                   0x40000000
+-#define BIT31                   0x80000000
+-
+ #define	MAX_WMMELE_LENGTH	64
+ 
+ //
+@@ -375,17 +342,17 @@ typedef struct _ACM{
+ 
+ typedef	u8		AC_UAPSD, *PAC_UAPSD;
+ 
+-#define	GET_VO_UAPSD(_apsd) ((_apsd) & BIT0)
+-#define	SET_VO_UAPSD(_apsd) ((_apsd) |= BIT0)
++#define	GET_VO_UAPSD(_apsd) ((_apsd) & BIT(0))
++#define	SET_VO_UAPSD(_apsd) ((_apsd) |= BIT(0))
+ 
+-#define	GET_VI_UAPSD(_apsd) ((_apsd) & BIT1)
+-#define	SET_VI_UAPSD(_apsd) ((_apsd) |= BIT1)
++#define	GET_VI_UAPSD(_apsd) ((_apsd) & BIT(1))
++#define	SET_VI_UAPSD(_apsd) ((_apsd) |= BIT(1))
+ 
+-#define	GET_BK_UAPSD(_apsd) ((_apsd) & BIT2)
+-#define	SET_BK_UAPSD(_apsd) ((_apsd) |= BIT2)
++#define	GET_BK_UAPSD(_apsd) ((_apsd) & BIT(2))
++#define	SET_BK_UAPSD(_apsd) ((_apsd) |= BIT(2))
+ 
+-#define	GET_BE_UAPSD(_apsd) ((_apsd) & BIT3)
+-#define	SET_BE_UAPSD(_apsd) ((_apsd) |= BIT3)
++#define	GET_BE_UAPSD(_apsd) ((_apsd) & BIT(3))
++#define	SET_BE_UAPSD(_apsd) ((_apsd) |= BIT(3))
+ 
+ 
+ //typedef struct _TCLASS{
+diff --git a/drivers/staging/rtl8192u/r8192U.h b/drivers/staging/rtl8192u/r8192U.h
+index a76748e3b506..ee1c72267811 100644
+--- a/drivers/staging/rtl8192u/r8192U.h
++++ b/drivers/staging/rtl8192u/r8192U.h
+@@ -43,39 +43,6 @@
+ #define MAX_KEY_LEN     61
+ #define KEY_BUF_SIZE    5
+ 
+-#define BIT0            0x00000001
+-#define BIT1            0x00000002
+-#define BIT2            0x00000004
+-#define BIT3            0x00000008
+-#define BIT4            0x00000010
+-#define BIT5            0x00000020
+-#define BIT6            0x00000040
+-#define BIT7            0x00000080
+-#define BIT8            0x00000100
+-#define BIT9            0x00000200
+-#define BIT10           0x00000400
+-#define BIT11           0x00000800
+-#define BIT12           0x00001000
+-#define BIT13           0x00002000
+-#define BIT14           0x00004000
+-#define BIT15           0x00008000
+-#define BIT16           0x00010000
+-#define BIT17           0x00020000
+-#define BIT18           0x00040000
+-#define BIT19           0x00080000
+-#define BIT20           0x00100000
+-#define BIT21           0x00200000
+-#define BIT22           0x00400000
+-#define BIT23           0x00800000
+-#define BIT24           0x01000000
+-#define BIT25           0x02000000
+-#define BIT26           0x04000000
+-#define BIT27           0x08000000
+-#define BIT28           0x10000000
+-#define BIT29           0x20000000
+-#define BIT30           0x40000000
+-#define BIT31           0x80000000
+-
+ #define	Rx_Smooth_Factor		20
+ #define DMESG(x, a...)
+ #define DMESGW(x, a...)
+@@ -87,44 +54,44 @@ extern u32 rt_global_debug_component;
+ 			pr_debug("RTL8192U: " x "\n", ##args);	\
+ 	} while (0)
+ 
+-#define COMP_TRACE              BIT0  /* Function call tracing. */
+-#define COMP_DBG                BIT1
+-#define COMP_INIT               BIT2  /* Driver initialization/halt/reset. */
++#define COMP_TRACE              BIT(0)  /* Function call tracing. */
++#define COMP_DBG                BIT(1)
++#define COMP_INIT               BIT(2)  /* Driver initialization/halt/reset. */
+ 
+ 
+-#define COMP_RECV               BIT3  /* Receive data path. */
+-#define COMP_SEND               BIT4  /* Send data path. */
+-#define COMP_IO                 BIT5
++#define COMP_RECV               BIT(3)  /* Receive data path. */
++#define COMP_SEND               BIT(4)  /* Send data path. */
++#define COMP_IO                 BIT(5)
+ /* 802.11 Power Save mode or System/Device Power state. */
+-#define COMP_POWER              BIT6
++#define COMP_POWER              BIT(6)
+ /* 802.11 link related: join/start BSS, leave BSS. */
+-#define COMP_EPROM              BIT7
+-#define COMP_SWBW               BIT8  /* Bandwidth switch. */
+-#define COMP_POWER_TRACKING     BIT9  /* 8190 TX Power Tracking */
+-#define COMP_TURBO              BIT10 /* Turbo Mode */
+-#define COMP_QOS                BIT11
+-#define COMP_RATE               BIT12 /* Rate Adaptive mechanism */
+-#define COMP_RM                 BIT13 /* Radio Measurement */
+-#define COMP_DIG                BIT14
+-#define COMP_PHY                BIT15
+-#define COMP_CH                 BIT16 /* Channel setting debug */
+-#define COMP_TXAGC              BIT17 /* Tx power */
+-#define COMP_HIPWR              BIT18 /* High Power Mechanism */
+-#define COMP_HALDM              BIT19 /* HW Dynamic Mechanism */
+-#define COMP_SEC                BIT20 /* Event handling */
+-#define COMP_LED                BIT21
+-#define COMP_RF                 BIT22
+-#define COMP_RXDESC             BIT23 /* Rx desc information for SD3 debug */
++#define COMP_EPROM              BIT(7)
++#define COMP_SWBW               BIT(8)  /* Bandwidth switch. */
++#define COMP_POWER_TRACKING     BIT(9)  /* 8190 TX Power Tracking */
++#define COMP_TURBO              BIT(10) /* Turbo Mode */
++#define COMP_QOS                BIT(11)
++#define COMP_RATE               BIT(12) /* Rate Adaptive mechanism */
++#define COMP_RM                 BIT(13) /* Radio Measurement */
++#define COMP_DIG                BIT(14)
++#define COMP_PHY                BIT(15)
++#define COMP_CH                 BIT(16) /* Channel setting debug */
++#define COMP_TXAGC              BIT(17) /* Tx power */
++#define COMP_HIPWR              BIT(18) /* High Power Mechanism */
++#define COMP_HALDM              BIT(19) /* HW Dynamic Mechanism */
++#define COMP_SEC                BIT(20) /* Event handling */
++#define COMP_LED                BIT(21)
++#define COMP_RF                 BIT(22)
++#define COMP_RXDESC             BIT(23) /* Rx desc information for SD3 debug */
+ 
+ /* 11n or 8190 specific code */
+ 
+-#define COMP_FIRMWARE           BIT24 /* Firmware downloading */
+-#define COMP_HT                 BIT25 /* 802.11n HT related information */
+-#define COMP_AMSDU              BIT26 /* A-MSDU Debugging */
+-#define COMP_SCAN               BIT27
+-#define COMP_DOWN               BIT29 /* rm driver module */
+-#define COMP_RESET              BIT30 /* Silent reset */
+-#define COMP_ERR                BIT31 /* Error out, always on */
++#define COMP_FIRMWARE           BIT(24) /* Firmware downloading */
++#define COMP_HT                 BIT(25) /* 802.11n HT related information */
++#define COMP_AMSDU              BIT(26) /* A-MSDU Debugging */
++#define COMP_SCAN               BIT(27)
++#define COMP_DOWN               BIT(29) /* rm driver module */
++#define COMP_RESET              BIT(30) /* Silent reset */
++#define COMP_ERR                BIT(31) /* Error out, always on */
+ 
+ #define RTL819x_DEBUG
+ #ifdef RTL819x_DEBUG
+diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
+index eab0d811e85a..678ecf6d2b79 100644
+--- a/drivers/staging/rtl8192u/r8192U_core.c
++++ b/drivers/staging/rtl8192u/r8192U_core.c
+@@ -233,7 +233,7 @@ static void CamResetAllEntry(struct net_device *dev)
+ 	 * condition, Cam can not be reset because upper layer will not set
+ 	 * this static key again.
+ 	 */
+-	ulcommand |= BIT31 | BIT30;
++	ulcommand |= BIT(31) | BIT(30);
+ 	write_nic_dword(dev, RWCAM, ulcommand);
+ 
+ }
+@@ -242,7 +242,7 @@ static void CamResetAllEntry(struct net_device *dev)
+ void write_cam(struct net_device *dev, u8 addr, u32 data)
+ {
+ 	write_nic_dword(dev, WCAMI, data);
+-	write_nic_dword(dev, RWCAM, BIT31 | BIT16 | (addr & 0xff));
++	write_nic_dword(dev, RWCAM, BIT(31) | BIT(16) | (addr & 0xff));
+ }
+ 
+ u32 read_cam(struct net_device *dev, u8 addr)
+@@ -2412,7 +2412,7 @@ static void rtl8192_get_eeprom_size(struct net_device *dev)
+ 	read_nic_word_E(dev, EPROM_CMD, &curCR);
+ 	RT_TRACE(COMP_EPROM,
+ 		 "read from Reg EPROM_CMD(%x):%x\n", EPROM_CMD, curCR);
+-	/* whether need I consider BIT5? */
++	/* whether need I consider BIT(5?) */
+ 	priv->epromtype =
+ 		(curCR & Cmd9346CR_9356SEL) ? EPROM_93c56 : EPROM_93c46;
+ 	RT_TRACE(COMP_EPROM,
+@@ -5180,14 +5180,14 @@ void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
+ 		 dev, EntryNo, KeyIndex, KeyType, MacAddr);
+ 
+ 	if (DefaultKey)
+-		usConfig |= BIT15 | (KeyType << 2);
++		usConfig |= BIT(15) | (KeyType << 2);
+ 	else
+-		usConfig |= BIT15 | (KeyType << 2) | KeyIndex;
++		usConfig |= BIT(15) | (KeyType << 2) | KeyIndex;
+ 
+ 
+ 	for (i = 0; i < CAM_CONTENT_COUNT; i++) {
+ 		TargetCommand  = i + CAM_CONTENT_COUNT * EntryNo;
+-		TargetCommand |= BIT31 | BIT16;
++		TargetCommand |= BIT(31) | BIT(16);
+ 
+ 		if (i == 0) { /* MAC|Config */
+ 			TargetContent = (u32)(*(MacAddr + 0)) << 16 |
+diff --git a/drivers/staging/rtl8192u/r8192U_dm.c b/drivers/staging/rtl8192u/r8192U_dm.c
+index 5277f2eec033..375ec96b9469 100644
+--- a/drivers/staging/rtl8192u/r8192U_dm.c
++++ b/drivers/staging/rtl8192u/r8192U_dm.c
+@@ -325,21 +325,26 @@ static void dm_check_rate_adaptive(struct net_device *dev)
+ 			(!pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI20MHz);
+ 
+ 		pra->upper_rssi_threshold_ratr =
+-				(pra->upper_rssi_threshold_ratr & (~BIT31)) | ((bshort_gi_enabled) ? BIT31:0);
++				(pra->upper_rssi_threshold_ratr & (~BIT(31))) |
++				((bshort_gi_enabled) ? BIT(31) : 0);
+ 
+ 		pra->middle_rssi_threshold_ratr =
+-				(pra->middle_rssi_threshold_ratr & (~BIT31)) | ((bshort_gi_enabled) ? BIT31:0);
++				(pra->middle_rssi_threshold_ratr & (~BIT(31))) |
++				((bshort_gi_enabled) ? BIT(31) : 0);
+ 
+ 		if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) {
+ 			pra->low_rssi_threshold_ratr =
+-				(pra->low_rssi_threshold_ratr_40M & (~BIT31)) | ((bshort_gi_enabled) ? BIT31:0);
++			      (pra->low_rssi_threshold_ratr_40M & (~BIT(31))) |
++			      ((bshort_gi_enabled) ? BIT(31) : 0);
+ 		} else {
+ 			pra->low_rssi_threshold_ratr =
+-			(pra->low_rssi_threshold_ratr_20M & (~BIT31)) | ((bshort_gi_enabled) ? BIT31:0);
++			(pra->low_rssi_threshold_ratr_20M & (~BIT(31))) |
++			((bshort_gi_enabled) ? BIT(31) : 0);
+ 		}
+ 		/* cosa add for test */
+ 		pra->ping_rssi_ratr =
+-				(pra->ping_rssi_ratr & (~BIT31)) | ((bshort_gi_enabled) ? BIT31:0);
++				(pra->ping_rssi_ratr & (~BIT(31))) |
++				((bshort_gi_enabled) ? BIT(31) : 0);
+ 
+ 		/* 2007/10/08 MH We support RA smooth scheme now. When it is the first
+ 		   time to link with AP. We will not change upper/lower threshold. If
+@@ -2378,7 +2383,7 @@ static	void	dm_check_pbc_gpio(struct net_device *dev)
+ 	if (tmp1byte == 0xff)
+ 		return;
+ 
+-	if (tmp1byte&BIT6 || tmp1byte&BIT0) {
++	if (tmp1byte & BIT(6) || tmp1byte & BIT(0)) {
+ 		/*
+ 		 * Here we only set bPbcPressed to TRUE
+ 		 * After trigger PBC, the variable will be set to FALSE
+diff --git a/drivers/staging/rtl8192u/r8192U_hw.h b/drivers/staging/rtl8192u/r8192U_hw.h
+index a93694ff0c42..e07d65d04dbc 100644
+--- a/drivers/staging/rtl8192u/r8192U_hw.h
++++ b/drivers/staging/rtl8192u/r8192U_hw.h
+@@ -55,17 +55,17 @@ typedef enum _BaseBand_Config_Type{
+ #define BB_ANTATTEN_CHAN14	0x0c
+ #define BB_ANTENNA_B 0x40
+ 
+-#define BB_HOST_BANG (1<<30)
+-#define BB_HOST_BANG_EN (1<<2)
+-#define BB_HOST_BANG_CLK (1<<1)
+-#define BB_HOST_BANG_RW (1<<3)
++#define BB_HOST_BANG		BIT(30)
++#define BB_HOST_BANG_EN		BIT(2)
++#define BB_HOST_BANG_CLK	BIT(1)
++#define BB_HOST_BANG_RW		BIT(3)
+ #define BB_HOST_BANG_DATA	 1
+ 
+ //#if (RTL819X_FPGA_VER & RTL819X_FPGA_VIVI_070920)
+ #define AFR			0x010
+-#define AFR_CardBEn		(1<<0)
+-#define AFR_CLKRUN_SEL		(1<<1)
+-#define AFR_FuncRegEn		(1<<2)
++#define AFR_CardBEn		BIT(0)
++#define AFR_CLKRUN_SEL		BIT(1)
++#define AFR_FuncRegEn		BIT(2)
+ #define RTL8190_EEPROM_ID	0x8129
+ #define EEPROM_VID		0x02
+ #define EEPROM_PID		0x04
+@@ -126,38 +126,39 @@ enum _RTL8192Usb_HW {
+ #define TCR_LRL_OFFSET		0
+ #define TCR_SRL_OFFSET		8
+ #define TCR_MXDMA_OFFSET	21
+-#define TCR_SAT			BIT24		// Enable Rate depedent ack timeout timer
++#define TCR_SAT			BIT(24)	// Enable Rate depedent ack timeout timer
+ 	RCR			= 0x044, // Receive Configuration Register
+-#define MAC_FILTER_MASK ((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<5) | \
+-		(1<<12) | (1<<18) | (1<<19) | (1<<20) | (1<<21) | (1<<22) | (1<<23))
+-#define RX_FIFO_THRESHOLD_MASK ((1<<13) | (1<<14) | (1<<15))
++#define MAC_FILTER_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(5) | \
++			 BIT(12) | BIT(18) | BIT(19) | BIT(20) | BIT(21) | \
++			 BIT(22) | BIT(23))
++#define RX_FIFO_THRESHOLD_MASK (BIT(13) | BIT(14) | BIT(15))
+ #define RX_FIFO_THRESHOLD_SHIFT 13
+ #define RX_FIFO_THRESHOLD_128 3
+ #define RX_FIFO_THRESHOLD_256 4
+ #define RX_FIFO_THRESHOLD_512 5
+ #define RX_FIFO_THRESHOLD_1024 6
+ #define RX_FIFO_THRESHOLD_NONE 7
+-#define MAX_RX_DMA_MASK ((1<<8) | (1<<9) | (1<<10))
++#define MAX_RX_DMA_MASK 	(BIT(8) | BIT(9) | BIT(10))
+ #define RCR_MXDMA_OFFSET	8
+ #define RCR_FIFO_OFFSET		13
+-#define RCR_ONLYERLPKT		BIT31			// Early Receiving based on Packet Size.
+-#define RCR_ENCS2		BIT30			// Enable Carrier Sense Detection Method 2
+-#define RCR_ENCS1		BIT29			// Enable Carrier Sense Detection Method 1
+-#define RCR_ENMBID		BIT27			// Enable Multiple BssId.
+-#define RCR_ACKTXBW		(BIT24|BIT25)		// TXBW Setting of ACK frames
+-#define RCR_CBSSID		BIT23			// Accept BSSID match packet
+-#define RCR_APWRMGT		BIT22			// Accept power management packet
+-#define	RCR_ADD3		BIT21			// Accept address 3 match packet
+-#define RCR_AMF			BIT20			// Accept management type frame
+-#define RCR_ACF			BIT19			// Accept control type frame
+-#define RCR_ADF			BIT18			// Accept data type frame
+-#define RCR_RXFTH		BIT13			// Rx FIFO Threshold
+-#define RCR_AICV		BIT12			// Accept ICV error packet
+-#define	RCR_ACRC32		BIT5			// Accept CRC32 error packet
+-#define	RCR_AB			BIT3			// Accept broadcast packet
+-#define	RCR_AM			BIT2			// Accept multicast packet
+-#define	RCR_APM			BIT1			// Accept physical match packet
+-#define	RCR_AAP			BIT0			// Accept all unicast packet
++#define RCR_ONLYERLPKT		BIT(31)			// Early Receiving based on Packet Size.
++#define RCR_ENCS2		BIT(30)			// Enable Carrier Sense Detection Method 2
++#define RCR_ENCS1		BIT(29)			// Enable Carrier Sense Detection Method 1
++#define RCR_ENMBID		BIT(27)			// Enable Multiple BssId.
++#define RCR_ACKTXBW		(BIT(24) | BIT(25))	// TXBW Setting of ACK frames
++#define RCR_CBSSID		BIT(23)			// Accept BSSID match packet
++#define RCR_APWRMGT		BIT(22)			// Accept power management packet
++#define	RCR_ADD3		BIT(21)			// Accept address 3 match packet
++#define RCR_AMF			BIT(20)			// Accept management type frame
++#define RCR_ACF			BIT(19)			// Accept control type frame
++#define RCR_ADF			BIT(18)			// Accept data type frame
++#define RCR_RXFTH		BIT(13)			// Rx FIFO Threshold
++#define RCR_AICV		BIT(12)			// Accept ICV error packet
++#define	RCR_ACRC32		BIT(5)			// Accept CRC32 error packet
++#define	RCR_AB			BIT(3)			// Accept broadcast packet
++#define	RCR_AM			BIT(2)			// Accept multicast packet
++#define	RCR_APM			BIT(1)			// Accept physical match packet
++#define	RCR_AAP			BIT(0)			// Accept all unicast packet
+ 	SLOT_TIME		= 0x049, // Slot Time Register
+ 	ACK_TIMEOUT		= 0x04c, // Ack Timeout Register
+ 	PIFS_TIME		= 0x04d, // PIFS time
+@@ -180,12 +181,12 @@ enum _RTL8192Usb_HW {
+ 	WCAMI			= 0x0A4, // Software write CAM input content
+ 	RCAMO			= 0x0A8, // Software read/write CAM config
+ 	SECR			= 0x0B0, //Security Configuration Register
+-#define	SCR_TxUseDK		BIT0			//Force Tx Use Default Key
+-#define SCR_RxUseDK		BIT1			//Force Rx Use Default Key
+-#define SCR_TxEncEnable		BIT2			//Enable Tx Encryption
+-#define SCR_RxDecEnable		BIT3			//Enable Rx Decryption
+-#define SCR_SKByA2		BIT4			//Search kEY BY A2
+-#define SCR_NoSKMC		BIT5			//No Key Search for Multicast
++#define	SCR_TxUseDK		BIT(0)			//Force Tx Use Default Key
++#define SCR_RxUseDK		BIT(1)			//Force Rx Use Default Key
++#define SCR_TxEncEnable		BIT(2)			//Enable Tx Encryption
++#define SCR_RxDecEnable		BIT(3)			//Enable Rx Decryption
++#define SCR_SKByA2		BIT(4)			//Search kEY BY A2
++#define SCR_NoSKMC		BIT(5)			//No Key Search for Multicast
+ #define SCR_UseDK		0x01
+ #define SCR_TxSecEnable		0x02
+ #define SCR_RxSecEnable		0x04
+@@ -226,13 +227,13 @@ enum _RTL8192Usb_HW {
+ ////       8190 AcmHwCtrl bits                                    (offset 0x171, 1 byte)
+ ////----------------------------------------------------------------------------
+ //
+-#define AcmHw_HwEn              BIT0
+-#define AcmHw_BeqEn             BIT1
+-#define AcmHw_ViqEn             BIT2
+-#define AcmHw_VoqEn             BIT3
+-#define AcmHw_BeqStatus         BIT4
+-#define AcmHw_ViqStatus         BIT5
+-#define AcmHw_VoqStatus         BIT6
++#define AcmHw_HwEn              BIT(0)
++#define AcmHw_BeqEn             BIT(1)
++#define AcmHw_ViqEn             BIT(2)
++#define AcmHw_VoqEn             BIT(3)
++#define AcmHw_BeqStatus         BIT(4)
++#define AcmHw_ViqStatus         BIT(5)
++#define AcmHw_VoqStatus         BIT(6)
+ 
+ 	AcmFwCtrl		= 0x172, // ACM Firmware Control Register
+ 	AES_11N_FIX		= 0x173,
+@@ -281,18 +282,18 @@ enum _RTL8192Usb_HW {
+ 	NHM_RPI_COUNTER5	= 0x269, // Noise Histogram RPI counter5, the fraction of signal strength in (NHM_THRESHOLD4, NHM_THRESHOLD5].
+ 	NHM_RPI_COUNTER6	= 0x26A, // Noise Histogram RPI counter6, the fraction of signal strength in (NHM_THRESHOLD5, NHM_THRESHOLD6].
+ 	NHM_RPI_COUNTER7	= 0x26B, // Noise Histogram RPI counter7, the fraction of signal strength in (NHM_THRESHOLD6, NHM_THRESHOLD7].
+-#define	BW_OPMODE_11J			BIT0
+-#define	BW_OPMODE_5G			BIT1
+-#define	BW_OPMODE_20MHZ			BIT2
++#define	BW_OPMODE_11J			BIT(0)
++#define	BW_OPMODE_5G			BIT(1)
++#define	BW_OPMODE_20MHZ			BIT(2)
+ 	BW_OPMODE		= 0x300, // Bandwidth operation mode
+ 	MSR			= 0x303, // Media Status register
+-#define MSR_LINK_MASK      ((1<<0)|(1<<1))
++#define MSR_LINK_MASK      (BIT(0)|BIT(1))
+ #define MSR_LINK_MANAGED   2
+ #define MSR_LINK_NONE      0
+ #define MSR_LINK_SHIFT     0
+ #define MSR_LINK_ADHOC     1
+ #define MSR_LINK_MASTER    3
+-#define MSR_LINK_ENEDCA	   (1<<4)
++#define MSR_LINK_ENEDCA	   BIT(4)
+ 	RETRY_LIMIT		= 0x304, // Retry Limit [15:8]-short, [7:0]-long
+ #define RETRY_LIMIT_SHORT_SHIFT 8
+ #define RETRY_LIMIT_LONG_SHIFT 0
+@@ -304,27 +305,27 @@ enum _RTL8192Usb_HW {
+ #define RRSR_RSC_LOWSUBCHNL		0x400000
+ #define RRSR_RSC_UPSUBCHANL		0x200000
+ #define RRSR_SHORT					0x800000
+-#define RRSR_1M						BIT0
+-#define RRSR_2M						BIT1
+-#define RRSR_5_5M					BIT2
+-#define RRSR_11M					BIT3
+-#define RRSR_6M						BIT4
+-#define RRSR_9M						BIT5
+-#define RRSR_12M					BIT6
+-#define RRSR_18M					BIT7
+-#define RRSR_24M					BIT8
+-#define RRSR_36M					BIT9
+-#define RRSR_48M					BIT10
+-#define RRSR_54M					BIT11
+-#define RRSR_MCS0					BIT12
+-#define RRSR_MCS1					BIT13
+-#define RRSR_MCS2					BIT14
+-#define RRSR_MCS3					BIT15
+-#define RRSR_MCS4					BIT16
+-#define RRSR_MCS5					BIT17
+-#define RRSR_MCS6					BIT18
+-#define RRSR_MCS7					BIT19
+-#define BRSR_AckShortPmb			BIT23		// CCK ACK: use Short Preamble or not.
++#define RRSR_1M						BIT(0)
++#define RRSR_2M						BIT(1)
++#define RRSR_5_5M					BIT(2)
++#define RRSR_11M					BIT(3)
++#define RRSR_6M						BIT(4)
++#define RRSR_9M						BIT(5)
++#define RRSR_12M					BIT(6)
++#define RRSR_18M					BIT(7)
++#define RRSR_24M					BIT(8)
++#define RRSR_36M					BIT(9)
++#define RRSR_48M					BIT(10)
++#define RRSR_54M					BIT(11)
++#define RRSR_MCS0					BIT(12)
++#define RRSR_MCS1					BIT(13)
++#define RRSR_MCS2					BIT(14)
++#define RRSR_MCS3					BIT(15)
++#define RRSR_MCS4					BIT(16)
++#define RRSR_MCS5					BIT(17)
++#define RRSR_MCS6					BIT(18)
++#define RRSR_MCS7					BIT(19)
++#define BRSR_AckShortPmb			BIT(23)		// CCK ACK: use Short Preamble or not.
+ 	RATR0			= 0x320, // Rate Adaptive Table register1
+ 	UFWP			= 0x318,
+ 	DRIVER_RSSI		= 0x32c,					// Driver tell Firmware current RSSI
+@@ -380,10 +381,10 @@ enum _RTL8192Usb_HW {
+ 	MacBlkCtrl		= 0x403, // Mac block on/off control register
+ 
+ 	EPROM_CMD		= 0xfe58,
+-#define Cmd9346CR_9356SEL	(1<<4)
+-#define EPROM_CMD_RESERVED_MASK (1<<5)
++#define Cmd9346CR_9356SEL	BIT(4)
++#define EPROM_CMD_RESERVED_MASK BIT(5)
+ #define EPROM_CMD_OPERATING_MODE_SHIFT 6
+-#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6))
++#define EPROM_CMD_OPERATING_MODE_MASK (BIT(7) | BIT(6))
+ #define EPROM_CMD_CONFIG 0x3
+ #define EPROM_CMD_NORMAL 0
+ #define EPROM_CMD_LOAD 1
+diff --git a/drivers/staging/rtl8192u/r819xU_cmdpkt.h b/drivers/staging/rtl8192u/r819xU_cmdpkt.h
+index cc8029a15df4..f490e253ee50 100644
+--- a/drivers/staging/rtl8192u/r819xU_cmdpkt.h
++++ b/drivers/staging/rtl8192u/r819xU_cmdpkt.h
+@@ -9,9 +9,9 @@
+ #define		CMPK_TX_RAHIS_SIZE		sizeof(cmpk_tx_rahis_t)
+ 
+ /* 2008/05/08 amy For USB constant. */
+-#define ISR_TxBcnOk		BIT27		/* Transmit Beacon OK */
+-#define ISR_TxBcnErr		BIT26		/* Transmit Beacon Error */
+-#define ISR_BcnTimerIntr	BIT13		/* Beacon Timer Interrupt */
++#define ISR_TxBcnOk		BIT(27)		/* Transmit Beacon OK */
++#define ISR_TxBcnErr		BIT(26)		/* Transmit Beacon Error */
++#define ISR_BcnTimerIntr	BIT(13)		/* Beacon Timer Interrupt */
+ 
+ 
+ /* Define element ID of command packet. */
+diff --git a/drivers/staging/rtl8192u/r819xU_phy.c b/drivers/staging/rtl8192u/r819xU_phy.c
+index e5dbaca9e518..70656441c145 100644
+--- a/drivers/staging/rtl8192u/r819xU_phy.c
++++ b/drivers/staging/rtl8192u/r819xU_phy.c
+@@ -1110,7 +1110,7 @@ bool rtl8192_SetRFPowerState(struct net_device *dev,
+ 		case eRfOn:
+ 			/* RF-A, RF-B */
+ 			/* enable RF-Chip A/B - 0x860[4] */
+-			rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4,
++			rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT(4),
+ 					 0x1);
+ 			/* analog to digital on - 0x88c[9:8] */
+ 			rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x300,
+@@ -1135,7 +1135,7 @@ bool rtl8192_SetRFPowerState(struct net_device *dev,
+ 		case eRfOff:
+ 			/* RF-A, RF-B */
+ 			/* disable RF-Chip A/B - 0x860[4] */
+-			rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4,
++			rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT(4),
+ 					 0x0);
+ 			/* analog to digital off, for power save */
+ 			rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00,

commit ffda203c0cf3b5b4648ba24c7d1ca34b9dcd4a3e
+Author: Anish Bhatt 
+Date:   Tue Sep 29 12:15:49 2015 -0700
+
+    wilc1000 : Use BIT() macro where possible
+    
+    Replace (1 << x) by BIT(x) as recommended by
+    checkpatch.pl
+    
+    Signed-off-by: Anish Bhatt 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c
+index 99de804a1da8..358bd2dd0a13 100644
+--- a/drivers/staging/wilc1000/host_interface.c
++++ b/drivers/staging/wilc1000/host_interface.c
+@@ -7316,7 +7316,7 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo)
+ 				pNewJoinBssParam->wmm_cap = true;
+ 
+ 				/* Check if Bit 7 is set indicating U-APSD capability */
+-				if (pu8IEs[index + 8] & (1 << 7))
++				if (pu8IEs[index + 8] & BIT(7))
+ 					pNewJoinBssParam->uapsd_cap = true;
+ 				index += pu8IEs[index + 1] + 2;
+ 				continue;
+@@ -7332,7 +7332,7 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo)
+ 				pNewJoinBssParam->u8Index = pu8IEs[index + 9];
+ 
+ 				/* Check if Bit 7 is set indicating Opss capability */
+-				if (pu8IEs[index + 10] & (1 << 7)) {
++				if (pu8IEs[index + 10] & BIT(7)) {
+ 					pNewJoinBssParam->u8OppEnable = 1;
+ 					pNewJoinBssParam->u8CtWindow = pu8IEs[index + 10];
+ 				} else
+diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h
+index c96fff998e26..0261b367f077 100644
+--- a/drivers/staging/wilc1000/host_interface.h
++++ b/drivers/staging/wilc1000/host_interface.h
+@@ -138,25 +138,25 @@ typedef struct {
+ } tstrCfgParamVal;
+ 
+ typedef enum {
+-	RETRY_SHORT		= 1 << 0,
+-	RETRY_LONG		= 1 << 1,
+-	FRAG_THRESHOLD		= 1 << 2,
+-	RTS_THRESHOLD		= 1 << 3,
+-	BSS_TYPE		= 1 << 4,
+-	AUTH_TYPE		= 1 << 5,
+-	AUTHEN_TIMEOUT		= 1 << 6,
+-	POWER_MANAGEMENT	= 1 << 7,
+-	PREAMBLE		= 1 << 8,
+-	SHORT_SLOT_ALLOWED	= 1 << 9,
+-	TXOP_PROT_DISABLE	= 1 << 10,
+-	BEACON_INTERVAL		= 1 << 11,
+-	DTIM_PERIOD		= 1 << 12,
+-	SITE_SURVEY		= 1 << 13,
+-	SITE_SURVEY_SCAN_TIME	= 1 << 14,
+-	ACTIVE_SCANTIME		= 1 << 15,
+-	PASSIVE_SCANTIME	= 1 << 16,
+-	CURRENT_TX_RATE		= 1 << 17,
+-	HT_ENABLE		= 1 << 18,
++	RETRY_SHORT		= BIT(0),
++	RETRY_LONG		= BIT(1),
++	FRAG_THRESHOLD		= BIT(2),
++	RTS_THRESHOLD		= BIT(3),
++	BSS_TYPE		= BIT(4),
++	AUTH_TYPE		= BIT(5),
++	AUTHEN_TIMEOUT		= BIT(6),
++	POWER_MANAGEMENT	= BIT(7),
++	PREAMBLE		= BIT(8),
++	SHORT_SLOT_ALLOWED	= BIT(9),
++	TXOP_PROT_DISABLE	= BIT(10),
++	BEACON_INTERVAL		= BIT(11),
++	DTIM_PERIOD		= BIT(12),
++	SITE_SURVEY		= BIT(13),
++	SITE_SURVEY_SCAN_TIME	= BIT(14),
++	ACTIVE_SCANTIME		= BIT(15),
++	PASSIVE_SCANTIME	= BIT(16),
++	CURRENT_TX_RATE		= BIT(17),
++	HT_ENABLE		= BIT(18),
+ } tenuCfgParam;
+ 
+ typedef struct {
+diff --git a/drivers/staging/wilc1000/linux_wlan_common.h b/drivers/staging/wilc1000/linux_wlan_common.h
+index 8ef80c6ffbad..2b76e41ebd4d 100644
+--- a/drivers/staging/wilc1000/linux_wlan_common.h
++++ b/drivers/staging/wilc1000/linux_wlan_common.h
+@@ -44,10 +44,10 @@ void wilc_debugfs_remove(void);
+ extern atomic_t REGION;
+ extern atomic_t DEBUG_LEVEL;
+ 
+-#define DEBUG           (1 << 0)
+-#define INFO            (1 << 1)
+-#define WRN             (1 << 2)
+-#define ERR             (1 << 3)
++#define DEBUG           BIT(0)
++#define INFO            BIT(1)
++#define WRN             BIT(2)
++#define ERR             BIT(3)
+ 
+ #define PRINT_D(region, ...)						\
+ 	do {								\
+diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c
+index c22b35e643c7..6da65e88c345 100644
+--- a/drivers/staging/wilc1000/wilc_sdio.c
++++ b/drivers/staging/wilc1000/wilc_sdio.c
+@@ -529,7 +529,7 @@ static int sdio_sync(void)
+ 		return 0;
+ 	}
+ 
+-	reg &= ~(1 << 8);
++	reg &= ~BIT(8);
+ 	if (!sdio_write_reg(WILC_MISC, reg)) {
+ 		g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed write misc reg...\n");
+ 		return 0;
+@@ -548,7 +548,7 @@ static int sdio_sync(void)
+ 			g_sdio.dPrint(N_ERR, "[wilc spi]: Failed read reg (%08x)...\n", WILC_PIN_MUX_0);
+ 			return 0;
+ 		}
+-		reg |= (1 << 8);
++		reg |= BIT(8);
+ 		ret = sdio_write_reg(WILC_PIN_MUX_0, reg);
+ 		if (!ret) {
+ 			g_sdio.dPrint(N_ERR, "[wilc spi]: Failed write reg (%08x)...\n", WILC_PIN_MUX_0);
+@@ -563,7 +563,7 @@ static int sdio_sync(void)
+ 			g_sdio.dPrint(N_ERR, "[wilc spi]: Failed read reg (%08x)...\n", WILC_INTR_ENABLE);
+ 			return 0;
+ 		}
+-		reg |= (1 << 16);
++		reg |= BIT(16);
+ 		ret = sdio_write_reg(WILC_INTR_ENABLE, reg);
+ 		if (!ret) {
+ 			g_sdio.dPrint(N_ERR, "[wilc spi]: Failed write reg (%08x)...\n", WILC_INTR_ENABLE);
+@@ -756,17 +756,17 @@ static int sdio_read_int(u32 *int_status)
+ 	cmd.data = 0;
+ 	g_sdio.sdio_cmd52(&cmd);
+ 
+-	if (cmd.data & (1 << 0))
++	if (cmd.data & BIT(0))
+ 		tmp |= INT_0;
+-	if (cmd.data & (1 << 2))
++	if (cmd.data & BIT(2))
+ 		tmp |= INT_1;
+-	if (cmd.data & (1 << 3))
++	if (cmd.data & BIT(3))
+ 		tmp |= INT_2;
+-	if (cmd.data & (1 << 4))
++	if (cmd.data & BIT(4))
+ 		tmp |= INT_3;
+-	if (cmd.data & (1 << 5))
++	if (cmd.data & BIT(5))
+ 		tmp |= INT_4;
+-	if (cmd.data & (1 << 6))
++	if (cmd.data & BIT(6))
+ 		tmp |= INT_5;
+ 	{
+ 		int i;
+@@ -810,7 +810,7 @@ static int sdio_clear_int_ext(u32 val)
+ 		{
+ 			u32 flags;
+ 
+-			flags = val & ((1 << MAX_NUN_INT_THRPT_ENH2) - 1);
++			flags = val & (BIT(MAX_NUN_INT_THRPT_ENH2) - 1);
+ 			reg = flags;
+ 		}
+ #else
+@@ -818,13 +818,13 @@ static int sdio_clear_int_ext(u32 val)
+ #endif
+ 		/* select VMM table 0 */
+ 		if ((val & SEL_VMM_TBL0) == SEL_VMM_TBL0)
+-			reg |= (1 << 5);
++			reg |= BIT(5);
+ 		/* select VMM table 1 */
+ 		if ((val & SEL_VMM_TBL1) == SEL_VMM_TBL1)
+-			reg |= (1 << 6);
++			reg |= BIT(6);
+ 		/* enable VMM */
+ 		if ((val & EN_VMM) == EN_VMM)
+-			reg |= (1 << 7);
++			reg |= BIT(7);
+ 		if (reg) {
+ 			sdio_cmd52_t cmd;
+ 
+@@ -848,7 +848,7 @@ static int sdio_clear_int_ext(u32 val)
+ 			/* Cannot clear multiple interrupts. Must clear each interrupt individually */
+ 			u32 flags;
+ 
+-			flags = val & ((1 << MAX_NUM_INT) - 1);
++			flags = val & (BIT(MAX_NUM_INT) - 1);
+ 			if (flags) {
+ 				int i;
+ 
+@@ -861,7 +861,7 @@ static int sdio_clear_int_ext(u32 val)
+ 						cmd.function = 0;
+ 						cmd.raw = 0;
+ 						cmd.address = 0xf8;
+-						cmd.data = (1 << i);
++						cmd.data = BIT(i);
+ 
+ 						ret = g_sdio.sdio_cmd52(&cmd);
+ 						if (!ret) {
+@@ -891,13 +891,13 @@ static int sdio_clear_int_ext(u32 val)
+ 			vmm_ctl = 0;
+ 			/* select VMM table 0 */
+ 			if ((val & SEL_VMM_TBL0) == SEL_VMM_TBL0)
+-				vmm_ctl |= (1 << 0);
++				vmm_ctl |= BIT(0);
+ 			/* select VMM table 1 */
+ 			if ((val & SEL_VMM_TBL1) == SEL_VMM_TBL1)
+-				vmm_ctl |= (1 << 1);
++				vmm_ctl |= BIT(1);
+ 			/* enable VMM */
+ 			if ((val & EN_VMM) == EN_VMM)
+-				vmm_ctl |= (1 << 2);
++				vmm_ctl |= BIT(2);
+ 
+ 			if (vmm_ctl) {
+ 				sdio_cmd52_t cmd;
+@@ -944,7 +944,7 @@ static int sdio_sync_ext(int nint /*  how mant interrupts to enable. */)
+ 		return 0;
+ 	}
+ 
+-	reg &= ~(1 << 8);
++	reg &= ~BIT(8);
+ 	if (!sdio_write_reg(WILC_MISC, reg)) {
+ 		g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed write misc reg...\n");
+ 		return 0;
+@@ -963,7 +963,7 @@ static int sdio_sync_ext(int nint /*  how mant interrupts to enable. */)
+ 			g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed read reg (%08x)...\n", WILC_PIN_MUX_0);
+ 			return 0;
+ 		}
+-		reg |= (1 << 8);
++		reg |= BIT(8);
+ 		ret = sdio_write_reg(WILC_PIN_MUX_0, reg);
+ 		if (!ret) {
+ 			g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed write reg (%08x)...\n", WILC_PIN_MUX_0);
+@@ -980,7 +980,7 @@ static int sdio_sync_ext(int nint /*  how mant interrupts to enable. */)
+ 		}
+ 
+ 		for (i = 0; (i < 5) && (nint > 0); i++, nint--)
+-			reg |= (1 << (27 + i));
++			reg |= BIT((27 + i));
+ 		ret = sdio_write_reg(WILC_INTR_ENABLE, reg);
+ 		if (!ret) {
+ 			g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed write reg (%08x)...\n", WILC_INTR_ENABLE);
+@@ -994,7 +994,7 @@ static int sdio_sync_ext(int nint /*  how mant interrupts to enable. */)
+ 			}
+ 
+ 			for (i = 0; (i < 3) && (nint > 0); i++, nint--)
+-				reg |= (1 << i);
++				reg |= BIT(i);
+ 
+ 			ret = sdio_read_reg(WILC_INTR2_ENABLE, ®);
+ 			if (!ret) {
+diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/wilc_spi.c
+index 8426641197ca..f7627701fb35 100644
+--- a/drivers/staging/wilc1000/wilc_spi.c
++++ b/drivers/staging/wilc1000/wilc_spi.c
+@@ -128,7 +128,7 @@ static int spi_cmd(u8 cmd, u32 adr, u32 data, u32 sz, u8 clockless)
+ 	case CMD_INTERNAL_READ:                 /* internal register read */
+ 		bc[1] = (u8)(adr >> 8);
+ 		if (clockless)
+-			bc[1] |= (1 << 7);
++			bc[1] |= BIT(7);
+ 		bc[2] = (u8)adr;
+ 		bc[3] = 0x00;
+ 		len = 5;
+@@ -179,7 +179,7 @@ static int spi_cmd(u8 cmd, u32 adr, u32 data, u32 sz, u8 clockless)
+ 	case CMD_INTERNAL_WRITE:                /* internal register write */
+ 		bc[1] = (u8)(adr >> 8);
+ 		if (clockless)
+-			bc[1] |= (1 << 7);
++			bc[1] |= BIT(7);
+ 		bc[2] = (u8)(adr);
+ 		bc[3] = (u8)(data >> 24);
+ 		bc[4] = (u8)(data >> 16);
+@@ -288,7 +288,7 @@ static int spi_cmd_complete(u8 cmd, u32 adr, u8 *b, u32 sz, u8 clockless)
+ 	case CMD_INTERNAL_READ:                 /* internal register read */
+ 		wb[1] = (u8)(adr >> 8);
+ 		if (clockless == 1)
+-			wb[1] |= (1 << 7);
++			wb[1] |= BIT(7);
+ 		wb[2] = (u8)adr;
+ 		wb[3] = 0x00;
+ 		len = 5;
+@@ -339,7 +339,7 @@ static int spi_cmd_complete(u8 cmd, u32 adr, u8 *b, u32 sz, u8 clockless)
+ 	case CMD_INTERNAL_WRITE:                /* internal register write */
+ 		wb[1] = (u8)(adr >> 8);
+ 		if (clockless == 1)
+-			wb[1] |= (1 << 7);
++			wb[1] |= BIT(7);
+ 		wb[2] = (u8)(adr);
+ 		wb[3] = b[3];
+ 		wb[4] = b[2];
+@@ -1048,7 +1048,7 @@ static int spi_sync(void)
+ 		PRINT_ER("[wilc spi]: Failed read reg (%08x)...\n", WILC_PIN_MUX_0);
+ 		return 0;
+ 	}
+-	reg |= (1 << 8);
++	reg |= BIT(8);
+ 	ret = spi_write_reg(WILC_PIN_MUX_0, reg);
+ 	if (!ret) {
+ 		PRINT_ER("[wilc spi]: Failed write reg (%08x)...\n", WILC_PIN_MUX_0);
+@@ -1063,7 +1063,7 @@ static int spi_sync(void)
+ 		PRINT_ER("[wilc spi]: Failed read reg (%08x)...\n", WILC_INTR_ENABLE);
+ 		return 0;
+ 	}
+-	reg |= (1 << 16);
++	reg |= BIT(16);
+ 	ret = spi_write_reg(WILC_INTR_ENABLE, reg);
+ 	if (!ret) {
+ 		PRINT_ER("[wilc spi]: Failed write reg (%08x)...\n", WILC_INTR_ENABLE);
+@@ -1254,7 +1254,7 @@ static int spi_clear_int_ext(u32 val)
+ 	} else {
+ 		u32 flags;
+ 
+-		flags = val & ((1 << MAX_NUM_INT) - 1);
++		flags = val & (BIT(MAX_NUM_INT) - 1);
+ 		if (flags) {
+ 			int i;
+ 
+@@ -1284,10 +1284,10 @@ static int spi_clear_int_ext(u32 val)
+ 			tbl_ctl = 0;
+ 			/* select VMM table 0 */
+ 			if ((val & SEL_VMM_TBL0) == SEL_VMM_TBL0)
+-				tbl_ctl |= (1 << 0);
++				tbl_ctl |= BIT(0);
+ 			/* select VMM table 1 */
+ 			if ((val & SEL_VMM_TBL1) == SEL_VMM_TBL1)
+-				tbl_ctl |= (1 << 1);
++				tbl_ctl |= BIT(1);
+ 
+ 			ret = spi_write_reg(WILC_VMM_TBL_CTL, tbl_ctl);
+ 			if (!ret) {
+@@ -1331,7 +1331,7 @@ static int spi_sync_ext(int nint /*  how mant interrupts to enable. */)
+ 		PRINT_ER("[wilc spi]: Failed read reg (%08x)...\n", WILC_PIN_MUX_0);
+ 		return 0;
+ 	}
+-	reg |= (1 << 8);
++	reg |= BIT(8);
+ 	ret = spi_write_reg(WILC_PIN_MUX_0, reg);
+ 	if (!ret) {
+ 		PRINT_ER("[wilc spi]: Failed write reg (%08x)...\n", WILC_PIN_MUX_0);
+@@ -1348,7 +1348,7 @@ static int spi_sync_ext(int nint /*  how mant interrupts to enable. */)
+ 	}
+ 
+ 	for (i = 0; (i < 5) && (nint > 0); i++, nint--) {
+-		reg |= (1 << (27 + i));
++		reg |= (BIT((27 + i)));
+ 	}
+ 	ret = spi_write_reg(WILC_INTR_ENABLE, reg);
+ 	if (!ret) {
+@@ -1363,7 +1363,7 @@ static int spi_sync_ext(int nint /*  how mant interrupts to enable. */)
+ 		}
+ 
+ 		for (i = 0; (i < 3) && (nint > 0); i++, nint--) {
+-			reg |= (1 << i);
++			reg |= BIT(i);
+ 		}
+ 
+ 		ret = spi_read_reg(WILC_INTR2_ENABLE, ®);
+diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h
+index af49c912558e..d3a03c68f803 100644
+--- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h
++++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h
+@@ -52,8 +52,8 @@
+ 
+ /*iftype*/
+ enum stats_flags {
+-	WILC_WFI_RX_PKT = 1 << 0,
+-	WILC_WFI_TX_PKT = 1 << 1,
++	WILC_WFI_RX_PKT = BIT(0),
++	WILC_WFI_TX_PKT = BIT(1),
+ };
+ 
+ struct WILC_WFI_stats {
+diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c
+index 93af5d430f91..428e94fdd716 100644
+--- a/drivers/staging/wilc1000/wilc_wlan.c
++++ b/drivers/staging/wilc1000/wilc_wlan.c
+@@ -649,7 +649,7 @@ static inline void chip_allow_sleep(void)
+ 	/* Clear bit 1 */
+ 	g_wlan.hif_func.hif_read_reg(0xf0, ®);
+ 
+-	g_wlan.hif_func.hif_write_reg(0xf0, reg & ~(1 << 0));
++	g_wlan.hif_func.hif_write_reg(0xf0, reg & ~BIT(0));
+ }
+ 
+ static inline void chip_wakeup(void)
+@@ -661,10 +661,10 @@ static inline void chip_wakeup(void)
+ 		do {
+ 			g_wlan.hif_func.hif_read_reg(1, ®);
+ 			/* Set bit 1 */
+-			g_wlan.hif_func.hif_write_reg(1, reg | (1 << 1));
++			g_wlan.hif_func.hif_write_reg(1, reg | BIT(1));
+ 
+ 			/* Clear bit 1*/
+-			g_wlan.hif_func.hif_write_reg(1, reg & ~(1 << 1));
++			g_wlan.hif_func.hif_write_reg(1, reg & ~BIT(1));
+ 
+ 			do {
+ 				/* Wait for the chip to stabilize*/
+@@ -681,7 +681,7 @@ static inline void chip_wakeup(void)
+ 		g_wlan.hif_func.hif_read_reg(0xf0, ®);
+ 		do {
+ 			/* Set bit 1 */
+-			g_wlan.hif_func.hif_write_reg(0xf0, reg | (1 << 0));
++			g_wlan.hif_func.hif_write_reg(0xf0, reg | BIT(0));
+ 
+ 			/* Check the clock status */
+ 			g_wlan.hif_func.hif_read_reg(0xf1, &clk_status_reg);
+@@ -704,7 +704,8 @@ static inline void chip_wakeup(void)
+ 			/* in case of failure, Reset the wakeup bit to introduce a new edge on the next loop */
+ 			if ((clk_status_reg & 0x1) == 0) {
+ 				/* Reset bit 0 */
+-				g_wlan.hif_func.hif_write_reg(0xf0, reg & (~(1 << 0)));
++				g_wlan.hif_func.hif_write_reg(0xf0, reg &
++							      (~BIT(0)));
+ 			}
+ 		} while ((clk_status_reg & 0x1) == 0);
+ 	}
+@@ -712,7 +713,7 @@ static inline void chip_wakeup(void)
+ 
+ 	if (genuChipPSstate == CHIP_SLEEPING_MANUAL) {
+ 		g_wlan.hif_func.hif_read_reg(0x1C0C, ®);
+-		reg &= ~(1 << 0);
++		reg &= ~BIT(0);
+ 		g_wlan.hif_func.hif_write_reg(0x1C0C, reg);
+ 
+ 		if (wilc_get_chipid(false) >= 0x1002b0) {
+@@ -720,11 +721,11 @@ static inline void chip_wakeup(void)
+ 			u32 val32;
+ 
+ 			g_wlan.hif_func.hif_read_reg(0x1e1c, &val32);
+-			val32 |= (1 << 6);
++			val32 |= BIT(6);
+ 			g_wlan.hif_func.hif_write_reg(0x1e1c, val32);
+ 
+ 			g_wlan.hif_func.hif_read_reg(0x1e9c, &val32);
+-			val32 |= (1 << 6);
++			val32 |= BIT(6);
+ 			g_wlan.hif_func.hif_write_reg(0x1e9c, val32);
+ 		}
+ 	}
+@@ -739,19 +740,19 @@ static inline void chip_wakeup(void)
+ 		if ((g_wlan.io_func.io_type & 0x1) == HIF_SPI) {
+ 			g_wlan.hif_func.hif_read_reg(1, ®);
+ 			/* Make sure bit 1 is 0 before we start. */
+-			g_wlan.hif_func.hif_write_reg(1, reg & ~(1 << 1));
++			g_wlan.hif_func.hif_write_reg(1, reg & ~BIT(1));
+ 			/* Set bit 1 */
+-			g_wlan.hif_func.hif_write_reg(1, reg | (1 << 1));
++			g_wlan.hif_func.hif_write_reg(1, reg | BIT(1));
+ 			/* Clear bit 1*/
+-			g_wlan.hif_func.hif_write_reg(1, reg  & ~(1 << 1));
++			g_wlan.hif_func.hif_write_reg(1, reg  & ~BIT(1));
+ 		} else if ((g_wlan.io_func.io_type & 0x1) == HIF_SDIO)	 {
+ 			/* Make sure bit 0 is 0 before we start. */
+ 			g_wlan.hif_func.hif_read_reg(0xf0, ®);
+-			g_wlan.hif_func.hif_write_reg(0xf0, reg & ~(1 << 0));
++			g_wlan.hif_func.hif_write_reg(0xf0, reg & ~BIT(0));
+ 			/* Set bit 1 */
+-			g_wlan.hif_func.hif_write_reg(0xf0, reg | (1 << 0));
++			g_wlan.hif_func.hif_write_reg(0xf0, reg | BIT(0));
+ 			/* Clear bit 1 */
+-			g_wlan.hif_func.hif_write_reg(0xf0, reg  & ~(1 << 0));
++			g_wlan.hif_func.hif_write_reg(0xf0, reg  & ~BIT(0));
+ 		}
+ 
+ 		do {
+@@ -769,7 +770,7 @@ static inline void chip_wakeup(void)
+ 
+ 	if (genuChipPSstate == CHIP_SLEEPING_MANUAL) {
+ 		g_wlan.hif_func.hif_read_reg(0x1C0C, ®);
+-		reg &= ~(1 << 0);
++		reg &= ~BIT(0);
+ 		g_wlan.hif_func.hif_write_reg(0x1C0C, reg);
+ 
+ 		if (wilc_get_chipid(false) >= 0x1002b0) {
+@@ -777,11 +778,11 @@ static inline void chip_wakeup(void)
+ 			u32 val32;
+ 
+ 			g_wlan.hif_func.hif_read_reg(0x1e1c, &val32);
+-			val32 |= (1 << 6);
++			val32 |= BIT(6);
+ 			g_wlan.hif_func.hif_write_reg(0x1e1c, val32);
+ 
+ 			g_wlan.hif_func.hif_read_reg(0x1e9c, &val32);
+-			val32 |= (1 << 6);
++			val32 |= BIT(6);
+ 			g_wlan.hif_func.hif_write_reg(0x1e9c, val32);
+ 		}
+ 	}
+@@ -873,7 +874,7 @@ static int wilc_wlan_handle_txq(u32 *pu32TxqCount)
+ 				PRINT_D(TX_DBG, "VMMTable entry size = %d\n", vmm_table[i]);
+ 
+ 				if (tqe->type == WILC_CFG_PKT) {
+-					vmm_table[i] |= (1 << 10);
++					vmm_table[i] |= BIT(10);
+ 					PRINT_D(TX_DBG, "VMMTable entry changed for CFG packet = %d\n", vmm_table[i]);
+ 				}
+ #ifdef BIG_ENDIAN
+@@ -998,7 +999,7 @@ static int wilc_wlan_handle_txq(u32 *pu32TxqCount)
+ 					wilc_debug(N_ERR, "[wilc txq]: fail can't read reg WILC_HOST_TX_CTRL..\n");
+ 					break;
+ 				}
+-				reg &= ~(1ul << 0);
++				reg &= ~BIT(0);
+ 				ret = p->hif_func.hif_write_reg(WILC_HOST_TX_CTRL, reg);
+ 				if (!ret) {
+ 					wilc_debug(N_ERR, "[wilc txq]: fail can't write reg WILC_HOST_TX_CTRL..\n");
+@@ -1039,9 +1040,9 @@ static int wilc_wlan_handle_txq(u32 *pu32TxqCount)
+ 				vmm_sz *= 4;
+ 				header = (tqe->type << 31) | (tqe->buffer_size << 15) | vmm_sz;
+ 				if (tqe->type == WILC_MGMT_PKT)
+-					header |= (1 << 30);
++					header |= BIT(30);
+ 				else
+-					header &= ~(1 << 30);
++					header &= ~BIT(30);
+ 
+ #ifdef BIG_ENDIAN
+ 				header = BYTE_SWAP(header);
+@@ -1405,7 +1406,7 @@ static int wilc_wlan_firmware_download(const u8 *buffer, u32 buffer_size)
+ 	u8 *dma_buffer;
+ 	int ret = 0;
+ 
+-	blksz = (1ul << 12);
++	blksz = BIT(12);
+ 	/* Allocate a DMA coherent  buffer. */
+ 
+ 	dma_buffer = kmalloc(blksz, GFP_KERNEL);
+@@ -1482,7 +1483,7 @@ static int wilc_wlan_start(void)
+ 	 **/
+ 	if (p->io_func.io_type == HIF_SDIO) {
+ 		reg = 0;
+-		reg |= (1 << 3); /* bug 4456 and 4557 */
++		reg |= BIT(3); /* bug 4456 and 4557 */
+ 	} else if (p->io_func.io_type == HIF_SPI) {
+ 		reg = 1;
+ 	}
+@@ -1557,13 +1558,13 @@ static int wilc_wlan_start(void)
+ 
+ 
+ 	p->hif_func.hif_read_reg(WILC_GLB_RESET_0, ®);
+-	if ((reg & (1ul << 10)) == (1ul << 10)) {
+-		reg &= ~(1ul << 10);
++	if ((reg & BIT(10)) == BIT(10)) {
++		reg &= ~BIT(10);
+ 		p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
+ 		p->hif_func.hif_read_reg(WILC_GLB_RESET_0, ®);
+ 	}
+ 
+-	reg |= (1ul << 10);
++	reg |= BIT(10);
+ 	ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
+ 	p->hif_func.hif_read_reg(WILC_GLB_RESET_0, ®);
+ 	release_bus(RELEASE_ONLY);
+@@ -1598,7 +1599,7 @@ static int wilc_wlan_stop(void)
+ 		return ret;
+ 	}
+ 
+-	reg &= ~(1 << 10);
++	reg &= ~BIT(10);
+ 
+ 
+ 	ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
+@@ -1619,9 +1620,9 @@ static int wilc_wlan_stop(void)
+ 		}
+ 		PRINT_D(GENERIC_DBG, "Read RESET Reg %x : Retry%d\n", reg, timeout);
+ 		/*Workaround to ensure that the chip is actually reset*/
+-		if ((reg & (1 << 10))) {
++		if ((reg & BIT(10))) {
+ 			PRINT_D(GENERIC_DBG, "Bit 10 not reset : Retry %d\n", timeout);
+-			reg &= ~(1 << 10);
++			reg &= ~BIT(10);
+ 			ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
+ 			timeout--;
+ 		} else {
+@@ -1637,10 +1638,11 @@ static int wilc_wlan_stop(void)
+ 		}
+ 
+ 	} while (timeout);
+-	reg = ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 8) | (1 << 9) | (1 << 26) | (1 << 29) | (1 << 30) | (1 << 31));
++	reg = (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(8) | BIT(9) | BIT(26) |
++	       BIT(29) | BIT(30) | BIT(31));
+ 
+ 	p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
+-	reg = ~(1 << 10);
++	reg = (u32)~BIT(10);
+ 
+ 	ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
+ 
+@@ -1868,7 +1870,7 @@ u32 init_chip(void)
+ 			wilc_debug(N_ERR, "[wilc start]: fail read reg 0x1118 ...\n");
+ 			return ret;
+ 		}
+-		reg |= (1 << 0);
++		reg |= BIT(0);
+ 		ret = g_wlan.hif_func.hif_write_reg(0x1118, reg);
+ 		if (!ret) {
+ 			wilc_debug(N_ERR, "[wilc start]: fail write reg 0x1118 ...\n");
+diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h
+index 60da18c9d938..1ed4e2c9d396 100644
+--- a/drivers/staging/wilc1000/wilc_wlan.h
++++ b/drivers/staging/wilc1000/wilc_wlan.h
+@@ -152,7 +152,7 @@
+ #endif
+ 
+ 
+-#define ABORT_INT   (1 << 31)
++#define ABORT_INT   BIT(31)
+ 
+ /*******************************************/
+ /*        E0 and later Interrupt flags.    */
+@@ -191,15 +191,15 @@
+ /* 7: Select VMM table 2                   */
+ /* 8: Enable VMM                           */
+ /*******************************************/
+-#define CLR_INT0             (1 << 0)
+-#define CLR_INT1             (1 << 1)
+-#define CLR_INT2             (1 << 2)
+-#define CLR_INT3             (1 << 3)
+-#define CLR_INT4             (1 << 4)
+-#define CLR_INT5             (1 << 5)
+-#define SEL_VMM_TBL0         (1 << 6)
+-#define SEL_VMM_TBL1         (1 << 7)
+-#define EN_VMM               (1 << 8)
++#define CLR_INT0             BIT(0)
++#define CLR_INT1             BIT(1)
++#define CLR_INT2             BIT(2)
++#define CLR_INT3             BIT(3)
++#define CLR_INT4             BIT(4)
++#define CLR_INT5             BIT(5)
++#define SEL_VMM_TBL0         BIT(6)
++#define SEL_VMM_TBL1         BIT(7)
++#define EN_VMM               BIT(8)
+ 
+ #define DATA_INT_EXT	INT_0
+ #define PLL_INT_EXT         INT_1

commit 65ead4ecb2d22a78592263ecba3decbc9df548dd
+Author: Anish Bhatt 
+Date:   Tue Sep 29 12:15:48 2015 -0700
+
+    wilc1000 : Remove leftover comment delimiters
+    
+    Remove leftover comment delimiters that were only partially removed
+    in a previous cleanup.
+    
+    Fixes : c3ca63728ad8 ("staging: wilc1000: remove useless comment")
+    Signed-off-by: Anish Bhatt 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c
+index be5e6f964d68..93af5d430f91 100644
+--- a/drivers/staging/wilc1000/wilc_wlan.c
++++ b/drivers/staging/wilc1000/wilc_wlan.c
+@@ -1637,13 +1637,12 @@ static int wilc_wlan_stop(void)
+ 		}
+ 
+ 	} while (timeout);
+-	reg = ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 8) | (1 << 9) | (1 << 26) | (1 << 29) | (1 << 30) | (1 << 31)); /**/
+-	/**/
+-	p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);                                 /**/
+-	reg = ~(1 << 10);                                                                                               /**/
+-	/**/
+-	ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);                                 /**/
+-/******************************************************************************/
++	reg = ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 8) | (1 << 9) | (1 << 26) | (1 << 29) | (1 << 30) | (1 << 31));
++
++	p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
++	reg = ~(1 << 10);
++
++	ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
+ 
+ 	release_bus(RELEASE_ALLOW_SLEEP);
+ 

commit 5cfe8c144524f7e1688b41c5dab46722be4a912b
+Author: Anish Bhatt 
+Date:   Fri Sep 25 00:45:15 2015 -0700
+
+    wilc1000 : Remove unused macro definitions
+    
+    Remove all unused TCP_*_MASK macro definitions
+    
+    Signed-off-by: Anish Bhatt 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c
+index 54d0d7100b02..be5e6f964d68 100644
+--- a/drivers/staging/wilc1000/wilc_wlan.c
++++ b/drivers/staging/wilc1000/wilc_wlan.c
+@@ -279,9 +279,6 @@ typedef struct {
+ struct Ack_session_info *Free_head;
+ struct Ack_session_info *Alloc_head;
+ 
+-#define TCP_FIN_MASK		(1 << 0)
+-#define TCP_SYN_MASK		(1 << 1)
+-#define TCP_Ack_MASK		(1 << 4)
+ #define NOT_TCP_ACK			(-1)
+ 
+ #define MAX_TCP_SESSION		25

commit 00b8c95b680791a72b4bb14dc371ff1f1daae39c
+Author: Chengyu Song 
+Date:   Tue Mar 24 20:18:49 2015 -0400
+
+    cifs: potential missing check for posix_lock_file_wait
+    
+    posix_lock_file_wait may fail under certain circumstances, and its result is
+    usually checked/returned. But given the complexity of cifs, I'm not sure if
+    the result is intentially left unchecked and always expected to succeed.
+    
+    Signed-off-by: Chengyu Song 
+    Acked-by: Jeff Layton 
+    Signed-off-by: Steve French 
+
+diff --git a/fs/cifs/file.c b/fs/cifs/file.c
+index 5cfa7129d876..3f50cee79df9 100644
+--- a/fs/cifs/file.c
++++ b/fs/cifs/file.c
+@@ -1552,8 +1552,8 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
+ 		rc = server->ops->mand_unlock_range(cfile, flock, xid);
+ 
+ out:
+-	if (flock->fl_flags & FL_POSIX)
+-		posix_lock_file_wait(file, flock);
++	if (flock->fl_flags & FL_POSIX && !rc)
++		rc = posix_lock_file_wait(file, flock);
+ 	return rc;
+ }
+ 

commit 27a4e3884e9c6497f96cc28256c3cdaa93d4cf97
+Author: Chengyu Song 
+Date:   Thu Apr 16 12:47:12 2015 -0700
+
+    hfsplus: incorrect return value
+    
+    In case of memory allocation error, the return should be -ENOMEM, instead
+    of -ENOSPC.
+    
+    Signed-off-by: Chengyu Song 
+    Reviewed-by: Sergei Antonov 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
+index f0235c1640af..3074609befc3 100644
+--- a/fs/hfsplus/dir.c
++++ b/fs/hfsplus/dir.c
+@@ -434,7 +434,7 @@ static int hfsplus_symlink(struct inode *dir, struct dentry *dentry,
+ {
+ 	struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb);
+ 	struct inode *inode;
+-	int res = -ENOSPC;
++	int res = -ENOMEM;
+ 
+ 	mutex_lock(&sbi->vh_mutex);
+ 	inode = hfsplus_new_inode(dir->i_sb, S_IFLNK | S_IRWXUGO);
+@@ -476,7 +476,7 @@ static int hfsplus_mknod(struct inode *dir, struct dentry *dentry,
+ {
+ 	struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb);
+ 	struct inode *inode;
+-	int res = -ENOSPC;
++	int res = -ENOMEM;
+ 
+ 	mutex_lock(&sbi->vh_mutex);
+ 	inode = hfsplus_new_inode(dir->i_sb, mode);

commit 13f244852f1197b623af2d3076fae197d2e038ec
+Author: Chengyu Song 
+Date:   Thu Apr 16 12:46:53 2015 -0700
+
+    hfs: incorrect return values
+    
+    In case of memory allocation error, the return should be -ENOMEM, instead
+    of -ENOSPC.
+    
+    Signed-off-by: Chengyu Song 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
+index 145566851e7a..36d1a6ae7655 100644
+--- a/fs/hfs/dir.c
++++ b/fs/hfs/dir.c
+@@ -197,7 +197,7 @@ static int hfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+ 
+ 	inode = hfs_new_inode(dir, &dentry->d_name, mode);
+ 	if (!inode)
+-		return -ENOSPC;
++		return -ENOMEM;
+ 
+ 	res = hfs_cat_create(inode->i_ino, dir, &dentry->d_name, inode);
+ 	if (res) {
+@@ -226,7 +226,7 @@ static int hfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+ 
+ 	inode = hfs_new_inode(dir, &dentry->d_name, S_IFDIR | mode);
+ 	if (!inode)
+-		return -ENOSPC;
++		return -ENOMEM;
+ 
+ 	res = hfs_cat_create(inode->i_ino, dir, &dentry->d_name, inode);
+ 	if (res) {

commit e2ac55b6a8e337fac7cc59c6f452caac92ab5ee6
+Author: Chengyu Song 
+Date:   Tue Apr 14 15:43:44 2015 -0700
+
+    ocfs2: incorrect check for debugfs returns
+    
+    debugfs_create_dir and debugfs_create_file may return -ENODEV when debugfs
+    is not configured, so the return value should be checked against
+    ERROR_VALUE as well, otherwise the later dereference of the dentry pointer
+    would crash the kernel.
+    
+    This patch tries to solve this problem by fixing certain checks. However,
+    I have that found other call sites are protected by #ifdef CONFIG_DEBUG_FS.
+    In current implementation, if CONFIG_DEBUG_FS is defined, then the above
+    two functions will never return any ERROR_VALUE. So another possibility
+    to fix this is to surround all the buggy checks/functions with the same
+    #ifdef CONFIG_DEBUG_FS. But I'm not sure if this would break any functionality,
+    as only OCFS2_FS_STATS declares dependency on DEBUG_FS.
+    
+    Signed-off-by: Chengyu Song 
+    Cc: Mark Fasheh 
+    Cc: Joel Becker 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
+index 16eff45727ee..8e19b9d7aba8 100644
+--- a/fs/ocfs2/cluster/heartbeat.c
++++ b/fs/ocfs2/cluster/heartbeat.c
+@@ -1312,7 +1312,9 @@ static int o2hb_debug_init(void)
+ 	int ret = -ENOMEM;
+ 
+ 	o2hb_debug_dir = debugfs_create_dir(O2HB_DEBUG_DIR, NULL);
+-	if (!o2hb_debug_dir) {
++	if (IS_ERR_OR_NULL(o2hb_debug_dir)) {
++		ret = o2hb_debug_dir ?
++			PTR_ERR(o2hb_debug_dir) : -ENOMEM;
+ 		mlog_errno(ret);
+ 		goto bail;
+ 	}
+@@ -1325,7 +1327,9 @@ static int o2hb_debug_init(void)
+ 						 sizeof(o2hb_live_node_bitmap),
+ 						 O2NM_MAX_NODES,
+ 						 o2hb_live_node_bitmap);
+-	if (!o2hb_debug_livenodes) {
++	if (IS_ERR_OR_NULL(o2hb_debug_livenodes)) {
++		ret = o2hb_debug_livenodes ?
++			PTR_ERR(o2hb_debug_livenodes) : -ENOMEM;
+ 		mlog_errno(ret);
+ 		goto bail;
+ 	}
+@@ -1338,7 +1342,9 @@ static int o2hb_debug_init(void)
+ 						   sizeof(o2hb_live_region_bitmap),
+ 						   O2NM_MAX_REGIONS,
+ 						   o2hb_live_region_bitmap);
+-	if (!o2hb_debug_liveregions) {
++	if (IS_ERR_OR_NULL(o2hb_debug_liveregions)) {
++		ret = o2hb_debug_liveregions ?
++			PTR_ERR(o2hb_debug_liveregions) : -ENOMEM;
+ 		mlog_errno(ret);
+ 		goto bail;
+ 	}
+@@ -1352,7 +1358,9 @@ static int o2hb_debug_init(void)
+ 					  sizeof(o2hb_quorum_region_bitmap),
+ 					  O2NM_MAX_REGIONS,
+ 					  o2hb_quorum_region_bitmap);
+-	if (!o2hb_debug_quorumregions) {
++	if (IS_ERR_OR_NULL(o2hb_debug_quorumregions)) {
++		ret = o2hb_debug_quorumregions ?
++			PTR_ERR(o2hb_debug_quorumregions) : -ENOMEM;
+ 		mlog_errno(ret);
+ 		goto bail;
+ 	}
+@@ -1366,7 +1374,9 @@ static int o2hb_debug_init(void)
+ 					  sizeof(o2hb_failed_region_bitmap),
+ 					  O2NM_MAX_REGIONS,
+ 					  o2hb_failed_region_bitmap);
+-	if (!o2hb_debug_failedregions) {
++	if (IS_ERR_OR_NULL(o2hb_debug_failedregions)) {
++		ret = o2hb_debug_failedregions ?
++			PTR_ERR(o2hb_debug_failedregions) : -ENOMEM;
+ 		mlog_errno(ret);
+ 		goto bail;
+ 	}
+@@ -2000,7 +2010,8 @@ static int o2hb_debug_region_init(struct o2hb_region *reg, struct dentry *dir)
+ 
+ 	reg->hr_debug_dir =
+ 		debugfs_create_dir(config_item_name(®->hr_item), dir);
+-	if (!reg->hr_debug_dir) {
++	if (IS_ERR_OR_NULL(reg->hr_debug_dir)) {
++		ret = reg->hr_debug_dir ? PTR_ERR(reg->hr_debug_dir) : -ENOMEM;
+ 		mlog_errno(ret);
+ 		goto bail;
+ 	}
+@@ -2013,7 +2024,9 @@ static int o2hb_debug_region_init(struct o2hb_region *reg, struct dentry *dir)
+ 					  O2HB_DB_TYPE_REGION_LIVENODES,
+ 					  sizeof(reg->hr_live_node_bitmap),
+ 					  O2NM_MAX_NODES, reg);
+-	if (!reg->hr_debug_livenodes) {
++	if (IS_ERR_OR_NULL(reg->hr_debug_livenodes)) {
++		ret = reg->hr_debug_livenodes ?
++			PTR_ERR(reg->hr_debug_livenodes) : -ENOMEM;
+ 		mlog_errno(ret);
+ 		goto bail;
+ 	}
+@@ -2025,7 +2038,9 @@ static int o2hb_debug_region_init(struct o2hb_region *reg, struct dentry *dir)
+ 					  sizeof(*(reg->hr_db_regnum)),
+ 					  O2HB_DB_TYPE_REGION_NUMBER,
+ 					  0, O2NM_MAX_NODES, reg);
+-	if (!reg->hr_debug_regnum) {
++	if (IS_ERR_OR_NULL(reg->hr_debug_regnum)) {
++		ret = reg->hr_debug_regnum ?
++			PTR_ERR(reg->hr_debug_regnum) : -ENOMEM;
+ 		mlog_errno(ret);
+ 		goto bail;
+ 	}
+@@ -2037,7 +2052,9 @@ static int o2hb_debug_region_init(struct o2hb_region *reg, struct dentry *dir)
+ 					  sizeof(*(reg->hr_db_elapsed_time)),
+ 					  O2HB_DB_TYPE_REGION_ELAPSED_TIME,
+ 					  0, 0, reg);
+-	if (!reg->hr_debug_elapsed_time) {
++	if (IS_ERR_OR_NULL(reg->hr_debug_elapsed_time)) {
++		ret = reg->hr_debug_elapsed_time ?
++			PTR_ERR(reg->hr_debug_elapsed_time) : -ENOMEM;
+ 		mlog_errno(ret);
+ 		goto bail;
+ 	}
+@@ -2049,13 +2066,16 @@ static int o2hb_debug_region_init(struct o2hb_region *reg, struct dentry *dir)
+ 					  sizeof(*(reg->hr_db_pinned)),
+ 					  O2HB_DB_TYPE_REGION_PINNED,
+ 					  0, 0, reg);
+-	if (!reg->hr_debug_pinned) {
++	if (IS_ERR_OR_NULL(reg->hr_debug_pinned)) {
++		ret = reg->hr_debug_pinned ?
++			PTR_ERR(reg->hr_debug_pinned) : -ENOMEM;
+ 		mlog_errno(ret);
+ 		goto bail;
+ 	}
+ 
+-	ret = 0;
++	return 0;
+ bail:
++	debugfs_remove_recursive(reg->hr_debug_dir);
+ 	return ret;
+ }
+ 
+diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
+index 11849a44dc5a..23adcbf374d3 100644
+--- a/fs/ocfs2/dlmglue.c
++++ b/fs/ocfs2/dlmglue.c
+@@ -2954,7 +2954,7 @@ static int ocfs2_dlm_init_debug(struct ocfs2_super *osb)
+ 							 osb->osb_debug_root,
+ 							 osb,
+ 							 &ocfs2_dlm_debug_fops);
+-	if (!dlm_debug->d_locking_state) {
++	if (IS_ERR_OR_NULL(dlm_debug->d_locking_state)) {
+ 		ret = -EINVAL;
+ 		mlog(ML_ERROR,
+ 		     "Unable to create locking state debugfs file.\n");
+diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
+index 26675185b886..fb43de586791 100644
+--- a/fs/ocfs2/super.c
++++ b/fs/ocfs2/super.c
+@@ -1112,7 +1112,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
+ 
+ 	osb->osb_debug_root = debugfs_create_dir(osb->uuid_str,
+ 						 ocfs2_debugfs_root);
+-	if (!osb->osb_debug_root) {
++	if (IS_ERR_OR_NULL(osb->osb_debug_root)) {
+ 		status = -EINVAL;
+ 		mlog(ML_ERROR, "Unable to create per-mount debugfs root.\n");
+ 		goto read_super_error;
+@@ -1122,7 +1122,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
+ 					    osb->osb_debug_root,
+ 					    osb,
+ 					    &ocfs2_osb_debug_fops);
+-	if (!osb->osb_ctxt) {
++	if (IS_ERR_OR_NULL(osb->osb_ctxt)) {
+ 		status = -EINVAL;
+ 		mlog_errno(status);
+ 		goto read_super_error;
+@@ -1606,8 +1606,9 @@ static int __init ocfs2_init(void)
+ 	}
+ 
+ 	ocfs2_debugfs_root = debugfs_create_dir("ocfs2", NULL);
+-	if (!ocfs2_debugfs_root) {
+-		status = -ENOMEM;
++	if (IS_ERR_OR_NULL(ocfs2_debugfs_root)) {
++		status = ocfs2_debugfs_root ?
++			PTR_ERR(ocfs2_debugfs_root) : -ENOMEM;
+ 		mlog(ML_ERROR, "Unable to create ocfs2 debugfs root.\n");
+ 		goto out4;
+ 	}

commit 629b8729cc2ca8fde7deb008dab09f3ad19fed52
+Author: Chengyu Song 
+Date:   Wed Mar 25 16:37:07 2015 -0400
+
+    nfsd: NFSD_FAULT_INJECTION depends on DEBUG_FS
+    
+    NFSD_FAULT_INJECTION depends on DEBUG_FS, otherwise the debugfs_create_*
+    interface may return unexpected error -ENODEV, and cause system crash.
+    
+    Signed-off-by: Chengyu Song 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig
+index 683bf718aead..8b87b7a0eab5 100644
+--- a/fs/nfsd/Kconfig
++++ b/fs/nfsd/Kconfig
+@@ -107,7 +107,7 @@ config NFSD_V4_SECURITY_LABEL
+ 
+ config NFSD_FAULT_INJECTION
+ 	bool "NFS server manual fault injection"
+-	depends on NFSD_V4 && DEBUG_KERNEL
++	depends on NFSD_V4 && DEBUG_KERNEL && DEBUG_FS
+ 	help
+ 	  This option enables support for manually injecting faults
+ 	  into the NFS server.  This is intended to be used for

commit 7b4ddfa7c9523a19fca30830f8b426964d359da2
+Author: Chengyu Song 
+Date:   Tue Mar 24 09:37:53 2015 -0500
+
+    gfs2: incorrect check for debugfs returns
+    
+    debugfs_create_dir and debugfs_create_file may return -ENODEV when debugfs
+    is not configured, so the return value should be checked against ERROR_VALUE
+    as well, otherwise the later dereference of the dentry pointer would crash
+    the kernel.
+    
+    Signed-off-by: Chengyu Song 
+    Signed-off-by: Bob Peterson 
+    Acked-by: Steven Whitehouse 
+
+diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
+index f42dffba056a..0fa8062f85a7 100644
+--- a/fs/gfs2/glock.c
++++ b/fs/gfs2/glock.c
+@@ -2047,34 +2047,41 @@ static const struct file_operations gfs2_sbstats_fops = {
+ 
+ int gfs2_create_debugfs_file(struct gfs2_sbd *sdp)
+ {
+-	sdp->debugfs_dir = debugfs_create_dir(sdp->sd_table_name, gfs2_root);
+-	if (!sdp->debugfs_dir)
+-		return -ENOMEM;
+-	sdp->debugfs_dentry_glocks = debugfs_create_file("glocks",
+-							 S_IFREG | S_IRUGO,
+-							 sdp->debugfs_dir, sdp,
+-							 &gfs2_glocks_fops);
+-	if (!sdp->debugfs_dentry_glocks)
++	struct dentry *dent;
++
++	dent = debugfs_create_dir(sdp->sd_table_name, gfs2_root);
++	if (IS_ERR_OR_NULL(dent))
++		goto fail;
++	sdp->debugfs_dir = dent;
++
++	dent = debugfs_create_file("glocks",
++				   S_IFREG | S_IRUGO,
++				   sdp->debugfs_dir, sdp,
++				   &gfs2_glocks_fops);
++	if (IS_ERR_OR_NULL(dent))
+ 		goto fail;
++	sdp->debugfs_dentry_glocks = dent;
+ 
+-	sdp->debugfs_dentry_glstats = debugfs_create_file("glstats",
+-							S_IFREG | S_IRUGO,
+-							sdp->debugfs_dir, sdp,
+-							&gfs2_glstats_fops);
+-	if (!sdp->debugfs_dentry_glstats)
++	dent = debugfs_create_file("glstats",
++				   S_IFREG | S_IRUGO,
++				   sdp->debugfs_dir, sdp,
++				   &gfs2_glstats_fops);
++	if (IS_ERR_OR_NULL(dent))
+ 		goto fail;
++	sdp->debugfs_dentry_glstats = dent;
+ 
+-	sdp->debugfs_dentry_sbstats = debugfs_create_file("sbstats",
+-							S_IFREG | S_IRUGO,
+-							sdp->debugfs_dir, sdp,
+-							&gfs2_sbstats_fops);
+-	if (!sdp->debugfs_dentry_sbstats)
++	dent = debugfs_create_file("sbstats",
++				   S_IFREG | S_IRUGO,
++				   sdp->debugfs_dir, sdp,
++				   &gfs2_sbstats_fops);
++	if (IS_ERR_OR_NULL(dent))
+ 		goto fail;
++	sdp->debugfs_dentry_sbstats = dent;
+ 
+ 	return 0;
+ fail:
+ 	gfs2_delete_debugfs_file(sdp);
+-	return -ENOMEM;
++	return dent ? PTR_ERR(dent) : -ENOMEM;
+ }
+ 
+ void gfs2_delete_debugfs_file(struct gfs2_sbd *sdp)
+@@ -2100,6 +2107,8 @@ void gfs2_delete_debugfs_file(struct gfs2_sbd *sdp)
+ int gfs2_register_debugfs(void)
+ {
+ 	gfs2_root = debugfs_create_dir("gfs2", NULL);
++	if (IS_ERR(gfs2_root))
++		return PTR_ERR(gfs2_root);
+ 	return gfs2_root ? 0 : -ENOMEM;
+ }
+ 

commit 26e726afe01c1c82072cf23a5ed89ce25f39d9f2
+Author: Chengyu Song 
+Date:   Tue Mar 24 18:12:56 2015 -0400
+
+    btrfs: incorrect handling for fiemap_fill_next_extent return
+    
+    fiemap_fill_next_extent returns 0 on success, -errno on error, 1 if this was
+    the last extent that will fit in user array. If 1 is returned, the return
+    value may eventually returned to user space, which should not happen, according
+    to manpage of ioctl.
+    
+    Signed-off-by: Chengyu Song 
+    Reviewed-by: David Sterba 
+    Reviewed-by: Liu Bo 
+    Signed-off-by: Chris Mason 
+
+diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
+index d688cfe5d496..782f3bc4651d 100644
+--- a/fs/btrfs/extent_io.c
++++ b/fs/btrfs/extent_io.c
+@@ -4514,8 +4514,11 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ 		}
+ 		ret = fiemap_fill_next_extent(fieinfo, em_start, disko,
+ 					      em_len, flags);
+-		if (ret)
++		if (ret) {
++			if (ret == 1)
++				ret = 0;
+ 			goto out_free;
++		}
+ 	}
+ out_free:
+ 	free_extent_map(em);

commit 20dafeefac97d1a690b113f2a954dc84fdf8f290
+Author: Byoungyoung Lee 
+Date:   Wed Mar 25 14:57:53 2015 +1100
+
+    xfs: xfs_mru_cache_insert() should use GFP_NOFS
+    
+    xfs_mru_cache_insert() can be called from within transaction context
+    during block allocation like so:
+    
+    write(2)
+      ....
+        xfs_get_blocks
+          xfs_iomap_write_direct
+            start transaction
+            xfs_bmapi_write
+              xfs_bmapi_allocate
+                xfs_bmap_btalloc
+                  xfs_bmap_btalloc_filestreams
+                    xfs_filestream_new_ag
+                      xfs_filestream_pick_ag
+                        xfs_mru_cache_insert
+                          radix_tree_preload(GFP_KERNEL)
+    
+    In this case, GFP_KERNEL is incorrect and can potentially lead to
+    deadlocks in memory reclaim. It should use GFP_NOFS allocations to
+    avoid lock recursion problems.
+    
+    [dchinner: rewrote commit message]
+    
+    Signed-off-by: Byoungyoung Lee 
+    Signed-off-by: Sanidhya Kashyap 
+    Reviewed-by: Dave Chinner 
+    Signed-off-by: Dave Chinner 
+
+diff --git a/fs/xfs/xfs_mru_cache.c b/fs/xfs/xfs_mru_cache.c
+index 30ecca3037e3..f8a674d7f092 100644
+--- a/fs/xfs/xfs_mru_cache.c
++++ b/fs/xfs/xfs_mru_cache.c
+@@ -437,7 +437,7 @@ xfs_mru_cache_insert(
+ 	if (!mru || !mru->lists)
+ 		return -EINVAL;
+ 
+-	if (radix_tree_preload(GFP_KERNEL))
++	if (radix_tree_preload(GFP_NOFS))
+ 		return -ENOMEM;
+ 
+ 	INIT_LIST_HEAD(&elem->list_node);

commit 6348675c4e3612e001860354fea78258e041d9a1
+Author: Pranith Kumar 
+Date:   Wed Apr 16 16:46:01 2014 -0400
+
+    torture: Remove unused definition
+    
+    The torture_parm() macro is the same as torture_param(), and torture_parm()
+    is not used.  This commit therefore removes torture_parm().
+    
+    Signed-off-by: Pranith Kumar 
+    Signed-off-by: Paul E. McKenney 
+    Reviewed-by: Josh Triplett 
+
+diff --git a/include/linux/torture.h b/include/linux/torture.h
+index f998574247fd..5ca58fcbaf1b 100644
+--- a/include/linux/torture.h
++++ b/include/linux/torture.h
+@@ -49,12 +49,6 @@
+ #define VERBOSE_TOROUT_ERRSTRING(s) \
+ 	do { if (verbose) pr_alert("%s" TORTURE_FLAG "!!! %s\n", torture_type, s); } while (0)
+ 
+-/* Definitions for a non-string torture-test module parameter. */
+-#define torture_parm(type, name, init, msg) \
+-	static type name = init; \
+-	module_param(name, type, 0444); \
+-	MODULE_PARM_DESC(name, msg);
+-
+ /* Definitions for online/offline exerciser. */
+ int torture_onoff_init(long ooholdoff, long oointerval);
+ char *torture_onoff_stats(char *page);

commit 8c96ae1dfa1608b92ddbf8bb285d7269832e4ac0
+Author: Pranith Kumar 
+Date:   Mon Apr 14 10:25:43 2014 -0700
+
+    rcu: Remove duplicate resched_cpu() declaration
+    
+    Signed-off-by: Pranith Kumar 
+    Signed-off-by: Paul E. McKenney 
+    Reviewed-by: Josh Triplett 
+
+diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
+index dbf43f5c86fa..ecd7e046de76 100644
+--- a/kernel/rcu/tree.c
++++ b/kernel/rcu/tree.c
+@@ -975,12 +975,6 @@ static void print_other_cpu_stall(struct rcu_state *rsp)
+ 	force_quiescent_state(rsp);  /* Kick them all. */
+ }
+ 
+-/*
+- * This function really isn't for public consumption, but RCU is special in
+- * that context switches can allow the state machine to make progress.
+- */
+-extern void resched_cpu(int cpu);
+-
+ static void print_cpu_stall(struct rcu_state *rsp)
+ {
+ 	int cpu;

commit 36bc5ee6a8d13333980fa54e97d3469d3d4cda98
+Author: Evan McClain 
+Date:   Tue Mar 9 19:20:58 2010 -0500
+
+    backlight: mbp_nvidia_bl - add five more MacBook variants
+    
+    This adds the MacBook 1,1 2,1 3,1 4,1 and 4,2 to the DMI tables.
+    
+    Signed-off-by: Evan McClain 
+    Signed-off-by: Richard Purdie 
+
+diff --git a/drivers/video/backlight/mbp_nvidia_bl.c b/drivers/video/backlight/mbp_nvidia_bl.c
+index 0881358eeace..1b5d3fe6bbbc 100644
+--- a/drivers/video/backlight/mbp_nvidia_bl.c
++++ b/drivers/video/backlight/mbp_nvidia_bl.c
+@@ -137,6 +137,51 @@ static int mbp_dmi_match(const struct dmi_system_id *id)
+ }
+ 
+ static const struct dmi_system_id __initdata mbp_device_table[] = {
++	{
++		.callback	= mbp_dmi_match,
++		.ident		= "MacBook 1,1",
++		.matches	= {
++			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
++			DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"),
++		},
++		.driver_data	= (void *)&intel_chipset_data,
++	},
++	{
++		.callback	= mbp_dmi_match,
++		.ident		= "MacBook 2,1",
++		.matches	= {
++			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
++			DMI_MATCH(DMI_PRODUCT_NAME, "MacBook2,1"),
++		},
++		.driver_data	= (void *)&intel_chipset_data,
++	},
++	{
++		.callback	= mbp_dmi_match,
++		.ident		= "MacBook 3,1",
++		.matches	= {
++			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
++			DMI_MATCH(DMI_PRODUCT_NAME, "MacBook3,1"),
++		},
++		.driver_data	= (void *)&intel_chipset_data,
++	},
++	{
++		.callback	= mbp_dmi_match,
++		.ident		= "MacBook 4,1",
++		.matches	= {
++			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
++			DMI_MATCH(DMI_PRODUCT_NAME, "MacBook4,1"),
++		},
++		.driver_data	= (void *)&intel_chipset_data,
++	},
++	{
++		.callback	= mbp_dmi_match,
++		.ident		= "MacBook 4,2",
++		.matches	= {
++			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
++			DMI_MATCH(DMI_PRODUCT_NAME, "MacBook4,2"),
++		},
++		.driver_data	= (void *)&intel_chipset_data,
++	},
+ 	{
+ 		.callback	= mbp_dmi_match,
+ 		.ident		= "MacBookPro 3,1",

commit 341e0cb593a2b7ec86dd6ca96c68eadc3f6fe1e6
+Author: Janak Desai 
+Date:   Mon Mar 28 11:09:46 2016 -0400
+
+    netlabel: fix a problem with netlbl_secattr_catmap_setrng()
+    
+    We try to be clever and set large chunks of the bitmap at once, when
+    possible; unfortunately we weren't very clever when we wrote the code
+    and messed up the if-conditional.  Fix this bug and restore proper
+    operation.
+    
+    Signed-off-by: Janak Desai 
+    Signed-off-by: Paul Moore 
+
+diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
+index 28cddc85b700..1325776daa27 100644
+--- a/net/netlabel/netlabel_kapi.c
++++ b/net/netlabel/netlabel_kapi.c
+@@ -677,7 +677,7 @@ int netlbl_catmap_setrng(struct netlbl_lsm_catmap **catmap,
+ 	u32 spot = start;
+ 
+ 	while (rc == 0 && spot <= end) {
+-		if (((spot & (BITS_PER_LONG - 1)) != 0) &&
++		if (((spot & (BITS_PER_LONG - 1)) == 0) &&
+ 		    ((end - spot) > BITS_PER_LONG)) {
+ 			rc = netlbl_catmap_setlong(catmap,
+ 						   spot,

commit c36f74e67fa12202dbcb4ad92c5ac844f9d36b98
+Author: Joshua Roys 
+Date:   Wed Feb 24 18:52:44 2010 -0500
+
+    netlabel: fix export of SELinux categories > 127
+    
+    This fixes corrupted CIPSO packets when SELinux categories greater than 127
+    are used.  The bug occured on the second (and later) loops through the
+    while; the inner for loop through the ebitmap->maps array used the same
+    index as the NetLabel catmap->bitmap array, even though the NetLabel bitmap
+    is twice as long as the SELinux bitmap.
+    
+    Signed-off-by: Joshua Roys 
+    Acked-by: Paul Moore 
+    Signed-off-by: James Morris 
+
+diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
+index 68c7348d1acc..04b6145d767f 100644
+--- a/security/selinux/ss/ebitmap.c
++++ b/security/selinux/ss/ebitmap.c
+@@ -128,7 +128,7 @@ int ebitmap_netlbl_export(struct ebitmap *ebmap,
+ 			cmap_idx = delta / NETLBL_CATMAP_MAPSIZE;
+ 			cmap_sft = delta % NETLBL_CATMAP_MAPSIZE;
+ 			c_iter->bitmap[cmap_idx]
+-				|= e_iter->maps[cmap_idx] << cmap_sft;
++				|= e_iter->maps[i] << cmap_sft;
+ 		}
+ 		e_iter = e_iter->next;
+ 	}

\ No newline at end of file diff --git a/detail/28.html b/detail/28.html new file mode 100644 index 0000000..2978212 --- /dev/null +++ b/detail/28.html @@ -0,0 +1,2276 @@ +

Patches contributed by University of Illinois, Urbana-Champaign


commit 9e09b75079e229b08f12a732712100fdb9af8cab
+Author: Ruowen Qin 
+Date:   Tue Sep 26 23:50:30 2023 -0500
+
+    samples/bpf: Add -fsanitize=bounds to userspace programs
+    
+    The sanitizer flag, which is supported by both clang and gcc, would make
+    it easier to debug array index out-of-bounds problems in these programs.
+    
+    Make the Makfile smarter to detect ubsan support from the compiler and
+    add the '-fsanitize=bounds' accordingly.
+    
+    Suggested-by: Mimi Zohar 
+    Signed-off-by: Jinghao Jia 
+    Signed-off-by: Jinghao Jia 
+    Signed-off-by: Ruowen Qin 
+    Signed-off-by: Andrii Nakryiko 
+    Tested-by: Jiri Olsa 
+    Acked-by: Jiri Olsa 
+    Link: https://lore.kernel.org/bpf/20230927045030.224548-2-ruowenq2@illinois.edu
+
+diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
+index 6c707ebcebb9..90af76fa9dd8 100644
+--- a/samples/bpf/Makefile
++++ b/samples/bpf/Makefile
+@@ -169,6 +169,9 @@ endif
+ TPROGS_CFLAGS += -Wall -O2
+ TPROGS_CFLAGS += -Wmissing-prototypes
+ TPROGS_CFLAGS += -Wstrict-prototypes
++TPROGS_CFLAGS += $(call try-run,\
++	printf "int main() { return 0; }" |\
++	$(CC) -Werror -fsanitize=bounds -x c - -o "$$TMP",-fsanitize=bounds,)
+ 
+ TPROGS_CFLAGS += -I$(objtree)/usr/include
+ TPROGS_CFLAGS += -I$(srctree)/tools/testing/selftests/bpf/

commit 81a5603a0f50fd7cf17ff21d106052215eaf2028
+Author: Arnav Rawat 
+Date:   Fri Nov 11 14:32:09 2022 +0000
+
+    platform/x86: ideapad-laptop: Fix interrupt storm on fn-lock toggle on some Yoga laptops
+    
+    Commit 3ae86d2d4704 ("platform/x86: ideapad-laptop: Fix Legion 5 Fn lock
+    LED") uses the WMI event-id for the fn-lock event on some Legion 5 laptops
+    to manually toggle the fn-lock LED because the EC does not do it itself.
+    However, the same WMI ID is also sent on some Yoga laptops. Here, setting
+    the fn-lock state is not valid behavior, and causes the EC to spam
+    interrupts until the laptop is rebooted.
+    
+    Add a set_fn_lock_led_list[] DMI-id list and only enable the workaround to
+    manually set the LED on models on this list.
+    
+    Link: https://bugzilla.kernel.org/show_bug.cgi?id=212671
+    Cc: Meng Dong 
+    Signed-off-by: Arnav Rawat 
+    Link: https://lore.kernel.org/r/12093851.O9o76ZdvQC@fedora
+    [hdegoede@redhat.com: Check DMI-id list only once and store the result]
+    Signed-off-by: Hans de Goede 
+
+diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
+index 33b3dfdd1b08..6c460cdc05bb 100644
+--- a/drivers/platform/x86/ideapad-laptop.c
++++ b/drivers/platform/x86/ideapad-laptop.c
+@@ -136,6 +136,7 @@ struct ideapad_private {
+ 		bool dytc                 : 1;
+ 		bool fan_mode             : 1;
+ 		bool fn_lock              : 1;
++		bool set_fn_lock_led      : 1;
+ 		bool hw_rfkill_switch     : 1;
+ 		bool kbd_bl               : 1;
+ 		bool touchpad_ctrl_via_ec : 1;
+@@ -1501,6 +1502,9 @@ static void ideapad_wmi_notify(u32 value, void *context)
+ 		ideapad_input_report(priv, value);
+ 		break;
+ 	case 208:
++		if (!priv->features.set_fn_lock_led)
++			break;
++
+ 		if (!eval_hals(priv->adev->handle, &result)) {
+ 			bool state = test_bit(HALS_FNLOCK_STATE_BIT, &result);
+ 
+@@ -1514,6 +1518,18 @@ static void ideapad_wmi_notify(u32 value, void *context)
+ }
+ #endif
+ 
++/* On some models we need to call exec_sals(SALS_FNLOCK_ON/OFF) to set the LED */
++static const struct dmi_system_id set_fn_lock_led_list[] = {
++	{
++		/* https://bugzilla.kernel.org/show_bug.cgi?id=212671 */
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++			DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Legion R7000P2020H"),
++		}
++	},
++	{}
++};
++
+ /*
+  * Some ideapads have a hardware rfkill switch, but most do not have one.
+  * Reading VPCCMD_R_RF always results in 0 on models without a hardware rfkill,
+@@ -1556,6 +1572,7 @@ static void ideapad_check_features(struct ideapad_private *priv)
+ 	acpi_handle handle = priv->adev->handle;
+ 	unsigned long val;
+ 
++	priv->features.set_fn_lock_led = dmi_check_system(set_fn_lock_led_list);
+ 	priv->features.hw_rfkill_switch = dmi_check_system(hw_rfkill_list);
+ 
+ 	/* Most ideapads with ELAN0634 touchpad don't use EC touchpad switch */

commit 0d8315dddd2899f519fe1ca3d4d5cdaf44ea421e
+Author: YiFei Zhu 
+Date:   Wed Nov 11 07:33:54 2020 -0600
+
+    seccomp/cache: Report cache data through /proc/pid/seccomp_cache
+    
+    Currently the kernel does not provide an infrastructure to translate
+    architecture numbers to a human-readable name. Translating syscall
+    numbers to syscall names is possible through FTRACE_SYSCALL
+    infrastructure but it does not provide support for compat syscalls.
+    
+    This will create a file for each PID as /proc/pid/seccomp_cache.
+    The file will be empty when no seccomp filters are loaded, or be
+    in the format of:
+      
+    where ALLOW means the cache is guaranteed to allow the syscall,
+    and filter means the cache will pass the syscall to the BPF filter.
+    
+    For the docker default profile on x86_64 it looks like:
+    x86_64 0 ALLOW
+    x86_64 1 ALLOW
+    x86_64 2 ALLOW
+    x86_64 3 ALLOW
+    [...]
+    x86_64 132 ALLOW
+    x86_64 133 ALLOW
+    x86_64 134 FILTER
+    x86_64 135 FILTER
+    x86_64 136 FILTER
+    x86_64 137 ALLOW
+    x86_64 138 ALLOW
+    x86_64 139 FILTER
+    x86_64 140 ALLOW
+    x86_64 141 ALLOW
+    [...]
+    
+    This file is guarded by CONFIG_SECCOMP_CACHE_DEBUG with a default
+    of N because I think certain users of seccomp might not want the
+    application to know which syscalls are definitely usable. For
+    the same reason, it is also guarded by CAP_SYS_ADMIN.
+    
+    Suggested-by: Jann Horn 
+    Link: https://lore.kernel.org/lkml/CAG48ez3Ofqp4crXGksLmZY6=fGrF_tWyUCg7PBkAetvbbOPeOA@mail.gmail.com/
+    Signed-off-by: YiFei Zhu 
+    Signed-off-by: Kees Cook 
+    Link: https://lore.kernel.org/r/94e663fa53136f5a11f432c661794d1ee7060779.1605101222.git.yifeifz2@illinois.edu
+
+diff --git a/arch/Kconfig b/arch/Kconfig
+index 56b6ccc0e32d..35c9463b7d10 100644
+--- a/arch/Kconfig
++++ b/arch/Kconfig
+@@ -486,6 +486,9 @@ config HAVE_ARCH_SECCOMP_FILTER
+ 	  - secure_computing return value is checked and a return value of -1
+ 	    results in the system call being skipped immediately.
+ 	  - seccomp syscall wired up
++	  - if !HAVE_SPARSE_SYSCALL_NR, have SECCOMP_ARCH_NATIVE,
++	    SECCOMP_ARCH_NATIVE_NR, SECCOMP_ARCH_NATIVE_NAME defined. If
++	    COMPAT is supported, have the SECCOMP_ARCH_COMPAT* defines too.
+ 
+ config SECCOMP
+ 	prompt "Enable seccomp to safely execute untrusted bytecode"
+@@ -514,6 +517,20 @@ config SECCOMP_FILTER
+ 
+ 	  See Documentation/userspace-api/seccomp_filter.rst for details.
+ 
++config SECCOMP_CACHE_DEBUG
++	bool "Show seccomp filter cache status in /proc/pid/seccomp_cache"
++	depends on SECCOMP_FILTER && !HAVE_SPARSE_SYSCALL_NR
++	depends on PROC_FS
++	help
++	  This enables the /proc/pid/seccomp_cache interface to monitor
++	  seccomp cache data. The file format is subject to change. Reading
++	  the file requires CAP_SYS_ADMIN.
++
++	  This option is for debugging only. Enabling presents the risk that
++	  an adversary may be able to infer the seccomp filter logic.
++
++	  If unsure, say N.
++
+ config HAVE_ARCH_STACKLEAK
+ 	bool
+ 	help
+diff --git a/fs/proc/base.c b/fs/proc/base.c
+index b362523a9829..8a7d682ba881 100644
+--- a/fs/proc/base.c
++++ b/fs/proc/base.c
+@@ -3263,6 +3263,9 @@ static const struct pid_entry tgid_base_stuff[] = {
+ #ifdef CONFIG_PROC_PID_ARCH_STATUS
+ 	ONE("arch_status", S_IRUGO, proc_pid_arch_status),
+ #endif
++#ifdef CONFIG_SECCOMP_CACHE_DEBUG
++	ONE("seccomp_cache", S_IRUSR, proc_pid_seccomp_cache),
++#endif
+ };
+ 
+ static int proc_tgid_base_readdir(struct file *file, struct dir_context *ctx)
+@@ -3592,6 +3595,9 @@ static const struct pid_entry tid_base_stuff[] = {
+ #ifdef CONFIG_PROC_PID_ARCH_STATUS
+ 	ONE("arch_status", S_IRUGO, proc_pid_arch_status),
+ #endif
++#ifdef CONFIG_SECCOMP_CACHE_DEBUG
++	ONE("seccomp_cache", S_IRUSR, proc_pid_seccomp_cache),
++#endif
+ };
+ 
+ static int proc_tid_base_readdir(struct file *file, struct dir_context *ctx)
+diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
+index 02aef2844c38..76963ec4641a 100644
+--- a/include/linux/seccomp.h
++++ b/include/linux/seccomp.h
+@@ -121,4 +121,11 @@ static inline long seccomp_get_metadata(struct task_struct *task,
+ 	return -EINVAL;
+ }
+ #endif /* CONFIG_SECCOMP_FILTER && CONFIG_CHECKPOINT_RESTORE */
++
++#ifdef CONFIG_SECCOMP_CACHE_DEBUG
++struct seq_file;
++
++int proc_pid_seccomp_cache(struct seq_file *m, struct pid_namespace *ns,
++			   struct pid *pid, struct task_struct *task);
++#endif
+ #endif /* _LINUX_SECCOMP_H */
+diff --git a/kernel/seccomp.c b/kernel/seccomp.c
+index d8cf468dbe1e..76f524e320b1 100644
+--- a/kernel/seccomp.c
++++ b/kernel/seccomp.c
+@@ -553,6 +553,9 @@ void seccomp_filter_release(struct task_struct *tsk)
+ {
+ 	struct seccomp_filter *orig = tsk->seccomp.filter;
+ 
++	/* We are effectively holding the siglock by not having any sighand. */
++	WARN_ON(tsk->sighand != NULL);
++
+ 	/* Detach task from its filter tree. */
+ 	tsk->seccomp.filter = NULL;
+ 	__seccomp_filter_release(orig);
+@@ -2335,3 +2338,59 @@ static int __init seccomp_sysctl_init(void)
+ device_initcall(seccomp_sysctl_init)
+ 
+ #endif /* CONFIG_SYSCTL */
++
++#ifdef CONFIG_SECCOMP_CACHE_DEBUG
++/* Currently CONFIG_SECCOMP_CACHE_DEBUG implies SECCOMP_ARCH_NATIVE */
++static void proc_pid_seccomp_cache_arch(struct seq_file *m, const char *name,
++					const void *bitmap, size_t bitmap_size)
++{
++	int nr;
++
++	for (nr = 0; nr < bitmap_size; nr++) {
++		bool cached = test_bit(nr, bitmap);
++		char *status = cached ? "ALLOW" : "FILTER";
++
++		seq_printf(m, "%s %d %s\n", name, nr, status);
++	}
++}
++
++int proc_pid_seccomp_cache(struct seq_file *m, struct pid_namespace *ns,
++			   struct pid *pid, struct task_struct *task)
++{
++	struct seccomp_filter *f;
++	unsigned long flags;
++
++	/*
++	 * We don't want some sandboxed process to know what their seccomp
++	 * filters consist of.
++	 */
++	if (!file_ns_capable(m->file, &init_user_ns, CAP_SYS_ADMIN))
++		return -EACCES;
++
++	if (!lock_task_sighand(task, &flags))
++		return -ESRCH;
++
++	f = READ_ONCE(task->seccomp.filter);
++	if (!f) {
++		unlock_task_sighand(task, &flags);
++		return 0;
++	}
++
++	/* prevent filter from being freed while we are printing it */
++	__get_seccomp_filter(f);
++	unlock_task_sighand(task, &flags);
++
++	proc_pid_seccomp_cache_arch(m, SECCOMP_ARCH_NATIVE_NAME,
++				    f->cache.allow_native,
++				    SECCOMP_ARCH_NATIVE_NR);
++
++#ifdef SECCOMP_ARCH_COMPAT
++	proc_pid_seccomp_cache_arch(m, SECCOMP_ARCH_COMPAT_NAME,
++				    f->cache.allow_compat,
++				    SECCOMP_ARCH_COMPAT_NR);
++#endif /* SECCOMP_ARCH_COMPAT */
++
++	__put_seccomp_filter(f);
++	return 0;
++}
++#endif /* CONFIG_SECCOMP_CACHE_DEBUG */

commit 445247b02342a05b7d528bba6d85d2d418875b69
+Author: YiFei Zhu 
+Date:   Wed Nov 11 07:33:53 2020 -0600
+
+    xtensa: Enable seccomp architecture tracking
+    
+    To enable seccomp constant action bitmaps, we need to have a static
+    mapping to the audit architecture and system call table size. Add these
+    for xtensa.
+    
+    Signed-off-by: YiFei Zhu 
+    Signed-off-by: Kees Cook 
+    Link: https://lore.kernel.org/r/79669648ba167d668ea6ffb4884250abcd5ed254.1605101222.git.yifeifz2@illinois.edu
+
+diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
+index c59c42a1221a..9718e9593564 100644
+--- a/arch/xtensa/include/asm/Kbuild
++++ b/arch/xtensa/include/asm/Kbuild
+@@ -7,5 +7,4 @@ generic-y += mcs_spinlock.h
+ generic-y += param.h
+ generic-y += qrwlock.h
+ generic-y += qspinlock.h
+-generic-y += seccomp.h
+ generic-y += user.h
+diff --git a/arch/xtensa/include/asm/seccomp.h b/arch/xtensa/include/asm/seccomp.h
+new file mode 100644
+index 000000000000..f1cb6b0a9e1f
+--- /dev/null
++++ b/arch/xtensa/include/asm/seccomp.h
+@@ -0,0 +1,11 @@
++/* SPDX-License-Identifier: GPL-2.0-only */
++#ifndef _ASM_SECCOMP_H
++#define _ASM_SECCOMP_H
++
++#include 
++
++#define SECCOMP_ARCH_NATIVE		AUDIT_ARCH_XTENSA
++#define SECCOMP_ARCH_NATIVE_NR		NR_syscalls
++#define SECCOMP_ARCH_NATIVE_NAME	"xtensa"
++
++#endif /* _ASM_SECCOMP_H */

commit 4c18bc054bffe415bec9e0edaa9ff1a84c1a6973
+Author: YiFei Zhu 
+Date:   Wed Nov 11 07:33:52 2020 -0600
+
+    sh: Enable seccomp architecture tracking
+    
+    To enable seccomp constant action bitmaps, we need to have a static
+    mapping to the audit architecture and system call table size. Add these
+    for sh.
+    
+    Signed-off-by: YiFei Zhu 
+    Signed-off-by: Kees Cook 
+    Link: https://lore.kernel.org/r/61ae084cd4783b9b50860d9dedb4a348cf1b7b6f.1605101222.git.yifeifz2@illinois.edu
+
+diff --git a/arch/sh/include/asm/seccomp.h b/arch/sh/include/asm/seccomp.h
+index 54111e4d32b8..d4578395fd66 100644
+--- a/arch/sh/include/asm/seccomp.h
++++ b/arch/sh/include/asm/seccomp.h
+@@ -8,4 +8,14 @@
+ #define __NR_seccomp_exit __NR_exit
+ #define __NR_seccomp_sigreturn __NR_rt_sigreturn
+ 
++#ifdef CONFIG_CPU_LITTLE_ENDIAN
++#define __SECCOMP_ARCH_LE		__AUDIT_ARCH_LE
++#else
++#define __SECCOMP_ARCH_LE		0
++#endif
++
++#define SECCOMP_ARCH_NATIVE		(AUDIT_ARCH_SH | __SECCOMP_ARCH_LE)
++#define SECCOMP_ARCH_NATIVE_NR		NR_syscalls
++#define SECCOMP_ARCH_NATIVE_NAME	"sh"
++
+ #endif /* __ASM_SECCOMP_H */

commit c09058eda2654c37fd7ac28c2004c3aae8b988e9
+Author: YiFei Zhu 
+Date:   Wed Nov 11 07:33:51 2020 -0600
+
+    s390: Enable seccomp architecture tracking
+    
+    To enable seccomp constant action bitmaps, we need to have a static
+    mapping to the audit architecture and system call table size. Add these
+    for s390.
+    
+    Signed-off-by: YiFei Zhu 
+    Acked-by: Heiko Carstens 
+    Signed-off-by: Kees Cook 
+    Link: https://lore.kernel.org/r/a381b10aa2c5b1e583642f3cd46ced842d9d4ce5.1605101222.git.yifeifz2@illinois.edu
+
+diff --git a/arch/s390/include/asm/seccomp.h b/arch/s390/include/asm/seccomp.h
+index 795bbe0d7ca6..71d46f0ba97b 100644
+--- a/arch/s390/include/asm/seccomp.h
++++ b/arch/s390/include/asm/seccomp.h
+@@ -16,4 +16,13 @@
+ 
+ #include 
+ 
++#define SECCOMP_ARCH_NATIVE		AUDIT_ARCH_S390X
++#define SECCOMP_ARCH_NATIVE_NR		NR_syscalls
++#define SECCOMP_ARCH_NATIVE_NAME	"s390x"
++#ifdef CONFIG_COMPAT
++# define SECCOMP_ARCH_COMPAT		AUDIT_ARCH_S390
++# define SECCOMP_ARCH_COMPAT_NR		NR_syscalls
++# define SECCOMP_ARCH_COMPAT_NAME	"s390"
++#endif
++
+ #endif	/* _ASM_S390_SECCOMP_H */

commit 673a11a7e4152b101bad6851c4e4c34c7c6d6dde
+Author: YiFei Zhu 
+Date:   Wed Nov 11 07:33:50 2020 -0600
+
+    riscv: Enable seccomp architecture tracking
+    
+    To enable seccomp constant action bitmaps, we need to have a static
+    mapping to the audit architecture and system call table size. Add these
+    for riscv.
+    
+    Signed-off-by: YiFei Zhu 
+    Signed-off-by: Kees Cook 
+    Link: https://lore.kernel.org/r/58ef925d00505cbb77478fa6bd2b48ab2d902460.1605101222.git.yifeifz2@illinois.edu
+
+diff --git a/arch/riscv/include/asm/seccomp.h b/arch/riscv/include/asm/seccomp.h
+index bf7744ee3b3d..c7ee6a3507be 100644
+--- a/arch/riscv/include/asm/seccomp.h
++++ b/arch/riscv/include/asm/seccomp.h
+@@ -7,4 +7,14 @@
+ 
+ #include 
+ 
++#ifdef CONFIG_64BIT
++# define SECCOMP_ARCH_NATIVE		AUDIT_ARCH_RISCV64
++# define SECCOMP_ARCH_NATIVE_NR		NR_syscalls
++# define SECCOMP_ARCH_NATIVE_NAME	"riscv64"
++#else /* !CONFIG_64BIT */
++# define SECCOMP_ARCH_NATIVE		AUDIT_ARCH_RISCV32
++# define SECCOMP_ARCH_NATIVE_NR		NR_syscalls
++# define SECCOMP_ARCH_NATIVE_NAME	"riscv32"
++#endif
++
+ #endif /* _ASM_SECCOMP_H */

commit e7bcb4622ddf4473da6c03fa8423919a568c57dc
+Author: YiFei Zhu 
+Date:   Wed Nov 11 07:33:49 2020 -0600
+
+    powerpc: Enable seccomp architecture tracking
+    
+    To enable seccomp constant action bitmaps, we need to have a static
+    mapping to the audit architecture and system call table size. Add these
+    for powerpc.
+    
+    __LITTLE_ENDIAN__ is used here instead of CONFIG_CPU_LITTLE_ENDIAN
+    to keep it consistent with asm/syscall.h.
+    
+    Signed-off-by: YiFei Zhu 
+    Signed-off-by: Kees Cook 
+    Link: https://lore.kernel.org/r/0b64925362671cdaa26d01bfe50b3ba5e164adfd.1605101222.git.yifeifz2@illinois.edu
+
+diff --git a/arch/powerpc/include/asm/seccomp.h b/arch/powerpc/include/asm/seccomp.h
+index 51209f6071c5..ac2033f134f0 100644
+--- a/arch/powerpc/include/asm/seccomp.h
++++ b/arch/powerpc/include/asm/seccomp.h
+@@ -8,4 +8,27 @@
+ 
+ #include 
+ 
++#ifdef __LITTLE_ENDIAN__
++#define __SECCOMP_ARCH_LE		__AUDIT_ARCH_LE
++#define __SECCOMP_ARCH_LE_NAME		"le"
++#else
++#define __SECCOMP_ARCH_LE		0
++#define __SECCOMP_ARCH_LE_NAME
++#endif
++
++#ifdef CONFIG_PPC64
++# define SECCOMP_ARCH_NATIVE		(AUDIT_ARCH_PPC64 | __SECCOMP_ARCH_LE)
++# define SECCOMP_ARCH_NATIVE_NR		NR_syscalls
++# define SECCOMP_ARCH_NATIVE_NAME	"ppc64" __SECCOMP_ARCH_LE_NAME
++# ifdef CONFIG_COMPAT
++#  define SECCOMP_ARCH_COMPAT		(AUDIT_ARCH_PPC | __SECCOMP_ARCH_LE)
++#  define SECCOMP_ARCH_COMPAT_NR	NR_syscalls
++#  define SECCOMP_ARCH_COMPAT_NAME	"ppc" __SECCOMP_ARCH_LE_NAME
++# endif
++#else /* !CONFIG_PPC64 */
++# define SECCOMP_ARCH_NATIVE		(AUDIT_ARCH_PPC | __SECCOMP_ARCH_LE)
++# define SECCOMP_ARCH_NATIVE_NR		NR_syscalls
++# define SECCOMP_ARCH_NATIVE_NAME	"ppc" __SECCOMP_ARCH_LE_NAME
++#endif
++
+ #endif	/* _ASM_POWERPC_SECCOMP_H */

commit 6aa7923c8737d1f8fd2a06154155d68dec646464
+Author: YiFei Zhu 
+Date:   Wed Nov 11 07:33:48 2020 -0600
+
+    parisc: Enable seccomp architecture tracking
+    
+    To enable seccomp constant action bitmaps, we need to have a static
+    mapping to the audit architecture and system call table size. Add these
+    for parisc.
+    
+    Signed-off-by: YiFei Zhu 
+    Acked-by: Helge Deller 
+    Signed-off-by: Kees Cook 
+    Link: https://lore.kernel.org/r/9bb86c546eda753adf5270425e7353202dbce87c.1605101222.git.yifeifz2@illinois.edu
+
+diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
+index e3ee5c0bfe80..f16c4db80116 100644
+--- a/arch/parisc/include/asm/Kbuild
++++ b/arch/parisc/include/asm/Kbuild
+@@ -5,5 +5,4 @@ generated-y += syscall_table_c32.h
+ generic-y += kvm_para.h
+ generic-y += local64.h
+ generic-y += mcs_spinlock.h
+-generic-y += seccomp.h
+ generic-y += user.h
+diff --git a/arch/parisc/include/asm/seccomp.h b/arch/parisc/include/asm/seccomp.h
+new file mode 100644
+index 000000000000..b058b2220322
+--- /dev/null
++++ b/arch/parisc/include/asm/seccomp.h
+@@ -0,0 +1,22 @@
++/* SPDX-License-Identifier: GPL-2.0-only */
++#ifndef _ASM_SECCOMP_H
++#define _ASM_SECCOMP_H
++
++#include 
++
++#ifdef CONFIG_64BIT
++# define SECCOMP_ARCH_NATIVE		AUDIT_ARCH_PARISC64
++# define SECCOMP_ARCH_NATIVE_NR		NR_syscalls
++# define SECCOMP_ARCH_NATIVE_NAME	"parisc64"
++# ifdef CONFIG_COMPAT
++#  define SECCOMP_ARCH_COMPAT		AUDIT_ARCH_PARISC
++#  define SECCOMP_ARCH_COMPAT_NR	NR_syscalls
++#  define SECCOMP_ARCH_COMPAT_NAME	"parisc"
++# endif
++#else /* !CONFIG_64BIT */
++# define SECCOMP_ARCH_NATIVE		AUDIT_ARCH_PARISC
++# define SECCOMP_ARCH_NATIVE_NR		NR_syscalls
++# define SECCOMP_ARCH_NATIVE_NAME	"parisc"
++#endif
++
++#endif /* _ASM_SECCOMP_H */

commit 6e9ae6f98809e0d123ff4d769ba2e6f652119138
+Author: YiFei Zhu 
+Date:   Wed Nov 11 07:33:47 2020 -0600
+
+    csky: Enable seccomp architecture tracking
+    
+    To enable seccomp constant action bitmaps, we need to have a static
+    mapping to the audit architecture and system call table size. Add these
+    for csky.
+    
+    Signed-off-by: YiFei Zhu 
+    Signed-off-by: Kees Cook 
+    Link: https://lore.kernel.org/r/f9219026d4803b22f3e57e3768b4e42e004ef236.1605101222.git.yifeifz2@illinois.edu
+
+diff --git a/arch/csky/include/asm/Kbuild b/arch/csky/include/asm/Kbuild
+index 64876e59e2ef..93372255984d 100644
+--- a/arch/csky/include/asm/Kbuild
++++ b/arch/csky/include/asm/Kbuild
+@@ -4,6 +4,5 @@ generic-y += gpio.h
+ generic-y += kvm_para.h
+ generic-y += local64.h
+ generic-y += qrwlock.h
+-generic-y += seccomp.h
+ generic-y += user.h
+ generic-y += vmlinux.lds.h
+diff --git a/arch/csky/include/asm/seccomp.h b/arch/csky/include/asm/seccomp.h
+new file mode 100644
+index 000000000000..d33e758126fb
+--- /dev/null
++++ b/arch/csky/include/asm/seccomp.h
+@@ -0,0 +1,11 @@
++/* SPDX-License-Identifier: GPL-2.0-only */
++#ifndef _ASM_SECCOMP_H
++#define _ASM_SECCOMP_H
++
++#include 
++
++#define SECCOMP_ARCH_NATIVE		AUDIT_ARCH_CSKY
++#define SECCOMP_ARCH_NATIVE_NR		NR_syscalls
++#define SECCOMP_ARCH_NATIVE_NAME	"csky"
++
++#endif /* _ASM_SECCOMP_H */

commit 8e01b51a31a1e08e2c3e8fcc0ef6790441be2f61
+Author: YiFei Zhu 
+Date:   Sun Oct 11 10:47:43 2020 -0500
+
+    seccomp/cache: Add "emulator" to check if filter is constant allow
+    
+    SECCOMP_CACHE will only operate on syscalls that do not access
+    any syscall arguments or instruction pointer. To facilitate
+    this we need a static analyser to know whether a filter will
+    return allow regardless of syscall arguments for a given
+    architecture number / syscall number pair. This is implemented
+    here with a pseudo-emulator, and stored in a per-filter bitmap.
+    
+    In order to build this bitmap at filter attach time, each filter is
+    emulated for every syscall (under each possible architecture), and
+    checked for any accesses of struct seccomp_data that are not the "arch"
+    nor "nr" (syscall) members. If only "arch" and "nr" are examined, and
+    the program returns allow, then we can be sure that the filter must
+    return allow independent from syscall arguments.
+    
+    Nearly all seccomp filters are built from these cBPF instructions:
+    
+    BPF_LD  | BPF_W    | BPF_ABS
+    BPF_JMP | BPF_JEQ  | BPF_K
+    BPF_JMP | BPF_JGE  | BPF_K
+    BPF_JMP | BPF_JGT  | BPF_K
+    BPF_JMP | BPF_JSET | BPF_K
+    BPF_JMP | BPF_JA
+    BPF_RET | BPF_K
+    BPF_ALU | BPF_AND  | BPF_K
+    
+    Each of these instructions are emulated. Any weirdness or loading
+    from a syscall argument will cause the emulator to bail.
+    
+    The emulation is also halted if it reaches a return. In that case,
+    if it returns an SECCOMP_RET_ALLOW, the syscall is marked as good.
+    
+    Emulator structure and comments are from Kees [1] and Jann [2].
+    
+    Emulation is done at attach time. If a filter depends on more
+    filters, and if the dependee does not guarantee to allow the
+    syscall, then we skip the emulation of this syscall.
+    
+    [1] https://lore.kernel.org/lkml/20200923232923.3142503-5-keescook@chromium.org/
+    [2] https://lore.kernel.org/lkml/CAG48ez1p=dR_2ikKq=xVxkoGg0fYpTBpkhJSv1w-6BG=76PAvw@mail.gmail.com/
+    
+    Suggested-by: Jann Horn 
+    Signed-off-by: YiFei Zhu 
+    Reviewed-by: Jann Horn 
+    Co-developed-by: Kees Cook 
+    Signed-off-by: Kees Cook 
+    Link: https://lore.kernel.org/r/71c7be2db5ee08905f41c3be5c1ad6e2601ce88f.1602431034.git.yifeifz2@illinois.edu
+
+diff --git a/kernel/seccomp.c b/kernel/seccomp.c
+index fe35f4f38949..d8cf468dbe1e 100644
+--- a/kernel/seccomp.c
++++ b/kernel/seccomp.c
+@@ -169,6 +169,10 @@ static inline bool seccomp_cache_check_allow(const struct seccomp_filter *sfilte
+ {
+ 	return false;
+ }
++
++static inline void seccomp_cache_prepare(struct seccomp_filter *sfilter)
++{
++}
+ #endif /* SECCOMP_ARCH_NATIVE */
+ 
+ /**
+@@ -187,6 +191,7 @@ static inline bool seccomp_cache_check_allow(const struct seccomp_filter *sfilte
+  *	   this filter after reaching 0. The @users count is always smaller
+  *	   or equal to @refs. Hence, reaching 0 for @users does not mean
+  *	   the filter can be freed.
++ * @cache: cache of arch/syscall mappings to actions
+  * @log: true if all actions except for SECCOMP_RET_ALLOW should be logged
+  * @prev: points to a previously installed, or inherited, filter
+  * @prog: the BPF program to evaluate
+@@ -208,6 +213,7 @@ struct seccomp_filter {
+ 	refcount_t refs;
+ 	refcount_t users;
+ 	bool log;
++	struct action_cache cache;
+ 	struct seccomp_filter *prev;
+ 	struct bpf_prog *prog;
+ 	struct notification *notif;
+@@ -621,7 +627,12 @@ static struct seccomp_filter *seccomp_prepare_filter(struct sock_fprog *fprog)
+ {
+ 	struct seccomp_filter *sfilter;
+ 	int ret;
+-	const bool save_orig = IS_ENABLED(CONFIG_CHECKPOINT_RESTORE);
++	const bool save_orig =
++#if defined(CONFIG_CHECKPOINT_RESTORE) || defined(SECCOMP_ARCH_NATIVE)
++		true;
++#else
++		false;
++#endif
+ 
+ 	if (fprog->len == 0 || fprog->len > BPF_MAXINSNS)
+ 		return ERR_PTR(-EINVAL);
+@@ -687,6 +698,148 @@ seccomp_prepare_user_filter(const char __user *user_filter)
+ 	return filter;
+ }
+ 
++#ifdef SECCOMP_ARCH_NATIVE
++/**
++ * seccomp_is_const_allow - check if filter is constant allow with given data
++ * @fprog: The BPF programs
++ * @sd: The seccomp data to check against, only syscall number and arch
++ *      number are considered constant.
++ */
++static bool seccomp_is_const_allow(struct sock_fprog_kern *fprog,
++				   struct seccomp_data *sd)
++{
++	unsigned int reg_value = 0;
++	unsigned int pc;
++	bool op_res;
++
++	if (WARN_ON_ONCE(!fprog))
++		return false;
++
++	for (pc = 0; pc < fprog->len; pc++) {
++		struct sock_filter *insn = &fprog->filter[pc];
++		u16 code = insn->code;
++		u32 k = insn->k;
++
++		switch (code) {
++		case BPF_LD | BPF_W | BPF_ABS:
++			switch (k) {
++			case offsetof(struct seccomp_data, nr):
++				reg_value = sd->nr;
++				break;
++			case offsetof(struct seccomp_data, arch):
++				reg_value = sd->arch;
++				break;
++			default:
++				/* can't optimize (non-constant value load) */
++				return false;
++			}
++			break;
++		case BPF_RET | BPF_K:
++			/* reached return with constant values only, check allow */
++			return k == SECCOMP_RET_ALLOW;
++		case BPF_JMP | BPF_JA:
++			pc += insn->k;
++			break;
++		case BPF_JMP | BPF_JEQ | BPF_K:
++		case BPF_JMP | BPF_JGE | BPF_K:
++		case BPF_JMP | BPF_JGT | BPF_K:
++		case BPF_JMP | BPF_JSET | BPF_K:
++			switch (BPF_OP(code)) {
++			case BPF_JEQ:
++				op_res = reg_value == k;
++				break;
++			case BPF_JGE:
++				op_res = reg_value >= k;
++				break;
++			case BPF_JGT:
++				op_res = reg_value > k;
++				break;
++			case BPF_JSET:
++				op_res = !!(reg_value & k);
++				break;
++			default:
++				/* can't optimize (unknown jump) */
++				return false;
++			}
++
++			pc += op_res ? insn->jt : insn->jf;
++			break;
++		case BPF_ALU | BPF_AND | BPF_K:
++			reg_value &= k;
++			break;
++		default:
++			/* can't optimize (unknown insn) */
++			return false;
++		}
++	}
++
++	/* ran off the end of the filter?! */
++	WARN_ON(1);
++	return false;
++}
++
++static void seccomp_cache_prepare_bitmap(struct seccomp_filter *sfilter,
++					 void *bitmap, const void *bitmap_prev,
++					 size_t bitmap_size, int arch)
++{
++	struct sock_fprog_kern *fprog = sfilter->prog->orig_prog;
++	struct seccomp_data sd;
++	int nr;
++
++	if (bitmap_prev) {
++		/* The new filter must be as restrictive as the last. */
++		bitmap_copy(bitmap, bitmap_prev, bitmap_size);
++	} else {
++		/* Before any filters, all syscalls are always allowed. */
++		bitmap_fill(bitmap, bitmap_size);
++	}
++
++	for (nr = 0; nr < bitmap_size; nr++) {
++		/* No bitmap change: not a cacheable action. */
++		if (!test_bit(nr, bitmap))
++			continue;
++
++		sd.nr = nr;
++		sd.arch = arch;
++
++		/* No bitmap change: continue to always allow. */
++		if (seccomp_is_const_allow(fprog, &sd))
++			continue;
++
++		/*
++		 * Not a cacheable action: always run filters.
++		 * atomic clear_bit() not needed, filter not visible yet.
++		 */
++		__clear_bit(nr, bitmap);
++	}
++}
++
++/**
++ * seccomp_cache_prepare - emulate the filter to find cachable syscalls
++ * @sfilter: The seccomp filter
++ *
++ * Returns 0 if successful or -errno if error occurred.
++ */
++static void seccomp_cache_prepare(struct seccomp_filter *sfilter)
++{
++	struct action_cache *cache = &sfilter->cache;
++	const struct action_cache *cache_prev =
++		sfilter->prev ? &sfilter->prev->cache : NULL;
++
++	seccomp_cache_prepare_bitmap(sfilter, cache->allow_native,
++				     cache_prev ? cache_prev->allow_native : NULL,
++				     SECCOMP_ARCH_NATIVE_NR,
++				     SECCOMP_ARCH_NATIVE);
++
++#ifdef SECCOMP_ARCH_COMPAT
++	seccomp_cache_prepare_bitmap(sfilter, cache->allow_compat,
++				     cache_prev ? cache_prev->allow_compat : NULL,
++				     SECCOMP_ARCH_COMPAT_NR,
++				     SECCOMP_ARCH_COMPAT);
++#endif /* SECCOMP_ARCH_COMPAT */
++}
++#endif /* SECCOMP_ARCH_NATIVE */
++
+ /**
+  * seccomp_attach_filter: validate and attach filter
+  * @flags:  flags to change filter behavior
+@@ -736,6 +889,7 @@ static long seccomp_attach_filter(unsigned int flags,
+ 	 * task reference.
+ 	 */
+ 	filter->prev = current->seccomp.filter;
++	seccomp_cache_prepare(filter);
+ 	current->seccomp.filter = filter;
+ 	atomic_inc(¤t->seccomp.filter_count);
+ 

commit f9d480b6ffbeb336bf7f6ce44825c00f61b3abae
+Author: YiFei Zhu 
+Date:   Sun Oct 11 10:47:42 2020 -0500
+
+    seccomp/cache: Lookup syscall allowlist bitmap for fast path
+    
+    The overhead of running Seccomp filters has been part of some past
+    discussions [1][2][3]. Oftentimes, the filters have a large number
+    of instructions that check syscall numbers one by one and jump based
+    on that. Some users chain BPF filters which further enlarge the
+    overhead. A recent work [6] comprehensively measures the Seccomp
+    overhead and shows that the overhead is non-negligible and has a
+    non-trivial impact on application performance.
+    
+    We observed some common filters, such as docker's [4] or
+    systemd's [5], will make most decisions based only on the syscall
+    numbers, and as past discussions considered, a bitmap where each bit
+    represents a syscall makes most sense for these filters.
+    
+    The fast (common) path for seccomp should be that the filter permits
+    the syscall to pass through, and failing seccomp is expected to be
+    an exceptional case; it is not expected for userspace to call a
+    denylisted syscall over and over.
+    
+    When it can be concluded that an allow must occur for the given
+    architecture and syscall pair (this determination is introduced in
+    the next commit), seccomp will immediately allow the syscall,
+    bypassing further BPF execution.
+    
+    Each architecture number has its own bitmap. The architecture
+    number in seccomp_data is checked against the defined architecture
+    number constant before proceeding to test the bit against the
+    bitmap with the syscall number as the index of the bit in the
+    bitmap, and if the bit is set, seccomp returns allow. The bitmaps
+    are all clear in this patch and will be initialized in the next
+    commit.
+    
+    When only one architecture exists, the check against architecture
+    number is skipped, suggested by Kees Cook [7].
+    
+    [1] https://lore.kernel.org/linux-security-module/c22a6c3cefc2412cad00ae14c1371711@huawei.com/T/
+    [2] https://lore.kernel.org/lkml/202005181120.971232B7B@keescook/T/
+    [3] https://github.com/seccomp/libseccomp/issues/116
+    [4] https://github.com/moby/moby/blob/ae0ef82b90356ac613f329a8ef5ee42ca923417d/profiles/seccomp/default.json
+    [5] https://github.com/systemd/systemd/blob/6743a1caf4037f03dc51a1277855018e4ab61957/src/shared/seccomp-util.c#L270
+    [6] Draco: Architectural and Operating System Support for System Call Security
+        https://tianyin.github.io/pub/draco.pdf, MICRO-53, Oct. 2020
+    [7] https://lore.kernel.org/bpf/202010091614.8BB0EB64@keescook/
+    
+    Co-developed-by: Dimitrios Skarlatos 
+    Signed-off-by: Dimitrios Skarlatos 
+    Signed-off-by: YiFei Zhu 
+    Reviewed-by: Jann Horn 
+    Signed-off-by: Kees Cook 
+    Link: https://lore.kernel.org/r/10f91a367ec4fcdea7fc3f086de3f5f13a4a7436.1602431034.git.yifeifz2@illinois.edu
+
+diff --git a/kernel/seccomp.c b/kernel/seccomp.c
+index 8ad7a293255a..fe35f4f38949 100644
+--- a/kernel/seccomp.c
++++ b/kernel/seccomp.c
+@@ -143,6 +143,34 @@ struct notification {
+ 	struct list_head notifications;
+ };
+ 
++#ifdef SECCOMP_ARCH_NATIVE
++/**
++ * struct action_cache - per-filter cache of seccomp actions per
++ * arch/syscall pair
++ *
++ * @allow_native: A bitmap where each bit represents whether the
++ *		  filter will always allow the syscall, for the
++ *		  native architecture.
++ * @allow_compat: A bitmap where each bit represents whether the
++ *		  filter will always allow the syscall, for the
++ *		  compat architecture.
++ */
++struct action_cache {
++	DECLARE_BITMAP(allow_native, SECCOMP_ARCH_NATIVE_NR);
++#ifdef SECCOMP_ARCH_COMPAT
++	DECLARE_BITMAP(allow_compat, SECCOMP_ARCH_COMPAT_NR);
++#endif
++};
++#else
++struct action_cache { };
++
++static inline bool seccomp_cache_check_allow(const struct seccomp_filter *sfilter,
++					     const struct seccomp_data *sd)
++{
++	return false;
++}
++#endif /* SECCOMP_ARCH_NATIVE */
++
+ /**
+  * struct seccomp_filter - container for seccomp BPF programs
+  *
+@@ -298,6 +326,52 @@ static int seccomp_check_filter(struct sock_filter *filter, unsigned int flen)
+ 	return 0;
+ }
+ 
++#ifdef SECCOMP_ARCH_NATIVE
++static inline bool seccomp_cache_check_allow_bitmap(const void *bitmap,
++						    size_t bitmap_size,
++						    int syscall_nr)
++{
++	if (unlikely(syscall_nr < 0 || syscall_nr >= bitmap_size))
++		return false;
++	syscall_nr = array_index_nospec(syscall_nr, bitmap_size);
++
++	return test_bit(syscall_nr, bitmap);
++}
++
++/**
++ * seccomp_cache_check_allow - lookup seccomp cache
++ * @sfilter: The seccomp filter
++ * @sd: The seccomp data to lookup the cache with
++ *
++ * Returns true if the seccomp_data is cached and allowed.
++ */
++static inline bool seccomp_cache_check_allow(const struct seccomp_filter *sfilter,
++					     const struct seccomp_data *sd)
++{
++	int syscall_nr = sd->nr;
++	const struct action_cache *cache = &sfilter->cache;
++
++#ifndef SECCOMP_ARCH_COMPAT
++	/* A native-only architecture doesn't need to check sd->arch. */
++	return seccomp_cache_check_allow_bitmap(cache->allow_native,
++						SECCOMP_ARCH_NATIVE_NR,
++						syscall_nr);
++#else
++	if (likely(sd->arch == SECCOMP_ARCH_NATIVE))
++		return seccomp_cache_check_allow_bitmap(cache->allow_native,
++							SECCOMP_ARCH_NATIVE_NR,
++							syscall_nr);
++	if (likely(sd->arch == SECCOMP_ARCH_COMPAT))
++		return seccomp_cache_check_allow_bitmap(cache->allow_compat,
++							SECCOMP_ARCH_COMPAT_NR,
++							syscall_nr);
++#endif /* SECCOMP_ARCH_COMPAT */
++
++	WARN_ON_ONCE(true);
++	return false;
++}
++#endif /* SECCOMP_ARCH_NATIVE */
++
+ /**
+  * seccomp_run_filters - evaluates all seccomp filters against @sd
+  * @sd: optional seccomp data to be passed to filters
+@@ -320,6 +394,9 @@ static u32 seccomp_run_filters(const struct seccomp_data *sd,
+ 	if (WARN_ON(f == NULL))
+ 		return SECCOMP_RET_KILL_PROCESS;
+ 
++	if (seccomp_cache_check_allow(f, sd))
++		return SECCOMP_RET_ALLOW;
++
+ 	/*
+ 	 * All filters in the list are evaluated and the lowest BPF return
+ 	 * value always takes priority (ignoring the DATA).

commit 282a181b1a0d66de1f0894d82f395fcd478f51d1
+Author: YiFei Zhu 
+Date:   Thu Sep 24 07:44:16 2020 -0500
+
+    seccomp: Move config option SECCOMP to arch/Kconfig
+    
+    In order to make adding configurable features into seccomp easier,
+    it's better to have the options at one single location, considering
+    especially that the bulk of seccomp code is arch-independent. An quick
+    look also show that many SECCOMP descriptions are outdated; they talk
+    about /proc rather than prctl.
+    
+    As a result of moving the config option and keeping it default on,
+    architectures arm, arm64, csky, riscv, sh, and xtensa did not have SECCOMP
+    on by default prior to this and SECCOMP will be default in this change.
+    
+    Architectures microblaze, mips, powerpc, s390, sh, and sparc have an
+    outdated depend on PROC_FS and this dependency is removed in this change.
+    
+    Suggested-by: Jann Horn 
+    Link: https://lore.kernel.org/lkml/CAG48ez1YWz9cnp08UZgeieYRhHdqh-ch7aNwc4JRBnGyrmgfMg@mail.gmail.com/
+    Signed-off-by: YiFei Zhu 
+    [kees: added HAVE_ARCH_SECCOMP help text, tweaked wording]
+    Signed-off-by: Kees Cook 
+    Link: https://lore.kernel.org/r/9ede6ef35c847e58d61e476c6a39540520066613.1600951211.git.yifeifz2@illinois.edu
+
+diff --git a/arch/Kconfig b/arch/Kconfig
+index af14a567b493..21a3675a7a3a 100644
+--- a/arch/Kconfig
++++ b/arch/Kconfig
+@@ -444,10 +444,23 @@ config ARCH_WANT_OLD_COMPAT_IPC
+ 	select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
+ 	bool
+ 
++config HAVE_ARCH_SECCOMP
++	bool
++	help
++	  An arch should select this symbol to support seccomp mode 1 (the fixed
++	  syscall policy), and must provide an overrides for __NR_seccomp_sigreturn,
++	  and compat syscalls if the asm-generic/seccomp.h defaults need adjustment:
++	  - __NR_seccomp_read_32
++	  - __NR_seccomp_write_32
++	  - __NR_seccomp_exit_32
++	  - __NR_seccomp_sigreturn_32
++
+ config HAVE_ARCH_SECCOMP_FILTER
+ 	bool
++	select HAVE_ARCH_SECCOMP
+ 	help
+ 	  An arch should select this symbol if it provides all of these things:
++	  - all the requirements for HAVE_ARCH_SECCOMP
+ 	  - syscall_get_arch()
+ 	  - syscall_get_arguments()
+ 	  - syscall_rollback()
+@@ -458,6 +471,23 @@ config HAVE_ARCH_SECCOMP_FILTER
+ 	    results in the system call being skipped immediately.
+ 	  - seccomp syscall wired up
+ 
++config SECCOMP
++	prompt "Enable seccomp to safely execute untrusted bytecode"
++	def_bool y
++	depends on HAVE_ARCH_SECCOMP
++	help
++	  This kernel feature is useful for number crunching applications
++	  that may need to handle untrusted bytecode during their
++	  execution. By using pipes or other transports made available
++	  to the process as file descriptors supporting the read/write
++	  syscalls, it's possible to isolate those applications in their
++	  own address space using seccomp. Once seccomp is enabled via
++	  prctl(PR_SET_SECCOMP) or the seccomp() syscall, it cannot be
++	  disabled and the task is only allowed to execute a few safe
++	  syscalls defined by each seccomp mode.
++
++	  If unsure, say Y.
++
+ config SECCOMP_FILTER
+ 	def_bool y
+ 	depends on HAVE_ARCH_SECCOMP_FILTER && SECCOMP && NET
+diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
+index e00d94b16658..e26c19a16284 100644
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -67,6 +67,7 @@ config ARM
+ 	select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL && !CPU_ENDIAN_BE32 && MMU
+ 	select HAVE_ARCH_KGDB if !CPU_ENDIAN_BE32 && MMU
+ 	select HAVE_ARCH_MMAP_RND_BITS if MMU
++	select HAVE_ARCH_SECCOMP
+ 	select HAVE_ARCH_SECCOMP_FILTER if AEABI && !OABI_COMPAT
+ 	select HAVE_ARCH_THREAD_STRUCT_WHITELIST
+ 	select HAVE_ARCH_TRACEHOOK
+@@ -1617,20 +1618,6 @@ config UACCESS_WITH_MEMCPY
+ 	  However, if the CPU data cache is using a write-allocate mode,
+ 	  this option is unlikely to provide any performance gain.
+ 
+-config SECCOMP
+-	bool
+-	prompt "Enable seccomp to safely compute untrusted bytecode"
+-	help
+-	  This kernel feature is useful for number crunching applications
+-	  that may need to compute untrusted bytecode during their
+-	  execution. By using pipes or other transports made available to
+-	  the process as file descriptors supporting the read/write
+-	  syscalls, it's possible to isolate those applications in
+-	  their own address space using seccomp. Once seccomp is
+-	  enabled via prctl(PR_SET_SECCOMP), it cannot be disabled
+-	  and the task is only allowed to execute a few safe syscalls
+-	  defined by each seccomp mode.
+-
+ config PARAVIRT
+ 	bool "Enable paravirtualization code"
+ 	help
+diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
+index 6d232837cbee..98c4e34cbec1 100644
+--- a/arch/arm64/Kconfig
++++ b/arch/arm64/Kconfig
+@@ -1033,19 +1033,6 @@ config ARCH_ENABLE_SPLIT_PMD_PTLOCK
+ config CC_HAVE_SHADOW_CALL_STACK
+ 	def_bool $(cc-option, -fsanitize=shadow-call-stack -ffixed-x18)
+ 
+-config SECCOMP
+-	bool "Enable seccomp to safely compute untrusted bytecode"
+-	help
+-	  This kernel feature is useful for number crunching applications
+-	  that may need to compute untrusted bytecode during their
+-	  execution. By using pipes or other transports made available to
+-	  the process as file descriptors supporting the read/write
+-	  syscalls, it's possible to isolate those applications in
+-	  their own address space using seccomp. Once seccomp is
+-	  enabled via prctl(PR_SET_SECCOMP), it cannot be disabled
+-	  and the task is only allowed to execute a few safe syscalls
+-	  defined by each seccomp mode.
+-
+ config PARAVIRT
+ 	bool "Enable paravirtualization code"
+ 	help
+diff --git a/arch/csky/Kconfig b/arch/csky/Kconfig
+index 3d5afb5f5685..7f424c85772c 100644
+--- a/arch/csky/Kconfig
++++ b/arch/csky/Kconfig
+@@ -309,16 +309,3 @@ endmenu
+ source "arch/csky/Kconfig.platforms"
+ 
+ source "kernel/Kconfig.hz"
+-
+-config SECCOMP
+-	bool "Enable seccomp to safely compute untrusted bytecode"
+-	help
+-	  This kernel feature is useful for number crunching applications
+-	  that may need to compute untrusted bytecode during their
+-	  execution. By using pipes or other transports made available to
+-	  the process as file descriptors supporting the read/write
+-	  syscalls, it's possible to isolate those applications in
+-	  their own address space using seccomp. Once seccomp is
+-	  enabled via prctl(PR_SET_SECCOMP), it cannot be disabled
+-	  and the task is only allowed to execute a few safe syscalls
+-	  defined by each seccomp mode.
+diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
+index d262ac0c8714..37bd6a5f38fb 100644
+--- a/arch/microblaze/Kconfig
++++ b/arch/microblaze/Kconfig
+@@ -26,6 +26,7 @@ config MICROBLAZE
+ 	select GENERIC_SCHED_CLOCK
+ 	select HAVE_ARCH_HASH
+ 	select HAVE_ARCH_KGDB
++	select HAVE_ARCH_SECCOMP
+ 	select HAVE_DEBUG_KMEMLEAK
+ 	select HAVE_DMA_CONTIGUOUS
+ 	select HAVE_DYNAMIC_FTRACE
+@@ -120,23 +121,6 @@ config CMDLINE_FORCE
+ 	  Set this to have arguments from the default kernel command string
+ 	  override those passed by the boot loader.
+ 
+-config SECCOMP
+-	bool "Enable seccomp to safely compute untrusted bytecode"
+-	depends on PROC_FS
+-	default y
+-	help
+-	  This kernel feature is useful for number crunching applications
+-	  that may need to compute untrusted bytecode during their
+-	  execution. By using pipes or other transports made available to
+-	  the process as file descriptors supporting the read/write
+-	  syscalls, it's possible to isolate those applications in
+-	  their own address space using seccomp. Once seccomp is
+-	  enabled via /proc//seccomp, it cannot be disabled
+-	  and the task is only allowed to execute a few safe syscalls
+-	  defined by each seccomp mode.
+-
+-	  If unsure, say Y. Only embedded should say N here.
+-
+ endmenu
+ 
+ menu "Kernel features"
+diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
+index c95fa3a2484c..5f88a8fc11fc 100644
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -3004,23 +3004,6 @@ config PHYSICAL_START
+ 	  specified in the "crashkernel=YM@XM" command line boot parameter
+ 	  passed to the panic-ed kernel).
+ 
+-config SECCOMP
+-	bool "Enable seccomp to safely compute untrusted bytecode"
+-	depends on PROC_FS
+-	default y
+-	help
+-	  This kernel feature is useful for number crunching applications
+-	  that may need to compute untrusted bytecode during their
+-	  execution. By using pipes or other transports made available to
+-	  the process as file descriptors supporting the read/write
+-	  syscalls, it's possible to isolate those applications in
+-	  their own address space using seccomp. Once seccomp is
+-	  enabled via /proc//seccomp, it cannot be disabled
+-	  and the task is only allowed to execute a few safe syscalls
+-	  defined by each seccomp mode.
+-
+-	  If unsure, say Y. Only embedded should say N here.
+-
+ config MIPS_O32_FP64_SUPPORT
+ 	bool "Support for O32 binaries using 64-bit FP" if !CPU_MIPSR6
+ 	depends on 32BIT || MIPS32_O32
+diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
+index 3b0f53dd70bc..cd4afe1e7a6c 100644
+--- a/arch/parisc/Kconfig
++++ b/arch/parisc/Kconfig
+@@ -378,19 +378,3 @@ endmenu
+ 
+ 
+ source "drivers/parisc/Kconfig"
+-
+-config SECCOMP
+-	def_bool y
+-	prompt "Enable seccomp to safely compute untrusted bytecode"
+-	help
+-	  This kernel feature is useful for number crunching applications
+-	  that may need to compute untrusted bytecode during their
+-	  execution. By using pipes or other transports made available to
+-	  the process as file descriptors supporting the read/write
+-	  syscalls, it's possible to isolate those applications in
+-	  their own address space using seccomp. Once seccomp is
+-	  enabled via prctl(PR_SET_SECCOMP), it cannot be disabled
+-	  and the task is only allowed to execute a few safe syscalls
+-	  defined by each seccomp mode.
+-
+-	  If unsure, say Y. Only embedded should say N here.
+diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
+index 1f48bbfb3ce9..136fe860caef 100644
+--- a/arch/powerpc/Kconfig
++++ b/arch/powerpc/Kconfig
+@@ -934,23 +934,6 @@ config ARCH_WANTS_FREEZER_CONTROL
+ 
+ source "kernel/power/Kconfig"
+ 
+-config SECCOMP
+-	bool "Enable seccomp to safely compute untrusted bytecode"
+-	depends on PROC_FS
+-	default y
+-	help
+-	  This kernel feature is useful for number crunching applications
+-	  that may need to compute untrusted bytecode during their
+-	  execution. By using pipes or other transports made available to
+-	  the process as file descriptors supporting the read/write
+-	  syscalls, it's possible to isolate those applications in
+-	  their own address space using seccomp. Once seccomp is
+-	  enabled via /proc//seccomp, it cannot be disabled
+-	  and the task is only allowed to execute a few safe syscalls
+-	  defined by each seccomp mode.
+-
+-	  If unsure, say Y. Only embedded should say N here.
+-
+ config PPC_MEM_KEYS
+ 	prompt "PowerPC Memory Protection Keys"
+ 	def_bool y
+diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
+index df18372861d8..c456b558fab9 100644
+--- a/arch/riscv/Kconfig
++++ b/arch/riscv/Kconfig
+@@ -333,19 +333,6 @@ menu "Kernel features"
+ 
+ source "kernel/Kconfig.hz"
+ 
+-config SECCOMP
+-	bool "Enable seccomp to safely compute untrusted bytecode"
+-	help
+-	  This kernel feature is useful for number crunching applications
+-	  that may need to compute untrusted bytecode during their
+-	  execution. By using pipes or other transports made available to
+-	  the process as file descriptors supporting the read/write
+-	  syscalls, it's possible to isolate those applications in
+-	  their own address space using seccomp. Once seccomp is
+-	  enabled via prctl(PR_SET_SECCOMP), it cannot be disabled
+-	  and the task is only allowed to execute a few safe syscalls
+-	  defined by each seccomp mode.
+-
+ config RISCV_SBI_V01
+ 	bool "SBI v0.1 support"
+ 	default y
+diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
+index 3d86e12e8e3c..7f7b40ec699e 100644
+--- a/arch/s390/Kconfig
++++ b/arch/s390/Kconfig
+@@ -791,23 +791,6 @@ config CRASH_DUMP
+ 
+ endmenu
+ 
+-config SECCOMP
+-	def_bool y
+-	prompt "Enable seccomp to safely compute untrusted bytecode"
+-	depends on PROC_FS
+-	help
+-	  This kernel feature is useful for number crunching applications
+-	  that may need to compute untrusted bytecode during their
+-	  execution. By using pipes or other transports made available to
+-	  the process as file descriptors supporting the read/write
+-	  syscalls, it's possible to isolate those applications in
+-	  their own address space using seccomp. Once seccomp is
+-	  enabled via /proc//seccomp, it cannot be disabled
+-	  and the task is only allowed to execute a few safe syscalls
+-	  defined by each seccomp mode.
+-
+-	  If unsure, say Y.
+-
+ config CCW
+ 	def_bool y
+ 
+diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
+index d20927128fce..18278152c91c 100644
+--- a/arch/sh/Kconfig
++++ b/arch/sh/Kconfig
+@@ -600,22 +600,6 @@ config PHYSICAL_START
+ 	  where the fail safe kernel needs to run at a different address
+ 	  than the panic-ed kernel.
+ 
+-config SECCOMP
+-	bool "Enable seccomp to safely compute untrusted bytecode"
+-	depends on PROC_FS
+-	help
+-	  This kernel feature is useful for number crunching applications
+-	  that may need to compute untrusted bytecode during their
+-	  execution. By using pipes or other transports made available to
+-	  the process as file descriptors supporting the read/write
+-	  syscalls, it's possible to isolate those applications in
+-	  their own address space using seccomp. Once seccomp is
+-	  enabled via prctl, it cannot be disabled and the task is only
+-	  allowed to execute a few safe syscalls defined by each seccomp
+-	  mode.
+-
+-	  If unsure, say N.
+-
+ config SMP
+ 	bool "Symmetric multi-processing support"
+ 	depends on SYS_SUPPORTS_SMP
+diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
+index efeff2c896a5..d62ce83cf009 100644
+--- a/arch/sparc/Kconfig
++++ b/arch/sparc/Kconfig
+@@ -23,6 +23,7 @@ config SPARC
+ 	select HAVE_OPROFILE
+ 	select HAVE_ARCH_KGDB if !SMP || SPARC64
+ 	select HAVE_ARCH_TRACEHOOK
++	select HAVE_ARCH_SECCOMP if SPARC64
+ 	select HAVE_EXIT_THREAD
+ 	select HAVE_PCI
+ 	select SYSCTL_EXCEPTION_TRACE
+@@ -226,23 +227,6 @@ config EARLYFB
+ 	help
+ 	  Say Y here to enable a faster early framebuffer boot console.
+ 
+-config SECCOMP
+-	bool "Enable seccomp to safely compute untrusted bytecode"
+-	depends on SPARC64 && PROC_FS
+-	default y
+-	help
+-	  This kernel feature is useful for number crunching applications
+-	  that may need to compute untrusted bytecode during their
+-	  execution. By using pipes or other transports made available to
+-	  the process as file descriptors supporting the read/write
+-	  syscalls, it's possible to isolate those applications in
+-	  their own address space using seccomp. Once seccomp is
+-	  enabled via /proc//seccomp, it cannot be disabled
+-	  and the task is only allowed to execute a few safe syscalls
+-	  defined by each seccomp mode.
+-
+-	  If unsure, say Y. Only embedded should say N here.
+-
+ config HOTPLUG_CPU
+ 	bool "Support for hot-pluggable CPUs"
+ 	depends on SPARC64 && SMP
+diff --git a/arch/um/Kconfig b/arch/um/Kconfig
+index eb51fec75948..d49f471b02e3 100644
+--- a/arch/um/Kconfig
++++ b/arch/um/Kconfig
+@@ -173,22 +173,6 @@ config PGTABLE_LEVELS
+ 	default 3 if 3_LEVEL_PGTABLES
+ 	default 2
+ 
+-config SECCOMP
+-	def_bool y
+-	prompt "Enable seccomp to safely compute untrusted bytecode"
+-	help
+-	  This kernel feature is useful for number crunching applications
+-	  that may need to compute untrusted bytecode during their
+-	  execution. By using pipes or other transports made available to
+-	  the process as file descriptors supporting the read/write
+-	  syscalls, it's possible to isolate those applications in
+-	  their own address space using seccomp. Once seccomp is
+-	  enabled via prctl(PR_SET_SECCOMP), it cannot be disabled
+-	  and the task is only allowed to execute a few safe syscalls
+-	  defined by each seccomp mode.
+-
+-	  If unsure, say Y.
+-
+ config UML_TIME_TRAVEL_SUPPORT
+ 	bool
+ 	prompt "Support time-travel mode (e.g. for test execution)"
+diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
+index 7101ac64bb20..1ab22869a765 100644
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -1968,22 +1968,6 @@ config EFI_MIXED
+ 
+ 	   If unsure, say N.
+ 
+-config SECCOMP
+-	def_bool y
+-	prompt "Enable seccomp to safely compute untrusted bytecode"
+-	help
+-	  This kernel feature is useful for number crunching applications
+-	  that may need to compute untrusted bytecode during their
+-	  execution. By using pipes or other transports made available to
+-	  the process as file descriptors supporting the read/write
+-	  syscalls, it's possible to isolate those applications in
+-	  their own address space using seccomp. Once seccomp is
+-	  enabled via prctl(PR_SET_SECCOMP), it cannot be disabled
+-	  and the task is only allowed to execute a few safe syscalls
+-	  defined by each seccomp mode.
+-
+-	  If unsure, say Y. Only embedded should say N here.
+-
+ source "kernel/Kconfig.hz"
+ 
+ config KEXEC
+diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
+index e997e0119c02..d8a29dc5a284 100644
+--- a/arch/xtensa/Kconfig
++++ b/arch/xtensa/Kconfig
+@@ -217,20 +217,6 @@ config HOTPLUG_CPU
+ 
+ 	  Say N if you want to disable CPU hotplug.
+ 
+-config SECCOMP
+-	bool
+-	prompt "Enable seccomp to safely compute untrusted bytecode"
+-	help
+-	  This kernel feature is useful for number crunching applications
+-	  that may need to compute untrusted bytecode during their
+-	  execution. By using pipes or other transports made available to
+-	  the process as file descriptors supporting the read/write
+-	  syscalls, it's possible to isolate those applications in
+-	  their own address space using seccomp. Once seccomp is
+-	  enabled via prctl(PR_SET_SECCOMP), it cannot be disabled
+-	  and the task is only allowed to execute a few safe syscalls
+-	  defined by each seccomp mode.
+-
+ config FAST_SYSCALL_XTENSA
+ 	bool "Enable fast atomic syscalls"
+ 	default n

commit 219db95bbe796277c739cca17fe134f6c2ce6676
+Author: Ayush Ranjan 
+Date:   Thu Aug 22 23:18:33 2019 -0400
+
+    ext4: documentation fixes
+    
+    This commit aims to fix the following issues in ext4 documentation:
+    - Flexible block group docs said that the aim was to group block
+      metadata together instead of block group metadata.
+    - The documentation consistly uses "location" instead of "block number".
+      It is easy to confuse location to be an absolute offset on disk. Added
+      a line to clarify all location values are in terms of block numbers.
+    - Dirent2 docs said that the rec_len field is shortened instead of the
+      name_len field.
+    - Typo in bg_checksum description.
+    - Inode size is 160 bytes now, and hence i_extra_isize is now 32.
+    - Cluster size formula was incorrect, it did not include the +10 to
+      s_log_cluster_size value.
+    - Typo: there were two s_wtime_hi in the superblock struct.
+    - Superblock struct was outdated, added the new fields which were part
+      of s_reserved earlier.
+    - Multiple mount protection seems to be implemented in fs/ext4/mmp.c.
+    
+    Signed-off-by: Ayush Ranjan 
+    Signed-off-by: Theodore Ts'o 
+    Reviewed-by: Andreas Dilger 
+
+diff --git a/Documentation/filesystems/ext4/blockgroup.rst b/Documentation/filesystems/ext4/blockgroup.rst
+index baf888e4c06a..3da156633339 100644
+--- a/Documentation/filesystems/ext4/blockgroup.rst
++++ b/Documentation/filesystems/ext4/blockgroup.rst
+@@ -71,11 +71,11 @@ if the flex\_bg size is 4, then group 0 will contain (in order) the
+ superblock, group descriptors, data block bitmaps for groups 0-3, inode
+ bitmaps for groups 0-3, inode tables for groups 0-3, and the remaining
+ space in group 0 is for file data. The effect of this is to group the
+-block metadata close together for faster loading, and to enable large
+-files to be continuous on disk. Backup copies of the superblock and
+-group descriptors are always at the beginning of block groups, even if
+-flex\_bg is enabled. The number of block groups that make up a flex\_bg
+-is given by 2 ^ ``sb.s_log_groups_per_flex``.
++block group metadata close together for faster loading, and to enable
++large files to be continuous on disk. Backup copies of the superblock
++and group descriptors are always at the beginning of block groups, even
++if flex\_bg is enabled. The number of block groups that make up a
++flex\_bg is given by 2 ^ ``sb.s_log_groups_per_flex``.
+ 
+ Meta Block Groups
+ -----------------
+diff --git a/Documentation/filesystems/ext4/blocks.rst b/Documentation/filesystems/ext4/blocks.rst
+index 73d4dc0f7bda..bd722ecd92d6 100644
+--- a/Documentation/filesystems/ext4/blocks.rst
++++ b/Documentation/filesystems/ext4/blocks.rst
+@@ -10,7 +10,9 @@ block groups. Block size is specified at mkfs time and typically is
+ 4KiB. You may experience mounting problems if block size is greater than
+ page size (i.e. 64KiB blocks on a i386 which only has 4KiB memory
+ pages). By default a filesystem can contain 2^32 blocks; if the '64bit'
+-feature is enabled, then a filesystem can have 2^64 blocks.
++feature is enabled, then a filesystem can have 2^64 blocks. The location
++of structures is stored in terms of the block number the structure lives
++in and not the absolute offset on disk.
+ 
+ For 32-bit filesystems, limits are as follows:
+ 
+diff --git a/Documentation/filesystems/ext4/directory.rst b/Documentation/filesystems/ext4/directory.rst
+index 614034e24669..073940cc64ed 100644
+--- a/Documentation/filesystems/ext4/directory.rst
++++ b/Documentation/filesystems/ext4/directory.rst
+@@ -59,7 +59,7 @@ is at most 263 bytes long, though on disk you'll need to reference
+      - File name.
+ 
+ Since file names cannot be longer than 255 bytes, the new directory
+-entry format shortens the rec\_len field and uses the space for a file
++entry format shortens the name\_len field and uses the space for a file
+ type flag, probably to avoid having to load every inode during directory
+ tree traversal. This format is ``ext4_dir_entry_2``, which is at most
+ 263 bytes long, though on disk you'll need to reference
+diff --git a/Documentation/filesystems/ext4/group_descr.rst b/Documentation/filesystems/ext4/group_descr.rst
+index 0f783ed88592..7ba6114e7f5c 100644
+--- a/Documentation/filesystems/ext4/group_descr.rst
++++ b/Documentation/filesystems/ext4/group_descr.rst
+@@ -99,9 +99,12 @@ The block group descriptor is laid out in ``struct ext4_group_desc``.
+    * - 0x1E
+      - \_\_le16
+      - bg\_checksum
+-     - Group descriptor checksum; crc16(sb\_uuid+group+desc) if the
+-       RO\_COMPAT\_GDT\_CSUM feature is set, or crc32c(sb\_uuid+group\_desc) &
+-       0xFFFF if the RO\_COMPAT\_METADATA\_CSUM feature is set.
++     - Group descriptor checksum; crc16(sb\_uuid+group\_num+bg\_desc) if the
++       RO\_COMPAT\_GDT\_CSUM feature is set, or
++       crc32c(sb\_uuid+group\_num+bg\_desc) & 0xFFFF if the
++       RO\_COMPAT\_METADATA\_CSUM feature is set.  The bg\_checksum
++       field in bg\_desc is skipped when calculating crc16 checksum,
++       and set to zero if crc32c checksum is used.
+    * -
+      -
+      -
+diff --git a/Documentation/filesystems/ext4/inodes.rst b/Documentation/filesystems/ext4/inodes.rst
+index 6bd35e506b6f..34f62928cebc 100644
+--- a/Documentation/filesystems/ext4/inodes.rst
++++ b/Documentation/filesystems/ext4/inodes.rst
+@@ -470,8 +470,8 @@ inode, which allows struct ext4\_inode to grow for a new kernel without
+ having to upgrade all of the on-disk inodes. Access to fields beyond
+ EXT2\_GOOD\_OLD\_INODE\_SIZE should be verified to be within
+ ``i_extra_isize``. By default, ext4 inode records are 256 bytes, and (as
+-of October 2013) the inode structure is 156 bytes
+-(``i_extra_isize = 28``). The extra space between the end of the inode
++of August 2019) the inode structure is 160 bytes
++(``i_extra_isize = 32``). The extra space between the end of the inode
+ structure and the end of the inode record can be used to store extended
+ attributes. Each inode record can be as large as the filesystem block
+ size, though this is not terribly efficient.
+diff --git a/Documentation/filesystems/ext4/super.rst b/Documentation/filesystems/ext4/super.rst
+index 04ff079a2acf..48b6c78fc38e 100644
+--- a/Documentation/filesystems/ext4/super.rst
++++ b/Documentation/filesystems/ext4/super.rst
+@@ -58,7 +58,7 @@ The ext4 superblock is laid out as follows in
+    * - 0x1C
+      - \_\_le32
+      - s\_log\_cluster\_size
+-     - Cluster size is (2 ^ s\_log\_cluster\_size) blocks if bigalloc is
++     - Cluster size is 2 ^ (10 + s\_log\_cluster\_size) blocks if bigalloc is
+        enabled. Otherwise s\_log\_cluster\_size must equal s\_log\_block\_size.
+    * - 0x20
+      - \_\_le32
+@@ -447,7 +447,7 @@ The ext4 superblock is laid out as follows in
+      - Upper 8 bits of the s_wtime field.
+    * - 0x275
+      - \_\_u8
+-     - s\_wtime_hi
++     - s\_mtime_hi
+      - Upper 8 bits of the s_mtime field.
+    * - 0x276
+      - \_\_u8
+@@ -466,12 +466,20 @@ The ext4 superblock is laid out as follows in
+      - s\_last_error_time_hi
+      - Upper 8 bits of the s_last_error_time_hi field.
+    * - 0x27A
+-     - \_\_u8[2]
+-     - s\_pad
++     - \_\_u8
++     - s\_pad[2]
+      - Zero padding.
+    * - 0x27C
++     - \_\_le16
++     - s\_encoding
++     - Filename charset encoding.
++   * - 0x27E
++     - \_\_le16
++     - s\_encoding_flags
++     - Filename charset encoding flags.
++   * - 0x280
+      - \_\_le32
+-     - s\_reserved[96]
++     - s\_reserved[95]
+      - Padding to the end of the block.
+    * - 0x3FC
+      - \_\_le32
+@@ -617,7 +625,7 @@ following:
+    * - 0x80
+      - Enable a filesystem size of 2^64 blocks (INCOMPAT\_64BIT).
+    * - 0x100
+-     - Multiple mount protection. Not implemented (INCOMPAT\_MMP).
++     - Multiple mount protection (INCOMPAT\_MMP).
+    * - 0x200
+      - Flexible block groups. See the earlier discussion of this feature
+        (INCOMPAT\_FLEX\_BG).

commit 642d89252201c4155fc3946bf9cdea409e5d263e
+Author: Matt Johnson 
+Date:   Fri Apr 27 01:42:30 2012 -0500
+
+    ahci: Detect Marvell 88SE9172 SATA controller
+    
+    The Marvell 88SE9172 SATA controller (PCI ID 1b4b 917a) already worked
+    once it was detected, but was missing an ahci_pci_tbl entry.
+    
+    Boot tested on a Gigabyte Z68X-UD3H-B3 motherboard.
+    
+    Signed-off-by: Matt Johnson 
+    Signed-off-by: Jeff Garzik 
+
+diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
+index 79a1e9dd56d9..ebaf67e4b2bc 100644
+--- a/drivers/ata/ahci.c
++++ b/drivers/ata/ahci.c
+@@ -394,6 +394,8 @@ static const struct pci_device_id ahci_pci_tbl[] = {
+ 	  .driver_data = board_ahci_yes_fbs },			/* 88se9128 */
+ 	{ PCI_DEVICE(0x1b4b, 0x9125),
+ 	  .driver_data = board_ahci_yes_fbs },			/* 88se9125 */
++	{ PCI_DEVICE(0x1b4b, 0x917a),
++	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 */
+ 	{ PCI_DEVICE(0x1b4b, 0x91a3),
+ 	  .driver_data = board_ahci_yes_fbs },
+ 

commit 4cde7e0dca98e0e93dceb174d83f766d0d637c23
+Author: Heechul Yun 
+Date:   Tue Jul 19 13:26:54 2011 +0100
+
+    ARM: 6998/2: kernel: use proper memory barriers for bitops
+    
+    Improve scalability by avoiding costly and unnecessary L2 cache sync
+    in handling bitops.
+    
+    Signed-off-by: Heechul Yun 
+    Acked-by: Catalin Marinas 
+    Signed-off-by: Russell King 
+
+diff --git a/arch/arm/include/asm/bitops.h b/arch/arm/include/asm/bitops.h
+index b4892a06442c..f4280593dfa3 100644
+--- a/arch/arm/include/asm/bitops.h
++++ b/arch/arm/include/asm/bitops.h
+@@ -26,8 +26,8 @@
+ #include 
+ #include 
+ 
+-#define smp_mb__before_clear_bit()	mb()
+-#define smp_mb__after_clear_bit()	mb()
++#define smp_mb__before_clear_bit()	smp_mb()
++#define smp_mb__after_clear_bit()	smp_mb()
+ 
+ /*
+  * These functions are the basis of our bit ops.

commit c7e89b16eb90e7bdf0d71bd5ba265ce8d424f30b
+Author: Heechul Yun 
+Date:   Fri Jul 8 13:32:34 2011 +0100
+
+    ARM: 6995/2: mm: remove unnecessary cache flush on v6 copypage
+    
+    Originally introduced to maintain coherency between icache and dcache
+    in v6 nonaliasing mode. This is now handled by __sync_icache_dcache since
+    c0177800, therefore unnecessary in this function.
+    
+    Signed-off-by: Heechul Yun 
+    Acked-by: Catalin Marinas 
+    Signed-off-by: Russell King 
+
+diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c
+index bdba6c65c901..63cca0097130 100644
+--- a/arch/arm/mm/copypage-v6.c
++++ b/arch/arm/mm/copypage-v6.c
+@@ -41,7 +41,6 @@ static void v6_copy_user_highpage_nonaliasing(struct page *to,
+ 	kfrom = kmap_atomic(from, KM_USER0);
+ 	kto = kmap_atomic(to, KM_USER1);
+ 	copy_page(kto, kfrom);
+-	__cpuc_flush_dcache_area(kto, PAGE_SIZE);
+ 	kunmap_atomic(kto, KM_USER1);
+ 	kunmap_atomic(kfrom, KM_USER0);
+ }

commit b6ac161364eccce1bea4a23a9de395883e90d7ab
+Author: Stoyan Gaydarov 
+Date:   Tue Jul 21 22:02:27 2009 -0500
+
+    Staging: ARRAY_SIZE changes
+    
+    These changes were a direct result of using a semantic patch
+    More information can be found at http://www.emn.fr/x-info/coccinelle/
+    
+    Signed-off-by: Stoyan Gaydarov 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
+index c4d8c4cae4a5..091a1a5822a8 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci230.c
++++ b/drivers/staging/comedi/drivers/amplc_pci230.c
+@@ -513,7 +513,7 @@ MODULE_DEVICE_TABLE(pci, pci230_pci_table);
+ /*
+  * Useful for shorthand access to the particular board structure
+  */
+-#define n_pci230_boards (sizeof(pci230_boards)/sizeof(pci230_boards[0]))
++#define n_pci230_boards ARRAY_SIZE(pci230_boards)
+ #define thisboard ((const struct pci230_board *)dev->board_ptr)
+ 
+ /* this structure is for data unique to this hardware driver.  If
+diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
+index 2f7aa3b5ef8e..12d12b43a6f1 100644
+--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
++++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
+@@ -78,7 +78,7 @@ static const struct das16cs_board das16cs_boards[] = {
+ 	 },
+ };
+ 
+-#define n_boards (sizeof(das16cs_boards)/sizeof(das16cs_boards[0]))
++#define n_boards ARRAY_SIZE(das16cs_boards)
+ #define thisboard ((const struct das16cs_board *)dev->board_ptr)
+ 
+ struct das16cs_private {
+diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
+index 74fcc1086c51..9cab21eaaa18 100644
+--- a/drivers/staging/comedi/drivers/das08_cs.c
++++ b/drivers/staging/comedi/drivers/das08_cs.c
+@@ -65,8 +65,7 @@ static struct comedi_driver driver_das08_cs = {
+ 	.attach = das08_cs_attach,
+ 	.detach = das08_common_detach,
+ 	.board_name = &das08_cs_boards[0].name,
+-	.num_names = sizeof(das08_cs_boards) /
+-	    sizeof(struct das08_board_struct),
++	.num_names = ARRAY_SIZE(das08_cs_boards),
+ 	.offset = sizeof(struct das08_board_struct),
+ };
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
+index 7a49dfce67be..b37ef37c2d2d 100644
+--- a/drivers/staging/comedi/drivers/ni_6527.c
++++ b/drivers/staging/comedi/drivers/ni_6527.c
+@@ -103,7 +103,7 @@ static const struct ni6527_board ni6527_boards[] = {
+ 	 },
+ };
+ 
+-#define n_ni6527_boards (sizeof(ni6527_boards)/sizeof(ni6527_boards[0]))
++#define n_ni6527_boards ARRAY_SIZE(ni6527_boards)
+ #define this_board ((const struct ni6527_board *)dev->board_ptr)
+ 
+ static DEFINE_PCI_DEVICE_TABLE(ni6527_pci_table) = {
+diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
+index 8079c41b7338..6b118c15b49e 100644
+--- a/drivers/staging/comedi/drivers/ni_65xx.c
++++ b/drivers/staging/comedi/drivers/ni_65xx.c
+@@ -246,7 +246,7 @@ static const struct ni_65xx_board ni_65xx_boards[] = {
+ 	 },
+ };
+ 
+-#define n_ni_65xx_boards (sizeof(ni_65xx_boards)/sizeof(ni_65xx_boards[0]))
++#define n_ni_65xx_boards ARRAY_SIZE(ni_65xx_boards)
+ static inline const struct ni_65xx_board *board(struct comedi_device *dev)
+ {
+ 	return dev->board_ptr;
+diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
+index 772c9372e435..404d3c516ed1 100644
+--- a/drivers/staging/comedi/drivers/ni_660x.c
++++ b/drivers/staging/comedi/drivers/ni_660x.c
+@@ -454,7 +454,7 @@ static inline const struct ni_660x_board *board(struct comedi_device *dev)
+ 	return dev->board_ptr;
+ }
+ 
+-#define n_ni_660x_boards (sizeof(ni_660x_boards)/sizeof(ni_660x_boards[0]))
++#define n_ni_660x_boards ARRAY_SIZE(ni_660x_boards)
+ 
+ static int ni_660x_attach(struct comedi_device *dev,
+ 			  struct comedi_devconfig *it);
+diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
+index 89ce5b873ffe..9b43547e80a1 100644
+--- a/drivers/staging/comedi/drivers/ni_670x.c
++++ b/drivers/staging/comedi/drivers/ni_670x.c
+@@ -111,7 +111,7 @@ struct ni_670x_private {
+ };
+ 
+ #define devpriv ((struct ni_670x_private *)dev->private)
+-#define n_ni_670x_boards (sizeof(ni_670x_boards)/sizeof(ni_670x_boards[0]))
++#define n_ni_670x_boards ARRAY_SIZE(ni_670x_boards)
+ 
+ static int ni_670x_attach(struct comedi_device *dev,
+ 			  struct comedi_devconfig *it);
+diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
+index cde30b77a15f..901833d9b772 100644
+--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
++++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
+@@ -121,7 +121,7 @@ static const struct atmio16_board_t atmio16_boards[] = {
+ 	 },
+ };
+ 
+-#define n_atmio16_boards sizeof(atmio16_boards)/sizeof(atmio16_boards[0])
++#define n_atmio16_boards ARRAY_SIZE(atmio16_boards)
+ 
+ #define boardtype ((const struct atmio16_board_t *)dev->board_ptr)
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
+index 15148d1642d4..52b2eca9e73d 100644
+--- a/drivers/staging/comedi/drivers/ni_pcidio.c
++++ b/drivers/staging/comedi/drivers/ni_pcidio.c
+@@ -374,7 +374,7 @@ static const struct nidio_board nidio_boards[] = {
+ 	 },
+ };
+ 
+-#define n_nidio_boards (sizeof(nidio_boards)/sizeof(nidio_boards[0]))
++#define n_nidio_boards ARRAY_SIZE(nidio_boards)
+ #define this_board ((const struct nidio_board *)dev->board_ptr)
+ 
+ static DEFINE_PCI_DEVICE_TABLE(ni_pcidio_pci_table) = {
+diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
+index 0dc639212ade..19d87553d906 100644
+--- a/drivers/staging/comedi/drivers/ni_pcimio.c
++++ b/drivers/staging/comedi/drivers/ni_pcimio.c
+@@ -1208,7 +1208,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 	 },
+ };
+ 
+-#define n_pcimio_boards ((sizeof(ni_boards)/sizeof(ni_boards[0])))
++#define n_pcimio_boards ARRAY_SIZE(ni_boards)
+ 
+ static int pcimio_attach(struct comedi_device *dev,
+ 			 struct comedi_devconfig *it);
+diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c
+index 7368bf3011c9..acac67090810 100644
+--- a/drivers/staging/comedi/drivers/pcmad.c
++++ b/drivers/staging/comedi/drivers/pcmad.c
+@@ -69,7 +69,7 @@ static const struct pcmad_board_struct pcmad_boards[] = {
+ };
+ 
+ #define this_board ((const struct pcmad_board_struct *)(dev->board_ptr))
+-#define n_pcmad_boards (sizeof(pcmad_boards)/sizeof(pcmad_boards[0]))
++#define n_pcmad_boards ARRAY_SIZE(pcmad_boards)
+ 
+ struct pcmad_priv_struct {
+ 	int differential;
+diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c
+index 729a0d8766e8..d23e588d0632 100644
+--- a/drivers/staging/comedi/drivers/poc.c
++++ b/drivers/staging/comedi/drivers/poc.c
+@@ -102,7 +102,7 @@ static const struct boarddef_struct boards[] = {
+ 	 },
+ };
+ 
+-#define n_boards (sizeof(boards)/sizeof(boards[0]))
++#define n_boards ARRAY_SIZE(boards)
+ #define this_board ((const struct boarddef_struct *)dev->board_ptr)
+ 
+ static struct comedi_driver driver_poc = {
+diff --git a/drivers/staging/epl/EplDllk.c b/drivers/staging/epl/EplDllk.c
+index 25d2c34325db..0572c3d0aefd 100644
+--- a/drivers/staging/epl/EplDllk.c
++++ b/drivers/staging/epl/EplDllk.c
+@@ -328,7 +328,7 @@ tEplKernel EplDllkAddInstance(tEplDllkInitParam * pInitParam_p)
+ 	// initialize and link pointers in instance structure to frame tables
+ 	EplDllkInstance_g.m_pTxBuffer = aEplDllkTxBuffer_l;
+ 	EplDllkInstance_g.m_uiMaxTxFrames =
+-	    sizeof(aEplDllkTxBuffer_l) / sizeof(tEdrvTxBuffer);
++	    ARRAY_SIZE(aEplDllkTxBuffer_l);
+ 
+ 	// initialize state
+ 	EplDllkInstance_g.m_DllState = kEplDllGsInit;
+diff --git a/drivers/staging/epl/proc_fs.c b/drivers/staging/epl/proc_fs.c
+index 9ccf079e67e1..e48949d9ddf5 100644
+--- a/drivers/staging/epl/proc_fs.c
++++ b/drivers/staging/epl/proc_fs.c
+@@ -196,7 +196,7 @@ void TgtDbgSignalTracePoint(u8 bTracePointNumber_p)
+ {
+ 
+ 	if (bTracePointNumber_p >=
+-	    (sizeof(aatmDbgTracePoint_l) / sizeof(aatmDbgTracePoint_l[0]))) {
++	    ARRAY_SIZE(aatmDbgTracePoint_l)) {
+ 		goto Exit;
+ 	}
+ 
+@@ -330,7 +330,7 @@ static int EplLinProcRead(char *pcBuffer_p,
+ 		nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
+ 				  "DbgTracePoints:\n");
+ 		for (nNum = 0;
+-		     nNum < (sizeof(aatmDbgTracePoint_l) / sizeof(atomic_t));
++		     nNum < ARRAY_SIZE(aatmDbgTracePoint_l);
+ 		     nNum++) {
+ 			nSize +=
+ 			    snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
+diff --git a/drivers/staging/line6/driver.c b/drivers/staging/line6/driver.c
+index 85a20d0002c0..f188ecee502f 100644
+--- a/drivers/staging/line6/driver.c
++++ b/drivers/staging/line6/driver.c
+@@ -682,7 +682,7 @@ static int line6_probe(struct usb_interface *interface, const struct usb_device_
+ 		return -ENODEV;
+ 
+ 	/* check vendor and product id */
+-	for (devtype = sizeof(line6_id_table) / sizeof(line6_id_table[0]) - 1; devtype--;)
++	for (devtype = ARRAY_SIZE(line6_id_table) - 1; devtype--;)
+ 		if ((le16_to_cpu(usbdev->descriptor.idVendor) == line6_id_table[devtype].idVendor) &&
+ 			 (le16_to_cpu(usbdev->descriptor.idProduct) == line6_id_table[devtype].idProduct))
+ 			break;
+diff --git a/drivers/staging/meilhaus/me0600_device.h b/drivers/staging/meilhaus/me0600_device.h
+index d93a8aee581b..75bd3b7351d2 100644
+--- a/drivers/staging/meilhaus/me0600_device.h
++++ b/drivers/staging/meilhaus/me0600_device.h
+@@ -54,7 +54,7 @@ static me0600_version_t me0600_versions[] = {
+ 	{0},
+ };
+ 
+-#define ME0600_DEVICE_VERSIONS (sizeof(me0600_versions) / sizeof(me0600_version_t) - 1)	/**< Returns the number of entries in #me0600_versions. */
++#define ME0600_DEVICE_VERSIONS (ARRAY_SIZE(me0600_versions) - 1)	/**< Returns the number of entries in #me0600_versions. */
+ 
+ /**
+  * @brief Returns the index of the device entry in #me0600_versions.
+diff --git a/drivers/staging/meilhaus/me0900_device.h b/drivers/staging/meilhaus/me0900_device.h
+index bd17f2521511..53c05e83675d 100644
+--- a/drivers/staging/meilhaus/me0900_device.h
++++ b/drivers/staging/meilhaus/me0900_device.h
+@@ -53,7 +53,7 @@ static me0900_version_t me0900_versions[] = {
+ 	{0},
+ };
+ 
+-#define ME0900_DEVICE_VERSIONS (sizeof(me0900_versions) / sizeof(me0900_version_t) - 1)	/**< Returns the number of entries in #me0900_versions. */
++#define ME0900_DEVICE_VERSIONS (ARRAY_SIZE(me0900_versions) - 1)	/**< Returns the number of entries in #me0900_versions. */
+ 
+ /**
+  * @brief Returns the index of the device entry in #me0900_versions.
+diff --git a/drivers/staging/meilhaus/me1400_device.h b/drivers/staging/meilhaus/me1400_device.h
+index 6215b250047d..d20112d8da60 100644
+--- a/drivers/staging/meilhaus/me1400_device.h
++++ b/drivers/staging/meilhaus/me1400_device.h
+@@ -60,7 +60,7 @@ static me1400_version_t me1400_versions[] = {
+ 	{0}
+ };
+ 
+-#define ME1400_DEVICE_VERSIONS (sizeof(me1400_versions) / sizeof(me1400_version_t) - 1)	/**< Returns the number of entries in #me1400_versions. */
++#define ME1400_DEVICE_VERSIONS (ARRAY_SIZE(me1400_versions) - 1)	/**< Returns the number of entries in #me1400_versions. */
+ 
+ /**
+  * @brief Returns the index of the device entry in #me1400_versions.
+diff --git a/drivers/staging/meilhaus/me1600_device.h b/drivers/staging/meilhaus/me1600_device.h
+index f7b231f73ac8..c73aca11ae88 100644
+--- a/drivers/staging/meilhaus/me1600_device.h
++++ b/drivers/staging/meilhaus/me1600_device.h
+@@ -58,7 +58,7 @@ static me1600_version_t me1600_versions[] = {
+ };
+ 
+ /**< Returns the number of entries in #me1600_versions. */
+-#define ME1600_DEVICE_VERSIONS (sizeof(me1600_versions) / sizeof(me1600_version_t) - 1)
++#define ME1600_DEVICE_VERSIONS (ARRAY_SIZE(me1600_versions) - 1)
+ 
+ /**
+  * @brief Returns the index of the device entry in #me1600_versions.
+diff --git a/drivers/staging/meilhaus/me4600_device.h b/drivers/staging/meilhaus/me4600_device.h
+index fa812d4cc6dc..c755c574cda2 100644
+--- a/drivers/staging/meilhaus/me4600_device.h
++++ b/drivers/staging/meilhaus/me4600_device.h
+@@ -80,7 +80,7 @@ static me4600_version_t me4600_versions[] = {
+ 	{0},
+ };
+ 
+-#define ME4600_DEVICE_VERSIONS (sizeof(me4600_versions) / sizeof(me4600_version_t) - 1)	/**< Returns the number of entries in #me4600_versions. */
++#define ME4600_DEVICE_VERSIONS (ARRAY_SIZE(me4600_versions) - 1)	/**< Returns the number of entries in #me4600_versions. */
+ 
+ /**
+  * @brief Returns the index of the device entry in #me4600_versions.
+diff --git a/drivers/staging/meilhaus/me6000_device.h b/drivers/staging/meilhaus/me6000_device.h
+index 18cc7d1e14f1..eed401152101 100644
+--- a/drivers/staging/meilhaus/me6000_device.h
++++ b/drivers/staging/meilhaus/me6000_device.h
+@@ -103,7 +103,7 @@ static me6000_version_t me6000_versions[] = {
+ 	{0},
+ };
+ 
+-#define ME6000_DEVICE_VERSIONS (sizeof(me6000_versions) / sizeof(me6000_version_t) - 1)	/**< Returns the number of entries in #me6000_versions. */
++#define ME6000_DEVICE_VERSIONS (ARRAY_SIZE(me6000_versions) - 1)	/**< Returns the number of entries in #me6000_versions. */
+ 
+ /**
+  * @brief Returns the index of the device entry in #me6000_versions.
+diff --git a/drivers/staging/meilhaus/me8100_device.h b/drivers/staging/meilhaus/me8100_device.h
+index 44c42efb04e2..238dc0622801 100644
+--- a/drivers/staging/meilhaus/me8100_device.h
++++ b/drivers/staging/meilhaus/me8100_device.h
+@@ -53,7 +53,7 @@ static me8100_version_t me8100_versions[] = {
+ 	{0},
+ };
+ 
+-#define ME8100_DEVICE_VERSIONS (sizeof(me8100_versions) / sizeof(me8100_version_t) - 1)	/**< Returns the number of entries in #me8100_versions. */
++#define ME8100_DEVICE_VERSIONS (ARRAY_SIZE(me8100_versions) - 1)	/**< Returns the number of entries in #me8100_versions. */
+ 
+ /**
+  * @brief Returns the index of the device entry in #me8100_versions.
+diff --git a/drivers/staging/meilhaus/me8200_device.h b/drivers/staging/meilhaus/me8200_device.h
+index cbd2a01ddb41..66f50842dac0 100644
+--- a/drivers/staging/meilhaus/me8200_device.h
++++ b/drivers/staging/meilhaus/me8200_device.h
+@@ -53,7 +53,7 @@ static me8200_version_t me8200_versions[] = {
+ 	{0},
+ };
+ 
+-#define ME8200_DEVICE_VERSIONS (sizeof(me8200_versions) / sizeof(me8200_version_t) - 1)	/**< Returns the number of entries in #me8200_versions. */
++#define ME8200_DEVICE_VERSIONS (ARRAY_SIZE(me8200_versions) - 1)	/**< Returns the number of entries in #me8200_versions. */
+ 
+ /**
+  * @brief Returns the index of the device entry in #me8200_versions.
+diff --git a/drivers/staging/meilhaus/metempl_device.h b/drivers/staging/meilhaus/metempl_device.h
+index 3c3702cc72eb..c0626e7b73a7 100644
+--- a/drivers/staging/meilhaus/metempl_device.h
++++ b/drivers/staging/meilhaus/metempl_device.h
+@@ -50,7 +50,7 @@ static metempl_version_t metempl_versions[] = {
+ 	{0},
+ };
+ 
+-#define METEMPL_DEVICE_VERSIONS (sizeof(metempl_versions) / sizeof(metempl_version_t) - 1) /**< Returns the number of entries in #metempl_versions. */
++#define METEMPL_DEVICE_VERSIONS (ARRAY_SIZE(metempl_versions) - 1) /**< Returns the number of entries in #metempl_versions. */
+ 
+ /**
+  * @brief Returns the index of the device entry in #metempl_versions.
+diff --git a/drivers/staging/rtl8187se/r8180_wx.c b/drivers/staging/rtl8187se/r8180_wx.c
+index 081c022f0bc2..766892e31f52 100644
+--- a/drivers/staging/rtl8187se/r8180_wx.c
++++ b/drivers/staging/rtl8187se/r8180_wx.c
+@@ -27,7 +27,7 @@
+ u32 rtl8180_rates[] = {1000000,2000000,5500000,11000000,
+ 	6000000,9000000,12000000,18000000,24000000,36000000,48000000,54000000};
+ 
+-#define RATE_COUNT (sizeof(rtl8180_rates)/sizeof(rtl8180_rates[0]))
++#define RATE_COUNT ARRAY_SIZE(rtl8180_rates)
+ 
+ static CHANNEL_LIST DefaultChannelPlan[] = {
+ //	{{1,2,3,4,5,6,7,8,9,10,11,12,13,14},14},			//Default channel plan
+@@ -1578,9 +1578,9 @@ static struct iw_statistics *r8180_get_wireless_stats(struct net_device *dev)
+ 
+ struct iw_handler_def  r8180_wx_handlers_def={
+ 	.standard = r8180_wx_handlers,
+-	.num_standard = sizeof(r8180_wx_handlers) / sizeof(iw_handler),
++	.num_standard = ARRAY_SIZE(r8180_wx_handlers),
+ 	.private = r8180_private_handler,
+-	.num_private = sizeof(r8180_private_handler) / sizeof(iw_handler),
++	.num_private = ARRAY_SIZE(r8180_private_handler),
+  	.num_private_args = sizeof(r8180_private_args) / sizeof(struct iw_priv_args),
+ 	.get_wireless_stats = r8180_get_wireless_stats,
+ 	.private_args = (struct iw_priv_args *)r8180_private_args,
+diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c
+index 3afd8b34f68c..145a3120c6bb 100644
+--- a/drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c
++++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c
+@@ -87,7 +87,7 @@ static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee,
+         }
+ 	/* Add the protocol name */
+ 	iwe.cmd = SIOCGIWNAME;
+-	for(i=0; i<(sizeof(ieee80211_modes)/sizeof(ieee80211_modes[0])); i++) {
++	for(i=0; imode&(1<
commit 62f589c5e391dc2081db42e801382304c652e43a
+Author: Stoyan Gaydarov 
+Date:   Wed Jul 22 05:02:33 2009 +0200
+
+    ARRAY_SIZE changes
+    
+    These changes were a direct result of using a semantic patch
+    More information can be found at http://www.emn.fr/x-info/coccinelle/
+    
+    Signed-off-by: Stoyan Gaydarov 
+    Signed-off-by: Jesper Nilsson 
+
+diff --git a/arch/cris/arch-v32/mach-a3/io.c b/arch/cris/arch-v32/mach-a3/io.c
+index c22f67ecd9f3..090ceb99ef0b 100644
+--- a/arch/cris/arch-v32/mach-a3/io.c
++++ b/arch/cris/arch-v32/mach-a3/io.c
+@@ -36,7 +36,7 @@ struct crisv32_ioport crisv32_ioports[] = {
+ 	},
+ };
+ 
+-#define NBR_OF_PORTS sizeof(crisv32_ioports)/sizeof(struct crisv32_ioport)
++#define NBR_OF_PORTS ARRAY_SIZE(crisv32_ioports)
+ 
+ struct crisv32_iopin crisv32_led_net0_green;
+ struct crisv32_iopin crisv32_led_net0_red;
+diff --git a/arch/cris/arch-v32/mach-fs/io.c b/arch/cris/arch-v32/mach-fs/io.c
+index cb6327b1f8f8..a6958661fa8e 100644
+--- a/arch/cris/arch-v32/mach-fs/io.c
++++ b/arch/cris/arch-v32/mach-fs/io.c
+@@ -52,7 +52,7 @@ struct crisv32_ioport crisv32_ioports[] = {
+ 	}
+ };
+ 
+-#define NBR_OF_PORTS sizeof(crisv32_ioports)/sizeof(struct crisv32_ioport)
++#define NBR_OF_PORTS ARRAY_SIZE(crisv32_ioports)
+ 
+ struct crisv32_iopin crisv32_led_net0_green;
+ struct crisv32_iopin crisv32_led_net0_red;

commit a888ad451a96881a7e40f40f717d05f1f3b26ad4
+Author: Stoyan Gaydarov 
+Date:   Tue Jul 21 17:02:31 2009 +0000
+
+    powerpc: ARRAY_SIZE changes in pasemi and powermac code
+    
+    These changes were a direct result of using a semantic patch
+    More information can be found at http://www.emn.fr/x-info/coccinelle/
+    
+    Signed-off-by: Stoyan Gaydarov 
+    Signed-off-by: Benjamin Herrenschmidt 
+
+diff --git a/arch/powerpc/platforms/pasemi/idle.c b/arch/powerpc/platforms/pasemi/idle.c
+index 43911d8b0206..75b296bc51af 100644
+--- a/arch/powerpc/platforms/pasemi/idle.c
++++ b/arch/powerpc/platforms/pasemi/idle.c
+@@ -90,7 +90,7 @@ machine_late_initcall(pasemi, pasemi_idle_init);
+ static int __init idle_param(char *p)
+ {
+ 	int i;
+-	for (i = 0; i < sizeof(modes)/sizeof(struct sleep_mode); i++) {
++	for (i = 0; i < ARRAY_SIZE(modes); i++) {
+ 		if (!strcmp(modes[i].name, p)) {
+ 			current_mode = i;
+ 			break;
+diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c
+index e6c0040ee797..095de3227d83 100644
+--- a/arch/powerpc/platforms/powermac/feature.c
++++ b/arch/powerpc/platforms/powermac/feature.c
+@@ -2419,13 +2419,13 @@ static int __init probe_motherboard(void)
+ 	dt = of_find_node_by_name(NULL, "device-tree");
+ 	if (dt != NULL)
+ 		model = of_get_property(dt, "model", NULL);
+-	for(i=0; model && i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) {
++	for(i=0; model && i
commit 2020002a878403a6858868d85a43623f74859dba
+Author: Stoyan Gaydarov 
+Date:   Thu Aug 6 15:07:28 2009 -0700
+
+    drivers/w1/masters/omap_hdq.c: fix missing mutex unlock
+    
+    This was found using a semantic patch, more info can be found at:
+    http://www.emn.fr/x-info/coccinelle/
+    
+    Signed-off-by: Stoyan Gaydarov 
+    Acked-by: Evgeniy Polyakov 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c
+index a7e3b706b9d3..0d92969404c3 100644
+--- a/drivers/w1/masters/omap_hdq.c
++++ b/drivers/w1/masters/omap_hdq.c
+@@ -687,6 +687,7 @@ static int omap_hdq_remove(struct platform_device *pdev)
+ 
+ 	if (hdq_data->hdq_usecount) {
+ 		dev_dbg(&pdev->dev, "removed when use count is not zero\n");
++		mutex_unlock(&hdq_data->hdq_mutex);
+ 		return -EBUSY;
+ 	}
+ 

commit 9b30a26bf3d2c56dcb1c3afaca28b73fcd6ed405
+Author: Stoyan Gaydarov 
+Date:   Thu Jul 30 05:25:29 2009 -0500
+
+    perf tools: Fix faulty check
+    
+    This patch fixes a spelling error that has resulted from copy
+    and pasting. The location of the error was found using a
+    semantic patch but the semantic patch was not trying to find
+    these errors. After looking things over it seemed logical that
+    this change was needed. Please review it and then include the
+    patch if it is in fact the correct change.
+    
+    Signed-off-by: Stoyan Gaydarov 
+    Signed-off-by: Peter Zijlstra 
+    Cc: Mike Galbraith 
+    Cc: Paul Mackerras 
+    Cc: Arnaldo Carvalho de Melo 
+    Cc: Frederic Weisbecker 
+    LKML-Reference: <1248949529-20891-1-git-send-email-sgayda2@uiuc.edu>
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
+index 28106059bf12..b4fe0579bd6b 100644
+--- a/tools/perf/util/symbol.c
++++ b/tools/perf/util/symbol.c
+@@ -565,7 +565,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
+ 		goto out_elf_end;
+ 
+ 	secstrs = elf_getdata(sec_strndx, NULL);
+-	if (symstrs == NULL)
++	if (secstrs == NULL)
+ 		goto out_elf_end;
+ 
+ 	nr_syms = shdr.sh_size / shdr.sh_entsize;

commit 450d6e306b4717bfae11218a02648509baf04ce1
+Author: Stoyan Gaydarov 
+Date:   Thu Jul 30 10:25:19 2009 +0000
+
+    parisc: fixed faulty check in lba_pci
+    
+    This patche fixes a spelling error that has resulted from copy and pasting.
+    The location of the error was found using a semantic patch but the semantic
+    patch was not trying to find these errors. After looking things over it
+    seemed logical that this change was needed.
+    
+    Signed-off-by: Stoyan Gaydarov 
+    Signed-off-by: Helge Deller 
+
+diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
+index ede614616f8e..3aeb3279c92a 100644
+--- a/drivers/parisc/lba_pci.c
++++ b/drivers/parisc/lba_pci.c
+@@ -992,7 +992,7 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
+ 		return;
+ 
+ 	io_pdc_cell = kzalloc(sizeof(pdc_pat_cell_mod_maddr_block_t), GFP_KERNEL);
+-	if (!pa_pdc_cell) {
++	if (!io_pdc_cell) {
+ 		kfree(pa_pdc_cell);
+ 		return;
+ 	}

\ No newline at end of file diff --git a/detail/29.html b/detail/29.html new file mode 100644 index 0000000..d97ed89 --- /dev/null +++ b/detail/29.html @@ -0,0 +1,8407 @@ +

Patches contributed by Auburn University


commit c93396e13576928a073154b5715761ff8a998368
+Author: Theodore Kilgore 
+Date:   Mon Feb 4 13:17:55 2013 -0300
+
+    [media] gspca: Remove gspca-specific debug magic
+    
+    Instead use v4l2_dbg and v4l2_err. Note that the PDEBUG macro is kept to
+    make this patch-set less invasive, but it is simply a wrapper around
+    v4l2_dbg now. Most of the other changes are there to make the dev parameter
+    for the v4l2_xxx macros available everywhere we do logging.
+    
+    Signed-off-by: Theodore Kilgore 
+    Signed-off-by: Hans de Goede 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/usb/gspca/benq.c b/drivers/media/usb/gspca/benq.c
+index 352f32190e68..05f406deae13 100644
+--- a/drivers/media/usb/gspca/benq.c
++++ b/drivers/media/usb/gspca/benq.c
+@@ -186,7 +186,7 @@ static void sd_isoc_irq(struct urb *urb)
+ 		/* check the packet status and length */
+ 		if (urb0->iso_frame_desc[i].actual_length != SD_PKT_SZ
+ 		    || urb->iso_frame_desc[i].actual_length != SD_PKT_SZ) {
+-			PDEBUG(D_ERR, "ISOC bad lengths %d / %d",
++			PERR("ISOC bad lengths %d / %d",
+ 				urb0->iso_frame_desc[i].actual_length,
+ 				urb->iso_frame_desc[i].actual_length);
+ 			gspca_dev->last_packet_type = DISCARD_PACKET;
+diff --git a/drivers/media/usb/gspca/conex.c b/drivers/media/usb/gspca/conex.c
+index c9052f20435e..38714df31ac4 100644
+--- a/drivers/media/usb/gspca/conex.c
++++ b/drivers/media/usb/gspca/conex.c
+@@ -73,12 +73,11 @@ static void reg_r(struct gspca_dev *gspca_dev,
+ {
+ 	struct usb_device *dev = gspca_dev->dev;
+ 
+-#ifdef GSPCA_DEBUG
+ 	if (len > USB_BUF_SZ) {
+-		pr_err("reg_r: buffer overflow\n");
++		PERR("reg_r: buffer overflow\n");
+ 		return;
+ 	}
+-#endif
++
+ 	usb_control_msg(dev,
+ 			usb_rcvctrlpipe(dev, 0),
+ 			0,
+@@ -113,13 +112,12 @@ static void reg_w(struct gspca_dev *gspca_dev,
+ {
+ 	struct usb_device *dev = gspca_dev->dev;
+ 
+-#ifdef GSPCA_DEBUG
+ 	if (len > USB_BUF_SZ) {
+-		pr_err("reg_w: buffer overflow\n");
++		PERR("reg_w: buffer overflow\n");
+ 		return;
+ 	}
+ 	PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
+-#endif
++
+ 	memcpy(gspca_dev->usb_buf, buffer, len);
+ 	usb_control_msg(dev,
+ 			usb_sndctrlpipe(dev, 0),
+@@ -689,7 +687,7 @@ static void cx11646_jpeg(struct gspca_dev*gspca_dev)
+ 		reg_w_val(gspca_dev, 0x0053, 0x00);
+ 	} while (--retry);
+ 	if (retry == 0)
+-		PDEBUG(D_ERR, "Damned Errors sending jpeg Table");
++		PERR("Damned Errors sending jpeg Table");
+ 	/* send the qtable now */
+ 	reg_r(gspca_dev, 0x0001, 1);		/* -> 0x18 */
+ 	length = 8;
+diff --git a/drivers/media/usb/gspca/cpia1.c b/drivers/media/usb/gspca/cpia1.c
+index 1dcdd9f95f1c..064b53043b15 100644
+--- a/drivers/media/usb/gspca/cpia1.c
++++ b/drivers/media/usb/gspca/cpia1.c
+@@ -421,8 +421,7 @@ static int cpia_usb_transferCmd(struct gspca_dev *gspca_dev, u8 *command)
+ 		pipe = usb_sndctrlpipe(gspca_dev->dev, 0);
+ 		requesttype = USB_TYPE_VENDOR | USB_RECIP_DEVICE;
+ 	} else {
+-		PDEBUG(D_ERR, "Unexpected first byte of command: %x",
+-		       command[0]);
++		PERR("Unexpected first byte of command: %x", command[0]);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -701,7 +700,7 @@ static void reset_camera_params(struct gspca_dev *gspca_dev)
+ 	params->qx3.cradled = 0;
+ }
+ 
+-static void printstatus(struct cam_params *params)
++static void printstatus(struct gspca_dev *gspca_dev, struct cam_params *params)
+ {
+ 	PDEBUG(D_PROBE, "status: %02x %02x %02x %02x %02x %02x %02x %02x",
+ 	       params->status.systemState, params->status.grabState,
+@@ -725,10 +724,9 @@ static int goto_low_power(struct gspca_dev *gspca_dev)
+ 
+ 	if (sd->params.status.systemState != LO_POWER_STATE) {
+ 		if (sd->params.status.systemState != WARM_BOOT_STATE) {
+-			PDEBUG(D_ERR,
+-			       "unexpected state after lo power cmd: %02x",
+-			       sd->params.status.systemState);
+-			printstatus(&sd->params);
++			PERR("unexpected state after lo power cmd: %02x",
++			     sd->params.status.systemState);
++			printstatus(gspca_dev, &sd->params);
+ 		}
+ 		return -EIO;
+ 	}
+@@ -756,9 +754,9 @@ static int goto_high_power(struct gspca_dev *gspca_dev)
+ 		return ret;
+ 
+ 	if (sd->params.status.systemState != HI_POWER_STATE) {
+-		PDEBUG(D_ERR, "unexpected state after hi power cmd: %02x",
+-			       sd->params.status.systemState);
+-		printstatus(&sd->params);
++		PERR("unexpected state after hi power cmd: %02x",
++		     sd->params.status.systemState);
++		printstatus(gspca_dev, &sd->params);
+ 		return -EIO;
+ 	}
+ 
+@@ -1449,8 +1447,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ 	sd->params.version.firmwareVersion = 0;
+ 	get_version_information(gspca_dev);
+ 	if (sd->params.version.firmwareVersion != 1) {
+-		PDEBUG(D_ERR, "only firmware version 1 is supported (got: %d)",
+-		       sd->params.version.firmwareVersion);
++		PERR("only firmware version 1 is supported (got: %d)",
++		     sd->params.version.firmwareVersion);
+ 		return -ENODEV;
+ 	}
+ 
+@@ -1475,9 +1473,9 @@ static int sd_start(struct gspca_dev *gspca_dev)
+ 	/* Start the camera in low power mode */
+ 	if (goto_low_power(gspca_dev)) {
+ 		if (sd->params.status.systemState != WARM_BOOT_STATE) {
+-			PDEBUG(D_ERR, "unexpected systemstate: %02x",
+-			       sd->params.status.systemState);
+-			printstatus(&sd->params);
++			PERR("unexpected systemstate: %02x",
++			     sd->params.status.systemState);
++			printstatus(gspca_dev, &sd->params);
+ 			return -ENODEV;
+ 		}
+ 
+@@ -1523,9 +1521,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
+ 		return ret;
+ 
+ 	if (sd->params.status.fatalError) {
+-		PDEBUG(D_ERR, "fatal_error: %04x, vp_status: %04x",
+-		       sd->params.status.fatalError,
+-		       sd->params.status.vpStatus);
++		PERR("fatal_error: %04x, vp_status: %04x",
++		     sd->params.status.fatalError, sd->params.status.vpStatus);
+ 		return -EIO;
+ 	}
+ 
+diff --git a/drivers/media/usb/gspca/etoms.c b/drivers/media/usb/gspca/etoms.c
+index 38f68e11c3a2..948a6357573d 100644
+--- a/drivers/media/usb/gspca/etoms.c
++++ b/drivers/media/usb/gspca/etoms.c
+@@ -163,12 +163,11 @@ static void reg_r(struct gspca_dev *gspca_dev,
+ {
+ 	struct usb_device *dev = gspca_dev->dev;
+ 
+-#ifdef GSPCA_DEBUG
+ 	if (len > USB_BUF_SZ) {
+-		pr_err("reg_r: buffer overflow\n");
++		PERR("reg_r: buffer overflow\n");
+ 		return;
+ 	}
+-#endif
++
+ 	usb_control_msg(dev,
+ 			usb_rcvctrlpipe(dev, 0),
+ 			0,
+@@ -201,13 +200,12 @@ static void reg_w(struct gspca_dev *gspca_dev,
+ {
+ 	struct usb_device *dev = gspca_dev->dev;
+ 
+-#ifdef GSPCA_DEBUG
+ 	if (len > USB_BUF_SZ) {
+ 		pr_err("reg_w: buffer overflow\n");
+ 		return;
+ 	}
+ 	PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
+-#endif
++
+ 	memcpy(gspca_dev->usb_buf, buffer, len);
+ 	usb_control_msg(dev,
+ 			usb_sndctrlpipe(dev, 0),
+@@ -274,7 +272,7 @@ static int et_video(struct gspca_dev *gspca_dev,
+ 		     : 0);		/* stopvideo */
+ 	ret = Et_WaitStatus(gspca_dev);
+ 	if (ret != 0)
+-		PDEBUG(D_ERR, "timeout video on/off");
++		PERR("timeout video on/off");
+ 	return ret;
+ }
+ 
+diff --git a/drivers/media/usb/gspca/gl860/gl860.c b/drivers/media/usb/gspca/gl860/gl860.c
+index 96d9c28a748c..cb1e64ca59c9 100644
+--- a/drivers/media/usb/gspca/gl860/gl860.c
++++ b/drivers/media/usb/gspca/gl860/gl860.c
+@@ -582,7 +582,7 @@ int gl860_RTx(struct gspca_dev *gspca_dev,
+ 		pr_err("ctrl transfer failed %4d [p%02x r%d v%04x i%04x len%d]\n",
+ 		       r, pref, req, val, index, len);
+ 	else if (len > 1 && r < len)
+-		PDEBUG(D_ERR, "short ctrl transfer %d/%d", r, len);
++		PERR("short ctrl transfer %d/%d", r, len);
+ 
+ 	msleep(1);
+ 
+diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c
+index 5784ff4e1b2f..5800d65f9144 100644
+--- a/drivers/media/usb/gspca/gspca.c
++++ b/drivers/media/usb/gspca/gspca.c
+@@ -60,14 +60,14 @@ MODULE_DESCRIPTION("GSPCA USB Camera Driver");
+ MODULE_LICENSE("GPL");
+ MODULE_VERSION(GSPCA_VERSION);
+ 
+-#ifdef GSPCA_DEBUG
+-int gspca_debug = D_ERR | D_PROBE;
++int gspca_debug;
+ EXPORT_SYMBOL(gspca_debug);
+ 
+-static void PDEBUG_MODE(char *txt, __u32 pixfmt, int w, int h)
++static void PDEBUG_MODE(struct gspca_dev *gspca_dev, int debug, char *txt,
++			__u32 pixfmt, int w, int h)
+ {
+ 	if ((pixfmt >> 24) >= '0' && (pixfmt >> 24) <= 'z') {
+-		PDEBUG(D_CONF|D_STREAM, "%s %c%c%c%c %dx%d",
++		PDEBUG(debug, "%s %c%c%c%c %dx%d",
+ 			txt,
+ 			pixfmt & 0xff,
+ 			(pixfmt >> 8) & 0xff,
+@@ -75,15 +75,12 @@ static void PDEBUG_MODE(char *txt, __u32 pixfmt, int w, int h)
+ 			pixfmt >> 24,
+ 			w, h);
+ 	} else {
+-		PDEBUG(D_CONF|D_STREAM, "%s 0x%08x %dx%d",
++		PDEBUG(debug, "%s 0x%08x %dx%d",
+ 			txt,
+ 			pixfmt,
+ 			w, h);
+ 	}
+ }
+-#else
+-#define PDEBUG_MODE(txt, pixfmt, w, h)
+-#endif
+ 
+ /* specific memory types - !! should be different from V4L2_MEMORY_xxx */
+ #define GSPCA_MEMORY_NO 0	/* V4L2_MEMORY_xxx starts from 1 */
+@@ -129,7 +126,7 @@ static void int_irq(struct urb *urb)
+ 	case 0:
+ 		if (gspca_dev->sd_desc->int_pkt_scan(gspca_dev,
+ 		    urb->transfer_buffer, urb->actual_length) < 0) {
+-			PDEBUG(D_ERR, "Unknown packet received");
++			PERR("Unknown packet received");
+ 		}
+ 		break;
+ 
+@@ -143,7 +140,7 @@ static void int_irq(struct urb *urb)
+ 		break;
+ 
+ 	default:
+-		PDEBUG(D_ERR, "URB error %i, resubmitting", urb->status);
++		PERR("URB error %i, resubmitting", urb->status);
+ 		urb->status = 0;
+ 		ret = 0;
+ 	}
+@@ -229,7 +226,7 @@ static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev,
+ 	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ 	ret = usb_submit_urb(urb, GFP_KERNEL);
+ 	if (ret < 0) {
+-		PDEBUG(D_ERR, "submit int URB failed with error %i", ret);
++		PERR("submit int URB failed with error %i", ret);
+ 		goto error_submit;
+ 	}
+ 	gspca_dev->int_urb = urb;
+@@ -315,7 +312,7 @@ static void fill_frame(struct gspca_dev *gspca_dev,
+ 		if (gspca_dev->frozen)
+ 			return;
+ #endif
+-		PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
++		PERR("urb status: %d", urb->status);
+ 		urb->status = 0;
+ 		goto resubmit;
+ 	}
+@@ -388,7 +385,7 @@ static void bulk_irq(struct urb *urb)
+ 		if (gspca_dev->frozen)
+ 			return;
+ #endif
+-		PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
++		PERR("urb status: %d", urb->status);
+ 		urb->status = 0;
+ 		goto resubmit;
+ 	}
+@@ -460,7 +457,7 @@ void gspca_frame_add(struct gspca_dev *gspca_dev,
+ 	/* append the packet to the frame buffer */
+ 	if (len > 0) {
+ 		if (gspca_dev->image_len + len > gspca_dev->frsz) {
+-			PDEBUG(D_ERR|D_PACK, "frame overflow %d > %d",
++			PERR("frame overflow %d > %d",
+ 				gspca_dev->image_len + len,
+ 				gspca_dev->frsz);
+ 			packet_type = DISCARD_PACKET;
+@@ -960,9 +957,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
+ 		/* the bandwidth is not wide enough
+ 		 * negotiate or try a lower alternate setting */
+ retry:
+-		PDEBUG(D_ERR|D_STREAM,
+-			"alt %d - bandwidth not wide enough - trying again",
+-			alt);
++		PERR("alt %d - bandwidth not wide enough, trying again", alt);
+ 		msleep(20);	/* wait for kill complete */
+ 		if (gspca_dev->sd_desc->isoc_nego) {
+ 			ret = gspca_dev->sd_desc->isoc_nego(gspca_dev);
+@@ -1127,10 +1122,9 @@ static int try_fmt_vid_cap(struct gspca_dev *gspca_dev,
+ 	w = fmt->fmt.pix.width;
+ 	h = fmt->fmt.pix.height;
+ 
+-#ifdef GSPCA_DEBUG
+-	if (gspca_debug & D_CONF)
+-		PDEBUG_MODE("try fmt cap", fmt->fmt.pix.pixelformat, w, h);
+-#endif
++	PDEBUG_MODE(gspca_dev, D_CONF, "try fmt cap",
++		    fmt->fmt.pix.pixelformat, w, h);
++
+ 	/* search the closest mode for width and height */
+ 	mode = wxh_to_mode(gspca_dev, w, h);
+ 
+@@ -1143,8 +1137,6 @@ static int try_fmt_vid_cap(struct gspca_dev *gspca_dev,
+ 					fmt->fmt.pix.pixelformat);
+ 		if (mode2 >= 0)
+ 			mode = mode2;
+-/*		else
+-			;		 * no chance, return this mode */
+ 	}
+ 	fmt->fmt.pix = gspca_dev->cam.cam_mode[mode];
+ 	/* some drivers use priv internally, zero it before giving it to
+@@ -1280,15 +1272,6 @@ static int dev_open(struct file *file)
+ 	if (!try_module_get(gspca_dev->module))
+ 		return -ENODEV;
+ 
+-#ifdef GSPCA_DEBUG
+-	/* activate the v4l2 debug */
+-	if (gspca_debug & D_V4L2)
+-		gspca_dev->vdev.debug |= V4L2_DEBUG_IOCTL
+-					| V4L2_DEBUG_IOCTL_ARG;
+-	else
+-		gspca_dev->vdev.debug &= ~(V4L2_DEBUG_IOCTL
+-					| V4L2_DEBUG_IOCTL_ARG);
+-#endif
+ 	return v4l2_fh_open(file);
+ }
+ 
+@@ -1483,14 +1466,8 @@ static int vidioc_streamon(struct file *file, void *priv,
+ 		if (ret < 0)
+ 			goto out;
+ 	}
+-#ifdef GSPCA_DEBUG
+-	if (gspca_debug & D_STREAM) {
+-		PDEBUG_MODE("stream on OK",
+-			gspca_dev->pixfmt,
+-			gspca_dev->width,
+-			gspca_dev->height);
+-	}
+-#endif
++	PDEBUG_MODE(gspca_dev, D_STREAM, "stream on OK", gspca_dev->pixfmt,
++		    gspca_dev->width, gspca_dev->height);
+ 	ret = 0;
+ out:
+ 	mutex_unlock(&gspca_dev->queue_lock);
+@@ -1741,8 +1718,7 @@ static int vidioc_dqbuf(struct file *file, void *priv,
+ 		if (copy_to_user((__u8 __user *) frame->v4l2_buf.m.userptr,
+ 				 frame->data,
+ 				 frame->v4l2_buf.bytesused)) {
+-			PDEBUG(D_ERR|D_STREAM,
+-				"dqbuf cp to user failed");
++			PERR("dqbuf cp to user failed");
+ 			ret = -EFAULT;
+ 		}
+ 	}
+@@ -1954,8 +1930,7 @@ static ssize_t dev_read(struct file *file, char __user *data,
+ 		count = frame->v4l2_buf.bytesused;
+ 	ret = copy_to_user(data, frame->data, count);
+ 	if (ret != 0) {
+-		PDEBUG(D_ERR|D_STREAM,
+-			"read cp to user lack %d / %zd", ret, count);
++		PERR("read cp to user lack %d / %zd", ret, count);
+ 		ret = -EFAULT;
+ 		goto out;
+ 	}
+@@ -2290,10 +2265,6 @@ static void __exit gspca_exit(void)
+ module_init(gspca_init);
+ module_exit(gspca_exit);
+ 
+-#ifdef GSPCA_DEBUG
+ module_param_named(debug, gspca_debug, int, 0644);
+ MODULE_PARM_DESC(debug,
+-		"Debug (bit) 0x01:error 0x02:probe 0x04:config"
+-		" 0x08:stream 0x10:frame 0x20:packet"
+-		" 0x0100: v4l2");
+-#endif
++		"1:probe 2:config 3:stream 4:frame 5:packet 6:usbi 7:usbo");
+diff --git a/drivers/media/usb/gspca/gspca.h b/drivers/media/usb/gspca/gspca.h
+index ac62cd3b590e..c3af3212d51e 100644
+--- a/drivers/media/usb/gspca/gspca.h
++++ b/drivers/media/usb/gspca/gspca.h
+@@ -10,30 +10,26 @@
+ #include 
+ #include 
+ 
+-/* compilation option */
+-/*#define GSPCA_DEBUG 1*/
+ 
+-#ifdef GSPCA_DEBUG
+-/* GSPCA our debug messages */
++
++/* GSPCA debug codes */
++
++#define D_PROBE  1
++#define D_CONF   2
++#define D_STREAM 3
++#define D_FRAM   4
++#define D_PACK   5
++#define D_USBI   6
++#define D_USBO   7
++
+ extern int gspca_debug;
+-#define PDEBUG(level, fmt, ...)					\
+-do {								\
+-	if (gspca_debug & (level))				\
+-		pr_info(fmt, ##__VA_ARGS__);			\
+-} while (0)
+-
+-#define D_ERR  0x01
+-#define D_PROBE 0x02
+-#define D_CONF 0x04
+-#define D_STREAM 0x08
+-#define D_FRAM 0x10
+-#define D_PACK 0x20
+-#define D_USBI 0x00
+-#define D_USBO 0x00
+-#define D_V4L2 0x0100
+-#else
+-#define PDEBUG(level, fmt, ...) do {} while(0)
+-#endif
++
++
++#define PDEBUG(level, fmt, ...) \
++	v4l2_dbg(level, gspca_debug, &gspca_dev->v4l2_dev, fmt, ##__VA_ARGS__)
++
++#define PERR(fmt, ...) \
++	v4l2_err(&gspca_dev->v4l2_dev, fmt, ##__VA_ARGS__)
+ 
+ #define GSPCA_MAX_FRAMES 16	/* maximum number of video frame buffers */
+ /* image transfers */
+diff --git a/drivers/media/usb/gspca/jeilinj.c b/drivers/media/usb/gspca/jeilinj.c
+index 1ba29fe7fada..8da3dde38385 100644
+--- a/drivers/media/usb/gspca/jeilinj.c
++++ b/drivers/media/usb/gspca/jeilinj.c
+@@ -266,7 +266,7 @@ static int jlj_start(struct gspca_dev *gspca_dev)
+ 	msleep(2);
+ 	setfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->freq));
+ 	if (gspca_dev->usb_err < 0)
+-		PDEBUG(D_ERR, "Start streaming command failed");
++		PERR("Start streaming command failed");
+ 	return gspca_dev->usb_err;
+ }
+ 
+diff --git a/drivers/media/usb/gspca/konica.c b/drivers/media/usb/gspca/konica.c
+index 61e25dbf2447..39c96bb4c985 100644
+--- a/drivers/media/usb/gspca/konica.c
++++ b/drivers/media/usb/gspca/konica.c
+@@ -277,7 +277,7 @@ static void sd_isoc_irq(struct urb *urb)
+ 		if (gspca_dev->frozen)
+ 			return;
+ #endif
+-		PDEBUG(D_ERR, "urb status: %d", urb->status);
++		PERR("urb status: %d", urb->status);
+ 		st = usb_submit_urb(urb, GFP_ATOMIC);
+ 		if (st < 0)
+ 			pr_err("resubmit urb error %d\n", st);
+@@ -295,33 +295,30 @@ static void sd_isoc_irq(struct urb *urb)
+ 	sd->last_data_urb = NULL;
+ 
+ 	if (!data_urb || data_urb->start_frame != status_urb->start_frame) {
+-		PDEBUG(D_ERR|D_PACK, "lost sync on frames");
++		PERR("lost sync on frames");
+ 		goto resubmit;
+ 	}
+ 
+ 	if (data_urb->number_of_packets != status_urb->number_of_packets) {
+-		PDEBUG(D_ERR|D_PACK,
+-		       "no packets does not match, data: %d, status: %d",
+-		       data_urb->number_of_packets,
+-		       status_urb->number_of_packets);
++		PERR("no packets does not match, data: %d, status: %d",
++		     data_urb->number_of_packets,
++		     status_urb->number_of_packets);
+ 		goto resubmit;
+ 	}
+ 
+ 	for (i = 0; i < status_urb->number_of_packets; i++) {
+ 		if (data_urb->iso_frame_desc[i].status ||
+ 		    status_urb->iso_frame_desc[i].status) {
+-			PDEBUG(D_ERR|D_PACK,
+-			       "pkt %d data-status %d, status-status %d", i,
+-			       data_urb->iso_frame_desc[i].status,
+-			       status_urb->iso_frame_desc[i].status);
++			PERR("pkt %d data-status %d, status-status %d", i,
++			     data_urb->iso_frame_desc[i].status,
++			     status_urb->iso_frame_desc[i].status);
+ 			gspca_dev->last_packet_type = DISCARD_PACKET;
+ 			continue;
+ 		}
+ 
+ 		if (status_urb->iso_frame_desc[i].actual_length != 1) {
+-			PDEBUG(D_ERR|D_PACK,
+-			       "bad status packet length %d",
+-			       status_urb->iso_frame_desc[i].actual_length);
++			PERR("bad status packet length %d",
++			     status_urb->iso_frame_desc[i].actual_length);
+ 			gspca_dev->last_packet_type = DISCARD_PACKET;
+ 			continue;
+ 		}
+@@ -366,12 +363,11 @@ static void sd_isoc_irq(struct urb *urb)
+ 	if (data_urb) {
+ 		st = usb_submit_urb(data_urb, GFP_ATOMIC);
+ 		if (st < 0)
+-			PDEBUG(D_ERR|D_PACK,
+-			       "usb_submit_urb(data_urb) ret %d", st);
++			PERR("usb_submit_urb(data_urb) ret %d", st);
+ 	}
+ 	st = usb_submit_urb(status_urb, GFP_ATOMIC);
+ 	if (st < 0)
+-		pr_err("usb_submit_urb(status_urb) ret %d\n", st);
++		PERR("usb_submit_urb(status_urb) ret %d\n", st);
+ }
+ 
+ static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
+diff --git a/drivers/media/usb/gspca/m5602/m5602_core.c b/drivers/media/usb/gspca/m5602/m5602_core.c
+index 907a968f474d..d926e62cb80b 100644
+--- a/drivers/media/usb/gspca/m5602/m5602_core.c
++++ b/drivers/media/usb/gspca/m5602/m5602_core.c
+@@ -41,6 +41,7 @@ MODULE_DEVICE_TABLE(usb, m5602_table);
+ int m5602_read_bridge(struct sd *sd, const u8 address, u8 *i2c_data)
+ {
+ 	int err;
++	struct gspca_dev *gspca_dev = (struct gspca_dev *) sd;
+ 	struct usb_device *udev = sd->gspca_dev.dev;
+ 	__u8 *buf = sd->gspca_dev.usb_buf;
+ 
+@@ -62,6 +63,7 @@ int m5602_read_bridge(struct sd *sd, const u8 address, u8 *i2c_data)
+ int m5602_write_bridge(struct sd *sd, const u8 address, const u8 i2c_data)
+ {
+ 	int err;
++	struct gspca_dev *gspca_dev = (struct gspca_dev *) sd;
+ 	struct usb_device *udev = sd->gspca_dev.dev;
+ 	__u8 *buf = sd->gspca_dev.usb_buf;
+ 
+@@ -98,6 +100,7 @@ int m5602_read_sensor(struct sd *sd, const u8 address,
+ 		       u8 *i2c_data, const u8 len)
+ {
+ 	int err, i;
++	struct gspca_dev *gspca_dev = (struct gspca_dev *) sd;
+ 
+ 	if (!len || len > sd->sensor->i2c_regW)
+ 		return -EINVAL;
+@@ -147,6 +150,7 @@ int m5602_write_sensor(struct sd *sd, const u8 address,
+ {
+ 	int err, i;
+ 	u8 *p;
++	struct gspca_dev *gspca_dev = (struct gspca_dev *) sd;
+ 	struct usb_device *udev = sd->gspca_dev.dev;
+ 	__u8 *buf = sd->gspca_dev.usb_buf;
+ 
+@@ -378,7 +382,7 @@ static int m5602_configure(struct gspca_dev *gspca_dev,
+ 	return 0;
+ 
+ fail:
+-	PDEBUG(D_ERR, "ALi m5602 webcam failed");
++	PERR("ALi m5602 webcam failed");
+ 	cam->cam_mode = NULL;
+ 	cam->nmodes = 0;
+ 
+diff --git a/drivers/media/usb/gspca/m5602/m5602_mt9m111.c b/drivers/media/usb/gspca/m5602/m5602_mt9m111.c
+index b5f66921b3eb..cfa4663f8934 100644
+--- a/drivers/media/usb/gspca/m5602/m5602_mt9m111.c
++++ b/drivers/media/usb/gspca/m5602/m5602_mt9m111.c
+@@ -56,6 +56,7 @@ int mt9m111_probe(struct sd *sd)
+ {
+ 	u8 data[2] = {0x00, 0x00};
+ 	int i;
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 
+ 	if (force_sensor) {
+ 		if (force_sensor == MT9M111_SENSOR) {
+@@ -169,6 +170,7 @@ int mt9m111_start(struct sd *sd)
+ 	int i, err = 0;
+ 	u8 data[2];
+ 	struct cam *cam = &sd->gspca_dev.cam;
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 
+ 	int width = cam->cam_mode[sd->gspca_dev.curr_mode].width - 1;
+ 	int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
+@@ -229,11 +231,11 @@ int mt9m111_start(struct sd *sd)
+ 
+ 	switch (width) {
+ 	case 640:
+-		PDEBUG(D_V4L2, "Configuring camera for VGA mode");
++		PDEBUG(D_CONF, "Configuring camera for VGA mode");
+ 		break;
+ 
+ 	case 320:
+-		PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
++		PDEBUG(D_CONF, "Configuring camera for QVGA mode");
+ 		break;
+ 	}
+ 	return err;
+@@ -252,7 +254,7 @@ static int mt9m111_set_hvflip(struct gspca_dev *gspca_dev)
+ 	int hflip;
+ 	int vflip;
+ 
+-	PDEBUG(D_V4L2, "Set hvflip to %d %d", sd->hflip->val, sd->vflip->val);
++	PDEBUG(D_CONF, "Set hvflip to %d %d", sd->hflip->val, sd->vflip->val);
+ 
+ 	/* The mt9m111 is flipped by default */
+ 	hflip = !sd->hflip->val;
+@@ -293,7 +295,7 @@ static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev,
+ 
+ 	err = m5602_write_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2);
+ 
+-	PDEBUG(D_V4L2, "Set auto white balance %d", val);
++	PDEBUG(D_CONF, "Set auto white balance %d", val);
+ 	return err;
+ }
+ 
+@@ -326,7 +328,7 @@ static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+ 
+ 	data[1] = (tmp & 0xff);
+ 	data[0] = (tmp & 0xff00) >> 8;
+-	PDEBUG(D_V4L2, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
++	PDEBUG(D_CONF, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
+ 	       data[1], data[0]);
+ 
+ 	err = m5602_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN,
+@@ -344,7 +346,7 @@ static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
+ 	data[1] = (val & 0xff);
+ 	data[0] = (val & 0xff00) >> 8;
+ 
+-	PDEBUG(D_V4L2, "Set green balance %d", val);
++	PDEBUG(D_CONF, "Set green balance %d", val);
+ 	err = m5602_write_sensor(sd, MT9M111_SC_GREEN_1_GAIN,
+ 				 data, 2);
+ 	if (err < 0)
+@@ -362,7 +364,7 @@ static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
+ 	data[1] = (val & 0xff);
+ 	data[0] = (val & 0xff00) >> 8;
+ 
+-	PDEBUG(D_V4L2, "Set blue balance %d", val);
++	PDEBUG(D_CONF, "Set blue balance %d", val);
+ 
+ 	return m5602_write_sensor(sd, MT9M111_SC_BLUE_GAIN,
+ 				  data, 2);
+@@ -376,7 +378,7 @@ static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
+ 	data[1] = (val & 0xff);
+ 	data[0] = (val & 0xff00) >> 8;
+ 
+-	PDEBUG(D_V4L2, "Set red balance %d", val);
++	PDEBUG(D_CONF, "Set red balance %d", val);
+ 
+ 	return m5602_write_sensor(sd, MT9M111_SC_RED_GAIN,
+ 				  data, 2);
+diff --git a/drivers/media/usb/gspca/m5602/m5602_ov7660.c b/drivers/media/usb/gspca/m5602/m5602_ov7660.c
+index 3bbe3ad5d4a9..4ac78893cc5f 100644
+--- a/drivers/media/usb/gspca/m5602/m5602_ov7660.c
++++ b/drivers/media/usb/gspca/m5602/m5602_ov7660.c
+@@ -175,7 +175,7 @@ static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+ 	u8 i2c_data = val;
+ 	struct sd *sd = (struct sd *) gspca_dev;
+ 
+-	PDEBUG(D_V4L2, "Setting gain to %d", val);
++	PDEBUG(D_CONF, "Setting gain to %d", val);
+ 
+ 	err = m5602_write_sensor(sd, OV7660_GAIN, &i2c_data, 1);
+ 	return err;
+@@ -188,7 +188,7 @@ static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev,
+ 	u8 i2c_data;
+ 	struct sd *sd = (struct sd *) gspca_dev;
+ 
+-	PDEBUG(D_V4L2, "Set auto white balance to %d", val);
++	PDEBUG(D_CONF, "Set auto white balance to %d", val);
+ 
+ 	err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
+ 	if (err < 0)
+@@ -206,7 +206,7 @@ static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
+ 	u8 i2c_data;
+ 	struct sd *sd = (struct sd *) gspca_dev;
+ 
+-	PDEBUG(D_V4L2, "Set auto gain control to %d", val);
++	PDEBUG(D_CONF, "Set auto gain control to %d", val);
+ 
+ 	err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
+ 	if (err < 0)
+@@ -224,7 +224,7 @@ static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev,
+ 	u8 i2c_data;
+ 	struct sd *sd = (struct sd *) gspca_dev;
+ 
+-	PDEBUG(D_V4L2, "Set auto exposure control to %d", val);
++	PDEBUG(D_CONF, "Set auto exposure control to %d", val);
+ 
+ 	err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
+ 	if (err < 0)
+@@ -242,7 +242,7 @@ static int ov7660_set_hvflip(struct gspca_dev *gspca_dev)
+ 	u8 i2c_data;
+ 	struct sd *sd = (struct sd *) gspca_dev;
+ 
+-	PDEBUG(D_V4L2, "Set hvflip to %d, %d", sd->hflip->val, sd->vflip->val);
++	PDEBUG(D_CONF, "Set hvflip to %d, %d", sd->hflip->val, sd->vflip->val);
+ 
+ 	i2c_data = (sd->hflip->val << 5) | (sd->vflip->val << 4);
+ 
+diff --git a/drivers/media/usb/gspca/m5602/m5602_ov9650.c b/drivers/media/usb/gspca/m5602/m5602_ov9650.c
+index e2fe2f942fe6..59bc62bfae26 100644
+--- a/drivers/media/usb/gspca/m5602/m5602_ov9650.c
++++ b/drivers/media/usb/gspca/m5602/m5602_ov9650.c
+@@ -147,6 +147,7 @@ int ov9650_probe(struct sd *sd)
+ {
+ 	int err = 0;
+ 	u8 prod_id = 0, ver_id = 0, i;
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 
+ 	if (force_sensor) {
+ 		if (force_sensor == OV9650_SENSOR) {
+@@ -268,6 +269,7 @@ int ov9650_start(struct sd *sd)
+ 	int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
+ 	int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
+ 	int hor_offs = OV9650_LEFT_OFFSET;
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 
+ 	if ((!dmi_check_system(ov9650_flip_dmi_table) &&
+ 		sd->vflip->val) ||
+@@ -351,7 +353,7 @@ int ov9650_start(struct sd *sd)
+ 
+ 	switch (width) {
+ 	case 640:
+-		PDEBUG(D_V4L2, "Configuring camera for VGA mode");
++		PDEBUG(D_CONF, "Configuring camera for VGA mode");
+ 
+ 		data = OV9650_VGA_SELECT | OV9650_RGB_SELECT |
+ 		       OV9650_RAW_RGB_SELECT;
+@@ -359,7 +361,7 @@ int ov9650_start(struct sd *sd)
+ 		break;
+ 
+ 	case 352:
+-		PDEBUG(D_V4L2, "Configuring camera for CIF mode");
++		PDEBUG(D_CONF, "Configuring camera for CIF mode");
+ 
+ 		data = OV9650_CIF_SELECT | OV9650_RGB_SELECT |
+ 				OV9650_RAW_RGB_SELECT;
+@@ -367,7 +369,7 @@ int ov9650_start(struct sd *sd)
+ 		break;
+ 
+ 	case 320:
+-		PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
++		PDEBUG(D_CONF, "Configuring camera for QVGA mode");
+ 
+ 		data = OV9650_QVGA_SELECT | OV9650_RGB_SELECT |
+ 				OV9650_RAW_RGB_SELECT;
+@@ -375,7 +377,7 @@ int ov9650_start(struct sd *sd)
+ 		break;
+ 
+ 	case 176:
+-		PDEBUG(D_V4L2, "Configuring camera for QCIF mode");
++		PDEBUG(D_CONF, "Configuring camera for QCIF mode");
+ 
+ 		data = OV9650_QCIF_SELECT | OV9650_RGB_SELECT |
+ 			OV9650_RAW_RGB_SELECT;
+@@ -404,7 +406,7 @@ static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+ 	u8 i2c_data;
+ 	int err;
+ 
+-	PDEBUG(D_V4L2, "Set exposure to %d", val);
++	PDEBUG(D_CONF, "Set exposure to %d", val);
+ 
+ 	/* The 6 MSBs */
+ 	i2c_data = (val >> 10) & 0x3f;
+@@ -432,7 +434,7 @@ static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+ 	u8 i2c_data;
+ 	struct sd *sd = (struct sd *) gspca_dev;
+ 
+-	PDEBUG(D_V4L2, "Setting gain to %d", val);
++	PDEBUG(D_CONF, "Setting gain to %d", val);
+ 
+ 	/* The 2 MSB */
+ 	/* Read the OV9650_VREF register first to avoid
+@@ -460,7 +462,7 @@ static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
+ 	u8 i2c_data;
+ 	struct sd *sd = (struct sd *) gspca_dev;
+ 
+-	PDEBUG(D_V4L2, "Set red gain to %d", val);
++	PDEBUG(D_CONF, "Set red gain to %d", val);
+ 
+ 	i2c_data = val & 0xff;
+ 	err = m5602_write_sensor(sd, OV9650_RED, &i2c_data, 1);
+@@ -473,7 +475,7 @@ static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
+ 	u8 i2c_data;
+ 	struct sd *sd = (struct sd *) gspca_dev;
+ 
+-	PDEBUG(D_V4L2, "Set blue gain to %d", val);
++	PDEBUG(D_CONF, "Set blue gain to %d", val);
+ 
+ 	i2c_data = val & 0xff;
+ 	err = m5602_write_sensor(sd, OV9650_BLUE, &i2c_data, 1);
+@@ -488,7 +490,7 @@ static int ov9650_set_hvflip(struct gspca_dev *gspca_dev)
+ 	int hflip = sd->hflip->val;
+ 	int vflip = sd->vflip->val;
+ 
+-	PDEBUG(D_V4L2, "Set hvflip to %d %d", hflip, vflip);
++	PDEBUG(D_CONF, "Set hvflip to %d %d", hflip, vflip);
+ 
+ 	if (dmi_check_system(ov9650_flip_dmi_table))
+ 		vflip = !vflip;
+@@ -512,7 +514,7 @@ static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev,
+ 	u8 i2c_data;
+ 	struct sd *sd = (struct sd *) gspca_dev;
+ 
+-	PDEBUG(D_V4L2, "Set auto exposure control to %d", val);
++	PDEBUG(D_CONF, "Set auto exposure control to %d", val);
+ 
+ 	err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
+ 	if (err < 0)
+@@ -531,7 +533,7 @@ static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev,
+ 	u8 i2c_data;
+ 	struct sd *sd = (struct sd *) gspca_dev;
+ 
+-	PDEBUG(D_V4L2, "Set auto white balance to %d", val);
++	PDEBUG(D_CONF, "Set auto white balance to %d", val);
+ 
+ 	err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
+ 	if (err < 0)
+@@ -549,7 +551,7 @@ static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
+ 	u8 i2c_data;
+ 	struct sd *sd = (struct sd *) gspca_dev;
+ 
+-	PDEBUG(D_V4L2, "Set auto gain control to %d", val);
++	PDEBUG(D_CONF, "Set auto gain control to %d", val);
+ 
+ 	err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
+ 	if (err < 0)
+diff --git a/drivers/media/usb/gspca/m5602/m5602_po1030.c b/drivers/media/usb/gspca/m5602/m5602_po1030.c
+index 189086291303..4bf5c43424b7 100644
+--- a/drivers/media/usb/gspca/m5602/m5602_po1030.c
++++ b/drivers/media/usb/gspca/m5602/m5602_po1030.c
+@@ -55,6 +55,7 @@ static const struct v4l2_ctrl_config po1030_greenbal_cfg = {
+ int po1030_probe(struct sd *sd)
+ {
+ 	u8 dev_id_h = 0, i;
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 
+ 	if (force_sensor) {
+ 		if (force_sensor == PO1030_SENSOR) {
+@@ -305,10 +306,10 @@ static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+ 	u8 i2c_data;
+ 	int err;
+ 
+-	PDEBUG(D_V4L2, "Set exposure to %d", val & 0xffff);
++	PDEBUG(D_CONF, "Set exposure to %d", val & 0xffff);
+ 
+ 	i2c_data = ((val & 0xff00) >> 8);
+-	PDEBUG(D_V4L2, "Set exposure to high byte to 0x%x",
++	PDEBUG(D_CONF, "Set exposure to high byte to 0x%x",
+ 	       i2c_data);
+ 
+ 	err = m5602_write_sensor(sd, PO1030_INTEGLINES_H,
+@@ -317,7 +318,7 @@ static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+ 		return err;
+ 
+ 	i2c_data = (val & 0xff);
+-	PDEBUG(D_V4L2, "Set exposure to low byte to 0x%x",
++	PDEBUG(D_CONF, "Set exposure to low byte to 0x%x",
+ 	       i2c_data);
+ 	err = m5602_write_sensor(sd, PO1030_INTEGLINES_M,
+ 				  &i2c_data, 1);
+@@ -332,7 +333,7 @@ static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+ 	int err;
+ 
+ 	i2c_data = val & 0xff;
+-	PDEBUG(D_V4L2, "Set global gain to %d", i2c_data);
++	PDEBUG(D_CONF, "Set global gain to %d", i2c_data);
+ 	err = m5602_write_sensor(sd, PO1030_GLOBALGAIN,
+ 				 &i2c_data, 1);
+ 	return err;
+@@ -344,7 +345,7 @@ static int po1030_set_hvflip(struct gspca_dev *gspca_dev)
+ 	u8 i2c_data;
+ 	int err;
+ 
+-	PDEBUG(D_V4L2, "Set hvflip %d %d", sd->hflip->val, sd->vflip->val);
++	PDEBUG(D_CONF, "Set hvflip %d %d", sd->hflip->val, sd->vflip->val);
+ 	err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
+ 	if (err < 0)
+ 		return err;
+@@ -365,7 +366,7 @@ static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
+ 	int err;
+ 
+ 	i2c_data = val & 0xff;
+-	PDEBUG(D_V4L2, "Set red gain to %d", i2c_data);
++	PDEBUG(D_CONF, "Set red gain to %d", i2c_data);
+ 	err = m5602_write_sensor(sd, PO1030_RED_GAIN,
+ 				  &i2c_data, 1);
+ 	return err;
+@@ -378,7 +379,7 @@ static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
+ 	int err;
+ 
+ 	i2c_data = val & 0xff;
+-	PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data);
++	PDEBUG(D_CONF, "Set blue gain to %d", i2c_data);
+ 	err = m5602_write_sensor(sd, PO1030_BLUE_GAIN,
+ 				  &i2c_data, 1);
+ 
+@@ -392,7 +393,7 @@ static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
+ 	int err;
+ 
+ 	i2c_data = val & 0xff;
+-	PDEBUG(D_V4L2, "Set green gain to %d", i2c_data);
++	PDEBUG(D_CONF, "Set green gain to %d", i2c_data);
+ 
+ 	err = m5602_write_sensor(sd, PO1030_GREEN_1_GAIN,
+ 			   &i2c_data, 1);
+@@ -414,7 +415,7 @@ static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev,
+ 	if (err < 0)
+ 		return err;
+ 
+-	PDEBUG(D_V4L2, "Set auto white balance to %d", val);
++	PDEBUG(D_CONF, "Set auto white balance to %d", val);
+ 	i2c_data = (i2c_data & 0xfe) | (val & 0x01);
+ 	err = m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
+ 	return err;
+@@ -431,7 +432,7 @@ static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev,
+ 	if (err < 0)
+ 		return err;
+ 
+-	PDEBUG(D_V4L2, "Set auto exposure to %d", val);
++	PDEBUG(D_CONF, "Set auto exposure to %d", val);
+ 	val = (val == V4L2_EXPOSURE_AUTO);
+ 	i2c_data = (i2c_data & 0xfd) | ((val & 0x01) << 1);
+ 	return m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
+diff --git a/drivers/media/usb/gspca/m5602/m5602_s5k4aa.c b/drivers/media/usb/gspca/m5602/m5602_s5k4aa.c
+index 42ffaf04771c..7d12599458e2 100644
+--- a/drivers/media/usb/gspca/m5602/m5602_s5k4aa.c
++++ b/drivers/media/usb/gspca/m5602/m5602_s5k4aa.c
+@@ -145,6 +145,7 @@ int s5k4aa_probe(struct sd *sd)
+ {
+ 	u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ 	const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75};
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	int i, err = 0;
+ 
+ 	if (force_sensor) {
+@@ -215,10 +216,11 @@ int s5k4aa_start(struct sd *sd)
+ 	int i, err = 0;
+ 	u8 data[2];
+ 	struct cam *cam = &sd->gspca_dev.cam;
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 
+ 	switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) {
+ 	case 1280:
+-		PDEBUG(D_V4L2, "Configuring camera for SXGA mode");
++		PDEBUG(D_CONF, "Configuring camera for SXGA mode");
+ 
+ 		for (i = 0; i < ARRAY_SIZE(SXGA_s5k4aa); i++) {
+ 			switch (SXGA_s5k4aa[i][0]) {
+@@ -251,7 +253,7 @@ int s5k4aa_start(struct sd *sd)
+ 		break;
+ 
+ 	case 640:
+-		PDEBUG(D_V4L2, "Configuring camera for VGA mode");
++		PDEBUG(D_CONF, "Configuring camera for VGA mode");
+ 
+ 		for (i = 0; i < ARRAY_SIZE(VGA_s5k4aa); i++) {
+ 			switch (VGA_s5k4aa[i][0]) {
+@@ -367,7 +369,7 @@ static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+ 	u8 data = S5K4AA_PAGE_MAP_2;
+ 	int err;
+ 
+-	PDEBUG(D_V4L2, "Set exposure to %d", val);
++	PDEBUG(D_CONF, "Set exposure to %d", val);
+ 	err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ 	if (err < 0)
+ 		return err;
+@@ -389,7 +391,7 @@ static int s5k4aa_set_hvflip(struct gspca_dev *gspca_dev)
+ 	int hflip = sd->hflip->val;
+ 	int vflip = sd->vflip->val;
+ 
+-	PDEBUG(D_V4L2, "Set hvflip %d %d", hflip, vflip);
++	PDEBUG(D_CONF, "Set hvflip %d %d", hflip, vflip);
+ 	err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ 	if (err < 0)
+ 		return err;
+@@ -439,7 +441,7 @@ static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+ 	u8 data = S5K4AA_PAGE_MAP_2;
+ 	int err;
+ 
+-	PDEBUG(D_V4L2, "Set gain to %d", val);
++	PDEBUG(D_CONF, "Set gain to %d", val);
+ 	err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ 	if (err < 0)
+ 		return err;
+@@ -456,7 +458,7 @@ static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
+ 	u8 data = S5K4AA_PAGE_MAP_2;
+ 	int err;
+ 
+-	PDEBUG(D_V4L2, "Set brightness to %d", val);
++	PDEBUG(D_CONF, "Set brightness to %d", val);
+ 	err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ 	if (err < 0)
+ 		return err;
+@@ -471,7 +473,7 @@ static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val)
+ 	u8 data = S5K4AA_PAGE_MAP_2;
+ 	int err;
+ 
+-	PDEBUG(D_V4L2, "Set noise to %d", val);
++	PDEBUG(D_CONF, "Set noise to %d", val);
+ 	err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ 	if (err < 0)
+ 		return err;
+diff --git a/drivers/media/usb/gspca/m5602/m5602_s5k83a.c b/drivers/media/usb/gspca/m5602/m5602_s5k83a.c
+index 69ee6e26b8ea..7cbc3a00bda8 100644
+--- a/drivers/media/usb/gspca/m5602/m5602_s5k83a.c
++++ b/drivers/media/usb/gspca/m5602/m5602_s5k83a.c
+@@ -51,6 +51,7 @@ int s5k83a_probe(struct sd *sd)
+ {
+ 	u8 prod_id = 0, ver_id = 0;
+ 	int i, err = 0;
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 
+ 	if (force_sensor) {
+ 		if (force_sensor == S5K83A_SENSOR) {
+diff --git a/drivers/media/usb/gspca/mr97310a.c b/drivers/media/usb/gspca/mr97310a.c
+index 8f4714df5990..68bb2f359666 100644
+--- a/drivers/media/usb/gspca/mr97310a.c
++++ b/drivers/media/usb/gspca/mr97310a.c
+@@ -289,7 +289,7 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev)
+ 			return err_code;
+ 	}
+ 	if (status != 0x0a)
+-		PDEBUG(D_ERR, "status is %02x", status);
++		PERR("status is %02x", status);
+ 
+ 	tries = 0;
+ 	while (tries < 4) {
+@@ -330,7 +330,7 @@ static void stream_stop(struct gspca_dev *gspca_dev)
+ 	gspca_dev->usb_buf[0] = 0x01;
+ 	gspca_dev->usb_buf[1] = 0x00;
+ 	if (mr_write(gspca_dev, 2) < 0)
+-		PDEBUG(D_ERR, "Stream Stop failed");
++		PERR("Stream Stop failed");
+ }
+ 
+ static void lcd_stop(struct gspca_dev *gspca_dev)
+@@ -338,7 +338,7 @@ static void lcd_stop(struct gspca_dev *gspca_dev)
+ 	gspca_dev->usb_buf[0] = 0x19;
+ 	gspca_dev->usb_buf[1] = 0x54;
+ 	if (mr_write(gspca_dev, 2) < 0)
+-		PDEBUG(D_ERR, "LCD Stop failed");
++		PERR("LCD Stop failed");
+ }
+ 
+ static int isoc_enable(struct gspca_dev *gspca_dev)
+@@ -1026,7 +1026,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+ 	struct sd *sd = (struct sd *) gspca_dev;
+ 	unsigned char *sof;
+ 
+-	sof = pac_find_sof(&sd->sof_read, data, len);
++	sof = pac_find_sof(gspca_dev, &sd->sof_read, data, len);
+ 	if (sof) {
+ 		int n;
+ 
+diff --git a/drivers/media/usb/gspca/ov519.c b/drivers/media/usb/gspca/ov519.c
+index 9ad19a7ef81b..a3958ee86816 100644
+--- a/drivers/media/usb/gspca/ov519.c
++++ b/drivers/media/usb/gspca/ov519.c
+@@ -2034,6 +2034,7 @@ static unsigned char ov7670_abs_to_sm(unsigned char v)
+ /* Write a OV519 register */
+ static void reg_w(struct sd *sd, u16 index, u16 value)
+ {
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	int ret, req = 0;
+ 
+ 	if (sd->gspca_dev.usb_err < 0)
+@@ -2071,7 +2072,7 @@ static void reg_w(struct sd *sd, u16 index, u16 value)
+ 			sd->gspca_dev.usb_buf, 1, 500);
+ leave:
+ 	if (ret < 0) {
+-		pr_err("reg_w %02x failed %d\n", index, ret);
++		PERR("reg_w %02x failed %d\n", index, ret);
+ 		sd->gspca_dev.usb_err = ret;
+ 		return;
+ 	}
+@@ -2081,6 +2082,7 @@ static void reg_w(struct sd *sd, u16 index, u16 value)
+ /* returns: negative is error, pos or zero is data */
+ static int reg_r(struct sd *sd, u16 index)
+ {
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	int ret;
+ 	int req;
+ 
+@@ -2110,7 +2112,7 @@ static int reg_r(struct sd *sd, u16 index)
+ 		PDEBUG(D_USBI, "GET %02x 0000 %04x %02x",
+ 			req, index, ret);
+ 	} else {
+-		pr_err("reg_r %02x failed %d\n", index, ret);
++		PERR("reg_r %02x failed %d\n", index, ret);
+ 		sd->gspca_dev.usb_err = ret;
+ 	}
+ 
+@@ -2121,6 +2123,7 @@ static int reg_r(struct sd *sd, u16 index)
+ static int reg_r8(struct sd *sd,
+ 		  u16 index)
+ {
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	int ret;
+ 
+ 	if (sd->gspca_dev.usb_err < 0)
+@@ -2135,7 +2138,7 @@ static int reg_r8(struct sd *sd,
+ 	if (ret >= 0) {
+ 		ret = sd->gspca_dev.usb_buf[0];
+ 	} else {
+-		pr_err("reg_r8 %02x failed %d\n", index, ret);
++		PERR("reg_r8 %02x failed %d\n", index, ret);
+ 		sd->gspca_dev.usb_err = ret;
+ 	}
+ 
+@@ -2174,6 +2177,7 @@ static void reg_w_mask(struct sd *sd,
+  */
+ static void ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n)
+ {
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	int ret;
+ 
+ 	if (sd->gspca_dev.usb_err < 0)
+@@ -2188,13 +2192,14 @@ static void ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n)
+ 			0, index,
+ 			sd->gspca_dev.usb_buf, n, 500);
+ 	if (ret < 0) {
+-		pr_err("reg_w32 %02x failed %d\n", index, ret);
++		PERR("reg_w32 %02x failed %d\n", index, ret);
+ 		sd->gspca_dev.usb_err = ret;
+ 	}
+ }
+ 
+ static void ov511_i2c_w(struct sd *sd, u8 reg, u8 value)
+ {
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	int rc, retries;
+ 
+ 	PDEBUG(D_USBO, "ov511_i2c_w %02x %02x", reg, value);
+@@ -2228,6 +2233,7 @@ static void ov511_i2c_w(struct sd *sd, u8 reg, u8 value)
+ 
+ static int ov511_i2c_r(struct sd *sd, u8 reg)
+ {
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	int rc, value, retries;
+ 
+ 	/* Two byte write cycle */
+@@ -2300,6 +2306,8 @@ static void ov518_i2c_w(struct sd *sd,
+ 		u8 reg,
+ 		u8 value)
+ {
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
++
+ 	PDEBUG(D_USBO, "ov518_i2c_w %02x %02x", reg, value);
+ 
+ 	/* Select camera register */
+@@ -2325,6 +2333,7 @@ static void ov518_i2c_w(struct sd *sd,
+  */
+ static int ov518_i2c_r(struct sd *sd, u8 reg)
+ {
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	int value;
+ 
+ 	/* Select camera register */
+@@ -2345,6 +2354,7 @@ static int ov518_i2c_r(struct sd *sd, u8 reg)
+ 
+ static void ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value)
+ {
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	int ret;
+ 
+ 	if (sd->gspca_dev.usb_err < 0)
+@@ -2357,7 +2367,7 @@ static void ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value)
+ 			(u16) value, (u16) reg, NULL, 0, 500);
+ 
+ 	if (ret < 0) {
+-		pr_err("ovfx2_i2c_w %02x failed %d\n", reg, ret);
++		PERR("ovfx2_i2c_w %02x failed %d\n", reg, ret);
+ 		sd->gspca_dev.usb_err = ret;
+ 	}
+ 
+@@ -2366,6 +2376,7 @@ static void ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value)
+ 
+ static int ovfx2_i2c_r(struct sd *sd, u8 reg)
+ {
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	int ret;
+ 
+ 	if (sd->gspca_dev.usb_err < 0)
+@@ -2381,7 +2392,7 @@ static int ovfx2_i2c_r(struct sd *sd, u8 reg)
+ 		ret = sd->gspca_dev.usb_buf[0];
+ 		PDEBUG(D_USBI, "ovfx2_i2c_r %02x %02x", reg, ret);
+ 	} else {
+-		pr_err("ovfx2_i2c_r %02x failed %d\n", reg, ret);
++		PERR("ovfx2_i2c_r %02x failed %d\n", reg, ret);
+ 		sd->gspca_dev.usb_err = ret;
+ 	}
+ 
+@@ -2478,6 +2489,8 @@ static void i2c_w_mask(struct sd *sd,
+  * registers while the camera is streaming */
+ static inline void ov51x_stop(struct sd *sd)
+ {
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
++
+ 	PDEBUG(D_STREAM, "stopping");
+ 	sd->stopped = 1;
+ 	switch (sd->bridge) {
+@@ -2507,6 +2520,8 @@ static inline void ov51x_stop(struct sd *sd)
+  * actually stopped (for performance). */
+ static inline void ov51x_restart(struct sd *sd)
+ {
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
++
+ 	PDEBUG(D_STREAM, "restarting");
+ 	if (!sd->stopped)
+ 		return;
+@@ -2545,6 +2560,7 @@ static void ov51x_set_slave_ids(struct sd *sd, u8 slave);
+ static int init_ov_sensor(struct sd *sd, u8 slave)
+ {
+ 	int i;
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 
+ 	ov51x_set_slave_ids(sd, slave);
+ 
+@@ -2624,10 +2640,11 @@ static void write_i2c_regvals(struct sd *sd,
+ /* This initializes the OV2x10 / OV3610 / OV3620 / OV9600 */
+ static void ov_hires_configure(struct sd *sd)
+ {
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	int high, low;
+ 
+ 	if (sd->bridge != BRIDGE_OVFX2) {
+-		pr_err("error hires sensors only supported with ovfx2\n");
++		PERR("error hires sensors only supported with ovfx2\n");
+ 		return;
+ 	}
+ 
+@@ -2662,7 +2679,7 @@ static void ov_hires_configure(struct sd *sd)
+ 		}
+ 		break;
+ 	}
+-	pr_err("Error unknown sensor type: %02x%02x\n", high, low);
++	PERR("Error unknown sensor type: %02x%02x\n", high, low);
+ }
+ 
+ /* This initializes the OV8110, OV8610 sensor. The OV8110 uses
+@@ -2670,6 +2687,7 @@ static void ov_hires_configure(struct sd *sd)
+  */
+ static void ov8xx0_configure(struct sd *sd)
+ {
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	int rc;
+ 
+ 	PDEBUG(D_PROBE, "starting ov8xx0 configuration");
+@@ -2677,13 +2695,13 @@ static void ov8xx0_configure(struct sd *sd)
+ 	/* Detect sensor (sub)type */
+ 	rc = i2c_r(sd, OV7610_REG_COM_I);
+ 	if (rc < 0) {
+-		PDEBUG(D_ERR, "Error detecting sensor type");
++		PERR("Error detecting sensor type");
+ 		return;
+ 	}
+ 	if ((rc & 3) == 1)
+ 		sd->sensor = SEN_OV8610;
+ 	else
+-		pr_err("Unknown image sensor version: %d\n", rc & 3);
++		PERR("Unknown image sensor version: %d\n", rc & 3);
+ }
+ 
+ /* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses
+@@ -2691,6 +2709,7 @@ static void ov8xx0_configure(struct sd *sd)
+  */
+ static void ov7xx0_configure(struct sd *sd)
+ {
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	int rc, high, low;
+ 
+ 	PDEBUG(D_PROBE, "starting OV7xx0 configuration");
+@@ -2701,7 +2720,7 @@ static void ov7xx0_configure(struct sd *sd)
+ 	/* add OV7670 here
+ 	 * it appears to be wrongly detected as a 7610 by default */
+ 	if (rc < 0) {
+-		pr_err("Error detecting sensor type\n");
++		PERR("Error detecting sensor type\n");
+ 		return;
+ 	}
+ 	if ((rc & 3) == 3) {
+@@ -2729,19 +2748,19 @@ static void ov7xx0_configure(struct sd *sd)
+ 		/* try to read product id registers */
+ 		high = i2c_r(sd, 0x0a);
+ 		if (high < 0) {
+-			pr_err("Error detecting camera chip PID\n");
++			PERR("Error detecting camera chip PID\n");
+ 			return;
+ 		}
+ 		low = i2c_r(sd, 0x0b);
+ 		if (low < 0) {
+-			pr_err("Error detecting camera chip VER\n");
++			PERR("Error detecting camera chip VER\n");
+ 			return;
+ 		}
+ 		if (high == 0x76) {
+ 			switch (low) {
+ 			case 0x30:
+-				pr_err("Sensor is an OV7630/OV7635\n");
+-				pr_err("7630 is not supported by this driver\n");
++				PERR("Sensor is an OV7630/OV7635\n");
++				PERR("7630 is not supported by this driver\n");
+ 				return;
+ 			case 0x40:
+ 				PDEBUG(D_PROBE, "Sensor is an OV7645");
+@@ -2760,7 +2779,7 @@ static void ov7xx0_configure(struct sd *sd)
+ 				sd->sensor = SEN_OV7660;
+ 				break;
+ 			default:
+-				pr_err("Unknown sensor: 0x76%02x\n", low);
++				PERR("Unknown sensor: 0x76%02x\n", low);
+ 				return;
+ 			}
+ 		} else {
+@@ -2768,20 +2787,22 @@ static void ov7xx0_configure(struct sd *sd)
+ 			sd->sensor = SEN_OV7620;
+ 		}
+ 	} else {
+-		pr_err("Unknown image sensor version: %d\n", rc & 3);
++		PERR("Unknown image sensor version: %d\n", rc & 3);
+ 	}
+ }
+ 
+ /* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */
+ static void ov6xx0_configure(struct sd *sd)
+ {
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	int rc;
++
+ 	PDEBUG(D_PROBE, "starting OV6xx0 configuration");
+ 
+ 	/* Detect sensor (sub)type */
+ 	rc = i2c_r(sd, OV7610_REG_COM_I);
+ 	if (rc < 0) {
+-		pr_err("Error detecting sensor type\n");
++		PERR("Error detecting sensor type\n");
+ 		return;
+ 	}
+ 
+@@ -2810,7 +2831,7 @@ static void ov6xx0_configure(struct sd *sd)
+ 		pr_warn("WARNING: Sensor is an OV66307. Your camera may have been misdetected in previous driver versions.\n");
+ 		break;
+ 	default:
+-		pr_err("FATAL: Unknown sensor version: 0x%02x\n", rc);
++		PERR("FATAL: Unknown sensor version: 0x%02x\n", rc);
+ 		return;
+ 	}
+ 
+@@ -2907,6 +2928,7 @@ static void ov51x_upload_quan_tables(struct sd *sd)
+ 		7, 7, 7, 7, 7, 7, 8, 8
+ 	};
+ 
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	const unsigned char *pYTable, *pUVTable;
+ 	unsigned char val0, val1;
+ 	int i, size, reg = R51x_COMP_LUT_BEGIN;
+@@ -3300,7 +3322,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
+ 	} else if (init_ov_sensor(sd, OV_HIRES_SID) >= 0) {
+ 		ov_hires_configure(sd);
+ 	} else {
+-		pr_err("Can't determine sensor slave IDs\n");
++		PERR("Can't determine sensor slave IDs\n");
+ 		goto error;
+ 	}
+ 
+@@ -3433,7 +3455,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
+ 	}
+ 	return gspca_dev->usb_err;
+ error:
+-	PDEBUG(D_ERR, "OV519 Config failed");
++	PERR("OV519 Config failed");
+ 	return -EINVAL;
+ }
+ 
+@@ -3459,6 +3481,7 @@ static int sd_isoc_init(struct gspca_dev *gspca_dev)
+  */
+ static void ov511_mode_init_regs(struct sd *sd)
+ {
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	int hsegs, vsegs, packet_size, fps, needed;
+ 	int interlaced = 0;
+ 	struct usb_host_interface *alt;
+@@ -3467,7 +3490,7 @@ static void ov511_mode_init_regs(struct sd *sd)
+ 	intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
+ 	alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
+ 	if (!alt) {
+-		pr_err("Couldn't get altsetting\n");
++		PERR("Couldn't get altsetting\n");
+ 		sd->gspca_dev.usb_err = -EIO;
+ 		return;
+ 	}
+@@ -3583,6 +3606,7 @@ static void ov511_mode_init_regs(struct sd *sd)
+  */
+ static void ov518_mode_init_regs(struct sd *sd)
+ {
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	int hsegs, vsegs, packet_size;
+ 	struct usb_host_interface *alt;
+ 	struct usb_interface *intf;
+@@ -3590,7 +3614,7 @@ static void ov518_mode_init_regs(struct sd *sd)
+ 	intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
+ 	alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
+ 	if (!alt) {
+-		pr_err("Couldn't get altsetting\n");
++		PERR("Couldn't get altsetting\n");
+ 		sd->gspca_dev.usb_err = -EIO;
+ 		return;
+ 	}
+@@ -3750,6 +3774,8 @@ static void ov519_mode_init_regs(struct sd *sd)
+ 		/* windows reads 0x55 at this point, why? */
+ 	};
+ 
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
++
+ 	/******** Set the mode ********/
+ 	switch (sd->sensor) {
+ 	default:
+@@ -3865,11 +3891,10 @@ static void ov519_mode_init_regs(struct sd *sd)
+ 
+ static void mode_init_ov_sensor_regs(struct sd *sd)
+ {
+-	struct gspca_dev *gspca_dev;
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	int qvga, xstart, xend, ystart, yend;
+ 	u8 v;
+ 
+-	gspca_dev = &sd->gspca_dev;
+ 	qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1;
+ 
+ 	/******** Mode (VGA/QVGA) and sensor specific regs ********/
+@@ -4304,7 +4329,7 @@ static void ov511_pkt_scan(struct gspca_dev *gspca_dev,
+ 			/* Frame end */
+ 			if ((in[9] + 1) * 8 != gspca_dev->width ||
+ 			    (in[10] + 1) * 8 != gspca_dev->height) {
+-				PDEBUG(D_ERR, "Invalid frame size, got: %dx%d,"
++				PERR("Invalid frame size, got: %dx%d,"
+ 					" requested: %dx%d\n",
+ 					(in[9] + 1) * 8, (in[10] + 1) * 8,
+ 					gspca_dev->width, gspca_dev->height);
+@@ -4355,7 +4380,7 @@ static void ov518_pkt_scan(struct gspca_dev *gspca_dev,
+ 		   except that they may contain part of the footer), are
+ 		   numbered 0 */
+ 		else if (sd->packet_nr == 0 || data[len]) {
+-			PDEBUG(D_ERR, "Invalid packet nr: %d (expect: %d)",
++			PERR("Invalid packet nr: %d (expect: %d)",
+ 				(int)data[len], (int)sd->packet_nr);
+ 			gspca_dev->last_packet_type = DISCARD_PACKET;
+ 			return;
+@@ -4898,7 +4923,7 @@ static int sd_init_controls(struct gspca_dev *gspca_dev)
+ 			QUALITY_MIN, QUALITY_MAX, 1, QUALITY_DEF);
+ 
+ 	if (hdl->error) {
+-		pr_err("Could not initialize controls\n");
++		PERR("Could not initialize controls\n");
+ 		return hdl->error;
+ 	}
+ 	if (gspca_dev->autogain)
+diff --git a/drivers/media/usb/gspca/ov534.c b/drivers/media/usb/gspca/ov534.c
+index bb09d7884b89..2e28c81a03ab 100644
+--- a/drivers/media/usb/gspca/ov534.c
++++ b/drivers/media/usb/gspca/ov534.c
+@@ -690,7 +690,7 @@ static int sccb_check_status(struct gspca_dev *gspca_dev)
+ 		case 0x03:
+ 			break;
+ 		default:
+-			PDEBUG(D_ERR, "sccb status 0x%02x, attempt %d/5",
++			PERR("sccb status 0x%02x, attempt %d/5",
+ 			       data, i + 1);
+ 		}
+ 	}
+diff --git a/drivers/media/usb/gspca/pac207.c b/drivers/media/usb/gspca/pac207.c
+index 3b75097dd34e..83519be94e58 100644
+--- a/drivers/media/usb/gspca/pac207.c
++++ b/drivers/media/usb/gspca/pac207.c
+@@ -373,7 +373,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+ 	struct sd *sd = (struct sd *) gspca_dev;
+ 	unsigned char *sof;
+ 
+-	sof = pac_find_sof(&sd->sof_read, data, len);
++	sof = pac_find_sof(gspca_dev, &sd->sof_read, data, len);
+ 	if (sof) {
+ 		int n;
+ 
+diff --git a/drivers/media/usb/gspca/pac7302.c b/drivers/media/usb/gspca/pac7302.c
+index add6f725ba50..682ef3340911 100644
+--- a/drivers/media/usb/gspca/pac7302.c
++++ b/drivers/media/usb/gspca/pac7302.c
+@@ -344,13 +344,10 @@ static void reg_w_var(struct gspca_dev *gspca_dev,
+ 			reg_w_page(gspca_dev, page3, page3_len);
+ 			break;
+ 		default:
+-#ifdef GSPCA_DEBUG
+ 			if (len > USB_BUF_SZ) {
+-				PDEBUG(D_ERR|D_STREAM,
+-					"Incorrect variable sequence");
++				PERR("Incorrect variable sequence");
+ 				return;
+ 			}
+-#endif
+ 			while (len > 0) {
+ 				if (len < 8) {
+ 					reg_w_buf(gspca_dev,
+@@ -795,7 +792,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+ 	u8 *image;
+ 	u8 *sof;
+ 
+-	sof = pac_find_sof(&sd->sof_read, data, len);
++	sof = pac_find_sof(gspca_dev, &sd->sof_read, data, len);
+ 	if (sof) {
+ 		int n, lum_offset, footer_length;
+ 
+diff --git a/drivers/media/usb/gspca/pac7311.c b/drivers/media/usb/gspca/pac7311.c
+index a12dfbf6e051..1a5bdc853a80 100644
+--- a/drivers/media/usb/gspca/pac7311.c
++++ b/drivers/media/usb/gspca/pac7311.c
+@@ -262,8 +262,7 @@ static void reg_w_var(struct gspca_dev *gspca_dev,
+ 			break;
+ 		default:
+ 			if (len > USB_BUF_SZ) {
+-				PDEBUG(D_ERR|D_STREAM,
+-					"Incorrect variable sequence");
++				PERR("Incorrect variable sequence");
+ 				return;
+ 			}
+ 			while (len > 0) {
+@@ -575,7 +574,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+ 	u8 *image;
+ 	unsigned char *sof;
+ 
+-	sof = pac_find_sof(&sd->sof_read, data, len);
++	sof = pac_find_sof(gspca_dev, &sd->sof_read, data, len);
+ 	if (sof) {
+ 		int n, lum_offset, footer_length;
+ 
+diff --git a/drivers/media/usb/gspca/pac_common.h b/drivers/media/usb/gspca/pac_common.h
+index 8462a7c1a338..fbc5e226c3e4 100644
+--- a/drivers/media/usb/gspca/pac_common.h
++++ b/drivers/media/usb/gspca/pac_common.h
+@@ -71,7 +71,7 @@ static const unsigned char pac_sof_marker[5] =
+ 	   +----------+
+ */
+ 
+-static unsigned char *pac_find_sof(u8 *sof_read,
++static unsigned char *pac_find_sof(struct gspca_dev *gspca_dev, u8 *sof_read,
+ 					unsigned char *m, int len)
+ {
+ 	int i;
+diff --git a/drivers/media/usb/gspca/sn9c2028.c b/drivers/media/usb/gspca/sn9c2028.c
+index 03fa3fd940b4..39b6b2e02963 100644
+--- a/drivers/media/usb/gspca/sn9c2028.c
++++ b/drivers/media/usb/gspca/sn9c2028.c
+@@ -650,13 +650,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
+ 
+ 	result = sn9c2028_read1(gspca_dev);
+ 	if (result < 0)
+-		PDEBUG(D_ERR, "Camera Stop read failed");
++		PERR("Camera Stop read failed");
+ 
+ 	memset(data, 0, 6);
+ 	data[0] = 0x14;
+ 	result = sn9c2028_command(gspca_dev, data);
+ 	if (result < 0)
+-		PDEBUG(D_ERR, "Camera Stop command failed");
++		PERR("Camera Stop command failed");
+ }
+ 
+ /* Include sn9c2028 sof detection functions */
+diff --git a/drivers/media/usb/gspca/sonixj.c b/drivers/media/usb/gspca/sonixj.c
+index 8246e1dc3e9d..3b5ccb1c4cdf 100644
+--- a/drivers/media/usb/gspca/sonixj.c
++++ b/drivers/media/usb/gspca/sonixj.c
+@@ -1159,12 +1159,11 @@ static void reg_r(struct gspca_dev *gspca_dev,
+ 
+ 	if (gspca_dev->usb_err < 0)
+ 		return;
+-#ifdef GSPCA_DEBUG
+ 	if (len > USB_BUF_SZ) {
+-		pr_err("reg_r: buffer overflow\n");
++		PERR("reg_r: buffer overflow\n");
+ 		return;
+ 	}
+-#endif
++
+ 	ret = usb_control_msg(gspca_dev->dev,
+ 			usb_rcvctrlpipe(gspca_dev->dev, 0),
+ 			0,
+@@ -1213,12 +1212,12 @@ static void reg_w(struct gspca_dev *gspca_dev,
+ 		return;
+ 	PDEBUG(D_USBO, "reg_w [%04x] = %02x %02x ..",
+ 		value, buffer[0], buffer[1]);
+-#ifdef GSPCA_DEBUG
++
+ 	if (len > USB_BUF_SZ) {
+-		pr_err("reg_w: buffer overflow\n");
++		PERR("reg_w: buffer overflow\n");
+ 		return;
+ 	}
+-#endif
++
+ 	memcpy(gspca_dev->usb_buf, buffer, len);
+ 	ret = usb_control_msg(gspca_dev->dev,
+ 			usb_sndctrlpipe(gspca_dev->dev, 0),
+diff --git a/drivers/media/usb/gspca/spca1528.c b/drivers/media/usb/gspca/spca1528.c
+index 14d635277d71..688592b289ea 100644
+--- a/drivers/media/usb/gspca/spca1528.c
++++ b/drivers/media/usb/gspca/spca1528.c
+@@ -146,7 +146,7 @@ static void wait_status_0(struct gspca_dev *gspca_dev)
+ 		w += 15;
+ 		msleep(w);
+ 	} while (--i > 0);
+-	PDEBUG(D_ERR, "wait_status_0 timeout");
++	PERR("wait_status_0 timeout");
+ 	gspca_dev->usb_err = -ETIME;
+ }
+ 
+@@ -164,7 +164,7 @@ static void wait_status_1(struct gspca_dev *gspca_dev)
+ 			return;
+ 		}
+ 	} while (--i > 0);
+-	PDEBUG(D_ERR, "wait_status_1 timeout");
++	PERR("wait_status_1 timeout");
+ 	gspca_dev->usb_err = -ETIME;
+ }
+ 
+diff --git a/drivers/media/usb/gspca/spca500.c b/drivers/media/usb/gspca/spca500.c
+index 25cb68d0556d..9f8bf51fd64b 100644
+--- a/drivers/media/usb/gspca/spca500.c
++++ b/drivers/media/usb/gspca/spca500.c
+@@ -489,7 +489,7 @@ static int spca500_full_reset(struct gspca_dev *gspca_dev)
+ 		return err;
+ 	err = reg_r_wait(gspca_dev, 0x06, 0, 0);
+ 	if (err < 0) {
+-		PDEBUG(D_ERR, "reg_r_wait() failed");
++		PERR("reg_r_wait() failed");
+ 		return err;
+ 	}
+ 	/* all ok */
+@@ -505,7 +505,7 @@ static int spca500_full_reset(struct gspca_dev *gspca_dev)
+ static int spca500_synch310(struct gspca_dev *gspca_dev)
+ {
+ 	if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0) < 0) {
+-		PDEBUG(D_ERR, "Set packet size: set interface error");
++		PERR("Set packet size: set interface error");
+ 		goto error;
+ 	}
+ 	spca500_ping310(gspca_dev);
+@@ -519,7 +519,7 @@ static int spca500_synch310(struct gspca_dev *gspca_dev)
+ 	if (usb_set_interface(gspca_dev->dev,
+ 				gspca_dev->iface,
+ 				gspca_dev->alt) < 0) {
+-		PDEBUG(D_ERR, "Set packet size: set interface error");
++		PERR("Set packet size: set interface error");
+ 		goto error;
+ 	}
+ 	return 0;
+@@ -544,7 +544,7 @@ static void spca500_reinit(struct gspca_dev *gspca_dev)
+ 	err = spca50x_setup_qtable(gspca_dev, 0x00, 0x8800, 0x8840,
+ 				 qtable_pocketdv);
+ 	if (err < 0)
+-		PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed on init");
++		PERR("spca50x_setup_qtable failed on init");
+ 
+ 	/* set qtable index */
+ 	reg_w(gspca_dev, 0x00, 0x8880, 2);
+@@ -639,7 +639,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
+ 					   0x00, 0x8800, 0x8840,
+ 					   qtable_creative_pccam);
+ 		if (err < 0)
+-			PDEBUG(D_ERR, "spca50x_setup_qtable failed");
++			PERR("spca50x_setup_qtable failed");
+ 		/* Init SDRAM - needed for SDRAM access */
+ 		reg_w(gspca_dev, 0x00, 0x870a, 0x04);
+ 
+@@ -647,7 +647,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
+ 		reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
+ 		msleep(500);
+ 		if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
+-			PDEBUG(D_ERR, "reg_r_wait() failed");
++			PERR("reg_r_wait() failed");
+ 
+ 		reg_r(gspca_dev, 0x816b, 1);
+ 		Data = gspca_dev->usb_buf[0];
+@@ -660,13 +660,13 @@ static int sd_start(struct gspca_dev *gspca_dev)
+ 		/* enable drop packet */
+ 		err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
+ 		if (err < 0)
+-			PDEBUG(D_ERR, "failed to enable drop packet");
++			PERR("failed to enable drop packet");
+ 		reg_w(gspca_dev, 0x00, 0x8880, 3);
+ 		err = spca50x_setup_qtable(gspca_dev,
+ 					   0x00, 0x8800, 0x8840,
+ 					   qtable_creative_pccam);
+ 		if (err < 0)
+-			PDEBUG(D_ERR, "spca50x_setup_qtable failed");
++			PERR("spca50x_setup_qtable failed");
+ 
+ 		/* Init SDRAM - needed for SDRAM access */
+ 		reg_w(gspca_dev, 0x00, 0x870a, 0x04);
+@@ -675,7 +675,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
+ 		reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
+ 
+ 		if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
+-			PDEBUG(D_ERR, "reg_r_wait() failed");
++			PERR("reg_r_wait() failed");
+ 
+ 		reg_r(gspca_dev, 0x816b, 1);
+ 		Data = gspca_dev->usb_buf[0];
+@@ -689,18 +689,18 @@ static int sd_start(struct gspca_dev *gspca_dev)
+ 		/* do a full reset */
+ 		err = spca500_full_reset(gspca_dev);
+ 		if (err < 0)
+-			PDEBUG(D_ERR, "spca500_full_reset failed");
++			PERR("spca500_full_reset failed");
+ 
+ 		/* enable drop packet */
+ 		err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
+ 		if (err < 0)
+-			PDEBUG(D_ERR, "failed to enable drop packet");
++			PERR("failed to enable drop packet");
+ 		reg_w(gspca_dev, 0x00, 0x8880, 3);
+ 		err = spca50x_setup_qtable(gspca_dev,
+ 					   0x00, 0x8800, 0x8840,
+ 					   qtable_creative_pccam);
+ 		if (err < 0)
+-			PDEBUG(D_ERR, "spca50x_setup_qtable failed");
++			PERR("spca50x_setup_qtable failed");
+ 
+ 		spca500_setmode(gspca_dev, xmult, ymult);
+ 		reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
+@@ -709,7 +709,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
+ 		reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
+ 
+ 		if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
+-			PDEBUG(D_ERR, "reg_r_wait() failed");
++			PERR("reg_r_wait() failed");
+ 
+ 		reg_r(gspca_dev, 0x816b, 1);
+ 		Data = gspca_dev->usb_buf[0];
+@@ -722,7 +722,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
+ 		/* do a full reset */
+ 		err = spca500_full_reset(gspca_dev);
+ 		if (err < 0)
+-			PDEBUG(D_ERR, "spca500_full_reset failed");
++			PERR("spca500_full_reset failed");
+ 		/* enable drop packet */
+ 		reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
+ 		reg_w(gspca_dev, 0x00, 0x8880, 0);
+@@ -730,7 +730,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
+ 					   0x00, 0x8800, 0x8840,
+ 					   qtable_kodak_ez200);
+ 		if (err < 0)
+-			PDEBUG(D_ERR, "spca50x_setup_qtable failed");
++			PERR("spca50x_setup_qtable failed");
+ 		spca500_setmode(gspca_dev, xmult, ymult);
+ 
+ 		reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
+@@ -739,7 +739,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
+ 		reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
+ 
+ 		if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
+-			PDEBUG(D_ERR, "reg_r_wait() failed");
++			PERR("reg_r_wait() failed");
+ 
+ 		reg_r(gspca_dev, 0x816b, 1);
+ 		Data = gspca_dev->usb_buf[0];
+@@ -765,7 +765,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
+ 		err = spca50x_setup_qtable(gspca_dev,
+ 				   0x00, 0x8800, 0x8840, qtable_pocketdv);
+ 		if (err < 0)
+-			PDEBUG(D_ERR, "spca50x_setup_qtable failed");
++			PERR("spca50x_setup_qtable failed");
+ 		reg_w(gspca_dev, 0x00, 0x8880, 2);
+ 
+ 		/* familycam Quicksmart pocketDV stuff */
+@@ -795,7 +795,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
+ 					0x00, 0x8800,
+ 					0x8840, qtable_creative_pccam);
+ 		if (err < 0)
+-			PDEBUG(D_ERR, "spca50x_setup_qtable failed");
++			PERR("spca50x_setup_qtable failed");
+ 		reg_w(gspca_dev, 0x00, 0x8880, 3);
+ 		reg_w(gspca_dev, 0x00, 0x800a, 0x00);
+ 		/* Init SDRAM - needed for SDRAM access */
+diff --git a/drivers/media/usb/gspca/spca501.c b/drivers/media/usb/gspca/spca501.c
+index 3b7f777785b4..d92fd17d6701 100644
+--- a/drivers/media/usb/gspca/spca501.c
++++ b/drivers/media/usb/gspca/spca501.c
+@@ -1756,10 +1756,11 @@ static const __u16 spca501c_mysterious_init_data[][3] = {
+ 	{}
+ };
+ 
+-static int reg_write(struct usb_device *dev,
+-		     __u16 req, __u16 index, __u16 value)
++static int reg_write(struct gspca_dev *gspca_dev,
++					__u16 req, __u16 index, __u16 value)
+ {
+ 	int ret;
++	struct usb_device *dev = gspca_dev->dev;
+ 
+ 	ret = usb_control_msg(dev,
+ 			usb_sndctrlpipe(dev, 0),
+@@ -1774,17 +1775,15 @@ static int reg_write(struct usb_device *dev,
+ }
+ 
+ 
+-static int write_vector(struct gspca_dev *gspca_dev,
+-			const __u16 data[][3])
++static int write_vector(struct gspca_dev *gspca_dev, const __u16 data[][3])
+ {
+-	struct usb_device *dev = gspca_dev->dev;
+ 	int ret, i = 0;
+ 
+ 	while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
+-		ret = reg_write(dev, data[i][0], data[i][2], data[i][1]);
++		ret = reg_write(gspca_dev, data[i][0], data[i][2],
++								data[i][1]);
+ 		if (ret < 0) {
+-			PDEBUG(D_ERR,
+-				"Reg write failed for 0x%02x,0x%02x,0x%02x",
++			PERR("Reg write failed for 0x%02x,0x%02x,0x%02x",
+ 				data[i][0], data[i][1], data[i][2]);
+ 			return ret;
+ 		}
+@@ -1795,30 +1794,28 @@ static int write_vector(struct gspca_dev *gspca_dev,
+ 
+ static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
+ {
+-	reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x12, val);
++	reg_write(gspca_dev, SPCA501_REG_CCDSP, 0x12, val);
+ }
+ 
+ static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
+ {
+-	reg_write(gspca_dev->dev, 0x00, 0x00,
+-				  (val >> 8) & 0xff);
+-	reg_write(gspca_dev->dev, 0x00, 0x01,
+-				  val & 0xff);
++	reg_write(gspca_dev, 0x00, 0x00, (val >> 8) & 0xff);
++	reg_write(gspca_dev, 0x00, 0x01, val & 0xff);
+ }
+ 
+ static void setcolors(struct gspca_dev *gspca_dev, s32 val)
+ {
+-	reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x0c, val);
++	reg_write(gspca_dev, SPCA501_REG_CCDSP, 0x0c, val);
+ }
+ 
+ static void setblue_balance(struct gspca_dev *gspca_dev, s32 val)
+ {
+-	reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x11, val);
++	reg_write(gspca_dev, SPCA501_REG_CCDSP, 0x11, val);
+ }
+ 
+ static void setred_balance(struct gspca_dev *gspca_dev, s32 val)
+ {
+-	reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x13, val);
++	reg_write(gspca_dev, SPCA501_REG_CCDSP, 0x13, val);
+ }
+ 
+ /* this function is called at probe time */
+@@ -1868,7 +1865,6 @@ static int sd_init(struct gspca_dev *gspca_dev)
+ static int sd_start(struct gspca_dev *gspca_dev)
+ {
+ 	struct sd *sd = (struct sd *) gspca_dev;
+-	struct usb_device *dev = gspca_dev->dev;
+ 	int mode;
+ 
+ 	switch (sd->subtype) {
+@@ -1895,20 +1891,20 @@ static int sd_start(struct gspca_dev *gspca_dev)
+ 
+ 	/* Enable ISO packet machine CTRL reg=2,
+ 	 * index=1 bitmask=0x2 (bit ordinal 1) */
+-	reg_write(dev, SPCA50X_REG_USB, 0x6, 0x94);
++	reg_write(gspca_dev, SPCA50X_REG_USB, 0x6, 0x94);
+ 	switch (mode) {
+ 	case 0: /* 640x480 */
+-		reg_write(dev, SPCA50X_REG_USB, 0x07, 0x004a);
++		reg_write(gspca_dev, SPCA50X_REG_USB, 0x07, 0x004a);
+ 		break;
+ 	case 1: /* 320x240 */
+-		reg_write(dev, SPCA50X_REG_USB, 0x07, 0x104a);
++		reg_write(gspca_dev, SPCA50X_REG_USB, 0x07, 0x104a);
+ 		break;
+ 	default:
+ /*	case 2:  * 160x120 */
+-		reg_write(dev, SPCA50X_REG_USB, 0x07, 0x204a);
++		reg_write(gspca_dev, SPCA50X_REG_USB, 0x07, 0x204a);
+ 		break;
+ 	}
+-	reg_write(dev, SPCA501_REG_CTLRL, 0x01, 0x02);
++	reg_write(gspca_dev, SPCA501_REG_CTLRL, 0x01, 0x02);
+ 
+ 	return 0;
+ }
+@@ -1917,7 +1913,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
+ {
+ 	/* Disable ISO packet
+ 	 * machine CTRL reg=2, index=1 bitmask=0x0 (bit ordinal 1) */
+-	reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x01, 0x00);
++	reg_write(gspca_dev, SPCA501_REG_CTLRL, 0x01, 0x00);
+ }
+ 
+ /* called on streamoff with alt 0 and on disconnect */
+@@ -1925,7 +1921,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
+ {
+ 	if (!gspca_dev->present)
+ 		return;
+-	reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x05, 0x00);
++	reg_write(gspca_dev, SPCA501_REG_CTLRL, 0x05, 0x00);
+ }
+ 
+ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+diff --git a/drivers/media/usb/gspca/spca505.c b/drivers/media/usb/gspca/spca505.c
+index bc7d67c3cb04..232b330d2dd3 100644
+--- a/drivers/media/usb/gspca/spca505.c
++++ b/drivers/media/usb/gspca/spca505.c
+@@ -544,10 +544,11 @@ static const u8 spca505b_open_data_ccd[][3] = {
+ 	{}
+ };
+ 
+-static int reg_write(struct usb_device *dev,
++static int reg_write(struct gspca_dev *gspca_dev,
+ 		     u16 req, u16 index, u16 value)
+ {
+ 	int ret;
++	struct usb_device *dev = gspca_dev->dev;
+ 
+ 	ret = usb_control_msg(dev,
+ 			usb_sndctrlpipe(dev, 0),
+@@ -584,11 +585,11 @@ static int reg_read(struct gspca_dev *gspca_dev,
+ static int write_vector(struct gspca_dev *gspca_dev,
+ 			const u8 data[][3])
+ {
+-	struct usb_device *dev = gspca_dev->dev;
+ 	int ret, i = 0;
+ 
+ 	while (data[i][0] != 0) {
+-		ret = reg_write(dev, data[i][0], data[i][2], data[i][1]);
++		ret = reg_write(gspca_dev, data[i][0], data[i][2],
++								data[i][1]);
+ 		if (ret < 0)
+ 			return ret;
+ 		i++;
+@@ -629,14 +630,13 @@ static int sd_init(struct gspca_dev *gspca_dev)
+ 
+ static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
+ {
+-	reg_write(gspca_dev->dev, 0x05, 0x00, (255 - brightness) >> 6);
+-	reg_write(gspca_dev->dev, 0x05, 0x01, (255 - brightness) << 2);
++	reg_write(gspca_dev, 0x05, 0x00, (255 - brightness) >> 6);
++	reg_write(gspca_dev, 0x05, 0x01, (255 - brightness) << 2);
+ }
+ 
+ static int sd_start(struct gspca_dev *gspca_dev)
+ {
+ 	struct sd *sd = (struct sd *) gspca_dev;
+-	struct usb_device *dev = gspca_dev->dev;
+ 	int ret, mode;
+ 	static u8 mode_tb[][3] = {
+ 	/*	  r00   r06   r07	*/
+@@ -654,9 +654,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
+ 	ret = reg_read(gspca_dev, 0x06, 0x16);
+ 
+ 	if (ret < 0) {
+-		PDEBUG(D_ERR|D_CONF,
+-		       "register read failed err: %d",
+-		       ret);
++		PERR("register read failed err: %d", ret);
+ 		return ret;
+ 	}
+ 	if (ret != 0x0101) {
+@@ -664,22 +662,22 @@ static int sd_start(struct gspca_dev *gspca_dev)
+ 		       ret);
+ 	}
+ 
+-	ret = reg_write(gspca_dev->dev, 0x06, 0x16, 0x0a);
++	ret = reg_write(gspca_dev, 0x06, 0x16, 0x0a);
+ 	if (ret < 0)
+ 		return ret;
+-	reg_write(gspca_dev->dev, 0x05, 0xc2, 0x12);
++	reg_write(gspca_dev, 0x05, 0xc2, 0x12);
+ 
+ 	/* necessary because without it we can see stream
+ 	 * only once after loading module */
+ 	/* stopping usb registers Tomasz change */
+-	reg_write(dev, 0x02, 0x00, 0x00);
++	reg_write(gspca_dev, 0x02, 0x00, 0x00);
+ 
+ 	mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
+-	reg_write(dev, SPCA50X_REG_COMPRESS, 0x00, mode_tb[mode][0]);
+-	reg_write(dev, SPCA50X_REG_COMPRESS, 0x06, mode_tb[mode][1]);
+-	reg_write(dev, SPCA50X_REG_COMPRESS, 0x07, mode_tb[mode][2]);
++	reg_write(gspca_dev, SPCA50X_REG_COMPRESS, 0x00, mode_tb[mode][0]);
++	reg_write(gspca_dev, SPCA50X_REG_COMPRESS, 0x06, mode_tb[mode][1]);
++	reg_write(gspca_dev, SPCA50X_REG_COMPRESS, 0x07, mode_tb[mode][2]);
+ 
+-	return reg_write(dev, SPCA50X_REG_USB,
++	return reg_write(gspca_dev, SPCA50X_REG_USB,
+ 			 SPCA50X_USB_CTRL,
+ 			 SPCA50X_CUSB_ENABLE);
+ }
+@@ -687,7 +685,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
+ static void sd_stopN(struct gspca_dev *gspca_dev)
+ {
+ 	/* Disable ISO packet machine */
+-	reg_write(gspca_dev->dev, 0x02, 0x00, 0x00);
++	reg_write(gspca_dev, 0x02, 0x00, 0x00);
+ }
+ 
+ /* called on streamoff with alt 0 and on disconnect */
+@@ -697,11 +695,11 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
+ 		return;
+ 
+ 	/* This maybe reset or power control */
+-	reg_write(gspca_dev->dev, 0x03, 0x03, 0x20);
+-	reg_write(gspca_dev->dev, 0x03, 0x01, 0x00);
+-	reg_write(gspca_dev->dev, 0x03, 0x00, 0x01);
+-	reg_write(gspca_dev->dev, 0x05, 0x10, 0x01);
+-	reg_write(gspca_dev->dev, 0x05, 0x11, 0x0f);
++	reg_write(gspca_dev, 0x03, 0x03, 0x20);
++	reg_write(gspca_dev, 0x03, 0x01, 0x00);
++	reg_write(gspca_dev, 0x03, 0x00, 0x01);
++	reg_write(gspca_dev, 0x05, 0x10, 0x01);
++	reg_write(gspca_dev, 0x05, 0x11, 0x0f);
+ }
+ 
+ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+diff --git a/drivers/media/usb/gspca/spca508.c b/drivers/media/usb/gspca/spca508.c
+index 1286b4170b88..75f2beb2ea5a 100644
+--- a/drivers/media/usb/gspca/spca508.c
++++ b/drivers/media/usb/gspca/spca508.c
+@@ -1241,10 +1241,10 @@ static const u16 spca508_vista_init_data[][2] = {
+ 	{}
+ };
+ 
+-static int reg_write(struct usb_device *dev,
+-			u16 index, u16 value)
++static int reg_write(struct gspca_dev *gspca_dev, u16 index, u16 value)
+ {
+ 	int ret;
++	struct usb_device *dev = gspca_dev->dev;
+ 
+ 	ret = usb_control_msg(dev,
+ 			usb_sndctrlpipe(dev, 0),
+@@ -1286,22 +1286,21 @@ static int reg_read(struct gspca_dev *gspca_dev,
+ static int ssi_w(struct gspca_dev *gspca_dev,
+ 		u16 reg, u16 val)
+ {
+-	struct usb_device *dev = gspca_dev->dev;
+ 	int ret, retry;
+ 
+-	ret = reg_write(dev, 0x8802, reg >> 8);
++	ret = reg_write(gspca_dev, 0x8802, reg >> 8);
+ 	if (ret < 0)
+ 		goto out;
+-	ret = reg_write(dev, 0x8801, reg & 0x00ff);
++	ret = reg_write(gspca_dev, 0x8801, reg & 0x00ff);
+ 	if (ret < 0)
+ 		goto out;
+ 	if ((reg & 0xff00) == 0x1000) {		/* if 2 bytes */
+-		ret = reg_write(dev, 0x8805, val & 0x00ff);
++		ret = reg_write(gspca_dev, 0x8805, val & 0x00ff);
+ 		if (ret < 0)
+ 			goto out;
+ 		val >>= 8;
+ 	}
+-	ret = reg_write(dev, 0x8800, val);
++	ret = reg_write(gspca_dev, 0x8800, val);
+ 	if (ret < 0)
+ 		goto out;
+ 
+@@ -1314,8 +1313,7 @@ static int ssi_w(struct gspca_dev *gspca_dev,
+ 		if (gspca_dev->usb_buf[0] == 0)
+ 			break;
+ 		if (--retry <= 0) {
+-			PDEBUG(D_ERR, "ssi_w busy %02x",
+-					gspca_dev->usb_buf[0]);
++			PERR("ssi_w busy %02x", gspca_dev->usb_buf[0]);
+ 			ret = -1;
+ 			break;
+ 		}
+@@ -1329,7 +1327,6 @@ static int ssi_w(struct gspca_dev *gspca_dev,
+ static int write_vector(struct gspca_dev *gspca_dev,
+ 			const u16 (*data)[2])
+ {
+-	struct usb_device *dev = gspca_dev->dev;
+ 	int ret = 0;
+ 
+ 	while ((*data)[1] != 0) {
+@@ -1337,7 +1334,8 @@ static int write_vector(struct gspca_dev *gspca_dev,
+ 			if ((*data)[1] == 0xdd00)	/* delay */
+ 				msleep((*data)[0]);
+ 			else
+-				ret = reg_write(dev, (*data)[1], (*data)[0]);
++				ret = reg_write(gspca_dev, (*data)[1],
++								(*data)[0]);
+ 		} else {
+ 			ret = ssi_w(gspca_dev, (*data)[1], (*data)[0]);
+ 		}
+@@ -1363,8 +1361,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ 		spca508cs110_init_data,		/* MicroInnovationIC200 4 */
+ 		spca508_init_data,		/* ViewQuestVQ110 5 */
+ 	};
+-
+-#ifdef GSPCA_DEBUG
+ 	int data1, data2;
+ 
+ 	/* Read from global register the USB product and vendor IDs, just to
+@@ -1381,7 +1377,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ 
+ 	data1 = reg_read(gspca_dev, 0x8621);
+ 	PDEBUG(D_PROBE, "Window 1 average luminance: %d", data1);
+-#endif
+ 
+ 	cam = &gspca_dev->cam;
+ 	cam->cam_mode = sif_mode;
+@@ -1404,26 +1399,26 @@ static int sd_start(struct gspca_dev *gspca_dev)
+ 	int mode;
+ 
+ 	mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
+-	reg_write(gspca_dev->dev, 0x8500, mode);
++	reg_write(gspca_dev, 0x8500, mode);
+ 	switch (mode) {
+ 	case 0:
+ 	case 1:
+-		reg_write(gspca_dev->dev, 0x8700, 0x28);	/* clock */
++		reg_write(gspca_dev, 0x8700, 0x28); /* clock */
+ 		break;
+ 	default:
+ /*	case 2: */
+ /*	case 3: */
+-		reg_write(gspca_dev->dev, 0x8700, 0x23);	/* clock */
++		reg_write(gspca_dev, 0x8700, 0x23); /* clock */
+ 		break;
+ 	}
+-	reg_write(gspca_dev->dev, 0x8112, 0x10 | 0x20);
++	reg_write(gspca_dev, 0x8112, 0x10 | 0x20);
+ 	return 0;
+ }
+ 
+ static void sd_stopN(struct gspca_dev *gspca_dev)
+ {
+ 	/* Video ISO disable, Video Drop Packet enable: */
+-	reg_write(gspca_dev->dev, 0x8112, 0x20);
++	reg_write(gspca_dev, 0x8112, 0x20);
+ }
+ 
+ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+@@ -1450,10 +1445,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+ static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
+ {
+ 	/* MX seem contrast */
+-	reg_write(gspca_dev->dev, 0x8651, brightness);
+-	reg_write(gspca_dev->dev, 0x8652, brightness);
+-	reg_write(gspca_dev->dev, 0x8653, brightness);
+-	reg_write(gspca_dev->dev, 0x8654, brightness);
++	reg_write(gspca_dev, 0x8651, brightness);
++	reg_write(gspca_dev, 0x8652, brightness);
++	reg_write(gspca_dev, 0x8653, brightness);
++	reg_write(gspca_dev, 0x8654, brightness);
+ }
+ 
+ static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
+diff --git a/drivers/media/usb/gspca/spca561.c b/drivers/media/usb/gspca/spca561.c
+index d1db3d8f6522..403d71cd65d9 100644
+--- a/drivers/media/usb/gspca/spca561.c
++++ b/drivers/media/usb/gspca/spca561.c
+@@ -285,9 +285,10 @@ static const __u16 spca561_161rev12A_data2[][2] = {
+ 	{}
+ };
+ 
+-static void reg_w_val(struct usb_device *dev, __u16 index, __u8 value)
++static void reg_w_val(struct gspca_dev *gspca_dev, __u16 index, __u8 value)
+ {
+ 	int ret;
++	struct usb_device *dev = gspca_dev->dev;
+ 
+ 	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ 			      0,		/* request */
+@@ -301,12 +302,11 @@ static void reg_w_val(struct usb_device *dev, __u16 index, __u8 value)
+ static void write_vector(struct gspca_dev *gspca_dev,
+ 			const __u16 data[][2])
+ {
+-	struct usb_device *dev = gspca_dev->dev;
+ 	int i;
+ 
+ 	i = 0;
+ 	while (data[i][1] != 0) {
+-		reg_w_val(dev, data[i][1], data[i][0]);
++		reg_w_val(gspca_dev, data[i][1], data[i][0]);
+ 		i++;
+ 	}
+ }
+@@ -339,9 +339,9 @@ static void i2c_write(struct gspca_dev *gspca_dev, __u16 value, __u16 reg)
+ {
+ 	int retry = 60;
+ 
+-	reg_w_val(gspca_dev->dev, 0x8801, reg);
+-	reg_w_val(gspca_dev->dev, 0x8805, value);
+-	reg_w_val(gspca_dev->dev, 0x8800, value >> 8);
++	reg_w_val(gspca_dev, 0x8801, reg);
++	reg_w_val(gspca_dev, 0x8805, value);
++	reg_w_val(gspca_dev, 0x8800, value >> 8);
+ 	do {
+ 		reg_r(gspca_dev, 0x8803, 1);
+ 		if (!gspca_dev->usb_buf[0])
+@@ -355,9 +355,9 @@ static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode)
+ 	int retry = 60;
+ 	__u8 value;
+ 
+-	reg_w_val(gspca_dev->dev, 0x8804, 0x92);
+-	reg_w_val(gspca_dev->dev, 0x8801, reg);
+-	reg_w_val(gspca_dev->dev, 0x8802, mode | 0x01);
++	reg_w_val(gspca_dev, 0x8804, 0x92);
++	reg_w_val(gspca_dev, 0x8801, reg);
++	reg_w_val(gspca_dev, 0x8802, mode | 0x01);
+ 	do {
+ 		reg_r(gspca_dev, 0x8803, 1);
+ 		if (!gspca_dev->usb_buf[0]) {
+@@ -459,14 +459,13 @@ static int sd_init_72a(struct gspca_dev *gspca_dev)
+ 	write_sensor_72a(gspca_dev, rev72a_init_sensor1);
+ 	write_vector(gspca_dev, rev72a_init_data2);
+ 	write_sensor_72a(gspca_dev, rev72a_init_sensor2);
+-	reg_w_val(gspca_dev->dev, 0x8112, 0x30);
++	reg_w_val(gspca_dev, 0x8112, 0x30);
+ 	return 0;
+ }
+ 
+ static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
+ {
+ 	struct sd *sd = (struct sd *) gspca_dev;
+-	struct usb_device *dev = gspca_dev->dev;
+ 	__u16 reg;
+ 
+ 	if (sd->chip_revision == Rev012A)
+@@ -474,16 +473,15 @@ static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
+ 	else
+ 		reg = 0x8611;
+ 
+-	reg_w_val(dev, reg + 0, val);		/* R */
+-	reg_w_val(dev, reg + 1, val);		/* Gr */
+-	reg_w_val(dev, reg + 2, val);		/* B */
+-	reg_w_val(dev, reg + 3, val);		/* Gb */
++	reg_w_val(gspca_dev, reg + 0, val);		/* R */
++	reg_w_val(gspca_dev, reg + 1, val);		/* Gr */
++	reg_w_val(gspca_dev, reg + 2, val);		/* B */
++	reg_w_val(gspca_dev, reg + 3, val);		/* Gb */
+ }
+ 
+ static void setwhite(struct gspca_dev *gspca_dev, s32 white, s32 contrast)
+ {
+ 	struct sd *sd = (struct sd *) gspca_dev;
+-	struct usb_device *dev = gspca_dev->dev;
+ 	__u8 blue, red;
+ 	__u16 reg;
+ 
+@@ -496,11 +494,11 @@ static void setwhite(struct gspca_dev *gspca_dev, s32 white, s32 contrast)
+ 		reg = 0x8651;
+ 		red += contrast - 0x20;
+ 		blue += contrast - 0x20;
+-		reg_w_val(dev, 0x8652, contrast + 0x20); /* Gr */
+-		reg_w_val(dev, 0x8654, contrast + 0x20); /* Gb */
++		reg_w_val(gspca_dev, 0x8652, contrast + 0x20); /* Gr */
++		reg_w_val(gspca_dev, 0x8654, contrast + 0x20); /* Gb */
+ 	}
+-	reg_w_val(dev, reg, red);
+-	reg_w_val(dev, reg + 2, blue);
++	reg_w_val(gspca_dev, reg, red);
++	reg_w_val(gspca_dev, reg + 2, blue);
+ }
+ 
+ /* rev 12a only */
+@@ -570,7 +568,6 @@ static void setautogain(struct gspca_dev *gspca_dev, s32 val)
+ 
+ static int sd_start_12a(struct gspca_dev *gspca_dev)
+ {
+-	struct usb_device *dev = gspca_dev->dev;
+ 	int mode;
+ 	static const __u8 Reg8391[8] =
+ 		{0x92, 0x30, 0x20, 0x00, 0x0c, 0x00, 0x00, 0x00};
+@@ -578,34 +575,33 @@ static int sd_start_12a(struct gspca_dev *gspca_dev)
+ 	mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
+ 	if (mode <= 1) {
+ 		/* Use compression on 320x240 and above */
+-		reg_w_val(dev, 0x8500, 0x10 | mode);
++		reg_w_val(gspca_dev, 0x8500, 0x10 | mode);
+ 	} else {
+ 		/* I couldn't get the compression to work below 320x240
+ 		 * Fortunately at these resolutions the bandwidth
+ 		 * is sufficient to push raw frames at ~20fps */
+-		reg_w_val(dev, 0x8500, mode);
++		reg_w_val(gspca_dev, 0x8500, mode);
+ 	}		/* -- qq@kuku.eu.org */
+ 
+ 	gspca_dev->usb_buf[0] = 0xaa;
+ 	gspca_dev->usb_buf[1] = 0x00;
+ 	reg_w_buf(gspca_dev, 0x8307, 2);
+ 	/* clock - lower 0x8X values lead to fps > 30 */
+-	reg_w_val(gspca_dev->dev, 0x8700, 0x8a);
++	reg_w_val(gspca_dev, 0x8700, 0x8a);
+ 					/* 0x8f 0x85 0x27 clock */
+-	reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20);
+-	reg_w_val(gspca_dev->dev, 0x850b, 0x03);
++	reg_w_val(gspca_dev, 0x8112, 0x1e | 0x20);
++	reg_w_val(gspca_dev, 0x850b, 0x03);
+ 	memcpy(gspca_dev->usb_buf, Reg8391, 8);
+ 	reg_w_buf(gspca_dev, 0x8391, 8);
+ 	reg_w_buf(gspca_dev, 0x8390, 8);
+ 
+ 	/* Led ON (bit 3 -> 0 */
+-	reg_w_val(gspca_dev->dev, 0x8114, 0x00);
++	reg_w_val(gspca_dev, 0x8114, 0x00);
+ 	return 0;
+ }
+ static int sd_start_72a(struct gspca_dev *gspca_dev)
+ {
+ 	struct sd *sd = (struct sd *) gspca_dev;
+-	struct usb_device *dev = gspca_dev->dev;
+ 	int Clck;
+ 	int mode;
+ 
+@@ -630,15 +626,15 @@ static int sd_start_72a(struct gspca_dev *gspca_dev)
+ 		Clck = 0x21;
+ 		break;
+ 	}
+-	reg_w_val(dev, 0x8700, Clck);	/* 0x27 clock */
+-	reg_w_val(dev, 0x8702, 0x81);
+-	reg_w_val(dev, 0x8500, mode);	/* mode */
++	reg_w_val(gspca_dev, 0x8700, Clck);	/* 0x27 clock */
++	reg_w_val(gspca_dev, 0x8702, 0x81);
++	reg_w_val(gspca_dev, 0x8500, mode);	/* mode */
+ 	write_sensor_72a(gspca_dev, rev72a_init_sensor2);
+ 	setwhite(gspca_dev, v4l2_ctrl_g_ctrl(sd->hue),
+ 			v4l2_ctrl_g_ctrl(sd->contrast));
+ /*	setbrightness(gspca_dev);	 * fixme: bad values */
+ 	setautogain(gspca_dev, v4l2_ctrl_g_ctrl(sd->autogain));
+-	reg_w_val(dev, 0x8112, 0x10 | 0x20);
++	reg_w_val(gspca_dev, 0x8112, 0x10 | 0x20);
+ 	return 0;
+ }
+ 
+@@ -647,12 +643,12 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
+ 	struct sd *sd = (struct sd *) gspca_dev;
+ 
+ 	if (sd->chip_revision == Rev012A) {
+-		reg_w_val(gspca_dev->dev, 0x8112, 0x0e);
++		reg_w_val(gspca_dev, 0x8112, 0x0e);
+ 		/* Led Off (bit 3 -> 1 */
+-		reg_w_val(gspca_dev->dev, 0x8114, 0x08);
++		reg_w_val(gspca_dev, 0x8114, 0x08);
+ 	} else {
+-		reg_w_val(gspca_dev->dev, 0x8112, 0x20);
+-/*		reg_w_val(gspca_dev->dev, 0x8102, 0x00); ?? */
++		reg_w_val(gspca_dev, 0x8112, 0x20);
++/*		reg_w_val(gspca_dev, 0x8102, 0x00); ?? */
+ 	}
+ }
+ 
+@@ -736,7 +732,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+ 
+ 		/* This should never happen */
+ 		if (len < 2) {
+-			PDEBUG(D_ERR, "Short SOF packet, ignoring");
++			PERR("Short SOF packet, ignoring");
+ 			gspca_dev->last_packet_type = DISCARD_PACKET;
+ 			return;
+ 		}
+diff --git a/drivers/media/usb/gspca/sq905.c b/drivers/media/usb/gspca/sq905.c
+index 1d99f10a3e19..a7ae0ec9fa91 100644
+--- a/drivers/media/usb/gspca/sq905.c
++++ b/drivers/media/usb/gspca/sq905.c
+@@ -387,7 +387,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
+ 	}
+ 
+ 	if (ret < 0) {
+-		PDEBUG(D_ERR, "Start streaming command failed");
++		PERR("Start streaming command failed");
+ 		return ret;
+ 	}
+ 	/* Start the workqueue function to do the streaming */
+diff --git a/drivers/media/usb/gspca/sq905c.c b/drivers/media/usb/gspca/sq905c.c
+index 410cdcbb55d4..acb19fb9a3df 100644
+--- a/drivers/media/usb/gspca/sq905c.c
++++ b/drivers/media/usb/gspca/sq905c.c
+@@ -215,13 +215,13 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ 
+ 	ret = sq905c_command(gspca_dev, SQ905C_GET_ID, 0);
+ 	if (ret < 0) {
+-		PDEBUG(D_ERR, "Get version command failed");
++		PERR("Get version command failed");
+ 		return ret;
+ 	}
+ 
+ 	ret = sq905c_read(gspca_dev, 0xf5, 0, 20);
+ 	if (ret < 0) {
+-		PDEBUG(D_ERR, "Reading version command failed");
++		PERR("Reading version command failed");
+ 		return ret;
+ 	}
+ 	/* Note we leave out the usb id and the manufacturing date */
+@@ -286,7 +286,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
+ 	}
+ 
+ 	if (ret < 0) {
+-		PDEBUG(D_ERR, "Start streaming command failed");
++		PERR("Start streaming command failed");
+ 		return ret;
+ 	}
+ 	/* Start the workqueue function to do the streaming */
+diff --git a/drivers/media/usb/gspca/sq930x.c b/drivers/media/usb/gspca/sq930x.c
+index 7e8748b31e85..b10d0821111c 100644
+--- a/drivers/media/usb/gspca/sq930x.c
++++ b/drivers/media/usb/gspca/sq930x.c
+@@ -541,13 +541,11 @@ static void ucbus_write(struct gspca_dev *gspca_dev,
+ 	if (gspca_dev->usb_err < 0)
+ 		return;
+ 
+-#ifdef GSPCA_DEBUG
+ 	if ((batchsize - 1) * 3 > USB_BUF_SZ) {
+-		pr_err("Bug: usb_buf overflow\n");
++		PERR("Bug: usb_buf overflow\n");
+ 		gspca_dev->usb_err = -ENOMEM;
+ 		return;
+ 	}
+-#endif
+ 
+ 	for (;;) {
+ 		len = ncmds;
+diff --git a/drivers/media/usb/gspca/stv0680.c b/drivers/media/usb/gspca/stv0680.c
+index 67605272aaa8..9c0827631b9c 100644
+--- a/drivers/media/usb/gspca/stv0680.c
++++ b/drivers/media/usb/gspca/stv0680.c
+@@ -86,7 +86,7 @@ static int stv_sndctrl(struct gspca_dev *gspca_dev, int set, u8 req, u16 val,
+ static int stv0680_handle_error(struct gspca_dev *gspca_dev, int ret)
+ {
+ 	stv_sndctrl(gspca_dev, 0, 0x80, 0, 0x02); /* Get Last Error */
+-	PDEBUG(D_ERR, "last error: %i,  command = 0x%x",
++	PERR("last error: %i,  command = 0x%x",
+ 	       gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
+ 	return ret;
+ }
+@@ -98,7 +98,7 @@ static int stv0680_get_video_mode(struct gspca_dev *gspca_dev)
+ 	gspca_dev->usb_buf[0] = 0x0f;
+ 
+ 	if (stv_sndctrl(gspca_dev, 0, 0x87, 0, 0x08) != 0x08) {
+-		PDEBUG(D_ERR, "Get_Camera_Mode failed");
++		PERR("Get_Camera_Mode failed");
+ 		return stv0680_handle_error(gspca_dev, -EIO);
+ 	}
+ 
+@@ -116,13 +116,13 @@ static int stv0680_set_video_mode(struct gspca_dev *gspca_dev, u8 mode)
+ 	gspca_dev->usb_buf[0] = mode;
+ 
+ 	if (stv_sndctrl(gspca_dev, 3, 0x07, 0x0100, 0x08) != 0x08) {
+-		PDEBUG(D_ERR, "Set_Camera_Mode failed");
++		PERR("Set_Camera_Mode failed");
+ 		return stv0680_handle_error(gspca_dev, -EIO);
+ 	}
+ 
+ 	/* Verify we got what we've asked for */
+ 	if (stv0680_get_video_mode(gspca_dev) != mode) {
+-		PDEBUG(D_ERR, "Error setting camera video mode!");
++		PERR("Error setting camera video mode!");
+ 		return -EIO;
+ 	}
+ 
+@@ -146,7 +146,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ 	/* ping camera to be sure STV0680 is present */
+ 	if (stv_sndctrl(gspca_dev, 0, 0x88, 0x5678, 0x02) != 0x02 ||
+ 	    gspca_dev->usb_buf[0] != 0x56 || gspca_dev->usb_buf[1] != 0x78) {
+-		PDEBUG(D_ERR, "STV(e): camera ping failed!!");
++		PERR("STV(e): camera ping failed!!");
+ 		return stv0680_handle_error(gspca_dev, -ENODEV);
+ 	}
+ 
+@@ -156,7 +156,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ 
+ 	if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0200, 0x22) != 0x22 ||
+ 	    gspca_dev->usb_buf[7] != 0xa0 || gspca_dev->usb_buf[8] != 0x23) {
+-		PDEBUG(D_ERR, "Could not get descriptor 0200.");
++		PERR("Could not get descriptor 0200.");
+ 		return stv0680_handle_error(gspca_dev, -ENODEV);
+ 	}
+ 	if (stv_sndctrl(gspca_dev, 0, 0x8a, 0, 0x02) != 0x02)
+@@ -167,7 +167,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ 		return stv0680_handle_error(gspca_dev, -ENODEV);
+ 
+ 	if (!(gspca_dev->usb_buf[7] & 0x09)) {
+-		PDEBUG(D_ERR, "Camera supports neither CIF nor QVGA mode");
++		PERR("Camera supports neither CIF nor QVGA mode");
+ 		return -ENODEV;
+ 	}
+ 	if (gspca_dev->usb_buf[7] & 0x01)
+diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx.c b/drivers/media/usb/gspca/stv06xx/stv06xx.c
+index 657160b4a1f7..55ee7a61c67f 100644
+--- a/drivers/media/usb/gspca/stv06xx/stv06xx.c
++++ b/drivers/media/usb/gspca/stv06xx/stv06xx.c
+@@ -42,8 +42,10 @@ static bool dump_sensor;
+ int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data)
+ {
+ 	int err;
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	struct usb_device *udev = sd->gspca_dev.dev;
+ 	__u8 *buf = sd->gspca_dev.usb_buf;
++
+ 	u8 len = (i2c_data > 0xff) ? 2 : 1;
+ 
+ 	buf[0] = i2c_data & 0xff;
+@@ -62,6 +64,7 @@ int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data)
+ int stv06xx_read_bridge(struct sd *sd, u16 address, u8 *i2c_data)
+ {
+ 	int err;
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	struct usb_device *udev = sd->gspca_dev.dev;
+ 	__u8 *buf = sd->gspca_dev.usb_buf;
+ 
+@@ -110,6 +113,7 @@ static int stv06xx_write_sensor_finish(struct sd *sd)
+ int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len)
+ {
+ 	int err, i, j;
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	struct usb_device *udev = sd->gspca_dev.dev;
+ 	__u8 *buf = sd->gspca_dev.usb_buf;
+ 
+@@ -139,6 +143,7 @@ int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len)
+ int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len)
+ {
+ 	int err, i, j;
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	struct usb_device *udev = sd->gspca_dev.dev;
+ 	__u8 *buf = sd->gspca_dev.usb_buf;
+ 
+@@ -170,6 +175,7 @@ int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len)
+ int stv06xx_read_sensor(struct sd *sd, const u8 address, u16 *value)
+ {
+ 	int err;
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	struct usb_device *udev = sd->gspca_dev.dev;
+ 	__u8 *buf = sd->gspca_dev.usb_buf;
+ 
+@@ -283,7 +289,7 @@ static int stv06xx_start(struct gspca_dev *gspca_dev)
+ 	intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
+ 	alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
+ 	if (!alt) {
+-		PDEBUG(D_ERR, "Couldn't get altsetting");
++		PERR("Couldn't get altsetting");
+ 		return -EIO;
+ 	}
+ 
+@@ -341,7 +347,7 @@ static int stv06xx_isoc_nego(struct gspca_dev *gspca_dev)
+ 
+ 	ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
+ 	if (ret < 0)
+-		PDEBUG(D_ERR|D_STREAM, "set alt 1 err %d", ret);
++		PERR("set alt 1 err %d", ret);
+ 
+ 	return ret;
+ }
+@@ -406,7 +412,7 @@ static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev,
+ 		len -= 4;
+ 
+ 		if (len < chunk_len) {
+-			PDEBUG(D_ERR, "URB packet length is smaller"
++			PERR("URB packet length is smaller"
+ 				" than the specified chunk length");
+ 			gspca_dev->last_packet_type = DISCARD_PACKET;
+ 			return;
+@@ -449,7 +455,7 @@ static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev,
+ 				sd->to_skip = gspca_dev->width * 4;
+ 
+ 			if (chunk_len)
+-				PDEBUG(D_ERR, "Chunk length is "
++				PERR("Chunk length is "
+ 					      "non-zero on a SOF");
+ 			break;
+ 
+@@ -463,7 +469,7 @@ static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev,
+ 					NULL, 0);
+ 
+ 			if (chunk_len)
+-				PDEBUG(D_ERR, "Chunk length is "
++				PERR("Chunk length is "
+ 					      "non-zero on a EOF");
+ 			break;
+ 
+@@ -596,7 +602,6 @@ MODULE_DEVICE_TABLE(usb, device_table);
+ static int sd_probe(struct usb_interface *intf,
+ 			const struct usb_device_id *id)
+ {
+-	PDEBUG(D_PROBE, "Probing for a stv06xx device");
+ 	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
+ 			       THIS_MODULE);
+ }
+diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.c b/drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.c
+index 06fa54c5efb2..2220b70d47e6 100644
+--- a/drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.c
++++ b/drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.c
+@@ -255,7 +255,7 @@ static int hdcs_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+ 		if (err < 0)
+ 			return err;
+ 	}
+-	PDEBUG(D_V4L2, "Writing exposure %d, rowexp %d, srowexp %d",
++	PDEBUG(D_CONF, "Writing exposure %d, rowexp %d, srowexp %d",
+ 	       val, rowexp, srowexp);
+ 	return err;
+ }
+@@ -280,7 +280,7 @@ static int hdcs_set_gains(struct sd *sd, u8 g)
+ 
+ static int hdcs_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+ {
+-	PDEBUG(D_V4L2, "Writing gain %d", val);
++	PDEBUG(D_CONF, "Writing gain %d", val);
+ 	return hdcs_set_gains((struct sd *) gspca_dev,
+ 			       val & 0xff);
+ }
+@@ -467,6 +467,8 @@ static int hdcs_probe_1020(struct sd *sd)
+ 
+ static int hdcs_start(struct sd *sd)
+ {
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
++
+ 	PDEBUG(D_STREAM, "Starting stream");
+ 
+ 	return hdcs_set_state(sd, HDCS_STATE_RUN);
+@@ -474,6 +476,8 @@ static int hdcs_start(struct sd *sd)
+ 
+ static int hdcs_stop(struct sd *sd)
+ {
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
++
+ 	PDEBUG(D_STREAM, "Halting stream");
+ 
+ 	return hdcs_set_state(sd, HDCS_STATE_SLEEP);
+diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c
+index cdfc3d05ab6b..8206b7743300 100644
+--- a/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c
++++ b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c
+@@ -190,6 +190,7 @@ static int pb0100_start(struct sd *sd)
+ 	int err, packet_size, max_packet_size;
+ 	struct usb_host_interface *alt;
+ 	struct usb_interface *intf;
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	struct cam *cam = &sd->gspca_dev.cam;
+ 	u32 mode = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
+ 
+@@ -239,6 +240,7 @@ static int pb0100_start(struct sd *sd)
+ 
+ static int pb0100_stop(struct sd *sd)
+ {
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	int err;
+ 
+ 	err = stv06xx_write_sensor(sd, PB_ABORTFRAME, 1);
+@@ -334,7 +336,7 @@ static int pb0100_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+ 	err = stv06xx_write_sensor(sd, PB_G1GAIN, val);
+ 	if (!err)
+ 		err = stv06xx_write_sensor(sd, PB_G2GAIN, val);
+-	PDEBUG(D_V4L2, "Set green gain to %d, status: %d", val, err);
++	PDEBUG(D_CONF, "Set green gain to %d, status: %d", val, err);
+ 
+ 	if (!err)
+ 		err = pb0100_set_red_balance(gspca_dev, ctrls->red->val);
+@@ -357,7 +359,7 @@ static int pb0100_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
+ 		val = 255;
+ 
+ 	err = stv06xx_write_sensor(sd, PB_RGAIN, val);
+-	PDEBUG(D_V4L2, "Set red gain to %d, status: %d", val, err);
++	PDEBUG(D_CONF, "Set red gain to %d, status: %d", val, err);
+ 
+ 	return err;
+ }
+@@ -375,7 +377,7 @@ static int pb0100_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
+ 		val = 255;
+ 
+ 	err = stv06xx_write_sensor(sd, PB_BGAIN, val);
+-	PDEBUG(D_V4L2, "Set blue gain to %d, status: %d", val, err);
++	PDEBUG(D_CONF, "Set blue gain to %d, status: %d", val, err);
+ 
+ 	return err;
+ }
+@@ -386,7 +388,7 @@ static int pb0100_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+ 	int err;
+ 
+ 	err = stv06xx_write_sensor(sd, PB_RINTTIME, val);
+-	PDEBUG(D_V4L2, "Set exposure to %d, status: %d", val, err);
++	PDEBUG(D_CONF, "Set exposure to %d, status: %d", val, err);
+ 
+ 	return err;
+ }
+@@ -406,7 +408,7 @@ static int pb0100_set_autogain(struct gspca_dev *gspca_dev, __s32 val)
+ 		val = 0;
+ 
+ 	err = stv06xx_write_sensor(sd, PB_EXPGAIN, val);
+-	PDEBUG(D_V4L2, "Set autogain to %d (natural: %d), status: %d",
++	PDEBUG(D_CONF, "Set autogain to %d (natural: %d), status: %d",
+ 	       val, ctrls->natural->val, err);
+ 
+ 	return err;
+@@ -428,7 +430,7 @@ static int pb0100_set_autogain_target(struct gspca_dev *gspca_dev, __s32 val)
+ 	if (!err)
+ 		err = stv06xx_write_sensor(sd, PB_R22, darkpixels);
+ 
+-	PDEBUG(D_V4L2, "Set autogain target to %d, status: %d", val, err);
++	PDEBUG(D_CONF, "Set autogain target to %d, status: %d", val, err);
+ 
+ 	return err;
+ }
+diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_st6422.c b/drivers/media/usb/gspca/stv06xx/stv06xx_st6422.c
+index 8a57990dfe0f..515a9e121653 100644
+--- a/drivers/media/usb/gspca/stv06xx/stv06xx_st6422.c
++++ b/drivers/media/usb/gspca/stv06xx/stv06xx_st6422.c
+@@ -279,6 +279,8 @@ static int st6422_start(struct sd *sd)
+ 
+ static int st6422_stop(struct sd *sd)
+ {
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
++
+ 	PDEBUG(D_STREAM, "Halting stream");
+ 
+ 	return 0;
+diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.c b/drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.c
+index e95fa8997d22..bf3e5c317a26 100644
+--- a/drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.c
++++ b/drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.c
+@@ -131,6 +131,7 @@ static int vv6410_init(struct sd *sd)
+ static int vv6410_start(struct sd *sd)
+ {
+ 	int err;
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	struct cam *cam = &sd->gspca_dev.cam;
+ 	u32 priv = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
+ 
+@@ -163,6 +164,7 @@ static int vv6410_start(struct sd *sd)
+ 
+ static int vv6410_stop(struct sd *sd)
+ {
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	int err;
+ 
+ 	/* Turn off LED */
+@@ -208,7 +210,7 @@ static int vv6410_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+ 	else
+ 		i2c_data &= ~VV6410_HFLIP;
+ 
+-	PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
++	PDEBUG(D_CONF, "Set horizontal flip to %d", val);
+ 	err = stv06xx_write_sensor(sd, VV6410_DATAFORMAT, i2c_data);
+ 
+ 	return (err < 0) ? err : 0;
+@@ -229,7 +231,7 @@ static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+ 	else
+ 		i2c_data &= ~VV6410_VFLIP;
+ 
+-	PDEBUG(D_V4L2, "Set vertical flip to %d", val);
++	PDEBUG(D_CONF, "Set vertical flip to %d", val);
+ 	err = stv06xx_write_sensor(sd, VV6410_DATAFORMAT, i2c_data);
+ 
+ 	return (err < 0) ? err : 0;
+@@ -240,7 +242,7 @@ static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val)
+ 	int err;
+ 	struct sd *sd = (struct sd *) gspca_dev;
+ 
+-	PDEBUG(D_V4L2, "Set analog gain to %d", val);
++	PDEBUG(D_CONF, "Set analog gain to %d", val);
+ 	err = stv06xx_write_sensor(sd, VV6410_ANALOGGAIN, 0xf0 | (val & 0xf));
+ 
+ 	return (err < 0) ? err : 0;
+@@ -257,7 +259,7 @@ static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+ 	fine = val % VV6410_CIF_LINELENGTH;
+ 	coarse = min(512, val / VV6410_CIF_LINELENGTH);
+ 
+-	PDEBUG(D_V4L2, "Set coarse exposure to %d, fine expsure to %d",
++	PDEBUG(D_CONF, "Set coarse exposure to %d, fine expsure to %d",
+ 	       coarse, fine);
+ 
+ 	err = stv06xx_write_sensor(sd, VV6410_FINEH, fine >> 8);
+diff --git a/drivers/media/usb/gspca/sunplus.c b/drivers/media/usb/gspca/sunplus.c
+index 9ccfcb1c6479..af8767a9bd4c 100644
+--- a/drivers/media/usb/gspca/sunplus.c
++++ b/drivers/media/usb/gspca/sunplus.c
+@@ -251,12 +251,10 @@ static void reg_r(struct gspca_dev *gspca_dev,
+ {
+ 	int ret;
+ 
+-#ifdef GSPCA_DEBUG
+ 	if (len > USB_BUF_SZ) {
+-		pr_err("reg_r: buffer overflow\n");
++		PERR("reg_r: buffer overflow\n");
+ 		return;
+ 	}
+-#endif
+ 	if (gspca_dev->usb_err < 0)
+ 		return;
+ 	ret = usb_control_msg(gspca_dev->dev,
+@@ -357,12 +355,14 @@ static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
+ 	PDEBUG(D_FRAM, "after wait 0x%04x", gspca_dev->usb_buf[0]);
+ }
+ 
+-#ifdef GSPCA_DEBUG
+ static void spca504_read_info(struct gspca_dev *gspca_dev)
+ {
+ 	int i;
+ 	u8 info[6];
+ 
++	if (gspca_debug < D_STREAM)
++		return;
++
+ 	for (i = 0; i < 6; i++) {
+ 		reg_r(gspca_dev, 0, i, 1);
+ 		info[i] = gspca_dev->usb_buf[0];
+@@ -373,7 +373,6 @@ static void spca504_read_info(struct gspca_dev *gspca_dev)
+ 		info[0], info[1], info[2],
+ 		info[3], info[4], info[5]);
+ }
+-#endif
+ 
+ static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
+ 			u8 req,
+@@ -432,11 +431,13 @@ static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
+ 	}
+ }
+ 
+-#ifdef GSPCA_DEBUG
+ static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
+ {
+ 	u8 *data;
+ 
++	if (gspca_debug < D_STREAM)
++		return;
++
+ 	data = gspca_dev->usb_buf;
+ 	reg_r(gspca_dev, 0x20, 0, 5);
+ 	PDEBUG(D_STREAM, "FirmWare: %d %d %d %d %d",
+@@ -444,7 +445,6 @@ static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
+ 	reg_r(gspca_dev, 0x23, 0, 64);
+ 	reg_r(gspca_dev, 0x23, 1, 64);
+ }
+-#endif
+ 
+ static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
+ {
+@@ -457,9 +457,8 @@ static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
+ 		reg_w_riv(gspca_dev, 0x31, 0, 0);
+ 		spca504B_WaitCmdStatus(gspca_dev);
+ 		spca504B_PollingDataReady(gspca_dev);
+-#ifdef GSPCA_DEBUG
+ 		spca50x_GetFirmware(gspca_dev);
+-#endif
++
+ 		reg_w_1(gspca_dev, 0x24, 0, 8, 2);		/* type */
+ 		reg_r(gspca_dev, 0x24, 8, 1);
+ 
+@@ -645,14 +644,10 @@ static int sd_init(struct gspca_dev *gspca_dev)
+ 		/* fall thru */
+ 	case BRIDGE_SPCA533:
+ 		spca504B_PollingDataReady(gspca_dev);
+-#ifdef GSPCA_DEBUG
+ 		spca50x_GetFirmware(gspca_dev);
+-#endif
+ 		break;
+ 	case BRIDGE_SPCA536:
+-#ifdef GSPCA_DEBUG
+ 		spca50x_GetFirmware(gspca_dev);
+-#endif
+ 		reg_r(gspca_dev, 0x00, 0x5002, 1);
+ 		reg_w_1(gspca_dev, 0x24, 0, 0, 0);
+ 		reg_r(gspca_dev, 0x24, 0, 1);
+@@ -678,9 +673,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
+ /*	case BRIDGE_SPCA504: */
+ 		PDEBUG(D_STREAM, "Opening SPCA504");
+ 		if (sd->subtype == AiptekMiniPenCam13) {
+-#ifdef GSPCA_DEBUG
+ 			spca504_read_info(gspca_dev);
+-#endif
+ 
+ 			/* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
+ 			spca504A_acknowledged_command(gspca_dev, 0x24,
+@@ -752,9 +745,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
+ 		break;
+ 	case BRIDGE_SPCA504:
+ 		if (sd->subtype == AiptekMiniPenCam13) {
+-#ifdef GSPCA_DEBUG
+ 			spca504_read_info(gspca_dev);
+-#endif
+ 
+ 			/* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
+ 			spca504A_acknowledged_command(gspca_dev, 0x24,
+@@ -766,9 +757,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
+ 							0, 0, 0x9d, 1);
+ 		} else {
+ 			spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
+-#ifdef GSPCA_DEBUG
+ 			spca504_read_info(gspca_dev);
+-#endif
+ 			spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
+ 			spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
+ 		}
+diff --git a/drivers/media/usb/gspca/vc032x.c b/drivers/media/usb/gspca/vc032x.c
+index e50079503d96..c00ac57de510 100644
+--- a/drivers/media/usb/gspca/vc032x.c
++++ b/drivers/media/usb/gspca/vc032x.c
+@@ -2927,7 +2927,6 @@ static void reg_r(struct gspca_dev *gspca_dev,
+ 		  u16 len)
+ {
+ 	reg_r_i(gspca_dev, req, index, len);
+-#ifdef GSPCA_DEBUG
+ 	if (gspca_dev->usb_err < 0)
+ 		return;
+ 	if (len == 1)
+@@ -2936,7 +2935,6 @@ static void reg_r(struct gspca_dev *gspca_dev,
+ 	else
+ 		PDEBUG(D_USBI, "GET %02x 0001 %04x %*ph",
+ 				req, index, 3, gspca_dev->usb_buf);
+-#endif
+ }
+ 
+ static void reg_w_i(struct gspca_dev *gspca_dev,
+@@ -2964,11 +2962,9 @@ static void reg_w(struct gspca_dev *gspca_dev,
+ 			    u16 value,
+ 			    u16 index)
+ {
+-#ifdef GSPCA_DEBUG
+ 	if (gspca_dev->usb_err < 0)
+ 		return;
+ 	PDEBUG(D_USBO, "SET %02x %04x %04x", req, value, index);
+-#endif
+ 	reg_w_i(gspca_dev, req, value, index);
+ }
+ 
+@@ -3044,8 +3040,7 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev)
+ 		if (value == 0 && ptsensor_info->IdAdd == 0x82)
+ 			value = read_sensor_register(gspca_dev, 0x83);
+ 		if (value != 0) {
+-			PDEBUG(D_ERR|D_PROBE, "Sensor ID %04x (%d)",
+-				value, i);
++			PDEBUG(D_PROBE, "Sensor ID %04x (%d)", value, i);
+ 			if (value == ptsensor_info->VpId)
+ 				return ptsensor_info->sensorId;
+ 
+@@ -3069,14 +3064,12 @@ static void i2c_write(struct gspca_dev *gspca_dev,
+ {
+ 	int retry;
+ 
+-#ifdef GSPCA_DEBUG
+ 	if (gspca_dev->usb_err < 0)
+ 		return;
+ 	if (size == 1)
+ 		PDEBUG(D_USBO, "i2c_w %02x %02x", reg, *val);
+ 	else
+ 		PDEBUG(D_USBO, "i2c_w %02x %02x%02x", reg, *val, val[1]);
+-#endif
+ 	reg_r_i(gspca_dev, 0xa1, 0xb33f, 1);
+ /*fixme:should check if (!(gspca_dev->usb_buf[0] & 0x02)) error*/
+ 	reg_w_i(gspca_dev, 0xa0, size, 0xb334);
+diff --git a/drivers/media/usb/gspca/w996Xcf.c b/drivers/media/usb/gspca/w996Xcf.c
+index 9e3a909e0a00..2165da0c7ce1 100644
+--- a/drivers/media/usb/gspca/w996Xcf.c
++++ b/drivers/media/usb/gspca/w996Xcf.c
+@@ -232,6 +232,7 @@ static void w9968cf_smbus_write_nack(struct sd *sd)
+ 
+ static void w9968cf_smbus_read_ack(struct sd *sd)
+ {
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	int sda;
+ 
+ 	/* Ensure SDA is high before raising clock to avoid a spurious stop */
+@@ -248,6 +249,7 @@ static void w9968cf_smbus_read_ack(struct sd *sd)
+ /* SMBus protocol: S Addr Wr [A] Subaddr [A] Value [A] P */
+ static void w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value)
+ {
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	u16* data = (u16 *)sd->gspca_dev.usb_buf;
+ 
+ 	data[0] = 0x082f | ((sd->sensor_addr & 0x80) ? 0x1500 : 0x0);
+@@ -297,6 +299,7 @@ static void w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value)
+ /* SMBus protocol: S Addr Wr [A] Subaddr [A] P S Addr+1 Rd [A] [Value] NA P */
+ static int w9968cf_i2c_r(struct sd *sd, u8 reg)
+ {
++	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 	int ret = 0;
+ 	u8 value;
+ 
+@@ -326,7 +329,7 @@ static int w9968cf_i2c_r(struct sd *sd, u8 reg)
+ 		ret = value;
+ 		PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value);
+ 	} else
+-		PDEBUG(D_ERR, "i2c read [0x%02x] failed", reg);
++		PERR("i2c read [0x%02x] failed", reg);
+ 
+ 	return ret;
+ }
+diff --git a/drivers/media/usb/gspca/zc3xx.c b/drivers/media/usb/gspca/zc3xx.c
+index a8dc421f9f1f..cbfc2f921427 100644
+--- a/drivers/media/usb/gspca/zc3xx.c
++++ b/drivers/media/usb/gspca/zc3xx.c
+@@ -6259,12 +6259,11 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev)
+ 	retword |= i2c_read(gspca_dev, 0x01);		/* ID 1 */
+ 	PDEBUG(D_PROBE, "probe 3wr vga 2 0x%04x", retword);
+ 	if (retword == 0x2030) {
+-#ifdef GSPCA_DEBUG
+ 		u8 retbyte;
+ 
+ 		retbyte = i2c_read(gspca_dev, 0x02);	/* revision number */
+ 		PDEBUG(D_PROBE, "sensor PO2030 rev 0x%02x", retbyte);
+-#endif
++
+ 		send_unknown(gspca_dev, SENSOR_PO2030);
+ 		return retword;
+ 	}

commit fe3449a4aa4e62404cc1c57c945fd56152b2f877
+Author: Theodore Kilgore 
+Date:   Tue Dec 13 18:09:15 2011 -0300
+
+    [media] gspca: Add jl2005bcd sub driver
+    
+    Written by Theodore Kilgore
+    
+    With minor changes by Hans de Goede:
+    -Code style fixes
+    -Correct the verbose level on various PDEBUG messages
+    -Make error messages use pr_err instead of PDEBUG
+    -Document the jl20 pixel format
+    
+    Signed-off-by: Theodore Kilgore 
+    Signed-off-by: Hans de Goede 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/Documentation/DocBook/media/v4l/pixfmt.xml b/Documentation/DocBook/media/v4l/pixfmt.xml
+index a33a4b22173b..9ddc57cb2ef9 100644
+--- a/Documentation/DocBook/media/v4l/pixfmt.xml
++++ b/Documentation/DocBook/media/v4l/pixfmt.xml
+@@ -890,6 +890,11 @@ kernel sources in the file Documentation/video4linux/cx2341x/README.hm
+ 	    'M310'
+ 	    Compressed BGGR Bayer format used by the gspca driver.
+ 	  
++	  
++	    V4L2_PIX_FMT_JL2005BCD
++	    'JL20'
++	    JPEG compressed RGGB Bayer format used by the gspca driver.
++	  
+ 	  
+ 	    V4L2_PIX_FMT_OV511
+ 	    'O511'
+diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt
+index 393815b62810..f2060f0dc02c 100644
+--- a/Documentation/video4linux/gspca.txt
++++ b/Documentation/video4linux/gspca.txt
+@@ -279,6 +279,7 @@ pac7302		093a:2628	Genius iLook 300
+ pac7302		093a:2629	Genious iSlim 300
+ pac7302		093a:262a	Webcam 300k
+ pac7302		093a:262c	Philips SPC 230 NC
++jl2005bcd	0979:0227	Various brands, 19 known cameras supported
+ jeilinj		0979:0280	Sakar 57379
+ jeilinj		0979:0280	Sportscam DV15
+ zc3xx		0ac8:0302	Z-star Vimicro zc0302
+diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig
+index 103af3fe5aa0..dfe268bfa4f8 100644
+--- a/drivers/media/video/gspca/Kconfig
++++ b/drivers/media/video/gspca/Kconfig
+@@ -77,6 +77,16 @@ config USB_GSPCA_JEILINJ
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called gspca_jeilinj.
+ 
++config USB_GSPCA_JL2005BCD
++	tristate "JL2005B/C/D USB V4L2 driver"
++	depends on VIDEO_V4L2 && USB_GSPCA
++	help
++	  Say Y here if you want support for cameras based the
++	  JL2005B, JL2005C, or JL2005D chip.
++
++	  To compile this driver as a module, choose M here: the
++	  module will be called gspca_jl2005bcd.
++
+ config USB_GSPCA_KINECT
+ 	tristate "Kinect sensor device USB Camera Driver"
+ 	depends on VIDEO_V4L2 && USB_GSPCA
+diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile
+index f345f494d0f3..79ebe46e1ad7 100644
+--- a/drivers/media/video/gspca/Makefile
++++ b/drivers/media/video/gspca/Makefile
+@@ -5,6 +5,7 @@ obj-$(CONFIG_USB_GSPCA_CPIA1)    += gspca_cpia1.o
+ obj-$(CONFIG_USB_GSPCA_ETOMS)    += gspca_etoms.o
+ obj-$(CONFIG_USB_GSPCA_FINEPIX)  += gspca_finepix.o
+ obj-$(CONFIG_USB_GSPCA_JEILINJ)  += gspca_jeilinj.o
++obj-$(CONFIG_USB_GSPCA_JL2005BCD) += gspca_jl2005bcd.o
+ obj-$(CONFIG_USB_GSPCA_KINECT)   += gspca_kinect.o
+ obj-$(CONFIG_USB_GSPCA_KONICA)   += gspca_konica.o
+ obj-$(CONFIG_USB_GSPCA_MARS)     += gspca_mars.o
+@@ -49,6 +50,7 @@ gspca_cpia1-objs    := cpia1.o
+ gspca_etoms-objs    := etoms.o
+ gspca_finepix-objs  := finepix.o
+ gspca_jeilinj-objs  := jeilinj.o
++gspca_jl2005bcd-objs  := jl2005bcd.o
+ gspca_kinect-objs   := kinect.o
+ gspca_konica-objs   := konica.o
+ gspca_mars-objs     := mars.o
+diff --git a/drivers/media/video/gspca/jl2005bcd.c b/drivers/media/video/gspca/jl2005bcd.c
+new file mode 100644
+index 000000000000..53f58ef367cf
+--- /dev/null
++++ b/drivers/media/video/gspca/jl2005bcd.c
+@@ -0,0 +1,554 @@
++/*
++ * Jeilin JL2005B/C/D library
++ *
++ * Copyright (C) 2011 Theodore Kilgore 
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#define MODULE_NAME "jl2005bcd"
++
++#include 
++#include 
++#include "gspca.h"
++
++
++MODULE_AUTHOR("Theodore Kilgore ");
++MODULE_DESCRIPTION("JL2005B/C/D USB Camera Driver");
++MODULE_LICENSE("GPL");
++
++/* Default timeouts, in ms */
++#define JL2005C_CMD_TIMEOUT 500
++#define JL2005C_DATA_TIMEOUT 1000
++
++/* Maximum transfer size to use. */
++#define JL2005C_MAX_TRANSFER 0x200
++#define FRAME_HEADER_LEN 16
++
++
++/* specific webcam descriptor */
++struct sd {
++	struct gspca_dev gspca_dev;  /* !! must be the first item */
++	unsigned char firmware_id[6];
++	const struct v4l2_pix_format *cap_mode;
++	/* Driver stuff */
++	struct work_struct work_struct;
++	struct workqueue_struct *work_thread;
++	u8 frame_brightness;
++	int block_size;	/* block size of camera */
++	int vga;	/* 1 if vga cam, 0 if cif cam */
++};
++
++
++/* Camera has two resolution settings. What they are depends on model. */
++static const struct v4l2_pix_format cif_mode[] = {
++	{176, 144, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
++		.bytesperline = 176,
++		.sizeimage = 176 * 144,
++		.colorspace = V4L2_COLORSPACE_SRGB,
++		.priv = 0},
++	{352, 288, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
++		.bytesperline = 352,
++		.sizeimage = 352 * 288,
++		.colorspace = V4L2_COLORSPACE_SRGB,
++		.priv = 0},
++};
++
++static const struct v4l2_pix_format vga_mode[] = {
++	{320, 240, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
++		.bytesperline = 320,
++		.sizeimage = 320 * 240,
++		.colorspace = V4L2_COLORSPACE_SRGB,
++		.priv = 0},
++	{640, 480, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
++		.bytesperline = 640,
++		.sizeimage = 640 * 480,
++		.colorspace = V4L2_COLORSPACE_SRGB,
++		.priv = 0},
++};
++
++/*
++ * cam uses endpoint 0x03 to send commands, 0x84 for read commands,
++ * and 0x82 for bulk data transfer.
++ */
++
++/* All commands are two bytes only */
++static int jl2005c_write2(struct gspca_dev *gspca_dev, unsigned char *command)
++{
++	int retval;
++
++	memcpy(gspca_dev->usb_buf, command, 2);
++	retval = usb_bulk_msg(gspca_dev->dev,
++			usb_sndbulkpipe(gspca_dev->dev, 3),
++			gspca_dev->usb_buf, 2, NULL, 500);
++	if (retval < 0)
++		pr_err("command write [%02x] error %d\n",
++		       gspca_dev->usb_buf[0], retval);
++	return retval;
++}
++
++/* Response to a command is one byte in usb_buf[0], only if requested. */
++static int jl2005c_read1(struct gspca_dev *gspca_dev)
++{
++	int retval;
++
++	retval = usb_bulk_msg(gspca_dev->dev,
++				usb_rcvbulkpipe(gspca_dev->dev, 0x84),
++				gspca_dev->usb_buf, 1, NULL, 500);
++	if (retval < 0)
++		pr_err("read command [0x%02x] error %d\n",
++		       gspca_dev->usb_buf[0], retval);
++	return retval;
++}
++
++/* Response appears in gspca_dev->usb_buf[0] */
++static int jl2005c_read_reg(struct gspca_dev *gspca_dev, unsigned char reg)
++{
++	int retval;
++
++	static u8 instruction[2] = {0x95, 0x00};
++	/* put register to read in byte 1 */
++	instruction[1] = reg;
++	/* Send the read request */
++	retval = jl2005c_write2(gspca_dev, instruction);
++	if (retval < 0)
++		return retval;
++	retval = jl2005c_read1(gspca_dev);
++
++	return retval;
++}
++
++static int jl2005c_start_new_frame(struct gspca_dev *gspca_dev)
++{
++	int i;
++	int retval;
++	int frame_brightness = 0;
++
++	static u8 instruction[2] = {0x7f, 0x01};
++
++	retval = jl2005c_write2(gspca_dev, instruction);
++	if (retval < 0)
++		return retval;
++
++	i = 0;
++	while (i < 20 && !frame_brightness) {
++		/* If we tried 20 times, give up. */
++		retval = jl2005c_read_reg(gspca_dev, 0x7e);
++		if (retval < 0)
++			return retval;
++		frame_brightness = gspca_dev->usb_buf[0];
++		retval = jl2005c_read_reg(gspca_dev, 0x7d);
++		if (retval < 0)
++			return retval;
++		i++;
++	}
++	PDEBUG(D_FRAM, "frame_brightness is 0x%02x", gspca_dev->usb_buf[0]);
++	return retval;
++}
++
++static int jl2005c_write_reg(struct gspca_dev *gspca_dev, unsigned char reg,
++						    unsigned char value)
++{
++	int retval;
++	u8 instruction[2];
++
++	instruction[0] = reg;
++	instruction[1] = value;
++
++	retval = jl2005c_write2(gspca_dev, instruction);
++	if (retval < 0)
++			return retval;
++
++	return retval;
++}
++
++static int jl2005c_get_firmware_id(struct gspca_dev *gspca_dev)
++{
++	struct sd *sd = (struct sd *)gspca_dev;
++	int i = 0;
++	int retval = -1;
++	unsigned char regs_to_read[] = {0x57, 0x02, 0x03, 0x5d, 0x5e, 0x5f};
++
++	PDEBUG(D_PROBE, "Running jl2005c_get_firmware_id");
++	/* Read the first ID byte once for warmup */
++	retval = jl2005c_read_reg(gspca_dev, regs_to_read[0]);
++	PDEBUG(D_PROBE, "response is %02x", gspca_dev->usb_buf[0]);
++	if (retval < 0)
++		return retval;
++	/* Now actually get the ID string */
++	for (i = 0; i < 6; i++) {
++		retval = jl2005c_read_reg(gspca_dev, regs_to_read[i]);
++		if (retval < 0)
++			return retval;
++		sd->firmware_id[i] = gspca_dev->usb_buf[0];
++	}
++	PDEBUG(D_PROBE, "firmware ID is %02x%02x%02x%02x%02x%02x",
++						sd->firmware_id[0],
++						sd->firmware_id[1],
++						sd->firmware_id[2],
++						sd->firmware_id[3],
++						sd->firmware_id[4],
++						sd->firmware_id[5]);
++	return 0;
++}
++
++static int jl2005c_stream_start_vga_lg
++		    (struct gspca_dev *gspca_dev)
++{
++	int i;
++	int retval = -1;
++	static u8 instruction[][2] = {
++		{0x05, 0x00},
++		{0x7c, 0x00},
++		{0x7d, 0x18},
++		{0x02, 0x00},
++		{0x01, 0x00},
++		{0x04, 0x52},
++	};
++
++	for (i = 0; i < ARRAY_SIZE(instruction); i++) {
++		msleep(60);
++		retval = jl2005c_write2(gspca_dev, instruction[i]);
++		if (retval < 0)
++			return retval;
++	}
++	msleep(60);
++	return retval;
++}
++
++static int jl2005c_stream_start_vga_small(struct gspca_dev *gspca_dev)
++{
++	int i;
++	int retval = -1;
++	static u8 instruction[][2] = {
++		{0x06, 0x00},
++		{0x7c, 0x00},
++		{0x7d, 0x1a},
++		{0x02, 0x00},
++		{0x01, 0x00},
++		{0x04, 0x52},
++	};
++
++	for (i = 0; i < ARRAY_SIZE(instruction); i++) {
++		msleep(60);
++		retval = jl2005c_write2(gspca_dev, instruction[i]);
++		if (retval < 0)
++			return retval;
++	}
++	msleep(60);
++	return retval;
++}
++
++static int jl2005c_stream_start_cif_lg(struct gspca_dev *gspca_dev)
++{
++	int i;
++	int retval = -1;
++	static u8 instruction[][2] = {
++		{0x05, 0x00},
++		{0x7c, 0x00},
++		{0x7d, 0x30},
++		{0x02, 0x00},
++		{0x01, 0x00},
++		{0x04, 0x42},
++	};
++
++	for (i = 0; i < ARRAY_SIZE(instruction); i++) {
++		msleep(60);
++		retval = jl2005c_write2(gspca_dev, instruction[i]);
++		if (retval < 0)
++			return retval;
++	}
++	msleep(60);
++	return retval;
++}
++
++static int jl2005c_stream_start_cif_small(struct gspca_dev *gspca_dev)
++{
++	int i;
++	int retval = -1;
++	static u8 instruction[][2] = {
++		{0x06, 0x00},
++		{0x7c, 0x00},
++		{0x7d, 0x32},
++		{0x02, 0x00},
++		{0x01, 0x00},
++		{0x04, 0x42},
++	};
++
++	for (i = 0; i < ARRAY_SIZE(instruction); i++) {
++		msleep(60);
++		retval = jl2005c_write2(gspca_dev, instruction[i]);
++		if (retval < 0)
++			return retval;
++	}
++	msleep(60);
++	return retval;
++}
++
++
++static int jl2005c_stop(struct gspca_dev *gspca_dev)
++{
++	int retval;
++
++	retval = jl2005c_write_reg(gspca_dev, 0x07, 0x00);
++	return retval;
++}
++
++/* This function is called as a workqueue function and runs whenever the camera
++ * is streaming data. Because it is a workqueue function it is allowed to sleep
++ * so we can use synchronous USB calls. To avoid possible collisions with other
++ * threads attempting to use the camera's USB interface the gspca usb_lock is
++ * used when performing the one USB control operation inside the workqueue,
++ * which tells the camera to close the stream. In practice the only thing
++ * which needs to be protected against is the usb_set_interface call that
++ * gspca makes during stream_off. Otherwise the camera doesn't provide any
++ * controls that the user could try to change.
++ */
++static void jl2005c_dostream(struct work_struct *work)
++{
++	struct sd *dev = container_of(work, struct sd, work_struct);
++	struct gspca_dev *gspca_dev = &dev->gspca_dev;
++	int bytes_left = 0; /* bytes remaining in current frame. */
++	int data_len;   /* size to use for the next read. */
++	int header_read = 0;
++	unsigned char header_sig[2] = {0x4a, 0x4c};
++	int act_len;
++	int packet_type;
++	int ret;
++	u8 *buffer;
++
++	buffer = kmalloc(JL2005C_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
++	if (!buffer) {
++		pr_err("Couldn't allocate USB buffer\n");
++		goto quit_stream;
++	}
++
++	while (gspca_dev->present && gspca_dev->streaming) {
++		/* Check if this is a new frame. If so, start the frame first */
++		if (!header_read) {
++			mutex_lock(&gspca_dev->usb_lock);
++			ret = jl2005c_start_new_frame(gspca_dev);
++			mutex_unlock(&gspca_dev->usb_lock);
++			if (ret < 0)
++				goto quit_stream;
++			ret = usb_bulk_msg(gspca_dev->dev,
++				usb_rcvbulkpipe(gspca_dev->dev, 0x82),
++				buffer, JL2005C_MAX_TRANSFER, &act_len,
++				JL2005C_DATA_TIMEOUT);
++			PDEBUG(D_PACK,
++				"Got %d bytes out of %d for header",
++					act_len, JL2005C_MAX_TRANSFER);
++			if (ret < 0 || act_len < JL2005C_MAX_TRANSFER)
++				goto quit_stream;
++			/* Check whether we actually got the first blodk */
++			if (memcmp(header_sig, buffer, 2) != 0) {
++				pr_err("First block is not the first block\n");
++				goto quit_stream;
++			}
++			/* total size to fetch is byte 7, times blocksize
++			 * of which we already got act_len */
++			bytes_left = buffer[0x07] * dev->block_size - act_len;
++			PDEBUG(D_PACK, "bytes_left = 0x%x", bytes_left);
++			/* We keep the header. It has other information, too.*/
++			packet_type = FIRST_PACKET;
++			gspca_frame_add(gspca_dev, packet_type,
++					buffer, act_len);
++			header_read = 1;
++		}
++		while (bytes_left > 0 && gspca_dev->present) {
++			data_len = bytes_left > JL2005C_MAX_TRANSFER ?
++				JL2005C_MAX_TRANSFER : bytes_left;
++			ret = usb_bulk_msg(gspca_dev->dev,
++				usb_rcvbulkpipe(gspca_dev->dev, 0x82),
++				buffer, data_len, &act_len,
++				JL2005C_DATA_TIMEOUT);
++			if (ret < 0 || act_len < data_len)
++				goto quit_stream;
++			PDEBUG(D_PACK,
++				"Got %d bytes out of %d for frame",
++						data_len, bytes_left);
++			bytes_left -= data_len;
++			if (bytes_left == 0) {
++				packet_type = LAST_PACKET;
++				header_read = 0;
++			} else
++				packet_type = INTER_PACKET;
++			gspca_frame_add(gspca_dev, packet_type,
++					buffer, data_len);
++		}
++	}
++quit_stream:
++	if (gspca_dev->present) {
++		mutex_lock(&gspca_dev->usb_lock);
++		jl2005c_stop(gspca_dev);
++		mutex_unlock(&gspca_dev->usb_lock);
++	}
++	kfree(buffer);
++}
++
++
++
++
++/* This function is called at probe time */
++static int sd_config(struct gspca_dev *gspca_dev,
++			const struct usb_device_id *id)
++{
++	struct cam *cam;
++	struct sd *sd = (struct sd *) gspca_dev;
++
++	cam = &gspca_dev->cam;
++	/* We don't use the buffer gspca allocates so make it small. */
++	cam->bulk_size = 64;
++	cam->bulk = 1;
++	/* For the rest, the camera needs to be detected */
++	jl2005c_get_firmware_id(gspca_dev);
++	/* Here are some known firmware IDs
++	 * First some JL2005B cameras
++	 * {0x41, 0x07, 0x04, 0x2c, 0xe8, 0xf2}	Sakar KidzCam
++	 * {0x45, 0x02, 0x08, 0xb9, 0x00, 0xd2}	No-name JL2005B
++	 * JL2005C cameras
++	 * {0x01, 0x0c, 0x16, 0x10, 0xf8, 0xc8}	Argus DC-1512
++	 * {0x12, 0x04, 0x03, 0xc0, 0x00, 0xd8}	ICarly
++	 * {0x86, 0x08, 0x05, 0x02, 0x00, 0xd4}	Jazz
++	 *
++	 * Based upon this scanty evidence, we can detect a CIF camera by
++	 * testing byte 0 for 0x4x.
++	 */
++	if ((sd->firmware_id[0] & 0xf0) == 0x40) {
++		cam->cam_mode	= cif_mode;
++		cam->nmodes	= ARRAY_SIZE(cif_mode);
++		sd->block_size	= 0x80;
++	} else {
++		cam->cam_mode	= vga_mode;
++		cam->nmodes	= ARRAY_SIZE(vga_mode);
++		sd->block_size	= 0x200;
++	}
++
++	INIT_WORK(&sd->work_struct, jl2005c_dostream);
++
++	return 0;
++}
++
++/* this function is called at probe and resume time */
++static int sd_init(struct gspca_dev *gspca_dev)
++{
++	return 0;
++}
++
++static int sd_start(struct gspca_dev *gspca_dev)
++{
++
++	struct sd *sd = (struct sd *) gspca_dev;
++	sd->cap_mode = gspca_dev->cam.cam_mode;
++
++	switch (gspca_dev->width) {
++	case 640:
++		PDEBUG(D_STREAM, "Start streaming at vga resolution");
++		jl2005c_stream_start_vga_lg(gspca_dev);
++		break;
++	case 320:
++		PDEBUG(D_STREAM, "Start streaming at qvga resolution");
++		jl2005c_stream_start_vga_small(gspca_dev);
++		break;
++	case 352:
++		PDEBUG(D_STREAM, "Start streaming at cif resolution");
++		jl2005c_stream_start_cif_lg(gspca_dev);
++		break;
++	case 176:
++		PDEBUG(D_STREAM, "Start streaming at qcif resolution");
++		jl2005c_stream_start_cif_small(gspca_dev);
++		break;
++	default:
++		pr_err("Unknown resolution specified\n");
++		return -1;
++	}
++
++	/* Start the workqueue function to do the streaming */
++	sd->work_thread = create_singlethread_workqueue(MODULE_NAME);
++	queue_work(sd->work_thread, &sd->work_struct);
++
++	return 0;
++}
++
++/* called on streamoff with alt==0 and on disconnect */
++/* the usb_lock is held at entry - restore on exit */
++static void sd_stop0(struct gspca_dev *gspca_dev)
++{
++	struct sd *dev = (struct sd *) gspca_dev;
++
++	/* wait for the work queue to terminate */
++	mutex_unlock(&gspca_dev->usb_lock);
++	/* This waits for sq905c_dostream to finish */
++	destroy_workqueue(dev->work_thread);
++	dev->work_thread = NULL;
++	mutex_lock(&gspca_dev->usb_lock);
++}
++
++
++
++/* sub-driver description */
++static const struct sd_desc sd_desc = {
++	.name = MODULE_NAME,
++	/* .ctrls = none have been detected */
++	/* .nctrls = ARRAY_SIZE(sd_ctrls),  */
++	.config = sd_config,
++	.init = sd_init,
++	.start = sd_start,
++	.stop0 = sd_stop0,
++};
++
++/* -- module initialisation -- */
++static const __devinitdata struct usb_device_id device_table[] = {
++	{USB_DEVICE(0x0979, 0x0227)},
++	{}
++};
++MODULE_DEVICE_TABLE(usb, device_table);
++
++/* -- device connect -- */
++static int sd_probe(struct usb_interface *intf,
++				const struct usb_device_id *id)
++{
++	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
++				THIS_MODULE);
++}
++
++static struct usb_driver sd_driver = {
++	.name = MODULE_NAME,
++	.id_table = device_table,
++	.probe = sd_probe,
++	.disconnect = gspca_disconnect,
++#ifdef CONFIG_PM
++	.suspend = gspca_suspend,
++	.resume = gspca_resume,
++#endif
++};
++
++/* -- module insert / remove -- */
++static int __init sd_mod_init(void)
++{
++	int ret;
++
++	ret = usb_register(&sd_driver);
++	if (ret < 0)
++		return ret;
++	return 0;
++}
++static void __exit sd_mod_exit(void)
++{
++	usb_deregister(&sd_driver);
++}
++
++module_init(sd_mod_init);
++module_exit(sd_mod_exit);
+diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
+index 2965906a02c9..6bfaa767a817 100644
+--- a/include/linux/videodev2.h
++++ b/include/linux/videodev2.h
+@@ -401,6 +401,7 @@ struct v4l2_pix_format {
+ #define V4L2_PIX_FMT_SPCA561  v4l2_fourcc('S', '5', '6', '1') /* compressed GBRG bayer */
+ #define V4L2_PIX_FMT_PAC207   v4l2_fourcc('P', '2', '0', '7') /* compressed BGGR bayer */
+ #define V4L2_PIX_FMT_MR97310A v4l2_fourcc('M', '3', '1', '0') /* compressed BGGR bayer */
++#define V4L2_PIX_FMT_JL2005BCD v4l2_fourcc('J', 'L', '2', '0') /* compressed RGGB bayer */
+ #define V4L2_PIX_FMT_SN9C2028 v4l2_fourcc('S', 'O', 'N', 'X') /* compressed GBRG bayer */
+ #define V4L2_PIX_FMT_SQ905C   v4l2_fourcc('9', '0', '5', 'C') /* compressed RGGB bayer */
+ #define V4L2_PIX_FMT_PJPG     v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */

commit 634b4770539de63581ccdb554426547ced6ded01
+Author: Theodore Kilgore 
+Date:   Fri Dec 24 17:06:04 2010 -0300
+
+    [media] gspca - sq905c: Adds the Lego Bionicle
+    
+    This patch adds the Vendor:Product number of the Lego Bionicle camera to
+    the existing gspca/sq905c.c and also a line for the camera in gspca.txt.
+    The camera works "out of the box" with these small changes. So this is
+    just in time for Christmas. Think of the children.
+    
+    Signed-off-by: Theodore Kilgore 
+    Signed-off-by: Jean-François Moine 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt
+index 6a562eeeb4cd..261776e0c5e1 100644
+--- a/Documentation/video4linux/gspca.txt
++++ b/Documentation/video4linux/gspca.txt
+@@ -366,6 +366,7 @@ t613		17a1:0128	TASCORP JPEG Webcam, NGS Cyclops
+ vc032x		17ef:4802	Lenovo Vc0323+MI1310_SOC
+ pac207		2001:f115	D-Link DSB-C120
+ sq905c		2770:9050	Disney pix micro (CIF)
++sq905c		2770:9051	Lego Bionicle
+ sq905c		2770:9052	Disney pix micro 2 (VGA)
+ sq905c		2770:905c	All 11 known cameras with this ID
+ sq905		2770:9120	All 24 known cameras with this ID
+diff --git a/drivers/media/video/gspca/sq905c.c b/drivers/media/video/gspca/sq905c.c
+index c2e88b5303cb..8ba199543856 100644
+--- a/drivers/media/video/gspca/sq905c.c
++++ b/drivers/media/video/gspca/sq905c.c
+@@ -301,6 +301,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
+ static const __devinitdata struct usb_device_id device_table[] = {
+ 	{USB_DEVICE(0x2770, 0x905c)},
+ 	{USB_DEVICE(0x2770, 0x9050)},
++	{USB_DEVICE(0x2770, 0x9051)},
+ 	{USB_DEVICE(0x2770, 0x9052)},
+ 	{USB_DEVICE(0x2770, 0x913d)},
+ 	{}

commit 9d3103d061224e939272d05d54192038f66ffd54
+Author: Theodore Kilgore 
+Date:   Tue Feb 9 18:05:25 2010 -0300
+
+    V4L/DVB: gspca_mr97310a: add support for the Sakar 1638x CyberPix
+    
+    This camera has a sensor type we did not support sofar, this patch adds
+    support for the new sensor type found in the Sakar 1638x CyberPix.
+    
+    Signed-off-by: Theodore Kilgore 
+    Signed-off-by: Hans de Goede 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c
+index 959ea2a530a4..33744e724eaa 100644
+--- a/drivers/media/video/gspca/mr97310a.c
++++ b/drivers/media/video/gspca/mr97310a.c
+@@ -57,6 +57,14 @@
+ #define MR97310A_GAIN_MAX		31
+ #define MR97310A_GAIN_DEFAULT		25
+ 
++#define MR97310A_CONTRAST_MIN		0
++#define MR97310A_CONTRAST_MAX		31
++#define MR97310A_CONTRAST_DEFAULT	23
++
++#define MR97310A_CS_GAIN_MIN		0
++#define MR97310A_CS_GAIN_MAX		0x7ff
++#define MR97310A_CS_GAIN_DEFAULT	0x110
++
+ #define MR97310A_MIN_CLOCKDIV_MIN	3
+ #define MR97310A_MIN_CLOCKDIV_MAX	8
+ #define MR97310A_MIN_CLOCKDIV_DEFAULT	3
+@@ -82,7 +90,8 @@ struct sd {
+ 
+ 	int brightness;
+ 	u16 exposure;
+-	u8 gain;
++	u32 gain;
++	u8 contrast;
+ 	u8 min_clockdiv;
+ };
+ 
+@@ -98,6 +107,8 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
+ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
+ static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
+ static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
++static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
++static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
+ static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
+ static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
+ static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val);
+@@ -105,11 +116,13 @@ static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val);
+ static void setbrightness(struct gspca_dev *gspca_dev);
+ static void setexposure(struct gspca_dev *gspca_dev);
+ static void setgain(struct gspca_dev *gspca_dev);
++static void setcontrast(struct gspca_dev *gspca_dev);
+ 
+ /* V4L2 controls supported by the driver */
+ static const struct ctrl sd_ctrls[] = {
+ /* Separate brightness control description for Argus QuickClix as it has
+-   different limits from the other mr97310a cameras */
++ * different limits from the other mr97310a cameras, and separate gain
++ * control for Sakar CyberPix camera. */
+ 	{
+ #define NORM_BRIGHTNESS_IDX 0
+ 		{
+@@ -171,7 +184,37 @@ static const struct ctrl sd_ctrls[] = {
+ 		.get = sd_getgain,
+ 	},
+ 	{
+-#define MIN_CLOCKDIV_IDX 4
++#define SAKAR_CS_GAIN_IDX 4
++		{
++			.id = V4L2_CID_GAIN,
++			.type = V4L2_CTRL_TYPE_INTEGER,
++			.name = "Gain",
++			.minimum = MR97310A_CS_GAIN_MIN,
++			.maximum = MR97310A_CS_GAIN_MAX,
++			.step = 1,
++			.default_value = MR97310A_CS_GAIN_DEFAULT,
++			.flags = 0,
++		},
++		.set = sd_setgain,
++		.get = sd_getgain,
++	},
++	{
++#define CONTRAST_IDX 5
++		{
++			.id = V4L2_CID_CONTRAST,
++			.type = V4L2_CTRL_TYPE_INTEGER,
++			.name = "Contrast",
++			.minimum = MR97310A_CONTRAST_MIN,
++			.maximum = MR97310A_CONTRAST_MAX,
++			.step = 1,
++			.default_value = MR97310A_CONTRAST_DEFAULT,
++			.flags = 0,
++		},
++		.set = sd_setcontrast,
++		.get = sd_getcontrast,
++	},
++	{
++#define MIN_CLOCKDIV_IDX 6
+ 		{
+ 			.id = V4L2_CID_PRIVATE_BASE,
+ 			.type = V4L2_CTRL_TYPE_INTEGER,
+@@ -436,6 +479,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ {
+ 	struct sd *sd = (struct sd *) gspca_dev;
+ 	struct cam *cam;
++	int gain_default = MR97310A_GAIN_DEFAULT;
+ 	int err_code;
+ 
+ 	cam = &gspca_dev->cam;
+@@ -479,7 +523,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ 		 *
+ 		 * Name		sd->sensor_type		reported by
+ 		 *
+-		 * Sakar Spy-shot	0		T. Kilgore
++		 * Sakar 56379 Spy-shot	0		T. Kilgore
+ 		 * Innovage		0		T. Kilgore
+ 		 * Vivitar Mini		0		H. De Goede
+ 		 * Vivitar Mini		0		E. Rodriguez
+@@ -507,14 +551,17 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ 
+ 		/*
+ 		 * Here is a table of the responses to the query for sensor
+-		 * type, from the known MR97310A VGA cameras.
++		 * type, from the known MR97310A VGA cameras. Six different
++		 * cameras of which five share the same USB ID.
+ 		 *
+ 		 * Name			gspca_dev->usb_buf[]	sd->sensor_type
+ 		 *				sd->do_lcd_stop
+ 		 * Aiptek Pencam VGA+	0300		0		1
+-		 * ION digital		0350		0		1
++		 * ION digital		0300		0		1
+ 		 * Argus DC-1620	0450		1		0
+ 		 * Argus QuickClix	0420		1		1
++		 * Sakar 77379 Digital	0350		0		1
++		 * Sakar 1638x CyberPix	0120		0		2
+ 		 *
+ 		 * Based upon these results, we assume default settings
+ 		 * and then correct as necessary, as follows.
+@@ -524,10 +571,12 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ 		sd->sensor_type = 1;
+ 		sd->do_lcd_stop = 0;
+ 		sd->adj_colors = 0;
+-		if ((gspca_dev->usb_buf[0] != 0x03) &&
++		if (gspca_dev->usb_buf[0] == 0x01) {
++			sd->sensor_type = 2;
++		} else if ((gspca_dev->usb_buf[0] != 0x03) &&
+ 					(gspca_dev->usb_buf[0] != 0x04)) {
+ 			PDEBUG(D_ERR, "Unknown VGA Sensor id Byte 0: %02x",
+-					gspca_dev->usb_buf[1]);
++					gspca_dev->usb_buf[0]);
+ 			PDEBUG(D_ERR, "Defaults assumed, may not work");
+ 			PDEBUG(D_ERR, "Please report this");
+ 		}
+@@ -571,9 +620,13 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ 		/* No brightness for sensor_type 0 */
+ 		if (sd->sensor_type == 0)
+ 			gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) |
+-					      (1 << ARGUS_QC_BRIGHTNESS_IDX);
++					      (1 << ARGUS_QC_BRIGHTNESS_IDX) |
++					      (1 << CONTRAST_IDX) |
++					      (1 << SAKAR_CS_GAIN_IDX);
+ 		else
+ 			gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) |
++					      (1 << CONTRAST_IDX) |
++					      (1 << SAKAR_CS_GAIN_IDX) |
+ 					      (1 << MIN_CLOCKDIV_IDX);
+ 	} else {
+ 		/* All controls need to be disabled if VGA sensor_type is 0 */
+@@ -582,17 +635,30 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ 					      (1 << ARGUS_QC_BRIGHTNESS_IDX) |
+ 					      (1 << EXPOSURE_IDX) |
+ 					      (1 << GAIN_IDX) |
++					      (1 << CONTRAST_IDX) |
++					      (1 << SAKAR_CS_GAIN_IDX) |
+ 					      (1 << MIN_CLOCKDIV_IDX);
+-		else if (sd->do_lcd_stop)
++		else if (sd->sensor_type == 2) {
++			gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) |
++					      (1 << ARGUS_QC_BRIGHTNESS_IDX) |
++					      (1 << GAIN_IDX) |
++					      (1 << MIN_CLOCKDIV_IDX);
++			gain_default = MR97310A_CS_GAIN_DEFAULT;
++		} else if (sd->do_lcd_stop)
+ 			/* Argus QuickClix has different brightness limits */
+-			gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX);
++			gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) |
++					      (1 << CONTRAST_IDX) |
++					      (1 << SAKAR_CS_GAIN_IDX);
+ 		else
+-			gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX);
++			gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) |
++					      (1 << CONTRAST_IDX) |
++					      (1 << SAKAR_CS_GAIN_IDX);
+ 	}
+ 
+ 	sd->brightness = MR97310A_BRIGHTNESS_DEFAULT;
+ 	sd->exposure = MR97310A_EXPOSURE_DEFAULT;
+-	sd->gain = MR97310A_GAIN_DEFAULT;
++	sd->gain = gain_default;
++	sd->contrast = MR97310A_CONTRAST_DEFAULT;
+ 	sd->min_clockdiv = MR97310A_MIN_CLOCKDIV_DEFAULT;
+ 
+ 	return 0;
+@@ -720,6 +786,10 @@ static int start_vga_cam(struct gspca_dev *gspca_dev)
+ 		data[5]  = 0x00;
+ 		data[10] = 0x91;
+ 	}
++	if (sd->sensor_type == 2) {
++		data[5]  = 0x00;
++		data[10] = 0x18;
++	}
+ 
+ 	switch (gspca_dev->width) {
+ 	case 160:
+@@ -734,6 +804,10 @@ static int start_vga_cam(struct gspca_dev *gspca_dev)
+ 		data[4] = 0x78;  /* reg 3, V size/4 */
+ 		data[6] = 0x04;  /* reg 5, H start */
+ 		data[8] = 0x03;  /* reg 7, V start */
++		if (sd->sensor_type == 2) {
++			data[6] = 2;
++			data[8] = 1;
++		}
+ 		if (sd->do_lcd_stop)
+ 			data[8] = 0x04;  /* Bayer tile shifted */
+ 		break;
+@@ -756,7 +830,6 @@ static int start_vga_cam(struct gspca_dev *gspca_dev)
+ 		return err_code;
+ 
+ 	if (!sd->sensor_type) {
+-		/* The only known sensor_type 0 cam is the Argus DC-1620 */
+ 		const struct sensor_w_data vga_sensor0_init_data[] = {
+ 			{0x01, 0x00, {0x0c, 0x00, 0x04}, 3},
+ 			{0x14, 0x00, {0x01, 0xe4, 0x02, 0x84}, 4},
+@@ -767,7 +840,7 @@ static int start_vga_cam(struct gspca_dev *gspca_dev)
+ 		};
+ 		err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data,
+ 					 ARRAY_SIZE(vga_sensor0_init_data));
+-	} else {	/* sd->sensor_type = 1 */
++	} else if (sd->sensor_type == 1) {
+ 		const struct sensor_w_data color_adj[] = {
+ 			{0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00,
+ 				/* adjusted blue, green, red gain correct
+@@ -805,6 +878,48 @@ static int start_vga_cam(struct gspca_dev *gspca_dev)
+ 
+ 		err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data,
+ 					 ARRAY_SIZE(vga_sensor1_init_data));
++	} else {	/* sensor type == 2 */
++		const struct sensor_w_data vga_sensor2_init_data[] = {
++
++			{0x01, 0x00, {0x48}, 1},
++			{0x02, 0x00, {0x22}, 1},
++			/* Reg 3 msb and 4 is lsb of the exposure setting*/
++			{0x05, 0x00, {0x10}, 1},
++			{0x06, 0x00, {0x00}, 1},
++			{0x07, 0x00, {0x00}, 1},
++			{0x08, 0x00, {0x00}, 1},
++			{0x09, 0x00, {0x00}, 1},
++			/* The following are used in the gain control
++			 * which is BTW completely borked in the OEM driver
++			 * The values for each color go from 0 to 0x7ff
++			 *{0x0a, 0x00, {0x01}, 1},  green1 gain msb
++			 *{0x0b, 0x00, {0x10}, 1},  green1 gain lsb
++			 *{0x0c, 0x00, {0x01}, 1},  red gain msb
++			 *{0x0d, 0x00, {0x10}, 1},  red gain lsb
++			 *{0x0e, 0x00, {0x01}, 1},  blue gain msb
++			 *{0x0f, 0x00, {0x10}, 1},  blue gain lsb
++			 *{0x10, 0x00, {0x01}, 1}, green2 gain msb
++			 *{0x11, 0x00, {0x10}, 1}, green2 gain lsb
++			 */
++			{0x12, 0x00, {0x00}, 1},
++			{0x13, 0x00, {0x04}, 1}, /* weird effect on colors */
++			{0x14, 0x00, {0x00}, 1},
++			{0x15, 0x00, {0x06}, 1},
++			{0x16, 0x00, {0x01}, 1},
++			{0x17, 0x00, {0xe2}, 1}, /* vertical alignment */
++			{0x18, 0x00, {0x02}, 1},
++			{0x19, 0x00, {0x82}, 1}, /* don't mess with */
++			{0x1a, 0x00, {0x00}, 1},
++			{0x1b, 0x00, {0x20}, 1},
++			/* {0x1c, 0x00, {0x17}, 1}, contrast control */
++			{0x1d, 0x00, {0x80}, 1}, /* moving causes a mess */
++			{0x1e, 0x00, {0x08}, 1}, /* moving jams the camera */
++			{0x1f, 0x00, {0x0c}, 1},
++			{0x20, 0x00, {0x00}, 1},
++			{0, 0, {0}, 0}
++		};
++		err_code = sensor_write_regs(gspca_dev, vga_sensor2_init_data,
++					 ARRAY_SIZE(vga_sensor2_init_data));
+ 	}
+ 	return err_code;
+ }
+@@ -837,6 +952,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
+ 		return err_code;
+ 
+ 	setbrightness(gspca_dev);
++	setcontrast(gspca_dev);
+ 	setexposure(gspca_dev);
+ 	setgain(gspca_dev);
+ 
+@@ -896,7 +1012,7 @@ static void setbrightness(struct gspca_dev *gspca_dev)
+ static void setexposure(struct gspca_dev *gspca_dev)
+ {
+ 	struct sd *sd = (struct sd *) gspca_dev;
+-	int exposure;
++	int exposure = MR97310A_EXPOSURE_DEFAULT;
+ 	u8 buf[2];
+ 
+ 	if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX))
+@@ -908,6 +1024,11 @@ static void setexposure(struct gspca_dev *gspca_dev)
+ 		exposure = (sd->exposure * 9267) / 10000 + 300;
+ 		sensor_write1(gspca_dev, 3, exposure >> 4);
+ 		sensor_write1(gspca_dev, 4, exposure & 0x0f);
++	} else if (sd->sensor_type == 2) {
++		exposure = sd->exposure;
++		exposure >>= 3;
++		sensor_write1(gspca_dev, 3, exposure >> 8);
++		sensor_write1(gspca_dev, 4, exposure & 0xff);
+ 	} else {
+ 		/* We have both a clock divider and an exposure register.
+ 		   We first calculate the clock divider, as that determines
+@@ -946,17 +1067,34 @@ static void setexposure(struct gspca_dev *gspca_dev)
+ static void setgain(struct gspca_dev *gspca_dev)
+ {
+ 	struct sd *sd = (struct sd *) gspca_dev;
++	u8 gainreg;
+ 
+-	if (gspca_dev->ctrl_dis & (1 << GAIN_IDX))
++	if ((gspca_dev->ctrl_dis & (1 << GAIN_IDX)) &&
++	    (gspca_dev->ctrl_dis & (1 << SAKAR_CS_GAIN_IDX)))
+ 		return;
+ 
+-	if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) {
++	if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1)
+ 		sensor_write1(gspca_dev, 0x0e, sd->gain);
+-	} else {
++	else if (sd->cam_type == CAM_TYPE_VGA && sd->sensor_type == 2)
++		for (gainreg = 0x0a; gainreg < 0x11; gainreg += 2) {
++			sensor_write1(gspca_dev, gainreg, sd->gain >> 8);
++			sensor_write1(gspca_dev, gainreg + 1, sd->gain & 0xff);
++		}
++	else
+ 		sensor_write1(gspca_dev, 0x10, sd->gain);
+-	}
+ }
+ 
++static void setcontrast(struct gspca_dev *gspca_dev)
++{
++	struct sd *sd = (struct sd *) gspca_dev;
++
++	if (gspca_dev->ctrl_dis & (1 << CONTRAST_IDX))
++		return;
++
++	sensor_write1(gspca_dev, 0x1c, sd->contrast);
++}
++
++
+ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
+ {
+ 	struct sd *sd = (struct sd *) gspca_dev;
+@@ -1011,6 +1149,25 @@ static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
+ 	return 0;
+ }
+ 
++static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
++{
++	struct sd *sd = (struct sd *) gspca_dev;
++
++	sd->contrast = val;
++	if (gspca_dev->streaming)
++		setcontrast(gspca_dev);
++	return 0;
++}
++
++
++static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
++{
++	struct sd *sd = (struct sd *) gspca_dev;
++
++	*val = sd->contrast;
++	return 0;
++}
++
+ static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val)
+ {
+ 	struct sd *sd = (struct sd *) gspca_dev;

commit c260fe936de6a52010a3247f9c3e8da47d9726e8
+Author: Theodore Kilgore 
+Date:   Fri Jan 15 05:54:36 2010 -0300
+
+    V4L/DVB: gspca_mr97310a: Simplify sensor detection
+    
+    Simplify sensor detection a bit (share more of the code between cif and vga
+    cameras). Also remove an unnecessary write from zero_the_pointer().
+    
+    Signed-off-by: Theodore Kilgore 
+    Signed-off-by: Hans de Goede 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c
+index d842e8184426..959ea2a530a4 100644
+--- a/drivers/media/video/gspca/mr97310a.c
++++ b/drivers/media/video/gspca/mr97310a.c
+@@ -327,7 +327,6 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev)
+ 	if (err_code < 0)
+ 		return err_code;
+ 
+-	err_code = mr_write(gspca_dev, 1);
+ 	data[0] = 0x19;
+ 	data[1] = 0x51;
+ 	err_code = mr_write(gspca_dev, 2);
+@@ -460,12 +459,14 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ 	if (err_code < 0)
+ 		return err_code;
+ 
++	/* Now, the query for sensor type. */
++	err_code = cam_get_response16(gspca_dev, 0x07, 1);
++	if (err_code < 0)
++		return err_code;
++
+ 	if (id->idProduct == 0x0110 || id->idProduct == 0x010e) {
+ 		sd->cam_type = CAM_TYPE_CIF;
+ 		cam->nmodes--;
+-		err_code = cam_get_response16(gspca_dev, 0x06, 1);
+-		if (err_code < 0)
+-			return err_code;
+ 		/*
+ 		 * All but one of the known CIF cameras share the same USB ID,
+ 		 * but two different init routines are in use, and the control
+@@ -473,7 +474,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ 		 * of the two known varieties is connected!
+ 		 *
+ 		 * A list of known CIF cameras follows. They all report either
+-		 * 0002 for type 0 or 0003 for type 1.
++		 * 0200 for type 0 or 0300 for type 1.
+ 		 * If you have another to report, please do
+ 		 *
+ 		 * Name		sd->sensor_type		reported by
+@@ -487,7 +488,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ 		 * Philips dig. keych.	1		T. Kilgore
+ 		 * Trust Spyc@m 100	1		A. Jacobs
+ 		 */
+-		switch (gspca_dev->usb_buf[1]) {
++		switch (gspca_dev->usb_buf[0]) {
+ 		case 2:
+ 			sd->sensor_type = 0;
+ 			break;
+@@ -504,13 +505,9 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ 	} else {
+ 		sd->cam_type = CAM_TYPE_VGA;
+ 
+-		err_code = cam_get_response16(gspca_dev, 0x07, 1);
+-		if (err_code < 0)
+-			return err_code;
+-
+ 		/*
+-		 * Here is a table of the responses to the previous command
+-		 * from the known MR97310A VGA cameras.
++		 * Here is a table of the responses to the query for sensor
++		 * type, from the known MR97310A VGA cameras.
+ 		 *
+ 		 * Name			gspca_dev->usb_buf[]	sd->sensor_type
+ 		 *				sd->do_lcd_stop
+@@ -560,7 +557,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ 		PDEBUG(D_PROBE, "MR97310A VGA camera detected, sensor: %d",
+ 		       sd->sensor_type);
+ 	}
+-	/* Stop streaming as we've started it to probe the sensor type. */
++	/* Stop streaming as we've started it only to probe the sensor type. */
+ 	sd_stopN(gspca_dev);
+ 
+ 	if (force_sensor_type != -1) {

commit ed9885aa8145d0cd531ac53d1456a6b3d238150c
+Author: Theodore Kilgore 
+Date:   Thu Jan 14 12:07:18 2010 -0300
+
+    V4L/DVB (14006): gscpa_sq905c: Better detection of CIF resolution cameras
+    
+    gscpa_sq905c: Better detection of CIF resolution cameras
+    
+    Signed-off-by: Theodore Kilgore 
+    Signed-off-by: Hans de Goede 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/gspca/sq905c.c b/drivers/media/video/gspca/sq905c.c
+index d70b156872d6..bbfaf8361f65 100644
+--- a/drivers/media/video/gspca/sq905c.c
++++ b/drivers/media/video/gspca/sq905c.c
+@@ -47,6 +47,7 @@ MODULE_LICENSE("GPL");
+ 
+ /* Commands. These go in the "value" slot. */
+ #define SQ905C_CLEAR   0xa0		/* clear everything */
++#define SQ905C_GET_ID  0x14f4		/* Read version number */
+ #define SQ905C_CAPTURE_LOW 0xa040	/* Starts capture at 160x120 */
+ #define SQ905C_CAPTURE_MED 0x1440	/* Starts capture at 320x240 */
+ #define SQ905C_CAPTURE_HI 0x2840	/* Starts capture at 320x240 */
+@@ -101,6 +102,26 @@ static int sq905c_command(struct gspca_dev *gspca_dev, u16 command, u16 index)
+ 	return 0;
+ }
+ 
++static int sq905c_read(struct gspca_dev *gspca_dev, u16 command, u16 index,
++		       int size)
++{
++	int ret;
++
++	ret = usb_control_msg(gspca_dev->dev,
++			      usb_rcvctrlpipe(gspca_dev->dev, 0),
++			      USB_REQ_SYNCH_FRAME,		/* request */
++			      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
++			      command, index, gspca_dev->usb_buf, size,
++			      SQ905C_CMD_TIMEOUT);
++	if (ret < 0) {
++		PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)",
++		       __func__, ret);
++		return ret;
++	}
++
++	return 0;
++}
++
+ /* This function is called as a workqueue function and runs whenever the camera
+  * is streaming data. Because it is a workqueue function it is allowed to sleep
+  * so we can use synchronous USB calls. To avoid possible collisions with other
+@@ -183,13 +204,34 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ {
+ 	struct cam *cam = &gspca_dev->cam;
+ 	struct sd *dev = (struct sd *) gspca_dev;
++	int i, ret;
+ 
+ 	PDEBUG(D_PROBE,
+ 		"SQ9050 camera detected"
+ 		" (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
++
++	ret = sq905c_command(gspca_dev, SQ905C_GET_ID, 0);
++	if (ret < 0) {
++		PDEBUG(D_ERR, "Get version command failed");
++		return ret;
++	}
++
++	ret = sq905c_read(gspca_dev, 0xf5, 0, 20);
++	if (ret < 0) {
++		PDEBUG(D_ERR, "Reading version command failed");
++		return ret;
++	}
++	/* Note we leave out the usb id and the manufacturing date */
++	PDEBUG(D_PROBE,
++	       "SQ9050 ID string: %02x - %02x %02x %02x %02x %02x %02x",
++		gspca_dev->usb_buf[3],
++		gspca_dev->usb_buf[14], gspca_dev->usb_buf[15],
++		gspca_dev->usb_buf[16], gspca_dev->usb_buf[17],
++		gspca_dev->usb_buf[18], gspca_dev->usb_buf[19]);
++
+ 	cam->cam_mode = sq905c_mode;
+ 	cam->nmodes = 2;
+-	if (id->idProduct == 0x9050)
++	if (gspca_dev->usb_buf[15] == 0)
+ 		cam->nmodes = 1;
+ 	/* We don't use the buffer gspca allocates so make it small. */
+ 	cam->bulk_size = 32;

commit 9336960d075839b41bef89a0c68899c4025e8289
+Author: Theodore Kilgore 
+Date:   Fri Dec 25 05:19:24 2009 -0300
+
+    V4L/DVB (13993): gspca.txt: add cams supported by mr97310a, sq905(c) and sn9c2028 drivers
+    
+    gspca.txt: add cams supported by mr97310a, sq905(c) and sn9c2028 drivers
+    
+    Signed-off-by: Theodore Kilgore 
+    Signed-off-by: Hans de Goede 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt
+index c6364faa15af..9de9db03f9d5 100644
+--- a/Documentation/video4linux/gspca.txt
++++ b/Documentation/video4linux/gspca.txt
+@@ -42,6 +42,7 @@ ov519		041e:4064	Creative Live! VISTA VF0420
+ ov519		041e:4067	Creative Live! Cam Video IM (VF0350)
+ ov519		041e:4068	Creative Live! VISTA VF0470
+ spca561		0458:7004	Genius VideoCAM Express V2
++sn9c2028	0458:7005	Genius Smart 300, version 2
+ sunplus		0458:7006	Genius Dsc 1.3 Smart
+ zc3xx		0458:7007	Genius VideoCam V2
+ zc3xx		0458:700c	Genius VideoCam V3
+@@ -226,7 +227,8 @@ sunplus		08ca:2050	Medion MD 41437
+ sunplus		08ca:2060	Aiptek PocketDV5300
+ tv8532		0923:010f	ICM532 cams
+ mars		093a:050f	Mars-Semi Pc-Camera
+-mr97310a	093a:010f	Sakar Digital no. 77379
++mr97310a	093a:010e	All four known CIF cams with this ID
++mr97310a	093a:010f	All four known VGA cams with this ID
+ pac207		093a:2460	Qtec Webcam 100
+ pac207		093a:2461	HP Webcam
+ pac207		093a:2463	Philips SPC 220 NC
+@@ -326,6 +328,10 @@ sn9c20x		0c45:62b0	PC Camera (SN9C202 + MT9V011/MT9V111/MT9V112)
+ sn9c20x		0c45:62b3	PC Camera (SN9C202 + OV9655)
+ sn9c20x		0c45:62bb	PC Camera (SN9C202 + OV7660)
+ sn9c20x		0c45:62bc	PC Camera (SN9C202 + HV7131R)
++sn9c2028	0c45:8001	Wild Planet Digital Spy Camera
++sn9c2028	0c45:8003	Sakar #11199, #6637x, #67480 keychain cams
++sn9c2028	0c45:8008	Mini-Shotz ms-350
++sn9c2028	0c45:800a	Vivitar Vivicam 3350B
+ sunplus		0d64:0303	Sunplus FashionCam DXG
+ ov519		0e96:c001	TRUST 380 USB2 SPACEC@M
+ etoms		102c:6151	Qcam Sangha CIF
+@@ -343,10 +349,11 @@ spca501		1776:501c	Arowana 300K CMOS Camera
+ t613		17a1:0128	TASCORP JPEG Webcam, NGS Cyclops
+ vc032x		17ef:4802	Lenovo Vc0323+MI1310_SOC
+ pac207		2001:f115	D-Link DSB-C120
+-sq905c		2770:9050	sq905c
+-sq905c		2770:905c	DualCamera
+-sq905		2770:9120	Argus Digital Camera DC1512
+-sq905c		2770:913d	sq905c
++sq905c		2770:9050	Disney pix micro (CIF)
++sq905c		2770:9052	Disney pix micro 2 (VGA)
++sq905c		2770:905c	All 11 known cameras with this ID
++sq905		2770:9120	All 24 known cameras with this ID
++sq905c		2770:913d	All 4 known cameras with this ID
+ spca500		2899:012c	Toptro Industrial
+ ov519		8020:ef04	ov519
+ spca508		8086:0110	Intel Easy PC Camera

commit 5bdd00b93e368acc793748340c15cd2811fdd02b
+Author: Theodore Kilgore 
+Date:   Fri Dec 25 05:16:32 2009 -0300
+
+    V4L/DVB (13992): gspca_sn9c2028: New gspca subdriver
+    
+    New gspca subdriver adding support for SN9C2028 dual-mode cameras.
+    
+    Signed-off-by: Theodore Kilgore 
+    Signed-off-by: Hans de Goede 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig
+index 561bab0874ce..20b0f62fe77f 100644
+--- a/drivers/media/video/gspca/Kconfig
++++ b/drivers/media/video/gspca/Kconfig
+@@ -141,6 +141,16 @@ config USB_GSPCA_PAC7311
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called gspca_pac7311.
+ 
++config USB_GSPCA_SN9C2028
++	tristate "SONIX Dual-Mode USB Camera Driver"
++	depends on VIDEO_V4L2 && USB_GSPCA
++	help
++	  Say Y here if you want streaming support for Sonix SN9C2028 cameras.
++	  These are supported as stillcams in libgphoto2/camlibs/sonix.
++
++	  To compile this driver as a module, choose M here: the
++	  module will be called gspca_sn9c2028.
++
+ config USB_GSPCA_SN9C20X
+ 	tristate "SN9C20X USB Camera Driver"
+ 	depends on VIDEO_V4L2 && USB_GSPCA
+diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile
+index 553753d5c5ea..643722046749 100644
+--- a/drivers/media/video/gspca/Makefile
++++ b/drivers/media/video/gspca/Makefile
+@@ -12,6 +12,7 @@ obj-$(CONFIG_USB_GSPCA_OV534_9)  += gspca_ov534_9.o
+ obj-$(CONFIG_USB_GSPCA_PAC207)   += gspca_pac207.o
+ obj-$(CONFIG_USB_GSPCA_PAC7302)  += gspca_pac7302.o
+ obj-$(CONFIG_USB_GSPCA_PAC7311)  += gspca_pac7311.o
++obj-$(CONFIG_USB_GSPCA_SN9C2028) += gspca_sn9c2028.o
+ obj-$(CONFIG_USB_GSPCA_SN9C20X)  += gspca_sn9c20x.o
+ obj-$(CONFIG_USB_GSPCA_SONIXB)   += gspca_sonixb.o
+ obj-$(CONFIG_USB_GSPCA_SONIXJ)   += gspca_sonixj.o
+@@ -45,6 +46,7 @@ gspca_ov534_9-objs  := ov534_9.o
+ gspca_pac207-objs   := pac207.o
+ gspca_pac7302-objs  := pac7302.o
+ gspca_pac7311-objs  := pac7311.o
++gspca_sn9c2028-objs := sn9c2028.o
+ gspca_sn9c20x-objs  := sn9c20x.o
+ gspca_sonixb-objs   := sonixb.o
+ gspca_sonixj-objs   := sonixj.o
+diff --git a/drivers/media/video/gspca/sn9c2028.c b/drivers/media/video/gspca/sn9c2028.c
+new file mode 100644
+index 000000000000..dda5fd4aa69e
+--- /dev/null
++++ b/drivers/media/video/gspca/sn9c2028.c
+@@ -0,0 +1,757 @@
++/*
++ * SN9C2028 library
++ *
++ * Copyright (C) 2009 Theodore Kilgore 
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#define MODULE_NAME "sn9c2028"
++
++#include "gspca.h"
++
++MODULE_AUTHOR("Theodore Kilgore");
++MODULE_DESCRIPTION("Sonix SN9C2028 USB Camera Driver");
++MODULE_LICENSE("GPL");
++
++/* specific webcam descriptor */
++struct sd {
++	struct gspca_dev gspca_dev;  /* !! must be the first item */
++	u8 sof_read;
++	u16 model;
++};
++
++struct init_command {
++	unsigned char instruction[6];
++	unsigned char to_read; /* length to read. 0 means no reply requested */
++};
++
++/* V4L2 controls supported by the driver */
++static struct ctrl sd_ctrls[] = {
++};
++
++/* How to change the resolution of any of the VGA cams is unknown */
++static const struct v4l2_pix_format vga_mode[] = {
++	{640, 480, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE,
++		.bytesperline = 640,
++		.sizeimage = 640 * 480 * 3 / 4,
++		.colorspace = V4L2_COLORSPACE_SRGB,
++		.priv = 0},
++};
++
++/* No way to change the resolution of the CIF cams is known */
++static const struct v4l2_pix_format cif_mode[] = {
++	{352, 288, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE,
++		.bytesperline = 352,
++		.sizeimage = 352 * 288 * 3 / 4,
++		.colorspace = V4L2_COLORSPACE_SRGB,
++		.priv = 0},
++};
++
++/* the bytes to write are in gspca_dev->usb_buf */
++static int sn9c2028_command(struct gspca_dev *gspca_dev, u8 *command)
++{
++	int rc;
++
++	PDEBUG(D_USBO, "sending command %02x%02x%02x%02x%02x%02x", command[0],
++	       command[1], command[2], command[3], command[4], command[5]);
++
++	memcpy(gspca_dev->usb_buf, command, 6);
++	rc = usb_control_msg(gspca_dev->dev,
++			usb_sndctrlpipe(gspca_dev->dev, 0),
++			USB_REQ_GET_CONFIGURATION,
++			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
++			2, 0, gspca_dev->usb_buf, 6, 500);
++	if (rc < 0) {
++		PDEBUG(D_ERR, "command write [%02x] error %d",
++				gspca_dev->usb_buf[0], rc);
++		return rc;
++	}
++
++	return 0;
++}
++
++static int sn9c2028_read1(struct gspca_dev *gspca_dev)
++{
++	int rc;
++
++	rc = usb_control_msg(gspca_dev->dev,
++			usb_rcvctrlpipe(gspca_dev->dev, 0),
++			USB_REQ_GET_STATUS,
++			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
++			1, 0, gspca_dev->usb_buf, 1, 500);
++	if (rc != 1) {
++		PDEBUG(D_ERR, "read1 error %d", rc);
++		return (rc < 0) ? rc : -EIO;
++	}
++	PDEBUG(D_USBI, "read1 response %02x", gspca_dev->usb_buf[0]);
++	return gspca_dev->usb_buf[0];
++}
++
++static int sn9c2028_read4(struct gspca_dev *gspca_dev, u8 *reading)
++{
++	int rc;
++	rc = usb_control_msg(gspca_dev->dev,
++			usb_rcvctrlpipe(gspca_dev->dev, 0),
++			USB_REQ_GET_STATUS,
++			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
++			4, 0, gspca_dev->usb_buf, 4, 500);
++	if (rc != 4) {
++		PDEBUG(D_ERR, "read4 error %d", rc);
++		return (rc < 0) ? rc : -EIO;
++	}
++	memcpy(reading, gspca_dev->usb_buf, 4);
++	PDEBUG(D_USBI, "read4 response %02x%02x%02x%02x", reading[0],
++	       reading[1], reading[2], reading[3]);
++	return rc;
++}
++
++static int sn9c2028_long_command(struct gspca_dev *gspca_dev, u8 *command)
++{
++	int i, status;
++	__u8 reading[4];
++
++	status = sn9c2028_command(gspca_dev, command);
++	if (status < 0)
++		return status;
++
++	status = -1;
++	for (i = 0; i < 256 && status < 2; i++)
++		status = sn9c2028_read1(gspca_dev);
++	if (status != 2) {
++		PDEBUG(D_ERR, "long command status read error %d", status);
++		return (status < 0) ? status : -EIO;
++	}
++
++	memset(reading, 0, 4);
++	status = sn9c2028_read4(gspca_dev, reading);
++	if (status < 0)
++		return status;
++
++	/* in general, the first byte of the response is the first byte of
++	 * the command, or'ed with 8 */
++	status = sn9c2028_read1(gspca_dev);
++	if (status < 0)
++		return status;
++
++	return 0;
++}
++
++static int sn9c2028_short_command(struct gspca_dev *gspca_dev, u8 *command)
++{
++	int err_code;
++
++	err_code = sn9c2028_command(gspca_dev, command);
++	if (err_code < 0)
++		return err_code;
++
++	err_code = sn9c2028_read1(gspca_dev);
++	if (err_code < 0)
++		return err_code;
++
++	return 0;
++}
++
++/* this function is called at probe time */
++static int sd_config(struct gspca_dev *gspca_dev,
++		     const struct usb_device_id *id)
++{
++	struct sd *sd = (struct sd *) gspca_dev;
++	struct cam *cam = &gspca_dev->cam;
++
++	PDEBUG(D_PROBE, "SN9C2028 camera detected (vid/pid 0x%04X:0x%04X)",
++	       id->idVendor, id->idProduct);
++
++	sd->model = id->idProduct;
++
++	switch (sd->model) {
++	case 0x7005:
++		PDEBUG(D_PROBE, "Genius Smart 300 camera");
++		break;
++	case 0x8000:
++		PDEBUG(D_PROBE, "DC31VC");
++		break;
++	case 0x8001:
++		PDEBUG(D_PROBE, "Spy camera");
++		break;
++	case 0x8003:
++		PDEBUG(D_PROBE, "CIF camera");
++		break;
++	case 0x8008:
++		PDEBUG(D_PROBE, "Mini-Shotz ms-350 camera");
++		break;
++	case 0x800a:
++		PDEBUG(D_PROBE, "Vivitar 3350b type camera");
++		cam->input_flags = V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP;
++		break;
++	}
++
++	switch (sd->model) {
++	case 0x8000:
++	case 0x8001:
++	case 0x8003:
++		cam->cam_mode = cif_mode;
++		cam->nmodes = ARRAY_SIZE(cif_mode);
++		break;
++	default:
++		cam->cam_mode = vga_mode;
++		cam->nmodes = ARRAY_SIZE(vga_mode);
++	}
++	return 0;
++}
++
++/* this function is called at probe and resume time */
++static int sd_init(struct gspca_dev *gspca_dev)
++{
++	int status = -1;
++
++	sn9c2028_read1(gspca_dev);
++	sn9c2028_read1(gspca_dev);
++	status = sn9c2028_read1(gspca_dev);
++
++	return (status < 0) ? status : 0;
++}
++
++static int run_start_commands(struct gspca_dev *gspca_dev,
++			      struct init_command *cam_commands, int n)
++{
++	int i, err_code = -1;
++
++	for (i = 0; i < n; i++) {
++		switch (cam_commands[i].to_read) {
++		case 4:
++			err_code = sn9c2028_long_command(gspca_dev,
++					cam_commands[i].instruction);
++			break;
++		case 1:
++			err_code = sn9c2028_short_command(gspca_dev,
++					cam_commands[i].instruction);
++			break;
++		case 0:
++			err_code = sn9c2028_command(gspca_dev,
++					cam_commands[i].instruction);
++			break;
++		}
++		if (err_code < 0)
++			return err_code;
++	}
++	return 0;
++}
++
++static int start_spy_cam(struct gspca_dev *gspca_dev)
++{
++	struct init_command spy_start_commands[] = {
++		{{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4},
++		{{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4},
++		{{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, /* width  352 */
++		{{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, /* height 288 */
++		/* {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, */
++		{{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4},
++		{{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* red gain ?*/
++		/* {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, */
++		{{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4},
++		/* {{0x13, 0x29, 0x01, 0x0c, 0x00, 0x00}, 4}, */
++		{{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
++		/* {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, */
++		{{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
++		{{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4},
++		/* {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, */
++		{{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4},
++		{{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4},
++		{{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
++		{{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x02, 0x06, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x03, 0x13, 0x00, 0x00, 0x00}, 4}, /*don't mess with*/
++		/*{{0x11, 0x04, 0x06, 0x00, 0x00, 0x00}, 4}, observed */
++		{{0x11, 0x04, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */
++		/*{{0x11, 0x05, 0x65, 0x00, 0x00, 0x00}, 4}, observed */
++		{{0x11, 0x05, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */
++		{{0x11, 0x06, 0xb1, 0x00, 0x00, 0x00}, 4}, /* observed */
++		{{0x11, 0x07, 0x00, 0x00, 0x00, 0x00}, 4},
++		/*{{0x11, 0x08, 0x06, 0x00, 0x00, 0x00}, 4}, observed */
++		{{0x11, 0x08, 0x0b, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x09, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x0a, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x0c, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x0d, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x0e, 0x04, 0x00, 0x00, 0x00}, 4},
++		/* {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4}, */
++		/* brightness or gain. 0 is default. 4 is good
++		 * indoors at night with incandescent lighting */
++		{{0x11, 0x0f, 0x04, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x10, 0x06, 0x00, 0x00, 0x00}, 4}, /*hstart or hoffs*/
++		{{0x11, 0x11, 0x06, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x14, 0x02, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x13, 0x01, 0x00, 0x00, 0x00}, 4},
++		/* {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, observed */
++		{{0x1b, 0x02, 0x11, 0x00, 0x00, 0x00}, 1}, /* brighter */
++		/* {{0x1b, 0x13, 0x01, 0x00, 0x00, 0x00}, 1}, observed */
++		{{0x1b, 0x13, 0x11, 0x00, 0x00, 0x00}, 1},
++		{{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1}, /* compresses */
++		/* Camera should start to capture now. */
++	};
++
++	return run_start_commands(gspca_dev, spy_start_commands,
++				  ARRAY_SIZE(spy_start_commands));
++}
++
++static int start_cif_cam(struct gspca_dev *gspca_dev)
++{
++	struct init_command cif_start_commands[] = {
++		{{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
++		/* The entire sequence below seems redundant */
++		/* {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x22, 0x01, 0x06, 0x00, 0x00}, 4},
++		{{0x13, 0x23, 0x01, 0x02, 0x00, 0x00}, 4},
++		{{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, width?
++		{{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, height?
++		{{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample?
++		{{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4},
++		{{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
++		{{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
++		{{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
++		{{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
++		{{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
++		{{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},*/
++		{{0x1b, 0x21, 0x00, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x17, 0x00, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x19, 0x00, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x03, 0x5a, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x04, 0x27, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x05, 0x01, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x12, 0x14, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x14, 0x00, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x15, 0x00, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x16, 0x00, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x77, 0xa2, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x06, 0x0f, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x07, 0x14, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x08, 0x0f, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x09, 0x10, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x12, 0x07, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x10, 0x1f, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
++		{{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 1}, /* width/8 */
++		{{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 1}, /* height/8 */
++		/* {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample?
++		 * {{0x13, 0x28, 0x01, 0x1e, 0x00, 0x00}, 4}, does nothing
++		 * {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, */
++		/* {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4},
++		 * causes subsampling
++		 * but not a change in the resolution setting! */
++		{{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
++		{{0x13, 0x2d, 0x01, 0x01, 0x00, 0x00}, 4},
++		{{0x13, 0x2e, 0x01, 0x08, 0x00, 0x00}, 4},
++		{{0x13, 0x2f, 0x01, 0x06, 0x00, 0x00}, 4},
++		{{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x1b, 0x04, 0x6d, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x05, 0x03, 0x00, 0x00, 0x00}, 1},
++		{{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x0e, 0x01, 0x00, 0x00, 0x00}, 1},
++		{{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1},
++		{{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x10, 0x0f, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
++		{{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1},/* use compression */
++		/* Camera should start to capture now. */
++	};
++
++	return run_start_commands(gspca_dev, cif_start_commands,
++				  ARRAY_SIZE(cif_start_commands));
++}
++
++static int start_ms350_cam(struct gspca_dev *gspca_dev)
++{
++	struct init_command ms350_start_commands[] = {
++		{{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4},
++		{{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4},
++		{{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4},
++		{{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4},
++		{{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4},
++		{{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4},
++		{{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
++		{{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
++		{{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
++		{{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
++		{{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
++		{{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x00, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x01, 0x70, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x02, 0x05, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x03, 0x5d, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x04, 0x07, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x05, 0x25, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x06, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x07, 0x09, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x08, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x09, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x0c, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x0d, 0x0c, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x0e, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x11, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x13, 0x63, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x15, 0x70, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x18, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x11, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* width  */
++		{{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* height */
++		{{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* vstart? */
++		{{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4},
++		{{0x13, 0x29, 0x01, 0x40, 0x00, 0x00}, 4}, /* hstart? */
++		{{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
++		{{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
++		{{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
++		{{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
++		{{0x1b, 0x02, 0x05, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
++		{{0x20, 0x18, 0x00, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x02, 0x0a, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 0},
++		/* Camera should start to capture now. */
++	};
++
++	return run_start_commands(gspca_dev, ms350_start_commands,
++				  ARRAY_SIZE(ms350_start_commands));
++}
++
++static int start_genius_cam(struct gspca_dev *gspca_dev)
++{
++	struct init_command genius_start_commands[] = {
++		{{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4},
++		{{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4},
++		/* "preliminary" width and height settings */
++		{{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
++		{{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
++		{{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4},
++		{{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
++		{{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4},
++		{{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4},
++		{{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4},
++		{{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x25, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x26, 0x02, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x27, 0x88, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x30, 0x38, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x31, 0x2a, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x32, 0x2a, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x33, 0x2a, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x34, 0x02, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x5b, 0x0a, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* real width */
++		{{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* real height */
++		{{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
++		{{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
++		{{0x13, 0x29, 0x01, 0x62, 0x00, 0x00}, 4},
++		{{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
++		{{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
++		{{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
++		{{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
++		{{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x21, 0x2a, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x23, 0x28, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x11, 0x04, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x13, 0x03, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x15, 0xe0, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x16, 0x02, 0x00, 0x00, 0x00}, 4},
++		{{0x11, 0x17, 0x80, 0x00, 0x00, 0x00}, 4},
++		{{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1},
++		{{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1},
++		{{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 0}
++		/* Camera should start to capture now. */
++	};
++
++	return run_start_commands(gspca_dev, genius_start_commands,
++				  ARRAY_SIZE(genius_start_commands));
++}
++
++static int start_vivitar_cam(struct gspca_dev *gspca_dev)
++{
++	struct init_command vivitar_start_commands[] = {
++		{{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x22, 0x01, 0x01, 0x00, 0x00}, 4},
++		{{0x13, 0x23, 0x01, 0x01, 0x00, 0x00}, 4},
++		{{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4},
++		{{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4},
++		{{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
++		{{0x13, 0x28, 0x01, 0x0a, 0x00, 0x00}, 4},
++		/*
++		 * Above is changed from OEM 0x0b. Fixes Bayer tiling.
++		 * Presumably gives a vertical shift of one row.
++		 */
++		{{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4},
++		/* Above seems to do horizontal shift. */
++		{{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
++		{{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
++		{{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
++		{{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
++		/* Above three commands seem to relate to brightness. */
++		{{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
++		{{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x1b, 0x12, 0x80, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x01, 0x77, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x02, 0x3a, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x12, 0x78, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x14, 0x80, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x15, 0x34, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x1b, 0x04, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x20, 0x44, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x23, 0xee, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x26, 0xa0, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x27, 0x9a, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x28, 0xa0, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x29, 0x30, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x2a, 0x80, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x2b, 0x00, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x2f, 0x3d, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x30, 0x24, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x32, 0x86, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x60, 0xa9, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x61, 0x42, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x65, 0x00, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x69, 0x38, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x6f, 0x88, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x70, 0x0b, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x71, 0x00, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x74, 0x21, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x75, 0x86, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x76, 0x00, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x7d, 0xf3, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x17, 0x1c, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x18, 0xc0, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x19, 0x05, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x1a, 0xf6, 0x00, 0x00, 0x00}, 1},
++		/* {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4},
++		{{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4},
++		{{0x13, 0x28, 0x01, 0x0b, 0x00, 0x00}, 4}, */
++		{{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x10, 0x26, 0x00, 0x00, 0x00}, 1},
++		{{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x1b, 0x76, 0x03, 0x00, 0x00, 0x00}, 1},
++		{{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1},
++		{{0x1b, 0x00, 0x3f, 0x00, 0x00, 0x00}, 1},
++		/* Above is brightness; OEM driver setting is 0x10 */
++		{{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
++		{{0x20, 0x29, 0x30, 0x00, 0x00, 0x00}, 1},
++		{{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1}
++	};
++
++	return run_start_commands(gspca_dev, vivitar_start_commands,
++				  ARRAY_SIZE(vivitar_start_commands));
++}
++
++static int sd_start(struct gspca_dev *gspca_dev)
++{
++	struct sd *sd = (struct sd *) gspca_dev;
++	int err_code;
++
++	sd->sof_read = 0;
++
++	switch (sd->model) {
++	case 0x7005:
++		err_code = start_genius_cam(gspca_dev);
++		break;
++	case 0x8001:
++		err_code = start_spy_cam(gspca_dev);
++		break;
++	case 0x8003:
++		err_code = start_cif_cam(gspca_dev);
++		break;
++	case 0x8008:
++		err_code = start_ms350_cam(gspca_dev);
++		break;
++	case 0x800a:
++		err_code = start_vivitar_cam(gspca_dev);
++		break;
++	default:
++		PDEBUG(D_ERR, "Starting unknown camera, please report this");
++		return -ENXIO;
++	}
++
++	return err_code;
++}
++
++static void sd_stopN(struct gspca_dev *gspca_dev)
++{
++	int result;
++	__u8 data[6];
++
++	result = sn9c2028_read1(gspca_dev);
++	if (result < 0)
++		PDEBUG(D_ERR, "Camera Stop read failed");
++
++	memset(data, 0, 6);
++	data[0] = 0x14;
++	result = sn9c2028_command(gspca_dev, data);
++	if (result < 0)
++		PDEBUG(D_ERR, "Camera Stop command failed");
++}
++
++/* Include sn9c2028 sof detection functions */
++#include "sn9c2028.h"
++
++static void sd_pkt_scan(struct gspca_dev *gspca_dev,
++			__u8 *data,			/* isoc packet */
++			int len)			/* iso packet length */
++{
++	unsigned char *sof;
++
++	sof = sn9c2028_find_sof(gspca_dev, data, len);
++	if (sof) {
++		int n;
++
++		/* finish decoding current frame */
++		n = sof - data;
++		if (n > sizeof sn9c2028_sof_marker)
++			n -= sizeof sn9c2028_sof_marker;
++		else
++			n = 0;
++		gspca_frame_add(gspca_dev, LAST_PACKET, data, n);
++		/* Start next frame. */
++		gspca_frame_add(gspca_dev, FIRST_PACKET,
++			sn9c2028_sof_marker, sizeof sn9c2028_sof_marker);
++		len -= sof - data;
++		data = sof;
++	}
++	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
++}
++
++/* sub-driver description */
++static const struct sd_desc sd_desc = {
++	.name = MODULE_NAME,
++	.ctrls = sd_ctrls,
++	.nctrls = ARRAY_SIZE(sd_ctrls),
++	.config = sd_config,
++	.init = sd_init,
++	.start = sd_start,
++	.stopN = sd_stopN,
++	.pkt_scan = sd_pkt_scan,
++};
++
++/* -- module initialisation -- */
++static const __devinitdata struct usb_device_id device_table[] = {
++	{USB_DEVICE(0x0458, 0x7005)}, /* Genius Smart 300, version 2 */
++	/* The Genius Smart is untested. I can't find an owner ! */
++	/* {USB_DEVICE(0x0c45, 0x8000)}, DC31VC, Don't know this camera */
++	{USB_DEVICE(0x0c45, 0x8001)}, /* Wild Planet digital spy cam */
++	{USB_DEVICE(0x0c45, 0x8003)}, /* Several small CIF cameras */
++	/* {USB_DEVICE(0x0c45, 0x8006)}, Unknown VGA camera */
++	{USB_DEVICE(0x0c45, 0x8008)}, /* Mini-Shotz ms-350 */
++	{USB_DEVICE(0x0c45, 0x800a)}, /* Vivicam 3350B */
++	{}
++};
++MODULE_DEVICE_TABLE(usb, device_table);
++
++/* -- device connect -- */
++static int sd_probe(struct usb_interface *intf,
++			const struct usb_device_id *id)
++{
++	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
++			       THIS_MODULE);
++}
++
++static struct usb_driver sd_driver = {
++	.name = MODULE_NAME,
++	.id_table = device_table,
++	.probe = sd_probe,
++	.disconnect = gspca_disconnect,
++#ifdef CONFIG_PM
++	.suspend = gspca_suspend,
++	.resume = gspca_resume,
++#endif
++};
++
++/* -- module insert / remove -- */
++static int __init sd_mod_init(void)
++{
++	int ret;
++
++	ret = usb_register(&sd_driver);
++	if (ret < 0)
++		return ret;
++	PDEBUG(D_PROBE, "registered");
++	return 0;
++}
++
++static void __exit sd_mod_exit(void)
++{
++	usb_deregister(&sd_driver);
++	PDEBUG(D_PROBE, "deregistered");
++}
++
++module_init(sd_mod_init);
++module_exit(sd_mod_exit);
+diff --git a/drivers/media/video/gspca/sn9c2028.h b/drivers/media/video/gspca/sn9c2028.h
+new file mode 100644
+index 000000000000..8fd1d3e05665
+--- /dev/null
++++ b/drivers/media/video/gspca/sn9c2028.h
+@@ -0,0 +1,51 @@
++/*
++ * SN9C2028 common functions
++ *
++ * Copyright (C) 2009 Theodore Kilgore 
++ *
++ * Based closely upon the file gspca/pac_common.h
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *
++ */
++
++static const unsigned char sn9c2028_sof_marker[5] =
++	{ 0xff, 0xff, 0x00, 0xc4, 0xc4 };
++
++static unsigned char *sn9c2028_find_sof(struct gspca_dev *gspca_dev,
++					unsigned char *m, int len)
++{
++	struct sd *sd = (struct sd *) gspca_dev;
++	int i;
++
++	/* Search for the SOF marker (fixed part) in the header */
++	for (i = 0; i < len; i++) {
++		if (m[i] == sn9c2028_sof_marker[sd->sof_read]) {
++			sd->sof_read++;
++			if (sd->sof_read == sizeof(sn9c2028_sof_marker)) {
++				PDEBUG(D_FRAM,
++					"SOF found, bytes to analyze: %u."
++					" Frame starts at byte #%u",
++					len, i + 1);
++				sd->sof_read = 0;
++				return m + i + 1;
++			}
++		} else {
++			sd->sof_read = 0;
++		}
++	}
++
++	return NULL;
++}
+diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
+index d4962a782b8a..1b06360af38d 100644
+--- a/include/linux/videodev2.h
++++ b/include/linux/videodev2.h
+@@ -362,6 +362,7 @@ struct v4l2_pix_format {
+ #define V4L2_PIX_FMT_SPCA561  v4l2_fourcc('S', '5', '6', '1') /* compressed GBRG bayer */
+ #define V4L2_PIX_FMT_PAC207   v4l2_fourcc('P', '2', '0', '7') /* compressed BGGR bayer */
+ #define V4L2_PIX_FMT_MR97310A v4l2_fourcc('M', '3', '1', '0') /* compressed BGGR bayer */
++#define V4L2_PIX_FMT_SN9C2028 v4l2_fourcc('S', 'O', 'N', 'X') /* compressed GBRG bayer */
+ #define V4L2_PIX_FMT_SQ905C   v4l2_fourcc('9', '0', '5', 'C') /* compressed RGGB bayer */
+ #define V4L2_PIX_FMT_PJPG     v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */
+ #define V4L2_PIX_FMT_OV511    v4l2_fourcc('O', '5', '1', '1') /* ov511 JPEG */

commit 542821d8d064d04e898a3c473b742b4e512de09d
+Author: Theodore Kilgore 
+Date:   Sun Nov 1 13:09:15 2009 -0300
+
+    V4L/DVB (13267): gspca_mr97310a: Change brightness for VGA type 1 cameras downward
+    
+    gspca_mr97310a: Change brightness for VGA type 1 cameras downward
+    
+    Signed-off-by: Theodore Kilgore 
+    Signed-off-by: Hans de Goede 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c
+index d2bfdec1c907..442bf1ec5eda 100644
+--- a/drivers/media/video/gspca/mr97310a.c
++++ b/drivers/media/video/gspca/mr97310a.c
+@@ -780,8 +780,9 @@ static int start_vga_cam(struct gspca_dev *gspca_dev)
+ 
+ 		const struct sensor_w_data vga_sensor1_init_data[] = {
+ 			{0x11, 0x04, {0x01}, 1},
+-			/*{0x0a, 0x00, {0x00, 0x01, 0x00, 0x00, 0x01, */
+-			{0x0a, 0x00, {0x01, 0x06, 0x00, 0x00, 0x01,
++			{0x0a, 0x00, {0x00, 0x01, 0x00, 0x00, 0x01,
++			/* These settings may be better for some cameras */
++			/* {0x0a, 0x00, {0x01, 0x06, 0x00, 0x00, 0x01, */
+ 				0x00, 0x0a}, 7},
+ 			{0x11, 0x04, {0x01}, 1},
+ 			{0x12, 0x00, {0x00, 0x63, 0x00, 0x70, 0x00, 0x00}, 6},

commit b4b84deede5edb1e5492533a04f24ea16d1fae0a
+Author: Theodore Kilgore 
+Date:   Sun Nov 1 13:07:08 2009 -0300
+
+    V4L/DVB (13266): gspca_mr97310a: Fix / update some comments
+    
+    gspca_mr97310a: Fix / update some comments
+    
+    Signed-off-by: Theodore Kilgore 
+    Signed-off-by: Hans de Goede 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c
+index 57ea1c772214..d2bfdec1c907 100644
+--- a/drivers/media/video/gspca/mr97310a.c
++++ b/drivers/media/video/gspca/mr97310a.c
+@@ -814,9 +814,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
+ 
+ 	/* Some of the VGA cameras require the memory pointer
+ 	 * to be set to 0 again. We have been forced to start the
+-	 * stream somewhere else to detect the hardware, and closed it,
+-	 * and now since we are restarting the stream we need to do a
+-	 * completely fresh and clean start. */
++	 * stream in sd_config() to detect the hardware, and closed it.
++	 * Thus, we need here to do a completely fresh and clean start. */
+ 	err_code = zero_the_pointer(gspca_dev);
+ 	if (err_code < 0)
+ 		return err_code;
+@@ -875,7 +874,7 @@ static void setbrightness(struct gspca_dev *gspca_dev)
+ 		value_reg += 4;
+ 	}
+ 
+-	/* Note register 7 is also seen as 0x8x or 0xCx in dumps */
++	/* Note register 7 is also seen as 0x8x or 0xCx in some dumps */
+ 	if (sd->brightness > 0) {
+ 		sensor_write1(gspca_dev, sign_reg, 0x00);
+ 		val = sd->brightness;
+@@ -900,7 +899,7 @@ static void setexposure(struct gspca_dev *gspca_dev)
+ 		return;
+ 
+ 	if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) {
+-		/* This cam does not like exposure settings > 300,
++		/* This cam does not like exposure settings < 300,
+ 		   so scale 0 - 4095 to 300 - 4095 */
+ 		exposure = (sd->exposure * 9267) / 10000 + 300;
+ 		sensor_write1(gspca_dev, 3, exposure >> 4);
+@@ -908,7 +907,7 @@ static void setexposure(struct gspca_dev *gspca_dev)
+ 	} else {
+ 		/* We have both a clock divider and an exposure register.
+ 		   We first calculate the clock divider, as that determines
+-		   the maximum exposure and then we calculayte the exposure
++		   the maximum exposure and then we calculate the exposure
+ 		   register setting (which goes from 0 - 511).
+ 
+ 		   Note our 0 - 4095 exposure is mapped to 0 - 511

commit b31210d737f383c14a02b20ab68e1a5770818f2d
+Author: Theodore Kilgore 
+Date:   Sun Nov 1 13:02:59 2009 -0300
+
+    V4L/DVB (13265): gspca_mr97310a: Partly back off red gain change for Sakar Digital VGA camera
+    
+    gspca_mr97310a: Partly back off red gain change for Sakar Digital VGA camera
+    
+    Signed-off-by: Theodore Kilgore 
+    Signed-off-by: Hans de Goede 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c
+index a97061a9e44a..57ea1c772214 100644
+--- a/drivers/media/video/gspca/mr97310a.c
++++ b/drivers/media/video/gspca/mr97310a.c
+@@ -769,7 +769,7 @@ static int start_vga_cam(struct gspca_dev *gspca_dev)
+ 			{0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00,
+ 				/* adjusted blue, green, red gain correct
+ 				   too much blue from the Sakar Digital */
+-				0x05, 0x01, 0x05}, 8}
++				0x05, 0x01, 0x04}, 8}
+ 		};
+ 
+ 		const struct sensor_w_data color_no_adj[] = {

commit 64f4d9a367b4fe329ba78e3171d1abb1338a951f
+Author: Theodore Kilgore 
+Date:   Fri Oct 30 04:43:39 2009 -0300
+
+    V4L/DVB (13245): gspca_mr97310a: Change blue gain setting for Sakar Digital VGA camera
+    
+    gspca_mr97310a: Change blue gain setting for Sakar Digital VGA camera
+    
+    Signed-off-by: Theodore Kilgore 
+    Signed-off-by: Hans de Goede 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c
+index b66169256dc4..a97061a9e44a 100644
+--- a/drivers/media/video/gspca/mr97310a.c
++++ b/drivers/media/video/gspca/mr97310a.c
+@@ -78,6 +78,7 @@ struct sd {
+ 	u8 cam_type;	/* 0 is CIF and 1 is VGA */
+ 	u8 sensor_type;	/* We use 0 and 1 here, too. */
+ 	u8 do_lcd_stop;
++	u8 adj_colors;
+ 
+ 	int brightness;
+ 	u16 exposure;
+@@ -525,6 +526,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ 
+ 		sd->sensor_type = 1;
+ 		sd->do_lcd_stop = 0;
++		sd->adj_colors = 0;
+ 		if ((gspca_dev->usb_buf[0] != 0x03) &&
+ 					(gspca_dev->usb_buf[0] != 0x04)) {
+ 			PDEBUG(D_ERR, "Unknown VGA Sensor id Byte 0: %02x",
+@@ -532,6 +534,10 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ 			PDEBUG(D_ERR, "Defaults assumed, may not work");
+ 			PDEBUG(D_ERR, "Please report this");
+ 		}
++		/* Sakar Digital color needs to be adjusted. */
++		if ((gspca_dev->usb_buf[0] == 0x03) &&
++					(gspca_dev->usb_buf[1] == 0x50))
++			sd->adj_colors = 1;
+ 		if (gspca_dev->usb_buf[0] == 0x04) {
+ 			sd->do_lcd_stop = 1;
+ 			switch (gspca_dev->usb_buf[1]) {
+@@ -759,9 +765,20 @@ static int start_vga_cam(struct gspca_dev *gspca_dev)
+ 		err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data,
+ 					 ARRAY_SIZE(vga_sensor0_init_data));
+ 	} else {	/* sd->sensor_type = 1 */
+-		const struct sensor_w_data vga_sensor1_init_data[] = {
++		const struct sensor_w_data color_adj[] = {
++			{0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00,
++				/* adjusted blue, green, red gain correct
++				   too much blue from the Sakar Digital */
++				0x05, 0x01, 0x05}, 8}
++		};
++
++		const struct sensor_w_data color_no_adj[] = {
+ 			{0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00,
+-				0x07, 0x00, 0x01}, 8},
++				/* default blue, green, red gain settings */
++				0x07, 0x00, 0x01}, 8}
++		};
++
++		const struct sensor_w_data vga_sensor1_init_data[] = {
+ 			{0x11, 0x04, {0x01}, 1},
+ 			/*{0x0a, 0x00, {0x00, 0x01, 0x00, 0x00, 0x01, */
+ 			{0x0a, 0x00, {0x01, 0x06, 0x00, 0x00, 0x01,
+@@ -771,6 +788,17 @@ static int start_vga_cam(struct gspca_dev *gspca_dev)
+ 			{0x11, 0x04, {0x01}, 1},
+ 			{0, 0, {0}, 0}
+ 		};
++
++		if (sd->adj_colors)
++			err_code = sensor_write_regs(gspca_dev, color_adj,
++					 ARRAY_SIZE(color_adj));
++		else
++			err_code = sensor_write_regs(gspca_dev, color_no_adj,
++					 ARRAY_SIZE(color_no_adj));
++
++		if (err_code < 0)
++			return err_code;
++
+ 		err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data,
+ 					 ARRAY_SIZE(vga_sensor1_init_data));
+ 	}

commit 1160a3818ec387ddadfd173b3bceea654a474b74
+Author: Theodore Kilgore 
+Date:   Fri Oct 30 04:29:56 2009 -0300
+
+    V4L/DVB (13244): gspca_mr97310a: Fix / update some comments
+    
+    gspca_mr97310a: Fix / update some comments
+    
+    Signed-off-by: Theodore Kilgore 
+    Signed-off-by: Hans de Goede 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c
+index d316b56e396e..b66169256dc4 100644
+--- a/drivers/media/video/gspca/mr97310a.c
++++ b/drivers/media/video/gspca/mr97310a.c
+@@ -18,7 +18,9 @@
+  * Several previously unsupported cameras are owned and have been tested by
+  * Hans de Goede  and
+  * Thomas Kaiser  and
+- * Theodore Kilgore 
++ * Theodore Kilgore  and
++ * Edmond Rodriguez  and
++ * Aurelien Jacobs 
+  *
+  * The MR97311A support in gspca/mars.c has been helpful in understanding some
+  * of the registers in these cameras.
+@@ -105,8 +107,8 @@ static void setgain(struct gspca_dev *gspca_dev);
+ 
+ /* V4L2 controls supported by the driver */
+ static struct ctrl sd_ctrls[] = {
+-/* Seprate brightness control description for Argus QuickClix as it has
+-   different limits from to other mr97310a camera's */
++/* Separate brightness control description for Argus QuickClix as it has
++   different limits from the other mr97310a cameras */
+ 	{
+ #define NORM_BRIGHTNESS_IDX 0
+ 		{
+@@ -428,7 +430,7 @@ static int isoc_enable(struct gspca_dev *gspca_dev)
+ 	return mr_write(gspca_dev, 2);
+ }
+ 
+-/* this function is called at probe time */
++/* This function is called at probe time */
+ static int sd_config(struct gspca_dev *gspca_dev,
+ 		     const struct usb_device_id *id)
+ {
+@@ -441,11 +443,11 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ 	cam->nmodes = ARRAY_SIZE(vga_mode);
+ 	sd->do_lcd_stop = 0;
+ 
+-	/* Now, logical layout of the driver must fall sacrifice to the
+-	 * realities of the hardware supported. We have to sort out several
+-	 * cameras which share the USB ID but are in fact different inside.
+-	 * We need to start the initialization process for the cameras in
+-	 * order to classify them. Some of the supported cameras require the
++	/* Several of the supported CIF cameras share the same USB ID but
++	 * require different initializations and different control settings.
++	 * The same is true of the VGA cameras. Therefore, we are forced
++	 * to start the initialization process in order to determine which
++	 * camera is present. Some of the supported cameras require the
+ 	 * memory pointer to be set to 0 as the very first item of business
+ 	 * or else they will not stream. So we do that immediately.
+ 	 */
+@@ -464,9 +466,10 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ 		if (err_code < 0)
+ 			return err_code;
+ 		/*
+-		 * The various CIF cameras share the same USB ID but use
+-		 * different init routines and different controls. We need to
+-		 * detect which one is connected!
++		 * All but one of the known CIF cameras share the same USB ID,
++		 * but two different init routines are in use, and the control
++		 * settings are different, too. We need to detect which camera
++		 * of the two known varieties is connected!
+ 		 *
+ 		 * A list of known CIF cameras follows. They all report either
+ 		 * 0002 for type 0 or 0003 for type 1.
+@@ -481,6 +484,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ 		 * Vivitar Mini		1		T. Kilgore
+ 		 * Elta-Media 8212dc	1		T. Kaiser
+ 		 * Philips dig. keych.	1		T. Kilgore
++		 * Trust Spyc@m 100	1		A. Jacobs
+ 		 */
+ 		switch (gspca_dev->usb_buf[1]) {
+ 		case 2:

commit b3e440eef8a842736d63cc6a6594d80dfbb75fd9
+Author: Theodore Kilgore 
+Date:   Fri Oct 9 03:54:49 2009 -0300
+
+    V4L/DVB (13139): gspca_mr97310a: Improve VGA sensor type detection
+    
+    Improve (and also simplify :) gspca_mr97310a: VGA sensor type detection.
+    As it was still failing on some machines (not with some cams, but on
+    some machines interesting enough).
+    
+    Signed-off-by: Theodore Kilgore 
+    Signed-off-by: Hans de Goede 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c
+index f4c83b367900..abc56e37efcb 100644
+--- a/drivers/media/video/gspca/mr97310a.c
++++ b/drivers/media/video/gspca/mr97310a.c
+@@ -431,12 +431,13 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ 	if (err_code < 0)
+ 		return err_code;
+ 
++	err_code = stream_start(gspca_dev);
++	if (err_code < 0)
++		return err_code;
++
+ 	if (id->idProduct == 0x010e) {
+ 		sd->cam_type = CAM_TYPE_CIF;
+ 		cam->nmodes--;
+-		err_code = stream_start(gspca_dev);
+-		if (err_code < 0)
+-			return err_code;
+ 		err_code = cam_get_response16(gspca_dev, 0x06, 1);
+ 		if (err_code < 0)
+ 			return err_code;
+@@ -476,74 +477,52 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ 	} else {
+ 		sd->cam_type = CAM_TYPE_VGA;
+ 
+-		/*
+-		 * VGA cams also have two different sensor types. Detection
+-		 * requires a two-step process.
+-		 *
+-		 * Here is a report on the result of the first test for the
+-		 * known MR97310a VGA cameras. If you have another to report,
+-		 * please do.
+-		 *
+-		 * Name		byte just read			sd->sensor_type
+-		 *				sd->do_lcd_stop
+-		 * Aiptek Pencam VGA+	0x31		0	1
+-		 * ION digital		0x31		0	1
+-		 * Sakar Digital 77379	0x31		0	1
+-		 * Argus DC-1620	0x30		1	0
+-		 * Argus QuickClix	0x30		1	1 (see note)
+-		 * Note that this test fails to distinguish sd->sensor_type
+-		 * for the two cameras which have reported 0x30.
+-		 * Another test will be run on them.
+-		 * But the sd->do_lcd_stop setting is needed, too.
+-		 */
+-
+-		err_code = cam_get_response16(gspca_dev, 0x20, 1);
+-		if (err_code < 0)
+-			return err_code;
+-		sd->sensor_type = gspca_dev->usb_buf[0] & 1;
+-		sd->do_lcd_stop = (~gspca_dev->usb_buf[0]) & 1;
+-		err_code = stream_start(gspca_dev);
++		err_code = cam_get_response16(gspca_dev, 0x07, 1);
+ 		if (err_code < 0)
+ 			return err_code;
+ 
+ 		/*
+-		 * A second test can now resolve any remaining ambiguity in the
+-		 * identification of the camera's sensor type. Specifically,
+-		 * it now gives the correct sensor_type for the Argus DC-1620
+-		 * and the Argus QuickClix.
+-		 *
+-		 * This second test is only run if needed,
+-		 * but additional results from testing some other cameras
+-		 * are recorded here, too:
++		 * Here is a table of the responses to the previous command
++		 * from the known MR97310A VGA cameras.
+ 		 *
+ 		 * Name			gspca_dev->usb_buf[]	sd->sensor_type
++		 *				sd->do_lcd_stop
++		 * Aiptek Pencam VGA+	0300		0		1
++		 * ION digital		0350		0		1
++		 * Argus DC-1620	0450		1		0
++		 * Argus QuickClix	0420		1		1
+ 		 *
+-		 * Aiptek Pencam VGA+	0300	(test not needed)	1
+-		 * ION digital		0350	(test not needed)	1
+-		 * Argus DC-1620	0450	(remains as type 0)	0
+-		 * Argus QuickClix	0420	(corrected to type 1)	1
++		 * Based upon these results, we assume default settings
++		 * and then correct as necessary, as follows.
+ 		 *
+-		 * This test even seems able to distinguish one VGA cam from
+-		 * another which may be useful. However, the CIF type 1 cameras
+-		 * do not like it.
+ 		 */
+ 
+-		if (!sd->sensor_type) {
+-			err_code = cam_get_response16(gspca_dev, 0x07, 1);
+-			if (err_code < 0)
+-				return err_code;
+-
++		sd->sensor_type = 1;
++		sd->do_lcd_stop = 0;
++		if ((gspca_dev->usb_buf[0] != 0x03) &&
++					(gspca_dev->usb_buf[0] != 0x04)) {
++			PDEBUG(D_ERR, "Unknown VGA Sensor id Byte 0: %02x",
++					gspca_dev->usb_buf[1]);
++			PDEBUG(D_ERR, "Defaults assumed, may not work");
++			PDEBUG(D_ERR, "Please report this");
++		}
++		if (gspca_dev->usb_buf[0] == 0x04) {
++			sd->do_lcd_stop = 1;
+ 			switch (gspca_dev->usb_buf[1]) {
+ 			case 0x50:
++				sd->sensor_type = 0;
++				PDEBUG(D_PROBE, "sensor_type corrected to 0");
+ 				break;
+ 			case 0x20:
+-				sd->sensor_type = 1;
+-				PDEBUG(D_PROBE, "sensor_type corrected to 1");
++				/* Nothing to do here. */
+ 				break;
+ 			default:
+-				PDEBUG(D_ERR, "Unknown VGA Sensor id : %02x",
+-				       gspca_dev->usb_buf[1]);
+-				return -ENODEV;
++				PDEBUG(D_ERR,
++					"Unknown VGA Sensor id Byte 1: %02x",
++					gspca_dev->usb_buf[1]);
++				PDEBUG(D_ERR,
++					"Defaults assumed, may not work");
++				PDEBUG(D_ERR, "Please report this");
+ 			}
+ 		}
+ 		PDEBUG(D_PROBE, "MR97310A VGA camera detected, sensor: %d",

commit 930bf78c20187f3cbbf0775cd317616c6b681a8a
+Author: Theodore Kilgore 
+Date:   Mon Oct 5 05:11:35 2009 -0300
+
+    V4L/DVB (13137): gspca_mr97310a: Add controls for vga cams with sensor type 0
+    
+    This patch adds controls for vga cams with sensor type 0, in order to
+    correctly report the present controls, the probing of the sensor type
+    has been moved from sd_start to sd_config, since this made the sensor
+    type probing unreliable the detection method was changed.
+    
+    Note this requires the camera to enter streaming mode, so sd_config now
+    briefly makes the camera stream.
+    
+    Signed-off-by: Theodore Kilgore 
+    Signed-off-by: Hans de Goede 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c
+index f8328b9efae5..f4c83b367900 100644
+--- a/drivers/media/video/gspca/mr97310a.c
++++ b/drivers/media/video/gspca/mr97310a.c
+@@ -1,23 +1,28 @@
+ /*
+  * Mars MR97310A library
+  *
++ * The original mr97310a driver, which supported the Aiptek Pencam VGA+, is
+  * Copyright (C) 2009 Kyle Guinn 
+  *
+  * Support for the MR97310A cameras in addition to the Aiptek Pencam VGA+
+  * and for the routines for detecting and classifying these various cameras,
++ * is Copyright (C) 2009 Theodore Kilgore 
+  *
++ * Support for the control settings for the CIF cameras is
++ * Copyright (C) 2009 Hans de Goede  and
++ * Thomas Kaiser 
++ *
++ * Support for the control settings for the VGA cameras is
+  * Copyright (C) 2009 Theodore Kilgore 
+  *
+- * Acknowledgements:
++ * Several previously unsupported cameras are owned and have been tested by
++ * Hans de Goede  and
++ * Thomas Kaiser  and
++ * Theodore Kilgore 
+  *
+  * The MR97311A support in gspca/mars.c has been helpful in understanding some
+  * of the registers in these cameras.
+  *
+- * Hans de Goede  and
+- * Thomas Kaiser 
+- * have assisted with their experience. Each of them has also helped by
+- * testing a previously unsupported camera.
+- *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+  * the Free Software Foundation; either version 2 of the License, or
+@@ -40,11 +45,9 @@
+ #define CAM_TYPE_CIF			0
+ #define CAM_TYPE_VGA			1
+ 
+-#define MR97310A_BRIGHTNESS_MIN		-254
+-#define MR97310A_BRIGHTNESS_MAX		255
+ #define MR97310A_BRIGHTNESS_DEFAULT	0
+ 
+-#define MR97310A_EXPOSURE_MIN		300
++#define MR97310A_EXPOSURE_MIN		0
+ #define MR97310A_EXPOSURE_MAX		4095
+ #define MR97310A_EXPOSURE_DEFAULT	1000
+ 
+@@ -82,6 +85,7 @@ struct sensor_w_data {
+ 	int len;
+ };
+ 
++static void sd_stopN(struct gspca_dev *gspca_dev);
+ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
+ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
+ static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
+@@ -94,14 +98,16 @@ static void setgain(struct gspca_dev *gspca_dev);
+ 
+ /* V4L2 controls supported by the driver */
+ static struct ctrl sd_ctrls[] = {
++/* Seprate brightness control description for Argus QuickClix as it has
++   different limits from to other mr97310a camera's */
+ 	{
+-#define BRIGHTNESS_IDX 0
++#define NORM_BRIGHTNESS_IDX 0
+ 		{
+ 			.id = V4L2_CID_BRIGHTNESS,
+ 			.type = V4L2_CTRL_TYPE_INTEGER,
+ 			.name = "Brightness",
+-			.minimum = MR97310A_BRIGHTNESS_MIN,
+-			.maximum = MR97310A_BRIGHTNESS_MAX,
++			.minimum = -254,
++			.maximum = 255,
+ 			.step = 1,
+ 			.default_value = MR97310A_BRIGHTNESS_DEFAULT,
+ 			.flags = 0,
+@@ -110,7 +116,22 @@ static struct ctrl sd_ctrls[] = {
+ 		.get = sd_getbrightness,
+ 	},
+ 	{
+-#define EXPOSURE_IDX 1
++#define ARGUS_QC_BRIGHTNESS_IDX 1
++		{
++			.id = V4L2_CID_BRIGHTNESS,
++			.type = V4L2_CTRL_TYPE_INTEGER,
++			.name = "Brightness",
++			.minimum = 0,
++			.maximum = 15,
++			.step = 1,
++			.default_value = MR97310A_BRIGHTNESS_DEFAULT,
++			.flags = 0,
++		},
++		.set = sd_setbrightness,
++		.get = sd_getbrightness,
++	},
++	{
++#define EXPOSURE_IDX 2
+ 		{
+ 			.id = V4L2_CID_EXPOSURE,
+ 			.type = V4L2_CTRL_TYPE_INTEGER,
+@@ -125,7 +146,7 @@ static struct ctrl sd_ctrls[] = {
+ 		.get = sd_getexposure,
+ 	},
+ 	{
+-#define GAIN_IDX 2
++#define GAIN_IDX 3
+ 		{
+ 			.id = V4L2_CID_GAIN,
+ 			.type = V4L2_CTRL_TYPE_INTEGER,
+@@ -230,12 +251,17 @@ static int sensor_write1(struct gspca_dev *gspca_dev, u8 reg, u8 data)
+ 	int rc;
+ 
+ 	buf = data;
+-	rc = sensor_write_reg(gspca_dev, reg, 0x01, &buf, 1);
++	if (sd->cam_type == CAM_TYPE_CIF) {
++		rc = sensor_write_reg(gspca_dev, reg, 0x01, &buf, 1);
++		confirm_reg = sd->sensor_type ? 0x13 : 0x11;
++	} else {
++		rc = sensor_write_reg(gspca_dev, reg, 0x00, &buf, 1);
++		confirm_reg = 0x11;
++	}
+ 	if (rc < 0)
+ 		return rc;
+ 
+ 	buf = 0x01;
+-	confirm_reg = sd->sensor_type ? 0x13 : 0x11;
+ 	rc = sensor_write_reg(gspca_dev, confirm_reg, 0x00, &buf, 1);
+ 	if (rc < 0)
+ 		return rc;
+@@ -243,18 +269,26 @@ static int sensor_write1(struct gspca_dev *gspca_dev, u8 reg, u8 data)
+ 	return 0;
+ }
+ 
+-static int cam_get_response16(struct gspca_dev *gspca_dev)
++static int cam_get_response16(struct gspca_dev *gspca_dev, u8 reg, int verbose)
+ {
+-	__u8 *data = gspca_dev->usb_buf;
+ 	int err_code;
+ 
+-	data[0] = 0x21;
++	gspca_dev->usb_buf[0] = reg;
+ 	err_code = mr_write(gspca_dev, 1);
+ 	if (err_code < 0)
+ 		return err_code;
+ 
+ 	err_code = mr_read(gspca_dev, 16);
+-	return err_code;
++	if (err_code < 0)
++		return err_code;
++
++	if (verbose)
++		PDEBUG(D_PROBE, "Register: %02x reads %02x%02x%02x", reg,
++		       gspca_dev->usb_buf[0],
++		       gspca_dev->usb_buf[1],
++		       gspca_dev->usb_buf[2]);
++
++	return 0;
+ }
+ 
+ static int zero_the_pointer(struct gspca_dev *gspca_dev)
+@@ -264,7 +298,7 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev)
+ 	u8 status = 0;
+ 	int tries = 0;
+ 
+-	err_code = cam_get_response16(gspca_dev);
++	err_code = cam_get_response16(gspca_dev, 0x21, 0);
+ 	if (err_code < 0)
+ 		return err_code;
+ 
+@@ -275,7 +309,7 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev)
+ 	if (err_code < 0)
+ 		return err_code;
+ 
+-	err_code = cam_get_response16(gspca_dev);
++	err_code = cam_get_response16(gspca_dev, 0x21, 0);
+ 	if (err_code < 0)
+ 		return err_code;
+ 
+@@ -285,7 +319,7 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev)
+ 	if (err_code < 0)
+ 		return err_code;
+ 
+-	err_code = cam_get_response16(gspca_dev);
++	err_code = cam_get_response16(gspca_dev, 0x21, 0);
+ 	if (err_code < 0)
+ 		return err_code;
+ 
+@@ -295,7 +329,7 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev)
+ 	if (err_code < 0)
+ 		return err_code;
+ 
+-	err_code = cam_get_response16(gspca_dev);
++	err_code = cam_get_response16(gspca_dev, 0x21, 0);
+ 	if (err_code < 0)
+ 		return err_code;
+ 
+@@ -306,7 +340,7 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev)
+ 		return err_code;
+ 
+ 	while (status != 0x0a && tries < 256) {
+-		err_code = cam_get_response16(gspca_dev);
++		err_code = cam_get_response16(gspca_dev, 0x21, 0);
+ 		status = data[0];
+ 		tries++;
+ 		if (err_code < 0)
+@@ -323,7 +357,7 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev)
+ 		if (err_code < 0)
+ 			return err_code;
+ 
+-		err_code = cam_get_response16(gspca_dev);
++		err_code = cam_get_response16(gspca_dev, 0x21, 0);
+ 		status = data[0];
+ 		tries++;
+ 		if (err_code < 0)
+@@ -342,22 +376,34 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev)
+ 	return 0;
+ }
+ 
+-static u8 get_sensor_id(struct gspca_dev *gspca_dev)
++static int stream_start(struct gspca_dev *gspca_dev)
+ {
+-	int err_code;
+-
+-	gspca_dev->usb_buf[0] = 0x1e;
+-	err_code = mr_write(gspca_dev, 1);
+-	if (err_code < 0)
+-		return err_code;
++	gspca_dev->usb_buf[0] = 0x01;
++	gspca_dev->usb_buf[1] = 0x01;
++	return mr_write(gspca_dev, 2);
++}
+ 
+-	err_code = mr_read(gspca_dev, 16);
+-	if (err_code < 0)
+-		return err_code;
++static void stream_stop(struct gspca_dev *gspca_dev)
++{
++	gspca_dev->usb_buf[0] = 0x01;
++	gspca_dev->usb_buf[1] = 0x00;
++	if (mr_write(gspca_dev, 2) < 0)
++		PDEBUG(D_ERR, "Stream Stop failed");
++}
+ 
+-	PDEBUG(D_PROBE, "Byte zero reported is %01x", gspca_dev->usb_buf[0]);
++static void lcd_stop(struct gspca_dev *gspca_dev)
++{
++	gspca_dev->usb_buf[0] = 0x19;
++	gspca_dev->usb_buf[1] = 0x54;
++	if (mr_write(gspca_dev, 2) < 0)
++		PDEBUG(D_ERR, "LCD Stop failed");
++}
+ 
+-	return gspca_dev->usb_buf[0];
++static int isoc_enable(struct gspca_dev *gspca_dev)
++{
++	gspca_dev->usb_buf[0] = 0x00;
++	gspca_dev->usb_buf[1] = 0x4d;  /* ISOC transfering enable... */
++	return mr_write(gspca_dev, 2);
+ }
+ 
+ /* this function is called at probe time */
+@@ -366,60 +412,172 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ {
+ 	struct sd *sd = (struct sd *) gspca_dev;
+ 	struct cam *cam;
+-	__u8 *data = gspca_dev->usb_buf;
+ 	int err_code;
+ 
+ 	cam = &gspca_dev->cam;
+ 	cam->cam_mode = vga_mode;
+ 	cam->nmodes = ARRAY_SIZE(vga_mode);
++	sd->do_lcd_stop = 0;
++
++	/* Now, logical layout of the driver must fall sacrifice to the
++	 * realities of the hardware supported. We have to sort out several
++	 * cameras which share the USB ID but are in fact different inside.
++	 * We need to start the initialization process for the cameras in
++	 * order to classify them. Some of the supported cameras require the
++	 * memory pointer to be set to 0 as the very first item of business
++	 * or else they will not stream. So we do that immediately.
++	 */
++	err_code = zero_the_pointer(gspca_dev);
++	if (err_code < 0)
++		return err_code;
+ 
+ 	if (id->idProduct == 0x010e) {
+ 		sd->cam_type = CAM_TYPE_CIF;
+ 		cam->nmodes--;
+-
+-		data[0] = 0x01;
+-		data[1] = 0x01;
+-		err_code = mr_write(gspca_dev, 2);
++		err_code = stream_start(gspca_dev);
++		if (err_code < 0)
++			return err_code;
++		err_code = cam_get_response16(gspca_dev, 0x06, 1);
+ 		if (err_code < 0)
+ 			return err_code;
+-
+-		msleep(200);
+-		data[0] = get_sensor_id(gspca_dev);
+ 		/*
+-		 * Known CIF cameras. If you have another to report, please do
++		 * The various CIF cameras share the same USB ID but use
++		 * different init routines and different controls. We need to
++		 * detect which one is connected!
+ 		 *
+-		 * Name			byte just read		sd->sensor_type
+-		 *					reported by
+-		 * Sakar Spy-shot	0x28		T. Kilgore	0
+-		 * Innovage		0xf5 (unstable)	T. Kilgore	0
+-		 * Vivitar Mini		0x53		H. De Goede	0
+-		 * Vivitar Mini		0x04 / 0x24	E. Rodriguez	0
+-		 * Vivitar Mini		0x08		T. Kilgore	1
+-		 * Elta-Media 8212dc	0x23		T. Kaiser	1
+-		 * Philips dig. keych.	0x37		T. Kilgore	1
++		 * A list of known CIF cameras follows. They all report either
++		 * 0002 for type 0 or 0003 for type 1.
++		 * If you have another to report, please do
++		 *
++		 * Name		sd->sensor_type		reported by
++		 *
++		 * Sakar Spy-shot	0		T. Kilgore
++		 * Innovage		0		T. Kilgore
++		 * Vivitar Mini		0		H. De Goede
++		 * Vivitar Mini		0		E. Rodriguez
++		 * Vivitar Mini		1		T. Kilgore
++		 * Elta-Media 8212dc	1		T. Kaiser
++		 * Philips dig. keych.	1		T. Kilgore
+ 		 */
+-		if ((data[0] & 0x78) == 8 ||
+-		    ((data[0] & 0x2) == 0x2 && data[0] != 0x53))
+-			sd->sensor_type = 1;
+-		else
++		switch (gspca_dev->usb_buf[1]) {
++		case 2:
+ 			sd->sensor_type = 0;
+-
++			break;
++		case 3:
++			sd->sensor_type = 1;
++			break;
++		default:
++			PDEBUG(D_ERR, "Unknown CIF Sensor id : %02x",
++			       gspca_dev->usb_buf[1]);
++			return -ENODEV;
++		}
+ 		PDEBUG(D_PROBE, "MR97310A CIF camera detected, sensor: %d",
+ 		       sd->sensor_type);
++	} else {
++		sd->cam_type = CAM_TYPE_VGA;
+ 
+-		if (force_sensor_type != -1) {
+-			sd->sensor_type = !! force_sensor_type;
+-			PDEBUG(D_PROBE, "Forcing sensor type to: %d",
+-			       sd->sensor_type);
++		/*
++		 * VGA cams also have two different sensor types. Detection
++		 * requires a two-step process.
++		 *
++		 * Here is a report on the result of the first test for the
++		 * known MR97310a VGA cameras. If you have another to report,
++		 * please do.
++		 *
++		 * Name		byte just read			sd->sensor_type
++		 *				sd->do_lcd_stop
++		 * Aiptek Pencam VGA+	0x31		0	1
++		 * ION digital		0x31		0	1
++		 * Sakar Digital 77379	0x31		0	1
++		 * Argus DC-1620	0x30		1	0
++		 * Argus QuickClix	0x30		1	1 (see note)
++		 * Note that this test fails to distinguish sd->sensor_type
++		 * for the two cameras which have reported 0x30.
++		 * Another test will be run on them.
++		 * But the sd->do_lcd_stop setting is needed, too.
++		 */
++
++		err_code = cam_get_response16(gspca_dev, 0x20, 1);
++		if (err_code < 0)
++			return err_code;
++		sd->sensor_type = gspca_dev->usb_buf[0] & 1;
++		sd->do_lcd_stop = (~gspca_dev->usb_buf[0]) & 1;
++		err_code = stream_start(gspca_dev);
++		if (err_code < 0)
++			return err_code;
++
++		/*
++		 * A second test can now resolve any remaining ambiguity in the
++		 * identification of the camera's sensor type. Specifically,
++		 * it now gives the correct sensor_type for the Argus DC-1620
++		 * and the Argus QuickClix.
++		 *
++		 * This second test is only run if needed,
++		 * but additional results from testing some other cameras
++		 * are recorded here, too:
++		 *
++		 * Name			gspca_dev->usb_buf[]	sd->sensor_type
++		 *
++		 * Aiptek Pencam VGA+	0300	(test not needed)	1
++		 * ION digital		0350	(test not needed)	1
++		 * Argus DC-1620	0450	(remains as type 0)	0
++		 * Argus QuickClix	0420	(corrected to type 1)	1
++		 *
++		 * This test even seems able to distinguish one VGA cam from
++		 * another which may be useful. However, the CIF type 1 cameras
++		 * do not like it.
++		 */
++
++		if (!sd->sensor_type) {
++			err_code = cam_get_response16(gspca_dev, 0x07, 1);
++			if (err_code < 0)
++				return err_code;
++
++			switch (gspca_dev->usb_buf[1]) {
++			case 0x50:
++				break;
++			case 0x20:
++				sd->sensor_type = 1;
++				PDEBUG(D_PROBE, "sensor_type corrected to 1");
++				break;
++			default:
++				PDEBUG(D_ERR, "Unknown VGA Sensor id : %02x",
++				       gspca_dev->usb_buf[1]);
++				return -ENODEV;
++			}
+ 		}
++		PDEBUG(D_PROBE, "MR97310A VGA camera detected, sensor: %d",
++		       sd->sensor_type);
++	}
++	/* Stop streaming as we've started it to probe the sensor type. */
++	sd_stopN(gspca_dev);
+ 
++	if (force_sensor_type != -1) {
++		sd->sensor_type = !!force_sensor_type;
++		PDEBUG(D_PROBE, "Forcing sensor type to: %d",
++		       sd->sensor_type);
++	}
++
++	/* Setup controls depending on camera type */
++	if (sd->cam_type == CAM_TYPE_CIF) {
++		/* No brightness for sensor_type 0 */
+ 		if (sd->sensor_type == 0)
+-			gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX);
++			gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) |
++					      (1 << ARGUS_QC_BRIGHTNESS_IDX);
++		else
++			gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX);
+ 	} else {
+-		sd->cam_type = CAM_TYPE_VGA;
+-		PDEBUG(D_PROBE, "MR97310A VGA camera detected");
+-		gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX) |
+-				      (1 << EXPOSURE_IDX) | (1 << GAIN_IDX);
++		/* All controls need to be disabled if VGA sensor_type is 0 */
++		if (sd->sensor_type == 0)
++			gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) |
++					      (1 << ARGUS_QC_BRIGHTNESS_IDX) |
++					      (1 << EXPOSURE_IDX) |
++					      (1 << GAIN_IDX);
++		else if (sd->do_lcd_stop)
++			/* Argus QuickClix has different brightness limits */
++			gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX);
++		else
++			gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX);
+ 	}
+ 
+ 	sd->brightness = MR97310A_BRIGHTNESS_DEFAULT;
+@@ -455,11 +613,6 @@ static int start_cif_cam(struct gspca_dev *gspca_dev)
+ 	};
+ 
+ 	/* Note: Some of the above descriptions guessed from MR97113A driver */
+-	data[0] = 0x01;
+-	data[1] = 0x01;
+-	err_code = mr_write(gspca_dev, 2);
+-	if (err_code < 0)
+-		return err_code;
+ 
+ 	memcpy(data, startup_string, 11);
+ 	if (sd->sensor_type)
+@@ -533,22 +686,7 @@ static int start_cif_cam(struct gspca_dev *gspca_dev)
+ 		err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data,
+ 					 ARRAY_SIZE(cif_sensor1_init_data));
+ 	}
+-	if (err_code < 0)
+-		return err_code;
+-
+-	setbrightness(gspca_dev);
+-	setexposure(gspca_dev);
+-	setgain(gspca_dev);
+-
+-	msleep(200);
+-
+-	data[0] = 0x00;
+-	data[1] = 0x4d;  /* ISOC transfering enable... */
+-	err_code = mr_write(gspca_dev, 2);
+-	if (err_code < 0)
+-		return err_code;
+-
+-	return 0;
++	return err_code;
+ }
+ 
+ static int start_vga_cam(struct gspca_dev *gspca_dev)
+@@ -558,84 +696,8 @@ static int start_vga_cam(struct gspca_dev *gspca_dev)
+ 	int err_code;
+ 	const __u8 startup_string[] = {0x00, 0x0d, 0x01, 0x00, 0x00, 0x2b,
+ 				       0x00, 0x00, 0x00, 0x50, 0xc0};
+-
+ 	/* What some of these mean is explained in start_cif_cam(), above */
+-	sd->sof_read = 0;
+-
+-	/*
+-	 * We have to know which camera we have, because the register writes
+-	 * depend upon the camera. This test, run before we actually enter
+-	 * the initialization routine, distinguishes most of the cameras, If
+-	 * needed, another routine is done later, too.
+-	 */
+-	memset(data, 0, 16);
+-	data[0] = 0x20;
+-	err_code = mr_write(gspca_dev, 1);
+-	if (err_code < 0)
+-		return err_code;
+-
+-	err_code = mr_read(gspca_dev, 16);
+-	if (err_code < 0)
+-		return err_code;
+-
+-	PDEBUG(D_PROBE, "Byte reported is %02x", data[0]);
+-
+-	msleep(200);
+-	/*
+-	 * Known VGA cameras. If you have another to report, please do
+-	 *
+-	 * Name			byte just read		sd->sensor_type
+-	 *				sd->do_lcd_stop
+-	 * Aiptek Pencam VGA+	0x31		0	1
+-	 * ION digital		0x31		0	1
+-	 * Argus DC-1620	0x30		1	0
+-	 * Argus QuickClix	0x30		1	1 (not caught here)
+-	 */
+-	sd->sensor_type = data[0] & 1;
+-	sd->do_lcd_stop = (~data[0]) & 1;
+-
+-
+-
+-	/* Streaming setup begins here. */
+-
+-
+-	data[0] = 0x01;
+-	data[1] = 0x01;
+-	err_code = mr_write(gspca_dev, 2);
+-	if (err_code < 0)
+-		return err_code;
+-
+-	/*
+-	 * A second test can now resolve any remaining ambiguity in the
+-	 * identification of the camera type,
+-	 */
+-	if (!sd->sensor_type) {
+-		data[0] = get_sensor_id(gspca_dev);
+-		if (data[0] == 0x7f) {
+-			sd->sensor_type = 1;
+-			PDEBUG(D_PROBE, "sensor_type corrected to 1");
+-		}
+-		msleep(200);
+-	}
+-
+-	if (force_sensor_type != -1) {
+-		sd->sensor_type = !! force_sensor_type;
+-		PDEBUG(D_PROBE, "Forcing sensor type to: %d",
+-		       sd->sensor_type);
+-	}
+ 
+-	/*
+-	 * Known VGA cameras.
+-	 * This test is only run if the previous test returned 0x30, but
+-	 * here is the information for all others, too, just for reference.
+-	 *
+-	 * Name			byte just read		sd->sensor_type
+-	 *
+-	 * Aiptek Pencam VGA+	0xfb	(this test not run)	1
+-	 * ION digital		0xbd	(this test not run)	1
+-	 * Argus DC-1620	0xe5	(no change)		0
+-	 * Argus QuickClix	0x7f	(reclassified)		1
+-	 */
+ 	memcpy(data, startup_string, 11);
+ 	if (!sd->sensor_type) {
+ 		data[5]  = 0x00;
+@@ -704,14 +766,6 @@ static int start_vga_cam(struct gspca_dev *gspca_dev)
+ 		err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data,
+ 					 ARRAY_SIZE(vga_sensor1_init_data));
+ 	}
+-	if (err_code < 0)
+-		return err_code;
+-
+-	msleep(200);
+-	data[0] = 0x00;
+-	data[1] = 0x4d;  /* ISOC transfering enable... */
+-	err_code = mr_write(gspca_dev, 2);
+-
+ 	return err_code;
+ }
+ 
+@@ -719,82 +773,101 @@ static int sd_start(struct gspca_dev *gspca_dev)
+ {
+ 	struct sd *sd = (struct sd *) gspca_dev;
+ 	int err_code;
+-	struct cam *cam;
+ 
+-	cam = &gspca_dev->cam;
+ 	sd->sof_read = 0;
+-	/*
+-	 * Some of the supported cameras require the memory pointer to be
+-	 * set to 0, or else they will not stream.
+-	 */
+-	zero_the_pointer(gspca_dev);
+-	msleep(200);
++
++	/* Some of the VGA cameras require the memory pointer
++	 * to be set to 0 again. We have been forced to start the
++	 * stream somewhere else to detect the hardware, and closed it,
++	 * and now since we are restarting the stream we need to do a
++	 * completely fresh and clean start. */
++	err_code = zero_the_pointer(gspca_dev);
++	if (err_code < 0)
++		return err_code;
++
++	err_code = stream_start(gspca_dev);
++	if (err_code < 0)
++		return err_code;
++
+ 	if (sd->cam_type == CAM_TYPE_CIF) {
+ 		err_code = start_cif_cam(gspca_dev);
+ 	} else {
+ 		err_code = start_vga_cam(gspca_dev);
+ 	}
+-	return err_code;
++	if (err_code < 0)
++		return err_code;
++
++	setbrightness(gspca_dev);
++	setexposure(gspca_dev);
++	setgain(gspca_dev);
++
++	return isoc_enable(gspca_dev);
+ }
+ 
+ static void sd_stopN(struct gspca_dev *gspca_dev)
+ {
+ 	struct sd *sd = (struct sd *) gspca_dev;
+-	int result;
+-
+-	gspca_dev->usb_buf[0] = 1;
+-	gspca_dev->usb_buf[1] = 0;
+-	result = mr_write(gspca_dev, 2);
+-	if (result < 0)
+-		PDEBUG(D_ERR, "Camera Stop failed");
+ 
++	stream_stop(gspca_dev);
+ 	/* Not all the cams need this, but even if not, probably a good idea */
+ 	zero_the_pointer(gspca_dev);
+-	if (sd->do_lcd_stop) {
+-		gspca_dev->usb_buf[0] = 0x19;
+-		gspca_dev->usb_buf[1] = 0x54;
+-		result = mr_write(gspca_dev, 2);
+-		if (result < 0)
+-			PDEBUG(D_ERR, "Camera Stop failed");
+-	}
++	if (sd->do_lcd_stop)
++		lcd_stop(gspca_dev);
+ }
+ 
+ static void setbrightness(struct gspca_dev *gspca_dev)
+ {
+ 	struct sd *sd = (struct sd *) gspca_dev;
+ 	u8 val;
+-
+-	if (gspca_dev->ctrl_dis & (1 << BRIGHTNESS_IDX))
++	u8 sign_reg = 7;  /* This reg and the next one used on CIF cams. */
++	u8 value_reg = 8; /* VGA cams seem to use regs 0x0b and 0x0c */
++	const u8 quick_clix_table[] =
++	/*	  0  1  2   3  4  5  6  7  8  9  10  11  12  13  14  15 */
++		{ 0, 4, 8, 12, 1, 2, 3, 5, 6, 9,  7, 10, 13, 11, 14, 15};
++	/*
++	 * This control is disabled for CIF type 1 and VGA type 0 cameras.
++	 * It does not quite act linearly for the Argus QuickClix camera,
++	 * but it does control brightness. The values are 0 - 15 only, and
++	 * the table above makes them act consecutively.
++	 */
++	if ((gspca_dev->ctrl_dis & (1 << NORM_BRIGHTNESS_IDX)) &&
++	    (gspca_dev->ctrl_dis & (1 << ARGUS_QC_BRIGHTNESS_IDX)))
+ 		return;
+ 
++	if (sd->cam_type == CAM_TYPE_VGA) {
++		sign_reg += 4;
++		value_reg += 4;
++	}
++
+ 	/* Note register 7 is also seen as 0x8x or 0xCx in dumps */
+ 	if (sd->brightness > 0) {
+-		sensor_write1(gspca_dev, 7, 0x00);
++		sensor_write1(gspca_dev, sign_reg, 0x00);
+ 		val = sd->brightness;
+ 	} else {
+-		sensor_write1(gspca_dev, 7, 0x01);
+-		val = 257 - sd->brightness;
++		sensor_write1(gspca_dev, sign_reg, 0x01);
++		val = (257 - sd->brightness);
+ 	}
+-	sensor_write1(gspca_dev, 8, val);
++	/* Use lookup table for funky Argus QuickClix brightness */
++	if (sd->do_lcd_stop)
++		val = quick_clix_table[val];
++
++	sensor_write1(gspca_dev, value_reg, val);
+ }
+ 
+ static void setexposure(struct gspca_dev *gspca_dev)
+ {
+ 	struct sd *sd = (struct sd *) gspca_dev;
+-	u8 val;
++	int exposure;
+ 
+ 	if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX))
+ 		return;
+ 
+-	if (sd->sensor_type) {
+-		val = sd->exposure >> 4;
+-		sensor_write1(gspca_dev, 3, val);
+-		val = sd->exposure & 0xf;
+-		sensor_write1(gspca_dev, 4, val);
++	if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) {
++		/* This cam does not like very low exposure settings */
++		exposure = (sd->exposure < 300) ? 300 : sd->exposure;
++		sensor_write1(gspca_dev, 3, exposure >> 4);
++		sensor_write1(gspca_dev, 4, exposure & 0x0f);
+ 	} else {
+-		u8 clockdiv;
+-		int exposure;
+-
+ 		/* We have both a clock divider and an exposure register.
+ 		   We first calculate the clock divider, as that determines
+ 		   the maximum exposure and then we calculayte the exposure
+@@ -802,7 +875,7 @@ static void setexposure(struct gspca_dev *gspca_dev)
+ 
+ 		   Note our 0 - 4095 exposure is mapped to 0 - 511
+ 		   milliseconds exposure time */
+-		clockdiv = (60 * sd->exposure + 7999) / 8000;
++		u8 clockdiv = (60 * sd->exposure + 7999) / 8000;
+ 
+ 		/* Limit framerate to not exceed usb bandwidth */
+ 		if (clockdiv < 3 && gspca_dev->width >= 320)
+@@ -810,6 +883,9 @@ static void setexposure(struct gspca_dev *gspca_dev)
+ 		else if (clockdiv < 2)
+ 			clockdiv = 2;
+ 
++		if (sd->cam_type == CAM_TYPE_VGA && clockdiv < 4)
++			clockdiv = 4;
++
+ 		/* Frame exposure time in ms = 1000 * clockdiv / 60 ->
+ 		exposure = (sd->exposure / 8) * 511 / (1000 * clockdiv / 60) */
+ 		exposure = (60 * 511 * sd->exposure) / (8000 * clockdiv);
+@@ -832,7 +908,7 @@ static void setgain(struct gspca_dev *gspca_dev)
+ 	if (gspca_dev->ctrl_dis & (1 << GAIN_IDX))
+ 		return;
+ 
+-	if (sd->sensor_type) {
++	if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) {
+ 		sensor_write1(gspca_dev, 0x0e, sd->gain);
+ 	} else {
+ 		sensor_write1(gspca_dev, 0x10, sd->gain);

commit 32345b059676169444d8d3c4a59009adcdf93885
+Author: Theodore Kilgore 
+Date:   Sun Nov 1 12:59:42 2009 -0300
+
+    V4L/DVB (13264): gspca_mr97310a: Change vstart for CIF sensor type 1 cams
+    
+    gspca_mr97310a: Change vstart for CIF sensor type 1 cams
+    
+    This fixes the distortion at the end of the frame, and avoids the bad frame
+    dropping done because of this distortion, trippling the framerate!
+    
+    Signed-off-by: Theodore Kilgore 
+    Signed-off-by: Hans de Goede 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c
+index 140c8f320e47..f8328b9efae5 100644
+--- a/drivers/media/video/gspca/mr97310a.c
++++ b/drivers/media/video/gspca/mr97310a.c
+@@ -483,7 +483,7 @@ static int start_cif_cam(struct gspca_dev *gspca_dev)
+ 		data[3] = 0x2c;			   /* reg 2, H size/8 */
+ 		data[4] = 0x48;			   /* reg 3, V size/4 */
+ 		data[6] = 0x06;			   /* reg 5, H start  */
+-		data[8] = 0x06 + sd->sensor_type;  /* reg 7, V start  */
++		data[8] = 0x06 - sd->sensor_type;  /* reg 7, V start  */
+ 		break;
+ 	}
+ 	err_code = mr_write(gspca_dev, 11);

commit 70136081fc67ea77d849f86fa323e5773c8e40ea
+Author: Theodore Kilgore 
+Date:   Fri Dec 25 05:15:10 2009 -0300
+
+    V4L/DVB (13991): gspca_mr973010a: Fix cif type 1 cameras not streaming on UHCI controllers
+    
+    If you read the mail to Oliver Neukum on the linux-usb list, then you know
+    that I found a cure for the mysterious problem that the MR97310a CIF "type
+    1" cameras have been freezing up and refusing to stream if hooked up to a
+    machine with a UHCI controller.
+    
+    Namely, the cure is that if the camera is an mr97310a CIF type 1 camera, you
+    have to send it 0xa0, 0x00. Somehow, this is a timing reset command, or
+    such. It un-blocks whatever was previously stopping the CIF type 1 cameras
+    from working on the UHCI-based machines.
+    
+    Signed-off-by: Theodore Kilgore 
+    Signed-off-by: Hans de Goede 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c
+index a9178d9d6745..d842e8184426 100644
+--- a/drivers/media/video/gspca/mr97310a.c
++++ b/drivers/media/video/gspca/mr97310a.c
+@@ -697,6 +697,12 @@ static int start_cif_cam(struct gspca_dev *gspca_dev)
+ 			{0x13, 0x00, {0x01}, 1},
+ 			{0, 0, {0}, 0}
+ 		};
++		/* Without this command the cam won't work with USB-UHCI */
++		gspca_dev->usb_buf[0] = 0x0a;
++		gspca_dev->usb_buf[1] = 0x00;
++		err_code = mr_write(gspca_dev, 2);
++		if (err_code < 0)
++			return err_code;
+ 		err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data,
+ 					 ARRAY_SIZE(cif_sensor1_init_data));
+ 	}

commit 89f0863c4225aaed2763f526815c54a9e1b0f788
+Author: Theodore Kilgore 
+Date:   Fri Aug 14 06:51:52 2009 -0300
+
+    V4L/DVB (12618): gspca: mr97310a add support for CIF and more VGA camera's
+    
+    This patch adds supports for mr97310a camera's with CIF sensors (2 different
+    types) and for VGA mr97310a camera with a different sensor then supported
+    until now.
+    
+    This patch also add support for controls for one of the 2 CIF sensors, this
+    was written by Thomas Kaiser 
+    
+    Signed-off-by: Theodore Kilgore 
+    Signed-off-by: Thomas Kaiser 
+    Signed-off-by: Hans de Goede 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c
+index 30132513400c..3a3edf82a361 100644
+--- a/drivers/media/video/gspca/mr97310a.c
++++ b/drivers/media/video/gspca/mr97310a.c
+@@ -3,6 +3,21 @@
+  *
+  * Copyright (C) 2009 Kyle Guinn 
+  *
++ * Support for the MR97310A cameras in addition to the Aiptek Pencam VGA+
++ * and for the routines for detecting and classifying these various cameras,
++ *
++ * Copyright (C) 2009 Theodore Kilgore 
++ *
++ * Acknowledgements:
++ *
++ * The MR97311A support in gspca/mars.c has been helpful in understanding some
++ * of the registers in these cameras.
++ *
++ * Hans de Goede  and
++ * Thomas Kaiser 
++ * have assisted with their experience. Each of them has also helped by
++ * testing a previously unsupported camera.
++ *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+  * the Free Software Foundation; either version 2 of the License, or
+@@ -22,7 +37,23 @@
+ 
+ #include "gspca.h"
+ 
+-MODULE_AUTHOR("Kyle Guinn ");
++#define CAM_TYPE_CIF			0
++#define CAM_TYPE_VGA			1
++
++#define MR97310A_BRIGHTNESS_MIN		-254
++#define MR97310A_BRIGHTNESS_MAX		255
++#define MR97310A_BRIGHTNESS_DEFAULT	0
++
++#define MR97310A_EXPOSURE_MIN		300
++#define MR97310A_EXPOSURE_MAX		4095
++#define MR97310A_EXPOSURE_DEFAULT	1000
++
++#define MR97310A_GAIN_MIN		0
++#define MR97310A_GAIN_MAX		31
++#define MR97310A_GAIN_DEFAULT		25
++
++MODULE_AUTHOR("Kyle Guinn ,"
++	      "Theodore Kilgore ");
+ MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver");
+ MODULE_LICENSE("GPL");
+ 
+@@ -30,10 +61,75 @@ MODULE_LICENSE("GPL");
+ struct sd {
+ 	struct gspca_dev gspca_dev;  /* !! must be the first item */
+ 	u8 sof_read;
++	u8 cam_type;	/* 0 is CIF and 1 is VGA */
++	u8 sensor_type;	/* We use 0 and 1 here, too. */
++	u8 do_lcd_stop;
++	u8 regs[15];
++
++	int brightness;
++	u16 exposure;
++	u8 autogain;
++	u8 gain;
+ };
+ 
++struct sensor_w_data {
++	u8 reg;
++	u8 flags;
++	u8 data[16];
++	int len;
++};
++
++static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
++static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
++static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
++static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
++static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
++static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
++
+ /* V4L2 controls supported by the driver */
+ static struct ctrl sd_ctrls[] = {
++	{
++		{
++			.id = V4L2_CID_BRIGHTNESS,
++			.type = V4L2_CTRL_TYPE_INTEGER,
++			.name = "Brightness",
++			.minimum = MR97310A_BRIGHTNESS_MIN,
++			.maximum = MR97310A_BRIGHTNESS_MAX,
++			.step = 1,
++			.default_value = MR97310A_BRIGHTNESS_DEFAULT,
++			.flags = 0,
++		},
++		.set = sd_setbrightness,
++		.get = sd_getbrightness,
++	},
++	{
++		{
++			.id = V4L2_CID_EXPOSURE,
++			.type = V4L2_CTRL_TYPE_INTEGER,
++			.name = "Exposure",
++			.minimum = MR97310A_EXPOSURE_MIN,
++			.maximum = MR97310A_EXPOSURE_MAX,
++			.step = 1,
++			.default_value = MR97310A_EXPOSURE_DEFAULT,
++			.flags = 0,
++		},
++		.set = sd_setexposure,
++		.get = sd_getexposure,
++	},
++	{
++		{
++			.id = V4L2_CID_GAIN,
++			.type = V4L2_CTRL_TYPE_INTEGER,
++			.name = "Gain",
++			.minimum = MR97310A_GAIN_MIN,
++			.maximum = MR97310A_GAIN_MAX,
++			.step = 1,
++			.default_value = MR97310A_GAIN_DEFAULT,
++			.flags = 0,
++		},
++		.set = sd_setgain,
++		.get = sd_getgain,
++	},
+ };
+ 
+ static const struct v4l2_pix_format vga_mode[] = {
+@@ -65,7 +161,7 @@ static const struct v4l2_pix_format vga_mode[] = {
+ };
+ 
+ /* the bytes to write are in gspca_dev->usb_buf */
+-static int reg_w(struct gspca_dev *gspca_dev, int len)
++static int mr_write(struct gspca_dev *gspca_dev, int len)
+ {
+ 	int rc;
+ 
+@@ -78,15 +174,200 @@ static int reg_w(struct gspca_dev *gspca_dev, int len)
+ 	return rc;
+ }
+ 
++/* the bytes are read into gspca_dev->usb_buf */
++static int mr_read(struct gspca_dev *gspca_dev, int len)
++{
++	int rc;
++
++	rc = usb_bulk_msg(gspca_dev->dev,
++			  usb_rcvbulkpipe(gspca_dev->dev, 3),
++			  gspca_dev->usb_buf, len, NULL, 500);
++	if (rc < 0)
++		PDEBUG(D_ERR, "reg read [%02x] error %d",
++		       gspca_dev->usb_buf[0], rc);
++	return rc;
++}
++
++static int sensor_write_reg(struct gspca_dev *gspca_dev, u8 reg, u8 flags,
++	const u8 *data, int len)
++{
++	gspca_dev->usb_buf[0] = 0x1f;
++	gspca_dev->usb_buf[1] = flags;
++	gspca_dev->usb_buf[2] = reg;
++	memcpy(gspca_dev->usb_buf + 3, data, len);
++
++	return mr_write(gspca_dev, len + 3);
++}
++
++static int sensor_write_regs(struct gspca_dev *gspca_dev,
++	const struct sensor_w_data *data, int len)
++{
++	int i, rc;
++
++	for (i = 0; i < len; i++) {
++		rc = sensor_write_reg(gspca_dev, data[i].reg, data[i].flags,
++					  data[i].data, data[i].len);
++		if (rc < 0)
++			return rc;
++	}
++
++	return 0;
++}
++
++static int sensor_write1(struct gspca_dev *gspca_dev, u8 reg, u8 data)
++{
++	u8 buf;
++	int rc;
++
++	buf = data;
++	rc = sensor_write_reg(gspca_dev, reg, 0x01, &buf, 1);
++	if (rc < 0)
++		return rc;
++
++	buf = 0x01;
++	rc = sensor_write_reg(gspca_dev, 0x13, 0x00, &buf, 1);
++	if (rc < 0)
++		return rc;
++
++	return 0;
++}
++
++static int cam_get_response16(struct gspca_dev *gspca_dev)
++{
++	__u8 *data = gspca_dev->usb_buf;
++	int err_code;
++
++	data[0] = 0x21;
++	err_code = mr_write(gspca_dev, 1);
++	if (err_code < 0)
++		return err_code;
++
++	err_code = mr_read(gspca_dev, 16);
++	return err_code;
++}
++
++static int zero_the_pointer(struct gspca_dev *gspca_dev)
++{
++	__u8 *data = gspca_dev->usb_buf;
++	int err_code;
++	u8 status = 0;
++	int tries = 0;
++
++	err_code = cam_get_response16(gspca_dev);
++	if (err_code < 0)
++		return err_code;
++
++	err_code = mr_write(gspca_dev, 1);
++	data[0] = 0x19;
++	data[1] = 0x51;
++	err_code = mr_write(gspca_dev, 2);
++	if (err_code < 0)
++		return err_code;
++
++	err_code = cam_get_response16(gspca_dev);
++	if (err_code < 0)
++		return err_code;
++
++	data[0] = 0x19;
++	data[1] = 0xba;
++	err_code = mr_write(gspca_dev, 2);
++	if (err_code < 0)
++		return err_code;
++
++	err_code = cam_get_response16(gspca_dev);
++	if (err_code < 0)
++		return err_code;
++
++	data[0] = 0x19;
++	data[1] = 0x00;
++	err_code = mr_write(gspca_dev, 2);
++	if (err_code < 0)
++		return err_code;
++
++	err_code = cam_get_response16(gspca_dev);
++	if (err_code < 0)
++		return err_code;
++
++	data[0] = 0x19;
++	data[1] = 0x00;
++	err_code = mr_write(gspca_dev, 2);
++	if (err_code < 0)
++		return err_code;
++
++	while (status != 0x0a && tries < 256) {
++		err_code = cam_get_response16(gspca_dev);
++		status = data[0];
++		tries++;
++		if (err_code < 0)
++			return err_code;
++	}
++	PDEBUG(D_ERR, "status is %02x", status);
++
++	tries = 0;
++	while (tries < 4) {
++		data[0] = 0x19;
++		data[1] = 0x00;
++		err_code = mr_write(gspca_dev, 2);
++		if (err_code < 0)
++			return err_code;
++
++		err_code = cam_get_response16(gspca_dev);
++		status = data[0];
++		tries++;
++		if (err_code < 0)
++			return err_code;
++	}
++	PDEBUG(D_ERR, "Read 16 bytes from camera");
++
++	data[0] = 0x19;
++	err_code = mr_write(gspca_dev, 1);
++	if (err_code < 0)
++		return err_code;
++
++	err_code = mr_read(gspca_dev, 16);
++	if (err_code < 0)
++		return err_code;
++
++	return 0;
++}
++
++static u8 get_sensor_id(struct gspca_dev *gspca_dev)
++{
++	int err_code;
++
++	gspca_dev->usb_buf[0] = 0x1e;
++	err_code = mr_write(gspca_dev, 1);
++	if (err_code < 0)
++		return err_code;
++
++	err_code = mr_read(gspca_dev, 16);
++	if (err_code < 0)
++		return err_code;
++
++	PDEBUG(D_ERR, "Read 16 bytes from camera");
++	PDEBUG(D_ERR, "Byte zero reported is %01x", gspca_dev->usb_buf[0]);
++
++	return gspca_dev->usb_buf[0];
++}
++
+ /* this function is called at probe time */
+ static int sd_config(struct gspca_dev *gspca_dev,
+ 		     const struct usb_device_id *id)
+ {
++	struct sd *sd = (struct sd *) gspca_dev;
+ 	struct cam *cam;
+ 
+ 	cam = &gspca_dev->cam;
+ 	cam->cam_mode = vga_mode;
+ 	cam->nmodes = ARRAY_SIZE(vga_mode);
++	sd->cam_type = CAM_TYPE_VGA;
++	PDEBUG(D_PROBE,
++		"MR97310A camera detected"
++		" (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
++	if (id->idProduct == 0x010e) {
++		cam->nmodes--;
++		sd->cam_type = CAM_TYPE_CIF;
++	}
+ 	return 0;
+ }
+ 
+@@ -96,183 +377,468 @@ static int sd_init(struct gspca_dev *gspca_dev)
+ 	return 0;
+ }
+ 
+-static int sd_start(struct gspca_dev *gspca_dev)
++static int adjust_cif_sensor(struct gspca_dev *gspca_dev)
++{
++	/*
++	 * FIXME: The following sequence resets brightness, contrast, and
++	 * related  settings. Some of the values are adjustable, presumably
++	 * based upon what is detected in the frames. Here, only some
++	 * vaules are used which are compromises. When more is known about
++	 * what is done here, this needs to be moved out to presently
++	 * nonexistent functions which do controls. The same control messages
++	 * do work for all of the CIF cameras.
++	 */
++
++	const struct sensor_w_data  cif_sensor1_adjust_data[] = {
++		{0x02, 0x01, {0x10, 0x12, 0x0a}, 3},
++		/* Last or possibly two last bytes adjustable, above. */
++		{0x13, 0x04, {0x01}, 1}, /* seems to mean "write" */
++		{0x05, 0x01, {0x22, 0x00, 0x81, 0x06}, 4},
++		/* Last or possibly two last bytes adjustable, above. */
++		{0x13, 0x04, {0x01}, 1},
++		{0x09, 0x02, {0x05, 0x00, 0x00, 0x05, 0x07, 0x16}, 6},
++		/* Last or possibly two last bytes adjustable, above. */
++		{0x13, 0x04, {0x01}, 1},
++		{0, 0, {0}, 0}
++	};
++
++	return sensor_write_regs(gspca_dev, cif_sensor1_adjust_data,
++				 ARRAY_SIZE(cif_sensor1_adjust_data));
++}
++
++static int start_cif_cam(struct gspca_dev *gspca_dev)
+ {
+ 	struct sd *sd = (struct sd *) gspca_dev;
+ 	__u8 *data = gspca_dev->usb_buf;
+ 	int err_code;
+-
+-	sd->sof_read = 0;
+-
+-	/* Note:  register descriptions guessed from MR97113A driver */
+-
++	const __u8 startup_string[] = {
++		0x00,
++		0x0d,
++		0x01,
++		0x00, /* Hsize/8 for 352 or 320 */
++		0x00, /* Vsize/4 for 288 or 240 */
++		0x13, /* or 0xbb, depends on sensor */
++		0x00, /* Hstart, depends on res. */
++		0x00, /* reserved ? */
++		0x00, /* Vstart, depends on res. and sensor */
++		0x50, /* 0x54 to get 176 or 160 */
++		0xc0
++	};
++
++	/* Note: Some of the above descriptions guessed from MR97113A driver */
++	sd->sensor_type = 0;
+ 	data[0] = 0x01;
+ 	data[1] = 0x01;
+-	err_code = reg_w(gspca_dev, 2);
++	err_code = mr_write(gspca_dev, 2);
+ 	if (err_code < 0)
+ 		return err_code;
+ 
+-	data[0] = 0x00;
+-	data[1] = 0x0d;
+-	data[2] = 0x01;
+-	data[5] = 0x2b;
+-	data[7] = 0x00;
+-	data[9] = 0x50;  /* reg 8, no scale down */
+-	data[10] = 0xc0;
++	msleep(200);
++	data[0] = get_sensor_id(gspca_dev);
++	/*
++	 * Known CIF cameras. If you have another to report, please do
++	 *
++	 * Name			byte just read		sd->sensor_type
++	 *					reported by
++	 * Sakar Spy-shot	0x28		T. Kilgore	0
++	 * Innovage		0xf5 (unstable)	T. Kilgore	0
++	 * Vivitar Mini		0x53		H. De Goede	0
++	 * Vivitar Mini		0x08		T. Kilgore	1
++	 * Elta-Media 8212dc	0x23		T. Kaiser	1
++	 * Philips dig. keych.	0x37		T. Kilgore	1
++	 */
++	if ((data[0] & 0x78) == 8 || (data[0] & 0x2) == 0x2)
++		sd->sensor_type = 1;
++
++	PDEBUG(D_ERR, "Sensor type is %01x", sd->sensor_type);
++	memcpy(data, startup_string, 11);
++	if (sd->sensor_type)
++		data[5] = 0xbb;
+ 
+ 	switch (gspca_dev->width) {
+ 	case 160:
+-		data[9] |= 0x0c;  /* reg 8, 4:1 scale down */
++		data[9] |= 0x04;  /* reg 8, 2:1 scale down from 320 */
+ 		/* fall thru */
+ 	case 320:
+-		data[9] |= 0x04;  /* reg 8, 2:1 scale down */
+-		/* fall thru */
+-	case 640:
+ 	default:
+-		data[3] = 0x50;  /* reg 2, H size */
+-		data[4] = 0x78;  /* reg 3, V size */
+-		data[6] = 0x04;  /* reg 5, H start */
+-		data[8] = 0x03;  /* reg 7, V start */
++		data[3] = 0x28;			   /* reg 2, H size/8 */
++		data[4] = 0x3c;			   /* reg 3, V size/4 */
++		data[6] = 0x14;			   /* reg 5, H start  */
++		data[8] = 0x1a + sd->sensor_type;  /* reg 7, V start  */
+ 		break;
+-
+ 	case 176:
+-		data[9] |= 0x04;  /* reg 8, 2:1 scale down */
++		data[9] |= 0x04;  /* reg 8, 2:1 scale down from 352 */
+ 		/* fall thru */
+ 	case 352:
+-		data[3] = 0x2c;  /* reg 2, H size */
+-		data[4] = 0x48;  /* reg 3, V size */
+-		data[6] = 0x94;  /* reg 5, H start */
+-		data[8] = 0x63;  /* reg 7, V start */
++		data[3] = 0x2c;			   /* reg 2, H size/8 */
++		data[4] = 0x48;			   /* reg 3, V size/4 */
++		data[6] = 0x06;			   /* reg 5, H start  */
++		data[8] = 0x06 + sd->sensor_type;  /* reg 7, V start  */
+ 		break;
+ 	}
+-
+-	err_code = reg_w(gspca_dev, 11);
++	err_code = mr_write(gspca_dev, 11);
+ 	if (err_code < 0)
+ 		return err_code;
+ 
+-	data[0] = 0x0a;
+-	data[1] = 0x80;
+-	err_code = reg_w(gspca_dev, 2);
++	if (!sd->sensor_type) {
++		const struct sensor_w_data cif_sensor0_init_data[] = {
++			{0x02, 0x00, {0x03, 0x5a, 0xb5, 0x01,
++				      0x0f, 0x14, 0x0f, 0x10}, 8},
++			{0x0c, 0x00, {0x04, 0x01, 0x01, 0x00, 0x1f}, 5},
++			{0x12, 0x00, {0x07}, 1},
++			{0x1f, 0x00, {0x06}, 1},
++			{0x27, 0x00, {0x04}, 1},
++			{0x29, 0x00, {0x0c}, 1},
++			{0x40, 0x00, {0x40, 0x00, 0x04}, 3},
++			{0x50, 0x00, {0x60}, 1},
++			{0x60, 0x00, {0x06}, 1},
++			{0x6b, 0x00, {0x85, 0x85, 0xc8, 0xc8, 0xc8, 0xc8}, 6},
++			{0x72, 0x00, {0x1e, 0x56}, 2},
++			{0x75, 0x00, {0x58, 0x40, 0xa2, 0x02, 0x31, 0x02,
++				      0x31, 0x80, 0x00}, 9},
++			{0x11, 0x00, {0x01}, 1},
++			{0, 0, {0}, 0}
++		};
++		err_code = sensor_write_regs(gspca_dev, cif_sensor0_init_data,
++					 ARRAY_SIZE(cif_sensor0_init_data));
++	} else {	/* sd->sensor_type = 1 */
++		const struct sensor_w_data cif_sensor1_init_data[] = {
++			{0x02, 0x00, {0x10}, 1},
++			{0x03, 0x01, {0x12}, 1},
++			{0x04, 0x01, {0x05}, 1},
++			{0x05, 0x01, {0x65}, 1},
++			{0x06, 0x01, {0x32}, 1},
++			{0x07, 0x01, {0x00}, 1},
++			{0x08, 0x02, {0x06}, 1},
++			{0x09, 0x02, {0x0e}, 1},
++			{0x0a, 0x02, {0x05}, 1},
++			{0x0b, 0x02, {0x05}, 1},
++			{0x0c, 0x02, {0x0f}, 1},
++			{0x0d, 0x02, {0x00}, 1},
++			{0x0e, 0x02, {0x0c}, 1},
++			{0x0f, 0x00, {0x00}, 1},
++			{0x10, 0x00, {0x06}, 1},
++			{0x11, 0x00, {0x07}, 1},
++			{0x12, 0x00, {0x00}, 1},
++			{0x13, 0x00, {0x01}, 1},
++			{0, 0, {0}, 0}
++		};
++		err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data,
++					 ARRAY_SIZE(cif_sensor1_init_data));
++	}
+ 	if (err_code < 0)
+ 		return err_code;
+ 
+-	data[0] = 0x14;
+-	data[1] = 0x0a;
+-	err_code = reg_w(gspca_dev, 2);
++	msleep(200);
++	data[0] = 0x00;
++	data[1] = 0x4d;  /* ISOC transfering enable... */
++	err_code = mr_write(gspca_dev, 2);
+ 	if (err_code < 0)
+ 		return err_code;
+ 
+-	data[0] = 0x1b;
+-	data[1] = 0x00;
+-	err_code = reg_w(gspca_dev, 2);
++	msleep(200);
++	err_code = adjust_cif_sensor(gspca_dev);
+ 	if (err_code < 0)
+ 		return err_code;
+ 
+-	data[0] = 0x15;
+-	data[1] = 0x16;
+-	err_code = reg_w(gspca_dev, 2);
+-	if (err_code < 0)
+-		return err_code;
++	msleep(200);
++	return 0;
++}
+ 
+-	data[0] = 0x16;
+-	data[1] = 0x10;
+-	err_code = reg_w(gspca_dev, 2);
+-	if (err_code < 0)
+-		return err_code;
++static int start_vga_cam(struct gspca_dev *gspca_dev)
++{
++	struct sd *sd = (struct sd *) gspca_dev;
++	__u8 *data = gspca_dev->usb_buf;
++	int err_code;
++	const __u8 startup_string[] = {0x00, 0x0d, 0x01, 0x00, 0x00, 0x2b,
++				       0x00, 0x00, 0x00, 0x50, 0xc0};
+ 
+-	data[0] = 0x17;
+-	data[1] = 0x3a;
+-	err_code = reg_w(gspca_dev, 2);
+-	if (err_code < 0)
+-		return err_code;
++	/* What some of these mean is explained in start_cif_cam(), above */
++	sd->sof_read = 0;
+ 
+-	data[0] = 0x18;
+-	data[1] = 0x68;
+-	err_code = reg_w(gspca_dev, 2);
++	/*
++	 * We have to know which camera we have, because the register writes
++	 * depend upon the camera. This test, run before we actually enter
++	 * the initialization routine, distinguishes most of the cameras, If
++	 * needed, another routine is done later, too.
++	 */
++	memset(data, 0, 16);
++	data[0] = 0x20;
++	err_code = mr_write(gspca_dev, 1);
+ 	if (err_code < 0)
+ 		return err_code;
+ 
+-	data[0] = 0x1f;
+-	data[1] = 0x00;
+-	data[2] = 0x02;
+-	data[3] = 0x06;
+-	data[4] = 0x59;
+-	data[5] = 0x0c;
+-	data[6] = 0x16;
+-	data[7] = 0x00;
+-	data[8] = 0x07;
+-	data[9] = 0x00;
+-	data[10] = 0x01;
+-	err_code = reg_w(gspca_dev, 11);
++	err_code = mr_read(gspca_dev, 16);
+ 	if (err_code < 0)
+ 		return err_code;
+ 
+-	data[0] = 0x1f;
+-	data[1] = 0x04;
+-	data[2] = 0x11;
+-	data[3] = 0x01;
+-	err_code = reg_w(gspca_dev, 4);
+-	if (err_code < 0)
+-		return err_code;
++	PDEBUG(D_ERR, "Read 16 bytes from camera");
++	PDEBUG(D_ERR, "Byte reported is %02x", data[0]);
+ 
+-	data[0] = 0x1f;
+-	data[1] = 0x00;
+-	data[2] = 0x0a;
+-	data[3] = 0x00;
+-	data[4] = 0x01;
+-	data[5] = 0x00;
+-	data[6] = 0x00;
+-	data[7] = 0x01;
+-	data[8] = 0x00;
+-	data[9] = 0x0a;
+-	err_code = reg_w(gspca_dev, 10);
+-	if (err_code < 0)
+-		return err_code;
++	msleep(200);
++	/*
++	 * Known VGA cameras. If you have another to report, please do
++	 *
++	 * Name			byte just read		sd->sensor_type
++	 *				sd->do_lcd_stop
++	 * Aiptek Pencam VGA+	0x31		0	1
++	 * ION digital		0x31		0	1
++	 * Argus DC-1620	0x30		1	0
++	 * Argus QuickClix	0x30		1	1 (not caught here)
++	 */
++	sd->sensor_type = data[0] & 1;
++	sd->do_lcd_stop = (~data[0]) & 1;
+ 
+-	data[0] = 0x1f;
+-	data[1] = 0x04;
+-	data[2] = 0x11;
+-	data[3] = 0x01;
+-	err_code = reg_w(gspca_dev, 4);
++
++
++	/* Streaming setup begins here. */
++
++
++	data[0] = 0x01;
++	data[1] = 0x01;
++	err_code = mr_write(gspca_dev, 2);
+ 	if (err_code < 0)
+ 		return err_code;
+ 
+-	data[0] = 0x1f;
+-	data[1] = 0x00;
+-	data[2] = 0x12;
+-	data[3] = 0x00;
+-	data[4] = 0x63;
+-	data[5] = 0x00;
+-	data[6] = 0x70;
+-	data[7] = 0x00;
+-	data[8] = 0x00;
+-	err_code = reg_w(gspca_dev, 9);
++	/*
++	 * A second test can now resolve any remaining ambiguity in the
++	 * identification of the camera type,
++	 */
++	if (!sd->sensor_type) {
++		data[0] = get_sensor_id(gspca_dev);
++		if (data[0] == 0x7f) {
++			sd->sensor_type = 1;
++			PDEBUG(D_ERR, "sensor_type corrected to 1");
++		}
++		msleep(200);
++	}
++
++	/*
++	 * Known VGA cameras.
++	 * This test is only run if the previous test returned 0x30, but
++	 * here is the information for all others, too, just for reference.
++	 *
++	 * Name			byte just read		sd->sensor_type
++	 *
++	 * Aiptek Pencam VGA+	0xfb	(this test not run)	1
++	 * ION digital		0xbd	(this test not run)	1
++	 * Argus DC-1620	0xe5	(no change)		0
++	 * Argus QuickClix	0x7f	(reclassified)		1
++	 */
++	memcpy(data, startup_string, 11);
++	if (!sd->sensor_type) {
++		data[5]  = 0x00;
++		data[10] = 0x91;
++	}
++
++	switch (gspca_dev->width) {
++	case 160:
++		data[9] |= 0x0c;  /* reg 8, 4:1 scale down */
++		/* fall thru */
++	case 320:
++		data[9] |= 0x04;  /* reg 8, 2:1 scale down */
++		/* fall thru */
++	case 640:
++	default:
++		data[3] = 0x50;  /* reg 2, H size/8 */
++		data[4] = 0x78;  /* reg 3, V size/4 */
++		data[6] = 0x04;  /* reg 5, H start */
++		data[8] = 0x03;  /* reg 7, V start */
++		if (sd->do_lcd_stop)
++			data[8] = 0x04;  /* Bayer tile shifted */
++		break;
++
++	case 176:
++		data[9] |= 0x04;  /* reg 8, 2:1 scale down */
++		/* fall thru */
++	case 352:
++		data[3] = 0x2c;  /* reg 2, H size */
++		data[4] = 0x48;  /* reg 3, V size */
++		data[6] = 0x94;  /* reg 5, H start */
++		data[8] = 0x63;  /* reg 7, V start */
++		if (sd->do_lcd_stop)
++			data[8] = 0x64;  /* Bayer tile shifted */
++		break;
++	}
++
++	err_code = mr_write(gspca_dev, 11);
+ 	if (err_code < 0)
+ 		return err_code;
+ 
+-	data[0] = 0x1f;
+-	data[1] = 0x04;
+-	data[2] = 0x11;
+-	data[3] = 0x01;
+-	err_code = reg_w(gspca_dev, 4);
++	if (!sd->sensor_type) {
++		/* The only known sensor_type 0 cam is the Argus DC-1620 */
++		const struct sensor_w_data vga_sensor0_init_data[] = {
++			{0x01, 0x00, {0x0c, 0x00, 0x04}, 3},
++			{0x14, 0x00, {0x01, 0xe4, 0x02, 0x84}, 4},
++			{0x20, 0x00, {0x00, 0x80, 0x00, 0x08}, 4},
++			{0x25, 0x00, {0x03, 0xa9, 0x80}, 3},
++			{0x30, 0x00, {0x30, 0x18, 0x10, 0x18}, 4},
++			{0, 0, {0}, 0}
++		};
++		err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data,
++					 ARRAY_SIZE(vga_sensor0_init_data));
++	} else {	/* sd->sensor_type = 1 */
++		const struct sensor_w_data vga_sensor1_init_data[] = {
++			{0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00,
++				0x07, 0x00, 0x01}, 8},
++			{0x11, 0x04, {0x01}, 1},
++			/*{0x0a, 0x00, {0x00, 0x01, 0x00, 0x00, 0x01, */
++			{0x0a, 0x00, {0x01, 0x06, 0x00, 0x00, 0x01,
++				0x00, 0x0a}, 7},
++			{0x11, 0x04, {0x01}, 1},
++			{0x12, 0x00, {0x00, 0x63, 0x00, 0x70, 0x00, 0x00}, 6},
++			{0x11, 0x04, {0x01}, 1},
++			{0, 0, {0}, 0}
++		};
++		err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data,
++					 ARRAY_SIZE(vga_sensor1_init_data));
++	}
+ 	if (err_code < 0)
+ 		return err_code;
+ 
++	msleep(200);
+ 	data[0] = 0x00;
+ 	data[1] = 0x4d;  /* ISOC transfering enable... */
+-	err_code = reg_w(gspca_dev, 2);
++	err_code = mr_write(gspca_dev, 2);
++
++	return err_code;
++}
++
++static int sd_start(struct gspca_dev *gspca_dev)
++{
++	struct sd *sd = (struct sd *) gspca_dev;
++	int err_code;
++	struct cam *cam;
++
++	/* TEST TEST */
++	int i;
++	for (i = 2; i <= 14; i++)
++		sd->regs[i] = sd_ctrls[i - 2].qctrl.default_value;
++
++	cam = &gspca_dev->cam;
++	sd->sof_read = 0;
++	/*
++	 * Some of the supported cameras require the memory pointer to be
++	 * set to 0, or else they will not stream.
++	 */
++	zero_the_pointer(gspca_dev);
++	msleep(200);
++	if (sd->cam_type == CAM_TYPE_CIF) {
++		PDEBUG(D_ERR, "CIF camera");
++		err_code = start_cif_cam(gspca_dev);
++	} else {
++		PDEBUG(D_ERR, "VGA camera");
++		err_code = start_vga_cam(gspca_dev);
++	}
+ 	return err_code;
+ }
+ 
+ static void sd_stopN(struct gspca_dev *gspca_dev)
+ {
++	struct sd *sd = (struct sd *) gspca_dev;
+ 	int result;
+ 
+ 	gspca_dev->usb_buf[0] = 1;
+ 	gspca_dev->usb_buf[1] = 0;
+-	result = reg_w(gspca_dev, 2);
++	result = mr_write(gspca_dev, 2);
+ 	if (result < 0)
+ 		PDEBUG(D_ERR, "Camera Stop failed");
++
++	/* Not all the cams need this, but even if not, probably a good idea */
++	zero_the_pointer(gspca_dev);
++	if (sd->do_lcd_stop) {
++		gspca_dev->usb_buf[0] = 0x19;
++		gspca_dev->usb_buf[1] = 0x54;
++		result = mr_write(gspca_dev, 2);
++		if (result < 0)
++			PDEBUG(D_ERR, "Camera Stop failed");
++	}
++}
++
++static void setbrightness(struct gspca_dev *gspca_dev)
++{
++	struct sd *sd = (struct sd *) gspca_dev;
++	u8 val;
++	if (sd->brightness > 0) {
++		sensor_write1(gspca_dev, 7, 0);
++		val = sd->brightness;
++	} else {
++		sensor_write1(gspca_dev, 7, 1);
++		val = 257 - sd->brightness;
++	}
++	sensor_write1(gspca_dev, 8, val);
++}
++
++static void setexposure(struct gspca_dev *gspca_dev)
++{
++	struct sd *sd = (struct sd *) gspca_dev;
++	u8 val;
++
++	val = sd->exposure >> 4;
++	sensor_write1(gspca_dev, 3, val);
++	val = sd->exposure & 0xf;
++	sensor_write1(gspca_dev, 4, val);
++}
++
++static void setgain(struct gspca_dev *gspca_dev)
++{
++	struct sd *sd = (struct sd *) gspca_dev;
++
++	sensor_write1(gspca_dev, 3, sd->gain);
++}
++
++static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
++{
++	struct sd *sd = (struct sd *) gspca_dev;
++
++	sd->brightness = val;
++	if (gspca_dev->streaming)
++		setbrightness(gspca_dev);
++	return 0;
++}
++
++static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
++{
++	struct sd *sd = (struct sd *) gspca_dev;
++
++	*val = sd->brightness;
++	return 0;
++}
++
++static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
++{
++	struct sd *sd = (struct sd *) gspca_dev;
++
++	sd->exposure = val;
++	if (gspca_dev->streaming)
++		setexposure(gspca_dev);
++	return 0;
++}
++
++static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
++{
++	struct sd *sd = (struct sd *) gspca_dev;
++
++	*val = sd->exposure;
++	return 0;
++}
++
++static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
++{
++	struct sd *sd = (struct sd *) gspca_dev;
++
++	sd->gain = val;
++	if (gspca_dev->streaming)
++		setgain(gspca_dev);
++	return 0;
++}
++
++static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
++{
++	struct sd *sd = (struct sd *) gspca_dev;
++
++	*val = sd->gain;
++	return 0;
+ }
+ 
+ /* Include pac common sof detection functions */
+@@ -320,8 +886,9 @@ static const struct sd_desc sd_desc = {
+ 
+ /* -- module initialisation -- */
+ static const __devinitdata struct usb_device_id device_table[] = {
+-	{USB_DEVICE(0x08ca, 0x0111)},
+-	{USB_DEVICE(0x093a, 0x010f)},
++	{USB_DEVICE(0x08ca, 0x0111)},	/* Aiptek Pencam VGA+ */
++	{USB_DEVICE(0x093a, 0x010f)},	/* All other known MR97310A VGA cams */
++	{USB_DEVICE(0x093a, 0x010e)},	/* All known MR97310A CIF cams */
+ 	{}
+ };
+ MODULE_DEVICE_TABLE(usb, device_table);

commit 3040b043423c1726a14595d500f6409070b1e722
+Author: Theodore Kilgore 
+Date:   Mon Aug 3 04:13:23 2009 -0300
+
+    V4L/DVB (12459): gspca - jeilinj: New subdriver for Jeilin chip.
+    
+    Signed-off-by: Theodore Kilgore 
+    Signed-off-by: Jean-Francois Moine 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt
+index b43702470130..76203a2213ad 100644
+--- a/Documentation/video4linux/gspca.txt
++++ b/Documentation/video4linux/gspca.txt
+@@ -239,6 +239,7 @@ pac7311		093a:2626	Labtec 2200
+ pac7311		093a:2629	Genious iSlim 300
+ pac7311		093a:262a	Webcam 300k
+ pac7311		093a:262c	Philips SPC 230 NC
++jeilinj		0979:0280	Sakar 57379
+ zc3xx		0ac8:0302	Z-star Vimicro zc0302
+ vc032x		0ac8:0321	Vimicro generic vc0321
+ vc032x		0ac8:0323	Vimicro Vc0323
+diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig
+index f114dd1507c2..e800c22a9a89 100644
+--- a/drivers/media/video/gspca/Kconfig
++++ b/drivers/media/video/gspca/Kconfig
+@@ -47,6 +47,15 @@ config USB_GSPCA_FINEPIX
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called gspca_finepix.
+ 
++config USB_GSPCA_JEILINJ
++	tristate "Jeilin JPEG USB V4L2 driver"
++	depends on VIDEO_V4L2 && USB_GSPCA
++	help
++	  Say Y here if you want support for cameras based on this Jeilin chip.
++
++	  To compile this driver as a module, choose M here: the
++	  module will be called gspca_jeilinj.
++
+ config USB_GSPCA_MARS
+ 	tristate "Mars USB Camera Driver"
+ 	depends on VIDEO_V4L2 && USB_GSPCA
+diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile
+index f6d3b86e9ad5..035616b5e867 100644
+--- a/drivers/media/video/gspca/Makefile
++++ b/drivers/media/video/gspca/Makefile
+@@ -2,6 +2,7 @@ obj-$(CONFIG_USB_GSPCA)          += gspca_main.o
+ obj-$(CONFIG_USB_GSPCA_CONEX)    += gspca_conex.o
+ obj-$(CONFIG_USB_GSPCA_ETOMS)    += gspca_etoms.o
+ obj-$(CONFIG_USB_GSPCA_FINEPIX)  += gspca_finepix.o
++obj-$(CONFIG_USB_GSPCA_JEILINJ)  += gspca_jeilinj.o
+ obj-$(CONFIG_USB_GSPCA_MARS)     += gspca_mars.o
+ obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o
+ obj-$(CONFIG_USB_GSPCA_OV519)    += gspca_ov519.o
+@@ -30,6 +31,7 @@ gspca_main-objs     := gspca.o
+ gspca_conex-objs    := conex.o
+ gspca_etoms-objs    := etoms.o
+ gspca_finepix-objs  := finepix.o
++gspca_jeilinj-objs  := jeilinj.o
+ gspca_mars-objs     := mars.o
+ gspca_mr97310a-objs := mr97310a.o
+ gspca_ov519-objs    := ov519.o
+diff --git a/drivers/media/video/gspca/jeilinj.c b/drivers/media/video/gspca/jeilinj.c
+new file mode 100644
+index 000000000000..dbfa3ed6e8ef
+--- /dev/null
++++ b/drivers/media/video/gspca/jeilinj.c
+@@ -0,0 +1,388 @@
++/*
++ * Jeilinj subdriver
++ *
++ * Supports some Jeilin dual-mode cameras which use bulk transport and
++ * download raw JPEG data.
++ *
++ * Copyright (C) 2009 Theodore Kilgore
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#define MODULE_NAME "jeilinj"
++
++#include 
++#include "gspca.h"
++#include "jpeg.h"
++
++MODULE_AUTHOR("Theodore Kilgore ");
++MODULE_DESCRIPTION("GSPCA/JEILINJ USB Camera Driver");
++MODULE_LICENSE("GPL");
++
++/* Default timeouts, in ms */
++#define JEILINJ_CMD_TIMEOUT 500
++#define JEILINJ_DATA_TIMEOUT 1000
++
++/* Maximum transfer size to use. */
++#define JEILINJ_MAX_TRANSFER 0x200
++
++#define FRAME_HEADER_LEN 0x10
++
++/* Structure to hold all of our device specific stuff */
++struct sd {
++	struct gspca_dev gspca_dev;	/* !! must be the first item */
++	const struct v4l2_pix_format *cap_mode;
++	/* Driver stuff */
++	struct work_struct work_struct;
++	struct workqueue_struct *work_thread;
++	u8 quality;				 /* image quality */
++	u8 jpegqual;				/* webcam quality */
++	u8 *jpeg_hdr;
++};
++
++	struct jlj_command {
++		unsigned char instruction[2];
++		unsigned char ack_wanted;
++	};
++
++/* AFAICT these cameras will only do 320x240. */
++static struct v4l2_pix_format jlj_mode[] = {
++	{ 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
++		.bytesperline = 320,
++		.sizeimage = 320 * 240,
++		.colorspace = V4L2_COLORSPACE_JPEG,
++		.priv = 0}
++};
++
++/*
++ * cam uses endpoint 0x03 to send commands, 0x84 for read commands,
++ * and 0x82 for bulk transfer.
++ */
++
++/* All commands are two bytes only */
++static int jlj_write2(struct gspca_dev *gspca_dev, unsigned char *command)
++{
++	int retval;
++
++	memcpy(gspca_dev->usb_buf, command, 2);
++	retval = usb_bulk_msg(gspca_dev->dev,
++			usb_sndbulkpipe(gspca_dev->dev, 3),
++			gspca_dev->usb_buf, 2, NULL, 500);
++	if (retval < 0)
++		PDEBUG(D_ERR, "command write [%02x] error %d",
++				gspca_dev->usb_buf[0], retval);
++	return retval;
++}
++
++/* Responses are one byte only */
++static int jlj_read1(struct gspca_dev *gspca_dev, unsigned char response)
++{
++	int retval;
++
++	retval = usb_bulk_msg(gspca_dev->dev,
++	usb_rcvbulkpipe(gspca_dev->dev, 0x84),
++				gspca_dev->usb_buf, 1, NULL, 500);
++	response = gspca_dev->usb_buf[0];
++	if (retval < 0)
++		PDEBUG(D_ERR, "read command [%02x] error %d",
++				gspca_dev->usb_buf[0], retval);
++	return retval;
++}
++
++static int jlj_start(struct gspca_dev *gspca_dev)
++{
++	int i;
++	int retval = -1;
++	u8 response = 0xff;
++	struct jlj_command start_commands[] = {
++		{{0x71, 0x81}, 0},
++		{{0x70, 0x05}, 0},
++		{{0x95, 0x70}, 1},
++		{{0x71, 0x81}, 0},
++		{{0x70, 0x04}, 0},
++		{{0x95, 0x70}, 1},
++		{{0x71, 0x00}, 0},
++		{{0x70, 0x08}, 0},
++		{{0x95, 0x70}, 1},
++		{{0x94, 0x02}, 0},
++		{{0xde, 0x24}, 0},
++		{{0x94, 0x02}, 0},
++		{{0xdd, 0xf0}, 0},
++		{{0x94, 0x02}, 0},
++		{{0xe3, 0x2c}, 0},
++		{{0x94, 0x02}, 0},
++		{{0xe4, 0x00}, 0},
++		{{0x94, 0x02}, 0},
++		{{0xe5, 0x00}, 0},
++		{{0x94, 0x02}, 0},
++		{{0xe6, 0x2c}, 0},
++		{{0x94, 0x03}, 0},
++		{{0xaa, 0x00}, 0},
++		{{0x71, 0x1e}, 0},
++		{{0x70, 0x06}, 0},
++		{{0x71, 0x80}, 0},
++		{{0x70, 0x07}, 0}
++	};
++	for (i = 0; i < ARRAY_SIZE(start_commands); i++) {
++		retval = jlj_write2(gspca_dev, start_commands[i].instruction);
++		if (retval < 0)
++			return retval;
++		if (start_commands[i].ack_wanted)
++			retval = jlj_read1(gspca_dev, response);
++		if (retval < 0)
++			return retval;
++	}
++	PDEBUG(D_ERR, "jlj_start retval is %d", retval);
++	return retval;
++}
++
++static int jlj_stop(struct gspca_dev *gspca_dev)
++{
++	int i;
++	int retval;
++	struct jlj_command stop_commands[] = {
++		{{0x71, 0x00}, 0},
++		{{0x70, 0x09}, 0},
++		{{0x71, 0x80}, 0},
++		{{0x70, 0x05}, 0}
++	};
++	for (i = 0; i < ARRAY_SIZE(stop_commands); i++) {
++		retval = jlj_write2(gspca_dev, stop_commands[i].instruction);
++		if (retval < 0)
++			return retval;
++	}
++	return retval;
++}
++
++/* This function is called as a workqueue function and runs whenever the camera
++ * is streaming data. Because it is a workqueue function it is allowed to sleep
++ * so we can use synchronous USB calls. To avoid possible collisions with other
++ * threads attempting to use the camera's USB interface the gspca usb_lock is
++ * used when performing the one USB control operation inside the workqueue,
++ * which tells the camera to close the stream. In practice the only thing
++ * which needs to be protected against is the usb_set_interface call that
++ * gspca makes during stream_off. Otherwise the camera doesn't provide any
++ * controls that the user could try to change.
++ */
++
++static void jlj_dostream(struct work_struct *work)
++{
++	struct sd *dev = container_of(work, struct sd, work_struct);
++	struct gspca_dev *gspca_dev = &dev->gspca_dev;
++	struct gspca_frame *frame;
++	int blocks_left; /* 0x200-sized blocks remaining in current frame. */
++	int size_in_blocks;
++	int act_len;
++	int discarding = 0; /* true if we failed to get space for frame. */
++	int packet_type;
++	int ret;
++	u8 *buffer;
++
++	buffer = kmalloc(JEILINJ_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
++	if (!buffer) {
++		PDEBUG(D_ERR, "Couldn't allocate USB buffer");
++		goto quit_stream;
++	}
++	while (gspca_dev->present && gspca_dev->streaming) {
++		if (!gspca_dev->present)
++			goto quit_stream;
++		/* Start a new frame, and add the JPEG header, first thing */
++		frame = gspca_get_i_frame(gspca_dev);
++		if (frame && !discarding)
++			gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
++					dev->jpeg_hdr, JPEG_HDR_SZ);
++		 else
++			discarding = 1;
++		/*
++		 * Now request data block 0. Line 0 reports the size
++		 * to download, in blocks of size 0x200, and also tells the
++		 * "actual" data size, in bytes, which seems best to ignore.
++		 */
++		ret = usb_bulk_msg(gspca_dev->dev,
++				usb_rcvbulkpipe(gspca_dev->dev, 0x82),
++				buffer, JEILINJ_MAX_TRANSFER, &act_len,
++				JEILINJ_DATA_TIMEOUT);
++		PDEBUG(D_STREAM,
++			"Got %d bytes out of %d for Block 0",
++			act_len, JEILINJ_MAX_TRANSFER);
++		if (ret < 0 || act_len < FRAME_HEADER_LEN)
++			goto quit_stream;
++		size_in_blocks = buffer[0x0a];
++		blocks_left = buffer[0x0a] - 1;
++		PDEBUG(D_STREAM, "blocks_left = 0x%x", blocks_left);
++		packet_type = INTER_PACKET;
++		if (frame && !discarding)
++			/* Toss line 0 of data block 0, keep the rest. */
++			gspca_frame_add(gspca_dev, packet_type,
++				frame, buffer + FRAME_HEADER_LEN,
++				JEILINJ_MAX_TRANSFER - FRAME_HEADER_LEN);
++			else
++				discarding = 1;
++		while (blocks_left > 0) {
++			if (!gspca_dev->present)
++				goto quit_stream;
++			ret = usb_bulk_msg(gspca_dev->dev,
++				usb_rcvbulkpipe(gspca_dev->dev, 0x82),
++				buffer, JEILINJ_MAX_TRANSFER, &act_len,
++				JEILINJ_DATA_TIMEOUT);
++			if (ret < 0 || act_len < JEILINJ_MAX_TRANSFER)
++				goto quit_stream;
++			PDEBUG(D_STREAM,
++				"%d blocks remaining for frame", blocks_left);
++			blocks_left -= 1;
++			if (blocks_left == 0)
++				packet_type = LAST_PACKET;
++			else
++				packet_type = INTER_PACKET;
++			if (frame && !discarding)
++				gspca_frame_add(gspca_dev, packet_type,
++						frame, buffer,
++						JEILINJ_MAX_TRANSFER);
++			else
++				discarding = 1;
++		}
++	}
++quit_stream:
++	mutex_lock(&gspca_dev->usb_lock);
++	if (gspca_dev->present)
++		jlj_stop(gspca_dev);
++	mutex_unlock(&gspca_dev->usb_lock);
++	kfree(buffer);
++}
++
++/* This function is called at probe time just before sd_init */
++static int sd_config(struct gspca_dev *gspca_dev,
++		const struct usb_device_id *id)
++{
++	struct cam *cam = &gspca_dev->cam;
++	struct sd *dev  = (struct sd *) gspca_dev;
++
++	dev->quality  = 85;
++	dev->jpegqual = 85;
++	PDEBUG(D_PROBE,
++		"JEILINJ camera detected"
++		" (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
++	cam->cam_mode = jlj_mode;
++	cam->nmodes = 1;
++	cam->bulk = 1;
++	/* We don't use the buffer gspca allocates so make it small. */
++	cam->bulk_size = 32;
++	INIT_WORK(&dev->work_struct, jlj_dostream);
++	return 0;
++}
++
++/* called on streamoff with alt==0 and on disconnect */
++/* the usb_lock is held at entry - restore on exit */
++static void sd_stop0(struct gspca_dev *gspca_dev)
++{
++	struct sd *dev = (struct sd *) gspca_dev;
++
++	/* wait for the work queue to terminate */
++	mutex_unlock(&gspca_dev->usb_lock);
++	/* This waits for jlj_dostream to finish */
++	destroy_workqueue(dev->work_thread);
++	dev->work_thread = NULL;
++	mutex_lock(&gspca_dev->usb_lock);
++	kfree(dev->jpeg_hdr);
++}
++
++/* this function is called at probe and resume time */
++static int sd_init(struct gspca_dev *gspca_dev)
++{
++	return 0;
++}
++
++/* Set up for getting frames. */
++static int sd_start(struct gspca_dev *gspca_dev)
++{
++	struct sd *dev = (struct sd *) gspca_dev;
++	int ret;
++
++	/* create the JPEG header */
++	dev->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
++	jpeg_define(dev->jpeg_hdr, gspca_dev->height, gspca_dev->width,
++			0x21);          /* JPEG 422 */
++	jpeg_set_qual(dev->jpeg_hdr, dev->quality);
++	PDEBUG(D_STREAM, "Start streaming at 320x240");
++	ret = jlj_start(gspca_dev);
++	if (ret < 0) {
++		PDEBUG(D_ERR, "Start streaming command failed");
++		return ret;
++	}
++	/* Start the workqueue function to do the streaming */
++	dev->work_thread = create_singlethread_workqueue(MODULE_NAME);
++	queue_work(dev->work_thread, &dev->work_struct);
++
++	return 0;
++}
++
++/* Table of supported USB devices */
++static const __devinitdata struct usb_device_id device_table[] = {
++	{USB_DEVICE(0x0979, 0x0280)},
++	{}
++};
++
++MODULE_DEVICE_TABLE(usb, device_table);
++
++/* sub-driver description */
++static const struct sd_desc sd_desc = {
++	.name   = MODULE_NAME,
++	.config = sd_config,
++	.init   = sd_init,
++	.start  = sd_start,
++	.stop0  = sd_stop0,
++};
++
++/* -- device connect -- */
++static int sd_probe(struct usb_interface *intf,
++		const struct usb_device_id *id)
++{
++	return gspca_dev_probe(intf, id,
++			&sd_desc,
++			sizeof(struct sd),
++			THIS_MODULE);
++}
++
++static struct usb_driver sd_driver = {
++	.name       = MODULE_NAME,
++	.id_table   = device_table,
++	.probe      = sd_probe,
++	.disconnect = gspca_disconnect,
++#ifdef CONFIG_PM
++	.suspend = gspca_suspend,
++	.resume  = gspca_resume,
++#endif
++};
++
++/* -- module insert / remove -- */
++static int __init sd_mod_init(void)
++{
++	int ret;
++
++	ret = usb_register(&sd_driver);
++	if (ret < 0)
++		return ret;
++	PDEBUG(D_PROBE, "registered");
++	return 0;
++}
++
++static void __exit sd_mod_exit(void)
++{
++	usb_deregister(&sd_driver);
++	PDEBUG(D_PROBE, "deregistered");
++}
++
++module_init(sd_mod_init);
++module_exit(sd_mod_exit);

commit ebf58f70e853b9ffe50d6b194d3679b7dc2cac9c
+Author: Theodore Kilgore 
+Date:   Sun Apr 5 15:36:04 2009 -0300
+
+    V4L/DVB (11483): gspca - mr97310a: Webcam 093a:010f added.
+    
+    Signed-off-by: Theodore Kilgore 
+    Signed-off-by: Jean-Francois Moine 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt
+index 98529e03a46e..e418a8fb9c66 100644
+--- a/Documentation/video4linux/gspca.txt
++++ b/Documentation/video4linux/gspca.txt
+@@ -209,6 +209,7 @@ sunplus		08ca:2050	Medion MD 41437
+ sunplus		08ca:2060	Aiptek PocketDV5300
+ tv8532		0923:010f	ICM532 cams
+ mars		093a:050f	Mars-Semi Pc-Camera
++mr97310a	093a:010f	Sakar Digital no. 77379
+ pac207		093a:2460	Qtec Webcam 100
+ pac207		093a:2461	HP Webcam
+ pac207		093a:2463	Philips SPC 220 NC
+diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c
+index f9da55b20fa3..30132513400c 100644
+--- a/drivers/media/video/gspca/mr97310a.c
++++ b/drivers/media/video/gspca/mr97310a.c
+@@ -321,6 +321,7 @@ static const struct sd_desc sd_desc = {
+ /* -- module initialisation -- */
+ static const __devinitdata struct usb_device_id device_table[] = {
+ 	{USB_DEVICE(0x08ca, 0x0111)},
++	{USB_DEVICE(0x093a, 0x010f)},
+ 	{}
+ };
+ MODULE_DEVICE_TABLE(usb, device_table);

commit 14a19c0a2254ba58ed7559e072456ab94c9a2d3c
+Author: Theodore Kilgore 
+Date:   Wed Mar 25 07:13:13 2009 -0300
+
+    V4L/DVB (11213): gspca - sq905c: New subdriver.
+    
+    The code in the new sq905c.c is based upon the structure of the code in
+    gspca/sq905.c, and upon the code in libgphoto2/camlibs/digigr8, which supports
+    the same set of cameras in stillcam mode. I am a co-author of gspca/sq905.c and
+    I am the sole author of libgphoto2/camlibs/digigr8, which is licensed under the
+    LGPL. I hereby give myself permission to use my own code from libgphoto2 in
+    gspca/sq905c.c.
+    
+    Signed-off-by: Theodore Kilgore 
+    Signed-off-by: Jean-Francois Moine 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig
+index a0f05ef5ca70..578dc4ffc965 100644
+--- a/drivers/media/video/gspca/Kconfig
++++ b/drivers/media/video/gspca/Kconfig
+@@ -185,6 +185,15 @@ config USB_GSPCA_SQ905
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called gspca_sq905.
+ 
++config USB_GSPCA_SQ905C
++	tristate "SQ Technologies SQ905C based USB Camera Driver"
++	depends on VIDEO_V4L2 && USB_GSPCA
++	help
++	  Say Y here if you want support for cameras based on the SQ905C chip.
++
++	  To compile this driver as a module, choose M here: the
++	  module will be called gspca_sq905c.
++
+ config USB_GSPCA_STK014
+ 	tristate "Syntek DV4000 (STK014) USB Camera Driver"
+ 	depends on VIDEO_V4L2 && USB_GSPCA
+diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile
+index b6ec61185736..8a6643e8eb96 100644
+--- a/drivers/media/video/gspca/Makefile
++++ b/drivers/media/video/gspca/Makefile
+@@ -17,6 +17,7 @@ obj-$(CONFIG_USB_GSPCA_SPCA506)  += gspca_spca506.o
+ obj-$(CONFIG_USB_GSPCA_SPCA508)  += gspca_spca508.o
+ obj-$(CONFIG_USB_GSPCA_SPCA561)  += gspca_spca561.o
+ obj-$(CONFIG_USB_GSPCA_SQ905)    += gspca_sq905.o
++obj-$(CONFIG_USB_GSPCA_SQ905C)   += gspca_sq905c.o
+ obj-$(CONFIG_USB_GSPCA_SUNPLUS)  += gspca_sunplus.o
+ obj-$(CONFIG_USB_GSPCA_STK014)   += gspca_stk014.o
+ obj-$(CONFIG_USB_GSPCA_T613)     += gspca_t613.o
+@@ -43,6 +44,7 @@ gspca_spca506-objs  := spca506.o
+ gspca_spca508-objs  := spca508.o
+ gspca_spca561-objs  := spca561.o
+ gspca_sq905-objs    := sq905.o
++gspca_sq905c-objs   := sq905c.o
+ gspca_stk014-objs   := stk014.o
+ gspca_sunplus-objs  := sunplus.o
+ gspca_t613-objs     := t613.o
+diff --git a/drivers/media/video/gspca/sq905c.c b/drivers/media/video/gspca/sq905c.c
+new file mode 100644
+index 000000000000..0bcb74a1b143
+--- /dev/null
++++ b/drivers/media/video/gspca/sq905c.c
+@@ -0,0 +1,328 @@
++/*
++ * SQ905C subdriver
++ *
++ * Copyright (C) 2009 Theodore Kilgore
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++/*
++ *
++ * This driver uses work done in
++ * libgphoto2/camlibs/digigr8, Copyright (C) Theodore Kilgore.
++ *
++ * This driver has also used as a base the sq905c driver
++ * and may contain code fragments from it.
++ */
++
++#define MODULE_NAME "sq905c"
++
++#include 
++#include "gspca.h"
++
++MODULE_AUTHOR("Theodore Kilgore ");
++MODULE_DESCRIPTION("GSPCA/SQ905C USB Camera Driver");
++MODULE_LICENSE("GPL");
++
++/* Default timeouts, in ms */
++#define SQ905C_CMD_TIMEOUT 500
++#define SQ905C_DATA_TIMEOUT 1000
++
++/* Maximum transfer size to use. */
++#define SQ905C_MAX_TRANSFER 0x8000
++
++#define FRAME_HEADER_LEN 0x50
++
++/* Commands. These go in the "value" slot. */
++#define SQ905C_CLEAR   0xa0		/* clear everything */
++#define SQ905C_CAPTURE_LOW 0xa040	/* Starts capture at 160x120 */
++#define SQ905C_CAPTURE_MED 0x1440	/* Starts capture at 320x240 */
++#define SQ905C_CAPTURE_HI 0x2840	/* Starts capture at 320x240 */
++
++/* For capture, this must go in the "index" slot. */
++#define SQ905C_CAPTURE_INDEX 0x110f
++
++/* Structure to hold all of our device specific stuff */
++struct sd {
++	struct gspca_dev gspca_dev;	/* !! must be the first item */
++	const struct v4l2_pix_format *cap_mode;
++	/* Driver stuff */
++	struct work_struct work_struct;
++	struct workqueue_struct *work_thread;
++};
++
++/*
++ * Most of these cameras will do 640x480 and 320x240. 160x120 works
++ * in theory but gives very poor output. Therefore, not supported.
++ * The 0x2770:0x9050 cameras have max resolution of 320x240.
++ */
++static struct v4l2_pix_format sq905c_mode[] = {
++	{ 320, 240, V4L2_PIX_FMT_SQ905C, V4L2_FIELD_NONE,
++		.bytesperline = 320,
++		.sizeimage = 320 * 240,
++		.colorspace = V4L2_COLORSPACE_SRGB,
++		.priv = 0},
++	{ 640, 480, V4L2_PIX_FMT_SQ905C, V4L2_FIELD_NONE,
++		.bytesperline = 640,
++		.sizeimage = 640 * 480,
++		.colorspace = V4L2_COLORSPACE_SRGB,
++		.priv = 0}
++};
++
++/* Send a command to the camera. */
++static int sq905c_command(struct gspca_dev *gspca_dev, u16 command, u16 index)
++{
++	int ret;
++
++	ret = usb_control_msg(gspca_dev->dev,
++			      usb_sndctrlpipe(gspca_dev->dev, 0),
++			      USB_REQ_SYNCH_FRAME,                /* request */
++			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
++			      command, index, NULL, 0,
++			      SQ905C_CMD_TIMEOUT);
++	if (ret < 0) {
++		PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)",
++			__func__, ret);
++		return ret;
++	}
++
++	return 0;
++}
++
++/* This function is called as a workqueue function and runs whenever the camera
++ * is streaming data. Because it is a workqueue function it is allowed to sleep
++ * so we can use synchronous USB calls. To avoid possible collisions with other
++ * threads attempting to use the camera's USB interface the gspca usb_lock is
++ * used when performing the one USB control operation inside the workqueue,
++ * which tells the camera to close the stream. In practice the only thing
++ * which needs to be protected against is the usb_set_interface call that
++ * gspca makes during stream_off. Otherwise the camera doesn't provide any
++ * controls that the user could try to change.
++ */
++static void sq905c_dostream(struct work_struct *work)
++{
++	struct sd *dev = container_of(work, struct sd, work_struct);
++	struct gspca_dev *gspca_dev = &dev->gspca_dev;
++	struct gspca_frame *frame;
++	int bytes_left; /* bytes remaining in current frame. */
++	int data_len;   /* size to use for the next read. */
++	int act_len;
++	int discarding = 0; /* true if we failed to get space for frame. */
++	int packet_type;
++	int ret;
++	u8 *buffer;
++
++	buffer = kmalloc(SQ905C_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
++	if (!buffer) {
++		PDEBUG(D_ERR, "Couldn't allocate USB buffer");
++		goto quit_stream;
++	}
++
++	while (gspca_dev->present && gspca_dev->streaming) {
++		if (!gspca_dev->present)
++			goto quit_stream;
++		/* Request the header, which tells the size to download */
++		ret = usb_bulk_msg(gspca_dev->dev,
++				usb_rcvbulkpipe(gspca_dev->dev, 0x81),
++				buffer, FRAME_HEADER_LEN, &act_len,
++				SQ905C_DATA_TIMEOUT);
++		PDEBUG(D_STREAM,
++			"Got %d bytes out of %d for header",
++			act_len, FRAME_HEADER_LEN);
++		if (ret < 0 || act_len < FRAME_HEADER_LEN)
++			goto quit_stream;
++		/* size is read from 4 bytes starting 0x40, little endian */
++		bytes_left = buffer[0x40]|(buffer[0x41]<<8)|(buffer[0x42]<<16)
++					|(buffer[0x43]<<24);
++		PDEBUG(D_STREAM, "bytes_left = 0x%x", bytes_left);
++		/* We keep the header. It has other information, too. */
++		packet_type = FIRST_PACKET;
++		frame = gspca_get_i_frame(gspca_dev);
++		if (frame && !discarding) {
++			gspca_frame_add(gspca_dev, packet_type,
++				frame, buffer, FRAME_HEADER_LEN);
++			} else
++				discarding = 1;
++		while (bytes_left > 0) {
++			data_len = bytes_left > SQ905C_MAX_TRANSFER ?
++				SQ905C_MAX_TRANSFER : bytes_left;
++			if (!gspca_dev->present)
++				goto quit_stream;
++			ret = usb_bulk_msg(gspca_dev->dev,
++				usb_rcvbulkpipe(gspca_dev->dev, 0x81),
++				buffer, data_len, &act_len,
++				SQ905C_DATA_TIMEOUT);
++			if (ret < 0 || act_len < data_len)
++				goto quit_stream;
++			PDEBUG(D_STREAM,
++				"Got %d bytes out of %d for frame",
++				data_len, bytes_left);
++			bytes_left -= data_len;
++			if (bytes_left == 0)
++				packet_type = LAST_PACKET;
++			else
++				packet_type = INTER_PACKET;
++			frame = gspca_get_i_frame(gspca_dev);
++			if (frame && !discarding)
++				gspca_frame_add(gspca_dev, packet_type,
++						frame, buffer, data_len);
++			else
++				discarding = 1;
++		}
++	}
++quit_stream:
++	mutex_lock(&gspca_dev->usb_lock);
++	if (gspca_dev->present)
++		sq905c_command(gspca_dev, SQ905C_CLEAR, 0);
++	mutex_unlock(&gspca_dev->usb_lock);
++	kfree(buffer);
++}
++
++/* This function is called at probe time just before sd_init */
++static int sd_config(struct gspca_dev *gspca_dev,
++		const struct usb_device_id *id)
++{
++	struct cam *cam = &gspca_dev->cam;
++	struct sd *dev = (struct sd *) gspca_dev;
++
++	PDEBUG(D_PROBE,
++		"SQ9050 camera detected"
++		" (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
++	cam->cam_mode = sq905c_mode;
++	cam->nmodes = 2;
++	if (id->idProduct == 0x9050)
++		cam->nmodes = 1;
++	/* We don't use the buffer gspca allocates so make it small. */
++	cam->bulk_size = 32;
++	INIT_WORK(&dev->work_struct, sq905c_dostream);
++	return 0;
++}
++
++/* called on streamoff with alt==0 and on disconnect */
++/* the usb_lock is held at entry - restore on exit */
++static void sd_stop0(struct gspca_dev *gspca_dev)
++{
++	struct sd *dev = (struct sd *) gspca_dev;
++
++	/* wait for the work queue to terminate */
++	mutex_unlock(&gspca_dev->usb_lock);
++	/* This waits for sq905c_dostream to finish */
++	destroy_workqueue(dev->work_thread);
++	dev->work_thread = NULL;
++	mutex_lock(&gspca_dev->usb_lock);
++}
++
++/* this function is called at probe and resume time */
++static int sd_init(struct gspca_dev *gspca_dev)
++{
++	int ret;
++
++	/* connect to the camera and reset it. */
++	ret = sq905c_command(gspca_dev, SQ905C_CLEAR, 0);
++	return ret;
++}
++
++/* Set up for getting frames. */
++static int sd_start(struct gspca_dev *gspca_dev)
++{
++	struct sd *dev = (struct sd *) gspca_dev;
++	int ret;
++
++	dev->cap_mode = gspca_dev->cam.cam_mode;
++	/* "Open the shutter" and set size, to start capture */
++	switch (gspca_dev->width) {
++	case 640:
++		PDEBUG(D_STREAM, "Start streaming at high resolution");
++		dev->cap_mode++;
++		ret = sq905c_command(gspca_dev, SQ905C_CAPTURE_HI,
++						SQ905C_CAPTURE_INDEX);
++		break;
++	default: /* 320 */
++	PDEBUG(D_STREAM, "Start streaming at medium resolution");
++		ret = sq905c_command(gspca_dev, SQ905C_CAPTURE_MED,
++						SQ905C_CAPTURE_INDEX);
++	}
++
++	if (ret < 0) {
++		PDEBUG(D_ERR, "Start streaming command failed");
++		return ret;
++	}
++	/* Start the workqueue function to do the streaming */
++	dev->work_thread = create_singlethread_workqueue(MODULE_NAME);
++	queue_work(dev->work_thread, &dev->work_struct);
++
++	return 0;
++}
++
++/* Table of supported USB devices */
++static const __devinitdata struct usb_device_id device_table[] = {
++	{USB_DEVICE(0x2770, 0x905c)},
++	{USB_DEVICE(0x2770, 0x9050)},
++	{USB_DEVICE(0x2770, 0x913d)},
++	{}
++};
++
++MODULE_DEVICE_TABLE(usb, device_table);
++
++/* sub-driver description */
++static const struct sd_desc sd_desc = {
++	.name   = MODULE_NAME,
++	.config = sd_config,
++	.init   = sd_init,
++	.start  = sd_start,
++	.stop0  = sd_stop0,
++};
++
++/* -- device connect -- */
++static int sd_probe(struct usb_interface *intf,
++		const struct usb_device_id *id)
++{
++	return gspca_dev_probe(intf, id,
++			&sd_desc,
++			sizeof(struct sd),
++			THIS_MODULE);
++}
++
++static struct usb_driver sd_driver = {
++	.name       = MODULE_NAME,
++	.id_table   = device_table,
++	.probe      = sd_probe,
++	.disconnect = gspca_disconnect,
++#ifdef CONFIG_PM
++	.suspend = gspca_suspend,
++	.resume  = gspca_resume,
++#endif
++};
++
++/* -- module insert / remove -- */
++static int __init sd_mod_init(void)
++{
++	int ret;
++
++	ret = usb_register(&sd_driver);
++	if (ret < 0)
++		return ret;
++	PDEBUG(D_PROBE, "registered");
++	return 0;
++}
++
++static void __exit sd_mod_exit(void)
++{
++	usb_deregister(&sd_driver);
++	PDEBUG(D_PROBE, "deregistered");
++}
++
++module_init(sd_mod_init);
++module_exit(sd_mod_exit);
+diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
+index 61f1a4921afd..139d234923cd 100644
+--- a/include/linux/videodev2.h
++++ b/include/linux/videodev2.h
+@@ -345,6 +345,7 @@ struct v4l2_pix_format {
+ #define V4L2_PIX_FMT_SPCA561  v4l2_fourcc('S', '5', '6', '1') /* compressed GBRG bayer */
+ #define V4L2_PIX_FMT_PAC207   v4l2_fourcc('P', '2', '0', '7') /* compressed BGGR bayer */
+ #define V4L2_PIX_FMT_MR97310A v4l2_fourcc('M', '3', '1', '0') /* compressed BGGR bayer */
++#define V4L2_PIX_FMT_SQ905C   v4l2_fourcc('9', '0', '5', 'C') /* compressed RGGB bayer */
+ #define V4L2_PIX_FMT_PJPG     v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */
+ #define V4L2_PIX_FMT_YVYU    v4l2_fourcc('Y', 'V', 'Y', 'U') /* 16  YVU 4:2:2     */
+ 

commit 9832d765f82769799ba15ac9d2e8edf8f7de6898
+Author: Theodore Kilgore 
+Date:   Fri Mar 13 13:04:31 2009 -0300
+
+    V4L/DVB (10986): mr97310a: don't discard frame headers on stream output
+    
+    Fix a bug where all frame headers were being discarded, instead of being part of the
+    stream output, on MR97310A cameras.
+    
+    The frame headers contain information which may be useful in processing
+    the video output and therefore should be kept and not discarded.
+    
+    A corresponding patch to the decompression algorithm in
+    libv4lconvert/mr97310a.c corrects the change in frame offset.
+    
+    Signed-off-by: Theodore Kilgore 
+    Signed-off-by: Hans de Goede 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c
+index 5ec5ce6e3ed9..2a901a4a6f00 100644
+--- a/drivers/media/video/gspca/mr97310a.c
++++ b/drivers/media/video/gspca/mr97310a.c
+@@ -29,9 +29,7 @@ MODULE_LICENSE("GPL");
+ /* specific webcam descriptor */
+ struct sd {
+ 	struct gspca_dev gspca_dev;  /* !! must be the first item */
+-
+ 	u8 sof_read;
+-	u8 header_read;
+ };
+ 
+ /* V4L2 controls supported by the driver */
+@@ -285,7 +283,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+ 			__u8 *data,                   /* isoc packet */
+ 			int len)                      /* iso packet length */
+ {
+-	struct sd *sd = (struct sd *) gspca_dev;
+ 	unsigned char *sof;
+ 
+ 	sof = pac_find_sof(gspca_dev, data, len);
+@@ -300,25 +297,12 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+ 			n = 0;
+ 		frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
+ 					data, n);
+-		sd->header_read = 0;
+-		gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0);
++		/* Start next frame. */
++		gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
++			pac_sof_marker, sizeof pac_sof_marker);
+ 		len -= sof - data;
+ 		data = sof;
+ 	}
+-	if (sd->header_read < 7) {
+-		int needed;
+-
+-		/* skip the rest of the header */
+-		needed = 7 - sd->header_read;
+-		if (len <= needed) {
+-			sd->header_read += len;
+-			return;
+-		}
+-		data += needed;
+-		len -= needed;
+-		sd->header_read = 7;
+-	}
+-
+ 	gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
+ }
+ 

\ No newline at end of file diff --git a/detail/3.html b/detail/3.html new file mode 100644 index 0000000..9c8d1a1 --- /dev/null +++ b/detail/3.html @@ -0,0 +1,314438 @@ +

Patches contributed by University of Virginia, Charlottesville


commit 29727f3bc2e691d59c521ff09b4d59a743b5d9a3
+Author: Bill Pemberton 
+Date:   Wed Mar 20 11:46:10 2013 -0400
+
+    Revert "USB: quatech2: only write to the tty if the port is open."
+    
+    This reverts commit 27b351c5546008c640b3e65152f60ca74b3706f1.
+    
+    Calling tty_flip_buffer_push on an unopened tty is legal, so the
+    driver doesn't need track if port has been opened.  Reverting this
+    allows the entire is_open logic to be removed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c
+index d643a4d4d770..00e6c9bac8a3 100644
+--- a/drivers/usb/serial/quatech2.c
++++ b/drivers/usb/serial/quatech2.c
+@@ -661,9 +661,7 @@ void qt2_process_read_urb(struct urb *urb)
+ 						 __func__);
+ 					break;
+ 				}
+-
+-				if (port_priv->is_open)
+-					tty_flip_buffer_push(&port->port);
++				tty_flip_buffer_push(&port->port);
+ 
+ 				newport = *(ch + 3);
+ 
+@@ -706,8 +704,7 @@ void qt2_process_read_urb(struct urb *urb)
+ 		tty_insert_flip_string(&port->port, ch, 1);
+ 	}
+ 
+-	if (port_priv->is_open)
+-		tty_flip_buffer_push(&port->port);
++	tty_flip_buffer_push(&port->port);
+ }
+ 
+ static void qt2_write_bulk_callback(struct urb *urb)

commit 27b351c5546008c640b3e65152f60ca74b3706f1
+Author: Bill Pemberton 
+Date:   Wed Mar 13 09:50:15 2013 -0400
+
+    USB: quatech2: only write to the tty if the port is open.
+    
+    The commit 2e124b4a390ca85325fae75764bef92f0547fa25 removed the checks
+    that prevented qt2_process_read_urb() from trying to put chars into
+    ttys that weren't actually opened.  This resulted in 'tty is NULL'
+    warnings from flush_to_ldisc() when the device was used.
+    
+    The devices use just one read urb for all ports.  As a result
+    qt2_process_read_urb() may be called with the current port set to a
+    port number that has not been opened.  Add a check if the port is open
+    before calling tty_flip_buffer_push().
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c
+index 00e6c9bac8a3..d643a4d4d770 100644
+--- a/drivers/usb/serial/quatech2.c
++++ b/drivers/usb/serial/quatech2.c
+@@ -661,7 +661,9 @@ void qt2_process_read_urb(struct urb *urb)
+ 						 __func__);
+ 					break;
+ 				}
+-				tty_flip_buffer_push(&port->port);
++
++				if (port_priv->is_open)
++					tty_flip_buffer_push(&port->port);
+ 
+ 				newport = *(ch + 3);
+ 
+@@ -704,7 +706,8 @@ void qt2_process_read_urb(struct urb *urb)
+ 		tty_insert_flip_string(&port->port, ch, 1);
+ 	}
+ 
+-	tty_flip_buffer_push(&port->port);
++	if (port_priv->is_open)
++		tty_flip_buffer_push(&port->port);
+ }
+ 
+ static void qt2_write_bulk_callback(struct urb *urb)

commit 0b255e927d47b550620dfd3475ee74b0f52e09c8
+Author: Bill Pemberton 
+Date:   Tue Nov 27 15:59:38 2012 -0500
+
+    i2c: remove __dev* attributes from subsystem
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Peter Korsgaard  (for ocores and mux-gpio)
+    Acked-by: Havard Skinnemoen  (for i2c-gpio)
+    Acked-by: Guan Xuetao  (for puf3)
+    Acked-by: Barry Song  (for sirf)
+    Reviewed-by: Jean Delvare 
+    [wsa: Fixed "foo* bar" flaws while we are here]
+    Signed-off-by: Wolfram Sang 
+
+diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
+index 125cd8e0ad25..3f491815e2c4 100644
+--- a/drivers/i2c/busses/i2c-ali1535.c
++++ b/drivers/i2c/busses/i2c-ali1535.c
+@@ -139,7 +139,7 @@ static unsigned short ali1535_offset;
+    Note the differences between kernels with the old PCI BIOS interface and
+    newer kernels with the real PCI interface. In compat.h some things are
+    defined to make the transition easier. */
+-static int __devinit ali1535_setup(struct pci_dev *dev)
++static int ali1535_setup(struct pci_dev *dev)
+ {
+ 	int retval;
+ 	unsigned char temp;
+@@ -502,7 +502,7 @@ static DEFINE_PCI_DEVICE_TABLE(ali1535_ids) = {
+ 
+ MODULE_DEVICE_TABLE(pci, ali1535_ids);
+ 
+-static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id)
++static int ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	if (ali1535_setup(dev)) {
+ 		dev_warn(&dev->dev,
+@@ -518,7 +518,7 @@ static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_
+ 	return i2c_add_adapter(&ali1535_adapter);
+ }
+ 
+-static void __devexit ali1535_remove(struct pci_dev *dev)
++static void ali1535_remove(struct pci_dev *dev)
+ {
+ 	i2c_del_adapter(&ali1535_adapter);
+ 	release_region(ali1535_smba, ALI1535_SMB_IOSIZE);
+@@ -528,7 +528,7 @@ static struct pci_driver ali1535_driver = {
+ 	.name		= "ali1535_smbus",
+ 	.id_table	= ali1535_ids,
+ 	.probe		= ali1535_probe,
+-	.remove		= __devexit_p(ali1535_remove),
++	.remove		= ali1535_remove,
+ };
+ 
+ module_pci_driver(ali1535_driver);
+diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
+index e02d9f86c6a0..84ccd9496a5e 100644
+--- a/drivers/i2c/busses/i2c-ali1563.c
++++ b/drivers/i2c/busses/i2c-ali1563.c
+@@ -326,7 +326,7 @@ static u32 ali1563_func(struct i2c_adapter * a)
+ }
+ 
+ 
+-static int __devinit ali1563_setup(struct pci_dev * dev)
++static int ali1563_setup(struct pci_dev *dev)
+ {
+ 	u16 ctrl;
+ 
+@@ -390,8 +390,8 @@ static struct i2c_adapter ali1563_adapter = {
+ 	.algo	= &ali1563_algorithm,
+ };
+ 
+-static int __devinit ali1563_probe(struct pci_dev * dev,
+-				const struct pci_device_id * id_table)
++static int ali1563_probe(struct pci_dev *dev,
++			 const struct pci_device_id *id_table)
+ {
+ 	int error;
+ 
+@@ -411,7 +411,7 @@ static int __devinit ali1563_probe(struct pci_dev * dev,
+ 	return error;
+ }
+ 
+-static void __devexit ali1563_remove(struct pci_dev * dev)
++static void ali1563_remove(struct pci_dev *dev)
+ {
+ 	i2c_del_adapter(&ali1563_adapter);
+ 	ali1563_shutdown(dev);
+@@ -428,7 +428,7 @@ static struct pci_driver ali1563_pci_driver = {
+  	.name		= "ali1563_smbus",
+ 	.id_table	= ali1563_id_table,
+  	.probe		= ali1563_probe,
+-	.remove		= __devexit_p(ali1563_remove),
++	.remove		= ali1563_remove,
+ };
+ 
+ module_pci_driver(ali1563_pci_driver);
+diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
+index ce8d26d053a5..26bcc6127cee 100644
+--- a/drivers/i2c/busses/i2c-ali15x3.c
++++ b/drivers/i2c/busses/i2c-ali15x3.c
+@@ -131,7 +131,7 @@ MODULE_PARM_DESC(force_addr,
+ static struct pci_driver ali15x3_driver;
+ static unsigned short ali15x3_smba;
+ 
+-static int __devinit ali15x3_setup(struct pci_dev *ALI15X3_dev)
++static int ali15x3_setup(struct pci_dev *ALI15X3_dev)
+ {
+ 	u16 a;
+ 	unsigned char temp;
+@@ -484,7 +484,7 @@ static DEFINE_PCI_DEVICE_TABLE(ali15x3_ids) = {
+ 
+ MODULE_DEVICE_TABLE (pci, ali15x3_ids);
+ 
+-static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id)
++static int ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	if (ali15x3_setup(dev)) {
+ 		dev_err(&dev->dev,
+@@ -500,7 +500,7 @@ static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_
+ 	return i2c_add_adapter(&ali15x3_adapter);
+ }
+ 
+-static void __devexit ali15x3_remove(struct pci_dev *dev)
++static void ali15x3_remove(struct pci_dev *dev)
+ {
+ 	i2c_del_adapter(&ali15x3_adapter);
+ 	release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE);
+@@ -510,7 +510,7 @@ static struct pci_driver ali15x3_driver = {
+ 	.name		= "ali15x3_smbus",
+ 	.id_table	= ali15x3_ids,
+ 	.probe		= ali15x3_probe,
+-	.remove		= __devexit_p(ali15x3_remove),
++	.remove		= ali15x3_remove,
+ };
+ 
+ module_pci_driver(ali15x3_driver);
+diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
+index 304aa03b57b2..e13e2aa2d05d 100644
+--- a/drivers/i2c/busses/i2c-amd756.c
++++ b/drivers/i2c/busses/i2c-amd756.c
+@@ -324,8 +324,7 @@ static DEFINE_PCI_DEVICE_TABLE(amd756_ids) = {
+ 
+ MODULE_DEVICE_TABLE (pci, amd756_ids);
+ 
+-static int __devinit amd756_probe(struct pci_dev *pdev,
+-				  const struct pci_device_id *id)
++static int amd756_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ 	int nforce = (id->driver_data == NFORCE);
+ 	int error;
+@@ -397,7 +396,7 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
+ 	return error;
+ }
+ 
+-static void __devexit amd756_remove(struct pci_dev *dev)
++static void amd756_remove(struct pci_dev *dev)
+ {
+ 	i2c_del_adapter(&amd756_smbus);
+ 	release_region(amd756_ioport, SMB_IOSIZE);
+@@ -407,7 +406,7 @@ static struct pci_driver amd756_driver = {
+ 	.name		= "amd756_smbus",
+ 	.id_table	= amd756_ids,
+ 	.probe		= amd756_probe,
+-	.remove		= __devexit_p(amd756_remove),
++	.remove		= amd756_remove,
+ };
+ 
+ module_pci_driver(amd756_driver);
+diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
+index 0919ac1d99aa..a44e6e77c5a1 100644
+--- a/drivers/i2c/busses/i2c-amd8111.c
++++ b/drivers/i2c/busses/i2c-amd8111.c
+@@ -422,8 +422,7 @@ static DEFINE_PCI_DEVICE_TABLE(amd8111_ids) = {
+ 
+ MODULE_DEVICE_TABLE (pci, amd8111_ids);
+ 
+-static int __devinit amd8111_probe(struct pci_dev *dev,
+-		const struct pci_device_id *id)
++static int amd8111_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	struct amd_smbus *smbus;
+ 	int error;
+@@ -475,7 +474,7 @@ static int __devinit amd8111_probe(struct pci_dev *dev,
+ 	return error;
+ }
+ 
+-static void __devexit amd8111_remove(struct pci_dev *dev)
++static void amd8111_remove(struct pci_dev *dev)
+ {
+ 	struct amd_smbus *smbus = pci_get_drvdata(dev);
+ 
+@@ -488,7 +487,7 @@ static struct pci_driver amd8111_driver = {
+ 	.name		= "amd8111_smbus2",
+ 	.id_table	= amd8111_ids,
+ 	.probe		= amd8111_probe,
+-	.remove		= __devexit_p(amd8111_remove),
++	.remove		= amd8111_remove,
+ };
+ 
+ module_pci_driver(amd8111_driver);
+diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
+index b4575ee4bdf3..2bfc04d0a1b1 100644
+--- a/drivers/i2c/busses/i2c-at91.c
++++ b/drivers/i2c/busses/i2c-at91.c
+@@ -145,7 +145,7 @@ static void at91_init_twi_bus(struct at91_twi_dev *dev)
+  * Calculate symmetric clock as stated in datasheet:
+  * twi_clk = F_MAIN / (2 * (cdiv * (1 << ckdiv) + offset))
+  */
+-static void __devinit at91_calc_twi_clock(struct at91_twi_dev *dev, int twi_clk)
++static void at91_calc_twi_clock(struct at91_twi_dev *dev, int twi_clk)
+ {
+ 	int ckdiv, cdiv, div;
+ 	struct at91_twi_pdata *pdata = dev->pdata;
+@@ -604,7 +604,7 @@ MODULE_DEVICE_TABLE(of, atmel_twi_dt_ids);
+ #define atmel_twi_dt_ids NULL
+ #endif
+ 
+-static bool __devinit filter(struct dma_chan *chan, void *slave)
++static bool filter(struct dma_chan *chan, void *slave)
+ {
+ 	struct at_dma_slave *sl = slave;
+ 
+@@ -616,7 +616,7 @@ static bool __devinit filter(struct dma_chan *chan, void *slave)
+ 	}
+ }
+ 
+-static int __devinit at91_twi_configure_dma(struct at91_twi_dev *dev, u32 phy_addr)
++static int at91_twi_configure_dma(struct at91_twi_dev *dev, u32 phy_addr)
+ {
+ 	int ret = 0;
+ 	struct at_dma_slave *sdata;
+@@ -688,7 +688,7 @@ static int __devinit at91_twi_configure_dma(struct at91_twi_dev *dev, u32 phy_ad
+ 	return ret;
+ }
+ 
+-static struct at91_twi_pdata * __devinit at91_twi_get_driver_data(
++static struct at91_twi_pdata *at91_twi_get_driver_data(
+ 					struct platform_device *pdev)
+ {
+ 	if (pdev->dev.of_node) {
+@@ -701,7 +701,7 @@ static struct at91_twi_pdata * __devinit at91_twi_get_driver_data(
+ 	return (struct at91_twi_pdata *) platform_get_device_id(pdev)->driver_data;
+ }
+ 
+-static int __devinit at91_twi_probe(struct platform_device *pdev)
++static int at91_twi_probe(struct platform_device *pdev)
+ {
+ 	struct at91_twi_dev *dev;
+ 	struct resource *mem;
+@@ -779,7 +779,7 @@ static int __devinit at91_twi_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit at91_twi_remove(struct platform_device *pdev)
++static int at91_twi_remove(struct platform_device *pdev)
+ {
+ 	struct at91_twi_dev *dev = platform_get_drvdata(pdev);
+ 	int rc;
+@@ -820,7 +820,7 @@ static const struct dev_pm_ops at91_twi_pm = {
+ 
+ static struct platform_driver at91_twi_driver = {
+ 	.probe		= at91_twi_probe,
+-	.remove		= __devexit_p(at91_twi_remove),
++	.remove		= at91_twi_remove,
+ 	.id_table	= at91_twi_devtypes,
+ 	.driver		= {
+ 		.name	= "at91_i2c",
+diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c
+index 582d616db346..b278298787d7 100644
+--- a/drivers/i2c/busses/i2c-au1550.c
++++ b/drivers/i2c/busses/i2c-au1550.c
+@@ -313,7 +313,7 @@ static void i2c_au1550_disable(struct i2c_au1550_data *priv)
+  * Prior to calling us, the 50MHz clock frequency and routing
+  * must have been set up for the PSC indicated by the adapter.
+  */
+-static int __devinit
++static int
+ i2c_au1550_probe(struct platform_device *pdev)
+ {
+ 	struct i2c_au1550_data *priv;
+@@ -372,7 +372,7 @@ i2c_au1550_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit i2c_au1550_remove(struct platform_device *pdev)
++static int i2c_au1550_remove(struct platform_device *pdev)
+ {
+ 	struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
+ 
+@@ -423,7 +423,7 @@ static struct platform_driver au1xpsc_smbus_driver = {
+ 		.pm	= AU1XPSC_SMBUS_PMOPS,
+ 	},
+ 	.probe		= i2c_au1550_probe,
+-	.remove		= __devexit_p(i2c_au1550_remove),
++	.remove		= i2c_au1550_remove,
+ };
+ 
+ module_platform_driver(au1xpsc_smbus_driver);
+diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c
+index c1e1096ba069..2e79c1024191 100644
+--- a/drivers/i2c/busses/i2c-cpm.c
++++ b/drivers/i2c/busses/i2c-cpm.c
+@@ -426,7 +426,7 @@ static const struct i2c_adapter cpm_ops = {
+ 	.algo		= &cpm_i2c_algo,
+ };
+ 
+-static int __devinit cpm_i2c_setup(struct cpm_i2c *cpm)
++static int cpm_i2c_setup(struct cpm_i2c *cpm)
+ {
+ 	struct platform_device *ofdev = cpm->ofdev;
+ 	const u32 *data;
+@@ -634,7 +634,7 @@ static void cpm_i2c_shutdown(struct cpm_i2c *cpm)
+ 		cpm_muram_free(cpm->i2c_addr);
+ }
+ 
+-static int __devinit cpm_i2c_probe(struct platform_device *ofdev)
++static int cpm_i2c_probe(struct platform_device *ofdev)
+ {
+ 	int result, len;
+ 	struct cpm_i2c *cpm;
+@@ -688,7 +688,7 @@ static int __devinit cpm_i2c_probe(struct platform_device *ofdev)
+ 	return result;
+ }
+ 
+-static int __devexit cpm_i2c_remove(struct platform_device *ofdev)
++static int cpm_i2c_remove(struct platform_device *ofdev)
+ {
+ 	struct cpm_i2c *cpm = dev_get_drvdata(&ofdev->dev);
+ 
+@@ -716,7 +716,7 @@ MODULE_DEVICE_TABLE(of, cpm_i2c_match);
+ 
+ static struct platform_driver cpm_i2c_driver = {
+ 	.probe		= cpm_i2c_probe,
+-	.remove		= __devexit_p(cpm_i2c_remove),
++	.remove		= cpm_i2c_remove,
+ 	.driver = {
+ 		.name = "fsl-i2c-cpm",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c
+index 92a1e2c15baa..6add851e9dee 100644
+--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
++++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
+@@ -207,7 +207,7 @@ static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
+ 	return dev->controller->clk_khz;
+ }
+ 
+-static int __devinit i2c_dw_pci_probe(struct pci_dev *pdev,
++static int i2c_dw_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+ {
+ 	struct dw_i2c_dev *dev;
+@@ -328,7 +328,7 @@ const struct pci_device_id *id)
+ 	return r;
+ }
+ 
+-static void __devexit i2c_dw_pci_remove(struct pci_dev *pdev)
++static void i2c_dw_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct dw_i2c_dev *dev = pci_get_drvdata(pdev);
+ 
+@@ -368,7 +368,7 @@ static struct pci_driver dw_i2c_driver = {
+ 	.name		= DRIVER_NAME,
+ 	.id_table	= i2_designware_pci_ids,
+ 	.probe		= i2c_dw_pci_probe,
+-	.remove		= __devexit_p(i2c_dw_pci_remove),
++	.remove		= i2c_dw_pci_remove,
+ 	.driver         = {
+ 		.pm     = &i2c_dw_pm_ops,
+ 	},
+diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
+index 0506fef8dc00..343357a2b5b4 100644
+--- a/drivers/i2c/busses/i2c-designware-platdrv.c
++++ b/drivers/i2c/busses/i2c-designware-platdrv.c
+@@ -50,7 +50,7 @@ static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
+ 	return clk_get_rate(dev->clk)/1000;
+ }
+ 
+-static int __devinit dw_i2c_probe(struct platform_device *pdev)
++static int dw_i2c_probe(struct platform_device *pdev)
+ {
+ 	struct dw_i2c_dev *dev;
+ 	struct i2c_adapter *adap;
+@@ -169,7 +169,7 @@ static int __devinit dw_i2c_probe(struct platform_device *pdev)
+ 	return r;
+ }
+ 
+-static int __devexit dw_i2c_remove(struct platform_device *pdev)
++static int dw_i2c_remove(struct platform_device *pdev)
+ {
+ 	struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
+ 	struct resource *mem;
+@@ -228,7 +228,7 @@ static SIMPLE_DEV_PM_OPS(dw_i2c_dev_pm_ops, dw_i2c_suspend, dw_i2c_resume);
+ MODULE_ALIAS("platform:i2c_designware");
+ 
+ static struct platform_driver dw_i2c_driver = {
+-	.remove		= __devexit_p(dw_i2c_remove),
++	.remove		= dw_i2c_remove,
+ 	.driver		= {
+ 		.name	= "i2c_designware",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/i2c/busses/i2c-eg20t.c b/drivers/i2c/busses/i2c-eg20t.c
+index 259f7697bf25..5e7886e7136e 100644
+--- a/drivers/i2c/busses/i2c-eg20t.c
++++ b/drivers/i2c/busses/i2c-eg20t.c
+@@ -758,7 +758,7 @@ static void pch_i2c_disbl_int(struct i2c_algo_pch_data *adap)
+ 	iowrite32(BUFFER_MODE_INTR_DISBL, p + PCH_I2CBUFMSK);
+ }
+ 
+-static int __devinit pch_i2c_probe(struct pci_dev *pdev,
++static int pch_i2c_probe(struct pci_dev *pdev,
+ 				   const struct pci_device_id *id)
+ {
+ 	void __iomem *base_addr;
+@@ -851,7 +851,7 @@ static int __devinit pch_i2c_probe(struct pci_dev *pdev,
+ 	return ret;
+ }
+ 
+-static void __devexit pch_i2c_remove(struct pci_dev *pdev)
++static void pch_i2c_remove(struct pci_dev *pdev)
+ {
+ 	int i;
+ 	struct adapter_info *adap_info = pci_get_drvdata(pdev);
+@@ -948,7 +948,7 @@ static struct pci_driver pch_pcidriver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = pch_pcidev_id,
+ 	.probe = pch_i2c_probe,
+-	.remove = __devexit_p(pch_i2c_remove),
++	.remove = pch_i2c_remove,
+ 	.suspend = pch_i2c_suspend,
+ 	.resume = pch_i2c_resume
+ };
+diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c
+index 37e2e82a9c88..485497066ed7 100644
+--- a/drivers/i2c/busses/i2c-elektor.c
++++ b/drivers/i2c/busses/i2c-elektor.c
+@@ -205,7 +205,7 @@ static struct i2c_adapter pcf_isa_ops = {
+ 	.name		= "i2c-elektor",
+ };
+ 
+-static int __devinit elektor_match(struct device *dev, unsigned int id)
++static int elektor_match(struct device *dev, unsigned int id)
+ {
+ #ifdef __alpha__
+ 	/* check to see we have memory mapped PCF8584 connected to the
+@@ -264,7 +264,7 @@ static int __devinit elektor_match(struct device *dev, unsigned int id)
+ 	return 1;
+ }
+ 
+-static int __devinit elektor_probe(struct device *dev, unsigned int id)
++static int elektor_probe(struct device *dev, unsigned int id)
+ {
+ 	init_waitqueue_head(&pcf_wait);
+ 	if (pcf_isa_init())
+@@ -293,7 +293,7 @@ static int __devinit elektor_probe(struct device *dev, unsigned int id)
+ 	return -ENODEV;
+ }
+ 
+-static int __devexit elektor_remove(struct device *dev, unsigned int id)
++static int elektor_remove(struct device *dev, unsigned int id)
+ {
+ 	i2c_del_adapter(&pcf_isa_ops);
+ 
+@@ -316,7 +316,7 @@ static int __devexit elektor_remove(struct device *dev, unsigned int id)
+ static struct isa_driver i2c_elektor_driver = {
+ 	.match		= elektor_match,
+ 	.probe		= elektor_probe,
+-	.remove		= __devexit_p(elektor_remove),
++	.remove		= elektor_remove,
+ 	.driver = {
+ 		.owner	= THIS_MODULE,
+ 		.name	= "i2c-elektor",
+diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
+index 257299a92df3..f3fa4332bbdf 100644
+--- a/drivers/i2c/busses/i2c-gpio.c
++++ b/drivers/i2c/busses/i2c-gpio.c
+@@ -85,7 +85,7 @@ static int i2c_gpio_getscl(void *data)
+ 	return gpio_get_value(pdata->scl_pin);
+ }
+ 
+-static int __devinit of_i2c_gpio_probe(struct device_node *np,
++static int of_i2c_gpio_probe(struct device_node *np,
+ 			     struct i2c_gpio_platform_data *pdata)
+ {
+ 	u32 reg;
+@@ -117,7 +117,7 @@ static int __devinit of_i2c_gpio_probe(struct device_node *np,
+ 	return 0;
+ }
+ 
+-static int __devinit i2c_gpio_probe(struct platform_device *pdev)
++static int i2c_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct i2c_gpio_private_data *priv;
+ 	struct i2c_gpio_platform_data *pdata;
+@@ -218,7 +218,7 @@ static int __devinit i2c_gpio_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit i2c_gpio_remove(struct platform_device *pdev)
++static int i2c_gpio_remove(struct platform_device *pdev)
+ {
+ 	struct i2c_gpio_private_data *priv;
+ 	struct i2c_gpio_platform_data *pdata;
+@@ -251,7 +251,7 @@ static struct platform_driver i2c_gpio_driver = {
+ 		.of_match_table	= of_match_ptr(i2c_gpio_dt_ids),
+ 	},
+ 	.probe		= i2c_gpio_probe,
+-	.remove		= __devexit_p(i2c_gpio_remove),
++	.remove		= i2c_gpio_remove,
+ };
+ 
+ static int __init i2c_gpio_init(void)
+diff --git a/drivers/i2c/busses/i2c-highlander.c b/drivers/i2c/busses/i2c-highlander.c
+index 19515df61021..3351cc7ed11f 100644
+--- a/drivers/i2c/busses/i2c-highlander.c
++++ b/drivers/i2c/busses/i2c-highlander.c
+@@ -356,7 +356,7 @@ static const struct i2c_algorithm highlander_i2c_algo = {
+ 	.functionality	= highlander_i2c_func,
+ };
+ 
+-static int __devinit highlander_i2c_probe(struct platform_device *pdev)
++static int highlander_i2c_probe(struct platform_device *pdev)
+ {
+ 	struct highlander_i2c_dev *dev;
+ 	struct i2c_adapter *adap;
+@@ -441,7 +441,7 @@ static int __devinit highlander_i2c_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit highlander_i2c_remove(struct platform_device *pdev)
++static int highlander_i2c_remove(struct platform_device *pdev)
+ {
+ 	struct highlander_i2c_dev *dev = platform_get_drvdata(pdev);
+ 
+@@ -465,7 +465,7 @@ static struct platform_driver highlander_i2c_driver = {
+ 	},
+ 
+ 	.probe		= highlander_i2c_probe,
+-	.remove		= __devexit_p(highlander_i2c_remove),
++	.remove		= highlander_i2c_remove,
+ };
+ 
+ module_platform_driver(highlander_i2c_driver);
+diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c
+index c9f95e1666a8..79c3d9069a48 100644
+--- a/drivers/i2c/busses/i2c-hydra.c
++++ b/drivers/i2c/busses/i2c-hydra.c
+@@ -112,7 +112,7 @@ static DEFINE_PCI_DEVICE_TABLE(hydra_ids) = {
+ 
+ MODULE_DEVICE_TABLE (pci, hydra_ids);
+ 
+-static int __devinit hydra_probe(struct pci_dev *dev,
++static int hydra_probe(struct pci_dev *dev,
+ 				 const struct pci_device_id *id)
+ {
+ 	unsigned long base = pci_resource_start(dev, 0);
+@@ -139,7 +139,7 @@ static int __devinit hydra_probe(struct pci_dev *dev,
+ 	return 0;
+ }
+ 
+-static void __devexit hydra_remove(struct pci_dev *dev)
++static void hydra_remove(struct pci_dev *dev)
+ {
+ 	pdregw(hydra_bit_data.data, 0);		/* clear SCLK_OE and SDAT_OE */
+ 	i2c_del_adapter(&hydra_adap);
+@@ -153,7 +153,7 @@ static struct pci_driver hydra_driver = {
+ 	.name		= "hydra_smbus",
+ 	.id_table	= hydra_ids,
+ 	.probe		= hydra_probe,
+-	.remove		= __devexit_p(hydra_remove),
++	.remove		= hydra_remove,
+ };
+ 
+ module_pci_driver(hydra_driver);
+diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
+index 1e73638225e1..3092387f6ef4 100644
+--- a/drivers/i2c/busses/i2c-i801.c
++++ b/drivers/i2c/busses/i2c-i801.c
+@@ -841,14 +841,14 @@ struct dmi_onboard_device_info {
+ 	const char *i2c_type;
+ };
+ 
+-static struct dmi_onboard_device_info __devinitdata dmi_devices[] = {
++static const struct dmi_onboard_device_info dmi_devices[] = {
+ 	{ "Syleus", DMI_DEV_TYPE_OTHER, 0x73, "fscsyl" },
+ 	{ "Hermes", DMI_DEV_TYPE_OTHER, 0x73, "fscher" },
+ 	{ "Hades",  DMI_DEV_TYPE_OTHER, 0x73, "fschds" },
+ };
+ 
+-static void __devinit dmi_check_onboard_device(u8 type, const char *name,
+-					       struct i2c_adapter *adap)
++static void dmi_check_onboard_device(u8 type, const char *name,
++				     struct i2c_adapter *adap)
+ {
+ 	int i;
+ 	struct i2c_board_info info;
+@@ -871,8 +871,7 @@ static void __devinit dmi_check_onboard_device(u8 type, const char *name,
+ /* We use our own function to check for onboard devices instead of
+    dmi_find_device() as some buggy BIOS's have the devices we are interested
+    in marked as disabled */
+-static void __devinit dmi_check_onboard_devices(const struct dmi_header *dm,
+-						void *adap)
++static void dmi_check_onboard_devices(const struct dmi_header *dm, void *adap)
+ {
+ 	int i, count;
+ 
+@@ -901,7 +900,7 @@ static void __devinit dmi_check_onboard_devices(const struct dmi_header *dm,
+ }
+ 
+ /* Register optional slaves */
+-static void __devinit i801_probe_optional_slaves(struct i801_priv *priv)
++static void i801_probe_optional_slaves(struct i801_priv *priv)
+ {
+ 	/* Only register slaves on main SMBus channel */
+ 	if (priv->features & FEATURE_IDF)
+@@ -921,7 +920,7 @@ static void __devinit i801_probe_optional_slaves(struct i801_priv *priv)
+ }
+ #else
+ static void __init input_apanel_init(void) {}
+-static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) {}
++static void i801_probe_optional_slaves(struct i801_priv *priv) {}
+ #endif	/* CONFIG_X86 && CONFIG_DMI */
+ 
+ #if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
+@@ -944,7 +943,7 @@ static struct i801_mux_config i801_mux_config_asus_z8_d18 = {
+ 	.n_gpios = 2,
+ };
+ 
+-static struct dmi_system_id __devinitdata mux_dmi_table[] = {
++static const struct dmi_system_id mux_dmi_table[] = {
+ 	{
+ 		.matches = {
+ 			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+@@ -1012,7 +1011,7 @@ static struct dmi_system_id __devinitdata mux_dmi_table[] = {
+ };
+ 
+ /* Setup multiplexing if needed */
+-static int __devinit i801_add_mux(struct i801_priv *priv)
++static int i801_add_mux(struct i801_priv *priv)
+ {
+ 	struct device *dev = &priv->adapter.dev;
+ 	const struct i801_mux_config *mux_config;
+@@ -1048,13 +1047,13 @@ static int __devinit i801_add_mux(struct i801_priv *priv)
+ 	return 0;
+ }
+ 
+-static void __devexit i801_del_mux(struct i801_priv *priv)
++static void i801_del_mux(struct i801_priv *priv)
+ {
+ 	if (priv->mux_pdev)
+ 		platform_device_unregister(priv->mux_pdev);
+ }
+ 
+-static unsigned int __devinit i801_get_adapter_class(struct i801_priv *priv)
++static unsigned int i801_get_adapter_class(struct i801_priv *priv)
+ {
+ 	const struct dmi_system_id *id;
+ 	const struct i801_mux_config *mux_config;
+@@ -1084,8 +1083,7 @@ static inline unsigned int i801_get_adapter_class(struct i801_priv *priv)
+ }
+ #endif
+ 
+-static int __devinit i801_probe(struct pci_dev *dev,
+-				const struct pci_device_id *id)
++static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	unsigned char temp;
+ 	int err, i;
+@@ -1226,7 +1224,7 @@ static int __devinit i801_probe(struct pci_dev *dev,
+ 	return err;
+ }
+ 
+-static void __devexit i801_remove(struct pci_dev *dev)
++static void i801_remove(struct pci_dev *dev)
+ {
+ 	struct i801_priv *priv = pci_get_drvdata(dev);
+ 
+@@ -1272,7 +1270,7 @@ static struct pci_driver i801_driver = {
+ 	.name		= "i801_smbus",
+ 	.id_table	= i801_ids,
+ 	.probe		= i801_probe,
+-	.remove		= __devexit_p(i801_remove),
++	.remove		= i801_remove,
+ 	.suspend	= i801_suspend,
+ 	.resume		= i801_resume,
+ };
+diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
+index 806e225f3de7..33a2abb6c063 100644
+--- a/drivers/i2c/busses/i2c-ibm_iic.c
++++ b/drivers/i2c/busses/i2c-ibm_iic.c
+@@ -660,7 +660,7 @@ static inline u8 iic_clckdiv(unsigned int opb)
+ 	return (u8)((opb + 9) / 10 - 1);
+ }
+ 
+-static int __devinit iic_request_irq(struct platform_device *ofdev,
++static int iic_request_irq(struct platform_device *ofdev,
+ 				     struct ibm_iic_private *dev)
+ {
+ 	struct device_node *np = ofdev->dev.of_node;
+@@ -691,7 +691,7 @@ static int __devinit iic_request_irq(struct platform_device *ofdev,
+ /*
+  * Register single IIC interface
+  */
+-static int __devinit iic_probe(struct platform_device *ofdev)
++static int iic_probe(struct platform_device *ofdev)
+ {
+ 	struct device_node *np = ofdev->dev.of_node;
+ 	struct ibm_iic_private *dev;
+@@ -781,7 +781,7 @@ static int __devinit iic_probe(struct platform_device *ofdev)
+ /*
+  * Cleanup initialized IIC interface
+  */
+-static int __devexit iic_remove(struct platform_device *ofdev)
++static int iic_remove(struct platform_device *ofdev)
+ {
+ 	struct ibm_iic_private *dev = dev_get_drvdata(&ofdev->dev);
+ 
+@@ -812,7 +812,7 @@ static struct platform_driver ibm_iic_driver = {
+ 		.of_match_table = ibm_iic_match,
+ 	},
+ 	.probe	= iic_probe,
+-	.remove	= __devexit_p(iic_remove),
++	.remove	= iic_remove,
+ };
+ 
+ module_platform_driver(ibm_iic_driver);
+diff --git a/drivers/i2c/busses/i2c-intel-mid.c b/drivers/i2c/busses/i2c-intel-mid.c
+index 7c28f10f95ca..de3736bf6465 100644
+--- a/drivers/i2c/busses/i2c-intel-mid.c
++++ b/drivers/i2c/busses/i2c-intel-mid.c
+@@ -947,7 +947,7 @@ static const struct dev_pm_ops intel_mid_i2c_pm_ops = {
+  * 5. Call intel_mid_i2c_hwinit() for hardware initialization
+  * 6. Register I2C adapter in i2c-core
+  */
+-static int __devinit intel_mid_i2c_probe(struct pci_dev *dev,
++static int intel_mid_i2c_probe(struct pci_dev *dev,
+ 				    const struct pci_device_id *id)
+ {
+ 	struct intel_mid_i2c_private *mrst;
+@@ -1079,7 +1079,7 @@ static int __devinit intel_mid_i2c_probe(struct pci_dev *dev,
+ 	return err;
+ }
+ 
+-static void __devexit intel_mid_i2c_remove(struct pci_dev *dev)
++static void intel_mid_i2c_remove(struct pci_dev *dev)
+ {
+ 	struct intel_mid_i2c_private *mrst = pci_get_drvdata(dev);
+ 	intel_mid_i2c_disable(&mrst->adap);
+@@ -1113,7 +1113,7 @@ static struct pci_driver intel_mid_i2c_driver = {
+ 	.name		= DRIVER_NAME,
+ 	.id_table	= intel_mid_i2c_ids,
+ 	.probe		= intel_mid_i2c_probe,
+-	.remove		= __devexit_p(intel_mid_i2c_remove),
++	.remove		= intel_mid_i2c_remove,
+ };
+ 
+ module_pci_driver(intel_mid_i2c_driver);
+diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c
+index f90a6057508d..4099f79c2280 100644
+--- a/drivers/i2c/busses/i2c-isch.c
++++ b/drivers/i2c/busses/i2c-isch.c
+@@ -249,7 +249,7 @@ static struct i2c_adapter sch_adapter = {
+ 	.algo		= &smbus_algorithm,
+ };
+ 
+-static int __devinit smbus_sch_probe(struct platform_device *dev)
++static int smbus_sch_probe(struct platform_device *dev)
+ {
+ 	struct resource *res;
+ 	int retval;
+@@ -284,7 +284,7 @@ static int __devinit smbus_sch_probe(struct platform_device *dev)
+ 	return retval;
+ }
+ 
+-static int __devexit smbus_sch_remove(struct platform_device *pdev)
++static int smbus_sch_remove(struct platform_device *pdev)
+ {
+ 	struct resource *res;
+ 	if (sch_smba) {
+@@ -303,7 +303,7 @@ static struct platform_driver smbus_sch_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe		= smbus_sch_probe,
+-	.remove		= __devexit_p(smbus_sch_remove),
++	.remove		= smbus_sch_remove,
+ };
+ 
+ module_platform_driver(smbus_sch_driver);
+diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
+index ca86430cb4a2..a69459e5c3f3 100644
+--- a/drivers/i2c/busses/i2c-mpc.c
++++ b/drivers/i2c/busses/i2c-mpc.c
+@@ -175,7 +175,7 @@ static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
+ }
+ 
+ #if defined(CONFIG_PPC_MPC52xx) || defined(CONFIG_PPC_MPC512x)
+-static const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] __devinitconst = {
++static const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] = {
+ 	{20, 0x20}, {22, 0x21}, {24, 0x22}, {26, 0x23},
+ 	{28, 0x24}, {30, 0x01}, {32, 0x25}, {34, 0x02},
+ 	{36, 0x26}, {40, 0x27}, {44, 0x04}, {48, 0x28},
+@@ -196,7 +196,7 @@ static const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] __devinitconst = {
+ 	{10240, 0x9d}, {12288, 0x9e}, {15360, 0x9f}
+ };
+ 
+-static int __devinit mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock,
++static int mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock,
+ 					  int prescaler, u32 *real_clk)
+ {
+ 	const struct mpc_i2c_divider *div = NULL;
+@@ -230,7 +230,7 @@ static int __devinit mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock,
+ 	return (int)div->fdr;
+ }
+ 
+-static void __devinit mpc_i2c_setup_52xx(struct device_node *node,
++static void mpc_i2c_setup_52xx(struct device_node *node,
+ 					 struct mpc_i2c *i2c,
+ 					 u32 clock, u32 prescaler)
+ {
+@@ -252,7 +252,7 @@ static void __devinit mpc_i2c_setup_52xx(struct device_node *node,
+ 			 fdr);
+ }
+ #else /* !(CONFIG_PPC_MPC52xx || CONFIG_PPC_MPC512x) */
+-static void __devinit mpc_i2c_setup_52xx(struct device_node *node,
++static void mpc_i2c_setup_52xx(struct device_node *node,
+ 					 struct mpc_i2c *i2c,
+ 					 u32 clock, u32 prescaler)
+ {
+@@ -260,7 +260,7 @@ static void __devinit mpc_i2c_setup_52xx(struct device_node *node,
+ #endif /* CONFIG_PPC_MPC52xx || CONFIG_PPC_MPC512x */
+ 
+ #ifdef CONFIG_PPC_MPC512x
+-static void __devinit mpc_i2c_setup_512x(struct device_node *node,
++static void mpc_i2c_setup_512x(struct device_node *node,
+ 					 struct mpc_i2c *i2c,
+ 					 u32 clock, u32 prescaler)
+ {
+@@ -288,7 +288,7 @@ static void __devinit mpc_i2c_setup_512x(struct device_node *node,
+ 	mpc_i2c_setup_52xx(node, i2c, clock, prescaler);
+ }
+ #else /* CONFIG_PPC_MPC512x */
+-static void __devinit mpc_i2c_setup_512x(struct device_node *node,
++static void mpc_i2c_setup_512x(struct device_node *node,
+ 					 struct mpc_i2c *i2c,
+ 					 u32 clock, u32 prescaler)
+ {
+@@ -296,7 +296,7 @@ static void __devinit mpc_i2c_setup_512x(struct device_node *node,
+ #endif /* CONFIG_PPC_MPC512x */
+ 
+ #ifdef CONFIG_FSL_SOC
+-static const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] __devinitconst = {
++static const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] = {
+ 	{160, 0x0120}, {192, 0x0121}, {224, 0x0122}, {256, 0x0123},
+ 	{288, 0x0100}, {320, 0x0101}, {352, 0x0601}, {384, 0x0102},
+ 	{416, 0x0602}, {448, 0x0126}, {480, 0x0103}, {512, 0x0127},
+@@ -316,7 +316,7 @@ static const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] __devinitconst = {
+ 	{49152, 0x011e}, {61440, 0x011f}
+ };
+ 
+-static u32 __devinit mpc_i2c_get_sec_cfg_8xxx(void)
++static u32 mpc_i2c_get_sec_cfg_8xxx(void)
+ {
+ 	struct device_node *node = NULL;
+ 	u32 __iomem *reg;
+@@ -345,7 +345,7 @@ static u32 __devinit mpc_i2c_get_sec_cfg_8xxx(void)
+ 	return val;
+ }
+ 
+-static int __devinit mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock,
++static int mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock,
+ 					  u32 prescaler, u32 *real_clk)
+ {
+ 	const struct mpc_i2c_divider *div = NULL;
+@@ -383,7 +383,7 @@ static int __devinit mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock,
+ 	return div ? (int)div->fdr : -EINVAL;
+ }
+ 
+-static void __devinit mpc_i2c_setup_8xxx(struct device_node *node,
++static void mpc_i2c_setup_8xxx(struct device_node *node,
+ 					 struct mpc_i2c *i2c,
+ 					 u32 clock, u32 prescaler)
+ {
+@@ -408,7 +408,7 @@ static void __devinit mpc_i2c_setup_8xxx(struct device_node *node,
+ }
+ 
+ #else /* !CONFIG_FSL_SOC */
+-static void __devinit mpc_i2c_setup_8xxx(struct device_node *node,
++static void mpc_i2c_setup_8xxx(struct device_node *node,
+ 					 struct mpc_i2c *i2c,
+ 					 u32 clock, u32 prescaler)
+ {
+@@ -615,7 +615,7 @@ static struct i2c_adapter mpc_ops = {
+ };
+ 
+ static const struct of_device_id mpc_i2c_of_match[];
+-static int __devinit fsl_i2c_probe(struct platform_device *op)
++static int fsl_i2c_probe(struct platform_device *op)
+ {
+ 	const struct of_device_id *match;
+ 	struct mpc_i2c *i2c;
+@@ -706,7 +706,7 @@ static int __devinit fsl_i2c_probe(struct platform_device *op)
+ 	return result;
+ };
+ 
+-static int __devexit fsl_i2c_remove(struct platform_device *op)
++static int fsl_i2c_remove(struct platform_device *op)
+ {
+ 	struct mpc_i2c *i2c = dev_get_drvdata(&op->dev);
+ 
+@@ -746,24 +746,24 @@ static int mpc_i2c_resume(struct device *dev)
+ SIMPLE_DEV_PM_OPS(mpc_i2c_pm_ops, mpc_i2c_suspend, mpc_i2c_resume);
+ #endif
+ 
+-static const struct mpc_i2c_data mpc_i2c_data_512x __devinitdata = {
++static const struct mpc_i2c_data mpc_i2c_data_512x = {
+ 	.setup = mpc_i2c_setup_512x,
+ };
+ 
+-static const struct mpc_i2c_data mpc_i2c_data_52xx __devinitdata = {
++static const struct mpc_i2c_data mpc_i2c_data_52xx = {
+ 	.setup = mpc_i2c_setup_52xx,
+ };
+ 
+-static const struct mpc_i2c_data mpc_i2c_data_8313 __devinitdata = {
++static const struct mpc_i2c_data mpc_i2c_data_8313 = {
+ 	.setup = mpc_i2c_setup_8xxx,
+ };
+ 
+-static const struct mpc_i2c_data mpc_i2c_data_8543 __devinitdata = {
++static const struct mpc_i2c_data mpc_i2c_data_8543 = {
+ 	.setup = mpc_i2c_setup_8xxx,
+ 	.prescaler = 2,
+ };
+ 
+-static const struct mpc_i2c_data mpc_i2c_data_8544 __devinitdata = {
++static const struct mpc_i2c_data mpc_i2c_data_8544 = {
+ 	.setup = mpc_i2c_setup_8xxx,
+ 	.prescaler = 3,
+ };
+@@ -785,7 +785,7 @@ MODULE_DEVICE_TABLE(of, mpc_i2c_of_match);
+ /* Structure for a device driver */
+ static struct platform_driver mpc_i2c_driver = {
+ 	.probe		= fsl_i2c_probe,
+-	.remove		= __devexit_p(fsl_i2c_remove),
++	.remove		= fsl_i2c_remove,
+ 	.driver = {
+ 		.owner = THIS_MODULE,
+ 		.name = DRV_NAME,
+diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
+index 2e9d56719e99..8b20ef8524ac 100644
+--- a/drivers/i2c/busses/i2c-mv64xxx.c
++++ b/drivers/i2c/busses/i2c-mv64xxx.c
+@@ -495,7 +495,7 @@ static const struct i2c_algorithm mv64xxx_i2c_algo = {
+  *
+  *****************************************************************************
+  */
+-static int __devinit
++static int
+ mv64xxx_i2c_map_regs(struct platform_device *pd,
+ 	struct mv64xxx_i2c_data *drv_data)
+ {
+@@ -530,13 +530,13 @@ mv64xxx_i2c_unmap_regs(struct mv64xxx_i2c_data *drv_data)
+ }
+ 
+ #ifdef CONFIG_OF
+-static int __devinit
++static int
+ mv64xxx_calc_freq(const int tclk, const int n, const int m)
+ {
+ 	return tclk / (10 * (m + 1) * (2 << n));
+ }
+ 
+-static bool __devinit
++static bool
+ mv64xxx_find_baud_factors(const u32 req_freq, const u32 tclk, u32 *best_n,
+ 			  u32 *best_m)
+ {
+@@ -560,7 +560,7 @@ mv64xxx_find_baud_factors(const u32 req_freq, const u32 tclk, u32 *best_n,
+ 	return true;
+ }
+ 
+-static int __devinit
++static int
+ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
+ 		  struct device_node *np)
+ {
+@@ -597,7 +597,7 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
+ #endif
+ }
+ #else /* CONFIG_OF */
+-static int __devinit
++static int
+ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
+ 		  struct device_node *np)
+ {
+@@ -605,7 +605,7 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
+ }
+ #endif /* CONFIG_OF */
+ 
+-static int __devinit
++static int
+ mv64xxx_i2c_probe(struct platform_device *pd)
+ {
+ 	struct mv64xxx_i2c_data		*drv_data;
+@@ -697,7 +697,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
+ 	return rc;
+ }
+ 
+-static int __devexit
++static int
+ mv64xxx_i2c_remove(struct platform_device *dev)
+ {
+ 	struct mv64xxx_i2c_data		*drv_data = platform_get_drvdata(dev);
+@@ -718,7 +718,7 @@ mv64xxx_i2c_remove(struct platform_device *dev)
+ 	return rc;
+ }
+ 
+-static const struct of_device_id mv64xxx_i2c_of_match_table[] __devinitdata = {
++static const struct of_device_id mv64xxx_i2c_of_match_table[] = {
+ 	{ .compatible = "marvell,mv64xxx-i2c", },
+ 	{}
+ };
+@@ -726,7 +726,7 @@ MODULE_DEVICE_TABLE(of, mv64xxx_i2c_of_match_table);
+ 
+ static struct platform_driver mv64xxx_i2c_driver = {
+ 	.probe	= mv64xxx_i2c_probe,
+-	.remove	= __devexit_p(mv64xxx_i2c_remove),
++	.remove	= mv64xxx_i2c_remove,
+ 	.driver	= {
+ 		.owner	= THIS_MODULE,
+ 		.name	= MV64XXX_I2C_CTLR_NAME,
+diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
+index 6ed53da9e1f4..1b1a936eccc9 100644
+--- a/drivers/i2c/busses/i2c-mxs.c
++++ b/drivers/i2c/busses/i2c-mxs.c
+@@ -432,7 +432,7 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
+ 	return 0;
+ }
+ 
+-static int __devinit mxs_i2c_probe(struct platform_device *pdev)
++static int mxs_i2c_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	struct mxs_i2c_dev *i2c;
+@@ -515,7 +515,7 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit mxs_i2c_remove(struct platform_device *pdev)
++static int mxs_i2c_remove(struct platform_device *pdev)
+ {
+ 	struct mxs_i2c_dev *i2c = platform_get_drvdata(pdev);
+ 	int ret;
+@@ -546,7 +546,7 @@ static struct platform_driver mxs_i2c_driver = {
+ 		   .owner = THIS_MODULE,
+ 		   .of_match_table = mxs_i2c_dt_ids,
+ 		   },
+-	.remove = __devexit_p(mxs_i2c_remove),
++	.remove = mxs_i2c_remove,
+ };
+ 
+ static int __init mxs_i2c_init(void)
+diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
+index 392303b4be07..adac8542771d 100644
+--- a/drivers/i2c/busses/i2c-nforce2.c
++++ b/drivers/i2c/busses/i2c-nforce2.c
+@@ -117,7 +117,7 @@ struct nforce2_smbus {
+ #define MAX_TIMEOUT	100
+ 
+ /* We disable the second SMBus channel on these boards */
+-static struct dmi_system_id __devinitdata nforce2_dmi_blacklist2[] = {
++static const struct dmi_system_id nforce2_dmi_blacklist2[] = {
+ 	{
+ 		.ident = "DFI Lanparty NF4 Expert",
+ 		.matches = {
+@@ -330,8 +330,8 @@ static DEFINE_PCI_DEVICE_TABLE(nforce2_ids) = {
+ MODULE_DEVICE_TABLE (pci, nforce2_ids);
+ 
+ 
+-static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar,
+-	int alt_reg, struct nforce2_smbus *smbus, const char *name)
++static int nforce2_probe_smb(struct pci_dev *dev, int bar, int alt_reg,
++			     struct nforce2_smbus *smbus, const char *name)
+ {
+ 	int error;
+ 
+@@ -382,7 +382,7 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar,
+ }
+ 
+ 
+-static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_id *id)
++static int nforce2_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	struct nforce2_smbus *smbuses;
+ 	int res1, res2;
+@@ -430,7 +430,7 @@ static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_
+ }
+ 
+ 
+-static void __devexit nforce2_remove(struct pci_dev *dev)
++static void nforce2_remove(struct pci_dev *dev)
+ {
+ 	struct nforce2_smbus *smbuses = pci_get_drvdata(dev);
+ 
+@@ -450,7 +450,7 @@ static struct pci_driver nforce2_driver = {
+ 	.name		= "nForce2_smbus",
+ 	.id_table	= nforce2_ids,
+ 	.probe		= nforce2_probe,
+-	.remove		= __devexit_p(nforce2_remove),
++	.remove		= nforce2_remove,
+ };
+ 
+ module_pci_driver(nforce2_driver);
+diff --git a/drivers/i2c/busses/i2c-nuc900.c b/drivers/i2c/busses/i2c-nuc900.c
+index a23b91b0b738..865ee350adb3 100644
+--- a/drivers/i2c/busses/i2c-nuc900.c
++++ b/drivers/i2c/busses/i2c-nuc900.c
+@@ -518,7 +518,7 @@ static const struct i2c_algorithm nuc900_i2c_algorithm = {
+  * called by the bus driver when a suitable device is found
+ */
+ 
+-static int __devinit nuc900_i2c_probe(struct platform_device *pdev)
++static int nuc900_i2c_probe(struct platform_device *pdev)
+ {
+ 	struct nuc900_i2c *i2c;
+ 	struct nuc900_platform_i2c *pdata;
+@@ -663,7 +663,7 @@ static int __devinit nuc900_i2c_probe(struct platform_device *pdev)
+  * called when device is removed from the bus
+ */
+ 
+-static int __devexit nuc900_i2c_remove(struct platform_device *pdev)
++static int nuc900_i2c_remove(struct platform_device *pdev)
+ {
+ 	struct nuc900_i2c *i2c = platform_get_drvdata(pdev);
+ 
+@@ -684,7 +684,7 @@ static int __devexit nuc900_i2c_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver nuc900_i2c_driver = {
+ 	.probe		= nuc900_i2c_probe,
+-	.remove		= __devexit_p(nuc900_i2c_remove),
++	.remove		= nuc900_i2c_remove,
+ 	.driver		= {
+ 		.owner	= THIS_MODULE,
+ 		.name	= "nuc900-i2c0",
+diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
+index 9b35c9fbb2fe..a873d0ad1acb 100644
+--- a/drivers/i2c/busses/i2c-ocores.c
++++ b/drivers/i2c/busses/i2c-ocores.c
+@@ -343,7 +343,7 @@ static int ocores_i2c_of_probe(struct platform_device *pdev,
+ #define ocores_i2c_of_probe(pdev,i2c) -ENODEV
+ #endif
+ 
+-static int __devinit ocores_i2c_probe(struct platform_device *pdev)
++static int ocores_i2c_probe(struct platform_device *pdev)
+ {
+ 	struct ocores_i2c *i2c;
+ 	struct ocores_i2c_platform_data *pdata;
+@@ -441,7 +441,7 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit ocores_i2c_remove(struct platform_device *pdev)
++static int ocores_i2c_remove(struct platform_device *pdev)
+ {
+ 	struct ocores_i2c *i2c = platform_get_drvdata(pdev);
+ 
+@@ -485,7 +485,7 @@ static SIMPLE_DEV_PM_OPS(ocores_i2c_pm, ocores_i2c_suspend, ocores_i2c_resume);
+ 
+ static struct platform_driver ocores_i2c_driver = {
+ 	.probe   = ocores_i2c_probe,
+-	.remove  = __devexit_p(ocores_i2c_remove),
++	.remove  = ocores_i2c_remove,
+ 	.driver  = {
+ 		.owner = THIS_MODULE,
+ 		.name = "ocores-i2c",
+diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
+index f44c83549fe5..484ca771fdff 100644
+--- a/drivers/i2c/busses/i2c-octeon.c
++++ b/drivers/i2c/busses/i2c-octeon.c
+@@ -446,7 +446,7 @@ static struct i2c_adapter octeon_i2c_ops = {
+ /**
+  * octeon_i2c_setclock - Calculate and set clock divisors.
+  */
+-static int __devinit octeon_i2c_setclock(struct octeon_i2c *i2c)
++static int octeon_i2c_setclock(struct octeon_i2c *i2c)
+ {
+ 	int tclk, thp_base, inc, thp_idx, mdiv_idx, ndiv_idx, foscl, diff;
+ 	int thp = 0x18, mdiv = 2, ndiv = 0, delta_hz = 1000000;
+@@ -489,7 +489,7 @@ static int __devinit octeon_i2c_setclock(struct octeon_i2c *i2c)
+ 	return 0;
+ }
+ 
+-static int __devinit octeon_i2c_initlowlevel(struct octeon_i2c *i2c)
++static int octeon_i2c_initlowlevel(struct octeon_i2c *i2c)
+ {
+ 	u8 status;
+ 	int tries;
+@@ -510,7 +510,7 @@ static int __devinit octeon_i2c_initlowlevel(struct octeon_i2c *i2c)
+ 	return -EIO;
+ }
+ 
+-static int __devinit octeon_i2c_probe(struct platform_device *pdev)
++static int octeon_i2c_probe(struct platform_device *pdev)
+ {
+ 	int irq, result = 0;
+ 	struct octeon_i2c *i2c;
+@@ -609,7 +609,7 @@ static int __devinit octeon_i2c_probe(struct platform_device *pdev)
+ 	return result;
+ };
+ 
+-static int __devexit octeon_i2c_remove(struct platform_device *pdev)
++static int octeon_i2c_remove(struct platform_device *pdev)
+ {
+ 	struct octeon_i2c *i2c = platform_get_drvdata(pdev);
+ 
+@@ -628,7 +628,7 @@ MODULE_DEVICE_TABLE(of, octeon_i2c_match);
+ 
+ static struct platform_driver octeon_i2c_driver = {
+ 	.probe		= octeon_i2c_probe,
+-	.remove		= __devexit_p(octeon_i2c_remove),
++	.remove		= octeon_i2c_remove,
+ 	.driver		= {
+ 		.owner	= THIS_MODULE,
+ 		.name	= DRV_NAME,
+diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
+index 7a62acb7d262..20d41bfa7c19 100644
+--- a/drivers/i2c/busses/i2c-omap.c
++++ b/drivers/i2c/busses/i2c-omap.c
+@@ -1069,7 +1069,7 @@ MODULE_DEVICE_TABLE(of, omap_i2c_of_match);
+ #define OMAP_I2C_SCHEME_0		0
+ #define OMAP_I2C_SCHEME_1		1
+ 
+-static int __devinit
++static int
+ omap_i2c_probe(struct platform_device *pdev)
+ {
+ 	struct omap_i2c_dev	*dev;
+@@ -1267,7 +1267,7 @@ omap_i2c_probe(struct platform_device *pdev)
+ 	return r;
+ }
+ 
+-static int __devexit omap_i2c_remove(struct platform_device *pdev)
++static int omap_i2c_remove(struct platform_device *pdev)
+ {
+ 	struct omap_i2c_dev	*dev = platform_get_drvdata(pdev);
+ 	int ret;
+@@ -1333,7 +1333,7 @@ static struct dev_pm_ops omap_i2c_pm_ops = {
+ 
+ static struct platform_driver omap_i2c_driver = {
+ 	.probe		= omap_i2c_probe,
+-	.remove		= __devexit_p(omap_i2c_remove),
++	.remove		= omap_i2c_remove,
+ 	.driver		= {
+ 		.name	= "omap_i2c",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c
+index 4b95f7a63a3b..aa9577881925 100644
+--- a/drivers/i2c/busses/i2c-parport-light.c
++++ b/drivers/i2c/busses/i2c-parport-light.c
+@@ -135,7 +135,7 @@ static struct lineop parport_ctrl_irq = {
+ 	.port		= PORT_CTRL,
+ };
+ 
+-static int __devinit i2c_parport_probe(struct platform_device *pdev)
++static int i2c_parport_probe(struct platform_device *pdev)
+ {
+ 	int err;
+ 
+@@ -169,7 +169,7 @@ static int __devinit i2c_parport_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit i2c_parport_remove(struct platform_device *pdev)
++static int i2c_parport_remove(struct platform_device *pdev)
+ {
+ 	if (ara) {
+ 		line_set(0, &parport_ctrl_irq);
+@@ -191,7 +191,7 @@ static struct platform_driver i2c_parport_driver = {
+ 		.name	= DRVNAME,
+ 	},
+ 	.probe		= i2c_parport_probe,
+-	.remove		= __devexit_p(i2c_parport_remove),
++	.remove		= i2c_parport_remove,
+ };
+ 
+ static int __init i2c_parport_device_add(u16 address)
+diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c
+index 12edefd4183a..615f632c846f 100644
+--- a/drivers/i2c/busses/i2c-pasemi.c
++++ b/drivers/i2c/busses/i2c-pasemi.c
+@@ -340,7 +340,7 @@ static const struct i2c_algorithm smbus_algorithm = {
+ 	.functionality	= pasemi_smb_func,
+ };
+ 
+-static int __devinit pasemi_smb_probe(struct pci_dev *dev,
++static int pasemi_smb_probe(struct pci_dev *dev,
+ 				      const struct pci_device_id *id)
+ {
+ 	struct pasemi_smbus *smbus;
+@@ -392,7 +392,7 @@ static int __devinit pasemi_smb_probe(struct pci_dev *dev,
+ 	return error;
+ }
+ 
+-static void __devexit pasemi_smb_remove(struct pci_dev *dev)
++static void pasemi_smb_remove(struct pci_dev *dev)
+ {
+ 	struct pasemi_smbus *smbus = pci_get_drvdata(dev);
+ 
+@@ -412,7 +412,7 @@ static struct pci_driver pasemi_smb_driver = {
+ 	.name		= "i2c-pasemi",
+ 	.id_table	= pasemi_smb_ids,
+ 	.probe		= pasemi_smb_probe,
+-	.remove		= __devexit_p(pasemi_smb_remove),
++	.remove		= pasemi_smb_remove,
+ };
+ 
+ module_pci_driver(pasemi_smb_driver);
+diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c
+index 29933f87d8fa..323f061a3163 100644
+--- a/drivers/i2c/busses/i2c-pca-isa.c
++++ b/drivers/i2c/busses/i2c-pca-isa.c
+@@ -119,7 +119,7 @@ static struct i2c_adapter pca_isa_ops = {
+ 	.timeout	= HZ,
+ };
+ 
+-static int __devinit pca_isa_match(struct device *dev, unsigned int id)
++static int pca_isa_match(struct device *dev, unsigned int id)
+ {
+ 	int match = base != 0;
+ 
+@@ -132,7 +132,7 @@ static int __devinit pca_isa_match(struct device *dev, unsigned int id)
+ 	return match;
+ }
+ 
+-static int __devinit pca_isa_probe(struct device *dev, unsigned int id)
++static int pca_isa_probe(struct device *dev, unsigned int id)
+ {
+ 	init_waitqueue_head(&pca_wait);
+ 
+@@ -174,7 +174,7 @@ static int __devinit pca_isa_probe(struct device *dev, unsigned int id)
+ 	return -ENODEV;
+ }
+ 
+-static int __devexit pca_isa_remove(struct device *dev, unsigned int id)
++static int pca_isa_remove(struct device *dev, unsigned int id)
+ {
+ 	i2c_del_adapter(&pca_isa_ops);
+ 
+@@ -190,7 +190,7 @@ static int __devexit pca_isa_remove(struct device *dev, unsigned int id)
+ static struct isa_driver pca_isa_driver = {
+ 	.match		= pca_isa_match,
+ 	.probe		= pca_isa_probe,
+-	.remove		= __devexit_p(pca_isa_remove),
++	.remove		= pca_isa_remove,
+ 	.driver = {
+ 		.owner	= THIS_MODULE,
+ 		.name	= DRIVER,
+diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c
+index 675878f49f76..a30d2f613c03 100644
+--- a/drivers/i2c/busses/i2c-pca-platform.c
++++ b/drivers/i2c/busses/i2c-pca-platform.c
+@@ -131,7 +131,7 @@ static irqreturn_t i2c_pca_pf_handler(int this_irq, void *dev_id)
+ }
+ 
+ 
+-static int __devinit i2c_pca_pf_probe(struct platform_device *pdev)
++static int i2c_pca_pf_probe(struct platform_device *pdev)
+ {
+ 	struct i2c_pca_pf_data *i2c;
+ 	struct resource *res;
+@@ -257,7 +257,7 @@ static int __devinit i2c_pca_pf_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit i2c_pca_pf_remove(struct platform_device *pdev)
++static int i2c_pca_pf_remove(struct platform_device *pdev)
+ {
+ 	struct i2c_pca_pf_data *i2c = platform_get_drvdata(pdev);
+ 	platform_set_drvdata(pdev, NULL);
+@@ -279,7 +279,7 @@ static int __devexit i2c_pca_pf_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver i2c_pca_pf_driver = {
+ 	.probe = i2c_pca_pf_probe,
+-	.remove = __devexit_p(i2c_pca_pf_remove),
++	.remove = i2c_pca_pf_remove,
+ 	.driver = {
+ 		.name = "i2c-pca-platform",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
+index f7216ed2f3a9..39ab78c1a02c 100644
+--- a/drivers/i2c/busses/i2c-piix4.c
++++ b/drivers/i2c/busses/i2c-piix4.c
+@@ -99,7 +99,7 @@ MODULE_PARM_DESC(force_addr,
+ static int srvrworks_csb5_delay;
+ static struct pci_driver piix4_driver;
+ 
+-static struct dmi_system_id __devinitdata piix4_dmi_blacklist[] = {
++static const struct dmi_system_id piix4_dmi_blacklist[] = {
+ 	{
+ 		.ident = "Sapphire AM2RD790",
+ 		.matches = {
+@@ -119,7 +119,7 @@ static struct dmi_system_id __devinitdata piix4_dmi_blacklist[] = {
+ 
+ /* The IBM entry is in a separate table because we only check it
+    on Intel-based systems */
+-static struct dmi_system_id __devinitdata piix4_dmi_ibm[] = {
++static const struct dmi_system_id piix4_dmi_ibm[] = {
+ 	{
+ 		.ident = "IBM",
+ 		.matches = { DMI_MATCH(DMI_SYS_VENDOR, "IBM"), },
+@@ -131,8 +131,8 @@ struct i2c_piix4_adapdata {
+ 	unsigned short smba;
+ };
+ 
+-static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
+-				const struct pci_device_id *id)
++static int piix4_setup(struct pci_dev *PIIX4_dev,
++		       const struct pci_device_id *id)
+ {
+ 	unsigned char temp;
+ 	unsigned short piix4_smba;
+@@ -230,8 +230,8 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
+ 	return piix4_smba;
+ }
+ 
+-static int __devinit piix4_setup_sb800(struct pci_dev *PIIX4_dev,
+-				const struct pci_device_id *id)
++static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
++			     const struct pci_device_id *id)
+ {
+ 	unsigned short piix4_smba;
+ 	unsigned short smba_idx = 0xcd6;
+@@ -294,9 +294,9 @@ static int __devinit piix4_setup_sb800(struct pci_dev *PIIX4_dev,
+ 	return piix4_smba;
+ }
+ 
+-static int __devinit piix4_setup_aux(struct pci_dev *PIIX4_dev,
+-				const struct pci_device_id *id,
+-				unsigned short base_reg_addr)
++static int piix4_setup_aux(struct pci_dev *PIIX4_dev,
++			   const struct pci_device_id *id,
++			   unsigned short base_reg_addr)
+ {
+ 	/* Set up auxiliary SMBus controllers found on some
+ 	 * AMD chipsets e.g. SP5100 (SB700 derivative) */
+@@ -540,9 +540,8 @@ MODULE_DEVICE_TABLE (pci, piix4_ids);
+ static struct i2c_adapter *piix4_main_adapter;
+ static struct i2c_adapter *piix4_aux_adapter;
+ 
+-static int __devinit piix4_add_adapter(struct pci_dev *dev,
+-					unsigned short smba,
+-					struct i2c_adapter **padap)
++static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba,
++			     struct i2c_adapter **padap)
+ {
+ 	struct i2c_adapter *adap;
+ 	struct i2c_piix4_adapdata *adapdata;
+@@ -588,8 +587,7 @@ static int __devinit piix4_add_adapter(struct pci_dev *dev,
+ 	return 0;
+ }
+ 
+-static int __devinit piix4_probe(struct pci_dev *dev,
+-				const struct pci_device_id *id)
++static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	int retval;
+ 
+@@ -626,7 +624,7 @@ static int __devinit piix4_probe(struct pci_dev *dev,
+ 	return 0;
+ }
+ 
+-static void __devexit piix4_adap_remove(struct i2c_adapter *adap)
++static void piix4_adap_remove(struct i2c_adapter *adap)
+ {
+ 	struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(adap);
+ 
+@@ -638,7 +636,7 @@ static void __devexit piix4_adap_remove(struct i2c_adapter *adap)
+ 	}
+ }
+ 
+-static void __devexit piix4_remove(struct pci_dev *dev)
++static void piix4_remove(struct pci_dev *dev)
+ {
+ 	if (piix4_main_adapter) {
+ 		piix4_adap_remove(piix4_main_adapter);
+@@ -655,7 +653,7 @@ static struct pci_driver piix4_driver = {
+ 	.name		= "piix4_smbus",
+ 	.id_table	= piix4_ids,
+ 	.probe		= piix4_probe,
+-	.remove		= __devexit_p(piix4_remove),
++	.remove		= piix4_remove,
+ };
+ 
+ module_pci_driver(piix4_driver);
+diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c
+index 3d71395ae1f7..083d68cfaf0b 100644
+--- a/drivers/i2c/busses/i2c-pmcmsp.c
++++ b/drivers/i2c/busses/i2c-pmcmsp.c
+@@ -270,7 +270,7 @@ static irqreturn_t pmcmsptwi_interrupt(int irq, void *ptr)
+ /*
+  * Probe for and register the device and return 0 if there is one.
+  */
+-static int __devinit pmcmsptwi_probe(struct platform_device *pldev)
++static int pmcmsptwi_probe(struct platform_device *pldev)
+ {
+ 	struct resource *res;
+ 	int rc = -ENODEV;
+@@ -368,7 +368,7 @@ static int __devinit pmcmsptwi_probe(struct platform_device *pldev)
+ /*
+  * Release the device and return 0 if there is one.
+  */
+-static int __devexit pmcmsptwi_remove(struct platform_device *pldev)
++static int pmcmsptwi_remove(struct platform_device *pldev)
+ {
+ 	struct resource *res;
+ 
+@@ -628,7 +628,7 @@ static struct i2c_adapter pmcmsptwi_adapter = {
+ 
+ static struct platform_driver pmcmsptwi_driver = {
+ 	.probe  = pmcmsptwi_probe,
+-	.remove	= __devexit_p(pmcmsptwi_remove),
++	.remove	= pmcmsptwi_remove,
+ 	.driver = {
+ 		.name	= DRV_NAME,
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c
+index 8488bddfe465..ce4097012e97 100644
+--- a/drivers/i2c/busses/i2c-pnx.c
++++ b/drivers/i2c/busses/i2c-pnx.c
+@@ -619,7 +619,7 @@ static SIMPLE_DEV_PM_OPS(i2c_pnx_pm,
+ #define PNX_I2C_PM	NULL
+ #endif
+ 
+-static int __devinit i2c_pnx_probe(struct platform_device *pdev)
++static int i2c_pnx_probe(struct platform_device *pdev)
+ {
+ 	unsigned long tmp;
+ 	int ret = 0;
+@@ -765,7 +765,7 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit i2c_pnx_remove(struct platform_device *pdev)
++static int i2c_pnx_remove(struct platform_device *pdev)
+ {
+ 	struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
+ 
+@@ -797,7 +797,7 @@ static struct platform_driver i2c_pnx_driver = {
+ 		.pm = PNX_I2C_PM,
+ 	},
+ 	.probe = i2c_pnx_probe,
+-	.remove = __devexit_p(i2c_pnx_remove),
++	.remove = i2c_pnx_remove,
+ };
+ 
+ static int __init i2c_adap_pnx_init(void)
+diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c
+index 5285f8565de4..0dd5b334d090 100644
+--- a/drivers/i2c/busses/i2c-powermac.c
++++ b/drivers/i2c/busses/i2c-powermac.c
+@@ -210,7 +210,7 @@ static const struct i2c_algorithm i2c_powermac_algorithm = {
+ };
+ 
+ 
+-static int __devexit i2c_powermac_remove(struct platform_device *dev)
++static int i2c_powermac_remove(struct platform_device *dev)
+ {
+ 	struct i2c_adapter	*adapter = platform_get_drvdata(dev);
+ 	int			rc;
+@@ -227,7 +227,7 @@ static int __devexit i2c_powermac_remove(struct platform_device *dev)
+ 	return 0;
+ }
+ 
+-static u32 __devinit i2c_powermac_get_addr(struct i2c_adapter *adap,
++static u32 i2c_powermac_get_addr(struct i2c_adapter *adap,
+ 					   struct pmac_i2c_bus *bus,
+ 					   struct device_node *node)
+ {
+@@ -255,7 +255,7 @@ static u32 __devinit i2c_powermac_get_addr(struct i2c_adapter *adap,
+ 	return 0xffffffff;
+ }
+ 
+-static void __devinit i2c_powermac_create_one(struct i2c_adapter *adap,
++static void i2c_powermac_create_one(struct i2c_adapter *adap,
+ 					      const char *type,
+ 					      u32 addr)
+ {
+@@ -271,7 +271,7 @@ static void __devinit i2c_powermac_create_one(struct i2c_adapter *adap,
+ 			type);
+ }
+ 
+-static void __devinit i2c_powermac_add_missing(struct i2c_adapter *adap,
++static void i2c_powermac_add_missing(struct i2c_adapter *adap,
+ 					       struct pmac_i2c_bus *bus,
+ 					       bool found_onyx)
+ {
+@@ -297,7 +297,7 @@ static void __devinit i2c_powermac_add_missing(struct i2c_adapter *adap,
+ 	}
+ }
+ 
+-static bool __devinit i2c_powermac_get_type(struct i2c_adapter *adap,
++static bool i2c_powermac_get_type(struct i2c_adapter *adap,
+ 					    struct device_node *node,
+ 					    u32 addr, char *type, int type_size)
+ {
+@@ -336,7 +336,7 @@ static bool __devinit i2c_powermac_get_type(struct i2c_adapter *adap,
+ 	return false;
+ }
+ 
+-static void __devinit i2c_powermac_register_devices(struct i2c_adapter *adap,
++static void i2c_powermac_register_devices(struct i2c_adapter *adap,
+ 						    struct pmac_i2c_bus *bus)
+ {
+ 	struct i2c_client *newdev;
+@@ -403,7 +403,7 @@ static void __devinit i2c_powermac_register_devices(struct i2c_adapter *adap,
+ 	i2c_powermac_add_missing(adap, bus, found_onyx);
+ }
+ 
+-static int __devinit i2c_powermac_probe(struct platform_device *dev)
++static int i2c_powermac_probe(struct platform_device *dev)
+ {
+ 	struct pmac_i2c_bus *bus = dev->dev.platform_data;
+ 	struct device_node *parent = NULL;
+@@ -467,7 +467,7 @@ static int __devinit i2c_powermac_probe(struct platform_device *dev)
+ 
+ static struct platform_driver i2c_powermac_driver = {
+ 	.probe = i2c_powermac_probe,
+-	.remove = __devexit_p(i2c_powermac_remove),
++	.remove = i2c_powermac_remove,
+ 	.driver = {
+ 		.name = "i2c-powermac",
+ 		.bus = &platform_bus_type,
+diff --git a/drivers/i2c/busses/i2c-puv3.c b/drivers/i2c/busses/i2c-puv3.c
+index d8515be00b98..d7c512d717a7 100644
+--- a/drivers/i2c/busses/i2c-puv3.c
++++ b/drivers/i2c/busses/i2c-puv3.c
+@@ -184,7 +184,7 @@ static struct i2c_algorithm puv3_i2c_algorithm = {
+ /*
+  * Main initialization routine.
+  */
+-static int __devinit puv3_i2c_probe(struct platform_device *pdev)
++static int puv3_i2c_probe(struct platform_device *pdev)
+ {
+ 	struct i2c_adapter *adapter;
+ 	struct resource *mem;
+@@ -231,7 +231,7 @@ static int __devinit puv3_i2c_probe(struct platform_device *pdev)
+ 	return rc;
+ }
+ 
+-static int __devexit puv3_i2c_remove(struct platform_device *pdev)
++static int puv3_i2c_remove(struct platform_device *pdev)
+ {
+ 	struct i2c_adapter *adapter = platform_get_drvdata(pdev);
+ 	struct resource *mem;
+@@ -276,7 +276,7 @@ static SIMPLE_DEV_PM_OPS(puv3_i2c_pm, puv3_i2c_suspend, NULL);
+ 
+ static struct platform_driver puv3_i2c_driver = {
+ 	.probe		= puv3_i2c_probe,
+-	.remove		= __devexit_p(puv3_i2c_remove),
++	.remove		= puv3_i2c_remove,
+ 	.driver		= {
+ 		.name	= "PKUnity-v3-I2C",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/i2c/busses/i2c-pxa-pci.c b/drivers/i2c/busses/i2c-pxa-pci.c
+index 4dc9bef17d77..3d4985695aed 100644
+--- a/drivers/i2c/busses/i2c-pxa-pci.c
++++ b/drivers/i2c/busses/i2c-pxa-pci.c
+@@ -94,7 +94,7 @@ static struct platform_device *add_i2c_device(struct pci_dev *dev, int bar)
+ 	return ERR_PTR(ret);
+ }
+ 
+-static int __devinit ce4100_i2c_probe(struct pci_dev *dev,
++static int ce4100_i2c_probe(struct pci_dev *dev,
+ 		const struct pci_device_id *ent)
+ {
+ 	int ret;
+@@ -135,7 +135,7 @@ static int __devinit ce4100_i2c_probe(struct pci_dev *dev,
+ 	return ret;
+ }
+ 
+-static void __devexit ce4100_i2c_remove(struct pci_dev *dev)
++static void ce4100_i2c_remove(struct pci_dev *dev)
+ {
+ 	struct ce4100_devices *sds;
+ 	unsigned int i;
+@@ -160,7 +160,7 @@ static struct pci_driver ce4100_i2c_driver = {
+ 	.name           = "ce4100_i2c",
+ 	.id_table       = ce4100_i2c_devices,
+ 	.probe          = ce4100_i2c_probe,
+-	.remove         = __devexit_p(ce4100_i2c_remove),
++	.remove         = ce4100_i2c_remove,
+ };
+ 
+ module_pci_driver(ce4100_i2c_driver);
+diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
+index 72a8071a5556..9bd4d73d29e3 100644
+--- a/drivers/i2c/busses/i2c-rcar.c
++++ b/drivers/i2c/busses/i2c-rcar.c
+@@ -613,7 +613,7 @@ static const struct i2c_algorithm rcar_i2c_algo = {
+ 	.functionality	= rcar_i2c_func,
+ };
+ 
+-static int __devinit rcar_i2c_probe(struct platform_device *pdev)
++static int rcar_i2c_probe(struct platform_device *pdev)
+ {
+ 	struct i2c_rcar_platform_data *pdata = pdev->dev.platform_data;
+ 	struct rcar_i2c_priv *priv;
+@@ -682,7 +682,7 @@ static int __devinit rcar_i2c_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit rcar_i2c_remove(struct platform_device *pdev)
++static int rcar_i2c_remove(struct platform_device *pdev)
+ {
+ 	struct rcar_i2c_priv *priv = platform_get_drvdata(pdev);
+ 	struct device *dev = &pdev->dev;
+@@ -699,7 +699,7 @@ static struct platform_driver rcar_i2c_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= rcar_i2c_probe,
+-	.remove		= __devexit_p(rcar_i2c_remove),
++	.remove		= rcar_i2c_remove,
+ };
+ 
+ module_platform_driver(rcar_i2c_driver);
+diff --git a/drivers/i2c/busses/i2c-s6000.c b/drivers/i2c/busses/i2c-s6000.c
+index b76a29d1f8e4..008836409efe 100644
+--- a/drivers/i2c/busses/i2c-s6000.c
++++ b/drivers/i2c/busses/i2c-s6000.c
+@@ -248,7 +248,7 @@ static struct i2c_algorithm s6i2c_algorithm = {
+ 	.functionality = s6i2c_functionality,
+ };
+ 
+-static u16 __devinit nanoseconds_on_clk(struct s6i2c_if *iface, u32 ns)
++static u16 nanoseconds_on_clk(struct s6i2c_if *iface, u32 ns)
+ {
+ 	u32 dividend = ((clk_get_rate(iface->clk) / 1000) * ns) / 1000000;
+ 	if (dividend > 0xffff)
+@@ -256,7 +256,7 @@ static u16 __devinit nanoseconds_on_clk(struct s6i2c_if *iface, u32 ns)
+ 	return dividend;
+ }
+ 
+-static int __devinit s6i2c_probe(struct platform_device *dev)
++static int s6i2c_probe(struct platform_device *dev)
+ {
+ 	struct s6i2c_if *iface = &s6i2c_if;
+ 	struct i2c_adapter *p_adap;
+@@ -361,7 +361,7 @@ static int __devinit s6i2c_probe(struct platform_device *dev)
+ 	return rc;
+ }
+ 
+-static int __devexit s6i2c_remove(struct platform_device *pdev)
++static int s6i2c_remove(struct platform_device *pdev)
+ {
+ 	struct s6i2c_if *iface = platform_get_drvdata(pdev);
+ 	i2c_wr16(iface, S6_I2C_ENABLE, 0);
+@@ -378,7 +378,7 @@ static int __devexit s6i2c_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver s6i2c_driver = {
+ 	.probe		= s6i2c_probe,
+-	.remove		= __devexit_p(s6i2c_remove),
++	.remove		= s6i2c_remove,
+ 	.driver		= {
+ 		.name	= DRV_NAME,
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c
+index c0c9dffbdb12..3a2253e1bf59 100644
+--- a/drivers/i2c/busses/i2c-sh7760.c
++++ b/drivers/i2c/busses/i2c-sh7760.c
+@@ -390,7 +390,7 @@ static const struct i2c_algorithm sh7760_i2c_algo = {
+  * iclk = mclk/(CDF + 1).  iclk must be < 20MHz.
+  * scl = iclk/(SCGD*8 + 20).
+  */
+-static int __devinit calc_CCR(unsigned long scl_hz)
++static int calc_CCR(unsigned long scl_hz)
+ {
+ 	struct clk *mclk;
+ 	unsigned long mck, m1, dff, odff, iclk;
+@@ -430,7 +430,7 @@ static int __devinit calc_CCR(unsigned long scl_hz)
+ 	return ((scgdm << 2) | cdfm);
+ }
+ 
+-static int __devinit sh7760_i2c_probe(struct platform_device *pdev)
++static int sh7760_i2c_probe(struct platform_device *pdev)
+ {
+ 	struct sh7760_i2c_platdata *pd;
+ 	struct resource *res;
+@@ -536,7 +536,7 @@ static int __devinit sh7760_i2c_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit sh7760_i2c_remove(struct platform_device *pdev)
++static int sh7760_i2c_remove(struct platform_device *pdev)
+ {
+ 	struct cami2c *id = platform_get_drvdata(pdev);
+ 
+@@ -557,7 +557,7 @@ static struct platform_driver sh7760_i2c_drv = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= sh7760_i2c_probe,
+-	.remove		= __devexit_p(sh7760_i2c_remove),
++	.remove		= sh7760_i2c_remove,
+ };
+ 
+ module_platform_driver(sh7760_i2c_drv);
+diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
+index 9411c1b892c0..b6e7a83a8296 100644
+--- a/drivers/i2c/busses/i2c-sh_mobile.c
++++ b/drivers/i2c/busses/i2c-sh_mobile.c
+@@ -758,7 +758,7 @@ static const struct dev_pm_ops sh_mobile_i2c_dev_pm_ops = {
+ 	.runtime_resume = sh_mobile_i2c_runtime_nop,
+ };
+ 
+-static const struct of_device_id sh_mobile_i2c_dt_ids[] __devinitconst = {
++static const struct of_device_id sh_mobile_i2c_dt_ids[] = {
+ 	{ .compatible = "renesas,rmobile-iic", },
+ 	{},
+ };
+diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c
+index 5574a47792fb..3f1818b87974 100644
+--- a/drivers/i2c/busses/i2c-sirf.c
++++ b/drivers/i2c/busses/i2c-sirf.c
+@@ -258,7 +258,7 @@ static const struct i2c_algorithm i2c_sirfsoc_algo = {
+ 	.functionality = i2c_sirfsoc_func,
+ };
+ 
+-static int __devinit i2c_sirfsoc_probe(struct platform_device *pdev)
++static int i2c_sirfsoc_probe(struct platform_device *pdev)
+ {
+ 	struct sirfsoc_i2c *siic;
+ 	struct i2c_adapter *adap;
+@@ -385,7 +385,7 @@ static int __devinit i2c_sirfsoc_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit i2c_sirfsoc_remove(struct platform_device *pdev)
++static int i2c_sirfsoc_remove(struct platform_device *pdev)
+ {
+ 	struct i2c_adapter *adapter = platform_get_drvdata(pdev);
+ 	struct sirfsoc_i2c *siic = adapter->algo_data;
+@@ -433,7 +433,7 @@ static const struct dev_pm_ops i2c_sirfsoc_pm_ops = {
+ };
+ #endif
+ 
+-static const struct of_device_id sirfsoc_i2c_of_match[] __devinitconst = {
++static const struct of_device_id sirfsoc_i2c_of_match[] = {
+ 	{ .compatible = "sirf,prima2-i2c", },
+ 	{},
+ };
+@@ -449,7 +449,7 @@ static struct platform_driver i2c_sirfsoc_driver = {
+ 		.of_match_table = sirfsoc_i2c_of_match,
+ 	},
+ 	.probe = i2c_sirfsoc_probe,
+-	.remove = __devexit_p(i2c_sirfsoc_remove),
++	.remove = i2c_sirfsoc_remove,
+ };
+ module_platform_driver(i2c_sirfsoc_driver);
+ 
+diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c
+index 87e5126d449c..79fd96a04386 100644
+--- a/drivers/i2c/busses/i2c-sis5595.c
++++ b/drivers/i2c/busses/i2c-sis5595.c
+@@ -142,7 +142,7 @@ static void sis5595_write(u8 reg, u8 data)
+ 	outb(data, sis5595_base + SMB_DAT);
+ }
+ 
+-static int __devinit sis5595_setup(struct pci_dev *SIS5595_dev)
++static int sis5595_setup(struct pci_dev *SIS5595_dev)
+ {
+ 	u16 a;
+ 	u8 val;
+@@ -376,7 +376,7 @@ static DEFINE_PCI_DEVICE_TABLE(sis5595_ids) = {
+ 
+ MODULE_DEVICE_TABLE (pci, sis5595_ids);
+ 
+-static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_id *id)
++static int sis5595_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	int err;
+ 
+diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c
+index 5d6723b7525e..de6dddb9f865 100644
+--- a/drivers/i2c/busses/i2c-sis630.c
++++ b/drivers/i2c/busses/i2c-sis630.c
+@@ -389,7 +389,7 @@ static u32 sis630_func(struct i2c_adapter *adapter)
+ 		I2C_FUNC_SMBUS_BLOCK_DATA;
+ }
+ 
+-static int __devinit sis630_setup(struct pci_dev *sis630_dev)
++static int sis630_setup(struct pci_dev *sis630_dev)
+ {
+ 	unsigned char b;
+ 	struct pci_dev *dummy = NULL;
+@@ -480,7 +480,7 @@ static DEFINE_PCI_DEVICE_TABLE(sis630_ids) = {
+ 
+ MODULE_DEVICE_TABLE (pci, sis630_ids);
+ 
+-static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_id *id)
++static int sis630_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	if (sis630_setup(dev)) {
+ 		dev_err(&dev->dev, "SIS630 comp. bus not detected, module not inserted.\n");
+@@ -496,7 +496,7 @@ static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_i
+ 	return i2c_add_adapter(&sis630_adapter);
+ }
+ 
+-static void __devexit sis630_remove(struct pci_dev *dev)
++static void sis630_remove(struct pci_dev *dev)
+ {
+ 	if (acpi_base) {
+ 		i2c_del_adapter(&sis630_adapter);
+@@ -510,7 +510,7 @@ static struct pci_driver sis630_driver = {
+ 	.name		= "sis630_smbus",
+ 	.id_table	= sis630_ids,
+ 	.probe		= sis630_probe,
+-	.remove		= __devexit_p(sis630_remove),
++	.remove		= sis630_remove,
+ };
+ 
+ module_pci_driver(sis630_driver);
+diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
+index 7b72614a9bc0..b9faf9b6002b 100644
+--- a/drivers/i2c/busses/i2c-sis96x.c
++++ b/drivers/i2c/busses/i2c-sis96x.c
+@@ -252,7 +252,7 @@ static DEFINE_PCI_DEVICE_TABLE(sis96x_ids) = {
+ 
+ MODULE_DEVICE_TABLE (pci, sis96x_ids);
+ 
+-static int __devinit sis96x_probe(struct pci_dev *dev,
++static int sis96x_probe(struct pci_dev *dev,
+ 				const struct pci_device_id *id)
+ {
+ 	u16 ww = 0;
+@@ -308,7 +308,7 @@ static int __devinit sis96x_probe(struct pci_dev *dev,
+ 	return retval;
+ }
+ 
+-static void __devexit sis96x_remove(struct pci_dev *dev)
++static void sis96x_remove(struct pci_dev *dev)
+ {
+ 	if (sis96x_smbus_base) {
+ 		i2c_del_adapter(&sis96x_adapter);
+@@ -321,7 +321,7 @@ static struct pci_driver sis96x_driver = {
+ 	.name		= "sis96x_smbus",
+ 	.id_table	= sis96x_ids,
+ 	.probe		= sis96x_probe,
+-	.remove		= __devexit_p(sis96x_remove),
++	.remove		= sis96x_remove,
+ };
+ 
+ module_pci_driver(sis96x_driver);
+diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
+index dcea77bf6f50..7b38877ffec1 100644
+--- a/drivers/i2c/busses/i2c-tegra.c
++++ b/drivers/i2c/busses/i2c-tegra.c
+@@ -642,7 +642,7 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
+ 
+ #if defined(CONFIG_OF)
+ /* Match table for of_platform binding */
+-static const struct of_device_id tegra_i2c_of_match[] __devinitconst = {
++static const struct of_device_id tegra_i2c_of_match[] = {
+ 	{ .compatible = "nvidia,tegra30-i2c", .data = &tegra30_i2c_hw, },
+ 	{ .compatible = "nvidia,tegra20-i2c", .data = &tegra20_i2c_hw, },
+ 	{ .compatible = "nvidia,tegra20-i2c-dvc", .data = &tegra20_i2c_hw, },
+@@ -651,7 +651,7 @@ static const struct of_device_id tegra_i2c_of_match[] __devinitconst = {
+ MODULE_DEVICE_TABLE(of, tegra_i2c_of_match);
+ #endif
+ 
+-static int __devinit tegra_i2c_probe(struct platform_device *pdev)
++static int tegra_i2c_probe(struct platform_device *pdev)
+ {
+ 	struct tegra_i2c_dev *i2c_dev;
+ 	struct tegra_i2c_platform_data *pdata = pdev->dev.platform_data;
+@@ -769,7 +769,7 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit tegra_i2c_remove(struct platform_device *pdev)
++static int tegra_i2c_remove(struct platform_device *pdev)
+ {
+ 	struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
+ 	i2c_del_adapter(&i2c_dev->adapter);
+@@ -817,7 +817,7 @@ static SIMPLE_DEV_PM_OPS(tegra_i2c_pm, tegra_i2c_suspend, tegra_i2c_resume);
+ 
+ static struct platform_driver tegra_i2c_driver = {
+ 	.probe   = tegra_i2c_probe,
+-	.remove  = __devexit_p(tegra_i2c_remove),
++	.remove  = tegra_i2c_remove,
+ 	.driver  = {
+ 		.name  = "tegra-i2c",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c
+index 7ffee71ca190..be662511c58b 100644
+--- a/drivers/i2c/busses/i2c-via.c
++++ b/drivers/i2c/busses/i2c-via.c
+@@ -96,7 +96,7 @@ static DEFINE_PCI_DEVICE_TABLE(vt586b_ids) = {
+ 
+ MODULE_DEVICE_TABLE (pci, vt586b_ids);
+ 
+-static int __devinit vt586b_probe(struct pci_dev *dev, const struct pci_device_id *id)
++static int vt586b_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	u16 base;
+ 	u8 rev;
+@@ -146,7 +146,7 @@ static int __devinit vt586b_probe(struct pci_dev *dev, const struct pci_device_i
+ 	return 0;
+ }
+ 
+-static void __devexit vt586b_remove(struct pci_dev *dev)
++static void vt586b_remove(struct pci_dev *dev)
+ {
+ 	i2c_del_adapter(&vt586b_adapter);
+ 	release_region(I2C_DIR, IOSPACE);
+@@ -158,7 +158,7 @@ static struct pci_driver vt586b_driver = {
+ 	.name		= "vt586b_smbus",
+ 	.id_table	= vt586b_ids,
+ 	.probe		= vt586b_probe,
+-	.remove		= __devexit_p(vt586b_remove),
++	.remove		= vt586b_remove,
+ };
+ 
+ module_pci_driver(vt586b_driver);
+diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
+index 271c9a2b0fd7..b2d90e105f41 100644
+--- a/drivers/i2c/busses/i2c-viapro.c
++++ b/drivers/i2c/busses/i2c-viapro.c
+@@ -320,8 +320,8 @@ static struct i2c_adapter vt596_adapter = {
+ 	.algo		= &smbus_algorithm,
+ };
+ 
+-static int __devinit vt596_probe(struct pci_dev *pdev,
+-				 const struct pci_device_id *id)
++static int vt596_probe(struct pci_dev *pdev,
++		       const struct pci_device_id *id)
+ {
+ 	unsigned char temp;
+ 	int error;
+diff --git a/drivers/i2c/busses/i2c-viperboard.c b/drivers/i2c/busses/i2c-viperboard.c
+index f5fa20dea906..f45c32c1ace6 100644
+--- a/drivers/i2c/busses/i2c-viperboard.c
++++ b/drivers/i2c/busses/i2c-viperboard.c
+@@ -360,7 +360,7 @@ static const struct i2c_algorithm vprbrd_algorithm = {
+ 	.functionality	= vprbrd_i2c_func,
+ };
+ 
+-static int __devinit vprbrd_i2c_probe(struct platform_device *pdev)
++static int vprbrd_i2c_probe(struct platform_device *pdev)
+ {
+ 	struct vprbrd *vb = dev_get_drvdata(pdev->dev.parent);
+ 	struct vprbrd_i2c *vb_i2c;
+@@ -418,7 +418,7 @@ static int __devinit vprbrd_i2c_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit vprbrd_i2c_remove(struct platform_device *pdev)
++static int vprbrd_i2c_remove(struct platform_device *pdev)
+ {
+ 	struct vprbrd_i2c *vb_i2c = platform_get_drvdata(pdev);
+ 	int ret;
+@@ -432,7 +432,7 @@ static struct platform_driver vprbrd_i2c_driver = {
+ 	.driver.name	= "viperboard-i2c",
+ 	.driver.owner	= THIS_MODULE,
+ 	.probe		= vprbrd_i2c_probe,
+-	.remove		= __devexit_p(vprbrd_i2c_remove),
++	.remove		= vprbrd_i2c_remove,
+ };
+ 
+ static int __init vprbrd_i2c_init(void)
+diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
+index 641d0e5e3303..f042f6da0ace 100644
+--- a/drivers/i2c/busses/i2c-xiic.c
++++ b/drivers/i2c/busses/i2c-xiic.c
+@@ -689,7 +689,7 @@ static struct i2c_adapter xiic_adapter = {
+ };
+ 
+ 
+-static int __devinit xiic_i2c_probe(struct platform_device *pdev)
++static int xiic_i2c_probe(struct platform_device *pdev)
+ {
+ 	struct xiic_i2c *i2c;
+ 	struct xiic_i2c_platform_data *pdata;
+@@ -774,7 +774,7 @@ static int __devinit xiic_i2c_probe(struct platform_device *pdev)
+ 	return -ENOENT;
+ }
+ 
+-static int __devexit xiic_i2c_remove(struct platform_device* pdev)
++static int xiic_i2c_remove(struct platform_device *pdev)
+ {
+ 	struct xiic_i2c *i2c = platform_get_drvdata(pdev);
+ 	struct resource *res;
+@@ -800,7 +800,7 @@ static int __devexit xiic_i2c_remove(struct platform_device* pdev)
+ }
+ 
+ #if defined(CONFIG_OF)
+-static const struct of_device_id xiic_of_match[] __devinitconst = {
++static const struct of_device_id xiic_of_match[] = {
+ 	{ .compatible = "xlnx,xps-iic-2.00.a", },
+ 	{},
+ };
+@@ -809,7 +809,7 @@ MODULE_DEVICE_TABLE(of, xiic_of_match);
+ 
+ static struct platform_driver xiic_i2c_driver = {
+ 	.probe   = xiic_i2c_probe,
+-	.remove  = __devexit_p(xiic_i2c_remove),
++	.remove  = xiic_i2c_remove,
+ 	.driver  = {
+ 		.owner = THIS_MODULE,
+ 		.name = DRIVER_NAME,
+diff --git a/drivers/i2c/busses/i2c-xlr.c b/drivers/i2c/busses/i2c-xlr.c
+index 96d3fabd8883..a005265461da 100644
+--- a/drivers/i2c/busses/i2c-xlr.c
++++ b/drivers/i2c/busses/i2c-xlr.c
+@@ -214,7 +214,7 @@ static struct i2c_algorithm xlr_i2c_algo = {
+ 	.functionality	= xlr_func,
+ };
+ 
+-static int __devinit xlr_i2c_probe(struct platform_device *pdev)
++static int xlr_i2c_probe(struct platform_device *pdev)
+ {
+ 	struct xlr_i2c_private  *priv;
+ 	struct resource *res;
+@@ -251,7 +251,7 @@ static int __devinit xlr_i2c_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit xlr_i2c_remove(struct platform_device *pdev)
++static int xlr_i2c_remove(struct platform_device *pdev)
+ {
+ 	struct xlr_i2c_private *priv;
+ 
+@@ -263,7 +263,7 @@ static int __devexit xlr_i2c_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver xlr_i2c_driver = {
+ 	.probe  = xlr_i2c_probe,
+-	.remove = __devexit_p(xlr_i2c_remove),
++	.remove = xlr_i2c_remove,
+ 	.driver = {
+ 		.name   = "xlr-i2cbus",
+ 		.owner  = THIS_MODULE,
+diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
+index 08aab57337dd..3862a953239c 100644
+--- a/drivers/i2c/busses/scx200_acb.c
++++ b/drivers/i2c/busses/scx200_acb.c
+@@ -389,7 +389,7 @@ static const struct i2c_algorithm scx200_acb_algorithm = {
+ static struct scx200_acb_iface *scx200_acb_list;
+ static DEFINE_MUTEX(scx200_acb_list_mutex);
+ 
+-static __devinit int scx200_acb_probe(struct scx200_acb_iface *iface)
++static int scx200_acb_probe(struct scx200_acb_iface *iface)
+ {
+ 	u8 val;
+ 
+@@ -424,7 +424,7 @@ static __devinit int scx200_acb_probe(struct scx200_acb_iface *iface)
+ 	return 0;
+ }
+ 
+-static __devinit struct scx200_acb_iface *scx200_create_iface(const char *text,
++static struct scx200_acb_iface *scx200_create_iface(const char *text,
+ 		struct device *dev, int index)
+ {
+ 	struct scx200_acb_iface *iface;
+@@ -449,7 +449,7 @@ static __devinit struct scx200_acb_iface *scx200_create_iface(const char *text,
+ 	return iface;
+ }
+ 
+-static int __devinit scx200_acb_create(struct scx200_acb_iface *iface)
++static int scx200_acb_create(struct scx200_acb_iface *iface)
+ {
+ 	struct i2c_adapter *adapter;
+ 	int rc;
+@@ -480,7 +480,7 @@ static int __devinit scx200_acb_create(struct scx200_acb_iface *iface)
+ 	return 0;
+ }
+ 
+-static struct scx200_acb_iface * __devinit scx200_create_dev(const char *text,
++static struct scx200_acb_iface *scx200_create_dev(const char *text,
+ 		unsigned long base, int index, struct device *dev)
+ {
+ 	struct scx200_acb_iface *iface;
+@@ -508,7 +508,7 @@ static struct scx200_acb_iface * __devinit scx200_create_dev(const char *text,
+ 	return NULL;
+ }
+ 
+-static int __devinit scx200_probe(struct platform_device *pdev)
++static int scx200_probe(struct platform_device *pdev)
+ {
+ 	struct scx200_acb_iface *iface;
+ 	struct resource *res;
+@@ -530,14 +530,14 @@ static int __devinit scx200_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static void __devexit scx200_cleanup_iface(struct scx200_acb_iface *iface)
++static void scx200_cleanup_iface(struct scx200_acb_iface *iface)
+ {
+ 	i2c_del_adapter(&iface->adapter);
+ 	release_region(iface->base, 8);
+ 	kfree(iface);
+ }
+ 
+-static int __devexit scx200_remove(struct platform_device *pdev)
++static int scx200_remove(struct platform_device *pdev)
+ {
+ 	struct scx200_acb_iface *iface;
+ 
+@@ -554,7 +554,7 @@ static struct platform_driver scx200_pci_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = scx200_probe,
+-	.remove = __devexit_p(scx200_remove),
++	.remove = scx200_remove,
+ };
+ 
+ static DEFINE_PCI_DEVICE_TABLE(scx200_isa) = {
+diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c
+index 3b7bc06fe8a6..9f50ef04a4bd 100644
+--- a/drivers/i2c/muxes/i2c-mux-gpio.c
++++ b/drivers/i2c/muxes/i2c-mux-gpio.c
+@@ -53,14 +53,14 @@ static int i2c_mux_gpio_deselect(struct i2c_adapter *adap, void *data, u32 chan)
+ 	return 0;
+ }
+ 
+-static int __devinit match_gpio_chip_by_label(struct gpio_chip *chip,
++static int match_gpio_chip_by_label(struct gpio_chip *chip,
+ 					      void *data)
+ {
+ 	return !strcmp(chip->label, data);
+ }
+ 
+ #ifdef CONFIG_OF
+-static int __devinit i2c_mux_gpio_probe_dt(struct gpiomux *mux,
++static int i2c_mux_gpio_probe_dt(struct gpiomux *mux,
+ 					struct platform_device *pdev)
+ {
+ 	struct device_node *np = pdev->dev.of_node;
+@@ -125,14 +125,14 @@ static int __devinit i2c_mux_gpio_probe_dt(struct gpiomux *mux,
+ 	return 0;
+ }
+ #else
+-static int __devinit i2c_mux_gpio_probe_dt(struct gpiomux *mux,
++static int i2c_mux_gpio_probe_dt(struct gpiomux *mux,
+ 					struct platform_device *pdev)
+ {
+ 	return 0;
+ }
+ #endif
+ 
+-static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev)
++static int i2c_mux_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct gpiomux *mux;
+ 	struct i2c_adapter *parent;
+@@ -239,7 +239,7 @@ static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit i2c_mux_gpio_remove(struct platform_device *pdev)
++static int i2c_mux_gpio_remove(struct platform_device *pdev)
+ {
+ 	struct gpiomux *mux = platform_get_drvdata(pdev);
+ 	int i;
+@@ -256,7 +256,7 @@ static int __devexit i2c_mux_gpio_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static const struct of_device_id i2c_mux_gpio_of_match[] __devinitconst = {
++static const struct of_device_id i2c_mux_gpio_of_match[] = {
+ 	{ .compatible = "i2c-mux-gpio", },
+ 	{},
+ };
+@@ -264,7 +264,7 @@ MODULE_DEVICE_TABLE(of, i2c_mux_gpio_of_match);
+ 
+ static struct platform_driver i2c_mux_gpio_driver = {
+ 	.probe	= i2c_mux_gpio_probe,
+-	.remove	= __devexit_p(i2c_mux_gpio_remove),
++	.remove	= i2c_mux_gpio_remove,
+ 	.driver	= {
+ 		.owner	= THIS_MODULE,
+ 		.name	= "i2c-mux-gpio",
+diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c
+index 7fa5b24b16db..1e44d04d1b22 100644
+--- a/drivers/i2c/muxes/i2c-mux-pinctrl.c
++++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c
+@@ -129,7 +129,7 @@ static inline int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
+ }
+ #endif
+ 
+-static int __devinit i2c_mux_pinctrl_probe(struct platform_device *pdev)
++static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
+ {
+ 	struct i2c_mux_pinctrl *mux;
+ 	int (*deselect)(struct i2c_adapter *, void *, u32);
+@@ -241,7 +241,7 @@ static int __devinit i2c_mux_pinctrl_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit i2c_mux_pinctrl_remove(struct platform_device *pdev)
++static int i2c_mux_pinctrl_remove(struct platform_device *pdev)
+ {
+ 	struct i2c_mux_pinctrl *mux = platform_get_drvdata(pdev);
+ 	int i;
+@@ -255,7 +255,7 @@ static int __devexit i2c_mux_pinctrl_remove(struct platform_device *pdev)
+ }
+ 
+ #ifdef CONFIG_OF
+-static const struct of_device_id i2c_mux_pinctrl_of_match[] __devinitconst = {
++static const struct of_device_id i2c_mux_pinctrl_of_match[] = {
+ 	{ .compatible = "i2c-mux-pinctrl", },
+ 	{},
+ };
+@@ -269,7 +269,7 @@ static struct platform_driver i2c_mux_pinctrl_driver = {
+ 		.of_match_table = of_match_ptr(i2c_mux_pinctrl_of_match),
+ 	},
+ 	.probe	= i2c_mux_pinctrl_probe,
+-	.remove	= __devexit_p(i2c_mux_pinctrl_remove),
++	.remove	= i2c_mux_pinctrl_remove,
+ };
+ module_platform_driver(i2c_mux_pinctrl_driver);
+ 

commit 7a79e94e973639da7bf1b8242d504f9db9e5e848
+Author: Bill Pemberton 
+Date:   Fri Dec 7 09:26:37 2012 -0500
+
+    ASoC: codecs: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c
+index 9fd3b6827bba..60159c07448d 100644
+--- a/sound/soc/codecs/88pm860x-codec.c
++++ b/sound/soc/codecs/88pm860x-codec.c
+@@ -1423,7 +1423,7 @@ static struct snd_soc_codec_driver soc_codec_dev_pm860x = {
+ 	.num_dapm_routes = ARRAY_SIZE(pm860x_dapm_routes),
+ };
+ 
+-static int __devinit pm860x_codec_probe(struct platform_device *pdev)
++static int pm860x_codec_probe(struct platform_device *pdev)
+ {
+ 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+ 	struct pm860x_priv *pm860x;
+@@ -1463,7 +1463,7 @@ static int __devinit pm860x_codec_probe(struct platform_device *pdev)
+ 	return -EINVAL;
+ }
+ 
+-static int __devexit pm860x_codec_remove(struct platform_device *pdev)
++static int pm860x_codec_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_codec(&pdev->dev);
+ 	platform_set_drvdata(pdev, NULL);
+@@ -1476,7 +1476,7 @@ static struct platform_driver pm860x_codec_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe	= pm860x_codec_probe,
+-	.remove	= __devexit_p(pm860x_codec_remove),
++	.remove	= pm860x_codec_remove,
+ };
+ 
+ module_platform_driver(pm860x_codec_driver);
+diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c
+index 4d96090db662..6c12ac206ee9 100644
+--- a/sound/soc/codecs/ab8500-codec.c
++++ b/sound/soc/codecs/ab8500-codec.c
+@@ -2554,7 +2554,7 @@ static struct snd_soc_codec_driver ab8500_codec_driver = {
+ 	.num_dapm_routes =	ARRAY_SIZE(ab8500_dapm_routes),
+ };
+ 
+-static int __devinit ab8500_codec_driver_probe(struct platform_device *pdev)
++static int ab8500_codec_driver_probe(struct platform_device *pdev)
+ {
+ 	int status;
+ 	struct ab8500_codec_drvdata *drvdata;
+@@ -2580,7 +2580,7 @@ static int __devinit ab8500_codec_driver_probe(struct platform_device *pdev)
+ 	return status;
+ }
+ 
+-static int __devexit ab8500_codec_driver_remove(struct platform_device *pdev)
++static int ab8500_codec_driver_remove(struct platform_device *pdev)
+ {
+ 	dev_info(&pdev->dev, "%s Enter.\n", __func__);
+ 
+@@ -2595,7 +2595,7 @@ static struct platform_driver ab8500_codec_platform_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= ab8500_codec_driver_probe,
+-	.remove		= __devexit_p(ab8500_codec_driver_remove),
++	.remove		= ab8500_codec_driver_remove,
+ 	.suspend	= NULL,
+ 	.resume		= NULL,
+ };
+diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
+index ea06b834a7de..ef2ae32ffc66 100644
+--- a/sound/soc/codecs/ac97.c
++++ b/sound/soc/codecs/ac97.c
+@@ -118,13 +118,13 @@ static struct snd_soc_codec_driver soc_codec_dev_ac97 = {
+ 	.resume =	ac97_soc_resume,
+ };
+ 
+-static __devinit int ac97_probe(struct platform_device *pdev)
++static int ac97_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_codec(&pdev->dev,
+ 			&soc_codec_dev_ac97, &ac97_dai, 1);
+ }
+ 
+-static int __devexit ac97_remove(struct platform_device *pdev)
++static int ac97_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_codec(&pdev->dev);
+ 	return 0;
+@@ -137,7 +137,7 @@ static struct platform_driver ac97_codec_driver = {
+ 	},
+ 
+ 	.probe = ac97_probe,
+-	.remove = __devexit_p(ac97_remove),
++	.remove = ac97_remove,
+ };
+ 
+ module_platform_driver(ac97_codec_driver);
+diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c
+index dce6ebeef452..9a92b7962f41 100644
+--- a/sound/soc/codecs/ad1836.c
++++ b/sound/soc/codecs/ad1836.c
+@@ -360,7 +360,7 @@ static const struct regmap_config ad1836_regmap_config = {
+ 	.cache_type = REGCACHE_RBTREE,
+ };
+ 
+-static int __devinit ad1836_spi_probe(struct spi_device *spi)
++static int ad1836_spi_probe(struct spi_device *spi)
+ {
+ 	struct ad1836_priv *ad1836;
+ 	int ret;
+@@ -383,7 +383,7 @@ static int __devinit ad1836_spi_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit ad1836_spi_remove(struct spi_device *spi)
++static int ad1836_spi_remove(struct spi_device *spi)
+ {
+ 	snd_soc_unregister_codec(&spi->dev);
+ 	return 0;
+@@ -405,7 +405,7 @@ static struct spi_driver ad1836_spi_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= ad1836_spi_probe,
+-	.remove		= __devexit_p(ad1836_spi_remove),
++	.remove		= ad1836_spi_remove,
+ 	.id_table	= ad1836_ids,
+ };
+ 
+diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c
+index 2f752660f678..aea7e52cf714 100644
+--- a/sound/soc/codecs/ad193x.c
++++ b/sound/soc/codecs/ad193x.c
+@@ -378,7 +378,7 @@ static const struct regmap_config ad193x_spi_regmap_config = {
+ 	.volatile_reg = adau193x_reg_volatile,
+ };
+ 
+-static int __devinit ad193x_spi_probe(struct spi_device *spi)
++static int ad193x_spi_probe(struct spi_device *spi)
+ {
+ 	struct ad193x_priv *ad193x;
+ 
+@@ -397,7 +397,7 @@ static int __devinit ad193x_spi_probe(struct spi_device *spi)
+ 			&ad193x_dai, 1);
+ }
+ 
+-static int __devexit ad193x_spi_remove(struct spi_device *spi)
++static int ad193x_spi_remove(struct spi_device *spi)
+ {
+ 	snd_soc_unregister_codec(&spi->dev);
+ 	return 0;
+@@ -409,7 +409,7 @@ static struct spi_driver ad193x_spi_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= ad193x_spi_probe,
+-	.remove		= __devexit_p(ad193x_spi_remove),
++	.remove		= ad193x_spi_remove,
+ };
+ #endif
+ 
+@@ -430,8 +430,8 @@ static const struct i2c_device_id ad193x_id[] = {
+ };
+ MODULE_DEVICE_TABLE(i2c, ad193x_id);
+ 
+-static int __devinit ad193x_i2c_probe(struct i2c_client *client,
+-		const struct i2c_device_id *id)
++static int ad193x_i2c_probe(struct i2c_client *client,
++			    const struct i2c_device_id *id)
+ {
+ 	struct ad193x_priv *ad193x;
+ 
+@@ -450,7 +450,7 @@ static int __devinit ad193x_i2c_probe(struct i2c_client *client,
+ 			&ad193x_dai, 1);
+ }
+ 
+-static int __devexit ad193x_i2c_remove(struct i2c_client *client)
++static int ad193x_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -461,7 +461,7 @@ static struct i2c_driver ad193x_i2c_driver = {
+ 		.name = "ad193x",
+ 	},
+ 	.probe    = ad193x_i2c_probe,
+-	.remove   = __devexit_p(ad193x_i2c_remove),
++	.remove   = ad193x_i2c_remove,
+ 	.id_table = ad193x_id,
+ };
+ #endif
+diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
+index 8c39dddd7d00..f385342947d3 100644
+--- a/sound/soc/codecs/ad1980.c
++++ b/sound/soc/codecs/ad1980.c
+@@ -255,13 +255,13 @@ static struct snd_soc_codec_driver soc_codec_dev_ad1980 = {
+ 	.read = ac97_read,
+ };
+ 
+-static __devinit int ad1980_probe(struct platform_device *pdev)
++static int ad1980_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_codec(&pdev->dev,
+ 			&soc_codec_dev_ad1980, &ad1980_dai, 1);
+ }
+ 
+-static int __devexit ad1980_remove(struct platform_device *pdev)
++static int ad1980_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_codec(&pdev->dev);
+ 	return 0;
+@@ -274,7 +274,7 @@ static struct platform_driver ad1980_codec_driver = {
+ 	},
+ 
+ 	.probe = ad1980_probe,
+-	.remove = __devexit_p(ad1980_remove),
++	.remove = ad1980_remove,
+ };
+ 
+ module_platform_driver(ad1980_codec_driver);
+diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c
+index ee7a68dcefd2..b1f2baf42b48 100644
+--- a/sound/soc/codecs/ad73311.c
++++ b/sound/soc/codecs/ad73311.c
+@@ -47,7 +47,7 @@ static int ad73311_probe(struct platform_device *pdev)
+ 			&soc_codec_dev_ad73311, &ad73311_dai, 1);
+ }
+ 
+-static int __devexit ad73311_remove(struct platform_device *pdev)
++static int ad73311_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_codec(&pdev->dev);
+ 	return 0;
+@@ -60,7 +60,7 @@ static struct platform_driver ad73311_codec_driver = {
+ 	},
+ 
+ 	.probe = ad73311_probe,
+-	.remove = __devexit_p(ad73311_remove),
++	.remove = ad73311_remove,
+ };
+ 
+ module_platform_driver(ad73311_codec_driver);
+diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c
+index 704544bfc90d..068b3ae56a17 100644
+--- a/sound/soc/codecs/adau1373.c
++++ b/sound/soc/codecs/adau1373.c
+@@ -1353,8 +1353,8 @@ static struct snd_soc_codec_driver adau1373_codec_driver = {
+ 	.num_dapm_routes = ARRAY_SIZE(adau1373_dapm_routes),
+ };
+ 
+-static int __devinit adau1373_i2c_probe(struct i2c_client *client,
+-	const struct i2c_device_id *id)
++static int adau1373_i2c_probe(struct i2c_client *client,
++			      const struct i2c_device_id *id)
+ {
+ 	struct adau1373 *adau1373;
+ 	int ret;
+@@ -1370,7 +1370,7 @@ static int __devinit adau1373_i2c_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit adau1373_i2c_remove(struct i2c_client *client)
++static int adau1373_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -1388,7 +1388,7 @@ static struct i2c_driver adau1373_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = adau1373_i2c_probe,
+-	.remove = __devexit_p(adau1373_i2c_remove),
++	.remove = adau1373_i2c_remove,
+ 	.id_table = adau1373_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
+index 51f2f3cd8136..dafdbe87edeb 100644
+--- a/sound/soc/codecs/adau1701.c
++++ b/sound/soc/codecs/adau1701.c
+@@ -489,8 +489,8 @@ static struct snd_soc_codec_driver adau1701_codec_drv = {
+ 	.set_sysclk		= adau1701_set_sysclk,
+ };
+ 
+-static __devinit int adau1701_i2c_probe(struct i2c_client *client,
+-		const struct i2c_device_id *id)
++static int adau1701_i2c_probe(struct i2c_client *client,
++			      const struct i2c_device_id *id)
+ {
+ 	struct adau1701 *adau1701;
+ 	int ret;
+@@ -505,7 +505,7 @@ static __devinit int adau1701_i2c_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static __devexit int adau1701_i2c_remove(struct i2c_client *client)
++static int adau1701_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -523,7 +523,7 @@ static struct i2c_driver adau1701_i2c_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= adau1701_i2c_probe,
+-	.remove		= __devexit_p(adau1701_i2c_remove),
++	.remove		= adau1701_i2c_remove,
+ 	.id_table	= adau1701_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c
+index ebd7b37b902b..3c839cc4e00e 100644
+--- a/sound/soc/codecs/adav80x.c
++++ b/sound/soc/codecs/adav80x.c
+@@ -839,8 +839,8 @@ static struct snd_soc_codec_driver adav80x_codec_driver = {
+ 	.num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes),
+ };
+ 
+-static int __devinit adav80x_bus_probe(struct device *dev,
+-		enum snd_soc_control_type control_type)
++static int adav80x_bus_probe(struct device *dev,
++			     enum snd_soc_control_type control_type)
+ {
+ 	struct adav80x *adav80x;
+ 	int ret;
+@@ -860,7 +860,7 @@ static int __devinit adav80x_bus_probe(struct device *dev,
+ 	return ret;
+ }
+ 
+-static int __devexit adav80x_bus_remove(struct device *dev)
++static int adav80x_bus_remove(struct device *dev)
+ {
+ 	snd_soc_unregister_codec(dev);
+ 	kfree(dev_get_drvdata(dev));
+@@ -868,12 +868,12 @@ static int __devexit adav80x_bus_remove(struct device *dev)
+ }
+ 
+ #if defined(CONFIG_SPI_MASTER)
+-static int __devinit adav80x_spi_probe(struct spi_device *spi)
++static int adav80x_spi_probe(struct spi_device *spi)
+ {
+ 	return adav80x_bus_probe(&spi->dev, SND_SOC_SPI);
+ }
+ 
+-static int __devexit adav80x_spi_remove(struct spi_device *spi)
++static int adav80x_spi_remove(struct spi_device *spi)
+ {
+ 	return adav80x_bus_remove(&spi->dev);
+ }
+@@ -884,7 +884,7 @@ static struct spi_driver adav80x_spi_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= adav80x_spi_probe,
+-	.remove		= __devexit_p(adav80x_spi_remove),
++	.remove		= adav80x_spi_remove,
+ };
+ #endif
+ 
+@@ -895,13 +895,13 @@ static const struct i2c_device_id adav80x_id[] = {
+ };
+ MODULE_DEVICE_TABLE(i2c, adav80x_id);
+ 
+-static int __devinit adav80x_i2c_probe(struct i2c_client *client,
+-		const struct i2c_device_id *id)
++static int adav80x_i2c_probe(struct i2c_client *client,
++			     const struct i2c_device_id *id)
+ {
+ 	return adav80x_bus_probe(&client->dev, SND_SOC_I2C);
+ }
+ 
+-static int __devexit adav80x_i2c_remove(struct i2c_client *client)
++static int adav80x_i2c_remove(struct i2c_client *client)
+ {
+ 	return adav80x_bus_remove(&client->dev);
+ }
+@@ -912,7 +912,7 @@ static struct i2c_driver adav80x_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = adav80x_i2c_probe,
+-	.remove = __devexit_p(adav80x_i2c_remove),
++	.remove = adav80x_i2c_remove,
+ 	.id_table = adav80x_id,
+ };
+ #endif
+diff --git a/sound/soc/codecs/ads117x.c b/sound/soc/codecs/ads117x.c
+index 8103b938b8c0..506d474c4d22 100644
+--- a/sound/soc/codecs/ads117x.c
++++ b/sound/soc/codecs/ads117x.c
+@@ -36,13 +36,13 @@ static struct snd_soc_dai_driver ads117x_dai = {
+ 
+ static struct snd_soc_codec_driver soc_codec_dev_ads117x;
+ 
+-static __devinit int ads117x_probe(struct platform_device *pdev)
++static int ads117x_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_codec(&pdev->dev,
+ 			&soc_codec_dev_ads117x, &ads117x_dai, 1);
+ }
+ 
+-static int __devexit ads117x_remove(struct platform_device *pdev)
++static int ads117x_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_codec(&pdev->dev);
+ 	return 0;
+@@ -55,7 +55,7 @@ static struct platform_driver ads117x_codec_driver = {
+ 	},
+ 
+ 	.probe = ads117x_probe,
+-	.remove = __devexit_p(ads117x_remove),
++	.remove = ads117x_remove,
+ };
+ 
+ module_platform_driver(ads117x_codec_driver);
+diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
+index 4b11b82b2273..6f6c335a5baa 100644
+--- a/sound/soc/codecs/ak4104.c
++++ b/sound/soc/codecs/ak4104.c
+@@ -258,7 +258,7 @@ static int ak4104_spi_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit ak4104_spi_remove(struct spi_device *spi)
++static int ak4104_spi_remove(struct spi_device *spi)
+ {
+ 	snd_soc_unregister_codec(&spi->dev);
+ 	return 0;
+@@ -277,7 +277,7 @@ static struct spi_driver ak4104_spi_driver = {
+ 		.of_match_table = ak4104_of_match,
+ 	},
+ 	.probe  = ak4104_spi_probe,
+-	.remove = __devexit_p(ak4104_spi_remove),
++	.remove = ak4104_spi_remove,
+ };
+ 
+ module_spi_driver(ak4104_spi_driver);
+diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
+index fc5581063b2d..684fe910669f 100644
+--- a/sound/soc/codecs/ak4535.c
++++ b/sound/soc/codecs/ak4535.c
+@@ -436,8 +436,8 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4535 = {
+ 	.num_dapm_routes = ARRAY_SIZE(ak4535_audio_map),
+ };
+ 
+-static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int ak4535_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct ak4535_priv *ak4535;
+ 	int ret;
+@@ -462,7 +462,7 @@ static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int ak4535_i2c_remove(struct i2c_client *client)
++static int ak4535_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -480,7 +480,7 @@ static struct i2c_driver ak4535_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe =    ak4535_i2c_probe,
+-	.remove =   __devexit_p(ak4535_i2c_remove),
++	.remove =   ak4535_i2c_remove,
+ 	.id_table = ak4535_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c
+index 543a12f471be..5f9af1fb76e8 100644
+--- a/sound/soc/codecs/ak4641.c
++++ b/sound/soc/codecs/ak4641.c
+@@ -557,8 +557,8 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4641 = {
+ };
+ 
+ 
+-static int __devinit ak4641_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int ak4641_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct ak4641_platform_data *pdata = i2c->dev.platform_data;
+ 	struct ak4641_priv *ak4641;
+@@ -610,7 +610,7 @@ static int __devinit ak4641_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static int __devexit ak4641_i2c_remove(struct i2c_client *i2c)
++static int ak4641_i2c_remove(struct i2c_client *i2c)
+ {
+ 	struct ak4641_platform_data *pdata = i2c->dev.platform_data;
+ 
+@@ -640,7 +640,7 @@ static struct i2c_driver ak4641_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe =    ak4641_i2c_probe,
+-	.remove =   __devexit_p(ak4641_i2c_remove),
++	.remove =   ak4641_i2c_remove,
+ 	.id_table = ak4641_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
+index 546466abb77f..1f0cdab03294 100644
+--- a/sound/soc/codecs/ak4642.c
++++ b/sound/soc/codecs/ak4642.c
+@@ -513,15 +513,15 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4648 = {
+ };
+ 
+ #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+-static __devinit int ak4642_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int ak4642_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	return snd_soc_register_codec(&i2c->dev,
+ 				(struct snd_soc_codec_driver *)id->driver_data,
+ 				&ak4642_dai, 1);
+ }
+ 
+-static __devexit int ak4642_i2c_remove(struct i2c_client *client)
++static int ak4642_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -541,7 +541,7 @@ static struct i2c_driver ak4642_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe		= ak4642_i2c_probe,
+-	.remove		= __devexit_p(ak4642_i2c_remove),
++	.remove		= ak4642_i2c_remove,
+ 	.id_table	= ak4642_i2c_id,
+ };
+ #endif
+diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c
+index 2b457976a7bf..25bdf6ad4a54 100644
+--- a/sound/soc/codecs/ak4671.c
++++ b/sound/soc/codecs/ak4671.c
+@@ -655,8 +655,8 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4671 = {
+ 	.num_dapm_routes = ARRAY_SIZE(ak4671_intercon),
+ };
+ 
+-static int __devinit ak4671_i2c_probe(struct i2c_client *client,
+-		const struct i2c_device_id *id)
++static int ak4671_i2c_probe(struct i2c_client *client,
++			    const struct i2c_device_id *id)
+ {
+ 	struct ak4671_priv *ak4671;
+ 	int ret;
+@@ -674,7 +674,7 @@ static int __devinit ak4671_i2c_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static __devexit int ak4671_i2c_remove(struct i2c_client *client)
++static int ak4671_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -692,7 +692,7 @@ static struct i2c_driver ak4671_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = ak4671_i2c_probe,
+-	.remove = __devexit_p(ak4671_i2c_remove),
++	.remove = ak4671_i2c_remove,
+ 	.id_table = ak4671_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c
+index 1960478ce6bb..256c364193a5 100644
+--- a/sound/soc/codecs/alc5623.c
++++ b/sound/soc/codecs/alc5623.c
+@@ -991,8 +991,8 @@ static struct snd_soc_codec_driver soc_codec_device_alc5623 = {
+  *    low  = 0x1a
+  *    high = 0x1b
+  */
+-static __devinit int alc5623_i2c_probe(struct i2c_client *client,
+-				const struct i2c_device_id *id)
++static int alc5623_i2c_probe(struct i2c_client *client,
++			     const struct i2c_device_id *id)
+ {
+ 	struct alc5623_platform_data *pdata;
+ 	struct alc5623_priv *alc5623;
+@@ -1058,7 +1058,7 @@ static __devinit int alc5623_i2c_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static __devexit int alc5623_i2c_remove(struct i2c_client *client)
++static int alc5623_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -1079,7 +1079,7 @@ static struct i2c_driver alc5623_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = alc5623_i2c_probe,
+-	.remove =  __devexit_p(alc5623_i2c_remove),
++	.remove =  alc5623_i2c_remove,
+ 	.id_table = alc5623_i2c_table,
+ };
+ 
+diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c
+index 7dd02420b36d..f2e62e45f912 100644
+--- a/sound/soc/codecs/alc5632.c
++++ b/sound/soc/codecs/alc5632.c
+@@ -1116,8 +1116,8 @@ static struct regmap_config alc5632_regmap = {
+  *    low  = 0x1a
+  *    high = 0x1b
+  */
+-static __devinit int alc5632_i2c_probe(struct i2c_client *client,
+-				const struct i2c_device_id *id)
++static int alc5632_i2c_probe(struct i2c_client *client,
++			     const struct i2c_device_id *id)
+ {
+ 	struct alc5632_priv *alc5632;
+ 	int ret, ret1, ret2;
+@@ -1179,7 +1179,7 @@ static __devinit int alc5632_i2c_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static __devexit int alc5632_i2c_remove(struct i2c_client *client)
++static int alc5632_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -1198,7 +1198,7 @@ static struct i2c_driver alc5632_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = alc5632_i2c_probe,
+-	.remove =  __devexit_p(alc5632_i2c_remove),
++	.remove =  alc5632_i2c_remove,
+ 	.id_table = alc5632_i2c_table,
+ };
+ 
+diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c
+index 064cd6a93516..23316c887b19 100644
+--- a/sound/soc/codecs/cq93vc.c
++++ b/sound/soc/codecs/cq93vc.c
+@@ -201,7 +201,7 @@ static struct platform_driver cq93vc_codec_driver = {
+ 	},
+ 
+ 	.probe = cq93vc_platform_probe,
+-	.remove = __devexit_p(cq93vc_platform_remove),
++	.remove = cq93vc_platform_remove,
+ };
+ 
+ module_platform_driver(cq93vc_codec_driver);
+diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c
+index 6ad3878db8fc..4f1127935fdf 100644
+--- a/sound/soc/codecs/cs4271.c
++++ b/sound/soc/codecs/cs4271.c
+@@ -570,7 +570,7 @@ static struct snd_soc_codec_driver soc_codec_dev_cs4271 = {
+ };
+ 
+ #if defined(CONFIG_SPI_MASTER)
+-static int __devinit cs4271_spi_probe(struct spi_device *spi)
++static int cs4271_spi_probe(struct spi_device *spi)
+ {
+ 	struct cs4271_private *cs4271;
+ 
+@@ -585,7 +585,7 @@ static int __devinit cs4271_spi_probe(struct spi_device *spi)
+ 		&cs4271_dai, 1);
+ }
+ 
+-static int __devexit cs4271_spi_remove(struct spi_device *spi)
++static int cs4271_spi_remove(struct spi_device *spi)
+ {
+ 	snd_soc_unregister_codec(&spi->dev);
+ 	return 0;
+@@ -598,7 +598,7 @@ static struct spi_driver cs4271_spi_driver = {
+ 		.of_match_table = of_match_ptr(cs4271_dt_ids),
+ 	},
+ 	.probe		= cs4271_spi_probe,
+-	.remove		= __devexit_p(cs4271_spi_remove),
++	.remove		= cs4271_spi_remove,
+ };
+ #endif /* defined(CONFIG_SPI_MASTER) */
+ 
+@@ -609,8 +609,8 @@ static const struct i2c_device_id cs4271_i2c_id[] = {
+ };
+ MODULE_DEVICE_TABLE(i2c, cs4271_i2c_id);
+ 
+-static int __devinit cs4271_i2c_probe(struct i2c_client *client,
+-				      const struct i2c_device_id *id)
++static int cs4271_i2c_probe(struct i2c_client *client,
++			    const struct i2c_device_id *id)
+ {
+ 	struct cs4271_private *cs4271;
+ 
+@@ -625,7 +625,7 @@ static int __devinit cs4271_i2c_probe(struct i2c_client *client,
+ 		&cs4271_dai, 1);
+ }
+ 
+-static int __devexit cs4271_i2c_remove(struct i2c_client *client)
++static int cs4271_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -639,7 +639,7 @@ static struct i2c_driver cs4271_i2c_driver = {
+ 	},
+ 	.id_table	= cs4271_i2c_id,
+ 	.probe		= cs4271_i2c_probe,
+-	.remove		= __devexit_p(cs4271_i2c_remove),
++	.remove		= cs4271_i2c_remove,
+ };
+ #endif /* defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) */
+ 
+diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c
+index 97a81051e88d..99bb1c69499e 100644
+--- a/sound/soc/codecs/cs42l52.c
++++ b/sound/soc/codecs/cs42l52.c
+@@ -1271,7 +1271,7 @@ static struct i2c_driver cs42l52_i2c_driver = {
+ 	},
+ 	.id_table = cs42l52_id,
+ 	.probe =    cs42l52_i2c_probe,
+-	.remove =   __devexit_p(cs42l52_i2c_remove),
++	.remove =   cs42l52_i2c_remove,
+ };
+ 
+ module_i2c_driver(cs42l52_i2c_driver);
+diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c
+index 2c08c4cb465a..a0791ecf6d95 100644
+--- a/sound/soc/codecs/cs42l73.c
++++ b/sound/soc/codecs/cs42l73.c
+@@ -1345,8 +1345,8 @@ static struct regmap_config cs42l73_regmap = {
+ 	.cache_type = REGCACHE_RBTREE,
+ };
+ 
+-static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client,
+-				       const struct i2c_device_id *id)
++static int cs42l73_i2c_probe(struct i2c_client *i2c_client,
++			     const struct i2c_device_id *id)
+ {
+ 	struct cs42l73_private *cs42l73;
+ 	int ret;
+@@ -1406,7 +1406,7 @@ static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client,
+ 	return 0;
+ }
+ 
+-static __devexit int cs42l73_i2c_remove(struct i2c_client *client)
++static int cs42l73_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -1426,7 +1426,7 @@ static struct i2c_driver cs42l73_i2c_driver = {
+ 		   },
+ 	.id_table = cs42l73_id,
+ 	.probe = cs42l73_i2c_probe,
+-	.remove = __devexit_p(cs42l73_i2c_remove),
++	.remove = cs42l73_i2c_remove,
+ 
+ };
+ 
+diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c
+index 843c1eb72faf..9c1231456502 100644
+--- a/sound/soc/codecs/da7210.c
++++ b/sound/soc/codecs/da7210.c
+@@ -1218,8 +1218,8 @@ static const struct regmap_config da7210_regmap_config_i2c = {
+ 	.cache_type = REGCACHE_RBTREE,
+ };
+ 
+-static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
+-			   	      const struct i2c_device_id *id)
++static int da7210_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct da7210_priv *da7210;
+ 	int ret;
+@@ -1251,7 +1251,7 @@ static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static int __devexit da7210_i2c_remove(struct i2c_client *client)
++static int da7210_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -1270,7 +1270,7 @@ static struct i2c_driver da7210_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe		= da7210_i2c_probe,
+-	.remove		= __devexit_p(da7210_i2c_remove),
++	.remove		= da7210_i2c_remove,
+ 	.id_table	= da7210_i2c_id,
+ };
+ #endif
+@@ -1314,7 +1314,7 @@ static const struct regmap_config da7210_regmap_config_spi = {
+ 	.cache_type = REGCACHE_RBTREE,
+ };
+ 
+-static int __devinit da7210_spi_probe(struct spi_device *spi)
++static int da7210_spi_probe(struct spi_device *spi)
+ {
+ 	struct da7210_priv *da7210;
+ 	int ret;
+@@ -1343,7 +1343,7 @@ static int __devinit da7210_spi_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit da7210_spi_remove(struct spi_device *spi)
++static int da7210_spi_remove(struct spi_device *spi)
+ {
+ 	snd_soc_unregister_codec(&spi->dev);
+ 	return 0;
+@@ -1355,7 +1355,7 @@ static struct spi_driver da7210_spi_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = da7210_spi_probe,
+-	.remove = __devexit_p(da7210_spi_remove)
++	.remove = da7210_spi_remove
+ };
+ #endif
+ 
+diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c
+index 01be2a320e21..dc0284dc9e6f 100644
+--- a/sound/soc/codecs/da732x.c
++++ b/sound/soc/codecs/da732x.c
+@@ -1557,8 +1557,8 @@ static struct snd_soc_codec_driver soc_codec_dev_da732x = {
+ 	.reg_cache_size		= ARRAY_SIZE(da732x_reg_cache),
+ };
+ 
+-static __devinit int da732x_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int da732x_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct da732x_priv *da732x;
+ 	unsigned int reg;
+@@ -1596,7 +1596,7 @@ static __devinit int da732x_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int da732x_i2c_remove(struct i2c_client *client)
++static int da732x_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 
+@@ -1615,7 +1615,7 @@ static struct i2c_driver da732x_i2c_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= da732x_i2c_probe,
+-	.remove		= __devexit_p(da732x_i2c_remove),
++	.remove		= da732x_i2c_remove,
+ 	.id_table	= da732x_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c
+index d3a6de2e757b..fc9802d1281d 100644
+--- a/sound/soc/codecs/da9055.c
++++ b/sound/soc/codecs/da9055.c
+@@ -1484,8 +1484,8 @@ static const struct regmap_config da9055_regmap_config = {
+ 	.cache_type = REGCACHE_RBTREE,
+ };
+ 
+-static int __devinit da9055_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int da9055_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct da9055_priv *da9055;
+ 	struct da9055_platform_data *pdata = dev_get_platdata(&i2c->dev);
+@@ -1517,7 +1517,7 @@ static int __devinit da9055_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static int __devexit da9055_remove(struct i2c_client *client)
++static int da9055_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -1536,7 +1536,7 @@ static struct i2c_driver da9055_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe		= da9055_i2c_probe,
+-	.remove		= __devexit_p(da9055_remove),
++	.remove		= da9055_remove,
+ 	.id_table	= da9055_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/dfbmcs320.c b/sound/soc/codecs/dfbmcs320.c
+index bfe46aa90362..4f4f7f41a7d1 100644
+--- a/sound/soc/codecs/dfbmcs320.c
++++ b/sound/soc/codecs/dfbmcs320.c
+@@ -33,13 +33,13 @@ static struct snd_soc_dai_driver dfbmcs320_dai = {
+ 
+ static struct snd_soc_codec_driver soc_codec_dev_dfbmcs320;
+ 
+-static int __devinit dfbmcs320_probe(struct platform_device *pdev)
++static int dfbmcs320_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_dfbmcs320,
+ 			&dfbmcs320_dai, 1);
+ }
+ 
+-static int __devexit dfbmcs320_remove(struct platform_device *pdev)
++static int dfbmcs320_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_codec(&pdev->dev);
+ 
+@@ -52,7 +52,7 @@ static struct platform_driver dfmcs320_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = dfbmcs320_probe,
+-	.remove = __devexit_p(dfbmcs320_remove),
++	.remove = dfbmcs320_remove,
+ };
+ 
+ module_platform_driver(dfmcs320_driver);
+diff --git a/sound/soc/codecs/dmic.c b/sound/soc/codecs/dmic.c
+index 3e929f079a1f..66967ba6f757 100644
+--- a/sound/soc/codecs/dmic.c
++++ b/sound/soc/codecs/dmic.c
+@@ -66,13 +66,13 @@ static struct snd_soc_codec_driver soc_dmic = {
+ 	.probe	= dmic_probe,
+ };
+ 
+-static int __devinit dmic_dev_probe(struct platform_device *pdev)
++static int dmic_dev_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_codec(&pdev->dev,
+ 			&soc_dmic, &dmic_dai, 1);
+ }
+ 
+-static int __devexit dmic_dev_remove(struct platform_device *pdev)
++static int dmic_dev_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_codec(&pdev->dev);
+ 	return 0;
+@@ -86,7 +86,7 @@ static struct platform_driver dmic_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = dmic_dev_probe,
+-	.remove = __devexit_p(dmic_dev_remove),
++	.remove = dmic_dev_remove,
+ };
+ 
+ module_platform_driver(dmic_driver);
+diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c
+index 9ad1da36887e..d991529e1aff 100644
+--- a/sound/soc/codecs/jz4740.c
++++ b/sound/soc/codecs/jz4740.c
+@@ -348,7 +348,7 @@ static const struct regmap_config jz4740_codec_regmap_config = {
+ 	.cache_type = REGCACHE_RBTREE,
+ };
+ 
+-static int __devinit jz4740_codec_probe(struct platform_device *pdev)
++static int jz4740_codec_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 	struct jz4740_codec *jz4740_codec;
+@@ -380,7 +380,7 @@ static int __devinit jz4740_codec_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit jz4740_codec_remove(struct platform_device *pdev)
++static int jz4740_codec_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_codec(&pdev->dev);
+ 
+@@ -391,7 +391,7 @@ static int __devexit jz4740_codec_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver jz4740_codec_driver = {
+ 	.probe = jz4740_codec_probe,
+-	.remove = __devexit_p(jz4740_codec_remove),
++	.remove = jz4740_codec_remove,
+ 	.driver = {
+ 		.name = "jz4740-codec",
+ 		.owner = THIS_MODULE,
+diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c
+index 81a328c78838..9f9f59573f72 100644
+--- a/sound/soc/codecs/lm4857.c
++++ b/sound/soc/codecs/lm4857.c
+@@ -209,8 +209,8 @@ static struct snd_soc_codec_driver soc_codec_dev_lm4857 = {
+ 	.set_bias_level = lm4857_set_bias_level,
+ };
+ 
+-static int __devinit lm4857_i2c_probe(struct i2c_client *i2c,
+-	const struct i2c_device_id *id)
++static int lm4857_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct lm4857 *lm4857;
+ 	int ret;
+@@ -228,7 +228,7 @@ static int __devinit lm4857_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static int __devexit lm4857_i2c_remove(struct i2c_client *i2c)
++static int lm4857_i2c_remove(struct i2c_client *i2c)
+ {
+ 	snd_soc_unregister_codec(&i2c->dev);
+ 	return 0;
+@@ -246,7 +246,7 @@ static struct i2c_driver lm4857_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = lm4857_i2c_probe,
+-	.remove = __devexit_p(lm4857_i2c_remove),
++	.remove = lm4857_i2c_remove,
+ 	.id_table = lm4857_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c
+index a777de6a1b23..a6ac2313047d 100644
+--- a/sound/soc/codecs/max9768.c
++++ b/sound/soc/codecs/max9768.c
+@@ -159,8 +159,8 @@ static const struct regmap_config max9768_i2c_regmap_config = {
+ 	.cache_type = REGCACHE_RBTREE,
+ };
+ 
+-static int __devinit max9768_i2c_probe(struct i2c_client *client,
+-	const struct i2c_device_id *id)
++static int max9768_i2c_probe(struct i2c_client *client,
++			     const struct i2c_device_id *id)
+ {
+ 	struct max9768 *max9768;
+ 	struct max9768_pdata *pdata = client->dev.platform_data;
+@@ -208,7 +208,7 @@ static int __devinit max9768_i2c_probe(struct i2c_client *client,
+ 	return err;
+ }
+ 
+-static int __devexit max9768_i2c_remove(struct i2c_client *client)
++static int max9768_i2c_remove(struct i2c_client *client)
+ {
+ 	struct max9768 *max9768 = i2c_get_clientdata(client);
+ 
+@@ -234,7 +234,7 @@ static struct i2c_driver max9768_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = max9768_i2c_probe,
+-	.remove = __devexit_p(max9768_i2c_remove),
++	.remove = max9768_i2c_remove,
+ 	.id_table = max9768_i2c_id,
+ };
+ module_i2c_driver(max9768_i2c_driver);
+diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
+index b858264235c4..a4c16fd70f77 100644
+--- a/sound/soc/codecs/max98088.c
++++ b/sound/soc/codecs/max98088.c
+@@ -2084,7 +2084,7 @@ static int max98088_i2c_probe(struct i2c_client *i2c,
+        return ret;
+ }
+ 
+-static int __devexit max98088_i2c_remove(struct i2c_client *client)
++static int max98088_i2c_remove(struct i2c_client *client)
+ {
+        snd_soc_unregister_codec(&client->dev);
+        return 0;
+diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c
+index 38d43c59d3f4..41cdd1642970 100644
+--- a/sound/soc/codecs/max98095.c
++++ b/sound/soc/codecs/max98095.c
+@@ -2511,7 +2511,7 @@ static int max98095_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static int __devexit max98095_i2c_remove(struct i2c_client *client)
++static int max98095_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -2529,7 +2529,7 @@ static struct i2c_driver max98095_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe  = max98095_i2c_probe,
+-	.remove = __devexit_p(max98095_i2c_remove),
++	.remove = max98095_i2c_remove,
+ 	.id_table = max98095_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c
+index efe535c37b39..58c38a5b481c 100644
+--- a/sound/soc/codecs/max9850.c
++++ b/sound/soc/codecs/max9850.c
+@@ -329,8 +329,8 @@ static struct snd_soc_codec_driver soc_codec_dev_max9850 = {
+ 	.num_dapm_routes = ARRAY_SIZE(max9850_dapm_routes),
+ };
+ 
+-static int __devinit max9850_i2c_probe(struct i2c_client *i2c,
+-		const struct i2c_device_id *id)
++static int max9850_i2c_probe(struct i2c_client *i2c,
++			     const struct i2c_device_id *id)
+ {
+ 	struct max9850_priv *max9850;
+ 	int ret;
+@@ -347,7 +347,7 @@ static int __devinit max9850_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int max9850_i2c_remove(struct i2c_client *client)
++static int max9850_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -365,7 +365,7 @@ static struct i2c_driver max9850_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = max9850_i2c_probe,
+-	.remove = __devexit_p(max9850_i2c_remove),
++	.remove = max9850_i2c_remove,
+ 	.id_table = max9850_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/max9877.c b/sound/soc/codecs/max9877.c
+index d15e5943c85e..6b6c74cd83e2 100644
+--- a/sound/soc/codecs/max9877.c
++++ b/sound/soc/codecs/max9877.c
+@@ -258,8 +258,8 @@ int max9877_add_controls(struct snd_soc_codec *codec)
+ }
+ EXPORT_SYMBOL_GPL(max9877_add_controls);
+ 
+-static int __devinit max9877_i2c_probe(struct i2c_client *client,
+-		const struct i2c_device_id *id)
++static int max9877_i2c_probe(struct i2c_client *client,
++			     const struct i2c_device_id *id)
+ {
+ 	i2c = client;
+ 
+@@ -268,7 +268,7 @@ static int __devinit max9877_i2c_probe(struct i2c_client *client,
+ 	return 0;
+ }
+ 
+-static __devexit int max9877_i2c_remove(struct i2c_client *client)
++static int max9877_i2c_remove(struct i2c_client *client)
+ {
+ 	i2c = NULL;
+ 
+@@ -287,7 +287,7 @@ static struct i2c_driver max9877_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = max9877_i2c_probe,
+-	.remove = __devexit_p(max9877_i2c_remove),
++	.remove = max9877_i2c_remove,
+ 	.id_table = max9877_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c
+index bc955999c8aa..5402dfbbb716 100644
+--- a/sound/soc/codecs/mc13783.c
++++ b/sound/soc/codecs/mc13783.c
+@@ -779,7 +779,7 @@ static struct platform_driver mc13783_codec_driver = {
+ 		   .owner = THIS_MODULE,
+ 		   },
+ 	.probe = mc13783_codec_probe,
+-	.remove = __devexit_p(mc13783_codec_remove),
++	.remove = mc13783_codec_remove,
+ };
+ 
+ module_platform_driver(mc13783_codec_driver);
+diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c
+index 96aa5fa05160..26118828782b 100644
+--- a/sound/soc/codecs/ml26124.c
++++ b/sound/soc/codecs/ml26124.c
+@@ -626,8 +626,8 @@ static const struct regmap_config ml26124_i2c_regmap = {
+ 	.write_flag_mask = 0x01,
+ };
+ 
+-static __devinit int ml26124_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int ml26124_i2c_probe(struct i2c_client *i2c,
++			     const struct i2c_device_id *id)
+ {
+ 	struct ml26124_priv *priv;
+ 	int ret;
+@@ -649,7 +649,7 @@ static __devinit int ml26124_i2c_probe(struct i2c_client *i2c,
+ 			&soc_codec_dev_ml26124, &ml26124_dai, 1);
+ }
+ 
+-static __devexit int ml26124_i2c_remove(struct i2c_client *client)
++static int ml26124_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -667,7 +667,7 @@ static struct i2c_driver ml26124_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = ml26124_i2c_probe,
+-	.remove = __devexit_p(ml26124_i2c_remove),
++	.remove = ml26124_i2c_remove,
+ 	.id_table = ml26124_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/omap-hdmi.c b/sound/soc/codecs/omap-hdmi.c
+index 1bf5c74f5f96..529d06444c54 100644
+--- a/sound/soc/codecs/omap-hdmi.c
++++ b/sound/soc/codecs/omap-hdmi.c
+@@ -39,13 +39,13 @@ static struct snd_soc_dai_driver omap_hdmi_codec_dai = {
+ 	},
+ };
+ 
+-static __devinit int omap_hdmi_codec_probe(struct platform_device *pdev)
++static int omap_hdmi_codec_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_codec(&pdev->dev, &omap_hdmi_codec,
+ 			&omap_hdmi_codec_dai, 1);
+ }
+ 
+-static __devexit int omap_hdmi_codec_remove(struct platform_device *pdev)
++static int omap_hdmi_codec_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_codec(&pdev->dev);
+ 	return 0;
+@@ -58,7 +58,7 @@ static struct platform_driver omap_hdmi_codec_driver = {
+ 	},
+ 
+ 	.probe		= omap_hdmi_codec_probe,
+-	.remove		= __devexit_p(omap_hdmi_codec_remove),
++	.remove		= omap_hdmi_codec_remove,
+ };
+ 
+ module_platform_driver(omap_hdmi_codec_driver);
+diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c
+index edcaa7ea5487..f2a6282b41f4 100644
+--- a/sound/soc/codecs/pcm3008.c
++++ b/sound/soc/codecs/pcm3008.c
+@@ -149,13 +149,13 @@ static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = {
+ 	.resume =	pcm3008_soc_resume,
+ };
+ 
+-static int __devinit pcm3008_codec_probe(struct platform_device *pdev)
++static int pcm3008_codec_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_codec(&pdev->dev,
+ 			&soc_codec_dev_pcm3008, &pcm3008_dai, 1);
+ }
+ 
+-static int __devexit pcm3008_codec_remove(struct platform_device *pdev)
++static int pcm3008_codec_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_codec(&pdev->dev);
+ 	return 0;
+@@ -165,7 +165,7 @@ MODULE_ALIAS("platform:pcm3008-codec");
+ 
+ static struct platform_driver pcm3008_codec_driver = {
+ 	.probe		= pcm3008_codec_probe,
+-	.remove		= __devexit_p(pcm3008_codec_remove),
++	.remove		= pcm3008_codec_remove,
+ 	.driver		= {
+ 		.name	= "pcm3008-codec",
+ 		.owner	= THIS_MODULE,
+diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c
+index d6ca615489ee..912c9cbc2724 100644
+--- a/sound/soc/codecs/rt5631.c
++++ b/sound/soc/codecs/rt5631.c
+@@ -1748,7 +1748,7 @@ static int rt5631_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int rt5631_i2c_remove(struct i2c_client *client)
++static int rt5631_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -1760,7 +1760,7 @@ static struct i2c_driver rt5631_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = rt5631_i2c_probe,
+-	.remove   = __devexit_p(rt5631_i2c_remove),
++	.remove   = rt5631_i2c_remove,
+ 	.id_table = rt5631_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
+index df2f99d1d428..cb1675cd8e1c 100644
+--- a/sound/soc/codecs/sgtl5000.c
++++ b/sound/soc/codecs/sgtl5000.c
+@@ -1404,8 +1404,8 @@ static struct snd_soc_codec_driver sgtl5000_driver = {
+ 	.num_dapm_routes = ARRAY_SIZE(sgtl5000_dapm_routes),
+ };
+ 
+-static __devinit int sgtl5000_i2c_probe(struct i2c_client *client,
+-					const struct i2c_device_id *id)
++static int sgtl5000_i2c_probe(struct i2c_client *client,
++			      const struct i2c_device_id *id)
+ {
+ 	struct sgtl5000_priv *sgtl5000;
+ 	int ret;
+@@ -1422,7 +1422,7 @@ static __devinit int sgtl5000_i2c_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static __devexit int sgtl5000_i2c_remove(struct i2c_client *client)
++static int sgtl5000_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 
+@@ -1449,7 +1449,7 @@ static struct i2c_driver sgtl5000_i2c_driver = {
+ 		   .of_match_table = sgtl5000_dt_ids,
+ 		   },
+ 	.probe = sgtl5000_i2c_probe,
+-	.remove = __devexit_p(sgtl5000_i2c_remove),
++	.remove = sgtl5000_i2c_remove,
+ 	.id_table = sgtl5000_id,
+ };
+ 
+diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c
+index 38145ba74db8..f2d61a187830 100644
+--- a/sound/soc/codecs/si476x.c
++++ b/sound/soc/codecs/si476x.c
+@@ -226,13 +226,13 @@ static struct snd_soc_codec_driver soc_codec_dev_si476x = {
+ 	.write  = si476x_codec_write,
+ };
+ 
+-static int __devinit si476x_platform_probe(struct platform_device *pdev)
++static int si476x_platform_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_si476x,
+ 				      &si476x_dai, 1);
+ }
+ 
+-static int __devexit si476x_platform_remove(struct platform_device *pdev)
++static int si476x_platform_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_codec(&pdev->dev);
+ 	return 0;
+@@ -246,7 +246,7 @@ static struct platform_driver si476x_platform_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= si476x_platform_probe,
+-	.remove		= __devexit_p(si476x_platform_remove),
++	.remove		= si476x_platform_remove,
+ };
+ module_platform_driver(si476x_platform_driver);
+ 
+diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c
+index 50dbdb9357ea..d1ae869d3181 100644
+--- a/sound/soc/codecs/sn95031.c
++++ b/sound/soc/codecs/sn95031.c
+@@ -896,14 +896,14 @@ struct snd_soc_codec_driver sn95031_codec = {
+ 	.num_dapm_routes	= ARRAY_SIZE(sn95031_audio_map),
+ };
+ 
+-static int __devinit sn95031_device_probe(struct platform_device *pdev)
++static int sn95031_device_probe(struct platform_device *pdev)
+ {
+ 	pr_debug("codec device probe called for %s\n", dev_name(&pdev->dev));
+ 	return snd_soc_register_codec(&pdev->dev, &sn95031_codec,
+ 			sn95031_dais, ARRAY_SIZE(sn95031_dais));
+ }
+ 
+-static int __devexit sn95031_device_remove(struct platform_device *pdev)
++static int sn95031_device_remove(struct platform_device *pdev)
+ {
+ 	pr_debug("codec device remove called\n");
+ 	snd_soc_unregister_codec(&pdev->dev);
+@@ -916,7 +916,7 @@ static struct platform_driver sn95031_codec_driver = {
+ 		.owner		= THIS_MODULE,
+ 	},
+ 	.probe		= sn95031_device_probe,
+-	.remove		= __devexit_p(sn95031_device_remove),
++	.remove		= sn95031_device_remove,
+ };
+ 
+ module_platform_driver(sn95031_codec_driver);
+diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
+index 079066fef425..f8d30e5f6371 100644
+--- a/sound/soc/codecs/ssm2602.c
++++ b/sound/soc/codecs/ssm2602.c
+@@ -691,7 +691,7 @@ static const struct regmap_config ssm2602_regmap_config = {
+ };
+ 
+ #if defined(CONFIG_SPI_MASTER)
+-static int __devinit ssm2602_spi_probe(struct spi_device *spi)
++static int ssm2602_spi_probe(struct spi_device *spi)
+ {
+ 	struct ssm2602_priv *ssm2602;
+ 	int ret;
+@@ -713,7 +713,7 @@ static int __devinit ssm2602_spi_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit ssm2602_spi_remove(struct spi_device *spi)
++static int ssm2602_spi_remove(struct spi_device *spi)
+ {
+ 	snd_soc_unregister_codec(&spi->dev);
+ 	return 0;
+@@ -725,7 +725,7 @@ static struct spi_driver ssm2602_spi_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= ssm2602_spi_probe,
+-	.remove		= __devexit_p(ssm2602_spi_remove),
++	.remove		= ssm2602_spi_remove,
+ };
+ #endif
+ 
+@@ -736,7 +736,7 @@ static struct spi_driver ssm2602_spi_driver = {
+  *    low  = 0x1a
+  *    high = 0x1b
+  */
+-static int __devinit ssm2602_i2c_probe(struct i2c_client *i2c,
++static int ssm2602_i2c_probe(struct i2c_client *i2c,
+ 			     const struct i2c_device_id *id)
+ {
+ 	struct ssm2602_priv *ssm2602;
+@@ -759,7 +759,7 @@ static int __devinit ssm2602_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static int __devexit ssm2602_i2c_remove(struct i2c_client *client)
++static int ssm2602_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -780,7 +780,7 @@ static struct i2c_driver ssm2602_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = ssm2602_i2c_probe,
+-	.remove = __devexit_p(ssm2602_i2c_remove),
++	.remove = ssm2602_i2c_remove,
+ 	.id_table = ssm2602_i2c_id,
+ };
+ #endif
+diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c
+index 0935bfe62471..cfb55fe35e98 100644
+--- a/sound/soc/codecs/sta32x.c
++++ b/sound/soc/codecs/sta32x.c
+@@ -995,8 +995,8 @@ static const struct regmap_config sta32x_regmap = {
+ 	.volatile_reg =		sta32x_reg_is_volatile,
+ };
+ 
+-static __devinit int sta32x_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int sta32x_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct sta32x_priv *sta32x;
+ 	int ret, i;
+@@ -1033,7 +1033,7 @@ static __devinit int sta32x_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int sta32x_i2c_remove(struct i2c_client *client)
++static int sta32x_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -1053,7 +1053,7 @@ static struct i2c_driver sta32x_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe =    sta32x_i2c_probe,
+-	.remove =   __devexit_p(sta32x_i2c_remove),
++	.remove =   sta32x_i2c_remove,
+ 	.id_table = sta32x_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c
+index 9e3144862386..ab355c4f0b2d 100644
+--- a/sound/soc/codecs/sta529.c
++++ b/sound/soc/codecs/sta529.c
+@@ -380,8 +380,8 @@ static const struct regmap_config sta529_regmap = {
+ 	.num_reg_defaults = ARRAY_SIZE(sta529_reg_defaults),
+ };
+ 
+-static __devinit int sta529_i2c_probe(struct i2c_client *i2c,
+-		const struct i2c_device_id *id)
++static int sta529_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct sta529 *sta529;
+ 	int ret;
+@@ -412,7 +412,7 @@ static __devinit int sta529_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static int __devexit sta529_i2c_remove(struct i2c_client *client)
++static int sta529_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 
+@@ -431,7 +431,7 @@ static struct i2c_driver sta529_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe		= sta529_i2c_probe,
+-	.remove		= __devexit_p(sta529_i2c_remove),
++	.remove		= sta529_i2c_remove,
+ 	.id_table	= sta529_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c
+index 982e437799a8..2eda85ba79ac 100644
+--- a/sound/soc/codecs/stac9766.c
++++ b/sound/soc/codecs/stac9766.c
+@@ -385,13 +385,13 @@ static struct snd_soc_codec_driver soc_codec_dev_stac9766 = {
+ 	.reg_cache_default = stac9766_reg,
+ };
+ 
+-static __devinit int stac9766_probe(struct platform_device *pdev)
++static int stac9766_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_codec(&pdev->dev,
+ 			&soc_codec_dev_stac9766, stac9766_dai, ARRAY_SIZE(stac9766_dai));
+ }
+ 
+-static int __devexit stac9766_remove(struct platform_device *pdev)
++static int stac9766_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_codec(&pdev->dev);
+ 	return 0;
+@@ -404,7 +404,7 @@ static struct platform_driver stac9766_codec_driver = {
+ 	},
+ 
+ 	.probe = stac9766_probe,
+-	.remove = __devexit_p(stac9766_remove),
++	.remove = stac9766_remove,
+ };
+ 
+ module_platform_driver(stac9766_codec_driver);
+diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
+index e39e08d5d8e4..17df4e32feac 100644
+--- a/sound/soc/codecs/tlv320aic32x4.c
++++ b/sound/soc/codecs/tlv320aic32x4.c
+@@ -716,8 +716,8 @@ static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = {
+ 	.set_bias_level = aic32x4_set_bias_level,
+ };
+ 
+-static __devinit int aic32x4_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int aic32x4_i2c_probe(struct i2c_client *i2c,
++			     const struct i2c_device_id *id)
+ {
+ 	struct aic32x4_pdata *pdata = i2c->dev.platform_data;
+ 	struct aic32x4_priv *aic32x4;
+@@ -748,7 +748,7 @@ static __devinit int aic32x4_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int aic32x4_i2c_remove(struct i2c_client *client)
++static int aic32x4_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -766,7 +766,7 @@ static struct i2c_driver aic32x4_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe =    aic32x4_i2c_probe,
+-	.remove =   __devexit_p(aic32x4_i2c_remove),
++	.remove =   aic32x4_i2c_remove,
+ 	.id_table = aic32x4_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
+index d2e16c5d7d1f..782b0cded2e6 100644
+--- a/sound/soc/codecs/tlv320dac33.c
++++ b/sound/soc/codecs/tlv320dac33.c
+@@ -1514,8 +1514,8 @@ static struct snd_soc_dai_driver dac33_dai = {
+ 	.ops = &dac33_dai_ops,
+ };
+ 
+-static int __devinit dac33_i2c_probe(struct i2c_client *client,
+-				     const struct i2c_device_id *id)
++static int dac33_i2c_probe(struct i2c_client *client,
++			   const struct i2c_device_id *id)
+ {
+ 	struct tlv320dac33_platform_data *pdata;
+ 	struct tlv320dac33_priv *dac33;
+@@ -1586,7 +1586,7 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit dac33_i2c_remove(struct i2c_client *client)
++static int dac33_i2c_remove(struct i2c_client *client)
+ {
+ 	struct tlv320dac33_priv *dac33 = i2c_get_clientdata(client);
+ 
+@@ -1617,7 +1617,7 @@ static struct i2c_driver tlv320dac33_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe		= dac33_i2c_probe,
+-	.remove		= __devexit_p(dac33_i2c_remove),
++	.remove		= dac33_i2c_remove,
+ 	.id_table	= tlv320dac33_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c
+index 565ff39ad3a3..8d75aa152c8c 100644
+--- a/sound/soc/codecs/tpa6130a2.c
++++ b/sound/soc/codecs/tpa6130a2.c
+@@ -359,8 +359,8 @@ int tpa6130a2_add_controls(struct snd_soc_codec *codec)
+ }
+ EXPORT_SYMBOL_GPL(tpa6130a2_add_controls);
+ 
+-static int __devinit tpa6130a2_probe(struct i2c_client *client,
+-				     const struct i2c_device_id *id)
++static int tpa6130a2_probe(struct i2c_client *client,
++			   const struct i2c_device_id *id)
+ {
+ 	struct device *dev;
+ 	struct tpa6130a2_data *data;
+@@ -455,7 +455,7 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit tpa6130a2_remove(struct i2c_client *client)
++static int tpa6130a2_remove(struct i2c_client *client)
+ {
+ 	struct tpa6130a2_data *data = i2c_get_clientdata(client);
+ 
+@@ -483,7 +483,7 @@ static struct i2c_driver tpa6130a2_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = tpa6130a2_probe,
+-	.remove = __devexit_p(tpa6130a2_remove),
++	.remove = tpa6130a2_remove,
+ 	.id_table = tpa6130a2_id,
+ };
+ 
+diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
+index 00b85cc1b9a3..3fc3fc64dd8b 100644
+--- a/sound/soc/codecs/twl6040.c
++++ b/sound/soc/codecs/twl6040.c
+@@ -1229,13 +1229,13 @@ static struct snd_soc_codec_driver soc_codec_dev_twl6040 = {
+ 	.num_dapm_routes = ARRAY_SIZE(intercon),
+ };
+ 
+-static int __devinit twl6040_codec_probe(struct platform_device *pdev)
++static int twl6040_codec_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl6040,
+ 				      twl6040_dai, ARRAY_SIZE(twl6040_dai));
+ }
+ 
+-static int __devexit twl6040_codec_remove(struct platform_device *pdev)
++static int twl6040_codec_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_codec(&pdev->dev);
+ 	return 0;
+@@ -1247,7 +1247,7 @@ static struct platform_driver twl6040_codec_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = twl6040_codec_probe,
+-	.remove = __devexit_p(twl6040_codec_remove),
++	.remove = twl6040_codec_remove,
+ };
+ 
+ module_platform_driver(twl6040_codec_driver);
+diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
+index 6c3d43b8ee85..6d0aa44c3757 100644
+--- a/sound/soc/codecs/uda134x.c
++++ b/sound/soc/codecs/uda134x.c
+@@ -601,13 +601,13 @@ static struct snd_soc_codec_driver soc_codec_dev_uda134x = {
+ 	.set_bias_level = uda134x_set_bias_level,
+ };
+ 
+-static int __devinit uda134x_codec_probe(struct platform_device *pdev)
++static int uda134x_codec_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_codec(&pdev->dev,
+ 			&soc_codec_dev_uda134x, &uda134x_dai, 1);
+ }
+ 
+-static int __devexit uda134x_codec_remove(struct platform_device *pdev)
++static int uda134x_codec_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_codec(&pdev->dev);
+ 	return 0;
+@@ -619,7 +619,7 @@ static struct platform_driver uda134x_codec_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = uda134x_codec_probe,
+-	.remove = __devexit_p(uda134x_codec_remove),
++	.remove = uda134x_codec_remove,
+ };
+ 
+ module_platform_driver(uda134x_codec_driver);
+diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
+index 2502214b84ab..fd0a314bc209 100644
+--- a/sound/soc/codecs/uda1380.c
++++ b/sound/soc/codecs/uda1380.c
+@@ -795,8 +795,8 @@ static struct snd_soc_codec_driver soc_codec_dev_uda1380 = {
+ };
+ 
+ #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+-static __devinit int uda1380_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int uda1380_i2c_probe(struct i2c_client *i2c,
++			     const struct i2c_device_id *id)
+ {
+ 	struct uda1380_priv *uda1380;
+ 	int ret;
+@@ -814,7 +814,7 @@ static __devinit int uda1380_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static int __devexit uda1380_i2c_remove(struct i2c_client *i2c)
++static int uda1380_i2c_remove(struct i2c_client *i2c)
+ {
+ 	snd_soc_unregister_codec(&i2c->dev);
+ 	return 0;
+@@ -832,7 +832,7 @@ static struct i2c_driver uda1380_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe =    uda1380_i2c_probe,
+-	.remove =   __devexit_p(uda1380_i2c_remove),
++	.remove =   uda1380_i2c_remove,
+ 	.id_table = uda1380_i2c_id,
+ };
+ #endif
+diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c
+index 7b24d6d192e1..54cd3da09abd 100644
+--- a/sound/soc/codecs/wl1273.c
++++ b/sound/soc/codecs/wl1273.c
+@@ -485,13 +485,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wl1273 = {
+ 	.remove = wl1273_remove,
+ };
+ 
+-static int __devinit wl1273_platform_probe(struct platform_device *pdev)
++static int wl1273_platform_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wl1273,
+ 				      &wl1273_dai, 1);
+ }
+ 
+-static int __devexit wl1273_platform_remove(struct platform_device *pdev)
++static int wl1273_platform_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_codec(&pdev->dev);
+ 	return 0;
+@@ -505,7 +505,7 @@ static struct platform_driver wl1273_platform_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= wl1273_platform_probe,
+-	.remove		= __devexit_p(wl1273_platform_remove),
++	.remove		= wl1273_platform_remove,
+ };
+ 
+ module_platform_driver(wl1273_platform_driver);
+diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c
+index 40256b526259..ad2fee4bb4cd 100644
+--- a/sound/soc/codecs/wm0010.c
++++ b/sound/soc/codecs/wm0010.c
+@@ -885,7 +885,7 @@ static int wm0010_probe(struct snd_soc_codec *codec)
+ 	return 0;
+ }
+ 
+-static int __devinit wm0010_spi_probe(struct spi_device *spi)
++static int wm0010_spi_probe(struct spi_device *spi)
+ {
+ 	unsigned long gpio_flags;
+ 	int ret;
+@@ -985,7 +985,7 @@ static int __devinit wm0010_spi_probe(struct spi_device *spi)
+ 	return 0;
+ }
+ 
+-static int __devexit wm0010_spi_remove(struct spi_device *spi)
++static int wm0010_spi_remove(struct spi_device *spi)
+ {
+ 	struct wm0010_priv *wm0010 = spi_get_drvdata(spi);
+ 
+@@ -1007,7 +1007,7 @@ static struct spi_driver wm0010_spi_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= wm0010_spi_probe,
+-	.remove		= __devexit_p(wm0010_spi_remove),
++	.remove		= wm0010_spi_remove,
+ };
+ 
+ module_spi_driver(wm0010_spi_driver);
+diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c
+index 951d7b49476a..6e6b93d4696e 100644
+--- a/sound/soc/codecs/wm1250-ev1.c
++++ b/sound/soc/codecs/wm1250-ev1.c
+@@ -153,7 +153,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm1250_ev1 = {
+ 	.idle_bias_off = true,
+ };
+ 
+-static int __devinit wm1250_ev1_pdata(struct i2c_client *i2c)
++static int wm1250_ev1_pdata(struct i2c_client *i2c)
+ {
+ 	struct wm1250_ev1_pdata *pdata = dev_get_platdata(&i2c->dev);
+ 	struct wm1250_priv *wm1250;
+@@ -199,8 +199,8 @@ static void wm1250_ev1_free(struct i2c_client *i2c)
+ 		gpio_free_array(wm1250->gpios, ARRAY_SIZE(wm1250->gpios));
+ }
+ 
+-static int __devinit wm1250_ev1_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *i2c_id)
++static int wm1250_ev1_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *i2c_id)
+ {
+ 	int id, board, rev, ret;
+ 
+@@ -237,7 +237,7 @@ static int __devinit wm1250_ev1_probe(struct i2c_client *i2c,
+ 	return 0;
+ }
+ 
+-static int __devexit wm1250_ev1_remove(struct i2c_client *i2c)
++static int wm1250_ev1_remove(struct i2c_client *i2c)
+ {
+ 	snd_soc_unregister_codec(&i2c->dev);
+ 	wm1250_ev1_free(i2c);
+@@ -257,7 +257,7 @@ static struct i2c_driver wm1250_ev1_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe =    wm1250_ev1_probe,
+-	.remove =   __devexit_p(wm1250_ev1_remove),
++	.remove =   wm1250_ev1_remove,
+ 	.id_table = wm1250_ev1_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c
+index 02750ab020de..1cbe88f01d63 100644
+--- a/sound/soc/codecs/wm2000.c
++++ b/sound/soc/codecs/wm2000.c
+@@ -764,8 +764,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm2000 = {
+ 	.num_controls = ARRAY_SIZE(wm2000_controls),
+ };
+ 
+-static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *i2c_id)
++static int wm2000_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *i2c_id)
+ {
+ 	struct wm2000_priv *wm2000;
+ 	struct wm2000_platform_data *pdata;
+@@ -871,7 +871,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm2000_i2c_remove(struct i2c_client *i2c)
++static int wm2000_i2c_remove(struct i2c_client *i2c)
+ {
+ 	snd_soc_unregister_codec(&i2c->dev);
+ 
+@@ -890,7 +890,7 @@ static struct i2c_driver wm2000_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = wm2000_i2c_probe,
+-	.remove = __devexit_p(wm2000_i2c_remove),
++	.remove = wm2000_i2c_remove,
+ 	.id_table = wm2000_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c
+index ff45b02a9dff..afcf31df77e0 100644
+--- a/sound/soc/codecs/wm2200.c
++++ b/sound/soc/codecs/wm2200.c
+@@ -2184,8 +2184,8 @@ static const unsigned int wm2200_mic_ctrl_reg[] = {
+ 	WM2200_IN3L_CONTROL,
+ };
+ 
+-static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm2200_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm2200_pdata *pdata = dev_get_platdata(&i2c->dev);
+ 	struct wm2200_priv *wm2200;
+@@ -2385,7 +2385,7 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm2200_i2c_remove(struct i2c_client *i2c)
++static int wm2200_i2c_remove(struct i2c_client *i2c)
+ {
+ 	struct wm2200_priv *wm2200 = i2c_get_clientdata(i2c);
+ 
+@@ -2458,7 +2458,7 @@ static struct i2c_driver wm2200_i2c_driver = {
+ 		.pm = &wm2200_pm,
+ 	},
+ 	.probe =    wm2200_i2c_probe,
+-	.remove =   __devexit_p(wm2200_i2c_remove),
++	.remove =   wm2200_i2c_remove,
+ 	.id_table = wm2200_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c
+index 9f57996ff272..5a5f36936235 100644
+--- a/sound/soc/codecs/wm5100.c
++++ b/sound/soc/codecs/wm5100.c
+@@ -2414,8 +2414,8 @@ static const unsigned int wm5100_mic_ctrl_reg[] = {
+ 	WM5100_IN4L_CONTROL,
+ };
+ 
+-static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm5100_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm5100_pdata *pdata = dev_get_platdata(&i2c->dev);
+ 	struct wm5100_priv *wm5100;
+@@ -2639,7 +2639,7 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm5100_i2c_remove(struct i2c_client *i2c)
++static int wm5100_i2c_remove(struct i2c_client *i2c)
+ {
+ 	struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c);
+ 
+@@ -2717,7 +2717,7 @@ static struct i2c_driver wm5100_i2c_driver = {
+ 		.pm = &wm5100_pm,
+ 	},
+ 	.probe =    wm5100_i2c_probe,
+-	.remove =   __devexit_p(wm5100_i2c_remove),
++	.remove =   wm5100_i2c_remove,
+ 	.id_table = wm5100_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c
+index 27f7e38e7eca..688ade080589 100644
+--- a/sound/soc/codecs/wm5102.c
++++ b/sound/soc/codecs/wm5102.c
+@@ -1475,7 +1475,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5102 = {
+ 	.num_dapm_routes = ARRAY_SIZE(wm5102_dapm_routes),
+ };
+ 
+-static int __devinit wm5102_probe(struct platform_device *pdev)
++static int wm5102_probe(struct platform_device *pdev)
+ {
+ 	struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
+ 	struct wm5102_priv *wm5102;
+@@ -1527,7 +1527,7 @@ static int __devinit wm5102_probe(struct platform_device *pdev)
+ 				      wm5102_dai, ARRAY_SIZE(wm5102_dai));
+ }
+ 
+-static int __devexit wm5102_remove(struct platform_device *pdev)
++static int wm5102_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_codec(&pdev->dev);
+ 	pm_runtime_disable(&pdev->dev);
+@@ -1541,7 +1541,7 @@ static struct platform_driver wm5102_codec_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = wm5102_probe,
+-	.remove = __devexit_p(wm5102_remove),
++	.remove = wm5102_remove,
+ };
+ 
+ module_platform_driver(wm5102_codec_driver);
+diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
+index c57dc7468300..ae80c8c28536 100644
+--- a/sound/soc/codecs/wm5110.c
++++ b/sound/soc/codecs/wm5110.c
+@@ -992,7 +992,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5110 = {
+ 	.num_dapm_routes = ARRAY_SIZE(wm5110_dapm_routes),
+ };
+ 
+-static int __devinit wm5110_probe(struct platform_device *pdev)
++static int wm5110_probe(struct platform_device *pdev)
+ {
+ 	struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
+ 	struct wm5110_priv *wm5110;
+@@ -1031,7 +1031,7 @@ static int __devinit wm5110_probe(struct platform_device *pdev)
+ 				      wm5110_dai, ARRAY_SIZE(wm5110_dai));
+ }
+ 
+-static int __devexit wm5110_remove(struct platform_device *pdev)
++static int wm5110_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_codec(&pdev->dev);
+ 	pm_runtime_disable(&pdev->dev);
+@@ -1045,7 +1045,7 @@ static struct platform_driver wm5110_codec_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = wm5110_probe,
+-	.remove = __devexit_p(wm5110_remove),
++	.remove = wm5110_remove,
+ };
+ 
+ module_platform_driver(wm5110_codec_driver);
+diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
+index 32b8f0852f6e..fb92fb47d636 100644
+--- a/sound/soc/codecs/wm8350.c
++++ b/sound/soc/codecs/wm8350.c
+@@ -1625,13 +1625,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8350 = {
+ 	.num_dapm_routes = ARRAY_SIZE(wm8350_dapm_routes),
+ };
+ 
+-static int __devinit wm8350_probe(struct platform_device *pdev)
++static int wm8350_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8350,
+ 			&wm8350_dai, 1);
+ }
+ 
+-static int __devexit wm8350_remove(struct platform_device *pdev)
++static int wm8350_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_codec(&pdev->dev);
+ 	return 0;
+@@ -1643,7 +1643,7 @@ static struct platform_driver wm8350_codec_driver = {
+ 		   .owner = THIS_MODULE,
+ 		   },
+ 	.probe = wm8350_probe,
+-	.remove = __devexit_p(wm8350_remove),
++	.remove = wm8350_remove,
+ };
+ 
+ module_platform_driver(wm8350_codec_driver);
+diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
+index 262c44082eb0..af6d227e67be 100644
+--- a/sound/soc/codecs/wm8400.c
++++ b/sound/soc/codecs/wm8400.c
+@@ -1431,13 +1431,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8400 = {
+ 	.num_dapm_routes = ARRAY_SIZE(wm8400_dapm_routes),
+ };
+ 
+-static int __devinit wm8400_probe(struct platform_device *pdev)
++static int wm8400_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8400,
+ 			&wm8400_dai, 1);
+ }
+ 
+-static int __devexit wm8400_remove(struct platform_device *pdev)
++static int wm8400_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_codec(&pdev->dev);
+ 	return 0;
+@@ -1449,7 +1449,7 @@ static struct platform_driver wm8400_codec_driver = {
+ 		   .owner = THIS_MODULE,
+ 		   },
+ 	.probe = wm8400_probe,
+-	.remove = __devexit_p(wm8400_remove),
++	.remove = wm8400_remove,
+ };
+ 
+ module_platform_driver(wm8400_codec_driver);
+diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
+index 923e7e1f6704..6ed5433943ea 100644
+--- a/sound/soc/codecs/wm8510.c
++++ b/sound/soc/codecs/wm8510.c
+@@ -645,7 +645,7 @@ static const struct regmap_config wm8510_regmap = {
+ };
+ 
+ #if defined(CONFIG_SPI_MASTER)
+-static int __devinit wm8510_spi_probe(struct spi_device *spi)
++static int wm8510_spi_probe(struct spi_device *spi)
+ {
+ 	struct wm8510_priv *wm8510;
+ 	int ret;
+@@ -667,7 +667,7 @@ static int __devinit wm8510_spi_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit wm8510_spi_remove(struct spi_device *spi)
++static int wm8510_spi_remove(struct spi_device *spi)
+ {
+ 	snd_soc_unregister_codec(&spi->dev);
+ 	return 0;
+@@ -680,13 +680,13 @@ static struct spi_driver wm8510_spi_driver = {
+ 		.of_match_table = wm8510_of_match,
+ 	},
+ 	.probe		= wm8510_spi_probe,
+-	.remove		= __devexit_p(wm8510_spi_remove),
++	.remove		= wm8510_spi_remove,
+ };
+ #endif /* CONFIG_SPI_MASTER */
+ 
+ #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+-static __devinit int wm8510_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8510_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8510_priv *wm8510;
+ 	int ret;
+@@ -708,7 +708,7 @@ static __devinit int wm8510_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm8510_i2c_remove(struct i2c_client *client)
++static int wm8510_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -727,7 +727,7 @@ static struct i2c_driver wm8510_i2c_driver = {
+ 		.of_match_table = wm8510_of_match,
+ 	},
+ 	.probe =    wm8510_i2c_probe,
+-	.remove =   __devexit_p(wm8510_i2c_remove),
++	.remove =   wm8510_i2c_remove,
+ 	.id_table = wm8510_i2c_id,
+ };
+ #endif
+diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
+index 8d5c27673501..139bf9ac9407 100644
+--- a/sound/soc/codecs/wm8523.c
++++ b/sound/soc/codecs/wm8523.c
+@@ -453,8 +453,8 @@ static const struct regmap_config wm8523_regmap = {
+ };
+ 
+ #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+-static __devinit int wm8523_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8523_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8523_priv *wm8523;
+ 	unsigned int val;
+@@ -528,7 +528,7 @@ static __devinit int wm8523_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm8523_i2c_remove(struct i2c_client *client)
++static int wm8523_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -547,7 +547,7 @@ static struct i2c_driver wm8523_i2c_driver = {
+ 		.of_match_table = wm8523_of_match,
+ 	},
+ 	.probe =    wm8523_i2c_probe,
+-	.remove =   __devexit_p(wm8523_i2c_remove),
++	.remove =   wm8523_i2c_remove,
+ 	.id_table = wm8523_i2c_id,
+ };
+ #endif
+diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c
+index 8b8bb70f1eb9..5b428b060d41 100644
+--- a/sound/soc/codecs/wm8711.c
++++ b/sound/soc/codecs/wm8711.c
+@@ -429,7 +429,7 @@ static const struct regmap_config wm8711_regmap = {
+ };
+ 
+ #if defined(CONFIG_SPI_MASTER)
+-static int __devinit wm8711_spi_probe(struct spi_device *spi)
++static int wm8711_spi_probe(struct spi_device *spi)
+ {
+ 	struct wm8711_priv *wm8711;
+ 	int ret;
+@@ -451,7 +451,7 @@ static int __devinit wm8711_spi_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit wm8711_spi_remove(struct spi_device *spi)
++static int wm8711_spi_remove(struct spi_device *spi)
+ {
+ 	snd_soc_unregister_codec(&spi->dev);
+ 
+@@ -465,13 +465,13 @@ static struct spi_driver wm8711_spi_driver = {
+ 		.of_match_table = wm8711_of_match,
+ 	},
+ 	.probe		= wm8711_spi_probe,
+-	.remove		= __devexit_p(wm8711_spi_remove),
++	.remove		= wm8711_spi_remove,
+ };
+ #endif /* CONFIG_SPI_MASTER */
+ 
+ #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+-static __devinit int wm8711_i2c_probe(struct i2c_client *client,
+-				      const struct i2c_device_id *id)
++static int wm8711_i2c_probe(struct i2c_client *client,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8711_priv *wm8711;
+ 	int ret;
+@@ -493,7 +493,7 @@ static __devinit int wm8711_i2c_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static __devexit int wm8711_i2c_remove(struct i2c_client *client)
++static int wm8711_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -512,7 +512,7 @@ static struct i2c_driver wm8711_i2c_driver = {
+ 		.of_match_table = wm8711_of_match,
+ 	},
+ 	.probe =    wm8711_i2c_probe,
+-	.remove =   __devexit_p(wm8711_i2c_remove),
++	.remove =   wm8711_i2c_remove,
+ 	.id_table = wm8711_i2c_id,
+ };
+ #endif
+diff --git a/sound/soc/codecs/wm8727.c b/sound/soc/codecs/wm8727.c
+index e81705620718..462f5e4d5c05 100644
+--- a/sound/soc/codecs/wm8727.c
++++ b/sound/soc/codecs/wm8727.c
+@@ -45,13 +45,13 @@ static struct snd_soc_dai_driver wm8727_dai = {
+ 
+ static struct snd_soc_codec_driver soc_codec_dev_wm8727;
+ 
+-static __devinit int wm8727_probe(struct platform_device *pdev)
++static int wm8727_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_codec(&pdev->dev,
+ 			&soc_codec_dev_wm8727, &wm8727_dai, 1);
+ }
+ 
+-static int __devexit wm8727_remove(struct platform_device *pdev)
++static int wm8727_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_codec(&pdev->dev);
+ 	return 0;
+@@ -64,7 +64,7 @@ static struct platform_driver wm8727_codec_driver = {
+ 	},
+ 
+ 	.probe = wm8727_probe,
+-	.remove = __devexit_p(wm8727_remove),
++	.remove = wm8727_remove,
+ };
+ 
+ module_platform_driver(wm8727_codec_driver);
+diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c
+index 00a12a0c3919..c6a292dcded0 100644
+--- a/sound/soc/codecs/wm8728.c
++++ b/sound/soc/codecs/wm8728.c
+@@ -280,7 +280,7 @@ static const struct regmap_config wm8728_regmap = {
+ };
+ 
+ #if defined(CONFIG_SPI_MASTER)
+-static int __devinit wm8728_spi_probe(struct spi_device *spi)
++static int wm8728_spi_probe(struct spi_device *spi)
+ {
+ 	struct wm8728_priv *wm8728;
+ 	int ret;
+@@ -302,7 +302,7 @@ static int __devinit wm8728_spi_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit wm8728_spi_remove(struct spi_device *spi)
++static int wm8728_spi_remove(struct spi_device *spi)
+ {
+ 	snd_soc_unregister_codec(&spi->dev);
+ 
+@@ -316,13 +316,13 @@ static struct spi_driver wm8728_spi_driver = {
+ 		.of_match_table = wm8728_of_match,
+ 	},
+ 	.probe		= wm8728_spi_probe,
+-	.remove		= __devexit_p(wm8728_spi_remove),
++	.remove		= wm8728_spi_remove,
+ };
+ #endif /* CONFIG_SPI_MASTER */
+ 
+ #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+-static __devinit int wm8728_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8728_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8728_priv *wm8728;
+ 	int ret;
+@@ -344,7 +344,7 @@ static __devinit int wm8728_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm8728_i2c_remove(struct i2c_client *client)
++static int wm8728_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -363,7 +363,7 @@ static struct i2c_driver wm8728_i2c_driver = {
+ 		.of_match_table = wm8728_of_match,
+ 	},
+ 	.probe =    wm8728_i2c_probe,
+-	.remove =   __devexit_p(wm8728_i2c_remove),
++	.remove =   wm8728_i2c_remove,
+ 	.id_table = wm8728_i2c_id,
+ };
+ #endif
+diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
+index bb1d26919b10..5276062d6c79 100644
+--- a/sound/soc/codecs/wm8731.c
++++ b/sound/soc/codecs/wm8731.c
+@@ -631,7 +631,7 @@ static const struct regmap_config wm8731_regmap = {
+ };
+ 
+ #if defined(CONFIG_SPI_MASTER)
+-static int __devinit wm8731_spi_probe(struct spi_device *spi)
++static int wm8731_spi_probe(struct spi_device *spi)
+ {
+ 	struct wm8731_priv *wm8731;
+ 	int ret;
+@@ -661,7 +661,7 @@ static int __devinit wm8731_spi_probe(struct spi_device *spi)
+ 	return 0;
+ }
+ 
+-static int __devexit wm8731_spi_remove(struct spi_device *spi)
++static int wm8731_spi_remove(struct spi_device *spi)
+ {
+ 	snd_soc_unregister_codec(&spi->dev);
+ 	return 0;
+@@ -674,13 +674,13 @@ static struct spi_driver wm8731_spi_driver = {
+ 		.of_match_table = wm8731_of_match,
+ 	},
+ 	.probe		= wm8731_spi_probe,
+-	.remove		= __devexit_p(wm8731_spi_remove),
++	.remove		= wm8731_spi_remove,
+ };
+ #endif /* CONFIG_SPI_MASTER */
+ 
+ #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+-static __devinit int wm8731_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8731_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8731_priv *wm8731;
+ 	int ret;
+@@ -710,7 +710,7 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c,
+ 	return 0;
+ }
+ 
+-static __devexit int wm8731_i2c_remove(struct i2c_client *client)
++static int wm8731_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -729,7 +729,7 @@ static struct i2c_driver wm8731_i2c_driver = {
+ 		.of_match_table = wm8731_of_match,
+ 	},
+ 	.probe =    wm8731_i2c_probe,
+-	.remove =   __devexit_p(wm8731_i2c_remove),
++	.remove =   wm8731_i2c_remove,
+ 	.id_table = wm8731_i2c_id,
+ };
+ #endif
+diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c
+index 5c9634f4c1f0..2f167a8ca01b 100644
+--- a/sound/soc/codecs/wm8737.c
++++ b/sound/soc/codecs/wm8737.c
+@@ -645,8 +645,8 @@ static const struct regmap_config wm8737_regmap = {
+ };
+ 
+ #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+-static __devinit int wm8737_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8737_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8737_priv *wm8737;
+ 	int ret, i;
+@@ -679,7 +679,7 @@ static __devinit int wm8737_i2c_probe(struct i2c_client *i2c,
+ 
+ }
+ 
+-static __devexit int wm8737_i2c_remove(struct i2c_client *client)
++static int wm8737_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 
+@@ -699,13 +699,13 @@ static struct i2c_driver wm8737_i2c_driver = {
+ 		.of_match_table = wm8737_of_match,
+ 	},
+ 	.probe =    wm8737_i2c_probe,
+-	.remove =   __devexit_p(wm8737_i2c_remove),
++	.remove =   wm8737_i2c_remove,
+ 	.id_table = wm8737_i2c_id,
+ };
+ #endif
+ 
+ #if defined(CONFIG_SPI_MASTER)
+-static int __devinit wm8737_spi_probe(struct spi_device *spi)
++static int wm8737_spi_probe(struct spi_device *spi)
+ {
+ 	struct wm8737_priv *wm8737;
+ 	int ret, i;
+@@ -737,7 +737,7 @@ static int __devinit wm8737_spi_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit wm8737_spi_remove(struct spi_device *spi)
++static int wm8737_spi_remove(struct spi_device *spi)
+ {
+ 	snd_soc_unregister_codec(&spi->dev);
+ 
+@@ -751,7 +751,7 @@ static struct spi_driver wm8737_spi_driver = {
+ 		.of_match_table = wm8737_of_match,
+ 	},
+ 	.probe		= wm8737_spi_probe,
+-	.remove		= __devexit_p(wm8737_spi_remove),
++	.remove		= wm8737_spi_remove,
+ };
+ #endif /* CONFIG_SPI_MASTER */
+ 
+diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c
+index 99b8ebe93424..b18813cc7ba9 100644
+--- a/sound/soc/codecs/wm8741.c
++++ b/sound/soc/codecs/wm8741.c
+@@ -562,7 +562,7 @@ static struct i2c_driver wm8741_i2c_driver = {
+ #endif
+ 
+ #if defined(CONFIG_SPI_MASTER)
+-static int __devinit wm8741_spi_probe(struct spi_device *spi)
++static int wm8741_spi_probe(struct spi_device *spi)
+ {
+ 	struct wm8741_priv *wm8741;
+ 	int ret, i;
+@@ -596,7 +596,7 @@ static int __devinit wm8741_spi_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit wm8741_spi_remove(struct spi_device *spi)
++static int wm8741_spi_remove(struct spi_device *spi)
+ {
+ 	snd_soc_unregister_codec(&spi->dev);
+ 	return 0;
+@@ -609,7 +609,7 @@ static struct spi_driver wm8741_spi_driver = {
+ 		.of_match_table = wm8741_of_match,
+ 	},
+ 	.probe		= wm8741_spi_probe,
+-	.remove		= __devexit_p(wm8741_spi_remove),
++	.remove		= wm8741_spi_remove,
+ };
+ #endif /* CONFIG_SPI_MASTER */
+ 
+diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
+index 7665d68c4558..50d5ff616232 100644
+--- a/sound/soc/codecs/wm8750.c
++++ b/sound/soc/codecs/wm8750.c
+@@ -769,7 +769,7 @@ static const struct regmap_config wm8750_regmap = {
+ };
+ 
+ #if defined(CONFIG_SPI_MASTER)
+-static int __devinit wm8750_spi_probe(struct spi_device *spi)
++static int wm8750_spi_probe(struct spi_device *spi)
+ {
+ 	struct wm8750_priv *wm8750;
+ 	struct regmap *regmap;
+@@ -791,7 +791,7 @@ static int __devinit wm8750_spi_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit wm8750_spi_remove(struct spi_device *spi)
++static int wm8750_spi_remove(struct spi_device *spi)
+ {
+ 	snd_soc_unregister_codec(&spi->dev);
+ 	return 0;
+@@ -812,13 +812,13 @@ static struct spi_driver wm8750_spi_driver = {
+ 	},
+ 	.id_table	= wm8750_spi_ids,
+ 	.probe		= wm8750_spi_probe,
+-	.remove		= __devexit_p(wm8750_spi_remove),
++	.remove		= wm8750_spi_remove,
+ };
+ #endif /* CONFIG_SPI_MASTER */
+ 
+ #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+-static __devinit int wm8750_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8750_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8750_priv *wm8750;
+ 	struct regmap *regmap;
+@@ -840,7 +840,7 @@ static __devinit int wm8750_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm8750_i2c_remove(struct i2c_client *client)
++static int wm8750_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -860,7 +860,7 @@ static struct i2c_driver wm8750_i2c_driver = {
+ 		.of_match_table = wm8750_of_match,
+ 	},
+ 	.probe =    wm8750_i2c_probe,
+-	.remove =   __devexit_p(wm8750_i2c_remove),
++	.remove =   wm8750_i2c_remove,
+ 	.id_table = wm8750_i2c_id,
+ };
+ #endif
+diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
+index 50a5dc7974e1..0a4ab4c423d1 100644
+--- a/sound/soc/codecs/wm8753.c
++++ b/sound/soc/codecs/wm8753.c
+@@ -1550,7 +1550,7 @@ static const struct regmap_config wm8753_regmap = {
+ };
+ 
+ #if defined(CONFIG_SPI_MASTER)
+-static int __devinit wm8753_spi_probe(struct spi_device *spi)
++static int wm8753_spi_probe(struct spi_device *spi)
+ {
+ 	struct wm8753_priv *wm8753;
+ 	int ret;
+@@ -1578,7 +1578,7 @@ static int __devinit wm8753_spi_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit wm8753_spi_remove(struct spi_device *spi)
++static int wm8753_spi_remove(struct spi_device *spi)
+ {
+ 	snd_soc_unregister_codec(&spi->dev);
+ 	return 0;
+@@ -1591,13 +1591,13 @@ static struct spi_driver wm8753_spi_driver = {
+ 		.of_match_table = wm8753_of_match,
+ 	},
+ 	.probe		= wm8753_spi_probe,
+-	.remove		= __devexit_p(wm8753_spi_remove),
++	.remove		= wm8753_spi_remove,
+ };
+ #endif /* CONFIG_SPI_MASTER */
+ 
+ #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+-static __devinit int wm8753_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8753_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8753_priv *wm8753;
+ 	int ret;
+@@ -1625,7 +1625,7 @@ static __devinit int wm8753_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm8753_i2c_remove(struct i2c_client *client)
++static int wm8753_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -1644,7 +1644,7 @@ static struct i2c_driver wm8753_i2c_driver = {
+ 		.of_match_table = wm8753_of_match,
+ 	},
+ 	.probe =    wm8753_i2c_probe,
+-	.remove =   __devexit_p(wm8753_i2c_remove),
++	.remove =   wm8753_i2c_remove,
+ 	.id_table = wm8753_i2c_id,
+ };
+ #endif
+diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c
+index 0b690ba875f8..89a18d82f303 100644
+--- a/sound/soc/codecs/wm8770.c
++++ b/sound/soc/codecs/wm8770.c
+@@ -650,7 +650,7 @@ static const struct regmap_config wm8770_regmap = {
+ 	.volatile_reg = wm8770_volatile_reg,
+ };
+ 
+-static int __devinit wm8770_spi_probe(struct spi_device *spi)
++static int wm8770_spi_probe(struct spi_device *spi)
+ {
+ 	struct wm8770_priv *wm8770;
+ 	int ret, i;
+@@ -697,7 +697,7 @@ static int __devinit wm8770_spi_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit wm8770_spi_remove(struct spi_device *spi)
++static int wm8770_spi_remove(struct spi_device *spi)
+ {
+ 	struct wm8770_priv *wm8770 = spi_get_drvdata(spi);
+ 	int i;
+@@ -718,7 +718,7 @@ static struct spi_driver wm8770_spi_driver = {
+ 		.of_match_table = wm8770_of_match,
+ 	},
+ 	.probe = wm8770_spi_probe,
+-	.remove = __devexit_p(wm8770_spi_remove)
++	.remove = wm8770_spi_remove
+ };
+ 
+ module_spi_driver(wm8770_spi_driver);
+diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c
+index c32249ddb2e0..f31017ed1381 100644
+--- a/sound/soc/codecs/wm8776.c
++++ b/sound/soc/codecs/wm8776.c
+@@ -492,7 +492,7 @@ static const struct regmap_config wm8776_regmap = {
+ };
+ 
+ #if defined(CONFIG_SPI_MASTER)
+-static int __devinit wm8776_spi_probe(struct spi_device *spi)
++static int wm8776_spi_probe(struct spi_device *spi)
+ {
+ 	struct wm8776_priv *wm8776;
+ 	int ret;
+@@ -514,7 +514,7 @@ static int __devinit wm8776_spi_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit wm8776_spi_remove(struct spi_device *spi)
++static int wm8776_spi_remove(struct spi_device *spi)
+ {
+ 	snd_soc_unregister_codec(&spi->dev);
+ 	return 0;
+@@ -527,13 +527,13 @@ static struct spi_driver wm8776_spi_driver = {
+ 		.of_match_table = wm8776_of_match,
+ 	},
+ 	.probe		= wm8776_spi_probe,
+-	.remove		= __devexit_p(wm8776_spi_remove),
++	.remove		= wm8776_spi_remove,
+ };
+ #endif /* CONFIG_SPI_MASTER */
+ 
+ #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+-static __devinit int wm8776_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8776_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8776_priv *wm8776;
+ 	int ret;
+@@ -555,7 +555,7 @@ static __devinit int wm8776_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm8776_i2c_remove(struct i2c_client *client)
++static int wm8776_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -575,7 +575,7 @@ static struct i2c_driver wm8776_i2c_driver = {
+ 		.of_match_table = wm8776_of_match,
+ 	},
+ 	.probe =    wm8776_i2c_probe,
+-	.remove =   __devexit_p(wm8776_i2c_remove),
++	.remove =   wm8776_i2c_remove,
+ 	.id_table = wm8776_i2c_id,
+ };
+ #endif
+diff --git a/sound/soc/codecs/wm8782.c b/sound/soc/codecs/wm8782.c
+index 3fdea98f732e..f1fdbf63abb4 100644
+--- a/sound/soc/codecs/wm8782.c
++++ b/sound/soc/codecs/wm8782.c
+@@ -42,13 +42,13 @@ static struct snd_soc_dai_driver wm8782_dai = {
+ 
+ static struct snd_soc_codec_driver soc_codec_dev_wm8782;
+ 
+-static __devinit int wm8782_probe(struct platform_device *pdev)
++static int wm8782_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_codec(&pdev->dev,
+ 			&soc_codec_dev_wm8782, &wm8782_dai, 1);
+ }
+ 
+-static int __devexit wm8782_remove(struct platform_device *pdev)
++static int wm8782_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_codec(&pdev->dev);
+ 	return 0;
+@@ -60,7 +60,7 @@ static struct platform_driver wm8782_codec_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = wm8782_probe,
+-	.remove = __devexit_p(wm8782_remove),
++	.remove = wm8782_remove,
+ };
+ 
+ module_platform_driver(wm8782_codec_driver);
+diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
+index 837bfb51cebf..d321a875b029 100644
+--- a/sound/soc/codecs/wm8804.c
++++ b/sound/soc/codecs/wm8804.c
+@@ -702,7 +702,7 @@ static struct regmap_config wm8804_regmap_config = {
+ };
+ 
+ #if defined(CONFIG_SPI_MASTER)
+-static int __devinit wm8804_spi_probe(struct spi_device *spi)
++static int wm8804_spi_probe(struct spi_device *spi)
+ {
+ 	struct wm8804_priv *wm8804;
+ 	int ret;
+@@ -725,7 +725,7 @@ static int __devinit wm8804_spi_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit wm8804_spi_remove(struct spi_device *spi)
++static int wm8804_spi_remove(struct spi_device *spi)
+ {
+ 	snd_soc_unregister_codec(&spi->dev);
+ 	return 0;
+@@ -738,13 +738,13 @@ static struct spi_driver wm8804_spi_driver = {
+ 		.of_match_table = wm8804_of_match,
+ 	},
+ 	.probe = wm8804_spi_probe,
+-	.remove = __devexit_p(wm8804_spi_remove)
++	.remove = wm8804_spi_remove
+ };
+ #endif
+ 
+ #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+-static __devinit int wm8804_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8804_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8804_priv *wm8804;
+ 	int ret;
+@@ -766,7 +766,7 @@ static __devinit int wm8804_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm8804_i2c_remove(struct i2c_client *i2c)
++static int wm8804_i2c_remove(struct i2c_client *i2c)
+ {
+ 	snd_soc_unregister_codec(&i2c->dev);
+ 	return 0;
+@@ -785,7 +785,7 @@ static struct i2c_driver wm8804_i2c_driver = {
+ 		.of_match_table = wm8804_of_match,
+ 	},
+ 	.probe = wm8804_i2c_probe,
+-	.remove = __devexit_p(wm8804_i2c_remove),
++	.remove = wm8804_i2c_remove,
+ 	.id_table = wm8804_i2c_id
+ };
+ #endif
+diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
+index e781f865e5d7..7c8257c5a17b 100644
+--- a/sound/soc/codecs/wm8900.c
++++ b/sound/soc/codecs/wm8900.c
+@@ -1247,7 +1247,7 @@ static const struct regmap_config wm8900_regmap = {
+ };
+ 
+ #if defined(CONFIG_SPI_MASTER)
+-static int __devinit wm8900_spi_probe(struct spi_device *spi)
++static int wm8900_spi_probe(struct spi_device *spi)
+ {
+ 	struct wm8900_priv *wm8900;
+ 	int ret;
+@@ -1269,7 +1269,7 @@ static int __devinit wm8900_spi_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit wm8900_spi_remove(struct spi_device *spi)
++static int wm8900_spi_remove(struct spi_device *spi)
+ {
+ 	snd_soc_unregister_codec(&spi->dev);
+ 	return 0;
+@@ -1281,13 +1281,13 @@ static struct spi_driver wm8900_spi_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= wm8900_spi_probe,
+-	.remove		= __devexit_p(wm8900_spi_remove),
++	.remove		= wm8900_spi_remove,
+ };
+ #endif /* CONFIG_SPI_MASTER */
+ 
+ #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+-static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8900_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8900_priv *wm8900;
+ 	int ret;
+@@ -1309,7 +1309,7 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm8900_i2c_remove(struct i2c_client *client)
++static int wm8900_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -1327,7 +1327,7 @@ static struct i2c_driver wm8900_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe =    wm8900_i2c_probe,
+-	.remove =   __devexit_p(wm8900_i2c_remove),
++	.remove =   wm8900_i2c_remove,
+ 	.id_table = wm8900_i2c_id,
+ };
+ #endif
+diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
+index 839414f9e2ed..134e41c870b9 100644
+--- a/sound/soc/codecs/wm8903.c
++++ b/sound/soc/codecs/wm8903.c
+@@ -2020,8 +2020,8 @@ static int wm8903_set_pdata_from_of(struct i2c_client *i2c,
+ 	return 0;
+ }
+ 
+-static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8903_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8903_platform_data *pdata = dev_get_platdata(&i2c->dev);
+ 	struct wm8903_priv *wm8903;
+@@ -2206,7 +2206,7 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm8903_i2c_remove(struct i2c_client *client)
++static int wm8903_i2c_remove(struct i2c_client *client)
+ {
+ 	struct wm8903_priv *wm8903 = i2c_get_clientdata(client);
+ 
+@@ -2237,7 +2237,7 @@ static struct i2c_driver wm8903_i2c_driver = {
+ 		.of_match_table = wm8903_of_match,
+ 	},
+ 	.probe =    wm8903_i2c_probe,
+-	.remove =   __devexit_p(wm8903_i2c_remove),
++	.remove =   wm8903_i2c_remove,
+ 	.id_table = wm8903_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
+index 7c8df52a8d9d..3ff195c541db 100644
+--- a/sound/soc/codecs/wm8904.c
++++ b/sound/soc/codecs/wm8904.c
+@@ -2111,8 +2111,8 @@ static const struct regmap_config wm8904_regmap = {
+ 	.num_reg_defaults = ARRAY_SIZE(wm8904_reg_defaults),
+ };
+ 
+-static __devinit int wm8904_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8904_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8904_priv *wm8904;
+ 	unsigned int val;
+@@ -2247,7 +2247,7 @@ static __devinit int wm8904_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm8904_i2c_remove(struct i2c_client *client)
++static int wm8904_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -2267,7 +2267,7 @@ static struct i2c_driver wm8904_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe =    wm8904_i2c_probe,
+-	.remove =   __devexit_p(wm8904_i2c_remove),
++	.remove =   wm8904_i2c_remove,
+ 	.id_table = wm8904_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
+index b20aa4e7c3f9..b1591c61c254 100644
+--- a/sound/soc/codecs/wm8940.c
++++ b/sound/soc/codecs/wm8940.c
+@@ -742,8 +742,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8940 = {
+ 	.volatile_register = wm8940_volatile_register,
+ };
+ 
+-static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8940_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8940_priv *wm8940;
+ 	int ret;
+@@ -762,7 +762,7 @@ static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm8940_i2c_remove(struct i2c_client *client)
++static int wm8940_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 
+@@ -781,7 +781,7 @@ static struct i2c_driver wm8940_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe =    wm8940_i2c_probe,
+-	.remove =   __devexit_p(wm8940_i2c_remove),
++	.remove =   wm8940_i2c_remove,
+ 	.id_table = wm8940_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c
+index 7a82b7d28dcd..82c8ba975720 100644
+--- a/sound/soc/codecs/wm8955.c
++++ b/sound/soc/codecs/wm8955.c
+@@ -1012,8 +1012,8 @@ static const struct regmap_config wm8955_regmap = {
+ 	.num_reg_defaults = ARRAY_SIZE(wm8955_reg_defaults),
+ };
+ 
+-static __devinit int wm8955_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8955_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8955_priv *wm8955;
+ 	int ret;
+@@ -1039,7 +1039,7 @@ static __devinit int wm8955_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm8955_i2c_remove(struct i2c_client *client)
++static int wm8955_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 
+@@ -1058,7 +1058,7 @@ static struct i2c_driver wm8955_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe =    wm8955_i2c_probe,
+-	.remove =   __devexit_p(wm8955_i2c_remove),
++	.remove =   wm8955_i2c_remove,
+ 	.id_table = wm8955_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
+index cf09cb625a7b..9bb927325993 100644
+--- a/sound/soc/codecs/wm8960.c
++++ b/sound/soc/codecs/wm8960.c
+@@ -1028,8 +1028,8 @@ static const struct regmap_config wm8960_regmap = {
+ 	.volatile_reg = wm8960_volatile,
+ };
+ 
+-static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8960_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8960_data *pdata = dev_get_platdata(&i2c->dev);
+ 	struct wm8960_priv *wm8960;
+@@ -1062,7 +1062,7 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm8960_i2c_remove(struct i2c_client *client)
++static int wm8960_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -1080,7 +1080,7 @@ static struct i2c_driver wm8960_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe =    wm8960_i2c_probe,
+-	.remove =   __devexit_p(wm8960_i2c_remove),
++	.remove =   wm8960_i2c_remove,
+ 	.id_table = wm8960_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
+index f387670d0d75..900328e28a15 100644
+--- a/sound/soc/codecs/wm8961.c
++++ b/sound/soc/codecs/wm8961.c
+@@ -937,8 +937,8 @@ static const struct regmap_config wm8961_regmap = {
+ 	.readable_reg = wm8961_readable,
+ };
+ 
+-static __devinit int wm8961_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8961_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8961_priv *wm8961;
+ 	unsigned int val;
+@@ -993,7 +993,7 @@ static __devinit int wm8961_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm8961_i2c_remove(struct i2c_client *client)
++static int wm8961_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 
+@@ -1012,7 +1012,7 @@ static struct i2c_driver wm8961_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe =    wm8961_i2c_probe,
+-	.remove =   __devexit_p(wm8961_i2c_remove),
++	.remove =   wm8961_i2c_remove,
+ 	.id_table = wm8961_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
+index 8fd38cb4ba48..bd4b0db4cdaa 100644
+--- a/sound/soc/codecs/wm8962.c
++++ b/sound/soc/codecs/wm8962.c
+@@ -3588,8 +3588,8 @@ static const struct regmap_config wm8962_regmap = {
+ 	.cache_type = REGCACHE_RBTREE,
+ };
+ 
+-static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8962_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8962_pdata *pdata = dev_get_platdata(&i2c->dev);
+ 	struct wm8962_priv *wm8962;
+@@ -3699,7 +3699,7 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm8962_i2c_remove(struct i2c_client *client)
++static int wm8962_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -3765,7 +3765,7 @@ static struct i2c_driver wm8962_i2c_driver = {
+ 		.pm = &wm8962_pm,
+ 	},
+ 	.probe =    wm8962_i2c_probe,
+-	.remove =   __devexit_p(wm8962_i2c_remove),
++	.remove =   wm8962_i2c_remove,
+ 	.id_table = wm8962_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
+index 70dd27e94514..67aba78a7ca5 100644
+--- a/sound/soc/codecs/wm8971.c
++++ b/sound/soc/codecs/wm8971.c
+@@ -717,8 +717,8 @@ static const struct regmap_config wm8971_regmap = {
+ 	.cache_type = REGCACHE_RBTREE,
+ };
+ 
+-static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8971_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8971_priv *wm8971;
+ 	struct regmap *regmap;
+@@ -741,7 +741,7 @@ static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm8971_i2c_remove(struct i2c_client *client)
++static int wm8971_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -759,7 +759,7 @@ static struct i2c_driver wm8971_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe =    wm8971_i2c_probe,
+-	.remove =   __devexit_p(wm8971_i2c_remove),
++	.remove =   wm8971_i2c_remove,
+ 	.id_table = wm8971_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
+index 9a39511af52a..ea58b73e86b2 100644
+--- a/sound/soc/codecs/wm8974.c
++++ b/sound/soc/codecs/wm8974.c
+@@ -625,8 +625,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8974 = {
+ 	.num_dapm_routes = ARRAY_SIZE(wm8974_dapm_routes),
+ };
+ 
+-static __devinit int wm8974_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8974_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	int ret;
+ 
+@@ -636,7 +636,7 @@ static __devinit int wm8974_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm8974_i2c_remove(struct i2c_client *client)
++static int wm8974_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 
+@@ -655,7 +655,7 @@ static struct i2c_driver wm8974_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe =    wm8974_i2c_probe,
+-	.remove =   __devexit_p(wm8974_i2c_remove),
++	.remove =   wm8974_i2c_remove,
+ 	.id_table = wm8974_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c
+index ef467001c3d5..f347af3a67c2 100644
+--- a/sound/soc/codecs/wm8978.c
++++ b/sound/soc/codecs/wm8978.c
+@@ -1035,8 +1035,8 @@ static const struct regmap_config wm8978_regmap_config = {
+ 	.num_reg_defaults = ARRAY_SIZE(wm8978_reg_defaults),
+ };
+ 
+-static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8978_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8978_priv *wm8978;
+ 	int ret;
+@@ -1072,7 +1072,7 @@ static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
+ 	return 0;
+ }
+ 
+-static __devexit int wm8978_i2c_remove(struct i2c_client *client)
++static int wm8978_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 
+@@ -1091,7 +1091,7 @@ static struct i2c_driver wm8978_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe =    wm8978_i2c_probe,
+-	.remove =   __devexit_p(wm8978_i2c_remove),
++	.remove =   wm8978_i2c_remove,
+ 	.id_table = wm8978_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c
+index d8879f262d27..9fe1e041da49 100644
+--- a/sound/soc/codecs/wm8983.c
++++ b/sound/soc/codecs/wm8983.c
+@@ -1087,7 +1087,7 @@ static const struct regmap_config wm8983_regmap = {
+ };
+ 
+ #if defined(CONFIG_SPI_MASTER)
+-static int __devinit wm8983_spi_probe(struct spi_device *spi)
++static int wm8983_spi_probe(struct spi_device *spi)
+ {
+ 	struct wm8983_priv *wm8983;
+ 	int ret;
+@@ -1110,7 +1110,7 @@ static int __devinit wm8983_spi_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit wm8983_spi_remove(struct spi_device *spi)
++static int wm8983_spi_remove(struct spi_device *spi)
+ {
+ 	snd_soc_unregister_codec(&spi->dev);
+ 	return 0;
+@@ -1122,13 +1122,13 @@ static struct spi_driver wm8983_spi_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = wm8983_spi_probe,
+-	.remove = __devexit_p(wm8983_spi_remove)
++	.remove = wm8983_spi_remove
+ };
+ #endif
+ 
+ #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+-static __devinit int wm8983_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8983_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8983_priv *wm8983;
+ 	int ret;
+@@ -1152,7 +1152,7 @@ static __devinit int wm8983_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm8983_i2c_remove(struct i2c_client *client)
++static int wm8983_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -1170,7 +1170,7 @@ static struct i2c_driver wm8983_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = wm8983_i2c_probe,
+-	.remove = __devexit_p(wm8983_i2c_remove),
++	.remove = wm8983_i2c_remove,
+ 	.id_table = wm8983_i2c_id
+ };
+ #endif
+diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c
+index 7b3f4097609b..ab3782657ac8 100644
+--- a/sound/soc/codecs/wm8985.c
++++ b/sound/soc/codecs/wm8985.c
+@@ -1111,7 +1111,7 @@ static const struct regmap_config wm8985_regmap = {
+ };
+ 
+ #if defined(CONFIG_SPI_MASTER)
+-static int __devinit wm8985_spi_probe(struct spi_device *spi)
++static int wm8985_spi_probe(struct spi_device *spi)
+ {
+ 	struct wm8985_priv *wm8985;
+ 	int ret;
+@@ -1135,7 +1135,7 @@ static int __devinit wm8985_spi_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit wm8985_spi_remove(struct spi_device *spi)
++static int wm8985_spi_remove(struct spi_device *spi)
+ {
+ 	snd_soc_unregister_codec(&spi->dev);
+ 	return 0;
+@@ -1147,13 +1147,13 @@ static struct spi_driver wm8985_spi_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = wm8985_spi_probe,
+-	.remove = __devexit_p(wm8985_spi_remove)
++	.remove = wm8985_spi_remove
+ };
+ #endif
+ 
+ #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+-static __devinit int wm8985_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8985_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8985_priv *wm8985;
+ 	int ret;
+@@ -1177,7 +1177,7 @@ static __devinit int wm8985_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm8985_i2c_remove(struct i2c_client *i2c)
++static int wm8985_i2c_remove(struct i2c_client *i2c)
+ {
+ 	snd_soc_unregister_codec(&i2c->dev);
+ 	return 0;
+@@ -1195,7 +1195,7 @@ static struct i2c_driver wm8985_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = wm8985_i2c_probe,
+-	.remove = __devexit_p(wm8985_i2c_remove),
++	.remove = wm8985_i2c_remove,
+ 	.id_table = wm8985_i2c_id
+ };
+ #endif
+diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
+index 715788de442e..39b9acceb595 100644
+--- a/sound/soc/codecs/wm8988.c
++++ b/sound/soc/codecs/wm8988.c
+@@ -872,7 +872,7 @@ static struct regmap_config wm8988_regmap = {
+ };
+ 
+ #if defined(CONFIG_SPI_MASTER)
+-static int __devinit wm8988_spi_probe(struct spi_device *spi)
++static int wm8988_spi_probe(struct spi_device *spi)
+ {
+ 	struct wm8988_priv *wm8988;
+ 	int ret;
+@@ -896,7 +896,7 @@ static int __devinit wm8988_spi_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit wm8988_spi_remove(struct spi_device *spi)
++static int wm8988_spi_remove(struct spi_device *spi)
+ {
+ 	snd_soc_unregister_codec(&spi->dev);
+ 	return 0;
+@@ -908,13 +908,13 @@ static struct spi_driver wm8988_spi_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= wm8988_spi_probe,
+-	.remove		= __devexit_p(wm8988_spi_remove),
++	.remove		= wm8988_spi_remove,
+ };
+ #endif /* CONFIG_SPI_MASTER */
+ 
+ #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+-static __devinit int wm8988_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8988_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8988_priv *wm8988;
+ 	int ret;
+@@ -938,7 +938,7 @@ static __devinit int wm8988_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm8988_i2c_remove(struct i2c_client *client)
++static int wm8988_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -956,7 +956,7 @@ static struct i2c_driver wm8988_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe =    wm8988_i2c_probe,
+-	.remove =   __devexit_p(wm8988_i2c_remove),
++	.remove =   wm8988_i2c_remove,
+ 	.id_table = wm8988_i2c_id,
+ };
+ #endif
+diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
+index c28c83e5395d..837978e16e9d 100644
+--- a/sound/soc/codecs/wm8990.c
++++ b/sound/soc/codecs/wm8990.c
+@@ -1382,8 +1382,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8990 = {
+ };
+ 
+ #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+-static __devinit int wm8990_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8990_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8990_priv *wm8990;
+ 	int ret;
+@@ -1401,7 +1401,7 @@ static __devinit int wm8990_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm8990_i2c_remove(struct i2c_client *client)
++static int wm8990_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 
+@@ -1420,7 +1420,7 @@ static struct i2c_driver wm8990_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe =    wm8990_i2c_probe,
+-	.remove =   __devexit_p(wm8990_i2c_remove),
++	.remove =   wm8990_i2c_remove,
+ 	.id_table = wm8990_i2c_id,
+ };
+ #endif
+diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c
+index fe439f027e10..3a39df7a3829 100644
+--- a/sound/soc/codecs/wm8991.c
++++ b/sound/soc/codecs/wm8991.c
+@@ -1357,8 +1357,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8991 = {
+ 	.reg_cache_default = wm8991_reg_defs
+ };
+ 
+-static __devinit int wm8991_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8991_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8991_priv *wm8991;
+ 	int ret;
+@@ -1376,7 +1376,7 @@ static __devinit int wm8991_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm8991_i2c_remove(struct i2c_client *client)
++static int wm8991_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 
+@@ -1395,7 +1395,7 @@ static struct i2c_driver wm8991_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = wm8991_i2c_probe,
+-	.remove = __devexit_p(wm8991_i2c_remove),
++	.remove = wm8991_i2c_remove,
+ 	.id_table = wm8991_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
+index 347a359a7c86..433d59a0f3ef 100644
+--- a/sound/soc/codecs/wm8993.c
++++ b/sound/soc/codecs/wm8993.c
+@@ -1645,8 +1645,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8993 = {
+ 	.set_bias_level = wm8993_set_bias_level,
+ };
+ 
+-static __devinit int wm8993_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8993_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8993_priv *wm8993;
+ 	unsigned int reg;
+@@ -1745,7 +1745,7 @@ static __devinit int wm8993_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm8993_i2c_remove(struct i2c_client *i2c)
++static int wm8993_i2c_remove(struct i2c_client *i2c)
+ {
+ 	struct wm8993_priv *wm8993 = i2c_get_clientdata(i2c);
+ 
+@@ -1769,7 +1769,7 @@ static struct i2c_driver wm8993_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe =    wm8993_i2c_probe,
+-	.remove =   __devexit_p(wm8993_i2c_remove),
++	.remove =   wm8993_i2c_remove,
+ 	.id_table = wm8993_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
+index 60b34ff8179b..3b269fa226bd 100644
+--- a/sound/soc/codecs/wm8994.c
++++ b/sound/soc/codecs/wm8994.c
+@@ -4287,7 +4287,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8994 = {
+ 	.set_bias_level = wm8994_set_bias_level,
+ };
+ 
+-static int __devinit wm8994_probe(struct platform_device *pdev)
++static int wm8994_probe(struct platform_device *pdev)
+ {
+ 	struct wm8994_priv *wm8994;
+ 
+@@ -4303,7 +4303,7 @@ static int __devinit wm8994_probe(struct platform_device *pdev)
+ 			wm8994_dai, ARRAY_SIZE(wm8994_dai));
+ }
+ 
+-static int __devexit wm8994_remove(struct platform_device *pdev)
++static int wm8994_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_codec(&pdev->dev);
+ 	return 0;
+@@ -4347,7 +4347,7 @@ static struct platform_driver wm8994_codec_driver = {
+ 		.pm = &wm8994_pm_ops,
+ 	},
+ 	.probe = wm8994_probe,
+-	.remove = __devexit_p(wm8994_remove),
++	.remove = wm8994_remove,
+ };
+ 
+ module_platform_driver(wm8994_codec_driver);
+diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c
+index f1a7cf147af0..90a65c427541 100644
+--- a/sound/soc/codecs/wm8995.c
++++ b/sound/soc/codecs/wm8995.c
+@@ -2256,7 +2256,7 @@ static struct regmap_config wm8995_regmap = {
+ };
+ 
+ #if defined(CONFIG_SPI_MASTER)
+-static int __devinit wm8995_spi_probe(struct spi_device *spi)
++static int wm8995_spi_probe(struct spi_device *spi)
+ {
+ 	struct wm8995_priv *wm8995;
+ 	int ret;
+@@ -2280,7 +2280,7 @@ static int __devinit wm8995_spi_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit wm8995_spi_remove(struct spi_device *spi)
++static int wm8995_spi_remove(struct spi_device *spi)
+ {
+ 	snd_soc_unregister_codec(&spi->dev);
+ 	return 0;
+@@ -2292,13 +2292,13 @@ static struct spi_driver wm8995_spi_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = wm8995_spi_probe,
+-	.remove = __devexit_p(wm8995_spi_remove)
++	.remove = wm8995_spi_remove
+ };
+ #endif
+ 
+ #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+-static __devinit int wm8995_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8995_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8995_priv *wm8995;
+ 	int ret;
+@@ -2325,7 +2325,7 @@ static __devinit int wm8995_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm8995_i2c_remove(struct i2c_client *client)
++static int wm8995_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -2344,7 +2344,7 @@ static struct i2c_driver wm8995_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = wm8995_i2c_probe,
+-	.remove = __devexit_p(wm8995_i2c_remove),
++	.remove = wm8995_i2c_remove,
+ 	.id_table = wm8995_i2c_id
+ };
+ #endif
+diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c
+index 6dcb02c3666f..46fe83d2b224 100644
+--- a/sound/soc/codecs/wm8996.c
++++ b/sound/soc/codecs/wm8996.c
+@@ -2765,8 +2765,8 @@ static struct snd_soc_dai_driver wm8996_dai[] = {
+ 	},
+ };
+ 
+-static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm8996_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm8996_priv *wm8996;
+ 	int ret, i;
+@@ -3077,7 +3077,7 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int wm8996_i2c_remove(struct i2c_client *client)
++static int wm8996_i2c_remove(struct i2c_client *client)
+ {
+ 	struct wm8996_priv *wm8996 = i2c_get_clientdata(client);
+ 	int i;
+@@ -3107,7 +3107,7 @@ static struct i2c_driver wm8996_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe =    wm8996_i2c_probe,
+-	.remove =   __devexit_p(wm8996_i2c_remove),
++	.remove =   wm8996_i2c_remove,
+ 	.id_table = wm8996_i2c_id,
+ };
+ 
+diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
+index 860144e85e06..630b3d776ec2 100644
+--- a/sound/soc/codecs/wm9081.c
++++ b/sound/soc/codecs/wm9081.c
+@@ -1327,8 +1327,8 @@ static const struct regmap_config wm9081_regmap = {
+ };
+ 
+ #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+-static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
+-				      const struct i2c_device_id *id)
++static int wm9081_i2c_probe(struct i2c_client *i2c,
++			    const struct i2c_device_id *id)
+ {
+ 	struct wm9081_priv *wm9081;
+ 	unsigned int reg;
+@@ -1386,7 +1386,7 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
+ 	return 0;
+ }
+ 
+-static __devexit int wm9081_i2c_remove(struct i2c_client *client)
++static int wm9081_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -1404,7 +1404,7 @@ static struct i2c_driver wm9081_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe =    wm9081_i2c_probe,
+-	.remove =   __devexit_p(wm9081_i2c_remove),
++	.remove =   wm9081_i2c_remove,
+ 	.id_table = wm9081_i2c_id,
+ };
+ #endif
+diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c
+index bb55a70a104a..a07fe1618eec 100644
+--- a/sound/soc/codecs/wm9090.c
++++ b/sound/soc/codecs/wm9090.c
+@@ -664,7 +664,7 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
+ 	return 0;
+ }
+ 
+-static int __devexit wm9090_i2c_remove(struct i2c_client *i2c)
++static int wm9090_i2c_remove(struct i2c_client *i2c)
+ {
+ 	snd_soc_unregister_codec(&i2c->dev);
+ 	return 0;
+@@ -683,7 +683,7 @@ static struct i2c_driver wm9090_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = wm9090_i2c_probe,
+-	.remove = __devexit_p(wm9090_i2c_remove),
++	.remove = wm9090_i2c_remove,
+ 	.id_table = wm9090_id,
+ };
+ 
+diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c
+index e8e782a0c78d..05b1f346695b 100644
+--- a/sound/soc/codecs/wm9705.c
++++ b/sound/soc/codecs/wm9705.c
+@@ -382,13 +382,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9705 = {
+ 	.num_dapm_routes = ARRAY_SIZE(wm9705_audio_map),
+ };
+ 
+-static __devinit int wm9705_probe(struct platform_device *pdev)
++static int wm9705_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_codec(&pdev->dev,
+ 			&soc_codec_dev_wm9705, wm9705_dai, ARRAY_SIZE(wm9705_dai));
+ }
+ 
+-static int __devexit wm9705_remove(struct platform_device *pdev)
++static int wm9705_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_codec(&pdev->dev);
+ 	return 0;
+@@ -401,7 +401,7 @@ static struct platform_driver wm9705_codec_driver = {
+ 	},
+ 
+ 	.probe = wm9705_probe,
+-	.remove = __devexit_p(wm9705_remove),
++	.remove = wm9705_remove,
+ };
+ 
+ module_platform_driver(wm9705_codec_driver);
+diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
+index 4dd73ea08d0b..8e9a6a3eeb1a 100644
+--- a/sound/soc/codecs/wm9712.c
++++ b/sound/soc/codecs/wm9712.c
+@@ -685,13 +685,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9712 = {
+ 	.num_dapm_routes = ARRAY_SIZE(wm9712_audio_map),
+ };
+ 
+-static __devinit int wm9712_probe(struct platform_device *pdev)
++static int wm9712_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_codec(&pdev->dev,
+ 			&soc_codec_dev_wm9712, wm9712_dai, ARRAY_SIZE(wm9712_dai));
+ }
+ 
+-static int __devexit wm9712_remove(struct platform_device *pdev)
++static int wm9712_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_codec(&pdev->dev);
+ 	return 0;
+@@ -704,7 +704,7 @@ static struct platform_driver wm9712_codec_driver = {
+ 	},
+ 
+ 	.probe = wm9712_probe,
+-	.remove = __devexit_p(wm9712_remove),
++	.remove = wm9712_remove,
+ };
+ 
+ module_platform_driver(wm9712_codec_driver);
+diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
+index 3eb19fb71d17..f7afa68d8c7f 100644
+--- a/sound/soc/codecs/wm9713.c
++++ b/sound/soc/codecs/wm9713.c
+@@ -1254,13 +1254,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9713 = {
+ 	.num_dapm_routes = ARRAY_SIZE(wm9713_audio_map),
+ };
+ 
+-static __devinit int wm9713_probe(struct platform_device *pdev)
++static int wm9713_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_codec(&pdev->dev,
+ 			&soc_codec_dev_wm9713, wm9713_dai, ARRAY_SIZE(wm9713_dai));
+ }
+ 
+-static int __devexit wm9713_remove(struct platform_device *pdev)
++static int wm9713_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_codec(&pdev->dev);
+ 	return 0;
+@@ -1273,7 +1273,7 @@ static struct platform_driver wm9713_codec_driver = {
+ 	},
+ 
+ 	.probe = wm9713_probe,
+-	.remove = __devexit_p(wm9713_remove),
++	.remove = wm9713_remove,
+ };
+ 
+ module_platform_driver(wm9713_codec_driver);

commit e51e97eecdb2a4415aac5f1a69aa66ed787f1217
+Author: Bill Pemberton 
+Date:   Fri Dec 7 09:26:36 2012 -0500
+
+    ASoC: utils: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c
+index 60053709e417..fe4541df498c 100644
+--- a/sound/soc/soc-utils.c
++++ b/sound/soc/soc-utils.c
+@@ -94,7 +94,7 @@ static struct snd_soc_dai_driver dummy_dai = {
+ 	.name = "snd-soc-dummy-dai",
+ };
+ 
+-static __devinit int snd_soc_dummy_probe(struct platform_device *pdev)
++static int snd_soc_dummy_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 
+@@ -111,7 +111,7 @@ static __devinit int snd_soc_dummy_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static __devexit int snd_soc_dummy_remove(struct platform_device *pdev)
++static int snd_soc_dummy_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_platform(&pdev->dev);
+ 	snd_soc_unregister_codec(&pdev->dev);
+@@ -125,7 +125,7 @@ static struct platform_driver soc_dummy_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = snd_soc_dummy_probe,
+-	.remove = __devexit_p(snd_soc_dummy_remove),
++	.remove = snd_soc_dummy_remove,
+ };
+ 
+ static struct platform_device *soc_dummy_dev;

commit da794876f27c48ba67a6b3295ded27bbd81ba7e4
+Author: Bill Pemberton 
+Date:   Fri Dec 7 09:26:35 2012 -0500
+
+    ASoC: ux500: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/ux500/mop500.c b/sound/soc/ux500/mop500.c
+index 651a52a95fd7..ae6990738783 100644
+--- a/sound/soc/ux500/mop500.c
++++ b/sound/soc/ux500/mop500.c
+@@ -71,8 +71,8 @@ static void mop500_of_node_put(void)
+ 	}
+ }
+ 
+-static int __devinit mop500_of_probe(struct platform_device *pdev,
+-				struct device_node *np)
++static int mop500_of_probe(struct platform_device *pdev,
++			   struct device_node *np)
+ {
+ 	struct device_node *codec_np, *msp_np[2];
+ 	int i;
+@@ -99,7 +99,7 @@ static int __devinit mop500_of_probe(struct platform_device *pdev,
+ 	return 0;
+ }
+ 
+-static int __devinit mop500_probe(struct platform_device *pdev)
++static int mop500_probe(struct platform_device *pdev)
+ {
+ 	struct device_node *np = pdev->dev.of_node;
+ 	int ret;
+@@ -136,7 +136,7 @@ static int __devinit mop500_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit mop500_remove(struct platform_device *pdev)
++static int mop500_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *mop500_card = platform_get_drvdata(pdev);
+ 
+@@ -161,7 +161,7 @@ static struct platform_driver snd_soc_mop500_driver = {
+ 		.of_match_table = snd_soc_mop500_match,
+ 	},
+ 	.probe = mop500_probe,
+-	.remove = __devexit_p(mop500_remove),
++	.remove = mop500_remove,
+ };
+ 
+ module_platform_driver(snd_soc_mop500_driver);
+diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c
+index 478b4b60e0cc..94a3e5705aaa 100644
+--- a/sound/soc/ux500/ux500_msp_dai.c
++++ b/sound/soc/ux500/ux500_msp_dai.c
+@@ -768,7 +768,7 @@ static struct snd_soc_dai_driver ux500_msp_dai_drv[UX500_NBR_OF_DAI] = {
+ 	},
+ };
+ 
+-static int __devinit ux500_msp_drv_probe(struct platform_device *pdev)
++static int ux500_msp_drv_probe(struct platform_device *pdev)
+ {
+ 	struct ux500_msp_i2s_drvdata *drvdata;
+ 	int ret = 0;
+@@ -855,7 +855,7 @@ static int __devinit ux500_msp_drv_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit ux500_msp_drv_remove(struct platform_device *pdev)
++static int ux500_msp_drv_remove(struct platform_device *pdev)
+ {
+ 	struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(&pdev->dev);
+ 
+diff --git a/sound/soc/ux500/ux500_pcm.c b/sound/soc/ux500/ux500_pcm.c
+index 894c9f4bb9f6..c6821a5ab0fb 100644
+--- a/sound/soc/ux500/ux500_pcm.c
++++ b/sound/soc/ux500/ux500_pcm.c
+@@ -282,7 +282,7 @@ static struct snd_soc_platform_driver ux500_pcm_soc_drv = {
+ 	.pcm_new        = ux500_pcm_new,
+ };
+ 
+-int __devinit ux500_pcm_register_platform(struct platform_device *pdev)
++int ux500_pcm_register_platform(struct platform_device *pdev)
+ {
+ 	int ret;
+ 
+@@ -298,7 +298,7 @@ int __devinit ux500_pcm_register_platform(struct platform_device *pdev)
+ }
+ EXPORT_SYMBOL_GPL(ux500_pcm_register_platform);
+ 
+-int __devexit ux500_pcm_unregister_platform(struct platform_device *pdev)
++int ux500_pcm_unregister_platform(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_platform(&pdev->dev);
+ 

commit d8628d1c824011dff9260f7e009c1bfed043c95e
+Author: Bill Pemberton 
+Date:   Fri Dec 7 09:26:34 2012 -0500
+
+    ASoC: txx9: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c
+index 28db4ca997ca..16ab69635e2e 100644
+--- a/sound/soc/txx9/txx9aclc-ac97.c
++++ b/sound/soc/txx9/txx9aclc-ac97.c
+@@ -170,7 +170,7 @@ static struct snd_soc_dai_driver txx9aclc_ac97_dai = {
+ 	},
+ };
+ 
+-static int __devinit txx9aclc_ac97_dev_probe(struct platform_device *pdev)
++static int txx9aclc_ac97_dev_probe(struct platform_device *pdev)
+ {
+ 	struct txx9aclc_plat_drvdata *drvdata;
+ 	struct resource *r;
+@@ -208,7 +208,7 @@ static int __devinit txx9aclc_ac97_dev_probe(struct platform_device *pdev)
+ 	return snd_soc_register_dai(&pdev->dev, &txx9aclc_ac97_dai);
+ }
+ 
+-static int __devexit txx9aclc_ac97_dev_remove(struct platform_device *pdev)
++static int txx9aclc_ac97_dev_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_dai(&pdev->dev);
+ 	return 0;
+@@ -216,7 +216,7 @@ static int __devexit txx9aclc_ac97_dev_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver txx9aclc_ac97_driver = {
+ 	.probe		= txx9aclc_ac97_dev_probe,
+-	.remove		= __devexit_p(txx9aclc_ac97_dev_remove),
++	.remove		= txx9aclc_ac97_dev_remove,
+ 	.driver		= {
+ 		.name	= "txx9aclc-ac97",
+ 		.owner	= THIS_MODULE,
+diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c
+index b609d2c64c55..45a6428cba8d 100644
+--- a/sound/soc/txx9/txx9aclc.c
++++ b/sound/soc/txx9/txx9aclc.c
+@@ -417,12 +417,12 @@ static struct snd_soc_platform_driver txx9aclc_soc_platform = {
+ 	.pcm_free	= txx9aclc_pcm_free_dma_buffers,
+ };
+ 
+-static int __devinit txx9aclc_soc_platform_probe(struct platform_device *pdev)
++static int txx9aclc_soc_platform_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_platform(&pdev->dev, &txx9aclc_soc_platform);
+ }
+ 
+-static int __devexit txx9aclc_soc_platform_remove(struct platform_device *pdev)
++static int txx9aclc_soc_platform_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_platform(&pdev->dev);
+ 	return 0;
+@@ -435,7 +435,7 @@ static struct platform_driver txx9aclc_pcm_driver = {
+ 	},
+ 
+ 	.probe = txx9aclc_soc_platform_probe,
+-	.remove = __devexit_p(txx9aclc_soc_platform_remove),
++	.remove = txx9aclc_soc_platform_remove,
+ };
+ 
+ module_platform_driver(txx9aclc_pcm_driver);

commit 4652a0d0c48324e1227e2b2500d17045840e2fb3
+Author: Bill Pemberton 
+Date:   Fri Dec 7 09:26:33 2012 -0500
+
+    ASoC: tegra: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/tegra/tegra20_das.c b/sound/soc/tegra/tegra20_das.c
+index 49653375970b..654318483877 100644
+--- a/sound/soc/tegra/tegra20_das.c
++++ b/sound/soc/tegra/tegra20_das.c
+@@ -131,7 +131,7 @@ static const struct regmap_config tegra20_das_regmap_config = {
+ 	.cache_type = REGCACHE_RBTREE,
+ };
+ 
+-static int __devinit tegra20_das_probe(struct platform_device *pdev)
++static int tegra20_das_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res, *region;
+ 	void __iomem *regs;
+@@ -200,7 +200,7 @@ static int __devinit tegra20_das_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit tegra20_das_remove(struct platform_device *pdev)
++static int tegra20_das_remove(struct platform_device *pdev)
+ {
+ 	if (!das)
+ 		return -ENODEV;
+@@ -217,7 +217,7 @@ static const struct of_device_id tegra20_das_of_match[] = {
+ 
+ static struct platform_driver tegra20_das_driver = {
+ 	.probe = tegra20_das_probe,
+-	.remove = __devexit_p(tegra20_das_remove),
++	.remove = tegra20_das_remove,
+ 	.driver = {
+ 		.name = DRV_NAME,
+ 		.owner = THIS_MODULE,
+diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c
+index 2ae8af86edbd..caa772de5a18 100644
+--- a/sound/soc/tegra/tegra20_i2s.c
++++ b/sound/soc/tegra/tegra20_i2s.c
+@@ -331,7 +331,7 @@ static const struct regmap_config tegra20_i2s_regmap_config = {
+ 	.cache_type = REGCACHE_RBTREE,
+ };
+ 
+-static __devinit int tegra20_i2s_platform_probe(struct platform_device *pdev)
++static int tegra20_i2s_platform_probe(struct platform_device *pdev)
+ {
+ 	struct tegra20_i2s *i2s;
+ 	struct resource *mem, *memregion, *dmareq;
+@@ -447,7 +447,7 @@ static __devinit int tegra20_i2s_platform_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit tegra20_i2s_platform_remove(struct platform_device *pdev)
++static int tegra20_i2s_platform_remove(struct platform_device *pdev)
+ {
+ 	struct tegra20_i2s *i2s = dev_get_drvdata(&pdev->dev);
+ 
+@@ -481,7 +481,7 @@ static struct platform_driver tegra20_i2s_driver = {
+ 		.pm = &tegra20_i2s_pm_ops,
+ 	},
+ 	.probe = tegra20_i2s_platform_probe,
+-	.remove = __devexit_p(tegra20_i2s_platform_remove),
++	.remove = tegra20_i2s_platform_remove,
+ };
+ module_platform_driver(tegra20_i2s_driver);
+ 
+diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c
+index d9641ef7b1ee..04771d14d343 100644
+--- a/sound/soc/tegra/tegra20_spdif.c
++++ b/sound/soc/tegra/tegra20_spdif.c
+@@ -257,7 +257,7 @@ static const struct regmap_config tegra20_spdif_regmap_config = {
+ 	.cache_type = REGCACHE_RBTREE,
+ };
+ 
+-static __devinit int tegra20_spdif_platform_probe(struct platform_device *pdev)
++static int tegra20_spdif_platform_probe(struct platform_device *pdev)
+ {
+ 	struct tegra20_spdif *spdif;
+ 	struct resource *mem, *memregion, *dmareq;
+@@ -357,7 +357,7 @@ static __devinit int tegra20_spdif_platform_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit tegra20_spdif_platform_remove(struct platform_device *pdev)
++static int tegra20_spdif_platform_remove(struct platform_device *pdev)
+ {
+ 	struct tegra20_spdif *spdif = dev_get_drvdata(&pdev->dev);
+ 
+@@ -385,7 +385,7 @@ static struct platform_driver tegra20_spdif_driver = {
+ 		.pm = &tegra20_spdif_pm_ops,
+ 	},
+ 	.probe = tegra20_spdif_platform_probe,
+-	.remove = __devexit_p(tegra20_spdif_platform_remove),
++	.remove = tegra20_spdif_platform_remove,
+ };
+ 
+ module_platform_driver(tegra20_spdif_driver);
+diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c
+index 2269170b0df4..fd596d2a19b4 100644
+--- a/sound/soc/tegra/tegra30_ahub.c
++++ b/sound/soc/tegra/tegra30_ahub.c
+@@ -300,7 +300,7 @@ static const char * const configlink_clocks[] = {
+ 	"spdif_in",
+ };
+ 
+-struct of_dev_auxdata ahub_auxdata[] __devinitdata = {
++struct of_dev_auxdata ahub_auxdata[] = {
+ 	OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080300, "tegra30-i2s.0", NULL),
+ 	OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080400, "tegra30-i2s.1", NULL),
+ 	OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080500, "tegra30-i2s.2", NULL),
+@@ -434,7 +434,7 @@ static const struct regmap_config tegra30_ahub_ahub_regmap_config = {
+ 	.cache_type = REGCACHE_RBTREE,
+ };
+ 
+-static int __devinit tegra30_ahub_probe(struct platform_device *pdev)
++static int tegra30_ahub_probe(struct platform_device *pdev)
+ {
+ 	struct clk *clk;
+ 	int i;
+@@ -586,7 +586,7 @@ static int __devinit tegra30_ahub_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit tegra30_ahub_remove(struct platform_device *pdev)
++static int tegra30_ahub_remove(struct platform_device *pdev)
+ {
+ 	if (!ahub)
+ 		return -ENODEV;
+@@ -615,7 +615,7 @@ static const struct dev_pm_ops tegra30_ahub_pm_ops = {
+ 
+ static struct platform_driver tegra30_ahub_driver = {
+ 	.probe = tegra30_ahub_probe,
+-	.remove = __devexit_p(tegra30_ahub_remove),
++	.remove = tegra30_ahub_remove,
+ 	.driver = {
+ 		.name = DRV_NAME,
+ 		.owner = THIS_MODULE,
+diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c
+index bf0e089e7997..27e91dd0b91c 100644
+--- a/sound/soc/tegra/tegra30_i2s.c
++++ b/sound/soc/tegra/tegra30_i2s.c
+@@ -391,7 +391,7 @@ static const struct regmap_config tegra30_i2s_regmap_config = {
+ 	.cache_type = REGCACHE_RBTREE,
+ };
+ 
+-static __devinit int tegra30_i2s_platform_probe(struct platform_device *pdev)
++static int tegra30_i2s_platform_probe(struct platform_device *pdev)
+ {
+ 	struct tegra30_i2s *i2s;
+ 	u32 cif_ids[2];
+@@ -492,7 +492,7 @@ static __devinit int tegra30_i2s_platform_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit tegra30_i2s_platform_remove(struct platform_device *pdev)
++static int tegra30_i2s_platform_remove(struct platform_device *pdev)
+ {
+ 	struct tegra30_i2s *i2s = dev_get_drvdata(&pdev->dev);
+ 
+@@ -526,7 +526,7 @@ static struct platform_driver tegra30_i2s_driver = {
+ 		.pm = &tegra30_i2s_pm_ops,
+ 	},
+ 	.probe = tegra30_i2s_platform_probe,
+-	.remove = __devexit_p(tegra30_i2s_platform_remove),
++	.remove = tegra30_i2s_platform_remove,
+ };
+ module_platform_driver(tegra30_i2s_driver);
+ 
+diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c
+index 523795a6e83e..c80adb9da472 100644
+--- a/sound/soc/tegra/tegra_alc5632.c
++++ b/sound/soc/tegra/tegra_alc5632.c
+@@ -150,7 +150,7 @@ static struct snd_soc_card snd_soc_tegra_alc5632 = {
+ 	.fully_routed = true,
+ };
+ 
+-static __devinit int tegra_alc5632_probe(struct platform_device *pdev)
++static int tegra_alc5632_probe(struct platform_device *pdev)
+ {
+ 	struct device_node *np = pdev->dev.of_node;
+ 	struct snd_soc_card *card = &snd_soc_tegra_alc5632;
+@@ -227,7 +227,7 @@ static __devinit int tegra_alc5632_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit tegra_alc5632_remove(struct platform_device *pdev)
++static int tegra_alc5632_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 	struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(card);
+@@ -255,7 +255,7 @@ static struct platform_driver tegra_alc5632_driver = {
+ 		.of_match_table = tegra_alc5632_of_match,
+ 	},
+ 	.probe = tegra_alc5632_probe,
+-	.remove = __devexit_p(tegra_alc5632_remove),
++	.remove = tegra_alc5632_remove,
+ };
+ module_platform_driver(tegra_alc5632_driver);
+ 
+diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
+index e18733963cb4..c925ab0adeb6 100644
+--- a/sound/soc/tegra/tegra_pcm.c
++++ b/sound/soc/tegra/tegra_pcm.c
+@@ -253,13 +253,13 @@ static struct snd_soc_platform_driver tegra_pcm_platform = {
+ 	.pcm_free	= tegra_pcm_free,
+ };
+ 
+-int __devinit tegra_pcm_platform_register(struct device *dev)
++int tegra_pcm_platform_register(struct device *dev)
+ {
+ 	return snd_soc_register_platform(dev, &tegra_pcm_platform);
+ }
+ EXPORT_SYMBOL_GPL(tegra_pcm_platform_register);
+ 
+-void __devexit tegra_pcm_platform_unregister(struct device *dev)
++void tegra_pcm_platform_unregister(struct device *dev)
+ {
+ 	snd_soc_unregister_platform(dev);
+ }
+diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c
+index effe5b41b5f9..c8ef88a67c59 100644
+--- a/sound/soc/tegra/tegra_wm8753.c
++++ b/sound/soc/tegra/tegra_wm8753.c
+@@ -122,7 +122,7 @@ static struct snd_soc_card snd_soc_tegra_wm8753 = {
+ 	.fully_routed = true,
+ };
+ 
+-static __devinit int tegra_wm8753_driver_probe(struct platform_device *pdev)
++static int tegra_wm8753_driver_probe(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = &snd_soc_tegra_wm8753;
+ 	struct tegra_wm8753 *machine;
+@@ -188,7 +188,7 @@ static __devinit int tegra_wm8753_driver_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit tegra_wm8753_driver_remove(struct platform_device *pdev)
++static int tegra_wm8753_driver_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 	struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
+@@ -213,7 +213,7 @@ static struct platform_driver tegra_wm8753_driver = {
+ 		.of_match_table = tegra_wm8753_of_match,
+ 	},
+ 	.probe = tegra_wm8753_driver_probe,
+-	.remove = __devexit_p(tegra_wm8753_driver_remove),
++	.remove = tegra_wm8753_driver_remove,
+ };
+ module_platform_driver(tegra_wm8753_driver);
+ 
+diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c
+index 0f794126fbe4..bbd79bf56303 100644
+--- a/sound/soc/tegra/tegra_wm8903.c
++++ b/sound/soc/tegra/tegra_wm8903.c
+@@ -252,7 +252,7 @@ static struct snd_soc_card snd_soc_tegra_wm8903 = {
+ 	.fully_routed = true,
+ };
+ 
+-static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
++static int tegra_wm8903_driver_probe(struct platform_device *pdev)
+ {
+ 	struct device_node *np = pdev->dev.of_node;
+ 	struct snd_soc_card *card = &snd_soc_tegra_wm8903;
+@@ -402,7 +402,7 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev)
++static int tegra_wm8903_driver_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 	struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
+@@ -430,7 +430,7 @@ static struct platform_driver tegra_wm8903_driver = {
+ 		.of_match_table = tegra_wm8903_of_match,
+ 	},
+ 	.probe = tegra_wm8903_driver_probe,
+-	.remove = __devexit_p(tegra_wm8903_driver_remove),
++	.remove = tegra_wm8903_driver_remove,
+ };
+ module_platform_driver(tegra_wm8903_driver);
+ 
+diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c
+index 4a255a4d0c47..7fcf6c2297db 100644
+--- a/sound/soc/tegra/trimslice.c
++++ b/sound/soc/tegra/trimslice.c
+@@ -120,7 +120,7 @@ static struct snd_soc_card snd_soc_trimslice = {
+ 	.fully_routed = true,
+ };
+ 
+-static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev)
++static int tegra_snd_trimslice_probe(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = &snd_soc_trimslice;
+ 	struct tegra_trimslice *trimslice;
+@@ -183,7 +183,7 @@ static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit tegra_snd_trimslice_remove(struct platform_device *pdev)
++static int tegra_snd_trimslice_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 	struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card);
+@@ -208,7 +208,7 @@ static struct platform_driver tegra_snd_trimslice_driver = {
+ 		.of_match_table = trimslice_of_match,
+ 	},
+ 	.probe = tegra_snd_trimslice_probe,
+-	.remove = __devexit_p(tegra_snd_trimslice_remove),
++	.remove = tegra_snd_trimslice_remove,
+ };
+ module_platform_driver(tegra_snd_trimslice_driver);
+ 

commit 468c11754b5b543ab2d03ee5cc2e658f50cb1e59
+Author: Bill Pemberton 
+Date:   Fri Dec 7 09:26:32 2012 -0500
+
+    ASoC: spear: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/spear/spear_pcm.c b/sound/soc/spear/spear_pcm.c
+index 8c7f23729446..9b76cc5a1148 100644
+--- a/sound/soc/spear/spear_pcm.c
++++ b/sound/soc/spear/spear_pcm.c
+@@ -184,12 +184,12 @@ struct snd_soc_platform_driver spear_soc_platform = {
+ 	.pcm_free	=	spear_pcm_free,
+ };
+ 
+-static int __devinit spear_soc_platform_probe(struct platform_device *pdev)
++static int spear_soc_platform_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_platform(&pdev->dev, &spear_soc_platform);
+ }
+ 
+-static int __devexit spear_soc_platform_remove(struct platform_device *pdev)
++static int spear_soc_platform_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_platform(&pdev->dev);
+ 
+@@ -203,7 +203,7 @@ static struct platform_driver spear_pcm_driver = {
+ 	},
+ 
+ 	.probe = spear_soc_platform_probe,
+-	.remove = __devexit_p(spear_soc_platform_remove),
++	.remove = spear_soc_platform_remove,
+ };
+ 
+ module_platform_driver(spear_pcm_driver);

commit bb5eb6ec2604c495805427b61a0ba0ff9d5b4aa9
+Author: Bill Pemberton 
+Date:   Fri Dec 7 09:26:31 2012 -0500
+
+    ASoC: sh: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c
+index 7da20186b19e..19eff8fc4fdd 100644
+--- a/sound/soc/sh/dma-sh7760.c
++++ b/sound/soc/sh/dma-sh7760.c
+@@ -348,12 +348,12 @@ static struct snd_soc_platform sh7760_soc_platform = {
+ 	.pcm_free	= camelot_pcm_free,
+ };
+ 
+-static int __devinit sh7760_soc_platform_probe(struct platform_device *pdev)
++static int sh7760_soc_platform_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_platform(&pdev->dev, &sh7760_soc_platform);
+ }
+ 
+-static int __devexit sh7760_soc_platform_remove(struct platform_device *pdev)
++static int sh7760_soc_platform_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_platform(&pdev->dev);
+ 	return 0;
+@@ -366,7 +366,7 @@ static struct platform_driver sh7760_pcm_driver = {
+ 	},
+ 
+ 	.probe = sh7760_soc_platform_probe,
+-	.remove = __devexit_p(sh7760_soc_platform_remove),
++	.remove = sh7760_soc_platform_remove,
+ };
+ 
+ module_platform_driver(sh7760_pcm_driver);
+diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c
+index 3474d7befe5a..4cc2d64ef476 100644
+--- a/sound/soc/sh/hac.c
++++ b/sound/soc/sh/hac.c
+@@ -310,13 +310,13 @@ static struct snd_soc_dai_driver sh4_hac_dai[] = {
+ #endif
+ };
+ 
+-static int __devinit hac_soc_platform_probe(struct platform_device *pdev)
++static int hac_soc_platform_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_dais(&pdev->dev, sh4_hac_dai,
+ 			ARRAY_SIZE(sh4_hac_dai));
+ }
+ 
+-static int __devexit hac_soc_platform_remove(struct platform_device *pdev)
++static int hac_soc_platform_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(sh4_hac_dai));
+ 	return 0;
+@@ -329,7 +329,7 @@ static struct platform_driver hac_pcm_driver = {
+ 	},
+ 
+ 	.probe = hac_soc_platform_probe,
+-	.remove = __devexit_p(hac_soc_platform_remove),
++	.remove = hac_soc_platform_remove,
+ };
+ 
+ module_platform_driver(hac_pcm_driver);
+diff --git a/sound/soc/sh/siu_dai.c b/sound/soc/sh/siu_dai.c
+index 52d4c17b1232..34facdc9e4ac 100644
+--- a/sound/soc/sh/siu_dai.c
++++ b/sound/soc/sh/siu_dai.c
+@@ -726,7 +726,7 @@ static struct snd_soc_dai_driver siu_i2s_dai = {
+ 	.ops = &siu_dai_ops,
+ };
+ 
+-static int __devinit siu_probe(struct platform_device *pdev)
++static int siu_probe(struct platform_device *pdev)
+ {
+ 	const struct firmware *fw_entry;
+ 	struct resource *res, *region;
+@@ -815,7 +815,7 @@ static int __devinit siu_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit siu_remove(struct platform_device *pdev)
++static int siu_remove(struct platform_device *pdev)
+ {
+ 	struct siu_info *info = dev_get_drvdata(&pdev->dev);
+ 	struct resource *res;
+@@ -843,7 +843,7 @@ static struct platform_driver siu_driver = {
+ 		.name	= "siu-pcm-audio",
+ 	},
+ 	.probe		= siu_probe,
+-	.remove		= __devexit_p(siu_remove),
++	.remove		= siu_remove,
+ };
+ 
+ module_platform_driver(siu_driver);
+diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c
+index ff82b56a8860..c8e73a703934 100644
+--- a/sound/soc/sh/ssi.c
++++ b/sound/soc/sh/ssi.c
+@@ -379,13 +379,13 @@ static struct snd_soc_dai_driver sh4_ssi_dai[] = {
+ #endif
+ };
+ 
+-static int __devinit sh4_soc_dai_probe(struct platform_device *pdev)
++static int sh4_soc_dai_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_dais(&pdev->dev, sh4_ssi_dai,
+ 			ARRAY_SIZE(sh4_ssi_dai));
+ }
+ 
+-static int __devexit sh4_soc_dai_remove(struct platform_device *pdev)
++static int sh4_soc_dai_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(sh4_ssi_dai));
+ 	return 0;
+@@ -398,7 +398,7 @@ static struct platform_driver sh4_ssi_driver = {
+ 	},
+ 
+ 	.probe = sh4_soc_dai_probe,
+-	.remove = __devexit_p(sh4_soc_dai_remove),
++	.remove = sh4_soc_dai_remove,
+ };
+ 
+ module_platform_driver(sh4_ssi_driver);

commit 9ac8a7122e17ccaaf35714f6d8d91ef2eae0e077
+Author: Bill Pemberton 
+Date:   Fri Dec 7 09:26:30 2012 -0500
+
+    ASoC: s6000: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/s6000/s6000-i2s.c b/sound/soc/s6000/s6000-i2s.c
+index aaabdbaec19c..fee4d477a49c 100644
+--- a/sound/soc/s6000/s6000-i2s.c
++++ b/sound/soc/s6000/s6000-i2s.c
+@@ -436,7 +436,7 @@ static struct snd_soc_dai_driver s6000_i2s_dai = {
+ 	.ops = &s6000_i2s_dai_ops,
+ };
+ 
+-static int __devinit s6000_i2s_probe(struct platform_device *pdev)
++static int s6000_i2s_probe(struct platform_device *pdev)
+ {
+ 	struct s6000_i2s_dev *dev;
+ 	struct resource *scbmem, *sifmem, *region, *dma1, *dma2;
+@@ -566,7 +566,7 @@ static int __devinit s6000_i2s_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static void __devexit s6000_i2s_remove(struct platform_device *pdev)
++static void s6000_i2s_remove(struct platform_device *pdev)
+ {
+ 	struct s6000_i2s_dev *dev = dev_get_drvdata(&pdev->dev);
+ 	struct resource *region;
+@@ -597,7 +597,7 @@ static void __devexit s6000_i2s_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver s6000_i2s_driver = {
+ 	.probe  = s6000_i2s_probe,
+-	.remove = __devexit_p(s6000_i2s_remove),
++	.remove = s6000_i2s_remove,
+ 	.driver = {
+ 		.name   = "s6000-i2s",
+ 		.owner  = THIS_MODULE,
+diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c
+index 716da861c629..1358c7de2521 100644
+--- a/sound/soc/s6000/s6000-pcm.c
++++ b/sound/soc/s6000/s6000-pcm.c
+@@ -500,12 +500,12 @@ static struct snd_soc_platform_driver s6000_soc_platform = {
+ 	.pcm_free = 	s6000_pcm_free,
+ };
+ 
+-static int __devinit s6000_soc_platform_probe(struct platform_device *pdev)
++static int s6000_soc_platform_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_platform(&pdev->dev, &s6000_soc_platform);
+ }
+ 
+-static int __devexit s6000_soc_platform_remove(struct platform_device *pdev)
++static int s6000_soc_platform_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_platform(&pdev->dev);
+ 	return 0;
+@@ -518,7 +518,7 @@ static struct platform_driver s6000_pcm_driver = {
+ 	},
+ 
+ 	.probe = s6000_soc_platform_probe,
+-	.remove = __devexit_p(s6000_soc_platform_remove),
++	.remove = s6000_soc_platform_remove,
+ };
+ 
+ module_platform_driver(s6000_pcm_driver);

commit 7ff6000627eb996d6d02aa5362ecca7b7ac7ebef
+Author: Bill Pemberton 
+Date:   Fri Dec 7 09:26:29 2012 -0500
+
+    ASoC: OMAP: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c
+index d8e96b2cd03e..2600447fa74f 100644
+--- a/sound/soc/omap/ams-delta.c
++++ b/sound/soc/omap/ams-delta.c
+@@ -575,7 +575,7 @@ static struct snd_soc_card ams_delta_audio_card = {
+ };
+ 
+ /* Module init/exit */
+-static __devinit int ams_delta_probe(struct platform_device *pdev)
++static int ams_delta_probe(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = &ams_delta_audio_card;
+ 	int ret;
+@@ -591,7 +591,7 @@ static __devinit int ams_delta_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit ams_delta_remove(struct platform_device *pdev)
++static int ams_delta_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -616,7 +616,7 @@ static struct platform_driver ams_delta_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = ams_delta_probe,
+-	.remove = __devexit_p(ams_delta_remove),
++	.remove = ams_delta_remove,
+ };
+ 
+ module_platform_driver(ams_delta_driver);
+diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c
+index a9a243860428..285c8368cb47 100644
+--- a/sound/soc/omap/mcbsp.c
++++ b/sound/soc/omap/mcbsp.c
+@@ -930,8 +930,7 @@ static const struct attribute_group sidetone_attr_group = {
+ 	.attrs = (struct attribute **)sidetone_attrs,
+ };
+ 
+-static int __devinit omap_st_add(struct omap_mcbsp *mcbsp,
+-				 struct resource *res)
++static int omap_st_add(struct omap_mcbsp *mcbsp, struct resource *res)
+ {
+ 	struct omap_mcbsp_st_data *st_data;
+ 	int err;
+@@ -957,7 +956,7 @@ static int __devinit omap_st_add(struct omap_mcbsp *mcbsp,
+  * McBSP1 and McBSP3 are directly mapped on 1610 and 1510.
+  * 730 has only 2 McBSP, and both of them are MPU peripherals.
+  */
+-int __devinit omap_mcbsp_init(struct platform_device *pdev)
++int omap_mcbsp_init(struct platform_device *pdev)
+ {
+ 	struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
+ 	struct resource *res;
+@@ -1085,7 +1084,7 @@ int __devinit omap_mcbsp_init(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-void __devexit omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp)
++void omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp)
+ {
+ 	if (mcbsp->pdata->buffer_size)
+ 		sysfs_remove_group(&mcbsp->dev->kobj, &additional_attr_group);
+diff --git a/sound/soc/omap/mcbsp.h b/sound/soc/omap/mcbsp.h
+index a89791c239a5..f93e0b0af303 100644
+--- a/sound/soc/omap/mcbsp.h
++++ b/sound/soc/omap/mcbsp.h
+@@ -347,7 +347,7 @@ int omap_st_enable(struct omap_mcbsp *mcbsp);
+ int omap_st_disable(struct omap_mcbsp *mcbsp);
+ int omap_st_is_enabled(struct omap_mcbsp *mcbsp);
+ 
+-int __devinit omap_mcbsp_init(struct platform_device *pdev);
+-void __devexit omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp);
++int omap_mcbsp_init(struct platform_device *pdev);
++void omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp);
+ 
+ #endif /* __ASOC_MCBSP_H */
+diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c
+index 1d6ea8609d28..e7d93fa412a9 100644
+--- a/sound/soc/omap/omap-abe-twl6040.c
++++ b/sound/soc/omap/omap-abe-twl6040.c
+@@ -273,7 +273,7 @@ static struct snd_soc_card omap_abe_card = {
+ 	.num_dapm_routes = ARRAY_SIZE(audio_map),
+ };
+ 
+-static __devinit int omap_abe_probe(struct platform_device *pdev)
++static int omap_abe_probe(struct platform_device *pdev)
+ {
+ 	struct omap_abe_twl6040_data *pdata = dev_get_platdata(&pdev->dev);
+ 	struct device_node *node = pdev->dev.of_node;
+@@ -390,7 +390,7 @@ static __devinit int omap_abe_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit omap_abe_remove(struct platform_device *pdev)
++static int omap_abe_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 	struct abe_twl6040 *priv = snd_soc_card_get_drvdata(card);
+@@ -417,7 +417,7 @@ static struct platform_driver omap_abe_driver = {
+ 		.of_match_table = omap_abe_of_match,
+ 	},
+ 	.probe = omap_abe_probe,
+-	.remove = __devexit_p(omap_abe_remove),
++	.remove = omap_abe_remove,
+ };
+ 
+ module_platform_driver(omap_abe_driver);
+diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c
+index 5a6aeaf552a8..ba49ccd9eed9 100644
+--- a/sound/soc/omap/omap-dmic.c
++++ b/sound/soc/omap/omap-dmic.c
+@@ -448,7 +448,7 @@ static struct snd_soc_dai_driver omap_dmic_dai = {
+ 	.ops = &omap_dmic_dai_ops,
+ };
+ 
+-static __devinit int asoc_dmic_probe(struct platform_device *pdev)
++static int asoc_dmic_probe(struct platform_device *pdev)
+ {
+ 	struct omap_dmic *dmic;
+ 	struct resource *res;
+@@ -518,7 +518,7 @@ static __devinit int asoc_dmic_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit asoc_dmic_remove(struct platform_device *pdev)
++static int asoc_dmic_remove(struct platform_device *pdev)
+ {
+ 	struct omap_dmic *dmic = platform_get_drvdata(pdev);
+ 
+@@ -541,7 +541,7 @@ static struct platform_driver asoc_dmic_driver = {
+ 		.of_match_table = omap_dmic_of_match,
+ 	},
+ 	.probe = asoc_dmic_probe,
+-	.remove = __devexit_p(asoc_dmic_remove),
++	.remove = asoc_dmic_remove,
+ };
+ 
+ module_platform_driver(asoc_dmic_driver);
+diff --git a/sound/soc/omap/omap-hdmi-card.c b/sound/soc/omap/omap-hdmi-card.c
+index eaa2ea0e3f81..d4eaa92e518e 100644
+--- a/sound/soc/omap/omap-hdmi-card.c
++++ b/sound/soc/omap/omap-hdmi-card.c
+@@ -45,7 +45,7 @@ static struct snd_soc_card snd_soc_omap_hdmi = {
+ 	.num_links = 1,
+ };
+ 
+-static __devinit int omap_hdmi_probe(struct platform_device *pdev)
++static int omap_hdmi_probe(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = &snd_soc_omap_hdmi;
+ 	int ret;
+@@ -61,7 +61,7 @@ static __devinit int omap_hdmi_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit omap_hdmi_remove(struct platform_device *pdev)
++static int omap_hdmi_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -76,7 +76,7 @@ static struct platform_driver omap_hdmi_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = omap_hdmi_probe,
+-	.remove = __devexit_p(omap_hdmi_remove),
++	.remove = omap_hdmi_remove,
+ };
+ 
+ module_platform_driver(omap_hdmi_driver);
+diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c
+index f59c69fb400e..7ea24819d570 100644
+--- a/sound/soc/omap/omap-hdmi.c
++++ b/sound/soc/omap/omap-hdmi.c
+@@ -262,7 +262,7 @@ static struct snd_soc_dai_driver omap_hdmi_dai = {
+ 	.ops = &omap_hdmi_dai_ops,
+ };
+ 
+-static __devinit int omap_hdmi_probe(struct platform_device *pdev)
++static int omap_hdmi_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 	struct resource *hdmi_rsrc;
+@@ -324,7 +324,7 @@ static __devinit int omap_hdmi_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit omap_hdmi_remove(struct platform_device *pdev)
++static int omap_hdmi_remove(struct platform_device *pdev)
+ {
+ 	struct hdmi_priv *hdmi_data = dev_get_drvdata(&pdev->dev);
+ 
+@@ -345,7 +345,7 @@ static struct platform_driver hdmi_dai_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = omap_hdmi_probe,
+-	.remove = __devexit_p(omap_hdmi_remove),
++	.remove = omap_hdmi_remove,
+ };
+ 
+ module_platform_driver(hdmi_dai_driver);
+diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
+index 09167609c93e..8d2defd6fdbe 100644
+--- a/sound/soc/omap/omap-mcbsp.c
++++ b/sound/soc/omap/omap-mcbsp.c
+@@ -757,7 +757,7 @@ static const struct of_device_id omap_mcbsp_of_match[] = {
+ };
+ MODULE_DEVICE_TABLE(of, omap_mcbsp_of_match);
+ 
+-static __devinit int asoc_mcbsp_probe(struct platform_device *pdev)
++static int asoc_mcbsp_probe(struct platform_device *pdev)
+ {
+ 	struct omap_mcbsp_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ 	struct omap_mcbsp *mcbsp;
+@@ -798,7 +798,7 @@ static __devinit int asoc_mcbsp_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit asoc_mcbsp_remove(struct platform_device *pdev)
++static int asoc_mcbsp_remove(struct platform_device *pdev)
+ {
+ 	struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
+ 
+@@ -824,7 +824,7 @@ static struct platform_driver asoc_mcbsp_driver = {
+ 	},
+ 
+ 	.probe = asoc_mcbsp_probe,
+-	.remove = __devexit_p(asoc_mcbsp_remove),
++	.remove = asoc_mcbsp_remove,
+ };
+ 
+ module_platform_driver(asoc_mcbsp_driver);
+diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
+index 56965bb3275c..2fe8be209452 100644
+--- a/sound/soc/omap/omap-mcpdm.c
++++ b/sound/soc/omap/omap-mcpdm.c
+@@ -429,7 +429,7 @@ void omap_mcpdm_configure_dn_offsets(struct snd_soc_pcm_runtime *rtd,
+ }
+ EXPORT_SYMBOL_GPL(omap_mcpdm_configure_dn_offsets);
+ 
+-static __devinit int asoc_mcpdm_probe(struct platform_device *pdev)
++static int asoc_mcpdm_probe(struct platform_device *pdev)
+ {
+ 	struct omap_mcpdm *mcpdm;
+ 	struct resource *res;
+@@ -487,7 +487,7 @@ static __devinit int asoc_mcpdm_probe(struct platform_device *pdev)
+ 	return snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai);
+ }
+ 
+-static int __devexit asoc_mcpdm_remove(struct platform_device *pdev)
++static int asoc_mcpdm_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_dai(&pdev->dev);
+ 	return 0;
+@@ -507,7 +507,7 @@ static struct platform_driver asoc_mcpdm_driver = {
+ 	},
+ 
+ 	.probe	= asoc_mcpdm_probe,
+-	.remove	= __devexit_p(asoc_mcpdm_remove),
++	.remove	= asoc_mcpdm_remove,
+ };
+ 
+ module_platform_driver(asoc_mcpdm_driver);
+diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
+index 340874ebf9ae..5f7e5b9c87a8 100644
+--- a/sound/soc/omap/omap-pcm.c
++++ b/sound/soc/omap/omap-pcm.c
+@@ -297,13 +297,13 @@ static struct snd_soc_platform_driver omap_soc_platform = {
+ 	.pcm_free	= omap_pcm_free_dma_buffers,
+ };
+ 
+-static __devinit int omap_pcm_probe(struct platform_device *pdev)
++static int omap_pcm_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_platform(&pdev->dev,
+ 			&omap_soc_platform);
+ }
+ 
+-static int __devexit omap_pcm_remove(struct platform_device *pdev)
++static int omap_pcm_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_platform(&pdev->dev);
+ 	return 0;
+@@ -316,7 +316,7 @@ static struct platform_driver omap_pcm_driver = {
+ 	},
+ 
+ 	.probe = omap_pcm_probe,
+-	.remove = __devexit_p(omap_pcm_remove),
++	.remove = omap_pcm_remove,
+ };
+ 
+ module_platform_driver(omap_pcm_driver);
+diff --git a/sound/soc/omap/omap-twl4030.c b/sound/soc/omap/omap-twl4030.c
+index 3b97b87971f5..4541d28b5314 100644
+--- a/sound/soc/omap/omap-twl4030.c
++++ b/sound/soc/omap/omap-twl4030.c
+@@ -107,7 +107,7 @@ static struct snd_soc_card omap_twl4030_card = {
+ 	.num_links = ARRAY_SIZE(omap_twl4030_dai_links),
+ };
+ 
+-static __devinit int omap_twl4030_probe(struct platform_device *pdev)
++static int omap_twl4030_probe(struct platform_device *pdev)
+ {
+ 	struct omap_tw4030_pdata *pdata = dev_get_platdata(&pdev->dev);
+ 	struct device_node *node = pdev->dev.of_node;
+@@ -154,7 +154,7 @@ static __devinit int omap_twl4030_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit omap_twl4030_remove(struct platform_device *pdev)
++static int omap_twl4030_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -177,7 +177,7 @@ static struct platform_driver omap_twl4030_driver = {
+ 		.of_match_table = omap_twl4030_of_match,
+ 	},
+ 	.probe = omap_twl4030_probe,
+-	.remove = __devexit_p(omap_twl4030_remove),
++	.remove = omap_twl4030_remove,
+ };
+ 
+ module_platform_driver(omap_twl4030_driver);

commit ce69ace56a1cdb8a0f22e1e923dbcf74756a6554
+Author: Bill Pemberton 
+Date:   Fri Dec 7 09:26:28 2012 -0500
+
+    ASoC: nuc900: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c
+index 946020a647db..0418467a4848 100644
+--- a/sound/soc/nuc900/nuc900-ac97.c
++++ b/sound/soc/nuc900/nuc900-ac97.c
+@@ -314,7 +314,7 @@ static struct snd_soc_dai_driver nuc900_ac97_dai = {
+ 	.ops = &nuc900_ac97_dai_ops,
+ };
+ 
+-static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev)
++static int nuc900_ac97_drvprobe(struct platform_device *pdev)
+ {
+ 	struct nuc900_audio *nuc900_audio;
+ 	int ret;
+@@ -382,7 +382,7 @@ static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit nuc900_ac97_drvremove(struct platform_device *pdev)
++static int nuc900_ac97_drvremove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_dai(&pdev->dev);
+ 
+@@ -403,7 +403,7 @@ static struct platform_driver nuc900_ac97_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= nuc900_ac97_drvprobe,
+-	.remove		= __devexit_p(nuc900_ac97_drvremove),
++	.remove		= nuc900_ac97_drvremove,
+ };
+ 
+ module_platform_driver(nuc900_ac97_driver);
+diff --git a/sound/soc/nuc900/nuc900-pcm.c b/sound/soc/nuc900/nuc900-pcm.c
+index 37585b47f4e3..c894ff0f2580 100644
+--- a/sound/soc/nuc900/nuc900-pcm.c
++++ b/sound/soc/nuc900/nuc900-pcm.c
+@@ -337,12 +337,12 @@ static struct snd_soc_platform_driver nuc900_soc_platform = {
+ 	.pcm_free	= nuc900_dma_free_dma_buffers,
+ };
+ 
+-static int __devinit nuc900_soc_platform_probe(struct platform_device *pdev)
++static int nuc900_soc_platform_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_platform(&pdev->dev, &nuc900_soc_platform);
+ }
+ 
+-static int __devexit nuc900_soc_platform_remove(struct platform_device *pdev)
++static int nuc900_soc_platform_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_platform(&pdev->dev);
+ 	return 0;
+@@ -355,7 +355,7 @@ static struct platform_driver nuc900_pcm_driver = {
+ 	},
+ 
+ 	.probe = nuc900_soc_platform_probe,
+-	.remove = __devexit_p(nuc900_soc_platform_remove),
++	.remove = nuc900_soc_platform_remove,
+ };
+ 
+ module_platform_driver(nuc900_pcm_driver);

commit fd582736aba64e0fe4995d47c4a1b1ade7600d74
+Author: Bill Pemberton 
+Date:   Fri Dec 7 09:26:27 2012 -0500
+
+    ASoC: mxs: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c
+index f82d766cbf9e..564b5b60319d 100644
+--- a/sound/soc/mxs/mxs-pcm.c
++++ b/sound/soc/mxs/mxs-pcm.c
+@@ -220,13 +220,13 @@ static struct snd_soc_platform_driver mxs_soc_platform = {
+ 	.pcm_free	= mxs_pcm_free,
+ };
+ 
+-int __devinit mxs_pcm_platform_register(struct device *dev)
++int mxs_pcm_platform_register(struct device *dev)
+ {
+ 	return snd_soc_register_platform(dev, &mxs_soc_platform);
+ }
+ EXPORT_SYMBOL_GPL(mxs_pcm_platform_register);
+ 
+-void __devexit mxs_pcm_platform_unregister(struct device *dev)
++void mxs_pcm_platform_unregister(struct device *dev)
+ {
+ 	snd_soc_unregister_platform(dev);
+ }
+diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c
+index b304e375568a..365d9d27a321 100644
+--- a/sound/soc/mxs/mxs-saif.c
++++ b/sound/soc/mxs/mxs-saif.c
+@@ -657,7 +657,7 @@ static irqreturn_t mxs_saif_irq(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit mxs_saif_probe(struct platform_device *pdev)
++static int mxs_saif_probe(struct platform_device *pdev)
+ {
+ 	struct device_node *np = pdev->dev.of_node;
+ 	struct resource *iores, *dmares;
+@@ -792,7 +792,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit mxs_saif_remove(struct platform_device *pdev)
++static int mxs_saif_remove(struct platform_device *pdev)
+ {
+ 	mxs_pcm_platform_unregister(&pdev->dev);
+ 	snd_soc_unregister_dai(&pdev->dev);
+@@ -808,7 +808,7 @@ MODULE_DEVICE_TABLE(of, mxs_saif_dt_ids);
+ 
+ static struct platform_driver mxs_saif_driver = {
+ 	.probe = mxs_saif_probe,
+-	.remove = __devexit_p(mxs_saif_remove),
++	.remove = mxs_saif_remove,
+ 
+ 	.driver = {
+ 		.name = "mxs-saif",
+diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c
+index 215113b05f7d..b1d9b5ebeeeb 100644
+--- a/sound/soc/mxs/mxs-sgtl5000.c
++++ b/sound/soc/mxs/mxs-sgtl5000.c
+@@ -112,7 +112,7 @@ static struct snd_soc_card mxs_sgtl5000 = {
+ 	.num_links	= ARRAY_SIZE(mxs_sgtl5000_dai),
+ };
+ 
+-static int __devinit mxs_sgtl5000_probe_dt(struct platform_device *pdev)
++static int mxs_sgtl5000_probe_dt(struct platform_device *pdev)
+ {
+ 	struct device_node *np = pdev->dev.of_node;
+ 	struct device_node *saif_np[2], *codec_np;
+@@ -145,7 +145,7 @@ static int __devinit mxs_sgtl5000_probe_dt(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devinit mxs_sgtl5000_probe(struct platform_device *pdev)
++static int mxs_sgtl5000_probe(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = &mxs_sgtl5000;
+ 	int ret;
+@@ -176,7 +176,7 @@ static int __devinit mxs_sgtl5000_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit mxs_sgtl5000_remove(struct platform_device *pdev)
++static int mxs_sgtl5000_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -200,7 +200,7 @@ static struct platform_driver mxs_sgtl5000_audio_driver = {
+ 		.of_match_table = mxs_sgtl5000_dt_ids,
+ 	},
+ 	.probe = mxs_sgtl5000_probe,
+-	.remove = __devexit_p(mxs_sgtl5000_remove),
++	.remove = mxs_sgtl5000_remove,
+ };
+ 
+ module_platform_driver(mxs_sgtl5000_audio_driver);

commit 34e15fbdaa7b1839941d42c5fea96329a53be135
+Author: Bill Pemberton 
+Date:   Fri Dec 7 09:26:26 2012 -0500
+
+    ASoC: kirkwood: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c
+index 58d5a96b366f..d3d4bdca1cc6 100644
+--- a/sound/soc/kirkwood/kirkwood-dma.c
++++ b/sound/soc/kirkwood/kirkwood-dma.c
+@@ -372,12 +372,12 @@ static struct snd_soc_platform_driver kirkwood_soc_platform = {
+ 	.pcm_free	= kirkwood_dma_free_dma_buffers,
+ };
+ 
+-static int __devinit kirkwood_soc_platform_probe(struct platform_device *pdev)
++static int kirkwood_soc_platform_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_platform(&pdev->dev, &kirkwood_soc_platform);
+ }
+ 
+-static int __devexit kirkwood_soc_platform_remove(struct platform_device *pdev)
++static int kirkwood_soc_platform_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_platform(&pdev->dev);
+ 	return 0;
+@@ -390,7 +390,7 @@ static struct platform_driver kirkwood_pcm_driver = {
+ 	},
+ 
+ 	.probe = kirkwood_soc_platform_probe,
+-	.remove = __devexit_p(kirkwood_soc_platform_remove),
++	.remove = kirkwood_soc_platform_remove,
+ };
+ 
+ module_platform_driver(kirkwood_pcm_driver);
+diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c
+index d3629d5927e9..282d8b1163ba 100644
+--- a/sound/soc/kirkwood/kirkwood-i2s.c
++++ b/sound/soc/kirkwood/kirkwood-i2s.c
+@@ -451,7 +451,7 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk = {
+ 	.ops = &kirkwood_i2s_dai_ops,
+ };
+ 
+-static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev)
++static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
+ {
+ 	struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data;
+ 	struct snd_soc_dai_driver *soc_dai = &kirkwood_i2s_dai;
+@@ -540,7 +540,7 @@ static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static __devexit int kirkwood_i2s_dev_remove(struct platform_device *pdev)
++static int kirkwood_i2s_dev_remove(struct platform_device *pdev)
+ {
+ 	struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev);
+ 
+@@ -557,7 +557,7 @@ static __devexit int kirkwood_i2s_dev_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver kirkwood_i2s_driver = {
+ 	.probe  = kirkwood_i2s_dev_probe,
+-	.remove = __devexit_p(kirkwood_i2s_dev_remove),
++	.remove = kirkwood_i2s_dev_remove,
+ 	.driver = {
+ 		.name = DRV_NAME,
+ 		.owner = THIS_MODULE,
+diff --git a/sound/soc/kirkwood/kirkwood-openrd.c b/sound/soc/kirkwood/kirkwood-openrd.c
+index c28540aeea25..b979c7154715 100644
+--- a/sound/soc/kirkwood/kirkwood-openrd.c
++++ b/sound/soc/kirkwood/kirkwood-openrd.c
+@@ -71,7 +71,7 @@ static struct snd_soc_card openrd_client = {
+ 	.num_links = ARRAY_SIZE(openrd_client_dai),
+ };
+ 
+-static int __devinit openrd_probe(struct platform_device *pdev)
++static int openrd_probe(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = &openrd_client;
+ 	int ret;
+@@ -85,7 +85,7 @@ static int __devinit openrd_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit openrd_remove(struct platform_device *pdev)
++static int openrd_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -99,7 +99,7 @@ static struct platform_driver openrd_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= openrd_probe,
+-	.remove		= __devexit_p(openrd_remove),
++	.remove		= openrd_remove,
+ };
+ 
+ module_platform_driver(openrd_driver);
+diff --git a/sound/soc/kirkwood/kirkwood-t5325.c b/sound/soc/kirkwood/kirkwood-t5325.c
+index c67bbc574987..1d0ed6f8add7 100644
+--- a/sound/soc/kirkwood/kirkwood-t5325.c
++++ b/sound/soc/kirkwood/kirkwood-t5325.c
+@@ -92,7 +92,7 @@ static struct snd_soc_card t5325 = {
+ 	.num_dapm_routes = ARRAY_SIZE(t5325_route),
+ };
+ 
+-static int __devinit t5325_probe(struct platform_device *pdev)
++static int t5325_probe(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = &t5325;
+ 	int ret;
+@@ -106,7 +106,7 @@ static int __devinit t5325_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit t5325_remove(struct platform_device *pdev)
++static int t5325_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -120,7 +120,7 @@ static struct platform_driver t5325_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= t5325_probe,
+-	.remove		= __devexit_p(t5325_remove),
++	.remove		= t5325_remove,
+ };
+ 
+ module_platform_driver(t5325_driver);

commit 7759f2ea944914534dd3095db8978b75a2e4c982
+Author: Bill Pemberton 
+Date:   Fri Dec 7 09:26:25 2012 -0500
+
+    ASoC: mid-x86: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/mid-x86/mfld_machine.c b/sound/soc/mid-x86/mfld_machine.c
+index 2cc7782714b5..4139116c33b5 100644
+--- a/sound/soc/mid-x86/mfld_machine.c
++++ b/sound/soc/mid-x86/mfld_machine.c
+@@ -358,7 +358,7 @@ static irqreturn_t snd_mfld_jack_detection(int irq, void *data)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit snd_mfld_mc_probe(struct platform_device *pdev)
++static int snd_mfld_mc_probe(struct platform_device *pdev)
+ {
+ 	int ret_val = 0, irq;
+ 	struct mfld_mc_private *mc_drv_ctx;
+@@ -417,7 +417,7 @@ static int __devinit snd_mfld_mc_probe(struct platform_device *pdev)
+ 	return ret_val;
+ }
+ 
+-static int __devexit snd_mfld_mc_remove(struct platform_device *pdev)
++static int snd_mfld_mc_remove(struct platform_device *pdev)
+ {
+ 	struct mfld_mc_private *mc_drv_ctx = platform_get_drvdata(pdev);
+ 
+@@ -435,7 +435,7 @@ static struct platform_driver snd_mfld_mc_driver = {
+ 		.name = "msic_audio",
+ 	},
+ 	.probe = snd_mfld_mc_probe,
+-	.remove = __devexit_p(snd_mfld_mc_remove),
++	.remove = snd_mfld_mc_remove,
+ };
+ 
+ module_platform_driver(snd_mfld_mc_driver);

commit d6a29e3de0f93883464d132e4779c723d78b7a38
+Author: Bill Pemberton 
+Date:   Fri Dec 7 09:26:24 2012 -0500
+
+    ASoC: jz4740: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c
+index 41349670adab..6cef491f4823 100644
+--- a/sound/soc/jz4740/jz4740-i2s.c
++++ b/sound/soc/jz4740/jz4740-i2s.c
+@@ -425,7 +425,7 @@ static struct snd_soc_dai_driver jz4740_i2s_dai = {
+ 	.resume = jz4740_i2s_resume,
+ };
+ 
+-static int __devinit jz4740_i2s_dev_probe(struct platform_device *pdev)
++static int jz4740_i2s_dev_probe(struct platform_device *pdev)
+ {
+ 	struct jz4740_i2s *i2s;
+ 	int ret;
+@@ -492,7 +492,7 @@ static int __devinit jz4740_i2s_dev_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit jz4740_i2s_dev_remove(struct platform_device *pdev)
++static int jz4740_i2s_dev_remove(struct platform_device *pdev)
+ {
+ 	struct jz4740_i2s *i2s = platform_get_drvdata(pdev);
+ 
+@@ -512,7 +512,7 @@ static int __devexit jz4740_i2s_dev_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver jz4740_i2s_driver = {
+ 	.probe = jz4740_i2s_dev_probe,
+-	.remove = __devexit_p(jz4740_i2s_dev_remove),
++	.remove = jz4740_i2s_dev_remove,
+ 	.driver = {
+ 		.name = "jz4740-i2s",
+ 		.owner = THIS_MODULE,
+diff --git a/sound/soc/jz4740/jz4740-pcm.c b/sound/soc/jz4740/jz4740-pcm.c
+index 9b8cf256847d..710059292318 100644
+--- a/sound/soc/jz4740/jz4740-pcm.c
++++ b/sound/soc/jz4740/jz4740-pcm.c
+@@ -335,12 +335,12 @@ static struct snd_soc_platform_driver jz4740_soc_platform = {
+ 		.pcm_free	= jz4740_pcm_free,
+ };
+ 
+-static int __devinit jz4740_pcm_probe(struct platform_device *pdev)
++static int jz4740_pcm_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_platform(&pdev->dev, &jz4740_soc_platform);
+ }
+ 
+-static int __devexit jz4740_pcm_remove(struct platform_device *pdev)
++static int jz4740_pcm_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_platform(&pdev->dev);
+ 	return 0;
+@@ -348,7 +348,7 @@ static int __devexit jz4740_pcm_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver jz4740_pcm_driver = {
+ 	.probe = jz4740_pcm_probe,
+-	.remove = __devexit_p(jz4740_pcm_remove),
++	.remove = jz4740_pcm_remove,
+ 	.driver = {
+ 		.name = "jz4740-pcm-audio",
+ 		.owner = THIS_MODULE,
+diff --git a/sound/soc/jz4740/qi_lb60.c b/sound/soc/jz4740/qi_lb60.c
+index e8aaff18d7cc..55fd6b5df55f 100644
+--- a/sound/soc/jz4740/qi_lb60.c
++++ b/sound/soc/jz4740/qi_lb60.c
+@@ -96,7 +96,7 @@ static const struct gpio qi_lb60_gpios[] = {
+ 	{ QI_LB60_AMP_GPIO, GPIOF_OUT_INIT_LOW, "AMP" },
+ };
+ 
+-static int __devinit qi_lb60_probe(struct platform_device *pdev)
++static int qi_lb60_probe(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = &qi_lb60;
+ 	int ret;
+@@ -116,7 +116,7 @@ static int __devinit qi_lb60_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit qi_lb60_remove(struct platform_device *pdev)
++static int qi_lb60_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -131,7 +131,7 @@ static struct platform_driver qi_lb60_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= qi_lb60_probe,
+-	.remove		= __devexit_p(qi_lb60_remove),
++	.remove		= qi_lb60_remove,
+ };
+ 
+ module_platform_driver(qi_lb60_driver);

commit 145e2879560e3e99ae46e26f510e3b4a26cc03d4
+Author: Bill Pemberton 
+Date:   Fri Dec 7 09:26:23 2012 -0500
+
+    ASoC: cirrus: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/cirrus/edb93xx.c b/sound/soc/cirrus/edb93xx.c
+index e01cb02abd3a..5db68cf7b281 100644
+--- a/sound/soc/cirrus/edb93xx.c
++++ b/sound/soc/cirrus/edb93xx.c
+@@ -80,7 +80,7 @@ static struct snd_soc_card snd_soc_edb93xx = {
+ 	.num_links	= 1,
+ };
+ 
+-static int __devinit edb93xx_probe(struct platform_device *pdev)
++static int edb93xx_probe(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = &snd_soc_edb93xx;
+ 	int ret;
+@@ -101,7 +101,7 @@ static int __devinit edb93xx_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit edb93xx_remove(struct platform_device *pdev)
++static int edb93xx_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -117,7 +117,7 @@ static struct platform_driver edb93xx_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= edb93xx_probe,
+-	.remove		= __devexit_p(edb93xx_remove),
++	.remove		= edb93xx_remove,
+ };
+ 
+ module_platform_driver(edb93xx_driver);
+diff --git a/sound/soc/cirrus/ep93xx-ac97.c b/sound/soc/cirrus/ep93xx-ac97.c
+index c3521653cfd3..f3f50e6fd6eb 100644
+--- a/sound/soc/cirrus/ep93xx-ac97.c
++++ b/sound/soc/cirrus/ep93xx-ac97.c
+@@ -352,7 +352,7 @@ static struct snd_soc_dai_driver ep93xx_ac97_dai = {
+ 	.ops			= &ep93xx_ac97_dai_ops,
+ };
+ 
+-static int __devinit ep93xx_ac97_probe(struct platform_device *pdev)
++static int ep93xx_ac97_probe(struct platform_device *pdev)
+ {
+ 	struct ep93xx_ac97_info *info;
+ 	struct resource *res;
+@@ -402,7 +402,7 @@ static int __devinit ep93xx_ac97_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit ep93xx_ac97_remove(struct platform_device *pdev)
++static int ep93xx_ac97_remove(struct platform_device *pdev)
+ {
+ 	struct ep93xx_ac97_info	*info = platform_get_drvdata(pdev);
+ 
+@@ -420,7 +420,7 @@ static int __devexit ep93xx_ac97_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver ep93xx_ac97_driver = {
+ 	.probe	= ep93xx_ac97_probe,
+-	.remove	= __devexit_p(ep93xx_ac97_remove),
++	.remove	= ep93xx_ac97_remove,
+ 	.driver = {
+ 		.name = "ep93xx-ac97",
+ 		.owner = THIS_MODULE,
+diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c
+index ac4a7515e7be..3365d4e843b7 100644
+--- a/sound/soc/cirrus/ep93xx-i2s.c
++++ b/sound/soc/cirrus/ep93xx-i2s.c
+@@ -422,7 +422,7 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit ep93xx_i2s_remove(struct platform_device *pdev)
++static int ep93xx_i2s_remove(struct platform_device *pdev)
+ {
+ 	struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev);
+ 
+@@ -436,7 +436,7 @@ static int __devexit ep93xx_i2s_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver ep93xx_i2s_driver = {
+ 	.probe	= ep93xx_i2s_probe,
+-	.remove	= __devexit_p(ep93xx_i2s_remove),
++	.remove	= ep93xx_i2s_remove,
+ 	.driver	= {
+ 		.name	= "ep93xx-i2s",
+ 		.owner	= THIS_MODULE,
+diff --git a/sound/soc/cirrus/ep93xx-pcm.c b/sound/soc/cirrus/ep93xx-pcm.c
+index 665d9c94cc17..72eb7a49e16a 100644
+--- a/sound/soc/cirrus/ep93xx-pcm.c
++++ b/sound/soc/cirrus/ep93xx-pcm.c
+@@ -213,12 +213,12 @@ static struct snd_soc_platform_driver ep93xx_soc_platform = {
+ 	.pcm_free	= &ep93xx_pcm_free_dma_buffers,
+ };
+ 
+-static int __devinit ep93xx_soc_platform_probe(struct platform_device *pdev)
++static int ep93xx_soc_platform_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_platform(&pdev->dev, &ep93xx_soc_platform);
+ }
+ 
+-static int __devexit ep93xx_soc_platform_remove(struct platform_device *pdev)
++static int ep93xx_soc_platform_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_platform(&pdev->dev);
+ 	return 0;
+@@ -231,7 +231,7 @@ static struct platform_driver ep93xx_pcm_driver = {
+ 	},
+ 
+ 	.probe = ep93xx_soc_platform_probe,
+-	.remove = __devexit_p(ep93xx_soc_platform_remove),
++	.remove = ep93xx_soc_platform_remove,
+ };
+ 
+ module_platform_driver(ep93xx_pcm_driver);
+diff --git a/sound/soc/cirrus/simone.c b/sound/soc/cirrus/simone.c
+index dd997094eb30..a397bb0d8179 100644
+--- a/sound/soc/cirrus/simone.c
++++ b/sound/soc/cirrus/simone.c
+@@ -41,7 +41,7 @@ static struct snd_soc_card snd_soc_simone = {
+ 
+ static struct platform_device *simone_snd_ac97_device;
+ 
+-static int __devinit simone_probe(struct platform_device *pdev)
++static int simone_probe(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = &snd_soc_simone;
+ 	int ret;
+@@ -63,7 +63,7 @@ static int __devinit simone_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit simone_remove(struct platform_device *pdev)
++static int simone_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -79,7 +79,7 @@ static struct platform_driver simone_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= simone_probe,
+-	.remove		= __devexit_p(simone_remove),
++	.remove		= simone_remove,
+ };
+ 
+ module_platform_driver(simone_driver);
+diff --git a/sound/soc/cirrus/snappercl15.c b/sound/soc/cirrus/snappercl15.c
+index a193cea3cf3c..9d77fe28dfcc 100644
+--- a/sound/soc/cirrus/snappercl15.c
++++ b/sound/soc/cirrus/snappercl15.c
+@@ -98,7 +98,7 @@ static struct snd_soc_card snd_soc_snappercl15 = {
+ 	.num_links	= 1,
+ };
+ 
+-static int __devinit snappercl15_probe(struct platform_device *pdev)
++static int snappercl15_probe(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = &snd_soc_snappercl15;
+ 	int ret;
+@@ -119,7 +119,7 @@ static int __devinit snappercl15_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit snappercl15_remove(struct platform_device *pdev)
++static int snappercl15_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -135,7 +135,7 @@ static struct platform_driver snappercl15_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= snappercl15_probe,
+-	.remove		= __devexit_p(snappercl15_remove),
++	.remove		= snappercl15_remove,
+ };
+ 
+ module_platform_driver(snappercl15_driver);

commit 5c658be06175ec1dc8c80c8e28404b729f48df1b
+Author: Bill Pemberton 
+Date:   Fri Dec 7 09:26:22 2012 -0500
+
+    ASoC: au1x: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/au1x/ac97c.c b/sound/soc/au1x/ac97c.c
+index c5ac2449563a..ea7d9d157022 100644
+--- a/sound/soc/au1x/ac97c.c
++++ b/sound/soc/au1x/ac97c.c
+@@ -223,7 +223,7 @@ static struct snd_soc_dai_driver au1xac97c_dai_driver = {
+ 	.ops			= &alchemy_ac97c_ops,
+ };
+ 
+-static int __devinit au1xac97c_drvprobe(struct platform_device *pdev)
++static int au1xac97c_drvprobe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 	struct resource *iores, *dmares;
+@@ -276,7 +276,7 @@ static int __devinit au1xac97c_drvprobe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit au1xac97c_drvremove(struct platform_device *pdev)
++static int au1xac97c_drvremove(struct platform_device *pdev)
+ {
+ 	struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev);
+ 
+@@ -330,7 +330,7 @@ static struct platform_driver au1xac97c_driver = {
+ 		.pm	= AU1XPSCAC97_PMOPS,
+ 	},
+ 	.probe		= au1xac97c_drvprobe,
+-	.remove		= __devexit_p(au1xac97c_drvremove),
++	.remove		= au1xac97c_drvremove,
+ };
+ 
+ static int __init au1xac97c_load(void)
+diff --git a/sound/soc/au1x/db1000.c b/sound/soc/au1x/db1000.c
+index 511d83c11a9a..376d976bcc2d 100644
+--- a/sound/soc/au1x/db1000.c
++++ b/sound/soc/au1x/db1000.c
+@@ -34,14 +34,14 @@ static struct snd_soc_card db1000_ac97 = {
+ 	.num_links	= 1,
+ };
+ 
+-static int __devinit db1000_audio_probe(struct platform_device *pdev)
++static int db1000_audio_probe(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = &db1000_ac97;
+ 	card->dev = &pdev->dev;
+ 	return snd_soc_register_card(card);
+ }
+ 
+-static int __devexit db1000_audio_remove(struct platform_device *pdev)
++static int db1000_audio_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 	snd_soc_unregister_card(card);
+@@ -55,7 +55,7 @@ static struct platform_driver db1000_audio_driver = {
+ 		.pm	= &snd_soc_pm_ops,
+ 	},
+ 	.probe		= db1000_audio_probe,
+-	.remove		= __devexit_p(db1000_audio_remove),
++	.remove		= db1000_audio_remove,
+ };
+ 
+ module_platform_driver(db1000_audio_driver);
+diff --git a/sound/soc/au1x/db1200.c b/sound/soc/au1x/db1200.c
+index 30ea513d81d7..a497a0cfeba1 100644
+--- a/sound/soc/au1x/db1200.c
++++ b/sound/soc/au1x/db1200.c
+@@ -167,7 +167,7 @@ static struct snd_soc_card db1550_i2s_machine = {
+ 
+ /*-------------------------  COMMON PART  ---------------------------*/
+ 
+-static struct snd_soc_card *db1200_cards[] __devinitdata = {
++static struct snd_soc_card *db1200_cards[] = {
+ 	&db1200_ac97_machine,
+ 	&db1200_i2s_machine,
+ 	&db1300_ac97_machine,
+@@ -176,7 +176,7 @@ static struct snd_soc_card *db1200_cards[] __devinitdata = {
+ 	&db1550_i2s_machine,
+ };
+ 
+-static int __devinit db1200_audio_probe(struct platform_device *pdev)
++static int db1200_audio_probe(struct platform_device *pdev)
+ {
+ 	const struct platform_device_id *pid = platform_get_device_id(pdev);
+ 	struct snd_soc_card *card;
+@@ -186,7 +186,7 @@ static int __devinit db1200_audio_probe(struct platform_device *pdev)
+ 	return snd_soc_register_card(card);
+ }
+ 
+-static int __devexit db1200_audio_remove(struct platform_device *pdev)
++static int db1200_audio_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 	snd_soc_unregister_card(card);
+@@ -201,7 +201,7 @@ static struct platform_driver db1200_audio_driver = {
+ 	},
+ 	.id_table	= db1200_pids,
+ 	.probe		= db1200_audio_probe,
+-	.remove		= __devexit_p(db1200_audio_remove),
++	.remove		= db1200_audio_remove,
+ };
+ 
+ module_platform_driver(db1200_audio_driver);
+diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c
+index 8372cd35f0d6..3b4eafaf30d3 100644
+--- a/sound/soc/au1x/dbdma2.c
++++ b/sound/soc/au1x/dbdma2.c
+@@ -347,7 +347,7 @@ static struct snd_soc_platform_driver au1xpsc_soc_platform = {
+ 	.pcm_free	= au1xpsc_pcm_free_dma_buffers,
+ };
+ 
+-static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev)
++static int au1xpsc_pcm_drvprobe(struct platform_device *pdev)
+ {
+ 	struct au1xpsc_audio_dmadata *dmadata;
+ 
+@@ -362,7 +362,7 @@ static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev)
+ 	return snd_soc_register_platform(&pdev->dev, &au1xpsc_soc_platform);
+ }
+ 
+-static int __devexit au1xpsc_pcm_drvremove(struct platform_device *pdev)
++static int au1xpsc_pcm_drvremove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_platform(&pdev->dev);
+ 
+@@ -375,7 +375,7 @@ static struct platform_driver au1xpsc_pcm_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= au1xpsc_pcm_drvprobe,
+-	.remove		= __devexit_p(au1xpsc_pcm_drvremove),
++	.remove		= au1xpsc_pcm_drvremove,
+ };
+ 
+ module_platform_driver(au1xpsc_pcm_driver);
+diff --git a/sound/soc/au1x/dma.c b/sound/soc/au1x/dma.c
+index 0a91b186a86f..befd1074f9bd 100644
+--- a/sound/soc/au1x/dma.c
++++ b/sound/soc/au1x/dma.c
+@@ -322,7 +322,7 @@ static struct snd_soc_platform_driver alchemy_pcm_soc_platform = {
+ 	.pcm_free	= alchemy_pcm_free_dma_buffers,
+ };
+ 
+-static int __devinit alchemy_pcm_drvprobe(struct platform_device *pdev)
++static int alchemy_pcm_drvprobe(struct platform_device *pdev)
+ {
+ 	struct alchemy_pcm_ctx *ctx;
+ 
+@@ -335,7 +335,7 @@ static int __devinit alchemy_pcm_drvprobe(struct platform_device *pdev)
+ 	return snd_soc_register_platform(&pdev->dev, &alchemy_pcm_soc_platform);
+ }
+ 
+-static int __devexit alchemy_pcm_drvremove(struct platform_device *pdev)
++static int alchemy_pcm_drvremove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_platform(&pdev->dev);
+ 
+@@ -348,7 +348,7 @@ static struct platform_driver alchemy_pcmdma_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= alchemy_pcm_drvprobe,
+-	.remove		= __devexit_p(alchemy_pcm_drvremove),
++	.remove		= alchemy_pcm_drvremove,
+ };
+ 
+ module_platform_driver(alchemy_pcmdma_driver);
+diff --git a/sound/soc/au1x/i2sc.c b/sound/soc/au1x/i2sc.c
+index d4b9e364a47a..072448afc219 100644
+--- a/sound/soc/au1x/i2sc.c
++++ b/sound/soc/au1x/i2sc.c
+@@ -225,7 +225,7 @@ static struct snd_soc_dai_driver au1xi2s_dai_driver = {
+ 	.ops = &au1xi2s_dai_ops,
+ };
+ 
+-static int __devinit au1xi2s_drvprobe(struct platform_device *pdev)
++static int au1xi2s_drvprobe(struct platform_device *pdev)
+ {
+ 	struct resource *iores, *dmares;
+ 	struct au1xpsc_audio_data *ctx;
+@@ -263,7 +263,7 @@ static int __devinit au1xi2s_drvprobe(struct platform_device *pdev)
+ 	return snd_soc_register_dai(&pdev->dev, &au1xi2s_dai_driver);
+ }
+ 
+-static int __devexit au1xi2s_drvremove(struct platform_device *pdev)
++static int au1xi2s_drvremove(struct platform_device *pdev)
+ {
+ 	struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev);
+ 
+@@ -309,7 +309,7 @@ static struct platform_driver au1xi2s_driver = {
+ 		.pm	= AU1XI2SC_PMOPS,
+ 	},
+ 	.probe		= au1xi2s_drvprobe,
+-	.remove		= __devexit_p(au1xi2s_drvremove),
++	.remove		= au1xi2s_drvremove,
+ };
+ 
+ module_platform_driver(au1xi2s_driver);
+diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c
+index 476b79a1c11a..6ba07e365967 100644
+--- a/sound/soc/au1x/psc-ac97.c
++++ b/sound/soc/au1x/psc-ac97.c
+@@ -361,7 +361,7 @@ static const struct snd_soc_dai_driver au1xpsc_ac97_dai_template = {
+ 	.ops = &au1xpsc_ac97_dai_ops,
+ };
+ 
+-static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
++static int au1xpsc_ac97_drvprobe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 	struct resource *iores, *dmares;
+@@ -427,7 +427,7 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit au1xpsc_ac97_drvremove(struct platform_device *pdev)
++static int au1xpsc_ac97_drvremove(struct platform_device *pdev)
+ {
+ 	struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
+ 
+@@ -495,7 +495,7 @@ static struct platform_driver au1xpsc_ac97_driver = {
+ 		.pm	= AU1XPSCAC97_PMOPS,
+ 	},
+ 	.probe		= au1xpsc_ac97_drvprobe,
+-	.remove		= __devexit_p(au1xpsc_ac97_drvremove),
++	.remove		= au1xpsc_ac97_drvremove,
+ };
+ 
+ static int __init au1xpsc_ac97_load(void)
+diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c
+index 0607ba3d9258..360b4e50d7c8 100644
+--- a/sound/soc/au1x/psc-i2s.c
++++ b/sound/soc/au1x/psc-i2s.c
+@@ -288,7 +288,7 @@ static const struct snd_soc_dai_driver au1xpsc_i2s_dai_template = {
+ 	.ops = &au1xpsc_i2s_dai_ops,
+ };
+ 
+-static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
++static int au1xpsc_i2s_drvprobe(struct platform_device *pdev)
+ {
+ 	struct resource *iores, *dmares;
+ 	unsigned long sel;
+@@ -353,7 +353,7 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
+ 	return snd_soc_register_dai(&pdev->dev, &wd->dai_drv);
+ }
+ 
+-static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev)
++static int au1xpsc_i2s_drvremove(struct platform_device *pdev)
+ {
+ 	struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
+ 
+@@ -418,7 +418,7 @@ static struct platform_driver au1xpsc_i2s_driver = {
+ 		.pm	= AU1XPSCI2S_PMOPS,
+ 	},
+ 	.probe		= au1xpsc_i2s_drvprobe,
+-	.remove		= __devexit_p(au1xpsc_i2s_drvremove),
++	.remove		= au1xpsc_i2s_drvremove,
+ };
+ 
+ module_platform_driver(au1xpsc_i2s_driver);

commit 71d14ea60ad81a685cc9a879d2b9a89494cdba8f
+Author: Bill Pemberton 
+Date:   Fri Dec 7 09:26:21 2012 -0500
+
+    ASoC: atmel: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c
+index 0744610e53dd..da976291da9e 100644
+--- a/sound/soc/atmel/sam9g20_wm8731.c
++++ b/sound/soc/atmel/sam9g20_wm8731.c
+@@ -197,7 +197,7 @@ static struct snd_soc_card snd_soc_at91sam9g20ek = {
+ 	.set_bias_level = at91sam9g20ek_set_bias_level,
+ };
+ 
+-static int __devinit at91sam9g20ek_audio_probe(struct platform_device *pdev)
++static int at91sam9g20ek_audio_probe(struct platform_device *pdev)
+ {
+ 	struct device_node *np = pdev->dev.of_node;
+ 	struct device_node *codec_np, *cpu_np;
+@@ -301,7 +301,7 @@ static int __devinit at91sam9g20ek_audio_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit at91sam9g20ek_audio_remove(struct platform_device *pdev)
++static int at91sam9g20ek_audio_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -328,7 +328,7 @@ static struct platform_driver at91sam9g20ek_audio_driver = {
+ 		.of_match_table = of_match_ptr(at91sam9g20ek_wm8731_dt_ids),
+ 	},
+ 	.probe	= at91sam9g20ek_audio_probe,
+-	.remove	= __devexit_p(at91sam9g20ek_audio_remove),
++	.remove	= at91sam9g20ek_audio_remove,
+ };
+ 
+ module_platform_driver(at91sam9g20ek_audio_driver);

commit 05c4c6f7072cff531c62322e07a156b1501df7a5
+Author: Bill Pemberton 
+Date:   Fri Dec 7 09:26:20 2012 -0500
+
+    ASoC: twl4030: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
+index e7f608996c41..63b280b06035 100644
+--- a/sound/soc/codecs/twl4030.c
++++ b/sound/soc/codecs/twl4030.c
+@@ -2334,13 +2334,13 @@ static struct snd_soc_codec_driver soc_codec_dev_twl4030 = {
+ 	.num_dapm_routes = ARRAY_SIZE(intercon),
+ };
+ 
+-static int __devinit twl4030_codec_probe(struct platform_device *pdev)
++static int twl4030_codec_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl4030,
+ 			twl4030_dai, ARRAY_SIZE(twl4030_dai));
+ }
+ 
+-static int __devexit twl4030_codec_remove(struct platform_device *pdev)
++static int twl4030_codec_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_codec(&pdev->dev);
+ 	return 0;
+@@ -2350,7 +2350,7 @@ MODULE_ALIAS("platform:twl4030-codec");
+ 
+ static struct platform_driver twl4030_codec_driver = {
+ 	.probe		= twl4030_codec_probe,
+-	.remove		= __devexit_p(twl4030_codec_remove),
++	.remove		= twl4030_codec_remove,
+ 	.driver		= {
+ 		.name	= "twl4030-codec",
+ 		.owner	= THIS_MODULE,

commit bd479f6f5f5dc2a54bc2cc658c310ed8ad2228a9
+Author: Bill Pemberton 
+Date:   Fri Dec 7 09:26:19 2012 -0500
+
+    ASoC: lm49453: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c
+index 096b6aa87f0f..d75257d40a49 100644
+--- a/sound/soc/codecs/lm49453.c
++++ b/sound/soc/codecs/lm49453.c
+@@ -1483,8 +1483,8 @@ static const struct regmap_config lm49453_regmap_config = {
+ 	.cache_type = REGCACHE_RBTREE,
+ };
+ 
+-static __devinit int lm49453_i2c_probe(struct i2c_client *i2c,
+-				       const struct i2c_device_id *id)
++static int lm49453_i2c_probe(struct i2c_client *i2c,
++			     const struct i2c_device_id *id)
+ {
+ 	struct lm49453_priv *lm49453;
+ 	int ret = 0;
+@@ -1514,7 +1514,7 @@ static __devinit int lm49453_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static int __devexit lm49453_i2c_remove(struct i2c_client *client)
++static int lm49453_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -1532,7 +1532,7 @@ static struct i2c_driver lm49453_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = lm49453_i2c_probe,
+-	.remove = __devexit_p(lm49453_i2c_remove),
++	.remove = lm49453_i2c_remove,
+ 	.id_table = lm49453_i2c_id,
+ };
+ 

commit c88f3de8555486706c87f5f34f9b45e4c4826283
+Author: Bill Pemberton 
+Date:   Fri Dec 7 09:26:18 2012 -0500
+
+    ASoC: isabelle: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c
+index 1bf55602c9eb..53b455b8c07a 100644
+--- a/sound/soc/codecs/isabelle.c
++++ b/sound/soc/codecs/isabelle.c
+@@ -1119,8 +1119,8 @@ static const struct regmap_config isabelle_regmap_config = {
+ 	.cache_type = REGCACHE_RBTREE,
+ };
+ 
+-static int __devinit isabelle_i2c_probe(struct i2c_client *i2c,
+-					const struct i2c_device_id *id)
++static int isabelle_i2c_probe(struct i2c_client *i2c,
++			      const struct i2c_device_id *id)
+ {
+ 	struct regmap *isabelle_regmap;
+ 	int ret = 0;
+@@ -1145,7 +1145,7 @@ static int __devinit isabelle_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static int __devexit isabelle_i2c_remove(struct i2c_client *client)
++static int isabelle_i2c_remove(struct i2c_client *client)
+ {
+ 	snd_soc_unregister_codec(&client->dev);
+ 	return 0;
+@@ -1163,7 +1163,7 @@ static struct i2c_driver isabelle_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = isabelle_i2c_probe,
+-	.remove = __devexit_p(isabelle_i2c_remove),
++	.remove = isabelle_i2c_remove,
+ 	.id_table = isabelle_i2c_id,
+ };
+ 

commit 570f6fe1c35481a2f70f848216978a68b96dc92a
+Author: Bill Pemberton 
+Date:   Fri Dec 7 09:26:17 2012 -0500
+
+    ASoC: pxa: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Haojian Zhuang 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/pxa/brownstone.c b/sound/soc/pxa/brownstone.c
+index 5e666e03d333..4ad76099dd43 100644
+--- a/sound/soc/pxa/brownstone.c
++++ b/sound/soc/pxa/brownstone.c
+@@ -140,7 +140,7 @@ static struct snd_soc_card brownstone = {
+ 	.num_dapm_routes = ARRAY_SIZE(brownstone_audio_map),
+ };
+ 
+-static int __devinit brownstone_probe(struct platform_device *pdev)
++static int brownstone_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 
+@@ -152,7 +152,7 @@ static int __devinit brownstone_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit brownstone_remove(struct platform_device *pdev)
++static int brownstone_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_card(&brownstone);
+ 	return 0;
+@@ -164,7 +164,7 @@ static struct platform_driver mmp_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= brownstone_probe,
+-	.remove		= __devexit_p(brownstone_remove),
++	.remove		= brownstone_remove,
+ };
+ 
+ module_platform_driver(mmp_driver);
+diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
+index 863367ad89ce..f4cce1e80112 100644
+--- a/sound/soc/pxa/corgi.c
++++ b/sound/soc/pxa/corgi.c
+@@ -303,7 +303,7 @@ static struct snd_soc_card corgi = {
+ 	.num_dapm_routes = ARRAY_SIZE(corgi_audio_map),
+ };
+ 
+-static int __devinit corgi_probe(struct platform_device *pdev)
++static int corgi_probe(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = &corgi;
+ 	int ret;
+@@ -317,7 +317,7 @@ static int __devinit corgi_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit corgi_remove(struct platform_device *pdev)
++static int corgi_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -331,7 +331,7 @@ static struct platform_driver corgi_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= corgi_probe,
+-	.remove		= __devexit_p(corgi_remove),
++	.remove		= corgi_remove,
+ };
+ 
+ module_platform_driver(corgi_driver);
+diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c
+index 7b1bc2390039..70d799b13f0d 100644
+--- a/sound/soc/pxa/e740_wm9705.c
++++ b/sound/soc/pxa/e740_wm9705.c
+@@ -144,7 +144,7 @@ static struct gpio e740_audio_gpios[] = {
+ 	{ GPIO_E740_WM9705_nAVDD2, GPIOF_OUT_INIT_HIGH, "Audio power" },
+ };
+ 
+-static int __devinit e740_probe(struct platform_device *pdev)
++static int e740_probe(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = &e740;
+ 	int ret;
+@@ -165,7 +165,7 @@ static int __devinit e740_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit e740_remove(struct platform_device *pdev)
++static int e740_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -180,7 +180,7 @@ static struct platform_driver e740_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= e740_probe,
+-	.remove		= __devexit_p(e740_remove),
++	.remove		= e740_remove,
+ };
+ 
+ module_platform_driver(e740_driver);
+diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c
+index 47b89d71e287..f94d2ab51351 100644
+--- a/sound/soc/pxa/e750_wm9705.c
++++ b/sound/soc/pxa/e750_wm9705.c
+@@ -126,7 +126,7 @@ static struct gpio e750_audio_gpios[] = {
+ 	{ GPIO_E750_SPK_AMP_OFF, GPIOF_OUT_INIT_HIGH, "Speaker amp" },
+ };
+ 
+-static int __devinit e750_probe(struct platform_device *pdev)
++static int e750_probe(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = &e750;
+ 	int ret;
+@@ -147,7 +147,7 @@ static int __devinit e750_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit e750_remove(struct platform_device *pdev)
++static int e750_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -162,7 +162,7 @@ static struct platform_driver e750_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= e750_probe,
+-	.remove		= __devexit_p(e750_remove),
++	.remove		= e750_remove,
+ };
+ 
+ module_platform_driver(e750_driver);
+diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c
+index ea9707ec6f28..8768a640dd71 100644
+--- a/sound/soc/pxa/e800_wm9712.c
++++ b/sound/soc/pxa/e800_wm9712.c
+@@ -116,7 +116,7 @@ static struct gpio e800_audio_gpios[] = {
+ 	{ GPIO_E800_HP_AMP_OFF, GPIOF_OUT_INIT_HIGH, "Speaker amp" },
+ };
+ 
+-static int __devinit e800_probe(struct platform_device *pdev)
++static int e800_probe(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = &e800;
+ 	int ret;
+@@ -137,7 +137,7 @@ static int __devinit e800_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit e800_remove(struct platform_device *pdev)
++static int e800_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -152,7 +152,7 @@ static struct platform_driver e800_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= e800_probe,
+-	.remove		= __devexit_p(e800_remove),
++	.remove		= e800_remove,
+ };
+ 
+ module_platform_driver(e800_driver);
+diff --git a/sound/soc/pxa/imote2.c b/sound/soc/pxa/imote2.c
+index b93dafd32b80..eef1f7b7b38e 100644
+--- a/sound/soc/pxa/imote2.c
++++ b/sound/soc/pxa/imote2.c
+@@ -65,7 +65,7 @@ static struct snd_soc_card imote2 = {
+ 	.num_links = 1,
+ };
+ 
+-static int __devinit imote2_probe(struct platform_device *pdev)
++static int imote2_probe(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = &imote2;
+ 	int ret;
+@@ -79,7 +79,7 @@ static int __devinit imote2_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit imote2_remove(struct platform_device *pdev)
++static int imote2_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -93,7 +93,7 @@ static struct platform_driver imote2_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= imote2_probe,
+-	.remove		= __devexit_p(imote2_remove),
++	.remove		= imote2_remove,
+ };
+ 
+ module_platform_driver(imote2_driver);
+diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c
+index 8687c1c65d29..97b711e12821 100644
+--- a/sound/soc/pxa/mioa701_wm9713.c
++++ b/sound/soc/pxa/mioa701_wm9713.c
+@@ -186,7 +186,7 @@ static struct snd_soc_card mioa701 = {
+ 	.num_links = ARRAY_SIZE(mioa701_dai),
+ };
+ 
+-static int __devinit mioa701_wm9713_probe(struct platform_device *pdev)
++static int mioa701_wm9713_probe(struct platform_device *pdev)
+ {
+ 	int rc;
+ 
+@@ -202,7 +202,7 @@ static int __devinit mioa701_wm9713_probe(struct platform_device *pdev)
+ 	return rc;
+ }
+ 
+-static int __devexit mioa701_wm9713_remove(struct platform_device *pdev)
++static int mioa701_wm9713_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -212,7 +212,7 @@ static int __devexit mioa701_wm9713_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver mioa701_wm9713_driver = {
+ 	.probe		= mioa701_wm9713_probe,
+-	.remove		= __devexit_p(mioa701_wm9713_remove),
++	.remove		= mioa701_wm9713_remove,
+ 	.driver		= {
+ 		.name		= "mioa701-wm9713",
+ 		.owner		= THIS_MODULE,
+diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c
+index e834faf859fd..190eb0bccf5f 100644
+--- a/sound/soc/pxa/mmp-pcm.c
++++ b/sound/soc/pxa/mmp-pcm.c
+@@ -257,7 +257,7 @@ struct snd_soc_platform_driver mmp_soc_platform = {
+ 	.pcm_free	= mmp_pcm_free_dma_buffers,
+ };
+ 
+-static __devinit int mmp_pcm_probe(struct platform_device *pdev)
++static int mmp_pcm_probe(struct platform_device *pdev)
+ {
+ 	struct mmp_audio_platdata *pdata = pdev->dev.platform_data;
+ 
+@@ -274,7 +274,7 @@ static __devinit int mmp_pcm_probe(struct platform_device *pdev)
+ 	return snd_soc_register_platform(&pdev->dev, &mmp_soc_platform);
+ }
+ 
+-static int __devexit mmp_pcm_remove(struct platform_device *pdev)
++static int mmp_pcm_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_platform(&pdev->dev);
+ 	return 0;
+@@ -287,7 +287,7 @@ static struct platform_driver mmp_pcm_driver = {
+ 	},
+ 
+ 	.probe = mmp_pcm_probe,
+-	.remove = __devexit_p(mmp_pcm_remove),
++	.remove = mmp_pcm_remove,
+ };
+ 
+ module_platform_driver(mmp_pcm_driver);
+diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c
+index 4d6cb8a30fc8..41c3a09b53ea 100644
+--- a/sound/soc/pxa/mmp-sspa.c
++++ b/sound/soc/pxa/mmp-sspa.c
+@@ -405,7 +405,7 @@ struct snd_soc_dai_driver mmp_sspa_dai = {
+ 	.ops = &mmp_sspa_dai_ops,
+ };
+ 
+-static __devinit int asoc_mmp_sspa_probe(struct platform_device *pdev)
++static int asoc_mmp_sspa_probe(struct platform_device *pdev)
+ {
+ 	struct sspa_priv *priv;
+ 	struct resource *res;
+@@ -453,7 +453,7 @@ static __devinit int asoc_mmp_sspa_probe(struct platform_device *pdev)
+ 	return snd_soc_register_dai(&pdev->dev, &mmp_sspa_dai);
+ }
+ 
+-static int __devexit asoc_mmp_sspa_remove(struct platform_device *pdev)
++static int asoc_mmp_sspa_remove(struct platform_device *pdev)
+ {
+ 	struct sspa_priv *priv = platform_get_drvdata(pdev);
+ 
+@@ -470,7 +470,7 @@ static struct platform_driver asoc_mmp_sspa_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = asoc_mmp_sspa_probe,
+-	.remove = __devexit_p(asoc_mmp_sspa_remove),
++	.remove = asoc_mmp_sspa_remove,
+ };
+ 
+ module_platform_driver(asoc_mmp_sspa_driver);
+diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c
+index aa3da91907c6..2074e2daf9c6 100644
+--- a/sound/soc/pxa/palm27x.c
++++ b/sound/soc/pxa/palm27x.c
+@@ -187,7 +187,7 @@ static int palm27x_asoc_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit palm27x_asoc_remove(struct platform_device *pdev)
++static int palm27x_asoc_remove(struct platform_device *pdev)
+ {
+ 	platform_device_unregister(palm27x_snd_device);
+ 	return 0;
+@@ -195,7 +195,7 @@ static int __devexit palm27x_asoc_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver palm27x_wm9712_driver = {
+ 	.probe		= palm27x_asoc_probe,
+-	.remove		= __devexit_p(palm27x_asoc_remove),
++	.remove		= palm27x_asoc_remove,
+ 	.driver		= {
+ 		.name		= "palm27x-asoc",
+ 		.owner		= THIS_MODULE,
+diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
+index d2cc81735036..fafe46355c31 100644
+--- a/sound/soc/pxa/poodle.c
++++ b/sound/soc/pxa/poodle.c
+@@ -269,7 +269,7 @@ static struct snd_soc_card poodle = {
+ 	.num_dapm_routes = ARRAY_SIZE(poodle_audio_map),
+ };
+ 
+-static int __devinit poodle_probe(struct platform_device *pdev)
++static int poodle_probe(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = &poodle;
+ 	int ret;
+@@ -291,7 +291,7 @@ static int __devinit poodle_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit poodle_remove(struct platform_device *pdev)
++static int poodle_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -305,7 +305,7 @@ static struct platform_driver poodle_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= poodle_probe,
+-	.remove		= __devexit_p(poodle_remove),
++	.remove		= poodle_remove,
+ };
+ 
+ module_platform_driver(poodle_driver);
+diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
+index 4da5fc55c7ee..d3eb0c2eec77 100644
+--- a/sound/soc/pxa/pxa-ssp.c
++++ b/sound/soc/pxa/pxa-ssp.c
+@@ -794,12 +794,12 @@ static struct snd_soc_dai_driver pxa_ssp_dai = {
+ 		.ops = &pxa_ssp_dai_ops,
+ };
+ 
+-static __devinit int asoc_ssp_probe(struct platform_device *pdev)
++static int asoc_ssp_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_dai(&pdev->dev, &pxa_ssp_dai);
+ }
+ 
+-static int __devexit asoc_ssp_remove(struct platform_device *pdev)
++static int asoc_ssp_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_dai(&pdev->dev);
+ 	return 0;
+@@ -812,7 +812,7 @@ static struct platform_driver asoc_ssp_driver = {
+ 	},
+ 
+ 	.probe = asoc_ssp_probe,
+-	.remove = __devexit_p(asoc_ssp_remove),
++	.remove = asoc_ssp_remove,
+ };
+ 
+ module_platform_driver(asoc_ssp_driver);
+diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
+index 06ea2744cc88..4b0a009bd683 100644
+--- a/sound/soc/pxa/pxa2xx-ac97.c
++++ b/sound/soc/pxa/pxa2xx-ac97.c
+@@ -104,7 +104,7 @@ static int pxa2xx_ac97_resume(struct snd_soc_dai *dai)
+ #define pxa2xx_ac97_resume	NULL
+ #endif
+ 
+-static int __devinit pxa2xx_ac97_probe(struct snd_soc_dai *dai)
++static int pxa2xx_ac97_probe(struct snd_soc_dai *dai)
+ {
+ 	return pxa2xx_ac97_hw_probe(to_platform_device(dai->dev));
+ }
+@@ -234,7 +234,7 @@ static struct snd_soc_dai_driver pxa_ac97_dai_driver[] = {
+ 
+ EXPORT_SYMBOL_GPL(soc_ac97_ops);
+ 
+-static __devinit int pxa2xx_ac97_dev_probe(struct platform_device *pdev)
++static int pxa2xx_ac97_dev_probe(struct platform_device *pdev)
+ {
+ 	if (pdev->id != -1) {
+ 		dev_err(&pdev->dev, "PXA2xx has only one AC97 port.\n");
+@@ -249,7 +249,7 @@ static __devinit int pxa2xx_ac97_dev_probe(struct platform_device *pdev)
+ 			ARRAY_SIZE(pxa_ac97_dai_driver));
+ }
+ 
+-static int __devexit pxa2xx_ac97_dev_remove(struct platform_device *pdev)
++static int pxa2xx_ac97_dev_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(pxa_ac97_dai_driver));
+ 	return 0;
+@@ -257,7 +257,7 @@ static int __devexit pxa2xx_ac97_dev_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver pxa2xx_ac97_driver = {
+ 	.probe		= pxa2xx_ac97_dev_probe,
+-	.remove		= __devexit_p(pxa2xx_ac97_dev_remove),
++	.remove		= pxa2xx_ac97_dev_remove,
+ 	.driver		= {
+ 		.name	= "pxa2xx-ac97",
+ 		.owner	= THIS_MODULE,
+diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
+index 3075a426124c..6b1a06f67564 100644
+--- a/sound/soc/pxa/pxa2xx-i2s.c
++++ b/sound/soc/pxa/pxa2xx-i2s.c
+@@ -365,7 +365,7 @@ static int pxa2xx_i2s_drv_probe(struct platform_device *pdev)
+ 	return snd_soc_register_dai(&pdev->dev, &pxa_i2s_dai);
+ }
+ 
+-static int __devexit pxa2xx_i2s_drv_remove(struct platform_device *pdev)
++static int pxa2xx_i2s_drv_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_dai(&pdev->dev);
+ 	return 0;
+@@ -373,7 +373,7 @@ static int __devexit pxa2xx_i2s_drv_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver pxa2xx_i2s_driver = {
+ 	.probe = pxa2xx_i2s_drv_probe,
+-	.remove = __devexit_p(pxa2xx_i2s_drv_remove),
++	.remove = pxa2xx_i2s_drv_remove,
+ 
+ 	.driver = {
+ 		.name = "pxa2xx-i2s",
+diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
+index fdd6bedef9bd..ecff116cb7b0 100644
+--- a/sound/soc/pxa/pxa2xx-pcm.c
++++ b/sound/soc/pxa/pxa2xx-pcm.c
+@@ -120,12 +120,12 @@ static struct snd_soc_platform_driver pxa2xx_soc_platform = {
+ 	.pcm_free	= pxa2xx_pcm_free_dma_buffers,
+ };
+ 
+-static int __devinit pxa2xx_soc_platform_probe(struct platform_device *pdev)
++static int pxa2xx_soc_platform_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_platform(&pdev->dev, &pxa2xx_soc_platform);
+ }
+ 
+-static int __devexit pxa2xx_soc_platform_remove(struct platform_device *pdev)
++static int pxa2xx_soc_platform_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_platform(&pdev->dev);
+ 	return 0;
+@@ -138,7 +138,7 @@ static struct platform_driver pxa_pcm_driver = {
+ 	},
+ 
+ 	.probe = pxa2xx_soc_platform_probe,
+-	.remove = __devexit_p(pxa2xx_soc_platform_remove),
++	.remove = pxa2xx_soc_platform_remove,
+ };
+ 
+ module_platform_driver(pxa_pcm_driver);
+diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
+index 2aec63f3706a..a3fe19123f07 100644
+--- a/sound/soc/pxa/tosa.c
++++ b/sound/soc/pxa/tosa.c
+@@ -241,7 +241,7 @@ static struct snd_soc_card tosa = {
+ 	.num_links = ARRAY_SIZE(tosa_dai),
+ };
+ 
+-static int __devinit tosa_probe(struct platform_device *pdev)
++static int tosa_probe(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = ⤩
+ 	int ret;
+@@ -262,7 +262,7 @@ static int __devinit tosa_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit tosa_remove(struct platform_device *pdev)
++static int tosa_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -277,7 +277,7 @@ static struct platform_driver tosa_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= tosa_probe,
+-	.remove		= __devexit_p(tosa_remove),
++	.remove		= tosa_remove,
+ };
+ 
+ module_platform_driver(tosa_driver);
+diff --git a/sound/soc/pxa/ttc-dkb.c b/sound/soc/pxa/ttc-dkb.c
+index 935491a8a770..f4ea4f6663a2 100644
+--- a/sound/soc/pxa/ttc-dkb.c
++++ b/sound/soc/pxa/ttc-dkb.c
+@@ -131,7 +131,7 @@ static struct snd_soc_card ttc_dkb_card = {
+ 	.num_dapm_routes = ARRAY_SIZE(ttc_audio_map),
+ };
+ 
+-static int __devinit ttc_dkb_probe(struct platform_device *pdev)
++static int ttc_dkb_probe(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = &ttc_dkb_card;
+ 	int ret;
+@@ -146,7 +146,7 @@ static int __devinit ttc_dkb_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit ttc_dkb_remove(struct platform_device *pdev)
++static int ttc_dkb_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -161,7 +161,7 @@ static struct platform_driver ttc_dkb_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= ttc_dkb_probe,
+-	.remove		= __devexit_p(ttc_dkb_remove),
++	.remove		= ttc_dkb_remove,
+ };
+ 
+ module_platform_driver(ttc_dkb_driver);

commit a0a3d518c33853940936fae5ed579509fe5966eb
+Author: Bill Pemberton 
+Date:   Fri Dec 7 09:26:16 2012 -0500
+
+    ASoC: fsl: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c
+index 267d5b4b63ce..75ffdf0e2aad 100644
+--- a/sound/soc/fsl/eukrea-tlv320.c
++++ b/sound/soc/fsl/eukrea-tlv320.c
+@@ -93,7 +93,7 @@ static struct snd_soc_card eukrea_tlv320 = {
+ 	.num_links	= 1,
+ };
+ 
+-static int __devinit eukrea_tlv320_probe(struct platform_device *pdev)
++static int eukrea_tlv320_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 	int int_port = 0, ext_port;
+@@ -142,7 +142,7 @@ static int __devinit eukrea_tlv320_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit eukrea_tlv320_remove(struct platform_device *pdev)
++static int eukrea_tlv320_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_card(&eukrea_tlv320);
+ 
+@@ -155,7 +155,7 @@ static struct platform_driver eukrea_tlv320_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = eukrea_tlv320_probe,
+-	.remove = __devexit_p(eukrea_tlv320_remove),};
++	.remove = eukrea_tlv320_remove,};
+ 
+ module_platform_driver(eukrea_tlv320_driver);
+ 
+diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
+index 6feb26500580..9cc5c1f82f09 100644
+--- a/sound/soc/fsl/fsl_dma.c
++++ b/sound/soc/fsl/fsl_dma.c
+@@ -894,7 +894,7 @@ static struct snd_pcm_ops fsl_dma_ops = {
+ 	.pointer	= fsl_dma_pointer,
+ };
+ 
+-static int __devinit fsl_soc_dma_probe(struct platform_device *pdev)
++static int fsl_soc_dma_probe(struct platform_device *pdev)
+  {
+ 	struct dma_object *dma;
+ 	struct device_node *np = pdev->dev.of_node;
+@@ -958,7 +958,7 @@ static int __devinit fsl_soc_dma_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit fsl_soc_dma_remove(struct platform_device *pdev)
++static int fsl_soc_dma_remove(struct platform_device *pdev)
+ {
+ 	struct dma_object *dma = dev_get_drvdata(&pdev->dev);
+ 
+@@ -983,7 +983,7 @@ static struct platform_driver fsl_soc_dma_driver = {
+ 		.of_match_table = fsl_soc_dma_ids,
+ 	},
+ 	.probe = fsl_soc_dma_probe,
+-	.remove = __devexit_p(fsl_soc_dma_remove),
++	.remove = fsl_soc_dma_remove,
+ };
+ 
+ module_platform_driver(fsl_soc_dma_driver);
+diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
+index 4ed2afd47782..7decbd9b2340 100644
+--- a/sound/soc/fsl/fsl_ssi.c
++++ b/sound/soc/fsl/fsl_ssi.c
+@@ -639,7 +639,7 @@ static void make_lowercase(char *s)
+ 	}
+ }
+ 
+-static int __devinit fsl_ssi_probe(struct platform_device *pdev)
++static int fsl_ssi_probe(struct platform_device *pdev)
+ {
+ 	struct fsl_ssi_private *ssi_private;
+ 	int ret = 0;
+diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c
+index 524ce6210cee..251f4d981e0c 100644
+--- a/sound/soc/fsl/imx-audmux.c
++++ b/sound/soc/fsl/imx-audmux.c
+@@ -162,7 +162,7 @@ static void __init audmux_debugfs_init(void)
+ 	}
+ }
+ 
+-static void __devexit audmux_debugfs_remove(void)
++static void audmux_debugfs_remove(void)
+ {
+ 	debugfs_remove_recursive(audmux_debugfs_root);
+ }
+@@ -244,7 +244,7 @@ int imx_audmux_v2_configure_port(unsigned int port, unsigned int ptcr,
+ }
+ EXPORT_SYMBOL_GPL(imx_audmux_v2_configure_port);
+ 
+-static int __devinit imx_audmux_probe(struct platform_device *pdev)
++static int imx_audmux_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res;
+ 	struct pinctrl *pinctrl;
+@@ -278,7 +278,7 @@ static int __devinit imx_audmux_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit imx_audmux_remove(struct platform_device *pdev)
++static int imx_audmux_remove(struct platform_device *pdev)
+ {
+ 	if (audmux_type == IMX31_AUDMUX)
+ 		audmux_debugfs_remove();
+@@ -289,7 +289,7 @@ static int __devexit imx_audmux_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver imx_audmux_driver = {
+ 	.probe		= imx_audmux_probe,
+-	.remove		= __devexit_p(imx_audmux_remove),
++	.remove		= imx_audmux_remove,
+ 	.id_table	= imx_audmux_ids,
+ 	.driver	= {
+ 		.name	= DRIVER_NAME,
+diff --git a/sound/soc/fsl/imx-mc13783.c b/sound/soc/fsl/imx-mc13783.c
+index 549b31fdc9dd..4ae30f21fdb5 100644
+--- a/sound/soc/fsl/imx-mc13783.c
++++ b/sound/soc/fsl/imx-mc13783.c
+@@ -98,7 +98,7 @@ static struct snd_soc_card imx_mc13783 = {
+ 	.num_dapm_routes = ARRAY_SIZE(imx_mc13783_routes),
+ };
+ 
+-static int __devinit imx_mc13783_probe(struct platform_device *pdev)
++static int imx_mc13783_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 
+@@ -148,7 +148,7 @@ static int __devinit imx_mc13783_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit imx_mc13783_remove(struct platform_device *pdev)
++static int imx_mc13783_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_card(&imx_mc13783);
+ 
+@@ -161,7 +161,7 @@ static struct platform_driver imx_mc13783_audio_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = imx_mc13783_probe,
+-	.remove = __devexit_p(imx_mc13783_remove)
++	.remove = imx_mc13783_remove
+ };
+ 
+ module_platform_driver(imx_mc13783_audio_driver);
+diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c
+index d85929b79c35..bf363d8d044a 100644
+--- a/sound/soc/fsl/imx-pcm-dma.c
++++ b/sound/soc/fsl/imx-pcm-dma.c
+@@ -154,12 +154,12 @@ static struct snd_soc_platform_driver imx_soc_platform_mx2 = {
+ 	.pcm_free	= imx_pcm_free,
+ };
+ 
+-static int __devinit imx_soc_platform_probe(struct platform_device *pdev)
++static int imx_soc_platform_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_platform(&pdev->dev, &imx_soc_platform_mx2);
+ }
+ 
+-static int __devexit imx_soc_platform_remove(struct platform_device *pdev)
++static int imx_soc_platform_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_platform(&pdev->dev);
+ 	return 0;
+@@ -171,7 +171,7 @@ static struct platform_driver imx_pcm_driver = {
+ 			.owner = THIS_MODULE,
+ 	},
+ 	.probe = imx_soc_platform_probe,
+-	.remove = __devexit_p(imx_soc_platform_remove),
++	.remove = imx_soc_platform_remove,
+ };
+ 
+ module_platform_driver(imx_pcm_driver);
+diff --git a/sound/soc/fsl/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c
+index 22c6130957ba..713bd79428a9 100644
+--- a/sound/soc/fsl/imx-pcm-fiq.c
++++ b/sound/soc/fsl/imx-pcm-fiq.c
+@@ -282,7 +282,7 @@ static struct snd_soc_platform_driver imx_soc_platform_fiq = {
+ 	.pcm_free	= imx_pcm_fiq_free,
+ };
+ 
+-static int __devinit imx_soc_platform_probe(struct platform_device *pdev)
++static int imx_soc_platform_probe(struct platform_device *pdev)
+ {
+ 	struct imx_ssi *ssi = platform_get_drvdata(pdev);
+ 	int ret;
+@@ -316,7 +316,7 @@ static int __devinit imx_soc_platform_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit imx_soc_platform_remove(struct platform_device *pdev)
++static int imx_soc_platform_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_platform(&pdev->dev);
+ 	return 0;
+@@ -329,7 +329,7 @@ static struct platform_driver imx_pcm_driver = {
+ 	},
+ 
+ 	.probe = imx_soc_platform_probe,
+-	.remove = __devexit_p(imx_soc_platform_remove),
++	.remove = imx_soc_platform_remove,
+ };
+ 
+ module_platform_driver(imx_pcm_driver);
+diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c
+index 3d9b1c427ce9..424347e9b2d7 100644
+--- a/sound/soc/fsl/imx-sgtl5000.c
++++ b/sound/soc/fsl/imx-sgtl5000.c
+@@ -56,7 +56,7 @@ static const struct snd_soc_dapm_widget imx_sgtl5000_dapm_widgets[] = {
+ 	SND_SOC_DAPM_SPK("Ext Spk", NULL),
+ };
+ 
+-static int __devinit imx_sgtl5000_probe(struct platform_device *pdev)
++static int imx_sgtl5000_probe(struct platform_device *pdev)
+ {
+ 	struct device_node *np = pdev->dev.of_node;
+ 	struct device_node *ssi_np, *codec_np;
+@@ -185,7 +185,7 @@ static int __devinit imx_sgtl5000_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit imx_sgtl5000_remove(struct platform_device *pdev)
++static int imx_sgtl5000_remove(struct platform_device *pdev)
+ {
+ 	struct imx_sgtl5000_data *data = platform_get_drvdata(pdev);
+ 
+@@ -211,7 +211,7 @@ static struct platform_driver imx_sgtl5000_driver = {
+ 		.of_match_table = imx_sgtl5000_dt_ids,
+ 	},
+ 	.probe = imx_sgtl5000_probe,
+-	.remove = __devexit_p(imx_sgtl5000_remove),
++	.remove = imx_sgtl5000_remove,
+ };
+ module_platform_driver(imx_sgtl5000_driver);
+ 
+diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c
+index 006f7d465ed2..2c8d89eecdcf 100644
+--- a/sound/soc/fsl/imx-ssi.c
++++ b/sound/soc/fsl/imx-ssi.c
+@@ -639,7 +639,7 @@ static int imx_ssi_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit imx_ssi_remove(struct platform_device *pdev)
++static int imx_ssi_remove(struct platform_device *pdev)
+ {
+ 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ 	struct imx_ssi *ssi = platform_get_drvdata(pdev);
+@@ -660,7 +660,7 @@ static int __devexit imx_ssi_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver imx_ssi_driver = {
+ 	.probe = imx_ssi_probe,
+-	.remove = __devexit_p(imx_ssi_remove),
++	.remove = imx_ssi_remove,
+ 
+ 	.driver = {
+ 		.name = "imx-ssi",
+diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c
+index a313c0ae36db..a4aec0488dd3 100644
+--- a/sound/soc/fsl/mpc5200_psc_ac97.c
++++ b/sound/soc/fsl/mpc5200_psc_ac97.c
+@@ -277,7 +277,7 @@ static struct snd_soc_dai_driver psc_ac97_dai[] = {
+  * - Probe/remove operations
+  * - OF device match table
+  */
+-static int __devinit psc_ac97_of_probe(struct platform_device *op)
++static int psc_ac97_of_probe(struct platform_device *op)
+ {
+ 	int rc;
+ 	struct snd_ac97 ac97;
+@@ -310,7 +310,7 @@ static int __devinit psc_ac97_of_probe(struct platform_device *op)
+ 	return 0;
+ }
+ 
+-static int __devexit psc_ac97_of_remove(struct platform_device *op)
++static int psc_ac97_of_remove(struct platform_device *op)
+ {
+ 	mpc5200_audio_dma_destroy(op);
+ 	snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_ac97_dai));
+@@ -318,7 +318,7 @@ static int __devexit psc_ac97_of_remove(struct platform_device *op)
+ }
+ 
+ /* Match table for of_platform binding */
+-static struct of_device_id psc_ac97_match[] __devinitdata = {
++static struct of_device_id psc_ac97_match[] = {
+ 	{ .compatible = "fsl,mpc5200-psc-ac97", },
+ 	{ .compatible = "fsl,mpc5200b-psc-ac97", },
+ 	{}
+@@ -327,7 +327,7 @@ MODULE_DEVICE_TABLE(of, psc_ac97_match);
+ 
+ static struct platform_driver psc_ac97_driver = {
+ 	.probe = psc_ac97_of_probe,
+-	.remove = __devexit_p(psc_ac97_of_remove),
++	.remove = psc_ac97_of_remove,
+ 	.driver = {
+ 		.name = "mpc5200-psc-ac97",
+ 		.owner = THIS_MODULE,
+diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c
+index ba1f0a66358f..b95b966f25a0 100644
+--- a/sound/soc/fsl/mpc5200_psc_i2s.c
++++ b/sound/soc/fsl/mpc5200_psc_i2s.c
+@@ -153,7 +153,7 @@ static struct snd_soc_dai_driver psc_i2s_dai[] = {{
+  * - Probe/remove operations
+  * - OF device match table
+  */
+-static int __devinit psc_i2s_of_probe(struct platform_device *op)
++static int psc_i2s_of_probe(struct platform_device *op)
+ {
+ 	int rc;
+ 	struct psc_dma *psc_dma;
+@@ -205,7 +205,7 @@ static int __devinit psc_i2s_of_probe(struct platform_device *op)
+ 
+ }
+ 
+-static int __devexit psc_i2s_of_remove(struct platform_device *op)
++static int psc_i2s_of_remove(struct platform_device *op)
+ {
+ 	mpc5200_audio_dma_destroy(op);
+ 	snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_i2s_dai));
+@@ -213,7 +213,7 @@ static int __devexit psc_i2s_of_remove(struct platform_device *op)
+ }
+ 
+ /* Match table for of_platform binding */
+-static struct of_device_id psc_i2s_match[] __devinitdata = {
++static struct of_device_id psc_i2s_match[] = {
+ 	{ .compatible = "fsl,mpc5200-psc-i2s", },
+ 	{ .compatible = "fsl,mpc5200b-psc-i2s", },
+ 	{}
+@@ -222,7 +222,7 @@ MODULE_DEVICE_TABLE(of, psc_i2s_match);
+ 
+ static struct platform_driver psc_i2s_driver = {
+ 	.probe = psc_i2s_of_probe,
+-	.remove = __devexit_p(psc_i2s_of_remove),
++	.remove = psc_i2s_of_remove,
+ 	.driver = {
+ 		.name = "mpc5200-psc-i2s",
+ 		.owner = THIS_MODULE,
+diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
+index 9ff9318c52b9..228c52e71440 100644
+--- a/sound/soc/fsl/mpc8610_hpcd.c
++++ b/sound/soc/fsl/mpc8610_hpcd.c
+@@ -368,7 +368,7 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev)
+  *
+  * This function is called when the platform device is removed.
+  */
+-static int __devexit mpc8610_hpcd_remove(struct platform_device *pdev)
++static int mpc8610_hpcd_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 	struct mpc8610_hpcd_data *machine_data =
+@@ -382,7 +382,7 @@ static int __devexit mpc8610_hpcd_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver mpc8610_hpcd_driver = {
+ 	.probe = mpc8610_hpcd_probe,
+-	.remove = __devexit_p(mpc8610_hpcd_remove),
++	.remove = mpc8610_hpcd_remove,
+ 	.driver = {
+ 		/* The name must match 'compatible' property in the device tree,
+ 		 * in lowercase letters.
+diff --git a/sound/soc/fsl/mx27vis-aic32x4.c b/sound/soc/fsl/mx27vis-aic32x4.c
+index 2b76877b1789..3d1074179057 100644
+--- a/sound/soc/fsl/mx27vis-aic32x4.c
++++ b/sound/soc/fsl/mx27vis-aic32x4.c
+@@ -180,7 +180,7 @@ static struct snd_soc_card mx27vis_aic32x4 = {
+ 	.num_dapm_routes = ARRAY_SIZE(aic32x4_dapm_routes),
+ };
+ 
+-static int __devinit mx27vis_aic32x4_probe(struct platform_device *pdev)
++static int mx27vis_aic32x4_probe(struct platform_device *pdev)
+ {
+ 	struct snd_mx27vis_platform_data *pdata = pdev->dev.platform_data;
+ 	int ret;
+@@ -219,7 +219,7 @@ static int __devinit mx27vis_aic32x4_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit mx27vis_aic32x4_remove(struct platform_device *pdev)
++static int mx27vis_aic32x4_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_card(&mx27vis_aic32x4);
+ 
+@@ -232,7 +232,7 @@ static struct platform_driver mx27vis_aic32x4_audio_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = mx27vis_aic32x4_probe,
+-	.remove = __devexit_p(mx27vis_aic32x4_remove),
++	.remove = mx27vis_aic32x4_remove,
+ };
+ 
+ module_platform_driver(mx27vis_aic32x4_audio_driver);
+diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c
+index 144d49603637..ba59c23a137b 100644
+--- a/sound/soc/fsl/p1022_ds.c
++++ b/sound/soc/fsl/p1022_ds.c
+@@ -376,7 +376,7 @@ static int p1022_ds_probe(struct platform_device *pdev)
+  *
+  * This function is called when the platform device is removed.
+  */
+-static int __devexit p1022_ds_remove(struct platform_device *pdev)
++static int p1022_ds_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 	struct machine_data *mdata =
+@@ -390,7 +390,7 @@ static int __devexit p1022_ds_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver p1022_ds_driver = {
+ 	.probe = p1022_ds_probe,
+-	.remove = __devexit_p(p1022_ds_remove),
++	.remove = p1022_ds_remove,
+ 	.driver = {
+ 		/*
+ 		 * The name must match 'compatible' property in the device tree,
+diff --git a/sound/soc/fsl/p1022_rdk.c b/sound/soc/fsl/p1022_rdk.c
+index 897e32ffdc42..f21551911533 100644
+--- a/sound/soc/fsl/p1022_rdk.c
++++ b/sound/soc/fsl/p1022_rdk.c
+@@ -326,7 +326,7 @@ static int p1022_rdk_probe(struct platform_device *pdev)
+  *
+  * This function is called when the platform device is removed.
+  */
+-static int __devexit p1022_rdk_remove(struct platform_device *pdev)
++static int p1022_rdk_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 	struct machine_data *mdata =
+@@ -340,7 +340,7 @@ static int __devexit p1022_rdk_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver p1022_rdk_driver = {
+ 	.probe = p1022_rdk_probe,
+-	.remove = __devexit_p(p1022_rdk_remove),
++	.remove = p1022_rdk_remove,
+ 	.driver = {
+ 		/*
+ 		 * The name must match 'compatible' property in the device tree,
+diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c
+index 4d261927662f..8e52c1485df3 100644
+--- a/sound/soc/fsl/pcm030-audio-fabric.c
++++ b/sound/soc/fsl/pcm030-audio-fabric.c
+@@ -101,7 +101,7 @@ static int __init pcm030_fabric_probe(struct platform_device *op)
+ 	return ret;
+ }
+ 
+-static int __devexit pcm030_fabric_remove(struct platform_device *op)
++static int pcm030_fabric_remove(struct platform_device *op)
+ {
+ 	struct pcm030_audio_data *pdata = platform_get_drvdata(op);
+ 	int ret;
+@@ -120,7 +120,7 @@ MODULE_DEVICE_TABLE(of, pcm030_audio_match);
+ 
+ static struct platform_driver pcm030_fabric_driver = {
+ 	.probe		= pcm030_fabric_probe,
+-	.remove		= __devexit_p(pcm030_fabric_remove),
++	.remove		= pcm030_fabric_remove,
+ 	.driver		= {
+ 		.name	= DRV_NAME,
+ 		.owner	= THIS_MODULE,

commit fdca21ad4603200ac39268be3a2b93907a6b85e4
+Author: Bill Pemberton 
+Date:   Fri Dec 7 09:26:15 2012 -0500
+
+    ASoC: Samsung: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c
+index cd6c7073c50d..0df3c5644cfa 100644
+--- a/sound/soc/samsung/ac97.c
++++ b/sound/soc/samsung/ac97.c
+@@ -370,7 +370,7 @@ static struct snd_soc_dai_driver s3c_ac97_dai[] = {
+ 	},
+ };
+ 
+-static __devinit int s3c_ac97_probe(struct platform_device *pdev)
++static int s3c_ac97_probe(struct platform_device *pdev)
+ {
+ 	struct resource *mem_res, *dmatx_res, *dmarx_res, *dmamic_res, *irq_res;
+ 	struct s3c_audio_pdata *ac97_pdata;
+@@ -485,7 +485,7 @@ static __devinit int s3c_ac97_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static __devexit int s3c_ac97_remove(struct platform_device *pdev)
++static int s3c_ac97_remove(struct platform_device *pdev)
+ {
+ 	struct resource *mem_res, *irq_res;
+ 
+@@ -510,7 +510,7 @@ static __devexit int s3c_ac97_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver s3c_ac97_driver = {
+ 	.probe  = s3c_ac97_probe,
+-	.remove = __devexit_p(s3c_ac97_remove),
++	.remove = s3c_ac97_remove,
+ 	.driver = {
+ 		.name = "samsung-ac97",
+ 		.owner = THIS_MODULE,
+diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c
+index 01c1c5a2d321..ceed466af9ff 100644
+--- a/sound/soc/samsung/bells.c
++++ b/sound/soc/samsung/bells.c
+@@ -412,7 +412,7 @@ static struct snd_soc_card bells_cards[] = {
+ };
+ 
+ 
+-static __devinit int bells_probe(struct platform_device *pdev)
++static int bells_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 
+@@ -429,7 +429,7 @@ static __devinit int bells_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit bells_remove(struct platform_device *pdev)
++static int bells_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_card(&bells_cards[pdev->id]);
+ 
+@@ -443,7 +443,7 @@ static struct platform_driver bells_driver = {
+ 		.pm = &snd_soc_pm_ops,
+ 	},
+ 	.probe = bells_probe,
+-	.remove = __devexit_p(bells_remove),
++	.remove = bells_remove,
+ };
+ 
+ module_platform_driver(bells_driver);
+diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
+index 64529904a95f..db87628d7630 100644
+--- a/sound/soc/samsung/dma.c
++++ b/sound/soc/samsung/dma.c
+@@ -432,13 +432,13 @@ static struct snd_soc_platform_driver samsung_asoc_platform = {
+ 	.pcm_free	= dma_free_dma_buffers,
+ };
+ 
+-int __devinit asoc_dma_platform_register(struct device *dev)
++int asoc_dma_platform_register(struct device *dev)
+ {
+ 	return snd_soc_register_platform(dev, &samsung_asoc_platform);
+ }
+ EXPORT_SYMBOL_GPL(asoc_dma_platform_register);
+ 
+-void __devexit asoc_dma_platform_unregister(struct device *dev)
++void asoc_dma_platform_unregister(struct device *dev)
+ {
+ 	snd_soc_unregister_platform(dev);
+ }
+diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
+index 0aa0451823ce..d2d124f1dd1b 100644
+--- a/sound/soc/samsung/i2s.c
++++ b/sound/soc/samsung/i2s.c
+@@ -952,8 +952,7 @@ static const struct snd_soc_dai_ops samsung_i2s_dai_ops = {
+ 					SNDRV_PCM_FMTBIT_S16_LE | \
+ 					SNDRV_PCM_FMTBIT_S24_LE)
+ 
+-static __devinit
+-struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
++static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
+ {
+ 	struct i2s_dai *i2s;
+ 
+@@ -994,7 +993,7 @@ struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
+ 	return i2s;
+ }
+ 
+-static __devinit int samsung_i2s_probe(struct platform_device *pdev)
++static int samsung_i2s_probe(struct platform_device *pdev)
+ {
+ 	u32 dma_pl_chan, dma_cp_chan, dma_pl_sec_chan;
+ 	struct i2s_dai *pri_dai, *sec_dai = NULL;
+@@ -1117,7 +1116,7 @@ static __devinit int samsung_i2s_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static __devexit int samsung_i2s_remove(struct platform_device *pdev)
++static int samsung_i2s_remove(struct platform_device *pdev)
+ {
+ 	struct i2s_dai *i2s, *other;
+ 	struct resource *res;
+@@ -1146,7 +1145,7 @@ static __devexit int samsung_i2s_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver samsung_i2s_driver = {
+ 	.probe  = samsung_i2s_probe,
+-	.remove = __devexit_p(samsung_i2s_remove),
++	.remove = samsung_i2s_remove,
+ 	.driver = {
+ 		.name = "samsung-i2s",
+ 		.owner = THIS_MODULE,
+diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c
+index c227c3163cae..a07950b0c8ce 100644
+--- a/sound/soc/samsung/idma.c
++++ b/sound/soc/samsung/idma.c
+@@ -416,12 +416,12 @@ static struct snd_soc_platform_driver asoc_idma_platform = {
+ 	.pcm_free = idma_free,
+ };
+ 
+-static int __devinit asoc_idma_platform_probe(struct platform_device *pdev)
++static int asoc_idma_platform_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_platform(&pdev->dev, &asoc_idma_platform);
+ }
+ 
+-static int __devexit asoc_idma_platform_remove(struct platform_device *pdev)
++static int asoc_idma_platform_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_platform(&pdev->dev);
+ 	return 0;
+@@ -434,7 +434,7 @@ static struct platform_driver asoc_idma_driver = {
+ 	},
+ 
+ 	.probe = asoc_idma_platform_probe,
+-	.remove = __devexit_p(asoc_idma_platform_remove),
++	.remove = asoc_idma_platform_remove,
+ };
+ 
+ module_platform_driver(asoc_idma_driver);
+diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c
+index de4cfdf5fdfc..bfb91f34a22a 100644
+--- a/sound/soc/samsung/littlemill.c
++++ b/sound/soc/samsung/littlemill.c
+@@ -297,7 +297,7 @@ static struct snd_soc_card littlemill = {
+ 	.late_probe = littlemill_late_probe,
+ };
+ 
+-static __devinit int littlemill_probe(struct platform_device *pdev)
++static int littlemill_probe(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = &littlemill;
+ 	int ret;
+@@ -314,7 +314,7 @@ static __devinit int littlemill_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit littlemill_remove(struct platform_device *pdev)
++static int littlemill_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -330,7 +330,7 @@ static struct platform_driver littlemill_driver = {
+ 		.pm = &snd_soc_pm_ops,
+ 	},
+ 	.probe = littlemill_probe,
+-	.remove = __devexit_p(littlemill_remove),
++	.remove = littlemill_remove,
+ };
+ 
+ module_platform_driver(littlemill_driver);
+diff --git a/sound/soc/samsung/lowland.c b/sound/soc/samsung/lowland.c
+index a71c31af4e0e..570cf5229508 100644
+--- a/sound/soc/samsung/lowland.c
++++ b/sound/soc/samsung/lowland.c
+@@ -180,7 +180,7 @@ static struct snd_soc_card lowland = {
+ 	.num_dapm_routes = ARRAY_SIZE(audio_paths),
+ };
+ 
+-static __devinit int lowland_probe(struct platform_device *pdev)
++static int lowland_probe(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = &lowland;
+ 	int ret;
+@@ -197,7 +197,7 @@ static __devinit int lowland_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit lowland_remove(struct platform_device *pdev)
++static int lowland_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -213,7 +213,7 @@ static struct platform_driver lowland_driver = {
+ 		.pm = &snd_soc_pm_ops,
+ 	},
+ 	.probe = lowland_probe,
+-	.remove = __devexit_p(lowland_remove),
++	.remove = lowland_remove,
+ };
+ 
+ module_platform_driver(lowland_driver);
+diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c
+index ecd509048771..13bab79ad93d 100644
+--- a/sound/soc/samsung/pcm.c
++++ b/sound/soc/samsung/pcm.c
+@@ -490,7 +490,7 @@ static struct snd_soc_dai_driver s3c_pcm_dai[] = {
+ 	},
+ };
+ 
+-static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
++static int s3c_pcm_dev_probe(struct platform_device *pdev)
+ {
+ 	struct s3c_pcm_info *pcm;
+ 	struct resource *mem_res, *dmatx_res, *dmarx_res;
+@@ -613,7 +613,7 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static __devexit int s3c_pcm_dev_remove(struct platform_device *pdev)
++static int s3c_pcm_dev_remove(struct platform_device *pdev)
+ {
+ 	struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id];
+ 	struct resource *mem_res;
+@@ -638,7 +638,7 @@ static __devexit int s3c_pcm_dev_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver s3c_pcm_driver = {
+ 	.probe  = s3c_pcm_dev_probe,
+-	.remove = __devexit_p(s3c_pcm_dev_remove),
++	.remove = s3c_pcm_dev_remove,
+ 	.driver = {
+ 		.name = "samsung-pcm",
+ 		.owner = THIS_MODULE,
+diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c
+index edf5f527c5a2..221337716393 100644
+--- a/sound/soc/samsung/s3c2412-i2s.c
++++ b/sound/soc/samsung/s3c2412-i2s.c
+@@ -160,7 +160,7 @@ static struct snd_soc_dai_driver s3c2412_i2s_dai = {
+ 	.ops = &s3c2412_i2s_dai_ops,
+ };
+ 
+-static __devinit int s3c2412_iis_dev_probe(struct platform_device *pdev)
++static int s3c2412_iis_dev_probe(struct platform_device *pdev)
+ {
+ 	int ret = 0;
+ 
+@@ -182,7 +182,7 @@ static __devinit int s3c2412_iis_dev_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static __devexit int s3c2412_iis_dev_remove(struct platform_device *pdev)
++static int s3c2412_iis_dev_remove(struct platform_device *pdev)
+ {
+ 	asoc_dma_platform_unregister(&pdev->dev);
+ 	snd_soc_unregister_dai(&pdev->dev);
+@@ -191,7 +191,7 @@ static __devexit int s3c2412_iis_dev_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver s3c2412_iis_driver = {
+ 	.probe  = s3c2412_iis_dev_probe,
+-	.remove = __devexit_p(s3c2412_iis_dev_remove),
++	.remove = s3c2412_iis_dev_remove,
+ 	.driver = {
+ 		.name = "s3c2412-iis",
+ 		.owner = THIS_MODULE,
+diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c
+index 0022d51fd160..ee10e8704e97 100644
+--- a/sound/soc/samsung/s3c24xx-i2s.c
++++ b/sound/soc/samsung/s3c24xx-i2s.c
+@@ -465,7 +465,7 @@ static struct snd_soc_dai_driver s3c24xx_i2s_dai = {
+ 	.ops = &s3c24xx_i2s_dai_ops,
+ };
+ 
+-static __devinit int s3c24xx_iis_dev_probe(struct platform_device *pdev)
++static int s3c24xx_iis_dev_probe(struct platform_device *pdev)
+ {
+ 	int ret = 0;
+ 
+@@ -487,7 +487,7 @@ static __devinit int s3c24xx_iis_dev_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static __devexit int s3c24xx_iis_dev_remove(struct platform_device *pdev)
++static int s3c24xx_iis_dev_remove(struct platform_device *pdev)
+ {
+ 	asoc_dma_platform_unregister(&pdev->dev);
+ 	snd_soc_unregister_dai(&pdev->dev);
+@@ -496,7 +496,7 @@ static __devexit int s3c24xx_iis_dev_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver s3c24xx_iis_driver = {
+ 	.probe  = s3c24xx_iis_dev_probe,
+-	.remove = __devexit_p(s3c24xx_iis_dev_remove),
++	.remove = s3c24xx_iis_dev_remove,
+ 	.driver = {
+ 		.name = "s3c24xx-iis",
+ 		.owner = THIS_MODULE,
+diff --git a/sound/soc/samsung/s3c24xx_simtec.c b/sound/soc/samsung/s3c24xx_simtec.c
+index 335a7d8a4a8d..2c015f62ead6 100644
+--- a/sound/soc/samsung/s3c24xx_simtec.c
++++ b/sound/soc/samsung/s3c24xx_simtec.c
+@@ -313,8 +313,8 @@ const struct dev_pm_ops simtec_audio_pmops = {
+ EXPORT_SYMBOL_GPL(simtec_audio_pmops);
+ #endif
+ 
+-int __devinit simtec_audio_core_probe(struct platform_device *pdev,
+-				      struct snd_soc_card *card)
++int simtec_audio_core_probe(struct platform_device *pdev,
++			    struct snd_soc_card *card)
+ {
+ 	struct platform_device *snd_dev;
+ 	int ret;
+@@ -371,7 +371,7 @@ int __devinit simtec_audio_core_probe(struct platform_device *pdev,
+ }
+ EXPORT_SYMBOL_GPL(simtec_audio_core_probe);
+ 
+-int __devexit simtec_audio_remove(struct platform_device *pdev)
++int simtec_audio_remove(struct platform_device *pdev)
+ {
+ 	struct platform_device *snd_dev = platform_get_drvdata(pdev);
+ 
+diff --git a/sound/soc/samsung/s3c24xx_simtec_hermes.c b/sound/soc/samsung/s3c24xx_simtec_hermes.c
+index befabe8979f7..d8a0543cae5e 100644
+--- a/sound/soc/samsung/s3c24xx_simtec_hermes.c
++++ b/sound/soc/samsung/s3c24xx_simtec_hermes.c
+@@ -99,7 +99,7 @@ static struct snd_soc_card snd_soc_machine_simtec_aic33 = {
+ 	.num_dapm_routes = ARRAY_SIZE(base_map),
+ };
+ 
+-static int __devinit simtec_audio_hermes_probe(struct platform_device *pd)
++static int simtec_audio_hermes_probe(struct platform_device *pd)
+ {
+ 	dev_info(&pd->dev, "probing....\n");
+ 	return simtec_audio_core_probe(pd, &snd_soc_machine_simtec_aic33);
+@@ -112,7 +112,7 @@ static struct platform_driver simtec_audio_hermes_platdrv = {
+ 		.pm	= simtec_audio_pm,
+ 	},
+ 	.probe	= simtec_audio_hermes_probe,
+-	.remove	= __devexit_p(simtec_audio_remove),
++	.remove	= simtec_audio_remove,
+ };
+ 
+ module_platform_driver(simtec_audio_hermes_platdrv);
+diff --git a/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c b/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
+index 5552f82c92a7..1ac0d7a63a3a 100644
+--- a/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
++++ b/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
+@@ -88,7 +88,7 @@ static struct snd_soc_card snd_soc_machine_simtec_aic23 = {
+ 	.num_dapm_routes = ARRAY_SIZE(base_map),
+ };
+ 
+-static int __devinit simtec_audio_tlv320aic23_probe(struct platform_device *pd)
++static int simtec_audio_tlv320aic23_probe(struct platform_device *pd)
+ {
+ 	return simtec_audio_core_probe(pd, &snd_soc_machine_simtec_aic23);
+ }
+@@ -100,7 +100,7 @@ static struct platform_driver simtec_audio_tlv320aic23_driver = {
+ 		.pm	= simtec_audio_pm,
+ 	},
+ 	.probe	= simtec_audio_tlv320aic23_probe,
+-	.remove	= __devexit_p(simtec_audio_remove),
++	.remove	= simtec_audio_remove,
+ };
+ 
+ module_platform_driver(simtec_audio_tlv320aic23_driver);
+diff --git a/sound/soc/samsung/smdk_wm8580pcm.c b/sound/soc/samsung/smdk_wm8580pcm.c
+index 34239fe9afde..e43bd4294f99 100644
+--- a/sound/soc/samsung/smdk_wm8580pcm.c
++++ b/sound/soc/samsung/smdk_wm8580pcm.c
+@@ -153,7 +153,7 @@ static struct snd_soc_card smdk_pcm = {
+  * is absent (or not connected), so we connect EXT_VOICE_CLK(OSC4),
+  * 2.0484Mhz, directly with MCLK both Codec and SoC.
+  */
+-static int __devinit snd_smdk_probe(struct platform_device *pdev)
++static int snd_smdk_probe(struct platform_device *pdev)
+ {
+ 	int ret = 0;
+ 
+@@ -173,7 +173,7 @@ static int __devinit snd_smdk_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit snd_smdk_remove(struct platform_device *pdev)
++static int snd_smdk_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_card(&smdk_pcm);
+ 	platform_set_drvdata(pdev, NULL);
+@@ -186,7 +186,7 @@ static struct platform_driver snd_smdk_driver = {
+ 		.name = "samsung-smdk-pcm",
+ 	},
+ 	.probe = snd_smdk_probe,
+-	.remove = __devexit_p(snd_smdk_remove),
++	.remove = snd_smdk_remove,
+ };
+ 
+ module_platform_driver(snd_smdk_driver);
+diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c
+index dd0aa8cb1a9e..b0d0ab8bff5a 100644
+--- a/sound/soc/samsung/smdk_wm8994.c
++++ b/sound/soc/samsung/smdk_wm8994.c
+@@ -150,7 +150,7 @@ static struct snd_soc_card smdk = {
+ };
+ 
+ 
+-static int __devinit smdk_audio_probe(struct platform_device *pdev)
++static int smdk_audio_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 	struct snd_soc_card *card = &smdk;
+@@ -164,7 +164,7 @@ static int __devinit smdk_audio_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit smdk_audio_remove(struct platform_device *pdev)
++static int smdk_audio_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -179,7 +179,7 @@ static struct platform_driver smdk_audio_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= smdk_audio_probe,
+-	.remove		= __devexit_p(smdk_audio_remove),
++	.remove		= smdk_audio_remove,
+ };
+ 
+ module_platform_driver(smdk_audio_driver);
+diff --git a/sound/soc/samsung/smdk_wm8994pcm.c b/sound/soc/samsung/smdk_wm8994pcm.c
+index 15f6b44e9de3..3688a32000a2 100644
+--- a/sound/soc/samsung/smdk_wm8994pcm.c
++++ b/sound/soc/samsung/smdk_wm8994pcm.c
+@@ -129,7 +129,7 @@ static struct snd_soc_card smdk_pcm = {
+ 	.num_links = 1,
+ };
+ 
+-static int __devinit snd_smdk_probe(struct platform_device *pdev)
++static int snd_smdk_probe(struct platform_device *pdev)
+ {
+ 	int ret = 0;
+ 
+@@ -143,7 +143,7 @@ static int __devinit snd_smdk_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit snd_smdk_remove(struct platform_device *pdev)
++static int snd_smdk_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_card(&smdk_pcm);
+ 	platform_set_drvdata(pdev, NULL);
+@@ -156,7 +156,7 @@ static struct platform_driver snd_smdk_driver = {
+ 		.name = "samsung-smdk-pcm",
+ 	},
+ 	.probe = snd_smdk_probe,
+-	.remove = __devexit_p(snd_smdk_remove),
++	.remove = snd_smdk_remove,
+ };
+ 
+ module_platform_driver(snd_smdk_driver);
+diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c
+index 8606fc6cb37d..5008e5bd6ed8 100644
+--- a/sound/soc/samsung/spdif.c
++++ b/sound/soc/samsung/spdif.c
+@@ -357,7 +357,7 @@ static struct snd_soc_dai_driver samsung_spdif_dai = {
+ 	.resume = spdif_resume,
+ };
+ 
+-static __devinit int spdif_probe(struct platform_device *pdev)
++static int spdif_probe(struct platform_device *pdev)
+ {
+ 	struct s3c_audio_pdata *spdif_pdata;
+ 	struct resource *mem_res, *dma_res;
+@@ -460,7 +460,7 @@ static __devinit int spdif_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static __devexit int spdif_remove(struct platform_device *pdev)
++static int spdif_remove(struct platform_device *pdev)
+ {
+ 	struct samsung_spdif_info *spdif = &spdif_info;
+ 	struct resource *mem_res;
+@@ -484,7 +484,7 @@ static __devexit int spdif_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver samsung_spdif_driver = {
+ 	.probe	= spdif_probe,
+-	.remove	= __devexit_p(spdif_remove),
++	.remove	= spdif_remove,
+ 	.driver	= {
+ 		.name	= "samsung-spdif",
+ 		.owner	= THIS_MODULE,
+diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c
+index d7906a144195..57df90d6b7c1 100644
+--- a/sound/soc/samsung/speyside.c
++++ b/sound/soc/samsung/speyside.c
+@@ -320,7 +320,7 @@ static struct snd_soc_card speyside = {
+ 	.late_probe = speyside_late_probe,
+ };
+ 
+-static __devinit int speyside_probe(struct platform_device *pdev)
++static int speyside_probe(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = &speyside;
+ 	int ret;
+@@ -337,7 +337,7 @@ static __devinit int speyside_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit speyside_remove(struct platform_device *pdev)
++static int speyside_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -353,7 +353,7 @@ static struct platform_driver speyside_driver = {
+ 		.pm = &snd_soc_pm_ops,
+ 	},
+ 	.probe = speyside_probe,
+-	.remove = __devexit_p(speyside_remove),
++	.remove = speyside_remove,
+ };
+ 
+ module_platform_driver(speyside_driver);
+diff --git a/sound/soc/samsung/tobermory.c b/sound/soc/samsung/tobermory.c
+index 42e4c8e6b03e..f21ff608a819 100644
+--- a/sound/soc/samsung/tobermory.c
++++ b/sound/soc/samsung/tobermory.c
+@@ -214,7 +214,7 @@ static struct snd_soc_card tobermory = {
+ 	.late_probe = tobermory_late_probe,
+ };
+ 
+-static __devinit int tobermory_probe(struct platform_device *pdev)
++static int tobermory_probe(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = &tobermory;
+ 	int ret;
+@@ -231,7 +231,7 @@ static __devinit int tobermory_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit tobermory_remove(struct platform_device *pdev)
++static int tobermory_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -247,7 +247,7 @@ static struct platform_driver tobermory_driver = {
+ 		.pm = &snd_soc_pm_ops,
+ 	},
+ 	.probe = tobermory_probe,
+-	.remove = __devexit_p(tobermory_remove),
++	.remove = tobermory_remove,
+ };
+ 
+ module_platform_driver(tobermory_driver);

commit d7f1be84fb6f622e390d3ea392382aa9a541c087
+Author: Bill Pemberton 
+Date:   Fri Dec 7 09:26:14 2012 -0500
+
+    ASoC: pxa/hx4700: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/pxa/hx4700.c b/sound/soc/pxa/hx4700.c
+index 2a342c92d829..dcc9b04bd92c 100644
+--- a/sound/soc/pxa/hx4700.c
++++ b/sound/soc/pxa/hx4700.c
+@@ -183,7 +183,7 @@ static struct gpio hx4700_audio_gpios[] = {
+ 	{ GPIO92_HX4700_HP_DRIVER, GPIOF_OUT_INIT_LOW, "EP_POWER" },
+ };
+ 
+-static int __devinit hx4700_audio_probe(struct platform_device *pdev)
++static int hx4700_audio_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 
+@@ -204,7 +204,7 @@ static int __devinit hx4700_audio_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit hx4700_audio_remove(struct platform_device *pdev)
++static int hx4700_audio_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_jack_free_gpios(&hs_jack, 1, &hs_jack_gpio);
+ 	snd_soc_unregister_card(&snd_soc_card_hx4700);
+@@ -223,7 +223,7 @@ static struct platform_driver hx4700_audio_driver = {
+ 		.pm = &snd_soc_pm_ops,
+ 	},
+ 	.probe	= hx4700_audio_probe,
+-	.remove	= __devexit_p(hx4700_audio_remove),
++	.remove	= hx4700_audio_remove,
+ };
+ 
+ module_platform_driver(hx4700_audio_driver);

commit dca66dab760b1a2abd9c577ba85ba051d79ee206
+Author: Bill Pemberton 
+Date:   Fri Dec 7 09:26:13 2012 -0500
+
+    ASoC: blackfin: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c
+index d7dc9bde0976..7e2f36004a5a 100644
+--- a/sound/soc/blackfin/bf5xx-ac97-pcm.c
++++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c
+@@ -453,12 +453,12 @@ static struct snd_soc_platform_driver bf5xx_ac97_soc_platform = {
+ 	.pcm_free	= bf5xx_pcm_free_dma_buffers,
+ };
+ 
+-static int __devinit bf5xx_soc_platform_probe(struct platform_device *pdev)
++static int bf5xx_soc_platform_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_platform(&pdev->dev, &bf5xx_ac97_soc_platform);
+ }
+ 
+-static int __devexit bf5xx_soc_platform_remove(struct platform_device *pdev)
++static int bf5xx_soc_platform_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_platform(&pdev->dev);
+ 	return 0;
+@@ -471,7 +471,7 @@ static struct platform_driver bf5xx_pcm_driver = {
+ 	},
+ 
+ 	.probe = bf5xx_soc_platform_probe,
+-	.remove = __devexit_p(bf5xx_soc_platform_remove),
++	.remove = bf5xx_soc_platform_remove,
+ };
+ 
+ module_platform_driver(bf5xx_pcm_driver);
+diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c
+index f4e9dc4e262e..8e41bcb020eb 100644
+--- a/sound/soc/blackfin/bf5xx-ac97.c
++++ b/sound/soc/blackfin/bf5xx-ac97.c
+@@ -282,7 +282,7 @@ static struct snd_soc_dai_driver bfin_ac97_dai = {
+ 		.formats = SNDRV_PCM_FMTBIT_S16_LE, },
+ };
+ 
+-static int __devinit asoc_bfin_ac97_probe(struct platform_device *pdev)
++static int asoc_bfin_ac97_probe(struct platform_device *pdev)
+ {
+ 	struct sport_device *sport_handle;
+ 	int ret;
+@@ -352,7 +352,7 @@ static int __devinit asoc_bfin_ac97_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit asoc_bfin_ac97_remove(struct platform_device *pdev)
++static int asoc_bfin_ac97_remove(struct platform_device *pdev)
+ {
+ 	struct sport_device *sport_handle = platform_get_drvdata(pdev);
+ 
+@@ -372,7 +372,7 @@ static struct platform_driver asoc_bfin_ac97_driver = {
+ 	},
+ 
+ 	.probe = asoc_bfin_ac97_probe,
+-	.remove = __devexit_p(asoc_bfin_ac97_remove),
++	.remove = asoc_bfin_ac97_remove,
+ };
+ 
+ module_platform_driver(asoc_bfin_ac97_driver);
+diff --git a/sound/soc/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c
+index 16b9c9efd19a..d23f4b0ea54f 100644
+--- a/sound/soc/blackfin/bf5xx-ad1836.c
++++ b/sound/soc/blackfin/bf5xx-ad1836.c
+@@ -75,7 +75,7 @@ static struct snd_soc_card bf5xx_ad1836 = {
+ 	.num_links = 1,
+ };
+ 
+-static __devinit int bf5xx_ad1836_driver_probe(struct platform_device *pdev)
++static int bf5xx_ad1836_driver_probe(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = &bf5xx_ad1836;
+ 	const char **link_name;
+@@ -98,7 +98,7 @@ static __devinit int bf5xx_ad1836_driver_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit bf5xx_ad1836_driver_remove(struct platform_device *pdev)
++static int bf5xx_ad1836_driver_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -113,7 +113,7 @@ static struct platform_driver bf5xx_ad1836_driver = {
+ 		.pm = &snd_soc_pm_ops,
+ 	},
+ 	.probe = bf5xx_ad1836_driver_probe,
+-	.remove = __devexit_p(bf5xx_ad1836_driver_remove),
++	.remove = bf5xx_ad1836_driver_remove,
+ };
+ module_platform_driver(bf5xx_ad1836_driver);
+ 
+diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c
+index 63205d723eab..262c1de364d8 100644
+--- a/sound/soc/blackfin/bf5xx-i2s-pcm.c
++++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c
+@@ -292,12 +292,12 @@ static struct snd_soc_platform_driver bf5xx_i2s_soc_platform = {
+ 	.pcm_free	= bf5xx_pcm_free_dma_buffers,
+ };
+ 
+-static int __devinit bfin_i2s_soc_platform_probe(struct platform_device *pdev)
++static int bfin_i2s_soc_platform_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_platform(&pdev->dev, &bf5xx_i2s_soc_platform);
+ }
+ 
+-static int __devexit bfin_i2s_soc_platform_remove(struct platform_device *pdev)
++static int bfin_i2s_soc_platform_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_platform(&pdev->dev);
+ 	return 0;
+@@ -310,7 +310,7 @@ static struct platform_driver bfin_i2s_pcm_driver = {
+ 	},
+ 
+ 	.probe = bfin_i2s_soc_platform_probe,
+-	.remove = __devexit_p(bfin_i2s_soc_platform_remove),
++	.remove = bfin_i2s_soc_platform_remove,
+ };
+ 
+ module_platform_driver(bfin_i2s_pcm_driver);
+diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c
+index 4dccf0374fe7..168d88bccb41 100644
+--- a/sound/soc/blackfin/bf5xx-i2s.c
++++ b/sound/soc/blackfin/bf5xx-i2s.c
+@@ -245,7 +245,7 @@ static struct snd_soc_dai_driver bf5xx_i2s_dai = {
+ 	.ops = &bf5xx_i2s_dai_ops,
+ };
+ 
+-static int __devinit bf5xx_i2s_probe(struct platform_device *pdev)
++static int bf5xx_i2s_probe(struct platform_device *pdev)
+ {
+ 	struct sport_device *sport_handle;
+ 	int ret;
+@@ -267,7 +267,7 @@ static int __devinit bf5xx_i2s_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit bf5xx_i2s_remove(struct platform_device *pdev)
++static int bf5xx_i2s_remove(struct platform_device *pdev)
+ {
+ 	struct sport_device *sport_handle = platform_get_drvdata(pdev);
+ 
+@@ -281,7 +281,7 @@ static int __devexit bf5xx_i2s_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver bfin_i2s_driver = {
+ 	.probe  = bf5xx_i2s_probe,
+-	.remove = __devexit_p(bf5xx_i2s_remove),
++	.remove = bf5xx_i2s_remove,
+ 	.driver = {
+ 		.name = "bfin-i2s",
+ 		.owner = THIS_MODULE,
+diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.c b/sound/soc/blackfin/bf5xx-tdm-pcm.c
+index 254490cf1876..0e6b888bb4cc 100644
+--- a/sound/soc/blackfin/bf5xx-tdm-pcm.c
++++ b/sound/soc/blackfin/bf5xx-tdm-pcm.c
+@@ -317,12 +317,12 @@ static struct snd_soc_platform_driver bf5xx_tdm_soc_platform = {
+ 	.pcm_free       = bf5xx_pcm_free_dma_buffers,
+ };
+ 
+-static int __devinit bf5xx_soc_platform_probe(struct platform_device *pdev)
++static int bf5xx_soc_platform_probe(struct platform_device *pdev)
+ {
+ 	return snd_soc_register_platform(&pdev->dev, &bf5xx_tdm_soc_platform);
+ }
+ 
+-static int __devexit bf5xx_soc_platform_remove(struct platform_device *pdev)
++static int bf5xx_soc_platform_remove(struct platform_device *pdev)
+ {
+ 	snd_soc_unregister_platform(&pdev->dev);
+ 	return 0;
+@@ -335,7 +335,7 @@ static struct platform_driver bfin_tdm_driver = {
+ 	},
+ 
+ 	.probe = bf5xx_soc_platform_probe,
+-	.remove = __devexit_p(bf5xx_soc_platform_remove),
++	.remove = bf5xx_soc_platform_remove,
+ };
+ 
+ module_platform_driver(bfin_tdm_driver);
+diff --git a/sound/soc/blackfin/bf5xx-tdm.c b/sound/soc/blackfin/bf5xx-tdm.c
+index 594f88217c74..c1e516ec53ad 100644
+--- a/sound/soc/blackfin/bf5xx-tdm.c
++++ b/sound/soc/blackfin/bf5xx-tdm.c
+@@ -249,7 +249,7 @@ static struct snd_soc_dai_driver bf5xx_tdm_dai = {
+ 	.ops = &bf5xx_tdm_dai_ops,
+ };
+ 
+-static int __devinit bfin_tdm_probe(struct platform_device *pdev)
++static int bfin_tdm_probe(struct platform_device *pdev)
+ {
+ 	struct sport_device *sport_handle;
+ 	int ret;
+@@ -295,7 +295,7 @@ static int __devinit bfin_tdm_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit bfin_tdm_remove(struct platform_device *pdev)
++static int bfin_tdm_remove(struct platform_device *pdev)
+ {
+ 	struct sport_device *sport_handle = platform_get_drvdata(pdev);
+ 
+@@ -307,7 +307,7 @@ static int __devexit bfin_tdm_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver bfin_tdm_driver = {
+ 	.probe  = bfin_tdm_probe,
+-	.remove = __devexit_p(bfin_tdm_remove),
++	.remove = bfin_tdm_remove,
+ 	.driver = {
+ 		.name   = "bfin-tdm",
+ 		.owner  = THIS_MODULE,
+diff --git a/sound/soc/blackfin/bf6xx-i2s.c b/sound/soc/blackfin/bf6xx-i2s.c
+index c3c2466d3a42..8f337972f438 100644
+--- a/sound/soc/blackfin/bf6xx-i2s.c
++++ b/sound/soc/blackfin/bf6xx-i2s.c
+@@ -186,7 +186,7 @@ static struct snd_soc_dai_driver bfin_i2s_dai = {
+ 	.ops = &bfin_i2s_dai_ops,
+ };
+ 
+-static int __devinit bfin_i2s_probe(struct platform_device *pdev)
++static int bfin_i2s_probe(struct platform_device *pdev)
+ {
+ 	struct sport_device *sport;
+ 	struct device *dev = &pdev->dev;
+@@ -208,7 +208,7 @@ static int __devinit bfin_i2s_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit bfin_i2s_remove(struct platform_device *pdev)
++static int bfin_i2s_remove(struct platform_device *pdev)
+ {
+ 	struct sport_device *sport = platform_get_drvdata(pdev);
+ 
+@@ -220,7 +220,7 @@ static int __devexit bfin_i2s_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver bfin_i2s_driver = {
+ 	.probe  = bfin_i2s_probe,
+-	.remove = __devexit_p(bfin_i2s_remove),
++	.remove = bfin_i2s_remove,
+ 	.driver = {
+ 		.name = "bfin-i2s",
+ 		.owner = THIS_MODULE,
+diff --git a/sound/soc/blackfin/bfin-eval-adau1373.c b/sound/soc/blackfin/bfin-eval-adau1373.c
+index f3adbdbdd5e1..4ef9683bcad8 100644
+--- a/sound/soc/blackfin/bfin-eval-adau1373.c
++++ b/sound/soc/blackfin/bfin-eval-adau1373.c
+@@ -157,7 +157,7 @@ static int bfin_eval_adau1373_probe(struct platform_device *pdev)
+ 	return snd_soc_register_card(&bfin_eval_adau1373);
+ }
+ 
+-static int __devexit bfin_eval_adau1373_remove(struct platform_device *pdev)
++static int bfin_eval_adau1373_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -173,7 +173,7 @@ static struct platform_driver bfin_eval_adau1373_driver = {
+ 		.pm = &snd_soc_pm_ops,
+ 	},
+ 	.probe = bfin_eval_adau1373_probe,
+-	.remove = __devexit_p(bfin_eval_adau1373_remove),
++	.remove = bfin_eval_adau1373_remove,
+ };
+ 
+ module_platform_driver(bfin_eval_adau1373_driver);
+diff --git a/sound/soc/blackfin/bfin-eval-adau1701.c b/sound/soc/blackfin/bfin-eval-adau1701.c
+index b0531fc9d814..3b55081a96c0 100644
+--- a/sound/soc/blackfin/bfin-eval-adau1701.c
++++ b/sound/soc/blackfin/bfin-eval-adau1701.c
+@@ -97,7 +97,7 @@ static int bfin_eval_adau1701_probe(struct platform_device *pdev)
+ 	return snd_soc_register_card(&bfin_eval_adau1701);
+ }
+ 
+-static int __devexit bfin_eval_adau1701_remove(struct platform_device *pdev)
++static int bfin_eval_adau1701_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -113,7 +113,7 @@ static struct platform_driver bfin_eval_adau1701_driver = {
+ 		.pm = &snd_soc_pm_ops,
+ 	},
+ 	.probe = bfin_eval_adau1701_probe,
+-	.remove = __devexit_p(bfin_eval_adau1701_remove),
++	.remove = bfin_eval_adau1701_remove,
+ };
+ 
+ module_platform_driver(bfin_eval_adau1701_driver);
+diff --git a/sound/soc/blackfin/bfin-eval-adav80x.c b/sound/soc/blackfin/bfin-eval-adav80x.c
+index 84b09987b7f3..3b1b61a44815 100644
+--- a/sound/soc/blackfin/bfin-eval-adav80x.c
++++ b/sound/soc/blackfin/bfin-eval-adav80x.c
+@@ -122,7 +122,7 @@ static int bfin_eval_adav80x_probe(struct platform_device *pdev)
+ 	return snd_soc_register_card(&bfin_eval_adav80x);
+ }
+ 
+-static int __devexit bfin_eval_adav80x_remove(struct platform_device *pdev)
++static int bfin_eval_adav80x_remove(struct platform_device *pdev)
+ {
+ 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+ 
+@@ -145,7 +145,7 @@ static struct platform_driver bfin_eval_adav80x_driver = {
+ 		.pm = &snd_soc_pm_ops,
+ 	},
+ 	.probe = bfin_eval_adav80x_probe,
+-	.remove = __devexit_p(bfin_eval_adav80x_remove),
++	.remove = bfin_eval_adav80x_remove,
+ 	.id_table = bfin_eval_adav80x_ids,
+ };
+ 

commit 14c56706f9d90d00573b7509b20c49ba56ea7eb1
+Author: Bill Pemberton 
+Date:   Thu Dec 6 12:35:29 2012 -0500
+
+    ALSA: snd-usb-caiaq: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Daniel Mack 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/usb/caiaq/control.c b/sound/usb/caiaq/control.c
+index 00e5d0a469e1..adb8d03267a0 100644
+--- a/sound/usb/caiaq/control.c
++++ b/sound/usb/caiaq/control.c
+@@ -137,7 +137,7 @@ static int control_put(struct snd_kcontrol *kcontrol,
+ 	return 1;
+ }
+ 
+-static struct snd_kcontrol_new kcontrol_template __devinitdata = {
++static struct snd_kcontrol_new kcontrol_template = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_HWDEP,
+ 	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ 	.index = 0,
+@@ -489,8 +489,8 @@ static struct caiaq_controller kontrols4_controller[] = {
+ 	{ "LED: FX2: Mode",			133 | CNT_INTVAL },
+ };
+ 
+-static int __devinit add_controls(struct caiaq_controller *c, int num,
+-				  struct snd_usb_caiaqdev *dev)
++static int add_controls(struct caiaq_controller *c, int num,
++			struct snd_usb_caiaqdev *dev)
+ {
+ 	int i, ret;
+ 	struct snd_kcontrol *kc;
+@@ -507,7 +507,7 @@ static int __devinit add_controls(struct caiaq_controller *c, int num,
+ 	return 0;
+ }
+ 
+-int __devinit snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev)
++int snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev)
+ {
+ 	int ret = 0;
+ 
+diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c
+index 7da0d0aa72cb..c828f8189c25 100644
+--- a/sound/usb/caiaq/device.c
++++ b/sound/usb/caiaq/device.c
+@@ -289,7 +289,7 @@ int snd_usb_caiaq_set_auto_msg(struct snd_usb_caiaqdev *dev,
+ 					  tmp, sizeof(tmp));
+ }
+ 
+-static void __devinit setup_card(struct snd_usb_caiaqdev *dev)
++static void setup_card(struct snd_usb_caiaqdev *dev)
+ {
+ 	int ret;
+ 	char val[4];
+@@ -407,7 +407,7 @@ static int create_card(struct usb_device *usb_dev,
+ 	return 0;
+ }
+ 
+-static int __devinit init_card(struct snd_usb_caiaqdev *dev)
++static int init_card(struct snd_usb_caiaqdev *dev)
+ {
+ 	char *c, usbpath[32];
+ 	struct usb_device *usb_dev = dev->chip.dev;
+@@ -481,7 +481,7 @@ static int __devinit init_card(struct snd_usb_caiaqdev *dev)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_probe(struct usb_interface *intf,
++static int snd_probe(struct usb_interface *intf,
+ 		     const struct usb_device_id *id)
+ {
+ 	int ret;

commit 87f9796a0336efa46d0fbecfb2875afe07dd6972
+Author: Bill Pemberton 
+Date:   Thu Dec 6 12:35:28 2012 -0500
+
+    ALSA: snd-usb-6fire: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c
+index fc8cc823e438..4394ae796356 100644
+--- a/sound/usb/6fire/chip.c
++++ b/sound/usb/6fire/chip.c
+@@ -82,8 +82,8 @@ static void usb6fire_chip_destroy(struct sfire_chip *chip)
+ 	}
+ }
+ 
+-static int __devinit usb6fire_chip_probe(struct usb_interface *intf,
+-		const struct usb_device_id *usb_id)
++static int usb6fire_chip_probe(struct usb_interface *intf,
++			       const struct usb_device_id *usb_id)
+ {
+ 	int ret;
+ 	int i;
+diff --git a/sound/usb/6fire/comm.c b/sound/usb/6fire/comm.c
+index 1a75c36932d8..9e6e3ffd86bb 100644
+--- a/sound/usb/6fire/comm.c
++++ b/sound/usb/6fire/comm.c
+@@ -125,7 +125,7 @@ static int usb6fire_comm_write16(struct comm_runtime *rt, u8 request,
+ 	return usb6fire_comm_send_buffer(buffer, rt->chip->dev);
+ }
+ 
+-int __devinit usb6fire_comm_init(struct sfire_chip *chip)
++int usb6fire_comm_init(struct sfire_chip *chip)
+ {
+ 	struct comm_runtime *rt = kzalloc(sizeof(struct comm_runtime),
+ 			GFP_KERNEL);
+diff --git a/sound/usb/6fire/comm.h b/sound/usb/6fire/comm.h
+index d2af0a5ddcf3..6a0840b0dcff 100644
+--- a/sound/usb/6fire/comm.h
++++ b/sound/usb/6fire/comm.h
+@@ -36,7 +36,7 @@ struct comm_runtime {
+ 			u8 vh, u8 vl);
+ };
+ 
+-int __devinit usb6fire_comm_init(struct sfire_chip *chip);
++int usb6fire_comm_init(struct sfire_chip *chip);
+ void usb6fire_comm_abort(struct sfire_chip *chip);
+ void usb6fire_comm_destroy(struct sfire_chip *chip);
+ #endif /* USB6FIRE_COMM_H */
+diff --git a/sound/usb/6fire/control.c b/sound/usb/6fire/control.c
+index 07ed914d5e71..f6434c245720 100644
+--- a/sound/usb/6fire/control.c
++++ b/sound/usb/6fire/control.c
+@@ -411,7 +411,7 @@ static int usb6fire_control_digital_thru_get(struct snd_kcontrol *kcontrol,
+ 	return 0;
+ }
+ 
+-static struct __devinitdata snd_kcontrol_new vol_elements[] = {
++static struct snd_kcontrol_new vol_elements[] = {
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "Analog Playback Volume",
+@@ -451,7 +451,7 @@ static struct __devinitdata snd_kcontrol_new vol_elements[] = {
+ 	{}
+ };
+ 
+-static struct __devinitdata snd_kcontrol_new mute_elements[] = {
++static struct snd_kcontrol_new mute_elements[] = {
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "Analog Playback Switch",
+@@ -485,7 +485,7 @@ static struct __devinitdata snd_kcontrol_new mute_elements[] = {
+ 	{}
+ };
+ 
+-static struct __devinitdata snd_kcontrol_new elements[] = {
++static struct snd_kcontrol_new elements[] = {
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "Line/Phono Capture Route",
+@@ -561,7 +561,7 @@ static int usb6fire_control_add_virtual(
+ 	return 0;
+ }
+ 
+-int __devinit usb6fire_control_init(struct sfire_chip *chip)
++int usb6fire_control_init(struct sfire_chip *chip)
+ {
+ 	int i;
+ 	int ret;
+diff --git a/sound/usb/6fire/control.h b/sound/usb/6fire/control.h
+index 9a596d95474a..5a40ba143489 100644
+--- a/sound/usb/6fire/control.h
++++ b/sound/usb/6fire/control.h
+@@ -50,7 +50,7 @@ struct control_runtime {
+ 	u8 ivol_updated;
+ };
+ 
+-int __devinit usb6fire_control_init(struct sfire_chip *chip);
++int usb6fire_control_init(struct sfire_chip *chip);
+ void usb6fire_control_abort(struct sfire_chip *chip);
+ void usb6fire_control_destroy(struct sfire_chip *chip);
+ #endif /* USB6FIRE_CONTROL_H */
+diff --git a/sound/usb/6fire/firmware.h b/sound/usb/6fire/firmware.h
+index 008569895381..c109c4f75aba 100644
+--- a/sound/usb/6fire/firmware.h
++++ b/sound/usb/6fire/firmware.h
+@@ -22,6 +22,6 @@ enum /* firmware state of device */
+ 	FW_NOT_READY = 1
+ };
+ 
+-int __devinit usb6fire_fw_init(struct usb_interface *intf);
++int usb6fire_fw_init(struct usb_interface *intf);
+ #endif /* USB6FIRE_FIRMWARE_H */
+ 
+diff --git a/sound/usb/6fire/midi.c b/sound/usb/6fire/midi.c
+index f0e5179b242b..26722423330d 100644
+--- a/sound/usb/6fire/midi.c
++++ b/sound/usb/6fire/midi.c
+@@ -146,7 +146,7 @@ static struct snd_rawmidi_ops in_ops = {
+ 	.trigger = usb6fire_midi_in_trigger
+ };
+ 
+-int __devinit usb6fire_midi_init(struct sfire_chip *chip)
++int usb6fire_midi_init(struct sfire_chip *chip)
+ {
+ 	int ret;
+ 	struct midi_runtime *rt = kzalloc(sizeof(struct midi_runtime),
+diff --git a/sound/usb/6fire/midi.h b/sound/usb/6fire/midi.h
+index 5114eccc1d8e..c321006e5430 100644
+--- a/sound/usb/6fire/midi.h
++++ b/sound/usb/6fire/midi.h
+@@ -38,7 +38,7 @@ struct midi_runtime {
+ 	void (*in_received)(struct midi_runtime *rt, u8 *data, int length);
+ };
+ 
+-int __devinit usb6fire_midi_init(struct sfire_chip *chip);
++int usb6fire_midi_init(struct sfire_chip *chip);
+ void usb6fire_midi_abort(struct sfire_chip *chip);
+ void usb6fire_midi_destroy(struct sfire_chip *chip);
+ #endif /* USB6FIRE_MIDI_H */
+diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c
+index c97d05f0e966..cabedb416fc4 100644
+--- a/sound/usb/6fire/pcm.c
++++ b/sound/usb/6fire/pcm.c
+@@ -559,9 +559,9 @@ static struct snd_pcm_ops pcm_ops = {
+ 	.pointer = usb6fire_pcm_pointer,
+ };
+ 
+-static void __devinit usb6fire_pcm_init_urb(struct pcm_urb *urb,
+-		struct sfire_chip *chip, bool in, int ep,
+-		void (*handler)(struct urb *))
++static void usb6fire_pcm_init_urb(struct pcm_urb *urb,
++				  struct sfire_chip *chip, bool in, int ep,
++				  void (*handler)(struct urb *))
+ {
+ 	urb->chip = chip;
+ 	usb_init_urb(&urb->instance);
+@@ -578,7 +578,7 @@ static void __devinit usb6fire_pcm_init_urb(struct pcm_urb *urb,
+ 	urb->instance.number_of_packets = PCM_N_PACKETS_PER_URB;
+ }
+ 
+-int __devinit usb6fire_pcm_init(struct sfire_chip *chip)
++int usb6fire_pcm_init(struct sfire_chip *chip)
+ {
+ 	int i;
+ 	int ret;
+diff --git a/sound/usb/6fire/pcm.h b/sound/usb/6fire/pcm.h
+index 3104301b257d..9b01133ee3fe 100644
+--- a/sound/usb/6fire/pcm.h
++++ b/sound/usb/6fire/pcm.h
+@@ -69,7 +69,7 @@ struct pcm_runtime {
+ 	bool stream_wait_cond;
+ };
+ 
+-int __devinit usb6fire_pcm_init(struct sfire_chip *chip);
++int usb6fire_pcm_init(struct sfire_chip *chip);
+ void usb6fire_pcm_abort(struct sfire_chip *chip);
+ void usb6fire_pcm_destroy(struct sfire_chip *chip);
+ #endif /* USB6FIRE_PCM_H */

commit fbbb01a12d5d553ea3851a020d98c0ac9b383673
+Author: Bill Pemberton 
+Date:   Thu Dec 6 12:35:27 2012 -0500
+
+    ALSA: drivers: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c
+index 1904046686e2..3d822328d383 100644
+--- a/sound/drivers/aloop.c
++++ b/sound/drivers/aloop.c
+@@ -774,8 +774,8 @@ static struct snd_pcm_ops loopback_capture_ops = {
+ 	.mmap =		snd_pcm_lib_mmap_vmalloc,
+ };
+ 
+-static int __devinit loopback_pcm_new(struct loopback *loopback,
+-				      int device, int substreams)
++static int loopback_pcm_new(struct loopback *loopback,
++			    int device, int substreams)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -949,7 +949,7 @@ static int loopback_channels_get(struct snd_kcontrol *kcontrol,
+ 	return 0;
+ }
+ 
+-static struct snd_kcontrol_new loopback_controls[]  __devinitdata = {
++static struct snd_kcontrol_new loopback_controls[]  = {
+ {
+ 	.iface =        SNDRV_CTL_ELEM_IFACE_PCM,
+ 	.name =         "PCM Rate Shift 100000",
+@@ -998,7 +998,7 @@ static struct snd_kcontrol_new loopback_controls[]  __devinitdata = {
+ }
+ };
+ 
+-static int __devinit loopback_mixer_new(struct loopback *loopback, int notify)
++static int loopback_mixer_new(struct loopback *loopback, int notify)
+ {
+ 	struct snd_card *card = loopback->card;
+ 	struct snd_pcm *pcm;
+@@ -1111,7 +1111,7 @@ static void print_cable_info(struct snd_info_entry *entry,
+ 	mutex_unlock(&loopback->cable_lock);
+ }
+ 
+-static int __devinit loopback_proc_new(struct loopback *loopback, int cidx)
++static int loopback_proc_new(struct loopback *loopback, int cidx)
+ {
+ 	char name[32];
+ 	struct snd_info_entry *entry;
+@@ -1132,7 +1132,7 @@ static int __devinit loopback_proc_new(struct loopback *loopback, int cidx)
+ 
+ #endif
+ 
+-static int __devinit loopback_probe(struct platform_device *devptr)
++static int loopback_probe(struct platform_device *devptr)
+ {
+ 	struct snd_card *card;
+ 	struct loopback *loopback;
+@@ -1177,7 +1177,7 @@ static int __devinit loopback_probe(struct platform_device *devptr)
+ 	return err;
+ }
+ 
+-static int __devexit loopback_remove(struct platform_device *devptr)
++static int loopback_remove(struct platform_device *devptr)
+ {
+ 	snd_card_free(platform_get_drvdata(devptr));
+ 	platform_set_drvdata(devptr, NULL);
+@@ -1215,7 +1215,7 @@ static SIMPLE_DEV_PM_OPS(loopback_pm, loopback_suspend, loopback_resume);
+ 
+ static struct platform_driver loopback_driver = {
+ 	.probe		= loopback_probe,
+-	.remove		= __devexit_p(loopback_remove),
++	.remove		= loopback_remove,
+ 	.driver		= {
+ 		.name	= SND_LOOPBACK_DRIVER,
+ 		.owner	= THIS_MODULE,
+diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
+index 4f522cf48455..fd798f753609 100644
+--- a/sound/drivers/dummy.c
++++ b/sound/drivers/dummy.c
+@@ -688,8 +688,8 @@ static struct snd_pcm_ops dummy_pcm_ops_no_buf = {
+ 	.page =		dummy_pcm_page,
+ };
+ 
+-static int __devinit snd_card_dummy_pcm(struct snd_dummy *dummy, int device,
+-					int substreams)
++static int snd_card_dummy_pcm(struct snd_dummy *dummy, int device,
++			      int substreams)
+ {
+ 	struct snd_pcm *pcm;
+ 	struct snd_pcm_ops *ops;
+@@ -891,7 +891,7 @@ DUMMY_CAPSRC("CD Capture Switch", 0, MIXER_ADDR_CD),
+ },
+ };
+ 
+-static int __devinit snd_card_dummy_new_mixer(struct snd_dummy *dummy)
++static int snd_card_dummy_new_mixer(struct snd_dummy *dummy)
+ {
+ 	struct snd_card *card = dummy->card;
+ 	struct snd_kcontrol *kcontrol;
+@@ -1031,7 +1031,7 @@ static void dummy_proc_write(struct snd_info_entry *entry,
+ 	}
+ }
+ 
+-static void __devinit dummy_proc_init(struct snd_dummy *chip)
++static void dummy_proc_init(struct snd_dummy *chip)
+ {
+ 	struct snd_info_entry *entry;
+ 
+@@ -1046,7 +1046,7 @@ static void __devinit dummy_proc_init(struct snd_dummy *chip)
+ #define dummy_proc_init(x)
+ #endif /* CONFIG_SND_DEBUG && CONFIG_PROC_FS */
+ 
+-static int __devinit snd_dummy_probe(struct platform_device *devptr)
++static int snd_dummy_probe(struct platform_device *devptr)
+ {
+ 	struct snd_card *card;
+ 	struct snd_dummy *dummy;
+@@ -1126,7 +1126,7 @@ static int __devinit snd_dummy_probe(struct platform_device *devptr)
+ 	return err;
+ }
+ 
+-static int __devexit snd_dummy_remove(struct platform_device *devptr)
++static int snd_dummy_remove(struct platform_device *devptr)
+ {
+ 	snd_card_free(platform_get_drvdata(devptr));
+ 	platform_set_drvdata(devptr, NULL);
+@@ -1162,7 +1162,7 @@ static SIMPLE_DEV_PM_OPS(snd_dummy_pm, snd_dummy_suspend, snd_dummy_resume);
+ 
+ static struct platform_driver snd_dummy_driver = {
+ 	.probe		= snd_dummy_probe,
+-	.remove		= __devexit_p(snd_dummy_remove),
++	.remove		= snd_dummy_remove,
+ 	.driver		= {
+ 		.name	= SND_DUMMY_DRIVER,
+ 		.owner	= THIS_MODULE,
+diff --git a/sound/drivers/ml403-ac97cr.c b/sound/drivers/ml403-ac97cr.c
+index 6c83b1aed288..8125a7e95ee4 100644
+--- a/sound/drivers/ml403-ac97cr.c
++++ b/sound/drivers/ml403-ac97cr.c
+@@ -1063,7 +1063,7 @@ snd_ml403_ac97cr_codec_write(struct snd_ac97 *ac97, unsigned short reg,
+ 	return;
+ }
+ 
+-static int __devinit
++static int
+ snd_ml403_ac97cr_chip_init(struct snd_ml403_ac97cr *ml403_ac97cr)
+ {
+ 	unsigned long end_time;
+@@ -1108,7 +1108,7 @@ static int snd_ml403_ac97cr_dev_free(struct snd_device *snddev)
+ 	return snd_ml403_ac97cr_free(ml403_ac97cr);
+ }
+ 
+-static int __devinit
++static int
+ snd_ml403_ac97cr_create(struct snd_card *card, struct platform_device *pfdev,
+ 			struct snd_ml403_ac97cr **rml403_ac97cr)
+ {
+@@ -1204,7 +1204,7 @@ static void snd_ml403_ac97cr_mixer_free(struct snd_ac97 *ac97)
+ 	PDEBUG(INIT_INFO, "mixer_free(): (done)\n");
+ }
+ 
+-static int __devinit
++static int
+ snd_ml403_ac97cr_mixer(struct snd_ml403_ac97cr *ml403_ac97cr)
+ {
+ 	struct snd_ac97_bus *bus;
+@@ -1237,7 +1237,7 @@ snd_ml403_ac97cr_mixer(struct snd_ml403_ac97cr *ml403_ac97cr)
+ 	return err;
+ }
+ 
+-static int __devinit
++static int
+ snd_ml403_ac97cr_pcm(struct snd_ml403_ac97cr *ml403_ac97cr, int device,
+ 		     struct snd_pcm **rpcm)
+ {
+@@ -1268,7 +1268,7 @@ snd_ml403_ac97cr_pcm(struct snd_ml403_ac97cr *ml403_ac97cr, int device,
+ 	return 0;
+ }
+ 
+-static int __devinit snd_ml403_ac97cr_probe(struct platform_device *pfdev)
++static int snd_ml403_ac97cr_probe(struct platform_device *pfdev)
+ {
+ 	struct snd_card *card;
+ 	struct snd_ml403_ac97cr *ml403_ac97cr = NULL;
+diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
+index bc03a2046c9c..da1a29bfc85d 100644
+--- a/sound/drivers/mpu401/mpu401.c
++++ b/sound/drivers/mpu401/mpu401.c
+@@ -100,7 +100,7 @@ static int snd_mpu401_create(int dev, struct snd_card **rcard)
+ 	return err;
+ }
+ 
+-static int __devinit snd_mpu401_probe(struct platform_device *devptr)
++static int snd_mpu401_probe(struct platform_device *devptr)
+ {
+ 	int dev = devptr->id;
+ 	int err;
+@@ -126,7 +126,7 @@ static int __devinit snd_mpu401_probe(struct platform_device *devptr)
+ 	return 0;
+ }
+ 
+-static int __devexit snd_mpu401_remove(struct platform_device *devptr)
++static int snd_mpu401_remove(struct platform_device *devptr)
+ {
+ 	snd_card_free(platform_get_drvdata(devptr));
+ 	platform_set_drvdata(devptr, NULL);
+@@ -137,7 +137,7 @@ static int __devexit snd_mpu401_remove(struct platform_device *devptr)
+ 
+ static struct platform_driver snd_mpu401_driver = {
+ 	.probe		= snd_mpu401_probe,
+-	.remove		= __devexit_p(snd_mpu401_remove),
++	.remove		= snd_mpu401_remove,
+ 	.driver		= {
+ 		.name	= SND_MPU401_DRIVER,
+ 		.owner	= THIS_MODULE,
+@@ -156,8 +156,8 @@ static struct pnp_device_id snd_mpu401_pnpids[] = {
+ 
+ MODULE_DEVICE_TABLE(pnp, snd_mpu401_pnpids);
+ 
+-static int __devinit snd_mpu401_pnp(int dev, struct pnp_dev *device,
+-				 const struct pnp_device_id *id)
++static int snd_mpu401_pnp(int dev, struct pnp_dev *device,
++			  const struct pnp_device_id *id)
+ {
+ 	if (!pnp_port_valid(device, 0) ||
+ 	    pnp_port_flags(device, 0) & IORESOURCE_DISABLED) {
+@@ -182,8 +182,8 @@ static int __devinit snd_mpu401_pnp(int dev, struct pnp_dev *device,
+ 	return 0;
+ }
+ 
+-static int __devinit snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev,
+-					  const struct pnp_device_id *id)
++static int snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev,
++				const struct pnp_device_id *id)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -211,7 +211,7 @@ static int __devinit snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev,
+ 	return -ENODEV;
+ }
+ 
+-static void __devexit snd_mpu401_pnp_remove(struct pnp_dev *dev)
++static void snd_mpu401_pnp_remove(struct pnp_dev *dev)
+ {
+ 	struct snd_card *card = (struct snd_card *) pnp_get_drvdata(dev);
+ 
+@@ -223,7 +223,7 @@ static struct pnp_driver snd_mpu401_pnp_driver = {
+ 	.name = "mpu401",
+ 	.id_table = snd_mpu401_pnpids,
+ 	.probe = snd_mpu401_pnp_probe,
+-	.remove = __devexit_p(snd_mpu401_pnp_remove),
++	.remove = snd_mpu401_pnp_remove,
+ };
+ #else
+ static struct pnp_driver snd_mpu401_pnp_driver;
+diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
+index cad73af3860c..9f1815b99a15 100644
+--- a/sound/drivers/mtpav.c
++++ b/sound/drivers/mtpav.c
+@@ -583,7 +583,7 @@ static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id)
+ /*
+  * get ISA resources
+  */
+-static int __devinit snd_mtpav_get_ISA(struct mtpav * mcard)
++static int snd_mtpav_get_ISA(struct mtpav *mcard)
+ {
+ 	if ((mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI")) == NULL) {
+ 		snd_printk(KERN_ERR "MTVAP port 0x%lx is busy\n", port);
+@@ -619,8 +619,8 @@ static struct snd_rawmidi_ops snd_mtpav_input = {
+  * get RAWMIDI resources
+  */
+ 
+-static void __devinit snd_mtpav_set_name(struct mtpav *chip,
+-				      struct snd_rawmidi_substream *substream)
++static void snd_mtpav_set_name(struct mtpav *chip,
++			       struct snd_rawmidi_substream *substream)
+ {
+ 	if (substream->number >= 0 && substream->number < chip->num_ports)
+ 		sprintf(substream->name, "MTP direct %d", (substream->number % chip->num_ports) + 1);
+@@ -634,7 +634,7 @@ static void __devinit snd_mtpav_set_name(struct mtpav *chip,
+ 		strcpy(substream->name, "MTP broadcast");
+ }
+ 
+-static int __devinit snd_mtpav_get_RAWMIDI(struct mtpav *mcard)
++static int snd_mtpav_get_RAWMIDI(struct mtpav *mcard)
+ {
+ 	int rval;
+ 	struct snd_rawmidi *rawmidi;
+@@ -691,7 +691,7 @@ static void snd_mtpav_free(struct snd_card *card)
+ 
+ /*
+  */
+-static int __devinit snd_mtpav_probe(struct platform_device *dev)
++static int snd_mtpav_probe(struct platform_device *dev)
+ {
+ 	struct snd_card *card;
+ 	int err;
+@@ -746,7 +746,7 @@ static int __devinit snd_mtpav_probe(struct platform_device *dev)
+ 	return err;
+ }
+ 
+-static int __devexit snd_mtpav_remove(struct platform_device *devptr)
++static int snd_mtpav_remove(struct platform_device *devptr)
+ {
+ 	snd_card_free(platform_get_drvdata(devptr));
+ 	platform_set_drvdata(devptr, NULL);
+@@ -757,7 +757,7 @@ static int __devexit snd_mtpav_remove(struct platform_device *devptr)
+ 
+ static struct platform_driver snd_mtpav_driver = {
+ 	.probe		= snd_mtpav_probe,
+-	.remove		= __devexit_p(snd_mtpav_remove),
++	.remove		= snd_mtpav_remove,
+ 	.driver		= {
+ 		.name	= SND_MTPAV_DRIVER,
+ 		.owner	= THIS_MODULE,
+diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c
+index 2d5514b0a290..4e0dd22ba08e 100644
+--- a/sound/drivers/mts64.c
++++ b/sound/drivers/mts64.c
+@@ -83,9 +83,9 @@ static int snd_mts64_free(struct mts64 *mts)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_mts64_create(struct snd_card *card, 
+-				      struct pardevice *pardev, 
+-				      struct mts64 **rchip)
++static int snd_mts64_create(struct snd_card *card,
++			    struct pardevice *pardev,
++			    struct mts64 **rchip)
+ {
+ 	struct mts64 *mts;
+ 
+@@ -214,7 +214,7 @@ static int mts64_device_ready(struct parport *p)
+  *  0 init ok
+  *  -EIO failure
+  */
+-static int __devinit mts64_device_init(struct parport *p)
++static int mts64_device_init(struct parport *p)
+ {
+ 	int i;
+ 
+@@ -290,7 +290,7 @@ static u8 mts64_map_midi_input(u8 c)
+  *  0       device found
+  *  -ENODEV no device
+  */
+-static int __devinit mts64_probe(struct parport *p)
++static int mts64_probe(struct parport *p)
+ {
+ 	u8 c;
+ 
+@@ -483,7 +483,7 @@ static int snd_mts64_ctl_smpte_switch_put(struct snd_kcontrol* kctl,
+ 	return changed;
+ }
+ 
+-static struct snd_kcontrol_new mts64_ctl_smpte_switch __devinitdata = {
++static struct snd_kcontrol_new mts64_ctl_smpte_switch = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
+ 	.name  = "SMPTE Playback Switch",
+ 	.index = 0,
+@@ -556,7 +556,7 @@ static int snd_mts64_ctl_smpte_time_put(struct snd_kcontrol *kctl,
+ 	return changed;
+ }
+ 
+-static struct snd_kcontrol_new mts64_ctl_smpte_time_hours __devinitdata = {
++static struct snd_kcontrol_new mts64_ctl_smpte_time_hours = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
+ 	.name  = "SMPTE Time Hours",
+ 	.index = 0,
+@@ -567,7 +567,7 @@ static struct snd_kcontrol_new mts64_ctl_smpte_time_hours __devinitdata = {
+ 	.put  = snd_mts64_ctl_smpte_time_put
+ };
+ 
+-static struct snd_kcontrol_new mts64_ctl_smpte_time_minutes __devinitdata = {
++static struct snd_kcontrol_new mts64_ctl_smpte_time_minutes = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
+ 	.name  = "SMPTE Time Minutes",
+ 	.index = 0,
+@@ -578,7 +578,7 @@ static struct snd_kcontrol_new mts64_ctl_smpte_time_minutes __devinitdata = {
+ 	.put  = snd_mts64_ctl_smpte_time_put
+ };
+ 
+-static struct snd_kcontrol_new mts64_ctl_smpte_time_seconds __devinitdata = {
++static struct snd_kcontrol_new mts64_ctl_smpte_time_seconds = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
+ 	.name  = "SMPTE Time Seconds",
+ 	.index = 0,
+@@ -589,7 +589,7 @@ static struct snd_kcontrol_new mts64_ctl_smpte_time_seconds __devinitdata = {
+ 	.put  = snd_mts64_ctl_smpte_time_put
+ };
+ 
+-static struct snd_kcontrol_new mts64_ctl_smpte_time_frames __devinitdata = {
++static struct snd_kcontrol_new mts64_ctl_smpte_time_frames = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
+ 	.name  = "SMPTE Time Frames",
+ 	.index = 0,
+@@ -651,7 +651,7 @@ static int snd_mts64_ctl_smpte_fps_put(struct snd_kcontrol *kctl,
+ 	return changed;
+ }
+ 
+-static struct snd_kcontrol_new mts64_ctl_smpte_fps __devinitdata = {
++static struct snd_kcontrol_new mts64_ctl_smpte_fps = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
+ 	.name  = "SMPTE Fps",
+ 	.index = 0,
+@@ -663,11 +663,11 @@ static struct snd_kcontrol_new mts64_ctl_smpte_fps __devinitdata = {
+ };
+ 
+ 
+-static int __devinit snd_mts64_ctl_create(struct snd_card *card, 
+-					  struct mts64 *mts) 
++static int snd_mts64_ctl_create(struct snd_card *card,
++				struct mts64 *mts)
+ {
+ 	int err, i;
+-	static struct snd_kcontrol_new *control[] __devinitdata = {
++	static struct snd_kcontrol_new *control[] = {
+ 		&mts64_ctl_smpte_switch,
+ 		&mts64_ctl_smpte_time_hours,
+ 		&mts64_ctl_smpte_time_minutes,
+@@ -774,7 +774,7 @@ static struct snd_rawmidi_ops snd_mts64_rawmidi_input_ops = {
+ };
+ 
+ /* Create and initialize the rawmidi component */
+-static int __devinit snd_mts64_rawmidi_create(struct snd_card *card)
++static int snd_mts64_rawmidi_create(struct snd_card *card)
+ {
+ 	struct mts64 *mts = card->private_data;
+ 	struct snd_rawmidi *rmidi;
+@@ -860,7 +860,7 @@ static void snd_mts64_interrupt(void *private)
+ 	spin_unlock(&mts->lock);
+ }
+ 
+-static int __devinit snd_mts64_probe_port(struct parport *p)
++static int snd_mts64_probe_port(struct parport *p)
+ {
+ 	struct pardevice *pardev;
+ 	int res;
+@@ -884,7 +884,7 @@ static int __devinit snd_mts64_probe_port(struct parport *p)
+ 	return res;
+ }
+ 
+-static void __devinit snd_mts64_attach(struct parport *p)
++static void snd_mts64_attach(struct parport *p)
+ {
+ 	struct platform_device *device;
+ 
+@@ -940,7 +940,7 @@ static void snd_mts64_card_private_free(struct snd_card *card)
+ 	snd_mts64_free(mts);
+ }
+ 
+-static int __devinit snd_mts64_probe(struct platform_device *pdev)
++static int snd_mts64_probe(struct platform_device *pdev)
+ {
+ 	struct pardevice *pardev;
+ 	struct parport *p;
+@@ -1025,7 +1025,7 @@ static int __devinit snd_mts64_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit snd_mts64_remove(struct platform_device *pdev)
++static int snd_mts64_remove(struct platform_device *pdev)
+ {
+ 	struct snd_card *card = platform_get_drvdata(pdev);
+ 
+@@ -1038,7 +1038,7 @@ static int __devexit snd_mts64_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver snd_mts64_driver = {
+ 	.probe  = snd_mts64_probe,
+-	.remove = __devexit_p(snd_mts64_remove),
++	.remove = snd_mts64_remove,
+ 	.driver = {
+ 		.name = PLATFORM_DRIVER,
+ 		.owner	= THIS_MODULE,
+diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c
+index ef171295f6d4..7a5fdb9b0afc 100644
+--- a/sound/drivers/pcsp/pcsp.c
++++ b/sound/drivers/pcsp/pcsp.c
+@@ -39,7 +39,7 @@ MODULE_PARM_DESC(nopcm, "Disable PC-Speaker PCM sound. Only beeps remain.");
+ 
+ struct snd_pcsp pcsp_chip;
+ 
+-static int __devinit snd_pcsp_create(struct snd_card *card)
++static int snd_pcsp_create(struct snd_card *card)
+ {
+ 	static struct snd_device_ops ops = { };
+ 	struct timespec tp;
+@@ -93,7 +93,7 @@ static int __devinit snd_pcsp_create(struct snd_card *card)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev)
++static int snd_card_pcsp_probe(int devnum, struct device *dev)
+ {
+ 	struct snd_card *card;
+ 	int err;
+@@ -142,7 +142,7 @@ static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev)
+ 	return 0;
+ }
+ 
+-static int __devinit alsa_card_pcsp_init(struct device *dev)
++static int alsa_card_pcsp_init(struct device *dev)
+ {
+ 	int err;
+ 
+@@ -161,12 +161,12 @@ static int __devinit alsa_card_pcsp_init(struct device *dev)
+ 	return 0;
+ }
+ 
+-static void __devexit alsa_card_pcsp_exit(struct snd_pcsp *chip)
++static void alsa_card_pcsp_exit(struct snd_pcsp *chip)
+ {
+ 	snd_card_free(chip->card);
+ }
+ 
+-static int __devinit pcsp_probe(struct platform_device *dev)
++static int pcsp_probe(struct platform_device *dev)
+ {
+ 	int err;
+ 
+@@ -184,7 +184,7 @@ static int __devinit pcsp_probe(struct platform_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devexit pcsp_remove(struct platform_device *dev)
++static int pcsp_remove(struct platform_device *dev)
+ {
+ 	struct snd_pcsp *chip = platform_get_drvdata(dev);
+ 	alsa_card_pcsp_exit(chip);
+@@ -227,7 +227,7 @@ static struct platform_driver pcsp_platform_driver = {
+ 		.pm	= PCSP_PM_OPS,
+ 	},
+ 	.probe		= pcsp_probe,
+-	.remove		= __devexit_p(pcsp_remove),
++	.remove		= pcsp_remove,
+ 	.shutdown	= pcsp_shutdown,
+ };
+ 
+diff --git a/sound/drivers/pcsp/pcsp_input.c b/sound/drivers/pcsp/pcsp_input.c
+index b5e2b54c2604..b874b0ad99cd 100644
+--- a/sound/drivers/pcsp/pcsp_input.c
++++ b/sound/drivers/pcsp/pcsp_input.c
+@@ -77,7 +77,7 @@ static int pcspkr_input_event(struct input_dev *dev, unsigned int type,
+ 	return 0;
+ }
+ 
+-int __devinit pcspkr_input_init(struct input_dev **rdev, struct device *dev)
++int pcspkr_input_init(struct input_dev **rdev, struct device *dev)
+ {
+ 	int err;
+ 
+diff --git a/sound/drivers/pcsp/pcsp_input.h b/sound/drivers/pcsp/pcsp_input.h
+index e66738c78333..d692749b8c9b 100644
+--- a/sound/drivers/pcsp/pcsp_input.h
++++ b/sound/drivers/pcsp/pcsp_input.h
+@@ -7,7 +7,7 @@
+ #ifndef __PCSP_INPUT_H__
+ #define __PCSP_INPUT_H__
+ 
+-int __devinit pcspkr_input_init(struct input_dev **rdev, struct device *dev);
++int pcspkr_input_init(struct input_dev **rdev, struct device *dev);
+ int pcspkr_input_remove(struct input_dev *dev);
+ void pcspkr_stop_sound(void);
+ 
+diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c
+index 434981dd4a61..29ebaa4ec0fd 100644
+--- a/sound/drivers/pcsp/pcsp_lib.c
++++ b/sound/drivers/pcsp/pcsp_lib.c
+@@ -334,7 +334,7 @@ static struct snd_pcm_ops snd_pcsp_playback_ops = {
+ 	.pointer = snd_pcsp_playback_pointer,
+ };
+ 
+-int __devinit snd_pcsp_new_pcm(struct snd_pcsp *chip)
++int snd_pcsp_new_pcm(struct snd_pcsp *chip)
+ {
+ 	int err;
+ 
+diff --git a/sound/drivers/pcsp/pcsp_mixer.c b/sound/drivers/pcsp/pcsp_mixer.c
+index 6f633f4f3b96..f1e1defc09b1 100644
+--- a/sound/drivers/pcsp/pcsp_mixer.c
++++ b/sound/drivers/pcsp/pcsp_mixer.c
+@@ -119,17 +119,17 @@ static int pcsp_pcspkr_put(struct snd_kcontrol *kcontrol,
+ 	.put =		pcsp_##ctl_type##_put, \
+ }
+ 
+-static struct snd_kcontrol_new __devinitdata snd_pcsp_controls_pcm[] = {
++static struct snd_kcontrol_new snd_pcsp_controls_pcm[] = {
+ 	PCSP_MIXER_CONTROL(enable, "Master Playback Switch"),
+ 	PCSP_MIXER_CONTROL(treble, "BaseFRQ Playback Volume"),
+ };
+ 
+-static struct snd_kcontrol_new __devinitdata snd_pcsp_controls_spkr[] = {
++static struct snd_kcontrol_new snd_pcsp_controls_spkr[] = {
+ 	PCSP_MIXER_CONTROL(pcspkr, "Beep Playback Switch"),
+ };
+ 
+-static int __devinit snd_pcsp_ctls_add(struct snd_pcsp *chip,
+-	struct snd_kcontrol_new *ctls, int num)
++static int snd_pcsp_ctls_add(struct snd_pcsp *chip,
++			     struct snd_kcontrol_new *ctls, int num)
+ {
+ 	int i, err;
+ 	struct snd_card *card = chip->card;
+@@ -141,7 +141,7 @@ static int __devinit snd_pcsp_ctls_add(struct snd_pcsp *chip,
+ 	return 0;
+ }
+ 
+-int __devinit snd_pcsp_new_mixer(struct snd_pcsp *chip, int nopcm)
++int snd_pcsp_new_mixer(struct snd_pcsp *chip, int nopcm)
+ {
+ 	int err;
+ 	struct snd_card *card = chip->card;
+diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c
+index 8364855ed14f..991018df7131 100644
+--- a/sound/drivers/portman2x4.c
++++ b/sound/drivers/portman2x4.c
+@@ -96,9 +96,9 @@ static int portman_free(struct portman *pm)
+ 	return 0;
+ }
+ 
+-static int __devinit portman_create(struct snd_card *card, 
+-				    struct pardevice *pardev, 
+-				    struct portman **rchip)
++static int portman_create(struct snd_card *card,
++			  struct pardevice *pardev,
++			  struct portman **rchip)
+ {
+ 	struct portman *pm;
+ 
+@@ -561,7 +561,7 @@ static struct snd_rawmidi_ops snd_portman_midi_input = {
+ };
+ 
+ /* Create and initialize the rawmidi component */
+-static int __devinit snd_portman_rawmidi_create(struct snd_card *card)
++static int snd_portman_rawmidi_create(struct snd_card *card)
+ {
+ 	struct portman *pm = card->private_data;
+ 	struct snd_rawmidi *rmidi;
+@@ -648,7 +648,7 @@ static void snd_portman_interrupt(void *userdata)
+ 	spin_unlock(&pm->reg_lock);
+ }
+ 
+-static int __devinit snd_portman_probe_port(struct parport *p)
++static int snd_portman_probe_port(struct parport *p)
+ {
+ 	struct pardevice *pardev;
+ 	int res;
+@@ -672,7 +672,7 @@ static int __devinit snd_portman_probe_port(struct parport *p)
+ 	return res ? -EIO : 0;
+ }
+ 
+-static void __devinit snd_portman_attach(struct parport *p)
++static void snd_portman_attach(struct parport *p)
+ {
+ 	struct platform_device *device;
+ 
+@@ -728,7 +728,7 @@ static void snd_portman_card_private_free(struct snd_card *card)
+ 	portman_free(pm);
+ }
+ 
+-static int __devinit snd_portman_probe(struct platform_device *pdev)
++static int snd_portman_probe(struct platform_device *pdev)
+ {
+ 	struct pardevice *pardev;
+ 	struct parport *p;
+@@ -814,7 +814,7 @@ static int __devinit snd_portman_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit snd_portman_remove(struct platform_device *pdev)
++static int snd_portman_remove(struct platform_device *pdev)
+ {
+ 	struct snd_card *card = platform_get_drvdata(pdev);
+ 
+@@ -827,7 +827,7 @@ static int __devexit snd_portman_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver snd_portman_driver = {
+ 	.probe  = snd_portman_probe,
+-	.remove = __devexit_p(snd_portman_remove),
++	.remove = snd_portman_remove,
+ 	.driver = {
+ 		.name = PLATFORM_DRIVER,
+ 		.owner	= THIS_MODULE,
+diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
+index 86700671d1ac..7425dd8c1f09 100644
+--- a/sound/drivers/serial-u16550.c
++++ b/sound/drivers/serial-u16550.c
+@@ -328,7 +328,7 @@ static void snd_uart16550_buffer_timer(unsigned long data)
+  *  return 0 if found
+  *  return negative error if not found
+  */
+-static int __devinit snd_uart16550_detect(struct snd_uart16550 *uart)
++static int snd_uart16550_detect(struct snd_uart16550 *uart)
+ {
+ 	unsigned long io_base = uart->base;
+ 	int ok;
+@@ -783,14 +783,14 @@ static int snd_uart16550_dev_free(struct snd_device *device)
+ 	return snd_uart16550_free(uart);
+ }
+ 
+-static int __devinit snd_uart16550_create(struct snd_card *card,
+-				       unsigned long iobase,
+-				       int irq,
+-				       unsigned int speed,
+-				       unsigned int base,
+-				       int adaptor,
+-				       int droponfull,
+-				       struct snd_uart16550 **ruart)
++static int snd_uart16550_create(struct snd_card *card,
++				unsigned long iobase,
++				int irq,
++				unsigned int speed,
++				unsigned int base,
++				int adaptor,
++				int droponfull,
++				struct snd_uart16550 **ruart)
+ {
+ 	static struct snd_device_ops ops = {
+ 		.dev_free =	snd_uart16550_dev_free,
+@@ -863,7 +863,7 @@ static int __devinit snd_uart16550_create(struct snd_card *card,
+ 	return 0;
+ }
+ 
+-static void __devinit snd_uart16550_substreams(struct snd_rawmidi_str *stream)
++static void snd_uart16550_substreams(struct snd_rawmidi_str *stream)
+ {
+ 	struct snd_rawmidi_substream *substream;
+ 
+@@ -872,9 +872,9 @@ static void __devinit snd_uart16550_substreams(struct snd_rawmidi_str *stream)
+ 	}
+ }
+ 
+-static int __devinit snd_uart16550_rmidi(struct snd_uart16550 *uart, int device,
+-				      int outs, int ins,
+-				      struct snd_rawmidi **rmidi)
++static int snd_uart16550_rmidi(struct snd_uart16550 *uart, int device,
++			       int outs, int ins,
++			       struct snd_rawmidi **rmidi)
+ {
+ 	struct snd_rawmidi *rrawmidi;
+ 	int err;
+@@ -899,7 +899,7 @@ static int __devinit snd_uart16550_rmidi(struct snd_uart16550 *uart, int device,
+ 	return 0;
+ }
+ 
+-static int __devinit snd_serial_probe(struct platform_device *devptr)
++static int snd_serial_probe(struct platform_device *devptr)
+ {
+ 	struct snd_card *card;
+ 	struct snd_uart16550 *uart;
+@@ -982,7 +982,7 @@ static int __devinit snd_serial_probe(struct platform_device *devptr)
+ 	return err;
+ }
+ 
+-static int __devexit snd_serial_remove(struct platform_device *devptr)
++static int snd_serial_remove(struct platform_device *devptr)
+ {
+ 	snd_card_free(platform_get_drvdata(devptr));
+ 	platform_set_drvdata(devptr, NULL);
+@@ -993,7 +993,7 @@ static int __devexit snd_serial_remove(struct platform_device *devptr)
+ 
+ static struct platform_driver snd_serial_driver = {
+ 	.probe		= snd_serial_probe,
+-	.remove		= __devexit_p( snd_serial_remove),
++	.remove		=  snd_serial_remove,
+ 	.driver		= {
+ 		.name	= SND_SERIAL_DRIVER,
+ 		.owner	= THIS_MODULE,
+diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c
+index d7d514df9058..cc4be88d7318 100644
+--- a/sound/drivers/virmidi.c
++++ b/sound/drivers/virmidi.c
+@@ -83,7 +83,7 @@ struct snd_card_virmidi {
+ static struct platform_device *devices[SNDRV_CARDS];
+ 
+ 
+-static int __devinit snd_virmidi_probe(struct platform_device *devptr)
++static int snd_virmidi_probe(struct platform_device *devptr)
+ {
+ 	struct snd_card *card;
+ 	struct snd_card_virmidi *vmidi;
+@@ -129,7 +129,7 @@ static int __devinit snd_virmidi_probe(struct platform_device *devptr)
+ 	return err;
+ }
+ 
+-static int __devexit snd_virmidi_remove(struct platform_device *devptr)
++static int snd_virmidi_remove(struct platform_device *devptr)
+ {
+ 	snd_card_free(platform_get_drvdata(devptr));
+ 	platform_set_drvdata(devptr, NULL);
+@@ -140,7 +140,7 @@ static int __devexit snd_virmidi_remove(struct platform_device *devptr)
+ 
+ static struct platform_driver snd_virmidi_driver = {
+ 	.probe		= snd_virmidi_probe,
+-	.remove		= __devexit_p(snd_virmidi_remove),
++	.remove		= snd_virmidi_remove,
+ 	.driver		= {
+ 		.name	= SND_VIRMIDI_DRIVER,
+ 		.owner	= THIS_MODULE,

commit 4423d247509fe65fb9e9efb35229fd1d3986d41d
+Author: Bill Pemberton 
+Date:   Thu Dec 6 12:35:26 2012 -0500
+
+    ALSA: at73c213: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c
+index c6500d00053b..4dd60d8a4889 100644
+--- a/sound/spi/at73c213.c
++++ b/sound/spi/at73c213.c
+@@ -330,7 +330,7 @@ static struct snd_pcm_ops at73c213_playback_ops = {
+ 	.pointer	= snd_at73c213_pcm_pointer,
+ };
+ 
+-static int __devinit snd_at73c213_pcm_new(struct snd_at73c213 *chip, int device)
++static int snd_at73c213_pcm_new(struct snd_at73c213 *chip, int device)
+ {
+ 	struct snd_pcm *pcm;
+ 	int retval;
+@@ -665,7 +665,7 @@ static int snd_at73c213_aux_capture_volume_info(
+ 			| (mask << 24) | (invert << 22))		\
+ }
+ 
+-static struct snd_kcontrol_new snd_at73c213_controls[] __devinitdata = {
++static struct snd_kcontrol_new snd_at73c213_controls[] = {
+ AT73C213_STEREO("Master Playback Volume", 0, DAC_LMPG, DAC_RMPG, 0, 0, 0x1f, 1),
+ AT73C213_STEREO("Master Playback Switch", 0, DAC_LMPG, DAC_RMPG, 5, 5, 1, 1),
+ AT73C213_STEREO("PCM Playback Volume", 0, DAC_LLOG, DAC_RLOG, 0, 0, 0x1f, 1),
+@@ -709,7 +709,7 @@ AT73C213_MONO_SWITCH("Aux Capture Switch", 0, DAC_CTRL, DAC_CTRL_ONAUXIN,
+ AT73C213_MONO_SWITCH("Line Capture Switch", 0, DAC_CTRL, 0, 0x03, 0),
+ };
+ 
+-static int __devinit snd_at73c213_mixer(struct snd_at73c213 *chip)
++static int snd_at73c213_mixer(struct snd_at73c213 *chip)
+ {
+ 	struct snd_card *card;
+ 	int errval, idx;
+@@ -744,7 +744,7 @@ static int __devinit snd_at73c213_mixer(struct snd_at73c213 *chip)
+ /*
+  * Device functions
+  */
+-static int __devinit snd_at73c213_ssc_init(struct snd_at73c213 *chip)
++static int snd_at73c213_ssc_init(struct snd_at73c213 *chip)
+ {
+ 	/*
+ 	 * Continuous clock output.
+@@ -774,7 +774,7 @@ static int __devinit snd_at73c213_ssc_init(struct snd_at73c213 *chip)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_at73c213_chip_init(struct snd_at73c213 *chip)
++static int snd_at73c213_chip_init(struct snd_at73c213 *chip)
+ {
+ 	int retval;
+ 	unsigned char dac_ctrl = 0;
+@@ -879,8 +879,8 @@ static int snd_at73c213_dev_free(struct snd_device *device)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_at73c213_dev_init(struct snd_card *card,
+-					 struct spi_device *spi)
++static int snd_at73c213_dev_init(struct snd_card *card,
++				 struct spi_device *spi)
+ {
+ 	static struct snd_device_ops ops = {
+ 		.dev_free	= snd_at73c213_dev_free,
+@@ -940,7 +940,7 @@ static int __devinit snd_at73c213_dev_init(struct snd_card *card,
+ 	return retval;
+ }
+ 
+-static int __devinit snd_at73c213_probe(struct spi_device *spi)
++static int snd_at73c213_probe(struct spi_device *spi)
+ {
+ 	struct snd_card			*card;
+ 	struct snd_at73c213		*chip;
+@@ -1007,7 +1007,7 @@ static int __devinit snd_at73c213_probe(struct spi_device *spi)
+ 	return retval;
+ }
+ 
+-static int __devexit snd_at73c213_remove(struct spi_device *spi)
++static int snd_at73c213_remove(struct spi_device *spi)
+ {
+ 	struct snd_card *card = dev_get_drvdata(&spi->dev);
+ 	struct snd_at73c213 *chip = card->private_data;
+@@ -1109,7 +1109,7 @@ static struct spi_driver at73c213_driver = {
+ 	.probe		= snd_at73c213_probe,
+ 	.suspend	= snd_at73c213_suspend,
+ 	.resume		= snd_at73c213_resume,
+-	.remove		= __devexit_p(snd_at73c213_remove),
++	.remove		= snd_at73c213_remove,
+ };
+ 
+ module_spi_driver(at73c213_driver);

commit 32e02a7b690f22b2f56efac929d7c300994ddc4c
+Author: Bill Pemberton 
+Date:   Thu Dec 6 12:35:25 2012 -0500
+
+    ALSA: sparc: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c
+index 5701787c0e6b..174d21fb56e2 100644
+--- a/sound/sparc/amd7930.c
++++ b/sound/sparc/amd7930.c
+@@ -755,7 +755,7 @@ static struct snd_pcm_ops snd_amd7930_capture_ops = {
+ 	.pointer	=	snd_amd7930_capture_pointer,
+ };
+ 
+-static int __devinit snd_amd7930_pcm(struct snd_amd7930 *amd)
++static int snd_amd7930_pcm(struct snd_amd7930 *amd)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -854,7 +854,7 @@ static int snd_amd7930_put_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new amd7930_controls[] __devinitdata = {
++static struct snd_kcontrol_new amd7930_controls[] = {
+ 	{
+ 		.iface		=	SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name		=	"Monitor Volume",
+@@ -884,7 +884,7 @@ static struct snd_kcontrol_new amd7930_controls[] __devinitdata = {
+ 	},
+ };
+ 
+-static int __devinit snd_amd7930_mixer(struct snd_amd7930 *amd)
++static int snd_amd7930_mixer(struct snd_amd7930 *amd)
+ {
+ 	struct snd_card *card;
+ 	int idx, err;
+@@ -933,10 +933,10 @@ static struct snd_device_ops snd_amd7930_dev_ops = {
+ 	.dev_free	=	snd_amd7930_dev_free,
+ };
+ 
+-static int __devinit snd_amd7930_create(struct snd_card *card,
+-					struct platform_device *op,
+-					int irq, int dev,
+-					struct snd_amd7930 **ramd)
++static int snd_amd7930_create(struct snd_card *card,
++			      struct platform_device *op,
++			      int irq, int dev,
++			      struct snd_amd7930 **ramd)
+ {
+ 	struct snd_amd7930 *amd;
+ 	unsigned long flags;
+@@ -1002,7 +1002,7 @@ static int __devinit snd_amd7930_create(struct snd_card *card,
+ 	return 0;
+ }
+ 
+-static int __devinit amd7930_sbus_probe(struct platform_device *op)
++static int amd7930_sbus_probe(struct platform_device *op)
+ {
+ 	struct resource *rp = &op->resource[0];
+ 	static int dev_num;
+diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c
+index f2eabd3f22fd..54aaad2a10f5 100644
+--- a/sound/sparc/cs4231.c
++++ b/sound/sparc/cs4231.c
+@@ -702,7 +702,7 @@ static int snd_cs4231_timer_stop(struct snd_timer *timer)
+ 	return 0;
+ }
+ 
+-static void __devinit snd_cs4231_init(struct snd_cs4231 *chip)
++static void snd_cs4231_init(struct snd_cs4231 *chip)
+ {
+ 	unsigned long flags;
+ 
+@@ -1019,7 +1019,7 @@ static snd_pcm_uframes_t snd_cs4231_capture_pointer(
+ 	return bytes_to_frames(substream->runtime, ptr);
+ }
+ 
+-static int __devinit snd_cs4231_probe(struct snd_cs4231 *chip)
++static int snd_cs4231_probe(struct snd_cs4231 *chip)
+ {
+ 	unsigned long flags;
+ 	int i;
+@@ -1218,7 +1218,7 @@ static struct snd_pcm_ops snd_cs4231_capture_ops = {
+ 	.pointer	=	snd_cs4231_capture_pointer,
+ };
+ 
+-static int __devinit snd_cs4231_pcm(struct snd_card *card)
++static int snd_cs4231_pcm(struct snd_card *card)
+ {
+ 	struct snd_cs4231 *chip = card->private_data;
+ 	struct snd_pcm *pcm;
+@@ -1247,7 +1247,7 @@ static int __devinit snd_cs4231_pcm(struct snd_card *card)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_cs4231_timer(struct snd_card *card)
++static int snd_cs4231_timer(struct snd_card *card)
+ {
+ 	struct snd_cs4231 *chip = card->private_data;
+ 	struct snd_timer *timer;
+@@ -1498,7 +1498,7 @@ static int snd_cs4231_put_double(struct snd_kcontrol *kcontrol,
+   .private_value = (left_reg) | ((right_reg) << 8) | ((shift_left) << 16) | \
+ 		   ((shift_right) << 19) | ((mask) << 24) | ((invert) << 22) }
+ 
+-static struct snd_kcontrol_new snd_cs4231_controls[] __devinitdata = {
++static struct snd_kcontrol_new snd_cs4231_controls[] = {
+ CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT,
+ 		CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
+ CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT,
+@@ -1537,7 +1537,7 @@ CS4231_SINGLE("Line Out Switch", 0, CS4231_PIN_CTRL, 6, 1, 1),
+ CS4231_SINGLE("Headphone Out Switch", 0, CS4231_PIN_CTRL, 7, 1, 1)
+ };
+ 
+-static int __devinit snd_cs4231_mixer(struct snd_card *card)
++static int snd_cs4231_mixer(struct snd_card *card)
+ {
+ 	struct snd_cs4231 *chip = card->private_data;
+ 	int err, idx;
+@@ -1558,7 +1558,7 @@ static int __devinit snd_cs4231_mixer(struct snd_card *card)
+ 
+ static int dev;
+ 
+-static int __devinit cs4231_attach_begin(struct snd_card **rcard)
++static int cs4231_attach_begin(struct snd_card **rcard)
+ {
+ 	struct snd_card *card;
+ 	struct snd_cs4231 *chip;
+@@ -1589,7 +1589,7 @@ static int __devinit cs4231_attach_begin(struct snd_card **rcard)
+ 	return 0;
+ }
+ 
+-static int __devinit cs4231_attach_finish(struct snd_card *card)
++static int cs4231_attach_finish(struct snd_card *card)
+ {
+ 	struct snd_cs4231 *chip = card->private_data;
+ 	int err;
+@@ -1793,9 +1793,9 @@ static struct snd_device_ops snd_cs4231_sbus_dev_ops = {
+ 	.dev_free	=	snd_cs4231_sbus_dev_free,
+ };
+ 
+-static int __devinit snd_cs4231_sbus_create(struct snd_card *card,
+-					    struct platform_device *op,
+-					    int dev)
++static int snd_cs4231_sbus_create(struct snd_card *card,
++				  struct platform_device *op,
++				  int dev)
+ {
+ 	struct snd_cs4231 *chip = card->private_data;
+ 	int err;
+@@ -1856,7 +1856,7 @@ static int __devinit snd_cs4231_sbus_create(struct snd_card *card,
+ 	return 0;
+ }
+ 
+-static int __devinit cs4231_sbus_probe(struct platform_device *op)
++static int cs4231_sbus_probe(struct platform_device *op)
+ {
+ 	struct resource *rp = &op->resource[0];
+ 	struct snd_card *card;
+@@ -1959,9 +1959,9 @@ static struct snd_device_ops snd_cs4231_ebus_dev_ops = {
+ 	.dev_free	=	snd_cs4231_ebus_dev_free,
+ };
+ 
+-static int __devinit snd_cs4231_ebus_create(struct snd_card *card,
+-					    struct platform_device *op,
+-					    int dev)
++static int snd_cs4231_ebus_create(struct snd_card *card,
++				  struct platform_device *op,
++				  int dev)
+ {
+ 	struct snd_cs4231 *chip = card->private_data;
+ 	int err;
+@@ -2048,7 +2048,7 @@ static int __devinit snd_cs4231_ebus_create(struct snd_card *card,
+ 	return 0;
+ }
+ 
+-static int __devinit cs4231_ebus_probe(struct platform_device *op)
++static int cs4231_ebus_probe(struct platform_device *op)
+ {
+ 	struct snd_card *card;
+ 	int err;
+@@ -2072,7 +2072,7 @@ static int __devinit cs4231_ebus_probe(struct platform_device *op)
+ }
+ #endif
+ 
+-static int __devinit cs4231_probe(struct platform_device *op)
++static int cs4231_probe(struct platform_device *op)
+ {
+ #ifdef EBUS_SUPPORT
+ 	if (!strcmp(op->dev.of_node->parent->name, "ebus"))
+@@ -2086,7 +2086,7 @@ static int __devinit cs4231_probe(struct platform_device *op)
+ 	return -ENODEV;
+ }
+ 
+-static int __devexit cs4231_remove(struct platform_device *op)
++static int cs4231_remove(struct platform_device *op)
+ {
+ 	struct snd_cs4231 *chip = dev_get_drvdata(&op->dev);
+ 
+@@ -2115,7 +2115,7 @@ static struct platform_driver cs4231_driver = {
+ 		.of_match_table = cs4231_match,
+ 	},
+ 	.probe		= cs4231_probe,
+-	.remove		= __devexit_p(cs4231_remove),
++	.remove		= cs4231_remove,
+ };
+ 
+ module_platform_driver(cs4231_driver);
+diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c
+index ae35f5342e10..75e6016d3efe 100644
+--- a/sound/sparc/dbri.c
++++ b/sound/sparc/dbri.c
+@@ -745,7 +745,7 @@ static void dbri_reset(struct snd_dbri *dbri)
+ }
+ 
+ /* Lock must not be held before calling this */
+-static void __devinit dbri_initialize(struct snd_dbri *dbri)
++static void dbri_initialize(struct snd_dbri *dbri)
+ {
+ 	s32 *cmd;
+ 	u32 dma_addr;
+@@ -1305,7 +1305,7 @@ to the DBRI via the CHI interface and few of the DBRI's PIO pins.
+  * Lock must not be held before calling it.
+ 
+ */
+-static __devinit void cs4215_setup_pipes(struct snd_dbri *dbri)
++static void cs4215_setup_pipes(struct snd_dbri *dbri)
+ {
+ 	unsigned long flags;
+ 
+@@ -1338,7 +1338,7 @@ static __devinit void cs4215_setup_pipes(struct snd_dbri *dbri)
+ 	dbri_cmdwait(dbri);
+ }
+ 
+-static __devinit int cs4215_init_data(struct cs4215 *mm)
++static int cs4215_init_data(struct cs4215 *mm)
+ {
+ 	/*
+ 	 * No action, memory resetting only.
+@@ -1630,7 +1630,7 @@ static int cs4215_prepare(struct snd_dbri *dbri, unsigned int rate,
+ /*
+  *
+  */
+-static __devinit int cs4215_init(struct snd_dbri *dbri)
++static int cs4215_init(struct snd_dbri *dbri)
+ {
+ 	u32 reg2 = sbus_readl(dbri->regs + REG2);
+ 	dprintk(D_MM, "cs4215_init: reg2=0x%x\n", reg2);
+@@ -2217,7 +2217,7 @@ static struct snd_pcm_ops snd_dbri_ops = {
+ 	.pointer = snd_dbri_pointer,
+ };
+ 
+-static int __devinit snd_dbri_pcm(struct snd_card *card)
++static int snd_dbri_pcm(struct snd_card *card)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -2409,7 +2409,7 @@ static int snd_cs4215_put_single(struct snd_kcontrol *kcontrol,
+   .private_value = (entry) | ((shift) << 8) | ((mask) << 16) |	\
+ 			((invert) << 24) },
+ 
+-static struct snd_kcontrol_new dbri_controls[] __devinitdata = {
++static struct snd_kcontrol_new dbri_controls[] = {
+ 	{
+ 	 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	 .name  = "Playback Volume",
+@@ -2436,7 +2436,7 @@ static struct snd_kcontrol_new dbri_controls[] __devinitdata = {
+ 	CS4215_SINGLE("Mic boost", 4, 4, 1, 1)
+ };
+ 
+-static int __devinit snd_dbri_mixer(struct snd_card *card)
++static int snd_dbri_mixer(struct snd_card *card)
+ {
+ 	int idx, err;
+ 	struct snd_dbri *dbri;
+@@ -2500,7 +2500,7 @@ static void dbri_debug_read(struct snd_info_entry *entry,
+ }
+ #endif
+ 
+-static void __devinit snd_dbri_proc(struct snd_card *card)
++static void snd_dbri_proc(struct snd_card *card)
+ {
+ 	struct snd_dbri *dbri = card->private_data;
+ 	struct snd_info_entry *entry;
+@@ -2523,9 +2523,9 @@ static void __devinit snd_dbri_proc(struct snd_card *card)
+ */
+ static void snd_dbri_free(struct snd_dbri *dbri);
+ 
+-static int __devinit snd_dbri_create(struct snd_card *card,
+-				     struct platform_device *op,
+-				     int irq, int dev)
++static int snd_dbri_create(struct snd_card *card,
++			   struct platform_device *op,
++			   int irq, int dev)
+ {
+ 	struct snd_dbri *dbri = card->private_data;
+ 	int err;
+@@ -2593,7 +2593,7 @@ static void snd_dbri_free(struct snd_dbri *dbri)
+ 				  (void *)dbri->dma, dbri->dma_dvma);
+ }
+ 
+-static int __devinit dbri_probe(struct platform_device *op)
++static int dbri_probe(struct platform_device *op)
+ {
+ 	struct snd_dbri *dbri;
+ 	struct resource *rp;
+@@ -2663,7 +2663,7 @@ static int __devinit dbri_probe(struct platform_device *op)
+ 	return err;
+ }
+ 
+-static int __devexit dbri_remove(struct platform_device *op)
++static int dbri_remove(struct platform_device *op)
+ {
+ 	struct snd_card *card = dev_get_drvdata(&op->dev);
+ 
+@@ -2694,7 +2694,7 @@ static struct platform_driver dbri_sbus_driver = {
+ 		.of_match_table = dbri_match,
+ 	},
+ 	.probe		= dbri_probe,
+-	.remove		= __devexit_p(dbri_remove),
++	.remove		= dbri_remove,
+ };
+ 
+ module_platform_driver(dbri_sbus_driver);

commit e74033a858bf36d5763eafea600e07fc917e3592
+Author: Bill Pemberton 
+Date:   Thu Dec 6 12:35:24 2012 -0500
+
+    ALSA: sh: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/sh/aica.c b/sound/sh/aica.c
+index d48b523207eb..e59a73a9bc42 100644
+--- a/sound/sh/aica.c
++++ b/sound/sh/aica.c
+@@ -540,7 +540,7 @@ static int aica_pcmvolume_put(struct snd_kcontrol *kcontrol,
+ 	return 1;
+ }
+ 
+-static struct snd_kcontrol_new snd_aica_pcmswitch_control __devinitdata = {
++static struct snd_kcontrol_new snd_aica_pcmswitch_control = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "PCM Playback Switch",
+ 	.index = 0,
+@@ -549,7 +549,7 @@ static struct snd_kcontrol_new snd_aica_pcmswitch_control __devinitdata = {
+ 	.put = aica_pcmswitch_put
+ };
+ 
+-static struct snd_kcontrol_new snd_aica_pcmvolume_control __devinitdata = {
++static struct snd_kcontrol_new snd_aica_pcmvolume_control = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "PCM Playback Volume",
+ 	.index = 0,
+@@ -574,8 +574,7 @@ static int load_aica_firmware(void)
+ 	return err;
+ }
+ 
+-static int __devinit add_aicamixer_controls(struct snd_card_aica
+-					    *dreamcastcard)
++static int add_aicamixer_controls(struct snd_card_aica *dreamcastcard)
+ {
+ 	int err;
+ 	err = snd_ctl_add
+@@ -591,7 +590,7 @@ static int __devinit add_aicamixer_controls(struct snd_card_aica
+ 	return 0;
+ }
+ 
+-static int __devexit snd_aica_remove(struct platform_device *devptr)
++static int snd_aica_remove(struct platform_device *devptr)
+ {
+ 	struct snd_card_aica *dreamcastcard;
+ 	dreamcastcard = platform_get_drvdata(devptr);
+@@ -603,7 +602,7 @@ static int __devexit snd_aica_remove(struct platform_device *devptr)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_aica_probe(struct platform_device *devptr)
++static int snd_aica_probe(struct platform_device *devptr)
+ {
+ 	int err;
+ 	struct snd_card_aica *dreamcastcard;
+@@ -652,7 +651,7 @@ static int __devinit snd_aica_probe(struct platform_device *devptr)
+ 
+ static struct platform_driver snd_aica_driver = {
+ 	.probe = snd_aica_probe,
+-	.remove = __devexit_p(snd_aica_remove),
++	.remove = snd_aica_remove,
+ 	.driver = {
+ 		.name = SND_AICA_DRIVER,
+ 		.owner	= THIS_MODULE,
+diff --git a/sound/sh/sh_dac_audio.c b/sound/sh/sh_dac_audio.c
+index 0a3394751ed2..e68c4fc91a03 100644
+--- a/sound/sh/sh_dac_audio.c
++++ b/sound/sh/sh_dac_audio.c
+@@ -261,7 +261,7 @@ static struct snd_pcm_ops snd_sh_dac_pcm_ops = {
+ 	.mmap		= snd_pcm_lib_mmap_iomem,
+ };
+ 
+-static int __devinit snd_sh_dac_pcm(struct snd_sh_dac *chip, int device)
++static int snd_sh_dac_pcm(struct snd_sh_dac *chip, int device)
+ {
+ 	int err;
+ 	struct snd_pcm *pcm;
+@@ -346,9 +346,9 @@ static enum hrtimer_restart sh_dac_audio_timer(struct hrtimer *handle)
+ }
+ 
+ /* create  --  chip-specific constructor for the cards components */
+-static int __devinit snd_sh_dac_create(struct snd_card *card,
+-				       struct platform_device *devptr,
+-				       struct snd_sh_dac **rchip)
++static int snd_sh_dac_create(struct snd_card *card,
++			     struct platform_device *devptr,
++			     struct snd_sh_dac **rchip)
+ {
+ 	struct snd_sh_dac *chip;
+ 	int err;
+@@ -392,7 +392,7 @@ static int __devinit snd_sh_dac_create(struct snd_card *card,
+ }
+ 
+ /* driver .probe  --  constructor */
+-static int __devinit snd_sh_dac_probe(struct platform_device *devptr)
++static int snd_sh_dac_probe(struct platform_device *devptr)
+ {
+ 	struct snd_sh_dac *chip;
+ 	struct snd_card *card;

commit 15afafc2565bc785eb7a440b8b4a53f77910cf04
+Author: Bill Pemberton 
+Date:   Thu Dec 6 12:35:23 2012 -0500
+
+    ALSA: ppc: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c
+index b36679384b27..5fbf5db2543d 100644
+--- a/sound/ppc/awacs.c
++++ b/sound/ppc/awacs.c
+@@ -477,7 +477,7 @@ static int snd_pmac_awacs_put_master_amp(struct snd_kcontrol *kcontrol,
+ #define AMP_CH_SPK	0
+ #define AMP_CH_HD	1
+ 
+-static struct snd_kcontrol_new snd_pmac_awacs_amp_vol[] __devinitdata = {
++static struct snd_kcontrol_new snd_pmac_awacs_amp_vol[] = {
+ 	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	  .name = "Speaker Playback Volume",
+ 	  .info = snd_pmac_awacs_info_volume_amp,
+@@ -514,7 +514,7 @@ static struct snd_kcontrol_new snd_pmac_awacs_amp_vol[] __devinitdata = {
+ 	},
+ };
+ 
+-static struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw __devinitdata = {
++static struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "Headphone Playback Switch",
+ 	.info = snd_pmac_boolean_stereo_info,
+@@ -523,7 +523,7 @@ static struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw __devinitdata = {
+ 	.private_value = AMP_CH_HD,
+ };
+ 
+-static struct snd_kcontrol_new snd_pmac_awacs_amp_spk_sw __devinitdata = {
++static struct snd_kcontrol_new snd_pmac_awacs_amp_spk_sw = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "Speaker Playback Switch",
+ 	.info = snd_pmac_boolean_stereo_info,
+@@ -595,46 +595,46 @@ static int snd_pmac_screamer_mic_boost_put(struct snd_kcontrol *kcontrol,
+ /*
+  * lists of mixer elements
+  */
+-static struct snd_kcontrol_new snd_pmac_awacs_mixers[] __devinitdata = {
++static struct snd_kcontrol_new snd_pmac_awacs_mixers[] = {
+ 	AWACS_SWITCH("Master Capture Switch", 1, SHIFT_LOOPTHRU, 0),
+ 	AWACS_VOLUME("Master Capture Volume", 0, 4, 0),
+ /*	AWACS_SWITCH("Unknown Playback Switch", 6, SHIFT_PAROUT0, 0), */
+ };
+ 
+-static struct snd_kcontrol_new snd_pmac_screamer_mixers_beige[] __devinitdata = {
++static struct snd_kcontrol_new snd_pmac_screamer_mixers_beige[] = {
+ 	AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
+ 	AWACS_VOLUME("Play-through Playback Volume", 5, 6, 1),
+ 	AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
+ 	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_LINE, 0),
+ };
+ 
+-static struct snd_kcontrol_new snd_pmac_screamer_mixers_lo[] __devinitdata = {
++static struct snd_kcontrol_new snd_pmac_screamer_mixers_lo[] = {
+ 	AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
+ };
+ 
+-static struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] __devinitdata = {
++static struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] = {
+ 	AWACS_VOLUME("Play-through Playback Volume", 5, 6, 1),
+ 	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
+ };
+ 
+-static struct snd_kcontrol_new snd_pmac_screamer_mixers_g4agp[] __devinitdata = {
++static struct snd_kcontrol_new snd_pmac_screamer_mixers_g4agp[] = {
+ 	AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
+ 	AWACS_VOLUME("Master Playback Volume", 5, 6, 1),
+ 	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
+ 	AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
+ };
+ 
+-static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac7500[] __devinitdata = {
++static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac7500[] = {
+ 	AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
+ 	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
+ 	AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
+ };
+ 
+-static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac5500[] __devinitdata = {
++static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac5500[] = {
+ 	AWACS_VOLUME("Headphone Playback Volume", 2, 6, 1),
+ };
+ 
+-static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac[] __devinitdata = {
++static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac[] = {
+ 	AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
+ 	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
+ };
+@@ -642,34 +642,34 @@ static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac[] __devinitdata = {
+ /* FIXME: is this correct order?
+  * screamer (powerbook G3 pismo) seems to have different bits...
+  */
+-static struct snd_kcontrol_new snd_pmac_awacs_mixers2[] __devinitdata = {
++static struct snd_kcontrol_new snd_pmac_awacs_mixers2[] = {
+ 	AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_LINE, 0),
+ 	AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_MIC, 0),
+ };
+ 
+-static struct snd_kcontrol_new snd_pmac_screamer_mixers2[] __devinitdata = {
++static struct snd_kcontrol_new snd_pmac_screamer_mixers2[] = {
+ 	AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
+ 	AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_LINE, 0),
+ };
+ 
+-static struct snd_kcontrol_new snd_pmac_awacs_mixers2_pmac5500[] __devinitdata = {
++static struct snd_kcontrol_new snd_pmac_awacs_mixers2_pmac5500[] = {
+ 	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
+ };
+ 
+-static struct snd_kcontrol_new snd_pmac_awacs_master_sw __devinitdata =
++static struct snd_kcontrol_new snd_pmac_awacs_master_sw =
+ AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1);
+ 
+-static struct snd_kcontrol_new snd_pmac_awacs_master_sw_imac __devinitdata =
++static struct snd_kcontrol_new snd_pmac_awacs_master_sw_imac =
+ AWACS_SWITCH("Line out Playback Switch", 1, SHIFT_HDMUTE, 1);
+ 
+-static struct snd_kcontrol_new snd_pmac_awacs_master_sw_pmac5500 __devinitdata =
++static struct snd_kcontrol_new snd_pmac_awacs_master_sw_pmac5500 =
+ AWACS_SWITCH("Headphone Playback Switch", 1, SHIFT_HDMUTE, 1);
+ 
+-static struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] __devinitdata = {
++static struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] = {
+ 	AWACS_SWITCH("Mic Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
+ };
+ 
+-static struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] __devinitdata = {
++static struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] = {
+ 	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	  .name = "Mic Boost Capture Volume",
+ 	  .info = snd_pmac_screamer_mic_boost_info,
+@@ -678,34 +678,34 @@ static struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] __devinitdata = {
+ 	},
+ };
+ 
+-static struct snd_kcontrol_new snd_pmac_awacs_mic_boost_pmac7500[] __devinitdata =
++static struct snd_kcontrol_new snd_pmac_awacs_mic_boost_pmac7500[] =
+ {
+ 	AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
+ };
+ 
+-static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_beige[] __devinitdata =
++static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_beige[] =
+ {
+ 	AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
+ 	AWACS_SWITCH("CD Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0),
+ };
+ 
+-static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_imac[] __devinitdata =
++static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_imac[] =
+ {
+ 	AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
+ 	AWACS_SWITCH("Mic Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0),
+ };
+ 
+-static struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] __devinitdata = {
++static struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] = {
+ 	AWACS_VOLUME("Speaker Playback Volume", 4, 6, 1),
+ };
+ 
+-static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw __devinitdata =
++static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw =
+ AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1);
+ 
+-static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac1 __devinitdata =
++static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac1 =
+ AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_PAROUT1, 1);
+ 
+-static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac2 __devinitdata =
++static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac2 =
+ AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_PAROUT1, 0);
+ 
+ 
+@@ -872,7 +872,7 @@ static void snd_pmac_awacs_update_automute(struct snd_pmac *chip, int do_notify)
+ /*
+  * initialize chip
+  */
+-int __devinit
++int
+ snd_pmac_awacs_init(struct snd_pmac *chip)
+ {
+ 	int pm7500 = IS_PM7500;
+diff --git a/sound/ppc/beep.c b/sound/ppc/beep.c
+index a9d350789f55..0040f048221f 100644
+--- a/sound/ppc/beep.c
++++ b/sound/ppc/beep.c
+@@ -215,7 +215,7 @@ static struct snd_kcontrol_new snd_pmac_beep_mixer = {
+ };
+ 
+ /* Initialize beep stuff */
+-int __devinit snd_pmac_attach_beep(struct snd_pmac *chip)
++int snd_pmac_attach_beep(struct snd_pmac *chip)
+ {
+ 	struct pmac_beep *beep;
+ 	struct input_dev *input_dev;
+diff --git a/sound/ppc/burgundy.c b/sound/ppc/burgundy.c
+index 00e2d5166d0a..cb4f0a5e984e 100644
+--- a/sound/ppc/burgundy.c
++++ b/sound/ppc/burgundy.c
+@@ -467,7 +467,7 @@ static int snd_pmac_burgundy_put_switch_b(struct snd_kcontrol *kcontrol,
+ /*
+  * Burgundy mixers
+  */
+-static struct snd_kcontrol_new snd_pmac_burgundy_mixers[] __devinitdata = {
++static struct snd_kcontrol_new snd_pmac_burgundy_mixers[] = {
+ 	BURGUNDY_VOLUME_W("Master Playback Volume", 0,
+ 			MASK_ADDR_BURGUNDY_MASTER_VOLUME, 8),
+ 	BURGUNDY_VOLUME_W("CD Capture Volume", 0,
+@@ -495,7 +495,7 @@ static struct snd_kcontrol_new snd_pmac_burgundy_mixers[] __devinitdata = {
+  */	BURGUNDY_SWITCH_B("PCM Capture Switch", 0,
+ 			MASK_ADDR_BURGUNDY_HOSTIFEH, 0x01, 0, 0)
+ };
+-static struct snd_kcontrol_new snd_pmac_burgundy_mixers_imac[] __devinitdata = {
++static struct snd_kcontrol_new snd_pmac_burgundy_mixers_imac[] = {
+ 	BURGUNDY_VOLUME_W("Line in Capture Volume", 0,
+ 			MASK_ADDR_BURGUNDY_VOLLINE, 16),
+ 	BURGUNDY_VOLUME_W("Mic Capture Volume", 0,
+@@ -521,7 +521,7 @@ static struct snd_kcontrol_new snd_pmac_burgundy_mixers_imac[] __devinitdata = {
+ 	BURGUNDY_SWITCH_B("Mic Boost Capture Switch", 0,
+ 			MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1)
+ };
+-static struct snd_kcontrol_new snd_pmac_burgundy_mixers_pmac[] __devinitdata = {
++static struct snd_kcontrol_new snd_pmac_burgundy_mixers_pmac[] = {
+ 	BURGUNDY_VOLUME_W("Line in Capture Volume", 0,
+ 			MASK_ADDR_BURGUNDY_VOLMIC, 16),
+ 	BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0,
+@@ -537,33 +537,33 @@ static struct snd_kcontrol_new snd_pmac_burgundy_mixers_pmac[] __devinitdata = {
+ /*	BURGUNDY_SWITCH_B("Line in Boost Capture Switch", 0,
+  *		MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1) */
+ };
+-static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_imac __devinitdata =
++static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_imac =
+ BURGUNDY_SWITCH_B("Master Playback Switch", 0,
+ 	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+ 	BURGUNDY_OUTPUT_LEFT | BURGUNDY_LINEOUT_LEFT | BURGUNDY_HP_LEFT,
+ 	BURGUNDY_OUTPUT_RIGHT | BURGUNDY_LINEOUT_RIGHT | BURGUNDY_HP_RIGHT, 1);
+-static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_pmac __devinitdata =
++static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_pmac =
+ BURGUNDY_SWITCH_B("Master Playback Switch", 0,
+ 	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+ 	BURGUNDY_OUTPUT_INTERN
+ 	| BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
+-static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_imac __devinitdata =
++static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_imac =
+ BURGUNDY_SWITCH_B("Speaker Playback Switch", 0,
+ 	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+ 	BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
+-static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_pmac __devinitdata =
++static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_pmac =
+ BURGUNDY_SWITCH_B("Speaker Playback Switch", 0,
+ 	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+ 	BURGUNDY_OUTPUT_INTERN, 0, 0);
+-static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_imac __devinitdata =
++static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_imac =
+ BURGUNDY_SWITCH_B("Line out Playback Switch", 0,
+ 	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+ 	BURGUNDY_LINEOUT_LEFT, BURGUNDY_LINEOUT_RIGHT, 1);
+-static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_pmac __devinitdata =
++static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_pmac =
+ BURGUNDY_SWITCH_B("Line out Playback Switch", 0,
+ 	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+ 	BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
+-static struct snd_kcontrol_new snd_pmac_burgundy_hp_sw_imac __devinitdata =
++static struct snd_kcontrol_new snd_pmac_burgundy_hp_sw_imac =
+ BURGUNDY_SWITCH_B("Headphone Playback Switch", 0,
+ 	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+ 	BURGUNDY_HP_LEFT, BURGUNDY_HP_RIGHT, 1);
+@@ -617,7 +617,7 @@ static void snd_pmac_burgundy_update_automute(struct snd_pmac *chip, int do_noti
+ /*
+  * initialize burgundy
+  */
+-int __devinit snd_pmac_burgundy_init(struct snd_pmac *chip)
++int snd_pmac_burgundy_init(struct snd_pmac *chip)
+ {
+ 	int imac = of_machine_is_compatible("iMac");
+ 	int i, err;
+diff --git a/sound/ppc/daca.c b/sound/ppc/daca.c
+index 24200b7bdace..b86526223e4e 100644
+--- a/sound/ppc/daca.c
++++ b/sound/ppc/daca.c
+@@ -244,7 +244,7 @@ static void daca_cleanup(struct snd_pmac *chip)
+ }
+ 
+ /* exported */
+-int __devinit snd_pmac_daca_init(struct snd_pmac *chip)
++int snd_pmac_daca_init(struct snd_pmac *chip)
+ {
+ 	int i, err;
+ 	struct pmac_daca *mix;
+diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c
+index 4080becf4cef..01aecc2b5073 100644
+--- a/sound/ppc/keywest.c
++++ b/sound/ppc/keywest.c
+@@ -115,7 +115,7 @@ void snd_pmac_keywest_cleanup(struct pmac_keywest *i2c)
+ 	}
+ }
+ 
+-int __devinit snd_pmac_tumbler_post_init(void)
++int snd_pmac_tumbler_post_init(void)
+ {
+ 	int err;
+ 	
+@@ -130,7 +130,7 @@ int __devinit snd_pmac_tumbler_post_init(void)
+ }
+ 
+ /* exported */
+-int __devinit snd_pmac_keywest_init(struct pmac_keywest *i2c)
++int snd_pmac_keywest_init(struct pmac_keywest *i2c)
+ {
+ 	int err;
+ 
+diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
+index ab96cde7417b..c93fbbb201fe 100644
+--- a/sound/ppc/pmac.c
++++ b/sound/ppc/pmac.c
+@@ -702,7 +702,7 @@ static struct snd_pcm_ops snd_pmac_capture_ops = {
+ 	.pointer =	snd_pmac_capture_pointer,
+ };
+ 
+-int __devinit snd_pmac_pcm_new(struct snd_pmac *chip)
++int snd_pmac_pcm_new(struct snd_pmac *chip)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -907,7 +907,7 @@ static int snd_pmac_dev_free(struct snd_device *device)
+  * check the machine support byteswap (little-endian)
+  */
+ 
+-static void __devinit detect_byte_swap(struct snd_pmac *chip)
++static void detect_byte_swap(struct snd_pmac *chip)
+ {
+ 	struct device_node *mio;
+ 
+@@ -933,7 +933,7 @@ static void __devinit detect_byte_swap(struct snd_pmac *chip)
+ /*
+  * detect a sound chip
+  */
+-static int __devinit snd_pmac_detect(struct snd_pmac *chip)
++static int snd_pmac_detect(struct snd_pmac *chip)
+ {
+ 	struct device_node *sound;
+ 	struct device_node *dn;
+@@ -1146,7 +1146,7 @@ static int pmac_hp_detect_get(struct snd_kcontrol *kcontrol,
+ 	return 0;
+ }
+ 
+-static struct snd_kcontrol_new auto_mute_controls[] __devinitdata = {
++static struct snd_kcontrol_new auto_mute_controls[] = {
+ 	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	  .name = "Auto Mute Switch",
+ 	  .info = snd_pmac_boolean_mono_info,
+@@ -1161,7 +1161,7 @@ static struct snd_kcontrol_new auto_mute_controls[] __devinitdata = {
+ 	},
+ };
+ 
+-int __devinit snd_pmac_add_automute(struct snd_pmac *chip)
++int snd_pmac_add_automute(struct snd_pmac *chip)
+ {
+ 	int err;
+ 	chip->auto_mute = 1;
+@@ -1178,7 +1178,7 @@ int __devinit snd_pmac_add_automute(struct snd_pmac *chip)
+ /*
+  * create and detect a pmac chip record
+  */
+-int __devinit snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return)
++int snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return)
+ {
+ 	struct snd_pmac *chip;
+ 	struct device_node *np;
+diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c
+index 210cafe04890..09fc848d32ec 100644
+--- a/sound/ppc/powermac.c
++++ b/sound/ppc/powermac.c
+@@ -51,7 +51,7 @@ static struct platform_device *device;
+ /*
+  */
+ 
+-static int __devinit snd_pmac_probe(struct platform_device *devptr)
++static int snd_pmac_probe(struct platform_device *devptr)
+ {
+ 	struct snd_card *card;
+ 	struct snd_pmac *chip;
+@@ -136,7 +136,7 @@ static int __devinit snd_pmac_probe(struct platform_device *devptr)
+ }
+ 
+ 
+-static int __devexit snd_pmac_remove(struct platform_device *devptr)
++static int snd_pmac_remove(struct platform_device *devptr)
+ {
+ 	snd_card_free(platform_get_drvdata(devptr));
+ 	platform_set_drvdata(devptr, NULL);
+@@ -168,7 +168,7 @@ static SIMPLE_DEV_PM_OPS(snd_pmac_pm, snd_pmac_driver_suspend, snd_pmac_driver_r
+ 
+ static struct platform_driver snd_pmac_driver = {
+ 	.probe		= snd_pmac_probe,
+-	.remove		= __devexit_p(snd_pmac_remove),
++	.remove		= snd_pmac_remove,
+ 	.driver		= {
+ 		.name	= SND_PMAC_DRIVER,
+ 		.owner	= THIS_MODULE,
+diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
+index 9cea84c3e0c6..b23354a4ceca 100644
+--- a/sound/ppc/tumbler.c
++++ b/sound/ppc/tumbler.c
+@@ -844,7 +844,7 @@ static int snapper_put_capture_source(struct snd_kcontrol *kcontrol,
+ 
+ /*
+  */
+-static struct snd_kcontrol_new tumbler_mixers[] __devinitdata = {
++static struct snd_kcontrol_new tumbler_mixers[] = {
+ 	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	  .name = "Master Playback Volume",
+ 	  .info = tumbler_info_master_volume,
+@@ -868,7 +868,7 @@ static struct snd_kcontrol_new tumbler_mixers[] __devinitdata = {
+ 	},
+ };
+ 
+-static struct snd_kcontrol_new snapper_mixers[] __devinitdata = {
++static struct snd_kcontrol_new snapper_mixers[] = {
+ 	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	  .name = "Master Playback Volume",
+ 	  .info = tumbler_info_master_volume,
+@@ -901,7 +901,7 @@ static struct snd_kcontrol_new snapper_mixers[] __devinitdata = {
+ 	},
+ };
+ 
+-static struct snd_kcontrol_new tumbler_hp_sw __devinitdata = {
++static struct snd_kcontrol_new tumbler_hp_sw = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "Headphone Playback Switch",
+ 	.info = snd_pmac_boolean_mono_info,
+@@ -909,7 +909,7 @@ static struct snd_kcontrol_new tumbler_hp_sw __devinitdata = {
+ 	.put = tumbler_put_mute_switch,
+ 	.private_value = TUMBLER_MUTE_HP,
+ };
+-static struct snd_kcontrol_new tumbler_speaker_sw __devinitdata = {
++static struct snd_kcontrol_new tumbler_speaker_sw = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "Speaker Playback Switch",
+ 	.info = snd_pmac_boolean_mono_info,
+@@ -917,7 +917,7 @@ static struct snd_kcontrol_new tumbler_speaker_sw __devinitdata = {
+ 	.put = tumbler_put_mute_switch,
+ 	.private_value = TUMBLER_MUTE_AMP,
+ };
+-static struct snd_kcontrol_new tumbler_lineout_sw __devinitdata = {
++static struct snd_kcontrol_new tumbler_lineout_sw = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "Line Out Playback Switch",
+ 	.info = snd_pmac_boolean_mono_info,
+@@ -925,7 +925,7 @@ static struct snd_kcontrol_new tumbler_lineout_sw __devinitdata = {
+ 	.put = tumbler_put_mute_switch,
+ 	.private_value = TUMBLER_MUTE_LINE,
+ };
+-static struct snd_kcontrol_new tumbler_drc_sw __devinitdata = {
++static struct snd_kcontrol_new tumbler_drc_sw = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "DRC Switch",
+ 	.info = snd_pmac_boolean_mono_info,
+@@ -1276,7 +1276,7 @@ static void tumbler_resume(struct snd_pmac *chip)
+ #endif
+ 
+ /* initialize tumbler */
+-static int __devinit tumbler_init(struct snd_pmac *chip)
++static int tumbler_init(struct snd_pmac *chip)
+ {
+ 	int irq;
+ 	struct pmac_tumbler *mix = chip->mixer_data;
+@@ -1349,7 +1349,7 @@ static void tumbler_cleanup(struct snd_pmac *chip)
+ }
+ 
+ /* exported */
+-int __devinit snd_pmac_tumbler_init(struct snd_pmac *chip)
++int snd_pmac_tumbler_init(struct snd_pmac *chip)
+ {
+ 	int i, err;
+ 	struct pmac_tumbler *mix;

commit 5cc3203f72d89064da315529103f277124f57005
+Author: Bill Pemberton 
+Date:   Thu Dec 6 12:35:22 2012 -0500
+
+    ALSA: sound/ps3: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Geoff Levand 
+    Cc: linuxppc-dev@lists.ozlabs.org
+    Cc: cbe-oss-dev@lists.ozlabs.org
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c
+index 9b18b5243a56..8c7dcbe0118d 100644
+--- a/sound/ppc/snd_ps3.c
++++ b/sound/ppc/snd_ps3.c
+@@ -786,7 +786,7 @@ static struct snd_pcm_ops snd_ps3_pcm_spdif_ops = {
+ };
+ 
+ 
+-static int __devinit snd_ps3_map_mmio(void)
++static int snd_ps3_map_mmio(void)
+ {
+ 	the_card.mapped_mmio_vaddr =
+ 		ioremap(the_card.ps3_dev->m_region->bus_addr,
+@@ -808,7 +808,7 @@ static void snd_ps3_unmap_mmio(void)
+ 	the_card.mapped_mmio_vaddr = NULL;
+ }
+ 
+-static int __devinit snd_ps3_allocate_irq(void)
++static int snd_ps3_allocate_irq(void)
+ {
+ 	int ret;
+ 	u64 lpar_addr, lpar_size;
+@@ -866,7 +866,7 @@ static void snd_ps3_free_irq(void)
+ 	ps3_irq_plug_destroy(the_card.irq_no);
+ }
+ 
+-static void __devinit snd_ps3_audio_set_base_addr(uint64_t ioaddr_start)
++static void snd_ps3_audio_set_base_addr(uint64_t ioaddr_start)
+ {
+ 	uint64_t val;
+ 	int ret;
+@@ -882,7 +882,7 @@ static void __devinit snd_ps3_audio_set_base_addr(uint64_t ioaddr_start)
+ 			ret);
+ }
+ 
+-static void __devinit snd_ps3_audio_fixup(struct snd_ps3_card_info *card)
++static void snd_ps3_audio_fixup(struct snd_ps3_card_info *card)
+ {
+ 	/*
+ 	 * avsetting driver seems to never change the followings
+@@ -906,7 +906,7 @@ static void __devinit snd_ps3_audio_fixup(struct snd_ps3_card_info *card)
+ 		   PS3_AUDIO_AO_3WMCTRL_ASOPLRCK_DEFAULT);
+ }
+ 
+-static int __devinit snd_ps3_init_avsetting(struct snd_ps3_card_info *card)
++static int snd_ps3_init_avsetting(struct snd_ps3_card_info *card)
+ {
+ 	int ret;
+ 	pr_debug("%s: start\n", __func__);
+@@ -928,7 +928,7 @@ static int __devinit snd_ps3_init_avsetting(struct snd_ps3_card_info *card)
+ 	return ret;
+ }
+ 
+-static int __devinit snd_ps3_driver_probe(struct ps3_system_bus_device *dev)
++static int snd_ps3_driver_probe(struct ps3_system_bus_device *dev)
+ {
+ 	int i, ret;
+ 	u64 lpar_addr, lpar_size;

commit 1bff292e9abec7477d43abb2b93c7fd26c44859b
+Author: Bill Pemberton 
+Date:   Thu Dec 6 12:35:21 2012 -0500
+
+    ALSA: isa: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c
+index 2c2f829c3fd7..26ce26a5884d 100644
+--- a/sound/isa/ad1816a/ad1816a.c
++++ b/sound/isa/ad1816a/ad1816a.c
+@@ -94,8 +94,8 @@ MODULE_DEVICE_TABLE(pnp_card, snd_ad1816a_pnpids);
+ #define	DRIVER_NAME	"snd-card-ad1816a"
+ 
+ 
+-static int __devinit snd_card_ad1816a_pnp(int dev, struct pnp_card_link *card,
+-					  const struct pnp_card_device_id *id)
++static int snd_card_ad1816a_pnp(int dev, struct pnp_card_link *card,
++				const struct pnp_card_device_id *id)
+ {
+ 	struct pnp_dev *pdev;
+ 	int err;
+@@ -135,8 +135,8 @@ static int __devinit snd_card_ad1816a_pnp(int dev, struct pnp_card_link *card,
+ 	return 0;
+ }
+ 
+-static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard,
+-					    const struct pnp_card_device_id *pid)
++static int snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard,
++				  const struct pnp_card_device_id *pid)
+ {
+ 	int error;
+ 	struct snd_card *card;
+@@ -217,10 +217,10 @@ static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard
+ 	return 0;
+ }
+ 
+-static unsigned int __devinitdata ad1816a_devices;
++static unsigned int ad1816a_devices;
+ 
+-static int __devinit snd_ad1816a_pnp_detect(struct pnp_card_link *card,
+-					    const struct pnp_card_device_id *id)
++static int snd_ad1816a_pnp_detect(struct pnp_card_link *card,
++				  const struct pnp_card_device_id *id)
+ {
+ 	static int dev;
+ 	int res;
+@@ -238,7 +238,7 @@ static int __devinit snd_ad1816a_pnp_detect(struct pnp_card_link *card,
+         return -ENODEV;
+ }
+ 
+-static void __devexit snd_ad1816a_pnp_remove(struct pnp_card_link * pcard)
++static void snd_ad1816a_pnp_remove(struct pnp_card_link *pcard)
+ {
+ 	snd_card_free(pnp_get_card_drvdata(pcard));
+ 	pnp_set_card_drvdata(pcard, NULL);
+@@ -270,7 +270,7 @@ static struct pnp_card_driver ad1816a_pnpc_driver = {
+ 	.name		= "ad1816a",
+ 	.id_table	= snd_ad1816a_pnpids,
+ 	.probe		= snd_ad1816a_pnp_detect,
+-	.remove		= __devexit_p(snd_ad1816a_pnp_remove),
++	.remove		= snd_ad1816a_pnp_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= snd_ad1816a_pnp_suspend,
+ 	.resume		= snd_ad1816a_pnp_resume,
+diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c
+index db64df6023e0..f0fd98e695e3 100644
+--- a/sound/isa/ad1816a/ad1816a_lib.c
++++ b/sound/isa/ad1816a/ad1816a_lib.c
+@@ -537,7 +537,7 @@ void snd_ad1816a_resume(struct snd_ad1816a *chip)
+ }
+ #endif
+ 
+-static int __devinit snd_ad1816a_probe(struct snd_ad1816a *chip)
++static int snd_ad1816a_probe(struct snd_ad1816a *chip)
+ {
+ 	unsigned long flags;
+ 
+@@ -583,7 +583,7 @@ static int snd_ad1816a_dev_free(struct snd_device *device)
+ 	return snd_ad1816a_free(chip);
+ }
+ 
+-static const char __devinit *snd_ad1816a_chip_id(struct snd_ad1816a *chip)
++static const char *snd_ad1816a_chip_id(struct snd_ad1816a *chip)
+ {
+ 	switch (chip->hardware) {
+ 	case AD1816A_HW_AD1816A: return "AD1816A";
+@@ -596,9 +596,9 @@ static const char __devinit *snd_ad1816a_chip_id(struct snd_ad1816a *chip)
+ 	}
+ }
+ 
+-int __devinit snd_ad1816a_create(struct snd_card *card,
+-				 unsigned long port, int irq, int dma1, int dma2,
+-				 struct snd_ad1816a *chip)
++int snd_ad1816a_create(struct snd_card *card,
++		       unsigned long port, int irq, int dma1, int dma2,
++		       struct snd_ad1816a *chip)
+ {
+         static struct snd_device_ops ops = {
+ 		.dev_free =	snd_ad1816a_dev_free,
+@@ -675,7 +675,7 @@ static struct snd_pcm_ops snd_ad1816a_capture_ops = {
+ 	.pointer =	snd_ad1816a_capture_pointer,
+ };
+ 
+-int __devinit snd_ad1816a_pcm(struct snd_ad1816a *chip, int device, struct snd_pcm **rpcm)
++int snd_ad1816a_pcm(struct snd_ad1816a *chip, int device, struct snd_pcm **rpcm)
+ {
+ 	int error;
+ 	struct snd_pcm *pcm;
+@@ -702,7 +702,8 @@ int __devinit snd_ad1816a_pcm(struct snd_ad1816a *chip, int device, struct snd_p
+ 	return 0;
+ }
+ 
+-int __devinit snd_ad1816a_timer(struct snd_ad1816a *chip, int device, struct snd_timer **rtimer)
++int snd_ad1816a_timer(struct snd_ad1816a *chip, int device,
++		      struct snd_timer **rtimer)
+ {
+ 	struct snd_timer *timer;
+ 	struct snd_timer_id tid;
+@@ -923,7 +924,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
+ static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
+ static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
+ 
+-static struct snd_kcontrol_new snd_ad1816a_controls[] __devinitdata = {
++static struct snd_kcontrol_new snd_ad1816a_controls[] = {
+ AD1816A_DOUBLE("Master Playback Switch", AD1816A_MASTER_ATT, 15, 7, 1, 1),
+ AD1816A_DOUBLE_TLV("Master Playback Volume", AD1816A_MASTER_ATT, 8, 0, 31, 1,
+ 		   db_scale_5bit),
+@@ -969,7 +970,7 @@ AD1816A_SINGLE("3D Control - Switch", AD1816A_3D_PHAT_CTRL, 15, 1, 1),
+ AD1816A_SINGLE("3D Control - Level", AD1816A_3D_PHAT_CTRL, 0, 15, 0),
+ };
+                                         
+-int __devinit snd_ad1816a_mixer(struct snd_ad1816a *chip)
++int snd_ad1816a_mixer(struct snd_ad1816a *chip)
+ {
+ 	struct snd_card *card;
+ 	unsigned int idx;
+diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
+index 2af77faefbb1..c214ecf45400 100644
+--- a/sound/isa/ad1848/ad1848.c
++++ b/sound/isa/ad1848/ad1848.c
+@@ -64,7 +64,7 @@ MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver.");
+ module_param_array(thinkpad, bool, NULL, 0444);
+ MODULE_PARM_DESC(thinkpad, "Enable only for the onboard CS4248 of IBM Thinkpad 360/750/755 series.");
+ 
+-static int __devinit snd_ad1848_match(struct device *dev, unsigned int n)
++static int snd_ad1848_match(struct device *dev, unsigned int n)
+ {
+ 	if (!enable[n])
+ 		return 0;
+@@ -84,7 +84,7 @@ static int __devinit snd_ad1848_match(struct device *dev, unsigned int n)
+ 	return 1;
+ }
+ 
+-static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n)
++static int snd_ad1848_probe(struct device *dev, unsigned int n)
+ {
+ 	struct snd_card *card;
+ 	struct snd_wss *chip;
+@@ -132,7 +132,7 @@ out:	snd_card_free(card);
+ 	return error;
+ }
+ 
+-static int __devexit snd_ad1848_remove(struct device *dev, unsigned int n)
++static int snd_ad1848_remove(struct device *dev, unsigned int n)
+ {
+ 	snd_card_free(dev_get_drvdata(dev));
+ 	dev_set_drvdata(dev, NULL);
+@@ -164,7 +164,7 @@ static int snd_ad1848_resume(struct device *dev, unsigned int n)
+ static struct isa_driver snd_ad1848_driver = {
+ 	.match		= snd_ad1848_match,
+ 	.probe		= snd_ad1848_probe,
+-	.remove		= __devexit_p(snd_ad1848_remove),
++	.remove		= snd_ad1848_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= snd_ad1848_suspend,
+ 	.resume		= snd_ad1848_resume,
+diff --git a/sound/isa/adlib.c b/sound/isa/adlib.c
+index 4d50c69f3290..d26545543732 100644
+--- a/sound/isa/adlib.c
++++ b/sound/isa/adlib.c
+@@ -30,7 +30,7 @@ MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
+ module_param_array(port, long, NULL, 0444);
+ MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
+ 
+-static int __devinit snd_adlib_match(struct device *dev, unsigned int n)
++static int snd_adlib_match(struct device *dev, unsigned int n)
+ {
+ 	if (!enable[n])
+ 		return 0;
+@@ -47,7 +47,7 @@ static void snd_adlib_free(struct snd_card *card)
+ 	release_and_free_resource(card->private_data);
+ }
+ 
+-static int __devinit snd_adlib_probe(struct device *dev, unsigned int n)
++static int snd_adlib_probe(struct device *dev, unsigned int n)
+ {
+ 	struct snd_card *card;
+ 	struct snd_opl3 *opl3;
+@@ -98,7 +98,7 @@ out:	snd_card_free(card);
+ 	return error;
+ }
+ 
+-static int __devexit snd_adlib_remove(struct device *dev, unsigned int n)
++static int snd_adlib_remove(struct device *dev, unsigned int n)
+ {
+ 	snd_card_free(dev_get_drvdata(dev));
+ 	dev_set_drvdata(dev, NULL);
+@@ -108,7 +108,7 @@ static int __devexit snd_adlib_remove(struct device *dev, unsigned int n)
+ static struct isa_driver snd_adlib_driver = {
+ 	.match		= snd_adlib_match,
+ 	.probe		= snd_adlib_probe,
+-	.remove		= __devexit_p(snd_adlib_remove),
++	.remove		= snd_adlib_remove,
+ 
+ 	.driver		= {
+ 		.name	= DEV_NAME
+diff --git a/sound/isa/als100.c b/sound/isa/als100.c
+index f7cdaf51512d..10f08a18fe3b 100644
+--- a/sound/isa/als100.c
++++ b/sound/isa/als100.c
+@@ -117,9 +117,9 @@ static struct pnp_card_device_id snd_als100_pnpids[] = {
+ 
+ MODULE_DEVICE_TABLE(pnp_card, snd_als100_pnpids);
+ 
+-static int __devinit snd_card_als100_pnp(int dev, struct snd_card_als100 *acard,
+-					 struct pnp_card_link *card,
+-					 const struct pnp_card_device_id *id)
++static int snd_card_als100_pnp(int dev, struct snd_card_als100 *acard,
++			       struct pnp_card_link *card,
++			       const struct pnp_card_device_id *id)
+ {
+ 	struct pnp_dev *pdev;
+ 	int err;
+@@ -183,9 +183,9 @@ static int __devinit snd_card_als100_pnp(int dev, struct snd_card_als100 *acard,
+ 	return 0;
+ }
+ 
+-static int __devinit snd_card_als100_probe(int dev,
+-					struct pnp_card_link *pcard,
+-					const struct pnp_card_device_id *pid)
++static int snd_card_als100_probe(int dev,
++				 struct pnp_card_link *pcard,
++				 const struct pnp_card_device_id *pid)
+ {
+ 	int error;
+ 	struct snd_sb *chip;
+@@ -286,10 +286,10 @@ static int __devinit snd_card_als100_probe(int dev,
+ 	return 0;
+ }
+ 
+-static unsigned int __devinitdata als100_devices;
++static unsigned int als100_devices;
+ 
+-static int __devinit snd_als100_pnp_detect(struct pnp_card_link *card,
+-					   const struct pnp_card_device_id *id)
++static int snd_als100_pnp_detect(struct pnp_card_link *card,
++				 const struct pnp_card_device_id *id)
+ {
+ 	static int dev;
+ 	int res;
+@@ -307,7 +307,7 @@ static int __devinit snd_als100_pnp_detect(struct pnp_card_link *card,
+ 	return -ENODEV;
+ }
+ 
+-static void __devexit snd_als100_pnp_remove(struct pnp_card_link * pcard)
++static void snd_als100_pnp_remove(struct pnp_card_link *pcard)
+ {
+ 	snd_card_free(pnp_get_card_drvdata(pcard));
+ 	pnp_set_card_drvdata(pcard, NULL);
+@@ -344,7 +344,7 @@ static struct pnp_card_driver als100_pnpc_driver = {
+ 	.name		= "als100",
+         .id_table       = snd_als100_pnpids,
+         .probe          = snd_als100_pnp_detect,
+-        .remove         = __devexit_p(snd_als100_pnp_remove),
++	.remove		= snd_als100_pnp_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= snd_als100_pnp_suspend,
+ 	.resume		= snd_als100_pnp_resume,
+diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c
+index 6a2c78ef1d8f..db301ff94ec2 100644
+--- a/sound/isa/azt2320.c
++++ b/sound/isa/azt2320.c
+@@ -99,9 +99,9 @@ MODULE_DEVICE_TABLE(pnp_card, snd_azt2320_pnpids);
+ 
+ #define	DRIVER_NAME	"snd-card-azt2320"
+ 
+-static int __devinit snd_card_azt2320_pnp(int dev, struct snd_card_azt2320 *acard,
+-					  struct pnp_card_link *card,
+-					  const struct pnp_card_device_id *id)
++static int snd_card_azt2320_pnp(int dev, struct snd_card_azt2320 *acard,
++				struct pnp_card_link *card,
++				const struct pnp_card_device_id *id)
+ {
+ 	struct pnp_dev *pdev;
+ 	int err;
+@@ -147,7 +147,7 @@ static int __devinit snd_card_azt2320_pnp(int dev, struct snd_card_azt2320 *acar
+ }
+ 
+ /* same of snd_sbdsp_command by Jaroslav Kysela */
+-static int __devinit snd_card_azt2320_command(unsigned long port, unsigned char val)
++static int snd_card_azt2320_command(unsigned long port, unsigned char val)
+ {
+ 	int i;
+ 	unsigned long limit;
+@@ -161,7 +161,7 @@ static int __devinit snd_card_azt2320_command(unsigned long port, unsigned char
+ 	return -EBUSY;
+ }
+ 
+-static int __devinit snd_card_azt2320_enable_wss(unsigned long port)
++static int snd_card_azt2320_enable_wss(unsigned long port)
+ {
+ 	int error;
+ 
+@@ -174,9 +174,9 @@ static int __devinit snd_card_azt2320_enable_wss(unsigned long port)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_card_azt2320_probe(int dev,
+-					    struct pnp_card_link *pcard,
+-					    const struct pnp_card_device_id *pid)
++static int snd_card_azt2320_probe(int dev,
++				  struct pnp_card_link *pcard,
++				  const struct pnp_card_device_id *pid)
+ {
+ 	int error;
+ 	struct snd_card *card;
+@@ -264,10 +264,10 @@ static int __devinit snd_card_azt2320_probe(int dev,
+ 	return 0;
+ }
+ 
+-static unsigned int __devinitdata azt2320_devices;
++static unsigned int azt2320_devices;
+ 
+-static int __devinit snd_azt2320_pnp_detect(struct pnp_card_link *card,
+-					    const struct pnp_card_device_id *id)
++static int snd_azt2320_pnp_detect(struct pnp_card_link *card,
++				  const struct pnp_card_device_id *id)
+ {
+ 	static int dev;
+ 	int res;
+@@ -285,7 +285,7 @@ static int __devinit snd_azt2320_pnp_detect(struct pnp_card_link *card,
+         return -ENODEV;
+ }
+ 
+-static void __devexit snd_azt2320_pnp_remove(struct pnp_card_link * pcard)
++static void snd_azt2320_pnp_remove(struct pnp_card_link *pcard)
+ {
+ 	snd_card_free(pnp_get_card_drvdata(pcard));
+ 	pnp_set_card_drvdata(pcard, NULL);
+@@ -320,7 +320,7 @@ static struct pnp_card_driver azt2320_pnpc_driver = {
+ 	.name           = "azt2320",
+ 	.id_table       = snd_azt2320_pnpids,
+ 	.probe          = snd_azt2320_pnp_detect,
+-	.remove         = __devexit_p(snd_azt2320_pnp_remove),
++	.remove         = snd_azt2320_pnp_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= snd_azt2320_pnp_suspend,
+ 	.resume		= snd_azt2320_pnp_resume,
+diff --git a/sound/isa/cmi8328.c b/sound/isa/cmi8328.c
+index bde60139bb95..a7369fe19a6f 100644
+--- a/sound/isa/cmi8328.c
++++ b/sound/isa/cmi8328.c
+@@ -140,7 +140,7 @@ static void snd_cmi8328_cfg_restore(u16 port, u8 cfg[])
+ 	snd_cmi8328_cfg_write(port, CFG3, cfg[2]);
+ }
+ 
+-static int __devinit snd_cmi8328_mixer(struct snd_wss *chip)
++static int snd_cmi8328_mixer(struct snd_wss *chip)
+ {
+ 	struct snd_card *card;
+ 	struct snd_ctl_elem_id id1, id2;
+@@ -212,7 +212,7 @@ int array_find_l(long array[], long item)
+ 	return -1;
+ }
+ 
+-static int __devinit snd_cmi8328_probe(struct device *pdev, unsigned int ndev)
++static int snd_cmi8328_probe(struct device *pdev, unsigned int ndev)
+ {
+ 	struct snd_card *card;
+ 	struct snd_opl3 *opl3;
+@@ -401,7 +401,7 @@ static int __devinit snd_cmi8328_probe(struct device *pdev, unsigned int ndev)
+ 	return err;
+ }
+ 
+-static int __devexit snd_cmi8328_remove(struct device *pdev, unsigned int dev)
++static int snd_cmi8328_remove(struct device *pdev, unsigned int dev)
+ {
+ 	struct snd_card *card = dev_get_drvdata(pdev);
+ 	struct snd_cmi8328 *cmi = card->private_data;
+@@ -459,7 +459,7 @@ static int snd_cmi8328_resume(struct device *pdev, unsigned int n)
+ 
+ static struct isa_driver snd_cmi8328_driver = {
+ 	.probe		= snd_cmi8328_probe,
+-	.remove		= __devexit_p(snd_cmi8328_remove),
++	.remove		= snd_cmi8328_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= snd_cmi8328_suspend,
+ 	.resume		= snd_cmi8328_resume,
+diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
+index 7bd5e337ee93..c707c52268ab 100644
+--- a/sound/isa/cmi8330.c
++++ b/sound/isa/cmi8330.c
+@@ -193,7 +193,7 @@ MODULE_DEVICE_TABLE(pnp_card, snd_cmi8330_pnpids);
+ #endif
+ 
+ 
+-static struct snd_kcontrol_new snd_cmi8330_controls[] __devinitdata = {
++static struct snd_kcontrol_new snd_cmi8330_controls[] = {
+ WSS_DOUBLE("Master Playback Volume", 0,
+ 		CMI8330_MASTVOL, CMI8330_MASTVOL, 4, 0, 15, 0),
+ WSS_SINGLE("Loud Playback Switch", 0,
+@@ -249,7 +249,7 @@ WSS_SINGLE(SNDRV_CTL_NAME_IEC958("Input ", PLAYBACK, SWITCH), 0,
+ };
+ 
+ #ifdef ENABLE_SB_MIXER
+-static struct sbmix_elem cmi8330_sb_mixers[] __devinitdata = {
++static struct sbmix_elem cmi8330_sb_mixers[] = {
+ SB_DOUBLE("SB Master Playback Volume", SB_DSP4_MASTER_DEV, (SB_DSP4_MASTER_DEV + 1), 3, 3, 31),
+ SB_DOUBLE("Tone Control - Bass", SB_DSP4_BASS_DEV, (SB_DSP4_BASS_DEV + 1), 4, 4, 15),
+ SB_DOUBLE("Tone Control - Treble", SB_DSP4_TREBLE_DEV, (SB_DSP4_TREBLE_DEV + 1), 4, 4, 15),
+@@ -267,7 +267,7 @@ SB_DOUBLE("SB Playback Volume", SB_DSP4_OGAIN_DEV, (SB_DSP4_OGAIN_DEV + 1), 6, 6
+ SB_SINGLE("SB Mic Auto Gain", SB_DSP4_MIC_AGC, 0, 1),
+ };
+ 
+-static unsigned char cmi8330_sb_init_values[][2] __devinitdata = {
++static unsigned char cmi8330_sb_init_values[][2] = {
+ 	{ SB_DSP4_MASTER_DEV + 0, 0 },
+ 	{ SB_DSP4_MASTER_DEV + 1, 0 },
+ 	{ SB_DSP4_PCM_DEV + 0, 0 },
+@@ -281,7 +281,7 @@ static unsigned char cmi8330_sb_init_values[][2] __devinitdata = {
+ };
+ 
+ 
+-static int __devinit cmi8330_add_sb_mixers(struct snd_sb *chip)
++static int cmi8330_add_sb_mixers(struct snd_sb *chip)
+ {
+ 	int idx, err;
+ 	unsigned long flags;
+@@ -306,7 +306,7 @@ static int __devinit cmi8330_add_sb_mixers(struct snd_sb *chip)
+ }
+ #endif
+ 
+-static int __devinit snd_cmi8330_mixer(struct snd_card *card, struct snd_cmi8330 *acard)
++static int snd_cmi8330_mixer(struct snd_card *card, struct snd_cmi8330 *acard)
+ {
+ 	unsigned int idx;
+ 	int err;
+@@ -329,9 +329,9 @@ static int __devinit snd_cmi8330_mixer(struct snd_card *card, struct snd_cmi8330
+ }
+ 
+ #ifdef CONFIG_PNP
+-static int __devinit snd_cmi8330_pnp(int dev, struct snd_cmi8330 *acard,
+-				     struct pnp_card_link *card,
+-				     const struct pnp_card_device_id *id)
++static int snd_cmi8330_pnp(int dev, struct snd_cmi8330 *acard,
++			   struct pnp_card_link *card,
++			   const struct pnp_card_device_id *id)
+ {
+ 	struct pnp_dev *pdev;
+ 	int err;
+@@ -437,7 +437,7 @@ static int snd_cmi8330_capture_open(struct snd_pcm_substream *substream)
+ 	return chip->streams[SNDRV_PCM_STREAM_CAPTURE].open(substream);
+ }
+ 
+-static int __devinit snd_cmi8330_pcm(struct snd_card *card, struct snd_cmi8330 *chip)
++static int snd_cmi8330_pcm(struct snd_card *card, struct snd_cmi8330 *chip)
+ {
+ 	struct snd_pcm *pcm;
+ 	const struct snd_pcm_ops *ops;
+@@ -532,7 +532,7 @@ static int snd_cmi8330_card_new(int dev, struct snd_card **cardp)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev)
++static int snd_cmi8330_probe(struct snd_card *card, int dev)
+ {
+ 	struct snd_cmi8330 *acard;
+ 	int i, err;
+@@ -613,8 +613,8 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev)
+ 	return snd_card_register(card);
+ }
+ 
+-static int __devinit snd_cmi8330_isa_match(struct device *pdev,
+-					   unsigned int dev)
++static int snd_cmi8330_isa_match(struct device *pdev,
++				 unsigned int dev)
+ {
+ 	if (!enable[dev] || is_isapnp_selected(dev))
+ 		return 0;
+@@ -629,8 +629,8 @@ static int __devinit snd_cmi8330_isa_match(struct device *pdev,
+ 	return 1;
+ }
+ 
+-static int __devinit snd_cmi8330_isa_probe(struct device *pdev,
+-					   unsigned int dev)
++static int snd_cmi8330_isa_probe(struct device *pdev,
++				 unsigned int dev)
+ {
+ 	struct snd_card *card;
+ 	int err;
+@@ -647,8 +647,8 @@ static int __devinit snd_cmi8330_isa_probe(struct device *pdev,
+ 	return 0;
+ }
+ 
+-static int __devexit snd_cmi8330_isa_remove(struct device *devptr,
+-					    unsigned int dev)
++static int snd_cmi8330_isa_remove(struct device *devptr,
++				  unsigned int dev)
+ {
+ 	snd_card_free(dev_get_drvdata(devptr));
+ 	dev_set_drvdata(devptr, NULL);
+@@ -673,7 +673,7 @@ static int snd_cmi8330_isa_resume(struct device *dev, unsigned int n)
+ static struct isa_driver snd_cmi8330_driver = {
+ 	.match		= snd_cmi8330_isa_match,
+ 	.probe		= snd_cmi8330_isa_probe,
+-	.remove		= __devexit_p(snd_cmi8330_isa_remove),
++	.remove		= snd_cmi8330_isa_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= snd_cmi8330_isa_suspend,
+ 	.resume		= snd_cmi8330_isa_resume,
+@@ -685,8 +685,8 @@ static struct isa_driver snd_cmi8330_driver = {
+ 
+ 
+ #ifdef CONFIG_PNP
+-static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard,
+-					    const struct pnp_card_device_id *pid)
++static int snd_cmi8330_pnp_detect(struct pnp_card_link *pcard,
++				  const struct pnp_card_device_id *pid)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -717,7 +717,7 @@ static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_cmi8330_pnp_remove(struct pnp_card_link * pcard)
++static void snd_cmi8330_pnp_remove(struct pnp_card_link *pcard)
+ {
+ 	snd_card_free(pnp_get_card_drvdata(pcard));
+ 	pnp_set_card_drvdata(pcard, NULL);
+@@ -740,7 +740,7 @@ static struct pnp_card_driver cmi8330_pnpc_driver = {
+ 	.name = "cmi8330",
+ 	.id_table = snd_cmi8330_pnpids,
+ 	.probe = snd_cmi8330_pnp_detect,
+-	.remove = __devexit_p(snd_cmi8330_pnp_remove),
++	.remove = snd_cmi8330_pnp_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= snd_cmi8330_pnp_suspend,
+ 	.resume		= snd_cmi8330_pnp_resume,
+diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c
+index 99dda45e82f5..aa7a5d86e480 100644
+--- a/sound/isa/cs423x/cs4231.c
++++ b/sound/isa/cs423x/cs4231.c
+@@ -68,7 +68,7 @@ MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver.");
+ module_param_array(dma2, int, NULL, 0444);
+ MODULE_PARM_DESC(dma2, "DMA2 # for " CRD_NAME " driver.");
+ 
+-static int __devinit snd_cs4231_match(struct device *dev, unsigned int n)
++static int snd_cs4231_match(struct device *dev, unsigned int n)
+ {
+ 	if (!enable[n])
+ 		return 0;
+@@ -88,7 +88,7 @@ static int __devinit snd_cs4231_match(struct device *dev, unsigned int n)
+ 	return 1;
+ }
+ 
+-static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n)
++static int snd_cs4231_probe(struct device *dev, unsigned int n)
+ {
+ 	struct snd_card *card;
+ 	struct snd_wss *chip;
+@@ -148,7 +148,7 @@ out:	snd_card_free(card);
+ 	return error;
+ }
+ 
+-static int __devexit snd_cs4231_remove(struct device *dev, unsigned int n)
++static int snd_cs4231_remove(struct device *dev, unsigned int n)
+ {
+ 	snd_card_free(dev_get_drvdata(dev));
+ 	dev_set_drvdata(dev, NULL);
+@@ -180,7 +180,7 @@ static int snd_cs4231_resume(struct device *dev, unsigned int n)
+ static struct isa_driver snd_cs4231_driver = {
+ 	.match		= snd_cs4231_match,
+ 	.probe		= snd_cs4231_probe,
+-	.remove		= __devexit_p(snd_cs4231_remove),
++	.remove		= snd_cs4231_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= snd_cs4231_suspend,
+ 	.resume		= snd_cs4231_resume,
+diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
+index 740c51a1ed7b..252e9fb37db3 100644
+--- a/sound/isa/cs423x/cs4236.c
++++ b/sound/isa/cs423x/cs4236.c
+@@ -251,7 +251,7 @@ static struct pnp_card_device_id snd_cs423x_pnpids[] = {
+ MODULE_DEVICE_TABLE(pnp_card, snd_cs423x_pnpids);
+ 
+ /* WSS initialization */
+-static int __devinit snd_cs423x_pnp_init_wss(int dev, struct pnp_dev *pdev)
++static int snd_cs423x_pnp_init_wss(int dev, struct pnp_dev *pdev)
+ {
+ 	if (pnp_activate_dev(pdev) < 0) {
+ 		printk(KERN_ERR IDENT " WSS PnP configure failed for WSS (out of resources?)\n");
+@@ -272,7 +272,7 @@ static int __devinit snd_cs423x_pnp_init_wss(int dev, struct pnp_dev *pdev)
+ }
+ 
+ /* CTRL initialization */
+-static int __devinit snd_cs423x_pnp_init_ctrl(int dev, struct pnp_dev *pdev)
++static int snd_cs423x_pnp_init_ctrl(int dev, struct pnp_dev *pdev)
+ {
+ 	if (pnp_activate_dev(pdev) < 0) {
+ 		printk(KERN_ERR IDENT " CTRL PnP configure failed for WSS (out of resources?)\n");
+@@ -284,7 +284,7 @@ static int __devinit snd_cs423x_pnp_init_ctrl(int dev, struct pnp_dev *pdev)
+ }
+ 
+ /* MPU initialization */
+-static int __devinit snd_cs423x_pnp_init_mpu(int dev, struct pnp_dev *pdev)
++static int snd_cs423x_pnp_init_mpu(int dev, struct pnp_dev *pdev)
+ {
+ 	if (pnp_activate_dev(pdev) < 0) {
+ 		printk(KERN_ERR IDENT " MPU401 PnP configure failed for WSS (out of resources?)\n");
+@@ -303,9 +303,9 @@ static int __devinit snd_cs423x_pnp_init_mpu(int dev, struct pnp_dev *pdev)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_card_cs423x_pnp(int dev, struct snd_card_cs4236 *acard,
+-					 struct pnp_dev *pdev,
+-					 struct pnp_dev *cdev)
++static int snd_card_cs423x_pnp(int dev, struct snd_card_cs4236 *acard,
++			       struct pnp_dev *pdev,
++			       struct pnp_dev *cdev)
+ {
+ 	acard->wss = pdev;
+ 	if (snd_cs423x_pnp_init_wss(dev, acard->wss) < 0)
+@@ -317,9 +317,9 @@ static int __devinit snd_card_cs423x_pnp(int dev, struct snd_card_cs4236 *acard,
+ 	return 0;
+ }
+ 
+-static int __devinit snd_card_cs423x_pnpc(int dev, struct snd_card_cs4236 *acard,
+-					  struct pnp_card_link *card,
+-					  const struct pnp_card_device_id *id)
++static int snd_card_cs423x_pnpc(int dev, struct snd_card_cs4236 *acard,
++				struct pnp_card_link *card,
++				const struct pnp_card_device_id *id)
+ {
+ 	acard->wss = pnp_request_card_device(card, id->devs[0].id, NULL);
+ 	if (acard->wss == NULL)
+@@ -378,7 +378,7 @@ static int snd_cs423x_card_new(int dev, struct snd_card **cardp)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_cs423x_probe(struct snd_card *card, int dev)
++static int snd_cs423x_probe(struct snd_card *card, int dev)
+ {
+ 	struct snd_card_cs4236 *acard;
+ 	struct snd_pcm *pcm;
+@@ -456,8 +456,8 @@ static int __devinit snd_cs423x_probe(struct snd_card *card, int dev)
+ 	return snd_card_register(card);
+ }
+ 
+-static int __devinit snd_cs423x_isa_match(struct device *pdev,
+-					  unsigned int dev)
++static int snd_cs423x_isa_match(struct device *pdev,
++				unsigned int dev)
+ {
+ 	if (!enable[dev] || is_isapnp_selected(dev))
+ 		return 0;
+@@ -481,8 +481,8 @@ static int __devinit snd_cs423x_isa_match(struct device *pdev,
+ 	return 1;
+ }
+ 
+-static int __devinit snd_cs423x_isa_probe(struct device *pdev,
+-					  unsigned int dev)
++static int snd_cs423x_isa_probe(struct device *pdev,
++				unsigned int dev)
+ {
+ 	struct snd_card *card;
+ 	int err;
+@@ -500,8 +500,8 @@ static int __devinit snd_cs423x_isa_probe(struct device *pdev,
+ 	return 0;
+ }
+ 
+-static int __devexit snd_cs423x_isa_remove(struct device *pdev,
+-					   unsigned int dev)
++static int snd_cs423x_isa_remove(struct device *pdev,
++				 unsigned int dev)
+ {
+ 	snd_card_free(dev_get_drvdata(pdev));
+ 	dev_set_drvdata(pdev, NULL);
+@@ -540,7 +540,7 @@ static int snd_cs423x_isa_resume(struct device *dev, unsigned int n)
+ static struct isa_driver cs423x_isa_driver = {
+ 	.match		= snd_cs423x_isa_match,
+ 	.probe		= snd_cs423x_isa_probe,
+-	.remove		= __devexit_p(snd_cs423x_isa_remove),
++	.remove		= snd_cs423x_isa_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= snd_cs423x_isa_suspend,
+ 	.resume		= snd_cs423x_isa_resume,
+@@ -552,8 +552,8 @@ static struct isa_driver cs423x_isa_driver = {
+ 
+ 
+ #ifdef CONFIG_PNP
+-static int __devinit snd_cs423x_pnpbios_detect(struct pnp_dev *pdev,
+-					       const struct pnp_device_id *id)
++static int snd_cs423x_pnpbios_detect(struct pnp_dev *pdev,
++				     const struct pnp_device_id *id)
+ {
+ 	static int dev;
+ 	int err;
+@@ -597,7 +597,7 @@ static int __devinit snd_cs423x_pnpbios_detect(struct pnp_dev *pdev,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_cs423x_pnp_remove(struct pnp_dev *pdev)
++static void snd_cs423x_pnp_remove(struct pnp_dev *pdev)
+ {
+ 	snd_card_free(pnp_get_drvdata(pdev));
+ 	pnp_set_drvdata(pdev, NULL);
+@@ -619,15 +619,15 @@ static struct pnp_driver cs423x_pnp_driver = {
+ 	.name = "cs423x-pnpbios",
+ 	.id_table = snd_cs423x_pnpbiosids,
+ 	.probe = snd_cs423x_pnpbios_detect,
+-	.remove = __devexit_p(snd_cs423x_pnp_remove),
++	.remove = snd_cs423x_pnp_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= snd_cs423x_pnp_suspend,
+ 	.resume		= snd_cs423x_pnp_resume,
+ #endif
+ };
+ 
+-static int __devinit snd_cs423x_pnpc_detect(struct pnp_card_link *pcard,
+-					    const struct pnp_card_device_id *pid)
++static int snd_cs423x_pnpc_detect(struct pnp_card_link *pcard,
++				  const struct pnp_card_device_id *pid)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -659,7 +659,7 @@ static int __devinit snd_cs423x_pnpc_detect(struct pnp_card_link *pcard,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_cs423x_pnpc_remove(struct pnp_card_link * pcard)
++static void snd_cs423x_pnpc_remove(struct pnp_card_link *pcard)
+ {
+ 	snd_card_free(pnp_get_card_drvdata(pcard));
+ 	pnp_set_card_drvdata(pcard, NULL);
+@@ -682,7 +682,7 @@ static struct pnp_card_driver cs423x_pnpc_driver = {
+ 	.name = CS423X_ISAPNP_DRIVER,
+ 	.id_table = snd_cs423x_pnpids,
+ 	.probe = snd_cs423x_pnpc_detect,
+-	.remove = __devexit_p(snd_cs423x_pnpc_remove),
++	.remove = snd_cs423x_pnpc_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= snd_cs423x_pnpc_suspend,
+ 	.resume		= snd_cs423x_pnpc_resume,
+diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c
+index b036e60f62d1..102874a703d4 100644
+--- a/sound/isa/es1688/es1688.c
++++ b/sound/isa/es1688/es1688.c
+@@ -90,13 +90,13 @@ MODULE_PARM_DESC(dma8, "8-bit DMA # for " CRD_NAME " driver.");
+ #define is_isapnp_selected(dev)		0
+ #endif
+ 
+-static int __devinit snd_es1688_match(struct device *dev, unsigned int n)
++static int snd_es1688_match(struct device *dev, unsigned int n)
+ {
+ 	return enable[n] && !is_isapnp_selected(n);
+ }
+ 
+-static int __devinit snd_es1688_legacy_create(struct snd_card *card,
+-					struct device *dev, unsigned int n)
++static int snd_es1688_legacy_create(struct snd_card *card,
++				    struct device *dev, unsigned int n)
+ {
+ 	struct snd_es1688 *chip = card->private_data;
+ 	static long possible_ports[] = {0x220, 0x240, 0x260};
+@@ -134,7 +134,7 @@ static int __devinit snd_es1688_legacy_create(struct snd_card *card,
+ 	return error;
+ }
+ 
+-static int __devinit snd_es1688_probe(struct snd_card *card, unsigned int n)
++static int snd_es1688_probe(struct snd_card *card, unsigned int n)
+ {
+ 	struct snd_es1688 *chip = card->private_data;
+ 	struct snd_opl3 *opl3;
+@@ -182,7 +182,7 @@ static int __devinit snd_es1688_probe(struct snd_card *card, unsigned int n)
+ 	return snd_card_register(card);
+ }
+ 
+-static int __devinit snd_es1688_isa_probe(struct device *dev, unsigned int n)
++static int snd_es1688_isa_probe(struct device *dev, unsigned int n)
+ {
+ 	struct snd_card *card;
+ 	int error;
+@@ -210,7 +210,7 @@ static int __devinit snd_es1688_isa_probe(struct device *dev, unsigned int n)
+ 	return error;
+ }
+ 
+-static int __devexit snd_es1688_isa_remove(struct device *dev, unsigned int n)
++static int snd_es1688_isa_remove(struct device *dev, unsigned int n)
+ {
+ 	snd_card_free(dev_get_drvdata(dev));
+ 	dev_set_drvdata(dev, NULL);
+@@ -220,7 +220,7 @@ static int __devexit snd_es1688_isa_remove(struct device *dev, unsigned int n)
+ static struct isa_driver snd_es1688_driver = {
+ 	.match		= snd_es1688_match,
+ 	.probe		= snd_es1688_isa_probe,
+-	.remove		= __devexit_p(snd_es1688_isa_remove),
++	.remove		= snd_es1688_isa_remove,
+ #if 0	/* FIXME */
+ 	.suspend	= snd_es1688_suspend,
+ 	.resume		= snd_es1688_resume,
+@@ -233,9 +233,9 @@ static struct isa_driver snd_es1688_driver = {
+ static int snd_es968_pnp_is_probed;
+ 
+ #ifdef CONFIG_PNP
+-static int __devinit snd_card_es968_pnp(struct snd_card *card, unsigned int n,
+-					struct pnp_card_link *pcard,
+-					const struct pnp_card_device_id *pid)
++static int snd_card_es968_pnp(struct snd_card *card, unsigned int n,
++			      struct pnp_card_link *pcard,
++			      const struct pnp_card_device_id *pid)
+ {
+ 	struct snd_es1688 *chip = card->private_data;
+ 	struct pnp_dev *pdev;
+@@ -258,8 +258,8 @@ static int __devinit snd_card_es968_pnp(struct snd_card *card, unsigned int n,
+ 				 mpu_irq[n], dma8[n], ES1688_HW_AUTO);
+ }
+ 
+-static int __devinit snd_es968_pnp_detect(struct pnp_card_link *pcard,
+-					  const struct pnp_card_device_id *pid)
++static int snd_es968_pnp_detect(struct pnp_card_link *pcard,
++				const struct pnp_card_device_id *pid)
+ {
+ 	struct snd_card *card;
+ 	static unsigned int dev;
+@@ -295,7 +295,7 @@ static int __devinit snd_es968_pnp_detect(struct pnp_card_link *pcard,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_es968_pnp_remove(struct pnp_card_link * pcard)
++static void snd_es968_pnp_remove(struct pnp_card_link *pcard)
+ {
+ 	snd_card_free(pnp_get_card_drvdata(pcard));
+ 	pnp_set_card_drvdata(pcard, NULL);
+@@ -338,7 +338,7 @@ static struct pnp_card_driver es968_pnpc_driver = {
+ 	.name		= DEV_NAME " PnP",
+ 	.id_table	= snd_es968_pnpids,
+ 	.probe		= snd_es968_pnp_detect,
+-	.remove		= __devexit_p(snd_es968_pnp_remove),
++	.remove		= snd_es968_pnp_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= snd_es968_pnp_suspend,
+ 	.resume		= snd_es968_pnp_resume,
+diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
+index c20baafd9b7c..24380efe31a1 100644
+--- a/sound/isa/es18xx.c
++++ b/sound/isa/es18xx.c
+@@ -348,7 +348,7 @@ static inline int snd_es18xx_mixer_writable(struct snd_es18xx *chip, unsigned ch
+ }
+ 
+ 
+-static int __devinit snd_es18xx_reset(struct snd_es18xx *chip)
++static int snd_es18xx_reset(struct snd_es18xx *chip)
+ {
+ 	int i;
+         outb(0x03, chip->port + 0x06);
+@@ -1363,7 +1363,7 @@ static struct snd_kcontrol_new snd_es18xx_hw_volume_controls[] = {
+ ES18XX_SINGLE("Hardware Master Volume Split", 0, 0x64, 7, 1, 0),
+ };
+ 
+-static int __devinit snd_es18xx_config_read(struct snd_es18xx *chip, unsigned char reg)
++static int snd_es18xx_config_read(struct snd_es18xx *chip, unsigned char reg)
+ {
+ 	int data;
+ 
+@@ -1372,8 +1372,8 @@ static int __devinit snd_es18xx_config_read(struct snd_es18xx *chip, unsigned ch
+ 	return data;
+ }
+ 
+-static void __devinit snd_es18xx_config_write(struct snd_es18xx *chip, 
+-					      unsigned char reg, unsigned char data)
++static void snd_es18xx_config_write(struct snd_es18xx *chip,
++				    unsigned char reg, unsigned char data)
+ {
+ 	/* No need for spinlocks, this function is used only in
+ 	   otherwise protected init code */
+@@ -1384,9 +1384,9 @@ static void __devinit snd_es18xx_config_write(struct snd_es18xx *chip,
+ #endif
+ }
+ 
+-static int __devinit snd_es18xx_initialize(struct snd_es18xx *chip,
+-					   unsigned long mpu_port,
+-					   unsigned long fm_port)
++static int snd_es18xx_initialize(struct snd_es18xx *chip,
++				 unsigned long mpu_port,
++				 unsigned long fm_port)
+ {
+ 	int mask = 0;
+ 
+@@ -1549,7 +1549,7 @@ static int __devinit snd_es18xx_initialize(struct snd_es18xx *chip,
+         return 0;
+ }
+ 
+-static int __devinit snd_es18xx_identify(struct snd_es18xx *chip)
++static int snd_es18xx_identify(struct snd_es18xx *chip)
+ {
+ 	int hi,lo;
+ 
+@@ -1618,9 +1618,9 @@ static int __devinit snd_es18xx_identify(struct snd_es18xx *chip)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_es18xx_probe(struct snd_es18xx *chip,
+-					unsigned long mpu_port,
+-					unsigned long fm_port)
++static int snd_es18xx_probe(struct snd_es18xx *chip,
++			    unsigned long mpu_port,
++			    unsigned long fm_port)
+ {
+ 	if (snd_es18xx_identify(chip) < 0) {
+ 		snd_printk(KERN_ERR PFX "[0x%lx] ESS chip not found\n", chip->port);
+@@ -1680,8 +1680,8 @@ static struct snd_pcm_ops snd_es18xx_capture_ops = {
+ 	.pointer =	snd_es18xx_capture_pointer,
+ };
+ 
+-static int __devinit snd_es18xx_pcm(struct snd_card *card, int device,
+-				    struct snd_pcm **rpcm)
++static int snd_es18xx_pcm(struct snd_card *card, int device,
++			  struct snd_pcm **rpcm)
+ {
+ 	struct snd_es18xx *chip = card->private_data;
+         struct snd_pcm *pcm;
+@@ -1777,11 +1777,11 @@ static int snd_es18xx_dev_free(struct snd_device *device)
+ 	return snd_es18xx_free(device->card);
+ }
+ 
+-static int __devinit snd_es18xx_new_device(struct snd_card *card,
+-					   unsigned long port,
+-					   unsigned long mpu_port,
+-					   unsigned long fm_port,
+-					   int irq, int dma1, int dma2)
++static int snd_es18xx_new_device(struct snd_card *card,
++				 unsigned long port,
++				 unsigned long mpu_port,
++				 unsigned long fm_port,
++				 int irq, int dma1, int dma2)
+ {
+ 	struct snd_es18xx *chip = card->private_data;
+ 	static struct snd_device_ops ops = {
+@@ -1839,7 +1839,7 @@ static int __devinit snd_es18xx_new_device(struct snd_card *card,
+         return 0;
+ }
+ 
+-static int __devinit snd_es18xx_mixer(struct snd_card *card)
++static int snd_es18xx_mixer(struct snd_card *card)
+ {
+ 	struct snd_es18xx *chip = card->private_data;
+ 	int err;
+@@ -2016,7 +2016,7 @@ static struct pnp_device_id snd_audiodrive_pnpbiosids[] = {
+ MODULE_DEVICE_TABLE(pnp, snd_audiodrive_pnpbiosids);
+ 
+ /* PnP main device initialization */
+-static int __devinit snd_audiodrive_pnp_init_main(int dev, struct pnp_dev *pdev)
++static int snd_audiodrive_pnp_init_main(int dev, struct pnp_dev *pdev)
+ {
+ 	if (pnp_activate_dev(pdev) < 0) {
+ 		snd_printk(KERN_ERR PFX "PnP configure failure (out of resources?)\n");
+@@ -2043,8 +2043,8 @@ static int __devinit snd_audiodrive_pnp_init_main(int dev, struct pnp_dev *pdev)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_audiodrive_pnp(int dev, struct snd_es18xx *chip,
+-					struct pnp_dev *pdev)
++static int snd_audiodrive_pnp(int dev, struct snd_es18xx *chip,
++			      struct pnp_dev *pdev)
+ {
+ 	chip->dev = pdev;
+ 	if (snd_audiodrive_pnp_init_main(dev, chip->dev) < 0)
+@@ -2073,9 +2073,9 @@ static struct pnp_card_device_id snd_audiodrive_pnpids[] = {
+ 
+ MODULE_DEVICE_TABLE(pnp_card, snd_audiodrive_pnpids);
+ 
+-static int __devinit snd_audiodrive_pnpc(int dev, struct snd_es18xx *chip,
+-					struct pnp_card_link *card,
+-					const struct pnp_card_device_id *id)
++static int snd_audiodrive_pnpc(int dev, struct snd_es18xx *chip,
++			       struct pnp_card_link *card,
++			       const struct pnp_card_device_id *id)
+ {
+ 	chip->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
+ 	if (chip->dev == NULL)
+@@ -2111,7 +2111,7 @@ static int snd_es18xx_card_new(int dev, struct snd_card **cardp)
+ 			       sizeof(struct snd_es18xx), cardp);
+ }
+ 
+-static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev)
++static int snd_audiodrive_probe(struct snd_card *card, int dev)
+ {
+ 	struct snd_es18xx *chip = card->private_data;
+ 	struct snd_opl3 *opl3;
+@@ -2169,12 +2169,12 @@ static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev)
+ 	return snd_card_register(card);
+ }
+ 
+-static int __devinit snd_es18xx_isa_match(struct device *pdev, unsigned int dev)
++static int snd_es18xx_isa_match(struct device *pdev, unsigned int dev)
+ {
+ 	return enable[dev] && !is_isapnp_selected(dev);
+ }
+ 
+-static int __devinit snd_es18xx_isa_probe1(int dev, struct device *devptr)
++static int snd_es18xx_isa_probe1(int dev, struct device *devptr)
+ {
+ 	struct snd_card *card;
+ 	int err;
+@@ -2191,7 +2191,7 @@ static int __devinit snd_es18xx_isa_probe1(int dev, struct device *devptr)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_es18xx_isa_probe(struct device *pdev, unsigned int dev)
++static int snd_es18xx_isa_probe(struct device *pdev, unsigned int dev)
+ {
+ 	int err;
+ 	static int possible_irqs[] = {5, 9, 10, 7, 11, 12, -1};
+@@ -2231,8 +2231,8 @@ static int __devinit snd_es18xx_isa_probe(struct device *pdev, unsigned int dev)
+ 	}
+ }
+ 
+-static int __devexit snd_es18xx_isa_remove(struct device *devptr,
+-					   unsigned int dev)
++static int snd_es18xx_isa_remove(struct device *devptr,
++				 unsigned int dev)
+ {
+ 	snd_card_free(dev_get_drvdata(devptr));
+ 	dev_set_drvdata(devptr, NULL);
+@@ -2257,7 +2257,7 @@ static int snd_es18xx_isa_resume(struct device *dev, unsigned int n)
+ static struct isa_driver snd_es18xx_isa_driver = {
+ 	.match		= snd_es18xx_isa_match,
+ 	.probe		= snd_es18xx_isa_probe,
+-	.remove		= __devexit_p(snd_es18xx_isa_remove),
++	.remove		= snd_es18xx_isa_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= snd_es18xx_isa_suspend,
+ 	.resume		= snd_es18xx_isa_resume,
+@@ -2269,8 +2269,8 @@ static struct isa_driver snd_es18xx_isa_driver = {
+ 
+ 
+ #ifdef CONFIG_PNP
+-static int __devinit snd_audiodrive_pnp_detect(struct pnp_dev *pdev,
+-					    const struct pnp_device_id *id)
++static int snd_audiodrive_pnp_detect(struct pnp_dev *pdev,
++				     const struct pnp_device_id *id)
+ {
+ 	static int dev;
+ 	int err;
+@@ -2302,7 +2302,7 @@ static int __devinit snd_audiodrive_pnp_detect(struct pnp_dev *pdev,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_audiodrive_pnp_remove(struct pnp_dev * pdev)
++static void snd_audiodrive_pnp_remove(struct pnp_dev *pdev)
+ {
+ 	snd_card_free(pnp_get_drvdata(pdev));
+ 	pnp_set_drvdata(pdev, NULL);
+@@ -2323,15 +2323,15 @@ static struct pnp_driver es18xx_pnp_driver = {
+ 	.name = "es18xx-pnpbios",
+ 	.id_table = snd_audiodrive_pnpbiosids,
+ 	.probe = snd_audiodrive_pnp_detect,
+-	.remove = __devexit_p(snd_audiodrive_pnp_remove),
++	.remove = snd_audiodrive_pnp_remove,
+ #ifdef CONFIG_PM
+ 	.suspend = snd_audiodrive_pnp_suspend,
+ 	.resume = snd_audiodrive_pnp_resume,
+ #endif
+ };
+ 
+-static int __devinit snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard,
+-					       const struct pnp_card_device_id *pid)
++static int snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard,
++				      const struct pnp_card_device_id *pid)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -2363,7 +2363,7 @@ static int __devinit snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_audiodrive_pnpc_remove(struct pnp_card_link * pcard)
++static void snd_audiodrive_pnpc_remove(struct pnp_card_link *pcard)
+ {
+ 	snd_card_free(pnp_get_card_drvdata(pcard));
+ 	pnp_set_card_drvdata(pcard, NULL);
+@@ -2387,7 +2387,7 @@ static struct pnp_card_driver es18xx_pnpc_driver = {
+ 	.name = "es18xx",
+ 	.id_table = snd_audiodrive_pnpids,
+ 	.probe = snd_audiodrive_pnpc_detect,
+-	.remove = __devexit_p(snd_audiodrive_pnpc_remove),
++	.remove = snd_audiodrive_pnpc_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= snd_audiodrive_pnpc_suspend,
+ 	.resume		= snd_audiodrive_pnpc_resume,
+diff --git a/sound/isa/galaxy/galaxy.c b/sound/isa/galaxy/galaxy.c
+index 55e20782858d..672184e3221a 100644
+--- a/sound/isa/galaxy/galaxy.c
++++ b/sound/isa/galaxy/galaxy.c
+@@ -84,7 +84,7 @@ MODULE_PARM_DESC(dma2, "Capture DMA # for " CRD_NAME " driver.");
+ 
+ #define DSP_COMMAND_GET_VERSION	0xe1
+ 
+-static int __devinit dsp_get_byte(void __iomem *port, u8 *val)
++static int dsp_get_byte(void __iomem *port, u8 *val)
+ {
+ 	int loops = 1000;
+ 
+@@ -97,7 +97,7 @@ static int __devinit dsp_get_byte(void __iomem *port, u8 *val)
+ 	return 0;
+ }
+ 
+-static int __devinit dsp_reset(void __iomem *port)
++static int dsp_reset(void __iomem *port)
+ {
+ 	u8 val;
+ 
+@@ -111,7 +111,7 @@ static int __devinit dsp_reset(void __iomem *port)
+ 	return 0;
+ }
+ 
+-static int __devinit dsp_command(void __iomem *port, u8 cmd)
++static int dsp_command(void __iomem *port, u8 cmd)
+ {
+ 	int loops = 1000;
+ 
+@@ -124,7 +124,7 @@ static int __devinit dsp_command(void __iomem *port, u8 cmd)
+ 	return 0;
+ }
+ 
+-static int __devinit dsp_get_version(void __iomem *port, u8 *major, u8 *minor)
++static int dsp_get_version(void __iomem *port, u8 *major, u8 *minor)
+ {
+ 	int err;
+ 
+@@ -161,7 +161,7 @@ static int __devinit dsp_get_version(void __iomem *port, u8 *major, u8 *minor)
+ 
+ #define WSS_SIGNATURE		4
+ 
+-static int __devinit wss_detect(void __iomem *wss_port)
++static int wss_detect(void __iomem *wss_port)
+ {
+ 	if ((ioread8(wss_port + WSS_PORT_SIGNATURE) & 0x3f) != WSS_SIGNATURE)
+ 		return -ENODEV;
+@@ -204,7 +204,7 @@ struct snd_galaxy {
+ static u32 config[SNDRV_CARDS];
+ static u8 wss_config[SNDRV_CARDS];
+ 
+-static int __devinit snd_galaxy_match(struct device *dev, unsigned int n)
++static int snd_galaxy_match(struct device *dev, unsigned int n)
+ {
+ 	if (!enable[n])
+ 		return 0;
+@@ -379,7 +379,7 @@ static int __devinit snd_galaxy_match(struct device *dev, unsigned int n)
+ 	return 1;
+ }
+ 
+-static int __devinit galaxy_init(struct snd_galaxy *galaxy, u8 *type)
++static int galaxy_init(struct snd_galaxy *galaxy, u8 *type)
+ {
+ 	u8 major;
+ 	u8 minor;
+@@ -411,7 +411,7 @@ static int __devinit galaxy_init(struct snd_galaxy *galaxy, u8 *type)
+ 	return 0;
+ }
+ 
+-static int __devinit galaxy_set_mode(struct snd_galaxy *galaxy, u8 mode)
++static int galaxy_set_mode(struct snd_galaxy *galaxy, u8 mode)
+ {
+ 	int err;
+ 
+@@ -449,7 +449,7 @@ static void galaxy_set_config(struct snd_galaxy *galaxy, u32 config)
+ 	msleep(10);
+ }
+ 
+-static void __devinit galaxy_config(struct snd_galaxy *galaxy, u32 config)
++static void galaxy_config(struct snd_galaxy *galaxy, u32 config)
+ {
+ 	int i;
+ 
+@@ -461,7 +461,7 @@ static void __devinit galaxy_config(struct snd_galaxy *galaxy, u32 config)
+ 	galaxy_set_config(galaxy, config);
+ }
+ 
+-static int __devinit galaxy_wss_config(struct snd_galaxy *galaxy, u8 wss_config)
++static int galaxy_wss_config(struct snd_galaxy *galaxy, u8 wss_config)
+ {
+ 	int err;
+ 
+@@ -498,7 +498,7 @@ static void snd_galaxy_free(struct snd_card *card)
+ 	}
+ }
+ 
+-static int __devinit snd_galaxy_probe(struct device *dev, unsigned int n)
++static int snd_galaxy_probe(struct device *dev, unsigned int n)
+ {
+ 	struct snd_galaxy *galaxy;
+ 	struct snd_wss *chip;
+@@ -620,7 +620,7 @@ static int __devinit snd_galaxy_probe(struct device *dev, unsigned int n)
+ 	return err;
+ }
+ 
+-static int __devexit snd_galaxy_remove(struct device *dev, unsigned int n)
++static int snd_galaxy_remove(struct device *dev, unsigned int n)
+ {
+ 	snd_card_free(dev_get_drvdata(dev));
+ 	dev_set_drvdata(dev, NULL);
+@@ -630,7 +630,7 @@ static int __devexit snd_galaxy_remove(struct device *dev, unsigned int n)
+ static struct isa_driver snd_galaxy_driver = {
+ 	.match		= snd_galaxy_match,
+ 	.probe		= snd_galaxy_probe,
+-	.remove		= __devexit_p(snd_galaxy_remove),
++	.remove		= snd_galaxy_remove,
+ 
+ 	.driver		= {
+ 		.name	= DEV_NAME
+diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c
+index bf6333671613..16bca4e96c08 100644
+--- a/sound/isa/gus/gusclassic.c
++++ b/sound/isa/gus/gusclassic.c
+@@ -73,13 +73,14 @@ MODULE_PARM_DESC(channels, "GF1 channels for " CRD_NAME " driver.");
+ module_param_array(pcm_channels, int, NULL, 0444);
+ MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for " CRD_NAME " driver.");
+ 
+-static int __devinit snd_gusclassic_match(struct device *dev, unsigned int n)
++static int snd_gusclassic_match(struct device *dev, unsigned int n)
+ {
+ 	return enable[n];
+ }
+ 
+-static int __devinit snd_gusclassic_create(struct snd_card *card,
+-		struct device *dev, unsigned int n, struct snd_gus_card **rgus)
++static int snd_gusclassic_create(struct snd_card *card,
++				 struct device *dev, unsigned int n,
++				 struct snd_gus_card **rgus)
+ {
+ 	static long possible_ports[] = {0x220, 0x230, 0x240, 0x250, 0x260};
+ 	static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, 4, -1};
+@@ -123,7 +124,7 @@ static int __devinit snd_gusclassic_create(struct snd_card *card,
+ 	return error;
+ }
+ 
+-static int __devinit snd_gusclassic_detect(struct snd_gus_card *gus)
++static int snd_gusclassic_detect(struct snd_gus_card *gus)
+ {
+ 	unsigned char d;
+ 
+@@ -142,7 +143,7 @@ static int __devinit snd_gusclassic_detect(struct snd_gus_card *gus)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_gusclassic_probe(struct device *dev, unsigned int n)
++static int snd_gusclassic_probe(struct device *dev, unsigned int n)
+ {
+ 	struct snd_card *card;
+ 	struct snd_gus_card *gus;
+@@ -211,7 +212,7 @@ out:	snd_card_free(card);
+ 	return error;
+ }
+ 
+-static int __devexit snd_gusclassic_remove(struct device *dev, unsigned int n)
++static int snd_gusclassic_remove(struct device *dev, unsigned int n)
+ {
+ 	snd_card_free(dev_get_drvdata(dev));
+ 	dev_set_drvdata(dev, NULL);
+@@ -221,7 +222,7 @@ static int __devexit snd_gusclassic_remove(struct device *dev, unsigned int n)
+ static struct isa_driver snd_gusclassic_driver = {
+ 	.match		= snd_gusclassic_match,
+ 	.probe		= snd_gusclassic_probe,
+-	.remove		= __devexit_p(snd_gusclassic_remove),
++	.remove		= snd_gusclassic_remove,
+ #if 0	/* FIXME */
+ 	.suspend	= snd_gusclassic_suspend,
+ 	.remove		= snd_gusclassic_remove,
+diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c
+index bc10cc26e5f9..0b9c2426b49f 100644
+--- a/sound/isa/gus/gusextreme.c
++++ b/sound/isa/gus/gusextreme.c
+@@ -89,13 +89,14 @@ MODULE_PARM_DESC(channels, "GF1 channels for " CRD_NAME " driver.");
+ module_param_array(pcm_channels, int, NULL, 0444);
+ MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for " CRD_NAME " driver.");
+ 
+-static int __devinit snd_gusextreme_match(struct device *dev, unsigned int n)
++static int snd_gusextreme_match(struct device *dev, unsigned int n)
+ {
+ 	return enable[n];
+ }
+ 
+-static int __devinit snd_gusextreme_es1688_create(struct snd_card *card,
+-		struct snd_es1688 *chip, struct device *dev, unsigned int n)
++static int snd_gusextreme_es1688_create(struct snd_card *card,
++					struct snd_es1688 *chip,
++					struct device *dev, unsigned int n)
+ {
+ 	static long possible_ports[] = {0x220, 0x240, 0x260};
+ 	static int possible_irqs[] = {5, 9, 10, 7, -1};
+@@ -132,8 +133,9 @@ static int __devinit snd_gusextreme_es1688_create(struct snd_card *card,
+ 	return error;
+ }
+ 
+-static int __devinit snd_gusextreme_gus_card_create(struct snd_card *card,
+-		struct device *dev, unsigned int n, struct snd_gus_card **rgus)
++static int snd_gusextreme_gus_card_create(struct snd_card *card,
++					  struct device *dev, unsigned int n,
++					  struct snd_gus_card **rgus)
+ {
+ 	static int possible_irqs[] = {11, 12, 15, 9, 5, 7, 3, -1};
+ 	static int possible_dmas[] = {5, 6, 7, 3, 1, -1};
+@@ -156,8 +158,8 @@ static int __devinit snd_gusextreme_gus_card_create(struct snd_card *card,
+ 			0, channels[n], pcm_channels[n], 0, rgus);
+ }
+ 
+-static int __devinit snd_gusextreme_detect(struct snd_gus_card *gus,
+-	struct snd_es1688 *es1688)
++static int snd_gusextreme_detect(struct snd_gus_card *gus,
++				 struct snd_es1688 *es1688)
+ {
+ 	unsigned long flags;
+ 	unsigned char d;
+@@ -206,7 +208,7 @@ static int __devinit snd_gusextreme_detect(struct snd_gus_card *gus,
+ 	return 0;
+ }
+ 
+-static int __devinit snd_gusextreme_mixer(struct snd_card *card)
++static int snd_gusextreme_mixer(struct snd_card *card)
+ {
+ 	struct snd_ctl_elem_id id1, id2;
+ 	int error;
+@@ -232,7 +234,7 @@ static int __devinit snd_gusextreme_mixer(struct snd_card *card)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_gusextreme_probe(struct device *dev, unsigned int n)
++static int snd_gusextreme_probe(struct device *dev, unsigned int n)
+ {
+ 	struct snd_card *card;
+ 	struct snd_gus_card *gus;
+@@ -339,7 +341,7 @@ out:	snd_card_free(card);
+ 	return error;
+ }
+ 
+-static int __devexit snd_gusextreme_remove(struct device *dev, unsigned int n)
++static int snd_gusextreme_remove(struct device *dev, unsigned int n)
+ {
+ 	snd_card_free(dev_get_drvdata(dev));
+ 	dev_set_drvdata(dev, NULL);
+@@ -349,7 +351,7 @@ static int __devexit snd_gusextreme_remove(struct device *dev, unsigned int n)
+ static struct isa_driver snd_gusextreme_driver = {
+ 	.match		= snd_gusextreme_match,
+ 	.probe		= snd_gusextreme_probe,
+-	.remove		= __devexit_p(snd_gusextreme_remove),
++	.remove		= snd_gusextreme_remove,
+ #if 0	/* FIXME */
+ 	.suspend	= snd_gusextreme_suspend,
+ 	.resume		= snd_gusextreme_resume,
+diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
+index 41c3f448745f..c309a5d0e7e1 100644
+--- a/sound/isa/gus/gusmax.c
++++ b/sound/isa/gus/gusmax.c
+@@ -82,7 +82,7 @@ struct snd_gusmax {
+ 
+ #define PFX	"gusmax: "
+ 
+-static int __devinit snd_gusmax_detect(struct snd_gus_card * gus)
++static int snd_gusmax_detect(struct snd_gus_card *gus)
+ {
+ 	unsigned char d;
+ 
+@@ -124,8 +124,8 @@ static irqreturn_t snd_gusmax_interrupt(int irq, void *dev_id)
+ 	return IRQ_RETVAL(handled);
+ }
+ 
+-static void __devinit snd_gusmax_init(int dev, struct snd_card *card,
+-				      struct snd_gus_card * gus)
++static void snd_gusmax_init(int dev, struct snd_card *card,
++			    struct snd_gus_card *gus)
+ {
+ 	gus->equal_irq = 1;
+ 	gus->codec_flag = 1;
+@@ -140,7 +140,7 @@ static void __devinit snd_gusmax_init(int dev, struct snd_card *card,
+ 	outb(gus->max_cntrl_val, GUSP(gus, MAXCNTRLPORT));
+ }
+ 
+-static int __devinit snd_gusmax_mixer(struct snd_wss *chip)
++static int snd_gusmax_mixer(struct snd_wss *chip)
+ {
+ 	struct snd_card *card = chip->card;
+ 	struct snd_ctl_elem_id id1, id2;
+@@ -199,12 +199,12 @@ static void snd_gusmax_free(struct snd_card *card)
+ 		free_irq(maxcard->irq, (void *)maxcard);
+ }
+ 
+-static int __devinit snd_gusmax_match(struct device *pdev, unsigned int dev)
++static int snd_gusmax_match(struct device *pdev, unsigned int dev)
+ {
+ 	return enable[dev];
+ }
+ 
+-static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev)
++static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
+ {
+ 	static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
+ 	static int possible_dmas[] = {5, 6, 7, 1, 3, -1};
+@@ -354,7 +354,7 @@ static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev)
+ 	return err;
+ }
+ 
+-static int __devexit snd_gusmax_remove(struct device *devptr, unsigned int dev)
++static int snd_gusmax_remove(struct device *devptr, unsigned int dev)
+ {
+ 	snd_card_free(dev_get_drvdata(devptr));
+ 	dev_set_drvdata(devptr, NULL);
+@@ -366,7 +366,7 @@ static int __devexit snd_gusmax_remove(struct device *devptr, unsigned int dev)
+ static struct isa_driver snd_gusmax_driver = {
+ 	.match		= snd_gusmax_match,
+ 	.probe		= snd_gusmax_probe,
+-	.remove		= __devexit_p(snd_gusmax_remove),
++	.remove		= snd_gusmax_remove,
+ 	/* FIXME: suspend/resume */
+ 	.driver		= {
+ 		.name	= DEV_NAME
+diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
+index 3fc8b66fd167..78bc5744e89a 100644
+--- a/sound/isa/gus/interwave.c
++++ b/sound/isa/gus/interwave.c
+@@ -207,9 +207,9 @@ static struct snd_i2c_bit_ops snd_interwave_i2c_bit_ops = {
+ 	.getdata  = snd_interwave_i2c_getdataline,
+ };
+ 
+-static int __devinit snd_interwave_detect_stb(struct snd_interwave *iwcard,
+-					      struct snd_gus_card * gus, int dev,
+-					      struct snd_i2c_bus **rbus)
++static int snd_interwave_detect_stb(struct snd_interwave *iwcard,
++				    struct snd_gus_card *gus, int dev,
++				    struct snd_i2c_bus **rbus)
+ {
+ 	unsigned long port;
+ 	struct snd_i2c_bus *bus;
+@@ -249,11 +249,11 @@ static int __devinit snd_interwave_detect_stb(struct snd_interwave *iwcard,
+ }
+ #endif
+ 
+-static int __devinit snd_interwave_detect(struct snd_interwave *iwcard,
+-				          struct snd_gus_card * gus,
+-				          int dev
++static int snd_interwave_detect(struct snd_interwave *iwcard,
++				struct snd_gus_card *gus,
++				int dev
+ #ifdef SNDRV_STB
+-				          , struct snd_i2c_bus **rbus
++				, struct snd_i2c_bus **rbus
+ #endif
+ 				          )
+ {
+@@ -318,7 +318,7 @@ static irqreturn_t snd_interwave_interrupt(int irq, void *dev_id)
+ 	return IRQ_RETVAL(handled);
+ }
+ 
+-static void __devinit snd_interwave_reset(struct snd_gus_card * gus)
++static void snd_interwave_reset(struct snd_gus_card *gus)
+ {
+ 	snd_gf1_write8(gus, SNDRV_GF1_GB_RESET, 0x00);
+ 	udelay(160);
+@@ -326,7 +326,7 @@ static void __devinit snd_interwave_reset(struct snd_gus_card * gus)
+ 	udelay(160);
+ }
+ 
+-static void __devinit snd_interwave_bank_sizes(struct snd_gus_card * gus, int *sizes)
++static void snd_interwave_bank_sizes(struct snd_gus_card *gus, int *sizes)
+ {
+ 	unsigned int idx;
+ 	unsigned int local;
+@@ -377,7 +377,7 @@ struct rom_hdr {
+ 	/* 511 */ unsigned char csum;
+ };
+ 
+-static void __devinit snd_interwave_detect_memory(struct snd_gus_card * gus)
++static void snd_interwave_detect_memory(struct snd_gus_card *gus)
+ {
+ 	static unsigned int lmc[13] =
+ 	{
+@@ -475,7 +475,7 @@ static void __devinit snd_interwave_detect_memory(struct snd_gus_card * gus)
+ 		snd_interwave_reset(gus);
+ }
+ 
+-static void __devinit snd_interwave_init(int dev, struct snd_gus_card * gus)
++static void snd_interwave_init(int dev, struct snd_gus_card *gus)
+ {
+ 	unsigned long flags;
+ 
+@@ -508,7 +508,7 @@ WSS_DOUBLE("Mic Playback Volume", 0,
+ 		CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 0, 0, 31, 1)
+ };
+ 
+-static int __devinit snd_interwave_mixer(struct snd_wss *chip)
++static int snd_interwave_mixer(struct snd_wss *chip)
+ {
+ 	struct snd_card *card = chip->card;
+ 	struct snd_ctl_elem_id id1, id2;
+@@ -558,9 +558,9 @@ static int __devinit snd_interwave_mixer(struct snd_wss *chip)
+ 
+ #ifdef CONFIG_PNP
+ 
+-static int __devinit snd_interwave_pnp(int dev, struct snd_interwave *iwcard,
+-				       struct pnp_card_link *card,
+-				       const struct pnp_card_device_id *id)
++static int snd_interwave_pnp(int dev, struct snd_interwave *iwcard,
++			     struct pnp_card_link *card,
++			     const struct pnp_card_device_id *id)
+ {
+ 	struct pnp_dev *pdev;
+ 	int err;
+@@ -644,7 +644,7 @@ static int snd_interwave_card_new(int dev, struct snd_card **cardp)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_interwave_probe(struct snd_card *card, int dev)
++static int snd_interwave_probe(struct snd_card *card, int dev)
+ {
+ 	int xirq, xdma1, xdma2;
+ 	struct snd_interwave *iwcard = card->private_data;
+@@ -775,7 +775,7 @@ static int __devinit snd_interwave_probe(struct snd_card *card, int dev)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_interwave_isa_probe1(int dev, struct device *devptr)
++static int snd_interwave_isa_probe1(int dev, struct device *devptr)
+ {
+ 	struct snd_card *card;
+ 	int err;
+@@ -793,8 +793,8 @@ static int __devinit snd_interwave_isa_probe1(int dev, struct device *devptr)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_interwave_isa_match(struct device *pdev,
+-					     unsigned int dev)
++static int snd_interwave_isa_match(struct device *pdev,
++				   unsigned int dev)
+ {
+ 	if (!enable[dev])
+ 		return 0;
+@@ -805,8 +805,8 @@ static int __devinit snd_interwave_isa_match(struct device *pdev,
+ 	return 1;
+ }
+ 
+-static int __devinit snd_interwave_isa_probe(struct device *pdev,
+-					     unsigned int dev)
++static int snd_interwave_isa_probe(struct device *pdev,
++				   unsigned int dev)
+ {
+ 	int err;
+ 	static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
+@@ -846,7 +846,7 @@ static int __devinit snd_interwave_isa_probe(struct device *pdev,
+ 	}
+ }
+ 
+-static int __devexit snd_interwave_isa_remove(struct device *devptr, unsigned int dev)
++static int snd_interwave_isa_remove(struct device *devptr, unsigned int dev)
+ {
+ 	snd_card_free(dev_get_drvdata(devptr));
+ 	dev_set_drvdata(devptr, NULL);
+@@ -856,7 +856,7 @@ static int __devexit snd_interwave_isa_remove(struct device *devptr, unsigned in
+ static struct isa_driver snd_interwave_driver = {
+ 	.match		= snd_interwave_isa_match,
+ 	.probe		= snd_interwave_isa_probe,
+-	.remove		= __devexit_p(snd_interwave_isa_remove),
++	.remove		= snd_interwave_isa_remove,
+ 	/* FIXME: suspend,resume */
+ 	.driver		= {
+ 		.name	= INTERWAVE_DRIVER
+@@ -864,8 +864,8 @@ static struct isa_driver snd_interwave_driver = {
+ };
+ 
+ #ifdef CONFIG_PNP
+-static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard,
+-					      const struct pnp_card_device_id *pid)
++static int snd_interwave_pnp_detect(struct pnp_card_link *pcard,
++				    const struct pnp_card_device_id *pid)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -896,7 +896,7 @@ static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_interwave_pnp_remove(struct pnp_card_link * pcard)
++static void snd_interwave_pnp_remove(struct pnp_card_link *pcard)
+ {
+ 	snd_card_free(pnp_get_card_drvdata(pcard));
+ 	pnp_set_card_drvdata(pcard, NULL);
+@@ -907,7 +907,7 @@ static struct pnp_card_driver interwave_pnpc_driver = {
+ 	.name = INTERWAVE_PNP_DRIVER,
+ 	.id_table = snd_interwave_pnpids,
+ 	.probe = snd_interwave_pnp_detect,
+-	.remove = __devexit_p(snd_interwave_pnp_remove),
++	.remove = snd_interwave_pnp_remove,
+ 	/* FIXME: suspend,resume */
+ };
+ 
+diff --git a/sound/isa/msnd/msnd.h b/sound/isa/msnd/msnd.h
+index a168ba3313ac..dbac3a42347b 100644
+--- a/sound/isa/msnd/msnd.h
++++ b/sound/isa/msnd/msnd.h
+@@ -303,6 +303,6 @@ int snd_msndmidi_new(struct snd_card *card, int device);
+ void snd_msndmidi_input_read(void *mpu);
+ 
+ void snd_msndmix_setup(struct snd_msnd *chip);
+-int __devinit snd_msndmix_new(struct snd_card *card);
++int snd_msndmix_new(struct snd_card *card);
+ int snd_msndmix_force_recsrc(struct snd_msnd *chip, int recsrc);
+ #endif /* __MSND_H */
+diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c
+index 29cc8e162b02..ddabb406b14c 100644
+--- a/sound/isa/msnd/msnd_pinnacle.c
++++ b/sound/isa/msnd/msnd_pinnacle.c
+@@ -78,7 +78,7 @@
+ #  define LOGNAME			"snd_msnd_pinnacle"
+ #endif
+ 
+-static void __devinit set_default_audio_parameters(struct snd_msnd *chip)
++static void set_default_audio_parameters(struct snd_msnd *chip)
+ {
+ 	chip->play_sample_size = DEFSAMPLESIZE;
+ 	chip->play_sample_rate = DEFSAMPLERATE;
+@@ -213,7 +213,7 @@ static int snd_msnd_reset_dsp(long io, unsigned char *info)
+ 	return -EIO;
+ }
+ 
+-static int __devinit snd_msnd_probe(struct snd_card *card)
++static int snd_msnd_probe(struct snd_card *card)
+ {
+ 	struct snd_msnd *chip = card->private_data;
+ 	unsigned char info;
+@@ -497,7 +497,7 @@ static int snd_msnd_send_dsp_cmd_chk(struct snd_msnd *chip, u8 cmd)
+ 	return snd_msnd_send_dsp_cmd(chip, cmd);
+ }
+ 
+-static int __devinit snd_msnd_calibrate_adc(struct snd_msnd *chip, u16 srate)
++static int snd_msnd_calibrate_adc(struct snd_msnd *chip, u16 srate)
+ {
+ 	snd_printdd("snd_msnd_calibrate_adc(%i)\n", srate);
+ 	writew(srate, chip->SMA + SMA_wCalFreqAtoD);
+@@ -535,7 +535,7 @@ static void snd_msnd_mpu401_close(struct snd_mpu401 *mpu)
+ static long mpu_io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
+ static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
+ 
+-static int __devinit snd_msnd_attach(struct snd_card *card)
++static int snd_msnd_attach(struct snd_card *card)
+ {
+ 	struct snd_msnd *chip = card->private_data;
+ 	int err;
+@@ -634,7 +634,7 @@ static int __devinit snd_msnd_attach(struct snd_card *card)
+ }
+ 
+ 
+-static void __devexit snd_msnd_unload(struct snd_card *card)
++static void snd_msnd_unload(struct snd_card *card)
+ {
+ 	struct snd_msnd *chip = card->private_data;
+ 
+@@ -649,7 +649,7 @@ static void __devexit snd_msnd_unload(struct snd_card *card)
+ 
+ /* Pinnacle/Fiji Logical Device Configuration */
+ 
+-static int __devinit snd_msnd_write_cfg(int cfg, int reg, int value)
++static int snd_msnd_write_cfg(int cfg, int reg, int value)
+ {
+ 	outb(reg, cfg);
+ 	outb(value, cfg + 1);
+@@ -660,7 +660,7 @@ static int __devinit snd_msnd_write_cfg(int cfg, int reg, int value)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_msnd_write_cfg_io0(int cfg, int num, u16 io)
++static int snd_msnd_write_cfg_io0(int cfg, int num, u16 io)
+ {
+ 	if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+ 		return -EIO;
+@@ -671,7 +671,7 @@ static int __devinit snd_msnd_write_cfg_io0(int cfg, int num, u16 io)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_msnd_write_cfg_io1(int cfg, int num, u16 io)
++static int snd_msnd_write_cfg_io1(int cfg, int num, u16 io)
+ {
+ 	if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+ 		return -EIO;
+@@ -682,7 +682,7 @@ static int __devinit snd_msnd_write_cfg_io1(int cfg, int num, u16 io)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_msnd_write_cfg_irq(int cfg, int num, u16 irq)
++static int snd_msnd_write_cfg_irq(int cfg, int num, u16 irq)
+ {
+ 	if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+ 		return -EIO;
+@@ -693,7 +693,7 @@ static int __devinit snd_msnd_write_cfg_irq(int cfg, int num, u16 irq)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_msnd_write_cfg_mem(int cfg, int num, int mem)
++static int snd_msnd_write_cfg_mem(int cfg, int num, int mem)
+ {
+ 	u16 wmem;
+ 
+@@ -711,7 +711,7 @@ static int __devinit snd_msnd_write_cfg_mem(int cfg, int num, int mem)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_msnd_activate_logical(int cfg, int num)
++static int snd_msnd_activate_logical(int cfg, int num)
+ {
+ 	if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+ 		return -EIO;
+@@ -720,8 +720,8 @@ static int __devinit snd_msnd_activate_logical(int cfg, int num)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_msnd_write_cfg_logical(int cfg, int num, u16 io0,
+-						u16 io1, u16 irq, int mem)
++static int snd_msnd_write_cfg_logical(int cfg, int num, u16 io0,
++				      u16 io1, u16 irq, int mem)
+ {
+ 	if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+ 		return -EIO;
+@@ -738,7 +738,7 @@ static int __devinit snd_msnd_write_cfg_logical(int cfg, int num, u16 io0,
+ 	return 0;
+ }
+ 
+-static int __devinit snd_msnd_pinnacle_cfg_reset(int cfg)
++static int snd_msnd_pinnacle_cfg_reset(int cfg)
+ {
+ 	int i;
+ 
+@@ -818,7 +818,7 @@ module_param_array(joystick_io, long, NULL, S_IRUGO);
+ #endif
+ 
+ 
+-static int __devinit snd_msnd_isa_match(struct device *pdev, unsigned int i)
++static int snd_msnd_isa_match(struct device *pdev, unsigned int i)
+ {
+ 	if (io[i] == SNDRV_AUTO_PORT)
+ 		return 0;
+@@ -888,7 +888,7 @@ static int __devinit snd_msnd_isa_match(struct device *pdev, unsigned int i)
+ 	return 1;
+ }
+ 
+-static int __devinit snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
++static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
+ {
+ 	int err;
+ 	struct snd_card *card;
+@@ -1061,7 +1061,7 @@ static int __devinit snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
+ #endif
+ }
+ 
+-static int __devexit snd_msnd_isa_remove(struct device *pdev, unsigned int dev)
++static int snd_msnd_isa_remove(struct device *pdev, unsigned int dev)
+ {
+ 	snd_msnd_unload(dev_get_drvdata(pdev));
+ 	dev_set_drvdata(pdev, NULL);
+@@ -1073,7 +1073,7 @@ static int __devexit snd_msnd_isa_remove(struct device *pdev, unsigned int dev)
+ static struct isa_driver snd_msnd_driver = {
+ 	.match		= snd_msnd_isa_match,
+ 	.probe		= snd_msnd_isa_probe,
+-	.remove		= __devexit_p(snd_msnd_isa_remove),
++	.remove		= snd_msnd_isa_remove,
+ 	/* FIXME: suspend, resume */
+ 	.driver		= {
+ 		.name	= DEV_NAME
+@@ -1081,8 +1081,8 @@ static struct isa_driver snd_msnd_driver = {
+ };
+ 
+ #ifdef CONFIG_PNP
+-static int __devinit snd_msnd_pnp_detect(struct pnp_card_link *pcard,
+-					 const struct pnp_card_device_id *pid)
++static int snd_msnd_pnp_detect(struct pnp_card_link *pcard,
++			       const struct pnp_card_device_id *pid)
+ {
+ 	static int idx;
+ 	struct pnp_dev *pnp_dev;
+@@ -1185,7 +1185,7 @@ static int __devinit snd_msnd_pnp_detect(struct pnp_card_link *pcard,
+ 	return ret;
+ }
+ 
+-static void __devexit snd_msnd_pnp_remove(struct pnp_card_link *pcard)
++static void snd_msnd_pnp_remove(struct pnp_card_link *pcard)
+ {
+ 	snd_msnd_unload(pnp_get_card_drvdata(pcard));
+ 	pnp_set_card_drvdata(pcard, NULL);
+@@ -1207,7 +1207,7 @@ static struct pnp_card_driver msnd_pnpc_driver = {
+ 	.name = "msnd_pinnacle",
+ 	.id_table = msnd_pnpids,
+ 	.probe = snd_msnd_pnp_detect,
+-	.remove = __devexit_p(snd_msnd_pnp_remove),
++	.remove = snd_msnd_pnp_remove,
+ };
+ #endif /* CONFIG_PNP */
+ 
+diff --git a/sound/isa/msnd/msnd_pinnacle_mixer.c b/sound/isa/msnd/msnd_pinnacle_mixer.c
+index 1de59d441426..031dc69b7470 100644
+--- a/sound/isa/msnd/msnd_pinnacle_mixer.c
++++ b/sound/isa/msnd/msnd_pinnacle_mixer.c
+@@ -302,7 +302,7 @@ DUMMY_VOLUME("Monitor",	0, MSND_MIXER_IMIX),
+ };
+ 
+ 
+-int __devinit snd_msndmix_new(struct snd_card *card)
++int snd_msndmix_new(struct snd_card *card)
+ {
+ 	struct snd_msnd *chip = card->private_data;
+ 	unsigned int idx;
+diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
+index f6cc0b917ef0..075777a6cf0b 100644
+--- a/sound/isa/opl3sa2.c
++++ b/sound/isa/opl3sa2.c
+@@ -221,7 +221,7 @@ static void snd_opl3sa2_write(struct snd_opl3sa2 *chip, unsigned char reg, unsig
+ 	spin_unlock_irqrestore(&chip->reg_lock, flags);
+ }
+ 
+-static int __devinit snd_opl3sa2_detect(struct snd_card *card)
++static int snd_opl3sa2_detect(struct snd_card *card)
+ {
+ 	struct snd_opl3sa2 *chip = card->private_data;
+ 	unsigned long port;
+@@ -496,7 +496,7 @@ static void snd_opl3sa2_master_free(struct snd_kcontrol *kcontrol)
+ 	chip->master_volume = NULL;
+ }
+ 
+-static int __devinit snd_opl3sa2_mixer(struct snd_card *card)
++static int snd_opl3sa2_mixer(struct snd_card *card)
+ {
+ 	struct snd_opl3sa2 *chip = card->private_data;
+ 	struct snd_ctl_elem_id id1, id2;
+@@ -596,8 +596,8 @@ static int snd_opl3sa2_resume(struct snd_card *card)
+ #endif /* CONFIG_PM */
+ 
+ #ifdef CONFIG_PNP
+-static int __devinit snd_opl3sa2_pnp(int dev, struct snd_opl3sa2 *chip,
+-				     struct pnp_dev *pdev)
++static int snd_opl3sa2_pnp(int dev, struct snd_opl3sa2 *chip,
++			   struct pnp_dev *pdev)
+ {
+ 	if (pnp_activate_dev(pdev) < 0) {
+ 		snd_printk(KERN_ERR "PnP configure failure (out of resources?)\n");
+@@ -647,7 +647,7 @@ static int snd_opl3sa2_card_new(int dev, struct snd_card **cardp)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev)
++static int snd_opl3sa2_probe(struct snd_card *card, int dev)
+ {
+ 	int xirq, xdma1, xdma2;
+ 	struct snd_opl3sa2 *chip;
+@@ -721,8 +721,8 @@ static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev)
+ }
+ 
+ #ifdef CONFIG_PNP
+-static int __devinit snd_opl3sa2_pnp_detect(struct pnp_dev *pdev,
+-					    const struct pnp_device_id *id)
++static int snd_opl3sa2_pnp_detect(struct pnp_dev *pdev,
++				  const struct pnp_device_id *id)
+ {
+ 	static int dev;
+ 	int err;
+@@ -754,7 +754,7 @@ static int __devinit snd_opl3sa2_pnp_detect(struct pnp_dev *pdev,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_opl3sa2_pnp_remove(struct pnp_dev * pdev)
++static void snd_opl3sa2_pnp_remove(struct pnp_dev *pdev)
+ {
+ 	snd_card_free(pnp_get_drvdata(pdev));
+ 	pnp_set_drvdata(pdev, NULL);
+@@ -775,15 +775,15 @@ static struct pnp_driver opl3sa2_pnp_driver = {
+ 	.name = "snd-opl3sa2-pnpbios",
+ 	.id_table = snd_opl3sa2_pnpbiosids,
+ 	.probe = snd_opl3sa2_pnp_detect,
+-	.remove = __devexit_p(snd_opl3sa2_pnp_remove),
++	.remove = snd_opl3sa2_pnp_remove,
+ #ifdef CONFIG_PM
+ 	.suspend = snd_opl3sa2_pnp_suspend,
+ 	.resume = snd_opl3sa2_pnp_resume,
+ #endif
+ };
+ 
+-static int __devinit snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard,
+-					     const struct pnp_card_device_id *id)
++static int snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard,
++				   const struct pnp_card_device_id *id)
+ {
+ 	static int dev;
+ 	struct pnp_dev *pdev;
+@@ -820,7 +820,7 @@ static int __devinit snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_opl3sa2_pnp_cremove(struct pnp_card_link * pcard)
++static void snd_opl3sa2_pnp_cremove(struct pnp_card_link *pcard)
+ {
+ 	snd_card_free(pnp_get_card_drvdata(pcard));
+ 	pnp_set_card_drvdata(pcard, NULL);
+@@ -842,7 +842,7 @@ static struct pnp_card_driver opl3sa2_pnpc_driver = {
+ 	.name = "snd-opl3sa2-cpnp",
+ 	.id_table = snd_opl3sa2_pnpids,
+ 	.probe = snd_opl3sa2_pnp_cdetect,
+-	.remove = __devexit_p(snd_opl3sa2_pnp_cremove),
++	.remove = snd_opl3sa2_pnp_cremove,
+ #ifdef CONFIG_PM
+ 	.suspend = snd_opl3sa2_pnp_csuspend,
+ 	.resume = snd_opl3sa2_pnp_cresume,
+@@ -850,8 +850,8 @@ static struct pnp_card_driver opl3sa2_pnpc_driver = {
+ };
+ #endif /* CONFIG_PNP */
+ 
+-static int __devinit snd_opl3sa2_isa_match(struct device *pdev,
+-					   unsigned int dev)
++static int snd_opl3sa2_isa_match(struct device *pdev,
++				 unsigned int dev)
+ {
+ 	if (!enable[dev])
+ 		return 0;
+@@ -878,8 +878,8 @@ static int __devinit snd_opl3sa2_isa_match(struct device *pdev,
+ 	return 1;
+ }
+ 
+-static int __devinit snd_opl3sa2_isa_probe(struct device *pdev,
+-					   unsigned int dev)
++static int snd_opl3sa2_isa_probe(struct device *pdev,
++				 unsigned int dev)
+ {
+ 	struct snd_card *card;
+ 	int err;
+@@ -896,8 +896,8 @@ static int __devinit snd_opl3sa2_isa_probe(struct device *pdev,
+ 	return 0;
+ }
+ 
+-static int __devexit snd_opl3sa2_isa_remove(struct device *devptr,
+-					    unsigned int dev)
++static int snd_opl3sa2_isa_remove(struct device *devptr,
++				  unsigned int dev)
+ {
+ 	snd_card_free(dev_get_drvdata(devptr));
+ 	dev_set_drvdata(devptr, NULL);
+@@ -922,7 +922,7 @@ static int snd_opl3sa2_isa_resume(struct device *dev, unsigned int n)
+ static struct isa_driver snd_opl3sa2_isa_driver = {
+ 	.match		= snd_opl3sa2_isa_match,
+ 	.probe		= snd_opl3sa2_isa_probe,
+-	.remove		= __devexit_p(snd_opl3sa2_isa_remove),
++	.remove		= snd_opl3sa2_isa_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= snd_opl3sa2_isa_suspend,
+ 	.resume		= snd_opl3sa2_isa_resume,
+diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c
+index 4a7ff4e8985b..c3da1df9371d 100644
+--- a/sound/isa/opti9xx/miro.c
++++ b/sound/isa/opti9xx/miro.c
+@@ -587,7 +587,7 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol,
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_miro_controls[] __devinitdata = {
++static struct snd_kcontrol_new snd_miro_controls[] = {
+ MIRO_DOUBLE("Master Playback Volume", 0, ACI_GET_MASTER, ACI_SET_MASTER),
+ MIRO_DOUBLE("Mic Playback Volume", 1, ACI_GET_MIC, ACI_SET_MIC),
+ MIRO_DOUBLE("Line Playback Volume", 1, ACI_GET_LINE, ACI_SET_LINE),
+@@ -599,7 +599,7 @@ MIRO_DOUBLE("Aux Playback Volume", 2, ACI_GET_LINE2, ACI_SET_LINE2),
+ 
+ /* Equalizer with seven bands (only PCM20) 
+    from -12dB up to +12dB on each band */
+-static struct snd_kcontrol_new snd_miro_eq_controls[] __devinitdata = {
++static struct snd_kcontrol_new snd_miro_eq_controls[] = {
+ MIRO_DOUBLE("Tone Control - 28 Hz", 0, ACI_GET_EQ1, ACI_SET_EQ1),
+ MIRO_DOUBLE("Tone Control - 160 Hz", 0, ACI_GET_EQ2, ACI_SET_EQ2),
+ MIRO_DOUBLE("Tone Control - 400 Hz", 0, ACI_GET_EQ3, ACI_SET_EQ3),
+@@ -609,15 +609,15 @@ MIRO_DOUBLE("Tone Control - 6.3 kHz", 0, ACI_GET_EQ6, ACI_SET_EQ6),
+ MIRO_DOUBLE("Tone Control - 16 kHz", 0, ACI_GET_EQ7, ACI_SET_EQ7),
+ };
+ 
+-static struct snd_kcontrol_new snd_miro_radio_control[] __devinitdata = {
++static struct snd_kcontrol_new snd_miro_radio_control[] = {
+ MIRO_DOUBLE("Radio Playback Volume", 0, ACI_GET_LINE1, ACI_SET_LINE1),
+ };
+ 
+-static struct snd_kcontrol_new snd_miro_line_control[] __devinitdata = {
++static struct snd_kcontrol_new snd_miro_line_control[] = {
+ MIRO_DOUBLE("Line Playback Volume", 2, ACI_GET_LINE1, ACI_SET_LINE1),
+ };
+ 
+-static struct snd_kcontrol_new snd_miro_preamp_control[] __devinitdata = {
++static struct snd_kcontrol_new snd_miro_preamp_control[] = {
+ {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "Mic Boost",
+@@ -627,7 +627,7 @@ static struct snd_kcontrol_new snd_miro_preamp_control[] __devinitdata = {
+ 	.put = snd_miro_put_preamp,
+ }};
+ 
+-static struct snd_kcontrol_new snd_miro_amp_control[] __devinitdata = {
++static struct snd_kcontrol_new snd_miro_amp_control[] = {
+ {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "Line Boost",
+@@ -637,7 +637,7 @@ static struct snd_kcontrol_new snd_miro_amp_control[] __devinitdata = {
+ 	.put = snd_miro_put_amp,
+ }};
+ 
+-static struct snd_kcontrol_new snd_miro_capture_control[] __devinitdata = {
++static struct snd_kcontrol_new snd_miro_capture_control[] = {
+ {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "PCM Capture Switch",
+@@ -647,7 +647,7 @@ static struct snd_kcontrol_new snd_miro_capture_control[] __devinitdata = {
+ 	.put = snd_miro_put_capture,
+ }};
+ 
+-static unsigned char aci_init_values[][2] __devinitdata = {
++static unsigned char aci_init_values[][2] = {
+ 	{ ACI_SET_MUTE, 0x00 },
+ 	{ ACI_SET_POWERAMP, 0x00 },
+ 	{ ACI_SET_PREAMP, 0x00 },
+@@ -670,7 +670,7 @@ static unsigned char aci_init_values[][2] __devinitdata = {
+ 	{ ACI_SET_MASTER + 1, 0x20 },
+ };
+ 
+-static int __devinit snd_set_aci_init_values(struct snd_miro *miro)
++static int snd_set_aci_init_values(struct snd_miro *miro)
+ {
+ 	int idx, error;
+ 	struct snd_miro_aci *aci = miro->aci;
+@@ -713,8 +713,8 @@ static int __devinit snd_set_aci_init_values(struct snd_miro *miro)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_miro_mixer(struct snd_card *card,
+-				    struct snd_miro *miro)
++static int snd_miro_mixer(struct snd_card *card,
++			  struct snd_miro *miro)
+ {
+ 	unsigned int idx;
+ 	int err;
+@@ -771,8 +771,8 @@ static int __devinit snd_miro_mixer(struct snd_card *card,
+ 	return 0;
+ }
+ 
+-static int __devinit snd_miro_init(struct snd_miro *chip,
+-				   unsigned short hardware)
++static int snd_miro_init(struct snd_miro *chip,
++			 unsigned short hardware)
+ {
+ 	static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};
+ 
+@@ -989,8 +989,8 @@ static void snd_miro_proc_read(struct snd_info_entry * entry,
+ 	snd_iprintf(buffer, "  preamp  : 0x%x\n", aci->aci_preamp);
+ }
+ 
+-static void __devinit snd_miro_proc_init(struct snd_card *card,
+-					 struct snd_miro *miro)
++static void snd_miro_proc_init(struct snd_card *card,
++			       struct snd_miro *miro)
+ {
+ 	struct snd_info_entry *entry;
+ 
+@@ -1002,7 +1002,7 @@ static void __devinit snd_miro_proc_init(struct snd_card *card,
+  *  Init
+  */
+ 
+-static int __devinit snd_miro_configure(struct snd_miro *chip)
++static int snd_miro_configure(struct snd_miro *chip)
+ {
+ 	unsigned char wss_base_bits;
+ 	unsigned char irq_bits;
+@@ -1162,7 +1162,7 @@ static int __devinit snd_miro_configure(struct snd_miro *chip)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_miro_opti_check(struct snd_miro *chip)
++static int snd_miro_opti_check(struct snd_miro *chip)
+ {
+ 	unsigned char value;
+ 
+@@ -1182,8 +1182,8 @@ static int __devinit snd_miro_opti_check(struct snd_miro *chip)
+ 	return -ENODEV;
+ }
+ 
+-static int __devinit snd_card_miro_detect(struct snd_card *card,
+-					  struct snd_miro *chip)
++static int snd_card_miro_detect(struct snd_card *card,
++				struct snd_miro *chip)
+ {
+ 	int i, err;
+ 
+@@ -1200,8 +1200,8 @@ static int __devinit snd_card_miro_detect(struct snd_card *card,
+ 	return -ENODEV;
+ }
+ 
+-static int __devinit snd_card_miro_aci_detect(struct snd_card *card,
+-					      struct snd_miro *miro)
++static int snd_card_miro_aci_detect(struct snd_card *card,
++				    struct snd_miro *miro)
+ {
+ 	unsigned char regval;
+ 	int i;
+@@ -1265,7 +1265,7 @@ static void snd_card_miro_free(struct snd_card *card)
+ 	release_and_free_resource(miro->res_mc_base);
+ }
+ 
+-static int __devinit snd_miro_probe(struct snd_card *card)
++static int snd_miro_probe(struct snd_card *card)
+ {
+ 	int error;
+ 	struct snd_miro *miro = card->private_data;
+@@ -1386,7 +1386,7 @@ static int __devinit snd_miro_probe(struct snd_card *card)
+ 	return snd_card_register(card);
+ }
+ 
+-static int __devinit snd_miro_isa_match(struct device *devptr, unsigned int n)
++static int snd_miro_isa_match(struct device *devptr, unsigned int n)
+ {
+ #ifdef CONFIG_PNP
+ 	if (snd_miro_pnp_is_probed)
+@@ -1397,7 +1397,7 @@ static int __devinit snd_miro_isa_match(struct device *devptr, unsigned int n)
+ 	return 1;
+ }
+ 
+-static int __devinit snd_miro_isa_probe(struct device *devptr, unsigned int n)
++static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
+ {
+ 	static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
+ 	static long possible_mpu_ports[] = {0x330, 0x300, 0x310, 0x320, -1};
+@@ -1491,8 +1491,8 @@ static int __devinit snd_miro_isa_probe(struct device *devptr, unsigned int n)
+ 	return 0;
+ }
+ 
+-static int __devexit snd_miro_isa_remove(struct device *devptr,
+-					 unsigned int dev)
++static int snd_miro_isa_remove(struct device *devptr,
++			       unsigned int dev)
+ {
+ 	snd_card_free(dev_get_drvdata(devptr));
+ 	dev_set_drvdata(devptr, NULL);
+@@ -1504,7 +1504,7 @@ static int __devexit snd_miro_isa_remove(struct device *devptr,
+ static struct isa_driver snd_miro_driver = {
+ 	.match		= snd_miro_isa_match,
+ 	.probe		= snd_miro_isa_probe,
+-	.remove		= __devexit_p(snd_miro_isa_remove),
++	.remove		= snd_miro_isa_remove,
+ 	/* FIXME: suspend/resume */
+ 	.driver		= {
+ 		.name	= DEV_NAME
+@@ -1513,9 +1513,9 @@ static struct isa_driver snd_miro_driver = {
+ 
+ #ifdef CONFIG_PNP
+ 
+-static int __devinit snd_card_miro_pnp(struct snd_miro *chip,
+-					struct pnp_card_link *card,
+-					const struct pnp_card_device_id *pid)
++static int snd_card_miro_pnp(struct snd_miro *chip,
++			     struct pnp_card_link *card,
++			     const struct pnp_card_device_id *pid)
+ {
+ 	struct pnp_dev *pdev;
+ 	int err;
+@@ -1574,8 +1574,8 @@ static int __devinit snd_card_miro_pnp(struct snd_miro *chip,
+ 	return 0;
+ }
+ 
+-static int __devinit snd_miro_pnp_probe(struct pnp_card_link *pcard,
+-					const struct pnp_card_device_id *pid)
++static int snd_miro_pnp_probe(struct pnp_card_link *pcard,
++			      const struct pnp_card_device_id *pid)
+ {
+ 	struct snd_card *card;
+ 	int err;
+@@ -1624,7 +1624,7 @@ static int __devinit snd_miro_pnp_probe(struct pnp_card_link *pcard,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_miro_pnp_remove(struct pnp_card_link * pcard)
++static void snd_miro_pnp_remove(struct pnp_card_link *pcard)
+ {
+ 	snd_card_free(pnp_get_card_drvdata(pcard));
+ 	pnp_set_card_drvdata(pcard, NULL);
+@@ -1636,7 +1636,7 @@ static struct pnp_card_driver miro_pnpc_driver = {
+ 	.name		= "miro",
+ 	.id_table	= snd_miro_pnpids,
+ 	.probe		= snd_miro_pnp_probe,
+-	.remove		= __devexit_p(snd_miro_pnp_remove),
++	.remove		= snd_miro_pnp_remove,
+ };
+ #endif
+ 
+diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
+index 2899c9fd1ceb..b41ed8661b23 100644
+--- a/sound/isa/opti9xx/opti92x-ad1848.c
++++ b/sound/isa/opti9xx/opti92x-ad1848.c
+@@ -186,8 +186,8 @@ static char * snd_opti9xx_names[] = {
+ 	"82C930",	"82C931",	"82C933"
+ };
+ 
+-static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip,
+-				      unsigned short hardware)
++static int snd_opti9xx_init(struct snd_opti9xx *chip,
++			    unsigned short hardware)
+ {
+ 	static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};
+ 
+@@ -593,7 +593,7 @@ WSS_DOUBLE_TLV("Aux Playback Volume", 0,
+ 		db_scale_4bit_12db_max),
+ };
+ 
+-static int __devinit snd_opti93x_mixer(struct snd_wss *chip)
++static int snd_opti93x_mixer(struct snd_wss *chip)
+ {
+ 	struct snd_card *card;
+ 	unsigned int idx;
+@@ -666,7 +666,7 @@ static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id)
+ 
+ #endif /* OPTi93X */
+ 
+-static int __devinit snd_opti9xx_read_check(struct snd_opti9xx *chip)
++static int snd_opti9xx_read_check(struct snd_opti9xx *chip)
+ {
+ 	unsigned char value;
+ #ifdef OPTi93X
+@@ -707,8 +707,8 @@ static int __devinit snd_opti9xx_read_check(struct snd_opti9xx *chip)
+ 	return -ENODEV;
+ }
+ 
+-static int __devinit snd_card_opti9xx_detect(struct snd_card *card,
+-					     struct snd_opti9xx *chip)
++static int snd_card_opti9xx_detect(struct snd_card *card,
++				   struct snd_opti9xx *chip)
+ {
+ 	int i, err;
+ 
+@@ -732,9 +732,9 @@ static int __devinit snd_card_opti9xx_detect(struct snd_card *card,
+ }
+ 
+ #ifdef CONFIG_PNP
+-static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
+-					  struct pnp_card_link *card,
+-					  const struct pnp_card_device_id *pid)
++static int snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
++				struct pnp_card_link *card,
++				const struct pnp_card_device_id *pid)
+ {
+ 	struct pnp_dev *pdev;
+ 	int err;
+@@ -817,7 +817,7 @@ static void snd_card_opti9xx_free(struct snd_card *card)
+ 	}
+ }
+ 
+-static int __devinit snd_opti9xx_probe(struct snd_card *card)
++static int snd_opti9xx_probe(struct snd_card *card)
+ {
+ 	static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
+ 	int error;
+@@ -952,8 +952,8 @@ static int snd_opti9xx_card_new(struct snd_card **cardp)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_opti9xx_isa_match(struct device *devptr,
+-					   unsigned int dev)
++static int snd_opti9xx_isa_match(struct device *devptr,
++				 unsigned int dev)
+ {
+ #ifdef CONFIG_PNP
+ 	if (snd_opti9xx_pnp_is_probed)
+@@ -964,8 +964,8 @@ static int __devinit snd_opti9xx_isa_match(struct device *devptr,
+ 	return 1;
+ }
+ 
+-static int __devinit snd_opti9xx_isa_probe(struct device *devptr,
+-					   unsigned int dev)
++static int snd_opti9xx_isa_probe(struct device *devptr,
++				 unsigned int dev)
+ {
+ 	struct snd_card *card;
+ 	int error;
+@@ -1031,8 +1031,8 @@ static int __devinit snd_opti9xx_isa_probe(struct device *devptr,
+ 	return 0;
+ }
+ 
+-static int __devexit snd_opti9xx_isa_remove(struct device *devptr,
+-					    unsigned int dev)
++static int snd_opti9xx_isa_remove(struct device *devptr,
++				  unsigned int dev)
+ {
+ 	snd_card_free(dev_get_drvdata(devptr));
+ 	dev_set_drvdata(devptr, NULL);
+@@ -1083,7 +1083,7 @@ static int snd_opti9xx_isa_resume(struct device *dev, unsigned int n)
+ static struct isa_driver snd_opti9xx_driver = {
+ 	.match		= snd_opti9xx_isa_match,
+ 	.probe		= snd_opti9xx_isa_probe,
+-	.remove		= __devexit_p(snd_opti9xx_isa_remove),
++	.remove		= snd_opti9xx_isa_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= snd_opti9xx_isa_suspend,
+ 	.resume		= snd_opti9xx_isa_resume,
+@@ -1094,8 +1094,8 @@ static struct isa_driver snd_opti9xx_driver = {
+ };
+ 
+ #ifdef CONFIG_PNP
+-static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
+-					   const struct pnp_card_device_id *pid)
++static int snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
++				 const struct pnp_card_device_id *pid)
+ {
+ 	struct snd_card *card;
+ 	int error, hw;
+@@ -1146,7 +1146,7 @@ static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_opti9xx_pnp_remove(struct pnp_card_link * pcard)
++static void snd_opti9xx_pnp_remove(struct pnp_card_link *pcard)
+ {
+ 	snd_card_free(pnp_get_card_drvdata(pcard));
+ 	pnp_set_card_drvdata(pcard, NULL);
+@@ -1171,7 +1171,7 @@ static struct pnp_card_driver opti9xx_pnpc_driver = {
+ 	.name		= "opti9xx",
+ 	.id_table	= snd_opti9xx_pnpids,
+ 	.probe		= snd_opti9xx_pnp_probe,
+-	.remove		= __devexit_p(snd_opti9xx_pnp_remove),
++	.remove		= snd_opti9xx_pnp_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= snd_opti9xx_pnp_suspend,
+ 	.resume		= snd_opti9xx_pnp_resume,
+diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c
+index 2aae6a0efbcd..1d8a0364b9f5 100644
+--- a/sound/isa/sb/emu8000.c
++++ b/sound/isa/sb/emu8000.c
+@@ -131,7 +131,7 @@ snd_emu8000_dma_chan(struct snd_emu8000 *emu, int ch, int mode)
+ 
+ /*
+  */
+-static void __devinit
++static void
+ snd_emu8000_read_wait(struct snd_emu8000 *emu)
+ {
+ 	while ((EMU8000_SMALR_READ(emu) & 0x80000000) != 0) {
+@@ -143,7 +143,7 @@ snd_emu8000_read_wait(struct snd_emu8000 *emu)
+ 
+ /*
+  */
+-static void __devinit
++static void
+ snd_emu8000_write_wait(struct snd_emu8000 *emu)
+ {
+ 	while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
+@@ -156,7 +156,7 @@ snd_emu8000_write_wait(struct snd_emu8000 *emu)
+ /*
+  * detect a card at the given port
+  */
+-static int __devinit
++static int
+ snd_emu8000_detect(struct snd_emu8000 *emu)
+ {
+ 	/* Initialise */
+@@ -182,7 +182,7 @@ snd_emu8000_detect(struct snd_emu8000 *emu)
+ /*
+  * intiailize audio channels
+  */
+-static void __devinit
++static void
+ init_audio(struct snd_emu8000 *emu)
+ {
+ 	int ch;
+@@ -223,7 +223,7 @@ init_audio(struct snd_emu8000 *emu)
+ /*
+  * initialize DMA address
+  */
+-static void __devinit
++static void
+ init_dma(struct snd_emu8000 *emu)
+ {
+ 	EMU8000_SMALR_WRITE(emu, 0);
+@@ -327,7 +327,7 @@ static unsigned short init4[128] /*__devinitdata*/ = {
+  * Taken from the oss driver, not obvious from the doc how this
+  * is meant to work
+  */
+-static void __devinit
++static void
+ send_array(struct snd_emu8000 *emu, unsigned short *data, int size)
+ {
+ 	int i;
+@@ -349,7 +349,7 @@ send_array(struct snd_emu8000 *emu, unsigned short *data, int size)
+  * Send initialization arrays to start up, this just follows the
+  * initialisation sequence in the adip.
+  */
+-static void __devinit
++static void
+ init_arrays(struct snd_emu8000 *emu)
+ {
+ 	send_array(emu, init1, ARRAY_SIZE(init1)/4);
+@@ -375,7 +375,7 @@ init_arrays(struct snd_emu8000 *emu)
+  * seems that the only way to do this is to use the one channel and keep
+  * reallocating between read and write.
+  */
+-static void __devinit
++static void
+ size_dram(struct snd_emu8000 *emu)
+ {
+ 	int i, size, detected_size;
+@@ -512,7 +512,7 @@ snd_emu8000_init_fm(struct snd_emu8000 *emu)
+ /*
+  * The main initialization routine.
+  */
+-static void __devinit
++static void
+ snd_emu8000_init_hw(struct snd_emu8000 *emu)
+ {
+ 	int i;
+@@ -1031,7 +1031,7 @@ static struct snd_kcontrol_new *mixer_defs[EMU8000_NUM_CONTROLS] = {
+ /*
+  * create and attach mixer elements for WaveTable treble/bass controls
+  */
+-static int __devinit
++static int
+ snd_emu8000_create_mixer(struct snd_card *card, struct snd_emu8000 *emu)
+ {
+ 	int i, err = 0;
+@@ -1082,7 +1082,7 @@ static int snd_emu8000_dev_free(struct snd_device *device)
+ /*
+  * initialize and register emu8000 synth device.
+  */
+-int __devinit
++int
+ snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
+ 		struct snd_seq_device **awe_ret)
+ {
+diff --git a/sound/isa/sb/jazz16.c b/sound/isa/sb/jazz16.c
+index 410758c68090..4961da4e627c 100644
+--- a/sound/isa/sb/jazz16.c
++++ b/sound/isa/sb/jazz16.c
+@@ -78,8 +78,8 @@ static irqreturn_t jazz16_interrupt(int irq, void *chip)
+ 	return snd_sb8dsp_interrupt(chip);
+ }
+ 
+-static int __devinit jazz16_configure_ports(unsigned long port,
+-					    unsigned long mpu_port, int idx)
++static int jazz16_configure_ports(unsigned long port,
++				  unsigned long mpu_port, int idx)
+ {
+ 	unsigned char val;
+ 
+@@ -99,8 +99,8 @@ static int __devinit jazz16_configure_ports(unsigned long port,
+ 	return 0;
+ }
+ 
+-static int __devinit jazz16_detect_board(unsigned long port,
+-					 unsigned long mpu_port)
++static int jazz16_detect_board(unsigned long port,
++			       unsigned long mpu_port)
+ {
+ 	int err;
+ 	int val;
+@@ -156,7 +156,7 @@ static int __devinit jazz16_detect_board(unsigned long port,
+ 	return err;
+ }
+ 
+-static int __devinit jazz16_configure_board(struct snd_sb *chip, int mpu_irq)
++static int jazz16_configure_board(struct snd_sb *chip, int mpu_irq)
+ {
+ 	static unsigned char jazz_irq_bits[] = { 0, 0, 2, 3, 0, 1, 0, 4,
+ 						 0, 2, 5, 0, 0, 0, 0, 6 };
+@@ -183,7 +183,7 @@ static int __devinit jazz16_configure_board(struct snd_sb *chip, int mpu_irq)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_jazz16_match(struct device *devptr, unsigned int dev)
++static int snd_jazz16_match(struct device *devptr, unsigned int dev)
+ {
+ 	if (!enable[dev])
+ 		return 0;
+@@ -218,7 +218,7 @@ static int __devinit snd_jazz16_match(struct device *devptr, unsigned int dev)
+ 	return 1;
+ }
+ 
+-static int __devinit snd_jazz16_probe(struct device *devptr, unsigned int dev)
++static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
+ {
+ 	struct snd_card *card;
+ 	struct snd_card_jazz16 *jazz16;
+@@ -341,7 +341,7 @@ static int __devinit snd_jazz16_probe(struct device *devptr, unsigned int dev)
+ 	return err;
+ }
+ 
+-static int __devexit snd_jazz16_remove(struct device *devptr, unsigned int dev)
++static int snd_jazz16_remove(struct device *devptr, unsigned int dev)
+ {
+ 	struct snd_card *card = dev_get_drvdata(devptr);
+ 
+@@ -380,7 +380,7 @@ static int snd_jazz16_resume(struct device *pdev, unsigned int n)
+ static struct isa_driver snd_jazz16_driver = {
+ 	.match		= snd_jazz16_match,
+ 	.probe		= snd_jazz16_probe,
+-	.remove		= __devexit_p(snd_jazz16_remove),
++	.remove		= snd_jazz16_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= snd_jazz16_suspend,
+ 	.resume		= snd_jazz16_resume,
+diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
+index 39b8eca15213..50dbec454f98 100644
+--- a/sound/isa/sb/sb16.c
++++ b/sound/isa/sb/sb16.c
+@@ -250,9 +250,9 @@ MODULE_DEVICE_TABLE(pnp_card, snd_sb16_pnpids);
+ 
+ #ifdef CONFIG_PNP
+ 
+-static int __devinit snd_card_sb16_pnp(int dev, struct snd_card_sb16 *acard,
+-				       struct pnp_card_link *card,
+-				       const struct pnp_card_device_id *id)
++static int snd_card_sb16_pnp(int dev, struct snd_card_sb16 *acard,
++			     struct pnp_card_link *card,
++			     const struct pnp_card_device_id *id)
+ {
+ 	struct pnp_dev *pdev;
+ 	int err;
+@@ -337,7 +337,7 @@ static int snd_sb16_card_new(int dev, struct snd_card **cardp)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_sb16_probe(struct snd_card *card, int dev)
++static int snd_sb16_probe(struct snd_card *card, int dev)
+ {
+ 	int xirq, xdma8, xdma16;
+ 	struct snd_sb *chip;
+@@ -487,7 +487,7 @@ static int snd_sb16_resume(struct snd_card *card)
+ }
+ #endif
+ 
+-static int __devinit snd_sb16_isa_probe1(int dev, struct device *pdev)
++static int snd_sb16_isa_probe1(int dev, struct device *pdev)
+ {
+ 	struct snd_card_sb16 *acard;
+ 	struct snd_card *card;
+@@ -517,12 +517,12 @@ static int __devinit snd_sb16_isa_probe1(int dev, struct device *pdev)
+ }
+ 
+ 
+-static int __devinit snd_sb16_isa_match(struct device *pdev, unsigned int dev)
++static int snd_sb16_isa_match(struct device *pdev, unsigned int dev)
+ {
+ 	return enable[dev] && !is_isapnp_selected(dev);
+ }
+ 
+-static int __devinit snd_sb16_isa_probe(struct device *pdev, unsigned int dev)
++static int snd_sb16_isa_probe(struct device *pdev, unsigned int dev)
+ {
+ 	int err;
+ 	static int possible_irqs[] = {5, 9, 10, 7, -1};
+@@ -563,7 +563,7 @@ static int __devinit snd_sb16_isa_probe(struct device *pdev, unsigned int dev)
+ 	}
+ }
+ 
+-static int __devexit snd_sb16_isa_remove(struct device *pdev, unsigned int dev)
++static int snd_sb16_isa_remove(struct device *pdev, unsigned int dev)
+ {
+ 	snd_card_free(dev_get_drvdata(pdev));
+ 	dev_set_drvdata(pdev, NULL);
+@@ -592,7 +592,7 @@ static int snd_sb16_isa_resume(struct device *dev, unsigned int n)
+ static struct isa_driver snd_sb16_isa_driver = {
+ 	.match		= snd_sb16_isa_match,
+ 	.probe		= snd_sb16_isa_probe,
+-	.remove		= __devexit_p(snd_sb16_isa_remove),
++	.remove		= snd_sb16_isa_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= snd_sb16_isa_suspend,
+ 	.resume		= snd_sb16_isa_resume,
+@@ -604,8 +604,8 @@ static struct isa_driver snd_sb16_isa_driver = {
+ 
+ 
+ #ifdef CONFIG_PNP
+-static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard,
+-					 const struct pnp_card_device_id *pid)
++static int snd_sb16_pnp_detect(struct pnp_card_link *pcard,
++			       const struct pnp_card_device_id *pid)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -631,7 +631,7 @@ static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard,
+ 	return -ENODEV;
+ }
+ 
+-static void __devexit snd_sb16_pnp_remove(struct pnp_card_link * pcard)
++static void snd_sb16_pnp_remove(struct pnp_card_link *pcard)
+ {
+ 	snd_card_free(pnp_get_card_drvdata(pcard));
+ 	pnp_set_card_drvdata(pcard, NULL);
+@@ -657,7 +657,7 @@ static struct pnp_card_driver sb16_pnpc_driver = {
+ #endif
+ 	.id_table = snd_sb16_pnpids,
+ 	.probe = snd_sb16_pnp_detect,
+-	.remove = __devexit_p(snd_sb16_pnp_remove),
++	.remove = snd_sb16_pnp_remove,
+ #ifdef CONFIG_PM
+ 	.suspend = snd_sb16_pnp_suspend,
+ 	.resume = snd_sb16_pnp_resume,
+diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
+index ab5cebea52e1..237d964ff8a6 100644
+--- a/sound/isa/sb/sb8.c
++++ b/sound/isa/sb/sb8.c
+@@ -79,7 +79,7 @@ static void snd_sb8_free(struct snd_card *card)
+ 	release_and_free_resource(acard->fm_res);
+ }
+ 
+-static int __devinit snd_sb8_match(struct device *pdev, unsigned int dev)
++static int snd_sb8_match(struct device *pdev, unsigned int dev)
+ {
+ 	if (!enable[dev])
+ 		return 0;
+@@ -94,7 +94,7 @@ static int __devinit snd_sb8_match(struct device *pdev, unsigned int dev)
+ 	return 1;
+ }
+ 
+-static int __devinit snd_sb8_probe(struct device *pdev, unsigned int dev)
++static int snd_sb8_probe(struct device *pdev, unsigned int dev)
+ {
+ 	struct snd_sb *chip;
+ 	struct snd_card *card;
+@@ -205,7 +205,7 @@ static int __devinit snd_sb8_probe(struct device *pdev, unsigned int dev)
+ 	return err;
+ }
+ 
+-static int __devexit snd_sb8_remove(struct device *pdev, unsigned int dev)
++static int snd_sb8_remove(struct device *pdev, unsigned int dev)
+ {
+ 	snd_card_free(dev_get_drvdata(pdev));
+ 	dev_set_drvdata(pdev, NULL);
+@@ -244,7 +244,7 @@ static int snd_sb8_resume(struct device *dev, unsigned int n)
+ static struct isa_driver snd_sb8_driver = {
+ 	.match		= snd_sb8_match,
+ 	.probe		= snd_sb8_probe,
+-	.remove		= __devexit_p(snd_sb8_remove),
++	.remove		= snd_sb8_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= snd_sb8_suspend,
+ 	.resume		= snd_sb8_resume,
+diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c
+index d97d0f381817..5376ebff845e 100644
+--- a/sound/isa/sc6000.c
++++ b/sound/isa/sc6000.c
+@@ -121,7 +121,7 @@ MODULE_PARM_DESC(joystick, "Enable gameport.");
+ /*
+  * sc6000_irq_to_softcfg - Decode irq number into cfg code.
+  */
+-static __devinit unsigned char sc6000_irq_to_softcfg(int irq)
++static unsigned char sc6000_irq_to_softcfg(int irq)
+ {
+ 	unsigned char val = 0;
+ 
+@@ -150,7 +150,7 @@ static __devinit unsigned char sc6000_irq_to_softcfg(int irq)
+ /*
+  * sc6000_dma_to_softcfg - Decode dma number into cfg code.
+  */
+-static __devinit unsigned char sc6000_dma_to_softcfg(int dma)
++static unsigned char sc6000_dma_to_softcfg(int dma)
+ {
+ 	unsigned char val = 0;
+ 
+@@ -173,7 +173,7 @@ static __devinit unsigned char sc6000_dma_to_softcfg(int dma)
+ /*
+  * sc6000_mpu_irq_to_softcfg - Decode MPU-401 irq number into cfg code.
+  */
+-static __devinit unsigned char sc6000_mpu_irq_to_softcfg(int mpu_irq)
++static unsigned char sc6000_mpu_irq_to_softcfg(int mpu_irq)
+ {
+ 	unsigned char val = 0;
+ 
+@@ -242,8 +242,8 @@ static int sc6000_write(char __iomem *vport, int cmd)
+ 	return -EIO;
+ }
+ 
+-static int __devinit sc6000_dsp_get_answer(char __iomem *vport, int command,
+-					   char *data, int data_len)
++static int sc6000_dsp_get_answer(char __iomem *vport, int command,
++				 char *data, int data_len)
+ {
+ 	int len = 0;
+ 
+@@ -269,7 +269,7 @@ static int __devinit sc6000_dsp_get_answer(char __iomem *vport, int command,
+ 	return len ? len : -EIO;
+ }
+ 
+-static int __devinit sc6000_dsp_reset(char __iomem *vport)
++static int sc6000_dsp_reset(char __iomem *vport)
+ {
+ 	iowrite8(1, vport + DSP_RESET);
+ 	udelay(10);
+@@ -281,7 +281,7 @@ static int __devinit sc6000_dsp_reset(char __iomem *vport)
+ }
+ 
+ /* detection and initialization */
+-static int __devinit sc6000_hw_cfg_write(char __iomem *vport, const int *cfg)
++static int sc6000_hw_cfg_write(char __iomem *vport, const int *cfg)
+ {
+ 	if (sc6000_write(vport, COMMAND_6C) < 0) {
+ 		snd_printk(KERN_WARNING "CMD 0x%x: failed!\n", COMMAND_6C);
+@@ -345,8 +345,8 @@ static int sc6000_setup_board(char __iomem *vport, int config)
+ 	return 0;
+ }
+ 
+-static int __devinit sc6000_init_mss(char __iomem *vport, int config,
+-				     char __iomem *vmss_port, int mss_config)
++static int sc6000_init_mss(char __iomem *vport, int config,
++			   char __iomem *vmss_port, int mss_config)
+ {
+ 	if (sc6000_write(vport, DSP_INIT_MSS)) {
+ 		snd_printk(KERN_ERR "sc6000_init_mss [0x%x]: failed!\n",
+@@ -364,9 +364,9 @@ static int __devinit sc6000_init_mss(char __iomem *vport, int config,
+ 	return 0;
+ }
+ 
+-static void __devinit sc6000_hw_cfg_encode(char __iomem *vport, int *cfg,
+-					   long xport, long xmpu,
+-					   long xmss_port, int joystick)
++static void sc6000_hw_cfg_encode(char __iomem *vport, int *cfg,
++				 long xport, long xmpu,
++				 long xmss_port, int joystick)
+ {
+ 	cfg[0] = 0;
+ 	cfg[1] = 0;
+@@ -386,8 +386,8 @@ static void __devinit sc6000_hw_cfg_encode(char __iomem *vport, int *cfg,
+ 	snd_printd("hw cfg %x, %x\n", cfg[0], cfg[1]);
+ }
+ 
+-static int __devinit sc6000_init_board(char __iomem *vport,
+-					char __iomem *vmss_port, int dev)
++static int sc6000_init_board(char __iomem *vport,
++			     char __iomem *vmss_port, int dev)
+ {
+ 	char answer[15];
+ 	char version[2];
+@@ -467,7 +467,7 @@ static int __devinit sc6000_init_board(char __iomem *vport,
+ 	return 0;
+ }
+ 
+-static int __devinit snd_sc6000_mixer(struct snd_wss *chip)
++static int snd_sc6000_mixer(struct snd_wss *chip)
+ {
+ 	struct snd_card *card = chip->card;
+ 	struct snd_ctl_elem_id id1, id2;
+@@ -502,7 +502,7 @@ static int __devinit snd_sc6000_mixer(struct snd_wss *chip)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_sc6000_match(struct device *devptr, unsigned int dev)
++static int snd_sc6000_match(struct device *devptr, unsigned int dev)
+ {
+ 	if (!enable[dev])
+ 		return 0;
+@@ -545,7 +545,7 @@ static int __devinit snd_sc6000_match(struct device *devptr, unsigned int dev)
+ 	return 1;
+ }
+ 
+-static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev)
++static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
+ {
+ 	static int possible_irqs[] = { 5, 7, 9, 10, 11, -1 };
+ 	static int possible_dmas[] = { 1, 3, 0, -1 };
+@@ -687,7 +687,7 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev)
+ 	return err;
+ }
+ 
+-static int __devexit snd_sc6000_remove(struct device *devptr, unsigned int dev)
++static int snd_sc6000_remove(struct device *devptr, unsigned int dev)
+ {
+ 	struct snd_card *card = dev_get_drvdata(devptr);
+ 	char __iomem **vport = card->private_data;
+@@ -706,7 +706,7 @@ static int __devexit snd_sc6000_remove(struct device *devptr, unsigned int dev)
+ static struct isa_driver snd_sc6000_driver = {
+ 	.match		= snd_sc6000_match,
+ 	.probe		= snd_sc6000_probe,
+-	.remove		= __devexit_p(snd_sc6000_remove),
++	.remove		= snd_sc6000_remove,
+ 	/* FIXME: suspend/resume */
+ 	.driver		= {
+ 		.name	= DRV_NAME,
+diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
+index 8490f59709bb..42a009720b29 100644
+--- a/sound/isa/sscape.c
++++ b/sound/isa/sscape.c
+@@ -683,7 +683,7 @@ static struct snd_kcontrol_new midi_mixer_ctl = {
+  * These IRQs are encoded as bit patterns so that they can be
+  * written to the control registers.
+  */
+-static unsigned __devinit get_irq_config(int sscape_type, int irq)
++static unsigned get_irq_config(int sscape_type, int irq)
+ {
+ 	static const int valid_irq[] = { 9, 5, 7, 10 };
+ 	static const int old_irq[] = { 9, 7, 5, 15 };
+@@ -706,7 +706,7 @@ static unsigned __devinit get_irq_config(int sscape_type, int irq)
+  * Perform certain arcane port-checks to see whether there
+  * is a SoundScape board lurking behind the given ports.
+  */
+-static int __devinit detect_sscape(struct soundscape *s, long wss_io)
++static int detect_sscape(struct soundscape *s, long wss_io)
+ {
+ 	unsigned long flags;
+ 	unsigned d;
+@@ -817,8 +817,8 @@ static int mpu401_open(struct snd_mpu401 *mpu)
+ /*
+  * Initialse an MPU-401 subdevice for MIDI support on the SoundScape.
+  */
+-static int __devinit create_mpu401(struct snd_card *card, int devnum,
+-				   unsigned long port, int irq)
++static int create_mpu401(struct snd_card *card, int devnum,
++			 unsigned long port, int irq)
+ {
+ 	struct soundscape *sscape = get_card_soundscape(card);
+ 	struct snd_rawmidi *rawmidi;
+@@ -845,8 +845,8 @@ static int __devinit create_mpu401(struct snd_card *card, int devnum,
+  * try to support at least some of the extra bits by overriding
+  * some of the CS4231 callback.
+  */
+-static int __devinit create_ad1845(struct snd_card *card, unsigned port,
+-				   int irq, int dma1, int dma2)
++static int create_ad1845(struct snd_card *card, unsigned port,
++			 int irq, int dma1, int dma2)
+ {
+ 	register struct soundscape *sscape = get_card_soundscape(card);
+ 	struct snd_wss *chip;
+@@ -937,7 +937,7 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
+  * Create an ALSA soundcard entry for the SoundScape, using
+  * the given list of port, IRQ and DMA resources.
+  */
+-static int __devinit create_sscape(int dev, struct snd_card *card)
++static int create_sscape(int dev, struct snd_card *card)
+ {
+ 	struct soundscape *sscape = get_card_soundscape(card);
+ 	unsigned dma_cfg;
+@@ -1143,7 +1143,7 @@ static int __devinit create_sscape(int dev, struct snd_card *card)
+ }
+ 
+ 
+-static int __devinit snd_sscape_match(struct device *pdev, unsigned int i)
++static int snd_sscape_match(struct device *pdev, unsigned int i)
+ {
+ 	/*
+ 	 * Make sure we were given ALL of the other parameters.
+@@ -1163,7 +1163,7 @@ static int __devinit snd_sscape_match(struct device *pdev, unsigned int i)
+ 	return 1;
+ }
+ 
+-static int __devinit snd_sscape_probe(struct device *pdev, unsigned int dev)
++static int snd_sscape_probe(struct device *pdev, unsigned int dev)
+ {
+ 	struct snd_card *card;
+ 	struct soundscape *sscape;
+@@ -1197,7 +1197,7 @@ static int __devinit snd_sscape_probe(struct device *pdev, unsigned int dev)
+ 	return ret;
+ }
+ 
+-static int __devexit snd_sscape_remove(struct device *devptr, unsigned int dev)
++static int snd_sscape_remove(struct device *devptr, unsigned int dev)
+ {
+ 	snd_card_free(dev_get_drvdata(devptr));
+ 	dev_set_drvdata(devptr, NULL);
+@@ -1209,7 +1209,7 @@ static int __devexit snd_sscape_remove(struct device *devptr, unsigned int dev)
+ static struct isa_driver snd_sscape_driver = {
+ 	.match		= snd_sscape_match,
+ 	.probe		= snd_sscape_probe,
+-	.remove		= __devexit_p(snd_sscape_remove),
++	.remove		= snd_sscape_remove,
+ 	/* FIXME: suspend/resume */
+ 	.driver		= {
+ 		.name	= DEV_NAME
+@@ -1217,7 +1217,7 @@ static struct isa_driver snd_sscape_driver = {
+ };
+ 
+ #ifdef CONFIG_PNP
+-static inline int __devinit get_next_autoindex(int i)
++static inline int get_next_autoindex(int i)
+ {
+ 	while (i < SNDRV_CARDS && port[i] != SNDRV_AUTO_PORT)
+ 		++i;
+@@ -1225,8 +1225,8 @@ static inline int __devinit get_next_autoindex(int i)
+ }
+ 
+ 
+-static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard,
+-				       const struct pnp_card_device_id *pid)
++static int sscape_pnp_detect(struct pnp_card_link *pcard,
++			     const struct pnp_card_device_id *pid)
+ {
+ 	static int idx = 0;
+ 	struct pnp_dev *dev;
+@@ -1310,7 +1310,7 @@ static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard,
+ 	return ret;
+ }
+ 
+-static void __devexit sscape_pnp_remove(struct pnp_card_link * pcard)
++static void sscape_pnp_remove(struct pnp_card_link *pcard)
+ {
+ 	snd_card_free(pnp_get_card_drvdata(pcard));
+ 	pnp_set_card_drvdata(pcard, NULL);
+@@ -1321,7 +1321,7 @@ static struct pnp_card_driver sscape_pnpc_driver = {
+ 	.name = "sscape",
+ 	.id_table = sscape_pnpids,
+ 	.probe = sscape_pnp_detect,
+-	.remove = __devexit_p(sscape_pnp_remove),
++	.remove = sscape_pnp_remove,
+ };
+ 
+ #endif /* CONFIG_PNP */
+diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
+index e0a73271cb91..fe5dd982bd23 100644
+--- a/sound/isa/wavefront/wavefront.c
++++ b/sound/isa/wavefront/wavefront.c
+@@ -98,7 +98,7 @@ static struct pnp_card_device_id snd_wavefront_pnpids[] = {
+ 
+ MODULE_DEVICE_TABLE(pnp_card, snd_wavefront_pnpids);
+ 
+-static int __devinit
++static int
+ snd_wavefront_pnp (int dev, snd_wavefront_card_t *acard, struct pnp_card_link *card,
+ 		   const struct pnp_card_device_id *id)
+ {
+@@ -231,10 +231,9 @@ static irqreturn_t snd_wavefront_ics2115_interrupt(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static struct snd_hwdep * __devinit
+-snd_wavefront_new_synth (struct snd_card *card,
+-			 int hw_dev,
+-			 snd_wavefront_card_t *acard)
++static struct snd_hwdep *snd_wavefront_new_synth(struct snd_card *card,
++						 int hw_dev,
++						 snd_wavefront_card_t *acard)
+ {
+ 	struct snd_hwdep *wavefront_synth;
+ 
+@@ -257,11 +256,10 @@ snd_wavefront_new_synth (struct snd_card *card,
+ 	return wavefront_synth;
+ }
+ 
+-static struct snd_hwdep * __devinit
+-snd_wavefront_new_fx (struct snd_card *card,
+-		      int hw_dev,
+-		      snd_wavefront_card_t *acard,
+-		      unsigned long port)
++static struct snd_hwdep *snd_wavefront_new_fx(struct snd_card *card,
++					      int hw_dev,
++					      snd_wavefront_card_t *acard,
++					      unsigned long port)
+ 
+ {
+ 	struct snd_hwdep *fx_processor;
+@@ -284,12 +282,11 @@ snd_wavefront_new_fx (struct snd_card *card,
+ static snd_wavefront_mpu_id internal_id = internal_mpu;
+ static snd_wavefront_mpu_id external_id = external_mpu;
+ 
+-static struct snd_rawmidi *__devinit
+-snd_wavefront_new_midi (struct snd_card *card,
+-			int midi_dev,
+-			snd_wavefront_card_t *acard,
+-			unsigned long port,
+-			snd_wavefront_mpu_id mpu)
++static struct snd_rawmidi *snd_wavefront_new_midi(struct snd_card *card,
++						  int midi_dev,
++						  snd_wavefront_card_t *acard,
++						  unsigned long port,
++						  snd_wavefront_mpu_id mpu)
+ 
+ {
+ 	struct snd_rawmidi *rmidi;
+@@ -361,7 +358,7 @@ static int snd_wavefront_card_new(int dev, struct snd_card **cardp)
+ 	return 0;
+ }
+ 
+-static int __devinit
++static int
+ snd_wavefront_probe (struct snd_card *card, int dev)
+ {
+ 	snd_wavefront_card_t *acard = card->private_data;
+@@ -541,8 +538,8 @@ snd_wavefront_probe (struct snd_card *card, int dev)
+ 	return snd_card_register(card);
+ }	
+ 
+-static int __devinit snd_wavefront_isa_match(struct device *pdev,
+-					     unsigned int dev)
++static int snd_wavefront_isa_match(struct device *pdev,
++				   unsigned int dev)
+ {
+ 	if (!enable[dev])
+ 		return 0;
+@@ -561,8 +558,8 @@ static int __devinit snd_wavefront_isa_match(struct device *pdev,
+ 	return 1;
+ }
+ 
+-static int __devinit snd_wavefront_isa_probe(struct device *pdev,
+-					     unsigned int dev)
++static int snd_wavefront_isa_probe(struct device *pdev,
++				   unsigned int dev)
+ {
+ 	struct snd_card *card;
+ 	int err;
+@@ -580,8 +577,8 @@ static int __devinit snd_wavefront_isa_probe(struct device *pdev,
+ 	return 0;
+ }
+ 
+-static int __devexit snd_wavefront_isa_remove(struct device *devptr,
+-					      unsigned int dev)
++static int snd_wavefront_isa_remove(struct device *devptr,
++				    unsigned int dev)
+ {
+ 	snd_card_free(dev_get_drvdata(devptr));
+ 	dev_set_drvdata(devptr, NULL);
+@@ -593,7 +590,7 @@ static int __devexit snd_wavefront_isa_remove(struct device *devptr,
+ static struct isa_driver snd_wavefront_driver = {
+ 	.match		= snd_wavefront_isa_match,
+ 	.probe		= snd_wavefront_isa_probe,
+-	.remove		= __devexit_p(snd_wavefront_isa_remove),
++	.remove		= snd_wavefront_isa_remove,
+ 	/* FIXME: suspend, resume */
+ 	.driver		= {
+ 		.name	= DEV_NAME
+@@ -602,8 +599,8 @@ static struct isa_driver snd_wavefront_driver = {
+ 
+ 
+ #ifdef CONFIG_PNP
+-static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard,
+-					const struct pnp_card_device_id *pid)
++static int snd_wavefront_pnp_detect(struct pnp_card_link *pcard,
++				    const struct pnp_card_device_id *pid)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -637,7 +634,7 @@ static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_wavefront_pnp_remove(struct pnp_card_link * pcard)
++static void snd_wavefront_pnp_remove(struct pnp_card_link *pcard)
+ {
+ 	snd_card_free(pnp_get_card_drvdata(pcard));
+ 	pnp_set_card_drvdata(pcard, NULL);
+@@ -648,7 +645,7 @@ static struct pnp_card_driver wavefront_pnpc_driver = {
+ 	.name		= "wavefront",
+ 	.id_table	= snd_wavefront_pnpids,
+ 	.probe		= snd_wavefront_pnp_detect,
+-	.remove		= __devexit_p(snd_wavefront_pnp_remove),
++	.remove		= snd_wavefront_pnp_remove,
+ 	/* FIXME: suspend,resume */
+ };
+ 
+diff --git a/sound/isa/wavefront/wavefront_fx.c b/sound/isa/wavefront/wavefront_fx.c
+index e51e0906050b..b77883c7ee76 100644
+--- a/sound/isa/wavefront/wavefront_fx.c
++++ b/sound/isa/wavefront/wavefront_fx.c
+@@ -240,7 +240,7 @@ snd_wavefront_fx_ioctl (struct snd_hwdep *sdev, struct file *file,
+    that outputs it.
+ */
+ 
+-int __devinit
++int
+ snd_wavefront_fx_start (snd_wavefront_t *dev)
+ {
+ 	unsigned int i;
+diff --git a/sound/isa/wavefront/wavefront_midi.c b/sound/isa/wavefront/wavefront_midi.c
+index 65329f3abc30..7dc991682297 100644
+--- a/sound/isa/wavefront/wavefront_midi.c
++++ b/sound/isa/wavefront/wavefront_midi.c
+@@ -481,7 +481,7 @@ snd_wavefront_midi_disable_virtual (snd_wavefront_card_t *card)
+ 	spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags);
+ }
+ 
+-int __devinit
++int
+ snd_wavefront_midi_start (snd_wavefront_card_t *card)
+ 
+ {
+diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
+index b1bf8d4e6494..a2f87f9488ee 100644
+--- a/sound/isa/wavefront/wavefront_synth.c
++++ b/sound/isa/wavefront/wavefront_synth.c
+@@ -1739,7 +1739,7 @@ snd_wavefront_internal_interrupt (snd_wavefront_card_t *card)
+ 7 Unused
+ */
+ 
+-static int __devinit
++static int
+ snd_wavefront_interrupt_bits (int irq)
+ 
+ {
+@@ -1767,7 +1767,7 @@ snd_wavefront_interrupt_bits (int irq)
+ 	return bits;
+ }
+ 
+-static void __devinit
++static void
+ wavefront_should_cause_interrupt (snd_wavefront_t *dev, 
+ 				  int val, int port, unsigned long timeout)
+ 
+@@ -1786,7 +1786,7 @@ wavefront_should_cause_interrupt (snd_wavefront_t *dev,
+ 	}
+ }
+ 
+-static int __devinit
++static int
+ wavefront_reset_to_cleanliness (snd_wavefront_t *dev)
+ 
+ {
+@@ -1937,7 +1937,7 @@ wavefront_reset_to_cleanliness (snd_wavefront_t *dev)
+ 	return (1);
+ }
+ 
+-static int __devinit
++static int
+ wavefront_download_firmware (snd_wavefront_t *dev, char *path)
+ 
+ {
+@@ -2010,7 +2010,7 @@ wavefront_download_firmware (snd_wavefront_t *dev, char *path)
+ }
+ 
+ 
+-static int __devinit
++static int
+ wavefront_do_reset (snd_wavefront_t *dev)
+ 
+ {
+@@ -2099,7 +2099,7 @@ wavefront_do_reset (snd_wavefront_t *dev)
+ 	return 1;
+ }
+ 
+-int __devinit
++int
+ snd_wavefront_start (snd_wavefront_t *dev)
+ 
+ {
+@@ -2141,7 +2141,7 @@ snd_wavefront_start (snd_wavefront_t *dev)
+ 	return (0);
+ }
+ 
+-int __devinit
++int
+ snd_wavefront_detect (snd_wavefront_card_t *card)
+ 
+ {

commit f120a6fb486c2500c9ae11fd2da11fbde29bc186
+Author: Bill Pemberton 
+Date:   Thu Dec 6 12:35:20 2012 -0500
+
+    ALSA: oxygen: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Clemens Ladisch 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c
+index 2becae155a48..ada6c256378e 100644
+--- a/sound/pci/oxygen/oxygen.c
++++ b/sound/pci/oxygen/oxygen.c
+@@ -756,8 +756,8 @@ static const struct oxygen_model model_generic = {
+ 	.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+ };
+ 
+-static int __devinit get_oxygen_model(struct oxygen *chip,
+-				      const struct pci_device_id *id)
++static int get_oxygen_model(struct oxygen *chip,
++			    const struct pci_device_id *id)
+ {
+ 	static const char *const names[] = {
+ 		[MODEL_MERIDIAN]	= "AuzenTech X-Meridian",
+@@ -848,8 +848,8 @@ static int __devinit get_oxygen_model(struct oxygen *chip,
+ 	return 0;
+ }
+ 
+-static int __devinit generic_oxygen_probe(struct pci_dev *pci,
+-					  const struct pci_device_id *pci_id)
++static int generic_oxygen_probe(struct pci_dev *pci,
++				const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	int err;
+@@ -871,7 +871,7 @@ static struct pci_driver oxygen_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = oxygen_ids,
+ 	.probe = generic_oxygen_probe,
+-	.remove = __devexit_p(oxygen_pci_remove),
++	.remove = oxygen_pci_remove,
+ #ifdef CONFIG_PM_SLEEP
+ 	.driver = {
+ 		.pm = &oxygen_pci_pm,
+diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
+index 8104eab90e51..64b9fda5f04a 100644
+--- a/sound/pci/oxygen/virtuoso.c
++++ b/sound/pci/oxygen/virtuoso.c
+@@ -58,8 +58,8 @@ static DEFINE_PCI_DEVICE_TABLE(xonar_ids) = {
+ };
+ MODULE_DEVICE_TABLE(pci, xonar_ids);
+ 
+-static int __devinit get_xonar_model(struct oxygen *chip,
+-				     const struct pci_device_id *id)
++static int get_xonar_model(struct oxygen *chip,
++			   const struct pci_device_id *id)
+ {
+ 	if (get_xonar_pcm179x_model(chip, id) >= 0)
+ 		return 0;
+@@ -70,8 +70,8 @@ static int __devinit get_xonar_model(struct oxygen *chip,
+ 	return -EINVAL;
+ }
+ 
+-static int __devinit xonar_probe(struct pci_dev *pci,
+-				 const struct pci_device_id *pci_id)
++static int xonar_probe(struct pci_dev *pci,
++		       const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	int err;
+@@ -93,7 +93,7 @@ static struct pci_driver xonar_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = xonar_ids,
+ 	.probe = xonar_probe,
+-	.remove = __devexit_p(oxygen_pci_remove),
++	.remove = oxygen_pci_remove,
+ #ifdef CONFIG_PM_SLEEP
+ 	.driver = {
+ 		.pm = &oxygen_pci_pm,
+diff --git a/sound/pci/oxygen/xonar_cs43xx.c b/sound/pci/oxygen/xonar_cs43xx.c
+index c8febf4b9bd6..d231b93d6ab5 100644
+--- a/sound/pci/oxygen/xonar_cs43xx.c
++++ b/sound/pci/oxygen/xonar_cs43xx.c
+@@ -431,8 +431,8 @@ static const struct oxygen_model model_xonar_d1 = {
+ 	.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+ };
+ 
+-int __devinit get_xonar_cs43xx_model(struct oxygen *chip,
+-				     const struct pci_device_id *id)
++int get_xonar_cs43xx_model(struct oxygen *chip,
++			   const struct pci_device_id *id)
+ {
+ 	switch (id->subdevice) {
+ 	case 0x834f:
+diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c
+index 8433aa7c3d75..c8c7f2c9b355 100644
+--- a/sound/pci/oxygen/xonar_pcm179x.c
++++ b/sound/pci/oxygen/xonar_pcm179x.c
+@@ -1087,8 +1087,8 @@ static const struct oxygen_model model_xonar_st = {
+ 	.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+ };
+ 
+-int __devinit get_xonar_pcm179x_model(struct oxygen *chip,
+-				      const struct pci_device_id *id)
++int get_xonar_pcm179x_model(struct oxygen *chip,
++			    const struct pci_device_id *id)
+ {
+ 	switch (id->subdevice) {
+ 	case 0x8269:
+diff --git a/sound/pci/oxygen/xonar_wm87x6.c b/sound/pci/oxygen/xonar_wm87x6.c
+index b555b620babb..6ce68604c25e 100644
+--- a/sound/pci/oxygen/xonar_wm87x6.c
++++ b/sound/pci/oxygen/xonar_wm87x6.c
+@@ -1320,8 +1320,8 @@ static const struct oxygen_model model_xonar_hdav_slim = {
+ 	.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+ };
+ 
+-int __devinit get_xonar_wm87x6_model(struct oxygen *chip,
+-				     const struct pci_device_id *id)
++int get_xonar_wm87x6_model(struct oxygen *chip,
++			   const struct pci_device_id *id)
+ {
+ 	switch (id->subdevice) {
+ 	case 0x838e:

commit 3dd0676335f846e3e7d275c379a112c2f8a832cb
+Author: Bill Pemberton 
+Date:   Thu Dec 6 12:35:19 2012 -0500
+
+    ALSA: bt87X: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Clemens Ladisch 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
+index b6a95eeca095..cdd100dae855 100644
+--- a/sound/pci/bt87x.c
++++ b/sound/pci/bt87x.c
+@@ -164,7 +164,7 @@ struct snd_bt87x_board {
+ 	unsigned no_digital:1;	/* No digital input */
+ };
+ 
+-static __devinitdata struct snd_bt87x_board snd_bt87x_boards[] = {
++static struct snd_bt87x_board snd_bt87x_boards[] = {
+ 	[SND_BT87X_BOARD_UNKNOWN] = {
+ 		.dig_rate = 32000, /* just a guess */
+ 	},
+@@ -696,7 +696,7 @@ static int snd_bt87x_dev_free(struct snd_device *device)
+ 	return snd_bt87x_free(chip);
+ }
+ 
+-static int __devinit snd_bt87x_pcm(struct snd_bt87x *chip, int device, char *name)
++static int snd_bt87x_pcm(struct snd_bt87x *chip, int device, char *name)
+ {
+ 	int err;
+ 	struct snd_pcm *pcm;
+@@ -714,9 +714,9 @@ static int __devinit snd_bt87x_pcm(struct snd_bt87x *chip, int device, char *nam
+ 							ALIGN(255 * 4092, 1024));
+ }
+ 
+-static int __devinit snd_bt87x_create(struct snd_card *card,
+-				      struct pci_dev *pci,
+-				      struct snd_bt87x **rchip)
++static int snd_bt87x_create(struct snd_card *card,
++			    struct pci_dev *pci,
++			    struct snd_bt87x **rchip)
+ {
+ 	struct snd_bt87x *chip;
+ 	int err;
+@@ -822,7 +822,7 @@ MODULE_DEVICE_TABLE(pci, snd_bt87x_ids);
+  * (DVB cards use the audio function to transfer MPEG data) */
+ static struct {
+ 	unsigned short subvendor, subdevice;
+-} blacklist[] __devinitdata = {
++} blacklist[] = {
+ 	{0x0071, 0x0101}, /* Nebula Electronics DigiTV */
+ 	{0x11bd, 0x001c}, /* Pinnacle PCTV Sat */
+ 	{0x11bd, 0x0026}, /* Pinnacle PCTV SAT CI */
+@@ -837,7 +837,7 @@ static struct {
+ };
+ 
+ /* return the id of the card, or a negative value if it's blacklisted */
+-static int __devinit snd_bt87x_detect_card(struct pci_dev *pci)
++static int snd_bt87x_detect_card(struct pci_dev *pci)
+ {
+ 	int i;
+ 	const struct pci_device_id *supported;
+@@ -862,8 +862,8 @@ static int __devinit snd_bt87x_detect_card(struct pci_dev *pci)
+ 	return SND_BT87X_BOARD_UNKNOWN;
+ }
+ 
+-static int __devinit snd_bt87x_probe(struct pci_dev *pci,
+-				     const struct pci_device_id *pci_id)
++static int snd_bt87x_probe(struct pci_dev *pci,
++			   const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -948,7 +948,7 @@ static int __devinit snd_bt87x_probe(struct pci_dev *pci,
+ 	return err;
+ }
+ 
+-static void __devexit snd_bt87x_remove(struct pci_dev *pci)
++static void snd_bt87x_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -966,7 +966,7 @@ static struct pci_driver bt87x_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_bt87x_ids,
+ 	.probe = snd_bt87x_probe,
+-	.remove = __devexit_p(snd_bt87x_remove),
++	.remove = snd_bt87x_remove,
+ };
+ 
+ module_pci_driver(bt87x_driver);

commit 2f5c1302815c4c5b946a1cf8c6a79152f3dde721
+Author: Bill Pemberton 
+Date:   Thu Dec 6 12:35:18 2012 -0500
+
+    ALSA: ad1889: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Thibaut Varene 
+    Cc: linux-parisc@vger.kernel.org
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
+index e672ff4df2da..ad8a31173939 100644
+--- a/sound/pci/ad1889.c
++++ b/sound/pci/ad1889.c
+@@ -624,7 +624,7 @@ snd_ad1889_interrupt(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit
++static int
+ snd_ad1889_pcm_init(struct snd_ad1889 *chip, int device, struct snd_pcm **rpcm)
+ {
+ 	int err;
+@@ -747,7 +747,7 @@ snd_ad1889_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffe
+ 	snd_iprintf(buffer, "Resampler samplerate: %u Hz\n", reg);
+ }
+ 
+-static void __devinit
++static void
+ snd_ad1889_proc_init(struct snd_ad1889 *chip)
+ {
+ 	struct snd_info_entry *entry;
+@@ -767,7 +767,7 @@ static struct ac97_quirk ac97_quirks[] = {
+ 	{ } /* terminator */
+ };
+ 
+-static void __devinit
++static void
+ snd_ad1889_ac97_xinit(struct snd_ad1889 *chip)
+ {
+ 	u16 reg;
+@@ -805,7 +805,7 @@ snd_ad1889_ac97_free(struct snd_ac97 *ac97)
+ 	chip->ac97 = NULL;
+ }
+ 
+-static int __devinit
++static int
+ snd_ad1889_ac97_init(struct snd_ad1889 *chip, const char *quirk_override)
+ {
+ 	int err;
+@@ -878,7 +878,7 @@ snd_ad1889_dev_free(struct snd_device *device)
+ 	return snd_ad1889_free(chip);
+ }
+ 
+-static int __devinit
++static int
+ snd_ad1889_init(struct snd_ad1889 *chip) 
+ {
+ 	ad1889_writew(chip, AD_DS_CCS, AD_DS_CCS_CLKEN); /* turn on clock */
+@@ -892,7 +892,7 @@ snd_ad1889_init(struct snd_ad1889 *chip)
+ 	return 0;
+ }
+ 
+-static int __devinit
++static int
+ snd_ad1889_create(struct snd_card *card,
+ 		  struct pci_dev *pci,
+ 		  struct snd_ad1889 **rchip)
+@@ -978,7 +978,7 @@ snd_ad1889_create(struct snd_card *card,
+ 	return err;
+ }
+ 
+-static int __devinit
++static int
+ snd_ad1889_probe(struct pci_dev *pci,
+ 		 const struct pci_device_id *pci_id)
+ {
+@@ -1042,7 +1042,7 @@ snd_ad1889_probe(struct pci_dev *pci,
+ 	return err;
+ }
+ 
+-static void __devexit
++static void
+ snd_ad1889_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+@@ -1059,7 +1059,7 @@ static struct pci_driver ad1889_pci_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_ad1889_ids,
+ 	.probe = snd_ad1889_probe,
+-	.remove = __devexit_p(snd_ad1889_remove),
++	.remove = snd_ad1889_remove,
+ };
+ 
+ module_pci_driver(ad1889_pci_driver);

commit 9921041452ef6bd12a47e5b3e324d07e84629e03
+Author: Bill Pemberton 
+Date:   Thu Dec 6 12:35:17 2012 -0500
+
+    sound: oss: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c
+index 98d23bdcaf21..4918b7145b73 100644
+--- a/sound/oss/ad1848.c
++++ b/sound/oss/ad1848.c
+@@ -2864,7 +2864,7 @@ static struct {
+ 	{NULL}
+ };
+ 
+-static struct isapnp_device_id id_table[] __devinitdata = {
++static struct isapnp_device_id id_table[] = {
+ 	{	ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001),
+ 		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 },
+         {       ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+diff --git a/sound/oss/kahlua.c b/sound/oss/kahlua.c
+index 52d06a334e8f..2a44cc106459 100644
+--- a/sound/oss/kahlua.c
++++ b/sound/oss/kahlua.c
+@@ -43,7 +43,7 @@
+  *	not real hardware.
+  */
+ 
+-static u8 __devinit mixer_read(unsigned long io, u8 reg)
++static u8 mixer_read(unsigned long io, u8 reg)
+ {
+ 	outb(reg, io + 4);
+ 	udelay(20);
+@@ -52,7 +52,7 @@ static u8 __devinit mixer_read(unsigned long io, u8 reg)
+ 	return reg;
+ }
+ 
+-static int __devinit probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
++static int probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ 	struct address_info *hw_config;
+ 	unsigned long base;
+@@ -183,7 +183,7 @@ static int __devinit probe_one(struct pci_dev *pdev, const struct pci_device_id
+ 	return 1;
+ }
+ 
+-static void __devexit remove_one(struct pci_dev *pdev)
++static void remove_one(struct pci_dev *pdev)
+ {
+ 	struct address_info *hw_config = pci_get_drvdata(pdev);
+ 	sb_dsp_unload(hw_config, 0);
+@@ -210,7 +210,7 @@ static struct pci_driver kahlua_driver = {
+ 	.name		= "kahlua",
+ 	.id_table	= id_tbl,
+ 	.probe		= probe_one,
+-	.remove		= __devexit_p(remove_one),
++	.remove		= remove_one,
+ };
+ 
+ 
+@@ -220,7 +220,7 @@ static int __init kahlua_init_module(void)
+ 	return pci_register_driver(&kahlua_driver);
+ }
+ 
+-static void __devexit kahlua_cleanup_module(void)
++static void kahlua_cleanup_module(void)
+ {
+ 	pci_unregister_driver(&kahlua_driver);
+ }

commit 05bcf50367668b6706a44e89c166c541f2644d04
+Author: Bill Pemberton 
+Date:   Thu Dec 6 12:35:16 2012 -0500
+
+    ALSA: parisc/harmony: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: linux-parisc@vger.kernel.org
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c
+index f47f9e226b08..0e66ba48d453 100644
+--- a/sound/parisc/harmony.c
++++ b/sound/parisc/harmony.c
+@@ -856,7 +856,7 @@ static struct snd_kcontrol_new snd_harmony_controls[] = {
+ 		       HARMONY_GAIN_HE_SHIFT, 1, 0),
+ };
+ 
+-static void __devinit
++static void
+ snd_harmony_mixer_reset(struct snd_harmony *h)
+ {
+ 	harmony_mute(h);
+@@ -865,7 +865,7 @@ snd_harmony_mixer_reset(struct snd_harmony *h)
+ 	harmony_unmute(h);
+ }
+ 
+-static int __devinit
++static int
+ snd_harmony_mixer_init(struct snd_harmony *h)
+ {
+ 	struct snd_card *card;
+@@ -915,7 +915,7 @@ snd_harmony_dev_free(struct snd_device *dev)
+ 	return snd_harmony_free(h);
+ }
+ 
+-static int __devinit
++static int
+ snd_harmony_create(struct snd_card *card, 
+ 		   struct parisc_device *padev, 
+ 		   struct snd_harmony **rchip)
+@@ -972,7 +972,7 @@ snd_harmony_create(struct snd_card *card,
+ 	return err;
+ }
+ 
+-static int __devinit
++static int
+ snd_harmony_probe(struct parisc_device *padev)
+ {
+ 	int err;
+@@ -1012,7 +1012,7 @@ snd_harmony_probe(struct parisc_device *padev)
+ 	return err;
+ }
+ 
+-static int __devexit
++static int
+ snd_harmony_remove(struct parisc_device *padev)
+ {
+ 	snd_card_free(parisc_get_drvdata(padev));
+@@ -1024,7 +1024,7 @@ static struct parisc_driver snd_harmony_driver = {
+ 	.name = "harmony",
+ 	.id_table = snd_harmony_devtable,
+ 	.probe = snd_harmony_probe,
+-	.remove = __devexit_p(snd_harmony_remove),
++	.remove = snd_harmony_remove,
+ };
+ 
+ static int __init 

commit e0f8cb5fac7f6ab0353caccab54e960bbe517123
+Author: Bill Pemberton 
+Date:   Thu Dec 6 12:35:15 2012 -0500
+
+    ALSA: mips: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c
+index 3f3ec0bec067..224f54be15a6 100644
+--- a/sound/mips/au1x00.c
++++ b/sound/mips/au1x00.c
+@@ -439,7 +439,7 @@ static struct snd_pcm_ops snd_card_au1000_capture_ops = {
+ 	.pointer		= snd_au1000_pointer,
+ };
+ 
+-static int __devinit
++static int
+ snd_au1000_pcm_new(struct snd_au1000 *au1000)
+ {
+ 	struct snd_pcm *pcm;
+@@ -552,7 +552,7 @@ get the interrupt driven case to work efficiently */
+ 	spin_unlock(&au1000->ac97_lock);
+ }
+ 
+-static int __devinit
++static int
+ snd_au1000_ac97_new(struct snd_au1000 *au1000)
+ {
+ 	int err;
+diff --git a/sound/mips/hal2.c b/sound/mips/hal2.c
+index 5f88d1f09ffe..7420c59444ab 100644
+--- a/sound/mips/hal2.c
++++ b/sound/mips/hal2.c
+@@ -260,7 +260,7 @@ static int hal2_gain_put(struct snd_kcontrol *kcontrol,
+ 	return old != new;
+ }
+ 
+-static struct snd_kcontrol_new hal2_ctrl_headphone __devinitdata = {
++static struct snd_kcontrol_new hal2_ctrl_headphone = {
+ 	.iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name           = "Headphone Playback Volume",
+ 	.access         = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+@@ -270,7 +270,7 @@ static struct snd_kcontrol_new hal2_ctrl_headphone __devinitdata = {
+ 	.put            = hal2_gain_put,
+ };
+ 
+-static struct snd_kcontrol_new hal2_ctrl_mic __devinitdata = {
++static struct snd_kcontrol_new hal2_ctrl_mic = {
+ 	.iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name           = "Mic Capture Volume",
+ 	.access         = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+@@ -280,7 +280,7 @@ static struct snd_kcontrol_new hal2_ctrl_mic __devinitdata = {
+ 	.put            = hal2_gain_put,
+ };
+ 
+-static int __devinit hal2_mixer_create(struct snd_hal2 *hal2)
++static int hal2_mixer_create(struct snd_hal2 *hal2)
+ {
+ 	int err;
+ 
+@@ -733,7 +733,7 @@ static struct snd_pcm_ops hal2_capture_ops = {
+ 	.ack =         hal2_capture_ack,
+ };
+ 
+-static int __devinit hal2_pcm_create(struct snd_hal2 *hal2)
++static int hal2_pcm_create(struct snd_hal2 *hal2)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -874,7 +874,7 @@ static int hal2_create(struct snd_card *card, struct snd_hal2 **rchip)
+ 	return 0;
+ }
+ 
+-static int __devinit hal2_probe(struct platform_device *pdev)
++static int hal2_probe(struct platform_device *pdev)
+ {
+ 	struct snd_card *card;
+ 	struct snd_hal2 *chip;
+@@ -917,7 +917,7 @@ static int __devinit hal2_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit hal2_remove(struct platform_device *pdev)
++static int hal2_remove(struct platform_device *pdev)
+ {
+ 	struct snd_card *card = platform_get_drvdata(pdev);
+ 
+@@ -928,7 +928,7 @@ static int __devexit hal2_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver hal2_driver = {
+ 	.probe	= hal2_probe,
+-	.remove	= __devexit_p(hal2_remove),
++	.remove	= hal2_remove,
+ 	.driver = {
+ 		.name	= "sgihal2",
+ 		.owner	= THIS_MODULE,
+diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c
+index ceaa593ea4ef..01a03efdc8b0 100644
+--- a/sound/mips/sgio2audio.c
++++ b/sound/mips/sgio2audio.c
+@@ -237,7 +237,7 @@ static int sgio2audio_source_put(struct snd_kcontrol *kcontrol,
+ }
+ 
+ /* dac1/pcm0 mixer control */
+-static struct snd_kcontrol_new sgio2audio_ctrl_pcm0 __devinitdata = {
++static struct snd_kcontrol_new sgio2audio_ctrl_pcm0 = {
+ 	.iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name           = "PCM Playback Volume",
+ 	.index          = 0,
+@@ -249,7 +249,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_pcm0 __devinitdata = {
+ };
+ 
+ /* dac2/pcm1 mixer control */
+-static struct snd_kcontrol_new sgio2audio_ctrl_pcm1 __devinitdata = {
++static struct snd_kcontrol_new sgio2audio_ctrl_pcm1 = {
+ 	.iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name           = "PCM Playback Volume",
+ 	.index          = 1,
+@@ -261,7 +261,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_pcm1 __devinitdata = {
+ };
+ 
+ /* record level mixer control */
+-static struct snd_kcontrol_new sgio2audio_ctrl_reclevel __devinitdata = {
++static struct snd_kcontrol_new sgio2audio_ctrl_reclevel = {
+ 	.iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name           = "Capture Volume",
+ 	.access         = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+@@ -272,7 +272,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_reclevel __devinitdata = {
+ };
+ 
+ /* record level source control */
+-static struct snd_kcontrol_new sgio2audio_ctrl_recsource __devinitdata = {
++static struct snd_kcontrol_new sgio2audio_ctrl_recsource = {
+ 	.iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name           = "Capture Source",
+ 	.access         = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+@@ -282,7 +282,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_recsource __devinitdata = {
+ };
+ 
+ /* line mixer control */
+-static struct snd_kcontrol_new sgio2audio_ctrl_line __devinitdata = {
++static struct snd_kcontrol_new sgio2audio_ctrl_line = {
+ 	.iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name           = "Line Playback Volume",
+ 	.index          = 0,
+@@ -294,7 +294,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_line __devinitdata = {
+ };
+ 
+ /* cd mixer control */
+-static struct snd_kcontrol_new sgio2audio_ctrl_cd __devinitdata = {
++static struct snd_kcontrol_new sgio2audio_ctrl_cd = {
+ 	.iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name           = "Line Playback Volume",
+ 	.index          = 1,
+@@ -306,7 +306,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_cd __devinitdata = {
+ };
+ 
+ /* mic mixer control */
+-static struct snd_kcontrol_new sgio2audio_ctrl_mic __devinitdata = {
++static struct snd_kcontrol_new sgio2audio_ctrl_mic = {
+ 	.iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name           = "Mic Playback Volume",
+ 	.access         = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+@@ -317,7 +317,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_mic __devinitdata = {
+ };
+ 
+ 
+-static int __devinit snd_sgio2audio_new_mixer(struct snd_sgio2audio *chip)
++static int snd_sgio2audio_new_mixer(struct snd_sgio2audio *chip)
+ {
+ 	int err;
+ 
+@@ -726,7 +726,7 @@ static struct snd_pcm_ops snd_sgio2audio_capture_ops = {
+  */
+ 
+ /* create a pcm device */
+-static int __devinit snd_sgio2audio_new_pcm(struct snd_sgio2audio *chip)
++static int snd_sgio2audio_new_pcm(struct snd_sgio2audio *chip)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -834,8 +834,8 @@ static struct snd_device_ops ops = {
+ 	.dev_free = snd_sgio2audio_dev_free,
+ };
+ 
+-static int __devinit snd_sgio2audio_create(struct snd_card *card,
+-					   struct snd_sgio2audio **rchip)
++static int snd_sgio2audio_create(struct snd_card *card,
++				 struct snd_sgio2audio **rchip)
+ {
+ 	struct snd_sgio2audio *chip;
+ 	int i, err;
+@@ -914,7 +914,7 @@ static int __devinit snd_sgio2audio_create(struct snd_card *card,
+ 	return 0;
+ }
+ 
+-static int __devinit snd_sgio2audio_probe(struct platform_device *pdev)
++static int snd_sgio2audio_probe(struct platform_device *pdev)
+ {
+ 	struct snd_card *card;
+ 	struct snd_sgio2audio *chip;
+@@ -958,7 +958,7 @@ static int __devinit snd_sgio2audio_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit snd_sgio2audio_remove(struct platform_device *pdev)
++static int snd_sgio2audio_remove(struct platform_device *pdev)
+ {
+ 	struct snd_card *card = platform_get_drvdata(pdev);
+ 
+@@ -969,7 +969,7 @@ static int __devexit snd_sgio2audio_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver sgio2audio_driver = {
+ 	.probe	= snd_sgio2audio_probe,
+-	.remove	= __devexit_p(snd_sgio2audio_remove),
++	.remove	= snd_sgio2audio_remove,
+ 	.driver = {
+ 		.name	= "sgio2audio",
+ 		.owner	= THIS_MODULE,

commit 325fbfe0904eb78007b3c319a73f277b7222116f
+Author: Bill Pemberton 
+Date:   Thu Dec 6 12:35:14 2012 -0500
+
+    ALSA: firewire-speakers: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Clemens Ladisch 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/firewire/speakers.c b/sound/firewire/speakers.c
+index 297244e658d9..d6846557f270 100644
+--- a/sound/firewire/speakers.c
++++ b/sound/firewire/speakers.c
+@@ -663,7 +663,7 @@ static void fwspk_card_free(struct snd_card *card)
+ 	mutex_destroy(&fwspk->mutex);
+ }
+ 
+-static const struct device_info *__devinit fwspk_detect(struct fw_device *dev)
++static const struct device_info *fwspk_detect(struct fw_device *dev)
+ {
+ 	static const struct device_info griffin_firewave = {
+ 		.driver_name = "FireWave",
+@@ -699,7 +699,7 @@ static const struct device_info *__devinit fwspk_detect(struct fw_device *dev)
+ 	return NULL;
+ }
+ 
+-static int __devinit fwspk_probe(struct device *unit_dev)
++static int fwspk_probe(struct device *unit_dev)
+ {
+ 	struct fw_unit *unit = fw_unit(unit_dev);
+ 	struct fw_device *fw_dev = fw_parent_device(unit);
+@@ -770,7 +770,7 @@ static int __devinit fwspk_probe(struct device *unit_dev)
+ 	return err;
+ }
+ 
+-static int __devexit fwspk_remove(struct device *dev)
++static int fwspk_remove(struct device *dev)
+ {
+ 	struct fwspk *fwspk = dev_get_drvdata(dev);
+ 
+@@ -834,7 +834,7 @@ static struct fw_driver fwspk_driver = {
+ 		.name	= KBUILD_MODNAME,
+ 		.bus	= &fw_bus_type,
+ 		.probe	= fwspk_probe,
+-		.remove	= __devexit_p(fwspk_remove),
++		.remove	= fwspk_remove,
+ 	},
+ 	.update   = fwspk_bus_reset,
+ 	.id_table = fwspk_id_table,

commit 61dc674c3b7cc970e62f819c2177059dfdb8b870
+Author: Bill Pemberton 
+Date:   Thu Dec 6 12:35:13 2012 -0500
+
+    ALSA: atmel: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/atmel/abdac.c b/sound/atmel/abdac.c
+index 277ebce23a45..071ce1b5f2b4 100644
+--- a/sound/atmel/abdac.c
++++ b/sound/atmel/abdac.c
+@@ -309,7 +309,7 @@ static struct snd_pcm_ops atmel_abdac_ops = {
+ 	.pointer	= atmel_abdac_pointer,
+ };
+ 
+-static int __devinit atmel_abdac_pcm_new(struct atmel_abdac *dac)
++static int atmel_abdac_pcm_new(struct atmel_abdac *dac)
+ {
+ 	struct snd_pcm_hardware hw = atmel_abdac_hw;
+ 	struct snd_pcm *pcm;
+@@ -386,7 +386,7 @@ static int set_sample_rates(struct atmel_abdac *dac)
+ 	return retval;
+ }
+ 
+-static int __devinit atmel_abdac_probe(struct platform_device *pdev)
++static int atmel_abdac_probe(struct platform_device *pdev)
+ {
+ 	struct snd_card		*card;
+ 	struct atmel_abdac	*dac;
+@@ -567,7 +567,7 @@ static SIMPLE_DEV_PM_OPS(atmel_abdac_pm, atmel_abdac_suspend, atmel_abdac_resume
+ #define ATMEL_ABDAC_PM_OPS	NULL
+ #endif
+ 
+-static int __devexit atmel_abdac_remove(struct platform_device *pdev)
++static int atmel_abdac_remove(struct platform_device *pdev)
+ {
+ 	struct snd_card *card = platform_get_drvdata(pdev);
+ 	struct atmel_abdac *dac = get_dac(card);
+@@ -589,7 +589,7 @@ static int __devexit atmel_abdac_remove(struct platform_device *pdev)
+ }
+ 
+ static struct platform_driver atmel_abdac_driver = {
+-	.remove		= __devexit_p(atmel_abdac_remove),
++	.remove		= atmel_abdac_remove,
+ 	.driver		= {
+ 		.name	= "atmel_abdac",
+ 		.owner	= THIS_MODULE,
+diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c
+index 9052aff37f64..79d6bda58753 100644
+--- a/sound/atmel/ac97c.c
++++ b/sound/atmel/ac97c.c
+@@ -728,7 +728,7 @@ static irqreturn_t atmel_ac97c_interrupt(int irq, void *dev)
+ 	return retval;
+ }
+ 
+-static struct ac97_pcm at91_ac97_pcm_defs[] __devinitdata = {
++static struct ac97_pcm at91_ac97_pcm_defs[] = {
+ 	/* Playback */
+ 	{
+ 		.exclusive = 1,
+@@ -756,7 +756,7 @@ static struct ac97_pcm at91_ac97_pcm_defs[] __devinitdata = {
+ 	},
+ };
+ 
+-static int __devinit atmel_ac97c_pcm_new(struct atmel_ac97c *chip)
++static int atmel_ac97c_pcm_new(struct atmel_ac97c *chip)
+ {
+ 	struct snd_pcm		*pcm;
+ 	struct snd_pcm_hardware	hw = atmel_ac97c_hw;
+@@ -902,7 +902,7 @@ static void atmel_ac97c_reset(struct atmel_ac97c *chip)
+ 	}
+ }
+ 
+-static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
++static int atmel_ac97c_probe(struct platform_device *pdev)
+ {
+ 	struct snd_card			*card;
+ 	struct atmel_ac97c		*chip;
+@@ -1168,7 +1168,7 @@ static SIMPLE_DEV_PM_OPS(atmel_ac97c_pm, atmel_ac97c_suspend, atmel_ac97c_resume
+ #define ATMEL_AC97C_PM_OPS	NULL
+ #endif
+ 
+-static int __devexit atmel_ac97c_remove(struct platform_device *pdev)
++static int atmel_ac97c_remove(struct platform_device *pdev)
+ {
+ 	struct snd_card *card = platform_get_drvdata(pdev);
+ 	struct atmel_ac97c *chip = get_chip(card);
+@@ -1205,7 +1205,7 @@ static int __devexit atmel_ac97c_remove(struct platform_device *pdev)
+ }
+ 
+ static struct platform_driver atmel_ac97c_driver = {
+-	.remove		= __devexit_p(atmel_ac97c_remove),
++	.remove		= atmel_ac97c_remove,
+ 	.driver		= {
+ 		.name	= "atmel_ac97c",
+ 		.owner	= THIS_MODULE,

commit e21596bba143563cd8a2071ea0caff3256fad735
+Author: Bill Pemberton 
+Date:   Thu Dec 6 12:35:12 2012 -0500
+
+    ALSA: pxa2xx: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Eric Miao 
+    Cc: Russell King 
+    Cc: Haojian Zhuang 
+    Cc: linux-arm-kernel@lists.infradead.org
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c
+index 48d7c0aa5073..6fc0ae90e5b1 100644
+--- a/sound/arm/pxa2xx-ac97-lib.c
++++ b/sound/arm/pxa2xx-ac97-lib.c
+@@ -314,7 +314,7 @@ int pxa2xx_ac97_hw_resume(void)
+ EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_resume);
+ #endif
+ 
+-int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev)
++int pxa2xx_ac97_hw_probe(struct platform_device *dev)
+ {
+ 	int ret;
+ 	pxa2xx_audio_ops_t *pdata = dev->dev.platform_data;
+diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
+index 4e1fda75c1c9..ec54be4efff0 100644
+--- a/sound/arm/pxa2xx-ac97.c
++++ b/sound/arm/pxa2xx-ac97.c
+@@ -163,7 +163,7 @@ static int pxa2xx_ac97_resume(struct device *dev)
+ static SIMPLE_DEV_PM_OPS(pxa2xx_ac97_pm_ops, pxa2xx_ac97_suspend, pxa2xx_ac97_resume);
+ #endif
+ 
+-static int __devinit pxa2xx_ac97_probe(struct platform_device *dev)
++static int pxa2xx_ac97_probe(struct platform_device *dev)
+ {
+ 	struct snd_card *card;
+ 	struct snd_ac97_bus *ac97_bus;
+@@ -224,7 +224,7 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev)
+ 	return ret;
+ }
+ 
+-static int __devexit pxa2xx_ac97_remove(struct platform_device *dev)
++static int pxa2xx_ac97_remove(struct platform_device *dev)
+ {
+ 	struct snd_card *card = platform_get_drvdata(dev);
+ 
+@@ -239,7 +239,7 @@ static int __devexit pxa2xx_ac97_remove(struct platform_device *dev)
+ 
+ static struct platform_driver pxa2xx_ac97_driver = {
+ 	.probe		= pxa2xx_ac97_probe,
+-	.remove		= __devexit_p(pxa2xx_ac97_remove),
++	.remove		= pxa2xx_ac97_remove,
+ 	.driver		= {
+ 		.name	= "pxa2xx-ac97",
+ 		.owner	= THIS_MODULE,

commit 6c9dc19c103b36da066c64a7758f5934f245f37d
+Author: Bill Pemberton 
+Date:   Thu Dec 6 12:35:11 2012 -0500
+
+    ALSA: AACI: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Russell King 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
+index 5119fdabcb98..aa5d8034890b 100644
+--- a/sound/arm/aaci.c
++++ b/sound/arm/aaci.c
+@@ -786,7 +786,7 @@ static int aaci_resume(struct amba_device *dev)
+ #endif
+ 
+ 
+-static struct ac97_pcm ac97_defs[] __devinitdata = {
++static struct ac97_pcm ac97_defs[] = {
+ 	[0] = {	/* Front PCM */
+ 		.exclusive = 1,
+ 		.r = {
+@@ -832,7 +832,7 @@ static struct snd_ac97_bus_ops aaci_bus_ops = {
+ 	.read	= aaci_ac97_read,
+ };
+ 
+-static int __devinit aaci_probe_ac97(struct aaci *aaci)
++static int aaci_probe_ac97(struct aaci *aaci)
+ {
+ 	struct snd_ac97_template ac97_template;
+ 	struct snd_ac97_bus *ac97_bus;
+@@ -893,7 +893,7 @@ static void aaci_free_card(struct snd_card *card)
+ 		iounmap(aaci->base);
+ }
+ 
+-static struct aaci * __devinit aaci_init_card(struct amba_device *dev)
++static struct aaci *aaci_init_card(struct amba_device *dev)
+ {
+ 	struct aaci *aaci;
+ 	struct snd_card *card;
+@@ -926,7 +926,7 @@ static struct aaci * __devinit aaci_init_card(struct amba_device *dev)
+ 	return aaci;
+ }
+ 
+-static int __devinit aaci_init_pcm(struct aaci *aaci)
++static int aaci_init_pcm(struct aaci *aaci)
+ {
+ 	struct snd_pcm *pcm;
+ 	int ret;
+@@ -948,7 +948,7 @@ static int __devinit aaci_init_pcm(struct aaci *aaci)
+ 	return ret;
+ }
+ 
+-static unsigned int __devinit aaci_size_fifo(struct aaci *aaci)
++static unsigned int aaci_size_fifo(struct aaci *aaci)
+ {
+ 	struct aaci_runtime *aacirun = &aaci->playback;
+ 	int i;
+@@ -984,8 +984,8 @@ static unsigned int __devinit aaci_size_fifo(struct aaci *aaci)
+ 	return i;
+ }
+ 
+-static int __devinit aaci_probe(struct amba_device *dev,
+-	const struct amba_id *id)
++static int aaci_probe(struct amba_device *dev,
++		      const struct amba_id *id)
+ {
+ 	struct aaci *aaci;
+ 	int ret, i;
+@@ -1072,7 +1072,7 @@ static int __devinit aaci_probe(struct amba_device *dev,
+ 	return ret;
+ }
+ 
+-static int __devexit aaci_remove(struct amba_device *dev)
++static int aaci_remove(struct amba_device *dev)
+ {
+ 	struct snd_card *card = amba_get_drvdata(dev);
+ 
+@@ -1104,7 +1104,7 @@ static struct amba_driver aaci_driver = {
+ 		.name	= DRIVER_NAME,
+ 	},
+ 	.probe		= aaci_probe,
+-	.remove		= __devexit_p(aaci_remove),
++	.remove		= aaci_remove,
+ 	.suspend	= aaci_suspend,
+ 	.resume		= aaci_resume,
+ 	.id_table	= aaci_ids,

commit e23e7a1436207217000c2854214bc908936af3cb
+Author: Bill Pemberton 
+Date:   Thu Dec 6 12:35:10 2012 -0500
+
+    ALSA: pci: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/ak4531_codec.c b/sound/pci/ak4531_codec.c
+index cadf7b962e30..3bf0dc53360a 100644
+--- a/sound/pci/ak4531_codec.c
++++ b/sound/pci/ak4531_codec.c
+@@ -274,7 +274,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_master, -6200, 200, 0);
+ static const DECLARE_TLV_DB_SCALE(db_scale_mono, -2800, 400, 0);
+ static const DECLARE_TLV_DB_SCALE(db_scale_input, -5000, 200, 0);
+ 
+-static struct snd_kcontrol_new snd_ak4531_controls[] __devinitdata = {
++static struct snd_kcontrol_new snd_ak4531_controls[] = {
+ 
+ AK4531_DOUBLE_TLV("Master Playback Switch", 0,
+ 		  AK4531_LMASTER, AK4531_RMASTER, 7, 7, 1, 1,
+@@ -383,9 +383,9 @@ static u8 snd_ak4531_initial_map[0x19 + 1] = {
+ 	0x01		/* 19: Mic Amp Setup */
+ };
+ 
+-int __devinit snd_ak4531_mixer(struct snd_card *card,
+-			       struct snd_ak4531 *_ak4531,
+-			       struct snd_ak4531 **rak4531)
++int snd_ak4531_mixer(struct snd_card *card,
++		     struct snd_ak4531 *_ak4531,
++		     struct snd_ak4531 **rak4531)
+ {
+ 	unsigned int idx;
+ 	int err;
+@@ -483,7 +483,7 @@ static void snd_ak4531_proc_read(struct snd_info_entry *entry,
+ 		    ak4531->regs[AK4531_MIC_GAIN] & 1 ? "+30dB" : "+0dB");
+ }
+ 
+-static void __devinit
++static void
+ snd_ak4531_proc_init(struct snd_card *card, struct snd_ak4531 *ak4531)
+ {
+ 	struct snd_info_entry *entry;
+diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
+index c7e3c533316e..136a393b70ab 100644
+--- a/sound/pci/ali5451/ali5451.c
++++ b/sound/pci/ali5451/ali5451.c
+@@ -1678,8 +1678,8 @@ static void snd_ali_pcm_free(struct snd_pcm *pcm)
+ }
+ 
+ 
+-static int __devinit snd_ali_pcm(struct snd_ali * codec, int device,
+-				 struct ali_pcm_description *desc)
++static int snd_ali_pcm(struct snd_ali *codec, int device,
++		       struct ali_pcm_description *desc)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -1727,7 +1727,7 @@ static struct ali_pcm_description ali_pcms[] = {
+ 	}
+ };
+ 
+-static int __devinit snd_ali_build_pcms(struct snd_ali *codec)
++static int snd_ali_build_pcms(struct snd_ali *codec)
+ {
+ 	int i, err;
+ 	for (i = 0; i < codec->num_of_codecs && i < ARRAY_SIZE(ali_pcms); i++) {
+@@ -1832,7 +1832,7 @@ static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol,
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_ali5451_mixer_spdif[] __devinitdata = {
++static struct snd_kcontrol_new snd_ali5451_mixer_spdif[] = {
+ 	/* spdif aplayback switch */
+ 	/* FIXME: "IEC958 Playback Switch" may conflict with one on ac97_codec */
+ 	ALI5451_SPDIF(SNDRV_CTL_NAME_IEC958("Output ",NONE,SWITCH), 0, 0),
+@@ -1842,7 +1842,7 @@ static struct snd_kcontrol_new snd_ali5451_mixer_spdif[] __devinitdata = {
+ 	ALI5451_SPDIF(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0, 2)
+ };
+ 
+-static int __devinit snd_ali_mixer(struct snd_ali * codec)
++static int snd_ali_mixer(struct snd_ali *codec)
+ {
+ 	struct snd_ac97_template ac97;
+ 	unsigned int idx;
+@@ -2079,14 +2079,14 @@ static void snd_ali_proc_read(struct snd_info_entry *entry,
+ 		snd_iprintf(buf, "%02x: %08x\n", i, inl(ALI_REG(codec, i)));
+ }
+ 
+-static void __devinit snd_ali_proc_init(struct snd_ali *codec)
++static void snd_ali_proc_init(struct snd_ali *codec)
+ {
+ 	struct snd_info_entry *entry;
+ 	if (!snd_card_proc_new(codec->card, "ali5451", &entry))
+ 		snd_info_set_text_ops(entry, codec, snd_ali_proc_read);
+ }
+ 
+-static int __devinit snd_ali_resources(struct snd_ali *codec)
++static int snd_ali_resources(struct snd_ali *codec)
+ {
+ 	int err;
+ 
+@@ -2112,11 +2112,11 @@ static int snd_ali_dev_free(struct snd_device *device)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_ali_create(struct snd_card *card,
+-				    struct pci_dev *pci,
+-				    int pcm_streams,
+-				    int spdif_support,
+-				    struct snd_ali ** r_ali)
++static int snd_ali_create(struct snd_card *card,
++			  struct pci_dev *pci,
++			  int pcm_streams,
++			  int spdif_support,
++			  struct snd_ali **r_ali)
+ {
+ 	struct snd_ali *codec;
+ 	int i, err;
+@@ -2246,8 +2246,8 @@ static int __devinit snd_ali_create(struct snd_card *card,
+ 	return 0;
+ }
+ 
+-static int __devinit snd_ali_probe(struct pci_dev *pci,
+-				   const struct pci_device_id *pci_id)
++static int snd_ali_probe(struct pci_dev *pci,
++			 const struct pci_device_id *pci_id)
+ {
+ 	struct snd_card *card;
+ 	struct snd_ali *codec;
+@@ -2295,7 +2295,7 @@ static int __devinit snd_ali_probe(struct pci_dev *pci,
+ 	return err;
+ }
+ 
+-static void __devexit snd_ali_remove(struct pci_dev *pci)
++static void snd_ali_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -2305,7 +2305,7 @@ static struct pci_driver ali5451_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_ali_ids,
+ 	.probe = snd_ali_probe,
+-	.remove = __devexit_p(snd_ali_remove),
++	.remove = snd_ali_remove,
+ 	.driver = {
+ 		.pm = ALI_PM_OPS,
+ 	},
+diff --git a/sound/pci/als300.c b/sound/pci/als300.c
+index 5af3cb6b0c18..864c4310366b 100644
+--- a/sound/pci/als300.c
++++ b/sound/pci/als300.c
+@@ -278,7 +278,7 @@ static irqreturn_t snd_als300plus_interrupt(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static void __devexit snd_als300_remove(struct pci_dev *pci)
++static void snd_als300_remove(struct pci_dev *pci)
+ {
+ 	snd_als300_dbgcallenter();
+ 	snd_card_free(pci_get_drvdata(pci));
+@@ -622,7 +622,7 @@ static struct snd_pcm_ops snd_als300_capture_ops = {
+ 	.pointer =	snd_als300_pointer,
+ };
+ 
+-static int __devinit snd_als300_new_pcm(struct snd_als300 *chip)
++static int snd_als300_new_pcm(struct snd_als300 *chip)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -683,9 +683,9 @@ static void snd_als300_init(struct snd_als300 *chip)
+ 	snd_als300_dbgcallleave();
+ }
+ 
+-static int __devinit snd_als300_create(struct snd_card *card,
+-				       struct pci_dev *pci, int chip_type,
+-				       struct snd_als300 **rchip)
++static int snd_als300_create(struct snd_card *card,
++			     struct pci_dev *pci, int chip_type,
++			     struct snd_als300 **rchip)
+ {
+ 	struct snd_als300 *chip;
+ 	void *irq_handler;
+@@ -815,7 +815,7 @@ static SIMPLE_DEV_PM_OPS(snd_als300_pm, snd_als300_suspend, snd_als300_resume);
+ #define SND_ALS300_PM_OPS	NULL
+ #endif
+ 
+-static int __devinit snd_als300_probe(struct pci_dev *pci,
++static int snd_als300_probe(struct pci_dev *pci,
+                              const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+@@ -867,7 +867,7 @@ static struct pci_driver als300_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_als300_ids,
+ 	.probe = snd_als300_probe,
+-	.remove = __devexit_p(snd_als300_remove),
++	.remove = snd_als300_remove,
+ 	.driver = {
+ 		.pm = SND_ALS300_PM_OPS,
+ 	},
+diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
+index feb2a1436830..61efda2a4d94 100644
+--- a/sound/pci/als4000.c
++++ b/sound/pci/als4000.c
+@@ -694,7 +694,7 @@ static struct snd_pcm_ops snd_als4000_capture_ops = {
+ 	.pointer =	snd_als4000_capture_pointer
+ };
+ 
+-static int __devinit snd_als4000_pcm(struct snd_sb *chip, int device)
++static int snd_als4000_pcm(struct snd_sb *chip, int device)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -770,7 +770,7 @@ static void snd_als4000_configure(struct snd_sb *chip)
+ }
+ 
+ #ifdef SUPPORT_JOYSTICK
+-static int __devinit snd_als4000_create_gameport(struct snd_card_als4000 *acard, int dev)
++static int snd_als4000_create_gameport(struct snd_card_als4000 *acard, int dev)
+ {
+ 	struct gameport *gp;
+ 	struct resource *r;
+@@ -847,8 +847,8 @@ static void snd_card_als4000_free( struct snd_card *card )
+ 	pci_disable_device(acard->pci);
+ }
+ 
+-static int __devinit snd_card_als4000_probe(struct pci_dev *pci,
+-					  const struct pci_device_id *pci_id)
++static int snd_card_als4000_probe(struct pci_dev *pci,
++				  const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -981,7 +981,7 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci,
+ 	return err;
+ }
+ 
+-static void __devexit snd_card_als4000_remove(struct pci_dev *pci)
++static void snd_card_als4000_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -1046,7 +1046,7 @@ static struct pci_driver als4000_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_als4000_ids,
+ 	.probe = snd_card_als4000_probe,
+-	.remove = __devexit_p(snd_card_als4000_remove),
++	.remove = snd_card_als4000_remove,
+ 	.driver = {
+ 		.pm = SND_ALS4000_PM_OPS,
+ 	},
+diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c
+index eedc017c1cd8..3536b076b529 100644
+--- a/sound/pci/asihpi/asihpi.c
++++ b/sound/pci/asihpi/asihpi.c
+@@ -1235,8 +1235,7 @@ static struct snd_pcm_ops snd_card_asihpi_capture_mmap_ops = {
+ 	.pointer = snd_card_asihpi_capture_pointer,
+ };
+ 
+-static int __devinit snd_card_asihpi_pcm_new(
+-		struct snd_card_asihpi *asihpi, int device)
++static int snd_card_asihpi_pcm_new(struct snd_card_asihpi *asihpi, int device)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -1497,8 +1496,8 @@ static int snd_asihpi_volume_mute_put(struct snd_kcontrol *kcontrol,
+ 	return change;
+ }
+ 
+-static int __devinit snd_asihpi_volume_add(struct snd_card_asihpi *asihpi,
+-					struct hpi_control *hpi_ctl)
++static int snd_asihpi_volume_add(struct snd_card_asihpi *asihpi,
++				 struct hpi_control *hpi_ctl)
+ {
+ 	struct snd_card *card = asihpi->card;
+ 	struct snd_kcontrol_new snd_control;
+@@ -1593,8 +1592,8 @@ static int snd_asihpi_level_put(struct snd_kcontrol *kcontrol,
+ 
+ static const DECLARE_TLV_DB_SCALE(db_scale_level, -1000, 100, 0);
+ 
+-static int __devinit snd_asihpi_level_add(struct snd_card_asihpi *asihpi,
+-					struct hpi_control *hpi_ctl)
++static int snd_asihpi_level_add(struct snd_card_asihpi *asihpi,
++				struct hpi_control *hpi_ctl)
+ {
+ 	struct snd_card *card = asihpi->card;
+ 	struct snd_kcontrol_new snd_control;
+@@ -1715,8 +1714,8 @@ static int snd_asihpi_aesebu_rxstatus_get(struct snd_kcontrol *kcontrol,
+ 	return 0;
+ }
+ 
+-static int __devinit snd_asihpi_aesebu_rx_add(struct snd_card_asihpi *asihpi,
+-					struct hpi_control *hpi_ctl)
++static int snd_asihpi_aesebu_rx_add(struct snd_card_asihpi *asihpi,
++				    struct hpi_control *hpi_ctl)
+ {
+ 	struct snd_card *card = asihpi->card;
+ 	struct snd_kcontrol_new snd_control;
+@@ -1753,8 +1752,8 @@ static int snd_asihpi_aesebu_tx_format_put(struct snd_kcontrol *kcontrol,
+ }
+ 
+ 
+-static int __devinit snd_asihpi_aesebu_tx_add(struct snd_card_asihpi *asihpi,
+-					struct hpi_control *hpi_ctl)
++static int snd_asihpi_aesebu_tx_add(struct snd_card_asihpi *asihpi,
++				    struct hpi_control *hpi_ctl)
+ {
+ 	struct snd_card *card = asihpi->card;
+ 	struct snd_kcontrol_new snd_control;
+@@ -1996,8 +1995,8 @@ static int snd_asihpi_tuner_freq_put(struct snd_kcontrol *kcontrol,
+ }
+ 
+ /* Tuner control group initializer  */
+-static int __devinit snd_asihpi_tuner_add(struct snd_card_asihpi *asihpi,
+-					struct hpi_control *hpi_ctl)
++static int snd_asihpi_tuner_add(struct snd_card_asihpi *asihpi,
++				struct hpi_control *hpi_ctl)
+ {
+ 	struct snd_card *card = asihpi->card;
+ 	struct snd_kcontrol_new snd_control;
+@@ -2100,8 +2099,8 @@ static int snd_asihpi_meter_get(struct snd_kcontrol *kcontrol,
+ 	return 0;
+ }
+ 
+-static int __devinit snd_asihpi_meter_add(struct snd_card_asihpi *asihpi,
+-					struct hpi_control *hpi_ctl, int subidx)
++static int snd_asihpi_meter_add(struct snd_card_asihpi *asihpi,
++				struct hpi_control *hpi_ctl, int subidx)
+ {
+ 	struct snd_card *card = asihpi->card;
+ 	struct snd_kcontrol_new snd_control;
+@@ -2214,8 +2213,8 @@ static int snd_asihpi_mux_put(struct snd_kcontrol *kcontrol,
+ }
+ 
+ 
+-static int  __devinit snd_asihpi_mux_add(struct snd_card_asihpi *asihpi,
+-					struct hpi_control *hpi_ctl)
++static int  snd_asihpi_mux_add(struct snd_card_asihpi *asihpi,
++			       struct hpi_control *hpi_ctl)
+ {
+ 	struct snd_card *card = asihpi->card;
+ 	struct snd_kcontrol_new snd_control;
+@@ -2303,8 +2302,8 @@ static int snd_asihpi_cmode_put(struct snd_kcontrol *kcontrol,
+ }
+ 
+ 
+-static int __devinit snd_asihpi_cmode_add(struct snd_card_asihpi *asihpi,
+-					struct hpi_control *hpi_ctl)
++static int snd_asihpi_cmode_add(struct snd_card_asihpi *asihpi,
++				struct hpi_control *hpi_ctl)
+ {
+ 	struct snd_card *card = asihpi->card;
+ 	struct snd_kcontrol_new snd_control;
+@@ -2471,8 +2470,8 @@ static int snd_asihpi_clkrate_get(struct snd_kcontrol *kcontrol,
+ 	return 0;
+ }
+ 
+-static int __devinit snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi,
+-					struct hpi_control *hpi_ctl)
++static int snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi,
++				      struct hpi_control *hpi_ctl)
+ {
+ 	struct snd_card *card = asihpi->card;
+ 	struct snd_kcontrol_new snd_control;
+@@ -2548,7 +2547,7 @@ static int __devinit snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi,
+    Mixer
+  ------------------------------------------------------------*/
+ 
+-static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi)
++static int snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi)
+ {
+ 	struct snd_card *card = asihpi->card;
+ 	unsigned int idx = 0;
+@@ -2722,7 +2721,7 @@ snd_asihpi_proc_read(struct snd_info_entry *entry,
+ 	}
+ }
+ 
+-static void __devinit snd_asihpi_proc_init(struct snd_card_asihpi *asihpi)
++static void snd_asihpi_proc_init(struct snd_card_asihpi *asihpi)
+ {
+ 	struct snd_info_entry *entry;
+ 
+@@ -2764,8 +2763,8 @@ static int snd_asihpi_hpi_ioctl(struct snd_hwdep *hw, struct file *file,
+ /* results in /dev/snd/hwC#D0 file for each card with index #
+    also /proc/asound/hwdep will contain '#-00: asihpi (HPI) for each card'
+ */
+-static int __devinit snd_asihpi_hpi_new(struct snd_card_asihpi *asihpi,
+-	int device, struct snd_hwdep **rhwdep)
++static int snd_asihpi_hpi_new(struct snd_card_asihpi *asihpi,
++			      int device, struct snd_hwdep **rhwdep)
+ {
+ 	struct snd_hwdep *hw;
+ 	int err;
+@@ -2789,8 +2788,8 @@ static int __devinit snd_asihpi_hpi_new(struct snd_card_asihpi *asihpi,
+ /*------------------------------------------------------------
+    CARD
+  ------------------------------------------------------------*/
+-static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev,
+-				       const struct pci_device_id *pci_id)
++static int snd_asihpi_probe(struct pci_dev *pci_dev,
++			    const struct pci_device_id *pci_id)
+ {
+ 	int err;
+ 	struct hpi_adapter *hpi;
+@@ -2944,7 +2943,7 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev,
+ 
+ }
+ 
+-static void __devexit snd_asihpi_remove(struct pci_dev *pci_dev)
++static void snd_asihpi_remove(struct pci_dev *pci_dev)
+ {
+ 	struct hpi_adapter *hpi = pci_get_drvdata(pci_dev);
+ 	snd_card_free(hpi->snd_card);
+@@ -2967,7 +2966,7 @@ static struct pci_driver driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = asihpi_pci_tbl,
+ 	.probe = snd_asihpi_probe,
+-	.remove = __devexit_p(snd_asihpi_remove),
++	.remove = snd_asihpi_remove,
+ #ifdef CONFIG_PM_SLEEP
+ /*	.suspend = snd_asihpi_suspend,
+ 	.resume = snd_asihpi_resume, */
+diff --git a/sound/pci/asihpi/hpioctl.c b/sound/pci/asihpi/hpioctl.c
+index 8f9674972376..ef5019fe5193 100644
+--- a/sound/pci/asihpi/hpioctl.c
++++ b/sound/pci/asihpi/hpioctl.c
+@@ -307,8 +307,8 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ 	return err;
+ }
+ 
+-int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
+-	const struct pci_device_id *pci_id)
++int asihpi_adapter_probe(struct pci_dev *pci_dev,
++			 const struct pci_device_id *pci_id)
+ {
+ 	int idx, nm;
+ 	int adapter_index;
+@@ -420,7 +420,7 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
+ 	return -ENODEV;
+ }
+ 
+-void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev)
++void asihpi_adapter_remove(struct pci_dev *pci_dev)
+ {
+ 	int idx;
+ 	struct hpi_message hm;
+diff --git a/sound/pci/asihpi/hpioctl.h b/sound/pci/asihpi/hpioctl.h
+index 2614aff672e2..0d767e10ac48 100644
+--- a/sound/pci/asihpi/hpioctl.h
++++ b/sound/pci/asihpi/hpioctl.h
+@@ -19,9 +19,9 @@
+ Linux HPI ioctl, and shared module init functions
+ *******************************************************************************/
+ 
+-int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
+-	const struct pci_device_id *pci_id);
+-void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev);
++int asihpi_adapter_probe(struct pci_dev *pci_dev,
++			 const struct pci_device_id *pci_id);
++void asihpi_adapter_remove(struct pci_dev *pci_dev);
+ void __init asihpi_init(void);
+ void __exit asihpi_exit(void);
+ 
+diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
+index 368df8b0853e..a67743183aaf 100644
+--- a/sound/pci/atiixp.c
++++ b/sound/pci/atiixp.c
+@@ -296,7 +296,7 @@ static DEFINE_PCI_DEVICE_TABLE(snd_atiixp_ids) = {
+ 
+ MODULE_DEVICE_TABLE(pci, snd_atiixp_ids);
+ 
+-static struct snd_pci_quirk atiixp_quirks[] __devinitdata = {
++static struct snd_pci_quirk atiixp_quirks[] = {
+ 	SND_PCI_QUIRK(0x105b, 0x0c81, "Foxconn RC4107MA-RS2", 0),
+ 	SND_PCI_QUIRK(0x15bd, 0x3100, "DFI RS482", 0),
+ 	{ } /* terminator */
+@@ -561,7 +561,7 @@ static int snd_atiixp_aclink_down(struct atiixp *chip)
+ 	     ATI_REG_ISR_CODEC2_NOT_READY)
+ #define CODEC_CHECK_BITS (ALL_CODEC_NOT_READY|ATI_REG_ISR_NEW_FRAME)
+ 
+-static int __devinit ac97_probing_bugs(struct pci_dev *pci)
++static int ac97_probing_bugs(struct pci_dev *pci)
+ {
+ 	const struct snd_pci_quirk *q;
+ 
+@@ -575,7 +575,7 @@ static int __devinit ac97_probing_bugs(struct pci_dev *pci)
+ 	return -1;
+ }
+ 
+-static int __devinit snd_atiixp_codec_detect(struct atiixp *chip)
++static int snd_atiixp_codec_detect(struct atiixp *chip)
+ {
+ 	int timeout;
+ 
+@@ -1183,7 +1183,7 @@ static struct snd_pcm_ops snd_atiixp_spdif_ops = {
+ 	.pointer =	snd_atiixp_pcm_pointer,
+ };
+ 
+-static struct ac97_pcm atiixp_pcm_defs[] __devinitdata = {
++static struct ac97_pcm atiixp_pcm_defs[] = {
+ 	/* front PCM */
+ 	{
+ 		.exclusive = 1,
+@@ -1247,7 +1247,7 @@ static struct atiixp_dma_ops snd_atiixp_spdif_dma_ops = {
+ };
+ 	
+ 
+-static int __devinit snd_atiixp_pcm_new(struct atiixp *chip)
++static int snd_atiixp_pcm_new(struct atiixp *chip)
+ {
+ 	struct snd_pcm *pcm;
+ 	struct snd_pcm_chmap *chmap;
+@@ -1390,7 +1390,7 @@ static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id)
+  * ac97 mixer section
+  */
+ 
+-static struct ac97_quirk ac97_quirks[] __devinitdata = {
++static struct ac97_quirk ac97_quirks[] = {
+ 	{
+ 		.subvendor = 0x103c,
+ 		.subdevice = 0x006b,
+@@ -1412,8 +1412,8 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
+ 	{ } /* terminator */
+ };
+ 
+-static int __devinit snd_atiixp_mixer_new(struct atiixp *chip, int clock,
+-					  const char *quirk_override)
++static int snd_atiixp_mixer_new(struct atiixp *chip, int clock,
++				const char *quirk_override)
+ {
+ 	struct snd_ac97_bus *pbus;
+ 	struct snd_ac97_template ac97;
+@@ -1560,7 +1560,7 @@ static void snd_atiixp_proc_read(struct snd_info_entry *entry,
+ 		snd_iprintf(buffer, "%02x: %08x\n", i, readl(chip->remap_addr + i));
+ }
+ 
+-static void __devinit snd_atiixp_proc_init(struct atiixp *chip)
++static void snd_atiixp_proc_init(struct atiixp *chip)
+ {
+ 	struct snd_info_entry *entry;
+ 
+@@ -1602,9 +1602,9 @@ static int snd_atiixp_dev_free(struct snd_device *device)
+ /*
+  * constructor for chip instance
+  */
+-static int __devinit snd_atiixp_create(struct snd_card *card,
+-				      struct pci_dev *pci,
+-				      struct atiixp **r_chip)
++static int snd_atiixp_create(struct snd_card *card,
++			     struct pci_dev *pci,
++			     struct atiixp **r_chip)
+ {
+ 	static struct snd_device_ops ops = {
+ 		.dev_free =	snd_atiixp_dev_free,
+@@ -1661,8 +1661,8 @@ static int __devinit snd_atiixp_create(struct snd_card *card,
+ }
+ 
+ 
+-static int __devinit snd_atiixp_probe(struct pci_dev *pci,
+-				     const struct pci_device_id *pci_id)
++static int snd_atiixp_probe(struct pci_dev *pci,
++			    const struct pci_device_id *pci_id)
+ {
+ 	struct snd_card *card;
+ 	struct atiixp *chip;
+@@ -1710,7 +1710,7 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci,
+ 	return err;
+ }
+ 
+-static void __devexit snd_atiixp_remove(struct pci_dev *pci)
++static void snd_atiixp_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -1720,7 +1720,7 @@ static struct pci_driver atiixp_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_atiixp_ids,
+ 	.probe = snd_atiixp_probe,
+-	.remove = __devexit_p(snd_atiixp_remove),
++	.remove = snd_atiixp_remove,
+ 	.driver = {
+ 		.pm = SND_ATIIXP_PM_OPS,
+ 	},
+diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
+index 6fc03d9f2cff..d0bec7ba3b0d 100644
+--- a/sound/pci/atiixp_modem.c
++++ b/sound/pci/atiixp_modem.c
+@@ -988,7 +988,7 @@ static struct atiixp_dma_ops snd_atiixp_capture_dma_ops = {
+ 	.flush_dma = atiixp_in_flush_dma,
+ };
+ 
+-static int __devinit snd_atiixp_pcm_new(struct atiixp_modem *chip)
++static int snd_atiixp_pcm_new(struct atiixp_modem *chip)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -1061,7 +1061,7 @@ static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id)
+  * ac97 mixer section
+  */
+ 
+-static int __devinit snd_atiixp_mixer_new(struct atiixp_modem *chip, int clock)
++static int snd_atiixp_mixer_new(struct atiixp_modem *chip, int clock)
+ {
+ 	struct snd_ac97_bus *pbus;
+ 	struct snd_ac97_template ac97;
+@@ -1186,7 +1186,7 @@ static void snd_atiixp_proc_read(struct snd_info_entry *entry,
+ 		snd_iprintf(buffer, "%02x: %08x\n", i, readl(chip->remap_addr + i));
+ }
+ 
+-static void __devinit snd_atiixp_proc_init(struct atiixp_modem *chip)
++static void snd_atiixp_proc_init(struct atiixp_modem *chip)
+ {
+ 	struct snd_info_entry *entry;
+ 
+@@ -1228,9 +1228,9 @@ static int snd_atiixp_dev_free(struct snd_device *device)
+ /*
+  * constructor for chip instance
+  */
+-static int __devinit snd_atiixp_create(struct snd_card *card,
+-				       struct pci_dev *pci,
+-				       struct atiixp_modem **r_chip)
++static int snd_atiixp_create(struct snd_card *card,
++			     struct pci_dev *pci,
++			     struct atiixp_modem **r_chip)
+ {
+ 	static struct snd_device_ops ops = {
+ 		.dev_free =	snd_atiixp_dev_free,
+@@ -1287,8 +1287,8 @@ static int __devinit snd_atiixp_create(struct snd_card *card,
+ }
+ 
+ 
+-static int __devinit snd_atiixp_probe(struct pci_dev *pci,
+-				      const struct pci_device_id *pci_id)
++static int snd_atiixp_probe(struct pci_dev *pci,
++			    const struct pci_device_id *pci_id)
+ {
+ 	struct snd_card *card;
+ 	struct atiixp_modem *chip;
+@@ -1331,7 +1331,7 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci,
+ 	return err;
+ }
+ 
+-static void __devexit snd_atiixp_remove(struct pci_dev *pci)
++static void snd_atiixp_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -1341,7 +1341,7 @@ static struct pci_driver atiixp_modem_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_atiixp_ids,
+ 	.probe = snd_atiixp_probe,
+-	.remove = __devexit_p(snd_atiixp_remove),
++	.remove = snd_atiixp_remove,
+ 	.driver = {
+ 		.pm = SND_ATIIXP_PM_OPS,
+ 	},
+diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
+index ffc376f9f4e4..b157e1fadd8f 100644
+--- a/sound/pci/au88x0/au88x0.c
++++ b/sound/pci/au88x0/au88x0.c
+@@ -78,7 +78,7 @@ static void vortex_fix_agp_bridge(struct pci_dev *via)
+ 	}
+ }
+ 
+-static void __devinit snd_vortex_workaround(struct pci_dev *vortex, int fix)
++static void snd_vortex_workaround(struct pci_dev *vortex, int fix)
+ {
+ 	struct pci_dev *via = NULL;
+ 
+@@ -137,7 +137,7 @@ static int snd_vortex_dev_free(struct snd_device *device)
+ 
+ // chip-specific constructor
+ // (see "Management of Cards and Components")
+-static int __devinit
++static int
+ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
+ {
+ 	vortex_t *chip;
+@@ -234,7 +234,7 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
+ }
+ 
+ // constructor -- see "Constructor" sub-section
+-static int __devinit
++static int
+ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+@@ -368,7 +368,7 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+ }
+ 
+ // destructor -- see "Destructor" sub-section
+-static void __devexit snd_vortex_remove(struct pci_dev *pci)
++static void snd_vortex_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -379,7 +379,7 @@ static struct pci_driver vortex_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_vortex_ids,
+ 	.probe = snd_vortex_probe,
+-	.remove = __devexit_p(snd_vortex_remove),
++	.remove = snd_vortex_remove,
+ };
+ 
+ module_pci_driver(vortex_driver);
+diff --git a/sound/pci/au88x0/au88x0_a3d.c b/sound/pci/au88x0/au88x0_a3d.c
+index 9ae8b3b17651..aad831acbb17 100644
+--- a/sound/pci/au88x0/au88x0_a3d.c
++++ b/sound/pci/au88x0/au88x0_a3d.c
+@@ -594,7 +594,7 @@ static int Vort3DRend_Initialize(vortex_t * v, unsigned short mode)
+ static int vortex_a3d_register_controls(vortex_t * vortex);
+ static void vortex_a3d_unregister_controls(vortex_t * vortex);
+ /* A3D base support init/shudown */
+-static void __devinit vortex_Vort3D_enable(vortex_t * v)
++static void vortex_Vort3D_enable(vortex_t *v)
+ {
+ 	int i;
+ 
+@@ -845,7 +845,7 @@ snd_vortex_a3d_filter_put(struct snd_kcontrol *kcontrol,
+ 	return changed;
+ }
+ 
+-static struct snd_kcontrol_new vortex_a3d_kcontrol __devinitdata = {
++static struct snd_kcontrol_new vortex_a3d_kcontrol = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ 	.name = "Playback PCM advanced processing",
+ 	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+@@ -855,7 +855,7 @@ static struct snd_kcontrol_new vortex_a3d_kcontrol __devinitdata = {
+ };
+ 
+ /* Control (un)registration. */
+-static int __devinit vortex_a3d_register_controls(vortex_t * vortex)
++static int vortex_a3d_register_controls(vortex_t *vortex)
+ {
+ 	struct snd_kcontrol *kcontrol;
+ 	int err, i;
+diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c
+index 2698abf5d05d..ae59dbaa53d9 100644
+--- a/sound/pci/au88x0/au88x0_core.c
++++ b/sound/pci/au88x0/au88x0_core.c
+@@ -2680,7 +2680,7 @@ static void vortex_spdif_init(vortex_t * vortex, int spdif_sr, int spdif_mode)
+ 
+ /* Initialization */
+ 
+-static int __devinit vortex_core_init(vortex_t * vortex)
++static int vortex_core_init(vortex_t *vortex)
+ {
+ 
+ 	printk(KERN_INFO "Vortex: init.... ");
+diff --git a/sound/pci/au88x0/au88x0_eq.c b/sound/pci/au88x0/au88x0_eq.c
+index 278ed8189fca..e7220533ecfc 100644
+--- a/sound/pci/au88x0/au88x0_eq.c
++++ b/sound/pci/au88x0/au88x0_eq.c
+@@ -757,7 +757,7 @@ snd_vortex_eqtoggle_put(struct snd_kcontrol *kcontrol,
+ 	return 1;		/* Allways changes */
+ }
+ 
+-static struct snd_kcontrol_new vortex_eqtoggle_kcontrol __devinitdata = {
++static struct snd_kcontrol_new vortex_eqtoggle_kcontrol = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "EQ Enable",
+ 	.index = 0,
+@@ -815,7 +815,7 @@ snd_vortex_eq_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucon
+ 	return changed;
+ }
+ 
+-static struct snd_kcontrol_new vortex_eq_kcontrol __devinitdata = {
++static struct snd_kcontrol_new vortex_eq_kcontrol = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "                        .",
+ 	.index = 0,
+@@ -854,7 +854,7 @@ snd_vortex_peaks_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *u
+ 	return 0;
+ }
+ 
+-static struct snd_kcontrol_new vortex_levels_kcontrol __devinitdata = {
++static struct snd_kcontrol_new vortex_levels_kcontrol = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "EQ Peaks",
+ 	.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+@@ -863,7 +863,7 @@ static struct snd_kcontrol_new vortex_levels_kcontrol __devinitdata = {
+ };
+ 
+ /* EQ band gain labels. */
+-static char *EqBandLabels[10] __devinitdata = {
++static char *EqBandLabels[10] = {
+ 	"EQ0 31Hz\0",
+ 	"EQ1 63Hz\0",
+ 	"EQ2 125Hz\0",
+@@ -877,7 +877,7 @@ static char *EqBandLabels[10] __devinitdata = {
+ };
+ 
+ /* ALSA driver entry points. Init and exit. */
+-static int __devinit vortex_eq_init(vortex_t * vortex)
++static int vortex_eq_init(vortex_t *vortex)
+ {
+ 	struct snd_kcontrol *kcontrol;
+ 	int err, i;
+diff --git a/sound/pci/au88x0/au88x0_game.c b/sound/pci/au88x0/au88x0_game.c
+index 30a456700d89..280f86de2230 100644
+--- a/sound/pci/au88x0/au88x0_game.c
++++ b/sound/pci/au88x0/au88x0_game.c
+@@ -92,7 +92,7 @@ static int vortex_game_open(struct gameport *gameport, int mode)
+ 	return 0;
+ }
+ 
+-static int __devinit vortex_gameport_register(vortex_t * vortex)
++static int vortex_gameport_register(vortex_t *vortex)
+ {
+ 	struct gameport *gp;
+ 
+diff --git a/sound/pci/au88x0/au88x0_mixer.c b/sound/pci/au88x0/au88x0_mixer.c
+index fa13efbebdaf..a58298cfe7e0 100644
+--- a/sound/pci/au88x0/au88x0_mixer.c
++++ b/sound/pci/au88x0/au88x0_mixer.c
+@@ -19,7 +19,7 @@ static int remove_ctl(struct snd_card *card, const char *name)
+ 	return snd_ctl_remove_id(card, &id);
+ }
+ 
+-static int __devinit snd_vortex_mixer(vortex_t * vortex)
++static int snd_vortex_mixer(vortex_t *vortex)
+ {
+ 	struct snd_ac97_bus *pbus;
+ 	struct snd_ac97_template ac97;
+diff --git a/sound/pci/au88x0/au88x0_mpu401.c b/sound/pci/au88x0/au88x0_mpu401.c
+index e6c6a0febb75..29e5945eef60 100644
+--- a/sound/pci/au88x0/au88x0_mpu401.c
++++ b/sound/pci/au88x0/au88x0_mpu401.c
+@@ -41,7 +41,7 @@
+ #define MPU401_ENTER_UART	0x3f
+ #define MPU401_ACK		    0xfe
+ 
+-static int __devinit snd_vortex_midi(vortex_t * vortex)
++static int snd_vortex_midi(vortex_t *vortex)
+ {
+ 	struct snd_rawmidi *rmidi;
+ 	int temp, mode;
+diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c
+index b2405020284c..a4184bb27761 100644
+--- a/sound/pci/au88x0/au88x0_pcm.c
++++ b/sound/pci/au88x0/au88x0_pcm.c
+@@ -516,7 +516,7 @@ static int snd_vortex_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el
+ }
+ 
+ /* spdif controls */
+-static struct snd_kcontrol_new snd_vortex_mixer_spdif[] __devinitdata = {
++static struct snd_kcontrol_new snd_vortex_mixer_spdif[] = {
+ 	{
+ 		.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+ 		.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
+@@ -598,7 +598,7 @@ static int snd_vortex_pcm_vol_put(struct snd_kcontrol *kcontrol,
+ 
+ static const DECLARE_TLV_DB_MINMAX(vortex_pcm_vol_db_scale, -9600, 2400);
+ 
+-static struct snd_kcontrol_new snd_vortex_pcm_vol __devinitdata = {
++static struct snd_kcontrol_new snd_vortex_pcm_vol = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ 	.name = "PCM Playback Volume",
+ 	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+@@ -611,7 +611,7 @@ static struct snd_kcontrol_new snd_vortex_pcm_vol __devinitdata = {
+ };
+ 
+ /* create a pcm device */
+-static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
++static int snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
+ {
+ 	struct snd_pcm *pcm;
+ 	struct snd_kcontrol *kctl;
+diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
+index 0f804741825f..08e9a4702cbc 100644
+--- a/sound/pci/aw2/aw2-alsa.c
++++ b/sound/pci/aw2/aw2-alsa.c
+@@ -113,11 +113,11 @@ struct aw2 {
+  * FUNCTION DECLARATIONS
+  ********************************/
+ static int snd_aw2_dev_free(struct snd_device *device);
+-static int __devinit snd_aw2_create(struct snd_card *card,
+-				    struct pci_dev *pci, struct aw2 **rchip);
+-static int __devinit snd_aw2_probe(struct pci_dev *pci,
+-				   const struct pci_device_id *pci_id);
+-static void __devexit snd_aw2_remove(struct pci_dev *pci);
++static int snd_aw2_create(struct snd_card *card,
++			  struct pci_dev *pci, struct aw2 **rchip);
++static int snd_aw2_probe(struct pci_dev *pci,
++			 const struct pci_device_id *pci_id);
++static void snd_aw2_remove(struct pci_dev *pci);
+ static int snd_aw2_pcm_playback_open(struct snd_pcm_substream *substream);
+ static int snd_aw2_pcm_playback_close(struct snd_pcm_substream *substream);
+ static int snd_aw2_pcm_capture_open(struct snd_pcm_substream *substream);
+@@ -135,7 +135,7 @@ static snd_pcm_uframes_t snd_aw2_pcm_pointer_playback(struct snd_pcm_substream
+ 						      *substream);
+ static snd_pcm_uframes_t snd_aw2_pcm_pointer_capture(struct snd_pcm_substream
+ 						     *substream);
+-static int __devinit snd_aw2_new_pcm(struct aw2 *chip);
++static int snd_aw2_new_pcm(struct aw2 *chip);
+ 
+ static int snd_aw2_control_switch_capture_info(struct snd_kcontrol *kcontrol,
+ 					       struct snd_ctl_elem_info *uinfo);
+@@ -173,7 +173,7 @@ static struct pci_driver aw2_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_aw2_ids,
+ 	.probe = snd_aw2_probe,
+-	.remove = __devexit_p(snd_aw2_remove),
++	.remove = snd_aw2_remove,
+ };
+ 
+ module_pci_driver(aw2_driver);
+@@ -202,7 +202,7 @@ static struct snd_pcm_ops snd_aw2_capture_ops = {
+ 	.pointer = snd_aw2_pcm_pointer_capture,
+ };
+ 
+-static struct snd_kcontrol_new aw2_control __devinitdata = {
++static struct snd_kcontrol_new aw2_control = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "PCM Capture Route",
+ 	.index = 0,
+@@ -242,8 +242,8 @@ static int snd_aw2_dev_free(struct snd_device *device)
+ }
+ 
+ /* chip-specific constructor */
+-static int __devinit snd_aw2_create(struct snd_card *card,
+-				    struct pci_dev *pci, struct aw2 **rchip)
++static int snd_aw2_create(struct snd_card *card,
++			  struct pci_dev *pci, struct aw2 **rchip)
+ {
+ 	struct aw2 *chip;
+ 	int err;
+@@ -332,8 +332,8 @@ static int __devinit snd_aw2_create(struct snd_card *card,
+ }
+ 
+ /* constructor */
+-static int __devinit snd_aw2_probe(struct pci_dev *pci,
+-				   const struct pci_device_id *pci_id)
++static int snd_aw2_probe(struct pci_dev *pci,
++			 const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -389,7 +389,7 @@ static int __devinit snd_aw2_probe(struct pci_dev *pci,
+ }
+ 
+ /* destructor */
+-static void __devexit snd_aw2_remove(struct pci_dev *pci)
++static void snd_aw2_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -591,7 +591,7 @@ static snd_pcm_uframes_t snd_aw2_pcm_pointer_capture(struct snd_pcm_substream
+ }
+ 
+ /* create a pcm device */
+-static int __devinit snd_aw2_new_pcm(struct aw2 *chip)
++static int snd_aw2_new_pcm(struct aw2 *chip)
+ {
+ 	struct snd_pcm *pcm_playback_ana;
+ 	struct snd_pcm *pcm_playback_num;
+diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
+index c03b66b784a3..1204a0fa3368 100644
+--- a/sound/pci/azt3328.c
++++ b/sound/pci/azt3328.c
+@@ -817,7 +817,7 @@ snd_azf3328_mixer_ac97_write(struct snd_ac97 *ac97,
+ 		snd_azf3328_mixer_ac97_map_unsupported(reg_ac97, "write");
+ }
+ 
+-static int __devinit
++static int
+ snd_azf3328_mixer_new(struct snd_azf3328 *chip)
+ {
+ 	struct snd_ac97_bus *bus;
+@@ -1171,7 +1171,7 @@ snd_azf3328_put_mixer_enum(struct snd_kcontrol *kcontrol,
+ 	return (nreg != oreg);
+ }
+ 
+-static struct snd_kcontrol_new snd_azf3328_mixer_controls[] __devinitdata = {
++static struct snd_kcontrol_new snd_azf3328_mixer_controls[] = {
+ 	AZF3328_MIXER_SWITCH("Master Playback Switch", IDX_MIXER_PLAY_MASTER, 15, 1),
+ 	AZF3328_MIXER_VOL_STEREO("Master Playback Volume", IDX_MIXER_PLAY_MASTER, 0x1f, 1),
+ 	AZF3328_MIXER_SWITCH("PCM Playback Switch", IDX_MIXER_WAVEOUT, 15, 1),
+@@ -1229,7 +1229,7 @@ static struct snd_kcontrol_new snd_azf3328_mixer_controls[] __devinitdata = {
+ #endif
+ };
+ 
+-static u16 __devinitdata snd_azf3328_init_values[][2] = {
++static u16 snd_azf3328_init_values[][2] = {
+         { IDX_MIXER_PLAY_MASTER,	MIXER_MUTE_MASK|0x1f1f },
+         { IDX_MIXER_MODEMOUT,		MIXER_MUTE_MASK|0x1f1f },
+ 	{ IDX_MIXER_BASSTREBLE,		0x0000 },
+@@ -1245,7 +1245,7 @@ static u16 __devinitdata snd_azf3328_init_values[][2] = {
+         { IDX_MIXER_REC_VOLUME,		MIXER_MUTE_MASK|0x0707 },
+ };
+ 
+-static int __devinit
++static int
+ snd_azf3328_mixer_new(struct snd_azf3328 *chip)
+ {
+ 	struct snd_card *card;
+@@ -1899,7 +1899,7 @@ snd_azf3328_gameport_cooked_read(struct gameport *gameport,
+ 	return 0;
+ }
+ 
+-static int __devinit
++static int
+ snd_azf3328_gameport(struct snd_azf3328 *chip, int dev)
+ {
+ 	struct gameport *gp;
+@@ -2212,7 +2212,7 @@ static struct snd_pcm_ops snd_azf3328_i2s_out_ops = {
+ 	.pointer =	snd_azf3328_pcm_pointer
+ };
+ 
+-static int __devinit
++static int
+ snd_azf3328_pcm(struct snd_azf3328 *chip)
+ {
+ enum { AZF_PCMDEV_STD, AZF_PCMDEV_I2S_OUT, NUM_AZF_PCMDEVS }; /* pcm devices */
+@@ -2344,7 +2344,7 @@ static struct snd_timer_hardware snd_azf3328_timer_hw = {
+ 	.precise_resolution = snd_azf3328_timer_precise_resolution,
+ };
+ 
+-static int __devinit
++static int
+ snd_azf3328_timer(struct snd_azf3328 *chip, int device)
+ {
+ 	struct snd_timer *timer = NULL;
+@@ -2489,7 +2489,7 @@ snd_azf3328_debug_show_ports(const struct snd_azf3328 *chip)
+ #endif /* DEBUG_MISC */
+ }
+ 
+-static int __devinit
++static int
+ snd_azf3328_create(struct snd_card *card,
+ 		   struct pci_dev *pci,
+ 		   unsigned long device_type,
+@@ -2615,7 +2615,7 @@ snd_azf3328_create(struct snd_card *card,
+ 	return err;
+ }
+ 
+-static int __devinit
++static int
+ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+@@ -2720,7 +2720,7 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+ 	return err;
+ }
+ 
+-static void __devexit
++static void
+ snd_azf3328_remove(struct pci_dev *pci)
+ {
+ 	snd_azf3328_dbgcallenter();
+@@ -2872,7 +2872,7 @@ static struct pci_driver azf3328_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_azf3328_ids,
+ 	.probe = snd_azf3328_probe,
+-	.remove = __devexit_p(snd_azf3328_remove),
++	.remove = snd_azf3328_remove,
+ 	.driver = {
+ 		.pm = SND_AZF3328_PM_OPS,
+ 	},
+diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
+index 65c55910566b..1610a5705970 100644
+--- a/sound/pci/ca0106/ca0106_main.c
++++ b/sound/pci/ca0106/ca0106_main.c
+@@ -1352,7 +1352,7 @@ static const struct snd_pcm_chmap_elem side_map[] = {
+ 	{ }
+ };
+ 
+-static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device)
++static int snd_ca0106_pcm(struct snd_ca0106 *emu, int device)
+ {
+ 	struct snd_pcm *pcm;
+ 	struct snd_pcm_substream *substream;
+@@ -1650,7 +1650,7 @@ static void ca0106_stop_chip(struct snd_ca0106 *chip)
+ 	 */
+ }
+ 
+-static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
++static int snd_ca0106_create(int dev, struct snd_card *card,
+ 					 struct pci_dev *pci,
+ 					 struct snd_ca0106 **rchip)
+ {
+@@ -1777,7 +1777,7 @@ static int ca0106_dev_id_port(void *dev_id)
+ 	return ((struct snd_ca0106 *)dev_id)->port;
+ }
+ 
+-static int __devinit snd_ca0106_midi(struct snd_ca0106 *chip, unsigned int channel)
++static int snd_ca0106_midi(struct snd_ca0106 *chip, unsigned int channel)
+ {
+ 	struct snd_ca_midi *midi;
+ 	char *name;
+@@ -1828,7 +1828,7 @@ static int __devinit snd_ca0106_midi(struct snd_ca0106 *chip, unsigned int chann
+ }
+ 
+ 
+-static int __devinit snd_ca0106_probe(struct pci_dev *pci,
++static int snd_ca0106_probe(struct pci_dev *pci,
+ 					const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+@@ -1893,7 +1893,7 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
+ 	return err;
+ }
+ 
+-static void __devexit snd_ca0106_remove(struct pci_dev *pci)
++static void snd_ca0106_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -1971,7 +1971,7 @@ static struct pci_driver ca0106_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_ca0106_ids,
+ 	.probe = snd_ca0106_probe,
+-	.remove = __devexit_p(snd_ca0106_remove),
++	.remove = snd_ca0106_remove,
+ 	.driver = {
+ 		.pm = SND_CA0106_PM_OPS,
+ 	},
+diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
+index 68eacf7002d6..27de0de90018 100644
+--- a/sound/pci/ca0106/ca0106_mixer.c
++++ b/sound/pci/ca0106/ca0106_mixer.c
+@@ -325,7 +325,7 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
+         return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata =
++static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in =
+ {
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name =		"Shared Mic/Line in Capture Switch",
+@@ -334,7 +334,7 @@ static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata =
+ 	.put =		snd_ca0106_capture_mic_line_in_put
+ };
+ 
+-static struct snd_kcontrol_new snd_ca0106_capture_line_in_side_out __devinitdata =
++static struct snd_kcontrol_new snd_ca0106_capture_line_in_side_out =
+ {
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name =		"Shared Line in/Side out Capture Switch",
+@@ -588,7 +588,7 @@ static int spi_mute_put(struct snd_kcontrol *kcontrol,
+ 	.private_value = ((chid) << 8) | (reg)			\
+ }
+ 
+-static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
++static struct snd_kcontrol_new snd_ca0106_volume_ctls[] = {
+ 	CA_VOLUME("Analog Front Playback Volume",
+ 		  CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2),
+         CA_VOLUME("Analog Rear Playback Volume",
+@@ -669,7 +669,7 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
+ 	.private_value = chid					\
+ }
+ 
+-static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] __devinitdata = {
++static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] = {
+         I2C_VOLUME("Phone Capture Volume", 0),
+         I2C_VOLUME("Mic Capture Volume", 1),
+         I2C_VOLUME("Line in Capture Volume", 2),
+@@ -691,7 +691,7 @@ static const int spi_dmute_bit[] = {
+ 	SPI_DMUTE4_BIT,
+ };
+ 
+-static struct snd_kcontrol_new __devinit
++static struct snd_kcontrol_new
+ snd_ca0106_volume_spi_dac_ctl(struct snd_ca0106_details *details,
+ 			      int channel_id)
+ {
+@@ -735,7 +735,7 @@ snd_ca0106_volume_spi_dac_ctl(struct snd_ca0106_details *details,
+ 	return spi_switch;
+ }
+ 
+-static int __devinit remove_ctl(struct snd_card *card, const char *name)
++static int remove_ctl(struct snd_card *card, const char *name)
+ {
+ 	struct snd_ctl_elem_id id;
+ 	memset(&id, 0, sizeof(id));
+@@ -744,7 +744,7 @@ static int __devinit remove_ctl(struct snd_card *card, const char *name)
+ 	return snd_ctl_remove_id(card, &id);
+ }
+ 
+-static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card, const char *name)
++static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name)
+ {
+ 	struct snd_ctl_elem_id sid;
+ 	memset(&sid, 0, sizeof(sid));
+@@ -754,7 +754,7 @@ static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card, const char
+ 	return snd_ctl_find_id(card, &sid);
+ }
+ 
+-static int __devinit rename_ctl(struct snd_card *card, const char *src, const char *dst)
++static int rename_ctl(struct snd_card *card, const char *src, const char *dst)
+ {
+ 	struct snd_kcontrol *kctl = ctl_find(card, src);
+ 	if (kctl) {
+@@ -774,10 +774,10 @@ static int __devinit rename_ctl(struct snd_card *card, const char *src, const ch
+ 		}							\
+ 	} while (0)
+ 
+-static __devinitdata
++static
+ DECLARE_TLV_DB_SCALE(snd_ca0106_master_db_scale, -6375, 25, 1);
+ 
+-static char *slave_vols[] __devinitdata = {
++static char *slave_vols[] = {
+ 	"Analog Front Playback Volume",
+         "Analog Rear Playback Volume",
+ 	"Analog Center/LFE Playback Volume",
+@@ -790,7 +790,7 @@ static char *slave_vols[] __devinitdata = {
+ 	NULL
+ };
+ 
+-static char *slave_sws[] __devinitdata = {
++static char *slave_sws[] = {
+ 	"Analog Front Playback Switch",
+ 	"Analog Rear Playback Switch",
+ 	"Analog Center/LFE Playback Switch",
+@@ -799,7 +799,7 @@ static char *slave_sws[] __devinitdata = {
+ 	NULL
+ };
+ 
+-static void __devinit add_slaves(struct snd_card *card,
++static void add_slaves(struct snd_card *card,
+ 				 struct snd_kcontrol *master, char **list)
+ {
+ 	for (; *list; list++) {
+@@ -809,7 +809,7 @@ static void __devinit add_slaves(struct snd_card *card,
+ 	}
+ }
+ 
+-int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
++int snd_ca0106_mixer(struct snd_ca0106 *emu)
+ {
+ 	int err;
+         struct snd_card *card = emu->card;
+diff --git a/sound/pci/ca0106/ca0106_proc.c b/sound/pci/ca0106/ca0106_proc.c
+index c694464b1168..4f9c2821bb31 100644
+--- a/sound/pci/ca0106/ca0106_proc.c
++++ b/sound/pci/ca0106/ca0106_proc.c
+@@ -424,7 +424,7 @@ static void snd_ca0106_proc_i2c_write(struct snd_info_entry *entry,
+         }
+ }
+ 
+-int __devinit snd_ca0106_proc_init(struct snd_ca0106 * emu)
++int snd_ca0106_proc_init(struct snd_ca0106 *emu)
+ {
+ 	struct snd_info_entry *entry;
+ 	
+diff --git a/sound/pci/ca0106/ca_midi.c b/sound/pci/ca0106/ca_midi.c
+index c7885117da33..8bbdf265d11d 100644
+--- a/sound/pci/ca0106/ca_midi.c
++++ b/sound/pci/ca0106/ca_midi.c
+@@ -286,7 +286,7 @@ static void ca_rmidi_free(struct snd_rawmidi *rmidi)
+ 	ca_midi_free(rmidi->private_data);
+ }
+ 
+-int __devinit ca_midi_init(void *dev_id, struct snd_ca_midi *midi, int device, char *name)
++int ca_midi_init(void *dev_id, struct snd_ca_midi *midi, int device, char *name)
+ {
+ 	struct snd_rawmidi *rmidi;
+ 	int err;
+diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
+index 22122ff26e34..c617435db6e6 100644
+--- a/sound/pci/cmipci.c
++++ b/sound/pci/cmipci.c
+@@ -1045,7 +1045,7 @@ static int snd_cmipci_spdif_default_put(struct snd_kcontrol *kcontrol,
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_cmipci_spdif_default __devinitdata =
++static struct snd_kcontrol_new snd_cmipci_spdif_default =
+ {
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+ 	.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
+@@ -1072,7 +1072,7 @@ static int snd_cmipci_spdif_mask_get(struct snd_kcontrol *kcontrol,
+ 	return 0;
+ }
+ 
+-static struct snd_kcontrol_new snd_cmipci_spdif_mask __devinitdata =
++static struct snd_kcontrol_new snd_cmipci_spdif_mask =
+ {
+ 	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+@@ -1119,7 +1119,7 @@ static int snd_cmipci_spdif_stream_put(struct snd_kcontrol *kcontrol,
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_cmipci_spdif_stream __devinitdata =
++static struct snd_kcontrol_new snd_cmipci_spdif_stream =
+ {
+ 	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+@@ -1897,7 +1897,7 @@ static struct snd_pcm_ops snd_cmipci_capture_spdif_ops = {
+ /*
+  */
+ 
+-static int __devinit snd_cmipci_pcm_new(struct cmipci *cm, int device)
++static int snd_cmipci_pcm_new(struct cmipci *cm, int device)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -1920,7 +1920,7 @@ static int __devinit snd_cmipci_pcm_new(struct cmipci *cm, int device)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_cmipci_pcm2_new(struct cmipci *cm, int device)
++static int snd_cmipci_pcm2_new(struct cmipci *cm, int device)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -1942,7 +1942,7 @@ static int __devinit snd_cmipci_pcm2_new(struct cmipci *cm, int device)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_cmipci_pcm_spdif_new(struct cmipci *cm, int device)
++static int snd_cmipci_pcm_spdif_new(struct cmipci *cm, int device)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -2290,7 +2290,7 @@ static int snd_cmipci_put_native_mixer_sensitive(struct snd_kcontrol *kcontrol,
+ }
+ 
+ 
+-static struct snd_kcontrol_new snd_cmipci_mixers[] __devinitdata = {
++static struct snd_kcontrol_new snd_cmipci_mixers[] = {
+ 	CMIPCI_SB_VOL_STEREO("Master Playback Volume", SB_DSP4_MASTER_DEV, 3, 31),
+ 	CMIPCI_MIXER_SW_MONO("3D Control - Switch", CM_REG_MIXER1, CM_X3DEN_SHIFT, 0),
+ 	CMIPCI_SB_VOL_STEREO("PCM Playback Volume", SB_DSP4_PCM_DEV, 3, 31),
+@@ -2601,7 +2601,7 @@ static int snd_cmipci_mic_in_mode_put(struct snd_kcontrol *kcontrol,
+ }
+ 
+ /* both for CM8338/8738 */
+-static struct snd_kcontrol_new snd_cmipci_mixer_switches[] __devinitdata = {
++static struct snd_kcontrol_new snd_cmipci_mixer_switches[] = {
+ 	DEFINE_MIXER_SWITCH("Four Channel Mode", fourch),
+ 	{
+ 		.name = "Line-In Mode",
+@@ -2613,11 +2613,11 @@ static struct snd_kcontrol_new snd_cmipci_mixer_switches[] __devinitdata = {
+ };
+ 
+ /* for non-multichannel chips */
+-static struct snd_kcontrol_new snd_cmipci_nomulti_switch __devinitdata =
++static struct snd_kcontrol_new snd_cmipci_nomulti_switch =
+ DEFINE_MIXER_SWITCH("Exchange DAC", exchange_dac);
+ 
+ /* only for CM8738 */
+-static struct snd_kcontrol_new snd_cmipci_8738_mixer_switches[] __devinitdata = {
++static struct snd_kcontrol_new snd_cmipci_8738_mixer_switches[] = {
+ #if 0 /* controlled in pcm device */
+ 	DEFINE_MIXER_SWITCH("IEC958 In Record", spdif_in),
+ 	DEFINE_MIXER_SWITCH("IEC958 Out", spdif_out),
+@@ -2639,14 +2639,14 @@ static struct snd_kcontrol_new snd_cmipci_8738_mixer_switches[] __devinitdata =
+ };
+ 
+ /* only for model 033/037 */
+-static struct snd_kcontrol_new snd_cmipci_old_mixer_switches[] __devinitdata = {
++static struct snd_kcontrol_new snd_cmipci_old_mixer_switches[] = {
+ 	DEFINE_MIXER_SWITCH("IEC958 Mix Analog", spdif_dac_out),
+ 	DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase),
+ 	DEFINE_MIXER_SWITCH("IEC958 In Select", spdif_in_sel1),
+ };
+ 
+ /* only for model 039 or later */
+-static struct snd_kcontrol_new snd_cmipci_extra_mixer_switches[] __devinitdata = {
++static struct snd_kcontrol_new snd_cmipci_extra_mixer_switches[] = {
+ 	DEFINE_MIXER_SWITCH("IEC958 In Select", spdif_in_sel2),
+ 	DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase2),
+ 	{
+@@ -2659,11 +2659,11 @@ static struct snd_kcontrol_new snd_cmipci_extra_mixer_switches[] __devinitdata =
+ };
+ 
+ /* card control switches */
+-static struct snd_kcontrol_new snd_cmipci_modem_switch __devinitdata =
++static struct snd_kcontrol_new snd_cmipci_modem_switch =
+ DEFINE_CARD_SWITCH("Modem", modem);
+ 
+ 
+-static int __devinit snd_cmipci_mixer_new(struct cmipci *cm, int pcm_spdif_device)
++static int snd_cmipci_mixer_new(struct cmipci *cm, int pcm_spdif_device)
+ {
+ 	struct snd_card *card;
+ 	struct snd_kcontrol_new *sw;
+@@ -2791,7 +2791,7 @@ static void snd_cmipci_proc_read(struct snd_info_entry *entry,
+ 	snd_iprintf(buffer, "\n");
+ }
+ 
+-static void __devinit snd_cmipci_proc_init(struct cmipci *cm)
++static void snd_cmipci_proc_init(struct cmipci *cm)
+ {
+ 	struct snd_info_entry *entry;
+ 
+@@ -2817,7 +2817,7 @@ static DEFINE_PCI_DEVICE_TABLE(snd_cmipci_ids) = {
+  * check chip version and capabilities
+  * driver name is modified according to the chip model
+  */
+-static void __devinit query_chip(struct cmipci *cm)
++static void query_chip(struct cmipci *cm)
+ {
+ 	unsigned int detect;
+ 
+@@ -2866,7 +2866,7 @@ static void __devinit query_chip(struct cmipci *cm)
+ }
+ 
+ #ifdef SUPPORT_JOYSTICK
+-static int __devinit snd_cmipci_create_gameport(struct cmipci *cm, int dev)
++static int snd_cmipci_create_gameport(struct cmipci *cm, int dev)
+ {
+ 	static int ports[] = { 0x201, 0x200, 0 }; /* FIXME: majority is 0x201? */
+ 	struct gameport *gp;
+@@ -2959,7 +2959,7 @@ static int snd_cmipci_dev_free(struct snd_device *device)
+ 	return snd_cmipci_free(cm);
+ }
+ 
+-static int __devinit snd_cmipci_create_fm(struct cmipci *cm, long fm_port)
++static int snd_cmipci_create_fm(struct cmipci *cm, long fm_port)
+ {
+ 	long iosynth;
+ 	unsigned int val;
+@@ -3012,8 +3012,8 @@ static int __devinit snd_cmipci_create_fm(struct cmipci *cm, long fm_port)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
+-				       int dev, struct cmipci **rcmipci)
++static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
++			     int dev, struct cmipci **rcmipci)
+ {
+ 	struct cmipci *cm;
+ 	int err;
+@@ -3265,8 +3265,8 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc
+ 
+ MODULE_DEVICE_TABLE(pci, snd_cmipci_ids);
+ 
+-static int __devinit snd_cmipci_probe(struct pci_dev *pci,
+-				      const struct pci_device_id *pci_id)
++static int snd_cmipci_probe(struct pci_dev *pci,
++			    const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -3314,7 +3314,7 @@ static int __devinit snd_cmipci_probe(struct pci_dev *pci,
+ 
+ }
+ 
+-static void __devexit snd_cmipci_remove(struct pci_dev *pci)
++static void snd_cmipci_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -3415,7 +3415,7 @@ static struct pci_driver cmipci_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_cmipci_ids,
+ 	.probe = snd_cmipci_probe,
+-	.remove = __devexit_p(snd_cmipci_remove),
++	.remove = snd_cmipci_remove,
+ 	.driver = {
+ 		.pm = SND_CMIPCI_PM_OPS,
+ 	},
+diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
+index 8e86ec0031fc..6a8695069941 100644
+--- a/sound/pci/cs4281.c
++++ b/sound/pci/cs4281.c
+@@ -969,8 +969,8 @@ static struct snd_pcm_ops snd_cs4281_capture_ops = {
+ 	.pointer =	snd_cs4281_pointer,
+ };
+ 
+-static int __devinit snd_cs4281_pcm(struct cs4281 * chip, int device,
+-				    struct snd_pcm ** rpcm)
++static int snd_cs4281_pcm(struct cs4281 *chip, int device,
++			  struct snd_pcm **rpcm)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -1093,7 +1093,7 @@ static void snd_cs4281_mixer_free_ac97(struct snd_ac97 *ac97)
+ 		chip->ac97 = NULL;
+ }
+ 
+-static int __devinit snd_cs4281_mixer(struct cs4281 * chip)
++static int snd_cs4281_mixer(struct cs4281 *chip)
+ {
+ 	struct snd_card *card = chip->card;
+ 	struct snd_ac97_template ac97;
+@@ -1171,7 +1171,7 @@ static struct snd_info_entry_ops snd_cs4281_proc_ops_BA1 = {
+ 	.read = snd_cs4281_BA1_read,
+ };
+ 
+-static void __devinit snd_cs4281_proc_init(struct cs4281 * chip)
++static void snd_cs4281_proc_init(struct cs4281 *chip)
+ {
+ 	struct snd_info_entry *entry;
+ 
+@@ -1259,7 +1259,7 @@ static int snd_cs4281_gameport_open(struct gameport *gameport, int mode)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_cs4281_create_gameport(struct cs4281 *chip)
++static int snd_cs4281_create_gameport(struct cs4281 *chip)
+ {
+ 	struct gameport *gp;
+ 
+@@ -1335,10 +1335,10 @@ static int snd_cs4281_dev_free(struct snd_device *device)
+ 
+ static int snd_cs4281_chip_init(struct cs4281 *chip); /* defined below */
+ 
+-static int __devinit snd_cs4281_create(struct snd_card *card,
+-				       struct pci_dev *pci,
+-				       struct cs4281 ** rchip,
+-				       int dual_codec)
++static int snd_cs4281_create(struct snd_card *card,
++			     struct pci_dev *pci,
++			     struct cs4281 **rchip,
++			     int dual_codec)
+ {
+ 	struct cs4281 *chip;
+ 	unsigned int tmp;
+@@ -1779,8 +1779,8 @@ static struct snd_rawmidi_ops snd_cs4281_midi_input =
+ 	.trigger =	snd_cs4281_midi_input_trigger,
+ };
+ 
+-static int __devinit snd_cs4281_midi(struct cs4281 * chip, int device,
+-				     struct snd_rawmidi **rrawmidi)
++static int snd_cs4281_midi(struct cs4281 *chip, int device,
++			   struct snd_rawmidi **rrawmidi)
+ {
+ 	struct snd_rawmidi *rmidi;
+ 	int err;
+@@ -1901,8 +1901,8 @@ static void snd_cs4281_opl3_command(struct snd_opl3 *opl3, unsigned short cmd,
+ 	spin_unlock_irqrestore(&opl3->reg_lock, flags);
+ }
+ 
+-static int __devinit snd_cs4281_probe(struct pci_dev *pci,
+-				      const struct pci_device_id *pci_id)
++static int snd_cs4281_probe(struct pci_dev *pci,
++			    const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -1968,7 +1968,7 @@ static int __devinit snd_cs4281_probe(struct pci_dev *pci,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_cs4281_remove(struct pci_dev *pci)
++static void snd_cs4281_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -2095,7 +2095,7 @@ static struct pci_driver cs4281_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_cs4281_ids,
+ 	.probe = snd_cs4281_probe,
+-	.remove = __devexit_p(snd_cs4281_remove),
++	.remove = snd_cs4281_remove,
+ 	.driver = {
+ 		.pm = CS4281_PM_OPS,
+ 	},
+diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
+index 575bed0836ff..6b0d8b50a305 100644
+--- a/sound/pci/cs46xx/cs46xx.c
++++ b/sound/pci/cs46xx/cs46xx.c
+@@ -73,8 +73,8 @@ static DEFINE_PCI_DEVICE_TABLE(snd_cs46xx_ids) = {
+ 
+ MODULE_DEVICE_TABLE(pci, snd_cs46xx_ids);
+ 
+-static int __devinit snd_card_cs46xx_probe(struct pci_dev *pci,
+-					   const struct pci_device_id *pci_id)
++static int snd_card_cs46xx_probe(struct pci_dev *pci,
++				 const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -155,7 +155,7 @@ static int __devinit snd_card_cs46xx_probe(struct pci_dev *pci,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_card_cs46xx_remove(struct pci_dev *pci)
++static void snd_card_cs46xx_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -165,7 +165,7 @@ static struct pci_driver cs46xx_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_cs46xx_ids,
+ 	.probe = snd_card_cs46xx_probe,
+-	.remove = __devexit_p(snd_card_cs46xx_remove),
++	.remove = snd_card_cs46xx_remove,
+ #ifdef CONFIG_PM_SLEEP
+ 	.driver = {
+ 		.pm = &snd_cs46xx_pm,
+diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
+index a2bb8c91ebe6..1b66efd9b728 100644
+--- a/sound/pci/cs46xx/cs46xx_lib.c
++++ b/sound/pci/cs46xx/cs46xx_lib.c
+@@ -1590,7 +1590,7 @@ static struct snd_pcm_ops snd_cs46xx_capture_indirect_ops = {
+ #define MAX_PLAYBACK_CHANNELS	1
+ #endif
+ 
+-int __devinit snd_cs46xx_pcm(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm)
++int snd_cs46xx_pcm(struct snd_cs46xx *chip, int device, struct snd_pcm **rpcm)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -1621,7 +1621,8 @@ int __devinit snd_cs46xx_pcm(struct snd_cs46xx *chip, int device, struct snd_pcm
+ 
+ 
+ #ifdef CONFIG_SND_CS46XX_NEW_DSP
+-int __devinit snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm)
++int snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device,
++			struct snd_pcm **rpcm)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -1650,7 +1651,8 @@ int __devinit snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device, struct sn
+ 	return 0;
+ }
+ 
+-int __devinit snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm)
++int snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device,
++			      struct snd_pcm **rpcm)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -1679,7 +1681,8 @@ int __devinit snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device, str
+ 	return 0;
+ }
+ 
+-int __devinit snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm)
++int snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device,
++			  struct snd_pcm **rpcm)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -2092,7 +2095,7 @@ static int snd_cs46xx_spdif_stream_put(struct snd_kcontrol *kcontrol,
+ #endif /* CONFIG_SND_CS46XX_NEW_DSP */
+ 
+ 
+-static struct snd_kcontrol_new snd_cs46xx_controls[] __devinitdata = {
++static struct snd_kcontrol_new snd_cs46xx_controls[] = {
+ {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "DAC Volume",
+@@ -2278,7 +2281,7 @@ static void snd_cs46xx_codec_reset (struct snd_ac97 * ac97)
+ }
+ #endif
+ 
+-static int __devinit cs46xx_detect_codec(struct snd_cs46xx *chip, int codec)
++static int cs46xx_detect_codec(struct snd_cs46xx *chip, int codec)
+ {
+ 	int idx, err;
+ 	struct snd_ac97_template ac97;
+@@ -2311,7 +2314,7 @@ static int __devinit cs46xx_detect_codec(struct snd_cs46xx *chip, int codec)
+ 	return -ENXIO;
+ }
+ 
+-int __devinit snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device)
++int snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device)
+ {
+ 	struct snd_card *card = chip->card;
+ 	struct snd_ctl_elem_id id;
+@@ -2531,7 +2534,7 @@ static struct snd_rawmidi_ops snd_cs46xx_midi_input =
+ 	.trigger =	snd_cs46xx_midi_input_trigger,
+ };
+ 
+-int __devinit snd_cs46xx_midi(struct snd_cs46xx *chip, int device, struct snd_rawmidi **rrawmidi)
++int snd_cs46xx_midi(struct snd_cs46xx *chip, int device, struct snd_rawmidi **rrawmidi)
+ {
+ 	struct snd_rawmidi *rmidi;
+ 	int err;
+@@ -2613,7 +2616,7 @@ static int snd_cs46xx_gameport_open(struct gameport *gameport, int mode)
+ 	return 0;
+ }
+ 
+-int __devinit snd_cs46xx_gameport(struct snd_cs46xx *chip)
++int snd_cs46xx_gameport(struct snd_cs46xx *chip)
+ {
+ 	struct gameport *gp;
+ 
+@@ -2649,7 +2652,7 @@ static inline void snd_cs46xx_remove_gameport(struct snd_cs46xx *chip)
+ 	}
+ }
+ #else
+-int __devinit snd_cs46xx_gameport(struct snd_cs46xx *chip) { return -ENOSYS; }
++int snd_cs46xx_gameport(struct snd_cs46xx *chip) { return -ENOSYS; }
+ static inline void snd_cs46xx_remove_gameport(struct snd_cs46xx *chip) { }
+ #endif /* CONFIG_GAMEPORT */
+ 
+@@ -2674,7 +2677,7 @@ static struct snd_info_entry_ops snd_cs46xx_proc_io_ops = {
+ 	.read = snd_cs46xx_io_read,
+ };
+ 
+-static int __devinit snd_cs46xx_proc_init(struct snd_card *card, struct snd_cs46xx *chip)
++static int snd_cs46xx_proc_init(struct snd_card *card, struct snd_cs46xx *chip)
+ {
+ 	struct snd_info_entry *entry;
+ 	int idx;
+@@ -3061,7 +3064,7 @@ static void cs46xx_enable_stream_irqs(struct snd_cs46xx *chip)
+ 	snd_cs46xx_poke(chip, BA1_CIE, tmp);	/* capture interrupt enable */
+ }
+ 
+-int __devinit snd_cs46xx_start_dsp(struct snd_cs46xx *chip)
++int snd_cs46xx_start_dsp(struct snd_cs46xx *chip)
+ {	
+ 	unsigned int tmp;
+ 	/*
+@@ -3477,7 +3480,7 @@ struct cs_card_type
+ 	void (*mixer_init)(struct snd_cs46xx *);
+ };
+ 
+-static struct cs_card_type __devinitdata cards[] = {
++static struct cs_card_type cards[] = {
+ 	{
+ 		.vendor = 0x1489,
+ 		.id = 0x7001,
+@@ -3717,10 +3720,10 @@ SIMPLE_DEV_PM_OPS(snd_cs46xx_pm, snd_cs46xx_suspend, snd_cs46xx_resume);
+ /*
+  */
+ 
+-int __devinit snd_cs46xx_create(struct snd_card *card,
+-		      struct pci_dev * pci,
++int snd_cs46xx_create(struct snd_card *card,
++		      struct pci_dev *pci,
+ 		      int external_amp, int thinkpad,
+-		      struct snd_cs46xx ** rchip)
++		      struct snd_cs46xx **rchip)
+ {
+ 	struct snd_cs46xx *chip;
+ 	int err, idx;
+diff --git a/sound/pci/cs5530.c b/sound/pci/cs5530.c
+index d1cca2831575..dace827b45d1 100644
+--- a/sound/pci/cs5530.c
++++ b/sound/pci/cs5530.c
+@@ -88,13 +88,13 @@ static int snd_cs5530_dev_free(struct snd_device *device)
+ 	return snd_cs5530_free(chip);
+ }
+ 
+-static void __devexit snd_cs5530_remove(struct pci_dev *pci)
++static void snd_cs5530_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+ }
+ 
+-static u8 __devinit snd_cs5530_mixer_read(unsigned long io, u8 reg)
++static u8 snd_cs5530_mixer_read(unsigned long io, u8 reg)
+ {
+ 	outb(reg, io + 4);
+ 	udelay(20);
+@@ -103,9 +103,9 @@ static u8 __devinit snd_cs5530_mixer_read(unsigned long io, u8 reg)
+ 	return reg;
+ }
+ 
+-static int __devinit snd_cs5530_create(struct snd_card *card,
+-				       struct pci_dev *pci,
+-				       struct snd_cs5530 **rchip)
++static int snd_cs5530_create(struct snd_card *card,
++			     struct pci_dev *pci,
++			     struct snd_cs5530 **rchip)
+ {
+ 	struct snd_cs5530 *chip;
+ 	unsigned long sb_base;
+@@ -250,8 +250,8 @@ static int __devinit snd_cs5530_create(struct snd_card *card,
+ 	return 0;
+ }
+ 
+-static int __devinit snd_cs5530_probe(struct pci_dev *pci,
+-					const struct pci_device_id *pci_id)
++static int snd_cs5530_probe(struct pci_dev *pci,
++			    const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -294,7 +294,7 @@ static struct pci_driver cs5530_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_cs5530_ids,
+ 	.probe = snd_cs5530_probe,
+-	.remove = __devexit_p(snd_cs5530_remove),
++	.remove = snd_cs5530_remove,
+ };
+ 
+ module_pci_driver(cs5530_driver);
+diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c
+index 4915efa551fc..7e4b13e2d12a 100644
+--- a/sound/pci/cs5535audio/cs5535audio.c
++++ b/sound/pci/cs5535audio/cs5535audio.c
+@@ -43,7 +43,7 @@ static char *ac97_quirk;
+ module_param(ac97_quirk, charp, 0444);
+ MODULE_PARM_DESC(ac97_quirk, "AC'97 board specific workarounds.");
+ 
+-static struct ac97_quirk ac97_quirks[] __devinitdata = {
++static struct ac97_quirk ac97_quirks[] = {
+ #if 0 /* Not yet confirmed if all 5536 boards are HP only */
+ 	{
+ 		.subvendor = PCI_VENDOR_ID_AMD, 
+@@ -144,7 +144,7 @@ static unsigned short snd_cs5535audio_ac97_codec_read(struct snd_ac97 *ac97,
+ 	return snd_cs5535audio_codec_read(cs5535au, reg);
+ }
+ 
+-static int __devinit snd_cs5535audio_mixer(struct cs5535audio *cs5535au)
++static int snd_cs5535audio_mixer(struct cs5535audio *cs5535au)
+ {
+ 	struct snd_card *card = cs5535au->card;
+ 	struct snd_ac97_bus *pbus;
+@@ -270,9 +270,9 @@ static int snd_cs5535audio_dev_free(struct snd_device *device)
+ 	return snd_cs5535audio_free(cs5535au);
+ }
+ 
+-static int __devinit snd_cs5535audio_create(struct snd_card *card,
+-					    struct pci_dev *pci,
+-					    struct cs5535audio **rcs5535au)
++static int snd_cs5535audio_create(struct snd_card *card,
++				  struct pci_dev *pci,
++				  struct cs5535audio **rcs5535au)
+ {
+ 	struct cs5535audio *cs5535au;
+ 
+@@ -338,8 +338,8 @@ static int __devinit snd_cs5535audio_create(struct snd_card *card,
+ 	return err;
+ }
+ 
+-static int __devinit snd_cs5535audio_probe(struct pci_dev *pci,
+-					   const struct pci_device_id *pci_id)
++static int snd_cs5535audio_probe(struct pci_dev *pci,
++				 const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -387,7 +387,7 @@ static int __devinit snd_cs5535audio_probe(struct pci_dev *pci,
+ 	return err;
+ }
+ 
+-static void __devexit snd_cs5535audio_remove(struct pci_dev *pci)
++static void snd_cs5535audio_remove(struct pci_dev *pci)
+ {
+ 	olpc_quirks_cleanup();
+ 	snd_card_free(pci_get_drvdata(pci));
+@@ -398,7 +398,7 @@ static struct pci_driver cs5535audio_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_cs5535audio_ids,
+ 	.probe = snd_cs5535audio_probe,
+-	.remove = __devexit_p(snd_cs5535audio_remove),
++	.remove = snd_cs5535audio_remove,
+ #ifdef CONFIG_PM_SLEEP
+ 	.driver = {
+ 		.pm = &snd_cs5535audio_pm,
+diff --git a/sound/pci/cs5535audio/cs5535audio.h b/sound/pci/cs5535audio/cs5535audio.h
+index bb3cc641130c..0579daa62215 100644
+--- a/sound/pci/cs5535audio/cs5535audio.h
++++ b/sound/pci/cs5535audio/cs5535audio.h
+@@ -97,10 +97,10 @@ struct cs5535audio {
+ extern const struct dev_pm_ops snd_cs5535audio_pm;
+ 
+ #ifdef CONFIG_OLPC
+-void __devinit olpc_prequirks(struct snd_card *card,
+-		struct snd_ac97_template *ac97);
+-int __devinit olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97);
+-void __devexit olpc_quirks_cleanup(void);
++void olpc_prequirks(struct snd_card *card,
++		    struct snd_ac97_template *ac97);
++int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97);
++void olpc_quirks_cleanup(void);
+ void olpc_analog_input(struct snd_ac97 *ac97, int on);
+ void olpc_mic_bias(struct snd_ac97 *ac97, int on);
+ 
+@@ -133,7 +133,7 @@ static inline void olpc_capture_open(struct snd_ac97 *ac97) { }
+ static inline void olpc_capture_close(struct snd_ac97 *ac97) { }
+ #endif
+ 
+-int __devinit snd_cs5535audio_pcm(struct cs5535audio *cs5535audio);
++int snd_cs5535audio_pcm(struct cs5535audio *cs5535audio);
+ 
+ #endif /* __SOUND_CS5535AUDIO_H */
+ 
+diff --git a/sound/pci/cs5535audio/cs5535audio_olpc.c b/sound/pci/cs5535audio/cs5535audio_olpc.c
+index 50da49be9ae5..da1cb9c4c76c 100644
+--- a/sound/pci/cs5535audio/cs5535audio_olpc.c
++++ b/sound/pci/cs5535audio/cs5535audio_olpc.c
+@@ -114,7 +114,7 @@ static int olpc_mic_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *v)
+ 	return 1;
+ }
+ 
+-static struct snd_kcontrol_new olpc_cs5535audio_ctls[] __devinitdata = {
++static struct snd_kcontrol_new olpc_cs5535audio_ctls[] = {
+ {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "DC Mode Enable",
+@@ -133,8 +133,8 @@ static struct snd_kcontrol_new olpc_cs5535audio_ctls[] __devinitdata = {
+ },
+ };
+ 
+-void __devinit olpc_prequirks(struct snd_card *card,
+-		struct snd_ac97_template *ac97)
++void olpc_prequirks(struct snd_card *card,
++		    struct snd_ac97_template *ac97)
+ {
+ 	if (!machine_is_olpc())
+ 		return;
+@@ -144,7 +144,7 @@ void __devinit olpc_prequirks(struct snd_card *card,
+ 		ac97->scaps |= AC97_SCAP_INV_EAPD;
+ }
+ 
+-int __devinit olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97)
++int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97)
+ {
+ 	struct snd_ctl_elem_id elem;
+ 	int i, err;
+@@ -185,7 +185,7 @@ int __devinit olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97)
+ 	return 0;
+ }
+ 
+-void __devexit olpc_quirks_cleanup(void)
++void olpc_quirks_cleanup(void)
+ {
+ 	gpio_free(OLPC_GPIO_MIC_AC);
+ }
+diff --git a/sound/pci/cs5535audio/cs5535audio_pcm.c b/sound/pci/cs5535audio/cs5535audio_pcm.c
+index dbf94b189e75..9ab01a7047cf 100644
+--- a/sound/pci/cs5535audio/cs5535audio_pcm.c
++++ b/sound/pci/cs5535audio/cs5535audio_pcm.c
+@@ -422,7 +422,7 @@ static struct cs5535audio_dma_ops snd_cs5535audio_capture_dma_ops = {
+         .read_dma_pntr = cs5535audio_capture_read_dma_pntr,
+ };
+ 
+-int __devinit snd_cs5535audio_pcm(struct cs5535audio *cs5535au)
++int snd_cs5535audio_pcm(struct cs5535audio *cs5535au)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c
+index a2f997a9977a..b5fa583a239a 100644
+--- a/sound/pci/ctxfi/ctatc.c
++++ b/sound/pci/ctxfi/ctatc.c
+@@ -38,7 +38,7 @@
+ 			    | (0x10 << 16) \
+ 			    | ((IEC958_AES3_CON_FS_48000) << 24))
+ 
+-static struct snd_pci_quirk __devinitdata subsys_20k1_list[] = {
++static struct snd_pci_quirk subsys_20k1_list[] = {
+ 	SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0022, "SB055x", CTSB055X),
+ 	SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x002f, "SB055x", CTSB055X),
+ 	SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0029, "SB073x", CTSB073X),
+@@ -48,7 +48,7 @@ static struct snd_pci_quirk __devinitdata subsys_20k1_list[] = {
+ 	{ } /* terminator */
+ };
+ 
+-static struct snd_pci_quirk __devinitdata subsys_20k2_list[] = {
++static struct snd_pci_quirk subsys_20k2_list[] = {
+ 	SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB0760,
+ 		      "SB0760", CTSB0760),
+ 	SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB1270,
+@@ -1249,7 +1249,7 @@ static int atc_dev_free(struct snd_device *dev)
+ 	return ct_atc_destroy(atc);
+ }
+ 
+-static int __devinit atc_identify_card(struct ct_atc *atc, unsigned int ssid)
++static int atc_identify_card(struct ct_atc *atc, unsigned int ssid)
+ {
+ 	const struct snd_pci_quirk *p;
+ 	const struct snd_pci_quirk *list;
+@@ -1296,7 +1296,7 @@ static int __devinit atc_identify_card(struct ct_atc *atc, unsigned int ssid)
+ 	return 0;
+ }
+ 
+-int __devinit ct_atc_create_alsa_devs(struct ct_atc *atc)
++int ct_atc_create_alsa_devs(struct ct_atc *atc)
+ {
+ 	enum CTALSADEVS i;
+ 	int err;
+@@ -1319,7 +1319,7 @@ int __devinit ct_atc_create_alsa_devs(struct ct_atc *atc)
+ 	return 0;
+ }
+ 
+-static int __devinit atc_create_hw_devs(struct ct_atc *atc)
++static int atc_create_hw_devs(struct ct_atc *atc)
+ {
+ 	struct hw *hw;
+ 	struct card_conf info = {0};
+@@ -1614,7 +1614,7 @@ static int atc_resume(struct ct_atc *atc)
+ }
+ #endif
+ 
+-static struct ct_atc atc_preset __devinitdata = {
++static struct ct_atc atc_preset = {
+ 	.map_audio_buffer = ct_map_audio_buffer,
+ 	.unmap_audio_buffer = ct_unmap_audio_buffer,
+ 	.pcm_playback_prepare = atc_pcm_playback_prepare,
+@@ -1665,10 +1665,10 @@ static struct ct_atc atc_preset __devinitdata = {
+  *  Returns 0 if succeeds, or negative error code if fails.
+  */
+ 
+-int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci,
+-			    unsigned int rsr, unsigned int msr,
+-			    int chip_type, unsigned int ssid,
+-			    struct ct_atc **ratc)
++int ct_atc_create(struct snd_card *card, struct pci_dev *pci,
++		  unsigned int rsr, unsigned int msr,
++		  int chip_type, unsigned int ssid,
++		  struct ct_atc **ratc)
+ {
+ 	struct ct_atc *atc;
+ 	static struct snd_device_ops ops = {
+diff --git a/sound/pci/ctxfi/ctatc.h b/sound/pci/ctxfi/ctatc.h
+index 69b51f9d345e..5f11ca22fcde 100644
+--- a/sound/pci/ctxfi/ctatc.h
++++ b/sound/pci/ctxfi/ctatc.h
+@@ -152,9 +152,9 @@ struct ct_atc {
+ };
+ 
+ 
+-int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci,
+-			    unsigned int rsr, unsigned int msr, int chip_type,
+-			    unsigned int subsysid, struct ct_atc **ratc);
+-int __devinit ct_atc_create_alsa_devs(struct ct_atc *atc);
++int ct_atc_create(struct snd_card *card, struct pci_dev *pci,
++		  unsigned int rsr, unsigned int msr, int chip_type,
++		  unsigned int subsysid, struct ct_atc **ratc);
++int ct_atc_create_alsa_devs(struct ct_atc *atc);
+ 
+ #endif /* CTATC_H */
+diff --git a/sound/pci/ctxfi/cthardware.c b/sound/pci/ctxfi/cthardware.c
+index 8e64f4862e85..110b8ace6d8a 100644
+--- a/sound/pci/ctxfi/cthardware.c
++++ b/sound/pci/ctxfi/cthardware.c
+@@ -20,8 +20,8 @@
+ #include "cthw20k2.h"
+ #include 
+ 
+-int __devinit create_hw_obj(struct pci_dev *pci, enum CHIPTYP chip_type,
+-			    enum CTCARDS model, struct hw **rhw)
++int create_hw_obj(struct pci_dev *pci, enum CHIPTYP chip_type,
++		  enum CTCARDS model, struct hw **rhw)
+ {
+ 	int err;
+ 
+diff --git a/sound/pci/ctxfi/cthw20k1.c b/sound/pci/ctxfi/cthw20k1.c
+index 4507f7088b24..6ac40beb49da 100644
+--- a/sound/pci/ctxfi/cthw20k1.c
++++ b/sound/pci/ctxfi/cthw20k1.c
+@@ -2171,7 +2171,7 @@ static void hw_write_pci(struct hw *hw, u32 reg, u32 data)
+ 		&container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags);
+ }
+ 
+-static struct hw ct20k1_preset __devinitdata = {
++static struct hw ct20k1_preset = {
+ 	.irq = -1,
+ 
+ 	.card_init = hw_card_init,
+@@ -2275,7 +2275,7 @@ static struct hw ct20k1_preset __devinitdata = {
+ 	.get_wc = get_wc,
+ };
+ 
+-int __devinit create_20k1_hw_obj(struct hw **rhw)
++int create_20k1_hw_obj(struct hw **rhw)
+ {
+ 	struct hw20k1 *hw20k1;
+ 
+diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c
+index b9c9349058bc..b1438861d38a 100644
+--- a/sound/pci/ctxfi/cthw20k2.c
++++ b/sound/pci/ctxfi/cthw20k2.c
+@@ -2237,7 +2237,7 @@ static void hw_write_20kx(struct hw *hw, u32 reg, u32 data)
+ 	writel(data, (void *)(hw->mem_base + reg));
+ }
+ 
+-static struct hw ct20k2_preset __devinitdata = {
++static struct hw ct20k2_preset = {
+ 	.irq = -1,
+ 
+ 	.card_init = hw_card_init,
+@@ -2345,7 +2345,7 @@ static struct hw ct20k2_preset __devinitdata = {
+ 	.get_wc = get_wc,
+ };
+ 
+-int __devinit create_20k2_hw_obj(struct hw **rhw)
++int create_20k2_hw_obj(struct hw **rhw)
+ {
+ 	struct hw20k2 *hw20k2;
+ 
+diff --git a/sound/pci/ctxfi/xfi.c b/sound/pci/ctxfi/xfi.c
+index 07c07d752fd8..d01ffcb2b2f5 100644
+--- a/sound/pci/ctxfi/xfi.c
++++ b/sound/pci/ctxfi/xfi.c
+@@ -56,7 +56,7 @@ static DEFINE_PCI_DEVICE_TABLE(ct_pci_dev_ids) = {
+ };
+ MODULE_DEVICE_TABLE(pci, ct_pci_dev_ids);
+ 
+-static int __devinit
++static int
+ ct_card_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+@@ -119,7 +119,7 @@ ct_card_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+ 	return err;
+ }
+ 
+-static void __devexit ct_card_remove(struct pci_dev *pci)
++static void ct_card_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -152,7 +152,7 @@ static struct pci_driver ct_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = ct_pci_dev_ids,
+ 	.probe = ct_card_probe,
+-	.remove = __devexit_p(ct_card_remove),
++	.remove = ct_card_remove,
+ 	.driver = {
+ 		.pm = CT_CARD_PM_OPS,
+ 	},
+diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
+index abb0b86c41c9..760cbff53210 100644
+--- a/sound/pci/echoaudio/echoaudio.c
++++ b/sound/pci/echoaudio/echoaudio.c
+@@ -907,7 +907,7 @@ static int snd_echo_preallocate_pages(struct snd_pcm *pcm, struct device *dev)
+ 
+ 
+ /*<--snd_echo_probe() */
+-static int __devinit snd_echo_new_pcm(struct echoaudio *chip)
++static int snd_echo_new_pcm(struct echoaudio *chip)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -1050,7 +1050,7 @@ static int snd_echo_output_gain_put(struct snd_kcontrol *kcontrol,
+ 
+ #ifdef ECHOCARD_HAS_LINE_OUT_GAIN
+ /* On the Mia this one controls the line-out volume */
+-static struct snd_kcontrol_new snd_echo_line_output_gain __devinitdata = {
++static struct snd_kcontrol_new snd_echo_line_output_gain = {
+ 	.name = "Line Playback Volume",
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+@@ -1061,7 +1061,7 @@ static struct snd_kcontrol_new snd_echo_line_output_gain __devinitdata = {
+ 	.tlv = {.p = db_scale_output_gain},
+ };
+ #else
+-static struct snd_kcontrol_new snd_echo_pcm_output_gain __devinitdata = {
++static struct snd_kcontrol_new snd_echo_pcm_output_gain = {
+ 	.name = "PCM Playback Volume",
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+@@ -1131,7 +1131,7 @@ static int snd_echo_input_gain_put(struct snd_kcontrol *kcontrol,
+ 
+ static const DECLARE_TLV_DB_SCALE(db_scale_input_gain, -2500, 50, 0);
+ 
+-static struct snd_kcontrol_new snd_echo_line_input_gain __devinitdata = {
++static struct snd_kcontrol_new snd_echo_line_input_gain = {
+ 	.name = "Line Capture Volume",
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+@@ -1195,7 +1195,7 @@ static int snd_echo_output_nominal_put(struct snd_kcontrol *kcontrol,
+ 	return changed;
+ }
+ 
+-static struct snd_kcontrol_new snd_echo_output_nominal_level __devinitdata = {
++static struct snd_kcontrol_new snd_echo_output_nominal_level = {
+ 	.name = "Line Playback Switch (-10dBV)",
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.info = snd_echo_output_nominal_info,
+@@ -1261,7 +1261,7 @@ static int snd_echo_input_nominal_put(struct snd_kcontrol *kcontrol,
+ 	return changed;
+ }
+ 
+-static struct snd_kcontrol_new snd_echo_intput_nominal_level __devinitdata = {
++static struct snd_kcontrol_new snd_echo_intput_nominal_level = {
+ 	.name = "Line Capture Switch (-10dBV)",
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.info = snd_echo_input_nominal_info,
+@@ -1327,7 +1327,7 @@ static int snd_echo_mixer_put(struct snd_kcontrol *kcontrol,
+ 	return changed;
+ }
+ 
+-static struct snd_kcontrol_new snd_echo_monitor_mixer __devinitdata = {
++static struct snd_kcontrol_new snd_echo_monitor_mixer = {
+ 	.name = "Monitor Mixer Volume",
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+@@ -1395,7 +1395,7 @@ static int snd_echo_vmixer_put(struct snd_kcontrol *kcontrol,
+ 	return changed;
+ }
+ 
+-static struct snd_kcontrol_new snd_echo_vmixer __devinitdata = {
++static struct snd_kcontrol_new snd_echo_vmixer = {
+ 	.name = "VMixer Volume",
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+@@ -1490,7 +1490,7 @@ static int snd_echo_digital_mode_put(struct snd_kcontrol *kcontrol,
+ 	return changed;
+ }
+ 
+-static struct snd_kcontrol_new snd_echo_digital_mode_switch __devinitdata = {
++static struct snd_kcontrol_new snd_echo_digital_mode_switch = {
+ 	.name = "Digital mode Switch",
+ 	.iface = SNDRV_CTL_ELEM_IFACE_CARD,
+ 	.info = snd_echo_digital_mode_info,
+@@ -1547,7 +1547,7 @@ static int snd_echo_spdif_mode_put(struct snd_kcontrol *kcontrol,
+ 	return 0;
+ }
+ 
+-static struct snd_kcontrol_new snd_echo_spdif_mode_switch __devinitdata = {
++static struct snd_kcontrol_new snd_echo_spdif_mode_switch = {
+ 	.name = "S/PDIF mode Switch",
+ 	.iface = SNDRV_CTL_ELEM_IFACE_CARD,
+ 	.info = snd_echo_spdif_mode_info,
+@@ -1626,7 +1626,7 @@ static int snd_echo_clock_source_put(struct snd_kcontrol *kcontrol,
+ 	return changed;
+ }
+ 
+-static struct snd_kcontrol_new snd_echo_clock_source_switch __devinitdata = {
++static struct snd_kcontrol_new snd_echo_clock_source_switch = {
+ 	.name = "Sample Clock Source",
+ 	.iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ 	.info = snd_echo_clock_source_info,
+@@ -1669,7 +1669,7 @@ static int snd_echo_phantom_power_put(struct snd_kcontrol *kcontrol,
+ 	return changed;
+ }
+ 
+-static struct snd_kcontrol_new snd_echo_phantom_power_switch __devinitdata = {
++static struct snd_kcontrol_new snd_echo_phantom_power_switch = {
+ 	.name = "Phantom power Switch",
+ 	.iface = SNDRV_CTL_ELEM_IFACE_CARD,
+ 	.info = snd_echo_phantom_power_info,
+@@ -1712,7 +1712,7 @@ static int snd_echo_automute_put(struct snd_kcontrol *kcontrol,
+ 	return changed;
+ }
+ 
+-static struct snd_kcontrol_new snd_echo_automute_switch __devinitdata = {
++static struct snd_kcontrol_new snd_echo_automute_switch = {
+ 	.name = "Digital Capture Switch (automute)",
+ 	.iface = SNDRV_CTL_ELEM_IFACE_CARD,
+ 	.info = snd_echo_automute_info,
+@@ -1739,7 +1739,7 @@ static int snd_echo_vumeters_switch_put(struct snd_kcontrol *kcontrol,
+ 	return 1;
+ }
+ 
+-static struct snd_kcontrol_new snd_echo_vumeters_switch __devinitdata = {
++static struct snd_kcontrol_new snd_echo_vumeters_switch = {
+ 	.name = "VU-meters Switch",
+ 	.iface = SNDRV_CTL_ELEM_IFACE_CARD,
+ 	.access = SNDRV_CTL_ELEM_ACCESS_WRITE,
+@@ -1780,7 +1780,7 @@ static int snd_echo_vumeters_get(struct snd_kcontrol *kcontrol,
+ 	return 0;
+ }
+ 
+-static struct snd_kcontrol_new snd_echo_vumeters __devinitdata = {
++static struct snd_kcontrol_new snd_echo_vumeters = {
+ 	.name = "VU-meters",
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.access = SNDRV_CTL_ELEM_ACCESS_READ |
+@@ -1836,7 +1836,7 @@ static int snd_echo_channels_info_get(struct snd_kcontrol *kcontrol,
+ 	return 0;
+ }
+ 
+-static struct snd_kcontrol_new snd_echo_channels_info __devinitdata = {
++static struct snd_kcontrol_new snd_echo_channels_info = {
+ 	.name = "Channels info",
+ 	.iface = SNDRV_CTL_ELEM_IFACE_HWDEP,
+ 	.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+@@ -1940,9 +1940,9 @@ static int snd_echo_dev_free(struct snd_device *device)
+ 
+ 
+ /* <--snd_echo_probe() */
+-static __devinit int snd_echo_create(struct snd_card *card,
+-				     struct pci_dev *pci,
+-				     struct echoaudio **rchip)
++static int snd_echo_create(struct snd_card *card,
++			   struct pci_dev *pci,
++			   struct echoaudio **rchip)
+ {
+ 	struct echoaudio *chip;
+ 	int err;
+@@ -2040,8 +2040,8 @@ static __devinit int snd_echo_create(struct snd_card *card,
+ 
+ 
+ /* constructor */
+-static int __devinit snd_echo_probe(struct pci_dev *pci,
+-				    const struct pci_device_id *pci_id)
++static int snd_echo_probe(struct pci_dev *pci,
++			  const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -2316,7 +2316,7 @@ static SIMPLE_DEV_PM_OPS(snd_echo_pm, snd_echo_suspend, snd_echo_resume);
+ #endif /* CONFIG_PM_SLEEP */
+ 
+ 
+-static void __devexit snd_echo_remove(struct pci_dev *pci)
++static void snd_echo_remove(struct pci_dev *pci)
+ {
+ 	struct echoaudio *chip;
+ 
+@@ -2337,7 +2337,7 @@ static struct pci_driver echo_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_echo_ids,
+ 	.probe = snd_echo_probe,
+-	.remove = __devexit_p(snd_echo_remove),
++	.remove = snd_echo_remove,
+ 	.driver = {
+ 		.pm = SND_ECHO_PM_OPS,
+ 	},
+diff --git a/sound/pci/echoaudio/echoaudio.h b/sound/pci/echoaudio/echoaudio.h
+index e158369f5faa..b86b88da81cd 100644
+--- a/sound/pci/echoaudio/echoaudio.h
++++ b/sound/pci/echoaudio/echoaudio.h
+@@ -475,8 +475,8 @@ static int enable_midi_input(struct echoaudio *chip, char enable);
+ static void snd_echo_midi_output_trigger(
+ 			struct snd_rawmidi_substream *substream, int up);
+ static int midi_service_irq(struct echoaudio *chip);
+-static int __devinit snd_echo_midi_create(struct snd_card *card,
+-					  struct echoaudio *chip);
++static int snd_echo_midi_create(struct snd_card *card,
++				struct echoaudio *chip);
+ #endif
+ 
+ 
+diff --git a/sound/pci/echoaudio/midi.c b/sound/pci/echoaudio/midi.c
+index a953d142cb4b..abfd51c2530e 100644
+--- a/sound/pci/echoaudio/midi.c
++++ b/sound/pci/echoaudio/midi.c
+@@ -307,8 +307,8 @@ static struct snd_rawmidi_ops snd_echo_midi_output = {
+ 
+ 
+ /* <--snd_echo_probe() */
+-static int __devinit snd_echo_midi_create(struct snd_card *card,
+-					  struct echoaudio *chip)
++static int snd_echo_midi_create(struct snd_card *card,
++				struct echoaudio *chip)
+ {
+ 	int err;
+ 
+diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
+index a168138efc5e..8c5010f7889c 100644
+--- a/sound/pci/emu10k1/emu10k1.c
++++ b/sound/pci/emu10k1/emu10k1.c
+@@ -99,8 +99,8 @@ static DEFINE_PCI_DEVICE_TABLE(snd_emu10k1_ids) = {
+ 
+ MODULE_DEVICE_TABLE(pci, snd_emu10k1_ids);
+ 
+-static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci,
+-					    const struct pci_device_id *pci_id)
++static int snd_card_emu10k1_probe(struct pci_dev *pci,
++				  const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -199,7 +199,7 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci,
+ 	return err;
+ }
+ 
+-static void __devexit snd_card_emu10k1_remove(struct pci_dev *pci)
++static void snd_card_emu10k1_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -278,7 +278,7 @@ static struct pci_driver emu10k1_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_emu10k1_ids,
+ 	.probe = snd_card_emu10k1_probe,
+-	.remove = __devexit_p(snd_card_emu10k1_remove),
++	.remove = snd_card_emu10k1_remove,
+ 	.driver = {
+ 		.pm = SND_EMU10K1_PM_OPS,
+ 	},
+diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
+index 527ef216d4ca..a7c296a36a17 100644
+--- a/sound/pci/emu10k1/emu10k1_main.c
++++ b/sound/pci/emu10k1/emu10k1_main.c
+@@ -1726,7 +1726,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
+ 	{ } /* terminator */
+ };
+ 
+-int __devinit snd_emu10k1_create(struct snd_card *card,
++int snd_emu10k1_create(struct snd_card *card,
+ 		       struct pci_dev *pci,
+ 		       unsigned short extin_mask,
+ 		       unsigned short extout_mask,
+@@ -2013,7 +2013,7 @@ static unsigned char saved_regs_audigy[] = {
+ 	0xff /* end */
+ };
+ 
+-static int __devinit alloc_pm_buffer(struct snd_emu10k1 *emu)
++static int alloc_pm_buffer(struct snd_emu10k1 *emu)
+ {
+ 	int size;
+ 
+diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
+index 556fd6f456e3..cdff11d48ebd 100644
+--- a/sound/pci/emu10k1/emu10k1x.c
++++ b/sound/pci/emu10k1/emu10k1x.c
+@@ -842,7 +842,7 @@ static const struct snd_pcm_chmap_elem clfe_map[] = {
+ 	{ }
+ };
+ 
+-static int __devinit snd_emu10k1x_pcm(struct emu10k1x *emu, int device, struct snd_pcm **rpcm)
++static int snd_emu10k1x_pcm(struct emu10k1x *emu, int device, struct snd_pcm **rpcm)
+ {
+ 	struct snd_pcm *pcm;
+ 	const struct snd_pcm_chmap_elem *map = NULL;
+@@ -902,9 +902,9 @@ static int __devinit snd_emu10k1x_pcm(struct emu10k1x *emu, int device, struct s
+ 	return 0;
+ }
+ 
+-static int __devinit snd_emu10k1x_create(struct snd_card *card,
+-					 struct pci_dev *pci,
+-					 struct emu10k1x **rchip)
++static int snd_emu10k1x_create(struct snd_card *card,
++			       struct pci_dev *pci,
++			       struct emu10k1x **rchip)
+ {
+ 	struct emu10k1x *chip;
+ 	int err;
+@@ -1066,7 +1066,7 @@ static void snd_emu10k1x_proc_reg_write(struct snd_info_entry *entry,
+ 	}
+ }
+ 
+-static int __devinit snd_emu10k1x_proc_init(struct emu10k1x * emu)
++static int snd_emu10k1x_proc_init(struct emu10k1x *emu)
+ {
+ 	struct snd_info_entry *entry;
+ 	
+@@ -1115,7 +1115,7 @@ static int snd_emu10k1x_shared_spdif_put(struct snd_kcontrol *kcontrol,
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_emu10k1x_shared_spdif __devinitdata =
++static struct snd_kcontrol_new snd_emu10k1x_shared_spdif =
+ {
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name =		"Analog/Digital Output Jack",
+@@ -1194,7 +1194,7 @@ static struct snd_kcontrol_new snd_emu10k1x_spdif_control =
+ 	.put =          snd_emu10k1x_spdif_put
+ };
+ 
+-static int __devinit snd_emu10k1x_mixer(struct emu10k1x *emu)
++static int snd_emu10k1x_mixer(struct emu10k1x *emu)
+ {
+ 	int err;
+ 	struct snd_kcontrol *kctl;
+@@ -1507,8 +1507,9 @@ static void snd_emu10k1x_midi_free(struct snd_rawmidi *rmidi)
+ 	midi->rmidi = NULL;
+ }
+ 
+-static int __devinit emu10k1x_midi_init(struct emu10k1x *emu,
+-					struct emu10k1x_midi *midi, int device, char *name)
++static int emu10k1x_midi_init(struct emu10k1x *emu,
++			      struct emu10k1x_midi *midi, int device,
++			      char *name)
+ {
+ 	struct snd_rawmidi *rmidi;
+ 	int err;
+@@ -1531,7 +1532,7 @@ static int __devinit emu10k1x_midi_init(struct emu10k1x *emu,
+ 	return 0;
+ }
+ 
+-static int __devinit snd_emu10k1x_midi(struct emu10k1x *emu)
++static int snd_emu10k1x_midi(struct emu10k1x *emu)
+ {
+ 	struct emu10k1x_midi *midi = &emu->midi;
+ 	int err;
+@@ -1548,8 +1549,8 @@ static int __devinit snd_emu10k1x_midi(struct emu10k1x *emu)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_emu10k1x_probe(struct pci_dev *pci,
+-					const struct pci_device_id *pci_id)
++static int snd_emu10k1x_probe(struct pci_dev *pci,
++			      const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -1619,7 +1620,7 @@ static int __devinit snd_emu10k1x_probe(struct pci_dev *pci,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_emu10k1x_remove(struct pci_dev *pci)
++static void snd_emu10k1x_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -1637,7 +1638,7 @@ static struct pci_driver emu10k1x_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_emu10k1x_ids,
+ 	.probe = snd_emu10k1x_probe,
+-	.remove = __devexit_p(snd_emu10k1x_remove),
++	.remove = snd_emu10k1x_remove,
+ };
+ 
+ module_pci_driver(emu10k1x_driver);
+diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
+index 52419959178c..0275209ca82e 100644
+--- a/sound/pci/emu10k1/emufx.c
++++ b/sound/pci/emu10k1/emufx.c
+@@ -1073,7 +1073,7 @@ static int snd_emu10k1_ipcm_peek(struct snd_emu10k1 *emu,
+ #define SND_EMU10K1_PLAYBACK_CHANNELS	8
+ #define SND_EMU10K1_CAPTURE_CHANNELS	4
+ 
+-static void __devinit
++static void
+ snd_emu10k1_init_mono_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
+ 			      const char *name, int gpr, int defval)
+ {
+@@ -1094,7 +1094,7 @@ snd_emu10k1_init_mono_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
+ 	}
+ }
+ 
+-static void __devinit
++static void
+ snd_emu10k1_init_stereo_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
+ 				const char *name, int gpr, int defval)
+ {
+@@ -1116,7 +1116,7 @@ snd_emu10k1_init_stereo_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
+ 	}
+ }
+ 
+-static void __devinit
++static void
+ snd_emu10k1_init_mono_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
+ 				    const char *name, int gpr, int defval)
+ {
+@@ -1129,7 +1129,7 @@ snd_emu10k1_init_mono_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
+ 	ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF;
+ }
+ 
+-static void __devinit
++static void
+ snd_emu10k1_init_stereo_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
+ 				      const char *name, int gpr, int defval)
+ {
+@@ -1168,7 +1168,7 @@ static int snd_emu10k1_audigy_dsp_convert_32_to_2x16(
+  * initial DSP configuration for Audigy
+  */
+ 
+-static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
++static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
+ {
+ 	int err, i, z, gpr, nctl;
+ 	int bit_shifter16;
+@@ -1757,14 +1757,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
+ 
+ /* when volume = max, then copy only to avoid volume modification */
+ /* with iMAC0 (negative values) */
+-static void __devinit _volume(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
++static void _volume(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
+ {
+ 	OP(icode, ptr, iMAC0, dst, C_00000000, src, vol);
+ 	OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff);
+ 	OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000001);
+ 	OP(icode, ptr, iACC3, dst, src, C_00000000, C_00000000);
+ }
+-static void __devinit _volume_add(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
++static void _volume_add(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
+ {
+ 	OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff);
+ 	OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002);
+@@ -1772,7 +1772,7 @@ static void __devinit _volume_add(struct snd_emu10k1_fx8010_code *icode, u32 *pt
+ 	OP(icode, ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000001);
+ 	OP(icode, ptr, iMAC0, dst, dst, src, vol);
+ }
+-static void __devinit _volume_out(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
++static void _volume_out(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
+ {
+ 	OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff);
+ 	OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002);
+@@ -1803,7 +1803,7 @@ static void __devinit _volume_out(struct snd_emu10k1_fx8010_code *icode, u32 *pt
+ 		_SWITCH_NEG(icode, ptr, GPR(dst), GPR(src))
+ 
+ 
+-static int __devinit _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
++static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
+ {
+ 	int err, i, z, gpr, tmp, playback, capture;
+ 	u32 ptr;
+@@ -2373,7 +2373,7 @@ static int __devinit _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
+ 	return err;
+ }
+ 
+-int __devinit snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
++int snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
+ {
+ 	spin_lock_init(&emu->fx8010.irq_lock);
+ 	INIT_LIST_HEAD(&emu->fx8010.gpr_ctl);
+@@ -2626,7 +2626,8 @@ static int snd_emu10k1_fx8010_release(struct snd_hwdep * hw, struct file *file)
+ 	return 0;
+ }
+ 
+-int __devinit snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device, struct snd_hwdep ** rhwdep)
++int snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device,
++			   struct snd_hwdep **rhwdep)
+ {
+ 	struct snd_hwdep *hw;
+ 	int err;
+@@ -2647,7 +2648,7 @@ int __devinit snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device, struct
+ }
+ 
+ #ifdef CONFIG_PM_SLEEP
+-int __devinit snd_emu10k1_efx_alloc_pm_buffer(struct snd_emu10k1 *emu)
++int snd_emu10k1_efx_alloc_pm_buffer(struct snd_emu10k1 *emu)
+ {
+ 	int len;
+ 
+diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c
+index 9d890a5aec5a..f6c3da0d377d 100644
+--- a/sound/pci/emu10k1/emumixer.c
++++ b/sound/pci/emu10k1/emumixer.c
+@@ -510,7 +510,7 @@ static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol,
+ 	.private_value = chid					\
+ }
+ 
+-static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] __devinitdata = {
++static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] = {
+ 	EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Enum", 0),
+ 	EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Enum", 1),
+ 	EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Enum", 2),
+@@ -539,7 +539,7 @@ static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] __devinitdata = {
+ 
+ 
+ /* 1616(m) cardbus */
+-static struct snd_kcontrol_new snd_emu1616_output_enum_ctls[] __devinitdata = {
++static struct snd_kcontrol_new snd_emu1616_output_enum_ctls[] = {
+ 	EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Enum", 0),
+ 	EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Enum", 1),
+ 	EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Enum", 2),
+@@ -571,7 +571,7 @@ static struct snd_kcontrol_new snd_emu1616_output_enum_ctls[] __devinitdata = {
+ 	.private_value = chid					\
+ }
+ 
+-static struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] __devinitdata = {
++static struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] = {
+ 	EMU1010_SOURCE_INPUT("DSP 0 Capture Enum", 0),
+ 	EMU1010_SOURCE_INPUT("DSP 1 Capture Enum", 1),
+ 	EMU1010_SOURCE_INPUT("DSP 2 Capture Enum", 2),
+@@ -639,7 +639,7 @@ static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ct
+ 	.private_value = chid					\
+ }
+ 
+-static struct snd_kcontrol_new snd_emu1010_adc_pads[] __devinitdata = {
++static struct snd_kcontrol_new snd_emu1010_adc_pads[] = {
+ 	EMU1010_ADC_PADS("ADC1 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD1),
+ 	EMU1010_ADC_PADS("ADC2 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD2),
+ 	EMU1010_ADC_PADS("ADC3 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD3),
+@@ -687,7 +687,7 @@ static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ct
+ 	.private_value = chid					\
+ }
+ 
+-static struct snd_kcontrol_new snd_emu1010_dac_pads[] __devinitdata = {
++static struct snd_kcontrol_new snd_emu1010_dac_pads[] = {
+ 	EMU1010_DAC_PADS("DAC1 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD1),
+ 	EMU1010_DAC_PADS("DAC2 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD2),
+ 	EMU1010_DAC_PADS("DAC3 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD3),
+@@ -989,7 +989,7 @@ static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol,
+ }
+ 
+ 
+-static struct snd_kcontrol_new snd_audigy_i2c_volume_ctls[] __devinitdata = {
++static struct snd_kcontrol_new snd_audigy_i2c_volume_ctls[] = {
+ 	I2C_VOLUME("Mic Capture Volume", 0),
+ 	I2C_VOLUME("Line Capture Volume", 0)
+ };
+@@ -1621,7 +1621,7 @@ static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol,
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_emu10k1_shared_spdif __devinitdata =
++static struct snd_kcontrol_new snd_emu10k1_shared_spdif =
+ {
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name =		"SB Live Analog/Digital Output Jack",
+@@ -1630,7 +1630,7 @@ static struct snd_kcontrol_new snd_emu10k1_shared_spdif __devinitdata =
+ 	.put =		snd_emu10k1_shared_spdif_put
+ };
+ 
+-static struct snd_kcontrol_new snd_audigy_shared_spdif __devinitdata =
++static struct snd_kcontrol_new snd_audigy_shared_spdif =
+ {
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name =		"Audigy Analog/Digital Output Jack",
+@@ -1668,7 +1668,7 @@ static int snd_audigy_capture_boost_put(struct snd_kcontrol *kcontrol,
+ 	return snd_ac97_update(emu->ac97, AC97_REC_GAIN, val);
+ }
+ 
+-static struct snd_kcontrol_new snd_audigy_capture_boost __devinitdata =
++static struct snd_kcontrol_new snd_audigy_capture_boost =
+ {
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name =		"Analog Capture Boost",
+@@ -1716,8 +1716,8 @@ static int rename_ctl(struct snd_card *card, const char *src, const char *dst)
+ 	return -ENOENT;
+ }
+ 
+-int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
+-				int pcm_device, int multi_device)
++int snd_emu10k1_mixer(struct snd_emu10k1 *emu,
++		      int pcm_device, int multi_device)
+ {
+ 	int err, pcm;
+ 	struct snd_kcontrol *kctl;
+diff --git a/sound/pci/emu10k1/emumpu401.c b/sound/pci/emu10k1/emumpu401.c
+index bab564824efe..1ec91246dfee 100644
+--- a/sound/pci/emu10k1/emumpu401.c
++++ b/sound/pci/emu10k1/emumpu401.c
+@@ -326,7 +326,7 @@ static void snd_emu10k1_midi_free(struct snd_rawmidi *rmidi)
+ 	midi->rmidi = NULL;
+ }
+ 
+-static int __devinit emu10k1_midi_init(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *midi, int device, char *name)
++static int emu10k1_midi_init(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *midi, int device, char *name)
+ {
+ 	struct snd_rawmidi *rmidi;
+ 	int err;
+@@ -349,7 +349,7 @@ static int __devinit emu10k1_midi_init(struct snd_emu10k1 *emu, struct snd_emu10
+ 	return 0;
+ }
+ 
+-int __devinit snd_emu10k1_midi(struct snd_emu10k1 *emu)
++int snd_emu10k1_midi(struct snd_emu10k1 *emu)
+ {
+ 	struct snd_emu10k1_midi *midi = &emu->midi;
+ 	int err;
+@@ -366,7 +366,7 @@ int __devinit snd_emu10k1_midi(struct snd_emu10k1 *emu)
+ 	return 0;
+ }
+ 
+-int __devinit snd_emu10k1_audigy_midi(struct snd_emu10k1 *emu)
++int snd_emu10k1_audigy_midi(struct snd_emu10k1 *emu)
+ {
+ 	struct snd_emu10k1_midi *midi;
+ 	int err;
+diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
+index 0e6664fa6cd9..748a286277eb 100644
+--- a/sound/pci/emu10k1/emupcm.c
++++ b/sound/pci/emu10k1/emupcm.c
+@@ -1391,7 +1391,7 @@ static struct snd_pcm_ops snd_emu10k1_efx_playback_ops = {
+ 	.page =			snd_pcm_sgbuf_ops_page,
+ };
+ 
+-int __devinit snd_emu10k1_pcm(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm)
++int snd_emu10k1_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm **rpcm)
+ {
+ 	struct snd_pcm *pcm;
+ 	struct snd_pcm_substream *substream;
+@@ -1426,7 +1426,8 @@ int __devinit snd_emu10k1_pcm(struct snd_emu10k1 * emu, int device, struct snd_p
+ 	return 0;
+ }
+ 
+-int __devinit snd_emu10k1_pcm_multi(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm)
++int snd_emu10k1_pcm_multi(struct snd_emu10k1 *emu, int device,
++			  struct snd_pcm **rpcm)
+ {
+ 	struct snd_pcm *pcm;
+ 	struct snd_pcm_substream *substream;
+@@ -1469,7 +1470,8 @@ static struct snd_pcm_ops snd_emu10k1_capture_mic_ops = {
+ 	.pointer =		snd_emu10k1_capture_pointer,
+ };
+ 
+-int __devinit snd_emu10k1_pcm_mic(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm)
++int snd_emu10k1_pcm_mic(struct snd_emu10k1 *emu, int device,
++			struct snd_pcm **rpcm)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -1810,7 +1812,8 @@ static struct snd_pcm_ops snd_emu10k1_fx8010_playback_ops = {
+ 	.ack =			snd_emu10k1_fx8010_playback_transfer,
+ };
+ 
+-int __devinit snd_emu10k1_pcm_efx(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm)
++int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device,
++			struct snd_pcm **rpcm)
+ {
+ 	struct snd_pcm *pcm;
+ 	struct snd_kcontrol *kctl;
+diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c
+index bc38dd4d071f..2ca9f2e93139 100644
+--- a/sound/pci/emu10k1/emuproc.c
++++ b/sound/pci/emu10k1/emuproc.c
+@@ -577,7 +577,7 @@ static struct snd_info_entry_ops snd_emu10k1_proc_ops_fx8010 = {
+ 	.read = snd_emu10k1_fx8010_read,
+ };
+ 
+-int __devinit snd_emu10k1_proc_init(struct snd_emu10k1 * emu)
++int snd_emu10k1_proc_init(struct snd_emu10k1 *emu)
+ {
+ 	struct snd_info_entry *entry;
+ #ifdef CONFIG_SND_DEBUG
+diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c
+index 88cec6b7dd41..7e2025cd6d9c 100644
+--- a/sound/pci/emu10k1/p16v.c
++++ b/sound/pci/emu10k1/p16v.c
+@@ -637,7 +637,7 @@ int snd_p16v_free(struct snd_emu10k1 *chip)
+ 	return 0;
+ }
+ 
+-int __devinit snd_p16v_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm **rpcm)
++int snd_p16v_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm **rpcm)
+ {
+ 	struct snd_pcm *pcm;
+ 	struct snd_pcm_substream *substream;
+@@ -854,7 +854,7 @@ static const DECLARE_TLV_DB_SCALE(snd_p16v_db_scale1, -5175, 25, 1);
+ 	.private_value = ((xreg) | ((xhl) << 8)) \
+ }
+ 
+-static struct snd_kcontrol_new p16v_mixer_controls[] __devinitdata = {
++static struct snd_kcontrol_new p16v_mixer_controls[] = {
+ 	P16V_VOL("HD Analog Front Playback Volume", PLAYBACK_VOLUME_MIXER9, 0),
+ 	P16V_VOL("HD Analog Rear Playback Volume", PLAYBACK_VOLUME_MIXER10, 1),
+ 	P16V_VOL("HD Analog Center/LFE Playback Volume", PLAYBACK_VOLUME_MIXER9, 1),
+@@ -880,7 +880,7 @@ static struct snd_kcontrol_new p16v_mixer_controls[] __devinitdata = {
+ };
+ 
+ 
+-int __devinit snd_p16v_mixer(struct snd_emu10k1 *emu)
++int snd_p16v_mixer(struct snd_emu10k1 *emu)
+ {
+ 	int i, err;
+         struct snd_card *card = emu->card;
+@@ -897,7 +897,7 @@ int __devinit snd_p16v_mixer(struct snd_emu10k1 *emu)
+ 
+ #define NUM_CHS	1	/* up to 4, but only first channel is used */
+ 
+-int __devinit snd_p16v_alloc_pm_buffer(struct snd_emu10k1 *emu)
++int snd_p16v_alloc_pm_buffer(struct snd_emu10k1 *emu)
+ {
+ 	emu->p16v_saved = vmalloc(NUM_CHS * 4 * 0x80);
+ 	if (! emu->p16v_saved)
+diff --git a/sound/pci/emu10k1/timer.c b/sound/pci/emu10k1/timer.c
+index 72321e946ccc..b69a7f8a216c 100644
+--- a/sound/pci/emu10k1/timer.c
++++ b/sound/pci/emu10k1/timer.c
+@@ -75,7 +75,7 @@ static struct snd_timer_hardware snd_emu10k1_timer_hw = {
+ 	.precise_resolution = snd_emu10k1_timer_precise_resolution,
+ };
+ 
+-int __devinit snd_emu10k1_timer(struct snd_emu10k1 *emu, int device)
++int snd_emu10k1_timer(struct snd_emu10k1 *emu, int device)
+ {
+ 	struct snd_timer *timer = NULL;
+ 	struct snd_timer_id tid;
+diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
+index 5674cc316530..db2dc835171d 100644
+--- a/sound/pci/ens1370.c
++++ b/sound/pci/ens1370.c
+@@ -1268,8 +1268,8 @@ static const struct snd_pcm_chmap_elem surround_map[] = {
+ 	{ }
+ };
+ 
+-static int __devinit snd_ensoniq_pcm(struct ensoniq * ensoniq, int device,
+-				     struct snd_pcm ** rpcm)
++static int snd_ensoniq_pcm(struct ensoniq *ensoniq, int device,
++			   struct snd_pcm **rpcm)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -1310,8 +1310,8 @@ static int __devinit snd_ensoniq_pcm(struct ensoniq * ensoniq, int device,
+ 	return 0;
+ }
+ 
+-static int __devinit snd_ensoniq_pcm2(struct ensoniq * ensoniq, int device,
+-				      struct snd_pcm ** rpcm)
++static int snd_ensoniq_pcm2(struct ensoniq *ensoniq, int device,
++			    struct snd_pcm **rpcm)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -1484,7 +1484,7 @@ static int snd_es1371_spdif_put(struct snd_kcontrol *kcontrol,
+ 
+ 
+ /* spdif controls */
+-static struct snd_kcontrol_new snd_es1371_mixer_spdif[] __devinitdata = {
++static struct snd_kcontrol_new snd_es1371_mixer_spdif[] = {
+ 	ES1371_SPDIF(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH)),
+ 	{
+ 		.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+@@ -1546,7 +1546,7 @@ static int snd_es1373_rear_put(struct snd_kcontrol *kcontrol,
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_ens1373_rear __devinitdata =
++static struct snd_kcontrol_new snd_ens1373_rear =
+ {
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name =		"AC97 2ch->4ch Copy Switch",
+@@ -1591,7 +1591,7 @@ static int snd_es1373_line_put(struct snd_kcontrol *kcontrol,
+ 	return changed;
+ }
+ 
+-static struct snd_kcontrol_new snd_ens1373_line __devinitdata =
++static struct snd_kcontrol_new snd_ens1373_line =
+ {
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name =		"Line In->Rear Out Switch",
+@@ -1625,7 +1625,7 @@ static int es1371_quirk_lookup(struct ensoniq *ensoniq,
+ 	return 0;
+ }
+ 
+-static struct es1371_quirk es1371_spdif_present[] __devinitdata = {
++static struct es1371_quirk es1371_spdif_present[] = {
+ 	{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_C },
+ 	{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_D },
+ 	{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_E },
+@@ -1634,14 +1634,14 @@ static struct es1371_quirk es1371_spdif_present[] __devinitdata = {
+ 	{ .vid = PCI_ANY_ID, .did = PCI_ANY_ID }
+ };
+ 
+-static struct snd_pci_quirk ens1373_line_quirk[] __devinitdata = {
++static struct snd_pci_quirk ens1373_line_quirk[] = {
+ 	SND_PCI_QUIRK_ID(0x1274, 0x2000), /* GA-7DXR */
+ 	SND_PCI_QUIRK_ID(0x1458, 0xa000), /* GA-8IEXP */
+ 	{ } /* end */
+ };
+ 
+-static int __devinit snd_ensoniq_1371_mixer(struct ensoniq *ensoniq,
+-					    int has_spdif, int has_line)
++static int snd_ensoniq_1371_mixer(struct ensoniq *ensoniq,
++				  int has_spdif, int has_line)
+ {
+ 	struct snd_card *card = ensoniq->card;
+ 	struct snd_ac97_bus *pbus;
+@@ -1749,7 +1749,7 @@ static int snd_ensoniq_control_put(struct snd_kcontrol *kcontrol,
+  * ENS1370 mixer
+  */
+ 
+-static struct snd_kcontrol_new snd_es1370_controls[2] __devinitdata = {
++static struct snd_kcontrol_new snd_es1370_controls[2] = {
+ ENSONIQ_CONTROL("PCM 0 Output also on Line-In Jack", ES_1370_XCTL0),
+ ENSONIQ_CONTROL("Mic +5V bias", ES_1370_XCTL1)
+ };
+@@ -1762,7 +1762,7 @@ static void snd_ensoniq_mixer_free_ak4531(struct snd_ak4531 *ak4531)
+ 	ensoniq->u.es1370.ak4531 = NULL;
+ }
+ 
+-static int __devinit snd_ensoniq_1370_mixer(struct ensoniq * ensoniq)
++static int snd_ensoniq_1370_mixer(struct ensoniq *ensoniq)
+ {
+ 	struct snd_card *card = ensoniq->card;
+ 	struct snd_ak4531 ak4531;
+@@ -1796,7 +1796,7 @@ static int __devinit snd_ensoniq_1370_mixer(struct ensoniq * ensoniq)
+ #ifdef SUPPORT_JOYSTICK
+ 
+ #ifdef CHIP1371
+-static int __devinit snd_ensoniq_get_joystick_port(int dev)
++static int snd_ensoniq_get_joystick_port(int dev)
+ {
+ 	switch (joystick_port[dev]) {
+ 	case 0: /* disabled */
+@@ -1819,7 +1819,7 @@ static inline int snd_ensoniq_get_joystick_port(int dev)
+ }
+ #endif
+ 
+-static int __devinit snd_ensoniq_create_gameport(struct ensoniq *ensoniq, int dev)
++static int snd_ensoniq_create_gameport(struct ensoniq *ensoniq, int dev)
+ {
+ 	struct gameport *gp;
+ 	int io_port;
+@@ -1913,7 +1913,7 @@ static void snd_ensoniq_proc_read(struct snd_info_entry *entry,
+ #endif
+ }
+ 
+-static void __devinit snd_ensoniq_proc_init(struct ensoniq * ensoniq)
++static void snd_ensoniq_proc_init(struct ensoniq *ensoniq)
+ {
+ 	struct snd_info_entry *entry;
+ 
+@@ -1960,7 +1960,7 @@ static int snd_ensoniq_dev_free(struct snd_device *device)
+ }
+ 
+ #ifdef CHIP1371
+-static struct snd_pci_quirk es1371_amplifier_hack[] __devinitdata = {
++static struct snd_pci_quirk es1371_amplifier_hack[] = {
+ 	SND_PCI_QUIRK_ID(0x107b, 0x2150),	/* Gateway Solo 2150 */
+ 	SND_PCI_QUIRK_ID(0x13bd, 0x100c),	/* EV1938 on Mebius PC-MJ100V */
+ 	SND_PCI_QUIRK_ID(0x1102, 0x5938),	/* Targa Xtender300 */
+@@ -2106,9 +2106,9 @@ static SIMPLE_DEV_PM_OPS(snd_ensoniq_pm, snd_ensoniq_suspend, snd_ensoniq_resume
+ #define SND_ENSONIQ_PM_OPS	NULL
+ #endif /* CONFIG_PM_SLEEP */
+ 
+-static int __devinit snd_ensoniq_create(struct snd_card *card,
+-				     struct pci_dev *pci,
+-				     struct ensoniq ** rensoniq)
++static int snd_ensoniq_create(struct snd_card *card,
++			      struct pci_dev *pci,
++			      struct ensoniq **rensoniq)
+ {
+ 	struct ensoniq *ensoniq;
+ 	int err;
+@@ -2361,8 +2361,8 @@ static struct snd_rawmidi_ops snd_ensoniq_midi_input =
+ 	.trigger =	snd_ensoniq_midi_input_trigger,
+ };
+ 
+-static int __devinit snd_ensoniq_midi(struct ensoniq * ensoniq, int device,
+-				      struct snd_rawmidi **rrawmidi)
++static int snd_ensoniq_midi(struct ensoniq *ensoniq, int device,
++			    struct snd_rawmidi **rrawmidi)
+ {
+ 	struct snd_rawmidi *rmidi;
+ 	int err;
+@@ -2422,8 +2422,8 @@ static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit snd_audiopci_probe(struct pci_dev *pci,
+-					const struct pci_device_id *pci_id)
++static int snd_audiopci_probe(struct pci_dev *pci,
++			      const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -2494,7 +2494,7 @@ static int __devinit snd_audiopci_probe(struct pci_dev *pci,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_audiopci_remove(struct pci_dev *pci)
++static void snd_audiopci_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -2504,7 +2504,7 @@ static struct pci_driver ens137x_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_audiopci_ids,
+ 	.probe = snd_audiopci_probe,
+-	.remove = __devexit_p(snd_audiopci_remove),
++	.remove = snd_audiopci_remove,
+ 	.driver = {
+ 		.pm = SND_ENSONIQ_PM_OPS,
+ 	},
+diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
+index 394c5d413530..8423403954ab 100644
+--- a/sound/pci/es1938.c
++++ b/sound/pci/es1938.c
+@@ -1027,7 +1027,7 @@ static struct snd_pcm_ops snd_es1938_capture_ops = {
+ 	.copy =		snd_es1938_capture_copy,
+ };
+ 
+-static int __devinit snd_es1938_new_pcm(struct es1938 *chip, int device)
++static int snd_es1938_new_pcm(struct es1938 *chip, int device)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -1539,7 +1539,7 @@ static SIMPLE_DEV_PM_OPS(es1938_pm, es1938_suspend, es1938_resume);
+ #endif /* CONFIG_PM_SLEEP */
+ 
+ #ifdef SUPPORT_JOYSTICK
+-static int __devinit snd_es1938_create_gameport(struct es1938 *chip)
++static int snd_es1938_create_gameport(struct es1938 *chip)
+ {
+ 	struct gameport *gp;
+ 
+@@ -1594,9 +1594,9 @@ static int snd_es1938_dev_free(struct snd_device *device)
+ 	return snd_es1938_free(chip);
+ }
+ 
+-static int __devinit snd_es1938_create(struct snd_card *card,
+-				    struct pci_dev * pci,
+-				    struct es1938 ** rchip)
++static int snd_es1938_create(struct snd_card *card,
++			     struct pci_dev *pci,
++			     struct es1938 **rchip)
+ {
+ 	struct es1938 *chip;
+ 	int err;
+@@ -1754,7 +1754,7 @@ static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id)
+ 
+ #define ES1938_DMA_SIZE 64
+ 
+-static int __devinit snd_es1938_mixer(struct es1938 *chip)
++static int snd_es1938_mixer(struct es1938 *chip)
+ {
+ 	struct snd_card *card;
+ 	unsigned int idx;
+@@ -1792,8 +1792,8 @@ static int __devinit snd_es1938_mixer(struct es1938 *chip)
+ }
+        
+ 
+-static int __devinit snd_es1938_probe(struct pci_dev *pci,
+-				      const struct pci_device_id *pci_id)
++static int snd_es1938_probe(struct pci_dev *pci,
++			    const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -1878,7 +1878,7 @@ static int __devinit snd_es1938_probe(struct pci_dev *pci,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_es1938_remove(struct pci_dev *pci)
++static void snd_es1938_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -1888,7 +1888,7 @@ static struct pci_driver es1938_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_es1938_ids,
+ 	.probe = snd_es1938_probe,
+-	.remove = __devexit_p(snd_es1938_remove),
++	.remove = snd_es1938_remove,
+ 	.driver = {
+ 		.pm = ES1938_PM_OPS,
+ 	},
+diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
+index 7266020c16cb..879db2d7796a 100644
+--- a/sound/pci/es1968.c
++++ b/sound/pci/es1968.c
+@@ -1429,7 +1429,7 @@ static void snd_es1968_free_dmabuf(struct es1968 *chip)
+ 	}
+ }
+ 
+-static int __devinit
++static int
+ snd_es1968_init_dmabuf(struct es1968 *chip)
+ {
+ 	int err;
+@@ -1704,7 +1704,7 @@ static struct snd_pcm_ops snd_es1968_capture_ops = {
+  */
+ #define CLOCK_MEASURE_BUFSIZE	16768	/* enough large for a single shot */
+ 
+-static void __devinit es1968_measure_clock(struct es1968 *chip)
++static void es1968_measure_clock(struct es1968 *chip)
+ {
+ 	int i, apu;
+ 	unsigned int pa, offset, t;
+@@ -1806,7 +1806,7 @@ static void snd_es1968_pcm_free(struct snd_pcm *pcm)
+ 	esm->pcm = NULL;
+ }
+ 
+-static int __devinit
++static int
+ snd_es1968_pcm(struct es1968 *chip, int device)
+ {
+ 	struct snd_pcm *pcm;
+@@ -2016,7 +2016,7 @@ static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id)
+  *  Mixer stuff
+  */
+ 
+-static int __devinit
++static int
+ snd_es1968_mixer(struct es1968 *chip)
+ {
+ 	struct snd_ac97_bus *pbus;
+@@ -2465,7 +2465,7 @@ static SIMPLE_DEV_PM_OPS(es1968_pm, es1968_suspend, es1968_resume);
+ 
+ #ifdef SUPPORT_JOYSTICK
+ #define JOYSTICK_ADDR	0x200
+-static int __devinit snd_es1968_create_gameport(struct es1968 *chip, int dev)
++static int snd_es1968_create_gameport(struct es1968 *chip, int dev)
+ {
+ 	struct gameport *gp;
+ 	struct resource *r;
+@@ -2516,7 +2516,7 @@ static inline void snd_es1968_free_gameport(struct es1968 *chip) { }
+ #endif
+ 
+ #ifdef CONFIG_SND_ES1968_INPUT
+-static int __devinit snd_es1968_input_register(struct es1968 *chip)
++static int snd_es1968_input_register(struct es1968 *chip)
+ {
+ 	struct input_dev *input_dev;
+ 	int err;
+@@ -2653,7 +2653,7 @@ struct ess_device_list {
+ 	unsigned short vendor;	/* subsystem vendor id */
+ };
+ 
+-static struct ess_device_list pm_whitelist[] __devinitdata = {
++static struct ess_device_list pm_whitelist[] = {
+ 	{ TYPE_MAESTRO2E, 0x0e11 },	/* Compaq Armada */
+ 	{ TYPE_MAESTRO2E, 0x1028 },
+ 	{ TYPE_MAESTRO2E, 0x103c },
+@@ -2664,19 +2664,19 @@ static struct ess_device_list pm_whitelist[] __devinitdata = {
+ 	{ TYPE_MAESTRO2, 0x125d },	/* a PCI card, e.g. SF64-PCE2 */
+ };
+ 
+-static struct ess_device_list mpu_blacklist[] __devinitdata = {
++static struct ess_device_list mpu_blacklist[] = {
+ 	{ TYPE_MAESTRO2, 0x125d },
+ };
+ 
+-static int __devinit snd_es1968_create(struct snd_card *card,
+-				       struct pci_dev *pci,
+-				       int total_bufsize,
+-				       int play_streams,
+-				       int capt_streams,
+-				       int chip_type,
+-				       int do_pm,
+-				       int radio_nr,
+-				       struct es1968 **chip_ret)
++static int snd_es1968_create(struct snd_card *card,
++			     struct pci_dev *pci,
++			     int total_bufsize,
++			     int play_streams,
++			     int capt_streams,
++			     int chip_type,
++			     int do_pm,
++			     int radio_nr,
++			     struct es1968 **chip_ret)
+ {
+ 	static struct snd_device_ops ops = {
+ 		.dev_free =	snd_es1968_dev_free,
+@@ -2795,8 +2795,8 @@ static int __devinit snd_es1968_create(struct snd_card *card,
+ 
+ /*
+  */
+-static int __devinit snd_es1968_probe(struct pci_dev *pci,
+-				      const struct pci_device_id *pci_id)
++static int snd_es1968_probe(struct pci_dev *pci,
++			    const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -2906,7 +2906,7 @@ static int __devinit snd_es1968_probe(struct pci_dev *pci,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_es1968_remove(struct pci_dev *pci)
++static void snd_es1968_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -2916,7 +2916,7 @@ static struct pci_driver es1968_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_es1968_ids,
+ 	.probe = snd_es1968_probe,
+-	.remove = __devexit_p(snd_es1968_remove),
++	.remove = snd_es1968_remove,
+ 	.driver = {
+ 		.pm = ES1968_PM_OPS,
+ 	},
+diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
+index c5806f89be1e..4f07fda5adf2 100644
+--- a/sound/pci/fm801.c
++++ b/sound/pci/fm801.c
+@@ -689,7 +689,7 @@ static struct snd_pcm_ops snd_fm801_capture_ops = {
+ 	.pointer =	snd_fm801_capture_pointer,
+ };
+ 
+-static int __devinit snd_fm801_pcm(struct fm801 *chip, int device, struct snd_pcm ** rpcm)
++static int snd_fm801_pcm(struct fm801 *chip, int device, struct snd_pcm **rpcm)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -984,7 +984,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_dsp, -3450, 150, 0);
+ 
+ #define FM801_CONTROLS ARRAY_SIZE(snd_fm801_controls)
+ 
+-static struct snd_kcontrol_new snd_fm801_controls[] __devinitdata = {
++static struct snd_kcontrol_new snd_fm801_controls[] = {
+ FM801_DOUBLE_TLV("Wave Playback Volume", FM801_PCM_VOL, 0, 8, 31, 1,
+ 		 db_scale_dsp),
+ FM801_SINGLE("Wave Playback Switch", FM801_PCM_VOL, 15, 1, 1),
+@@ -1005,7 +1005,7 @@ FM801_SINGLE("FM Playback Switch", FM801_FM_VOL, 15, 1, 1),
+ 
+ #define FM801_CONTROLS_MULTI ARRAY_SIZE(snd_fm801_controls_multi)
+ 
+-static struct snd_kcontrol_new snd_fm801_controls_multi[] __devinitdata = {
++static struct snd_kcontrol_new snd_fm801_controls_multi[] = {
+ FM801_SINGLE("AC97 2ch->4ch Copy Switch", FM801_CODEC_CTRL, 7, 1, 0),
+ FM801_SINGLE("AC97 18-bit Switch", FM801_CODEC_CTRL, 10, 1, 0),
+ FM801_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), FM801_I2S_MODE, 8, 1, 0),
+@@ -1030,7 +1030,7 @@ static void snd_fm801_mixer_free_ac97(struct snd_ac97 *ac97)
+ 	}
+ }
+ 
+-static int __devinit snd_fm801_mixer(struct fm801 *chip)
++static int snd_fm801_mixer(struct fm801 *chip)
+ {
+ 	struct snd_ac97_template ac97;
+ 	unsigned int i;
+@@ -1191,11 +1191,11 @@ static int snd_fm801_dev_free(struct snd_device *device)
+ 	return snd_fm801_free(chip);
+ }
+ 
+-static int __devinit snd_fm801_create(struct snd_card *card,
+-				      struct pci_dev * pci,
+-				      int tea575x_tuner,
+-				      int radio_nr,
+-				      struct fm801 ** rchip)
++static int snd_fm801_create(struct snd_card *card,
++			    struct pci_dev *pci,
++			    int tea575x_tuner,
++			    int radio_nr,
++			    struct fm801 **rchip)
+ {
+ 	struct fm801 *chip;
+ 	int err;
+@@ -1296,8 +1296,8 @@ static int __devinit snd_fm801_create(struct snd_card *card,
+ 	return 0;
+ }
+ 
+-static int __devinit snd_card_fm801_probe(struct pci_dev *pci,
+-					  const struct pci_device_id *pci_id)
++static int snd_card_fm801_probe(struct pci_dev *pci,
++				const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -1367,7 +1367,7 @@ static int __devinit snd_card_fm801_probe(struct pci_dev *pci,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_card_fm801_remove(struct pci_dev *pci)
++static void snd_card_fm801_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -1439,7 +1439,7 @@ static struct pci_driver fm801_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_fm801_ids,
+ 	.probe = snd_card_fm801_probe,
+-	.remove = __devexit_p(snd_card_fm801_remove),
++	.remove = snd_card_fm801_remove,
+ 	.driver = {
+ 		.pm = SND_FM801_PM_OPS,
+ 	},
+diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
+index eb481090d372..335685e0e4ea 100644
+--- a/sound/pci/hda/hda_intel.c
++++ b/sound/pci/hda/hda_intel.c
+@@ -607,8 +607,8 @@ enum {
+ #define DELAYED_INIT_MARK
+ #define DELAYED_INITDATA_MARK
+ #else
+-#define DELAYED_INIT_MARK	__devinit
+-#define DELAYED_INITDATA_MARK	__devinitdata
++#define DELAYED_INIT_MARK
++#define DELAYED_INITDATA_MARK
+ #endif
+ 
+ static char *driver_short_names[] DELAYED_INITDATA_MARK = {
+@@ -1717,7 +1717,7 @@ static int DELAYED_INIT_MARK azx_codec_create(struct azx *chip, const char *mode
+ }
+ 
+ /* configure each codec instance */
+-static int __devinit azx_codec_configure(struct azx *chip)
++static int azx_codec_configure(struct azx *chip)
+ {
+ 	struct hda_codec *codec;
+ 	list_for_each_entry(codec, &chip->bus->codec_list, list) {
+@@ -2489,7 +2489,7 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
+ /*
+  * mixer creation - all stuff is implemented in hda module
+  */
+-static int __devinit azx_mixer_create(struct azx *chip)
++static int azx_mixer_create(struct azx *chip)
+ {
+ 	return snd_hda_build_controls(chip->bus);
+ }
+@@ -2498,7 +2498,7 @@ static int __devinit azx_mixer_create(struct azx *chip)
+ /*
+  * initialize SD streams
+  */
+-static int __devinit azx_init_stream(struct azx *chip)
++static int azx_init_stream(struct azx *chip)
+ {
+ 	int i;
+ 
+@@ -2740,7 +2740,7 @@ static int DELAYED_INIT_MARK azx_first_init(struct azx *chip);
+ static int DELAYED_INIT_MARK azx_probe_continue(struct azx *chip);
+ 
+ #ifdef SUPPORT_VGA_SWITCHEROO
+-static struct pci_dev __devinit *get_bound_vga(struct pci_dev *pci);
++static struct pci_dev *get_bound_vga(struct pci_dev *pci);
+ 
+ static void azx_vs_set_state(struct pci_dev *pci,
+ 			     enum vga_switcheroo_state state)
+@@ -2805,7 +2805,7 @@ static bool azx_vs_can_switch(struct pci_dev *pci)
+ 	return true;
+ }
+ 
+-static void __devinit init_vga_switcheroo(struct azx *chip)
++static void init_vga_switcheroo(struct azx *chip)
+ {
+ 	struct pci_dev *p = get_bound_vga(chip->pci);
+ 	if (p) {
+@@ -2822,7 +2822,7 @@ static const struct vga_switcheroo_client_ops azx_vs_ops = {
+ 	.can_switch = azx_vs_can_switch,
+ };
+ 
+-static int __devinit register_vga_switcheroo(struct azx *chip)
++static int register_vga_switcheroo(struct azx *chip)
+ {
+ 	int err;
+ 
+@@ -2917,7 +2917,7 @@ static int azx_dev_free(struct snd_device *device)
+ /*
+  * Check of disabled HDMI controller by vga-switcheroo
+  */
+-static struct pci_dev __devinit *get_bound_vga(struct pci_dev *pci)
++static struct pci_dev *get_bound_vga(struct pci_dev *pci)
+ {
+ 	struct pci_dev *p;
+ 
+@@ -2940,7 +2940,7 @@ static struct pci_dev __devinit *get_bound_vga(struct pci_dev *pci)
+ 	return NULL;
+ }
+ 
+-static bool __devinit check_hdmi_disabled(struct pci_dev *pci)
++static bool check_hdmi_disabled(struct pci_dev *pci)
+ {
+ 	bool vga_inactive = false;
+ 	struct pci_dev *p = get_bound_vga(pci);
+@@ -2957,7 +2957,7 @@ static bool __devinit check_hdmi_disabled(struct pci_dev *pci)
+ /*
+  * white/black-listing for position_fix
+  */
+-static struct snd_pci_quirk position_fix_list[] __devinitdata = {
++static struct snd_pci_quirk position_fix_list[] = {
+ 	SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),
+ 	SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
+ 	SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
+@@ -2975,7 +2975,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = {
+ 	{}
+ };
+ 
+-static int __devinit check_position_fix(struct azx *chip, int fix)
++static int check_position_fix(struct azx *chip, int fix)
+ {
+ 	const struct snd_pci_quirk *q;
+ 
+@@ -3012,7 +3012,7 @@ static int __devinit check_position_fix(struct azx *chip, int fix)
+ /*
+  * black-lists for probe_mask
+  */
+-static struct snd_pci_quirk probe_mask_list[] __devinitdata = {
++static struct snd_pci_quirk probe_mask_list[] = {
+ 	/* Thinkpad often breaks the controller communication when accessing
+ 	 * to the non-working (or non-existing) modem codec slot.
+ 	 */
+@@ -3033,7 +3033,7 @@ static struct snd_pci_quirk probe_mask_list[] __devinitdata = {
+ 
+ #define AZX_FORCE_CODEC_MASK	0x100
+ 
+-static void __devinit check_probe_mask(struct azx *chip, int dev)
++static void check_probe_mask(struct azx *chip, int dev)
+ {
+ 	const struct snd_pci_quirk *q;
+ 
+@@ -3061,7 +3061,7 @@ static void __devinit check_probe_mask(struct azx *chip, int dev)
+ /*
+  * white/black-list for enable_msi
+  */
+-static struct snd_pci_quirk msi_black_list[] __devinitdata = {
++static struct snd_pci_quirk msi_black_list[] = {
+ 	SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */
+ 	SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */
+ 	SND_PCI_QUIRK(0x1043, 0x822d, "ASUS", 0), /* Athlon64 X2 + nvidia MCP55 */
+@@ -3070,7 +3070,7 @@ static struct snd_pci_quirk msi_black_list[] __devinitdata = {
+ 	{}
+ };
+ 
+-static void __devinit check_msi(struct azx *chip)
++static void check_msi(struct azx *chip)
+ {
+ 	const struct snd_pci_quirk *q;
+ 
+@@ -3096,7 +3096,7 @@ static void __devinit check_msi(struct azx *chip)
+ }
+ 
+ /* check the snoop mode availability */
+-static void __devinit azx_check_snoop_available(struct azx *chip)
++static void azx_check_snoop_available(struct azx *chip)
+ {
+ 	bool snoop = chip->snoop;
+ 
+@@ -3128,9 +3128,9 @@ static void __devinit azx_check_snoop_available(struct azx *chip)
+ /*
+  * constructor
+  */
+-static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
+-				int dev, unsigned int driver_caps,
+-				struct azx **rchip)
++static int azx_create(struct snd_card *card, struct pci_dev *pci,
++		      int dev, unsigned int driver_caps,
++		      struct azx **rchip)
+ {
+ 	static struct snd_device_ops ops = {
+ 		.dev_free = azx_dev_free,
+@@ -3410,8 +3410,8 @@ static void azx_firmware_cb(const struct firmware *fw, void *context)
+ }
+ #endif
+ 
+-static int __devinit azx_probe(struct pci_dev *pci,
+-			       const struct pci_device_id *pci_id)
++static int azx_probe(struct pci_dev *pci,
++		     const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -3551,7 +3551,7 @@ static int DELAYED_INIT_MARK azx_probe_continue(struct azx *chip)
+ 	return err;
+ }
+ 
+-static void __devexit azx_remove(struct pci_dev *pci)
++static void azx_remove(struct pci_dev *pci)
+ {
+ 	struct snd_card *card = pci_get_drvdata(pci);
+ 
+@@ -3738,7 +3738,7 @@ static struct pci_driver azx_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = azx_ids,
+ 	.probe = azx_probe,
+-	.remove = __devexit_p(azx_remove),
++	.remove = azx_remove,
+ 	.driver = {
+ 		.pm = AZX_PM_OPS,
+ 	},
+diff --git a/sound/pci/ice1712/amp.c b/sound/pci/ice1712/amp.c
+index d9bd27b25100..2f9b93467867 100644
+--- a/sound/pci/ice1712/amp.c
++++ b/sound/pci/ice1712/amp.c
+@@ -37,7 +37,7 @@ static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
+ 	snd_vt1724_write_i2c(ice, WM_DEV, cval >> 8, cval & 0xff);
+ }
+ 
+-static int __devinit snd_vt1724_amp_init(struct snd_ice1712 *ice)
++static int snd_vt1724_amp_init(struct snd_ice1712 *ice)
+ {
+ 	static const unsigned short wm_inits[] = {
+ 		WM_ATTEN_L,	0x0000,	/* 0 db */
+@@ -65,7 +65,7 @@ static int __devinit snd_vt1724_amp_init(struct snd_ice1712 *ice)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_vt1724_amp_add_controls(struct snd_ice1712 *ice)
++static int snd_vt1724_amp_add_controls(struct snd_ice1712 *ice)
+ {
+ 	if (ice->ac97)
+ 		/* we use pins 39 and 41 of the VT1616 for left and right
+@@ -77,7 +77,7 @@ static int __devinit snd_vt1724_amp_add_controls(struct snd_ice1712 *ice)
+ 
+ 
+ /* entry point */
+-struct snd_ice1712_card_info snd_vt1724_amp_cards[] __devinitdata = {
++struct snd_ice1712_card_info snd_vt1724_amp_cards[] = {
+ 	{
+ 		.subvendor = VT1724_SUBDEVICE_AV710,
+ 		.name = "Chaintech AV-710",
+diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c
+index ce9941c5e988..55902ec40344 100644
+--- a/sound/pci/ice1712/aureon.c
++++ b/sound/pci/ice1712/aureon.c
+@@ -1433,7 +1433,7 @@ static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl
+  * mixers
+  */
+ 
+-static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
++static struct snd_kcontrol_new aureon_dac_controls[] = {
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "Master Playback Switch",
+@@ -1548,7 +1548,7 @@ static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
+ 	}
+ };
+ 
+-static struct snd_kcontrol_new wm_controls[] __devinitdata = {
++static struct snd_kcontrol_new wm_controls[] = {
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "PCM Playback Switch",
+@@ -1614,7 +1614,7 @@ static struct snd_kcontrol_new wm_controls[] __devinitdata = {
+ 	}
+ };
+ 
+-static struct snd_kcontrol_new ac97_controls[] __devinitdata = {
++static struct snd_kcontrol_new ac97_controls[] = {
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "AC97 Playback Switch",
+@@ -1719,7 +1719,7 @@ static struct snd_kcontrol_new ac97_controls[] __devinitdata = {
+ 	}
+ };
+ 
+-static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
++static struct snd_kcontrol_new universe_ac97_controls[] = {
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "AC97 Playback Switch",
+@@ -1851,7 +1851,7 @@ static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
+ 
+ };
+ 
+-static struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
++static struct snd_kcontrol_new cs8415_controls[] = {
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH),
+@@ -1896,7 +1896,7 @@ static struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
+ 	}
+ };
+ 
+-static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
++static int aureon_add_controls(struct snd_ice1712 *ice)
+ {
+ 	unsigned int i, counts;
+ 	int err;
+@@ -2124,7 +2124,7 @@ static int aureon_resume(struct snd_ice1712 *ice)
+ /*
+  * initialize the chip
+  */
+-static int __devinit aureon_init(struct snd_ice1712 *ice)
++static int aureon_init(struct snd_ice1712 *ice)
+ {
+ 	struct aureon_spec *spec;
+ 	int i, err;
+@@ -2174,7 +2174,7 @@ static int __devinit aureon_init(struct snd_ice1712 *ice)
+  * hence the driver needs to sets up it properly.
+  */
+ 
+-static unsigned char aureon51_eeprom[] __devinitdata = {
++static unsigned char aureon51_eeprom[] = {
+ 	[ICE_EEP2_SYSCONF]     = 0x0a,	/* clock 512, spdif-in/ADC, 3DACs */
+ 	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
+ 	[ICE_EEP2_I2S]         = 0xfc,	/* vol, 96k, 24bit, 192k */
+@@ -2190,7 +2190,7 @@ static unsigned char aureon51_eeprom[] __devinitdata = {
+ 	[ICE_EEP2_GPIO_STATE2] = 0x00,
+ };
+ 
+-static unsigned char aureon71_eeprom[] __devinitdata = {
++static unsigned char aureon71_eeprom[] = {
+ 	[ICE_EEP2_SYSCONF]     = 0x0b,	/* clock 512, spdif-in/ADC, 4DACs */
+ 	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
+ 	[ICE_EEP2_I2S]         = 0xfc,	/* vol, 96k, 24bit, 192k */
+@@ -2207,7 +2207,7 @@ static unsigned char aureon71_eeprom[] __devinitdata = {
+ };
+ #define prodigy71_eeprom aureon71_eeprom
+ 
+-static unsigned char aureon71_universe_eeprom[] __devinitdata = {
++static unsigned char aureon71_universe_eeprom[] = {
+ 	[ICE_EEP2_SYSCONF]     = 0x2b,	/* clock 512, mpu401, spdif-in/ADC,
+ 					 * 4DACs
+ 					 */
+@@ -2225,7 +2225,7 @@ static unsigned char aureon71_universe_eeprom[] __devinitdata = {
+ 	[ICE_EEP2_GPIO_STATE2] = 0x00,
+ };
+ 
+-static unsigned char prodigy71lt_eeprom[] __devinitdata = {
++static unsigned char prodigy71lt_eeprom[] = {
+ 	[ICE_EEP2_SYSCONF]     = 0x4b,	/* clock 384, spdif-in/ADC, 4DACs */
+ 	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
+ 	[ICE_EEP2_I2S]         = 0xfc,	/* vol, 96k, 24bit, 192k */
+@@ -2243,7 +2243,7 @@ static unsigned char prodigy71lt_eeprom[] __devinitdata = {
+ #define prodigy71xt_eeprom prodigy71lt_eeprom
+ 
+ /* entry point */
+-struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
++struct snd_ice1712_card_info snd_vt1724_aureon_cards[] = {
+ 	{
+ 		.subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
+ 		.name = "Terratec Aureon 5.1-Sky",
+diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c
+index bbef99bf77df..ab2bca164d6f 100644
+--- a/sound/pci/ice1712/delta.c
++++ b/sound/pci/ice1712/delta.c
+@@ -431,7 +431,7 @@ static int snd_ice1712_delta1010lt_wordclock_status_get(struct snd_kcontrol *kco
+ 	return 0;
+ }
+ 
+-static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_status __devinitdata =
++static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_status =
+ {
+ 	.access =	(SNDRV_CTL_ELEM_ACCESS_READ),
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+@@ -444,7 +444,7 @@ static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_status __devini
+  * initialize the chips on M-Audio cards
+  */
+ 
+-static struct snd_akm4xxx akm_audiophile __devinitdata = {
++static struct snd_akm4xxx akm_audiophile = {
+ 	.type = SND_AK4528,
+ 	.num_adcs = 2,
+ 	.num_dacs = 2,
+@@ -453,7 +453,7 @@ static struct snd_akm4xxx akm_audiophile __devinitdata = {
+ 	}
+ };
+ 
+-static struct snd_ak4xxx_private akm_audiophile_priv __devinitdata = {
++static struct snd_ak4xxx_private akm_audiophile_priv = {
+ 	.caddr = 2,
+ 	.cif = 0,
+ 	.data_mask = ICE1712_DELTA_AP_DOUT,
+@@ -465,7 +465,7 @@ static struct snd_ak4xxx_private akm_audiophile_priv __devinitdata = {
+ 	.mask_flags = 0,
+ };
+ 
+-static struct snd_akm4xxx akm_delta410 __devinitdata = {
++static struct snd_akm4xxx akm_delta410 = {
+ 	.type = SND_AK4529,
+ 	.num_adcs = 2,
+ 	.num_dacs = 8,
+@@ -474,7 +474,7 @@ static struct snd_akm4xxx akm_delta410 __devinitdata = {
+ 	}
+ };
+ 
+-static struct snd_ak4xxx_private akm_delta410_priv __devinitdata = {
++static struct snd_ak4xxx_private akm_delta410_priv = {
+ 	.caddr = 0,
+ 	.cif = 0,
+ 	.data_mask = ICE1712_DELTA_AP_DOUT,
+@@ -486,7 +486,7 @@ static struct snd_ak4xxx_private akm_delta410_priv __devinitdata = {
+ 	.mask_flags = 0,
+ };
+ 
+-static struct snd_akm4xxx akm_delta1010lt __devinitdata = {
++static struct snd_akm4xxx akm_delta1010lt = {
+ 	.type = SND_AK4524,
+ 	.num_adcs = 8,
+ 	.num_dacs = 8,
+@@ -496,7 +496,7 @@ static struct snd_akm4xxx akm_delta1010lt __devinitdata = {
+ 	}
+ };
+ 
+-static struct snd_ak4xxx_private akm_delta1010lt_priv __devinitdata = {
++static struct snd_ak4xxx_private akm_delta1010lt_priv = {
+ 	.caddr = 2,
+ 	.cif = 0, /* the default level of the CIF pin from AK4524 */
+ 	.data_mask = ICE1712_DELTA_1010LT_DOUT,
+@@ -508,7 +508,7 @@ static struct snd_ak4xxx_private akm_delta1010lt_priv __devinitdata = {
+ 	.mask_flags = 0,
+ };
+ 
+-static struct snd_akm4xxx akm_delta66e __devinitdata = {
++static struct snd_akm4xxx akm_delta66e = {
+ 	.type = SND_AK4524,
+ 	.num_adcs = 4,
+ 	.num_dacs = 4,
+@@ -518,7 +518,7 @@ static struct snd_akm4xxx akm_delta66e __devinitdata = {
+ 	}
+ };
+ 
+-static struct snd_ak4xxx_private akm_delta66e_priv __devinitdata = {
++static struct snd_ak4xxx_private akm_delta66e_priv = {
+ 	.caddr = 2,
+ 	.cif = 0, /* the default level of the CIF pin from AK4524 */
+ 	.data_mask = ICE1712_DELTA_66E_DOUT,
+@@ -531,7 +531,7 @@ static struct snd_ak4xxx_private akm_delta66e_priv __devinitdata = {
+ };
+ 
+ 
+-static struct snd_akm4xxx akm_delta44 __devinitdata = {
++static struct snd_akm4xxx akm_delta44 = {
+ 	.type = SND_AK4524,
+ 	.num_adcs = 4,
+ 	.num_dacs = 4,
+@@ -541,7 +541,7 @@ static struct snd_akm4xxx akm_delta44 __devinitdata = {
+ 	}
+ };
+ 
+-static struct snd_ak4xxx_private akm_delta44_priv __devinitdata = {
++static struct snd_ak4xxx_private akm_delta44_priv = {
+ 	.caddr = 2,
+ 	.cif = 0, /* the default level of the CIF pin from AK4524 */
+ 	.data_mask = ICE1712_DELTA_CODEC_SERIAL_DATA,
+@@ -553,7 +553,7 @@ static struct snd_ak4xxx_private akm_delta44_priv __devinitdata = {
+ 	.mask_flags = 0,
+ };
+ 
+-static struct snd_akm4xxx akm_vx442 __devinitdata = {
++static struct snd_akm4xxx akm_vx442 = {
+ 	.type = SND_AK4524,
+ 	.num_adcs = 4,
+ 	.num_dacs = 4,
+@@ -563,7 +563,7 @@ static struct snd_akm4xxx akm_vx442 __devinitdata = {
+ 	}
+ };
+ 
+-static struct snd_ak4xxx_private akm_vx442_priv __devinitdata = {
++static struct snd_ak4xxx_private akm_vx442_priv = {
+ 	.caddr = 2,
+ 	.cif = 0,
+ 	.data_mask = ICE1712_VX442_DOUT,
+@@ -575,7 +575,7 @@ static struct snd_ak4xxx_private akm_vx442_priv __devinitdata = {
+ 	.mask_flags = 0,
+ };
+ 
+-static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
++static int snd_ice1712_delta_init(struct snd_ice1712 *ice)
+ {
+ 	int err;
+ 	struct snd_akm4xxx *ak;
+@@ -713,19 +713,19 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
+  * additional controls for M-Audio cards
+  */
+ 
+-static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_select __devinitdata =
++static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_select =
+ ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Sync", 0, ICE1712_DELTA_WORD_CLOCK_SELECT, 1, 0);
+-static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_select __devinitdata =
++static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_select =
+ ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Sync", 0, ICE1712_DELTA_1010LT_WORDCLOCK, 0, 0);
+-static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_status __devinitdata =
++static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_status =
+ ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Status", 0, ICE1712_DELTA_WORD_CLOCK_STATUS, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE);
+-static struct snd_kcontrol_new snd_ice1712_deltadio2496_spdif_in_select __devinitdata =
++static struct snd_kcontrol_new snd_ice1712_deltadio2496_spdif_in_select =
+ ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "IEC958 Input Optical", 0, ICE1712_DELTA_SPDIF_INPUT_SELECT, 0, 0);
+-static struct snd_kcontrol_new snd_ice1712_delta_spdif_in_status __devinitdata =
++static struct snd_kcontrol_new snd_ice1712_delta_spdif_in_status =
+ ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Delta IEC958 Input Status", 0, ICE1712_DELTA_SPDIF_IN_STAT, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE);
+ 
+ 
+-static int __devinit snd_ice1712_delta_add_controls(struct snd_ice1712 *ice)
++static int snd_ice1712_delta_add_controls(struct snd_ice1712 *ice)
+ {
+ 	int err;
+ 
+@@ -801,7 +801,7 @@ static int __devinit snd_ice1712_delta_add_controls(struct snd_ice1712 *ice)
+ 
+ 
+ /* entry point */
+-struct snd_ice1712_card_info snd_ice1712_delta_cards[] __devinitdata = {
++struct snd_ice1712_card_info snd_ice1712_delta_cards[] = {
+ 	{
+ 		.subvendor = ICE1712_SUBDEVICE_DELTA1010,
+ 		.name = "M Audio Delta 1010",
+diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c
+index bf289f0a1ed4..bc2e7011c55d 100644
+--- a/sound/pci/ice1712/ews.c
++++ b/sound/pci/ice1712/ews.c
+@@ -343,7 +343,7 @@ static void ews88_setup_spdif(struct snd_ice1712 *ice, int rate)
+ 
+ /*
+  */
+-static struct snd_akm4xxx akm_ews88mt __devinitdata = {
++static struct snd_akm4xxx akm_ews88mt = {
+ 	.num_adcs = 8,
+ 	.num_dacs = 8,
+ 	.type = SND_AK4524,
+@@ -353,7 +353,7 @@ static struct snd_akm4xxx akm_ews88mt __devinitdata = {
+ 	}
+ };
+ 
+-static struct snd_ak4xxx_private akm_ews88mt_priv __devinitdata = {
++static struct snd_ak4xxx_private akm_ews88mt_priv = {
+ 	.caddr = 2,
+ 	.cif = 1, /* CIF high */
+ 	.data_mask = ICE1712_EWS88_SERIAL_DATA,
+@@ -365,7 +365,7 @@ static struct snd_ak4xxx_private akm_ews88mt_priv __devinitdata = {
+ 	.mask_flags = 0,
+ };
+ 
+-static struct snd_akm4xxx akm_ewx2496 __devinitdata = {
++static struct snd_akm4xxx akm_ewx2496 = {
+ 	.num_adcs = 2,
+ 	.num_dacs = 2,
+ 	.type = SND_AK4524,
+@@ -374,7 +374,7 @@ static struct snd_akm4xxx akm_ewx2496 __devinitdata = {
+ 	}
+ };
+ 
+-static struct snd_ak4xxx_private akm_ewx2496_priv __devinitdata = {
++static struct snd_ak4xxx_private akm_ewx2496_priv = {
+ 	.caddr = 2,
+ 	.cif = 1, /* CIF high */
+ 	.data_mask = ICE1712_EWS88_SERIAL_DATA,
+@@ -386,7 +386,7 @@ static struct snd_ak4xxx_private akm_ewx2496_priv __devinitdata = {
+ 	.mask_flags = 0,
+ };
+ 
+-static struct snd_akm4xxx akm_6fire __devinitdata = {
++static struct snd_akm4xxx akm_6fire = {
+ 	.num_adcs = 6,
+ 	.num_dacs = 6,
+ 	.type = SND_AK4524,
+@@ -395,7 +395,7 @@ static struct snd_akm4xxx akm_6fire __devinitdata = {
+ 	}
+ };
+ 
+-static struct snd_ak4xxx_private akm_6fire_priv __devinitdata = {
++static struct snd_ak4xxx_private akm_6fire_priv = {
+ 	.caddr = 2,
+ 	.cif = 1, /* CIF high */
+ 	.data_mask = ICE1712_6FIRE_SERIAL_DATA,
+@@ -419,7 +419,7 @@ static struct snd_ak4xxx_private akm_6fire_priv __devinitdata = {
+ 
+ static int snd_ice1712_6fire_write_pca(struct snd_ice1712 *ice, unsigned char reg, unsigned char data);
+ 
+-static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice)
++static int snd_ice1712_ews_init(struct snd_ice1712 *ice)
+ {
+ 	int err;
+ 	struct snd_akm4xxx *ak;
+@@ -615,7 +615,7 @@ static int snd_ice1712_ewx_io_sense_put(struct snd_kcontrol *kcontrol, struct sn
+ 	return val != nval;
+ }
+ 
+-static struct snd_kcontrol_new snd_ice1712_ewx2496_controls[] __devinitdata = {
++static struct snd_kcontrol_new snd_ice1712_ewx2496_controls[] = {
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "Input Sensitivity Switch",
+@@ -723,7 +723,7 @@ static int snd_ice1712_ews88mt_input_sense_put(struct snd_kcontrol *kcontrol, st
+ 	return ndata != data;
+ }
+ 
+-static struct snd_kcontrol_new snd_ice1712_ews88mt_input_sense __devinitdata = {
++static struct snd_kcontrol_new snd_ice1712_ews88mt_input_sense = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "Input Sensitivity Switch",
+ 	.info = snd_ice1712_ewx_io_sense_info,
+@@ -732,7 +732,7 @@ static struct snd_kcontrol_new snd_ice1712_ews88mt_input_sense __devinitdata = {
+ 	.count = 8,
+ };
+ 
+-static struct snd_kcontrol_new snd_ice1712_ews88mt_output_sense __devinitdata = {
++static struct snd_kcontrol_new snd_ice1712_ews88mt_output_sense = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "Output Sensitivity Switch",
+ 	.info = snd_ice1712_ewx_io_sense_info,
+@@ -810,7 +810,7 @@ static int snd_ice1712_ews88d_control_put(struct snd_kcontrol *kcontrol, struct
+   .private_value = xshift | (xinvert << 8),\
+ }
+ 
+-static struct snd_kcontrol_new snd_ice1712_ews88d_controls[] __devinitdata = {
++static struct snd_kcontrol_new snd_ice1712_ews88d_controls[] = {
+ 	EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "IEC958 Input Optical", 0, 1, 0), /* inverted */
+ 	EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "ADAT Output Optical", 1, 0, 0),
+ 	EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "ADAT External Master Clock", 2, 0, 0),
+@@ -947,7 +947,7 @@ static int snd_ice1712_6fire_select_input_put(struct snd_kcontrol *kcontrol, str
+   .private_value = xshift | (xinvert << 8),\
+ }
+ 
+-static struct snd_kcontrol_new snd_ice1712_6fire_controls[] __devinitdata = {
++static struct snd_kcontrol_new snd_ice1712_6fire_controls[] = {
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "Analog Input Select",
+@@ -963,7 +963,7 @@ static struct snd_kcontrol_new snd_ice1712_6fire_controls[] __devinitdata = {
+ };
+ 
+ 
+-static int __devinit snd_ice1712_ews_add_controls(struct snd_ice1712 *ice)
++static int snd_ice1712_ews_add_controls(struct snd_ice1712 *ice)
+ {
+ 	unsigned int idx;
+ 	int err;
+@@ -1029,7 +1029,7 @@ static int __devinit snd_ice1712_ews_add_controls(struct snd_ice1712 *ice)
+ 
+ 
+ /* entry point */
+-struct snd_ice1712_card_info snd_ice1712_ews_cards[] __devinitdata = {
++struct snd_ice1712_card_info snd_ice1712_ews_cards[] = {
+ 	{
+ 		.subvendor = ICE1712_SUBDEVICE_EWX2496,
+ 		.name = "TerraTec EWX24/96",
+diff --git a/sound/pci/ice1712/hoontech.c b/sound/pci/ice1712/hoontech.c
+index 3d84d21e484d..59e37c581691 100644
+--- a/sound/pci/ice1712/hoontech.c
++++ b/sound/pci/ice1712/hoontech.c
+@@ -39,7 +39,7 @@ struct hoontech_spec {
+ 	unsigned short boxconfig[4];
+ };
+ 
+-static void __devinit snd_ice1712_stdsp24_gpio_write(struct snd_ice1712 *ice, unsigned char byte)
++static void snd_ice1712_stdsp24_gpio_write(struct snd_ice1712 *ice, unsigned char byte)
+ {
+ 	byte |= ICE1712_STDSP24_CLOCK_BIT;
+ 	udelay(100);
+@@ -52,7 +52,7 @@ static void __devinit snd_ice1712_stdsp24_gpio_write(struct snd_ice1712 *ice, un
+ 	snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, byte);
+ }
+ 
+-static void __devinit snd_ice1712_stdsp24_darear(struct snd_ice1712 *ice, int activate)
++static void snd_ice1712_stdsp24_darear(struct snd_ice1712 *ice, int activate)
+ {
+ 	struct hoontech_spec *spec = ice->spec;
+ 	mutex_lock(&ice->gpio_mutex);
+@@ -61,7 +61,7 @@ static void __devinit snd_ice1712_stdsp24_darear(struct snd_ice1712 *ice, int ac
+ 	mutex_unlock(&ice->gpio_mutex);
+ }
+ 
+-static void __devinit snd_ice1712_stdsp24_mute(struct snd_ice1712 *ice, int activate)
++static void snd_ice1712_stdsp24_mute(struct snd_ice1712 *ice, int activate)
+ {
+ 	struct hoontech_spec *spec = ice->spec;
+ 	mutex_lock(&ice->gpio_mutex);
+@@ -70,7 +70,7 @@ static void __devinit snd_ice1712_stdsp24_mute(struct snd_ice1712 *ice, int acti
+ 	mutex_unlock(&ice->gpio_mutex);
+ }
+ 
+-static void __devinit snd_ice1712_stdsp24_insel(struct snd_ice1712 *ice, int activate)
++static void snd_ice1712_stdsp24_insel(struct snd_ice1712 *ice, int activate)
+ {
+ 	struct hoontech_spec *spec = ice->spec;
+ 	mutex_lock(&ice->gpio_mutex);
+@@ -79,7 +79,7 @@ static void __devinit snd_ice1712_stdsp24_insel(struct snd_ice1712 *ice, int act
+ 	mutex_unlock(&ice->gpio_mutex);
+ }
+ 
+-static void __devinit snd_ice1712_stdsp24_box_channel(struct snd_ice1712 *ice, int box, int chn, int activate)
++static void snd_ice1712_stdsp24_box_channel(struct snd_ice1712 *ice, int box, int chn, int activate)
+ {
+ 	struct hoontech_spec *spec = ice->spec;
+ 
+@@ -129,7 +129,7 @@ static void __devinit snd_ice1712_stdsp24_box_channel(struct snd_ice1712 *ice, i
+ 	mutex_unlock(&ice->gpio_mutex);
+ }
+ 
+-static void __devinit snd_ice1712_stdsp24_box_midi(struct snd_ice1712 *ice, int box, int master)
++static void snd_ice1712_stdsp24_box_midi(struct snd_ice1712 *ice, int box, int master)
+ {
+ 	struct hoontech_spec *spec = ice->spec;
+ 
+@@ -157,7 +157,7 @@ static void __devinit snd_ice1712_stdsp24_box_midi(struct snd_ice1712 *ice, int
+ 	mutex_unlock(&ice->gpio_mutex);
+ }
+ 
+-static void __devinit snd_ice1712_stdsp24_midi2(struct snd_ice1712 *ice, int activate)
++static void snd_ice1712_stdsp24_midi2(struct snd_ice1712 *ice, int activate)
+ {
+ 	struct hoontech_spec *spec = ice->spec;
+ 	mutex_lock(&ice->gpio_mutex);
+@@ -166,7 +166,7 @@ static void __devinit snd_ice1712_stdsp24_midi2(struct snd_ice1712 *ice, int act
+ 	mutex_unlock(&ice->gpio_mutex);
+ }
+ 
+-static int __devinit snd_ice1712_hoontech_init(struct snd_ice1712 *ice)
++static int snd_ice1712_hoontech_init(struct snd_ice1712 *ice)
+ {
+ 	struct hoontech_spec *spec;
+ 	int box, chn;
+@@ -266,10 +266,10 @@ static void stdsp24_ak4524_lock(struct snd_akm4xxx *ak, int chip)
+ 	snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ~tmp);
+ }
+ 
+-static int __devinit snd_ice1712_value_init(struct snd_ice1712 *ice)
++static int snd_ice1712_value_init(struct snd_ice1712 *ice)
+ {
+ 	/* Hoontech STDSP24 with modified hardware */
+-	static struct snd_akm4xxx akm_stdsp24_mv __devinitdata = {
++	static struct snd_akm4xxx akm_stdsp24_mv = {
+ 		.num_adcs = 2,
+ 		.num_dacs = 2,
+ 		.type = SND_AK4524,
+@@ -278,7 +278,7 @@ static int __devinit snd_ice1712_value_init(struct snd_ice1712 *ice)
+ 		}
+ 	};
+ 
+-	static struct snd_ak4xxx_private akm_stdsp24_mv_priv __devinitdata = {
++	static struct snd_ak4xxx_private akm_stdsp24_mv_priv = {
+ 		.caddr = 2,
+ 		.cif = 1, /* CIF high */
+ 		.data_mask = ICE1712_STDSP24_SERIAL_DATA,
+@@ -316,7 +316,7 @@ static int __devinit snd_ice1712_value_init(struct snd_ice1712 *ice)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_ice1712_ez8_init(struct snd_ice1712 *ice)
++static int snd_ice1712_ez8_init(struct snd_ice1712 *ice)
+ {
+ 	ice->gpio.write_mask = ice->eeprom.gpiomask;
+ 	ice->gpio.direction = ice->eeprom.gpiodir;
+@@ -328,7 +328,7 @@ static int __devinit snd_ice1712_ez8_init(struct snd_ice1712 *ice)
+ 
+ 
+ /* entry point */
+-struct snd_ice1712_card_info snd_ice1712_hoontech_cards[] __devinitdata = {
++struct snd_ice1712_card_info snd_ice1712_hoontech_cards[] = {
+ 	{
+ 		.subvendor = ICE1712_SUBDEVICE_STDSP24,
+ 		.name = "Hoontech SoundTrack Audio DSP24",
+diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
+index dd64e223f5cf..2ffdc35d5ffd 100644
+--- a/sound/pci/ice1712/ice1712.c
++++ b/sound/pci/ice1712/ice1712.c
+@@ -279,7 +279,7 @@ static int snd_ice1712_digmix_route_ac97_put(struct snd_kcontrol *kcontrol, stru
+ 	return val != nval;
+ }
+ 
+-static struct snd_kcontrol_new snd_ice1712_mixer_digmix_route_ac97 __devinitdata = {
++static struct snd_kcontrol_new snd_ice1712_mixer_digmix_route_ac97 = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "Digital Mixer To AC97",
+ 	.info = snd_ice1712_digmix_route_ac97_info,
+@@ -387,7 +387,7 @@ static void setup_cs8427(struct snd_ice1712 *ice, int rate)
+ /*
+  * create and initialize callbacks for cs8427 interface
+  */
+-int __devinit snd_ice1712_init_cs8427(struct snd_ice1712 *ice, int addr)
++int snd_ice1712_init_cs8427(struct snd_ice1712 *ice, int addr)
+ {
+ 	int err;
+ 
+@@ -878,7 +878,7 @@ static struct snd_pcm_ops snd_ice1712_capture_ops = {
+ 	.pointer =	snd_ice1712_capture_pointer,
+ };
+ 
+-static int __devinit snd_ice1712_pcm(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm)
++static int snd_ice1712_pcm(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -908,7 +908,7 @@ static int __devinit snd_ice1712_pcm(struct snd_ice1712 *ice, int device, struct
+ 	return 0;
+ }
+ 
+-static int __devinit snd_ice1712_pcm_ds(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm)
++static int snd_ice1712_pcm_ds(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -1253,7 +1253,7 @@ static struct snd_pcm_ops snd_ice1712_capture_pro_ops = {
+ 	.pointer =	snd_ice1712_capture_pro_pointer,
+ };
+ 
+-static int __devinit snd_ice1712_pcm_profi(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm)
++static int snd_ice1712_pcm_profi(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -1387,7 +1387,7 @@ static int snd_ice1712_pro_mixer_volume_put(struct snd_kcontrol *kcontrol, struc
+ 
+ static const DECLARE_TLV_DB_SCALE(db_scale_playback, -14400, 150, 0);
+ 
+-static struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] __devinitdata = {
++static struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] = {
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "Multi Playback Switch",
+@@ -1411,7 +1411,7 @@ static struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] __devinitdata
+ 	},
+ };
+ 
+-static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch __devinitdata = {
++static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "H/W Multi Capture Switch",
+ 	.info = snd_ice1712_pro_mixer_switch_info,
+@@ -1420,7 +1420,7 @@ static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch __devinit
+ 	.private_value = 10,
+ };
+ 
+-static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch __devinitdata = {
++static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = SNDRV_CTL_NAME_IEC958("Multi ", CAPTURE, SWITCH),
+ 	.info = snd_ice1712_pro_mixer_switch_info,
+@@ -1430,7 +1430,7 @@ static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch __devinitd
+ 	.count = 2,
+ };
+ 
+-static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume __devinitdata = {
++static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ 		   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
+@@ -1442,7 +1442,7 @@ static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume __devinit
+ 	.tlv = { .p = db_scale_playback }
+ };
+ 
+-static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_volume __devinitdata = {
++static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_volume = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = SNDRV_CTL_NAME_IEC958("Multi ", CAPTURE, VOLUME),
+ 	.info = snd_ice1712_pro_mixer_volume_info,
+@@ -1452,7 +1452,7 @@ static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_volume __devinitd
+ 	.count = 2,
+ };
+ 
+-static int __devinit snd_ice1712_build_pro_mixer(struct snd_ice1712 *ice)
++static int snd_ice1712_build_pro_mixer(struct snd_ice1712 *ice)
+ {
+ 	struct snd_card *card = ice->card;
+ 	unsigned int idx;
+@@ -1511,7 +1511,7 @@ static void snd_ice1712_mixer_free_ac97(struct snd_ac97 *ac97)
+ 	ice->ac97 = NULL;
+ }
+ 
+-static int __devinit snd_ice1712_ac97_mixer(struct snd_ice1712 *ice)
++static int snd_ice1712_ac97_mixer(struct snd_ice1712 *ice)
+ {
+ 	int err, bus_num = 0;
+ 	struct snd_ac97_template ac97;
+@@ -1610,7 +1610,7 @@ static void snd_ice1712_proc_read(struct snd_info_entry *entry,
+ 	snd_iprintf(buffer, "  GPIO_DIRECTION   : 0x%02x\n", (unsigned)snd_ice1712_read(ice, ICE1712_IREG_GPIO_DIRECTION));
+ }
+ 
+-static void __devinit snd_ice1712_proc_init(struct snd_ice1712 *ice)
++static void snd_ice1712_proc_init(struct snd_ice1712 *ice)
+ {
+ 	struct snd_info_entry *entry;
+ 
+@@ -1639,7 +1639,7 @@ static int snd_ice1712_eeprom_get(struct snd_kcontrol *kcontrol,
+ 	return 0;
+ }
+ 
+-static struct snd_kcontrol_new snd_ice1712_eeprom __devinitdata = {
++static struct snd_kcontrol_new snd_ice1712_eeprom = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_CARD,
+ 	.name = "ICE1712 EEPROM",
+ 	.access = SNDRV_CTL_ELEM_ACCESS_READ,
+@@ -1675,7 +1675,7 @@ static int snd_ice1712_spdif_default_put(struct snd_kcontrol *kcontrol,
+ 	return 0;
+ }
+ 
+-static struct snd_kcontrol_new snd_ice1712_spdif_default __devinitdata =
++static struct snd_kcontrol_new snd_ice1712_spdif_default =
+ {
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+ 	.name =         SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
+@@ -1726,7 +1726,7 @@ static int snd_ice1712_spdif_maskp_get(struct snd_kcontrol *kcontrol,
+ 	return 0;
+ }
+ 
+-static struct snd_kcontrol_new snd_ice1712_spdif_maskc __devinitdata =
++static struct snd_kcontrol_new snd_ice1712_spdif_maskc =
+ {
+ 	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+@@ -1735,7 +1735,7 @@ static struct snd_kcontrol_new snd_ice1712_spdif_maskc __devinitdata =
+ 	.get =		snd_ice1712_spdif_maskc_get,
+ };
+ 
+-static struct snd_kcontrol_new snd_ice1712_spdif_maskp __devinitdata =
++static struct snd_kcontrol_new snd_ice1712_spdif_maskp =
+ {
+ 	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+@@ -1762,7 +1762,7 @@ static int snd_ice1712_spdif_stream_put(struct snd_kcontrol *kcontrol,
+ 	return 0;
+ }
+ 
+-static struct snd_kcontrol_new snd_ice1712_spdif_stream __devinitdata =
++static struct snd_kcontrol_new snd_ice1712_spdif_stream =
+ {
+ 	.access =	(SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ 			 SNDRV_CTL_ELEM_ACCESS_INACTIVE),
+@@ -1893,7 +1893,7 @@ static int snd_ice1712_pro_internal_clock_put(struct snd_kcontrol *kcontrol,
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_ice1712_pro_internal_clock __devinitdata = {
++static struct snd_kcontrol_new snd_ice1712_pro_internal_clock = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "Multi Track Internal Clock",
+ 	.info = snd_ice1712_pro_internal_clock_info,
+@@ -1964,7 +1964,7 @@ static int snd_ice1712_pro_internal_clock_default_put(struct snd_kcontrol *kcont
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_ice1712_pro_internal_clock_default __devinitdata = {
++static struct snd_kcontrol_new snd_ice1712_pro_internal_clock_default = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "Multi Track Internal Clock Default",
+ 	.info = snd_ice1712_pro_internal_clock_default_info,
+@@ -1995,7 +1995,7 @@ static int snd_ice1712_pro_rate_locking_put(struct snd_kcontrol *kcontrol,
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_ice1712_pro_rate_locking __devinitdata = {
++static struct snd_kcontrol_new snd_ice1712_pro_rate_locking = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "Multi Track Rate Locking",
+ 	.info = snd_ice1712_pro_rate_locking_info,
+@@ -2026,7 +2026,7 @@ static int snd_ice1712_pro_rate_reset_put(struct snd_kcontrol *kcontrol,
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_ice1712_pro_rate_reset __devinitdata = {
++static struct snd_kcontrol_new snd_ice1712_pro_rate_reset = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "Multi Track Rate Reset",
+ 	.info = snd_ice1712_pro_rate_reset_info,
+@@ -2193,7 +2193,7 @@ static int snd_ice1712_pro_route_spdif_put(struct snd_kcontrol *kcontrol,
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route __devinitdata = {
++static struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "H/W Playback Route",
+ 	.info = snd_ice1712_pro_route_info,
+@@ -2201,7 +2201,7 @@ static struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route __devinitdata
+ 	.put = snd_ice1712_pro_route_analog_put,
+ };
+ 
+-static struct snd_kcontrol_new snd_ice1712_mixer_pro_spdif_route __devinitdata = {
++static struct snd_kcontrol_new snd_ice1712_mixer_pro_spdif_route = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, NONE) "Route",
+ 	.info = snd_ice1712_pro_route_info,
+@@ -2243,7 +2243,7 @@ static int snd_ice1712_pro_volume_rate_put(struct snd_kcontrol *kcontrol,
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_ice1712_mixer_pro_volume_rate __devinitdata = {
++static struct snd_kcontrol_new snd_ice1712_mixer_pro_volume_rate = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "Multi Track Volume Rate",
+ 	.info = snd_ice1712_pro_volume_rate_info,
+@@ -2276,7 +2276,7 @@ static int snd_ice1712_pro_peak_get(struct snd_kcontrol *kcontrol,
+ 	return 0;
+ }
+ 
+-static struct snd_kcontrol_new snd_ice1712_mixer_pro_peak __devinitdata = {
++static struct snd_kcontrol_new snd_ice1712_mixer_pro_peak = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ 	.name = "Multi Track Peak",
+ 	.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+@@ -2291,16 +2291,16 @@ static struct snd_kcontrol_new snd_ice1712_mixer_pro_peak __devinitdata = {
+ /*
+  * list of available boards
+  */
+-static struct snd_ice1712_card_info *card_tables[] __devinitdata = {
++static struct snd_ice1712_card_info *card_tables[] = {
+ 	snd_ice1712_hoontech_cards,
+ 	snd_ice1712_delta_cards,
+ 	snd_ice1712_ews_cards,
+ 	NULL,
+ };
+ 
+-static unsigned char __devinit snd_ice1712_read_i2c(struct snd_ice1712 *ice,
+-						 unsigned char dev,
+-						 unsigned char addr)
++static unsigned char snd_ice1712_read_i2c(struct snd_ice1712 *ice,
++					  unsigned char dev,
++					  unsigned char addr)
+ {
+ 	long t = 0x10000;
+ 
+@@ -2310,8 +2310,8 @@ static unsigned char __devinit snd_ice1712_read_i2c(struct snd_ice1712 *ice,
+ 	return inb(ICEREG(ice, I2C_DATA));
+ }
+ 
+-static int __devinit snd_ice1712_read_eeprom(struct snd_ice1712 *ice,
+-					     const char *modelname)
++static int snd_ice1712_read_eeprom(struct snd_ice1712 *ice,
++				   const char *modelname)
+ {
+ 	int dev = 0xa0;		/* EEPROM device address */
+ 	unsigned int i, size;
+@@ -2385,7 +2385,7 @@ static int __devinit snd_ice1712_read_eeprom(struct snd_ice1712 *ice,
+ 
+ 
+ 
+-static int __devinit snd_ice1712_chip_init(struct snd_ice1712 *ice)
++static int snd_ice1712_chip_init(struct snd_ice1712 *ice)
+ {
+ 	outb(ICE1712_RESET | ICE1712_NATIVE, ICEREG(ice, CONTROL));
+ 	udelay(200);
+@@ -2432,7 +2432,7 @@ static int __devinit snd_ice1712_chip_init(struct snd_ice1712 *ice)
+ 	return 0;
+ }
+ 
+-int __devinit snd_ice1712_spdif_build_controls(struct snd_ice1712 *ice)
++int snd_ice1712_spdif_build_controls(struct snd_ice1712 *ice)
+ {
+ 	int err;
+ 	struct snd_kcontrol *kctl;
+@@ -2460,7 +2460,7 @@ int __devinit snd_ice1712_spdif_build_controls(struct snd_ice1712 *ice)
+ }
+ 
+ 
+-static int __devinit snd_ice1712_build_controls(struct snd_ice1712 *ice)
++static int snd_ice1712_build_controls(struct snd_ice1712 *ice)
+ {
+ 	int err;
+ 
+@@ -2530,13 +2530,13 @@ static int snd_ice1712_dev_free(struct snd_device *device)
+ 	return snd_ice1712_free(ice);
+ }
+ 
+-static int __devinit snd_ice1712_create(struct snd_card *card,
+-					struct pci_dev *pci,
+-					const char *modelname,
+-					int omni,
+-					int cs8427_timeout,
+-					int dxr_enable,
+-					struct snd_ice1712 **r_ice1712)
++static int snd_ice1712_create(struct snd_card *card,
++			      struct pci_dev *pci,
++			      const char *modelname,
++			      int omni,
++			      int cs8427_timeout,
++			      int dxr_enable,
++			      struct snd_ice1712 **r_ice1712)
+ {
+ 	struct snd_ice1712 *ice;
+ 	int err;
+@@ -2650,10 +2650,10 @@ static int __devinit snd_ice1712_create(struct snd_card *card,
+  *
+  */
+ 
+-static struct snd_ice1712_card_info no_matched __devinitdata;
++static struct snd_ice1712_card_info no_matched;
+ 
+-static int __devinit snd_ice1712_probe(struct pci_dev *pci,
+-				       const struct pci_device_id *pci_id)
++static int snd_ice1712_probe(struct pci_dev *pci,
++			     const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -2797,7 +2797,7 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_ice1712_remove(struct pci_dev *pci)
++static void snd_ice1712_remove(struct pci_dev *pci)
+ {
+ 	struct snd_card *card = pci_get_drvdata(pci);
+ 	struct snd_ice1712 *ice = card->private_data;
+@@ -2812,7 +2812,7 @@ static struct pci_driver ice1712_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_ice1712_ids,
+ 	.probe = snd_ice1712_probe,
+-	.remove = __devexit_p(snd_ice1712_remove),
++	.remove = snd_ice1712_remove,
+ };
+ 
+ module_pci_driver(ice1712_driver);
+diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
+index ea99e5695f9f..ce70e7f113e0 100644
+--- a/sound/pci/ice1712/ice1724.c
++++ b/sound/pci/ice1712/ice1724.c
+@@ -1135,7 +1135,7 @@ static struct snd_pcm_ops snd_vt1724_capture_pro_ops = {
+ 	.pointer =	snd_vt1724_pcm_pointer,
+ };
+ 
+-static int __devinit snd_vt1724_pcm_profi(struct snd_ice1712 *ice, int device)
++static int snd_vt1724_pcm_profi(struct snd_ice1712 *ice, int device)
+ {
+ 	struct snd_pcm *pcm;
+ 	int capt, err;
+@@ -1315,7 +1315,7 @@ static struct snd_pcm_ops snd_vt1724_capture_spdif_ops = {
+ };
+ 
+ 
+-static int __devinit snd_vt1724_pcm_spdif(struct snd_ice1712 *ice, int device)
++static int snd_vt1724_pcm_spdif(struct snd_ice1712 *ice, int device)
+ {
+ 	char *name;
+ 	struct snd_pcm *pcm;
+@@ -1449,7 +1449,7 @@ static struct snd_pcm_ops snd_vt1724_playback_indep_ops = {
+ };
+ 
+ 
+-static int __devinit snd_vt1724_pcm_indep(struct snd_ice1712 *ice, int device)
++static int snd_vt1724_pcm_indep(struct snd_ice1712 *ice, int device)
+ {
+ 	struct snd_pcm *pcm;
+ 	int play;
+@@ -1484,7 +1484,7 @@ static int __devinit snd_vt1724_pcm_indep(struct snd_ice1712 *ice, int device)
+  *  Mixer section
+  */
+ 
+-static int __devinit snd_vt1724_ac97_mixer(struct snd_ice1712 *ice)
++static int snd_vt1724_ac97_mixer(struct snd_ice1712 *ice)
+ {
+ 	int err;
+ 
+@@ -1570,7 +1570,7 @@ static void snd_vt1724_proc_read(struct snd_info_entry *entry,
+ 			    idx, inb(ice->profi_port+idx));
+ }
+ 
+-static void __devinit snd_vt1724_proc_init(struct snd_ice1712 *ice)
++static void snd_vt1724_proc_init(struct snd_ice1712 *ice)
+ {
+ 	struct snd_info_entry *entry;
+ 
+@@ -1599,7 +1599,7 @@ static int snd_vt1724_eeprom_get(struct snd_kcontrol *kcontrol,
+ 	return 0;
+ }
+ 
+-static struct snd_kcontrol_new snd_vt1724_eeprom __devinitdata = {
++static struct snd_kcontrol_new snd_vt1724_eeprom = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_CARD,
+ 	.name = "ICE1724 EEPROM",
+ 	.access = SNDRV_CTL_ELEM_ACCESS_READ,
+@@ -1712,7 +1712,7 @@ static int snd_vt1724_spdif_default_put(struct snd_kcontrol *kcontrol,
+ 	return val != old;
+ }
+ 
+-static struct snd_kcontrol_new snd_vt1724_spdif_default __devinitdata =
++static struct snd_kcontrol_new snd_vt1724_spdif_default =
+ {
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+ 	.name =         SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
+@@ -1744,7 +1744,7 @@ static int snd_vt1724_spdif_maskp_get(struct snd_kcontrol *kcontrol,
+ 	return 0;
+ }
+ 
+-static struct snd_kcontrol_new snd_vt1724_spdif_maskc __devinitdata =
++static struct snd_kcontrol_new snd_vt1724_spdif_maskc =
+ {
+ 	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+@@ -1753,7 +1753,7 @@ static struct snd_kcontrol_new snd_vt1724_spdif_maskc __devinitdata =
+ 	.get =		snd_vt1724_spdif_maskc_get,
+ };
+ 
+-static struct snd_kcontrol_new snd_vt1724_spdif_maskp __devinitdata =
++static struct snd_kcontrol_new snd_vt1724_spdif_maskp =
+ {
+ 	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+@@ -1790,7 +1790,7 @@ static int snd_vt1724_spdif_sw_put(struct snd_kcontrol *kcontrol,
+ 	return old != val;
+ }
+ 
+-static struct snd_kcontrol_new snd_vt1724_spdif_switch __devinitdata =
++static struct snd_kcontrol_new snd_vt1724_spdif_switch =
+ {
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	/* FIXME: the following conflict with IEC958 Playback Route */
+@@ -1965,7 +1965,7 @@ static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol,
+ 	return old_rate != new_rate;
+ }
+ 
+-static struct snd_kcontrol_new snd_vt1724_pro_internal_clock __devinitdata = {
++static struct snd_kcontrol_new snd_vt1724_pro_internal_clock = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "Multi Track Internal Clock",
+ 	.info = snd_vt1724_pro_internal_clock_info,
+@@ -1996,7 +1996,7 @@ static int snd_vt1724_pro_rate_locking_put(struct snd_kcontrol *kcontrol,
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_vt1724_pro_rate_locking __devinitdata = {
++static struct snd_kcontrol_new snd_vt1724_pro_rate_locking = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "Multi Track Rate Locking",
+ 	.info = snd_vt1724_pro_rate_locking_info,
+@@ -2027,7 +2027,7 @@ static int snd_vt1724_pro_rate_reset_put(struct snd_kcontrol *kcontrol,
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_vt1724_pro_rate_reset __devinitdata = {
++static struct snd_kcontrol_new snd_vt1724_pro_rate_reset = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "Multi Track Rate Reset",
+ 	.info = snd_vt1724_pro_rate_reset_info,
+@@ -2149,7 +2149,7 @@ static int snd_vt1724_pro_route_spdif_put(struct snd_kcontrol *kcontrol,
+ 					 digital_route_shift(idx));
+ }
+ 
+-static struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route __devinitdata =
++static struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route =
+ {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "H/W Playback Route",
+@@ -2158,7 +2158,7 @@ static struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route __devinitdata =
+ 	.put = snd_vt1724_pro_route_analog_put,
+ };
+ 
+-static struct snd_kcontrol_new snd_vt1724_mixer_pro_spdif_route __devinitdata = {
++static struct snd_kcontrol_new snd_vt1724_mixer_pro_spdif_route = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, NONE) "Route",
+ 	.info = snd_vt1724_pro_route_info,
+@@ -2194,7 +2194,7 @@ static int snd_vt1724_pro_peak_get(struct snd_kcontrol *kcontrol,
+ 	return 0;
+ }
+ 
+-static struct snd_kcontrol_new snd_vt1724_mixer_pro_peak __devinitdata = {
++static struct snd_kcontrol_new snd_vt1724_mixer_pro_peak = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ 	.name = "Multi Track Peak",
+ 	.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+@@ -2206,13 +2206,13 @@ static struct snd_kcontrol_new snd_vt1724_mixer_pro_peak __devinitdata = {
+  *
+  */
+ 
+-static struct snd_ice1712_card_info no_matched __devinitdata;
++static struct snd_ice1712_card_info no_matched;
+ 
+ 
+ /*
+   ooAoo cards with no controls
+ */
+-static unsigned char ooaoo_sq210_eeprom[] __devinitdata = {
++static unsigned char ooaoo_sq210_eeprom[] = {
+ 	[ICE_EEP2_SYSCONF]     = 0x4c,	/* 49MHz crystal, no mpu401, no ADC,
+ 					   1xDACs */
+ 	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
+@@ -2232,7 +2232,7 @@ static unsigned char ooaoo_sq210_eeprom[] __devinitdata = {
+ };
+ 
+ 
+-static struct snd_ice1712_card_info snd_vt1724_ooaoo_cards[] __devinitdata = {
++static struct snd_ice1712_card_info snd_vt1724_ooaoo_cards[] = {
+ 	{
+ 		.name = "ooAoo SQ210a",
+ 		.model = "sq210a",
+@@ -2242,7 +2242,7 @@ static struct snd_ice1712_card_info snd_vt1724_ooaoo_cards[] __devinitdata = {
+ 	{ } /* terminator */
+ };
+ 
+-static struct snd_ice1712_card_info *card_tables[] __devinitdata = {
++static struct snd_ice1712_card_info *card_tables[] = {
+ 	snd_vt1724_revo_cards,
+ 	snd_vt1724_amp_cards,
+ 	snd_vt1724_aureon_cards,
+@@ -2307,8 +2307,8 @@ void snd_vt1724_write_i2c(struct snd_ice1712 *ice,
+ 	mutex_unlock(&ice->i2c_mutex);
+ }
+ 
+-static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice,
+-					    const char *modelname)
++static int snd_vt1724_read_eeprom(struct snd_ice1712 *ice,
++				  const char *modelname)
+ {
+ 	const int dev = 0xa0;		/* EEPROM device address */
+ 	unsigned int i, size;
+@@ -2430,7 +2430,7 @@ static int snd_vt1724_chip_init(struct snd_ice1712 *ice)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_vt1724_spdif_build_controls(struct snd_ice1712 *ice)
++static int snd_vt1724_spdif_build_controls(struct snd_ice1712 *ice)
+ {
+ 	int err;
+ 	struct snd_kcontrol *kctl;
+@@ -2472,7 +2472,7 @@ static int __devinit snd_vt1724_spdif_build_controls(struct snd_ice1712 *ice)
+ }
+ 
+ 
+-static int __devinit snd_vt1724_build_controls(struct snd_ice1712 *ice)
++static int snd_vt1724_build_controls(struct snd_ice1712 *ice)
+ {
+ 	int err;
+ 
+@@ -2532,10 +2532,10 @@ static int snd_vt1724_dev_free(struct snd_device *device)
+ 	return snd_vt1724_free(ice);
+ }
+ 
+-static int __devinit snd_vt1724_create(struct snd_card *card,
+-				       struct pci_dev *pci,
+-				       const char *modelname,
+-				       struct snd_ice1712 **r_ice1712)
++static int snd_vt1724_create(struct snd_card *card,
++			     struct pci_dev *pci,
++			     const char *modelname,
++			     struct snd_ice1712 **r_ice1712)
+ {
+ 	struct snd_ice1712 *ice;
+ 	int err;
+@@ -2622,8 +2622,8 @@ static int __devinit snd_vt1724_create(struct snd_card *card,
+  *
+  */
+ 
+-static int __devinit snd_vt1724_probe(struct pci_dev *pci,
+-				      const struct pci_device_id *pci_id)
++static int snd_vt1724_probe(struct pci_dev *pci,
++			    const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -2792,7 +2792,7 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_vt1724_remove(struct pci_dev *pci)
++static void snd_vt1724_remove(struct pci_dev *pci)
+ {
+ 	struct snd_card *card = pci_get_drvdata(pci);
+ 	struct snd_ice1712 *ice = card->private_data;
+@@ -2900,7 +2900,7 @@ static struct pci_driver vt1724_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_vt1724_ids,
+ 	.probe = snd_vt1724_probe,
+-	.remove = __devexit_p(snd_vt1724_remove),
++	.remove = snd_vt1724_remove,
+ 	.driver = {
+ 		.pm = SND_VT1724_PM_OPS,
+ 	},
+diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c
+index a6b23b421512..8855933e710d 100644
+--- a/sound/pci/ice1712/juli.c
++++ b/sound/pci/ice1712/juli.c
+@@ -282,7 +282,7 @@ static const struct snd_akm4xxx_dac_channel juli_dac[] = {
+ };
+ 
+ 
+-static struct snd_akm4xxx akm_juli_dac __devinitdata = {
++static struct snd_akm4xxx akm_juli_dac = {
+ 	.type = SND_AK4358,
+ 	.num_dacs = 8,	/* DAC1 - analog out
+ 			   DAC2 - analog in monitor
+@@ -357,7 +357,7 @@ static int juli_mute_put(struct snd_kcontrol *kcontrol,
+ 	return 0;
+ }
+ 
+-static struct snd_kcontrol_new juli_mute_controls[] __devinitdata = {
++static struct snd_kcontrol_new juli_mute_controls[] = {
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "Master Playback Switch",
+@@ -411,7 +411,7 @@ static struct snd_kcontrol_new juli_mute_controls[] __devinitdata = {
+ 	},
+ };
+ 
+-static char *slave_vols[] __devinitdata = {
++static char *slave_vols[] = {
+ 	PCM_VOLUME,
+ 	MONITOR_AN_IN_VOLUME,
+ 	MONITOR_DIG_IN_VOLUME,
+@@ -419,11 +419,11 @@ static char *slave_vols[] __devinitdata = {
+ 	NULL
+ };
+ 
+-static __devinitdata
++static
+ DECLARE_TLV_DB_SCALE(juli_master_db_scale, -6350, 50, 1);
+ 
+-static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card,
+-		const char *name)
++static struct snd_kcontrol *ctl_find(struct snd_card *card,
++				     const char *name)
+ {
+ 	struct snd_ctl_elem_id sid;
+ 	memset(&sid, 0, sizeof(sid));
+@@ -433,9 +433,9 @@ static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card,
+ 	return snd_ctl_find_id(card, &sid);
+ }
+ 
+-static void __devinit add_slaves(struct snd_card *card,
+-				 struct snd_kcontrol *master,
+-				 char * const *list)
++static void add_slaves(struct snd_card *card,
++		       struct snd_kcontrol *master,
++		       char * const *list)
+ {
+ 	for (; *list; list++) {
+ 		struct snd_kcontrol *slave = ctl_find(card, *list);
+@@ -447,7 +447,7 @@ static void __devinit add_slaves(struct snd_card *card,
+ 	}
+ }
+ 
+-static int __devinit juli_add_controls(struct snd_ice1712 *ice)
++static int juli_add_controls(struct snd_ice1712 *ice)
+ {
+ 	struct juli_spec *spec = ice->spec;
+ 	int err;
+@@ -579,7 +579,7 @@ static void juli_ak4114_change(struct ak4114 *ak4114, unsigned char c0,
+ 	}
+ }
+ 
+-static int __devinit juli_init(struct snd_ice1712 *ice)
++static int juli_init(struct snd_ice1712 *ice)
+ {
+ 	static const unsigned char ak4114_init_vals[] = {
+ 		/* AK4117_REG_PWRDN */	AK4114_RST | AK4114_PWN |
+@@ -667,7 +667,7 @@ static int __devinit juli_init(struct snd_ice1712 *ice)
+  * hence the driver needs to sets up it properly.
+  */
+ 
+-static unsigned char juli_eeprom[] __devinitdata = {
++static unsigned char juli_eeprom[] = {
+ 	[ICE_EEP2_SYSCONF]     = 0x2b,	/* clock 512, mpu401, 1xADC, 1xDACs,
+ 					   SPDIF in */
+ 	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
+@@ -686,7 +686,7 @@ static unsigned char juli_eeprom[] __devinitdata = {
+ };
+ 
+ /* entry point */
+-struct snd_ice1712_card_info snd_vt1724_juli_cards[] __devinitdata = {
++struct snd_ice1712_card_info snd_vt1724_juli_cards[] = {
+ 	{
+ 		.subvendor = VT1724_SUBDEVICE_JULI,
+ 		.name = "ESI Juli@",
+diff --git a/sound/pci/ice1712/maya44.c b/sound/pci/ice1712/maya44.c
+index d8d749e5ed41..63aa39f06f02 100644
+--- a/sound/pci/ice1712/maya44.c
++++ b/sound/pci/ice1712/maya44.c
+@@ -454,7 +454,7 @@ static int maya_pb_route_put(struct snd_kcontrol *kcontrol,
+  * controls to be added
+  */
+ 
+-static struct snd_kcontrol_new maya_controls[] __devinitdata = {
++static struct snd_kcontrol_new maya_controls[] = {
+ 	{
+ 		.name = "Crossmix Playback Volume",
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+@@ -544,7 +544,7 @@ static struct snd_kcontrol_new maya_controls[] __devinitdata = {
+ 	},
+ };
+ 
+-static int __devinit maya44_add_controls(struct snd_ice1712 *ice)
++static int maya44_add_controls(struct snd_ice1712 *ice)
+ {
+ 	int err, i;
+ 
+@@ -561,8 +561,8 @@ static int __devinit maya44_add_controls(struct snd_ice1712 *ice)
+ /*
+  * initialize a wm8776 chip
+  */
+-static void __devinit wm8776_init(struct snd_ice1712 *ice,
+-				  struct snd_wm8776 *wm, unsigned int addr)
++static void wm8776_init(struct snd_ice1712 *ice,
++			struct snd_wm8776 *wm, unsigned int addr)
+ {
+ 	static const unsigned short inits_wm8776[] = {
+ 		0x02, 0x100, /* R2: headphone L+R muted + update */
+@@ -692,14 +692,14 @@ static struct snd_pcm_hw_constraint_list dac_rates = {
+ /*
+  * chip addresses on I2C bus
+  */
+-static unsigned char wm8776_addr[2] __devinitdata = {
++static unsigned char wm8776_addr[2] = {
+ 	0x34, 0x36, /* codec 0 & 1 */
+ };
+ 
+ /*
+  * initialize the chip
+  */
+-static int __devinit maya44_init(struct snd_ice1712 *ice)
++static int maya44_init(struct snd_ice1712 *ice)
+ {
+ 	int i;
+ 	struct snd_maya44 *chip;
+@@ -742,7 +742,7 @@ static int __devinit maya44_init(struct snd_ice1712 *ice)
+  * hence the driver needs to sets up it properly.
+  */
+ 
+-static unsigned char maya44_eeprom[] __devinitdata = {
++static unsigned char maya44_eeprom[] = {
+ 	[ICE_EEP2_SYSCONF]     = 0x45,
+ 		/* clock xin1=49.152MHz, mpu401, 2 stereo ADCs+DACs */
+ 	[ICE_EEP2_ACLINK]      = 0x80,
+@@ -764,7 +764,7 @@ static unsigned char maya44_eeprom[] __devinitdata = {
+ };
+ 
+ /* entry point */
+-struct snd_ice1712_card_info snd_vt1724_maya44_cards[] __devinitdata = {
++struct snd_ice1712_card_info snd_vt1724_maya44_cards[] = {
+ 	{
+ 		.subvendor = VT1724_SUBDEVICE_MAYA44,
+ 		.name = "ESI Maya44",
+diff --git a/sound/pci/ice1712/phase.c b/sound/pci/ice1712/phase.c
+index c9be75a457c3..0011e04f36a2 100644
+--- a/sound/pci/ice1712/phase.c
++++ b/sound/pci/ice1712/phase.c
+@@ -102,13 +102,13 @@ static const unsigned char wm_vol[256] = {
+ #define WM_VOL_MAX	(sizeof(wm_vol) - 1)
+ #define WM_VOL_MUTE	0x8000
+ 
+-static struct snd_akm4xxx akm_phase22 __devinitdata = {
++static struct snd_akm4xxx akm_phase22 = {
+ 	.type = SND_AK4524,
+ 	.num_dacs = 2,
+ 	.num_adcs = 2,
+ };
+ 
+-static struct snd_ak4xxx_private akm_phase22_priv __devinitdata = {
++static struct snd_ak4xxx_private akm_phase22_priv = {
+ 	.caddr =	2,
+ 	.cif =		1,
+ 	.data_mask =	1 << 4,
+@@ -120,7 +120,7 @@ static struct snd_ak4xxx_private akm_phase22_priv __devinitdata = {
+ 	.mask_flags =	0,
+ };
+ 
+-static int __devinit phase22_init(struct snd_ice1712 *ice)
++static int phase22_init(struct snd_ice1712 *ice)
+ {
+ 	struct snd_akm4xxx *ak;
+ 	int err;
+@@ -157,7 +157,7 @@ static int __devinit phase22_init(struct snd_ice1712 *ice)
+ 	return 0;
+ }
+ 
+-static int __devinit phase22_add_controls(struct snd_ice1712 *ice)
++static int phase22_add_controls(struct snd_ice1712 *ice)
+ {
+ 	int err = 0;
+ 
+@@ -171,7 +171,7 @@ static int __devinit phase22_add_controls(struct snd_ice1712 *ice)
+ 	return 0;
+ }
+ 
+-static unsigned char phase22_eeprom[] __devinitdata = {
++static unsigned char phase22_eeprom[] = {
+ 	[ICE_EEP2_SYSCONF]     = 0x28,  /* clock 512, mpu 401,
+ 					spdif-in/1xADC, 1xDACs */
+ 	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
+@@ -188,7 +188,7 @@ static unsigned char phase22_eeprom[] __devinitdata = {
+ 	[ICE_EEP2_GPIO_STATE2] = 0x00,
+ };
+ 
+-static unsigned char phase28_eeprom[] __devinitdata = {
++static unsigned char phase28_eeprom[] = {
+ 	[ICE_EEP2_SYSCONF]     = 0x2b,  /* clock 512, mpu401,
+ 					spdif-in/1xADC, 4xDACs */
+ 	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
+@@ -378,7 +378,7 @@ static int wm_master_vol_put(struct snd_kcontrol *kcontrol,
+ 	return change;
+ }
+ 
+-static int __devinit phase28_init(struct snd_ice1712 *ice)
++static int phase28_init(struct snd_ice1712 *ice)
+ {
+ 	static const unsigned short wm_inits_phase28[] = {
+ 		/* These come first to reduce init pop noise */
+@@ -769,7 +769,7 @@ static int phase28_oversampling_put(struct snd_kcontrol *kcontrol,
+ static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
+ static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
+ 
+-static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = {
++static struct snd_kcontrol_new phase28_dac_controls[] = {
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "Master Playback Switch",
+@@ -884,7 +884,7 @@ static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = {
+ 	}
+ };
+ 
+-static struct snd_kcontrol_new wm_controls[] __devinitdata = {
++static struct snd_kcontrol_new wm_controls[] = {
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "PCM Playback Switch",
+@@ -918,7 +918,7 @@ static struct snd_kcontrol_new wm_controls[] __devinitdata = {
+ 	}
+ };
+ 
+-static int __devinit phase28_add_controls(struct snd_ice1712 *ice)
++static int phase28_add_controls(struct snd_ice1712 *ice)
+ {
+ 	unsigned int i, counts;
+ 	int err;
+@@ -942,7 +942,7 @@ static int __devinit phase28_add_controls(struct snd_ice1712 *ice)
+ 	return 0;
+ }
+ 
+-struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = {
++struct snd_ice1712_card_info snd_vt1724_phase_cards[] = {
+ 	{
+ 		.subvendor = VT1724_SUBDEVICE_PHASE22,
+ 		.name = "Terratec PHASE 22",
+diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c
+index 3ce1289263a3..5555eb4b2400 100644
+--- a/sound/pci/ice1712/pontis.c
++++ b/sound/pci/ice1712/pontis.c
+@@ -549,7 +549,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_volume, -6400, 50, 1);
+  * mixers
+  */
+ 
+-static struct snd_kcontrol_new pontis_controls[] __devinitdata = {
++static struct snd_kcontrol_new pontis_controls[] = {
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+@@ -696,7 +696,7 @@ static void cs_proc_init(struct snd_ice1712 *ice)
+ }
+ 
+ 
+-static int __devinit pontis_add_controls(struct snd_ice1712 *ice)
++static int pontis_add_controls(struct snd_ice1712 *ice)
+ {
+ 	unsigned int i;
+ 	int err;
+@@ -717,7 +717,7 @@ static int __devinit pontis_add_controls(struct snd_ice1712 *ice)
+ /*
+  * initialize the chip
+  */
+-static int __devinit pontis_init(struct snd_ice1712 *ice)
++static int pontis_init(struct snd_ice1712 *ice)
+ {
+ 	static const unsigned short wm_inits[] = {
+ 		/* These come first to reduce init pop noise */
+@@ -804,7 +804,7 @@ static int __devinit pontis_init(struct snd_ice1712 *ice)
+  * hence the driver needs to sets up it properly.
+  */
+ 
+-static unsigned char pontis_eeprom[] __devinitdata = {
++static unsigned char pontis_eeprom[] = {
+ 	[ICE_EEP2_SYSCONF]     = 0x08,	/* clock 256, mpu401, spdif-in/ADC, 1DAC */
+ 	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
+ 	[ICE_EEP2_I2S]         = 0xf8,	/* vol, 96k, 24bit, 192k */
+@@ -821,7 +821,7 @@ static unsigned char pontis_eeprom[] __devinitdata = {
+ };
+ 
+ /* entry point */
+-struct snd_ice1712_card_info snd_vt1720_pontis_cards[] __devinitdata = {
++struct snd_ice1712_card_info snd_vt1720_pontis_cards[] = {
+ 	{
+ 		.subvendor = VT1720_SUBDEVICE_PONTIS_MS300,
+ 		.name = "Pontis MS300",
+diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c
+index 3fcf581e7ef8..e610339f7601 100644
+--- a/sound/pci/ice1712/prodigy192.c
++++ b/sound/pci/ice1712/prodigy192.c
+@@ -368,7 +368,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0);
+  * mixers
+  */
+ 
+-static struct snd_kcontrol_new stac_controls[] __devinitdata = {
++static struct snd_kcontrol_new stac_controls[] = {
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "Master Playback Switch",
+@@ -606,7 +606,7 @@ static int ak4114_input_sw_put(struct snd_kcontrol *kcontrol,
+ }
+ 
+ 
+-static struct snd_kcontrol_new ak4114_controls[] __devinitdata = {
++static struct snd_kcontrol_new ak4114_controls[] = {
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "MIODIO IEC958 Capture Input",
+@@ -671,7 +671,7 @@ static void stac9460_proc_init(struct snd_ice1712 *ice)
+ }
+ 
+ 
+-static int __devinit prodigy192_add_controls(struct snd_ice1712 *ice)
++static int prodigy192_add_controls(struct snd_ice1712 *ice)
+ {
+ 	struct prodigy192_spec *spec = ice->spec;
+ 	unsigned int i;
+@@ -727,7 +727,7 @@ static int prodigy192_miodio_exists(struct snd_ice1712 *ice)
+ /*
+  * initialize the chip
+  */
+-static int __devinit prodigy192_init(struct snd_ice1712 *ice)
++static int prodigy192_init(struct snd_ice1712 *ice)
+ {
+ 	static const unsigned short stac_inits_prodigy[] = {
+ 		STAC946X_RESET, 0,
+@@ -783,7 +783,7 @@ static int __devinit prodigy192_init(struct snd_ice1712 *ice)
+  * hence the driver needs to sets up it properly.
+  */
+ 
+-static unsigned char prodigy71_eeprom[] __devinitdata = {
++static unsigned char prodigy71_eeprom[] = {
+ 	[ICE_EEP2_SYSCONF]     = 0x6a,	/* 49MHz crystal, mpu401,
+ 					 * spdif-in+ 1 stereo ADC,
+ 					 * 3 stereo DACs
+@@ -807,7 +807,7 @@ static unsigned char prodigy71_eeprom[] __devinitdata = {
+ 
+ 
+ /* entry point */
+-struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[] __devinitdata = {
++struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[] = {
+ 	{
+ 		.subvendor = VT1724_SUBDEVICE_PRODIGY192VE,
+ 		.name = "Audiotrak Prodigy 192",
+diff --git a/sound/pci/ice1712/prodigy_hifi.c b/sound/pci/ice1712/prodigy_hifi.c
+index 4fea87fb5799..2261d1e49150 100644
+--- a/sound/pci/ice1712/prodigy_hifi.c
++++ b/sound/pci/ice1712/prodigy_hifi.c
+@@ -298,7 +298,7 @@ static int ak4396_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem
+ static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
+ static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);
+ 
+-static struct snd_kcontrol_new prodigy_hd2_controls[] __devinitdata = {
++static struct snd_kcontrol_new prodigy_hd2_controls[] = {
+     {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+@@ -781,7 +781,7 @@ static int wm_chswap_put(struct snd_kcontrol *kcontrol,
+  * mixers
+  */
+ 
+-static struct snd_kcontrol_new prodigy_hifi_controls[] __devinitdata = {
++static struct snd_kcontrol_new prodigy_hifi_controls[] = {
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+@@ -938,7 +938,7 @@ static void wm_proc_init(struct snd_ice1712 *ice)
+ 	}
+ }
+ 
+-static int __devinit prodigy_hifi_add_controls(struct snd_ice1712 *ice)
++static int prodigy_hifi_add_controls(struct snd_ice1712 *ice)
+ {
+ 	unsigned int i;
+ 	int err;
+@@ -955,7 +955,7 @@ static int __devinit prodigy_hifi_add_controls(struct snd_ice1712 *ice)
+ 	return 0;
+ }
+ 
+-static int __devinit prodigy_hd2_add_controls(struct snd_ice1712 *ice)
++static int prodigy_hd2_add_controls(struct snd_ice1712 *ice)
+ {
+ 	unsigned int i;
+ 	int err;
+@@ -976,7 +976,7 @@ static int __devinit prodigy_hd2_add_controls(struct snd_ice1712 *ice)
+ /*
+  * initialize the chip
+  */
+-static int __devinit prodigy_hifi_init(struct snd_ice1712 *ice)
++static int prodigy_hifi_init(struct snd_ice1712 *ice)
+ {
+ 	static unsigned short wm_inits[] = {
+ 		/* These come first to reduce init pop noise */
+@@ -1114,7 +1114,7 @@ static int prodigy_hd2_resume(struct snd_ice1712 *ice)
+ }
+ #endif
+ 
+-static int __devinit prodigy_hd2_init(struct snd_ice1712 *ice)
++static int prodigy_hd2_init(struct snd_ice1712 *ice)
+ {
+ 	struct prodigy_hifi_spec *spec;
+ 
+@@ -1151,7 +1151,7 @@ static int __devinit prodigy_hd2_init(struct snd_ice1712 *ice)
+ }
+ 
+ 
+-static unsigned char prodigy71hifi_eeprom[] __devinitdata = {
++static unsigned char prodigy71hifi_eeprom[] = {
+ 	0x4b,   /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
+ 	0x80,   /* ACLINK: I2S */
+ 	0xfc,   /* I2S: vol, 96k, 24bit, 192k */
+@@ -1167,7 +1167,7 @@ static unsigned char prodigy71hifi_eeprom[] __devinitdata = {
+ 	0x00,   /* GPIO_STATE2 */
+ };
+ 
+-static unsigned char prodigyhd2_eeprom[] __devinitdata = {
++static unsigned char prodigyhd2_eeprom[] = {
+ 	0x4b,   /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
+ 	0x80,   /* ACLINK: I2S */
+ 	0xfc,   /* I2S: vol, 96k, 24bit, 192k */
+@@ -1183,7 +1183,7 @@ static unsigned char prodigyhd2_eeprom[] __devinitdata = {
+ 	0x00,   /* GPIO_STATE2 */
+ };
+ 
+-static unsigned char fortissimo4_eeprom[] __devinitdata = {
++static unsigned char fortissimo4_eeprom[] = {
+ 	0x43,   /* SYSCONF: clock 512, ADC, 4DACs */	
+ 	0x80,   /* ACLINK: I2S */
+ 	0xfc,   /* I2S: vol, 96k, 24bit, 192k */
+@@ -1200,7 +1200,7 @@ static unsigned char fortissimo4_eeprom[] __devinitdata = {
+ };
+ 
+ /* entry point */
+-struct snd_ice1712_card_info snd_vt1724_prodigy_hifi_cards[] __devinitdata = {
++struct snd_ice1712_card_info snd_vt1724_prodigy_hifi_cards[] = {
+ 	{
+ 		.subvendor = VT1724_SUBDEVICE_PRODIGY_HIFI,
+ 		.name = "Audiotrak Prodigy 7.1 HiFi",
+diff --git a/sound/pci/ice1712/psc724.c b/sound/pci/ice1712/psc724.c
+index 0b6c4e69b8d0..302ac6ddd545 100644
+--- a/sound/pci/ice1712/psc724.c
++++ b/sound/pci/ice1712/psc724.c
+@@ -316,7 +316,7 @@ static const char *clfe_deemph	= "CLFE Deemphasis Playback Switch";
+ static const char *rear_clfe_izd = "Rear Infinite Zero Detect Playback Switch";
+ static const char *rear_clfe_zc	= "Rear Zero Cross Detect Playback Switch";
+ 
+-static int __devinit psc724_add_controls(struct snd_ice1712 *ice)
++static int psc724_add_controls(struct snd_ice1712 *ice)
+ {
+ 	struct snd_kcontrol_new cont;
+ 	struct snd_kcontrol *ctl;
+@@ -396,7 +396,7 @@ static int psc724_resume(struct snd_ice1712 *ice)
+ 
+ /* init */
+ 
+-static int __devinit psc724_init(struct snd_ice1712 *ice)
++static int psc724_init(struct snd_ice1712 *ice)
+ {
+ 	struct psc724_spec *spec;
+ 
+@@ -434,7 +434,7 @@ static void psc724_exit(struct snd_ice1712 *ice)
+ }
+ 
+ /* PSC724 has buggy EEPROM (no 96&192kHz, all FFh GPIOs), so override it here */
+-static unsigned char psc724_eeprom[] __devinitdata = {
++static unsigned char psc724_eeprom[] = {
+ 	[ICE_EEP2_SYSCONF]	= 0x42,	/* 49.152MHz, 1 ADC, 3 DACs */
+ 	[ICE_EEP2_ACLINK]	= 0x80,	/* I2S */
+ 	[ICE_EEP2_I2S]		= 0xf0,	/* I2S volume, 96kHz, 24bit */
+@@ -449,7 +449,7 @@ static unsigned char psc724_eeprom[] __devinitdata = {
+ 	[ICE_EEP2_GPIO_STATE2]	= 0x20,	/* unmuted, all WM8766 pins low */
+ };
+ 
+-struct snd_ice1712_card_info snd_vt1724_psc724_cards[] __devinitdata = {
++struct snd_ice1712_card_info snd_vt1724_psc724_cards[] = {
+ 	{
+ 		.subvendor = VT1724_SUBDEVICE_PSC724,
+ 		.name = "Philips PSC724 Ultimate Edge",
+diff --git a/sound/pci/ice1712/quartet.c b/sound/pci/ice1712/quartet.c
+index c85b2ff79115..975e0357bd5a 100644
+--- a/sound/pci/ice1712/quartet.c
++++ b/sound/pci/ice1712/quartet.c
+@@ -386,7 +386,7 @@ static const struct snd_akm4xxx_adc_channel qtet_adc[] = {
+ 	AK_CONTROL(PCM_34_CAPTURE_VOLUME, 2),
+ };
+ 
+-static struct snd_akm4xxx akm_qtet_dac __devinitdata = {
++static struct snd_akm4xxx akm_qtet_dac = {
+ 	.type = SND_AK4620,
+ 	.num_dacs = 4,	/* DAC1 - Output 12
+ 	*/
+@@ -758,7 +758,7 @@ static int qtet_sw_put(struct snd_kcontrol *kcontrol,
+ 	.put = qtet_sw_put,\
+ 	.private_value = xpriv }
+ 
+-static struct snd_kcontrol_new qtet_controls[] __devinitdata = {
++static struct snd_kcontrol_new qtet_controls[] = {
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "Master Playback Switch",
+@@ -795,17 +795,17 @@ static struct snd_kcontrol_new qtet_controls[] __devinitdata = {
+ 	QTET_CONTROL("Output 3/4 to Monitor 1/2", sw, OUT34_MON12),
+ };
+ 
+-static char *slave_vols[] __devinitdata = {
++static char *slave_vols[] = {
+ 	PCM_12_PLAYBACK_VOLUME,
+ 	PCM_34_PLAYBACK_VOLUME,
+ 	NULL
+ };
+ 
+-static __devinitdata
++static
+ DECLARE_TLV_DB_SCALE(qtet_master_db_scale, -6350, 50, 1);
+ 
+-static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card,
+-		const char *name)
++static struct snd_kcontrol *ctl_find(struct snd_card *card,
++				     const char *name)
+ {
+ 	struct snd_ctl_elem_id sid;
+ 	memset(&sid, 0, sizeof(sid));
+@@ -815,8 +815,8 @@ static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card,
+ 	return snd_ctl_find_id(card, &sid);
+ }
+ 
+-static void __devinit add_slaves(struct snd_card *card,
+-		struct snd_kcontrol *master, char * const *list)
++static void add_slaves(struct snd_card *card,
++		       struct snd_kcontrol *master, char * const *list)
+ {
+ 	for (; *list; list++) {
+ 		struct snd_kcontrol *slave = ctl_find(card, *list);
+@@ -825,7 +825,7 @@ static void __devinit add_slaves(struct snd_card *card,
+ 	}
+ }
+ 
+-static int __devinit qtet_add_controls(struct snd_ice1712 *ice)
++static int qtet_add_controls(struct snd_ice1712 *ice)
+ {
+ 	struct qtet_spec *spec = ice->spec;
+ 	int err, i;
+@@ -1007,7 +1007,7 @@ static void qtet_spdif_in_open(struct snd_ice1712 *ice,
+ /*
+  * initialize the chip
+  */
+-static int __devinit qtet_init(struct snd_ice1712 *ice)
++static int qtet_init(struct snd_ice1712 *ice)
+ {
+ 	static const unsigned char ak4113_init_vals[] = {
+ 		/* AK4113_REG_PWRDN */	AK4113_RST | AK4113_PWN |
+@@ -1095,7 +1095,7 @@ static int __devinit qtet_init(struct snd_ice1712 *ice)
+ 	return 0;
+ }
+ 
+-static unsigned char qtet_eeprom[] __devinitdata = {
++static unsigned char qtet_eeprom[] = {
+ 	[ICE_EEP2_SYSCONF]     = 0x28,	/* clock 256(24MHz), mpu401, 1xADC,
+ 					   1xDACs, SPDIF in */
+ 	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
+@@ -1116,7 +1116,7 @@ static unsigned char qtet_eeprom[] __devinitdata = {
+ };
+ 
+ /* entry point */
+-struct snd_ice1712_card_info snd_vt1724_qtet_cards[] __devinitdata = {
++struct snd_ice1712_card_info snd_vt1724_qtet_cards[] = {
+ 	{
+ 		.subvendor = VT1724_SUBDEVICE_QTET,
+ 		.name = "Infrasonic Quartet",
+diff --git a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c
+index a1b79758766b..7641080a9b5d 100644
+--- a/sound/pci/ice1712/revo.c
++++ b/sound/pci/ice1712/revo.c
+@@ -234,7 +234,7 @@ static const struct snd_akm4xxx_adc_channel revo51_adc[] = {
+ 	},
+ };
+ 
+-static struct snd_akm4xxx akm_revo_front __devinitdata = {
++static struct snd_akm4xxx akm_revo_front = {
+ 	.type = SND_AK4381,
+ 	.num_dacs = 2,
+ 	.ops = {
+@@ -243,7 +243,7 @@ static struct snd_akm4xxx akm_revo_front __devinitdata = {
+ 	.dac_info = revo71_front,
+ };
+ 
+-static struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = {
++static struct snd_ak4xxx_private akm_revo_front_priv = {
+ 	.caddr = 1,
+ 	.cif = 0,
+ 	.data_mask = VT1724_REVO_CDOUT,
+@@ -255,7 +255,7 @@ static struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = {
+ 	.mask_flags = 0,
+ };
+ 
+-static struct snd_akm4xxx akm_revo_surround __devinitdata = {
++static struct snd_akm4xxx akm_revo_surround = {
+ 	.type = SND_AK4355,
+ 	.idx_offset = 1,
+ 	.num_dacs = 6,
+@@ -265,7 +265,7 @@ static struct snd_akm4xxx akm_revo_surround __devinitdata = {
+ 	.dac_info = revo71_surround,
+ };
+ 
+-static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = {
++static struct snd_ak4xxx_private akm_revo_surround_priv = {
+ 	.caddr = 3,
+ 	.cif = 0,
+ 	.data_mask = VT1724_REVO_CDOUT,
+@@ -277,7 +277,7 @@ static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = {
+ 	.mask_flags = 0,
+ };
+ 
+-static struct snd_akm4xxx akm_revo51 __devinitdata = {
++static struct snd_akm4xxx akm_revo51 = {
+ 	.type = SND_AK4358,
+ 	.num_dacs = 8,
+ 	.ops = {
+@@ -286,7 +286,7 @@ static struct snd_akm4xxx akm_revo51 __devinitdata = {
+ 	.dac_info = revo51_dac,
+ };
+ 
+-static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = {
++static struct snd_ak4xxx_private akm_revo51_priv = {
+ 	.caddr = 2,
+ 	.cif = 0,
+ 	.data_mask = VT1724_REVO_CDOUT,
+@@ -298,13 +298,13 @@ static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = {
+ 	.mask_flags = 0,
+ };
+ 
+-static struct snd_akm4xxx akm_revo51_adc __devinitdata = {
++static struct snd_akm4xxx akm_revo51_adc = {
+ 	.type = SND_AK5365,
+ 	.num_adcs = 2,
+ 	.adc_info = revo51_adc,
+ };
+ 
+-static struct snd_ak4xxx_private akm_revo51_adc_priv __devinitdata = {
++static struct snd_ak4xxx_private akm_revo51_adc_priv = {
+ 	.caddr = 2,
+ 	.cif = 0,
+ 	.data_mask = VT1724_REVO_CDOUT,
+@@ -345,7 +345,7 @@ static const struct snd_akm4xxx_dac_channel ap192_dac[] = {
+ 	AK_DAC("PCM Playback Volume", 2)
+ };
+ 
+-static struct snd_akm4xxx akm_ap192 __devinitdata = {
++static struct snd_akm4xxx akm_ap192 = {
+ 	.type = SND_AK4358,
+ 	.num_dacs = 2,
+ 	.ops = {
+@@ -354,7 +354,7 @@ static struct snd_akm4xxx akm_ap192 __devinitdata = {
+ 	.dac_info = ap192_dac,
+ };
+ 
+-static struct snd_ak4xxx_private akm_ap192_priv __devinitdata = {
++static struct snd_ak4xxx_private akm_ap192_priv = {
+ 	.caddr = 2,
+ 	.cif = 0,
+ 	.data_mask = VT1724_REVO_CDOUT,
+@@ -467,7 +467,7 @@ static unsigned char ap192_ak4114_read(void *private_data, unsigned char addr)
+ 	return data;
+ }
+ 
+-static int __devinit ap192_ak4114_init(struct snd_ice1712 *ice)
++static int ap192_ak4114_init(struct snd_ice1712 *ice)
+ {
+ 	static const unsigned char ak4114_init_vals[] = {
+ 		AK4114_RST | AK4114_PWN | AK4114_OCKS0 | AK4114_OCKS1,
+@@ -495,7 +495,7 @@ static int __devinit ap192_ak4114_init(struct snd_ice1712 *ice)
+ 	return 0; /* error ignored; it's no fatal error */
+ }
+ 
+-static int __devinit revo_init(struct snd_ice1712 *ice)
++static int revo_init(struct snd_ice1712 *ice)
+ {
+ 	struct snd_akm4xxx *ak;
+ 	int err;
+@@ -573,7 +573,7 @@ static int __devinit revo_init(struct snd_ice1712 *ice)
+ }
+ 
+ 
+-static int __devinit revo_add_controls(struct snd_ice1712 *ice)
++static int revo_add_controls(struct snd_ice1712 *ice)
+ {
+ 	struct revo51_spec *spec;
+ 	int err;
+@@ -606,7 +606,7 @@ static int __devinit revo_add_controls(struct snd_ice1712 *ice)
+ }
+ 
+ /* entry point */
+-struct snd_ice1712_card_info snd_vt1724_revo_cards[] __devinitdata = {
++struct snd_ice1712_card_info snd_vt1724_revo_cards[] = {
+ 	{
+ 		.subvendor = VT1724_SUBDEVICE_REVOLUTION71,
+ 		.name = "M Audio Revolution-7.1",
+diff --git a/sound/pci/ice1712/se.c b/sound/pci/ice1712/se.c
+index 53b555f5bbea..ffd894bb4507 100644
+--- a/sound/pci/ice1712/se.c
++++ b/sound/pci/ice1712/se.c
+@@ -113,7 +113,7 @@ struct se_spec {
+ /*  WM8740 interface                                                        */
+ /****************************************************************************/
+ 
+-static void __devinit se200pci_WM8740_init(struct snd_ice1712 *ice)
++static void se200pci_WM8740_init(struct snd_ice1712 *ice)
+ {
+ 	/* nothing to do */
+ }
+@@ -195,7 +195,7 @@ static void se200pci_WM8766_set_volume(struct snd_ice1712 *ice, int ch,
+ 	}
+ }
+ 
+-static void __devinit se200pci_WM8766_init(struct snd_ice1712 *ice)
++static void se200pci_WM8766_init(struct snd_ice1712 *ice)
+ {
+ 	se200pci_WM8766_write(ice, 0x1f, 0x000); /* RESET ALL */
+ 	udelay(10);
+@@ -299,10 +299,10 @@ static void se200pci_WM8776_set_agc(struct snd_ice1712 *ice, unsigned int agc)
+ 	}
+ }
+ 
+-static void __devinit se200pci_WM8776_init(struct snd_ice1712 *ice)
++static void se200pci_WM8776_init(struct snd_ice1712 *ice)
+ {
+ 	int i;
+-	static unsigned short __devinitdata default_values[] = {
++	static unsigned short default_values[] = {
+ 		0x100, 0x100, 0x100,
+ 		0x100, 0x100, 0x100,
+ 		0x000, 0x090, 0x000, 0x000,
+@@ -599,7 +599,7 @@ static int se200pci_cont_enum_put(struct snd_kcontrol *kc,
+ static const DECLARE_TLV_DB_SCALE(db_scale_gain1, -12750, 50, 1);
+ static const DECLARE_TLV_DB_SCALE(db_scale_gain2, -10350, 50, 1);
+ 
+-static int __devinit se200pci_add_controls(struct snd_ice1712 *ice)
++static int se200pci_add_controls(struct snd_ice1712 *ice)
+ {
+ 	int i;
+ 	struct snd_kcontrol_new cont;
+@@ -677,7 +677,7 @@ static int __devinit se200pci_add_controls(struct snd_ice1712 *ice)
+ /*  probe/initialize/setup                                                  */
+ /****************************************************************************/
+ 
+-static int __devinit se_init(struct snd_ice1712 *ice)
++static int se_init(struct snd_ice1712 *ice)
+ {
+ 	struct se_spec *spec;
+ 
+@@ -705,7 +705,7 @@ static int __devinit se_init(struct snd_ice1712 *ice)
+ 	return -ENOENT;
+ }
+ 
+-static int __devinit se_add_controls(struct snd_ice1712 *ice)
++static int se_add_controls(struct snd_ice1712 *ice)
+ {
+ 	int err;
+ 
+@@ -722,7 +722,7 @@ static int __devinit se_add_controls(struct snd_ice1712 *ice)
+ /*  entry point                                                             */
+ /****************************************************************************/
+ 
+-static unsigned char se200pci_eeprom[] __devinitdata = {
++static unsigned char se200pci_eeprom[] = {
+ 	[ICE_EEP2_SYSCONF]	= 0x4b,	/* 49.152Hz, spdif-in/ADC, 4DACs */
+ 	[ICE_EEP2_ACLINK]	= 0x80,	/* I2S */
+ 	[ICE_EEP2_I2S]		= 0x78,	/* 96k-ok, 24bit, 192k-ok */
+@@ -741,7 +741,7 @@ static unsigned char se200pci_eeprom[] __devinitdata = {
+ 	[ICE_EEP2_GPIO_STATE2]	= 0x07, /* WM8766 ML/MC/MD */
+ };
+ 
+-static unsigned char se90pci_eeprom[] __devinitdata = {
++static unsigned char se90pci_eeprom[] = {
+ 	[ICE_EEP2_SYSCONF]	= 0x4b,	/* 49.152Hz, spdif-in/ADC, 4DACs */
+ 	[ICE_EEP2_ACLINK]	= 0x80,	/* I2S */
+ 	[ICE_EEP2_I2S]		= 0x78,	/* 96k-ok, 24bit, 192k-ok */
+@@ -750,7 +750,7 @@ static unsigned char se90pci_eeprom[] __devinitdata = {
+ 	/* ALL GPIO bits are in input mode */
+ };
+ 
+-struct snd_ice1712_card_info snd_vt1724_se_cards[] __devinitdata = {
++struct snd_ice1712_card_info snd_vt1724_se_cards[] = {
+ 	{
+ 		.subvendor = VT1724_SUBDEVICE_SE200PCI,
+ 		.name = "ONKYO SE200PCI",
+diff --git a/sound/pci/ice1712/vt1720_mobo.c b/sound/pci/ice1712/vt1720_mobo.c
+index 8a0a8393ad9e..5dbb867e642c 100644
+--- a/sound/pci/ice1712/vt1720_mobo.c
++++ b/sound/pci/ice1712/vt1720_mobo.c
+@@ -31,7 +31,7 @@
+ #include "vt1720_mobo.h"
+ 
+ 
+-static int __devinit k8x800_init(struct snd_ice1712 *ice)
++static int k8x800_init(struct snd_ice1712 *ice)
+ {
+ 	ice->vt1720 = 1;
+ 
+@@ -45,7 +45,7 @@ static int __devinit k8x800_init(struct snd_ice1712 *ice)
+ 	return 0;
+ }
+ 
+-static int __devinit k8x800_add_controls(struct snd_ice1712 *ice)
++static int k8x800_add_controls(struct snd_ice1712 *ice)
+ {
+ 	/* FIXME: needs some quirks for VT1616? */
+ 	return 0;
+@@ -53,7 +53,7 @@ static int __devinit k8x800_add_controls(struct snd_ice1712 *ice)
+ 
+ /* EEPROM image */
+ 
+-static unsigned char k8x800_eeprom[] __devinitdata = {
++static unsigned char k8x800_eeprom[] = {
+ 	[ICE_EEP2_SYSCONF]     = 0x01,	/* clock 256, 1ADC, 2DACs */
+ 	[ICE_EEP2_ACLINK]      = 0x02,	/* ACLINK, packed */
+ 	[ICE_EEP2_I2S]         = 0x00,	/* - */
+@@ -69,7 +69,7 @@ static unsigned char k8x800_eeprom[] __devinitdata = {
+ 	[ICE_EEP2_GPIO_STATE2] = 0x00,	/* - */
+ };
+ 
+-static unsigned char sn25p_eeprom[] __devinitdata = {
++static unsigned char sn25p_eeprom[] = {
+ 	[ICE_EEP2_SYSCONF]     = 0x01,	/* clock 256, 1ADC, 2DACs */
+ 	[ICE_EEP2_ACLINK]      = 0x02,	/* ACLINK, packed */
+ 	[ICE_EEP2_I2S]         = 0x00,	/* - */
+@@ -87,7 +87,7 @@ static unsigned char sn25p_eeprom[] __devinitdata = {
+ 
+ 
+ /* entry point */
+-struct snd_ice1712_card_info snd_vt1720_mobo_cards[] __devinitdata = {
++struct snd_ice1712_card_info snd_vt1720_mobo_cards[] = {
+ 	{
+ 		.subvendor = VT1720_SUBDEVICE_K8X800,
+ 		.name = "Albatron K8X800 Pro II",
+diff --git a/sound/pci/ice1712/wtm.c b/sound/pci/ice1712/wtm.c
+index 184163bbd732..bcf30a387b87 100644
+--- a/sound/pci/ice1712/wtm.c
++++ b/sound/pci/ice1712/wtm.c
+@@ -383,7 +383,7 @@ static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,
+ /*
+  * Control tabs
+  */
+-static struct snd_kcontrol_new stac9640_controls[] __devinitdata = {
++static struct snd_kcontrol_new stac9640_controls[] = {
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "Master Playback Switch",
+@@ -447,7 +447,7 @@ static struct snd_kcontrol_new stac9640_controls[] __devinitdata = {
+ 
+ 
+ /*INIT*/
+-static int __devinit wtm_add_controls(struct snd_ice1712 *ice)
++static int wtm_add_controls(struct snd_ice1712 *ice)
+ {
+ 	unsigned int i;
+ 	int err;
+@@ -461,7 +461,7 @@ static int __devinit wtm_add_controls(struct snd_ice1712 *ice)
+ 	return 0;
+ }
+ 
+-static int __devinit wtm_init(struct snd_ice1712 *ice)
++static int wtm_init(struct snd_ice1712 *ice)
+ {
+ 	static unsigned short stac_inits_prodigy[] = {
+ 		STAC946X_RESET, 0,
+@@ -484,7 +484,7 @@ static int __devinit wtm_init(struct snd_ice1712 *ice)
+ }
+ 
+ 
+-static unsigned char wtm_eeprom[] __devinitdata = {
++static unsigned char wtm_eeprom[] = {
+ 	0x47,	/*SYSCONF: clock 192KHz, 4ADC, 8DAC */
+ 	0x80,	/* ACLINK : I2S */
+ 	0xf8,	/* I2S: vol; 96k, 24bit, 192k */
+@@ -502,7 +502,7 @@ static unsigned char wtm_eeprom[] __devinitdata = {
+ 
+ 
+ /*entry point*/
+-struct snd_ice1712_card_info snd_vt1724_wtm_cards[] __devinitdata = {
++struct snd_ice1712_card_info snd_vt1724_wtm_cards[] = {
+ 	{
+ 		.subvendor = VT1724_SUBDEVICE_WTM,
+ 		.name = "ESI Waveterminal 192M",
+diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
+index ea4b706c8d63..3b9be752f3e2 100644
+--- a/sound/pci/intel8x0.c
++++ b/sound/pci/intel8x0.c
+@@ -592,8 +592,8 @@ static unsigned short snd_intel8x0_codec_read(struct snd_ac97 *ac97,
+ 	return res;
+ }
+ 
+-static void __devinit snd_intel8x0_codec_read_test(struct intel8x0 *chip,
+-						   unsigned int codec)
++static void snd_intel8x0_codec_read_test(struct intel8x0 *chip,
++					 unsigned int codec)
+ {
+ 	unsigned int tmp;
+ 
+@@ -1507,8 +1507,8 @@ struct ich_pcm_table {
+ 	int ac97_idx;
+ };
+ 
+-static int __devinit snd_intel8x0_pcm1(struct intel8x0 *chip, int device,
+-				       struct ich_pcm_table *rec)
++static int snd_intel8x0_pcm1(struct intel8x0 *chip, int device,
++			     struct ich_pcm_table *rec)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -1564,7 +1564,7 @@ static int __devinit snd_intel8x0_pcm1(struct intel8x0 *chip, int device,
+ 	return 0;
+ }
+ 
+-static struct ich_pcm_table intel_pcms[] __devinitdata = {
++static struct ich_pcm_table intel_pcms[] = {
+ 	{
+ 		.playback_ops = &snd_intel8x0_playback_ops,
+ 		.capture_ops = &snd_intel8x0_capture_ops,
+@@ -1601,7 +1601,7 @@ static struct ich_pcm_table intel_pcms[] __devinitdata = {
+ 	},
+ };
+ 
+-static struct ich_pcm_table nforce_pcms[] __devinitdata = {
++static struct ich_pcm_table nforce_pcms[] = {
+ 	{
+ 		.playback_ops = &snd_intel8x0_playback_ops,
+ 		.capture_ops = &snd_intel8x0_capture_ops,
+@@ -1624,7 +1624,7 @@ static struct ich_pcm_table nforce_pcms[] __devinitdata = {
+ 	},
+ };
+ 
+-static struct ich_pcm_table ali_pcms[] __devinitdata = {
++static struct ich_pcm_table ali_pcms[] = {
+ 	{
+ 		.playback_ops = &snd_intel8x0_ali_playback_ops,
+ 		.capture_ops = &snd_intel8x0_ali_capture_ops,
+@@ -1656,7 +1656,7 @@ static struct ich_pcm_table ali_pcms[] __devinitdata = {
+ #endif
+ };
+ 
+-static int __devinit snd_intel8x0_pcm(struct intel8x0 *chip)
++static int snd_intel8x0_pcm(struct intel8x0 *chip)
+ {
+ 	int i, tblsize, device, err;
+ 	struct ich_pcm_table *tbl, *rec;
+@@ -1719,7 +1719,7 @@ static void snd_intel8x0_mixer_free_ac97(struct snd_ac97 *ac97)
+ 	chip->ac97[ac97->num] = NULL;
+ }
+ 
+-static struct ac97_pcm ac97_pcm_defs[] __devinitdata = {
++static struct ac97_pcm ac97_pcm_defs[] = {
+ 	/* front PCM */
+ 	{
+ 		.exclusive = 1,
+@@ -1789,7 +1789,7 @@ static struct ac97_pcm ac97_pcm_defs[] __devinitdata = {
+ 	},
+ };
+ 
+-static struct ac97_quirk ac97_quirks[] __devinitdata = {
++static struct ac97_quirk ac97_quirks[] = {
+         {
+ 		.subvendor = 0x0e11,
+ 		.subdevice = 0x000e,
+@@ -2196,8 +2196,8 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
+ 	{ } /* terminator */
+ };
+ 
+-static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock,
+-					const char *quirk_override)
++static int snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock,
++			      const char *quirk_override)
+ {
+ 	struct snd_ac97_bus *pbus;
+ 	struct snd_ac97_template ac97;
+@@ -2765,7 +2765,7 @@ static SIMPLE_DEV_PM_OPS(intel8x0_pm, intel8x0_suspend, intel8x0_resume);
+ 
+ #define INTEL8X0_TESTBUF_SIZE	32768	/* enough large for one shot */
+ 
+-static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip)
++static void intel8x0_measure_ac97_clock(struct intel8x0 *chip)
+ {
+ 	struct snd_pcm_substream *subs;
+ 	struct ichdev *ichdev;
+@@ -2883,7 +2883,7 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip)
+ 	snd_ac97_update_power(chip->ac97[0], AC97_PCM_FRONT_DAC_RATE, 0);
+ }
+ 
+-static struct snd_pci_quirk intel8x0_clock_list[] __devinitdata = {
++static struct snd_pci_quirk intel8x0_clock_list[] = {
+ 	SND_PCI_QUIRK(0x0e11, 0x008a, "AD1885", 41000),
+ 	SND_PCI_QUIRK(0x1028, 0x00be, "AD1885", 44100),
+ 	SND_PCI_QUIRK(0x1028, 0x0177, "AD1980", 48000),
+@@ -2892,7 +2892,7 @@ static struct snd_pci_quirk intel8x0_clock_list[] __devinitdata = {
+ 	{ }	/* terminator */
+ };
+ 
+-static int __devinit intel8x0_in_clock_list(struct intel8x0 *chip)
++static int intel8x0_in_clock_list(struct intel8x0 *chip)
+ {
+ 	struct pci_dev *pci = chip->pci;
+ 	const struct snd_pci_quirk *wl;
+@@ -2941,7 +2941,7 @@ static void snd_intel8x0_proc_read(struct snd_info_entry * entry,
+ 			chip->ac97_sdin[2]);
+ }
+ 
+-static void __devinit snd_intel8x0_proc_init(struct intel8x0 * chip)
++static void snd_intel8x0_proc_init(struct intel8x0 *chip)
+ {
+ 	struct snd_info_entry *entry;
+ 
+@@ -2970,7 +2970,7 @@ static unsigned int sis_codec_bits[3] = {
+ 	ICH_PCR, ICH_SCR, ICH_SIS_TCR
+ };
+ 
+-static int __devinit snd_intel8x0_inside_vm(struct pci_dev *pci)
++static int snd_intel8x0_inside_vm(struct pci_dev *pci)
+ {
+ 	int result  = inside_vm;
+ 	char *msg   = NULL;
+@@ -3009,10 +3009,10 @@ static int __devinit snd_intel8x0_inside_vm(struct pci_dev *pci)
+ 	return result;
+ }
+ 
+-static int __devinit snd_intel8x0_create(struct snd_card *card,
+-					 struct pci_dev *pci,
+-					 unsigned long device_type,
+-					 struct intel8x0 ** r_intel8x0)
++static int snd_intel8x0_create(struct snd_card *card,
++			       struct pci_dev *pci,
++			       unsigned long device_type,
++			       struct intel8x0 **r_intel8x0)
+ {
+ 	struct intel8x0 *chip;
+ 	int err;
+@@ -3227,7 +3227,7 @@ static int __devinit snd_intel8x0_create(struct snd_card *card,
+ static struct shortname_table {
+ 	unsigned int id;
+ 	const char *s;
+-} shortnames[] __devinitdata = {
++} shortnames[] = {
+ 	{ PCI_DEVICE_ID_INTEL_82801AA_5, "Intel 82801AA-ICH" },
+ 	{ PCI_DEVICE_ID_INTEL_82801AB_5, "Intel 82901AB-ICH0" },
+ 	{ PCI_DEVICE_ID_INTEL_82801BA_4, "Intel 82801BA-ICH2" },
+@@ -3253,13 +3253,13 @@ static struct shortname_table {
+ 	{ 0, NULL },
+ };
+ 
+-static struct snd_pci_quirk spdif_aclink_defaults[] __devinitdata = {
++static struct snd_pci_quirk spdif_aclink_defaults[] = {
+ 	SND_PCI_QUIRK(0x147b, 0x1c1a, "ASUS KN8", 1),
+ 	{ } /* end */
+ };
+ 
+ /* look up white/black list for SPDIF over ac-link */
+-static int __devinit check_default_spdif_aclink(struct pci_dev *pci)
++static int check_default_spdif_aclink(struct pci_dev *pci)
+ {
+ 	const struct snd_pci_quirk *w;
+ 
+@@ -3276,8 +3276,8 @@ static int __devinit check_default_spdif_aclink(struct pci_dev *pci)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
+-					const struct pci_device_id *pci_id)
++static int snd_intel8x0_probe(struct pci_dev *pci,
++			      const struct pci_device_id *pci_id)
+ {
+ 	struct snd_card *card;
+ 	struct intel8x0 *chip;
+@@ -3359,7 +3359,7 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_intel8x0_remove(struct pci_dev *pci)
++static void snd_intel8x0_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -3369,7 +3369,7 @@ static struct pci_driver intel8x0_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_intel8x0_ids,
+ 	.probe = snd_intel8x0_probe,
+-	.remove = __devexit_p(snd_intel8x0_remove),
++	.remove = snd_intel8x0_remove,
+ 	.driver = {
+ 		.pm = INTEL8X0_PM_OPS,
+ 	},
+diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
+index 4d551736531e..fea09e8ea608 100644
+--- a/sound/pci/intel8x0m.c
++++ b/sound/pci/intel8x0m.c
+@@ -710,8 +710,8 @@ struct ich_pcm_table {
+ 	int ac97_idx;
+ };
+ 
+-static int __devinit snd_intel8x0m_pcm1(struct intel8x0m *chip, int device,
+-				       struct ich_pcm_table *rec)
++static int snd_intel8x0m_pcm1(struct intel8x0m *chip, int device,
++			      struct ich_pcm_table *rec)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -749,7 +749,7 @@ static int __devinit snd_intel8x0m_pcm1(struct intel8x0m *chip, int device,
+ 	return 0;
+ }
+ 
+-static struct ich_pcm_table intel_pcms[] __devinitdata = {
++static struct ich_pcm_table intel_pcms[] = {
+ 	{
+ 		.suffix = "Modem",
+ 		.playback_ops = &snd_intel8x0m_playback_ops,
+@@ -759,7 +759,7 @@ static struct ich_pcm_table intel_pcms[] __devinitdata = {
+ 	},
+ };
+ 
+-static int __devinit snd_intel8x0m_pcm(struct intel8x0m *chip)
++static int snd_intel8x0m_pcm(struct intel8x0m *chip)
+ {
+ 	int i, tblsize, device, err;
+ 	struct ich_pcm_table *tbl, *rec;
+@@ -819,7 +819,7 @@ static void snd_intel8x0m_mixer_free_ac97(struct snd_ac97 *ac97)
+ }
+ 
+ 
+-static int __devinit snd_intel8x0m_mixer(struct intel8x0m *chip, int ac97_clock)
++static int snd_intel8x0m_mixer(struct intel8x0m *chip, int ac97_clock)
+ {
+ 	struct snd_ac97_bus *pbus;
+ 	struct snd_ac97_template ac97;
+@@ -1090,7 +1090,7 @@ static void snd_intel8x0m_proc_read(struct snd_info_entry * entry,
+ 			(tmp & (ICH_PCR | ICH_SCR | ICH_TCR)) == 0 ? " none" : "");
+ }
+ 
+-static void __devinit snd_intel8x0m_proc_init(struct intel8x0m * chip)
++static void snd_intel8x0m_proc_init(struct intel8x0m *chip)
+ {
+ 	struct snd_info_entry *entry;
+ 
+@@ -1113,10 +1113,10 @@ struct ich_reg_info {
+ 	unsigned int offset;
+ };
+ 
+-static int __devinit snd_intel8x0m_create(struct snd_card *card,
+-					 struct pci_dev *pci,
+-					 unsigned long device_type,
+-					 struct intel8x0m **r_intel8x0m)
++static int snd_intel8x0m_create(struct snd_card *card,
++				struct pci_dev *pci,
++				unsigned long device_type,
++				struct intel8x0m **r_intel8x0m)
+ {
+ 	struct intel8x0m *chip;
+ 	int err;
+@@ -1252,7 +1252,7 @@ static int __devinit snd_intel8x0m_create(struct snd_card *card,
+ static struct shortname_table {
+ 	unsigned int id;
+ 	const char *s;
+-} shortnames[] __devinitdata = {
++} shortnames[] = {
+ 	{ PCI_DEVICE_ID_INTEL_82801AA_6, "Intel 82801AA-ICH" },
+ 	{ PCI_DEVICE_ID_INTEL_82801AB_6, "Intel 82901AB-ICH0" },
+ 	{ PCI_DEVICE_ID_INTEL_82801BA_6, "Intel 82801BA-ICH2" },
+@@ -1275,8 +1275,8 @@ static struct shortname_table {
+ 	{ 0 },
+ };
+ 
+-static int __devinit snd_intel8x0m_probe(struct pci_dev *pci,
+-					const struct pci_device_id *pci_id)
++static int snd_intel8x0m_probe(struct pci_dev *pci,
++			       const struct pci_device_id *pci_id)
+ {
+ 	struct snd_card *card;
+ 	struct intel8x0m *chip;
+@@ -1325,7 +1325,7 @@ static int __devinit snd_intel8x0m_probe(struct pci_dev *pci,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_intel8x0m_remove(struct pci_dev *pci)
++static void snd_intel8x0m_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -1335,7 +1335,7 @@ static struct pci_driver intel8x0m_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_intel8x0m_ids,
+ 	.probe = snd_intel8x0m_probe,
+-	.remove = __devexit_p(snd_intel8x0m_remove),
++	.remove = snd_intel8x0m_remove,
+ 	.driver = {
+ 		.pm = INTEL8X0M_PM_OPS,
+ 	},
+diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
+index 8a67ce95f246..43b4228d9afe 100644
+--- a/sound/pci/korg1212/korg1212.c
++++ b/sound/pci/korg1212/korg1212.c
+@@ -2083,7 +2083,7 @@ static void snd_korg1212_proc_read(struct snd_info_entry *entry,
+         snd_iprintf(buffer, "    Error count: %ld\n", korg1212->totalerrorcnt);
+ }
+ 
+-static void __devinit snd_korg1212_proc_init(struct snd_korg1212 *korg1212)
++static void snd_korg1212_proc_init(struct snd_korg1212 *korg1212)
+ {
+ 	struct snd_info_entry *entry;
+ 
+@@ -2154,8 +2154,8 @@ static int snd_korg1212_dev_free(struct snd_device *device)
+ 	return snd_korg1212_free(korg1212);
+ }
+ 
+-static int __devinit snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
+-                                         struct snd_korg1212 ** rchip)
++static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
++			       struct snd_korg1212 **rchip)
+ 
+ {
+         int err, rc;
+@@ -2429,7 +2429,7 @@ static int __devinit snd_korg1212_create(struct snd_card *card, struct pci_dev *
+  * Card initialisation
+  */
+ 
+-static int __devinit
++static int
+ snd_korg1212_probe(struct pci_dev *pci,
+ 		const struct pci_device_id *pci_id)
+ {
+@@ -2470,7 +2470,7 @@ snd_korg1212_probe(struct pci_dev *pci,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_korg1212_remove(struct pci_dev *pci)
++static void snd_korg1212_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -2480,7 +2480,7 @@ static struct pci_driver korg1212_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_korg1212_ids,
+ 	.probe = snd_korg1212_probe,
+-	.remove = __devexit_p(snd_korg1212_remove),
++	.remove = snd_korg1212_remove,
+ };
+ 
+ module_pci_driver(korg1212_driver);
+diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c
+index ac15166bee68..322b638e8ec4 100644
+--- a/sound/pci/lola/lola.c
++++ b/sound/pci/lola/lola.c
+@@ -445,7 +445,7 @@ static void lola_reset_setups(struct lola *chip)
+ 	lola_setup_all_analog_gains(chip, PLAY, false); /* output, update */
+ }
+ 
+-static int __devinit lola_parse_tree(struct lola *chip)
++static int lola_parse_tree(struct lola *chip)
+ {
+ 	unsigned int val;
+ 	int nid, err;
+@@ -568,8 +568,8 @@ static int lola_dev_free(struct snd_device *device)
+ 	return 0;
+ }
+ 
+-static int __devinit lola_create(struct snd_card *card, struct pci_dev *pci,
+-				 int dev, struct lola **rchip)
++static int lola_create(struct snd_card *card, struct pci_dev *pci,
++		       int dev, struct lola **rchip)
+ {
+ 	struct lola *chip;
+ 	int err;
+@@ -702,8 +702,8 @@ static int __devinit lola_create(struct snd_card *card, struct pci_dev *pci,
+ 	return err;
+ }
+ 
+-static int __devinit lola_probe(struct pci_dev *pci,
+-				const struct pci_device_id *pci_id)
++static int lola_probe(struct pci_dev *pci,
++		      const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -756,7 +756,7 @@ static int __devinit lola_probe(struct pci_dev *pci,
+ 	return err;
+ }
+ 
+-static void __devexit lola_remove(struct pci_dev *pci)
++static void lola_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -774,7 +774,7 @@ static struct pci_driver lola_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = lola_ids,
+ 	.probe = lola_probe,
+-	.remove = __devexit_p(lola_remove),
++	.remove = lola_remove,
+ };
+ 
+ module_pci_driver(lola_driver);
+diff --git a/sound/pci/lola/lola_clock.c b/sound/pci/lola/lola_clock.c
+index 72f8ef0ac865..eb1d6b97df16 100644
+--- a/sound/pci/lola/lola_clock.c
++++ b/sound/pci/lola/lola_clock.c
+@@ -120,7 +120,7 @@ int lola_set_granularity(struct lola *chip, unsigned int val, bool force)
+  * Clock widget handling
+  */
+ 
+-int __devinit lola_init_clock_widget(struct lola *chip, int nid)
++int lola_init_clock_widget(struct lola *chip, int nid)
+ {
+ 	unsigned int val;
+ 	int i, j, nitems, nb_verbs, idx, idx_list;
+diff --git a/sound/pci/lola/lola_mixer.c b/sound/pci/lola/lola_mixer.c
+index 6b8d64812951..52c8d6b0f39b 100644
+--- a/sound/pci/lola/lola_mixer.c
++++ b/sound/pci/lola/lola_mixer.c
+@@ -28,8 +28,8 @@
+ #include 
+ #include "lola.h"
+ 
+-static int __devinit lola_init_pin(struct lola *chip, struct lola_pin *pin,
+-				   int dir, int nid)
++static int lola_init_pin(struct lola *chip, struct lola_pin *pin,
++			 int dir, int nid)
+ {
+ 	unsigned int val;
+ 	int err;
+@@ -91,7 +91,7 @@ static int __devinit lola_init_pin(struct lola *chip, struct lola_pin *pin,
+ 	return 0;
+ }
+ 
+-int __devinit lola_init_pins(struct lola *chip, int dir, int *nidp)
++int lola_init_pins(struct lola *chip, int dir, int *nidp)
+ {
+ 	int i, err, nid;
+ 	nid = *nidp;
+@@ -112,7 +112,7 @@ void lola_free_mixer(struct lola *chip)
+ 		vfree(chip->mixer.array_saved);
+ }
+ 
+-int __devinit lola_init_mixer_widget(struct lola *chip, int nid)
++int lola_init_mixer_widget(struct lola *chip, int nid)
+ {
+ 	unsigned int val;
+ 	int err;
+@@ -579,7 +579,7 @@ static int lola_analog_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
+ 	return 0;
+ }
+ 
+-static struct snd_kcontrol_new lola_analog_mixer __devinitdata = {
++static struct snd_kcontrol_new lola_analog_mixer = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ 		   SNDRV_CTL_ELEM_ACCESS_TLV_READ |
+@@ -590,7 +590,7 @@ static struct snd_kcontrol_new lola_analog_mixer __devinitdata = {
+ 	.tlv.c = lola_analog_vol_tlv,
+ };
+ 
+-static int __devinit create_analog_mixer(struct lola *chip, int dir, char *name)
++static int create_analog_mixer(struct lola *chip, int dir, char *name)
+ {
+ 	if (!chip->pin[dir].num_pins)
+ 		return 0;
+@@ -644,7 +644,7 @@ static int lola_input_src_put(struct snd_kcontrol *kcontrol,
+ 	return lola_set_src_config(chip, mask, true);
+ }
+ 
+-static struct snd_kcontrol_new lola_input_src_mixer __devinitdata = {
++static struct snd_kcontrol_new lola_input_src_mixer = {
+ 	.name = "Digital SRC Capture Switch",
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.info = lola_input_src_info,
+@@ -656,7 +656,7 @@ static struct snd_kcontrol_new lola_input_src_mixer __devinitdata = {
+  * Lola16161 or Lola881 can have Hardware sample rate converters
+  * on its digital input pins
+  */
+-static int __devinit create_input_src_mixer(struct lola *chip)
++static int create_input_src_mixer(struct lola *chip)
+ {
+ 	if (!chip->input_src_caps_mask)
+ 		return 0;
+@@ -726,7 +726,7 @@ static int lola_src_gain_put(struct snd_kcontrol *kcontrol,
+ /* raw value: 0 = -84dB, 336 = 0dB, 408=18dB, incremented 1 for mute */
+ static const DECLARE_TLV_DB_SCALE(lola_src_gain_tlv, -8425, 25, 1);
+ 
+-static struct snd_kcontrol_new lola_src_gain_mixer __devinitdata = {
++static struct snd_kcontrol_new lola_src_gain_mixer = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ 		   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
+@@ -736,8 +736,8 @@ static struct snd_kcontrol_new lola_src_gain_mixer __devinitdata = {
+ 	.tlv.p = lola_src_gain_tlv,
+ };
+ 
+-static int __devinit create_src_gain_mixer(struct lola *chip,
+-					   int num, int ofs, char *name)
++static int create_src_gain_mixer(struct lola *chip,
++				 int num, int ofs, char *name)
+ {
+ 	lola_src_gain_mixer.name = name;
+ 	lola_src_gain_mixer.private_value = ofs + (num << 8);
+@@ -813,7 +813,7 @@ static int lola_dest_gain_put(struct snd_kcontrol *kcontrol,
+ 
+ static const DECLARE_TLV_DB_SCALE(lola_dest_gain_tlv, -8425, 25, 1);
+ 
+-static struct snd_kcontrol_new lola_dest_gain_mixer __devinitdata = {
++static struct snd_kcontrol_new lola_dest_gain_mixer = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ 		   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
+@@ -823,9 +823,9 @@ static struct snd_kcontrol_new lola_dest_gain_mixer __devinitdata = {
+ 	.tlv.p = lola_dest_gain_tlv,
+ };
+ 
+-static int __devinit create_dest_gain_mixer(struct lola *chip,
+-					    int src_num, int src_ofs,
+-					    int num, int ofs, char *name)
++static int create_dest_gain_mixer(struct lola *chip,
++				  int src_num, int src_ofs,
++				  int num, int ofs, char *name)
+ {
+ 	lola_dest_gain_mixer.count = num;
+ 	lola_dest_gain_mixer.name = name;
+@@ -838,7 +838,7 @@ static int __devinit create_dest_gain_mixer(struct lola *chip,
+ 
+ /*
+  */
+-int __devinit lola_create_mixer(struct lola *chip)
++int lola_create_mixer(struct lola *chip)
+ {
+ 	int err;
+ 
+diff --git a/sound/pci/lola/lola_pcm.c b/sound/pci/lola/lola_pcm.c
+index c44db68eecb5..5ea85e8b83ab 100644
+--- a/sound/pci/lola/lola_pcm.c
++++ b/sound/pci/lola/lola_pcm.c
+@@ -597,7 +597,7 @@ static struct snd_pcm_ops lola_pcm_ops = {
+ 	.page = snd_pcm_sgbuf_ops_page,
+ };
+ 
+-int __devinit lola_create_pcm(struct lola *chip)
++int lola_create_pcm(struct lola *chip)
+ {
+ 	struct snd_pcm *pcm;
+ 	int i, err;
+@@ -690,7 +690,7 @@ static int lola_init_stream(struct lola *chip, struct lola_stream *str,
+ 	return 0;
+ }
+ 
+-int __devinit lola_init_pcm(struct lola *chip, int dir, int *nidp)
++int lola_init_pcm(struct lola *chip, int dir, int *nidp)
+ {
+ 	struct lola_pcm *pcm = &chip->pcm[dir];
+ 	int i, nid, err;
+diff --git a/sound/pci/lola/lola_proc.c b/sound/pci/lola/lola_proc.c
+index 9d7daf897c9d..04df83defc09 100644
+--- a/sound/pci/lola/lola_proc.c
++++ b/sound/pci/lola/lola_proc.c
+@@ -206,7 +206,7 @@ static void lola_proc_regs_read(struct snd_info_entry *entry,
+ 	}
+ }
+ 
+-void __devinit lola_proc_debug_new(struct lola *chip)
++void lola_proc_debug_new(struct lola *chip)
+ {
+ 	struct snd_info_entry *entry;
+ 
+diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c
+index 5579b08bb35b..298bc9b72991 100644
+--- a/sound/pci/lx6464es/lx6464es.c
++++ b/sound/pci/lx6464es/lx6464es.c
+@@ -578,7 +578,7 @@ static int snd_lx6464es_dev_free(struct snd_device *device)
+ }
+ 
+ /* reset the dsp during initialization */
+-static int __devinit lx_init_xilinx_reset(struct lx6464es *chip)
++static int lx_init_xilinx_reset(struct lx6464es *chip)
+ {
+ 	int i;
+ 	u32 plx_reg = lx_plx_reg_read(chip, ePLX_CHIPSC);
+@@ -620,7 +620,7 @@ static int __devinit lx_init_xilinx_reset(struct lx6464es *chip)
+ 	return 0;
+ }
+ 
+-static int __devinit lx_init_xilinx_test(struct lx6464es *chip)
++static int lx_init_xilinx_test(struct lx6464es *chip)
+ {
+ 	u32 reg;
+ 
+@@ -650,7 +650,7 @@ static int __devinit lx_init_xilinx_test(struct lx6464es *chip)
+ }
+ 
+ /* initialize ethersound */
+-static int __devinit lx_init_ethersound_config(struct lx6464es *chip)
++static int lx_init_ethersound_config(struct lx6464es *chip)
+ {
+ 	int i;
+ 	u32 orig_conf_es = lx_dsp_reg_read(chip, eReg_CONFES);
+@@ -690,7 +690,7 @@ static int __devinit lx_init_ethersound_config(struct lx6464es *chip)
+ 	return 0;
+ }
+ 
+-static int __devinit lx_init_get_version_features(struct lx6464es *chip)
++static int lx_init_get_version_features(struct lx6464es *chip)
+ {
+ 	u32 dsp_version;
+ 
+@@ -759,7 +759,7 @@ static int lx_set_granularity(struct lx6464es *chip, u32 gran)
+ }
+ 
+ /* initialize and test the xilinx dsp chip */
+-static int __devinit lx_init_dsp(struct lx6464es *chip)
++static int lx_init_dsp(struct lx6464es *chip)
+ {
+ 	int err;
+ 	int i;
+@@ -835,7 +835,7 @@ static struct snd_pcm_ops lx_ops_capture = {
+ 	.pointer   = lx_pcm_stream_pointer,
+ };
+ 
+-static int __devinit lx_pcm_create(struct lx6464es *chip)
++static int lx_pcm_create(struct lx6464es *chip)
+ {
+ 	int err;
+ 	struct snd_pcm *pcm;
+@@ -907,7 +907,7 @@ static int lx_control_playback_put(struct snd_kcontrol *kcontrol,
+ 	return changed;
+ }
+ 
+-static struct snd_kcontrol_new lx_control_playback_switch __devinitdata = {
++static struct snd_kcontrol_new lx_control_playback_switch = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "PCM Playback Switch",
+ 	.index = 0,
+@@ -954,7 +954,7 @@ static void lx_proc_levels_read(struct snd_info_entry *entry,
+ 	snd_iprintf(buffer, "\n");
+ }
+ 
+-static int __devinit lx_proc_create(struct snd_card *card, struct lx6464es *chip)
++static int lx_proc_create(struct snd_card *card, struct lx6464es *chip)
+ {
+ 	struct snd_info_entry *entry;
+ 	int err = snd_card_proc_new(card, "levels", &entry);
+@@ -966,9 +966,9 @@ static int __devinit lx_proc_create(struct snd_card *card, struct lx6464es *chip
+ }
+ 
+ 
+-static int __devinit snd_lx6464es_create(struct snd_card *card,
+-					 struct pci_dev *pci,
+-					 struct lx6464es **rchip)
++static int snd_lx6464es_create(struct snd_card *card,
++			       struct pci_dev *pci,
++			       struct lx6464es **rchip)
+ {
+ 	struct lx6464es *chip;
+ 	int err;
+@@ -1082,8 +1082,8 @@ static int __devinit snd_lx6464es_create(struct snd_card *card,
+ 	return err;
+ }
+ 
+-static int __devinit snd_lx6464es_probe(struct pci_dev *pci,
+-					const struct pci_device_id *pci_id)
++static int snd_lx6464es_probe(struct pci_dev *pci,
++			      const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -1136,7 +1136,7 @@ static int __devinit snd_lx6464es_probe(struct pci_dev *pci,
+ 
+ }
+ 
+-static void __devexit snd_lx6464es_remove(struct pci_dev *pci)
++static void snd_lx6464es_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -1147,7 +1147,7 @@ static struct pci_driver lx6464es_driver = {
+ 	.name =     KBUILD_MODNAME,
+ 	.id_table = snd_lx6464es_ids,
+ 	.probe =    snd_lx6464es_probe,
+-	.remove = __devexit_p(snd_lx6464es_remove),
++	.remove = snd_lx6464es_remove,
+ };
+ 
+ module_pci_driver(lx6464es_driver);
+diff --git a/sound/pci/lx6464es/lx_core.c b/sound/pci/lx6464es/lx_core.c
+index 8c3e7fcefd99..633c8607d053 100644
+--- a/sound/pci/lx6464es/lx_core.c
++++ b/sound/pci/lx6464es/lx_core.c
+@@ -385,7 +385,7 @@ static int lx_message_send_atomic(struct lx6464es *chip, struct lx_rmh *rmh)
+ 
+ 
+ /* low-level dsp access */
+-int __devinit lx_dsp_get_version(struct lx6464es *chip, u32 *rdsp_version)
++int lx_dsp_get_version(struct lx6464es *chip, u32 *rdsp_version)
+ {
+ 	u16 ret;
+ 	unsigned long flags;
+diff --git a/sound/pci/lx6464es/lx_core.h b/sound/pci/lx6464es/lx_core.h
+index 4d7ff797a646..5ec5e04da1a5 100644
+--- a/sound/pci/lx6464es/lx_core.h
++++ b/sound/pci/lx6464es/lx_core.h
+@@ -109,7 +109,7 @@ struct lx_rmh {
+ 
+ 
+ /* low-level dsp access */
+-int __devinit lx_dsp_get_version(struct lx6464es *chip, u32 *rdsp_version);
++int lx_dsp_get_version(struct lx6464es *chip, u32 *rdsp_version);
+ int lx_dsp_get_clock_frequency(struct lx6464es *chip, u32 *rfreq);
+ int lx_dsp_set_granularity(struct lx6464es *chip, u32 gran);
+ int lx_dsp_read_async_events(struct lx6464es *chip, u32 *data);
+diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
+index eb3cd3a4315e..9387533f70dc 100644
+--- a/sound/pci/maestro3.c
++++ b/sound/pci/maestro3.c
+@@ -822,7 +822,7 @@ static DEFINE_PCI_DEVICE_TABLE(snd_m3_ids) = {
+ 
+ MODULE_DEVICE_TABLE(pci, snd_m3_ids);
+ 
+-static struct snd_pci_quirk m3_amp_quirk_list[] __devinitdata = {
++static struct snd_pci_quirk m3_amp_quirk_list[] = {
+ 	SND_PCI_QUIRK(0x0E11, 0x0094, "Compaq Evo N600c", 0x0c),
+ 	SND_PCI_QUIRK(0x10f7, 0x833e, "Panasonic CF-28", 0x0d),
+ 	SND_PCI_QUIRK(0x10f7, 0x833d, "Panasonic CF-72", 0x0d),
+@@ -831,7 +831,7 @@ static struct snd_pci_quirk m3_amp_quirk_list[] __devinitdata = {
+ 	{ } /* END */
+ };
+ 
+-static struct snd_pci_quirk m3_irda_quirk_list[] __devinitdata = {
++static struct snd_pci_quirk m3_irda_quirk_list[] = {
+ 	SND_PCI_QUIRK(0x1028, 0x00b0, "Dell Inspiron 4000", 1),
+ 	SND_PCI_QUIRK(0x1028, 0x00a4, "Dell Inspiron 8000", 1),
+ 	SND_PCI_QUIRK(0x1028, 0x00e6, "Dell Inspiron 8100", 1),
+@@ -839,7 +839,7 @@ static struct snd_pci_quirk m3_irda_quirk_list[] __devinitdata = {
+ };
+ 
+ /* hardware volume quirks */
+-static struct snd_pci_quirk m3_hv_quirk_list[] __devinitdata = {
++static struct snd_pci_quirk m3_hv_quirk_list[] = {
+ 	/* Allegro chips */
+ 	SND_PCI_QUIRK(0x0E11, 0x002E, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+ 	SND_PCI_QUIRK(0x0E11, 0x0094, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
+@@ -917,7 +917,7 @@ static struct snd_pci_quirk m3_hv_quirk_list[] __devinitdata = {
+ };
+ 
+ /* HP Omnibook quirks */
+-static struct snd_pci_quirk m3_omnibook_quirk_list[] __devinitdata = {
++static struct snd_pci_quirk m3_omnibook_quirk_list[] = {
+ 	SND_PCI_QUIRK_ID(0x103c, 0x0010), /* HP OmniBook 6000 */
+ 	SND_PCI_QUIRK_ID(0x103c, 0x0011), /* HP OmniBook 500 */
+ 	{ } /* END */
+@@ -1856,7 +1856,7 @@ static struct snd_pcm_ops snd_m3_capture_ops = {
+ 	.pointer =	snd_m3_pcm_pointer,
+ };
+ 
+-static int __devinit
++static int
+ snd_m3_pcm(struct snd_m3 * chip, int device)
+ {
+ 	struct snd_pcm *pcm;
+@@ -2031,7 +2031,7 @@ static void snd_m3_ac97_reset(struct snd_m3 *chip)
+ #endif
+ }
+ 
+-static int __devinit snd_m3_mixer(struct snd_m3 *chip)
++static int snd_m3_mixer(struct snd_m3 *chip)
+ {
+ 	struct snd_ac97_bus *pbus;
+ 	struct snd_ac97_template ac97;
+@@ -2173,7 +2173,7 @@ static void snd_m3_assp_init(struct snd_m3 *chip)
+ }
+ 
+ 
+-static int __devinit snd_m3_assp_client_init(struct snd_m3 *chip, struct m3_dma *s, int index)
++static int snd_m3_assp_client_init(struct snd_m3 *chip, struct m3_dma *s, int index)
+ {
+ 	int data_bytes = 2 * ( MINISRC_TMP_BUFFER_SIZE / 2 + 
+ 			       MINISRC_IN_BUFFER_SIZE / 2 +
+@@ -2488,7 +2488,7 @@ static SIMPLE_DEV_PM_OPS(m3_pm, m3_suspend, m3_resume);
+ #endif /* CONFIG_PM_SLEEP */
+ 
+ #ifdef CONFIG_SND_MAESTRO3_INPUT
+-static int __devinit snd_m3_input_register(struct snd_m3 *chip)
++static int snd_m3_input_register(struct snd_m3 *chip)
+ {
+ 	struct input_dev *input_dev;
+ 	int err;
+@@ -2532,7 +2532,7 @@ static int snd_m3_dev_free(struct snd_device *device)
+ 	return snd_m3_free(chip);
+ }
+ 
+-static int __devinit
++static int
+ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
+ 	      int enable_amp,
+ 	      int amp_gpio,
+@@ -2700,7 +2700,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
+ 
+ /*
+  */
+-static int __devinit
++static int
+ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+@@ -2770,7 +2770,7 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+ 	return 0;
+ }
+ 
+-static void __devexit snd_m3_remove(struct pci_dev *pci)
++static void snd_m3_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -2780,7 +2780,7 @@ static struct pci_driver m3_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_m3_ids,
+ 	.probe = snd_m3_probe,
+-	.remove = __devexit_p(snd_m3_remove),
++	.remove = snd_m3_remove,
+ 	.driver = {
+ 		.pm = M3_PM_OPS,
+ 	},
+diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
+index 0762610c99c0..01f7f37a8410 100644
+--- a/sound/pci/mixart/mixart.c
++++ b/sound/pci/mixart/mixart.c
+@@ -1004,7 +1004,7 @@ static int snd_mixart_chip_dev_free(struct snd_device *device)
+ 
+ /*
+  */
+-static int __devinit snd_mixart_create(struct mixart_mgr *mgr, struct snd_card *card, int idx)
++static int snd_mixart_create(struct mixart_mgr *mgr, struct snd_card *card, int idx)
+ {
+ 	int err;
+ 	struct snd_mixart *chip;
+@@ -1180,7 +1180,7 @@ static void snd_mixart_proc_read(struct snd_info_entry *entry,
+ 	} /* endif elf loaded */
+ }
+ 
+-static void __devinit snd_mixart_proc_init(struct snd_mixart *chip)
++static void snd_mixart_proc_init(struct snd_mixart *chip)
+ {
+ 	struct snd_info_entry *entry;
+ 
+@@ -1209,8 +1209,8 @@ static void __devinit snd_mixart_proc_init(struct snd_mixart *chip)
+ /*
+  *    probe function - creates the card manager
+  */
+-static int __devinit snd_mixart_probe(struct pci_dev *pci,
+-				      const struct pci_device_id *pci_id)
++static int snd_mixart_probe(struct pci_dev *pci,
++			    const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct mixart_mgr *mgr;
+@@ -1374,7 +1374,7 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_mixart_remove(struct pci_dev *pci)
++static void snd_mixart_remove(struct pci_dev *pci)
+ {
+ 	snd_mixart_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -1384,7 +1384,7 @@ static struct pci_driver mixart_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_mixart_ids,
+ 	.probe = snd_mixart_probe,
+-	.remove = __devexit_p(snd_mixart_remove),
++	.remove = snd_mixart_remove,
+ };
+ 
+ module_pci_driver(mixart_driver);
+diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
+index e80e9a1e84aa..563a193e36a3 100644
+--- a/sound/pci/nm256/nm256.c
++++ b/sound/pci/nm256/nm256.c
+@@ -928,7 +928,7 @@ static struct snd_pcm_ops snd_nm256_capture_ops = {
+ 	.mmap =		snd_pcm_lib_mmap_iomem,
+ };
+ 
+-static int __devinit
++static int
+ snd_nm256_pcm(struct nm256 *chip, int device)
+ {
+ 	struct snd_pcm *pcm;
+@@ -1295,7 +1295,7 @@ snd_nm256_ac97_reset(struct snd_ac97 *ac97)
+ }
+ 
+ /* create an ac97 mixer interface */
+-static int __devinit
++static int
+ snd_nm256_mixer(struct nm256 *chip)
+ {
+ 	struct snd_ac97_bus *pbus;
+@@ -1336,7 +1336,7 @@ snd_nm256_mixer(struct nm256 *chip)
+  * RAM.
+  */
+ 
+-static int __devinit
++static int
+ snd_nm256_peek_for_sig(struct nm256 *chip)
+ {
+ 	/* The signature is located 1K below the end of video RAM.  */
+@@ -1472,7 +1472,7 @@ static int snd_nm256_dev_free(struct snd_device *device)
+ 	return snd_nm256_free(chip);
+ }
+ 
+-static int __devinit
++static int
+ snd_nm256_create(struct snd_card *card, struct pci_dev *pci,
+ 		 struct nm256 **chip_ret)
+ {
+@@ -1639,7 +1639,7 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci,
+ 
+ enum { NM_BLACKLISTED, NM_RESET_WORKAROUND, NM_RESET_WORKAROUND_2 };
+ 
+-static struct snd_pci_quirk nm256_quirks[] __devinitdata = {
++static struct snd_pci_quirk nm256_quirks[] = {
+ 	/* HP omnibook 4150 has cs4232 codec internally */
+ 	SND_PCI_QUIRK(0x103c, 0x0007, "HP omnibook 4150", NM_BLACKLISTED),
+ 	/* Reset workarounds to avoid lock-ups */
+@@ -1650,8 +1650,8 @@ static struct snd_pci_quirk nm256_quirks[] __devinitdata = {
+ };
+ 
+ 
+-static int __devinit snd_nm256_probe(struct pci_dev *pci,
+-				     const struct pci_device_id *pci_id)
++static int snd_nm256_probe(struct pci_dev *pci,
++			   const struct pci_device_id *pci_id)
+ {
+ 	struct snd_card *card;
+ 	struct nm256 *chip;
+@@ -1742,7 +1742,7 @@ static int __devinit snd_nm256_probe(struct pci_dev *pci,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_nm256_remove(struct pci_dev *pci)
++static void snd_nm256_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -1753,7 +1753,7 @@ static struct pci_driver nm256_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_nm256_ids,
+ 	.probe = snd_nm256_probe,
+-	.remove = __devexit_p(snd_nm256_remove),
++	.remove = snd_nm256_remove,
+ 	.driver = {
+ 		.pm = NM256_PM_OPS,
+ 	},
+diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
+index be4f1456009a..b97384ad946d 100644
+--- a/sound/pci/pcxhr/pcxhr.c
++++ b/sound/pci/pcxhr/pcxhr.c
+@@ -1203,8 +1203,8 @@ static int pcxhr_chip_dev_free(struct snd_device *device)
+ 
+ /*
+  */
+-static int __devinit pcxhr_create(struct pcxhr_mgr *mgr,
+-				  struct snd_card *card, int idx)
++static int pcxhr_create(struct pcxhr_mgr *mgr,
++			struct snd_card *card, int idx)
+ {
+ 	int err;
+ 	struct snd_pcxhr *chip;
+@@ -1453,7 +1453,7 @@ static void pcxhr_proc_ltc(struct snd_info_entry *entry,
+ 	}
+ }
+ 
+-static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip)
++static void pcxhr_proc_init(struct snd_pcxhr *chip)
+ {
+ 	struct snd_info_entry *entry;
+ 
+@@ -1513,8 +1513,8 @@ static int pcxhr_free(struct pcxhr_mgr *mgr)
+ /*
+  *    probe function - creates the card manager
+  */
+-static int __devinit pcxhr_probe(struct pci_dev *pci,
+-				 const struct pci_device_id *pci_id)
++static int pcxhr_probe(struct pci_dev *pci,
++		       const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct pcxhr_mgr *mgr;
+@@ -1688,7 +1688,7 @@ static int __devinit pcxhr_probe(struct pci_dev *pci,
+ 	return 0;
+ }
+ 
+-static void __devexit pcxhr_remove(struct pci_dev *pci)
++static void pcxhr_remove(struct pci_dev *pci)
+ {
+ 	pcxhr_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -1698,7 +1698,7 @@ static struct pci_driver pcxhr_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = pcxhr_ids,
+ 	.probe = pcxhr_probe,
+-	.remove = __devexit_p(pcxhr_remove),
++	.remove = pcxhr_remove,
+ };
+ 
+ module_pci_driver(pcxhr_driver);
+diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
+index 7d291542c5ba..63c1c8041554 100644
+--- a/sound/pci/riptide/riptide.c
++++ b/sound/pci/riptide/riptide.c
+@@ -1706,7 +1706,7 @@ static struct snd_pcm_ops snd_riptide_capture_ops = {
+ 	.pointer = snd_riptide_pointer,
+ };
+ 
+-static int __devinit
++static int
+ snd_riptide_pcm(struct snd_riptide *chip, int device, struct snd_pcm **rpcm)
+ {
+ 	struct snd_pcm *pcm;
+@@ -1857,7 +1857,7 @@ static int snd_riptide_dev_free(struct snd_device *device)
+ 	return snd_riptide_free(chip);
+ }
+ 
+-static int __devinit
++static int
+ snd_riptide_create(struct snd_card *card, struct pci_dev *pci,
+ 		   struct snd_riptide **rchip)
+ {
+@@ -1993,7 +1993,7 @@ snd_riptide_proc_read(struct snd_info_entry *entry,
+ 	snd_iprintf(buffer, "\n");
+ }
+ 
+-static void __devinit snd_riptide_proc_init(struct snd_riptide *chip)
++static void snd_riptide_proc_init(struct snd_riptide *chip)
+ {
+ 	struct snd_info_entry *entry;
+ 
+@@ -2001,7 +2001,7 @@ static void __devinit snd_riptide_proc_init(struct snd_riptide *chip)
+ 		snd_info_set_text_ops(entry, chip, snd_riptide_proc_read);
+ }
+ 
+-static int __devinit snd_riptide_mixer(struct snd_riptide *chip)
++static int snd_riptide_mixer(struct snd_riptide *chip)
+ {
+ 	struct snd_ac97_bus *pbus;
+ 	struct snd_ac97_template ac97;
+@@ -2027,7 +2027,7 @@ static int __devinit snd_riptide_mixer(struct snd_riptide *chip)
+ 
+ #ifdef SUPPORT_JOYSTICK
+ 
+-static int __devinit
++static int
+ snd_riptide_joystick_probe(struct pci_dev *pci, const struct pci_device_id *id)
+ {
+ 	static int dev;
+@@ -2060,7 +2060,7 @@ snd_riptide_joystick_probe(struct pci_dev *pci, const struct pci_device_id *id)
+ 	return 0;
+ }
+ 
+-static void __devexit snd_riptide_joystick_remove(struct pci_dev *pci)
++static void snd_riptide_joystick_remove(struct pci_dev *pci)
+ {
+ 	struct gameport *gameport = pci_get_drvdata(pci);
+ 	if (gameport) {
+@@ -2071,7 +2071,7 @@ static void __devexit snd_riptide_joystick_remove(struct pci_dev *pci)
+ }
+ #endif
+ 
+-static int __devinit
++static int
+ snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+@@ -2176,7 +2176,7 @@ snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+ 	return err;
+ }
+ 
+-static void __devexit snd_card_riptide_remove(struct pci_dev *pci)
++static void snd_card_riptide_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -2186,7 +2186,7 @@ static struct pci_driver driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_riptide_ids,
+ 	.probe = snd_card_riptide_probe,
+-	.remove = __devexit_p(snd_card_riptide_remove),
++	.remove = snd_card_riptide_remove,
+ 	.driver = {
+ 		.pm = RIPTIDE_PM_OPS,
+ 	},
+@@ -2197,7 +2197,7 @@ static struct pci_driver joystick_driver = {
+ 	.name = KBUILD_MODNAME "-joystick",
+ 	.id_table = snd_riptide_joystick_ids,
+ 	.probe = snd_riptide_joystick_probe,
+-	.remove = __devexit_p(snd_riptide_joystick_remove),
++	.remove = snd_riptide_joystick_remove,
+ };
+ #endif
+ 
+diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
+index 46b3629dda22..2450663e1a18 100644
+--- a/sound/pci/rme32.c
++++ b/sound/pci/rme32.c
+@@ -1332,7 +1332,7 @@ snd_rme32_free_adat_pcm(struct snd_pcm *pcm)
+ 	rme32->adat_pcm = NULL;
+ }
+ 
+-static int __devinit snd_rme32_create(struct rme32 * rme32)
++static int snd_rme32_create(struct rme32 *rme32)
+ {
+ 	struct pci_dev *pci = rme32->pci;
+ 	int err;
+@@ -1554,7 +1554,7 @@ snd_rme32_proc_read(struct snd_info_entry * entry, struct snd_info_buffer *buffe
+ 	}
+ }
+ 
+-static void __devinit snd_rme32_proc_init(struct rme32 * rme32)
++static void snd_rme32_proc_init(struct rme32 *rme32)
+ {
+ 	struct snd_info_entry *entry;
+ 
+@@ -1922,7 +1922,7 @@ static void snd_rme32_card_free(struct snd_card *card)
+ 	snd_rme32_free(card->private_data);
+ }
+ 
+-static int __devinit
++static int
+ snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+@@ -1978,7 +1978,7 @@ snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+ 	return 0;
+ }
+ 
+-static void __devexit snd_rme32_remove(struct pci_dev *pci)
++static void snd_rme32_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -1988,7 +1988,7 @@ static struct pci_driver rme32_driver = {
+ 	.name =		KBUILD_MODNAME,
+ 	.id_table =	snd_rme32_ids,
+ 	.probe =	snd_rme32_probe,
+-	.remove =	__devexit_p(snd_rme32_remove),
++	.remove =	snd_rme32_remove,
+ };
+ 
+ module_pci_driver(rme32_driver);
+diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
+index 9b98dc406988..5fb88ac82aa9 100644
+--- a/sound/pci/rme96.c
++++ b/sound/pci/rme96.c
+@@ -270,8 +270,7 @@ snd_rme96_playback_pointer(struct snd_pcm_substream *substream);
+ static snd_pcm_uframes_t
+ snd_rme96_capture_pointer(struct snd_pcm_substream *substream);
+ 
+-static void __devinit 
+-snd_rme96_proc_init(struct rme96 *rme96);
++static void snd_rme96_proc_init(struct rme96 *rme96);
+ 
+ static int
+ snd_rme96_create_switches(struct snd_card *card,
+@@ -1538,7 +1537,7 @@ snd_rme96_free_adat_pcm(struct snd_pcm *pcm)
+ 	rme96->adat_pcm = NULL;
+ }
+ 
+-static int __devinit
++static int
+ snd_rme96_create(struct rme96 *rme96)
+ {
+ 	struct pci_dev *pci = rme96->pci;
+@@ -1786,8 +1785,7 @@ snd_rme96_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer
+ 	}
+ }
+ 
+-static void __devinit 
+-snd_rme96_proc_init(struct rme96 *rme96)
++static void snd_rme96_proc_init(struct rme96 *rme96)
+ {
+ 	struct snd_info_entry *entry;
+ 
+@@ -2326,7 +2324,7 @@ static void snd_rme96_card_free(struct snd_card *card)
+ 	snd_rme96_free(card->private_data);
+ }
+ 
+-static int __devinit
++static int
+ snd_rme96_probe(struct pci_dev *pci,
+ 		const struct pci_device_id *pci_id)
+ {
+@@ -2389,7 +2387,7 @@ snd_rme96_probe(struct pci_dev *pci,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_rme96_remove(struct pci_dev *pci)
++static void snd_rme96_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -2399,7 +2397,7 @@ static struct pci_driver rme96_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_rme96_ids,
+ 	.probe = snd_rme96_probe,
+-	.remove = __devexit_p(snd_rme96_remove),
++	.remove = snd_rme96_remove,
+ };
+ 
+ module_pci_driver(rme96_driver);
+diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
+index 0f82bb5f42ea..4fae81f21efb 100644
+--- a/sound/pci/rme9652/hdsp.c
++++ b/sound/pci/rme9652/hdsp.c
+@@ -4020,7 +4020,7 @@ static void snd_hdsp_free_buffers(struct hdsp *hdsp)
+ 	snd_hammerfall_free_buffer(&hdsp->playback_dma_buf, hdsp->pci);
+ }
+ 
+-static int __devinit snd_hdsp_initialize_memory(struct hdsp *hdsp)
++static int snd_hdsp_initialize_memory(struct hdsp *hdsp)
+ {
+ 	unsigned long pb_bus, cb_bus;
+ 
+@@ -5413,8 +5413,8 @@ static int hdsp_request_fw_loader(struct hdsp *hdsp)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_hdsp_create(struct snd_card *card,
+-				     struct hdsp *hdsp)
++static int snd_hdsp_create(struct snd_card *card,
++			   struct hdsp *hdsp)
+ {
+ 	struct pci_dev *pci = hdsp->pci;
+ 	int err;
+@@ -5593,8 +5593,8 @@ static void snd_hdsp_card_free(struct snd_card *card)
+ 		snd_hdsp_free(hdsp);
+ }
+ 
+-static int __devinit snd_hdsp_probe(struct pci_dev *pci,
+-				    const struct pci_device_id *pci_id)
++static int snd_hdsp_probe(struct pci_dev *pci,
++			  const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct hdsp *hdsp;
+@@ -5637,7 +5637,7 @@ static int __devinit snd_hdsp_probe(struct pci_dev *pci,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_hdsp_remove(struct pci_dev *pci)
++static void snd_hdsp_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -5647,7 +5647,7 @@ static struct pci_driver hdsp_driver = {
+ 	.name =     KBUILD_MODNAME,
+ 	.id_table = snd_hdsp_ids,
+ 	.probe =    snd_hdsp_probe,
+-	.remove = __devexit_p(snd_hdsp_remove),
++	.remove = snd_hdsp_remove,
+ };
+ 
+ module_pci_driver(hdsp_driver);
+diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
+index a7e0de1a1b4b..6e02e064d7b4 100644
+--- a/sound/pci/rme9652/hdspm.c
++++ b/sound/pci/rme9652/hdspm.c
+@@ -962,10 +962,10 @@ static DEFINE_PCI_DEVICE_TABLE(snd_hdspm_ids) = {
+ MODULE_DEVICE_TABLE(pci, snd_hdspm_ids);
+ 
+ /* prototypes */
+-static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
+-						   struct hdspm * hdspm);
+-static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
+-					  struct hdspm * hdspm);
++static int snd_hdspm_create_alsa_devices(struct snd_card *card,
++					 struct hdspm *hdspm);
++static int snd_hdspm_create_pcm(struct snd_card *card,
++				struct hdspm *hdspm);
+ 
+ static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm);
+ static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm);
+@@ -1845,8 +1845,8 @@ static struct snd_rawmidi_ops snd_hdspm_midi_input =
+ 	.trigger =	snd_hdspm_midi_input_trigger,
+ };
+ 
+-static int __devinit snd_hdspm_create_midi (struct snd_card *card,
+-					    struct hdspm *hdspm, int id)
++static int snd_hdspm_create_midi(struct snd_card *card,
++				 struct hdspm *hdspm, int id)
+ {
+ 	int err;
+ 	char buf[32];
+@@ -4897,7 +4897,7 @@ static void snd_hdspm_proc_ports_out(struct snd_info_entry *entry,
+ }
+ 
+ 
+-static void __devinit snd_hdspm_proc_init(struct hdspm *hdspm)
++static void snd_hdspm_proc_init(struct hdspm *hdspm)
+ {
+ 	struct snd_info_entry *entry;
+ 
+@@ -6033,8 +6033,8 @@ static struct snd_pcm_ops snd_hdspm_capture_ops = {
+ 	.page = snd_pcm_sgbuf_ops_page,
+ };
+ 
+-static int __devinit snd_hdspm_create_hwdep(struct snd_card *card,
+-					    struct hdspm * hdspm)
++static int snd_hdspm_create_hwdep(struct snd_card *card,
++				  struct hdspm *hdspm)
+ {
+ 	struct snd_hwdep *hw;
+ 	int err;
+@@ -6059,7 +6059,7 @@ static int __devinit snd_hdspm_create_hwdep(struct snd_card *card,
+ /*------------------------------------------------------------
+    memory interface
+  ------------------------------------------------------------*/
+-static int __devinit snd_hdspm_preallocate_memory(struct hdspm *hdspm)
++static int snd_hdspm_preallocate_memory(struct hdspm *hdspm)
+ {
+ 	int err;
+ 	struct snd_pcm *pcm;
+@@ -6100,8 +6100,8 @@ static void hdspm_set_sgbuf(struct hdspm *hdspm,
+ 
+ 
+ /* ------------- ALSA Devices ---------------------------- */
+-static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
+-					  struct hdspm *hdspm)
++static int snd_hdspm_create_pcm(struct snd_card *card,
++				struct hdspm *hdspm)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -6136,8 +6136,8 @@ static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm)
+ 		snd_hdspm_flush_midi_input(hdspm, i);
+ }
+ 
+-static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
+-						   struct hdspm * hdspm)
++static int snd_hdspm_create_alsa_devices(struct snd_card *card,
++					 struct hdspm *hdspm)
+ {
+ 	int err, i;
+ 
+@@ -6195,8 +6195,9 @@ static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
+ 	return 0;
+ }
+ 
+-static int __devinit snd_hdspm_create(struct snd_card *card,
+-		struct hdspm *hdspm) {
++static int snd_hdspm_create(struct snd_card *card,
++			    struct hdspm *hdspm)
++{
+ 
+ 	struct pci_dev *pci = hdspm->pci;
+ 	int err;
+@@ -6569,8 +6570,8 @@ static void snd_hdspm_card_free(struct snd_card *card)
+ }
+ 
+ 
+-static int __devinit snd_hdspm_probe(struct pci_dev *pci,
+-				     const struct pci_device_id *pci_id)
++static int snd_hdspm_probe(struct pci_dev *pci,
++			   const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct hdspm *hdspm;
+@@ -6628,7 +6629,7 @@ static int __devinit snd_hdspm_probe(struct pci_dev *pci,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_hdspm_remove(struct pci_dev *pci)
++static void snd_hdspm_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -6638,7 +6639,7 @@ static struct pci_driver hdspm_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_hdspm_ids,
+ 	.probe = snd_hdspm_probe,
+-	.remove = __devexit_p(snd_hdspm_remove),
++	.remove = snd_hdspm_remove,
+ };
+ 
+ module_pci_driver(hdspm_driver);
+diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
+index a15fc100ab0c..773a67fff4cd 100644
+--- a/sound/pci/rme9652/rme9652.c
++++ b/sound/pci/rme9652/rme9652.c
+@@ -1757,7 +1757,7 @@ snd_rme9652_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buff
+ 	snd_iprintf(buffer, "\n");
+ }
+ 
+-static void __devinit snd_rme9652_proc_init(struct snd_rme9652 *rme9652)
++static void snd_rme9652_proc_init(struct snd_rme9652 *rme9652)
+ {
+ 	struct snd_info_entry *entry;
+ 
+@@ -1788,7 +1788,7 @@ static int snd_rme9652_free(struct snd_rme9652 *rme9652)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_rme9652_initialize_memory(struct snd_rme9652 *rme9652)
++static int snd_rme9652_initialize_memory(struct snd_rme9652 *rme9652)
+ {
+ 	unsigned long pb_bus, cb_bus;
+ 
+@@ -2414,8 +2414,8 @@ static struct snd_pcm_ops snd_rme9652_capture_ops = {
+ 	.copy =		snd_rme9652_capture_copy,
+ };
+ 
+-static int __devinit snd_rme9652_create_pcm(struct snd_card *card,
+-					 struct snd_rme9652 *rme9652)
++static int snd_rme9652_create_pcm(struct snd_card *card,
++				  struct snd_rme9652 *rme9652)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -2438,9 +2438,9 @@ static int __devinit snd_rme9652_create_pcm(struct snd_card *card,
+ 	return 0;
+ }
+ 
+-static int __devinit snd_rme9652_create(struct snd_card *card,
+-				     struct snd_rme9652 *rme9652,
+-				     int precise_ptr)
++static int snd_rme9652_create(struct snd_card *card,
++			      struct snd_rme9652 *rme9652,
++			      int precise_ptr)
+ {
+ 	struct pci_dev *pci = rme9652->pci;
+ 	int err;
+@@ -2578,8 +2578,8 @@ static void snd_rme9652_card_free(struct snd_card *card)
+ 		snd_rme9652_free(rme9652);
+ }
+ 
+-static int __devinit snd_rme9652_probe(struct pci_dev *pci,
+-				       const struct pci_device_id *pci_id)
++static int snd_rme9652_probe(struct pci_dev *pci,
++			     const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct snd_rme9652 *rme9652;
+@@ -2625,7 +2625,7 @@ static int __devinit snd_rme9652_probe(struct pci_dev *pci,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_rme9652_remove(struct pci_dev *pci)
++static void snd_rme9652_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -2635,7 +2635,7 @@ static struct pci_driver rme9652_driver = {
+ 	.name	  = KBUILD_MODNAME,
+ 	.id_table = snd_rme9652_ids,
+ 	.probe	  = snd_rme9652_probe,
+-	.remove	  = __devexit_p(snd_rme9652_remove),
++	.remove	  = snd_rme9652_remove,
+ };
+ 
+ module_pci_driver(rme9652_driver);
+diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c
+index 51e43407ebc5..550b9cfb8e3e 100644
+--- a/sound/pci/sis7019.c
++++ b/sound/pci/sis7019.c
+@@ -894,7 +894,7 @@ static struct snd_pcm_ops sis_capture_ops = {
+ 	.pointer = sis_pcm_pointer,
+ };
+ 
+-static int __devinit sis_pcm_create(struct sis7019 *sis)
++static int sis_pcm_create(struct sis7019 *sis)
+ {
+ 	struct snd_pcm *pcm;
+ 	int rc;
+@@ -1013,7 +1013,7 @@ static unsigned short sis_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
+ 					(reg << 8) | cmd[ac97->num]);
+ }
+ 
+-static int __devinit sis_mixer_create(struct sis7019 *sis)
++static int sis_mixer_create(struct sis7019 *sis)
+ {
+ 	struct snd_ac97_bus *bus;
+ 	struct snd_ac97_template ac97;
+@@ -1326,8 +1326,8 @@ static int sis_alloc_suspend(struct sis7019 *sis)
+ 	return 0;
+ }
+ 
+-static int __devinit sis_chip_create(struct snd_card *card,
+-					struct pci_dev *pci)
++static int sis_chip_create(struct snd_card *card,
++			   struct pci_dev *pci)
+ {
+ 	struct sis7019 *sis = card->private_data;
+ 	struct voice *voice;
+@@ -1417,8 +1417,8 @@ static int __devinit sis_chip_create(struct snd_card *card,
+ 	return rc;
+ }
+ 
+-static int __devinit snd_sis7019_probe(struct pci_dev *pci,
+-					const struct pci_device_id *pci_id)
++static int snd_sis7019_probe(struct pci_dev *pci,
++			     const struct pci_device_id *pci_id)
+ {
+ 	struct snd_card *card;
+ 	struct sis7019 *sis;
+@@ -1478,7 +1478,7 @@ static int __devinit snd_sis7019_probe(struct pci_dev *pci,
+ 	return rc;
+ }
+ 
+-static void __devexit snd_sis7019_remove(struct pci_dev *pci)
++static void snd_sis7019_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -1488,7 +1488,7 @@ static struct pci_driver sis7019_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_sis7019_ids,
+ 	.probe = snd_sis7019_probe,
+-	.remove = __devexit_p(snd_sis7019_remove),
++	.remove = snd_sis7019_remove,
+ 	.driver = {
+ 		.pm = SIS_PM_OPS,
+ 	},
+diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
+index baa9946bedf0..a2e7686e7ae3 100644
+--- a/sound/pci/sonicvibes.c
++++ b/sound/pci/sonicvibes.c
+@@ -877,7 +877,8 @@ static struct snd_pcm_ops snd_sonicvibes_capture_ops = {
+ 	.pointer =	snd_sonicvibes_capture_pointer,
+ };
+ 
+-static int __devinit snd_sonicvibes_pcm(struct sonicvibes * sonic, int device, struct snd_pcm ** rpcm)
++static int snd_sonicvibes_pcm(struct sonicvibes *sonic, int device,
++			      struct snd_pcm **rpcm)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -1087,7 +1088,7 @@ static int snd_sonicvibes_put_double(struct snd_kcontrol *kcontrol, struct snd_c
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_sonicvibes_controls[] __devinitdata = {
++static struct snd_kcontrol_new snd_sonicvibes_controls[] = {
+ SONICVIBES_DOUBLE("Capture Volume", 0, SV_IREG_LEFT_ADC, SV_IREG_RIGHT_ADC, 0, 0, 15, 0),
+ SONICVIBES_DOUBLE("Aux Playback Switch", 0, SV_IREG_LEFT_AUX1, SV_IREG_RIGHT_AUX1, 7, 7, 1, 1),
+ SONICVIBES_DOUBLE("Aux Playback Volume", 0, SV_IREG_LEFT_AUX1, SV_IREG_RIGHT_AUX1, 0, 0, 31, 1),
+@@ -1118,7 +1119,7 @@ static void snd_sonicvibes_master_free(struct snd_kcontrol *kcontrol)
+ 	sonic->master_volume = NULL;
+ }
+ 
+-static int __devinit snd_sonicvibes_mixer(struct sonicvibes * sonic)
++static int snd_sonicvibes_mixer(struct sonicvibes *sonic)
+ {
+ 	struct snd_card *card;
+ 	struct snd_kcontrol *kctl;
+@@ -1175,7 +1176,7 @@ static void snd_sonicvibes_proc_read(struct snd_info_entry *entry,
+ 	snd_iprintf(buffer, "MIDI to ext. Tx  : %s\n", tmp & 0x04 ? "on" : "off");
+ }
+ 
+-static void __devinit snd_sonicvibes_proc_init(struct sonicvibes * sonic)
++static void snd_sonicvibes_proc_init(struct sonicvibes *sonic)
+ {
+ 	struct snd_info_entry *entry;
+ 
+@@ -1188,10 +1189,10 @@ static void __devinit snd_sonicvibes_proc_init(struct sonicvibes * sonic)
+  */
+ 
+ #ifdef SUPPORT_JOYSTICK
+-static struct snd_kcontrol_new snd_sonicvibes_game_control __devinitdata =
++static struct snd_kcontrol_new snd_sonicvibes_game_control =
+ SONICVIBES_SINGLE("Joystick Speed", 0, SV_IREG_GAME_PORT, 1, 15, 0);
+ 
+-static int __devinit snd_sonicvibes_create_gameport(struct sonicvibes *sonic)
++static int snd_sonicvibes_create_gameport(struct sonicvibes *sonic)
+ {
+ 	struct gameport *gp;
+ 
+@@ -1246,11 +1247,11 @@ static int snd_sonicvibes_dev_free(struct snd_device *device)
+ 	return snd_sonicvibes_free(sonic);
+ }
+ 
+-static int __devinit snd_sonicvibes_create(struct snd_card *card,
+-					struct pci_dev *pci,
+-					int reverb,
+-					int mge,
+-					struct sonicvibes ** rsonic)
++static int snd_sonicvibes_create(struct snd_card *card,
++				 struct pci_dev *pci,
++				 int reverb,
++				 int mge,
++				 struct sonicvibes **rsonic)
+ {
+ 	struct sonicvibes *sonic;
+ 	unsigned int dmaa, dmac;
+@@ -1401,7 +1402,7 @@ static int __devinit snd_sonicvibes_create(struct snd_card *card,
+  *  MIDI section
+  */
+ 
+-static struct snd_kcontrol_new snd_sonicvibes_midi_controls[] __devinitdata = {
++static struct snd_kcontrol_new snd_sonicvibes_midi_controls[] = {
+ SONICVIBES_SINGLE("SonicVibes Wave Source RAM", 0, SV_IREG_WAVE_SOURCE, 0, 1, 0),
+ SONICVIBES_SINGLE("SonicVibes Wave Source RAM+ROM", 0, SV_IREG_WAVE_SOURCE, 1, 1, 0),
+ SONICVIBES_SINGLE("SonicVibes Onboard Synth", 0, SV_IREG_MPU401, 0, 1, 0),
+@@ -1422,8 +1423,8 @@ static void snd_sonicvibes_midi_input_close(struct snd_mpu401 * mpu)
+ 	outb(sonic->irqmask |= SV_MIDI_MASK, SV_REG(sonic, IRQMASK));
+ }
+ 
+-static int __devinit snd_sonicvibes_midi(struct sonicvibes * sonic,
+-					 struct snd_rawmidi *rmidi)
++static int snd_sonicvibes_midi(struct sonicvibes *sonic,
++			       struct snd_rawmidi *rmidi)
+ {
+ 	struct snd_mpu401 * mpu = rmidi->private_data;
+ 	struct snd_card *card = sonic->card;
+@@ -1441,8 +1442,8 @@ static int __devinit snd_sonicvibes_midi(struct sonicvibes * sonic,
+ 	return 0;
+ }
+ 
+-static int __devinit snd_sonic_probe(struct pci_dev *pci,
+-				     const struct pci_device_id *pci_id)
++static int snd_sonic_probe(struct pci_dev *pci,
++			   const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -1524,7 +1525,7 @@ static int __devinit snd_sonic_probe(struct pci_dev *pci,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_sonic_remove(struct pci_dev *pci)
++static void snd_sonic_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -1534,7 +1535,7 @@ static struct pci_driver sonicvibes_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_sonic_ids,
+ 	.probe = snd_sonic_probe,
+-	.remove = __devexit_p(snd_sonic_remove),
++	.remove = snd_sonic_remove,
+ };
+ 
+ module_pci_driver(sonicvibes_driver);
+diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
+index 8a6f1f76e870..1aefd6204a63 100644
+--- a/sound/pci/trident/trident.c
++++ b/sound/pci/trident/trident.c
+@@ -73,8 +73,8 @@ static DEFINE_PCI_DEVICE_TABLE(snd_trident_ids) = {
+ 
+ MODULE_DEVICE_TABLE(pci, snd_trident_ids);
+ 
+-static int __devinit snd_trident_probe(struct pci_dev *pci,
+-				       const struct pci_device_id *pci_id)
++static int snd_trident_probe(struct pci_dev *pci,
++			     const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -166,7 +166,7 @@ static int __devinit snd_trident_probe(struct pci_dev *pci,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_trident_remove(struct pci_dev *pci)
++static void snd_trident_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -176,7 +176,7 @@ static struct pci_driver trident_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_trident_ids,
+ 	.probe = snd_trident_probe,
+-	.remove = __devexit_p(snd_trident_remove),
++	.remove = snd_trident_remove,
+ #ifdef CONFIG_PM_SLEEP
+ 	.driver = {
+ 		.pm = &snd_trident_pm,
+diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
+index 06b10d1a76e5..fb0e1586a6f8 100644
+--- a/sound/pci/trident/trident_main.c
++++ b/sound/pci/trident/trident_main.c
+@@ -2171,8 +2171,8 @@ static struct snd_pcm_ops snd_trident_spdif_7018_ops = {
+   
+   ---------------------------------------------------------------------------*/
+ 
+-int __devinit snd_trident_pcm(struct snd_trident * trident,
+-			      int device, struct snd_pcm ** rpcm)
++int snd_trident_pcm(struct snd_trident *trident,
++		    int device, struct snd_pcm **rpcm)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -2229,8 +2229,8 @@ int __devinit snd_trident_pcm(struct snd_trident * trident,
+   
+   ---------------------------------------------------------------------------*/
+ 
+-int __devinit snd_trident_foldback_pcm(struct snd_trident * trident,
+-				       int device, struct snd_pcm ** rpcm)
++int snd_trident_foldback_pcm(struct snd_trident *trident,
++			     int device, struct snd_pcm **rpcm)
+ {
+ 	struct snd_pcm *foldback;
+ 	int err;
+@@ -2286,8 +2286,8 @@ int __devinit snd_trident_foldback_pcm(struct snd_trident * trident,
+   
+   ---------------------------------------------------------------------------*/
+ 
+-int __devinit snd_trident_spdif_pcm(struct snd_trident * trident,
+-				    int device, struct snd_pcm ** rpcm)
++int snd_trident_spdif_pcm(struct snd_trident *trident,
++			  int device, struct snd_pcm **rpcm)
+ {
+ 	struct snd_pcm *spdif;
+ 	int err;
+@@ -2371,7 +2371,7 @@ static int snd_trident_spdif_control_put(struct snd_kcontrol *kcontrol,
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_trident_spdif_control __devinitdata =
++static struct snd_kcontrol_new snd_trident_spdif_control =
+ {
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
+@@ -2434,7 +2434,7 @@ static int snd_trident_spdif_default_put(struct snd_kcontrol *kcontrol,
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_trident_spdif_default __devinitdata =
++static struct snd_kcontrol_new snd_trident_spdif_default =
+ {
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+ 	.name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
+@@ -2467,7 +2467,7 @@ static int snd_trident_spdif_mask_get(struct snd_kcontrol *kcontrol,
+ 	return 0;
+ }
+ 
+-static struct snd_kcontrol_new snd_trident_spdif_mask __devinitdata =
++static struct snd_kcontrol_new snd_trident_spdif_mask =
+ {
+ 	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+@@ -2529,7 +2529,7 @@ static int snd_trident_spdif_stream_put(struct snd_kcontrol *kcontrol,
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_trident_spdif_stream __devinitdata =
++static struct snd_kcontrol_new snd_trident_spdif_stream =
+ {
+ 	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+@@ -2579,7 +2579,7 @@ static int snd_trident_ac97_control_put(struct snd_kcontrol *kcontrol,
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_trident_ac97_rear_control __devinitdata =
++static struct snd_kcontrol_new snd_trident_ac97_rear_control =
+ {
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name =         "Rear Path",
+@@ -2637,7 +2637,7 @@ static int snd_trident_vol_control_put(struct snd_kcontrol *kcontrol,
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_trident_vol_music_control __devinitdata =
++static struct snd_kcontrol_new snd_trident_vol_music_control =
+ {
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name =         "Music Playback Volume",
+@@ -2648,7 +2648,7 @@ static struct snd_kcontrol_new snd_trident_vol_music_control __devinitdata =
+ 	.tlv = { .p = db_scale_gvol },
+ };
+ 
+-static struct snd_kcontrol_new snd_trident_vol_wave_control __devinitdata =
++static struct snd_kcontrol_new snd_trident_vol_wave_control =
+ {
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name =         "Wave Playback Volume",
+@@ -2715,7 +2715,7 @@ static int snd_trident_pcm_vol_control_put(struct snd_kcontrol *kcontrol,
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_trident_pcm_vol_control __devinitdata =
++static struct snd_kcontrol_new snd_trident_pcm_vol_control =
+ {
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name =         "PCM Front Playback Volume",
+@@ -2779,7 +2779,7 @@ static int snd_trident_pcm_pan_control_put(struct snd_kcontrol *kcontrol,
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_trident_pcm_pan_control __devinitdata =
++static struct snd_kcontrol_new snd_trident_pcm_pan_control =
+ {
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name =         "PCM Pan Playback Control",
+@@ -2836,7 +2836,7 @@ static int snd_trident_pcm_rvol_control_put(struct snd_kcontrol *kcontrol,
+ 
+ static const DECLARE_TLV_DB_SCALE(db_scale_crvol, -3175, 25, 1);
+ 
+-static struct snd_kcontrol_new snd_trident_pcm_rvol_control __devinitdata =
++static struct snd_kcontrol_new snd_trident_pcm_rvol_control =
+ {
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name =         "PCM Reverb Playback Volume",
+@@ -2892,7 +2892,7 @@ static int snd_trident_pcm_cvol_control_put(struct snd_kcontrol *kcontrol,
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_trident_pcm_cvol_control __devinitdata =
++static struct snd_kcontrol_new snd_trident_pcm_cvol_control =
+ {
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name =         "PCM Chorus Playback Volume",
+@@ -2972,7 +2972,7 @@ static int snd_trident_pcm_mixer_free(struct snd_trident *trident, struct snd_tr
+   
+   ---------------------------------------------------------------------------*/
+ 
+-static int __devinit snd_trident_mixer(struct snd_trident * trident, int pcm_spdif_device)
++static int snd_trident_mixer(struct snd_trident *trident, int pcm_spdif_device)
+ {
+ 	struct snd_ac97_template _ac97;
+ 	struct snd_card *card = trident->card;
+@@ -3191,7 +3191,7 @@ static int snd_trident_gameport_open(struct gameport *gameport, int mode)
+ 	}
+ }
+ 
+-int __devinit snd_trident_create_gameport(struct snd_trident *chip)
++int snd_trident_create_gameport(struct snd_trident *chip)
+ {
+ 	struct gameport *gp;
+ 
+@@ -3225,7 +3225,7 @@ static inline void snd_trident_free_gameport(struct snd_trident *chip)
+ 	}
+ }
+ #else
+-int __devinit snd_trident_create_gameport(struct snd_trident *chip) { return -ENOSYS; }
++int snd_trident_create_gameport(struct snd_trident *chip) { return -ENOSYS; }
+ static inline void snd_trident_free_gameport(struct snd_trident *chip) { }
+ #endif /* CONFIG_GAMEPORT */
+ 
+@@ -3329,7 +3329,7 @@ static void snd_trident_proc_read(struct snd_info_entry *entry,
+ 	}
+ }
+ 
+-static void __devinit snd_trident_proc_init(struct snd_trident * trident)
++static void snd_trident_proc_init(struct snd_trident *trident)
+ {
+ 	struct snd_info_entry *entry;
+ 	const char *s = "trident";
+@@ -3358,7 +3358,7 @@ static int snd_trident_dev_free(struct snd_device *device)
+   
+   ---------------------------------------------------------------------------*/
+ 
+-static int __devinit snd_trident_tlb_alloc(struct snd_trident *trident)
++static int snd_trident_tlb_alloc(struct snd_trident *trident)
+ {
+ 	int i;
+ 
+@@ -3539,7 +3539,7 @@ static int snd_trident_sis_init(struct snd_trident *trident)
+   
+   ---------------------------------------------------------------------------*/
+ 
+-int __devinit snd_trident_create(struct snd_card *card,
++int snd_trident_create(struct snd_card *card,
+ 		       struct pci_dev *pci,
+ 		       int pcm_streams,
+ 		       int pcm_spdif_device,
+diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
+index f0b4efdb483c..6442f611a07b 100644
+--- a/sound/pci/via82xx.c
++++ b/sound/pci/via82xx.c
+@@ -1437,7 +1437,7 @@ static void init_viadev(struct via82xx *chip, int idx, unsigned int reg_offset,
+ /*
+  * create pcm instances for VIA8233, 8233C and 8235 (not 8233A)
+  */
+-static int __devinit snd_via8233_pcm_new(struct via82xx *chip)
++static int snd_via8233_pcm_new(struct via82xx *chip)
+ {
+ 	struct snd_pcm *pcm;
+ 	struct snd_pcm_chmap *chmap;
+@@ -1505,7 +1505,7 @@ static int __devinit snd_via8233_pcm_new(struct via82xx *chip)
+ /*
+  * create pcm instances for VIA8233A
+  */
+-static int __devinit snd_via8233a_pcm_new(struct via82xx *chip)
++static int snd_via8233a_pcm_new(struct via82xx *chip)
+ {
+ 	struct snd_pcm *pcm;
+ 	struct snd_pcm_chmap *chmap;
+@@ -1566,7 +1566,7 @@ static int __devinit snd_via8233a_pcm_new(struct via82xx *chip)
+ /*
+  * create a pcm instance for via686a/b
+  */
+-static int __devinit snd_via686_pcm_new(struct via82xx *chip)
++static int snd_via686_pcm_new(struct via82xx *chip)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -1643,7 +1643,7 @@ static int snd_via8233_capture_source_put(struct snd_kcontrol *kcontrol,
+ 	return val != oval;
+ }
+ 
+-static struct snd_kcontrol_new snd_via8233_capture_source __devinitdata = {
++static struct snd_kcontrol_new snd_via8233_capture_source = {
+ 	.name = "Input Source Select",
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.info = snd_via8233_capture_source_info,
+@@ -1683,7 +1683,7 @@ static int snd_via8233_dxs3_spdif_put(struct snd_kcontrol *kcontrol,
+ 	return 0;
+ }
+ 
+-static struct snd_kcontrol_new snd_via8233_dxs3_spdif_control __devinitdata = {
++static struct snd_kcontrol_new snd_via8233_dxs3_spdif_control = {
+ 	.name = SNDRV_CTL_NAME_IEC958("Output ",NONE,SWITCH),
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.info = snd_via8233_dxs3_spdif_info,
+@@ -1772,7 +1772,7 @@ static int snd_via8233_pcmdxs_volume_put(struct snd_kcontrol *kcontrol,
+ 
+ static const DECLARE_TLV_DB_SCALE(db_scale_dxs, -4650, 150, 1);
+ 
+-static struct snd_kcontrol_new snd_via8233_pcmdxs_volume_control __devinitdata = {
++static struct snd_kcontrol_new snd_via8233_pcmdxs_volume_control = {
+ 	.name = "PCM Playback Volume",
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+@@ -1783,7 +1783,7 @@ static struct snd_kcontrol_new snd_via8233_pcmdxs_volume_control __devinitdata =
+ 	.tlv = { .p = db_scale_dxs }
+ };
+ 
+-static struct snd_kcontrol_new snd_via8233_dxs_volume_control __devinitdata = {
++static struct snd_kcontrol_new snd_via8233_dxs_volume_control = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ 	.device = 0,
+ 	/* .subdevice set later */
+@@ -1895,7 +1895,7 @@ static struct ac97_quirk ac97_quirks[] = {
+ 	{ } /* terminator */
+ };
+ 
+-static int __devinit snd_via82xx_mixer_new(struct via82xx *chip, const char *quirk_override)
++static int snd_via82xx_mixer_new(struct via82xx *chip, const char *quirk_override)
+ {
+ 	struct snd_ac97_template ac97;
+ 	int err;
+@@ -1930,7 +1930,7 @@ static int __devinit snd_via82xx_mixer_new(struct via82xx *chip, const char *qui
+ 
+ #ifdef SUPPORT_JOYSTICK
+ #define JOYSTICK_ADDR	0x200
+-static int __devinit snd_via686_create_gameport(struct via82xx *chip, unsigned char *legacy)
++static int snd_via686_create_gameport(struct via82xx *chip, unsigned char *legacy)
+ {
+ 	struct gameport *gp;
+ 	struct resource *r;
+@@ -1990,7 +1990,7 @@ static inline void snd_via686_free_gameport(struct via82xx *chip) { }
+  *
+  */
+ 
+-static int __devinit snd_via8233_init_misc(struct via82xx *chip)
++static int snd_via8233_init_misc(struct via82xx *chip)
+ {
+ 	int i, err, caps;
+ 	unsigned char val;
+@@ -2047,7 +2047,7 @@ static int __devinit snd_via8233_init_misc(struct via82xx *chip)
+ 	return 0;
+ }
+ 
+-static int __devinit snd_via686_init_misc(struct via82xx *chip)
++static int snd_via686_init_misc(struct via82xx *chip)
+ {
+ 	unsigned char legacy, legacy_cfg;
+ 	int rev_h = 0;
+@@ -2137,7 +2137,7 @@ static void snd_via82xx_proc_read(struct snd_info_entry *entry,
+ 	}
+ }
+ 
+-static void __devinit snd_via82xx_proc_init(struct via82xx *chip)
++static void snd_via82xx_proc_init(struct via82xx *chip)
+ {
+ 	struct snd_info_entry *entry;
+ 
+@@ -2370,12 +2370,12 @@ static int snd_via82xx_dev_free(struct snd_device *device)
+ 	return snd_via82xx_free(chip);
+ }
+ 
+-static int __devinit snd_via82xx_create(struct snd_card *card,
+-					struct pci_dev *pci,
+-					int chip_type,
+-					int revision,
+-					unsigned int ac97_clock,
+-					struct via82xx ** r_via)
++static int snd_via82xx_create(struct snd_card *card,
++			      struct pci_dev *pci,
++			      int chip_type,
++			      int revision,
++			      unsigned int ac97_clock,
++			      struct via82xx **r_via)
+ {
+ 	struct via82xx *chip;
+ 	int err;
+@@ -2452,7 +2452,7 @@ struct via823x_info {
+ 	char *name;
+ 	int type;
+ };
+-static struct via823x_info via823x_cards[] __devinitdata = {
++static struct via823x_info via823x_cards[] = {
+ 	{ VIA_REV_PRE_8233, "VIA 8233-Pre", TYPE_VIA8233 },
+ 	{ VIA_REV_8233C, "VIA 8233C", TYPE_VIA8233 },
+ 	{ VIA_REV_8233, "VIA 8233", TYPE_VIA8233 },
+@@ -2466,7 +2466,7 @@ static struct via823x_info via823x_cards[] __devinitdata = {
+  * auto detection of DXS channel supports.
+  */
+ 
+-static struct snd_pci_quirk dxs_whitelist[] __devinitdata = {
++static struct snd_pci_quirk dxs_whitelist[] = {
+ 	SND_PCI_QUIRK(0x1005, 0x4710, "Avance Logic Mobo", VIA_DXS_ENABLE),
+ 	SND_PCI_QUIRK(0x1019, 0x0996, "ESC Mobo", VIA_DXS_48K),
+ 	SND_PCI_QUIRK(0x1019, 0x0a81, "ECS K7VTA3 v8.0", VIA_DXS_NO_VRA),
+@@ -2510,7 +2510,7 @@ static struct snd_pci_quirk dxs_whitelist[] __devinitdata = {
+ 	{ } /* terminator */
+ };
+ 
+-static int __devinit check_dxs_list(struct pci_dev *pci, int revision)
++static int check_dxs_list(struct pci_dev *pci, int revision)
+ {
+ 	const struct snd_pci_quirk *w;
+ 
+@@ -2535,8 +2535,8 @@ static int __devinit check_dxs_list(struct pci_dev *pci, int revision)
+ 	return VIA_DXS_48K;
+ };
+ 
+-static int __devinit snd_via82xx_probe(struct pci_dev *pci,
+-				       const struct pci_device_id *pci_id)
++static int snd_via82xx_probe(struct pci_dev *pci,
++			     const struct pci_device_id *pci_id)
+ {
+ 	struct snd_card *card;
+ 	struct via82xx *chip;
+@@ -2643,7 +2643,7 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
+ 	return err;
+ }
+ 
+-static void __devexit snd_via82xx_remove(struct pci_dev *pci)
++static void snd_via82xx_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -2653,7 +2653,7 @@ static struct pci_driver via82xx_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_via82xx_ids,
+ 	.probe = snd_via82xx_probe,
+-	.remove = __devexit_p(snd_via82xx_remove),
++	.remove = snd_via82xx_remove,
+ 	.driver = {
+ 		.pm = SND_VIA82XX_PM_OPS,
+ 	},
+diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
+index 8e0efc416f22..4f5fd80b7e56 100644
+--- a/sound/pci/via82xx_modem.c
++++ b/sound/pci/via82xx_modem.c
+@@ -836,7 +836,7 @@ static void init_viadev(struct via82xx_modem *chip, int idx, unsigned int reg_of
+ /*
+  * create a pcm instance for via686a/b
+  */
+-static int __devinit snd_via686_pcm_new(struct via82xx_modem *chip)
++static int snd_via686_pcm_new(struct via82xx_modem *chip)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -885,7 +885,7 @@ static void snd_via82xx_mixer_free_ac97(struct snd_ac97 *ac97)
+ }
+ 
+ 
+-static int __devinit snd_via82xx_mixer_new(struct via82xx_modem *chip)
++static int snd_via82xx_mixer_new(struct via82xx_modem *chip)
+ {
+ 	struct snd_ac97_template ac97;
+ 	int err;
+@@ -928,7 +928,7 @@ static void snd_via82xx_proc_read(struct snd_info_entry *entry, struct snd_info_
+ 	}
+ }
+ 
+-static void __devinit snd_via82xx_proc_init(struct via82xx_modem *chip)
++static void snd_via82xx_proc_init(struct via82xx_modem *chip)
+ {
+ 	struct snd_info_entry *entry;
+ 
+@@ -1103,12 +1103,12 @@ static int snd_via82xx_dev_free(struct snd_device *device)
+ 	return snd_via82xx_free(chip);
+ }
+ 
+-static int __devinit snd_via82xx_create(struct snd_card *card,
+-					struct pci_dev *pci,
+-					int chip_type,
+-					int revision,
+-					unsigned int ac97_clock,
+-					struct via82xx_modem ** r_via)
++static int snd_via82xx_create(struct snd_card *card,
++			      struct pci_dev *pci,
++			      int chip_type,
++			      int revision,
++			      unsigned int ac97_clock,
++			      struct via82xx_modem **r_via)
+ {
+ 	struct via82xx_modem *chip;
+ 	int err;
+@@ -1168,8 +1168,8 @@ static int __devinit snd_via82xx_create(struct snd_card *card,
+ }
+ 
+ 
+-static int __devinit snd_via82xx_probe(struct pci_dev *pci,
+-				       const struct pci_device_id *pci_id)
++static int snd_via82xx_probe(struct pci_dev *pci,
++			     const struct pci_device_id *pci_id)
+ {
+ 	struct snd_card *card;
+ 	struct via82xx_modem *chip;
+@@ -1224,7 +1224,7 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
+ 	return err;
+ }
+ 
+-static void __devexit snd_via82xx_remove(struct pci_dev *pci)
++static void snd_via82xx_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -1234,7 +1234,7 @@ static struct pci_driver via82xx_modem_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_via82xx_modem_ids,
+ 	.probe = snd_via82xx_probe,
+-	.remove = __devexit_p(snd_via82xx_remove),
++	.remove = snd_via82xx_remove,
+ 	.driver = {
+ 		.pm = SND_VIA82XX_PM_OPS,
+ 	},
+diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
+index fdfbaf857233..e2f1ab37e154 100644
+--- a/sound/pci/vx222/vx222.c
++++ b/sound/pci/vx222/vx222.c
+@@ -134,9 +134,9 @@ static int snd_vx222_dev_free(struct snd_device *device)
+ }
+ 
+ 
+-static int __devinit snd_vx222_create(struct snd_card *card, struct pci_dev *pci,
+-				      struct snd_vx_hardware *hw,
+-				      struct snd_vx222 **rchip)
++static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci,
++			    struct snd_vx_hardware *hw,
++			    struct snd_vx222 **rchip)
+ {
+ 	struct vx_core *chip;
+ 	struct snd_vx222 *vx;
+@@ -188,8 +188,8 @@ static int __devinit snd_vx222_create(struct snd_card *card, struct pci_dev *pci
+ }
+ 
+ 
+-static int __devinit snd_vx222_probe(struct pci_dev *pci,
+-				     const struct pci_device_id *pci_id)
++static int snd_vx222_probe(struct pci_dev *pci,
++			   const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -251,7 +251,7 @@ static int __devinit snd_vx222_probe(struct pci_dev *pci,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_vx222_remove(struct pci_dev *pci)
++static void snd_vx222_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -300,7 +300,7 @@ static struct pci_driver vx222_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_vx222_ids,
+ 	.probe = snd_vx222_probe,
+-	.remove = __devexit_p(snd_vx222_remove),
++	.remove = snd_vx222_remove,
+ 	.driver = {
+ 		.pm = SND_VX222_PM_OPS,
+ 	},
+diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
+index e01fe34db9ec..01c49655a3c1 100644
+--- a/sound/pci/ymfpci/ymfpci.c
++++ b/sound/pci/ymfpci/ymfpci.c
+@@ -79,8 +79,8 @@ static DEFINE_PCI_DEVICE_TABLE(snd_ymfpci_ids) = {
+ MODULE_DEVICE_TABLE(pci, snd_ymfpci_ids);
+ 
+ #ifdef SUPPORT_JOYSTICK
+-static int __devinit snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev,
+-						int legacy_ctrl, int legacy_ctrl2)
++static int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev,
++				      int legacy_ctrl, int legacy_ctrl2)
+ {
+ 	struct gameport *gp;
+ 	struct resource *r = NULL;
+@@ -167,8 +167,8 @@ static inline int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev, i
+ void snd_ymfpci_free_gameport(struct snd_ymfpci *chip) { }
+ #endif /* SUPPORT_JOYSTICK */
+ 
+-static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci,
+-					   const struct pci_device_id *pci_id)
++static int snd_card_ymfpci_probe(struct pci_dev *pci,
++				 const struct pci_device_id *pci_id)
+ {
+ 	static int dev;
+ 	struct snd_card *card;
+@@ -344,7 +344,7 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci,
+ 	return 0;
+ }
+ 
+-static void __devexit snd_card_ymfpci_remove(struct pci_dev *pci)
++static void snd_card_ymfpci_remove(struct pci_dev *pci)
+ {
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+@@ -354,7 +354,7 @@ static struct pci_driver ymfpci_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = snd_ymfpci_ids,
+ 	.probe = snd_card_ymfpci_probe,
+-	.remove = __devexit_p(snd_card_ymfpci_remove),
++	.remove = snd_card_ymfpci_remove,
+ #ifdef CONFIG_PM_SLEEP
+ 	.driver = {
+ 		.pm = &snd_ymfpci_pm,
+diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
+index 60e8cb24bd44..22056c50fe39 100644
+--- a/sound/pci/ymfpci/ymfpci_main.c
++++ b/sound/pci/ymfpci/ymfpci_main.c
+@@ -597,7 +597,7 @@ static void snd_ymfpci_pcm_init_voice(struct snd_ymfpci_pcm *ypcm, unsigned int
+ 	}
+ }
+ 
+-static int __devinit snd_ymfpci_ac3_init(struct snd_ymfpci *chip)
++static int snd_ymfpci_ac3_init(struct snd_ymfpci *chip)
+ {
+ 	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+ 				4096, &chip->ac3_tmp_base) < 0)
+@@ -1143,7 +1143,7 @@ static struct snd_pcm_ops snd_ymfpci_capture_rec_ops = {
+ 	.pointer =		snd_ymfpci_capture_pointer,
+ };
+ 
+-int __devinit snd_ymfpci_pcm(struct snd_ymfpci *chip, int device, struct snd_pcm ** rpcm)
++int snd_ymfpci_pcm(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -1186,7 +1186,7 @@ static struct snd_pcm_ops snd_ymfpci_capture_ac97_ops = {
+ 	.pointer =		snd_ymfpci_capture_pointer,
+ };
+ 
+-int __devinit snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device, struct snd_pcm ** rpcm)
++int snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -1224,7 +1224,8 @@ static struct snd_pcm_ops snd_ymfpci_playback_spdif_ops = {
+ 	.pointer =		snd_ymfpci_playback_pointer,
+ };
+ 
+-int __devinit snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device, struct snd_pcm ** rpcm)
++int snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device,
++			 struct snd_pcm **rpcm)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -1269,7 +1270,8 @@ static const struct snd_pcm_chmap_elem surround_map[] = {
+ 	{ }
+ };
+ 
+-int __devinit snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device, struct snd_pcm ** rpcm)
++int snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device,
++		       struct snd_pcm **rpcm)
+ {
+ 	struct snd_pcm *pcm;
+ 	int err;
+@@ -1338,7 +1340,7 @@ static int snd_ymfpci_spdif_default_put(struct snd_kcontrol *kcontrol,
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_ymfpci_spdif_default __devinitdata =
++static struct snd_kcontrol_new snd_ymfpci_spdif_default =
+ {
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+ 	.name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
+@@ -1366,7 +1368,7 @@ static int snd_ymfpci_spdif_mask_get(struct snd_kcontrol *kcontrol,
+ 	return 0;
+ }
+ 
+-static struct snd_kcontrol_new snd_ymfpci_spdif_mask __devinitdata =
++static struct snd_kcontrol_new snd_ymfpci_spdif_mask =
+ {
+ 	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+@@ -1413,7 +1415,7 @@ static int snd_ymfpci_spdif_stream_put(struct snd_kcontrol *kcontrol,
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_ymfpci_spdif_stream __devinitdata =
++static struct snd_kcontrol_new snd_ymfpci_spdif_stream =
+ {
+ 	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+@@ -1461,7 +1463,7 @@ static int snd_ymfpci_drec_source_put(struct snd_kcontrol *kcontrol, struct snd_
+ 	return reg != old_reg;
+ }
+ 
+-static struct snd_kcontrol_new snd_ymfpci_drec_source __devinitdata = {
++static struct snd_kcontrol_new snd_ymfpci_drec_source = {
+ 	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name =		"Direct Recording Source",
+@@ -1631,7 +1633,7 @@ static int snd_ymfpci_put_dup4ch(struct snd_kcontrol *kcontrol, struct snd_ctl_e
+ 	return change;
+ }
+ 
+-static struct snd_kcontrol_new snd_ymfpci_dup4ch __devinitdata = {
++static struct snd_kcontrol_new snd_ymfpci_dup4ch = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "4ch Duplication",
+ 	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+@@ -1640,7 +1642,7 @@ static struct snd_kcontrol_new snd_ymfpci_dup4ch __devinitdata = {
+ 	.put = snd_ymfpci_put_dup4ch,
+ };
+ 
+-static struct snd_kcontrol_new snd_ymfpci_controls[] __devinitdata = {
++static struct snd_kcontrol_new snd_ymfpci_controls[] = {
+ {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.name = "Wave Playback Volume",
+@@ -1734,7 +1736,7 @@ static int snd_ymfpci_gpio_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
+ 	return 0;
+ }
+ 
+-static struct snd_kcontrol_new snd_ymfpci_rear_shared __devinitdata = {
++static struct snd_kcontrol_new snd_ymfpci_rear_shared = {
+ 	.name = "Shared Rear/Line-In Switch",
+ 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 	.info = snd_ymfpci_gpio_sw_info,
+@@ -1798,7 +1800,7 @@ static int snd_ymfpci_pcm_vol_put(struct snd_kcontrol *kcontrol,
+ 	return 0;
+ }
+ 
+-static struct snd_kcontrol_new snd_ymfpci_pcm_volume __devinitdata = {
++static struct snd_kcontrol_new snd_ymfpci_pcm_volume = {
+ 	.iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ 	.name = "PCM Playback Volume",
+ 	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+@@ -1825,7 +1827,7 @@ static void snd_ymfpci_mixer_free_ac97(struct snd_ac97 *ac97)
+ 	chip->ac97 = NULL;
+ }
+ 
+-int __devinit snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch)
++int snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch)
+ {
+ 	struct snd_ac97_template ac97;
+ 	struct snd_kcontrol *kctl;
+@@ -1969,7 +1971,7 @@ static struct snd_timer_hardware snd_ymfpci_timer_hw = {
+ 	.precise_resolution = snd_ymfpci_timer_precise_resolution,
+ };
+ 
+-int __devinit snd_ymfpci_timer(struct snd_ymfpci *chip, int device)
++int snd_ymfpci_timer(struct snd_ymfpci *chip, int device)
+ {
+ 	struct snd_timer *timer = NULL;
+ 	struct snd_timer_id tid;
+@@ -2005,7 +2007,7 @@ static void snd_ymfpci_proc_read(struct snd_info_entry *entry,
+ 		snd_iprintf(buffer, "%04x: %04x\n", i, snd_ymfpci_readl(chip, i));
+ }
+ 
+-static int __devinit snd_ymfpci_proc_init(struct snd_card *card, struct snd_ymfpci *chip)
++static int snd_ymfpci_proc_init(struct snd_card *card, struct snd_ymfpci *chip)
+ {
+ 	struct snd_info_entry *entry;
+ 	
+@@ -2127,7 +2129,7 @@ static void snd_ymfpci_download_image(struct snd_ymfpci *chip)
+ 	snd_ymfpci_enable_dsp(chip);
+ }
+ 
+-static int __devinit snd_ymfpci_memalloc(struct snd_ymfpci *chip)
++static int snd_ymfpci_memalloc(struct snd_ymfpci *chip)
+ {
+ 	long size, playback_ctrl_size;
+ 	int voice, bank, reg;
+@@ -2393,10 +2395,10 @@ static int snd_ymfpci_resume(struct device *dev)
+ SIMPLE_DEV_PM_OPS(snd_ymfpci_pm, snd_ymfpci_suspend, snd_ymfpci_resume);
+ #endif /* CONFIG_PM_SLEEP */
+ 
+-int __devinit snd_ymfpci_create(struct snd_card *card,
+-				struct pci_dev * pci,
+-				unsigned short old_legacy_ctrl,
+-				struct snd_ymfpci ** rchip)
++int snd_ymfpci_create(struct snd_card *card,
++		      struct pci_dev *pci,
++		      unsigned short old_legacy_ctrl,
++		      struct snd_ymfpci **rchip)
+ {
+ 	struct snd_ymfpci *chip;
+ 	int err;

commit 9e2ff36beae4bedbad2a69d458f9404f35fcb528
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:56:43 2012 -0500
+
+    rtlwifi: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
+index 086140cba026..3deacafdcd5e 100644
+--- a/drivers/net/wireless/rtlwifi/pci.c
++++ b/drivers/net/wireless/rtlwifi/pci.c
+@@ -1756,7 +1756,7 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
+ 	return true;
+ }
+ 
+-int __devinit rtl_pci_probe(struct pci_dev *pdev,
++int rtl_pci_probe(struct pci_dev *pdev,
+ 			    const struct pci_device_id *id)
+ {
+ 	struct ieee80211_hw *hw = NULL;
+diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h
+index 7ea50a32bafb..65b08f50022e 100644
+--- a/drivers/net/wireless/rtlwifi/pci.h
++++ b/drivers/net/wireless/rtlwifi/pci.h
+@@ -236,7 +236,7 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw);
+ 
+ extern struct rtl_intf_ops rtl_pci_ops;
+ 
+-int __devinit rtl_pci_probe(struct pci_dev *pdev,
++int rtl_pci_probe(struct pci_dev *pdev,
+ 			    const struct pci_device_id *id);
+ void rtl_pci_disconnect(struct pci_dev *pdev);
+ #ifdef CONFIG_PM_SLEEP
+diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
+index e17f670d5c8e..03c6d18b2e07 100644
+--- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
++++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
+@@ -352,7 +352,7 @@ static struct rtl_hal_cfg rtl92de_hal_cfg = {
+ 	.maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15,
+ };
+ 
+-static struct pci_device_id rtl92de_pci_ids[] __devinitdata = {
++static struct pci_device_id rtl92de_pci_ids[] = {
+ 	{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8193, rtl92de_hal_cfg)},
+ 	{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x002B, rtl92de_hal_cfg)},
+ 	{},
+diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
+index 45c3443fccc8..cecc377e9e61 100644
+--- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
++++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
+@@ -400,7 +400,7 @@ static struct rtl_hal_cfg rtl92se_hal_cfg = {
+ 	.maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15,
+ };
+ 
+-static struct pci_device_id rtl92se_pci_ids[] __devinitdata = {
++static struct pci_device_id rtl92se_pci_ids[] = {
+ 	{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8192, rtl92se_hal_cfg)},
+ 	{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8171, rtl92se_hal_cfg)},
+ 	{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8172, rtl92se_hal_cfg)},
+diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c
+index e3ea4b346889..29f0969e4ba0 100644
+--- a/drivers/net/wireless/rtlwifi/usb.c
++++ b/drivers/net/wireless/rtlwifi/usb.c
+@@ -940,7 +940,7 @@ static struct rtl_intf_ops rtl_usb_ops = {
+ 	.waitq_insert = rtl_usb_tx_chk_waitq_insert,
+ };
+ 
+-int __devinit rtl_usb_probe(struct usb_interface *intf,
++int rtl_usb_probe(struct usb_interface *intf,
+ 			const struct usb_device_id *id)
+ {
+ 	int err;
+diff --git a/drivers/net/wireless/rtlwifi/usb.h b/drivers/net/wireless/rtlwifi/usb.h
+index 43846b329153..5235136f6dd2 100644
+--- a/drivers/net/wireless/rtlwifi/usb.h
++++ b/drivers/net/wireless/rtlwifi/usb.h
+@@ -156,7 +156,7 @@ struct rtl_usb_priv {
+ 
+ 
+ 
+-int __devinit rtl_usb_probe(struct usb_interface *intf,
++int rtl_usb_probe(struct usb_interface *intf,
+ 			    const struct usb_device_id *id);
+ void rtl_usb_disconnect(struct usb_interface *intf);
+ int rtl_usb_suspend(struct usb_interface *pusb_intf, pm_message_t message);

commit b74324d1048271240f65b2d91816d15e72dd80dd
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:56:42 2012 -0500
+
+    wlcore/wl18xx/wl12xx: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Luciano Coelho 
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/ti/wl1251/sdio.c b/drivers/net/wireless/ti/wl1251/sdio.c
+index e2750a12c6f1..e57ee48edff6 100644
+--- a/drivers/net/wireless/ti/wl1251/sdio.c
++++ b/drivers/net/wireless/ti/wl1251/sdio.c
+@@ -305,7 +305,7 @@ static int wl1251_sdio_probe(struct sdio_func *func,
+ 	return ret;
+ }
+ 
+-static void __devexit wl1251_sdio_remove(struct sdio_func *func)
++static void wl1251_sdio_remove(struct sdio_func *func)
+ {
+ 	struct wl1251 *wl = sdio_get_drvdata(func);
+ 	struct wl1251_sdio *wl_sdio = wl->if_priv;
+@@ -347,7 +347,7 @@ static struct sdio_driver wl1251_sdio_driver = {
+ 	.name		= "wl1251_sdio",
+ 	.id_table	= wl1251_devices,
+ 	.probe		= wl1251_sdio_probe,
+-	.remove		= __devexit_p(wl1251_sdio_remove),
++	.remove		= wl1251_sdio_remove,
+ 	.drv.pm		= &wl1251_sdio_pm_ops,
+ };
+ 
+diff --git a/drivers/net/wireless/ti/wl1251/spi.c b/drivers/net/wireless/ti/wl1251/spi.c
+index 567660cd2fcd..3b266d3231a3 100644
+--- a/drivers/net/wireless/ti/wl1251/spi.c
++++ b/drivers/net/wireless/ti/wl1251/spi.c
+@@ -237,7 +237,7 @@ static const struct wl1251_if_operations wl1251_spi_ops = {
+ 	.power = wl1251_spi_set_power,
+ };
+ 
+-static int __devinit wl1251_spi_probe(struct spi_device *spi)
++static int wl1251_spi_probe(struct spi_device *spi)
+ {
+ 	struct wl12xx_platform_data *pdata;
+ 	struct ieee80211_hw *hw;
+@@ -309,7 +309,7 @@ static int __devinit wl1251_spi_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit wl1251_spi_remove(struct spi_device *spi)
++static int wl1251_spi_remove(struct spi_device *spi)
+ {
+ 	struct wl1251 *wl = dev_get_drvdata(&spi->dev);
+ 
+@@ -326,7 +326,7 @@ static struct spi_driver wl1251_spi_driver = {
+ 	},
+ 
+ 	.probe		= wl1251_spi_probe,
+-	.remove		= __devexit_p(wl1251_spi_remove),
++	.remove		= wl1251_spi_remove,
+ };
+ 
+ static int __init wl1251_spi_init(void)
+diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
+index dadf1dbb002a..e5f5f8f39144 100644
+--- a/drivers/net/wireless/ti/wl12xx/main.c
++++ b/drivers/net/wireless/ti/wl12xx/main.c
+@@ -1696,7 +1696,7 @@ static int wl12xx_setup(struct wl1271 *wl)
+ 	return 0;
+ }
+ 
+-static int __devinit wl12xx_probe(struct platform_device *pdev)
++static int wl12xx_probe(struct platform_device *pdev)
+ {
+ 	struct wl1271 *wl;
+ 	struct ieee80211_hw *hw;
+@@ -1725,7 +1725,7 @@ static int __devinit wl12xx_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static const struct platform_device_id wl12xx_id_table[] __devinitconst = {
++static const struct platform_device_id wl12xx_id_table[] = {
+ 	{ "wl12xx", 0 },
+ 	{  } /* Terminating Entry */
+ };
+@@ -1733,7 +1733,7 @@ MODULE_DEVICE_TABLE(platform, wl12xx_id_table);
+ 
+ static struct platform_driver wl12xx_driver = {
+ 	.probe		= wl12xx_probe,
+-	.remove		= __devexit_p(wlcore_remove),
++	.remove		= wlcore_remove,
+ 	.id_table	= wl12xx_id_table,
+ 	.driver = {
+ 		.name	= "wl12xx_driver",
+diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
+index a39682a7c25f..8d8c1f8c63b7 100644
+--- a/drivers/net/wireless/ti/wl18xx/main.c
++++ b/drivers/net/wireless/ti/wl18xx/main.c
+@@ -1499,7 +1499,7 @@ static int wl18xx_setup(struct wl1271 *wl)
+ 	return 0;
+ }
+ 
+-static int __devinit wl18xx_probe(struct platform_device *pdev)
++static int wl18xx_probe(struct platform_device *pdev)
+ {
+ 	struct wl1271 *wl;
+ 	struct ieee80211_hw *hw;
+@@ -1528,7 +1528,7 @@ static int __devinit wl18xx_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static const struct platform_device_id wl18xx_id_table[] __devinitconst = {
++static const struct platform_device_id wl18xx_id_table[] = {
+ 	{ "wl18xx", 0 },
+ 	{  } /* Terminating Entry */
+ };
+@@ -1536,7 +1536,7 @@ MODULE_DEVICE_TABLE(platform, wl18xx_id_table);
+ 
+ static struct platform_driver wl18xx_driver = {
+ 	.probe		= wl18xx_probe,
+-	.remove		= __devexit_p(wlcore_remove),
++	.remove		= wlcore_remove,
+ 	.id_table	= wl18xx_id_table,
+ 	.driver = {
+ 		.name	= "wl18xx_driver",
+diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
+index 4f1a05b92d2d..ea9d8e011bc9 100644
+--- a/drivers/net/wireless/ti/wlcore/main.c
++++ b/drivers/net/wireless/ti/wlcore/main.c
+@@ -5660,7 +5660,7 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context)
+ 	complete_all(&wl->nvs_loading_complete);
+ }
+ 
+-int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
++int wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
+ {
+ 	int ret;
+ 
+@@ -5683,7 +5683,7 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
+ }
+ EXPORT_SYMBOL_GPL(wlcore_probe);
+ 
+-int __devexit wlcore_remove(struct platform_device *pdev)
++int wlcore_remove(struct platform_device *pdev)
+ {
+ 	struct wl1271 *wl = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c
+index 73ace4b2604e..646f703ae739 100644
+--- a/drivers/net/wireless/ti/wlcore/sdio.c
++++ b/drivers/net/wireless/ti/wlcore/sdio.c
+@@ -54,7 +54,7 @@ struct wl12xx_sdio_glue {
+ 	struct platform_device *core;
+ };
+ 
+-static const struct sdio_device_id wl1271_devices[] __devinitconst = {
++static const struct sdio_device_id wl1271_devices[] = {
+ 	{ SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271) },
+ 	{}
+ };
+@@ -214,7 +214,7 @@ static struct wl1271_if_operations sdio_ops = {
+ 	.set_block_size = wl1271_sdio_set_block_size,
+ };
+ 
+-static int __devinit wl1271_probe(struct sdio_func *func,
++static int wl1271_probe(struct sdio_func *func,
+ 				  const struct sdio_device_id *id)
+ {
+ 	struct wl12xx_platform_data *wlan_data;
+@@ -319,7 +319,7 @@ static int __devinit wl1271_probe(struct sdio_func *func,
+ 	return ret;
+ }
+ 
+-static void __devexit wl1271_remove(struct sdio_func *func)
++static void wl1271_remove(struct sdio_func *func)
+ {
+ 	struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func);
+ 
+@@ -384,7 +384,7 @@ static struct sdio_driver wl1271_sdio_driver = {
+ 	.name		= "wl1271_sdio",
+ 	.id_table	= wl1271_devices,
+ 	.probe		= wl1271_probe,
+-	.remove		= __devexit_p(wl1271_remove),
++	.remove		= wl1271_remove,
+ #ifdef CONFIG_PM
+ 	.drv = {
+ 		.pm = &wl1271_sdio_pm_ops,
+diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c
+index a519bc3adec1..f06f4770ce02 100644
+--- a/drivers/net/wireless/ti/wlcore/spi.c
++++ b/drivers/net/wireless/ti/wlcore/spi.c
+@@ -324,7 +324,7 @@ static struct wl1271_if_operations spi_ops = {
+ 	.set_block_size = NULL,
+ };
+ 
+-static int __devinit wl1271_probe(struct spi_device *spi)
++static int wl1271_probe(struct spi_device *spi)
+ {
+ 	struct wl12xx_spi_glue *glue;
+ 	struct wl12xx_platform_data *pdata;
+@@ -403,7 +403,7 @@ static int __devinit wl1271_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit wl1271_remove(struct spi_device *spi)
++static int wl1271_remove(struct spi_device *spi)
+ {
+ 	struct wl12xx_spi_glue *glue = spi_get_drvdata(spi);
+ 
+@@ -422,7 +422,7 @@ static struct spi_driver wl1271_spi_driver = {
+ 	},
+ 
+ 	.probe		= wl1271_probe,
+-	.remove		= __devexit_p(wl1271_remove),
++	.remove		= wl1271_remove,
+ };
+ 
+ static int __init wl1271_init(void)
+diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
+index 68584aa0f2b0..c3884937c007 100644
+--- a/drivers/net/wireless/ti/wlcore/wlcore.h
++++ b/drivers/net/wireless/ti/wlcore/wlcore.h
+@@ -414,8 +414,8 @@ struct wl1271 {
+ 	struct completion nvs_loading_complete;
+ };
+ 
+-int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev);
+-int __devexit wlcore_remove(struct platform_device *pdev);
++int wlcore_probe(struct wl1271 *wl, struct platform_device *pdev);
++int wlcore_remove(struct platform_device *pdev);
+ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size);
+ int wlcore_free_hw(struct wl1271 *wl);
+ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,

commit fd549f135c43d60b92aff7cfbbfdf4e79b6cc631
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:56:41 2012 -0500
+
+    rtl8187: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Herton Ronaldo Krzesinski 
+    Cc: Hin-Tak Leung 
+    Cc: Larry Finger 
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c
+index 52e6bebcf089..4574bd213705 100644
+--- a/drivers/net/wireless/rtl818x/rtl8187/dev.c
++++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c
+@@ -1411,7 +1411,7 @@ static void rtl8187_eeprom_register_write(struct eeprom_93cx6 *eeprom)
+ 	udelay(10);
+ }
+ 
+-static int __devinit rtl8187_probe(struct usb_interface *intf,
++static int rtl8187_probe(struct usb_interface *intf,
+ 				   const struct usb_device_id *id)
+ {
+ 	struct usb_device *udev = interface_to_usbdev(intf);
+@@ -1639,7 +1639,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
+ 	return err;
+ }
+ 
+-static void __devexit rtl8187_disconnect(struct usb_interface *intf)
++static void rtl8187_disconnect(struct usb_interface *intf)
+ {
+ 	struct ieee80211_hw *dev = usb_get_intfdata(intf);
+ 	struct rtl8187_priv *priv;
+@@ -1664,7 +1664,7 @@ static struct usb_driver rtl8187_driver = {
+ 	.name		= KBUILD_MODNAME,
+ 	.id_table	= rtl8187_table,
+ 	.probe		= rtl8187_probe,
+-	.disconnect	= __devexit_p(rtl8187_disconnect),
++	.disconnect	= rtl8187_disconnect,
+ 	.disable_hub_initiated_lpm = 1,
+ };
+ 

commit fb4e899dea7ea5e540db1deb71442d37bb8100fc
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:56:40 2012 -0500
+
+    rtl8187: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c
+index b4218a5f2066..1b3c2843221d 100644
+--- a/drivers/net/wireless/rtl818x/rtl8180/dev.c
++++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c
+@@ -901,7 +901,7 @@ static void rtl8180_eeprom_register_write(struct eeprom_93cx6 *eeprom)
+ 	udelay(10);
+ }
+ 
+-static int __devinit rtl8180_probe(struct pci_dev *pdev,
++static int rtl8180_probe(struct pci_dev *pdev,
+ 				   const struct pci_device_id *id)
+ {
+ 	struct ieee80211_hw *dev;
+@@ -1131,7 +1131,7 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit rtl8180_remove(struct pci_dev *pdev)
++static void rtl8180_remove(struct pci_dev *pdev)
+ {
+ 	struct ieee80211_hw *dev = pci_get_drvdata(pdev);
+ 	struct rtl8180_priv *priv;
+@@ -1170,7 +1170,7 @@ static struct pci_driver rtl8180_driver = {
+ 	.name		= KBUILD_MODNAME,
+ 	.id_table	= rtl8180_table,
+ 	.probe		= rtl8180_probe,
+-	.remove		= __devexit_p(rtl8180_remove),
++	.remove		= rtl8180_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= rtl8180_suspend,
+ 	.resume		= rtl8180_resume,

commit 692023597a5ec01fa2e5e3eec36948c7655009f6
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:56:39 2012 -0500
+
+    rt2x00: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Ivo van Doorn 
+    Cc: Gertjan van Wingerde 
+    Cc: Helmut Schaa 
+    Cc: users@rt2x00.serialmonkey.com (moderated for non-subscribers)
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
+index e3a2d9070cf6..a2d2bc2c7b3d 100644
+--- a/drivers/net/wireless/rt2x00/rt2400pci.c
++++ b/drivers/net/wireless/rt2x00/rt2400pci.c
+@@ -1831,7 +1831,7 @@ static struct pci_driver rt2400pci_driver = {
+ 	.name		= KBUILD_MODNAME,
+ 	.id_table	= rt2400pci_device_table,
+ 	.probe		= rt2400pci_probe,
+-	.remove		= __devexit_p(rt2x00pci_remove),
++	.remove		= rt2x00pci_remove,
+ 	.suspend	= rt2x00pci_suspend,
+ 	.resume		= rt2x00pci_resume,
+ };
+diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
+index 479d756e275b..9bea10f53f0a 100644
+--- a/drivers/net/wireless/rt2x00/rt2500pci.c
++++ b/drivers/net/wireless/rt2x00/rt2500pci.c
+@@ -2122,7 +2122,7 @@ static struct pci_driver rt2500pci_driver = {
+ 	.name		= KBUILD_MODNAME,
+ 	.id_table	= rt2500pci_device_table,
+ 	.probe		= rt2500pci_probe,
+-	.remove		= __devexit_p(rt2x00pci_remove),
++	.remove		= rt2x00pci_remove,
+ 	.suspend	= rt2x00pci_suspend,
+ 	.resume		= rt2x00pci_resume,
+ };
+diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
+index 27829e1e2e38..9224d874bf24 100644
+--- a/drivers/net/wireless/rt2x00/rt2800pci.c
++++ b/drivers/net/wireless/rt2x00/rt2800pci.c
+@@ -1176,7 +1176,7 @@ static struct platform_driver rt2800soc_driver = {
+ 		.mod_name	= KBUILD_MODNAME,
+ 	},
+ 	.probe		= rt2800soc_probe,
+-	.remove		= __devexit_p(rt2x00soc_remove),
++	.remove		= rt2x00soc_remove,
+ 	.suspend	= rt2x00soc_suspend,
+ 	.resume		= rt2x00soc_resume,
+ };
+@@ -1193,7 +1193,7 @@ static struct pci_driver rt2800pci_driver = {
+ 	.name		= KBUILD_MODNAME,
+ 	.id_table	= rt2800pci_device_table,
+ 	.probe		= rt2800pci_probe,
+-	.remove		= __devexit_p(rt2x00pci_remove),
++	.remove		= rt2x00pci_remove,
+ 	.suspend	= rt2x00pci_suspend,
+ 	.resume		= rt2x00pci_resume,
+ };
+diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
+index d6582a2fa353..f95792cfcf89 100644
+--- a/drivers/net/wireless/rt2x00/rt61pci.c
++++ b/drivers/net/wireless/rt2x00/rt61pci.c
+@@ -3094,7 +3094,7 @@ static struct pci_driver rt61pci_driver = {
+ 	.name		= KBUILD_MODNAME,
+ 	.id_table	= rt61pci_device_table,
+ 	.probe		= rt61pci_probe,
+-	.remove		= __devexit_p(rt2x00pci_remove),
++	.remove		= rt2x00pci_remove,
+ 	.suspend	= rt2x00pci_suspend,
+ 	.resume		= rt2x00pci_resume,
+ };

commit 337b563f72f2e379f11411614f68f3ec73f30592
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:56:38 2012 -0500
+
+    p54: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Christian Lamparter 
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c
+index 810c343e4e30..933e5d941937 100644
+--- a/drivers/net/wireless/p54/p54pci.c
++++ b/drivers/net/wireless/p54/p54pci.c
+@@ -540,7 +540,7 @@ static void p54p_firmware_step2(const struct firmware *fw,
+ 	pci_dev_put(pdev);
+ }
+ 
+-static int __devinit p54p_probe(struct pci_dev *pdev,
++static int p54p_probe(struct pci_dev *pdev,
+ 				const struct pci_device_id *id)
+ {
+ 	struct p54p_priv *priv;
+@@ -639,7 +639,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit p54p_remove(struct pci_dev *pdev)
++static void p54p_remove(struct pci_dev *pdev)
+ {
+ 	struct ieee80211_hw *dev = pci_get_drvdata(pdev);
+ 	struct p54p_priv *priv;
+@@ -692,7 +692,7 @@ static struct pci_driver p54p_driver = {
+ 	.name		= "p54pci",
+ 	.id_table	= p54p_table,
+ 	.probe		= p54p_probe,
+-	.remove		= __devexit_p(p54p_remove),
++	.remove		= p54p_remove,
+ 	.driver.pm	= P54P_PM_OPS,
+ };
+ 
+diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c
+index f7929906d437..4fd49a007b51 100644
+--- a/drivers/net/wireless/p54/p54spi.c
++++ b/drivers/net/wireless/p54/p54spi.c
+@@ -595,7 +595,7 @@ static void p54spi_op_stop(struct ieee80211_hw *dev)
+ 	cancel_work_sync(&priv->work);
+ }
+ 
+-static int __devinit p54spi_probe(struct spi_device *spi)
++static int p54spi_probe(struct spi_device *spi)
+ {
+ 	struct p54s_priv *priv = NULL;
+ 	struct ieee80211_hw *hw;
+@@ -683,7 +683,7 @@ static int __devinit p54spi_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit p54spi_remove(struct spi_device *spi)
++static int p54spi_remove(struct spi_device *spi)
+ {
+ 	struct p54s_priv *priv = dev_get_drvdata(&spi->dev);
+ 
+@@ -710,7 +710,7 @@ static struct spi_driver p54spi_driver = {
+ 	},
+ 
+ 	.probe		= p54spi_probe,
+-	.remove		= __devexit_p(p54spi_remove),
++	.remove		= p54spi_remove,
+ };
+ 
+ static int __init p54spi_init(void)
+diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
+index effb044a8a9d..e71c702e2eb1 100644
+--- a/drivers/net/wireless/p54/p54usb.c
++++ b/drivers/net/wireless/p54/p54usb.c
+@@ -986,7 +986,7 @@ static int p54u_load_firmware(struct ieee80211_hw *dev,
+ 	return err;
+ }
+ 
+-static int __devinit p54u_probe(struct usb_interface *intf,
++static int p54u_probe(struct usb_interface *intf,
+ 				const struct usb_device_id *id)
+ {
+ 	struct usb_device *udev = interface_to_usbdev(intf);
+@@ -1057,7 +1057,7 @@ static int __devinit p54u_probe(struct usb_interface *intf,
+ 	return err;
+ }
+ 
+-static void __devexit p54u_disconnect(struct usb_interface *intf)
++static void p54u_disconnect(struct usb_interface *intf)
+ {
+ 	struct ieee80211_hw *dev = usb_get_intfdata(intf);
+ 	struct p54u_priv *priv;
+@@ -1131,7 +1131,7 @@ static struct usb_driver p54u_driver = {
+ 	.name	= "p54usb",
+ 	.id_table = p54u_table,
+ 	.probe = p54u_probe,
+-	.disconnect = __devexit_p(p54u_disconnect),
++	.disconnect = p54u_disconnect,
+ 	.pre_reset = p54u_pre_reset,
+ 	.post_reset = p54u_post_reset,
+ #ifdef CONFIG_PM

commit baa366cda6ec9bf033301a4f547c26c833bd5930
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:56:37 2012 -0500
+
+    orinoco: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/orinoco/orinoco_nortel.c b/drivers/net/wireless/orinoco/orinoco_nortel.c
+index 326396b313a6..d73fdf6185a2 100644
+--- a/drivers/net/wireless/orinoco/orinoco_nortel.c
++++ b/drivers/net/wireless/orinoco/orinoco_nortel.c
+@@ -255,7 +255,7 @@ static int orinoco_nortel_init_one(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit orinoco_nortel_remove_one(struct pci_dev *pdev)
++static void orinoco_nortel_remove_one(struct pci_dev *pdev)
+ {
+ 	struct orinoco_private *priv = pci_get_drvdata(pdev);
+ 	struct orinoco_pci_card *card = priv->card;
+@@ -288,7 +288,7 @@ static struct pci_driver orinoco_nortel_driver = {
+ 	.name		= DRIVER_NAME,
+ 	.id_table	= orinoco_nortel_id_table,
+ 	.probe		= orinoco_nortel_init_one,
+-	.remove		= __devexit_p(orinoco_nortel_remove_one),
++	.remove		= orinoco_nortel_remove_one,
+ 	.suspend	= orinoco_pci_suspend,
+ 	.resume		= orinoco_pci_resume,
+ };
+diff --git a/drivers/net/wireless/orinoco/orinoco_pci.c b/drivers/net/wireless/orinoco/orinoco_pci.c
+index 6058c66b844e..677bf14eca84 100644
+--- a/drivers/net/wireless/orinoco/orinoco_pci.c
++++ b/drivers/net/wireless/orinoco/orinoco_pci.c
+@@ -199,7 +199,7 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit orinoco_pci_remove_one(struct pci_dev *pdev)
++static void orinoco_pci_remove_one(struct pci_dev *pdev)
+ {
+ 	struct orinoco_private *priv = pci_get_drvdata(pdev);
+ 
+@@ -228,7 +228,7 @@ static struct pci_driver orinoco_pci_driver = {
+ 	.name		= DRIVER_NAME,
+ 	.id_table	= orinoco_pci_id_table,
+ 	.probe		= orinoco_pci_init_one,
+-	.remove		= __devexit_p(orinoco_pci_remove_one),
++	.remove		= orinoco_pci_remove_one,
+ 	.suspend	= orinoco_pci_suspend,
+ 	.resume		= orinoco_pci_resume,
+ };
+diff --git a/drivers/net/wireless/orinoco/orinoco_plx.c b/drivers/net/wireless/orinoco/orinoco_plx.c
+index 2bac8248a991..2559dbd6184b 100644
+--- a/drivers/net/wireless/orinoco/orinoco_plx.c
++++ b/drivers/net/wireless/orinoco/orinoco_plx.c
+@@ -294,7 +294,7 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev)
++static void orinoco_plx_remove_one(struct pci_dev *pdev)
+ {
+ 	struct orinoco_private *priv = pci_get_drvdata(pdev);
+ 	struct orinoco_pci_card *card = priv->card;
+@@ -334,7 +334,7 @@ static struct pci_driver orinoco_plx_driver = {
+ 	.name		= DRIVER_NAME,
+ 	.id_table	= orinoco_plx_id_table,
+ 	.probe		= orinoco_plx_init_one,
+-	.remove		= __devexit_p(orinoco_plx_remove_one),
++	.remove		= orinoco_plx_remove_one,
+ 	.suspend	= orinoco_pci_suspend,
+ 	.resume		= orinoco_pci_resume,
+ };
+diff --git a/drivers/net/wireless/orinoco/orinoco_tmd.c b/drivers/net/wireless/orinoco/orinoco_tmd.c
+index 93159d68ec93..42afeeea2c40 100644
+--- a/drivers/net/wireless/orinoco/orinoco_tmd.c
++++ b/drivers/net/wireless/orinoco/orinoco_tmd.c
+@@ -188,7 +188,7 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit orinoco_tmd_remove_one(struct pci_dev *pdev)
++static void orinoco_tmd_remove_one(struct pci_dev *pdev)
+ {
+ 	struct orinoco_private *priv = pci_get_drvdata(pdev);
+ 	struct orinoco_pci_card *card = priv->card;
+@@ -214,7 +214,7 @@ static struct pci_driver orinoco_tmd_driver = {
+ 	.name		= DRIVER_NAME,
+ 	.id_table	= orinoco_tmd_id_table,
+ 	.probe		= orinoco_tmd_init_one,
+-	.remove		= __devexit_p(orinoco_tmd_remove_one),
++	.remove		= orinoco_tmd_remove_one,
+ 	.suspend	= orinoco_pci_suspend,
+ 	.resume		= orinoco_pci_resume,
+ };

commit 8dee5eef2ab313e519e6ce3c3bf9a16cfc6f5907
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:56:36 2012 -0500
+
+    mwl8k: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Lennert Buytenhek 
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
+index 434d508f9e3e..f221b95b90b3 100644
+--- a/drivers/net/wireless/mwl8k.c
++++ b/drivers/net/wireless/mwl8k.c
+@@ -5258,7 +5258,7 @@ enum {
+ #define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw"
+ #define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api)
+ 
+-static struct mwl8k_device_info mwl8k_info_tbl[] __devinitdata = {
++static struct mwl8k_device_info mwl8k_info_tbl[] = {
+ 	[MWL8363] = {
+ 		.part_name	= "88w8363",
+ 		.helper_image	= "mwl8k/helper_8363.fw",
+@@ -5756,7 +5756,7 @@ static int mwl8k_firmware_load_success(struct mwl8k_priv *priv)
+ 
+ 	return rc;
+ }
+-static int __devinit mwl8k_probe(struct pci_dev *pdev,
++static int mwl8k_probe(struct pci_dev *pdev,
+ 				 const struct pci_device_id *id)
+ {
+ 	static int printed_version;
+@@ -5873,7 +5873,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
+ 	return rc;
+ }
+ 
+-static void __devexit mwl8k_remove(struct pci_dev *pdev)
++static void mwl8k_remove(struct pci_dev *pdev)
+ {
+ 	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+ 	struct mwl8k_priv *priv;
+@@ -5925,7 +5925,7 @@ static struct pci_driver mwl8k_driver = {
+ 	.name		= MWL8K_NAME,
+ 	.id_table	= mwl8k_pci_id_table,
+ 	.probe		= mwl8k_probe,
+-	.remove		= __devexit_p(mwl8k_remove),
++	.remove		= mwl8k_remove,
+ };
+ 
+ module_pci_driver(mwl8k_driver);

commit fbdb7fcefe95cb77b9d692e6f9c7c02ecc846c10
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:56:35 2012 -0500
+
+    libertas: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Dan Williams 
+    Cc: libertas-dev@lists.infradead.org
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
+index 9604a1c4a74d..4bb6574f4073 100644
+--- a/drivers/net/wireless/libertas/if_spi.c
++++ b/drivers/net/wireless/libertas/if_spi.c
+@@ -1124,7 +1124,7 @@ static void if_spi_resume_worker(struct work_struct *work)
+ 	}
+ }
+ 
+-static int __devinit if_spi_probe(struct spi_device *spi)
++static int if_spi_probe(struct spi_device *spi)
+ {
+ 	struct if_spi_card *card;
+ 	struct lbs_private *priv = NULL;
+@@ -1226,7 +1226,7 @@ static int __devinit if_spi_probe(struct spi_device *spi)
+ 	return err;
+ }
+ 
+-static int __devexit libertas_spi_remove(struct spi_device *spi)
++static int libertas_spi_remove(struct spi_device *spi)
+ {
+ 	struct if_spi_card *card = spi_get_drvdata(spi);
+ 	struct lbs_private *priv = card->priv;
+@@ -1285,7 +1285,7 @@ static const struct dev_pm_ops if_spi_pm_ops = {
+ 
+ static struct spi_driver libertas_spi_driver = {
+ 	.probe	= if_spi_probe,
+-	.remove = __devexit_p(libertas_spi_remove),
++	.remove = libertas_spi_remove,
+ 	.driver = {
+ 		.name	= "libertas_spi",
+ 		.owner	= THIS_MODULE,

commit d00064d4f775150017835f2c93905f05691e1649
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:56:34 2012 -0500
+
+    iwlwifi: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Johannes Berg 
+    Cc: Wey-Yi Guy 
+    Cc: Intel Linux Wireless 
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c
+index 956fe6c370bc..2b7e8a0b1cd4 100644
+--- a/drivers/net/wireless/iwlwifi/pcie/drv.c
++++ b/drivers/net/wireless/iwlwifi/pcie/drv.c
+@@ -293,7 +293,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	return -EFAULT;
+ }
+ 
+-static void __devexit iwl_pci_remove(struct pci_dev *pdev)
++static void iwl_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct iwl_trans *trans = pci_get_drvdata(pdev);
+ 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+@@ -352,7 +352,7 @@ static struct pci_driver iwl_pci_driver = {
+ 	.name = DRV_NAME,
+ 	.id_table = iwl_hw_card_ids,
+ 	.probe = iwl_pci_probe,
+-	.remove = __devexit_p(iwl_pci_remove),
++	.remove = iwl_pci_remove,
+ 	.driver.pm = IWL_PM_OPS,
+ };
+ 

commit a027cb88bf692b86948c5495650665a2a1d5535f
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:56:33 2012 -0500
+
+    iwlegacy: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Stanislaw Gruszka 
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c
+index e252acb9c862..d604b4036a76 100644
+--- a/drivers/net/wireless/iwlegacy/3945-mac.c
++++ b/drivers/net/wireless/iwlegacy/3945-mac.c
+@@ -3794,7 +3794,7 @@ il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	return err;
+ }
+ 
+-static void __devexit
++static void
+ il3945_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct il_priv *il = pci_get_drvdata(pdev);
+@@ -3884,7 +3884,7 @@ static struct pci_driver il3945_driver = {
+ 	.name = DRV_NAME,
+ 	.id_table = il3945_hw_card_ids,
+ 	.probe = il3945_pci_probe,
+-	.remove = __devexit_p(il3945_pci_remove),
++	.remove = il3945_pci_remove,
+ 	.driver.pm = IL_LEGACY_PM_OPS,
+ };
+ 
+diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
+index 07ffa575e3ef..c3fbf6717564 100644
+--- a/drivers/net/wireless/iwlegacy/4965-mac.c
++++ b/drivers/net/wireless/iwlegacy/4965-mac.c
+@@ -6664,7 +6664,7 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	return err;
+ }
+ 
+-static void __devexit
++static void
+ il4965_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct il_priv *il = pci_get_drvdata(pdev);
+@@ -6772,7 +6772,7 @@ static struct pci_driver il4965_driver = {
+ 	.name = DRV_NAME,
+ 	.id_table = il4965_hw_card_ids,
+ 	.probe = il4965_pci_probe,
+-	.remove = __devexit_p(il4965_pci_remove),
++	.remove = il4965_pci_remove,
+ 	.driver.pm = IL_LEGACY_PM_OPS,
+ };
+ 

commit eb9248eee600092dcd982ce12b964c90e30c075c
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:56:32 2012 -0500
+
+    ipw2x00: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Stanislav Yakovlev 
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
+index 46938bc9886d..d92b21a8e597 100644
+--- a/drivers/net/wireless/ipw2x00/ipw2100.c
++++ b/drivers/net/wireless/ipw2x00/ipw2100.c
+@@ -6410,7 +6410,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
+ 	goto out;
+ }
+ 
+-static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev)
++static void ipw2100_pci_remove_one(struct pci_dev *pci_dev)
+ {
+ 	struct ipw2100_priv *priv = pci_get_drvdata(pci_dev);
+ 	struct net_device *dev = priv->net_dev;
+@@ -6606,7 +6606,7 @@ static struct pci_driver ipw2100_pci_driver = {
+ 	.name = DRV_NAME,
+ 	.id_table = ipw2100_pci_id_table,
+ 	.probe = ipw2100_pci_init_one,
+-	.remove = __devexit_p(ipw2100_pci_remove_one),
++	.remove = ipw2100_pci_remove_one,
+ #ifdef CONFIG_PM
+ 	.suspend = ipw2100_suspend,
+ 	.resume = ipw2100_resume,
+diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
+index b0879adcd441..844f201b7b70 100644
+--- a/drivers/net/wireless/ipw2x00/ipw2200.c
++++ b/drivers/net/wireless/ipw2x00/ipw2200.c
+@@ -10772,7 +10772,7 @@ static void ipw_bg_link_down(struct work_struct *work)
+ 	mutex_unlock(&priv->mutex);
+ }
+ 
+-static int __devinit ipw_setup_deferred_work(struct ipw_priv *priv)
++static int ipw_setup_deferred_work(struct ipw_priv *priv)
+ {
+ 	int ret = 0;
+ 
+@@ -11726,7 +11726,7 @@ static const struct net_device_ops ipw_netdev_ops = {
+ 	.ndo_validate_addr	= eth_validate_addr,
+ };
+ 
+-static int __devinit ipw_pci_probe(struct pci_dev *pdev,
++static int ipw_pci_probe(struct pci_dev *pdev,
+ 				   const struct pci_device_id *ent)
+ {
+ 	int err = 0;
+@@ -11899,7 +11899,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit ipw_pci_remove(struct pci_dev *pdev)
++static void ipw_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct ipw_priv *priv = pci_get_drvdata(pdev);
+ 	struct list_head *p, *q;
+@@ -12061,7 +12061,7 @@ static struct pci_driver ipw_driver = {
+ 	.name = DRV_NAME,
+ 	.id_table = card_ids,
+ 	.probe = ipw_pci_probe,
+-	.remove = __devexit_p(ipw_pci_remove),
++	.remove = ipw_pci_remove,
+ #ifdef CONFIG_PM
+ 	.suspend = ipw_pci_suspend,
+ 	.resume = ipw_pci_resume,

commit fcff0c0887f7286eda3ce47d8934acb3a78e1076
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:56:31 2012 -0500
+
+    brcm80211: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Brett Rudley 
+    Cc: Roland Vossen 
+    Cc: Arend van Spriel 
+    Cc: Franky (Zhenhui) Lin 
+    Cc: Kan Yan 
+    Cc: brcm80211-dev-list@broadcom.com
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+index 85dbaf8ac997..02d27eacc0e2 100644
+--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
++++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+@@ -1099,7 +1099,7 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev)
+  *
+  * Perimeter lock is initialized in the course of this function.
+  */
+-static int __devinit brcms_bcma_probe(struct bcma_device *pdev)
++static int brcms_bcma_probe(struct bcma_device *pdev)
+ {
+ 	struct brcms_info *wl;
+ 	struct ieee80211_hw *hw;
+@@ -1165,7 +1165,7 @@ static struct bcma_driver brcms_bcma_driver = {
+ 	.probe    = brcms_bcma_probe,
+ 	.suspend  = brcms_suspend,
+ 	.resume   = brcms_resume,
+-	.remove   = __devexit_p(brcms_remove),
++	.remove   = brcms_remove,
+ 	.id_table = brcms_coreid_table,
+ };
+ 

commit 157c9436e6e740b0fb3f3c10da0e2f68731a8052
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:56:30 2012 -0500
+
+    b43: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Stefano Brivio 
+    Cc: b43-dev@lists.infradead.org
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c
+index 714cad649c45..f2ea2ceec8a9 100644
+--- a/drivers/net/wireless/b43/pcmcia.c
++++ b/drivers/net/wireless/b43/pcmcia.c
+@@ -60,7 +60,7 @@ static int b43_pcmcia_resume(struct pcmcia_device *dev)
+ # define b43_pcmcia_resume		NULL
+ #endif /* CONFIG_PM */
+ 
+-static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
++static int b43_pcmcia_probe(struct pcmcia_device *dev)
+ {
+ 	struct ssb_bus *ssb;
+ 	int err = -ENOMEM;
+@@ -110,7 +110,7 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
+ 	return err;
+ }
+ 
+-static void __devexit b43_pcmcia_remove(struct pcmcia_device *dev)
++static void b43_pcmcia_remove(struct pcmcia_device *dev)
+ {
+ 	struct ssb_bus *ssb = dev->priv;
+ 
+@@ -125,7 +125,7 @@ static struct pcmcia_driver b43_pcmcia_driver = {
+ 	.name		= "b43-pcmcia",
+ 	.id_table	= b43_pcmcia_tbl,
+ 	.probe		= b43_pcmcia_probe,
+-	.remove		= __devexit_p(b43_pcmcia_remove),
++	.remove		= b43_pcmcia_remove,
+ 	.suspend	= b43_pcmcia_suspend,
+ 	.resume		= b43_pcmcia_resume,
+ };
+diff --git a/drivers/net/wireless/b43/sdio.c b/drivers/net/wireless/b43/sdio.c
+index a54fb2d29089..59a521800694 100644
+--- a/drivers/net/wireless/b43/sdio.c
++++ b/drivers/net/wireless/b43/sdio.c
+@@ -93,7 +93,7 @@ void b43_sdio_free_irq(struct b43_wldev *dev)
+ 	sdio->irq_handler = NULL;
+ }
+ 
+-static int __devinit b43_sdio_probe(struct sdio_func *func,
++static int b43_sdio_probe(struct sdio_func *func,
+ 				    const struct sdio_device_id *id)
+ {
+ 	struct b43_sdio *sdio;
+@@ -171,7 +171,7 @@ static int __devinit b43_sdio_probe(struct sdio_func *func,
+ 	return error;
+ }
+ 
+-static void __devexit b43_sdio_remove(struct sdio_func *func)
++static void b43_sdio_remove(struct sdio_func *func)
+ {
+ 	struct b43_sdio *sdio = sdio_get_drvdata(func);
+ 
+@@ -193,7 +193,7 @@ static struct sdio_driver b43_sdio_driver = {
+ 	.name		= "b43-sdio",
+ 	.id_table	= b43_sdio_ids,
+ 	.probe		= b43_sdio_probe,
+-	.remove		= __devexit_p(b43_sdio_remove),
++	.remove		= b43_sdio_remove,
+ };
+ 
+ int b43_sdio_init(void)

commit 991683ca49908a78ff00942d6832523657e578b7
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:56:29 2012 -0500
+
+    atmel: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/atmel_pci.c b/drivers/net/wireless/atmel_pci.c
+index 51e33b53386e..c1b159ebcffe 100644
+--- a/drivers/net/wireless/atmel_pci.c
++++ b/drivers/net/wireless/atmel_pci.c
+@@ -45,11 +45,11 @@ static struct pci_driver atmel_driver = {
+ 	.name     = "atmel",
+ 	.id_table = card_ids,
+ 	.probe    = atmel_pci_probe,
+-	.remove   = __devexit_p(atmel_pci_remove),
++	.remove   = atmel_pci_remove,
+ };
+ 
+ 
+-static int __devinit atmel_pci_probe(struct pci_dev *pdev,
++static int atmel_pci_probe(struct pci_dev *pdev,
+ 				     const struct pci_device_id *pent)
+ {
+ 	struct net_device *dev;
+@@ -69,7 +69,7 @@ static int __devinit atmel_pci_probe(struct pci_dev *pdev,
+ 	return 0;
+ }
+ 
+-static void __devexit atmel_pci_remove(struct pci_dev *pdev)
++static void atmel_pci_remove(struct pci_dev *pdev)
+ {
+ 	stop_atmel_card(pci_get_drvdata(pdev));
+ }

commit e829cf961bfd3c2c5ef0a2c5a51734c1628ce77e
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:56:28 2012 -0500
+
+    ath5k: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Jiri Slaby 
+    Cc: Nick Kossifidis 
+    Cc: Luis R. Rodriguez 
+    Cc: linux-wireless@vger.kernel.org
+    Cc: ath5k-devel@lists.ath5k.org
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
+index 2fd5bab2e22a..3a5a61e03922 100644
+--- a/drivers/net/wireless/ath/ath5k/base.c
++++ b/drivers/net/wireless/ath/ath5k/base.c
+@@ -2435,7 +2435,7 @@ static const struct ieee80211_iface_combination if_comb = {
+ 	.num_different_channels = 1,
+ };
+ 
+-int __devinit
++int
+ ath5k_init_ah(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops)
+ {
+ 	struct ieee80211_hw *hw = ah->hw;
+@@ -2861,7 +2861,7 @@ static void ath5k_reset_work(struct work_struct *work)
+ 	mutex_unlock(&ah->lock);
+ }
+ 
+-static int __devinit
++static int
+ ath5k_init(struct ieee80211_hw *hw)
+ {
+ 
+diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c
+index b9f708a45f4e..f77ef36acf87 100644
+--- a/drivers/net/wireless/ath/ath5k/led.c
++++ b/drivers/net/wireless/ath/ath5k/led.c
+@@ -158,7 +158,7 @@ void ath5k_unregister_leds(struct ath5k_hw *ah)
+ 	ath5k_unregister_led(&ah->tx_led);
+ }
+ 
+-int __devinit ath5k_init_leds(struct ath5k_hw *ah)
++int ath5k_init_leds(struct ath5k_hw *ah)
+ {
+ 	int ret = 0;
+ 	struct ieee80211_hw *hw = ah->hw;
+diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c
+index dff48fbc63bf..859db7c34f87 100644
+--- a/drivers/net/wireless/ath/ath5k/pci.c
++++ b/drivers/net/wireless/ath/ath5k/pci.c
+@@ -155,7 +155,7 @@ static const struct ath_bus_ops ath_pci_bus_ops = {
+ * PCI Initialization *
+ \********************/
+ 
+-static int __devinit
++static int
+ ath5k_pci_probe(struct pci_dev *pdev,
+ 		const struct pci_device_id *id)
+ {
+@@ -285,7 +285,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
+ 	return ret;
+ }
+ 
+-static void __devexit
++static void
+ ath5k_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+@@ -336,7 +336,7 @@ static struct pci_driver ath5k_pci_driver = {
+ 	.name		= KBUILD_MODNAME,
+ 	.id_table	= ath5k_pci_id_table,
+ 	.probe		= ath5k_pci_probe,
+-	.remove		= __devexit_p(ath5k_pci_remove),
++	.remove		= ath5k_pci_remove,
+ 	.driver.pm	= ATH5K_PM_OPS,
+ };
+ 

commit 04bfffb8053c7206c3b63c25c0775b6ad7053270
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:56:27 2012 -0500
+
+    wireless: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
+index 154a4965be4f..3d339e04efb7 100644
+--- a/drivers/net/wireless/adm8211.c
++++ b/drivers/net/wireless/adm8211.c
+@@ -1761,7 +1761,7 @@ static const struct ieee80211_ops adm8211_ops = {
+ 	.get_tsf		= adm8211_get_tsft
+ };
+ 
+-static int __devinit adm8211_probe(struct pci_dev *pdev,
++static int adm8211_probe(struct pci_dev *pdev,
+ 				   const struct pci_device_id *id)
+ {
+ 	struct ieee80211_hw *dev;
+@@ -1935,7 +1935,7 @@ static int __devinit adm8211_probe(struct pci_dev *pdev,
+ }
+ 
+ 
+-static void __devexit adm8211_remove(struct pci_dev *pdev)
++static void adm8211_remove(struct pci_dev *pdev)
+ {
+ 	struct ieee80211_hw *dev = pci_get_drvdata(pdev);
+ 	struct adm8211_priv *priv;
+@@ -1985,7 +1985,7 @@ static struct pci_driver adm8211_driver = {
+ 	.name		= "adm8211",
+ 	.id_table	= adm8211_pci_id_table,
+ 	.probe		= adm8211_probe,
+-	.remove		= __devexit_p(adm8211_remove),
++	.remove		= adm8211_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= adm8211_suspend,
+ 	.resume		= adm8211_resume,
+diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
+index 57f7db1ac31b..53295418f576 100644
+--- a/drivers/net/wireless/airo.c
++++ b/drivers/net/wireless/airo.c
+@@ -78,7 +78,7 @@ static struct pci_driver airo_driver = {
+ 	.name     = DRV_NAME,
+ 	.id_table = card_ids,
+ 	.probe    = airo_pci_probe,
+-	.remove   = __devexit_p(airo_pci_remove),
++	.remove   = airo_pci_remove,
+ 	.suspend  = airo_pci_suspend,
+ 	.resume   = airo_pci_resume,
+ };
+@@ -5584,7 +5584,7 @@ static void timer_func( struct net_device *dev ) {
+ }
+ 
+ #ifdef CONFIG_PCI
+-static int __devinit airo_pci_probe(struct pci_dev *pdev,
++static int airo_pci_probe(struct pci_dev *pdev,
+ 				    const struct pci_device_id *pent)
+ {
+ 	struct net_device *dev;
+@@ -5606,7 +5606,7 @@ static int __devinit airo_pci_probe(struct pci_dev *pdev,
+ 	return 0;
+ }
+ 
+-static void __devexit airo_pci_remove(struct pci_dev *pdev)
++static void airo_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 

commit 9e2b29d0d6ae05fb1ead7df68a209eece9c7749a
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:56:26 2012 -0500
+
+    rfkill: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Johannes Berg 
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: John W. Linville 
+
+diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c
+index 865adb61685a..78fc0937948d 100644
+--- a/net/rfkill/rfkill-gpio.c
++++ b/net/rfkill/rfkill-gpio.c
+@@ -213,7 +213,7 @@ static int rfkill_gpio_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver rfkill_gpio_driver = {
+ 	.probe = rfkill_gpio_probe,
+-	.remove = __devexit_p(rfkill_gpio_remove),
++	.remove = rfkill_gpio_remove,
+ 	.driver = {
+ 		   .name = "rfkill_gpio",
+ 		   .owner = THIS_MODULE,
+diff --git a/net/rfkill/rfkill-regulator.c b/net/rfkill/rfkill-regulator.c
+index 11da3018a853..4b5ab21ecb24 100644
+--- a/net/rfkill/rfkill-regulator.c
++++ b/net/rfkill/rfkill-regulator.c
+@@ -55,7 +55,7 @@ struct rfkill_ops rfkill_regulator_ops = {
+ 	.set_block = rfkill_regulator_set_block,
+ };
+ 
+-static int __devinit rfkill_regulator_probe(struct platform_device *pdev)
++static int rfkill_regulator_probe(struct platform_device *pdev)
+ {
+ 	struct rfkill_regulator_platform_data *pdata = pdev->dev.platform_data;
+ 	struct rfkill_regulator_data *rfkill_data;
+@@ -122,7 +122,7 @@ static int __devinit rfkill_regulator_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit rfkill_regulator_remove(struct platform_device *pdev)
++static int rfkill_regulator_remove(struct platform_device *pdev)
+ {
+ 	struct rfkill_regulator_data *rfkill_data = platform_get_drvdata(pdev);
+ 	struct rfkill *rf_kill = rfkill_data->rf_kill;
+@@ -137,7 +137,7 @@ static int __devexit rfkill_regulator_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver rfkill_regulator_driver = {
+ 	.probe = rfkill_regulator_probe,
+-	.remove = __devexit_p(rfkill_regulator_remove),
++	.remove = rfkill_regulator_remove,
+ 	.driver = {
+ 		.name = "rfkill-regulator",
+ 		.owner = THIS_MODULE,

commit 9f9a12f8ca79839c948464a37c5b557808278708
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:24:25 2012 -0500
+
+    net/intel: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Jeff Kirsher 
+    Cc: Jesse Brandeburg 
+    Cc: Bruce Allan 
+    Cc: Carolyn Wyborny 
+    Cc: Don Skidmore 
+    Cc: Greg Rose 
+    Cc: Peter P Waskiewicz Jr 
+    Cc: Alex Duyck 
+    Cc: John Ronciak 
+    Cc: Tushar Dave 
+    Cc: e1000-devel@lists.sourceforge.net
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c
+index 29ce9bd27f94..50c205098626 100644
+--- a/drivers/net/ethernet/intel/e100.c
++++ b/drivers/net/ethernet/intel/e100.c
+@@ -2829,7 +2829,7 @@ static const struct net_device_ops e100_netdev_ops = {
+ 	.ndo_set_features	= e100_set_features,
+ };
+ 
+-static int __devinit e100_probe(struct pci_dev *pdev,
++static int e100_probe(struct pci_dev *pdev,
+ 	const struct pci_device_id *ent)
+ {
+ 	struct net_device *netdev;
+@@ -2981,7 +2981,7 @@ static int __devinit e100_probe(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit e100_remove(struct pci_dev *pdev)
++static void e100_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *netdev = pci_get_drvdata(pdev);
+ 
+@@ -3167,7 +3167,7 @@ static struct pci_driver e100_driver = {
+ 	.name =         DRV_NAME,
+ 	.id_table =     e100_id_table,
+ 	.probe =        e100_probe,
+-	.remove =       __devexit_p(e100_remove),
++	.remove =       e100_remove,
+ #ifdef CONFIG_PM
+ 	/* Power Management hooks */
+ 	.suspend =      e100_suspend,
+diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
+index 222bfaff4622..840fb0d39034 100644
+--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
++++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
+@@ -111,7 +111,7 @@ void e1000_update_stats(struct e1000_adapter *adapter);
+ static int e1000_init_module(void);
+ static void e1000_exit_module(void);
+ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+-static void __devexit e1000_remove(struct pci_dev *pdev);
++static void e1000_remove(struct pci_dev *pdev);
+ static int e1000_alloc_queues(struct e1000_adapter *adapter);
+ static int e1000_sw_init(struct e1000_adapter *adapter);
+ static int e1000_open(struct net_device *netdev);
+@@ -202,7 +202,7 @@ static struct pci_driver e1000_driver = {
+ 	.name     = e1000_driver_name,
+ 	.id_table = e1000_pci_tbl,
+ 	.probe    = e1000_probe,
+-	.remove   = __devexit_p(e1000_remove),
++	.remove   = e1000_remove,
+ #ifdef CONFIG_PM
+ 	/* Power Management Hooks */
+ 	.suspend  = e1000_suspend,
+@@ -938,7 +938,7 @@ static int e1000_init_hw_struct(struct e1000_adapter *adapter,
+  * The OS initialization, configuring of the adapter private structure,
+  * and a hardware reset occur.
+  **/
+-static int __devinit e1000_probe(struct pci_dev *pdev,
++static int e1000_probe(struct pci_dev *pdev,
+ 				 const struct pci_device_id *ent)
+ {
+ 	struct net_device *netdev;
+@@ -1273,7 +1273,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
+  * memory.
+  **/
+ 
+-static void __devexit e1000_remove(struct pci_dev *pdev)
++static void e1000_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *netdev = pci_get_drvdata(pdev);
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+@@ -1309,7 +1309,7 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
+  * e1000_init_hw_struct MUST be called before this function
+  **/
+ 
+-static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
++static int e1000_sw_init(struct e1000_adapter *adapter)
+ {
+ 	adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
+ 
+@@ -1340,7 +1340,7 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
+  * number of queues at compile-time.
+  **/
+ 
+-static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter)
++static int e1000_alloc_queues(struct e1000_adapter *adapter)
+ {
+ 	adapter->tx_ring = kcalloc(adapter->num_tx_queues,
+ 	                           sizeof(struct e1000_tx_ring), GFP_KERNEL);
+diff --git a/drivers/net/ethernet/intel/e1000/e1000_param.c b/drivers/net/ethernet/intel/e1000/e1000_param.c
+index 1301eba8b57a..4e19aa0657f4 100644
+--- a/drivers/net/ethernet/intel/e1000/e1000_param.c
++++ b/drivers/net/ethernet/intel/e1000/e1000_param.c
+@@ -45,7 +45,7 @@
+ 
+ #define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
+ #define E1000_PARAM(X, desc) \
+-	static int __devinitdata X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
++	static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
+ 	static unsigned int num_##X; \
+ 	module_param_array_named(X, X, int, &num_##X, 0); \
+ 	MODULE_PARM_DESC(X, desc);
+@@ -205,7 +205,7 @@ struct e1000_option {
+ 	} arg;
+ };
+ 
+-static int __devinit e1000_validate_option(unsigned int *value,
++static int e1000_validate_option(unsigned int *value,
+ 					   const struct e1000_option *opt,
+ 					   struct e1000_adapter *adapter)
+ {
+@@ -268,7 +268,7 @@ static void e1000_check_copper_options(struct e1000_adapter *adapter);
+  * in a variable in the adapter structure.
+  **/
+ 
+-void __devinit e1000_check_options(struct e1000_adapter *adapter)
++void e1000_check_options(struct e1000_adapter *adapter)
+ {
+ 	struct e1000_option opt;
+ 	int bd = adapter->bd_number;
+@@ -534,7 +534,7 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter)
+  * Handles speed and duplex options on fiber adapters
+  **/
+ 
+-static void __devinit e1000_check_fiber_options(struct e1000_adapter *adapter)
++static void e1000_check_fiber_options(struct e1000_adapter *adapter)
+ {
+ 	int bd = adapter->bd_number;
+ 	if (num_Speed > bd) {
+@@ -560,7 +560,7 @@ static void __devinit e1000_check_fiber_options(struct e1000_adapter *adapter)
+  * Handles speed and duplex options on copper adapters
+  **/
+ 
+-static void __devinit e1000_check_copper_options(struct e1000_adapter *adapter)
++static void e1000_check_copper_options(struct e1000_adapter *adapter)
+ {
+ 	struct e1000_option opt;
+ 	unsigned int speed, dplx, an;
+diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
+index 6d06ed4e34b1..829e81471ae7 100644
+--- a/drivers/net/ethernet/intel/e1000e/netdev.c
++++ b/drivers/net/ethernet/intel/e1000e/netdev.c
+@@ -2503,7 +2503,7 @@ void e1000e_write_itr(struct e1000_adapter *adapter, u32 itr)
+  * e1000_alloc_queues - Allocate memory for all rings
+  * @adapter: board private structure to initialize
+  **/
+-static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter)
++static int e1000_alloc_queues(struct e1000_adapter *adapter)
+ {
+ 	int size = sizeof(struct e1000_ring);
+ 
+@@ -3676,7 +3676,7 @@ void e1000e_reinit_locked(struct e1000_adapter *adapter)
+  * Fields are initialized based on PCI device information and
+  * OS network device settings (MTU size).
+  **/
+-static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
++static int e1000_sw_init(struct e1000_adapter *adapter)
+ {
+ 	struct net_device *netdev = adapter->netdev;
+ 
+@@ -6024,7 +6024,7 @@ static const struct net_device_ops e1000e_netdev_ops = {
+  * The OS initialization, configuring of the adapter private structure,
+  * and a hardware reset occur.
+  **/
+-static int __devinit e1000_probe(struct pci_dev *pdev,
++static int e1000_probe(struct pci_dev *pdev,
+ 				 const struct pci_device_id *ent)
+ {
+ 	struct net_device *netdev;
+@@ -6361,7 +6361,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
+  * Hot-Plug event, or because the driver is going to be removed from
+  * memory.
+  **/
+-static void __devexit e1000_remove(struct pci_dev *pdev)
++static void e1000_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *netdev = pci_get_drvdata(pdev);
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+@@ -6512,7 +6512,7 @@ static struct pci_driver e1000_driver = {
+ 	.name     = e1000e_driver_name,
+ 	.id_table = e1000_pci_tbl,
+ 	.probe    = e1000_probe,
+-	.remove   = __devexit_p(e1000_remove),
++	.remove   = e1000_remove,
+ #ifdef CONFIG_PM
+ 	.driver   = {
+ 		.pm = &e1000_pm_ops,
+diff --git a/drivers/net/ethernet/intel/e1000e/param.c b/drivers/net/ethernet/intel/e1000e/param.c
+index 1fbb31554e4d..b3beed2232fd 100644
+--- a/drivers/net/ethernet/intel/e1000e/param.c
++++ b/drivers/net/ethernet/intel/e1000e/param.c
+@@ -53,7 +53,7 @@ MODULE_PARM_DESC(copybreak,
+  */
+ #define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
+ #define E1000_PARAM(X, desc)					\
+-	static int __devinitdata X[E1000_MAX_NIC+1]		\
++	static int X[E1000_MAX_NIC+1]		\
+ 		= E1000_PARAM_INIT;				\
+ 	static unsigned int num_##X;				\
+ 	module_param_array_named(X, X, int, &num_##X, 0);	\
+@@ -172,7 +172,7 @@ struct e1000_option {
+ 	} arg;
+ };
+ 
+-static int __devinit e1000_validate_option(unsigned int *value,
++static int e1000_validate_option(unsigned int *value,
+ 					   const struct e1000_option *opt,
+ 					   struct e1000_adapter *adapter)
+ {
+@@ -235,7 +235,7 @@ static int __devinit e1000_validate_option(unsigned int *value,
+  * value exists, a default value is used.  The final value is stored
+  * in a variable in the adapter structure.
+  **/
+-void __devinit e1000e_check_options(struct e1000_adapter *adapter)
++void e1000e_check_options(struct e1000_adapter *adapter)
+ {
+ 	struct e1000_hw *hw = &adapter->hw;
+ 	int bd = adapter->bd_number;
+diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
+index b85b15a88981..de4ebb306530 100644
+--- a/drivers/net/ethernet/intel/igb/igb_main.c
++++ b/drivers/net/ethernet/intel/igb/igb_main.c
+@@ -118,7 +118,7 @@ static void igb_free_all_tx_resources(struct igb_adapter *);
+ static void igb_free_all_rx_resources(struct igb_adapter *);
+ static void igb_setup_mrqc(struct igb_adapter *);
+ static int igb_probe(struct pci_dev *, const struct pci_device_id *);
+-static void __devexit igb_remove(struct pci_dev *pdev);
++static void igb_remove(struct pci_dev *pdev);
+ static int igb_sw_init(struct igb_adapter *);
+ static int igb_open(struct net_device *);
+ static int igb_close(struct net_device *);
+@@ -228,7 +228,7 @@ static struct pci_driver igb_driver = {
+ 	.name     = igb_driver_name,
+ 	.id_table = igb_pci_tbl,
+ 	.probe    = igb_probe,
+-	.remove   = __devexit_p(igb_remove),
++	.remove   = igb_remove,
+ #ifdef CONFIG_PM
+ 	.driver.pm = &igb_pm_ops,
+ #endif
+@@ -1824,7 +1824,7 @@ void igb_set_fw_version(struct igb_adapter *adapter)
+  * The OS initialization, configuring of the adapter private structure,
+  * and a hardware reset occur.
+  **/
+-static int __devinit igb_probe(struct pci_dev *pdev,
++static int igb_probe(struct pci_dev *pdev,
+ 			       const struct pci_device_id *ent)
+ {
+ 	struct net_device *netdev;
+@@ -2197,7 +2197,7 @@ static int __devinit igb_probe(struct pci_dev *pdev,
+  * Hot-Plug event, or because the driver is going to be removed from
+  * memory.
+  **/
+-static void __devexit igb_remove(struct pci_dev *pdev)
++static void igb_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *netdev = pci_get_drvdata(pdev);
+ 	struct igb_adapter *adapter = netdev_priv(netdev);
+@@ -2277,7 +2277,7 @@ static void __devexit igb_remove(struct pci_dev *pdev)
+  * mor expensive time wise to disable SR-IOV than it is to allocate and free
+  * the memory for the VFs.
+  **/
+-static void __devinit igb_probe_vfs(struct igb_adapter * adapter)
++static void igb_probe_vfs(struct igb_adapter *adapter)
+ {
+ #ifdef CONFIG_PCI_IOV
+ 	struct pci_dev *pdev = adapter->pdev;
+@@ -2338,7 +2338,7 @@ static void __devinit igb_probe_vfs(struct igb_adapter * adapter)
+  * Fields are initialized based on PCI device information and
+  * OS network device settings (MTU size).
+  **/
+-static int __devinit igb_sw_init(struct igb_adapter *adapter)
++static int igb_sw_init(struct igb_adapter *adapter)
+ {
+ 	struct e1000_hw *hw = &adapter->hw;
+ 	struct net_device *netdev = adapter->netdev;
+diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
+index 3d92ad8cdca1..b494309ee942 100644
+--- a/drivers/net/ethernet/intel/igbvf/netdev.c
++++ b/drivers/net/ethernet/intel/igbvf/netdev.c
+@@ -1098,7 +1098,7 @@ static int igbvf_request_msix(struct igbvf_adapter *adapter)
+  * igbvf_alloc_queues - Allocate memory for all rings
+  * @adapter: board private structure to initialize
+  **/
+-static int __devinit igbvf_alloc_queues(struct igbvf_adapter *adapter)
++static int igbvf_alloc_queues(struct igbvf_adapter *adapter)
+ {
+ 	struct net_device *netdev = adapter->netdev;
+ 
+@@ -1550,7 +1550,7 @@ void igbvf_reinit_locked(struct igbvf_adapter *adapter)
+  * Fields are initialized based on PCI device information and
+  * OS network device settings (MTU size).
+  **/
+-static int __devinit igbvf_sw_init(struct igbvf_adapter *adapter)
++static int igbvf_sw_init(struct igbvf_adapter *adapter)
+ {
+ 	struct net_device *netdev = adapter->netdev;
+ 	s32 rc;
+@@ -2618,7 +2618,7 @@ static const struct net_device_ops igbvf_netdev_ops = {
+  * The OS initialization, configuring of the adapter private structure,
+  * and a hardware reset occur.
+  **/
+-static int __devinit igbvf_probe(struct pci_dev *pdev,
++static int igbvf_probe(struct pci_dev *pdev,
+                                  const struct pci_device_id *ent)
+ {
+ 	struct net_device *netdev;
+@@ -2818,7 +2818,7 @@ static int __devinit igbvf_probe(struct pci_dev *pdev,
+  * Hot-Plug event, or because the driver is going to be removed from
+  * memory.
+  **/
+-static void __devexit igbvf_remove(struct pci_dev *pdev)
++static void igbvf_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *netdev = pci_get_drvdata(pdev);
+ 	struct igbvf_adapter *adapter = netdev_priv(netdev);
+@@ -2875,7 +2875,7 @@ static struct pci_driver igbvf_driver = {
+ 	.name     = igbvf_driver_name,
+ 	.id_table = igbvf_pci_tbl,
+ 	.probe    = igbvf_probe,
+-	.remove   = __devexit_p(igbvf_remove),
++	.remove   = igbvf_remove,
+ #ifdef CONFIG_PM
+ 	/* Power Management Hooks */
+ 	.suspend  = igbvf_suspend,
+diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
+index d99a2d51b948..ae96c10251be 100644
+--- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c
++++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
+@@ -73,7 +73,7 @@ MODULE_DEVICE_TABLE(pci, ixgb_pci_tbl);
+ static int ixgb_init_module(void);
+ static void ixgb_exit_module(void);
+ static int ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+-static void __devexit ixgb_remove(struct pci_dev *pdev);
++static void ixgb_remove(struct pci_dev *pdev);
+ static int ixgb_sw_init(struct ixgb_adapter *adapter);
+ static int ixgb_open(struct net_device *netdev);
+ static int ixgb_close(struct net_device *netdev);
+@@ -125,7 +125,7 @@ static struct pci_driver ixgb_driver = {
+ 	.name     = ixgb_driver_name,
+ 	.id_table = ixgb_pci_tbl,
+ 	.probe    = ixgb_probe,
+-	.remove   = __devexit_p(ixgb_remove),
++	.remove   = ixgb_remove,
+ 	.err_handler = &ixgb_err_handler
+ };
+ 
+@@ -391,7 +391,7 @@ static const struct net_device_ops ixgb_netdev_ops = {
+  * and a hardware reset occur.
+  **/
+ 
+-static int __devinit
++static int
+ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ 	struct net_device *netdev = NULL;
+@@ -558,7 +558,7 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+  * memory.
+  **/
+ 
+-static void __devexit
++static void
+ ixgb_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *netdev = pci_get_drvdata(pdev);
+@@ -584,7 +584,7 @@ ixgb_remove(struct pci_dev *pdev)
+  * OS network device settings (MTU size).
+  **/
+ 
+-static int __devinit
++static int
+ ixgb_sw_init(struct ixgb_adapter *adapter)
+ {
+ 	struct ixgb_hw *hw = &adapter->hw;
+diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_param.c b/drivers/net/ethernet/intel/ixgb/ixgb_param.c
+index 07d83ab46e21..04a60640ddda 100644
+--- a/drivers/net/ethernet/intel/ixgb/ixgb_param.c
++++ b/drivers/net/ethernet/intel/ixgb/ixgb_param.c
+@@ -47,7 +47,7 @@
+ 
+ #define IXGB_PARAM_INIT { [0 ... IXGB_MAX_NIC] = OPTION_UNSET }
+ #define IXGB_PARAM(X, desc)					\
+-	static int __devinitdata X[IXGB_MAX_NIC+1]		\
++	static int X[IXGB_MAX_NIC+1]		\
+ 		= IXGB_PARAM_INIT;				\
+ 	static unsigned int num_##X = 0;			\
+ 	module_param_array_named(X, X, int, &num_##X, 0);	\
+@@ -199,7 +199,7 @@ struct ixgb_option {
+ 	} arg;
+ };
+ 
+-static int __devinit
++static int
+ ixgb_validate_option(unsigned int *value, const struct ixgb_option *opt)
+ {
+ 	if (*value == OPTION_UNSET) {
+@@ -257,7 +257,7 @@ ixgb_validate_option(unsigned int *value, const struct ixgb_option *opt)
+  * in a variable in the adapter structure.
+  **/
+ 
+-void __devinit
++void
+ ixgb_check_options(struct ixgb_adapter *adapter)
+ {
+ 	int bd = adapter->bd_number;
+diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+index 79b834583188..2fa16de46786 100644
+--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+@@ -4462,7 +4462,7 @@ static void ixgbe_tx_timeout(struct net_device *netdev)
+  * Fields are initialized based on PCI device information and
+  * OS network device settings (MTU size).
+  **/
+-static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
++static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
+ {
+ 	struct ixgbe_hw *hw = &adapter->hw;
+ 	struct pci_dev *pdev = adapter->pdev;
+@@ -7183,7 +7183,7 @@ int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
+  * The OS initialization, configuring of the adapter private structure,
+  * and a hardware reset occur.
+  **/
+-static int __devinit ixgbe_probe(struct pci_dev *pdev,
++static int ixgbe_probe(struct pci_dev *pdev,
+ 				 const struct pci_device_id *ent)
+ {
+ 	struct net_device *netdev;
+@@ -7590,7 +7590,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
+  * Hot-Plug event, or because the driver is going to be removed from
+  * memory.
+  **/
+-static void __devexit ixgbe_remove(struct pci_dev *pdev)
++static void ixgbe_remove(struct pci_dev *pdev)
+ {
+ 	struct ixgbe_adapter *adapter = pci_get_drvdata(pdev);
+ 	struct net_device *netdev = adapter->netdev;
+@@ -7830,7 +7830,7 @@ static struct pci_driver ixgbe_driver = {
+ 	.name     = ixgbe_driver_name,
+ 	.id_table = ixgbe_pci_tbl,
+ 	.probe    = ixgbe_probe,
+-	.remove   = __devexit_p(ixgbe_remove),
++	.remove   = ixgbe_remove,
+ #ifdef CONFIG_PM
+ 	.suspend  = ixgbe_suspend,
+ 	.resume   = ixgbe_resume,
+diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+index f267c003a1bc..1e2f02ac268d 100644
+--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
++++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+@@ -2009,7 +2009,7 @@ static void ixgbevf_clear_interrupt_scheme(struct ixgbevf_adapter *adapter)
+  * Fields are initialized based on PCI device information and
+  * OS network device settings (MTU size).
+  **/
+-static int __devinit ixgbevf_sw_init(struct ixgbevf_adapter *adapter)
++static int ixgbevf_sw_init(struct ixgbevf_adapter *adapter)
+ {
+ 	struct ixgbe_hw *hw = &adapter->hw;
+ 	struct pci_dev *pdev = adapter->pdev;
+@@ -3242,7 +3242,7 @@ static void ixgbevf_assign_netdev_ops(struct net_device *dev)
+  * The OS initialization, configuring of the adapter private structure,
+  * and a hardware reset occur.
+  **/
+-static int __devinit ixgbevf_probe(struct pci_dev *pdev,
++static int ixgbevf_probe(struct pci_dev *pdev,
+ 				   const struct pci_device_id *ent)
+ {
+ 	struct net_device *netdev;
+@@ -3414,7 +3414,7 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev,
+  * Hot-Plug event, or because the driver is going to be removed from
+  * memory.
+  **/
+-static void __devexit ixgbevf_remove(struct pci_dev *pdev)
++static void ixgbevf_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *netdev = pci_get_drvdata(pdev);
+ 	struct ixgbevf_adapter *adapter = netdev_priv(netdev);
+@@ -3528,7 +3528,7 @@ static struct pci_driver ixgbevf_driver = {
+ 	.name     = ixgbevf_driver_name,
+ 	.id_table = ixgbevf_pci_tbl,
+ 	.probe    = ixgbevf_probe,
+-	.remove   = __devexit_p(ixgbevf_remove),
++	.remove   = ixgbevf_remove,
+ #ifdef CONFIG_PM
+ 	/* Power Management Hooks */
+ 	.suspend  = ixgbevf_suspend,

commit 0329aba13791ec256dacdfdc74eca8673f6dd2e8
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:24:24 2012 -0500
+
+    bnx2x: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Eilon Greenstein 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+index 5e07aa5e1aea..8ab1492cedd1 100644
+--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+@@ -3875,7 +3875,7 @@ void bnx2x_free_mem_bp(struct bnx2x *bp)
+ 	kfree(bp->ilt);
+ }
+ 
+-int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp)
++int bnx2x_alloc_mem_bp(struct bnx2x *bp)
+ {
+ 	struct bnx2x_fastpath *fp;
+ 	struct msix_entry *tbl;
+diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+index 32c3ab72718c..0991534f61da 100644
+--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+@@ -563,7 +563,7 @@ int bnx2x_poll(struct napi_struct *napi, int budget);
+  *
+  * @bp:		driver handle
+  */
+-int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp);
++int bnx2x_alloc_mem_bp(struct bnx2x *bp);
+ 
+ /**
+  * bnx2x_free_mem_bp - release memories outsize main driver structure
+diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+index c8ec3fcd2d35..d7b278c9b5d1 100644
+--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+@@ -79,7 +79,7 @@
+ /* Time in jiffies before concluding the transmitter is hung */
+ #define TX_TIMEOUT		(5*HZ)
+ 
+-static char version[] __devinitdata =
++static char version[] =
+ 	"Broadcom NetXtreme II 5771x/578xx 10/20-Gigabit Ethernet Driver "
+ 	DRV_MODULE_NAME " " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+ 
+@@ -149,7 +149,7 @@ enum bnx2x_board_type {
+ /* indexed by board_type, above */
+ static struct {
+ 	char *name;
+-} board_info[] __devinitdata = {
++} board_info[] = {
+ 	{ "Broadcom NetXtreme II BCM57710 10 Gigabit PCIe [Everest]" },
+ 	{ "Broadcom NetXtreme II BCM57711 10 Gigabit PCIe" },
+ 	{ "Broadcom NetXtreme II BCM57711E 10 Gigabit PCIe" },
+@@ -9420,7 +9420,7 @@ static inline void bnx2x_undi_int_disable(struct bnx2x *bp)
+ 		bnx2x_undi_int_disable_e1h(bp);
+ }
+ 
+-static void __devinit bnx2x_prev_unload_close_mac(struct bnx2x *bp)
++static void bnx2x_prev_unload_close_mac(struct bnx2x *bp)
+ {
+ 	u32 val, base_addr, offset, mask, reset_reg;
+ 	bool mac_stopped = false;
+@@ -9487,7 +9487,7 @@ static void __devinit bnx2x_prev_unload_close_mac(struct bnx2x *bp)
+ #define BNX2X_PREV_UNDI_BD(val)		((val) >> 16 & 0xffff)
+ #define BNX2X_PREV_UNDI_PROD(rcq, bd)	((bd) << 16 | (rcq))
+ 
+-static void __devinit bnx2x_prev_unload_undi_inc(struct bnx2x *bp, u8 port,
++static void bnx2x_prev_unload_undi_inc(struct bnx2x *bp, u8 port,
+ 						 u8 inc)
+ {
+ 	u16 rcq, bd;
+@@ -9503,7 +9503,7 @@ static void __devinit bnx2x_prev_unload_undi_inc(struct bnx2x *bp, u8 port,
+ 		       port, bd, rcq);
+ }
+ 
+-static int __devinit bnx2x_prev_mcp_done(struct bnx2x *bp)
++static int bnx2x_prev_mcp_done(struct bnx2x *bp)
+ {
+ 	u32 rc = bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE,
+ 				  DRV_MSG_CODE_UNLOAD_SKIP_LINK_RESET);
+@@ -9515,7 +9515,7 @@ static int __devinit bnx2x_prev_mcp_done(struct bnx2x *bp)
+ 	return 0;
+ }
+ 
+-static bool __devinit bnx2x_prev_is_path_marked(struct bnx2x *bp)
++static bool bnx2x_prev_is_path_marked(struct bnx2x *bp)
+ {
+ 	struct bnx2x_prev_path_list *tmp_list;
+ 	int rc = false;
+@@ -9539,7 +9539,7 @@ static bool __devinit bnx2x_prev_is_path_marked(struct bnx2x *bp)
+ 	return rc;
+ }
+ 
+-static int __devinit bnx2x_prev_mark_path(struct bnx2x *bp)
++static int bnx2x_prev_mark_path(struct bnx2x *bp)
+ {
+ 	struct bnx2x_prev_path_list *tmp_list;
+ 	int rc;
+@@ -9568,7 +9568,7 @@ static int __devinit bnx2x_prev_mark_path(struct bnx2x *bp)
+ 	return rc;
+ }
+ 
+-static int __devinit bnx2x_do_flr(struct bnx2x *bp)
++static int bnx2x_do_flr(struct bnx2x *bp)
+ {
+ 	int i;
+ 	u16 status;
+@@ -9608,7 +9608,7 @@ static int __devinit bnx2x_do_flr(struct bnx2x *bp)
+ 	return 0;
+ }
+ 
+-static int __devinit bnx2x_prev_unload_uncommon(struct bnx2x *bp)
++static int bnx2x_prev_unload_uncommon(struct bnx2x *bp)
+ {
+ 	int rc;
+ 
+@@ -9646,7 +9646,7 @@ static int __devinit bnx2x_prev_unload_uncommon(struct bnx2x *bp)
+ 	return rc;
+ }
+ 
+-static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp)
++static int bnx2x_prev_unload_common(struct bnx2x *bp)
+ {
+ 	u32 reset_reg, tmp_reg = 0, rc;
+ 	/* It is possible a previous function received 'common' answer,
+@@ -9729,7 +9729,7 @@ static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp)
+  * to clear the interrupt which detected this from the pglueb and the was done
+  * bit
+  */
+-static void __devinit bnx2x_prev_interrupted_dmae(struct bnx2x *bp)
++static void bnx2x_prev_interrupted_dmae(struct bnx2x *bp)
+ {
+ 	if (!CHIP_IS_E1x(bp)) {
+ 		u32 val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS);
+@@ -9741,7 +9741,7 @@ static void __devinit bnx2x_prev_interrupted_dmae(struct bnx2x *bp)
+ 	}
+ }
+ 
+-static int __devinit bnx2x_prev_unload(struct bnx2x *bp)
++static int bnx2x_prev_unload(struct bnx2x *bp)
+ {
+ 	int time_counter = 10;
+ 	u32 rc, fw, hw_lock_reg, hw_lock_val;
+@@ -9808,7 +9808,7 @@ static int __devinit bnx2x_prev_unload(struct bnx2x *bp)
+ 	return rc;
+ }
+ 
+-static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
++static void bnx2x_get_common_hwinfo(struct bnx2x *bp)
+ {
+ 	u32 val, val2, val3, val4, id, boot_mode;
+ 	u16 pmc;
+@@ -9991,7 +9991,7 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
+ #define IGU_FID(val)	GET_FIELD((val), IGU_REG_MAPPING_MEMORY_FID)
+ #define IGU_VEC(val)	GET_FIELD((val), IGU_REG_MAPPING_MEMORY_VECTOR)
+ 
+-static int __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp)
++static int bnx2x_get_igu_cam_info(struct bnx2x *bp)
+ {
+ 	int pfid = BP_FUNC(bp);
+ 	int igu_sb_id;
+@@ -10050,7 +10050,7 @@ static int __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp)
+ 	return 0;
+ }
+ 
+-static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp,
++static void bnx2x_link_settings_supported(struct bnx2x *bp,
+ 						    u32 switch_cfg)
+ {
+ 	int cfg_size = 0, idx, port = BP_PORT(bp);
+@@ -10149,7 +10149,7 @@ static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp,
+ 		       bp->port.supported[1]);
+ }
+ 
+-static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
++static void bnx2x_link_settings_requested(struct bnx2x *bp)
+ {
+ 	u32 link_config, idx, cfg_size = 0;
+ 	bp->port.advertising[0] = 0;
+@@ -10335,7 +10335,7 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
+ 	}
+ }
+ 
+-static void __devinit bnx2x_set_mac_buf(u8 *mac_buf, u32 mac_lo, u16 mac_hi)
++static void bnx2x_set_mac_buf(u8 *mac_buf, u32 mac_lo, u16 mac_hi)
+ {
+ 	mac_hi = cpu_to_be16(mac_hi);
+ 	mac_lo = cpu_to_be32(mac_lo);
+@@ -10343,7 +10343,7 @@ static void __devinit bnx2x_set_mac_buf(u8 *mac_buf, u32 mac_lo, u16 mac_hi)
+ 	memcpy(mac_buf + sizeof(mac_hi), &mac_lo, sizeof(mac_lo));
+ }
+ 
+-static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
++static void bnx2x_get_port_hwinfo(struct bnx2x *bp)
+ {
+ 	int port = BP_PORT(bp);
+ 	u32 config;
+@@ -10447,7 +10447,7 @@ void bnx2x_get_iscsi_info(struct bnx2x *bp)
+ 
+ }
+ 
+-static void __devinit bnx2x_get_ext_wwn_info(struct bnx2x *bp, int func)
++static void bnx2x_get_ext_wwn_info(struct bnx2x *bp, int func)
+ {
+ 	/* Port info */
+ 	bp->cnic_eth_dev.fcoe_wwn_port_name_hi =
+@@ -10461,7 +10461,7 @@ static void __devinit bnx2x_get_ext_wwn_info(struct bnx2x *bp, int func)
+ 	bp->cnic_eth_dev.fcoe_wwn_node_name_lo =
+ 		MF_CFG_RD(bp, func_ext_config[func].fcoe_wwn_node_name_lower);
+ }
+-static void __devinit bnx2x_get_fcoe_info(struct bnx2x *bp)
++static void bnx2x_get_fcoe_info(struct bnx2x *bp)
+ {
+ 	int port = BP_PORT(bp);
+ 	int func = BP_ABS_FUNC(bp);
+@@ -10521,7 +10521,7 @@ static void __devinit bnx2x_get_fcoe_info(struct bnx2x *bp)
+ 		bp->flags |= NO_FCOE_FLAG;
+ }
+ 
+-static void __devinit bnx2x_get_cnic_info(struct bnx2x *bp)
++static void bnx2x_get_cnic_info(struct bnx2x *bp)
+ {
+ 	/*
+ 	 * iSCSI may be dynamically disabled but reading
+@@ -10532,7 +10532,7 @@ static void __devinit bnx2x_get_cnic_info(struct bnx2x *bp)
+ 	bnx2x_get_fcoe_info(bp);
+ }
+ 
+-static void __devinit bnx2x_get_cnic_mac_hwinfo(struct bnx2x *bp)
++static void bnx2x_get_cnic_mac_hwinfo(struct bnx2x *bp)
+ {
+ 	u32 val, val2;
+ 	int func = BP_ABS_FUNC(bp);
+@@ -10626,7 +10626,7 @@ static void __devinit bnx2x_get_cnic_mac_hwinfo(struct bnx2x *bp)
+ 	}
+ }
+ 
+-static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
++static void bnx2x_get_mac_hwinfo(struct bnx2x *bp)
+ {
+ 	u32 val, val2;
+ 	int func = BP_ABS_FUNC(bp);
+@@ -10667,7 +10667,7 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
+ 			bp->dev->dev_addr);
+ }
+ 
+-static bool __devinit bnx2x_get_dropless_info(struct bnx2x *bp)
++static bool bnx2x_get_dropless_info(struct bnx2x *bp)
+ {
+ 	int tmp;
+ 	u32 cfg;
+@@ -10687,7 +10687,7 @@ static bool __devinit bnx2x_get_dropless_info(struct bnx2x *bp)
+ 	return cfg;
+ }
+ 
+-static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
++static int bnx2x_get_hwinfo(struct bnx2x *bp)
+ {
+ 	int /*abs*/func = BP_ABS_FUNC(bp);
+ 	int vn;
+@@ -10913,7 +10913,7 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
+ 	return rc;
+ }
+ 
+-static void __devinit bnx2x_read_fwinfo(struct bnx2x *bp)
++static void bnx2x_read_fwinfo(struct bnx2x *bp)
+ {
+ 	int cnt, i, block_end, rodi;
+ 	char vpd_start[BNX2X_VPD_LEN+1];
+@@ -10998,7 +10998,7 @@ static void __devinit bnx2x_read_fwinfo(struct bnx2x *bp)
+ 	return;
+ }
+ 
+-static void __devinit bnx2x_set_modes_bitmap(struct bnx2x *bp)
++static void bnx2x_set_modes_bitmap(struct bnx2x *bp)
+ {
+ 	u32 flags = 0;
+ 
+@@ -11048,7 +11048,7 @@ static void __devinit bnx2x_set_modes_bitmap(struct bnx2x *bp)
+ 	INIT_MODE_FLAGS(bp) = flags;
+ }
+ 
+-static int __devinit bnx2x_init_bp(struct bnx2x *bp)
++static int bnx2x_init_bp(struct bnx2x *bp)
+ {
+ 	int func;
+ 	int rc;
+@@ -11531,7 +11531,7 @@ static int bnx2x_set_coherency_mask(struct bnx2x *bp)
+ 	return 0;
+ }
+ 
+-static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
++static int bnx2x_init_dev(struct pci_dev *pdev,
+ 				    struct net_device *dev,
+ 				    unsigned long board_type)
+ {
+@@ -11705,7 +11705,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
+ 	return rc;
+ }
+ 
+-static void __devinit bnx2x_get_pcie_width_speed(struct bnx2x *bp,
++static void bnx2x_get_pcie_width_speed(struct bnx2x *bp,
+ 						 int *width, int *speed)
+ {
+ 	u32 val = REG_RD(bp, PCICFG_OFFSET + PCICFG_LINK_CONTROL);
+@@ -12010,7 +12010,7 @@ static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev,
+ 	return control & PCI_MSIX_FLAGS_QSIZE;
+ }
+ 
+-static int __devinit bnx2x_init_one(struct pci_dev *pdev,
++static int bnx2x_init_one(struct pci_dev *pdev,
+ 				    const struct pci_device_id *ent)
+ {
+ 	struct net_device *dev = NULL;
+@@ -12199,7 +12199,7 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
+ 	return rc;
+ }
+ 
+-static void __devexit bnx2x_remove_one(struct pci_dev *pdev)
++static void bnx2x_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct bnx2x *bp;
+@@ -12414,7 +12414,7 @@ static struct pci_driver bnx2x_pci_driver = {
+ 	.name        = DRV_MODULE_NAME,
+ 	.id_table    = bnx2x_pci_tbl,
+ 	.probe       = bnx2x_init_one,
+-	.remove      = __devexit_p(bnx2x_remove_one),
++	.remove      = bnx2x_remove_one,
+ 	.suspend     = bnx2x_suspend,
+ 	.resume      = bnx2x_resume,
+ 	.err_handler = &bnx2x_err_handler,

commit 047fc56614f8f8d03fb64ef3be44f040aad25d56
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:24:23 2012 -0500
+
+    net/broadcom: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+index c7ca7ec065ee..39387d67b722 100644
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+@@ -1612,7 +1612,7 @@ static const struct net_device_ops bcm_enet_ops = {
+ /*
+  * allocate netdevice, request register memory and register device.
+  */
+-static int __devinit bcm_enet_probe(struct platform_device *pdev)
++static int bcm_enet_probe(struct platform_device *pdev)
+ {
+ 	struct bcm_enet_priv *priv;
+ 	struct net_device *dev;
+@@ -1830,7 +1830,7 @@ static int __devinit bcm_enet_probe(struct platform_device *pdev)
+ /*
+  * exit func, stops hardware and unregisters netdevice
+  */
+-static int __devexit bcm_enet_remove(struct platform_device *pdev)
++static int bcm_enet_remove(struct platform_device *pdev)
+ {
+ 	struct bcm_enet_priv *priv;
+ 	struct net_device *dev;
+@@ -1877,7 +1877,7 @@ static int __devexit bcm_enet_remove(struct platform_device *pdev)
+ 
+ struct platform_driver bcm63xx_enet_driver = {
+ 	.probe	= bcm_enet_probe,
+-	.remove	= __devexit_p(bcm_enet_remove),
++	.remove	= bcm_enet_remove,
+ 	.driver	= {
+ 		.name	= "bcm63xx_enet",
+ 		.owner  = THIS_MODULE,
+@@ -1887,7 +1887,7 @@ struct platform_driver bcm63xx_enet_driver = {
+ /*
+  * reserve & remap memory space shared between all macs
+  */
+-static int __devinit bcm_enet_shared_probe(struct platform_device *pdev)
++static int bcm_enet_shared_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res;
+ 	unsigned int iomem_size;
+@@ -1908,7 +1908,7 @@ static int __devinit bcm_enet_shared_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit bcm_enet_shared_remove(struct platform_device *pdev)
++static int bcm_enet_shared_remove(struct platform_device *pdev)
+ {
+ 	struct resource *res;
+ 
+@@ -1924,7 +1924,7 @@ static int __devexit bcm_enet_shared_remove(struct platform_device *pdev)
+  */
+ struct platform_driver bcm63xx_enet_shared_driver = {
+ 	.probe	= bcm_enet_shared_probe,
+-	.remove	= __devexit_p(bcm_enet_shared_remove),
++	.remove	= bcm_enet_shared_remove,
+ 	.driver	= {
+ 		.name	= "bcm63xx_enet_shared",
+ 		.owner  = THIS_MODULE,
+diff --git a/drivers/net/ethernet/broadcom/cnic.c b/drivers/net/ethernet/broadcom/cnic.c
+index cc8434fd606e..3b825f422090 100644
+--- a/drivers/net/ethernet/broadcom/cnic.c
++++ b/drivers/net/ethernet/broadcom/cnic.c
+@@ -53,7 +53,7 @@
+ 
+ #define DRV_MODULE_NAME		"cnic"
+ 
+-static char version[] __devinitdata =
++static char version[] =
+ 	"Broadcom NetXtreme II CNIC Driver " DRV_MODULE_NAME " v" CNIC_MODULE_VERSION " (" CNIC_MODULE_RELDATE ")\n";
+ 
+ MODULE_AUTHOR("Michael Chan  and John(Zongxi) "
+diff --git a/drivers/net/ethernet/broadcom/sb1250-mac.c b/drivers/net/ethernet/broadcom/sb1250-mac.c
+index 49e7a258da8a..3a1c8a3cf7c9 100644
+--- a/drivers/net/ethernet/broadcom/sb1250-mac.c
++++ b/drivers/net/ethernet/broadcom/sb1250-mac.c
+@@ -2586,7 +2586,7 @@ static int sbmac_poll(struct napi_struct *napi, int budget)
+ }
+ 
+ 
+-static int __devinit sbmac_probe(struct platform_device *pldev)
++static int sbmac_probe(struct platform_device *pldev)
+ {
+ 	struct net_device *dev;
+ 	struct sbmac_softc *sc;

commit 8e0e46bb3224057fd65f3041977163b6ee13346d
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:24:22 2012 -0500
+
+    xen-netfront: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Konrad Rzeszutek Wilk 
+    Cc: Jeremy Fitzhardinge 
+    Cc: xen-devel@lists.xensource.com
+    Cc: virtualization@lists.linux-foundation.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
+index fc24eb9b3948..53451dd7b602 100644
+--- a/drivers/net/xen-netfront.c
++++ b/drivers/net/xen-netfront.c
+@@ -1311,7 +1311,7 @@ static const struct net_device_ops xennet_netdev_ops = {
+ #endif
+ };
+ 
+-static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev)
++static struct net_device *xennet_create_dev(struct xenbus_device *dev)
+ {
+ 	int i, err;
+ 	struct net_device *netdev;
+@@ -1407,7 +1407,7 @@ static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev
+  * structures and the ring buffers for communication with the backend, and
+  * inform the backend of the appropriate details for those.
+  */
+-static int __devinit netfront_probe(struct xenbus_device *dev,
++static int netfront_probe(struct xenbus_device *dev,
+ 				    const struct xenbus_device_id *id)
+ {
+ 	int err;
+@@ -1967,7 +1967,7 @@ static const struct xenbus_device_id netfront_ids[] = {
+ };
+ 
+ 
+-static int __devexit xennet_remove(struct xenbus_device *dev)
++static int xennet_remove(struct xenbus_device *dev)
+ {
+ 	struct netfront_info *info = dev_get_drvdata(&dev->dev);
+ 
+@@ -1990,7 +1990,7 @@ static int __devexit xennet_remove(struct xenbus_device *dev)
+ 
+ static DEFINE_XENBUS_DRIVER(netfront, ,
+ 	.probe = netfront_probe,
+-	.remove = __devexit_p(xennet_remove),
++	.remove = xennet_remove,
+ 	.resume = netfront_resume,
+ 	.otherend_changed = netback_changed,
+ );

commit a46182eb9a9b0801776d5b6eca7591774cdea7a8
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:24:21 2012 -0500
+
+    net/lmc: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c
+index f5d533a706ea..0e443fd0803b 100644
+--- a/drivers/net/wan/lmc/lmc_main.c
++++ b/drivers/net/wan/lmc/lmc_main.c
+@@ -816,7 +816,7 @@ static const struct net_device_ops lmc_ops = {
+ 	.ndo_get_stats  = lmc_get_stats,
+ };
+ 
+-static int __devinit lmc_init_one(struct pci_dev *pdev,
++static int lmc_init_one(struct pci_dev *pdev,
+ 				  const struct pci_device_id *ent)
+ {
+ 	lmc_softc_t *sc;
+@@ -986,7 +986,7 @@ static int __devinit lmc_init_one(struct pci_dev *pdev,
+ /*
+  * Called from pci when removing module.
+  */
+-static void __devexit lmc_remove_one(struct pci_dev *pdev)
++static void lmc_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 
+@@ -1733,7 +1733,7 @@ static struct pci_driver lmc_driver = {
+ 	.name		= "lmc",
+ 	.id_table	= lmc_pci_tbl,
+ 	.probe		= lmc_init_one,
+-	.remove		= __devexit_p(lmc_remove_one),
++	.remove		= lmc_remove_one,
+ };
+ 
+ module_pci_driver(lmc_driver);

commit da3f21b5f997e361a3251e757a10574984593c14
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:24:20 2012 -0500
+
+    ixp4xx_hss: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Krzysztof Halasa 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
+index e9a3da588e95..b617622526b4 100644
+--- a/drivers/net/wan/ixp4xx_hss.c
++++ b/drivers/net/wan/ixp4xx_hss.c
+@@ -1326,7 +1326,7 @@ static const struct net_device_ops hss_hdlc_ops = {
+ 	.ndo_do_ioctl   = hss_hdlc_ioctl,
+ };
+ 
+-static int __devinit hss_init_one(struct platform_device *pdev)
++static int hss_init_one(struct platform_device *pdev)
+ {
+ 	struct port *port;
+ 	struct net_device *dev;
+@@ -1377,7 +1377,7 @@ static int __devinit hss_init_one(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit hss_remove_one(struct platform_device *pdev)
++static int hss_remove_one(struct platform_device *pdev)
+ {
+ 	struct port *port = platform_get_drvdata(pdev);
+ 

commit aeea6bbfa3f185dcd6f812ece8bed778ec0da3be
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:24:19 2012 -0500
+
+    net/hdlc: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Krzysztof Halasa 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/wan/hd64570.c b/drivers/net/wan/hd64570.c
+index cf4903355a34..c6e1a4b9e4fb 100644
+--- a/drivers/net/wan/hd64570.c
++++ b/drivers/net/wan/hd64570.c
+@@ -676,7 +676,7 @@ static netdev_tx_t sca_xmit(struct sk_buff *skb, struct net_device *dev)
+ 
+ 
+ #ifdef NEED_DETECT_RAM
+-static u32 __devinit sca_detect_ram(card_t *card, u8 __iomem *rambase,
++static u32 sca_detect_ram(card_t *card, u8 __iomem *rambase,
+ 				    u32 ramsize)
+ {
+ 	/* Round RAM size to 32 bits, fill from end to start */
+@@ -705,7 +705,7 @@ static u32 __devinit sca_detect_ram(card_t *card, u8 __iomem *rambase,
+ #endif /* NEED_DETECT_RAM */
+ 
+ 
+-static void __devinit sca_init(card_t *card, int wait_states)
++static void sca_init(card_t *card, int wait_states)
+ {
+ 	sca_out(wait_states, WCRL, card); /* Wait Control */
+ 	sca_out(wait_states, WCRM, card);
+diff --git a/drivers/net/wan/hd64572.c b/drivers/net/wan/hd64572.c
+index e2779faa6c4f..f1685d9624c8 100644
+--- a/drivers/net/wan/hd64572.c
++++ b/drivers/net/wan/hd64572.c
+@@ -605,7 +605,7 @@ static netdev_tx_t sca_xmit(struct sk_buff *skb, struct net_device *dev)
+ }
+ 
+ 
+-static u32 __devinit sca_detect_ram(card_t *card, u8 __iomem *rambase,
++static u32 sca_detect_ram(card_t *card, u8 __iomem *rambase,
+ 				    u32 ramsize)
+ {
+ 	/* Round RAM size to 32 bits, fill from end to start */
+@@ -625,7 +625,7 @@ static u32 __devinit sca_detect_ram(card_t *card, u8 __iomem *rambase,
+ }
+ 
+ 
+-static void __devinit sca_init(card_t *card, int wait_states)
++static void sca_init(card_t *card, int wait_states)
+ {
+ 	sca_out(wait_states, WCRL, card); /* Wait Control */
+ 	sca_out(wait_states, WCRM, card);
+diff --git a/drivers/net/wan/pc300too.c b/drivers/net/wan/pc300too.c
+index 5fe246e060d7..a51cfa7c6540 100644
+--- a/drivers/net/wan/pc300too.c
++++ b/drivers/net/wan/pc300too.c
+@@ -297,7 +297,7 @@ static const struct net_device_ops pc300_ops = {
+ 	.ndo_do_ioctl   = pc300_ioctl,
+ };
+ 
+-static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
++static int pc300_pci_init_one(struct pci_dev *pdev,
+ 					const struct pci_device_id *ent)
+ {
+ 	card_t *card;
+diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c
+index 9659fcaa34ed..037c423a6328 100644
+--- a/drivers/net/wan/pci200syn.c
++++ b/drivers/net/wan/pci200syn.c
+@@ -276,7 +276,7 @@ static const struct net_device_ops pci200_ops = {
+ 	.ndo_do_ioctl   = pci200_ioctl,
+ };
+ 
+-static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
++static int pci200_pci_init_one(struct pci_dev *pdev,
+ 					 const struct pci_device_id *ent)
+ {
+ 	card_t *card;
+diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
+index feb7541b33fb..b72be1280361 100644
+--- a/drivers/net/wan/wanxl.c
++++ b/drivers/net/wan/wanxl.c
+@@ -557,7 +557,7 @@ static const struct net_device_ops wanxl_ops = {
+ 	.ndo_get_stats  = wanxl_get_stats,
+ };
+ 
+-static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
++static int wanxl_pci_init_one(struct pci_dev *pdev,
+ 					const struct pci_device_id *ent)
+ {
+ 	card_t *card;

commit 5a37931ff0be06b4c774aa604f86ed4566a0ede7
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:24:18 2012 -0500
+
+    farsync: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Kevin Curtis 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
+index b6271325f803..56941d6547eb 100644
+--- a/drivers/net/wan/farsync.c
++++ b/drivers/net/wan/farsync.c
+@@ -2361,7 +2361,7 @@ fst_start_xmit(struct sk_buff *skb, struct net_device *dev)
+  *      via a printk and leave the corresponding interface and all that follow
+  *      disabled.
+  */
+-static char *type_strings[] __devinitdata = {
++static char *type_strings[] = {
+ 	"no hardware",		/* Should never be seen */
+ 	"FarSync T2P",
+ 	"FarSync T4P",
+@@ -2371,7 +2371,7 @@ static char *type_strings[] __devinitdata = {
+ 	"FarSync TE1"
+ };
+ 
+-static void __devinit
++static void
+ fst_init_card(struct fst_card_info *card)
+ {
+ 	int i;
+@@ -2415,7 +2415,7 @@ static const struct net_device_ops fst_ops = {
+  *      Initialise card when detected.
+  *      Returns 0 to indicate success, or errno otherwise.
+  */
+-static int __devinit
++static int
+ fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ 	static int no_of_cards_added = 0;
+@@ -2615,7 +2615,7 @@ fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ /*
+  *      Cleanup and close down a card
+  */
+-static void __devexit
++static void
+ fst_remove_one(struct pci_dev *pdev)
+ {
+ 	struct fst_card_info *card;
+@@ -2652,7 +2652,7 @@ static struct pci_driver fst_driver = {
+         .name		= FST_NAME,
+         .id_table	= fst_pci_dev_id,
+         .probe		= fst_add_one,
+-        .remove	= __devexit_p(fst_remove_one),
++        .remove	= fst_remove_one,
+         .suspend	= NULL,
+         .resume	= NULL,
+ };

commit 6ad888c679ff7b4143e8a89706a5c097004b168a
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:24:17 2012 -0500
+
+    dscc4: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Francois Romieu 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
+index ef36cafd44b7..d50223050cf4 100644
+--- a/drivers/net/wan/dscc4.c
++++ b/drivers/net/wan/dscc4.c
+@@ -707,7 +707,7 @@ static void dscc4_free1(struct pci_dev *pdev)
+ 	kfree(ppriv);
+ }
+ 
+-static int __devinit dscc4_init_one(struct pci_dev *pdev,
++static int dscc4_init_one(struct pci_dev *pdev,
+ 				  const struct pci_device_id *ent)
+ {
+ 	struct dscc4_pci_priv *priv;
+@@ -1968,7 +1968,7 @@ static int dscc4_init_ring(struct net_device *dev)
+ 	return -ENOMEM;
+ }
+ 
+-static void __devexit dscc4_remove_one(struct pci_dev *pdev)
++static void dscc4_remove_one(struct pci_dev *pdev)
+ {
+ 	struct dscc4_pci_priv *ppriv;
+ 	struct dscc4_dev_priv *root;
+@@ -2053,7 +2053,7 @@ static struct pci_driver dscc4_driver = {
+ 	.name		= DRV_NAME,
+ 	.id_table	= dscc4_pci_tbl,
+ 	.probe		= dscc4_init_one,
+-	.remove		= __devexit_p(dscc4_remove_one),
++	.remove		= dscc4_remove_one,
+ };
+ 
+ module_pci_driver(dscc4_driver);

commit 3a4751a3bb2704ca382e22a07648a5c255d6916d
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:24:16 2012 -0500
+
+    vmxnet3: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Shreyas Bhatewara 
+    Cc: VMware, Inc. 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
+index e4a192b26423..dc8913c6238c 100644
+--- a/drivers/net/vmxnet3/vmxnet3_drv.c
++++ b/drivers/net/vmxnet3/vmxnet3_drv.c
+@@ -2885,7 +2885,7 @@ vmxnet3_reset_work(struct work_struct *data)
+ }
+ 
+ 
+-static int __devinit
++static int
+ vmxnet3_probe_device(struct pci_dev *pdev,
+ 		     const struct pci_device_id *id)
+ {
+@@ -3096,7 +3096,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,
+ }
+ 
+ 
+-static void __devexit
++static void
+ vmxnet3_remove_device(struct pci_dev *pdev)
+ {
+ 	struct net_device *netdev = pci_get_drvdata(pdev);
+@@ -3302,7 +3302,7 @@ static struct pci_driver vmxnet3_driver = {
+ 	.name		= vmxnet3_driver_name,
+ 	.id_table	= vmxnet3_pciid_table,
+ 	.probe		= vmxnet3_probe_device,
+-	.remove		= __devexit_p(vmxnet3_remove_device),
++	.remove		= vmxnet3_remove_device,
+ #ifdef CONFIG_PM
+ 	.driver.pm	= &vmxnet3_pm_ops,
+ #endif

commit 8cc085d604f7f2f1be68d0b50db1dfd5640266b7
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:24:15 2012 -0500
+
+    virtio_net: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Rusty Russell 
+    Cc: Michael S. Tsirkin 
+    Cc: virtualization@lists.linux-foundation.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
+index 26c502e4b871..90ac97df2d02 100644
+--- a/drivers/net/virtio_net.c
++++ b/drivers/net/virtio_net.c
+@@ -1203,7 +1203,7 @@ static void remove_vq_common(struct virtnet_info *vi)
+ 		__free_pages(get_a_page(vi, GFP_KERNEL), 0);
+ }
+ 
+-static void __devexit virtnet_remove(struct virtio_device *vdev)
++static void virtnet_remove(struct virtio_device *vdev)
+ {
+ 	struct virtnet_info *vi = vdev->priv;
+ 
+@@ -1293,7 +1293,7 @@ static struct virtio_driver virtio_net_driver = {
+ 	.driver.owner =	THIS_MODULE,
+ 	.id_table =	id_table,
+ 	.probe =	virtnet_probe,
+-	.remove =	__devexit_p(virtnet_remove),
++	.remove =	virtnet_remove,
+ 	.config_changed = virtnet_config_changed,
+ #ifdef CONFIG_PM
+ 	.freeze =	virtnet_freeze,

commit 633d1594974b33a673a9eaf141d557e176202d8f
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:24:14 2012 -0500
+
+    net/phy: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
+index 2ed1140df3e9..36fe08ac74bd 100644
+--- a/drivers/net/phy/mdio-gpio.c
++++ b/drivers/net/phy/mdio-gpio.c
+@@ -103,7 +103,7 @@ static struct mdiobb_ops mdio_gpio_ops = {
+ 	.get_mdio_data = mdio_get,
+ };
+ 
+-static struct mii_bus * __devinit mdio_gpio_bus_init(struct device *dev,
++static struct mii_bus *mdio_gpio_bus_init(struct device *dev,
+ 					struct mdio_gpio_platform_data *pdata,
+ 					int bus_id)
+ {
+@@ -173,7 +173,7 @@ static void mdio_gpio_bus_deinit(struct device *dev)
+ 	kfree(bitbang);
+ }
+ 
+-static void __devexit mdio_gpio_bus_destroy(struct device *dev)
++static void mdio_gpio_bus_destroy(struct device *dev)
+ {
+ 	struct mii_bus *bus = dev_get_drvdata(dev);
+ 
+@@ -181,7 +181,7 @@ static void __devexit mdio_gpio_bus_destroy(struct device *dev)
+ 	mdio_gpio_bus_deinit(dev);
+ }
+ 
+-static int __devinit mdio_gpio_probe(struct platform_device *pdev)
++static int mdio_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct mdio_gpio_platform_data *pdata;
+ 	struct mii_bus *new_bus;
+@@ -213,7 +213,7 @@ static int __devinit mdio_gpio_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit mdio_gpio_remove(struct platform_device *pdev)
++static int mdio_gpio_remove(struct platform_device *pdev)
+ {
+ 	mdio_gpio_bus_destroy(&pdev->dev);
+ 
+@@ -227,7 +227,7 @@ static struct of_device_id mdio_gpio_of_match[] = {
+ 
+ static struct platform_driver mdio_gpio_driver = {
+ 	.probe = mdio_gpio_probe,
+-	.remove = __devexit_p(mdio_gpio_remove),
++	.remove = mdio_gpio_remove,
+ 	.driver		= {
+ 		.name	= "mdio-gpio",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/net/phy/mdio-mux-gpio.c b/drivers/net/phy/mdio-mux-gpio.c
+index eefe49e8713c..0c9accb1c14f 100644
+--- a/drivers/net/phy/mdio-mux-gpio.c
++++ b/drivers/net/phy/mdio-mux-gpio.c
+@@ -49,7 +49,7 @@ static int mdio_mux_gpio_switch_fn(int current_child, int desired_child,
+ 	return 0;
+ }
+ 
+-static int __devinit mdio_mux_gpio_probe(struct platform_device *pdev)
++static int mdio_mux_gpio_probe(struct platform_device *pdev)
+ {
+ 	enum of_gpio_flags f;
+ 	struct mdio_mux_gpio_state *s;
+@@ -104,7 +104,7 @@ static int __devinit mdio_mux_gpio_probe(struct platform_device *pdev)
+ 	return r;
+ }
+ 
+-static int __devexit mdio_mux_gpio_remove(struct platform_device *pdev)
++static int mdio_mux_gpio_remove(struct platform_device *pdev)
+ {
+ 	struct mdio_mux_gpio_state *s = pdev->dev.platform_data;
+ 	mdio_mux_uninit(s->mux_handle);
+@@ -130,7 +130,7 @@ static struct platform_driver mdio_mux_gpio_driver = {
+ 		.of_match_table = mdio_mux_gpio_match,
+ 	},
+ 	.probe		= mdio_mux_gpio_probe,
+-	.remove		= __devexit_p(mdio_mux_gpio_remove),
++	.remove		= mdio_mux_gpio_remove,
+ };
+ 
+ module_platform_driver(mdio_mux_gpio_driver);
+diff --git a/drivers/net/phy/mdio-mux-mmioreg.c b/drivers/net/phy/mdio-mux-mmioreg.c
+index 9061ba622ac4..9733bd239a86 100644
+--- a/drivers/net/phy/mdio-mux-mmioreg.c
++++ b/drivers/net/phy/mdio-mux-mmioreg.c
+@@ -67,7 +67,7 @@ static int mdio_mux_mmioreg_switch_fn(int current_child, int desired_child,
+ 	return 0;
+ }
+ 
+-static int __devinit mdio_mux_mmioreg_probe(struct platform_device *pdev)
++static int mdio_mux_mmioreg_probe(struct platform_device *pdev)
+ {
+ 	struct device_node *np2, *np = pdev->dev.of_node;
+ 	struct mdio_mux_mmioreg_state *s;
+@@ -137,7 +137,7 @@ static int __devinit mdio_mux_mmioreg_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit mdio_mux_mmioreg_remove(struct platform_device *pdev)
++static int mdio_mux_mmioreg_remove(struct platform_device *pdev)
+ {
+ 	struct mdio_mux_mmioreg_state *s = dev_get_platdata(&pdev->dev);
+ 
+@@ -161,7 +161,7 @@ static struct platform_driver mdio_mux_mmioreg_driver = {
+ 		.of_match_table = mdio_mux_mmioreg_match,
+ 	},
+ 	.probe		= mdio_mux_mmioreg_probe,
+-	.remove		= __devexit_p(mdio_mux_mmioreg_remove),
++	.remove		= mdio_mux_mmioreg_remove,
+ };
+ 
+ module_platform_driver(mdio_mux_mmioreg_driver);
+diff --git a/drivers/net/phy/mdio-octeon.c b/drivers/net/phy/mdio-octeon.c
+index d4015aa663e6..09297fe05ae5 100644
+--- a/drivers/net/phy/mdio-octeon.c
++++ b/drivers/net/phy/mdio-octeon.c
+@@ -96,7 +96,7 @@ static int octeon_mdiobus_write(struct mii_bus *bus, int phy_id,
+ 	return 0;
+ }
+ 
+-static int __devinit octeon_mdiobus_probe(struct platform_device *pdev)
++static int octeon_mdiobus_probe(struct platform_device *pdev)
+ {
+ 	struct octeon_mdiobus *bus;
+ 	struct resource *res_mem;
+@@ -159,7 +159,7 @@ static int __devinit octeon_mdiobus_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit octeon_mdiobus_remove(struct platform_device *pdev)
++static int octeon_mdiobus_remove(struct platform_device *pdev)
+ {
+ 	struct octeon_mdiobus *bus;
+ 	union cvmx_smix_en smi_en;
+@@ -188,7 +188,7 @@ static struct platform_driver octeon_mdiobus_driver = {
+ 		.of_match_table = octeon_mdiobus_match,
+ 	},
+ 	.probe		= octeon_mdiobus_probe,
+-	.remove		= __devexit_p(octeon_mdiobus_remove),
++	.remove		= octeon_mdiobus_remove,
+ };
+ 
+ void octeon_mdiobus_force_mod_depencency(void)
+diff --git a/drivers/net/phy/spi_ks8995.c b/drivers/net/phy/spi_ks8995.c
+index 1c3abce78b6a..41eb8ffeb53d 100644
+--- a/drivers/net/phy/spi_ks8995.c
++++ b/drivers/net/phy/spi_ks8995.c
+@@ -264,7 +264,7 @@ static struct bin_attribute ks8995_registers_attr = {
+ 
+ /* ------------------------------------------------------------------------ */
+ 
+-static int __devinit ks8995_probe(struct spi_device *spi)
++static int ks8995_probe(struct spi_device *spi)
+ {
+ 	struct ks8995_switch    *ks;
+ 	struct ks8995_pdata     *pdata;
+@@ -332,7 +332,7 @@ static int __devinit ks8995_probe(struct spi_device *spi)
+ 	return err;
+ }
+ 
+-static int __devexit ks8995_remove(struct spi_device *spi)
++static int ks8995_remove(struct spi_device *spi)
+ {
+ 	struct ks8995_data      *ks8995;
+ 
+@@ -353,7 +353,7 @@ static struct spi_driver ks8995_driver = {
+ 		.owner	   = THIS_MODULE,
+ 	},
+ 	.probe	  = ks8995_probe,
+-	.remove	  = __devexit_p(ks8995_remove),
++	.remove	  = ks8995_remove,
+ };
+ 
+ static int __init ks8995_init(void)

commit 45ac936c3ec93f347cfb7652bd7b332dc0c9b2e8
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:24:13 2012 -0500
+
+    irda: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Samuel Ortiz 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c
+index e09417df8f39..b5151e4ced61 100644
+--- a/drivers/net/irda/au1k_ir.c
++++ b/drivers/net/irda/au1k_ir.c
+@@ -760,7 +760,7 @@ static const struct net_device_ops au1k_irda_netdev_ops = {
+ 	.ndo_do_ioctl		= au1k_irda_ioctl,
+ };
+ 
+-static int __devinit au1k_irda_net_init(struct net_device *dev)
++static int au1k_irda_net_init(struct net_device *dev)
+ {
+ 	struct au1k_private *aup = netdev_priv(dev);
+ 	struct db_dest *pDB, *pDBfree;
+@@ -849,7 +849,7 @@ static int __devinit au1k_irda_net_init(struct net_device *dev)
+ 	return retval;
+ }
+ 
+-static int __devinit au1k_irda_probe(struct platform_device *pdev)
++static int au1k_irda_probe(struct platform_device *pdev)
+ {
+ 	struct au1k_private *aup;
+ 	struct net_device *dev;
+@@ -921,7 +921,7 @@ static int __devinit au1k_irda_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit au1k_irda_remove(struct platform_device *pdev)
++static int au1k_irda_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *dev = platform_get_drvdata(pdev);
+ 	struct au1k_private *aup = netdev_priv(dev);
+@@ -949,7 +949,7 @@ static struct platform_driver au1k_irda_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= au1k_irda_probe,
+-	.remove		= __devexit_p(au1k_irda_remove),
++	.remove		= au1k_irda_remove,
+ };
+ 
+ static int __init au1k_irda_load(void)
+diff --git a/drivers/net/irda/bfin_sir.c b/drivers/net/irda/bfin_sir.c
+index c6a0299aa9f9..fed4a05d55c7 100644
+--- a/drivers/net/irda/bfin_sir.c
++++ b/drivers/net/irda/bfin_sir.c
+@@ -31,7 +31,7 @@ static void turnaround_delay(unsigned long last_jif, int mtt)
+ 	schedule_timeout_uninterruptible(ticks);
+ }
+ 
+-static void __devinit bfin_sir_init_ports(struct bfin_sir_port *sp, struct platform_device *pdev)
++static void bfin_sir_init_ports(struct bfin_sir_port *sp, struct platform_device *pdev)
+ {
+ 	int i;
+ 	struct resource *res;
+@@ -688,7 +688,7 @@ static const struct net_device_ops bfin_sir_ndo = {
+ 	.ndo_get_stats		= bfin_sir_stats,
+ };
+ 
+-static int __devinit bfin_sir_probe(struct platform_device *pdev)
++static int bfin_sir_probe(struct platform_device *pdev)
+ {
+ 	struct net_device *dev;
+ 	struct bfin_sir_self *self;
+@@ -775,7 +775,7 @@ static int __devinit bfin_sir_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit bfin_sir_remove(struct platform_device *pdev)
++static int bfin_sir_remove(struct platform_device *pdev)
+ {
+ 	struct bfin_sir_port *sir_port;
+ 	struct net_device *dev = NULL;
+@@ -798,7 +798,7 @@ static int __devexit bfin_sir_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver bfin_ir_driver = {
+ 	.probe   = bfin_sir_probe,
+-	.remove  = __devexit_p(bfin_sir_remove),
++	.remove  = bfin_sir_remove,
+ 	.suspend = bfin_sir_suspend,
+ 	.resume  = bfin_sir_resume,
+ 	.driver  = {
+diff --git a/drivers/net/irda/sh_irda.c b/drivers/net/irda/sh_irda.c
+index 945360a99cb4..9448587de453 100644
+--- a/drivers/net/irda/sh_irda.c
++++ b/drivers/net/irda/sh_irda.c
+@@ -753,7 +753,7 @@ static const struct net_device_ops sh_irda_ndo = {
+ 
+ 
+ ************************************************************************/
+-static int __devinit sh_irda_probe(struct platform_device *pdev)
++static int sh_irda_probe(struct platform_device *pdev)
+ {
+ 	struct net_device *ndev;
+ 	struct sh_irda_self *self;
+@@ -825,7 +825,7 @@ static int __devinit sh_irda_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit sh_irda_remove(struct platform_device *pdev)
++static int sh_irda_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *ndev = platform_get_drvdata(pdev);
+ 	struct sh_irda_self *self = netdev_priv(ndev);
+@@ -862,7 +862,7 @@ static const struct dev_pm_ops sh_irda_pm_ops = {
+ 
+ static struct platform_driver sh_irda_driver = {
+ 	.probe	= sh_irda_probe,
+-	.remove	= __devexit_p(sh_irda_remove),
++	.remove	= sh_irda_remove,
+ 	.driver	= {
+ 		.name	= DRIVER_NAME,
+ 		.pm	= &sh_irda_pm_ops,
+diff --git a/drivers/net/irda/sh_sir.c b/drivers/net/irda/sh_sir.c
+index 624ac1939e85..24aefcd84065 100644
+--- a/drivers/net/irda/sh_sir.c
++++ b/drivers/net/irda/sh_sir.c
+@@ -705,7 +705,7 @@ static const struct net_device_ops sh_sir_ndo = {
+ 
+ 
+ ************************************************************************/
+-static int __devinit sh_sir_probe(struct platform_device *pdev)
++static int sh_sir_probe(struct platform_device *pdev)
+ {
+ 	struct net_device *ndev;
+ 	struct sh_sir_self *self;
+@@ -783,7 +783,7 @@ static int __devinit sh_sir_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit sh_sir_remove(struct platform_device *pdev)
++static int sh_sir_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *ndev = platform_get_drvdata(pdev);
+ 	struct sh_sir_self *self = netdev_priv(ndev);
+@@ -803,7 +803,7 @@ static int __devexit sh_sir_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver sh_sir_driver = {
+ 	.probe   = sh_sir_probe,
+-	.remove  = __devexit_p(sh_sir_remove),
++	.remove  = sh_sir_remove,
+ 	.driver  = {
+ 		.name = DRIVER_NAME,
+ 	},
+diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
+index a926813ee91d..82c5f30aabab 100644
+--- a/drivers/net/irda/smsc-ircc2.c
++++ b/drivers/net/irda/smsc-ircc2.c
+@@ -376,7 +376,7 @@ MODULE_DEVICE_TABLE(pnp, smsc_ircc_pnp_table);
+ static int pnp_driver_registered;
+ 
+ #ifdef CONFIG_PNP
+-static int __devinit smsc_ircc_pnp_probe(struct pnp_dev *dev,
++static int smsc_ircc_pnp_probe(struct pnp_dev *dev,
+ 				      const struct pnp_device_id *dev_id)
+ {
+ 	unsigned int firbase, sirbase;
+@@ -515,7 +515,7 @@ static const struct net_device_ops smsc_ircc_netdev_ops = {
+  *    Try to open driver instance
+  *
+  */
+-static int __devinit smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq)
++static int smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq)
+ {
+ 	struct smsc_ircc_cb *self;
+ 	struct net_device *dev;
+diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c
+index 1a89fd459dd5..63efbf4b51c8 100644
+--- a/drivers/net/irda/via-ircc.c
++++ b/drivers/net/irda/via-ircc.c
+@@ -102,8 +102,8 @@ static int RxTimerHandler(struct via_ircc_cb *self, int iobase);
+ static void hwreset(struct via_ircc_cb *self);
+ static int via_ircc_dma_xmit(struct via_ircc_cb *self, u16 iobase);
+ static int upload_rxdata(struct via_ircc_cb *self, int iobase);
+-static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_device_id *id);
+-static void __devexit via_remove_one (struct pci_dev *pdev);
++static int via_init_one(struct pci_dev *pcidev, const struct pci_device_id *id);
++static void via_remove_one (struct pci_dev *pdev);
+ 
+ /* FIXME : Should use udelay() instead, even if we are x86 only - Jean II */
+ static void iodelay(int udelay)
+@@ -132,7 +132,7 @@ static struct pci_driver via_driver = {
+ 	.name		= VIA_MODULE_NAME,
+ 	.id_table	= via_pci_tbl,
+ 	.probe		= via_init_one,
+-	.remove		= __devexit_p(via_remove_one),
++	.remove		= via_remove_one,
+ };
+ 
+ 
+@@ -156,7 +156,7 @@ static int __init via_ircc_init(void)
+ 	return 0;
+ }
+ 
+-static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_device_id *id)
++static int via_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
+ {
+ 	int rc;
+         u8 temp,oldPCI_40,oldPCI_44,bTmp,bTmp1;
+@@ -286,8 +286,8 @@ static const struct net_device_ops via_ircc_fir_ops = {
+  *    Open driver instance
+  *
+  */
+-static __devinit int via_ircc_open(struct pci_dev *pdev, chipio_t * info,
+-				   unsigned int id)
++static int via_ircc_open(struct pci_dev *pdev, chipio_t *info,
++			 unsigned int id)
+ {
+ 	struct net_device *dev;
+ 	struct via_ircc_cb *self;
+@@ -424,7 +424,7 @@ static __devinit int via_ircc_open(struct pci_dev *pdev, chipio_t * info,
+  *    Close driver instance
+  *
+  */
+-static void __devexit via_remove_one(struct pci_dev *pdev)
++static void via_remove_one(struct pci_dev *pdev)
+ {
+ 	struct via_ircc_cb *self = pci_get_drvdata(pdev);
+ 	int iobase;
+diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
+index 9021d0131727..2f99f8881dfc 100644
+--- a/drivers/net/irda/vlsi_ir.c
++++ b/drivers/net/irda/vlsi_ir.c
+@@ -1627,7 +1627,7 @@ static int vlsi_irda_init(struct net_device *ndev)
+ 
+ /**************************************************************/
+ 
+-static int __devinit
++static int
+ vlsi_irda_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ 	struct net_device	*ndev;
+@@ -1699,7 +1699,7 @@ vlsi_irda_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	return -ENODEV;
+ }
+ 
+-static void __devexit vlsi_irda_remove(struct pci_dev *pdev)
++static void vlsi_irda_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *ndev = pci_get_drvdata(pdev);
+ 	vlsi_irda_dev_t *idev;
+@@ -1832,7 +1832,7 @@ static struct pci_driver vlsi_irda_driver = {
+ 	.name		= drivername,
+ 	.id_table	= vlsi_irda_table,
+ 	.probe		= vlsi_irda_probe,
+-	.remove		= __devexit_p(vlsi_irda_remove),
++	.remove		= vlsi_irda_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= vlsi_irda_suspend,
+ 	.resume		= vlsi_irda_resume,

commit bb1f4606754c45bbb467c15aa5fec84228f73e47
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:24:12 2012 -0500
+
+    ieee802154: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
+index ba753d87a32f..a4a62e170ec0 100644
+--- a/drivers/net/ieee802154/at86rf230.c
++++ b/drivers/net/ieee802154/at86rf230.c
+@@ -778,7 +778,7 @@ static int at86rf230_fill_data(struct spi_device *spi)
+ 	return 0;
+ }
+ 
+-static int __devinit at86rf230_probe(struct spi_device *spi)
++static int at86rf230_probe(struct spi_device *spi)
+ {
+ 	struct ieee802154_dev *dev;
+ 	struct at86rf230_local *lp;
+@@ -920,7 +920,7 @@ static int __devinit at86rf230_probe(struct spi_device *spi)
+ 	return rc;
+ }
+ 
+-static int __devexit at86rf230_remove(struct spi_device *spi)
++static int at86rf230_remove(struct spi_device *spi)
+ {
+ 	struct at86rf230_local *lp = spi_get_drvdata(spi);
+ 
+@@ -947,7 +947,7 @@ static struct spi_driver at86rf230_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe      = at86rf230_probe,
+-	.remove     = __devexit_p(at86rf230_remove),
++	.remove     = at86rf230_remove,
+ 	.suspend    = at86rf230_suspend,
+ 	.resume     = at86rf230_resume,
+ };
+diff --git a/drivers/net/ieee802154/fakehard.c b/drivers/net/ieee802154/fakehard.c
+index 7d39add7d467..1e9cb0bbf62c 100644
+--- a/drivers/net/ieee802154/fakehard.c
++++ b/drivers/net/ieee802154/fakehard.c
+@@ -354,7 +354,7 @@ static void ieee802154_fake_setup(struct net_device *dev)
+ }
+ 
+ 
+-static int __devinit ieee802154fake_probe(struct platform_device *pdev)
++static int ieee802154fake_probe(struct platform_device *pdev)
+ {
+ 	struct net_device *dev;
+ 	struct fakehard_priv *priv;
+@@ -412,7 +412,7 @@ static int __devinit ieee802154fake_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit ieee802154fake_remove(struct platform_device *pdev)
++static int ieee802154fake_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *dev = platform_get_drvdata(pdev);
+ 	unregister_netdev(dev);
+@@ -423,7 +423,7 @@ static struct platform_device *ieee802154fake_dev;
+ 
+ static struct platform_driver ieee802154fake_driver = {
+ 	.probe = ieee802154fake_probe,
+-	.remove = __devexit_p(ieee802154fake_remove),
++	.remove = ieee802154fake_remove,
+ 	.driver = {
+ 			.name = "ieee802154hardmac",
+ 			.owner = THIS_MODULE,
+diff --git a/drivers/net/ieee802154/fakelb.c b/drivers/net/ieee802154/fakelb.c
+index e7456fcd0913..b8d22173925d 100644
+--- a/drivers/net/ieee802154/fakelb.c
++++ b/drivers/net/ieee802154/fakelb.c
+@@ -221,7 +221,7 @@ static void fakelb_del(struct fakelb_dev_priv *priv)
+ 	ieee802154_free_device(priv->dev);
+ }
+ 
+-static int __devinit fakelb_probe(struct platform_device *pdev)
++static int fakelb_probe(struct platform_device *pdev)
+ {
+ 	struct fakelb_priv *priv;
+ 	struct fakelb_dev_priv *dp;
+@@ -253,7 +253,7 @@ static int __devinit fakelb_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit fakelb_remove(struct platform_device *pdev)
++static int fakelb_remove(struct platform_device *pdev)
+ {
+ 	struct fakelb_priv *priv = platform_get_drvdata(pdev);
+ 	struct fakelb_dev_priv *dp, *temp;
+@@ -269,7 +269,7 @@ static struct platform_device *ieee802154fake_dev;
+ 
+ static struct platform_driver ieee802154fake_driver = {
+ 	.probe = fakelb_probe,
+-	.remove = __devexit_p(fakelb_remove),
++	.remove = fakelb_remove,
+ 	.driver = {
+ 			.name = "ieee802154fakelb",
+ 			.owner = THIS_MODULE,
+diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c
+index ed7521693980..3f2c7aaf28c4 100644
+--- a/drivers/net/ieee802154/mrf24j40.c
++++ b/drivers/net/ieee802154/mrf24j40.c
+@@ -618,7 +618,7 @@ static void mrf24j40_isrwork(struct work_struct *work)
+ 	enable_irq(devrec->spi->irq);
+ }
+ 
+-static int __devinit mrf24j40_probe(struct spi_device *spi)
++static int mrf24j40_probe(struct spi_device *spi)
+ {
+ 	int ret = -ENOMEM;
+ 	u8 val;
+@@ -711,7 +711,7 @@ static int __devinit mrf24j40_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit mrf24j40_remove(struct spi_device *spi)
++static int mrf24j40_remove(struct spi_device *spi)
+ {
+ 	struct mrf24j40 *devrec = dev_get_drvdata(&spi->dev);
+ 
+@@ -746,7 +746,7 @@ static struct spi_driver mrf24j40_driver = {
+ 	},
+ 	.id_table = mrf24j40_ids,
+ 	.probe = mrf24j40_probe,
+-	.remove = __devexit_p(mrf24j40_remove),
++	.remove = mrf24j40_remove,
+ };
+ 
+ static int __init mrf24j40_init(void)

commit 6e9454913e9b0e7b02377ee102348dd8e9681f44
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:24:11 2012 -0500
+
+    hippi: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Jes Sorensen 
+    Cc: linux-hippi@sunsite.dk
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/hippi/rrunner.c b/drivers/net/hippi/rrunner.c
+index d4719632ffc6..e54b84d5ad76 100644
+--- a/drivers/net/hippi/rrunner.c
++++ b/drivers/net/hippi/rrunner.c
+@@ -61,7 +61,7 @@ MODULE_AUTHOR("Jes Sorensen ");
+ MODULE_DESCRIPTION("Essential RoadRunner HIPPI driver");
+ MODULE_LICENSE("GPL");
+ 
+-static char version[] __devinitdata = "rrunner.c: v0.50 11/11/2002  Jes Sorensen (jes@wildopensource.com)\n";
++static char version[] = "rrunner.c: v0.50 11/11/2002  Jes Sorensen (jes@wildopensource.com)\n";
+ 
+ 
+ static const struct net_device_ops rr_netdev_ops = {
+@@ -88,7 +88,7 @@ static const struct net_device_ops rr_netdev_ops = {
+  * stack will need to know about I/O vectors or something similar.
+  */
+ 
+-static int __devinit rr_init_one(struct pci_dev *pdev,
++static int rr_init_one(struct pci_dev *pdev,
+ 	const struct pci_device_id *ent)
+ {
+ 	struct net_device *dev;
+@@ -221,7 +221,7 @@ static int __devinit rr_init_one(struct pci_dev *pdev,
+ 	return ret;
+ }
+ 
+-static void __devexit rr_remove_one (struct pci_dev *pdev)
++static void rr_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct rr_private *rr = netdev_priv(dev);
+@@ -503,7 +503,7 @@ static unsigned int write_eeprom(struct rr_private *rrpriv,
+ }
+ 
+ 
+-static int __devinit rr_init(struct net_device *dev)
++static int rr_init(struct net_device *dev)
+ {
+ 	struct rr_private *rrpriv;
+ 	struct rr_regs __iomem *regs;
+@@ -1681,7 +1681,7 @@ static struct pci_driver rr_driver = {
+ 	.name		= "rrunner",
+ 	.id_table	= rr_pci_tbl,
+ 	.probe		= rr_init_one,
+-	.remove		= __devexit_p(rr_remove_one),
++	.remove		= rr_remove_one,
+ };
+ 
+ static int __init rr_init_module(void)

commit c354dfc3f222ec895411a8297d929ff666cbc153
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:24:10 2012 -0500
+
+    fddi: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Maciej W. Rozycki 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/fddi/defxx.c b/drivers/net/fddi/defxx.c
+index 6695a1dadf4e..3c8aab70f5e7 100644
+--- a/drivers/net/fddi/defxx.c
++++ b/drivers/net/fddi/defxx.c
+@@ -228,7 +228,7 @@
+ #define DRV_VERSION "v1.10"
+ #define DRV_RELDATE "2006/12/14"
+ 
+-static char version[] __devinitdata =
++static char version[] =
+ 	DRV_NAME ": " DRV_VERSION " " DRV_RELDATE
+ 	"  Lawrence V. Stefani and others\n";
+ 
+@@ -515,7 +515,7 @@ static const struct net_device_ops dfx_netdev_ops = {
+  *   initialized and the board resources are read and stored in
+  *   the device structure.
+  */
+-static int __devinit dfx_register(struct device *bdev)
++static int dfx_register(struct device *bdev)
+ {
+ 	static int version_disp;
+ 	int dfx_bus_pci = DFX_BUS_PCI(bdev);
+@@ -663,7 +663,7 @@ static int __devinit dfx_register(struct device *bdev)
+  *   enabled yet.
+  */
+ 
+-static void __devinit dfx_bus_init(struct net_device *dev)
++static void dfx_bus_init(struct net_device *dev)
+ {
+ 	DFX_board_t *bp = netdev_priv(dev);
+ 	struct device *bdev = bp->bus_dev;
+@@ -809,7 +809,7 @@ static void __devinit dfx_bus_init(struct net_device *dev)
+  *   Interrupts are disabled at the adapter bus-specific logic.
+  */
+ 
+-static void __devexit dfx_bus_uninit(struct net_device *dev)
++static void dfx_bus_uninit(struct net_device *dev)
+ {
+ 	DFX_board_t *bp = netdev_priv(dev);
+ 	struct device *bdev = bp->bus_dev;
+@@ -866,7 +866,7 @@ static void __devexit dfx_bus_uninit(struct net_device *dev)
+  *   None
+  */
+ 
+-static void __devinit dfx_bus_config_check(DFX_board_t *bp)
++static void dfx_bus_config_check(DFX_board_t *bp)
+ {
+ 	struct device __maybe_unused *bdev = bp->bus_dev;
+ 	int dfx_bus_eisa = DFX_BUS_EISA(bdev);
+@@ -962,7 +962,7 @@ static void __devinit dfx_bus_config_check(DFX_board_t *bp)
+  *   returning from this routine.
+  */
+ 
+-static int __devinit dfx_driver_init(struct net_device *dev,
++static int dfx_driver_init(struct net_device *dev,
+ 				     const char *print_name,
+ 				     resource_size_t bar_start)
+ {
+@@ -3579,7 +3579,7 @@ static void dfx_xmt_flush( DFX_board_t *bp )
+  *   Device structures for FDDI adapters (fddi0, fddi1, etc) are
+  *   freed.
+  */
+-static void __devexit dfx_unregister(struct device *bdev)
++static void dfx_unregister(struct device *bdev)
+ {
+ 	struct net_device *dev = dev_get_drvdata(bdev);
+ 	DFX_board_t *bp = netdev_priv(dev);
+@@ -3619,13 +3619,13 @@ static void __devexit dfx_unregister(struct device *bdev)
+ }
+ 
+ 
+-static int __devinit __maybe_unused dfx_dev_register(struct device *);
+-static int __devexit __maybe_unused dfx_dev_unregister(struct device *);
++static int __maybe_unused dfx_dev_register(struct device *);
++static int __maybe_unused dfx_dev_unregister(struct device *);
+ 
+ #ifdef CONFIG_PCI
+-static int __devinit dfx_pci_register(struct pci_dev *,
++static int dfx_pci_register(struct pci_dev *,
+ 				      const struct pci_device_id *);
+-static void __devexit dfx_pci_unregister(struct pci_dev *);
++static void dfx_pci_unregister(struct pci_dev *);
+ 
+ static DEFINE_PCI_DEVICE_TABLE(dfx_pci_table) = {
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI) },
+@@ -3637,16 +3637,16 @@ static struct pci_driver dfx_pci_driver = {
+ 	.name		= "defxx",
+ 	.id_table	= dfx_pci_table,
+ 	.probe		= dfx_pci_register,
+-	.remove		= __devexit_p(dfx_pci_unregister),
++	.remove		= dfx_pci_unregister,
+ };
+ 
+-static __devinit int dfx_pci_register(struct pci_dev *pdev,
++static int dfx_pci_register(struct pci_dev *pdev,
+ 				      const struct pci_device_id *ent)
+ {
+ 	return dfx_register(&pdev->dev);
+ }
+ 
+-static void __devexit dfx_pci_unregister(struct pci_dev *pdev)
++static void dfx_pci_unregister(struct pci_dev *pdev)
+ {
+ 	dfx_unregister(&pdev->dev);
+ }
+@@ -3668,7 +3668,7 @@ static struct eisa_driver dfx_eisa_driver = {
+ 		.name	= "defxx",
+ 		.bus	= &eisa_bus_type,
+ 		.probe	= dfx_dev_register,
+-		.remove	= __devexit_p(dfx_dev_unregister),
++		.remove	= dfx_dev_unregister,
+ 	},
+ };
+ #endif /* CONFIG_EISA */
+@@ -3689,12 +3689,12 @@ static struct tc_driver dfx_tc_driver = {
+ 		.name	= "defxx",
+ 		.bus	= &tc_bus_type,
+ 		.probe	= dfx_dev_register,
+-		.remove	= __devexit_p(dfx_dev_unregister),
++		.remove	= dfx_dev_unregister,
+ 	},
+ };
+ #endif /* CONFIG_TC */
+ 
+-static int __devinit __maybe_unused dfx_dev_register(struct device *dev)
++static int __maybe_unused dfx_dev_register(struct device *dev)
+ {
+ 	int status;
+ 
+@@ -3704,7 +3704,7 @@ static int __devinit __maybe_unused dfx_dev_register(struct device *dev)
+ 	return status;
+ }
+ 
+-static int __devexit __maybe_unused dfx_dev_unregister(struct device *dev)
++static int __maybe_unused dfx_dev_unregister(struct device *dev)
+ {
+ 	put_device(dev);
+ 	dfx_unregister(dev);
+@@ -3712,7 +3712,7 @@ static int __devexit __maybe_unused dfx_dev_unregister(struct device *dev)
+ }
+ 
+ 
+-static int __devinit dfx_init(void)
++static int dfx_init(void)
+ {
+ 	int status;
+ 
+@@ -3724,7 +3724,7 @@ static int __devinit dfx_init(void)
+ 	return status;
+ }
+ 
+-static void __devexit dfx_cleanup(void)
++static void dfx_cleanup(void)
+ {
+ 	tc_unregister_driver(&dfx_tc_driver);
+ 	eisa_driver_unregister(&dfx_eisa_driver);
+diff --git a/drivers/net/fddi/skfp/skfddi.c b/drivers/net/fddi/skfp/skfddi.c
+index 3d9a4596a423..d5bd563ac131 100644
+--- a/drivers/net/fddi/skfp/skfddi.c
++++ b/drivers/net/fddi/skfp/skfddi.c
+@@ -321,7 +321,7 @@ static int skfp_init_one(struct pci_dev *pdev,
+ /*
+  * Called for each adapter board from pci_unregister_driver
+  */
+-static void __devexit skfp_remove_one(struct pci_dev *pdev)
++static void skfp_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *p = pci_get_drvdata(pdev);
+ 	struct s_smc *lp = netdev_priv(p);
+@@ -2243,7 +2243,7 @@ static struct pci_driver skfddi_pci_driver = {
+ 	.name		= "skfddi",
+ 	.id_table	= skfddi_pci_tbl,
+ 	.probe		= skfp_init_one,
+-	.remove		= __devexit_p(skfp_remove_one),
++	.remove		= skfp_remove_one,
+ };
+ 
+ static int __init skfd_init(void)

commit a0a4efedf9dea0f2dd9625181b48c1f8c6d5418e
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:24:09 2012 -0500
+
+    net/ethernet: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/dnet.c b/drivers/net/ethernet/dnet.c
+index feb5095d81b7..2c177b329c8b 100644
+--- a/drivers/net/ethernet/dnet.c
++++ b/drivers/net/ethernet/dnet.c
+@@ -72,7 +72,7 @@ static void __dnet_set_hwaddr(struct dnet *bp)
+ 	dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_2_REG, tmp);
+ }
+ 
+-static void __devinit dnet_get_hwaddr(struct dnet *bp)
++static void dnet_get_hwaddr(struct dnet *bp)
+ {
+ 	u16 tmp;
+ 	u8 addr[6];
+@@ -826,7 +826,7 @@ static const struct net_device_ops dnet_netdev_ops = {
+ 	.ndo_change_mtu		= eth_change_mtu,
+ };
+ 
+-static int __devinit dnet_probe(struct platform_device *pdev)
++static int dnet_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res;
+ 	struct net_device *dev;
+@@ -942,7 +942,7 @@ static int __devinit dnet_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit dnet_remove(struct platform_device *pdev)
++static int dnet_remove(struct platform_device *pdev)
+ {
+ 
+ 	struct net_device *dev;
+@@ -968,7 +968,7 @@ static int __devexit dnet_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver dnet_driver = {
+ 	.probe		= dnet_probe,
+-	.remove		= __devexit_p(dnet_remove),
++	.remove		= dnet_remove,
+ 	.driver		= {
+ 		.name		= "dnet",
+ 	},
+diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c
+index 94b7bfcdb24e..8db1c06008de 100644
+--- a/drivers/net/ethernet/ethoc.c
++++ b/drivers/net/ethernet/ethoc.c
+@@ -665,7 +665,7 @@ static void ethoc_mdio_poll(struct net_device *dev)
+ {
+ }
+ 
+-static int __devinit ethoc_mdio_probe(struct net_device *dev)
++static int ethoc_mdio_probe(struct net_device *dev)
+ {
+ 	struct ethoc *priv = netdev_priv(dev);
+ 	struct phy_device *phy;
+@@ -905,7 +905,7 @@ static const struct net_device_ops ethoc_netdev_ops = {
+  * ethoc_probe - initialize OpenCores ethernet MAC
+  * pdev:	platform device
+  */
+-static int __devinit ethoc_probe(struct platform_device *pdev)
++static int ethoc_probe(struct platform_device *pdev)
+ {
+ 	struct net_device *netdev = NULL;
+ 	struct resource *res = NULL;
+@@ -1143,7 +1143,7 @@ static int __devinit ethoc_probe(struct platform_device *pdev)
+  * ethoc_remove - shutdown OpenCores ethernet MAC
+  * @pdev:	platform device
+  */
+-static int __devexit ethoc_remove(struct platform_device *pdev)
++static int ethoc_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *netdev = platform_get_drvdata(pdev);
+ 	struct ethoc *priv = netdev_priv(netdev);
+@@ -1190,7 +1190,7 @@ MODULE_DEVICE_TABLE(of, ethoc_match);
+ 
+ static struct platform_driver ethoc_driver = {
+ 	.probe   = ethoc_probe,
+-	.remove  = __devexit_p(ethoc_remove),
++	.remove  = ethoc_remove,
+ 	.suspend = ethoc_suspend,
+ 	.resume  = ethoc_resume,
+ 	.driver  = {
+diff --git a/drivers/net/ethernet/fealnx.c b/drivers/net/ethernet/fealnx.c
+index 0e4a0ac86aa8..519c2895e8f7 100644
+--- a/drivers/net/ethernet/fealnx.c
++++ b/drivers/net/ethernet/fealnx.c
+@@ -92,7 +92,7 @@ static int full_duplex[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
+ #include 
+ 
+ /* These identify the driver base version and may not be removed. */
+-static const char version[] __devinitconst =
++static const char version[] =
+ 	KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "\n";
+ 
+ 
+@@ -150,7 +150,7 @@ struct chip_info {
+ 	int flags;
+ };
+ 
+-static const struct chip_info skel_netdrv_tbl[] __devinitconst = {
++static const struct chip_info skel_netdrv_tbl[] = {
+  	{ "100/10M Ethernet PCI Adapter",	HAS_MII_XCVR },
+ 	{ "100/10M Ethernet PCI Adapter",	HAS_CHIP_XCVR },
+ 	{ "1000/100/10M Ethernet PCI Adapter",	HAS_MII_XCVR },
+@@ -477,7 +477,7 @@ static const struct net_device_ops netdev_ops = {
+ 	.ndo_validate_addr	= eth_validate_addr,
+ };
+ 
+-static int __devinit fealnx_init_one(struct pci_dev *pdev,
++static int fealnx_init_one(struct pci_dev *pdev,
+ 				     const struct pci_device_id *ent)
+ {
+ 	struct netdev_private *np;
+@@ -684,7 +684,7 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
+ }
+ 
+ 
+-static void __devexit fealnx_remove_one(struct pci_dev *pdev)
++static void fealnx_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 
+@@ -1950,7 +1950,7 @@ static struct pci_driver fealnx_driver = {
+ 	.name		= "fealnx",
+ 	.id_table	= fealnx_pci_tbl,
+ 	.probe		= fealnx_init_one,
+-	.remove		= __devexit_p(fealnx_remove_one),
++	.remove		= fealnx_remove_one,
+ };
+ 
+ static int __init fealnx_init(void)
+diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
+index 003c5bc7189f..c124e67a1a1c 100644
+--- a/drivers/net/ethernet/lantiq_etop.c
++++ b/drivers/net/ethernet/lantiq_etop.c
+@@ -774,7 +774,7 @@ ltq_etop_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit
++static int
+ ltq_etop_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *dev = platform_get_drvdata(pdev);
+@@ -789,7 +789,7 @@ ltq_etop_remove(struct platform_device *pdev)
+ }
+ 
+ static struct platform_driver ltq_mii_driver = {
+-	.remove = __devexit_p(ltq_etop_remove),
++	.remove = ltq_etop_remove,
+ 	.driver = {
+ 		.name = "ltq_etop",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/net/ethernet/s6gmac.c b/drivers/net/ethernet/s6gmac.c
+index 2ed3ab4b3c2d..72fc57dd084d 100644
+--- a/drivers/net/ethernet/s6gmac.c
++++ b/drivers/net/ethernet/s6gmac.c
+@@ -954,7 +954,7 @@ static struct net_device_stats *s6gmac_stats(struct net_device *dev)
+ 	return st;
+ }
+ 
+-static int __devinit s6gmac_probe(struct platform_device *pdev)
++static int s6gmac_probe(struct platform_device *pdev)
+ {
+ 	struct net_device *dev;
+ 	struct s6gmac *pd;
+@@ -1030,7 +1030,7 @@ static int __devinit s6gmac_probe(struct platform_device *pdev)
+ 	return res;
+ }
+ 
+-static int __devexit s6gmac_remove(struct platform_device *pdev)
++static int s6gmac_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *dev = platform_get_drvdata(pdev);
+ 	if (dev) {
+@@ -1046,7 +1046,7 @@ static int __devexit s6gmac_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver s6gmac_driver = {
+ 	.probe = s6gmac_probe,
+-	.remove = __devexit_p(s6gmac_remove),
++	.remove = s6gmac_remove,
+ 	.driver = {
+ 		.name = "s6gmac",
+ 		.owner = THIS_MODULE,

commit 06b0e68327d499c3588c954d2a2d86458d451c4b
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:24:08 2012 -0500
+
+    net/xilinx: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
+index f8e351880119..aad909d793d7 100644
+--- a/drivers/net/ethernet/xilinx/ll_temac_main.c
++++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
+@@ -1002,7 +1002,7 @@ static const struct ethtool_ops temac_ethtool_ops = {
+ 	.get_ts_info = ethtool_op_get_ts_info,
+ };
+ 
+-static int __devinit temac_of_probe(struct platform_device *op)
++static int temac_of_probe(struct platform_device *op)
+ {
+ 	struct device_node *np;
+ 	struct temac_local *lp;
+@@ -1144,7 +1144,7 @@ static int __devinit temac_of_probe(struct platform_device *op)
+ 	return rc;
+ }
+ 
+-static int __devexit temac_of_remove(struct platform_device *op)
++static int temac_of_remove(struct platform_device *op)
+ {
+ 	struct net_device *ndev = dev_get_drvdata(&op->dev);
+ 	struct temac_local *lp = netdev_priv(ndev);
+@@ -1163,7 +1163,7 @@ static int __devexit temac_of_remove(struct platform_device *op)
+ 	return 0;
+ }
+ 
+-static struct of_device_id temac_of_match[] __devinitdata = {
++static struct of_device_id temac_of_match[] = {
+ 	{ .compatible = "xlnx,xps-ll-temac-1.01.b", },
+ 	{ .compatible = "xlnx,xps-ll-temac-2.00.a", },
+ 	{ .compatible = "xlnx,xps-ll-temac-2.02.a", },
+@@ -1174,7 +1174,7 @@ MODULE_DEVICE_TABLE(of, temac_of_match);
+ 
+ static struct platform_driver temac_of_driver = {
+ 	.probe = temac_of_probe,
+-	.remove = __devexit_p(temac_of_remove),
++	.remove = temac_of_remove,
+ 	.driver = {
+ 		.owner = THIS_MODULE,
+ 		.name = "xilinx_temac",
+diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
+index 77cfe5110318..919b983114e9 100644
+--- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c
++++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
+@@ -1107,7 +1107,7 @@ static struct net_device_ops xemaclite_netdev_ops;
+  * Return:	0, if the driver is bound to the Emaclite device, or
+  *		a negative error if there is failure.
+  */
+-static int __devinit xemaclite_of_probe(struct platform_device *ofdev)
++static int xemaclite_of_probe(struct platform_device *ofdev)
+ {
+ 	struct resource r_irq; /* Interrupt resources */
+ 	struct resource r_mem; /* IO mem resources */
+@@ -1229,7 +1229,7 @@ static int __devinit xemaclite_of_probe(struct platform_device *ofdev)
+  *
+  * Return:	0, always.
+  */
+-static int __devexit xemaclite_of_remove(struct platform_device *of_dev)
++static int xemaclite_of_remove(struct platform_device *of_dev)
+ {
+ 	struct device *dev = &of_dev->dev;
+ 	struct net_device *ndev = dev_get_drvdata(dev);
+@@ -1280,7 +1280,7 @@ static struct net_device_ops xemaclite_netdev_ops = {
+ };
+ 
+ /* Match table for OF platform binding */
+-static struct of_device_id xemaclite_of_match[] __devinitdata = {
++static struct of_device_id xemaclite_of_match[] = {
+ 	{ .compatible = "xlnx,opb-ethernetlite-1.01.a", },
+ 	{ .compatible = "xlnx,opb-ethernetlite-1.01.b", },
+ 	{ .compatible = "xlnx,xps-ethernetlite-1.00.a", },
+@@ -1298,7 +1298,7 @@ static struct platform_driver xemaclite_of_driver = {
+ 		.of_match_table = xemaclite_of_match,
+ 	},
+ 	.probe		= xemaclite_of_probe,
+-	.remove		= __devexit_p(xemaclite_of_remove),
++	.remove		= xemaclite_of_remove,
+ };
+ 
+ module_platform_driver(xemaclite_of_driver);

commit 0e1effe39a5973888bed03db3a4998c4b8ba333a
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:24:07 2012 -0500
+
+    net/wiznet: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/wiznet/w5100.c b/drivers/net/ethernet/wiznet/w5100.c
+index 7daf92e56b65..352383890326 100644
+--- a/drivers/net/ethernet/wiznet/w5100.c
++++ b/drivers/net/ethernet/wiznet/w5100.c
+@@ -621,7 +621,7 @@ static const struct net_device_ops w5100_netdev_ops = {
+ 	.ndo_change_mtu		= eth_change_mtu,
+ };
+ 
+-static int __devinit w5100_hw_probe(struct platform_device *pdev)
++static int w5100_hw_probe(struct platform_device *pdev)
+ {
+ 	struct wiznet_platform_data *data = pdev->dev.platform_data;
+ 	struct net_device *ndev = platform_get_drvdata(pdev);
+@@ -696,7 +696,7 @@ static int __devinit w5100_hw_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devinit w5100_probe(struct platform_device *pdev)
++static int w5100_probe(struct platform_device *pdev)
+ {
+ 	struct w5100_priv *priv;
+ 	struct net_device *ndev;
+@@ -739,7 +739,7 @@ static int __devinit w5100_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit w5100_remove(struct platform_device *pdev)
++static int w5100_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *ndev = platform_get_drvdata(pdev);
+ 	struct w5100_priv *priv = netdev_priv(ndev);
+@@ -799,7 +799,7 @@ static struct platform_driver w5100_driver = {
+ 		.pm	= &w5100_pm_ops,
+ 	},
+ 	.probe		= w5100_probe,
+-	.remove		= __devexit_p(w5100_remove),
++	.remove		= w5100_remove,
+ };
+ 
+ module_platform_driver(w5100_driver);
+diff --git a/drivers/net/ethernet/wiznet/w5300.c b/drivers/net/ethernet/wiznet/w5300.c
+index bd9eec676a58..9d1d986f8d40 100644
+--- a/drivers/net/ethernet/wiznet/w5300.c
++++ b/drivers/net/ethernet/wiznet/w5300.c
+@@ -541,7 +541,7 @@ static const struct net_device_ops w5300_netdev_ops = {
+ 	.ndo_change_mtu		= eth_change_mtu,
+ };
+ 
+-static int __devinit w5300_hw_probe(struct platform_device *pdev)
++static int w5300_hw_probe(struct platform_device *pdev)
+ {
+ 	struct wiznet_platform_data *data = pdev->dev.platform_data;
+ 	struct net_device *ndev = platform_get_drvdata(pdev);
+@@ -608,7 +608,7 @@ static int __devinit w5300_hw_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devinit w5300_probe(struct platform_device *pdev)
++static int w5300_probe(struct platform_device *pdev)
+ {
+ 	struct w5300_priv *priv;
+ 	struct net_device *ndev;
+@@ -651,7 +651,7 @@ static int __devinit w5300_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit w5300_remove(struct platform_device *pdev)
++static int w5300_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *ndev = platform_get_drvdata(pdev);
+ 	struct w5300_priv *priv = netdev_priv(ndev);
+@@ -711,7 +711,7 @@ static struct platform_driver w5300_driver = {
+ 		.pm	= &w5300_pm_ops,
+ 	},
+ 	.probe		= w5300_probe,
+-	.remove		= __devexit_p(w5300_remove),
++	.remove		= w5300_remove,
+ };
+ 
+ module_platform_driver(w5300_driver);

commit fe4a57c581f88e81e9274e0750f1a22c8c73cf58
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:24:06 2012 -0500
+
+    net/ps3_gelic_wireless: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
+index 72b775fd49c8..d568af1eb4f4 100644
+--- a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
++++ b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
+@@ -2305,7 +2305,7 @@ static const struct iw_handler_def gelic_wl_wext_handler_def = {
+ 	.get_wireless_stats	= gelic_wl_get_wireless_stats,
+ };
+ 
+-static struct net_device * __devinit gelic_wl_alloc(struct gelic_card *card)
++static struct net_device *gelic_wl_alloc(struct gelic_card *card)
+ {
+ 	struct net_device *netdev;
+ 	struct gelic_port *port;
+@@ -2582,7 +2582,7 @@ static const struct ethtool_ops gelic_wl_ethtool_ops = {
+ 	.get_link	= gelic_wl_get_link,
+ };
+ 
+-static void __devinit gelic_wl_setup_netdev_ops(struct net_device *netdev)
++static void gelic_wl_setup_netdev_ops(struct net_device *netdev)
+ {
+ 	struct gelic_wl_info *wl;
+ 	wl = port_wl(netdev_priv(netdev));
+@@ -2598,7 +2598,7 @@ static void __devinit gelic_wl_setup_netdev_ops(struct net_device *netdev)
+ /*
+  * driver probe/remove
+  */
+-int __devinit gelic_wl_driver_probe(struct gelic_card *card)
++int gelic_wl_driver_probe(struct gelic_card *card)
+ {
+ 	int ret;
+ 	struct net_device *netdev;

commit 671a1435b4e04aa7fadca6e19d39cbc2d0617319
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:24:05 2012 -0500
+
+    net/spider_net: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Ishizaki Kou 
+    Cc: Jens Osterkamp 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/toshiba/spider_net.c b/drivers/net/ethernet/toshiba/spider_net.c
+index c1ebfe9efcb3..f1b91fd7e41c 100644
+--- a/drivers/net/ethernet/toshiba/spider_net.c
++++ b/drivers/net/ethernet/toshiba/spider_net.c
+@@ -2492,7 +2492,7 @@ spider_net_setup_pci_dev(struct pci_dev *pdev)
+  * spider_net_probe initializes pdev and registers a net_device
+  * structure for it. After that, the device can be ifconfig'ed up
+  **/
+-static int __devinit
++static int
+ spider_net_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ 	int err = -EIO;
+@@ -2531,7 +2531,7 @@ spider_net_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+  * spider_net_remove is called to remove the device and unregisters the
+  * net_device
+  **/
+-static void __devexit
++static void
+ spider_net_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *netdev;
+@@ -2559,7 +2559,7 @@ static struct pci_driver spider_net_driver = {
+ 	.name		= spider_net_driver_name,
+ 	.id_table	= spider_net_pci_tbl,
+ 	.probe		= spider_net_probe,
+-	.remove		= __devexit_p(spider_net_remove)
++	.remove		= spider_net_remove
+ };
+ 
+ /**

commit 14d4171de914859ea34cc820d1548c5063b8aaf4
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:24:04 2012 -0500
+
+    net/ps3_gelic_net: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Geoff Levand 
+    Cc: cbe-oss-dev@lists.ozlabs.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.c b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
+index 5ee82a77723b..d7c8af7cca02 100644
+--- a/drivers/net/ethernet/toshiba/ps3_gelic_net.c
++++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
+@@ -234,7 +234,7 @@ static void gelic_card_free_chain(struct gelic_card *card,
+  *
+  * returns 0 on success, <0 on failure
+  */
+-static int __devinit gelic_card_init_chain(struct gelic_card *card,
++static int gelic_card_init_chain(struct gelic_card *card,
+ 					   struct gelic_descr_chain *chain,
+ 					   struct gelic_descr *start_descr,
+ 					   int no)
+@@ -428,7 +428,7 @@ static int gelic_card_fill_rx_chain(struct gelic_card *card)
+  *
+  * returns 0 on success, < 0 on failure
+  */
+-static int __devinit gelic_card_alloc_rx_skbs(struct gelic_card *card)
++static int gelic_card_alloc_rx_skbs(struct gelic_card *card)
+ {
+ 	struct gelic_descr_chain *chain;
+ 	int ret;
+@@ -1468,7 +1468,7 @@ static const struct net_device_ops gelic_netdevice_ops = {
+  *
+  * fills out function pointers in the net_device structure
+  */
+-static void __devinit gelic_ether_setup_netdev_ops(struct net_device *netdev,
++static void gelic_ether_setup_netdev_ops(struct net_device *netdev,
+ 						   struct napi_struct *napi)
+ {
+ 	netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT;
+@@ -1489,7 +1489,7 @@ static void __devinit gelic_ether_setup_netdev_ops(struct net_device *netdev,
+  * gelic_ether_setup_netdev initializes the net_device structure
+  * and register it.
+  **/
+-int __devinit gelic_net_setup_netdev(struct net_device *netdev,
++int gelic_net_setup_netdev(struct net_device *netdev,
+ 				     struct gelic_card *card)
+ {
+ 	int status;
+@@ -1542,7 +1542,7 @@ int __devinit gelic_net_setup_netdev(struct net_device *netdev,
+  * the card and net_device structures are linked to each other
+  */
+ #define GELIC_ALIGN (32)
+-static struct gelic_card * __devinit gelic_alloc_card_net(struct net_device **netdev)
++static struct gelic_card *gelic_alloc_card_net(struct net_device **netdev)
+ {
+ 	struct gelic_card *card;
+ 	struct gelic_port *port;
+@@ -1593,7 +1593,7 @@ static struct gelic_card * __devinit gelic_alloc_card_net(struct net_device **ne
+ 	return card;
+ }
+ 
+-static void __devinit gelic_card_get_vlan_info(struct gelic_card *card)
++static void gelic_card_get_vlan_info(struct gelic_card *card)
+ {
+ 	u64 v1, v2;
+ 	int status;
+@@ -1667,7 +1667,7 @@ static void __devinit gelic_card_get_vlan_info(struct gelic_card *card)
+ /**
+  * ps3_gelic_driver_probe - add a device to the control of this driver
+  */
+-static int __devinit ps3_gelic_driver_probe(struct ps3_system_bus_device *dev)
++static int ps3_gelic_driver_probe(struct ps3_system_bus_device *dev)
+ {
+ 	struct gelic_card *card;
+ 	struct net_device *netdev;

commit e38921d4dd7d2f052c1c2344fac307463c3b8d2d
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:24:03 2012 -0500
+
+    net/davinci_emac: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
+index fce89a0ab06e..2a3e2c56bc60 100644
+--- a/drivers/net/ethernet/ti/davinci_emac.c
++++ b/drivers/net/ethernet/ti/davinci_emac.c
+@@ -1850,7 +1850,7 @@ static struct emac_platform_data
+  * resource information from platform init and register a network device
+  * and allocate resources necessary for driver to perform
+  */
+-static int __devinit davinci_emac_probe(struct platform_device *pdev)
++static int davinci_emac_probe(struct platform_device *pdev)
+ {
+ 	int rc = 0;
+ 	struct resource *res;
+@@ -2039,7 +2039,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
+  * Called when removing the device driver. We disable clock usage and release
+  * the resources taken up by the driver and unregister network device
+  */
+-static int __devexit davinci_emac_remove(struct platform_device *pdev)
++static int davinci_emac_remove(struct platform_device *pdev)
+ {
+ 	struct resource *res;
+ 	struct net_device *ndev = platform_get_drvdata(pdev);
+@@ -2107,7 +2107,7 @@ static struct platform_driver davinci_emac_driver = {
+ 		.of_match_table = of_match_ptr(davinci_emac_of_match),
+ 	},
+ 	.probe = davinci_emac_probe,
+-	.remove = __devexit_p(davinci_emac_remove),
++	.remove = davinci_emac_remove,
+ };
+ 
+ /**
+diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c
+index ae74280c0b9f..cca25509b039 100644
+--- a/drivers/net/ethernet/ti/davinci_mdio.c
++++ b/drivers/net/ethernet/ti/davinci_mdio.c
+@@ -310,7 +310,7 @@ static int davinci_mdio_probe_dt(struct mdio_platform_data *data,
+ }
+ 
+ 
+-static int __devinit davinci_mdio_probe(struct platform_device *pdev)
++static int davinci_mdio_probe(struct platform_device *pdev)
+ {
+ 	struct mdio_platform_data *pdata = pdev->dev.platform_data;
+ 	struct device *dev = &pdev->dev;
+@@ -416,7 +416,7 @@ static int __devinit davinci_mdio_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit davinci_mdio_remove(struct platform_device *pdev)
++static int davinci_mdio_remove(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	struct davinci_mdio_data *data = dev_get_drvdata(dev);
+@@ -496,7 +496,7 @@ static struct platform_driver davinci_mdio_driver = {
+ 		.of_match_table = of_match_ptr(davinci_mdio_of_mtable),
+ 	},
+ 	.probe = davinci_mdio_probe,
+-	.remove = __devexit_p(davinci_mdio_remove),
++	.remove = davinci_mdio_remove,
+ };
+ 
+ static int __init davinci_mdio_init(void)

commit f73d12bd298f9614d8600326e9bd1f7871fcde4b
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:24:02 2012 -0500
+
+    net/sun: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c
+index c8251be104d6..85f971fe2611 100644
+--- a/drivers/net/ethernet/sun/cassini.c
++++ b/drivers/net/ethernet/sun/cassini.c
+@@ -185,7 +185,7 @@
+ #define CAS_RESET_SPARE                 3
+ #endif
+ 
+-static char version[] __devinitdata =
++static char version[] =
+ 	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+ 
+ static int cassini_debug = -1;	/* -1 == use CAS_DEF_MSG_ENABLE as value */
+@@ -222,7 +222,7 @@ static int link_transition_timeout;
+ 
+ 
+ 
+-static u16 link_modes[] __devinitdata = {
++static u16 link_modes[] = {
+ 	BMCR_ANENABLE,			 /* 0 : autoneg */
+ 	0,				 /* 1 : 10bt half duplex */
+ 	BMCR_SPEED100,			 /* 2 : 100bt half duplex */
+@@ -4820,7 +4820,7 @@ static int cas_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+  * only subordinate device and we can tweak the bridge settings to
+  * reflect that fact.
+  */
+-static void __devinit cas_program_bridge(struct pci_dev *cas_pdev)
++static void cas_program_bridge(struct pci_dev *cas_pdev)
+ {
+ 	struct pci_dev *pdev = cas_pdev->bus->self;
+ 	u32 val;
+@@ -4916,7 +4916,7 @@ static const struct net_device_ops cas_netdev_ops = {
+ #endif
+ };
+ 
+-static int __devinit cas_init_one(struct pci_dev *pdev,
++static int cas_init_one(struct pci_dev *pdev,
+ 				  const struct pci_device_id *ent)
+ {
+ 	static int cas_version_printed = 0;
+@@ -5175,7 +5175,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
+ 	return -ENODEV;
+ }
+ 
+-static void __devexit cas_remove_one(struct pci_dev *pdev)
++static void cas_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct cas *cp;
+@@ -5273,7 +5273,7 @@ static struct pci_driver cas_driver = {
+ 	.name		= DRV_MODULE_NAME,
+ 	.id_table	= cas_pci_tbl,
+ 	.probe		= cas_init_one,
+-	.remove		= __devexit_p(cas_remove_one),
++	.remove		= cas_remove_one,
+ #ifdef CONFIG_PM
+ 	.suspend	= cas_suspend,
+ 	.resume		= cas_resume
+diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c
+index 275b430aeb75..6023949be3bd 100644
+--- a/drivers/net/ethernet/sun/niu.c
++++ b/drivers/net/ethernet/sun/niu.c
+@@ -38,7 +38,7 @@
+ #define DRV_MODULE_VERSION	"1.1"
+ #define DRV_MODULE_RELDATE	"Apr 22, 2010"
+ 
+-static char version[] __devinitdata =
++static char version[] =
+ 	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+ 
+ MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
+@@ -7977,7 +7977,7 @@ static int niu_set_ldg_sid(struct niu *np, int ldg, int func, int vector)
+ 	return 0;
+ }
+ 
+-static int __devinit niu_pci_eeprom_read(struct niu *np, u32 addr)
++static int niu_pci_eeprom_read(struct niu *np, u32 addr)
+ {
+ 	u64 frame, frame_base = (ESPC_PIO_STAT_READ_START |
+ 				 (addr << ESPC_PIO_STAT_ADDR_SHIFT));
+@@ -8020,7 +8020,7 @@ static int __devinit niu_pci_eeprom_read(struct niu *np, u32 addr)
+ 	return (frame & ESPC_PIO_STAT_DATA) >> ESPC_PIO_STAT_DATA_SHIFT;
+ }
+ 
+-static int __devinit niu_pci_eeprom_read16(struct niu *np, u32 off)
++static int niu_pci_eeprom_read16(struct niu *np, u32 off)
+ {
+ 	int err = niu_pci_eeprom_read(np, off);
+ 	u16 val;
+@@ -8036,7 +8036,7 @@ static int __devinit niu_pci_eeprom_read16(struct niu *np, u32 off)
+ 	return val;
+ }
+ 
+-static int __devinit niu_pci_eeprom_read16_swp(struct niu *np, u32 off)
++static int niu_pci_eeprom_read16_swp(struct niu *np, u32 off)
+ {
+ 	int err = niu_pci_eeprom_read(np, off);
+ 	u16 val;
+@@ -8054,7 +8054,7 @@ static int __devinit niu_pci_eeprom_read16_swp(struct niu *np, u32 off)
+ 	return val;
+ }
+ 
+-static int __devinit niu_pci_vpd_get_propname(struct niu *np,
++static int niu_pci_vpd_get_propname(struct niu *np,
+ 					      u32 off,
+ 					      char *namebuf,
+ 					      int namebuf_len)
+@@ -8075,7 +8075,7 @@ static int __devinit niu_pci_vpd_get_propname(struct niu *np,
+ 	return i + 1;
+ }
+ 
+-static void __devinit niu_vpd_parse_version(struct niu *np)
++static void niu_vpd_parse_version(struct niu *np)
+ {
+ 	struct niu_vpd *vpd = &np->vpd;
+ 	int len = strlen(vpd->version) + 1;
+@@ -8102,7 +8102,7 @@ static void __devinit niu_vpd_parse_version(struct niu *np)
+ }
+ 
+ /* ESPC_PIO_EN_ENABLE must be set */
+-static int __devinit niu_pci_vpd_scan_props(struct niu *np,
++static int niu_pci_vpd_scan_props(struct niu *np,
+ 					    u32 start, u32 end)
+ {
+ 	unsigned int found_mask = 0;
+@@ -8189,7 +8189,7 @@ static int __devinit niu_pci_vpd_scan_props(struct niu *np,
+ }
+ 
+ /* ESPC_PIO_EN_ENABLE must be set */
+-static void __devinit niu_pci_vpd_fetch(struct niu *np, u32 start)
++static void niu_pci_vpd_fetch(struct niu *np, u32 start)
+ {
+ 	u32 offset;
+ 	int err;
+@@ -8224,7 +8224,7 @@ static void __devinit niu_pci_vpd_fetch(struct niu *np, u32 start)
+ }
+ 
+ /* ESPC_PIO_EN_ENABLE must be set */
+-static u32 __devinit niu_pci_vpd_offset(struct niu *np)
++static u32 niu_pci_vpd_offset(struct niu *np)
+ {
+ 	u32 start = 0, end = ESPC_EEPROM_SIZE, ret;
+ 	int err;
+@@ -8279,7 +8279,7 @@ static u32 __devinit niu_pci_vpd_offset(struct niu *np)
+ 	return 0;
+ }
+ 
+-static int __devinit niu_phy_type_prop_decode(struct niu *np,
++static int niu_phy_type_prop_decode(struct niu *np,
+ 					      const char *phy_prop)
+ {
+ 	if (!strcmp(phy_prop, "mif")) {
+@@ -8334,7 +8334,7 @@ static int niu_pci_vpd_get_nports(struct niu *np)
+ 	return ports;
+ }
+ 
+-static void __devinit niu_pci_vpd_validate(struct niu *np)
++static void niu_pci_vpd_validate(struct niu *np)
+ {
+ 	struct net_device *dev = np->dev;
+ 	struct niu_vpd *vpd = &np->vpd;
+@@ -8380,7 +8380,7 @@ static void __devinit niu_pci_vpd_validate(struct niu *np)
+ 	memcpy(dev->dev_addr, dev->perm_addr, dev->addr_len);
+ }
+ 
+-static int __devinit niu_pci_probe_sprom(struct niu *np)
++static int niu_pci_probe_sprom(struct niu *np)
+ {
+ 	struct net_device *dev = np->dev;
+ 	int len, i;
+@@ -8538,7 +8538,7 @@ static int __devinit niu_pci_probe_sprom(struct niu *np)
+ 	return 0;
+ }
+ 
+-static int __devinit niu_get_and_validate_port(struct niu *np)
++static int niu_get_and_validate_port(struct niu *np)
+ {
+ 	struct niu_parent *parent = np->parent;
+ 
+@@ -8572,7 +8572,7 @@ static int __devinit niu_get_and_validate_port(struct niu *np)
+ 	return 0;
+ }
+ 
+-static int __devinit phy_record(struct niu_parent *parent,
++static int phy_record(struct niu_parent *parent,
+ 				struct phy_probe_info *p,
+ 				int dev_id_1, int dev_id_2, u8 phy_port,
+ 				int type)
+@@ -8611,7 +8611,7 @@ static int __devinit phy_record(struct niu_parent *parent,
+ 	return 0;
+ }
+ 
+-static int __devinit port_has_10g(struct phy_probe_info *p, int port)
++static int port_has_10g(struct phy_probe_info *p, int port)
+ {
+ 	int i;
+ 
+@@ -8627,7 +8627,7 @@ static int __devinit port_has_10g(struct phy_probe_info *p, int port)
+ 	return 0;
+ }
+ 
+-static int __devinit count_10g_ports(struct phy_probe_info *p, int *lowest)
++static int count_10g_ports(struct phy_probe_info *p, int *lowest)
+ {
+ 	int port, cnt;
+ 
+@@ -8644,7 +8644,7 @@ static int __devinit count_10g_ports(struct phy_probe_info *p, int *lowest)
+ 	return cnt;
+ }
+ 
+-static int __devinit count_1g_ports(struct phy_probe_info *p, int *lowest)
++static int count_1g_ports(struct phy_probe_info *p, int *lowest)
+ {
+ 	*lowest = 32;
+ 	if (p->cur[PHY_TYPE_MII])
+@@ -8653,7 +8653,7 @@ static int __devinit count_1g_ports(struct phy_probe_info *p, int *lowest)
+ 	return p->cur[PHY_TYPE_MII];
+ }
+ 
+-static void __devinit niu_n2_divide_channels(struct niu_parent *parent)
++static void niu_n2_divide_channels(struct niu_parent *parent)
+ {
+ 	int num_ports = parent->num_ports;
+ 	int i;
+@@ -8669,7 +8669,7 @@ static void __devinit niu_n2_divide_channels(struct niu_parent *parent)
+ 	}
+ }
+ 
+-static void __devinit niu_divide_channels(struct niu_parent *parent,
++static void niu_divide_channels(struct niu_parent *parent,
+ 					  int num_10g, int num_1g)
+ {
+ 	int num_ports = parent->num_ports;
+@@ -8731,7 +8731,7 @@ static void __devinit niu_divide_channels(struct niu_parent *parent,
+ 	}
+ }
+ 
+-static void __devinit niu_divide_rdc_groups(struct niu_parent *parent,
++static void niu_divide_rdc_groups(struct niu_parent *parent,
+ 					    int num_10g, int num_1g)
+ {
+ 	int i, num_ports = parent->num_ports;
+@@ -8776,7 +8776,7 @@ static void __devinit niu_divide_rdc_groups(struct niu_parent *parent,
+ 	}
+ }
+ 
+-static int __devinit fill_phy_probe_info(struct niu *np,
++static int fill_phy_probe_info(struct niu *np,
+ 					 struct niu_parent *parent,
+ 					 struct phy_probe_info *info)
+ {
+@@ -8819,7 +8819,7 @@ static int __devinit fill_phy_probe_info(struct niu *np,
+ 	return err;
+ }
+ 
+-static int __devinit walk_phys(struct niu *np, struct niu_parent *parent)
++static int walk_phys(struct niu *np, struct niu_parent *parent)
+ {
+ 	struct phy_probe_info *info = &parent->phy_probe_info;
+ 	int lowest_10g, lowest_1g;
+@@ -8948,7 +8948,7 @@ static int __devinit walk_phys(struct niu *np, struct niu_parent *parent)
+ 	return -EINVAL;
+ }
+ 
+-static int __devinit niu_probe_ports(struct niu *np)
++static int niu_probe_ports(struct niu *np)
+ {
+ 	struct niu_parent *parent = np->parent;
+ 	int err, i;
+@@ -8969,7 +8969,7 @@ static int __devinit niu_probe_ports(struct niu *np)
+ 	return 0;
+ }
+ 
+-static int __devinit niu_classifier_swstate_init(struct niu *np)
++static int niu_classifier_swstate_init(struct niu *np)
+ {
+ 	struct niu_classifier *cp = &np->clas;
+ 
+@@ -8981,7 +8981,7 @@ static int __devinit niu_classifier_swstate_init(struct niu *np)
+ 	return fflp_early_init(np);
+ }
+ 
+-static void __devinit niu_link_config_init(struct niu *np)
++static void niu_link_config_init(struct niu *np)
+ {
+ 	struct niu_link_config *lp = &np->link_config;
+ 
+@@ -9006,7 +9006,7 @@ static void __devinit niu_link_config_init(struct niu *np)
+ #endif
+ }
+ 
+-static int __devinit niu_init_mac_ipp_pcs_base(struct niu *np)
++static int niu_init_mac_ipp_pcs_base(struct niu *np)
+ {
+ 	switch (np->port) {
+ 	case 0:
+@@ -9045,7 +9045,7 @@ static int __devinit niu_init_mac_ipp_pcs_base(struct niu *np)
+ 	return 0;
+ }
+ 
+-static void __devinit niu_try_msix(struct niu *np, u8 *ldg_num_map)
++static void niu_try_msix(struct niu *np, u8 *ldg_num_map)
+ {
+ 	struct msix_entry msi_vec[NIU_NUM_LDG];
+ 	struct niu_parent *parent = np->parent;
+@@ -9084,7 +9084,7 @@ static void __devinit niu_try_msix(struct niu *np, u8 *ldg_num_map)
+ 	np->num_ldg = num_irqs;
+ }
+ 
+-static int __devinit niu_n2_irq_init(struct niu *np, u8 *ldg_num_map)
++static int niu_n2_irq_init(struct niu *np, u8 *ldg_num_map)
+ {
+ #ifdef CONFIG_SPARC64
+ 	struct platform_device *op = np->op;
+@@ -9108,7 +9108,7 @@ static int __devinit niu_n2_irq_init(struct niu *np, u8 *ldg_num_map)
+ #endif
+ }
+ 
+-static int __devinit niu_ldg_init(struct niu *np)
++static int niu_ldg_init(struct niu *np)
+ {
+ 	struct niu_parent *parent = np->parent;
+ 	u8 ldg_num_map[NIU_NUM_LDG];
+@@ -9225,13 +9225,13 @@ static int __devinit niu_ldg_init(struct niu *np)
+ 	return 0;
+ }
+ 
+-static void __devexit niu_ldg_free(struct niu *np)
++static void niu_ldg_free(struct niu *np)
+ {
+ 	if (np->flags & NIU_FLAGS_MSIX)
+ 		pci_disable_msix(np->pdev);
+ }
+ 
+-static int __devinit niu_get_of_props(struct niu *np)
++static int niu_get_of_props(struct niu *np)
+ {
+ #ifdef CONFIG_SPARC64
+ 	struct net_device *dev = np->dev;
+@@ -9300,7 +9300,7 @@ static int __devinit niu_get_of_props(struct niu *np)
+ #endif
+ }
+ 
+-static int __devinit niu_get_invariants(struct niu *np)
++static int niu_get_invariants(struct niu *np)
+ {
+ 	int err, have_props;
+ 	u32 offset;
+@@ -9479,7 +9479,7 @@ static struct device_attribute niu_parent_attributes[] = {
+ 	{}
+ };
+ 
+-static struct niu_parent * __devinit niu_new_parent(struct niu *np,
++static struct niu_parent *niu_new_parent(struct niu *np,
+ 						    union niu_parent_id *id,
+ 						    u8 ptype)
+ {
+@@ -9544,7 +9544,7 @@ static struct niu_parent * __devinit niu_new_parent(struct niu *np,
+ 	return NULL;
+ }
+ 
+-static struct niu_parent * __devinit niu_get_parent(struct niu *np,
++static struct niu_parent *niu_get_parent(struct niu *np,
+ 						    union niu_parent_id *id,
+ 						    u8 ptype)
+ {
+@@ -9662,7 +9662,7 @@ static const struct niu_ops niu_pci_ops = {
+ 	.unmap_single	= niu_pci_unmap_single,
+ };
+ 
+-static void __devinit niu_driver_version(void)
++static void niu_driver_version(void)
+ {
+ 	static int niu_version_printed;
+ 
+@@ -9670,7 +9670,7 @@ static void __devinit niu_driver_version(void)
+ 		pr_info("%s", version);
+ }
+ 
+-static struct net_device * __devinit niu_alloc_and_init(
++static struct net_device *niu_alloc_and_init(
+ 	struct device *gen_dev, struct pci_dev *pdev,
+ 	struct platform_device *op, const struct niu_ops *ops,
+ 	u8 port)
+@@ -9714,14 +9714,14 @@ static const struct net_device_ops niu_netdev_ops = {
+ 	.ndo_change_mtu		= niu_change_mtu,
+ };
+ 
+-static void __devinit niu_assign_netdev_ops(struct net_device *dev)
++static void niu_assign_netdev_ops(struct net_device *dev)
+ {
+ 	dev->netdev_ops = &niu_netdev_ops;
+ 	dev->ethtool_ops = &niu_ethtool_ops;
+ 	dev->watchdog_timeo = NIU_TX_TIMEOUT;
+ }
+ 
+-static void __devinit niu_device_announce(struct niu *np)
++static void niu_device_announce(struct niu *np)
+ {
+ 	struct net_device *dev = np->dev;
+ 
+@@ -9750,13 +9750,13 @@ static void __devinit niu_device_announce(struct niu *np)
+ 	}
+ }
+ 
+-static void __devinit niu_set_basic_features(struct net_device *dev)
++static void niu_set_basic_features(struct net_device *dev)
+ {
+ 	dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXHASH;
+ 	dev->features |= dev->hw_features | NETIF_F_RXCSUM;
+ }
+ 
+-static int __devinit niu_pci_init_one(struct pci_dev *pdev,
++static int niu_pci_init_one(struct pci_dev *pdev,
+ 				      const struct pci_device_id *ent)
+ {
+ 	union niu_parent_id parent_id;
+@@ -9895,7 +9895,7 @@ static int __devinit niu_pci_init_one(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit niu_pci_remove_one(struct pci_dev *pdev)
++static void niu_pci_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 
+@@ -9980,7 +9980,7 @@ static struct pci_driver niu_pci_driver = {
+ 	.name		= DRV_MODULE_NAME,
+ 	.id_table	= niu_pci_tbl,
+ 	.probe		= niu_pci_init_one,
+-	.remove		= __devexit_p(niu_pci_remove_one),
++	.remove		= niu_pci_remove_one,
+ 	.suspend	= niu_suspend,
+ 	.resume		= niu_resume,
+ };
+@@ -10044,7 +10044,7 @@ static const struct niu_ops niu_phys_ops = {
+ 	.unmap_single	= niu_phys_unmap_single,
+ };
+ 
+-static int __devinit niu_of_probe(struct platform_device *op)
++static int niu_of_probe(struct platform_device *op)
+ {
+ 	union niu_parent_id parent_id;
+ 	struct net_device *dev;
+@@ -10158,7 +10158,7 @@ static int __devinit niu_of_probe(struct platform_device *op)
+ 	return err;
+ }
+ 
+-static int __devexit niu_of_remove(struct platform_device *op)
++static int niu_of_remove(struct platform_device *op)
+ {
+ 	struct net_device *dev = dev_get_drvdata(&op->dev);
+ 
+@@ -10211,7 +10211,7 @@ static struct platform_driver niu_of_driver = {
+ 		.of_match_table = niu_match,
+ 	},
+ 	.probe		= niu_of_probe,
+-	.remove		= __devexit_p(niu_of_remove),
++	.remove		= niu_of_remove,
+ };
+ 
+ #endif /* CONFIG_SPARC64 */
+diff --git a/drivers/net/ethernet/sun/sunbmac.c b/drivers/net/ethernet/sun/sunbmac.c
+index c9c977bf02ac..8fda91009226 100644
+--- a/drivers/net/ethernet/sun/sunbmac.c
++++ b/drivers/net/ethernet/sun/sunbmac.c
+@@ -1074,7 +1074,7 @@ static const struct net_device_ops bigmac_ops = {
+ 	.ndo_validate_addr	= eth_validate_addr,
+ };
+ 
+-static int __devinit bigmac_ether_init(struct platform_device *op,
++static int bigmac_ether_init(struct platform_device *op,
+ 				       struct platform_device *qec_op)
+ {
+ 	static int version_printed;
+@@ -1233,7 +1233,7 @@ static int __devinit bigmac_ether_init(struct platform_device *op,
+ /* QEC can be the parent of either QuadEthernet or a BigMAC.  We want
+  * the latter.
+  */
+-static int __devinit bigmac_sbus_probe(struct platform_device *op)
++static int bigmac_sbus_probe(struct platform_device *op)
+ {
+ 	struct device *parent = op->dev.parent;
+ 	struct platform_device *qec_op;
+@@ -1243,7 +1243,7 @@ static int __devinit bigmac_sbus_probe(struct platform_device *op)
+ 	return bigmac_ether_init(op, qec_op);
+ }
+ 
+-static int __devexit bigmac_sbus_remove(struct platform_device *op)
++static int bigmac_sbus_remove(struct platform_device *op)
+ {
+ 	struct bigmac *bp = dev_get_drvdata(&op->dev);
+ 	struct device *parent = op->dev.parent;
+@@ -1286,7 +1286,7 @@ static struct platform_driver bigmac_sbus_driver = {
+ 		.of_match_table = bigmac_sbus_match,
+ 	},
+ 	.probe		= bigmac_sbus_probe,
+-	.remove		= __devexit_p(bigmac_sbus_remove),
++	.remove		= bigmac_sbus_remove,
+ };
+ 
+ module_platform_driver(bigmac_sbus_driver);
+diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c
+index 6c8695ec7cb9..c7bc0561b8eb 100644
+--- a/drivers/net/ethernet/sun/sungem.c
++++ b/drivers/net/ethernet/sun/sungem.c
+@@ -77,7 +77,7 @@
+ #define DRV_VERSION	"1.0"
+ #define DRV_AUTHOR	"David S. Miller "
+ 
+-static char version[] __devinitdata =
++static char version[] =
+         DRV_NAME ".c:v" DRV_VERSION " " DRV_AUTHOR "\n";
+ 
+ MODULE_AUTHOR(DRV_AUTHOR);
+@@ -2763,7 +2763,7 @@ static void get_gem_mac_nonobp(struct pci_dev *pdev, unsigned char *dev_addr)
+ }
+ #endif /* not Sparc and not PPC */
+ 
+-static int __devinit gem_get_device_address(struct gem *gp)
++static int gem_get_device_address(struct gem *gp)
+ {
+ #if defined(CONFIG_SPARC) || defined(CONFIG_PPC_PMAC)
+ 	struct net_device *dev = gp->dev;
+@@ -2827,7 +2827,7 @@ static const struct net_device_ops gem_netdev_ops = {
+ #endif
+ };
+ 
+-static int __devinit gem_init_one(struct pci_dev *pdev,
++static int gem_init_one(struct pci_dev *pdev,
+ 				  const struct pci_device_id *ent)
+ {
+ 	unsigned long gemreg_base, gemreg_len;
+diff --git a/drivers/net/ethernet/sun/sunhme.c b/drivers/net/ethernet/sun/sunhme.c
+index 73f341b8befb..43babc33a2c9 100644
+--- a/drivers/net/ethernet/sun/sunhme.c
++++ b/drivers/net/ethernet/sun/sunhme.c
+@@ -2499,7 +2499,7 @@ static int hme_version_printed;
+  *
+  * Return NULL on failure.
+  */
+-static struct quattro * __devinit quattro_sbus_find(struct platform_device *child)
++static struct quattro *quattro_sbus_find(struct platform_device *child)
+ {
+ 	struct device *parent = child->dev.parent;
+ 	struct platform_device *op;
+@@ -2580,7 +2580,7 @@ static void quattro_sbus_free_irqs(void)
+ #endif /* CONFIG_SBUS */
+ 
+ #ifdef CONFIG_PCI
+-static struct quattro * __devinit quattro_pci_find(struct pci_dev *pdev)
++static struct quattro *quattro_pci_find(struct pci_dev *pdev)
+ {
+ 	struct pci_dev *bdev = pdev->bus->self;
+ 	struct quattro *qp;
+@@ -2623,7 +2623,7 @@ static const struct net_device_ops hme_netdev_ops = {
+ };
+ 
+ #ifdef CONFIG_SBUS
+-static int __devinit happy_meal_sbus_probe_one(struct platform_device *op, int is_qfe)
++static int happy_meal_sbus_probe_one(struct platform_device *op, int is_qfe)
+ {
+ 	struct device_node *dp = op->dev.of_node, *sbus_dp;
+ 	struct quattro *qp = NULL;
+@@ -2927,7 +2927,7 @@ static void get_hme_mac_nonsparc(struct pci_dev *pdev, unsigned char *dev_addr)
+ }
+ #endif /* !(CONFIG_SPARC) */
+ 
+-static int __devinit happy_meal_pci_probe(struct pci_dev *pdev,
++static int happy_meal_pci_probe(struct pci_dev *pdev,
+ 					  const struct pci_device_id *ent)
+ {
+ 	struct quattro *qp = NULL;
+@@ -3162,7 +3162,7 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit happy_meal_pci_remove(struct pci_dev *pdev)
++static void happy_meal_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct happy_meal *hp = dev_get_drvdata(&pdev->dev);
+ 	struct net_device *net_dev = hp->dev;
+@@ -3190,7 +3190,7 @@ static struct pci_driver hme_pci_driver = {
+ 	.name		= "hme",
+ 	.id_table	= happymeal_pci_ids,
+ 	.probe		= happy_meal_pci_probe,
+-	.remove		= __devexit_p(happy_meal_pci_remove),
++	.remove		= happy_meal_pci_remove,
+ };
+ 
+ static int __init happy_meal_pci_init(void)
+@@ -3216,7 +3216,7 @@ static void happy_meal_pci_exit(void)
+ 
+ #ifdef CONFIG_SBUS
+ static const struct of_device_id hme_sbus_match[];
+-static int __devinit hme_sbus_probe(struct platform_device *op)
++static int hme_sbus_probe(struct platform_device *op)
+ {
+ 	const struct of_device_id *match;
+ 	struct device_node *dp = op->dev.of_node;
+@@ -3234,7 +3234,7 @@ static int __devinit hme_sbus_probe(struct platform_device *op)
+ 	return happy_meal_sbus_probe_one(op, is_qfe);
+ }
+ 
+-static int __devexit hme_sbus_remove(struct platform_device *op)
++static int hme_sbus_remove(struct platform_device *op)
+ {
+ 	struct happy_meal *hp = dev_get_drvdata(&op->dev);
+ 	struct net_device *net_dev = hp->dev;
+@@ -3284,7 +3284,7 @@ static struct platform_driver hme_sbus_driver = {
+ 		.of_match_table = hme_sbus_match,
+ 	},
+ 	.probe		= hme_sbus_probe,
+-	.remove		= __devexit_p(hme_sbus_remove),
++	.remove		= hme_sbus_remove,
+ };
+ 
+ static int __init happy_meal_sbus_init(void)
+diff --git a/drivers/net/ethernet/sun/sunqe.c b/drivers/net/ethernet/sun/sunqe.c
+index aeded7ff1c8f..1dcee6915843 100644
+--- a/drivers/net/ethernet/sun/sunqe.c
++++ b/drivers/net/ethernet/sun/sunqe.c
+@@ -744,7 +744,7 @@ static void qec_init_once(struct sunqec *qecp, struct platform_device *op)
+ 		    qecp->gregs + GLOB_RSIZE);
+ }
+ 
+-static u8 __devinit qec_get_burst(struct device_node *dp)
++static u8 qec_get_burst(struct device_node *dp)
+ {
+ 	u8 bsizes, bsizes_more;
+ 
+@@ -764,7 +764,7 @@ static u8 __devinit qec_get_burst(struct device_node *dp)
+ 	return bsizes;
+ }
+ 
+-static struct sunqec * __devinit get_qec(struct platform_device *child)
++static struct sunqec *get_qec(struct platform_device *child)
+ {
+ 	struct platform_device *op = to_platform_device(child->dev.parent);
+ 	struct sunqec *qecp;
+@@ -830,7 +830,7 @@ static const struct net_device_ops qec_ops = {
+ 	.ndo_validate_addr	= eth_validate_addr,
+ };
+ 
+-static int __devinit qec_ether_init(struct platform_device *op)
++static int qec_ether_init(struct platform_device *op)
+ {
+ 	static unsigned version_printed;
+ 	struct net_device *dev;
+@@ -929,12 +929,12 @@ static int __devinit qec_ether_init(struct platform_device *op)
+ 	return res;
+ }
+ 
+-static int __devinit qec_sbus_probe(struct platform_device *op)
++static int qec_sbus_probe(struct platform_device *op)
+ {
+ 	return qec_ether_init(op);
+ }
+ 
+-static int __devexit qec_sbus_remove(struct platform_device *op)
++static int qec_sbus_remove(struct platform_device *op)
+ {
+ 	struct sunqe *qp = dev_get_drvdata(&op->dev);
+ 	struct net_device *net_dev = qp->dev;
+@@ -971,7 +971,7 @@ static struct platform_driver qec_sbus_driver = {
+ 		.of_match_table = qec_sbus_match,
+ 	},
+ 	.probe		= qec_sbus_probe,
+-	.remove		= __devexit_p(qec_sbus_remove),
++	.remove		= qec_sbus_remove,
+ };
+ 
+ static int __init qec_init(void)
+diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c
+index a108db35924e..2852b7099eee 100644
+--- a/drivers/net/ethernet/sun/sunvnet.c
++++ b/drivers/net/ethernet/sun/sunvnet.c
+@@ -25,7 +25,7 @@
+ #define DRV_MODULE_VERSION	"1.0"
+ #define DRV_MODULE_RELDATE	"June 25, 2007"
+ 
+-static char version[] __devinitdata =
++static char version[] =
+ 	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+ MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
+ MODULE_DESCRIPTION("Sun LDOM virtual network driver");
+@@ -937,7 +937,7 @@ static void vnet_port_free_tx_bufs(struct vnet_port *port)
+ 	}
+ }
+ 
+-static int __devinit vnet_port_alloc_tx_bufs(struct vnet_port *port)
++static int vnet_port_alloc_tx_bufs(struct vnet_port *port)
+ {
+ 	struct vio_dring_state *dr;
+ 	unsigned long len;
+@@ -1019,7 +1019,7 @@ static const struct net_device_ops vnet_ops = {
+ 	.ndo_start_xmit		= vnet_start_xmit,
+ };
+ 
+-static struct vnet * __devinit vnet_new(const u64 *local_mac)
++static struct vnet *vnet_new(const u64 *local_mac)
+ {
+ 	struct net_device *dev;
+ 	struct vnet *vp;
+@@ -1067,7 +1067,7 @@ static struct vnet * __devinit vnet_new(const u64 *local_mac)
+ 	return ERR_PTR(err);
+ }
+ 
+-static struct vnet * __devinit vnet_find_or_create(const u64 *local_mac)
++static struct vnet *vnet_find_or_create(const u64 *local_mac)
+ {
+ 	struct vnet *iter, *vp;
+ 
+@@ -1088,7 +1088,7 @@ static struct vnet * __devinit vnet_find_or_create(const u64 *local_mac)
+ 
+ static const char *local_mac_prop = "local-mac-address";
+ 
+-static struct vnet * __devinit vnet_find_parent(struct mdesc_handle *hp,
++static struct vnet *vnet_find_parent(struct mdesc_handle *hp,
+ 						u64 port_node)
+ {
+ 	const u64 *local_mac = NULL;
+@@ -1125,14 +1125,14 @@ static struct vio_driver_ops vnet_vio_ops = {
+ 	.handshake_complete	= vnet_handshake_complete,
+ };
+ 
+-static void __devinit print_version(void)
++static void print_version(void)
+ {
+ 	printk_once(KERN_INFO "%s", version);
+ }
+ 
+ const char *remote_macaddr_prop = "remote-mac-address";
+ 
+-static int __devinit vnet_port_probe(struct vio_dev *vdev,
++static int vnet_port_probe(struct vio_dev *vdev,
+ 				     const struct vio_device_id *id)
+ {
+ 	struct mdesc_handle *hp;

commit f48a3c2af87960e3d497b518a3253337a18016db
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:24:01 2012 -0500
+
+    net/sgi: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c
+index 3e5519a0acc7..4b1deec9189a 100644
+--- a/drivers/net/ethernet/sgi/ioc3-eth.c
++++ b/drivers/net/ethernet/sgi/ioc3-eth.c
+@@ -1143,7 +1143,7 @@ static int ioc3_is_menet(struct pci_dev *pdev)
+  * Can't use UPF_IOREMAP as the whole of IOC3 resources have already been
+  * registered.
+  */
+-static void __devinit ioc3_8250_register(struct ioc3_uartregs __iomem *uart)
++static void ioc3_8250_register(struct ioc3_uartregs __iomem *uart)
+ {
+ #define COSMISC_CONSTANT 6
+ 
+@@ -1169,7 +1169,7 @@ static void __devinit ioc3_8250_register(struct ioc3_uartregs __iomem *uart)
+ 	serial8250_register_8250_port(&port);
+ }
+ 
+-static void __devinit ioc3_serial_probe(struct pci_dev *pdev, struct ioc3 *ioc3)
++static void ioc3_serial_probe(struct pci_dev *pdev, struct ioc3 *ioc3)
+ {
+ 	/*
+ 	 * We need to recognice and treat the fourth MENET serial as it
+@@ -1229,7 +1229,7 @@ static const struct net_device_ops ioc3_netdev_ops = {
+ 	.ndo_change_mtu		= eth_change_mtu,
+ };
+ 
+-static int __devinit ioc3_probe(struct pci_dev *pdev,
++static int ioc3_probe(struct pci_dev *pdev,
+ 	const struct pci_device_id *ent)
+ {
+ 	unsigned int sw_physid1, sw_physid2;
+@@ -1368,7 +1368,7 @@ static int __devinit ioc3_probe(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit ioc3_remove_one (struct pci_dev *pdev)
++static void ioc3_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct ioc3_private *ip = netdev_priv(dev);
+@@ -1396,7 +1396,7 @@ static struct pci_driver ioc3_driver = {
+ 	.name		= "ioc3-eth",
+ 	.id_table	= ioc3_pci_tbl,
+ 	.probe		= ioc3_probe,
+-	.remove		= __devexit_p(ioc3_remove_one),
++	.remove		= ioc3_remove_one,
+ };
+ 
+ static int __init ioc3_init_module(void)
+diff --git a/drivers/net/ethernet/sgi/meth.c b/drivers/net/ethernet/sgi/meth.c
+index 53efe7c7b1c0..79ad9c94a21b 100644
+--- a/drivers/net/ethernet/sgi/meth.c
++++ b/drivers/net/ethernet/sgi/meth.c
+@@ -825,7 +825,7 @@ static const struct net_device_ops meth_netdev_ops = {
+ /*
+  * The init function.
+  */
+-static int __devinit meth_probe(struct platform_device *pdev)
++static int meth_probe(struct platform_device *pdev)
+ {
+ 	struct net_device *dev;
+ 	struct meth_private *priv;

commit 03c4d832a2a752120d18567c27812d53ab176e6e
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:24:00 2012 -0500
+
+    net/pasemi: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Olof Johansson 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c
+index 6fa74d530e44..0be5844d6372 100644
+--- a/drivers/net/ethernet/pasemi/pasemi_mac.c
++++ b/drivers/net/ethernet/pasemi/pasemi_mac.c
+@@ -1727,7 +1727,7 @@ static const struct net_device_ops pasemi_netdev_ops = {
+ #endif
+ };
+ 
+-static int __devinit
++static int
+ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ 	struct net_device *dev;
+@@ -1849,7 +1849,7 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 
+ }
+ 
+-static void __devexit pasemi_mac_remove(struct pci_dev *pdev)
++static void pasemi_mac_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *netdev = pci_get_drvdata(pdev);
+ 	struct pasemi_mac *mac;
+@@ -1884,7 +1884,7 @@ static struct pci_driver pasemi_mac_driver = {
+ 	.name		= "pasemi_mac",
+ 	.id_table	= pasemi_mac_pci_tbl,
+ 	.probe		= pasemi_mac_probe,
+-	.remove		= __devexit_p(pasemi_mac_remove),
++	.remove		= pasemi_mac_remove,
+ };
+ 
+ static void __exit pasemi_mac_cleanup_module(void)

commit 654b8c5ce3b32403a915dfd41d92ad3118c3406e
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:59 2012 -0500
+
+    net/micrel: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/micrel/ks8695net.c b/drivers/net/ethernet/micrel/ks8695net.c
+index e62c31234cfa..07a6ebc47c92 100644
+--- a/drivers/net/ethernet/micrel/ks8695net.c
++++ b/drivers/net/ethernet/micrel/ks8695net.c
+@@ -1274,7 +1274,7 @@ ks8695_open(struct net_device *ndev)
+  *	This initialises the LAN switch in the KS8695 to a known-good
+  *	set of defaults.
+  */
+-static void __devinit
++static void
+ ks8695_init_switch(struct ks8695_priv *ksp)
+ {
+ 	u32 ctrl;
+@@ -1302,7 +1302,7 @@ ks8695_init_switch(struct ks8695_priv *ksp)
+  *	This initialises a KS8695's WAN phy to sensible values for
+  *	autonegotiation etc.
+  */
+-static void __devinit
++static void
+ ks8695_init_wan_phy(struct ks8695_priv *ksp)
+ {
+ 	u32 ctrl;
+@@ -1346,7 +1346,7 @@ static const struct net_device_ops ks8695_netdev_ops = {
+  *	wan ports, and an IORESOURCE_IRQ for the link IRQ for the wan
+  *	port.
+  */
+-static int __devinit
++static int
+ ks8695_probe(struct platform_device *pdev)
+ {
+ 	struct ks8695_priv *ksp;
+@@ -1594,7 +1594,7 @@ ks8695_drv_resume(struct platform_device *pdev)
+  *
+  *	This unregisters and releases a KS8695 ethernet device.
+  */
+-static int __devexit
++static int
+ ks8695_drv_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *ndev = platform_get_drvdata(pdev);
+@@ -1617,7 +1617,7 @@ static struct platform_driver ks8695_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= ks8695_probe,
+-	.remove		= __devexit_p(ks8695_drv_remove),
++	.remove		= ks8695_drv_remove,
+ 	.suspend	= ks8695_drv_suspend,
+ 	.resume		= ks8695_drv_resume,
+ };
+diff --git a/drivers/net/ethernet/micrel/ks8842.c b/drivers/net/ethernet/micrel/ks8842.c
+index 24fb049ac2f2..b71eb39ab448 100644
+--- a/drivers/net/ethernet/micrel/ks8842.c
++++ b/drivers/net/ethernet/micrel/ks8842.c
+@@ -1141,7 +1141,7 @@ static const struct ethtool_ops ks8842_ethtool_ops = {
+ 	.get_link		= ethtool_op_get_link,
+ };
+ 
+-static int __devinit ks8842_probe(struct platform_device *pdev)
++static int ks8842_probe(struct platform_device *pdev)
+ {
+ 	int err = -ENOMEM;
+ 	struct resource *iomem;
+@@ -1240,7 +1240,7 @@ static int __devinit ks8842_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit ks8842_remove(struct platform_device *pdev)
++static int ks8842_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *netdev = platform_get_drvdata(pdev);
+ 	struct ks8842_adapter *adapter = netdev_priv(netdev);
+@@ -1262,7 +1262,7 @@ static struct platform_driver ks8842_platform_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= ks8842_probe,
+-	.remove		= __devexit_p(ks8842_remove),
++	.remove		= ks8842_remove,
+ };
+ 
+ module_platform_driver(ks8842_platform_driver);
+diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c
+index 1540ebeb8669..286816a4e783 100644
+--- a/drivers/net/ethernet/micrel/ks8851.c
++++ b/drivers/net/ethernet/micrel/ks8851.c
+@@ -1415,7 +1415,7 @@ static int ks8851_resume(struct spi_device *spi)
+ #define ks8851_resume NULL
+ #endif
+ 
+-static int __devinit ks8851_probe(struct spi_device *spi)
++static int ks8851_probe(struct spi_device *spi)
+ {
+ 	struct net_device *ndev;
+ 	struct ks8851_net *ks;
+@@ -1534,7 +1534,7 @@ static int __devinit ks8851_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit ks8851_remove(struct spi_device *spi)
++static int ks8851_remove(struct spi_device *spi)
+ {
+ 	struct ks8851_net *priv = dev_get_drvdata(&spi->dev);
+ 
+@@ -1554,7 +1554,7 @@ static struct spi_driver ks8851_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = ks8851_probe,
+-	.remove = __devexit_p(ks8851_remove),
++	.remove = ks8851_remove,
+ 	.suspend = ks8851_suspend,
+ 	.resume = ks8851_resume,
+ };
+diff --git a/drivers/net/ethernet/micrel/ks8851_mll.c b/drivers/net/ethernet/micrel/ks8851_mll.c
+index 38529edfe350..ef8f9f92e547 100644
+--- a/drivers/net/ethernet/micrel/ks8851_mll.c
++++ b/drivers/net/ethernet/micrel/ks8851_mll.c
+@@ -1506,7 +1506,7 @@ static int ks_hw_init(struct ks_net *ks)
+ }
+ 
+ 
+-static int __devinit ks8851_probe(struct platform_device *pdev)
++static int ks8851_probe(struct platform_device *pdev)
+ {
+ 	int err = -ENOMEM;
+ 	struct resource *io_d, *io_c;
+@@ -1641,7 +1641,7 @@ static int __devinit ks8851_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit ks8851_remove(struct platform_device *pdev)
++static int ks8851_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *netdev = platform_get_drvdata(pdev);
+ 	struct ks_net *ks = netdev_priv(netdev);
+@@ -1663,7 +1663,7 @@ static struct platform_driver ks8851_platform_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = ks8851_probe,
+-	.remove = __devexit_p(ks8851_remove),
++	.remove = ks8851_remove,
+ };
+ 
+ module_platform_driver(ks8851_platform_driver);
+diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c
+index d16ef24e622f..f3f09b18a707 100644
+--- a/drivers/net/ethernet/micrel/ksz884x.c
++++ b/drivers/net/ethernet/micrel/ksz884x.c
+@@ -1487,7 +1487,7 @@ struct dev_priv {
+ #define DRV_VERSION		"1.0.0"
+ #define DRV_RELDATE		"Feb 8, 2010"
+ 
+-static char version[] __devinitdata =
++static char version[] =
+ 	"Micrel " DEVICE_NAME " " DRV_VERSION " (" DRV_RELDATE ")";
+ 
+ static u8 DEFAULT_MAC_ADDRESS[] = { 0x00, 0x10, 0xA1, 0x88, 0x42, 0x01 };
+@@ -6919,7 +6919,7 @@ static void read_other_addr(struct ksz_hw *hw)
+ #define PCI_VENDOR_ID_MICREL_KS		0x16c6
+ #endif
+ 
+-static int __devinit pcidev_init(struct pci_dev *pdev,
++static int pcidev_init(struct pci_dev *pdev,
+ 	const struct pci_device_id *id)
+ {
+ 	struct net_device *dev;

commit 33897cc869eef8b878b2408f77b7b0387e43e74e
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:58 2012 -0500
+
+    net/freescale: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
+index 2665162ff4e5..0704bcab178a 100644
+--- a/drivers/net/ethernet/freescale/fec.c
++++ b/drivers/net/ethernet/freescale/fec.c
+@@ -1484,7 +1484,7 @@ static int fec_enet_init(struct net_device *ndev)
+ }
+ 
+ #ifdef CONFIG_OF
+-static int __devinit fec_get_phy_mode_dt(struct platform_device *pdev)
++static int fec_get_phy_mode_dt(struct platform_device *pdev)
+ {
+ 	struct device_node *np = pdev->dev.of_node;
+ 
+@@ -1494,7 +1494,7 @@ static int __devinit fec_get_phy_mode_dt(struct platform_device *pdev)
+ 	return -ENODEV;
+ }
+ 
+-static void __devinit fec_reset_phy(struct platform_device *pdev)
++static void fec_reset_phy(struct platform_device *pdev)
+ {
+ 	int err, phy_reset;
+ 	int msec = 1;
+@@ -1533,7 +1533,7 @@ static inline void fec_reset_phy(struct platform_device *pdev)
+ }
+ #endif /* CONFIG_OF */
+ 
+-static int __devinit
++static int
+ fec_probe(struct platform_device *pdev)
+ {
+ 	struct fec_enet_private *fep;
+@@ -1701,7 +1701,7 @@ fec_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit
++static int
+ fec_drv_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *ndev = platform_get_drvdata(pdev);
+@@ -1790,7 +1790,7 @@ static struct platform_driver fec_driver = {
+ 	},
+ 	.id_table = fec_devtype,
+ 	.probe	= fec_probe,
+-	.remove	= __devexit_p(fec_drv_remove),
++	.remove	= fec_drv_remove,
+ };
+ 
+ module_platform_driver(fec_driver);
+diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c
+index 2933d08b036e..817d081d2cd8 100644
+--- a/drivers/net/ethernet/freescale/fec_mpc52xx.c
++++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c
+@@ -845,7 +845,7 @@ static const struct net_device_ops mpc52xx_fec_netdev_ops = {
+ /* OF Driver                                                                */
+ /* ======================================================================== */
+ 
+-static int __devinit mpc52xx_fec_probe(struct platform_device *op)
++static int mpc52xx_fec_probe(struct platform_device *op)
+ {
+ 	int rv;
+ 	struct net_device *ndev;
+diff --git a/drivers/net/ethernet/freescale/xgmac_mdio.c b/drivers/net/ethernet/freescale/xgmac_mdio.c
+index 1afb5ea2a984..418068b941b1 100644
+--- a/drivers/net/ethernet/freescale/xgmac_mdio.c
++++ b/drivers/net/ethernet/freescale/xgmac_mdio.c
+@@ -189,7 +189,7 @@ static int xgmac_mdio_reset(struct mii_bus *bus)
+ 	return ret;
+ }
+ 
+-static int __devinit xgmac_mdio_probe(struct platform_device *pdev)
++static int xgmac_mdio_probe(struct platform_device *pdev)
+ {
+ 	struct device_node *np = pdev->dev.of_node;
+ 	struct mii_bus *bus;
+@@ -240,7 +240,7 @@ static int __devinit xgmac_mdio_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit xgmac_mdio_remove(struct platform_device *pdev)
++static int xgmac_mdio_remove(struct platform_device *pdev)
+ {
+ 	struct mii_bus *bus = dev_get_drvdata(&pdev->dev);
+ 

commit 37a5b3d5315ab8c354ec147e26b3870dd5c93813
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:57 2012 -0500
+
+    net/cadence: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Nicolas Ferre 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/cadence/at91_ether.c b/drivers/net/ethernet/cadence/at91_ether.c
+index 716cc014a56e..3becdb2deb46 100644
+--- a/drivers/net/ethernet/cadence/at91_ether.c
++++ b/drivers/net/ethernet/cadence/at91_ether.c
+@@ -456,7 +456,7 @@ static int __init at91ether_probe(struct platform_device *pdev)
+ 	return res;
+ }
+ 
+-static int __devexit at91ether_remove(struct platform_device *pdev)
++static int at91ether_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *dev = platform_get_drvdata(pdev);
+ 	struct macb *lp = netdev_priv(dev);
+@@ -509,7 +509,7 @@ static int at91ether_resume(struct platform_device *pdev)
+ #endif
+ 
+ static struct platform_driver at91ether_driver = {
+-	.remove		= __devexit_p(at91ether_remove),
++	.remove		= at91ether_remove,
+ 	.suspend	= at91ether_suspend,
+ 	.resume		= at91ether_resume,
+ 	.driver		= {
+diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
+index 6a59bce38a8c..a9b0830fb39d 100644
+--- a/drivers/net/ethernet/cadence/macb.c
++++ b/drivers/net/ethernet/cadence/macb.c
+@@ -1470,7 +1470,7 @@ static const struct of_device_id macb_dt_ids[] = {
+ 
+ MODULE_DEVICE_TABLE(of, macb_dt_ids);
+ 
+-static int __devinit macb_get_phy_mode_dt(struct platform_device *pdev)
++static int macb_get_phy_mode_dt(struct platform_device *pdev)
+ {
+ 	struct device_node *np = pdev->dev.of_node;
+ 
+@@ -1480,7 +1480,7 @@ static int __devinit macb_get_phy_mode_dt(struct platform_device *pdev)
+ 	return -ENODEV;
+ }
+ 
+-static int __devinit macb_get_hwaddr_dt(struct macb *bp)
++static int macb_get_hwaddr_dt(struct macb *bp)
+ {
+ 	struct device_node *np = bp->pdev->dev.of_node;
+ 	if (np) {
+@@ -1494,11 +1494,11 @@ static int __devinit macb_get_hwaddr_dt(struct macb *bp)
+ 	return -ENODEV;
+ }
+ #else
+-static int __devinit macb_get_phy_mode_dt(struct platform_device *pdev)
++static int macb_get_phy_mode_dt(struct platform_device *pdev)
+ {
+ 	return -ENODEV;
+ }
+-static int __devinit macb_get_hwaddr_dt(struct macb *bp)
++static int macb_get_hwaddr_dt(struct macb *bp)
+ {
+ 	return -ENODEV;
+ }

commit 093d369d4e8e8b6361317edd83935bdf8a0c83de
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:56 2012 -0500
+
+    net/atheros: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Jay Cliburn 
+    Cc: Chris Snook 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+index d19f82f7597a..44bee4a2b9b3 100644
+--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
++++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+@@ -643,7 +643,7 @@ static int atl1c_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+  * @adapter: board private structure to initialize
+  *
+  */
+-static int __devinit atl1c_alloc_queues(struct atl1c_adapter *adapter)
++static int atl1c_alloc_queues(struct atl1c_adapter *adapter)
+ {
+ 	return 0;
+ }
+@@ -702,7 +702,7 @@ struct atl1c_platform_patch {
+ 	u32 patch_flag;
+ #define ATL1C_LINK_PATCH	0x1
+ };
+-static const struct atl1c_platform_patch plats[] __devinitconst = {
++static const struct atl1c_platform_patch plats[] = {
+ {0x2060, 0xC1, 0x1019, 0x8152, 0x1},
+ {0x2060, 0xC1, 0x1019, 0x2060, 0x1},
+ {0x2060, 0xC1, 0x1019, 0xE000, 0x1},
+@@ -725,7 +725,7 @@ static const struct atl1c_platform_patch plats[] __devinitconst = {
+ {0},
+ };
+ 
+-static void __devinit atl1c_patch_assign(struct atl1c_hw *hw)
++static void atl1c_patch_assign(struct atl1c_hw *hw)
+ {
+ 	struct pci_dev	*pdev = hw->adapter->pdev;
+ 	u32 misc_ctrl;
+@@ -764,7 +764,7 @@ static void __devinit atl1c_patch_assign(struct atl1c_hw *hw)
+  * Fields are initialized based on PCI device information and
+  * OS network device settings (MTU size).
+  */
+-static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter)
++static int atl1c_sw_init(struct atl1c_adapter *adapter)
+ {
+ 	struct atl1c_hw *hw   = &adapter->hw;
+ 	struct pci_dev	*pdev = adapter->pdev;
+@@ -2442,7 +2442,7 @@ static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
+  * The OS initialization, configuring of the adapter private structure,
+  * and a hardware reset occur.
+  */
+-static int __devinit atl1c_probe(struct pci_dev *pdev,
++static int atl1c_probe(struct pci_dev *pdev,
+ 				 const struct pci_device_id *ent)
+ {
+ 	struct net_device *netdev;
+@@ -2587,7 +2587,7 @@ static int __devinit atl1c_probe(struct pci_dev *pdev,
+  * Hot-Plug event, or because the driver is going to be removed from
+  * memory.
+  */
+-static void __devexit atl1c_remove(struct pci_dev *pdev)
++static void atl1c_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *netdev = pci_get_drvdata(pdev);
+ 	struct atl1c_adapter *adapter = netdev_priv(netdev);
+@@ -2697,7 +2697,7 @@ static struct pci_driver atl1c_driver = {
+ 	.name     = atl1c_driver_name,
+ 	.id_table = atl1c_pci_tbl,
+ 	.probe    = atl1c_probe,
+-	.remove   = __devexit_p(atl1c_remove),
++	.remove   = atl1c_remove,
+ 	.shutdown = atl1c_shutdown,
+ 	.err_handler = &atl1c_err_handler,
+ 	.driver.pm = &atl1c_pm_ops,
+diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+index e213da29e73d..dec5d2cfd386 100644
+--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
++++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+@@ -534,7 +534,7 @@ static void atl1e_setup_pcicmd(struct pci_dev *pdev)
+  * @adapter: board private structure to initialize
+  *
+  */
+-static int __devinit atl1e_alloc_queues(struct atl1e_adapter *adapter)
++static int atl1e_alloc_queues(struct atl1e_adapter *adapter)
+ {
+ 	return 0;
+ }
+@@ -547,7 +547,7 @@ static int __devinit atl1e_alloc_queues(struct atl1e_adapter *adapter)
+  * Fields are initialized based on PCI device information and
+  * OS network device settings (MTU size).
+  */
+-static int __devinit atl1e_sw_init(struct atl1e_adapter *adapter)
++static int atl1e_sw_init(struct atl1e_adapter *adapter)
+ {
+ 	struct atl1e_hw *hw   = &adapter->hw;
+ 	struct pci_dev	*pdev = adapter->pdev;
+@@ -2235,7 +2235,7 @@ static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
+  * The OS initialization, configuring of the adapter private structure,
+  * and a hardware reset occur.
+  */
+-static int __devinit atl1e_probe(struct pci_dev *pdev,
++static int atl1e_probe(struct pci_dev *pdev,
+ 				 const struct pci_device_id *ent)
+ {
+ 	struct net_device *netdev;
+@@ -2387,7 +2387,7 @@ static int __devinit atl1e_probe(struct pci_dev *pdev,
+  * Hot-Plug event, or because the driver is going to be removed from
+  * memory.
+  */
+-static void __devexit atl1e_remove(struct pci_dev *pdev)
++static void atl1e_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *netdev = pci_get_drvdata(pdev);
+ 	struct atl1e_adapter *adapter = netdev_priv(netdev);
+@@ -2499,7 +2499,7 @@ static struct pci_driver atl1e_driver = {
+ 	.name     = atl1e_driver_name,
+ 	.id_table = atl1e_pci_tbl,
+ 	.probe    = atl1e_probe,
+-	.remove   = __devexit_p(atl1e_remove),
++	.remove   = atl1e_remove,
+ 	/* Power Management Hooks */
+ #ifdef CONFIG_PM
+ 	.suspend  = atl1e_suspend,
+diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_param.c b/drivers/net/ethernet/atheros/atl1e/atl1e_param.c
+index b5086f1e637f..fa314282c9ad 100644
+--- a/drivers/net/ethernet/atheros/atl1e/atl1e_param.c
++++ b/drivers/net/ethernet/atheros/atl1e/atl1e_param.c
+@@ -40,7 +40,7 @@
+ #define ATL1E_PARAM_INIT { [0 ... ATL1E_MAX_NIC] = OPTION_UNSET }
+ 
+ #define ATL1E_PARAM(x, desc) \
+-	static int __devinitdata x[ATL1E_MAX_NIC + 1] = ATL1E_PARAM_INIT; \
++	static int x[ATL1E_MAX_NIC + 1] = ATL1E_PARAM_INIT; \
+ 	static unsigned int num_##x; \
+ 	module_param_array_named(x, x, int, &num_##x, 0); \
+ 	MODULE_PARM_DESC(x, desc);
+@@ -116,7 +116,8 @@ struct atl1e_option {
+ 	} arg;
+ };
+ 
+-static int __devinit atl1e_validate_option(int *value, struct atl1e_option *opt, struct atl1e_adapter *adapter)
++static int atl1e_validate_option(int *value, struct atl1e_option *opt,
++				 struct atl1e_adapter *adapter)
+ {
+ 	if (*value == OPTION_UNSET) {
+ 		*value = opt->def;
+@@ -177,7 +178,7 @@ static int __devinit atl1e_validate_option(int *value, struct atl1e_option *opt,
+  * value exists, a default value is used.  The final value is stored
+  * in a variable in the adapter structure.
+  */
+-void __devinit atl1e_check_options(struct atl1e_adapter *adapter)
++void atl1e_check_options(struct atl1e_adapter *adapter)
+ {
+ 	int bd = adapter->bd_number;
+ 
+diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c
+index 7bae2ad7a7c0..3e7327ec3901 100644
+--- a/drivers/net/ethernet/atheros/atlx/atl1.c
++++ b/drivers/net/ethernet/atheros/atlx/atl1.c
+@@ -113,7 +113,7 @@ static const struct ethtool_ops atl1_ethtool_ops;
+  *
+  * Default Value: 100 (200us)
+  */
+-static int __devinitdata int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
++static int int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
+ static unsigned int num_int_mod_timer;
+ module_param_array_named(int_mod_timer, int_mod_timer, int,
+ 	&num_int_mod_timer, 0);
+@@ -143,7 +143,7 @@ struct atl1_option {
+ 	} arg;
+ };
+ 
+-static int __devinit atl1_validate_option(int *value, struct atl1_option *opt,
++static int atl1_validate_option(int *value, struct atl1_option *opt,
+ 	struct pci_dev *pdev)
+ {
+ 	if (*value == OPTION_UNSET) {
+@@ -204,7 +204,7 @@ static int __devinit atl1_validate_option(int *value, struct atl1_option *opt,
+  * value exists, a default value is used.  The final value is stored
+  * in a variable in the adapter structure.
+  */
+-static void __devinit atl1_check_options(struct atl1_adapter *adapter)
++static void atl1_check_options(struct atl1_adapter *adapter)
+ {
+ 	struct pci_dev *pdev = adapter->pdev;
+ 	int bd = adapter->bd_number;
+@@ -945,7 +945,7 @@ static void atl1_set_mac_addr(struct atl1_hw *hw)
+  * Fields are initialized based on PCI device information and
+  * OS network device settings (MTU size).
+  */
+-static int __devinit atl1_sw_init(struct atl1_adapter *adapter)
++static int atl1_sw_init(struct atl1_adapter *adapter)
+ {
+ 	struct atl1_hw *hw = &adapter->hw;
+ 	struct net_device *netdev = adapter->netdev;
+@@ -2934,7 +2934,7 @@ static const struct net_device_ops atl1_netdev_ops = {
+  * The OS initialization, configuring of the adapter private structure,
+  * and a hardware reset occur.
+  */
+-static int __devinit atl1_probe(struct pci_dev *pdev,
++static int atl1_probe(struct pci_dev *pdev,
+ 	const struct pci_device_id *ent)
+ {
+ 	struct net_device *netdev;
+@@ -3113,7 +3113,7 @@ static int __devinit atl1_probe(struct pci_dev *pdev,
+  * Hot-Plug event, or because the driver is going to be removed from
+  * memory.
+  */
+-static void __devexit atl1_remove(struct pci_dev *pdev)
++static void atl1_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *netdev = pci_get_drvdata(pdev);
+ 	struct atl1_adapter *adapter;
+@@ -3146,7 +3146,7 @@ static struct pci_driver atl1_driver = {
+ 	.name = ATLX_DRIVER_NAME,
+ 	.id_table = atl1_pci_tbl,
+ 	.probe = atl1_probe,
+-	.remove = __devexit_p(atl1_remove),
++	.remove = atl1_remove,
+ 	.shutdown = atl1_shutdown,
+ 	.driver.pm = ATL1_PM_OPS,
+ };
+diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c
+index 623dd8635c46..7dc9766bb5ba 100644
+--- a/drivers/net/ethernet/atheros/atlx/atl2.c
++++ b/drivers/net/ethernet/atheros/atlx/atl2.c
+@@ -83,7 +83,7 @@ static void atl2_check_options(struct atl2_adapter *adapter);
+  * Fields are initialized based on PCI device information and
+  * OS network device settings (MTU size).
+  */
+-static int __devinit atl2_sw_init(struct atl2_adapter *adapter)
++static int atl2_sw_init(struct atl2_adapter *adapter)
+ {
+ 	struct atl2_hw *hw = &adapter->hw;
+ 	struct pci_dev *pdev = adapter->pdev;
+@@ -1338,7 +1338,7 @@ static const struct net_device_ops atl2_netdev_ops = {
+  * The OS initialization, configuring of the adapter private structure,
+  * and a hardware reset occur.
+  */
+-static int __devinit atl2_probe(struct pci_dev *pdev,
++static int atl2_probe(struct pci_dev *pdev,
+ 	const struct pci_device_id *ent)
+ {
+ 	struct net_device *netdev;
+@@ -1498,7 +1498,7 @@ static int __devinit atl2_probe(struct pci_dev *pdev,
+  */
+ /* FIXME: write the original MAC address back in case it was changed from a
+  * BIOS-set value, as in atl1 -- CHS */
+-static void __devexit atl2_remove(struct pci_dev *pdev)
++static void atl2_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *netdev = pci_get_drvdata(pdev);
+ 	struct atl2_adapter *adapter = netdev_priv(netdev);
+@@ -1705,7 +1705,7 @@ static struct pci_driver atl2_driver = {
+ 	.name     = atl2_driver_name,
+ 	.id_table = atl2_pci_tbl,
+ 	.probe    = atl2_probe,
+-	.remove   = __devexit_p(atl2_remove),
++	.remove   = atl2_remove,
+ 	/* Power Management Hooks */
+ 	.suspend  = atl2_suspend,
+ #ifdef CONFIG_PM
+@@ -2845,12 +2845,12 @@ static void atl2_force_ps(struct atl2_hw *hw)
+  */
+ 
+ #define ATL2_PARAM(X, desc) \
+-    static const int __devinitconst X[ATL2_MAX_NIC + 1] = ATL2_PARAM_INIT; \
++    static const int X[ATL2_MAX_NIC + 1] = ATL2_PARAM_INIT; \
+     MODULE_PARM(X, "1-" __MODULE_STRING(ATL2_MAX_NIC) "i"); \
+     MODULE_PARM_DESC(X, desc);
+ #else
+ #define ATL2_PARAM(X, desc) \
+-    static int __devinitdata X[ATL2_MAX_NIC+1] = ATL2_PARAM_INIT; \
++    static int X[ATL2_MAX_NIC+1] = ATL2_PARAM_INIT; \
+     static unsigned int num_##X; \
+     module_param_array_named(X, X, int, &num_##X, 0); \
+     MODULE_PARM_DESC(X, desc);
+@@ -2934,7 +2934,7 @@ struct atl2_option {
+ 	} arg;
+ };
+ 
+-static int __devinit atl2_validate_option(int *value, struct atl2_option *opt)
++static int atl2_validate_option(int *value, struct atl2_option *opt)
+ {
+ 	int i;
+ 	struct atl2_opt_list *ent;
+@@ -2992,7 +2992,7 @@ static int __devinit atl2_validate_option(int *value, struct atl2_option *opt)
+  * value exists, a default value is used.  The final value is stored
+  * in a variable in the adapter structure.
+  */
+-static void __devinit atl2_check_options(struct atl2_adapter *adapter)
++static void atl2_check_options(struct atl2_adapter *adapter)
+ {
+ 	int val;
+ 	struct atl2_option opt;

commit 97c71ad4cef8bf9af36d2c495a971e149a9b77c8
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:55 2012 -0500
+
+    net/apple: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/apple/bmac.c b/drivers/net/ethernet/apple/bmac.c
+index 855bdafb1a87..f36bbd6d5085 100644
+--- a/drivers/net/ethernet/apple/bmac.c
++++ b/drivers/net/ethernet/apple/bmac.c
+@@ -1244,7 +1244,7 @@ static const struct net_device_ops bmac_netdev_ops = {
+ 	.ndo_validate_addr	= eth_validate_addr,
+ };
+ 
+-static int __devinit bmac_probe(struct macio_dev *mdev, const struct of_device_id *match)
++static int bmac_probe(struct macio_dev *mdev, const struct of_device_id *match)
+ {
+ 	int j, rev, ret;
+ 	struct bmac_data *bp;
+@@ -1602,7 +1602,7 @@ bmac_proc_info(char *buffer, char **start, off_t offset, int length)
+ }
+ #endif
+ 
+-static int __devexit bmac_remove(struct macio_dev *mdev)
++static int bmac_remove(struct macio_dev *mdev)
+ {
+ 	struct net_device *dev = macio_get_drvdata(mdev);
+ 	struct bmac_data *bp = netdev_priv(dev);
+diff --git a/drivers/net/ethernet/apple/mace.c b/drivers/net/ethernet/apple/mace.c
+index e1df4b76c885..842fe7684904 100644
+--- a/drivers/net/ethernet/apple/mace.c
++++ b/drivers/net/ethernet/apple/mace.c
+@@ -106,7 +106,7 @@ static const struct net_device_ops mace_netdev_ops = {
+ 	.ndo_validate_addr	= eth_validate_addr,
+ };
+ 
+-static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_id *match)
++static int mace_probe(struct macio_dev *mdev, const struct of_device_id *match)
+ {
+ 	struct device_node *mace = macio_get_of_node(mdev);
+ 	struct net_device *dev;
+@@ -271,7 +271,7 @@ static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_i
+ 	return rc;
+ }
+ 
+-static int __devexit mace_remove(struct macio_dev *mdev)
++static int mace_remove(struct macio_dev *mdev)
+ {
+ 	struct net_device *dev = macio_get_drvdata(mdev);
+ 	struct mace_data *mp;
+diff --git a/drivers/net/ethernet/apple/macmace.c b/drivers/net/ethernet/apple/macmace.c
+index a92ddee7f665..a206779c68cf 100644
+--- a/drivers/net/ethernet/apple/macmace.c
++++ b/drivers/net/ethernet/apple/macmace.c
+@@ -195,7 +195,7 @@ static const struct net_device_ops mace_netdev_ops = {
+  * model of Macintrash has a MACE (AV macintoshes)
+  */
+ 
+-static int __devinit mace_probe(struct platform_device *pdev)
++static int mace_probe(struct platform_device *pdev)
+ {
+ 	int j;
+ 	struct mace_data *mp;
+@@ -746,7 +746,7 @@ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Macintosh MACE ethernet driver");
+ MODULE_ALIAS("platform:macmace");
+ 
+-static int __devexit mac_mace_device_remove (struct platform_device *pdev)
++static int mac_mace_device_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *dev = platform_get_drvdata(pdev);
+ 	struct mace_data *mp = netdev_priv(dev);
+@@ -768,7 +768,7 @@ static int __devexit mac_mace_device_remove (struct platform_device *pdev)
+ 
+ static struct platform_driver mac_mace_driver = {
+ 	.probe  = mace_probe,
+-	.remove = __devexit_p(mac_mace_device_remove),
++	.remove = mac_mace_device_remove,
+ 	.driver	= {
+ 		.name	= mac_mace_string,
+ 		.owner	= THIS_MODULE,

commit 0cb0568dfea6b51a39362c484c9caddfc94a78b0
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:54 2012 -0500
+
+    net/amd: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/amd/a2065.c b/drivers/net/ethernet/amd/a2065.c
+index 689dfcafc6d4..818f6d6cdbe0 100644
+--- a/drivers/net/ethernet/amd/a2065.c
++++ b/drivers/net/ethernet/amd/a2065.c
+@@ -639,12 +639,12 @@ static void lance_set_multicast(struct net_device *dev)
+ 	netif_wake_queue(dev);
+ }
+ 
+-static int __devinit a2065_init_one(struct zorro_dev *z,
++static int a2065_init_one(struct zorro_dev *z,
+ 				    const struct zorro_device_id *ent);
+-static void __devexit a2065_remove_one(struct zorro_dev *z);
++static void a2065_remove_one(struct zorro_dev *z);
+ 
+ 
+-static struct zorro_device_id a2065_zorro_tbl[] __devinitdata = {
++static struct zorro_device_id a2065_zorro_tbl[] = {
+ 	{ ZORRO_PROD_CBM_A2065_1 },
+ 	{ ZORRO_PROD_CBM_A2065_2 },
+ 	{ ZORRO_PROD_AMERISTAR_A2065 },
+@@ -656,7 +656,7 @@ static struct zorro_driver a2065_driver = {
+ 	.name		= "a2065",
+ 	.id_table	= a2065_zorro_tbl,
+ 	.probe		= a2065_init_one,
+-	.remove		= __devexit_p(a2065_remove_one),
++	.remove		= a2065_remove_one,
+ };
+ 
+ static const struct net_device_ops lance_netdev_ops = {
+@@ -670,7 +670,7 @@ static const struct net_device_ops lance_netdev_ops = {
+ 	.ndo_set_mac_address	= eth_mac_addr,
+ };
+ 
+-static int __devinit a2065_init_one(struct zorro_dev *z,
++static int a2065_init_one(struct zorro_dev *z,
+ 				    const struct zorro_device_id *ent)
+ {
+ 	struct net_device *dev;
+@@ -754,7 +754,7 @@ static int __devinit a2065_init_one(struct zorro_dev *z,
+ }
+ 
+ 
+-static void __devexit a2065_remove_one(struct zorro_dev *z)
++static void a2065_remove_one(struct zorro_dev *z)
+ {
+ 	struct net_device *dev = zorro_get_drvdata(z);
+ 
+diff --git a/drivers/net/ethernet/amd/amd8111e.c b/drivers/net/ethernet/amd/amd8111e.c
+index 3491d4312fc9..42d4e6ad58a5 100644
+--- a/drivers/net/ethernet/amd/amd8111e.c
++++ b/drivers/net/ethernet/amd/amd8111e.c
+@@ -1702,7 +1702,7 @@ static int amd8111e_resume(struct pci_dev *pci_dev)
+ }
+ 
+ 
+-static void __devexit amd8111e_remove_one(struct pci_dev *pdev)
++static void amd8111e_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	if (dev) {
+@@ -1774,7 +1774,7 @@ static void amd8111e_config_ipg(struct net_device* dev)
+ 
+ }
+ 
+-static void __devinit amd8111e_probe_ext_phy(struct net_device* dev)
++static void amd8111e_probe_ext_phy(struct net_device *dev)
+ {
+ 	struct amd8111e_priv *lp = netdev_priv(dev);
+ 	int i;
+@@ -1810,7 +1810,7 @@ static const struct net_device_ops amd8111e_netdev_ops = {
+ #endif
+ };
+ 
+-static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
++static int amd8111e_probe_one(struct pci_dev *pdev,
+ 				  const struct pci_device_id *ent)
+ {
+ 	int err,i,pm_cap;
+@@ -1976,7 +1976,7 @@ static struct pci_driver amd8111e_driver = {
+ 	.name   	= MODULE_NAME,
+ 	.id_table	= amd8111e_pci_tbl,
+ 	.probe		= amd8111e_probe_one,
+-	.remove		= __devexit_p(amd8111e_remove_one),
++	.remove		= amd8111e_remove_one,
+ 	.suspend	= amd8111e_suspend,
+ 	.resume		= amd8111e_resume
+ };
+diff --git a/drivers/net/ethernet/amd/ariadne.c b/drivers/net/ethernet/amd/ariadne.c
+index f2958df9a1e4..2ea7a231ef10 100644
+--- a/drivers/net/ethernet/amd/ariadne.c
++++ b/drivers/net/ethernet/amd/ariadne.c
+@@ -682,7 +682,7 @@ static void set_multicast_list(struct net_device *dev)
+ }
+ 
+ 
+-static void __devexit ariadne_remove_one(struct zorro_dev *z)
++static void ariadne_remove_one(struct zorro_dev *z)
+ {
+ 	struct net_device *dev = zorro_get_drvdata(z);
+ 
+@@ -692,7 +692,7 @@ static void __devexit ariadne_remove_one(struct zorro_dev *z)
+ 	free_netdev(dev);
+ }
+ 
+-static struct zorro_device_id ariadne_zorro_tbl[] __devinitdata = {
++static struct zorro_device_id ariadne_zorro_tbl[] = {
+ 	{ ZORRO_PROD_VILLAGE_TRONIC_ARIADNE },
+ 	{ 0 }
+ };
+@@ -710,7 +710,7 @@ static const struct net_device_ops ariadne_netdev_ops = {
+ 	.ndo_set_mac_address	= eth_mac_addr,
+ };
+ 
+-static int __devinit ariadne_init_one(struct zorro_dev *z,
++static int ariadne_init_one(struct zorro_dev *z,
+ 				      const struct zorro_device_id *ent)
+ {
+ 	unsigned long board = z->resource.start;
+@@ -774,7 +774,7 @@ static struct zorro_driver ariadne_driver = {
+ 	.name		= "ariadne",
+ 	.id_table	= ariadne_zorro_tbl,
+ 	.probe		= ariadne_init_one,
+-	.remove		= __devexit_p(ariadne_remove_one),
++	.remove		= ariadne_remove_one,
+ };
+ 
+ static int __init ariadne_init_module(void)
+diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c
+index f195acfa2df7..2ea221ed4777 100644
+--- a/drivers/net/ethernet/amd/au1000_eth.c
++++ b/drivers/net/ethernet/amd/au1000_eth.c
+@@ -1016,7 +1016,7 @@ static const struct net_device_ops au1000_netdev_ops = {
+ 	.ndo_change_mtu		= eth_change_mtu,
+ };
+ 
+-static int __devinit au1000_probe(struct platform_device *pdev)
++static int au1000_probe(struct platform_device *pdev)
+ {
+ 	static unsigned version_printed;
+ 	struct au1000_private *aup = NULL;
+@@ -1295,7 +1295,7 @@ static int __devinit au1000_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit au1000_remove(struct platform_device *pdev)
++static int au1000_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *dev = platform_get_drvdata(pdev);
+ 	struct au1000_private *aup = netdev_priv(dev);
+@@ -1340,7 +1340,7 @@ static int __devexit au1000_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver au1000_eth_driver = {
+ 	.probe  = au1000_probe,
+-	.remove = __devexit_p(au1000_remove),
++	.remove = au1000_remove,
+ 	.driver = {
+ 		.name   = "au1000-eth",
+ 		.owner  = THIS_MODULE,
+diff --git a/drivers/net/ethernet/amd/declance.c b/drivers/net/ethernet/amd/declance.c
+index 7203b522f234..baca0bd1b393 100644
+--- a/drivers/net/ethernet/amd/declance.c
++++ b/drivers/net/ethernet/amd/declance.c
+@@ -72,7 +72,7 @@
+ #include 
+ #include 
+ 
+-static char version[] __devinitdata =
++static char version[] =
+ "declance.c: v0.011 by Linux MIPS DECstation task force\n";
+ 
+ MODULE_AUTHOR("Linux MIPS DECstation task force");
+@@ -1020,7 +1020,7 @@ static const struct net_device_ops lance_netdev_ops = {
+ 	.ndo_set_mac_address	= eth_mac_addr,
+ };
+ 
+-static int __devinit dec_lance_probe(struct device *bdev, const int type)
++static int dec_lance_probe(struct device *bdev, const int type)
+ {
+ 	static unsigned version_printed;
+ 	static const char fmt[] = "declance%d";
+@@ -1322,7 +1322,7 @@ static void __exit dec_lance_platform_remove(void)
+ }
+ 
+ #ifdef CONFIG_TC
+-static int __devinit dec_lance_tc_probe(struct device *dev);
++static int dec_lance_tc_probe(struct device *dev);
+ static int __exit dec_lance_tc_remove(struct device *dev);
+ 
+ static const struct tc_device_id dec_lance_tc_table[] = {
+@@ -1341,7 +1341,7 @@ static struct tc_driver dec_lance_tc_driver = {
+ 	},
+ };
+ 
+-static int __devinit dec_lance_tc_probe(struct device *dev)
++static int dec_lance_tc_probe(struct device *dev)
+ {
+         int status = dec_lance_probe(dev, PMAD_LANCE);
+         if (!status)
+diff --git a/drivers/net/ethernet/amd/depca.c b/drivers/net/ethernet/amd/depca.c
+index c771de71612a..34a485363d5b 100644
+--- a/drivers/net/ethernet/amd/depca.c
++++ b/drivers/net/ethernet/amd/depca.c
+@@ -338,21 +338,21 @@ static struct eisa_driver depca_eisa_driver = {
+ 	.driver   = {
+ 		.name    = depca_string,
+ 		.probe   = depca_eisa_probe,
+-		.remove  = __devexit_p (depca_device_remove)
++		.remove  = depca_device_remove
+ 	}
+ };
+ #endif
+ 
+ static int depca_isa_probe (struct platform_device *);
+ 
+-static int __devexit depca_isa_remove(struct platform_device *pdev)
++static int depca_isa_remove(struct platform_device *pdev)
+ {
+ 	return depca_device_remove(&pdev->dev);
+ }
+ 
+ static struct platform_driver depca_isa_driver = {
+ 	.probe  = depca_isa_probe,
+-	.remove = __devexit_p(depca_isa_remove),
++	.remove = depca_isa_remove,
+ 	.driver	= {
+ 		.name   = depca_string,
+ 	},
+@@ -1320,7 +1320,7 @@ static enum depca_type __init depca_shmem_probe (ulong *mem_start)
+ 	return adapter;
+ }
+ 
+-static int __devinit depca_isa_probe (struct platform_device *device)
++static int depca_isa_probe(struct platform_device *device)
+ {
+ 	struct net_device *dev;
+ 	struct depca_private *lp;
+@@ -1412,7 +1412,7 @@ static int __init depca_eisa_probe (struct device *device)
+ }
+ #endif
+ 
+-static int __devexit depca_device_remove (struct device *device)
++static int depca_device_remove(struct device *device)
+ {
+ 	struct net_device *dev;
+ 	struct depca_private *lp;
+diff --git a/drivers/net/ethernet/amd/hplance.c b/drivers/net/ethernet/amd/hplance.c
+index 8baff4e5d964..705333e0eff9 100644
+--- a/drivers/net/ethernet/amd/hplance.c
++++ b/drivers/net/ethernet/amd/hplance.c
+@@ -46,11 +46,11 @@ struct hplance_private {
+  * plus board-specific init, open and close actions.
+  * Oh, and we need to tell the generic code how to read and write LANCE registers...
+  */
+-static int __devinit hplance_init_one(struct dio_dev *d,
++static int hplance_init_one(struct dio_dev *d,
+ 				const struct dio_device_id *ent);
+-static void __devinit hplance_init(struct net_device *dev,
++static void hplance_init(struct net_device *dev,
+ 				struct dio_dev *d);
+-static void __devexit hplance_remove_one(struct dio_dev *d);
++static void hplance_remove_one(struct dio_dev *d);
+ static void hplance_writerap(void *priv, unsigned short value);
+ static void hplance_writerdp(void *priv, unsigned short value);
+ static unsigned short hplance_readrdp(void *priv);
+@@ -66,7 +66,7 @@ static struct dio_driver hplance_driver = {
+ 	.name      = "hplance",
+ 	.id_table  = hplance_dio_tbl,
+ 	.probe     = hplance_init_one,
+-	.remove    = __devexit_p(hplance_remove_one),
++	.remove    = hplance_remove_one,
+ };
+ 
+ static const struct net_device_ops hplance_netdev_ops = {
+@@ -83,7 +83,7 @@ static const struct net_device_ops hplance_netdev_ops = {
+ };
+ 
+ /* Find all the HP Lance boards and initialise them... */
+-static int __devinit hplance_init_one(struct dio_dev *d,
++static int hplance_init_one(struct dio_dev *d,
+ 				const struct dio_device_id *ent)
+ {
+ 	struct net_device *dev;
+@@ -118,7 +118,7 @@ static int __devinit hplance_init_one(struct dio_dev *d,
+ 	return err;
+ }
+ 
+-static void __devexit hplance_remove_one(struct dio_dev *d)
++static void hplance_remove_one(struct dio_dev *d)
+ {
+ 	struct net_device *dev = dio_get_drvdata(d);
+ 
+@@ -128,7 +128,7 @@ static void __devexit hplance_remove_one(struct dio_dev *d)
+ }
+ 
+ /* Initialise a single lance board at the given DIO device */
+-static void __devinit hplance_init(struct net_device *dev, struct dio_dev *d)
++static void hplance_init(struct net_device *dev, struct dio_dev *d)
+ {
+         unsigned long va = (d->resource.start + DIO_VIRADDRBASE);
+         struct hplance_private *lp;
+diff --git a/drivers/net/ethernet/amd/sunlance.c b/drivers/net/ethernet/amd/sunlance.c
+index d7a3533d990b..64dbffa0a7e2 100644
+--- a/drivers/net/ethernet/amd/sunlance.c
++++ b/drivers/net/ethernet/amd/sunlance.c
+@@ -1304,7 +1304,7 @@ static const struct net_device_ops sparc_lance_ops = {
+ 	.ndo_validate_addr	= eth_validate_addr,
+ };
+ 
+-static int __devinit sparc_lance_probe_one(struct platform_device *op,
++static int sparc_lance_probe_one(struct platform_device *op,
+ 					   struct platform_device *ledma,
+ 					   struct platform_device *lebuffer)
+ {
+@@ -1488,7 +1488,7 @@ static int __devinit sparc_lance_probe_one(struct platform_device *op,
+ 	return -ENODEV;
+ }
+ 
+-static int __devinit sunlance_sbus_probe(struct platform_device *op)
++static int sunlance_sbus_probe(struct platform_device *op)
+ {
+ 	struct platform_device *parent = to_platform_device(op->dev.parent);
+ 	struct device_node *parent_dp = parent->dev.of_node;
+@@ -1504,7 +1504,7 @@ static int __devinit sunlance_sbus_probe(struct platform_device *op)
+ 	return err;
+ }
+ 
+-static int __devexit sunlance_sbus_remove(struct platform_device *op)
++static int sunlance_sbus_remove(struct platform_device *op)
+ {
+ 	struct lance_private *lp = dev_get_drvdata(&op->dev);
+ 	struct net_device *net_dev = lp->dev;
+@@ -1536,7 +1536,7 @@ static struct platform_driver sunlance_sbus_driver = {
+ 		.of_match_table = sunlance_sbus_match,
+ 	},
+ 	.probe		= sunlance_sbus_probe,
+-	.remove		= __devexit_p(sunlance_sbus_remove),
++	.remove		= sunlance_sbus_remove,
+ };
+ 
+ module_platform_driver(sunlance_sbus_driver);

commit af37557b1b222c64e005c105c81aa3888128bb5d
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:53 2012 -0500
+
+    jme: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Guo-Fu Tseng 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
+index 60ac46f4ac08..0519afa413d2 100644
+--- a/drivers/net/ethernet/jme.c
++++ b/drivers/net/ethernet/jme.c
+@@ -2965,7 +2965,7 @@ static const struct net_device_ops jme_netdev_ops = {
+ #endif
+ };
+ 
+-static int __devinit
++static int
+ jme_init_one(struct pci_dev *pdev,
+ 	     const struct pci_device_id *ent)
+ {
+@@ -3203,7 +3203,7 @@ jme_init_one(struct pci_dev *pdev,
+ 	return rc;
+ }
+ 
+-static void __devexit
++static void
+ jme_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *netdev = pci_get_drvdata(pdev);
+@@ -3318,7 +3318,7 @@ static struct pci_driver jme_driver = {
+ 	.name           = DRV_NAME,
+ 	.id_table       = jme_pci_tbl,
+ 	.probe          = jme_init_one,
+-	.remove         = __devexit_p(jme_remove_one),
++	.remove         = jme_remove_one,
+ 	.shutdown       = jme_shutdown,
+ 	.driver.pm	= JME_PM_OPS,
+ };

commit 331774760a65c27c673aa7735075124978e7994b
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:52 2012 -0500
+
+    icplus: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Francois Romieu 
+    Cc: Sorbica Shieh 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/icplus/ipg.c b/drivers/net/ethernet/icplus/ipg.c
+index 1b563bb959c2..f80ae745908d 100644
+--- a/drivers/net/ethernet/icplus/ipg.c
++++ b/drivers/net/ethernet/icplus/ipg.c
+@@ -2167,7 +2167,7 @@ static const struct ethtool_ops ipg_ethtool_ops = {
+ 	.nway_reset   = ipg_nway_reset,
+ };
+ 
+-static void __devexit ipg_remove(struct pci_dev *pdev)
++static void ipg_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct ipg_nic_private *sp = netdev_priv(dev);
+@@ -2199,7 +2199,7 @@ static const struct net_device_ops ipg_netdev_ops = {
+ 	.ndo_validate_addr	= eth_validate_addr,
+ };
+ 
+-static int __devinit ipg_probe(struct pci_dev *pdev,
++static int ipg_probe(struct pci_dev *pdev,
+ 			       const struct pci_device_id *id)
+ {
+ 	unsigned int i = id->driver_data;
+@@ -2296,7 +2296,7 @@ static struct pci_driver ipg_pci_driver = {
+ 	.name		= IPG_DRIVER_NAME,
+ 	.id_table	= ipg_pci_tbl,
+ 	.probe		= ipg_probe,
+-	.remove		= __devexit_p(ipg_remove),
++	.remove		= ipg_remove,
+ };
+ 
+ static int __init ipg_init_module(void)

commit 9871b639d00b75625a4bc855c09096e2c4897816
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:51 2012 -0500
+
+    ixp4xx_eth: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Krzysztof Halasa 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c
+index 477d6729b17f..d3ebb73277be 100644
+--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c
++++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c
+@@ -1379,7 +1379,7 @@ static const struct net_device_ops ixp4xx_netdev_ops = {
+ 	.ndo_validate_addr = eth_validate_addr,
+ };
+ 
+-static int __devinit eth_init_one(struct platform_device *pdev)
++static int eth_init_one(struct platform_device *pdev)
+ {
+ 	struct port *port;
+ 	struct net_device *dev;
+@@ -1480,7 +1480,7 @@ static int __devinit eth_init_one(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit eth_remove_one(struct platform_device *pdev)
++static int eth_remove_one(struct platform_device *pdev)
+ {
+ 	struct net_device *dev = platform_get_drvdata(pdev);
+ 	struct port *port = netdev_priv(dev);

commit 48d16cb1befb39ab1d7dc5842182d6133d88de0e
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:50 2012 -0500
+
+    xilinx_axienet: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Anirudha Sarangi 
+    Cc: John Linn 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+index a788501e978e..d9f69b82cc4f 100644
+--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
++++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+@@ -48,7 +48,7 @@
+ #define AXIENET_REGS_N		32
+ 
+ /* Match table for of_platform binding */
+-static struct of_device_id axienet_of_match[] __devinitdata = {
++static struct of_device_id axienet_of_match[] = {
+ 	{ .compatible = "xlnx,axi-ethernet-1.00.a", },
+ 	{ .compatible = "xlnx,axi-ethernet-1.01.a", },
+ 	{ .compatible = "xlnx,axi-ethernet-2.01.a", },
+@@ -1482,7 +1482,7 @@ static void axienet_dma_err_handler(unsigned long data)
+  * device. Parses through device tree and populates fields of
+  * axienet_local. It registers the Ethernet device.
+  */
+-static int __devinit axienet_of_probe(struct platform_device *op)
++static int axienet_of_probe(struct platform_device *op)
+ {
+ 	__be32 *p;
+ 	int size, ret = 0;
+@@ -1632,7 +1632,7 @@ static int __devinit axienet_of_probe(struct platform_device *op)
+ 	return ret;
+ }
+ 
+-static int __devexit axienet_of_remove(struct platform_device *op)
++static int axienet_of_remove(struct platform_device *op)
+ {
+ 	struct net_device *ndev = dev_get_drvdata(&op->dev);
+ 	struct axienet_local *lp = netdev_priv(ndev);
+@@ -1656,7 +1656,7 @@ static int __devexit axienet_of_remove(struct platform_device *op)
+ 
+ static struct platform_driver axienet_of_driver = {
+ 	.probe = axienet_of_probe,
+-	.remove = __devexit_p(axienet_of_remove),
++	.remove = axienet_of_remove,
+ 	.driver = {
+ 		 .owner = THIS_MODULE,
+ 		 .name = "xilinx_axienet",

commit 27add00620ed820f94c8d332591fe73ba384b7e9
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:49 2012 -0500
+
+    via-velocity: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Francois Romieu 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c
+index a46c19859683..dc9edd48c933 100644
+--- a/drivers/net/ethernet/via/via-velocity.c
++++ b/drivers/net/ethernet/via/via-velocity.c
+@@ -375,7 +375,7 @@ MODULE_DEVICE_TABLE(pci, velocity_id_table);
+  *	Given a chip identifier return a suitable description. Returns
+  *	a pointer a static string valid while the driver is loaded.
+  */
+-static const char __devinit *get_chip_name(enum chip_type chip_id)
++static const char *get_chip_name(enum chip_type chip_id)
+ {
+ 	int i;
+ 	for (i = 0; chip_info_table[i].name != NULL; i++)
+@@ -392,7 +392,7 @@ static const char __devinit *get_chip_name(enum chip_type chip_id)
+  *	unload for each active device that is present. Disconnects
+  *	the device from the network layer and frees all the resources
+  */
+-static void __devexit velocity_remove1(struct pci_dev *pdev)
++static void velocity_remove1(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct velocity_info *vptr = netdev_priv(dev);
+@@ -421,7 +421,8 @@ static void __devexit velocity_remove1(struct pci_dev *pdev)
+  *	all the verification and checking as well as reporting so that
+  *	we don't duplicate code for each option.
+  */
+-static void __devinit velocity_set_int_opt(int *opt, int val, int min, int max, int def, char *name, const char *devname)
++static void velocity_set_int_opt(int *opt, int val, int min, int max, int def,
++				 char *name, const char *devname)
+ {
+ 	if (val == -1)
+ 		*opt = def;
+@@ -449,7 +450,8 @@ static void __devinit velocity_set_int_opt(int *opt, int val, int min, int max,
+  *	all the verification and checking as well as reporting so that
+  *	we don't duplicate code for each option.
+  */
+-static void __devinit velocity_set_bool_opt(u32 *opt, int val, int def, u32 flag, char *name, const char *devname)
++static void velocity_set_bool_opt(u32 *opt, int val, int def, u32 flag,
++				  char *name, const char *devname)
+ {
+ 	(*opt) &= (~flag);
+ 	if (val == -1)
+@@ -474,7 +476,8 @@ static void __devinit velocity_set_bool_opt(u32 *opt, int val, int def, u32 flag
+  *	Turn the module and command options into a single structure
+  *	for the current device
+  */
+-static void __devinit velocity_get_options(struct velocity_opt *opts, int index, const char *devname)
++static void velocity_get_options(struct velocity_opt *opts, int index,
++				 const char *devname)
+ {
+ 
+ 	velocity_set_int_opt(&opts->rx_thresh, rx_thresh[index], RX_THRESH_MIN, RX_THRESH_MAX, RX_THRESH_DEF, "rx_thresh", devname);
+@@ -2627,7 +2630,7 @@ static const struct net_device_ops velocity_netdev_ops = {
+  *	Set up the initial velocity_info struct for the device that has been
+  *	discovered.
+  */
+-static void __devinit velocity_init_info(struct pci_dev *pdev,
++static void velocity_init_info(struct pci_dev *pdev,
+ 					 struct velocity_info *vptr,
+ 					 const struct velocity_info_tbl *info)
+ {
+@@ -2648,7 +2651,8 @@ static void __devinit velocity_init_info(struct pci_dev *pdev,
+  *	Retrieve the PCI configuration space data that interests us from
+  *	the kernel PCI layer
+  */
+-static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pci_dev *pdev)
++static int velocity_get_pci_info(struct velocity_info *vptr,
++				 struct pci_dev *pdev)
+ {
+ 	vptr->rev_id = pdev->revision;
+ 
+@@ -2685,7 +2689,7 @@ static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pc
+  *	Print per driver data as the kernel driver finds Velocity
+  *	hardware
+  */
+-static void __devinit velocity_print_info(struct velocity_info *vptr)
++static void velocity_print_info(struct velocity_info *vptr)
+ {
+ 	struct net_device *dev = vptr->dev;
+ 
+@@ -2709,7 +2713,8 @@ static u32 velocity_get_link(struct net_device *dev)
+  *	Configure a discovered adapter from scratch. Return a negative
+  *	errno error code on failure paths.
+  */
+-static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_device_id *ent)
++static int velocity_found1(struct pci_dev *pdev,
++			   const struct pci_device_id *ent)
+ {
+ 	static int first = 1;
+ 	struct net_device *dev;
+@@ -3108,7 +3113,7 @@ static struct pci_driver velocity_driver = {
+ 	.name		= VELOCITY_NAME,
+ 	.id_table	= velocity_id_table,
+ 	.probe		= velocity_found1,
+-	.remove		= __devexit_p(velocity_remove1),
++	.remove		= velocity_remove1,
+ #ifdef CONFIG_PM
+ 	.suspend	= velocity_suspend,
+ 	.resume		= velocity_resume,

commit 76e239e1fa66eab1cb5b80a86d4803dc839bbc8f
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:48 2012 -0500
+
+    via-rhine: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Roger Luethi 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
+index 0459c096629f..53ccc5174d08 100644
+--- a/drivers/net/ethernet/via/via-rhine.c
++++ b/drivers/net/ethernet/via/via-rhine.c
+@@ -113,7 +113,7 @@ static const int multicast_filter_limit = 32;
+ #include 
+ 
+ /* These identify the driver base version and may not be removed. */
+-static const char version[] __devinitconst =
++static const char version[] =
+ 	"v1.10-LK" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker";
+ 
+ /* This driver was written to use PCI memory space. Some early versions
+@@ -657,7 +657,7 @@ static void enable_mmio(long pioaddr, u32 quirks)
+  * Loads bytes 0x00-0x05, 0x6E-0x6F, 0x78-0x7B from EEPROM
+  * (plus 0x6C for Rhine-I/II)
+  */
+-static void __devinit rhine_reload_eeprom(long pioaddr, struct net_device *dev)
++static void rhine_reload_eeprom(long pioaddr, struct net_device *dev)
+ {
+ 	struct rhine_private *rp = netdev_priv(dev);
+ 	void __iomem *ioaddr = rp->base;
+@@ -823,7 +823,7 @@ static int rhine_napipoll(struct napi_struct *napi, int budget)
+ 	return work_done;
+ }
+ 
+-static void __devinit rhine_hw_init(struct net_device *dev, long pioaddr)
++static void rhine_hw_init(struct net_device *dev, long pioaddr)
+ {
+ 	struct rhine_private *rp = netdev_priv(dev);
+ 
+@@ -856,7 +856,7 @@ static const struct net_device_ops rhine_netdev_ops = {
+ #endif
+ };
+ 
+-static int __devinit rhine_init_one(struct pci_dev *pdev,
++static int rhine_init_one(struct pci_dev *pdev,
+ 				    const struct pci_device_id *ent)
+ {
+ 	struct net_device *dev;
+@@ -2232,7 +2232,7 @@ static int rhine_close(struct net_device *dev)
+ }
+ 
+ 
+-static void __devexit rhine_remove_one(struct pci_dev *pdev)
++static void rhine_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct rhine_private *rp = netdev_priv(dev);
+@@ -2359,7 +2359,7 @@ static struct pci_driver rhine_driver = {
+ 	.name		= DRV_NAME,
+ 	.id_table	= rhine_pci_tbl,
+ 	.probe		= rhine_init_one,
+-	.remove		= __devexit_p(rhine_remove_one),
++	.remove		= rhine_remove_one,
+ 	.shutdown	= rhine_shutdown,
+ 	.driver.pm	= RHINE_PM_OPS,
+ };

commit b38d13066020a5390b59d1b740b7985d548bfb5b
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:47 2012 -0500
+
+    tc35815: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/toshiba/tc35815.c b/drivers/net/ethernet/toshiba/tc35815.c
+index 651a70c55e6e..5db09efae927 100644
+--- a/drivers/net/ethernet/toshiba/tc35815.c
++++ b/drivers/net/ethernet/toshiba/tc35815.c
+@@ -60,7 +60,7 @@ enum tc35815_chiptype {
+ /* indexed by tc35815_chiptype, above */
+ static const struct {
+ 	const char *name;
+-} chip_info[] __devinitdata = {
++} chip_info[] = {
+ 	{ "TOSHIBA TC35815CF 10/100BaseTX" },
+ 	{ "TOSHIBA TC35815 with Wake on LAN" },
+ 	{ "TOSHIBA TC35815/TX4939" },
+@@ -719,7 +719,7 @@ static int tc_mii_init(struct net_device *dev)
+  * should provide a "tc35815-mac" device with a MAC address in its
+  * platform_data.
+  */
+-static int __devinit tc35815_mac_match(struct device *dev, void *data)
++static int tc35815_mac_match(struct device *dev, void *data)
+ {
+ 	struct platform_device *plat_dev = to_platform_device(dev);
+ 	struct pci_dev *pci_dev = data;
+@@ -727,7 +727,7 @@ static int __devinit tc35815_mac_match(struct device *dev, void *data)
+ 	return !strcmp(plat_dev->name, "tc35815-mac") && plat_dev->id == id;
+ }
+ 
+-static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev)
++static int tc35815_read_plat_dev_addr(struct net_device *dev)
+ {
+ 	struct tc35815_local *lp = netdev_priv(dev);
+ 	struct device *pd = bus_find_device(&platform_bus_type, NULL,
+@@ -741,13 +741,13 @@ static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev)
+ 	return -ENODEV;
+ }
+ #else
+-static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev)
++static int tc35815_read_plat_dev_addr(struct net_device *dev)
+ {
+ 	return -ENODEV;
+ }
+ #endif
+ 
+-static int __devinit tc35815_init_dev_addr(struct net_device *dev)
++static int tc35815_init_dev_addr(struct net_device *dev)
+ {
+ 	struct tc35815_regs __iomem *tr =
+ 		(struct tc35815_regs __iomem *)dev->base_addr;
+@@ -785,7 +785,7 @@ static const struct net_device_ops tc35815_netdev_ops = {
+ #endif
+ };
+ 
+-static int __devinit tc35815_init_one(struct pci_dev *pdev,
++static int tc35815_init_one(struct pci_dev *pdev,
+ 				      const struct pci_device_id *ent)
+ {
+ 	void __iomem *ioaddr = NULL;
+@@ -878,7 +878,7 @@ static int __devinit tc35815_init_one(struct pci_dev *pdev,
+ }
+ 
+ 
+-static void __devexit tc35815_remove_one(struct pci_dev *pdev)
++static void tc35815_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct tc35815_local *lp = netdev_priv(dev);
+@@ -2198,7 +2198,7 @@ static struct pci_driver tc35815_pci_driver = {
+ 	.name		= MODNAME,
+ 	.id_table	= tc35815_pci_tbl,
+ 	.probe		= tc35815_init_one,
+-	.remove		= __devexit_p(tc35815_remove_one),
++	.remove		= tc35815_remove_one,
+ #ifdef CONFIG_PM
+ 	.suspend	= tc35815_suspend,
+ 	.resume		= tc35815_resume,

commit 17abe3e4c67bfbf20e870be9c8b4634c12f73018
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:46 2012 -0500
+
+    tehuti: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Andy Gospodarek 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c
+index 6ce9edd95c04..1e4d743ff03e 100644
+--- a/drivers/net/ethernet/tehuti/tehuti.c
++++ b/drivers/net/ethernet/tehuti/tehuti.c
+@@ -1914,7 +1914,7 @@ static const struct net_device_ops bdx_netdev_ops = {
+  */
+ 
+ /* TBD: netif_msg should be checked and implemented. I disable it for now */
+-static int __devinit
++static int
+ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ 	struct net_device *ndev;
+@@ -2427,7 +2427,7 @@ static void bdx_set_ethtool_ops(struct net_device *netdev)
+  * Hot-Plug event, or because the driver is going to be removed from
+  * memory.
+  **/
+-static void __devexit bdx_remove(struct pci_dev *pdev)
++static void bdx_remove(struct pci_dev *pdev)
+ {
+ 	struct pci_nic *nic = pci_get_drvdata(pdev);
+ 	struct net_device *ndev;
+@@ -2458,7 +2458,7 @@ static struct pci_driver bdx_pci_driver = {
+ 	.name = BDX_DRV_NAME,
+ 	.id_table = bdx_pci_tbl,
+ 	.probe = bdx_probe,
+-	.remove = __devexit_p(bdx_remove),
++	.remove = bdx_remove,
+ };
+ 
+ /*

commit 663e12e61d8764ce342588325d1050d9cb5460c0
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:45 2012 -0500
+
+    cpsw: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
+index c9714e1c164a..40aff684aa23 100644
+--- a/drivers/net/ethernet/ti/cpsw.c
++++ b/drivers/net/ethernet/ti/cpsw.c
+@@ -1136,7 +1136,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
+ 	return ret;
+ }
+ 
+-static int __devinit cpsw_probe(struct platform_device *pdev)
++static int cpsw_probe(struct platform_device *pdev)
+ {
+ 	struct cpsw_platform_data	*data = pdev->dev.platform_data;
+ 	struct net_device		*ndev;
+@@ -1398,7 +1398,7 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit cpsw_remove(struct platform_device *pdev)
++static int cpsw_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *ndev = platform_get_drvdata(pdev);
+ 	struct cpsw_priv *priv = netdev_priv(ndev);
+@@ -1467,7 +1467,7 @@ static struct platform_driver cpsw_driver = {
+ 		.of_match_table = of_match_ptr(cpsw_of_mtable),
+ 	},
+ 	.probe = cpsw_probe,
+-	.remove = __devexit_p(cpsw_remove),
++	.remove = cpsw_remove,
+ };
+ 
+ static int __init cpsw_init(void)

commit 369158767af29ed54f3751f80222e751cf60236c
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:44 2012 -0500
+
+    tlan: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Samuel Chessman 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/ti/tlan.c b/drivers/net/ethernet/ti/tlan.c
+index 3e6abf0f2771..af16081677e7 100644
+--- a/drivers/net/ethernet/ti/tlan.c
++++ b/drivers/net/ethernet/ti/tlan.c
+@@ -300,7 +300,7 @@ these functions are more or less common to all linux network drivers.
+  **************************************************************/
+ 
+ 
+-static void __devexit tlan_remove_one(struct pci_dev *pdev)
++static void tlan_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct tlan_priv	*priv = netdev_priv(dev);
+@@ -392,7 +392,7 @@ static struct pci_driver tlan_driver = {
+ 	.name		= "tlan",
+ 	.id_table	= tlan_pci_tbl,
+ 	.probe		= tlan_init_one,
+-	.remove		= __devexit_p(tlan_remove_one),
++	.remove		= tlan_remove_one,
+ 	.suspend	= tlan_suspend,
+ 	.resume		= tlan_resume,
+ };
+@@ -434,7 +434,7 @@ static int __init tlan_probe(void)
+ }
+ 
+ 
+-static int __devinit tlan_init_one(struct pci_dev *pdev,
++static int tlan_init_one(struct pci_dev *pdev,
+ 				   const struct pci_device_id *ent)
+ {
+ 	return tlan_probe1(pdev, -1, -1, 0, ent);
+@@ -460,7 +460,7 @@ static int __devinit tlan_init_one(struct pci_dev *pdev,
+ *
+ **************************************************************/
+ 
+-static int __devinit tlan_probe1(struct pci_dev *pdev,
++static int tlan_probe1(struct pci_dev *pdev,
+ 				 long ioaddr, int irq, int rev,
+ 				 const struct pci_device_id *ent)
+ {

commit f57ae66ee5486426fc86ed46f97c5e15792c8535
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:43 2012 -0500
+
+    cpmac: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Florian Fainelli 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/ti/cpmac.c b/drivers/net/ethernet/ti/cpmac.c
+index 860c2526f08d..d9625f62b026 100644
+--- a/drivers/net/ethernet/ti/cpmac.c
++++ b/drivers/net/ethernet/ti/cpmac.c
+@@ -1110,7 +1110,7 @@ static const struct net_device_ops cpmac_netdev_ops = {
+ 
+ static int external_switch;
+ 
+-static int __devinit cpmac_probe(struct platform_device *pdev)
++static int cpmac_probe(struct platform_device *pdev)
+ {
+ 	int rc, phy_id;
+ 	char mdio_bus_id[MII_BUS_ID_SIZE];
+@@ -1204,7 +1204,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
+ 	return rc;
+ }
+ 
+-static int __devexit cpmac_remove(struct platform_device *pdev)
++static int cpmac_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *dev = platform_get_drvdata(pdev);
+ 	unregister_netdev(dev);
+@@ -1216,10 +1216,10 @@ static struct platform_driver cpmac_driver = {
+ 	.driver.name = "cpmac",
+ 	.driver.owner = THIS_MODULE,
+ 	.probe = cpmac_probe,
+-	.remove = __devexit_p(cpmac_remove),
++	.remove = cpmac_remove,
+ };
+ 
+-int __devinit cpmac_init(void)
++int cpmac_init(void)
+ {
+ 	u32 mask;
+ 	int i, res;
+@@ -1290,7 +1290,7 @@ int __devinit cpmac_init(void)
+ 	return res;
+ }
+ 
+-void __devexit cpmac_exit(void)
++void cpmac_exit(void)
+ {
+ 	platform_driver_unregister(&cpmac_driver);
+ 	mdiobus_unregister(cpmac_mii);

commit b0171cdc3702416274f05936ef63767d71c25065
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:42 2012 -0500
+
+    epic100: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/smsc/epic100.c b/drivers/net/ethernet/smsc/epic100.c
+index d01e59c348ad..347cccbeb53c 100644
+--- a/drivers/net/ethernet/smsc/epic100.c
++++ b/drivers/net/ethernet/smsc/epic100.c
+@@ -90,9 +90,9 @@ static int rx_copybreak;
+ #include 
+ 
+ /* These identify the driver base version and may not be removed. */
+-static char version[] __devinitdata =
++static char version[] =
+ DRV_NAME ".c:v1.11 1/7/2001 Written by Donald Becker \n";
+-static char version2[] __devinitdata =
++static char version2[] =
+ "  (unofficial 2.4.x kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n";
+ 
+ MODULE_AUTHOR("Donald Becker ");
+@@ -318,7 +318,7 @@ static const struct net_device_ops epic_netdev_ops = {
+ 	.ndo_validate_addr	= eth_validate_addr,
+ };
+ 
+-static int __devinit epic_init_one(struct pci_dev *pdev,
++static int epic_init_one(struct pci_dev *pdev,
+ 				   const struct pci_device_id *ent)
+ {
+ 	static int card_idx = -1;
+@@ -569,7 +569,7 @@ static inline void epic_napi_irq_on(struct net_device *dev,
+ 	ew32(INTMASK, ep->irq_mask | EpicNapiEvent);
+ }
+ 
+-static int __devinit read_eeprom(struct epic_private *ep, int location)
++static int read_eeprom(struct epic_private *ep, int location)
+ {
+ 	void __iomem *ioaddr = ep->ioaddr;
+ 	int i;
+@@ -1524,7 +1524,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+ }
+ 
+ 
+-static void __devexit epic_remove_one(struct pci_dev *pdev)
++static void epic_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct epic_private *ep = netdev_priv(dev);
+@@ -1577,7 +1577,7 @@ static struct pci_driver epic_driver = {
+ 	.name		= DRV_NAME,
+ 	.id_table	= epic_pci_tbl,
+ 	.probe		= epic_init_one,
+-	.remove		= __devexit_p(epic_remove_one),
++	.remove		= epic_remove_one,
+ #ifdef CONFIG_PM
+ 	.suspend	= epic_suspend,
+ 	.resume		= epic_resume,

commit 779c1a85813a4622cc3bb3d25ce10b523bd055ba
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:41 2012 -0500
+
+    tulip: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Grant Grundler 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/dec/tulip/de2104x.c b/drivers/net/ethernet/dec/tulip/de2104x.c
+index 77335853ac36..0918e3879abe 100644
+--- a/drivers/net/ethernet/dec/tulip/de2104x.c
++++ b/drivers/net/ethernet/dec/tulip/de2104x.c
+@@ -1700,7 +1700,7 @@ static const struct ethtool_ops de_ethtool_ops = {
+ 	.get_regs		= de_get_regs,
+ };
+ 
+-static void __devinit de21040_get_mac_address (struct de_private *de)
++static void de21040_get_mac_address(struct de_private *de)
+ {
+ 	unsigned i;
+ 
+@@ -1721,7 +1721,7 @@ static void __devinit de21040_get_mac_address (struct de_private *de)
+ 	}
+ }
+ 
+-static void __devinit de21040_get_media_info(struct de_private *de)
++static void de21040_get_media_info(struct de_private *de)
+ {
+ 	unsigned int i;
+ 
+@@ -1748,7 +1748,8 @@ static void __devinit de21040_get_media_info(struct de_private *de)
+ }
+ 
+ /* Note: this routine returns extra data bits for size detection. */
+-static unsigned __devinit tulip_read_eeprom(void __iomem *regs, int location, int addr_len)
++static unsigned tulip_read_eeprom(void __iomem *regs, int location,
++				  int addr_len)
+ {
+ 	int i;
+ 	unsigned retval = 0;
+@@ -1783,7 +1784,7 @@ static unsigned __devinit tulip_read_eeprom(void __iomem *regs, int location, in
+ 	return retval;
+ }
+ 
+-static void __devinit de21041_get_srom_info (struct de_private *de)
++static void de21041_get_srom_info(struct de_private *de)
+ {
+ 	unsigned i, sa_offset = 0, ofs;
+ 	u8 ee_data[DE_EEPROM_SIZE + 6] = {};
+@@ -1961,8 +1962,8 @@ static const struct net_device_ops de_netdev_ops = {
+ 	.ndo_validate_addr	= eth_validate_addr,
+ };
+ 
+-static int __devinit de_init_one (struct pci_dev *pdev,
+-				  const struct pci_device_id *ent)
++static int de_init_one(struct pci_dev *pdev,
++		       const struct pci_device_id *ent)
+ {
+ 	struct net_device *dev;
+ 	struct de_private *de;
+@@ -2099,7 +2100,7 @@ static int __devinit de_init_one (struct pci_dev *pdev,
+ 	return rc;
+ }
+ 
+-static void __devexit de_remove_one (struct pci_dev *pdev)
++static void de_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct de_private *de = netdev_priv(dev);
+@@ -2184,7 +2185,7 @@ static struct pci_driver de_driver = {
+ 	.name		= DRV_NAME,
+ 	.id_table	= de_pci_tbl,
+ 	.probe		= de_init_one,
+-	.remove		= __devexit_p(de_remove_one),
++	.remove		= de_remove_one,
+ #ifdef CONFIG_PM
+ 	.suspend	= de_suspend,
+ 	.resume		= de_resume,
+diff --git a/drivers/net/ethernet/dec/tulip/de4x5.c b/drivers/net/ethernet/dec/tulip/de4x5.c
+index f879e9224846..c411aedd8e60 100644
+--- a/drivers/net/ethernet/dec/tulip/de4x5.c
++++ b/drivers/net/ethernet/dec/tulip/de4x5.c
+@@ -479,7 +479,7 @@
+ 
+ #include "de4x5.h"
+ 
+-static const char version[] __devinitconst =
++static const char version[] =
+ 	KERN_INFO "de4x5.c:V0.546 2001/02/22 davies@maniac.ultranet.com\n";
+ 
+ #define c_char const char
+@@ -1092,7 +1092,7 @@ static const struct net_device_ops de4x5_netdev_ops = {
+ };
+ 
+ 
+-static int __devinit
++static int
+ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
+ {
+     char name[DE4X5_NAME_LENGTH + 1];
+@@ -2077,7 +2077,7 @@ static int __init de4x5_eisa_probe (struct device *gendev)
+ 	return status;
+ }
+ 
+-static int __devexit de4x5_eisa_remove (struct device *device)
++static int de4x5_eisa_remove(struct device *device)
+ {
+ 	struct net_device *dev;
+ 	u_long iobase;
+@@ -2104,7 +2104,7 @@ static struct eisa_driver de4x5_eisa_driver = {
+         .driver   = {
+                 .name    = "de4x5",
+                 .probe   = de4x5_eisa_probe,
+-                .remove  = __devexit_p (de4x5_eisa_remove),
++		.remove	 = de4x5_eisa_remove,
+         }
+ };
+ MODULE_DEVICE_TABLE(eisa, de4x5_eisa_ids);
+@@ -2118,7 +2118,7 @@ MODULE_DEVICE_TABLE(eisa, de4x5_eisa_ids);
+ ** DECchips, we can find the base SROM irrespective of the BIOS scan direction.
+ ** For single port cards this is a time waster...
+ */
+-static void __devinit
++static void
+ srom_search(struct net_device *dev, struct pci_dev *pdev)
+ {
+     u_char pb;
+@@ -2192,8 +2192,8 @@ srom_search(struct net_device *dev, struct pci_dev *pdev)
+ ** kernels use the V0.535[n] drivers.
+ */
+ 
+-static int __devinit de4x5_pci_probe (struct pci_dev *pdev,
+-				   const struct pci_device_id *ent)
++static int de4x5_pci_probe(struct pci_dev *pdev,
++			   const struct pci_device_id *ent)
+ {
+ 	u_char pb, pbus = 0, dev_num, dnum = 0, timer;
+ 	u_short vendor, status;
+@@ -2314,7 +2314,7 @@ static int __devinit de4x5_pci_probe (struct pci_dev *pdev,
+ 	return error;
+ }
+ 
+-static void __devexit de4x5_pci_remove (struct pci_dev *pdev)
++static void de4x5_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev;
+ 	u_long iobase;
+@@ -2344,7 +2344,7 @@ static struct pci_driver de4x5_pci_driver = {
+         .name           = "de4x5",
+         .id_table       = de4x5_pci_tbl,
+         .probe          = de4x5_pci_probe,
+-	.remove         = __devexit_p (de4x5_pci_remove),
++	.remove         = de4x5_pci_remove,
+ };
+ 
+ #endif
+diff --git a/drivers/net/ethernet/dec/tulip/dmfe.c b/drivers/net/ethernet/dec/tulip/dmfe.c
+index d23755ea9bc7..56a8fe7d4ef2 100644
+--- a/drivers/net/ethernet/dec/tulip/dmfe.c
++++ b/drivers/net/ethernet/dec/tulip/dmfe.c
+@@ -291,8 +291,8 @@ enum dmfe_CR6_bits {
+ };
+ 
+ /* Global variable declaration ----------------------------- */
+-static int __devinitdata printed_version;
+-static const char version[] __devinitconst =
++static int printed_version;
++static const char version[] =
+ 	"Davicom DM9xxx net driver, version " DRV_VERSION " (" DRV_RELDATE ")";
+ 
+ static int dmfe_debug;
+@@ -367,8 +367,8 @@ static const struct net_device_ops netdev_ops = {
+  *	Search DM910X board ,allocate space and register it
+  */
+ 
+-static int __devinit dmfe_init_one (struct pci_dev *pdev,
+-				    const struct pci_device_id *ent)
++static int dmfe_init_one(struct pci_dev *pdev,
++			 const struct pci_device_id *ent)
+ {
+ 	struct dmfe_board_info *db;	/* board information structure */
+ 	struct net_device *dev;
+@@ -531,7 +531,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev,
+ }
+ 
+ 
+-static void __devexit dmfe_remove_one (struct pci_dev *pdev)
++static void dmfe_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct dmfe_board_info *db = netdev_priv(dev);
+@@ -2187,7 +2187,7 @@ static struct pci_driver dmfe_driver = {
+ 	.name		= "dmfe",
+ 	.id_table	= dmfe_pci_tbl,
+ 	.probe		= dmfe_init_one,
+-	.remove		= __devexit_p(dmfe_remove_one),
++	.remove		= dmfe_remove_one,
+ 	.suspend        = dmfe_suspend,
+ 	.resume         = dmfe_resume
+ };
+diff --git a/drivers/net/ethernet/dec/tulip/eeprom.c b/drivers/net/ethernet/dec/tulip/eeprom.c
+index 44f7e8e82d85..df5a892fb49c 100644
+--- a/drivers/net/ethernet/dec/tulip/eeprom.c
++++ b/drivers/net/ethernet/dec/tulip/eeprom.c
+@@ -26,7 +26,7 @@
+    */
+ 
+ /* Known cards that have old-style EEPROMs. */
+-static struct eeprom_fixup eeprom_fixups[] __devinitdata = {
++static struct eeprom_fixup eeprom_fixups[] = {
+   {"Asante", 0, 0, 0x94, {0x1e00, 0x0000, 0x0800, 0x0100, 0x018c,
+ 			  0x0000, 0x0000, 0xe078, 0x0001, 0x0050, 0x0018 }},
+   {"SMC9332DST", 0, 0, 0xC0, { 0x1e00, 0x0000, 0x0800, 0x041f,
+@@ -79,7 +79,7 @@ static struct eeprom_fixup eeprom_fixups[] __devinitdata = {
+   {NULL}};
+ 
+ 
+-static const char *const block_name[] __devinitconst = {
++static const char *const block_name[] = {
+ 	"21140 non-MII",
+ 	"21140 MII PHY",
+ 	"21142 Serial PHY",
+@@ -102,7 +102,7 @@ static const char *const block_name[] __devinitconst = {
+  * #ifdef __hppa__ should completely optimize this function away for
+  * non-parisc hardware.
+  */
+-static void __devinit tulip_build_fake_mediatable(struct tulip_private *tp)
++static void tulip_build_fake_mediatable(struct tulip_private *tp)
+ {
+ #ifdef CONFIG_GSC
+ 	if (tp->flags & NEEDS_FAKE_MEDIA_TABLE) {
+@@ -140,7 +140,7 @@ static void __devinit tulip_build_fake_mediatable(struct tulip_private *tp)
+ #endif
+ }
+ 
+-void __devinit tulip_parse_eeprom(struct net_device *dev)
++void tulip_parse_eeprom(struct net_device *dev)
+ {
+ 	/*
+ 	  dev is not registered at this point, so logging messages can't
+@@ -339,7 +339,7 @@ void __devinit tulip_parse_eeprom(struct net_device *dev)
+ #define EE_READ_CMD		(6)
+ 
+ /* Note: this routine returns extra data bits for size detection. */
+-int __devinit tulip_read_eeprom(struct net_device *dev, int location, int addr_len)
++int tulip_read_eeprom(struct net_device *dev, int location, int addr_len)
+ {
+ 	int i;
+ 	unsigned retval = 0;
+diff --git a/drivers/net/ethernet/dec/tulip/media.c b/drivers/net/ethernet/dec/tulip/media.c
+index ae937c6749e7..93a4afaa09f1 100644
+--- a/drivers/net/ethernet/dec/tulip/media.c
++++ b/drivers/net/ethernet/dec/tulip/media.c
+@@ -447,7 +447,7 @@ int tulip_check_duplex(struct net_device *dev)
+ 	return 0;
+ }
+ 
+-void __devinit tulip_find_mii (struct net_device *dev, int board_idx)
++void tulip_find_mii(struct net_device *dev, int board_idx)
+ {
+ 	struct tulip_private *tp = netdev_priv(dev);
+ 	int phyn, phy_idx = 0;
+diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c
+index 885700a19978..157c8e6e93f9 100644
+--- a/drivers/net/ethernet/dec/tulip/tulip_core.c
++++ b/drivers/net/ethernet/dec/tulip/tulip_core.c
+@@ -37,7 +37,7 @@
+ #include 
+ #endif
+ 
+-static char version[] __devinitdata =
++static char version[] =
+ 	"Linux Tulip driver version " DRV_VERSION " (" DRV_RELDATE ")\n";
+ 
+ /* A few user-configurable values. */
+@@ -1191,8 +1191,8 @@ static void set_rx_mode(struct net_device *dev)
+ }
+ 
+ #ifdef CONFIG_TULIP_MWI
+-static void __devinit tulip_mwi_config (struct pci_dev *pdev,
+-					struct net_device *dev)
++static void tulip_mwi_config(struct pci_dev *pdev,
++			     struct net_device *dev)
+ {
+ 	struct tulip_private *tp = netdev_priv(dev);
+ 	u8 cache;
+@@ -1301,8 +1301,8 @@ DEFINE_PCI_DEVICE_TABLE(early_486_chipsets) = {
+ 	{ },
+ };
+ 
+-static int __devinit tulip_init_one (struct pci_dev *pdev,
+-				     const struct pci_device_id *ent)
++static int tulip_init_one(struct pci_dev *pdev,
++			  const struct pci_device_id *ent)
+ {
+ 	struct tulip_private *tp;
+ 	/* See note below on the multiport cards. */
+@@ -1927,7 +1927,7 @@ static int tulip_resume(struct pci_dev *pdev)
+ #endif /* CONFIG_PM */
+ 
+ 
+-static void __devexit tulip_remove_one (struct pci_dev *pdev)
++static void tulip_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata (pdev);
+ 	struct tulip_private *tp;
+@@ -1974,7 +1974,7 @@ static struct pci_driver tulip_driver = {
+ 	.name		= DRV_NAME,
+ 	.id_table	= tulip_pci_tbl,
+ 	.probe		= tulip_init_one,
+-	.remove		= __devexit_p(tulip_remove_one),
++	.remove		= tulip_remove_one,
+ #ifdef CONFIG_PM
+ 	.suspend	= tulip_suspend,
+ 	.resume		= tulip_resume,
+diff --git a/drivers/net/ethernet/dec/tulip/uli526x.c b/drivers/net/ethernet/dec/tulip/uli526x.c
+index 75d45f8a37dc..93845afe1cea 100644
+--- a/drivers/net/ethernet/dec/tulip/uli526x.c
++++ b/drivers/net/ethernet/dec/tulip/uli526x.c
+@@ -204,8 +204,8 @@ enum uli526x_CR6_bits {
+ };
+ 
+ /* Global variable declaration ----------------------------- */
+-static int __devinitdata printed_version;
+-static const char version[] __devinitconst =
++static int printed_version;
++static const char version[] =
+ 	"ULi M5261/M5263 net driver, version " DRV_VERSION " (" DRV_RELDATE ")";
+ 
+ static int uli526x_debug;
+@@ -281,8 +281,8 @@ static const struct net_device_ops netdev_ops = {
+  *	Search ULI526X board, allocate space and register it
+  */
+ 
+-static int __devinit uli526x_init_one (struct pci_dev *pdev,
+-				    const struct pci_device_id *ent)
++static int uli526x_init_one(struct pci_dev *pdev,
++			    const struct pci_device_id *ent)
+ {
+ 	struct uli526x_board_info *db;	/* board information structure */
+ 	struct net_device *dev;
+@@ -436,7 +436,7 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev,
+ }
+ 
+ 
+-static void __devexit uli526x_remove_one (struct pci_dev *pdev)
++static void uli526x_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct uli526x_board_info *db = netdev_priv(dev);
+@@ -1788,7 +1788,7 @@ static struct pci_driver uli526x_driver = {
+ 	.name		= "uli526x",
+ 	.id_table	= uli526x_pci_tbl,
+ 	.probe		= uli526x_init_one,
+-	.remove		= __devexit_p(uli526x_remove_one),
++	.remove		= uli526x_remove_one,
+ 	.suspend	= uli526x_suspend,
+ 	.resume		= uli526x_resume,
+ };
+diff --git a/drivers/net/ethernet/dec/tulip/winbond-840.c b/drivers/net/ethernet/dec/tulip/winbond-840.c
+index 7c1ec4d7920b..0a1bda857e76 100644
+--- a/drivers/net/ethernet/dec/tulip/winbond-840.c
++++ b/drivers/net/ethernet/dec/tulip/winbond-840.c
+@@ -236,7 +236,7 @@ struct pci_id_info {
+         int drv_flags;		/* Driver use, intended as capability flags. */
+ };
+ 
+-static const struct pci_id_info pci_id_tbl[] __devinitconst = {
++static const struct pci_id_info pci_id_tbl[] = {
+ 	{ 				/* Sometime a Level-One switch card. */
+ 	  "Winbond W89c840",	CanHaveMII | HasBrokenTx | FDXOnNoMII},
+ 	{ "Winbond W89c840",	CanHaveMII | HasBrokenTx},
+@@ -358,8 +358,8 @@ static const struct net_device_ops netdev_ops = {
+ 	.ndo_validate_addr	= eth_validate_addr,
+ };
+ 
+-static int __devinit w840_probe1 (struct pci_dev *pdev,
+-				  const struct pci_device_id *ent)
++static int w840_probe1(struct pci_dev *pdev,
++		       const struct pci_device_id *ent)
+ {
+ 	struct net_device *dev;
+ 	struct netdev_private *np;
+@@ -1532,7 +1532,7 @@ static int netdev_close(struct net_device *dev)
+ 	return 0;
+ }
+ 
+-static void __devexit w840_remove1 (struct pci_dev *pdev)
++static void w840_remove1(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 
+@@ -1647,7 +1647,7 @@ static struct pci_driver w840_driver = {
+ 	.name		= DRV_NAME,
+ 	.id_table	= w840_pci_tbl,
+ 	.probe		= w840_probe1,
+-	.remove		= __devexit_p(w840_remove1),
++	.remove		= w840_remove1,
+ #ifdef CONFIG_PM
+ 	.suspend	= w840_suspend,
+ 	.resume		= w840_resume,
+diff --git a/drivers/net/ethernet/dec/tulip/xircom_cb.c b/drivers/net/ethernet/dec/tulip/xircom_cb.c
+index 138bf83bc98e..88feced9a629 100644
+--- a/drivers/net/ethernet/dec/tulip/xircom_cb.c
++++ b/drivers/net/ethernet/dec/tulip/xircom_cb.c
+@@ -148,7 +148,7 @@ static struct pci_driver xircom_ops = {
+ 	.name		= "xircom_cb",
+ 	.id_table	= xircom_pci_table,
+ 	.probe		= xircom_probe,
+-	.remove		= __devexit_p(xircom_remove),
++	.remove		= xircom_remove,
+ };
+ 
+ 
+@@ -190,7 +190,7 @@ static const struct net_device_ops netdev_ops = {
+          first two packets that get send, and pump hates that.
+ 
+  */
+-static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_id *id)
++static int xircom_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ 	struct device *d = &pdev->dev;
+ 	struct net_device *dev = NULL;
+@@ -312,7 +312,7 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_
+  Interrupts and such are already stopped in the "ifconfig ethX down"
+  code.
+  */
+-static void __devexit xircom_remove(struct pci_dev *pdev)
++static void xircom_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct xircom_private *card = netdev_priv(dev);

commit f3f9e50927b6c4791bf81dacae8bf5e7832b535d
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:40 2012 -0500
+
+    smsc9420: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Steve Glendinning 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/smsc/smsc9420.c b/drivers/net/ethernet/smsc/smsc9420.c
+index 1fcd914ec39b..3c586585e1b3 100644
+--- a/drivers/net/ethernet/smsc/smsc9420.c
++++ b/drivers/net/ethernet/smsc/smsc9420.c
+@@ -1577,7 +1577,7 @@ static const struct net_device_ops smsc9420_netdev_ops = {
+ #endif /* CONFIG_NET_POLL_CONTROLLER */
+ };
+ 
+-static int __devinit
++static int
+ smsc9420_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ 	struct net_device *dev;
+@@ -1702,7 +1702,7 @@ smsc9420_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	return -ENODEV;
+ }
+ 
+-static void __devexit smsc9420_remove(struct pci_dev *pdev)
++static void smsc9420_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev;
+ 	struct smsc9420_pdata *pd;
+@@ -1736,7 +1736,7 @@ static struct pci_driver smsc9420_driver = {
+ 	.name = DRV_NAME,
+ 	.id_table = smsc9420_id_table,
+ 	.probe = smsc9420_probe,
+-	.remove = __devexit_p(smsc9420_remove),
++	.remove = smsc9420_remove,
+ #ifdef CONFIG_PM
+ 	.suspend = smsc9420_suspend,
+ 	.resume = smsc9420_resume,

commit 9f1e13db5987c440a76c496d83c773c13afb557e
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:39 2012 -0500
+
+    smc911x: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c
+index 990f57467a15..59a6f88da867 100644
+--- a/drivers/net/ethernet/smsc/smc911x.c
++++ b/drivers/net/ethernet/smsc/smc911x.c
+@@ -1712,7 +1712,7 @@ static const struct ethtool_ops smc911x_ethtool_ops = {
+  * This routine has a simple purpose -- make the SMC chip generate an
+  * interrupt, so an auto-detect routine can detect it, and find the IRQ,
+  */
+-static int __devinit smc911x_findirq(struct net_device *dev)
++static int smc911x_findirq(struct net_device *dev)
+ {
+ 	struct smc911x_local *lp = netdev_priv(dev);
+ 	int timeout = 20;
+@@ -1790,7 +1790,7 @@ static const struct net_device_ops smc911x_netdev_ops = {
+  * o  actually GRAB the irq.
+  * o  GRAB the region
+  */
+-static int __devinit smc911x_probe(struct net_device *dev)
++static int smc911x_probe(struct net_device *dev)
+ {
+ 	struct smc911x_local *lp = netdev_priv(dev);
+ 	int i, retval;
+@@ -2030,7 +2030,7 @@ static int __devinit smc911x_probe(struct net_device *dev)
+  *	 0 --> there is a device
+  *	 anything else, error
+  */
+-static int __devinit smc911x_drv_probe(struct platform_device *pdev)
++static int smc911x_drv_probe(struct platform_device *pdev)
+ {
+ 	struct net_device *ndev;
+ 	struct resource *res;
+@@ -2105,7 +2105,7 @@ static int __devinit smc911x_drv_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit smc911x_drv_remove(struct platform_device *pdev)
++static int smc911x_drv_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *ndev = platform_get_drvdata(pdev);
+ 	struct smc911x_local *lp = netdev_priv(ndev);
+@@ -2176,7 +2176,7 @@ static int smc911x_drv_resume(struct platform_device *dev)
+ 
+ static struct platform_driver smc911x_driver = {
+ 	.probe		 = smc911x_drv_probe,
+-	.remove	 = __devexit_p(smc911x_drv_remove),
++	.remove	 = smc911x_drv_remove,
+ 	.suspend	 = smc911x_drv_suspend,
+ 	.resume	 = smc911x_drv_resume,
+ 	.driver	 = {

commit 8489ec1f97006495d9eb06a90f1ffcbfeb879aab
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:38 2012 -0500
+
+    smsc911x: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Steve Glendinning 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
+index cc025620b681..c52a5cefa192 100644
+--- a/drivers/net/ethernet/smsc/smsc911x.c
++++ b/drivers/net/ethernet/smsc/smsc911x.c
+@@ -1031,7 +1031,7 @@ static int smsc911x_mii_probe(struct net_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devinit smsc911x_mii_init(struct platform_device *pdev,
++static int smsc911x_mii_init(struct platform_device *pdev,
+ 				       struct net_device *dev)
+ {
+ 	struct smsc911x_data *pdata = netdev_priv(dev);
+@@ -2087,7 +2087,7 @@ static const struct net_device_ops smsc911x_netdev_ops = {
+ };
+ 
+ /* copies the current mac address from hardware to dev->dev_addr */
+-static void __devinit smsc911x_read_mac_address(struct net_device *dev)
++static void smsc911x_read_mac_address(struct net_device *dev)
+ {
+ 	struct smsc911x_data *pdata = netdev_priv(dev);
+ 	u32 mac_high16 = smsc911x_mac_read(pdata, ADDRH);
+@@ -2102,7 +2102,7 @@ static void __devinit smsc911x_read_mac_address(struct net_device *dev)
+ }
+ 
+ /* Initializing private device structures, only called from probe */
+-static int __devinit smsc911x_init(struct net_device *dev)
++static int smsc911x_init(struct net_device *dev)
+ {
+ 	struct smsc911x_data *pdata = netdev_priv(dev);
+ 	unsigned int byte_test, mask;
+@@ -2239,7 +2239,7 @@ static int __devinit smsc911x_init(struct net_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devexit smsc911x_drv_remove(struct platform_device *pdev)
++static int smsc911x_drv_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *dev;
+ 	struct smsc911x_data *pdata;
+@@ -2296,7 +2296,7 @@ static const struct smsc911x_ops shifted_smsc911x_ops = {
+ };
+ 
+ #ifdef CONFIG_OF
+-static int __devinit smsc911x_probe_config_dt(
++static int smsc911x_probe_config_dt(
+ 				struct smsc911x_platform_config *config,
+ 				struct device_node *np)
+ {
+@@ -2346,7 +2346,7 @@ static inline int smsc911x_probe_config_dt(
+ }
+ #endif /* CONFIG_OF */
+ 
+-static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
++static int smsc911x_drv_probe(struct platform_device *pdev)
+ {
+ 	struct device_node *np = pdev->dev.of_node;
+ 	struct net_device *dev;
+@@ -2584,7 +2584,7 @@ MODULE_DEVICE_TABLE(of, smsc911x_dt_ids);
+ 
+ static struct platform_driver smsc911x_driver = {
+ 	.probe = smsc911x_drv_probe,
+-	.remove = __devexit_p(smsc911x_drv_remove),
++	.remove = smsc911x_drv_remove,
+ 	.driver = {
+ 		.name	= SMSC_CHIPNAME,
+ 		.owner	= THIS_MODULE,

commit 1e48fea4805db6766708d9387f8dc1c5d5226263
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:37 2012 -0500
+
+    smc91x: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Nicolas Pitre 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c
+index f516e5a71c53..b085692f3893 100644
+--- a/drivers/net/ethernet/smsc/smc91x.c
++++ b/drivers/net/ethernet/smsc/smc91x.c
+@@ -1779,7 +1779,7 @@ static const struct net_device_ops smc_netdev_ops = {
+  * I just deleted auto_irq.c, since it was never built...
+  *   --jgarzik
+  */
+-static int __devinit smc_findirq(struct smc_local *lp)
++static int smc_findirq(struct smc_local *lp)
+ {
+ 	void __iomem *ioaddr = lp->base;
+ 	int timeout = 20;
+@@ -1853,7 +1853,7 @@ static int __devinit smc_findirq(struct smc_local *lp)
+  * o  actually GRAB the irq.
+  * o  GRAB the region
+  */
+-static int __devinit smc_probe(struct net_device *dev, void __iomem *ioaddr,
++static int smc_probe(struct net_device *dev, void __iomem *ioaddr,
+ 			    unsigned long irq_flags)
+ {
+ 	struct smc_local *lp = netdev_priv(dev);
+@@ -2201,7 +2201,7 @@ static void smc_release_datacs(struct platform_device *pdev, struct net_device *
+  *	0 --> there is a device
+  *	anything else, error
+  */
+-static int __devinit smc_drv_probe(struct platform_device *pdev)
++static int smc_drv_probe(struct platform_device *pdev)
+ {
+ 	struct smc91x_platdata *pd = pdev->dev.platform_data;
+ 	struct smc_local *lp;
+@@ -2314,7 +2314,7 @@ static int __devinit smc_drv_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit smc_drv_remove(struct platform_device *pdev)
++static int smc_drv_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *ndev = platform_get_drvdata(pdev);
+ 	struct smc_local *lp = netdev_priv(ndev);
+@@ -2397,7 +2397,7 @@ static struct dev_pm_ops smc_drv_pm_ops = {
+ 
+ static struct platform_driver smc_driver = {
+ 	.probe		= smc_drv_probe,
+-	.remove		= __devexit_p(smc_drv_remove),
++	.remove		= smc_drv_remove,
+ 	.driver		= {
+ 		.name	= CARDNAME,
+ 		.owner	= THIS_MODULE,

commit 369e12313dbf7a08fa9ed50c07edd4b5ad399251
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:36 2012 -0500
+
+    sis900: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Daniele Venzano 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c
+index edf5edb13140..88c6c4243cb3 100644
+--- a/drivers/net/ethernet/sis/sis900.c
++++ b/drivers/net/ethernet/sis/sis900.c
+@@ -81,7 +81,7 @@
+ #define SIS900_MODULE_NAME "sis900"
+ #define SIS900_DRV_VERSION "v1.08.10 Apr. 2 2006"
+ 
+-static const char version[] __devinitconst =
++static const char version[] =
+ 	KERN_INFO "sis900.c: " SIS900_DRV_VERSION "\n";
+ 
+ static int max_interrupt_work = 40;
+@@ -251,7 +251,8 @@ static const struct ethtool_ops sis900_ethtool_ops;
+  *	@net_dev->perm_addr.
+  */
+ 
+-static int __devinit sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev)
++static int sis900_get_mac_addr(struct pci_dev *pci_dev,
++			       struct net_device *net_dev)
+ {
+ 	struct sis900_private *sis_priv = netdev_priv(net_dev);
+ 	void __iomem *ioaddr = sis_priv->ioaddr;
+@@ -287,8 +288,8 @@ static int __devinit sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_de
+  *	@net_dev->perm_addr.
+  */
+ 
+-static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev,
+-					struct net_device *net_dev)
++static int sis630e_get_mac_addr(struct pci_dev *pci_dev,
++				struct net_device *net_dev)
+ {
+ 	struct pci_dev *isa_bridge = NULL;
+ 	u8 reg;
+@@ -330,8 +331,8 @@ static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev,
+  *	@net_dev->dev_addr and @net_dev->perm_addr.
+  */
+ 
+-static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev,
+-					struct net_device *net_dev)
++static int sis635_get_mac_addr(struct pci_dev *pci_dev,
++			       struct net_device *net_dev)
+ {
+ 	struct sis900_private *sis_priv = netdev_priv(net_dev);
+ 	void __iomem *ioaddr = sis_priv->ioaddr;
+@@ -377,8 +378,8 @@ static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev,
+  *	MAC address is read into @net_dev->dev_addr and @net_dev->perm_addr.
+  */
+ 
+-static int __devinit sis96x_get_mac_addr(struct pci_dev * pci_dev,
+-					struct net_device *net_dev)
++static int sis96x_get_mac_addr(struct pci_dev *pci_dev,
++			       struct net_device *net_dev)
+ {
+ 	struct sis900_private *sis_priv = netdev_priv(net_dev);
+ 	void __iomem *ioaddr = sis_priv->ioaddr;
+@@ -433,7 +434,7 @@ static const struct net_device_ops sis900_netdev_ops = {
+  *	ie: sis900_open(), sis900_start_xmit(), sis900_close(), etc.
+  */
+ 
+-static int __devinit sis900_probe(struct pci_dev *pci_dev,
++static int sis900_probe(struct pci_dev *pci_dev,
+ 				const struct pci_device_id *pci_id)
+ {
+ 	struct sis900_private *sis_priv;
+@@ -605,7 +606,7 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
+  *	return error if it failed to found.
+  */
+ 
+-static int __devinit sis900_mii_probe(struct net_device * net_dev)
++static int sis900_mii_probe(struct net_device *net_dev)
+ {
+ 	struct sis900_private *sis_priv = netdev_priv(net_dev);
+ 	const char *dev_name = pci_name(sis_priv->pci_dev);
+@@ -824,7 +825,7 @@ static void sis900_set_capability(struct net_device *net_dev, struct mii_phy *ph
+  *	Note that location is in word (16 bits) unit
+  */
+ 
+-static u16 __devinit read_eeprom(void __iomem *ioaddr, int location)
++static u16 read_eeprom(void __iomem *ioaddr, int location)
+ {
+ 	u32 read_cmd = location | EEread;
+ 	int i;
+@@ -2410,7 +2411,7 @@ static void sis900_reset(struct net_device *net_dev)
+  *	remove and release SiS900 net device
+  */
+ 
+-static void __devexit sis900_remove(struct pci_dev *pci_dev)
++static void sis900_remove(struct pci_dev *pci_dev)
+ {
+ 	struct net_device *net_dev = pci_get_drvdata(pci_dev);
+ 	struct sis900_private *sis_priv = netdev_priv(net_dev);
+@@ -2496,7 +2497,7 @@ static struct pci_driver sis900_pci_driver = {
+ 	.name		= SIS900_MODULE_NAME,
+ 	.id_table	= sis900_pci_tbl,
+ 	.probe		= sis900_probe,
+-	.remove		= __devexit_p(sis900_remove),
++	.remove		= sis900_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= sis900_suspend,
+ 	.resume		= sis900_resume,

commit fe80f565d5007716c60d0a82497bed1d537a09a3
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:35 2012 -0500
+
+    sis190: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Francois Romieu 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/sis/sis190.c b/drivers/net/ethernet/sis/sis190.c
+index d8166012b7d4..c114c4f9cea8 100644
+--- a/drivers/net/ethernet/sis/sis190.c
++++ b/drivers/net/ethernet/sis/sis190.c
+@@ -415,7 +415,7 @@ static u16 mdio_read_latched(void __iomem *ioaddr, int phy_id, int reg)
+ 	return mdio_read(ioaddr, phy_id, reg);
+ }
+ 
+-static u16 __devinit sis190_read_eeprom(void __iomem *ioaddr, u32 reg)
++static u16 sis190_read_eeprom(void __iomem *ioaddr, u32 reg)
+ {
+ 	u16 data = 0xffff;
+ 	unsigned int i;
+@@ -1379,7 +1379,7 @@ static void sis190_mii_probe_88e1111_fixup(struct sis190_private *tp)
+  *	Identify and set current phy if found one,
+  *	return error if it failed to found.
+  */
+-static int __devinit sis190_mii_probe(struct net_device *dev)
++static int sis190_mii_probe(struct net_device *dev)
+ {
+ 	struct sis190_private *tp = netdev_priv(dev);
+ 	struct mii_if_info *mii_if = &tp->mii_if;
+@@ -1451,7 +1451,7 @@ static void sis190_release_board(struct pci_dev *pdev)
+ 	free_netdev(dev);
+ }
+ 
+-static struct net_device * __devinit sis190_init_board(struct pci_dev *pdev)
++static struct net_device *sis190_init_board(struct pci_dev *pdev)
+ {
+ 	struct sis190_private *tp;
+ 	struct net_device *dev;
+@@ -1573,7 +1573,7 @@ static void sis190_set_rgmii(struct sis190_private *tp, u8 reg)
+ 	tp->features |= (reg & 0x80) ? F_HAS_RGMII : 0;
+ }
+ 
+-static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev,
++static int sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev,
+ 						     struct net_device *dev)
+ {
+ 	struct sis190_private *tp = netdev_priv(dev);
+@@ -1615,10 +1615,10 @@ static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev,
+  *	APC CMOS RAM is accessed through ISA bridge.
+  *	MAC address is read into @net_dev->dev_addr.
+  */
+-static int __devinit sis190_get_mac_addr_from_apc(struct pci_dev *pdev,
++static int sis190_get_mac_addr_from_apc(struct pci_dev *pdev,
+ 						  struct net_device *dev)
+ {
+-	static const u16 __devinitconst ids[] = { 0x0965, 0x0966, 0x0968 };
++	static const u16 ids[] = { 0x0965, 0x0966, 0x0968 };
+ 	struct sis190_private *tp = netdev_priv(dev);
+ 	struct pci_dev *isa_bridge;
+ 	u8 reg, tmp8;
+@@ -1693,7 +1693,7 @@ static inline void sis190_init_rxfilter(struct net_device *dev)
+ 	SIS_PCI_COMMIT();
+ }
+ 
+-static int __devinit sis190_get_mac_addr(struct pci_dev *pdev,
++static int sis190_get_mac_addr(struct pci_dev *pdev,
+ 					 struct net_device *dev)
+ {
+ 	int rc;
+@@ -1845,7 +1845,7 @@ static const struct net_device_ops sis190_netdev_ops = {
+ #endif
+ };
+ 
+-static int __devinit sis190_init_one(struct pci_dev *pdev,
++static int sis190_init_one(struct pci_dev *pdev,
+ 				     const struct pci_device_id *ent)
+ {
+ 	static int printed_version = 0;
+@@ -1916,7 +1916,7 @@ static int __devinit sis190_init_one(struct pci_dev *pdev,
+ 	goto out;
+ }
+ 
+-static void __devexit sis190_remove_one(struct pci_dev *pdev)
++static void sis190_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct sis190_private *tp = netdev_priv(dev);
+@@ -1932,7 +1932,7 @@ static struct pci_driver sis190_pci_driver = {
+ 	.name		= DRV_NAME,
+ 	.id_table	= sis190_pci_tbl,
+ 	.probe		= sis190_init_one,
+-	.remove		= __devexit_p(sis190_remove_one),
++	.remove		= sis190_remove_one,
+ };
+ 
+ static int __init sis190_init_module(void)

commit 979857bbcfd493ce23f4865c7eb11c8853f065a4
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:34 2012 -0500
+
+    stmmac: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Giuseppe Cavallaro 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+index 1f069b0f6af5..5cf9eb6dd65f 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+@@ -61,7 +61,7 @@ static void stmmac_default_data(void)
+  * matches the device. The probe functions returns zero when the driver choose
+  * to take "ownership" of the device or an error code(-ve no) otherwise.
+  */
+-static int __devinit stmmac_pci_probe(struct pci_dev *pdev,
++static int stmmac_pci_probe(struct pci_dev *pdev,
+ 				      const struct pci_device_id *id)
+ {
+ 	int ret = 0;
+@@ -130,7 +130,7 @@ static int __devinit stmmac_pci_probe(struct pci_dev *pdev,
+  * Description: this function calls the main to free the net resources
+  * and releases the PCI resources.
+  */
+-static void __devexit stmmac_pci_remove(struct pci_dev *pdev)
++static void stmmac_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *ndev = pci_get_drvdata(pdev);
+ 	struct stmmac_priv *priv = netdev_priv(ndev);
+@@ -182,7 +182,7 @@ struct pci_driver stmmac_pci_driver = {
+ 	.name = STMMAC_RESOURCE_NAME,
+ 	.id_table = stmmac_id_table,
+ 	.probe = stmmac_pci_probe,
+-	.remove = __devexit_p(stmmac_pci_remove),
++	.remove = stmmac_pci_remove,
+ #ifdef CONFIG_PM
+ 	.suspend = stmmac_pci_suspend,
+ 	.resume = stmmac_pci_resume,
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+index ed112b55ae7f..b77b913df116 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -29,7 +29,7 @@
+ #include "stmmac.h"
+ 
+ #ifdef CONFIG_OF
+-static int __devinit stmmac_probe_config_dt(struct platform_device *pdev,
++static int stmmac_probe_config_dt(struct platform_device *pdev,
+ 					    struct plat_stmmacenet_data *plat,
+ 					    const char **mac)
+ {
+@@ -59,7 +59,7 @@ static int __devinit stmmac_probe_config_dt(struct platform_device *pdev,
+ 	return 0;
+ }
+ #else
+-static int __devinit stmmac_probe_config_dt(struct platform_device *pdev,
++static int stmmac_probe_config_dt(struct platform_device *pdev,
+ 					    struct plat_stmmacenet_data *plat,
+ 					    const char **mac)
+ {
+@@ -74,7 +74,7 @@ static int __devinit stmmac_probe_config_dt(struct platform_device *pdev,
+  * the necessary resources and invokes the main to init
+  * the net device, register the mdio bus etc.
+  */
+-static int __devinit stmmac_pltfr_probe(struct platform_device *pdev)
++static int stmmac_pltfr_probe(struct platform_device *pdev)
+ {
+ 	int ret = 0;
+ 	struct resource *res;

commit 58af79f06236164ce10e9b08aac12945496b4f5e
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:33 2012 -0500
+
+    sc92031: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/silan/sc92031.c b/drivers/net/ethernet/silan/sc92031.c
+index 32e55664df6e..2103449a2dfe 100644
+--- a/drivers/net/ethernet/silan/sc92031.c
++++ b/drivers/net/ethernet/silan/sc92031.c
+@@ -1395,7 +1395,7 @@ static const struct net_device_ops sc92031_netdev_ops = {
+ #endif
+ };
+ 
+-static int __devinit sc92031_probe(struct pci_dev *pdev,
++static int sc92031_probe(struct pci_dev *pdev,
+ 		const struct pci_device_id *id)
+ {
+ 	int err;
+@@ -1489,7 +1489,7 @@ static int __devinit sc92031_probe(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit sc92031_remove(struct pci_dev *pdev)
++static void sc92031_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct sc92031_priv *priv = netdev_priv(dev);
+@@ -1574,7 +1574,7 @@ static struct pci_driver sc92031_pci_driver = {
+ 	.name		= SC92031_NAME,
+ 	.id_table	= sc92031_pci_device_id_table,
+ 	.probe		= sc92031_probe,
+-	.remove		= __devexit_p(sc92031_remove),
++	.remove		= sc92031_remove,
+ 	.suspend	= sc92031_suspend,
+ 	.resume		= sc92031_resume,
+ };

commit 87d1fc11303473a2bd74eedb8377ff80d853972b
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:32 2012 -0500
+
+    sfc: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Solarflare linux maintainers 
+    Cc: Ben Hutchings 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
+index d858f310b2b2..e95cc7bb2e02 100644
+--- a/drivers/net/ethernet/sfc/efx.c
++++ b/drivers/net/ethernet/sfc/efx.c
+@@ -2669,7 +2669,7 @@ static int efx_pci_probe_main(struct efx_nic *efx)
+  * transmission; this is left to the first time one of the network
+  * interfaces is brought up (i.e. efx_net_open).
+  */
+-static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
++static int efx_pci_probe(struct pci_dev *pci_dev,
+ 				   const struct pci_device_id *entry)
+ {
+ 	struct net_device *net_dev;

commit 5911ce0d99b37a902b2c85e172139ce76c8fc583
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:31 2012 -0500
+
+    seeq: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Russell King 
+    Cc: linux-arm-kernel@lists.infradead.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/seeq/ether3.c b/drivers/net/ethernet/seeq/ether3.c
+index 72a01748d1b1..3aca57853ed4 100644
+--- a/drivers/net/ethernet/seeq/ether3.c
++++ b/drivers/net/ethernet/seeq/ether3.c
+@@ -67,7 +67,7 @@
+ #include 
+ #include 
+ 
+-static char version[] __devinitdata = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n";
++static char version[] = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n";
+ 
+ #include "ether3.h"
+ 
+@@ -194,7 +194,7 @@ static inline void ether3_ledon(struct net_device *dev)
+  * Read the ethernet address string from the on board rom.
+  * This is an ascii string!!!
+  */
+-static int __devinit
++static int
+ ether3_addr(char *addr, struct expansion_card *ec)
+ {
+ 	struct in_chunk_dir cd;
+@@ -219,7 +219,7 @@ ether3_addr(char *addr, struct expansion_card *ec)
+ 
+ /* --------------------------------------------------------------------------- */
+ 
+-static int __devinit
++static int
+ ether3_ramtest(struct net_device *dev, unsigned char byte)
+ {
+ 	unsigned char *buffer = kmalloc(RX_END, GFP_KERNEL);
+@@ -268,7 +268,7 @@ ether3_ramtest(struct net_device *dev, unsigned char byte)
+ 
+ /* ------------------------------------------------------------------------------- */
+ 
+-static int __devinit ether3_init_2(struct net_device *dev)
++static int ether3_init_2(struct net_device *dev)
+ {
+ 	int i;
+ 
+@@ -742,7 +742,7 @@ static void ether3_tx(struct net_device *dev)
+ 	}
+ }
+ 
+-static void __devinit ether3_banner(void)
++static void ether3_banner(void)
+ {
+ 	static unsigned version_printed = 0;
+ 
+@@ -761,7 +761,7 @@ static const struct net_device_ops ether3_netdev_ops = {
+ 	.ndo_set_mac_address	= eth_mac_addr,
+ };
+ 
+-static int __devinit
++static int
+ ether3_probe(struct expansion_card *ec, const struct ecard_id *id)
+ {
+ 	const struct ether3_data *data = id->data;
+@@ -858,7 +858,7 @@ ether3_probe(struct expansion_card *ec, const struct ecard_id *id)
+ 	return ret;
+ }
+ 
+-static void __devexit ether3_remove(struct expansion_card *ec)
++static void ether3_remove(struct expansion_card *ec)
+ {
+ 	struct net_device *dev = ecard_get_drvdata(ec);
+ 
+@@ -888,7 +888,7 @@ static const struct ecard_id ether3_ids[] = {
+ 
+ static struct ecard_driver ether3_driver = {
+ 	.probe		= ether3_probe,
+-	.remove		= __devexit_p(ether3_remove),
++	.remove		= ether3_remove,
+ 	.id_table	= ether3_ids,
+ 	.drv = {
+ 		.name	= "ether3",
+diff --git a/drivers/net/ethernet/seeq/sgiseeq.c b/drivers/net/ethernet/seeq/sgiseeq.c
+index 4d15bf413bdc..0fde9ca28269 100644
+--- a/drivers/net/ethernet/seeq/sgiseeq.c
++++ b/drivers/net/ethernet/seeq/sgiseeq.c
+@@ -721,7 +721,7 @@ static const struct net_device_ops sgiseeq_netdev_ops = {
+ 	.ndo_validate_addr	= eth_validate_addr,
+ };
+ 
+-static int __devinit sgiseeq_probe(struct platform_device *pdev)
++static int sgiseeq_probe(struct platform_device *pdev)
+ {
+ 	struct sgiseeq_platform_data *pd = pdev->dev.platform_data;
+ 	struct hpc3_regs *hpcregs = pd->hpc;

commit f1e242648bce83ec67f8bc047e1ad1ade7b85725
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:30 2012 -0500
+
+    r6040: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Florian Fainelli 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/rdc/r6040.c b/drivers/net/ethernet/rdc/r6040.c
+index 557a26545d75..ae27e4463f97 100644
+--- a/drivers/net/ethernet/rdc/r6040.c
++++ b/drivers/net/ethernet/rdc/r6040.c
+@@ -206,7 +206,7 @@ struct r6040_private {
+ 	int old_duplex;
+ };
+ 
+-static char version[] __devinitdata = DRV_NAME
++static char version[] = DRV_NAME
+ 	": RDC R6040 NAPI net driver,"
+ 	"version "DRV_VERSION " (" DRV_RELDATE ")";
+ 
+@@ -1073,7 +1073,7 @@ static int r6040_mii_probe(struct net_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devinit r6040_init_one(struct pci_dev *pdev,
++static int r6040_init_one(struct pci_dev *pdev,
+ 					 const struct pci_device_id *ent)
+ {
+ 	struct net_device *dev;
+@@ -1246,7 +1246,7 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit r6040_remove_one(struct pci_dev *pdev)
++static void r6040_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct r6040_private *lp = netdev_priv(dev);
+@@ -1274,7 +1274,7 @@ static struct pci_driver r6040_driver = {
+ 	.name		= DRV_NAME,
+ 	.id_table	= r6040_pci_tbl,
+ 	.probe		= r6040_init_one,
+-	.remove		= __devexit_p(r6040_remove_one),
++	.remove		= r6040_remove_one,
+ };
+ 
+ module_pci_driver(r6040_driver);

commit b4e54a9442c741e09f7df92f1f62e282a9c3dd05
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:29 2012 -0500
+
+    8139too: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c
+index 3ed7add23c12..5dc161630127 100644
+--- a/drivers/net/ethernet/realtek/8139too.c
++++ b/drivers/net/ethernet/realtek/8139too.c
+@@ -228,7 +228,7 @@ typedef enum {
+ static const struct {
+ 	const char *name;
+ 	u32 hw_flags;
+-} board_info[] __devinitconst = {
++} board_info[] = {
+ 	{ "RealTek RTL8139", RTL8139_CAPS },
+ 	{ "RealTek RTL8129", RTL8129_CAPS },
+ };
+@@ -748,7 +748,7 @@ static void rtl8139_chip_reset (void __iomem *ioaddr)
+ }
+ 
+ 
+-static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev)
++static struct net_device *rtl8139_init_board(struct pci_dev *pdev)
+ {
+ 	struct device *d = &pdev->dev;
+ 	void __iomem *ioaddr;
+@@ -935,8 +935,8 @@ static const struct net_device_ops rtl8139_netdev_ops = {
+ 	.ndo_set_features	= rtl8139_set_features,
+ };
+ 
+-static int __devinit rtl8139_init_one (struct pci_dev *pdev,
+-				       const struct pci_device_id *ent)
++static int rtl8139_init_one(struct pci_dev *pdev,
++			    const struct pci_device_id *ent)
+ {
+ 	struct net_device *dev = NULL;
+ 	struct rtl8139_private *tp;
+@@ -1103,7 +1103,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
+ }
+ 
+ 
+-static void __devexit rtl8139_remove_one (struct pci_dev *pdev)
++static void rtl8139_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata (pdev);
+ 	struct rtl8139_private *tp = netdev_priv(dev);
+@@ -1141,7 +1141,7 @@ static void __devexit rtl8139_remove_one (struct pci_dev *pdev)
+ #define EE_READ_CMD		(6)
+ #define EE_ERASE_CMD	(7)
+ 
+-static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len)
++static int read_eeprom(void __iomem *ioaddr, int location, int addr_len)
+ {
+ 	int i;
+ 	unsigned retval = 0;
+@@ -2652,7 +2652,7 @@ static struct pci_driver rtl8139_pci_driver = {
+ 	.name		= DRV_NAME,
+ 	.id_table	= rtl8139_pci_tbl,
+ 	.probe		= rtl8139_init_one,
+-	.remove		= __devexit_p(rtl8139_remove_one),
++	.remove		= rtl8139_remove_one,
+ #ifdef CONFIG_PM
+ 	.suspend	= rtl8139_suspend,
+ 	.resume		= rtl8139_resume,

commit baf63293532a0c23478c46df959ad11f93a0b904
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:28 2012 -0500
+
+    r8169: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Realtek linux nic maintainers 
+    Cc: Francois Romieu 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
+index 248f883d4434..891feee49ba9 100644
+--- a/drivers/net/ethernet/realtek/r8169.c
++++ b/drivers/net/ethernet/realtek/r8169.c
+@@ -3828,7 +3828,7 @@ static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp)
+ 	}
+ }
+ 
+-static void __devinit rtl_init_mdio_ops(struct rtl8169_private *tp)
++static void rtl_init_mdio_ops(struct rtl8169_private *tp)
+ {
+ 	struct mdio_ops *ops = &tp->mdio_ops;
+ 
+@@ -4080,7 +4080,7 @@ static void rtl_pll_power_up(struct rtl8169_private *tp)
+ 	rtl_generic_op(tp, tp->pll_power_ops.up);
+ }
+ 
+-static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp)
++static void rtl_init_pll_power_ops(struct rtl8169_private *tp)
+ {
+ 	struct pll_power_ops *ops = &tp->pll_power_ops;
+ 
+@@ -4274,7 +4274,7 @@ static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp)
+ 	RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
+ }
+ 
+-static void __devinit rtl_init_jumbo_ops(struct rtl8169_private *tp)
++static void rtl_init_jumbo_ops(struct rtl8169_private *tp)
+ {
+ 	struct jumbo_ops *ops = &tp->jumbo_ops;
+ 
+@@ -4715,7 +4715,7 @@ static u32 r8402_csi_read(struct rtl8169_private *tp, int addr)
+ 		RTL_R32(CSIDR) : ~0;
+ }
+ 
+-static void __devinit rtl_init_csi_ops(struct rtl8169_private *tp)
++static void rtl_init_csi_ops(struct rtl8169_private *tp)
+ {
+ 	struct csi_ops *ops = &tp->csi_ops;
+ 
+@@ -6610,7 +6610,7 @@ static void rtl_shutdown(struct pci_dev *pdev)
+ 	pm_runtime_put_noidle(d);
+ }
+ 
+-static void __devexit rtl_remove_one(struct pci_dev *pdev)
++static void rtl_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct rtl8169_private *tp = netdev_priv(dev);
+@@ -6730,7 +6730,7 @@ DECLARE_RTL_COND(rtl_rxtx_empty_cond)
+ 	return (RTL_R8(MCU) & RXTX_EMPTY) == RXTX_EMPTY;
+ }
+ 
+-static void __devinit rtl_hw_init_8168g(struct rtl8169_private *tp)
++static void rtl_hw_init_8168g(struct rtl8169_private *tp)
+ {
+ 	void __iomem *ioaddr = tp->mmio_addr;
+ 	u32 data;
+@@ -6764,7 +6764,7 @@ static void __devinit rtl_hw_init_8168g(struct rtl8169_private *tp)
+ 		return;
+ }
+ 
+-static void __devinit rtl_hw_initialize(struct rtl8169_private *tp)
++static void rtl_hw_initialize(struct rtl8169_private *tp)
+ {
+ 	switch (tp->mac_version) {
+ 	case RTL_GIGA_MAC_VER_40:
+@@ -6777,7 +6777,7 @@ static void __devinit rtl_hw_initialize(struct rtl8169_private *tp)
+ 	}
+ }
+ 
+-static int __devinit
++static int
+ rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ 	const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
+@@ -7028,7 +7028,7 @@ static struct pci_driver rtl8169_pci_driver = {
+ 	.name		= MODULENAME,
+ 	.id_table	= rtl8169_pci_tbl,
+ 	.probe		= rtl_init_one,
+-	.remove		= __devexit_p(rtl_remove_one),
++	.remove		= rtl_remove_one,
+ 	.shutdown	= rtl_shutdown,
+ 	.driver.pm	= RTL8169_PM_OPS,
+ };

commit 5d8e87265715a109b3e3dc0829dc2dbcbf8b16ac
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:27 2012 -0500
+
+    qlge: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Jitendra Kalsaria 
+    Cc: Ron Mercer 
+    Cc: linux-driver@qlogic.com
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
+index b262d6156816..cae881c18f0b 100644
+--- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c
++++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
+@@ -4491,7 +4491,7 @@ static void ql_release_all(struct pci_dev *pdev)
+ 	pci_set_drvdata(pdev, NULL);
+ }
+ 
+-static int __devinit ql_init_device(struct pci_dev *pdev,
++static int ql_init_device(struct pci_dev *pdev,
+ 				    struct net_device *ndev, int cards_found)
+ {
+ 	struct ql_adapter *qdev = netdev_priv(ndev);
+@@ -4656,7 +4656,7 @@ static void ql_timer(unsigned long data)
+ 	mod_timer(&qdev->timer, jiffies + (5*HZ));
+ }
+ 
+-static int __devinit qlge_probe(struct pci_dev *pdev,
++static int qlge_probe(struct pci_dev *pdev,
+ 				const struct pci_device_id *pci_entry)
+ {
+ 	struct net_device *ndev = NULL;
+@@ -4729,7 +4729,7 @@ int ql_clean_lb_rx_ring(struct rx_ring *rx_ring, int budget)
+ 	return ql_clean_inbound_rx_ring(rx_ring, budget);
+ }
+ 
+-static void __devexit qlge_remove(struct pci_dev *pdev)
++static void qlge_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *ndev = pci_get_drvdata(pdev);
+ 	struct ql_adapter *qdev = netdev_priv(ndev);
+@@ -4921,7 +4921,7 @@ static struct pci_driver qlge_driver = {
+ 	.name = DRV_NAME,
+ 	.id_table = qlge_pci_tbl,
+ 	.probe = qlge_probe,
+-	.remove = __devexit_p(qlge_remove),
++	.remove = qlge_remove,
+ #ifdef CONFIG_PM
+ 	.suspend = qlge_suspend,
+ 	.resume = qlge_resume,

commit e3a582feac18f586d1ba9ddb08d4f77719923bc9
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:26 2012 -0500
+
+    qla3xxx: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Jitendra Kalsaria 
+    Cc: Ron Mercer 
+    Cc: linux-driver@qlogic.com
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c
+index 12d1f2470d5c..df6eb27fa101 100644
+--- a/drivers/net/ethernet/qlogic/qla3xxx.c
++++ b/drivers/net/ethernet/qlogic/qla3xxx.c
+@@ -3769,7 +3769,7 @@ static const struct net_device_ops ql3xxx_netdev_ops = {
+ 	.ndo_tx_timeout		= ql3xxx_tx_timeout,
+ };
+ 
+-static int __devinit ql3xxx_probe(struct pci_dev *pdev,
++static int ql3xxx_probe(struct pci_dev *pdev,
+ 				  const struct pci_device_id *pci_entry)
+ {
+ 	struct net_device *ndev = NULL;
+@@ -3925,7 +3925,7 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit ql3xxx_remove(struct pci_dev *pdev)
++static void ql3xxx_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *ndev = pci_get_drvdata(pdev);
+ 	struct ql3_adapter *qdev = netdev_priv(ndev);
+@@ -3952,7 +3952,7 @@ static struct pci_driver ql3xxx_driver = {
+ 	.name = DRV_NAME,
+ 	.id_table = ql3xxx_pci_tbl,
+ 	.probe = ql3xxx_probe,
+-	.remove = __devexit_p(ql3xxx_remove),
++	.remove = ql3xxx_remove,
+ };
+ 
+ module_pci_driver(ql3xxx_driver);

commit 6bb58bb0afa28bc573fb8240a4bc4e04890e3389
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:25 2012 -0500
+
+    qlcnic: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Jitendra Kalsaria 
+    Cc: Sony Chacko 
+    Cc: linux-driver@qlogic.com
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+index 1eef0bf36aa6..0110db1d0a34 100644
+--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+@@ -54,9 +54,9 @@ static int qlcnic_config_npars;
+ module_param(qlcnic_config_npars, int, 0444);
+ MODULE_PARM_DESC(qlcnic_config_npars, "Configure NPARs (0=disabled, 1=enabled");
+ 
+-static int __devinit qlcnic_probe(struct pci_dev *pdev,
++static int qlcnic_probe(struct pci_dev *pdev,
+ 		const struct pci_device_id *ent);
+-static void __devexit qlcnic_remove(struct pci_dev *pdev);
++static void qlcnic_remove(struct pci_dev *pdev);
+ static int qlcnic_open(struct net_device *netdev);
+ static int qlcnic_close(struct net_device *netdev);
+ static void qlcnic_tx_timeout(struct net_device *netdev);
+@@ -1454,7 +1454,7 @@ qlcnic_alloc_msix_entries(struct qlcnic_adapter *adapter, u16 count)
+ 	return -ENOMEM;
+ }
+ 
+-static int __devinit
++static int
+ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ 	struct net_device *netdev = NULL;
+@@ -1618,7 +1618,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	return 0;
+ }
+ 
+-static void __devexit qlcnic_remove(struct pci_dev *pdev)
++static void qlcnic_remove(struct pci_dev *pdev)
+ {
+ 	struct qlcnic_adapter *adapter;
+ 	struct net_device *netdev;
+@@ -2928,7 +2928,7 @@ static struct pci_driver qlcnic_driver = {
+ 	.name = qlcnic_driver_name,
+ 	.id_table = qlcnic_pci_tbl,
+ 	.probe = qlcnic_probe,
+-	.remove = __devexit_p(qlcnic_remove),
++	.remove = qlcnic_remove,
+ #ifdef CONFIG_PM
+ 	.suspend = qlcnic_suspend,
+ 	.resume = qlcnic_resume,

commit c3f9c88c1ca2902bcadae7138d2b3de552205f64
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:24 2012 -0500
+
+    netxen: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Sony Chacko 
+    Cc: Rajesh Borundia 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+index df450616ab37..6098fd4adfeb 100644
+--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
++++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+@@ -60,9 +60,9 @@ static int auto_fw_reset = AUTO_FW_RESET_ENABLED;
+ module_param(auto_fw_reset, int, 0644);
+ MODULE_PARM_DESC(auto_fw_reset,"Auto firmware reset (0=disabled, 1=enabled");
+ 
+-static int __devinit netxen_nic_probe(struct pci_dev *pdev,
++static int netxen_nic_probe(struct pci_dev *pdev,
+ 		const struct pci_device_id *ent);
+-static void __devexit netxen_nic_remove(struct pci_dev *pdev);
++static void netxen_nic_remove(struct pci_dev *pdev);
+ static int netxen_nic_open(struct net_device *netdev);
+ static int netxen_nic_close(struct net_device *netdev);
+ static netdev_tx_t netxen_nic_xmit_frame(struct sk_buff *,
+@@ -1397,7 +1397,7 @@ static void netxen_mask_aer_correctable(struct netxen_adapter *adapter)
+ }
+ #endif
+ 
+-static int __devinit
++static int
+ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ 	struct net_device *netdev = NULL;
+@@ -1569,7 +1569,7 @@ void netxen_cleanup_minidump(struct netxen_adapter *adapter)
+ 	}
+ }
+ 
+-static void __devexit netxen_nic_remove(struct pci_dev *pdev)
++static void netxen_nic_remove(struct pci_dev *pdev)
+ {
+ 	struct netxen_adapter *adapter;
+ 	struct net_device *netdev;
+@@ -3350,7 +3350,7 @@ static struct pci_driver netxen_driver = {
+ 	.name = netxen_nic_driver_name,
+ 	.id_table = netxen_pci_tbl,
+ 	.probe = netxen_nic_probe,
+-	.remove = __devexit_p(netxen_nic_remove),
++	.remove = netxen_nic_remove,
+ #ifdef CONFIG_PM
+ 	.suspend = netxen_nic_suspend,
+ 	.resume = netxen_nic_resume,

commit 134c1f154e1f9c0c7eddc9d5d13e110aed16b03e
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:23 2012 -0500
+
+    packetengines: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/packetengines/hamachi.c b/drivers/net/ethernet/packetengines/hamachi.c
+index c2367158350e..bf829ee30077 100644
+--- a/drivers/net/ethernet/packetengines/hamachi.c
++++ b/drivers/net/ethernet/packetengines/hamachi.c
+@@ -166,7 +166,7 @@ static int tx_params[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+ #include 
+ #include 
+ 
+-static const char version[] __devinitconst =
++static const char version[] =
+ KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "  Written by Donald Becker\n"
+ "   Some modifications by Eric kasten \n"
+ "   Further modifications by Keith Underwood \n";
+@@ -576,8 +576,8 @@ static const struct net_device_ops hamachi_netdev_ops = {
+ };
+ 
+ 
+-static int __devinit hamachi_init_one (struct pci_dev *pdev,
+-				    const struct pci_device_id *ent)
++static int hamachi_init_one(struct pci_dev *pdev,
++			    const struct pci_device_id *ent)
+ {
+ 	struct hamachi_private *hmp;
+ 	int option, i, rx_int_var, tx_int_var, boguscnt;
+@@ -791,7 +791,7 @@ static int __devinit hamachi_init_one (struct pci_dev *pdev,
+ 	return ret;
+ }
+ 
+-static int __devinit read_eeprom(void __iomem *ioaddr, int location)
++static int read_eeprom(void __iomem *ioaddr, int location)
+ {
+ 	int bogus_cnt = 1000;
+ 
+@@ -1894,7 +1894,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+ }
+ 
+ 
+-static void __devexit hamachi_remove_one (struct pci_dev *pdev)
++static void hamachi_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 
+@@ -1923,7 +1923,7 @@ static struct pci_driver hamachi_driver = {
+ 	.name		= DRV_NAME,
+ 	.id_table	= hamachi_pci_tbl,
+ 	.probe		= hamachi_init_one,
+-	.remove		= __devexit_p(hamachi_remove_one),
++	.remove		= hamachi_remove_one,
+ };
+ 
+ static int __init hamachi_init (void)
+diff --git a/drivers/net/ethernet/packetengines/yellowfin.c b/drivers/net/ethernet/packetengines/yellowfin.c
+index 04e622fd468d..2800c449de4e 100644
+--- a/drivers/net/ethernet/packetengines/yellowfin.c
++++ b/drivers/net/ethernet/packetengines/yellowfin.c
+@@ -106,7 +106,7 @@ static int gx_fix;
+ #include 
+ 
+ /* These identify the driver base version and may not be removed. */
+-static const char version[] __devinitconst =
++static const char version[] =
+   KERN_INFO DRV_NAME ".c:v1.05  1/09/2001  Written by Donald Becker \n"
+   "  (unofficial 2.4.x port, " DRV_VERSION ", " DRV_RELDATE ")\n";
+ 
+@@ -367,7 +367,7 @@ static const struct net_device_ops netdev_ops = {
+ 	.ndo_tx_timeout 	= yellowfin_tx_timeout,
+ };
+ 
+-static int __devinit yellowfin_init_one(struct pci_dev *pdev,
++static int yellowfin_init_one(struct pci_dev *pdev,
+ 					const struct pci_device_id *ent)
+ {
+ 	struct net_device *dev;
+@@ -522,7 +522,7 @@ static int __devinit yellowfin_init_one(struct pci_dev *pdev,
+ 	return -ENODEV;
+ }
+ 
+-static int __devinit read_eeprom(void __iomem *ioaddr, int location)
++static int read_eeprom(void __iomem *ioaddr, int location)
+ {
+ 	int bogus_cnt = 10000;		/* Typical 33Mhz: 1050 ticks */
+ 
+@@ -1372,7 +1372,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+ }
+ 
+ 
+-static void __devexit yellowfin_remove_one (struct pci_dev *pdev)
++static void yellowfin_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct yellowfin_private *np;
+@@ -1399,7 +1399,7 @@ static struct pci_driver yellowfin_driver = {
+ 	.name		= DRV_NAME,
+ 	.id_table	= yellowfin_pci_tbl,
+ 	.probe		= yellowfin_init_one,
+-	.remove		= __devexit_p(yellowfin_remove_one),
++	.remove		= yellowfin_remove_one,
+ };
+ 
+ 

commit 5bc7ec702fd7680eb12be88ada87742db9676f5c
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:22 2012 -0500
+
+    net/octeon_mgmt: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/octeon/octeon_mgmt.c b/drivers/net/ethernet/octeon/octeon_mgmt.c
+index f97719c48516..b5499198e029 100644
+--- a/drivers/net/ethernet/octeon/octeon_mgmt.c
++++ b/drivers/net/ethernet/octeon/octeon_mgmt.c
+@@ -1419,7 +1419,7 @@ static const struct net_device_ops octeon_mgmt_ops = {
+ #endif
+ };
+ 
+-static int __devinit octeon_mgmt_probe(struct platform_device *pdev)
++static int octeon_mgmt_probe(struct platform_device *pdev)
+ {
+ 	struct net_device *netdev;
+ 	struct octeon_mgmt *p;
+@@ -1559,7 +1559,7 @@ static int __devinit octeon_mgmt_probe(struct platform_device *pdev)
+ 	return result;
+ }
+ 
+-static int __devexit octeon_mgmt_remove(struct platform_device *pdev)
++static int octeon_mgmt_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *netdev = dev_get_drvdata(&pdev->dev);
+ 
+@@ -1583,7 +1583,7 @@ static struct platform_driver octeon_mgmt_driver = {
+ 		.of_match_table = octeon_mgmt_match,
+ 	},
+ 	.probe		= octeon_mgmt_probe,
+-	.remove		= __devexit_p(octeon_mgmt_remove),
++	.remove		= octeon_mgmt_remove,
+ };
+ 
+ extern void octeon_mdiobus_force_mod_depencency(void);

commit 21524526b3ec66329cba682f11fdba77c8b0e698
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:21 2012 -0500
+
+    lpc_eth: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c
+index db6e1019be18..3466ca1e8f6c 100644
+--- a/drivers/net/ethernet/nxp/lpc_eth.c
++++ b/drivers/net/ethernet/nxp/lpc_eth.c
+@@ -1595,7 +1595,7 @@ MODULE_DEVICE_TABLE(of, lpc_eth_match);
+ 
+ static struct platform_driver lpc_eth_driver = {
+ 	.probe		= lpc_eth_drv_probe,
+-	.remove		= __devexit_p(lpc_eth_drv_remove),
++	.remove		= lpc_eth_drv_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= lpc_eth_drv_suspend,
+ 	.resume		= lpc_eth_drv_resume,

commit d05919a148154d6814cf98f515d477bf676e957e
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:20 2012 -0500
+
+    forcedeth: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
+index 876beceaf2d7..653487dc7b52 100644
+--- a/drivers/net/ethernet/nvidia/forcedeth.c
++++ b/drivers/net/ethernet/nvidia/forcedeth.c
+@@ -5520,7 +5520,7 @@ static const struct net_device_ops nv_netdev_ops_optimized = {
+ #endif
+ };
+ 
+-static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
++static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
+ {
+ 	struct net_device *dev;
+ 	struct fe_priv *np;
+@@ -5995,7 +5995,7 @@ static void nv_restore_mac_addr(struct pci_dev *pci_dev)
+ 	       base + NvRegTransmitPoll);
+ }
+ 
+-static void __devexit nv_remove(struct pci_dev *pci_dev)
++static void nv_remove(struct pci_dev *pci_dev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pci_dev);
+ 
+@@ -6271,7 +6271,7 @@ static struct pci_driver driver = {
+ 	.name		= DRV_NAME,
+ 	.id_table	= pci_tbl,
+ 	.probe		= nv_probe,
+-	.remove		= __devexit_p(nv_remove),
++	.remove		= nv_remove,
+ 	.shutdown	= nv_shutdown,
+ 	.driver.pm	= NV_PM_OPS,
+ };

commit 26735f2f126f5d75234e205687e3c15e1a5a3684
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:19 2012 -0500
+
+    nuvoton: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Wan ZongShun 
+    Cc: linux-arm-kernel@lists.infradead.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/nuvoton/w90p910_ether.c b/drivers/net/ethernet/nuvoton/w90p910_ether.c
+index 6893a65ae55f..cbd6a529d0c0 100644
+--- a/drivers/net/ethernet/nuvoton/w90p910_ether.c
++++ b/drivers/net/ethernet/nuvoton/w90p910_ether.c
+@@ -978,7 +978,7 @@ static int w90p910_ether_setup(struct net_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devinit w90p910_ether_probe(struct platform_device *pdev)
++static int w90p910_ether_probe(struct platform_device *pdev)
+ {
+ 	struct w90p910_ether *ether;
+ 	struct net_device *dev;
+@@ -1071,7 +1071,7 @@ static int __devinit w90p910_ether_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit w90p910_ether_remove(struct platform_device *pdev)
++static int w90p910_ether_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *dev = platform_get_drvdata(pdev);
+ 	struct w90p910_ether *ether = netdev_priv(dev);
+@@ -1096,7 +1096,7 @@ static int __devexit w90p910_ether_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver w90p910_ether_driver = {
+ 	.probe		= w90p910_ether_probe,
+-	.remove		= __devexit_p(w90p910_ether_remove),
++	.remove		= w90p910_ether_remove,
+ 	.driver		= {
+ 		.name	= "nuc900-emc",
+ 		.owner	= THIS_MODULE,

commit 3a036ce5c6fdd787d3146c639871668996221c0d
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:18 2012 -0500
+
+    vxge/s2io: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Jon Mason 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c
+index c98decb19ce8..3a010e356661 100644
+--- a/drivers/net/ethernet/neterion/s2io.c
++++ b/drivers/net/ethernet/neterion/s2io.c
+@@ -494,7 +494,7 @@ static struct pci_driver s2io_driver = {
+ 	.name = "S2IO",
+ 	.id_table = s2io_tbl,
+ 	.probe = s2io_init_nic,
+-	.remove = __devexit_p(s2io_rem_nic),
++	.remove = s2io_rem_nic,
+ 	.err_handler = &s2io_err_handler,
+ };
+ 
+@@ -7702,7 +7702,7 @@ static const struct net_device_ops s2io_netdev_ops = {
+  *  returns 0 on success and negative on failure.
+  */
+ 
+-static int __devinit
++static int
+ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
+ {
+ 	struct s2io_nic *sp;
+@@ -8200,7 +8200,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
+  * from memory.
+  */
+ 
+-static void __devexit s2io_rem_nic(struct pci_dev *pdev)
++static void s2io_rem_nic(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct s2io_nic *sp;
+diff --git a/drivers/net/ethernet/neterion/s2io.h b/drivers/net/ethernet/neterion/s2io.h
+index d5596926a1ef..032f9b6d850d 100644
+--- a/drivers/net/ethernet/neterion/s2io.h
++++ b/drivers/net/ethernet/neterion/s2io.h
+@@ -1075,9 +1075,9 @@ static inline void SPECIAL_REG_WRITE(u64 val, void __iomem *addr, int order)
+ /*
+  * Prototype declaration.
+  */
+-static int __devinit s2io_init_nic(struct pci_dev *pdev,
++static int s2io_init_nic(struct pci_dev *pdev,
+ 				   const struct pci_device_id *pre);
+-static void __devexit s2io_rem_nic(struct pci_dev *pdev);
++static void s2io_rem_nic(struct pci_dev *pdev);
+ static int init_shared_mem(struct s2io_nic *sp);
+ static void free_shared_mem(struct s2io_nic *sp);
+ static int init_nic(struct s2io_nic *nic);
+diff --git a/drivers/net/ethernet/neterion/vxge/vxge-config.c b/drivers/net/ethernet/neterion/vxge/vxge-config.c
+index c2e420a84d22..fbe5363cb89c 100644
+--- a/drivers/net/ethernet/neterion/vxge/vxge-config.c
++++ b/drivers/net/ethernet/neterion/vxge/vxge-config.c
+@@ -993,7 +993,7 @@ __vxge_hw_vpath_addr_get(struct __vxge_hw_virtualpath *vpath,
+  * for the driver, FW version information, and the first mac address for
+  * each vpath
+  */
+-enum vxge_hw_status __devinit
++enum vxge_hw_status
+ vxge_hw_device_hw_info_get(void __iomem *bar0,
+ 			   struct vxge_hw_device_hw_info *hw_info)
+ {
+@@ -1310,7 +1310,7 @@ __vxge_hw_device_config_check(struct vxge_hw_device_config *new_config)
+  * When done, the driver allocates sizeof(struct __vxge_hw_device) bytes for HW
+  * to enable the latter to perform Titan hardware initialization.
+  */
+-enum vxge_hw_status __devinit
++enum vxge_hw_status
+ vxge_hw_device_initialize(
+ 	struct __vxge_hw_device **devh,
+ 	struct vxge_hw_device_attr *attr,
+@@ -2917,7 +2917,7 @@ __vxge_hw_ring_create(struct __vxge_hw_vpath_handle *vp,
+  * vxge_hw_device_config_default_get - Initialize device config with defaults.
+  * Initialize Titan device config with default values.
+  */
+-enum vxge_hw_status __devinit
++enum vxge_hw_status
+ vxge_hw_device_config_default_get(struct vxge_hw_device_config *device_config)
+ {
+ 	u32 i;
+diff --git a/drivers/net/ethernet/neterion/vxge/vxge-config.h b/drivers/net/ethernet/neterion/vxge/vxge-config.h
+index 9e0c1eed5dc5..6ce4412fcc1a 100644
+--- a/drivers/net/ethernet/neterion/vxge/vxge-config.h
++++ b/drivers/net/ethernet/neterion/vxge/vxge-config.h
+@@ -1846,11 +1846,11 @@ struct vxge_hw_vpath_attr {
+ 	struct vxge_hw_fifo_attr	fifo_attr;
+ };
+ 
+-enum vxge_hw_status __devinit vxge_hw_device_hw_info_get(
++enum vxge_hw_status vxge_hw_device_hw_info_get(
+ 	void __iomem *bar0,
+ 	struct vxge_hw_device_hw_info *hw_info);
+ 
+-enum vxge_hw_status __devinit vxge_hw_device_config_default_get(
++enum vxge_hw_status vxge_hw_device_config_default_get(
+ 	struct vxge_hw_device_config *device_config);
+ 
+ /**
+@@ -1877,7 +1877,7 @@ u16 vxge_hw_device_link_width_get(struct __vxge_hw_device *devh);
+ const u8 *
+ vxge_hw_device_product_name_get(struct __vxge_hw_device *devh);
+ 
+-enum vxge_hw_status __devinit vxge_hw_device_initialize(
++enum vxge_hw_status vxge_hw_device_initialize(
+ 	struct __vxge_hw_device **devh,
+ 	struct vxge_hw_device_attr *attr,
+ 	struct vxge_hw_device_config *device_config);
+diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c
+index 3e5b7509502c..bb5770fc6503 100644
+--- a/drivers/net/ethernet/neterion/vxge/vxge-main.c
++++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c
+@@ -3371,7 +3371,7 @@ static const struct net_device_ops vxge_netdev_ops = {
+ #endif
+ };
+ 
+-static int __devinit vxge_device_register(struct __vxge_hw_device *hldev,
++static int vxge_device_register(struct __vxge_hw_device *hldev,
+ 					  struct vxge_config *config,
+ 					  int high_dma, int no_of_vpath,
+ 					  struct vxgedev **vdev_out)
+@@ -3672,7 +3672,7 @@ static void verify_bandwidth(void)
+ /*
+  * Vpath configuration
+  */
+-static int __devinit vxge_config_vpaths(
++static int vxge_config_vpaths(
+ 			struct vxge_hw_device_config *device_config,
+ 			u64 vpath_mask, struct vxge_config *config_param)
+ {
+@@ -3859,7 +3859,7 @@ static int __devinit vxge_config_vpaths(
+ }
+ 
+ /* initialize device configuratrions */
+-static void __devinit vxge_device_config_init(
++static void vxge_device_config_init(
+ 				struct vxge_hw_device_config *device_config,
+ 				int *intr_type)
+ {
+@@ -3912,7 +3912,7 @@ static void __devinit vxge_device_config_init(
+ 			device_config->rth_it_type);
+ }
+ 
+-static void __devinit vxge_print_parm(struct vxgedev *vdev, u64 vpath_mask)
++static void vxge_print_parm(struct vxgedev *vdev, u64 vpath_mask)
+ {
+ 	int i;
+ 
+@@ -4269,7 +4269,7 @@ static int vxge_probe_fw_update(struct vxgedev *vdev)
+ 	return ret;
+ }
+ 
+-static int __devinit is_sriov_initialized(struct pci_dev *pdev)
++static int is_sriov_initialized(struct pci_dev *pdev)
+ {
+ 	int pos;
+ 	u16 ctrl;
+@@ -4300,7 +4300,7 @@ static const struct vxge_hw_uld_cbs vxge_callbacks = {
+  * returns 0 on success and negative on failure.
+  *
+  */
+-static int __devinit
++static int
+ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
+ {
+ 	struct __vxge_hw_device *hldev;
+@@ -4764,7 +4764,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
+  * Description: This function is called by the Pci subsystem to release a
+  * PCI device and free up all resource held up by the device.
+  */
+-static void __devexit vxge_remove(struct pci_dev *pdev)
++static void vxge_remove(struct pci_dev *pdev)
+ {
+ 	struct __vxge_hw_device *hldev;
+ 	struct vxgedev *vdev;
+@@ -4809,7 +4809,7 @@ static struct pci_driver vxge_driver = {
+ 	.name = VXGE_DRIVER_NAME,
+ 	.id_table = vxge_id_table,
+ 	.probe = vxge_probe,
+-	.remove = __devexit_p(vxge_remove),
++	.remove = vxge_remove,
+ #ifdef CONFIG_PM
+ 	.suspend = vxge_pm_suspend,
+ 	.resume = vxge_pm_resume,

commit 6980cbe4a6dbb3d7871e99a3cbc74a572d14d327
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:17 2012 -0500
+
+    natsemi: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/natsemi/ibmlana.c b/drivers/net/ethernet/natsemi/ibmlana.c
+index 3f94ddbf4dc0..923e640d604c 100644
+--- a/drivers/net/ethernet/natsemi/ibmlana.c
++++ b/drivers/net/ethernet/natsemi/ibmlana.c
+@@ -900,7 +900,7 @@ static short ibmlana_adapter_ids[] __initdata = {
+ 	0x0000
+ };
+ 
+-static char *ibmlana_adapter_names[] __devinitdata = {
++static char *ibmlana_adapter_names[] = {
+ 	"IBM LAN Adapter/A",
+ 	NULL
+ };
+@@ -916,7 +916,7 @@ static const struct net_device_ops ibmlana_netdev_ops = {
+ 	.ndo_validate_addr	= eth_validate_addr,
+ };
+ 
+-static int __devinit ibmlana_init_one(struct device *kdev)
++static int ibmlana_init_one(struct device *kdev)
+ {
+ 	struct mca_device *mdev = to_mca_device(kdev);
+ 	struct net_device *dev;
+diff --git a/drivers/net/ethernet/natsemi/jazzsonic.c b/drivers/net/ethernet/natsemi/jazzsonic.c
+index 95dd39ffb230..b0b361546365 100644
+--- a/drivers/net/ethernet/natsemi/jazzsonic.c
++++ b/drivers/net/ethernet/natsemi/jazzsonic.c
+@@ -117,7 +117,7 @@ static const struct net_device_ops sonic_netdev_ops = {
+ 	.ndo_set_mac_address	= eth_mac_addr,
+ };
+ 
+-static int __devinit sonic_probe1(struct net_device *dev)
++static int sonic_probe1(struct net_device *dev)
+ {
+ 	static unsigned version_printed;
+ 	unsigned int silicon_revision;
+@@ -220,7 +220,7 @@ static int __devinit sonic_probe1(struct net_device *dev)
+  * Probe for a SONIC ethernet controller on a Mips Jazz board.
+  * Actually probing is superfluous but we're paranoid.
+  */
+-static int __devinit jazz_sonic_probe(struct platform_device *pdev)
++static int jazz_sonic_probe(struct platform_device *pdev)
+ {
+ 	struct net_device *dev;
+ 	struct sonic_local *lp;
+@@ -270,7 +270,7 @@ MODULE_ALIAS("platform:jazzsonic");
+ 
+ #include "sonic.c"
+ 
+-static int __devexit jazz_sonic_device_remove (struct platform_device *pdev)
++static int jazz_sonic_device_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *dev = platform_get_drvdata(pdev);
+ 	struct sonic_local* lp = netdev_priv(dev);
+@@ -286,7 +286,7 @@ static int __devexit jazz_sonic_device_remove (struct platform_device *pdev)
+ 
+ static struct platform_driver jazz_sonic_driver = {
+ 	.probe	= jazz_sonic_probe,
+-	.remove	= __devexit_p(jazz_sonic_device_remove),
++	.remove	= jazz_sonic_device_remove,
+ 	.driver	= {
+ 		.name	= jazz_sonic_string,
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/net/ethernet/natsemi/macsonic.c b/drivers/net/ethernet/natsemi/macsonic.c
+index b9680ba5a325..eaddbb7c24ab 100644
+--- a/drivers/net/ethernet/natsemi/macsonic.c
++++ b/drivers/net/ethernet/natsemi/macsonic.c
+@@ -196,7 +196,7 @@ static const struct net_device_ops macsonic_netdev_ops = {
+ 	.ndo_set_mac_address	= eth_mac_addr,
+ };
+ 
+-static int __devinit macsonic_init(struct net_device *dev)
++static int macsonic_init(struct net_device *dev)
+ {
+ 	struct sonic_local* lp = netdev_priv(dev);
+ 
+@@ -245,7 +245,7 @@ static int __devinit macsonic_init(struct net_device *dev)
+                           memcmp(mac, "\x00\x80\x19", 3) && \
+                           memcmp(mac, "\x00\x05\x02", 3))
+ 
+-static void __devinit mac_onboard_sonic_ethernet_addr(struct net_device *dev)
++static void mac_onboard_sonic_ethernet_addr(struct net_device *dev)
+ {
+ 	struct sonic_local *lp = netdev_priv(dev);
+ 	const int prom_addr = ONBOARD_SONIC_PROM_BASE;
+@@ -309,7 +309,7 @@ static void __devinit mac_onboard_sonic_ethernet_addr(struct net_device *dev)
+ 	eth_hw_addr_random(dev);
+ }
+ 
+-static int __devinit mac_onboard_sonic_probe(struct net_device *dev)
++static int mac_onboard_sonic_probe(struct net_device *dev)
+ {
+ 	struct sonic_local* lp = netdev_priv(dev);
+ 	int sr;
+@@ -420,7 +420,7 @@ static int __devinit mac_onboard_sonic_probe(struct net_device *dev)
+ 	return macsonic_init(dev);
+ }
+ 
+-static int __devinit mac_nubus_sonic_ethernet_addr(struct net_device *dev,
++static int mac_nubus_sonic_ethernet_addr(struct net_device *dev,
+ 						unsigned long prom_addr,
+ 						int id)
+ {
+@@ -435,7 +435,7 @@ static int __devinit mac_nubus_sonic_ethernet_addr(struct net_device *dev,
+ 	return 0;
+ }
+ 
+-static int __devinit macsonic_ident(struct nubus_dev *ndev)
++static int macsonic_ident(struct nubus_dev *ndev)
+ {
+ 	if (ndev->dr_hw == NUBUS_DRHW_ASANTE_LC &&
+ 	    ndev->dr_sw == NUBUS_DRSW_SONIC_LC)
+@@ -460,7 +460,7 @@ static int __devinit macsonic_ident(struct nubus_dev *ndev)
+ 	return -1;
+ }
+ 
+-static int __devinit mac_nubus_sonic_probe(struct net_device *dev)
++static int mac_nubus_sonic_probe(struct net_device *dev)
+ {
+ 	static int slots;
+ 	struct nubus_dev* ndev = NULL;
+@@ -573,7 +573,7 @@ static int __devinit mac_nubus_sonic_probe(struct net_device *dev)
+ 	return macsonic_init(dev);
+ }
+ 
+-static int __devinit mac_sonic_probe(struct platform_device *pdev)
++static int mac_sonic_probe(struct platform_device *pdev)
+ {
+ 	struct net_device *dev;
+ 	struct sonic_local *lp;
+@@ -619,7 +619,7 @@ MODULE_ALIAS("platform:macsonic");
+ 
+ #include "sonic.c"
+ 
+-static int __devexit mac_sonic_device_remove (struct platform_device *pdev)
++static int mac_sonic_device_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *dev = platform_get_drvdata(pdev);
+ 	struct sonic_local* lp = netdev_priv(dev);
+@@ -634,7 +634,7 @@ static int __devexit mac_sonic_device_remove (struct platform_device *pdev)
+ 
+ static struct platform_driver mac_sonic_driver = {
+ 	.probe  = mac_sonic_probe,
+-	.remove = __devexit_p(mac_sonic_device_remove),
++	.remove = mac_sonic_device_remove,
+ 	.driver	= {
+ 		.name	= mac_sonic_string,
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/net/ethernet/natsemi/natsemi.c b/drivers/net/ethernet/natsemi/natsemi.c
+index dbaaa99a0d43..77f7cd37ad30 100644
+--- a/drivers/net/ethernet/natsemi/natsemi.c
++++ b/drivers/net/ethernet/natsemi/natsemi.c
+@@ -127,7 +127,7 @@ static int full_duplex[MAX_UNITS];
+ #define NATSEMI_RX_LIMIT	2046	/* maximum supported by hardware */
+ 
+ /* These identify the driver base version and may not be removed. */
+-static const char version[] __devinitconst =
++static const char version[] =
+   KERN_INFO DRV_NAME " dp8381x driver, version "
+       DRV_VERSION ", " DRV_RELDATE "\n"
+   "  originally by Donald Becker \n"
+@@ -242,7 +242,7 @@ static struct {
+ 	const char *name;
+ 	unsigned long flags;
+ 	unsigned int eeprom_size;
+-} natsemi_pci_info[] __devinitdata = {
++} natsemi_pci_info[] = {
+ 	{ "Aculab E1/T1 PMXc cPCI carrier card", NATSEMI_FLAG_IGNORE_PHY, 128 },
+ 	{ "NatSemi DP8381[56]", 0, 24 },
+ };
+@@ -742,7 +742,7 @@ static void move_int_phy(struct net_device *dev, int addr)
+ 	udelay(1);
+ }
+ 
+-static void __devinit natsemi_init_media (struct net_device *dev)
++static void natsemi_init_media(struct net_device *dev)
+ {
+ 	struct netdev_private *np = netdev_priv(dev);
+ 	u32 tmp;
+@@ -797,8 +797,8 @@ static const struct net_device_ops natsemi_netdev_ops = {
+ #endif
+ };
+ 
+-static int __devinit natsemi_probe1 (struct pci_dev *pdev,
+-	const struct pci_device_id *ent)
++static int natsemi_probe1(struct pci_dev *pdev,
++			  const struct pci_device_id *ent)
+ {
+ 	struct net_device *dev;
+ 	struct netdev_private *np;
+@@ -3214,7 +3214,7 @@ static int netdev_close(struct net_device *dev)
+ }
+ 
+ 
+-static void __devexit natsemi_remove1 (struct pci_dev *pdev)
++static void natsemi_remove1(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	void __iomem * ioaddr = ns_ioaddr(dev);
+@@ -3353,7 +3353,7 @@ static struct pci_driver natsemi_driver = {
+ 	.name		= DRV_NAME,
+ 	.id_table	= natsemi_pci_tbl,
+ 	.probe		= natsemi_probe1,
+-	.remove		= __devexit_p(natsemi_remove1),
++	.remove		= natsemi_remove1,
+ #ifdef CONFIG_PM
+ 	.suspend	= natsemi_suspend,
+ 	.resume		= natsemi_resume,
+diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c
+index d52728b3c436..0281755200a7 100644
+--- a/drivers/net/ethernet/natsemi/ns83820.c
++++ b/drivers/net/ethernet/natsemi/ns83820.c
+@@ -1941,7 +1941,7 @@ static const struct net_device_ops netdev_ops = {
+ 	.ndo_tx_timeout		= ns83820_tx_timeout,
+ };
+ 
+-static int __devinit ns83820_init_one(struct pci_dev *pci_dev,
++static int ns83820_init_one(struct pci_dev *pci_dev,
+ 				      const struct pci_device_id *id)
+ {
+ 	struct net_device *ndev;
+@@ -2241,7 +2241,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev,
+ 	return err;
+ }
+ 
+-static void __devexit ns83820_remove_one(struct pci_dev *pci_dev)
++static void ns83820_remove_one(struct pci_dev *pci_dev)
+ {
+ 	struct net_device *ndev = pci_get_drvdata(pci_dev);
+ 	struct ns83820 *dev = PRIV(ndev); /* ok even if NULL */
+@@ -2272,7 +2272,7 @@ static struct pci_driver driver = {
+ 	.name		= "ns83820",
+ 	.id_table	= ns83820_pci_tbl,
+ 	.probe		= ns83820_init_one,
+-	.remove		= __devexit_p(ns83820_remove_one),
++	.remove		= ns83820_remove_one,
+ #if 0	/* FIXME: implement */
+ 	.suspend	= ,
+ 	.resume		= ,
+diff --git a/drivers/net/ethernet/natsemi/xtsonic.c b/drivers/net/ethernet/natsemi/xtsonic.c
+index 7dfe88398d7d..5e4748e855f6 100644
+--- a/drivers/net/ethernet/natsemi/xtsonic.c
++++ b/drivers/net/ethernet/natsemi/xtsonic.c
+@@ -249,7 +249,7 @@ static int __init sonic_probe1(struct net_device *dev)
+  * Actually probing is superfluous but we're paranoid.
+  */
+ 
+-int __devinit xtsonic_probe(struct platform_device *pdev)
++int xtsonic_probe(struct platform_device *pdev)
+ {
+ 	struct net_device *dev;
+ 	struct sonic_local *lp;
+@@ -297,7 +297,7 @@ MODULE_PARM_DESC(sonic_debug, "xtsonic debug level (1-4)");
+ 
+ #include "sonic.c"
+ 
+-static int __devexit xtsonic_device_remove (struct platform_device *pdev)
++static int xtsonic_device_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *dev = platform_get_drvdata(pdev);
+ 	struct sonic_local *lp = netdev_priv(dev);
+@@ -314,7 +314,7 @@ static int __devexit xtsonic_device_remove (struct platform_device *pdev)
+ 
+ static struct platform_driver xtsonic_driver = {
+ 	.probe = xtsonic_probe,
+-	.remove = __devexit_p(xtsonic_device_remove),
++	.remove = xtsonic_device_remove,
+ 	.driver = {
+ 		.name = xtsonic_string,
+ 	},

commit 19d1b44aa8eba6304abdfe9761bb941f38b512f5
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:16 2012 -0500
+
+    enc28j60: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/microchip/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c
+index 6118bdad244f..a99456c3dd87 100644
+--- a/drivers/net/ethernet/microchip/enc28j60.c
++++ b/drivers/net/ethernet/microchip/enc28j60.c
+@@ -1541,7 +1541,7 @@ static const struct net_device_ops enc28j60_netdev_ops = {
+ 	.ndo_validate_addr	= eth_validate_addr,
+ };
+ 
+-static int __devinit enc28j60_probe(struct spi_device *spi)
++static int enc28j60_probe(struct spi_device *spi)
+ {
+ 	struct net_device *dev;
+ 	struct enc28j60_net *priv;
+@@ -1617,7 +1617,7 @@ static int __devinit enc28j60_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit enc28j60_remove(struct spi_device *spi)
++static int enc28j60_remove(struct spi_device *spi)
+ {
+ 	struct enc28j60_net *priv = dev_get_drvdata(&spi->dev);
+ 
+@@ -1637,7 +1637,7 @@ static struct spi_driver enc28j60_driver = {
+ 		   .owner = THIS_MODULE,
+ 	 },
+ 	.probe = enc28j60_probe,
+-	.remove = __devexit_p(enc28j60_remove),
++	.remove = enc28j60_remove,
+ };
+ 
+ static int __init enc28j60_init(void)

commit f57e68488e27fb99bda29eb0c42b5450e439aa87
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:15 2012 -0500
+
+    mlx4_core: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
+index 2aa80afd98d2..340551eebedf 100644
+--- a/drivers/net/ethernet/mellanox/mlx4/main.c
++++ b/drivers/net/ethernet/mellanox/mlx4/main.c
+@@ -98,7 +98,7 @@ MODULE_PARM_DESC(log_num_mgm_entry_size, "log mgm size, that defines the num"
+ #define HCA_GLOBAL_CAP_MASK            0
+ #define PF_CONTEXT_BEHAVIOUR_MASK      0
+ 
+-static char mlx4_version[] __devinitdata =
++static char mlx4_version[] =
+ 	DRV_NAME ": Mellanox ConnectX core driver v"
+ 	DRV_VERSION " (" DRV_RELDATE ")\n";
+ 
+@@ -2224,7 +2224,7 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data)
+ 	return err;
+ }
+ 
+-static int __devinit mlx4_init_one(struct pci_dev *pdev,
++static int mlx4_init_one(struct pci_dev *pdev,
+ 				   const struct pci_device_id *id)
+ {
+ 	printk_once(KERN_INFO "%s", mlx4_version);
+@@ -2391,7 +2391,7 @@ static struct pci_driver mlx4_driver = {
+ 	.name		= DRV_NAME,
+ 	.id_table	= mlx4_pci_table,
+ 	.probe		= mlx4_init_one,
+-	.remove		= __devexit_p(mlx4_remove_one),
++	.remove		= mlx4_remove_one,
+ 	.err_handler    = &mlx4_err_handler,
+ };
+ 

commit 853e3f4c5f49e51c904dab0d25eda82a92f1341f
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:14 2012 -0500
+
+    skge: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Mirko Lindner 
+    Cc: Stephen Hemminger 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c
+index d19a143aa5a8..3d66e959a0cc 100644
+--- a/drivers/net/ethernet/marvell/skge.c
++++ b/drivers/net/ethernet/marvell/skge.c
+@@ -3860,7 +3860,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
+ 	return dev;
+ }
+ 
+-static void __devinit skge_show_addr(struct net_device *dev)
++static void skge_show_addr(struct net_device *dev)
+ {
+ 	const struct skge_port *skge = netdev_priv(dev);
+ 
+@@ -3869,7 +3869,7 @@ static void __devinit skge_show_addr(struct net_device *dev)
+ 
+ static int only_32bit_dma;
+ 
+-static int __devinit skge_probe(struct pci_dev *pdev,
++static int skge_probe(struct pci_dev *pdev,
+ 				const struct pci_device_id *ent)
+ {
+ 	struct net_device *dev, *dev1;
+@@ -4012,7 +4012,7 @@ static int __devinit skge_probe(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit skge_remove(struct pci_dev *pdev)
++static void skge_remove(struct pci_dev *pdev)
+ {
+ 	struct skge_hw *hw  = pci_get_drvdata(pdev);
+ 	struct net_device *dev0, *dev1;
+@@ -4142,7 +4142,7 @@ static struct pci_driver skge_driver = {
+ 	.name =         DRV_NAME,
+ 	.id_table =     skge_id_table,
+ 	.probe =        skge_probe,
+-	.remove =       __devexit_p(skge_remove),
++	.remove =       skge_remove,
+ 	.shutdown =	skge_shutdown,
+ 	.driver.pm =	SKGE_PM_OPS,
+ };
+diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
+index 78946feab4a2..bd77cb9dd964 100644
+--- a/drivers/net/ethernet/marvell/sky2.c
++++ b/drivers/net/ethernet/marvell/sky2.c
+@@ -3140,7 +3140,7 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk)
+ }
+ 
+ 
+-static int __devinit sky2_init(struct sky2_hw *hw)
++static int sky2_init(struct sky2_hw *hw)
+ {
+ 	u8 t8;
+ 
+@@ -4741,7 +4741,7 @@ static const struct net_device_ops sky2_netdev_ops[2] = {
+ };
+ 
+ /* Initialize network device */
+-static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
++static struct net_device *sky2_init_netdev(struct sky2_hw *hw,
+ 						     unsigned port,
+ 						     int highmem, int wol)
+ {
+@@ -4807,7 +4807,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
+ 	return dev;
+ }
+ 
+-static void __devinit sky2_show_addr(struct net_device *dev)
++static void sky2_show_addr(struct net_device *dev)
+ {
+ 	const struct sky2_port *sky2 = netdev_priv(dev);
+ 
+@@ -4815,7 +4815,7 @@ static void __devinit sky2_show_addr(struct net_device *dev)
+ }
+ 
+ /* Handle software interrupt used during MSI test */
+-static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id)
++static irqreturn_t sky2_test_intr(int irq, void *dev_id)
+ {
+ 	struct sky2_hw *hw = dev_id;
+ 	u32 status = sky2_read32(hw, B0_Y2_SP_ISRC2);
+@@ -4834,7 +4834,7 @@ static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id)
+ }
+ 
+ /* Test interrupt path by forcing a a software IRQ */
+-static int __devinit sky2_test_msi(struct sky2_hw *hw)
++static int sky2_test_msi(struct sky2_hw *hw)
+ {
+ 	struct pci_dev *pdev = hw->pdev;
+ 	int err;
+@@ -4896,7 +4896,7 @@ static const char *sky2_name(u8 chipid, char *buf, int sz)
+ 	return buf;
+ }
+ 
+-static int __devinit sky2_probe(struct pci_dev *pdev,
++static int sky2_probe(struct pci_dev *pdev,
+ 				const struct pci_device_id *ent)
+ {
+ 	struct net_device *dev, *dev1;
+@@ -5086,7 +5086,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit sky2_remove(struct pci_dev *pdev)
++static void sky2_remove(struct pci_dev *pdev)
+ {
+ 	struct sky2_hw *hw = pci_get_drvdata(pdev);
+ 	int i;
+@@ -5207,7 +5207,7 @@ static struct pci_driver sky2_driver = {
+ 	.name = DRV_NAME,
+ 	.id_table = sky2_id_table,
+ 	.probe = sky2_probe,
+-	.remove = __devexit_p(sky2_remove),
++	.remove = sky2_remove,
+ 	.shutdown = sky2_shutdown,
+ 	.driver.pm = SKY2_PM_OPS,
+ };

commit fe17dc1e2bae8599aa034e678f7bbfd1f98e5a15
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:13 2012 -0500
+
+    ibm/emac: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c
+index a0fe6e3fce61..c791ad3907b2 100644
+--- a/drivers/net/ethernet/ibm/emac/core.c
++++ b/drivers/net/ethernet/ibm/emac/core.c
+@@ -2261,7 +2261,7 @@ struct emac_depentry {
+ #define	EMAC_DEP_PREV_IDX	5
+ #define	EMAC_DEP_COUNT		6
+ 
+-static int __devinit emac_check_deps(struct emac_instance *dev,
++static int emac_check_deps(struct emac_instance *dev,
+ 				     struct emac_depentry *deps)
+ {
+ 	int i, there = 0;
+@@ -2314,7 +2314,7 @@ static void emac_put_deps(struct emac_instance *dev)
+ 		of_dev_put(dev->tah_dev);
+ }
+ 
+-static int __devinit emac_of_bus_notify(struct notifier_block *nb,
++static int emac_of_bus_notify(struct notifier_block *nb,
+ 					unsigned long action, void *data)
+ {
+ 	/* We are only intereted in device addition */
+@@ -2323,11 +2323,11 @@ static int __devinit emac_of_bus_notify(struct notifier_block *nb,
+ 	return 0;
+ }
+ 
+-static struct notifier_block emac_of_bus_notifier __devinitdata = {
++static struct notifier_block emac_of_bus_notifier = {
+ 	.notifier_call = emac_of_bus_notify
+ };
+ 
+-static int __devinit emac_wait_deps(struct emac_instance *dev)
++static int emac_wait_deps(struct emac_instance *dev)
+ {
+ 	struct emac_depentry deps[EMAC_DEP_COUNT];
+ 	int i, err;
+@@ -2367,7 +2367,7 @@ static int __devinit emac_wait_deps(struct emac_instance *dev)
+ 	return err;
+ }
+ 
+-static int __devinit emac_read_uint_prop(struct device_node *np, const char *name,
++static int emac_read_uint_prop(struct device_node *np, const char *name,
+ 					 u32 *val, int fatal)
+ {
+ 	int len;
+@@ -2382,7 +2382,7 @@ static int __devinit emac_read_uint_prop(struct device_node *np, const char *nam
+ 	return 0;
+ }
+ 
+-static int __devinit emac_init_phy(struct emac_instance *dev)
++static int emac_init_phy(struct emac_instance *dev)
+ {
+ 	struct device_node *np = dev->ofdev->dev.of_node;
+ 	struct net_device *ndev = dev->ndev;
+@@ -2518,7 +2518,7 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
+ 	return 0;
+ }
+ 
+-static int __devinit emac_init_config(struct emac_instance *dev)
++static int emac_init_config(struct emac_instance *dev)
+ {
+ 	struct device_node *np = dev->ofdev->dev.of_node;
+ 	const void *p;
+@@ -2703,7 +2703,7 @@ static const struct net_device_ops emac_gige_netdev_ops = {
+ 	.ndo_change_mtu		= emac_change_mtu,
+ };
+ 
+-static int __devinit emac_probe(struct platform_device *ofdev)
++static int emac_probe(struct platform_device *ofdev)
+ {
+ 	struct net_device *ndev;
+ 	struct emac_instance *dev;
+@@ -2930,7 +2930,7 @@ static int __devinit emac_probe(struct platform_device *ofdev)
+ 	return err;
+ }
+ 
+-static int __devexit emac_remove(struct platform_device *ofdev)
++static int emac_remove(struct platform_device *ofdev)
+ {
+ 	struct emac_instance *dev = dev_get_drvdata(&ofdev->dev);
+ 
+diff --git a/drivers/net/ethernet/ibm/emac/mal.c b/drivers/net/ethernet/ibm/emac/mal.c
+index 84c6b6cf9c14..8becaaf6eb5c 100644
+--- a/drivers/net/ethernet/ibm/emac/mal.c
++++ b/drivers/net/ethernet/ibm/emac/mal.c
+@@ -33,7 +33,7 @@
+ 
+ static int mal_count;
+ 
+-int __devinit mal_register_commac(struct mal_instance	*mal,
++int mal_register_commac(struct mal_instance	*mal,
+ 				  struct mal_commac	*commac)
+ {
+ 	unsigned long flags;
+@@ -517,7 +517,7 @@ void *mal_dump_regs(struct mal_instance *mal, void *buf)
+ 	return regs + 1;
+ }
+ 
+-static int __devinit mal_probe(struct platform_device *ofdev)
++static int mal_probe(struct platform_device *ofdev)
+ {
+ 	struct mal_instance *mal;
+ 	int err = 0, i, bd_size;
+@@ -729,7 +729,7 @@ static int __devinit mal_probe(struct platform_device *ofdev)
+ 	return err;
+ }
+ 
+-static int __devexit mal_remove(struct platform_device *ofdev)
++static int mal_remove(struct platform_device *ofdev)
+ {
+ 	struct mal_instance *mal = dev_get_drvdata(&ofdev->dev);
+ 
+diff --git a/drivers/net/ethernet/ibm/emac/rgmii.c b/drivers/net/ethernet/ibm/emac/rgmii.c
+index d3123282e18e..39251765b55d 100644
+--- a/drivers/net/ethernet/ibm/emac/rgmii.c
++++ b/drivers/net/ethernet/ibm/emac/rgmii.c
+@@ -93,7 +93,7 @@ static inline u32 rgmii_mode_mask(int mode, int input)
+ 	}
+ }
+ 
+-int __devinit rgmii_attach(struct platform_device *ofdev, int input, int mode)
++int rgmii_attach(struct platform_device *ofdev, int input, int mode)
+ {
+ 	struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev);
+ 	struct rgmii_regs __iomem *p = dev->base;
+@@ -228,7 +228,7 @@ void *rgmii_dump_regs(struct platform_device *ofdev, void *buf)
+ }
+ 
+ 
+-static int __devinit rgmii_probe(struct platform_device *ofdev)
++static int rgmii_probe(struct platform_device *ofdev)
+ {
+ 	struct device_node *np = ofdev->dev.of_node;
+ 	struct rgmii_instance *dev;
+@@ -289,7 +289,7 @@ static int __devinit rgmii_probe(struct platform_device *ofdev)
+ 	return rc;
+ }
+ 
+-static int __devexit rgmii_remove(struct platform_device *ofdev)
++static int rgmii_remove(struct platform_device *ofdev)
+ {
+ 	struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev);
+ 
+diff --git a/drivers/net/ethernet/ibm/emac/tah.c b/drivers/net/ethernet/ibm/emac/tah.c
+index 872912ef518d..795f1393e2b6 100644
+--- a/drivers/net/ethernet/ibm/emac/tah.c
++++ b/drivers/net/ethernet/ibm/emac/tah.c
+@@ -23,7 +23,7 @@
+ #include "emac.h"
+ #include "core.h"
+ 
+-int __devinit tah_attach(struct platform_device *ofdev, int channel)
++int tah_attach(struct platform_device *ofdev, int channel)
+ {
+ 	struct tah_instance *dev = dev_get_drvdata(&ofdev->dev);
+ 
+@@ -87,7 +87,7 @@ void *tah_dump_regs(struct platform_device *ofdev, void *buf)
+ 	return regs + 1;
+ }
+ 
+-static int __devinit tah_probe(struct platform_device *ofdev)
++static int tah_probe(struct platform_device *ofdev)
+ {
+ 	struct device_node *np = ofdev->dev.of_node;
+ 	struct tah_instance *dev;
+@@ -135,7 +135,7 @@ static int __devinit tah_probe(struct platform_device *ofdev)
+ 	return rc;
+ }
+ 
+-static int __devexit tah_remove(struct platform_device *ofdev)
++static int tah_remove(struct platform_device *ofdev)
+ {
+ 	struct tah_instance *dev = dev_get_drvdata(&ofdev->dev);
+ 
+diff --git a/drivers/net/ethernet/ibm/emac/zmii.c b/drivers/net/ethernet/ibm/emac/zmii.c
+index 415e9b4d5408..f91202f42125 100644
+--- a/drivers/net/ethernet/ibm/emac/zmii.c
++++ b/drivers/net/ethernet/ibm/emac/zmii.c
+@@ -82,7 +82,7 @@ static inline u32 zmii_mode_mask(int mode, int input)
+ 	}
+ }
+ 
+-int __devinit zmii_attach(struct platform_device *ofdev, int input, int *mode)
++int zmii_attach(struct platform_device *ofdev, int input, int *mode)
+ {
+ 	struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev);
+ 	struct zmii_regs __iomem *p = dev->base;
+@@ -231,7 +231,7 @@ void *zmii_dump_regs(struct platform_device *ofdev, void *buf)
+ 	return regs + 1;
+ }
+ 
+-static int __devinit zmii_probe(struct platform_device *ofdev)
++static int zmii_probe(struct platform_device *ofdev)
+ {
+ 	struct device_node *np = ofdev->dev.of_node;
+ 	struct zmii_instance *dev;
+@@ -282,7 +282,7 @@ static int __devinit zmii_probe(struct platform_device *ofdev)
+ 	return rc;
+ }
+ 
+-static int __devexit zmii_remove(struct platform_device *ofdev)
++static int zmii_remove(struct platform_device *ofdev)
+ {
+ 	struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev);
+ 

commit e11787a2313c41a1f4469d797b2d9bc6fe0642b1
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:12 2012 -0500
+
+    ibmveth: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Santiago Leon 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
+index b68d28a130e6..35485f2c144c 100644
+--- a/drivers/net/ethernet/ibm/ibmveth.c
++++ b/drivers/net/ethernet/ibm/ibmveth.c
+@@ -1324,7 +1324,7 @@ static const struct net_device_ops ibmveth_netdev_ops = {
+ #endif
+ };
+ 
+-static int __devinit ibmveth_probe(struct vio_dev *dev,
++static int ibmveth_probe(struct vio_dev *dev,
+ 				   const struct vio_device_id *id)
+ {
+ 	int rc, i;
+@@ -1426,7 +1426,7 @@ static int __devinit ibmveth_probe(struct vio_dev *dev,
+ 	return 0;
+ }
+ 
+-static int __devexit ibmveth_remove(struct vio_dev *dev)
++static int ibmveth_remove(struct vio_dev *dev)
+ {
+ 	struct net_device *netdev = dev_get_drvdata(&dev->dev);
+ 	struct ibmveth_adapter *adapter = netdev_priv(netdev);
+@@ -1593,7 +1593,7 @@ static int ibmveth_resume(struct device *dev)
+ 	return 0;
+ }
+ 
+-static struct vio_device_id ibmveth_device_table[] __devinitdata = {
++static struct vio_device_id ibmveth_device_table[] = {
+ 	{ "network", "IBM,l-lan"},
+ 	{ "", "" }
+ };

commit 170b52b873ca0772a1ae2453258eeec825d9b8af
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:11 2012 -0500
+
+    hp100: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Jaroslav Kysela 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/hp/hp100.c b/drivers/net/ethernet/hp/hp100.c
+index 3f4391bede81..598e576ddf51 100644
+--- a/drivers/net/ethernet/hp/hp100.c
++++ b/drivers/net/ethernet/hp/hp100.c
+@@ -308,7 +308,7 @@ static void wait(void)
+  * Read board id and convert to string.
+  * Effectively same code as decode_eisa_sig
+  */
+-static __devinit const char *hp100_read_id(int ioaddr)
++static const char *hp100_read_id(int ioaddr)
+ {
+ 	int i;
+ 	static char str[HP100_SIG_LEN];
+@@ -447,7 +447,7 @@ static const struct net_device_ops hp100_netdev_ops = {
+ 	.ndo_validate_addr	= eth_validate_addr,
+ };
+ 
+-static int __devinit hp100_probe1(struct net_device *dev, int ioaddr,
++static int hp100_probe1(struct net_device *dev, int ioaddr,
+ 				  u_char bus, struct pci_dev *pci_dev)
+ {
+ 	int i;
+@@ -2866,7 +2866,7 @@ static int __init hp100_eisa_probe (struct device *gendev)
+ 	return err;
+ }
+ 
+-static int __devexit hp100_eisa_remove (struct device *gendev)
++static int hp100_eisa_remove(struct device *gendev)
+ {
+ 	struct net_device *dev = dev_get_drvdata(gendev);
+ 	cleanup_dev(dev);
+@@ -2878,14 +2878,14 @@ static struct eisa_driver hp100_eisa_driver = {
+         .driver   = {
+                 .name    = "hp100",
+                 .probe   = hp100_eisa_probe,
+-                .remove  = __devexit_p (hp100_eisa_remove),
++		.remove	 = hp100_eisa_remove,
+         }
+ };
+ #endif
+ 
+ #ifdef CONFIG_PCI
+-static int __devinit hp100_pci_probe (struct pci_dev *pdev,
+-				     const struct pci_device_id *ent)
++static int hp100_pci_probe(struct pci_dev *pdev,
++			   const struct pci_device_id *ent)
+ {
+ 	struct net_device *dev;
+ 	int ioaddr;
+@@ -2937,7 +2937,7 @@ static int __devinit hp100_pci_probe (struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit hp100_pci_remove (struct pci_dev *pdev)
++static void hp100_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 
+@@ -2950,7 +2950,7 @@ static struct pci_driver hp100_pci_driver = {
+ 	.name		= "hp100",
+ 	.id_table	= hp100_pci_tbl,
+ 	.probe		= hp100_pci_probe,
+-	.remove		= __devexit_p(hp100_pci_remove),
++	.remove		= hp100_pci_remove,
+ };
+ #endif
+ 

commit 0297be07091fc809f27a9f50e5130d41c9ac3f52
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:10 2012 -0500
+
+    ehea: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Thadeu Lima de Souza Cascardo 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c
+index 09faf333e941..e238130574ca 100644
+--- a/drivers/net/ethernet/ibm/ehea/ehea_main.c
++++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c
+@@ -98,10 +98,10 @@ static struct ehea_fw_handle_array ehea_fw_handles;
+ static struct ehea_bcmc_reg_array ehea_bcmc_regs;
+ 
+ 
+-static int __devinit ehea_probe_adapter(struct platform_device *dev,
++static int ehea_probe_adapter(struct platform_device *dev,
+ 					const struct of_device_id *id);
+ 
+-static int __devexit ehea_remove(struct platform_device *dev);
++static int ehea_remove(struct platform_device *dev);
+ 
+ static struct of_device_id ehea_device_table[] = {
+ 	{
+@@ -2909,7 +2909,7 @@ static ssize_t ehea_show_port_id(struct device *dev,
+ static DEVICE_ATTR(log_port_id, S_IRUSR | S_IRGRP | S_IROTH, ehea_show_port_id,
+ 		   NULL);
+ 
+-static void __devinit logical_port_release(struct device *dev)
++static void logical_port_release(struct device *dev)
+ {
+ 	struct ehea_port *port = container_of(dev, struct ehea_port, ofdev.dev);
+ 	of_node_put(port->ofdev.dev.of_node);
+@@ -3257,7 +3257,7 @@ static void ehea_remove_device_sysfs(struct platform_device *dev)
+ 	device_remove_file(&dev->dev, &dev_attr_remove_port);
+ }
+ 
+-static int __devinit ehea_probe_adapter(struct platform_device *dev,
++static int ehea_probe_adapter(struct platform_device *dev,
+ 					const struct of_device_id *id)
+ {
+ 	struct ehea_adapter *adapter;
+@@ -3364,7 +3364,7 @@ static int __devinit ehea_probe_adapter(struct platform_device *dev,
+ 	return ret;
+ }
+ 
+-static int __devexit ehea_remove(struct platform_device *dev)
++static int ehea_remove(struct platform_device *dev)
+ {
+ 	struct ehea_adapter *adapter = dev_get_drvdata(&dev->dev);
+ 	int i;

commit 3bc6b06ce06039b981333e600f79963ae5a86dba
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:09 2012 -0500
+
+    be2net: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Sathya Perla 
+    Cc: Subbu Seetharaman 
+    Cc: Ajit Khaparde 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
+index 0661e9379583..b003abc24227 100644
+--- a/drivers/net/ethernet/emulex/benet/be_main.c
++++ b/drivers/net/ethernet/emulex/benet/be_main.c
+@@ -3761,7 +3761,7 @@ static int be_stats_init(struct be_adapter *adapter)
+ 	return 0;
+ }
+ 
+-static void __devexit be_remove(struct pci_dev *pdev)
++static void be_remove(struct pci_dev *pdev)
+ {
+ 	struct be_adapter *adapter = pci_get_drvdata(pdev);
+ 
+@@ -3994,7 +3994,7 @@ static inline char *func_name(struct be_adapter *adapter)
+ 	return be_physfn(adapter) ? "PF" : "VF";
+ }
+ 
+-static int __devinit be_probe(struct pci_dev *pdev,
++static int be_probe(struct pci_dev *pdev,
+ 			const struct pci_device_id *pdev_id)
+ {
+ 	int status = 0;

commit 4f2c53ea27a8d12aaf07f61b5d13d20cadfdefd0
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:08 2012 -0500
+
+    fs_enet: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Pantelis Antoniou 
+    Cc: Vitaly Bordug 
+    Cc: linuxppc-dev@lists.ozlabs.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+index 2b7633f766d9..e9879c5af7ba 100644
+--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
++++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+@@ -1004,7 +1004,7 @@ static const struct net_device_ops fs_enet_netdev_ops = {
+ };
+ 
+ static struct of_device_id fs_enet_match[];
+-static int __devinit fs_enet_probe(struct platform_device *ofdev)
++static int fs_enet_probe(struct platform_device *ofdev)
+ {
+ 	const struct of_device_id *match;
+ 	struct net_device *ndev;
+diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c
+index 151453309401..3f35b6a983e9 100644
+--- a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c
++++ b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c
+@@ -108,7 +108,7 @@ static struct mdiobb_ops bb_ops = {
+ 	.get_mdio_data = mdio_read,
+ };
+ 
+-static int __devinit fs_mii_bitbang_init(struct mii_bus *bus,
++static int fs_mii_bitbang_init(struct mii_bus *bus,
+                                          struct device_node *np)
+ {
+ 	struct resource res;
+@@ -150,7 +150,7 @@ static int __devinit fs_mii_bitbang_init(struct mii_bus *bus,
+ 	return 0;
+ }
+ 
+-static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev)
++static int fs_enet_mdio_probe(struct platform_device *ofdev)
+ {
+ 	struct mii_bus *new_bus;
+ 	struct bb_info *bitbang;
+diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c
+index cdf702a59485..18e8ef203736 100644
+--- a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c
++++ b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c
+@@ -102,7 +102,7 @@ static int fs_enet_fec_mii_reset(struct mii_bus *bus)
+ }
+ 
+ static struct of_device_id fs_enet_mdio_fec_match[];
+-static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev)
++static int fs_enet_mdio_probe(struct platform_device *ofdev)
+ {
+ 	const struct of_device_id *match;
+ 	struct resource res;

commit 64bc40de134bb5c7826ff384016f654219ed3956
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:07 2012 -0500
+
+    dlink: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c
+index 2fb01bf18155..1d342d37915c 100644
+--- a/drivers/net/ethernet/dlink/dl2k.c
++++ b/drivers/net/ethernet/dlink/dl2k.c
+@@ -23,7 +23,7 @@
+ #define dr16(reg)	ioread16(ioaddr + (reg))
+ #define dr8(reg)	ioread8(ioaddr + (reg))
+ 
+-static char version[] __devinitdata =
++static char version[] =
+       KERN_INFO DRV_NAME " " DRV_VERSION " " DRV_RELDATE "\n";
+ #define MAX_UNITS 8
+ static int mtu[MAX_UNITS];
+@@ -110,7 +110,7 @@ static const struct net_device_ops netdev_ops = {
+ 	.ndo_change_mtu		= change_mtu,
+ };
+ 
+-static int __devinit
++static int
+ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ 	struct net_device *dev;
+@@ -1727,7 +1727,7 @@ rio_close (struct net_device *dev)
+ 	return 0;
+ }
+ 
+-static void __devexit
++static void
+ rio_remove1 (struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata (pdev);
+@@ -1755,7 +1755,7 @@ static struct pci_driver rio_driver = {
+ 	.name		= "dl2k",
+ 	.id_table	= rio_pci_tbl,
+ 	.probe		= rio_probe1,
+-	.remove		= __devexit_p(rio_remove1),
++	.remove		= rio_remove1,
+ };
+ 
+ module_pci_driver(rio_driver);
+diff --git a/drivers/net/ethernet/dlink/sundance.c b/drivers/net/ethernet/dlink/sundance.c
+index 3b83588e51f6..2a5a5b0a5cae 100644
+--- a/drivers/net/ethernet/dlink/sundance.c
++++ b/drivers/net/ethernet/dlink/sundance.c
+@@ -102,7 +102,7 @@ static char *media[MAX_UNITS];
+ #include 
+ 
+ /* These identify the driver base version and may not be removed. */
+-static const char version[] __devinitconst =
++static const char version[] =
+ 	KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE
+ 	" Written by Donald Becker\n";
+ 
+@@ -218,7 +218,7 @@ enum {
+ struct pci_id_info {
+         const char *name;
+ };
+-static const struct pci_id_info pci_id_tbl[] __devinitconst = {
++static const struct pci_id_info pci_id_tbl[] = {
+ 	{"D-Link DFE-550TX FAST Ethernet Adapter"},
+ 	{"D-Link DFE-550FX 100Mbps Fiber-optics Adapter"},
+ 	{"D-Link DFE-580TX 4 port Server Adapter"},
+@@ -472,8 +472,8 @@ static const struct net_device_ops netdev_ops = {
+ 	.ndo_validate_addr	= eth_validate_addr,
+ };
+ 
+-static int __devinit sundance_probe1 (struct pci_dev *pdev,
+-				      const struct pci_device_id *ent)
++static int sundance_probe1(struct pci_dev *pdev,
++			   const struct pci_device_id *ent)
+ {
+ 	struct net_device *dev;
+ 	struct netdev_private *np;
+@@ -701,7 +701,7 @@ static int change_mtu(struct net_device *dev, int new_mtu)
+ 
+ #define eeprom_delay(ee_addr)	ioread32(ee_addr)
+ /* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. */
+-static int __devinit eeprom_read(void __iomem *ioaddr, int location)
++static int eeprom_read(void __iomem *ioaddr, int location)
+ {
+ 	int boguscnt = 10000;		/* Typical 1900 ticks. */
+ 	iowrite16(0x0200 | (location & 0xff), ioaddr + EECtrl);
+@@ -1844,7 +1844,7 @@ static int netdev_close(struct net_device *dev)
+ 	return 0;
+ }
+ 
+-static void __devexit sundance_remove1 (struct pci_dev *pdev)
++static void sundance_remove1(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 
+@@ -1910,7 +1910,7 @@ static struct pci_driver sundance_driver = {
+ 	.name		= DRV_NAME,
+ 	.id_table	= sundance_pci_tbl,
+ 	.probe		= sundance_probe1,
+-	.remove		= __devexit_p(sundance_remove1),
++	.remove		= sundance_remove1,
+ #ifdef CONFIG_PM
+ 	.suspend	= sundance_suspend,
+ 	.resume		= sundance_resume,

commit 6b6a3e7f65e5736030032b4d39901479ba437e5f
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:06 2012 -0500
+
+    dm9000: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
+index 36499d5edd95..c716e95a61fe 100644
+--- a/drivers/net/ethernet/davicom/dm9000.c
++++ b/drivers/net/ethernet/davicom/dm9000.c
+@@ -1359,7 +1359,7 @@ static const struct net_device_ops dm9000_netdev_ops = {
+ /*
+  * Search DM9000 board, allocate space and register it
+  */
+-static int __devinit
++static int
+ dm9000_probe(struct platform_device *pdev)
+ {
+ 	struct dm9000_plat_data *pdata = pdev->dev.platform_data;
+@@ -1661,7 +1661,7 @@ static const struct dev_pm_ops dm9000_drv_pm_ops = {
+ 	.resume		= dm9000_drv_resume,
+ };
+ 
+-static int __devexit
++static int
+ dm9000_drv_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *ndev = platform_get_drvdata(pdev);
+@@ -1683,7 +1683,7 @@ static struct platform_driver dm9000_driver = {
+ 		.pm	 = &dm9000_drv_pm_ops,
+ 	},
+ 	.probe   = dm9000_probe,
+-	.remove  = __devexit_p(dm9000_drv_remove),
++	.remove  = dm9000_drv_remove,
+ };
+ 
+ static int __init

commit 854de92f6d3471e694ea807a52b2670862b15d42
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:05 2012 -0500
+
+    enic: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Christian Benvenuti 
+    Cc: Roopa Prabhu 
+    Cc: Neel Patel 
+    Cc: Nishank Trivedi 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
+index ad1468b3ab91..930f03bd1263 100644
+--- a/drivers/net/ethernet/cisco/enic/enic_main.c
++++ b/drivers/net/ethernet/cisco/enic/enic_main.c
+@@ -2275,7 +2275,7 @@ static void enic_iounmap(struct enic *enic)
+ 			iounmap(enic->bar[i].vaddr);
+ }
+ 
+-static int __devinit enic_probe(struct pci_dev *pdev,
++static int enic_probe(struct pci_dev *pdev,
+ 	const struct pci_device_id *ent)
+ {
+ 	struct device *dev = &pdev->dev;
+@@ -2552,7 +2552,7 @@ static int __devinit enic_probe(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit enic_remove(struct pci_dev *pdev)
++static void enic_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *netdev = pci_get_drvdata(pdev);
+ 
+@@ -2584,7 +2584,7 @@ static struct pci_driver enic_driver = {
+ 	.name = DRV_NAME,
+ 	.id_table = enic_id_table,
+ 	.probe = enic_probe,
+-	.remove = __devexit_p(enic_remove),
++	.remove = enic_remove,
+ };
+ 
+ static int __init enic_init_module(void)

commit ff76a3cca3a2f8664e0625cb4d75601ff9ccde76
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:04 2012 -0500
+
+    chelsio: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
+index 1d17c92f2dda..5f60623dd7fd 100644
+--- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
++++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
+@@ -974,7 +974,7 @@ static const struct net_device_ops cxgb_netdev_ops = {
+ #endif
+ };
+ 
+-static int __devinit init_one(struct pci_dev *pdev,
++static int init_one(struct pci_dev *pdev,
+ 			      const struct pci_device_id *ent)
+ {
+ 	static int version_printed;
+@@ -1332,7 +1332,7 @@ static inline void t1_sw_reset(struct pci_dev *pdev)
+ 	pci_write_config_dword(pdev, A_PCICFG_PM_CSR, 0);
+ }
+ 
+-static void __devexit remove_one(struct pci_dev *pdev)
++static void remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct adapter *adapter = dev->ml_priv;
+@@ -1361,7 +1361,7 @@ static struct pci_driver driver = {
+ 	.name     = DRV_NAME,
+ 	.id_table = t1_pci_tbl,
+ 	.probe    = init_one,
+-	.remove   = __devexit_p(remove_one),
++	.remove   = remove_one,
+ };
+ 
+ static int __init t1_init_module(void)
+diff --git a/drivers/net/ethernet/chelsio/cxgb/sge.c b/drivers/net/ethernet/chelsio/cxgb/sge.c
+index 47a84359d4e4..9a0a85898a50 100644
+--- a/drivers/net/ethernet/chelsio/cxgb/sge.c
++++ b/drivers/net/ethernet/chelsio/cxgb/sge.c
+@@ -2071,7 +2071,7 @@ static void espibug_workaround(unsigned long data)
+ /*
+  * Creates a t1_sge structure and returns suggested resource parameters.
+  */
+-struct sge * __devinit t1_sge_create(struct adapter *adapter,
++struct sge *t1_sge_create(struct adapter *adapter,
+ 				     struct sge_params *p)
+ {
+ 	struct sge *sge = kzalloc(sizeof(*sge), GFP_KERNEL);
+diff --git a/drivers/net/ethernet/chelsio/cxgb/subr.c b/drivers/net/ethernet/chelsio/cxgb/subr.c
+index 8a43c7e19701..9527dc196f87 100644
+--- a/drivers/net/ethernet/chelsio/cxgb/subr.c
++++ b/drivers/net/ethernet/chelsio/cxgb/subr.c
+@@ -892,7 +892,7 @@ static void power_sequence_xpak(adapter_t* adapter)
+ 	}
+ }
+ 
+-int __devinit t1_get_board_rev(adapter_t *adapter, const struct board_info *bi,
++int t1_get_board_rev(adapter_t *adapter, const struct board_info *bi,
+ 			       struct adapter_params *p)
+ {
+ 	p->chip_version = bi->chip_term;
+@@ -992,7 +992,7 @@ int t1_init_hw_modules(adapter_t *adapter)
+ /*
+  * Determine a card's PCI mode.
+  */
+-static void __devinit get_pci_mode(adapter_t *adapter, struct chelsio_pci_params *p)
++static void get_pci_mode(adapter_t *adapter, struct chelsio_pci_params *p)
+ {
+ 	static const unsigned short speed_map[] = { 33, 66, 100, 133 };
+ 	u32 pci_mode;
+@@ -1028,7 +1028,7 @@ void t1_free_sw_modules(adapter_t *adapter)
+ 		t1_espi_destroy(adapter->espi);
+ }
+ 
+-static void __devinit init_link_config(struct link_config *lc,
++static void init_link_config(struct link_config *lc,
+ 				       const struct board_info *bi)
+ {
+ 	lc->supported = bi->caps;
+@@ -1049,7 +1049,7 @@ static void __devinit init_link_config(struct link_config *lc,
+  * Allocate and initialize the data structures that hold the SW state of
+  * the Terminator HW modules.
+  */
+-int __devinit t1_init_sw_modules(adapter_t *adapter,
++int t1_init_sw_modules(adapter_t *adapter,
+ 				 const struct board_info *bi)
+ {
+ 	unsigned int i;
+diff --git a/drivers/net/ethernet/chelsio/cxgb/tp.c b/drivers/net/ethernet/chelsio/cxgb/tp.c
+index 8bed4a59e65f..b146acabf982 100644
+--- a/drivers/net/ethernet/chelsio/cxgb/tp.c
++++ b/drivers/net/ethernet/chelsio/cxgb/tp.c
+@@ -55,7 +55,7 @@ void t1_tp_destroy(struct petp *tp)
+ 	kfree(tp);
+ }
+ 
+-struct petp *__devinit t1_tp_create(adapter_t * adapter, struct tp_params *p)
++struct petp *t1_tp_create(adapter_t *adapter, struct tp_params *p)
+ {
+ 	struct petp *tp = kzalloc(sizeof(*tp), GFP_KERNEL);
+ 

commit d289f864601eb3678824ba3c0b15217af79171e0
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:03 2012 -0500
+
+    cxgb4vf: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Casey Leedom 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+index 9dad56101e23..f866eb5e35de 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
++++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+@@ -2023,7 +2023,7 @@ static struct cxgb4vf_debugfs_entry debugfs_files[] = {
+  * Set up out /sys/kernel/debug/cxgb4vf sub-nodes.  We assume that the
+  * directory (debugfs_root) has already been set up.
+  */
+-static int __devinit setup_debugfs(struct adapter *adapter)
++static int setup_debugfs(struct adapter *adapter)
+ {
+ 	int i;
+ 
+@@ -2064,7 +2064,7 @@ static void cleanup_debugfs(struct adapter *adapter)
+  * adapter parameters we're going to be using and initialize basic adapter
+  * hardware support.
+  */
+-static int __devinit adap_init0(struct adapter *adapter)
++static int adap_init0(struct adapter *adapter)
+ {
+ 	struct vf_resources *vfres = &adapter->params.vfres;
+ 	struct sge_params *sge_params = &adapter->params.sge;
+@@ -2266,7 +2266,7 @@ static inline void init_rspq(struct sge_rspq *rspq, u8 timer_idx,
+  * be modified by the admin via ethtool and cxgbtool prior to the adapter
+  * being brought up for the first time.
+  */
+-static void __devinit cfg_queues(struct adapter *adapter)
++static void cfg_queues(struct adapter *adapter)
+ {
+ 	struct sge *s = &adapter->sge;
+ 	int q10g, n10g, qidx, pidx, qs;
+@@ -2361,7 +2361,7 @@ static void __devinit cfg_queues(struct adapter *adapter)
+  * Reduce the number of Ethernet queues across all ports to at most n.
+  * n provides at least one queue per port.
+  */
+-static void __devinit reduce_ethqs(struct adapter *adapter, int n)
++static void reduce_ethqs(struct adapter *adapter, int n)
+ {
+ 	int i;
+ 	struct port_info *pi;
+@@ -2400,7 +2400,7 @@ static void __devinit reduce_ethqs(struct adapter *adapter, int n)
+  * for our "extras".  Note that this process may lower the maximum number of
+  * allowed Queue Sets ...
+  */
+-static int __devinit enable_msix(struct adapter *adapter)
++static int enable_msix(struct adapter *adapter)
+ {
+ 	int i, err, want, need;
+ 	struct msix_entry entries[MSIX_ENTRIES];
+@@ -2462,7 +2462,7 @@ static const struct net_device_ops cxgb4vf_netdev_ops	= {
+  * state needed to manage the device.  This routine is called "init_one" in
+  * the PF Driver ...
+  */
+-static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev,
++static int cxgb4vf_pci_probe(struct pci_dev *pdev,
+ 				       const struct pci_device_id *ent)
+ {
+ 	static int version_printed;
+@@ -2769,7 +2769,7 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev,
+  * "probe" routine and quiesce the device (disable interrupts, etc.).  (Note
+  * that this is called "remove_one" in the PF Driver.)
+  */
+-static void __devexit cxgb4vf_pci_remove(struct pci_dev *pdev)
++static void cxgb4vf_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct adapter *adapter = pci_get_drvdata(pdev);
+ 
+@@ -2835,7 +2835,7 @@ static void __devexit cxgb4vf_pci_remove(struct pci_dev *pdev)
+  * "Shutdown" quiesce the device, stopping Ingress Packet and Interrupt
+  * delivery.
+  */
+-static void __devexit cxgb4vf_pci_shutdown(struct pci_dev *pdev)
++static void cxgb4vf_pci_shutdown(struct pci_dev *pdev)
+ {
+ 	struct adapter *adapter;
+ 	int pidx;
+@@ -2905,8 +2905,8 @@ static struct pci_driver cxgb4vf_driver = {
+ 	.name		= KBUILD_MODNAME,
+ 	.id_table	= cxgb4vf_pci_tbl,
+ 	.probe		= cxgb4vf_pci_probe,
+-	.remove		= __devexit_p(cxgb4vf_pci_remove),
+-	.shutdown	= __devexit_p(cxgb4vf_pci_shutdown),
++	.remove		= cxgb4vf_pci_remove,
++	.shutdown	= cxgb4vf_pci_shutdown,
+ };
+ 
+ /*
+diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
+index a65c80aed1f2..283f9d0d37fd 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
++++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
+@@ -232,8 +232,8 @@ static inline int t4vf_wr_mbox_ns(struct adapter *adapter, const void *cmd,
+ 	return t4vf_wr_mbox_core(adapter, cmd, size, rpl, false);
+ }
+ 
+-int __devinit t4vf_wait_dev_ready(struct adapter *);
+-int __devinit t4vf_port_init(struct adapter *, int);
++int t4vf_wait_dev_ready(struct adapter *);
++int t4vf_port_init(struct adapter *, int);
+ 
+ int t4vf_fw_reset(struct adapter *);
+ int t4vf_query_params(struct adapter *, unsigned int, const u32 *, u32 *);
+diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
+index fe3fd3dad6f7..9b70cccf8437 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
++++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
+@@ -46,7 +46,7 @@
+  * returning a value other than all 1's).  Return an error if it doesn't
+  * become ready ...
+  */
+-int __devinit t4vf_wait_dev_ready(struct adapter *adapter)
++int t4vf_wait_dev_ready(struct adapter *adapter)
+ {
+ 	const u32 whoami = T4VF_PL_BASE_ADDR + PL_VF_WHOAMI;
+ 	const u32 notready1 = 0xffffffff;
+@@ -253,7 +253,7 @@ static int hash_mac_addr(const u8 *addr)
+  *	Initializes the SW state maintained for each link, including the link's
+  *	capabilities and default speed/flow-control/autonegotiation settings.
+  */
+-static void __devinit init_link_config(struct link_config *lc,
++static void init_link_config(struct link_config *lc,
+ 				       unsigned int caps)
+ {
+ 	lc->supported = caps;
+@@ -275,7 +275,7 @@ static void __devinit init_link_config(struct link_config *lc,
+  *	@adapter: the adapter
+  *	@pidx: the adapter port index
+  */
+-int __devinit t4vf_port_init(struct adapter *adapter, int pidx)
++int t4vf_port_init(struct adapter *adapter, int pidx)
+ {
+ 	struct port_info *pi = adap2pinfo(adapter, pidx);
+ 	struct fw_vi_cmd vi_cmd, vi_rpl;

commit 91744948659a5cf937a9094f50f09c412656ca4a
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:02 2012 -0500
+
+    cxgb4: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Dimitris Michailidis 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+index 0df1284df497..bef893d4c68a 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
++++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+@@ -2148,7 +2148,7 @@ static const struct file_operations mem_debugfs_fops = {
+ 	.llseek  = default_llseek,
+ };
+ 
+-static void __devinit add_debugfs_mem(struct adapter *adap, const char *name,
++static void add_debugfs_mem(struct adapter *adap, const char *name,
+ 				      unsigned int idx, unsigned int size_mb)
+ {
+ 	struct dentry *de;
+@@ -2159,7 +2159,7 @@ static void __devinit add_debugfs_mem(struct adapter *adap, const char *name,
+ 		de->d_inode->i_size = size_mb << 20;
+ }
+ 
+-static int __devinit setup_debugfs(struct adapter *adap)
++static int setup_debugfs(struct adapter *adap)
+ {
+ 	int i;
+ 
+@@ -4173,7 +4173,7 @@ static inline void init_rspq(struct sge_rspq *q, u8 timer_idx, u8 pkt_cnt_idx,
+  * of ports we found and the number of available CPUs.  Most settings can be
+  * modified by the admin prior to actual use.
+  */
+-static void __devinit cfg_queues(struct adapter *adap)
++static void cfg_queues(struct adapter *adap)
+ {
+ 	struct sge *s = &adap->sge;
+ 	int i, q10g = 0, n10g = 0, qidx = 0;
+@@ -4257,7 +4257,7 @@ static void __devinit cfg_queues(struct adapter *adap)
+  * Reduce the number of Ethernet queues across all ports to at most n.
+  * n provides at least one queue per port.
+  */
+-static void __devinit reduce_ethqs(struct adapter *adap, int n)
++static void reduce_ethqs(struct adapter *adap, int n)
+ {
+ 	int i;
+ 	struct port_info *pi;
+@@ -4284,7 +4284,7 @@ static void __devinit reduce_ethqs(struct adapter *adap, int n)
+ /* 2 MSI-X vectors needed for the FW queue and non-data interrupts */
+ #define EXTRA_VECS 2
+ 
+-static int __devinit enable_msix(struct adapter *adap)
++static int enable_msix(struct adapter *adap)
+ {
+ 	int ofld_need = 0;
+ 	int i, err, want, need;
+@@ -4333,7 +4333,7 @@ static int __devinit enable_msix(struct adapter *adap)
+ 
+ #undef EXTRA_VECS
+ 
+-static int __devinit init_rss(struct adapter *adap)
++static int init_rss(struct adapter *adap)
+ {
+ 	unsigned int i, j;
+ 
+@@ -4349,7 +4349,7 @@ static int __devinit init_rss(struct adapter *adap)
+ 	return 0;
+ }
+ 
+-static void __devinit print_port_info(const struct net_device *dev)
++static void print_port_info(const struct net_device *dev)
+ {
+ 	static const char *base[] = {
+ 		"R XFI", "R XAUI", "T SGMII", "T XFI", "T XAUI", "KX4", "CX4",
+@@ -4386,7 +4386,7 @@ static void __devinit print_port_info(const struct net_device *dev)
+ 		    adap->params.vpd.sn, adap->params.vpd.ec);
+ }
+ 
+-static void __devinit enable_pcie_relaxed_ordering(struct pci_dev *dev)
++static void enable_pcie_relaxed_ordering(struct pci_dev *dev)
+ {
+ 	pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_RELAX_EN);
+ }
+@@ -4419,7 +4419,7 @@ static void free_some_resources(struct adapter *adapter)
+ #define VLAN_FEAT (NETIF_F_SG | NETIF_F_IP_CSUM | TSO_FLAGS | \
+ 		   NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA)
+ 
+-static int __devinit init_one(struct pci_dev *pdev,
++static int init_one(struct pci_dev *pdev,
+ 			      const struct pci_device_id *ent)
+ {
+ 	int func, i, err;
+@@ -4640,7 +4640,7 @@ static int __devinit init_one(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit remove_one(struct pci_dev *pdev)
++static void remove_one(struct pci_dev *pdev)
+ {
+ 	struct adapter *adapter = pci_get_drvdata(pdev);
+ 
+@@ -4680,7 +4680,7 @@ static struct pci_driver cxgb4_driver = {
+ 	.name     = KBUILD_MODNAME,
+ 	.id_table = cxgb4_pci_tbl,
+ 	.probe    = init_one,
+-	.remove   = __devexit_p(remove_one),
++	.remove   = remove_one,
+ 	.err_handler = &cxgb4_eeh,
+ };
+ 
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+index 730ae2cfa49e..8ea773630d10 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
++++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+@@ -2003,7 +2003,7 @@ void t4_tp_wr_bits_indirect(struct adapter *adap, unsigned int addr,
+  *
+  *	Initialize the congestion control parameters.
+  */
+-static void __devinit init_cong_ctrl(unsigned short *a, unsigned short *b)
++static void init_cong_ctrl(unsigned short *a, unsigned short *b)
+ {
+ 	a[0] = a[1] = a[2] = a[3] = a[4] = a[5] = a[6] = a[7] = a[8] = 1;
+ 	a[9] = 2;
+@@ -3440,7 +3440,7 @@ int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl)
+ 	return 0;
+ }
+ 
+-static void __devinit get_pci_mode(struct adapter *adapter,
++static void get_pci_mode(struct adapter *adapter,
+ 				   struct pci_params *p)
+ {
+ 	u16 val;
+@@ -3460,7 +3460,7 @@ static void __devinit get_pci_mode(struct adapter *adapter,
+  *	Initializes the SW state maintained for each link, including the link's
+  *	capabilities and default speed/flow-control/autonegotiation settings.
+  */
+-static void __devinit init_link_config(struct link_config *lc,
++static void init_link_config(struct link_config *lc,
+ 				       unsigned int caps)
+ {
+ 	lc->supported = caps;
+@@ -3485,7 +3485,7 @@ int t4_wait_dev_ready(struct adapter *adap)
+ 	return t4_read_reg(adap, PL_WHOAMI) != 0xffffffff ? 0 : -EIO;
+ }
+ 
+-static int __devinit get_flash_params(struct adapter *adap)
++static int get_flash_params(struct adapter *adap)
+ {
+ 	int ret;
+ 	u32 info;
+@@ -3521,7 +3521,7 @@ static int __devinit get_flash_params(struct adapter *adap)
+  *	values for some adapter tunables, take PHYs out of reset, and
+  *	initialize the MDIO interface.
+  */
+-int __devinit t4_prep_adapter(struct adapter *adapter)
++int t4_prep_adapter(struct adapter *adapter)
+ {
+ 	int ret;
+ 
+@@ -3549,7 +3549,7 @@ int __devinit t4_prep_adapter(struct adapter *adapter)
+ 	return 0;
+ }
+ 
+-int __devinit t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
++int t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
+ {
+ 	u8 addr[6];
+ 	int ret, i, j = 0;

commit 2109eaab72cf95cbb2af51253b46a72e4f2180c9
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:01 2012 -0500
+
+    cxgb3: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Divy Le Ray 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+index 9c9f3260344a..4aa3b21c6f7f 100644
+--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
++++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+@@ -3078,7 +3078,7 @@ static void set_nqsets(struct adapter *adap)
+ 	}
+ }
+ 
+-static int __devinit cxgb_enable_msix(struct adapter *adap)
++static int cxgb_enable_msix(struct adapter *adap)
+ {
+ 	struct msix_entry entries[SGE_QSETS + 1];
+ 	int vectors;
+@@ -3108,7 +3108,7 @@ static int __devinit cxgb_enable_msix(struct adapter *adap)
+ 	return err;
+ }
+ 
+-static void __devinit print_port_info(struct adapter *adap,
++static void print_port_info(struct adapter *adap,
+ 				      const struct adapter_info *ai)
+ {
+ 	static const char *pci_variant[] = {
+@@ -3165,7 +3165,7 @@ static const struct net_device_ops cxgb_netdev_ops = {
+ #endif
+ };
+ 
+-static void __devinit cxgb3_init_iscsi_mac(struct net_device *dev)
++static void cxgb3_init_iscsi_mac(struct net_device *dev)
+ {
+ 	struct port_info *pi = netdev_priv(dev);
+ 
+@@ -3176,7 +3176,7 @@ static void __devinit cxgb3_init_iscsi_mac(struct net_device *dev)
+ #define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN)
+ #define VLAN_FEAT (NETIF_F_SG | NETIF_F_IP_CSUM | TSO_FLAGS | \
+ 			NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA)
+-static int __devinit init_one(struct pci_dev *pdev,
++static int init_one(struct pci_dev *pdev,
+ 			      const struct pci_device_id *ent)
+ {
+ 	static int version_printed;
+@@ -3381,7 +3381,7 @@ static int __devinit init_one(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit remove_one(struct pci_dev *pdev)
++static void remove_one(struct pci_dev *pdev)
+ {
+ 	struct adapter *adapter = pci_get_drvdata(pdev);
+ 
+@@ -3425,7 +3425,7 @@ static struct pci_driver driver = {
+ 	.name = DRV_NAME,
+ 	.id_table = cxgb3_pci_tbl,
+ 	.probe = init_one,
+-	.remove = __devexit_p(remove_one),
++	.remove = remove_one,
+ 	.err_handler = &t3_err_handler,
+ };
+ 
+diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
+index 2dbbcbb450d3..942dace361d2 100644
+--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
++++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
+@@ -1382,7 +1382,7 @@ static inline int adap2type(struct adapter *adapter)
+ 	return type;
+ }
+ 
+-void __devinit cxgb3_adapter_ofld(struct adapter *adapter)
++void cxgb3_adapter_ofld(struct adapter *adapter)
+ {
+ 	struct t3cdev *tdev = &adapter->tdev;
+ 
+@@ -1396,7 +1396,7 @@ void __devinit cxgb3_adapter_ofld(struct adapter *adapter)
+ 	register_tdev(tdev);
+ }
+ 
+-void __devexit cxgb3_adapter_unofld(struct adapter *adapter)
++void cxgb3_adapter_unofld(struct adapter *adapter)
+ {
+ 	struct t3cdev *tdev = &adapter->tdev;
+ 

commit c4eef189aaef84612de3961b2681fbf794afca20
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:23:00 2012 -0500
+
+    bna: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Rasesh Mody 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
+index ce1eac529470..76b2af64adc2 100644
+--- a/drivers/net/ethernet/brocade/bna/bnad.c
++++ b/drivers/net/ethernet/brocade/bna/bnad.c
+@@ -3226,7 +3226,7 @@ bnad_pci_uninit(struct pci_dev *pdev)
+ 	pci_disable_device(pdev);
+ }
+ 
+-static int __devinit
++static int
+ bnad_pci_probe(struct pci_dev *pdev,
+ 		const struct pci_device_id *pcidev_id)
+ {
+@@ -3426,7 +3426,7 @@ bnad_pci_probe(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit
++static void
+ bnad_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *netdev = pci_get_drvdata(pdev);
+@@ -3490,7 +3490,7 @@ static struct pci_driver bnad_pci_driver = {
+ 	.name = BNAD_NAME,
+ 	.id_table = bnad_pci_id_table,
+ 	.probe = bnad_pci_probe,
+-	.remove = __devexit_p(bnad_pci_remove),
++	.remove = bnad_pci_remove,
+ };
+ 
+ static int __init

commit 229b1ad1cb1a7159658f466c736bc3898dabb876
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:22:59 2012 -0500
+
+    tg3: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Matt Carlson 
+    Cc: Michael Chan 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
+index 5cc976d01189..ac94939c03e6 100644
+--- a/drivers/net/ethernet/broadcom/tg3.c
++++ b/drivers/net/ethernet/broadcom/tg3.c
+@@ -211,7 +211,7 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
+ #define FIRMWARE_TG3TSO		"tigon/tg3_tso.bin"
+ #define FIRMWARE_TG3TSO5	"tigon/tg3_tso5.bin"
+ 
+-static char version[] __devinitdata =
++static char version[] =
+ 	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")";
+ 
+ MODULE_AUTHOR("David S. Miller (davem@redhat.com) and Jeff Garzik (jgarzik@pobox.com)");
+@@ -9938,7 +9938,7 @@ static void tg3_timer(unsigned long __opaque)
+ 	add_timer(&tp->timer);
+ }
+ 
+-static void __devinit tg3_timer_init(struct tg3 *tp)
++static void tg3_timer_init(struct tg3 *tp)
+ {
+ 	if (tg3_flag(tp, TAGGED_STATUS) &&
+ 	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 &&
+@@ -12829,7 +12829,7 @@ static const struct net_device_ops tg3_netdev_ops = {
+ #endif
+ };
+ 
+-static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
++static void tg3_get_eeprom_size(struct tg3 *tp)
+ {
+ 	u32 cursize, val, magic;
+ 
+@@ -12863,7 +12863,7 @@ static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
+ 	tp->nvram_size = cursize;
+ }
+ 
+-static void __devinit tg3_get_nvram_size(struct tg3 *tp)
++static void tg3_get_nvram_size(struct tg3 *tp)
+ {
+ 	u32 val;
+ 
+@@ -12896,7 +12896,7 @@ static void __devinit tg3_get_nvram_size(struct tg3 *tp)
+ 	tp->nvram_size = TG3_NVRAM_SIZE_512KB;
+ }
+ 
+-static void __devinit tg3_get_nvram_info(struct tg3 *tp)
++static void tg3_get_nvram_info(struct tg3 *tp)
+ {
+ 	u32 nvcfg1;
+ 
+@@ -12947,7 +12947,7 @@ static void __devinit tg3_get_nvram_info(struct tg3 *tp)
+ 	}
+ }
+ 
+-static void __devinit tg3_nvram_get_pagesize(struct tg3 *tp, u32 nvmcfg1)
++static void tg3_nvram_get_pagesize(struct tg3 *tp, u32 nvmcfg1)
+ {
+ 	switch (nvmcfg1 & NVRAM_CFG1_5752PAGE_SIZE_MASK) {
+ 	case FLASH_5752PAGE_SIZE_256:
+@@ -12974,7 +12974,7 @@ static void __devinit tg3_nvram_get_pagesize(struct tg3 *tp, u32 nvmcfg1)
+ 	}
+ }
+ 
+-static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp)
++static void tg3_get_5752_nvram_info(struct tg3 *tp)
+ {
+ 	u32 nvcfg1;
+ 
+@@ -13015,7 +13015,7 @@ static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp)
+ 	}
+ }
+ 
+-static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp)
++static void tg3_get_5755_nvram_info(struct tg3 *tp)
+ {
+ 	u32 nvcfg1, protect = 0;
+ 
+@@ -13071,7 +13071,7 @@ static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp)
+ 	}
+ }
+ 
+-static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp)
++static void tg3_get_5787_nvram_info(struct tg3 *tp)
+ {
+ 	u32 nvcfg1;
+ 
+@@ -13109,7 +13109,7 @@ static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp)
+ 	}
+ }
+ 
+-static void __devinit tg3_get_5761_nvram_info(struct tg3 *tp)
++static void tg3_get_5761_nvram_info(struct tg3 *tp)
+ {
+ 	u32 nvcfg1, protect = 0;
+ 
+@@ -13184,14 +13184,14 @@ static void __devinit tg3_get_5761_nvram_info(struct tg3 *tp)
+ 	}
+ }
+ 
+-static void __devinit tg3_get_5906_nvram_info(struct tg3 *tp)
++static void tg3_get_5906_nvram_info(struct tg3 *tp)
+ {
+ 	tp->nvram_jedecnum = JEDEC_ATMEL;
+ 	tg3_flag_set(tp, NVRAM_BUFFERED);
+ 	tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
+ }
+ 
+-static void __devinit tg3_get_57780_nvram_info(struct tg3 *tp)
++static void tg3_get_57780_nvram_info(struct tg3 *tp)
+ {
+ 	u32 nvcfg1;
+ 
+@@ -13264,7 +13264,7 @@ static void __devinit tg3_get_57780_nvram_info(struct tg3 *tp)
+ }
+ 
+ 
+-static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp)
++static void tg3_get_5717_nvram_info(struct tg3 *tp)
+ {
+ 	u32 nvcfg1;
+ 
+@@ -13342,7 +13342,7 @@ static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp)
+ 		tg3_flag_set(tp, NO_NVRAM_ADDR_TRANS);
+ }
+ 
+-static void __devinit tg3_get_5720_nvram_info(struct tg3 *tp)
++static void tg3_get_5720_nvram_info(struct tg3 *tp)
+ {
+ 	u32 nvcfg1, nvmpinstrp;
+ 
+@@ -13455,7 +13455,7 @@ static void __devinit tg3_get_5720_nvram_info(struct tg3 *tp)
+ }
+ 
+ /* Chips other than 5700/5701 use the NVRAM for fetching info. */
+-static void __devinit tg3_nvram_init(struct tg3 *tp)
++static void tg3_nvram_init(struct tg3 *tp)
+ {
+ 	tw32_f(GRC_EEPROM_ADDR,
+ 	     (EEPROM_ADDR_FSM_RESET |
+@@ -13525,7 +13525,7 @@ struct subsys_tbl_ent {
+ 	u32 phy_id;
+ };
+ 
+-static struct subsys_tbl_ent subsys_id_to_phy_id[] __devinitdata = {
++static struct subsys_tbl_ent subsys_id_to_phy_id[] = {
+ 	/* Broadcom boards. */
+ 	{ TG3PCI_SUBVENDOR_ID_BROADCOM,
+ 	  TG3PCI_SUBDEVICE_ID_BROADCOM_95700A6, TG3_PHY_ID_BCM5401 },
+@@ -13589,7 +13589,7 @@ static struct subsys_tbl_ent subsys_id_to_phy_id[] __devinitdata = {
+ 	  TG3PCI_SUBDEVICE_ID_IBM_5703SAX2, 0 }
+ };
+ 
+-static struct subsys_tbl_ent * __devinit tg3_lookup_by_subsys(struct tg3 *tp)
++static struct subsys_tbl_ent *tg3_lookup_by_subsys(struct tg3 *tp)
+ {
+ 	int i;
+ 
+@@ -13603,7 +13603,7 @@ static struct subsys_tbl_ent * __devinit tg3_lookup_by_subsys(struct tg3 *tp)
+ 	return NULL;
+ }
+ 
+-static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
++static void tg3_get_eeprom_hw_cfg(struct tg3 *tp)
+ {
+ 	u32 val;
+ 
+@@ -13803,7 +13803,7 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
+ 		device_set_wakeup_capable(&tp->pdev->dev, false);
+ }
+ 
+-static int __devinit tg3_issue_otp_command(struct tg3 *tp, u32 cmd)
++static int tg3_issue_otp_command(struct tg3 *tp, u32 cmd)
+ {
+ 	int i;
+ 	u32 val;
+@@ -13826,7 +13826,7 @@ static int __devinit tg3_issue_otp_command(struct tg3 *tp, u32 cmd)
+  * configuration is a 32-bit value that straddles the alignment boundary.
+  * We do two 32-bit reads and then shift and merge the results.
+  */
+-static u32 __devinit tg3_read_otp_phycfg(struct tg3 *tp)
++static u32 tg3_read_otp_phycfg(struct tg3 *tp)
+ {
+ 	u32 bhalf_otp, thalf_otp;
+ 
+@@ -13852,7 +13852,7 @@ static u32 __devinit tg3_read_otp_phycfg(struct tg3 *tp)
+ 	return ((thalf_otp & 0x0000ffff) << 16) | (bhalf_otp >> 16);
+ }
+ 
+-static void __devinit tg3_phy_init_link_config(struct tg3 *tp)
++static void tg3_phy_init_link_config(struct tg3 *tp)
+ {
+ 	u32 adv = ADVERTISED_Autoneg;
+ 
+@@ -13879,7 +13879,7 @@ static void __devinit tg3_phy_init_link_config(struct tg3 *tp)
+ 	tp->old_link = -1;
+ }
+ 
+-static int __devinit tg3_phy_probe(struct tg3 *tp)
++static int tg3_phy_probe(struct tg3 *tp)
+ {
+ 	u32 hw_phy_id_1, hw_phy_id_2;
+ 	u32 hw_phy_id, hw_phy_id_masked;
+@@ -14007,7 +14007,7 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
+ 	return err;
+ }
+ 
+-static void __devinit tg3_read_vpd(struct tg3 *tp)
++static void tg3_read_vpd(struct tg3 *tp)
+ {
+ 	u8 *vpd_data;
+ 	unsigned int block_end, rosize, len;
+@@ -14128,7 +14128,7 @@ static void __devinit tg3_read_vpd(struct tg3 *tp)
+ 	}
+ }
+ 
+-static int __devinit tg3_fw_img_is_valid(struct tg3 *tp, u32 offset)
++static int tg3_fw_img_is_valid(struct tg3 *tp, u32 offset)
+ {
+ 	u32 val;
+ 
+@@ -14141,7 +14141,7 @@ static int __devinit tg3_fw_img_is_valid(struct tg3 *tp, u32 offset)
+ 	return 1;
+ }
+ 
+-static void __devinit tg3_read_bc_ver(struct tg3 *tp)
++static void tg3_read_bc_ver(struct tg3 *tp)
+ {
+ 	u32 val, offset, start, ver_offset;
+ 	int i, dst_off;
+@@ -14193,7 +14193,7 @@ static void __devinit tg3_read_bc_ver(struct tg3 *tp)
+ 	}
+ }
+ 
+-static void __devinit tg3_read_hwsb_ver(struct tg3 *tp)
++static void tg3_read_hwsb_ver(struct tg3 *tp)
+ {
+ 	u32 val, major, minor;
+ 
+@@ -14209,7 +14209,7 @@ static void __devinit tg3_read_hwsb_ver(struct tg3 *tp)
+ 	snprintf(&tp->fw_ver[0], 32, "sb v%d.%02d", major, minor);
+ }
+ 
+-static void __devinit tg3_read_sb_ver(struct tg3 *tp, u32 val)
++static void tg3_read_sb_ver(struct tg3 *tp, u32 val)
+ {
+ 	u32 offset, major, minor, build;
+ 
+@@ -14264,7 +14264,7 @@ static void __devinit tg3_read_sb_ver(struct tg3 *tp, u32 val)
+ 	}
+ }
+ 
+-static void __devinit tg3_read_mgmtfw_ver(struct tg3 *tp)
++static void tg3_read_mgmtfw_ver(struct tg3 *tp)
+ {
+ 	u32 val, offset, start;
+ 	int i, vlen;
+@@ -14316,7 +14316,7 @@ static void __devinit tg3_read_mgmtfw_ver(struct tg3 *tp)
+ 	}
+ }
+ 
+-static void __devinit tg3_probe_ncsi(struct tg3 *tp)
++static void tg3_probe_ncsi(struct tg3 *tp)
+ {
+ 	u32 apedata;
+ 
+@@ -14332,7 +14332,7 @@ static void __devinit tg3_probe_ncsi(struct tg3 *tp)
+ 		tg3_flag_set(tp, APE_HAS_NCSI);
+ }
+ 
+-static void __devinit tg3_read_dash_ver(struct tg3 *tp)
++static void tg3_read_dash_ver(struct tg3 *tp)
+ {
+ 	int vlen;
+ 	u32 apedata;
+@@ -14355,7 +14355,7 @@ static void __devinit tg3_read_dash_ver(struct tg3 *tp)
+ 		 (apedata & APE_FW_VERSION_BLDMSK));
+ }
+ 
+-static void __devinit tg3_read_fw_ver(struct tg3 *tp)
++static void tg3_read_fw_ver(struct tg3 *tp)
+ {
+ 	u32 val;
+ 	bool vpd_vers = false;
+@@ -14408,7 +14408,7 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_write_reorder_chipsets) = {
+ 	{ },
+ };
+ 
+-static struct pci_dev * __devinit tg3_find_peer(struct tg3 *tp)
++static struct pci_dev *tg3_find_peer(struct tg3 *tp)
+ {
+ 	struct pci_dev *peer;
+ 	unsigned int func, devnr = tp->pdev->devfn & ~7;
+@@ -14436,7 +14436,7 @@ static struct pci_dev * __devinit tg3_find_peer(struct tg3 *tp)
+ 	return peer;
+ }
+ 
+-static void __devinit tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg)
++static void tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg)
+ {
+ 	tp->pci_chip_rev_id = misc_ctrl_reg >> MISC_HOST_CTRL_CHIPREV_SHIFT;
+ 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_USE_PROD_ID_REG) {
+@@ -14539,7 +14539,7 @@ static bool tg3_10_100_only_device(struct tg3 *tp,
+ 	return false;
+ }
+ 
+-static int __devinit tg3_get_invariants(struct tg3 *tp,
++static int tg3_get_invariants(struct tg3 *tp,
+ 					const struct pci_device_id *ent)
+ {
+ 	u32 misc_ctrl_reg;
+@@ -15299,7 +15299,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp,
+ }
+ 
+ #ifdef CONFIG_SPARC
+-static int __devinit tg3_get_macaddr_sparc(struct tg3 *tp)
++static int tg3_get_macaddr_sparc(struct tg3 *tp)
+ {
+ 	struct net_device *dev = tp->dev;
+ 	struct pci_dev *pdev = tp->pdev;
+@@ -15316,7 +15316,7 @@ static int __devinit tg3_get_macaddr_sparc(struct tg3 *tp)
+ 	return -ENODEV;
+ }
+ 
+-static int __devinit tg3_get_default_macaddr_sparc(struct tg3 *tp)
++static int tg3_get_default_macaddr_sparc(struct tg3 *tp)
+ {
+ 	struct net_device *dev = tp->dev;
+ 
+@@ -15326,7 +15326,7 @@ static int __devinit tg3_get_default_macaddr_sparc(struct tg3 *tp)
+ }
+ #endif
+ 
+-static int __devinit tg3_get_device_address(struct tg3 *tp)
++static int tg3_get_device_address(struct tg3 *tp)
+ {
+ 	struct net_device *dev = tp->dev;
+ 	u32 hi, lo, mac_offset;
+@@ -15405,7 +15405,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
+ #define BOUNDARY_SINGLE_CACHELINE	1
+ #define BOUNDARY_MULTI_CACHELINE	2
+ 
+-static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val)
++static u32 tg3_calc_dma_bndry(struct tg3 *tp, u32 val)
+ {
+ 	int cacheline_size;
+ 	u8 byte;
+@@ -15546,7 +15546,8 @@ static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val)
+ 	return val;
+ }
+ 
+-static int __devinit tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dma, int size, int to_device)
++static int tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dma,
++			   int size, int to_device)
+ {
+ 	struct tg3_internal_buffer_desc test_desc;
+ 	u32 sram_dma_descs;
+@@ -15633,7 +15634,7 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_dma_wait_state_chipsets) = {
+ 	{ },
+ };
+ 
+-static int __devinit tg3_test_dma(struct tg3 *tp)
++static int tg3_test_dma(struct tg3 *tp)
+ {
+ 	dma_addr_t buf_dma;
+ 	u32 *buf, saved_dma_rwctrl;
+@@ -15823,7 +15824,7 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
+ 	return ret;
+ }
+ 
+-static void __devinit tg3_init_bufmgr_config(struct tg3 *tp)
++static void tg3_init_bufmgr_config(struct tg3 *tp)
+ {
+ 	if (tg3_flag(tp, 57765_PLUS)) {
+ 		tp->bufmgr_config.mbuf_read_dma_low_water =
+@@ -15879,7 +15880,7 @@ static void __devinit tg3_init_bufmgr_config(struct tg3 *tp)
+ 	tp->bufmgr_config.dma_high_water = DEFAULT_DMA_HIGH_WATER;
+ }
+ 
+-static char * __devinit tg3_phy_string(struct tg3 *tp)
++static char *tg3_phy_string(struct tg3 *tp)
+ {
+ 	switch (tp->phy_id & TG3_PHY_ID_MASK) {
+ 	case TG3_PHY_ID_BCM5400:	return "5400";
+@@ -15910,7 +15911,7 @@ static char * __devinit tg3_phy_string(struct tg3 *tp)
+ 	}
+ }
+ 
+-static char * __devinit tg3_bus_string(struct tg3 *tp, char *str)
++static char *tg3_bus_string(struct tg3 *tp, char *str)
+ {
+ 	if (tg3_flag(tp, PCI_EXPRESS)) {
+ 		strcpy(str, "PCI Express");
+@@ -15946,7 +15947,7 @@ static char * __devinit tg3_bus_string(struct tg3 *tp, char *str)
+ 	return str;
+ }
+ 
+-static void __devinit tg3_init_coal(struct tg3 *tp)
++static void tg3_init_coal(struct tg3 *tp)
+ {
+ 	struct ethtool_coalesce *ec = &tp->coal;
+ 
+@@ -15977,7 +15978,7 @@ static void __devinit tg3_init_coal(struct tg3 *tp)
+ 	}
+ }
+ 
+-static int __devinit tg3_init_one(struct pci_dev *pdev,
++static int tg3_init_one(struct pci_dev *pdev,
+ 				  const struct pci_device_id *ent)
+ {
+ 	struct net_device *dev;
+@@ -16357,7 +16358,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit tg3_remove_one(struct pci_dev *pdev)
++static void tg3_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 
+@@ -16626,7 +16627,7 @@ static struct pci_driver tg3_driver = {
+ 	.name		= DRV_MODULE_NAME,
+ 	.id_table	= tg3_pci_tbl,
+ 	.probe		= tg3_init_one,
+-	.remove		= __devexit_p(tg3_remove_one),
++	.remove		= tg3_remove_one,
+ 	.err_handler	= &tg3_err_handler,
+ 	.driver.pm	= TG3_PM_OPS,
+ };

commit cfd95a634f49358ab8d2a759c637fef0b50e7583
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:22:58 2012 -0500
+
+    bnx2: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Michael Chan 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
+index d4310700c7a7..e264e960a762 100644
+--- a/drivers/net/ethernet/broadcom/bnx2.c
++++ b/drivers/net/ethernet/broadcom/bnx2.c
+@@ -71,7 +71,7 @@
+ /* Time in jiffies before concluding the transmitter is hung. */
+ #define TX_TIMEOUT  (5*HZ)
+ 
+-static char version[] __devinitdata =
++static char version[] =
+ 	"Broadcom NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+ 
+ MODULE_AUTHOR("Michael Chan ");
+@@ -106,7 +106,7 @@ typedef enum {
+ /* indexed by board_t, above */
+ static struct {
+ 	char *name;
+-} board_info[] __devinitdata = {
++} board_info[] = {
+ 	{ "Broadcom NetXtreme II BCM5706 1000Base-T" },
+ 	{ "HP NC370T Multifunction Gigabit Server Adapter" },
+ 	{ "HP NC370i Multifunction Gigabit Server Adapter" },
+@@ -7896,7 +7896,7 @@ poll_bnx2(struct net_device *dev)
+ }
+ #endif
+ 
+-static void __devinit
++static void
+ bnx2_get_5709_media(struct bnx2 *bp)
+ {
+ 	u32 val = REG_RD(bp, BNX2_MISC_DUAL_MEDIA_CTRL);
+@@ -7934,7 +7934,7 @@ bnx2_get_5709_media(struct bnx2 *bp)
+ 	}
+ }
+ 
+-static void __devinit
++static void
+ bnx2_get_pci_speed(struct bnx2 *bp)
+ {
+ 	u32 reg;
+@@ -7986,7 +7986,7 @@ bnx2_get_pci_speed(struct bnx2 *bp)
+ 
+ }
+ 
+-static void __devinit
++static void
+ bnx2_read_vpd_fw_ver(struct bnx2 *bp)
+ {
+ 	int rc, i, j;
+@@ -8054,7 +8054,7 @@ bnx2_read_vpd_fw_ver(struct bnx2 *bp)
+ 	kfree(data);
+ }
+ 
+-static int __devinit
++static int
+ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
+ {
+ 	struct bnx2 *bp;
+@@ -8439,7 +8439,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
+ 	return rc;
+ }
+ 
+-static char * __devinit
++static char *
+ bnx2_bus_string(struct bnx2 *bp, char *str)
+ {
+ 	char *s = str;
+@@ -8505,7 +8505,7 @@ static const struct net_device_ops bnx2_netdev_ops = {
+ #endif
+ };
+ 
+-static int __devinit
++static int
+ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ 	static int version_printed = 0;
+@@ -8573,7 +8573,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	return rc;
+ }
+ 
+-static void __devexit
++static void
+ bnx2_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+@@ -8752,7 +8752,7 @@ static struct pci_driver bnx2_pci_driver = {
+ 	.name		= DRV_MODULE_NAME,
+ 	.id_table	= bnx2_pci_tbl,
+ 	.probe		= bnx2_init_one,
+-	.remove		= __devexit_p(bnx2_remove_one),
++	.remove		= bnx2_remove_one,
+ 	.suspend	= bnx2_suspend,
+ 	.resume		= bnx2_resume,
+ 	.err_handler	= &bnx2_err_handler,

commit 239718871072b45370816cf272ea29c0d34b3d12
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:22:57 2012 -0500
+
+    b44: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Gary Zambrano 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c
+index 9786c0e9890e..c64351f486cd 100644
+--- a/drivers/net/ethernet/broadcom/b44.c
++++ b/drivers/net/ethernet/broadcom/b44.c
+@@ -2083,7 +2083,7 @@ static int b44_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ 	return err;
+ }
+ 
+-static int __devinit b44_get_invariants(struct b44 *bp)
++static int b44_get_invariants(struct b44 *bp)
+ {
+ 	struct ssb_device *sdev = bp->sdev;
+ 	int err = 0;
+@@ -2141,7 +2141,7 @@ static const struct net_device_ops b44_netdev_ops = {
+ #endif
+ };
+ 
+-static int __devinit b44_init_one(struct ssb_device *sdev,
++static int b44_init_one(struct ssb_device *sdev,
+ 				  const struct ssb_device_id *ent)
+ {
+ 	struct net_device *dev;
+@@ -2249,7 +2249,7 @@ static int __devinit b44_init_one(struct ssb_device *sdev,
+ 	return err;
+ }
+ 
+-static void __devexit b44_remove_one(struct ssb_device *sdev)
++static void b44_remove_one(struct ssb_device *sdev)
+ {
+ 	struct net_device *dev = ssb_get_drvdata(sdev);
+ 
+@@ -2340,7 +2340,7 @@ static struct ssb_driver b44_ssb_driver = {
+ 	.name		= DRV_MODULE_NAME,
+ 	.id_table	= b44_ssb_tbl,
+ 	.probe		= b44_init_one,
+-	.remove		= __devexit_p(b44_remove_one),
++	.remove		= b44_remove_one,
+ 	.suspend	= b44_suspend,
+ 	.resume		= b44_resume,
+ };

commit a9590879e12f920d8b2fc74c019b5d1604068862
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:22:56 2012 -0500
+
+    pcnet32: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Don Fry 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c
+index 86b6d8e4e6cd..a227ccdcb9b5 100644
+--- a/drivers/net/ethernet/amd/pcnet32.c
++++ b/drivers/net/ethernet/amd/pcnet32.c
+@@ -1443,7 +1443,7 @@ static const struct ethtool_ops pcnet32_ethtool_ops = {
+ /* only probes for non-PCI devices, the rest are handled by
+  * pci_register_driver via pcnet32_probe_pci */
+ 
+-static void __devinit pcnet32_probe_vlbus(unsigned int *pcnet32_portlist)
++static void pcnet32_probe_vlbus(unsigned int *pcnet32_portlist)
+ {
+ 	unsigned int *port, ioaddr;
+ 
+@@ -1462,7 +1462,7 @@ static void __devinit pcnet32_probe_vlbus(unsigned int *pcnet32_portlist)
+ 	}
+ }
+ 
+-static int __devinit
++static int
+ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ 	unsigned long ioaddr;
+@@ -1521,7 +1521,7 @@ static const struct net_device_ops pcnet32_netdev_ops = {
+  *  Called from both pcnet32_probe_vlbus and pcnet_probe_pci.
+  *  pdev will be NULL when called from pcnet32_probe_vlbus.
+  */
+-static int __devinit
++static int
+ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
+ {
+ 	struct pcnet32_private *lp;
+@@ -2823,7 +2823,7 @@ static int pcnet32_pm_resume(struct pci_dev *pdev)
+ 	return 0;
+ }
+ 
+-static void __devexit pcnet32_remove_one(struct pci_dev *pdev)
++static void pcnet32_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 
+@@ -2844,7 +2844,7 @@ static void __devexit pcnet32_remove_one(struct pci_dev *pdev)
+ static struct pci_driver pcnet32_driver = {
+ 	.name = DRV_NAME,
+ 	.probe = pcnet32_probe_pci,
+-	.remove = __devexit_p(pcnet32_remove_one),
++	.remove = pcnet32_remove_one,
+ 	.id_table = pcnet32_pci_tbl,
+ 	.suspend = pcnet32_pm_suspend,
+ 	.resume = pcnet32_pm_resume,

commit c0c0e29d8c94fb483bf94a2157f1ef0a7fb70b55
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:22:55 2012 -0500
+
+    aeroflex: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Kristoffer Glembo 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c
+index 9c77c736f171..aa53115bb38b 100644
+--- a/drivers/net/ethernet/aeroflex/greth.c
++++ b/drivers/net/ethernet/aeroflex/greth.c
+@@ -1376,7 +1376,7 @@ static int greth_mdio_init(struct greth_private *greth)
+ }
+ 
+ /* Initialize the GRETH MAC */
+-static int __devinit greth_of_probe(struct platform_device *ofdev)
++static int greth_of_probe(struct platform_device *ofdev)
+ {
+ 	struct net_device *dev;
+ 	struct greth_private *greth;
+@@ -1576,7 +1576,7 @@ static int __devinit greth_of_probe(struct platform_device *ofdev)
+ 	return err;
+ }
+ 
+-static int __devexit greth_of_remove(struct platform_device *of_dev)
++static int greth_of_remove(struct platform_device *of_dev)
+ {
+ 	struct net_device *ndev = dev_get_drvdata(&of_dev->dev);
+ 	struct greth_private *greth = netdev_priv(ndev);
+@@ -1619,7 +1619,7 @@ static struct platform_driver greth_of_driver = {
+ 		.of_match_table = greth_of_match,
+ 	},
+ 	.probe = greth_of_probe,
+-	.remove = __devexit_p(greth_of_remove),
++	.remove = greth_of_remove,
+ };
+ 
+ module_platform_driver(greth_of_driver);

commit 49f7315b3ece7900cbe763da2af67928fbdf6d55
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:22:54 2012 -0500
+
+    bfin_mac: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: uclinux-dist-devel@blackfin.uclinux.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/adi/bfin_mac.c b/drivers/net/ethernet/adi/bfin_mac.c
+index f1c458dc039a..c1fdb8be8bee 100644
+--- a/drivers/net/ethernet/adi/bfin_mac.c
++++ b/drivers/net/ethernet/adi/bfin_mac.c
+@@ -1603,7 +1603,7 @@ static const struct net_device_ops bfin_mac_netdev_ops = {
+ #endif
+ };
+ 
+-static int __devinit bfin_mac_probe(struct platform_device *pdev)
++static int bfin_mac_probe(struct platform_device *pdev)
+ {
+ 	struct net_device *ndev;
+ 	struct bfin_mac_local *lp;
+@@ -1727,7 +1727,7 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev)
+ 	return rc;
+ }
+ 
+-static int __devexit bfin_mac_remove(struct platform_device *pdev)
++static int bfin_mac_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *ndev = platform_get_drvdata(pdev);
+ 	struct bfin_mac_local *lp = netdev_priv(ndev);
+@@ -1786,7 +1786,7 @@ static int bfin_mac_resume(struct platform_device *pdev)
+ #define bfin_mac_resume NULL
+ #endif	/* CONFIG_PM */
+ 
+-static int __devinit bfin_mii_bus_probe(struct platform_device *pdev)
++static int bfin_mii_bus_probe(struct platform_device *pdev)
+ {
+ 	struct mii_bus *miibus;
+ 	struct bfin_mii_bus_platform_data *mii_bus_pd;
+@@ -1864,7 +1864,7 @@ static int __devinit bfin_mii_bus_probe(struct platform_device *pdev)
+ 	return rc;
+ }
+ 
+-static int __devexit bfin_mii_bus_remove(struct platform_device *pdev)
++static int bfin_mii_bus_remove(struct platform_device *pdev)
+ {
+ 	struct mii_bus *miibus = platform_get_drvdata(pdev);
+ 	struct bfin_mii_bus_platform_data *mii_bus_pd =
+@@ -1881,7 +1881,7 @@ static int __devexit bfin_mii_bus_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver bfin_mii_bus_driver = {
+ 	.probe = bfin_mii_bus_probe,
+-	.remove = __devexit_p(bfin_mii_bus_remove),
++	.remove = bfin_mii_bus_remove,
+ 	.driver = {
+ 		.name = "bfin_mii_bus",
+ 		.owner	= THIS_MODULE,
+@@ -1890,7 +1890,7 @@ static struct platform_driver bfin_mii_bus_driver = {
+ 
+ static struct platform_driver bfin_mac_driver = {
+ 	.probe = bfin_mac_probe,
+-	.remove = __devexit_p(bfin_mac_remove),
++	.remove = bfin_mac_remove,
+ 	.resume = bfin_mac_resume,
+ 	.suspend = bfin_mac_suspend,
+ 	.driver = {

commit d3ace588d8f55b526f03c7277c8cf08a87ea7ce7
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:22:53 2012 -0500
+
+    starfire: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Ion Badulescu 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c
+index 5b65992c2a0a..d67c192b6505 100644
+--- a/drivers/net/ethernet/adaptec/starfire.c
++++ b/drivers/net/ethernet/adaptec/starfire.c
+@@ -166,7 +166,7 @@ static int rx_copybreak /* = 0 */;
+ #define FIRMWARE_TX	"adaptec/starfire_tx.bin"
+ 
+ /* These identify the driver base version and may not be removed. */
+-static const char version[] __devinitconst =
++static const char version[] =
+ KERN_INFO "starfire.c:v1.03 7/26/2000  Written by Donald Becker \n"
+ " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n";
+ 
+@@ -295,7 +295,7 @@ MODULE_DEVICE_TABLE(pci, starfire_pci_tbl);
+ static const struct chip_info {
+ 	const char *name;
+ 	int drv_flags;
+-} netdrv_tbl[] __devinitconst = {
++} netdrv_tbl[] = {
+ 	{ "Adaptec Starfire 6915", CanHaveMII },
+ };
+ 
+@@ -641,7 +641,7 @@ static const struct net_device_ops netdev_ops = {
+ #endif
+ };
+ 
+-static int __devinit starfire_init_one(struct pci_dev *pdev,
++static int starfire_init_one(struct pci_dev *pdev,
+ 				       const struct pci_device_id *ent)
+ {
+ 	struct device *d = &pdev->dev;
+@@ -1990,7 +1990,7 @@ static int starfire_resume(struct pci_dev *pdev)
+ #endif /* CONFIG_PM */
+ 
+ 
+-static void __devexit starfire_remove_one (struct pci_dev *pdev)
++static void starfire_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct netdev_private *np = netdev_priv(dev);
+@@ -2018,7 +2018,7 @@ static void __devexit starfire_remove_one (struct pci_dev *pdev)
+ static struct pci_driver starfire_driver = {
+ 	.name		= DRV_NAME,
+ 	.probe		= starfire_init_one,
+-	.remove		= __devexit_p(starfire_remove_one),
++	.remove		= starfire_remove_one,
+ #ifdef CONFIG_PM
+ 	.suspend	= starfire_suspend,
+ 	.resume		= starfire_resume,

commit 083abbb7dc16b6b6955ef6f5299bdbff9877363f
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:22:52 2012 -0500
+
+    acenic: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Jes Sorensen 
+    Cc: linux-acenic@sunsite.dk
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/alteon/acenic.c b/drivers/net/ethernet/alteon/acenic.c
+index 7219123fa0a4..dfddce6342e5 100644
+--- a/drivers/net/ethernet/alteon/acenic.c
++++ b/drivers/net/ethernet/alteon/acenic.c
+@@ -426,7 +426,7 @@ MODULE_PARM_DESC(max_rx_desc, "AceNIC/3C985/GA620 max number of receive descript
+ MODULE_PARM_DESC(tx_ratio, "AceNIC/3C985/GA620 ratio of NIC memory used for TX/RX descriptors (range 0-63)");
+ 
+ 
+-static const char version[] __devinitconst =
++static const char version[] =
+   "acenic.c: v0.92 08/05/2002  Jes Sorensen, linux-acenic@SunSITE.dk\n"
+   "                            http://home.cern.ch/~jes/gige/acenic.html\n";
+ 
+@@ -454,7 +454,7 @@ static const struct net_device_ops ace_netdev_ops = {
+ 	.ndo_change_mtu		= ace_change_mtu,
+ };
+ 
+-static int __devinit acenic_probe_one(struct pci_dev *pdev,
++static int acenic_probe_one(struct pci_dev *pdev,
+ 		const struct pci_device_id *id)
+ {
+ 	struct net_device *dev;
+@@ -603,7 +603,7 @@ static int __devinit acenic_probe_one(struct pci_dev *pdev,
+ 	return -ENODEV;
+ }
+ 
+-static void __devexit acenic_remove_one(struct pci_dev *pdev)
++static void acenic_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct ace_private *ap = netdev_priv(dev);
+@@ -699,7 +699,7 @@ static struct pci_driver acenic_pci_driver = {
+ 	.name		= "acenic",
+ 	.id_table	= acenic_pci_tbl,
+ 	.probe		= acenic_probe_one,
+-	.remove		= __devexit_p(acenic_remove_one),
++	.remove		= acenic_remove_one,
+ };
+ 
+ static int __init acenic_init(void)
+@@ -871,7 +871,7 @@ static inline void ace_issue_cmd(struct ace_regs __iomem *regs, struct cmd *cmd)
+ }
+ 
+ 
+-static int __devinit ace_init(struct net_device *dev)
++static int ace_init(struct net_device *dev)
+ {
+ 	struct ace_private *ap;
+ 	struct ace_regs __iomem *regs;
+@@ -2824,7 +2824,7 @@ static struct net_device_stats *ace_get_stats(struct net_device *dev)
+ }
+ 
+ 
+-static void __devinit ace_copy(struct ace_regs __iomem *regs, const __be32 *src,
++static void ace_copy(struct ace_regs __iomem *regs, const __be32 *src,
+ 			       u32 dest, int size)
+ {
+ 	void __iomem *tdest;
+@@ -2851,7 +2851,7 @@ static void __devinit ace_copy(struct ace_regs __iomem *regs, const __be32 *src,
+ }
+ 
+ 
+-static void __devinit ace_clear(struct ace_regs __iomem *regs, u32 dest, int size)
++static void ace_clear(struct ace_regs __iomem *regs, u32 dest, int size)
+ {
+ 	void __iomem *tdest;
+ 	short tsize = 0, i;
+@@ -2882,7 +2882,7 @@ static void __devinit ace_clear(struct ace_regs __iomem *regs, u32 dest, int siz
+  * This operation requires the NIC to be halted and is performed with
+  * interrupts disabled and with the spinlock hold.
+  */
+-static int __devinit ace_load_firmware(struct net_device *dev)
++static int ace_load_firmware(struct net_device *dev)
+ {
+ 	const struct firmware *fw;
+ 	const char *fw_name = "acenic/tg2.bin";
+@@ -2962,7 +2962,7 @@ static int __devinit ace_load_firmware(struct net_device *dev)
+  * Thanks to Stevarino Webinski for helping tracking down the bugs in the
+  * code i2c readout code by beta testing all my hacks.
+  */
+-static void __devinit eeprom_start(struct ace_regs __iomem *regs)
++static void eeprom_start(struct ace_regs __iomem *regs)
+ {
+ 	u32 local;
+ 
+@@ -2991,7 +2991,7 @@ static void __devinit eeprom_start(struct ace_regs __iomem *regs)
+ }
+ 
+ 
+-static void __devinit eeprom_prep(struct ace_regs __iomem *regs, u8 magic)
++static void eeprom_prep(struct ace_regs __iomem *regs, u8 magic)
+ {
+ 	short i;
+ 	u32 local;
+@@ -3028,7 +3028,7 @@ static void __devinit eeprom_prep(struct ace_regs __iomem *regs, u8 magic)
+ }
+ 
+ 
+-static int __devinit eeprom_check_ack(struct ace_regs __iomem *regs)
++static int eeprom_check_ack(struct ace_regs __iomem *regs)
+ {
+ 	int state;
+ 	u32 local;
+@@ -3056,7 +3056,7 @@ static int __devinit eeprom_check_ack(struct ace_regs __iomem *regs)
+ }
+ 
+ 
+-static void __devinit eeprom_stop(struct ace_regs __iomem *regs)
++static void eeprom_stop(struct ace_regs __iomem *regs)
+ {
+ 	u32 local;
+ 
+@@ -3091,7 +3091,7 @@ static void __devinit eeprom_stop(struct ace_regs __iomem *regs)
+ /*
+  * Read a whole byte from the EEPROM.
+  */
+-static int __devinit read_eeprom_byte(struct net_device *dev,
++static int read_eeprom_byte(struct net_device *dev,
+ 				   unsigned long offset)
+ {
+ 	struct ace_private *ap = netdev_priv(dev);

commit 4168ac0eb323fa1f886830a19b7f263643bc0cbd
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:22:51 2012 -0500
+
+    8390: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/8390/etherh.c b/drivers/net/ethernet/8390/etherh.c
+index 6414e84516c0..78c6fb4b1143 100644
+--- a/drivers/net/ethernet/8390/etherh.c
++++ b/drivers/net/ethernet/8390/etherh.c
+@@ -521,7 +521,7 @@ static void __init etherh_banner(void)
+  * Read the ethernet address string from the on board rom.
+  * This is an ascii string...
+  */
+-static int __devinit etherh_addr(char *addr, struct expansion_card *ec)
++static int etherh_addr(char *addr, struct expansion_card *ec)
+ {
+ 	struct in_chunk_dir cd;
+ 	char *s;
+@@ -651,7 +651,7 @@ static const struct net_device_ops etherh_netdev_ops = {
+ static u32 etherh_regoffsets[16];
+ static u32 etherm_regoffsets[16];
+ 
+-static int __devinit
++static int
+ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
+ {
+ 	const struct etherh_data *data = id->data;
+@@ -769,7 +769,7 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
+ 	return ret;
+ }
+ 
+-static void __devexit etherh_remove(struct expansion_card *ec)
++static void etherh_remove(struct expansion_card *ec)
+ {
+ 	struct net_device *dev = ecard_get_drvdata(ec);
+ 
+@@ -833,7 +833,7 @@ static const struct ecard_id etherh_ids[] = {
+ 
+ static struct ecard_driver etherh_driver = {
+ 	.probe		= etherh_probe,
+-	.remove		= __devexit_p(etherh_remove),
++	.remove		= etherh_remove,
+ 	.id_table	= etherh_ids,
+ 	.drv = {
+ 		.name	= DRV_NAME,
+diff --git a/drivers/net/ethernet/8390/hydra.c b/drivers/net/ethernet/8390/hydra.c
+index 5370c884620b..bc81de1b7d4f 100644
+--- a/drivers/net/ethernet/8390/hydra.c
++++ b/drivers/net/ethernet/8390/hydra.c
+@@ -53,9 +53,9 @@ static const char version[] =
+ #define WORDSWAP(a)     ((((a)>>8)&0xff) | ((a)<<8))
+ 
+ 
+-static int __devinit hydra_init_one(struct zorro_dev *z,
++static int hydra_init_one(struct zorro_dev *z,
+ 				    const struct zorro_device_id *ent);
+-static int __devinit hydra_init(struct zorro_dev *z);
++static int hydra_init(struct zorro_dev *z);
+ static int hydra_open(struct net_device *dev);
+ static int hydra_close(struct net_device *dev);
+ static void hydra_reset_8390(struct net_device *dev);
+@@ -65,9 +65,9 @@ static void hydra_block_input(struct net_device *dev, int count,
+ 			      struct sk_buff *skb, int ring_offset);
+ static void hydra_block_output(struct net_device *dev, int count,
+ 			       const unsigned char *buf, int start_page);
+-static void __devexit hydra_remove_one(struct zorro_dev *z);
++static void hydra_remove_one(struct zorro_dev *z);
+ 
+-static struct zorro_device_id hydra_zorro_tbl[] __devinitdata = {
++static struct zorro_device_id hydra_zorro_tbl[] = {
+     { ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET },
+     { 0 }
+ };
+@@ -77,10 +77,10 @@ static struct zorro_driver hydra_driver = {
+     .name	= "hydra",
+     .id_table	= hydra_zorro_tbl,
+     .probe	= hydra_init_one,
+-    .remove	= __devexit_p(hydra_remove_one),
++    .remove	= hydra_remove_one,
+ };
+ 
+-static int __devinit hydra_init_one(struct zorro_dev *z,
++static int hydra_init_one(struct zorro_dev *z,
+ 				    const struct zorro_device_id *ent)
+ {
+     int err;
+@@ -110,7 +110,7 @@ static const struct net_device_ops hydra_netdev_ops = {
+ #endif
+ };
+ 
+-static int __devinit hydra_init(struct zorro_dev *z)
++static int hydra_init(struct zorro_dev *z)
+ {
+     struct net_device *dev;
+     unsigned long board = ZTWO_VADDR(z->resource.start);
+@@ -247,7 +247,7 @@ static void hydra_block_output(struct net_device *dev, int count,
+     z_memcpy_toio(mem_base+((start_page - NESM_START_PG)<<8), buf, count);
+ }
+ 
+-static void __devexit hydra_remove_one(struct zorro_dev *z)
++static void hydra_remove_one(struct zorro_dev *z)
+ {
+     struct net_device *dev = zorro_get_drvdata(z);
+ 
+diff --git a/drivers/net/ethernet/8390/ne2k-pci.c b/drivers/net/ethernet/8390/ne2k-pci.c
+index 5e8845febfb8..c0c127913dec 100644
+--- a/drivers/net/ethernet/8390/ne2k-pci.c
++++ b/drivers/net/ethernet/8390/ne2k-pci.c
+@@ -61,7 +61,7 @@ static int options[MAX_UNITS];
+ #include "8390.h"
+ 
+ /* These identify the driver base version and may not be removed. */
+-static const char version[] __devinitconst =
++static const char version[] =
+ 	KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE
+ 	" D. Becker/P. Gortmaker\n";
+ 
+@@ -119,7 +119,7 @@ enum ne2k_pci_chipsets {
+ static struct {
+ 	char *name;
+ 	int flags;
+-} pci_clone_list[] __devinitdata = {
++} pci_clone_list[] = {
+ 	{"RealTek RTL-8029", REALTEK_FDX},
+ 	{"Winbond 89C940", 0},
+ 	{"Compex RL2000", 0},
+@@ -215,8 +215,8 @@ static const struct net_device_ops ne2k_netdev_ops = {
+ #endif
+ };
+ 
+-static int __devinit ne2k_pci_init_one (struct pci_dev *pdev,
+-				     const struct pci_device_id *ent)
++static int ne2k_pci_init_one(struct pci_dev *pdev,
++			     const struct pci_device_id *ent)
+ {
+ 	struct net_device *dev;
+ 	int i;
+@@ -647,7 +647,7 @@ static const struct ethtool_ops ne2k_pci_ethtool_ops = {
+ 	.get_drvinfo		= ne2k_pci_get_drvinfo,
+ };
+ 
+-static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev)
++static void ne2k_pci_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 
+@@ -696,7 +696,7 @@ static int ne2k_pci_resume (struct pci_dev *pdev)
+ static struct pci_driver ne2k_driver = {
+ 	.name		= DRV_NAME,
+ 	.probe		= ne2k_pci_init_one,
+-	.remove		= __devexit_p(ne2k_pci_remove_one),
++	.remove		= ne2k_pci_remove_one,
+ 	.id_table	= ne2k_pci_tbl,
+ #ifdef CONFIG_PM
+ 	.suspend	= ne2k_pci_suspend,
+diff --git a/drivers/net/ethernet/8390/ne3210.c b/drivers/net/ethernet/8390/ne3210.c
+index e3f57427d5c5..ebcdb52ec739 100644
+--- a/drivers/net/ethernet/8390/ne3210.c
++++ b/drivers/net/ethernet/8390/ne3210.c
+@@ -222,7 +222,7 @@ static int __init ne3210_eisa_probe (struct device *device)
+ 	return retval;
+ }
+ 
+-static int __devexit ne3210_eisa_remove (struct device *device)
++static int ne3210_eisa_remove(struct device *device)
+ {
+ 	struct net_device  *dev    = dev_get_drvdata(device);
+ 	unsigned long       ioaddr = to_eisa_device (device)->base_addr;
+@@ -324,7 +324,7 @@ static struct eisa_driver ne3210_eisa_driver = {
+ 	.driver   = {
+ 		.name   = "ne3210",
+ 		.probe  = ne3210_eisa_probe,
+-		.remove = __devexit_p (ne3210_eisa_remove),
++		.remove = ne3210_eisa_remove,
+ 	},
+ };
+ 
+diff --git a/drivers/net/ethernet/8390/zorro8390.c b/drivers/net/ethernet/8390/zorro8390.c
+index 7818e6397e91..ceb89d90230e 100644
+--- a/drivers/net/ethernet/8390/zorro8390.c
++++ b/drivers/net/ethernet/8390/zorro8390.c
+@@ -75,7 +75,7 @@ static struct card_info {
+ 	zorro_id id;
+ 	const char *name;
+ 	unsigned int offset;
+-} cards[] __devinitdata = {
++} cards[] = {
+ 	{ ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, "Ariadne II", 0x0600 },
+ 	{ ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, "X-Surf", 0x8600 },
+ };
+@@ -254,7 +254,7 @@ static int zorro8390_close(struct net_device *dev)
+ 	return 0;
+ }
+ 
+-static void __devexit zorro8390_remove_one(struct zorro_dev *z)
++static void zorro8390_remove_one(struct zorro_dev *z)
+ {
+ 	struct net_device *dev = zorro_get_drvdata(z);
+ 
+@@ -264,7 +264,7 @@ static void __devexit zorro8390_remove_one(struct zorro_dev *z)
+ 	free_netdev(dev);
+ }
+ 
+-static struct zorro_device_id zorro8390_zorro_tbl[] __devinitdata = {
++static struct zorro_device_id zorro8390_zorro_tbl[] = {
+ 	{ ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, },
+ 	{ ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, },
+ 	{ 0 }
+@@ -286,7 +286,7 @@ static const struct net_device_ops zorro8390_netdev_ops = {
+ #endif
+ };
+ 
+-static int __devinit zorro8390_init(struct net_device *dev,
++static int zorro8390_init(struct net_device *dev,
+ 				    unsigned long board, const char *name,
+ 				    unsigned long ioaddr)
+ {
+@@ -396,7 +396,7 @@ static int __devinit zorro8390_init(struct net_device *dev,
+ 	return 0;
+ }
+ 
+-static int __devinit zorro8390_init_one(struct zorro_dev *z,
++static int zorro8390_init_one(struct zorro_dev *z,
+ 					const struct zorro_device_id *ent)
+ {
+ 	struct net_device *dev;
+@@ -432,7 +432,7 @@ static struct zorro_driver zorro8390_driver = {
+ 	.name		= "zorro8390",
+ 	.id_table	= zorro8390_zorro_tbl,
+ 	.probe		= zorro8390_init_one,
+-	.remove		= __devexit_p(zorro8390_remove_one),
++	.remove		= zorro8390_remove_one,
+ };
+ 
+ static int __init zorro8390_init_module(void)

commit 2791cf7a73d4c0ab110bcf21b5c0575efbe934d0
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:22:50 2012 -0500
+
+    3c509: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/3com/3c509.c b/drivers/net/ethernet/3com/3c509.c
+index 1a8eef2c3d58..9300185da976 100644
+--- a/drivers/net/ethernet/3com/3c509.c
++++ b/drivers/net/ethernet/3com/3c509.c
+@@ -92,7 +92,7 @@
+ #include 
+ #include 
+ 
+-static char version[] __devinitdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n";
++static char version[] = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n";
+ 
+ #ifdef EL3_DEBUG
+ static int el3_debug = EL3_DEBUG;
+@@ -184,7 +184,7 @@ static int max_interrupt_work = 10;
+ static int nopnp;
+ #endif
+ 
+-static int __devinit el3_common_init(struct net_device *dev);
++static int el3_common_init(struct net_device *dev);
+ static void el3_common_remove(struct net_device *dev);
+ static ushort id_read_eeprom(int index);
+ static ushort read_eeprom(int ioaddr, int index);
+@@ -270,7 +270,7 @@ static int el3_isa_id_sequence(__be16 *phys_addr)
+ 
+ }
+ 
+-static void __devinit el3_dev_fill(struct net_device *dev, __be16 *phys_addr,
++static void el3_dev_fill(struct net_device *dev, __be16 *phys_addr,
+ 				   int ioaddr, int irq, int if_port,
+ 				   enum el3_cardtype type)
+ {
+@@ -283,7 +283,7 @@ static void __devinit el3_dev_fill(struct net_device *dev, __be16 *phys_addr,
+ 	lp->type = type;
+ }
+ 
+-static int __devinit el3_isa_match(struct device *pdev,
++static int el3_isa_match(struct device *pdev,
+ 				   unsigned int ndev)
+ {
+ 	struct net_device *dev;
+@@ -341,7 +341,7 @@ static int __devinit el3_isa_match(struct device *pdev,
+ 	return 1;
+ }
+ 
+-static int __devexit el3_isa_remove(struct device *pdev,
++static int el3_isa_remove(struct device *pdev,
+ 				    unsigned int ndev)
+ {
+ 	el3_device_remove(pdev);
+@@ -382,7 +382,7 @@ static int el3_isa_resume(struct device *dev, unsigned int n)
+ 
+ static struct isa_driver el3_isa_driver = {
+ 	.match		= el3_isa_match,
+-	.remove		= __devexit_p(el3_isa_remove),
++	.remove		= el3_isa_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= el3_isa_suspend,
+ 	.resume		= el3_isa_resume,
+@@ -406,7 +406,7 @@ static struct pnp_device_id el3_pnp_ids[] = {
+ };
+ MODULE_DEVICE_TABLE(pnp, el3_pnp_ids);
+ 
+-static int __devinit el3_pnp_probe(struct pnp_dev *pdev,
++static int el3_pnp_probe(struct pnp_dev *pdev,
+ 				    const struct pnp_device_id *id)
+ {
+ 	short i;
+@@ -445,7 +445,7 @@ static int __devinit el3_pnp_probe(struct pnp_dev *pdev,
+ 	return 0;
+ }
+ 
+-static void __devexit el3_pnp_remove(struct pnp_dev *pdev)
++static void el3_pnp_remove(struct pnp_dev *pdev)
+ {
+ 	el3_common_remove(pnp_get_drvdata(pdev));
+ 	pnp_set_drvdata(pdev, NULL);
+@@ -467,7 +467,7 @@ static struct pnp_driver el3_pnp_driver = {
+ 	.name		= "3c509",
+ 	.id_table	= el3_pnp_ids,
+ 	.probe		= el3_pnp_probe,
+-	.remove		= __devexit_p(el3_pnp_remove),
++	.remove		= el3_pnp_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= el3_pnp_suspend,
+ 	.resume		= el3_pnp_resume,
+@@ -496,7 +496,7 @@ static struct eisa_driver el3_eisa_driver = {
+ 		.driver   = {
+ 				.name    = "3c579",
+ 				.probe   = el3_eisa_probe,
+-				.remove  = __devexit_p (el3_device_remove),
++				.remove  = el3_device_remove,
+ 				.suspend = el3_suspend,
+ 				.resume  = el3_resume,
+ 		}
+@@ -519,7 +519,7 @@ static const struct net_device_ops netdev_ops = {
+ #endif
+ };
+ 
+-static int __devinit el3_common_init(struct net_device *dev)
++static int el3_common_init(struct net_device *dev)
+ {
+ 	struct el3_private *lp = netdev_priv(dev);
+ 	int err;
+@@ -618,7 +618,7 @@ static int __init el3_eisa_probe (struct device *device)
+ /* This remove works for all device types.
+  *
+  * The net dev must be stored in the driver data field */
+-static int __devexit el3_device_remove (struct device *device)
++static int el3_device_remove(struct device *device)
+ {
+ 	struct net_device *dev;
+ 

commit 21cf689b16afa08fe8b02dfadaea88500d6c73c6
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:22:49 2012 -0500
+
+    typhoon: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: David Dillow 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/3com/typhoon.c b/drivers/net/ethernet/3com/typhoon.c
+index bb9670f29b59..27aaaf99e73e 100644
+--- a/drivers/net/ethernet/3com/typhoon.c
++++ b/drivers/net/ethernet/3com/typhoon.c
+@@ -168,7 +168,7 @@ enum typhoon_cards {
+ };
+ 
+ /* directly indexed by enum typhoon_cards, above */
+-static struct typhoon_card_info typhoon_card_info[] __devinitdata = {
++static struct typhoon_card_info typhoon_card_info[] = {
+ 	{ "3Com Typhoon (3C990-TX)",
+ 		TYPHOON_CRYPTO_NONE},
+ 	{ "3Com Typhoon (3CR990-TX-95)",
+@@ -2200,7 +2200,7 @@ typhoon_suspend(struct pci_dev *pdev, pm_message_t state)
+ }
+ #endif
+ 
+-static int __devinit
++static int
+ typhoon_test_mmio(struct pci_dev *pdev)
+ {
+ 	void __iomem *ioaddr = pci_iomap(pdev, 1, 128);
+@@ -2258,7 +2258,7 @@ static const struct net_device_ops typhoon_netdev_ops = {
+ 	.ndo_change_mtu		= eth_change_mtu,
+ };
+ 
+-static int __devinit
++static int
+ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ 	struct net_device *dev;
+@@ -2509,7 +2509,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	return err;
+ }
+ 
+-static void __devexit
++static void
+ typhoon_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+@@ -2533,7 +2533,7 @@ static struct pci_driver typhoon_driver = {
+ 	.name		= KBUILD_MODNAME,
+ 	.id_table	= typhoon_pci_tbl,
+ 	.probe		= typhoon_init_one,
+-	.remove		= __devexit_p(typhoon_remove_one),
++	.remove		= typhoon_remove_one,
+ #ifdef CONFIG_PM
+ 	.suspend	= typhoon_suspend,
+ 	.resume		= typhoon_resume,

commit 3f6db0f38f2a170b4d9d5a7e3c329ab7701cd0cb
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:22:48 2012 -0500
+
+    3c59x: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Steffen Klassert 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c
+index e463d1036829..658e224b3613 100644
+--- a/drivers/net/ethernet/3com/3c59x.c
++++ b/drivers/net/ethernet/3com/3c59x.c
+@@ -102,7 +102,7 @@ static int vortex_debug = 1;
+ #include 
+ 
+ 
+-static const char version[] __devinitconst =
++static const char version[] =
+ 	DRV_NAME ": Donald Becker and others.\n";
+ 
+ MODULE_AUTHOR("Donald Becker ");
+@@ -277,7 +277,7 @@ static struct vortex_chip_info {
+ 	int flags;
+ 	int drv_flags;
+ 	int io_size;
+-} vortex_info_tbl[] __devinitdata = {
++} vortex_info_tbl[] = {
+ 	{"3c590 Vortex 10Mbps",
+ 	 PCI_USES_MASTER, IS_VORTEX, 32, },
+ 	{"3c592 EISA 10Mbps Demon/Vortex",					/* AKPM: from Don's 3c59x_cb.c 0.49H */
+@@ -931,7 +931,7 @@ static int __init vortex_eisa_probe(struct device *device)
+ 	return 0;
+ }
+ 
+-static int __devexit vortex_eisa_remove(struct device *device)
++static int vortex_eisa_remove(struct device *device)
+ {
+ 	struct eisa_device *edev;
+ 	struct net_device *dev;
+@@ -962,7 +962,7 @@ static struct eisa_driver vortex_eisa_driver = {
+ 	.driver   = {
+ 		.name    = "3c59x",
+ 		.probe   = vortex_eisa_probe,
+-		.remove  = __devexit_p(vortex_eisa_remove)
++		.remove  = vortex_eisa_remove
+ 	}
+ };
+ 
+@@ -1000,7 +1000,7 @@ static int __init vortex_eisa_init(void)
+ }
+ 
+ /* returns count (>= 0), or negative on error */
+-static int __devinit vortex_init_one(struct pci_dev *pdev,
++static int vortex_init_one(struct pci_dev *pdev,
+ 				      const struct pci_device_id *ent)
+ {
+ 	int rc, unit, pci_bar;
+@@ -1088,7 +1088,7 @@ static const struct net_device_ops vortex_netdev_ops = {
+  *
+  * NOTE: pdev can be NULL, for the case of a Compaq device
+  */
+-static int __devinit vortex_probe1(struct device *gendev,
++static int vortex_probe1(struct device *gendev,
+ 				   void __iomem *ioaddr, int irq,
+ 				   int chip_idx, int card_idx)
+ {
+@@ -3222,7 +3222,7 @@ static void acpi_set_WOL(struct net_device *dev)
+ }
+ 
+ 
+-static void __devexit vortex_remove_one(struct pci_dev *pdev)
++static void vortex_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct vortex_private *vp;
+@@ -3265,7 +3265,7 @@ static void __devexit vortex_remove_one(struct pci_dev *pdev)
+ static struct pci_driver vortex_driver = {
+ 	.name		= "3c59x",
+ 	.probe		= vortex_init_one,
+-	.remove		= __devexit_p(vortex_remove_one),
++	.remove		= vortex_remove_one,
+ 	.id_table	= vortex_pci_tbl,
+ 	.driver.pm	= VORTEX_PM_OPS,
+ };

commit 58b10698d2d60b0b0c3bddd72038af14e62f92bc
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:22:47 2012 -0500
+
+    i825xx: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/i825xx/lasi_82596.c b/drivers/net/ethernet/i825xx/lasi_82596.c
+index 6eba352c52e0..f42f1b707733 100644
+--- a/drivers/net/ethernet/i825xx/lasi_82596.c
++++ b/drivers/net/ethernet/i825xx/lasi_82596.c
+@@ -150,7 +150,7 @@ static void mpu_port(struct net_device *dev, int c, dma_addr_t x)
+ 
+ #define LAN_PROM_ADDR	0xF0810000
+ 
+-static int __devinit
++static int
+ lan_init_chip(struct parisc_device *dev)
+ {
+ 	struct	net_device *netdevice;
+@@ -195,7 +195,7 @@ lan_init_chip(struct parisc_device *dev)
+ 	return retval;
+ }
+ 
+-static int __devexit lan_remove_chip (struct parisc_device *pdev)
++static int lan_remove_chip(struct parisc_device *pdev)
+ {
+ 	struct net_device *dev = parisc_get_drvdata(pdev);
+ 	struct i596_private *lp = netdev_priv(dev);
+@@ -219,10 +219,10 @@ static struct parisc_driver lan_driver = {
+ 	.name		= "lasi_82596",
+ 	.id_table	= lan_tbl,
+ 	.probe		= lan_init_chip,
+-	.remove         = __devexit_p(lan_remove_chip),
++	.remove         = lan_remove_chip,
+ };
+ 
+-static int __devinit lasi_82596_init(void)
++static int lasi_82596_init(void)
+ {
+ 	printk(KERN_INFO LASI_82596_DRIVER_VERSION "\n");
+ 	return register_parisc_driver(&lan_driver);
+diff --git a/drivers/net/ethernet/i825xx/lib82596.c b/drivers/net/ethernet/i825xx/lib82596.c
+index 3efbd8dbb63d..f045ea4dc514 100644
+--- a/drivers/net/ethernet/i825xx/lib82596.c
++++ b/drivers/net/ethernet/i825xx/lib82596.c
+@@ -1048,7 +1048,7 @@ static const struct net_device_ops i596_netdev_ops = {
+ #endif
+ };
+ 
+-static int __devinit i82596_probe(struct net_device *dev)
++static int i82596_probe(struct net_device *dev)
+ {
+ 	int i;
+ 	struct i596_private *lp = netdev_priv(dev);
+diff --git a/drivers/net/ethernet/i825xx/sni_82596.c b/drivers/net/ethernet/i825xx/sni_82596.c
+index 6b2a88817473..4ceae9a30274 100644
+--- a/drivers/net/ethernet/i825xx/sni_82596.c
++++ b/drivers/net/ethernet/i825xx/sni_82596.c
+@@ -75,7 +75,7 @@ static void mpu_port(struct net_device *dev, int c, dma_addr_t x)
+ }
+ 
+ 
+-static int __devinit sni_82596_probe(struct platform_device *dev)
++static int sni_82596_probe(struct platform_device *dev)
+ {
+ 	struct	net_device *netdevice;
+ 	struct i596_private *lp;
+@@ -147,7 +147,7 @@ static int __devinit sni_82596_probe(struct platform_device *dev)
+ 	return retval;
+ }
+ 
+-static int __devexit sni_82596_driver_remove(struct platform_device *pdev)
++static int sni_82596_driver_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *dev = platform_get_drvdata(pdev);
+ 	struct i596_private *lp = netdev_priv(dev);
+@@ -163,14 +163,14 @@ static int __devexit sni_82596_driver_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver sni_82596_driver = {
+ 	.probe	= sni_82596_probe,
+-	.remove	= __devexit_p(sni_82596_driver_remove),
++	.remove	= sni_82596_driver_remove,
+ 	.driver	= {
+ 		.name	= sni_82596_string,
+ 		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+-static int __devinit sni_82596_init(void)
++static int sni_82596_init(void)
+ {
+ 	printk(KERN_INFO SNI_82596_DRIVER_VERSION "\n");
+ 	return platform_driver_register(&sni_82596_driver);

commit 663c2a69e943b391b3cea25c616e339c5d5d4fab
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:22:46 2012 -0500
+
+    i825xx/ether1.c: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Russell King 
+    Cc: linux-arm-kernel@lists.infradead.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/i825xx/ether1.c b/drivers/net/ethernet/i825xx/ether1.c
+index 7b9609da6fe4..5d353c660068 100644
+--- a/drivers/net/ethernet/i825xx/ether1.c
++++ b/drivers/net/ethernet/i825xx/ether1.c
+@@ -72,7 +72,7 @@ static void ether1_timeout(struct net_device *dev);
+ 
+ /* ------------------------------------------------------------------------- */
+ 
+-static char version[] __devinitdata = "ether1 ethernet driver (c) 2000 Russell King v1.07\n";
++static char version[] = "ether1 ethernet driver (c) 2000 Russell King v1.07\n";
+ 
+ #define BUS_16 16
+ #define BUS_8  8
+@@ -250,7 +250,7 @@ ether1_readbuffer (struct net_device *dev, void *data, unsigned int start, unsig
+ 	} while (thislen);
+ }
+ 
+-static int __devinit
++static int
+ ether1_ramtest(struct net_device *dev, unsigned char byte)
+ {
+ 	unsigned char *buffer = kmalloc (BUFFER_SIZE, GFP_KERNEL);
+@@ -304,7 +304,7 @@ ether1_reset (struct net_device *dev)
+ 	return BUS_16;
+ }
+ 
+-static int __devinit
++static int
+ ether1_init_2(struct net_device *dev)
+ {
+ 	int i;
+@@ -966,7 +966,7 @@ ether1_setmulticastlist (struct net_device *dev)
+ 
+ /* ------------------------------------------------------------------------- */
+ 
+-static void __devinit ether1_banner(void)
++static void ether1_banner(void)
+ {
+ 	static unsigned int version_printed = 0;
+ 
+@@ -985,7 +985,7 @@ static const struct net_device_ops ether1_netdev_ops = {
+ 	.ndo_set_mac_address	= eth_mac_addr,
+ };
+ 
+-static int __devinit
++static int
+ ether1_probe(struct expansion_card *ec, const struct ecard_id *id)
+ {
+ 	struct net_device *dev;
+@@ -1046,7 +1046,7 @@ ether1_probe(struct expansion_card *ec, const struct ecard_id *id)
+ 	return ret;
+ }
+ 
+-static void __devexit ether1_remove(struct expansion_card *ec)
++static void ether1_remove(struct expansion_card *ec)
+ {
+ 	struct net_device *dev = ecard_get_drvdata(ec);
+ 
+@@ -1064,7 +1064,7 @@ static const struct ecard_id ether1_ids[] = {
+ 
+ static struct ecard_driver ether1_driver = {
+ 	.probe		= ether1_probe,
+-	.remove		= __devexit_p(ether1_remove),
++	.remove		= ether1_remove,
+ 	.id_table	= ether1_ids,
+ 	.drv = {
+ 		.name	= "ether1",

commit 92a66593e5e7ae60242c430abac7bd710d1c7da0
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:22:45 2012 -0500
+
+    drivers/net/ethernet/amd/am79c961a.c: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Russell King 
+    Cc: linux-arm-kernel@lists.infradead.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/ethernet/amd/am79c961a.c b/drivers/net/ethernet/amd/am79c961a.c
+index e10ffad525a7..60e2b701afe7 100644
+--- a/drivers/net/ethernet/amd/am79c961a.c
++++ b/drivers/net/ethernet/amd/am79c961a.c
+@@ -671,7 +671,7 @@ static const struct net_device_ops am79c961_netdev_ops = {
+ #endif
+ };
+ 
+-static int __devinit am79c961_probe(struct platform_device *pdev)
++static int am79c961_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res;
+ 	struct net_device *dev;

commit 3c8ac0f2ad53a96ac58efe7c98fac2986d081dfc
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:22:44 2012 -0500
+
+    can: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Wolfgang Grandegger 
+    Cc: Marc Kleine-Budde 
+    Cc: linux-can@vger.kernel.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
+index 14b166bdbeaf..b8e81eb6df13 100644
+--- a/drivers/net/can/at91_can.c
++++ b/drivers/net/can/at91_can.c
+@@ -155,7 +155,7 @@ struct at91_priv {
+ 	canid_t mb0_id;
+ };
+ 
+-static const struct at91_devtype_data at91_devtype_data[] __devinitconst = {
++static const struct at91_devtype_data at91_devtype_data[] = {
+ 	[AT91_DEVTYPE_SAM9263] = {
+ 		.rx_first = 1,
+ 		.rx_split = 8,
+@@ -1242,7 +1242,7 @@ static struct attribute_group at91_sysfs_attr_group = {
+ 	.attrs = at91_sysfs_attrs,
+ };
+ 
+-static int __devinit at91_can_probe(struct platform_device *pdev)
++static int at91_can_probe(struct platform_device *pdev)
+ {
+ 	const struct at91_devtype_data *devtype_data;
+ 	enum at91_devtype devtype;
+@@ -1339,7 +1339,7 @@ static int __devinit at91_can_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit at91_can_remove(struct platform_device *pdev)
++static int at91_can_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *dev = platform_get_drvdata(pdev);
+ 	struct at91_priv *priv = netdev_priv(dev);
+@@ -1376,7 +1376,7 @@ MODULE_DEVICE_TABLE(platform, at91_can_id_table);
+ 
+ static struct platform_driver at91_can_driver = {
+ 	.probe = at91_can_probe,
+-	.remove = __devexit_p(at91_can_remove),
++	.remove = at91_can_remove,
+ 	.driver = {
+ 		.name = KBUILD_MODNAME,
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c
+index a3f8de962258..6a0532176b69 100644
+--- a/drivers/net/can/bfin_can.c
++++ b/drivers/net/can/bfin_can.c
+@@ -531,7 +531,7 @@ static const struct net_device_ops bfin_can_netdev_ops = {
+ 	.ndo_start_xmit         = bfin_can_start_xmit,
+ };
+ 
+-static int __devinit bfin_can_probe(struct platform_device *pdev)
++static int bfin_can_probe(struct platform_device *pdev)
+ {
+ 	int err;
+ 	struct net_device *dev;
+@@ -611,7 +611,7 @@ static int __devinit bfin_can_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit bfin_can_remove(struct platform_device *pdev)
++static int bfin_can_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *dev = dev_get_drvdata(&pdev->dev);
+ 	struct bfin_can_priv *priv = netdev_priv(dev);
+@@ -677,7 +677,7 @@ static int bfin_can_resume(struct platform_device *pdev)
+ 
+ static struct platform_driver bfin_can_driver = {
+ 	.probe = bfin_can_probe,
+-	.remove = __devexit_p(bfin_can_remove),
++	.remove = bfin_can_remove,
+ 	.suspend = bfin_can_suspend,
+ 	.resume = bfin_can_resume,
+ 	.driver = {
+diff --git a/drivers/net/can/c_can/c_can_pci.c b/drivers/net/can/c_can/c_can_pci.c
+index 3d7830bcd2bf..a1f263170683 100644
+--- a/drivers/net/can/c_can/c_can_pci.c
++++ b/drivers/net/can/c_can/c_can_pci.c
+@@ -63,7 +63,7 @@ static void c_can_pci_write_reg_aligned_to_32bit(struct c_can_priv *priv,
+ 	writew(val, priv->base + 2 * priv->regs[index]);
+ }
+ 
+-static int __devinit c_can_pci_probe(struct pci_dev *pdev,
++static int c_can_pci_probe(struct pci_dev *pdev,
+ 				     const struct pci_device_id *ent)
+ {
+ 	struct c_can_pci_data *c_can_pci_data = (void *)ent->driver_data;
+@@ -174,7 +174,7 @@ static int __devinit c_can_pci_probe(struct pci_dev *pdev,
+ 	return ret;
+ }
+ 
+-static void __devexit c_can_pci_remove(struct pci_dev *pdev)
++static void c_can_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct c_can_priv *priv = netdev_priv(dev);
+@@ -210,7 +210,7 @@ static struct pci_driver c_can_pci_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = c_can_pci_tbl,
+ 	.probe = c_can_pci_probe,
+-	.remove = __devexit_p(c_can_pci_remove),
++	.remove = c_can_pci_remove,
+ };
+ 
+ module_pci_driver(c_can_pci_driver);
+diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
+index 0044fd859db3..d63b91904f82 100644
+--- a/drivers/net/can/c_can/c_can_platform.c
++++ b/drivers/net/can/c_can/c_can_platform.c
+@@ -106,7 +106,7 @@ static const struct of_device_id c_can_of_table[] = {
+ };
+ MODULE_DEVICE_TABLE(of, c_can_of_table);
+ 
+-static int __devinit c_can_plat_probe(struct platform_device *pdev)
++static int c_can_plat_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 	void __iomem *addr;
+@@ -248,7 +248,7 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit c_can_plat_remove(struct platform_device *pdev)
++static int c_can_plat_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *dev = platform_get_drvdata(pdev);
+ 	struct c_can_priv *priv = netdev_priv(dev);
+@@ -334,7 +334,7 @@ static struct platform_driver c_can_plat_driver = {
+ 		.of_match_table = of_match_ptr(c_can_of_table),
+ 	},
+ 	.probe = c_can_plat_probe,
+-	.remove = __devexit_p(c_can_plat_remove),
++	.remove = c_can_plat_remove,
+ 	.suspend = c_can_suspend,
+ 	.resume = c_can_resume,
+ 	.id_table = c_can_id_table,
+diff --git a/drivers/net/can/cc770/cc770_isa.c b/drivers/net/can/cc770/cc770_isa.c
+index 9f3a25ccd665..8eaaac81f320 100644
+--- a/drivers/net/can/cc770/cc770_isa.c
++++ b/drivers/net/can/cc770/cc770_isa.c
+@@ -75,12 +75,12 @@ MODULE_LICENSE("GPL v2");
+ 
+ static unsigned long port[MAXDEV];
+ static unsigned long mem[MAXDEV];
+-static int __devinitdata irq[MAXDEV];
+-static int __devinitdata clk[MAXDEV];
+-static u8 __devinitdata cir[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
+-static u8 __devinitdata cor[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
+-static u8 __devinitdata bcr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
+-static int __devinitdata indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1};
++static int irq[MAXDEV];
++static int clk[MAXDEV];
++static u8 cir[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
++static u8 cor[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
++static u8 bcr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
++static int indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1};
+ 
+ module_param_array(port, ulong, NULL, S_IRUGO);
+ MODULE_PARM_DESC(port, "I/O port number");
+@@ -166,7 +166,7 @@ static void cc770_isa_port_write_reg_indirect(const struct cc770_priv *priv,
+ 	spin_unlock_irqrestore(&cc770_isa_port_lock, flags);
+ }
+ 
+-static int __devinit cc770_isa_probe(struct platform_device *pdev)
++static int cc770_isa_probe(struct platform_device *pdev)
+ {
+ 	struct net_device *dev;
+ 	struct cc770_priv *priv;
+@@ -291,7 +291,7 @@ static int __devinit cc770_isa_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit cc770_isa_remove(struct platform_device *pdev)
++static int cc770_isa_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *dev = dev_get_drvdata(&pdev->dev);
+ 	struct cc770_priv *priv = netdev_priv(dev);
+@@ -316,7 +316,7 @@ static int __devexit cc770_isa_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver cc770_isa_driver = {
+ 	.probe = cc770_isa_probe,
+-	.remove = __devexit_p(cc770_isa_remove),
++	.remove = cc770_isa_remove,
+ 	.driver = {
+ 		.name = KBUILD_MODNAME,
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/net/can/cc770/cc770_platform.c b/drivers/net/can/cc770/cc770_platform.c
+index 3da6cbb542ae..7d451cd75006 100644
+--- a/drivers/net/can/cc770/cc770_platform.c
++++ b/drivers/net/can/cc770/cc770_platform.c
+@@ -75,7 +75,7 @@ static void cc770_platform_write_reg(const struct cc770_priv *priv, int reg,
+ 	iowrite8(val, priv->reg_base + reg);
+ }
+ 
+-static int __devinit cc770_get_of_node_data(struct platform_device *pdev,
++static int cc770_get_of_node_data(struct platform_device *pdev,
+ 					    struct cc770_priv *priv)
+ {
+ 	struct device_node *np = pdev->dev.of_node;
+@@ -148,7 +148,7 @@ static int __devinit cc770_get_of_node_data(struct platform_device *pdev,
+ 	return 0;
+ }
+ 
+-static int __devinit cc770_get_platform_data(struct platform_device *pdev,
++static int cc770_get_platform_data(struct platform_device *pdev,
+ 					     struct cc770_priv *priv)
+ {
+ 
+@@ -164,7 +164,7 @@ static int __devinit cc770_get_platform_data(struct platform_device *pdev,
+ 	return 0;
+ }
+ 
+-static int __devinit cc770_platform_probe(struct platform_device *pdev)
++static int cc770_platform_probe(struct platform_device *pdev)
+ {
+ 	struct net_device *dev;
+ 	struct cc770_priv *priv;
+@@ -238,7 +238,7 @@ static int __devinit cc770_platform_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit cc770_platform_remove(struct platform_device *pdev)
++static int cc770_platform_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *dev = dev_get_drvdata(&pdev->dev);
+ 	struct cc770_priv *priv = netdev_priv(dev);
+@@ -254,7 +254,7 @@ static int __devexit cc770_platform_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static struct of_device_id __devinitdata cc770_platform_table[] = {
++static struct of_device_id cc770_platform_table[] = {
+ 	{.compatible = "bosch,cc770"}, /* CC770 from Bosch */
+ 	{.compatible = "intc,82527"},  /* AN82527 from Intel CP */
+ 	{},
+@@ -268,7 +268,7 @@ static struct platform_driver cc770_platform_driver = {
+ 		.of_match_table = cc770_platform_table,
+ 	},
+ 	.probe = cc770_platform_probe,
+-	.remove = __devexit_p(cc770_platform_remove),
++	.remove = cc770_platform_remove,
+ };
+ 
+ module_platform_driver(cc770_platform_driver);
+diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
+index 9a17965e00fd..0289a6d86f66 100644
+--- a/drivers/net/can/flexcan.c
++++ b/drivers/net/can/flexcan.c
+@@ -922,7 +922,7 @@ static const struct net_device_ops flexcan_netdev_ops = {
+ 	.ndo_start_xmit	= flexcan_start_xmit,
+ };
+ 
+-static int __devinit register_flexcandev(struct net_device *dev)
++static int register_flexcandev(struct net_device *dev)
+ {
+ 	struct flexcan_priv *priv = netdev_priv(dev);
+ 	struct flexcan_regs __iomem *regs = priv->base;
+@@ -968,7 +968,7 @@ static int __devinit register_flexcandev(struct net_device *dev)
+ 	return err;
+ }
+ 
+-static void __devexit unregister_flexcandev(struct net_device *dev)
++static void unregister_flexcandev(struct net_device *dev)
+ {
+ 	unregister_candev(dev);
+ }
+@@ -987,7 +987,7 @@ static const struct platform_device_id flexcan_id_table[] = {
+ };
+ MODULE_DEVICE_TABLE(platform, flexcan_id_table);
+ 
+-static int __devinit flexcan_probe(struct platform_device *pdev)
++static int flexcan_probe(struct platform_device *pdev)
+ {
+ 	const struct of_device_id *of_id;
+ 	const struct flexcan_devtype_data *devtype_data;
+@@ -1109,7 +1109,7 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit flexcan_remove(struct platform_device *pdev)
++static int flexcan_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *dev = platform_get_drvdata(pdev);
+ 	struct flexcan_priv *priv = netdev_priv(dev);
+@@ -1170,7 +1170,7 @@ static struct platform_driver flexcan_driver = {
+ 		.of_match_table = flexcan_of_match,
+ 	},
+ 	.probe = flexcan_probe,
+-	.remove = __devexit_p(flexcan_remove),
++	.remove = flexcan_remove,
+ 	.suspend = flexcan_suspend,
+ 	.resume = flexcan_resume,
+ 	.id_table = flexcan_id_table,
+diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c
+index 391f484fccb7..17fbc7a09224 100644
+--- a/drivers/net/can/grcan.c
++++ b/drivers/net/can/grcan.c
+@@ -1659,7 +1659,7 @@ static int grcan_setup_netdev(struct platform_device *ofdev,
+ 	return err;
+ }
+ 
+-static int __devinit grcan_probe(struct platform_device *ofdev)
++static int grcan_probe(struct platform_device *ofdev)
+ {
+ 	struct device_node *np = ofdev->dev.of_node;
+ 	struct resource *res;
+@@ -1714,7 +1714,7 @@ static int __devinit grcan_probe(struct platform_device *ofdev)
+ 	return err;
+ }
+ 
+-static int __devexit grcan_remove(struct platform_device *ofdev)
++static int grcan_remove(struct platform_device *ofdev)
+ {
+ 	struct net_device *dev = dev_get_drvdata(&ofdev->dev);
+ 	struct grcan_priv *priv = netdev_priv(dev);
+@@ -1729,7 +1729,7 @@ static int __devexit grcan_remove(struct platform_device *ofdev)
+ 	return 0;
+ }
+ 
+-static struct of_device_id grcan_match[] __devinitconst = {
++static struct of_device_id grcan_match[] = {
+ 	{.name = "GAISLER_GRCAN"},
+ 	{.name = "01_03d"},
+ 	{.name = "GAISLER_GRHCAN"},
+@@ -1746,7 +1746,7 @@ static struct platform_driver grcan_driver = {
+ 		.of_match_table = grcan_match,
+ 	},
+ 	.probe = grcan_probe,
+-	.remove = __devexit_p(grcan_remove),
++	.remove = grcan_remove,
+ };
+ 
+ module_platform_driver(grcan_driver);
+diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c
+index c0bfb0ad3e0d..c4bc1d2e2033 100644
+--- a/drivers/net/can/janz-ican3.c
++++ b/drivers/net/can/janz-ican3.c
+@@ -365,7 +365,7 @@ static int ican3_old_send_msg(struct ican3_dev *mod, struct ican3_msg *msg)
+  * ICAN3 "new-style" Host Interface Setup
+  */
+ 
+-static void __devinit ican3_init_new_host_interface(struct ican3_dev *mod)
++static void ican3_init_new_host_interface(struct ican3_dev *mod)
+ {
+ 	struct ican3_new_desc desc;
+ 	unsigned long flags;
+@@ -444,7 +444,7 @@ static void __devinit ican3_init_new_host_interface(struct ican3_dev *mod)
+  * ICAN3 Fast Host Interface Setup
+  */
+ 
+-static void __devinit ican3_init_fast_host_interface(struct ican3_dev *mod)
++static void ican3_init_fast_host_interface(struct ican3_dev *mod)
+ {
+ 	struct ican3_fast_desc desc;
+ 	unsigned long flags;
+@@ -631,7 +631,7 @@ static int ican3_recv_msg(struct ican3_dev *mod, struct ican3_msg *msg)
+  * Quick Pre-constructed Messages
+  */
+ 
+-static int __devinit ican3_msg_connect(struct ican3_dev *mod)
++static int ican3_msg_connect(struct ican3_dev *mod)
+ {
+ 	struct ican3_msg msg;
+ 
+@@ -642,7 +642,7 @@ static int __devinit ican3_msg_connect(struct ican3_dev *mod)
+ 	return ican3_send_msg(mod, &msg);
+ }
+ 
+-static int __devexit ican3_msg_disconnect(struct ican3_dev *mod)
++static int ican3_msg_disconnect(struct ican3_dev *mod)
+ {
+ 	struct ican3_msg msg;
+ 
+@@ -653,7 +653,7 @@ static int __devexit ican3_msg_disconnect(struct ican3_dev *mod)
+ 	return ican3_send_msg(mod, &msg);
+ }
+ 
+-static int __devinit ican3_msg_newhostif(struct ican3_dev *mod)
++static int ican3_msg_newhostif(struct ican3_dev *mod)
+ {
+ 	struct ican3_msg msg;
+ 	int ret;
+@@ -674,7 +674,7 @@ static int __devinit ican3_msg_newhostif(struct ican3_dev *mod)
+ 	return 0;
+ }
+ 
+-static int __devinit ican3_msg_fasthostif(struct ican3_dev *mod)
++static int ican3_msg_fasthostif(struct ican3_dev *mod)
+ {
+ 	struct ican3_msg msg;
+ 	unsigned int addr;
+@@ -707,7 +707,7 @@ static int __devinit ican3_msg_fasthostif(struct ican3_dev *mod)
+  * Setup the CAN filter to either accept or reject all
+  * messages from the CAN bus.
+  */
+-static int __devinit ican3_set_id_filter(struct ican3_dev *mod, bool accept)
++static int ican3_set_id_filter(struct ican3_dev *mod, bool accept)
+ {
+ 	struct ican3_msg msg;
+ 	int ret;
+@@ -1421,7 +1421,7 @@ static int ican3_reset_module(struct ican3_dev *mod)
+ 	return -ETIMEDOUT;
+ }
+ 
+-static void __devexit ican3_shutdown_module(struct ican3_dev *mod)
++static void ican3_shutdown_module(struct ican3_dev *mod)
+ {
+ 	ican3_msg_disconnect(mod);
+ 	ican3_reset_module(mod);
+@@ -1430,7 +1430,7 @@ static void __devexit ican3_shutdown_module(struct ican3_dev *mod)
+ /*
+  * Startup an ICAN module, bringing it into fast mode
+  */
+-static int __devinit ican3_startup_module(struct ican3_dev *mod)
++static int ican3_startup_module(struct ican3_dev *mod)
+ {
+ 	int ret;
+ 
+@@ -1760,7 +1760,7 @@ static struct attribute_group ican3_sysfs_attr_group = {
+  * PCI Subsystem
+  */
+ 
+-static int __devinit ican3_probe(struct platform_device *pdev)
++static int ican3_probe(struct platform_device *pdev)
+ {
+ 	struct janz_platform_data *pdata;
+ 	struct net_device *ndev;
+@@ -1898,7 +1898,7 @@ static int __devinit ican3_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit ican3_remove(struct platform_device *pdev)
++static int ican3_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *ndev = platform_get_drvdata(pdev);
+ 	struct ican3_dev *mod = netdev_priv(ndev);
+@@ -1927,7 +1927,7 @@ static struct platform_driver ican3_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= ican3_probe,
+-	.remove		= __devexit_p(ican3_remove),
++	.remove		= ican3_remove,
+ };
+ 
+ module_platform_driver(ican3_driver);
+diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c
+index 26e7129332ab..5eaf47b8e37b 100644
+--- a/drivers/net/can/mcp251x.c
++++ b/drivers/net/can/mcp251x.c
+@@ -981,7 +981,7 @@ static const struct net_device_ops mcp251x_netdev_ops = {
+ 	.ndo_start_xmit = mcp251x_hard_start_xmit,
+ };
+ 
+-static int __devinit mcp251x_can_probe(struct spi_device *spi)
++static int mcp251x_can_probe(struct spi_device *spi)
+ {
+ 	struct net_device *net;
+ 	struct mcp251x_priv *priv;
+@@ -1100,7 +1100,7 @@ static int __devinit mcp251x_can_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit mcp251x_can_remove(struct spi_device *spi)
++static int mcp251x_can_remove(struct spi_device *spi)
+ {
+ 	struct mcp251x_platform_data *pdata = spi->dev.platform_data;
+ 	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
+@@ -1198,7 +1198,7 @@ static struct spi_driver mcp251x_can_driver = {
+ 
+ 	.id_table = mcp251x_id_table,
+ 	.probe = mcp251x_can_probe,
+-	.remove = __devexit_p(mcp251x_can_remove),
++	.remove = mcp251x_can_remove,
+ 	.suspend = mcp251x_can_suspend,
+ 	.resume = mcp251x_can_resume,
+ };
+diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
+index 514d02064255..06a4561955ca 100644
+--- a/drivers/net/can/mscan/mpc5xxx_can.c
++++ b/drivers/net/can/mscan/mpc5xxx_can.c
+@@ -43,12 +43,12 @@ struct mpc5xxx_can_data {
+ };
+ 
+ #ifdef CONFIG_PPC_MPC52xx
+-static struct of_device_id __devinitdata mpc52xx_cdm_ids[] = {
++static struct of_device_id mpc52xx_cdm_ids[] = {
+ 	{ .compatible = "fsl,mpc5200-cdm", },
+ 	{}
+ };
+ 
+-static u32 __devinit mpc52xx_can_get_clock(struct platform_device *ofdev,
++static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
+ 					   const char *clock_name,
+ 					   int *mscan_clksrc)
+ {
+@@ -101,7 +101,7 @@ static u32 __devinit mpc52xx_can_get_clock(struct platform_device *ofdev,
+ 	return freq;
+ }
+ #else /* !CONFIG_PPC_MPC52xx */
+-static u32 __devinit mpc52xx_can_get_clock(struct platform_device *ofdev,
++static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
+ 					   const char *clock_name,
+ 					   int *mscan_clksrc)
+ {
+@@ -124,12 +124,12 @@ struct mpc512x_clockctl {
+ 	u32 mccr[4];		/* MSCAN Clk Ctrl Reg 1-3 */
+ };
+ 
+-static struct of_device_id __devinitdata mpc512x_clock_ids[] = {
++static struct of_device_id mpc512x_clock_ids[] = {
+ 	{ .compatible = "fsl,mpc5121-clock", },
+ 	{}
+ };
+ 
+-static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev,
++static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
+ 					   const char *clock_name,
+ 					   int *mscan_clksrc)
+ {
+@@ -239,7 +239,7 @@ static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev,
+ 	return freq;
+ }
+ #else /* !CONFIG_PPC_MPC512x */
+-static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev,
++static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
+ 					   const char *clock_name,
+ 					   int *mscan_clksrc)
+ {
+@@ -248,7 +248,7 @@ static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev,
+ #endif /* CONFIG_PPC_MPC512x */
+ 
+ static const struct of_device_id mpc5xxx_can_table[];
+-static int __devinit mpc5xxx_can_probe(struct platform_device *ofdev)
++static int mpc5xxx_can_probe(struct platform_device *ofdev)
+ {
+ 	const struct of_device_id *match;
+ 	const struct mpc5xxx_can_data *data;
+@@ -323,7 +323,7 @@ static int __devinit mpc5xxx_can_probe(struct platform_device *ofdev)
+ 	return err;
+ }
+ 
+-static int __devexit mpc5xxx_can_remove(struct platform_device *ofdev)
++static int mpc5xxx_can_remove(struct platform_device *ofdev)
+ {
+ 	struct net_device *dev = dev_get_drvdata(&ofdev->dev);
+ 	struct mscan_priv *priv = netdev_priv(dev);
+@@ -380,17 +380,17 @@ static int mpc5xxx_can_resume(struct platform_device *ofdev)
+ }
+ #endif
+ 
+-static const struct mpc5xxx_can_data __devinitconst mpc5200_can_data = {
++static const struct mpc5xxx_can_data mpc5200_can_data = {
+ 	.type = MSCAN_TYPE_MPC5200,
+ 	.get_clock = mpc52xx_can_get_clock,
+ };
+ 
+-static const struct mpc5xxx_can_data __devinitconst mpc5121_can_data = {
++static const struct mpc5xxx_can_data mpc5121_can_data = {
+ 	.type = MSCAN_TYPE_MPC5121,
+ 	.get_clock = mpc512x_can_get_clock,
+ };
+ 
+-static const struct of_device_id __devinitconst mpc5xxx_can_table[] = {
++static const struct of_device_id mpc5xxx_can_table[] = {
+ 	{ .compatible = "fsl,mpc5200-mscan", .data = &mpc5200_can_data, },
+ 	/* Note that only MPC5121 Rev. 2 (and later) is supported */
+ 	{ .compatible = "fsl,mpc5121-mscan", .data = &mpc5121_can_data, },
+@@ -405,7 +405,7 @@ static struct platform_driver mpc5xxx_can_driver = {
+ 		.of_match_table = mpc5xxx_can_table,
+ 	},
+ 	.probe = mpc5xxx_can_probe,
+-	.remove = __devexit_p(mpc5xxx_can_remove),
++	.remove = mpc5xxx_can_remove,
+ #ifdef CONFIG_PM
+ 	.suspend = mpc5xxx_can_suspend,
+ 	.resume = mpc5xxx_can_resume,
+diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c
+index 48b3d62b34cb..7d1748575b1f 100644
+--- a/drivers/net/can/pch_can.c
++++ b/drivers/net/can/pch_can.c
+@@ -954,7 +954,7 @@ static const struct net_device_ops pch_can_netdev_ops = {
+ 	.ndo_start_xmit		= pch_xmit,
+ };
+ 
+-static void __devexit pch_can_remove(struct pci_dev *pdev)
++static void pch_can_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *ndev = pci_get_drvdata(pdev);
+ 	struct pch_can_priv *priv = netdev_priv(ndev);
+@@ -1178,7 +1178,7 @@ static int pch_can_get_berr_counter(const struct net_device *dev,
+ 	return 0;
+ }
+ 
+-static int __devinit pch_can_probe(struct pci_dev *pdev,
++static int pch_can_probe(struct pci_dev *pdev,
+ 				   const struct pci_device_id *id)
+ {
+ 	struct net_device *ndev;
+@@ -1269,7 +1269,7 @@ static struct pci_driver pch_can_pci_driver = {
+ 	.name = "pch_can",
+ 	.id_table = pch_pci_tbl,
+ 	.probe = pch_can_probe,
+-	.remove = __devexit_p(pch_can_remove),
++	.remove = pch_can_remove,
+ 	.suspend = pch_can_suspend,
+ 	.resume = pch_can_resume,
+ };
+diff --git a/drivers/net/can/sja1000/ems_pci.c b/drivers/net/can/sja1000/ems_pci.c
+index 5c6d412bafb5..f232bc8d0872 100644
+--- a/drivers/net/can/sja1000/ems_pci.c
++++ b/drivers/net/can/sja1000/ems_pci.c
+@@ -220,7 +220,7 @@ static void ems_pci_card_reset(struct ems_pci_card *card)
+  * Probe PCI device for EMS CAN signature and register each available
+  * CAN channel to SJA1000 Socket-CAN subsystem.
+  */
+-static int __devinit ems_pci_add_card(struct pci_dev *pdev,
++static int ems_pci_add_card(struct pci_dev *pdev,
+ 					const struct pci_device_id *ent)
+ {
+ 	struct sja1000_priv *priv;
+diff --git a/drivers/net/can/sja1000/ems_pcmcia.c b/drivers/net/can/sja1000/ems_pcmcia.c
+index 075a5457a190..46fc313214a2 100644
+--- a/drivers/net/can/sja1000/ems_pcmcia.c
++++ b/drivers/net/can/sja1000/ems_pcmcia.c
+@@ -166,7 +166,7 @@ static void ems_pcmcia_del_card(struct pcmcia_device *pdev)
+  * Probe PCI device for EMS CAN signature and register each available
+  * CAN channel to SJA1000 Socket-CAN subsystem.
+  */
+-static int __devinit ems_pcmcia_add_card(struct pcmcia_device *pdev,
++static int ems_pcmcia_add_card(struct pcmcia_device *pdev,
+ 					 unsigned long base)
+ {
+ 	struct sja1000_priv *priv;
+@@ -256,7 +256,7 @@ static int __devinit ems_pcmcia_add_card(struct pcmcia_device *pdev,
+ /*
+  * Setup PCMCIA socket and probe for EMS CPC-CARD
+  */
+-static int __devinit ems_pcmcia_probe(struct pcmcia_device *dev)
++static int ems_pcmcia_probe(struct pcmcia_device *dev)
+ {
+ 	int csval;
+ 
+diff --git a/drivers/net/can/sja1000/kvaser_pci.c b/drivers/net/can/sja1000/kvaser_pci.c
+index 23ed6ea4c7c3..4efdaf26eaea 100644
+--- a/drivers/net/can/sja1000/kvaser_pci.c
++++ b/drivers/net/can/sja1000/kvaser_pci.c
+@@ -290,7 +290,7 @@ static int kvaser_pci_add_chan(struct pci_dev *pdev, int channel,
+ 	return err;
+ }
+ 
+-static int __devinit kvaser_pci_init_one(struct pci_dev *pdev,
++static int kvaser_pci_init_one(struct pci_dev *pdev,
+ 					 const struct pci_device_id *ent)
+ {
+ 	int err;
+@@ -379,7 +379,7 @@ static int __devinit kvaser_pci_init_one(struct pci_dev *pdev,
+ 
+ }
+ 
+-static void __devexit kvaser_pci_remove_one(struct pci_dev *pdev)
++static void kvaser_pci_remove_one(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 
+@@ -394,7 +394,7 @@ static struct pci_driver kvaser_pci_driver = {
+ 	.name = DRV_NAME,
+ 	.id_table = kvaser_pci_tbl,
+ 	.probe = kvaser_pci_init_one,
+-	.remove = __devexit_p(kvaser_pci_remove_one),
++	.remove = kvaser_pci_remove_one,
+ };
+ 
+ module_pci_driver(kvaser_pci_driver);
+diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c
+index 6525dbcca4e3..3faeb3d84362 100644
+--- a/drivers/net/can/sja1000/peak_pci.c
++++ b/drivers/net/can/sja1000/peak_pci.c
+@@ -551,7 +551,7 @@ static void peak_pci_post_irq(const struct sja1000_priv *priv)
+ 		writew(chan->icr_mask, chan->cfg_base + PITA_ICR);
+ }
+ 
+-static int __devinit peak_pci_probe(struct pci_dev *pdev,
++static int peak_pci_probe(struct pci_dev *pdev,
+ 				    const struct pci_device_id *ent)
+ {
+ 	struct sja1000_priv *priv;
+@@ -717,7 +717,7 @@ static int __devinit peak_pci_probe(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit peak_pci_remove(struct pci_dev *pdev)
++static void peak_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev); /* Last device */
+ 	struct sja1000_priv *priv = netdev_priv(dev);
+@@ -757,7 +757,7 @@ static struct pci_driver peak_pci_driver = {
+ 	.name = DRV_NAME,
+ 	.id_table = peak_pci_tbl,
+ 	.probe = peak_pci_probe,
+-	.remove = __devexit_p(peak_pci_remove),
++	.remove = peak_pci_remove,
+ };
+ 
+ module_pci_driver(peak_pci_driver);
+diff --git a/drivers/net/can/sja1000/peak_pcmcia.c b/drivers/net/can/sja1000/peak_pcmcia.c
+index 272a85f32b14..f1175142b0a0 100644
+--- a/drivers/net/can/sja1000/peak_pcmcia.c
++++ b/drivers/net/can/sja1000/peak_pcmcia.c
+@@ -632,7 +632,7 @@ static void pcan_free(struct pcmcia_device *pdev)
+ /*
+  * setup PCMCIA socket and probe for PEAK-System PC-CARD
+  */
+-static int __devinit pcan_probe(struct pcmcia_device *pdev)
++static int pcan_probe(struct pcmcia_device *pdev)
+ {
+ 	struct pcan_pccard *card;
+ 	int err;
+diff --git a/drivers/net/can/sja1000/plx_pci.c b/drivers/net/can/sja1000/plx_pci.c
+index dc04407aa217..8b233f8c95f2 100644
+--- a/drivers/net/can/sja1000/plx_pci.c
++++ b/drivers/net/can/sja1000/plx_pci.c
+@@ -162,7 +162,7 @@ struct plx_pci_card_info {
+ 	void (*reset_func)(struct pci_dev *pdev);
+ };
+ 
+-static struct plx_pci_card_info plx_pci_card_info_adlink __devinitdata = {
++static struct plx_pci_card_info plx_pci_card_info_adlink = {
+ 	"Adlink PCI-7841/cPCI-7841", 2,
+ 	PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
+ 	{1, 0x00, 0x00}, { {2, 0x00, 0x80}, {2, 0x80, 0x80} },
+@@ -170,7 +170,7 @@ static struct plx_pci_card_info plx_pci_card_info_adlink __devinitdata = {
+ 	/* based on PLX9052 */
+ };
+ 
+-static struct plx_pci_card_info plx_pci_card_info_adlink_se __devinitdata = {
++static struct plx_pci_card_info plx_pci_card_info_adlink_se = {
+ 	"Adlink PCI-7841/cPCI-7841 SE", 2,
+ 	PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
+ 	{0, 0x00, 0x00}, { {2, 0x00, 0x80}, {2, 0x80, 0x80} },
+@@ -178,7 +178,7 @@ static struct plx_pci_card_info plx_pci_card_info_adlink_se __devinitdata = {
+ 	/* based on PLX9052 */
+ };
+ 
+-static struct plx_pci_card_info plx_pci_card_info_esd200 __devinitdata = {
++static struct plx_pci_card_info plx_pci_card_info_esd200 = {
+ 	"esd CAN-PCI/CPCI/PCI104/200", 2,
+ 	PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
+ 	{0, 0x00, 0x00}, { {2, 0x00, 0x80}, {2, 0x100, 0x80} },
+@@ -186,7 +186,7 @@ static struct plx_pci_card_info plx_pci_card_info_esd200 __devinitdata = {
+ 	/* based on PLX9030/9050 */
+ };
+ 
+-static struct plx_pci_card_info plx_pci_card_info_esd266 __devinitdata = {
++static struct plx_pci_card_info plx_pci_card_info_esd266 = {
+ 	"esd CAN-PCI/PMC/266", 2,
+ 	PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
+ 	{0, 0x00, 0x00}, { {2, 0x00, 0x80}, {2, 0x100, 0x80} },
+@@ -194,7 +194,7 @@ static struct plx_pci_card_info plx_pci_card_info_esd266 __devinitdata = {
+ 	/* based on PLX9056 */
+ };
+ 
+-static struct plx_pci_card_info plx_pci_card_info_esd2000 __devinitdata = {
++static struct plx_pci_card_info plx_pci_card_info_esd2000 = {
+ 	"esd CAN-PCIe/2000", 2,
+ 	PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
+ 	{0, 0x00, 0x00}, { {2, 0x00, 0x80}, {2, 0x100, 0x80} },
+@@ -202,7 +202,7 @@ static struct plx_pci_card_info plx_pci_card_info_esd2000 __devinitdata = {
+ 	/* based on PEX8311 */
+ };
+ 
+-static struct plx_pci_card_info plx_pci_card_info_ixxat __devinitdata = {
++static struct plx_pci_card_info plx_pci_card_info_ixxat = {
+ 	"IXXAT PC-I 04/PCI", 2,
+ 	PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
+ 	{0, 0x00, 0x00}, { {2, 0x00, 0x80}, {2, 0x200, 0x80} },
+@@ -210,7 +210,7 @@ static struct plx_pci_card_info plx_pci_card_info_ixxat __devinitdata = {
+ 	/* based on PLX9050 */
+ };
+ 
+-static struct plx_pci_card_info plx_pci_card_info_marathon __devinitdata = {
++static struct plx_pci_card_info plx_pci_card_info_marathon = {
+ 	"Marathon CAN-bus-PCI", 2,
+ 	PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
+ 	{0, 0x00, 0x00}, { {2, 0x00, 0x00}, {4, 0x00, 0x00} },
+@@ -218,7 +218,7 @@ static struct plx_pci_card_info plx_pci_card_info_marathon __devinitdata = {
+ 	/* based on PLX9052 */
+ };
+ 
+-static struct plx_pci_card_info plx_pci_card_info_tews __devinitdata = {
++static struct plx_pci_card_info plx_pci_card_info_tews = {
+ 	"TEWS TECHNOLOGIES TPMC810", 2,
+ 	PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
+ 	{0, 0x00, 0x00}, { {2, 0x000, 0x80}, {2, 0x100, 0x80} },
+@@ -226,7 +226,7 @@ static struct plx_pci_card_info plx_pci_card_info_tews __devinitdata = {
+ 	/* based on PLX9030 */
+ };
+ 
+-static struct plx_pci_card_info plx_pci_card_info_cti __devinitdata = {
++static struct plx_pci_card_info plx_pci_card_info_cti = {
+ 	"Connect Tech Inc. CANpro/104-Plus Opto (CRG001)", 2,
+ 	PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
+ 	{0, 0x00, 0x00}, { {2, 0x000, 0x80}, {2, 0x100, 0x80} },
+@@ -484,7 +484,7 @@ static void plx_pci_del_card(struct pci_dev *pdev)
+  * Probe PLX90xx based device for the SJA1000 chips and register each
+  * available CAN channel to SJA1000 Socket-CAN subsystem.
+  */
+-static int __devinit plx_pci_add_card(struct pci_dev *pdev,
++static int plx_pci_add_card(struct pci_dev *pdev,
+ 				      const struct pci_device_id *ent)
+ {
+ 	struct sja1000_priv *priv;
+diff --git a/drivers/net/can/sja1000/sja1000_isa.c b/drivers/net/can/sja1000/sja1000_isa.c
+index 90c5c2dfd2fd..5c8da4661489 100644
+--- a/drivers/net/can/sja1000/sja1000_isa.c
++++ b/drivers/net/can/sja1000/sja1000_isa.c
+@@ -42,11 +42,11 @@ MODULE_LICENSE("GPL v2");
+ 
+ static unsigned long port[MAXDEV];
+ static unsigned long mem[MAXDEV];
+-static int __devinitdata irq[MAXDEV];
+-static int __devinitdata clk[MAXDEV];
+-static unsigned char __devinitdata cdr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
+-static unsigned char __devinitdata ocr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
+-static int __devinitdata indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1};
++static int irq[MAXDEV];
++static int clk[MAXDEV];
++static unsigned char cdr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
++static unsigned char ocr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
++static int indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1};
+ 
+ module_param_array(port, ulong, NULL, S_IRUGO);
+ MODULE_PARM_DESC(port, "I/O port number");
+@@ -117,7 +117,7 @@ static void sja1000_isa_port_write_reg_indirect(const struct sja1000_priv *priv,
+ 	outb(val, base + 1);
+ }
+ 
+-static int __devinit sja1000_isa_probe(struct platform_device *pdev)
++static int sja1000_isa_probe(struct platform_device *pdev)
+ {
+ 	struct net_device *dev;
+ 	struct sja1000_priv *priv;
+@@ -223,7 +223,7 @@ static int __devinit sja1000_isa_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit sja1000_isa_remove(struct platform_device *pdev)
++static int sja1000_isa_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *dev = dev_get_drvdata(&pdev->dev);
+ 	struct sja1000_priv *priv = netdev_priv(dev);
+@@ -248,7 +248,7 @@ static int __devexit sja1000_isa_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver sja1000_isa_driver = {
+ 	.probe = sja1000_isa_probe,
+-	.remove = __devexit_p(sja1000_isa_remove),
++	.remove = sja1000_isa_remove,
+ 	.driver = {
+ 		.name = DRV_NAME,
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c
+index e45258d4369b..0f5917000aa2 100644
+--- a/drivers/net/can/sja1000/sja1000_of_platform.c
++++ b/drivers/net/can/sja1000/sja1000_of_platform.c
+@@ -70,7 +70,7 @@ static void sja1000_ofp_write_reg(const struct sja1000_priv *priv,
+ 	iowrite8(val, priv->reg_base + reg);
+ }
+ 
+-static int __devexit sja1000_ofp_remove(struct platform_device *ofdev)
++static int sja1000_ofp_remove(struct platform_device *ofdev)
+ {
+ 	struct net_device *dev = dev_get_drvdata(&ofdev->dev);
+ 	struct sja1000_priv *priv = netdev_priv(dev);
+@@ -90,7 +90,7 @@ static int __devexit sja1000_ofp_remove(struct platform_device *ofdev)
+ 	return 0;
+ }
+ 
+-static int __devinit sja1000_ofp_probe(struct platform_device *ofdev)
++static int sja1000_ofp_probe(struct platform_device *ofdev)
+ {
+ 	struct device_node *np = ofdev->dev.of_node;
+ 	struct net_device *dev;
+@@ -206,7 +206,7 @@ static int __devinit sja1000_ofp_probe(struct platform_device *ofdev)
+ 	return err;
+ }
+ 
+-static struct of_device_id __devinitdata sja1000_ofp_table[] = {
++static struct of_device_id sja1000_ofp_table[] = {
+ 	{.compatible = "nxp,sja1000"},
+ 	{},
+ };
+@@ -219,7 +219,7 @@ static struct platform_driver sja1000_ofp_driver = {
+ 		.of_match_table = sja1000_ofp_table,
+ 	},
+ 	.probe = sja1000_ofp_probe,
+-	.remove = __devexit_p(sja1000_ofp_remove),
++	.remove = sja1000_ofp_remove,
+ };
+ 
+ module_platform_driver(sja1000_ofp_driver);
+diff --git a/drivers/net/can/sja1000/tscan1.c b/drivers/net/can/sja1000/tscan1.c
+index 9756099a883a..76513dd780c7 100644
+--- a/drivers/net/can/sja1000/tscan1.c
++++ b/drivers/net/can/sja1000/tscan1.c
+@@ -71,7 +71,7 @@ MODULE_LICENSE("GPL");
+ #define TSCAN1_SJA1000_XTAL 16000000
+ 
+ /* SJA1000 IO base addresses */
+-static const unsigned short tscan1_sja1000_addresses[] __devinitconst = {
++static const unsigned short tscan1_sja1000_addresses[] = {
+ 	0x100, 0x120, 0x180, 0x1a0, 0x200, 0x240, 0x280, 0x320
+ };
+ 
+@@ -88,7 +88,7 @@ static void tscan1_write(const struct sja1000_priv *priv, int reg, u8 val)
+ }
+ 
+ /* Probe for a TS-CAN1 board with JP2:JP1 jumper setting ID */
+-static int __devinit tscan1_probe(struct device *dev, unsigned id)
++static int tscan1_probe(struct device *dev, unsigned id)
+ {
+ 	struct net_device *netdev;
+ 	struct sja1000_priv *priv;
+@@ -171,7 +171,7 @@ static int __devinit tscan1_probe(struct device *dev, unsigned id)
+ 	return -ENXIO;
+ }
+ 
+-static int __devexit tscan1_remove(struct device *dev, unsigned id /*unused*/)
++static int tscan1_remove(struct device *dev, unsigned id /*unused*/)
+ {
+ 	struct net_device *netdev;
+ 	struct sja1000_priv *priv;
+@@ -197,7 +197,7 @@ static int __devexit tscan1_remove(struct device *dev, unsigned id /*unused*/)
+ 
+ static struct isa_driver tscan1_isa_driver = {
+ 	.probe = tscan1_probe,
+-	.remove = __devexit_p(tscan1_remove),
++	.remove = tscan1_remove,
+ 	.driver = {
+ 		.name = "tscan1",
+ 	},
+diff --git a/drivers/net/can/softing/softing_cs.c b/drivers/net/can/softing/softing_cs.c
+index c0e1b1eb87a9..ce18ba52e4b9 100644
+--- a/drivers/net/can/softing/softing_cs.c
++++ b/drivers/net/can/softing/softing_cs.c
+@@ -159,7 +159,7 @@ MODULE_FIRMWARE(fw_dir "bcard2.bin");
+ MODULE_FIRMWARE(fw_dir "ldcard2.bin");
+ MODULE_FIRMWARE(fw_dir "cancrd2.bin");
+ 
+-static __devinit const struct softing_platform_data
++static const struct softing_platform_data
+ *softingcs_find_platform_data(unsigned int manf, unsigned int prod)
+ {
+ 	const struct softing_platform_data *lp;
+@@ -193,7 +193,7 @@ static int softingcs_enable_irq(struct platform_device *pdev, int v)
+ /*
+  * pcmcia check
+  */
+-static __devinit int softingcs_probe_config(struct pcmcia_device *pcmcia,
++static int softingcs_probe_config(struct pcmcia_device *pcmcia,
+ 		void *priv_data)
+ {
+ 	struct softing_platform_data *pdat = priv_data;
+@@ -215,7 +215,7 @@ static __devinit int softingcs_probe_config(struct pcmcia_device *pcmcia,
+ 	return pcmcia_request_window(pcmcia, pres, memspeed);
+ }
+ 
+-static __devexit void softingcs_remove(struct pcmcia_device *pcmcia)
++static void softingcs_remove(struct pcmcia_device *pcmcia)
+ {
+ 	struct platform_device *pdev = pcmcia->priv;
+ 
+@@ -235,7 +235,7 @@ static void softingcs_pdev_release(struct device *dev)
+ 	kfree(pdev);
+ }
+ 
+-static __devinit int softingcs_probe(struct pcmcia_device *pcmcia)
++static int softingcs_probe(struct pcmcia_device *pcmcia)
+ {
+ 	int ret;
+ 	struct platform_device *pdev;
+@@ -338,7 +338,7 @@ static struct pcmcia_driver softingcs_driver = {
+ 	.name		= "softingcs",
+ 	.id_table	= softingcs_ids,
+ 	.probe		= softingcs_probe,
+-	.remove		= __devexit_p(softingcs_remove),
++	.remove		= softingcs_remove,
+ };
+ 
+ static int __init softingcs_start(void)
+diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c
+index f2a221e7b968..50b1e0f21f1c 100644
+--- a/drivers/net/can/softing/softing_main.c
++++ b/drivers/net/can/softing/softing_main.c
+@@ -478,7 +478,7 @@ static void softing_card_shutdown(struct softing *card)
+ 	mutex_unlock(&card->fw.lock);
+ }
+ 
+-static __devinit int softing_card_boot(struct softing *card)
++static int softing_card_boot(struct softing *card)
+ {
+ 	int ret, j;
+ 	static const uint8_t stream[] = {
+@@ -645,7 +645,7 @@ static const struct can_bittiming_const softing_btr_const = {
+ };
+ 
+ 
+-static __devinit struct net_device *softing_netdev_create(struct softing *card,
++static struct net_device *softing_netdev_create(struct softing *card,
+ 		uint16_t chip_id)
+ {
+ 	struct net_device *netdev;
+@@ -676,7 +676,7 @@ static __devinit struct net_device *softing_netdev_create(struct softing *card,
+ 	return netdev;
+ }
+ 
+-static __devinit int softing_netdev_register(struct net_device *netdev)
++static int softing_netdev_register(struct net_device *netdev)
+ {
+ 	int ret;
+ 
+@@ -745,7 +745,7 @@ static const struct attribute_group softing_pdev_group = {
+ /*
+  * platform driver
+  */
+-static __devexit int softing_pdev_remove(struct platform_device *pdev)
++static int softing_pdev_remove(struct platform_device *pdev)
+ {
+ 	struct softing *card = platform_get_drvdata(pdev);
+ 	int j;
+@@ -766,7 +766,7 @@ static __devexit int softing_pdev_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static __devinit int softing_pdev_probe(struct platform_device *pdev)
++static int softing_pdev_probe(struct platform_device *pdev)
+ {
+ 	const struct softing_platform_data *pdat = pdev->dev.platform_data;
+ 	struct softing *card;
+@@ -871,7 +871,7 @@ static struct platform_driver softing_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = softing_pdev_probe,
+-	.remove = __devexit_p(softing_pdev_remove),
++	.remove = softing_pdev_remove,
+ };
+ 
+ module_platform_driver(softing_driver);
+diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c
+index 1267b366dcfe..f898c6363729 100644
+--- a/drivers/net/can/ti_hecc.c
++++ b/drivers/net/can/ti_hecc.c
+@@ -978,7 +978,7 @@ static int ti_hecc_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit ti_hecc_remove(struct platform_device *pdev)
++static int ti_hecc_remove(struct platform_device *pdev)
+ {
+ 	struct resource *res;
+ 	struct net_device *ndev = platform_get_drvdata(pdev);
+@@ -1045,7 +1045,7 @@ static struct platform_driver ti_hecc_driver = {
+ 		.owner   = THIS_MODULE,
+ 	},
+ 	.probe = ti_hecc_probe,
+-	.remove = __devexit_p(ti_hecc_remove),
++	.remove = ti_hecc_remove,
+ 	.suspend = ti_hecc_suspend,
+ 	.resume = ti_hecc_resume,
+ };

commit 7c47bab62192d4dd6ba7f7633f2fb94d259e964e
+Author: Bill Pemberton 
+Date:   Mon Dec 3 09:22:43 2012 -0500
+
+    ARCNET: remove __dev* attributes
+    
+    CONFIG_HOTPLUG is going away as an option.  As result the __dev*
+    markings will be going away.
+    
+    Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
+    and __devexit.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c
+index d427493997b6..cbc44f53755a 100644
+--- a/drivers/net/arcnet/com20020-pci.c
++++ b/drivers/net/arcnet/com20020-pci.c
+@@ -61,7 +61,7 @@ module_param(clockp, int, 0);
+ module_param(clockm, int, 0);
+ MODULE_LICENSE("GPL");
+ 
+-static int __devinit com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
++static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ 	struct net_device *dev;
+ 	struct arcnet_local *lp;
+@@ -135,7 +135,7 @@ static int __devinit com20020pci_probe(struct pci_dev *pdev, const struct pci_de
+ 	return err;
+ }
+ 
+-static void __devexit com20020pci_remove(struct pci_dev *pdev)
++static void com20020pci_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	unregister_netdev(dev);
+@@ -178,7 +178,7 @@ static struct pci_driver com20020pci_driver = {
+ 	.name		= "com20020",
+ 	.id_table	= com20020pci_id_table,
+ 	.probe		= com20020pci_probe,
+-	.remove		= __devexit_p(com20020pci_remove),
++	.remove		= com20020pci_remove,
+ };
+ 
+ static int __init com20020pci_init(void)

commit da095fd3d5063f2dd03468d71f7df39a0430d86f
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:46 2012 -0500
+
+    acpi: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Rafael J. Wysocki 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
+index 1599566ed1fe..73bca1141fa7 100644
+--- a/drivers/acpi/apei/ghes.c
++++ b/drivers/acpi/apei/ghes.c
+@@ -901,7 +901,7 @@ static unsigned long ghes_esource_prealloc_size(
+ 	return prealloc_size;
+ }
+ 
+-static int __devinit ghes_probe(struct platform_device *ghes_dev)
++static int ghes_probe(struct platform_device *ghes_dev)
+ {
+ 	struct acpi_hest_generic *generic;
+ 	struct ghes *ghes = NULL;
+diff --git a/drivers/acpi/hed.c b/drivers/acpi/hed.c
+index 20a0f2c3ca3b..0ec28a38f607 100644
+--- a/drivers/acpi/hed.c
++++ b/drivers/acpi/hed.c
+@@ -61,7 +61,7 @@ static void acpi_hed_notify(struct acpi_device *device, u32 event)
+ 	blocking_notifier_call_chain(&acpi_hed_notify_list, 0, NULL);
+ }
+ 
+-static int __devinit acpi_hed_add(struct acpi_device *device)
++static int acpi_hed_add(struct acpi_device *device)
+ {
+ 	/* Only one hardware error device */
+ 	if (hed_handle)
+diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
+index bce469c0b48a..f70b9e5fc1b5 100644
+--- a/drivers/acpi/pci_root.c
++++ b/drivers/acpi/pci_root.c
+@@ -445,7 +445,7 @@ acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 req)
+ }
+ EXPORT_SYMBOL(acpi_pci_osc_control_set);
+ 
+-static int __devinit acpi_pci_root_add(struct acpi_device *device)
++static int acpi_pci_root_add(struct acpi_device *device)
+ {
+ 	unsigned long long segment, bus;
+ 	acpi_status status;

commit 15856ad50bf5ea02a5ee22399c036d49e7e1124d
+Author: Bill Pemberton 
+Date:   Wed Nov 21 15:35:00 2012 -0500
+
+    PCI: Remove __dev* markings
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p, __devint,
+    __devinitdata, __devinitconst, and _devexit are no longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Bjorn Helgaas 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/pci/hotplug/cpcihp_zt5550.c b/drivers/pci/hotplug/cpcihp_zt5550.c
+index 6bf8d2ab164f..449b4bbc8301 100644
+--- a/drivers/pci/hotplug/cpcihp_zt5550.c
++++ b/drivers/pci/hotplug/cpcihp_zt5550.c
+@@ -271,7 +271,7 @@ static int zt5550_hc_init_one (struct pci_dev *pdev, const struct pci_device_id
+ 
+ }
+ 
+-static void __devexit zt5550_hc_remove_one(struct pci_dev *pdev)
++static void zt5550_hc_remove_one(struct pci_dev *pdev)
+ {
+ 	cpci_hp_stop();
+ 	cpci_hp_unregister_bus(bus0);
+@@ -290,7 +290,7 @@ static struct pci_driver zt5550_hc_driver = {
+ 	.name		= "zt5550_hc",
+ 	.id_table	= zt5550_hc_pci_tbl,
+ 	.probe		= zt5550_hc_init_one,
+-	.remove		= __devexit_p(zt5550_hc_remove_one),
++	.remove		= zt5550_hc_remove_one,
+ };
+ 
+ static int __init zt5550_init(void)
+diff --git a/drivers/pci/ioapic.c b/drivers/pci/ioapic.c
+index 205af8dc83c2..2eca902a4283 100644
+--- a/drivers/pci/ioapic.c
++++ b/drivers/pci/ioapic.c
+@@ -27,7 +27,7 @@ struct ioapic {
+ 	u32		gsi_base;
+ };
+ 
+-static int __devinit ioapic_probe(struct pci_dev *dev, const struct pci_device_id *ent)
++static int ioapic_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+ {
+ 	acpi_handle handle;
+ 	acpi_status status;
+@@ -88,7 +88,7 @@ static int __devinit ioapic_probe(struct pci_dev *dev, const struct pci_device_i
+ 	return -ENODEV;
+ }
+ 
+-static void __devexit ioapic_remove(struct pci_dev *dev)
++static void ioapic_remove(struct pci_dev *dev)
+ {
+ 	struct ioapic *ioapic = pci_get_drvdata(dev);
+ 
+@@ -110,7 +110,7 @@ static struct pci_driver ioapic_driver = {
+ 	.name		= "ioapic",
+ 	.id_table	= ioapic_devices,
+ 	.probe		= ioapic_probe,
+-	.remove		= __devexit_p(ioapic_remove),
++	.remove		= ioapic_remove,
+ };
+ 
+ static int __init ioapic_init(void)
+diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
+index aabf64798bda..bdf66b500f22 100644
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -86,7 +86,7 @@ enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_TUNE_OFF;
+  * the dfl or actual value as it sees fit.  Don't forget this is
+  * measured in 32-bit words, not bytes.
+  */
+-u8 pci_dfl_cache_line_size __devinitdata = L1_CACHE_BYTES >> 2;
++u8 pci_dfl_cache_line_size = L1_CACHE_BYTES >> 2;
+ u8 pci_cache_line_size;
+ 
+ /*
+@@ -3857,7 +3857,7 @@ static int __init pci_resource_alignment_sysfs_init(void)
+ 
+ late_initcall(pci_resource_alignment_sysfs_init);
+ 
+-static void __devinit pci_no_domains(void)
++static void pci_no_domains(void)
+ {
+ #ifdef CONFIG_PCI_DOMAINS
+ 	pci_domains_supported = 0;
+diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
+index 030cf12d5468..76ef634caf6f 100644
+--- a/drivers/pci/pcie/aer/aerdrv.c
++++ b/drivers/pci/pcie/aer/aerdrv.c
+@@ -41,7 +41,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
+ MODULE_DESCRIPTION(DRIVER_DESC);
+ MODULE_LICENSE("GPL");
+ 
+-static int __devinit aer_probe(struct pcie_device *dev);
++static int aer_probe(struct pcie_device *dev);
+ static void aer_remove(struct pcie_device *dev);
+ static pci_ers_result_t aer_error_detected(struct pci_dev *dev,
+ 	enum pci_channel_state error);
+@@ -300,7 +300,7 @@ static void aer_remove(struct pcie_device *dev)
+  *
+  * Invoked when PCI Express bus loads AER service driver.
+  */
+-static int __devinit aer_probe(struct pcie_device *dev)
++static int aer_probe(struct pcie_device *dev)
+ {
+ 	int status;
+ 	struct aer_rpc *rpc;
+diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
+index 0761d90ca279..d4824cb78b49 100644
+--- a/drivers/pci/pcie/portdrv_pci.c
++++ b/drivers/pci/pcie/portdrv_pci.c
+@@ -182,7 +182,7 @@ static const struct pci_device_id port_runtime_pm_black_list[] = {
+  * this port device.
+  *
+  */
+-static int __devinit pcie_portdrv_probe(struct pci_dev *dev,
++static int pcie_portdrv_probe(struct pci_dev *dev,
+ 					const struct pci_device_id *id)
+ {
+ 	int status;
+diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
+index 034cb1c73092..3683f6094e3f 100644
+--- a/drivers/pci/probe.c
++++ b/drivers/pci/probe.c
+@@ -305,7 +305,7 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
+ 	}
+ }
+ 
+-static void __devinit pci_read_bridge_io(struct pci_bus *child)
++static void pci_read_bridge_io(struct pci_bus *child)
+ {
+ 	struct pci_dev *dev = child->self;
+ 	u8 io_base_lo, io_limit_lo;
+@@ -345,7 +345,7 @@ static void __devinit pci_read_bridge_io(struct pci_bus *child)
+ 	}
+ }
+ 
+-static void __devinit pci_read_bridge_mmio(struct pci_bus *child)
++static void pci_read_bridge_mmio(struct pci_bus *child)
+ {
+ 	struct pci_dev *dev = child->self;
+ 	u16 mem_base_lo, mem_limit_lo;
+@@ -367,7 +367,7 @@ static void __devinit pci_read_bridge_mmio(struct pci_bus *child)
+ 	}
+ }
+ 
+-static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child)
++static void pci_read_bridge_mmio_pref(struct pci_bus *child)
+ {
+ 	struct pci_dev *dev = child->self;
+ 	u16 mem_base_lo, mem_limit_lo;
+@@ -417,7 +417,7 @@ static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child)
+ 	}
+ }
+ 
+-void __devinit pci_read_bridge_bases(struct pci_bus *child)
++void pci_read_bridge_bases(struct pci_bus *child)
+ {
+ 	struct pci_dev *dev = child->self;
+ 	struct resource *res;
+@@ -705,7 +705,7 @@ static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
+  * them, we proceed to assigning numbers to the remaining buses in
+  * order to avoid overlaps between old and new bus numbers.
+  */
+-int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
++int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
+ {
+ 	struct pci_bus *child;
+ 	int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS);
+@@ -1586,7 +1586,7 @@ void pcie_bus_configure_settings(struct pci_bus *bus, u8 mpss)
+ }
+ EXPORT_SYMBOL_GPL(pcie_bus_configure_settings);
+ 
+-unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
++unsigned int pci_scan_child_bus(struct pci_bus *bus)
+ {
+ 	unsigned int devfn, pass, max = bus->busn_res.start;
+ 	struct pci_dev *dev;
+@@ -1790,7 +1790,7 @@ void pci_bus_release_busn_res(struct pci_bus *b)
+ 			res, ret ? "can not be" : "is");
+ }
+ 
+-struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
++struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
+ 		struct pci_ops *ops, void *sysdata, struct list_head *resources)
+ {
+ 	struct pci_host_bridge_window *window;
+@@ -1826,7 +1826,7 @@ struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
+ EXPORT_SYMBOL(pci_scan_root_bus);
+ 
+ /* Deprecated; use pci_scan_root_bus() instead */
+-struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent,
++struct pci_bus *pci_scan_bus_parented(struct device *parent,
+ 		int bus, struct pci_ops *ops, void *sysdata)
+ {
+ 	LIST_HEAD(resources);
+@@ -1844,7 +1844,7 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent,
+ }
+ EXPORT_SYMBOL(pci_scan_bus_parented);
+ 
+-struct pci_bus * __devinit pci_scan_bus(int bus, struct pci_ops *ops,
++struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops,
+ 					void *sysdata)
+ {
+ 	LIST_HEAD(resources);
+diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
+index 7a451ff56ecc..22ad3ee0cf0b 100644
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -37,7 +37,7 @@
+  * key system devices. For devices that need to have mmio decoding always-on,
+  * we need to set the dev->mmio_always_on bit.
+  */
+-static void __devinit quirk_mmio_always_on(struct pci_dev *dev)
++static void quirk_mmio_always_on(struct pci_dev *dev)
+ {
+ 	dev->mmio_always_on = 1;
+ }
+@@ -48,7 +48,7 @@ DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_ANY_ID, PCI_ANY_ID,
+  * Mark this device with a broken_parity_status, to allow
+  * PCI scanning code to "skip" this now blacklisted device.
+  */
+-static void __devinit quirk_mellanox_tavor(struct pci_dev *dev)
++static void quirk_mellanox_tavor(struct pci_dev *dev)
+ {
+ 	dev->broken_parity_status = 1;	/* This device gives false positives */
+ }
+@@ -83,7 +83,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82441,	quirk_p
+     This appears to be BIOS not version dependent. So presumably there is a 
+     chipset level fix */
+     
+-static void __devinit quirk_isa_dma_hangs(struct pci_dev *dev)
++static void quirk_isa_dma_hangs(struct pci_dev *dev)
+ {
+ 	if (!isa_dma_bridge_buggy) {
+ 		isa_dma_bridge_buggy=1;
+@@ -106,7 +106,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_3,	quirk_isa_d
+  * Intel NM10 "TigerPoint" LPC PM1a_STS.BM_STS must be clear
+  * for some HT machines to use C4 w/o hanging.
+  */
+-static void __devinit quirk_tigerpoint_bm_sts(struct pci_dev *dev)
++static void quirk_tigerpoint_bm_sts(struct pci_dev *dev)
+ {
+ 	u32 pmbase;
+ 	u16 pm1a;
+@@ -125,7 +125,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TGP_LPC, quirk
+ /*
+  *	Chipsets where PCI->PCI transfers vanish or hang
+  */
+-static void __devinit quirk_nopcipci(struct pci_dev *dev)
++static void quirk_nopcipci(struct pci_dev *dev)
+ {
+ 	if ((pci_pci_problems & PCIPCI_FAIL)==0) {
+ 		dev_info(&dev->dev, "Disabling direct PCI/PCI transfers\n");
+@@ -135,7 +135,7 @@ static void __devinit quirk_nopcipci(struct pci_dev *dev)
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_5597,		quirk_nopcipci);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_496,		quirk_nopcipci);
+ 
+-static void __devinit quirk_nopciamd(struct pci_dev *dev)
++static void quirk_nopciamd(struct pci_dev *dev)
+ {
+ 	u8 rev;
+ 	pci_read_config_byte(dev, 0x08, &rev);
+@@ -150,7 +150,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_8151_0,	quirk_nopci
+ /*
+  *	Triton requires workarounds to be used by the drivers
+  */
+-static void __devinit quirk_triton(struct pci_dev *dev)
++static void quirk_triton(struct pci_dev *dev)
+ {
+ 	if ((pci_pci_problems&PCIPCI_TRITON)==0) {
+ 		dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
+@@ -229,7 +229,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8361,		quirk_viala
+ /*
+  *	VIA Apollo VP3 needs ETBF on BT848/878
+  */
+-static void __devinit quirk_viaetbf(struct pci_dev *dev)
++static void quirk_viaetbf(struct pci_dev *dev)
+ {
+ 	if ((pci_pci_problems&PCIPCI_VIAETBF)==0) {
+ 		dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
+@@ -238,7 +238,7 @@ static void __devinit quirk_viaetbf(struct pci_dev *dev)
+ }
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C597_0,	quirk_viaetbf);
+ 
+-static void __devinit quirk_vsfx(struct pci_dev *dev)
++static void quirk_vsfx(struct pci_dev *dev)
+ {
+ 	if ((pci_pci_problems&PCIPCI_VSFX)==0) {
+ 		dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
+@@ -253,7 +253,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C576,	quirk_vsfx)
+  *	workaround applied too
+  *	[Info kindly provided by ALi]
+  */	
+-static void __devinit quirk_alimagik(struct pci_dev *dev)
++static void quirk_alimagik(struct pci_dev *dev)
+ {
+ 	if ((pci_pci_problems&PCIPCI_ALIMAGIK)==0) {
+ 		dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
+@@ -267,7 +267,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 	PCI_DEVICE_ID_AL_M1651, 	quirk_alimag
+  *	Natoma has some interesting boundary conditions with Zoran stuff
+  *	at least
+  */
+-static void __devinit quirk_natoma(struct pci_dev *dev)
++static void quirk_natoma(struct pci_dev *dev)
+ {
+ 	if ((pci_pci_problems&PCIPCI_NATOMA)==0) {
+ 		dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
+@@ -285,7 +285,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443BX_2, 	qu
+  *  This chip can cause PCI parity errors if config register 0xA0 is read
+  *  while DMAs are occurring.
+  */
+-static void __devinit quirk_citrine(struct pci_dev *dev)
++static void quirk_citrine(struct pci_dev *dev)
+ {
+ 	dev->cfg_size = 0xA0;
+ }
+@@ -295,7 +295,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM,	PCI_DEVICE_ID_IBM_CITRINE,	quirk_cit
+  *  S3 868 and 968 chips report region size equal to 32M, but they decode 64M.
+  *  If it's needed, re-allocate the region.
+  */
+-static void __devinit quirk_s3_64M(struct pci_dev *dev)
++static void quirk_s3_64M(struct pci_dev *dev)
+ {
+ 	struct resource *r = &dev->resource[0];
+ 
+@@ -313,7 +313,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3,	PCI_DEVICE_ID_S3_968,		quirk_s3_64M);
+  * BAR0 should be 8 bytes; instead, it may be set to something like 8k
+  * (which conflicts w/ BAR1's memory range).
+  */
+-static void __devinit quirk_cs5536_vsa(struct pci_dev *dev)
++static void quirk_cs5536_vsa(struct pci_dev *dev)
+ {
+ 	if (pci_resource_len(dev, 0) != 8) {
+ 		struct resource *res = &dev->resource[0];
+@@ -324,7 +324,7 @@ static void __devinit quirk_cs5536_vsa(struct pci_dev *dev)
+ }
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, quirk_cs5536_vsa);
+ 
+-static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region,
++static void quirk_io_region(struct pci_dev *dev, unsigned region,
+ 	unsigned size, int nr, const char *name)
+ {
+ 	region &= ~(size-1);
+@@ -352,7 +352,7 @@ static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region,
+  *	ATI Northbridge setups MCE the processor if you even
+  *	read somewhere between 0x3b0->0x3bb or read 0x3d3
+  */
+-static void __devinit quirk_ati_exploding_mce(struct pci_dev *dev)
++static void quirk_ati_exploding_mce(struct pci_dev *dev)
+ {
+ 	dev_info(&dev->dev, "ATI Northbridge, reserving I/O ports 0x3b0 to 0x3bb\n");
+ 	/* Mae rhaid i ni beidio ag edrych ar y lleoliadiau I/O hyn */
+@@ -372,7 +372,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI,	PCI_DEVICE_ID_ATI_RS100,   quirk_ati_
+  *	0xE0 (64 bytes of ACPI registers)
+  *	0xE2 (32 bytes of SMB registers)
+  */
+-static void __devinit quirk_ali7101_acpi(struct pci_dev *dev)
++static void quirk_ali7101_acpi(struct pci_dev *dev)
+ {
+ 	u16 region;
+ 
+@@ -440,7 +440,7 @@ static void piix4_mem_quirk(struct pci_dev *dev, const char *name, unsigned int
+  *	0x90 (16 bytes of SMB registers)
+  * and a few strange programmable PIIX4 device resources.
+  */
+-static void __devinit quirk_piix4_acpi(struct pci_dev *dev)
++static void quirk_piix4_acpi(struct pci_dev *dev)
+ {
+ 	u32 region, res_a;
+ 
+@@ -489,7 +489,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82443MX_3,	qui
+  *	0x40 (128 bytes of ACPI, GPIO & TCO registers)
+  *	0x58 (64 bytes of GPIO I/O space)
+  */
+-static void __devinit quirk_ich4_lpc_acpi(struct pci_dev *dev)
++static void quirk_ich4_lpc_acpi(struct pci_dev *dev)
+ {
+ 	u32 region;
+ 	u8 enable;
+@@ -531,7 +531,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801DB_12,
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801EB_0,		quirk_ich4_lpc_acpi);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_ESB_1,		quirk_ich4_lpc_acpi);
+ 
+-static void __devinit ich6_lpc_acpi_gpio(struct pci_dev *dev)
++static void ich6_lpc_acpi_gpio(struct pci_dev *dev)
+ {
+ 	u32 region;
+ 	u8 enable;
+@@ -555,7 +555,7 @@ static void __devinit ich6_lpc_acpi_gpio(struct pci_dev *dev)
+ 	}
+ }
+ 
+-static void __devinit ich6_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name, int dynsize)
++static void ich6_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name, int dynsize)
+ {
+ 	u32 val;
+ 	u32 size, base;
+@@ -583,7 +583,7 @@ static void __devinit ich6_lpc_generic_decode(struct pci_dev *dev, unsigned reg,
+ 	dev_info(&dev->dev, "%s PIO at %04x-%04x\n", name, base, base+size-1);
+ }
+ 
+-static void __devinit quirk_ich6_lpc(struct pci_dev *dev)
++static void quirk_ich6_lpc(struct pci_dev *dev)
+ {
+ 	/* Shared ACPI/GPIO decode with all ICH6+ */
+ 	ich6_lpc_acpi_gpio(dev);
+@@ -595,7 +595,7 @@ static void __devinit quirk_ich6_lpc(struct pci_dev *dev)
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH6_0, quirk_ich6_lpc);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH6_1, quirk_ich6_lpc);
+ 
+-static void __devinit ich7_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name)
++static void ich7_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name)
+ {
+ 	u32 val;
+ 	u32 mask, base;
+@@ -619,7 +619,7 @@ static void __devinit ich7_lpc_generic_decode(struct pci_dev *dev, unsigned reg,
+ }
+ 
+ /* ICH7-10 has the same common LPC generic IO decode registers */
+-static void __devinit quirk_ich7_lpc(struct pci_dev *dev)
++static void quirk_ich7_lpc(struct pci_dev *dev)
+ {
+ 	/* We share the common ACPI/GPIO decode with ICH6 */
+ 	ich6_lpc_acpi_gpio(dev);
+@@ -648,7 +648,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_ICH10_1, qui
+  * VIA ACPI: One IO region pointed to by longword at
+  *	0x48 or 0x20 (256 bytes of ACPI registers)
+  */
+-static void __devinit quirk_vt82c586_acpi(struct pci_dev *dev)
++static void quirk_vt82c586_acpi(struct pci_dev *dev)
+ {
+ 	u32 region;
+ 
+@@ -666,7 +666,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_3,	quirk_vt
+  *	0x70 (128 bytes of hardware monitoring register)
+  *	0x90 (16 bytes of SMB registers)
+  */
+-static void __devinit quirk_vt82c686_acpi(struct pci_dev *dev)
++static void quirk_vt82c686_acpi(struct pci_dev *dev)
+ {
+ 	u16 hm;
+ 	u32 smb;
+@@ -688,7 +688,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_4,	quirk_vt
+  *	0x88 (128 bytes of power management registers)
+  *	0xd0 (16 bytes of SMB registers)
+  */
+-static void __devinit quirk_vt8235_acpi(struct pci_dev *dev)
++static void quirk_vt8235_acpi(struct pci_dev *dev)
+ {
+ 	u16 pm, smb;
+ 
+@@ -706,7 +706,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8235,	quirk_vt8235
+  * TI XIO2000a PCIe-PCI Bridge erroneously reports it supports fast back-to-back:
+  *	Disable fast back-to-back on the secondary bus segment
+  */
+-static void __devinit quirk_xio2000a(struct pci_dev *dev)
++static void quirk_xio2000a(struct pci_dev *dev)
+ {
+ 	struct pci_dev *pdev;
+ 	u16 command;
+@@ -780,7 +780,7 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8237,		quirk
+  * noapic specified. For the moment we assume it's the erratum. We may be wrong
+  * of course. However the advice is demonstrably good even if so..
+  */
+-static void __devinit quirk_amd_ioapic(struct pci_dev *dev)
++static void quirk_amd_ioapic(struct pci_dev *dev)
+ {
+ 	if (dev->revision >= 0x02) {
+ 		dev_warn(&dev->dev, "I/O APIC: AMD Erratum #22 may be present. In the event of instability try\n");
+@@ -789,7 +789,7 @@ static void __devinit quirk_amd_ioapic(struct pci_dev *dev)
+ }
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_VIPER_7410,	quirk_amd_ioapic);
+ 
+-static void __devinit quirk_ioapic_rmw(struct pci_dev *dev)
++static void quirk_ioapic_rmw(struct pci_dev *dev)
+ {
+ 	if (dev->devfn == 0 && dev->bus->number == 0)
+ 		sis_apic_bug = 1;
+@@ -801,7 +801,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,	PCI_ANY_ID,			quirk_ioapic_rmw);
+  * Some settings of MMRBC can lead to data corruption so block changes.
+  * See AMD 8131 HyperTransport PCI-X Tunnel Revision Guide
+  */
+-static void __devinit quirk_amd_8131_mmrbc(struct pci_dev *dev)
++static void quirk_amd_8131_mmrbc(struct pci_dev *dev)
+ {
+ 	if (dev->subordinate && dev->revision <= 0x12) {
+ 		dev_info(&dev->dev, "AMD8131 rev %x detected; "
+@@ -819,7 +819,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_
+  * value of the ACPI SCI interrupt is only done for convenience.
+  *	-jgarzik
+  */
+-static void __devinit quirk_via_acpi(struct pci_dev *d)
++static void quirk_via_acpi(struct pci_dev *d)
+ {
+ 	/*
+ 	 * VIA ACPI device: SCI IRQ line in PCI config byte 0x42
+@@ -926,7 +926,7 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_vlink);
+  * We need to switch it off to be able to recognize the real
+  * type of the chip.
+  */
+-static void __devinit quirk_vt82c598_id(struct pci_dev *dev)
++static void quirk_vt82c598_id(struct pci_dev *dev)
+ {
+ 	pci_write_config_byte(dev, 0xfc, 0);
+ 	pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device);
+@@ -978,7 +978,7 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_FE_GATE_700C
+  *	assigned to it. We force a larger allocation to ensure that
+  *	nothing gets put too close to it.
+  */
+-static void __devinit quirk_dunord ( struct pci_dev * dev )
++static void quirk_dunord(struct pci_dev *dev)
+ {
+ 	struct resource *r = &dev->resource [1];
+ 	r->start = 0;
+@@ -992,7 +992,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DUNORD,	PCI_DEVICE_ID_DUNORD_I3000,	quirk
+  * in the ProgIf. Unfortunately, the ProgIf value is wrong - 0x80
+  * instead of 0x01.
+  */
+-static void __devinit quirk_transparent_bridge(struct pci_dev *dev)
++static void quirk_transparent_bridge(struct pci_dev *dev)
+ {
+ 	dev->transparent = 1;
+ }
+@@ -1066,7 +1066,7 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SATA
+ /*
+  *	Serverworks CSB5 IDE does not fully support native mode
+  */
+-static void __devinit quirk_svwks_csb5ide(struct pci_dev *pdev)
++static void quirk_svwks_csb5ide(struct pci_dev *pdev)
+ {
+ 	u8 prog;
+ 	pci_read_config_byte(pdev, PCI_CLASS_PROG, &prog);
+@@ -1082,7 +1082,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB
+ /*
+  *	Intel 82801CAM ICH3-M datasheet says IDE modes must be the same
+  */
+-static void __devinit quirk_ide_samemode(struct pci_dev *pdev)
++static void quirk_ide_samemode(struct pci_dev *pdev)
+ {
+ 	u8 prog;
+ 
+@@ -1101,7 +1101,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, qui
+  * Some ATA devices break if put into D3
+  */
+ 
+-static void __devinit quirk_no_ata_d3(struct pci_dev *pdev)
++static void quirk_no_ata_d3(struct pci_dev *pdev)
+ {
+ 	pdev->dev_flags |= PCI_DEV_FLAGS_NO_D3;
+ }
+@@ -1121,7 +1121,7 @@ DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_VIA, PCI_ANY_ID,
+ /* This was originally an Alpha specific thing, but it really fits here.
+  * The i82375 PCI/EISA bridge appears as non-classified. Fix that.
+  */
+-static void __devinit quirk_eisa_bridge(struct pci_dev *dev)
++static void quirk_eisa_bridge(struct pci_dev *dev)
+ {
+ 	dev->class = PCI_CLASS_BRIDGE_EISA << 8;
+ }
+@@ -1155,7 +1155,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82375,	quirk_e
+  */
+ static int asus_hides_smbus;
+ 
+-static void __devinit asus_hides_smbus_hostbridge(struct pci_dev *dev)
++static void asus_hides_smbus_hostbridge(struct pci_dev *dev)
+ {
+ 	if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK)) {
+ 		if (dev->device == PCI_DEVICE_ID_INTEL_82845_HB)
+@@ -1538,7 +1538,7 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB3
+ #endif
+ 
+ #ifdef CONFIG_X86_IO_APIC
+-static void __devinit quirk_alder_ioapic(struct pci_dev *pdev)
++static void quirk_alder_ioapic(struct pci_dev *pdev)
+ {
+ 	int i;
+ 
+@@ -1561,7 +1561,7 @@ static void __devinit quirk_alder_ioapic(struct pci_dev *pdev)
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_EESSC,	quirk_alder_ioapic);
+ #endif
+ 
+-static void __devinit quirk_pcie_mch(struct pci_dev *pdev)
++static void quirk_pcie_mch(struct pci_dev *pdev)
+ {
+ 	pci_msi_off(pdev);
+ 	pdev->no_msi = 1;
+@@ -1575,7 +1575,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7525_MCH,	quir
+  * It's possible for the MSI to get corrupted if shpc and acpi
+  * are used together on certain PXH-based systems.
+  */
+-static void __devinit quirk_pcie_pxh(struct pci_dev *dev)
++static void quirk_pcie_pxh(struct pci_dev *dev)
+ {
+ 	pci_msi_off(dev);
+ 	dev->no_msi = 1;
+@@ -1777,7 +1777,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD,   PCI_DEVICE_ID_AMD_8111_SMBUS, 	qui
+  * but the PIO transfers won't work if BAR0 falls at the odd 8 bytes.
+  * Re-allocate the region if needed...
+  */
+-static void __devinit quirk_tc86c001_ide(struct pci_dev *dev)
++static void quirk_tc86c001_ide(struct pci_dev *dev)
+ {
+ 	struct resource *r = &dev->resource[0];
+ 
+@@ -1790,7 +1790,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA_2,
+ 			 PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE,
+ 			 quirk_tc86c001_ide);
+ 
+-static void __devinit quirk_netmos(struct pci_dev *dev)
++static void quirk_netmos(struct pci_dev *dev)
+ {
+ 	unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4;
+ 	unsigned int num_serial = dev->subsystem_device & 0xf;
+@@ -1828,7 +1828,7 @@ static void __devinit quirk_netmos(struct pci_dev *dev)
+ DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID,
+ 			 PCI_CLASS_COMMUNICATION_SERIAL, 8, quirk_netmos);
+ 
+-static void __devinit quirk_e100_interrupt(struct pci_dev *dev)
++static void quirk_e100_interrupt(struct pci_dev *dev)
+ {
+ 	u16 command, pmcsr;
+ 	u8 __iomem *csr;
+@@ -1901,7 +1901,7 @@ DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
+  * The 82575 and 82598 may experience data corruption issues when transitioning
+  * out of L0S.  To prevent this we need to disable L0S on the pci-e link
+  */
+-static void __devinit quirk_disable_aspm_l0s(struct pci_dev *dev)
++static void quirk_disable_aspm_l0s(struct pci_dev *dev)
+ {
+ 	dev_info(&dev->dev, "Disabling L0s\n");
+ 	pci_disable_link_state(dev, PCIE_LINK_STATE_L0S);
+@@ -1921,7 +1921,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f1, quirk_disable_aspm_l0s);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f4, quirk_disable_aspm_l0s);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1508, quirk_disable_aspm_l0s);
+ 
+-static void __devinit fixup_rev1_53c810(struct pci_dev* dev)
++static void fixup_rev1_53c810(struct pci_dev *dev)
+ {
+ 	/* rev 1 ncr53c810 chips don't set the class at all which means
+ 	 * they don't get their resources remapped. Fix that here.
+@@ -1935,7 +1935,7 @@ static void __devinit fixup_rev1_53c810(struct pci_dev* dev)
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810);
+ 
+ /* Enable 1k I/O space granularity on the Intel P64H2 */
+-static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev)
++static void quirk_p64h2_1k_io(struct pci_dev *dev)
+ {
+ 	u16 en1k;
+ 
+@@ -1968,7 +1968,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA,  PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
+ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_NVIDIA,  PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
+ 			quirk_nvidia_ck804_pcie_aer_ext_cap);
+ 
+-static void __devinit quirk_via_cx700_pci_parking_caching(struct pci_dev *dev)
++static void quirk_via_cx700_pci_parking_caching(struct pci_dev *dev)
+ {
+ 	/*
+ 	 * Disable PCI Bus Parking and PCI Master read caching on CX700
+@@ -2031,7 +2031,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, 0x324e, quirk_via_cx700_pci_parking_c
+  * We believe that it is legal to read beyond the end tag and
+  * therefore the solution is to limit the read/write length.
+  */
+-static void __devinit quirk_brcm_570x_limit_vpd(struct pci_dev *dev)
++static void quirk_brcm_570x_limit_vpd(struct pci_dev *dev)
+ {
+ 	/*
+ 	 * Only disable the VPD capability for 5706, 5706S, 5708,
+@@ -2091,7 +2091,7 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_BROADCOM,
+  * the DRBs - this is where we expose device 6.
+  * http://www.x86-secret.com/articles/tweak/pat/patsecrets-2.htm
+  */
+-static void __devinit quirk_unhide_mch_dev6(struct pci_dev *dev)
++static void quirk_unhide_mch_dev6(struct pci_dev *dev)
+ {
+ 	u8 reg;
+ 
+@@ -2115,7 +2115,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82875_HB,
+  * supports link speed auto negotiation, but falsely sets
+  * the link speed to 5GT/s.
+  */
+-static void __devinit quirk_tile_plx_gen1(struct pci_dev *dev)
++static void quirk_tile_plx_gen1(struct pci_dev *dev)
+ {
+ 	if (tile_plx_gen1) {
+ 		pci_write_config_dword(dev, 0x98, 0x1);
+@@ -2132,7 +2132,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8624, quirk_tile_plx_gen1);
+  * aware of it.  Instead of setting the flag on all busses in the
+  * machine, simply disable MSI globally.
+  */
+-static void __devinit quirk_disable_all_msi(struct pci_dev *dev)
++static void quirk_disable_all_msi(struct pci_dev *dev)
+ {
+ 	pci_no_msi();
+ 	dev_warn(&dev->dev, "MSI quirk detected; MSI disabled\n");
+@@ -2146,7 +2146,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3364, quirk_disab
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8380_0, quirk_disable_all_msi);
+ 
+ /* Disable MSI on chipsets that are known to not support it */
+-static void __devinit quirk_disable_msi(struct pci_dev *dev)
++static void quirk_disable_msi(struct pci_dev *dev)
+ {
+ 	if (dev->subordinate) {
+ 		dev_warn(&dev->dev, "MSI quirk detected; "
+@@ -2164,7 +2164,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x5a3f, quirk_disable_msi);
+  * we use the possible vendor/device IDs of the host bridge for the
+  * declared quirk, and search for the APC bridge by slot number.
+  */
+-static void __devinit quirk_amd_780_apc_msi(struct pci_dev *host_bridge)
++static void quirk_amd_780_apc_msi(struct pci_dev *host_bridge)
+ {
+ 	struct pci_dev *apc_bridge;
+ 
+@@ -2272,7 +2272,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE,
+  * for the MCP55 NIC. It is not yet determined whether the msi problem
+  * also affects other devices. As for now, turn off msi for this device.
+  */
+-static void __devinit nvenet_msi_disable(struct pci_dev *dev)
++static void nvenet_msi_disable(struct pci_dev *dev)
+ {
+ 	const char *board_name = dmi_get_system_info(DMI_BOARD_NAME);
+ 
+@@ -2298,7 +2298,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA,
+  * we have it set correctly.
+  * Note this is an undocumented register.
+  */
+-static void __devinit nvbridge_check_legacy_irq_routing(struct pci_dev *dev)
++static void nvbridge_check_legacy_irq_routing(struct pci_dev *dev)
+ {
+ 	u32 cfg;
+ 
+@@ -2534,11 +2534,11 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, nv_msi_ht_cap_q
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_ANY_ID, nv_msi_ht_cap_quirk_all);
+ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AL, PCI_ANY_ID, nv_msi_ht_cap_quirk_all);
+ 
+-static void __devinit quirk_msi_intx_disable_bug(struct pci_dev *dev)
++static void quirk_msi_intx_disable_bug(struct pci_dev *dev)
+ {
+ 	dev->dev_flags |= PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG;
+ }
+-static void __devinit quirk_msi_intx_disable_ati_bug(struct pci_dev *dev)
++static void quirk_msi_intx_disable_ati_bug(struct pci_dev *dev)
+ {
+ 	struct pci_dev *p;
+ 
+@@ -2612,7 +2612,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x1083,
+  * kernel fails to allocate resources when hotplug device is 
+  * inserted and PCI bus is rescanned.
+  */
+-static void __devinit quirk_hotplug_bridge(struct pci_dev *dev)
++static void quirk_hotplug_bridge(struct pci_dev *dev)
+ {
+ 	dev->is_hotplug_bridge = 1;
+ }
+@@ -2752,7 +2752,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x342e, vtd_mask_spec_errors);
+ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x3c28, vtd_mask_spec_errors);
+ #endif
+ 
+-static void __devinit fixup_ti816x_class(struct pci_dev* dev)
++static void fixup_ti816x_class(struct pci_dev *dev)
+ {
+ 	/* TI 816x devices do not have class code set when in PCIe boot mode */
+ 	dev_info(&dev->dev, "Setting PCI class for 816x PCIe device\n");
+@@ -2764,7 +2764,7 @@ DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_TI, 0xb800,
+ /* Some PCIe devices do not work reliably with the claimed maximum
+  * payload size supported.
+  */
+-static void __devinit fixup_mpss_256(struct pci_dev *dev)
++static void fixup_mpss_256(struct pci_dev *dev)
+ {
+ 	dev->pcie_mpss = 1; /* 256 bytes */
+ }
+@@ -2782,7 +2782,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SOLARFLARE,
+  * coalescing must be disabled.  Unfortunately, it cannot be re-enabled because
+  * it is possible to hotplug a device with MPS of 256B.
+  */
+-static void __devinit quirk_intel_mc_errata(struct pci_dev *dev)
++static void quirk_intel_mc_errata(struct pci_dev *dev)
+ {
+ 	int err;
+ 	u16 rcc;
+@@ -2888,7 +2888,7 @@ static void fixup_debug_report(struct pci_dev *dev, ktime_t calltime,
+  * This resolves crashes often seen on monitor unplug.
+  */
+ #define I915_DEIER_REG 0x4400c
+-static void __devinit disable_igfx_irq(struct pci_dev *dev)
++static void disable_igfx_irq(struct pci_dev *dev)
+ {
+ 	void __iomem *regs = pci_iomap(dev, 0, 0);
+ 	if (regs == NULL) {
+@@ -2914,7 +2914,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq);
+  * PCI_COMMAND_INTX_DISABLE works though they actually do not properly
+  * support this feature.
+  */
+-static void __devinit quirk_broken_intx_masking(struct pci_dev *dev)
++static void quirk_broken_intx_masking(struct pci_dev *dev)
+ {
+ 	dev->broken_intx_masking = 1;
+ }
+diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
+index 0aab85a51559..db542f4196a4 100644
+--- a/drivers/pci/xen-pcifront.c
++++ b/drivers/pci/xen-pcifront.c
+@@ -412,7 +412,7 @@ static int pcifront_claim_resource(struct pci_dev *dev, void *data)
+ 	return 0;
+ }
+ 
+-static int __devinit pcifront_scan_bus(struct pcifront_device *pdev,
++static int pcifront_scan_bus(struct pcifront_device *pdev,
+ 				unsigned int domain, unsigned int bus,
+ 				struct pci_bus *b)
+ {
+@@ -441,7 +441,7 @@ static int __devinit pcifront_scan_bus(struct pcifront_device *pdev,
+ 	return 0;
+ }
+ 
+-static int __devinit pcifront_scan_root(struct pcifront_device *pdev,
++static int pcifront_scan_root(struct pcifront_device *pdev,
+ 				 unsigned int domain, unsigned int bus)
+ {
+ 	struct pci_bus *b;
+@@ -503,7 +503,7 @@ static int __devinit pcifront_scan_root(struct pcifront_device *pdev,
+ 	return err;
+ }
+ 
+-static int __devinit pcifront_rescan_root(struct pcifront_device *pdev,
++static int pcifront_rescan_root(struct pcifront_device *pdev,
+ 				   unsigned int domain, unsigned int bus)
+ {
+ 	int err;
+@@ -834,7 +834,7 @@ static int pcifront_publish_info(struct pcifront_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devinit pcifront_try_connect(struct pcifront_device *pdev)
++static int pcifront_try_connect(struct pcifront_device *pdev)
+ {
+ 	int err = -EFAULT;
+ 	int i, num_roots, len;
+@@ -924,7 +924,7 @@ static int pcifront_try_disconnect(struct pcifront_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devinit pcifront_attach_devices(struct pcifront_device *pdev)
++static int pcifront_attach_devices(struct pcifront_device *pdev)
+ {
+ 	int err = -EFAULT;
+ 	int i, num_roots, len;
+diff --git a/include/linux/pci.h b/include/linux/pci.h
+index 699e9a920eca..d03d2463efac 100644
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -588,7 +588,7 @@ struct pci_driver {
+  * in a generic manner.
+  */
+ #define DEFINE_PCI_DEVICE_TABLE(_table) \
+-	const struct pci_device_id _table[] __devinitconst
++	const struct pci_device_id _table[]
+ 
+ /**
+  * PCI_DEVICE - macro used to describe a specific pci device
+@@ -686,7 +686,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
+ int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
+ int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
+ void pci_bus_release_busn_res(struct pci_bus *b);
+-struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
++struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
+ 					     struct pci_ops *ops, void *sysdata,
+ 					     struct list_head *resources);
+ struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
+@@ -1578,7 +1578,7 @@ extern int pci_pci_problems;
+ 
+ extern unsigned long pci_cardbus_io_size;
+ extern unsigned long pci_cardbus_mem_size;
+-extern u8 __devinitdata pci_dfl_cache_line_size;
++extern u8 pci_dfl_cache_line_size;
+ extern u8 pci_cache_line_size;
+ 
+ extern unsigned long pci_hotplug_io_size;

commit 7dc30303342562685392c8c7aa5194e98fd27625
+Author: Bill Pemberton 
+Date:   Wed Nov 21 15:34:59 2012 -0500
+
+    PCI: Always build setup-bus when PCI is enabled
+    
+    CONFIG_HOTPLUG is being removed so setup-bus always needs to be built
+    as part of PCI.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Bjorn Helgaas 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
+index 36f119d9c342..0c3efcffa83b 100644
+--- a/drivers/pci/Makefile
++++ b/drivers/pci/Makefile
+@@ -4,7 +4,7 @@
+ 
+ obj-y		+= access.o bus.o probe.o host-bridge.o remove.o pci.o \
+ 			pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \
+-			irq.o vpd.o
++			irq.o vpd.o setup-bus.o
+ obj-$(CONFIG_PROC_FS) += proc.o
+ obj-$(CONFIG_SYSFS) += slot.o
+ 
+@@ -58,9 +58,6 @@ obj-$(CONFIG_ACPI)    += pci-acpi.o
+ # SMBIOS provided firmware instance and labels
+ obj-$(CONFIG_PCI_LABEL) += pci-label.o
+ 
+-# Cardbus & CompactPCI use setup-bus
+-obj-$(CONFIG_HOTPLUG) += setup-bus.o
+-
+ obj-$(CONFIG_PCI_SYSCALL) += syscall.o
+ 
+ obj-$(CONFIG_PCI_STUB) += pci-stub.o

commit 8ccc9aa17a0ccfabf3b2eb31243c3204f81166f6
+Author: Bill Pemberton 
+Date:   Wed Nov 21 15:34:58 2012 -0500
+
+    PCI: Move pci_uevent into pci-driver.c
+    
+    With the demise of CONFIG_HOTPLUG as an option, the pci_uevent
+    function located in hotplug.c will now always be used and doesn't need
+    special treatment in the Makefile.  Move pci_uevent into pci-driver.c
+    and remove hotplug.c
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Bjorn Helgaas 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
+index 8d688b260e28..36f119d9c342 100644
+--- a/drivers/pci/Makefile
++++ b/drivers/pci/Makefile
+@@ -15,8 +15,6 @@ obj-$(CONFIG_PCIEPORTBUS) += pcie/
+ 
+ obj-$(CONFIG_PCI_IOAPIC) += ioapic.o
+ 
+-obj-$(CONFIG_HOTPLUG) += hotplug.o
+-
+ # Build the PCI Hotplug drivers if we were asked to
+ obj-$(CONFIG_HOTPLUG_PCI) += hotplug/
+ ifdef CONFIG_HOTPLUG_PCI
+diff --git a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c
+deleted file mode 100644
+index 2b5352a7dffc..000000000000
+--- a/drivers/pci/hotplug.c
++++ /dev/null
+@@ -1,37 +0,0 @@
+-#include 
+-#include 
+-#include 
+-#include "pci.h"
+-
+-int pci_uevent(struct device *dev, struct kobj_uevent_env *env)
+-{
+-	struct pci_dev *pdev;
+-
+-	if (!dev)
+-		return -ENODEV;
+-
+-	pdev = to_pci_dev(dev);
+-	if (!pdev)
+-		return -ENODEV;
+-
+-	if (add_uevent_var(env, "PCI_CLASS=%04X", pdev->class))
+-		return -ENOMEM;
+-
+-	if (add_uevent_var(env, "PCI_ID=%04X:%04X", pdev->vendor, pdev->device))
+-		return -ENOMEM;
+-
+-	if (add_uevent_var(env, "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
+-			   pdev->subsystem_device))
+-		return -ENOMEM;
+-
+-	if (add_uevent_var(env, "PCI_SLOT_NAME=%s", pci_name(pdev)))
+-		return -ENOMEM;
+-
+-	if (add_uevent_var(env, "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
+-			   pdev->vendor, pdev->device,
+-			   pdev->subsystem_vendor, pdev->subsystem_device,
+-			   (u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
+-			   (u8)(pdev->class)))
+-		return -ENOMEM;
+-	return 0;
+-}
+diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
+index 8919801cb27e..1dc78c5cabf8 100644
+--- a/drivers/pci/pci-driver.c
++++ b/drivers/pci/pci-driver.c
+@@ -1215,6 +1215,39 @@ void pci_dev_put(struct pci_dev *dev)
+ 		put_device(&dev->dev);
+ }
+ 
++static int pci_uevent(struct device *dev, struct kobj_uevent_env *env)
++{
++	struct pci_dev *pdev;
++
++	if (!dev)
++		return -ENODEV;
++
++	pdev = to_pci_dev(dev);
++	if (!pdev)
++		return -ENODEV;
++
++	if (add_uevent_var(env, "PCI_CLASS=%04X", pdev->class))
++		return -ENOMEM;
++
++	if (add_uevent_var(env, "PCI_ID=%04X:%04X", pdev->vendor, pdev->device))
++		return -ENOMEM;
++
++	if (add_uevent_var(env, "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
++			   pdev->subsystem_device))
++		return -ENOMEM;
++
++	if (add_uevent_var(env, "PCI_SLOT_NAME=%s", pci_name(pdev)))
++		return -ENOMEM;
++
++	if (add_uevent_var(env, "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
++			   pdev->vendor, pdev->device,
++			   pdev->subsystem_vendor, pdev->subsystem_device,
++			   (u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
++			   (u8)(pdev->class)))
++		return -ENOMEM;
++	return 0;
++}
++
+ struct bus_type pci_bus_type = {
+ 	.name		= "pci",
+ 	.match		= pci_bus_match,
+diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
+index 6e993af4d30b..e253881c4275 100644
+--- a/drivers/pci/pci.h
++++ b/drivers/pci/pci.h
+@@ -8,7 +8,6 @@
+ 
+ /* Functions internal to the PCI core code */
+ 
+-extern int pci_uevent(struct device *dev, struct kobj_uevent_env *env);
+ extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
+ extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
+ #if !defined(CONFIG_DMI) && !defined(CONFIG_ACPI)

commit b40b97ae736cad3084b13d2969b10c474572de89
+Author: Bill Pemberton 
+Date:   Wed Nov 21 15:34:57 2012 -0500
+
+    PCI: Remove CONFIG_HOTPLUG ifdefs
+    
+    Remove conditional code based on CONFIG_HOTPLUG being false.  It's
+    always on now in preparation of it going away as an option.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Bjorn Helgaas 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
+index 6c94fc9489e7..8919801cb27e 100644
+--- a/drivers/pci/pci-driver.c
++++ b/drivers/pci/pci-driver.c
+@@ -89,10 +89,6 @@ static void pci_free_dynids(struct pci_driver *drv)
+ 	spin_unlock(&drv->dynids.lock);
+ }
+ 
+-/*
+- * Dynamic device ID manipulation via sysfs is disabled for !CONFIG_HOTPLUG
+- */
+-#ifdef CONFIG_HOTPLUG
+ /**
+  * store_new_id - sysfs frontend to pci_add_dynid()
+  * @driver: target device driver
+@@ -191,10 +187,6 @@ static struct driver_attribute pci_drv_attrs[] = {
+ 	__ATTR_NULL,
+ };
+ 
+-#else
+-#define pci_drv_attrs	NULL
+-#endif /* CONFIG_HOTPLUG */
+-
+ /**
+  * pci_match_id - See if a pci device matches a given pci_id table
+  * @ids: array of PCI device id structures to search in
+@@ -1223,13 +1215,6 @@ void pci_dev_put(struct pci_dev *dev)
+ 		put_device(&dev->dev);
+ }
+ 
+-#ifndef CONFIG_HOTPLUG
+-int pci_uevent(struct device *dev, struct kobj_uevent_env *env)
+-{
+-	return -ENODEV;
+-}
+-#endif
+-
+ struct bus_type pci_bus_type = {
+ 	.name		= "pci",
+ 	.match		= pci_bus_match,
+diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
+index f39378d9da15..68d56f02e721 100644
+--- a/drivers/pci/pci-sysfs.c
++++ b/drivers/pci/pci-sysfs.c
+@@ -284,7 +284,6 @@ msi_bus_store(struct device *dev, struct device_attribute *attr,
+ 	return count;
+ }
+ 
+-#ifdef CONFIG_HOTPLUG
+ static DEFINE_MUTEX(pci_remove_rescan_mutex);
+ static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf,
+ 				size_t count)
+@@ -377,8 +376,6 @@ dev_bus_rescan_store(struct device *dev, struct device_attribute *attr,
+ 	return count;
+ }
+ 
+-#endif
+-
+ #if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI)
+ static ssize_t d3cold_allowed_store(struct device *dev,
+ 				    struct device_attribute *attr,
+@@ -424,10 +421,8 @@ struct device_attribute pci_dev_attrs[] = {
+ 	__ATTR(broken_parity_status,(S_IRUGO|S_IWUSR),
+ 		broken_parity_status_show,broken_parity_status_store),
+ 	__ATTR(msi_bus, 0644, msi_bus_show, msi_bus_store),
+-#ifdef CONFIG_HOTPLUG
+ 	__ATTR(remove, (S_IWUSR|S_IWGRP), NULL, remove_store),
+ 	__ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_rescan_store),
+-#endif
+ #if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI)
+ 	__ATTR(d3cold_allowed, 0644, d3cold_allowed_show, d3cold_allowed_store),
+ #endif
+@@ -435,9 +430,7 @@ struct device_attribute pci_dev_attrs[] = {
+ };
+ 
+ struct device_attribute pcibus_dev_attrs[] = {
+-#ifdef CONFIG_HOTPLUG
+ 	__ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_bus_rescan_store),
+-#endif
+ 	__ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpumaskaffinity, NULL),
+ 	__ATTR(cpulistaffinity, S_IRUGO, pci_bus_show_cpulistaffinity, NULL),
+ 	__ATTR_NULL,
+diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
+index fd92aab9904b..6e993af4d30b 100644
+--- a/drivers/pci/pci.h
++++ b/drivers/pci/pci.h
+@@ -159,11 +159,7 @@ static inline int pci_no_d1d2(struct pci_dev *dev)
+ }
+ extern struct device_attribute pci_dev_attrs[];
+ extern struct device_attribute pcibus_dev_attrs[];
+-#ifdef CONFIG_HOTPLUG
+ extern struct bus_attribute pci_bus_attrs[];
+-#else
+-#define pci_bus_attrs	NULL
+-#endif
+ 
+ 
+ /**
+diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
+index ec909afa90b6..034cb1c73092 100644
+--- a/drivers/pci/probe.c
++++ b/drivers/pci/probe.c
+@@ -1864,7 +1864,6 @@ struct pci_bus * __devinit pci_scan_bus(int bus, struct pci_ops *ops,
+ }
+ EXPORT_SYMBOL(pci_scan_bus);
+ 
+-#ifdef CONFIG_HOTPLUG
+ /**
+  * pci_rescan_bus_bridge_resize - scan a PCI bus for devices.
+  * @bridge: PCI bridge for the bus to scan
+@@ -1894,7 +1893,6 @@ EXPORT_SYMBOL(pci_add_new_bus);
+ EXPORT_SYMBOL(pci_scan_slot);
+ EXPORT_SYMBOL(pci_scan_bridge);
+ EXPORT_SYMBOL_GPL(pci_scan_child_bus);
+-#endif
+ 
+ static int __init pci_sort_bf_cmp(const struct device *d_a, const struct device *d_b)
+ {
+diff --git a/include/linux/pci.h b/include/linux/pci.h
+index ee2179546c63..699e9a920eca 100644
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -941,10 +941,8 @@ void set_pcie_hotplug_bridge(struct pci_dev *pdev);
+ 
+ /* Functions for PCI Hotplug drivers to use */
+ int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap);
+-#ifdef CONFIG_HOTPLUG
+ unsigned int pci_rescan_bus_bridge_resize(struct pci_dev *bridge);
+ unsigned int pci_rescan_bus(struct pci_bus *bus);
+-#endif
+ 
+ /* Vital product data routines */
+ ssize_t pci_read_vpd(struct pci_dev *dev, loff_t pos, size_t count, void *buf);

commit 8c610c120fb6ea279e8d01ce7aa555da29e59374
+Author: Bill Pemberton 
+Date:   Wed Nov 21 15:34:56 2012 -0500
+
+    unicore32/PCI: Remove CONFIG_HOTPLUG ifdefs
+    
+    Remove conditional code based on CONFIG_HOTPLUG being false.  It's
+    always on now in preparation of it going away as an option.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Guan Xuetao 
+    Acked-by: Bjorn Helgaas 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c
+index b0056f68d321..7c4359240b81 100644
+--- a/arch/unicore32/kernel/pci.c
++++ b/arch/unicore32/kernel/pci.c
+@@ -250,9 +250,7 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+ 	printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n",
+ 		bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis");
+ }
+-#ifdef CONFIG_HOTPLUG
+ EXPORT_SYMBOL(pcibios_fixup_bus);
+-#endif
+ 
+ static int __init pci_common_init(void)
+ {

commit 48bee693abca6e4f0f4d1f393f44b4be128b0a39
+Author: Bill Pemberton 
+Date:   Wed Nov 21 15:34:55 2012 -0500
+
+    sh/PCI: Remove CONFIG_HOTPLUG ifdefs
+    
+    Remove conditional code based on CONFIG_HOTPLUG being false.  It's
+    always on now in preparation of it going away as an option.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Paul Mundt 
+    Acked-by: Bjorn Helgaas 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
+index a7e078f2e2e4..81e5dafed3e4 100644
+--- a/arch/sh/drivers/pci/pci.c
++++ b/arch/sh/drivers/pci/pci.c
+@@ -319,7 +319,5 @@ EXPORT_SYMBOL(pci_iounmap);
+ 
+ #endif /* CONFIG_GENERIC_IOMAP */
+ 
+-#ifdef CONFIG_HOTPLUG
+ EXPORT_SYMBOL(PCIBIOS_MIN_IO);
+ EXPORT_SYMBOL(PCIBIOS_MIN_MEM);
+-#endif

commit e47034c7a1522b9572c76bb1d003d56d9f3fcb31
+Author: Bill Pemberton 
+Date:   Wed Nov 21 15:34:54 2012 -0500
+
+    powerpc/PCI: Remove CONFIG_HOTPLUG ifdefs
+    
+    Remove conditional code based on CONFIG_HOTPLUG being false.  It's
+    always on now in preparation of it going away as an option.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Benjamin Herrenschmidt 
+    Cc: Paul Mackerras 
+    Cc: Grant Likely 
+    Cc: Rob Herring 
+    Acked-by: Bjorn Helgaas 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
+index 7f94f760dd0c..abc0d0856994 100644
+--- a/arch/powerpc/kernel/pci-common.c
++++ b/arch/powerpc/kernel/pci-common.c
+@@ -1428,8 +1428,6 @@ void __init pcibios_resource_survey(void)
+ 		ppc_md.pcibios_fixup();
+ }
+ 
+-#ifdef CONFIG_HOTPLUG
+-
+ /* This is used by the PCI hotplug driver to allocate resource
+  * of newly plugged busses. We can try to consolidate with the
+  * rest of the code later, for now, keep it as-is as our main
+@@ -1488,8 +1486,6 @@ void pcibios_finish_adding_to_bus(struct pci_bus *bus)
+ }
+ EXPORT_SYMBOL_GPL(pcibios_finish_adding_to_bus);
+ 
+-#endif /* CONFIG_HOTPLUG */
+-
+ int pcibios_enable_device(struct pci_dev *dev, int mask)
+ {
+ 	if (ppc_md.pcibios_enable_device_hook)
+diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
+index 4ff190ff24a0..2cbe6768fddd 100644
+--- a/arch/powerpc/kernel/pci_64.c
++++ b/arch/powerpc/kernel/pci_64.c
+@@ -74,8 +74,6 @@ static int __init pcibios_init(void)
+ 
+ subsys_initcall(pcibios_init);
+ 
+-#ifdef CONFIG_HOTPLUG
+-
+ int pcibios_unmap_io_space(struct pci_bus *bus)
+ {
+ 	struct pci_controller *hose;
+@@ -124,8 +122,6 @@ int pcibios_unmap_io_space(struct pci_bus *bus)
+ }
+ EXPORT_SYMBOL_GPL(pcibios_unmap_io_space);
+ 
+-#endif /* CONFIG_HOTPLUG */
+-
+ static int __devinit pcibios_map_phb_io_space(struct pci_controller *hose)
+ {
+ 	struct vm_struct *area;

commit 0a6f19db99c4833ad01eccbee51812b8000d63ea
+Author: Bill Pemberton 
+Date:   Wed Nov 21 15:34:53 2012 -0500
+
+    mips/PCI: Remove CONFIG_HOTPLUG ifdefs
+    
+    Remove conditional code based on CONFIG_HOTPLUG being false.  It's
+    always on now in preparation of it going away as an option.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Ralf Baechle 
+    Cc: Grant Likely 
+    Cc: Rob Herring 
+    Acked-by: Bjorn Helgaas 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
+index 04e35bcde07c..4040416e0603 100644
+--- a/arch/mips/pci/pci.c
++++ b/arch/mips/pci/pci.c
+@@ -313,10 +313,8 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+ 	}
+ }
+ 
+-#ifdef CONFIG_HOTPLUG
+ EXPORT_SYMBOL(PCIBIOS_MIN_IO);
+ EXPORT_SYMBOL(PCIBIOS_MIN_MEM);
+-#endif
+ 
+ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+ 			enum pci_mmap_state mmap_state, int write_combine)

commit d5174d2d2a775998972c04f9875daf04fb156180
+Author: Bill Pemberton 
+Date:   Wed Nov 21 15:34:52 2012 -0500
+
+    microblaze/PCI: Remove CONFIG_HOTPLUG ifdefs
+    
+    Remove conditional code based on CONFIG_HOTPLUG being false.  It's
+    always on now in preparation of it going away as an option.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Michal Simek 
+    Cc: Grant Likely 
+    Cc: Rob Herring 
+    Acked-by: Bjorn Helgaas 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
+index 4dbb5055d04b..a1c5b996d66d 100644
+--- a/arch/microblaze/pci/pci-common.c
++++ b/arch/microblaze/pci/pci-common.c
+@@ -1346,8 +1346,6 @@ void __init pcibios_resource_survey(void)
+ 	pci_assign_unassigned_resources();
+ }
+ 
+-#ifdef CONFIG_HOTPLUG
+-
+ /* This is used by the PCI hotplug driver to allocate resource
+  * of newly plugged busses. We can try to consolidate with the
+  * rest of the code later, for now, keep it as-is as our main
+@@ -1407,8 +1405,6 @@ void pcibios_finish_adding_to_bus(struct pci_bus *bus)
+ }
+ EXPORT_SYMBOL_GPL(pcibios_finish_adding_to_bus);
+ 
+-#endif /* CONFIG_HOTPLUG */
+-
+ int pcibios_enable_device(struct pci_dev *dev, int mask)
+ {
+ 	return pci_enable_resources(dev, mask);

commit 463a1f8b3ceebe990ca9a8c7cc2e51ee42cb48eb
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:55 2012 -0500
+
+    dma: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Li Yang 
+    Cc: Zhang Wei 
+    Cc: Barry Song 
+    Acked-by: Viresh Kumar 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
+index 3b21818719d2..8f0b111af4de 100644
+--- a/drivers/dma/dw_dmac.c
++++ b/drivers/dma/dw_dmac.c
+@@ -1462,7 +1462,7 @@ static void dw_dma_off(struct dw_dma *dw)
+ 		dw->chan[i].initialized = false;
+ }
+ 
+-static int __devinit dw_probe(struct platform_device *pdev)
++static int dw_probe(struct platform_device *pdev)
+ {
+ 	struct dw_dma_platform_data *pdata;
+ 	struct resource		*io;
+diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
+index 5e5cce4ec720..232b4583ae93 100644
+--- a/drivers/dma/edma.c
++++ b/drivers/dma/edma.c
+@@ -545,7 +545,7 @@ static void edma_dma_init(struct edma_cc *ecc, struct dma_device *dma,
+ 	INIT_LIST_HEAD(&dma->channels);
+ }
+ 
+-static int __devinit edma_probe(struct platform_device *pdev)
++static int edma_probe(struct platform_device *pdev)
+ {
+ 	struct edma_cc *ecc;
+ 	int ret;
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index 094437b9d823..4fc2980556ad 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -1221,7 +1221,7 @@ static int fsldma_request_irqs(struct fsldma_device *fdev)
+ /* OpenFirmware Subsystem                                                     */
+ /*----------------------------------------------------------------------------*/
+ 
+-static int __devinit fsl_dma_chan_probe(struct fsldma_device *fdev,
++static int fsl_dma_chan_probe(struct fsldma_device *fdev,
+ 	struct device_node *node, u32 feature, const char *compatible)
+ {
+ 	struct fsldma_chan *chan;
+@@ -1324,7 +1324,7 @@ static void fsl_dma_chan_remove(struct fsldma_chan *chan)
+ 	kfree(chan);
+ }
+ 
+-static int __devinit fsldma_of_probe(struct platform_device *op)
++static int fsldma_of_probe(struct platform_device *op)
+ {
+ 	struct fsldma_device *fdev;
+ 	struct device_node *child;
+diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c
+index dffdeffe2c4e..bc764afacd9b 100644
+--- a/drivers/dma/intel_mid_dma.c
++++ b/drivers/dma/intel_mid_dma.c
+@@ -1225,7 +1225,7 @@ static void middma_shutdown(struct pci_dev *pdev)
+  * Initialize the PCI device, map BARs, query driver data.
+  * Call setup_dma to complete contoller and chan initilzation
+  */
+-static int __devinit intel_mid_dma_probe(struct pci_dev *pdev,
++static int intel_mid_dma_probe(struct pci_dev *pdev,
+ 					const struct pci_device_id *id)
+ {
+ 	struct middma_device *device;
+diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
+index f4a8668b3467..9072e173b860 100644
+--- a/drivers/dma/iop-adma.c
++++ b/drivers/dma/iop-adma.c
+@@ -968,7 +968,7 @@ static void iop_adma_issue_pending(struct dma_chan *chan)
+  */
+ #define IOP_ADMA_TEST_SIZE 2000
+ 
+-static int __devinit iop_adma_memcpy_self_test(struct iop_adma_device *device)
++static int iop_adma_memcpy_self_test(struct iop_adma_device *device)
+ {
+ 	int i;
+ 	void *src, *dest;
+@@ -1042,7 +1042,7 @@ static int __devinit iop_adma_memcpy_self_test(struct iop_adma_device *device)
+ }
+ 
+ #define IOP_ADMA_NUM_SRC_TEST 4 /* must be <= 15 */
+-static int __devinit
++static int
+ iop_adma_xor_val_self_test(struct iop_adma_device *device)
+ {
+ 	int i, src_idx;
+@@ -1243,7 +1243,7 @@ iop_adma_xor_val_self_test(struct iop_adma_device *device)
+ }
+ 
+ #ifdef CONFIG_RAID6_PQ
+-static int __devinit
++static int
+ iop_adma_pq_zero_sum_self_test(struct iop_adma_device *device)
+ {
+ 	/* combined sources, software pq results, and extra hw pq results */
+@@ -1429,7 +1429,7 @@ static int __devexit iop_adma_remove(struct platform_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devinit iop_adma_probe(struct platform_device *pdev)
++static int iop_adma_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res;
+ 	int ret = 0, i;
+diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c
+index 4777986adbaf..13bdf4a7e1ec 100644
+--- a/drivers/dma/mmp_pdma.c
++++ b/drivers/dma/mmp_pdma.c
+@@ -720,7 +720,7 @@ static int __devexit mmp_pdma_remove(struct platform_device *op)
+ 	return 0;
+ }
+ 
+-static int __devinit mmp_pdma_chan_init(struct mmp_pdma_device *pdev,
++static int mmp_pdma_chan_init(struct mmp_pdma_device *pdev,
+ 							int idx, int irq)
+ {
+ 	struct mmp_pdma_phy *phy  = &pdev->phy[idx];
+@@ -764,7 +764,7 @@ static struct of_device_id mmp_pdma_dt_ids[] = {
+ };
+ MODULE_DEVICE_TABLE(of, mmp_pdma_dt_ids);
+ 
+-static int __devinit mmp_pdma_probe(struct platform_device *op)
++static int mmp_pdma_probe(struct platform_device *op)
+ {
+ 	struct mmp_pdma_device *pdev;
+ 	const struct of_device_id *of_id;
+diff --git a/drivers/dma/mmp_tdma.c b/drivers/dma/mmp_tdma.c
+index 7d7fc6b19261..323821c0c095 100644
+--- a/drivers/dma/mmp_tdma.c
++++ b/drivers/dma/mmp_tdma.c
+@@ -475,7 +475,7 @@ static int __devexit mmp_tdma_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devinit mmp_tdma_chan_init(struct mmp_tdma_device *tdev,
++static int mmp_tdma_chan_init(struct mmp_tdma_device *tdev,
+ 						int idx, int irq, int type)
+ {
+ 	struct mmp_tdma_chan *tdmac;
+@@ -515,7 +515,7 @@ static struct of_device_id mmp_tdma_dt_ids[] = {
+ };
+ MODULE_DEVICE_TABLE(of, mmp_tdma_dt_ids);
+ 
+-static int __devinit mmp_tdma_probe(struct platform_device *pdev)
++static int mmp_tdma_probe(struct platform_device *pdev)
+ {
+ 	enum mmp_tdma_type type;
+ 	const struct of_device_id *of_id;
+diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
+index 4b8754b9a2df..2cd024a91d40 100644
+--- a/drivers/dma/mpc512x_dma.c
++++ b/drivers/dma/mpc512x_dma.c
+@@ -641,7 +641,7 @@ mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src,
+ 	return &mdesc->desc;
+ }
+ 
+-static int __devinit mpc_dma_probe(struct platform_device *op)
++static int mpc_dma_probe(struct platform_device *op)
+ {
+ 	struct device_node *dn = op->dev.of_node;
+ 	struct device *dev = &op->dev;
+diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
+index 2e9ad2d9fe44..d12ad00da4cb 100644
+--- a/drivers/dma/mv_xor.c
++++ b/drivers/dma/mv_xor.c
+@@ -901,7 +901,7 @@ static void mv_xor_issue_pending(struct dma_chan *chan)
+  */
+ #define MV_XOR_TEST_SIZE 2000
+ 
+-static int __devinit mv_xor_memcpy_self_test(struct mv_xor_device *device)
++static int mv_xor_memcpy_self_test(struct mv_xor_device *device)
+ {
+ 	int i;
+ 	void *src, *dest;
+@@ -975,7 +975,7 @@ static int __devinit mv_xor_memcpy_self_test(struct mv_xor_device *device)
+ }
+ 
+ #define MV_XOR_NUM_SRC_TEST 4 /* must be <= 15 */
+-static int __devinit
++static int
+ mv_xor_xor_self_test(struct mv_xor_device *device)
+ {
+ 	int i, src_idx;
+@@ -1100,7 +1100,7 @@ static int __devexit mv_xor_remove(struct platform_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devinit mv_xor_probe(struct platform_device *pdev)
++static int mv_xor_probe(struct platform_device *pdev)
+ {
+ 	int ret = 0;
+ 	int irq;
+diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c
+index f7f1c1947089..eca1c4ddf039 100644
+--- a/drivers/dma/pch_dma.c
++++ b/drivers/dma/pch_dma.c
+@@ -843,7 +843,7 @@ static int pch_dma_resume(struct pci_dev *pdev)
+ }
+ #endif
+ 
+-static int __devinit pch_dma_probe(struct pci_dev *pdev,
++static int pch_dma_probe(struct pci_dev *pdev,
+ 				   const struct pci_device_id *id)
+ {
+ 	struct pch_dma *pd;
+diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
+index 665668b6f2b1..95555f37ea6d 100644
+--- a/drivers/dma/pl330.c
++++ b/drivers/dma/pl330.c
+@@ -2851,7 +2851,7 @@ static irqreturn_t pl330_irq_handler(int irq, void *data)
+ 		return IRQ_NONE;
+ }
+ 
+-static int __devinit
++static int
+ pl330_probe(struct amba_device *adev, const struct amba_id *id)
+ {
+ 	struct dma_pl330_platdata *pdat;
+diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c
+index 5c6717c48f48..b94afc339e7f 100644
+--- a/drivers/dma/ppc4xx/adma.c
++++ b/drivers/dma/ppc4xx/adma.c
+@@ -4361,7 +4361,7 @@ static void ppc440spe_adma_release_irqs(struct ppc440spe_adma_device *adev,
+ /**
+  * ppc440spe_adma_probe - probe the asynch device
+  */
+-static int __devinit ppc440spe_adma_probe(struct platform_device *ofdev)
++static int ppc440spe_adma_probe(struct platform_device *ofdev)
+ {
+ 	struct device_node *np = ofdev->dev.of_node;
+ 	struct resource res;
+diff --git a/drivers/dma/sa11x0-dma.c b/drivers/dma/sa11x0-dma.c
+index 1255d9b2c3dd..2ad628df8223 100644
+--- a/drivers/dma/sa11x0-dma.c
++++ b/drivers/dma/sa11x0-dma.c
+@@ -826,7 +826,7 @@ static const struct sa11x0_dma_channel_desc chan_desc[] = {
+ 	CD(Ser4SSPRc, DDAR_RW),
+ };
+ 
+-static int __devinit sa11x0_dma_init_dmadev(struct dma_device *dmadev,
++static int sa11x0_dma_init_dmadev(struct dma_device *dmadev,
+ 	struct device *dev)
+ {
+ 	unsigned i;
+@@ -891,7 +891,7 @@ static void sa11x0_dma_free_channels(struct dma_device *dmadev)
+ 	}
+ }
+ 
+-static int __devinit sa11x0_dma_probe(struct platform_device *pdev)
++static int sa11x0_dma_probe(struct platform_device *pdev)
+ {
+ 	struct sa11x0_dma_dev *d;
+ 	struct resource *res;
+diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c
+index 7dcf4e073186..8201bb4e0cd7 100644
+--- a/drivers/dma/sh/shdma.c
++++ b/drivers/dma/sh/shdma.c
+@@ -483,7 +483,7 @@ static struct notifier_block sh_dmae_nmi_notifier __read_mostly = {
+ 	.priority	= 1,
+ };
+ 
+-static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id,
++static int sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id,
+ 					int irq, unsigned long flags)
+ {
+ 	const struct sh_dmae_channel *chan_pdata = &shdev->pdata->channel[id];
+@@ -646,7 +646,7 @@ static const struct shdma_ops sh_dmae_shdma_ops = {
+ 	.get_partial = sh_dmae_get_partial,
+ };
+ 
+-static int __devinit sh_dmae_probe(struct platform_device *pdev)
++static int sh_dmae_probe(struct platform_device *pdev)
+ {
+ 	struct sh_dmae_pdata *pdata = pdev->dev.platform_data;
+ 	unsigned long irqflags = IRQF_DISABLED,
+diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c
+index 62d42c9e16b9..c3de6edb9651 100644
+--- a/drivers/dma/sirf-dma.c
++++ b/drivers/dma/sirf-dma.c
+@@ -550,7 +550,7 @@ bool sirfsoc_dma_filter_id(struct dma_chan *chan, void *chan_id)
+ }
+ EXPORT_SYMBOL(sirfsoc_dma_filter_id);
+ 
+-static int __devinit sirfsoc_dma_probe(struct platform_device *op)
++static int sirfsoc_dma_probe(struct platform_device *op)
+ {
+ 	struct device_node *dn = op->dev.of_node;
+ 	struct device *dev = &op->dev;
+diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c
+index 655c4348e468..efdfffa13349 100644
+--- a/drivers/dma/tegra20-apb-dma.c
++++ b/drivers/dma/tegra20-apb-dma.c
+@@ -1197,7 +1197,7 @@ static const struct of_device_id tegra_dma_of_match[] __devinitconst = {
+ MODULE_DEVICE_TABLE(of, tegra_dma_of_match);
+ #endif
+ 
+-static int __devinit tegra_dma_probe(struct platform_device *pdev)
++static int tegra_dma_probe(struct platform_device *pdev)
+ {
+ 	struct resource	*res;
+ 	struct tegra_dma *tdma;
+diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c
+index 4e0dff59901d..98cf51e1544c 100644
+--- a/drivers/dma/timb_dma.c
++++ b/drivers/dma/timb_dma.c
+@@ -667,7 +667,7 @@ static irqreturn_t td_irq(int irq, void *devid)
+ }
+ 
+ 
+-static int __devinit td_probe(struct platform_device *pdev)
++static int td_probe(struct platform_device *pdev)
+ {
+ 	struct timb_dma_platform_data *pdata = pdev->dev.platform_data;
+ 	struct timb_dma *td;

commit a7d6e3ec28bba30d1409d70de1958edc6d9109d7
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:20:04 2012 -0500
+
+    dma: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Barry Song 
+    Acked-by: Viresh Kumar 
+    Acked-by: Russell King 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
+index c4b0eb3cde81..3b21818719d2 100644
+--- a/drivers/dma/dw_dmac.c
++++ b/drivers/dma/dw_dmac.c
+@@ -1700,7 +1700,7 @@ MODULE_DEVICE_TABLE(of, dw_dma_id_table);
+ #endif
+ 
+ static struct platform_driver dw_driver = {
+-	.remove		= __devexit_p(dw_remove),
++	.remove		= dw_remove,
+ 	.shutdown	= dw_shutdown,
+ 	.driver = {
+ 		.name	= "dw_dmac",
+diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
+index 05aea3ce8506..5e5cce4ec720 100644
+--- a/drivers/dma/edma.c
++++ b/drivers/dma/edma.c
+@@ -598,7 +598,7 @@ static int __devexit edma_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver edma_driver = {
+ 	.probe		= edma_probe,
+-	.remove		= __devexit_p(edma_remove),
++	.remove		= edma_remove,
+ 	.driver = {
+ 		.name = "edma-dma-engine",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c
+index 02b21d7d38e5..dffdeffe2c4e 100644
+--- a/drivers/dma/intel_mid_dma.c
++++ b/drivers/dma/intel_mid_dma.c
+@@ -1432,7 +1432,7 @@ static struct pci_driver intel_mid_dma_pci_driver = {
+ 	.name		=	"Intel MID DMA",
+ 	.id_table	=	intel_mid_dma_ids,
+ 	.probe		=	intel_mid_dma_probe,
+-	.remove		=	__devexit_p(intel_mid_dma_remove),
++	.remove		=	intel_mid_dma_remove,
+ #ifdef CONFIG_PM
+ 	.driver = {
+ 		.pm = &intel_mid_dma_pm,
+diff --git a/drivers/dma/ioat/pci.c b/drivers/dma/ioat/pci.c
+index c0573061b45d..bfa9a3536e09 100644
+--- a/drivers/dma/ioat/pci.c
++++ b/drivers/dma/ioat/pci.c
+@@ -125,7 +125,7 @@ static struct pci_driver ioat_pci_driver = {
+ 	.name		= DRV_NAME,
+ 	.id_table	= ioat_pci_tbl,
+ 	.probe		= ioat_pci_probe,
+-	.remove		= __devexit_p(ioat_remove),
++	.remove		= ioat_remove,
+ };
+ 
+ static struct ioatdma_device *
+diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
+index 79e3eba29702..f4a8668b3467 100644
+--- a/drivers/dma/iop-adma.c
++++ b/drivers/dma/iop-adma.c
+@@ -1711,7 +1711,7 @@ static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan)
+ 
+ static struct platform_driver iop_adma_driver = {
+ 	.probe		= iop_adma_probe,
+-	.remove		= __devexit_p(iop_adma_remove),
++	.remove		= iop_adma_remove,
+ 	.driver		= {
+ 		.owner	= THIS_MODULE,
+ 		.name	= "iop-adma",
+diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c
+index 14da1f403edf..4777986adbaf 100644
+--- a/drivers/dma/mmp_pdma.c
++++ b/drivers/dma/mmp_pdma.c
+@@ -865,7 +865,7 @@ static struct platform_driver mmp_pdma_driver = {
+ 	},
+ 	.id_table	= mmp_pdma_id_table,
+ 	.probe		= mmp_pdma_probe,
+-	.remove		= __devexit_p(mmp_pdma_remove),
++	.remove		= mmp_pdma_remove,
+ };
+ 
+ module_platform_driver(mmp_pdma_driver);
+diff --git a/drivers/dma/mmp_tdma.c b/drivers/dma/mmp_tdma.c
+index f3e8d71bcbc7..7d7fc6b19261 100644
+--- a/drivers/dma/mmp_tdma.c
++++ b/drivers/dma/mmp_tdma.c
+@@ -609,7 +609,7 @@ static struct platform_driver mmp_tdma_driver = {
+ 	},
+ 	.id_table	= mmp_tdma_id_table,
+ 	.probe		= mmp_tdma_probe,
+-	.remove		= __devexit_p(mmp_tdma_remove),
++	.remove		= mmp_tdma_remove,
+ };
+ 
+ module_platform_driver(mmp_tdma_driver);
+diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
+index 2ab0a3d0eed5..4b8754b9a2df 100644
+--- a/drivers/dma/mpc512x_dma.c
++++ b/drivers/dma/mpc512x_dma.c
+@@ -818,7 +818,7 @@ static struct of_device_id mpc_dma_match[] = {
+ 
+ static struct platform_driver mpc_dma_driver = {
+ 	.probe		= mpc_dma_probe,
+-	.remove		= __devexit_p(mpc_dma_remove),
++	.remove		= mpc_dma_remove,
+ 	.driver = {
+ 		.name = DRV_NAME,
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
+index e362e2b80efb..2e9ad2d9fe44 100644
+--- a/drivers/dma/mv_xor.c
++++ b/drivers/dma/mv_xor.c
+@@ -1262,7 +1262,7 @@ mv_xor_conf_mbus_windows(struct mv_xor_shared_private *msp,
+ 
+ static struct platform_driver mv_xor_driver = {
+ 	.probe		= mv_xor_probe,
+-	.remove		= __devexit_p(mv_xor_remove),
++	.remove		= mv_xor_remove,
+ 	.driver		= {
+ 		.owner	= THIS_MODULE,
+ 		.name	= MV_XOR_NAME,
+diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c
+index 987ab5cd2617..f7f1c1947089 100644
+--- a/drivers/dma/pch_dma.c
++++ b/drivers/dma/pch_dma.c
+@@ -1022,7 +1022,7 @@ static struct pci_driver pch_dma_driver = {
+ 	.name		= DRV_NAME,
+ 	.id_table	= pch_dma_id_table,
+ 	.probe		= pch_dma_probe,
+-	.remove		= __devexit_p(pch_dma_remove),
++	.remove		= pch_dma_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= pch_dma_suspend,
+ 	.resume		= pch_dma_resume,
+diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c
+index f72348d0bc41..5c6717c48f48 100644
+--- a/drivers/dma/ppc4xx/adma.c
++++ b/drivers/dma/ppc4xx/adma.c
+@@ -4914,7 +4914,7 @@ MODULE_DEVICE_TABLE(of, ppc440spe_adma_of_match);
+ 
+ static struct platform_driver ppc440spe_adma_driver = {
+ 	.probe = ppc440spe_adma_probe,
+-	.remove = __devexit_p(ppc440spe_adma_remove),
++	.remove = ppc440spe_adma_remove,
+ 	.driver = {
+ 		.name = "PPC440SP(E)-ADMA",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/dma/sa11x0-dma.c b/drivers/dma/sa11x0-dma.c
+index b893159c1ecb..1255d9b2c3dd 100644
+--- a/drivers/dma/sa11x0-dma.c
++++ b/drivers/dma/sa11x0-dma.c
+@@ -1072,7 +1072,7 @@ static struct platform_driver sa11x0_dma_driver = {
+ 		.pm	= &sa11x0_dma_pm_ops,
+ 	},
+ 	.probe		= sa11x0_dma_probe,
+-	.remove		= __devexit_p(sa11x0_dma_remove),
++	.remove		= sa11x0_dma_remove,
+ };
+ 
+ bool sa11x0_dma_filter_fn(struct dma_chan *chan, void *param)
+diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c
+index f41bcc5267fd..7dcf4e073186 100644
+--- a/drivers/dma/sh/shdma.c
++++ b/drivers/dma/sh/shdma.c
+@@ -926,7 +926,7 @@ static struct platform_driver sh_dmae_driver = {
+ 		.pm	= &sh_dmae_pm,
+ 		.name	= SH_DMAE_DRV_NAME,
+ 	},
+-	.remove		= __devexit_p(sh_dmae_remove),
++	.remove		= sh_dmae_remove,
+ 	.shutdown	= sh_dmae_shutdown,
+ };
+ 
+diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c
+index d451caace806..62d42c9e16b9 100644
+--- a/drivers/dma/sirf-dma.c
++++ b/drivers/dma/sirf-dma.c
+@@ -673,7 +673,7 @@ static struct of_device_id sirfsoc_dma_match[] = {
+ 
+ static struct platform_driver sirfsoc_dma_driver = {
+ 	.probe		= sirfsoc_dma_probe,
+-	.remove		= __devexit_p(sirfsoc_dma_remove),
++	.remove		= sirfsoc_dma_remove,
+ 	.driver = {
+ 		.name = DRV_NAME,
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c
+index 528c62dd4b00..655c4348e468 100644
+--- a/drivers/dma/tegra20-apb-dma.c
++++ b/drivers/dma/tegra20-apb-dma.c
+@@ -1418,7 +1418,7 @@ static struct platform_driver tegra_dmac_driver = {
+ 		.of_match_table = of_match_ptr(tegra_dma_of_match),
+ 	},
+ 	.probe		= tegra_dma_probe,
+-	.remove		= __devexit_p(tegra_dma_remove),
++	.remove		= tegra_dma_remove,
+ };
+ 
+ module_platform_driver(tegra_dmac_driver);

commit 7eeb741895ea8926e6064dd0bbb349c6ebc09e8b
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:24:13 2012 -0500
+
+    firewire: remove use of __devinitdata
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitdata is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Stefan Richter 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/firewire/nosy.c b/drivers/firewire/nosy.c
+index 7a712b9ffb15..76b2d390f6ec 100644
+--- a/drivers/firewire/nosy.c
++++ b/drivers/firewire/nosy.c
+@@ -683,7 +683,7 @@ add_card(struct pci_dev *dev, const struct pci_device_id *unused)
+ 	return ret;
+ }
+ 
+-static struct pci_device_id pci_table[] __devinitdata = {
++static struct pci_device_id pci_table[] = {
+ 	{
+ 		.vendor =    PCI_VENDOR_ID_TI,
+ 		.device =    PCI_DEVICE_ID_TI_PCILYNX,

commit 03f94c0f6215fa0cc471d07ffb3c4bcb1a0889c1
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:57 2012 -0500
+
+    firewire: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Stefan Richter 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/firewire/nosy.c b/drivers/firewire/nosy.c
+index 4ebfb2273672..7a712b9ffb15 100644
+--- a/drivers/firewire/nosy.c
++++ b/drivers/firewire/nosy.c
+@@ -529,7 +529,7 @@ remove_card(struct pci_dev *dev)
+ 
+ #define RCV_BUFFER_SIZE (16 * 1024)
+ 
+-static int __devinit
++static int
+ add_card(struct pci_dev *dev, const struct pci_device_id *unused)
+ {
+ 	struct pcilynx *lynx;
+diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
+index 834e71d2324d..f25610bb3148 100644
+--- a/drivers/firewire/ohci.c
++++ b/drivers/firewire/ohci.c
+@@ -3537,7 +3537,7 @@ static inline void pmac_ohci_on(struct pci_dev *dev) {}
+ static inline void pmac_ohci_off(struct pci_dev *dev) {}
+ #endif /* CONFIG_PPC_PMAC */
+ 
+-static int __devinit pci_probe(struct pci_dev *dev,
++static int pci_probe(struct pci_dev *dev,
+ 			       const struct pci_device_id *ent)
+ {
+ 	struct fw_ohci *ohci;

commit 678e8a6be911dd8684b894687ae88ff3b0ae4659
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:00 2012 -0500
+
+    leds: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Richard Purdie 
+    Cc: Jan-Simon Moeller 
+    Acked-by: Bryan Wu 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/leds/leds-adp5520.c b/drivers/leds/leds-adp5520.c
+index 28c97667c079..dcd9128a51a9 100644
+--- a/drivers/leds/leds-adp5520.c
++++ b/drivers/leds/leds-adp5520.c
+@@ -183,7 +183,7 @@ static int adp5520_led_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit adp5520_led_remove(struct platform_device *pdev)
++static int adp5520_led_remove(struct platform_device *pdev)
+ {
+ 	struct adp5520_leds_platform_data *pdata = pdev->dev.platform_data;
+ 	struct adp5520_led *led;
+diff --git a/drivers/leds/leds-asic3.c b/drivers/leds/leds-asic3.c
+index c700ad9053f5..b474745e001b 100644
+--- a/drivers/leds/leds-asic3.c
++++ b/drivers/leds/leds-asic3.c
+@@ -125,7 +125,7 @@ static int asic3_led_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit asic3_led_remove(struct platform_device *pdev)
++static int asic3_led_remove(struct platform_device *pdev)
+ {
+ 	struct asic3_led *led = pdev->dev.platform_data;
+ 
+diff --git a/drivers/leds/leds-blinkm.c b/drivers/leds/leds-blinkm.c
+index 5ed27d318074..a502678cc7f5 100644
+--- a/drivers/leds/leds-blinkm.c
++++ b/drivers/leds/leds-blinkm.c
+@@ -743,7 +743,7 @@ static int blinkm_probe(struct i2c_client *client,
+ 	return err;
+ }
+ 
+-static int __devexit blinkm_remove(struct i2c_client *client)
++static int blinkm_remove(struct i2c_client *client)
+ {
+ 	struct blinkm_data *data = i2c_get_clientdata(client);
+ 	int ret = 0;
+diff --git a/drivers/leds/leds-cobalt-qube.c b/drivers/leds/leds-cobalt-qube.c
+index f663979db63d..ffa99303b629 100644
+--- a/drivers/leds/leds-cobalt-qube.c
++++ b/drivers/leds/leds-cobalt-qube.c
+@@ -63,7 +63,7 @@ static int cobalt_qube_led_probe(struct platform_device *pdev)
+ 	return retval;
+ }
+ 
+-static int __devexit cobalt_qube_led_remove(struct platform_device *pdev)
++static int cobalt_qube_led_remove(struct platform_device *pdev)
+ {
+ 	led_classdev_unregister(&qube_front_led);
+ 
+diff --git a/drivers/leds/leds-cobalt-raq.c b/drivers/leds/leds-cobalt-raq.c
+index 9d88dc2f81a5..d52e47de396f 100644
+--- a/drivers/leds/leds-cobalt-raq.c
++++ b/drivers/leds/leds-cobalt-raq.c
+@@ -109,7 +109,7 @@ static int cobalt_raq_led_probe(struct platform_device *pdev)
+ 	return retval;
+ }
+ 
+-static int __devexit cobalt_raq_led_remove(struct platform_device *pdev)
++static int cobalt_raq_led_remove(struct platform_device *pdev)
+ {
+ 	led_classdev_unregister(&raq_power_off_led);
+ 	led_classdev_unregister(&raq_web_led);
+diff --git a/drivers/leds/leds-da903x.c b/drivers/leds/leds-da903x.c
+index bb174905b0fe..6f31b776765b 100644
+--- a/drivers/leds/leds-da903x.c
++++ b/drivers/leds/leds-da903x.c
+@@ -136,7 +136,7 @@ static int da903x_led_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit da903x_led_remove(struct platform_device *pdev)
++static int da903x_led_remove(struct platform_device *pdev)
+ {
+ 	struct da903x_led *led = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/leds/leds-da9052.c b/drivers/leds/leds-da9052.c
+index ded9931010a8..efec43344e9f 100644
+--- a/drivers/leds/leds-da9052.c
++++ b/drivers/leds/leds-da9052.c
+@@ -176,7 +176,7 @@ static int da9052_led_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit da9052_led_remove(struct platform_device *pdev)
++static int da9052_led_remove(struct platform_device *pdev)
+ {
+ 	struct da9052_led *led = platform_get_drvdata(pdev);
+ 	struct da9052_pdata *pdata;
+diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
+index 5c9efc73f06a..291c20797ca0 100644
+--- a/drivers/leds/leds-gpio.c
++++ b/drivers/leds/leds-gpio.c
+@@ -273,7 +273,7 @@ static int gpio_led_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit gpio_led_remove(struct platform_device *pdev)
++static int gpio_led_remove(struct platform_device *pdev)
+ {
+ 	struct gpio_leds_priv *priv = platform_get_drvdata(pdev);
+ 	int i;
+diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c
+index 1aaaaa230c99..214145483836 100644
+--- a/drivers/leds/leds-lm3530.c
++++ b/drivers/leds/leds-lm3530.c
+@@ -452,7 +452,7 @@ static int lm3530_probe(struct i2c_client *client,
+ 	return err;
+ }
+ 
+-static int __devexit lm3530_remove(struct i2c_client *client)
++static int lm3530_remove(struct i2c_client *client)
+ {
+ 	struct lm3530_data *drvdata = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/leds/leds-lm3533.c b/drivers/leds/leds-lm3533.c
+index 7a60440c5806..bbf24d038a7f 100644
+--- a/drivers/leds/leds-lm3533.c
++++ b/drivers/leds/leds-lm3533.c
+@@ -742,7 +742,7 @@ static int lm3533_led_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit lm3533_led_remove(struct platform_device *pdev)
++static int lm3533_led_remove(struct platform_device *pdev)
+ {
+ 	struct lm3533_led *led = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/leds/leds-lm355x.c b/drivers/leds/leds-lm355x.c
+index 0c9d3a083ac2..b13ce0371918 100644
+--- a/drivers/leds/leds-lm355x.c
++++ b/drivers/leds/leds-lm355x.c
+@@ -526,7 +526,7 @@ static int lm355x_probe(struct i2c_client *client,
+ 	return err;
+ }
+ 
+-static int __devexit lm355x_remove(struct i2c_client *client)
++static int lm355x_remove(struct i2c_client *client)
+ {
+ 	struct lm355x_chip_data *chip = i2c_get_clientdata(client);
+ 	struct lm355x_reg_data *preg = chip->regs;
+diff --git a/drivers/leds/leds-lm3642.c b/drivers/leds/leds-lm3642.c
+index 20a45812219b..215a7c1e56cc 100644
+--- a/drivers/leds/leds-lm3642.c
++++ b/drivers/leds/leds-lm3642.c
+@@ -420,7 +420,7 @@ static int lm3642_probe(struct i2c_client *client,
+ 	return err;
+ }
+ 
+-static int __devexit lm3642_remove(struct i2c_client *client)
++static int lm3642_remove(struct i2c_client *client)
+ {
+ 	struct lm3642_chip_data *chip = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/leds/leds-lp3944.c b/drivers/leds/leds-lp3944.c
+index 1544124bfcc5..b081f67e1dea 100644
+--- a/drivers/leds/leds-lp3944.c
++++ b/drivers/leds/leds-lp3944.c
+@@ -411,7 +411,7 @@ static int lp3944_probe(struct i2c_client *client,
+ 	return 0;
+ }
+ 
+-static int __devexit lp3944_remove(struct i2c_client *client)
++static int lp3944_remove(struct i2c_client *client)
+ {
+ 	struct lp3944_platform_data *pdata = client->dev.platform_data;
+ 	struct lp3944_data *data = i2c_get_clientdata(client);
+diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c
+index 847434c21f28..966f158a07db 100644
+--- a/drivers/leds/leds-lp5521.c
++++ b/drivers/leds/leds-lp5521.c
+@@ -855,7 +855,7 @@ static int lp5521_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit lp5521_remove(struct i2c_client *client)
++static int lp5521_remove(struct i2c_client *client)
+ {
+ 	struct lp5521_chip *chip = i2c_get_clientdata(client);
+ 	int i;
+diff --git a/drivers/leds/leds-lp8788.c b/drivers/leds/leds-lp8788.c
+index 27831ffe3953..4353942c5fd1 100644
+--- a/drivers/leds/leds-lp8788.c
++++ b/drivers/leds/leds-lp8788.c
+@@ -167,7 +167,7 @@ static int lp8788_led_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit lp8788_led_remove(struct platform_device *pdev)
++static int lp8788_led_remove(struct platform_device *pdev)
+ {
+ 	struct lp8788_led *led = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c
+index 6487293a5e6d..34b3ba4376fc 100644
+--- a/drivers/leds/leds-lt3593.c
++++ b/drivers/leds/leds-lt3593.c
+@@ -173,7 +173,7 @@ static int lt3593_led_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit lt3593_led_remove(struct platform_device *pdev)
++static int lt3593_led_remove(struct platform_device *pdev)
+ {
+ 	int i;
+ 	struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
+diff --git a/drivers/leds/leds-max8997.c b/drivers/leds/leds-max8997.c
+index f8db895acaf5..f449a8bdddc7 100644
+--- a/drivers/leds/leds-max8997.c
++++ b/drivers/leds/leds-max8997.c
+@@ -292,7 +292,7 @@ static int max8997_led_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit max8997_led_remove(struct platform_device *pdev)
++static int max8997_led_remove(struct platform_device *pdev)
+ {
+ 	struct max8997_led *led = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c
+index 39f72a7a1794..e942adaa7504 100644
+--- a/drivers/leds/leds-mc13783.c
++++ b/drivers/leds/leds-mc13783.c
+@@ -348,7 +348,7 @@ static int mc13783_led_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit mc13783_led_remove(struct platform_device *pdev)
++static int mc13783_led_remove(struct platform_device *pdev)
+ {
+ 	struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ 	struct mc13783_led *led = platform_get_drvdata(pdev);
+diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c
+index 5f2421804a0d..58a800b17dc7 100644
+--- a/drivers/leds/leds-netxbig.c
++++ b/drivers/leds/leds-netxbig.c
+@@ -389,7 +389,7 @@ static int netxbig_led_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit netxbig_led_remove(struct platform_device *pdev)
++static int netxbig_led_remove(struct platform_device *pdev)
+ {
+ 	struct netxbig_led_platform_data *pdata = pdev->dev.platform_data;
+ 	struct netxbig_led_data *leds_data;
+diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c
+index f5d0df32ab83..6315e88d04fd 100644
+--- a/drivers/leds/leds-ns2.c
++++ b/drivers/leds/leds-ns2.c
+@@ -292,7 +292,7 @@ static int ns2_led_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit ns2_led_remove(struct platform_device *pdev)
++static int ns2_led_remove(struct platform_device *pdev)
+ {
+ 	int i;
+ 	struct ns2_led_platform_data *pdata = pdev->dev.platform_data;
+diff --git a/drivers/leds/leds-ot200.c b/drivers/leds/leds-ot200.c
+index 4c26aa2d7af6..ee14662ed5ce 100644
+--- a/drivers/leds/leds-ot200.c
++++ b/drivers/leds/leds-ot200.c
+@@ -144,7 +144,7 @@ static int ot200_led_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit ot200_led_remove(struct platform_device *pdev)
++static int ot200_led_remove(struct platform_device *pdev)
+ {
+ 	int i;
+ 
+diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
+index f07c5203fbd5..706791af8fc8 100644
+--- a/drivers/leds/leds-pca955x.c
++++ b/drivers/leds/leds-pca955x.c
+@@ -363,7 +363,7 @@ static int pca955x_probe(struct i2c_client *client,
+ 	return err;
+ }
+ 
+-static int __devexit pca955x_remove(struct i2c_client *client)
++static int pca955x_remove(struct i2c_client *client)
+ {
+ 	struct pca955x *pca955x = i2c_get_clientdata(client);
+ 	int i;
+diff --git a/drivers/leds/leds-pca9633.c b/drivers/leds/leds-pca9633.c
+index d55bd8dc4813..9aae5679ffb2 100644
+--- a/drivers/leds/leds-pca9633.c
++++ b/drivers/leds/leds-pca9633.c
+@@ -164,7 +164,7 @@ static int pca9633_probe(struct i2c_client *client,
+ 	return err;
+ }
+ 
+-static int __devexit pca9633_remove(struct i2c_client *client)
++static int pca9633_remove(struct i2c_client *client)
+ {
+ 	struct pca9633_led *pca9633 = i2c_get_clientdata(client);
+ 	int i;
+diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
+index 7a988f18522a..e51ff7a3cd88 100644
+--- a/drivers/leds/leds-pwm.c
++++ b/drivers/leds/leds-pwm.c
+@@ -107,7 +107,7 @@ static int led_pwm_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit led_pwm_remove(struct platform_device *pdev)
++static int led_pwm_remove(struct platform_device *pdev)
+ {
+ 	int i;
+ 	struct led_pwm_platform_data *pdata = pdev->dev.platform_data;
+diff --git a/drivers/leds/leds-rb532.c b/drivers/leds/leds-rb532.c
+index 43f02f4a1953..9ebdd5011a7c 100644
+--- a/drivers/leds/leds-rb532.c
++++ b/drivers/leds/leds-rb532.c
+@@ -42,7 +42,7 @@ static int rb532_led_probe(struct platform_device *pdev)
+ 	return led_classdev_register(&pdev->dev, &rb532_uled);
+ }
+ 
+-static int __devexit rb532_led_remove(struct platform_device *pdev)
++static int rb532_led_remove(struct platform_device *pdev)
+ {
+ 	led_classdev_unregister(&rb532_uled);
+ 	return 0;
+diff --git a/drivers/leds/leds-regulator.c b/drivers/leds/leds-regulator.c
+index adb33f7c73ad..4253a9b03dbf 100644
+--- a/drivers/leds/leds-regulator.c
++++ b/drivers/leds/leds-regulator.c
+@@ -206,7 +206,7 @@ static int regulator_led_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit regulator_led_remove(struct platform_device *pdev)
++static int regulator_led_remove(struct platform_device *pdev)
+ {
+ 	struct regulator_led *led = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/leds/leds-renesas-tpu.c b/drivers/leds/leds-renesas-tpu.c
+index 053e45763f3c..bc8984795a3e 100644
+--- a/drivers/leds/leds-renesas-tpu.c
++++ b/drivers/leds/leds-renesas-tpu.c
+@@ -309,7 +309,7 @@ static int r_tpu_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit r_tpu_remove(struct platform_device *pdev)
++static int r_tpu_remove(struct platform_device *pdev)
+ {
+ 	struct r_tpu_priv *p = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/leds/leds-sunfire.c b/drivers/leds/leds-sunfire.c
+index f72886e08c22..07ff5a3a6cee 100644
+--- a/drivers/leds/leds-sunfire.c
++++ b/drivers/leds/leds-sunfire.c
+@@ -165,7 +165,7 @@ static int sunfire_led_generic_probe(struct platform_device *pdev,
+ 	return 0;
+ }
+ 
+-static int __devexit sunfire_led_generic_remove(struct platform_device *pdev)
++static int sunfire_led_generic_remove(struct platform_device *pdev)
+ {
+ 	struct sunfire_drvdata *p = dev_get_drvdata(&pdev->dev);
+ 	int i;
+diff --git a/drivers/leds/leds-tca6507.c b/drivers/leds/leds-tca6507.c
+index 9acec6130494..b26a63bae16b 100644
+--- a/drivers/leds/leds-tca6507.c
++++ b/drivers/leds/leds-tca6507.c
+@@ -730,7 +730,7 @@ static int tca6507_probe(struct i2c_client *client,
+ 	return err;
+ }
+ 
+-static int __devexit tca6507_remove(struct i2c_client *client)
++static int tca6507_remove(struct i2c_client *client)
+ {
+ 	int i;
+ 	struct tca6507_chip *tca = i2c_get_clientdata(client);

commit 98ea1ea20cb7090d5ae2003c23fc8a7f14fca4c7
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:23:02 2012 -0500
+
+    leds: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Richard Purdie 
+    Cc: Jan-Simon Moeller 
+    Acked-by: Bryan Wu 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/leds/leds-adp5520.c b/drivers/leds/leds-adp5520.c
+index e068802f5222..28c97667c079 100644
+--- a/drivers/leds/leds-adp5520.c
++++ b/drivers/leds/leds-adp5520.c
+@@ -85,7 +85,7 @@ static int adp5520_led_setup(struct adp5520_led *led)
+ 	return ret;
+ }
+ 
+-static int __devinit adp5520_led_prepare(struct platform_device *pdev)
++static int adp5520_led_prepare(struct platform_device *pdev)
+ {
+ 	struct adp5520_leds_platform_data *pdata = pdev->dev.platform_data;
+ 	struct device *dev = pdev->dev.parent;
+@@ -101,7 +101,7 @@ static int __devinit adp5520_led_prepare(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devinit adp5520_led_probe(struct platform_device *pdev)
++static int adp5520_led_probe(struct platform_device *pdev)
+ {
+ 	struct adp5520_leds_platform_data *pdata = pdev->dev.platform_data;
+ 	struct adp5520_led *led, *led_dat;
+diff --git a/drivers/leds/leds-asic3.c b/drivers/leds/leds-asic3.c
+index ec601e2e92dc..c700ad9053f5 100644
+--- a/drivers/leds/leds-asic3.c
++++ b/drivers/leds/leds-asic3.c
+@@ -92,7 +92,7 @@ static int blink_set(struct led_classdev *cdev,
+ 	return 0;
+ }
+ 
+-static int __devinit asic3_led_probe(struct platform_device *pdev)
++static int asic3_led_probe(struct platform_device *pdev)
+ {
+ 	struct asic3_led *led = pdev->dev.platform_data;
+ 	int ret;
+diff --git a/drivers/leds/leds-atmel-pwm.c b/drivers/leds/leds-atmel-pwm.c
+index 45430632faab..386773532d95 100644
+--- a/drivers/leds/leds-atmel-pwm.c
++++ b/drivers/leds/leds-atmel-pwm.c
+@@ -35,7 +35,7 @@ static void pwmled_brightness(struct led_classdev *cdev, enum led_brightness b)
+  * NOTE:  we reuse the platform_data structure of GPIO leds,
+  * but repurpose its "gpio" number as a PWM channel number.
+  */
+-static int __devinit pwmled_probe(struct platform_device *pdev)
++static int pwmled_probe(struct platform_device *pdev)
+ {
+ 	const struct gpio_led_platform_data	*pdata;
+ 	struct pwmled				*leds;
+diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c
+index 89ca6a2a19d1..9abe8de40edd 100644
+--- a/drivers/leds/leds-bd2802.c
++++ b/drivers/leds/leds-bd2802.c
+@@ -670,7 +670,7 @@ static void bd2802_unregister_led_classdev(struct bd2802_led *led)
+ 	led_classdev_unregister(&led->cdev_led1r);
+ }
+ 
+-static int __devinit bd2802_probe(struct i2c_client *client,
++static int bd2802_probe(struct i2c_client *client,
+ 			const struct i2c_device_id *id)
+ {
+ 	struct bd2802_led *led;
+diff --git a/drivers/leds/leds-blinkm.c b/drivers/leds/leds-blinkm.c
+index 92a2c1f696f5..5ed27d318074 100644
+--- a/drivers/leds/leds-blinkm.c
++++ b/drivers/leds/leds-blinkm.c
+@@ -632,7 +632,7 @@ static int blinkm_detect(struct i2c_client *client, struct i2c_board_info *info)
+ 	return 0;
+ }
+ 
+-static int __devinit blinkm_probe(struct i2c_client *client,
++static int blinkm_probe(struct i2c_client *client,
+ 			const struct i2c_device_id *id)
+ {
+ 	struct blinkm_data *data;
+diff --git a/drivers/leds/leds-clevo-mail.c b/drivers/leds/leds-clevo-mail.c
+index e024b0b1c3b1..b02547052e12 100644
+--- a/drivers/leds/leds-clevo-mail.c
++++ b/drivers/leds/leds-clevo-mail.c
+@@ -153,7 +153,7 @@ static struct led_classdev clevo_mail_led = {
+ 	.flags			= LED_CORE_SUSPENDRESUME,
+ };
+ 
+-static int __devinit clevo_mail_led_probe(struct platform_device *pdev)
++static int clevo_mail_led_probe(struct platform_device *pdev)
+ {
+ 	return led_classdev_register(&pdev->dev, &clevo_mail_led);
+ }
+diff --git a/drivers/leds/leds-cobalt-qube.c b/drivers/leds/leds-cobalt-qube.c
+index cdf00652dd55..f663979db63d 100644
+--- a/drivers/leds/leds-cobalt-qube.c
++++ b/drivers/leds/leds-cobalt-qube.c
+@@ -34,7 +34,7 @@ static struct led_classdev qube_front_led = {
+ 	.default_trigger	= "default-on",
+ };
+ 
+-static int __devinit cobalt_qube_led_probe(struct platform_device *pdev)
++static int cobalt_qube_led_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res;
+ 	int retval;
+diff --git a/drivers/leds/leds-cobalt-raq.c b/drivers/leds/leds-cobalt-raq.c
+index 0894e89d43fd..9d88dc2f81a5 100644
+--- a/drivers/leds/leds-cobalt-raq.c
++++ b/drivers/leds/leds-cobalt-raq.c
+@@ -76,7 +76,7 @@ static struct led_classdev raq_power_off_led = {
+ 	.default_trigger	= "power-off",
+ };
+ 
+-static int __devinit cobalt_raq_led_probe(struct platform_device *pdev)
++static int cobalt_raq_led_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res;
+ 	int retval;
+diff --git a/drivers/leds/leds-da903x.c b/drivers/leds/leds-da903x.c
+index de08c9312af0..bb174905b0fe 100644
+--- a/drivers/leds/leds-da903x.c
++++ b/drivers/leds/leds-da903x.c
+@@ -91,7 +91,7 @@ static void da903x_led_set(struct led_classdev *led_cdev,
+ 	schedule_work(&led->work);
+ }
+ 
+-static int __devinit da903x_led_probe(struct platform_device *pdev)
++static int da903x_led_probe(struct platform_device *pdev)
+ {
+ 	struct led_info *pdata = pdev->dev.platform_data;
+ 	struct da903x_led *led;
+diff --git a/drivers/leds/leds-da9052.c b/drivers/leds/leds-da9052.c
+index 0df968cf0599..ded9931010a8 100644
+--- a/drivers/leds/leds-da9052.c
++++ b/drivers/leds/leds-da9052.c
+@@ -102,7 +102,7 @@ static int da9052_configure_leds(struct da9052 *da9052)
+ 	return error;
+ }
+ 
+-static int __devinit da9052_led_probe(struct platform_device *pdev)
++static int da9052_led_probe(struct platform_device *pdev)
+ {
+ 	struct da9052_pdata *pdata;
+ 	struct da9052 *da9052;
+diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
+index 51bc51311de0..5c9efc73f06a 100644
+--- a/drivers/leds/leds-gpio.c
++++ b/drivers/leds/leds-gpio.c
+@@ -91,7 +91,7 @@ static int gpio_blink_set(struct led_classdev *led_cdev,
+ 						delay_on, delay_off);
+ }
+ 
+-static int __devinit create_gpio_led(const struct gpio_led *template,
++static int create_gpio_led(const struct gpio_led *template,
+ 	struct gpio_led_data *led_dat, struct device *parent,
+ 	int (*blink_set)(unsigned, int, unsigned long *, unsigned long *))
+ {
+@@ -167,7 +167,7 @@ static inline int sizeof_gpio_leds_priv(int num_leds)
+ 
+ /* Code to create from OpenFirmware platform devices */
+ #ifdef CONFIG_OF_GPIO
+-static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_device *pdev)
++static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
+ {
+ 	struct device_node *np = pdev->dev.of_node, *child;
+ 	struct gpio_leds_priv *priv;
+@@ -224,14 +224,14 @@ static const struct of_device_id of_gpio_leds_match[] = {
+ 	{},
+ };
+ #else /* CONFIG_OF_GPIO */
+-static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_device *pdev)
++static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
+ {
+ 	return NULL;
+ }
+ #endif /* CONFIG_OF_GPIO */
+ 
+ 
+-static int __devinit gpio_led_probe(struct platform_device *pdev)
++static int gpio_led_probe(struct platform_device *pdev)
+ {
+ 	struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
+ 	struct gpio_leds_priv *priv;
+diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c
+index 5ac59e1f3334..1aaaaa230c99 100644
+--- a/drivers/leds/leds-lm3530.c
++++ b/drivers/leds/leds-lm3530.c
+@@ -377,7 +377,7 @@ static ssize_t lm3530_mode_set(struct device *dev, struct device_attribute
+ }
+ static DEVICE_ATTR(mode, 0644, lm3530_mode_get, lm3530_mode_set);
+ 
+-static int __devinit lm3530_probe(struct i2c_client *client,
++static int lm3530_probe(struct i2c_client *client,
+ 			   const struct i2c_device_id *id)
+ {
+ 	struct lm3530_platform_data *pdata = client->dev.platform_data;
+diff --git a/drivers/leds/leds-lm3533.c b/drivers/leds/leds-lm3533.c
+index be246bf32e2d..7a60440c5806 100644
+--- a/drivers/leds/leds-lm3533.c
++++ b/drivers/leds/leds-lm3533.c
+@@ -646,7 +646,7 @@ static struct attribute_group lm3533_led_attribute_group = {
+ 	.attrs		= lm3533_led_attributes
+ };
+ 
+-static int __devinit lm3533_led_setup(struct lm3533_led *led,
++static int lm3533_led_setup(struct lm3533_led *led,
+ 					struct lm3533_led_platform_data *pdata)
+ {
+ 	int ret;
+@@ -658,7 +658,7 @@ static int __devinit lm3533_led_setup(struct lm3533_led *led,
+ 	return lm3533_ctrlbank_set_pwm(&led->cb, pdata->pwm);
+ }
+ 
+-static int __devinit lm3533_led_probe(struct platform_device *pdev)
++static int lm3533_led_probe(struct platform_device *pdev)
+ {
+ 	struct lm3533 *lm3533;
+ 	struct lm3533_led_platform_data *pdata;
+diff --git a/drivers/leds/leds-lm355x.c b/drivers/leds/leds-lm355x.c
+index 307d7b960809..0c9d3a083ac2 100644
+--- a/drivers/leds/leds-lm355x.c
++++ b/drivers/leds/leds-lm355x.c
+@@ -168,7 +168,7 @@ static char lm355x_name[][I2C_NAME_SIZE] = {
+ };
+ 
+ /* chip initialize */
+-static int __devinit lm355x_chip_init(struct lm355x_chip_data *chip)
++static int lm355x_chip_init(struct lm355x_chip_data *chip)
+ {
+ 	int ret;
+ 	unsigned int reg_val;
+@@ -420,7 +420,7 @@ static const struct regmap_config lm355x_regmap = {
+ };
+ 
+ /* module initialize */
+-static int __devinit lm355x_probe(struct i2c_client *client,
++static int lm355x_probe(struct i2c_client *client,
+ 				  const struct i2c_device_id *id)
+ {
+ 	struct lm355x_platform_data *pdata = client->dev.platform_data;
+diff --git a/drivers/leds/leds-lm3642.c b/drivers/leds/leds-lm3642.c
+index cae0b7017cbb..20a45812219b 100644
+--- a/drivers/leds/leds-lm3642.c
++++ b/drivers/leds/leds-lm3642.c
+@@ -93,7 +93,7 @@ struct lm3642_chip_data {
+ };
+ 
+ /* chip initialize */
+-static int __devinit lm3642_chip_init(struct lm3642_chip_data *chip)
++static int lm3642_chip_init(struct lm3642_chip_data *chip)
+ {
+ 	int ret;
+ 	struct lm3642_platform_data *pdata = chip->pdata;
+@@ -313,7 +313,7 @@ static const struct regmap_config lm3642_regmap = {
+ 	.max_register = REG_MAX,
+ };
+ 
+-static int __devinit lm3642_probe(struct i2c_client *client,
++static int lm3642_probe(struct i2c_client *client,
+ 				  const struct i2c_device_id *id)
+ {
+ 	struct lm3642_platform_data *pdata = client->dev.platform_data;
+diff --git a/drivers/leds/leds-lp3944.c b/drivers/leds/leds-lp3944.c
+index aa74b797a2fa..1544124bfcc5 100644
+--- a/drivers/leds/leds-lp3944.c
++++ b/drivers/leds/leds-lp3944.c
+@@ -374,7 +374,7 @@ static int lp3944_configure(struct i2c_client *client,
+ 	return err;
+ }
+ 
+-static int __devinit lp3944_probe(struct i2c_client *client,
++static int lp3944_probe(struct i2c_client *client,
+ 				  const struct i2c_device_id *id)
+ {
+ 	struct lp3944_platform_data *lp3944_pdata = client->dev.platform_data;
+diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c
+index d633ecf58687..847434c21f28 100644
+--- a/drivers/leds/leds-lp5521.c
++++ b/drivers/leds/leds-lp5521.c
+@@ -687,7 +687,7 @@ static void lp5521_unregister_sysfs(struct i2c_client *client)
+ 				&lp5521_led_attribute_group);
+ }
+ 
+-static int __devinit lp5521_init_led(struct lp5521_led *led,
++static int lp5521_init_led(struct lp5521_led *led,
+ 				struct i2c_client *client,
+ 				int chan, struct lp5521_platform_data *pdata)
+ {
+@@ -736,7 +736,7 @@ static int __devinit lp5521_init_led(struct lp5521_led *led,
+ 	return 0;
+ }
+ 
+-static int __devinit lp5521_probe(struct i2c_client *client,
++static int lp5521_probe(struct i2c_client *client,
+ 			const struct i2c_device_id *id)
+ {
+ 	struct lp5521_chip		*chip;
+diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c
+index 97994ffdc014..7e304b7ff779 100644
+--- a/drivers/leds/leds-lp5523.c
++++ b/drivers/leds/leds-lp5523.c
+@@ -833,7 +833,7 @@ static int __init lp5523_init_engine(struct lp5523_engine *engine, int id)
+ 	return 0;
+ }
+ 
+-static int __devinit lp5523_init_led(struct lp5523_led *led, struct device *dev,
++static int lp5523_init_led(struct lp5523_led *led, struct device *dev,
+ 			   int chan, struct lp5523_platform_data *pdata,
+ 			   const char *chip_name)
+ {
+@@ -882,7 +882,7 @@ static int __devinit lp5523_init_led(struct lp5523_led *led, struct device *dev,
+ 	return 0;
+ }
+ 
+-static int __devinit lp5523_probe(struct i2c_client *client,
++static int lp5523_probe(struct i2c_client *client,
+ 			const struct i2c_device_id *id)
+ {
+ 	struct lp5523_chip		*chip;
+diff --git a/drivers/leds/leds-lp8788.c b/drivers/leds/leds-lp8788.c
+index fbcfc1b821f8..27831ffe3953 100644
+--- a/drivers/leds/leds-lp8788.c
++++ b/drivers/leds/leds-lp8788.c
+@@ -125,7 +125,7 @@ static void lp8788_brightness_set(struct led_classdev *led_cdev,
+ 	schedule_work(&led->work);
+ }
+ 
+-static __devinit int lp8788_led_probe(struct platform_device *pdev)
++static int lp8788_led_probe(struct platform_device *pdev)
+ {
+ 	struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
+ 	struct lp8788_led_platform_data *led_pdata;
+diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c
+index 40657420cfc5..6487293a5e6d 100644
+--- a/drivers/leds/leds-lt3593.c
++++ b/drivers/leds/leds-lt3593.c
+@@ -82,7 +82,7 @@ static void lt3593_led_set(struct led_classdev *led_cdev,
+ 	schedule_work(&led_dat->work);
+ }
+ 
+-static int __devinit create_lt3593_led(const struct gpio_led *template,
++static int create_lt3593_led(const struct gpio_led *template,
+ 	struct lt3593_led_data *led_dat, struct device *parent)
+ {
+ 	int ret, state;
+@@ -140,7 +140,7 @@ static void delete_lt3593_led(struct lt3593_led_data *led)
+ 	gpio_free(led->gpio);
+ }
+ 
+-static int __devinit lt3593_led_probe(struct platform_device *pdev)
++static int lt3593_led_probe(struct platform_device *pdev)
+ {
+ 	struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
+ 	struct lt3593_led_data *leds_data;
+diff --git a/drivers/leds/leds-max8997.c b/drivers/leds/leds-max8997.c
+index b11a5a72bc3e..f8db895acaf5 100644
+--- a/drivers/leds/leds-max8997.c
++++ b/drivers/leds/leds-max8997.c
+@@ -229,7 +229,7 @@ static ssize_t max8997_led_store_mode(struct device *dev,
+ 
+ static DEVICE_ATTR(mode, 0644, max8997_led_show_mode, max8997_led_store_mode);
+ 
+-static int __devinit max8997_led_probe(struct platform_device *pdev)
++static int max8997_led_probe(struct platform_device *pdev)
+ {
+ 	struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+ 	struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev);
+diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c
+index e760b0754ff1..39f72a7a1794 100644
+--- a/drivers/leds/leds-mc13783.c
++++ b/drivers/leds/leds-mc13783.c
+@@ -128,7 +128,7 @@ static void mc13783_led_set(struct led_classdev *led_cdev,
+ 	schedule_work(&led->work);
+ }
+ 
+-static int __devinit mc13783_led_setup(struct mc13783_led *led, int max_current)
++static int mc13783_led_setup(struct mc13783_led *led, int max_current)
+ {
+ 	int shift = 0;
+ 	int mask = 0;
+@@ -181,7 +181,7 @@ static int __devinit mc13783_led_setup(struct mc13783_led *led, int max_current)
+ 	return ret;
+ }
+ 
+-static int __devinit mc13783_leds_prepare(struct platform_device *pdev)
++static int mc13783_leds_prepare(struct platform_device *pdev)
+ {
+ 	struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ 	struct mc13xxx *dev = dev_get_drvdata(pdev->dev.parent);
+@@ -262,7 +262,7 @@ static int __devinit mc13783_leds_prepare(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devinit mc13783_led_probe(struct platform_device *pdev)
++static int mc13783_led_probe(struct platform_device *pdev)
+ {
+ 	struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ 	struct mc13xxx_led_platform_data *led_cur;
+diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c
+index b3c0377b51fb..5f2421804a0d 100644
+--- a/drivers/leds/leds-netxbig.c
++++ b/drivers/leds/leds-netxbig.c
+@@ -71,7 +71,7 @@ static void gpio_ext_set_value(struct netxbig_gpio_ext *gpio_ext,
+ 	spin_unlock_irqrestore(&gpio_ext_lock, flags);
+ }
+ 
+-static int __devinit gpio_ext_init(struct netxbig_gpio_ext *gpio_ext)
++static int gpio_ext_init(struct netxbig_gpio_ext *gpio_ext)
+ {
+ 	int err;
+ 	int i;
+@@ -301,7 +301,7 @@ static void delete_netxbig_led(struct netxbig_led_data *led_dat)
+ 	led_classdev_unregister(&led_dat->cdev);
+ }
+ 
+-static int __devinit
++static int
+ create_netxbig_led(struct platform_device *pdev,
+ 		   struct netxbig_led_data *led_dat,
+ 		   const struct netxbig_led *template)
+@@ -352,7 +352,7 @@ create_netxbig_led(struct platform_device *pdev,
+ 	return ret;
+ }
+ 
+-static int __devinit netxbig_led_probe(struct platform_device *pdev)
++static int netxbig_led_probe(struct platform_device *pdev)
+ {
+ 	struct netxbig_led_platform_data *pdata = pdev->dev.platform_data;
+ 	struct netxbig_led_data *leds_data;
+diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c
+index 89c8b47b4794..f5d0df32ab83 100644
+--- a/drivers/leds/leds-ns2.c
++++ b/drivers/leds/leds-ns2.c
+@@ -184,7 +184,7 @@ static ssize_t ns2_led_sata_show(struct device *dev,
+ 
+ static DEVICE_ATTR(sata, 0644, ns2_led_sata_show, ns2_led_sata_store);
+ 
+-static int __devinit
++static int
+ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
+ 	       const struct ns2_led *template)
+ {
+@@ -263,7 +263,7 @@ static void delete_ns2_led(struct ns2_led_data *led_dat)
+ 	gpio_free(led_dat->slow);
+ }
+ 
+-static int __devinit ns2_led_probe(struct platform_device *pdev)
++static int ns2_led_probe(struct platform_device *pdev)
+ {
+ 	struct ns2_led_platform_data *pdata = pdev->dev.platform_data;
+ 	struct ns2_led_data *leds_data;
+diff --git a/drivers/leds/leds-ot200.c b/drivers/leds/leds-ot200.c
+index 925217890677..4c26aa2d7af6 100644
+--- a/drivers/leds/leds-ot200.c
++++ b/drivers/leds/leds-ot200.c
+@@ -115,7 +115,7 @@ static void ot200_led_brightness_set(struct led_classdev *led_cdev,
+ 	spin_unlock_irqrestore(&value_lock, flags);
+ }
+ 
+-static int __devinit ot200_led_probe(struct platform_device *pdev)
++static int ot200_led_probe(struct platform_device *pdev)
+ {
+ 	int i;
+ 	int ret;
+diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
+index 12506e74a4c5..f07c5203fbd5 100644
+--- a/drivers/leds/leds-pca955x.c
++++ b/drivers/leds/leds-pca955x.c
+@@ -255,7 +255,7 @@ static void pca955x_led_set(struct led_classdev *led_cdev, enum led_brightness v
+ 	schedule_work(&pca955x->work);
+ }
+ 
+-static int __devinit pca955x_probe(struct i2c_client *client,
++static int pca955x_probe(struct i2c_client *client,
+ 					const struct i2c_device_id *id)
+ {
+ 	struct pca955x *pca955x;
+diff --git a/drivers/leds/leds-pca9633.c b/drivers/leds/leds-pca9633.c
+index 0685f343ff18..d55bd8dc4813 100644
+--- a/drivers/leds/leds-pca9633.c
++++ b/drivers/leds/leds-pca9633.c
+@@ -93,7 +93,7 @@ static void pca9633_led_set(struct led_classdev *led_cdev,
+ 	schedule_work(&pca9633->work);
+ }
+ 
+-static int __devinit pca9633_probe(struct i2c_client *client,
++static int pca9633_probe(struct i2c_client *client,
+ 					const struct i2c_device_id *id)
+ {
+ 	struct pca9633_led *pca9633;
+diff --git a/drivers/leds/leds-rb532.c b/drivers/leds/leds-rb532.c
+index e34f1ff4e8ce..43f02f4a1953 100644
+--- a/drivers/leds/leds-rb532.c
++++ b/drivers/leds/leds-rb532.c
+@@ -37,7 +37,7 @@ static struct led_classdev rb532_uled = {
+ 	.default_trigger = "nand-disk",
+ };
+ 
+-static int __devinit rb532_led_probe(struct platform_device *pdev)
++static int rb532_led_probe(struct platform_device *pdev)
+ {
+ 	return led_classdev_register(&pdev->dev, &rb532_uled);
+ }
+diff --git a/drivers/leds/leds-regulator.c b/drivers/leds/leds-regulator.c
+index 521af9b4e299..adb33f7c73ad 100644
+--- a/drivers/leds/leds-regulator.c
++++ b/drivers/leds/leds-regulator.c
+@@ -140,7 +140,7 @@ static void regulator_led_brightness_set(struct led_classdev *led_cdev,
+ 	schedule_work(&led->work);
+ }
+ 
+-static int __devinit regulator_led_probe(struct platform_device *pdev)
++static int regulator_led_probe(struct platform_device *pdev)
+ {
+ 	struct led_regulator_platform_data *pdata = pdev->dev.platform_data;
+ 	struct regulator_led *led;
+diff --git a/drivers/leds/leds-renesas-tpu.c b/drivers/leds/leds-renesas-tpu.c
+index 71cab56a67aa..053e45763f3c 100644
+--- a/drivers/leds/leds-renesas-tpu.c
++++ b/drivers/leds/leds-renesas-tpu.c
+@@ -238,7 +238,7 @@ static void r_tpu_set_brightness(struct led_classdev *ldev,
+ 	schedule_work(&p->work);
+ }
+ 
+-static int __devinit r_tpu_probe(struct platform_device *pdev)
++static int r_tpu_probe(struct platform_device *pdev)
+ {
+ 	struct led_renesas_tpu_config *cfg = pdev->dev.platform_data;
+ 	struct r_tpu_priv *p;
+diff --git a/drivers/leds/leds-ss4200.c b/drivers/leds/leds-ss4200.c
+index 57371e1485ab..6469849e8266 100644
+--- a/drivers/leds/leds-ss4200.c
++++ b/drivers/leds/leds-ss4200.c
+@@ -263,7 +263,7 @@ static int nasgpio_led_set_blink(struct led_classdev *led_cdev,
+  * already taken care of this, but we will do so in a non destructive manner
+  * so that we have what we need whether the BIOS did it or not.
+  */
+-static int __devinit ich7_gpio_init(struct device *dev)
++static int ich7_gpio_init(struct device *dev)
+ {
+ 	int i;
+ 	u32 config_data = 0;
+@@ -342,7 +342,7 @@ static void ich7_lpc_cleanup(struct device *dev)
+  * so we can retrive the required operational information and prepare the GPIO.
+  */
+ static struct pci_dev *nas_gpio_pci_dev;
+-static int __devinit ich7_lpc_probe(struct pci_dev *dev,
++static int ich7_lpc_probe(struct pci_dev *dev,
+ 				    const struct pci_device_id *id)
+ {
+ 	int status;
+diff --git a/drivers/leds/leds-sunfire.c b/drivers/leds/leds-sunfire.c
+index 3d35c5861146..f72886e08c22 100644
+--- a/drivers/leds/leds-sunfire.c
++++ b/drivers/leds/leds-sunfire.c
+@@ -123,7 +123,7 @@ struct sunfire_drvdata {
+ 	struct sunfire_led	leds[NUM_LEDS_PER_BOARD];
+ };
+ 
+-static int __devinit sunfire_led_generic_probe(struct platform_device *pdev,
++static int sunfire_led_generic_probe(struct platform_device *pdev,
+ 					       struct led_type *types)
+ {
+ 	struct sunfire_drvdata *p;
+@@ -192,7 +192,7 @@ static struct led_type clockboard_led_types[NUM_LEDS_PER_BOARD] = {
+ 	},
+ };
+ 
+-static int __devinit sunfire_clockboard_led_probe(struct platform_device *pdev)
++static int sunfire_clockboard_led_probe(struct platform_device *pdev)
+ {
+ 	return sunfire_led_generic_probe(pdev, clockboard_led_types);
+ }
+@@ -213,7 +213,7 @@ static struct led_type fhc_led_types[NUM_LEDS_PER_BOARD] = {
+ 	},
+ };
+ 
+-static int __devinit sunfire_fhc_led_probe(struct platform_device *pdev)
++static int sunfire_fhc_led_probe(struct platform_device *pdev)
+ {
+ 	return sunfire_led_generic_probe(pdev, fhc_led_types);
+ }
+diff --git a/drivers/leds/leds-tca6507.c b/drivers/leds/leds-tca6507.c
+index 1172b4a264e8..9acec6130494 100644
+--- a/drivers/leds/leds-tca6507.c
++++ b/drivers/leds/leds-tca6507.c
+@@ -667,7 +667,7 @@ static void tca6507_remove_gpio(struct tca6507_chip *tca)
+ }
+ #endif /* CONFIG_GPIOLIB */
+ 
+-static int __devinit tca6507_probe(struct i2c_client *client,
++static int tca6507_probe(struct i2c_client *client,
+ 				   const struct i2c_device_id *id)
+ {
+ 	struct tca6507_chip *tca;

commit df07cf81268192e42c4cdf91f5f4bf9aaac1b2f0
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:20:20 2012 -0500
+
+    leds: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Richard Purdie 
+    Cc: Jan-Simon Moeller 
+    Acked-by: Bryan Wu 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/leds/leds-adp5520.c b/drivers/leds/leds-adp5520.c
+index aa56a867693a..e068802f5222 100644
+--- a/drivers/leds/leds-adp5520.c
++++ b/drivers/leds/leds-adp5520.c
+@@ -208,7 +208,7 @@ static struct platform_driver adp5520_led_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= adp5520_led_probe,
+-	.remove		= __devexit_p(adp5520_led_remove),
++	.remove		= adp5520_led_remove,
+ };
+ 
+ module_platform_driver(adp5520_led_driver);
+diff --git a/drivers/leds/leds-asic3.c b/drivers/leds/leds-asic3.c
+index 5de74ff90dcf..ec601e2e92dc 100644
+--- a/drivers/leds/leds-asic3.c
++++ b/drivers/leds/leds-asic3.c
+@@ -167,7 +167,7 @@ static const struct dev_pm_ops asic3_led_pm_ops = {
+ 
+ static struct platform_driver asic3_led_driver = {
+ 	.probe		= asic3_led_probe,
+-	.remove		= __devexit_p(asic3_led_remove),
++	.remove		= asic3_led_remove,
+ 	.driver		= {
+ 		.name	= "leds-asic3",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/leds/leds-blinkm.c b/drivers/leds/leds-blinkm.c
+index f7c3d7f1ec52..92a2c1f696f5 100644
+--- a/drivers/leds/leds-blinkm.c
++++ b/drivers/leds/leds-blinkm.c
+@@ -801,7 +801,7 @@ static struct i2c_driver blinkm_driver = {
+ 		   .name = "blinkm",
+ 		   },
+ 	.probe = blinkm_probe,
+-	.remove = __devexit_p(blinkm_remove),
++	.remove = blinkm_remove,
+ 	.id_table = blinkm_id,
+ 	.detect = blinkm_detect,
+ 	.address_list = normal_i2c,
+diff --git a/drivers/leds/leds-cobalt-qube.c b/drivers/leds/leds-cobalt-qube.c
+index 6a8725cc7b4d..cdf00652dd55 100644
+--- a/drivers/leds/leds-cobalt-qube.c
++++ b/drivers/leds/leds-cobalt-qube.c
+@@ -77,7 +77,7 @@ static int __devexit cobalt_qube_led_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver cobalt_qube_led_driver = {
+ 	.probe	= cobalt_qube_led_probe,
+-	.remove	= __devexit_p(cobalt_qube_led_remove),
++	.remove	= cobalt_qube_led_remove,
+ 	.driver	= {
+ 		.name	= "cobalt-qube-leds",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/leds/leds-cobalt-raq.c b/drivers/leds/leds-cobalt-raq.c
+index aac1c073fe7b..0894e89d43fd 100644
+--- a/drivers/leds/leds-cobalt-raq.c
++++ b/drivers/leds/leds-cobalt-raq.c
+@@ -124,7 +124,7 @@ static int __devexit cobalt_raq_led_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver cobalt_raq_led_driver = {
+ 	.probe	= cobalt_raq_led_probe,
+-	.remove	= __devexit_p(cobalt_raq_led_remove),
++	.remove	= cobalt_raq_led_remove,
+ 	.driver = {
+ 		.name	= "cobalt-raq-leds",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/leds/leds-da903x.c b/drivers/leds/leds-da903x.c
+index cc77c9d92615..de08c9312af0 100644
+--- a/drivers/leds/leds-da903x.c
++++ b/drivers/leds/leds-da903x.c
+@@ -150,7 +150,7 @@ static struct platform_driver da903x_led_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= da903x_led_probe,
+-	.remove		= __devexit_p(da903x_led_remove),
++	.remove		= da903x_led_remove,
+ };
+ 
+ module_platform_driver(da903x_led_driver);
+diff --git a/drivers/leds/leds-da9052.c b/drivers/leds/leds-da9052.c
+index 58a5244c437e..0df968cf0599 100644
+--- a/drivers/leds/leds-da9052.c
++++ b/drivers/leds/leds-da9052.c
+@@ -204,7 +204,7 @@ static struct platform_driver da9052_led_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= da9052_led_probe,
+-	.remove		= __devexit_p(da9052_led_remove),
++	.remove		= da9052_led_remove,
+ };
+ 
+ module_platform_driver(da9052_led_driver);
+diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
+index 087d1e66f4f7..51bc51311de0 100644
+--- a/drivers/leds/leds-gpio.c
++++ b/drivers/leds/leds-gpio.c
+@@ -288,7 +288,7 @@ static int __devexit gpio_led_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver gpio_led_driver = {
+ 	.probe		= gpio_led_probe,
+-	.remove		= __devexit_p(gpio_led_remove),
++	.remove		= gpio_led_remove,
+ 	.driver		= {
+ 		.name	= "leds-gpio",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c
+index b26306f6724d..5ac59e1f3334 100644
+--- a/drivers/leds/leds-lm3530.c
++++ b/drivers/leds/leds-lm3530.c
+@@ -472,7 +472,7 @@ MODULE_DEVICE_TABLE(i2c, lm3530_id);
+ 
+ static struct i2c_driver lm3530_i2c_driver = {
+ 	.probe = lm3530_probe,
+-	.remove = __devexit_p(lm3530_remove),
++	.remove = lm3530_remove,
+ 	.id_table = lm3530_id,
+ 	.driver = {
+ 		.name = LM3530_NAME,
+diff --git a/drivers/leds/leds-lm3533.c b/drivers/leds/leds-lm3533.c
+index f6837b99908c..be246bf32e2d 100644
+--- a/drivers/leds/leds-lm3533.c
++++ b/drivers/leds/leds-lm3533.c
+@@ -774,7 +774,7 @@ static struct platform_driver lm3533_led_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe		= lm3533_led_probe,
+-	.remove		= __devexit_p(lm3533_led_remove),
++	.remove		= lm3533_led_remove,
+ 	.shutdown	= lm3533_led_shutdown,
+ };
+ module_platform_driver(lm3533_led_driver);
+diff --git a/drivers/leds/leds-lm355x.c b/drivers/leds/leds-lm355x.c
+index 065ec015d67a..307d7b960809 100644
+--- a/drivers/leds/leds-lm355x.c
++++ b/drivers/leds/leds-lm355x.c
+@@ -560,7 +560,7 @@ static struct i2c_driver lm355x_i2c_driver = {
+ 		   .pm = NULL,
+ 		   },
+ 	.probe = lm355x_probe,
+-	.remove = __devexit_p(lm355x_remove),
++	.remove = lm355x_remove,
+ 	.id_table = lm355x_id,
+ };
+ 
+diff --git a/drivers/leds/leds-lm3642.c b/drivers/leds/leds-lm3642.c
+index 3285006e9888..cae0b7017cbb 100644
+--- a/drivers/leds/leds-lm3642.c
++++ b/drivers/leds/leds-lm3642.c
+@@ -450,7 +450,7 @@ static struct i2c_driver lm3642_i2c_driver = {
+ 		   .pm = NULL,
+ 		   },
+ 	.probe = lm3642_probe,
+-	.remove = __devexit_p(lm3642_remove),
++	.remove = lm3642_remove,
+ 	.id_table = lm3642_id,
+ };
+ 
+diff --git a/drivers/leds/leds-lp3944.c b/drivers/leds/leds-lp3944.c
+index c298f7d9f535..aa74b797a2fa 100644
+--- a/drivers/leds/leds-lp3944.c
++++ b/drivers/leds/leds-lp3944.c
+@@ -446,7 +446,7 @@ static struct i2c_driver lp3944_driver = {
+ 		   .name = "lp3944",
+ 	},
+ 	.probe    = lp3944_probe,
+-	.remove   = __devexit_p(lp3944_remove),
++	.remove   = lp3944_remove,
+ 	.id_table = lp3944_id,
+ };
+ 
+diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c
+index 2064aefedc07..d633ecf58687 100644
+--- a/drivers/leds/leds-lp5521.c
++++ b/drivers/leds/leds-lp5521.c
+@@ -886,7 +886,7 @@ static struct i2c_driver lp5521_driver = {
+ 		.name	= "lp5521",
+ 	},
+ 	.probe		= lp5521_probe,
+-	.remove		= __devexit_p(lp5521_remove),
++	.remove		= lp5521_remove,
+ 	.id_table	= lp5521_id,
+ };
+ 
+diff --git a/drivers/leds/leds-lp8788.c b/drivers/leds/leds-lp8788.c
+index 64009a176651..fbcfc1b821f8 100644
+--- a/drivers/leds/leds-lp8788.c
++++ b/drivers/leds/leds-lp8788.c
+@@ -179,7 +179,7 @@ static int __devexit lp8788_led_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver lp8788_led_driver = {
+ 	.probe = lp8788_led_probe,
+-	.remove = __devexit_p(lp8788_led_remove),
++	.remove = lp8788_led_remove,
+ 	.driver = {
+ 		.name = LP8788_DEV_KEYLED,
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c
+index 09a732217f6d..40657420cfc5 100644
+--- a/drivers/leds/leds-lt3593.c
++++ b/drivers/leds/leds-lt3593.c
+@@ -189,7 +189,7 @@ static int __devexit lt3593_led_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver lt3593_led_driver = {
+ 	.probe		= lt3593_led_probe,
+-	.remove		= __devexit_p(lt3593_led_remove),
++	.remove		= lt3593_led_remove,
+ 	.driver		= {
+ 		.name	= "leds-lt3593",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/leds/leds-max8997.c b/drivers/leds/leds-max8997.c
+index 569e36de37df..b11a5a72bc3e 100644
+--- a/drivers/leds/leds-max8997.c
++++ b/drivers/leds/leds-max8997.c
+@@ -308,7 +308,7 @@ static struct platform_driver max8997_led_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe  = max8997_led_probe,
+-	.remove = __devexit_p(max8997_led_remove),
++	.remove = max8997_led_remove,
+ };
+ 
+ module_platform_driver(max8997_led_driver);
+diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c
+index 2a5d43400677..e760b0754ff1 100644
+--- a/drivers/leds/leds-mc13783.c
++++ b/drivers/leds/leds-mc13783.c
+@@ -381,7 +381,7 @@ static struct platform_driver mc13783_led_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= mc13783_led_probe,
+-	.remove		= __devexit_p(mc13783_led_remove),
++	.remove		= mc13783_led_remove,
+ };
+ 
+ module_platform_driver(mc13783_led_driver);
+diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c
+index 461bbf9b33fa..b3c0377b51fb 100644
+--- a/drivers/leds/leds-netxbig.c
++++ b/drivers/leds/leds-netxbig.c
+@@ -407,7 +407,7 @@ static int __devexit netxbig_led_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver netxbig_led_driver = {
+ 	.probe		= netxbig_led_probe,
+-	.remove		= __devexit_p(netxbig_led_remove),
++	.remove		= netxbig_led_remove,
+ 	.driver		= {
+ 		.name	= "leds-netxbig",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c
+index d176ec83f5d9..89c8b47b4794 100644
+--- a/drivers/leds/leds-ns2.c
++++ b/drivers/leds/leds-ns2.c
+@@ -310,7 +310,7 @@ static int __devexit ns2_led_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver ns2_led_driver = {
+ 	.probe		= ns2_led_probe,
+-	.remove		= __devexit_p(ns2_led_remove),
++	.remove		= ns2_led_remove,
+ 	.driver		= {
+ 		.name	= "leds-ns2",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/leds/leds-ot200.c b/drivers/leds/leds-ot200.c
+index c4646825a620..925217890677 100644
+--- a/drivers/leds/leds-ot200.c
++++ b/drivers/leds/leds-ot200.c
+@@ -156,7 +156,7 @@ static int __devexit ot200_led_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver ot200_led_driver = {
+ 	.probe		= ot200_led_probe,
+-	.remove		= __devexit_p(ot200_led_remove),
++	.remove		= ot200_led_remove,
+ 	.driver		= {
+ 		.name	= "leds-ot200",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
+index aef3cf0432fe..12506e74a4c5 100644
+--- a/drivers/leds/leds-pca955x.c
++++ b/drivers/leds/leds-pca955x.c
+@@ -382,7 +382,7 @@ static struct i2c_driver pca955x_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe	= pca955x_probe,
+-	.remove	= __devexit_p(pca955x_remove),
++	.remove	= pca955x_remove,
+ 	.id_table = pca955x_id,
+ };
+ 
+diff --git a/drivers/leds/leds-pca9633.c b/drivers/leds/leds-pca9633.c
+index 2f2f9c43535d..0685f343ff18 100644
+--- a/drivers/leds/leds-pca9633.c
++++ b/drivers/leds/leds-pca9633.c
+@@ -183,7 +183,7 @@ static struct i2c_driver pca9633_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe	= pca9633_probe,
+-	.remove	= __devexit_p(pca9633_remove),
++	.remove	= pca9633_remove,
+ 	.id_table = pca9633_id,
+ };
+ 
+diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
+index f2e44c719437..7a988f18522a 100644
+--- a/drivers/leds/leds-pwm.c
++++ b/drivers/leds/leds-pwm.c
+@@ -125,7 +125,7 @@ static int __devexit led_pwm_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver led_pwm_driver = {
+ 	.probe		= led_pwm_probe,
+-	.remove		= __devexit_p(led_pwm_remove),
++	.remove		= led_pwm_remove,
+ 	.driver		= {
+ 		.name	= "leds_pwm",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/leds/leds-rb532.c b/drivers/leds/leds-rb532.c
+index a7815b6cd856..e34f1ff4e8ce 100644
+--- a/drivers/leds/leds-rb532.c
++++ b/drivers/leds/leds-rb532.c
+@@ -50,7 +50,7 @@ static int __devexit rb532_led_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver rb532_led_driver = {
+ 	.probe = rb532_led_probe,
+-	.remove = __devexit_p(rb532_led_remove),
++	.remove = rb532_led_remove,
+ 	.driver = {
+ 		.name = "rb532-led",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/leds/leds-regulator.c b/drivers/leds/leds-regulator.c
+index 25d382d60fa9..521af9b4e299 100644
+--- a/drivers/leds/leds-regulator.c
++++ b/drivers/leds/leds-regulator.c
+@@ -223,7 +223,7 @@ static struct platform_driver regulator_led_driver = {
+ 		   .owner = THIS_MODULE,
+ 		   },
+ 	.probe  = regulator_led_probe,
+-	.remove = __devexit_p(regulator_led_remove),
++	.remove = regulator_led_remove,
+ };
+ 
+ module_platform_driver(regulator_led_driver);
+diff --git a/drivers/leds/leds-renesas-tpu.c b/drivers/leds/leds-renesas-tpu.c
+index 771ea067e680..71cab56a67aa 100644
+--- a/drivers/leds/leds-renesas-tpu.c
++++ b/drivers/leds/leds-renesas-tpu.c
+@@ -328,7 +328,7 @@ static int __devexit r_tpu_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver r_tpu_device_driver = {
+ 	.probe		= r_tpu_probe,
+-	.remove		= __devexit_p(r_tpu_remove),
++	.remove		= r_tpu_remove,
+ 	.driver		= {
+ 		.name	= "leds-renesas-tpu",
+ 	}
+diff --git a/drivers/leds/leds-sunfire.c b/drivers/leds/leds-sunfire.c
+index 134d9a4b34f1..3d35c5861146 100644
+--- a/drivers/leds/leds-sunfire.c
++++ b/drivers/leds/leds-sunfire.c
+@@ -223,7 +223,7 @@ MODULE_ALIAS("platform:sunfire-fhc-leds");
+ 
+ static struct platform_driver sunfire_clockboard_led_driver = {
+ 	.probe		= sunfire_clockboard_led_probe,
+-	.remove		= __devexit_p(sunfire_led_generic_remove),
++	.remove		= sunfire_led_generic_remove,
+ 	.driver		= {
+ 		.name	= "sunfire-clockboard-leds",
+ 		.owner	= THIS_MODULE,
+@@ -232,7 +232,7 @@ static struct platform_driver sunfire_clockboard_led_driver = {
+ 
+ static struct platform_driver sunfire_fhc_led_driver = {
+ 	.probe		= sunfire_fhc_led_probe,
+-	.remove		= __devexit_p(sunfire_led_generic_remove),
++	.remove		= sunfire_led_generic_remove,
+ 	.driver		= {
+ 		.name	= "sunfire-fhc-leds",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/leds/leds-tca6507.c b/drivers/leds/leds-tca6507.c
+index dabcf7ae8d0f..1172b4a264e8 100644
+--- a/drivers/leds/leds-tca6507.c
++++ b/drivers/leds/leds-tca6507.c
+@@ -752,7 +752,7 @@ static struct i2c_driver tca6507_driver = {
+ 		.owner   = THIS_MODULE,
+ 	},
+ 	.probe    = tca6507_probe,
+-	.remove   = __devexit_p(tca6507_remove),
++	.remove   = tca6507_remove,
+ 	.id_table = tca6507_id,
+ };
+ 

commit 6e0ee714fdab0568c3487455951dea2673e9557f
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:03 2012 -0500
+
+    mmc: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Manuel Lauss 
+    Cc: Chris Ball 
+    Cc: "Michał Mirosław" 
+    Cc: Jarkko Lavinen 
+    Cc: Venkatraman S 
+    Cc: Viresh Kumar 
+    Cc: Ian Molton 
+    Cc: Bruce Chang 
+    Cc: Harald Welte 
+    Cc: Pierre Ossman 
+    Acked-by: Guennadi Liakhovetski 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
+index 606c16a6c639..127a8fade4da 100644
+--- a/drivers/mmc/host/au1xmmc.c
++++ b/drivers/mmc/host/au1xmmc.c
+@@ -1114,7 +1114,7 @@ static int au1xmmc_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit au1xmmc_remove(struct platform_device *pdev)
++static int au1xmmc_remove(struct platform_device *pdev)
+ {
+ 	struct au1xmmc_host *host = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c
+index 4ef3901451b4..fb4348c5b6ac 100644
+--- a/drivers/mmc/host/bfin_sdh.c
++++ b/drivers/mmc/host/bfin_sdh.c
+@@ -617,7 +617,7 @@ static int sdh_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit sdh_remove(struct platform_device *pdev)
++static int sdh_remove(struct platform_device *pdev)
+ {
+ 	struct mmc_host *mmc = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/mmc/host/cb710-mmc.c b/drivers/mmc/host/cb710-mmc.c
+index c12a5615ab9b..777ca2046b27 100644
+--- a/drivers/mmc/host/cb710-mmc.c
++++ b/drivers/mmc/host/cb710-mmc.c
+@@ -746,7 +746,7 @@ static int cb710_mmc_init(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit cb710_mmc_exit(struct platform_device *pdev)
++static int cb710_mmc_exit(struct platform_device *pdev)
+ {
+ 	struct cb710_slot *slot = cb710_pdev_to_slot(pdev);
+ 	struct mmc_host *mmc = cb710_slot_to_mmc(slot);
+diff --git a/drivers/mmc/host/dw_mmc-pci.c b/drivers/mmc/host/dw_mmc-pci.c
+index 324c8bfeb7ec..083fcd29c9c6 100644
+--- a/drivers/mmc/host/dw_mmc-pci.c
++++ b/drivers/mmc/host/dw_mmc-pci.c
+@@ -85,7 +85,7 @@ static int dw_mci_pci_probe(struct pci_dev *pdev,
+ 	return ret;
+ }
+ 
+-static void __devexit dw_mci_pci_remove(struct pci_dev *pdev)
++static void dw_mci_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct dw_mci *host = pci_get_drvdata(pdev);
+ 
+diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c
+index 867977f69841..8fd6d2cc498d 100644
+--- a/drivers/mmc/host/dw_mmc-pltfm.c
++++ b/drivers/mmc/host/dw_mmc-pltfm.c
+@@ -67,7 +67,7 @@ static int dw_mci_pltfm_probe(struct platform_device *pdev)
+ 	return dw_mci_pltfm_register(pdev, NULL);
+ }
+ 
+-static int __devexit dw_mci_pltfm_remove(struct platform_device *pdev)
++static int dw_mci_pltfm_remove(struct platform_device *pdev)
+ {
+ 	struct dw_mci *host = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/mmc/host/dw_mmc-pltfm.h b/drivers/mmc/host/dw_mmc-pltfm.h
+index 2ac37b81de4d..68e7fd2f6148 100644
+--- a/drivers/mmc/host/dw_mmc-pltfm.h
++++ b/drivers/mmc/host/dw_mmc-pltfm.h
+@@ -14,7 +14,7 @@
+ 
+ extern int dw_mci_pltfm_register(struct platform_device *pdev,
+ 				const struct dw_mci_drv_data *drv_data);
+-extern int __devexit dw_mci_pltfm_remove(struct platform_device *pdev);
++extern int dw_mci_pltfm_remove(struct platform_device *pdev);
+ extern const struct dev_pm_ops dw_mci_pltfm_pmops;
+ 
+ #endif /* _DW_MMC_PLTFM_H_ */
+diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c
+index 81826be41bc7..2391c6b7a4bb 100644
+--- a/drivers/mmc/host/jz4740_mmc.c
++++ b/drivers/mmc/host/jz4740_mmc.c
+@@ -938,7 +938,7 @@ static int jz4740_mmc_probe(struct platform_device* pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit jz4740_mmc_remove(struct platform_device *pdev)
++static int jz4740_mmc_remove(struct platform_device *pdev)
+ {
+ 	struct jz4740_mmc_host *host = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
+index 1e2256b296e8..74145d1d51f5 100644
+--- a/drivers/mmc/host/mmc_spi.c
++++ b/drivers/mmc/host/mmc_spi.c
+@@ -1485,7 +1485,7 @@ static int mmc_spi_probe(struct spi_device *spi)
+ }
+ 
+ 
+-static int __devexit mmc_spi_remove(struct spi_device *spi)
++static int mmc_spi_remove(struct spi_device *spi)
+ {
+ 	struct mmc_host		*mmc = dev_get_drvdata(&spi->dev);
+ 	struct mmc_spi_host	*host;
+diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
+index 5e3e05dfa57f..ec28d175d9c8 100644
+--- a/drivers/mmc/host/mmci.c
++++ b/drivers/mmc/host/mmci.c
+@@ -337,7 +337,7 @@ static void mmci_dma_setup(struct mmci_host *host)
+ }
+ 
+ /*
+- * This is used in or __devexit so inline it
++ * This is used in or so inline it
+  * so it can be discarded.
+  */
+ static inline void mmci_dma_release(struct mmci_host *host)
+@@ -1522,7 +1522,7 @@ static int mmci_probe(struct amba_device *dev,
+ 	return ret;
+ }
+ 
+-static int __devexit mmci_remove(struct amba_device *dev)
++static int mmci_remove(struct amba_device *dev)
+ {
+ 	struct mmc_host *mmc = amba_get_drvdata(dev);
+ 
+diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
+index e18441b63bf2..4e749ab690c8 100644
+--- a/drivers/mmc/host/omap.c
++++ b/drivers/mmc/host/omap.c
+@@ -1478,7 +1478,7 @@ static int mmc_omap_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit mmc_omap_remove(struct platform_device *pdev)
++static int mmc_omap_remove(struct platform_device *pdev)
+ {
+ 	struct mmc_omap_host *host = platform_get_drvdata(pdev);
+ 	int i;
+diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
+index 3bebdff21668..8cfcec360de1 100644
+--- a/drivers/mmc/host/omap_hsmmc.c
++++ b/drivers/mmc/host/omap_hsmmc.c
+@@ -1986,7 +1986,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit omap_hsmmc_remove(struct platform_device *pdev)
++static int omap_hsmmc_remove(struct platform_device *pdev)
+ {
+ 	struct omap_hsmmc_host *host = platform_get_drvdata(pdev);
+ 	struct resource *res;
+diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
+index b846a975408a..63fb265e0da6 100644
+--- a/drivers/mmc/host/s3cmci.c
++++ b/drivers/mmc/host/s3cmci.c
+@@ -1819,7 +1819,7 @@ static void s3cmci_shutdown(struct platform_device *pdev)
+ 	clk_disable(host->clk);
+ }
+ 
+-static int __devexit s3cmci_remove(struct platform_device *pdev)
++static int s3cmci_remove(struct platform_device *pdev)
+ {
+ 	struct mmc_host		*mmc  = platform_get_drvdata(pdev);
+ 	struct s3cmci_host	*host = mmc_priv(mmc);
+diff --git a/drivers/mmc/host/sdhci-cns3xxx.c b/drivers/mmc/host/sdhci-cns3xxx.c
+index ce959dcfa7b2..30bfdc4ae52a 100644
+--- a/drivers/mmc/host/sdhci-cns3xxx.c
++++ b/drivers/mmc/host/sdhci-cns3xxx.c
+@@ -100,7 +100,7 @@ static int sdhci_cns3xxx_probe(struct platform_device *pdev)
+ 	return sdhci_pltfm_register(pdev, &sdhci_cns3xxx_pdata);
+ }
+ 
+-static int __devexit sdhci_cns3xxx_remove(struct platform_device *pdev)
++static int sdhci_cns3xxx_remove(struct platform_device *pdev)
+ {
+ 	return sdhci_pltfm_unregister(pdev);
+ }
+diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c
+index 73c0eb8a091d..5f4d0331a91f 100644
+--- a/drivers/mmc/host/sdhci-dove.c
++++ b/drivers/mmc/host/sdhci-dove.c
+@@ -114,7 +114,7 @@ static int sdhci_dove_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit sdhci_dove_remove(struct platform_device *pdev)
++static int sdhci_dove_remove(struct platform_device *pdev)
+ {
+ 	struct sdhci_host *host = platform_get_drvdata(pdev);
+ 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
+index cd741bbde505..8d54fd7b9d37 100644
+--- a/drivers/mmc/host/sdhci-esdhc-imx.c
++++ b/drivers/mmc/host/sdhci-esdhc-imx.c
+@@ -599,7 +599,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev)
++static int sdhci_esdhc_imx_remove(struct platform_device *pdev)
+ {
+ 	struct sdhci_host *host = platform_get_drvdata(pdev);
+ 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
+index 1aceed7d5a60..6617d6750a71 100644
+--- a/drivers/mmc/host/sdhci-of-esdhc.c
++++ b/drivers/mmc/host/sdhci-of-esdhc.c
+@@ -213,7 +213,7 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)
+ 	return sdhci_pltfm_register(pdev, &sdhci_esdhc_pdata);
+ }
+ 
+-static int __devexit sdhci_esdhc_remove(struct platform_device *pdev)
++static int sdhci_esdhc_remove(struct platform_device *pdev)
+ {
+ 	return sdhci_pltfm_unregister(pdev);
+ }
+diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c
+index aa78f3c27164..c3d3715ec3d7 100644
+--- a/drivers/mmc/host/sdhci-of-hlwd.c
++++ b/drivers/mmc/host/sdhci-of-hlwd.c
+@@ -71,7 +71,7 @@ static int sdhci_hlwd_probe(struct platform_device *pdev)
+ 	return sdhci_pltfm_register(pdev, &sdhci_hlwd_pdata);
+ }
+ 
+-static int __devexit sdhci_hlwd_remove(struct platform_device *pdev)
++static int sdhci_hlwd_remove(struct platform_device *pdev)
+ {
+ 	return sdhci_pltfm_unregister(pdev);
+ }
+diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
+index 38447710a1ef..d01aa610391f 100644
+--- a/drivers/mmc/host/sdhci-pci.c
++++ b/drivers/mmc/host/sdhci-pci.c
+@@ -1347,7 +1347,7 @@ static void sdhci_pci_runtime_pm_allow(struct device *dev)
+ 	pm_suspend_ignore_children(dev, 1);
+ }
+ 
+-static void __devexit sdhci_pci_runtime_pm_forbid(struct device *dev)
++static void sdhci_pci_runtime_pm_forbid(struct device *dev)
+ {
+ 	pm_runtime_forbid(dev);
+ 	pm_runtime_get_noresume(dev);
+@@ -1445,7 +1445,7 @@ static int sdhci_pci_probe(struct pci_dev *pdev,
+ 	return ret;
+ }
+ 
+-static void __devexit sdhci_pci_remove(struct pci_dev *pdev)
++static void sdhci_pci_remove(struct pci_dev *pdev)
+ {
+ 	int i;
+ 	struct sdhci_pci_chip *chip;
+diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c
+index 7d4dc1946312..ac854aa192a8 100644
+--- a/drivers/mmc/host/sdhci-pxav2.c
++++ b/drivers/mmc/host/sdhci-pxav2.c
+@@ -247,7 +247,7 @@ static int sdhci_pxav2_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit sdhci_pxav2_remove(struct platform_device *pdev)
++static int sdhci_pxav2_remove(struct platform_device *pdev)
+ {
+ 	struct sdhci_host *host = platform_get_drvdata(pdev);
+ 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c
+index e89c80901f30..186dfc36e473 100644
+--- a/drivers/mmc/host/sdhci-pxav3.c
++++ b/drivers/mmc/host/sdhci-pxav3.c
+@@ -313,7 +313,7 @@ static int sdhci_pxav3_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit sdhci_pxav3_remove(struct platform_device *pdev)
++static int sdhci_pxav3_remove(struct platform_device *pdev)
+ {
+ 	struct sdhci_host *host = platform_get_drvdata(pdev);
+ 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
+index f5dde9eb7989..fe21ed428c3d 100644
+--- a/drivers/mmc/host/sdhci-s3c.c
++++ b/drivers/mmc/host/sdhci-s3c.c
+@@ -778,7 +778,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
++static int sdhci_s3c_remove(struct platform_device *pdev)
+ {
+ 	struct sdhci_host *host =  platform_get_drvdata(pdev);
+ 	struct sdhci_s3c *sc = sdhci_priv(host);
+diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c
+index 3fd18964145a..df2379a340f1 100644
+--- a/drivers/mmc/host/sdhci-spear.c
++++ b/drivers/mmc/host/sdhci-spear.c
+@@ -266,7 +266,7 @@ static int sdhci_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit sdhci_remove(struct platform_device *pdev)
++static int sdhci_remove(struct platform_device *pdev)
+ {
+ 	struct sdhci_host *host = platform_get_drvdata(pdev);
+ 	struct spear_sdhci *sdhci = dev_get_platdata(&pdev->dev);
+diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
+index d3936d0e3360..3695b2e0cbd2 100644
+--- a/drivers/mmc/host/sdhci-tegra.c
++++ b/drivers/mmc/host/sdhci-tegra.c
+@@ -370,7 +370,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
+ 	return rc;
+ }
+ 
+-static int __devexit sdhci_tegra_remove(struct platform_device *pdev)
++static int sdhci_tegra_remove(struct platform_device *pdev)
+ {
+ 	struct sdhci_host *host = platform_get_drvdata(pdev);
+ 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
+index 9872b52332f8..9b8efac896a8 100644
+--- a/drivers/mmc/host/sh_mmcif.c
++++ b/drivers/mmc/host/sh_mmcif.c
+@@ -1430,7 +1430,7 @@ static int sh_mmcif_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit sh_mmcif_remove(struct platform_device *pdev)
++static int sh_mmcif_remove(struct platform_device *pdev)
+ {
+ 	struct sh_mmcif_host *host = platform_get_drvdata(pdev);
+ 	struct sh_mmcif_plat_data *pd = pdev->dev.platform_data;
+diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
+index f415be885654..139212e79cde 100644
+--- a/drivers/mmc/host/tmio_mmc.c
++++ b/drivers/mmc/host/tmio_mmc.c
+@@ -107,7 +107,7 @@ static int tmio_mmc_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit tmio_mmc_remove(struct platform_device *pdev)
++static int tmio_mmc_remove(struct platform_device *pdev)
+ {
+ 	const struct mfd_cell *cell = mfd_get_cell(pdev);
+ 	struct mmc_host *mmc = platform_get_drvdata(pdev);
+diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c
+index 1f1a252184a7..4f84586c6e9e 100644
+--- a/drivers/mmc/host/via-sdmmc.c
++++ b/drivers/mmc/host/via-sdmmc.c
+@@ -1176,7 +1176,7 @@ static int via_sd_probe(struct pci_dev *pcidev,
+ 	return ret;
+ }
+ 
+-static void __devexit via_sd_remove(struct pci_dev *pcidev)
++static void via_sd_remove(struct pci_dev *pcidev)
+ {
+ 	struct via_crdr_mmc_host *sdhost = pci_get_drvdata(pcidev);
+ 	unsigned long flags;
+diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c
+index d71358a2695d..e954b7758876 100644
+--- a/drivers/mmc/host/wbsd.c
++++ b/drivers/mmc/host/wbsd.c
+@@ -1735,7 +1735,7 @@ static int wbsd_init(struct device *dev, int base, int irq, int dma,
+ 	return 0;
+ }
+ 
+-static void __devexit wbsd_shutdown(struct device *dev, int pnp)
++static void wbsd_shutdown(struct device *dev, int pnp)
+ {
+ 	struct mmc_host *mmc = dev_get_drvdata(dev);
+ 	struct wbsd_host *host;
+@@ -1768,7 +1768,7 @@ static int wbsd_probe(struct platform_device *dev)
+ 	return wbsd_init(&dev->dev, param_io, param_irq, param_dma, 0);
+ }
+ 
+-static int __devexit wbsd_remove(struct platform_device *dev)
++static int wbsd_remove(struct platform_device *dev)
+ {
+ 	wbsd_shutdown(&dev->dev, 0);
+ 
+@@ -1801,7 +1801,7 @@ wbsd_pnp_probe(struct pnp_dev *pnpdev, const struct pnp_device_id *dev_id)
+ 	return wbsd_init(&pnpdev->dev, io, irq, dma, 1);
+ }
+ 
+-static void __devexit wbsd_pnp_remove(struct pnp_dev *dev)
++static void wbsd_pnp_remove(struct pnp_dev *dev)
+ {
+ 	wbsd_shutdown(&dev->dev, 1);
+ }

commit 9647f84deeefcba8b9be22e1f1305eda88851635
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:25:11 2012 -0500
+
+    mmc: remove use of __devinitconst
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitconst is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Chris Ball 
+    Cc: linux-mmc@vger.kernel.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
+index ff9165178325..38447710a1ef 100644
+--- a/drivers/mmc/host/sdhci-pci.c
++++ b/drivers/mmc/host/sdhci-pci.c
+@@ -653,7 +653,7 @@ static const struct sdhci_pci_fixes sdhci_via = {
+ 	.probe		= via_probe,
+ };
+ 
+-static const struct pci_device_id pci_ids[] __devinitconst = {
++static const struct pci_device_id pci_ids[] = {
+ 	{
+ 		.vendor		= PCI_VENDOR_ID_RICOH,
+ 		.device		= PCI_DEVICE_ID_RICOH_R5C822,

commit 498d83e732809d9e9caaef700743c7bc1a7c1462
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:24:22 2012 -0500
+
+    mmc: remove use of __devinitdata
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitdata is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Chris Ball 
+    Cc: Grant Likely 
+    Cc: Rob Herring 
+    Cc: linux-mmc@vger.kernel.org
+    Cc: devicetree-discuss@lists.ozlabs.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
+index f7df7982ba11..1e2256b296e8 100644
+--- a/drivers/mmc/host/mmc_spi.c
++++ b/drivers/mmc/host/mmc_spi.c
+@@ -1517,7 +1517,7 @@ static int __devexit mmc_spi_remove(struct spi_device *spi)
+ 	return 0;
+ }
+ 
+-static struct of_device_id mmc_spi_of_match_table[] __devinitdata = {
++static struct of_device_id mmc_spi_of_match_table[] = {
+ 	{ .compatible = "mmc-spi-slot", },
+ 	{},
+ };
+diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c
+index 334ec5cd98a4..73c0eb8a091d 100644
+--- a/drivers/mmc/host/sdhci-dove.c
++++ b/drivers/mmc/host/sdhci-dove.c
+@@ -129,7 +129,7 @@ static int __devexit sdhci_dove_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static const struct of_device_id sdhci_dove_of_match_table[] __devinitdata = {
++static const struct of_device_id sdhci_dove_of_match_table[] = {
+ 	{ .compatible = "marvell,dove-sdhci", },
+ 	{}
+ };
+diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
+index 339c41e24d87..d3936d0e3360 100644
+--- a/drivers/mmc/host/sdhci-tegra.c
++++ b/drivers/mmc/host/sdhci-tegra.c
+@@ -206,7 +206,7 @@ static struct sdhci_tegra_soc_data soc_data_tegra30 = {
+ };
+ #endif
+ 
+-static const struct of_device_id sdhci_tegra_dt_match[] __devinitdata = {
++static const struct of_device_id sdhci_tegra_dt_match[] = {
+ #ifdef CONFIG_ARCH_TEGRA_3x_SOC
+ 	{ .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 },
+ #endif

commit c3be1efd41a97f93be390240387d356a07b664c7
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:23:06 2012 -0500
+
+    mmc: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Chris Ball 
+    Cc: Manuel Lauss 
+    Cc: "Michał Mirosław" 
+    Cc: Jarkko Lavinen 
+    Cc: Venkatraman S 
+    Cc: Ian Molton 
+    Cc: Bruce Chang 
+    Cc: Harald Welte 
+    Cc: Pierre Ossman 
+    Acked-by: Ludovic Desroches 
+    Acked-by: Viresh Kumar 
+    Acked-by: Guennadi Liakhovetski 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
+index ddf096e3803f..5248ba4369a3 100644
+--- a/drivers/mmc/host/atmel-mci.c
++++ b/drivers/mmc/host/atmel-mci.c
+@@ -511,7 +511,7 @@ static const struct of_device_id atmci_dt_ids[] = {
+ 
+ MODULE_DEVICE_TABLE(of, atmci_dt_ids);
+ 
+-static struct mci_platform_data __devinit*
++static struct mci_platform_data*
+ atmci_of_init(struct platform_device *pdev)
+ {
+ 	struct device_node *np = pdev->dev.of_node;
+diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
+index dbd0c8a4e98a..606c16a6c639 100644
+--- a/drivers/mmc/host/au1xmmc.c
++++ b/drivers/mmc/host/au1xmmc.c
+@@ -943,7 +943,7 @@ static const struct mmc_host_ops au1xmmc_ops = {
+ 	.enable_sdio_irq = au1xmmc_enable_sdio_irq,
+ };
+ 
+-static int __devinit au1xmmc_probe(struct platform_device *pdev)
++static int au1xmmc_probe(struct platform_device *pdev)
+ {
+ 	struct mmc_host *mmc;
+ 	struct au1xmmc_host *host;
+diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c
+index 156ebe7d6fd0..4ef3901451b4 100644
+--- a/drivers/mmc/host/bfin_sdh.c
++++ b/drivers/mmc/host/bfin_sdh.c
+@@ -522,7 +522,7 @@ static void sdh_reset(void)
+ 	SSYNC();
+ }
+ 
+-static int __devinit sdh_probe(struct platform_device *pdev)
++static int sdh_probe(struct platform_device *pdev)
+ {
+ 	struct mmc_host *mmc;
+ 	struct sdh_host *host;
+diff --git a/drivers/mmc/host/cb710-mmc.c b/drivers/mmc/host/cb710-mmc.c
+index 39280b5756e8..c12a5615ab9b 100644
+--- a/drivers/mmc/host/cb710-mmc.c
++++ b/drivers/mmc/host/cb710-mmc.c
+@@ -690,7 +690,7 @@ static int cb710_mmc_resume(struct platform_device *pdev)
+ 
+ #endif /* CONFIG_PM */
+ 
+-static int __devinit cb710_mmc_init(struct platform_device *pdev)
++static int cb710_mmc_init(struct platform_device *pdev)
+ {
+ 	struct cb710_slot *slot = cb710_pdev_to_slot(pdev);
+ 	struct cb710_chip *chip = cb710_slot_to_chip(slot);
+diff --git a/drivers/mmc/host/dw_mmc-pci.c b/drivers/mmc/host/dw_mmc-pci.c
+index edb37e9135ae..324c8bfeb7ec 100644
+--- a/drivers/mmc/host/dw_mmc-pci.c
++++ b/drivers/mmc/host/dw_mmc-pci.c
+@@ -37,7 +37,7 @@ static struct dw_mci_board pci_board_data = {
+ 	.fifo_depth			= 32,
+ };
+ 
+-static int __devinit dw_mci_pci_probe(struct pci_dev *pdev,
++static int dw_mci_pci_probe(struct pci_dev *pdev,
+ 				  const struct pci_device_id *entries)
+ {
+ 	struct dw_mci *host;
+diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c
+index 917936bee5d5..867977f69841 100644
+--- a/drivers/mmc/host/dw_mmc-pltfm.c
++++ b/drivers/mmc/host/dw_mmc-pltfm.c
+@@ -62,7 +62,7 @@ int dw_mci_pltfm_register(struct platform_device *pdev,
+ }
+ EXPORT_SYMBOL_GPL(dw_mci_pltfm_register);
+ 
+-static int __devinit dw_mci_pltfm_probe(struct platform_device *pdev)
++static int dw_mci_pltfm_probe(struct platform_device *pdev)
+ {
+ 	return dw_mci_pltfm_register(pdev, NULL);
+ }
+diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c
+index 31cf20f0eaaa..81826be41bc7 100644
+--- a/drivers/mmc/host/jz4740_mmc.c
++++ b/drivers/mmc/host/jz4740_mmc.c
+@@ -702,7 +702,7 @@ static const struct jz_gpio_bulk_request jz4740_mmc_pins[] = {
+ 	JZ_GPIO_BULK_PIN(MSC_DATA3),
+ };
+ 
+-static int __devinit jz4740_mmc_request_gpio(struct device *dev, int gpio,
++static int jz4740_mmc_request_gpio(struct device *dev, int gpio,
+ 	const char *name, bool output, int value)
+ {
+ 	int ret;
+@@ -724,7 +724,7 @@ static int __devinit jz4740_mmc_request_gpio(struct device *dev, int gpio,
+ 	return 0;
+ }
+ 
+-static int __devinit jz4740_mmc_request_gpios(struct platform_device *pdev)
++static int jz4740_mmc_request_gpios(struct platform_device *pdev)
+ {
+ 	int ret;
+ 	struct jz4740_mmc_platform_data *pdata = pdev->dev.platform_data;
+@@ -759,7 +759,7 @@ static int __devinit jz4740_mmc_request_gpios(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devinit jz4740_mmc_request_cd_irq(struct platform_device *pdev,
++static int jz4740_mmc_request_cd_irq(struct platform_device *pdev,
+ 	struct jz4740_mmc_host *host)
+ {
+ 	struct jz4740_mmc_platform_data *pdata = pdev->dev.platform_data;
+@@ -802,7 +802,7 @@ static inline size_t jz4740_mmc_num_pins(struct jz4740_mmc_host *host)
+ 	return num_pins;
+ }
+ 
+-static int __devinit jz4740_mmc_probe(struct platform_device* pdev)
++static int jz4740_mmc_probe(struct platform_device* pdev)
+ {
+ 	int ret;
+ 	struct mmc_host *mmc;
+diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
+index 3ca6757fbebd..5e3e05dfa57f 100644
+--- a/drivers/mmc/host/mmci.c
++++ b/drivers/mmc/host/mmci.c
+@@ -261,7 +261,7 @@ static void mmci_init_sg(struct mmci_host *host, struct mmc_data *data)
+  * no custom DMA interfaces are supported.
+  */
+ #ifdef CONFIG_DMA_ENGINE
+-static void __devinit mmci_dma_setup(struct mmci_host *host)
++static void mmci_dma_setup(struct mmci_host *host)
+ {
+ 	struct mmci_platform_data *plat = host->plat;
+ 	const char *rxname, *txname;
+@@ -337,7 +337,7 @@ static void __devinit mmci_dma_setup(struct mmci_host *host)
+ }
+ 
+ /*
+- * This is used in __devinit or __devexit so inline it
++ * This is used in or __devexit so inline it
+  * so it can be discarded.
+  */
+ static inline void mmci_dma_release(struct mmci_host *host)
+@@ -1255,7 +1255,7 @@ static void mmci_dt_populate_generic_pdata(struct device_node *np,
+ }
+ #endif
+ 
+-static int __devinit mmci_probe(struct amba_device *dev,
++static int mmci_probe(struct amba_device *dev,
+ 	const struct amba_id *id)
+ {
+ 	struct mmci_platform_data *plat = dev->dev.platform_data;
+diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
+index 3531a193d8d5..e18441b63bf2 100644
+--- a/drivers/mmc/host/omap.c
++++ b/drivers/mmc/host/omap.c
+@@ -1214,7 +1214,7 @@ static const struct mmc_host_ops mmc_omap_ops = {
+ 	.set_ios	= mmc_omap_set_ios,
+ };
+ 
+-static int __devinit mmc_omap_new_slot(struct mmc_omap_host *host, int id)
++static int mmc_omap_new_slot(struct mmc_omap_host *host, int id)
+ {
+ 	struct mmc_omap_slot *slot = NULL;
+ 	struct mmc_host *mmc;
+@@ -1309,7 +1309,7 @@ static void mmc_omap_remove_slot(struct mmc_omap_slot *slot)
+ 	mmc_free_host(mmc);
+ }
+ 
+-static int __devinit mmc_omap_probe(struct platform_device *pdev)
++static int mmc_omap_probe(struct platform_device *pdev)
+ {
+ 	struct omap_mmc_platform_data *pdata = pdev->dev.platform_data;
+ 	struct mmc_omap_host *host = NULL;
+diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
+index 58b4cf0f79a9..3bebdff21668 100644
+--- a/drivers/mmc/host/omap_hsmmc.c
++++ b/drivers/mmc/host/omap_hsmmc.c
+@@ -1715,7 +1715,7 @@ static inline struct omap_mmc_platform_data
+ }
+ #endif
+ 
+-static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
++static int omap_hsmmc_probe(struct platform_device *pdev)
+ {
+ 	struct omap_mmc_platform_data *pdata = pdev->dev.platform_data;
+ 	struct mmc_host *mmc;
+diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
+index 3f9d6d577a91..2b2f65ada22e 100644
+--- a/drivers/mmc/host/pxamci.c
++++ b/drivers/mmc/host/pxamci.c
+@@ -584,7 +584,7 @@ static const struct of_device_id pxa_mmc_dt_ids[] = {
+ 
+ MODULE_DEVICE_TABLE(of, pxa_mmc_dt_ids);
+ 
+-static int __devinit pxamci_of_init(struct platform_device *pdev)
++static int pxamci_of_init(struct platform_device *pdev)
+ {
+         struct device_node *np = pdev->dev.of_node;
+         struct pxamci_platform_data *pdata;
+@@ -614,7 +614,7 @@ static int __devinit pxamci_of_init(struct platform_device *pdev)
+         return 0;
+ }
+ #else
+-static int __devinit pxamci_of_init(struct platform_device *pdev)
++static int pxamci_of_init(struct platform_device *pdev)
+ {
+         return 0;
+ }
+diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
+index a5fe5b243680..b846a975408a 100644
+--- a/drivers/mmc/host/s3cmci.c
++++ b/drivers/mmc/host/s3cmci.c
+@@ -1540,7 +1540,7 @@ static inline void s3cmci_debugfs_remove(struct s3cmci_host *host) { }
+ 
+ #endif /* CONFIG_DEBUG_FS */
+ 
+-static int __devinit s3cmci_probe(struct platform_device *pdev)
++static int s3cmci_probe(struct platform_device *pdev)
+ {
+ 	struct s3cmci_host *host;
+ 	struct mmc_host	*mmc;
+diff --git a/drivers/mmc/host/sdhci-cns3xxx.c b/drivers/mmc/host/sdhci-cns3xxx.c
+index 9236fa9d504c..ce959dcfa7b2 100644
+--- a/drivers/mmc/host/sdhci-cns3xxx.c
++++ b/drivers/mmc/host/sdhci-cns3xxx.c
+@@ -95,7 +95,7 @@ static struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
+ 		  SDHCI_QUIRK_NONSTANDARD_CLOCK,
+ };
+ 
+-static int __devinit sdhci_cns3xxx_probe(struct platform_device *pdev)
++static int sdhci_cns3xxx_probe(struct platform_device *pdev)
+ {
+ 	return sdhci_pltfm_register(pdev, &sdhci_cns3xxx_pdata);
+ }
+diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c
+index 7ad1bb6cf6a0..334ec5cd98a4 100644
+--- a/drivers/mmc/host/sdhci-dove.c
++++ b/drivers/mmc/host/sdhci-dove.c
+@@ -78,7 +78,7 @@ static struct sdhci_pltfm_data sdhci_dove_pdata = {
+ 		  SDHCI_QUIRK_NO_HISPD_BIT,
+ };
+ 
+-static int __devinit sdhci_dove_probe(struct platform_device *pdev)
++static int sdhci_dove_probe(struct platform_device *pdev)
+ {
+ 	struct sdhci_host *host;
+ 	struct sdhci_pltfm_host *pltfm_host;
+diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
+index 6a4e98e60009..cd741bbde505 100644
+--- a/drivers/mmc/host/sdhci-esdhc-imx.c
++++ b/drivers/mmc/host/sdhci-esdhc-imx.c
+@@ -403,7 +403,7 @@ static irqreturn_t cd_irq(int irq, void *data)
+ };
+ 
+ #ifdef CONFIG_OF
+-static int __devinit
++static int
+ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
+ 			 struct esdhc_platform_data *boarddata)
+ {
+@@ -440,7 +440,7 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
+ }
+ #endif
+ 
+-static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
++static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
+ {
+ 	const struct of_device_id *of_id =
+ 			of_match_device(imx_esdhc_dt_ids, &pdev->dev);
+diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
+index d7eb4ed307e7..1aceed7d5a60 100644
+--- a/drivers/mmc/host/sdhci-of-esdhc.c
++++ b/drivers/mmc/host/sdhci-of-esdhc.c
+@@ -208,7 +208,7 @@ static struct sdhci_pltfm_data sdhci_esdhc_pdata = {
+ 	.ops = &sdhci_esdhc_ops,
+ };
+ 
+-static int __devinit sdhci_esdhc_probe(struct platform_device *pdev)
++static int sdhci_esdhc_probe(struct platform_device *pdev)
+ {
+ 	return sdhci_pltfm_register(pdev, &sdhci_esdhc_pdata);
+ }
+diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c
+index 3b6806902ac9..aa78f3c27164 100644
+--- a/drivers/mmc/host/sdhci-of-hlwd.c
++++ b/drivers/mmc/host/sdhci-of-hlwd.c
+@@ -66,7 +66,7 @@ static struct sdhci_pltfm_data sdhci_hlwd_pdata = {
+ 	.ops = &sdhci_hlwd_ops,
+ };
+ 
+-static int __devinit sdhci_hlwd_probe(struct platform_device *pdev)
++static int sdhci_hlwd_probe(struct platform_device *pdev)
+ {
+ 	return sdhci_pltfm_register(pdev, &sdhci_hlwd_pdata);
+ }
+diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
+index 7bc2270d9f91..ff9165178325 100644
+--- a/drivers/mmc/host/sdhci-pci.c
++++ b/drivers/mmc/host/sdhci-pci.c
+@@ -1183,7 +1183,7 @@ static const struct dev_pm_ops sdhci_pci_pm_ops = {
+  *                                                                           *
+ \*****************************************************************************/
+ 
+-static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
++static struct sdhci_pci_slot *sdhci_pci_probe_slot(
+ 	struct pci_dev *pdev, struct sdhci_pci_chip *chip, int first_bar,
+ 	int slotno)
+ {
+@@ -1338,7 +1338,7 @@ static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot)
+ 	sdhci_free_host(slot->host);
+ }
+ 
+-static void __devinit sdhci_pci_runtime_pm_allow(struct device *dev)
++static void sdhci_pci_runtime_pm_allow(struct device *dev)
+ {
+ 	pm_runtime_put_noidle(dev);
+ 	pm_runtime_allow(dev);
+@@ -1353,7 +1353,7 @@ static void __devexit sdhci_pci_runtime_pm_forbid(struct device *dev)
+ 	pm_runtime_get_noresume(dev);
+ }
+ 
+-static int __devinit sdhci_pci_probe(struct pci_dev *pdev,
++static int sdhci_pci_probe(struct pci_dev *pdev,
+ 				     const struct pci_device_id *ent)
+ {
+ 	struct sdhci_pci_chip *chip;
+diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c
+index 964fc6d0a81a..7d4dc1946312 100644
+--- a/drivers/mmc/host/sdhci-pxav2.c
++++ b/drivers/mmc/host/sdhci-pxav2.c
+@@ -166,7 +166,7 @@ static inline struct sdhci_pxa_platdata *pxav2_get_mmc_pdata(struct device *dev)
+ }
+ #endif
+ 
+-static int __devinit sdhci_pxav2_probe(struct platform_device *pdev)
++static int sdhci_pxav2_probe(struct platform_device *pdev)
+ {
+ 	struct sdhci_pltfm_host *pltfm_host;
+ 	struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
+diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c
+index a46cb67b1c33..e89c80901f30 100644
+--- a/drivers/mmc/host/sdhci-pxav3.c
++++ b/drivers/mmc/host/sdhci-pxav3.c
+@@ -214,7 +214,7 @@ static inline struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev)
+ }
+ #endif
+ 
+-static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
++static int sdhci_pxav3_probe(struct platform_device *pdev)
+ {
+ 	struct sdhci_pltfm_host *pltfm_host;
+ 	struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
+diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
+index b62a0c12fa8b..f5dde9eb7989 100644
+--- a/drivers/mmc/host/sdhci-s3c.c
++++ b/drivers/mmc/host/sdhci-s3c.c
+@@ -430,7 +430,7 @@ static void sdhci_s3c_setup_card_detect_gpio(struct sdhci_s3c *sc)
+ }
+ 
+ #ifdef CONFIG_OF
+-static int __devinit sdhci_s3c_parse_dt(struct device *dev,
++static int sdhci_s3c_parse_dt(struct device *dev,
+ 		struct sdhci_host *host, struct s3c_sdhci_platdata *pdata)
+ {
+ 	struct device_node *node = dev->of_node;
+@@ -525,7 +525,7 @@ static int __devinit sdhci_s3c_parse_dt(struct device *dev,
+ 	return -EINVAL;
+ }
+ #else
+-static int __devinit sdhci_s3c_parse_dt(struct device *dev,
++static int sdhci_s3c_parse_dt(struct device *dev,
+ 		struct sdhci_host *host, struct s3c_sdhci_platdata *pdata)
+ {
+ 	return -EINVAL;
+@@ -548,7 +548,7 @@ static inline struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data(
+ 			platform_get_device_id(pdev)->driver_data;
+ }
+ 
+-static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
++static int sdhci_s3c_probe(struct platform_device *pdev)
+ {
+ 	struct s3c_sdhci_platdata *pdata;
+ 	struct sdhci_s3c_drv_data *drv_data;
+diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c
+index 3ba9479712ff..3fd18964145a 100644
+--- a/drivers/mmc/host/sdhci-spear.c
++++ b/drivers/mmc/host/sdhci-spear.c
+@@ -71,8 +71,7 @@ static irqreturn_t sdhci_gpio_irq(int irq, void *dev_id)
+ }
+ 
+ #ifdef CONFIG_OF
+-static struct sdhci_plat_data * __devinit
+-sdhci_probe_config_dt(struct platform_device *pdev)
++static struct sdhci_plat_data *sdhci_probe_config_dt(struct platform_device *pdev)
+ {
+ 	struct device_node *np = pdev->dev.of_node;
+ 	struct sdhci_plat_data *pdata = NULL;
+@@ -96,14 +95,13 @@ sdhci_probe_config_dt(struct platform_device *pdev)
+ 	return pdata;
+ }
+ #else
+-static struct sdhci_plat_data * __devinit
+-sdhci_probe_config_dt(struct platform_device *pdev)
++static struct sdhci_plat_data *sdhci_probe_config_dt(struct platform_device *pdev)
+ {
+ 	return ERR_PTR(-ENOSYS);
+ }
+ #endif
+ 
+-static int __devinit sdhci_probe(struct platform_device *pdev)
++static int sdhci_probe(struct platform_device *pdev)
+ {
+ 	struct device_node *np = pdev->dev.of_node;
+ 	struct sdhci_host *host;
+diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
+index f2843549bf0f..339c41e24d87 100644
+--- a/drivers/mmc/host/sdhci-tegra.c
++++ b/drivers/mmc/host/sdhci-tegra.c
+@@ -217,7 +217,7 @@ static const struct of_device_id sdhci_tegra_dt_match[] __devinitdata = {
+ };
+ MODULE_DEVICE_TABLE(of, sdhci_dt_ids);
+ 
+-static struct tegra_sdhci_platform_data * __devinit sdhci_tegra_dt_parse_pdata(
++static struct tegra_sdhci_platform_data *sdhci_tegra_dt_parse_pdata(
+ 						struct platform_device *pdev)
+ {
+ 	struct tegra_sdhci_platform_data *plat;
+@@ -244,7 +244,7 @@ static struct tegra_sdhci_platform_data * __devinit sdhci_tegra_dt_parse_pdata(
+ 	return plat;
+ }
+ 
+-static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
++static int sdhci_tegra_probe(struct platform_device *pdev)
+ {
+ 	const struct of_device_id *match;
+ 	const struct sdhci_tegra_soc_data *soc_data;
+diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
+index d25bc97dc5c6..9872b52332f8 100644
+--- a/drivers/mmc/host/sh_mmcif.c
++++ b/drivers/mmc/host/sh_mmcif.c
+@@ -1302,7 +1302,7 @@ static void sh_mmcif_init_ocr(struct sh_mmcif_host *host)
+ 		dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n");
+ }
+ 
+-static int __devinit sh_mmcif_probe(struct platform_device *pdev)
++static int sh_mmcif_probe(struct platform_device *pdev)
+ {
+ 	int ret = 0, irq[2];
+ 	struct mmc_host *mmc;
+diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
+index 6a9a625503b3..9125684103a7 100644
+--- a/drivers/mmc/host/sh_mobile_sdhi.c
++++ b/drivers/mmc/host/sh_mobile_sdhi.c
+@@ -117,7 +117,7 @@ static const struct sh_mobile_sdhi_ops sdhi_ops = {
+ 	.cd_wakeup = sh_mobile_sdhi_cd_wakeup,
+ };
+ 
+-static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
++static int sh_mobile_sdhi_probe(struct platform_device *pdev)
+ {
+ 	struct sh_mobile_sdhi *priv;
+ 	struct tmio_mmc_data *mmc_data;
+diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
+index 2f9bbdf5689c..f415be885654 100644
+--- a/drivers/mmc/host/tmio_mmc.c
++++ b/drivers/mmc/host/tmio_mmc.c
+@@ -57,7 +57,7 @@ static int tmio_mmc_resume(struct platform_device *dev)
+ #define tmio_mmc_resume NULL
+ #endif
+ 
+-static int __devinit tmio_mmc_probe(struct platform_device *pdev)
++static int tmio_mmc_probe(struct platform_device *pdev)
+ {
+ 	const struct mfd_cell *cell = mfd_get_cell(pdev);
+ 	struct tmio_mmc_data *pdata;
+diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
+index 0d8a9bbe30be..50bf495a988b 100644
+--- a/drivers/mmc/host/tmio_mmc_pio.c
++++ b/drivers/mmc/host/tmio_mmc_pio.c
+@@ -918,7 +918,7 @@ static void tmio_mmc_init_ocr(struct tmio_mmc_host *host)
+ 		dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n");
+ }
+ 
+-int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
++int tmio_mmc_host_probe(struct tmio_mmc_host **host,
+ 				  struct platform_device *pdev,
+ 				  struct tmio_mmc_data *pdata)
+ {
+diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c
+index d8f8a5ec03f4..1f1a252184a7 100644
+--- a/drivers/mmc/host/via-sdmmc.c
++++ b/drivers/mmc/host/via-sdmmc.c
+@@ -1082,7 +1082,7 @@ static void via_init_mmc_host(struct via_crdr_mmc_host *host)
+ 	msleep(1);
+ }
+ 
+-static int __devinit via_sd_probe(struct pci_dev *pcidev,
++static int via_sd_probe(struct pci_dev *pcidev,
+ 				    const struct pci_device_id *id)
+ {
+ 	struct mmc_host *mmc;
+diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c
+index 3c8ef5994073..d71358a2695d 100644
+--- a/drivers/mmc/host/wbsd.c
++++ b/drivers/mmc/host/wbsd.c
+@@ -1196,7 +1196,7 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id)
+  * Allocate/free MMC structure.
+  */
+ 
+-static int __devinit wbsd_alloc_mmc(struct device *dev)
++static int wbsd_alloc_mmc(struct device *dev)
+ {
+ 	struct mmc_host *mmc;
+ 	struct wbsd_host *host;
+@@ -1288,7 +1288,7 @@ static void wbsd_free_mmc(struct device *dev)
+  * Scan for known chip id:s
+  */
+ 
+-static int __devinit wbsd_scan(struct wbsd_host *host)
++static int wbsd_scan(struct wbsd_host *host)
+ {
+ 	int i, j, k;
+ 	int id;
+@@ -1344,7 +1344,7 @@ static int __devinit wbsd_scan(struct wbsd_host *host)
+  * Allocate/free io port ranges
+  */
+ 
+-static int __devinit wbsd_request_region(struct wbsd_host *host, int base)
++static int wbsd_request_region(struct wbsd_host *host, int base)
+ {
+ 	if (base & 0x7)
+ 		return -EINVAL;
+@@ -1374,7 +1374,7 @@ static void wbsd_release_regions(struct wbsd_host *host)
+  * Allocate/free DMA port and buffer
+  */
+ 
+-static void __devinit wbsd_request_dma(struct wbsd_host *host, int dma)
++static void wbsd_request_dma(struct wbsd_host *host, int dma)
+ {
+ 	if (dma < 0)
+ 		return;
+@@ -1452,7 +1452,7 @@ static void wbsd_release_dma(struct wbsd_host *host)
+  * Allocate/free IRQ.
+  */
+ 
+-static int __devinit wbsd_request_irq(struct wbsd_host *host, int irq)
++static int wbsd_request_irq(struct wbsd_host *host, int irq)
+ {
+ 	int ret;
+ 
+@@ -1502,7 +1502,7 @@ static void  wbsd_release_irq(struct wbsd_host *host)
+  * Allocate all resources for the host.
+  */
+ 
+-static int __devinit wbsd_request_resources(struct wbsd_host *host,
++static int wbsd_request_resources(struct wbsd_host *host,
+ 	int base, int irq, int dma)
+ {
+ 	int ret;
+@@ -1644,7 +1644,7 @@ static void wbsd_chip_poweroff(struct wbsd_host *host)
+  *                                                                           *
+ \*****************************************************************************/
+ 
+-static int __devinit wbsd_init(struct device *dev, int base, int irq, int dma,
++static int wbsd_init(struct device *dev, int base, int irq, int dma,
+ 	int pnp)
+ {
+ 	struct wbsd_host *host = NULL;
+@@ -1762,7 +1762,7 @@ static void __devexit wbsd_shutdown(struct device *dev, int pnp)
+  * Non-PnP
+  */
+ 
+-static int __devinit wbsd_probe(struct platform_device *dev)
++static int wbsd_probe(struct platform_device *dev)
+ {
+ 	/* Use the module parameters for resources */
+ 	return wbsd_init(&dev->dev, param_io, param_irq, param_dma, 0);
+@@ -1781,7 +1781,7 @@ static int __devexit wbsd_remove(struct platform_device *dev)
+ 
+ #ifdef CONFIG_PNP
+ 
+-static int __devinit
++static int
+ wbsd_pnp_probe(struct pnp_dev *pnpdev, const struct pnp_device_id *dev_id)
+ {
+ 	int io, irq, dma;

commit 0433c14356702e296f474f77ebd42f0a9d9a5487
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:20:26 2012 -0500
+
+    mmc: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Chris Ball 
+    Cc: "Michał Mirosław" 
+    Cc: Jarkko Lavinen 
+    Cc: Venkatraman S 
+    Cc: Ian Molton 
+    Cc: Bruce Chang 
+    Cc: Harald Welte 
+    Cc: Pierre Ossman 
+    Acked-by: Viresh Kumar 
+    Acked-by: Guennadi Liakhovetski 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c
+index b9b463eca1ec..156ebe7d6fd0 100644
+--- a/drivers/mmc/host/bfin_sdh.c
++++ b/drivers/mmc/host/bfin_sdh.c
+@@ -680,7 +680,7 @@ static int sdh_resume(struct platform_device *dev)
+ 
+ static struct platform_driver sdh_driver = {
+ 	.probe   = sdh_probe,
+-	.remove  = __devexit_p(sdh_remove),
++	.remove  = sdh_remove,
+ 	.suspend = sdh_suspend,
+ 	.resume  = sdh_resume,
+ 	.driver  = {
+diff --git a/drivers/mmc/host/cb710-mmc.c b/drivers/mmc/host/cb710-mmc.c
+index 83693fd7c6b3..39280b5756e8 100644
+--- a/drivers/mmc/host/cb710-mmc.c
++++ b/drivers/mmc/host/cb710-mmc.c
+@@ -773,7 +773,7 @@ static int __devexit cb710_mmc_exit(struct platform_device *pdev)
+ static struct platform_driver cb710_mmc_driver = {
+ 	.driver.name = "cb710-mmc",
+ 	.probe = cb710_mmc_init,
+-	.remove = __devexit_p(cb710_mmc_exit),
++	.remove = cb710_mmc_exit,
+ #ifdef CONFIG_PM
+ 	.suspend = cb710_mmc_suspend,
+ 	.resume = cb710_mmc_resume,
+diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c
+index c8852a8128a9..31cf20f0eaaa 100644
+--- a/drivers/mmc/host/jz4740_mmc.c
++++ b/drivers/mmc/host/jz4740_mmc.c
+@@ -1004,7 +1004,7 @@ const struct dev_pm_ops jz4740_mmc_pm_ops = {
+ 
+ static struct platform_driver jz4740_mmc_driver = {
+ 	.probe = jz4740_mmc_probe,
+-	.remove = __devexit_p(jz4740_mmc_remove),
++	.remove = jz4740_mmc_remove,
+ 	.driver = {
+ 		.name = "jz4740-mmc",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
+index a600eabbd6c3..f7df7982ba11 100644
+--- a/drivers/mmc/host/mmc_spi.c
++++ b/drivers/mmc/host/mmc_spi.c
+@@ -1529,7 +1529,7 @@ static struct spi_driver mmc_spi_driver = {
+ 		.of_match_table = mmc_spi_of_match_table,
+ 	},
+ 	.probe =	mmc_spi_probe,
+-	.remove =	__devexit_p(mmc_spi_remove),
++	.remove =	mmc_spi_remove,
+ };
+ 
+ module_spi_driver(mmc_spi_driver);
+diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
+index edc3e9baf0e7..3ca6757fbebd 100644
+--- a/drivers/mmc/host/mmci.c
++++ b/drivers/mmc/host/mmci.c
+@@ -1669,7 +1669,7 @@ static struct amba_driver mmci_driver = {
+ 		.pm	= &mmci_dev_pm_ops,
+ 	},
+ 	.probe		= mmci_probe,
+-	.remove		= __devexit_p(mmci_remove),
++	.remove		= mmci_remove,
+ 	.id_table	= mmci_ids,
+ };
+ 
+diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
+index 48ad361613ef..3531a193d8d5 100644
+--- a/drivers/mmc/host/omap.c
++++ b/drivers/mmc/host/omap.c
+@@ -1566,7 +1566,7 @@ static int mmc_omap_resume(struct platform_device *pdev)
+ 
+ static struct platform_driver mmc_omap_driver = {
+ 	.probe		= mmc_omap_probe,
+-	.remove		= __devexit_p(mmc_omap_remove),
++	.remove		= mmc_omap_remove,
+ 	.suspend	= mmc_omap_suspend,
+ 	.resume		= mmc_omap_resume,
+ 	.driver		= {
+diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
+index fedd258cc4ea..58b4cf0f79a9 100644
+--- a/drivers/mmc/host/omap_hsmmc.c
++++ b/drivers/mmc/host/omap_hsmmc.c
+@@ -2149,7 +2149,7 @@ static struct dev_pm_ops omap_hsmmc_dev_pm_ops = {
+ 
+ static struct platform_driver omap_hsmmc_driver = {
+ 	.probe		= omap_hsmmc_probe,
+-	.remove		= __devexit_p(omap_hsmmc_remove),
++	.remove		= omap_hsmmc_remove,
+ 	.driver		= {
+ 		.name = DRIVER_NAME,
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
+index 4638ddab97b8..a5fe5b243680 100644
+--- a/drivers/mmc/host/s3cmci.c
++++ b/drivers/mmc/host/s3cmci.c
+@@ -1906,7 +1906,7 @@ static struct platform_driver s3cmci_driver = {
+ 	},
+ 	.id_table	= s3cmci_driver_ids,
+ 	.probe		= s3cmci_probe,
+-	.remove		= __devexit_p(s3cmci_remove),
++	.remove		= s3cmci_remove,
+ 	.shutdown	= s3cmci_shutdown,
+ };
+ 
+diff --git a/drivers/mmc/host/sdhci-cns3xxx.c b/drivers/mmc/host/sdhci-cns3xxx.c
+index 28a870804f60..9236fa9d504c 100644
+--- a/drivers/mmc/host/sdhci-cns3xxx.c
++++ b/drivers/mmc/host/sdhci-cns3xxx.c
+@@ -112,7 +112,7 @@ static struct platform_driver sdhci_cns3xxx_driver = {
+ 		.pm	= SDHCI_PLTFM_PMOPS,
+ 	},
+ 	.probe		= sdhci_cns3xxx_probe,
+-	.remove		= __devexit_p(sdhci_cns3xxx_remove),
++	.remove		= sdhci_cns3xxx_remove,
+ };
+ 
+ module_platform_driver(sdhci_cns3xxx_driver);
+diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c
+index 8fd50a211037..7ad1bb6cf6a0 100644
+--- a/drivers/mmc/host/sdhci-dove.c
++++ b/drivers/mmc/host/sdhci-dove.c
+@@ -143,7 +143,7 @@ static struct platform_driver sdhci_dove_driver = {
+ 		.of_match_table = of_match_ptr(sdhci_dove_of_match_table),
+ 	},
+ 	.probe		= sdhci_dove_probe,
+-	.remove		= __devexit_p(sdhci_dove_remove),
++	.remove		= sdhci_dove_remove,
+ };
+ 
+ module_platform_driver(sdhci_dove_driver);
+diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
+index effc2acfe778..6a4e98e60009 100644
+--- a/drivers/mmc/host/sdhci-esdhc-imx.c
++++ b/drivers/mmc/host/sdhci-esdhc-imx.c
+@@ -637,7 +637,7 @@ static struct platform_driver sdhci_esdhc_imx_driver = {
+ 	},
+ 	.id_table	= imx_esdhc_devtype,
+ 	.probe		= sdhci_esdhc_imx_probe,
+-	.remove		= __devexit_p(sdhci_esdhc_imx_remove),
++	.remove		= sdhci_esdhc_imx_remove,
+ };
+ 
+ module_platform_driver(sdhci_esdhc_imx_driver);
+diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
+index 63d219f57cae..d7eb4ed307e7 100644
+--- a/drivers/mmc/host/sdhci-of-esdhc.c
++++ b/drivers/mmc/host/sdhci-of-esdhc.c
+@@ -234,7 +234,7 @@ static struct platform_driver sdhci_esdhc_driver = {
+ 		.pm = SDHCI_PLTFM_PMOPS,
+ 	},
+ 	.probe = sdhci_esdhc_probe,
+-	.remove = __devexit_p(sdhci_esdhc_remove),
++	.remove = sdhci_esdhc_remove,
+ };
+ 
+ module_platform_driver(sdhci_esdhc_driver);
+diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c
+index 0ce088ae0228..3b6806902ac9 100644
+--- a/drivers/mmc/host/sdhci-of-hlwd.c
++++ b/drivers/mmc/host/sdhci-of-hlwd.c
+@@ -90,7 +90,7 @@ static struct platform_driver sdhci_hlwd_driver = {
+ 		.pm = SDHCI_PLTFM_PMOPS,
+ 	},
+ 	.probe = sdhci_hlwd_probe,
+-	.remove = __devexit_p(sdhci_hlwd_remove),
++	.remove = sdhci_hlwd_remove,
+ };
+ 
+ module_platform_driver(sdhci_hlwd_driver);
+diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
+index 04936f353ced..7bc2270d9f91 100644
+--- a/drivers/mmc/host/sdhci-pci.c
++++ b/drivers/mmc/host/sdhci-pci.c
+@@ -1470,7 +1470,7 @@ static struct pci_driver sdhci_driver = {
+ 	.name =		"sdhci-pci",
+ 	.id_table =	pci_ids,
+ 	.probe =	sdhci_pci_probe,
+-	.remove =	__devexit_p(sdhci_pci_remove),
++	.remove =	sdhci_pci_remove,
+ 	.driver =	{
+ 		.pm =   &sdhci_pci_pm_ops
+ 	},
+diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c
+index 8e63a9c04e31..964fc6d0a81a 100644
+--- a/drivers/mmc/host/sdhci-pxav2.c
++++ b/drivers/mmc/host/sdhci-pxav2.c
+@@ -275,7 +275,7 @@ static struct platform_driver sdhci_pxav2_driver = {
+ 		.pm	= SDHCI_PLTFM_PMOPS,
+ 	},
+ 	.probe		= sdhci_pxav2_probe,
+-	.remove		= __devexit_p(sdhci_pxav2_remove),
++	.remove		= sdhci_pxav2_remove,
+ };
+ 
+ module_platform_driver(sdhci_pxav2_driver);
+diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c
+index e918a2bb3af1..a46cb67b1c33 100644
+--- a/drivers/mmc/host/sdhci-pxav3.c
++++ b/drivers/mmc/host/sdhci-pxav3.c
+@@ -346,7 +346,7 @@ static struct platform_driver sdhci_pxav3_driver = {
+ 		.pm	= SDHCI_PLTFM_PMOPS,
+ 	},
+ 	.probe		= sdhci_pxav3_probe,
+-	.remove		= __devexit_p(sdhci_pxav3_remove),
++	.remove		= sdhci_pxav3_remove,
+ };
+ 
+ module_platform_driver(sdhci_pxav3_driver);
+diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
+index a54dd5d7a5f9..b62a0c12fa8b 100644
+--- a/drivers/mmc/host/sdhci-s3c.c
++++ b/drivers/mmc/host/sdhci-s3c.c
+@@ -916,7 +916,7 @@ MODULE_DEVICE_TABLE(of, sdhci_s3c_dt_match);
+ 
+ static struct platform_driver sdhci_s3c_driver = {
+ 	.probe		= sdhci_s3c_probe,
+-	.remove		= __devexit_p(sdhci_s3c_remove),
++	.remove		= sdhci_s3c_remove,
+ 	.id_table	= sdhci_s3c_driver_ids,
+ 	.driver		= {
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c
+index 6be89c032deb..3ba9479712ff 100644
+--- a/drivers/mmc/host/sdhci-spear.c
++++ b/drivers/mmc/host/sdhci-spear.c
+@@ -336,7 +336,7 @@ static struct platform_driver sdhci_driver = {
+ 		.of_match_table = of_match_ptr(sdhci_spear_id_table),
+ 	},
+ 	.probe		= sdhci_probe,
+-	.remove		= __devexit_p(sdhci_remove),
++	.remove		= sdhci_remove,
+ };
+ 
+ module_platform_driver(sdhci_driver);
+diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
+index f9eb91623701..f2843549bf0f 100644
+--- a/drivers/mmc/host/sdhci-tegra.c
++++ b/drivers/mmc/host/sdhci-tegra.c
+@@ -407,7 +407,7 @@ static struct platform_driver sdhci_tegra_driver = {
+ 		.pm	= SDHCI_PLTFM_PMOPS,
+ 	},
+ 	.probe		= sdhci_tegra_probe,
+-	.remove		= __devexit_p(sdhci_tegra_remove),
++	.remove		= sdhci_tegra_remove,
+ };
+ 
+ module_platform_driver(sdhci_tegra_driver);
+diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
+index 0bdc146178db..6a9a625503b3 100644
+--- a/drivers/mmc/host/sh_mobile_sdhi.c
++++ b/drivers/mmc/host/sh_mobile_sdhi.c
+@@ -330,7 +330,7 @@ static struct platform_driver sh_mobile_sdhi_driver = {
+ 		.of_match_table = sh_mobile_sdhi_of_match,
+ 	},
+ 	.probe		= sh_mobile_sdhi_probe,
+-	.remove		= __devexit_p(sh_mobile_sdhi_remove),
++	.remove		= sh_mobile_sdhi_remove,
+ };
+ 
+ module_platform_driver(sh_mobile_sdhi_driver);
+diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
+index 113ce6c9cf32..2f9bbdf5689c 100644
+--- a/drivers/mmc/host/tmio_mmc.c
++++ b/drivers/mmc/host/tmio_mmc.c
+@@ -133,7 +133,7 @@ static struct platform_driver tmio_mmc_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = tmio_mmc_probe,
+-	.remove = __devexit_p(tmio_mmc_remove),
++	.remove = tmio_mmc_remove,
+ 	.suspend = tmio_mmc_suspend,
+ 	.resume = tmio_mmc_resume,
+ };
+diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c
+index f18becef156d..d8f8a5ec03f4 100644
+--- a/drivers/mmc/host/via-sdmmc.c
++++ b/drivers/mmc/host/via-sdmmc.c
+@@ -1332,7 +1332,7 @@ static struct pci_driver via_sd_driver = {
+ 	.name = DRV_NAME,
+ 	.id_table = via_ids,
+ 	.probe = via_sd_probe,
+-	.remove = __devexit_p(via_sd_remove),
++	.remove = via_sd_remove,
+ 	.suspend = via_sd_suspend,
+ 	.resume = via_sd_resume,
+ };
+diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c
+index 64acd9ce141c..3c8ef5994073 100644
+--- a/drivers/mmc/host/wbsd.c
++++ b/drivers/mmc/host/wbsd.c
+@@ -1941,7 +1941,7 @@ static struct platform_device *wbsd_device;
+ 
+ static struct platform_driver wbsd_driver = {
+ 	.probe		= wbsd_probe,
+-	.remove		= __devexit_p(wbsd_remove),
++	.remove		= wbsd_remove,
+ 
+ 	.suspend	= wbsd_platform_suspend,
+ 	.resume		= wbsd_platform_resume,
+@@ -1957,7 +1957,7 @@ static struct pnp_driver wbsd_pnp_driver = {
+ 	.name		= DRIVER_NAME,
+ 	.id_table	= pnp_dev_table,
+ 	.probe		= wbsd_pnp_probe,
+-	.remove		= __devexit_p(wbsd_pnp_remove),
++	.remove		= wbsd_pnp_remove,
+ 
+ 	.suspend	= wbsd_pnp_suspend,
+ 	.resume		= wbsd_pnp_resume,

commit 77f37917a6f2bd8635b553178bb34bdd80f08e40
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:09 2012 -0500
+
+    pwm: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Thierry Reding 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/pwm/pwm-ab8500.c b/drivers/pwm/pwm-ab8500.c
+index a2f586ae1093..4248d0418273 100644
+--- a/drivers/pwm/pwm-ab8500.c
++++ b/drivers/pwm/pwm-ab8500.c
+@@ -122,7 +122,7 @@ static int ab8500_pwm_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit ab8500_pwm_remove(struct platform_device *pdev)
++static int ab8500_pwm_remove(struct platform_device *pdev)
+ {
+ 	struct ab8500_pwm_chip *ab8500 = platform_get_drvdata(pdev);
+ 	int err;
+diff --git a/drivers/pwm/pwm-bfin.c b/drivers/pwm/pwm-bfin.c
+index bcb60fe08762..7631ef194de7 100644
+--- a/drivers/pwm/pwm-bfin.c
++++ b/drivers/pwm/pwm-bfin.c
+@@ -139,7 +139,7 @@ static int bfin_pwm_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit bfin_pwm_remove(struct platform_device *pdev)
++static int bfin_pwm_remove(struct platform_device *pdev)
+ {
+ 	struct bfin_pwm_chip *pwm = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
+index 0b3c296449b4..8f26e9fcea97 100644
+--- a/drivers/pwm/pwm-imx.c
++++ b/drivers/pwm/pwm-imx.c
+@@ -290,7 +290,7 @@ static int imx_pwm_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit imx_pwm_remove(struct platform_device *pdev)
++static int imx_pwm_remove(struct platform_device *pdev)
+ {
+ 	struct imx_chip *imx;
+ 
+diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c
+index 6b6ec4df0686..0a2ede3c3932 100644
+--- a/drivers/pwm/pwm-jz4740.c
++++ b/drivers/pwm/pwm-jz4740.c
+@@ -191,7 +191,7 @@ static int jz4740_pwm_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit jz4740_pwm_remove(struct platform_device *pdev)
++static int jz4740_pwm_remove(struct platform_device *pdev)
+ {
+ 	struct jz4740_pwm_chip *jz4740 = platform_get_drvdata(pdev);
+ 	int ret;
+diff --git a/drivers/pwm/pwm-lpc32xx.c b/drivers/pwm/pwm-lpc32xx.c
+index 33967a084789..015a82235620 100644
+--- a/drivers/pwm/pwm-lpc32xx.c
++++ b/drivers/pwm/pwm-lpc32xx.c
+@@ -118,7 +118,7 @@ static int lpc32xx_pwm_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit lpc32xx_pwm_remove(struct platform_device *pdev)
++static int lpc32xx_pwm_remove(struct platform_device *pdev)
+ {
+ 	struct lpc32xx_pwm_chip *lpc32xx = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/pwm/pwm-mxs.c b/drivers/pwm/pwm-mxs.c
+index 4262d15231d0..7ec345f01831 100644
+--- a/drivers/pwm/pwm-mxs.c
++++ b/drivers/pwm/pwm-mxs.c
+@@ -174,7 +174,7 @@ static int mxs_pwm_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit mxs_pwm_remove(struct platform_device *pdev)
++static int mxs_pwm_remove(struct platform_device *pdev)
+ {
+ 	struct mxs_pwm_chip *mxs = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/pwm/pwm-puv3.c b/drivers/pwm/pwm-puv3.c
+index c1ee78ad5fcf..b882f6032fee 100644
+--- a/drivers/pwm/pwm-puv3.c
++++ b/drivers/pwm/pwm-puv3.c
+@@ -142,7 +142,7 @@ static int pwm_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit pwm_remove(struct platform_device *pdev)
++static int pwm_remove(struct platform_device *pdev)
+ {
+ 	struct puv3_pwm_chip *puv3 = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c
+index 644d45d1453b..f32fc4e66e0c 100644
+--- a/drivers/pwm/pwm-pxa.c
++++ b/drivers/pwm/pwm-pxa.c
+@@ -179,7 +179,7 @@ static int pwm_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit pwm_remove(struct platform_device *pdev)
++static int pwm_remove(struct platform_device *pdev)
+ {
+ 	struct pxa_pwm_chip *chip;
+ 
+diff --git a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c
+index 1f1ec3605b9d..e9b15d099c03 100644
+--- a/drivers/pwm/pwm-samsung.c
++++ b/drivers/pwm/pwm-samsung.c
+@@ -273,7 +273,7 @@ static int s3c_pwm_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit s3c_pwm_remove(struct platform_device *pdev)
++static int s3c_pwm_remove(struct platform_device *pdev)
+ {
+ 	struct s3c_chip *s3c = platform_get_drvdata(pdev);
+ 	int err;
+diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
+index 3e8ccbb10ac3..30c0e2b70ce8 100644
+--- a/drivers/pwm/pwm-tegra.c
++++ b/drivers/pwm/pwm-tegra.c
+@@ -210,7 +210,7 @@ static int tegra_pwm_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit tegra_pwm_remove(struct platform_device *pdev)
++static int tegra_pwm_remove(struct platform_device *pdev)
+ {
+ 	struct tegra_pwm_chip *pc = platform_get_drvdata(pdev);
+ 	int i;
+diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c
+index 0b9f89460b71..87c091b245cc 100644
+--- a/drivers/pwm/pwm-tiecap.c
++++ b/drivers/pwm/pwm-tiecap.c
+@@ -235,7 +235,7 @@ static int ecap_pwm_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit ecap_pwm_remove(struct platform_device *pdev)
++static int ecap_pwm_remove(struct platform_device *pdev)
+ {
+ 	struct ecap_pwm_chip *pc = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c
+index 7c353c0a9473..9ffd389d0c8b 100644
+--- a/drivers/pwm/pwm-tiehrpwm.c
++++ b/drivers/pwm/pwm-tiehrpwm.c
+@@ -443,7 +443,7 @@ static int ehrpwm_pwm_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit ehrpwm_pwm_remove(struct platform_device *pdev)
++static int ehrpwm_pwm_remove(struct platform_device *pdev)
+ {
+ 	struct ehrpwm_pwm_chip *pc = platform_get_drvdata(pdev);
+ 

commit 3e9fe83d278cce6974f0a4d1870c0ff4a0b74ba5
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:23:14 2012 -0500
+
+    pwm: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Thierry Reding 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/pwm/pwm-ab8500.c b/drivers/pwm/pwm-ab8500.c
+index 4a37aa264baf..a2f586ae1093 100644
+--- a/drivers/pwm/pwm-ab8500.c
++++ b/drivers/pwm/pwm-ab8500.c
+@@ -90,7 +90,7 @@ static const struct pwm_ops ab8500_pwm_ops = {
+ 	.disable = ab8500_pwm_disable,
+ };
+ 
+-static int __devinit ab8500_pwm_probe(struct platform_device *pdev)
++static int ab8500_pwm_probe(struct platform_device *pdev)
+ {
+ 	struct ab8500_pwm_chip *ab8500;
+ 	int err;
+diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
+index 369639c5b81e..0b3c296449b4 100644
+--- a/drivers/pwm/pwm-imx.c
++++ b/drivers/pwm/pwm-imx.c
+@@ -231,7 +231,7 @@ static const struct of_device_id imx_pwm_dt_ids[] = {
+ };
+ MODULE_DEVICE_TABLE(of, imx_pwm_dt_ids);
+ 
+-static int __devinit imx_pwm_probe(struct platform_device *pdev)
++static int imx_pwm_probe(struct platform_device *pdev)
+ {
+ 	const struct of_device_id *of_id =
+ 			of_match_device(imx_pwm_dt_ids, &pdev->dev);
+diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c
+index 14f473d37659..6b6ec4df0686 100644
+--- a/drivers/pwm/pwm-jz4740.c
++++ b/drivers/pwm/pwm-jz4740.c
+@@ -162,7 +162,7 @@ static const struct pwm_ops jz4740_pwm_ops = {
+ 	.owner = THIS_MODULE,
+ };
+ 
+-static int __devinit jz4740_pwm_probe(struct platform_device *pdev)
++static int jz4740_pwm_probe(struct platform_device *pdev)
+ {
+ 	struct jz4740_pwm_chip *jz4740;
+ 	int ret;
+diff --git a/drivers/pwm/pwm-puv3.c b/drivers/pwm/pwm-puv3.c
+index 5d7ee9b075f8..c1ee78ad5fcf 100644
+--- a/drivers/pwm/pwm-puv3.c
++++ b/drivers/pwm/pwm-puv3.c
+@@ -101,7 +101,7 @@ static const struct pwm_ops puv3_pwm_ops = {
+ 	.owner = THIS_MODULE,
+ };
+ 
+-static int __devinit pwm_probe(struct platform_device *pdev)
++static int pwm_probe(struct platform_device *pdev)
+ {
+ 	struct puv3_pwm_chip *puv3;
+ 	struct resource *r;
+diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c
+index 25fed89256db..644d45d1453b 100644
+--- a/drivers/pwm/pwm-pxa.c
++++ b/drivers/pwm/pwm-pxa.c
+@@ -135,7 +135,7 @@ static struct pwm_ops pxa_pwm_ops = {
+ 	.owner = THIS_MODULE,
+ };
+ 
+-static int __devinit pwm_probe(struct platform_device *pdev)
++static int pwm_probe(struct platform_device *pdev)
+ {
+ 	const struct platform_device_id *id = platform_get_device_id(pdev);
+ 	struct pxa_pwm_chip *pwm;
+diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c
+index 71488b1989c2..0b9f89460b71 100644
+--- a/drivers/pwm/pwm-tiecap.c
++++ b/drivers/pwm/pwm-tiecap.c
+@@ -184,7 +184,7 @@ static const struct pwm_ops ecap_pwm_ops = {
+ 	.owner		= THIS_MODULE,
+ };
+ 
+-static int __devinit ecap_pwm_probe(struct platform_device *pdev)
++static int ecap_pwm_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 	struct resource *r;
+diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c
+index a606b380f926..7c353c0a9473 100644
+--- a/drivers/pwm/pwm-tiehrpwm.c
++++ b/drivers/pwm/pwm-tiehrpwm.c
+@@ -392,7 +392,7 @@ static const struct pwm_ops ehrpwm_pwm_ops = {
+ 	.owner		= THIS_MODULE,
+ };
+ 
+-static int __devinit ehrpwm_pwm_probe(struct platform_device *pdev)
++static int ehrpwm_pwm_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 	struct resource *r;

commit fd1091125a1d11fcc635749d0d3dec36904a7a48
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:28 2012 -0500
+
+    pwm: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Thierry Reding 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/pwm/pwm-ab8500.c b/drivers/pwm/pwm-ab8500.c
+index cfb72ca873d1..4a37aa264baf 100644
+--- a/drivers/pwm/pwm-ab8500.c
++++ b/drivers/pwm/pwm-ab8500.c
+@@ -143,7 +143,7 @@ static struct platform_driver ab8500_pwm_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = ab8500_pwm_probe,
+-	.remove = __devexit_p(ab8500_pwm_remove),
++	.remove = ab8500_pwm_remove,
+ };
+ module_platform_driver(ab8500_pwm_driver);
+ 
+diff --git a/drivers/pwm/pwm-bfin.c b/drivers/pwm/pwm-bfin.c
+index 5da8e185e838..bcb60fe08762 100644
+--- a/drivers/pwm/pwm-bfin.c
++++ b/drivers/pwm/pwm-bfin.c
+@@ -151,7 +151,7 @@ static struct platform_driver bfin_pwm_driver = {
+ 		.name = "bfin-pwm",
+ 	},
+ 	.probe = bfin_pwm_probe,
+-	.remove = __devexit_p(bfin_pwm_remove),
++	.remove = bfin_pwm_remove,
+ };
+ 
+ module_platform_driver(bfin_pwm_driver);
+diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
+index 8a5d3ae2946a..369639c5b81e 100644
+--- a/drivers/pwm/pwm-imx.c
++++ b/drivers/pwm/pwm-imx.c
+@@ -307,7 +307,7 @@ static struct platform_driver imx_pwm_driver = {
+ 		.of_match_table = of_match_ptr(imx_pwm_dt_ids),
+ 	},
+ 	.probe		= imx_pwm_probe,
+-	.remove		= __devexit_p(imx_pwm_remove),
++	.remove		= imx_pwm_remove,
+ };
+ 
+ module_platform_driver(imx_pwm_driver);
+diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c
+index 10250fcefb98..14f473d37659 100644
+--- a/drivers/pwm/pwm-jz4740.c
++++ b/drivers/pwm/pwm-jz4740.c
+@@ -211,7 +211,7 @@ static struct platform_driver jz4740_pwm_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = jz4740_pwm_probe,
+-	.remove = __devexit_p(jz4740_pwm_remove),
++	.remove = jz4740_pwm_remove,
+ };
+ module_platform_driver(jz4740_pwm_driver);
+ 
+diff --git a/drivers/pwm/pwm-lpc32xx.c b/drivers/pwm/pwm-lpc32xx.c
+index adb87f0c1633..33967a084789 100644
+--- a/drivers/pwm/pwm-lpc32xx.c
++++ b/drivers/pwm/pwm-lpc32xx.c
+@@ -138,7 +138,7 @@ static struct platform_driver lpc32xx_pwm_driver = {
+ 		.of_match_table = of_match_ptr(lpc32xx_pwm_dt_ids),
+ 	},
+ 	.probe = lpc32xx_pwm_probe,
+-	.remove = __devexit_p(lpc32xx_pwm_remove),
++	.remove = lpc32xx_pwm_remove,
+ };
+ module_platform_driver(lpc32xx_pwm_driver);
+ 
+diff --git a/drivers/pwm/pwm-mxs.c b/drivers/pwm/pwm-mxs.c
+index e5852646f082..4262d15231d0 100644
+--- a/drivers/pwm/pwm-mxs.c
++++ b/drivers/pwm/pwm-mxs.c
+@@ -193,7 +193,7 @@ static struct platform_driver mxs_pwm_driver = {
+ 		.of_match_table = of_match_ptr(mxs_pwm_dt_ids),
+ 	},
+ 	.probe = mxs_pwm_probe,
+-	.remove = __devexit_p(mxs_pwm_remove),
++	.remove = mxs_pwm_remove,
+ };
+ module_platform_driver(mxs_pwm_driver);
+ 
+diff --git a/drivers/pwm/pwm-puv3.c b/drivers/pwm/pwm-puv3.c
+index 2a93f37c46ad..5d7ee9b075f8 100644
+--- a/drivers/pwm/pwm-puv3.c
++++ b/drivers/pwm/pwm-puv3.c
+@@ -154,7 +154,7 @@ static struct platform_driver puv3_pwm_driver = {
+ 		.name = "PKUnity-v3-PWM",
+ 	},
+ 	.probe = pwm_probe,
+-	.remove = __devexit_p(pwm_remove),
++	.remove = pwm_remove,
+ };
+ module_platform_driver(puv3_pwm_driver);
+ 
+diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c
+index 260c3a88564d..25fed89256db 100644
+--- a/drivers/pwm/pwm-pxa.c
++++ b/drivers/pwm/pwm-pxa.c
+@@ -196,7 +196,7 @@ static struct platform_driver pwm_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= pwm_probe,
+-	.remove		= __devexit_p(pwm_remove),
++	.remove		= pwm_remove,
+ 	.id_table	= pwm_id_table,
+ };
+ 
+diff --git a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c
+index 023a3bee76e7..1f1ec3605b9d 100644
+--- a/drivers/pwm/pwm-samsung.c
++++ b/drivers/pwm/pwm-samsung.c
+@@ -327,7 +327,7 @@ static struct platform_driver s3c_pwm_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= s3c_pwm_probe,
+-	.remove		= __devexit_p(s3c_pwm_remove),
++	.remove		= s3c_pwm_remove,
+ 	.suspend	= s3c_pwm_suspend,
+ 	.resume		= s3c_pwm_resume,
+ };
+diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
+index 057465e0553c..3e8ccbb10ac3 100644
+--- a/drivers/pwm/pwm-tegra.c
++++ b/drivers/pwm/pwm-tegra.c
+@@ -249,7 +249,7 @@ static struct platform_driver tegra_pwm_driver = {
+ 		.of_match_table = of_match_ptr(tegra_pwm_of_match),
+ 	},
+ 	.probe = tegra_pwm_probe,
+-	.remove = __devexit_p(tegra_pwm_remove),
++	.remove = tegra_pwm_remove,
+ };
+ 
+ module_platform_driver(tegra_pwm_driver);
+diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c
+index d6d4cf05565e..71488b1989c2 100644
+--- a/drivers/pwm/pwm-tiecap.c
++++ b/drivers/pwm/pwm-tiecap.c
+@@ -249,7 +249,7 @@ static struct platform_driver ecap_pwm_driver = {
+ 		.name = "ecap",
+ 	},
+ 	.probe = ecap_pwm_probe,
+-	.remove = __devexit_p(ecap_pwm_remove),
++	.remove = ecap_pwm_remove,
+ };
+ 
+ module_platform_driver(ecap_pwm_driver);
+diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c
+index d3c1dff0a0dc..a606b380f926 100644
+--- a/drivers/pwm/pwm-tiehrpwm.c
++++ b/drivers/pwm/pwm-tiehrpwm.c
+@@ -457,7 +457,7 @@ static struct platform_driver ehrpwm_pwm_driver = {
+ 		.name = "ehrpwm",
+ 	},
+ 	.probe = ehrpwm_pwm_probe,
+-	.remove = __devexit_p(ehrpwm_pwm_remove),
++	.remove = ehrpwm_pwm_remove,
+ };
+ 
+ module_platform_driver(ehrpwm_pwm_driver);
+diff --git a/drivers/pwm/pwm-twl6030.c b/drivers/pwm/pwm-twl6030.c
+index 8e6387864ca2..378a7e286366 100644
+--- a/drivers/pwm/pwm-twl6030.c
++++ b/drivers/pwm/pwm-twl6030.c
+@@ -176,7 +176,7 @@ static struct platform_driver twl6030_pwm_driver = {
+ 		.name = "twl6030-pwm",
+ 	},
+ 	.probe = twl6030_pwm_probe,
+-	.remove = __devexit_p(twl6030_pwm_remove),
++	.remove = twl6030_pwm_remove,
+ };
+ module_platform_driver(twl6030_pwm_driver);
+ 

commit 4740f73fe5388ab5d22d552d2a0dacc62418a70c
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:01 2012 -0500
+
+    mfd: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Srinidhi Kasagar 
+    Cc: Peter Tyser 
+    Cc: Daniel Walker 
+    Cc: Bryan Huntsman 
+    Acked-by: David Brown 
+    Acked-by: Linus Walleij 
+    Acked-by: Mark Brown 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c
+index 6746ecd260ad..391e23e6a647 100644
+--- a/drivers/mfd/88pm800.c
++++ b/drivers/mfd/88pm800.c
+@@ -554,7 +554,7 @@ static int pm800_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit pm800_remove(struct i2c_client *client)
++static int pm800_remove(struct i2c_client *client)
+ {
+ 	struct pm80x_chip *chip = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c
+index 13c09941dc2c..e671230be2b1 100644
+--- a/drivers/mfd/88pm805.c
++++ b/drivers/mfd/88pm805.c
+@@ -262,7 +262,7 @@ static int pm805_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit pm805_remove(struct i2c_client *client)
++static int pm805_remove(struct i2c_client *client)
+ {
+ 	struct pm80x_chip *chip = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
+index 20dd0d41aee4..893fc1ba6ead 100644
+--- a/drivers/mfd/88pm860x-core.c
++++ b/drivers/mfd/88pm860x-core.c
+@@ -1077,7 +1077,7 @@ static int pm860x_device_init(struct pm860x_chip *chip,
+ 	return 0;
+ }
+ 
+-static void __devexit pm860x_device_exit(struct pm860x_chip *chip)
++static void pm860x_device_exit(struct pm860x_chip *chip)
+ {
+ 	device_irq_exit(chip);
+ 	mfd_remove_devices(chip->dev);
+@@ -1200,7 +1200,7 @@ static int pm860x_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit pm860x_remove(struct i2c_client *client)
++static int pm860x_remove(struct i2c_client *client)
+ {
+ 	struct pm860x_chip *chip = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
+index bf188bc98986..2ec7725f4a08 100644
+--- a/drivers/mfd/ab3100-core.c
++++ b/drivers/mfd/ab3100-core.c
+@@ -961,7 +961,7 @@ static int ab3100_probe(struct i2c_client *client,
+ 	return err;
+ }
+ 
+-static int __devexit ab3100_remove(struct i2c_client *client)
++static int ab3100_remove(struct i2c_client *client)
+ {
+ 	struct ab3100 *ab3100 = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
+index 7335a9c8ffae..127b00aadae3 100644
+--- a/drivers/mfd/ab8500-core.c
++++ b/drivers/mfd/ab8500-core.c
+@@ -1473,7 +1473,7 @@ static int ab8500_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit ab8500_remove(struct platform_device *pdev)
++static int ab8500_remove(struct platform_device *pdev)
+ {
+ 	struct ab8500 *ab8500 = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c
+index 44843680d982..5a8e707bc038 100644
+--- a/drivers/mfd/ab8500-debugfs.c
++++ b/drivers/mfd/ab8500-debugfs.c
+@@ -597,7 +597,7 @@ static int ab8500_debug_probe(struct platform_device *plf)
+ 	return -ENOMEM;
+ }
+ 
+-static int __devexit ab8500_debug_remove(struct platform_device *plf)
++static int ab8500_debug_remove(struct platform_device *plf)
+ {
+ 	debugfs_remove(ab8500_val_file);
+ 	debugfs_remove(ab8500_address_file);
+diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c
+index c5e168e3ef11..3fb1f40d6389 100644
+--- a/drivers/mfd/ab8500-gpadc.c
++++ b/drivers/mfd/ab8500-gpadc.c
+@@ -634,7 +634,7 @@ static int ab8500_gpadc_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit ab8500_gpadc_remove(struct platform_device *pdev)
++static int ab8500_gpadc_remove(struct platform_device *pdev)
+ {
+ 	struct ab8500_gpadc *gpadc = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c
+index 499263c3110a..8a33b2c7eead 100644
+--- a/drivers/mfd/ab8500-sysctrl.c
++++ b/drivers/mfd/ab8500-sysctrl.c
+@@ -55,7 +55,7 @@ static int ab8500_sysctrl_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit ab8500_sysctrl_remove(struct platform_device *pdev)
++static int ab8500_sysctrl_remove(struct platform_device *pdev)
+ {
+ 	sysctrl_dev = NULL;
+ 	return 0;
+diff --git a/drivers/mfd/adp5520.c b/drivers/mfd/adp5520.c
+index f2f9d8ff6416..210dd038bb5a 100644
+--- a/drivers/mfd/adp5520.c
++++ b/drivers/mfd/adp5520.c
+@@ -307,7 +307,7 @@ static int adp5520_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit adp5520_remove(struct i2c_client *client)
++static int adp5520_remove(struct i2c_client *client)
+ {
+ 	struct adp5520_chip *chip = dev_get_drvdata(&client->dev);
+ 
+diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
+index 47e711674739..12fdabfb569e 100644
+--- a/drivers/mfd/arizona-core.c
++++ b/drivers/mfd/arizona-core.c
+@@ -553,7 +553,7 @@ int arizona_dev_init(struct arizona *arizona)
+ }
+ EXPORT_SYMBOL_GPL(arizona_dev_init);
+ 
+-int __devexit arizona_dev_exit(struct arizona *arizona)
++int arizona_dev_exit(struct arizona *arizona)
+ {
+ 	mfd_remove_devices(arizona->dev);
+ 	arizona_free_irq(arizona, ARIZONA_IRQ_UNDERCLOCKED, arizona);
+diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c
+index aaf1a69134df..44a1bb969841 100644
+--- a/drivers/mfd/arizona-i2c.c
++++ b/drivers/mfd/arizona-i2c.c
+@@ -65,7 +65,7 @@ static int arizona_i2c_probe(struct i2c_client *i2c,
+ 	return arizona_dev_init(arizona);
+ }
+ 
+-static int __devexit arizona_i2c_remove(struct i2c_client *i2c)
++static int arizona_i2c_remove(struct i2c_client *i2c)
+ {
+ 	struct arizona *arizona = dev_get_drvdata(&i2c->dev);
+ 	arizona_dev_exit(arizona);
+diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c
+index 9663cafdb7ff..1b9fdd698b03 100644
+--- a/drivers/mfd/arizona-spi.c
++++ b/drivers/mfd/arizona-spi.c
+@@ -65,7 +65,7 @@ static int arizona_spi_probe(struct spi_device *spi)
+ 	return arizona_dev_init(arizona);
+ }
+ 
+-static int __devexit arizona_spi_remove(struct spi_device *spi)
++static int arizona_spi_remove(struct spi_device *spi)
+ {
+ 	struct arizona *arizona = dev_get_drvdata(&spi->dev);
+ 	arizona_dev_exit(arizona);
+diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c
+index b0720d7c1b71..1b15986c01e1 100644
+--- a/drivers/mfd/asic3.c
++++ b/drivers/mfd/asic3.c
+@@ -1039,7 +1039,7 @@ static int __init asic3_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit asic3_remove(struct platform_device *pdev)
++static int asic3_remove(struct platform_device *pdev)
+ {
+ 	int ret;
+ 	struct asic3 *asic = platform_get_drvdata(pdev);
+diff --git a/drivers/mfd/cs5535-mfd.c b/drivers/mfd/cs5535-mfd.c
+index d9dc87f067d8..2e4752a9220a 100644
+--- a/drivers/mfd/cs5535-mfd.c
++++ b/drivers/mfd/cs5535-mfd.c
+@@ -166,7 +166,7 @@ static int cs5535_mfd_probe(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit cs5535_mfd_remove(struct pci_dev *pdev)
++static void cs5535_mfd_remove(struct pci_dev *pdev)
+ {
+ 	mfd_remove_devices(&pdev->dev);
+ 	pci_disable_device(pdev);
+diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c
+index 5fa1e91a9532..05176cd2862b 100644
+--- a/drivers/mfd/da903x.c
++++ b/drivers/mfd/da903x.c
+@@ -544,7 +544,7 @@ static int da903x_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit da903x_remove(struct i2c_client *client)
++static int da903x_remove(struct i2c_client *client)
+ {
+ 	struct da903x_chip *chip = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c
+index 96f66ed8dbfc..ac74a4d1daea 100644
+--- a/drivers/mfd/da9052-i2c.c
++++ b/drivers/mfd/da9052-i2c.c
+@@ -121,7 +121,7 @@ static int da9052_i2c_probe(struct i2c_client *client,
+ 	return 0;
+ }
+ 
+-static int __devexit da9052_i2c_remove(struct i2c_client *client)
++static int da9052_i2c_remove(struct i2c_client *client)
+ {
+ 	struct da9052 *da9052 = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/mfd/da9052-spi.c b/drivers/mfd/da9052-spi.c
+index 1ad324373c97..61d63b93576c 100644
+--- a/drivers/mfd/da9052-spi.c
++++ b/drivers/mfd/da9052-spi.c
+@@ -58,7 +58,7 @@ static int da9052_spi_probe(struct spi_device *spi)
+ 	return 0;
+ }
+ 
+-static int __devexit da9052_spi_remove(struct spi_device *spi)
++static int da9052_spi_remove(struct spi_device *spi)
+ {
+ 	struct da9052 *da9052 = dev_get_drvdata(&spi->dev);
+ 
+diff --git a/drivers/mfd/da9055-core.c b/drivers/mfd/da9055-core.c
+index 6f5a4984f0aa..f56a1a9f7777 100644
+--- a/drivers/mfd/da9055-core.c
++++ b/drivers/mfd/da9055-core.c
+@@ -412,7 +412,7 @@ int da9055_device_init(struct da9055 *da9055)
+ 	return ret;
+ }
+ 
+-void __devexit da9055_device_exit(struct da9055 *da9055)
++void da9055_device_exit(struct da9055 *da9055)
+ {
+ 	regmap_del_irq_chip(da9055->chip_irq, da9055->irq_data);
+ 	mfd_remove_devices(da9055->dev);
+diff --git a/drivers/mfd/da9055-i2c.c b/drivers/mfd/da9055-i2c.c
+index 7778d042fb5d..607387ffe8ca 100644
+--- a/drivers/mfd/da9055-i2c.c
++++ b/drivers/mfd/da9055-i2c.c
+@@ -44,7 +44,7 @@ static int da9055_i2c_probe(struct i2c_client *i2c,
+ 	return da9055_device_init(da9055);
+ }
+ 
+-static int __devexit da9055_i2c_remove(struct i2c_client *i2c)
++static int da9055_i2c_remove(struct i2c_client *i2c)
+ {
+ 	struct da9055 *da9055 = i2c_get_clientdata(i2c);
+ 
+diff --git a/drivers/mfd/davinci_voicecodec.c b/drivers/mfd/davinci_voicecodec.c
+index b2b0397059d8..c0bcc872af4e 100644
+--- a/drivers/mfd/davinci_voicecodec.c
++++ b/drivers/mfd/davinci_voicecodec.c
+@@ -151,7 +151,7 @@ static int __init davinci_vc_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit davinci_vc_remove(struct platform_device *pdev)
++static int davinci_vc_remove(struct platform_device *pdev)
+ {
+ 	struct davinci_vc *davinci_vc = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c
+index d81505e50d12..b7a61f0f27a4 100644
+--- a/drivers/mfd/ezx-pcap.c
++++ b/drivers/mfd/ezx-pcap.c
+@@ -391,7 +391,7 @@ static int pcap_add_subdev(struct pcap_chip *pcap,
+ 	return ret;
+ }
+ 
+-static int __devexit ezx_pcap_remove(struct spi_device *spi)
++static int ezx_pcap_remove(struct spi_device *spi)
+ {
+ 	struct pcap_chip *pcap = dev_get_drvdata(&spi->dev);
+ 	struct pcap_platform_data *pdata = spi->dev.platform_data;
+diff --git a/drivers/mfd/intel_msic.c b/drivers/mfd/intel_msic.c
+index 438ac3df166b..ab8d0b2739b2 100644
+--- a/drivers/mfd/intel_msic.c
++++ b/drivers/mfd/intel_msic.c
+@@ -364,7 +364,7 @@ static int intel_msic_init_devices(struct intel_msic *msic)
+ 	return ret;
+ }
+ 
+-static void __devexit intel_msic_remove_devices(struct intel_msic *msic)
++static void intel_msic_remove_devices(struct intel_msic *msic)
+ {
+ 	struct platform_device *pdev = msic->pdev;
+ 	struct intel_msic_platform_data *pdata = pdev->dev.platform_data;
+@@ -445,7 +445,7 @@ static int intel_msic_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit intel_msic_remove(struct platform_device *pdev)
++static int intel_msic_remove(struct platform_device *pdev)
+ {
+ 	struct intel_msic *msic = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c
+index 55c479e57aad..45ece11cc27c 100644
+--- a/drivers/mfd/janz-cmodio.c
++++ b/drivers/mfd/janz-cmodio.c
+@@ -254,7 +254,7 @@ static int cmodio_pci_probe(struct pci_dev *dev,
+ 	return ret;
+ }
+ 
+-static void __devexit cmodio_pci_remove(struct pci_dev *dev)
++static void cmodio_pci_remove(struct pci_dev *dev)
+ {
+ 	struct cmodio_device *priv = pci_get_drvdata(dev);
+ 
+diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c
+index c0d38c597f0c..0b8b55bb9b11 100644
+--- a/drivers/mfd/jz4740-adc.c
++++ b/drivers/mfd/jz4740-adc.c
+@@ -307,7 +307,7 @@ static int jz4740_adc_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit jz4740_adc_remove(struct platform_device *pdev)
++static int jz4740_adc_remove(struct platform_device *pdev)
+ {
+ 	struct jz4740_adc *adc = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/mfd/lm3533-core.c b/drivers/mfd/lm3533-core.c
+index 2b74508655d4..ceebf2c1ea97 100644
+--- a/drivers/mfd/lm3533-core.c
++++ b/drivers/mfd/lm3533-core.c
+@@ -534,7 +534,7 @@ static int lm3533_device_init(struct lm3533 *lm3533)
+ 	return ret;
+ }
+ 
+-static void __devexit lm3533_device_exit(struct lm3533 *lm3533)
++static void lm3533_device_exit(struct lm3533 *lm3533)
+ {
+ 	dev_dbg(lm3533->dev, "%s\n", __func__);
+ 
+@@ -624,7 +624,7 @@ static int lm3533_i2c_probe(struct i2c_client *i2c,
+ 	return 0;
+ }
+ 
+-static int __devexit lm3533_i2c_remove(struct i2c_client *i2c)
++static int lm3533_i2c_remove(struct i2c_client *i2c)
+ {
+ 	struct lm3533 *lm3533 = i2c_get_clientdata(i2c);
+ 
+diff --git a/drivers/mfd/lp8788.c b/drivers/mfd/lp8788.c
+index e1d7c9f18cc5..c3d3c9b4d3ad 100644
+--- a/drivers/mfd/lp8788.c
++++ b/drivers/mfd/lp8788.c
+@@ -203,7 +203,7 @@ static int lp8788_probe(struct i2c_client *cl, const struct i2c_device_id *id)
+ 			       ARRAY_SIZE(lp8788_devs), NULL, 0, NULL);
+ }
+ 
+-static int __devexit lp8788_remove(struct i2c_client *cl)
++static int lp8788_remove(struct i2c_client *cl)
+ {
+ 	struct lp8788 *lp = i2c_get_clientdata(cl);
+ 
+diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
+index 7c83e1b56588..2ad24caa07db 100644
+--- a/drivers/mfd/lpc_ich.c
++++ b/drivers/mfd/lpc_ich.c
+@@ -878,7 +878,7 @@ static int lpc_ich_probe(struct pci_dev *dev,
+ 	return 0;
+ }
+ 
+-static void __devexit lpc_ich_remove(struct pci_dev *dev)
++static void lpc_ich_remove(struct pci_dev *dev)
+ {
+ 	mfd_remove_devices(&dev->dev);
+ 	lpc_ich_restore_config_space(dev);
+diff --git a/drivers/mfd/lpc_sch.c b/drivers/mfd/lpc_sch.c
+index 5756a6af08dc..5624fcbba69b 100644
+--- a/drivers/mfd/lpc_sch.c
++++ b/drivers/mfd/lpc_sch.c
+@@ -164,7 +164,7 @@ static int lpc_sch_probe(struct pci_dev *dev,
+ 	return ret;
+ }
+ 
+-static void __devexit lpc_sch_remove(struct pci_dev *dev)
++static void lpc_sch_remove(struct pci_dev *dev)
+ {
+ 	mfd_remove_devices(&dev->dev);
+ }
+diff --git a/drivers/mfd/max8907.c b/drivers/mfd/max8907.c
+index 81ded7a4ca8c..e9b1c93a3ade 100644
+--- a/drivers/mfd/max8907.c
++++ b/drivers/mfd/max8907.c
+@@ -288,7 +288,7 @@ static int max8907_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int max8907_i2c_remove(struct i2c_client *i2c)
++static int max8907_i2c_remove(struct i2c_client *i2c)
+ {
+ 	struct max8907 *max8907 = i2c_get_clientdata(i2c);
+ 
+diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c
+index 60325c49afda..e32466e865b9 100644
+--- a/drivers/mfd/max8925-core.c
++++ b/drivers/mfd/max8925-core.c
+@@ -901,7 +901,7 @@ int max8925_device_init(struct max8925_chip *chip,
+ 	return ret;
+ }
+ 
+-void __devexit max8925_device_exit(struct max8925_chip *chip)
++void max8925_device_exit(struct max8925_chip *chip)
+ {
+ 	if (chip->core_irq)
+ 		free_irq(chip->core_irq, chip);
+diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c
+index 6e3d30aa00df..00b5b456063d 100644
+--- a/drivers/mfd/max8925-i2c.c
++++ b/drivers/mfd/max8925-i2c.c
+@@ -168,7 +168,7 @@ static int max8925_probe(struct i2c_client *client,
+ 	return 0;
+ }
+ 
+-static int __devexit max8925_remove(struct i2c_client *client)
++static int max8925_remove(struct i2c_client *client)
+ {
+ 	struct max8925_chip *chip = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/mfd/mc13xxx-i2c.c b/drivers/mfd/mc13xxx-i2c.c
+index 4a605fb63cbc..7957999f30bb 100644
+--- a/drivers/mfd/mc13xxx-i2c.c
++++ b/drivers/mfd/mc13xxx-i2c.c
+@@ -85,7 +85,7 @@ static int mc13xxx_i2c_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit mc13xxx_i2c_remove(struct i2c_client *client)
++static int mc13xxx_i2c_remove(struct i2c_client *client)
+ {
+ 	struct mc13xxx *mc13xxx = dev_get_drvdata(&client->dev);
+ 
+diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c
+index e7acd0511156..cb32f69d80ba 100644
+--- a/drivers/mfd/mc13xxx-spi.c
++++ b/drivers/mfd/mc13xxx-spi.c
+@@ -159,7 +159,7 @@ static int mc13xxx_spi_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit mc13xxx_spi_remove(struct spi_device *spi)
++static int mc13xxx_spi_remove(struct spi_device *spi)
+ {
+ 	struct mc13xxx *mc13xxx = dev_get_drvdata(&spi->dev);
+ 
+diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
+index fc23dfbb6910..29b8ed21213e 100644
+--- a/drivers/mfd/omap-usb-host.c
++++ b/drivers/mfd/omap-usb-host.c
+@@ -652,7 +652,7 @@ static int usbhs_omap_probe(struct platform_device *pdev)
+  *
+  * Reverses the effect of usbhs_omap_probe().
+  */
+-static int __devexit usbhs_omap_remove(struct platform_device *pdev)
++static int usbhs_omap_remove(struct platform_device *pdev)
+ {
+ 	struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
+index 0b586885446b..401b976e3aff 100644
+--- a/drivers/mfd/omap-usb-tll.c
++++ b/drivers/mfd/omap-usb-tll.c
+@@ -348,7 +348,7 @@ static int usbtll_omap_probe(struct platform_device *pdev)
+  *
+  * Reverses the effect of usbtll_omap_probe().
+  */
+-static int __devexit usbtll_omap_remove(struct platform_device *pdev)
++static int usbtll_omap_remove(struct platform_device *pdev)
+ {
+ 	struct usbtll_omap *tll = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/mfd/pcf50633-adc.c b/drivers/mfd/pcf50633-adc.c
+index dbd2f0d0078e..18b53cb72fea 100644
+--- a/drivers/mfd/pcf50633-adc.c
++++ b/drivers/mfd/pcf50633-adc.c
+@@ -218,7 +218,7 @@ static int pcf50633_adc_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit pcf50633_adc_remove(struct platform_device *pdev)
++static int pcf50633_adc_remove(struct platform_device *pdev)
+ {
+ 	struct pcf50633_adc *adc = platform_get_drvdata(pdev);
+ 	int i, head;
+diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c
+index fc477353081e..64803f13bcec 100644
+--- a/drivers/mfd/pcf50633-core.c
++++ b/drivers/mfd/pcf50633-core.c
+@@ -275,7 +275,7 @@ static int pcf50633_probe(struct i2c_client *client,
+ 	return 0;
+ }
+ 
+-static int __devexit pcf50633_remove(struct i2c_client *client)
++static int pcf50633_remove(struct i2c_client *client)
+ {
+ 	struct pcf50633 *pcf = i2c_get_clientdata(client);
+ 	int i;
+diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
+index 43491346e7d0..d4b297cbd801 100644
+--- a/drivers/mfd/pm8921-core.c
++++ b/drivers/mfd/pm8921-core.c
+@@ -165,7 +165,7 @@ static int pm8921_probe(struct platform_device *pdev)
+ 	return rc;
+ }
+ 
+-static int __devexit pm8921_remove(struct platform_device *pdev)
++static int pm8921_remove(struct platform_device *pdev)
+ {
+ 	struct pm8xxx_drvdata *drvdata;
+ 	struct pm8921 *pmic = NULL;
+diff --git a/drivers/mfd/pm8xxx-irq.c b/drivers/mfd/pm8xxx-irq.c
+index 59c20ea329de..1360e20adf11 100644
+--- a/drivers/mfd/pm8xxx-irq.c
++++ b/drivers/mfd/pm8xxx-irq.c
+@@ -363,7 +363,7 @@ struct pm_irq_chip *  pm8xxx_irq_init(struct device *dev,
+ 	return chip;
+ }
+ 
+-int __devexit pm8xxx_irq_exit(struct pm_irq_chip *chip)
++int pm8xxx_irq_exit(struct pm_irq_chip *chip)
+ {
+ 	irq_set_chained_handler(chip->devirq, NULL);
+ 	kfree(chip);
+diff --git a/drivers/mfd/rc5t583.c b/drivers/mfd/rc5t583.c
+index f721b13e986c..14bdaccefbec 100644
+--- a/drivers/mfd/rc5t583.c
++++ b/drivers/mfd/rc5t583.c
+@@ -303,7 +303,7 @@ static int rc5t583_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static int  __devexit rc5t583_i2c_remove(struct i2c_client *i2c)
++static int  rc5t583_i2c_remove(struct i2c_client *i2c)
+ {
+ 	struct rc5t583 *rc5t583 = i2c_get_clientdata(i2c);
+ 
+diff --git a/drivers/mfd/rdc321x-southbridge.c b/drivers/mfd/rdc321x-southbridge.c
+index be46539c3080..21b7bef73507 100644
+--- a/drivers/mfd/rdc321x-southbridge.c
++++ b/drivers/mfd/rdc321x-southbridge.c
+@@ -91,7 +91,7 @@ static int rdc321x_sb_probe(struct pci_dev *pdev,
+ 			       NULL, 0, NULL);
+ }
+ 
+-static void __devexit rdc321x_sb_remove(struct pci_dev *pdev)
++static void rdc321x_sb_remove(struct pci_dev *pdev)
+ {
+ 	mfd_remove_devices(&pdev->dev);
+ }
+diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
+index 9b53733cb297..9816c232e583 100644
+--- a/drivers/mfd/sm501.c
++++ b/drivers/mfd/sm501.c
+@@ -1685,7 +1685,7 @@ static void sm501_dev_remove(struct sm501_devdata *sm)
+ 	sm501_gpio_remove(sm);
+ }
+ 
+-static void __devexit sm501_pci_remove(struct pci_dev *dev)
++static void sm501_pci_remove(struct pci_dev *dev)
+ {
+ 	struct sm501_devdata *sm = pci_get_drvdata(dev);
+ 
+diff --git a/drivers/mfd/sta2x11-mfd.c b/drivers/mfd/sta2x11-mfd.c
+index 57f3361d0cb0..d6284cacd27a 100644
+--- a/drivers/mfd/sta2x11-mfd.c
++++ b/drivers/mfd/sta2x11-mfd.c
+@@ -89,7 +89,7 @@ static int sta2x11_mfd_add(struct pci_dev *pdev, gfp_t flags)
+ 	return 0;
+ }
+ 
+-static int __devexit mfd_remove(struct pci_dev *pdev)
++static int mfd_remove(struct pci_dev *pdev)
+ {
+ 	struct sta2x11_mfd *mfd = sta2x11_mfd_find(pdev);
+ 
+diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c
+index 8195ca2ac74b..36df18778029 100644
+--- a/drivers/mfd/stmpe-i2c.c
++++ b/drivers/mfd/stmpe-i2c.c
+@@ -63,7 +63,7 @@ stmpe_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
+ 	return stmpe_probe(&i2c_ci, id->driver_data);
+ }
+ 
+-static int __devexit stmpe_i2c_remove(struct i2c_client *i2c)
++static int stmpe_i2c_remove(struct i2c_client *i2c)
+ {
+ 	struct stmpe *stmpe = dev_get_drvdata(&i2c->dev);
+ 
+diff --git a/drivers/mfd/stmpe-spi.c b/drivers/mfd/stmpe-spi.c
+index 52774338998f..973659f8abd9 100644
+--- a/drivers/mfd/stmpe-spi.c
++++ b/drivers/mfd/stmpe-spi.c
+@@ -101,7 +101,7 @@ stmpe_spi_probe(struct spi_device *spi)
+ 	return stmpe_probe(&spi_ci, id->driver_data);
+ }
+ 
+-static int __devexit stmpe_spi_remove(struct spi_device *spi)
++static int stmpe_spi_remove(struct spi_device *spi)
+ {
+ 	struct stmpe *stmpe = dev_get_drvdata(&spi->dev);
+ 
+diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
+index 3dbfe9ab889c..3f10591ea94e 100644
+--- a/drivers/mfd/syscon.c
++++ b/drivers/mfd/syscon.c
+@@ -138,7 +138,7 @@ static int syscon_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit syscon_remove(struct platform_device *pdev)
++static int syscon_remove(struct platform_device *pdev)
+ {
+ 	struct syscon *syscon;
+ 
+diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c
+index 7e197f788b0a..a06d66b929b1 100644
+--- a/drivers/mfd/tc3589x.c
++++ b/drivers/mfd/tc3589x.c
+@@ -402,7 +402,7 @@ static int tc3589x_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static int __devexit tc3589x_remove(struct i2c_client *client)
++static int tc3589x_remove(struct i2c_client *client)
+ {
+ 	struct tc3589x *tc3589x = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c
+index ca18f262c34a..366f7b906278 100644
+--- a/drivers/mfd/tc6387xb.c
++++ b/drivers/mfd/tc6387xb.c
+@@ -208,7 +208,7 @@ static int tc6387xb_probe(struct platform_device *dev)
+ 	return ret;
+ }
+ 
+-static int __devexit tc6387xb_remove(struct platform_device *dev)
++static int tc6387xb_remove(struct platform_device *dev)
+ {
+ 	struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
+ 
+diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
+index 1ff8ed6390d1..15e1463e5e13 100644
+--- a/drivers/mfd/tc6393xb.c
++++ b/drivers/mfd/tc6393xb.c
+@@ -731,7 +731,7 @@ static int tc6393xb_probe(struct platform_device *dev)
+ 	return ret;
+ }
+ 
+-static int __devexit tc6393xb_remove(struct platform_device *dev)
++static int tc6393xb_remove(struct platform_device *dev)
+ {
+ 	struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
+ 	struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+diff --git a/drivers/mfd/ti-ssp.c b/drivers/mfd/ti-ssp.c
+index b177f96da864..09a14cec351b 100644
+--- a/drivers/mfd/ti-ssp.c
++++ b/drivers/mfd/ti-ssp.c
+@@ -433,7 +433,7 @@ static int ti_ssp_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit ti_ssp_remove(struct platform_device *pdev)
++static int ti_ssp_remove(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	struct ti_ssp *ssp = dev_get_drvdata(dev);
+diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c
+index a305ac109496..59e0ee247e86 100644
+--- a/drivers/mfd/timberdale.c
++++ b/drivers/mfd/timberdale.c
+@@ -840,7 +840,7 @@ static int timb_probe(struct pci_dev *dev,
+ 	return -ENODEV;
+ }
+ 
+-static void __devexit timb_remove(struct pci_dev *dev)
++static void timb_remove(struct pci_dev *dev)
+ {
+ 	struct timberdale_device *priv = pci_get_drvdata(dev);
+ 
+diff --git a/drivers/mfd/tps6105x.c b/drivers/mfd/tps6105x.c
+index 75a84ac4672e..1d302f583adf 100644
+--- a/drivers/mfd/tps6105x.c
++++ b/drivers/mfd/tps6105x.c
+@@ -199,7 +199,7 @@ static int tps6105x_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit tps6105x_remove(struct i2c_client *client)
++static int tps6105x_remove(struct i2c_client *client)
+ {
+ 	struct tps6105x *tps6105x = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c
+index 0c446eb86bdb..382a857b0dde 100644
+--- a/drivers/mfd/tps65090.c
++++ b/drivers/mfd/tps65090.c
+@@ -308,7 +308,7 @@ static int tps65090_i2c_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit tps65090_i2c_remove(struct i2c_client *client)
++static int tps65090_i2c_remove(struct i2c_client *client)
+ {
+ 	struct tps65090 *tps65090 = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c
+index 8cba75750e91..e14e252e3473 100644
+--- a/drivers/mfd/tps65217.c
++++ b/drivers/mfd/tps65217.c
+@@ -214,7 +214,7 @@ static int tps65217_probe(struct i2c_client *client,
+ 	return 0;
+ }
+ 
+-static int __devexit tps65217_remove(struct i2c_client *client)
++static int tps65217_remove(struct i2c_client *client)
+ {
+ 	struct tps65217 *tps = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c
+index 975fbb5f36aa..9f92c3b22093 100644
+--- a/drivers/mfd/tps6586x.c
++++ b/drivers/mfd/tps6586x.c
+@@ -548,7 +548,7 @@ static int tps6586x_i2c_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit tps6586x_i2c_remove(struct i2c_client *client)
++static int tps6586x_i2c_remove(struct i2c_client *client)
+ {
+ 	struct tps6586x *tps6586x = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c
+index 3a3402290a74..ce054654f5bb 100644
+--- a/drivers/mfd/tps65910.c
++++ b/drivers/mfd/tps65910.c
+@@ -302,7 +302,7 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static __devexit int tps65910_i2c_remove(struct i2c_client *i2c)
++static int tps65910_i2c_remove(struct i2c_client *i2c)
+ {
+ 	struct tps65910 *tps65910 = i2c_get_clientdata(i2c);
+ 
+diff --git a/drivers/mfd/tps65911-comparator.c b/drivers/mfd/tps65911-comparator.c
+index b3d268f95a77..c0816ebd9d7e 100644
+--- a/drivers/mfd/tps65911-comparator.c
++++ b/drivers/mfd/tps65911-comparator.c
+@@ -152,7 +152,7 @@ static int tps65911_comparator_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static __devexit int tps65911_comparator_remove(struct platform_device *pdev)
++static int tps65911_comparator_remove(struct platform_device *pdev)
+ {
+ 	struct tps65910 *tps65910;
+ 
+diff --git a/drivers/mfd/tps65912-spi.c b/drivers/mfd/tps65912-spi.c
+index 6366576a3056..b45f460d299f 100644
+--- a/drivers/mfd/tps65912-spi.c
++++ b/drivers/mfd/tps65912-spi.c
+@@ -99,7 +99,7 @@ static int tps65912_spi_probe(struct spi_device *spi)
+ 	return tps65912_device_init(tps65912);
+ }
+ 
+-static int __devexit tps65912_spi_remove(struct spi_device *spi)
++static int tps65912_spi_remove(struct spi_device *spi)
+ {
+ 	struct tps65912 *tps65912 = spi_get_drvdata(spi);
+ 
+diff --git a/drivers/mfd/twl4030-audio.c b/drivers/mfd/twl4030-audio.c
+index aacccdcf997c..e16edca92670 100644
+--- a/drivers/mfd/twl4030-audio.c
++++ b/drivers/mfd/twl4030-audio.c
+@@ -269,7 +269,7 @@ static int twl4030_audio_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit twl4030_audio_remove(struct platform_device *pdev)
++static int twl4030_audio_remove(struct platform_device *pdev)
+ {
+ 	mfd_remove_devices(&pdev->dev);
+ 	platform_set_drvdata(pdev, NULL);
+diff --git a/drivers/mfd/twl4030-madc.c b/drivers/mfd/twl4030-madc.c
+index 228d5aacd332..a39dcf3e2133 100644
+--- a/drivers/mfd/twl4030-madc.c
++++ b/drivers/mfd/twl4030-madc.c
+@@ -785,7 +785,7 @@ static int twl4030_madc_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit twl4030_madc_remove(struct platform_device *pdev)
++static int twl4030_madc_remove(struct platform_device *pdev)
+ {
+ 	struct twl4030_madc_data *madc = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/mfd/vx855.c b/drivers/mfd/vx855.c
+index 66ef03b02569..757ecc63338c 100644
+--- a/drivers/mfd/vx855.c
++++ b/drivers/mfd/vx855.c
+@@ -112,7 +112,7 @@ static int vx855_probe(struct pci_dev *pdev,
+ 	return ret;
+ }
+ 
+-static void __devexit vx855_remove(struct pci_dev *pdev)
++static void vx855_remove(struct pci_dev *pdev)
+ {
+ 	mfd_remove_devices(&pdev->dev);
+ 	pci_disable_device(pdev);
+diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c
+index 4c7225a53ba2..4e70e157a909 100644
+--- a/drivers/mfd/wm831x-spi.c
++++ b/drivers/mfd/wm831x-spi.c
+@@ -51,7 +51,7 @@ static int wm831x_spi_probe(struct spi_device *spi)
+ 	return wm831x_device_init(wm831x, type, spi->irq);
+ }
+ 
+-static int __devexit wm831x_spi_remove(struct spi_device *spi)
++static int wm831x_spi_remove(struct spi_device *spi)
+ {
+ 	struct wm831x *wm831x = dev_get_drvdata(&spi->dev);
+ 
+diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
+index 4e2432dc49f9..c7f62ac544ad 100644
+--- a/drivers/mfd/wm8994-core.c
++++ b/drivers/mfd/wm8994-core.c
+@@ -671,7 +671,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
+ 	return ret;
+ }
+ 
+-static __devexit void wm8994_device_exit(struct wm8994 *wm8994)
++static void wm8994_device_exit(struct wm8994 *wm8994)
+ {
+ 	pm_runtime_disable(wm8994->dev);
+ 	mfd_remove_devices(wm8994->dev);
+@@ -715,7 +715,7 @@ static int wm8994_i2c_probe(struct i2c_client *i2c,
+ 	return wm8994_device_init(wm8994, i2c->irq);
+ }
+ 
+-static __devexit int wm8994_i2c_remove(struct i2c_client *i2c)
++static int wm8994_i2c_remove(struct i2c_client *i2c)
+ {
+ 	struct wm8994 *wm8994 = i2c_get_clientdata(i2c);
+ 
+diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h
+index 83f0bdc530b7..1cb5698b4d76 100644
+--- a/include/linux/mfd/abx500/ab8500.h
++++ b/include/linux/mfd/abx500/ab8500.h
+@@ -293,7 +293,7 @@ struct ab8500_platform_data {
+ 
+ extern int ab8500_init(struct ab8500 *ab8500,
+ 				 enum ab8500_version version);
+-extern int __devexit ab8500_exit(struct ab8500 *ab8500);
++extern int ab8500_exit(struct ab8500 *ab8500);
+ 
+ extern int ab8500_suspend(struct ab8500 *ab8500);
+ 
+diff --git a/include/linux/mfd/pm8xxx/irq.h b/include/linux/mfd/pm8xxx/irq.h
+index ddaa7f5e9ed9..f83d6b43ecbb 100644
+--- a/include/linux/mfd/pm8xxx/irq.h
++++ b/include/linux/mfd/pm8xxx/irq.h
+@@ -39,7 +39,7 @@ struct pm_irq_chip;
+ int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq);
+ struct pm_irq_chip *pm8xxx_irq_init(struct device *dev,
+ 				const struct pm8xxx_irq_platform_data *pdata);
+-int __devexit pm8xxx_irq_exit(struct pm_irq_chip *chip);
++int pm8xxx_irq_exit(struct pm_irq_chip *chip);
+ #else
+ static inline int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq)
+ {
+@@ -51,7 +51,7 @@ static inline struct pm_irq_chip *pm8xxx_irq_init(
+ {
+ 	return ERR_PTR(-ENXIO);
+ }
+-static inline int __devexit pm8xxx_irq_exit(struct pm_irq_chip *chip)
++static inline int pm8xxx_irq_exit(struct pm_irq_chip *chip)
+ {
+ 	return -ENXIO;
+ }

commit a73e5df16b52a12f5210b20484e74c45ae25d04c
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:25:09 2012 -0500
+
+    mfd: remove use of __devinitconst
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitconst is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Mark Brown 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
+index 84b2303bc770..bf188bc98986 100644
+--- a/drivers/mfd/ab3100-core.c
++++ b/drivers/mfd/ab3100-core.c
+@@ -661,8 +661,7 @@ struct ab3100_init_setting {
+ 	u8 setting;
+ };
+ 
+-static const struct ab3100_init_setting __devinitconst
+-ab3100_init_settings[] = {
++static const struct ab3100_init_setting ab3100_init_settings[] = {
+ 	{
+ 		.abreg = AB3100_MCA,
+ 		.setting = 0x01
+@@ -803,7 +802,7 @@ struct ab_family_id {
+ 	char	*name;
+ };
+ 
+-static const struct ab_family_id ids[] __devinitconst = {
++static const struct ab_family_id ids[] = {
+ 	/* AB3100 */
+ 	{
+ 		.id = 0xc0,
+diff --git a/drivers/mfd/sta2x11-mfd.c b/drivers/mfd/sta2x11-mfd.c
+index 1438be54170c..57f3361d0cb0 100644
+--- a/drivers/mfd/sta2x11-mfd.c
++++ b/drivers/mfd/sta2x11-mfd.c
+@@ -305,7 +305,7 @@ enum bar1_cells {
+ 		.flags = IORESOURCE_MEM, \
+ 		}
+ 
+-static const __devinitconst struct resource gpio_resources[] = {
++static const struct resource gpio_resources[] = {
+ 	{
+ 		.name = "sta2x11_gpio", /* 4 consecutive cells, 1 driver */
+ 		.start = 0,
+@@ -313,17 +313,17 @@ static const __devinitconst struct resource gpio_resources[] = {
+ 		.flags = IORESOURCE_MEM,
+ 	}
+ };
+-static const __devinitconst struct resource sctl_resources[] = {
++static const struct resource sctl_resources[] = {
+ 	CELL_4K("sta2x11-sctl", STA2X11_SCTL),
+ };
+-static const __devinitconst struct resource scr_resources[] = {
++static const struct resource scr_resources[] = {
+ 	CELL_4K("sta2x11-scr", STA2X11_SCR),
+ };
+-static const __devinitconst struct resource time_resources[] = {
++static const struct resource time_resources[] = {
+ 	CELL_4K("sta2x11-time", STA2X11_TIME),
+ };
+ 
+-static const __devinitconst struct resource apbreg_resources[] = {
++static const struct resource apbreg_resources[] = {
+ 	CELL_4K("sta2x11-apbreg", STA2X11_APBREG),
+ };
+ 
+diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c
+index 294e14dcd907..a305ac109496 100644
+--- a/drivers/mfd/timberdale.c
++++ b/drivers/mfd/timberdale.c
+@@ -89,7 +89,7 @@ timberdale_ocores_platform_data = {
+ 	.num_devices = ARRAY_SIZE(timberdale_i2c_board_info)
+ };
+ 
+-static const __devinitconst struct resource timberdale_xiic_resources[] = {
++static const struct resource timberdale_xiic_resources[] = {
+ 	{
+ 		.start	= XIICOFFSET,
+ 		.end	= XIICEND,
+@@ -102,7 +102,7 @@ static const __devinitconst struct resource timberdale_xiic_resources[] = {
+ 	},
+ };
+ 
+-static const __devinitconst struct resource timberdale_ocores_resources[] = {
++static const struct resource timberdale_ocores_resources[] = {
+ 	{
+ 		.start	= OCORESOFFSET,
+ 		.end	= OCORESEND,
+@@ -151,7 +151,7 @@ static struct xspi_platform_data timberdale_xspi_platform_data = {
+ 	 */
+ };
+ 
+-static const __devinitconst struct resource timberdale_spi_resources[] = {
++static const struct resource timberdale_spi_resources[] = {
+ 	{
+ 		.start 	= SPIOFFSET,
+ 		.end	= SPIEND,
+@@ -170,7 +170,7 @@ static struct ks8842_platform_data
+ 	.tx_dma_channel = DMA_ETH_TX
+ };
+ 
+-static const __devinitconst struct resource timberdale_eth_resources[] = {
++static const struct resource timberdale_eth_resources[] = {
+ 	{
+ 		.start	= ETHOFFSET,
+ 		.end	= ETHEND,
+@@ -190,7 +190,7 @@ static struct timbgpio_platform_data
+ 	.irq_base = 200,
+ };
+ 
+-static const __devinitconst struct resource timberdale_gpio_resources[] = {
++static const struct resource timberdale_gpio_resources[] = {
+ 	{
+ 		.start	= GPIOOFFSET,
+ 		.end	= GPIOEND,
+@@ -203,7 +203,7 @@ static const __devinitconst struct resource timberdale_gpio_resources[] = {
+ 	},
+ };
+ 
+-static const __devinitconst struct resource timberdale_mlogicore_resources[] = {
++static const struct resource timberdale_mlogicore_resources[] = {
+ 	{
+ 		.start	= MLCOREOFFSET,
+ 		.end	= MLCOREEND,
+@@ -221,7 +221,7 @@ static const __devinitconst struct resource timberdale_mlogicore_resources[] = {
+ 	},
+ };
+ 
+-static const __devinitconst struct resource timberdale_uart_resources[] = {
++static const struct resource timberdale_uart_resources[] = {
+ 	{
+ 		.start	= UARTOFFSET,
+ 		.end	= UARTEND,
+@@ -234,7 +234,7 @@ static const __devinitconst struct resource timberdale_uart_resources[] = {
+ 	},
+ };
+ 
+-static const __devinitconst struct resource timberdale_uartlite_resources[] = {
++static const struct resource timberdale_uartlite_resources[] = {
+ 	{
+ 		.start	= UARTLITEOFFSET,
+ 		.end	= UARTLITEEND,
+@@ -262,7 +262,7 @@ static struct timb_video_platform_data
+ 	}
+ };
+ 
+-static const __devinitconst struct resource
++static const struct resource
+ timberdale_radio_resources[] = {
+ 	{
+ 		.start	= RDSOFFSET,
+@@ -291,7 +291,7 @@ static struct timb_radio_platform_data
+ 	.dsp = &timberdale_saa7706_i2c_board_info
+ };
+ 
+-static const __devinitconst struct resource timberdale_video_resources[] = {
++static const struct resource timberdale_video_resources[] = {
+ 	{
+ 		.start	= LOGIWOFFSET,
+ 		.end	= LOGIWEND,
+@@ -362,7 +362,7 @@ static struct timb_dma_platform_data timb_dma_platform_data = {
+ 	}
+ };
+ 
+-static const __devinitconst struct resource timberdale_dma_resources[] = {
++static const struct resource timberdale_dma_resources[] = {
+ 	{
+ 		.start	= DMAOFFSET,
+ 		.end	= DMAEND,
+@@ -606,7 +606,7 @@ static struct mfd_cell timberdale_cells_bar0_cfg3[] = {
+ 	},
+ };
+ 
+-static const __devinitconst struct resource timberdale_sdhc_resources[] = {
++static const struct resource timberdale_sdhc_resources[] = {
+ 	/* located in bar 1 and bar 2 */
+ 	{
+ 		.start	= SDHC0OFFSET,
+diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
+index 46429495836d..4e2432dc49f9 100644
+--- a/drivers/mfd/wm8994-core.c
++++ b/drivers/mfd/wm8994-core.c
+@@ -374,21 +374,21 @@ static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)
+ }
+ #endif
+ 
+-static const __devinitconst struct reg_default wm8994_revc_patch[] = {
++static const struct reg_default wm8994_revc_patch[] = {
+ 	{ 0x102, 0x3 },
+ 	{ 0x56, 0x3 },
+ 	{ 0x817, 0x0 },
+ 	{ 0x102, 0x0 },
+ };
+ 
+-static const __devinitconst struct reg_default wm8958_reva_patch[] = {
++static const struct reg_default wm8958_reva_patch[] = {
+ 	{ 0x102, 0x3 },
+ 	{ 0xcb, 0x81 },
+ 	{ 0x817, 0x0 },
+ 	{ 0x102, 0x0 },
+ };
+ 
+-static const __devinitconst struct reg_default wm1811_reva_patch[] = {
++static const struct reg_default wm1811_reva_patch[] = {
+ 	{ 0x102, 0x3 },
+ 	{ 0x56, 0xc07 },
+ 	{ 0x5d, 0x7e },

commit a9e9ce4c41672cf3f6fcb1288bfd6b26c1f2a917
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:24:21 2012 -0500
+
+    mfd: remove use of __devinitdata
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitdata is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Srinidhi Kasagar 
+    Cc: Peter Tyser 
+    Acked-by: Linus Walleij 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
+index ad36ad70a0c2..20dd0d41aee4 100644
+--- a/drivers/mfd/88pm860x-core.c
++++ b/drivers/mfd/88pm860x-core.c
+@@ -28,111 +28,111 @@
+ 
+ #define INT_STATUS_NUM			3
+ 
+-static struct resource bk0_resources[] __devinitdata = {
++static struct resource bk0_resources[] = {
+ 	{2, 2, "duty cycle", IORESOURCE_REG, },
+ 	{3, 3, "always on",  IORESOURCE_REG, },
+ 	{3, 3, "current",    IORESOURCE_REG, },
+ };
+-static struct resource bk1_resources[] __devinitdata = {
++static struct resource bk1_resources[] = {
+ 	{4, 4, "duty cycle", IORESOURCE_REG, },
+ 	{5, 5, "always on",  IORESOURCE_REG, },
+ 	{5, 5, "current",    IORESOURCE_REG, },
+ };
+-static struct resource bk2_resources[] __devinitdata = {
++static struct resource bk2_resources[] = {
+ 	{6, 6, "duty cycle", IORESOURCE_REG, },
+ 	{7, 7, "always on",  IORESOURCE_REG, },
+ 	{5, 5, "current",    IORESOURCE_REG, },
+ };
+ 
+-static struct resource led0_resources[] __devinitdata = {
++static struct resource led0_resources[] = {
+ 	/* RGB1 Red LED */
+ 	{0xd, 0xd, "control", IORESOURCE_REG, },
+ 	{0xc, 0xc, "blink",   IORESOURCE_REG, },
+ };
+-static struct resource led1_resources[] __devinitdata = {
++static struct resource led1_resources[] = {
+ 	/* RGB1 Green LED */
+ 	{0xe, 0xe, "control", IORESOURCE_REG, },
+ 	{0xc, 0xc, "blink",   IORESOURCE_REG, },
+ };
+-static struct resource led2_resources[] __devinitdata = {
++static struct resource led2_resources[] = {
+ 	/* RGB1 Blue LED */
+ 	{0xf, 0xf, "control", IORESOURCE_REG, },
+ 	{0xc, 0xc, "blink",   IORESOURCE_REG, },
+ };
+-static struct resource led3_resources[] __devinitdata = {
++static struct resource led3_resources[] = {
+ 	/* RGB2 Red LED */
+ 	{0x9, 0x9, "control", IORESOURCE_REG, },
+ 	{0x8, 0x8, "blink",   IORESOURCE_REG, },
+ };
+-static struct resource led4_resources[] __devinitdata = {
++static struct resource led4_resources[] = {
+ 	/* RGB2 Green LED */
+ 	{0xa, 0xa, "control", IORESOURCE_REG, },
+ 	{0x8, 0x8, "blink",   IORESOURCE_REG, },
+ };
+-static struct resource led5_resources[] __devinitdata = {
++static struct resource led5_resources[] = {
+ 	/* RGB2 Blue LED */
+ 	{0xb, 0xb, "control", IORESOURCE_REG, },
+ 	{0x8, 0x8, "blink",   IORESOURCE_REG, },
+ };
+ 
+-static struct resource buck1_resources[] __devinitdata = {
++static struct resource buck1_resources[] = {
+ 	{0x24, 0x24, "buck set", IORESOURCE_REG, },
+ };
+-static struct resource buck2_resources[] __devinitdata = {
++static struct resource buck2_resources[] = {
+ 	{0x25, 0x25, "buck set", IORESOURCE_REG, },
+ };
+-static struct resource buck3_resources[] __devinitdata = {
++static struct resource buck3_resources[] = {
+ 	{0x26, 0x26, "buck set", IORESOURCE_REG, },
+ };
+-static struct resource ldo1_resources[] __devinitdata = {
++static struct resource ldo1_resources[] = {
+ 	{0x10, 0x10, "ldo set", IORESOURCE_REG, },
+ };
+-static struct resource ldo2_resources[] __devinitdata = {
++static struct resource ldo2_resources[] = {
+ 	{0x11, 0x11, "ldo set", IORESOURCE_REG, },
+ };
+-static struct resource ldo3_resources[] __devinitdata = {
++static struct resource ldo3_resources[] = {
+ 	{0x12, 0x12, "ldo set", IORESOURCE_REG, },
+ };
+-static struct resource ldo4_resources[] __devinitdata = {
++static struct resource ldo4_resources[] = {
+ 	{0x13, 0x13, "ldo set", IORESOURCE_REG, },
+ };
+-static struct resource ldo5_resources[] __devinitdata = {
++static struct resource ldo5_resources[] = {
+ 	{0x14, 0x14, "ldo set", IORESOURCE_REG, },
+ };
+-static struct resource ldo6_resources[] __devinitdata = {
++static struct resource ldo6_resources[] = {
+ 	{0x15, 0x15, "ldo set", IORESOURCE_REG, },
+ };
+-static struct resource ldo7_resources[] __devinitdata = {
++static struct resource ldo7_resources[] = {
+ 	{0x16, 0x16, "ldo set", IORESOURCE_REG, },
+ };
+-static struct resource ldo8_resources[] __devinitdata = {
++static struct resource ldo8_resources[] = {
+ 	{0x17, 0x17, "ldo set", IORESOURCE_REG, },
+ };
+-static struct resource ldo9_resources[] __devinitdata = {
++static struct resource ldo9_resources[] = {
+ 	{0x18, 0x18, "ldo set", IORESOURCE_REG, },
+ };
+-static struct resource ldo10_resources[] __devinitdata = {
++static struct resource ldo10_resources[] = {
+ 	{0x19, 0x19, "ldo set", IORESOURCE_REG, },
+ };
+-static struct resource ldo12_resources[] __devinitdata = {
++static struct resource ldo12_resources[] = {
+ 	{0x1a, 0x1a, "ldo set", IORESOURCE_REG, },
+ };
+-static struct resource ldo_vibrator_resources[] __devinitdata = {
++static struct resource ldo_vibrator_resources[] = {
+ 	{0x28, 0x28, "ldo set", IORESOURCE_REG, },
+ };
+-static struct resource ldo14_resources[] __devinitdata = {
++static struct resource ldo14_resources[] = {
+ 	{0x1b, 0x1b, "ldo set", IORESOURCE_REG, },
+ };
+ 
+-static struct resource touch_resources[] __devinitdata = {
++static struct resource touch_resources[] = {
+ 	{PM8607_IRQ_PEN, PM8607_IRQ_PEN, "touch", IORESOURCE_IRQ,},
+ };
+ 
+-static struct resource onkey_resources[] __devinitdata = {
++static struct resource onkey_resources[] = {
+ 	{PM8607_IRQ_ONKEY, PM8607_IRQ_ONKEY, "onkey", IORESOURCE_IRQ,},
+ };
+ 
+-static struct resource codec_resources[] __devinitdata = {
++static struct resource codec_resources[] = {
+ 	/* Headset microphone insertion or removal */
+ 	{PM8607_IRQ_MICIN,   PM8607_IRQ_MICIN,   "micin",   IORESOURCE_IRQ,},
+ 	/* Hook-switch press or release */
+@@ -143,12 +143,12 @@ static struct resource codec_resources[] __devinitdata = {
+ 	{PM8607_IRQ_AUDIO_SHORT, PM8607_IRQ_AUDIO_SHORT, "audio-short", IORESOURCE_IRQ,},
+ };
+ 
+-static struct resource battery_resources[] __devinitdata = {
++static struct resource battery_resources[] = {
+ 	{PM8607_IRQ_CC,  PM8607_IRQ_CC,  "columb counter", IORESOURCE_IRQ,},
+ 	{PM8607_IRQ_BAT, PM8607_IRQ_BAT, "battery",        IORESOURCE_IRQ,},
+ };
+ 
+-static struct resource charger_resources[] __devinitdata = {
++static struct resource charger_resources[] = {
+ 	{PM8607_IRQ_CHG,  PM8607_IRQ_CHG,  "charger detect",  IORESOURCE_IRQ,},
+ 	{PM8607_IRQ_CHG_DONE,  PM8607_IRQ_CHG_DONE,  "charging done",       IORESOURCE_IRQ,},
+ 	{PM8607_IRQ_CHG_FAIL,  PM8607_IRQ_CHG_FAIL,  "charging timeout",    IORESOURCE_IRQ,},
+@@ -158,11 +158,11 @@ static struct resource charger_resources[] __devinitdata = {
+ 	{PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage",    IORESOURCE_IRQ,},
+ };
+ 
+-static struct resource rtc_resources[] __devinitdata = {
++static struct resource rtc_resources[] = {
+ 	{PM8607_IRQ_RTC, PM8607_IRQ_RTC, "rtc", IORESOURCE_IRQ,},
+ };
+ 
+-static struct mfd_cell bk_devs[] __devinitdata = {
++static struct mfd_cell bk_devs[] = {
+ 	{
+ 		.name = "88pm860x-backlight",
+ 		.id = 0,
+@@ -181,7 +181,7 @@ static struct mfd_cell bk_devs[] __devinitdata = {
+ 	},
+ };
+ 
+-static struct mfd_cell led_devs[] __devinitdata = {
++static struct mfd_cell led_devs[] = {
+ 	{
+ 		.name = "88pm860x-led",
+ 		.id = 0,
+@@ -215,7 +215,7 @@ static struct mfd_cell led_devs[] __devinitdata = {
+ 	},
+ };
+ 
+-static struct mfd_cell reg_devs[] __devinitdata = {
++static struct mfd_cell reg_devs[] = {
+ 	{
+ 		.name = "88pm860x-regulator",
+ 		.id = 0,
+diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
+index 43245f2ce758..7335a9c8ffae 100644
+--- a/drivers/mfd/ab8500-core.c
++++ b/drivers/mfd/ab8500-core.c
+@@ -623,7 +623,7 @@ static struct resource __devinitdata ab9540_gpio_resources[] = {
+ 	}
+ };
+ 
+-static struct resource __devinitdata ab8500_gpadc_resources[] = {
++static struct resource ab8500_gpadc_resources[] = {
+ 	{
+ 		.name	= "HW_CONV_END",
+ 		.start	= AB8500_INT_GP_HW_ADC_CONV_END,
+@@ -638,7 +638,7 @@ static struct resource __devinitdata ab8500_gpadc_resources[] = {
+ 	},
+ };
+ 
+-static struct resource __devinitdata ab8500_rtc_resources[] = {
++static struct resource ab8500_rtc_resources[] = {
+ 	{
+ 		.name	= "60S",
+ 		.start	= AB8500_INT_RTC_60S,
+@@ -653,7 +653,7 @@ static struct resource __devinitdata ab8500_rtc_resources[] = {
+ 	},
+ };
+ 
+-static struct resource __devinitdata ab8500_poweronkey_db_resources[] = {
++static struct resource ab8500_poweronkey_db_resources[] = {
+ 	{
+ 		.name	= "ONKEY_DBF",
+ 		.start	= AB8500_INT_PON_KEY1DB_F,
+@@ -668,7 +668,7 @@ static struct resource __devinitdata ab8500_poweronkey_db_resources[] = {
+ 	},
+ };
+ 
+-static struct resource __devinitdata ab8500_av_acc_detect_resources[] = {
++static struct resource ab8500_av_acc_detect_resources[] = {
+ 	{
+ 	       .name = "ACC_DETECT_1DB_F",
+ 	       .start = AB8500_INT_ACC_DETECT_1DB_F,
+@@ -707,7 +707,7 @@ static struct resource __devinitdata ab8500_av_acc_detect_resources[] = {
+ 	},
+ };
+ 
+-static struct resource __devinitdata ab8500_charger_resources[] = {
++static struct resource ab8500_charger_resources[] = {
+ 	{
+ 		.name = "MAIN_CH_UNPLUG_DET",
+ 		.start = AB8500_INT_MAIN_CH_UNPLUG_DET,
+@@ -788,7 +788,7 @@ static struct resource __devinitdata ab8500_charger_resources[] = {
+ 	},
+ };
+ 
+-static struct resource __devinitdata ab8500_btemp_resources[] = {
++static struct resource ab8500_btemp_resources[] = {
+ 	{
+ 		.name = "BAT_CTRL_INDB",
+ 		.start = AB8500_INT_BAT_CTRL_INDB,
+@@ -821,7 +821,7 @@ static struct resource __devinitdata ab8500_btemp_resources[] = {
+ 	},
+ };
+ 
+-static struct resource __devinitdata ab8500_fg_resources[] = {
++static struct resource ab8500_fg_resources[] = {
+ 	{
+ 		.name = "NCONV_ACCU",
+ 		.start = AB8500_INT_CCN_CONV_ACC,
+@@ -860,10 +860,10 @@ static struct resource __devinitdata ab8500_fg_resources[] = {
+ 	},
+ };
+ 
+-static struct resource __devinitdata ab8500_chargalg_resources[] = {};
++static struct resource ab8500_chargalg_resources[] = {};
+ 
+ #ifdef CONFIG_DEBUG_FS
+-static struct resource __devinitdata ab8500_debug_resources[] = {
++static struct resource ab8500_debug_resources[] = {
+ 	{
+ 		.name	= "IRQ_FIRST",
+ 		.start	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
+@@ -879,7 +879,7 @@ static struct resource __devinitdata ab8500_debug_resources[] = {
+ };
+ #endif
+ 
+-static struct resource __devinitdata ab8500_usb_resources[] = {
++static struct resource ab8500_usb_resources[] = {
+ 	{
+ 		.name = "ID_WAKEUP_R",
+ 		.start = AB8500_INT_ID_WAKEUP_R,
+@@ -924,7 +924,7 @@ static struct resource __devinitdata ab8500_usb_resources[] = {
+ 	},
+ };
+ 
+-static struct resource __devinitdata ab8505_iddet_resources[] = {
++static struct resource ab8505_iddet_resources[] = {
+ 	{
+ 		.name  = "KeyDeglitch",
+ 		.start = AB8505_INT_KEYDEGLITCH,
+@@ -957,7 +957,7 @@ static struct resource __devinitdata ab8505_iddet_resources[] = {
+ 	},
+ };
+ 
+-static struct resource __devinitdata ab8500_temp_resources[] = {
++static struct resource ab8500_temp_resources[] = {
+ 	{
+ 		.name  = "AB8500_TEMP_WARM",
+ 		.start = AB8500_INT_TEMP_WARM,
+@@ -966,7 +966,7 @@ static struct resource __devinitdata ab8500_temp_resources[] = {
+ 	},
+ };
+ 
+-static struct mfd_cell __devinitdata abx500_common_devs[] = {
++static struct mfd_cell abx500_common_devs[] = {
+ #ifdef CONFIG_DEBUG_FS
+ 	{
+ 		.name = "ab8500-debug",
+@@ -1038,7 +1038,7 @@ static struct mfd_cell __devinitdata abx500_common_devs[] = {
+ 	},
+ };
+ 
+-static struct mfd_cell __devinitdata ab8500_bm_devs[] = {
++static struct mfd_cell ab8500_bm_devs[] = {
+ 	{
+ 		.name = "ab8500-charger",
+ 		.num_resources = ARRAY_SIZE(ab8500_charger_resources),
+@@ -1061,7 +1061,7 @@ static struct mfd_cell __devinitdata ab8500_bm_devs[] = {
+ 	},
+ };
+ 
+-static struct mfd_cell __devinitdata ab8500_devs[] = {
++static struct mfd_cell ab8500_devs[] = {
+ 	{
+ 		.name = "ab8500-gpio",
+ 		.of_compatible = "stericsson,ab8500-gpio",
+@@ -1080,7 +1080,7 @@ static struct mfd_cell __devinitdata ab8500_devs[] = {
+ 	},
+ };
+ 
+-static struct mfd_cell __devinitdata ab9540_devs[] = {
++static struct mfd_cell ab9540_devs[] = {
+ 	{
+ 		.name = "ab8500-gpio",
+ 		.num_resources = ARRAY_SIZE(ab9540_gpio_resources),
+@@ -1097,7 +1097,7 @@ static struct mfd_cell __devinitdata ab9540_devs[] = {
+ };
+ 
+ /* Device list common to ab9540 and ab8505 */
+-static struct mfd_cell __devinitdata ab9540_ab8505_devs[] = {
++static struct mfd_cell ab9540_ab8505_devs[] = {
+ 	{
+ 		.name = "ab-iddet",
+ 		.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
+diff --git a/drivers/mfd/cs5535-mfd.c b/drivers/mfd/cs5535-mfd.c
+index 0779b13a7dd1..d9dc87f067d8 100644
+--- a/drivers/mfd/cs5535-mfd.c
++++ b/drivers/mfd/cs5535-mfd.c
+@@ -71,9 +71,9 @@ static int cs5535_mfd_res_disable(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static __devinitdata struct resource cs5535_mfd_resources[NR_BARS];
++static struct resource cs5535_mfd_resources[NR_BARS];
+ 
+-static __devinitdata struct mfd_cell cs5535_mfd_cells[] = {
++static struct mfd_cell cs5535_mfd_cells[] = {
+ 	{
+ 		.id = SMB_BAR,
+ 		.name = "cs5535-smb",
+diff --git a/drivers/mfd/da9052-core.c b/drivers/mfd/da9052-core.c
+index c71c4a247186..689b747416af 100644
+--- a/drivers/mfd/da9052-core.c
++++ b/drivers/mfd/da9052-core.c
+@@ -515,7 +515,7 @@ static struct resource da9052_tsi_resources[] = {
+ 	},
+ };
+ 
+-static struct mfd_cell __devinitdata da9052_subdev_info[] = {
++static struct mfd_cell da9052_subdev_info[] = {
+ 	{
+ 		.name = "da9052-regulator",
+ 		.id = 1,
+diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
+index 99891752c338..7c83e1b56588 100644
+--- a/drivers/mfd/lpc_ich.c
++++ b/drivers/mfd/lpc_ich.c
+@@ -196,7 +196,7 @@ enum lpc_chipsets {
+ 	LPC_LPT_LP,	/* Lynx Point-LP */
+ };
+ 
+-struct lpc_ich_info lpc_chipset_info[] __devinitdata = {
++struct lpc_ich_info lpc_chipset_info[] = {
+ 	[LPC_ICH] = {
+ 		.name = "ICH",
+ 		.iTCO_version = 1,
+diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c
+index d9e24c849a00..f6878f8db57d 100644
+--- a/drivers/mfd/max77686.c
++++ b/drivers/mfd/max77686.c
+@@ -45,7 +45,7 @@ static struct regmap_config max77686_regmap_config = {
+ };
+ 
+ #ifdef CONFIG_OF
+-static struct of_device_id __devinitdata max77686_pmic_dt_match[] = {
++static struct of_device_id max77686_pmic_dt_match[] = {
+ 	{.compatible = "maxim,max77686",        .data = 0},
+ 	{},
+ };
+diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c
+index 20daa16b83c9..60325c49afda 100644
+--- a/drivers/mfd/max8925-core.c
++++ b/drivers/mfd/max8925-core.c
+@@ -19,12 +19,12 @@
+ #include 
+ #include 
+ 
+-static struct resource bk_resources[] __devinitdata = {
++static struct resource bk_resources[] = {
+ 	{ 0x84, 0x84, "mode control", IORESOURCE_REG, },
+ 	{ 0x85, 0x85, "control",      IORESOURCE_REG, },
+ };
+ 
+-static struct mfd_cell bk_devs[] __devinitdata = {
++static struct mfd_cell bk_devs[] = {
+ 	{
+ 		.name		= "max8925-backlight",
+ 		.num_resources	= ARRAY_SIZE(bk_resources),
+@@ -110,99 +110,99 @@ static struct mfd_cell onkey_devs[] = {
+ 	},
+ };
+ 
+-static struct resource sd1_resources[] __devinitdata = {
++static struct resource sd1_resources[] = {
+ 	{0x06, 0x06, "sdv", IORESOURCE_REG, },
+ };
+ 
+-static struct resource sd2_resources[] __devinitdata = {
++static struct resource sd2_resources[] = {
+ 	{0x09, 0x09, "sdv", IORESOURCE_REG, },
+ };
+ 
+-static struct resource sd3_resources[] __devinitdata = {
++static struct resource sd3_resources[] = {
+ 	{0x0c, 0x0c, "sdv", IORESOURCE_REG, },
+ };
+ 
+-static struct resource ldo1_resources[] __devinitdata = {
++static struct resource ldo1_resources[] = {
+ 	{0x1a, 0x1a, "ldov", IORESOURCE_REG, },
+ };
+ 
+-static struct resource ldo2_resources[] __devinitdata = {
++static struct resource ldo2_resources[] = {
+ 	{0x1e, 0x1e, "ldov", IORESOURCE_REG, },
+ };
+ 
+-static struct resource ldo3_resources[] __devinitdata = {
++static struct resource ldo3_resources[] = {
+ 	{0x22, 0x22, "ldov", IORESOURCE_REG, },
+ };
+ 
+-static struct resource ldo4_resources[] __devinitdata = {
++static struct resource ldo4_resources[] = {
+ 	{0x26, 0x26, "ldov", IORESOURCE_REG, },
+ };
+ 
+-static struct resource ldo5_resources[] __devinitdata = {
++static struct resource ldo5_resources[] = {
+ 	{0x2a, 0x2a, "ldov", IORESOURCE_REG, },
+ };
+ 
+-static struct resource ldo6_resources[] __devinitdata = {
++static struct resource ldo6_resources[] = {
+ 	{0x2e, 0x2e, "ldov", IORESOURCE_REG, },
+ };
+ 
+-static struct resource ldo7_resources[] __devinitdata = {
++static struct resource ldo7_resources[] = {
+ 	{0x32, 0x32, "ldov", IORESOURCE_REG, },
+ };
+ 
+-static struct resource ldo8_resources[] __devinitdata = {
++static struct resource ldo8_resources[] = {
+ 	{0x36, 0x36, "ldov", IORESOURCE_REG, },
+ };
+ 
+-static struct resource ldo9_resources[] __devinitdata = {
++static struct resource ldo9_resources[] = {
+ 	{0x3a, 0x3a, "ldov", IORESOURCE_REG, },
+ };
+ 
+-static struct resource ldo10_resources[] __devinitdata = {
++static struct resource ldo10_resources[] = {
+ 	{0x3e, 0x3e, "ldov", IORESOURCE_REG, },
+ };
+ 
+-static struct resource ldo11_resources[] __devinitdata = {
++static struct resource ldo11_resources[] = {
+ 	{0x42, 0x42, "ldov", IORESOURCE_REG, },
+ };
+ 
+-static struct resource ldo12_resources[] __devinitdata = {
++static struct resource ldo12_resources[] = {
+ 	{0x46, 0x46, "ldov", IORESOURCE_REG, },
+ };
+ 
+-static struct resource ldo13_resources[] __devinitdata = {
++static struct resource ldo13_resources[] = {
+ 	{0x4a, 0x4a, "ldov", IORESOURCE_REG, },
+ };
+ 
+-static struct resource ldo14_resources[] __devinitdata = {
++static struct resource ldo14_resources[] = {
+ 	{0x4e, 0x4e, "ldov", IORESOURCE_REG, },
+ };
+ 
+-static struct resource ldo15_resources[] __devinitdata = {
++static struct resource ldo15_resources[] = {
+ 	{0x52, 0x52, "ldov", IORESOURCE_REG, },
+ };
+ 
+-static struct resource ldo16_resources[] __devinitdata = {
++static struct resource ldo16_resources[] = {
+ 	{0x12, 0x12, "ldov", IORESOURCE_REG, },
+ };
+ 
+-static struct resource ldo17_resources[] __devinitdata = {
++static struct resource ldo17_resources[] = {
+ 	{0x16, 0x16, "ldov", IORESOURCE_REG, },
+ };
+ 
+-static struct resource ldo18_resources[] __devinitdata = {
++static struct resource ldo18_resources[] = {
+ 	{0x74, 0x74, "ldov", IORESOURCE_REG, },
+ };
+ 
+-static struct resource ldo19_resources[] __devinitdata = {
++static struct resource ldo19_resources[] = {
+ 	{0x5e, 0x5e, "ldov", IORESOURCE_REG, },
+ };
+ 
+-static struct resource ldo20_resources[] __devinitdata = {
++static struct resource ldo20_resources[] = {
+ 	{0x9e, 0x9e, "ldov", IORESOURCE_REG, },
+ };
+ 
+-static struct mfd_cell reg_devs[] __devinitdata = {
++static struct mfd_cell reg_devs[] = {
+ 	{
+ 		.name = "max8925-regulator",
+ 		.id = 0,
+diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c
+index cb52783390c1..6ffd7a2affdc 100644
+--- a/drivers/mfd/palmas.c
++++ b/drivers/mfd/palmas.c
+@@ -492,7 +492,7 @@ static const struct i2c_device_id palmas_i2c_id[] = {
+ };
+ MODULE_DEVICE_TABLE(i2c, palmas_i2c_id);
+ 
+-static struct of_device_id __devinitdata of_palmas_match_tbl[] = {
++static struct of_device_id of_palmas_match_tbl[] = {
+ 	{ .compatible = "ti,palmas", },
+ 	{ /* end */ }
+ };
+diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
+index c9c102c49028..9b53733cb297 100644
+--- a/drivers/mfd/sm501.c
++++ b/drivers/mfd/sm501.c
+@@ -1728,7 +1728,7 @@ static struct pci_driver sm501_pci_driver = {
+ 
+ MODULE_ALIAS("platform:sm501");
+ 
+-static struct of_device_id __devinitdata of_sm501_match_tbl[] = {
++static struct of_device_id of_sm501_match_tbl[] = {
+ 	{ .compatible = "smi,sm501", },
+ 	{ /* end */ }
+ };
+diff --git a/drivers/mfd/sta2x11-mfd.c b/drivers/mfd/sta2x11-mfd.c
+index 2cfd55f343c2..1438be54170c 100644
+--- a/drivers/mfd/sta2x11-mfd.c
++++ b/drivers/mfd/sta2x11-mfd.c
+@@ -330,14 +330,14 @@ static const __devinitconst struct resource apbreg_resources[] = {
+ #define DEV(_name, _r) \
+ 	{ .name = _name, .num_resources = ARRAY_SIZE(_r), .resources = _r, }
+ 
+-static __devinitdata struct mfd_cell sta2x11_mfd_bar0[] = {
++static struct mfd_cell sta2x11_mfd_bar0[] = {
+ 	DEV("sta2x11-gpio", gpio_resources), /* offset 0: we add pdata later */
+ 	DEV("sta2x11-sctl", sctl_resources),
+ 	DEV("sta2x11-scr", scr_resources),
+ 	DEV("sta2x11-time", time_resources),
+ };
+ 
+-static __devinitdata struct mfd_cell sta2x11_mfd_bar1[] = {
++static struct mfd_cell sta2x11_mfd_bar1[] = {
+ 	DEV("sta2x11-apbreg", apbreg_resources),
+ };
+ 
+diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
+index 256723231a4e..1ff8ed6390d1 100644
+--- a/drivers/mfd/tc6393xb.c
++++ b/drivers/mfd/tc6393xb.c
+@@ -137,7 +137,7 @@ static int tc6393xb_nand_enable(struct platform_device *nand)
+ 	return 0;
+ }
+ 
+-static struct resource __devinitdata tc6393xb_nand_resources[] = {
++static struct resource tc6393xb_nand_resources[] = {
+ 	{
+ 		.start	= 0x1000,
+ 		.end	= 0x1007,
+@@ -196,7 +196,7 @@ static const struct resource tc6393xb_ohci_resources[] = {
+ 	},
+ };
+ 
+-static struct resource __devinitdata tc6393xb_fb_resources[] = {
++static struct resource tc6393xb_fb_resources[] = {
+ 	{
+ 		.start	= 0x5000,
+ 		.end	= 0x51ff,
+@@ -382,7 +382,7 @@ static struct tmio_mmc_data tc6393xb_mmc_data = {
+ 	.set_clk_div = tc6393xb_mmc_clk_div,
+ };
+ 
+-static struct mfd_cell __devinitdata tc6393xb_cells[] = {
++static struct mfd_cell tc6393xb_cells[] = {
+ 	[TC6393XB_CELL_NAND] = {
+ 		.name = "tmio-nand",
+ 		.enable = tc6393xb_nand_enable,
+diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c
+index dddf1df57838..294e14dcd907 100644
+--- a/drivers/mfd/timberdale.c
++++ b/drivers/mfd/timberdale.c
+@@ -75,13 +75,13 @@ static struct i2c_board_info timberdale_i2c_board_info[] = {
+ 	},
+ };
+ 
+-static __devinitdata struct xiic_i2c_platform_data
++static struct xiic_i2c_platform_data
+ timberdale_xiic_platform_data = {
+ 	.devices = timberdale_i2c_board_info,
+ 	.num_devices = ARRAY_SIZE(timberdale_i2c_board_info)
+ };
+ 
+-static __devinitdata struct ocores_i2c_platform_data
++static struct ocores_i2c_platform_data
+ timberdale_ocores_platform_data = {
+ 	.reg_shift = 2,
+ 	.clock_khz = 62500,
+@@ -143,7 +143,7 @@ static struct spi_board_info timberdale_spi_8bit_board_info[] = {
+ 	},
+ };
+ 
+-static __devinitdata struct xspi_platform_data timberdale_xspi_platform_data = {
++static struct xspi_platform_data timberdale_xspi_platform_data = {
+ 	.num_chipselect = 3,
+ 	.little_endian = true,
+ 	/* bits per word and devices will be filled in runtime depending
+@@ -164,7 +164,7 @@ static const __devinitconst struct resource timberdale_spi_resources[] = {
+ 	},
+ };
+ 
+-static __devinitdata struct ks8842_platform_data
++static struct ks8842_platform_data
+ 	timberdale_ks8842_platform_data = {
+ 	.rx_dma_channel = DMA_ETH_RX,
+ 	.tx_dma_channel = DMA_ETH_TX
+@@ -183,7 +183,7 @@ static const __devinitconst struct resource timberdale_eth_resources[] = {
+ 	},
+ };
+ 
+-static __devinitdata struct timbgpio_platform_data
++static struct timbgpio_platform_data
+ 	timberdale_gpio_platform_data = {
+ 	.gpio_base = 0,
+ 	.nr_pins = GPIO_NR_PINS,
+@@ -247,13 +247,13 @@ static const __devinitconst struct resource timberdale_uartlite_resources[] = {
+ 	},
+ };
+ 
+-static __devinitdata struct i2c_board_info timberdale_adv7180_i2c_board_info = {
++static struct i2c_board_info timberdale_adv7180_i2c_board_info = {
+ 	/* Requires jumper JP9 to be off */
+ 	I2C_BOARD_INFO("adv7180", 0x42 >> 1),
+ 	.irq = IRQ_TIMBERDALE_ADV7180
+ };
+ 
+-static __devinitdata struct timb_video_platform_data
++static struct timb_video_platform_data
+ 	timberdale_video_platform_data = {
+ 	.dma_channel = DMA_VIDEO_RX,
+ 	.i2c_adapter = 0,
+@@ -276,15 +276,15 @@ timberdale_radio_resources[] = {
+ 	},
+ };
+ 
+-static __devinitdata struct i2c_board_info timberdale_tef6868_i2c_board_info = {
++static struct i2c_board_info timberdale_tef6868_i2c_board_info = {
+ 	I2C_BOARD_INFO("tef6862", 0x60)
+ };
+ 
+-static __devinitdata struct i2c_board_info timberdale_saa7706_i2c_board_info = {
++static struct i2c_board_info timberdale_saa7706_i2c_board_info = {
+ 	I2C_BOARD_INFO("saa7706h", 0x1C)
+ };
+ 
+-static __devinitdata struct timb_radio_platform_data
++static struct timb_radio_platform_data
+ 	timberdale_radio_platform_data = {
+ 	.i2c_adapter = 0,
+ 	.tuner = &timberdale_tef6868_i2c_board_info,
+@@ -303,7 +303,7 @@ static const __devinitconst struct resource timberdale_video_resources[] = {
+ 	*/
+ };
+ 
+-static __devinitdata struct timb_dma_platform_data timb_dma_platform_data = {
++static struct timb_dma_platform_data timb_dma_platform_data = {
+ 	.nr_channels = 10,
+ 	.channels = {
+ 		{
+@@ -375,7 +375,7 @@ static const __devinitconst struct resource timberdale_dma_resources[] = {
+ 	},
+ };
+ 
+-static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = {
++static struct mfd_cell timberdale_cells_bar0_cfg0[] = {
+ 	{
+ 		.name = "timb-dma",
+ 		.num_resources = ARRAY_SIZE(timberdale_dma_resources),
+@@ -432,7 +432,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = {
+ 	},
+ };
+ 
+-static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = {
++static struct mfd_cell timberdale_cells_bar0_cfg1[] = {
+ 	{
+ 		.name = "timb-dma",
+ 		.num_resources = ARRAY_SIZE(timberdale_dma_resources),
+@@ -499,7 +499,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = {
+ 	},
+ };
+ 
+-static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = {
++static struct mfd_cell timberdale_cells_bar0_cfg2[] = {
+ 	{
+ 		.name = "timb-dma",
+ 		.num_resources = ARRAY_SIZE(timberdale_dma_resources),
+@@ -549,7 +549,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = {
+ 	},
+ };
+ 
+-static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = {
++static struct mfd_cell timberdale_cells_bar0_cfg3[] = {
+ 	{
+ 		.name = "timb-dma",
+ 		.num_resources = ARRAY_SIZE(timberdale_dma_resources),
+@@ -620,7 +620,7 @@ static const __devinitconst struct resource timberdale_sdhc_resources[] = {
+ 	},
+ };
+ 
+-static __devinitdata struct mfd_cell timberdale_cells_bar1[] = {
++static struct mfd_cell timberdale_cells_bar1[] = {
+ 	{
+ 		.name = "sdhci",
+ 		.num_resources = ARRAY_SIZE(timberdale_sdhc_resources),
+@@ -628,7 +628,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar1[] = {
+ 	},
+ };
+ 
+-static __devinitdata struct mfd_cell timberdale_cells_bar2[] = {
++static struct mfd_cell timberdale_cells_bar2[] = {
+ 	{
+ 		.name = "sdhci",
+ 		.num_resources = ARRAY_SIZE(timberdale_sdhc_resources),

commit f791be492f76dea7b0641ed227a60eeb2fa7e255
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:23:04 2012 -0500
+
+    mfd: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Srinidhi Kasagar 
+    Cc: Peter Tyser 
+    Cc: Daniel Walker 
+    Cc: Bryan Huntsman 
+    Acked-by: David Brown 
+    Acked-by: Mark Brown 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c
+index 321a50cdebf9..6746ecd260ad 100644
+--- a/drivers/mfd/88pm800.c
++++ b/drivers/mfd/88pm800.c
+@@ -248,7 +248,7 @@ static const struct regmap_irq pm800_irqs[] = {
+ 	},
+ };
+ 
+-static int __devinit device_gpadc_init(struct pm80x_chip *chip,
++static int device_gpadc_init(struct pm80x_chip *chip,
+ 				       struct pm80x_platform_data *pdata)
+ {
+ 	struct pm80x_subchip *subchip = chip->subchip;
+@@ -315,7 +315,7 @@ static int __devinit device_gpadc_init(struct pm80x_chip *chip,
+ 	return ret;
+ }
+ 
+-static int __devinit device_irq_init_800(struct pm80x_chip *chip)
++static int device_irq_init_800(struct pm80x_chip *chip)
+ {
+ 	struct regmap *map = chip->regmap;
+ 	unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
+@@ -415,7 +415,7 @@ static void pm800_pages_exit(struct pm80x_chip *chip)
+ 	}
+ }
+ 
+-static int __devinit device_800_init(struct pm80x_chip *chip,
++static int device_800_init(struct pm80x_chip *chip,
+ 				     struct pm80x_platform_data *pdata)
+ {
+ 	int ret, pmic_id;
+@@ -499,7 +499,7 @@ static int __devinit device_800_init(struct pm80x_chip *chip,
+ 	return ret;
+ }
+ 
+-static int __devinit pm800_probe(struct i2c_client *client,
++static int pm800_probe(struct i2c_client *client,
+ 				 const struct i2c_device_id *id)
+ {
+ 	int ret = 0;
+diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c
+index 41e0488b4e3b..13c09941dc2c 100644
+--- a/drivers/mfd/88pm805.c
++++ b/drivers/mfd/88pm805.c
+@@ -135,7 +135,7 @@ static struct regmap_irq pm805_irqs[] = {
+ 	},
+ };
+ 
+-static int __devinit device_irq_init_805(struct pm80x_chip *chip)
++static int device_irq_init_805(struct pm80x_chip *chip)
+ {
+ 	struct regmap *map = chip->regmap;
+ 	unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
+@@ -189,7 +189,7 @@ static struct regmap_irq_chip pm805_irq_chip = {
+ 	.ack_base = PM805_INT_STATUS1,
+ };
+ 
+-static int __devinit device_805_init(struct pm80x_chip *chip)
++static int device_805_init(struct pm80x_chip *chip)
+ {
+ 	int ret = 0;
+ 	unsigned int val;
+@@ -232,7 +232,7 @@ static int __devinit device_805_init(struct pm80x_chip *chip)
+ 	return ret;
+ }
+ 
+-static int __devinit pm805_probe(struct i2c_client *client,
++static int pm805_probe(struct i2c_client *client,
+ 				 const struct i2c_device_id *id)
+ {
+ 	int ret = 0;
+diff --git a/drivers/mfd/88pm80x.c b/drivers/mfd/88pm80x.c
+index cd0bf527d764..1adb355d86d1 100644
+--- a/drivers/mfd/88pm80x.c
++++ b/drivers/mfd/88pm80x.c
+@@ -31,7 +31,7 @@ const struct regmap_config pm80x_regmap_config = {
+ };
+ EXPORT_SYMBOL_GPL(pm80x_regmap_config);
+ 
+-int __devinit pm80x_init(struct i2c_client *client,
++int pm80x_init(struct i2c_client *client,
+ 				 const struct i2c_device_id *id)
+ {
+ 	struct pm80x_chip *chip;
+diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
+index c2d5595e49d0..ad36ad70a0c2 100644
+--- a/drivers/mfd/88pm860x-core.c
++++ b/drivers/mfd/88pm860x-core.c
+@@ -565,7 +565,7 @@ static struct irq_domain_ops pm860x_irq_domain_ops = {
+ 	.xlate	= irq_domain_xlate_onetwocell,
+ };
+ 
+-static int __devinit device_irq_init(struct pm860x_chip *chip,
++static int device_irq_init(struct pm860x_chip *chip,
+ 				     struct pm860x_platform_data *pdata)
+ {
+ 	struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
+@@ -730,7 +730,7 @@ int pm8606_osc_disable(struct pm860x_chip *chip, unsigned short client)
+ }
+ EXPORT_SYMBOL(pm8606_osc_disable);
+ 
+-static void __devinit device_osc_init(struct i2c_client *i2c)
++static void device_osc_init(struct i2c_client *i2c)
+ {
+ 	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
+ 
+@@ -745,7 +745,7 @@ static void __devinit device_osc_init(struct i2c_client *i2c)
+ 	chip->osc_status = PM8606_REF_GP_OSC_OFF;
+ }
+ 
+-static void __devinit device_bk_init(struct pm860x_chip *chip,
++static void device_bk_init(struct pm860x_chip *chip,
+ 				     struct pm860x_platform_data *pdata)
+ {
+ 	int ret, i;
+@@ -765,7 +765,7 @@ static void __devinit device_bk_init(struct pm860x_chip *chip,
+ 		dev_err(chip->dev, "Failed to add backlight subdev\n");
+ }
+ 
+-static void __devinit device_led_init(struct pm860x_chip *chip,
++static void device_led_init(struct pm860x_chip *chip,
+ 				      struct pm860x_platform_data *pdata)
+ {
+ 	int ret, i;
+@@ -787,7 +787,7 @@ static void __devinit device_led_init(struct pm860x_chip *chip,
+ 	}
+ }
+ 
+-static void __devinit device_regulator_init(struct pm860x_chip *chip,
++static void device_regulator_init(struct pm860x_chip *chip,
+ 					    struct pm860x_platform_data *pdata)
+ {
+ 	int ret;
+@@ -866,7 +866,7 @@ static void __devinit device_regulator_init(struct pm860x_chip *chip,
+ 	}
+ }
+ 
+-static void __devinit device_rtc_init(struct pm860x_chip *chip,
++static void device_rtc_init(struct pm860x_chip *chip,
+ 				      struct pm860x_platform_data *pdata)
+ {
+ 	int ret;
+@@ -885,7 +885,7 @@ static void __devinit device_rtc_init(struct pm860x_chip *chip,
+ 		dev_err(chip->dev, "Failed to add rtc subdev\n");
+ }
+ 
+-static void __devinit device_touch_init(struct pm860x_chip *chip,
++static void device_touch_init(struct pm860x_chip *chip,
+ 					struct pm860x_platform_data *pdata)
+ {
+ 	int ret;
+@@ -904,7 +904,7 @@ static void __devinit device_touch_init(struct pm860x_chip *chip,
+ 		dev_err(chip->dev, "Failed to add touch subdev\n");
+ }
+ 
+-static void __devinit device_power_init(struct pm860x_chip *chip,
++static void device_power_init(struct pm860x_chip *chip,
+ 					struct pm860x_platform_data *pdata)
+ {
+ 	int ret;
+@@ -951,7 +951,7 @@ static void __devinit device_power_init(struct pm860x_chip *chip,
+ 	}
+ }
+ 
+-static void __devinit device_onkey_init(struct pm860x_chip *chip,
++static void device_onkey_init(struct pm860x_chip *chip,
+ 					struct pm860x_platform_data *pdata)
+ {
+ 	int ret;
+@@ -965,7 +965,7 @@ static void __devinit device_onkey_init(struct pm860x_chip *chip,
+ 		dev_err(chip->dev, "Failed to add onkey subdev\n");
+ }
+ 
+-static void __devinit device_codec_init(struct pm860x_chip *chip,
++static void device_codec_init(struct pm860x_chip *chip,
+ 					struct pm860x_platform_data *pdata)
+ {
+ 	int ret;
+@@ -979,7 +979,7 @@ static void __devinit device_codec_init(struct pm860x_chip *chip,
+ 		dev_err(chip->dev, "Failed to add codec subdev\n");
+ }
+ 
+-static void __devinit device_8607_init(struct pm860x_chip *chip,
++static void device_8607_init(struct pm860x_chip *chip,
+ 				       struct i2c_client *i2c,
+ 				       struct pm860x_platform_data *pdata)
+ {
+@@ -1040,7 +1040,7 @@ static void __devinit device_8607_init(struct pm860x_chip *chip,
+ 	return;
+ }
+ 
+-static void __devinit device_8606_init(struct pm860x_chip *chip,
++static void device_8606_init(struct pm860x_chip *chip,
+ 				       struct i2c_client *i2c,
+ 				       struct pm860x_platform_data *pdata)
+ {
+@@ -1049,7 +1049,7 @@ static void __devinit device_8606_init(struct pm860x_chip *chip,
+ 	device_led_init(chip, pdata);
+ }
+ 
+-static int __devinit pm860x_device_init(struct pm860x_chip *chip,
++static int pm860x_device_init(struct pm860x_chip *chip,
+ 					struct pm860x_platform_data *pdata)
+ {
+ 	chip->core_irq = 0;
+@@ -1109,7 +1109,7 @@ static struct regmap_config pm860x_regmap_config = {
+ 	.val_bits = 8,
+ };
+ 
+-static int __devinit pm860x_dt_init(struct device_node *np,
++static int pm860x_dt_init(struct device_node *np,
+ 				    struct device *dev,
+ 				    struct pm860x_platform_data *pdata)
+ {
+@@ -1127,7 +1127,7 @@ static int __devinit pm860x_dt_init(struct device_node *np,
+ 	return 0;
+ }
+ 
+-static int __devinit pm860x_probe(struct i2c_client *client,
++static int pm860x_probe(struct i2c_client *client,
+ 				  const struct i2c_device_id *id)
+ {
+ 	struct pm860x_platform_data *pdata = client->dev.platform_data;
+diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
+index 8355d4ee6edd..84b2303bc770 100644
+--- a/drivers/mfd/ab3100-core.c
++++ b/drivers/mfd/ab3100-core.c
+@@ -708,7 +708,7 @@ ab3100_init_settings[] = {
+ 	},
+ };
+ 
+-static int __devinit ab3100_setup(struct ab3100 *ab3100)
++static int ab3100_setup(struct ab3100 *ab3100)
+ {
+ 	int err = 0;
+ 	int i;
+@@ -857,7 +857,7 @@ static const struct ab_family_id ids[] __devinitconst = {
+ 	},
+ };
+ 
+-static int __devinit ab3100_probe(struct i2c_client *client,
++static int ab3100_probe(struct i2c_client *client,
+ 				  const struct i2c_device_id *id)
+ {
+ 	struct ab3100 *ab3100;
+diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
+index 01a0e01f6a6c..43245f2ce758 100644
+--- a/drivers/mfd/ab8500-core.c
++++ b/drivers/mfd/ab8500-core.c
+@@ -1248,7 +1248,7 @@ static struct attribute_group ab9540_attr_group = {
+ 	.attrs	= ab9540_sysfs_entries,
+ };
+ 
+-static int __devinit ab8500_probe(struct platform_device *pdev)
++static int ab8500_probe(struct platform_device *pdev)
+ {
+ 	static char *switch_off_status[] = {
+ 		"Swoff bit programming",
+diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c
+index efdbc7bebd01..44843680d982 100644
+--- a/drivers/mfd/ab8500-debugfs.c
++++ b/drivers/mfd/ab8500-debugfs.c
+@@ -552,7 +552,7 @@ static struct dentry *ab8500_bank_file;
+ static struct dentry *ab8500_address_file;
+ static struct dentry *ab8500_val_file;
+ 
+-static int __devinit ab8500_debug_probe(struct platform_device *plf)
++static int ab8500_debug_probe(struct platform_device *plf)
+ {
+ 	debug_bank = AB8500_MISC;
+ 	debug_address = AB8500_REV_REG & 0x00FF;
+diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c
+index 97daf61f068c..c5e168e3ef11 100644
+--- a/drivers/mfd/ab8500-gpadc.c
++++ b/drivers/mfd/ab8500-gpadc.c
+@@ -571,7 +571,7 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc)
+ 		gpadc->cal_data[ADC_INPUT_VBAT].offset);
+ }
+ 
+-static int __devinit ab8500_gpadc_probe(struct platform_device *pdev)
++static int ab8500_gpadc_probe(struct platform_device *pdev)
+ {
+ 	int ret = 0;
+ 	struct ab8500_gpadc *gpadc;
+diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c
+index d8cc157af3e8..499263c3110a 100644
+--- a/drivers/mfd/ab8500-sysctrl.c
++++ b/drivers/mfd/ab8500-sysctrl.c
+@@ -49,7 +49,7 @@ int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value)
+ 		(u8)(reg & 0xFF), mask, value);
+ }
+ 
+-static int __devinit ab8500_sysctrl_probe(struct platform_device *pdev)
++static int ab8500_sysctrl_probe(struct platform_device *pdev)
+ {
+ 	sysctrl_dev = &pdev->dev;
+ 	return 0;
+diff --git a/drivers/mfd/adp5520.c b/drivers/mfd/adp5520.c
+index f664a52687d5..f2f9d8ff6416 100644
+--- a/drivers/mfd/adp5520.c
++++ b/drivers/mfd/adp5520.c
+@@ -203,7 +203,7 @@ static int adp5520_remove_subdevs(struct adp5520_chip *chip)
+ 	return device_for_each_child(chip->dev, NULL, __remove_subdev);
+ }
+ 
+-static int __devinit adp5520_probe(struct i2c_client *client,
++static int adp5520_probe(struct i2c_client *client,
+ 					const struct i2c_device_id *id)
+ {
+ 	struct adp5520_platform_data *pdata = client->dev.platform_data;
+diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
+index 1b48f2094806..47e711674739 100644
+--- a/drivers/mfd/arizona-core.c
++++ b/drivers/mfd/arizona-core.c
+@@ -285,7 +285,7 @@ static struct mfd_cell wm5110_devs[] = {
+ 	{ .name = "wm5110-codec" },
+ };
+ 
+-int __devinit arizona_dev_init(struct arizona *arizona)
++int arizona_dev_init(struct arizona *arizona)
+ {
+ 	struct device *dev = arizona->dev;
+ 	const char *type_name;
+diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c
+index 43d164736fcb..aaf1a69134df 100644
+--- a/drivers/mfd/arizona-i2c.c
++++ b/drivers/mfd/arizona-i2c.c
+@@ -22,7 +22,7 @@
+ 
+ #include "arizona.h"
+ 
+-static __devinit int arizona_i2c_probe(struct i2c_client *i2c,
++static int arizona_i2c_probe(struct i2c_client *i2c,
+ 					  const struct i2c_device_id *id)
+ {
+ 	struct arizona *arizona;
+diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c
+index cc79b824f706..9663cafdb7ff 100644
+--- a/drivers/mfd/arizona-spi.c
++++ b/drivers/mfd/arizona-spi.c
+@@ -22,7 +22,7 @@
+ 
+ #include "arizona.h"
+ 
+-static int __devinit arizona_spi_probe(struct spi_device *spi)
++static int arizona_spi_probe(struct spi_device *spi)
+ {
+ 	const struct spi_device_id *id = spi_get_device_id(spi);
+ 	struct arizona *arizona;
+diff --git a/drivers/mfd/cs5535-mfd.c b/drivers/mfd/cs5535-mfd.c
+index 5d3878ad39a6..0779b13a7dd1 100644
+--- a/drivers/mfd/cs5535-mfd.c
++++ b/drivers/mfd/cs5535-mfd.c
+@@ -113,7 +113,7 @@ static __devinitdata struct mfd_cell cs5535_mfd_cells[] = {
+ };
+ 
+ #ifdef CONFIG_OLPC
+-static void __devinit cs5535_clone_olpc_cells(void)
++static void cs5535_clone_olpc_cells(void)
+ {
+ 	const char *acpi_clones[] = { "olpc-xo1-pm-acpi", "olpc-xo1-sci-acpi" };
+ 
+@@ -126,7 +126,7 @@ static void __devinit cs5535_clone_olpc_cells(void)
+ static void cs5535_clone_olpc_cells(void) { }
+ #endif
+ 
+-static int __devinit cs5535_mfd_probe(struct pci_dev *pdev,
++static int cs5535_mfd_probe(struct pci_dev *pdev,
+ 		const struct pci_device_id *id)
+ {
+ 	int err, i;
+diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c
+index c715475df377..5fa1e91a9532 100644
+--- a/drivers/mfd/da903x.c
++++ b/drivers/mfd/da903x.c
+@@ -246,7 +246,7 @@ int da903x_query_status(struct device *dev, unsigned int sbits)
+ }
+ EXPORT_SYMBOL(da903x_query_status);
+ 
+-static int __devinit da9030_init_chip(struct da903x_chip *chip)
++static int da9030_init_chip(struct da903x_chip *chip)
+ {
+ 	uint8_t chip_id;
+ 	int err;
+@@ -459,7 +459,7 @@ static int da903x_remove_subdevs(struct da903x_chip *chip)
+ 	return device_for_each_child(chip->dev, NULL, __remove_subdev);
+ }
+ 
+-static int __devinit da903x_add_subdevs(struct da903x_chip *chip,
++static int da903x_add_subdevs(struct da903x_chip *chip,
+ 					struct da903x_platform_data *pdata)
+ {
+ 	struct da903x_subdev_info *subdev;
+@@ -491,7 +491,7 @@ static int __devinit da903x_add_subdevs(struct da903x_chip *chip,
+ 	return ret;
+ }
+ 
+-static int __devinit da903x_probe(struct i2c_client *client,
++static int da903x_probe(struct i2c_client *client,
+ 				  const struct i2c_device_id *id)
+ {
+ 	struct da903x_platform_data *pdata = client->dev.platform_data;
+diff --git a/drivers/mfd/da9052-core.c b/drivers/mfd/da9052-core.c
+index a0a62b24621b..c71c4a247186 100644
+--- a/drivers/mfd/da9052-core.c
++++ b/drivers/mfd/da9052-core.c
+@@ -769,7 +769,7 @@ struct regmap_config da9052_regmap_config = {
+ };
+ EXPORT_SYMBOL_GPL(da9052_regmap_config);
+ 
+-int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id)
++int da9052_device_init(struct da9052 *da9052, u8 chip_id)
+ {
+ 	struct da9052_pdata *pdata = da9052->dev->platform_data;
+ 	int ret;
+diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c
+index 8af0f0c5cefe..96f66ed8dbfc 100644
+--- a/drivers/mfd/da9052-i2c.c
++++ b/drivers/mfd/da9052-i2c.c
+@@ -64,7 +64,7 @@ static const struct of_device_id dialog_dt_ids[] = {
+ };
+ #endif
+ 
+-static int __devinit da9052_i2c_probe(struct i2c_client *client,
++static int da9052_i2c_probe(struct i2c_client *client,
+ 				       const struct i2c_device_id *id)
+ {
+ 	struct da9052 *da9052;
+diff --git a/drivers/mfd/da9052-spi.c b/drivers/mfd/da9052-spi.c
+index cbcc9bebbbe1..1ad324373c97 100644
+--- a/drivers/mfd/da9052-spi.c
++++ b/drivers/mfd/da9052-spi.c
+@@ -21,7 +21,7 @@
+ 
+ #include 
+ 
+-static int __devinit da9052_spi_probe(struct spi_device *spi)
++static int da9052_spi_probe(struct spi_device *spi)
+ {
+ 	int ret;
+ 	const struct spi_device_id *id = spi_get_device_id(spi);
+diff --git a/drivers/mfd/da9055-core.c b/drivers/mfd/da9055-core.c
+index ff6c77f392bd..6f5a4984f0aa 100644
+--- a/drivers/mfd/da9055-core.c
++++ b/drivers/mfd/da9055-core.c
+@@ -377,7 +377,7 @@ static struct regmap_irq_chip da9055_regmap_irq_chip = {
+ 	.num_irqs = ARRAY_SIZE(da9055_irqs),
+ };
+ 
+-int __devinit da9055_device_init(struct da9055 *da9055)
++int da9055_device_init(struct da9055 *da9055)
+ {
+ 	struct da9055_pdata *pdata = da9055->dev->platform_data;
+ 	int ret;
+diff --git a/drivers/mfd/da9055-i2c.c b/drivers/mfd/da9055-i2c.c
+index dbaca7bc36da..7778d042fb5d 100644
+--- a/drivers/mfd/da9055-i2c.c
++++ b/drivers/mfd/da9055-i2c.c
+@@ -18,7 +18,7 @@
+ 
+ #include 
+ 
+-static int __devinit da9055_i2c_probe(struct i2c_client *i2c,
++static int da9055_i2c_probe(struct i2c_client *i2c,
+ 				      const struct i2c_device_id *id)
+ {
+ 	struct da9055 *da9055;
+diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
+index 00b8b0f3dfb6..084a58776837 100644
+--- a/drivers/mfd/db8500-prcmu.c
++++ b/drivers/mfd/db8500-prcmu.c
+@@ -3034,7 +3034,7 @@ static struct mfd_cell db8500_prcmu_devs[] = {
+  * prcmu_fw_init - arch init call for the Linux PRCMU fw init logic
+  *
+  */
+-static int __devinit db8500_prcmu_probe(struct platform_device *pdev)
++static int db8500_prcmu_probe(struct platform_device *pdev)
+ {
+ 	struct ab8500_platform_data *ab8500_platdata = pdev->dev.platform_data;
+ 	struct device_node *np = pdev->dev.of_node;
+diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c
+index d7e4de041526..d81505e50d12 100644
+--- a/drivers/mfd/ezx-pcap.c
++++ b/drivers/mfd/ezx-pcap.c
+@@ -371,7 +371,7 @@ static int pcap_remove_subdev(struct device *dev, void *unused)
+ 	return 0;
+ }
+ 
+-static int __devinit pcap_add_subdev(struct pcap_chip *pcap,
++static int pcap_add_subdev(struct pcap_chip *pcap,
+ 						struct pcap_subdev *subdev)
+ {
+ 	struct platform_device *pdev;
+@@ -420,7 +420,7 @@ static int __devexit ezx_pcap_remove(struct spi_device *spi)
+ 	return 0;
+ }
+ 
+-static int __devinit ezx_pcap_probe(struct spi_device *spi)
++static int ezx_pcap_probe(struct spi_device *spi)
+ {
+ 	struct pcap_platform_data *pdata = spi->dev.platform_data;
+ 	struct pcap_chip *pcap;
+diff --git a/drivers/mfd/htc-i2cpld.c b/drivers/mfd/htc-i2cpld.c
+index d55065cc324c..324187c0c124 100644
+--- a/drivers/mfd/htc-i2cpld.c
++++ b/drivers/mfd/htc-i2cpld.c
+@@ -327,7 +327,7 @@ static void htcpld_chip_reset(struct i2c_client *client)
+ 		client, (chip_data->cache_out = chip_data->reset));
+ }
+ 
+-static int __devinit htcpld_setup_chip_irq(
++static int htcpld_setup_chip_irq(
+ 		struct platform_device *pdev,
+ 		int chip_index)
+ {
+@@ -361,7 +361,7 @@ static int __devinit htcpld_setup_chip_irq(
+ 	return ret;
+ }
+ 
+-static int __devinit htcpld_register_chip_i2c(
++static int htcpld_register_chip_i2c(
+ 		struct platform_device *pdev,
+ 		int chip_index)
+ {
+@@ -419,7 +419,7 @@ static int __devinit htcpld_register_chip_i2c(
+ 	return 0;
+ }
+ 
+-static void __devinit htcpld_unregister_chip_i2c(
++static void htcpld_unregister_chip_i2c(
+ 		struct platform_device *pdev,
+ 		int chip_index)
+ {
+@@ -434,7 +434,7 @@ static void __devinit htcpld_unregister_chip_i2c(
+ 		i2c_unregister_device(chip->client);
+ }
+ 
+-static int __devinit htcpld_register_chip_gpio(
++static int htcpld_register_chip_gpio(
+ 		struct platform_device *pdev,
+ 		int chip_index)
+ {
+@@ -501,7 +501,7 @@ static int __devinit htcpld_register_chip_gpio(
+ 	return 0;
+ }
+ 
+-static int __devinit htcpld_setup_chips(struct platform_device *pdev)
++static int htcpld_setup_chips(struct platform_device *pdev)
+ {
+ 	struct htcpld_data *htcpld;
+ 	struct device *dev = &pdev->dev;
+@@ -563,7 +563,7 @@ static int __devinit htcpld_setup_chips(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devinit htcpld_core_probe(struct platform_device *pdev)
++static int htcpld_core_probe(struct platform_device *pdev)
+ {
+ 	struct htcpld_data *htcpld;
+ 	struct device *dev = &pdev->dev;
+diff --git a/drivers/mfd/intel_msic.c b/drivers/mfd/intel_msic.c
+index c5f478eb4e18..438ac3df166b 100644
+--- a/drivers/mfd/intel_msic.c
++++ b/drivers/mfd/intel_msic.c
+@@ -306,7 +306,7 @@ int intel_msic_irq_read(struct intel_msic *msic, unsigned short reg, u8 *val)
+ }
+ EXPORT_SYMBOL_GPL(intel_msic_irq_read);
+ 
+-static int __devinit intel_msic_init_devices(struct intel_msic *msic)
++static int intel_msic_init_devices(struct intel_msic *msic)
+ {
+ 	struct platform_device *pdev = msic->pdev;
+ 	struct intel_msic_platform_data *pdata = pdev->dev.platform_data;
+@@ -375,7 +375,7 @@ static void __devexit intel_msic_remove_devices(struct intel_msic *msic)
+ 		gpio_free(pdata->ocd->gpio);
+ }
+ 
+-static int __devinit intel_msic_probe(struct platform_device *pdev)
++static int intel_msic_probe(struct platform_device *pdev)
+ {
+ 	struct intel_msic_platform_data *pdata = pdev->dev.platform_data;
+ 	struct intel_msic *msic;
+diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c
+index 1a3627784246..55c479e57aad 100644
+--- a/drivers/mfd/janz-cmodio.c
++++ b/drivers/mfd/janz-cmodio.c
+@@ -63,7 +63,7 @@ struct cmodio_device {
+  * Subdevices using the mfd-core API
+  */
+ 
+-static int __devinit cmodio_setup_subdevice(struct cmodio_device *priv,
++static int cmodio_setup_subdevice(struct cmodio_device *priv,
+ 					    char *name, unsigned int devno,
+ 					    unsigned int modno)
+ {
+@@ -120,7 +120,7 @@ static int __devinit cmodio_setup_subdevice(struct cmodio_device *priv,
+ }
+ 
+ /* Probe each submodule using kernel parameters */
+-static int __devinit cmodio_probe_submodules(struct cmodio_device *priv)
++static int cmodio_probe_submodules(struct cmodio_device *priv)
+ {
+ 	struct pci_dev *pdev = priv->pdev;
+ 	unsigned int num_probed = 0;
+@@ -177,7 +177,7 @@ static const struct attribute_group cmodio_sysfs_attr_group = {
+  * PCI Driver
+  */
+ 
+-static int __devinit cmodio_pci_probe(struct pci_dev *dev,
++static int cmodio_pci_probe(struct pci_dev *dev,
+ 				      const struct pci_device_id *id)
+ {
+ 	struct cmodio_device *priv;
+diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c
+index 9aed2a66180e..c0d38c597f0c 100644
+--- a/drivers/mfd/jz4740-adc.c
++++ b/drivers/mfd/jz4740-adc.c
+@@ -202,7 +202,7 @@ static struct mfd_cell jz4740_adc_cells[] = {
+ 	},
+ };
+ 
+-static int __devinit jz4740_adc_probe(struct platform_device *pdev)
++static int jz4740_adc_probe(struct platform_device *pdev)
+ {
+ 	struct irq_chip_generic *gc;
+ 	struct irq_chip_type *ct;
+diff --git a/drivers/mfd/lm3533-core.c b/drivers/mfd/lm3533-core.c
+index e7aa2a5a826b..2b74508655d4 100644
+--- a/drivers/mfd/lm3533-core.c
++++ b/drivers/mfd/lm3533-core.c
+@@ -382,7 +382,7 @@ static struct attribute_group lm3533_attribute_group = {
+ 	.attrs		= lm3533_attributes
+ };
+ 
+-static int __devinit lm3533_device_als_init(struct lm3533 *lm3533)
++static int lm3533_device_als_init(struct lm3533 *lm3533)
+ {
+ 	struct lm3533_platform_data *pdata = lm3533->dev->platform_data;
+ 	int ret;
+@@ -405,7 +405,7 @@ static int __devinit lm3533_device_als_init(struct lm3533 *lm3533)
+ 	return 0;
+ }
+ 
+-static int __devinit lm3533_device_bl_init(struct lm3533 *lm3533)
++static int lm3533_device_bl_init(struct lm3533 *lm3533)
+ {
+ 	struct lm3533_platform_data *pdata = lm3533->dev->platform_data;
+ 	int i;
+@@ -434,7 +434,7 @@ static int __devinit lm3533_device_bl_init(struct lm3533 *lm3533)
+ 	return 0;
+ }
+ 
+-static int __devinit lm3533_device_led_init(struct lm3533 *lm3533)
++static int lm3533_device_led_init(struct lm3533 *lm3533)
+ {
+ 	struct lm3533_platform_data *pdata = lm3533->dev->platform_data;
+ 	int i;
+@@ -463,7 +463,7 @@ static int __devinit lm3533_device_led_init(struct lm3533 *lm3533)
+ 	return 0;
+ }
+ 
+-static int __devinit lm3533_device_setup(struct lm3533 *lm3533,
++static int lm3533_device_setup(struct lm3533 *lm3533,
+ 					struct lm3533_platform_data *pdata)
+ {
+ 	int ret;
+@@ -479,7 +479,7 @@ static int __devinit lm3533_device_setup(struct lm3533 *lm3533,
+ 	return 0;
+ }
+ 
+-static int __devinit lm3533_device_init(struct lm3533 *lm3533)
++static int lm3533_device_init(struct lm3533 *lm3533)
+ {
+ 	struct lm3533_platform_data *pdata = lm3533->dev->platform_data;
+ 	int ret;
+@@ -596,7 +596,7 @@ static struct regmap_config regmap_config = {
+ 	.precious_reg	= lm3533_precious_register,
+ };
+ 
+-static int __devinit lm3533_i2c_probe(struct i2c_client *i2c,
++static int lm3533_i2c_probe(struct i2c_client *i2c,
+ 					const struct i2c_device_id *id)
+ {
+ 	struct lm3533 *lm3533;
+diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
+index a43c73ac25b0..99891752c338 100644
+--- a/drivers/mfd/lpc_ich.c
++++ b/drivers/mfd/lpc_ich.c
+@@ -672,7 +672,7 @@ static void lpc_ich_restore_config_space(struct pci_dev *dev)
+ 	}
+ }
+ 
+-static void __devinit lpc_ich_enable_acpi_space(struct pci_dev *dev)
++static void lpc_ich_enable_acpi_space(struct pci_dev *dev)
+ {
+ 	u8 reg_save;
+ 
+@@ -681,7 +681,7 @@ static void __devinit lpc_ich_enable_acpi_space(struct pci_dev *dev)
+ 	lpc_ich_acpi_save = reg_save;
+ }
+ 
+-static void __devinit lpc_ich_enable_gpio_space(struct pci_dev *dev)
++static void lpc_ich_enable_gpio_space(struct pci_dev *dev)
+ {
+ 	u8 reg_save;
+ 
+@@ -690,7 +690,7 @@ static void __devinit lpc_ich_enable_gpio_space(struct pci_dev *dev)
+ 	lpc_ich_gpio_save = reg_save;
+ }
+ 
+-static void __devinit lpc_ich_finalize_cell(struct mfd_cell *cell,
++static void lpc_ich_finalize_cell(struct mfd_cell *cell,
+ 					const struct pci_device_id *id)
+ {
+ 	cell->platform_data = &lpc_chipset_info[id->driver_data];
+@@ -702,7 +702,7 @@ static void __devinit lpc_ich_finalize_cell(struct mfd_cell *cell,
+  * GPIO groups and it's enough to have access to one of these to instantiate
+  * the device.
+  */
+-static int __devinit lpc_ich_check_conflict_gpio(struct resource *res)
++static int lpc_ich_check_conflict_gpio(struct resource *res)
+ {
+ 	int ret;
+ 	u8 use_gpio = 0;
+@@ -721,7 +721,7 @@ static int __devinit lpc_ich_check_conflict_gpio(struct resource *res)
+ 	return use_gpio ? use_gpio : ret;
+ }
+ 
+-static int __devinit lpc_ich_init_gpio(struct pci_dev *dev,
++static int lpc_ich_init_gpio(struct pci_dev *dev,
+ 				const struct pci_device_id *id)
+ {
+ 	u32 base_addr_cfg;
+@@ -798,7 +798,7 @@ static int __devinit lpc_ich_init_gpio(struct pci_dev *dev,
+ 	return ret;
+ }
+ 
+-static int __devinit lpc_ich_init_wdt(struct pci_dev *dev,
++static int lpc_ich_init_wdt(struct pci_dev *dev,
+ 				const struct pci_device_id *id)
+ {
+ 	u32 base_addr_cfg;
+@@ -852,7 +852,7 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev,
+ 	return ret;
+ }
+ 
+-static int __devinit lpc_ich_probe(struct pci_dev *dev,
++static int lpc_ich_probe(struct pci_dev *dev,
+ 				const struct pci_device_id *id)
+ {
+ 	int ret;
+diff --git a/drivers/mfd/lpc_sch.c b/drivers/mfd/lpc_sch.c
+index 27477f4533ea..5756a6af08dc 100644
+--- a/drivers/mfd/lpc_sch.c
++++ b/drivers/mfd/lpc_sch.c
+@@ -83,7 +83,7 @@ static DEFINE_PCI_DEVICE_TABLE(lpc_sch_ids) = {
+ };
+ MODULE_DEVICE_TABLE(pci, lpc_sch_ids);
+ 
+-static int __devinit lpc_sch_probe(struct pci_dev *dev,
++static int lpc_sch_probe(struct pci_dev *dev,
+ 				const struct pci_device_id *id)
+ {
+ 	unsigned int base_addr_cfg;
+diff --git a/drivers/mfd/max8907.c b/drivers/mfd/max8907.c
+index 17f2593d82b8..81ded7a4ca8c 100644
+--- a/drivers/mfd/max8907.c
++++ b/drivers/mfd/max8907.c
+@@ -183,7 +183,7 @@ static void max8907_power_off(void)
+ 			MAX8907_MASK_POWER_OFF, MAX8907_MASK_POWER_OFF);
+ }
+ 
+-static __devinit int max8907_i2c_probe(struct i2c_client *i2c,
++static int max8907_i2c_probe(struct i2c_client *i2c,
+ 				       const struct i2c_device_id *id)
+ {
+ 	struct max8907 *max8907;
+diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c
+index 9f54c04912f2..20daa16b83c9 100644
+--- a/drivers/mfd/max8925-core.c
++++ b/drivers/mfd/max8925-core.c
+@@ -714,7 +714,7 @@ static int max8925_irq_init(struct max8925_chip *chip, int irq,
+ 	return 0;
+ }
+ 
+-static void __devinit init_regulator(struct max8925_chip *chip,
++static void init_regulator(struct max8925_chip *chip,
+ 				     struct max8925_platform_data *pdata)
+ {
+ 	int ret;
+@@ -821,7 +821,7 @@ static void __devinit init_regulator(struct max8925_chip *chip,
+ 	}
+ }
+ 
+-int __devinit max8925_device_init(struct max8925_chip *chip,
++int max8925_device_init(struct max8925_chip *chip,
+ 				  struct max8925_platform_data *pdata)
+ {
+ 	int ret;
+diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c
+index 375e0475f6d2..6e3d30aa00df 100644
+--- a/drivers/mfd/max8925-i2c.c
++++ b/drivers/mfd/max8925-i2c.c
+@@ -135,7 +135,7 @@ static const struct i2c_device_id max8925_id_table[] = {
+ };
+ MODULE_DEVICE_TABLE(i2c, max8925_id_table);
+ 
+-static int __devinit max8925_probe(struct i2c_client *client,
++static int max8925_probe(struct i2c_client *client,
+ 				   const struct i2c_device_id *id)
+ {
+ 	struct max8925_platform_data *pdata = client->dev.platform_data;
+diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
+index 23cec57c02ba..fc23dfbb6910 100644
+--- a/drivers/mfd/omap-usb-host.c
++++ b/drivers/mfd/omap-usb-host.c
+@@ -464,7 +464,7 @@ static void omap_usbhs_deinit(struct device *dev)
+  *
+  * Allocates basic resources for this USB host controller.
+  */
+-static int __devinit usbhs_omap_probe(struct platform_device *pdev)
++static int usbhs_omap_probe(struct platform_device *pdev)
+ {
+ 	struct device			*dev =  &pdev->dev;
+ 	struct usbhs_omap_platform_data	*pdata = dev->platform_data;
+diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
+index 2d8edfd85e1c..0b586885446b 100644
+--- a/drivers/mfd/omap-usb-tll.c
++++ b/drivers/mfd/omap-usb-tll.c
+@@ -200,7 +200,7 @@ static unsigned ohci_omap3_fslsmode(enum usbhs_omap_port_mode mode)
+  *
+  * Allocates basic resources for this USB host controller.
+  */
+-static int __devinit usbtll_omap_probe(struct platform_device *pdev)
++static int usbtll_omap_probe(struct platform_device *pdev)
+ {
+ 	struct device				*dev =  &pdev->dev;
+ 	struct usbtll_omap_platform_data	*pdata = dev->platform_data;
+diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c
+index 4f8d6e6b19aa..cb52783390c1 100644
+--- a/drivers/mfd/palmas.c
++++ b/drivers/mfd/palmas.c
+@@ -247,7 +247,7 @@ static struct regmap_irq_chip palmas_irq_chip = {
+ 			PALMAS_INT1_MASK),
+ };
+ 
+-static void __devinit palmas_dt_to_pdata(struct device_node *node,
++static void palmas_dt_to_pdata(struct device_node *node,
+ 		struct palmas_platform_data *pdata)
+ {
+ 	int ret;
+@@ -275,7 +275,7 @@ static void __devinit palmas_dt_to_pdata(struct device_node *node,
+ 					PALMAS_POWER_CTRL_ENABLE2_MASK;
+ }
+ 
+-static int __devinit palmas_i2c_probe(struct i2c_client *i2c,
++static int palmas_i2c_probe(struct i2c_client *i2c,
+ 			    const struct i2c_device_id *id)
+ {
+ 	struct palmas *palmas;
+diff --git a/drivers/mfd/pcf50633-adc.c b/drivers/mfd/pcf50633-adc.c
+index a285b5111edb..dbd2f0d0078e 100644
+--- a/drivers/mfd/pcf50633-adc.c
++++ b/drivers/mfd/pcf50633-adc.c
+@@ -199,7 +199,7 @@ static void pcf50633_adc_irq(int irq, void *data)
+ 	kfree(req);
+ }
+ 
+-static int __devinit pcf50633_adc_probe(struct platform_device *pdev)
++static int pcf50633_adc_probe(struct platform_device *pdev)
+ {
+ 	struct pcf50633_adc *adc;
+ 
+diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c
+index ad438e85cbf7..fc477353081e 100644
+--- a/drivers/mfd/pcf50633-core.c
++++ b/drivers/mfd/pcf50633-core.c
+@@ -191,7 +191,7 @@ static struct regmap_config pcf50633_regmap_config = {
+ 	.val_bits = 8,
+ };
+ 
+-static int __devinit pcf50633_probe(struct i2c_client *client,
++static int pcf50633_probe(struct i2c_client *client,
+ 				const struct i2c_device_id *ids)
+ {
+ 	struct pcf50633 *pcf;
+diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
+index 24d57bcc98b6..43491346e7d0 100644
+--- a/drivers/mfd/pm8921-core.c
++++ b/drivers/mfd/pm8921-core.c
+@@ -80,7 +80,7 @@ static struct pm8xxx_drvdata pm8921_drvdata = {
+ 	.pmic_read_irq_stat	= pm8921_read_irq_stat,
+ };
+ 
+-static int __devinit pm8921_add_subdevices(const struct pm8921_platform_data
++static int pm8921_add_subdevices(const struct pm8921_platform_data
+ 					   *pdata,
+ 					   struct pm8921 *pmic,
+ 					   u32 rev)
+@@ -104,7 +104,7 @@ static int __devinit pm8921_add_subdevices(const struct pm8921_platform_data
+ 	return ret;
+ }
+ 
+-static int __devinit pm8921_probe(struct platform_device *pdev)
++static int pm8921_probe(struct platform_device *pdev)
+ {
+ 	const struct pm8921_platform_data *pdata = pdev->dev.platform_data;
+ 	struct pm8921 *pmic;
+diff --git a/drivers/mfd/pm8xxx-irq.c b/drivers/mfd/pm8xxx-irq.c
+index d452dd013081..59c20ea329de 100644
+--- a/drivers/mfd/pm8xxx-irq.c
++++ b/drivers/mfd/pm8xxx-irq.c
+@@ -309,7 +309,7 @@ int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq)
+ }
+ EXPORT_SYMBOL_GPL(pm8xxx_get_irq_stat);
+ 
+-struct pm_irq_chip *  __devinit pm8xxx_irq_init(struct device *dev,
++struct pm_irq_chip *  pm8xxx_irq_init(struct device *dev,
+ 				const struct pm8xxx_irq_platform_data *pdata)
+ {
+ 	struct pm_irq_chip  *chip;
+diff --git a/drivers/mfd/rc5t583.c b/drivers/mfd/rc5t583.c
+index d38ee24302ca..f721b13e986c 100644
+--- a/drivers/mfd/rc5t583.c
++++ b/drivers/mfd/rc5t583.c
+@@ -246,7 +246,7 @@ static const struct regmap_config rc5t583_regmap_config = {
+ 	.cache_type = REGCACHE_RBTREE,
+ };
+ 
+-static int __devinit rc5t583_i2c_probe(struct i2c_client *i2c,
++static int rc5t583_i2c_probe(struct i2c_client *i2c,
+ 			      const struct i2c_device_id *id)
+ {
+ 	struct rc5t583 *rc5t583;
+diff --git a/drivers/mfd/rdc321x-southbridge.c b/drivers/mfd/rdc321x-southbridge.c
+index 330396306d62..be46539c3080 100644
+--- a/drivers/mfd/rdc321x-southbridge.c
++++ b/drivers/mfd/rdc321x-southbridge.c
+@@ -72,7 +72,7 @@ static struct mfd_cell rdc321x_sb_cells[] = {
+ 	},
+ };
+ 
+-static int __devinit rdc321x_sb_probe(struct pci_dev *pdev,
++static int rdc321x_sb_probe(struct pci_dev *pdev,
+ 					const struct pci_device_id *ent)
+ {
+ 	int err;
+diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
+index 777af5ec25d4..c9c102c49028 100644
+--- a/drivers/mfd/sm501.c
++++ b/drivers/mfd/sm501.c
+@@ -1014,7 +1014,7 @@ static struct gpio_chip gpio_chip_template = {
+ 	.get			= sm501_gpio_get,
+ };
+ 
+-static int __devinit sm501_gpio_register_chip(struct sm501_devdata *sm,
++static int sm501_gpio_register_chip(struct sm501_devdata *sm,
+ 					      struct sm501_gpio *gpio,
+ 					      struct sm501_gpio_chip *chip)
+ {
+@@ -1042,7 +1042,7 @@ static int __devinit sm501_gpio_register_chip(struct sm501_devdata *sm,
+ 	return gpiochip_add(gchip);
+ }
+ 
+-static int __devinit sm501_register_gpio(struct sm501_devdata *sm)
++static int sm501_register_gpio(struct sm501_devdata *sm)
+ {
+ 	struct sm501_gpio *gpio = &sm->gpio;
+ 	resource_size_t iobase = sm->io_res->start + SM501_GPIO;
+@@ -1313,7 +1313,7 @@ static unsigned int sm501_mem_local[] = {
+  * Common init code for an SM501
+ */
+ 
+-static int __devinit sm501_init_dev(struct sm501_devdata *sm)
++static int sm501_init_dev(struct sm501_devdata *sm)
+ {
+ 	struct sm501_initdata *idata;
+ 	struct sm501_platdata *pdata;
+@@ -1389,7 +1389,7 @@ static int __devinit sm501_init_dev(struct sm501_devdata *sm)
+ 	return 0;
+ }
+ 
+-static int __devinit sm501_plat_probe(struct platform_device *dev)
++static int sm501_plat_probe(struct platform_device *dev)
+ {
+ 	struct sm501_devdata *sm;
+ 	int ret;
+@@ -1578,7 +1578,7 @@ static struct sm501_platdata sm501_pci_platdata = {
+ 	.gpio_base	= -1,
+ };
+ 
+-static int __devinit sm501_pci_probe(struct pci_dev *dev,
++static int sm501_pci_probe(struct pci_dev *dev,
+ 				     const struct pci_device_id *id)
+ {
+ 	struct sm501_devdata *sm;
+diff --git a/drivers/mfd/sta2x11-mfd.c b/drivers/mfd/sta2x11-mfd.c
+index d35da6820bea..2cfd55f343c2 100644
+--- a/drivers/mfd/sta2x11-mfd.c
++++ b/drivers/mfd/sta2x11-mfd.c
+@@ -69,7 +69,7 @@ static struct sta2x11_mfd *sta2x11_mfd_find(struct pci_dev *pdev)
+ 	return NULL;
+ }
+ 
+-static int __devinit sta2x11_mfd_add(struct pci_dev *pdev, gfp_t flags)
++static int sta2x11_mfd_add(struct pci_dev *pdev, gfp_t flags)
+ {
+ 	struct sta2x11_mfd *mfd = sta2x11_mfd_find(pdev);
+ 	struct sta2x11_instance *instance;
+@@ -363,7 +363,7 @@ static int sta2x11_mfd_resume(struct pci_dev *pdev)
+ 	return 0;
+ }
+ 
+-static int __devinit sta2x11_mfd_probe(struct pci_dev *pdev,
++static int sta2x11_mfd_probe(struct pci_dev *pdev,
+ 				       const struct pci_device_id *pci_id)
+ {
+ 	int err, i;
+diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c
+index 6a6aed74b946..8195ca2ac74b 100644
+--- a/drivers/mfd/stmpe-i2c.c
++++ b/drivers/mfd/stmpe-i2c.c
+@@ -52,7 +52,7 @@ static struct stmpe_client_info i2c_ci = {
+ 	.write_block = i2c_block_write,
+ };
+ 
+-static int __devinit
++static int
+ stmpe_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
+ {
+ 	i2c_ci.data = (void *)id;
+diff --git a/drivers/mfd/stmpe-spi.c b/drivers/mfd/stmpe-spi.c
+index 29590ad6a6e4..52774338998f 100644
+--- a/drivers/mfd/stmpe-spi.c
++++ b/drivers/mfd/stmpe-spi.c
+@@ -82,7 +82,7 @@ static struct stmpe_client_info spi_ci = {
+ 	.init = spi_init,
+ };
+ 
+-static int __devinit
++static int
+ stmpe_spi_probe(struct spi_device *spi)
+ {
+ 	const struct spi_device_id *id = spi_get_device_id(spi);
+diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
+index d258b595d0b7..3dbfe9ab889c 100644
+--- a/drivers/mfd/syscon.c
++++ b/drivers/mfd/syscon.c
+@@ -97,7 +97,7 @@ static struct regmap_config syscon_regmap_config = {
+ 	.reg_stride = 4,
+ };
+ 
+-static int __devinit syscon_probe(struct platform_device *pdev)
++static int syscon_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	struct device_node *np = dev->of_node;
+diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c
+index 553ce956da6d..7e197f788b0a 100644
+--- a/drivers/mfd/tc3589x.c
++++ b/drivers/mfd/tc3589x.c
+@@ -282,7 +282,7 @@ static int tc3589x_chip_init(struct tc3589x *tc3589x)
+ 	return tc3589x_reg_write(tc3589x, TC3589x_RSTINTCLR, 0x1);
+ }
+ 
+-static int __devinit tc3589x_device_init(struct tc3589x *tc3589x)
++static int tc3589x_device_init(struct tc3589x *tc3589x)
+ {
+ 	int ret = 0;
+ 	unsigned int blocks = tc3589x->pdata->block;
+@@ -329,7 +329,7 @@ static int tc3589x_of_probe(struct device_node *np,
+ 	return 0;
+ }
+ 
+-static int __devinit tc3589x_probe(struct i2c_client *i2c,
++static int tc3589x_probe(struct i2c_client *i2c,
+ 				   const struct i2c_device_id *id)
+ {
+ 	struct tc3589x_platform_data *pdata = i2c->dev.platform_data;
+diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c
+index 186f053e36ef..ca18f262c34a 100644
+--- a/drivers/mfd/tc6387xb.c
++++ b/drivers/mfd/tc6387xb.c
+@@ -138,7 +138,7 @@ static struct mfd_cell tc6387xb_cells[] = {
+ 	},
+ };
+ 
+-static int __devinit tc6387xb_probe(struct platform_device *dev)
++static int tc6387xb_probe(struct platform_device *dev)
+ {
+ 	struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
+ 	struct resource *iomem, *rscr;
+diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
+index 9411a88770b8..256723231a4e 100644
+--- a/drivers/mfd/tc6393xb.c
++++ b/drivers/mfd/tc6393xb.c
+@@ -602,7 +602,7 @@ static void tc6393xb_detach_irq(struct platform_device *dev)
+ 
+ /*--------------------------------------------------------------------------*/
+ 
+-static int __devinit tc6393xb_probe(struct platform_device *dev)
++static int tc6393xb_probe(struct platform_device *dev)
+ {
+ 	struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
+ 	struct tc6393xb *tc6393xb;
+diff --git a/drivers/mfd/ti-ssp.c b/drivers/mfd/ti-ssp.c
+index 1c31f877c6bb..b177f96da864 100644
+--- a/drivers/mfd/ti-ssp.c
++++ b/drivers/mfd/ti-ssp.c
+@@ -315,7 +315,7 @@ static irqreturn_t ti_ssp_interrupt(int irq, void *dev_data)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit ti_ssp_probe(struct platform_device *pdev)
++static int ti_ssp_probe(struct platform_device *pdev)
+ {
+ 	static struct ti_ssp *ssp;
+ 	const struct ti_ssp_data *pdata = pdev->dev.platform_data;
+diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c
+index 61badece0b9a..dddf1df57838 100644
+--- a/drivers/mfd/timberdale.c
++++ b/drivers/mfd/timberdale.c
+@@ -650,7 +650,7 @@ static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
+ 
+ /*--------------------------------------------------------------------------*/
+ 
+-static int __devinit timb_probe(struct pci_dev *dev,
++static int timb_probe(struct pci_dev *dev,
+ 	const struct pci_device_id *id)
+ {
+ 	struct timberdale_device *priv;
+diff --git a/drivers/mfd/tps6105x.c b/drivers/mfd/tps6105x.c
+index 45389600f86e..75a84ac4672e 100644
+--- a/drivers/mfd/tps6105x.c
++++ b/drivers/mfd/tps6105x.c
+@@ -86,7 +86,7 @@ int tps6105x_mask_and_set(struct tps6105x *tps6105x, u8 reg,
+ }
+ EXPORT_SYMBOL(tps6105x_mask_and_set);
+ 
+-static int __devinit tps6105x_startup(struct tps6105x *tps6105x)
++static int tps6105x_startup(struct tps6105x *tps6105x)
+ {
+ 	int ret;
+ 	u8 regval;
+@@ -133,7 +133,7 @@ static struct mfd_cell tps6105x_cells[] = {
+ 	},
+ };
+ 
+-static int __devinit tps6105x_probe(struct i2c_client *client,
++static int tps6105x_probe(struct i2c_client *client,
+ 			const struct i2c_device_id *id)
+ {
+ 	struct tps6105x			*tps6105x;
+diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c
+index d43ff16d8c4c..0c446eb86bdb 100644
+--- a/drivers/mfd/tps65090.c
++++ b/drivers/mfd/tps65090.c
+@@ -188,7 +188,7 @@ static irqreturn_t tps65090_irq(int irq, void *data)
+ 	return acks ? IRQ_HANDLED : IRQ_NONE;
+ }
+ 
+-static int __devinit tps65090_irq_init(struct tps65090 *tps65090, int irq,
++static int tps65090_irq_init(struct tps65090 *tps65090, int irq,
+ 	int irq_base)
+ {
+ 	int i, ret;
+@@ -251,7 +251,7 @@ static const struct regmap_config tps65090_regmap_config = {
+ 	.volatile_reg = is_volatile_reg,
+ };
+ 
+-static int __devinit tps65090_i2c_probe(struct i2c_client *client,
++static int tps65090_i2c_probe(struct i2c_client *client,
+ 					const struct i2c_device_id *id)
+ {
+ 	struct tps65090_platform_data *pdata = client->dev.platform_data;
+diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c
+index 76360c10246e..8cba75750e91 100644
+--- a/drivers/mfd/tps65217.c
++++ b/drivers/mfd/tps65217.c
+@@ -153,7 +153,7 @@ static const struct of_device_id tps65217_of_match[] = {
+ 	{ /* sentinel */ },
+ };
+ 
+-static int __devinit tps65217_probe(struct i2c_client *client,
++static int tps65217_probe(struct i2c_client *client,
+ 				const struct i2c_device_id *ids)
+ {
+ 	struct tps65217 *tps;
+diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c
+index a2e226f0f185..975fbb5f36aa 100644
+--- a/drivers/mfd/tps6586x.c
++++ b/drivers/mfd/tps6586x.c
+@@ -267,7 +267,7 @@ static irqreturn_t tps6586x_irq(int irq, void *data)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit tps6586x_irq_init(struct tps6586x *tps6586x, int irq,
++static int tps6586x_irq_init(struct tps6586x *tps6586x, int irq,
+ 				       int irq_base)
+ {
+ 	int i, ret;
+@@ -316,7 +316,7 @@ static int __devinit tps6586x_irq_init(struct tps6586x *tps6586x, int irq,
+ 	return ret;
+ }
+ 
+-static int __devinit tps6586x_add_subdevs(struct tps6586x *tps6586x,
++static int tps6586x_add_subdevs(struct tps6586x *tps6586x,
+ 					  struct tps6586x_platform_data *pdata)
+ {
+ 	struct tps6586x_subdev_info *subdev;
+@@ -468,7 +468,7 @@ static void tps6586x_power_off(void)
+ 	tps6586x_set_bits(tps6586x_dev, TPS6586X_SUPPLYENE, SLEEP_MODE_BIT);
+ }
+ 
+-static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
++static int tps6586x_i2c_probe(struct i2c_client *client,
+ 					const struct i2c_device_id *id)
+ {
+ 	struct tps6586x_platform_data *pdata = client->dev.platform_data;
+diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c
+index a3d732bcb519..3a3402290a74 100644
+--- a/drivers/mfd/tps65910.c
++++ b/drivers/mfd/tps65910.c
+@@ -78,7 +78,7 @@ static const struct regmap_config tps65910_regmap_config = {
+ 	.cache_type = REGCACHE_RBTREE,
+ };
+ 
+-static int __devinit tps65910_ck32k_init(struct tps65910 *tps65910,
++static int tps65910_ck32k_init(struct tps65910 *tps65910,
+ 					struct tps65910_board *pmic_pdata)
+ {
+ 	int ret;
+@@ -96,7 +96,7 @@ static int __devinit tps65910_ck32k_init(struct tps65910 *tps65910,
+ 	return 0;
+ }
+ 
+-static int __devinit tps65910_sleepinit(struct tps65910 *tps65910,
++static int tps65910_sleepinit(struct tps65910 *tps65910,
+ 		struct tps65910_board *pmic_pdata)
+ {
+ 	struct device *dev = NULL;
+@@ -237,7 +237,7 @@ static void tps65910_power_off(void)
+ 			DEVCTRL_DEV_ON_MASK);
+ }
+ 
+-static __devinit int tps65910_i2c_probe(struct i2c_client *i2c,
++static int tps65910_i2c_probe(struct i2c_client *i2c,
+ 					const struct i2c_device_id *id)
+ {
+ 	struct tps65910 *tps65910;
+diff --git a/drivers/mfd/tps65911-comparator.c b/drivers/mfd/tps65911-comparator.c
+index a0255874fb1d..b3d268f95a77 100644
+--- a/drivers/mfd/tps65911-comparator.c
++++ b/drivers/mfd/tps65911-comparator.c
+@@ -122,7 +122,7 @@ static ssize_t comp_threshold_show(struct device *dev,
+ static DEVICE_ATTR(comp1_threshold, S_IRUGO, comp_threshold_show, NULL);
+ static DEVICE_ATTR(comp2_threshold, S_IRUGO, comp_threshold_show, NULL);
+ 
+-static __devinit int tps65911_comparator_probe(struct platform_device *pdev)
++static int tps65911_comparator_probe(struct platform_device *pdev)
+ {
+ 	struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
+ 	struct tps65910_board *pdata = dev_get_platdata(tps65910->dev);
+diff --git a/drivers/mfd/tps65912-spi.c b/drivers/mfd/tps65912-spi.c
+index 054315da9d5f..6366576a3056 100644
+--- a/drivers/mfd/tps65912-spi.c
++++ b/drivers/mfd/tps65912-spi.c
+@@ -81,7 +81,7 @@ static int tps65912_spi_read(struct tps65912 *tps65912, u8 addr,
+ 	return ret;
+ }
+ 
+-static int __devinit tps65912_spi_probe(struct spi_device *spi)
++static int tps65912_spi_probe(struct spi_device *spi)
+ {
+ 	struct tps65912 *tps65912;
+ 
+diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
+index 4ae642320205..271d98a83caf 100644
+--- a/drivers/mfd/twl-core.c
++++ b/drivers/mfd/twl-core.c
+@@ -1170,7 +1170,7 @@ static int twl_remove(struct i2c_client *client)
+ }
+ 
+ /* NOTE: This driver only handles a single twl4030/tps659x0 chip */
+-static int __devinit
++static int
+ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
+ {
+ 	struct twl4030_platform_data	*pdata = client->dev.platform_data;
+diff --git a/drivers/mfd/twl4030-audio.c b/drivers/mfd/twl4030-audio.c
+index 08f99055b0fa..aacccdcf997c 100644
+--- a/drivers/mfd/twl4030-audio.c
++++ b/drivers/mfd/twl4030-audio.c
+@@ -184,7 +184,7 @@ static bool twl4030_audio_has_vibra(struct twl4030_audio_data *pdata,
+ 	return false;
+ }
+ 
+-static int __devinit twl4030_audio_probe(struct platform_device *pdev)
++static int twl4030_audio_probe(struct platform_device *pdev)
+ {
+ 	struct twl4030_audio *audio;
+ 	struct twl4030_audio_data *pdata = pdev->dev.platform_data;
+diff --git a/drivers/mfd/twl4030-madc.c b/drivers/mfd/twl4030-madc.c
+index 456ecb5ac4fe..228d5aacd332 100644
+--- a/drivers/mfd/twl4030-madc.c
++++ b/drivers/mfd/twl4030-madc.c
+@@ -692,7 +692,7 @@ static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on)
+ /*
+  * Initialize MADC and request for threaded irq
+  */
+-static int __devinit twl4030_madc_probe(struct platform_device *pdev)
++static int twl4030_madc_probe(struct platform_device *pdev)
+ {
+ 	struct twl4030_madc_data *madc;
+ 	struct twl4030_madc_platform_data *pdata = pdev->dev.platform_data;
+diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
+index 79ca33dfacca..a5332063183a 100644
+--- a/drivers/mfd/twl4030-power.c
++++ b/drivers/mfd/twl4030-power.c
+@@ -124,7 +124,7 @@ static u8 res_config_addrs[] = {
+ 	[RES_MAIN_REF]	= 0x94,
+ };
+ 
+-static int __devinit twl4030_write_script_byte(u8 address, u8 byte)
++static int twl4030_write_script_byte(u8 address, u8 byte)
+ {
+ 	int err;
+ 
+@@ -138,7 +138,7 @@ static int __devinit twl4030_write_script_byte(u8 address, u8 byte)
+ 	return err;
+ }
+ 
+-static int __devinit twl4030_write_script_ins(u8 address, u16 pmb_message,
++static int twl4030_write_script_ins(u8 address, u16 pmb_message,
+ 					   u8 delay, u8 next)
+ {
+ 	int err;
+@@ -158,7 +158,7 @@ static int __devinit twl4030_write_script_ins(u8 address, u16 pmb_message,
+ 	return err;
+ }
+ 
+-static int __devinit twl4030_write_script(u8 address, struct twl4030_ins *script,
++static int twl4030_write_script(u8 address, struct twl4030_ins *script,
+ 				       int len)
+ {
+ 	int err;
+@@ -183,7 +183,7 @@ static int __devinit twl4030_write_script(u8 address, struct twl4030_ins *script
+ 	return err;
+ }
+ 
+-static int __devinit twl4030_config_wakeup3_sequence(u8 address)
++static int twl4030_config_wakeup3_sequence(u8 address)
+ {
+ 	int err;
+ 	u8 data;
+@@ -208,7 +208,7 @@ static int __devinit twl4030_config_wakeup3_sequence(u8 address)
+ 	return err;
+ }
+ 
+-static int __devinit twl4030_config_wakeup12_sequence(u8 address)
++static int twl4030_config_wakeup12_sequence(u8 address)
+ {
+ 	int err = 0;
+ 	u8 data;
+@@ -262,7 +262,7 @@ static int __devinit twl4030_config_wakeup12_sequence(u8 address)
+ 	return err;
+ }
+ 
+-static int __devinit twl4030_config_sleep_sequence(u8 address)
++static int twl4030_config_sleep_sequence(u8 address)
+ {
+ 	int err;
+ 
+@@ -276,7 +276,7 @@ static int __devinit twl4030_config_sleep_sequence(u8 address)
+ 	return err;
+ }
+ 
+-static int __devinit twl4030_config_warmreset_sequence(u8 address)
++static int twl4030_config_warmreset_sequence(u8 address)
+ {
+ 	int err;
+ 	u8 rd_data;
+@@ -324,7 +324,7 @@ static int __devinit twl4030_config_warmreset_sequence(u8 address)
+ 	return err;
+ }
+ 
+-static int __devinit twl4030_configure_resource(struct twl4030_resconfig *rconfig)
++static int twl4030_configure_resource(struct twl4030_resconfig *rconfig)
+ {
+ 	int rconfig_addr;
+ 	int err;
+@@ -416,7 +416,7 @@ static int __devinit twl4030_configure_resource(struct twl4030_resconfig *rconfi
+ 	return 0;
+ }
+ 
+-static int __devinit load_twl4030_script(struct twl4030_script *tscript,
++static int load_twl4030_script(struct twl4030_script *tscript,
+ 	       u8 address)
+ {
+ 	int err;
+@@ -527,7 +527,7 @@ void twl4030_power_off(void)
+ 		pr_err("TWL4030 Unable to power off\n");
+ }
+ 
+-void __devinit twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
++void twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
+ {
+ 	int err = 0;
+ 	int i;
+diff --git a/drivers/mfd/vx855.c b/drivers/mfd/vx855.c
+index c5a7df84e6da..66ef03b02569 100644
+--- a/drivers/mfd/vx855.c
++++ b/drivers/mfd/vx855.c
+@@ -72,7 +72,7 @@ static struct mfd_cell vx855_cells[] = {
+ 	},
+ };
+ 
+-static __devinit int vx855_probe(struct pci_dev *pdev,
++static int vx855_probe(struct pci_dev *pdev,
+ 				 const struct pci_device_id *id)
+ {
+ 	int ret;
+diff --git a/drivers/mfd/wl1273-core.c b/drivers/mfd/wl1273-core.c
+index 7f3f3896662d..edbe6c1b755a 100644
+--- a/drivers/mfd/wl1273-core.c
++++ b/drivers/mfd/wl1273-core.c
+@@ -182,7 +182,7 @@ static int wl1273_core_remove(struct i2c_client *client)
+ 	return 0;
+ }
+ 
+-static int __devinit wl1273_core_probe(struct i2c_client *client,
++static int wl1273_core_probe(struct i2c_client *client,
+ 				       const struct i2c_device_id *id)
+ {
+ 	struct wl1273_fm_platform_data *pdata = client->dev.platform_data;
+diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c
+index 4329a3a9726f..4c7225a53ba2 100644
+--- a/drivers/mfd/wm831x-spi.c
++++ b/drivers/mfd/wm831x-spi.c
+@@ -21,7 +21,7 @@
+ 
+ #include 
+ 
+-static int __devinit wm831x_spi_probe(struct spi_device *spi)
++static int wm831x_spi_probe(struct spi_device *spi)
+ {
+ 	const struct spi_device_id *id = spi_get_device_id(spi);
+ 	struct wm831x *wm831x;
+diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
+index bb9cf5216115..46429495836d 100644
+--- a/drivers/mfd/wm8994-core.c
++++ b/drivers/mfd/wm8994-core.c
+@@ -399,7 +399,7 @@ static const __devinitconst struct reg_default wm1811_reva_patch[] = {
+ /*
+  * Instantiate the generic non-control parts of the device.
+  */
+-static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq)
++static int wm8994_device_init(struct wm8994 *wm8994, int irq)
+ {
+ 	struct wm8994_pdata *pdata = wm8994->dev->platform_data;
+ 	struct regmap_config *regmap_config;
+@@ -689,7 +689,7 @@ static const struct of_device_id wm8994_of_match[] = {
+ };
+ MODULE_DEVICE_TABLE(of, wm8994_of_match);
+ 
+-static __devinit int wm8994_i2c_probe(struct i2c_client *i2c,
++static int wm8994_i2c_probe(struct i2c_client *i2c,
+ 				      const struct i2c_device_id *id)
+ {
+ 	struct wm8994 *wm8994;
+diff --git a/include/linux/mfd/88pm80x.h b/include/linux/mfd/88pm80x.h
+index a0ca0dca1244..478672ed0c3d 100644
+--- a/include/linux/mfd/88pm80x.h
++++ b/include/linux/mfd/88pm80x.h
+@@ -364,6 +364,6 @@ static inline int pm80x_dev_resume(struct device *dev)
+ #endif
+ 
+ extern int pm80x_init(struct i2c_client *client,
+-			     const struct i2c_device_id *id) __devinit;
++		      const struct i2c_device_id *id);
+ extern int pm80x_deinit(struct i2c_client *client);
+ #endif /* __LINUX_MFD_88PM80X_H */
+diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h
+index 1491044efa10..83f0bdc530b7 100644
+--- a/include/linux/mfd/abx500/ab8500.h
++++ b/include/linux/mfd/abx500/ab8500.h
+@@ -291,7 +291,7 @@ struct ab8500_platform_data {
+ 	struct ab8500_codec_platform_data *codec;
+ };
+ 
+-extern int __devinit ab8500_init(struct ab8500 *ab8500,
++extern int ab8500_init(struct ab8500 *ab8500,
+ 				 enum ab8500_version version);
+ extern int __devexit ab8500_exit(struct ab8500 *ab8500);
+ 
+diff --git a/include/linux/mfd/pm8xxx/irq.h b/include/linux/mfd/pm8xxx/irq.h
+index 4b21769f4483..ddaa7f5e9ed9 100644
+--- a/include/linux/mfd/pm8xxx/irq.h
++++ b/include/linux/mfd/pm8xxx/irq.h
+@@ -37,7 +37,7 @@ struct pm_irq_chip;
+ 
+ #ifdef CONFIG_MFD_PM8XXX_IRQ
+ int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq);
+-struct pm_irq_chip * __devinit pm8xxx_irq_init(struct device *dev,
++struct pm_irq_chip *pm8xxx_irq_init(struct device *dev,
+ 				const struct pm8xxx_irq_platform_data *pdata);
+ int __devexit pm8xxx_irq_exit(struct pm_irq_chip *chip);
+ #else
+@@ -45,7 +45,7 @@ static inline int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq)
+ {
+ 	return -ENXIO;
+ }
+-static inline struct pm_irq_chip * __devinit pm8xxx_irq_init(
++static inline struct pm_irq_chip *pm8xxx_irq_init(
+ 				const struct device *dev,
+ 				const struct pm8xxx_irq_platform_data *pdata)
+ {

commit 84449216b01f9c2b4c9b1882f9d6abba07b7b7ca
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:20:24 2012 -0500
+
+    mfd: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Srinidhi Kasagar 
+    Cc: Peter Tyser 
+    Cc: Daniel Walker 
+    Cc: Bryan Huntsman 
+    Acked-by: David Brown 
+    Acked-by: Linus Walleij 
+    Acked-by: Mark Brown 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c
+index ce229ea933d1..321a50cdebf9 100644
+--- a/drivers/mfd/88pm800.c
++++ b/drivers/mfd/88pm800.c
+@@ -576,7 +576,7 @@ static struct i2c_driver pm800_driver = {
+ 		.pm = &pm80x_pm_ops,
+ 		},
+ 	.probe = pm800_probe,
+-	.remove = __devexit_p(pm800_remove),
++	.remove = pm800_remove,
+ 	.id_table = pm80x_id_table,
+ };
+ 
+diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c
+index c20a31136f04..41e0488b4e3b 100644
+--- a/drivers/mfd/88pm805.c
++++ b/drivers/mfd/88pm805.c
+@@ -281,7 +281,7 @@ static struct i2c_driver pm805_driver = {
+ 		.pm = &pm80x_pm_ops,
+ 		},
+ 	.probe = pm805_probe,
+-	.remove = __devexit_p(pm805_remove),
++	.remove = pm805_remove,
+ 	.id_table = pm80x_id_table,
+ };
+ 
+diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
+index 8fa86edf70d4..c2d5595e49d0 100644
+--- a/drivers/mfd/88pm860x-core.c
++++ b/drivers/mfd/88pm860x-core.c
+@@ -1258,7 +1258,7 @@ static struct i2c_driver pm860x_driver = {
+ 		.of_match_table	= of_match_ptr(pm860x_dt_ids),
+ 	},
+ 	.probe		= pm860x_probe,
+-	.remove		= __devexit_p(pm860x_remove),
++	.remove		= pm860x_remove,
+ 	.id_table	= pm860x_id_table,
+ };
+ 
+diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
+index 2b3dde571a50..8355d4ee6edd 100644
+--- a/drivers/mfd/ab3100-core.c
++++ b/drivers/mfd/ab3100-core.c
+@@ -986,7 +986,7 @@ static struct i2c_driver ab3100_driver = {
+ 	},
+ 	.id_table	= ab3100_id,
+ 	.probe		= ab3100_probe,
+-	.remove		= __devexit_p(ab3100_remove),
++	.remove		= ab3100_remove,
+ };
+ 
+ static int __init ab3100_i2c_init(void)
+diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
+index 1667c77b5cde..01a0e01f6a6c 100644
+--- a/drivers/mfd/ab8500-core.c
++++ b/drivers/mfd/ab8500-core.c
+@@ -1506,7 +1506,7 @@ static struct platform_driver ab8500_core_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe	= ab8500_probe,
+-	.remove	= __devexit_p(ab8500_remove),
++	.remove	= ab8500_remove,
+ 	.id_table = ab8500_id,
+ };
+ 
+diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c
+index c4cb806978ac..efdbc7bebd01 100644
+--- a/drivers/mfd/ab8500-debugfs.c
++++ b/drivers/mfd/ab8500-debugfs.c
+@@ -614,7 +614,7 @@ static struct platform_driver ab8500_debug_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe  = ab8500_debug_probe,
+-	.remove = __devexit_p(ab8500_debug_remove)
++	.remove = ab8500_debug_remove
+ };
+ 
+ static int __init ab8500_debug_init(void)
+diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c
+index 29d72a259c85..97daf61f068c 100644
+--- a/drivers/mfd/ab8500-gpadc.c
++++ b/drivers/mfd/ab8500-gpadc.c
+@@ -651,7 +651,7 @@ static int __devexit ab8500_gpadc_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver ab8500_gpadc_driver = {
+ 	.probe = ab8500_gpadc_probe,
+-	.remove = __devexit_p(ab8500_gpadc_remove),
++	.remove = ab8500_gpadc_remove,
+ 	.driver = {
+ 		.name = "ab8500-gpadc",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c
+index c28d4eb1eff0..d8cc157af3e8 100644
+--- a/drivers/mfd/ab8500-sysctrl.c
++++ b/drivers/mfd/ab8500-sysctrl.c
+@@ -67,7 +67,7 @@ static struct platform_driver ab8500_sysctrl_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = ab8500_sysctrl_probe,
+-	.remove = __devexit_p(ab8500_sysctrl_remove),
++	.remove = ab8500_sysctrl_remove,
+ };
+ 
+ static int __init ab8500_sysctrl_init(void)
+diff --git a/drivers/mfd/adp5520.c b/drivers/mfd/adp5520.c
+index ea8b9475731d..f664a52687d5 100644
+--- a/drivers/mfd/adp5520.c
++++ b/drivers/mfd/adp5520.c
+@@ -356,7 +356,7 @@ static struct i2c_driver adp5520_driver = {
+ 		.pm	= &adp5520_pm,
+ 	},
+ 	.probe		= adp5520_probe,
+-	.remove		= __devexit_p(adp5520_remove),
++	.remove		= adp5520_remove,
+ 	.id_table 	= adp5520_id,
+ };
+ 
+diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c
+index 570c4b438086..43d164736fcb 100644
+--- a/drivers/mfd/arizona-i2c.c
++++ b/drivers/mfd/arizona-i2c.c
+@@ -86,7 +86,7 @@ static struct i2c_driver arizona_i2c_driver = {
+ 		.pm	= &arizona_pm_ops,
+ 	},
+ 	.probe		= arizona_i2c_probe,
+-	.remove		= __devexit_p(arizona_i2c_remove),
++	.remove		= arizona_i2c_remove,
+ 	.id_table	= arizona_i2c_id,
+ };
+ 
+diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c
+index df2e5a8bee28..cc79b824f706 100644
+--- a/drivers/mfd/arizona-spi.c
++++ b/drivers/mfd/arizona-spi.c
+@@ -86,7 +86,7 @@ static struct spi_driver arizona_spi_driver = {
+ 		.pm	= &arizona_pm_ops,
+ 	},
+ 	.probe		= arizona_spi_probe,
+-	.remove		= __devexit_p(arizona_spi_remove),
++	.remove		= arizona_spi_remove,
+ 	.id_table	= arizona_spi_ids,
+ };
+ 
+diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c
+index 62f0883a7630..b0720d7c1b71 100644
+--- a/drivers/mfd/asic3.c
++++ b/drivers/mfd/asic3.c
+@@ -1071,7 +1071,7 @@ static struct platform_driver asic3_device_driver = {
+ 	.driver		= {
+ 		.name	= "asic3",
+ 	},
+-	.remove		= __devexit_p(asic3_remove),
++	.remove		= asic3_remove,
+ 	.shutdown	= asic3_shutdown,
+ };
+ 
+diff --git a/drivers/mfd/cs5535-mfd.c b/drivers/mfd/cs5535-mfd.c
+index 2b282133c725..5d3878ad39a6 100644
+--- a/drivers/mfd/cs5535-mfd.c
++++ b/drivers/mfd/cs5535-mfd.c
+@@ -183,7 +183,7 @@ static struct pci_driver cs5535_mfd_driver = {
+ 	.name = DRV_NAME,
+ 	.id_table = cs5535_mfd_pci_tbl,
+ 	.probe = cs5535_mfd_probe,
+-	.remove = __devexit_p(cs5535_mfd_remove),
++	.remove = cs5535_mfd_remove,
+ };
+ 
+ module_pci_driver(cs5535_mfd_driver);
+diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c
+index 1924b857a0fb..c715475df377 100644
+--- a/drivers/mfd/da903x.c
++++ b/drivers/mfd/da903x.c
+@@ -560,7 +560,7 @@ static struct i2c_driver da903x_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= da903x_probe,
+-	.remove		= __devexit_p(da903x_remove),
++	.remove		= da903x_remove,
+ 	.id_table	= da903x_id_table,
+ };
+ 
+diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c
+index 352c58b5a90d..8af0f0c5cefe 100644
+--- a/drivers/mfd/da9052-i2c.c
++++ b/drivers/mfd/da9052-i2c.c
+@@ -131,7 +131,7 @@ static int __devexit da9052_i2c_remove(struct i2c_client *client)
+ 
+ static struct i2c_driver da9052_i2c_driver = {
+ 	.probe = da9052_i2c_probe,
+-	.remove = __devexit_p(da9052_i2c_remove),
++	.remove = da9052_i2c_remove,
+ 	.id_table = da9052_i2c_id,
+ 	.driver = {
+ 		.name = "da9052",
+diff --git a/drivers/mfd/da9052-spi.c b/drivers/mfd/da9052-spi.c
+index dbeadc5a6436..cbcc9bebbbe1 100644
+--- a/drivers/mfd/da9052-spi.c
++++ b/drivers/mfd/da9052-spi.c
+@@ -76,7 +76,7 @@ static struct spi_device_id da9052_spi_id[] = {
+ 
+ static struct spi_driver da9052_spi_driver = {
+ 	.probe = da9052_spi_probe,
+-	.remove = __devexit_p(da9052_spi_remove),
++	.remove = da9052_spi_remove,
+ 	.id_table = da9052_spi_id,
+ 	.driver = {
+ 		.name = "da9052",
+diff --git a/drivers/mfd/da9055-i2c.c b/drivers/mfd/da9055-i2c.c
+index 88f6dca53bac..dbaca7bc36da 100644
+--- a/drivers/mfd/da9055-i2c.c
++++ b/drivers/mfd/da9055-i2c.c
+@@ -60,7 +60,7 @@ static struct i2c_device_id da9055_i2c_id[] = {
+ 
+ static struct i2c_driver da9055_i2c_driver = {
+ 	.probe = da9055_i2c_probe,
+-	.remove = __devexit_p(da9055_i2c_remove),
++	.remove = da9055_i2c_remove,
+ 	.id_table = da9055_i2c_id,
+ 	.driver = {
+ 		.name = "da9055",
+diff --git a/drivers/mfd/davinci_voicecodec.c b/drivers/mfd/davinci_voicecodec.c
+index 45e83a68641b..b2b0397059d8 100644
+--- a/drivers/mfd/davinci_voicecodec.c
++++ b/drivers/mfd/davinci_voicecodec.c
+@@ -174,7 +174,7 @@ static struct platform_driver davinci_vc_driver = {
+ 		.name = "davinci_voicecodec",
+ 		.owner = THIS_MODULE,
+ 	},
+-	.remove	= __devexit_p(davinci_vc_remove),
++	.remove	= davinci_vc_remove,
+ };
+ 
+ static int __init davinci_vc_init(void)
+diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c
+index db662e2dcfa5..d7e4de041526 100644
+--- a/drivers/mfd/ezx-pcap.c
++++ b/drivers/mfd/ezx-pcap.c
+@@ -525,7 +525,7 @@ static int __devinit ezx_pcap_probe(struct spi_device *spi)
+ 
+ static struct spi_driver ezxpcap_driver = {
+ 	.probe	= ezx_pcap_probe,
+-	.remove = __devexit_p(ezx_pcap_remove),
++	.remove = ezx_pcap_remove,
+ 	.driver = {
+ 		.name	= "ezx-pcap",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/mfd/intel_msic.c b/drivers/mfd/intel_msic.c
+index 266bdc5bd96d..c5f478eb4e18 100644
+--- a/drivers/mfd/intel_msic.c
++++ b/drivers/mfd/intel_msic.c
+@@ -457,7 +457,7 @@ static int __devexit intel_msic_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver intel_msic_driver = {
+ 	.probe		= intel_msic_probe,
+-	.remove		= __devexit_p(intel_msic_remove),
++	.remove		= intel_msic_remove,
+ 	.driver		= {
+ 		.name	= "intel_msic",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c
+index 965c4801df8a..1a3627784246 100644
+--- a/drivers/mfd/janz-cmodio.c
++++ b/drivers/mfd/janz-cmodio.c
+@@ -280,7 +280,7 @@ static struct pci_driver cmodio_pci_driver = {
+ 	.name     = DRV_NAME,
+ 	.id_table = cmodio_pci_ids,
+ 	.probe    = cmodio_pci_probe,
+-	.remove   = __devexit_p(cmodio_pci_remove),
++	.remove   = cmodio_pci_remove,
+ };
+ 
+ module_pci_driver(cmodio_pci_driver);
+diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c
+index c6b6d7dda517..9aed2a66180e 100644
+--- a/drivers/mfd/jz4740-adc.c
++++ b/drivers/mfd/jz4740-adc.c
+@@ -332,7 +332,7 @@ static int __devexit jz4740_adc_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver jz4740_adc_driver = {
+ 	.probe	= jz4740_adc_probe,
+-	.remove = __devexit_p(jz4740_adc_remove),
++	.remove = jz4740_adc_remove,
+ 	.driver = {
+ 		.name = "jz4740-adc",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/mfd/lm3533-core.c b/drivers/mfd/lm3533-core.c
+index 24212f45b201..e7aa2a5a826b 100644
+--- a/drivers/mfd/lm3533-core.c
++++ b/drivers/mfd/lm3533-core.c
+@@ -648,7 +648,7 @@ static struct i2c_driver lm3533_i2c_driver = {
+ 	},
+ 	.id_table	= lm3533_i2c_ids,
+ 	.probe		= lm3533_i2c_probe,
+-	.remove		= __devexit_p(lm3533_i2c_remove),
++	.remove		= lm3533_i2c_remove,
+ };
+ 
+ static int __init lm3533_i2c_init(void)
+diff --git a/drivers/mfd/lp8788.c b/drivers/mfd/lp8788.c
+index 3e94a699833c..e1d7c9f18cc5 100644
+--- a/drivers/mfd/lp8788.c
++++ b/drivers/mfd/lp8788.c
+@@ -224,7 +224,7 @@ static struct i2c_driver lp8788_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = lp8788_probe,
+-	.remove = __devexit_p(lp8788_remove),
++	.remove = lp8788_remove,
+ 	.id_table = lp8788_ids,
+ };
+ 
+diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
+index a22544fe5319..a43c73ac25b0 100644
+--- a/drivers/mfd/lpc_ich.c
++++ b/drivers/mfd/lpc_ich.c
+@@ -888,7 +888,7 @@ static struct pci_driver lpc_ich_driver = {
+ 	.name		= "lpc_ich",
+ 	.id_table	= lpc_ich_ids,
+ 	.probe		= lpc_ich_probe,
+-	.remove		= __devexit_p(lpc_ich_remove),
++	.remove		= lpc_ich_remove,
+ };
+ 
+ static int __init lpc_ich_init(void)
+diff --git a/drivers/mfd/lpc_sch.c b/drivers/mfd/lpc_sch.c
+index f6b9c5c96b24..27477f4533ea 100644
+--- a/drivers/mfd/lpc_sch.c
++++ b/drivers/mfd/lpc_sch.c
+@@ -173,7 +173,7 @@ static struct pci_driver lpc_sch_driver = {
+ 	.name		= "lpc_sch",
+ 	.id_table	= lpc_sch_ids,
+ 	.probe		= lpc_sch_probe,
+-	.remove		= __devexit_p(lpc_sch_remove),
++	.remove		= lpc_sch_remove,
+ };
+ 
+ module_pci_driver(lpc_sch_driver);
+diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c
+index d9e4b36edee9..375e0475f6d2 100644
+--- a/drivers/mfd/max8925-i2c.c
++++ b/drivers/mfd/max8925-i2c.c
+@@ -210,7 +210,7 @@ static struct i2c_driver max8925_driver = {
+ 		.pm     = &max8925_pm_ops,
+ 	},
+ 	.probe		= max8925_probe,
+-	.remove		= __devexit_p(max8925_remove),
++	.remove		= max8925_remove,
+ 	.id_table	= max8925_id_table,
+ };
+ 
+diff --git a/drivers/mfd/mc13xxx-i2c.c b/drivers/mfd/mc13xxx-i2c.c
+index 9d18dde3cd2a..4a605fb63cbc 100644
+--- a/drivers/mfd/mc13xxx-i2c.c
++++ b/drivers/mfd/mc13xxx-i2c.c
+@@ -102,7 +102,7 @@ static struct i2c_driver mc13xxx_i2c_driver = {
+ 		.of_match_table = mc13xxx_dt_ids,
+ 	},
+ 	.probe = mc13xxx_i2c_probe,
+-	.remove = __devexit_p(mc13xxx_i2c_remove),
++	.remove = mc13xxx_i2c_remove,
+ };
+ 
+ static int __init mc13xxx_i2c_init(void)
+diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c
+index 0bdb43a0aff0..e7acd0511156 100644
+--- a/drivers/mfd/mc13xxx-spi.c
++++ b/drivers/mfd/mc13xxx-spi.c
+@@ -176,7 +176,7 @@ static struct spi_driver mc13xxx_spi_driver = {
+ 		.of_match_table = mc13xxx_dt_ids,
+ 	},
+ 	.probe = mc13xxx_spi_probe,
+-	.remove = __devexit_p(mc13xxx_spi_remove),
++	.remove = mc13xxx_spi_remove,
+ };
+ 
+ static int __init mc13xxx_init(void)
+diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
+index 4b7757b84301..2d8edfd85e1c 100644
+--- a/drivers/mfd/omap-usb-tll.c
++++ b/drivers/mfd/omap-usb-tll.c
+@@ -424,7 +424,7 @@ static struct platform_driver usbtll_omap_driver = {
+ 		.pm		= &usbtllomap_dev_pm_ops,
+ 	},
+ 	.probe		= usbtll_omap_probe,
+-	.remove		= __devexit_p(usbtll_omap_remove),
++	.remove		= usbtll_omap_remove,
+ };
+ 
+ int omap_tll_enable(void)
+diff --git a/drivers/mfd/pcf50633-adc.c b/drivers/mfd/pcf50633-adc.c
+index 3927c17e4175..a285b5111edb 100644
+--- a/drivers/mfd/pcf50633-adc.c
++++ b/drivers/mfd/pcf50633-adc.c
+@@ -246,7 +246,7 @@ static struct platform_driver pcf50633_adc_driver = {
+ 		.name = "pcf50633-adc",
+ 	},
+ 	.probe = pcf50633_adc_probe,
+-	.remove = __devexit_p(pcf50633_adc_remove),
++	.remove = pcf50633_adc_remove,
+ };
+ 
+ module_platform_driver(pcf50633_adc_driver);
+diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c
+index 45ce1fb5a549..ad438e85cbf7 100644
+--- a/drivers/mfd/pcf50633-core.c
++++ b/drivers/mfd/pcf50633-core.c
+@@ -308,7 +308,7 @@ static struct i2c_driver pcf50633_driver = {
+ 	},
+ 	.id_table = pcf50633_id_table,
+ 	.probe = pcf50633_probe,
+-	.remove = __devexit_p(pcf50633_remove),
++	.remove = pcf50633_remove,
+ };
+ 
+ static int __init pcf50633_init(void)
+diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
+index e873b15753d8..24d57bcc98b6 100644
+--- a/drivers/mfd/pm8921-core.c
++++ b/drivers/mfd/pm8921-core.c
+@@ -187,7 +187,7 @@ static int __devexit pm8921_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver pm8921_driver = {
+ 	.probe		= pm8921_probe,
+-	.remove		= __devexit_p(pm8921_remove),
++	.remove		= pm8921_remove,
+ 	.driver		= {
+ 		.name	= "pm8921-core",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/mfd/rc5t583.c b/drivers/mfd/rc5t583.c
+index f1a024ecdb1e..d38ee24302ca 100644
+--- a/drivers/mfd/rc5t583.c
++++ b/drivers/mfd/rc5t583.c
+@@ -325,7 +325,7 @@ static struct i2c_driver rc5t583_i2c_driver = {
+ 		   .owner = THIS_MODULE,
+ 		   },
+ 	.probe = rc5t583_i2c_probe,
+-	.remove = __devexit_p(rc5t583_i2c_remove),
++	.remove = rc5t583_i2c_remove,
+ 	.id_table = rc5t583_i2c_id,
+ };
+ 
+diff --git a/drivers/mfd/rdc321x-southbridge.c b/drivers/mfd/rdc321x-southbridge.c
+index fbabc3cbe350..330396306d62 100644
+--- a/drivers/mfd/rdc321x-southbridge.c
++++ b/drivers/mfd/rdc321x-southbridge.c
+@@ -106,7 +106,7 @@ static struct pci_driver rdc321x_sb_driver = {
+ 	.name		= "RDC321x Southbridge",
+ 	.id_table	= rdc321x_sb_table,
+ 	.probe		= rdc321x_sb_probe,
+-	.remove		= __devexit_p(rdc321x_sb_remove),
++	.remove		= rdc321x_sb_remove,
+ };
+ 
+ module_pci_driver(rdc321x_sb_driver);
+diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
+index d927dd49acb3..777af5ec25d4 100644
+--- a/drivers/mfd/sm501.c
++++ b/drivers/mfd/sm501.c
+@@ -1723,7 +1723,7 @@ static struct pci_driver sm501_pci_driver = {
+ 	.name		= "sm501",
+ 	.id_table	= sm501_pci_tbl,
+ 	.probe		= sm501_pci_probe,
+-	.remove		= __devexit_p(sm501_pci_remove),
++	.remove		= sm501_pci_remove,
+ };
+ 
+ MODULE_ALIAS("platform:sm501");
+diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c
+index 947a06a1845f..6a6aed74b946 100644
+--- a/drivers/mfd/stmpe-i2c.c
++++ b/drivers/mfd/stmpe-i2c.c
+@@ -88,7 +88,7 @@ static struct i2c_driver stmpe_i2c_driver = {
+ 	.driver.pm	= &stmpe_dev_pm_ops,
+ #endif
+ 	.probe		= stmpe_i2c_probe,
+-	.remove		= __devexit_p(stmpe_i2c_remove),
++	.remove		= stmpe_i2c_remove,
+ 	.id_table	= stmpe_i2c_id,
+ };
+ 
+diff --git a/drivers/mfd/stmpe-spi.c b/drivers/mfd/stmpe-spi.c
+index 9edfe864cc05..29590ad6a6e4 100644
+--- a/drivers/mfd/stmpe-spi.c
++++ b/drivers/mfd/stmpe-spi.c
+@@ -128,7 +128,7 @@ static struct spi_driver stmpe_spi_driver = {
+ #endif
+ 	},
+ 	.probe		= stmpe_spi_probe,
+-	.remove		= __devexit_p(stmpe_spi_remove),
++	.remove		= stmpe_spi_remove,
+ 	.id_table	= stmpe_spi_id,
+ };
+ 
+diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
+index 65fe609026cc..d258b595d0b7 100644
+--- a/drivers/mfd/syscon.c
++++ b/drivers/mfd/syscon.c
+@@ -156,7 +156,7 @@ static struct platform_driver syscon_driver = {
+ 		.of_match_table = of_syscon_match,
+ 	},
+ 	.probe		= syscon_probe,
+-	.remove		= __devexit_p(syscon_remove),
++	.remove		= syscon_remove,
+ };
+ 
+ static int __init syscon_init(void)
+diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c
+index 8f4c853ca116..553ce956da6d 100644
+--- a/drivers/mfd/tc3589x.c
++++ b/drivers/mfd/tc3589x.c
+@@ -458,7 +458,7 @@ static struct i2c_driver tc3589x_driver = {
+ 	.driver.owner	= THIS_MODULE,
+ 	.driver.pm	= &tc3589x_dev_pm_ops,
+ 	.probe		= tc3589x_probe,
+-	.remove		= __devexit_p(tc3589x_remove),
++	.remove		= tc3589x_remove,
+ 	.id_table	= tc3589x_id,
+ };
+ 
+diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c
+index 413c891102f8..186f053e36ef 100644
+--- a/drivers/mfd/tc6387xb.c
++++ b/drivers/mfd/tc6387xb.c
+@@ -229,7 +229,7 @@ static struct platform_driver tc6387xb_platform_driver = {
+ 		.name		= "tc6387xb",
+ 	},
+ 	.probe		= tc6387xb_probe,
+-	.remove		= __devexit_p(tc6387xb_remove),
++	.remove		= tc6387xb_remove,
+ 	.suspend        = tc6387xb_suspend,
+ 	.resume         = tc6387xb_resume,
+ };
+diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
+index dcab026fcbb2..9411a88770b8 100644
+--- a/drivers/mfd/tc6393xb.c
++++ b/drivers/mfd/tc6393xb.c
+@@ -831,7 +831,7 @@ static int tc6393xb_resume(struct platform_device *dev)
+ 
+ static struct platform_driver tc6393xb_driver = {
+ 	.probe = tc6393xb_probe,
+-	.remove = __devexit_p(tc6393xb_remove),
++	.remove = tc6393xb_remove,
+ 	.suspend = tc6393xb_suspend,
+ 	.resume = tc6393xb_resume,
+ 
+diff --git a/drivers/mfd/ti-ssp.c b/drivers/mfd/ti-ssp.c
+index 7c3675a74f93..1c31f877c6bb 100644
+--- a/drivers/mfd/ti-ssp.c
++++ b/drivers/mfd/ti-ssp.c
+@@ -451,7 +451,7 @@ static int __devexit ti_ssp_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver ti_ssp_driver = {
+ 	.probe		= ti_ssp_probe,
+-	.remove		= __devexit_p(ti_ssp_remove),
++	.remove		= ti_ssp_remove,
+ 	.driver		= {
+ 		.name	= "ti-ssp",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c
+index cccc626c83c8..61badece0b9a 100644
+--- a/drivers/mfd/timberdale.c
++++ b/drivers/mfd/timberdale.c
+@@ -867,7 +867,7 @@ static struct pci_driver timberdale_pci_driver = {
+ 	.name = DRIVER_NAME,
+ 	.id_table = timberdale_pci_tbl,
+ 	.probe = timb_probe,
+-	.remove = __devexit_p(timb_remove),
++	.remove = timb_remove,
+ };
+ 
+ static int __init timberdale_init(void)
+diff --git a/drivers/mfd/tps6105x.c b/drivers/mfd/tps6105x.c
+index 14051bdc714b..45389600f86e 100644
+--- a/drivers/mfd/tps6105x.c
++++ b/drivers/mfd/tps6105x.c
+@@ -226,7 +226,7 @@ static struct i2c_driver tps6105x_driver = {
+ 		.name	= "tps6105x",
+ 	},
+ 	.probe		= tps6105x_probe,
+-	.remove		= __devexit_p(tps6105x_remove),
++	.remove		= tps6105x_remove,
+ 	.id_table	= tps6105x_id,
+ };
+ 
+diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c
+index 074ae32b0d2a..d43ff16d8c4c 100644
+--- a/drivers/mfd/tps65090.c
++++ b/drivers/mfd/tps65090.c
+@@ -354,7 +354,7 @@ static struct i2c_driver tps65090_driver = {
+ 		.pm	= &tps65090_pm_ops,
+ 	},
+ 	.probe		= tps65090_i2c_probe,
+-	.remove		= __devexit_p(tps65090_i2c_remove),
++	.remove		= tps65090_i2c_remove,
+ 	.id_table	= tps65090_id_table,
+ };
+ 
+diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c
+index 3fb32e655254..76360c10246e 100644
+--- a/drivers/mfd/tps65217.c
++++ b/drivers/mfd/tps65217.c
+@@ -237,7 +237,7 @@ static struct i2c_driver tps65217_driver = {
+ 	},
+ 	.id_table	= tps65217_id_table,
+ 	.probe		= tps65217_probe,
+-	.remove		= __devexit_p(tps65217_remove),
++	.remove		= tps65217_remove,
+ };
+ 
+ static int __init tps65217_init(void)
+diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c
+index 467464368773..a2e226f0f185 100644
+--- a/drivers/mfd/tps6586x.c
++++ b/drivers/mfd/tps6586x.c
+@@ -572,7 +572,7 @@ static struct i2c_driver tps6586x_driver = {
+ 		.of_match_table = of_match_ptr(tps6586x_of_match),
+ 	},
+ 	.probe		= tps6586x_i2c_probe,
+-	.remove		= __devexit_p(tps6586x_i2c_remove),
++	.remove		= tps6586x_i2c_remove,
+ 	.id_table	= tps6586x_id_table,
+ };
+ 
+diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c
+index 0d79ce2b5014..a3d732bcb519 100644
+--- a/drivers/mfd/tps65910.c
++++ b/drivers/mfd/tps65910.c
+@@ -327,7 +327,7 @@ static struct i2c_driver tps65910_i2c_driver = {
+ 		   .of_match_table = of_match_ptr(tps65910_of_match),
+ 	},
+ 	.probe = tps65910_i2c_probe,
+-	.remove = __devexit_p(tps65910_i2c_remove),
++	.remove = tps65910_i2c_remove,
+ 	.id_table = tps65910_i2c_id,
+ };
+ 
+diff --git a/drivers/mfd/tps65911-comparator.c b/drivers/mfd/tps65911-comparator.c
+index 0b6e361432c4..a0255874fb1d 100644
+--- a/drivers/mfd/tps65911-comparator.c
++++ b/drivers/mfd/tps65911-comparator.c
+@@ -169,7 +169,7 @@ static struct platform_driver tps65911_comparator_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = tps65911_comparator_probe,
+-	.remove = __devexit_p(tps65911_comparator_remove),
++	.remove = tps65911_comparator_remove,
+ };
+ 
+ static int __init tps65911_comparator_init(void)
+diff --git a/drivers/mfd/tps65912-spi.c b/drivers/mfd/tps65912-spi.c
+index 27d3302d56b8..054315da9d5f 100644
+--- a/drivers/mfd/tps65912-spi.c
++++ b/drivers/mfd/tps65912-spi.c
+@@ -114,7 +114,7 @@ static struct spi_driver tps65912_spi_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe	= tps65912_spi_probe,
+-	.remove = __devexit_p(tps65912_spi_remove),
++	.remove = tps65912_spi_remove,
+ };
+ 
+ static int __init tps65912_spi_init(void)
+diff --git a/drivers/mfd/twl4030-audio.c b/drivers/mfd/twl4030-audio.c
+index 5c11acf9e0fd..08f99055b0fa 100644
+--- a/drivers/mfd/twl4030-audio.c
++++ b/drivers/mfd/twl4030-audio.c
+@@ -291,7 +291,7 @@ static struct platform_driver twl4030_audio_driver = {
+ 		.of_match_table = twl4030_audio_of_match,
+ 	},
+ 	.probe		= twl4030_audio_probe,
+-	.remove		= __devexit_p(twl4030_audio_remove),
++	.remove		= twl4030_audio_remove,
+ };
+ 
+ module_platform_driver(twl4030_audio_driver);
+diff --git a/drivers/mfd/vx855.c b/drivers/mfd/vx855.c
+index b9a636d44c7f..c5a7df84e6da 100644
+--- a/drivers/mfd/vx855.c
++++ b/drivers/mfd/vx855.c
+@@ -128,7 +128,7 @@ static struct pci_driver vx855_pci_driver = {
+ 	.name		= "vx855",
+ 	.id_table	= vx855_pci_tbl,
+ 	.probe		= vx855_probe,
+-	.remove		= __devexit_p(vx855_remove),
++	.remove		= vx855_remove,
+ };
+ 
+ module_pci_driver(vx855_pci_driver);
+diff --git a/drivers/mfd/wl1273-core.c b/drivers/mfd/wl1273-core.c
+index 86e0e4309fc2..7f3f3896662d 100644
+--- a/drivers/mfd/wl1273-core.c
++++ b/drivers/mfd/wl1273-core.c
+@@ -262,7 +262,7 @@ static struct i2c_driver wl1273_core_driver = {
+ 	},
+ 	.probe = wl1273_core_probe,
+ 	.id_table = wl1273_driver_id_table,
+-	.remove = __devexit_p(wl1273_core_remove),
++	.remove = wl1273_core_remove,
+ };
+ 
+ static int __init wl1273_core_init(void)
+diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c
+index 4bceee98f0a4..4329a3a9726f 100644
+--- a/drivers/mfd/wm831x-spi.c
++++ b/drivers/mfd/wm831x-spi.c
+@@ -99,7 +99,7 @@ static struct spi_driver wm831x_spi_driver = {
+ 	},
+ 	.id_table	= wm831x_spi_ids,
+ 	.probe		= wm831x_spi_probe,
+-	.remove		= __devexit_p(wm831x_spi_remove),
++	.remove		= wm831x_spi_remove,
+ 	.shutdown	= wm831x_spi_shutdown,
+ };
+ 
+diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
+index 8fefc961ec06..bb9cf5216115 100644
+--- a/drivers/mfd/wm8994-core.c
++++ b/drivers/mfd/wm8994-core.c
+@@ -744,7 +744,7 @@ static struct i2c_driver wm8994_i2c_driver = {
+ 		.of_match_table = wm8994_of_match,
+ 	},
+ 	.probe = wm8994_i2c_probe,
+-	.remove = __devexit_p(wm8994_i2c_remove),
++	.remove = wm8994_i2c_remove,
+ 	.id_table = wm8994_i2c_id,
+ };
+ 

commit b1f7c8cc1b4619f3dfd9f36bcfd35a0f4ce0cd13
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:08 2012 -0500
+
+    ptp: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Richard Cochran 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/ptp/ptp_pch.c b/drivers/ptp/ptp_pch.c
+index 304cec21bc42..1367655eee39 100644
+--- a/drivers/ptp/ptp_pch.c
++++ b/drivers/ptp/ptp_pch.c
+@@ -557,7 +557,7 @@ static s32 pch_resume(struct pci_dev *pdev)
+ #define pch_resume NULL
+ #endif
+ 
+-static void __devexit pch_remove(struct pci_dev *pdev)
++static void pch_remove(struct pci_dev *pdev)
+ {
+ 	struct pch_dev *chip = pci_get_drvdata(pdev);
+ 

commit 5c0a42566c153349521ac5ff68561c29d2d261bf
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:23:28 2012 -0500
+
+    ptp: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Richard Cochran 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/ptp/ptp_pch.c b/drivers/ptp/ptp_pch.c
+index e624e4dd2abb..304cec21bc42 100644
+--- a/drivers/ptp/ptp_pch.c
++++ b/drivers/ptp/ptp_pch.c
+@@ -581,7 +581,7 @@ static void __devexit pch_remove(struct pci_dev *pdev)
+ 	dev_info(&pdev->dev, "complete\n");
+ }
+ 
+-static s32 __devinit
++static s32
+ pch_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ 	s32 ret;

commit 305c891e2a5ef6bc8d6399cd7178771224feac25
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:23:25 2012 -0500
+
+    rapidio: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Matt Porter 
+    Acked-by: Alexandre Bounine 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c
+index 38ecd8f4d60e..6faba406b6e9 100644
+--- a/drivers/rapidio/devices/tsi721.c
++++ b/drivers/rapidio/devices/tsi721.c
+@@ -2202,7 +2202,7 @@ static void tsi721_disable_ints(struct tsi721_device *priv)
+  *
+  * Configures Tsi721 as RapidIO master port.
+  */
+-static int __devinit tsi721_setup_mport(struct tsi721_device *priv)
++static int tsi721_setup_mport(struct tsi721_device *priv)
+ {
+ 	struct pci_dev *pdev = priv->pdev;
+ 	int err = 0;
+@@ -2302,7 +2302,7 @@ static int __devinit tsi721_setup_mport(struct tsi721_device *priv)
+ 	return err;
+ }
+ 
+-static int __devinit tsi721_probe(struct pci_dev *pdev,
++static int tsi721_probe(struct pci_dev *pdev,
+ 				  const struct pci_device_id *id)
+ {
+ 	struct tsi721_device *priv;
+diff --git a/drivers/rapidio/devices/tsi721.h b/drivers/rapidio/devices/tsi721.h
+index 7d5b13ba8d4f..b4b0d83f9ef6 100644
+--- a/drivers/rapidio/devices/tsi721.h
++++ b/drivers/rapidio/devices/tsi721.h
+@@ -846,7 +846,7 @@ struct tsi721_device {
+ 
+ #ifdef CONFIG_RAPIDIO_DMA_ENGINE
+ extern void tsi721_bdma_handler(struct tsi721_bdma_chan *bdma_chan);
+-extern int __devinit tsi721_register_dma(struct tsi721_device *priv);
++extern int tsi721_register_dma(struct tsi721_device *priv);
+ #endif
+ 
+ #endif
+diff --git a/drivers/rapidio/devices/tsi721_dma.c b/drivers/rapidio/devices/tsi721_dma.c
+index 92e06a5c62ec..502663f5f7c6 100644
+--- a/drivers/rapidio/devices/tsi721_dma.c
++++ b/drivers/rapidio/devices/tsi721_dma.c
+@@ -765,7 +765,7 @@ static int tsi721_device_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd,
+ 	return 0;
+ }
+ 
+-int __devinit tsi721_register_dma(struct tsi721_device *priv)
++int tsi721_register_dma(struct tsi721_device *priv)
+ {
+ 	int i;
+ 	int nr_channels = TSI721_DMA_MAXCH;
+diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
+index 07da58bb495c..a965acd3c0e4 100644
+--- a/drivers/rapidio/rio-scan.c
++++ b/drivers/rapidio/rio-scan.c
+@@ -371,7 +371,7 @@ static void rio_switch_init(struct rio_dev *rdev, int do_enum)
+  * device to the RIO device list.  Creates the generic sysfs nodes
+  * for an RIO device.
+  */
+-static int __devinit rio_add_device(struct rio_dev *rdev)
++static int rio_add_device(struct rio_dev *rdev)
+ {
+ 	int err;
+ 
+@@ -463,7 +463,7 @@ inline int rio_enable_rx_tx_port(struct rio_mport *port,
+  * to a RIO device on success or NULL on failure.
+  *
+  */
+-static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
++static struct rio_dev *rio_setup_device(struct rio_net *net,
+ 					struct rio_mport *port, u16 destid,
+ 					u8 hopcount, int do_enum)
+ {
+@@ -837,7 +837,7 @@ static u16 rio_get_host_deviceid_lock(struct rio_mport *port, u8 hopcount)
+  * Recursively enumerates a RIO network.  Transactions are sent via the
+  * master port passed in @port.
+  */
+-static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
++static int rio_enum_peer(struct rio_net *net, struct rio_mport *port,
+ 			 u8 hopcount, struct rio_dev *prev, int prev_port)
+ {
+ 	struct rio_dev *rdev;
+@@ -1044,7 +1044,7 @@ static int rio_enum_complete(struct rio_mport *port)
+  * Recursively discovers a RIO network.  Transactions are sent via the
+  * master port passed in @port.
+  */
+-static int __devinit
++static int
+ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid,
+ 	      u8 hopcount, struct rio_dev *prev, int prev_port)
+ {
+@@ -1151,7 +1151,7 @@ static int rio_mport_is_active(struct rio_mport *port)
+  * network list of associated master ports. Returns a
+  * RIO network pointer on success or %NULL on failure.
+  */
+-static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port,
++static struct rio_net *rio_alloc_net(struct rio_mport *port,
+ 					       int do_enum, u16 start)
+ {
+ 	struct rio_net *net;
+@@ -1266,7 +1266,7 @@ static void rio_pw_enable(struct rio_mport *port, int enable)
+  * link, then start recursive peer enumeration. Returns %0 if
+  * enumeration succeeds or %-EBUSY if enumeration fails.
+  */
+-int __devinit rio_enum_mport(struct rio_mport *mport)
++int rio_enum_mport(struct rio_mport *mport)
+ {
+ 	struct rio_net *net = NULL;
+ 	int rc = 0;
+@@ -1369,7 +1369,7 @@ static void rio_build_route_tables(struct rio_net *net)
+  * peer discovery. Returns %0 if discovery succeeds or %-EBUSY
+  * on failure.
+  */
+-int __devinit rio_disc_mport(struct rio_mport *mport)
++int rio_disc_mport(struct rio_mport *mport)
+ {
+ 	struct rio_net *net = NULL;
+ 	unsigned long to_end;
+diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c
+index c17ae22567e0..08bf922d2f20 100644
+--- a/drivers/rapidio/rio.c
++++ b/drivers/rapidio/rio.c
+@@ -1250,7 +1250,7 @@ static void rio_fixup_device(struct rio_dev *dev)
+ {
+ }
+ 
+-static int __devinit rio_init(void)
++static int rio_init(void)
+ {
+ 	struct rio_dev *dev = NULL;
+ 
+@@ -1267,7 +1267,7 @@ struct rio_disc_work {
+ 	struct rio_mport	*mport;
+ };
+ 
+-static void __devinit disc_work_handler(struct work_struct *_work)
++static void disc_work_handler(struct work_struct *_work)
+ {
+ 	struct rio_disc_work *work;
+ 
+@@ -1277,7 +1277,7 @@ static void __devinit disc_work_handler(struct work_struct *_work)
+ 	rio_disc_mport(work->mport);
+ }
+ 
+-int __devinit rio_init_mports(void)
++int rio_init_mports(void)
+ {
+ 	struct rio_mport *port;
+ 	struct rio_disc_work *work;

commit e765a02cb64bfef53f290122ca0897ef329a4e76
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:05 2012 -0500
+
+    pcmcia: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/pcmcia/bcm63xx_pcmcia.c b/drivers/pcmcia/bcm63xx_pcmcia.c
+index 7d2167995821..0c6aac1232fc 100644
+--- a/drivers/pcmcia/bcm63xx_pcmcia.c
++++ b/drivers/pcmcia/bcm63xx_pcmcia.c
+@@ -436,7 +436,7 @@ static int bcm63xx_drv_pcmcia_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit bcm63xx_drv_pcmcia_remove(struct platform_device *pdev)
++static int bcm63xx_drv_pcmcia_remove(struct platform_device *pdev)
+ {
+ 	struct bcm63xx_pcmcia_socket *skt;
+ 	struct resource *res;
+@@ -469,7 +469,7 @@ static int bcm63xx_cb_probe(struct pci_dev *dev,
+ 	return platform_driver_register(&bcm63xx_pcmcia_driver);
+ }
+ 
+-static void __devexit bcm63xx_cb_exit(struct pci_dev *dev)
++static void bcm63xx_cb_exit(struct pci_dev *dev)
+ {
+ 	platform_driver_unregister(&bcm63xx_pcmcia_driver);
+ 	bcm63xx_cb_dev = NULL;
+diff --git a/drivers/pcmcia/bfin_cf_pcmcia.c b/drivers/pcmcia/bfin_cf_pcmcia.c
+index dc1007392d56..ed3b522601b3 100644
+--- a/drivers/pcmcia/bfin_cf_pcmcia.c
++++ b/drivers/pcmcia/bfin_cf_pcmcia.c
+@@ -286,7 +286,7 @@ static int bfin_cf_probe(struct platform_device *pdev)
+ 	return status;
+ }
+ 
+-static int __devexit bfin_cf_remove(struct platform_device *pdev)
++static int bfin_cf_remove(struct platform_device *pdev)
+ {
+ 	struct bfin_cf_socket *cf = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/pcmcia/db1xxx_ss.c b/drivers/pcmcia/db1xxx_ss.c
+index aaded4fff4c0..a31e69ea99f3 100644
+--- a/drivers/pcmcia/db1xxx_ss.c
++++ b/drivers/pcmcia/db1xxx_ss.c
+@@ -559,7 +559,7 @@ static int db1x_pcmcia_socket_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit db1x_pcmcia_socket_remove(struct platform_device *pdev)
++static int db1x_pcmcia_socket_remove(struct platform_device *pdev)
+ {
+ 	struct db1x_pcmcia_sock *sock = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c
+index 1fe3d88ee566..a007321ad314 100644
+--- a/drivers/pcmcia/electra_cf.c
++++ b/drivers/pcmcia/electra_cf.c
+@@ -324,7 +324,7 @@ static int electra_cf_probe(struct platform_device *ofdev)
+ 
+ }
+ 
+-static int __devexit electra_cf_remove(struct platform_device *ofdev)
++static int electra_cf_remove(struct platform_device *ofdev)
+ {
+ 	struct device *device = &ofdev->dev;
+ 	struct electra_cf_socket *cf;
+diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
+index 26832de5f12c..3578e1ca97a0 100644
+--- a/drivers/pcmcia/i82092.c
++++ b/drivers/pcmcia/i82092.c
+@@ -162,7 +162,7 @@ static int i82092aa_pci_probe(struct pci_dev *dev, const struct pci_device_id *i
+ 	return ret;			
+ }
+ 
+-static void __devexit i82092aa_pci_remove(struct pci_dev *dev)
++static void i82092aa_pci_remove(struct pci_dev *dev)
+ {
+ 	struct pcmcia_socket *socket = pci_get_drvdata(dev);
+ 
+diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
+index 4bb8426afe6d..b29d97e170ae 100644
+--- a/drivers/pcmcia/pd6729.c
++++ b/drivers/pcmcia/pd6729.c
+@@ -739,7 +739,7 @@ static int pd6729_pci_probe(struct pci_dev *dev,
+ 	return ret;
+ }
+ 
+-static void __devexit pd6729_pci_remove(struct pci_dev *dev)
++static void pd6729_pci_remove(struct pci_dev *dev)
+ {
+ 	int i;
+ 	struct pd6729_socket *socket = pci_get_drvdata(dev);
+diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
+index 4c38a04d4356..430a9ac56091 100644
+--- a/drivers/pcmcia/rsrc_nonstatic.c
++++ b/drivers/pcmcia/rsrc_nonstatic.c
+@@ -1209,7 +1209,7 @@ static int pccard_sysfs_add_rsrc(struct device *dev,
+ 	return sysfs_create_group(&dev->kobj, &rsrc_attributes);
+ }
+ 
+-static void __devexit pccard_sysfs_remove_rsrc(struct device *dev,
++static void pccard_sysfs_remove_rsrc(struct device *dev,
+ 					       struct class_interface *class_intf)
+ {
+ 	struct pcmcia_socket *s = dev_get_drvdata(dev);
+diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c
+index cb69f61f11ba..65b02c3e14ce 100644
+--- a/drivers/pcmcia/sa1111_generic.c
++++ b/drivers/pcmcia/sa1111_generic.c
+@@ -211,7 +211,7 @@ static int pcmcia_probe(struct sa1111_dev *dev)
+ 	return 0;
+ }
+ 
+-static int __devexit pcmcia_remove(struct sa1111_dev *dev)
++static int pcmcia_remove(struct sa1111_dev *dev)
+ {
+ 	struct sa1111_pcmcia_socket *next, *s = dev_get_drvdata(&dev->dev);
+ 
+diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c
+index 287d73be203c..75806be344e5 100644
+--- a/drivers/pcmcia/vrc4171_card.c
++++ b/drivers/pcmcia/vrc4171_card.c
+@@ -746,7 +746,7 @@ static int vrc4171_card_init(void)
+ 	return 0;
+ }
+ 
+-static void __devexit vrc4171_card_exit(void)
++static void vrc4171_card_exit(void)
+ {
+ 	free_irq(vrc4171_irq, vrc4171_sockets);
+ 	vrc4171_remove_sockets();
+diff --git a/drivers/pcmcia/vrc4173_cardu.c b/drivers/pcmcia/vrc4173_cardu.c
+index fa17e38c194d..d92692056e24 100644
+--- a/drivers/pcmcia/vrc4173_cardu.c
++++ b/drivers/pcmcia/vrc4173_cardu.c
+@@ -581,7 +581,7 @@ static int vrc4173_cardu_init(void)
+ 	return pci_register_driver(&vrc4173_cardu_driver);
+ }
+ 
+-static void __devexit vrc4173_cardu_exit(void)
++static void vrc4173_cardu_exit(void)
+ {
+ 	pci_unregister_driver(&vrc4173_cardu_driver);
+ }
+diff --git a/drivers/pcmcia/xxs1500_ss.c b/drivers/pcmcia/xxs1500_ss.c
+index 86a89c732825..95f5b270ad44 100644
+--- a/drivers/pcmcia/xxs1500_ss.c
++++ b/drivers/pcmcia/xxs1500_ss.c
+@@ -299,7 +299,7 @@ static int xxs1500_pcmcia_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit xxs1500_pcmcia_remove(struct platform_device *pdev)
++static int xxs1500_pcmcia_remove(struct platform_device *pdev)
+ {
+ 	struct xxs1500_pcmcia_sock *sock = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
+index caa92cc7a428..6b4ff099fb13 100644
+--- a/drivers/pcmcia/yenta_socket.c
++++ b/drivers/pcmcia/yenta_socket.c
+@@ -783,7 +783,7 @@ static void yenta_free_resources(struct yenta_socket *socket)
+ /*
+  * Close it down - release our resources and go home..
+  */
+-static void __devexit yenta_close(struct pci_dev *dev)
++static void yenta_close(struct pci_dev *dev)
+ {
+ 	struct yenta_socket *sock = pci_get_drvdata(dev);
+ 

commit 21fb7674c972a73a2dc0954aeeac5929b7fb3e86
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:24:26 2012 -0500
+
+    pcmcia: remove use of __devinitdata
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitdata is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
+index 113bd4e978db..ff8a027a4afb 100644
+--- a/drivers/pcmcia/sa1100_generic.c
++++ b/drivers/pcmcia/sa1100_generic.c
+@@ -43,7 +43,7 @@
+ 
+ int __init pcmcia_collie_init(struct device *dev);
+ 
+-static int (*sa11x0_pcmcia_hw_init[])(struct device *dev) __devinitdata = {
++static int (*sa11x0_pcmcia_hw_init[])(struct device *dev) = {
+ #ifdef CONFIG_SA1100_ASSABET
+ 	pcmcia_assabet_init,
+ #endif

commit 34cdf25a126f053698d549cc12a9c30e9a8a0bab
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:23:12 2012 -0500
+
+    pcmcia: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Eric Miao 
+    Cc: Russell King 
+    Cc: Haojian Zhuang 
+    Acked-by: Eric Miao 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/pcmcia/bcm63xx_pcmcia.c b/drivers/pcmcia/bcm63xx_pcmcia.c
+index 57d1053d5bfa..7d2167995821 100644
+--- a/drivers/pcmcia/bcm63xx_pcmcia.c
++++ b/drivers/pcmcia/bcm63xx_pcmcia.c
+@@ -323,7 +323,7 @@ static struct pccard_operations bcm63xx_pcmcia_operations = {
+ /*
+  * register pcmcia socket to core
+  */
+-static int __devinit bcm63xx_drv_pcmcia_probe(struct platform_device *pdev)
++static int bcm63xx_drv_pcmcia_probe(struct platform_device *pdev)
+ {
+ 	struct bcm63xx_pcmcia_socket *skt;
+ 	struct pcmcia_socket *sock;
+@@ -461,7 +461,7 @@ struct platform_driver bcm63xx_pcmcia_driver = {
+ };
+ 
+ #ifdef CONFIG_CARDBUS
+-static int __devinit bcm63xx_cb_probe(struct pci_dev *dev,
++static int bcm63xx_cb_probe(struct pci_dev *dev,
+ 				      const struct pci_device_id *id)
+ {
+ 	/* keep pci device */
+diff --git a/drivers/pcmcia/bfin_cf_pcmcia.c b/drivers/pcmcia/bfin_cf_pcmcia.c
+index 2f4bd2751c7a..dc1007392d56 100644
+--- a/drivers/pcmcia/bfin_cf_pcmcia.c
++++ b/drivers/pcmcia/bfin_cf_pcmcia.c
+@@ -195,7 +195,7 @@ static struct pccard_operations bfin_cf_ops = {
+ 
+ /*--------------------------------------------------------------------------*/
+ 
+-static int __devinit bfin_cf_probe(struct platform_device *pdev)
++static int bfin_cf_probe(struct platform_device *pdev)
+ {
+ 	struct bfin_cf_socket *cf;
+ 	struct resource *io_mem, *attr_mem;
+diff --git a/drivers/pcmcia/db1xxx_ss.c b/drivers/pcmcia/db1xxx_ss.c
+index bbbf6f6c1dfc..aaded4fff4c0 100644
+--- a/drivers/pcmcia/db1xxx_ss.c
++++ b/drivers/pcmcia/db1xxx_ss.c
+@@ -409,7 +409,7 @@ static struct pccard_operations db1x_pcmcia_operations = {
+ 	.set_mem_map		= au1x00_pcmcia_set_mem_map,
+ };
+ 
+-static int __devinit db1x_pcmcia_socket_probe(struct platform_device *pdev)
++static int db1x_pcmcia_socket_probe(struct platform_device *pdev)
+ {
+ 	struct db1x_pcmcia_sock *sock;
+ 	struct resource *r;
+diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
+index 84e665961bbd..2deacbb2ffdc 100644
+--- a/drivers/pcmcia/ds.c
++++ b/drivers/pcmcia/ds.c
+@@ -1318,7 +1318,7 @@ static struct pcmcia_callback pcmcia_bus_callback = {
+ 	.resume = pcmcia_bus_resume,
+ };
+ 
+-static int __devinit pcmcia_bus_add_socket(struct device *dev,
++static int pcmcia_bus_add_socket(struct device *dev,
+ 					   struct class_interface *class_intf)
+ {
+ 	struct pcmcia_socket *socket = dev_get_drvdata(dev);
+diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c
+index 7647d232e9e2..1fe3d88ee566 100644
+--- a/drivers/pcmcia/electra_cf.c
++++ b/drivers/pcmcia/electra_cf.c
+@@ -181,7 +181,7 @@ static struct pccard_operations electra_cf_ops = {
+ 	.set_mem_map		= electra_cf_set_mem_map,
+ };
+ 
+-static int __devinit electra_cf_probe(struct platform_device *ofdev)
++static int electra_cf_probe(struct platform_device *ofdev)
+ {
+ 	struct device *device = &ofdev->dev;
+ 	struct device_node *np = ofdev->dev.of_node;
+diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
+index 3f6110008e9b..26832de5f12c 100644
+--- a/drivers/pcmcia/i82092.c
++++ b/drivers/pcmcia/i82092.c
+@@ -67,7 +67,7 @@ static struct socket_info sockets[MAX_SOCKETS];
+ static int socket_count;  /* shortcut */                                  	                                	
+ 
+ 
+-static int __devinit i82092aa_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
++static int i82092aa_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	unsigned char configbyte;
+ 	int i, ret;
+diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
+index aa79c0cc6dcf..4bb8426afe6d 100644
+--- a/drivers/pcmcia/pd6729.c
++++ b/drivers/pcmcia/pd6729.c
+@@ -589,7 +589,7 @@ static int pd6729_check_irq(int irq)
+ 	return 0;
+ }
+ 
+-static u_int __devinit pd6729_isa_scan(void)
++static u_int pd6729_isa_scan(void)
+ {
+ 	u_int mask0, mask = 0;
+ 	int i;
+@@ -620,7 +620,7 @@ static u_int __devinit pd6729_isa_scan(void)
+ 	return mask;
+ }
+ 
+-static int __devinit pd6729_pci_probe(struct pci_dev *dev,
++static int pd6729_pci_probe(struct pci_dev *dev,
+ 				      const struct pci_device_id *id)
+ {
+ 	int i, j, ret;
+diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c
+index 7dd879ce514d..89ebd8c76636 100644
+--- a/drivers/pcmcia/pxa2xx_sharpsl.c
++++ b/drivers/pcmcia/pxa2xx_sharpsl.c
+@@ -208,7 +208,7 @@ static struct pcmcia_low_level sharpsl_pcmcia_ops = {
+ #ifdef CONFIG_SA1100_COLLIE
+ #include "sa11xx_base.h"
+ 
+-int __devinit pcmcia_collie_init(struct device *dev)
++int pcmcia_collie_init(struct device *dev)
+ {
+        int ret = -ENODEV;
+ 
+diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
+index fcf4152689b5..4c38a04d4356 100644
+--- a/drivers/pcmcia/rsrc_nonstatic.c
++++ b/drivers/pcmcia/rsrc_nonstatic.c
+@@ -1199,7 +1199,7 @@ static const struct attribute_group rsrc_attributes = {
+ 	.attrs = pccard_rsrc_attributes,
+ };
+ 
+-static int __devinit pccard_sysfs_add_rsrc(struct device *dev,
++static int pccard_sysfs_add_rsrc(struct device *dev,
+ 					   struct class_interface *class_intf)
+ {
+ 	struct pcmcia_socket *s = dev_get_drvdata(dev);
+diff --git a/drivers/pcmcia/sa1100_assabet.c b/drivers/pcmcia/sa1100_assabet.c
+index ba8557eea618..44cfc4416e54 100644
+--- a/drivers/pcmcia/sa1100_assabet.c
++++ b/drivers/pcmcia/sa1100_assabet.c
+@@ -95,7 +95,7 @@ static struct pcmcia_low_level assabet_pcmcia_ops = {
+ 	.socket_suspend		= assabet_pcmcia_socket_suspend,
+ };
+ 
+-int __devinit pcmcia_assabet_init(struct device *dev)
++int pcmcia_assabet_init(struct device *dev)
+ {
+ 	int ret = -ENODEV;
+ 
+diff --git a/drivers/pcmcia/sa1100_cerf.c b/drivers/pcmcia/sa1100_cerf.c
+index c59c44921a3a..b3774e5d0396 100644
+--- a/drivers/pcmcia/sa1100_cerf.c
++++ b/drivers/pcmcia/sa1100_cerf.c
+@@ -81,7 +81,7 @@ static struct pcmcia_low_level cerf_pcmcia_ops = {
+ 	.configure_socket	= cerf_pcmcia_configure_socket,
+ };
+ 
+-int __devinit pcmcia_cerf_init(struct device *dev)
++int pcmcia_cerf_init(struct device *dev)
+ {
+ 	int ret = -ENODEV;
+ 
+diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
+index 2eea664bc079..113bd4e978db 100644
+--- a/drivers/pcmcia/sa1100_generic.c
++++ b/drivers/pcmcia/sa1100_generic.c
+@@ -67,7 +67,7 @@ static int (*sa11x0_pcmcia_hw_init[])(struct device *dev) __devinitdata = {
+ #endif
+ };
+ 
+-static int __devinit sa11x0_drv_pcmcia_probe(struct platform_device *dev)
++static int sa11x0_drv_pcmcia_probe(struct platform_device *dev)
+ {
+ 	int i, ret = -ENODEV;
+ 
+diff --git a/drivers/pcmcia/sa1100_h3600.c b/drivers/pcmcia/sa1100_h3600.c
+index d9c7337b909c..431d8b07cbaf 100644
+--- a/drivers/pcmcia/sa1100_h3600.c
++++ b/drivers/pcmcia/sa1100_h3600.c
+@@ -153,7 +153,7 @@ struct pcmcia_low_level h3600_pcmcia_ops = {
+ 	.socket_suspend		= h3600_pcmcia_socket_suspend,
+ };
+ 
+-int __devinit pcmcia_h3600_init(struct device *dev)
++int pcmcia_h3600_init(struct device *dev)
+ {
+ 	int ret = -ENODEV;
+ 
+diff --git a/drivers/pcmcia/sa1100_shannon.c b/drivers/pcmcia/sa1100_shannon.c
+index 56ab73915602..b07a2dc3296e 100644
+--- a/drivers/pcmcia/sa1100_shannon.c
++++ b/drivers/pcmcia/sa1100_shannon.c
+@@ -92,7 +92,7 @@ static struct pcmcia_low_level shannon_pcmcia_ops = {
+ 	.configure_socket	= shannon_pcmcia_configure_socket,
+ };
+ 
+-int __devinit pcmcia_shannon_init(struct device *dev)
++int pcmcia_shannon_init(struct device *dev)
+ {
+ 	int ret = -ENODEV;
+ 
+diff --git a/drivers/pcmcia/sa1100_simpad.c b/drivers/pcmcia/sa1100_simpad.c
+index 8647b17c449e..73fd37968b6a 100644
+--- a/drivers/pcmcia/sa1100_simpad.c
++++ b/drivers/pcmcia/sa1100_simpad.c
+@@ -109,7 +109,7 @@ static struct pcmcia_low_level simpad_pcmcia_ops = {
+ 	.socket_suspend		= simpad_pcmcia_socket_suspend,
+ };
+ 
+-int __devinit pcmcia_simpad_init(struct device *dev)
++int pcmcia_simpad_init(struct device *dev)
+ {
+ 	int ret = -ENODEV;
+ 
+diff --git a/drivers/pcmcia/sa1111_jornada720.c b/drivers/pcmcia/sa1111_jornada720.c
+index 69428d1f5ae1..3baa3ef09682 100644
+--- a/drivers/pcmcia/sa1111_jornada720.c
++++ b/drivers/pcmcia/sa1111_jornada720.c
+@@ -91,7 +91,7 @@ static struct pcmcia_low_level jornada720_pcmcia_ops = {
+ 	.nr			= 2,
+ };
+ 
+-int __devinit pcmcia_jornada720_init(struct device *dev)
++int pcmcia_jornada720_init(struct device *dev)
+ {
+ 	int ret = -ENODEV;
+ 
+diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c
+index 86e4a1a3c642..287d73be203c 100644
+--- a/drivers/pcmcia/vrc4171_card.c
++++ b/drivers/pcmcia/vrc4171_card.c
+@@ -564,7 +564,7 @@ static inline void reserve_using_irq(int slot)
+ 	vrc4171_irq_mask &= ~(1 << irq);
+ }
+ 
+-static int __devinit vrc4171_add_sockets(void)
++static int vrc4171_add_sockets(void)
+ {
+ 	vrc4171_socket_t *socket;
+ 	int slot, retval;
+@@ -631,7 +631,7 @@ static void vrc4171_remove_sockets(void)
+ 	}
+ }
+ 
+-static int __devinit vrc4171_card_setup(char *options)
++static int vrc4171_card_setup(char *options)
+ {
+ 	if (options == NULL || *options == '\0')
+ 		return 1;
+@@ -712,7 +712,7 @@ static struct platform_driver vrc4171_card_driver = {
+ 	},
+ };
+ 
+-static int __devinit vrc4171_card_init(void)
++static int vrc4171_card_init(void)
+ {
+ 	int retval;
+ 
+diff --git a/drivers/pcmcia/vrc4173_cardu.c b/drivers/pcmcia/vrc4173_cardu.c
+index cd0a315d922b..fa17e38c194d 100644
+--- a/drivers/pcmcia/vrc4173_cardu.c
++++ b/drivers/pcmcia/vrc4173_cardu.c
+@@ -456,7 +456,7 @@ static void cardu_interrupt(int irq, void *dev_id)
+ 	}
+ }
+ 
+-static int __devinit vrc4173_cardu_probe(struct pci_dev *dev,
++static int vrc4173_cardu_probe(struct pci_dev *dev,
+                                          const struct pci_device_id *ent)
+ {
+ 	vrc4173_socket_t *socket;
+@@ -533,7 +533,7 @@ static int __devinit vrc4173_cardu_probe(struct pci_dev *dev,
+ 	return ret;
+ }
+ 
+-static int __devinit vrc4173_cardu_setup(char *options)
++static int vrc4173_cardu_setup(char *options)
+ {
+ 	if (options == NULL || *options == '\0')
+ 		return 1;
+@@ -574,7 +574,7 @@ static struct pci_driver vrc4173_cardu_driver = {
+ 	.id_table	= vrc4173_cardu_id_table,
+ };
+ 
+-static int __devinit vrc4173_cardu_init(void)
++static int vrc4173_cardu_init(void)
+ {
+ 	vrc4173_cardu_slots = 0;
+ 
+diff --git a/drivers/pcmcia/xxs1500_ss.c b/drivers/pcmcia/xxs1500_ss.c
+index 86fa3dfc8bf9..86a89c732825 100644
+--- a/drivers/pcmcia/xxs1500_ss.c
++++ b/drivers/pcmcia/xxs1500_ss.c
+@@ -204,7 +204,7 @@ static struct pccard_operations xxs1500_pcmcia_operations = {
+ 	.set_mem_map		= au1x00_pcmcia_set_mem_map,
+ };
+ 
+-static int __devinit xxs1500_pcmcia_probe(struct platform_device *pdev)
++static int xxs1500_pcmcia_probe(struct platform_device *pdev)
+ {
+ 	struct xxs1500_pcmcia_sock *sock;
+ 	struct resource *r;
+diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
+index 407f403800ea..caa92cc7a428 100644
+--- a/drivers/pcmcia/yenta_socket.c
++++ b/drivers/pcmcia/yenta_socket.c
+@@ -1142,7 +1142,7 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge)
+  * interrupt, and that we can map the cardbus area. Fill in the
+  * socket information structure..
+  */
+-static int __devinit yenta_probe(struct pci_dev *dev, const struct pci_device_id *id)
++static int yenta_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	struct yenta_socket *socket;
+ 	int ret;

commit 96364e3a5cf1416c158a276134d9a4fc861548c2
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:20:38 2012 -0500
+
+    pcmcia: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/pcmcia/bcm63xx_pcmcia.c b/drivers/pcmcia/bcm63xx_pcmcia.c
+index c2e997a570bf..57d1053d5bfa 100644
+--- a/drivers/pcmcia/bcm63xx_pcmcia.c
++++ b/drivers/pcmcia/bcm63xx_pcmcia.c
+@@ -453,7 +453,7 @@ static int __devexit bcm63xx_drv_pcmcia_remove(struct platform_device *pdev)
+ 
+ struct platform_driver bcm63xx_pcmcia_driver = {
+ 	.probe	= bcm63xx_drv_pcmcia_probe,
+-	.remove	= __devexit_p(bcm63xx_drv_pcmcia_remove),
++	.remove	= bcm63xx_drv_pcmcia_remove,
+ 	.driver	= {
+ 		.name	= "bcm63xx_pcmcia",
+ 		.owner  = THIS_MODULE,
+@@ -503,7 +503,7 @@ static struct pci_driver bcm63xx_cardbus_driver = {
+ 	.name		= "bcm63xx_cardbus",
+ 	.id_table	= bcm63xx_cb_table,
+ 	.probe		= bcm63xx_cb_probe,
+-	.remove		= __devexit_p(bcm63xx_cb_exit),
++	.remove		= bcm63xx_cb_exit,
+ };
+ #endif
+ 
+diff --git a/drivers/pcmcia/bfin_cf_pcmcia.c b/drivers/pcmcia/bfin_cf_pcmcia.c
+index ac1a2232eab9..2f4bd2751c7a 100644
+--- a/drivers/pcmcia/bfin_cf_pcmcia.c
++++ b/drivers/pcmcia/bfin_cf_pcmcia.c
+@@ -307,7 +307,7 @@ static struct platform_driver bfin_cf_driver = {
+ 		   .owner = THIS_MODULE,
+ 		   },
+ 	.probe = bfin_cf_probe,
+-	.remove = __devexit_p(bfin_cf_remove),
++	.remove = bfin_cf_remove,
+ };
+ 
+ module_platform_driver(bfin_cf_driver);
+diff --git a/drivers/pcmcia/db1xxx_ss.c b/drivers/pcmcia/db1xxx_ss.c
+index a484b1fb3382..bbbf6f6c1dfc 100644
+--- a/drivers/pcmcia/db1xxx_ss.c
++++ b/drivers/pcmcia/db1xxx_ss.c
+@@ -577,7 +577,7 @@ static struct platform_driver db1x_pcmcia_socket_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= db1x_pcmcia_socket_probe,
+-	.remove		= __devexit_p(db1x_pcmcia_socket_remove),
++	.remove		= db1x_pcmcia_socket_remove,
+ };
+ 
+ module_platform_driver(db1x_pcmcia_socket_driver);
+diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
+index 4e8831bdb6ef..3f6110008e9b 100644
+--- a/drivers/pcmcia/i82092.c
++++ b/drivers/pcmcia/i82092.c
+@@ -35,7 +35,7 @@ static struct pci_driver i82092aa_pci_driver = {
+ 	.name           = "i82092aa",
+ 	.id_table       = i82092aa_pci_ids,
+ 	.probe          = i82092aa_pci_probe,
+-	.remove         = __devexit_p(i82092aa_pci_remove),
++	.remove         = i82092aa_pci_remove,
+ };
+ 
+ 
+diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
+index 253e3867dec7..aa79c0cc6dcf 100644
+--- a/drivers/pcmcia/pd6729.c
++++ b/drivers/pcmcia/pd6729.c
+@@ -772,7 +772,7 @@ static struct pci_driver pd6729_pci_driver = {
+ 	.name		= "pd6729",
+ 	.id_table	= pd6729_pci_ids,
+ 	.probe		= pd6729_pci_probe,
+-	.remove		= __devexit_p(pd6729_pci_remove),
++	.remove		= pd6729_pci_remove,
+ };
+ 
+ static int pd6729_module_init(void)
+diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
+index 9da9656242af..fcf4152689b5 100644
+--- a/drivers/pcmcia/rsrc_nonstatic.c
++++ b/drivers/pcmcia/rsrc_nonstatic.c
+@@ -1222,7 +1222,7 @@ static void __devexit pccard_sysfs_remove_rsrc(struct device *dev,
+ static struct class_interface pccard_rsrc_interface __refdata = {
+ 	.class = &pcmcia_socket_class,
+ 	.add_dev = &pccard_sysfs_add_rsrc,
+-	.remove_dev = __devexit_p(&pccard_sysfs_remove_rsrc),
++	.remove_dev = &pccard_sysfs_remove_rsrc,
+ };
+ 
+ static int __init nonstatic_sysfs_init(void)
+diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c
+index 70f728ce1856..cb69f61f11ba 100644
+--- a/drivers/pcmcia/sa1111_generic.c
++++ b/drivers/pcmcia/sa1111_generic.c
+@@ -234,7 +234,7 @@ static struct sa1111_driver pcmcia_driver = {
+ 	},
+ 	.devid		= SA1111_DEVID_PCMCIA,
+ 	.probe		= pcmcia_probe,
+-	.remove		= __devexit_p(pcmcia_remove),
++	.remove		= pcmcia_remove,
+ };
+ 
+ static int __init sa1111_drv_pcmcia_init(void)
+diff --git a/drivers/pcmcia/xxs1500_ss.c b/drivers/pcmcia/xxs1500_ss.c
+index fd5fbd10aad0..86fa3dfc8bf9 100644
+--- a/drivers/pcmcia/xxs1500_ss.c
++++ b/drivers/pcmcia/xxs1500_ss.c
+@@ -317,7 +317,7 @@ static struct platform_driver xxs1500_pcmcia_socket_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= xxs1500_pcmcia_probe,
+-	.remove		= __devexit_p(xxs1500_pcmcia_remove),
++	.remove		= xxs1500_pcmcia_remove,
+ };
+ 
+ module_platform_driver(xxs1500_pcmcia_socket_driver);
+diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
+index 667678db1153..407f403800ea 100644
+--- a/drivers/pcmcia/yenta_socket.c
++++ b/drivers/pcmcia/yenta_socket.c
+@@ -1435,7 +1435,7 @@ static struct pci_driver yenta_cardbus_driver = {
+ 	.name		= "yenta_cardbus",
+ 	.id_table	= yenta_table,
+ 	.probe		= yenta_probe,
+-	.remove		= __devexit_p(yenta_close),
++	.remove		= yenta_close,
+ 	.driver.pm	= YENTA_PM_OPS,
+ };
+ 

commit 13ee2b943c366fc899c860b1aef1c8a2b7a0e546
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:19:13 2012 -0500
+
+    pcmcia: remove CONFIG_HOTPLUG ifdefs
+    
+    Remove conditional code based on CONFIG_HOTPLUG being false.  It's
+    always on now in preparation of it going away as an option.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
+index 079629bff957..84e665961bbd 100644
+--- a/drivers/pcmcia/ds.c
++++ b/drivers/pcmcia/ds.c
+@@ -920,8 +920,6 @@ static int pcmcia_bus_match(struct device *dev, struct device_driver *drv)
+ 	return 0;
+ }
+ 
+-#ifdef CONFIG_HOTPLUG
+-
+ static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
+ {
+ 	struct pcmcia_device *p_dev;
+@@ -962,15 +960,6 @@ static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
+ 	return 0;
+ }
+ 
+-#else
+-
+-static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
+-{
+-	return -ENODEV;
+-}
+-
+-#endif
+-
+ /************************ runtime PM support ***************************/
+ 
+ static int pcmcia_dev_suspend(struct device *dev, pm_message_t state);

commit 7e4b9d0bb2a6464e541d51a1e59ba73470c7c453
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:34 2012 -0500
+
+    backlight: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Richard Purdie 
+    Cc: Florian Tobias Schandinat 
+    Acked-by: Jingoo Han 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c
+index a7eb3c4120c4..a1e41d4faa71 100644
+--- a/drivers/video/backlight/adp5520_bl.c
++++ b/drivers/video/backlight/adp5520_bl.c
+@@ -333,7 +333,7 @@ static int adp5520_bl_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit adp5520_bl_remove(struct platform_device *pdev)
++static int adp5520_bl_remove(struct platform_device *pdev)
+ {
+ 	struct backlight_device *bl = platform_get_drvdata(pdev);
+ 	struct adp5520_bl *data = bl_get_data(bl);
+diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c
+index 6feda753ce3e..6bb72c0cb803 100644
+--- a/drivers/video/backlight/adp8860_bl.c
++++ b/drivers/video/backlight/adp8860_bl.c
+@@ -295,7 +295,7 @@ static int adp8860_led_probe(struct i2c_client *client)
+ 	return ret;
+ }
+ 
+-static int __devexit adp8860_led_remove(struct i2c_client *client)
++static int adp8860_led_remove(struct i2c_client *client)
+ {
+ 	struct adp8860_backlight_platform_data *pdata =
+ 		client->dev.platform_data;
+@@ -315,7 +315,7 @@ static int adp8860_led_probe(struct i2c_client *client)
+ 	return 0;
+ }
+ 
+-static int __devexit adp8860_led_remove(struct i2c_client *client)
++static int adp8860_led_remove(struct i2c_client *client)
+ {
+ 	return 0;
+ }
+@@ -755,7 +755,7 @@ static int adp8860_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit adp8860_remove(struct i2c_client *client)
++static int adp8860_remove(struct i2c_client *client)
+ {
+ 	struct adp8860_bl *data = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c
+index 0ef93e1910f0..63c882b8177a 100644
+--- a/drivers/video/backlight/adp8870_bl.c
++++ b/drivers/video/backlight/adp8870_bl.c
+@@ -320,7 +320,7 @@ static int adp8870_led_probe(struct i2c_client *client)
+ 	return ret;
+ }
+ 
+-static int __devexit adp8870_led_remove(struct i2c_client *client)
++static int adp8870_led_remove(struct i2c_client *client)
+ {
+ 	struct adp8870_backlight_platform_data *pdata =
+ 		client->dev.platform_data;
+@@ -340,7 +340,7 @@ static int adp8870_led_probe(struct i2c_client *client)
+ 	return 0;
+ }
+ 
+-static int __devexit adp8870_led_remove(struct i2c_client *client)
++static int adp8870_led_remove(struct i2c_client *client)
+ {
+ 	return 0;
+ }
+@@ -929,7 +929,7 @@ static int adp8870_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit adp8870_remove(struct i2c_client *client)
++static int adp8870_remove(struct i2c_client *client)
+ {
+ 	struct adp8870_bl *data = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/video/backlight/ams369fg06.c b/drivers/video/backlight/ams369fg06.c
+index fbe43b03f1e2..f57e1905236a 100644
+--- a/drivers/video/backlight/ams369fg06.c
++++ b/drivers/video/backlight/ams369fg06.c
+@@ -548,7 +548,7 @@ static int ams369fg06_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit ams369fg06_remove(struct spi_device *spi)
++static int ams369fg06_remove(struct spi_device *spi)
+ {
+ 	struct ams369fg06 *lcd = dev_get_drvdata(&spi->dev);
+ 
+diff --git a/drivers/video/backlight/apple_bl.c b/drivers/video/backlight/apple_bl.c
+index 5b650be6d0b9..f088d4c07381 100644
+--- a/drivers/video/backlight/apple_bl.c
++++ b/drivers/video/backlight/apple_bl.c
+@@ -196,7 +196,7 @@ static int apple_bl_add(struct acpi_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devexit apple_bl_remove(struct acpi_device *dev, int type)
++static int apple_bl_remove(struct acpi_device *dev, int type)
+ {
+ 	backlight_device_unregister(apple_backlight_device);
+ 
+diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c
+index d54224791071..eaaebf21993e 100644
+--- a/drivers/video/backlight/corgi_lcd.c
++++ b/drivers/video/backlight/corgi_lcd.c
+@@ -590,7 +590,7 @@ static int corgi_lcd_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit corgi_lcd_remove(struct spi_device *spi)
++static int corgi_lcd_remove(struct spi_device *spi)
+ {
+ 	struct corgi_lcd *lcd = dev_get_drvdata(&spi->dev);
+ 
+diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c
+index 2ffcee0cd298..f5aa0a5961d6 100644
+--- a/drivers/video/backlight/l4f00242t03.c
++++ b/drivers/video/backlight/l4f00242t03.c
+@@ -230,7 +230,7 @@ static int l4f00242t03_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit l4f00242t03_remove(struct spi_device *spi)
++static int l4f00242t03_remove(struct spi_device *spi)
+ {
+ 	struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev);
+ 
+diff --git a/drivers/video/backlight/ld9040.c b/drivers/video/backlight/ld9040.c
+index 77ba103f6e5e..1cb352418513 100644
+--- a/drivers/video/backlight/ld9040.c
++++ b/drivers/video/backlight/ld9040.c
+@@ -788,7 +788,7 @@ static int ld9040_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit ld9040_remove(struct spi_device *spi)
++static int ld9040_remove(struct spi_device *spi)
+ {
+ 	struct ld9040 *lcd = dev_get_drvdata(&spi->dev);
+ 
+diff --git a/drivers/video/backlight/lm3533_bl.c b/drivers/video/backlight/lm3533_bl.c
+index 029901e95225..5d18d4d7f470 100644
+--- a/drivers/video/backlight/lm3533_bl.c
++++ b/drivers/video/backlight/lm3533_bl.c
+@@ -351,7 +351,7 @@ static int lm3533_bl_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit lm3533_bl_remove(struct platform_device *pdev)
++static int lm3533_bl_remove(struct platform_device *pdev)
+ {
+ 	struct lm3533_bl *bl = platform_get_drvdata(pdev);
+ 	struct backlight_device *bd = bl->bd;
+diff --git a/drivers/video/backlight/lm3630_bl.c b/drivers/video/backlight/lm3630_bl.c
+index cbc58d773b97..0207bc0a4407 100644
+--- a/drivers/video/backlight/lm3630_bl.c
++++ b/drivers/video/backlight/lm3630_bl.c
+@@ -429,7 +429,7 @@ static int lm3630_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit lm3630_remove(struct i2c_client *client)
++static int lm3630_remove(struct i2c_client *client)
+ {
+ 	int ret;
+ 	struct lm3630_chip_data *pchip = i2c_get_clientdata(client);
+diff --git a/drivers/video/backlight/lm3639_bl.c b/drivers/video/backlight/lm3639_bl.c
+index de292c11f643..b0e1e8ba4d9f 100644
+--- a/drivers/video/backlight/lm3639_bl.c
++++ b/drivers/video/backlight/lm3639_bl.c
+@@ -397,7 +397,7 @@ static int lm3639_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit lm3639_remove(struct i2c_client *client)
++static int lm3639_remove(struct i2c_client *client)
+ {
+ 	struct lm3639_chip_data *pchip = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/video/backlight/lms283gf05.c b/drivers/video/backlight/lms283gf05.c
+index e77fd1c97b5d..b29c7071c9db 100644
+--- a/drivers/video/backlight/lms283gf05.c
++++ b/drivers/video/backlight/lms283gf05.c
+@@ -193,7 +193,7 @@ static int lms283gf05_probe(struct spi_device *spi)
+ 	return 0;
+ }
+ 
+-static int __devexit lms283gf05_remove(struct spi_device *spi)
++static int lms283gf05_remove(struct spi_device *spi)
+ {
+ 	struct lms283gf05_state *st = dev_get_drvdata(&spi->dev);
+ 
+diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
+index b41c10f6e4f2..fd985e0681e9 100644
+--- a/drivers/video/backlight/lp855x_bl.c
++++ b/drivers/video/backlight/lp855x_bl.c
+@@ -297,7 +297,7 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
+ 	return ret;
+ }
+ 
+-static int __devexit lp855x_remove(struct i2c_client *cl)
++static int lp855x_remove(struct i2c_client *cl)
+ {
+ 	struct lp855x *lp = i2c_get_clientdata(cl);
+ 
+diff --git a/drivers/video/backlight/ltv350qv.c b/drivers/video/backlight/ltv350qv.c
+index b449bf25fb56..226d813edf01 100644
+--- a/drivers/video/backlight/ltv350qv.c
++++ b/drivers/video/backlight/ltv350qv.c
+@@ -261,7 +261,7 @@ static int ltv350qv_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit ltv350qv_remove(struct spi_device *spi)
++static int ltv350qv_remove(struct spi_device *spi)
+ {
+ 	struct ltv350qv *lcd = dev_get_drvdata(&spi->dev);
+ 
+diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c
+index 191c523baf09..c6bec7aab87b 100644
+--- a/drivers/video/backlight/max8925_bl.c
++++ b/drivers/video/backlight/max8925_bl.c
+@@ -171,7 +171,7 @@ static int max8925_backlight_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit max8925_backlight_remove(struct platform_device *pdev)
++static int max8925_backlight_remove(struct platform_device *pdev)
+ {
+ 	struct backlight_device *bl = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/video/backlight/pcf50633-backlight.c b/drivers/video/backlight/pcf50633-backlight.c
+index db83fba18cb1..0087396007e4 100644
+--- a/drivers/video/backlight/pcf50633-backlight.c
++++ b/drivers/video/backlight/pcf50633-backlight.c
+@@ -145,7 +145,7 @@ static int pcf50633_bl_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit pcf50633_bl_remove(struct platform_device *pdev)
++static int pcf50633_bl_remove(struct platform_device *pdev)
+ {
+ 	struct pcf50633_bl *pcf_bl = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c
+index 8b2992caedf7..894bfc5ce422 100644
+--- a/drivers/video/backlight/platform_lcd.c
++++ b/drivers/video/backlight/platform_lcd.c
+@@ -112,7 +112,7 @@ static int platform_lcd_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit platform_lcd_remove(struct platform_device *pdev)
++static int platform_lcd_remove(struct platform_device *pdev)
+ {
+ 	struct platform_lcd *plcd = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c
+index 11d08bce7c45..484e10dd1a8e 100644
+--- a/drivers/video/backlight/s6e63m0.c
++++ b/drivers/video/backlight/s6e63m0.c
+@@ -825,7 +825,7 @@ static int s6e63m0_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit s6e63m0_remove(struct spi_device *spi)
++static int s6e63m0_remove(struct spi_device *spi)
+ {
+ 	struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev);
+ 
+diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c
+index b5a30cab71e6..146ffb9404d1 100644
+--- a/drivers/video/backlight/tdo24m.c
++++ b/drivers/video/backlight/tdo24m.c
+@@ -401,7 +401,7 @@ static int tdo24m_probe(struct spi_device *spi)
+ 	return err;
+ }
+ 
+-static int __devexit tdo24m_remove(struct spi_device *spi)
++static int tdo24m_remove(struct spi_device *spi)
+ {
+ 	struct tdo24m *lcd = dev_get_drvdata(&spi->dev);
+ 
+diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c
+index dbcb89a35ccb..a0521abdcd8a 100644
+--- a/drivers/video/backlight/tosa_bl.c
++++ b/drivers/video/backlight/tosa_bl.c
+@@ -126,7 +126,7 @@ static int tosa_bl_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit tosa_bl_remove(struct i2c_client *client)
++static int tosa_bl_remove(struct i2c_client *client)
+ {
+ 	struct tosa_bl_data *data = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/video/backlight/tosa_lcd.c b/drivers/video/backlight/tosa_lcd.c
+index 6858116ab449..86fff88c2e4a 100644
+--- a/drivers/video/backlight/tosa_lcd.c
++++ b/drivers/video/backlight/tosa_lcd.c
+@@ -226,7 +226,7 @@ static int tosa_lcd_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit tosa_lcd_remove(struct spi_device *spi)
++static int tosa_lcd_remove(struct spi_device *spi)
+ {
+ 	struct tosa_lcd_data *data = dev_get_drvdata(&spi->dev);
+ 
+diff --git a/drivers/video/backlight/vgg2432a4.c b/drivers/video/backlight/vgg2432a4.c
+index db767bed9600..712b0acfd339 100644
+--- a/drivers/video/backlight/vgg2432a4.c
++++ b/drivers/video/backlight/vgg2432a4.c
+@@ -240,7 +240,7 @@ static int vgg2432a4_probe(struct spi_device *spi)
+ 	return 0;
+ }
+ 
+-static int __devexit vgg2432a4_remove(struct spi_device *spi)
++static int vgg2432a4_remove(struct spi_device *spi)
+ {
+ 	return ili9320_remove(dev_get_drvdata(&spi->dev));
+ }

commit 1b9e450de105c1429a15f4e2566695f4f425672a
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:46 2012 -0500
+
+    backlight: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Richard Purdie 
+    Cc: Florian Tobias Schandinat 
+    Acked-by: Jingoo Han 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c
+index e2a0da342de1..a7eb3c4120c4 100644
+--- a/drivers/video/backlight/adp5520_bl.c
++++ b/drivers/video/backlight/adp5520_bl.c
+@@ -282,7 +282,7 @@ static const struct attribute_group adp5520_bl_attr_group = {
+ 	.attrs = adp5520_bl_attributes,
+ };
+ 
+-static int __devinit adp5520_bl_probe(struct platform_device *pdev)
++static int adp5520_bl_probe(struct platform_device *pdev)
+ {
+ 	struct backlight_properties props;
+ 	struct backlight_device *bl;
+diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c
+index 953c5212efef..6feda753ce3e 100644
+--- a/drivers/video/backlight/adp8860_bl.c
++++ b/drivers/video/backlight/adp8860_bl.c
+@@ -213,7 +213,7 @@ static int adp8860_led_setup(struct adp8860_led *led)
+ 	return ret;
+ }
+ 
+-static int __devinit adp8860_led_probe(struct i2c_client *client)
++static int adp8860_led_probe(struct i2c_client *client)
+ {
+ 	struct adp8860_backlight_platform_data *pdata =
+ 		client->dev.platform_data;
+@@ -310,7 +310,7 @@ static int __devexit adp8860_led_remove(struct i2c_client *client)
+ 	return 0;
+ }
+ #else
+-static int __devinit adp8860_led_probe(struct i2c_client *client)
++static int adp8860_led_probe(struct i2c_client *client)
+ {
+ 	return 0;
+ }
+@@ -650,7 +650,7 @@ static const struct attribute_group adp8860_bl_attr_group = {
+ 	.attrs = adp8860_bl_attributes,
+ };
+ 
+-static int __devinit adp8860_probe(struct i2c_client *client,
++static int adp8860_probe(struct i2c_client *client,
+ 					const struct i2c_device_id *id)
+ {
+ 	struct backlight_device *bl;
+diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c
+index 558772b91795..0ef93e1910f0 100644
+--- a/drivers/video/backlight/adp8870_bl.c
++++ b/drivers/video/backlight/adp8870_bl.c
+@@ -235,7 +235,7 @@ static int adp8870_led_setup(struct adp8870_led *led)
+ 	return ret;
+ }
+ 
+-static int __devinit adp8870_led_probe(struct i2c_client *client)
++static int adp8870_led_probe(struct i2c_client *client)
+ {
+ 	struct adp8870_backlight_platform_data *pdata =
+ 		client->dev.platform_data;
+@@ -335,7 +335,7 @@ static int __devexit adp8870_led_remove(struct i2c_client *client)
+ 	return 0;
+ }
+ #else
+-static int __devinit adp8870_led_probe(struct i2c_client *client)
++static int adp8870_led_probe(struct i2c_client *client)
+ {
+ 	return 0;
+ }
+@@ -839,7 +839,7 @@ static const struct attribute_group adp8870_bl_attr_group = {
+ 	.attrs = adp8870_bl_attributes,
+ };
+ 
+-static int __devinit adp8870_probe(struct i2c_client *client,
++static int adp8870_probe(struct i2c_client *client,
+ 					const struct i2c_device_id *id)
+ {
+ 	struct backlight_properties props;
+diff --git a/drivers/video/backlight/ams369fg06.c b/drivers/video/backlight/ams369fg06.c
+index e48f4b1473ab..fbe43b03f1e2 100644
+--- a/drivers/video/backlight/ams369fg06.c
++++ b/drivers/video/backlight/ams369fg06.c
+@@ -474,7 +474,7 @@ static const struct backlight_ops ams369fg06_backlight_ops = {
+ 	.update_status = ams369fg06_set_brightness,
+ };
+ 
+-static int __devinit ams369fg06_probe(struct spi_device *spi)
++static int ams369fg06_probe(struct spi_device *spi)
+ {
+ 	int ret = 0;
+ 	struct ams369fg06 *lcd = NULL;
+diff --git a/drivers/video/backlight/apple_bl.c b/drivers/video/backlight/apple_bl.c
+index 9dc73ac3709a..5b650be6d0b9 100644
+--- a/drivers/video/backlight/apple_bl.c
++++ b/drivers/video/backlight/apple_bl.c
+@@ -137,7 +137,7 @@ static const struct hw_data nvidia_chipset_data = {
+ 	.set_brightness = nvidia_chipset_set_brightness,
+ };
+ 
+-static int __devinit apple_bl_add(struct acpi_device *dev)
++static int apple_bl_add(struct acpi_device *dev)
+ {
+ 	struct backlight_properties props;
+ 	struct pci_dev *host;
+diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c
+index 8617284f87bb..d54224791071 100644
+--- a/drivers/video/backlight/corgi_lcd.c
++++ b/drivers/video/backlight/corgi_lcd.c
+@@ -529,7 +529,7 @@ static int setup_gpio_backlight(struct corgi_lcd *lcd,
+ 	return 0;
+ }
+ 
+-static int __devinit corgi_lcd_probe(struct spi_device *spi)
++static int corgi_lcd_probe(struct spi_device *spi)
+ {
+ 	struct backlight_properties props;
+ 	struct corgi_lcd_platform_data *pdata = spi->dev.platform_data;
+diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c
+index 38aa00272141..c99966342448 100644
+--- a/drivers/video/backlight/hp680_bl.c
++++ b/drivers/video/backlight/hp680_bl.c
+@@ -103,7 +103,7 @@ static const struct backlight_ops hp680bl_ops = {
+ 	.update_status  = hp680bl_set_intensity,
+ };
+ 
+-static int __devinit hp680bl_probe(struct platform_device *pdev)
++static int hp680bl_probe(struct platform_device *pdev)
+ {
+ 	struct backlight_properties props;
+ 	struct backlight_device *bd;
+diff --git a/drivers/video/backlight/ili9320.c b/drivers/video/backlight/ili9320.c
+index 9327cd1b3143..66cc313185ad 100644
+--- a/drivers/video/backlight/ili9320.c
++++ b/drivers/video/backlight/ili9320.c
+@@ -171,7 +171,7 @@ static struct lcd_ops ili9320_ops = {
+ 	.set_power	= ili9320_set_power,
+ };
+ 
+-static void __devinit ili9320_setup_spi(struct ili9320 *ili,
++static void ili9320_setup_spi(struct ili9320 *ili,
+ 					struct spi_device *dev)
+ {
+ 	struct ili9320_spi *spi = &ili->access.spi;
+@@ -197,7 +197,7 @@ static void __devinit ili9320_setup_spi(struct ili9320 *ili,
+ 	spi_message_add_tail(&spi->xfer[1], &spi->message);
+ }
+ 
+-int __devinit ili9320_probe_spi(struct spi_device *spi,
++int ili9320_probe_spi(struct spi_device *spi,
+ 				struct ili9320_client *client)
+ {
+ 	struct ili9320_platdata *cfg = spi->dev.platform_data;
+diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c
+index 157a4c69ef94..2ffcee0cd298 100644
+--- a/drivers/video/backlight/l4f00242t03.c
++++ b/drivers/video/backlight/l4f00242t03.c
+@@ -150,7 +150,7 @@ static struct lcd_ops l4f_ops = {
+ 	.get_power	= l4f00242t03_lcd_power_get,
+ };
+ 
+-static int __devinit l4f00242t03_probe(struct spi_device *spi)
++static int l4f00242t03_probe(struct spi_device *spi)
+ {
+ 	struct l4f00242t03_priv *priv;
+ 	struct l4f00242t03_pdata *pdata = spi->dev.platform_data;
+diff --git a/drivers/video/backlight/lm3533_bl.c b/drivers/video/backlight/lm3533_bl.c
+index c9a0b5118c8a..029901e95225 100644
+--- a/drivers/video/backlight/lm3533_bl.c
++++ b/drivers/video/backlight/lm3533_bl.c
+@@ -257,7 +257,7 @@ static struct attribute_group lm3533_bl_attribute_group = {
+ 	.attrs		= lm3533_bl_attributes
+ };
+ 
+-static int __devinit lm3533_bl_setup(struct lm3533_bl *bl,
++static int lm3533_bl_setup(struct lm3533_bl *bl,
+ 					struct lm3533_bl_platform_data *pdata)
+ {
+ 	int ret;
+@@ -269,7 +269,7 @@ static int __devinit lm3533_bl_setup(struct lm3533_bl *bl,
+ 	return lm3533_ctrlbank_set_pwm(&bl->cb, pdata->pwm);
+ }
+ 
+-static int __devinit lm3533_bl_probe(struct platform_device *pdev)
++static int lm3533_bl_probe(struct platform_device *pdev)
+ {
+ 	struct lm3533 *lm3533;
+ 	struct lm3533_bl_platform_data *pdata;
+diff --git a/drivers/video/backlight/lm3630_bl.c b/drivers/video/backlight/lm3630_bl.c
+index d407855fbcc5..cbc58d773b97 100644
+--- a/drivers/video/backlight/lm3630_bl.c
++++ b/drivers/video/backlight/lm3630_bl.c
+@@ -55,7 +55,7 @@ struct lm3630_chip_data {
+ };
+ 
+ /* initialize chip */
+-static int __devinit lm3630_chip_init(struct lm3630_chip_data *pchip)
++static int lm3630_chip_init(struct lm3630_chip_data *pchip)
+ {
+ 	int ret;
+ 	unsigned int reg_val;
+@@ -349,7 +349,7 @@ static const struct regmap_config lm3630_regmap = {
+ 	.max_register = REG_MAX,
+ };
+ 
+-static int __devinit lm3630_probe(struct i2c_client *client,
++static int lm3630_probe(struct i2c_client *client,
+ 				  const struct i2c_device_id *id)
+ {
+ 	struct lm3630_platform_data *pdata = client->dev.platform_data;
+diff --git a/drivers/video/backlight/lm3639_bl.c b/drivers/video/backlight/lm3639_bl.c
+index 1bc53736ceab..de292c11f643 100644
+--- a/drivers/video/backlight/lm3639_bl.c
++++ b/drivers/video/backlight/lm3639_bl.c
+@@ -48,7 +48,7 @@ struct lm3639_chip_data {
+ };
+ 
+ /* initialize chip */
+-static int __devinit lm3639_chip_init(struct lm3639_chip_data *pchip)
++static int lm3639_chip_init(struct lm3639_chip_data *pchip)
+ {
+ 	int ret;
+ 	unsigned int reg_val;
+@@ -299,7 +299,7 @@ static const struct regmap_config lm3639_regmap = {
+ 	.max_register = REG_MAX,
+ };
+ 
+-static int __devinit lm3639_probe(struct i2c_client *client,
++static int lm3639_probe(struct i2c_client *client,
+ 				  const struct i2c_device_id *id)
+ {
+ 	int ret;
+diff --git a/drivers/video/backlight/lms283gf05.c b/drivers/video/backlight/lms283gf05.c
+index bfb4f370dcd9..e77fd1c97b5d 100644
+--- a/drivers/video/backlight/lms283gf05.c
++++ b/drivers/video/backlight/lms283gf05.c
+@@ -150,7 +150,7 @@ static struct lcd_ops lms_ops = {
+ 	.get_power	= NULL,
+ };
+ 
+-static int __devinit lms283gf05_probe(struct spi_device *spi)
++static int lms283gf05_probe(struct spi_device *spi)
+ {
+ 	struct lms283gf05_state *st;
+ 	struct lms283gf05_pdata *pdata = spi->dev.platform_data;
+diff --git a/drivers/video/backlight/ltv350qv.c b/drivers/video/backlight/ltv350qv.c
+index c63ce6e75021..b449bf25fb56 100644
+--- a/drivers/video/backlight/ltv350qv.c
++++ b/drivers/video/backlight/ltv350qv.c
+@@ -226,7 +226,7 @@ static struct lcd_ops ltv_ops = {
+ 	.set_power	= ltv350qv_set_power,
+ };
+ 
+-static int __devinit ltv350qv_probe(struct spi_device *spi)
++static int ltv350qv_probe(struct spi_device *spi)
+ {
+ 	struct ltv350qv *lcd;
+ 	struct lcd_device *ld;
+diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c
+index 3882b2761f78..191c523baf09 100644
+--- a/drivers/video/backlight/max8925_bl.c
++++ b/drivers/video/backlight/max8925_bl.c
+@@ -101,7 +101,7 @@ static const struct backlight_ops max8925_backlight_ops = {
+ 	.get_brightness	= max8925_backlight_get_brightness,
+ };
+ 
+-static int __devinit max8925_backlight_probe(struct platform_device *pdev)
++static int max8925_backlight_probe(struct platform_device *pdev)
+ {
+ 	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
+ 	struct max8925_backlight_pdata *pdata = pdev->dev.platform_data;
+diff --git a/drivers/video/backlight/pcf50633-backlight.c b/drivers/video/backlight/pcf50633-backlight.c
+index e654b5c4a3bb..db83fba18cb1 100644
+--- a/drivers/video/backlight/pcf50633-backlight.c
++++ b/drivers/video/backlight/pcf50633-backlight.c
+@@ -99,7 +99,7 @@ static const struct backlight_ops pcf50633_bl_ops = {
+ 	.options	= BL_CORE_SUSPENDRESUME,
+ };
+ 
+-static int __devinit pcf50633_bl_probe(struct platform_device *pdev)
++static int pcf50633_bl_probe(struct platform_device *pdev)
+ {
+ 	struct pcf50633_bl *pcf_bl;
+ 	struct device *parent = pdev->dev.parent;
+diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c
+index 54e72841982e..8b2992caedf7 100644
+--- a/drivers/video/backlight/platform_lcd.c
++++ b/drivers/video/backlight/platform_lcd.c
+@@ -73,7 +73,7 @@ static struct lcd_ops platform_lcd_ops = {
+ 	.check_fb	= platform_lcd_match,
+ };
+ 
+-static int __devinit platform_lcd_probe(struct platform_device *pdev)
++static int platform_lcd_probe(struct platform_device *pdev)
+ {
+ 	struct plat_lcd_data *pdata;
+ 	struct platform_lcd *plcd;
+diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c
+index 1438b993a9ef..11d08bce7c45 100644
+--- a/drivers/video/backlight/s6e63m0.c
++++ b/drivers/video/backlight/s6e63m0.c
+@@ -733,7 +733,7 @@ static ssize_t s6e63m0_sysfs_show_gamma_table(struct device *dev,
+ static DEVICE_ATTR(gamma_table, 0444,
+ 		s6e63m0_sysfs_show_gamma_table, NULL);
+ 
+-static int __devinit s6e63m0_probe(struct spi_device *spi)
++static int s6e63m0_probe(struct spi_device *spi)
+ {
+ 	int ret = 0;
+ 	struct s6e63m0 *lcd = NULL;
+diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c
+index 076f4f6d3335..b5a30cab71e6 100644
+--- a/drivers/video/backlight/tdo24m.c
++++ b/drivers/video/backlight/tdo24m.c
+@@ -328,7 +328,7 @@ static struct lcd_ops tdo24m_ops = {
+ 	.set_mode	= tdo24m_set_mode,
+ };
+ 
+-static int __devinit tdo24m_probe(struct spi_device *spi)
++static int tdo24m_probe(struct spi_device *spi)
+ {
+ 	struct tdo24m *lcd;
+ 	struct spi_message *m;
+diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c
+index 8a82cc91a17f..dbcb89a35ccb 100644
+--- a/drivers/video/backlight/tosa_bl.c
++++ b/drivers/video/backlight/tosa_bl.c
+@@ -78,7 +78,7 @@ static const struct backlight_ops bl_ops = {
+ 	.update_status		= tosa_bl_update_status,
+ };
+ 
+-static int __devinit tosa_bl_probe(struct i2c_client *client,
++static int tosa_bl_probe(struct i2c_client *client,
+ 		const struct i2c_device_id *id)
+ {
+ 	struct backlight_properties props;
+diff --git a/drivers/video/backlight/tosa_lcd.c b/drivers/video/backlight/tosa_lcd.c
+index bf64092509b8..6858116ab449 100644
+--- a/drivers/video/backlight/tosa_lcd.c
++++ b/drivers/video/backlight/tosa_lcd.c
+@@ -169,7 +169,7 @@ static struct lcd_ops tosa_lcd_ops = {
+ 	.set_mode = tosa_lcd_set_mode,
+ };
+ 
+-static int __devinit tosa_lcd_probe(struct spi_device *spi)
++static int tosa_lcd_probe(struct spi_device *spi)
+ {
+ 	int ret;
+ 	struct tosa_lcd_data *data;
+diff --git a/drivers/video/backlight/vgg2432a4.c b/drivers/video/backlight/vgg2432a4.c
+index f821ab8106fc..db767bed9600 100644
+--- a/drivers/video/backlight/vgg2432a4.c
++++ b/drivers/video/backlight/vgg2432a4.c
+@@ -227,7 +227,7 @@ static struct ili9320_client vgg2432a4_client = {
+ 
+ /* Device probe */
+ 
+-static int __devinit vgg2432a4_probe(struct spi_device *spi)
++static int vgg2432a4_probe(struct spi_device *spi)
+ {
+ 	int ret;
+ 

commit d1723fa266aff677571cad0bac7203ed2e424823
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:09 2012 -0500
+
+    backlight: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Richard Purdie 
+    Cc: Florian Tobias Schandinat 
+    Acked-by: Jingoo Han 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c
+index df5db99af23d..e2a0da342de1 100644
+--- a/drivers/video/backlight/adp5520_bl.c
++++ b/drivers/video/backlight/adp5520_bl.c
+@@ -375,7 +375,7 @@ static struct platform_driver adp5520_bl_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= adp5520_bl_probe,
+-	.remove		= __devexit_p(adp5520_bl_remove),
++	.remove		= adp5520_bl_remove,
+ 	.suspend	= adp5520_bl_suspend,
+ 	.resume		= adp5520_bl_resume,
+ };
+diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c
+index 77d1fdba597f..953c5212efef 100644
+--- a/drivers/video/backlight/adp8860_bl.c
++++ b/drivers/video/backlight/adp8860_bl.c
+@@ -805,7 +805,7 @@ static struct i2c_driver adp8860_driver = {
+ 		.name = KBUILD_MODNAME,
+ 	},
+ 	.probe    = adp8860_probe,
+-	.remove   = __devexit_p(adp8860_remove),
++	.remove   = adp8860_remove,
+ 	.suspend = adp8860_i2c_suspend,
+ 	.resume  = adp8860_i2c_resume,
+ 	.id_table = adp8860_id,
+diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c
+index edf7f91c8e61..558772b91795 100644
+--- a/drivers/video/backlight/adp8870_bl.c
++++ b/drivers/video/backlight/adp8870_bl.c
+@@ -977,7 +977,7 @@ static struct i2c_driver adp8870_driver = {
+ 		.name = KBUILD_MODNAME,
+ 	},
+ 	.probe    = adp8870_probe,
+-	.remove   = __devexit_p(adp8870_remove),
++	.remove   = adp8870_remove,
+ 	.suspend = adp8870_i2c_suspend,
+ 	.resume  = adp8870_i2c_resume,
+ 	.id_table = adp8870_id,
+diff --git a/drivers/video/backlight/ams369fg06.c b/drivers/video/backlight/ams369fg06.c
+index 3729238e7096..e48f4b1473ab 100644
+--- a/drivers/video/backlight/ams369fg06.c
++++ b/drivers/video/backlight/ams369fg06.c
+@@ -617,7 +617,7 @@ static struct spi_driver ams369fg06_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= ams369fg06_probe,
+-	.remove		= __devexit_p(ams369fg06_remove),
++	.remove		= ams369fg06_remove,
+ 	.shutdown	= ams369fg06_shutdown,
+ 	.suspend	= ams369fg06_suspend,
+ 	.resume		= ams369fg06_resume,
+diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c
+index c781768ba892..8617284f87bb 100644
+--- a/drivers/video/backlight/corgi_lcd.c
++++ b/drivers/video/backlight/corgi_lcd.c
+@@ -611,7 +611,7 @@ static struct spi_driver corgi_lcd_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= corgi_lcd_probe,
+-	.remove		= __devexit_p(corgi_lcd_remove),
++	.remove		= corgi_lcd_remove,
+ 	.suspend	= corgi_lcd_suspend,
+ 	.resume		= corgi_lcd_resume,
+ };
+diff --git a/drivers/video/backlight/ep93xx_bl.c b/drivers/video/backlight/ep93xx_bl.c
+index 08214e1f0958..ef3e21e8f825 100644
+--- a/drivers/video/backlight/ep93xx_bl.c
++++ b/drivers/video/backlight/ep93xx_bl.c
+@@ -141,7 +141,7 @@ static struct platform_driver ep93xxbl_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= ep93xxbl_probe,
+-	.remove		= __devexit_p(ep93xxbl_remove),
++	.remove		= ep93xxbl_remove,
+ 	.suspend	= ep93xxbl_suspend,
+ 	.resume		= ep93xxbl_resume,
+ };
+diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c
+index 2d90c0648aa0..157a4c69ef94 100644
+--- a/drivers/video/backlight/l4f00242t03.c
++++ b/drivers/video/backlight/l4f00242t03.c
+@@ -260,7 +260,7 @@ static struct spi_driver l4f00242t03_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= l4f00242t03_probe,
+-	.remove		= __devexit_p(l4f00242t03_remove),
++	.remove		= l4f00242t03_remove,
+ 	.shutdown	= l4f00242t03_shutdown,
+ };
+ 
+diff --git a/drivers/video/backlight/ld9040.c b/drivers/video/backlight/ld9040.c
+index 58f517fb7d40..77ba103f6e5e 100644
+--- a/drivers/video/backlight/ld9040.c
++++ b/drivers/video/backlight/ld9040.c
+@@ -847,7 +847,7 @@ static struct spi_driver ld9040_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= ld9040_probe,
+-	.remove		= __devexit_p(ld9040_remove),
++	.remove		= ld9040_remove,
+ 	.shutdown	= ld9040_shutdown,
+ 	.suspend	= ld9040_suspend,
+ 	.resume		= ld9040_resume,
+diff --git a/drivers/video/backlight/lm3533_bl.c b/drivers/video/backlight/lm3533_bl.c
+index 18dca0c29c68..c9a0b5118c8a 100644
+--- a/drivers/video/backlight/lm3533_bl.c
++++ b/drivers/video/backlight/lm3533_bl.c
+@@ -406,7 +406,7 @@ static struct platform_driver lm3533_bl_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= lm3533_bl_probe,
+-	.remove		= __devexit_p(lm3533_bl_remove),
++	.remove		= lm3533_bl_remove,
+ 	.shutdown	= lm3533_bl_shutdown,
+ 	.suspend	= lm3533_bl_suspend,
+ 	.resume		= lm3533_bl_resume,
+diff --git a/drivers/video/backlight/lm3630_bl.c b/drivers/video/backlight/lm3630_bl.c
+index dc191441796f..d407855fbcc5 100644
+--- a/drivers/video/backlight/lm3630_bl.c
++++ b/drivers/video/backlight/lm3630_bl.c
+@@ -463,7 +463,7 @@ static struct i2c_driver lm3630_i2c_driver = {
+ 		   .name = LM3630_NAME,
+ 		   },
+ 	.probe = lm3630_probe,
+-	.remove = __devexit_p(lm3630_remove),
++	.remove = lm3630_remove,
+ 	.id_table = lm3630_id,
+ };
+ 
+diff --git a/drivers/video/backlight/lm3639_bl.c b/drivers/video/backlight/lm3639_bl.c
+index 585949b57055..1bc53736ceab 100644
+--- a/drivers/video/backlight/lm3639_bl.c
++++ b/drivers/video/backlight/lm3639_bl.c
+@@ -425,7 +425,7 @@ static struct i2c_driver lm3639_i2c_driver = {
+ 		   .name = LM3639_NAME,
+ 		   },
+ 	.probe = lm3639_probe,
+-	.remove = __devexit_p(lm3639_remove),
++	.remove = lm3639_remove,
+ 	.id_table = lm3639_id,
+ };
+ 
+diff --git a/drivers/video/backlight/lms283gf05.c b/drivers/video/backlight/lms283gf05.c
+index ea43f2254196..bfb4f370dcd9 100644
+--- a/drivers/video/backlight/lms283gf05.c
++++ b/drivers/video/backlight/lms283gf05.c
+@@ -208,7 +208,7 @@ static struct spi_driver lms283gf05_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= lms283gf05_probe,
+-	.remove		= __devexit_p(lms283gf05_remove),
++	.remove		= lms283gf05_remove,
+ };
+ 
+ module_spi_driver(lms283gf05_driver);
+diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
+index aa6d4f71131f..b41c10f6e4f2 100644
+--- a/drivers/video/backlight/lp855x_bl.c
++++ b/drivers/video/backlight/lp855x_bl.c
+@@ -324,7 +324,7 @@ static struct i2c_driver lp855x_driver = {
+ 		   .name = "lp855x",
+ 		   },
+ 	.probe = lp855x_probe,
+-	.remove = __devexit_p(lp855x_remove),
++	.remove = lp855x_remove,
+ 	.id_table = lp855x_ids,
+ };
+ 
+diff --git a/drivers/video/backlight/ltv350qv.c b/drivers/video/backlight/ltv350qv.c
+index 4066a5bbd826..c63ce6e75021 100644
+--- a/drivers/video/backlight/ltv350qv.c
++++ b/drivers/video/backlight/ltv350qv.c
+@@ -305,7 +305,7 @@ static struct spi_driver ltv350qv_driver = {
+ 	},
+ 
+ 	.probe		= ltv350qv_probe,
+-	.remove		= __devexit_p(ltv350qv_remove),
++	.remove		= ltv350qv_remove,
+ 	.shutdown	= ltv350qv_shutdown,
+ 	.suspend	= ltv350qv_suspend,
+ 	.resume		= ltv350qv_resume,
+diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c
+index f72ba54f364e..3882b2761f78 100644
+--- a/drivers/video/backlight/max8925_bl.c
++++ b/drivers/video/backlight/max8925_bl.c
+@@ -185,7 +185,7 @@ static struct platform_driver max8925_backlight_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= max8925_backlight_probe,
+-	.remove		= __devexit_p(max8925_backlight_remove),
++	.remove		= max8925_backlight_remove,
+ };
+ 
+ module_platform_driver(max8925_backlight_driver);
+diff --git a/drivers/video/backlight/pcf50633-backlight.c b/drivers/video/backlight/pcf50633-backlight.c
+index c092159f4383..e654b5c4a3bb 100644
+--- a/drivers/video/backlight/pcf50633-backlight.c
++++ b/drivers/video/backlight/pcf50633-backlight.c
+@@ -158,7 +158,7 @@ static int __devexit pcf50633_bl_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver pcf50633_bl_driver = {
+ 	.probe =	pcf50633_bl_probe,
+-	.remove =	__devexit_p(pcf50633_bl_remove),
++	.remove =	pcf50633_bl_remove,
+ 	.driver = {
+ 		.name = "pcf50633-backlight",
+ 	},
+diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c
+index ca4f5d70fe10..54e72841982e 100644
+--- a/drivers/video/backlight/platform_lcd.c
++++ b/drivers/video/backlight/platform_lcd.c
+@@ -164,7 +164,7 @@ static struct platform_driver platform_lcd_driver = {
+ 		.of_match_table = of_match_ptr(platform_lcd_of_match),
+ 	},
+ 	.probe		= platform_lcd_probe,
+-	.remove		= __devexit_p(platform_lcd_remove),
++	.remove		= platform_lcd_remove,
+ };
+ 
+ module_platform_driver(platform_lcd_driver);
+diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c
+index 6437ae474cf2..1438b993a9ef 100644
+--- a/drivers/video/backlight/s6e63m0.c
++++ b/drivers/video/backlight/s6e63m0.c
+@@ -897,7 +897,7 @@ static struct spi_driver s6e63m0_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= s6e63m0_probe,
+-	.remove		= __devexit_p(s6e63m0_remove),
++	.remove		= s6e63m0_remove,
+ 	.shutdown	= s6e63m0_shutdown,
+ 	.suspend	= s6e63m0_suspend,
+ 	.resume		= s6e63m0_resume,
+diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c
+index 02444d042cd5..076f4f6d3335 100644
+--- a/drivers/video/backlight/tdo24m.c
++++ b/drivers/video/backlight/tdo24m.c
+@@ -444,7 +444,7 @@ static struct spi_driver tdo24m_driver = {
+ 		.owner		= THIS_MODULE,
+ 	},
+ 	.probe		= tdo24m_probe,
+-	.remove		= __devexit_p(tdo24m_remove),
++	.remove		= tdo24m_remove,
+ 	.shutdown	= tdo24m_shutdown,
+ 	.suspend	= tdo24m_suspend,
+ 	.resume		= tdo24m_resume,
+diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c
+index 49342e1d20be..8a82cc91a17f 100644
+--- a/drivers/video/backlight/tosa_bl.c
++++ b/drivers/video/backlight/tosa_bl.c
+@@ -170,7 +170,7 @@ static struct i2c_driver tosa_bl_driver = {
+ 		.owner		= THIS_MODULE,
+ 	},
+ 	.probe		= tosa_bl_probe,
+-	.remove		= __devexit_p(tosa_bl_remove),
++	.remove		= tosa_bl_remove,
+ 	.suspend	= tosa_bl_suspend,
+ 	.resume		= tosa_bl_resume,
+ 	.id_table	= tosa_bl_id,
+diff --git a/drivers/video/backlight/tosa_lcd.c b/drivers/video/backlight/tosa_lcd.c
+index 33047a66cc24..bf64092509b8 100644
+--- a/drivers/video/backlight/tosa_lcd.c
++++ b/drivers/video/backlight/tosa_lcd.c
+@@ -275,7 +275,7 @@ static struct spi_driver tosa_lcd_driver = {
+ 		.owner		= THIS_MODULE,
+ 	},
+ 	.probe		= tosa_lcd_probe,
+-	.remove		= __devexit_p(tosa_lcd_remove),
++	.remove		= tosa_lcd_remove,
+ 	.suspend	= tosa_lcd_suspend,
+ 	.resume		= tosa_lcd_resume,
+ };
+diff --git a/drivers/video/backlight/vgg2432a4.c b/drivers/video/backlight/vgg2432a4.c
+index b617fae9aa26..f821ab8106fc 100644
+--- a/drivers/video/backlight/vgg2432a4.c
++++ b/drivers/video/backlight/vgg2432a4.c
+@@ -256,7 +256,7 @@ static struct spi_driver vgg2432a4_driver = {
+ 		.owner		= THIS_MODULE,
+ 	},
+ 	.probe		= vgg2432a4_probe,
+-	.remove		= __devexit_p(vgg2432a4_remove),
++	.remove		= vgg2432a4_remove,
+ 	.shutdown	= vgg2432a4_shutdown,
+ 	.suspend	= vgg2432a4_suspend,
+ 	.resume		= vgg2432a4_resume,

commit 4b12b896c27c3b54592816606679f5b02f638930
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:24 2012 -0500
+
+    watchdog: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Wim Van Sebroeck 
+    Cc: Wan ZongShun 
+    Cc: Ben Dooks 
+    Cc: Kukjin Kim 
+    Acked-by: Mark Brown 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/watchdog/acquirewdt.c b/drivers/watchdog/acquirewdt.c
+index e009f938e667..24a517777fa0 100644
+--- a/drivers/watchdog/acquirewdt.c
++++ b/drivers/watchdog/acquirewdt.c
+@@ -275,7 +275,7 @@ static int acq_probe(struct platform_device *dev)
+ 	return ret;
+ }
+ 
+-static int __devexit acq_remove(struct platform_device *dev)
++static int acq_remove(struct platform_device *dev)
+ {
+ 	misc_deregister(&acq_miscdev);
+ 	release_region(wdt_start, 1);
+diff --git a/drivers/watchdog/advantechwdt.c b/drivers/watchdog/advantechwdt.c
+index cc50c57a3575..cc6702fc5268 100644
+--- a/drivers/watchdog/advantechwdt.c
++++ b/drivers/watchdog/advantechwdt.c
+@@ -282,7 +282,7 @@ static int advwdt_probe(struct platform_device *dev)
+ 	goto out;
+ }
+ 
+-static int __devexit advwdt_remove(struct platform_device *dev)
++static int advwdt_remove(struct platform_device *dev)
+ {
+ 	misc_deregister(&advwdt_miscdev);
+ 	release_region(wdt_start, 1);
+diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c
+index 154347ec0fc3..3003e2a9580b 100644
+--- a/drivers/watchdog/ar7_wdt.c
++++ b/drivers/watchdog/ar7_wdt.c
+@@ -314,7 +314,7 @@ static int ar7_wdt_probe(struct platform_device *pdev)
+ 	return rc;
+ }
+ 
+-static int __devexit ar7_wdt_remove(struct platform_device *pdev)
++static int ar7_wdt_remove(struct platform_device *pdev)
+ {
+ 	misc_deregister(&ar7_wdt_miscdev);
+ 	clk_put(vbus_clk);
+diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c
+index cc290bbcb39e..89831ed24a4f 100644
+--- a/drivers/watchdog/at91rm9200_wdt.c
++++ b/drivers/watchdog/at91rm9200_wdt.c
+@@ -216,7 +216,7 @@ static int at91wdt_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit at91wdt_remove(struct platform_device *pdev)
++static int at91wdt_remove(struct platform_device *pdev)
+ {
+ 	int res;
+ 
+diff --git a/drivers/watchdog/ath79_wdt.c b/drivers/watchdog/ath79_wdt.c
+index 5c0967d43021..7c8ede7816b1 100644
+--- a/drivers/watchdog/ath79_wdt.c
++++ b/drivers/watchdog/ath79_wdt.c
+@@ -270,7 +270,7 @@ static int ath79_wdt_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit ath79_wdt_remove(struct platform_device *pdev)
++static int ath79_wdt_remove(struct platform_device *pdev)
+ {
+ 	misc_deregister(&ath79_wdt_miscdev);
+ 	clk_disable(wdt_clk);
+diff --git a/drivers/watchdog/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c
+index 5a7cff6e093c..b2b80d4ac818 100644
+--- a/drivers/watchdog/bcm63xx_wdt.c
++++ b/drivers/watchdog/bcm63xx_wdt.c
+@@ -286,7 +286,7 @@ static int bcm63xx_wdt_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit bcm63xx_wdt_remove(struct platform_device *pdev)
++static int bcm63xx_wdt_remove(struct platform_device *pdev)
+ {
+ 	if (!nowayout)
+ 		bcm63xx_wdt_pause();
+diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c
+index 241f8af88d15..5d36d6fb4969 100644
+--- a/drivers/watchdog/bfin_wdt.c
++++ b/drivers/watchdog/bfin_wdt.c
+@@ -379,7 +379,7 @@ static int bfin_wdt_probe(struct platform_device *pdev)
+  *	Unregisters the misc device.  Actual device
+  *	deinitialization is handled by bfin_wdt_close().
+  */
+-static int __devexit bfin_wdt_remove(struct platform_device *pdev)
++static int bfin_wdt_remove(struct platform_device *pdev)
+ {
+ 	misc_deregister(&bfin_wdt_miscdev);
+ 	return 0;
+diff --git a/drivers/watchdog/cpu5wdt.c b/drivers/watchdog/cpu5wdt.c
+index 6eb710b5be76..cd87758abac3 100644
+--- a/drivers/watchdog/cpu5wdt.c
++++ b/drivers/watchdog/cpu5wdt.c
+@@ -261,7 +261,7 @@ static int cpu5wdt_init_module(void)
+ 	return cpu5wdt_init();
+ }
+ 
+-static void __devexit cpu5wdt_exit(void)
++static void cpu5wdt_exit(void)
+ {
+ 	if (cpu5wdt_device.queue) {
+ 		cpu5wdt_device.queue = 0;
+@@ -274,7 +274,7 @@ static void __devexit cpu5wdt_exit(void)
+ 
+ }
+ 
+-static void __devexit cpu5wdt_exit_module(void)
++static void cpu5wdt_exit_module(void)
+ {
+ 	cpu5wdt_exit();
+ }
+diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c
+index 731578b3b440..11d55ce5ca81 100644
+--- a/drivers/watchdog/cpwd.c
++++ b/drivers/watchdog/cpwd.c
+@@ -640,7 +640,7 @@ static int cpwd_probe(struct platform_device *op)
+ 	goto out;
+ }
+ 
+-static int __devexit cpwd_remove(struct platform_device *op)
++static int cpwd_remove(struct platform_device *op)
+ {
+ 	struct cpwd *p = dev_get_drvdata(&op->dev);
+ 	int i;
+diff --git a/drivers/watchdog/da9052_wdt.c b/drivers/watchdog/da9052_wdt.c
+index 93a316570294..8be70d8f2680 100644
+--- a/drivers/watchdog/da9052_wdt.c
++++ b/drivers/watchdog/da9052_wdt.c
+@@ -224,7 +224,7 @@ static int da9052_wdt_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit da9052_wdt_remove(struct platform_device *pdev)
++static int da9052_wdt_remove(struct platform_device *pdev)
+ {
+ 	struct da9052_wdt_data *driver_data = dev_get_drvdata(&pdev->dev);
+ 
+diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c
+index 6fc22d2e5e18..8791879e5181 100644
+--- a/drivers/watchdog/davinci_wdt.c
++++ b/drivers/watchdog/davinci_wdt.c
+@@ -248,7 +248,7 @@ static int davinci_wdt_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit davinci_wdt_remove(struct platform_device *pdev)
++static int davinci_wdt_remove(struct platform_device *pdev)
+ {
+ 	misc_deregister(&davinci_wdt_miscdev);
+ 	if (wdt_mem) {
+diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c
+index 49e24e5ac4ac..a0eba3c40e25 100644
+--- a/drivers/watchdog/dw_wdt.c
++++ b/drivers/watchdog/dw_wdt.c
+@@ -333,7 +333,7 @@ static int dw_wdt_drv_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit dw_wdt_drv_remove(struct platform_device *pdev)
++static int dw_wdt_drv_remove(struct platform_device *pdev)
+ {
+ 	misc_deregister(&dw_wdt_miscdev);
+ 
+diff --git a/drivers/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c
+index f1bd88c5a204..e0574844c313 100644
+--- a/drivers/watchdog/ep93xx_wdt.c
++++ b/drivers/watchdog/ep93xx_wdt.c
+@@ -156,7 +156,7 @@ static int ep93xx_wdt_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit ep93xx_wdt_remove(struct platform_device *pdev)
++static int ep93xx_wdt_remove(struct platform_device *pdev)
+ {
+ 	watchdog_unregister_device(&ep93xx_wdt_wdd);
+ 	return 0;
+diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c
+index 276f0092e6db..b9c5b58e59d3 100644
+--- a/drivers/watchdog/gef_wdt.c
++++ b/drivers/watchdog/gef_wdt.c
+@@ -285,7 +285,7 @@ static int gef_wdt_probe(struct platform_device *dev)
+ 	return misc_register(&gef_wdt_miscdev);
+ }
+ 
+-static int __devexit gef_wdt_remove(struct platform_device *dev)
++static int gef_wdt_remove(struct platform_device *dev)
+ {
+ 	misc_deregister(&gef_wdt_miscdev);
+ 
+diff --git a/drivers/watchdog/geodewdt.c b/drivers/watchdog/geodewdt.c
+index 28a3a8717262..fcd599d4e225 100644
+--- a/drivers/watchdog/geodewdt.c
++++ b/drivers/watchdog/geodewdt.c
+@@ -243,7 +243,7 @@ static int geodewdt_probe(struct platform_device *dev)
+ 	return ret;
+ }
+ 
+-static int __devexit geodewdt_remove(struct platform_device *dev)
++static int geodewdt_remove(struct platform_device *dev)
+ {
+ 	misc_deregister(&geodewdt_miscdev);
+ 	return 0;
+diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
+index cc25ddfa84eb..8717255ec7be 100644
+--- a/drivers/watchdog/hpwdt.c
++++ b/drivers/watchdog/hpwdt.c
+@@ -848,7 +848,7 @@ static int hpwdt_init_one(struct pci_dev *dev,
+ 	return retval;
+ }
+ 
+-static void __devexit hpwdt_exit(struct pci_dev *dev)
++static void hpwdt_exit(struct pci_dev *dev)
+ {
+ 	if (!nowayout)
+ 		hpwdt_stop();
+diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c
+index 31b87db90261..2b2ea13d03ea 100644
+--- a/drivers/watchdog/i6300esb.c
++++ b/drivers/watchdog/i6300esb.c
+@@ -465,7 +465,7 @@ static int esb_probe(struct pci_dev *pdev,
+ 	return ret;
+ }
+ 
+-static void __devexit esb_remove(struct pci_dev *pdev)
++static void esb_remove(struct pci_dev *pdev)
+ {
+ 	/* Stop the timer before we leave */
+ 	if (!nowayout)
+diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
+index fb341df65614..6130321da387 100644
+--- a/drivers/watchdog/iTCO_wdt.c
++++ b/drivers/watchdog/iTCO_wdt.c
+@@ -364,7 +364,7 @@ static struct watchdog_device iTCO_wdt_watchdog_dev = {
+  *	Init & exit routines
+  */
+ 
+-static void __devexit iTCO_wdt_cleanup(void)
++static void iTCO_wdt_cleanup(void)
+ {
+ 	/* Stop the timer before we leave */
+ 	if (!nowayout)
+@@ -533,7 +533,7 @@ static int iTCO_wdt_probe(struct platform_device *dev)
+ 	return ret;
+ }
+ 
+-static int __devexit iTCO_wdt_remove(struct platform_device *dev)
++static int iTCO_wdt_remove(struct platform_device *dev)
+ {
+ 	if (iTCO_wdt_private.tco_res || iTCO_wdt_private.smi_res)
+ 		iTCO_wdt_cleanup();
+diff --git a/drivers/watchdog/ib700wdt.c b/drivers/watchdog/ib700wdt.c
+index 5249596db2ab..eb6b5cc98ec6 100644
+--- a/drivers/watchdog/ib700wdt.c
++++ b/drivers/watchdog/ib700wdt.c
+@@ -319,7 +319,7 @@ static int ibwdt_probe(struct platform_device *dev)
+ 	return res;
+ }
+ 
+-static int __devexit ibwdt_remove(struct platform_device *dev)
++static int ibwdt_remove(struct platform_device *dev)
+ {
+ 	misc_deregister(&ibwdt_miscdev);
+ 	release_region(WDT_START, 1);
+diff --git a/drivers/watchdog/ie6xx_wdt.c b/drivers/watchdog/ie6xx_wdt.c
+index 94eef6fec0f3..e24ef6a6e064 100644
+--- a/drivers/watchdog/ie6xx_wdt.c
++++ b/drivers/watchdog/ie6xx_wdt.c
+@@ -295,7 +295,7 @@ static int ie6xx_wdt_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit ie6xx_wdt_remove(struct platform_device *pdev)
++static int ie6xx_wdt_remove(struct platform_device *pdev)
+ {
+ 	struct resource *res;
+ 
+diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c
+index eb7008a1d6e6..a61408fa0c94 100644
+--- a/drivers/watchdog/jz4740_wdt.c
++++ b/drivers/watchdog/jz4740_wdt.c
+@@ -197,7 +197,7 @@ static int jz4740_wdt_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit jz4740_wdt_remove(struct platform_device *pdev)
++static int jz4740_wdt_remove(struct platform_device *pdev)
+ {
+ 	struct jz4740_wdt_drvdata *drvdata = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/watchdog/ks8695_wdt.c b/drivers/watchdog/ks8695_wdt.c
+index c305adb49fbf..dce9ecffd44a 100644
+--- a/drivers/watchdog/ks8695_wdt.c
++++ b/drivers/watchdog/ks8695_wdt.c
+@@ -252,7 +252,7 @@ static int ks8695wdt_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit ks8695wdt_remove(struct platform_device *pdev)
++static int ks8695wdt_remove(struct platform_device *pdev)
+ {
+ 	int res;
+ 
+diff --git a/drivers/watchdog/lantiq_wdt.c b/drivers/watchdog/lantiq_wdt.c
+index fd9f43c48d47..79fe01b42339 100644
+--- a/drivers/watchdog/lantiq_wdt.c
++++ b/drivers/watchdog/lantiq_wdt.c
+@@ -220,7 +220,7 @@ ltq_wdt_probe(struct platform_device *pdev)
+ 	return misc_register(<q_wdt_miscdev);
+ }
+ 
+-static int __devexit
++static int
+ ltq_wdt_remove(struct platform_device *pdev)
+ {
+ 	misc_deregister(<q_wdt_miscdev);
+diff --git a/drivers/watchdog/max63xx_wdt.c b/drivers/watchdog/max63xx_wdt.c
+index b572c751ebf5..773c661723ca 100644
+--- a/drivers/watchdog/max63xx_wdt.c
++++ b/drivers/watchdog/max63xx_wdt.c
+@@ -209,7 +209,7 @@ static int max63xx_wdt_probe(struct platform_device *pdev)
+ 	return watchdog_register_device(&max63xx_wdt_dev);
+ }
+ 
+-static int __devexit max63xx_wdt_remove(struct platform_device *pdev)
++static int max63xx_wdt_remove(struct platform_device *pdev)
+ {
+ 	watchdog_unregister_device(&max63xx_wdt_dev);
+ 	return 0;
+diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c
+index 5c23a6bac944..da2752063bb7 100644
+--- a/drivers/watchdog/mpc8xxx_wdt.c
++++ b/drivers/watchdog/mpc8xxx_wdt.c
+@@ -245,7 +245,7 @@ static int mpc8xxx_wdt_probe(struct platform_device *ofdev)
+ 	return ret;
+ }
+ 
+-static int __devexit mpc8xxx_wdt_remove(struct platform_device *ofdev)
++static int mpc8xxx_wdt_remove(struct platform_device *ofdev)
+ {
+ 	mpc8xxx_wdt_pr_warn("watchdog removed");
+ 	del_timer_sync(&wdt_timer);
+diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c
+index 4f90ac5910af..a84eb551ea27 100644
+--- a/drivers/watchdog/mpcore_wdt.c
++++ b/drivers/watchdog/mpcore_wdt.c
+@@ -378,7 +378,7 @@ static int mpcore_wdt_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit mpcore_wdt_remove(struct platform_device *pdev)
++static int mpcore_wdt_remove(struct platform_device *pdev)
+ {
+ 	platform_set_drvdata(pdev, NULL);
+ 
+diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c
+index 8c642763ca6e..14dab6ff87aa 100644
+--- a/drivers/watchdog/mtx-1_wdt.c
++++ b/drivers/watchdog/mtx-1_wdt.c
+@@ -233,7 +233,7 @@ static int mtx1_wdt_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit mtx1_wdt_remove(struct platform_device *pdev)
++static int mtx1_wdt_remove(struct platform_device *pdev)
+ {
+ 	/* FIXME: do we need to lock this test ? */
+ 	if (mtx1_wdt_device.queue) {
+diff --git a/drivers/watchdog/mv64x60_wdt.c b/drivers/watchdog/mv64x60_wdt.c
+index 2876027a8886..c7fb878ca493 100644
+--- a/drivers/watchdog/mv64x60_wdt.c
++++ b/drivers/watchdog/mv64x60_wdt.c
+@@ -287,7 +287,7 @@ static int mv64x60_wdt_probe(struct platform_device *dev)
+ 	return misc_register(&mv64x60_wdt_miscdev);
+ }
+ 
+-static int __devexit mv64x60_wdt_remove(struct platform_device *dev)
++static int mv64x60_wdt_remove(struct platform_device *dev)
+ {
+ 	misc_deregister(&mv64x60_wdt_miscdev);
+ 
+diff --git a/drivers/watchdog/nuc900_wdt.c b/drivers/watchdog/nuc900_wdt.c
+index d05daefa8640..04c45a102992 100644
+--- a/drivers/watchdog/nuc900_wdt.c
++++ b/drivers/watchdog/nuc900_wdt.c
+@@ -309,7 +309,7 @@ static int nuc900wdt_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit nuc900wdt_remove(struct platform_device *pdev)
++static int nuc900wdt_remove(struct platform_device *pdev)
+ {
+ 	misc_deregister(&nuc900wdt_miscdev);
+ 
+diff --git a/drivers/watchdog/nv_tco.c b/drivers/watchdog/nv_tco.c
+index 45452845faca..59cf19eeea07 100644
+--- a/drivers/watchdog/nv_tco.c
++++ b/drivers/watchdog/nv_tco.c
+@@ -423,7 +423,7 @@ static int nv_tco_init(struct platform_device *dev)
+ 	return ret;
+ }
+ 
+-static void __devexit nv_tco_cleanup(void)
++static void nv_tco_cleanup(void)
+ {
+ 	u32 val;
+ 
+@@ -445,7 +445,7 @@ static void __devexit nv_tco_cleanup(void)
+ 	release_region(tcobase, 0x10);
+ }
+ 
+-static int __devexit nv_tco_remove(struct platform_device *dev)
++static int nv_tco_remove(struct platform_device *dev)
+ {
+ 	if (tcobase)
+ 		nv_tco_cleanup();
+diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c
+index 3ddc4e93906f..2761ddb08501 100644
+--- a/drivers/watchdog/of_xilinx_wdt.c
++++ b/drivers/watchdog/of_xilinx_wdt.c
+@@ -383,7 +383,7 @@ static int xwdt_probe(struct platform_device *pdev)
+ 	return rc;
+ }
+ 
+-static int __devexit xwdt_remove(struct platform_device *dev)
++static int xwdt_remove(struct platform_device *dev)
+ {
+ 	misc_deregister(&xwdt_miscdev);
+ 	iounmap(xdev.base);
+diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
+index 36a724614383..d8da5162f0dd 100644
+--- a/drivers/watchdog/omap_wdt.c
++++ b/drivers/watchdog/omap_wdt.c
+@@ -359,7 +359,7 @@ static void omap_wdt_shutdown(struct platform_device *pdev)
+ 	}
+ }
+ 
+-static int __devexit omap_wdt_remove(struct platform_device *pdev)
++static int omap_wdt_remove(struct platform_device *pdev)
+ {
+ 	struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
+ 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
+index f722635f3ecc..0478b001b1ef 100644
+--- a/drivers/watchdog/orion_wdt.c
++++ b/drivers/watchdog/orion_wdt.c
+@@ -181,7 +181,7 @@ static int orion_wdt_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit orion_wdt_remove(struct platform_device *pdev)
++static int orion_wdt_remove(struct platform_device *pdev)
+ {
+ 	watchdog_unregister_device(&orion_wdt);
+ 	clk_disable_unprepare(clk);
+diff --git a/drivers/watchdog/pcwd.c b/drivers/watchdog/pcwd.c
+index cef246abdd66..33e49a7f889f 100644
+--- a/drivers/watchdog/pcwd.c
++++ b/drivers/watchdog/pcwd.c
+@@ -949,7 +949,7 @@ static int pcwd_isa_probe(struct device *dev, unsigned int id)
+ 	return ret;
+ }
+ 
+-static int __devexit pcwd_isa_remove(struct device *dev, unsigned int id)
++static int pcwd_isa_remove(struct device *dev, unsigned int id)
+ {
+ 	if (debug >= DEBUG)
+ 		pr_debug("pcwd_isa_remove id=%d\n", id);
+diff --git a/drivers/watchdog/pcwd_pci.c b/drivers/watchdog/pcwd_pci.c
+index 6ec84b5bb508..7890f84edf76 100644
+--- a/drivers/watchdog/pcwd_pci.c
++++ b/drivers/watchdog/pcwd_pci.c
+@@ -785,7 +785,7 @@ static int pcipcwd_card_init(struct pci_dev *pdev,
+ 	return ret;
+ }
+ 
+-static void __devexit pcipcwd_card_exit(struct pci_dev *pdev)
++static void pcipcwd_card_exit(struct pci_dev *pdev)
+ {
+ 	/* Stop the timer before we leave */
+ 	if (!nowayout)
+diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c
+index 4f7afeab6698..dcba5dab6c29 100644
+--- a/drivers/watchdog/pnx4008_wdt.c
++++ b/drivers/watchdog/pnx4008_wdt.c
+@@ -192,7 +192,7 @@ static int pnx4008_wdt_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit pnx4008_wdt_remove(struct platform_device *pdev)
++static int pnx4008_wdt_remove(struct platform_device *pdev)
+ {
+ 	watchdog_unregister_device(&pnx4008_wdd);
+ 
+diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c
+index 22662808c37d..f78bc008cbb7 100644
+--- a/drivers/watchdog/rc32434_wdt.c
++++ b/drivers/watchdog/rc32434_wdt.c
+@@ -306,7 +306,7 @@ static int rc32434_wdt_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit rc32434_wdt_remove(struct platform_device *pdev)
++static int rc32434_wdt_remove(struct platform_device *pdev)
+ {
+ 	misc_deregister(&rc32434_wdt_miscdev);
+ 	iounmap(wdt_reg);
+diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c
+index 94667064c8cf..b0f116c2fd53 100644
+--- a/drivers/watchdog/rdc321x_wdt.c
++++ b/drivers/watchdog/rdc321x_wdt.c
+@@ -272,7 +272,7 @@ static int rdc321x_wdt_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit rdc321x_wdt_remove(struct platform_device *pdev)
++static int rdc321x_wdt_remove(struct platform_device *pdev)
+ {
+ 	if (rdc321x_wdt_device.queue) {
+ 		rdc321x_wdt_device.queue = 0;
+diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c
+index 84f523338ff4..0040451aec1d 100644
+--- a/drivers/watchdog/riowd.c
++++ b/drivers/watchdog/riowd.c
+@@ -220,7 +220,7 @@ static int riowd_probe(struct platform_device *op)
+ 	return err;
+ }
+ 
+-static int __devexit riowd_remove(struct platform_device *op)
++static int riowd_remove(struct platform_device *op)
+ {
+ 	struct riowd *p = dev_get_drvdata(&op->dev);
+ 
+diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
+index 2e28c145081c..b0dab10fc6a5 100644
+--- a/drivers/watchdog/s3c2410_wdt.c
++++ b/drivers/watchdog/s3c2410_wdt.c
+@@ -437,7 +437,7 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit s3c2410wdt_remove(struct platform_device *dev)
++static int s3c2410wdt_remove(struct platform_device *dev)
+ {
+ 	watchdog_unregister_device(&s3c2410_wdd);
+ 
+diff --git a/drivers/watchdog/sch311x_wdt.c b/drivers/watchdog/sch311x_wdt.c
+index 8ecec2919797..af7b136b1874 100644
+--- a/drivers/watchdog/sch311x_wdt.c
++++ b/drivers/watchdog/sch311x_wdt.c
+@@ -429,7 +429,7 @@ static int sch311x_wdt_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit sch311x_wdt_remove(struct platform_device *pdev)
++static int sch311x_wdt_remove(struct platform_device *pdev)
+ {
+ 	/* Stop the timer before we leave */
+ 	if (!nowayout)
+diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c
+index 9c57af943b87..6a89e4045fbd 100644
+--- a/drivers/watchdog/shwdt.c
++++ b/drivers/watchdog/shwdt.c
+@@ -298,7 +298,7 @@ static int sh_wdt_probe(struct platform_device *pdev)
+ 	return rc;
+ }
+ 
+-static int __devexit sh_wdt_remove(struct platform_device *pdev)
++static int sh_wdt_remove(struct platform_device *pdev)
+ {
+ 	struct sh_wdt *wdt = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c
+index 7ee39a79ff1e..b3876812ff07 100644
+--- a/drivers/watchdog/sp5100_tco.c
++++ b/drivers/watchdog/sp5100_tco.c
+@@ -412,7 +412,7 @@ static int sp5100_tco_init(struct platform_device *dev)
+ 	return ret;
+ }
+ 
+-static void __devexit sp5100_tco_cleanup(void)
++static void sp5100_tco_cleanup(void)
+ {
+ 	/* Stop the timer before we leave */
+ 	if (!nowayout)
+@@ -425,7 +425,7 @@ static void __devexit sp5100_tco_cleanup(void)
+ 	release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
+ }
+ 
+-static int __devexit sp5100_tco_remove(struct platform_device *dev)
++static int sp5100_tco_remove(struct platform_device *dev)
+ {
+ 	if (tcobase)
+ 		sp5100_tco_cleanup();
+diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c
+index 32a5419657d2..4552847fc7fe 100644
+--- a/drivers/watchdog/sp805_wdt.c
++++ b/drivers/watchdog/sp805_wdt.c
+@@ -272,7 +272,7 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
+ 	return ret;
+ }
+ 
+-static int __devexit sp805_wdt_remove(struct amba_device *adev)
++static int sp805_wdt_remove(struct amba_device *adev)
+ {
+ 	struct sp805_wdt *wdt = amba_get_drvdata(adev);
+ 
+diff --git a/drivers/watchdog/stmp3xxx_wdt.c b/drivers/watchdog/stmp3xxx_wdt.c
+index 254cce38cc03..1f4f69728fee 100644
+--- a/drivers/watchdog/stmp3xxx_wdt.c
++++ b/drivers/watchdog/stmp3xxx_wdt.c
+@@ -229,7 +229,7 @@ static int stmp3xxx_wdt_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit stmp3xxx_wdt_remove(struct platform_device *pdev)
++static int stmp3xxx_wdt_remove(struct platform_device *pdev)
+ {
+ 	misc_deregister(&stmp3xxx_wdt_miscdev);
+ 	return 0;
+diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c
+index d6e94b4c67f6..b8a92459f10f 100644
+--- a/drivers/watchdog/ts72xx_wdt.c
++++ b/drivers/watchdog/ts72xx_wdt.c
+@@ -476,7 +476,7 @@ static int ts72xx_wdt_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static __devexit int ts72xx_wdt_remove(struct platform_device *pdev)
++static int ts72xx_wdt_remove(struct platform_device *pdev)
+ {
+ 	struct ts72xx_wdt *wdt = platform_get_drvdata(pdev);
+ 	struct resource *res;
+diff --git a/drivers/watchdog/twl4030_wdt.c b/drivers/watchdog/twl4030_wdt.c
+index 6dab509caf94..9f54b1da7185 100644
+--- a/drivers/watchdog/twl4030_wdt.c
++++ b/drivers/watchdog/twl4030_wdt.c
+@@ -204,7 +204,7 @@ static int twl4030_wdt_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit twl4030_wdt_remove(struct platform_device *pdev)
++static int twl4030_wdt_remove(struct platform_device *pdev)
+ {
+ 	struct twl4030_wdt *wdt = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/watchdog/via_wdt.c b/drivers/watchdog/via_wdt.c
+index 098dfab82b6c..1a68f760cf86 100644
+--- a/drivers/watchdog/via_wdt.c
++++ b/drivers/watchdog/via_wdt.c
+@@ -229,7 +229,7 @@ static int wdt_probe(struct pci_dev *pdev,
+ 	return ret;
+ }
+ 
+-static void __devexit wdt_remove(struct pci_dev *pdev)
++static void wdt_remove(struct pci_dev *pdev)
+ {
+ 	watchdog_unregister_device(&wdt_dev);
+ 	del_timer(&timer);
+diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c
+index 13d27c878db4..36a54c0e32dd 100644
+--- a/drivers/watchdog/wdt_pci.c
++++ b/drivers/watchdog/wdt_pci.c
+@@ -705,7 +705,7 @@ static int wdtpci_init_one(struct pci_dev *dev,
+ }
+ 
+ 
+-static void __devexit wdtpci_remove_one(struct pci_dev *pdev)
++static void wdtpci_remove_one(struct pci_dev *pdev)
+ {
+ 	/* here we assume only one device will ever have
+ 	 * been picked up and registered by probe function */
+diff --git a/drivers/watchdog/wm831x_wdt.c b/drivers/watchdog/wm831x_wdt.c
+index 170c82e97454..9dcb6d082277 100644
+--- a/drivers/watchdog/wm831x_wdt.c
++++ b/drivers/watchdog/wm831x_wdt.c
+@@ -292,7 +292,7 @@ static int wm831x_wdt_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit wm831x_wdt_remove(struct platform_device *pdev)
++static int wm831x_wdt_remove(struct platform_device *pdev)
+ {
+ 	struct wm831x_wdt_drvdata *driver_data = dev_get_drvdata(&pdev->dev);
+ 
+diff --git a/drivers/watchdog/wm8350_wdt.c b/drivers/watchdog/wm8350_wdt.c
+index 4530fa00b78d..34d272ada23d 100644
+--- a/drivers/watchdog/wm8350_wdt.c
++++ b/drivers/watchdog/wm8350_wdt.c
+@@ -158,7 +158,7 @@ static int wm8350_wdt_probe(struct platform_device *pdev)
+ 	return watchdog_register_device(&wm8350_wdt);
+ }
+ 
+-static int __devexit wm8350_wdt_remove(struct platform_device *pdev)
++static int wm8350_wdt_remove(struct platform_device *pdev)
+ {
+ 	watchdog_unregister_device(&wm8350_wdt);
+ 	return 0;
+diff --git a/drivers/watchdog/xen_wdt.c b/drivers/watchdog/xen_wdt.c
+index 1eb6bdc020ac..92ad33d0cb71 100644
+--- a/drivers/watchdog/xen_wdt.c
++++ b/drivers/watchdog/xen_wdt.c
+@@ -280,7 +280,7 @@ static int xen_wdt_probe(struct platform_device *dev)
+ 	return ret;
+ }
+ 
+-static int __devexit xen_wdt_remove(struct platform_device *dev)
++static int xen_wdt_remove(struct platform_device *dev)
+ {
+ 	/* Stop the timer before we leave */
+ 	if (!nowayout)

commit 1d1313686422db3bffb2e7bd8eb2ccd9027d3783
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:24:05 2012 -0500
+
+    watchdog: remove use of __devinitdata
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitdata is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Wim Van Sebroeck 
+    Cc: Grant Likely 
+    Cc: Rob Herring 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/watchdog/mixcomwd.c b/drivers/watchdog/mixcomwd.c
+index 37e4b52dbce9..97d62ee50341 100644
+--- a/drivers/watchdog/mixcomwd.c
++++ b/drivers/watchdog/mixcomwd.c
+@@ -73,7 +73,7 @@
+ static struct {
+ 	int ioport;
+ 	int id;
+-} mixcomwd_io_info[] __devinitdata = {
++} mixcomwd_io_info[] = {
+ 	/* The Mixcom cards */
+ 	{0x0d90, MIXCOM_ID},
+ 	{0x0e90, MIXCOM_ID},
+diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c
+index fd3e5f6ee55c..3ddc4e93906f 100644
+--- a/drivers/watchdog/of_xilinx_wdt.c
++++ b/drivers/watchdog/of_xilinx_wdt.c
+@@ -393,7 +393,7 @@ static int __devexit xwdt_remove(struct platform_device *dev)
+ }
+ 
+ /* Match table for of_platform binding */
+-static struct of_device_id __devinitdata xwdt_of_match[] = {
++static struct of_device_id xwdt_of_match[] = {
+ 	{ .compatible = "xlnx,xps-timebase-wdt-1.01.a", },
+ 	{},
+ };
+diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
+index e6b7bd2117c6..f722635f3ecc 100644
+--- a/drivers/watchdog/orion_wdt.c
++++ b/drivers/watchdog/orion_wdt.c
+@@ -193,7 +193,7 @@ static void orion_wdt_shutdown(struct platform_device *pdev)
+ 	orion_wdt_stop(&orion_wdt);
+ }
+ 
+-static const struct of_device_id orion_wdt_of_match_table[] __devinitdata = {
++static const struct of_device_id orion_wdt_of_match_table[] = {
+ 	{ .compatible = "marvell,orion-wdt", },
+ 	{},
+ };

commit 2d991a164a61858012651e13c59521975504e260
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:41 2012 -0500
+
+    watchdog: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Wim Van Sebroeck 
+    Cc: Wan ZongShun 
+    Cc: Ben Dooks 
+    Cc: Kukjin Kim 
+    Acked-by: Mark Brown 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/watchdog/acquirewdt.c b/drivers/watchdog/acquirewdt.c
+index 49e0b89ceed9..e009f938e667 100644
+--- a/drivers/watchdog/acquirewdt.c
++++ b/drivers/watchdog/acquirewdt.c
+@@ -240,7 +240,7 @@ static struct miscdevice acq_miscdev = {
+  *	Init & exit routines
+  */
+ 
+-static int __devinit acq_probe(struct platform_device *dev)
++static int acq_probe(struct platform_device *dev)
+ {
+ 	int ret;
+ 
+diff --git a/drivers/watchdog/advantechwdt.c b/drivers/watchdog/advantechwdt.c
+index 9a74156f05ee..cc50c57a3575 100644
+--- a/drivers/watchdog/advantechwdt.c
++++ b/drivers/watchdog/advantechwdt.c
+@@ -238,7 +238,7 @@ static struct miscdevice advwdt_miscdev = {
+  *	Init & exit routines
+  */
+ 
+-static int __devinit advwdt_probe(struct platform_device *dev)
++static int advwdt_probe(struct platform_device *dev)
+ {
+ 	int ret;
+ 
+diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c
+index eb633d9951a2..154347ec0fc3 100644
+--- a/drivers/watchdog/ar7_wdt.c
++++ b/drivers/watchdog/ar7_wdt.c
+@@ -274,7 +274,7 @@ static struct miscdevice ar7_wdt_miscdev = {
+ 	.fops		= &ar7_wdt_fops,
+ };
+ 
+-static int __devinit ar7_wdt_probe(struct platform_device *pdev)
++static int ar7_wdt_probe(struct platform_device *pdev)
+ {
+ 	int rc;
+ 
+diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c
+index 75f3a6bc323b..cc290bbcb39e 100644
+--- a/drivers/watchdog/at91rm9200_wdt.c
++++ b/drivers/watchdog/at91rm9200_wdt.c
+@@ -199,7 +199,7 @@ static struct miscdevice at91wdt_miscdev = {
+ 	.fops		= &at91wdt_fops,
+ };
+ 
+-static int __devinit at91wdt_probe(struct platform_device *pdev)
++static int at91wdt_probe(struct platform_device *pdev)
+ {
+ 	int res;
+ 
+diff --git a/drivers/watchdog/ath79_wdt.c b/drivers/watchdog/ath79_wdt.c
+index 367ef5ed19b7..5c0967d43021 100644
+--- a/drivers/watchdog/ath79_wdt.c
++++ b/drivers/watchdog/ath79_wdt.c
+@@ -224,7 +224,7 @@ static struct miscdevice ath79_wdt_miscdev = {
+ 	.fops = &ath79_wdt_fops,
+ };
+ 
+-static int __devinit ath79_wdt_probe(struct platform_device *pdev)
++static int ath79_wdt_probe(struct platform_device *pdev)
+ {
+ 	u32 ctrl;
+ 	int err;
+diff --git a/drivers/watchdog/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c
+index e81b78444fa9..5a7cff6e093c 100644
+--- a/drivers/watchdog/bcm63xx_wdt.c
++++ b/drivers/watchdog/bcm63xx_wdt.c
+@@ -236,7 +236,7 @@ static struct miscdevice bcm63xx_wdt_miscdev = {
+ };
+ 
+ 
+-static int __devinit bcm63xx_wdt_probe(struct platform_device *pdev)
++static int bcm63xx_wdt_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 	struct resource *r;
+diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c
+index 4a85dbf5aec0..241f8af88d15 100644
+--- a/drivers/watchdog/bfin_wdt.c
++++ b/drivers/watchdog/bfin_wdt.c
+@@ -356,7 +356,7 @@ static const struct watchdog_info bfin_wdt_info = {
+  *	Registers the misc device.  Actual device
+  *	initialization is handled by bfin_wdt_open().
+  */
+-static int __devinit bfin_wdt_probe(struct platform_device *pdev)
++static int bfin_wdt_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 
+diff --git a/drivers/watchdog/cpu5wdt.c b/drivers/watchdog/cpu5wdt.c
+index 7e888393de1f..6eb710b5be76 100644
+--- a/drivers/watchdog/cpu5wdt.c
++++ b/drivers/watchdog/cpu5wdt.c
+@@ -215,7 +215,7 @@ static struct miscdevice cpu5wdt_misc = {
+ 
+ /* init/exit function */
+ 
+-static int __devinit cpu5wdt_init(void)
++static int cpu5wdt_init(void)
+ {
+ 	unsigned int val;
+ 	int err;
+@@ -256,7 +256,7 @@ static int __devinit cpu5wdt_init(void)
+ 	return err;
+ }
+ 
+-static int __devinit cpu5wdt_init_module(void)
++static int cpu5wdt_init_module(void)
+ {
+ 	return cpu5wdt_init();
+ }
+diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c
+index ed7f434bba79..731578b3b440 100644
+--- a/drivers/watchdog/cpwd.c
++++ b/drivers/watchdog/cpwd.c
+@@ -528,7 +528,7 @@ static const struct file_operations cpwd_fops = {
+ 	.llseek =		no_llseek,
+ };
+ 
+-static int __devinit cpwd_probe(struct platform_device *op)
++static int cpwd_probe(struct platform_device *op)
+ {
+ 	struct device_node *options;
+ 	const char *str_prop;
+diff --git a/drivers/watchdog/da9052_wdt.c b/drivers/watchdog/da9052_wdt.c
+index 463e9e55b560..93a316570294 100644
+--- a/drivers/watchdog/da9052_wdt.c
++++ b/drivers/watchdog/da9052_wdt.c
+@@ -179,7 +179,7 @@ static const struct watchdog_ops da9052_wdt_ops = {
+ };
+ 
+ 
+-static int __devinit da9052_wdt_probe(struct platform_device *pdev)
++static int da9052_wdt_probe(struct platform_device *pdev)
+ {
+ 	struct da9052 *da9052 = dev_get_drvdata(pdev->dev.parent);
+ 	struct da9052_wdt_data *driver_data;
+diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c
+index ea4e96259a82..6fc22d2e5e18 100644
+--- a/drivers/watchdog/davinci_wdt.c
++++ b/drivers/watchdog/davinci_wdt.c
+@@ -199,7 +199,7 @@ static struct miscdevice davinci_wdt_miscdev = {
+ 	.fops = &davinci_wdt_fops,
+ };
+ 
+-static int __devinit davinci_wdt_probe(struct platform_device *pdev)
++static int davinci_wdt_probe(struct platform_device *pdev)
+ {
+ 	int ret = 0, size;
+ 	struct device *dev = &pdev->dev;
+diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c
+index 6a8448dcc20e..49e24e5ac4ac 100644
+--- a/drivers/watchdog/dw_wdt.c
++++ b/drivers/watchdog/dw_wdt.c
+@@ -293,7 +293,7 @@ static struct miscdevice dw_wdt_miscdev = {
+ 	.minor		= WATCHDOG_MINOR,
+ };
+ 
+-static int __devinit dw_wdt_drv_probe(struct platform_device *pdev)
++static int dw_wdt_drv_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 	struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+diff --git a/drivers/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c
+index 91703a58145d..f1bd88c5a204 100644
+--- a/drivers/watchdog/ep93xx_wdt.c
++++ b/drivers/watchdog/ep93xx_wdt.c
+@@ -112,7 +112,7 @@ static struct watchdog_device ep93xx_wdt_wdd = {
+ 	.ops		= &ep93xx_wdt_ops,
+ };
+ 
+-static int __devinit ep93xx_wdt_probe(struct platform_device *pdev)
++static int ep93xx_wdt_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res;
+ 	unsigned long val;
+diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c
+index 17f4cae770c6..276f0092e6db 100644
+--- a/drivers/watchdog/gef_wdt.c
++++ b/drivers/watchdog/gef_wdt.c
+@@ -262,7 +262,7 @@ static struct miscdevice gef_wdt_miscdev = {
+ };
+ 
+ 
+-static int __devinit gef_wdt_probe(struct platform_device *dev)
++static int gef_wdt_probe(struct platform_device *dev)
+ {
+ 	int timeout = 10;
+ 	u32 freq;
+diff --git a/drivers/watchdog/geodewdt.c b/drivers/watchdog/geodewdt.c
+index a340e04f2379..28a3a8717262 100644
+--- a/drivers/watchdog/geodewdt.c
++++ b/drivers/watchdog/geodewdt.c
+@@ -215,7 +215,7 @@ static struct miscdevice geodewdt_miscdev = {
+ 	.fops = &geodewdt_fops,
+ };
+ 
+-static int __devinit geodewdt_probe(struct platform_device *dev)
++static int geodewdt_probe(struct platform_device *dev)
+ {
+ 	int ret;
+ 
+diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
+index 03687bcc74f2..cc25ddfa84eb 100644
+--- a/drivers/watchdog/hpwdt.c
++++ b/drivers/watchdog/hpwdt.c
+@@ -212,7 +212,7 @@ asm(".text                          \n\t"
+  *	0        :  SUCCESS
+  *	<0       :  FAILURE
+  */
+-static int __devinit cru_detect(unsigned long map_entry,
++static int cru_detect(unsigned long map_entry,
+ 	unsigned long map_offset)
+ {
+ 	void *bios32_map;
+@@ -268,7 +268,7 @@ static int __devinit cru_detect(unsigned long map_entry,
+ /*
+  *	bios_checksum
+  */
+-static int __devinit bios_checksum(const char __iomem *ptr, int len)
++static int bios_checksum(const char __iomem *ptr, int len)
+ {
+ 	char sum = 0;
+ 	int i;
+@@ -293,7 +293,7 @@ static int __devinit bios_checksum(const char __iomem *ptr, int len)
+  *	0        :  SUCCESS
+  *	<0       :  FAILURE
+  */
+-static int __devinit bios32_present(const char __iomem *p)
++static int bios32_present(const char __iomem *p)
+ {
+ 	struct bios32_service_dir *bios_32_ptr;
+ 	int length;
+@@ -323,7 +323,7 @@ static int __devinit bios32_present(const char __iomem *p)
+ 	return -ENODEV;
+ }
+ 
+-static int __devinit detect_cru_service(void)
++static int detect_cru_service(void)
+ {
+ 	char __iomem *p, *q;
+ 	int rc = -1;
+@@ -395,7 +395,7 @@ asm(".text                      \n\t"
+  *	This function checks whether or not a SMBIOS/DMI record is
+  *	the 64bit CRU info or not
+  */
+-static void __devinit dmi_find_cru(const struct dmi_header *dm, void *dummy)
++static void dmi_find_cru(const struct dmi_header *dm, void *dummy)
+ {
+ 	struct smbios_cru64_info *smbios_cru64_ptr;
+ 	unsigned long cru_physical_address;
+@@ -414,7 +414,7 @@ static void __devinit dmi_find_cru(const struct dmi_header *dm, void *dummy)
+ 	}
+ }
+ 
+-static int __devinit detect_cru_service(void)
++static int detect_cru_service(void)
+ {
+ 	cru_rom_addr = NULL;
+ 
+@@ -647,7 +647,7 @@ static struct miscdevice hpwdt_miscdev = {
+ 
+ #ifdef CONFIG_HPWDT_NMI_DECODING
+ #ifdef CONFIG_X86_LOCAL_APIC
+-static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
++static void hpwdt_check_nmi_decoding(struct pci_dev *dev)
+ {
+ 	/*
+ 	 * If nmi_watchdog is turned off then we can turn on
+@@ -656,7 +656,7 @@ static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
+ 	hpwdt_nmi_decoding = 1;
+ }
+ #else
+-static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
++static void hpwdt_check_nmi_decoding(struct pci_dev *dev)
+ {
+ 	dev_warn(&dev->dev, "NMI decoding is disabled. "
+ 		"Your kernel does not support a NMI Watchdog.\n");
+@@ -671,7 +671,7 @@ static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
+  *	This check is independent of architecture and needs to be made for
+  *	any ProLiant system.
+  */
+-static void __devinit dmi_find_icru(const struct dmi_header *dm, void *dummy)
++static void dmi_find_icru(const struct dmi_header *dm, void *dummy)
+ {
+ 	struct smbios_proliant_info *smbios_proliant_ptr;
+ 
+@@ -682,7 +682,7 @@ static void __devinit dmi_find_icru(const struct dmi_header *dm, void *dummy)
+ 	}
+ }
+ 
+-static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev)
++static int hpwdt_init_nmi_decoding(struct pci_dev *dev)
+ {
+ 	int retval;
+ 
+@@ -762,11 +762,11 @@ static void hpwdt_exit_nmi_decoding(void)
+ 		iounmap(cru_rom_addr);
+ }
+ #else /* !CONFIG_HPWDT_NMI_DECODING */
+-static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
++static void hpwdt_check_nmi_decoding(struct pci_dev *dev)
+ {
+ }
+ 
+-static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev)
++static int hpwdt_init_nmi_decoding(struct pci_dev *dev)
+ {
+ 	return 0;
+ }
+@@ -776,7 +776,7 @@ static void hpwdt_exit_nmi_decoding(void)
+ }
+ #endif /* CONFIG_HPWDT_NMI_DECODING */
+ 
+-static int __devinit hpwdt_init_one(struct pci_dev *dev,
++static int hpwdt_init_one(struct pci_dev *dev,
+ 					const struct pci_device_id *ent)
+ {
+ 	int retval;
+diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c
+index 2574066c6343..31b87db90261 100644
+--- a/drivers/watchdog/i6300esb.c
++++ b/drivers/watchdog/i6300esb.c
+@@ -344,7 +344,7 @@ MODULE_DEVICE_TABLE(pci, esb_pci_tbl);
+  *      Init & exit routines
+  */
+ 
+-static unsigned char __devinit esb_getdevice(struct pci_dev *pdev)
++static unsigned char esb_getdevice(struct pci_dev *pdev)
+ {
+ 	if (pci_enable_device(pdev)) {
+ 		pr_err("failed to enable device\n");
+@@ -375,7 +375,7 @@ static unsigned char __devinit esb_getdevice(struct pci_dev *pdev)
+ 	return 0;
+ }
+ 
+-static void __devinit esb_initdevice(void)
++static void esb_initdevice(void)
+ {
+ 	u8 val1;
+ 	u16 val2;
+@@ -416,7 +416,7 @@ static void __devinit esb_initdevice(void)
+ 	esb_timer_set_heartbeat(heartbeat);
+ }
+ 
+-static int __devinit esb_probe(struct pci_dev *pdev,
++static int esb_probe(struct pci_dev *pdev,
+ 		const struct pci_device_id *ent)
+ {
+ 	int ret;
+diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
+index b83f935f6d4d..fb341df65614 100644
+--- a/drivers/watchdog/iTCO_wdt.c
++++ b/drivers/watchdog/iTCO_wdt.c
+@@ -390,7 +390,7 @@ static void __devexit iTCO_wdt_cleanup(void)
+ 	iTCO_wdt_private.gcs = NULL;
+ }
+ 
+-static int __devinit iTCO_wdt_probe(struct platform_device *dev)
++static int iTCO_wdt_probe(struct platform_device *dev)
+ {
+ 	int ret = -ENODEV;
+ 	unsigned long val32;
+diff --git a/drivers/watchdog/ib700wdt.c b/drivers/watchdog/ib700wdt.c
+index 4e992c87741c..5249596db2ab 100644
+--- a/drivers/watchdog/ib700wdt.c
++++ b/drivers/watchdog/ib700wdt.c
+@@ -277,7 +277,7 @@ static struct miscdevice ibwdt_miscdev = {
+  *	Init & exit routines
+  */
+ 
+-static int __devinit ibwdt_probe(struct platform_device *dev)
++static int ibwdt_probe(struct platform_device *dev)
+ {
+ 	int res;
+ 
+diff --git a/drivers/watchdog/ie6xx_wdt.c b/drivers/watchdog/ie6xx_wdt.c
+index 93b2cda2f8dd..94eef6fec0f3 100644
+--- a/drivers/watchdog/ie6xx_wdt.c
++++ b/drivers/watchdog/ie6xx_wdt.c
+@@ -225,7 +225,7 @@ static const struct file_operations ie6xx_wdt_dbg_operations = {
+ 	.release	= single_release,
+ };
+ 
+-static void __devinit ie6xx_wdt_debugfs_init(void)
++static void ie6xx_wdt_debugfs_init(void)
+ {
+ 	/* /sys/kernel/debug/ie6xx_wdt */
+ 	ie6xx_wdt_data.debugfs = debugfs_create_file("ie6xx_wdt",
+@@ -238,7 +238,7 @@ static void ie6xx_wdt_debugfs_exit(void)
+ }
+ 
+ #else
+-static void __devinit ie6xx_wdt_debugfs_init(void)
++static void ie6xx_wdt_debugfs_init(void)
+ {
+ }
+ 
+@@ -247,7 +247,7 @@ static void ie6xx_wdt_debugfs_exit(void)
+ }
+ #endif
+ 
+-static int __devinit ie6xx_wdt_probe(struct platform_device *pdev)
++static int ie6xx_wdt_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res;
+ 	u8 wdtlr;
+diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c
+index 331a61340fe8..eb7008a1d6e6 100644
+--- a/drivers/watchdog/jz4740_wdt.c
++++ b/drivers/watchdog/jz4740_wdt.c
+@@ -144,7 +144,7 @@ static const struct watchdog_ops jz4740_wdt_ops = {
+ 	.set_timeout = jz4740_wdt_set_timeout,
+ };
+ 
+-static int __devinit jz4740_wdt_probe(struct platform_device *pdev)
++static int jz4740_wdt_probe(struct platform_device *pdev)
+ {
+ 	struct jz4740_wdt_drvdata *drvdata;
+ 	struct watchdog_device *jz4740_wdt;
+diff --git a/drivers/watchdog/ks8695_wdt.c b/drivers/watchdog/ks8695_wdt.c
+index 6ac9ff2493f6..c305adb49fbf 100644
+--- a/drivers/watchdog/ks8695_wdt.c
++++ b/drivers/watchdog/ks8695_wdt.c
+@@ -235,7 +235,7 @@ static struct miscdevice ks8695wdt_miscdev = {
+ 	.fops		= &ks8695wdt_fops,
+ };
+ 
+-static int __devinit ks8695wdt_probe(struct platform_device *pdev)
++static int ks8695wdt_probe(struct platform_device *pdev)
+ {
+ 	int res;
+ 
+diff --git a/drivers/watchdog/lantiq_wdt.c b/drivers/watchdog/lantiq_wdt.c
+index ce4df083d7fa..fd9f43c48d47 100644
+--- a/drivers/watchdog/lantiq_wdt.c
++++ b/drivers/watchdog/lantiq_wdt.c
+@@ -186,7 +186,7 @@ static struct miscdevice ltq_wdt_miscdev = {
+ 	.fops	= <q_wdt_fops,
+ };
+ 
+-static int __devinit
++static int
+ ltq_wdt_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+diff --git a/drivers/watchdog/max63xx_wdt.c b/drivers/watchdog/max63xx_wdt.c
+index 7e952217cf6b..b572c751ebf5 100644
+--- a/drivers/watchdog/max63xx_wdt.c
++++ b/drivers/watchdog/max63xx_wdt.c
+@@ -174,7 +174,7 @@ static struct watchdog_device max63xx_wdt_dev = {
+ 	.ops = &max63xx_wdt_ops,
+ };
+ 
+-static int __devinit max63xx_wdt_probe(struct platform_device *pdev)
++static int max63xx_wdt_probe(struct platform_device *pdev)
+ {
+ 	struct resource	*wdt_mem;
+ 	struct max63xx_timeout *table;
+diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c
+index e44d6d9c1f35..5c23a6bac944 100644
+--- a/drivers/watchdog/mpc8xxx_wdt.c
++++ b/drivers/watchdog/mpc8xxx_wdt.c
+@@ -188,7 +188,7 @@ static struct miscdevice mpc8xxx_wdt_miscdev = {
+ };
+ 
+ static const struct of_device_id mpc8xxx_wdt_match[];
+-static int __devinit mpc8xxx_wdt_probe(struct platform_device *ofdev)
++static int mpc8xxx_wdt_probe(struct platform_device *ofdev)
+ {
+ 	int ret;
+ 	const struct of_device_id *match;
+diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c
+index cf66cee35956..4f90ac5910af 100644
+--- a/drivers/watchdog/mpcore_wdt.c
++++ b/drivers/watchdog/mpcore_wdt.c
+@@ -327,7 +327,7 @@ static struct miscdevice mpcore_wdt_miscdev = {
+ 	.fops		= &mpcore_wdt_fops,
+ };
+ 
+-static int __devinit mpcore_wdt_probe(struct platform_device *pdev)
++static int mpcore_wdt_probe(struct platform_device *pdev)
+ {
+ 	struct mpcore_wdt *wdt;
+ 	struct resource *res;
+diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c
+index 5474a06ad607..8c642763ca6e 100644
+--- a/drivers/watchdog/mtx-1_wdt.c
++++ b/drivers/watchdog/mtx-1_wdt.c
+@@ -204,7 +204,7 @@ static struct miscdevice mtx1_wdt_misc = {
+ };
+ 
+ 
+-static int __devinit mtx1_wdt_probe(struct platform_device *pdev)
++static int mtx1_wdt_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 
+diff --git a/drivers/watchdog/mv64x60_wdt.c b/drivers/watchdog/mv64x60_wdt.c
+index 7d37da5522bb..2876027a8886 100644
+--- a/drivers/watchdog/mv64x60_wdt.c
++++ b/drivers/watchdog/mv64x60_wdt.c
+@@ -253,7 +253,7 @@ static struct miscdevice mv64x60_wdt_miscdev = {
+ 	.fops = &mv64x60_wdt_fops,
+ };
+ 
+-static int __devinit mv64x60_wdt_probe(struct platform_device *dev)
++static int mv64x60_wdt_probe(struct platform_device *dev)
+ {
+ 	struct mv64x60_wdt_pdata *pdata = dev->dev.platform_data;
+ 	struct resource *r;
+diff --git a/drivers/watchdog/nuc900_wdt.c b/drivers/watchdog/nuc900_wdt.c
+index a77f6900917d..d05daefa8640 100644
+--- a/drivers/watchdog/nuc900_wdt.c
++++ b/drivers/watchdog/nuc900_wdt.c
+@@ -242,7 +242,7 @@ static struct miscdevice nuc900wdt_miscdev = {
+ 	.fops		= &nuc900wdt_fops,
+ };
+ 
+-static int __devinit nuc900wdt_probe(struct platform_device *pdev)
++static int nuc900wdt_probe(struct platform_device *pdev)
+ {
+ 	int ret = 0;
+ 
+diff --git a/drivers/watchdog/nv_tco.c b/drivers/watchdog/nv_tco.c
+index e0d4496c2811..45452845faca 100644
+--- a/drivers/watchdog/nv_tco.c
++++ b/drivers/watchdog/nv_tco.c
+@@ -302,7 +302,7 @@ MODULE_DEVICE_TABLE(pci, tco_pci_tbl);
+  *	Init & exit routines
+  */
+ 
+-static unsigned char __devinit nv_tco_getdevice(void)
++static unsigned char nv_tco_getdevice(void)
+ {
+ 	struct pci_dev *dev = NULL;
+ 	u32 val;
+@@ -376,7 +376,7 @@ static unsigned char __devinit nv_tco_getdevice(void)
+ 	return 0;
+ }
+ 
+-static int __devinit nv_tco_init(struct platform_device *dev)
++static int nv_tco_init(struct platform_device *dev)
+ {
+ 	int ret;
+ 
+diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c
+index df8c5f3f3674..fd3e5f6ee55c 100644
+--- a/drivers/watchdog/of_xilinx_wdt.c
++++ b/drivers/watchdog/of_xilinx_wdt.c
+@@ -289,7 +289,7 @@ static struct miscdevice xwdt_miscdev = {
+ 	.fops       = &xwdt_fops,
+ };
+ 
+-static int __devinit xwdt_probe(struct platform_device *pdev)
++static int xwdt_probe(struct platform_device *pdev)
+ {
+ 	int rc;
+ 	u32 *tmptr;
+diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
+index 1596a5da3463..36a724614383 100644
+--- a/drivers/watchdog/omap_wdt.c
++++ b/drivers/watchdog/omap_wdt.c
+@@ -264,7 +264,7 @@ static const struct file_operations omap_wdt_fops = {
+ 	.llseek = no_llseek,
+ };
+ 
+-static int __devinit omap_wdt_probe(struct platform_device *pdev)
++static int omap_wdt_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res, *mem;
+ 	struct omap_wdt_dev *wdev;
+diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
+index 33a0872ab470..e6b7bd2117c6 100644
+--- a/drivers/watchdog/orion_wdt.c
++++ b/drivers/watchdog/orion_wdt.c
+@@ -142,7 +142,7 @@ static struct watchdog_device orion_wdt = {
+ 	.ops = &orion_wdt_ops,
+ };
+ 
+-static int __devinit orion_wdt_probe(struct platform_device *pdev)
++static int orion_wdt_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res;
+ 	int ret;
+diff --git a/drivers/watchdog/pcwd.c b/drivers/watchdog/pcwd.c
+index df454c9b5274..cef246abdd66 100644
+--- a/drivers/watchdog/pcwd.c
++++ b/drivers/watchdog/pcwd.c
+@@ -801,7 +801,7 @@ static inline int get_revision(void)
+  *  The initial rate is once per second at board start up, then twice
+  *  per second for normal operation.
+  */
+-static int __devinit pcwd_isa_match(struct device *dev, unsigned int id)
++static int pcwd_isa_match(struct device *dev, unsigned int id)
+ {
+ 	int base_addr = pcwd_ioports[id];
+ 	int port0, last_port0;	/* Reg 0, in case it's REV A */
+@@ -846,7 +846,7 @@ static int __devinit pcwd_isa_match(struct device *dev, unsigned int id)
+ 	return retval;
+ }
+ 
+-static int __devinit pcwd_isa_probe(struct device *dev, unsigned int id)
++static int pcwd_isa_probe(struct device *dev, unsigned int id)
+ {
+ 	int ret;
+ 
+diff --git a/drivers/watchdog/pcwd_pci.c b/drivers/watchdog/pcwd_pci.c
+index 1407a6fd077b..6ec84b5bb508 100644
+--- a/drivers/watchdog/pcwd_pci.c
++++ b/drivers/watchdog/pcwd_pci.c
+@@ -682,7 +682,7 @@ static struct notifier_block pcipcwd_notifier = {
+  *	Init & exit routines
+  */
+ 
+-static int __devinit pcipcwd_card_init(struct pci_dev *pdev,
++static int pcipcwd_card_init(struct pci_dev *pdev,
+ 		const struct pci_device_id *ent)
+ {
+ 	int ret = -EIO;
+diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c
+index 5c07fa47b8ce..4f7afeab6698 100644
+--- a/drivers/watchdog/pnx4008_wdt.c
++++ b/drivers/watchdog/pnx4008_wdt.c
+@@ -146,7 +146,7 @@ static struct watchdog_device pnx4008_wdd = {
+ 	.max_timeout = MAX_HEARTBEAT,
+ };
+ 
+-static int __devinit pnx4008_wdt_probe(struct platform_device *pdev)
++static int pnx4008_wdt_probe(struct platform_device *pdev)
+ {
+ 	struct resource *r;
+ 	int ret = 0;
+diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c
+index cf983d3a32fe..22662808c37d 100644
+--- a/drivers/watchdog/rc32434_wdt.c
++++ b/drivers/watchdog/rc32434_wdt.c
+@@ -260,7 +260,7 @@ static struct miscdevice rc32434_wdt_miscdev = {
+ 	.fops	= &rc32434_wdt_fops,
+ };
+ 
+-static int __devinit rc32434_wdt_probe(struct platform_device *pdev)
++static int rc32434_wdt_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 	struct resource *r;
+diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c
+index 27682148c99e..94667064c8cf 100644
+--- a/drivers/watchdog/rdc321x_wdt.c
++++ b/drivers/watchdog/rdc321x_wdt.c
+@@ -225,7 +225,7 @@ static struct miscdevice rdc321x_wdt_misc = {
+ 	.fops	= &rdc321x_wdt_fops,
+ };
+ 
+-static int __devinit rdc321x_wdt_probe(struct platform_device *pdev)
++static int rdc321x_wdt_probe(struct platform_device *pdev)
+ {
+ 	int err;
+ 	struct resource *r;
+diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c
+index 65851f4553c4..84f523338ff4 100644
+--- a/drivers/watchdog/riowd.c
++++ b/drivers/watchdog/riowd.c
+@@ -174,7 +174,7 @@ static struct miscdevice riowd_miscdev = {
+ 	.fops	= &riowd_fops
+ };
+ 
+-static int __devinit riowd_probe(struct platform_device *op)
++static int riowd_probe(struct platform_device *op)
+ {
+ 	struct riowd *p;
+ 	int err = -EINVAL;
+diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
+index c31742096932..2e28c145081c 100644
+--- a/drivers/watchdog/s3c2410_wdt.c
++++ b/drivers/watchdog/s3c2410_wdt.c
+@@ -303,7 +303,7 @@ static inline void s3c2410wdt_cpufreq_deregister(void)
+ }
+ #endif
+ 
+-static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
++static int s3c2410wdt_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev;
+ 	unsigned int wtcon;
+diff --git a/drivers/watchdog/sch311x_wdt.c b/drivers/watchdog/sch311x_wdt.c
+index 766b132e8c6e..8ecec2919797 100644
+--- a/drivers/watchdog/sch311x_wdt.c
++++ b/drivers/watchdog/sch311x_wdt.c
+@@ -356,7 +356,7 @@ static struct miscdevice sch311x_wdt_miscdev = {
+  *	Init & exit routines
+  */
+ 
+-static int __devinit sch311x_wdt_probe(struct platform_device *pdev)
++static int sch311x_wdt_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	int err;
+diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c
+index ce1be6eca640..9c57af943b87 100644
+--- a/drivers/watchdog/shwdt.c
++++ b/drivers/watchdog/shwdt.c
+@@ -217,7 +217,7 @@ static struct watchdog_device sh_wdt_dev = {
+ 	.ops	= &sh_wdt_ops,
+ };
+ 
+-static int __devinit sh_wdt_probe(struct platform_device *pdev)
++static int sh_wdt_probe(struct platform_device *pdev)
+ {
+ 	struct sh_wdt *wdt;
+ 	struct resource *res;
+diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c
+index 066901bdc4d5..7ee39a79ff1e 100644
+--- a/drivers/watchdog/sp5100_tco.c
++++ b/drivers/watchdog/sp5100_tco.c
+@@ -271,7 +271,7 @@ MODULE_DEVICE_TABLE(pci, sp5100_tco_pci_tbl);
+  * Init & exit routines
+  */
+ 
+-static unsigned char __devinit sp5100_tco_setupdevice(void)
++static unsigned char sp5100_tco_setupdevice(void)
+ {
+ 	struct pci_dev *dev = NULL;
+ 	u32 val;
+@@ -361,7 +361,7 @@ static unsigned char __devinit sp5100_tco_setupdevice(void)
+ 	return 0;
+ }
+ 
+-static int __devinit sp5100_tco_init(struct platform_device *dev)
++static int sp5100_tco_init(struct platform_device *dev)
+ {
+ 	int ret;
+ 	u32 val;
+diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c
+index f1c1e889e419..32a5419657d2 100644
+--- a/drivers/watchdog/sp805_wdt.c
++++ b/drivers/watchdog/sp805_wdt.c
+@@ -210,7 +210,7 @@ static const struct watchdog_ops wdt_ops = {
+ 	.get_timeleft	= wdt_timeleft,
+ };
+ 
+-static int __devinit
++static int
+ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
+ {
+ 	struct sp805_wdt *wdt;
+diff --git a/drivers/watchdog/stmp3xxx_wdt.c b/drivers/watchdog/stmp3xxx_wdt.c
+index 4226250eb6e4..254cce38cc03 100644
+--- a/drivers/watchdog/stmp3xxx_wdt.c
++++ b/drivers/watchdog/stmp3xxx_wdt.c
+@@ -204,7 +204,7 @@ static struct miscdevice stmp3xxx_wdt_miscdev = {
+ 	.fops = &stmp3xxx_wdt_fops,
+ };
+ 
+-static int __devinit stmp3xxx_wdt_probe(struct platform_device *pdev)
++static int stmp3xxx_wdt_probe(struct platform_device *pdev)
+ {
+ 	int ret = 0;
+ 
+diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c
+index 2acc1fe7f54d..d6e94b4c67f6 100644
+--- a/drivers/watchdog/ts72xx_wdt.c
++++ b/drivers/watchdog/ts72xx_wdt.c
+@@ -390,7 +390,7 @@ static struct miscdevice ts72xx_wdt_miscdev = {
+ 	.fops		= &ts72xx_wdt_fops,
+ };
+ 
+-static __devinit int ts72xx_wdt_probe(struct platform_device *pdev)
++static int ts72xx_wdt_probe(struct platform_device *pdev)
+ {
+ 	struct ts72xx_wdt *wdt;
+ 	struct resource *r1, *r2;
+diff --git a/drivers/watchdog/twl4030_wdt.c b/drivers/watchdog/twl4030_wdt.c
+index cf59a38478e0..6dab509caf94 100644
+--- a/drivers/watchdog/twl4030_wdt.c
++++ b/drivers/watchdog/twl4030_wdt.c
+@@ -170,7 +170,7 @@ static const struct file_operations twl4030_wdt_fops = {
+ 	.write		= twl4030_wdt_write_fop,
+ };
+ 
+-static int __devinit twl4030_wdt_probe(struct platform_device *pdev)
++static int twl4030_wdt_probe(struct platform_device *pdev)
+ {
+ 	int ret = 0;
+ 	struct twl4030_wdt *wdt;
+diff --git a/drivers/watchdog/via_wdt.c b/drivers/watchdog/via_wdt.c
+index a9af1ddae1ba..098dfab82b6c 100644
+--- a/drivers/watchdog/via_wdt.c
++++ b/drivers/watchdog/via_wdt.c
+@@ -155,7 +155,7 @@ static struct watchdog_device wdt_dev = {
+ 	.max_timeout =	WDT_TIMEOUT_MAX,
+ };
+ 
+-static int __devinit wdt_probe(struct pci_dev *pdev,
++static int wdt_probe(struct pci_dev *pdev,
+ 			       const struct pci_device_id *ent)
+ {
+ 	unsigned char conf;
+diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c
+index 05c14e4740c1..13d27c878db4 100644
+--- a/drivers/watchdog/wdt_pci.c
++++ b/drivers/watchdog/wdt_pci.c
+@@ -605,7 +605,7 @@ static struct notifier_block wdtpci_notifier = {
+ };
+ 
+ 
+-static int __devinit wdtpci_init_one(struct pci_dev *dev,
++static int wdtpci_init_one(struct pci_dev *dev,
+ 					const struct pci_device_id *ent)
+ {
+ 	int ret = -EIO;
+diff --git a/drivers/watchdog/wm831x_wdt.c b/drivers/watchdog/wm831x_wdt.c
+index f9c54feb8f1a..170c82e97454 100644
+--- a/drivers/watchdog/wm831x_wdt.c
++++ b/drivers/watchdog/wm831x_wdt.c
+@@ -181,7 +181,7 @@ static const struct watchdog_ops wm831x_wdt_ops = {
+ 	.set_timeout = wm831x_wdt_set_timeout,
+ };
+ 
+-static int __devinit wm831x_wdt_probe(struct platform_device *pdev)
++static int wm831x_wdt_probe(struct platform_device *pdev)
+ {
+ 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
+ 	struct wm831x_pdata *chip_pdata;
+diff --git a/drivers/watchdog/wm8350_wdt.c b/drivers/watchdog/wm8350_wdt.c
+index 770b6da1ff41..4530fa00b78d 100644
+--- a/drivers/watchdog/wm8350_wdt.c
++++ b/drivers/watchdog/wm8350_wdt.c
+@@ -140,7 +140,7 @@ static struct watchdog_device wm8350_wdt = {
+ 	.max_timeout = 4,
+ };
+ 
+-static int __devinit wm8350_wdt_probe(struct platform_device *pdev)
++static int wm8350_wdt_probe(struct platform_device *pdev)
+ {
+ 	struct wm8350 *wm8350 = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/watchdog/xen_wdt.c b/drivers/watchdog/xen_wdt.c
+index 99b956fa4ebd..1eb6bdc020ac 100644
+--- a/drivers/watchdog/xen_wdt.c
++++ b/drivers/watchdog/xen_wdt.c
+@@ -244,7 +244,7 @@ static struct miscdevice xen_wdt_miscdev = {
+ 	.fops =		&xen_wdt_fops,
+ };
+ 
+-static int __devinit xen_wdt_probe(struct platform_device *dev)
++static int xen_wdt_probe(struct platform_device *dev)
+ {
+ 	struct sched_watchdog wd = { .id = ~0 };
+ 	int ret = HYPERVISOR_sched_op(SCHEDOP_watchdog, &wd);

commit 82268714bdf06bc06135efb707a9de590ab2d294
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:12 2012 -0500
+
+    watchdog: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Wim Van Sebroeck 
+    Cc: Wan ZongShun 
+    Cc: Ben Dooks 
+    Cc: Kukjin Kim 
+    Acked-by: Mark Brown 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/watchdog/acquirewdt.c b/drivers/watchdog/acquirewdt.c
+index 4397881c83f4..49e0b89ceed9 100644
+--- a/drivers/watchdog/acquirewdt.c
++++ b/drivers/watchdog/acquirewdt.c
+@@ -293,7 +293,7 @@ static void acq_shutdown(struct platform_device *dev)
+ 
+ static struct platform_driver acquirewdt_driver = {
+ 	.probe		= acq_probe,
+-	.remove		= __devexit_p(acq_remove),
++	.remove		= acq_remove,
+ 	.shutdown	= acq_shutdown,
+ 	.driver		= {
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/watchdog/advantechwdt.c b/drivers/watchdog/advantechwdt.c
+index 64ae9e9fed94..9a74156f05ee 100644
+--- a/drivers/watchdog/advantechwdt.c
++++ b/drivers/watchdog/advantechwdt.c
+@@ -300,7 +300,7 @@ static void advwdt_shutdown(struct platform_device *dev)
+ 
+ static struct platform_driver advwdt_driver = {
+ 	.probe		= advwdt_probe,
+-	.remove		= __devexit_p(advwdt_remove),
++	.remove		= advwdt_remove,
+ 	.shutdown	= advwdt_shutdown,
+ 	.driver		= {
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c
+index dc30dbd21cf1..eb633d9951a2 100644
+--- a/drivers/watchdog/ar7_wdt.c
++++ b/drivers/watchdog/ar7_wdt.c
+@@ -330,7 +330,7 @@ static void ar7_wdt_shutdown(struct platform_device *pdev)
+ 
+ static struct platform_driver ar7_wdt_driver = {
+ 	.probe = ar7_wdt_probe,
+-	.remove = __devexit_p(ar7_wdt_remove),
++	.remove = ar7_wdt_remove,
+ 	.shutdown = ar7_wdt_shutdown,
+ 	.driver = {
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c
+index 7ef99a169e3b..75f3a6bc323b 100644
+--- a/drivers/watchdog/at91rm9200_wdt.c
++++ b/drivers/watchdog/at91rm9200_wdt.c
+@@ -254,7 +254,7 @@ static int at91wdt_resume(struct platform_device *pdev)
+ 
+ static struct platform_driver at91wdt_driver = {
+ 	.probe		= at91wdt_probe,
+-	.remove		= __devexit_p(at91wdt_remove),
++	.remove		= at91wdt_remove,
+ 	.shutdown	= at91wdt_shutdown,
+ 	.suspend	= at91wdt_suspend,
+ 	.resume		= at91wdt_resume,
+diff --git a/drivers/watchdog/ath79_wdt.c b/drivers/watchdog/ath79_wdt.c
+index 1f9371f49c40..367ef5ed19b7 100644
+--- a/drivers/watchdog/ath79_wdt.c
++++ b/drivers/watchdog/ath79_wdt.c
+@@ -284,7 +284,7 @@ static void ath97_wdt_shutdown(struct platform_device *pdev)
+ }
+ 
+ static struct platform_driver ath79_wdt_driver = {
+-	.remove		= __devexit_p(ath79_wdt_remove),
++	.remove		= ath79_wdt_remove,
+ 	.shutdown	= ath97_wdt_shutdown,
+ 	.driver		= {
+ 		.name	= DRIVER_NAME,
+diff --git a/drivers/watchdog/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c
+index 551880bfd629..e81b78444fa9 100644
+--- a/drivers/watchdog/bcm63xx_wdt.c
++++ b/drivers/watchdog/bcm63xx_wdt.c
+@@ -304,7 +304,7 @@ static void bcm63xx_wdt_shutdown(struct platform_device *pdev)
+ 
+ static struct platform_driver bcm63xx_wdt_driver = {
+ 	.probe	= bcm63xx_wdt_probe,
+-	.remove = __devexit_p(bcm63xx_wdt_remove),
++	.remove = bcm63xx_wdt_remove,
+ 	.shutdown = bcm63xx_wdt_shutdown,
+ 	.driver = {
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c
+index 38bc383e0677..4a85dbf5aec0 100644
+--- a/drivers/watchdog/bfin_wdt.c
++++ b/drivers/watchdog/bfin_wdt.c
+@@ -401,7 +401,7 @@ static struct platform_device *bfin_wdt_device;
+ 
+ static struct platform_driver bfin_wdt_driver = {
+ 	.probe     = bfin_wdt_probe,
+-	.remove    = __devexit_p(bfin_wdt_remove),
++	.remove    = bfin_wdt_remove,
+ 	.shutdown  = bfin_wdt_shutdown,
+ 	.suspend   = bfin_wdt_suspend,
+ 	.resume    = bfin_wdt_resume,
+diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c
+index 95b1b954de1b..ed7f434bba79 100644
+--- a/drivers/watchdog/cpwd.c
++++ b/drivers/watchdog/cpwd.c
+@@ -684,7 +684,7 @@ static struct platform_driver cpwd_driver = {
+ 		.of_match_table = cpwd_match,
+ 	},
+ 	.probe		= cpwd_probe,
+-	.remove		= __devexit_p(cpwd_remove),
++	.remove		= cpwd_remove,
+ };
+ 
+ module_platform_driver(cpwd_driver);
+diff --git a/drivers/watchdog/da9052_wdt.c b/drivers/watchdog/da9052_wdt.c
+index f7abbaeebcaf..463e9e55b560 100644
+--- a/drivers/watchdog/da9052_wdt.c
++++ b/drivers/watchdog/da9052_wdt.c
+@@ -236,7 +236,7 @@ static int __devexit da9052_wdt_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver da9052_wdt_driver = {
+ 	.probe = da9052_wdt_probe,
+-	.remove = __devexit_p(da9052_wdt_remove),
++	.remove = da9052_wdt_remove,
+ 	.driver = {
+ 		.name	= "da9052-watchdog",
+ 	},
+diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c
+index c8c5c8032bcb..ea4e96259a82 100644
+--- a/drivers/watchdog/davinci_wdt.c
++++ b/drivers/watchdog/davinci_wdt.c
+@@ -268,7 +268,7 @@ static struct platform_driver platform_wdt_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe = davinci_wdt_probe,
+-	.remove = __devexit_p(davinci_wdt_remove),
++	.remove = davinci_wdt_remove,
+ };
+ 
+ module_platform_driver(platform_wdt_driver);
+diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c
+index 06de1211a444..6a8448dcc20e 100644
+--- a/drivers/watchdog/dw_wdt.c
++++ b/drivers/watchdog/dw_wdt.c
+@@ -345,7 +345,7 @@ static int __devexit dw_wdt_drv_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver dw_wdt_driver = {
+ 	.probe		= dw_wdt_drv_probe,
+-	.remove		= __devexit_p(dw_wdt_drv_remove),
++	.remove		= dw_wdt_drv_remove,
+ 	.driver		= {
+ 		.name	= "dw_wdt",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c
+index 77050037597a..91703a58145d 100644
+--- a/drivers/watchdog/ep93xx_wdt.c
++++ b/drivers/watchdog/ep93xx_wdt.c
+@@ -168,7 +168,7 @@ static struct platform_driver ep93xx_wdt_driver = {
+ 		.name	= "ep93xx-wdt",
+ 	},
+ 	.probe		= ep93xx_wdt_probe,
+-	.remove		= __devexit_p(ep93xx_wdt_remove),
++	.remove		= ep93xx_wdt_remove,
+ };
+ 
+ module_platform_driver(ep93xx_wdt_driver);
+diff --git a/drivers/watchdog/geodewdt.c b/drivers/watchdog/geodewdt.c
+index dc563b680abd..a340e04f2379 100644
+--- a/drivers/watchdog/geodewdt.c
++++ b/drivers/watchdog/geodewdt.c
+@@ -256,7 +256,7 @@ static void geodewdt_shutdown(struct platform_device *dev)
+ 
+ static struct platform_driver geodewdt_driver = {
+ 	.probe		= geodewdt_probe,
+-	.remove		= __devexit_p(geodewdt_remove),
++	.remove		= geodewdt_remove,
+ 	.shutdown	= geodewdt_shutdown,
+ 	.driver		= {
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
+index ae60406ea8a1..03687bcc74f2 100644
+--- a/drivers/watchdog/hpwdt.c
++++ b/drivers/watchdog/hpwdt.c
+@@ -863,7 +863,7 @@ static struct pci_driver hpwdt_driver = {
+ 	.name = "hpwdt",
+ 	.id_table = hpwdt_devices,
+ 	.probe = hpwdt_init_one,
+-	.remove = __devexit_p(hpwdt_exit),
++	.remove = hpwdt_exit,
+ };
+ 
+ MODULE_AUTHOR("Tom Mingarelli");
+diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c
+index 276877d5b6a3..2574066c6343 100644
+--- a/drivers/watchdog/i6300esb.c
++++ b/drivers/watchdog/i6300esb.c
+@@ -488,7 +488,7 @@ static struct pci_driver esb_driver = {
+ 	.name		= ESB_MODULE_NAME,
+ 	.id_table	= esb_pci_tbl,
+ 	.probe          = esb_probe,
+-	.remove         = __devexit_p(esb_remove),
++	.remove         = esb_remove,
+ 	.shutdown       = esb_shutdown,
+ };
+ 
+diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
+index 545d387de411..b83f935f6d4d 100644
+--- a/drivers/watchdog/iTCO_wdt.c
++++ b/drivers/watchdog/iTCO_wdt.c
+@@ -548,7 +548,7 @@ static void iTCO_wdt_shutdown(struct platform_device *dev)
+ 
+ static struct platform_driver iTCO_wdt_driver = {
+ 	.probe          = iTCO_wdt_probe,
+-	.remove         = __devexit_p(iTCO_wdt_remove),
++	.remove         = iTCO_wdt_remove,
+ 	.shutdown       = iTCO_wdt_shutdown,
+ 	.driver         = {
+ 		.owner  = THIS_MODULE,
+diff --git a/drivers/watchdog/ib700wdt.c b/drivers/watchdog/ib700wdt.c
+index 184c0bfc87a4..4e992c87741c 100644
+--- a/drivers/watchdog/ib700wdt.c
++++ b/drivers/watchdog/ib700wdt.c
+@@ -337,7 +337,7 @@ static void ibwdt_shutdown(struct platform_device *dev)
+ 
+ static struct platform_driver ibwdt_driver = {
+ 	.probe		= ibwdt_probe,
+-	.remove		= __devexit_p(ibwdt_remove),
++	.remove		= ibwdt_remove,
+ 	.shutdown	= ibwdt_shutdown,
+ 	.driver		= {
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/watchdog/ie6xx_wdt.c b/drivers/watchdog/ie6xx_wdt.c
+index 8f541b940053..93b2cda2f8dd 100644
+--- a/drivers/watchdog/ie6xx_wdt.c
++++ b/drivers/watchdog/ie6xx_wdt.c
+@@ -311,7 +311,7 @@ static int __devexit ie6xx_wdt_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver ie6xx_wdt_driver = {
+ 	.probe		= ie6xx_wdt_probe,
+-	.remove		= __devexit_p(ie6xx_wdt_remove),
++	.remove		= ie6xx_wdt_remove,
+ 	.driver		= {
+ 		.name	= DRIVER_NAME,
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c
+index 978615ef899d..331a61340fe8 100644
+--- a/drivers/watchdog/jz4740_wdt.c
++++ b/drivers/watchdog/jz4740_wdt.c
+@@ -210,7 +210,7 @@ static int __devexit jz4740_wdt_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver jz4740_wdt_driver = {
+ 	.probe = jz4740_wdt_probe,
+-	.remove = __devexit_p(jz4740_wdt_remove),
++	.remove = jz4740_wdt_remove,
+ 	.driver = {
+ 		.name = "jz4740-wdt",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/watchdog/ks8695_wdt.c b/drivers/watchdog/ks8695_wdt.c
+index c1a4d3bf581d..6ac9ff2493f6 100644
+--- a/drivers/watchdog/ks8695_wdt.c
++++ b/drivers/watchdog/ks8695_wdt.c
+@@ -290,7 +290,7 @@ static int ks8695wdt_resume(struct platform_device *pdev)
+ 
+ static struct platform_driver ks8695wdt_driver = {
+ 	.probe		= ks8695wdt_probe,
+-	.remove		= __devexit_p(ks8695wdt_remove),
++	.remove		= ks8695wdt_remove,
+ 	.shutdown	= ks8695wdt_shutdown,
+ 	.suspend	= ks8695wdt_suspend,
+ 	.resume		= ks8695wdt_resume,
+diff --git a/drivers/watchdog/lantiq_wdt.c b/drivers/watchdog/lantiq_wdt.c
+index 2e74c3a8ee58..ce4df083d7fa 100644
+--- a/drivers/watchdog/lantiq_wdt.c
++++ b/drivers/watchdog/lantiq_wdt.c
+@@ -236,7 +236,7 @@ MODULE_DEVICE_TABLE(of, ltq_wdt_match);
+ 
+ static struct platform_driver ltq_wdt_driver = {
+ 	.probe = ltq_wdt_probe,
+-	.remove = __devexit_p(ltq_wdt_remove),
++	.remove = ltq_wdt_remove,
+ 	.driver = {
+ 		.name = "wdt",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/watchdog/max63xx_wdt.c b/drivers/watchdog/max63xx_wdt.c
+index 8f4a74e91619..7e952217cf6b 100644
+--- a/drivers/watchdog/max63xx_wdt.c
++++ b/drivers/watchdog/max63xx_wdt.c
+@@ -228,7 +228,7 @@ MODULE_DEVICE_TABLE(platform, max63xx_id_table);
+ 
+ static struct platform_driver max63xx_wdt_driver = {
+ 	.probe		= max63xx_wdt_probe,
+-	.remove		= __devexit_p(max63xx_wdt_remove),
++	.remove		= max63xx_wdt_remove,
+ 	.id_table	= max63xx_id_table,
+ 	.driver		= {
+ 		.name	= "max63xx_wdt",
+diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c
+index e6a038ae8dc2..e44d6d9c1f35 100644
+--- a/drivers/watchdog/mpc8xxx_wdt.c
++++ b/drivers/watchdog/mpc8xxx_wdt.c
+@@ -281,7 +281,7 @@ MODULE_DEVICE_TABLE(of, mpc8xxx_wdt_match);
+ 
+ static struct platform_driver mpc8xxx_wdt_driver = {
+ 	.probe		= mpc8xxx_wdt_probe,
+-	.remove		= __devexit_p(mpc8xxx_wdt_remove),
++	.remove		= mpc8xxx_wdt_remove,
+ 	.driver = {
+ 		.name = "mpc8xxx_wdt",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c
+index 7c741dc987bd..cf66cee35956 100644
+--- a/drivers/watchdog/mpcore_wdt.c
++++ b/drivers/watchdog/mpcore_wdt.c
+@@ -415,7 +415,7 @@ MODULE_ALIAS("platform:mpcore_wdt");
+ 
+ static struct platform_driver mpcore_wdt_driver = {
+ 	.probe		= mpcore_wdt_probe,
+-	.remove		= __devexit_p(mpcore_wdt_remove),
++	.remove		= mpcore_wdt_remove,
+ 	.suspend	= mpcore_wdt_suspend,
+ 	.resume		= mpcore_wdt_resume,
+ 	.shutdown	= mpcore_wdt_shutdown,
+diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c
+index c29e31d99fe8..5474a06ad607 100644
+--- a/drivers/watchdog/mtx-1_wdt.c
++++ b/drivers/watchdog/mtx-1_wdt.c
+@@ -248,7 +248,7 @@ static int __devexit mtx1_wdt_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver mtx1_wdt_driver = {
+ 	.probe = mtx1_wdt_probe,
+-	.remove = __devexit_p(mtx1_wdt_remove),
++	.remove = mtx1_wdt_remove,
+ 	.driver.name = "mtx1-wdt",
+ 	.driver.owner = THIS_MODULE,
+ };
+diff --git a/drivers/watchdog/mv64x60_wdt.c b/drivers/watchdog/mv64x60_wdt.c
+index c53d025e70df..7d37da5522bb 100644
+--- a/drivers/watchdog/mv64x60_wdt.c
++++ b/drivers/watchdog/mv64x60_wdt.c
+@@ -300,7 +300,7 @@ static int __devexit mv64x60_wdt_remove(struct platform_device *dev)
+ 
+ static struct platform_driver mv64x60_wdt_driver = {
+ 	.probe = mv64x60_wdt_probe,
+-	.remove = __devexit_p(mv64x60_wdt_remove),
++	.remove = mv64x60_wdt_remove,
+ 	.driver = {
+ 		.owner = THIS_MODULE,
+ 		.name = MV64x60_WDT_NAME,
+diff --git a/drivers/watchdog/nuc900_wdt.c b/drivers/watchdog/nuc900_wdt.c
+index ea4c7448b754..a77f6900917d 100644
+--- a/drivers/watchdog/nuc900_wdt.c
++++ b/drivers/watchdog/nuc900_wdt.c
+@@ -328,7 +328,7 @@ static int __devexit nuc900wdt_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver nuc900wdt_driver = {
+ 	.probe		= nuc900wdt_probe,
+-	.remove		= __devexit_p(nuc900wdt_remove),
++	.remove		= nuc900wdt_remove,
+ 	.driver		= {
+ 		.name	= "nuc900-wdt",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/watchdog/nv_tco.c b/drivers/watchdog/nv_tco.c
+index 6bbb9efc6125..e0d4496c2811 100644
+--- a/drivers/watchdog/nv_tco.c
++++ b/drivers/watchdog/nv_tco.c
+@@ -468,7 +468,7 @@ static void nv_tco_shutdown(struct platform_device *dev)
+ 
+ static struct platform_driver nv_tco_driver = {
+ 	.probe		= nv_tco_init,
+-	.remove		= __devexit_p(nv_tco_remove),
++	.remove		= nv_tco_remove,
+ 	.shutdown	= nv_tco_shutdown,
+ 	.driver		= {
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c
+index 294fb4e00521..df8c5f3f3674 100644
+--- a/drivers/watchdog/of_xilinx_wdt.c
++++ b/drivers/watchdog/of_xilinx_wdt.c
+@@ -401,7 +401,7 @@ MODULE_DEVICE_TABLE(of, xwdt_of_match);
+ 
+ static struct platform_driver xwdt_driver = {
+ 	.probe       = xwdt_probe,
+-	.remove      = __devexit_p(xwdt_remove),
++	.remove      = xwdt_remove,
+ 	.driver = {
+ 		.owner = THIS_MODULE,
+ 		.name  = WATCHDOG_NAME,
+diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
+index f5db18dbc0f9..1596a5da3463 100644
+--- a/drivers/watchdog/omap_wdt.c
++++ b/drivers/watchdog/omap_wdt.c
+@@ -426,7 +426,7 @@ MODULE_DEVICE_TABLE(of, omap_wdt_of_match);
+ 
+ static struct platform_driver omap_wdt_driver = {
+ 	.probe		= omap_wdt_probe,
+-	.remove		= __devexit_p(omap_wdt_remove),
++	.remove		= omap_wdt_remove,
+ 	.shutdown	= omap_wdt_shutdown,
+ 	.suspend	= omap_wdt_suspend,
+ 	.resume		= omap_wdt_resume,
+diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
+index c20f96b579d9..33a0872ab470 100644
+--- a/drivers/watchdog/orion_wdt.c
++++ b/drivers/watchdog/orion_wdt.c
+@@ -201,7 +201,7 @@ MODULE_DEVICE_TABLE(of, orion_wdt_of_match_table);
+ 
+ static struct platform_driver orion_wdt_driver = {
+ 	.probe		= orion_wdt_probe,
+-	.remove		= __devexit_p(orion_wdt_remove),
++	.remove		= orion_wdt_remove,
+ 	.shutdown	= orion_wdt_shutdown,
+ 	.driver		= {
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/watchdog/pcwd.c b/drivers/watchdog/pcwd.c
+index 75694cf24f86..df454c9b5274 100644
+--- a/drivers/watchdog/pcwd.c
++++ b/drivers/watchdog/pcwd.c
+@@ -984,7 +984,7 @@ static void pcwd_isa_shutdown(struct device *dev, unsigned int id)
+ static struct isa_driver pcwd_isa_driver = {
+ 	.match		= pcwd_isa_match,
+ 	.probe		= pcwd_isa_probe,
+-	.remove		= __devexit_p(pcwd_isa_remove),
++	.remove		= pcwd_isa_remove,
+ 	.shutdown	= pcwd_isa_shutdown,
+ 	.driver		= {
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/watchdog/pcwd_pci.c b/drivers/watchdog/pcwd_pci.c
+index ee6900da8678..1407a6fd077b 100644
+--- a/drivers/watchdog/pcwd_pci.c
++++ b/drivers/watchdog/pcwd_pci.c
+@@ -812,7 +812,7 @@ static struct pci_driver pcipcwd_driver = {
+ 	.name		= WATCHDOG_NAME,
+ 	.id_table	= pcipcwd_pci_tbl,
+ 	.probe		= pcipcwd_card_init,
+-	.remove		= __devexit_p(pcipcwd_card_exit),
++	.remove		= pcipcwd_card_exit,
+ };
+ 
+ module_pci_driver(pcipcwd_driver);
+diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c
+index 87722e126058..5c07fa47b8ce 100644
+--- a/drivers/watchdog/pnx4008_wdt.c
++++ b/drivers/watchdog/pnx4008_wdt.c
+@@ -217,7 +217,7 @@ static struct platform_driver platform_wdt_driver = {
+ 		.of_match_table = of_match_ptr(pnx4008_wdt_match),
+ 	},
+ 	.probe = pnx4008_wdt_probe,
+-	.remove = __devexit_p(pnx4008_wdt_remove),
++	.remove = pnx4008_wdt_remove,
+ };
+ 
+ module_platform_driver(platform_wdt_driver);
+diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c
+index 547353a50ebb..cf983d3a32fe 100644
+--- a/drivers/watchdog/rc32434_wdt.c
++++ b/drivers/watchdog/rc32434_wdt.c
+@@ -320,7 +320,7 @@ static void rc32434_wdt_shutdown(struct platform_device *pdev)
+ 
+ static struct platform_driver rc32434_wdt_driver = {
+ 	.probe		= rc32434_wdt_probe,
+-	.remove		= __devexit_p(rc32434_wdt_remove),
++	.remove		= rc32434_wdt_remove,
+ 	.shutdown	= rc32434_wdt_shutdown,
+ 	.driver		= {
+ 			.name = "rc32434_wdt",
+diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c
+index 042ccc56ae26..27682148c99e 100644
+--- a/drivers/watchdog/rdc321x_wdt.c
++++ b/drivers/watchdog/rdc321x_wdt.c
+@@ -286,7 +286,7 @@ static int __devexit rdc321x_wdt_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver rdc321x_wdt_driver = {
+ 	.probe = rdc321x_wdt_probe,
+-	.remove = __devexit_p(rdc321x_wdt_remove),
++	.remove = rdc321x_wdt_remove,
+ 	.driver = {
+ 		.owner = THIS_MODULE,
+ 		.name = "rdc321x-wdt",
+diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c
+index 49e1b1c2135c..65851f4553c4 100644
+--- a/drivers/watchdog/riowd.c
++++ b/drivers/watchdog/riowd.c
+@@ -246,7 +246,7 @@ static struct platform_driver riowd_driver = {
+ 		.of_match_table = riowd_match,
+ 	},
+ 	.probe		= riowd_probe,
+-	.remove		= __devexit_p(riowd_remove),
++	.remove		= riowd_remove,
+ };
+ 
+ module_platform_driver(riowd_driver);
+diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
+index 9245b4d23bfe..c31742096932 100644
+--- a/drivers/watchdog/s3c2410_wdt.c
++++ b/drivers/watchdog/s3c2410_wdt.c
+@@ -508,7 +508,7 @@ MODULE_DEVICE_TABLE(of, s3c2410_wdt_match);
+ 
+ static struct platform_driver s3c2410wdt_driver = {
+ 	.probe		= s3c2410wdt_probe,
+-	.remove		= __devexit_p(s3c2410wdt_remove),
++	.remove		= s3c2410wdt_remove,
+ 	.shutdown	= s3c2410wdt_shutdown,
+ 	.suspend	= s3c2410wdt_suspend,
+ 	.resume		= s3c2410wdt_resume,
+diff --git a/drivers/watchdog/sch311x_wdt.c b/drivers/watchdog/sch311x_wdt.c
+index 9681ada0f252..766b132e8c6e 100644
+--- a/drivers/watchdog/sch311x_wdt.c
++++ b/drivers/watchdog/sch311x_wdt.c
+@@ -451,7 +451,7 @@ static void sch311x_wdt_shutdown(struct platform_device *dev)
+ 
+ static struct platform_driver sch311x_wdt_driver = {
+ 	.probe		= sch311x_wdt_probe,
+-	.remove		= __devexit_p(sch311x_wdt_remove),
++	.remove		= sch311x_wdt_remove,
+ 	.shutdown	= sch311x_wdt_shutdown,
+ 	.driver		= {
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c
+index e5b59bebcdb1..ce1be6eca640 100644
+--- a/drivers/watchdog/shwdt.c
++++ b/drivers/watchdog/shwdt.c
+@@ -324,7 +324,7 @@ static struct platform_driver sh_wdt_driver = {
+ 	},
+ 
+ 	.probe		= sh_wdt_probe,
+-	.remove		= __devexit_p(sh_wdt_remove),
++	.remove		= sh_wdt_remove,
+ 	.shutdown	= sh_wdt_shutdown,
+ };
+ 
+diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c
+index ae5e82cb83fa..066901bdc4d5 100644
+--- a/drivers/watchdog/sp5100_tco.c
++++ b/drivers/watchdog/sp5100_tco.c
+@@ -439,7 +439,7 @@ static void sp5100_tco_shutdown(struct platform_device *dev)
+ 
+ static struct platform_driver sp5100_tco_driver = {
+ 	.probe		= sp5100_tco_init,
+-	.remove		= __devexit_p(sp5100_tco_remove),
++	.remove		= sp5100_tco_remove,
+ 	.shutdown	= sp5100_tco_shutdown,
+ 	.driver		= {
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c
+index e4841c36798b..f1c1e889e419 100644
+--- a/drivers/watchdog/sp805_wdt.c
++++ b/drivers/watchdog/sp805_wdt.c
+@@ -326,7 +326,7 @@ static struct amba_driver sp805_wdt_driver = {
+ 	},
+ 	.id_table	= sp805_wdt_ids,
+ 	.probe		= sp805_wdt_probe,
+-	.remove = __devexit_p(sp805_wdt_remove),
++	.remove = sp805_wdt_remove,
+ };
+ 
+ module_amba_driver(sp805_wdt_driver);
+diff --git a/drivers/watchdog/stmp3xxx_wdt.c b/drivers/watchdog/stmp3xxx_wdt.c
+index 21d96b92bfd7..4226250eb6e4 100644
+--- a/drivers/watchdog/stmp3xxx_wdt.c
++++ b/drivers/watchdog/stmp3xxx_wdt.c
+@@ -269,7 +269,7 @@ static struct platform_driver platform_wdt_driver = {
+ 		.name = "stmp3xxx_wdt",
+ 	},
+ 	.probe = stmp3xxx_wdt_probe,
+-	.remove = __devexit_p(stmp3xxx_wdt_remove),
++	.remove = stmp3xxx_wdt_remove,
+ 	.suspend = stmp3xxx_wdt_suspend,
+ 	.resume = stmp3xxx_wdt_resume,
+ };
+diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c
+index 8df050d800e6..2acc1fe7f54d 100644
+--- a/drivers/watchdog/ts72xx_wdt.c
++++ b/drivers/watchdog/ts72xx_wdt.c
+@@ -499,7 +499,7 @@ static __devexit int ts72xx_wdt_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver ts72xx_wdt_driver = {
+ 	.probe		= ts72xx_wdt_probe,
+-	.remove		= __devexit_p(ts72xx_wdt_remove),
++	.remove		= ts72xx_wdt_remove,
+ 	.driver		= {
+ 		.name	= "ts72xx-wdt",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/watchdog/twl4030_wdt.c b/drivers/watchdog/twl4030_wdt.c
+index 249f11305d26..cf59a38478e0 100644
+--- a/drivers/watchdog/twl4030_wdt.c
++++ b/drivers/watchdog/twl4030_wdt.c
+@@ -247,7 +247,7 @@ static int twl4030_wdt_resume(struct platform_device *pdev)
+ 
+ static struct platform_driver twl4030_wdt_driver = {
+ 	.probe		= twl4030_wdt_probe,
+-	.remove		= __devexit_p(twl4030_wdt_remove),
++	.remove		= twl4030_wdt_remove,
+ 	.suspend	= twl4030_wdt_suspend,
+ 	.resume		= twl4030_wdt_resume,
+ 	.driver		= {
+diff --git a/drivers/watchdog/via_wdt.c b/drivers/watchdog/via_wdt.c
+index aa50da3ccfe3..a9af1ddae1ba 100644
+--- a/drivers/watchdog/via_wdt.c
++++ b/drivers/watchdog/via_wdt.c
+@@ -250,7 +250,7 @@ static struct pci_driver wdt_driver = {
+ 	.name		= "via_wdt",
+ 	.id_table	= wdt_pci_table,
+ 	.probe		= wdt_probe,
+-	.remove		= __devexit_p(wdt_remove),
++	.remove		= wdt_remove,
+ };
+ 
+ module_pci_driver(wdt_driver);
+diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c
+index e32654efdbb6..05c14e4740c1 100644
+--- a/drivers/watchdog/wdt_pci.c
++++ b/drivers/watchdog/wdt_pci.c
+@@ -736,7 +736,7 @@ static struct pci_driver wdtpci_driver = {
+ 	.name		= "wdt_pci",
+ 	.id_table	= wdtpci_pci_tbl,
+ 	.probe		= wdtpci_init_one,
+-	.remove		= __devexit_p(wdtpci_remove_one),
++	.remove		= wdtpci_remove_one,
+ };
+ 
+ module_pci_driver(wdtpci_driver);
+diff --git a/drivers/watchdog/wm831x_wdt.c b/drivers/watchdog/wm831x_wdt.c
+index 87d66d236c3e..f9c54feb8f1a 100644
+--- a/drivers/watchdog/wm831x_wdt.c
++++ b/drivers/watchdog/wm831x_wdt.c
+@@ -306,7 +306,7 @@ static int __devexit wm831x_wdt_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver wm831x_wdt_driver = {
+ 	.probe = wm831x_wdt_probe,
+-	.remove = __devexit_p(wm831x_wdt_remove),
++	.remove = wm831x_wdt_remove,
+ 	.driver = {
+ 		.name = "wm831x-watchdog",
+ 	},
+diff --git a/drivers/watchdog/wm8350_wdt.c b/drivers/watchdog/wm8350_wdt.c
+index 3c76693447fd..770b6da1ff41 100644
+--- a/drivers/watchdog/wm8350_wdt.c
++++ b/drivers/watchdog/wm8350_wdt.c
+@@ -166,7 +166,7 @@ static int __devexit wm8350_wdt_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver wm8350_wdt_driver = {
+ 	.probe = wm8350_wdt_probe,
+-	.remove = __devexit_p(wm8350_wdt_remove),
++	.remove = wm8350_wdt_remove,
+ 	.driver = {
+ 		.name = "wm8350-wdt",
+ 	},
+diff --git a/drivers/watchdog/xen_wdt.c b/drivers/watchdog/xen_wdt.c
+index e4a25b51165c..99b956fa4ebd 100644
+--- a/drivers/watchdog/xen_wdt.c
++++ b/drivers/watchdog/xen_wdt.c
+@@ -315,7 +315,7 @@ static int xen_wdt_resume(struct platform_device *dev)
+ 
+ static struct platform_driver xen_wdt_driver = {
+ 	.probe          = xen_wdt_probe,
+-	.remove         = __devexit_p(xen_wdt_remove),
++	.remove         = xen_wdt_remove,
+ 	.shutdown       = xen_wdt_shutdown,
+ 	.suspend        = xen_wdt_suspend,
+ 	.resume         = xen_wdt_resume,

commit f90f54b3f3c4d1c9168d5f8e97c6ac5b9ad25f5e
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:06 2012 -0500
+
+    pinctrl: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Jean-Christophe Plagniol-Villard 
+    Cc: Stephen Warren 
+    Cc: Viresh Kumar 
+    Acked-by: Linus Walleij 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c
+index dd52b6a682c2..dd569e17ff41 100644
+--- a/drivers/pinctrl/pinctrl-bcm2835.c
++++ b/drivers/pinctrl/pinctrl-bcm2835.c
+@@ -1042,7 +1042,7 @@ static int __devinit bcm2835_pinctrl_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit bcm2835_pinctrl_remove(struct platform_device *pdev)
++static int bcm2835_pinctrl_remove(struct platform_device *pdev)
+ {
+ 	struct bcm2835_pinctrl *pc = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/pinctrl/pinctrl-imx.c b/drivers/pinctrl/pinctrl-imx.c
+index 63866d95357d..2bd771bcd3c1 100644
+--- a/drivers/pinctrl/pinctrl-imx.c
++++ b/drivers/pinctrl/pinctrl-imx.c
+@@ -611,7 +611,7 @@ int __devinit imx_pinctrl_probe(struct platform_device *pdev,
+ 	return 0;
+ }
+ 
+-int __devexit imx_pinctrl_remove(struct platform_device *pdev)
++int imx_pinctrl_remove(struct platform_device *pdev)
+ {
+ 	struct imx_pinctrl *ipctl = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/pinctrl/pinctrl-mmp2.c b/drivers/pinctrl/pinctrl-mmp2.c
+index a5159a3d67d2..4fbb3db3f1c1 100644
+--- a/drivers/pinctrl/pinctrl-mmp2.c
++++ b/drivers/pinctrl/pinctrl-mmp2.c
+@@ -691,7 +691,7 @@ static int __devinit mmp2_pinmux_probe(struct platform_device *pdev)
+ 	return pxa3xx_pinctrl_register(pdev, &mmp2_info);
+ }
+ 
+-static int __devexit mmp2_pinmux_remove(struct platform_device *pdev)
++static int mmp2_pinmux_remove(struct platform_device *pdev)
+ {
+ 	return pxa3xx_pinctrl_unregister(pdev);
+ }
+diff --git a/drivers/pinctrl/pinctrl-mxs.c b/drivers/pinctrl/pinctrl-mxs.c
+index 4ba4636b6a4a..feef5d6692fa 100644
+--- a/drivers/pinctrl/pinctrl-mxs.c
++++ b/drivers/pinctrl/pinctrl-mxs.c
+@@ -522,7 +522,7 @@ int __devinit mxs_pinctrl_probe(struct platform_device *pdev,
+ }
+ EXPORT_SYMBOL_GPL(mxs_pinctrl_probe);
+ 
+-int __devexit mxs_pinctrl_remove(struct platform_device *pdev)
++int mxs_pinctrl_remove(struct platform_device *pdev)
+ {
+ 	struct mxs_pinctrl_data *d = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/pinctrl/pinctrl-pxa168.c b/drivers/pinctrl/pinctrl-pxa168.c
+index 4abab7858309..cb771e4a6355 100644
+--- a/drivers/pinctrl/pinctrl-pxa168.c
++++ b/drivers/pinctrl/pinctrl-pxa168.c
+@@ -620,7 +620,7 @@ static int __devinit pxa168_pinmux_probe(struct platform_device *pdev)
+ 	return pxa3xx_pinctrl_register(pdev, &pxa168_info);
+ }
+ 
+-static int __devexit pxa168_pinmux_remove(struct platform_device *pdev)
++static int pxa168_pinmux_remove(struct platform_device *pdev)
+ {
+ 	return pxa3xx_pinctrl_unregister(pdev);
+ }
+diff --git a/drivers/pinctrl/pinctrl-pxa910.c b/drivers/pinctrl/pinctrl-pxa910.c
+index ee2c861b734c..5fecd221b830 100644
+--- a/drivers/pinctrl/pinctrl-pxa910.c
++++ b/drivers/pinctrl/pinctrl-pxa910.c
+@@ -976,7 +976,7 @@ static int __devinit pxa910_pinmux_probe(struct platform_device *pdev)
+ 	return pxa3xx_pinctrl_register(pdev, &pxa910_info);
+ }
+ 
+-static int __devexit pxa910_pinmux_remove(struct platform_device *pdev)
++static int pxa910_pinmux_remove(struct platform_device *pdev)
+ {
+ 	return pxa3xx_pinctrl_unregister(pdev);
+ }
+diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
+index 2e7cbb9b0c91..9f70b30a6fd4 100644
+--- a/drivers/pinctrl/pinctrl-single.c
++++ b/drivers/pinctrl/pinctrl-single.c
+@@ -986,7 +986,7 @@ static int __devinit pcs_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit pcs_remove(struct platform_device *pdev)
++static int pcs_remove(struct platform_device *pdev)
+ {
+ 	struct pcs_device *pcs = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c
+index 7da0b371fd65..cb24449a3498 100644
+--- a/drivers/pinctrl/pinctrl-tegra.c
++++ b/drivers/pinctrl/pinctrl-tegra.c
+@@ -758,7 +758,7 @@ int __devinit tegra_pinctrl_probe(struct platform_device *pdev,
+ }
+ EXPORT_SYMBOL_GPL(tegra_pinctrl_probe);
+ 
+-int __devexit tegra_pinctrl_remove(struct platform_device *pdev)
++int tegra_pinctrl_remove(struct platform_device *pdev)
+ {
+ 	struct tegra_pmx *pmx = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/pinctrl/pinctrl-u300.c b/drivers/pinctrl/pinctrl-u300.c
+index 62a739dc655e..ab09972450e5 100644
+--- a/drivers/pinctrl/pinctrl-u300.c
++++ b/drivers/pinctrl/pinctrl-u300.c
+@@ -1166,7 +1166,7 @@ static int __devinit u300_pmx_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit u300_pmx_remove(struct platform_device *pdev)
++static int u300_pmx_remove(struct platform_device *pdev)
+ {
+ 	struct u300_pmx *upmx = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c
+index b1fd6ee33c6c..66cf948589d4 100644
+--- a/drivers/pinctrl/spear/pinctrl-spear.c
++++ b/drivers/pinctrl/spear/pinctrl-spear.c
+@@ -344,7 +344,7 @@ int __devinit spear_pinctrl_probe(struct platform_device *pdev,
+ 	return 0;
+ }
+ 
+-int __devexit spear_pinctrl_remove(struct platform_device *pdev)
++int spear_pinctrl_remove(struct platform_device *pdev)
+ {
+ 	struct spear_pmx *pmx = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/pinctrl/spear/pinctrl-spear.h b/drivers/pinctrl/spear/pinctrl-spear.h
+index d950eb78d939..1914e905456b 100644
+--- a/drivers/pinctrl/spear/pinctrl-spear.h
++++ b/drivers/pinctrl/spear/pinctrl-spear.h
+@@ -138,7 +138,7 @@ struct spear_pmx {
+ void __devinit pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg);
+ int __devinit spear_pinctrl_probe(struct platform_device *pdev,
+ 		struct spear_pinctrl_machdata *machdata);
+-int __devexit spear_pinctrl_remove(struct platform_device *pdev);
++int spear_pinctrl_remove(struct platform_device *pdev);
+ 
+ #define SPEAR_PIN_0_TO_101		\
+ 	PINCTRL_PIN(0, "PLGPIO0"),	\
+diff --git a/drivers/pinctrl/spear/pinctrl-spear1310.c b/drivers/pinctrl/spear/pinctrl-spear1310.c
+index 1df013d2abfb..2c624e12ba96 100644
+--- a/drivers/pinctrl/spear/pinctrl-spear1310.c
++++ b/drivers/pinctrl/spear/pinctrl-spear1310.c
+@@ -2440,7 +2440,7 @@ static int __devinit spear1310_pinctrl_probe(struct platform_device *pdev)
+ 	return spear_pinctrl_probe(pdev, &spear1310_machdata);
+ }
+ 
+-static int __devexit spear1310_pinctrl_remove(struct platform_device *pdev)
++static int spear1310_pinctrl_remove(struct platform_device *pdev)
+ {
+ 	return spear_pinctrl_remove(pdev);
+ }
+diff --git a/drivers/pinctrl/spear/pinctrl-spear1340.c b/drivers/pinctrl/spear/pinctrl-spear1340.c
+index 5ef9801ea084..ed6c25694c89 100644
+--- a/drivers/pinctrl/spear/pinctrl-spear1340.c
++++ b/drivers/pinctrl/spear/pinctrl-spear1340.c
+@@ -1993,7 +1993,7 @@ static int __devinit spear1340_pinctrl_probe(struct platform_device *pdev)
+ 	return spear_pinctrl_probe(pdev, &spear1340_machdata);
+ }
+ 
+-static int __devexit spear1340_pinctrl_remove(struct platform_device *pdev)
++static int spear1340_pinctrl_remove(struct platform_device *pdev)
+ {
+ 	return spear_pinctrl_remove(pdev);
+ }
+diff --git a/drivers/pinctrl/spear/pinctrl-spear300.c b/drivers/pinctrl/spear/pinctrl-spear300.c
+index 6652fcd39fcc..efe29c6a3c8c 100644
+--- a/drivers/pinctrl/spear/pinctrl-spear300.c
++++ b/drivers/pinctrl/spear/pinctrl-spear300.c
+@@ -675,7 +675,7 @@ static int __devinit spear300_pinctrl_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit spear300_pinctrl_remove(struct platform_device *pdev)
++static int spear300_pinctrl_remove(struct platform_device *pdev)
+ {
+ 	return spear_pinctrl_remove(pdev);
+ }
+diff --git a/drivers/pinctrl/spear/pinctrl-spear310.c b/drivers/pinctrl/spear/pinctrl-spear310.c
+index 6066e795d0b3..d8b1fdefd8a8 100644
+--- a/drivers/pinctrl/spear/pinctrl-spear310.c
++++ b/drivers/pinctrl/spear/pinctrl-spear310.c
+@@ -398,7 +398,7 @@ static int __devinit spear310_pinctrl_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit spear310_pinctrl_remove(struct platform_device *pdev)
++static int spear310_pinctrl_remove(struct platform_device *pdev)
+ {
+ 	return spear_pinctrl_remove(pdev);
+ }
+diff --git a/drivers/pinctrl/spear/pinctrl-spear320.c b/drivers/pinctrl/spear/pinctrl-spear320.c
+index d154cba00898..dd7fcaff9591 100644
+--- a/drivers/pinctrl/spear/pinctrl-spear320.c
++++ b/drivers/pinctrl/spear/pinctrl-spear320.c
+@@ -3439,7 +3439,7 @@ static int __devinit spear320_pinctrl_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit spear320_pinctrl_remove(struct platform_device *pdev)
++static int spear320_pinctrl_remove(struct platform_device *pdev)
+ {
+ 	return spear_pinctrl_remove(pdev);
+ }

commit 84db00ba1ef372b3b06b6f75d0522295acb3054d
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:25:13 2012 -0500
+
+    pinctrl: remove use of __devinitconst
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitconst is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Stephen Warren 
+    Acked-by: Barry Song 
+    Acked-by: Linus Walleij 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c
+index 7e9be18ec2d2..dd52b6a682c2 100644
+--- a/drivers/pinctrl/pinctrl-bcm2835.c
++++ b/drivers/pinctrl/pinctrl-bcm2835.c
+@@ -372,7 +372,7 @@ static int bcm2835_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+ 	return irq_linear_revmap(pc->irq_domain, offset);
+ }
+ 
+-static struct gpio_chip bcm2835_gpio_chip __devinitconst = {
++static struct gpio_chip bcm2835_gpio_chip = {
+ 	.label = MODULE_NAME,
+ 	.owner = THIS_MODULE,
+ 	.request = bcm2835_gpio_request,
+@@ -931,7 +931,7 @@ static struct pinctrl_desc bcm2835_pinctrl_desc = {
+ 	.owner = THIS_MODULE,
+ };
+ 
+-static struct pinctrl_gpio_range bcm2835_pinctrl_gpio_range __devinitconst = {
++static struct pinctrl_gpio_range bcm2835_pinctrl_gpio_range = {
+ 	.name = MODULE_NAME,
+ 	.npins = BCM2835_NUM_GPIOS,
+ };
+@@ -1052,7 +1052,7 @@ static int __devexit bcm2835_pinctrl_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static struct of_device_id bcm2835_pinctrl_match[] __devinitconst = {
++static struct of_device_id bcm2835_pinctrl_match[] = {
+ 	{ .compatible = "brcm,bcm2835-gpio" },
+ 	{}
+ };
+diff --git a/drivers/pinctrl/pinctrl-sirf.c b/drivers/pinctrl/pinctrl-sirf.c
+index 9ecacf3d0a75..28922c32ad5d 100644
+--- a/drivers/pinctrl/pinctrl-sirf.c
++++ b/drivers/pinctrl/pinctrl-sirf.c
+@@ -1285,7 +1285,7 @@ static int __devinit sirfsoc_pinmux_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static const struct of_device_id pinmux_ids[] __devinitconst = {
++static const struct of_device_id pinmux_ids[] = {
+ 	{ .compatible = "sirf,prima2-pinctrl" },
+ 	{}
+ };

commit 99688ed7744614373e9a13187179319afe3c8db2
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:24:27 2012 -0500
+
+    pinctrl: remove use of __devinitdata
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitdata is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Jean-Christophe PLAGNIOL-VILLARD 
+    Cc: Viresh Kumar 
+    Acked-by: Linus Walleij 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/pinctrl/pinctrl-imx23.c b/drivers/pinctrl/pinctrl-imx23.c
+index 67e1b3bb70da..04364f7822b7 100644
+--- a/drivers/pinctrl/pinctrl-imx23.c
++++ b/drivers/pinctrl/pinctrl-imx23.c
+@@ -272,7 +272,7 @@ static int __devinit imx23_pinctrl_probe(struct platform_device *pdev)
+ 	return mxs_pinctrl_probe(pdev, &imx23_pinctrl_data);
+ }
+ 
+-static struct of_device_id imx23_pinctrl_of_match[] __devinitdata = {
++static struct of_device_id imx23_pinctrl_of_match[] = {
+ 	{ .compatible = "fsl,imx23-pinctrl", },
+ 	{ /* sentinel */ }
+ };
+diff --git a/drivers/pinctrl/pinctrl-imx28.c b/drivers/pinctrl/pinctrl-imx28.c
+index feeb4b9f802a..e1af2ba89004 100644
+--- a/drivers/pinctrl/pinctrl-imx28.c
++++ b/drivers/pinctrl/pinctrl-imx28.c
+@@ -388,7 +388,7 @@ static int __devinit imx28_pinctrl_probe(struct platform_device *pdev)
+ 	return mxs_pinctrl_probe(pdev, &imx28_pinctrl_data);
+ }
+ 
+-static struct of_device_id imx28_pinctrl_of_match[] __devinitdata = {
++static struct of_device_id imx28_pinctrl_of_match[] = {
+ 	{ .compatible = "fsl,imx28-pinctrl", },
+ 	{ /* sentinel */ }
+ };
+diff --git a/drivers/pinctrl/pinctrl-imx35.c b/drivers/pinctrl/pinctrl-imx35.c
+index a88d087ac0dd..1dbf5278acec 100644
+--- a/drivers/pinctrl/pinctrl-imx35.c
++++ b/drivers/pinctrl/pinctrl-imx35.c
+@@ -1559,7 +1559,7 @@ static struct imx_pinctrl_soc_info imx35_pinctrl_info = {
+ 	.npin_regs = ARRAY_SIZE(imx35_pin_regs),
+ };
+ 
+-static struct of_device_id imx35_pinctrl_of_match[] __devinitdata = {
++static struct of_device_id imx35_pinctrl_of_match[] = {
+ 	{ .compatible = "fsl,imx35-iomuxc", },
+ 	{ /* sentinel */ }
+ };
+diff --git a/drivers/pinctrl/pinctrl-imx51.c b/drivers/pinctrl/pinctrl-imx51.c
+index 5c489487a054..131216558a7b 100644
+--- a/drivers/pinctrl/pinctrl-imx51.c
++++ b/drivers/pinctrl/pinctrl-imx51.c
+@@ -1286,7 +1286,7 @@ static struct imx_pinctrl_soc_info imx51_pinctrl_info = {
+ 	.npin_regs = ARRAY_SIZE(imx51_pin_regs),
+ };
+ 
+-static struct of_device_id imx51_pinctrl_of_match[] __devinitdata = {
++static struct of_device_id imx51_pinctrl_of_match[] = {
+ 	{ .compatible = "fsl,imx51-iomuxc", },
+ 	{ /* sentinel */ }
+ };
+diff --git a/drivers/pinctrl/pinctrl-imx53.c b/drivers/pinctrl/pinctrl-imx53.c
+index 8e5c15f70895..ec4048691775 100644
+--- a/drivers/pinctrl/pinctrl-imx53.c
++++ b/drivers/pinctrl/pinctrl-imx53.c
+@@ -1613,7 +1613,7 @@ static struct imx_pinctrl_soc_info imx53_pinctrl_info = {
+ 	.npin_regs = ARRAY_SIZE(imx53_pin_regs),
+ };
+ 
+-static struct of_device_id imx53_pinctrl_of_match[] __devinitdata = {
++static struct of_device_id imx53_pinctrl_of_match[] = {
+ 	{ .compatible = "fsl,imx53-iomuxc", },
+ 	{ /* sentinel */ }
+ };
+diff --git a/drivers/pinctrl/pinctrl-imx6q.c b/drivers/pinctrl/pinctrl-imx6q.c
+index 831dae675330..844ab13c93a3 100644
+--- a/drivers/pinctrl/pinctrl-imx6q.c
++++ b/drivers/pinctrl/pinctrl-imx6q.c
+@@ -2297,7 +2297,7 @@ static struct imx_pinctrl_soc_info imx6q_pinctrl_info = {
+ 	.npin_regs = ARRAY_SIZE(imx6q_pin_regs),
+ };
+ 
+-static struct of_device_id imx6q_pinctrl_of_match[] __devinitdata = {
++static struct of_device_id imx6q_pinctrl_of_match[] = {
+ 	{ .compatible = "fsl,imx6q-iomuxc", },
+ 	{ /* sentinel */ }
+ };
+diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
+index a0d9584a08f7..2e7cbb9b0c91 100644
+--- a/drivers/pinctrl/pinctrl-single.c
++++ b/drivers/pinctrl/pinctrl-single.c
+@@ -998,7 +998,7 @@ static int __devexit pcs_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static struct of_device_id pcs_of_match[] __devinitdata = {
++static struct of_device_id pcs_of_match[] = {
+ 	{ .compatible = DRIVER_NAME, },
+ 	{ },
+ };
+diff --git a/drivers/pinctrl/pinctrl-tegra20.c b/drivers/pinctrl/pinctrl-tegra20.c
+index e749dedd8edb..1524bfd66602 100644
+--- a/drivers/pinctrl/pinctrl-tegra20.c
++++ b/drivers/pinctrl/pinctrl-tegra20.c
+@@ -2861,7 +2861,7 @@ static int __devinit tegra20_pinctrl_probe(struct platform_device *pdev)
+ 	return tegra_pinctrl_probe(pdev, &tegra20_pinctrl);
+ }
+ 
+-static struct of_device_id tegra20_pinctrl_of_match[] __devinitdata = {
++static struct of_device_id tegra20_pinctrl_of_match[] = {
+ 	{ .compatible = "nvidia,tegra20-pinmux", },
+ 	{ },
+ };
+diff --git a/drivers/pinctrl/pinctrl-tegra30.c b/drivers/pinctrl/pinctrl-tegra30.c
+index dc1e229b05fd..cf579ebf346f 100644
+--- a/drivers/pinctrl/pinctrl-tegra30.c
++++ b/drivers/pinctrl/pinctrl-tegra30.c
+@@ -3727,7 +3727,7 @@ static int __devinit tegra30_pinctrl_probe(struct platform_device *pdev)
+ 	return tegra_pinctrl_probe(pdev, &tegra30_pinctrl);
+ }
+ 
+-static struct of_device_id tegra30_pinctrl_of_match[] __devinitdata = {
++static struct of_device_id tegra30_pinctrl_of_match[] = {
+ 	{ .compatible = "nvidia,tegra30-pinmux", },
+ 	{ },
+ };
+diff --git a/drivers/pinctrl/spear/pinctrl-spear1310.c b/drivers/pinctrl/spear/pinctrl-spear1310.c
+index c256777bb957..1df013d2abfb 100644
+--- a/drivers/pinctrl/spear/pinctrl-spear1310.c
++++ b/drivers/pinctrl/spear/pinctrl-spear1310.c
+@@ -2428,7 +2428,7 @@ static struct spear_pinctrl_machdata spear1310_machdata = {
+ 	.modes_supported = false,
+ };
+ 
+-static struct of_device_id spear1310_pinctrl_of_match[] __devinitdata = {
++static struct of_device_id spear1310_pinctrl_of_match[] = {
+ 	{
+ 		.compatible = "st,spear1310-pinmux",
+ 	},
+diff --git a/drivers/pinctrl/spear/pinctrl-spear1340.c b/drivers/pinctrl/spear/pinctrl-spear1340.c
+index b9f72948c05d..5ef9801ea084 100644
+--- a/drivers/pinctrl/spear/pinctrl-spear1340.c
++++ b/drivers/pinctrl/spear/pinctrl-spear1340.c
+@@ -1981,7 +1981,7 @@ static struct spear_pinctrl_machdata spear1340_machdata = {
+ 	.modes_supported = false,
+ };
+ 
+-static struct of_device_id spear1340_pinctrl_of_match[] __devinitdata = {
++static struct of_device_id spear1340_pinctrl_of_match[] = {
+ 	{
+ 		.compatible = "st,spear1340-pinmux",
+ 	},
+diff --git a/drivers/pinctrl/spear/pinctrl-spear300.c b/drivers/pinctrl/spear/pinctrl-spear300.c
+index 55fddb2c5a6e..6652fcd39fcc 100644
+--- a/drivers/pinctrl/spear/pinctrl-spear300.c
++++ b/drivers/pinctrl/spear/pinctrl-spear300.c
+@@ -646,7 +646,7 @@ static struct spear_function *spear300_functions[] = {
+ 	&gpio1_function,
+ };
+ 
+-static struct of_device_id spear300_pinctrl_of_match[] __devinitdata = {
++static struct of_device_id spear300_pinctrl_of_match[] = {
+ 	{
+ 		.compatible = "st,spear300-pinmux",
+ 	},
+diff --git a/drivers/pinctrl/spear/pinctrl-spear310.c b/drivers/pinctrl/spear/pinctrl-spear310.c
+index 53b27ca5f22d..6066e795d0b3 100644
+--- a/drivers/pinctrl/spear/pinctrl-spear310.c
++++ b/drivers/pinctrl/spear/pinctrl-spear310.c
+@@ -371,7 +371,7 @@ static struct spear_function *spear310_functions[] = {
+ 	&tdm_function,
+ };
+ 
+-static struct of_device_id spear310_pinctrl_of_match[] __devinitdata = {
++static struct of_device_id spear310_pinctrl_of_match[] = {
+ 	{
+ 		.compatible = "st,spear310-pinmux",
+ 	},
+diff --git a/drivers/pinctrl/spear/pinctrl-spear320.c b/drivers/pinctrl/spear/pinctrl-spear320.c
+index 92df44e6eb39..d154cba00898 100644
+--- a/drivers/pinctrl/spear/pinctrl-spear320.c
++++ b/drivers/pinctrl/spear/pinctrl-spear320.c
+@@ -3410,7 +3410,7 @@ static struct spear_function *spear320_functions[] = {
+ 	&i2c2_function,
+ };
+ 
+-static struct of_device_id spear320_pinctrl_of_match[] __devinitdata = {
++static struct of_device_id spear320_pinctrl_of_match[] = {
+ 	{
+ 		.compatible = "st,spear320-pinmux",
+ 	},

commit 2a36f08636665d63ec2bfa49a815509e71d44eba
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:27 2012 -0500
+
+    pinctrl: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Jean-Christophe PLAGNIOL-VILLARD 
+    Acked-by: Viresh Kumar 
+    Acked-by: Linus Walleij 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/pinctrl/pinctrl-imx23.c b/drivers/pinctrl/pinctrl-imx23.c
+index 3674d877ed7c..67e1b3bb70da 100644
+--- a/drivers/pinctrl/pinctrl-imx23.c
++++ b/drivers/pinctrl/pinctrl-imx23.c
+@@ -285,7 +285,7 @@ static struct platform_driver imx23_pinctrl_driver = {
+ 		.of_match_table = imx23_pinctrl_of_match,
+ 	},
+ 	.probe = imx23_pinctrl_probe,
+-	.remove = __devexit_p(mxs_pinctrl_remove),
++	.remove = mxs_pinctrl_remove,
+ };
+ 
+ static int __init imx23_pinctrl_init(void)
+diff --git a/drivers/pinctrl/pinctrl-imx28.c b/drivers/pinctrl/pinctrl-imx28.c
+index 0f5b2122b1ba..feeb4b9f802a 100644
+--- a/drivers/pinctrl/pinctrl-imx28.c
++++ b/drivers/pinctrl/pinctrl-imx28.c
+@@ -401,7 +401,7 @@ static struct platform_driver imx28_pinctrl_driver = {
+ 		.of_match_table = imx28_pinctrl_of_match,
+ 	},
+ 	.probe = imx28_pinctrl_probe,
+-	.remove = __devexit_p(mxs_pinctrl_remove),
++	.remove = mxs_pinctrl_remove,
+ };
+ 
+ static int __init imx28_pinctrl_init(void)
+diff --git a/drivers/pinctrl/pinctrl-imx35.c b/drivers/pinctrl/pinctrl-imx35.c
+index 82f109e26f27..a88d087ac0dd 100644
+--- a/drivers/pinctrl/pinctrl-imx35.c
++++ b/drivers/pinctrl/pinctrl-imx35.c
+@@ -1576,7 +1576,7 @@ static struct platform_driver imx35_pinctrl_driver = {
+ 		.of_match_table = of_match_ptr(imx35_pinctrl_of_match),
+ 	},
+ 	.probe = imx35_pinctrl_probe,
+-	.remove = __devexit_p(imx_pinctrl_remove),
++	.remove = imx_pinctrl_remove,
+ };
+ 
+ static int __init imx35_pinctrl_init(void)
+diff --git a/drivers/pinctrl/pinctrl-imx51.c b/drivers/pinctrl/pinctrl-imx51.c
+index fb8468966779..5c489487a054 100644
+--- a/drivers/pinctrl/pinctrl-imx51.c
++++ b/drivers/pinctrl/pinctrl-imx51.c
+@@ -1303,7 +1303,7 @@ static struct platform_driver imx51_pinctrl_driver = {
+ 		.of_match_table = of_match_ptr(imx51_pinctrl_of_match),
+ 	},
+ 	.probe = imx51_pinctrl_probe,
+-	.remove = __devexit_p(imx_pinctrl_remove),
++	.remove = imx_pinctrl_remove,
+ };
+ 
+ static int __init imx51_pinctrl_init(void)
+diff --git a/drivers/pinctrl/pinctrl-imx53.c b/drivers/pinctrl/pinctrl-imx53.c
+index 783feb1ce064..8e5c15f70895 100644
+--- a/drivers/pinctrl/pinctrl-imx53.c
++++ b/drivers/pinctrl/pinctrl-imx53.c
+@@ -1630,7 +1630,7 @@ static struct platform_driver imx53_pinctrl_driver = {
+ 		.of_match_table = of_match_ptr(imx53_pinctrl_of_match),
+ 	},
+ 	.probe = imx53_pinctrl_probe,
+-	.remove = __devexit_p(imx_pinctrl_remove),
++	.remove = imx_pinctrl_remove,
+ };
+ 
+ static int __init imx53_pinctrl_init(void)
+diff --git a/drivers/pinctrl/pinctrl-imx6q.c b/drivers/pinctrl/pinctrl-imx6q.c
+index e9bf71fbedca..831dae675330 100644
+--- a/drivers/pinctrl/pinctrl-imx6q.c
++++ b/drivers/pinctrl/pinctrl-imx6q.c
+@@ -2314,7 +2314,7 @@ static struct platform_driver imx6q_pinctrl_driver = {
+ 		.of_match_table = of_match_ptr(imx6q_pinctrl_of_match),
+ 	},
+ 	.probe = imx6q_pinctrl_probe,
+-	.remove = __devexit_p(imx_pinctrl_remove),
++	.remove = imx_pinctrl_remove,
+ };
+ 
+ static int __init imx6q_pinctrl_init(void)
+diff --git a/drivers/pinctrl/pinctrl-mmp2.c b/drivers/pinctrl/pinctrl-mmp2.c
+index 2cfed552bbe4..a5159a3d67d2 100644
+--- a/drivers/pinctrl/pinctrl-mmp2.c
++++ b/drivers/pinctrl/pinctrl-mmp2.c
+@@ -702,7 +702,7 @@ static struct platform_driver mmp2_pinmux_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe	= mmp2_pinmux_probe,
+-	.remove	= __devexit_p(mmp2_pinmux_remove),
++	.remove	= mmp2_pinmux_remove,
+ };
+ 
+ static int __init mmp2_pinmux_init(void)
+diff --git a/drivers/pinctrl/pinctrl-pxa168.c b/drivers/pinctrl/pinctrl-pxa168.c
+index c1997fa7f28c..4abab7858309 100644
+--- a/drivers/pinctrl/pinctrl-pxa168.c
++++ b/drivers/pinctrl/pinctrl-pxa168.c
+@@ -631,7 +631,7 @@ static struct platform_driver pxa168_pinmux_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe	= pxa168_pinmux_probe,
+-	.remove	= __devexit_p(pxa168_pinmux_remove),
++	.remove	= pxa168_pinmux_remove,
+ };
+ 
+ static int __init pxa168_pinmux_init(void)
+diff --git a/drivers/pinctrl/pinctrl-pxa910.c b/drivers/pinctrl/pinctrl-pxa910.c
+index c72ab4b9cc8c..ee2c861b734c 100644
+--- a/drivers/pinctrl/pinctrl-pxa910.c
++++ b/drivers/pinctrl/pinctrl-pxa910.c
+@@ -987,7 +987,7 @@ static struct platform_driver pxa910_pinmux_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe	= pxa910_pinmux_probe,
+-	.remove	= __devexit_p(pxa910_pinmux_remove),
++	.remove	= pxa910_pinmux_remove,
+ };
+ 
+ static int __init pxa910_pinmux_init(void)
+diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
+index 726a729a2ec9..a0d9584a08f7 100644
+--- a/drivers/pinctrl/pinctrl-single.c
++++ b/drivers/pinctrl/pinctrl-single.c
+@@ -1006,7 +1006,7 @@ MODULE_DEVICE_TABLE(of, pcs_of_match);
+ 
+ static struct platform_driver pcs_driver = {
+ 	.probe		= pcs_probe,
+-	.remove		= __devexit_p(pcs_remove),
++	.remove		= pcs_remove,
+ 	.driver = {
+ 		.owner		= THIS_MODULE,
+ 		.name		= DRIVER_NAME,
+diff --git a/drivers/pinctrl/pinctrl-tegra20.c b/drivers/pinctrl/pinctrl-tegra20.c
+index a74f9a568536..e749dedd8edb 100644
+--- a/drivers/pinctrl/pinctrl-tegra20.c
++++ b/drivers/pinctrl/pinctrl-tegra20.c
+@@ -2873,7 +2873,7 @@ static struct platform_driver tegra20_pinctrl_driver = {
+ 		.of_match_table = tegra20_pinctrl_of_match,
+ 	},
+ 	.probe = tegra20_pinctrl_probe,
+-	.remove = __devexit_p(tegra_pinctrl_remove),
++	.remove = tegra_pinctrl_remove,
+ };
+ 
+ static int __init tegra20_pinctrl_init(void)
+diff --git a/drivers/pinctrl/pinctrl-tegra30.c b/drivers/pinctrl/pinctrl-tegra30.c
+index 7894f14c7059..dc1e229b05fd 100644
+--- a/drivers/pinctrl/pinctrl-tegra30.c
++++ b/drivers/pinctrl/pinctrl-tegra30.c
+@@ -3739,7 +3739,7 @@ static struct platform_driver tegra30_pinctrl_driver = {
+ 		.of_match_table = tegra30_pinctrl_of_match,
+ 	},
+ 	.probe = tegra30_pinctrl_probe,
+-	.remove = __devexit_p(tegra_pinctrl_remove),
++	.remove = tegra_pinctrl_remove,
+ };
+ 
+ static int __init tegra30_pinctrl_init(void)
+diff --git a/drivers/pinctrl/pinctrl-u300.c b/drivers/pinctrl/pinctrl-u300.c
+index 309f5b9a70ec..62a739dc655e 100644
+--- a/drivers/pinctrl/pinctrl-u300.c
++++ b/drivers/pinctrl/pinctrl-u300.c
+@@ -1184,7 +1184,7 @@ static struct platform_driver u300_pmx_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = u300_pmx_probe,
+-	.remove = __devexit_p(u300_pmx_remove),
++	.remove = u300_pmx_remove,
+ };
+ 
+ static int __init u300_pmx_init(void)
+diff --git a/drivers/pinctrl/spear/pinctrl-spear1310.c b/drivers/pinctrl/spear/pinctrl-spear1310.c
+index 0436fc7895d6..c256777bb957 100644
+--- a/drivers/pinctrl/spear/pinctrl-spear1310.c
++++ b/drivers/pinctrl/spear/pinctrl-spear1310.c
+@@ -2452,7 +2452,7 @@ static struct platform_driver spear1310_pinctrl_driver = {
+ 		.of_match_table = spear1310_pinctrl_of_match,
+ 	},
+ 	.probe = spear1310_pinctrl_probe,
+-	.remove = __devexit_p(spear1310_pinctrl_remove),
++	.remove = spear1310_pinctrl_remove,
+ };
+ 
+ static int __init spear1310_pinctrl_init(void)
+diff --git a/drivers/pinctrl/spear/pinctrl-spear1340.c b/drivers/pinctrl/spear/pinctrl-spear1340.c
+index 0606b8cf3f2c..b9f72948c05d 100644
+--- a/drivers/pinctrl/spear/pinctrl-spear1340.c
++++ b/drivers/pinctrl/spear/pinctrl-spear1340.c
+@@ -2005,7 +2005,7 @@ static struct platform_driver spear1340_pinctrl_driver = {
+ 		.of_match_table = spear1340_pinctrl_of_match,
+ 	},
+ 	.probe = spear1340_pinctrl_probe,
+-	.remove = __devexit_p(spear1340_pinctrl_remove),
++	.remove = spear1340_pinctrl_remove,
+ };
+ 
+ static int __init spear1340_pinctrl_init(void)
+diff --git a/drivers/pinctrl/spear/pinctrl-spear300.c b/drivers/pinctrl/spear/pinctrl-spear300.c
+index 4dfc2849b172..55fddb2c5a6e 100644
+--- a/drivers/pinctrl/spear/pinctrl-spear300.c
++++ b/drivers/pinctrl/spear/pinctrl-spear300.c
+@@ -687,7 +687,7 @@ static struct platform_driver spear300_pinctrl_driver = {
+ 		.of_match_table = spear300_pinctrl_of_match,
+ 	},
+ 	.probe = spear300_pinctrl_probe,
+-	.remove = __devexit_p(spear300_pinctrl_remove),
++	.remove = spear300_pinctrl_remove,
+ };
+ 
+ static int __init spear300_pinctrl_init(void)
+diff --git a/drivers/pinctrl/spear/pinctrl-spear310.c b/drivers/pinctrl/spear/pinctrl-spear310.c
+index 96883693fb7e..53b27ca5f22d 100644
+--- a/drivers/pinctrl/spear/pinctrl-spear310.c
++++ b/drivers/pinctrl/spear/pinctrl-spear310.c
+@@ -410,7 +410,7 @@ static struct platform_driver spear310_pinctrl_driver = {
+ 		.of_match_table = spear310_pinctrl_of_match,
+ 	},
+ 	.probe = spear310_pinctrl_probe,
+-	.remove = __devexit_p(spear310_pinctrl_remove),
++	.remove = spear310_pinctrl_remove,
+ };
+ 
+ static int __init spear310_pinctrl_init(void)
+diff --git a/drivers/pinctrl/spear/pinctrl-spear320.c b/drivers/pinctrl/spear/pinctrl-spear320.c
+index ca47b0e50780..92df44e6eb39 100644
+--- a/drivers/pinctrl/spear/pinctrl-spear320.c
++++ b/drivers/pinctrl/spear/pinctrl-spear320.c
+@@ -3451,7 +3451,7 @@ static struct platform_driver spear320_pinctrl_driver = {
+ 		.of_match_table = spear320_pinctrl_of_match,
+ 	},
+ 	.probe = spear320_pinctrl_probe,
+-	.remove = __devexit_p(spear320_pinctrl_remove),
++	.remove = spear320_pinctrl_remove,
+ };
+ 
+ static int __init spear320_pinctrl_init(void)

commit 281dfd0b6ed5403f5b9b1669f2a37a4f8cfc11c1
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:25:51 2012 -0500
+
+    hwmon: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hans de Goede 
+    Cc: Jean Delvare 
+    Cc: Alistair John Strachan 
+    Cc: Fenghua Yu 
+    Cc: Juerg Haefliger 
+    Cc: Andreas Herrmann 
+    Cc: Clemens Ladisch 
+    Cc: Rudolf Marek 
+    Cc: Jim Cromie 
+    Cc: "Mark M. Hoffman" 
+    Cc: Roger Lucas 
+    Acked-by: Guenter Roeck 
+    Acked-by: Mark Brown 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c
+index 700d5e0442ea..6119ff8e8c87 100644
+--- a/drivers/hwmon/abituguru.c
++++ b/drivers/hwmon/abituguru.c
+@@ -1434,7 +1434,7 @@ static int abituguru_probe(struct platform_device *pdev)
+ 	return res;
+ }
+ 
+-static int __devexit abituguru_remove(struct platform_device *pdev)
++static int abituguru_remove(struct platform_device *pdev)
+ {
+ 	int i;
+ 	struct abituguru_data *data = platform_get_drvdata(pdev);
+diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c
+index b8d0942a9872..205327d33c4d 100644
+--- a/drivers/hwmon/abituguru3.c
++++ b/drivers/hwmon/abituguru3.c
+@@ -1072,7 +1072,7 @@ static int abituguru3_probe(struct platform_device *pdev)
+ 	return res;
+ }
+ 
+-static int __devexit abituguru3_remove(struct platform_device *pdev)
++static int abituguru3_remove(struct platform_device *pdev)
+ {
+ 	int i;
+ 	struct abituguru3_data *data = platform_get_drvdata(pdev);
+diff --git a/drivers/hwmon/ad7314.c b/drivers/hwmon/ad7314.c
+index defd34b04629..a57584d28a40 100644
+--- a/drivers/hwmon/ad7314.c
++++ b/drivers/hwmon/ad7314.c
+@@ -135,7 +135,7 @@ static int ad7314_probe(struct spi_device *spi_dev)
+ 	return ret;
+ }
+ 
+-static int __devexit ad7314_remove(struct spi_device *spi_dev)
++static int ad7314_remove(struct spi_device *spi_dev)
+ {
+ 	struct ad7314_data *chip = dev_get_drvdata(&spi_dev->dev);
+ 
+diff --git a/drivers/hwmon/ad7414.c b/drivers/hwmon/ad7414.c
+index 20276ca37ed8..f3a5d4764eb9 100644
+--- a/drivers/hwmon/ad7414.c
++++ b/drivers/hwmon/ad7414.c
+@@ -226,7 +226,7 @@ static int ad7414_probe(struct i2c_client *client,
+ 	return err;
+ }
+ 
+-static int __devexit ad7414_remove(struct i2c_client *client)
++static int ad7414_remove(struct i2c_client *client)
+ {
+ 	struct ad7414_data *data = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/hwmon/adcxx.c b/drivers/hwmon/adcxx.c
+index ecc1e6c5fa9f..751b1f0264a4 100644
+--- a/drivers/hwmon/adcxx.c
++++ b/drivers/hwmon/adcxx.c
+@@ -208,7 +208,7 @@ static int adcxx_probe(struct spi_device *spi)
+ 	return status;
+ }
+ 
+-static int __devexit adcxx_remove(struct spi_device *spi)
++static int adcxx_remove(struct spi_device *spi)
+ {
+ 	struct adcxx *adc = spi_get_drvdata(spi);
+ 	int i;
+diff --git a/drivers/hwmon/ads7871.c b/drivers/hwmon/ads7871.c
+index 41a7837585fc..a79875986f91 100644
+--- a/drivers/hwmon/ads7871.c
++++ b/drivers/hwmon/ads7871.c
+@@ -225,7 +225,7 @@ static int ads7871_probe(struct spi_device *spi)
+ 	return err;
+ }
+ 
+-static int __devexit ads7871_remove(struct spi_device *spi)
++static int ads7871_remove(struct spi_device *spi)
+ {
+ 	struct ads7871_data *pdata = spi_get_drvdata(spi);
+ 
+diff --git a/drivers/hwmon/adt7411.c b/drivers/hwmon/adt7411.c
+index 68a5da715662..34ff03abb50b 100644
+--- a/drivers/hwmon/adt7411.c
++++ b/drivers/hwmon/adt7411.c
+@@ -317,7 +317,7 @@ static int adt7411_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit adt7411_remove(struct i2c_client *client)
++static int adt7411_remove(struct i2c_client *client)
+ {
+ 	struct adt7411_data *data = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
+index 65a374631995..001e22c60463 100644
+--- a/drivers/hwmon/coretemp.c
++++ b/drivers/hwmon/coretemp.c
+@@ -586,7 +586,7 @@ static int coretemp_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit coretemp_remove(struct platform_device *pdev)
++static int coretemp_remove(struct platform_device *pdev)
+ {
+ 	struct platform_data *pdata = platform_get_drvdata(pdev);
+ 	int i;
+diff --git a/drivers/hwmon/da9052-hwmon.c b/drivers/hwmon/da9052-hwmon.c
+index d3206e341de2..aca7f0c7ff79 100644
+--- a/drivers/hwmon/da9052-hwmon.c
++++ b/drivers/hwmon/da9052-hwmon.c
+@@ -316,7 +316,7 @@ static int da9052_hwmon_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit da9052_hwmon_remove(struct platform_device *pdev)
++static int da9052_hwmon_remove(struct platform_device *pdev)
+ {
+ 	struct da9052_hwmon *hwmon = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c
+index aa6a493731bf..7430f70ae452 100644
+--- a/drivers/hwmon/dme1737.c
++++ b/drivers/hwmon/dme1737.c
+@@ -2718,7 +2718,7 @@ static int dme1737_isa_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit dme1737_isa_remove(struct platform_device *pdev)
++static int dme1737_isa_remove(struct platform_device *pdev)
+ {
+ 	struct dme1737_data *data = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c
+index 0c8426eea6a6..a9816979c5de 100644
+--- a/drivers/hwmon/f71805f.c
++++ b/drivers/hwmon/f71805f.c
+@@ -1490,7 +1490,7 @@ static int f71805f_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit f71805f_remove(struct platform_device *pdev)
++static int f71805f_remove(struct platform_device *pdev)
+ {
+ 	struct f71805f_data *data = platform_get_drvdata(pdev);
+ 	int i;
+diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c
+index 4eca29850286..5cec685f1b79 100644
+--- a/drivers/hwmon/fam15h_power.c
++++ b/drivers/hwmon/fam15h_power.c
+@@ -235,7 +235,7 @@ static int fam15h_power_probe(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit fam15h_power_remove(struct pci_dev *pdev)
++static void fam15h_power_remove(struct pci_dev *pdev)
+ {
+ 	struct device *dev;
+ 	struct fam15h_power_data *data;
+diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c
+index 0f46cca6179a..4e04c1228e51 100644
+--- a/drivers/hwmon/gpio-fan.c
++++ b/drivers/hwmon/gpio-fan.c
+@@ -581,7 +581,7 @@ static int gpio_fan_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit gpio_fan_remove(struct platform_device *pdev)
++static int gpio_fan_remove(struct platform_device *pdev)
+ {
+ 	struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/hwmon/hih6130.c b/drivers/hwmon/hih6130.c
+index 5c65aef095ca..2dc37c7c6947 100644
+--- a/drivers/hwmon/hih6130.c
++++ b/drivers/hwmon/hih6130.c
+@@ -263,7 +263,7 @@ static int hih6130_probe(struct i2c_client *client,
+  * hih6130_remove() - remove device
+  * @client: I2C client device
+  */
+-static int __devexit hih6130_remove(struct i2c_client *client)
++static int hih6130_remove(struct i2c_client *client)
+ {
+ 	struct hih6130 *hih6130 = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c
+index f3bc723c930c..b87c2ccee06b 100644
+--- a/drivers/hwmon/i5k_amb.c
++++ b/drivers/hwmon/i5k_amb.c
+@@ -564,7 +564,7 @@ static int i5k_amb_probe(struct platform_device *pdev)
+ 	return res;
+ }
+ 
+-static int __devexit i5k_amb_remove(struct platform_device *pdev)
++static int i5k_amb_remove(struct platform_device *pdev)
+ {
+ 	int i;
+ 	struct i5k_amb_data *data = platform_get_drvdata(pdev);
+diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
+index 3a4da44f704f..d32aa354cbdf 100644
+--- a/drivers/hwmon/it87.c
++++ b/drivers/hwmon/it87.c
+@@ -428,7 +428,7 @@ static inline int has_old_autopwm(const struct it87_data *data)
+ }
+ 
+ static int it87_probe(struct platform_device *pdev);
+-static int __devexit it87_remove(struct platform_device *pdev);
++static int it87_remove(struct platform_device *pdev);
+ 
+ static int it87_read_value(struct it87_data *data, u8 reg);
+ static void it87_write_value(struct it87_data *data, u8 reg, u8 value);
+@@ -2158,7 +2158,7 @@ static int it87_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit it87_remove(struct platform_device *pdev)
++static int it87_remove(struct platform_device *pdev)
+ {
+ 	struct it87_data *data = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/hwmon/jz4740-hwmon.c b/drivers/hwmon/jz4740-hwmon.c
+index b944d615944b..e0d66b9590ab 100644
+--- a/drivers/hwmon/jz4740-hwmon.c
++++ b/drivers/hwmon/jz4740-hwmon.c
+@@ -172,7 +172,7 @@ static int jz4740_hwmon_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit jz4740_hwmon_remove(struct platform_device *pdev)
++static int jz4740_hwmon_remove(struct platform_device *pdev)
+ {
+ 	struct jz4740_hwmon *hwmon = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c
+index da8acda48ab0..e3b037c73a7e 100644
+--- a/drivers/hwmon/k10temp.c
++++ b/drivers/hwmon/k10temp.c
+@@ -192,7 +192,7 @@ static int k10temp_probe(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit k10temp_remove(struct pci_dev *pdev)
++static void k10temp_remove(struct pci_dev *pdev)
+ {
+ 	hwmon_device_unregister(pci_get_drvdata(pdev));
+ 	device_remove_file(&pdev->dev, &dev_attr_name);
+diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c
+index 8c46753158df..9f3c0aeacdb9 100644
+--- a/drivers/hwmon/k8temp.c
++++ b/drivers/hwmon/k8temp.c
+@@ -304,7 +304,7 @@ static int k8temp_probe(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit k8temp_remove(struct pci_dev *pdev)
++static void k8temp_remove(struct pci_dev *pdev)
+ {
+ 	struct k8temp_data *data = pci_get_drvdata(pdev);
+ 
+diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c
+index d5f006e67a51..016efa26ba7c 100644
+--- a/drivers/hwmon/lm70.c
++++ b/drivers/hwmon/lm70.c
+@@ -178,7 +178,7 @@ static int lm70_probe(struct spi_device *spi)
+ 	return status;
+ }
+ 
+-static int __devexit lm70_remove(struct spi_device *spi)
++static int lm70_remove(struct spi_device *spi)
+ {
+ 	struct lm70 *p_lm70 = spi_get_drvdata(spi);
+ 
+diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
+index 181d756badc5..53d6ee8ffa33 100644
+--- a/drivers/hwmon/lm78.c
++++ b/drivers/hwmon/lm78.c
+@@ -886,7 +886,7 @@ static int lm78_isa_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit lm78_isa_remove(struct platform_device *pdev)
++static int lm78_isa_remove(struct platform_device *pdev)
+ {
+ 	struct lm78_data *data = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/hwmon/max1111.c b/drivers/hwmon/max1111.c
+index 410351bcc3e3..eda077de8a9f 100644
+--- a/drivers/hwmon/max1111.c
++++ b/drivers/hwmon/max1111.c
+@@ -256,7 +256,7 @@ static int max1111_probe(struct spi_device *spi)
+ 	return err;
+ }
+ 
+-static int __devexit max1111_remove(struct spi_device *spi)
++static int max1111_remove(struct spi_device *spi)
+ {
+ 	struct max1111_data *data = spi_get_drvdata(spi);
+ 
+diff --git a/drivers/hwmon/max197.c b/drivers/hwmon/max197.c
+index 76c941e0b95f..b5ebb9198c75 100644
+--- a/drivers/hwmon/max197.c
++++ b/drivers/hwmon/max197.c
+@@ -316,7 +316,7 @@ static int max197_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit max197_remove(struct platform_device *pdev)
++static int max197_remove(struct platform_device *pdev)
+ {
+ 	struct max197_data *data = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/hwmon/mc13783-adc.c b/drivers/hwmon/mc13783-adc.c
+index 50032ee45a3b..2a7f331cd3c0 100644
+--- a/drivers/hwmon/mc13783-adc.c
++++ b/drivers/hwmon/mc13783-adc.c
+@@ -233,7 +233,7 @@ static int __init mc13783_adc_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit mc13783_adc_remove(struct platform_device *pdev)
++static int mc13783_adc_remove(struct platform_device *pdev)
+ {
+ 	struct mc13783_adc_priv *priv = platform_get_drvdata(pdev);
+ 	kernel_ulong_t driver_data = platform_get_device_id(pdev)->driver_data;
+diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
+index ac4f403bc618..a87eb8986e36 100644
+--- a/drivers/hwmon/ntc_thermistor.c
++++ b/drivers/hwmon/ntc_thermistor.c
+@@ -393,7 +393,7 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit ntc_thermistor_remove(struct platform_device *pdev)
++static int ntc_thermistor_remove(struct platform_device *pdev)
+ {
+ 	struct ntc_data *data = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
+index b4c11c6ac677..e35856bb79b4 100644
+--- a/drivers/hwmon/pc87360.c
++++ b/drivers/hwmon/pc87360.c
+@@ -228,7 +228,7 @@ struct pc87360_data {
+  */
+ 
+ static int pc87360_probe(struct platform_device *pdev);
+-static int __devexit pc87360_remove(struct platform_device *pdev);
++static int pc87360_remove(struct platform_device *pdev);
+ 
+ static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank,
+ 			      u8 reg);
+@@ -1375,7 +1375,7 @@ static int pc87360_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit pc87360_remove(struct platform_device *pdev)
++static int pc87360_remove(struct platform_device *pdev)
+ {
+ 	struct pc87360_data *data = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c
+index 36a0d177caf3..6086ad039d7d 100644
+--- a/drivers/hwmon/pc87427.c
++++ b/drivers/hwmon/pc87427.c
+@@ -1141,7 +1141,7 @@ static int pc87427_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit pc87427_remove(struct platform_device *pdev)
++static int pc87427_remove(struct platform_device *pdev)
+ {
+ 	struct pc87427_data *data = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/hwmon/s3c-hwmon.c b/drivers/hwmon/s3c-hwmon.c
+index 397e2ada61c2..ff2ae0252a48 100644
+--- a/drivers/hwmon/s3c-hwmon.c
++++ b/drivers/hwmon/s3c-hwmon.c
+@@ -364,7 +364,7 @@ static int s3c_hwmon_probe(struct platform_device *dev)
+ 	return ret;
+ }
+ 
+-static int __devexit s3c_hwmon_remove(struct platform_device *dev)
++static int s3c_hwmon_remove(struct platform_device *dev)
+ {
+ 	struct s3c_hwmon *hwmon = platform_get_drvdata(dev);
+ 	int i;
+diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c
+index d5b79e7dbedc..1c85d39df171 100644
+--- a/drivers/hwmon/sht15.c
++++ b/drivers/hwmon/sht15.c
+@@ -1002,7 +1002,7 @@ static int sht15_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit sht15_remove(struct platform_device *pdev)
++static int sht15_remove(struct platform_device *pdev)
+ {
+ 	struct sht15_data *data = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/hwmon/sht21.c b/drivers/hwmon/sht21.c
+index 9a4cc3b5ae0c..2e9f9570b6f8 100644
+--- a/drivers/hwmon/sht21.c
++++ b/drivers/hwmon/sht21.c
+@@ -233,7 +233,7 @@ static int sht21_probe(struct i2c_client *client,
+  * sht21_remove() - remove device
+  * @client: I2C client device
+  */
+-static int __devexit sht21_remove(struct i2c_client *client)
++static int sht21_remove(struct i2c_client *client)
+ {
+ 	struct sht21 *sht21 = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
+index e84836bcb6c8..06ce3c911db9 100644
+--- a/drivers/hwmon/sis5595.c
++++ b/drivers/hwmon/sis5595.c
+@@ -204,7 +204,7 @@ struct sis5595_data {
+ static struct pci_dev *s_bridge;	/* pointer to the (only) sis5595 */
+ 
+ static int sis5595_probe(struct platform_device *pdev);
+-static int __devexit sis5595_remove(struct platform_device *pdev);
++static int sis5595_remove(struct platform_device *pdev);
+ 
+ static int sis5595_read_value(struct sis5595_data *data, u8 reg);
+ static void sis5595_write_value(struct sis5595_data *data, u8 reg, u8 value);
+@@ -659,7 +659,7 @@ static int sis5595_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit sis5595_remove(struct platform_device *pdev)
++static int sis5595_remove(struct platform_device *pdev)
+ {
+ 	struct sis5595_data *data = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c
+index 9100a2748850..81348fadf3b6 100644
+--- a/drivers/hwmon/smsc47b397.c
++++ b/drivers/hwmon/smsc47b397.c
+@@ -228,7 +228,7 @@ static const struct attribute_group smsc47b397_group = {
+ 	.attrs = smsc47b397_attributes,
+ };
+ 
+-static int __devexit smsc47b397_remove(struct platform_device *pdev)
++static int smsc47b397_remove(struct platform_device *pdev)
+ {
+ 	struct smsc47b397_data *data = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c
+index bd8e4af6fd42..b10c3d36ccbc 100644
+--- a/drivers/hwmon/tmp102.c
++++ b/drivers/hwmon/tmp102.c
+@@ -216,7 +216,7 @@ static int tmp102_probe(struct i2c_client *client,
+ 	return status;
+ }
+ 
+-static int __devexit tmp102_remove(struct i2c_client *client)
++static int tmp102_remove(struct i2c_client *client)
+ {
+ 	struct tmp102 *tmp102 = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/hwmon/twl4030-madc-hwmon.c b/drivers/hwmon/twl4030-madc-hwmon.c
+index 6b42f415c5cd..149d44a7c584 100644
+--- a/drivers/hwmon/twl4030-madc-hwmon.c
++++ b/drivers/hwmon/twl4030-madc-hwmon.c
+@@ -120,7 +120,7 @@ static int twl4030_madc_hwmon_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit twl4030_madc_hwmon_remove(struct platform_device *pdev)
++static int twl4030_madc_hwmon_remove(struct platform_device *pdev)
+ {
+ 	hwmon_device_unregister(&pdev->dev);
+ 	sysfs_remove_group(&pdev->dev.kobj, &twl4030_madc_group);
+diff --git a/drivers/hwmon/ultra45_env.c b/drivers/hwmon/ultra45_env.c
+index 4a06fc016316..fb3e69341c1b 100644
+--- a/drivers/hwmon/ultra45_env.c
++++ b/drivers/hwmon/ultra45_env.c
+@@ -291,7 +291,7 @@ static int env_probe(struct platform_device *op)
+ 	goto out;
+ }
+ 
+-static int __devexit env_remove(struct platform_device *op)
++static int env_remove(struct platform_device *op)
+ {
+ 	struct env *p = platform_get_drvdata(op);
+ 
+diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c
+index b86ad796fa86..76f157b568ed 100644
+--- a/drivers/hwmon/via-cputemp.c
++++ b/drivers/hwmon/via-cputemp.c
+@@ -192,7 +192,7 @@ static int via_cputemp_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit via_cputemp_remove(struct platform_device *pdev)
++static int via_cputemp_remove(struct platform_device *pdev)
+ {
+ 	struct via_cputemp_data *data = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c
+index 9d6e27e8c0f5..e0e14a9f1658 100644
+--- a/drivers/hwmon/via686a.c
++++ b/drivers/hwmon/via686a.c
+@@ -339,7 +339,7 @@ struct via686a_data {
+ static struct pci_dev *s_bridge;	/* pointer to the (only) via686a */
+ 
+ static int via686a_probe(struct platform_device *pdev);
+-static int __devexit via686a_remove(struct platform_device *pdev);
++static int via686a_remove(struct platform_device *pdev);
+ 
+ static inline int via686a_read_value(struct via686a_data *data, u8 reg)
+ {
+@@ -728,7 +728,7 @@ static int via686a_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit via686a_remove(struct platform_device *pdev)
++static int via686a_remove(struct platform_device *pdev)
+ {
+ 	struct via686a_data *data = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c
+index ae02edb50c32..751703059fae 100644
+--- a/drivers/hwmon/vt1211.c
++++ b/drivers/hwmon/vt1211.c
+@@ -1217,7 +1217,7 @@ static int vt1211_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit vt1211_remove(struct platform_device *pdev)
++static int vt1211_remove(struct platform_device *pdev)
+ {
+ 	struct vt1211_data *data = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c
+index a86ef1b19209..a56355cef184 100644
+--- a/drivers/hwmon/vt8231.c
++++ b/drivers/hwmon/vt8231.c
+@@ -176,7 +176,7 @@ struct vt8231_data {
+ 
+ static struct pci_dev *s_bridge;
+ static int vt8231_probe(struct platform_device *pdev);
+-static int __devexit vt8231_remove(struct platform_device *pdev);
++static int vt8231_remove(struct platform_device *pdev);
+ static struct vt8231_data *vt8231_update_device(struct device *dev);
+ static void vt8231_init_device(struct vt8231_data *data);
+ 
+@@ -851,7 +851,7 @@ static int vt8231_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit vt8231_remove(struct platform_device *pdev)
++static int vt8231_remove(struct platform_device *pdev)
+ {
+ 	struct vt8231_data *data = platform_get_drvdata(pdev);
+ 	int i;
+diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
+index 09e17ff6163c..55ac41c05561 100644
+--- a/drivers/hwmon/w83627ehf.c
++++ b/drivers/hwmon/w83627ehf.c
+@@ -2596,7 +2596,7 @@ static int w83627ehf_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit w83627ehf_remove(struct platform_device *pdev)
++static int w83627ehf_remove(struct platform_device *pdev)
+ {
+ 	struct w83627ehf_data *data = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
+index e5a7e5294489..7f68b8309d10 100644
+--- a/drivers/hwmon/w83627hf.c
++++ b/drivers/hwmon/w83627hf.c
+@@ -393,7 +393,7 @@ struct w83627hf_data {
+ 
+ 
+ static int w83627hf_probe(struct platform_device *pdev);
+-static int __devexit w83627hf_remove(struct platform_device *pdev);
++static int w83627hf_remove(struct platform_device *pdev);
+ 
+ static int w83627hf_read_value(struct w83627hf_data *data, u16 reg);
+ static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value);
+@@ -1508,7 +1508,7 @@ static int w83627hf_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit w83627hf_remove(struct platform_device *pdev)
++static int w83627hf_remove(struct platform_device *pdev)
+ {
+ 	struct w83627hf_data *data = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
+index 54674a51960f..93bd28639595 100644
+--- a/drivers/hwmon/w83781d.c
++++ b/drivers/hwmon/w83781d.c
+@@ -1824,7 +1824,7 @@ w83781d_isa_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit
++static int
+ w83781d_isa_remove(struct platform_device *pdev)
+ {
+ 	struct w83781d_data *data = platform_get_drvdata(pdev);
+diff --git a/drivers/hwmon/wm831x-hwmon.c b/drivers/hwmon/wm831x-hwmon.c
+index 81e71663ba4e..df6ceaf8d58a 100644
+--- a/drivers/hwmon/wm831x-hwmon.c
++++ b/drivers/hwmon/wm831x-hwmon.c
+@@ -189,7 +189,7 @@ static int wm831x_hwmon_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit wm831x_hwmon_remove(struct platform_device *pdev)
++static int wm831x_hwmon_remove(struct platform_device *pdev)
+ {
+ 	struct wm831x_hwmon *hwmon = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/hwmon/wm8350-hwmon.c b/drivers/hwmon/wm8350-hwmon.c
+index 1fd641789d0f..64bf75c9442b 100644
+--- a/drivers/hwmon/wm8350-hwmon.c
++++ b/drivers/hwmon/wm8350-hwmon.c
+@@ -114,7 +114,7 @@ static int wm8350_hwmon_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit wm8350_hwmon_remove(struct platform_device *pdev)
++static int wm8350_hwmon_remove(struct platform_device *pdev)
+ {
+ 	struct wm8350 *wm8350 = platform_get_drvdata(pdev);
+ 

commit a5977246cfa44f70d7230f530918b7b7a06ad2eb
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:24:37 2012 -0500
+
+    hwmon: remove use of __devinitdata
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitdata is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Jean Delvare 
+    Acked-by: Guenter Roeck 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c
+index e52856bdc7b6..0f46cca6179a 100644
+--- a/drivers/hwmon/gpio-fan.c
++++ b/drivers/hwmon/gpio-fan.c
+@@ -499,7 +499,7 @@ static int gpio_fan_get_of_pdata(struct device *dev,
+ 	return 0;
+ }
+ 
+-static struct of_device_id of_gpio_fan_match[] __devinitdata = {
++static struct of_device_id of_gpio_fan_match[] = {
+ 	{ .compatible = "gpio-fan", },
+ 	{},
+ };
+diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c
+index 0d0faf056ae3..f3bc723c930c 100644
+--- a/drivers/hwmon/i5k_amb.c
++++ b/drivers/hwmon/i5k_amb.c
+@@ -488,14 +488,14 @@ static int i5k_channel_probe(u16 *amb_present, unsigned long dev_id)
+ static struct {
+ 	unsigned long err;
+ 	unsigned long fbd0;
+-} chipset_ids[] __devinitdata  = {
++} chipset_ids[]  = {
+ 	{ PCI_DEVICE_ID_INTEL_5000_ERR, PCI_DEVICE_ID_INTEL_5000_FBD0 },
+ 	{ PCI_DEVICE_ID_INTEL_5400_ERR, PCI_DEVICE_ID_INTEL_5400_FBD0 },
+ 	{ 0, 0 }
+ };
+ 
+ #ifdef MODULE
+-static struct pci_device_id i5k_amb_ids[] __devinitdata = {
++static struct pci_device_id i5k_amb_ids[] = {
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5000_ERR) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_ERR) },
+ 	{ 0, }
+diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
+index 5adc8299b264..e84836bcb6c8 100644
+--- a/drivers/hwmon/sis5595.c
++++ b/drivers/hwmon/sis5595.c
+@@ -758,7 +758,7 @@ static DEFINE_PCI_DEVICE_TABLE(sis5595_pci_ids) = {
+ 
+ MODULE_DEVICE_TABLE(pci, sis5595_pci_ids);
+ 
+-static int blacklist[] __devinitdata = {
++static int blacklist[] = {
+ 	PCI_DEVICE_ID_SI_540,
+ 	PCI_DEVICE_ID_SI_550,
+ 	PCI_DEVICE_ID_SI_630,

commit 6c931ae1c09a9618852c9619dac71f1f77776e3b
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:35 2012 -0500
+
+    hwmon: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hans de Goede 
+    Cc: Jean Delvare 
+    Cc: Alistair John Strachan 
+    Cc: Fenghua Yu 
+    Cc: Juerg Haefliger 
+    Cc: Andreas Herrmann 
+    Cc: Clemens Ladisch 
+    Cc: Rudolf Marek 
+    Cc: Jim Cromie 
+    Cc: "Mark M. Hoffman" 
+    Cc: Roger Lucas 
+    Acked-by: Guenter Roeck 
+    Acked-by: Mark Brown 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c
+index d12c3fb25fad..700d5e0442ea 100644
+--- a/drivers/hwmon/abituguru.c
++++ b/drivers/hwmon/abituguru.c
+@@ -478,7 +478,7 @@ static int abituguru_write(struct abituguru_data *data,
+  * alarm for sensor type X and then enabling the sensor as sensor type
+  * X, if we then get an alarm it is a sensor of type X.
+  */
+-static int __devinit
++static int
+ abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
+ 				   u8 sensor_addr)
+ {
+@@ -635,7 +635,7 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
+  * read/write test would be feasible because of the reaction above, I've
+  * however opted to stay on the safe side.
+  */
+-static void __devinit
++static void
+ abituguru_detect_no_bank2_sensors(struct abituguru_data *data)
+ {
+ 	int i;
+@@ -691,7 +691,7 @@ abituguru_detect_no_bank2_sensors(struct abituguru_data *data)
+ 		(int)data->bank2_sensors);
+ }
+ 
+-static void __devinit
++static void
+ abituguru_detect_no_pwms(struct abituguru_data *data)
+ {
+ 	int i, j;
+@@ -1264,7 +1264,7 @@ static struct sensor_device_attribute_2 abituguru_sysfs_attr[] = {
+ 	SENSOR_ATTR_2(name, 0444, show_name, NULL, 0, 0),
+ };
+ 
+-static int __devinit abituguru_probe(struct platform_device *pdev)
++static int abituguru_probe(struct platform_device *pdev)
+ {
+ 	struct abituguru_data *data;
+ 	int i, j, used, sysfs_names_free, sysfs_attr_i, res = -ENODEV;
+diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c
+index 56a807554889..b8d0942a9872 100644
+--- a/drivers/hwmon/abituguru3.c
++++ b/drivers/hwmon/abituguru3.c
+@@ -966,7 +966,7 @@ static struct sensor_device_attribute_2 abituguru3_sysfs_attr[] = {
+ 	SENSOR_ATTR_2(name, 0444, show_name, NULL, 0, 0),
+ };
+ 
+-static int __devinit abituguru3_probe(struct platform_device *pdev)
++static int abituguru3_probe(struct platform_device *pdev)
+ {
+ 	const int no_sysfs_attr[3] = { 10, 8, 7 };
+ 	int sensor_index[3] = { 0, 1, 1 };
+diff --git a/drivers/hwmon/ad7314.c b/drivers/hwmon/ad7314.c
+index fdda321c6066..defd34b04629 100644
+--- a/drivers/hwmon/ad7314.c
++++ b/drivers/hwmon/ad7314.c
+@@ -107,7 +107,7 @@ static const struct attribute_group ad7314_group = {
+ 	.attrs = ad7314_attributes,
+ };
+ 
+-static int __devinit ad7314_probe(struct spi_device *spi_dev)
++static int ad7314_probe(struct spi_device *spi_dev)
+ {
+ 	int ret;
+ 	struct ad7314_data *chip;
+diff --git a/drivers/hwmon/adcxx.c b/drivers/hwmon/adcxx.c
+index dff6f4f0dd71..ecc1e6c5fa9f 100644
+--- a/drivers/hwmon/adcxx.c
++++ b/drivers/hwmon/adcxx.c
+@@ -161,7 +161,7 @@ static struct sensor_device_attribute ad_input[] = {
+ 
+ /*----------------------------------------------------------------------*/
+ 
+-static int __devinit adcxx_probe(struct spi_device *spi)
++static int adcxx_probe(struct spi_device *spi)
+ {
+ 	int channels = spi_get_device_id(spi)->driver_data;
+ 	struct adcxx *adc;
+diff --git a/drivers/hwmon/ads7871.c b/drivers/hwmon/ads7871.c
+index 5a6cc1f91ba7..41a7837585fc 100644
+--- a/drivers/hwmon/ads7871.c
++++ b/drivers/hwmon/ads7871.c
+@@ -173,7 +173,7 @@ static const struct attribute_group ads7871_group = {
+ 	.attrs = ads7871_attributes,
+ };
+ 
+-static int __devinit ads7871_probe(struct spi_device *spi)
++static int ads7871_probe(struct spi_device *spi)
+ {
+ 	int ret, err;
+ 	uint8_t val;
+diff --git a/drivers/hwmon/adt7411.c b/drivers/hwmon/adt7411.c
+index a961af614770..68a5da715662 100644
+--- a/drivers/hwmon/adt7411.c
++++ b/drivers/hwmon/adt7411.c
+@@ -276,7 +276,7 @@ static int adt7411_detect(struct i2c_client *client,
+ 	return 0;
+ }
+ 
+-static int __devinit adt7411_probe(struct i2c_client *client,
++static int adt7411_probe(struct i2c_client *client,
+ 				   const struct i2c_device_id *id)
+ {
+ 	struct adt7411_data *data;
+diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
+index 5c0cdd385b1c..65a374631995 100644
+--- a/drivers/hwmon/coretemp.c
++++ b/drivers/hwmon/coretemp.c
+@@ -358,7 +358,7 @@ static int __cpuinit get_tjmax(struct cpuinfo_x86 *c, u32 id,
+ 	return adjust_tjmax(c, id, dev);
+ }
+ 
+-static int __devinit create_name_attr(struct platform_data *pdata,
++static int create_name_attr(struct platform_data *pdata,
+ 				      struct device *dev)
+ {
+ 	sysfs_attr_init(&pdata->name_attr.attr);
+@@ -553,7 +553,7 @@ static void coretemp_remove_core(struct platform_data *pdata,
+ 	pdata->core_data[indx] = NULL;
+ }
+ 
+-static int __devinit coretemp_probe(struct platform_device *pdev)
++static int coretemp_probe(struct platform_device *pdev)
+ {
+ 	struct platform_data *pdata;
+ 	int err;
+diff --git a/drivers/hwmon/da9052-hwmon.c b/drivers/hwmon/da9052-hwmon.c
+index ff28a2daa730..d3206e341de2 100644
+--- a/drivers/hwmon/da9052-hwmon.c
++++ b/drivers/hwmon/da9052-hwmon.c
+@@ -283,7 +283,7 @@ static struct attribute *da9052_attr[] = {
+ 
+ static const struct attribute_group da9052_attr_group = {.attrs = da9052_attr};
+ 
+-static int __devinit da9052_hwmon_probe(struct platform_device *pdev)
++static int da9052_hwmon_probe(struct platform_device *pdev)
+ {
+ 	struct da9052_hwmon *hwmon;
+ 	int ret;
+diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c
+index 32f81ca3c197..aa6a493731bf 100644
+--- a/drivers/hwmon/dme1737.c
++++ b/drivers/hwmon/dme1737.c
+@@ -2630,7 +2630,7 @@ static int __init dme1737_isa_device_add(unsigned short addr)
+ 	return err;
+ }
+ 
+-static int __devinit dme1737_isa_probe(struct platform_device *pdev)
++static int dme1737_isa_probe(struct platform_device *pdev)
+ {
+ 	u8 company, device;
+ 	struct resource *res;
+diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c
+index 56860dd23879..0c8426eea6a6 100644
+--- a/drivers/hwmon/f71805f.c
++++ b/drivers/hwmon/f71805f.c
+@@ -1343,7 +1343,7 @@ static struct attribute *f71805f_attr_pwm[] = {
+  * Device registration and initialization
+  */
+ 
+-static void __devinit f71805f_init_device(struct f71805f_data *data)
++static void f71805f_init_device(struct f71805f_data *data)
+ {
+ 	u8 reg;
+ 	int i;
+@@ -1374,7 +1374,7 @@ static void __devinit f71805f_init_device(struct f71805f_data *data)
+ 	}
+ }
+ 
+-static int __devinit f71805f_probe(struct platform_device *pdev)
++static int f71805f_probe(struct platform_device *pdev)
+ {
+ 	struct f71805f_sio_data *sio_data = pdev->dev.platform_data;
+ 	struct f71805f_data *data;
+diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c
+index 50e4ce2d22d8..bb7275cc47f3 100644
+--- a/drivers/hwmon/f71882fg.c
++++ b/drivers/hwmon/f71882fg.c
+@@ -364,7 +364,7 @@ static ssize_t store_pwm_auto_point_temp(struct device *dev,
+ static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
+ 	char *buf);
+ 
+-static int __devinit f71882fg_probe(struct platform_device *pdev);
++static int f71882fg_probe(struct platform_device *pdev);
+ static int f71882fg_remove(struct platform_device *pdev);
+ 
+ static struct platform_driver f71882fg_driver = {
+@@ -2145,7 +2145,7 @@ static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
+ 	return sprintf(buf, "%s\n", f71882fg_names[data->type]);
+ }
+ 
+-static int __devinit f71882fg_create_sysfs_files(struct platform_device *pdev,
++static int f71882fg_create_sysfs_files(struct platform_device *pdev,
+ 	struct sensor_device_attribute_2 *attr, int count)
+ {
+ 	int err, i;
+@@ -2167,7 +2167,7 @@ static void f71882fg_remove_sysfs_files(struct platform_device *pdev,
+ 		device_remove_file(&pdev->dev, &attr[i].dev_attr);
+ }
+ 
+-static int __devinit f71882fg_create_fan_sysfs_files(
++static int f71882fg_create_fan_sysfs_files(
+ 	struct platform_device *pdev, int idx)
+ {
+ 	struct f71882fg_data *data = platform_get_drvdata(pdev);
+@@ -2265,7 +2265,7 @@ static int __devinit f71882fg_create_fan_sysfs_files(
+ 	return err;
+ }
+ 
+-static int __devinit f71882fg_probe(struct platform_device *pdev)
++static int f71882fg_probe(struct platform_device *pdev)
+ {
+ 	struct f71882fg_data *data;
+ 	struct f71882fg_sio_data *sio_data = pdev->dev.platform_data;
+diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c
+index 327fbc6106ef..4eca29850286 100644
+--- a/drivers/hwmon/fam15h_power.c
++++ b/drivers/hwmon/fam15h_power.c
+@@ -111,7 +111,7 @@ static const struct attribute_group fam15h_power_attr_group = {
+ 	.attrs	= fam15h_power_attrs,
+ };
+ 
+-static bool __devinit fam15h_power_is_internal_node0(struct pci_dev *f4)
++static bool fam15h_power_is_internal_node0(struct pci_dev *f4)
+ {
+ 	u32 val;
+ 
+@@ -168,7 +168,7 @@ static int fam15h_power_resume(struct pci_dev *pdev)
+ #define fam15h_power_resume NULL
+ #endif
+ 
+-static void __devinit fam15h_power_init_data(struct pci_dev *f4,
++static void fam15h_power_init_data(struct pci_dev *f4,
+ 					     struct fam15h_power_data *data)
+ {
+ 	u32 val;
+@@ -194,7 +194,7 @@ static void __devinit fam15h_power_init_data(struct pci_dev *f4,
+ 	data->processor_pwr_watts = (tmp * 15625) >> 10;
+ }
+ 
+-static int __devinit fam15h_power_probe(struct pci_dev *pdev,
++static int fam15h_power_probe(struct pci_dev *pdev,
+ 					const struct pci_device_id *id)
+ {
+ 	struct fam15h_power_data *data;
+diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c
+index 4b1767f95b03..e52856bdc7b6 100644
+--- a/drivers/hwmon/gpio-fan.c
++++ b/drivers/hwmon/gpio-fan.c
+@@ -505,7 +505,7 @@ static struct of_device_id of_gpio_fan_match[] __devinitdata = {
+ };
+ #endif /* CONFIG_OF_GPIO */
+ 
+-static int __devinit gpio_fan_probe(struct platform_device *pdev)
++static int gpio_fan_probe(struct platform_device *pdev)
+ {
+ 	int err;
+ 	struct gpio_fan_data *fan_data;
+diff --git a/drivers/hwmon/hih6130.c b/drivers/hwmon/hih6130.c
+index 9ebe24e9220c..5c65aef095ca 100644
+--- a/drivers/hwmon/hih6130.c
++++ b/drivers/hwmon/hih6130.c
+@@ -220,7 +220,7 @@ static const struct attribute_group hih6130_attr_group = {
+  * device's name.
+  * Returns 0 on success.
+  */
+-static int __devinit hih6130_probe(struct i2c_client *client,
++static int hih6130_probe(struct i2c_client *client,
+ 				   const struct i2c_device_id *id)
+ {
+ 	struct hih6130 *hih6130;
+diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c
+index 3fa3cc8dd061..0d0faf056ae3 100644
+--- a/drivers/hwmon/i5k_amb.c
++++ b/drivers/hwmon/i5k_amb.c
+@@ -260,7 +260,7 @@ static ssize_t show_label(struct device *dev,
+ 		       attr->index & DIMM_MASK);
+ }
+ 
+-static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
++static int i5k_amb_hwmon_init(struct platform_device *pdev)
+ {
+ 	int i, j, k, d = 0;
+ 	u16 c;
+@@ -406,7 +406,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
+ 	return res;
+ }
+ 
+-static int __devinit i5k_amb_add(void)
++static int i5k_amb_add(void)
+ {
+ 	int res = -ENODEV;
+ 
+@@ -425,7 +425,7 @@ static int __devinit i5k_amb_add(void)
+ 	return res;
+ }
+ 
+-static int __devinit i5k_find_amb_registers(struct i5k_amb_data *data,
++static int i5k_find_amb_registers(struct i5k_amb_data *data,
+ 					    unsigned long devid)
+ {
+ 	struct pci_dev *pcidev;
+@@ -459,7 +459,7 @@ static int __devinit i5k_find_amb_registers(struct i5k_amb_data *data,
+ 	return res;
+ }
+ 
+-static int __devinit i5k_channel_probe(u16 *amb_present, unsigned long dev_id)
++static int i5k_channel_probe(u16 *amb_present, unsigned long dev_id)
+ {
+ 	struct pci_dev *pcidev;
+ 	u16 val16;
+@@ -503,7 +503,7 @@ static struct pci_device_id i5k_amb_ids[] __devinitdata = {
+ MODULE_DEVICE_TABLE(pci, i5k_amb_ids);
+ #endif
+ 
+-static int __devinit i5k_amb_probe(struct platform_device *pdev)
++static int i5k_amb_probe(struct platform_device *pdev)
+ {
+ 	struct i5k_amb_data *data;
+ 	struct resource *reso;
+diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
+index 2cb0da1190c7..3a4da44f704f 100644
+--- a/drivers/hwmon/it87.c
++++ b/drivers/hwmon/it87.c
+@@ -1966,7 +1966,7 @@ static void it87_remove_files(struct device *dev)
+ 	sysfs_remove_group(&dev->kobj, &it87_group_label);
+ }
+ 
+-static int __devinit it87_probe(struct platform_device *pdev)
++static int it87_probe(struct platform_device *pdev)
+ {
+ 	struct it87_data *data;
+ 	struct resource *res;
+@@ -2191,7 +2191,7 @@ static void it87_write_value(struct it87_data *data, u8 reg, u8 value)
+ }
+ 
+ /* Return 1 if and only if the PWM interface is safe to use */
+-static int __devinit it87_check_pwm(struct device *dev)
++static int it87_check_pwm(struct device *dev)
+ {
+ 	struct it87_data *data = dev_get_drvdata(dev);
+ 	/*
+@@ -2248,7 +2248,7 @@ static int __devinit it87_check_pwm(struct device *dev)
+ }
+ 
+ /* Called when we have found a new IT87. */
+-static void __devinit it87_init_device(struct platform_device *pdev)
++static void it87_init_device(struct platform_device *pdev)
+ {
+ 	struct it87_sio_data *sio_data = pdev->dev.platform_data;
+ 	struct it87_data *data = platform_get_drvdata(pdev);
+diff --git a/drivers/hwmon/jz4740-hwmon.c b/drivers/hwmon/jz4740-hwmon.c
+index fca0d3798ba6..b944d615944b 100644
+--- a/drivers/hwmon/jz4740-hwmon.c
++++ b/drivers/hwmon/jz4740-hwmon.c
+@@ -102,7 +102,7 @@ static const struct attribute_group jz4740_hwmon_attr_group = {
+ 	.attrs = jz4740_hwmon_attributes,
+ };
+ 
+-static int __devinit jz4740_hwmon_probe(struct platform_device *pdev)
++static int jz4740_hwmon_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 	struct jz4740_hwmon *hwmon;
+diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c
+index 2722cdecc79e..da8acda48ab0 100644
+--- a/drivers/hwmon/k10temp.c
++++ b/drivers/hwmon/k10temp.c
+@@ -95,7 +95,7 @@ static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0);
+ static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit, NULL, 1);
+ static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+ 
+-static bool __devinit has_erratum_319(struct pci_dev *pdev)
++static bool has_erratum_319(struct pci_dev *pdev)
+ {
+ 	u32 pkg_type, reg_dram_cfg;
+ 
+@@ -129,7 +129,7 @@ static bool __devinit has_erratum_319(struct pci_dev *pdev)
+ 	       (boot_cpu_data.x86_model == 4 && boot_cpu_data.x86_mask <= 2);
+ }
+ 
+-static int __devinit k10temp_probe(struct pci_dev *pdev,
++static int k10temp_probe(struct pci_dev *pdev,
+ 				   const struct pci_device_id *id)
+ {
+ 	struct device *hwmon_dev;
+diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c
+index 143a2f8079a3..8c46753158df 100644
+--- a/drivers/hwmon/k8temp.c
++++ b/drivers/hwmon/k8temp.c
+@@ -142,7 +142,7 @@ static DEFINE_PCI_DEVICE_TABLE(k8temp_ids) = {
+ 
+ MODULE_DEVICE_TABLE(pci, k8temp_ids);
+ 
+-static int __devinit is_rev_g_desktop(u8 model)
++static int is_rev_g_desktop(u8 model)
+ {
+ 	u32 brandidx;
+ 
+@@ -173,7 +173,7 @@ static int __devinit is_rev_g_desktop(u8 model)
+ 	return 1;
+ }
+ 
+-static int __devinit k8temp_probe(struct pci_dev *pdev,
++static int k8temp_probe(struct pci_dev *pdev,
+ 				  const struct pci_device_id *id)
+ {
+ 	int err;
+diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c
+index d3d5afd95a51..d5f006e67a51 100644
+--- a/drivers/hwmon/lm70.c
++++ b/drivers/hwmon/lm70.c
+@@ -131,7 +131,7 @@ static DEVICE_ATTR(name, S_IRUGO, lm70_show_name, NULL);
+ 
+ /*----------------------------------------------------------------------*/
+ 
+-static int __devinit lm70_probe(struct spi_device *spi)
++static int lm70_probe(struct spi_device *spi)
+ {
+ 	int chip = spi_get_device_id(spi)->driver_data;
+ 	struct lm70 *p_lm70;
+diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
+index 1dc3433d2acd..181d756badc5 100644
+--- a/drivers/hwmon/lm78.c
++++ b/drivers/hwmon/lm78.c
+@@ -833,7 +833,7 @@ static struct lm78_data *lm78_update_device(struct device *dev)
+ }
+ 
+ #ifdef CONFIG_ISA
+-static int __devinit lm78_isa_probe(struct platform_device *pdev)
++static int lm78_isa_probe(struct platform_device *pdev)
+ {
+ 	int err;
+ 	struct lm78_data *data;
+diff --git a/drivers/hwmon/max1111.c b/drivers/hwmon/max1111.c
+index 5ac15b07dc60..410351bcc3e3 100644
+--- a/drivers/hwmon/max1111.c
++++ b/drivers/hwmon/max1111.c
+@@ -157,7 +157,7 @@ static const struct attribute_group max1110_attr_group = {
+ 	.attrs	= max1110_attributes,
+ };
+ 
+-static int __devinit setup_transfer(struct max1111_data *data)
++static int setup_transfer(struct max1111_data *data)
+ {
+ 	struct spi_message *m;
+ 	struct spi_transfer *x;
+@@ -179,7 +179,7 @@ static int __devinit setup_transfer(struct max1111_data *data)
+ 	return 0;
+ }
+ 
+-static int __devinit max1111_probe(struct spi_device *spi)
++static int max1111_probe(struct spi_device *spi)
+ {
+ 	enum chips chip = spi_get_device_id(spi)->driver_data;
+ 	struct max1111_data *data;
+diff --git a/drivers/hwmon/max197.c b/drivers/hwmon/max197.c
+index 170e1b28128b..76c941e0b95f 100644
+--- a/drivers/hwmon/max197.c
++++ b/drivers/hwmon/max197.c
+@@ -257,7 +257,7 @@ static const struct attribute_group max197_sysfs_group = {
+ 	},
+ };
+ 
+-static int __devinit max197_probe(struct platform_device *pdev)
++static int max197_probe(struct platform_device *pdev)
+ {
+ 	int ch, ret;
+ 	struct max197_data *data;
+diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
+index dd232307780d..ac4f403bc618 100644
+--- a/drivers/hwmon/ntc_thermistor.c
++++ b/drivers/hwmon/ntc_thermistor.c
+@@ -309,7 +309,7 @@ static const struct attribute_group ntc_attr_group = {
+ 	.attrs = ntc_attributes,
+ };
+ 
+-static int __devinit ntc_thermistor_probe(struct platform_device *pdev)
++static int ntc_thermistor_probe(struct platform_device *pdev)
+ {
+ 	struct ntc_data *data;
+ 	struct ntc_thermistor_platform_data *pdata = pdev->dev.platform_data;
+diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
+index 07856630354b..b4c11c6ac677 100644
+--- a/drivers/hwmon/pc87360.c
++++ b/drivers/hwmon/pc87360.c
+@@ -1221,7 +1221,7 @@ static void pc87360_remove_files(struct device *dev)
+ 	sysfs_remove_group(&dev->kobj, &pc8736x_vin_group);
+ }
+ 
+-static int __devinit pc87360_probe(struct platform_device *pdev)
++static int pc87360_probe(struct platform_device *pdev)
+ {
+ 	int i;
+ 	struct pc87360_data *data;
+diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c
+index 288a775c6878..36a0d177caf3 100644
+--- a/drivers/hwmon/pc87427.c
++++ b/drivers/hwmon/pc87427.c
+@@ -956,7 +956,7 @@ static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+  * Device detection, attach and detach
+  */
+ 
+-static int __devinit pc87427_request_regions(struct platform_device *pdev,
++static int pc87427_request_regions(struct platform_device *pdev,
+ 					     int count)
+ {
+ 	struct resource *res;
+@@ -980,7 +980,7 @@ static int __devinit pc87427_request_regions(struct platform_device *pdev,
+ 	return 0;
+ }
+ 
+-static void __devinit pc87427_init_device(struct device *dev)
++static void pc87427_init_device(struct device *dev)
+ {
+ 	struct pc87427_sio_data *sio_data = dev->platform_data;
+ 	struct pc87427_data *data = dev_get_drvdata(dev);
+@@ -1072,7 +1072,7 @@ static void pc87427_remove_files(struct device *dev)
+ 	}
+ }
+ 
+-static int __devinit pc87427_probe(struct platform_device *pdev)
++static int pc87427_probe(struct platform_device *pdev)
+ {
+ 	struct pc87427_sio_data *sio_data = pdev->dev.platform_data;
+ 	struct pc87427_data *data;
+diff --git a/drivers/hwmon/s3c-hwmon.c b/drivers/hwmon/s3c-hwmon.c
+index df405e3696a9..397e2ada61c2 100644
+--- a/drivers/hwmon/s3c-hwmon.c
++++ b/drivers/hwmon/s3c-hwmon.c
+@@ -275,7 +275,7 @@ static void s3c_hwmon_remove_attr(struct device *dev,
+  * s3c_hwmon_probe - device probe entry.
+  * @dev: The device being probed.
+ */
+-static int __devinit s3c_hwmon_probe(struct platform_device *dev)
++static int s3c_hwmon_probe(struct platform_device *dev)
+ {
+ 	struct s3c_hwmon_pdata *pdata = dev->dev.platform_data;
+ 	struct s3c_hwmon *hwmon;
+diff --git a/drivers/hwmon/sch5627.c b/drivers/hwmon/sch5627.c
+index 49f6230bdcf1..0cc99fd83e8e 100644
+--- a/drivers/hwmon/sch5627.c
++++ b/drivers/hwmon/sch5627.c
+@@ -153,7 +153,7 @@ static struct sch5627_data *sch5627_update_device(struct device *dev)
+ 	return ret;
+ }
+ 
+-static int __devinit sch5627_read_limits(struct sch5627_data *data)
++static int sch5627_read_limits(struct sch5627_data *data)
+ {
+ 	int i, val;
+ 
+@@ -465,7 +465,7 @@ static int sch5627_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devinit sch5627_probe(struct platform_device *pdev)
++static int sch5627_probe(struct platform_device *pdev)
+ {
+ 	struct sch5627_data *data;
+ 	int err, build_code, build_id, hwmon_rev, val;
+diff --git a/drivers/hwmon/sch5636.c b/drivers/hwmon/sch5636.c
+index 517118016192..547b5c952eff 100644
+--- a/drivers/hwmon/sch5636.c
++++ b/drivers/hwmon/sch5636.c
+@@ -405,7 +405,7 @@ static int sch5636_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devinit sch5636_probe(struct platform_device *pdev)
++static int sch5636_probe(struct platform_device *pdev)
+ {
+ 	struct sch5636_data *data;
+ 	int i, err, val, revision[2];
+diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c
+index 32e3b29b1961..d5b79e7dbedc 100644
+--- a/drivers/hwmon/sht15.c
++++ b/drivers/hwmon/sht15.c
+@@ -884,7 +884,7 @@ static int sht15_invalidate_voltage(struct notifier_block *nb,
+ 	return NOTIFY_OK;
+ }
+ 
+-static int __devinit sht15_probe(struct platform_device *pdev)
++static int sht15_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 	struct sht15_data *data;
+diff --git a/drivers/hwmon/sht21.c b/drivers/hwmon/sht21.c
+index 3ffd3b3deb04..9a4cc3b5ae0c 100644
+--- a/drivers/hwmon/sht21.c
++++ b/drivers/hwmon/sht21.c
+@@ -187,7 +187,7 @@ static const struct attribute_group sht21_attr_group = {
+  * device's name.
+  * Returns 0 on success.
+  */
+-static int __devinit sht21_probe(struct i2c_client *client,
++static int sht21_probe(struct i2c_client *client,
+ 	const struct i2c_device_id *id)
+ {
+ 	struct sht21 *sht21;
+diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
+index fb6b6ed6accd..5adc8299b264 100644
+--- a/drivers/hwmon/sis5595.c
++++ b/drivers/hwmon/sis5595.c
+@@ -583,7 +583,7 @@ static const struct attribute_group sis5595_group_temp1 = {
+ };
+ 
+ /* This is called when the module is loaded */
+-static int __devinit sis5595_probe(struct platform_device *pdev)
++static int sis5595_probe(struct platform_device *pdev)
+ {
+ 	int err = 0;
+ 	int i;
+@@ -693,7 +693,7 @@ static void sis5595_write_value(struct sis5595_data *data, u8 reg, u8 value)
+ }
+ 
+ /* Called when we have found a new SIS5595. */
+-static void __devinit sis5595_init_device(struct sis5595_data *data)
++static void sis5595_init_device(struct sis5595_data *data)
+ {
+ 	u8 config = sis5595_read_value(data, SIS5595_REG_CONFIG);
+ 	if (!(config & 0x01))
+@@ -774,7 +774,7 @@ static int blacklist[] __devinitdata = {
+ 	PCI_DEVICE_ID_SI_5598,
+ 	0 };
+ 
+-static int __devinit sis5595_device_add(unsigned short address)
++static int sis5595_device_add(unsigned short address)
+ {
+ 	struct resource res = {
+ 		.start	= address,
+@@ -815,7 +815,7 @@ static int __devinit sis5595_device_add(unsigned short address)
+ 	return err;
+ }
+ 
+-static int __devinit sis5595_pci_probe(struct pci_dev *dev,
++static int sis5595_pci_probe(struct pci_dev *dev,
+ 				       const struct pci_device_id *id)
+ {
+ 	u16 address;
+diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c
+index 6edad30be3e3..9100a2748850 100644
+--- a/drivers/hwmon/smsc47b397.c
++++ b/drivers/hwmon/smsc47b397.c
+@@ -249,7 +249,7 @@ static struct platform_driver smsc47b397_driver = {
+ 	.remove		= smsc47b397_remove,
+ };
+ 
+-static int __devinit smsc47b397_probe(struct platform_device *pdev)
++static int smsc47b397_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	struct smsc47b397_data *data;
+diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c
+index ec11400dc980..bd8e4af6fd42 100644
+--- a/drivers/hwmon/tmp102.c
++++ b/drivers/hwmon/tmp102.c
+@@ -147,7 +147,7 @@ static const struct attribute_group tmp102_attr_group = {
+ #define TMP102_CONFIG  (TMP102_CONF_TM | TMP102_CONF_EM | TMP102_CONF_CR1)
+ #define TMP102_CONFIG_RD_ONLY (TMP102_CONF_R0 | TMP102_CONF_R1 | TMP102_CONF_AL)
+ 
+-static int __devinit tmp102_probe(struct i2c_client *client,
++static int tmp102_probe(struct i2c_client *client,
+ 				  const struct i2c_device_id *id)
+ {
+ 	struct tmp102 *tmp102;
+diff --git a/drivers/hwmon/twl4030-madc-hwmon.c b/drivers/hwmon/twl4030-madc-hwmon.c
+index 1a174f0a3cde..6b42f415c5cd 100644
+--- a/drivers/hwmon/twl4030-madc-hwmon.c
++++ b/drivers/hwmon/twl4030-madc-hwmon.c
+@@ -96,7 +96,7 @@ static const struct attribute_group twl4030_madc_group = {
+ 	.attrs = twl4030_madc_attributes,
+ };
+ 
+-static int __devinit twl4030_madc_hwmon_probe(struct platform_device *pdev)
++static int twl4030_madc_hwmon_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 	struct device *hwmon;
+diff --git a/drivers/hwmon/ultra45_env.c b/drivers/hwmon/ultra45_env.c
+index 89747b8ac818..4a06fc016316 100644
+--- a/drivers/hwmon/ultra45_env.c
++++ b/drivers/hwmon/ultra45_env.c
+@@ -250,7 +250,7 @@ static const struct attribute_group env_group = {
+ 	.attrs = env_attributes,
+ };
+ 
+-static int __devinit env_probe(struct platform_device *op)
++static int env_probe(struct platform_device *op)
+ {
+ 	struct env *p = kzalloc(sizeof(*p), GFP_KERNEL);
+ 	int err = -ENOMEM;
+diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c
+index 6021b7f3e364..b86ad796fa86 100644
+--- a/drivers/hwmon/via-cputemp.c
++++ b/drivers/hwmon/via-cputemp.c
+@@ -121,7 +121,7 @@ static const struct attribute_group via_cputemp_group = {
+ /* Optional attributes */
+ static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_cpu_vid, NULL);
+ 
+-static int __devinit via_cputemp_probe(struct platform_device *pdev)
++static int via_cputemp_probe(struct platform_device *pdev)
+ {
+ 	struct via_cputemp_data *data;
+ 	struct cpuinfo_x86 *c = &cpu_data(pdev->id);
+diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c
+index b2c155d6939f..9d6e27e8c0f5 100644
+--- a/drivers/hwmon/via686a.c
++++ b/drivers/hwmon/via686a.c
+@@ -682,7 +682,7 @@ static struct platform_driver via686a_driver = {
+ 
+ 
+ /* This is called when the module is loaded */
+-static int __devinit via686a_probe(struct platform_device *pdev)
++static int via686a_probe(struct platform_device *pdev)
+ {
+ 	struct via686a_data *data;
+ 	struct resource *res;
+@@ -745,7 +745,7 @@ static void via686a_update_fan_div(struct via686a_data *data)
+ 	data->fan_div[1] = reg >> 6;
+ }
+ 
+-static void __devinit via686a_init_device(struct via686a_data *data)
++static void via686a_init_device(struct via686a_data *data)
+ {
+ 	u8 reg;
+ 
+@@ -833,7 +833,7 @@ static DEFINE_PCI_DEVICE_TABLE(via686a_pci_ids) = {
+ };
+ MODULE_DEVICE_TABLE(pci, via686a_pci_ids);
+ 
+-static int __devinit via686a_device_add(unsigned short address)
++static int via686a_device_add(unsigned short address)
+ {
+ 	struct resource res = {
+ 		.start	= address,
+@@ -874,7 +874,7 @@ static int __devinit via686a_device_add(unsigned short address)
+ 	return err;
+ }
+ 
+-static int __devinit via686a_pci_probe(struct pci_dev *dev,
++static int via686a_pci_probe(struct pci_dev *dev,
+ 				       const struct pci_device_id *id)
+ {
+ 	u16 address, val;
+diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c
+index 07ec260abb43..ae02edb50c32 100644
+--- a/drivers/hwmon/vt1211.c
++++ b/drivers/hwmon/vt1211.c
+@@ -1086,7 +1086,7 @@ static struct device_attribute vt1211_sysfs_misc[] = {
+  * Device registration and initialization
+  * --------------------------------------------------------------------- */
+ 
+-static void __devinit vt1211_init_device(struct vt1211_data *data)
++static void vt1211_init_device(struct vt1211_data *data)
+ {
+ 	/* set VRM */
+ 	data->vrm = vid_which_vrm();
+@@ -1141,7 +1141,7 @@ static void vt1211_remove_sysfs(struct platform_device *pdev)
+ 		device_remove_file(dev, &vt1211_sysfs_misc[i]);
+ }
+ 
+-static int __devinit vt1211_probe(struct platform_device *pdev)
++static int vt1211_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	struct vt1211_data *data;
+diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c
+index 28f95bdf0358..a86ef1b19209 100644
+--- a/drivers/hwmon/vt8231.c
++++ b/drivers/hwmon/vt8231.c
+@@ -772,7 +772,7 @@ static DEFINE_PCI_DEVICE_TABLE(vt8231_pci_ids) = {
+ 
+ MODULE_DEVICE_TABLE(pci, vt8231_pci_ids);
+ 
+-static int __devinit vt8231_pci_probe(struct pci_dev *dev,
++static int vt8231_pci_probe(struct pci_dev *dev,
+ 				      const struct pci_device_id *id);
+ 
+ static struct pci_driver vt8231_pci_driver = {
+@@ -943,7 +943,7 @@ static struct vt8231_data *vt8231_update_device(struct device *dev)
+ 	return data;
+ }
+ 
+-static int __devinit vt8231_device_add(unsigned short address)
++static int vt8231_device_add(unsigned short address)
+ {
+ 	struct resource res = {
+ 		.start	= address,
+@@ -984,7 +984,7 @@ static int __devinit vt8231_device_add(unsigned short address)
+ 	return err;
+ }
+ 
+-static int __devinit vt8231_pci_probe(struct pci_dev *dev,
++static int vt8231_pci_probe(struct pci_dev *dev,
+ 				const struct pci_device_id *id)
+ {
+ 	u16 address, val;
+diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
+index c7e0794ce072..09e17ff6163c 100644
+--- a/drivers/hwmon/w83627ehf.c
++++ b/drivers/hwmon/w83627ehf.c
+@@ -1866,7 +1866,7 @@ static void w83627ehf_device_remove_files(struct device *dev)
+ }
+ 
+ /* Get the monitoring functions started */
+-static inline void __devinit w83627ehf_init_device(struct w83627ehf_data *data,
++static inline void w83627ehf_init_device(struct w83627ehf_data *data,
+ 						   enum kinds kind)
+ {
+ 	int i;
+@@ -1952,7 +1952,7 @@ static void w82627ehf_swap_tempreg(struct w83627ehf_data *data,
+ 	data->reg_temp_config[r2] = tmp;
+ }
+ 
+-static void __devinit
++static void
+ w83627ehf_set_temp_reg_ehf(struct w83627ehf_data *data, int n_temp)
+ {
+ 	int i;
+@@ -1965,7 +1965,7 @@ w83627ehf_set_temp_reg_ehf(struct w83627ehf_data *data, int n_temp)
+ 	}
+ }
+ 
+-static void __devinit
++static void
+ w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data,
+ 			   struct w83627ehf_data *data)
+ {
+@@ -2054,7 +2054,7 @@ w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data,
+ 	}
+ }
+ 
+-static int __devinit w83627ehf_probe(struct platform_device *pdev)
++static int w83627ehf_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	struct w83627ehf_sio_data *sio_data = dev->platform_data;
+diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
+index 3aff01505c86..e5a7e5294489 100644
+--- a/drivers/hwmon/w83627hf.c
++++ b/drivers/hwmon/w83627hf.c
+@@ -1342,7 +1342,7 @@ static const struct attribute_group w83627hf_group_opt = {
+ 	.attrs = w83627hf_attributes_opt,
+ };
+ 
+-static int __devinit w83627hf_probe(struct platform_device *pdev)
++static int w83627hf_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	struct w83627hf_sio_data *sio_data = dev->platform_data;
+@@ -1564,7 +1564,7 @@ static int w83627hf_read_value(struct w83627hf_data *data, u16 reg)
+ 	return res;
+ }
+ 
+-static int __devinit w83627thf_read_gpio5(struct platform_device *pdev)
++static int w83627thf_read_gpio5(struct platform_device *pdev)
+ {
+ 	struct w83627hf_sio_data *sio_data = pdev->dev.platform_data;
+ 	int res = 0xff, sel;
+@@ -1597,7 +1597,7 @@ static int __devinit w83627thf_read_gpio5(struct platform_device *pdev)
+ 	return res;
+ }
+ 
+-static int __devinit w83687thf_read_vid(struct platform_device *pdev)
++static int w83687thf_read_vid(struct platform_device *pdev)
+ {
+ 	struct w83627hf_sio_data *sio_data = pdev->dev.platform_data;
+ 	int res = 0xff;
+@@ -1649,7 +1649,7 @@ static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value)
+ 	return 0;
+ }
+ 
+-static void __devinit w83627hf_init_device(struct platform_device *pdev)
++static void w83627hf_init_device(struct platform_device *pdev)
+ {
+ 	struct w83627hf_data *data = platform_get_drvdata(pdev);
+ 	int i;
+diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
+index becd9d66c077..54674a51960f 100644
+--- a/drivers/hwmon/w83781d.c
++++ b/drivers/hwmon/w83781d.c
+@@ -1764,7 +1764,7 @@ w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value)
+ 	return 0;
+ }
+ 
+-static int __devinit
++static int
+ w83781d_isa_probe(struct platform_device *pdev)
+ {
+ 	int err, reg;
+diff --git a/drivers/hwmon/wm831x-hwmon.c b/drivers/hwmon/wm831x-hwmon.c
+index d77bdf4d1123..81e71663ba4e 100644
+--- a/drivers/hwmon/wm831x-hwmon.c
++++ b/drivers/hwmon/wm831x-hwmon.c
+@@ -157,7 +157,7 @@ static const struct attribute_group wm831x_attr_group = {
+ 	.attrs	= wm831x_attributes,
+ };
+ 
+-static int __devinit wm831x_hwmon_probe(struct platform_device *pdev)
++static int wm831x_hwmon_probe(struct platform_device *pdev)
+ {
+ 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
+ 	struct wm831x_hwmon *hwmon;
+diff --git a/drivers/hwmon/wm8350-hwmon.c b/drivers/hwmon/wm8350-hwmon.c
+index 9544485cc8dd..1fd641789d0f 100644
+--- a/drivers/hwmon/wm8350-hwmon.c
++++ b/drivers/hwmon/wm8350-hwmon.c
+@@ -91,7 +91,7 @@ static const struct attribute_group wm8350_attr_group = {
+ 	.attrs	= wm8350_attributes,
+ };
+ 
+-static int __devinit wm8350_hwmon_probe(struct platform_device *pdev)
++static int wm8350_hwmon_probe(struct platform_device *pdev)
+ {
+ 	struct wm8350 *wm8350 = platform_get_drvdata(pdev);
+ 	int ret;

commit 9e5e9b7a92e4e2e4ac1f0d6aa181639637660e45
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:20 2012 -0500
+
+    hwmon: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hans de Goede 
+    Cc: Jean Delvare 
+    Cc: Alistair John Strachan 
+    Cc: Fenghua Yu 
+    Cc: Juerg Haefliger 
+    Cc: Andreas Herrmann 
+    Cc: Clemens Ladisch 
+    Cc: Rudolf Marek 
+    Cc: Jim Cromie 
+    Cc: "Mark M. Hoffman" 
+    Cc: Roger Lucas 
+    Acked-by: Guenter Roeck 
+    Acked-by: Mark Brown 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c
+index 78b81793ddd9..d12c3fb25fad 100644
+--- a/drivers/hwmon/abituguru.c
++++ b/drivers/hwmon/abituguru.c
+@@ -1545,7 +1545,7 @@ static struct platform_driver abituguru_driver = {
+ 		.pm	= ABIT_UGURU_PM,
+ 	},
+ 	.probe		= abituguru_probe,
+-	.remove		= __devexit_p(abituguru_remove),
++	.remove		= abituguru_remove,
+ };
+ 
+ static int __init abituguru_detect(void)
+diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c
+index b174b8b2b4df..56a807554889 100644
+--- a/drivers/hwmon/abituguru3.c
++++ b/drivers/hwmon/abituguru3.c
+@@ -1171,7 +1171,7 @@ static struct platform_driver abituguru3_driver = {
+ 		.pm	= ABIT_UGURU3_PM
+ 	},
+ 	.probe	= abituguru3_probe,
+-	.remove	= __devexit_p(abituguru3_remove),
++	.remove	= abituguru3_remove,
+ };
+ 
+ static int __init abituguru3_dmi_detect(void)
+diff --git a/drivers/hwmon/ad7314.c b/drivers/hwmon/ad7314.c
+index 37c01e72d699..fdda321c6066 100644
+--- a/drivers/hwmon/ad7314.c
++++ b/drivers/hwmon/ad7314.c
+@@ -159,7 +159,7 @@ static struct spi_driver ad7314_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = ad7314_probe,
+-	.remove = __devexit_p(ad7314_remove),
++	.remove = ad7314_remove,
+ 	.id_table = ad7314_id,
+ };
+ 
+diff --git a/drivers/hwmon/ad7414.c b/drivers/hwmon/ad7414.c
+index b420fb3f3a71..20276ca37ed8 100644
+--- a/drivers/hwmon/ad7414.c
++++ b/drivers/hwmon/ad7414.c
+@@ -246,7 +246,7 @@ static struct i2c_driver ad7414_driver = {
+ 		.name	= "ad7414",
+ 	},
+ 	.probe	= ad7414_probe,
+-	.remove	= __devexit_p(ad7414_remove),
++	.remove	= ad7414_remove,
+ 	.id_table = ad7414_id,
+ };
+ 
+diff --git a/drivers/hwmon/adcxx.c b/drivers/hwmon/adcxx.c
+index f4c5867170d6..dff6f4f0dd71 100644
+--- a/drivers/hwmon/adcxx.c
++++ b/drivers/hwmon/adcxx.c
+@@ -240,7 +240,7 @@ static struct spi_driver adcxx_driver = {
+ 	},
+ 	.id_table = adcxx_ids,
+ 	.probe	= adcxx_probe,
+-	.remove	= __devexit_p(adcxx_remove),
++	.remove	= adcxx_remove,
+ };
+ 
+ module_spi_driver(adcxx_driver);
+diff --git a/drivers/hwmon/ads7871.c b/drivers/hwmon/ads7871.c
+index 1b53aa42b6db..5a6cc1f91ba7 100644
+--- a/drivers/hwmon/ads7871.c
++++ b/drivers/hwmon/ads7871.c
+@@ -241,7 +241,7 @@ static struct spi_driver ads7871_driver = {
+ 	},
+ 
+ 	.probe = ads7871_probe,
+-	.remove = __devexit_p(ads7871_remove),
++	.remove = ads7871_remove,
+ };
+ 
+ module_spi_driver(ads7871_driver);
+diff --git a/drivers/hwmon/adt7411.c b/drivers/hwmon/adt7411.c
+index 517f1856c706..a961af614770 100644
+--- a/drivers/hwmon/adt7411.c
++++ b/drivers/hwmon/adt7411.c
+@@ -337,7 +337,7 @@ static struct i2c_driver adt7411_driver = {
+ 		.name		= "adt7411",
+ 	},
+ 	.probe  = adt7411_probe,
+-	.remove	= __devexit_p(adt7411_remove),
++	.remove	= adt7411_remove,
+ 	.id_table = adt7411_id,
+ 	.detect = adt7411_detect,
+ 	.address_list = normal_i2c,
+diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
+index 47b8d84b489d..5c0cdd385b1c 100644
+--- a/drivers/hwmon/coretemp.c
++++ b/drivers/hwmon/coretemp.c
+@@ -608,7 +608,7 @@ static struct platform_driver coretemp_driver = {
+ 		.name = DRVNAME,
+ 	},
+ 	.probe = coretemp_probe,
+-	.remove = __devexit_p(coretemp_remove),
++	.remove = coretemp_remove,
+ };
+ 
+ static int __cpuinit coretemp_device_add(unsigned int cpu)
+diff --git a/drivers/hwmon/da9052-hwmon.c b/drivers/hwmon/da9052-hwmon.c
+index b8d01c5f5713..ff28a2daa730 100644
+--- a/drivers/hwmon/da9052-hwmon.c
++++ b/drivers/hwmon/da9052-hwmon.c
+@@ -328,7 +328,7 @@ static int __devexit da9052_hwmon_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver da9052_hwmon_driver = {
+ 	.probe = da9052_hwmon_probe,
+-	.remove = __devexit_p(da9052_hwmon_remove),
++	.remove = da9052_hwmon_remove,
+ 	.driver = {
+ 		.name = "da9052-hwmon",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c
+index fe0eeec0b750..32f81ca3c197 100644
+--- a/drivers/hwmon/dme1737.c
++++ b/drivers/hwmon/dme1737.c
+@@ -2734,7 +2734,7 @@ static struct platform_driver dme1737_isa_driver = {
+ 		.name = "dme1737",
+ 	},
+ 	.probe = dme1737_isa_probe,
+-	.remove = __devexit_p(dme1737_isa_remove),
++	.remove = dme1737_isa_remove,
+ };
+ 
+ /* ---------------------------------------------------------------------
+diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c
+index 4dd7723d257f..56860dd23879 100644
+--- a/drivers/hwmon/f71805f.c
++++ b/drivers/hwmon/f71805f.c
+@@ -1510,7 +1510,7 @@ static struct platform_driver f71805f_driver = {
+ 		.name	= DRVNAME,
+ 	},
+ 	.probe		= f71805f_probe,
+-	.remove		= __devexit_p(f71805f_remove),
++	.remove		= f71805f_remove,
+ };
+ 
+ static int __init f71805f_device_add(unsigned short address,
+diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c
+index 4f4110407387..327fbc6106ef 100644
+--- a/drivers/hwmon/fam15h_power.c
++++ b/drivers/hwmon/fam15h_power.c
+@@ -256,7 +256,7 @@ static struct pci_driver fam15h_power_driver = {
+ 	.name = "fam15h_power",
+ 	.id_table = fam15h_power_id_table,
+ 	.probe = fam15h_power_probe,
+-	.remove = __devexit_p(fam15h_power_remove),
++	.remove = fam15h_power_remove,
+ 	.resume = fam15h_power_resume,
+ };
+ 
+diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c
+index 1381a2e3bbd4..4b1767f95b03 100644
+--- a/drivers/hwmon/gpio-fan.c
++++ b/drivers/hwmon/gpio-fan.c
+@@ -626,7 +626,7 @@ static SIMPLE_DEV_PM_OPS(gpio_fan_pm, gpio_fan_suspend, gpio_fan_resume);
+ 
+ static struct platform_driver gpio_fan_driver = {
+ 	.probe		= gpio_fan_probe,
+-	.remove		= __devexit_p(gpio_fan_remove),
++	.remove		= gpio_fan_remove,
+ 	.driver	= {
+ 		.name	= "gpio-fan",
+ 		.pm	= GPIO_FAN_PM,
+diff --git a/drivers/hwmon/hih6130.c b/drivers/hwmon/hih6130.c
+index 9a675efaa78d..9ebe24e9220c 100644
+--- a/drivers/hwmon/hih6130.c
++++ b/drivers/hwmon/hih6130.c
+@@ -283,7 +283,7 @@ MODULE_DEVICE_TABLE(i2c, hih6130_id);
+ static struct i2c_driver hih6130_driver = {
+ 	.driver.name = "hih6130",
+ 	.probe       = hih6130_probe,
+-	.remove      = __devexit_p(hih6130_remove),
++	.remove      = hih6130_remove,
+ 	.id_table    = hih6130_id,
+ };
+ 
+diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c
+index 46141abaafba..3fa3cc8dd061 100644
+--- a/drivers/hwmon/i5k_amb.c
++++ b/drivers/hwmon/i5k_amb.c
+@@ -587,7 +587,7 @@ static struct platform_driver i5k_amb_driver = {
+ 		.name = DRVNAME,
+ 	},
+ 	.probe = i5k_amb_probe,
+-	.remove = __devexit_p(i5k_amb_remove),
++	.remove = i5k_amb_remove,
+ };
+ 
+ static int __init i5k_amb_init(void)
+diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
+index f1de3979181f..2cb0da1190c7 100644
+--- a/drivers/hwmon/it87.c
++++ b/drivers/hwmon/it87.c
+@@ -443,7 +443,7 @@ static struct platform_driver it87_driver = {
+ 		.name	= DRVNAME,
+ 	},
+ 	.probe	= it87_probe,
+-	.remove	= __devexit_p(it87_remove),
++	.remove	= it87_remove,
+ };
+ 
+ static ssize_t show_in(struct device *dev, struct device_attribute *attr,
+diff --git a/drivers/hwmon/jz4740-hwmon.c b/drivers/hwmon/jz4740-hwmon.c
+index dee9eec2036e..fca0d3798ba6 100644
+--- a/drivers/hwmon/jz4740-hwmon.c
++++ b/drivers/hwmon/jz4740-hwmon.c
+@@ -184,7 +184,7 @@ static int __devexit jz4740_hwmon_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver jz4740_hwmon_driver = {
+ 	.probe	= jz4740_hwmon_probe,
+-	.remove = __devexit_p(jz4740_hwmon_remove),
++	.remove = jz4740_hwmon_remove,
+ 	.driver = {
+ 		.name = "jz4740-hwmon",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c
+index f2fe8078633b..2722cdecc79e 100644
+--- a/drivers/hwmon/k10temp.c
++++ b/drivers/hwmon/k10temp.c
+@@ -219,7 +219,7 @@ static struct pci_driver k10temp_driver = {
+ 	.name = "k10temp",
+ 	.id_table = k10temp_id_table,
+ 	.probe = k10temp_probe,
+-	.remove = __devexit_p(k10temp_remove),
++	.remove = k10temp_remove,
+ };
+ 
+ module_pci_driver(k10temp_driver);
+diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c
+index e8c7fb0bbf95..143a2f8079a3 100644
+--- a/drivers/hwmon/k8temp.c
++++ b/drivers/hwmon/k8temp.c
+@@ -324,7 +324,7 @@ static struct pci_driver k8temp_driver = {
+ 	.name = "k8temp",
+ 	.id_table = k8temp_ids,
+ 	.probe = k8temp_probe,
+-	.remove = __devexit_p(k8temp_remove),
++	.remove = k8temp_remove,
+ };
+ 
+ module_pci_driver(k8temp_driver);
+diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c
+index 2d1777a03edb..d3d5afd95a51 100644
+--- a/drivers/hwmon/lm70.c
++++ b/drivers/hwmon/lm70.c
+@@ -207,7 +207,7 @@ static struct spi_driver lm70_driver = {
+ 	},
+ 	.id_table = lm70_ids,
+ 	.probe	= lm70_probe,
+-	.remove	= __devexit_p(lm70_remove),
++	.remove	= lm70_remove,
+ };
+ 
+ module_spi_driver(lm70_driver);
+diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
+index c6ffafe600ad..1dc3433d2acd 100644
+--- a/drivers/hwmon/lm78.c
++++ b/drivers/hwmon/lm78.c
+@@ -903,7 +903,7 @@ static struct platform_driver lm78_isa_driver = {
+ 		.name	= "lm78",
+ 	},
+ 	.probe		= lm78_isa_probe,
+-	.remove		= __devexit_p(lm78_isa_remove),
++	.remove		= lm78_isa_remove,
+ };
+ 
+ /* return 1 if a supported chip is found, 0 otherwise */
+diff --git a/drivers/hwmon/max1111.c b/drivers/hwmon/max1111.c
+index b4eb0889c465..5ac15b07dc60 100644
+--- a/drivers/hwmon/max1111.c
++++ b/drivers/hwmon/max1111.c
+@@ -283,7 +283,7 @@ static struct spi_driver max1111_driver = {
+ 	},
+ 	.id_table	= max1111_ids,
+ 	.probe		= max1111_probe,
+-	.remove		= __devexit_p(max1111_remove),
++	.remove		= max1111_remove,
+ };
+ 
+ module_spi_driver(max1111_driver);
+diff --git a/drivers/hwmon/max197.c b/drivers/hwmon/max197.c
+index 6304f2616fa7..170e1b28128b 100644
+--- a/drivers/hwmon/max197.c
++++ b/drivers/hwmon/max197.c
+@@ -339,7 +339,7 @@ static struct platform_driver max197_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = max197_probe,
+-	.remove = __devexit_p(max197_remove),
++	.remove = max197_remove,
+ 	.id_table = max197_device_ids,
+ };
+ module_platform_driver(max197_driver);
+diff --git a/drivers/hwmon/mc13783-adc.c b/drivers/hwmon/mc13783-adc.c
+index cf47a59657a9..50032ee45a3b 100644
+--- a/drivers/hwmon/mc13783-adc.c
++++ b/drivers/hwmon/mc13783-adc.c
+@@ -265,7 +265,7 @@ static const struct platform_device_id mc13783_adc_idtable[] = {
+ MODULE_DEVICE_TABLE(platform, mc13783_adc_idtable);
+ 
+ static struct platform_driver mc13783_adc_driver = {
+-	.remove		= __devexit_p(mc13783_adc_remove),
++	.remove		= mc13783_adc_remove,
+ 	.driver		= {
+ 		.owner	= THIS_MODULE,
+ 		.name	= DRIVER_NAME,
+diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
+index 74a6c58d0218..dd232307780d 100644
+--- a/drivers/hwmon/ntc_thermistor.c
++++ b/drivers/hwmon/ntc_thermistor.c
+@@ -419,7 +419,7 @@ static struct platform_driver ntc_thermistor_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = ntc_thermistor_probe,
+-	.remove = __devexit_p(ntc_thermistor_remove),
++	.remove = ntc_thermistor_remove,
+ 	.id_table = ntc_thermistor_id,
+ };
+ 
+diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
+index 91d5b2a21dd9..07856630354b 100644
+--- a/drivers/hwmon/pc87360.c
++++ b/drivers/hwmon/pc87360.c
+@@ -248,7 +248,7 @@ static struct platform_driver pc87360_driver = {
+ 		.name	= "pc87360",
+ 	},
+ 	.probe		= pc87360_probe,
+-	.remove		= __devexit_p(pc87360_remove),
++	.remove		= pc87360_remove,
+ };
+ 
+ /*
+diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c
+index f185b1fa53e5..288a775c6878 100644
+--- a/drivers/hwmon/pc87427.c
++++ b/drivers/hwmon/pc87427.c
+@@ -1158,7 +1158,7 @@ static struct platform_driver pc87427_driver = {
+ 		.name	= DRVNAME,
+ 	},
+ 	.probe		= pc87427_probe,
+-	.remove		= __devexit_p(pc87427_remove),
++	.remove		= pc87427_remove,
+ };
+ 
+ static int __init pc87427_device_add(const struct pc87427_sio_data *sio_data)
+diff --git a/drivers/hwmon/s3c-hwmon.c b/drivers/hwmon/s3c-hwmon.c
+index bcecd025fcc4..df405e3696a9 100644
+--- a/drivers/hwmon/s3c-hwmon.c
++++ b/drivers/hwmon/s3c-hwmon.c
+@@ -386,7 +386,7 @@ static struct platform_driver s3c_hwmon_driver = {
+ 		.owner		= THIS_MODULE,
+ 	},
+ 	.probe		= s3c_hwmon_probe,
+-	.remove		= __devexit_p(s3c_hwmon_remove),
++	.remove		= s3c_hwmon_remove,
+ };
+ 
+ module_platform_driver(s3c_hwmon_driver);
+diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c
+index 07a0c1a0b84d..32e3b29b1961 100644
+--- a/drivers/hwmon/sht15.c
++++ b/drivers/hwmon/sht15.c
+@@ -1043,7 +1043,7 @@ static struct platform_driver sht15_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = sht15_probe,
+-	.remove = __devexit_p(sht15_remove),
++	.remove = sht15_remove,
+ 	.id_table = sht15_device_ids,
+ };
+ module_platform_driver(sht15_driver);
+diff --git a/drivers/hwmon/sht21.c b/drivers/hwmon/sht21.c
+index 5f67546950b1..3ffd3b3deb04 100644
+--- a/drivers/hwmon/sht21.c
++++ b/drivers/hwmon/sht21.c
+@@ -253,7 +253,7 @@ MODULE_DEVICE_TABLE(i2c, sht21_id);
+ static struct i2c_driver sht21_driver = {
+ 	.driver.name = "sht21",
+ 	.probe       = sht21_probe,
+-	.remove      = __devexit_p(sht21_remove),
++	.remove      = sht21_remove,
+ 	.id_table    = sht21_id,
+ };
+ 
+diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
+index 8275f0e14eb7..fb6b6ed6accd 100644
+--- a/drivers/hwmon/sis5595.c
++++ b/drivers/hwmon/sis5595.c
+@@ -217,7 +217,7 @@ static struct platform_driver sis5595_driver = {
+ 		.name	= "sis5595",
+ 	},
+ 	.probe		= sis5595_probe,
+-	.remove		= __devexit_p(sis5595_remove),
++	.remove		= sis5595_remove,
+ };
+ 
+ /* 4 Voltages */
+diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c
+index 65b07de11a0f..6edad30be3e3 100644
+--- a/drivers/hwmon/smsc47b397.c
++++ b/drivers/hwmon/smsc47b397.c
+@@ -246,7 +246,7 @@ static struct platform_driver smsc47b397_driver = {
+ 		.name	= DRVNAME,
+ 	},
+ 	.probe		= smsc47b397_probe,
+-	.remove		= __devexit_p(smsc47b397_remove),
++	.remove		= smsc47b397_remove,
+ };
+ 
+ static int __devinit smsc47b397_probe(struct platform_device *pdev)
+diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c
+index b8777e54190a..ec11400dc980 100644
+--- a/drivers/hwmon/tmp102.c
++++ b/drivers/hwmon/tmp102.c
+@@ -283,7 +283,7 @@ static struct i2c_driver tmp102_driver = {
+ 	.driver.name	= DRIVER_NAME,
+ 	.driver.pm	= TMP102_DEV_PM_OPS,
+ 	.probe		= tmp102_probe,
+-	.remove		= __devexit_p(tmp102_remove),
++	.remove		= tmp102_remove,
+ 	.id_table	= tmp102_id,
+ };
+ 
+diff --git a/drivers/hwmon/ultra45_env.c b/drivers/hwmon/ultra45_env.c
+index 44136bb6d045..89747b8ac818 100644
+--- a/drivers/hwmon/ultra45_env.c
++++ b/drivers/hwmon/ultra45_env.c
+@@ -321,7 +321,7 @@ static struct platform_driver env_driver = {
+ 		.of_match_table = env_match,
+ 	},
+ 	.probe		= env_probe,
+-	.remove		= __devexit_p(env_remove),
++	.remove		= env_remove,
+ };
+ 
+ module_platform_driver(env_driver);
+diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c
+index 4cddee04f2e6..6021b7f3e364 100644
+--- a/drivers/hwmon/via-cputemp.c
++++ b/drivers/hwmon/via-cputemp.c
+@@ -209,7 +209,7 @@ static struct platform_driver via_cputemp_driver = {
+ 		.name = DRVNAME,
+ 	},
+ 	.probe = via_cputemp_probe,
+-	.remove = __devexit_p(via_cputemp_remove),
++	.remove = via_cputemp_remove,
+ };
+ 
+ struct pdev_entry {
+diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c
+index 299399aa30fe..b2c155d6939f 100644
+--- a/drivers/hwmon/via686a.c
++++ b/drivers/hwmon/via686a.c
+@@ -677,7 +677,7 @@ static struct platform_driver via686a_driver = {
+ 		.name	= "via686a",
+ 	},
+ 	.probe		= via686a_probe,
+-	.remove		= __devexit_p(via686a_remove),
++	.remove		= via686a_remove,
+ };
+ 
+ 
+diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c
+index f2c61153dba9..07ec260abb43 100644
+--- a/drivers/hwmon/vt1211.c
++++ b/drivers/hwmon/vt1211.c
+@@ -1233,7 +1233,7 @@ static struct platform_driver vt1211_driver = {
+ 		.name  = DRVNAME,
+ 	},
+ 	.probe  = vt1211_probe,
+-	.remove = __devexit_p(vt1211_remove),
++	.remove = vt1211_remove,
+ };
+ 
+ static int __init vt1211_device_add(unsigned short address)
+diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c
+index 84e3dc5e3a83..28f95bdf0358 100644
+--- a/drivers/hwmon/vt8231.c
++++ b/drivers/hwmon/vt8231.c
+@@ -762,7 +762,7 @@ static struct platform_driver vt8231_driver = {
+ 		.name	= "vt8231",
+ 	},
+ 	.probe	= vt8231_probe,
+-	.remove	= __devexit_p(vt8231_remove),
++	.remove	= vt8231_remove,
+ };
+ 
+ static DEFINE_PCI_DEVICE_TABLE(vt8231_pci_ids) = {
+diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
+index de3c7e04c3b5..c7e0794ce072 100644
+--- a/drivers/hwmon/w83627ehf.c
++++ b/drivers/hwmon/w83627ehf.c
+@@ -2614,7 +2614,7 @@ static struct platform_driver w83627ehf_driver = {
+ 		.name	= DRVNAME,
+ 	},
+ 	.probe		= w83627ehf_probe,
+-	.remove		= __devexit_p(w83627ehf_remove),
++	.remove		= w83627ehf_remove,
+ };
+ 
+ /* w83627ehf_find() looks for a '627 in the Super-I/O config space */
+diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
+index af1589908709..3aff01505c86 100644
+--- a/drivers/hwmon/w83627hf.c
++++ b/drivers/hwmon/w83627hf.c
+@@ -407,7 +407,7 @@ static struct platform_driver w83627hf_driver = {
+ 		.name	= DRVNAME,
+ 	},
+ 	.probe		= w83627hf_probe,
+-	.remove		= __devexit_p(w83627hf_remove),
++	.remove		= w83627hf_remove,
+ };
+ 
+ static ssize_t
+diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
+index 20f11d31da40..becd9d66c077 100644
+--- a/drivers/hwmon/w83781d.c
++++ b/drivers/hwmon/w83781d.c
+@@ -1842,7 +1842,7 @@ static struct platform_driver w83781d_isa_driver = {
+ 		.name = "w83781d",
+ 	},
+ 	.probe = w83781d_isa_probe,
+-	.remove = __devexit_p(w83781d_isa_remove),
++	.remove = w83781d_isa_remove,
+ };
+ 
+ /* return 1 if a supported chip is found, 0 otherwise */
+diff --git a/drivers/hwmon/wm831x-hwmon.c b/drivers/hwmon/wm831x-hwmon.c
+index d0db1f2738fb..d77bdf4d1123 100644
+--- a/drivers/hwmon/wm831x-hwmon.c
++++ b/drivers/hwmon/wm831x-hwmon.c
+@@ -201,7 +201,7 @@ static int __devexit wm831x_hwmon_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver wm831x_hwmon_driver = {
+ 	.probe = wm831x_hwmon_probe,
+-	.remove = __devexit_p(wm831x_hwmon_remove),
++	.remove = wm831x_hwmon_remove,
+ 	.driver = {
+ 		.name = "wm831x-hwmon",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/hwmon/wm8350-hwmon.c b/drivers/hwmon/wm8350-hwmon.c
+index b955756bdb42..9544485cc8dd 100644
+--- a/drivers/hwmon/wm8350-hwmon.c
++++ b/drivers/hwmon/wm8350-hwmon.c
+@@ -126,7 +126,7 @@ static int __devexit wm8350_hwmon_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver wm8350_hwmon_driver = {
+ 	.probe = wm8350_hwmon_probe,
+-	.remove = __devexit_p(wm8350_hwmon_remove),
++	.remove = wm8350_hwmon_remove,
+ 	.driver = {
+ 		.name = "wm8350-hwmon",
+ 		.owner = THIS_MODULE,

commit 415ec69fb1861fc377c65cb30ddc76999891b8e1
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:07 2012 -0500
+
+    power: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Anton Vorontsov 
+    Cc: David Woodhouse 
+    Acked-by: Mark Brown 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/power/88pm860x_battery.c b/drivers/power/88pm860x_battery.c
+index 0a8e09fc2138..8bc80b05c63c 100644
+--- a/drivers/power/88pm860x_battery.c
++++ b/drivers/power/88pm860x_battery.c
+@@ -989,7 +989,7 @@ static int pm860x_battery_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit pm860x_battery_remove(struct platform_device *pdev)
++static int pm860x_battery_remove(struct platform_device *pdev)
+ {
+ 	struct pm860x_battery_info *info = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/power/88pm860x_charger.c b/drivers/power/88pm860x_charger.c
+index 5f034f2c1964..4b37a5af8deb 100644
+--- a/drivers/power/88pm860x_charger.c
++++ b/drivers/power/88pm860x_charger.c
+@@ -718,7 +718,7 @@ static int pm860x_charger_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit pm860x_charger_remove(struct platform_device *pdev)
++static int pm860x_charger_remove(struct platform_device *pdev)
+ {
+ 	struct pm860x_charger_info *info = platform_get_drvdata(pdev);
+ 	int i;
+diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
+index 87a7c972a909..989b09950aff 100644
+--- a/drivers/power/ab8500_btemp.c
++++ b/drivers/power/ab8500_btemp.c
+@@ -938,7 +938,7 @@ static int ab8500_btemp_suspend(struct platform_device *pdev,
+ #define ab8500_btemp_resume       NULL
+ #endif
+ 
+-static int __devexit ab8500_btemp_remove(struct platform_device *pdev)
++static int ab8500_btemp_remove(struct platform_device *pdev)
+ {
+ 	struct ab8500_btemp *di = platform_get_drvdata(pdev);
+ 	int i, irq;
+diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
+index b19149b540ee..7ecb8abe20b5 100644
+--- a/drivers/power/ab8500_charger.c
++++ b/drivers/power/ab8500_charger.c
+@@ -2490,7 +2490,7 @@ static int ab8500_charger_suspend(struct platform_device *pdev,
+ #define ab8500_charger_resume       NULL
+ #endif
+ 
+-static int __devexit ab8500_charger_remove(struct platform_device *pdev)
++static int ab8500_charger_remove(struct platform_device *pdev)
+ {
+ 	struct ab8500_charger *di = platform_get_drvdata(pdev);
+ 	int i, irq, ret;
+diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
+index b3598b86bbe0..331dc43ded4e 100644
+--- a/drivers/power/ab8500_fg.c
++++ b/drivers/power/ab8500_fg.c
+@@ -2411,7 +2411,7 @@ static int ab8500_fg_suspend(struct platform_device *pdev,
+ #define ab8500_fg_resume       NULL
+ #endif
+ 
+-static int __devexit ab8500_fg_remove(struct platform_device *pdev)
++static int ab8500_fg_remove(struct platform_device *pdev)
+ {
+ 	int ret = 0;
+ 	struct ab8500_fg *di = platform_get_drvdata(pdev);
+diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c
+index 44a5fdac970f..19f254190790 100644
+--- a/drivers/power/abx500_chargalg.c
++++ b/drivers/power/abx500_chargalg.c
+@@ -1782,7 +1782,7 @@ static int abx500_chargalg_suspend(struct platform_device *pdev,
+ #define abx500_chargalg_resume       NULL
+ #endif
+ 
+-static int __devexit abx500_chargalg_remove(struct platform_device *pdev)
++static int abx500_chargalg_remove(struct platform_device *pdev)
+ {
+ 	struct abx500_chargalg *di = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/power/avs/smartreflex.c b/drivers/power/avs/smartreflex.c
+index c7d441710423..d0fed2c5cf2c 100644
+--- a/drivers/power/avs/smartreflex.c
++++ b/drivers/power/avs/smartreflex.c
+@@ -1026,7 +1026,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit omap_sr_remove(struct platform_device *pdev)
++static int omap_sr_remove(struct platform_device *pdev)
+ {
+ 	struct omap_sr_data *pdata = pdev->dev.platform_data;
+ 	struct omap_sr *sr_info;
+@@ -1059,7 +1059,7 @@ static int __devexit omap_sr_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static void __devexit omap_sr_shutdown(struct platform_device *pdev)
++static void omap_sr_shutdown(struct platform_device *pdev)
+ {
+ 	struct omap_sr_data *pdata = pdev->dev.platform_data;
+ 	struct omap_sr *sr_info;
+diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
+index a256a4c05dc6..e0edaf7de54b 100644
+--- a/drivers/power/bq27x00_battery.c
++++ b/drivers/power/bq27x00_battery.c
+@@ -969,7 +969,7 @@ static int bq27000_battery_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit bq27000_battery_remove(struct platform_device *pdev)
++static int bq27000_battery_remove(struct platform_device *pdev)
+ {
+ 	struct bq27x00_device_info *di = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
+index 5a1cc0a88483..adb3a4b59cb3 100644
+--- a/drivers/power/charger-manager.c
++++ b/drivers/power/charger-manager.c
+@@ -1655,7 +1655,7 @@ static int charger_manager_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit charger_manager_remove(struct platform_device *pdev)
++static int charger_manager_remove(struct platform_device *pdev)
+ {
+ 	struct charger_manager *cm = platform_get_drvdata(pdev);
+ 	struct charger_desc *desc = cm->desc;
+diff --git a/drivers/power/collie_battery.c b/drivers/power/collie_battery.c
+index d3d80bb84c8f..c58d0e31bdef 100644
+--- a/drivers/power/collie_battery.c
++++ b/drivers/power/collie_battery.c
+@@ -349,7 +349,7 @@ static int collie_bat_probe(struct ucb1x00_dev *dev)
+ 	return ret;
+ }
+ 
+-static void __devexit collie_bat_remove(struct ucb1x00_dev *dev)
++static void collie_bat_remove(struct ucb1x00_dev *dev)
+ {
+ 	free_irq(gpio_to_irq(COLLIE_GPIO_CO), &collie_bat_main);
+ 
+diff --git a/drivers/power/da9052-battery.c b/drivers/power/da9052-battery.c
+index 133829065afb..bb0df8917adc 100644
+--- a/drivers/power/da9052-battery.c
++++ b/drivers/power/da9052-battery.c
+@@ -630,7 +630,7 @@ static s32 da9052_bat_probe(struct platform_device *pdev)
+ 	kfree(bat);
+ 	return ret;
+ }
+-static int __devexit da9052_bat_remove(struct platform_device *pdev)
++static int da9052_bat_remove(struct platform_device *pdev)
+ {
+ 	int i;
+ 	int irq;
+diff --git a/drivers/power/ds2780_battery.c b/drivers/power/ds2780_battery.c
+index 42024f854213..8b6c4539e7f4 100644
+--- a/drivers/power/ds2780_battery.c
++++ b/drivers/power/ds2780_battery.c
+@@ -819,7 +819,7 @@ static int ds2780_battery_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit ds2780_battery_remove(struct platform_device *pdev)
++static int ds2780_battery_remove(struct platform_device *pdev)
+ {
+ 	struct ds2780_device_info *dev_info = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/power/ds2781_battery.c b/drivers/power/ds2781_battery.c
+index 46821aafe6be..0a5acc6fc6f0 100644
+--- a/drivers/power/ds2781_battery.c
++++ b/drivers/power/ds2781_battery.c
+@@ -810,7 +810,7 @@ static int ds2781_battery_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit ds2781_battery_remove(struct platform_device *pdev)
++static int ds2781_battery_remove(struct platform_device *pdev)
+ {
+ 	struct ds2781_device_info *dev_info = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/power/generic-adc-battery.c b/drivers/power/generic-adc-battery.c
+index 055dea7a1756..e902b088d52c 100644
+--- a/drivers/power/generic-adc-battery.c
++++ b/drivers/power/generic-adc-battery.c
+@@ -351,7 +351,7 @@ static int gab_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit gab_remove(struct platform_device *pdev)
++static int gab_remove(struct platform_device *pdev)
+ {
+ 	int chan;
+ 	struct gab *adc_bat = platform_get_drvdata(pdev);
+diff --git a/drivers/power/gpio-charger.c b/drivers/power/gpio-charger.c
+index cea6e6ae0e84..e3e40a9f3af2 100644
+--- a/drivers/power/gpio-charger.c
++++ b/drivers/power/gpio-charger.c
+@@ -144,7 +144,7 @@ static int gpio_charger_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit gpio_charger_remove(struct platform_device *pdev)
++static int gpio_charger_remove(struct platform_device *pdev)
+ {
+ 	struct gpio_charger *gpio_charger = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/power/intel_mid_battery.c b/drivers/power/intel_mid_battery.c
+index 0eb50b0daf74..18d136b443ee 100644
+--- a/drivers/power/intel_mid_battery.c
++++ b/drivers/power/intel_mid_battery.c
+@@ -754,7 +754,7 @@ static int platform_pmic_battery_probe(struct platform_device *pdev)
+  * pmic_battery_probe.
+  */
+ 
+-static int __devexit platform_pmic_battery_remove(struct platform_device *pdev)
++static int platform_pmic_battery_remove(struct platform_device *pdev)
+ {
+ 	struct pmic_power_module_info *pbi = dev_get_drvdata(&pdev->dev);
+ 
+diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c
+index 3a1b9598d168..176ad59d99f5 100644
+--- a/drivers/power/isp1704_charger.c
++++ b/drivers/power/isp1704_charger.c
+@@ -484,7 +484,7 @@ static int isp1704_charger_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit isp1704_charger_remove(struct platform_device *pdev)
++static int isp1704_charger_remove(struct platform_device *pdev)
+ {
+ 	struct isp1704_charger *isp = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/power/jz4740-battery.c b/drivers/power/jz4740-battery.c
+index 1f7d2ca0dbd2..74ac69e0687f 100644
+--- a/drivers/power/jz4740-battery.c
++++ b/drivers/power/jz4740-battery.c
+@@ -376,7 +376,7 @@ static int jz_battery_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit jz_battery_remove(struct platform_device *pdev)
++static int jz_battery_remove(struct platform_device *pdev)
+ {
+ 	struct jz_battery *jz_battery = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/power/lp8727_charger.c b/drivers/power/lp8727_charger.c
+index c6ba2ff215de..4ee71a90e248 100644
+--- a/drivers/power/lp8727_charger.c
++++ b/drivers/power/lp8727_charger.c
+@@ -522,7 +522,7 @@ static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id)
+ 	return 0;
+ }
+ 
+-static int __devexit lp8727_remove(struct i2c_client *cl)
++static int lp8727_remove(struct i2c_client *cl)
+ {
+ 	struct lp8727_chg *pchg = i2c_get_clientdata(cl);
+ 
+diff --git a/drivers/power/lp8788-charger.c b/drivers/power/lp8788-charger.c
+index 3bdb4be8db2b..a1c51ac117fd 100644
+--- a/drivers/power/lp8788-charger.c
++++ b/drivers/power/lp8788-charger.c
+@@ -766,7 +766,7 @@ static int lp8788_charger_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit lp8788_charger_remove(struct platform_device *pdev)
++static int lp8788_charger_remove(struct platform_device *pdev)
+ {
+ 	struct lp8788_charger *pchg = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/power/max17040_battery.c b/drivers/power/max17040_battery.c
+index ae10a21ed70c..22cfe9cc4727 100644
+--- a/drivers/power/max17040_battery.c
++++ b/drivers/power/max17040_battery.c
+@@ -238,7 +238,7 @@ static int max17040_probe(struct i2c_client *client,
+ 	return 0;
+ }
+ 
+-static int __devexit max17040_remove(struct i2c_client *client)
++static int max17040_remove(struct i2c_client *client)
+ {
+ 	struct max17040_chip *chip = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/power/max17042_battery.c b/drivers/power/max17042_battery.c
+index 8752bc01a9ea..5ffe46916f0b 100644
+--- a/drivers/power/max17042_battery.c
++++ b/drivers/power/max17042_battery.c
+@@ -775,7 +775,7 @@ static int max17042_probe(struct i2c_client *client,
+ 	return 0;
+ }
+ 
+-static int __devexit max17042_remove(struct i2c_client *client)
++static int max17042_remove(struct i2c_client *client)
+ {
+ 	struct max17042_chip *chip = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/power/max8903_charger.c b/drivers/power/max8903_charger.c
+index 83272c51f6a5..14e2b96d93b0 100644
+--- a/drivers/power/max8903_charger.c
++++ b/drivers/power/max8903_charger.c
+@@ -345,7 +345,7 @@ static int max8903_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static __devexit int max8903_remove(struct platform_device *pdev)
++static int max8903_remove(struct platform_device *pdev)
+ {
+ 	struct max8903_data *data = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/power/max8925_power.c b/drivers/power/max8925_power.c
+index 7b8191b08a46..1a075f1f1b67 100644
+--- a/drivers/power/max8925_power.c
++++ b/drivers/power/max8925_power.c
+@@ -414,7 +414,7 @@ static int max8925_init_charger(struct max8925_chip *chip,
+ 	return 0;
+ }
+ 
+-static __devexit int max8925_deinit_charger(struct max8925_power_info *info)
++static int max8925_deinit_charger(struct max8925_power_info *info)
+ {
+ 	struct max8925_chip *chip = info->chip;
+ 	int irq;
+@@ -501,7 +501,7 @@ static int max8925_power_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static __devexit int max8925_power_remove(struct platform_device *pdev)
++static int max8925_power_remove(struct platform_device *pdev)
+ {
+ 	struct max8925_power_info *info = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/power/max8997_charger.c b/drivers/power/max8997_charger.c
+index c6767dfd4c41..e757885b620c 100644
+--- a/drivers/power/max8997_charger.c
++++ b/drivers/power/max8997_charger.c
+@@ -167,7 +167,7 @@ static int max8997_battery_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit max8997_battery_remove(struct platform_device *pdev)
++static int max8997_battery_remove(struct platform_device *pdev)
+ {
+ 	struct charger_data *charger = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/power/max8998_charger.c b/drivers/power/max8998_charger.c
+index 9f34c80f358c..bf677e3daec9 100644
+--- a/drivers/power/max8998_charger.c
++++ b/drivers/power/max8998_charger.c
+@@ -178,7 +178,7 @@ static int max8998_battery_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit max8998_battery_remove(struct platform_device *pdev)
++static int max8998_battery_remove(struct platform_device *pdev)
+ {
+ 	struct max8998_battery_data *max8998 = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c
+index 60d5449a9960..298c47d111b4 100644
+--- a/drivers/power/olpc_battery.c
++++ b/drivers/power/olpc_battery.c
+@@ -659,7 +659,7 @@ static int olpc_battery_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit olpc_battery_remove(struct platform_device *pdev)
++static int olpc_battery_remove(struct platform_device *pdev)
+ {
+ 	device_remove_file(olpc_bat.dev, &olpc_bat_error);
+ 	device_remove_bin_file(olpc_bat.dev, &olpc_bat_eeprom);
+diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c
+index c0ba4ecb1943..c2122a7ad065 100644
+--- a/drivers/power/pcf50633-charger.c
++++ b/drivers/power/pcf50633-charger.c
+@@ -447,7 +447,7 @@ static int pcf50633_mbc_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit pcf50633_mbc_remove(struct platform_device *pdev)
++static int pcf50633_mbc_remove(struct platform_device *pdev)
+ {
+ 	struct pcf50633_mbc *mbc = platform_get_drvdata(pdev);
+ 	int i;
+diff --git a/drivers/power/sbs-battery.c b/drivers/power/sbs-battery.c
+index 30280c5b1fb7..3960f0b2afe9 100644
+--- a/drivers/power/sbs-battery.c
++++ b/drivers/power/sbs-battery.c
+@@ -800,7 +800,7 @@ static int sbs_probe(struct i2c_client *client,
+ 	return rc;
+ }
+ 
+-static int __devexit sbs_remove(struct i2c_client *client)
++static int sbs_remove(struct i2c_client *client)
+ {
+ 	struct sbs_info *chip = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/power/tosa_battery.c b/drivers/power/tosa_battery.c
+index d958c9f6d524..0224de50c540 100644
+--- a/drivers/power/tosa_battery.c
++++ b/drivers/power/tosa_battery.c
+@@ -409,7 +409,7 @@ static int tosa_bat_probe(struct platform_device *dev)
+ 	return ret;
+ }
+ 
+-static int __devexit tosa_bat_remove(struct platform_device *dev)
++static int tosa_bat_remove(struct platform_device *dev)
+ {
+ 	free_irq(gpio_to_irq(TOSA_GPIO_JACKET_DETECT), &tosa_bat_jacket);
+ 	free_irq(gpio_to_irq(TOSA_GPIO_BAT1_CRG), &tosa_bat_jacket);
+diff --git a/drivers/power/wm831x_backup.c b/drivers/power/wm831x_backup.c
+index ef3b81788752..d9cc169f1424 100644
+--- a/drivers/power/wm831x_backup.c
++++ b/drivers/power/wm831x_backup.c
+@@ -207,7 +207,7 @@ static int wm831x_backup_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static __devexit int wm831x_backup_remove(struct platform_device *pdev)
++static int wm831x_backup_remove(struct platform_device *pdev)
+ {
+ 	struct wm831x_backup *devdata = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c
+index d21af8a01af3..3bed2f55cf7d 100644
+--- a/drivers/power/wm831x_power.c
++++ b/drivers/power/wm831x_power.c
+@@ -625,7 +625,7 @@ static int wm831x_power_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static __devexit int wm831x_power_remove(struct platform_device *pdev)
++static int wm831x_power_remove(struct platform_device *pdev)
+ {
+ 	struct wm831x_power *wm831x_power = platform_get_drvdata(pdev);
+ 	struct wm831x *wm831x = wm831x_power->wm831x;
+diff --git a/drivers/power/wm8350_power.c b/drivers/power/wm8350_power.c
+index 6acb63a41a2d..b3607e2906d2 100644
+--- a/drivers/power/wm8350_power.c
++++ b/drivers/power/wm8350_power.c
+@@ -501,7 +501,7 @@ static int wm8350_power_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static __devexit int wm8350_power_remove(struct platform_device *pdev)
++static int wm8350_power_remove(struct platform_device *pdev)
+ {
+ 	struct wm8350 *wm8350 = platform_get_drvdata(pdev);
+ 	struct wm8350_power *power = &wm8350->power;
+diff --git a/drivers/power/wm97xx_battery.c b/drivers/power/wm97xx_battery.c
+index 4b3f7634fd30..58f7348e6c22 100644
+--- a/drivers/power/wm97xx_battery.c
++++ b/drivers/power/wm97xx_battery.c
+@@ -263,7 +263,7 @@ static int wm97xx_bat_probe(struct platform_device *dev)
+ 	return ret;
+ }
+ 
+-static int __devexit wm97xx_bat_remove(struct platform_device *dev)
++static int wm97xx_bat_remove(struct platform_device *dev)
+ {
+ 	struct wm97xx_pdata *wmdata = dev->dev.platform_data;
+ 	struct wm97xx_batt_pdata *pdata = wmdata->batt_pdata;
+diff --git a/drivers/power/z2_battery.c b/drivers/power/z2_battery.c
+index ebf16296aca3..814d2e31f0c9 100644
+--- a/drivers/power/z2_battery.c
++++ b/drivers/power/z2_battery.c
+@@ -251,7 +251,7 @@ static int z2_batt_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit z2_batt_remove(struct i2c_client *client)
++static int z2_batt_remove(struct i2c_client *client)
+ {
+ 	struct z2_charger *charger = i2c_get_clientdata(client);
+ 	struct z2_battery_info *info = charger->info;

commit c8afa6406e60aec6ff90033e5ffe41a206609296
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:23 2012 -0500
+
+    power: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Anton Vorontsov 
+    Cc: David Woodhouse 
+    Acked-by: Mark Brown 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/power/88pm860x_battery.c b/drivers/power/88pm860x_battery.c
+index ebf7bb5c57ed..0a8e09fc2138 100644
+--- a/drivers/power/88pm860x_battery.c
++++ b/drivers/power/88pm860x_battery.c
+@@ -901,7 +901,7 @@ static enum power_supply_property pm860x_batt_props[] = {
+ 	POWER_SUPPLY_PROP_TEMP,
+ };
+ 
+-static __devinit int pm860x_battery_probe(struct platform_device *pdev)
++static int pm860x_battery_probe(struct platform_device *pdev)
+ {
+ 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+ 	struct pm860x_battery_info *info;
+diff --git a/drivers/power/88pm860x_charger.c b/drivers/power/88pm860x_charger.c
+index fc051732e5dc..5f034f2c1964 100644
+--- a/drivers/power/88pm860x_charger.c
++++ b/drivers/power/88pm860x_charger.c
+@@ -645,7 +645,7 @@ static struct pm860x_irq_desc {
+ 	{ "vchg", pm860x_vchg_handler },
+ };
+ 
+-static __devinit int pm860x_charger_probe(struct platform_device *pdev)
++static int pm860x_charger_probe(struct platform_device *pdev)
+ {
+ 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+ 	struct pm860x_charger_info *info;
+diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
+index 61867095d440..87a7c972a909 100644
+--- a/drivers/power/ab8500_btemp.c
++++ b/drivers/power/ab8500_btemp.c
+@@ -960,7 +960,7 @@ static int __devexit ab8500_btemp_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devinit ab8500_btemp_probe(struct platform_device *pdev)
++static int ab8500_btemp_probe(struct platform_device *pdev)
+ {
+ 	int irq, i, ret = 0;
+ 	u8 val;
+diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
+index fe36df2680a3..b19149b540ee 100644
+--- a/drivers/power/ab8500_charger.c
++++ b/drivers/power/ab8500_charger.c
+@@ -2531,7 +2531,7 @@ static int __devexit ab8500_charger_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devinit ab8500_charger_probe(struct platform_device *pdev)
++static int ab8500_charger_probe(struct platform_device *pdev)
+ {
+ 	int irq, i, charger_status, ret = 0;
+ 	struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
+diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
+index ff2f09c0c128..b3598b86bbe0 100644
+--- a/drivers/power/ab8500_fg.c
++++ b/drivers/power/ab8500_fg.c
+@@ -2442,7 +2442,7 @@ static struct ab8500_fg_interrupts ab8500_fg_irq[] = {
+ 	{"CCEOC", ab8500_fg_cc_data_end_handler},
+ };
+ 
+-static int __devinit ab8500_fg_probe(struct platform_device *pdev)
++static int ab8500_fg_probe(struct platform_device *pdev)
+ {
+ 	int i, irq;
+ 	int ret = 0;
+diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c
+index 6ed6b88f1fa8..44a5fdac970f 100644
+--- a/drivers/power/abx500_chargalg.c
++++ b/drivers/power/abx500_chargalg.c
+@@ -1800,7 +1800,7 @@ static int __devexit abx500_chargalg_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devinit abx500_chargalg_probe(struct platform_device *pdev)
++static int abx500_chargalg_probe(struct platform_device *pdev)
+ {
+ 	struct abx500_bm_plat_data *plat_data;
+ 	int ret = 0;
+diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
+index 8faeb40cf78f..a256a4c05dc6 100644
+--- a/drivers/power/bq27x00_battery.c
++++ b/drivers/power/bq27x00_battery.c
+@@ -926,7 +926,7 @@ static int bq27000_read_platform(struct bq27x00_device_info *di, u8 reg,
+ 	return pdata->read(dev, reg);
+ }
+ 
+-static int __devinit bq27000_battery_probe(struct platform_device *pdev)
++static int bq27000_battery_probe(struct platform_device *pdev)
+ {
+ 	struct bq27x00_device_info *di;
+ 	struct bq27000_platform_data *pdata = pdev->dev.platform_data;
+diff --git a/drivers/power/collie_battery.c b/drivers/power/collie_battery.c
+index cd9ef5103d07..d3d80bb84c8f 100644
+--- a/drivers/power/collie_battery.c
++++ b/drivers/power/collie_battery.c
+@@ -305,7 +305,7 @@ static int collie_bat_resume(struct ucb1x00_dev *dev)
+ #define collie_bat_resume NULL
+ #endif
+ 
+-static int __devinit collie_bat_probe(struct ucb1x00_dev *dev)
++static int collie_bat_probe(struct ucb1x00_dev *dev)
+ {
+ 	int ret;
+ 
+diff --git a/drivers/power/da9052-battery.c b/drivers/power/da9052-battery.c
+index 753d4ba483f7..133829065afb 100644
+--- a/drivers/power/da9052-battery.c
++++ b/drivers/power/da9052-battery.c
+@@ -576,7 +576,7 @@ static const char *const da9052_bat_irqs[] = {
+ 	"CHG END",
+ };
+ 
+-static s32 __devinit da9052_bat_probe(struct platform_device *pdev)
++static s32 da9052_bat_probe(struct platform_device *pdev)
+ {
+ 	struct da9052_pdata *pdata;
+ 	struct da9052_battery *bat;
+diff --git a/drivers/power/ds2780_battery.c b/drivers/power/ds2780_battery.c
+index 2154822e9c86..42024f854213 100644
+--- a/drivers/power/ds2780_battery.c
++++ b/drivers/power/ds2780_battery.c
+@@ -755,7 +755,7 @@ static const struct attribute_group ds2780_attr_group = {
+ 	.attrs = ds2780_attributes,
+ };
+ 
+-static int __devinit ds2780_battery_probe(struct platform_device *pdev)
++static int ds2780_battery_probe(struct platform_device *pdev)
+ {
+ 	int ret = 0;
+ 	struct ds2780_device_info *dev_info;
+diff --git a/drivers/power/ds2781_battery.c b/drivers/power/ds2781_battery.c
+index ce1200914b89..46821aafe6be 100644
+--- a/drivers/power/ds2781_battery.c
++++ b/drivers/power/ds2781_battery.c
+@@ -750,7 +750,7 @@ static const struct attribute_group ds2781_attr_group = {
+ 	.attrs = ds2781_attributes,
+ };
+ 
+-static int __devinit ds2781_battery_probe(struct platform_device *pdev)
++static int ds2781_battery_probe(struct platform_device *pdev)
+ {
+ 	int ret = 0;
+ 	struct ds2781_device_info *dev_info;
+diff --git a/drivers/power/generic-adc-battery.c b/drivers/power/generic-adc-battery.c
+index 60a0f29a9ac9..055dea7a1756 100644
+--- a/drivers/power/generic-adc-battery.c
++++ b/drivers/power/generic-adc-battery.c
+@@ -236,7 +236,7 @@ static irqreturn_t gab_charged(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit gab_probe(struct platform_device *pdev)
++static int gab_probe(struct platform_device *pdev)
+ {
+ 	struct gab *adc_bat;
+ 	struct power_supply *psy;
+diff --git a/drivers/power/gpio-charger.c b/drivers/power/gpio-charger.c
+index e74fb2fbdb2c..cea6e6ae0e84 100644
+--- a/drivers/power/gpio-charger.c
++++ b/drivers/power/gpio-charger.c
+@@ -68,7 +68,7 @@ static enum power_supply_property gpio_charger_properties[] = {
+ 	POWER_SUPPLY_PROP_ONLINE,
+ };
+ 
+-static int __devinit gpio_charger_probe(struct platform_device *pdev)
++static int gpio_charger_probe(struct platform_device *pdev)
+ {
+ 	const struct gpio_charger_platform_data *pdata = pdev->dev.platform_data;
+ 	struct gpio_charger *gpio_charger;
+diff --git a/drivers/power/intel_mid_battery.c b/drivers/power/intel_mid_battery.c
+index 8ba1c67af60e..0eb50b0daf74 100644
+--- a/drivers/power/intel_mid_battery.c
++++ b/drivers/power/intel_mid_battery.c
+@@ -649,7 +649,7 @@ static void pmic_battery_handle_intrpt(struct work_struct *work)
+  * PMIC battery initializes its internal data structue and other
+  * infrastructure components for it to work as expected.
+  */
+-static __devinit int probe(int irq, struct device *dev)
++static int probe(int irq, struct device *dev)
+ {
+ 	int retval = 0;
+ 	struct pmic_power_module_info *pbi;
+@@ -739,7 +739,7 @@ static __devinit int probe(int irq, struct device *dev)
+ 	return retval;
+ }
+ 
+-static int __devinit platform_pmic_battery_probe(struct platform_device *pdev)
++static int platform_pmic_battery_probe(struct platform_device *pdev)
+ {
+ 	return probe(pdev->id, &pdev->dev);
+ }
+diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c
+index 1f0c5857130b..3a1b9598d168 100644
+--- a/drivers/power/isp1704_charger.c
++++ b/drivers/power/isp1704_charger.c
+@@ -406,7 +406,7 @@ static inline int isp1704_test_ulpi(struct isp1704_charger *isp)
+ 	return -ENODEV;
+ }
+ 
+-static int __devinit isp1704_charger_probe(struct platform_device *pdev)
++static int isp1704_charger_probe(struct platform_device *pdev)
+ {
+ 	struct isp1704_charger	*isp;
+ 	int			ret = -ENODEV;
+diff --git a/drivers/power/jz4740-battery.c b/drivers/power/jz4740-battery.c
+index c9abfef66aa1..1f7d2ca0dbd2 100644
+--- a/drivers/power/jz4740-battery.c
++++ b/drivers/power/jz4740-battery.c
+@@ -238,7 +238,7 @@ static void jz_battery_work(struct work_struct *work)
+ 	schedule_delayed_work(&jz_battery->work, interval);
+ }
+ 
+-static int __devinit jz_battery_probe(struct platform_device *pdev)
++static int jz_battery_probe(struct platform_device *pdev)
+ {
+ 	int ret = 0;
+ 	struct jz_battery_platform_data *pdata = pdev->dev.parent->platform_data;
+diff --git a/drivers/power/lp8788-charger.c b/drivers/power/lp8788-charger.c
+index 5d743b75f5cf..3bdb4be8db2b 100644
+--- a/drivers/power/lp8788-charger.c
++++ b/drivers/power/lp8788-charger.c
+@@ -729,7 +729,7 @@ static const struct attribute_group lp8788_attr_group = {
+ 	.attrs = lp8788_charger_attr,
+ };
+ 
+-static __devinit int lp8788_charger_probe(struct platform_device *pdev)
++static int lp8788_charger_probe(struct platform_device *pdev)
+ {
+ 	struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
+ 	struct lp8788_charger *pchg;
+diff --git a/drivers/power/max17040_battery.c b/drivers/power/max17040_battery.c
+index fcc712e8aaeb..ae10a21ed70c 100644
+--- a/drivers/power/max17040_battery.c
++++ b/drivers/power/max17040_battery.c
+@@ -197,7 +197,7 @@ static enum power_supply_property max17040_battery_props[] = {
+ 	POWER_SUPPLY_PROP_CAPACITY,
+ };
+ 
+-static int __devinit max17040_probe(struct i2c_client *client,
++static int max17040_probe(struct i2c_client *client,
+ 			const struct i2c_device_id *id)
+ {
+ 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+diff --git a/drivers/power/max17042_battery.c b/drivers/power/max17042_battery.c
+index 0896fec2eecc..8752bc01a9ea 100644
+--- a/drivers/power/max17042_battery.c
++++ b/drivers/power/max17042_battery.c
+@@ -681,7 +681,7 @@ max17042_get_pdata(struct device *dev)
+ }
+ #endif
+ 
+-static int __devinit max17042_probe(struct i2c_client *client,
++static int max17042_probe(struct i2c_client *client,
+ 			const struct i2c_device_id *id)
+ {
+ 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+diff --git a/drivers/power/max8903_charger.c b/drivers/power/max8903_charger.c
+index 53ab51e8c892..83272c51f6a5 100644
+--- a/drivers/power/max8903_charger.c
++++ b/drivers/power/max8903_charger.c
+@@ -179,7 +179,7 @@ static irqreturn_t max8903_fault(int irq, void *_data)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static __devinit int max8903_probe(struct platform_device *pdev)
++static int max8903_probe(struct platform_device *pdev)
+ {
+ 	struct max8903_data *data;
+ 	struct device *dev = &pdev->dev;
+diff --git a/drivers/power/max8925_power.c b/drivers/power/max8925_power.c
+index 872806018d58..7b8191b08a46 100644
+--- a/drivers/power/max8925_power.c
++++ b/drivers/power/max8925_power.c
+@@ -356,7 +356,7 @@ do {									\
+ 			_irq, ret);					\
+ } while (0)
+ 
+-static __devinit int max8925_init_charger(struct max8925_chip *chip,
++static int max8925_init_charger(struct max8925_chip *chip,
+ 					  struct max8925_power_info *info)
+ {
+ 	int ret;
+@@ -426,7 +426,7 @@ static __devexit int max8925_deinit_charger(struct max8925_power_info *info)
+ 	return 0;
+ }
+ 
+-static __devinit int max8925_power_probe(struct platform_device *pdev)
++static int max8925_power_probe(struct platform_device *pdev)
+ {
+ 	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
+ 	struct max8925_power_pdata *pdata = NULL;
+diff --git a/drivers/power/max8997_charger.c b/drivers/power/max8997_charger.c
+index 19cfd2d12901..c6767dfd4c41 100644
+--- a/drivers/power/max8997_charger.c
++++ b/drivers/power/max8997_charger.c
+@@ -86,7 +86,7 @@ static int max8997_battery_get_property(struct power_supply *psy,
+ 	return 0;
+ }
+ 
+-static __devinit int max8997_battery_probe(struct platform_device *pdev)
++static int max8997_battery_probe(struct platform_device *pdev)
+ {
+ 	int ret = 0;
+ 	struct charger_data *charger;
+diff --git a/drivers/power/max8998_charger.c b/drivers/power/max8998_charger.c
+index 1db13638ef7f..9f34c80f358c 100644
+--- a/drivers/power/max8998_charger.c
++++ b/drivers/power/max8998_charger.c
+@@ -75,7 +75,7 @@ static int max8998_battery_get_property(struct power_supply *psy,
+ 	return 0;
+ }
+ 
+-static __devinit int max8998_battery_probe(struct platform_device *pdev)
++static int max8998_battery_probe(struct platform_device *pdev)
+ {
+ 	struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+ 	struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev);
+diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c
+index 31479115db73..60d5449a9960 100644
+--- a/drivers/power/olpc_battery.c
++++ b/drivers/power/olpc_battery.c
+@@ -598,7 +598,7 @@ static int olpc_battery_suspend(struct platform_device *pdev,
+ 	return 0;
+ }
+ 
+-static int __devinit olpc_battery_probe(struct platform_device *pdev)
++static int olpc_battery_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 	uint8_t status;
+diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c
+index 81bada0a3692..c0ba4ecb1943 100644
+--- a/drivers/power/pcf50633-charger.c
++++ b/drivers/power/pcf50633-charger.c
+@@ -366,7 +366,7 @@ static const u8 mbc_irq_handlers[] = {
+ 	PCF50633_IRQ_LOWBAT,
+ };
+ 
+-static int __devinit pcf50633_mbc_probe(struct platform_device *pdev)
++static int pcf50633_mbc_probe(struct platform_device *pdev)
+ {
+ 	struct pcf50633_mbc *mbc;
+ 	int ret;
+diff --git a/drivers/power/s3c_adc_battery.c b/drivers/power/s3c_adc_battery.c
+index 8b804a566756..d2ca989dcbdc 100644
+--- a/drivers/power/s3c_adc_battery.c
++++ b/drivers/power/s3c_adc_battery.c
+@@ -286,7 +286,7 @@ static irqreturn_t s3c_adc_bat_charged(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit s3c_adc_bat_probe(struct platform_device *pdev)
++static int s3c_adc_bat_probe(struct platform_device *pdev)
+ {
+ 	struct s3c_adc_client	*client;
+ 	struct s3c_adc_bat_pdata *pdata = pdev->dev.platform_data;
+diff --git a/drivers/power/sbs-battery.c b/drivers/power/sbs-battery.c
+index de57fdd75a8c..30280c5b1fb7 100644
+--- a/drivers/power/sbs-battery.c
++++ b/drivers/power/sbs-battery.c
+@@ -675,7 +675,7 @@ static struct sbs_platform_data *sbs_of_populate_pdata(
+ }
+ #endif
+ 
+-static int __devinit sbs_probe(struct i2c_client *client,
++static int sbs_probe(struct i2c_client *client,
+ 	const struct i2c_device_id *id)
+ {
+ 	struct sbs_info *chip;
+diff --git a/drivers/power/tosa_battery.c b/drivers/power/tosa_battery.c
+index 9625a765d566..d958c9f6d524 100644
+--- a/drivers/power/tosa_battery.c
++++ b/drivers/power/tosa_battery.c
+@@ -342,7 +342,7 @@ static int tosa_bat_resume(struct platform_device *dev)
+ #define tosa_bat_resume NULL
+ #endif
+ 
+-static int __devinit tosa_bat_probe(struct platform_device *dev)
++static int tosa_bat_probe(struct platform_device *dev)
+ {
+ 	int ret;
+ 
+diff --git a/drivers/power/wm831x_backup.c b/drivers/power/wm831x_backup.c
+index 6ea6fbd32c20..ef3b81788752 100644
+--- a/drivers/power/wm831x_backup.c
++++ b/drivers/power/wm831x_backup.c
+@@ -161,7 +161,7 @@ static enum power_supply_property wm831x_backup_props[] = {
+  *		Initialisation
+  *********************************************************************/
+ 
+-static __devinit int wm831x_backup_probe(struct platform_device *pdev)
++static int wm831x_backup_probe(struct platform_device *pdev)
+ {
+ 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
+ 	struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data;
+diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c
+index 6b6a678c7c81..d21af8a01af3 100644
+--- a/drivers/power/wm831x_power.c
++++ b/drivers/power/wm831x_power.c
+@@ -489,7 +489,7 @@ static irqreturn_t wm831x_pwr_src_irq(int irq, void *data)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static __devinit int wm831x_power_probe(struct platform_device *pdev)
++static int wm831x_power_probe(struct platform_device *pdev)
+ {
+ 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
+ 	struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data;
+diff --git a/drivers/power/wm8350_power.c b/drivers/power/wm8350_power.c
+index 50d5605f4fd2..6acb63a41a2d 100644
+--- a/drivers/power/wm8350_power.c
++++ b/drivers/power/wm8350_power.c
+@@ -442,7 +442,7 @@ static void free_charger_irq(struct wm8350 *wm8350)
+ 	wm8350_free_irq(wm8350, WM8350_IRQ_EXT_BAT_FB, wm8350);
+ }
+ 
+-static __devinit int wm8350_power_probe(struct platform_device *pdev)
++static int wm8350_power_probe(struct platform_device *pdev)
+ {
+ 	struct wm8350 *wm8350 = platform_get_drvdata(pdev);
+ 	struct wm8350_power *power = &wm8350->power;
+diff --git a/drivers/power/wm97xx_battery.c b/drivers/power/wm97xx_battery.c
+index 786d1cd685c3..4b3f7634fd30 100644
+--- a/drivers/power/wm97xx_battery.c
++++ b/drivers/power/wm97xx_battery.c
+@@ -162,7 +162,7 @@ static const struct dev_pm_ops wm97xx_bat_pm_ops = {
+ };
+ #endif
+ 
+-static int __devinit wm97xx_bat_probe(struct platform_device *dev)
++static int wm97xx_bat_probe(struct platform_device *dev)
+ {
+ 	int ret = 0;
+ 	int props = 1;	/* POWER_SUPPLY_PROP_PRESENT */
+diff --git a/drivers/power/z2_battery.c b/drivers/power/z2_battery.c
+index 406dbd3d6bff..ebf16296aca3 100644
+--- a/drivers/power/z2_battery.c
++++ b/drivers/power/z2_battery.c
+@@ -180,7 +180,7 @@ static int z2_batt_ps_init(struct z2_charger *charger, int props)
+ 	return 0;
+ }
+ 
+-static int __devinit z2_batt_probe(struct i2c_client *client,
++static int z2_batt_probe(struct i2c_client *client,
+ 				const struct i2c_device_id *id)
+ {
+ 	int ret = 0;

commit 28ea73f4c67cb3dd8c972b21d9fdf84ea78d6daa
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:20:40 2012 -0500
+
+    power: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Anton Vorontsov 
+    Cc: David Woodhouse 
+    Acked-by: Mark Brown 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/power/88pm860x_battery.c b/drivers/power/88pm860x_battery.c
+index beed5ecf75e1..ebf7bb5c57ed 100644
+--- a/drivers/power/88pm860x_battery.c
++++ b/drivers/power/88pm860x_battery.c
+@@ -1033,7 +1033,7 @@ static struct platform_driver pm860x_battery_driver = {
+ 		   .pm = &pm860x_battery_pm_ops,
+ 	},
+ 	.probe = pm860x_battery_probe,
+-	.remove = __devexit_p(pm860x_battery_remove),
++	.remove = pm860x_battery_remove,
+ };
+ module_platform_driver(pm860x_battery_driver);
+ 
+diff --git a/drivers/power/88pm860x_charger.c b/drivers/power/88pm860x_charger.c
+index 2dbeb1460901..fc051732e5dc 100644
+--- a/drivers/power/88pm860x_charger.c
++++ b/drivers/power/88pm860x_charger.c
+@@ -738,7 +738,7 @@ static struct platform_driver pm860x_charger_driver = {
+ 		   .owner = THIS_MODULE,
+ 	},
+ 	.probe = pm860x_charger_probe,
+-	.remove = __devexit_p(pm860x_charger_remove),
++	.remove = pm860x_charger_remove,
+ };
+ module_platform_driver(pm860x_charger_driver);
+ 
+diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
+index e3b6395b20dd..61867095d440 100644
+--- a/drivers/power/ab8500_btemp.c
++++ b/drivers/power/ab8500_btemp.c
+@@ -1101,7 +1101,7 @@ static int __devinit ab8500_btemp_probe(struct platform_device *pdev)
+ 
+ static struct platform_driver ab8500_btemp_driver = {
+ 	.probe = ab8500_btemp_probe,
+-	.remove = __devexit_p(ab8500_btemp_remove),
++	.remove = ab8500_btemp_remove,
+ 	.suspend = ab8500_btemp_suspend,
+ 	.resume = ab8500_btemp_resume,
+ 	.driver = {
+diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
+index 26ff759e2220..fe36df2680a3 100644
+--- a/drivers/power/ab8500_charger.c
++++ b/drivers/power/ab8500_charger.c
+@@ -2765,7 +2765,7 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev)
+ 
+ static struct platform_driver ab8500_charger_driver = {
+ 	.probe = ab8500_charger_probe,
+-	.remove = __devexit_p(ab8500_charger_remove),
++	.remove = ab8500_charger_remove,
+ 	.suspend = ab8500_charger_suspend,
+ 	.resume = ab8500_charger_resume,
+ 	.driver = {
+diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
+index 2db8cc254399..ff2f09c0c128 100644
+--- a/drivers/power/ab8500_fg.c
++++ b/drivers/power/ab8500_fg.c
+@@ -2614,7 +2614,7 @@ static int __devinit ab8500_fg_probe(struct platform_device *pdev)
+ 
+ static struct platform_driver ab8500_fg_driver = {
+ 	.probe = ab8500_fg_probe,
+-	.remove = __devexit_p(ab8500_fg_remove),
++	.remove = ab8500_fg_remove,
+ 	.suspend = ab8500_fg_suspend,
+ 	.resume = ab8500_fg_resume,
+ 	.driver = {
+diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c
+index 4d302803ffcc..6ed6b88f1fa8 100644
+--- a/drivers/power/abx500_chargalg.c
++++ b/drivers/power/abx500_chargalg.c
+@@ -1893,7 +1893,7 @@ static int __devinit abx500_chargalg_probe(struct platform_device *pdev)
+ 
+ static struct platform_driver abx500_chargalg_driver = {
+ 	.probe = abx500_chargalg_probe,
+-	.remove = __devexit_p(abx500_chargalg_remove),
++	.remove = abx500_chargalg_remove,
+ 	.suspend = abx500_chargalg_suspend,
+ 	.resume = abx500_chargalg_resume,
+ 	.driver = {
+diff --git a/drivers/power/avs/smartreflex.c b/drivers/power/avs/smartreflex.c
+index 24768a27e1d8..c7d441710423 100644
+--- a/drivers/power/avs/smartreflex.c
++++ b/drivers/power/avs/smartreflex.c
+@@ -1083,8 +1083,8 @@ static void __devexit omap_sr_shutdown(struct platform_device *pdev)
+ }
+ 
+ static struct platform_driver smartreflex_driver = {
+-	.remove         = __devexit_p(omap_sr_remove),
+-	.shutdown	= __devexit_p(omap_sr_shutdown),
++	.remove         = omap_sr_remove,
++	.shutdown	= omap_sr_shutdown,
+ 	.driver		= {
+ 		.name	= "smartreflex",
+ 	},
+diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
+index 5860d4dfbe9c..8faeb40cf78f 100644
+--- a/drivers/power/bq27x00_battery.c
++++ b/drivers/power/bq27x00_battery.c
+@@ -983,7 +983,7 @@ static int __devexit bq27000_battery_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver bq27000_battery_driver = {
+ 	.probe	= bq27000_battery_probe,
+-	.remove = __devexit_p(bq27000_battery_remove),
++	.remove = bq27000_battery_remove,
+ 	.driver = {
+ 		.name = "bq27000-battery",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
+index 8a0aca6364c7..5a1cc0a88483 100644
+--- a/drivers/power/charger-manager.c
++++ b/drivers/power/charger-manager.c
+@@ -1812,7 +1812,7 @@ static struct platform_driver charger_manager_driver = {
+ 		.pm = &charger_manager_pm,
+ 	},
+ 	.probe = charger_manager_probe,
+-	.remove = __devexit_p(charger_manager_remove),
++	.remove = charger_manager_remove,
+ 	.id_table = charger_manager_id,
+ };
+ 
+diff --git a/drivers/power/collie_battery.c b/drivers/power/collie_battery.c
+index b19bfe400f8c..cd9ef5103d07 100644
+--- a/drivers/power/collie_battery.c
++++ b/drivers/power/collie_battery.c
+@@ -367,7 +367,7 @@ static void __devexit collie_bat_remove(struct ucb1x00_dev *dev)
+ 
+ static struct ucb1x00_driver collie_bat_driver = {
+ 	.add		= collie_bat_probe,
+-	.remove		= __devexit_p(collie_bat_remove),
++	.remove		= collie_bat_remove,
+ 	.suspend	= collie_bat_suspend,
+ 	.resume		= collie_bat_resume,
+ };
+diff --git a/drivers/power/da9052-battery.c b/drivers/power/da9052-battery.c
+index d9d034d7496f..753d4ba483f7 100644
+--- a/drivers/power/da9052-battery.c
++++ b/drivers/power/da9052-battery.c
+@@ -648,7 +648,7 @@ static int __devexit da9052_bat_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver da9052_bat_driver = {
+ 	.probe = da9052_bat_probe,
+-	.remove = __devexit_p(da9052_bat_remove),
++	.remove = da9052_bat_remove,
+ 	.driver = {
+ 		.name = "da9052-bat",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/power/ds2780_battery.c b/drivers/power/ds2780_battery.c
+index 74fad941c56c..2154822e9c86 100644
+--- a/drivers/power/ds2780_battery.c
++++ b/drivers/power/ds2780_battery.c
+@@ -837,7 +837,7 @@ static struct platform_driver ds2780_battery_driver = {
+ 		.name = "ds2780-battery",
+ 	},
+ 	.probe	  = ds2780_battery_probe,
+-	.remove   = __devexit_p(ds2780_battery_remove),
++	.remove   = ds2780_battery_remove,
+ };
+ 
+ module_platform_driver(ds2780_battery_driver);
+diff --git a/drivers/power/ds2781_battery.c b/drivers/power/ds2781_battery.c
+index 22b3c8c93552..ce1200914b89 100644
+--- a/drivers/power/ds2781_battery.c
++++ b/drivers/power/ds2781_battery.c
+@@ -827,7 +827,7 @@ static struct platform_driver ds2781_battery_driver = {
+ 		.name = "ds2781-battery",
+ 	},
+ 	.probe	  = ds2781_battery_probe,
+-	.remove   = __devexit_p(ds2781_battery_remove),
++	.remove   = ds2781_battery_remove,
+ };
+ module_platform_driver(ds2781_battery_driver);
+ 
+diff --git a/drivers/power/generic-adc-battery.c b/drivers/power/generic-adc-battery.c
+index 9bdf44470396..60a0f29a9ac9 100644
+--- a/drivers/power/generic-adc-battery.c
++++ b/drivers/power/generic-adc-battery.c
+@@ -413,7 +413,7 @@ static struct platform_driver gab_driver = {
+ 		.pm	= GAB_PM_OPS
+ 	},
+ 	.probe		= gab_probe,
+-	.remove		= __devexit_p(gab_remove),
++	.remove		= gab_remove,
+ };
+ module_platform_driver(gab_driver);
+ 
+diff --git a/drivers/power/gpio-charger.c b/drivers/power/gpio-charger.c
+index cb2aa3195687..e74fb2fbdb2c 100644
+--- a/drivers/power/gpio-charger.c
++++ b/drivers/power/gpio-charger.c
+@@ -177,7 +177,7 @@ static SIMPLE_DEV_PM_OPS(gpio_charger_pm_ops, NULL, gpio_charger_resume);
+ 
+ static struct platform_driver gpio_charger_driver = {
+ 	.probe = gpio_charger_probe,
+-	.remove = __devexit_p(gpio_charger_remove),
++	.remove = gpio_charger_remove,
+ 	.driver = {
+ 		.name = "gpio-charger",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/power/intel_mid_battery.c b/drivers/power/intel_mid_battery.c
+index d09649706bd3..8ba1c67af60e 100644
+--- a/drivers/power/intel_mid_battery.c
++++ b/drivers/power/intel_mid_battery.c
+@@ -776,7 +776,7 @@ static struct platform_driver platform_pmic_battery_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = platform_pmic_battery_probe,
+-	.remove = __devexit_p(platform_pmic_battery_remove),
++	.remove = platform_pmic_battery_remove,
+ };
+ 
+ module_platform_driver(platform_pmic_battery_driver);
+diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c
+index 122911978da2..1f0c5857130b 100644
+--- a/drivers/power/isp1704_charger.c
++++ b/drivers/power/isp1704_charger.c
+@@ -502,7 +502,7 @@ static struct platform_driver isp1704_charger_driver = {
+ 		.name = "isp1704_charger",
+ 	},
+ 	.probe = isp1704_charger_probe,
+-	.remove = __devexit_p(isp1704_charger_remove),
++	.remove = isp1704_charger_remove,
+ };
+ 
+ module_platform_driver(isp1704_charger_driver);
+diff --git a/drivers/power/jz4740-battery.c b/drivers/power/jz4740-battery.c
+index ffbed5e5b945..c9abfef66aa1 100644
+--- a/drivers/power/jz4740-battery.c
++++ b/drivers/power/jz4740-battery.c
+@@ -431,7 +431,7 @@ static const struct dev_pm_ops jz_battery_pm_ops = {
+ 
+ static struct platform_driver jz_battery_driver = {
+ 	.probe		= jz_battery_probe,
+-	.remove		= __devexit_p(jz_battery_remove),
++	.remove		= jz_battery_remove,
+ 	.driver = {
+ 		.name = "jz4740-battery",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/power/lp8727_charger.c b/drivers/power/lp8727_charger.c
+index c628224b7f58..c6ba2ff215de 100644
+--- a/drivers/power/lp8727_charger.c
++++ b/drivers/power/lp8727_charger.c
+@@ -542,7 +542,7 @@ static struct i2c_driver lp8727_driver = {
+ 		   .name = "lp8727",
+ 		   },
+ 	.probe = lp8727_probe,
+-	.remove = __devexit_p(lp8727_remove),
++	.remove = lp8727_remove,
+ 	.id_table = lp8727_ids,
+ };
+ module_i2c_driver(lp8727_driver);
+diff --git a/drivers/power/lp8788-charger.c b/drivers/power/lp8788-charger.c
+index e852d12cd077..5d743b75f5cf 100644
+--- a/drivers/power/lp8788-charger.c
++++ b/drivers/power/lp8788-charger.c
+@@ -781,7 +781,7 @@ static int __devexit lp8788_charger_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver lp8788_charger_driver = {
+ 	.probe = lp8788_charger_probe,
+-	.remove = __devexit_p(lp8788_charger_remove),
++	.remove = lp8788_charger_remove,
+ 	.driver = {
+ 		.name = LP8788_DEV_CHARGER,
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/power/max17040_battery.c b/drivers/power/max17040_battery.c
+index 58e67830143c..fcc712e8aaeb 100644
+--- a/drivers/power/max17040_battery.c
++++ b/drivers/power/max17040_battery.c
+@@ -285,7 +285,7 @@ static struct i2c_driver max17040_i2c_driver = {
+ 		.name	= "max17040",
+ 	},
+ 	.probe		= max17040_probe,
+-	.remove		= __devexit_p(max17040_remove),
++	.remove		= max17040_remove,
+ 	.suspend	= max17040_suspend,
+ 	.resume		= max17040_resume,
+ 	.id_table	= max17040_id,
+diff --git a/drivers/power/max17042_battery.c b/drivers/power/max17042_battery.c
+index 74abc6c755b4..0896fec2eecc 100644
+--- a/drivers/power/max17042_battery.c
++++ b/drivers/power/max17042_battery.c
+@@ -851,7 +851,7 @@ static struct i2c_driver max17042_i2c_driver = {
+ 		.pm	= MAX17042_PM_OPS,
+ 	},
+ 	.probe		= max17042_probe,
+-	.remove		= __devexit_p(max17042_remove),
++	.remove		= max17042_remove,
+ 	.id_table	= max17042_id,
+ };
+ module_i2c_driver(max17042_i2c_driver);
+diff --git a/drivers/power/max8903_charger.c b/drivers/power/max8903_charger.c
+index 3e23f43e98af..53ab51e8c892 100644
+--- a/drivers/power/max8903_charger.c
++++ b/drivers/power/max8903_charger.c
+@@ -367,7 +367,7 @@ static __devexit int max8903_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver max8903_driver = {
+ 	.probe	= max8903_probe,
+-	.remove	= __devexit_p(max8903_remove),
++	.remove	= max8903_remove,
+ 	.driver = {
+ 		.name	= "max8903-charger",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/power/max8925_power.c b/drivers/power/max8925_power.c
+index daa333bd7ebb..872806018d58 100644
+--- a/drivers/power/max8925_power.c
++++ b/drivers/power/max8925_power.c
+@@ -517,7 +517,7 @@ static __devexit int max8925_power_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver max8925_power_driver = {
+ 	.probe	= max8925_power_probe,
+-	.remove	= __devexit_p(max8925_power_remove),
++	.remove	= max8925_power_remove,
+ 	.driver	= {
+ 		.name	= "max8925-power",
+ 	},
+diff --git a/drivers/power/max8997_charger.c b/drivers/power/max8997_charger.c
+index 6e88c5d026b9..19cfd2d12901 100644
+--- a/drivers/power/max8997_charger.c
++++ b/drivers/power/max8997_charger.c
+@@ -187,7 +187,7 @@ static struct platform_driver max8997_battery_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = max8997_battery_probe,
+-	.remove = __devexit_p(max8997_battery_remove),
++	.remove = max8997_battery_remove,
+ 	.id_table = max8997_battery_id,
+ };
+ 
+diff --git a/drivers/power/max8998_charger.c b/drivers/power/max8998_charger.c
+index 6dc01c255592..1db13638ef7f 100644
+--- a/drivers/power/max8998_charger.c
++++ b/drivers/power/max8998_charger.c
+@@ -199,7 +199,7 @@ static struct platform_driver max8998_battery_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = max8998_battery_probe,
+-	.remove = __devexit_p(max8998_battery_remove),
++	.remove = max8998_battery_remove,
+ 	.id_table = max8998_battery_id,
+ };
+ 
+diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c
+index a89a41acf9c5..31479115db73 100644
+--- a/drivers/power/olpc_battery.c
++++ b/drivers/power/olpc_battery.c
+@@ -681,7 +681,7 @@ static struct platform_driver olpc_battery_driver = {
+ 		.of_match_table = olpc_battery_ids,
+ 	},
+ 	.probe = olpc_battery_probe,
+-	.remove = __devexit_p(olpc_battery_remove),
++	.remove = olpc_battery_remove,
+ 	.suspend = olpc_battery_suspend,
+ };
+ 
+diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c
+index 3d1e9efb6f53..81bada0a3692 100644
+--- a/drivers/power/pcf50633-charger.c
++++ b/drivers/power/pcf50633-charger.c
+@@ -471,7 +471,7 @@ static struct platform_driver pcf50633_mbc_driver = {
+ 		.name = "pcf50633-mbc",
+ 	},
+ 	.probe = pcf50633_mbc_probe,
+-	.remove = __devexit_p(pcf50633_mbc_remove),
++	.remove = pcf50633_mbc_remove,
+ };
+ 
+ module_platform_driver(pcf50633_mbc_driver);
+diff --git a/drivers/power/sbs-battery.c b/drivers/power/sbs-battery.c
+index 4146596d254b..de57fdd75a8c 100644
+--- a/drivers/power/sbs-battery.c
++++ b/drivers/power/sbs-battery.c
+@@ -853,7 +853,7 @@ MODULE_DEVICE_TABLE(i2c, sbs_id);
+ 
+ static struct i2c_driver sbs_battery_driver = {
+ 	.probe		= sbs_probe,
+-	.remove		= __devexit_p(sbs_remove),
++	.remove		= sbs_remove,
+ 	.suspend	= sbs_suspend,
+ 	.resume		= sbs_resume,
+ 	.id_table	= sbs_id,
+diff --git a/drivers/power/smb347-charger.c b/drivers/power/smb347-charger.c
+index a9707c11fbed..acf84e80fe98 100644
+--- a/drivers/power/smb347-charger.c
++++ b/drivers/power/smb347-charger.c
+@@ -1313,7 +1313,7 @@ static struct i2c_driver smb347_driver = {
+ 		.name = "smb347",
+ 	},
+ 	.probe        = smb347_probe,
+-	.remove       = __devexit_p(smb347_remove),
++	.remove       = smb347_remove,
+ 	.id_table     = smb347_id,
+ };
+ 
+diff --git a/drivers/power/tosa_battery.c b/drivers/power/tosa_battery.c
+index 51199b5ce221..9625a765d566 100644
+--- a/drivers/power/tosa_battery.c
++++ b/drivers/power/tosa_battery.c
+@@ -433,7 +433,7 @@ static struct platform_driver tosa_bat_driver = {
+ 	.driver.name	= "wm97xx-battery",
+ 	.driver.owner	= THIS_MODULE,
+ 	.probe		= tosa_bat_probe,
+-	.remove		= __devexit_p(tosa_bat_remove),
++	.remove		= tosa_bat_remove,
+ 	.suspend	= tosa_bat_suspend,
+ 	.resume		= tosa_bat_resume,
+ };
+diff --git a/drivers/power/wm831x_backup.c b/drivers/power/wm831x_backup.c
+index 6243e6975126..6ea6fbd32c20 100644
+--- a/drivers/power/wm831x_backup.c
++++ b/drivers/power/wm831x_backup.c
+@@ -220,7 +220,7 @@ static __devexit int wm831x_backup_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver wm831x_backup_driver = {
+ 	.probe = wm831x_backup_probe,
+-	.remove = __devexit_p(wm831x_backup_remove),
++	.remove = wm831x_backup_remove,
+ 	.driver = {
+ 		.name = "wm831x-backup",
+ 	},
+diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c
+index fc1ad9551182..6b6a678c7c81 100644
+--- a/drivers/power/wm831x_power.c
++++ b/drivers/power/wm831x_power.c
+@@ -654,7 +654,7 @@ static __devexit int wm831x_power_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver wm831x_power_driver = {
+ 	.probe = wm831x_power_probe,
+-	.remove = __devexit_p(wm831x_power_remove),
++	.remove = wm831x_power_remove,
+ 	.driver = {
+ 		.name = "wm831x-power",
+ 	},
+diff --git a/drivers/power/wm8350_power.c b/drivers/power/wm8350_power.c
+index fae04d384657..50d5605f4fd2 100644
+--- a/drivers/power/wm8350_power.c
++++ b/drivers/power/wm8350_power.c
+@@ -516,7 +516,7 @@ static __devexit int wm8350_power_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver wm8350_power_driver = {
+ 	.probe = wm8350_power_probe,
+-	.remove = __devexit_p(wm8350_power_remove),
++	.remove = wm8350_power_remove,
+ 	.driver = {
+ 		.name = "wm8350-power",
+ 	},
+diff --git a/drivers/power/wm97xx_battery.c b/drivers/power/wm97xx_battery.c
+index e128a813dc24..786d1cd685c3 100644
+--- a/drivers/power/wm97xx_battery.c
++++ b/drivers/power/wm97xx_battery.c
+@@ -287,7 +287,7 @@ static struct platform_driver wm97xx_bat_driver = {
+ #endif
+ 	},
+ 	.probe		= wm97xx_bat_probe,
+-	.remove		= __devexit_p(wm97xx_bat_remove),
++	.remove		= wm97xx_bat_remove,
+ };
+ 
+ module_platform_driver(wm97xx_bat_driver);
+diff --git a/drivers/power/z2_battery.c b/drivers/power/z2_battery.c
+index 5757d0d6782f..406dbd3d6bff 100644
+--- a/drivers/power/z2_battery.c
++++ b/drivers/power/z2_battery.c
+@@ -313,7 +313,7 @@ static struct i2c_driver z2_batt_driver = {
+ 		.pm	= Z2_BATTERY_PM_OPS
+ 	},
+ 	.probe		= z2_batt_probe,
+-	.remove		= __devexit_p(z2_batt_remove),
++	.remove		= z2_batt_remove,
+ 	.id_table	= z2_batt_id,
+ };
+ module_i2c_driver(z2_batt_driver);

commit e533a349c0258f38a67afa1c2402a12f46227049
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:25:52 2012 -0500
+
+    hwspinlock: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Ohad Ben-Cohen 
+    Cc: Srinidhi Kasagar 
+    Acked-by: Linus Walleij 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/hwspinlock/omap_hwspinlock.c b/drivers/hwspinlock/omap_hwspinlock.c
+index f21b2ed6e185..292869cc9034 100644
+--- a/drivers/hwspinlock/omap_hwspinlock.c
++++ b/drivers/hwspinlock/omap_hwspinlock.c
+@@ -142,7 +142,7 @@ static int omap_hwspinlock_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit omap_hwspinlock_remove(struct platform_device *pdev)
++static int omap_hwspinlock_remove(struct platform_device *pdev)
+ {
+ 	struct hwspinlock_device *bank = platform_get_drvdata(pdev);
+ 	void __iomem *io_base = bank->lock[0].priv - LOCK_BASE_OFFSET;
+diff --git a/drivers/hwspinlock/u8500_hsem.c b/drivers/hwspinlock/u8500_hsem.c
+index 5a5b3f2e4eb6..401c33bcdb45 100644
+--- a/drivers/hwspinlock/u8500_hsem.c
++++ b/drivers/hwspinlock/u8500_hsem.c
+@@ -148,7 +148,7 @@ static int u8500_hsem_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit u8500_hsem_remove(struct platform_device *pdev)
++static int u8500_hsem_remove(struct platform_device *pdev)
+ {
+ 	struct hwspinlock_device *bank = platform_get_drvdata(pdev);
+ 	void __iomem *io_base = bank->lock[0].priv - HSEM_REGISTER_OFFSET;

commit 571291066d053c34d28de26a6d9d96ac7d171a61
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:23:22 2012 -0500
+
+    hwspinlock: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Ohad Ben-Cohen 
+    Cc: Srinidhi Kasagar 
+    Acked-by: Linus Walleij 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/hwspinlock/omap_hwspinlock.c b/drivers/hwspinlock/omap_hwspinlock.c
+index 28640b8a81a1..f21b2ed6e185 100644
+--- a/drivers/hwspinlock/omap_hwspinlock.c
++++ b/drivers/hwspinlock/omap_hwspinlock.c
+@@ -78,7 +78,7 @@ static const struct hwspinlock_ops omap_hwspinlock_ops = {
+ 	.relax = omap_hwspinlock_relax,
+ };
+ 
+-static int __devinit omap_hwspinlock_probe(struct platform_device *pdev)
++static int omap_hwspinlock_probe(struct platform_device *pdev)
+ {
+ 	struct hwspinlock_pdata *pdata = pdev->dev.platform_data;
+ 	struct hwspinlock_device *bank;
+diff --git a/drivers/hwspinlock/u8500_hsem.c b/drivers/hwspinlock/u8500_hsem.c
+index 4039810e06d6..5a5b3f2e4eb6 100644
+--- a/drivers/hwspinlock/u8500_hsem.c
++++ b/drivers/hwspinlock/u8500_hsem.c
+@@ -91,7 +91,7 @@ static const struct hwspinlock_ops u8500_hwspinlock_ops = {
+ 	.relax		= u8500_hsem_relax,
+ };
+ 
+-static int __devinit u8500_hsem_probe(struct platform_device *pdev)
++static int u8500_hsem_probe(struct platform_device *pdev)
+ {
+ 	struct hwspinlock_pdata *pdata = pdev->dev.platform_data;
+ 	struct hwspinlock_device *bank;

commit 9eb26bddfc586da0a9d10646150acb2d120c3890
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:20:13 2012 -0500
+
+    hwspinlock: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Ohad Ben-Cohen 
+    Cc: Srinidhi Kasagar 
+    Acked-by: Linus Walleij 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/hwspinlock/omap_hwspinlock.c b/drivers/hwspinlock/omap_hwspinlock.c
+index 887d34effb3a..28640b8a81a1 100644
+--- a/drivers/hwspinlock/omap_hwspinlock.c
++++ b/drivers/hwspinlock/omap_hwspinlock.c
+@@ -163,7 +163,7 @@ static int __devexit omap_hwspinlock_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver omap_hwspinlock_driver = {
+ 	.probe		= omap_hwspinlock_probe,
+-	.remove		= __devexit_p(omap_hwspinlock_remove),
++	.remove		= omap_hwspinlock_remove,
+ 	.driver		= {
+ 		.name	= "omap_hwspinlock",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/hwspinlock/u8500_hsem.c b/drivers/hwspinlock/u8500_hsem.c
+index 86980fe04117..4039810e06d6 100644
+--- a/drivers/hwspinlock/u8500_hsem.c
++++ b/drivers/hwspinlock/u8500_hsem.c
+@@ -172,7 +172,7 @@ static int __devexit u8500_hsem_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver u8500_hsem_driver = {
+ 	.probe		= u8500_hsem_probe,
+-	.remove		= __devexit_p(u8500_hsem_remove),
++	.remove		= u8500_hsem_remove,
+ 	.driver		= {
+ 		.name	= "u8500_hsem",
+ 		.owner	= THIS_MODULE,

commit 206210ce68c1feb1d9d05839ceacc97ad1b0b324
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:25:50 2012 -0500
+
+    gpio: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Grant Likely 
+    Acked-by: Linus Walleij 
+    Cc: Peter Tyser 
+    Acked-by: Mark Brown 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c
+index 2e6df4180dea..464be961f605 100644
+--- a/drivers/gpio/gpio-74x164.c
++++ b/drivers/gpio/gpio-74x164.c
+@@ -181,7 +181,7 @@ static int gen_74x164_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit gen_74x164_remove(struct spi_device *spi)
++static int gen_74x164_remove(struct spi_device *spi)
+ {
+ 	struct gen_74x164_chip *chip;
+ 	int ret;
+diff --git a/drivers/gpio/gpio-ab8500.c b/drivers/gpio/gpio-ab8500.c
+index 0a636de39989..983ad425f0ac 100644
+--- a/drivers/gpio/gpio-ab8500.c
++++ b/drivers/gpio/gpio-ab8500.c
+@@ -474,7 +474,7 @@ static int ab8500_gpio_probe(struct platform_device *pdev)
+  * ab8500_gpio_remove() - remove Ab8500-gpio driver
+  * @pdev :	Platform device registered
+  */
+-static int __devexit ab8500_gpio_remove(struct platform_device *pdev)
++static int ab8500_gpio_remove(struct platform_device *pdev)
+ {
+ 	struct ab8500_gpio *ab8500_gpio = platform_get_drvdata(pdev);
+ 	int ret;
+diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c
+index 2a34204bc729..e60567fc5073 100644
+--- a/drivers/gpio/gpio-adnp.c
++++ b/drivers/gpio/gpio-adnp.c
+@@ -563,7 +563,7 @@ static int adnp_i2c_probe(struct i2c_client *client,
+ 	return err;
+ }
+ 
+-static __devexit int adnp_i2c_remove(struct i2c_client *client)
++static int adnp_i2c_remove(struct i2c_client *client)
+ {
+ 	struct adnp *adnp = i2c_get_clientdata(client);
+ 	struct device_node *np = client->dev.of_node;
+diff --git a/drivers/gpio/gpio-adp5520.c b/drivers/gpio/gpio-adp5520.c
+index b9fac75b4ddd..8afa95f831b1 100644
+--- a/drivers/gpio/gpio-adp5520.c
++++ b/drivers/gpio/gpio-adp5520.c
+@@ -167,7 +167,7 @@ static int adp5520_gpio_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit adp5520_gpio_remove(struct platform_device *pdev)
++static int adp5520_gpio_remove(struct platform_device *pdev)
+ {
+ 	struct adp5520_gpio *dev;
+ 	int ret;
+diff --git a/drivers/gpio/gpio-adp5588.c b/drivers/gpio/gpio-adp5588.c
+index 27001ec3bcbb..2ba56987db04 100644
+--- a/drivers/gpio/gpio-adp5588.c
++++ b/drivers/gpio/gpio-adp5588.c
+@@ -438,7 +438,7 @@ static int adp5588_gpio_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit adp5588_gpio_remove(struct i2c_client *client)
++static int adp5588_gpio_remove(struct i2c_client *client)
+ {
+ 	struct adp5588_gpio_platform_data *pdata = client->dev.platform_data;
+ 	struct adp5588_gpio *dev = i2c_get_clientdata(client);
+diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c
+index 0a76fb0f66ce..0ea853f68db2 100644
+--- a/drivers/gpio/gpio-arizona.c
++++ b/drivers/gpio/gpio-arizona.c
+@@ -141,7 +141,7 @@ static int arizona_gpio_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit arizona_gpio_remove(struct platform_device *pdev)
++static int arizona_gpio_remove(struct platform_device *pdev)
+ {
+ 	struct arizona_gpio *arizona_gpio = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/gpio/gpio-cs5535.c b/drivers/gpio/gpio-cs5535.c
+index d4a6d82d7a3e..c0a3aeba6f21 100644
+--- a/drivers/gpio/gpio-cs5535.c
++++ b/drivers/gpio/gpio-cs5535.c
+@@ -355,7 +355,7 @@ static int cs5535_gpio_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit cs5535_gpio_remove(struct platform_device *pdev)
++static int cs5535_gpio_remove(struct platform_device *pdev)
+ {
+ 	struct resource *r;
+ 	int err;
+diff --git a/drivers/gpio/gpio-da9052.c b/drivers/gpio/gpio-da9052.c
+index 2139825c4d59..a05aacd2777a 100644
+--- a/drivers/gpio/gpio-da9052.c
++++ b/drivers/gpio/gpio-da9052.c
+@@ -229,7 +229,7 @@ static int da9052_gpio_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit da9052_gpio_remove(struct platform_device *pdev)
++static int da9052_gpio_remove(struct platform_device *pdev)
+ {
+ 	struct da9052_gpio *gpio = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c
+index 6253a05349ef..320a718cab40 100644
+--- a/drivers/gpio/gpio-em.c
++++ b/drivers/gpio/gpio-em.c
+@@ -375,7 +375,7 @@ static int em_gio_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit em_gio_remove(struct platform_device *pdev)
++static int em_gio_remove(struct platform_device *pdev)
+ {
+ 	struct em_gio_priv *p = platform_get_drvdata(pdev);
+ 	struct resource *irq[2];
+diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c
+index be3759648149..05fcc0f247ca 100644
+--- a/drivers/gpio/gpio-generic.c
++++ b/drivers/gpio/gpio-generic.c
+@@ -507,7 +507,7 @@ static int bgpio_pdev_probe(struct platform_device *pdev)
+ 	return gpiochip_add(&bgc->gc);
+ }
+ 
+-static int __devexit bgpio_pdev_remove(struct platform_device *pdev)
++static int bgpio_pdev_remove(struct platform_device *pdev)
+ {
+ 	struct bgpio_chip *bgc = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c
+index 3ff9ff671e31..6cc87ac8e019 100644
+--- a/drivers/gpio/gpio-ich.c
++++ b/drivers/gpio/gpio-ich.c
+@@ -442,7 +442,7 @@ static int ichx_gpio_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit ichx_gpio_remove(struct platform_device *pdev)
++static int ichx_gpio_remove(struct platform_device *pdev)
+ {
+ 	int err;
+ 
+diff --git a/drivers/gpio/gpio-janz-ttl.c b/drivers/gpio/gpio-janz-ttl.c
+index cd28270672f2..7d0a04169a35 100644
+--- a/drivers/gpio/gpio-janz-ttl.c
++++ b/drivers/gpio/gpio-janz-ttl.c
+@@ -211,7 +211,7 @@ static int ttl_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit ttl_remove(struct platform_device *pdev)
++static int ttl_remove(struct platform_device *pdev)
+ {
+ 	struct ttl_module *mod = platform_get_drvdata(pdev);
+ 	struct device *dev = &pdev->dev;
+diff --git a/drivers/gpio/gpio-langwell.c b/drivers/gpio/gpio-langwell.c
+index a3bf90d4e93b..e77b2b3e94af 100644
+--- a/drivers/gpio/gpio-langwell.c
++++ b/drivers/gpio/gpio-langwell.c
+@@ -484,7 +484,7 @@ static int wp_gpio_probe(struct platform_device *pdev)
+ 	return retval;
+ }
+ 
+-static int __devexit wp_gpio_remove(struct platform_device *pdev)
++static int wp_gpio_remove(struct platform_device *pdev)
+ {
+ 	struct lnw_gpio *lnw = platform_get_drvdata(pdev);
+ 	int err;
+diff --git a/drivers/gpio/gpio-max7300.c b/drivers/gpio/gpio-max7300.c
+index 5c92414e4d60..4b6b9a04e326 100644
+--- a/drivers/gpio/gpio-max7300.c
++++ b/drivers/gpio/gpio-max7300.c
+@@ -55,7 +55,7 @@ static int max7300_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit max7300_remove(struct i2c_client *client)
++static int max7300_remove(struct i2c_client *client)
+ {
+ 	return __max730x_remove(&client->dev);
+ }
+diff --git a/drivers/gpio/gpio-max7301.c b/drivers/gpio/gpio-max7301.c
+index cf5d5b3a0e0b..c6c535c1310e 100644
+--- a/drivers/gpio/gpio-max7301.c
++++ b/drivers/gpio/gpio-max7301.c
+@@ -75,7 +75,7 @@ static int max7301_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit max7301_remove(struct spi_device *spi)
++static int max7301_remove(struct spi_device *spi)
+ {
+ 	return __max730x_remove(&spi->dev);
+ }
+diff --git a/drivers/gpio/gpio-max730x.c b/drivers/gpio/gpio-max730x.c
+index 91b4f45ef042..22b75825a39e 100644
+--- a/drivers/gpio/gpio-max730x.c
++++ b/drivers/gpio/gpio-max730x.c
+@@ -226,7 +226,7 @@ int __max730x_probe(struct max7301 *ts)
+ }
+ EXPORT_SYMBOL_GPL(__max730x_probe);
+ 
+-int __devexit __max730x_remove(struct device *dev)
++int __max730x_remove(struct device *dev)
+ {
+ 	struct max7301 *ts = dev_get_drvdata(dev);
+ 	int ret;
+diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c
+index 5edd2cb3b4a7..1e0467ce4c37 100644
+--- a/drivers/gpio/gpio-max732x.c
++++ b/drivers/gpio/gpio-max732x.c
+@@ -651,7 +651,7 @@ static int max732x_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit max732x_remove(struct i2c_client *client)
++static int max732x_remove(struct i2c_client *client)
+ {
+ 	struct max732x_platform_data *pdata = client->dev.platform_data;
+ 	struct max732x_chip *chip = i2c_get_clientdata(client);
+diff --git a/drivers/gpio/gpio-mc33880.c b/drivers/gpio/gpio-mc33880.c
+index 79fc430de247..6a8fdc26ae6a 100644
+--- a/drivers/gpio/gpio-mc33880.c
++++ b/drivers/gpio/gpio-mc33880.c
+@@ -147,7 +147,7 @@ static int mc33880_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit mc33880_remove(struct spi_device *spi)
++static int mc33880_remove(struct spi_device *spi)
+ {
+ 	struct mc33880 *mc;
+ 	int ret;
+diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c
+index 45079aeb60bc..ce620f1ef4aa 100644
+--- a/drivers/gpio/gpio-mcp23s08.c
++++ b/drivers/gpio/gpio-mcp23s08.c
+@@ -508,7 +508,7 @@ static int mcp230xx_probe(struct i2c_client *client,
+ 	return status;
+ }
+ 
+-static int __devexit mcp230xx_remove(struct i2c_client *client)
++static int mcp230xx_remove(struct i2c_client *client)
+ {
+ 	struct mcp23s08 *mcp = i2c_get_clientdata(client);
+ 	int status;
+diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c
+index 934b9bce6282..b73366523fae 100644
+--- a/drivers/gpio/gpio-ml-ioh.c
++++ b/drivers/gpio/gpio-ml-ioh.c
+@@ -517,7 +517,7 @@ static int ioh_gpio_probe(struct pci_dev *pdev,
+ 	return ret;
+ }
+ 
+-static void __devexit ioh_gpio_remove(struct pci_dev *pdev)
++static void ioh_gpio_remove(struct pci_dev *pdev)
+ {
+ 	int err;
+ 	int i;
+diff --git a/drivers/gpio/gpio-msm-v2.c b/drivers/gpio/gpio-msm-v2.c
+index 5451bec942ef..55a7e7769af6 100644
+--- a/drivers/gpio/gpio-msm-v2.c
++++ b/drivers/gpio/gpio-msm-v2.c
+@@ -376,7 +376,7 @@ static int msm_gpio_probe(struct platform_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devexit msm_gpio_remove(struct platform_device *dev)
++static int msm_gpio_remove(struct platform_device *dev)
+ {
+ 	int ret = gpiochip_remove(&msm_gpio.gpio_chip);
+ 
+diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c
+index 09568a4b7799..bb2b66be17a4 100644
+--- a/drivers/gpio/gpio-pch.c
++++ b/drivers/gpio/gpio-pch.c
+@@ -442,7 +442,7 @@ static int pch_gpio_probe(struct pci_dev *pdev,
+ 	return ret;
+ }
+ 
+-static void __devexit pch_gpio_remove(struct pci_dev *pdev)
++static void pch_gpio_remove(struct pci_dev *pdev)
+ {
+ 	int err;
+ 	struct pch_gpio *chip = pci_get_drvdata(pdev);
+diff --git a/drivers/gpio/gpio-rc5t583.c b/drivers/gpio/gpio-rc5t583.c
+index 59ee5de68e50..e63d6a397e17 100644
+--- a/drivers/gpio/gpio-rc5t583.c
++++ b/drivers/gpio/gpio-rc5t583.c
+@@ -146,7 +146,7 @@ static int rc5t583_gpio_probe(struct platform_device *pdev)
+ 	return gpiochip_add(&rc5t583_gpio->gpio_chip);
+ }
+ 
+-static int __devexit rc5t583_gpio_remove(struct platform_device *pdev)
++static int rc5t583_gpio_remove(struct platform_device *pdev)
+ {
+ 	struct rc5t583_gpio *rc5t583_gpio = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/gpio/gpio-rdc321x.c b/drivers/gpio/gpio-rdc321x.c
+index dd3b49f09844..1bf55f67f7a5 100644
+--- a/drivers/gpio/gpio-rdc321x.c
++++ b/drivers/gpio/gpio-rdc321x.c
+@@ -206,7 +206,7 @@ static int rdc321x_gpio_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit rdc321x_gpio_remove(struct platform_device *pdev)
++static int rdc321x_gpio_remove(struct platform_device *pdev)
+ {
+ 	int ret;
+ 	struct rdc321x_gpio *rdc321x_gpio_dev = platform_get_drvdata(pdev);
+diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
+index 4498855c7d74..edae963f4625 100644
+--- a/drivers/gpio/gpio-sch.c
++++ b/drivers/gpio/gpio-sch.c
+@@ -271,7 +271,7 @@ static int sch_gpio_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit sch_gpio_remove(struct platform_device *pdev)
++static int sch_gpio_remove(struct platform_device *pdev)
+ {
+ 	struct resource *res;
+ 	if (gpio_ba) {
+diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c
+index 72cf6183ee9f..6dff78b19725 100644
+--- a/drivers/gpio/gpio-stmpe.c
++++ b/drivers/gpio/gpio-stmpe.c
+@@ -378,7 +378,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit stmpe_gpio_remove(struct platform_device *pdev)
++static int stmpe_gpio_remove(struct platform_device *pdev)
+ {
+ 	struct stmpe_gpio *stmpe_gpio = platform_get_drvdata(pdev);
+ 	struct stmpe *stmpe = stmpe_gpio->stmpe;
+diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/gpio-sx150x.c
+index 9c93308abff6..796b6c42fa70 100644
+--- a/drivers/gpio/gpio-sx150x.c
++++ b/drivers/gpio/gpio-sx150x.c
+@@ -622,7 +622,7 @@ static int sx150x_probe(struct i2c_client *client,
+ 	return rc;
+ }
+ 
+-static int __devexit sx150x_remove(struct i2c_client *client)
++static int sx150x_remove(struct i2c_client *client)
+ {
+ 	struct sx150x_chip *chip;
+ 	int rc;
+diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c
+index d69d7c8838c6..839f44923cb9 100644
+--- a/drivers/gpio/gpio-tc3589x.c
++++ b/drivers/gpio/gpio-tc3589x.c
+@@ -389,7 +389,7 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit tc3589x_gpio_remove(struct platform_device *pdev)
++static int tc3589x_gpio_remove(struct platform_device *pdev)
+ {
+ 	struct tc3589x_gpio *tc3589x_gpio = platform_get_drvdata(pdev);
+ 	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c
+index 728d6e773a84..702cca9284f1 100644
+--- a/drivers/gpio/gpio-timberdale.c
++++ b/drivers/gpio/gpio-timberdale.c
+@@ -316,7 +316,7 @@ static int timbgpio_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit timbgpio_remove(struct platform_device *pdev)
++static int timbgpio_remove(struct platform_device *pdev)
+ {
+ 	int err;
+ 	struct timbgpio_platform_data *pdata = pdev->dev.platform_data;
+diff --git a/drivers/gpio/gpio-tps6586x.c b/drivers/gpio/gpio-tps6586x.c
+index b0b2ee076e68..c1b82da56504 100644
+--- a/drivers/gpio/gpio-tps6586x.c
++++ b/drivers/gpio/gpio-tps6586x.c
+@@ -126,7 +126,7 @@ static int tps6586x_gpio_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit tps6586x_gpio_remove(struct platform_device *pdev)
++static int tps6586x_gpio_remove(struct platform_device *pdev)
+ {
+ 	struct tps6586x_gpio *tps6586x_gpio = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c
+index 635352c063c7..5083825a0348 100644
+--- a/drivers/gpio/gpio-tps65910.c
++++ b/drivers/gpio/gpio-tps65910.c
+@@ -188,7 +188,7 @@ static int tps65910_gpio_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit tps65910_gpio_remove(struct platform_device *pdev)
++static int tps65910_gpio_remove(struct platform_device *pdev)
+ {
+ 	struct tps65910_gpio *tps65910_gpio = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/gpio/gpio-tps65912.c b/drivers/gpio/gpio-tps65912.c
+index c0623b8a7495..30a5844a7dca 100644
+--- a/drivers/gpio/gpio-tps65912.c
++++ b/drivers/gpio/gpio-tps65912.c
+@@ -113,7 +113,7 @@ static int tps65912_gpio_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit tps65912_gpio_remove(struct platform_device *pdev)
++static int tps65912_gpio_remove(struct platform_device *pdev)
+ {
+ 	struct tps65912_gpio_data  *tps65912_gpio = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c
+index 648e5608a175..8beae6627656 100644
+--- a/drivers/gpio/gpio-twl4030.c
++++ b/drivers/gpio/gpio-twl4030.c
+@@ -505,7 +505,7 @@ static int gpio_twl4030_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-/* Cannot use __devexit as gpio_twl4030_probe() calls us */
++/* Cannot use as gpio_twl4030_probe() calls us */
+ static int gpio_twl4030_remove(struct platform_device *pdev)
+ {
+ 	struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
+diff --git a/drivers/gpio/gpio-twl6040.c b/drivers/gpio/gpio-twl6040.c
+index 2962b84bd253..0be82c6dd796 100644
+--- a/drivers/gpio/gpio-twl6040.c
++++ b/drivers/gpio/gpio-twl6040.c
+@@ -113,7 +113,7 @@ static int gpo_twl6040_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit gpo_twl6040_remove(struct platform_device *pdev)
++static int gpo_twl6040_remove(struct platform_device *pdev)
+ {
+ 	return gpiochip_remove(&twl6040gpo_chip);
+ }
+diff --git a/drivers/gpio/gpio-vr41xx.c b/drivers/gpio/gpio-vr41xx.c
+index c13920b6cd72..9902732a382d 100644
+--- a/drivers/gpio/gpio-vr41xx.c
++++ b/drivers/gpio/gpio-vr41xx.c
+@@ -552,7 +552,7 @@ static int giu_probe(struct platform_device *pdev)
+ 	return cascade_irq(irq, giu_get_irq);
+ }
+ 
+-static int __devexit giu_remove(struct platform_device *pdev)
++static int giu_remove(struct platform_device *pdev)
+ {
+ 	if (giu_base) {
+ 		iounmap(giu_base);
+diff --git a/drivers/gpio/gpio-vx855.c b/drivers/gpio/gpio-vx855.c
+index 90dd23b0af8a..2b7252cb2427 100644
+--- a/drivers/gpio/gpio-vx855.c
++++ b/drivers/gpio/gpio-vx855.c
+@@ -284,7 +284,7 @@ static int vx855gpio_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit vx855gpio_remove(struct platform_device *pdev)
++static int vx855gpio_remove(struct platform_device *pdev)
+ {
+ 	struct vx855_gpio *vg = platform_get_drvdata(pdev);
+ 	struct resource *res;
+diff --git a/drivers/gpio/gpio-wm831x.c b/drivers/gpio/gpio-wm831x.c
+index 8182145ea29b..2a743e10ecb6 100644
+--- a/drivers/gpio/gpio-wm831x.c
++++ b/drivers/gpio/gpio-wm831x.c
+@@ -275,7 +275,7 @@ static int wm831x_gpio_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit wm831x_gpio_remove(struct platform_device *pdev)
++static int wm831x_gpio_remove(struct platform_device *pdev)
+ {
+ 	struct wm831x_gpio *wm831x_gpio = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/gpio/gpio-wm8350.c b/drivers/gpio/gpio-wm8350.c
+index 2b99fc3fadd0..0b598cf3df9d 100644
+--- a/drivers/gpio/gpio-wm8350.c
++++ b/drivers/gpio/gpio-wm8350.c
+@@ -141,7 +141,7 @@ static int wm8350_gpio_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit wm8350_gpio_remove(struct platform_device *pdev)
++static int wm8350_gpio_remove(struct platform_device *pdev)
+ {
+ 	struct wm8350_gpio_data *wm8350_gpio = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c
+index fc3917889dab..ae409fd94af7 100644
+--- a/drivers/gpio/gpio-wm8994.c
++++ b/drivers/gpio/gpio-wm8994.c
+@@ -281,7 +281,7 @@ static int wm8994_gpio_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit wm8994_gpio_remove(struct platform_device *pdev)
++static int wm8994_gpio_remove(struct platform_device *pdev)
+ {
+ 	struct wm8994_gpio *wm8994_gpio = platform_get_drvdata(pdev);
+ 

commit b5ba78de76b0a39cfcf08dec78e90b737e995965
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:25:05 2012 -0500
+
+    gpio: remove use of __devinitconst
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitconst is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Grant Likely 
+    Acked-by: Linus Walleij 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c
+index 9f23684d1cfc..2a34204bc729 100644
+--- a/drivers/gpio/gpio-adnp.c
++++ b/drivers/gpio/gpio-adnp.c
+@@ -582,13 +582,13 @@ static __devexit int adnp_i2c_remove(struct i2c_client *client)
+ 	return 0;
+ }
+ 
+-static const struct i2c_device_id adnp_i2c_id[] __devinitconst = {
++static const struct i2c_device_id adnp_i2c_id[] = {
+ 	{ "gpio-adnp" },
+ 	{ },
+ };
+ MODULE_DEVICE_TABLE(i2c, adnp_i2c_id);
+ 
+-static const struct of_device_id adnp_of_match[] __devinitconst = {
++static const struct of_device_id adnp_of_match[] = {
+ 	{ .compatible = "ad,gpio-adnp", },
+ 	{ },
+ };

commit aeca8ad1f0613a76a8f5fed174810fab9bc424cf
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:24:14 2012 -0500
+
+    gpio: remove use of __devinitdata
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitdata is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Grant Likely 
+    Acked-by: Linus Walleij 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/gpio/gpio-da9052.c b/drivers/gpio/gpio-da9052.c
+index 5d2bc81d6f84..2139825c4d59 100644
+--- a/drivers/gpio/gpio-da9052.c
++++ b/drivers/gpio/gpio-da9052.c
+@@ -188,7 +188,7 @@ static int da9052_gpio_to_irq(struct gpio_chip *gc, u32 offset)
+ 	return da9052->irq_base + DA9052_IRQ_GPI0 + offset;
+ }
+ 
+-static struct gpio_chip reference_gp __devinitdata = {
++static struct gpio_chip reference_gp = {
+ 	.label = "da9052-gpio",
+ 	.owner = THIS_MODULE,
+ 	.get = da9052_gpio_get,
+diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c
+index 9f676f4629f1..36d7dee07b28 100644
+--- a/drivers/gpio/gpio-lpc32xx.c
++++ b/drivers/gpio/gpio-lpc32xx.c
+@@ -559,7 +559,7 @@ static int lpc32xx_gpio_probe(struct platform_device *pdev)
+ }
+ 
+ #ifdef CONFIG_OF
+-static struct of_device_id lpc32xx_gpio_of_match[] __devinitdata = {
++static struct of_device_id lpc32xx_gpio_of_match[] = {
+ 	{ .compatible = "nxp,lpc3220-gpio", },
+ 	{ },
+ };
+diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
+index 88ad416c2bb0..f2a04ba0ca6c 100644
+--- a/drivers/gpio/gpio-mvebu.c
++++ b/drivers/gpio/gpio-mvebu.c
+@@ -459,7 +459,7 @@ static struct platform_device_id mvebu_gpio_ids[] = {
+ };
+ MODULE_DEVICE_TABLE(platform, mvebu_gpio_ids);
+ 
+-static struct of_device_id mvebu_gpio_of_match[] __devinitdata = {
++static struct of_device_id mvebu_gpio_of_match[] = {
+ 	{
+ 		.compatible = "marvell,orion-gpio",
+ 		.data       = (void*) MVEBU_GPIO_SOC_VARIANT_ORION,
+diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
+index 45105a26d4bb..4cd3e1df05d8 100644
+--- a/drivers/gpio/gpio-tegra.c
++++ b/drivers/gpio/gpio-tegra.c
+@@ -365,7 +365,7 @@ static struct tegra_gpio_soc_config tegra30_gpio_config = {
+ 	.upper_offset = 0x80,
+ };
+ 
+-static struct of_device_id tegra_gpio_of_match[] __devinitdata = {
++static struct of_device_id tegra_gpio_of_match[] = {
+ 	{ .compatible = "nvidia,tegra30-gpio", .data = &tegra30_gpio_config },
+ 	{ .compatible = "nvidia,tegra20-gpio", .data = &tegra20_gpio_config },
+ 	{ },
+diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c
+index 5a35138eeade..9ae7aa8ca48a 100644
+--- a/drivers/gpio/gpio-xilinx.c
++++ b/drivers/gpio/gpio-xilinx.c
+@@ -209,7 +209,7 @@ static int xgpio_of_probe(struct device_node *np)
+ 	return 0;
+ }
+ 
+-static struct of_device_id xgpio_of_match[] __devinitdata = {
++static struct of_device_id xgpio_of_match[] = {
+ 	{ .compatible = "xlnx,xps-gpio-1.00.a", },
+ 	{ /* end of list */ },
+ };

commit 3836309d93462bbf34851c078be6e5e77d888e3d
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:34 2012 -0500
+
+    gpio: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Grant Likely 
+    Cc: Peter Tyser 
+    Cc: Santosh Shilimkar 
+    Cc: Kevin Hilman 
+    Acked-by: Linus Walleij 
+    Acked-by: Mark Brown 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c
+index ee1cb30e7608..2e6df4180dea 100644
+--- a/drivers/gpio/gpio-74x164.c
++++ b/drivers/gpio/gpio-74x164.c
+@@ -105,7 +105,7 @@ static int gen_74x164_direction_output(struct gpio_chip *gc,
+ 	return 0;
+ }
+ 
+-static int __devinit gen_74x164_probe(struct spi_device *spi)
++static int gen_74x164_probe(struct spi_device *spi)
+ {
+ 	struct gen_74x164_chip *chip;
+ 	struct gen_74x164_chip_platform_data *pdata;
+diff --git a/drivers/gpio/gpio-ab8500.c b/drivers/gpio/gpio-ab8500.c
+index 48c3babbf3c6..0a636de39989 100644
+--- a/drivers/gpio/gpio-ab8500.c
++++ b/drivers/gpio/gpio-ab8500.c
+@@ -402,7 +402,7 @@ static void ab8500_gpio_irq_remove(struct ab8500_gpio *ab8500_gpio)
+ 	}
+ }
+ 
+-static int __devinit ab8500_gpio_probe(struct platform_device *pdev)
++static int ab8500_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct ab8500_platform_data *ab8500_pdata =
+ 				dev_get_platdata(pdev->dev.parent);
+diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c
+index 9796b9cbde89..9f23684d1cfc 100644
+--- a/drivers/gpio/gpio-adnp.c
++++ b/drivers/gpio/gpio-adnp.c
+@@ -516,7 +516,7 @@ static void adnp_irq_teardown(struct adnp *adnp)
+ 	irq_domain_remove(adnp->domain);
+ }
+ 
+-static __devinit int adnp_i2c_probe(struct i2c_client *client,
++static int adnp_i2c_probe(struct i2c_client *client,
+ 				    const struct i2c_device_id *id)
+ {
+ 	struct device_node *np = client->dev.of_node;
+diff --git a/drivers/gpio/gpio-adp5520.c b/drivers/gpio/gpio-adp5520.c
+index fc01e6d8c46b..b9fac75b4ddd 100644
+--- a/drivers/gpio/gpio-adp5520.c
++++ b/drivers/gpio/gpio-adp5520.c
+@@ -87,7 +87,7 @@ static int adp5520_gpio_direction_output(struct gpio_chip *chip,
+ 	return ret;
+ }
+ 
+-static int __devinit adp5520_gpio_probe(struct platform_device *pdev)
++static int adp5520_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct adp5520_gpio_platform_data *pdata = pdev->dev.platform_data;
+ 	struct adp5520_gpio *dev;
+diff --git a/drivers/gpio/gpio-adp5588.c b/drivers/gpio/gpio-adp5588.c
+index f762269cb624..27001ec3bcbb 100644
+--- a/drivers/gpio/gpio-adp5588.c
++++ b/drivers/gpio/gpio-adp5588.c
+@@ -346,7 +346,7 @@ static void adp5588_irq_teardown(struct adp5588_gpio *dev)
+ }
+ #endif /* CONFIG_GPIO_ADP5588_IRQ */
+ 
+-static int __devinit adp5588_gpio_probe(struct i2c_client *client,
++static int adp5588_gpio_probe(struct i2c_client *client,
+ 					const struct i2c_device_id *id)
+ {
+ 	struct adp5588_gpio_platform_data *pdata = client->dev.platform_data;
+diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c
+index a406573259ad..0a76fb0f66ce 100644
+--- a/drivers/gpio/gpio-arizona.c
++++ b/drivers/gpio/gpio-arizona.c
+@@ -94,7 +94,7 @@ static struct gpio_chip template_chip = {
+ 	.can_sleep		= 1,
+ };
+ 
+-static int __devinit arizona_gpio_probe(struct platform_device *pdev)
++static int arizona_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
+ 	struct arizona_pdata *pdata = arizona->dev->platform_data;
+diff --git a/drivers/gpio/gpio-cs5535.c b/drivers/gpio/gpio-cs5535.c
+index 00f98f934d36..d4a6d82d7a3e 100644
+--- a/drivers/gpio/gpio-cs5535.c
++++ b/drivers/gpio/gpio-cs5535.c
+@@ -300,7 +300,7 @@ static struct cs5535_gpio_chip cs5535_gpio_chip = {
+ 	},
+ };
+ 
+-static int __devinit cs5535_gpio_probe(struct platform_device *pdev)
++static int cs5535_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res;
+ 	int err = -EIO;
+diff --git a/drivers/gpio/gpio-da9052.c b/drivers/gpio/gpio-da9052.c
+index 9f5824dfd606..5d2bc81d6f84 100644
+--- a/drivers/gpio/gpio-da9052.c
++++ b/drivers/gpio/gpio-da9052.c
+@@ -201,7 +201,7 @@ static struct gpio_chip reference_gp __devinitdata = {
+ 	.base = -1,
+ };
+ 
+-static int __devinit da9052_gpio_probe(struct platform_device *pdev)
++static int da9052_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct da9052_gpio *gpio;
+ 	struct da9052_pdata *pdata;
+diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c
+index e246165864ac..6253a05349ef 100644
+--- a/drivers/gpio/gpio-em.c
++++ b/drivers/gpio/gpio-em.c
+@@ -268,7 +268,7 @@ static void em_gio_irq_domain_cleanup(struct em_gio_priv *p)
+ 	/* FIXME: irq domain wants to be freed! */
+ }
+ 
+-static int __devinit em_gio_probe(struct platform_device *pdev)
++static int em_gio_probe(struct platform_device *pdev)
+ {
+ 	struct gpio_em_config *pdata = pdev->dev.platform_data;
+ 	struct em_gio_priv *p;
+diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c
+index 9fe5b8fe9be8..56b98eebe1fc 100644
+--- a/drivers/gpio/gpio-ep93xx.c
++++ b/drivers/gpio/gpio-ep93xx.c
+@@ -340,7 +340,7 @@ static int ep93xx_gpio_add_bank(struct bgpio_chip *bgc, struct device *dev,
+ 	return gpiochip_add(&bgc->gc);
+ }
+ 
+-static int __devinit ep93xx_gpio_probe(struct platform_device *pdev)
++static int ep93xx_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct ep93xx_gpio *ep93xx_gpio;
+ 	struct resource *res;
+diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c
+index 983f0f2a85f4..be3759648149 100644
+--- a/drivers/gpio/gpio-generic.c
++++ b/drivers/gpio/gpio-generic.c
+@@ -444,7 +444,7 @@ static void __iomem *bgpio_map(struct platform_device *pdev,
+ 	return ret;
+ }
+ 
+-static int __devinit bgpio_pdev_probe(struct platform_device *pdev)
++static int bgpio_pdev_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	struct resource *r;
+diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c
+index c230263302ca..3ff9ff671e31 100644
+--- a/drivers/gpio/gpio-ich.c
++++ b/drivers/gpio/gpio-ich.c
+@@ -238,7 +238,7 @@ static void ichx_gpio_set(struct gpio_chip *chip, unsigned nr, int val)
+ 	ichx_write_bit(GPIO_LVL, nr, val, 0);
+ }
+ 
+-static void __devinit ichx_gpiolib_setup(struct gpio_chip *chip)
++static void ichx_gpiolib_setup(struct gpio_chip *chip)
+ {
+ 	chip->owner = THIS_MODULE;
+ 	chip->label = DRV_NAME;
+@@ -313,7 +313,7 @@ static struct ichx_desc intel5_desc = {
+ 	.ngpio = 76,
+ };
+ 
+-static int __devinit ichx_gpio_request_regions(struct resource *res_base,
++static int ichx_gpio_request_regions(struct resource *res_base,
+ 						const char *name, u8 use_gpio)
+ {
+ 	int i;
+@@ -353,7 +353,7 @@ static void ichx_gpio_release_regions(struct resource *res_base, u8 use_gpio)
+ 	}
+ }
+ 
+-static int __devinit ichx_gpio_probe(struct platform_device *pdev)
++static int ichx_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res_base, *res_pm;
+ 	int err;
+diff --git a/drivers/gpio/gpio-janz-ttl.c b/drivers/gpio/gpio-janz-ttl.c
+index 365dd040445b..cd28270672f2 100644
+--- a/drivers/gpio/gpio-janz-ttl.c
++++ b/drivers/gpio/gpio-janz-ttl.c
+@@ -108,13 +108,13 @@ static void ttl_set_value(struct gpio_chip *gpio, unsigned offset, int value)
+ 	spin_unlock(&mod->lock);
+ }
+ 
+-static void __devinit ttl_write_reg(struct ttl_module *mod, u8 reg, u16 val)
++static void ttl_write_reg(struct ttl_module *mod, u8 reg, u16 val)
+ {
+ 	iowrite16be(reg, &mod->regs->control);
+ 	iowrite16be(val, &mod->regs->control);
+ }
+ 
+-static void __devinit ttl_setup_device(struct ttl_module *mod)
++static void ttl_setup_device(struct ttl_module *mod)
+ {
+ 	/* reset the device to a known state */
+ 	iowrite16be(0x0000, &mod->regs->control);
+@@ -140,7 +140,7 @@ static void __devinit ttl_setup_device(struct ttl_module *mod)
+ 	ttl_write_reg(mod, MASTER_CONF_CTL, CONF_PAE | CONF_PBE | CONF_PCE);
+ }
+ 
+-static int __devinit ttl_probe(struct platform_device *pdev)
++static int ttl_probe(struct platform_device *pdev)
+ {
+ 	struct janz_platform_data *pdata;
+ 	struct device *dev = &pdev->dev;
+diff --git a/drivers/gpio/gpio-langwell.c b/drivers/gpio/gpio-langwell.c
+index b8158967eac3..a3bf90d4e93b 100644
+--- a/drivers/gpio/gpio-langwell.c
++++ b/drivers/gpio/gpio-langwell.c
+@@ -332,7 +332,7 @@ static const struct dev_pm_ops lnw_gpio_pm_ops = {
+ 	.runtime_idle = lnw_gpio_runtime_idle,
+ };
+ 
+-static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
++static int lnw_gpio_probe(struct pci_dev *pdev,
+ 			const struct pci_device_id *id)
+ {
+ 	void *base;
+@@ -435,7 +435,7 @@ static struct pci_driver lnw_gpio_driver = {
+ };
+ 
+ 
+-static int __devinit wp_gpio_probe(struct platform_device *pdev)
++static int wp_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct lnw_gpio *lnw;
+ 	struct gpio_chip *gc;
+diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c
+index 3644e0dcb3dd..9f676f4629f1 100644
+--- a/drivers/gpio/gpio-lpc32xx.c
++++ b/drivers/gpio/gpio-lpc32xx.c
+@@ -542,7 +542,7 @@ static int lpc32xx_of_xlate(struct gpio_chip *gc,
+ 	return gpiospec->args[1];
+ }
+ 
+-static int __devinit lpc32xx_gpio_probe(struct platform_device *pdev)
++static int lpc32xx_gpio_probe(struct platform_device *pdev)
+ {
+ 	int i;
+ 
+diff --git a/drivers/gpio/gpio-max7300.c b/drivers/gpio/gpio-max7300.c
+index 869235f95e86..5c92414e4d60 100644
+--- a/drivers/gpio/gpio-max7300.c
++++ b/drivers/gpio/gpio-max7300.c
+@@ -31,7 +31,7 @@ static int max7300_i2c_read(struct device *dev, unsigned int reg)
+ 	return i2c_smbus_read_byte_data(client, reg);
+ }
+ 
+-static int __devinit max7300_probe(struct i2c_client *client,
++static int max7300_probe(struct i2c_client *client,
+ 			 const struct i2c_device_id *id)
+ {
+ 	struct max7301 *ts;
+diff --git a/drivers/gpio/gpio-max7301.c b/drivers/gpio/gpio-max7301.c
+index 31bf49d73f5f..cf5d5b3a0e0b 100644
+--- a/drivers/gpio/gpio-max7301.c
++++ b/drivers/gpio/gpio-max7301.c
+@@ -50,7 +50,7 @@ static int max7301_spi_read(struct device *dev, unsigned int reg)
+ 	return word & 0xff;
+ }
+ 
+-static int __devinit max7301_probe(struct spi_device *spi)
++static int max7301_probe(struct spi_device *spi)
+ {
+ 	struct max7301 *ts;
+ 	int ret;
+diff --git a/drivers/gpio/gpio-max730x.c b/drivers/gpio/gpio-max730x.c
+index 05e2dac60b3b..91b4f45ef042 100644
+--- a/drivers/gpio/gpio-max730x.c
++++ b/drivers/gpio/gpio-max730x.c
+@@ -160,7 +160,7 @@ static void max7301_set(struct gpio_chip *chip, unsigned offset, int value)
+ 	mutex_unlock(&ts->lock);
+ }
+ 
+-int __devinit __max730x_probe(struct max7301 *ts)
++int __max730x_probe(struct max7301 *ts)
+ {
+ 	struct device *dev = ts->dev;
+ 	struct max7301_platform_data *pdata;
+diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c
+index 67ef5eae87cd..5edd2cb3b4a7 100644
+--- a/drivers/gpio/gpio-max732x.c
++++ b/drivers/gpio/gpio-max732x.c
+@@ -526,7 +526,7 @@ static void max732x_irq_teardown(struct max732x_chip *chip)
+ }
+ #endif
+ 
+-static int __devinit max732x_setup_gpio(struct max732x_chip *chip,
++static int max732x_setup_gpio(struct max732x_chip *chip,
+ 					const struct i2c_device_id *id,
+ 					unsigned gpio_start)
+ {
+@@ -574,7 +574,7 @@ static int __devinit max732x_setup_gpio(struct max732x_chip *chip,
+ 	return port;
+ }
+ 
+-static int __devinit max732x_probe(struct i2c_client *client,
++static int max732x_probe(struct i2c_client *client,
+ 				   const struct i2c_device_id *id)
+ {
+ 	struct max732x_platform_data *pdata;
+diff --git a/drivers/gpio/gpio-mc33880.c b/drivers/gpio/gpio-mc33880.c
+index c6572e1de333..79fc430de247 100644
+--- a/drivers/gpio/gpio-mc33880.c
++++ b/drivers/gpio/gpio-mc33880.c
+@@ -80,7 +80,7 @@ static void mc33880_set(struct gpio_chip *chip, unsigned offset, int value)
+ 	mutex_unlock(&mc->lock);
+ }
+ 
+-static int __devinit mc33880_probe(struct spi_device *spi)
++static int mc33880_probe(struct spi_device *spi)
+ {
+ 	struct mc33880 *mc;
+ 	struct mc33880_platform_data *pdata;
+diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c
+index 47b6002a73f5..45079aeb60bc 100644
+--- a/drivers/gpio/gpio-mcp23s08.c
++++ b/drivers/gpio/gpio-mcp23s08.c
+@@ -475,7 +475,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
+ 
+ #ifdef CONFIG_I2C
+ 
+-static int __devinit mcp230xx_probe(struct i2c_client *client,
++static int mcp230xx_probe(struct i2c_client *client,
+ 				    const struct i2c_device_id *id)
+ {
+ 	struct mcp23s08_platform_data *pdata;
+diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c
+index c824b5d1acd3..934b9bce6282 100644
+--- a/drivers/gpio/gpio-ml-ioh.c
++++ b/drivers/gpio/gpio-ml-ioh.c
+@@ -385,7 +385,7 @@ static irqreturn_t ioh_gpio_handler(int irq, void *dev_id)
+ 	return ret;
+ }
+ 
+-static __devinit void ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip,
++static void ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip,
+ 				unsigned int irq_start, unsigned int num)
+ {
+ 	struct irq_chip_generic *gc;
+@@ -406,7 +406,7 @@ static __devinit void ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip,
+ 			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
+ }
+ 
+-static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
++static int ioh_gpio_probe(struct pci_dev *pdev,
+ 				    const struct pci_device_id *id)
+ {
+ 	int ret;
+diff --git a/drivers/gpio/gpio-mpc5200.c b/drivers/gpio/gpio-mpc5200.c
+index 2c7cef367fc0..42647f26c9e0 100644
+--- a/drivers/gpio/gpio-mpc5200.c
++++ b/drivers/gpio/gpio-mpc5200.c
+@@ -148,7 +148,7 @@ mpc52xx_wkup_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+ 	return 0;
+ }
+ 
+-static int __devinit mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev)
++static int mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev)
+ {
+ 	struct mpc52xx_gpiochip *chip;
+ 	struct mpc52xx_gpio_wkup __iomem *regs;
+@@ -308,7 +308,7 @@ mpc52xx_simple_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+ 	return 0;
+ }
+ 
+-static int __devinit mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev)
++static int mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev)
+ {
+ 	struct mpc52xx_gpiochip *chip;
+ 	struct gpio_chip *gc;
+diff --git a/drivers/gpio/gpio-msic.c b/drivers/gpio/gpio-msic.c
+index b38986285868..27ea7b9257ff 100644
+--- a/drivers/gpio/gpio-msic.c
++++ b/drivers/gpio/gpio-msic.c
+@@ -256,7 +256,7 @@ static void msic_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+ 	chip->irq_eoi(data);
+ }
+ 
+-static int __devinit platform_msic_gpio_probe(struct platform_device *pdev)
++static int platform_msic_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	struct intel_msic_gpio_pdata *pdata = dev->platform_data;
+diff --git a/drivers/gpio/gpio-msm-v2.c b/drivers/gpio/gpio-msm-v2.c
+index 26f5122330c2..5451bec942ef 100644
+--- a/drivers/gpio/gpio-msm-v2.c
++++ b/drivers/gpio/gpio-msm-v2.c
+@@ -352,7 +352,7 @@ static struct irq_chip msm_gpio_irq_chip = {
+ 	.irq_set_wake	= msm_gpio_irq_set_wake,
+ };
+ 
+-static int __devinit msm_gpio_probe(struct platform_device *dev)
++static int msm_gpio_probe(struct platform_device *dev)
+ {
+ 	int i, irq, ret;
+ 
+diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
+index cf7afb9eb61a..88ad416c2bb0 100644
+--- a/drivers/gpio/gpio-mvebu.c
++++ b/drivers/gpio/gpio-mvebu.c
+@@ -478,7 +478,7 @@ static struct of_device_id mvebu_gpio_of_match[] __devinitdata = {
+ };
+ MODULE_DEVICE_TABLE(of, mvebu_gpio_of_match);
+ 
+-static int __devinit mvebu_gpio_probe(struct platform_device *pdev)
++static int mvebu_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct mvebu_gpio_chip *mvchip;
+ 	const struct of_device_id *match;
+diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
+index 80f44bb64a87..7877335c4cc8 100644
+--- a/drivers/gpio/gpio-mxc.c
++++ b/drivers/gpio/gpio-mxc.c
+@@ -356,7 +356,7 @@ static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base)
+ 			       IRQ_NOREQUEST, 0);
+ }
+ 
+-static void __devinit mxc_gpio_get_hw(struct platform_device *pdev)
++static void mxc_gpio_get_hw(struct platform_device *pdev)
+ {
+ 	const struct of_device_id *of_id =
+ 			of_match_device(mxc_gpio_dt_ids, &pdev->dev);
+@@ -395,7 +395,7 @@ static int mxc_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
+ 	return irq_find_mapping(port->domain, offset);
+ }
+ 
+-static int __devinit mxc_gpio_probe(struct platform_device *pdev)
++static int mxc_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct device_node *np = pdev->dev.of_node;
+ 	struct mxc_gpio_port *port;
+diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c
+index 796fb13e4815..fa2a63cad32e 100644
+--- a/drivers/gpio/gpio-mxs.c
++++ b/drivers/gpio/gpio-mxs.c
+@@ -214,7 +214,7 @@ static const struct of_device_id mxs_gpio_dt_ids[] = {
+ };
+ MODULE_DEVICE_TABLE(of, mxs_gpio_dt_ids);
+ 
+-static int __devinit mxs_gpio_probe(struct platform_device *pdev)
++static int mxs_gpio_probe(struct platform_device *pdev)
+ {
+ 	const struct of_device_id *of_id =
+ 			of_match_device(mxs_gpio_dt_ids, &pdev->dev);
+diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
+index d335af1d4d85..148a4f23d118 100644
+--- a/drivers/gpio/gpio-omap.c
++++ b/drivers/gpio/gpio-omap.c
+@@ -1012,7 +1012,7 @@ static void omap_gpio_mod_init(struct gpio_bank *bank)
+ 		dev_err(bank->dev, "Could not get gpio dbck\n");
+ }
+ 
+-static __devinit void
++static void
+ omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,
+ 		    unsigned int num)
+ {
+@@ -1041,7 +1041,7 @@ omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,
+ 			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
+ }
+ 
+-static void __devinit omap_gpio_chip_init(struct gpio_bank *bank)
++static void omap_gpio_chip_init(struct gpio_bank *bank)
+ {
+ 	int j;
+ 	static int gpio;
+@@ -1089,7 +1089,7 @@ static void __devinit omap_gpio_chip_init(struct gpio_bank *bank)
+ 
+ static const struct of_device_id omap_gpio_match[];
+ 
+-static int __devinit omap_gpio_probe(struct platform_device *pdev)
++static int omap_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	struct device_node *node = dev->of_node;
+diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
+index 9c693ae17956..fff7c2be58f9 100644
+--- a/drivers/gpio/gpio-pca953x.c
++++ b/drivers/gpio/gpio-pca953x.c
+@@ -602,7 +602,7 @@ pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, u32 *invert)
+ }
+ #endif
+ 
+-static int __devinit device_pca953x_init(struct pca953x_chip *chip, u32 invert)
++static int device_pca953x_init(struct pca953x_chip *chip, u32 invert)
+ {
+ 	int ret;
+ 
+@@ -621,7 +621,7 @@ static int __devinit device_pca953x_init(struct pca953x_chip *chip, u32 invert)
+ 	return ret;
+ }
+ 
+-static int __devinit device_pca957x_init(struct pca953x_chip *chip, u32 invert)
++static int device_pca957x_init(struct pca953x_chip *chip, u32 invert)
+ {
+ 	int ret;
+ 	u32 val = 0;
+@@ -652,7 +652,7 @@ static int __devinit device_pca957x_init(struct pca953x_chip *chip, u32 invert)
+ 	return ret;
+ }
+ 
+-static int __devinit pca953x_probe(struct i2c_client *client,
++static int pca953x_probe(struct i2c_client *client,
+ 				   const struct i2c_device_id *id)
+ {
+ 	struct pca953x_platform_data *pdata;
+diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c
+index d693560cde4f..09568a4b7799 100644
+--- a/drivers/gpio/gpio-pch.c
++++ b/drivers/gpio/gpio-pch.c
+@@ -325,7 +325,7 @@ static irqreturn_t pch_gpio_handler(int irq, void *dev_id)
+ 	return ret;
+ }
+ 
+-static __devinit void pch_gpio_alloc_generic_chip(struct pch_gpio *chip,
++static void pch_gpio_alloc_generic_chip(struct pch_gpio *chip,
+ 				unsigned int irq_start, unsigned int num)
+ {
+ 	struct irq_chip_generic *gc;
+@@ -345,7 +345,7 @@ static __devinit void pch_gpio_alloc_generic_chip(struct pch_gpio *chip,
+ 			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
+ }
+ 
+-static int __devinit pch_gpio_probe(struct pci_dev *pdev,
++static int pch_gpio_probe(struct pci_dev *pdev,
+ 				    const struct pci_device_id *id)
+ {
+ 	s32 ret;
+diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c
+index 98d52cb3fd1a..3e35243c136f 100644
+--- a/drivers/gpio/gpio-pxa.c
++++ b/drivers/gpio/gpio-pxa.c
+@@ -250,7 +250,7 @@ static int pxa_gpio_of_xlate(struct gpio_chip *gc,
+ }
+ #endif
+ 
+-static int __devinit pxa_init_gpio_chip(int gpio_end,
++static int pxa_init_gpio_chip(int gpio_end,
+ 					int (*set_wake)(unsigned int, unsigned int))
+ {
+ 	int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
+@@ -490,7 +490,7 @@ const struct irq_domain_ops pxa_irq_domain_ops = {
+ 	.xlate	= irq_domain_xlate_twocell,
+ };
+ 
+-static int __devinit pxa_gpio_probe_dt(struct platform_device *pdev)
++static int pxa_gpio_probe_dt(struct platform_device *pdev)
+ {
+ 	int ret, nr_banks, nr_gpios;
+ 	struct device_node *prev, *next, *np = pdev->dev.of_node;
+@@ -537,7 +537,7 @@ static int __devinit pxa_gpio_probe_dt(struct platform_device *pdev)
+ #define pxa_gpio_probe_dt(pdev)		(-1)
+ #endif
+ 
+-static int __devinit pxa_gpio_probe(struct platform_device *pdev)
++static int pxa_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct pxa_gpio_chip *c;
+ 	struct resource *res;
+diff --git a/drivers/gpio/gpio-rc5t583.c b/drivers/gpio/gpio-rc5t583.c
+index 2931514c574a..59ee5de68e50 100644
+--- a/drivers/gpio/gpio-rc5t583.c
++++ b/drivers/gpio/gpio-rc5t583.c
+@@ -111,7 +111,7 @@ static void rc5t583_gpio_free(struct gpio_chip *gc, unsigned offset)
+ 	rc5t583_set_bits(parent, RC5T583_GPIO_PGSEL, BIT(offset));
+ }
+ 
+-static int __devinit rc5t583_gpio_probe(struct platform_device *pdev)
++static int rc5t583_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent);
+ 	struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev);
+diff --git a/drivers/gpio/gpio-rdc321x.c b/drivers/gpio/gpio-rdc321x.c
+index 17b971bffc85..dd3b49f09844 100644
+--- a/drivers/gpio/gpio-rdc321x.c
++++ b/drivers/gpio/gpio-rdc321x.c
+@@ -128,7 +128,7 @@ static int rdc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+ /*
+  * Cache the initial value of both GPIO data registers
+  */
+-static int __devinit rdc321x_gpio_probe(struct platform_device *pdev)
++static int rdc321x_gpio_probe(struct platform_device *pdev)
+ {
+ 	int err;
+ 	struct resource *r;
+diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
+index ed54425bffe8..4498855c7d74 100644
+--- a/drivers/gpio/gpio-sch.c
++++ b/drivers/gpio/gpio-sch.c
+@@ -185,7 +185,7 @@ static struct gpio_chip sch_gpio_resume = {
+ 	.set			= sch_gpio_resume_set,
+ };
+ 
+-static int __devinit sch_gpio_probe(struct platform_device *pdev)
++static int sch_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res;
+ 	int err, id;
+diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c
+index e25f73130b40..88f374ac7753 100644
+--- a/drivers/gpio/gpio-sodaville.c
++++ b/drivers/gpio/gpio-sodaville.c
+@@ -129,7 +129,7 @@ static struct irq_domain_ops irq_domain_sdv_ops = {
+ 	.xlate = sdv_xlate,
+ };
+ 
+-static __devinit int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
++static int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
+ 		struct pci_dev *pdev)
+ {
+ 	struct irq_chip_type *ct;
+@@ -186,7 +186,7 @@ static __devinit int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
+ 	return ret;
+ }
+ 
+-static int __devinit sdv_gpio_probe(struct pci_dev *pdev,
++static int sdv_gpio_probe(struct pci_dev *pdev,
+ 					const struct pci_device_id *pci_id)
+ {
+ 	struct sdv_gpio_chip_data *sd;
+diff --git a/drivers/gpio/gpio-sta2x11.c b/drivers/gpio/gpio-sta2x11.c
+index 6064fb376e11..558542552aae 100644
+--- a/drivers/gpio/gpio-sta2x11.c
++++ b/drivers/gpio/gpio-sta2x11.c
+@@ -320,7 +320,7 @@ static irqreturn_t gsta_gpio_handler(int irq, void *dev_id)
+ 	return ret;
+ }
+ 
+-static __devinit void gsta_alloc_irq_chip(struct gsta_gpio *chip)
++static void gsta_alloc_irq_chip(struct gsta_gpio *chip)
+ {
+ 	struct irq_chip_generic *gc;
+ 	struct irq_chip_type *ct;
+@@ -353,7 +353,7 @@ static __devinit void gsta_alloc_irq_chip(struct gsta_gpio *chip)
+ }
+ 
+ /* The platform device used here is instantiated by the MFD device */
+-static int __devinit gsta_probe(struct platform_device *dev)
++static int gsta_probe(struct platform_device *dev)
+ {
+ 	int i, err;
+ 	struct pci_dev *pdev;
+diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c
+index 821392d22137..72cf6183ee9f 100644
+--- a/drivers/gpio/gpio-stmpe.c
++++ b/drivers/gpio/gpio-stmpe.c
+@@ -267,7 +267,7 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio)
++static int stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio)
+ {
+ 	int base = stmpe_gpio->irq_base;
+ 	int irq;
+@@ -301,7 +301,7 @@ static void stmpe_gpio_irq_remove(struct stmpe_gpio *stmpe_gpio)
+ 	}
+ }
+ 
+-static int __devinit stmpe_gpio_probe(struct platform_device *pdev)
++static int stmpe_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
+ 	struct stmpe_gpio_platform_data *pdata;
+diff --git a/drivers/gpio/gpio-stp-xway.c b/drivers/gpio/gpio-stp-xway.c
+index 8bead0bb6459..85841ee70b17 100644
+--- a/drivers/gpio/gpio-stp-xway.c
++++ b/drivers/gpio/gpio-stp-xway.c
+@@ -197,7 +197,7 @@ static int xway_stp_hw_init(struct xway_stp *chip)
+ 	return 0;
+ }
+ 
+-static int __devinit xway_stp_probe(struct platform_device *pdev)
++static int xway_stp_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ 	const __be32 *shadow, *groups, *dsl, *phy;
+diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/gpio-sx150x.c
+index 0e1472db6a4b..9c93308abff6 100644
+--- a/drivers/gpio/gpio-sx150x.c
++++ b/drivers/gpio/gpio-sx150x.c
+@@ -575,7 +575,7 @@ static void sx150x_remove_irq_chip(struct sx150x_chip *chip)
+ 	}
+ }
+ 
+-static int __devinit sx150x_probe(struct i2c_client *client,
++static int sx150x_probe(struct i2c_client *client,
+ 				const struct i2c_device_id *id)
+ {
+ 	static const u32 i2c_funcs = I2C_FUNC_SMBUS_BYTE_DATA |
+diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c
+index debe67e595d2..d69d7c8838c6 100644
+--- a/drivers/gpio/gpio-tc3589x.c
++++ b/drivers/gpio/gpio-tc3589x.c
+@@ -311,7 +311,7 @@ static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio,
+ 	return 0;
+ }
+ 
+-static int __devinit tc3589x_gpio_probe(struct platform_device *pdev)
++static int tc3589x_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
+ 	struct tc3589x_gpio_platform_data *pdata;
+diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
+index d982593d7563..45105a26d4bb 100644
+--- a/drivers/gpio/gpio-tegra.c
++++ b/drivers/gpio/gpio-tegra.c
+@@ -376,7 +376,7 @@ static struct of_device_id tegra_gpio_of_match[] __devinitdata = {
+  */
+ static struct lock_class_key gpio_lock_class;
+ 
+-static int __devinit tegra_gpio_probe(struct platform_device *pdev)
++static int tegra_gpio_probe(struct platform_device *pdev)
+ {
+ 	const struct of_device_id *match;
+ 	struct tegra_gpio_soc_config *config;
+diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c
+index 1a3e2b9b4772..728d6e773a84 100644
+--- a/drivers/gpio/gpio-timberdale.c
++++ b/drivers/gpio/gpio-timberdale.c
+@@ -222,7 +222,7 @@ static struct irq_chip timbgpio_irqchip = {
+ 	.irq_set_type	= timbgpio_irq_type,
+ };
+ 
+-static int __devinit timbgpio_probe(struct platform_device *pdev)
++static int timbgpio_probe(struct platform_device *pdev)
+ {
+ 	int err, i;
+ 	struct gpio_chip *gc;
+diff --git a/drivers/gpio/gpio-tps6586x.c b/drivers/gpio/gpio-tps6586x.c
+index d048ea81e521..b0b2ee076e68 100644
+--- a/drivers/gpio/gpio-tps6586x.c
++++ b/drivers/gpio/gpio-tps6586x.c
+@@ -80,7 +80,7 @@ static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset,
+ 				val, mask);
+ }
+ 
+-static int __devinit tps6586x_gpio_probe(struct platform_device *pdev)
++static int tps6586x_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct tps6586x_platform_data *pdata;
+ 	struct tps6586x_gpio *tps6586x_gpio;
+diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c
+index cf4e327b128b..635352c063c7 100644
+--- a/drivers/gpio/gpio-tps65910.c
++++ b/drivers/gpio/gpio-tps65910.c
+@@ -113,7 +113,7 @@ static struct tps65910_board *tps65910_parse_dt_for_gpio(struct device *dev,
+ }
+ #endif
+ 
+-static int __devinit tps65910_gpio_probe(struct platform_device *pdev)
++static int tps65910_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
+ 	struct tps65910_board *pdata = dev_get_platdata(tps65910->dev);
+diff --git a/drivers/gpio/gpio-tps65912.c b/drivers/gpio/gpio-tps65912.c
+index 55c1d35f2e14..c0623b8a7495 100644
+--- a/drivers/gpio/gpio-tps65912.c
++++ b/drivers/gpio/gpio-tps65912.c
+@@ -84,7 +84,7 @@ static struct gpio_chip template_chip = {
+ 	.base			= -1,
+ };
+ 
+-static int __devinit tps65912_gpio_probe(struct platform_device *pdev)
++static int tps65912_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent);
+ 	struct tps65912_board *pdata = tps65912->dev->platform_data;
+diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c
+index c5f8ca233e1f..648e5608a175 100644
+--- a/drivers/gpio/gpio-twl4030.c
++++ b/drivers/gpio/gpio-twl4030.c
+@@ -352,7 +352,7 @@ static struct gpio_chip twl_gpiochip = {
+ 
+ /*----------------------------------------------------------------------*/
+ 
+-static int __devinit gpio_twl4030_pulls(u32 ups, u32 downs)
++static int gpio_twl4030_pulls(u32 ups, u32 downs)
+ {
+ 	u8		message[6];
+ 	unsigned	i, gpio_bit;
+@@ -377,7 +377,7 @@ static int __devinit gpio_twl4030_pulls(u32 ups, u32 downs)
+ 				REG_GPIOPUPDCTR1, 5);
+ }
+ 
+-static int __devinit gpio_twl4030_debounce(u32 debounce, u8 mmc_cd)
++static int gpio_twl4030_debounce(u32 debounce, u8 mmc_cd)
+ {
+ 	u8		message[4];
+ 
+@@ -419,7 +419,7 @@ static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev)
+ 	return omap_twl_info;
+ }
+ 
+-static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
++static int gpio_twl4030_probe(struct platform_device *pdev)
+ {
+ 	struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
+ 	struct device_node *node = pdev->dev.of_node;
+diff --git a/drivers/gpio/gpio-twl6040.c b/drivers/gpio/gpio-twl6040.c
+index dd58e8b25043..2962b84bd253 100644
+--- a/drivers/gpio/gpio-twl6040.c
++++ b/drivers/gpio/gpio-twl6040.c
+@@ -82,7 +82,7 @@ static struct gpio_chip twl6040gpo_chip = {
+ 
+ /*----------------------------------------------------------------------*/
+ 
+-static int __devinit gpo_twl6040_probe(struct platform_device *pdev)
++static int gpo_twl6040_probe(struct platform_device *pdev)
+ {
+ 	struct twl6040_gpo_data *pdata = pdev->dev.platform_data;
+ 	struct device *twl6040_core_dev = pdev->dev.parent;
+diff --git a/drivers/gpio/gpio-vr41xx.c b/drivers/gpio/gpio-vr41xx.c
+index 54d6e9a7400f..c13920b6cd72 100644
+--- a/drivers/gpio/gpio-vr41xx.c
++++ b/drivers/gpio/gpio-vr41xx.c
+@@ -490,7 +490,7 @@ static struct gpio_chip vr41xx_gpio_chip = {
+ 	.to_irq			= vr41xx_gpio_to_irq,
+ };
+ 
+-static int __devinit giu_probe(struct platform_device *pdev)
++static int giu_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res;
+ 	unsigned int trigger, i, pin;
+diff --git a/drivers/gpio/gpio-vt8500.c b/drivers/gpio/gpio-vt8500.c
+index bcd8e4aa7c7d..579f26403918 100644
+--- a/drivers/gpio/gpio-vt8500.c
++++ b/drivers/gpio/gpio-vt8500.c
+@@ -269,7 +269,7 @@ static struct of_device_id vt8500_gpio_dt_ids[] = {
+ 	{ /* Sentinel */ },
+ };
+ 
+-static int __devinit vt8500_gpio_probe(struct platform_device *pdev)
++static int vt8500_gpio_probe(struct platform_device *pdev)
+ {
+ 	void __iomem *gpio_base;
+ 	struct device_node *np;
+diff --git a/drivers/gpio/gpio-vx855.c b/drivers/gpio/gpio-vx855.c
+index 43fcc42576dc..90dd23b0af8a 100644
+--- a/drivers/gpio/gpio-vx855.c
++++ b/drivers/gpio/gpio-vx855.c
+@@ -219,7 +219,7 @@ static void vx855gpio_gpio_setup(struct vx855_gpio *vg)
+ }
+ 
+ /* This platform device is ordinarily registered by the vx855 mfd driver */
+-static __devinit int vx855gpio_probe(struct platform_device *pdev)
++static int vx855gpio_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res_gpi;
+ 	struct resource *res_gpo;
+diff --git a/drivers/gpio/gpio-wm831x.c b/drivers/gpio/gpio-wm831x.c
+index 273d541ac6b5..8182145ea29b 100644
+--- a/drivers/gpio/gpio-wm831x.c
++++ b/drivers/gpio/gpio-wm831x.c
+@@ -243,7 +243,7 @@ static struct gpio_chip template_chip = {
+ 	.can_sleep		= 1,
+ };
+ 
+-static int __devinit wm831x_gpio_probe(struct platform_device *pdev)
++static int wm831x_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
+ 	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+diff --git a/drivers/gpio/gpio-wm8350.c b/drivers/gpio/gpio-wm8350.c
+index 348a7d985ee3..2b99fc3fadd0 100644
+--- a/drivers/gpio/gpio-wm8350.c
++++ b/drivers/gpio/gpio-wm8350.c
+@@ -109,7 +109,7 @@ static struct gpio_chip template_chip = {
+ 	.can_sleep		= 1,
+ };
+ 
+-static int __devinit wm8350_gpio_probe(struct platform_device *pdev)
++static int wm8350_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct wm8350 *wm8350 = dev_get_drvdata(pdev->dev.parent);
+ 	struct wm8350_platform_data *pdata = wm8350->dev->platform_data;
+diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c
+index 59f0944ba484..fc3917889dab 100644
+--- a/drivers/gpio/gpio-wm8994.c
++++ b/drivers/gpio/gpio-wm8994.c
+@@ -245,7 +245,7 @@ static struct gpio_chip template_chip = {
+ 	.can_sleep		= 1,
+ };
+ 
+-static int __devinit wm8994_gpio_probe(struct platform_device *pdev)
++static int wm8994_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent);
+ 	struct wm8994_pdata *pdata = wm8994->dev->platform_data;
+diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c
+index 79b0fe8a7253..5a35138eeade 100644
+--- a/drivers/gpio/gpio-xilinx.c
++++ b/drivers/gpio/gpio-xilinx.c
+@@ -159,7 +159,7 @@ static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc)
+  * driver data structure. It returns 0, if the driver is bound to the GPIO
+  * device, or a negative value if there is an error.
+  */
+-static int __devinit xgpio_of_probe(struct device_node *np)
++static int xgpio_of_probe(struct device_node *np)
+ {
+ 	struct xgpio_instance *chip;
+ 	int status = 0;

commit 8283c4ff57bdf3c1d8985c86e4ef44e1bb70f1f6
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:20:08 2012 -0500
+
+    gpio: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Grant Likely 
+    Cc: Peter Tyser 
+    Acked-by: Linus Walleij 
+    Acked-by: Mark Brown 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c
+index f05e54258ffb..ee1cb30e7608 100644
+--- a/drivers/gpio/gpio-74x164.c
++++ b/drivers/gpio/gpio-74x164.c
+@@ -215,7 +215,7 @@ static struct spi_driver gen_74x164_driver = {
+ 		.of_match_table	= of_match_ptr(gen_74x164_dt_ids),
+ 	},
+ 	.probe		= gen_74x164_probe,
+-	.remove		= __devexit_p(gen_74x164_remove),
++	.remove		= gen_74x164_remove,
+ };
+ module_spi_driver(gen_74x164_driver);
+ 
+diff --git a/drivers/gpio/gpio-ab8500.c b/drivers/gpio/gpio-ab8500.c
+index 050c05d91896..48c3babbf3c6 100644
+--- a/drivers/gpio/gpio-ab8500.c
++++ b/drivers/gpio/gpio-ab8500.c
+@@ -499,7 +499,7 @@ static struct platform_driver ab8500_gpio_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = ab8500_gpio_probe,
+-	.remove = __devexit_p(ab8500_gpio_remove),
++	.remove = ab8500_gpio_remove,
+ };
+ 
+ static int __init ab8500_gpio_init(void)
+diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c
+index 3df88336415e..9796b9cbde89 100644
+--- a/drivers/gpio/gpio-adnp.c
++++ b/drivers/gpio/gpio-adnp.c
+@@ -601,7 +601,7 @@ static struct i2c_driver adnp_i2c_driver = {
+ 		.of_match_table = of_match_ptr(adnp_of_match),
+ 	},
+ 	.probe = adnp_i2c_probe,
+-	.remove = __devexit_p(adnp_i2c_remove),
++	.remove = adnp_i2c_remove,
+ 	.id_table = adnp_i2c_id,
+ };
+ module_i2c_driver(adnp_i2c_driver);
+diff --git a/drivers/gpio/gpio-adp5520.c b/drivers/gpio/gpio-adp5520.c
+index 2f263cc32561..fc01e6d8c46b 100644
+--- a/drivers/gpio/gpio-adp5520.c
++++ b/drivers/gpio/gpio-adp5520.c
+@@ -190,7 +190,7 @@ static struct platform_driver adp5520_gpio_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= adp5520_gpio_probe,
+-	.remove		= __devexit_p(adp5520_gpio_remove),
++	.remove		= adp5520_gpio_remove,
+ };
+ 
+ module_platform_driver(adp5520_gpio_driver);
+diff --git a/drivers/gpio/gpio-adp5588.c b/drivers/gpio/gpio-adp5588.c
+index eeedad42913e..f762269cb624 100644
+--- a/drivers/gpio/gpio-adp5588.c
++++ b/drivers/gpio/gpio-adp5588.c
+@@ -479,7 +479,7 @@ static struct i2c_driver adp5588_gpio_driver = {
+ 		   .name = DRV_NAME,
+ 		   },
+ 	.probe = adp5588_gpio_probe,
+-	.remove = __devexit_p(adp5588_gpio_remove),
++	.remove = adp5588_gpio_remove,
+ 	.id_table = adp5588_gpio_id,
+ };
+ 
+diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c
+index 8740d2eb06f8..a406573259ad 100644
+--- a/drivers/gpio/gpio-arizona.c
++++ b/drivers/gpio/gpio-arizona.c
+@@ -152,7 +152,7 @@ static struct platform_driver arizona_gpio_driver = {
+ 	.driver.name	= "arizona-gpio",
+ 	.driver.owner	= THIS_MODULE,
+ 	.probe		= arizona_gpio_probe,
+-	.remove		= __devexit_p(arizona_gpio_remove),
++	.remove		= arizona_gpio_remove,
+ };
+ 
+ module_platform_driver(arizona_gpio_driver);
+diff --git a/drivers/gpio/gpio-cs5535.c b/drivers/gpio/gpio-cs5535.c
+index 19eda1bbe343..00f98f934d36 100644
+--- a/drivers/gpio/gpio-cs5535.c
++++ b/drivers/gpio/gpio-cs5535.c
+@@ -378,7 +378,7 @@ static struct platform_driver cs5535_gpio_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = cs5535_gpio_probe,
+-	.remove = __devexit_p(cs5535_gpio_remove),
++	.remove = cs5535_gpio_remove,
+ };
+ 
+ module_platform_driver(cs5535_gpio_driver);
+diff --git a/drivers/gpio/gpio-da9052.c b/drivers/gpio/gpio-da9052.c
+index 24b8c2974047..9f5824dfd606 100644
+--- a/drivers/gpio/gpio-da9052.c
++++ b/drivers/gpio/gpio-da9052.c
+@@ -238,7 +238,7 @@ static int __devexit da9052_gpio_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver da9052_gpio_driver = {
+ 	.probe = da9052_gpio_probe,
+-	.remove = __devexit_p(da9052_gpio_remove),
++	.remove = da9052_gpio_remove,
+ 	.driver = {
+ 		.name	= "da9052-gpio",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c
+index efb4c2d0d132..e246165864ac 100644
+--- a/drivers/gpio/gpio-em.c
++++ b/drivers/gpio/gpio-em.c
+@@ -399,7 +399,7 @@ static int __devexit em_gio_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver em_gio_device_driver = {
+ 	.probe		= em_gio_probe,
+-	.remove		= __devexit_p(em_gio_remove),
++	.remove		= em_gio_remove,
+ 	.driver		= {
+ 		.name	= "em_gio",
+ 	}
+diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c
+index 82e2e4fe599e..983f0f2a85f4 100644
+--- a/drivers/gpio/gpio-generic.c
++++ b/drivers/gpio/gpio-generic.c
+@@ -527,7 +527,7 @@ static struct platform_driver bgpio_driver = {
+ 	},
+ 	.id_table = bgpio_id_table,
+ 	.probe = bgpio_pdev_probe,
+-	.remove = __devexit_p(bgpio_pdev_remove),
++	.remove = bgpio_pdev_remove,
+ };
+ 
+ module_platform_driver(bgpio_driver);
+diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c
+index d4d617966696..c230263302ca 100644
+--- a/drivers/gpio/gpio-ich.c
++++ b/drivers/gpio/gpio-ich.c
+@@ -467,7 +467,7 @@ static struct platform_driver ichx_gpio_driver = {
+ 		.name	= DRV_NAME,
+ 	},
+ 	.probe		= ichx_gpio_probe,
+-	.remove		= __devexit_p(ichx_gpio_remove),
++	.remove		= ichx_gpio_remove,
+ };
+ 
+ module_platform_driver(ichx_gpio_driver);
+diff --git a/drivers/gpio/gpio-janz-ttl.c b/drivers/gpio/gpio-janz-ttl.c
+index f2f000dd70b3..365dd040445b 100644
+--- a/drivers/gpio/gpio-janz-ttl.c
++++ b/drivers/gpio/gpio-janz-ttl.c
+@@ -234,7 +234,7 @@ static struct platform_driver ttl_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= ttl_probe,
+-	.remove		= __devexit_p(ttl_remove),
++	.remove		= ttl_remove,
+ };
+ 
+ module_platform_driver(ttl_driver);
+diff --git a/drivers/gpio/gpio-langwell.c b/drivers/gpio/gpio-langwell.c
+index 202a99207b7d..b8158967eac3 100644
+--- a/drivers/gpio/gpio-langwell.c
++++ b/drivers/gpio/gpio-langwell.c
+@@ -499,7 +499,7 @@ static int __devexit wp_gpio_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver wp_gpio_driver = {
+ 	.probe		= wp_gpio_probe,
+-	.remove		= __devexit_p(wp_gpio_remove),
++	.remove		= wp_gpio_remove,
+ 	.driver		= {
+ 		.name	= "wp_gpio",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/gpio/gpio-max7300.c b/drivers/gpio/gpio-max7300.c
+index a5ca0ab1b372..869235f95e86 100644
+--- a/drivers/gpio/gpio-max7300.c
++++ b/drivers/gpio/gpio-max7300.c
+@@ -72,7 +72,7 @@ static struct i2c_driver max7300_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = max7300_probe,
+-	.remove = __devexit_p(max7300_remove),
++	.remove = max7300_remove,
+ 	.id_table = max7300_id,
+ };
+ 
+diff --git a/drivers/gpio/gpio-max7301.c b/drivers/gpio/gpio-max7301.c
+index 741acfcbe761..31bf49d73f5f 100644
+--- a/drivers/gpio/gpio-max7301.c
++++ b/drivers/gpio/gpio-max7301.c
+@@ -92,7 +92,7 @@ static struct spi_driver max7301_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = max7301_probe,
+-	.remove = __devexit_p(max7301_remove),
++	.remove = max7301_remove,
+ 	.id_table = max7301_id,
+ };
+ 
+diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c
+index 9504120812a5..67ef5eae87cd 100644
+--- a/drivers/gpio/gpio-max732x.c
++++ b/drivers/gpio/gpio-max732x.c
+@@ -690,7 +690,7 @@ static struct i2c_driver max732x_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= max732x_probe,
+-	.remove		= __devexit_p(max732x_remove),
++	.remove		= max732x_remove,
+ 	.id_table	= max732x_id,
+ };
+ 
+diff --git a/drivers/gpio/gpio-mc33880.c b/drivers/gpio/gpio-mc33880.c
+index 2de57ce5feb6..c6572e1de333 100644
+--- a/drivers/gpio/gpio-mc33880.c
++++ b/drivers/gpio/gpio-mc33880.c
+@@ -175,7 +175,7 @@ static struct spi_driver mc33880_driver = {
+ 		.owner		= THIS_MODULE,
+ 	},
+ 	.probe		= mc33880_probe,
+-	.remove		= __devexit_p(mc33880_remove),
++	.remove		= mc33880_remove,
+ };
+ 
+ static int __init mc33880_init(void)
+diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c
+index 0f425189de11..47b6002a73f5 100644
+--- a/drivers/gpio/gpio-mcp23s08.c
++++ b/drivers/gpio/gpio-mcp23s08.c
+@@ -533,7 +533,7 @@ static struct i2c_driver mcp230xx_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= mcp230xx_probe,
+-	.remove		= __devexit_p(mcp230xx_remove),
++	.remove		= mcp230xx_remove,
+ 	.id_table	= mcp230xx_id,
+ };
+ 
+diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c
+index 6a29ee1847be..c824b5d1acd3 100644
+--- a/drivers/gpio/gpio-ml-ioh.c
++++ b/drivers/gpio/gpio-ml-ioh.c
+@@ -606,7 +606,7 @@ static struct pci_driver ioh_gpio_driver = {
+ 	.name = "ml_ioh_gpio",
+ 	.id_table = ioh_gpio_pcidev_id,
+ 	.probe = ioh_gpio_probe,
+-	.remove = __devexit_p(ioh_gpio_remove),
++	.remove = ioh_gpio_remove,
+ 	.suspend = ioh_gpio_suspend,
+ 	.resume = ioh_gpio_resume
+ };
+diff --git a/drivers/gpio/gpio-msm-v2.c b/drivers/gpio/gpio-msm-v2.c
+index 38305beb4375..26f5122330c2 100644
+--- a/drivers/gpio/gpio-msm-v2.c
++++ b/drivers/gpio/gpio-msm-v2.c
+@@ -390,7 +390,7 @@ static int __devexit msm_gpio_remove(struct platform_device *dev)
+ 
+ static struct platform_driver msm_gpio_driver = {
+ 	.probe = msm_gpio_probe,
+-	.remove = __devexit_p(msm_gpio_remove),
++	.remove = msm_gpio_remove,
+ 	.driver = {
+ 		.name = "msmgpio",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c
+index 4ad0c4f9171c..d693560cde4f 100644
+--- a/drivers/gpio/gpio-pch.c
++++ b/drivers/gpio/gpio-pch.c
+@@ -531,7 +531,7 @@ static struct pci_driver pch_gpio_driver = {
+ 	.name = "pch_gpio",
+ 	.id_table = pch_gpio_pcidev_id,
+ 	.probe = pch_gpio_probe,
+-	.remove = __devexit_p(pch_gpio_remove),
++	.remove = pch_gpio_remove,
+ 	.suspend = pch_gpio_suspend,
+ 	.resume = pch_gpio_resume
+ };
+diff --git a/drivers/gpio/gpio-rc5t583.c b/drivers/gpio/gpio-rc5t583.c
+index 08428bf17718..2931514c574a 100644
+--- a/drivers/gpio/gpio-rc5t583.c
++++ b/drivers/gpio/gpio-rc5t583.c
+@@ -159,7 +159,7 @@ static struct platform_driver rc5t583_gpio_driver = {
+ 		.owner   = THIS_MODULE,
+ 	},
+ 	.probe		= rc5t583_gpio_probe,
+-	.remove		= __devexit_p(rc5t583_gpio_remove),
++	.remove		= rc5t583_gpio_remove,
+ };
+ 
+ static int __init rc5t583_gpio_init(void)
+diff --git a/drivers/gpio/gpio-rdc321x.c b/drivers/gpio/gpio-rdc321x.c
+index b62d443e9a59..17b971bffc85 100644
+--- a/drivers/gpio/gpio-rdc321x.c
++++ b/drivers/gpio/gpio-rdc321x.c
+@@ -225,7 +225,7 @@ static struct platform_driver rdc321x_gpio_driver = {
+ 	.driver.name	= "rdc321x-gpio",
+ 	.driver.owner	= THIS_MODULE,
+ 	.probe		= rdc321x_gpio_probe,
+-	.remove		= __devexit_p(rdc321x_gpio_remove),
++	.remove		= rdc321x_gpio_remove,
+ };
+ 
+ module_platform_driver(rdc321x_gpio_driver);
+diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
+index 8707d4572a06..ed54425bffe8 100644
+--- a/drivers/gpio/gpio-sch.c
++++ b/drivers/gpio/gpio-sch.c
+@@ -303,7 +303,7 @@ static struct platform_driver sch_gpio_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe		= sch_gpio_probe,
+-	.remove		= __devexit_p(sch_gpio_remove),
++	.remove		= sch_gpio_remove,
+ };
+ 
+ module_platform_driver(sch_gpio_driver);
+diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c
+index dce34727bbf8..821392d22137 100644
+--- a/drivers/gpio/gpio-stmpe.c
++++ b/drivers/gpio/gpio-stmpe.c
+@@ -412,7 +412,7 @@ static struct platform_driver stmpe_gpio_driver = {
+ 	.driver.name	= "stmpe-gpio",
+ 	.driver.owner	= THIS_MODULE,
+ 	.probe		= stmpe_gpio_probe,
+-	.remove		= __devexit_p(stmpe_gpio_remove),
++	.remove		= stmpe_gpio_remove,
+ };
+ 
+ static int __init stmpe_gpio_init(void)
+diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/gpio-sx150x.c
+index eb3e215d2396..0e1472db6a4b 100644
+--- a/drivers/gpio/gpio-sx150x.c
++++ b/drivers/gpio/gpio-sx150x.c
+@@ -646,7 +646,7 @@ static struct i2c_driver sx150x_driver = {
+ 		.owner = THIS_MODULE
+ 	},
+ 	.probe    = sx150x_probe,
+-	.remove   = __devexit_p(sx150x_remove),
++	.remove   = sx150x_remove,
+ 	.id_table = sx150x_id,
+ };
+ 
+diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c
+index 1e48317e70fb..debe67e595d2 100644
+--- a/drivers/gpio/gpio-tc3589x.c
++++ b/drivers/gpio/gpio-tc3589x.c
+@@ -419,7 +419,7 @@ static struct platform_driver tc3589x_gpio_driver = {
+ 	.driver.name	= "tc3589x-gpio",
+ 	.driver.owner	= THIS_MODULE,
+ 	.probe		= tc3589x_gpio_probe,
+-	.remove		= __devexit_p(tc3589x_gpio_remove),
++	.remove		= tc3589x_gpio_remove,
+ };
+ 
+ static int __init tc3589x_gpio_init(void)
+diff --git a/drivers/gpio/gpio-tps6586x.c b/drivers/gpio/gpio-tps6586x.c
+index 2526b3bb0fae..d048ea81e521 100644
+--- a/drivers/gpio/gpio-tps6586x.c
++++ b/drivers/gpio/gpio-tps6586x.c
+@@ -137,7 +137,7 @@ static struct platform_driver tps6586x_gpio_driver = {
+ 	.driver.name	= "tps6586x-gpio",
+ 	.driver.owner	= THIS_MODULE,
+ 	.probe		= tps6586x_gpio_probe,
+-	.remove		= __devexit_p(tps6586x_gpio_remove),
++	.remove		= tps6586x_gpio_remove,
+ };
+ 
+ static int __init tps6586x_gpio_init(void)
+diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c
+index 11f29c82253c..cf4e327b128b 100644
+--- a/drivers/gpio/gpio-tps65910.c
++++ b/drivers/gpio/gpio-tps65910.c
+@@ -199,7 +199,7 @@ static struct platform_driver tps65910_gpio_driver = {
+ 	.driver.name    = "tps65910-gpio",
+ 	.driver.owner   = THIS_MODULE,
+ 	.probe		= tps65910_gpio_probe,
+-	.remove		= __devexit_p(tps65910_gpio_remove),
++	.remove		= tps65910_gpio_remove,
+ };
+ 
+ static int __init tps65910_gpio_init(void)
+diff --git a/drivers/gpio/gpio-tps65912.c b/drivers/gpio/gpio-tps65912.c
+index 99106d1e2e55..55c1d35f2e14 100644
+--- a/drivers/gpio/gpio-tps65912.c
++++ b/drivers/gpio/gpio-tps65912.c
+@@ -126,7 +126,7 @@ static struct platform_driver tps65912_gpio_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = tps65912_gpio_probe,
+-	.remove = __devexit_p(tps65912_gpio_remove),
++	.remove = tps65912_gpio_remove,
+ };
+ 
+ static int __init tps65912_gpio_init(void)
+diff --git a/drivers/gpio/gpio-vr41xx.c b/drivers/gpio/gpio-vr41xx.c
+index 82d5c20ad3cb..54d6e9a7400f 100644
+--- a/drivers/gpio/gpio-vr41xx.c
++++ b/drivers/gpio/gpio-vr41xx.c
+@@ -564,7 +564,7 @@ static int __devexit giu_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver giu_device_driver = {
+ 	.probe		= giu_probe,
+-	.remove		= __devexit_p(giu_remove),
++	.remove		= giu_remove,
+ 	.driver		= {
+ 		.name	= "GIU",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/gpio/gpio-vx855.c b/drivers/gpio/gpio-vx855.c
+index 76ebfe5ff702..43fcc42576dc 100644
+--- a/drivers/gpio/gpio-vx855.c
++++ b/drivers/gpio/gpio-vx855.c
+@@ -312,7 +312,7 @@ static struct platform_driver vx855gpio_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= vx855gpio_probe,
+-	.remove		= __devexit_p(vx855gpio_remove),
++	.remove		= vx855gpio_remove,
+ };
+ 
+ module_platform_driver(vx855gpio_driver);
+diff --git a/drivers/gpio/gpio-wm831x.c b/drivers/gpio/gpio-wm831x.c
+index b6eda35089d5..273d541ac6b5 100644
+--- a/drivers/gpio/gpio-wm831x.c
++++ b/drivers/gpio/gpio-wm831x.c
+@@ -286,7 +286,7 @@ static struct platform_driver wm831x_gpio_driver = {
+ 	.driver.name	= "wm831x-gpio",
+ 	.driver.owner	= THIS_MODULE,
+ 	.probe		= wm831x_gpio_probe,
+-	.remove		= __devexit_p(wm831x_gpio_remove),
++	.remove		= wm831x_gpio_remove,
+ };
+ 
+ static int __init wm831x_gpio_init(void)
+diff --git a/drivers/gpio/gpio-wm8350.c b/drivers/gpio/gpio-wm8350.c
+index fb4293889392..348a7d985ee3 100644
+--- a/drivers/gpio/gpio-wm8350.c
++++ b/drivers/gpio/gpio-wm8350.c
+@@ -152,7 +152,7 @@ static struct platform_driver wm8350_gpio_driver = {
+ 	.driver.name	= "wm8350-gpio",
+ 	.driver.owner	= THIS_MODULE,
+ 	.probe		= wm8350_gpio_probe,
+-	.remove		= __devexit_p(wm8350_gpio_remove),
++	.remove		= wm8350_gpio_remove,
+ };
+ 
+ static int __init wm8350_gpio_init(void)
+diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c
+index 1c764e779d80..59f0944ba484 100644
+--- a/drivers/gpio/gpio-wm8994.c
++++ b/drivers/gpio/gpio-wm8994.c
+@@ -292,7 +292,7 @@ static struct platform_driver wm8994_gpio_driver = {
+ 	.driver.name	= "wm8994-gpio",
+ 	.driver.owner	= THIS_MODULE,
+ 	.probe		= wm8994_gpio_probe,
+-	.remove		= __devexit_p(wm8994_gpio_remove),
++	.remove		= wm8994_gpio_remove,
+ };
+ 
+ static int __init wm8994_gpio_init(void)

commit 1fc7ad5d393df9e69c0cfcb01b2d803dd2021277
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:25:43 2012 -0500
+
+    clk: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Mike Turquette 
+    Acked-by: Mark Brown 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/clk/clk-max77686.c b/drivers/clk/clk-max77686.c
+index fe449c25efd1..d098f72e1d5f 100644
+--- a/drivers/clk/clk-max77686.c
++++ b/drivers/clk/clk-max77686.c
+@@ -199,7 +199,7 @@ static int max77686_clk_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit max77686_clk_remove(struct platform_device *pdev)
++static int max77686_clk_remove(struct platform_device *pdev)
+ {
+ 	struct max77686_clk **max77686_clks = platform_get_drvdata(pdev);
+ 	int i;
+diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c
+index d0f1442fdae2..1b4e2281323d 100644
+--- a/drivers/clk/clk-wm831x.c
++++ b/drivers/clk/clk-wm831x.c
+@@ -399,7 +399,7 @@ static int wm831x_clk_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit wm831x_clk_remove(struct platform_device *pdev)
++static int wm831x_clk_remove(struct platform_device *pdev)
+ {
+ 	struct wm831x_clk *clkdata = dev_get_drvdata(&pdev->dev);
+ 

commit 018ae93fbc6cb2c843bb899bce05328c393b373d
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:52 2012 -0500
+
+    clk: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Mike Turquette 
+    Acked-by: Mark Brown 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/clk/clk-max77686.c b/drivers/clk/clk-max77686.c
+index fff7e6f36ef1..fe449c25efd1 100644
+--- a/drivers/clk/clk-max77686.c
++++ b/drivers/clk/clk-max77686.c
+@@ -143,7 +143,7 @@ static int max77686_clk_register(struct device *dev,
+ 	return 0;
+ }
+ 
+-static __devinit int max77686_clk_probe(struct platform_device *pdev)
++static int max77686_clk_probe(struct platform_device *pdev)
+ {
+ 	struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+ 	struct max77686_clk **max77686_clks;
+diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c
+index 3cbd662adcf2..d0f1442fdae2 100644
+--- a/drivers/clk/clk-wm831x.c
++++ b/drivers/clk/clk-wm831x.c
+@@ -350,7 +350,7 @@ static struct clk_init_data wm831x_clkout_init = {
+ 	.flags = CLK_SET_RATE_PARENT,
+ };
+ 
+-static __devinit int wm831x_clk_probe(struct platform_device *pdev)
++static int wm831x_clk_probe(struct platform_device *pdev)
+ {
+ 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
+ 	struct wm831x_clk *clkdata;

commit f9cfa6305198f190a685e45a3d78140ea8f298a9
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:19:59 2012 -0500
+
+    clk: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Mike Turquette 
+    Acked-by: Mark Brown 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/clk/clk-max77686.c b/drivers/clk/clk-max77686.c
+index ac5f5434cb9a..fff7e6f36ef1 100644
+--- a/drivers/clk/clk-max77686.c
++++ b/drivers/clk/clk-max77686.c
+@@ -223,7 +223,7 @@ static struct platform_driver max77686_clk_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = max77686_clk_probe,
+-	.remove = __devexit_p(max77686_clk_remove),
++	.remove = max77686_clk_remove,
+ 	.id_table = max77686_clk_id,
+ };
+ 
+diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c
+index e7b7765e85f3..3cbd662adcf2 100644
+--- a/drivers/clk/clk-wm831x.c
++++ b/drivers/clk/clk-wm831x.c
+@@ -412,7 +412,7 @@ static int __devexit wm831x_clk_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver wm831x_clk_driver = {
+ 	.probe = wm831x_clk_probe,
+-	.remove = __devexit_p(wm831x_clk_remove),
++	.remove = wm831x_clk_remove,
+ 	.driver		= {
+ 		.name	= "wm831x-clk",
+ 		.owner	= THIS_MODULE,

commit 164dce822157311eeb81470492889bcd83d84ff1
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:19:57 2012 -0500
+
+    tpm_infineon: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Rajiv Andrade 
+    Cc: Marcel Selhorst 
+    Cc: Sirrix AG 
+    Acked-by: Kent Yoder 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c
+index 8d9ff73faac3..0126e8098672 100644
+--- a/drivers/char/tpm/tpm_infineon.c
++++ b/drivers/char/tpm/tpm_infineon.c
+@@ -655,7 +655,7 @@ static struct pnp_driver tpm_inf_pnp_driver = {
+ 	.probe = tpm_inf_pnp_probe,
+ 	.suspend = tpm_inf_pnp_suspend,
+ 	.resume = tpm_inf_pnp_resume,
+-	.remove = __devexit_p(tpm_inf_pnp_remove)
++	.remove = tpm_inf_pnp_remove
+ };
+ 
+ static int __init init_inf(void)

commit afc6d36912f3f3404fcc1dd2234d9028706a9b6a
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:42 2012 -0500
+
+    tpm: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Rajiv Andrade 
+    Cc: Marcel Selhorst 
+    Cc: Sirrix AG 
+    Acked-by: Kent Yoder 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c
+index 5a831aec9d4b..bcdb078c1b84 100644
+--- a/drivers/char/tpm/tpm_i2c_infineon.c
++++ b/drivers/char/tpm/tpm_i2c_infineon.c
+@@ -555,7 +555,7 @@ static struct tpm_vendor_specific tpm_tis_i2c = {
+ 	.miscdev.fops = &tis_ops,
+ };
+ 
+-static int __devinit tpm_tis_i2c_init(struct device *dev)
++static int tpm_tis_i2c_init(struct device *dev)
+ {
+ 	u32 vendor;
+ 	int rc = 0;
+@@ -632,7 +632,7 @@ static const struct i2c_device_id tpm_tis_i2c_table[] = {
+ MODULE_DEVICE_TABLE(i2c, tpm_tis_i2c_table);
+ static SIMPLE_DEV_PM_OPS(tpm_tis_i2c_ops, tpm_pm_suspend, tpm_pm_resume);
+ 
+-static int __devinit tpm_tis_i2c_probe(struct i2c_client *client,
++static int tpm_tis_i2c_probe(struct i2c_client *client,
+ 			     const struct i2c_device_id *id)
+ {
+ 	int rc;
+diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c
+index efc4ab36a9d6..d9ba6157da96 100644
+--- a/drivers/char/tpm/tpm_ibmvtpm.c
++++ b/drivers/char/tpm/tpm_ibmvtpm.c
+@@ -602,7 +602,7 @@ static void ibmvtpm_tasklet(void *data)
+  *	0 - Success
+  *	Non-zero - Failure
+  */
+-static int __devinit tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
++static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
+ 				   const struct vio_device_id *id)
+ {
+ 	struct ibmvtpm_dev *ibmvtpm;
+diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c
+index 3251a44e8ceb..8d9ff73faac3 100644
+--- a/drivers/char/tpm/tpm_infineon.c
++++ b/drivers/char/tpm/tpm_infineon.c
+@@ -415,7 +415,7 @@ static const struct pnp_device_id tpm_inf_pnp_tbl[] = {
+ 
+ MODULE_DEVICE_TABLE(pnp, tpm_inf_pnp_tbl);
+ 
+-static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
++static int tpm_inf_pnp_probe(struct pnp_dev *dev,
+ 				       const struct pnp_device_id *dev_id)
+ {
+ 	int rc = 0;
+diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
+index 6bdf2671254f..253161c302b9 100644
+--- a/drivers/char/tpm/tpm_tis.c
++++ b/drivers/char/tpm/tpm_tis.c
+@@ -729,7 +729,7 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
+ #endif
+ 
+ #ifdef CONFIG_PNP
+-static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
++static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
+ 				      const struct pnp_device_id *pnp_id)
+ {
+ 	resource_size_t start, len;

commit 610141ee651cee2cd27584434aa9dd9d967f0089
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:19 2012 -0500
+
+    lib: kobject_uevent is no longer dependant on CONFIG_HOTPLUG
+    
+    CONFIG_HOTPLUG is being removed so kobject_uevent needs to always be
+    part of the library.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/lib/Makefile b/lib/Makefile
+index 821a16229111..66787b9f6616 100644
+--- a/lib/Makefile
++++ b/lib/Makefile
+@@ -12,7 +12,7 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \
+ 	 idr.o int_sqrt.o extable.o \
+ 	 sha1.o md5.o irq_regs.o reciprocal_div.o argv_split.o \
+ 	 proportions.o flex_proportions.o prio_heap.o ratelimit.o show_mem.o \
+-	 is_single_threaded.o plist.o decompress.o
++	 is_single_threaded.o plist.o decompress.o kobject_uevent.o
+ 
+ lib-$(CONFIG_MMU) += ioremap.o
+ lib-$(CONFIG_SMP) += cpumask.o
+@@ -31,7 +31,6 @@ CFLAGS_kobject.o += -DDEBUG
+ CFLAGS_kobject_uevent.o += -DDEBUG
+ endif
+ 
+-lib-$(CONFIG_HOTPLUG) += kobject_uevent.o
+ obj-$(CONFIG_GENERIC_IOMAP) += iomap.o
+ obj-$(CONFIG_GENERIC_PCI_IOMAP) += pci_iomap.o
+ obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o

commit e3a1a5ec5cd516c85848611992102fc00e8af601
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:19:30 2012 -0500
+
+    kernel/ksysfs.c: remove CONFIG_HOTPLUG ifdefs
+    
+    Remove conditional code based on CONFIG_HOTPLUG being false.  It's
+    always on now in preparation of it going away as an option.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c
+index 4e316e1acf58..c01eac66c0cc 100644
+--- a/kernel/ksysfs.c
++++ b/kernel/ksysfs.c
+@@ -26,7 +26,6 @@ static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
+ static struct kobj_attribute _name##_attr = \
+ 	__ATTR(_name, 0644, _name##_show, _name##_store)
+ 
+-#if defined(CONFIG_HOTPLUG)
+ /* current uevent sequence number */
+ static ssize_t uevent_seqnum_show(struct kobject *kobj,
+ 				  struct kobj_attribute *attr, char *buf)
+@@ -54,7 +53,7 @@ static ssize_t uevent_helper_store(struct kobject *kobj,
+ 	return count;
+ }
+ KERNEL_ATTR_RW(uevent_helper);
+-#endif
++
+ 
+ #ifdef CONFIG_PROFILING
+ static ssize_t profiling_show(struct kobject *kobj,
+@@ -169,10 +168,8 @@ EXPORT_SYMBOL_GPL(kernel_kobj);
+ 
+ static struct attribute * kernel_attrs[] = {
+ 	&fscaps_attr.attr,
+-#if defined(CONFIG_HOTPLUG)
+ 	&uevent_seqnum_attr.attr,
+ 	&uevent_helper_attr.attr,
+-#endif
+ #ifdef CONFIG_PROFILING
+ 	&profiling_attr.attr,
+ #endif

commit 3b572b506c76a7a38c8debe45b50d09295620810
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:19:29 2012 -0500
+
+    sysctl: remove CONFIG_HOTPLUG ifdefs
+    
+    Remove conditional code based on CONFIG_HOTPLUG being false.  It's
+    always on now in preparation of it going away as an option.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/kernel/sysctl.c b/kernel/sysctl.c
+index 26f65eaa01f9..33f71f37267e 100644
+--- a/kernel/sysctl.c
++++ b/kernel/sysctl.c
+@@ -565,7 +565,7 @@ static struct ctl_table kern_table[] = {
+ 		.extra2		= &one,
+ 	},
+ #endif
+-#ifdef CONFIG_HOTPLUG
++
+ 	{
+ 		.procname	= "hotplug",
+ 		.data		= &uevent_helper,
+@@ -573,7 +573,7 @@ static struct ctl_table kern_table[] = {
+ 		.mode		= 0644,
+ 		.proc_handler	= proc_dostring,
+ 	},
+-#endif
++
+ #ifdef CONFIG_CHR_DEV_SG
+ 	{
+ 		.procname	= "sg-big-buff",

commit 1c9a9f59149e247e264db1fbf9f8ea3d5066eb64
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:19:21 2012 -0500
+
+    kobject: remove CONFIG_HOTPLUG ifdefs
+    
+    Remove conditional code based on CONFIG_HOTPLUG being false.  It's
+    always on now in preparation of it going away as an option.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/include/linux/kobject.h b/include/linux/kobject.h
+index 1e57449395b1..939b11268c86 100644
+--- a/include/linux/kobject.h
++++ b/include/linux/kobject.h
+@@ -203,7 +203,6 @@ extern struct kobject *power_kobj;
+ /* The global /sys/firmware/ kobject for people to chain off of */
+ extern struct kobject *firmware_kobj;
+ 
+-#if defined(CONFIG_HOTPLUG)
+ int kobject_uevent(struct kobject *kobj, enum kobject_action action);
+ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
+ 			char *envp[]);
+@@ -213,22 +212,5 @@ int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...);
+ 
+ int kobject_action_type(const char *buf, size_t count,
+ 			enum kobject_action *type);
+-#else
+-static inline int kobject_uevent(struct kobject *kobj,
+-				 enum kobject_action action)
+-{ return 0; }
+-static inline int kobject_uevent_env(struct kobject *kobj,
+-				      enum kobject_action action,
+-				      char *envp[])
+-{ return 0; }
+-
+-static inline __printf(2, 3)
+-int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
+-{ return -ENOMEM; }
+-
+-static inline int kobject_action_type(const char *buf, size_t count,
+-				      enum kobject_action *type)
+-{ return -EINVAL; }
+-#endif
+ 
+ #endif /* _KOBJECT_H_ */

commit a42d1e31d4a2380cf1bda8e3510ff1859ddf55a5
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:19:18 2012 -0500
+
+    driver core: remove CONFIG_HOTPLUG ifdefs
+    
+    Remove conditional code based on CONFIG_HOTPLUG being false.  It's
+    always on now in preparation of it going away as an option.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/base/bus.c b/drivers/base/bus.c
+index 181ed2660b33..24eb07868344 100644
+--- a/drivers/base/bus.c
++++ b/drivers/base/bus.c
+@@ -164,8 +164,6 @@ static const struct kset_uevent_ops bus_uevent_ops = {
+ 
+ static struct kset *bus_kset;
+ 
+-
+-#ifdef CONFIG_HOTPLUG
+ /* Manually detach a device from its associated driver. */
+ static ssize_t driver_unbind(struct device_driver *drv,
+ 			     const char *buf, size_t count)
+@@ -252,7 +250,6 @@ static ssize_t store_drivers_probe(struct bus_type *bus,
+ 		return -EINVAL;
+ 	return count;
+ }
+-#endif
+ 
+ static struct device *next_device(struct klist_iter *i)
+ {
+@@ -618,11 +615,6 @@ static void driver_remove_attrs(struct bus_type *bus,
+ 	}
+ }
+ 
+-#ifdef CONFIG_HOTPLUG
+-/*
+- * Thanks to drivers making their tables __devinit, we can't allow manual
+- * bind and unbind from userspace unless CONFIG_HOTPLUG is enabled.
+- */
+ static int __must_check add_bind_files(struct device_driver *drv)
+ {
+ 	int ret;
+@@ -666,12 +658,6 @@ static void remove_probe_files(struct bus_type *bus)
+ 	bus_remove_file(bus, &bus_attr_drivers_autoprobe);
+ 	bus_remove_file(bus, &bus_attr_drivers_probe);
+ }
+-#else
+-static inline int add_bind_files(struct device_driver *drv) { return 0; }
+-static inline void remove_bind_files(struct device_driver *drv) {}
+-static inline int add_probe_files(struct bus_type *bus) { return 0; }
+-static inline void remove_probe_files(struct bus_type *bus) {}
+-#endif
+ 
+ static ssize_t driver_uevent_store(struct device_driver *drv,
+ 				   const char *buf, size_t count)

commit 38de2790c7bd212fa96f50c896fdc2f4def76087
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:19:14 2012 -0500
+
+    pnpbios: remove CONFIG_HOTPLUG ifdefs
+    
+    Remove conditional code based on CONFIG_HOTPLUG being false.  It's
+    always on now in preparation of it going away as an option.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Adam Belay 
+    Reviewed-by: Bjorn Helgaas 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
+index 9d4222648640..5d66e5585f97 100644
+--- a/drivers/pnp/pnpbios/core.c
++++ b/drivers/pnp/pnpbios/core.c
+@@ -91,8 +91,6 @@ struct pnp_dev_node_info node_info;
+  *
+  */
+ 
+-#ifdef CONFIG_HOTPLUG
+-
+ static struct completion unload_sem;
+ 
+ /*
+@@ -199,8 +197,6 @@ static int pnp_dock_thread(void *unused)
+ 	complete_and_exit(&unload_sem, 0);
+ }
+ 
+-#endif				/* CONFIG_HOTPLUG */
+-
+ static int pnpbios_get_resources(struct pnp_dev *dev)
+ {
+ 	u8 nodenum = dev->number;
+@@ -573,21 +569,19 @@ fs_initcall(pnpbios_init);
+ 
+ static int __init pnpbios_thread_init(void)
+ {
++	struct task_struct *task;
+ #if defined(CONFIG_PPC)
+ 	if (check_legacy_ioport(PNPBIOS_BASE))
+ 		return 0;
+ #endif
+ 	if (pnpbios_disabled)
+ 		return 0;
+-#ifdef CONFIG_HOTPLUG
+-	{
+-		struct task_struct *task;
+-		init_completion(&unload_sem);
+-		task = kthread_run(pnp_dock_thread, NULL, "kpnpbiosd");
+-		if (IS_ERR(task))
+-			return PTR_ERR(task);
+-	}
+-#endif
++
++	init_completion(&unload_sem);
++	task = kthread_run(pnp_dock_thread, NULL, "kpnpbiosd");
++	if (IS_ERR(task))
++		return PTR_ERR(task);
++
+ 	return 0;
+ }
+ 

commit 5f7e22283cec597e532b75d5a455ce6ed75de362
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:20:06 2012 -0500
+
+    extcon: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: MyungJoo Ham 
+    Cc: Chanwoo Choi 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c
+index 84144e6708c7..eda2a1aa4adb 100644
+--- a/drivers/extcon/extcon-adc-jack.c
++++ b/drivers/extcon/extcon-adc-jack.c
+@@ -188,7 +188,7 @@ static int adc_jack_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver adc_jack_driver = {
+ 	.probe          = adc_jack_probe,
+-	.remove         = __devexit_p(adc_jack_remove),
++	.remove         = adc_jack_remove,
+ 	.driver         = {
+ 		.name   = "adc-jack",
+ 		.owner  = THIS_MODULE,
+diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
+index 2473be9ac5de..f10f05d4ee9c 100644
+--- a/drivers/extcon/extcon-arizona.c
++++ b/drivers/extcon/extcon-arizona.c
+@@ -544,7 +544,7 @@ static struct platform_driver arizona_extcon_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= arizona_extcon_probe,
+-	.remove		= __devexit_p(arizona_extcon_remove),
++	.remove		= arizona_extcon_remove,
+ };
+ 
+ module_platform_driver(arizona_extcon_driver);
+diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c
+index e02219e5a3d8..1b14bfcdc176 100644
+--- a/drivers/extcon/extcon-gpio.c
++++ b/drivers/extcon/extcon-gpio.c
+@@ -150,7 +150,7 @@ static int gpio_extcon_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver gpio_extcon_driver = {
+ 	.probe		= gpio_extcon_probe,
+-	.remove		= __devexit_p(gpio_extcon_remove),
++	.remove		= gpio_extcon_remove,
+ 	.driver		= {
+ 		.name	= "extcon-gpio",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c
+index 437f573dc582..b656dfa401a6 100644
+--- a/drivers/extcon/extcon-max77693.c
++++ b/drivers/extcon/extcon-max77693.c
+@@ -795,7 +795,7 @@ static struct platform_driver max77693_muic_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= max77693_muic_probe,
+-	.remove		= __devexit_p(max77693_muic_remove),
++	.remove		= max77693_muic_remove,
+ };
+ 
+ module_platform_driver(max77693_muic_driver);
+diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
+index 49812991c5e6..bad76f51161b 100644
+--- a/drivers/extcon/extcon-max8997.c
++++ b/drivers/extcon/extcon-max8997.c
+@@ -531,7 +531,7 @@ static struct platform_driver max8997_muic_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= max8997_muic_probe,
+-	.remove		= __devexit_p(max8997_muic_remove),
++	.remove		= max8997_muic_remove,
+ };
+ 
+ module_platform_driver(max8997_muic_driver);

commit 44f34fd4a7f80439f14bdd2df032b0b4427c4ab0
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:23:21 2012 -0500
+
+    extcon: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: MyungJoo Ham 
+    Cc: Chanwoo Choi 
+    Acked-by: Mark Brown 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c
+index b88ae918a262..84144e6708c7 100644
+--- a/drivers/extcon/extcon-adc-jack.c
++++ b/drivers/extcon/extcon-adc-jack.c
+@@ -91,7 +91,7 @@ static irqreturn_t adc_jack_irq_thread(int irq, void *_data)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit adc_jack_probe(struct platform_device *pdev)
++static int adc_jack_probe(struct platform_device *pdev)
+ {
+ 	struct adc_jack_data *data;
+ 	struct adc_jack_pdata *pdata = pdev->dev.platform_data;
+diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
+index c4ea28c30c33..2473be9ac5de 100644
+--- a/drivers/extcon/extcon-arizona.c
++++ b/drivers/extcon/extcon-arizona.c
+@@ -337,7 +337,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit arizona_extcon_probe(struct platform_device *pdev)
++static int arizona_extcon_probe(struct platform_device *pdev)
+ {
+ 	struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
+ 	struct arizona_pdata *pdata;
+diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c
+index 3fe3381dc60a..e02219e5a3d8 100644
+--- a/drivers/extcon/extcon-gpio.c
++++ b/drivers/extcon/extcon-gpio.c
+@@ -76,7 +76,7 @@ static ssize_t extcon_gpio_print_state(struct extcon_dev *edev, char *buf)
+ 	return -EINVAL;
+ }
+ 
+-static int __devinit gpio_extcon_probe(struct platform_device *pdev)
++static int gpio_extcon_probe(struct platform_device *pdev)
+ {
+ 	struct gpio_extcon_platform_data *pdata = pdev->dev.platform_data;
+ 	struct gpio_extcon_data *extcon_data;
+diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c
+index 3cde2c5c88f3..437f573dc582 100644
+--- a/drivers/extcon/extcon-max77693.c
++++ b/drivers/extcon/extcon-max77693.c
+@@ -648,7 +648,7 @@ static int max77693_muic_detect_accessory(struct max77693_muic_info *info)
+ 	return ret;
+ }
+ 
+-static int __devinit max77693_muic_probe(struct platform_device *pdev)
++static int max77693_muic_probe(struct platform_device *pdev)
+ {
+ 	struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent);
+ 	struct max77693_platform_data *pdata = dev_get_platdata(max77693->dev);
+diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
+index b85189b20b97..49812991c5e6 100644
+--- a/drivers/extcon/extcon-max8997.c
++++ b/drivers/extcon/extcon-max8997.c
+@@ -426,7 +426,7 @@ static void max8997_muic_detect_dev(struct max8997_muic_info *info)
+ 	max8997_muic_handle_charger_type(info, chg_type);
+ }
+ 
+-static int __devinit max8997_muic_probe(struct platform_device *pdev)
++static int max8997_muic_probe(struct platform_device *pdev)
+ {
+ 	struct max8997_dev *max8997 = dev_get_drvdata(pdev->dev.parent);
+ 	struct max8997_platform_data *pdata = dev_get_platdata(max8997->dev);

commit 93ed0327808f7d7ef0fc90114c3457629dd683c1
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:25:49 2012 -0500
+
+    extcon: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: MyungJoo Ham 
+    Cc: Chanwoo Choi 
+    Acked-by: Mark Brown 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c
+index e87196f6d2d2..b88ae918a262 100644
+--- a/drivers/extcon/extcon-adc-jack.c
++++ b/drivers/extcon/extcon-adc-jack.c
+@@ -175,7 +175,7 @@ static int __devinit adc_jack_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit adc_jack_remove(struct platform_device *pdev)
++static int adc_jack_remove(struct platform_device *pdev)
+ {
+ 	struct adc_jack_data *data = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
+index cdab9e598297..c4ea28c30c33 100644
+--- a/drivers/extcon/extcon-arizona.c
++++ b/drivers/extcon/extcon-arizona.c
+@@ -517,7 +517,7 @@ static int __devinit arizona_extcon_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit arizona_extcon_remove(struct platform_device *pdev)
++static int arizona_extcon_remove(struct platform_device *pdev)
+ {
+ 	struct arizona_extcon_info *info = platform_get_drvdata(pdev);
+ 	struct arizona *arizona = info->arizona;
+diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c
+index 71d3ab7b3d8d..3fe3381dc60a 100644
+--- a/drivers/extcon/extcon-gpio.c
++++ b/drivers/extcon/extcon-gpio.c
+@@ -137,7 +137,7 @@ static int __devinit gpio_extcon_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit gpio_extcon_remove(struct platform_device *pdev)
++static int gpio_extcon_remove(struct platform_device *pdev)
+ {
+ 	struct gpio_extcon_data *extcon_data = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c
+index a17d0d91ada2..3cde2c5c88f3 100644
+--- a/drivers/extcon/extcon-max77693.c
++++ b/drivers/extcon/extcon-max77693.c
+@@ -774,7 +774,7 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit max77693_muic_remove(struct platform_device *pdev)
++static int max77693_muic_remove(struct platform_device *pdev)
+ {
+ 	struct max77693_muic_info *info = platform_get_drvdata(pdev);
+ 	int i;
+diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
+index 77b66b0cc8f5..b85189b20b97 100644
+--- a/drivers/extcon/extcon-max8997.c
++++ b/drivers/extcon/extcon-max8997.c
+@@ -508,7 +508,7 @@ static int __devinit max8997_muic_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit max8997_muic_remove(struct platform_device *pdev)
++static int max8997_muic_remove(struct platform_device *pdev)
+ {
+ 	struct max8997_muic_info *info = platform_get_drvdata(pdev);
+ 	int i;

commit e2619cf78e19476bfd7ceaefa9eff0847529346e
+Author: Bill Pemberton 
+Date:   Fri Nov 23 21:50:47 2012 -0800
+
+    Input: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Mark Brown 
+    Signed-off-by: Dmitry Torokhov 
+
+diff --git a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c
+index 786fa316c65f..fa7a95c1da0e 100644
+--- a/drivers/input/gameport/emu10k1-gp.c
++++ b/drivers/input/gameport/emu10k1-gp.c
+@@ -107,7 +107,7 @@ static int emu_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	return error;
+ }
+ 
+-static void __devexit emu_remove(struct pci_dev *pdev)
++static void emu_remove(struct pci_dev *pdev)
+ {
+ 	struct emu *emu = pci_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c
+index b1705e17020f..ae912d3aee4e 100644
+--- a/drivers/input/gameport/fm801-gp.c
++++ b/drivers/input/gameport/fm801-gp.c
+@@ -129,7 +129,7 @@ static int fm801_gp_probe(struct pci_dev *pci, const struct pci_device_id *id)
+ 	return error;
+ }
+ 
+-static void __devexit fm801_gp_remove(struct pci_dev *pci)
++static void fm801_gp_remove(struct pci_dev *pci)
+ {
+ 	struct fm801_gp *gp = pci_get_drvdata(pci);
+ 
+diff --git a/drivers/input/joystick/as5011.c b/drivers/input/joystick/as5011.c
+index ad7673305d7d..121cd63d3334 100644
+--- a/drivers/input/joystick/as5011.c
++++ b/drivers/input/joystick/as5011.c
+@@ -341,7 +341,7 @@ static int as5011_probe(struct i2c_client *client,
+ 	return error;
+ }
+ 
+-static int __devexit as5011_remove(struct i2c_client *client)
++static int as5011_remove(struct i2c_client *client)
+ {
+ 	struct as5011_device *as5011 = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/joystick/maplecontrol.c b/drivers/input/joystick/maplecontrol.c
+index 5ff3cb4a6de3..59c10ec5a2a1 100644
+--- a/drivers/input/joystick/maplecontrol.c
++++ b/drivers/input/joystick/maplecontrol.c
+@@ -157,7 +157,7 @@ static int probe_maple_controller(struct device *dev)
+ 	return error;
+ }
+ 
+-static int __devexit remove_maple_controller(struct device *dev)
++static int remove_maple_controller(struct device *dev)
+ {
+ 	struct maple_device *mdev = to_maple_dev(dev);
+ 	struct dc_pad *pad = maple_get_drvdata(mdev);
+diff --git a/drivers/input/keyboard/adp5520-keys.c b/drivers/input/keyboard/adp5520-keys.c
+index 64de9652398f..ef26b17fb159 100644
+--- a/drivers/input/keyboard/adp5520-keys.c
++++ b/drivers/input/keyboard/adp5520-keys.c
+@@ -182,7 +182,7 @@ static int adp5520_keys_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit adp5520_keys_remove(struct platform_device *pdev)
++static int adp5520_keys_remove(struct platform_device *pdev)
+ {
+ 	struct adp5520_keys *dev = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c
+index a20fe70ffa83..dbd2047f1641 100644
+--- a/drivers/input/keyboard/adp5588-keys.c
++++ b/drivers/input/keyboard/adp5588-keys.c
+@@ -224,7 +224,7 @@ static int adp5588_gpio_add(struct adp5588_kpad *kpad)
+ 	return 0;
+ }
+ 
+-static void __devexit adp5588_gpio_remove(struct adp5588_kpad *kpad)
++static void adp5588_gpio_remove(struct adp5588_kpad *kpad)
+ {
+ 	struct device *dev = &kpad->client->dev;
+ 	const struct adp5588_kpad_platform_data *pdata = dev->platform_data;
+@@ -587,7 +587,7 @@ static int adp5588_probe(struct i2c_client *client,
+ 	return error;
+ }
+ 
+-static int __devexit adp5588_remove(struct i2c_client *client)
++static int adp5588_remove(struct i2c_client *client)
+ {
+ 	struct adp5588_kpad *kpad = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c
+index 8f591da17deb..67d12b3427c9 100644
+--- a/drivers/input/keyboard/adp5589-keys.c
++++ b/drivers/input/keyboard/adp5589-keys.c
+@@ -550,7 +550,7 @@ static int adp5589_gpio_add(struct adp5589_kpad *kpad)
+ 	return 0;
+ }
+ 
+-static void __devexit adp5589_gpio_remove(struct adp5589_kpad *kpad)
++static void adp5589_gpio_remove(struct adp5589_kpad *kpad)
+ {
+ 	struct device *dev = &kpad->client->dev;
+ 	const struct adp5589_kpad_platform_data *pdata = dev->platform_data;
+@@ -1044,7 +1044,7 @@ static int adp5589_probe(struct i2c_client *client,
+ 	return error;
+ }
+ 
+-static int __devexit adp5589_remove(struct i2c_client *client)
++static int adp5589_remove(struct i2c_client *client)
+ {
+ 	struct adp5589_kpad *kpad = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c
+index 8f3c2b665382..20b9fa91fb9e 100644
+--- a/drivers/input/keyboard/bf54x-keys.c
++++ b/drivers/input/keyboard/bf54x-keys.c
+@@ -331,7 +331,7 @@ static int bfin_kpad_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit bfin_kpad_remove(struct platform_device *pdev)
++static int bfin_kpad_remove(struct platform_device *pdev)
+ {
+ 	struct bfin_kpad_platform_data *pdata = pdev->dev.platform_data;
+ 	struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
+diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c
+index 8e4b438ddc8d..4e4e453ea15e 100644
+--- a/drivers/input/keyboard/davinci_keyscan.c
++++ b/drivers/input/keyboard/davinci_keyscan.c
+@@ -303,7 +303,7 @@ static int __init davinci_ks_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit davinci_ks_remove(struct platform_device *pdev)
++static int davinci_ks_remove(struct platform_device *pdev)
+ {
+ 	struct davinci_ks *davinci_ks = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c
+index 30c00082ed90..9857e8fd0987 100644
+--- a/drivers/input/keyboard/ep93xx_keypad.c
++++ b/drivers/input/keyboard/ep93xx_keypad.c
+@@ -346,7 +346,7 @@ static int ep93xx_keypad_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit ep93xx_keypad_remove(struct platform_device *pdev)
++static int ep93xx_keypad_remove(struct platform_device *pdev)
+ {
+ 	struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
+ 	struct resource *res;
+diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
+index c714c585c307..1a5cb6f34f4c 100644
+--- a/drivers/input/keyboard/gpio_keys.c
++++ b/drivers/input/keyboard/gpio_keys.c
+@@ -760,7 +760,7 @@ static int gpio_keys_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit gpio_keys_remove(struct platform_device *pdev)
++static int gpio_keys_remove(struct platform_device *pdev)
+ {
+ 	struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
+ 	struct input_dev *input = ddata->input;
+diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c
+index 8c09ce244aa2..32e508781ddc 100644
+--- a/drivers/input/keyboard/gpio_keys_polled.c
++++ b/drivers/input/keyboard/gpio_keys_polled.c
+@@ -328,7 +328,7 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit gpio_keys_polled_remove(struct platform_device *pdev)
++static int gpio_keys_polled_remove(struct platform_device *pdev)
+ {
+ 	struct gpio_keys_polled_dev *bdev = platform_get_drvdata(pdev);
+ 	const struct gpio_keys_platform_data *pdata = bdev->pdata;
+diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c
+index a5da05ac6094..198dc07a1be5 100644
+--- a/drivers/input/keyboard/hilkbd.c
++++ b/drivers/input/keyboard/hilkbd.c
+@@ -286,7 +286,7 @@ static int hil_keyb_init(void)
+ 	return err;
+ }
+ 
+-static void __devexit hil_keyb_exit(void)
++static void hil_keyb_exit(void)
+ {
+ 	if (HIL_IRQ)
+ 		free_irq(HIL_IRQ, hil_dev.dev_id);
+@@ -320,7 +320,7 @@ static int hil_probe_chip(struct parisc_device *dev)
+ 	return hil_keyb_init();
+ }
+ 
+-static int __devexit hil_remove_chip(struct parisc_device *dev)
++static int hil_remove_chip(struct parisc_device *dev)
+ {
+ 	hil_keyb_exit();
+ 
+diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c
+index d4d95428c276..7ad74517654b 100644
+--- a/drivers/input/keyboard/imx_keypad.c
++++ b/drivers/input/keyboard/imx_keypad.c
+@@ -554,7 +554,7 @@ static int imx_keypad_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit imx_keypad_remove(struct platform_device *pdev)
++static int imx_keypad_remove(struct platform_device *pdev)
+ {
+ 	struct imx_keypad *keypad = platform_get_drvdata(pdev);
+ 	struct resource *res;
+diff --git a/drivers/input/keyboard/jornada680_kbd.c b/drivers/input/keyboard/jornada680_kbd.c
+index eac650c26ad4..74e75a6e8deb 100644
+--- a/drivers/input/keyboard/jornada680_kbd.c
++++ b/drivers/input/keyboard/jornada680_kbd.c
+@@ -240,7 +240,7 @@ static int jornada680kbd_probe(struct platform_device *pdev)
+ 
+ }
+ 
+-static int __devexit jornada680kbd_remove(struct platform_device *pdev)
++static int jornada680kbd_remove(struct platform_device *pdev)
+ {
+ 	struct jornadakbd *jornadakbd = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/keyboard/jornada720_kbd.c b/drivers/input/keyboard/jornada720_kbd.c
+index 2f08a03e7cba..5ceef636df2f 100644
+--- a/drivers/input/keyboard/jornada720_kbd.c
++++ b/drivers/input/keyboard/jornada720_kbd.c
+@@ -152,7 +152,7 @@ static int jornada720_kbd_probe(struct platform_device *pdev)
+ 	return err;
+ };
+ 
+-static int __devexit jornada720_kbd_remove(struct platform_device *pdev)
++static int jornada720_kbd_remove(struct platform_device *pdev)
+ {
+ 	struct jornadakbd *jornadakbd = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c
+index ee0116b0a427..93c812662134 100644
+--- a/drivers/input/keyboard/lm8323.c
++++ b/drivers/input/keyboard/lm8323.c
+@@ -764,7 +764,7 @@ static int lm8323_probe(struct i2c_client *client,
+ 	return err;
+ }
+ 
+-static int __devexit lm8323_remove(struct i2c_client *client)
++static int lm8323_remove(struct i2c_client *client)
+ {
+ 	struct lm8323_chip *lm = i2c_get_clientdata(client);
+ 	int i;
+diff --git a/drivers/input/keyboard/lm8333.c b/drivers/input/keyboard/lm8333.c
+index 9fc03727d61d..5a8ca35dc9af 100644
+--- a/drivers/input/keyboard/lm8333.c
++++ b/drivers/input/keyboard/lm8333.c
+@@ -202,7 +202,7 @@ static int lm8333_probe(struct i2c_client *client,
+ 	return err;
+ }
+ 
+-static int __devexit lm8333_remove(struct i2c_client *client)
++static int lm8333_remove(struct i2c_client *client)
+ {
+ 	struct lm8333 *lm8333 = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c
+index e2892466f3cc..c94d610b9d78 100644
+--- a/drivers/input/keyboard/locomokbd.c
++++ b/drivers/input/keyboard/locomokbd.c
+@@ -321,7 +321,7 @@ static int locomokbd_probe(struct locomo_dev *dev)
+ 	return err;
+ }
+ 
+-static int __devexit locomokbd_remove(struct locomo_dev *dev)
++static int locomokbd_remove(struct locomo_dev *dev)
+ {
+ 	struct locomokbd *locomokbd = locomo_get_drvdata(dev);
+ 
+diff --git a/drivers/input/keyboard/lpc32xx-keys.c b/drivers/input/keyboard/lpc32xx-keys.c
+index 72f8a0be82e1..1b8add6cfb9d 100644
+--- a/drivers/input/keyboard/lpc32xx-keys.c
++++ b/drivers/input/keyboard/lpc32xx-keys.c
+@@ -310,7 +310,7 @@ static int lpc32xx_kscan_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit lpc32xx_kscan_remove(struct platform_device *pdev)
++static int lpc32xx_kscan_remove(struct platform_device *pdev)
+ {
+ 	struct lpc32xx_kscan_drv *kscandat = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c
+index b9d67c2f30d6..f4ff0dda7597 100644
+--- a/drivers/input/keyboard/matrix_keypad.c
++++ b/drivers/input/keyboard/matrix_keypad.c
+@@ -539,7 +539,7 @@ static int matrix_keypad_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit matrix_keypad_remove(struct platform_device *pdev)
++static int matrix_keypad_remove(struct platform_device *pdev)
+ {
+ 	struct matrix_keypad *keypad = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c
+index 98b8ff10e6f1..7c7af2b01e65 100644
+--- a/drivers/input/keyboard/max7359_keypad.c
++++ b/drivers/input/keyboard/max7359_keypad.c
+@@ -260,7 +260,7 @@ static int max7359_probe(struct i2c_client *client,
+ 	return error;
+ }
+ 
+-static int __devexit max7359_remove(struct i2c_client *client)
++static int max7359_remove(struct i2c_client *client)
+ {
+ 	struct max7359_keypad *keypad = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c
+index e729774cecd8..7c236f9c6a51 100644
+--- a/drivers/input/keyboard/mcs_touchkey.c
++++ b/drivers/input/keyboard/mcs_touchkey.c
+@@ -200,7 +200,7 @@ static int mcs_touchkey_probe(struct i2c_client *client,
+ 	return error;
+ }
+ 
+-static int __devexit mcs_touchkey_remove(struct i2c_client *client)
++static int mcs_touchkey_remove(struct i2c_client *client)
+ {
+ 	struct mcs_touchkey_data *data = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c
+index 854486c347fe..f7f3e9a9fd3f 100644
+--- a/drivers/input/keyboard/mpr121_touchkey.c
++++ b/drivers/input/keyboard/mpr121_touchkey.c
+@@ -272,7 +272,7 @@ static int mpr_touchkey_probe(struct i2c_client *client,
+ 	return error;
+ }
+ 
+-static int __devexit mpr_touchkey_remove(struct i2c_client *client)
++static int mpr_touchkey_remove(struct i2c_client *client)
+ {
+ 	struct mpr121_touchkey *mpr121 = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c
+index 2304a8192cf7..0e6a8151fee3 100644
+--- a/drivers/input/keyboard/nomadik-ske-keypad.c
++++ b/drivers/input/keyboard/nomadik-ske-keypad.c
+@@ -366,7 +366,7 @@ static int __init ske_keypad_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit ske_keypad_remove(struct platform_device *pdev)
++static int ske_keypad_remove(struct platform_device *pdev)
+ {
+ 	struct ske_keypad *keypad = platform_get_drvdata(pdev);
+ 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c
+index ffb8c6c1c5dc..d0d5226d9cd4 100644
+--- a/drivers/input/keyboard/omap-keypad.c
++++ b/drivers/input/keyboard/omap-keypad.c
+@@ -357,7 +357,7 @@ static int omap_kp_probe(struct platform_device *pdev)
+ 	return -EINVAL;
+ }
+ 
+-static int __devexit omap_kp_remove(struct platform_device *pdev)
++static int omap_kp_remove(struct platform_device *pdev)
+ {
+ 	struct omap_kp *omap_kp = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
+index c16a3229968c..e25b022692cd 100644
+--- a/drivers/input/keyboard/omap4-keypad.c
++++ b/drivers/input/keyboard/omap4-keypad.c
+@@ -406,7 +406,7 @@ static int omap4_keypad_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit omap4_keypad_remove(struct platform_device *pdev)
++static int omap4_keypad_remove(struct platform_device *pdev)
+ {
+ 	struct omap4_keypad *keypad_data = platform_get_drvdata(pdev);
+ 	struct resource *res;
+diff --git a/drivers/input/keyboard/opencores-kbd.c b/drivers/input/keyboard/opencores-kbd.c
+index ddc1c39c0c31..7ac5f174c6f7 100644
+--- a/drivers/input/keyboard/opencores-kbd.c
++++ b/drivers/input/keyboard/opencores-kbd.c
+@@ -139,7 +139,7 @@ static int opencores_kbd_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit opencores_kbd_remove(struct platform_device *pdev)
++static int opencores_kbd_remove(struct platform_device *pdev)
+ {
+ 	struct opencores_kbd *opencores_kbd = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c
+index fa177aba5dbe..74339e139d43 100644
+--- a/drivers/input/keyboard/pmic8xxx-keypad.c
++++ b/drivers/input/keyboard/pmic8xxx-keypad.c
+@@ -712,7 +712,7 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev)
+ 	return rc;
+ }
+ 
+-static int __devexit pmic8xxx_kp_remove(struct platform_device *pdev)
++static int pmic8xxx_kp_remove(struct platform_device *pdev)
+ {
+ 	struct pmic8xxx_kp *kp = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
+index 91778fee8b99..5330d8fbf6c0 100644
+--- a/drivers/input/keyboard/pxa27x_keypad.c
++++ b/drivers/input/keyboard/pxa27x_keypad.c
+@@ -595,7 +595,7 @@ static int pxa27x_keypad_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit pxa27x_keypad_remove(struct platform_device *pdev)
++static int pxa27x_keypad_remove(struct platform_device *pdev)
+ {
+ 	struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
+ 	struct resource *res;
+diff --git a/drivers/input/keyboard/pxa930_rotary.c b/drivers/input/keyboard/pxa930_rotary.c
+index 60797c22322d..bcad95be73aa 100644
+--- a/drivers/input/keyboard/pxa930_rotary.c
++++ b/drivers/input/keyboard/pxa930_rotary.c
+@@ -174,7 +174,7 @@ static int pxa930_rotary_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit pxa930_rotary_remove(struct platform_device *pdev)
++static int pxa930_rotary_remove(struct platform_device *pdev)
+ {
+ 	struct pxa930_rotary *r = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/keyboard/qt1070.c b/drivers/input/keyboard/qt1070.c
+index f9358e7d90bc..42b773b3125a 100644
+--- a/drivers/input/keyboard/qt1070.c
++++ b/drivers/input/keyboard/qt1070.c
+@@ -230,7 +230,7 @@ static int qt1070_probe(struct i2c_client *client,
+ 	return err;
+ }
+ 
+-static int __devexit qt1070_remove(struct i2c_client *client)
++static int qt1070_remove(struct i2c_client *client)
+ {
+ 	struct qt1070_data *data = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c
+index 69a6a6ffdbe3..3dc2b0f27b0c 100644
+--- a/drivers/input/keyboard/qt2160.c
++++ b/drivers/input/keyboard/qt2160.c
+@@ -335,7 +335,7 @@ static int qt2160_probe(struct i2c_client *client,
+ 	return error;
+ }
+ 
+-static int __devexit qt2160_remove(struct i2c_client *client)
++static int qt2160_remove(struct i2c_client *client)
+ {
+ 	struct qt2160_data *qt2160 = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c
+index 5c6a808ed62d..acc161966c3e 100644
+--- a/drivers/input/keyboard/samsung-keypad.c
++++ b/drivers/input/keyboard/samsung-keypad.c
+@@ -523,7 +523,7 @@ static int samsung_keypad_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit samsung_keypad_remove(struct platform_device *pdev)
++static int samsung_keypad_remove(struct platform_device *pdev)
+ {
+ 	struct samsung_keypad *keypad = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c
+index ffa9adb23f21..fdb9eb2df380 100644
+--- a/drivers/input/keyboard/sh_keysc.c
++++ b/drivers/input/keyboard/sh_keysc.c
+@@ -272,7 +272,7 @@ static int sh_keysc_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit sh_keysc_remove(struct platform_device *pdev)
++static int sh_keysc_remove(struct platform_device *pdev)
+ {
+ 	struct sh_keysc_priv *priv = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c
+index 3c503dae7b64..d70093bef740 100644
+--- a/drivers/input/keyboard/spear-keyboard.c
++++ b/drivers/input/keyboard/spear-keyboard.c
+@@ -279,7 +279,7 @@ static int spear_kbd_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit spear_kbd_remove(struct platform_device *pdev)
++static int spear_kbd_remove(struct platform_device *pdev)
+ {
+ 	device_init_wakeup(&pdev->dev, 0);
+ 	platform_set_drvdata(pdev, NULL);
+diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c
+index b3f917d73cd6..7bac0524900a 100644
+--- a/drivers/input/keyboard/stmpe-keypad.c
++++ b/drivers/input/keyboard/stmpe-keypad.c
+@@ -335,7 +335,7 @@ static int stmpe_keypad_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit stmpe_keypad_remove(struct platform_device *pdev)
++static int stmpe_keypad_remove(struct platform_device *pdev)
+ {
+ 	struct stmpe_keypad *keypad = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/keyboard/tc3589x-keypad.c b/drivers/input/keyboard/tc3589x-keypad.c
+index 6d725d633aeb..2fb0d76a04c4 100644
+--- a/drivers/input/keyboard/tc3589x-keypad.c
++++ b/drivers/input/keyboard/tc3589x-keypad.c
+@@ -382,7 +382,7 @@ static int tc3589x_keypad_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit tc3589x_keypad_remove(struct platform_device *pdev)
++static int tc3589x_keypad_remove(struct platform_device *pdev)
+ {
+ 	struct tc_keypad *keypad = platform_get_drvdata(pdev);
+ 	int irq = platform_get_irq(pdev, 0);
+diff --git a/drivers/input/keyboard/tca6416-keypad.c b/drivers/input/keyboard/tca6416-keypad.c
+index 4f44579689a4..bfc832c35a7c 100644
+--- a/drivers/input/keyboard/tca6416-keypad.c
++++ b/drivers/input/keyboard/tca6416-keypad.c
+@@ -313,7 +313,7 @@ static int tca6416_keypad_probe(struct i2c_client *client,
+ 	return error;
+ }
+ 
+-static int __devexit tca6416_keypad_remove(struct i2c_client *client)
++static int tca6416_keypad_remove(struct i2c_client *client)
+ {
+ 	struct tca6416_keypad_chip *chip = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/keyboard/tca8418_keypad.c b/drivers/input/keyboard/tca8418_keypad.c
+index 6f970961f244..f1e966bdcff5 100644
+--- a/drivers/input/keyboard/tca8418_keypad.c
++++ b/drivers/input/keyboard/tca8418_keypad.c
+@@ -388,7 +388,7 @@ static int tca8418_keypad_probe(struct i2c_client *client,
+ 	return error;
+ }
+ 
+-static int __devexit tca8418_keypad_remove(struct i2c_client *client)
++static int tca8418_keypad_remove(struct i2c_client *client)
+ {
+ 	struct tca8418_keypad *keypad_data = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c
+index cf8ab689231b..c76f96872d31 100644
+--- a/drivers/input/keyboard/tegra-kbc.c
++++ b/drivers/input/keyboard/tegra-kbc.c
+@@ -838,7 +838,7 @@ static int tegra_kbc_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit tegra_kbc_remove(struct platform_device *pdev)
++static int tegra_kbc_remove(struct platform_device *pdev)
+ {
+ 	struct tegra_kbc *kbc = platform_get_drvdata(pdev);
+ 	struct resource *res;
+diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c
+index 55cd0700af8c..ee1635011292 100644
+--- a/drivers/input/keyboard/tnetv107x-keypad.c
++++ b/drivers/input/keyboard/tnetv107x-keypad.c
+@@ -301,7 +301,7 @@ static int keypad_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit keypad_remove(struct platform_device *pdev)
++static int keypad_remove(struct platform_device *pdev)
+ {
+ 	struct keypad_data *kp = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c
+index 78dd9f27dd87..04f84fd57173 100644
+--- a/drivers/input/keyboard/twl4030_keypad.c
++++ b/drivers/input/keyboard/twl4030_keypad.c
+@@ -432,7 +432,7 @@ static int twl4030_kp_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit twl4030_kp_remove(struct platform_device *pdev)
++static int twl4030_kp_remove(struct platform_device *pdev)
+ {
+ 	struct twl4030_keypad *kp = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c
+index 7574e10ef097..ee163bee8cce 100644
+--- a/drivers/input/keyboard/w90p910_keypad.c
++++ b/drivers/input/keyboard/w90p910_keypad.c
+@@ -234,7 +234,7 @@ static int w90p910_keypad_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit w90p910_keypad_remove(struct platform_device *pdev)
++static int w90p910_keypad_remove(struct platform_device *pdev)
+ {
+ 	struct w90p910_keypad *keypad = platform_get_drvdata(pdev);
+ 	struct resource *res;
+diff --git a/drivers/input/misc/88pm80x_onkey.c b/drivers/input/misc/88pm80x_onkey.c
+index 946edcadfb2e..ee43e5b7c881 100644
+--- a/drivers/input/misc/88pm80x_onkey.c
++++ b/drivers/input/misc/88pm80x_onkey.c
+@@ -139,7 +139,7 @@ static int pm80x_onkey_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit pm80x_onkey_remove(struct platform_device *pdev)
++static int pm80x_onkey_remove(struct platform_device *pdev)
+ {
+ 	struct pm80x_onkey_info *info = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/misc/88pm860x_onkey.c b/drivers/input/misc/88pm860x_onkey.c
+index 81af2d70e5dc..abd8453e5212 100644
+--- a/drivers/input/misc/88pm860x_onkey.c
++++ b/drivers/input/misc/88pm860x_onkey.c
+@@ -121,7 +121,7 @@ static int pm860x_onkey_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit pm860x_onkey_remove(struct platform_device *pdev)
++static int pm860x_onkey_remove(struct platform_device *pdev)
+ {
+ 	struct pm860x_onkey_info *info = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/misc/ab8500-ponkey.c b/drivers/input/misc/ab8500-ponkey.c
+index f188222d208d..2f090b46e716 100644
+--- a/drivers/input/misc/ab8500-ponkey.c
++++ b/drivers/input/misc/ab8500-ponkey.c
+@@ -118,7 +118,7 @@ static int ab8500_ponkey_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit ab8500_ponkey_remove(struct platform_device *pdev)
++static int ab8500_ponkey_remove(struct platform_device *pdev)
+ {
+ 	struct ab8500_ponkey *ponkey = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c
+index 9477602c7211..29d2064c26f2 100644
+--- a/drivers/input/misc/ad714x-i2c.c
++++ b/drivers/input/misc/ad714x-i2c.c
+@@ -87,7 +87,7 @@ static int ad714x_i2c_probe(struct i2c_client *client,
+ 	return 0;
+ }
+ 
+-static int __devexit ad714x_i2c_remove(struct i2c_client *client)
++static int ad714x_i2c_remove(struct i2c_client *client)
+ {
+ 	struct ad714x_chip *chip = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/misc/ad714x-spi.c b/drivers/input/misc/ad714x-spi.c
+index 497871e506f4..bdccca42d138 100644
+--- a/drivers/input/misc/ad714x-spi.c
++++ b/drivers/input/misc/ad714x-spi.c
+@@ -103,7 +103,7 @@ static int ad714x_spi_probe(struct spi_device *spi)
+ 	return 0;
+ }
+ 
+-static int __devexit ad714x_spi_remove(struct spi_device *spi)
++static int ad714x_spi_remove(struct spi_device *spi)
+ {
+ 	struct ad714x_chip *chip = spi_get_drvdata(spi);
+ 
+diff --git a/drivers/input/misc/adxl34x-i2c.c b/drivers/input/misc/adxl34x-i2c.c
+index e262885f62de..535dda48cace 100644
+--- a/drivers/input/misc/adxl34x-i2c.c
++++ b/drivers/input/misc/adxl34x-i2c.c
+@@ -98,7 +98,7 @@ static int adxl34x_i2c_probe(struct i2c_client *client,
+ 	return 0;
+ }
+ 
+-static int __devexit adxl34x_i2c_remove(struct i2c_client *client)
++static int adxl34x_i2c_remove(struct i2c_client *client)
+ {
+ 	struct adxl34x *ac = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/misc/adxl34x-spi.c b/drivers/input/misc/adxl34x-spi.c
+index 1071d252df07..ad5f40d37e48 100644
+--- a/drivers/input/misc/adxl34x-spi.c
++++ b/drivers/input/misc/adxl34x-spi.c
+@@ -87,7 +87,7 @@ static int adxl34x_spi_probe(struct spi_device *spi)
+ 	return 0;
+ }
+ 
+-static int __devexit adxl34x_spi_remove(struct spi_device *spi)
++static int adxl34x_spi_remove(struct spi_device *spi)
+ {
+ 	struct adxl34x *ac = dev_get_drvdata(&spi->dev);
+ 
+diff --git a/drivers/input/misc/bfin_rotary.c b/drivers/input/misc/bfin_rotary.c
+index 9cb4a74a479a..a6666e142a91 100644
+--- a/drivers/input/misc/bfin_rotary.c
++++ b/drivers/input/misc/bfin_rotary.c
+@@ -196,7 +196,7 @@ static int bfin_rotary_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit bfin_rotary_remove(struct platform_device *pdev)
++static int bfin_rotary_remove(struct platform_device *pdev)
+ {
+ 	struct bfin_rot *rotary = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c
+index a3219c2a3855..08ffcabd7220 100644
+--- a/drivers/input/misc/bma150.c
++++ b/drivers/input/misc/bma150.c
+@@ -613,7 +613,7 @@ static int bma150_probe(struct i2c_client *client,
+ 	return error;
+ }
+ 
+-static int __devexit bma150_remove(struct i2c_client *client)
++static int bma150_remove(struct i2c_client *client)
+ {
+ 	struct bma150_data *bma150 = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/misc/cma3000_d0x_i2c.c b/drivers/input/misc/cma3000_d0x_i2c.c
+index ca2103efaf17..4fdef98ceb56 100644
+--- a/drivers/input/misc/cma3000_d0x_i2c.c
++++ b/drivers/input/misc/cma3000_d0x_i2c.c
+@@ -69,7 +69,7 @@ static int cma3000_i2c_probe(struct i2c_client *client,
+ 	return 0;
+ }
+ 
+-static int __devexit cma3000_i2c_remove(struct i2c_client *client)
++static int cma3000_i2c_remove(struct i2c_client *client)
+ {
+ 	struct cma3000_accl_data *data = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c
+index beeb53dc073d..4f77f87847e8 100644
+--- a/drivers/input/misc/cobalt_btns.c
++++ b/drivers/input/misc/cobalt_btns.c
+@@ -135,7 +135,7 @@ static int cobalt_buttons_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit cobalt_buttons_remove(struct platform_device *pdev)
++static int cobalt_buttons_remove(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	struct buttons_dev *bdev = dev_get_drvdata(dev);
+diff --git a/drivers/input/misc/da9052_onkey.c b/drivers/input/misc/da9052_onkey.c
+index 8464029972db..630c1ce4980a 100644
+--- a/drivers/input/misc/da9052_onkey.c
++++ b/drivers/input/misc/da9052_onkey.c
+@@ -141,7 +141,7 @@ static int da9052_onkey_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit da9052_onkey_remove(struct platform_device *pdev)
++static int da9052_onkey_remove(struct platform_device *pdev)
+ {
+ 	struct da9052_onkey *onkey = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/misc/da9055_onkey.c b/drivers/input/misc/da9055_onkey.c
+index cbf49893450c..ee6ae3a00174 100644
+--- a/drivers/input/misc/da9055_onkey.c
++++ b/drivers/input/misc/da9055_onkey.c
+@@ -141,7 +141,7 @@ static int da9055_onkey_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit da9055_onkey_remove(struct platform_device *pdev)
++static int da9055_onkey_remove(struct platform_device *pdev)
+ {
+ 	struct da9055_onkey *onkey = platform_get_drvdata(pdev);
+ 	int irq = platform_get_irq_byname(pdev, "ONKEY");
+diff --git a/drivers/input/misc/dm355evm_keys.c b/drivers/input/misc/dm355evm_keys.c
+index 5409ab7684bb..a309a5c0899e 100644
+--- a/drivers/input/misc/dm355evm_keys.c
++++ b/drivers/input/misc/dm355evm_keys.c
+@@ -239,7 +239,7 @@ static int dm355evm_keys_probe(struct platform_device *pdev)
+ 	return status;
+ }
+ 
+-static int __devexit dm355evm_keys_remove(struct platform_device *pdev)
++static int dm355evm_keys_remove(struct platform_device *pdev)
+ {
+ 	struct dm355evm_keys	*keys = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/misc/gp2ap002a00f.c b/drivers/input/misc/gp2ap002a00f.c
+index 8ad99be5e5c8..fe30bd0fe4bd 100644
+--- a/drivers/input/misc/gp2ap002a00f.c
++++ b/drivers/input/misc/gp2ap002a00f.c
+@@ -205,7 +205,7 @@ static int gp2a_probe(struct i2c_client *client,
+ 	return error;
+ }
+ 
+-static int __devexit gp2a_remove(struct i2c_client *client)
++static int gp2a_remove(struct i2c_client *client)
+ {
+ 	struct gp2a_data *dt = i2c_get_clientdata(client);
+ 	const struct gp2a_platform_data *pdata = dt->pdata;
+diff --git a/drivers/input/misc/gpio_tilt_polled.c b/drivers/input/misc/gpio_tilt_polled.c
+index 467884be3b3a..da05cca8b562 100644
+--- a/drivers/input/misc/gpio_tilt_polled.c
++++ b/drivers/input/misc/gpio_tilt_polled.c
+@@ -179,7 +179,7 @@ static int gpio_tilt_polled_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit gpio_tilt_polled_remove(struct platform_device *pdev)
++static int gpio_tilt_polled_remove(struct platform_device *pdev)
+ {
+ 	struct gpio_tilt_polled_dev *tdev = platform_get_drvdata(pdev);
+ 	const struct gpio_tilt_platform_data *pdata = tdev->pdata;
+diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c
+index 97620d56ac0a..6ab3decc86e6 100644
+--- a/drivers/input/misc/ixp4xx-beeper.c
++++ b/drivers/input/misc/ixp4xx-beeper.c
+@@ -132,7 +132,7 @@ static int ixp4xx_spkr_probe(struct platform_device *dev)
+ 	return err;
+ }
+ 
+-static int __devexit ixp4xx_spkr_remove(struct platform_device *dev)
++static int ixp4xx_spkr_remove(struct platform_device *dev)
+ {
+ 	struct input_dev *input_dev = platform_get_drvdata(dev);
+ 	unsigned int pin = (unsigned int) input_get_drvdata(input_dev);
+diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
+index 57f1f1284165..a993b67a8a5b 100644
+--- a/drivers/input/misc/kxtj9.c
++++ b/drivers/input/misc/kxtj9.c
+@@ -466,7 +466,7 @@ static int kxtj9_setup_polled_device(struct kxtj9_data *tj9)
+ 	return 0;
+ }
+ 
+-static void __devexit kxtj9_teardown_polled_device(struct kxtj9_data *tj9)
++static void kxtj9_teardown_polled_device(struct kxtj9_data *tj9)
+ {
+ 	input_unregister_polled_device(tj9->poll_dev);
+ 	input_free_polled_device(tj9->poll_dev);
+@@ -594,7 +594,7 @@ static int kxtj9_probe(struct i2c_client *client,
+ 	return err;
+ }
+ 
+-static int __devexit kxtj9_remove(struct i2c_client *client)
++static int kxtj9_remove(struct i2c_client *client)
+ {
+ 	struct kxtj9_data *tj9 = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/misc/m68kspkr.c b/drivers/input/misc/m68kspkr.c
+index ec8f59dcb46c..b40ee4b47f4f 100644
+--- a/drivers/input/misc/m68kspkr.c
++++ b/drivers/input/misc/m68kspkr.c
+@@ -80,7 +80,7 @@ static int m68kspkr_probe(struct platform_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devexit m68kspkr_remove(struct platform_device *dev)
++static int m68kspkr_remove(struct platform_device *dev)
+ {
+ 	struct input_dev *input_dev = platform_get_drvdata(dev);
+ 
+diff --git a/drivers/input/misc/max8925_onkey.c b/drivers/input/misc/max8925_onkey.c
+index 57bc42c92d4b..369a39de4ff3 100644
+--- a/drivers/input/misc/max8925_onkey.c
++++ b/drivers/input/misc/max8925_onkey.c
+@@ -141,7 +141,7 @@ static int max8925_onkey_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit max8925_onkey_remove(struct platform_device *pdev)
++static int max8925_onkey_remove(struct platform_device *pdev)
+ {
+ 	struct max8925_onkey_info *info = platform_get_drvdata(pdev);
+ 	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
+diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c
+index 2613b2f3174e..e973133212a5 100644
+--- a/drivers/input/misc/max8997_haptic.c
++++ b/drivers/input/misc/max8997_haptic.c
+@@ -354,7 +354,7 @@ static int max8997_haptic_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit max8997_haptic_remove(struct platform_device *pdev)
++static int max8997_haptic_remove(struct platform_device *pdev)
+ {
+ 	struct max8997_haptic *chip = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/misc/mc13783-pwrbutton.c b/drivers/input/misc/mc13783-pwrbutton.c
+index a50ad911c7f5..0906ca593d5f 100644
+--- a/drivers/input/misc/mc13783-pwrbutton.c
++++ b/drivers/input/misc/mc13783-pwrbutton.c
+@@ -230,7 +230,7 @@ static int mc13783_pwrbutton_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit mc13783_pwrbutton_remove(struct platform_device *pdev)
++static int mc13783_pwrbutton_remove(struct platform_device *pdev)
+ {
+ 	struct mc13783_pwrb *priv = platform_get_drvdata(pdev);
+ 	const struct mc13xxx_buttons_platform_data *pdata;
+diff --git a/drivers/input/misc/mma8450.c b/drivers/input/misc/mma8450.c
+index d4528cc47f8f..480557f14f23 100644
+--- a/drivers/input/misc/mma8450.c
++++ b/drivers/input/misc/mma8450.c
+@@ -212,7 +212,7 @@ static int mma8450_probe(struct i2c_client *c,
+ 	return err;
+ }
+ 
+-static int __devexit mma8450_remove(struct i2c_client *c)
++static int mma8450_remove(struct i2c_client *c)
+ {
+ 	struct mma8450 *m = i2c_get_clientdata(c);
+ 	struct input_polled_dev *idev = m->idev;
+diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c
+index ff600565654e..dce0d95943c5 100644
+--- a/drivers/input/misc/mpu3050.c
++++ b/drivers/input/misc/mpu3050.c
+@@ -402,7 +402,7 @@ static int mpu3050_probe(struct i2c_client *client,
+  *
+  *	Our sensor is going away, clean up the resources.
+  */
+-static int __devexit mpu3050_remove(struct i2c_client *client)
++static int mpu3050_remove(struct i2c_client *client)
+ {
+ 	struct mpu3050_sensor *sensor = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/misc/pcap_keys.c b/drivers/input/misc/pcap_keys.c
+index 56d03ac3a430..40ac9a5adf89 100644
+--- a/drivers/input/misc/pcap_keys.c
++++ b/drivers/input/misc/pcap_keys.c
+@@ -104,7 +104,7 @@ static int pcap_keys_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit pcap_keys_remove(struct platform_device *pdev)
++static int pcap_keys_remove(struct platform_device *pdev)
+ {
+ 	struct pcap_keys *pcap_keys = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/misc/pcf50633-input.c b/drivers/input/misc/pcf50633-input.c
+index 8efb898863c7..73b13ebabe56 100644
+--- a/drivers/input/misc/pcf50633-input.c
++++ b/drivers/input/misc/pcf50633-input.c
+@@ -93,7 +93,7 @@ static int pcf50633_input_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit pcf50633_input_remove(struct platform_device *pdev)
++static int pcf50633_input_remove(struct platform_device *pdev)
+ {
+ 	struct pcf50633_input *input  = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/misc/pcf8574_keypad.c b/drivers/input/misc/pcf8574_keypad.c
+index dbe2093c284b..e37392976fdd 100644
+--- a/drivers/input/misc/pcf8574_keypad.c
++++ b/drivers/input/misc/pcf8574_keypad.c
+@@ -156,7 +156,7 @@ static int pcf8574_kp_probe(struct i2c_client *client, const struct i2c_device_i
+ 	return ret;
+ }
+ 
+-static int __devexit pcf8574_kp_remove(struct i2c_client *client)
++static int pcf8574_kp_remove(struct i2c_client *client)
+ {
+ 	struct kp_data *lp = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c
+index 943b461aaf3f..199db78acc4f 100644
+--- a/drivers/input/misc/pcspkr.c
++++ b/drivers/input/misc/pcspkr.c
+@@ -95,7 +95,7 @@ static int pcspkr_probe(struct platform_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devexit pcspkr_remove(struct platform_device *dev)
++static int pcspkr_remove(struct platform_device *dev)
+ {
+ 	struct input_dev *pcspkr_dev = platform_get_drvdata(dev);
+ 
+diff --git a/drivers/input/misc/pm8xxx-vibrator.c b/drivers/input/misc/pm8xxx-vibrator.c
+index 1ac2b1f548a9..a9da65e41c5b 100644
+--- a/drivers/input/misc/pm8xxx-vibrator.c
++++ b/drivers/input/misc/pm8xxx-vibrator.c
+@@ -242,7 +242,7 @@ static int pm8xxx_vib_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit pm8xxx_vib_remove(struct platform_device *pdev)
++static int pm8xxx_vib_remove(struct platform_device *pdev)
+ {
+ 	struct pm8xxx_vib *vib = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c
+index 26e49acefa9c..4b811be73974 100644
+--- a/drivers/input/misc/pmic8xxx-pwrkey.c
++++ b/drivers/input/misc/pmic8xxx-pwrkey.c
+@@ -187,7 +187,7 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit pmic8xxx_pwrkey_remove(struct platform_device *pdev)
++static int pmic8xxx_pwrkey_remove(struct platform_device *pdev)
+ {
+ 	struct pmic8xxx_pwrkey *pwrkey = platform_get_drvdata(pdev);
+ 	int key_release_irq = platform_get_irq(pdev, 0);
+diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c
+index 48b505bddb1c..0808868461de 100644
+--- a/drivers/input/misc/pwm-beeper.c
++++ b/drivers/input/misc/pwm-beeper.c
+@@ -129,7 +129,7 @@ static int pwm_beeper_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit pwm_beeper_remove(struct platform_device *pdev)
++static int pwm_beeper_remove(struct platform_device *pdev)
+ {
+ 	struct pwm_beeper *beeper = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/misc/rb532_button.c b/drivers/input/misc/rb532_button.c
+index 91f71d6be57b..fb4f8ac3343b 100644
+--- a/drivers/input/misc/rb532_button.c
++++ b/drivers/input/misc/rb532_button.c
+@@ -81,7 +81,7 @@ static int rb532_button_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit rb532_button_remove(struct platform_device *pdev)
++static int rb532_button_remove(struct platform_device *pdev)
+ {
+ 	struct input_polled_dev *poll_dev = dev_get_drvdata(&pdev->dev);
+ 
+diff --git a/drivers/input/misc/retu-pwrbutton.c b/drivers/input/misc/retu-pwrbutton.c
+index 389e84e26a9a..7ca09baa0016 100644
+--- a/drivers/input/misc/retu-pwrbutton.c
++++ b/drivers/input/misc/retu-pwrbutton.c
+@@ -76,7 +76,7 @@ static int retu_pwrbutton_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit retu_pwrbutton_remove(struct platform_device *pdev)
++static int retu_pwrbutton_remove(struct platform_device *pdev)
+ {
+ 	return 0;
+ }
+diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c
+index cd3c363f7e2b..aff47b2c38ff 100644
+--- a/drivers/input/misc/rotary_encoder.c
++++ b/drivers/input/misc/rotary_encoder.c
+@@ -301,7 +301,7 @@ static int rotary_encoder_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit rotary_encoder_remove(struct platform_device *pdev)
++static int rotary_encoder_remove(struct platform_device *pdev)
+ {
+ 	struct rotary_encoder *encoder = platform_get_drvdata(pdev);
+ 	const struct rotary_encoder_platform_data *pdata = encoder->pdata;
+diff --git a/drivers/input/misc/sgi_btns.c b/drivers/input/misc/sgi_btns.c
+index 22ccd3f35607..ad6415ceaf5f 100644
+--- a/drivers/input/misc/sgi_btns.c
++++ b/drivers/input/misc/sgi_btns.c
+@@ -143,7 +143,7 @@ static int sgi_buttons_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit sgi_buttons_remove(struct platform_device *pdev)
++static int sgi_buttons_remove(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	struct buttons_dev *bdev = dev_get_drvdata(dev);
+diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c
+index d0239b496399..a53586a7fbdb 100644
+--- a/drivers/input/misc/sparcspkr.c
++++ b/drivers/input/misc/sparcspkr.c
+@@ -229,7 +229,7 @@ static int bbc_beep_probe(struct platform_device *op)
+ 	return err;
+ }
+ 
+-static int __devexit bbc_remove(struct platform_device *op)
++static int bbc_remove(struct platform_device *op)
+ {
+ 	struct sparcspkr_state *state = dev_get_drvdata(&op->dev);
+ 	struct input_dev *input_dev = state->input_dev;
+@@ -310,7 +310,7 @@ static int grover_beep_probe(struct platform_device *op)
+ 	return err;
+ }
+ 
+-static int __devexit grover_remove(struct platform_device *op)
++static int grover_remove(struct platform_device *op)
+ {
+ 	struct sparcspkr_state *state = dev_get_drvdata(&op->dev);
+ 	struct grover_beep_info *info = &state->u.grover;
+diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c
+index 21030266bb3f..78eb6b30580a 100644
+--- a/drivers/input/misc/twl4030-vibra.c
++++ b/drivers/input/misc/twl4030-vibra.c
+@@ -269,7 +269,7 @@ static int twl4030_vibra_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit twl4030_vibra_remove(struct platform_device *pdev)
++static int twl4030_vibra_remove(struct platform_device *pdev)
+ {
+ 	struct vibra_info *info = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c
+index 4b650e43fdd9..71a28ee699f3 100644
+--- a/drivers/input/misc/twl6040-vibra.c
++++ b/drivers/input/misc/twl6040-vibra.c
+@@ -418,7 +418,7 @@ static int twl6040_vibra_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit twl6040_vibra_remove(struct platform_device *pdev)
++static int twl6040_vibra_remove(struct platform_device *pdev)
+ {
+ 	struct vibra_info *info = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
+index 46d79c516854..56536f4b9572 100644
+--- a/drivers/input/misc/wistron_btns.c
++++ b/drivers/input/misc/wistron_btns.c
+@@ -1077,7 +1077,7 @@ static void wistron_led_init(struct device *parent)
+ 	}
+ }
+ 
+-static void __devexit wistron_led_remove(void)
++static void wistron_led_remove(void)
+ {
+ 	if (leds_present & FE_MAIL_LED)
+ 		led_classdev_unregister(&wistron_mail_led);
+@@ -1277,7 +1277,7 @@ static int wistron_probe(struct platform_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devexit wistron_remove(struct platform_device *dev)
++static int wistron_remove(struct platform_device *dev)
+ {
+ 	wistron_led_remove();
+ 	input_unregister_polled_device(wistron_idev);
+diff --git a/drivers/input/misc/wm831x-on.c b/drivers/input/misc/wm831x-on.c
+index de7751e1b13c..558767d8ebf4 100644
+--- a/drivers/input/misc/wm831x-on.c
++++ b/drivers/input/misc/wm831x-on.c
+@@ -124,7 +124,7 @@ static int wm831x_on_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit wm831x_on_remove(struct platform_device *pdev)
++static int wm831x_on_remove(struct platform_device *pdev)
+ {
+ 	struct wm831x_on *wm831x_on = platform_get_drvdata(pdev);
+ 	int irq = platform_get_irq(pdev, 0);
+diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c
+index 8e1fe82e16b7..532eaca4cc56 100644
+--- a/drivers/input/mouse/gpio_mouse.c
++++ b/drivers/input/mouse/gpio_mouse.c
+@@ -150,7 +150,7 @@ static int gpio_mouse_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit gpio_mouse_remove(struct platform_device *pdev)
++static int gpio_mouse_remove(struct platform_device *pdev)
+ {
+ 	struct input_polled_dev *input = platform_get_drvdata(pdev);
+ 	struct gpio_mouse_platform_data *pdata = input->private;
+diff --git a/drivers/input/mouse/maplemouse.c b/drivers/input/mouse/maplemouse.c
+index 3541f362866b..0a60717b91c6 100644
+--- a/drivers/input/mouse/maplemouse.c
++++ b/drivers/input/mouse/maplemouse.c
+@@ -114,7 +114,7 @@ static int probe_maple_mouse(struct device *dev)
+ 	return error;
+ }
+ 
+-static int __devexit remove_maple_mouse(struct device *dev)
++static int remove_maple_mouse(struct device *dev)
+ {
+ 	struct maple_device *mdev = to_maple_dev(dev);
+ 	struct dc_mouse *mse = maple_get_drvdata(mdev);
+diff --git a/drivers/input/mouse/navpoint.c b/drivers/input/mouse/navpoint.c
+index f51df6bfc52b..8e1b98ea5648 100644
+--- a/drivers/input/mouse/navpoint.c
++++ b/drivers/input/mouse/navpoint.c
+@@ -299,7 +299,7 @@ static int navpoint_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit navpoint_remove(struct platform_device *pdev)
++static int navpoint_remove(struct platform_device *pdev)
+ {
+ 	const struct navpoint_platform_data *pdata =
+ 					dev_get_platdata(&pdev->dev);
+diff --git a/drivers/input/mouse/pxa930_trkball.c b/drivers/input/mouse/pxa930_trkball.c
+index ed808fce0ac0..0ecb9e7945eb 100644
+--- a/drivers/input/mouse/pxa930_trkball.c
++++ b/drivers/input/mouse/pxa930_trkball.c
+@@ -230,7 +230,7 @@ static int pxa930_trkball_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit pxa930_trkball_remove(struct platform_device *pdev)
++static int pxa930_trkball_remove(struct platform_device *pdev)
+ {
+ 	struct pxa930_trkball *trkball = platform_get_drvdata(pdev);
+ 	int irq = platform_get_irq(pdev, 0);
+diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c
+index 007c378bd694..ad822608f6ee 100644
+--- a/drivers/input/mouse/synaptics_i2c.c
++++ b/drivers/input/mouse/synaptics_i2c.c
+@@ -601,7 +601,7 @@ static int synaptics_i2c_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit synaptics_i2c_remove(struct i2c_client *client)
++static int synaptics_i2c_remove(struct i2c_client *client)
+ {
+ 	struct synaptics_i2c *touch = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/serio/altera_ps2.c b/drivers/input/serio/altera_ps2.c
+index ea46ddcf2ed5..479ce5fe8955 100644
+--- a/drivers/input/serio/altera_ps2.c
++++ b/drivers/input/serio/altera_ps2.c
+@@ -159,7 +159,7 @@ static int altera_ps2_probe(struct platform_device *pdev)
+ /*
+  * Remove one device from this driver.
+  */
+-static int __devexit altera_ps2_remove(struct platform_device *pdev)
++static int altera_ps2_remove(struct platform_device *pdev)
+ {
+ 	struct ps2if *ps2if = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c
+index 7c502c391bbc..4e2fd44865e1 100644
+--- a/drivers/input/serio/ambakmi.c
++++ b/drivers/input/serio/ambakmi.c
+@@ -163,7 +163,7 @@ static int amba_kmi_probe(struct amba_device *dev,
+ 	return ret;
+ }
+ 
+-static int __devexit amba_kmi_remove(struct amba_device *dev)
++static int amba_kmi_remove(struct amba_device *dev)
+ {
+ 	struct amba_kmi_port *kmi = amba_get_drvdata(dev);
+ 
+diff --git a/drivers/input/serio/arc_ps2.c b/drivers/input/serio/arc_ps2.c
+index e618c2a825aa..b571eb3e4efc 100644
+--- a/drivers/input/serio/arc_ps2.c
++++ b/drivers/input/serio/arc_ps2.c
+@@ -242,7 +242,7 @@ static int arc_ps2_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit arc_ps2_remove(struct platform_device *pdev)
++static int arc_ps2_remove(struct platform_device *pdev)
+ {
+ 	struct arc_ps2_data *arc_ps2 = platform_get_drvdata(pdev);
+ 	int i;
+diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c
+index e8a8748bae6f..cfe549d4eaa5 100644
+--- a/drivers/input/serio/ct82c710.c
++++ b/drivers/input/serio/ct82c710.c
+@@ -199,7 +199,7 @@ static int ct82c710_probe(struct platform_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devexit ct82c710_remove(struct platform_device *dev)
++static int ct82c710_remove(struct platform_device *dev)
+ {
+ 	serio_unregister_port(ct82c710_port);
+ 
+diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c
+index a36a4667ddae..8d9ba0c3827c 100644
+--- a/drivers/input/serio/gscps2.c
++++ b/drivers/input/serio/gscps2.c
+@@ -414,7 +414,7 @@ static int gscps2_probe(struct parisc_device *dev)
+  * @return: success/error report
+  */
+ 
+-static int __devexit gscps2_remove(struct parisc_device *dev)
++static int gscps2_remove(struct parisc_device *dev)
+ {
+ 	struct gscps2port *ps2port = dev_get_drvdata(&dev->dev);
+ 
+diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h
+index c11748575786..d6aa4c67dbb6 100644
+--- a/drivers/input/serio/i8042-sparcio.h
++++ b/drivers/input/serio/i8042-sparcio.h
+@@ -80,7 +80,7 @@ static int sparc_i8042_probe(struct platform_device *op)
+ 	return 0;
+ }
+ 
+-static int __devexit sparc_i8042_remove(struct platform_device *op)
++static int sparc_i8042_remove(struct platform_device *op)
+ {
+ 	of_iounmap(kbd_res, kbd_iobase, 8);
+ 
+diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
+index 2539195729bd..78e4de42efaa 100644
+--- a/drivers/input/serio/i8042.c
++++ b/drivers/input/serio/i8042.c
+@@ -1284,7 +1284,7 @@ static void __init i8042_register_ports(void)
+ 	}
+ }
+ 
+-static void __devexit i8042_unregister_ports(void)
++static void i8042_unregister_ports(void)
+ {
+ 	int i;
+ 
+@@ -1437,7 +1437,7 @@ static int __init i8042_probe(struct platform_device *dev)
+ 	return error;
+ }
+ 
+-static int __devexit i8042_remove(struct platform_device *dev)
++static int i8042_remove(struct platform_device *dev)
+ {
+ 	i8042_unregister_ports();
+ 	i8042_free_irqs();
+diff --git a/drivers/input/serio/maceps2.c b/drivers/input/serio/maceps2.c
+index 057240e3a74a..bc85e1cc66d8 100644
+--- a/drivers/input/serio/maceps2.c
++++ b/drivers/input/serio/maceps2.c
+@@ -151,7 +151,7 @@ static int maceps2_probe(struct platform_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devexit maceps2_remove(struct platform_device *dev)
++static int maceps2_remove(struct platform_device *dev)
+ {
+ 	serio_unregister_port(maceps2_port[0]);
+ 	serio_unregister_port(maceps2_port[1]);
+diff --git a/drivers/input/serio/pcips2.c b/drivers/input/serio/pcips2.c
+index 1914290674ef..76f83836fd5a 100644
+--- a/drivers/input/serio/pcips2.c
++++ b/drivers/input/serio/pcips2.c
+@@ -176,7 +176,7 @@ static int pcips2_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ 	return ret;
+ }
+ 
+-static void __devexit pcips2_remove(struct pci_dev *dev)
++static void pcips2_remove(struct pci_dev *dev)
+ {
+ 	struct pcips2_data *ps2if = pci_get_drvdata(dev);
+ 
+diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c
+index 3c58f6b2fe54..70fe542839fb 100644
+--- a/drivers/input/serio/q40kbd.c
++++ b/drivers/input/serio/q40kbd.c
+@@ -168,7 +168,7 @@ static int q40kbd_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit q40kbd_remove(struct platform_device *pdev)
++static int q40kbd_remove(struct platform_device *pdev)
+ {
+ 	struct q40kbd *q40kbd = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c
+index d64f053ae3ee..567566ae0dae 100644
+--- a/drivers/input/serio/rpckbd.c
++++ b/drivers/input/serio/rpckbd.c
+@@ -153,7 +153,7 @@ static int rpckbd_probe(struct platform_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devexit rpckbd_remove(struct platform_device *dev)
++static int rpckbd_remove(struct platform_device *dev)
+ {
+ 	struct serio *serio = platform_get_drvdata(dev);
+ 	struct rpckbd_data *rpckbd = serio->port_data;
+diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
+index 4458ec3b1d2a..b3e688911fd9 100644
+--- a/drivers/input/serio/sa1111ps2.c
++++ b/drivers/input/serio/sa1111ps2.c
+@@ -334,7 +334,7 @@ static int ps2_probe(struct sa1111_dev *dev)
+ /*
+  * Remove one device from this driver.
+  */
+-static int __devexit ps2_remove(struct sa1111_dev *dev)
++static int ps2_remove(struct sa1111_dev *dev)
+ {
+ 	struct ps2if *ps2if = sa1111_get_drvdata(dev);
+ 
+diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c
+index ed5e8e625bff..17be85948ffd 100644
+--- a/drivers/input/serio/xilinx_ps2.c
++++ b/drivers/input/serio/xilinx_ps2.c
+@@ -333,7 +333,7 @@ static int xps2_of_probe(struct platform_device *ofdev)
+  * if the driver module is being unloaded. It frees any resources allocated to
+  * the device.
+  */
+-static int __devexit xps2_of_remove(struct platform_device *of_dev)
++static int xps2_of_remove(struct platform_device *of_dev)
+ {
+ 	struct xps2data *drvdata = platform_get_drvdata(of_dev);
+ 	struct resource r_mem; /* IO mem resources */
+diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c
+index 183d35b9d07a..c7068942ebe8 100644
+--- a/drivers/input/touchscreen/88pm860x-ts.c
++++ b/drivers/input/touchscreen/88pm860x-ts.c
+@@ -293,7 +293,7 @@ static int pm860x_touch_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit pm860x_touch_remove(struct platform_device *pdev)
++static int pm860x_touch_remove(struct platform_device *pdev)
+ {
+ 	struct pm860x_touch *touch = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c
+index 61c0a98d6dd7..23fa829b869d 100644
+--- a/drivers/input/touchscreen/ad7877.c
++++ b/drivers/input/touchscreen/ad7877.c
+@@ -810,7 +810,7 @@ static int ad7877_probe(struct spi_device *spi)
+ 	return err;
+ }
+ 
+-static int __devexit ad7877_remove(struct spi_device *spi)
++static int ad7877_remove(struct spi_device *spi)
+ {
+ 	struct ad7877 *ts = dev_get_drvdata(&spi->dev);
+ 
+diff --git a/drivers/input/touchscreen/ad7879-i2c.c b/drivers/input/touchscreen/ad7879-i2c.c
+index b155770c521d..dcf390771549 100644
+--- a/drivers/input/touchscreen/ad7879-i2c.c
++++ b/drivers/input/touchscreen/ad7879-i2c.c
+@@ -75,7 +75,7 @@ static int ad7879_i2c_probe(struct i2c_client *client,
+ 	return 0;
+ }
+ 
+-static int __devexit ad7879_i2c_remove(struct i2c_client *client)
++static int ad7879_i2c_remove(struct i2c_client *client)
+ {
+ 	struct ad7879 *ts = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/touchscreen/ad7879-spi.c b/drivers/input/touchscreen/ad7879-spi.c
+index c9b73e0b6528..606da5bd6115 100644
+--- a/drivers/input/touchscreen/ad7879-spi.c
++++ b/drivers/input/touchscreen/ad7879-spi.c
+@@ -137,7 +137,7 @@ static int ad7879_spi_probe(struct spi_device *spi)
+ 	return 0;
+ }
+ 
+-static int __devexit ad7879_spi_remove(struct spi_device *spi)
++static int ad7879_spi_remove(struct spi_device *spi)
+ {
+ 	struct ad7879 *ts = spi_get_drvdata(spi);
+ 
+diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
+index 156a36b43bff..4f702b3ec1a3 100644
+--- a/drivers/input/touchscreen/ads7846.c
++++ b/drivers/input/touchscreen/ads7846.c
+@@ -1390,7 +1390,7 @@ static int ads7846_probe(struct spi_device *spi)
+ 	return err;
+ }
+ 
+-static int __devexit ads7846_remove(struct spi_device *spi)
++static int ads7846_remove(struct spi_device *spi)
+ {
+ 	struct ads7846 *ts = dev_get_drvdata(&spi->dev);
+ 
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index cd961bcf9f0e..d04f810cb1dd 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -1200,7 +1200,7 @@ static int mxt_probe(struct i2c_client *client,
+ 	return error;
+ }
+ 
+-static int __devexit mxt_remove(struct i2c_client *client)
++static int mxt_remove(struct i2c_client *client)
+ {
+ 	struct mxt_data *data = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c
+index 4b4f5ab76e5c..55092d1c5cb9 100644
+--- a/drivers/input/touchscreen/atmel_tsadcc.c
++++ b/drivers/input/touchscreen/atmel_tsadcc.c
+@@ -323,7 +323,7 @@ static int atmel_tsadcc_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit atmel_tsadcc_remove(struct platform_device *pdev)
++static int atmel_tsadcc_remove(struct platform_device *pdev)
+ {
+ 	struct atmel_tsadcc *ts_dev = dev_get_drvdata(&pdev->dev);
+ 	struct resource *res;
+diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c
+index cdd233f3ed8e..c6e19a96348e 100644
+--- a/drivers/input/touchscreen/auo-pixcir-ts.c
++++ b/drivers/input/touchscreen/auo-pixcir-ts.c
+@@ -599,7 +599,7 @@ static int auo_pixcir_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit auo_pixcir_remove(struct i2c_client *client)
++static int auo_pixcir_remove(struct i2c_client *client)
+ {
+ 	struct auo_pixcir_ts *ts = i2c_get_clientdata(client);
+ 	const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data;
+diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c
+index bf90391aae59..59a8ce86fcda 100644
+--- a/drivers/input/touchscreen/bu21013_ts.c
++++ b/drivers/input/touchscreen/bu21013_ts.c
+@@ -549,7 +549,7 @@ static int bu21013_probe(struct i2c_client *client,
+  * This function uses to remove the i2c-client
+  * touchscreen driver and returns integer.
+  */
+-static int __devexit bu21013_remove(struct i2c_client *client)
++static int bu21013_remove(struct i2c_client *client)
+ {
+ 	struct bu21013_ts_data *bu21013_data = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c
+index 0aaa24ec6f51..96e0eedcc7e5 100644
+--- a/drivers/input/touchscreen/cy8ctmg110_ts.c
++++ b/drivers/input/touchscreen/cy8ctmg110_ts.c
+@@ -323,7 +323,7 @@ static int cy8ctmg110_resume(struct device *dev)
+ static SIMPLE_DEV_PM_OPS(cy8ctmg110_pm, cy8ctmg110_suspend, cy8ctmg110_resume);
+ #endif
+ 
+-static int __devexit cy8ctmg110_remove(struct i2c_client *client)
++static int cy8ctmg110_remove(struct i2c_client *client)
+ {
+ 	struct cy8ctmg110 *ts = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c
+index 167e9834e597..4dbdf44b8fc5 100644
+--- a/drivers/input/touchscreen/cyttsp_i2c.c
++++ b/drivers/input/touchscreen/cyttsp_i2c.c
+@@ -102,7 +102,7 @@ static int cyttsp_i2c_probe(struct i2c_client *client,
+ 	return 0;
+ }
+ 
+-static int __devexit cyttsp_i2c_remove(struct i2c_client *client)
++static int cyttsp_i2c_remove(struct i2c_client *client)
+ {
+ 	struct cyttsp *ts = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/touchscreen/cyttsp_spi.c b/drivers/input/touchscreen/cyttsp_spi.c
+index 8ea29d9ae3bc..638e20310f12 100644
+--- a/drivers/input/touchscreen/cyttsp_spi.c
++++ b/drivers/input/touchscreen/cyttsp_spi.c
+@@ -172,7 +172,7 @@ static int cyttsp_spi_probe(struct spi_device *spi)
+ 	return 0;
+ }
+ 
+-static int __devexit cyttsp_spi_remove(struct spi_device *spi)
++static int cyttsp_spi_remove(struct spi_device *spi)
+ {
+ 	struct cyttsp *ts = spi_get_drvdata(spi);
+ 
+diff --git a/drivers/input/touchscreen/da9034-ts.c b/drivers/input/touchscreen/da9034-ts.c
+index 53a95244a14c..34ad84105e6e 100644
+--- a/drivers/input/touchscreen/da9034-ts.c
++++ b/drivers/input/touchscreen/da9034-ts.c
+@@ -361,7 +361,7 @@ static int da9034_touch_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit da9034_touch_remove(struct platform_device *pdev)
++static int da9034_touch_remove(struct platform_device *pdev)
+ {
+ 	struct da9034_touch *touch = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/touchscreen/da9052_tsi.c b/drivers/input/touchscreen/da9052_tsi.c
+index 8a493b962db3..303966ffe1e8 100644
+--- a/drivers/input/touchscreen/da9052_tsi.c
++++ b/drivers/input/touchscreen/da9052_tsi.c
+@@ -336,7 +336,7 @@ static int da9052_ts_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int  __devexit da9052_ts_remove(struct platform_device *pdev)
++static int  da9052_ts_remove(struct platform_device *pdev)
+ {
+ 	struct da9052_tsi *tsi = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
+index 677e78804b79..a9170157b442 100644
+--- a/drivers/input/touchscreen/edt-ft5x06.c
++++ b/drivers/input/touchscreen/edt-ft5x06.c
+@@ -592,7 +592,7 @@ edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata,
+ 			    tsdata->debug_dir, tsdata, &debugfs_raw_data_fops);
+ }
+ 
+-static void __devexit
++static void
+ edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
+ {
+ 	if (tsdata->debug_dir)
+@@ -822,7 +822,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
+ 	return error;
+ }
+ 
+-static int __devexit edt_ft5x06_ts_remove(struct i2c_client *client)
++static int edt_ft5x06_ts_remove(struct i2c_client *client)
+ {
+ 	const struct edt_ft5x06_platform_data *pdata =
+ 						dev_get_platdata(&client->dev);
+diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c
+index a65709959fa0..55255a940072 100644
+--- a/drivers/input/touchscreen/eeti_ts.c
++++ b/drivers/input/touchscreen/eeti_ts.c
+@@ -248,7 +248,7 @@ static int eeti_ts_probe(struct i2c_client *client,
+ 	return err;
+ }
+ 
+-static int __devexit eeti_ts_remove(struct i2c_client *client)
++static int eeti_ts_remove(struct i2c_client *client)
+ {
+ 	struct eeti_ts_priv *priv = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c
+index f5e09ca1ffed..17c9097f3b5d 100644
+--- a/drivers/input/touchscreen/egalax_ts.c
++++ b/drivers/input/touchscreen/egalax_ts.c
+@@ -246,7 +246,7 @@ static int egalax_ts_probe(struct i2c_client *client,
+ 	return error;
+ }
+ 
+-static __devexit int egalax_ts_remove(struct i2c_client *client)
++static int egalax_ts_remove(struct i2c_client *client)
+ {
+ 	struct egalax_ts *ts = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/touchscreen/htcpen.c b/drivers/input/touchscreen/htcpen.c
+index 32a451c89d53..6c4fb8436957 100644
+--- a/drivers/input/touchscreen/htcpen.c
++++ b/drivers/input/touchscreen/htcpen.c
+@@ -174,7 +174,7 @@ static int htcpen_isa_probe(struct device *dev, unsigned int id)
+ 	return err;
+ }
+ 
+-static int __devexit htcpen_isa_remove(struct device *dev, unsigned int id)
++static int htcpen_isa_remove(struct device *dev, unsigned int id)
+ {
+ 	struct input_dev *htcpen_dev = dev_get_drvdata(dev);
+ 
+diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c
+index 7e6221c9ea7d..1418bdda61bb 100644
+--- a/drivers/input/touchscreen/ili210x.c
++++ b/drivers/input/touchscreen/ili210x.c
+@@ -298,7 +298,7 @@ static int ili210x_i2c_probe(struct i2c_client *client,
+ 	return error;
+ }
+ 
+-static int __devexit ili210x_i2c_remove(struct i2c_client *client)
++static int ili210x_i2c_remove(struct i2c_client *client)
+ {
+ 	struct ili210x *priv = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/touchscreen/intel-mid-touch.c b/drivers/input/touchscreen/intel-mid-touch.c
+index e413f3344edd..465db5dba8b4 100644
+--- a/drivers/input/touchscreen/intel-mid-touch.c
++++ b/drivers/input/touchscreen/intel-mid-touch.c
+@@ -643,7 +643,7 @@ static int mrstouch_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit mrstouch_remove(struct platform_device *pdev)
++static int mrstouch_remove(struct platform_device *pdev)
+ {
+ 	struct mrstouch_dev *tsdev = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/touchscreen/jornada720_ts.c b/drivers/input/touchscreen/jornada720_ts.c
+index 7ef90def6b0b..282d7c7ad2fc 100644
+--- a/drivers/input/touchscreen/jornada720_ts.c
++++ b/drivers/input/touchscreen/jornada720_ts.c
+@@ -151,7 +151,7 @@ static int jornada720_ts_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit jornada720_ts_remove(struct platform_device *pdev)
++static int jornada720_ts_remove(struct platform_device *pdev)
+ {
+ 	struct jornada_ts *jornada_ts = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/touchscreen/lpc32xx_ts.c b/drivers/input/touchscreen/lpc32xx_ts.c
+index 39d50b7d470a..9101ee529c92 100644
+--- a/drivers/input/touchscreen/lpc32xx_ts.c
++++ b/drivers/input/touchscreen/lpc32xx_ts.c
+@@ -309,7 +309,7 @@ static int lpc32xx_ts_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit lpc32xx_ts_remove(struct platform_device *pdev)
++static int lpc32xx_ts_remove(struct platform_device *pdev)
+ {
+ 	struct lpc32xx_tsc *tsc = platform_get_drvdata(pdev);
+ 	struct resource *res;
+diff --git a/drivers/input/touchscreen/max11801_ts.c b/drivers/input/touchscreen/max11801_ts.c
+index ac06db6a7b05..00bc6caa27f5 100644
+--- a/drivers/input/touchscreen/max11801_ts.c
++++ b/drivers/input/touchscreen/max11801_ts.c
+@@ -228,7 +228,7 @@ static int max11801_ts_probe(struct i2c_client *client,
+ 	return error;
+ }
+ 
+-static __devexit int max11801_ts_remove(struct i2c_client *client)
++static int max11801_ts_remove(struct i2c_client *client)
+ {
+ 	struct max11801_data *data = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c
+index 5c18c5cb9f7a..02103b6abb39 100644
+--- a/drivers/input/touchscreen/mc13783_ts.c
++++ b/drivers/input/touchscreen/mc13783_ts.c
+@@ -229,7 +229,7 @@ static int __init mc13783_ts_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit mc13783_ts_remove(struct platform_device *pdev)
++static int mc13783_ts_remove(struct platform_device *pdev)
+ {
+ 	struct mc13783_ts_priv *priv = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c
+index c9da87bd2570..f9f4e0c56eda 100644
+--- a/drivers/input/touchscreen/mcs5000_ts.c
++++ b/drivers/input/touchscreen/mcs5000_ts.c
+@@ -249,7 +249,7 @@ static int mcs5000_ts_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit mcs5000_ts_remove(struct i2c_client *client)
++static int mcs5000_ts_remove(struct i2c_client *client)
+ {
+ 	struct mcs5000_ts_data *data = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
+index 633737e14e47..98841d8aa635 100644
+--- a/drivers/input/touchscreen/mms114.c
++++ b/drivers/input/touchscreen/mms114.c
+@@ -508,7 +508,7 @@ static int mms114_probe(struct i2c_client *client,
+ 	return error;
+ }
+ 
+-static int __devexit mms114_remove(struct i2c_client *client)
++static int mms114_remove(struct i2c_client *client)
+ {
+ 	struct mms114_data *data = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/touchscreen/pcap_ts.c b/drivers/input/touchscreen/pcap_ts.c
+index 900dc78be08d..f22e04dd4e16 100644
+--- a/drivers/input/touchscreen/pcap_ts.c
++++ b/drivers/input/touchscreen/pcap_ts.c
+@@ -202,7 +202,7 @@ static int pcap_ts_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit pcap_ts_remove(struct platform_device *pdev)
++static int pcap_ts_remove(struct platform_device *pdev)
+ {
+ 	struct pcap_ts *pcap_ts = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
+index cffea4c368ad..6cc6b36663ff 100644
+--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
++++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
+@@ -189,7 +189,7 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
+ 	return error;
+ }
+ 
+-static int __devexit pixcir_i2c_ts_remove(struct i2c_client *client)
++static int pixcir_i2c_ts_remove(struct i2c_client *client)
+ {
+ 	struct pixcir_i2c_ts_data *tsdata = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c
+index 8f2f22b612a0..b061af2c8376 100644
+--- a/drivers/input/touchscreen/s3c2410_ts.c
++++ b/drivers/input/touchscreen/s3c2410_ts.c
+@@ -365,7 +365,7 @@ static int s3c2410ts_probe(struct platform_device *pdev)
+  *
+  * Free up our state ready to be removed.
+  */
+-static int __devexit s3c2410ts_remove(struct platform_device *pdev)
++static int s3c2410ts_remove(struct platform_device *pdev)
+ {
+ 	free_irq(ts.irq_tc, ts.input);
+ 	del_timer_sync(&touch_timer);
+diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c
+index 2a71dfde301c..d9d05e222428 100644
+--- a/drivers/input/touchscreen/st1232.c
++++ b/drivers/input/touchscreen/st1232.c
+@@ -206,7 +206,7 @@ static int st1232_ts_probe(struct i2c_client *client,
+ 	return error;
+ }
+ 
+-static int __devexit st1232_ts_remove(struct i2c_client *client)
++static int st1232_ts_remove(struct i2c_client *client)
+ {
+ 	struct st1232_ts_data *ts = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c
+index 011b686798dc..84d884b4ec3e 100644
+--- a/drivers/input/touchscreen/stmpe-ts.c
++++ b/drivers/input/touchscreen/stmpe-ts.c
+@@ -371,7 +371,7 @@ static int stmpe_input_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit stmpe_ts_remove(struct platform_device *pdev)
++static int stmpe_ts_remove(struct platform_device *pdev)
+ {
+ 	struct stmpe_touch *ts = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/touchscreen/tnetv107x-ts.c b/drivers/input/touchscreen/tnetv107x-ts.c
+index 63f75ebb3281..acfb87607b87 100644
+--- a/drivers/input/touchscreen/tnetv107x-ts.c
++++ b/drivers/input/touchscreen/tnetv107x-ts.c
+@@ -357,7 +357,7 @@ static int tsc_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit tsc_remove(struct platform_device *pdev)
++static int tsc_remove(struct platform_device *pdev)
+ {
+ 	struct tsc_data *ts = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/input/touchscreen/tps6507x-ts.c b/drivers/input/touchscreen/tps6507x-ts.c
+index e1ec9e074ed3..820a066c3b8a 100644
+--- a/drivers/input/touchscreen/tps6507x-ts.c
++++ b/drivers/input/touchscreen/tps6507x-ts.c
+@@ -345,7 +345,7 @@ static int tps6507x_ts_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit tps6507x_ts_remove(struct platform_device *pdev)
++static int tps6507x_ts_remove(struct platform_device *pdev)
+ {
+ 	struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev);
+ 	struct tps6507x_ts *tsc = tps6507x_dev->ts;
+diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c
+index 20889305d46c..9c0cdc7ea449 100644
+--- a/drivers/input/touchscreen/tsc2005.c
++++ b/drivers/input/touchscreen/tsc2005.c
+@@ -686,7 +686,7 @@ static int tsc2005_probe(struct spi_device *spi)
+ 	return error;
+ }
+ 
+-static int __devexit tsc2005_remove(struct spi_device *spi)
++static int tsc2005_remove(struct spi_device *spi)
+ {
+ 	struct tsc2005 *ts = spi_get_drvdata(spi);
+ 
+diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c
+index 47b41eb0e38f..0b67ba476b4c 100644
+--- a/drivers/input/touchscreen/tsc2007.c
++++ b/drivers/input/touchscreen/tsc2007.c
+@@ -366,7 +366,7 @@ static int tsc2007_probe(struct i2c_client *client,
+ 	return err;
+ }
+ 
+-static int __devexit tsc2007_remove(struct i2c_client *client)
++static int tsc2007_remove(struct i2c_client *client)
+ {
+ 	struct tsc2007	*ts = i2c_get_clientdata(client);
+ 	struct tsc2007_platform_data *pdata = client->dev.platform_data;
+diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
+index 518363d01c2f..1271f97b4079 100644
+--- a/drivers/input/touchscreen/ucb1400_ts.c
++++ b/drivers/input/touchscreen/ucb1400_ts.c
+@@ -397,7 +397,7 @@ static int ucb1400_ts_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit ucb1400_ts_remove(struct platform_device *pdev)
++static int ucb1400_ts_remove(struct platform_device *pdev)
+ {
+ 	struct ucb1400_ts *ucb = pdev->dev.platform_data;
+ 
+diff --git a/drivers/input/touchscreen/w90p910_ts.c b/drivers/input/touchscreen/w90p910_ts.c
+index f0378a9dc93e..d2ef8f05c66e 100644
+--- a/drivers/input/touchscreen/w90p910_ts.c
++++ b/drivers/input/touchscreen/w90p910_ts.c
+@@ -301,7 +301,7 @@ fail1:	input_free_device(input_dev);
+ 	return err;
+ }
+ 
+-static int __devexit w90x900ts_remove(struct platform_device *pdev)
++static int w90x900ts_remove(struct platform_device *pdev)
+ {
+ 	struct w90p910_ts *w90p910_ts = platform_get_drvdata(pdev);
+ 	struct resource *res;
+diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c
+index bb02ccd51008..bf0d07620bac 100644
+--- a/drivers/input/touchscreen/wacom_i2c.c
++++ b/drivers/input/touchscreen/wacom_i2c.c
+@@ -225,7 +225,7 @@ static int wacom_i2c_probe(struct i2c_client *client,
+ 	return error;
+ }
+ 
+-static int __devexit wacom_i2c_remove(struct i2c_client *client)
++static int wacom_i2c_remove(struct i2c_client *client)
+ {
+ 	struct wacom_i2c *wac_i2c = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/input/touchscreen/wm831x-ts.c b/drivers/input/touchscreen/wm831x-ts.c
+index 28d81256ec69..f88fab56178c 100644
+--- a/drivers/input/touchscreen/wm831x-ts.c
++++ b/drivers/input/touchscreen/wm831x-ts.c
+@@ -381,7 +381,7 @@ static int wm831x_ts_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static __devexit int wm831x_ts_remove(struct platform_device *pdev)
++static int wm831x_ts_remove(struct platform_device *pdev)
+ {
+ 	struct wm831x_ts *wm831x_ts = platform_get_drvdata(pdev);
+ 

commit 5298cc4cc753bbe4c530b41341834f6ef3344d0d
+Author: Bill Pemberton 
+Date:   Fri Nov 23 21:38:25 2012 -0800
+
+    Input: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Mark Brown 
+    Acked-by: Javier Martinez Canillas 
+    Signed-off-by: Dmitry Torokhov 
+
+diff --git a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c
+index c300089b5172..786fa316c65f 100644
+--- a/drivers/input/gameport/emu10k1-gp.c
++++ b/drivers/input/gameport/emu10k1-gp.c
+@@ -57,7 +57,7 @@ static const struct pci_device_id emu_tbl[] = {
+ 
+ MODULE_DEVICE_TABLE(pci, emu_tbl);
+ 
+-static int __devinit emu_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
++static int emu_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ 	struct emu *emu;
+ 	struct gameport *port;
+diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c
+index e3ab458bfb8a..b1705e17020f 100644
+--- a/drivers/input/gameport/fm801-gp.c
++++ b/drivers/input/gameport/fm801-gp.c
+@@ -78,7 +78,7 @@ static int fm801_gp_open(struct gameport *gameport, int mode)
+ 	return 0;
+ }
+ 
+-static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device_id *id)
++static int fm801_gp_probe(struct pci_dev *pci, const struct pci_device_id *id)
+ {
+ 	struct fm801_gp *gp;
+ 	struct gameport *port;
+diff --git a/drivers/input/joystick/as5011.c b/drivers/input/joystick/as5011.c
+index 94f332773aec..ad7673305d7d 100644
+--- a/drivers/input/joystick/as5011.c
++++ b/drivers/input/joystick/as5011.c
+@@ -157,7 +157,7 @@ static irqreturn_t as5011_axis_interrupt(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit as5011_configure_chip(struct as5011_device *as5011,
++static int as5011_configure_chip(struct as5011_device *as5011,
+ 				const struct as5011_platform_data *plat_dat)
+ {
+ 	struct i2c_client *client = as5011->i2c_client;
+@@ -225,8 +225,8 @@ static int __devinit as5011_configure_chip(struct as5011_device *as5011,
+ 	return 0;
+ }
+ 
+-static int __devinit as5011_probe(struct i2c_client *client,
+-				const struct i2c_device_id *id)
++static int as5011_probe(struct i2c_client *client,
++			 const struct i2c_device_id *id)
+ {
+ 	const struct as5011_platform_data *plat_data;
+ 	struct as5011_device *as5011;
+diff --git a/drivers/input/joystick/maplecontrol.c b/drivers/input/joystick/maplecontrol.c
+index c84345704258..5ff3cb4a6de3 100644
+--- a/drivers/input/joystick/maplecontrol.c
++++ b/drivers/input/joystick/maplecontrol.c
+@@ -78,7 +78,7 @@ static void dc_pad_close(struct input_dev *dev)
+ }
+ 
+ /* allow the controller to be used */
+-static int __devinit probe_maple_controller(struct device *dev)
++static int probe_maple_controller(struct device *dev)
+ {
+ 	static const short btn_bit[32] = {
+ 		BTN_C, BTN_B, BTN_A, BTN_START, -1, -1, -1, -1,
+diff --git a/drivers/input/keyboard/adp5520-keys.c b/drivers/input/keyboard/adp5520-keys.c
+index 46796b26ff31..64de9652398f 100644
+--- a/drivers/input/keyboard/adp5520-keys.c
++++ b/drivers/input/keyboard/adp5520-keys.c
+@@ -69,7 +69,7 @@ static int adp5520_keys_notifier(struct notifier_block *nb,
+ 	return 0;
+ }
+ 
+-static int __devinit adp5520_keys_probe(struct platform_device *pdev)
++static int adp5520_keys_probe(struct platform_device *pdev)
+ {
+ 	struct adp5520_keys_platform_data *pdata = pdev->dev.platform_data;
+ 	struct input_dev *input;
+diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c
+index 39c2a6d2c99f..a20fe70ffa83 100644
+--- a/drivers/input/keyboard/adp5588-keys.c
++++ b/drivers/input/keyboard/adp5588-keys.c
+@@ -145,7 +145,7 @@ static int adp5588_gpio_direction_output(struct gpio_chip *chip,
+ 	return ret;
+ }
+ 
+-static int __devinit adp5588_build_gpiomap(struct adp5588_kpad *kpad,
++static int adp5588_build_gpiomap(struct adp5588_kpad *kpad,
+ 				const struct adp5588_kpad_platform_data *pdata)
+ {
+ 	bool pin_used[ADP5588_MAXGPIO];
+@@ -170,7 +170,7 @@ static int __devinit adp5588_build_gpiomap(struct adp5588_kpad *kpad,
+ 	return n_unused;
+ }
+ 
+-static int __devinit adp5588_gpio_add(struct adp5588_kpad *kpad)
++static int adp5588_gpio_add(struct adp5588_kpad *kpad)
+ {
+ 	struct device *dev = &kpad->client->dev;
+ 	const struct adp5588_kpad_platform_data *pdata = dev->platform_data;
+@@ -319,7 +319,7 @@ static irqreturn_t adp5588_irq(int irq, void *handle)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit adp5588_setup(struct i2c_client *client)
++static int adp5588_setup(struct i2c_client *client)
+ {
+ 	const struct adp5588_kpad_platform_data *pdata = client->dev.platform_data;
+ 	const struct adp5588_gpio_platform_data *gpio_data = pdata->gpio_data;
+@@ -382,7 +382,7 @@ static int __devinit adp5588_setup(struct i2c_client *client)
+ 	return 0;
+ }
+ 
+-static void __devinit adp5588_report_switch_state(struct adp5588_kpad *kpad)
++static void adp5588_report_switch_state(struct adp5588_kpad *kpad)
+ {
+ 	int gpi_stat1 = adp5588_read(kpad->client, GPIO_DAT_STAT1);
+ 	int gpi_stat2 = adp5588_read(kpad->client, GPIO_DAT_STAT2);
+@@ -420,8 +420,8 @@ static void __devinit adp5588_report_switch_state(struct adp5588_kpad *kpad)
+ }
+ 
+ 
+-static int __devinit adp5588_probe(struct i2c_client *client,
+-					const struct i2c_device_id *id)
++static int adp5588_probe(struct i2c_client *client,
++			 const struct i2c_device_id *id)
+ {
+ 	struct adp5588_kpad *kpad;
+ 	const struct adp5588_kpad_platform_data *pdata = client->dev.platform_data;
+diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c
+index 6e0c2e3a6a8d..8f591da17deb 100644
+--- a/drivers/input/keyboard/adp5589-keys.c
++++ b/drivers/input/keyboard/adp5589-keys.c
+@@ -464,7 +464,7 @@ static int adp5589_gpio_direction_output(struct gpio_chip *chip,
+ 	return ret;
+ }
+ 
+-static int __devinit adp5589_build_gpiomap(struct adp5589_kpad *kpad,
++static int adp5589_build_gpiomap(struct adp5589_kpad *kpad,
+ 				const struct adp5589_kpad_platform_data *pdata)
+ {
+ 	bool pin_used[ADP5589_MAXGPIO];
+@@ -496,7 +496,7 @@ static int __devinit adp5589_build_gpiomap(struct adp5589_kpad *kpad,
+ 	return n_unused;
+ }
+ 
+-static int __devinit adp5589_gpio_add(struct adp5589_kpad *kpad)
++static int adp5589_gpio_add(struct adp5589_kpad *kpad)
+ {
+ 	struct device *dev = &kpad->client->dev;
+ 	const struct adp5589_kpad_platform_data *pdata = dev->platform_data;
+@@ -641,8 +641,7 @@ static irqreturn_t adp5589_irq(int irq, void *handle)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit adp5589_get_evcode(struct adp5589_kpad *kpad,
+-					unsigned short key)
++static int adp5589_get_evcode(struct adp5589_kpad *kpad, unsigned short key)
+ {
+ 	int i;
+ 
+@@ -655,7 +654,7 @@ static int __devinit adp5589_get_evcode(struct adp5589_kpad *kpad,
+ 	return -EINVAL;
+ }
+ 
+-static int __devinit adp5589_setup(struct adp5589_kpad *kpad)
++static int adp5589_setup(struct adp5589_kpad *kpad)
+ {
+ 	struct i2c_client *client = kpad->client;
+ 	const struct adp5589_kpad_platform_data *pdata =
+@@ -820,7 +819,7 @@ static int __devinit adp5589_setup(struct adp5589_kpad *kpad)
+ 	return 0;
+ }
+ 
+-static void __devinit adp5589_report_switch_state(struct adp5589_kpad *kpad)
++static void adp5589_report_switch_state(struct adp5589_kpad *kpad)
+ {
+ 	int gpi_stat_tmp, pin_loc;
+ 	int i;
+@@ -860,8 +859,8 @@ static void __devinit adp5589_report_switch_state(struct adp5589_kpad *kpad)
+ 	input_sync(kpad->input);
+ }
+ 
+-static int __devinit adp5589_probe(struct i2c_client *client,
+-				   const struct i2c_device_id *id)
++static int adp5589_probe(struct i2c_client *client,
++			 const struct i2c_device_id *id)
+ {
+ 	struct adp5589_kpad *kpad;
+ 	const struct adp5589_kpad_platform_data *pdata =
+diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c
+index 8a7909a87216..8f3c2b665382 100644
+--- a/drivers/input/keyboard/bf54x-keys.c
++++ b/drivers/input/keyboard/bf54x-keys.c
+@@ -177,7 +177,7 @@ static irqreturn_t bfin_kpad_isr(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit bfin_kpad_probe(struct platform_device *pdev)
++static int bfin_kpad_probe(struct platform_device *pdev)
+ {
+ 	struct bf54x_kpad *bf54x_kpad;
+ 	struct bfin_kpad_platform_data *pdata = pdev->dev.platform_data;
+diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c
+index bdf326155960..30c00082ed90 100644
+--- a/drivers/input/keyboard/ep93xx_keypad.c
++++ b/drivers/input/keyboard/ep93xx_keypad.c
+@@ -232,7 +232,7 @@ static int ep93xx_keypad_resume(struct device *dev)
+ static SIMPLE_DEV_PM_OPS(ep93xx_keypad_pm_ops,
+ 			 ep93xx_keypad_suspend, ep93xx_keypad_resume);
+ 
+-static int __devinit ep93xx_keypad_probe(struct platform_device *pdev)
++static int ep93xx_keypad_probe(struct platform_device *pdev)
+ {
+ 	struct ep93xx_keypad *keypad;
+ 	const struct matrix_keymap_data *keymap_data;
+diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
+index 96b5ac5998f1..c714c585c307 100644
+--- a/drivers/input/keyboard/gpio_keys.c
++++ b/drivers/input/keyboard/gpio_keys.c
+@@ -423,10 +423,10 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit gpio_keys_setup_key(struct platform_device *pdev,
+-					 struct input_dev *input,
+-					 struct gpio_button_data *bdata,
+-					 const struct gpio_keys_button *button)
++static int gpio_keys_setup_key(struct platform_device *pdev,
++				struct input_dev *input,
++				struct gpio_button_data *bdata,
++				const struct gpio_keys_button *button)
+ {
+ 	const char *desc = button->desc ? button->desc : "gpio_keys";
+ 	struct device *dev = &pdev->dev;
+@@ -551,7 +551,7 @@ static void gpio_keys_close(struct input_dev *input)
+ /*
+  * Translate OpenFirmware node properties into platform_data
+  */
+-static struct gpio_keys_platform_data * __devinit
++static struct gpio_keys_platform_data *
+ gpio_keys_get_devtree_pdata(struct device *dev)
+ {
+ 	struct device_node *node, *pp;
+@@ -658,7 +658,7 @@ static void gpio_remove_key(struct gpio_button_data *bdata)
+ 		gpio_free(bdata->button->gpio);
+ }
+ 
+-static int __devinit gpio_keys_probe(struct platform_device *pdev)
++static int gpio_keys_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev);
+diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c
+index 922cbbdb5c84..8c09ce244aa2 100644
+--- a/drivers/input/keyboard/gpio_keys_polled.c
++++ b/drivers/input/keyboard/gpio_keys_polled.c
+@@ -103,8 +103,7 @@ static void gpio_keys_polled_close(struct input_polled_dev *dev)
+ }
+ 
+ #ifdef CONFIG_OF
+-static struct gpio_keys_platform_data * __devinit
+-gpio_keys_polled_get_devtree_pdata(struct device *dev)
++static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct device *dev)
+ {
+ 	struct device_node *node, *pp;
+ 	struct gpio_keys_platform_data *pdata;
+@@ -196,7 +195,7 @@ gpio_keys_polled_get_devtree_pdata(struct device *dev)
+ }
+ #endif
+ 
+-static int __devinit gpio_keys_polled_probe(struct platform_device *pdev)
++static int gpio_keys_polled_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev);
+diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c
+index 97d3151232be..a5da05ac6094 100644
+--- a/drivers/input/keyboard/hilkbd.c
++++ b/drivers/input/keyboard/hilkbd.c
+@@ -200,7 +200,7 @@ static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len)
+ 
+ 
+ /* initialize HIL */
+-static int __devinit hil_keyb_init(void)
++static int hil_keyb_init(void)
+ {
+ 	unsigned char c;
+ 	unsigned int i, kbid;
+@@ -299,7 +299,7 @@ static void __devexit hil_keyb_exit(void)
+ }
+ 
+ #if defined(CONFIG_PARISC)
+-static int __devinit hil_probe_chip(struct parisc_device *dev)
++static int hil_probe_chip(struct parisc_device *dev)
+ {
+ 	/* Only allow one HIL keyboard */
+ 	if (hil_dev.dev)
+diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c
+index 93c344137cc5..d4d95428c276 100644
+--- a/drivers/input/keyboard/imx_keypad.c
++++ b/drivers/input/keyboard/imx_keypad.c
+@@ -413,7 +413,7 @@ static int imx_keypad_open(struct input_dev *dev)
+ 	return -EIO;
+ }
+ 
+-static int __devinit imx_keypad_probe(struct platform_device *pdev)
++static int imx_keypad_probe(struct platform_device *pdev)
+ {
+ 	const struct matrix_keymap_data *keymap_data = pdev->dev.platform_data;
+ 	struct imx_keypad *keypad;
+diff --git a/drivers/input/keyboard/jornada680_kbd.c b/drivers/input/keyboard/jornada680_kbd.c
+index bd1a9c365d11..eac650c26ad4 100644
+--- a/drivers/input/keyboard/jornada680_kbd.c
++++ b/drivers/input/keyboard/jornada680_kbd.c
+@@ -179,7 +179,7 @@ static void jornadakbd680_poll(struct input_polled_dev *dev)
+ 	memcpy(jornadakbd->old_scan, jornadakbd->new_scan, JORNADA_SCAN_SIZE);
+ }
+ 
+-static int __devinit jornada680kbd_probe(struct platform_device *pdev)
++static int jornada680kbd_probe(struct platform_device *pdev)
+ {
+ 	struct jornadakbd *jornadakbd;
+ 	struct input_polled_dev *poll_dev;
+diff --git a/drivers/input/keyboard/jornada720_kbd.c b/drivers/input/keyboard/jornada720_kbd.c
+index 9771db1de01b..2f08a03e7cba 100644
+--- a/drivers/input/keyboard/jornada720_kbd.c
++++ b/drivers/input/keyboard/jornada720_kbd.c
+@@ -94,7 +94,7 @@ static irqreturn_t jornada720_kbd_interrupt(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ };
+ 
+-static int __devinit jornada720_kbd_probe(struct platform_device *pdev)
++static int jornada720_kbd_probe(struct platform_device *pdev)
+ {
+ 	struct jornadakbd *jornadakbd;
+ 	struct input_dev *input_dev;
+diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c
+index 87432859be52..ee0116b0a427 100644
+--- a/drivers/input/keyboard/lm8323.c
++++ b/drivers/input/keyboard/lm8323.c
+@@ -624,7 +624,7 @@ static ssize_t lm8323_set_disable(struct device *dev,
+ }
+ static DEVICE_ATTR(disable_kp, 0644, lm8323_show_disable, lm8323_set_disable);
+ 
+-static int __devinit lm8323_probe(struct i2c_client *client,
++static int lm8323_probe(struct i2c_client *client,
+ 				  const struct i2c_device_id *id)
+ {
+ 	struct lm8323_platform_data *pdata = client->dev.platform_data;
+diff --git a/drivers/input/keyboard/lm8333.c b/drivers/input/keyboard/lm8333.c
+index c76e488ce9bc..9fc03727d61d 100644
+--- a/drivers/input/keyboard/lm8333.c
++++ b/drivers/input/keyboard/lm8333.c
+@@ -128,7 +128,7 @@ static irqreturn_t lm8333_irq_thread(int irq, void *data)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit lm8333_probe(struct i2c_client *client,
++static int lm8333_probe(struct i2c_client *client,
+ 				  const struct i2c_device_id *id)
+ {
+ 	const struct lm8333_platform_data *pdata = client->dev.platform_data;
+diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c
+index dba900c54ce6..e2892466f3cc 100644
+--- a/drivers/input/keyboard/locomokbd.c
++++ b/drivers/input/keyboard/locomokbd.c
+@@ -236,7 +236,7 @@ static void locomokbd_close(struct input_dev *dev)
+ 	locomo_writel(r, locomokbd->base + LOCOMO_KIC);
+ }
+ 
+-static int __devinit locomokbd_probe(struct locomo_dev *dev)
++static int locomokbd_probe(struct locomo_dev *dev)
+ {
+ 	struct locomokbd *locomokbd;
+ 	struct input_dev *input_dev;
+diff --git a/drivers/input/keyboard/lpc32xx-keys.c b/drivers/input/keyboard/lpc32xx-keys.c
+index 8872ce62c9d8..72f8a0be82e1 100644
+--- a/drivers/input/keyboard/lpc32xx-keys.c
++++ b/drivers/input/keyboard/lpc32xx-keys.c
+@@ -139,7 +139,7 @@ static void lpc32xx_kscan_close(struct input_dev *dev)
+ 	clk_disable_unprepare(kscandat->clk);
+ }
+ 
+-static int __devinit lpc32xx_parse_dt(struct device *dev,
++static int lpc32xx_parse_dt(struct device *dev,
+ 				      struct lpc32xx_kscan_drv *kscandat)
+ {
+ 	struct device_node *np = dev->of_node;
+@@ -166,7 +166,7 @@ static int __devinit lpc32xx_parse_dt(struct device *dev,
+ 	return 0;
+ }
+ 
+-static int __devinit lpc32xx_kscan_probe(struct platform_device *pdev)
++static int lpc32xx_kscan_probe(struct platform_device *pdev)
+ {
+ 	struct lpc32xx_kscan_drv *kscandat;
+ 	struct input_dev *input;
+diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c
+index ed2bacdf2ccb..b9d67c2f30d6 100644
+--- a/drivers/input/keyboard/matrix_keypad.c
++++ b/drivers/input/keyboard/matrix_keypad.c
+@@ -301,8 +301,8 @@ static int matrix_keypad_resume(struct device *dev)
+ static SIMPLE_DEV_PM_OPS(matrix_keypad_pm_ops,
+ 			 matrix_keypad_suspend, matrix_keypad_resume);
+ 
+-static int __devinit matrix_keypad_init_gpio(struct platform_device *pdev,
+-					     struct matrix_keypad *keypad)
++static int matrix_keypad_init_gpio(struct platform_device *pdev,
++				   struct matrix_keypad *keypad)
+ {
+ 	const struct matrix_keypad_platform_data *pdata = keypad->pdata;
+ 	int i, err;
+@@ -397,7 +397,7 @@ static void matrix_keypad_free_gpio(struct matrix_keypad *keypad)
+ }
+ 
+ #ifdef CONFIG_OF
+-static struct matrix_keypad_platform_data * __devinit
++static struct matrix_keypad_platform_data *
+ matrix_keypad_parse_dt(struct device *dev)
+ {
+ 	struct matrix_keypad_platform_data *pdata;
+@@ -465,7 +465,7 @@ matrix_keypad_parse_dt(struct device *dev)
+ }
+ #endif
+ 
+-static int __devinit matrix_keypad_probe(struct platform_device *pdev)
++static int matrix_keypad_probe(struct platform_device *pdev)
+ {
+ 	const struct matrix_keypad_platform_data *pdata;
+ 	struct matrix_keypad *keypad;
+diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c
+index 90478d182bc8..98b8ff10e6f1 100644
+--- a/drivers/input/keyboard/max7359_keypad.c
++++ b/drivers/input/keyboard/max7359_keypad.c
+@@ -179,7 +179,7 @@ static void max7359_initialize(struct i2c_client *client)
+ 	max7359_fall_deepsleep(client);
+ }
+ 
+-static int __devinit max7359_probe(struct i2c_client *client,
++static int max7359_probe(struct i2c_client *client,
+ 					const struct i2c_device_id *id)
+ {
+ 	const struct matrix_keymap_data *keymap_data = client->dev.platform_data;
+diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c
+index 751b1419e56b..e729774cecd8 100644
+--- a/drivers/input/keyboard/mcs_touchkey.c
++++ b/drivers/input/keyboard/mcs_touchkey.c
+@@ -97,7 +97,7 @@ static irqreturn_t mcs_touchkey_interrupt(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit mcs_touchkey_probe(struct i2c_client *client,
++static int mcs_touchkey_probe(struct i2c_client *client,
+ 		const struct i2c_device_id *id)
+ {
+ 	const struct mcs_platform_data *pdata;
+diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c
+index 38b1c0f72ed3..854486c347fe 100644
+--- a/drivers/input/keyboard/mpr121_touchkey.c
++++ b/drivers/input/keyboard/mpr121_touchkey.c
+@@ -123,7 +123,7 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit mpr121_phys_init(const struct mpr121_platform_data *pdata,
++static int mpr121_phys_init(const struct mpr121_platform_data *pdata,
+ 				      struct mpr121_touchkey *mpr121,
+ 				      struct i2c_client *client)
+ {
+@@ -185,8 +185,8 @@ static int __devinit mpr121_phys_init(const struct mpr121_platform_data *pdata,
+ 	return ret;
+ }
+ 
+-static int __devinit mpr_touchkey_probe(struct i2c_client *client,
+-					const struct i2c_device_id *id)
++static int mpr_touchkey_probe(struct i2c_client *client,
++			      const struct i2c_device_id *id)
+ {
+ 	const struct mpr121_platform_data *pdata = client->dev.platform_data;
+ 	struct mpr121_touchkey *mpr121;
+diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c
+index 1d17d91ed1e1..ffb8c6c1c5dc 100644
+--- a/drivers/input/keyboard/omap-keypad.c
++++ b/drivers/input/keyboard/omap-keypad.c
+@@ -244,7 +244,7 @@ static int omap_kp_resume(struct platform_device *dev)
+ #define omap_kp_resume	NULL
+ #endif
+ 
+-static int __devinit omap_kp_probe(struct platform_device *pdev)
++static int omap_kp_probe(struct platform_device *pdev)
+ {
+ 	struct omap_kp *omap_kp;
+ 	struct input_dev *input_dev;
+diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
+index 7145ab3401f8..c16a3229968c 100644
+--- a/drivers/input/keyboard/omap4-keypad.c
++++ b/drivers/input/keyboard/omap4-keypad.c
+@@ -211,8 +211,8 @@ static void omap4_keypad_close(struct input_dev *input)
+ }
+ 
+ #ifdef CONFIG_OF
+-static int __devinit omap4_keypad_parse_dt(struct device *dev,
+-					   struct omap4_keypad *keypad_data)
++static int omap4_keypad_parse_dt(struct device *dev,
++				 struct omap4_keypad *keypad_data)
+ {
+ 	struct device_node *np = dev->of_node;
+ 
+@@ -241,7 +241,7 @@ static inline int omap4_keypad_parse_dt(struct device *dev,
+ }
+ #endif
+ 
+-static int __devinit omap4_keypad_probe(struct platform_device *pdev)
++static int omap4_keypad_probe(struct platform_device *pdev)
+ {
+ 	const struct omap4_keypad_platform_data *pdata =
+ 				dev_get_platdata(&pdev->dev);
+diff --git a/drivers/input/keyboard/opencores-kbd.c b/drivers/input/keyboard/opencores-kbd.c
+index 7914ede8e4bf..ddc1c39c0c31 100644
+--- a/drivers/input/keyboard/opencores-kbd.c
++++ b/drivers/input/keyboard/opencores-kbd.c
+@@ -37,7 +37,7 @@ static irqreturn_t opencores_kbd_isr(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit opencores_kbd_probe(struct platform_device *pdev)
++static int opencores_kbd_probe(struct platform_device *pdev)
+ {
+ 	struct input_dev *input;
+ 	struct opencores_kbd *opencores_kbd;
+diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c
+index d3623c5a3eea..fa177aba5dbe 100644
+--- a/drivers/input/keyboard/pmic8xxx-keypad.c
++++ b/drivers/input/keyboard/pmic8xxx-keypad.c
+@@ -397,7 +397,7 @@ static irqreturn_t pmic8xxx_kp_irq(int irq, void *data)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit pmic8xxx_kpd_init(struct pmic8xxx_kp *kp)
++static int pmic8xxx_kpd_init(struct pmic8xxx_kp *kp)
+ {
+ 	int bits, rc, cycles;
+ 	u8 scan_val = 0, ctrl_val = 0;
+@@ -447,7 +447,7 @@ static int __devinit pmic8xxx_kpd_init(struct pmic8xxx_kp *kp)
+ 
+ }
+ 
+-static int  __devinit pmic8xxx_kp_config_gpio(int gpio_start, int num_gpios,
++static int  pmic8xxx_kp_config_gpio(int gpio_start, int num_gpios,
+ 			struct pmic8xxx_kp *kp, struct pm_gpio *gpio_config)
+ {
+ 	int	rc, i;
+@@ -518,7 +518,7 @@ static void pmic8xxx_kp_close(struct input_dev *dev)
+  * - set irq edge type.
+  * - enable the keypad controller.
+  */
+-static int __devinit pmic8xxx_kp_probe(struct platform_device *pdev)
++static int pmic8xxx_kp_probe(struct platform_device *pdev)
+ {
+ 	const struct pm8xxx_keypad_platform_data *pdata =
+ 					dev_get_platdata(&pdev->dev);
+diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
+index a6bcd3129f0f..91778fee8b99 100644
+--- a/drivers/input/keyboard/pxa27x_keypad.c
++++ b/drivers/input/keyboard/pxa27x_keypad.c
+@@ -482,7 +482,7 @@ static const struct dev_pm_ops pxa27x_keypad_pm_ops = {
+ };
+ #endif
+ 
+-static int __devinit pxa27x_keypad_probe(struct platform_device *pdev)
++static int pxa27x_keypad_probe(struct platform_device *pdev)
+ {
+ 	struct pxa27x_keypad_platform_data *pdata = pdev->dev.platform_data;
+ 	struct pxa27x_keypad *keypad;
+diff --git a/drivers/input/keyboard/pxa930_rotary.c b/drivers/input/keyboard/pxa930_rotary.c
+index f8f89d1f230d..60797c22322d 100644
+--- a/drivers/input/keyboard/pxa930_rotary.c
++++ b/drivers/input/keyboard/pxa930_rotary.c
+@@ -82,7 +82,7 @@ static void pxa930_rotary_close(struct input_dev *dev)
+ 	clear_sbcr(r);
+ }
+ 
+-static int __devinit pxa930_rotary_probe(struct platform_device *pdev)
++static int pxa930_rotary_probe(struct platform_device *pdev)
+ {
+ 	struct pxa930_rotary_platform_data *pdata = pdev->dev.platform_data;
+ 	struct pxa930_rotary *r;
+diff --git a/drivers/input/keyboard/qt1070.c b/drivers/input/keyboard/qt1070.c
+index eb46405eaad0..f9358e7d90bc 100644
+--- a/drivers/input/keyboard/qt1070.c
++++ b/drivers/input/keyboard/qt1070.c
+@@ -91,7 +91,7 @@ static int qt1070_write(struct i2c_client *client, u8 reg, u8 data)
+ 	return ret;
+ }
+ 
+-static bool __devinit qt1070_identify(struct i2c_client *client)
++static bool qt1070_identify(struct i2c_client *client)
+ {
+ 	int id, ver;
+ 
+@@ -140,7 +140,7 @@ static irqreturn_t qt1070_interrupt(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit qt1070_probe(struct i2c_client *client,
++static int qt1070_probe(struct i2c_client *client,
+ 				const struct i2c_device_id *id)
+ {
+ 	struct qt1070_data *data;
+diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c
+index 691fe92a9824..69a6a6ffdbe3 100644
+--- a/drivers/input/keyboard/qt2160.c
++++ b/drivers/input/keyboard/qt2160.c
+@@ -183,7 +183,7 @@ static void qt2160_worker(struct work_struct *work)
+ 	qt2160_schedule_read(qt2160);
+ }
+ 
+-static int __devinit qt2160_read(struct i2c_client *client, u8 reg)
++static int qt2160_read(struct i2c_client *client, u8 reg)
+ {
+ 	int ret;
+ 
+@@ -204,7 +204,7 @@ static int __devinit qt2160_read(struct i2c_client *client, u8 reg)
+ 	return ret;
+ }
+ 
+-static int __devinit qt2160_write(struct i2c_client *client, u8 reg, u8 data)
++static int qt2160_write(struct i2c_client *client, u8 reg, u8 data)
+ {
+ 	int ret;
+ 
+@@ -217,7 +217,7 @@ static int __devinit qt2160_write(struct i2c_client *client, u8 reg, u8 data)
+ }
+ 
+ 
+-static bool __devinit qt2160_identify(struct i2c_client *client)
++static bool qt2160_identify(struct i2c_client *client)
+ {
+ 	int id, ver, rev;
+ 
+@@ -248,7 +248,7 @@ static bool __devinit qt2160_identify(struct i2c_client *client)
+ 	return true;
+ }
+ 
+-static int __devinit qt2160_probe(struct i2c_client *client,
++static int qt2160_probe(struct i2c_client *client,
+ 				  const struct i2c_device_id *id)
+ {
+ 	struct qt2160_data *qt2160;
+diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c
+index f02772aa47df..5c6a808ed62d 100644
+--- a/drivers/input/keyboard/samsung-keypad.c
++++ b/drivers/input/keyboard/samsung-keypad.c
+@@ -366,7 +366,7 @@ static void samsung_keypad_dt_gpio_free(struct samsung_keypad *keypad)
+ }
+ #endif
+ 
+-static int __devinit samsung_keypad_probe(struct platform_device *pdev)
++static int samsung_keypad_probe(struct platform_device *pdev)
+ {
+ 	const struct samsung_keypad_platdata *pdata;
+ 	const struct matrix_keymap_data *keymap_data;
+diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c
+index 07415a36ec1e..ffa9adb23f21 100644
+--- a/drivers/input/keyboard/sh_keysc.c
++++ b/drivers/input/keyboard/sh_keysc.c
+@@ -162,7 +162,7 @@ static irqreturn_t sh_keysc_isr(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit sh_keysc_probe(struct platform_device *pdev)
++static int sh_keysc_probe(struct platform_device *pdev)
+ {
+ 	struct sh_keysc_priv *priv;
+ 	struct sh_keysc_info *pdata;
+diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c
+index 0c8862343e75..3c503dae7b64 100644
+--- a/drivers/input/keyboard/spear-keyboard.c
++++ b/drivers/input/keyboard/spear-keyboard.c
+@@ -146,7 +146,7 @@ static void spear_kbd_close(struct input_dev *dev)
+ }
+ 
+ #ifdef CONFIG_OF
+-static int __devinit spear_kbd_parse_dt(struct platform_device *pdev,
++static int spear_kbd_parse_dt(struct platform_device *pdev,
+                                         struct spear_kbd *kbd)
+ {
+ 	struct device_node *np = pdev->dev.of_node;
+@@ -181,7 +181,7 @@ static inline int spear_kbd_parse_dt(struct platform_device *pdev,
+ }
+ #endif
+ 
+-static int __devinit spear_kbd_probe(struct platform_device *pdev)
++static int spear_kbd_probe(struct platform_device *pdev)
+ {
+ 	struct kbd_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ 	const struct matrix_keymap_data *keymap = pdata ? pdata->keymap : NULL;
+diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c
+index 286719f5bc0b..b3f917d73cd6 100644
+--- a/drivers/input/keyboard/stmpe-keypad.c
++++ b/drivers/input/keyboard/stmpe-keypad.c
+@@ -166,7 +166,7 @@ static irqreturn_t stmpe_keypad_irq(int irq, void *dev)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit stmpe_keypad_altfunc_init(struct stmpe_keypad *keypad)
++static int stmpe_keypad_altfunc_init(struct stmpe_keypad *keypad)
+ {
+ 	const struct stmpe_keypad_variant *variant = keypad->variant;
+ 	unsigned int col_gpios = variant->col_gpios;
+@@ -207,7 +207,7 @@ static int __devinit stmpe_keypad_altfunc_init(struct stmpe_keypad *keypad)
+ 	return stmpe_set_altfunc(stmpe, pins, STMPE_BLOCK_KEYPAD);
+ }
+ 
+-static int __devinit stmpe_keypad_chip_init(struct stmpe_keypad *keypad)
++static int stmpe_keypad_chip_init(struct stmpe_keypad *keypad)
+ {
+ 	const struct stmpe_keypad_platform_data *plat = keypad->plat;
+ 	const struct stmpe_keypad_variant *variant = keypad->variant;
+@@ -257,7 +257,7 @@ static int __devinit stmpe_keypad_chip_init(struct stmpe_keypad *keypad)
+ 			      (plat->debounce_ms << 1));
+ }
+ 
+-static int __devinit stmpe_keypad_probe(struct platform_device *pdev)
++static int stmpe_keypad_probe(struct platform_device *pdev)
+ {
+ 	struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
+ 	const struct stmpe_keypad_platform_data *plat;
+diff --git a/drivers/input/keyboard/tc3589x-keypad.c b/drivers/input/keyboard/tc3589x-keypad.c
+index 75fa2b98aaeb..6d725d633aeb 100644
+--- a/drivers/input/keyboard/tc3589x-keypad.c
++++ b/drivers/input/keyboard/tc3589x-keypad.c
+@@ -299,7 +299,7 @@ static void tc3589x_keypad_close(struct input_dev *input)
+ 	tc3589x_keypad_disable(keypad);
+ }
+ 
+-static int __devinit tc3589x_keypad_probe(struct platform_device *pdev)
++static int tc3589x_keypad_probe(struct platform_device *pdev)
+ {
+ 	struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
+ 	struct tc_keypad *keypad;
+diff --git a/drivers/input/keyboard/tca6416-keypad.c b/drivers/input/keyboard/tca6416-keypad.c
+index f5fa75aa9db4..4f44579689a4 100644
+--- a/drivers/input/keyboard/tca6416-keypad.c
++++ b/drivers/input/keyboard/tca6416-keypad.c
+@@ -166,7 +166,7 @@ static void tca6416_keys_close(struct input_dev *dev)
+ 		disable_irq(chip->irqnum);
+ }
+ 
+-static int __devinit tca6416_setup_registers(struct tca6416_keypad_chip *chip)
++static int tca6416_setup_registers(struct tca6416_keypad_chip *chip)
+ {
+ 	int error;
+ 
+@@ -197,7 +197,7 @@ static int __devinit tca6416_setup_registers(struct tca6416_keypad_chip *chip)
+ 	return 0;
+ }
+ 
+-static int __devinit tca6416_keypad_probe(struct i2c_client *client,
++static int tca6416_keypad_probe(struct i2c_client *client,
+ 				   const struct i2c_device_id *id)
+ {
+ 	struct tca6416_keys_platform_data *pdata;
+diff --git a/drivers/input/keyboard/tca8418_keypad.c b/drivers/input/keyboard/tca8418_keypad.c
+index 672b5f8bcc11..6f970961f244 100644
+--- a/drivers/input/keyboard/tca8418_keypad.c
++++ b/drivers/input/keyboard/tca8418_keypad.c
+@@ -241,7 +241,7 @@ static irqreturn_t tca8418_irq_handler(int irq, void *dev_id)
+ /*
+  * Configure the TCA8418 for keypad operation
+  */
+-static int __devinit tca8418_configure(struct tca8418_keypad *keypad_data)
++static int tca8418_configure(struct tca8418_keypad *keypad_data)
+ {
+ 	int reg, error;
+ 
+@@ -270,7 +270,7 @@ static int __devinit tca8418_configure(struct tca8418_keypad *keypad_data)
+ 	return error;
+ }
+ 
+-static int __devinit tca8418_keypad_probe(struct i2c_client *client,
++static int tca8418_keypad_probe(struct i2c_client *client,
+ 					  const struct i2c_device_id *id)
+ {
+ 	const struct tca8418_keypad_platform_data *pdata =
+diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c
+index 0bbcf971d103..cf8ab689231b 100644
+--- a/drivers/input/keyboard/tegra-kbc.c
++++ b/drivers/input/keyboard/tegra-kbc.c
+@@ -573,7 +573,7 @@ static void tegra_kbc_close(struct input_dev *dev)
+ 	return tegra_kbc_stop(kbc);
+ }
+ 
+-static bool __devinit
++static bool
+ tegra_kbc_check_pin_cfg(const struct tegra_kbc_platform_data *pdata,
+ 			struct device *dev, unsigned int *num_rows)
+ {
+@@ -619,7 +619,7 @@ tegra_kbc_check_pin_cfg(const struct tegra_kbc_platform_data *pdata,
+ }
+ 
+ #ifdef CONFIG_OF
+-static struct tegra_kbc_platform_data * __devinit tegra_kbc_dt_parse_pdata(
++static struct tegra_kbc_platform_data *tegra_kbc_dt_parse_pdata(
+ 	struct platform_device *pdev)
+ {
+ 	struct tegra_kbc_platform_data *pdata;
+@@ -670,7 +670,7 @@ static inline struct tegra_kbc_platform_data *tegra_kbc_dt_parse_pdata(
+ }
+ #endif
+ 
+-static int __devinit tegra_kbd_setup_keymap(struct tegra_kbc *kbc)
++static int tegra_kbd_setup_keymap(struct tegra_kbc *kbc)
+ {
+ 	const struct tegra_kbc_platform_data *pdata = kbc->pdata;
+ 	const struct matrix_keymap_data *keymap_data = pdata->keymap_data;
+@@ -697,7 +697,7 @@ static int __devinit tegra_kbd_setup_keymap(struct tegra_kbc *kbc)
+ 	return retval;
+ }
+ 
+-static int __devinit tegra_kbc_probe(struct platform_device *pdev)
++static int tegra_kbc_probe(struct platform_device *pdev)
+ {
+ 	const struct tegra_kbc_platform_data *pdata = pdev->dev.platform_data;
+ 	struct tegra_kbc *kbc;
+diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c
+index 05d923c51c1e..55cd0700af8c 100644
+--- a/drivers/input/keyboard/tnetv107x-keypad.c
++++ b/drivers/input/keyboard/tnetv107x-keypad.c
+@@ -153,7 +153,7 @@ static void keypad_stop(struct input_dev *dev)
+ 	clk_disable(kp->clk);
+ }
+ 
+-static int __devinit keypad_probe(struct platform_device *pdev)
++static int keypad_probe(struct platform_device *pdev)
+ {
+ 	const struct matrix_keypad_platform_data *pdata;
+ 	const struct matrix_keymap_data *keymap_data;
+diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c
+index ae25909d51b1..78dd9f27dd87 100644
+--- a/drivers/input/keyboard/twl4030_keypad.c
++++ b/drivers/input/keyboard/twl4030_keypad.c
+@@ -271,7 +271,7 @@ static irqreturn_t do_kp_irq(int irq, void *_kp)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit twl4030_kp_program(struct twl4030_keypad *kp)
++static int twl4030_kp_program(struct twl4030_keypad *kp)
+ {
+ 	u8 reg;
+ 	int i;
+@@ -328,7 +328,7 @@ static int __devinit twl4030_kp_program(struct twl4030_keypad *kp)
+  * Registers keypad device with input subsystem
+  * and configures TWL4030 keypad registers
+  */
+-static int __devinit twl4030_kp_probe(struct platform_device *pdev)
++static int twl4030_kp_probe(struct platform_device *pdev)
+ {
+ 	struct twl4030_keypad_data *pdata = pdev->dev.platform_data;
+ 	const struct matrix_keymap_data *keymap_data;
+diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c
+index a90fdfc0948f..7574e10ef097 100644
+--- a/drivers/input/keyboard/w90p910_keypad.c
++++ b/drivers/input/keyboard/w90p910_keypad.c
+@@ -118,7 +118,7 @@ static void w90p910_keypad_close(struct input_dev *dev)
+ 	clk_disable(keypad->clk);
+ }
+ 
+-static int __devinit w90p910_keypad_probe(struct platform_device *pdev)
++static int w90p910_keypad_probe(struct platform_device *pdev)
+ {
+ 	const struct w90p910_keypad_platform_data *pdata =
+ 						pdev->dev.platform_data;
+diff --git a/drivers/input/misc/88pm80x_onkey.c b/drivers/input/misc/88pm80x_onkey.c
+index f77557523bb9..946edcadfb2e 100644
+--- a/drivers/input/misc/88pm80x_onkey.c
++++ b/drivers/input/misc/88pm80x_onkey.c
+@@ -62,7 +62,7 @@ static irqreturn_t pm80x_onkey_handler(int irq, void *data)
+ static SIMPLE_DEV_PM_OPS(pm80x_onkey_pm_ops, pm80x_dev_suspend,
+ 			 pm80x_dev_resume);
+ 
+-static int __devinit pm80x_onkey_probe(struct platform_device *pdev)
++static int pm80x_onkey_probe(struct platform_device *pdev)
+ {
+ 
+ 	struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+diff --git a/drivers/input/misc/88pm860x_onkey.c b/drivers/input/misc/88pm860x_onkey.c
+index 8391a9d86ab5..81af2d70e5dc 100644
+--- a/drivers/input/misc/88pm860x_onkey.c
++++ b/drivers/input/misc/88pm860x_onkey.c
+@@ -56,7 +56,7 @@ static irqreturn_t pm860x_onkey_handler(int irq, void *data)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit pm860x_onkey_probe(struct platform_device *pdev)
++static int pm860x_onkey_probe(struct platform_device *pdev)
+ {
+ 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+ 	struct pm860x_onkey_info *info;
+diff --git a/drivers/input/misc/ab8500-ponkey.c b/drivers/input/misc/ab8500-ponkey.c
+index ae9c20522dbd..f188222d208d 100644
+--- a/drivers/input/misc/ab8500-ponkey.c
++++ b/drivers/input/misc/ab8500-ponkey.c
+@@ -45,7 +45,7 @@ static irqreturn_t ab8500_ponkey_handler(int irq, void *data)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit ab8500_ponkey_probe(struct platform_device *pdev)
++static int ab8500_ponkey_probe(struct platform_device *pdev)
+ {
+ 	struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
+ 	struct ab8500_ponkey *ponkey;
+diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c
+index 02e21d4f5e73..9477602c7211 100644
+--- a/drivers/input/misc/ad714x-i2c.c
++++ b/drivers/input/misc/ad714x-i2c.c
+@@ -72,7 +72,7 @@ static int ad714x_i2c_read(struct ad714x_chip *chip,
+ 	return 0;
+ }
+ 
+-static int __devinit ad714x_i2c_probe(struct i2c_client *client,
++static int ad714x_i2c_probe(struct i2c_client *client,
+ 					const struct i2c_device_id *id)
+ {
+ 	struct ad714x_chip *chip;
+diff --git a/drivers/input/misc/ad714x-spi.c b/drivers/input/misc/ad714x-spi.c
+index eee820b41356..497871e506f4 100644
+--- a/drivers/input/misc/ad714x-spi.c
++++ b/drivers/input/misc/ad714x-spi.c
+@@ -83,7 +83,7 @@ static int ad714x_spi_write(struct ad714x_chip *chip,
+ 	return 0;
+ }
+ 
+-static int __devinit ad714x_spi_probe(struct spi_device *spi)
++static int ad714x_spi_probe(struct spi_device *spi)
+ {
+ 	struct ad714x_chip *chip;
+ 	int err;
+diff --git a/drivers/input/misc/adxl34x-i2c.c b/drivers/input/misc/adxl34x-i2c.c
+index 09094ca972c7..e262885f62de 100644
+--- a/drivers/input/misc/adxl34x-i2c.c
++++ b/drivers/input/misc/adxl34x-i2c.c
+@@ -73,7 +73,7 @@ static const struct adxl34x_bus_ops adxl34x_i2c_bops = {
+ 	.read_block	= adxl34x_i2c_read_block,
+ };
+ 
+-static int __devinit adxl34x_i2c_probe(struct i2c_client *client,
++static int adxl34x_i2c_probe(struct i2c_client *client,
+ 				       const struct i2c_device_id *id)
+ {
+ 	struct adxl34x *ac;
+diff --git a/drivers/input/misc/adxl34x-spi.c b/drivers/input/misc/adxl34x-spi.c
+index 756c899bfa7f..1071d252df07 100644
+--- a/drivers/input/misc/adxl34x-spi.c
++++ b/drivers/input/misc/adxl34x-spi.c
+@@ -65,7 +65,7 @@ static const struct adxl34x_bus_ops adxl34x_spi_bops = {
+ 	.read_block	= adxl34x_spi_read_block,
+ };
+ 
+-static int __devinit adxl34x_spi_probe(struct spi_device *spi)
++static int adxl34x_spi_probe(struct spi_device *spi)
+ {
+ 	struct adxl34x *ac;
+ 
+diff --git a/drivers/input/misc/bfin_rotary.c b/drivers/input/misc/bfin_rotary.c
+index 6df3f88a46dd..9cb4a74a479a 100644
+--- a/drivers/input/misc/bfin_rotary.c
++++ b/drivers/input/misc/bfin_rotary.c
+@@ -90,7 +90,7 @@ static irqreturn_t bfin_rotary_isr(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit bfin_rotary_probe(struct platform_device *pdev)
++static int bfin_rotary_probe(struct platform_device *pdev)
+ {
+ 	struct bfin_rotary_platform_data *pdata = pdev->dev.platform_data;
+ 	struct bfin_rot *rotary;
+diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c
+index 5b459d7dd207..a3219c2a3855 100644
+--- a/drivers/input/misc/bma150.c
++++ b/drivers/input/misc/bma150.c
+@@ -224,7 +224,7 @@ static int bma150_set_mode(struct bma150_data *bma150, u8 mode)
+ 	return 0;
+ }
+ 
+-static int __devinit bma150_soft_reset(struct bma150_data *bma150)
++static int bma150_soft_reset(struct bma150_data *bma150)
+ {
+ 	int error;
+ 
+@@ -237,19 +237,19 @@ static int __devinit bma150_soft_reset(struct bma150_data *bma150)
+ 	return 0;
+ }
+ 
+-static int __devinit bma150_set_range(struct bma150_data *bma150, u8 range)
++static int bma150_set_range(struct bma150_data *bma150, u8 range)
+ {
+ 	return bma150_set_reg_bits(bma150->client, range, BMA150_RANGE_POS,
+ 				BMA150_RANGE_MSK, BMA150_RANGE_REG);
+ }
+ 
+-static int __devinit bma150_set_bandwidth(struct bma150_data *bma150, u8 bw)
++static int bma150_set_bandwidth(struct bma150_data *bma150, u8 bw)
+ {
+ 	return bma150_set_reg_bits(bma150->client, bw, BMA150_BANDWIDTH_POS,
+ 				BMA150_BANDWIDTH_MSK, BMA150_BANDWIDTH_REG);
+ }
+ 
+-static int __devinit bma150_set_low_g_interrupt(struct bma150_data *bma150,
++static int bma150_set_low_g_interrupt(struct bma150_data *bma150,
+ 					u8 enable, u8 hyst, u8 dur, u8 thres)
+ {
+ 	int error;
+@@ -273,7 +273,7 @@ static int __devinit bma150_set_low_g_interrupt(struct bma150_data *bma150,
+ 				BMA150_LOW_G_EN_REG);
+ }
+ 
+-static int __devinit bma150_set_high_g_interrupt(struct bma150_data *bma150,
++static int bma150_set_high_g_interrupt(struct bma150_data *bma150,
+ 					u8 enable, u8 hyst, u8 dur, u8 thres)
+ {
+ 	int error;
+@@ -300,7 +300,7 @@ static int __devinit bma150_set_high_g_interrupt(struct bma150_data *bma150,
+ }
+ 
+ 
+-static int __devinit bma150_set_any_motion_interrupt(struct bma150_data *bma150,
++static int bma150_set_any_motion_interrupt(struct bma150_data *bma150,
+ 						u8 enable, u8 dur, u8 thres)
+ {
+ 	int error;
+@@ -424,7 +424,7 @@ static void bma150_poll_close(struct input_polled_dev *ipoll_dev)
+ 	bma150_close(bma150);
+ }
+ 
+-static int __devinit bma150_initialize(struct bma150_data *bma150,
++static int bma150_initialize(struct bma150_data *bma150,
+ 				       const struct bma150_cfg *cfg)
+ {
+ 	int error;
+@@ -465,7 +465,7 @@ static int __devinit bma150_initialize(struct bma150_data *bma150,
+ 	return bma150_set_mode(bma150, BMA150_MODE_SLEEP);
+ }
+ 
+-static void __devinit bma150_init_input_device(struct bma150_data *bma150,
++static void bma150_init_input_device(struct bma150_data *bma150,
+ 						struct input_dev *idev)
+ {
+ 	idev->name = BMA150_DRIVER;
+@@ -479,7 +479,7 @@ static void __devinit bma150_init_input_device(struct bma150_data *bma150,
+ 	input_set_abs_params(idev, ABS_Z, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
+ }
+ 
+-static int __devinit bma150_register_input_device(struct bma150_data *bma150)
++static int bma150_register_input_device(struct bma150_data *bma150)
+ {
+ 	struct input_dev *idev;
+ 	int error;
+@@ -504,7 +504,7 @@ static int __devinit bma150_register_input_device(struct bma150_data *bma150)
+ 	return 0;
+ }
+ 
+-static int __devinit bma150_register_polled_device(struct bma150_data *bma150)
++static int bma150_register_polled_device(struct bma150_data *bma150)
+ {
+ 	struct input_polled_dev *ipoll_dev;
+ 	int error;
+@@ -535,7 +535,7 @@ static int __devinit bma150_register_polled_device(struct bma150_data *bma150)
+ 	return 0;
+ }
+ 
+-static int __devinit bma150_probe(struct i2c_client *client,
++static int bma150_probe(struct i2c_client *client,
+ 				  const struct i2c_device_id *id)
+ {
+ 	const struct bma150_platform_data *pdata = client->dev.platform_data;
+diff --git a/drivers/input/misc/cma3000_d0x_i2c.c b/drivers/input/misc/cma3000_d0x_i2c.c
+index 523b6aabd7fc..ca2103efaf17 100644
+--- a/drivers/input/misc/cma3000_d0x_i2c.c
++++ b/drivers/input/misc/cma3000_d0x_i2c.c
+@@ -55,7 +55,7 @@ static const struct cma3000_bus_ops cma3000_i2c_bops = {
+ 	.write		= cma3000_i2c_set,
+ };
+ 
+-static int __devinit cma3000_i2c_probe(struct i2c_client *client,
++static int cma3000_i2c_probe(struct i2c_client *client,
+ 					const struct i2c_device_id *id)
+ {
+ 	struct cma3000_accl_data *data;
+diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c
+index 659f20df6040..beeb53dc073d 100644
+--- a/drivers/input/misc/cobalt_btns.c
++++ b/drivers/input/misc/cobalt_btns.c
+@@ -73,7 +73,7 @@ static void handle_buttons(struct input_polled_dev *dev)
+ 	}
+ }
+ 
+-static int __devinit cobalt_buttons_probe(struct platform_device *pdev)
++static int cobalt_buttons_probe(struct platform_device *pdev)
+ {
+ 	struct buttons_dev *bdev;
+ 	struct input_polled_dev *poll_dev;
+diff --git a/drivers/input/misc/da9052_onkey.c b/drivers/input/misc/da9052_onkey.c
+index acd07e8c32bc..8464029972db 100644
+--- a/drivers/input/misc/da9052_onkey.c
++++ b/drivers/input/misc/da9052_onkey.c
+@@ -71,7 +71,7 @@ static irqreturn_t da9052_onkey_irq(int irq, void *data)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit da9052_onkey_probe(struct platform_device *pdev)
++static int da9052_onkey_probe(struct platform_device *pdev)
+ {
+ 	struct da9052 *da9052 = dev_get_drvdata(pdev->dev.parent);
+ 	struct da9052_onkey *onkey;
+diff --git a/drivers/input/misc/da9055_onkey.c b/drivers/input/misc/da9055_onkey.c
+index fe434e07dbfc..cbf49893450c 100644
+--- a/drivers/input/misc/da9055_onkey.c
++++ b/drivers/input/misc/da9055_onkey.c
+@@ -73,7 +73,7 @@ static irqreturn_t da9055_onkey_irq(int irq, void *data)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit da9055_onkey_probe(struct platform_device *pdev)
++static int da9055_onkey_probe(struct platform_device *pdev)
+ {
+ 	struct da9055 *da9055 = dev_get_drvdata(pdev->dev.parent);
+ 	struct da9055_onkey *onkey;
+diff --git a/drivers/input/misc/dm355evm_keys.c b/drivers/input/misc/dm355evm_keys.c
+index 1afb91cd71fb..5409ab7684bb 100644
+--- a/drivers/input/misc/dm355evm_keys.c
++++ b/drivers/input/misc/dm355evm_keys.c
+@@ -173,7 +173,7 @@ static irqreturn_t dm355evm_keys_irq(int irq, void *_keys)
+ 
+ /*----------------------------------------------------------------------*/
+ 
+-static int __devinit dm355evm_keys_probe(struct platform_device *pdev)
++static int dm355evm_keys_probe(struct platform_device *pdev)
+ {
+ 	struct dm355evm_keys	*keys;
+ 	struct input_dev	*input;
+diff --git a/drivers/input/misc/gp2ap002a00f.c b/drivers/input/misc/gp2ap002a00f.c
+index 99ec8d0c6e41..8ad99be5e5c8 100644
+--- a/drivers/input/misc/gp2ap002a00f.c
++++ b/drivers/input/misc/gp2ap002a00f.c
+@@ -98,7 +98,7 @@ static void gp2a_device_close(struct input_dev *dev)
+ 			"unable to deactivate, err %d\n", error);
+ }
+ 
+-static int __devinit gp2a_initialize(struct gp2a_data *dt)
++static int gp2a_initialize(struct gp2a_data *dt)
+ {
+ 	int error;
+ 
+@@ -122,7 +122,7 @@ static int __devinit gp2a_initialize(struct gp2a_data *dt)
+ 	return error;
+ }
+ 
+-static int __devinit gp2a_probe(struct i2c_client *client,
++static int gp2a_probe(struct i2c_client *client,
+ 				const struct i2c_device_id *id)
+ {
+ 	const struct gp2a_platform_data *pdata = client->dev.platform_data;
+diff --git a/drivers/input/misc/gpio_tilt_polled.c b/drivers/input/misc/gpio_tilt_polled.c
+index bf97679fe522..467884be3b3a 100644
+--- a/drivers/input/misc/gpio_tilt_polled.c
++++ b/drivers/input/misc/gpio_tilt_polled.c
+@@ -96,7 +96,7 @@ static void gpio_tilt_polled_close(struct input_polled_dev *dev)
+ 		pdata->disable(tdev->dev);
+ }
+ 
+-static int __devinit gpio_tilt_polled_probe(struct platform_device *pdev)
++static int gpio_tilt_polled_probe(struct platform_device *pdev)
+ {
+ 	const struct gpio_tilt_platform_data *pdata = pdev->dev.platform_data;
+ 	struct device *dev = &pdev->dev;
+diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c
+index 18a2970f88ee..97620d56ac0a 100644
+--- a/drivers/input/misc/ixp4xx-beeper.c
++++ b/drivers/input/misc/ixp4xx-beeper.c
+@@ -87,7 +87,7 @@ static irqreturn_t ixp4xx_spkr_interrupt(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit ixp4xx_spkr_probe(struct platform_device *dev)
++static int ixp4xx_spkr_probe(struct platform_device *dev)
+ {
+ 	struct input_dev *input_dev;
+ 	int err;
+diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
+index 8414ddb31815..57f1f1284165 100644
+--- a/drivers/input/misc/kxtj9.c
++++ b/drivers/input/misc/kxtj9.c
+@@ -295,7 +295,7 @@ static void kxtj9_input_close(struct input_dev *dev)
+ 	kxtj9_disable(tj9);
+ }
+ 
+-static void __devinit kxtj9_init_input_device(struct kxtj9_data *tj9,
++static void kxtj9_init_input_device(struct kxtj9_data *tj9,
+ 					      struct input_dev *input_dev)
+ {
+ 	__set_bit(EV_ABS, input_dev->evbit);
+@@ -308,7 +308,7 @@ static void __devinit kxtj9_init_input_device(struct kxtj9_data *tj9,
+ 	input_dev->dev.parent = &tj9->client->dev;
+ }
+ 
+-static int __devinit kxtj9_setup_input_device(struct kxtj9_data *tj9)
++static int kxtj9_setup_input_device(struct kxtj9_data *tj9)
+ {
+ 	struct input_dev *input_dev;
+ 	int err;
+@@ -433,7 +433,7 @@ static void kxtj9_polled_input_close(struct input_polled_dev *dev)
+ 	kxtj9_disable(tj9);
+ }
+ 
+-static int __devinit kxtj9_setup_polled_device(struct kxtj9_data *tj9)
++static int kxtj9_setup_polled_device(struct kxtj9_data *tj9)
+ {
+ 	int err;
+ 	struct input_polled_dev *poll_dev;
+@@ -485,7 +485,7 @@ static inline void kxtj9_teardown_polled_device(struct kxtj9_data *tj9)
+ 
+ #endif
+ 
+-static int __devinit kxtj9_verify(struct kxtj9_data *tj9)
++static int kxtj9_verify(struct kxtj9_data *tj9)
+ {
+ 	int retval;
+ 
+@@ -506,7 +506,7 @@ static int __devinit kxtj9_verify(struct kxtj9_data *tj9)
+ 	return retval;
+ }
+ 
+-static int __devinit kxtj9_probe(struct i2c_client *client,
++static int kxtj9_probe(struct i2c_client *client,
+ 				 const struct i2c_device_id *id)
+ {
+ 	const struct kxtj9_platform_data *pdata = client->dev.platform_data;
+diff --git a/drivers/input/misc/m68kspkr.c b/drivers/input/misc/m68kspkr.c
+index f3a3c5e14d00..ec8f59dcb46c 100644
+--- a/drivers/input/misc/m68kspkr.c
++++ b/drivers/input/misc/m68kspkr.c
+@@ -48,7 +48,7 @@ static int m68kspkr_event(struct input_dev *dev, unsigned int type, unsigned int
+ 	return 0;
+ }
+ 
+-static int __devinit m68kspkr_probe(struct platform_device *dev)
++static int m68kspkr_probe(struct platform_device *dev)
+ {
+ 	struct input_dev *input_dev;
+ 	int err;
+diff --git a/drivers/input/misc/max8925_onkey.c b/drivers/input/misc/max8925_onkey.c
+index 3c3db6787e8f..57bc42c92d4b 100644
+--- a/drivers/input/misc/max8925_onkey.c
++++ b/drivers/input/misc/max8925_onkey.c
+@@ -62,7 +62,7 @@ static irqreturn_t max8925_onkey_handler(int irq, void *data)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit max8925_onkey_probe(struct platform_device *pdev)
++static int max8925_onkey_probe(struct platform_device *pdev)
+ {
+ 	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
+ 	struct max8925_onkey_info *info;
+diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c
+index 8db64f652d7a..2613b2f3174e 100644
+--- a/drivers/input/misc/max8997_haptic.c
++++ b/drivers/input/misc/max8997_haptic.c
+@@ -241,7 +241,7 @@ static void max8997_haptic_close(struct input_dev *dev)
+ 	max8997_haptic_disable(chip);
+ }
+ 
+-static int __devinit max8997_haptic_probe(struct platform_device *pdev)
++static int max8997_haptic_probe(struct platform_device *pdev)
+ {
+ 	struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+ 	const struct max8997_platform_data *pdata =
+diff --git a/drivers/input/misc/mc13783-pwrbutton.c b/drivers/input/misc/mc13783-pwrbutton.c
+index a0c35a058318..a50ad911c7f5 100644
+--- a/drivers/input/misc/mc13783-pwrbutton.c
++++ b/drivers/input/misc/mc13783-pwrbutton.c
+@@ -89,7 +89,7 @@ static irqreturn_t button_irq(int irq, void *_priv)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit mc13783_pwrbutton_probe(struct platform_device *pdev)
++static int mc13783_pwrbutton_probe(struct platform_device *pdev)
+ {
+ 	const struct mc13xxx_buttons_platform_data *pdata;
+ 	struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent);
+diff --git a/drivers/input/misc/mma8450.c b/drivers/input/misc/mma8450.c
+index 050a246043dc..d4528cc47f8f 100644
+--- a/drivers/input/misc/mma8450.c
++++ b/drivers/input/misc/mma8450.c
+@@ -167,7 +167,7 @@ static void mma8450_close(struct input_polled_dev *dev)
+ /*
+  * I2C init/probing/exit functions
+  */
+-static int __devinit mma8450_probe(struct i2c_client *c,
++static int mma8450_probe(struct i2c_client *c,
+ 				   const struct i2c_device_id *id)
+ {
+ 	struct input_polled_dev *idev;
+diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c
+index ab114092b9a9..ff600565654e 100644
+--- a/drivers/input/misc/mpu3050.c
++++ b/drivers/input/misc/mpu3050.c
+@@ -257,7 +257,7 @@ static irqreturn_t mpu3050_interrupt_thread(int irq, void *data)
+  *
+  *	Called during device probe; configures the sampling method.
+  */
+-static int __devinit mpu3050_hw_init(struct mpu3050_sensor *sensor)
++static int mpu3050_hw_init(struct mpu3050_sensor *sensor)
+ {
+ 	struct i2c_client *client = sensor->client;
+ 	int ret;
+@@ -306,7 +306,7 @@ static int __devinit mpu3050_hw_init(struct mpu3050_sensor *sensor)
+  *
+  *	If present install the relevant sysfs interfaces and input device.
+  */
+-static int __devinit mpu3050_probe(struct i2c_client *client,
++static int mpu3050_probe(struct i2c_client *client,
+ 				   const struct i2c_device_id *id)
+ {
+ 	struct mpu3050_sensor *sensor;
+diff --git a/drivers/input/misc/pcap_keys.c b/drivers/input/misc/pcap_keys.c
+index afd3f5ae17f9..56d03ac3a430 100644
+--- a/drivers/input/misc/pcap_keys.c
++++ b/drivers/input/misc/pcap_keys.c
+@@ -48,7 +48,7 @@ static irqreturn_t pcap_keys_handler(int irq, void *_pcap_keys)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit pcap_keys_probe(struct platform_device *pdev)
++static int pcap_keys_probe(struct platform_device *pdev)
+ {
+ 	int err = -ENOMEM;
+ 	struct pcap_keys *pcap_keys;
+diff --git a/drivers/input/misc/pcf50633-input.c b/drivers/input/misc/pcf50633-input.c
+index 3896b0f8e9bb..8efb898863c7 100644
+--- a/drivers/input/misc/pcf50633-input.c
++++ b/drivers/input/misc/pcf50633-input.c
+@@ -53,7 +53,7 @@ pcf50633_input_irq(int irq, void *data)
+ 	input_sync(input->input_dev);
+ }
+ 
+-static int __devinit pcf50633_input_probe(struct platform_device *pdev)
++static int pcf50633_input_probe(struct platform_device *pdev)
+ {
+ 	struct pcf50633_input *input;
+ 	struct input_dev *input_dev;
+diff --git a/drivers/input/misc/pcf8574_keypad.c b/drivers/input/misc/pcf8574_keypad.c
+index 6c480bf58456..dbe2093c284b 100644
+--- a/drivers/input/misc/pcf8574_keypad.c
++++ b/drivers/input/misc/pcf8574_keypad.c
+@@ -82,7 +82,7 @@ static irqreturn_t pcf8574_kp_irq_handler(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit pcf8574_kp_probe(struct i2c_client *client, const struct i2c_device_id *id)
++static int pcf8574_kp_probe(struct i2c_client *client, const struct i2c_device_id *id)
+ {
+ 	int i, ret;
+ 	struct input_dev *idev;
+diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c
+index 17d6555fec72..943b461aaf3f 100644
+--- a/drivers/input/misc/pcspkr.c
++++ b/drivers/input/misc/pcspkr.c
+@@ -63,7 +63,7 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c
+ 	return 0;
+ }
+ 
+-static int __devinit pcspkr_probe(struct platform_device *dev)
++static int pcspkr_probe(struct platform_device *dev)
+ {
+ 	struct input_dev *pcspkr_dev;
+ 	int err;
+diff --git a/drivers/input/misc/pm8xxx-vibrator.c b/drivers/input/misc/pm8xxx-vibrator.c
+index 2e0a3bfeff07..1ac2b1f548a9 100644
+--- a/drivers/input/misc/pm8xxx-vibrator.c
++++ b/drivers/input/misc/pm8xxx-vibrator.c
+@@ -178,7 +178,7 @@ static int pm8xxx_vib_play_effect(struct input_dev *dev, void *data,
+ 	return 0;
+ }
+ 
+-static int __devinit pm8xxx_vib_probe(struct platform_device *pdev)
++static int pm8xxx_vib_probe(struct platform_device *pdev)
+ 
+ {
+ 	struct pm8xxx_vib *vib;
+diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c
+index b2396e2ad369..26e49acefa9c 100644
+--- a/drivers/input/misc/pmic8xxx-pwrkey.c
++++ b/drivers/input/misc/pmic8xxx-pwrkey.c
+@@ -81,7 +81,7 @@ static int pmic8xxx_pwrkey_resume(struct device *dev)
+ static SIMPLE_DEV_PM_OPS(pm8xxx_pwr_key_pm_ops,
+ 		pmic8xxx_pwrkey_suspend, pmic8xxx_pwrkey_resume);
+ 
+-static int __devinit pmic8xxx_pwrkey_probe(struct platform_device *pdev)
++static int pmic8xxx_pwrkey_probe(struct platform_device *pdev)
+ {
+ 	struct input_dev *pwr;
+ 	int key_release_irq = platform_get_irq(pdev, 0);
+diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c
+index d40c2f630d5e..48b505bddb1c 100644
+--- a/drivers/input/misc/pwm-beeper.c
++++ b/drivers/input/misc/pwm-beeper.c
+@@ -65,7 +65,7 @@ static int pwm_beeper_event(struct input_dev *input,
+ 	return 0;
+ }
+ 
+-static int __devinit pwm_beeper_probe(struct platform_device *pdev)
++static int pwm_beeper_probe(struct platform_device *pdev)
+ {
+ 	unsigned long pwm_id = (unsigned long)pdev->dev.platform_data;
+ 	struct pwm_beeper *beeper;
+diff --git a/drivers/input/misc/rb532_button.c b/drivers/input/misc/rb532_button.c
+index 718dd8367b6a..91f71d6be57b 100644
+--- a/drivers/input/misc/rb532_button.c
++++ b/drivers/input/misc/rb532_button.c
+@@ -51,7 +51,7 @@ static void rb532_button_poll(struct input_polled_dev *poll_dev)
+ 	input_sync(poll_dev->input);
+ }
+ 
+-static int __devinit rb532_button_probe(struct platform_device *pdev)
++static int rb532_button_probe(struct platform_device *pdev)
+ {
+ 	struct input_polled_dev *poll_dev;
+ 	int error;
+diff --git a/drivers/input/misc/retu-pwrbutton.c b/drivers/input/misc/retu-pwrbutton.c
+index 4500027d82a0..389e84e26a9a 100644
+--- a/drivers/input/misc/retu-pwrbutton.c
++++ b/drivers/input/misc/retu-pwrbutton.c
+@@ -42,7 +42,7 @@ static irqreturn_t retu_pwrbutton_irq(int irq, void *_pwr)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit retu_pwrbutton_probe(struct platform_device *pdev)
++static int retu_pwrbutton_probe(struct platform_device *pdev)
+ {
+ 	struct retu_dev *rdev = dev_get_drvdata(pdev->dev.parent);
+ 	struct input_dev *idev;
+diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c
+index b183a0e7a21a..cd3c363f7e2b 100644
+--- a/drivers/input/misc/rotary_encoder.c
++++ b/drivers/input/misc/rotary_encoder.c
+@@ -149,8 +149,7 @@ static struct of_device_id rotary_encoder_of_match[] = {
+ };
+ MODULE_DEVICE_TABLE(of, rotary_encoder_of_match);
+ 
+-static struct rotary_encoder_platform_data * __devinit
+-rotary_encoder_parse_dt(struct device *dev)
++static struct rotary_encoder_platform_data *rotary_encoder_parse_dt(struct device *dev)
+ {
+ 	const struct of_device_id *of_id =
+ 				of_match_device(rotary_encoder_of_match, dev);
+@@ -192,7 +191,7 @@ rotary_encoder_parse_dt(struct device *dev)
+ }
+ #endif
+ 
+-static int __devinit rotary_encoder_probe(struct platform_device *pdev)
++static int rotary_encoder_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	const struct rotary_encoder_platform_data *pdata = dev_get_platdata(dev);
+diff --git a/drivers/input/misc/sgi_btns.c b/drivers/input/misc/sgi_btns.c
+index fd731e86e316..22ccd3f35607 100644
+--- a/drivers/input/misc/sgi_btns.c
++++ b/drivers/input/misc/sgi_btns.c
+@@ -91,7 +91,7 @@ static void handle_buttons(struct input_polled_dev *dev)
+ 	}
+ }
+ 
+-static int __devinit sgi_buttons_probe(struct platform_device *pdev)
++static int sgi_buttons_probe(struct platform_device *pdev)
+ {
+ 	struct buttons_dev *bdev;
+ 	struct input_polled_dev *poll_dev;
+diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c
+index b9c870251f14..d0239b496399 100644
+--- a/drivers/input/misc/sparcspkr.c
++++ b/drivers/input/misc/sparcspkr.c
+@@ -139,7 +139,7 @@ static int grover_spkr_event(struct input_dev *dev, unsigned int type, unsigned
+ 	return 0;
+ }
+ 
+-static int __devinit sparcspkr_probe(struct device *dev)
++static int sparcspkr_probe(struct device *dev)
+ {
+ 	struct sparcspkr_state *state = dev_get_drvdata(dev);
+ 	struct input_dev *input_dev;
+@@ -182,7 +182,7 @@ static void sparcspkr_shutdown(struct platform_device *dev)
+ 	state->event(input_dev, EV_SND, SND_BELL, 0);
+ }
+ 
+-static int __devinit bbc_beep_probe(struct platform_device *op)
++static int bbc_beep_probe(struct platform_device *op)
+ {
+ 	struct sparcspkr_state *state;
+ 	struct bbc_beep_info *info;
+@@ -267,7 +267,7 @@ static struct platform_driver bbc_beep_driver = {
+ 	.shutdown	= sparcspkr_shutdown,
+ };
+ 
+-static int __devinit grover_beep_probe(struct platform_device *op)
++static int grover_beep_probe(struct platform_device *op)
+ {
+ 	struct sparcspkr_state *state;
+ 	struct grover_beep_info *info;
+diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c
+index 29f2207c5d04..21030266bb3f 100644
+--- a/drivers/input/misc/twl4030-vibra.c
++++ b/drivers/input/misc/twl4030-vibra.c
+@@ -207,7 +207,7 @@ static bool twl4030_vibra_check_coexist(struct twl4030_vibra_data *pdata,
+ 	return false;
+ }
+ 
+-static int __devinit twl4030_vibra_probe(struct platform_device *pdev)
++static int twl4030_vibra_probe(struct platform_device *pdev)
+ {
+ 	struct twl4030_vibra_data *pdata = pdev->dev.platform_data;
+ 	struct device_node *twl4030_core_node = pdev->dev.parent->of_node;
+diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c
+index 463e96380def..4b650e43fdd9 100644
+--- a/drivers/input/misc/twl6040-vibra.c
++++ b/drivers/input/misc/twl6040-vibra.c
+@@ -255,7 +255,7 @@ static int twl6040_vibra_suspend(struct device *dev)
+ 
+ static SIMPLE_DEV_PM_OPS(twl6040_vibra_pm_ops, twl6040_vibra_suspend, NULL);
+ 
+-static int __devinit twl6040_vibra_probe(struct platform_device *pdev)
++static int twl6040_vibra_probe(struct platform_device *pdev)
+ {
+ 	struct twl6040_vibra_data *pdata = pdev->dev.platform_data;
+ 	struct device *twl6040_core_dev = pdev->dev.parent;
+diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
+index 3f9ad238e4e9..46d79c516854 100644
+--- a/drivers/input/misc/wistron_btns.c
++++ b/drivers/input/misc/wistron_btns.c
+@@ -170,7 +170,7 @@ static u16 bios_pop_queue(void)
+ 	return regs.eax;
+ }
+ 
+-static void __devinit bios_attach(void)
++static void bios_attach(void)
+ {
+ 	struct regs regs;
+ 
+@@ -190,7 +190,7 @@ static void bios_detach(void)
+ 	call_bios(®s);
+ }
+ 
+-static u8 __devinit bios_get_cmos_address(void)
++static u8 bios_get_cmos_address(void)
+ {
+ 	struct regs regs;
+ 
+@@ -202,7 +202,7 @@ static u8 __devinit bios_get_cmos_address(void)
+ 	return regs.ecx;
+ }
+ 
+-static u16 __devinit bios_get_default_setting(u8 subsys)
++static u16 bios_get_default_setting(u8 subsys)
+ {
+ 	struct regs regs;
+ 
+@@ -1052,7 +1052,7 @@ static struct led_classdev wistron_wifi_led = {
+ 	.brightness_set		= wistron_wifi_led_set,
+ };
+ 
+-static void __devinit wistron_led_init(struct device *parent)
++static void wistron_led_init(struct device *parent)
+ {
+ 	if (leds_present & FE_WIFI_LED) {
+ 		u16 wifi = bios_get_default_setting(WIFI);
+@@ -1168,7 +1168,7 @@ static void wistron_poll(struct input_polled_dev *dev)
+ 		dev->poll_interval = POLL_INTERVAL_DEFAULT;
+ }
+ 
+-static int __devinit wistron_setup_keymap(struct input_dev *dev,
++static int wistron_setup_keymap(struct input_dev *dev,
+ 					  struct key_entry *entry)
+ {
+ 	switch (entry->type) {
+@@ -1199,7 +1199,7 @@ static int __devinit wistron_setup_keymap(struct input_dev *dev,
+ 	return 0;
+ }
+ 
+-static int __devinit setup_input_dev(void)
++static int setup_input_dev(void)
+ {
+ 	struct input_dev *input_dev;
+ 	int error;
+@@ -1237,7 +1237,7 @@ static int __devinit setup_input_dev(void)
+ 
+ /* Driver core */
+ 
+-static int __devinit wistron_probe(struct platform_device *dev)
++static int wistron_probe(struct platform_device *dev)
+ {
+ 	int err;
+ 
+diff --git a/drivers/input/misc/wm831x-on.c b/drivers/input/misc/wm831x-on.c
+index 3a12951ad7fb..de7751e1b13c 100644
+--- a/drivers/input/misc/wm831x-on.c
++++ b/drivers/input/misc/wm831x-on.c
+@@ -69,7 +69,7 @@ static irqreturn_t wm831x_on_irq(int irq, void *data)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit wm831x_on_probe(struct platform_device *pdev)
++static int wm831x_on_probe(struct platform_device *pdev)
+ {
+ 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
+ 	struct wm831x_on *wm831x_on;
+diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c
+index 6f7d99013031..e21c1816a8f9 100644
+--- a/drivers/input/misc/xen-kbdfront.c
++++ b/drivers/input/misc/xen-kbdfront.c
+@@ -104,7 +104,7 @@ static irqreturn_t input_handler(int rq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit xenkbd_probe(struct xenbus_device *dev,
++static int xenkbd_probe(struct xenbus_device *dev,
+ 				  const struct xenbus_device_id *id)
+ {
+ 	int ret, i, abs;
+diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c
+index b3a8aa95a2d8..8e1fe82e16b7 100644
+--- a/drivers/input/mouse/gpio_mouse.c
++++ b/drivers/input/mouse/gpio_mouse.c
+@@ -46,7 +46,7 @@ static void gpio_mouse_scan(struct input_polled_dev *dev)
+ 	input_sync(input);
+ }
+ 
+-static int __devinit gpio_mouse_probe(struct platform_device *pdev)
++static int gpio_mouse_probe(struct platform_device *pdev)
+ {
+ 	struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data;
+ 	struct input_polled_dev *input_poll;
+diff --git a/drivers/input/mouse/maplemouse.c b/drivers/input/mouse/maplemouse.c
+index 03ccf02c5475..3541f362866b 100644
+--- a/drivers/input/mouse/maplemouse.c
++++ b/drivers/input/mouse/maplemouse.c
+@@ -64,7 +64,7 @@ static void dc_mouse_close(struct input_dev *dev)
+ }
+ 
+ /* allow the mouse to be used */
+-static int __devinit probe_maple_mouse(struct device *dev)
++static int probe_maple_mouse(struct device *dev)
+ {
+ 	struct maple_device *mdev = to_maple_dev(dev);
+ 	struct maple_driver *mdrv = to_maple_driver(dev->driver);
+diff --git a/drivers/input/mouse/navpoint.c b/drivers/input/mouse/navpoint.c
+index ac4e0771d05a..f51df6bfc52b 100644
+--- a/drivers/input/mouse/navpoint.c
++++ b/drivers/input/mouse/navpoint.c
+@@ -206,7 +206,7 @@ static void navpoint_close(struct input_dev *input)
+ 	navpoint_down(navpoint);
+ }
+ 
+-static int __devinit navpoint_probe(struct platform_device *pdev)
++static int navpoint_probe(struct platform_device *pdev)
+ {
+ 	const struct navpoint_platform_data *pdata =
+ 					dev_get_platdata(&pdev->dev);
+diff --git a/drivers/input/mouse/pxa930_trkball.c b/drivers/input/mouse/pxa930_trkball.c
+index 953a0481efc1..ed808fce0ac0 100644
+--- a/drivers/input/mouse/pxa930_trkball.c
++++ b/drivers/input/mouse/pxa930_trkball.c
+@@ -143,7 +143,7 @@ static void pxa930_trkball_close(struct input_dev *dev)
+ 	pxa930_trkball_disable(trkball);
+ }
+ 
+-static int __devinit pxa930_trkball_probe(struct platform_device *pdev)
++static int pxa930_trkball_probe(struct platform_device *pdev)
+ {
+ 	struct pxa930_trkball *trkball;
+ 	struct input_dev *input;
+diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c
+index fa8f162cbee3..007c378bd694 100644
+--- a/drivers/input/mouse/synaptics_i2c.c
++++ b/drivers/input/mouse/synaptics_i2c.c
+@@ -535,7 +535,7 @@ static struct synaptics_i2c *synaptics_i2c_touch_create(struct i2c_client *clien
+ 	return touch;
+ }
+ 
+-static int __devinit synaptics_i2c_probe(struct i2c_client *client,
++static int synaptics_i2c_probe(struct i2c_client *client,
+ 			       const struct i2c_device_id *dev_id)
+ {
+ 	int ret;
+diff --git a/drivers/input/serio/altera_ps2.c b/drivers/input/serio/altera_ps2.c
+index 50da8e5634c3..ea46ddcf2ed5 100644
+--- a/drivers/input/serio/altera_ps2.c
++++ b/drivers/input/serio/altera_ps2.c
+@@ -81,7 +81,7 @@ static void altera_ps2_close(struct serio *io)
+ /*
+  * Add one device to this driver.
+  */
+-static int __devinit altera_ps2_probe(struct platform_device *pdev)
++static int altera_ps2_probe(struct platform_device *pdev)
+ {
+ 	struct ps2if *ps2if;
+ 	struct serio *serio;
+diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c
+index beb08160b39e..7c502c391bbc 100644
+--- a/drivers/input/serio/ambakmi.c
++++ b/drivers/input/serio/ambakmi.c
+@@ -107,7 +107,7 @@ static void amba_kmi_close(struct serio *io)
+ 	clk_disable_unprepare(kmi->clk);
+ }
+ 
+-static int __devinit amba_kmi_probe(struct amba_device *dev,
++static int amba_kmi_probe(struct amba_device *dev,
+ 	const struct amba_id *id)
+ {
+ 	struct amba_kmi_port *kmi;
+diff --git a/drivers/input/serio/arc_ps2.c b/drivers/input/serio/arc_ps2.c
+index 72fda8ff4e10..e618c2a825aa 100644
+--- a/drivers/input/serio/arc_ps2.c
++++ b/drivers/input/serio/arc_ps2.c
+@@ -123,7 +123,7 @@ static void arc_ps2_close(struct serio *io)
+ 		  port->status_addr);
+ }
+ 
+-static void __iomem * __devinit arc_ps2_calc_addr(struct arc_ps2_data *arc_ps2,
++static void __iomem *arc_ps2_calc_addr(struct arc_ps2_data *arc_ps2,
+ 						  int index, bool status)
+ {
+ 	void __iomem *addr;
+@@ -135,7 +135,7 @@ static void __iomem * __devinit arc_ps2_calc_addr(struct arc_ps2_data *arc_ps2,
+ 	return addr;
+ }
+ 
+-static void __devinit arc_ps2_inhibit_ports(struct arc_ps2_data *arc_ps2)
++static void arc_ps2_inhibit_ports(struct arc_ps2_data *arc_ps2)
+ {
+ 	void __iomem *addr;
+ 	u32 val;
+@@ -149,7 +149,7 @@ static void __devinit arc_ps2_inhibit_ports(struct arc_ps2_data *arc_ps2)
+ 	}
+ }
+ 
+-static int __devinit arc_ps2_create_port(struct platform_device *pdev,
++static int arc_ps2_create_port(struct platform_device *pdev,
+ 					 struct arc_ps2_data *arc_ps2,
+ 					 int index)
+ {
+@@ -180,7 +180,7 @@ static int __devinit arc_ps2_create_port(struct platform_device *pdev,
+ 	return 0;
+ }
+ 
+-static int __devinit arc_ps2_probe(struct platform_device *pdev)
++static int arc_ps2_probe(struct platform_device *pdev)
+ {
+ 	struct arc_ps2_data *arc_ps2;
+ 	struct resource *res;
+diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c
+index 64bcd1559c68..e8a8748bae6f 100644
+--- a/drivers/input/serio/ct82c710.c
++++ b/drivers/input/serio/ct82c710.c
+@@ -175,7 +175,7 @@ static int __init ct82c710_detect(void)
+ 	return 0;
+ }
+ 
+-static int __devinit ct82c710_probe(struct platform_device *dev)
++static int ct82c710_probe(struct platform_device *dev)
+ {
+ 	ct82c710_port = kzalloc(sizeof(struct serio), GFP_KERNEL);
+ 	if (!ct82c710_port)
+diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c
+index 49cb7ca55ff6..a36a4667ddae 100644
+--- a/drivers/input/serio/gscps2.c
++++ b/drivers/input/serio/gscps2.c
+@@ -327,7 +327,7 @@ static void gscps2_close(struct serio *port)
+  * @return: success/error report
+  */
+ 
+-static int __devinit gscps2_probe(struct parisc_device *dev)
++static int gscps2_probe(struct parisc_device *dev)
+ {
+ 	struct gscps2port *ps2port;
+ 	struct serio *serio;
+diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h
+index 3f6c835ae005..c11748575786 100644
+--- a/drivers/input/serio/i8042-sparcio.h
++++ b/drivers/input/serio/i8042-sparcio.h
+@@ -49,7 +49,7 @@ static inline void i8042_write_command(int val)
+ #define OBP_PS2MS_NAME1		"kdmouse"
+ #define OBP_PS2MS_NAME2		"mouse"
+ 
+-static int __devinit sparc_i8042_probe(struct platform_device *op)
++static int sparc_i8042_probe(struct platform_device *op)
+ {
+ 	struct device_node *dp = op->dev.of_node;
+ 
+diff --git a/drivers/input/serio/maceps2.c b/drivers/input/serio/maceps2.c
+index 2226277089db..057240e3a74a 100644
+--- a/drivers/input/serio/maceps2.c
++++ b/drivers/input/serio/maceps2.c
+@@ -116,7 +116,7 @@ static void maceps2_close(struct serio *dev)
+ }
+ 
+ 
+-static struct serio * __devinit maceps2_allocate_port(int idx)
++static struct serio *maceps2_allocate_port(int idx)
+ {
+ 	struct serio *serio;
+ 
+@@ -135,7 +135,7 @@ static struct serio * __devinit maceps2_allocate_port(int idx)
+ 	return serio;
+ }
+ 
+-static int __devinit maceps2_probe(struct platform_device *dev)
++static int maceps2_probe(struct platform_device *dev)
+ {
+ 	maceps2_port[0] = maceps2_allocate_port(0);
+ 	maceps2_port[1] = maceps2_allocate_port(1);
+diff --git a/drivers/input/serio/pcips2.c b/drivers/input/serio/pcips2.c
+index 98093731ae62..1914290674ef 100644
+--- a/drivers/input/serio/pcips2.c
++++ b/drivers/input/serio/pcips2.c
+@@ -127,7 +127,7 @@ static void pcips2_close(struct serio *io)
+ 	free_irq(ps2if->dev->irq, ps2if);
+ }
+ 
+-static int __devinit pcips2_probe(struct pci_dev *dev, const struct pci_device_id *id)
++static int pcips2_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	struct pcips2_data *ps2if;
+ 	struct serio *serio;
+diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c
+index 530488006105..3c58f6b2fe54 100644
+--- a/drivers/input/serio/q40kbd.c
++++ b/drivers/input/serio/q40kbd.c
+@@ -122,7 +122,7 @@ static void q40kbd_close(struct serio *port)
+ 	q40kbd_flush(q40kbd);
+ }
+ 
+-static int __devinit q40kbd_probe(struct platform_device *pdev)
++static int q40kbd_probe(struct platform_device *pdev)
+ {
+ 	struct q40kbd *q40kbd;
+ 	struct serio *port;
+diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c
+index a5100d455e30..d64f053ae3ee 100644
+--- a/drivers/input/serio/rpckbd.c
++++ b/drivers/input/serio/rpckbd.c
+@@ -114,7 +114,7 @@ static void rpckbd_close(struct serio *port)
+  * Allocate and initialize serio structure for subsequent registration
+  * with serio core.
+  */
+-static int __devinit rpckbd_probe(struct platform_device *dev)
++static int rpckbd_probe(struct platform_device *dev)
+ {
+ 	struct rpckbd_data *rpckbd;
+ 	struct serio *serio;
+diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
+index 4aacf4f94e3e..4458ec3b1d2a 100644
+--- a/drivers/input/serio/sa1111ps2.c
++++ b/drivers/input/serio/sa1111ps2.c
+@@ -193,7 +193,7 @@ static void ps2_close(struct serio *io)
+ /*
+  * Clear the input buffer.
+  */
+-static void __devinit ps2_clear_input(struct ps2if *ps2if)
++static void ps2_clear_input(struct ps2if *ps2if)
+ {
+ 	int maxread = 100;
+ 
+@@ -203,7 +203,7 @@ static void __devinit ps2_clear_input(struct ps2if *ps2if)
+ 	}
+ }
+ 
+-static unsigned int __devinit ps2_test_one(struct ps2if *ps2if,
++static unsigned int ps2_test_one(struct ps2if *ps2if,
+ 					   unsigned int mask)
+ {
+ 	unsigned int val;
+@@ -220,7 +220,7 @@ static unsigned int __devinit ps2_test_one(struct ps2if *ps2if,
+  * Test the keyboard interface.  We basically check to make sure that
+  * we can drive each line to the keyboard independently of each other.
+  */
+-static int __devinit ps2_test(struct ps2if *ps2if)
++static int ps2_test(struct ps2if *ps2if)
+ {
+ 	unsigned int stat;
+ 	int ret = 0;
+@@ -251,7 +251,7 @@ static int __devinit ps2_test(struct ps2if *ps2if)
+ /*
+  * Add one device to this driver.
+  */
+-static int __devinit ps2_probe(struct sa1111_dev *dev)
++static int ps2_probe(struct sa1111_dev *dev)
+ {
+ 	struct ps2if *ps2if;
+ 	struct serio *serio;
+diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c
+index f929d8f2dc50..ed5e8e625bff 100644
+--- a/drivers/input/serio/xilinx_ps2.c
++++ b/drivers/input/serio/xilinx_ps2.c
+@@ -233,7 +233,7 @@ static void sxps2_close(struct serio *pserio)
+  * It returns 0, if the driver is bound to the PS/2 device, or a negative
+  * value if there is an error.
+  */
+-static int __devinit xps2_of_probe(struct platform_device *ofdev)
++static int xps2_of_probe(struct platform_device *ofdev)
+ {
+ 	struct resource r_irq; /* Interrupt resources */
+ 	struct resource r_mem; /* IO mem resources */
+diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c
+index e609db85bea1..183d35b9d07a 100644
+--- a/drivers/input/touchscreen/88pm860x-ts.c
++++ b/drivers/input/touchscreen/88pm860x-ts.c
+@@ -115,7 +115,7 @@ static void pm860x_touch_close(struct input_dev *dev)
+ }
+ 
+ #ifdef CONFIG_OF
+-static int __devinit pm860x_touch_dt_init(struct platform_device *pdev,
++static int pm860x_touch_dt_init(struct platform_device *pdev,
+ 					  struct pm860x_chip *chip,
+ 					  int *res_x)
+ {
+@@ -169,7 +169,7 @@ static int __devinit pm860x_touch_dt_init(struct platform_device *pdev,
+ #define pm860x_touch_dt_init(x, y, z)	(-1)
+ #endif
+ 
+-static int __devinit pm860x_touch_probe(struct platform_device *pdev)
++static int pm860x_touch_probe(struct platform_device *pdev)
+ {
+ 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+ 	struct pm860x_touch_pdata *pdata = pdev->dev.platform_data;
+diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c
+index d2df6a48ba65..61c0a98d6dd7 100644
+--- a/drivers/input/touchscreen/ad7877.c
++++ b/drivers/input/touchscreen/ad7877.c
+@@ -682,7 +682,7 @@ static void ad7877_setup_ts_def_msg(struct spi_device *spi, struct ad7877 *ts)
+ 	}
+ }
+ 
+-static int __devinit ad7877_probe(struct spi_device *spi)
++static int ad7877_probe(struct spi_device *spi)
+ {
+ 	struct ad7877			*ts;
+ 	struct input_dev		*input_dev;
+diff --git a/drivers/input/touchscreen/ad7879-i2c.c b/drivers/input/touchscreen/ad7879-i2c.c
+index 850c95d69198..b155770c521d 100644
+--- a/drivers/input/touchscreen/ad7879-i2c.c
++++ b/drivers/input/touchscreen/ad7879-i2c.c
+@@ -54,7 +54,7 @@ static const struct ad7879_bus_ops ad7879_i2c_bus_ops = {
+ 	.write		= ad7879_i2c_write,
+ };
+ 
+-static int __devinit ad7879_i2c_probe(struct i2c_client *client,
++static int ad7879_i2c_probe(struct i2c_client *client,
+ 				      const struct i2c_device_id *id)
+ {
+ 	struct ad7879 *ts;
+diff --git a/drivers/input/touchscreen/ad7879-spi.c b/drivers/input/touchscreen/ad7879-spi.c
+index 86b0fdb6046b..c9b73e0b6528 100644
+--- a/drivers/input/touchscreen/ad7879-spi.c
++++ b/drivers/input/touchscreen/ad7879-spi.c
+@@ -110,7 +110,7 @@ static const struct ad7879_bus_ops ad7879_spi_bus_ops = {
+ 	.write		= ad7879_spi_write,
+ };
+ 
+-static int __devinit ad7879_spi_probe(struct spi_device *spi)
++static int ad7879_spi_probe(struct spi_device *spi)
+ {
+ 	struct ad7879 *ts;
+ 	int err;
+diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
+index 560484de0bfb..156a36b43bff 100644
+--- a/drivers/input/touchscreen/ads7846.c
++++ b/drivers/input/touchscreen/ads7846.c
+@@ -955,7 +955,7 @@ static int ads7846_resume(struct device *dev)
+ 
+ static SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume);
+ 
+-static int __devinit ads7846_setup_pendown(struct spi_device *spi,
++static int ads7846_setup_pendown(struct spi_device *spi,
+ 					   struct ads7846 *ts)
+ {
+ 	struct ads7846_platform_data *pdata = spi->dev.platform_data;
+@@ -997,7 +997,7 @@ static int __devinit ads7846_setup_pendown(struct spi_device *spi,
+  * Set up the transfers to read touchscreen state; this assumes we
+  * use formula #2 for pressure, not #3.
+  */
+-static void __devinit ads7846_setup_spi_msg(struct ads7846 *ts,
++static void ads7846_setup_spi_msg(struct ads7846 *ts,
+ 				const struct ads7846_platform_data *pdata)
+ {
+ 	struct spi_message *m = &ts->msg[0];
+@@ -1196,7 +1196,7 @@ static void __devinit ads7846_setup_spi_msg(struct ads7846 *ts,
+ 	spi_message_add_tail(x, m);
+ }
+ 
+-static int __devinit ads7846_probe(struct spi_device *spi)
++static int ads7846_probe(struct spi_device *spi)
+ {
+ 	struct ads7846 *ts;
+ 	struct ads7846_packet *packet;
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 6199303d9d3c..cd961bcf9f0e 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -1095,7 +1095,7 @@ static void mxt_input_close(struct input_dev *dev)
+ 	mxt_stop(data);
+ }
+ 
+-static int __devinit mxt_probe(struct i2c_client *client,
++static int mxt_probe(struct i2c_client *client,
+ 		const struct i2c_device_id *id)
+ {
+ 	const struct mxt_platform_data *pdata = client->dev.platform_data;
+diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c
+index 53712b9142a5..4b4f5ab76e5c 100644
+--- a/drivers/input/touchscreen/atmel_tsadcc.c
++++ b/drivers/input/touchscreen/atmel_tsadcc.c
+@@ -177,7 +177,7 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
+  * The functions for inserting/removing us as a module.
+  */
+ 
+-static int __devinit atmel_tsadcc_probe(struct platform_device *pdev)
++static int atmel_tsadcc_probe(struct platform_device *pdev)
+ {
+ 	struct atmel_tsadcc	*ts_dev;
+ 	struct input_dev	*input_dev;
+diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c
+index 912926dd97c0..cdd233f3ed8e 100644
+--- a/drivers/input/touchscreen/auo-pixcir-ts.c
++++ b/drivers/input/touchscreen/auo-pixcir-ts.c
+@@ -286,7 +286,7 @@ static int auo_pixcir_power_mode(struct auo_pixcir_ts *ts, int mode)
+ 	return 0;
+ }
+ 
+-static __devinit int auo_pixcir_int_config(struct auo_pixcir_ts *ts,
++static int auo_pixcir_int_config(struct auo_pixcir_ts *ts,
+ 					   int int_setting)
+ {
+ 	struct i2c_client *client = ts->client;
+@@ -482,7 +482,7 @@ static int auo_pixcir_resume(struct device *dev)
+ static SIMPLE_DEV_PM_OPS(auo_pixcir_pm_ops, auo_pixcir_suspend,
+ 			 auo_pixcir_resume);
+ 
+-static int __devinit auo_pixcir_probe(struct i2c_client *client,
++static int auo_pixcir_probe(struct i2c_client *client,
+ 				      const struct i2c_device_id *id)
+ {
+ 	const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data;
+diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c
+index c2be1fe51923..bf90391aae59 100644
+--- a/drivers/input/touchscreen/bu21013_ts.c
++++ b/drivers/input/touchscreen/bu21013_ts.c
+@@ -429,7 +429,7 @@ static void bu21013_free_irq(struct bu21013_ts_data *bu21013_data)
+  * This function used to initializes the i2c-client touchscreen
+  * driver and returns integer.
+  */
+-static int __devinit bu21013_probe(struct i2c_client *client,
++static int bu21013_probe(struct i2c_client *client,
+ 					const struct i2c_device_id *id)
+ {
+ 	struct bu21013_ts_data *bu21013_data;
+diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c
+index 9a2044f978ae..0aaa24ec6f51 100644
+--- a/drivers/input/touchscreen/cy8ctmg110_ts.c
++++ b/drivers/input/touchscreen/cy8ctmg110_ts.c
+@@ -175,7 +175,7 @@ static irqreturn_t cy8ctmg110_irq_thread(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit cy8ctmg110_probe(struct i2c_client *client,
++static int cy8ctmg110_probe(struct i2c_client *client,
+ 					const struct i2c_device_id *id)
+ {
+ 	const struct cy8ctmg110_pdata *pdata = client->dev.platform_data;
+diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c
+index 1a7aca935b26..167e9834e597 100644
+--- a/drivers/input/touchscreen/cyttsp_i2c.c
++++ b/drivers/input/touchscreen/cyttsp_i2c.c
+@@ -81,7 +81,7 @@ static const struct cyttsp_bus_ops cyttsp_i2c_bus_ops = {
+ 	.read           = cyttsp_i2c_read_block_data,
+ };
+ 
+-static int __devinit cyttsp_i2c_probe(struct i2c_client *client,
++static int cyttsp_i2c_probe(struct i2c_client *client,
+ 				      const struct i2c_device_id *id)
+ {
+ 	struct cyttsp *ts;
+diff --git a/drivers/input/touchscreen/cyttsp_spi.c b/drivers/input/touchscreen/cyttsp_spi.c
+index 915af4cfe2b2..8ea29d9ae3bc 100644
+--- a/drivers/input/touchscreen/cyttsp_spi.c
++++ b/drivers/input/touchscreen/cyttsp_spi.c
+@@ -147,7 +147,7 @@ static const struct cyttsp_bus_ops cyttsp_spi_bus_ops = {
+ 	.read		= cyttsp_spi_read_block_data,
+ };
+ 
+-static int __devinit cyttsp_spi_probe(struct spi_device *spi)
++static int cyttsp_spi_probe(struct spi_device *spi)
+ {
+ 	struct cyttsp *ts;
+ 	int error;
+diff --git a/drivers/input/touchscreen/da9034-ts.c b/drivers/input/touchscreen/da9034-ts.c
+index ec156a6bf59d..53a95244a14c 100644
+--- a/drivers/input/touchscreen/da9034-ts.c
++++ b/drivers/input/touchscreen/da9034-ts.c
+@@ -297,7 +297,7 @@ static void da9034_touch_close(struct input_dev *dev)
+ }
+ 
+ 
+-static int __devinit da9034_touch_probe(struct platform_device *pdev)
++static int da9034_touch_probe(struct platform_device *pdev)
+ {
+ 	struct da9034_touch_pdata *pdata = pdev->dev.platform_data;
+ 	struct da9034_touch *touch;
+diff --git a/drivers/input/touchscreen/da9052_tsi.c b/drivers/input/touchscreen/da9052_tsi.c
+index 5dfb39b21c90..8a493b962db3 100644
+--- a/drivers/input/touchscreen/da9052_tsi.c
++++ b/drivers/input/touchscreen/da9052_tsi.c
+@@ -143,7 +143,7 @@ static void da9052_ts_pen_work(struct work_struct *work)
+ 	}
+ }
+ 
+-static int __devinit da9052_ts_configure_gpio(struct da9052 *da9052)
++static int da9052_ts_configure_gpio(struct da9052 *da9052)
+ {
+ 	int error;
+ 
+@@ -162,7 +162,7 @@ static int __devinit da9052_ts_configure_gpio(struct da9052 *da9052)
+ 	return 0;
+ }
+ 
+-static int __devinit da9052_configure_tsi(struct da9052_tsi *tsi)
++static int da9052_configure_tsi(struct da9052_tsi *tsi)
+ {
+ 	int error;
+ 
+@@ -229,7 +229,7 @@ static void da9052_ts_input_close(struct input_dev *input_dev)
+ 	da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG, 1 << 1, 0);
+ }
+ 
+-static int __devinit da9052_ts_probe(struct platform_device *pdev)
++static int da9052_ts_probe(struct platform_device *pdev)
+ {
+ 	struct da9052 *da9052;
+ 	struct da9052_tsi *tsi;
+diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
+index 65ed9d958e5f..677e78804b79 100644
+--- a/drivers/input/touchscreen/edt-ft5x06.c
++++ b/drivers/input/touchscreen/edt-ft5x06.c
+@@ -575,7 +575,7 @@ static const struct file_operations debugfs_raw_data_fops = {
+ 	.read = edt_ft5x06_debugfs_raw_data_read,
+ };
+ 
+-static void __devinit
++static void
+ edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata,
+ 			      const char *debugfs_name)
+ {
+@@ -617,7 +617,7 @@ edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
+ 
+ 
+ 
+-static int __devinit edt_ft5x06_ts_reset(struct i2c_client *client,
++static int edt_ft5x06_ts_reset(struct i2c_client *client,
+ 					 int reset_pin)
+ {
+ 	int error;
+@@ -641,7 +641,7 @@ static int __devinit edt_ft5x06_ts_reset(struct i2c_client *client,
+ 	return 0;
+ }
+ 
+-static int __devinit edt_ft5x06_ts_identify(struct i2c_client *client,
++static int edt_ft5x06_ts_identify(struct i2c_client *client,
+ 					    char *model_name,
+ 					    char *fw_version)
+ {
+@@ -675,7 +675,7 @@ static int __devinit edt_ft5x06_ts_identify(struct i2c_client *client,
+ 	    pdata->name <= edt_ft5x06_attr_##name.limit_high)		\
+ 		edt_ft5x06_register_write(tsdata, reg, pdata->name)
+ 
+-static void __devinit
++static void
+ edt_ft5x06_ts_get_defaults(struct edt_ft5x06_ts_data *tsdata,
+ 			   const struct edt_ft5x06_platform_data *pdata)
+ {
+@@ -689,7 +689,7 @@ edt_ft5x06_ts_get_defaults(struct edt_ft5x06_ts_data *tsdata,
+ 	EDT_ATTR_CHECKSET(report_rate, WORK_REGISTER_REPORT_RATE);
+ }
+ 
+-static void __devinit
++static void
+ edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata)
+ {
+ 	tsdata->threshold = edt_ft5x06_register_read(tsdata,
+@@ -702,7 +702,7 @@ edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata)
+ 	tsdata->num_y = edt_ft5x06_register_read(tsdata, WORK_REGISTER_NUM_Y);
+ }
+ 
+-static int __devinit edt_ft5x06_ts_probe(struct i2c_client *client,
++static int edt_ft5x06_ts_probe(struct i2c_client *client,
+ 					 const struct i2c_device_id *id)
+ {
+ 	const struct edt_ft5x06_platform_data *pdata =
+diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c
+index a2d9a65e586d..a65709959fa0 100644
+--- a/drivers/input/touchscreen/eeti_ts.c
++++ b/drivers/input/touchscreen/eeti_ts.c
+@@ -154,7 +154,7 @@ static void eeti_ts_close(struct input_dev *dev)
+ 	eeti_ts_stop(priv);
+ }
+ 
+-static int __devinit eeti_ts_probe(struct i2c_client *client,
++static int eeti_ts_probe(struct i2c_client *client,
+ 				   const struct i2c_device_id *idp)
+ {
+ 	struct eeti_ts_platform_data *pdata = client->dev.platform_data;
+diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c
+index d85078d06497..f5e09ca1ffed 100644
+--- a/drivers/input/touchscreen/egalax_ts.c
++++ b/drivers/input/touchscreen/egalax_ts.c
+@@ -153,7 +153,7 @@ static int egalax_wake_up_device(struct i2c_client *client)
+ 	return 0;
+ }
+ 
+-static int __devinit egalax_firmware_version(struct i2c_client *client)
++static int egalax_firmware_version(struct i2c_client *client)
+ {
+ 	static const u8 cmd[MAX_I2C_DATA_LEN] = { 0x03, 0x03, 0xa, 0x01, 0x41 };
+ 	int ret;
+@@ -165,7 +165,7 @@ static int __devinit egalax_firmware_version(struct i2c_client *client)
+ 	return 0;
+ }
+ 
+-static int __devinit egalax_ts_probe(struct i2c_client *client,
++static int egalax_ts_probe(struct i2c_client *client,
+ 				       const struct i2c_device_id *id)
+ {
+ 	struct egalax_ts *ts;
+diff --git a/drivers/input/touchscreen/htcpen.c b/drivers/input/touchscreen/htcpen.c
+index 5cc3240139ec..32a451c89d53 100644
+--- a/drivers/input/touchscreen/htcpen.c
++++ b/drivers/input/touchscreen/htcpen.c
+@@ -102,7 +102,7 @@ static void htcpen_close(struct input_dev *dev)
+ 	synchronize_irq(HTCPEN_IRQ);
+ }
+ 
+-static int __devinit htcpen_isa_probe(struct device *dev, unsigned int id)
++static int htcpen_isa_probe(struct device *dev, unsigned int id)
+ {
+ 	struct input_dev *htcpen_dev;
+ 	int err = -EBUSY;
+diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c
+index e8fd6c26b76c..7e6221c9ea7d 100644
+--- a/drivers/input/touchscreen/ili210x.c
++++ b/drivers/input/touchscreen/ili210x.c
+@@ -180,7 +180,7 @@ static const struct attribute_group ili210x_attr_group = {
+ 	.attrs = ili210x_attributes,
+ };
+ 
+-static int __devinit ili210x_i2c_probe(struct i2c_client *client,
++static int ili210x_i2c_probe(struct i2c_client *client,
+ 				       const struct i2c_device_id *id)
+ {
+ 	struct device *dev = &client->dev;
+diff --git a/drivers/input/touchscreen/intel-mid-touch.c b/drivers/input/touchscreen/intel-mid-touch.c
+index f27364f7ad11..e413f3344edd 100644
+--- a/drivers/input/touchscreen/intel-mid-touch.c
++++ b/drivers/input/touchscreen/intel-mid-touch.c
+@@ -427,7 +427,7 @@ static irqreturn_t mrstouch_pendet_irq(int irq, void *dev_id)
+ }
+ 
+ /* Utility to read PMIC ID */
+-static int __devinit mrstouch_read_pmic_id(uint *vendor, uint *rev)
++static int mrstouch_read_pmic_id(uint *vendor, uint *rev)
+ {
+ 	int err;
+ 	u8 r;
+@@ -446,7 +446,7 @@ static int __devinit mrstouch_read_pmic_id(uint *vendor, uint *rev)
+  * Parse ADC channels to find end of the channel configured by other ADC user
+  * NEC and MAXIM requires 4 channels and FreeScale needs 18 channels
+  */
+-static int __devinit mrstouch_chan_parse(struct mrstouch_dev *tsdev)
++static int mrstouch_chan_parse(struct mrstouch_dev *tsdev)
+ {
+ 	int found = 0;
+ 	int err, i;
+@@ -478,7 +478,7 @@ static int __devinit mrstouch_chan_parse(struct mrstouch_dev *tsdev)
+ /*
+  * Writes touch screen channels to ADC address selection registers
+  */
+-static int __devinit mrstouch_ts_chan_set(uint offset)
++static int mrstouch_ts_chan_set(uint offset)
+ {
+ 	u16 chan;
+ 
+@@ -494,7 +494,7 @@ static int __devinit mrstouch_ts_chan_set(uint offset)
+ }
+ 
+ /* Initialize ADC */
+-static int __devinit mrstouch_adc_init(struct mrstouch_dev *tsdev)
++static int mrstouch_adc_init(struct mrstouch_dev *tsdev)
+ {
+ 	int err, start;
+ 	u8 ra, rm;
+@@ -568,7 +568,7 @@ static int __devinit mrstouch_adc_init(struct mrstouch_dev *tsdev)
+ 
+ 
+ /* Probe function for touch screen driver */
+-static int __devinit mrstouch_probe(struct platform_device *pdev)
++static int mrstouch_probe(struct platform_device *pdev)
+ {
+ 	struct mrstouch_dev *tsdev;
+ 	struct input_dev *input;
+diff --git a/drivers/input/touchscreen/jornada720_ts.c b/drivers/input/touchscreen/jornada720_ts.c
+index ad35c8ceac26..7ef90def6b0b 100644
+--- a/drivers/input/touchscreen/jornada720_ts.c
++++ b/drivers/input/touchscreen/jornada720_ts.c
+@@ -99,7 +99,7 @@ static irqreturn_t jornada720_ts_interrupt(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit jornada720_ts_probe(struct platform_device *pdev)
++static int jornada720_ts_probe(struct platform_device *pdev)
+ {
+ 	struct jornada_ts *jornada_ts;
+ 	struct input_dev *input_dev;
+diff --git a/drivers/input/touchscreen/lpc32xx_ts.c b/drivers/input/touchscreen/lpc32xx_ts.c
+index 8134f6100de0..39d50b7d470a 100644
+--- a/drivers/input/touchscreen/lpc32xx_ts.c
++++ b/drivers/input/touchscreen/lpc32xx_ts.c
+@@ -203,7 +203,7 @@ static void lpc32xx_ts_close(struct input_dev *dev)
+ 	lpc32xx_stop_tsc(tsc);
+ }
+ 
+-static int __devinit lpc32xx_ts_probe(struct platform_device *pdev)
++static int lpc32xx_ts_probe(struct platform_device *pdev)
+ {
+ 	struct lpc32xx_tsc *tsc;
+ 	struct input_dev *input;
+diff --git a/drivers/input/touchscreen/max11801_ts.c b/drivers/input/touchscreen/max11801_ts.c
+index e3e637f01609..ac06db6a7b05 100644
+--- a/drivers/input/touchscreen/max11801_ts.c
++++ b/drivers/input/touchscreen/max11801_ts.c
+@@ -156,7 +156,7 @@ static irqreturn_t max11801_ts_interrupt(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static void __devinit max11801_ts_phy_init(struct max11801_data *data)
++static void max11801_ts_phy_init(struct max11801_data *data)
+ {
+ 	struct i2c_client *client = data->client;
+ 
+@@ -174,7 +174,7 @@ static void __devinit max11801_ts_phy_init(struct max11801_data *data)
+ 	max11801_write_reg(client, OP_MODE_CONF_REG, 0x36);
+ }
+ 
+-static int __devinit max11801_ts_probe(struct i2c_client *client,
++static int max11801_ts_probe(struct i2c_client *client,
+ 				       const struct i2c_device_id *id)
+ {
+ 	struct max11801_data *data;
+diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c
+index 94a4ff6de3f9..c9da87bd2570 100644
+--- a/drivers/input/touchscreen/mcs5000_ts.c
++++ b/drivers/input/touchscreen/mcs5000_ts.c
+@@ -187,7 +187,7 @@ static void mcs5000_ts_phys_init(struct mcs5000_ts_data *data)
+ 			OP_MODE_ACTIVE | REPORT_RATE_80);
+ }
+ 
+-static int __devinit mcs5000_ts_probe(struct i2c_client *client,
++static int mcs5000_ts_probe(struct i2c_client *client,
+ 		const struct i2c_device_id *id)
+ {
+ 	struct mcs5000_ts_data *data;
+diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
+index 0334898f9205..633737e14e47 100644
+--- a/drivers/input/touchscreen/mms114.c
++++ b/drivers/input/touchscreen/mms114.c
+@@ -362,7 +362,7 @@ static void mms114_input_close(struct input_dev *dev)
+ }
+ 
+ #ifdef CONFIG_OF
+-static struct mms114_platform_data * __devinit mms114_parse_dt(struct device *dev)
++static struct mms114_platform_data *mms114_parse_dt(struct device *dev)
+ {
+ 	struct mms114_platform_data *pdata;
+ 	struct device_node *np = dev->of_node;
+@@ -405,7 +405,7 @@ static inline struct mms114_platform_data *mms114_parse_dt(struct device *dev)
+ }
+ #endif
+ 
+-static int __devinit mms114_probe(struct i2c_client *client,
++static int mms114_probe(struct i2c_client *client,
+ 				  const struct i2c_device_id *id)
+ {
+ 	const struct mms114_platform_data *pdata;
+diff --git a/drivers/input/touchscreen/pcap_ts.c b/drivers/input/touchscreen/pcap_ts.c
+index 97f07baa6e8f..900dc78be08d 100644
+--- a/drivers/input/touchscreen/pcap_ts.c
++++ b/drivers/input/touchscreen/pcap_ts.c
+@@ -137,7 +137,7 @@ static void pcap_ts_close(struct input_dev *dev)
+ 				pcap_ts->read_state << PCAP_ADC_TS_M_SHIFT);
+ }
+ 
+-static int __devinit pcap_ts_probe(struct platform_device *pdev)
++static int pcap_ts_probe(struct platform_device *pdev)
+ {
+ 	struct input_dev *input_dev;
+ 	struct pcap_ts *pcap_ts;
+diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
+index 4fcb63e4337b..cffea4c368ad 100644
+--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
++++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
+@@ -125,7 +125,7 @@ static int pixcir_i2c_ts_resume(struct device *dev)
+ static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops,
+ 			 pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume);
+ 
+-static int __devinit pixcir_i2c_ts_probe(struct i2c_client *client,
++static int pixcir_i2c_ts_probe(struct i2c_client *client,
+ 					 const struct i2c_device_id *id)
+ {
+ 	const struct pixcir_ts_platform_data *pdata = client->dev.platform_data;
+diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c
+index 4dda7656e077..8f2f22b612a0 100644
+--- a/drivers/input/touchscreen/s3c2410_ts.c
++++ b/drivers/input/touchscreen/s3c2410_ts.c
+@@ -238,7 +238,7 @@ static void s3c24xx_ts_select(struct s3c_adc_client *client, unsigned select)
+  * Initialise, find and allocate any resources we need to run and then
+  * register with the ADC and input systems.
+  */
+-static int __devinit s3c2410ts_probe(struct platform_device *pdev)
++static int s3c2410ts_probe(struct platform_device *pdev)
+ {
+ 	struct s3c2410_ts_mach_info *info;
+ 	struct device *dev = &pdev->dev;
+diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c
+index 5fa0ca346478..2a71dfde301c 100644
+--- a/drivers/input/touchscreen/st1232.c
++++ b/drivers/input/touchscreen/st1232.c
+@@ -139,7 +139,7 @@ static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit st1232_ts_probe(struct i2c_client *client,
++static int st1232_ts_probe(struct i2c_client *client,
+ 					const struct i2c_device_id *id)
+ {
+ 	struct st1232_ts_data *ts;
+diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c
+index f4897545ec6c..011b686798dc 100644
+--- a/drivers/input/touchscreen/stmpe-ts.c
++++ b/drivers/input/touchscreen/stmpe-ts.c
+@@ -168,7 +168,7 @@ static irqreturn_t stmpe_ts_handler(int irq, void *data)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit stmpe_init_hw(struct stmpe_touch *ts)
++static int stmpe_init_hw(struct stmpe_touch *ts)
+ {
+ 	int ret;
+ 	u8 adc_ctrl1, adc_ctrl1_mask, tsc_cfg, tsc_cfg_mask;
+@@ -308,7 +308,7 @@ static void stmpe_ts_get_platform_info(struct platform_device *pdev,
+ 	}
+ }
+ 
+-static int __devinit stmpe_input_probe(struct platform_device *pdev)
++static int stmpe_input_probe(struct platform_device *pdev)
+ {
+ 	struct stmpe_touch *ts;
+ 	struct input_dev *idev;
+diff --git a/drivers/input/touchscreen/ti_tscadc.c b/drivers/input/touchscreen/ti_tscadc.c
+index d229c741d544..bcedf2e7468c 100644
+--- a/drivers/input/touchscreen/ti_tscadc.c
++++ b/drivers/input/touchscreen/ti_tscadc.c
+@@ -303,7 +303,7 @@ static irqreturn_t tscadc_irq(int irq, void *dev)
+  * The functions for inserting/removing driver as a module.
+  */
+ 
+-static int __devinit tscadc_probe(struct platform_device *pdev)
++static int tscadc_probe(struct platform_device *pdev)
+ {
+ 	const struct tsc_data *pdata = pdev->dev.platform_data;
+ 	struct resource *res;
+diff --git a/drivers/input/touchscreen/tnetv107x-ts.c b/drivers/input/touchscreen/tnetv107x-ts.c
+index 62d57e8d49fe..63f75ebb3281 100644
+--- a/drivers/input/touchscreen/tnetv107x-ts.c
++++ b/drivers/input/touchscreen/tnetv107x-ts.c
+@@ -243,7 +243,7 @@ static void tsc_stop(struct input_dev *dev)
+ 	clk_disable(ts->clk);
+ }
+ 
+-static int __devinit tsc_probe(struct platform_device *pdev)
++static int tsc_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	struct tsc_data *ts;
+diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c
+index db472a80bcb2..20889305d46c 100644
+--- a/drivers/input/touchscreen/tsc2005.c
++++ b/drivers/input/touchscreen/tsc2005.c
+@@ -555,7 +555,7 @@ static void tsc2005_close(struct input_dev *input)
+ 	mutex_unlock(&ts->mutex);
+ }
+ 
+-static void __devinit tsc2005_setup_spi_xfer(struct tsc2005 *ts)
++static void tsc2005_setup_spi_xfer(struct tsc2005 *ts)
+ {
+ 	tsc2005_setup_read(&ts->spi_x, TSC2005_REG_X, false);
+ 	tsc2005_setup_read(&ts->spi_y, TSC2005_REG_Y, false);
+@@ -569,7 +569,7 @@ static void __devinit tsc2005_setup_spi_xfer(struct tsc2005 *ts)
+ 	spi_message_add_tail(&ts->spi_z2.spi_xfer, &ts->spi_read_msg);
+ }
+ 
+-static int __devinit tsc2005_probe(struct spi_device *spi)
++static int tsc2005_probe(struct spi_device *spi)
+ {
+ 	const struct tsc2005_platform_data *pdata = spi->dev.platform_data;
+ 	struct tsc2005 *ts;
+diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c
+index 3b195835cb03..47b41eb0e38f 100644
+--- a/drivers/input/touchscreen/tsc2007.c
++++ b/drivers/input/touchscreen/tsc2007.c
+@@ -273,7 +273,7 @@ static void tsc2007_close(struct input_dev *input_dev)
+ 	tsc2007_stop(ts);
+ }
+ 
+-static int __devinit tsc2007_probe(struct i2c_client *client,
++static int tsc2007_probe(struct i2c_client *client,
+ 				   const struct i2c_device_id *id)
+ {
+ 	struct tsc2007 *ts;
+diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
+index 780eda612547..518363d01c2f 100644
+--- a/drivers/input/touchscreen/ucb1400_ts.c
++++ b/drivers/input/touchscreen/ucb1400_ts.c
+@@ -274,7 +274,7 @@ static void ucb1400_ts_close(struct input_dev *idev)
+  * Try to probe our interrupt, rather than relying on lots of
+  * hard-coded machine dependencies.
+  */
+-static int __devinit ucb1400_ts_detect_irq(struct ucb1400_ts *ucb,
++static int ucb1400_ts_detect_irq(struct ucb1400_ts *ucb,
+ 					   struct platform_device *pdev)
+ {
+ 	unsigned long mask, timeout;
+@@ -318,7 +318,7 @@ static int __devinit ucb1400_ts_detect_irq(struct ucb1400_ts *ucb,
+ 	return 0;
+ }
+ 
+-static int __devinit ucb1400_ts_probe(struct platform_device *pdev)
++static int ucb1400_ts_probe(struct platform_device *pdev)
+ {
+ 	struct ucb1400_ts *ucb = pdev->dev.platform_data;
+ 	int error, x_res, y_res;
+diff --git a/drivers/input/touchscreen/w90p910_ts.c b/drivers/input/touchscreen/w90p910_ts.c
+index 039e4eadb6ac..f0378a9dc93e 100644
+--- a/drivers/input/touchscreen/w90p910_ts.c
++++ b/drivers/input/touchscreen/w90p910_ts.c
+@@ -215,7 +215,7 @@ static void w90p910_close(struct input_dev *dev)
+ 	clk_disable(w90p910_ts->clk);
+ }
+ 
+-static int __devinit w90x900ts_probe(struct platform_device *pdev)
++static int w90x900ts_probe(struct platform_device *pdev)
+ {
+ 	struct w90p910_ts *w90p910_ts;
+ 	struct input_dev *input_dev;
+diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c
+index 0c033dfbd73e..bb02ccd51008 100644
+--- a/drivers/input/touchscreen/wacom_i2c.c
++++ b/drivers/input/touchscreen/wacom_i2c.c
+@@ -144,7 +144,7 @@ static void wacom_i2c_close(struct input_dev *dev)
+ 	disable_irq(client->irq);
+ }
+ 
+-static int __devinit wacom_i2c_probe(struct i2c_client *client,
++static int wacom_i2c_probe(struct i2c_client *client,
+ 				     const struct i2c_device_id *id)
+ {
+ 	struct wacom_i2c *wac_i2c;
+diff --git a/drivers/input/touchscreen/wm831x-ts.c b/drivers/input/touchscreen/wm831x-ts.c
+index 17f14b69438a..28d81256ec69 100644
+--- a/drivers/input/touchscreen/wm831x-ts.c
++++ b/drivers/input/touchscreen/wm831x-ts.c
+@@ -233,7 +233,7 @@ static void wm831x_ts_input_close(struct input_dev *idev)
+ 	}
+ }
+ 
+-static __devinit int wm831x_ts_probe(struct platform_device *pdev)
++static int wm831x_ts_probe(struct platform_device *pdev)
+ {
+ 	struct wm831x_ts *wm831x_ts;
+ 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);

commit 78f50c246f4286d40a1f42fecc779d47e40503a2
+Author: Bill Pemberton 
+Date:   Fri Nov 23 21:31:00 2012 -0800
+
+    Input: remove use of __devinitconst
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitconst is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Dmitry Torokhov 
+
+diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c
+index 5f66272c2d7c..dba900c54ce6 100644
+--- a/drivers/input/keyboard/locomokbd.c
++++ b/drivers/input/keyboard/locomokbd.c
+@@ -46,7 +46,7 @@ MODULE_LICENSE("GPL");
+ #define KEY_CENTER		KEY_F15
+ 
+ static const unsigned char
+-locomokbd_keycode[LOCOMOKBD_NUMKEYS] __devinitconst = {
++locomokbd_keycode[LOCOMOKBD_NUMKEYS] = {
+ 	0, KEY_ESC, KEY_ACTIVITY, 0, 0, 0, 0, 0, 0, 0,				/* 0 - 9 */
+ 	0, 0, 0, 0, 0, 0, 0, KEY_MENU, KEY_HOME, KEY_CONTACT,			/* 10 - 19 */
+ 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,						/* 20 - 29 */
+diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c
+index 63b20d029454..38b1c0f72ed3 100644
+--- a/drivers/input/keyboard/mpr121_touchkey.c
++++ b/drivers/input/keyboard/mpr121_touchkey.c
+@@ -71,7 +71,7 @@ struct mpr121_init_register {
+ 	u8 val;
+ };
+ 
+-static const struct mpr121_init_register init_reg_table[] __devinitconst = {
++static const struct mpr121_init_register init_reg_table[] = {
+ 	{ MHD_RISING_ADDR,	0x1 },
+ 	{ NHD_RISING_ADDR,	0x1 },
+ 	{ MHD_FALLING_ADDR,	0x1 },
+diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c
+index 73f90dd8eee6..f929d8f2dc50 100644
+--- a/drivers/input/serio/xilinx_ps2.c
++++ b/drivers/input/serio/xilinx_ps2.c
+@@ -355,7 +355,7 @@ static int __devexit xps2_of_remove(struct platform_device *of_dev)
+ }
+ 
+ /* Match table for of_platform binding */
+-static const struct of_device_id xps2_of_match[] __devinitconst = {
++static const struct of_device_id xps2_of_match[] = {
+ 	{ .compatible = "xlnx,xps-ps2-1.00.a", },
+ 	{ /* end of list */ },
+ };
+diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c
+index 62a4b5d71643..5fa0ca346478 100644
+--- a/drivers/input/touchscreen/st1232.c
++++ b/drivers/input/touchscreen/st1232.c
+@@ -255,7 +255,7 @@ static const struct i2c_device_id st1232_ts_id[] = {
+ MODULE_DEVICE_TABLE(i2c, st1232_ts_id);
+ 
+ #ifdef CONFIG_OF
+-static const struct of_device_id st1232_ts_dt_ids[] __devinitconst = {
++static const struct of_device_id st1232_ts_dt_ids[] = {
+ 	{ .compatible = "sitronix,st1232", },
+ 	{ }
+ };

commit d6f6dfd941de2b106af1290b810eff9b1c523772
+Author: Bill Pemberton 
+Date:   Fri Nov 23 21:30:24 2012 -0800
+
+    Input: remove use of __devinitdata
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitdata is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Dmitry Torokhov 
+
+diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c
+index 48ef283cef37..0bbcf971d103 100644
+--- a/drivers/input/keyboard/tegra-kbc.c
++++ b/drivers/input/keyboard/tegra-kbc.c
+@@ -87,7 +87,7 @@ struct tegra_kbc {
+ 	struct clk *clk;
+ };
+ 
+-static const u32 tegra_kbc_default_keymap[] __devinitdata = {
++static const u32 tegra_kbc_default_keymap[] = {
+ 	KEY(0, 2, KEY_W),
+ 	KEY(0, 3, KEY_S),
+ 	KEY(0, 4, KEY_A),
+@@ -223,7 +223,7 @@ static const u32 tegra_kbc_default_keymap[] __devinitdata = {
+ };
+ 
+ static const
+-struct matrix_keymap_data tegra_kbc_default_keymap_data __devinitdata = {
++struct matrix_keymap_data tegra_kbc_default_keymap_data = {
+ 	.keymap		= tegra_kbc_default_keymap,
+ 	.keymap_size	= ARRAY_SIZE(tegra_kbc_default_keymap),
+ };
+diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c
+index 0788c94fb460..5b459d7dd207 100644
+--- a/drivers/input/misc/bma150.c
++++ b/drivers/input/misc/bma150.c
+@@ -158,7 +158,7 @@ struct bma150_data {
+  * are stated and verified by Bosch Sensortec where they are configured
+  * to provide a generic sensitivity performance.
+  */
+-static struct bma150_cfg default_cfg __devinitdata = {
++static struct bma150_cfg default_cfg = {
+ 	.any_motion_int = 1,
+ 	.hg_int = 1,
+ 	.lg_int = 1,
+diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
+index f4c1bc8a5a8d..0334898f9205 100644
+--- a/drivers/input/touchscreen/mms114.c
++++ b/drivers/input/touchscreen/mms114.c
+@@ -576,7 +576,7 @@ static const struct i2c_device_id mms114_id[] = {
+ MODULE_DEVICE_TABLE(i2c, mms114_id);
+ 
+ #ifdef CONFIG_OF
+-static struct of_device_id __devinitdata mms114_dt_match[] = {
++static struct of_device_id mms114_dt_match[] = {
+ 	{ .compatible = "melfas,mms114" },
+ 	{ }
+ };

commit 1cb0aa88179b7a71c240529e9d781d7bbb43d2e8
+Author: Bill Pemberton 
+Date:   Fri Nov 23 21:27:39 2012 -0800
+
+    Input: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Russell King 
+    Signed-off-by: Dmitry Torokhov 
+
+diff --git a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c
+index daceafe7ee7d..c300089b5172 100644
+--- a/drivers/input/gameport/emu10k1-gp.c
++++ b/drivers/input/gameport/emu10k1-gp.c
+@@ -122,7 +122,7 @@ static struct pci_driver emu_driver = {
+         .name =         "Emu10k1_gameport",
+         .id_table =     emu_tbl,
+         .probe =        emu_probe,
+-        .remove =       __devexit_p(emu_remove),
++	.remove =	emu_remove,
+ };
+ 
+ module_pci_driver(emu_driver);
+diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c
+index 48ad3829ff20..e3ab458bfb8a 100644
+--- a/drivers/input/gameport/fm801-gp.c
++++ b/drivers/input/gameport/fm801-gp.c
+@@ -150,7 +150,7 @@ static struct pci_driver fm801_gp_driver = {
+ 	.name =		"FM801_gameport",
+ 	.id_table =	fm801_gp_id_table,
+ 	.probe =	fm801_gp_probe,
+-	.remove =	__devexit_p(fm801_gp_remove),
++	.remove =	fm801_gp_remove,
+ };
+ 
+ module_pci_driver(fm801_gp_driver);
+diff --git a/drivers/input/joystick/as5011.c b/drivers/input/joystick/as5011.c
+index 9d869e202b81..94f332773aec 100644
+--- a/drivers/input/joystick/as5011.c
++++ b/drivers/input/joystick/as5011.c
+@@ -366,7 +366,7 @@ static struct i2c_driver as5011_driver = {
+ 		.name = "as5011",
+ 	},
+ 	.probe		= as5011_probe,
+-	.remove		= __devexit_p(as5011_remove),
++	.remove		= as5011_remove,
+ 	.id_table	= as5011_id,
+ };
+ 
+diff --git a/drivers/input/joystick/maplecontrol.c b/drivers/input/joystick/maplecontrol.c
+index 77cfde571bd9..c84345704258 100644
+--- a/drivers/input/joystick/maplecontrol.c
++++ b/drivers/input/joystick/maplecontrol.c
+@@ -175,7 +175,7 @@ static struct maple_driver dc_pad_driver = {
+ 	.drv = {
+ 		.name	= "Dreamcast_controller",
+ 		.probe	= probe_maple_controller,
+-		.remove	= __devexit_p(remove_maple_controller),
++		.remove	= remove_maple_controller,
+ 	},
+ };
+ 
+diff --git a/drivers/input/keyboard/adp5520-keys.c b/drivers/input/keyboard/adp5520-keys.c
+index e9e8674dfda1..46796b26ff31 100644
+--- a/drivers/input/keyboard/adp5520-keys.c
++++ b/drivers/input/keyboard/adp5520-keys.c
+@@ -200,7 +200,7 @@ static struct platform_driver adp5520_keys_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= adp5520_keys_probe,
+-	.remove		= __devexit_p(adp5520_keys_remove),
++	.remove		= adp5520_keys_remove,
+ };
+ module_platform_driver(adp5520_keys_driver);
+ 
+diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c
+index b083bf10f139..39c2a6d2c99f 100644
+--- a/drivers/input/keyboard/adp5588-keys.c
++++ b/drivers/input/keyboard/adp5588-keys.c
+@@ -650,7 +650,7 @@ static struct i2c_driver adp5588_driver = {
+ #endif
+ 	},
+ 	.probe    = adp5588_probe,
+-	.remove   = __devexit_p(adp5588_remove),
++	.remove   = adp5588_remove,
+ 	.id_table = adp5588_id,
+ };
+ 
+diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c
+index 74e603213386..6e0c2e3a6a8d 100644
+--- a/drivers/input/keyboard/adp5589-keys.c
++++ b/drivers/input/keyboard/adp5589-keys.c
+@@ -1104,7 +1104,7 @@ static struct i2c_driver adp5589_driver = {
+ 		.pm = &adp5589_dev_pm_ops,
+ 	},
+ 	.probe = adp5589_probe,
+-	.remove = __devexit_p(adp5589_remove),
++	.remove = adp5589_remove,
+ 	.id_table = adp5589_id,
+ };
+ 
+diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c
+index 8eb9116e0a5f..8a7909a87216 100644
+--- a/drivers/input/keyboard/bf54x-keys.c
++++ b/drivers/input/keyboard/bf54x-keys.c
+@@ -390,7 +390,7 @@ static struct platform_driver bfin_kpad_device_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= bfin_kpad_probe,
+-	.remove		= __devexit_p(bfin_kpad_remove),
++	.remove		= bfin_kpad_remove,
+ 	.suspend	= bfin_kpad_suspend,
+ 	.resume		= bfin_kpad_resume,
+ };
+diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c
+index d5bacbb479b0..8e4b438ddc8d 100644
+--- a/drivers/input/keyboard/davinci_keyscan.c
++++ b/drivers/input/keyboard/davinci_keyscan.c
+@@ -326,7 +326,7 @@ static struct platform_driver davinci_ks_driver = {
+ 		.name = "davinci_keyscan",
+ 		.owner = THIS_MODULE,
+ 	},
+-	.remove	= __devexit_p(davinci_ks_remove),
++	.remove	= davinci_ks_remove,
+ };
+ 
+ static int __init davinci_ks_init(void)
+diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c
+index 7363402de8d4..bdf326155960 100644
+--- a/drivers/input/keyboard/ep93xx_keypad.c
++++ b/drivers/input/keyboard/ep93xx_keypad.c
+@@ -380,7 +380,7 @@ static struct platform_driver ep93xx_keypad_driver = {
+ 		.pm	= &ep93xx_keypad_pm_ops,
+ 	},
+ 	.probe		= ep93xx_keypad_probe,
+-	.remove		= __devexit_p(ep93xx_keypad_remove),
++	.remove		= ep93xx_keypad_remove,
+ };
+ module_platform_driver(ep93xx_keypad_driver);
+ 
+diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
+index 6a68041c261d..96b5ac5998f1 100644
+--- a/drivers/input/keyboard/gpio_keys.c
++++ b/drivers/input/keyboard/gpio_keys.c
+@@ -824,7 +824,7 @@ static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume);
+ 
+ static struct platform_driver gpio_keys_device_driver = {
+ 	.probe		= gpio_keys_probe,
+-	.remove		= __devexit_p(gpio_keys_remove),
++	.remove		= gpio_keys_remove,
+ 	.driver		= {
+ 		.name	= "gpio-keys",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c
+index f2142de789e7..922cbbdb5c84 100644
+--- a/drivers/input/keyboard/gpio_keys_polled.c
++++ b/drivers/input/keyboard/gpio_keys_polled.c
+@@ -357,7 +357,7 @@ static int __devexit gpio_keys_polled_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver gpio_keys_polled_driver = {
+ 	.probe	= gpio_keys_polled_probe,
+-	.remove	= __devexit_p(gpio_keys_polled_remove),
++	.remove	= gpio_keys_polled_remove,
+ 	.driver	= {
+ 		.name	= DRV_NAME,
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c
+index 5f72440b50c8..97d3151232be 100644
+--- a/drivers/input/keyboard/hilkbd.c
++++ b/drivers/input/keyboard/hilkbd.c
+@@ -341,7 +341,7 @@ static struct parisc_driver hil_driver = {
+ 	.name		= "hil",
+ 	.id_table	= hil_tbl,
+ 	.probe		= hil_probe_chip,
+-	.remove		= __devexit_p(hil_remove_chip),
++	.remove		= hil_remove_chip,
+ };
+ 
+ static int __init hil_init(void)
+diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c
+index cdc252612c0b..93c344137cc5 100644
+--- a/drivers/input/keyboard/imx_keypad.c
++++ b/drivers/input/keyboard/imx_keypad.c
+@@ -632,7 +632,7 @@ static struct platform_driver imx_keypad_driver = {
+ 		.pm	= &imx_kbd_pm_ops,
+ 	},
+ 	.probe		= imx_keypad_probe,
+-	.remove		= __devexit_p(imx_keypad_remove),
++	.remove		= imx_keypad_remove,
+ };
+ module_platform_driver(imx_keypad_driver);
+ 
+diff --git a/drivers/input/keyboard/jornada680_kbd.c b/drivers/input/keyboard/jornada680_kbd.c
+index 24f3ea01c4d5..bd1a9c365d11 100644
+--- a/drivers/input/keyboard/jornada680_kbd.c
++++ b/drivers/input/keyboard/jornada680_kbd.c
+@@ -258,7 +258,7 @@ static struct platform_driver jornada680kbd_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe	= jornada680kbd_probe,
+-	.remove	= __devexit_p(jornada680kbd_remove),
++	.remove	= jornada680kbd_remove,
+ };
+ module_platform_driver(jornada680kbd_driver);
+ 
+diff --git a/drivers/input/keyboard/jornada720_kbd.c b/drivers/input/keyboard/jornada720_kbd.c
+index 9d639fa1afbd..9771db1de01b 100644
+--- a/drivers/input/keyboard/jornada720_kbd.c
++++ b/drivers/input/keyboard/jornada720_kbd.c
+@@ -173,6 +173,6 @@ static struct platform_driver jornada720_kbd_driver = {
+ 		.owner	= THIS_MODULE,
+ 	 },
+ 	.probe   = jornada720_kbd_probe,
+-	.remove  = __devexit_p(jornada720_kbd_remove),
++	.remove  = jornada720_kbd_remove,
+ };
+ module_platform_driver(jornada720_kbd_driver);
+diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c
+index 39ac2787e275..87432859be52 100644
+--- a/drivers/input/keyboard/lm8323.c
++++ b/drivers/input/keyboard/lm8323.c
+@@ -846,7 +846,7 @@ static struct i2c_driver lm8323_i2c_driver = {
+ 		.pm	= &lm8323_pm_ops,
+ 	},
+ 	.probe		= lm8323_probe,
+-	.remove		= __devexit_p(lm8323_remove),
++	.remove		= lm8323_remove,
+ 	.id_table	= lm8323_id,
+ };
+ MODULE_DEVICE_TABLE(i2c, lm8323_id);
+diff --git a/drivers/input/keyboard/lm8333.c b/drivers/input/keyboard/lm8333.c
+index 081fd9effa8c..c76e488ce9bc 100644
+--- a/drivers/input/keyboard/lm8333.c
++++ b/drivers/input/keyboard/lm8333.c
+@@ -225,7 +225,7 @@ static struct i2c_driver lm8333_driver = {
+ 		.owner		= THIS_MODULE,
+ 	},
+ 	.probe		= lm8333_probe,
+-	.remove		= __devexit_p(lm8333_remove),
++	.remove		= lm8333_remove,
+ 	.id_table	= lm8333_id,
+ };
+ module_i2c_driver(lm8333_driver);
+diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c
+index b1ab29861e1c..5f66272c2d7c 100644
+--- a/drivers/input/keyboard/locomokbd.c
++++ b/drivers/input/keyboard/locomokbd.c
+@@ -345,7 +345,7 @@ static struct locomo_driver keyboard_driver = {
+ 	},
+ 	.devid	= LOCOMO_DEVID_KEYBOARD,
+ 	.probe	= locomokbd_probe,
+-	.remove	= __devexit_p(locomokbd_remove),
++	.remove	= locomokbd_remove,
+ };
+ 
+ static int __init locomokbd_init(void)
+diff --git a/drivers/input/keyboard/lpc32xx-keys.c b/drivers/input/keyboard/lpc32xx-keys.c
+index dd786c8a7584..8872ce62c9d8 100644
+--- a/drivers/input/keyboard/lpc32xx-keys.c
++++ b/drivers/input/keyboard/lpc32xx-keys.c
+@@ -377,7 +377,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_kscan_match);
+ 
+ static struct platform_driver lpc32xx_kscan_driver = {
+ 	.probe		= lpc32xx_kscan_probe,
+-	.remove		= __devexit_p(lpc32xx_kscan_remove),
++	.remove		= lpc32xx_kscan_remove,
+ 	.driver		= {
+ 		.name	= DRV_NAME,
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c
+index 05d3a969ff4e..ed2bacdf2ccb 100644
+--- a/drivers/input/keyboard/matrix_keypad.c
++++ b/drivers/input/keyboard/matrix_keypad.c
+@@ -564,7 +564,7 @@ MODULE_DEVICE_TABLE(of, matrix_keypad_dt_match);
+ 
+ static struct platform_driver matrix_keypad_driver = {
+ 	.probe		= matrix_keypad_probe,
+-	.remove		= __devexit_p(matrix_keypad_remove),
++	.remove		= matrix_keypad_remove,
+ 	.driver		= {
+ 		.name	= "matrix-keypad",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c
+index 8edada8ae712..90478d182bc8 100644
+--- a/drivers/input/keyboard/max7359_keypad.c
++++ b/drivers/input/keyboard/max7359_keypad.c
+@@ -312,7 +312,7 @@ static struct i2c_driver max7359_i2c_driver = {
+ 		.pm   = &max7359_pm,
+ 	},
+ 	.probe		= max7359_probe,
+-	.remove		= __devexit_p(max7359_remove),
++	.remove		= max7359_remove,
+ 	.id_table	= max7359_ids,
+ };
+ 
+diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c
+index 0d77f6c84950..751b1419e56b 100644
+--- a/drivers/input/keyboard/mcs_touchkey.c
++++ b/drivers/input/keyboard/mcs_touchkey.c
+@@ -270,7 +270,7 @@ static struct i2c_driver mcs_touchkey_driver = {
+ 		.pm	= &mcs_touchkey_pm_ops,
+ 	},
+ 	.probe		= mcs_touchkey_probe,
+-	.remove		= __devexit_p(mcs_touchkey_remove),
++	.remove		= mcs_touchkey_remove,
+ 	.shutdown       = mcs_touchkey_shutdown,
+ 	.id_table	= mcs_touchkey_id,
+ };
+diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c
+index 7613f1cac951..63b20d029454 100644
+--- a/drivers/input/keyboard/mpr121_touchkey.c
++++ b/drivers/input/keyboard/mpr121_touchkey.c
+@@ -327,7 +327,7 @@ static struct i2c_driver mpr_touchkey_driver = {
+ 	},
+ 	.id_table	= mpr121_id,
+ 	.probe		= mpr_touchkey_probe,
+-	.remove		= __devexit_p(mpr_touchkey_remove),
++	.remove		= mpr_touchkey_remove,
+ };
+ 
+ module_i2c_driver(mpr_touchkey_driver);
+diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c
+index a1a9375f18ff..2304a8192cf7 100644
+--- a/drivers/input/keyboard/nomadik-ske-keypad.c
++++ b/drivers/input/keyboard/nomadik-ske-keypad.c
+@@ -427,7 +427,7 @@ static struct platform_driver ske_keypad_driver = {
+ 		.owner  = THIS_MODULE,
+ 		.pm = &ske_keypad_dev_pm_ops,
+ 	},
+-	.remove = __devexit_p(ske_keypad_remove),
++	.remove = ske_keypad_remove,
+ };
+ 
+ static int __init ske_keypad_init(void)
+diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c
+index 4a5fcc8026f5..1d17d91ed1e1 100644
+--- a/drivers/input/keyboard/omap-keypad.c
++++ b/drivers/input/keyboard/omap-keypad.c
+@@ -379,7 +379,7 @@ static int __devexit omap_kp_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver omap_kp_driver = {
+ 	.probe		= omap_kp_probe,
+-	.remove		= __devexit_p(omap_kp_remove),
++	.remove		= omap_kp_remove,
+ 	.suspend	= omap_kp_suspend,
+ 	.resume		= omap_kp_resume,
+ 	.driver		= {
+diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
+index c05f98c41410..7145ab3401f8 100644
+--- a/drivers/input/keyboard/omap4-keypad.c
++++ b/drivers/input/keyboard/omap4-keypad.c
+@@ -440,7 +440,7 @@ MODULE_DEVICE_TABLE(of, omap_keypad_dt_match);
+ 
+ static struct platform_driver omap4_keypad_driver = {
+ 	.probe		= omap4_keypad_probe,
+-	.remove		= __devexit_p(omap4_keypad_remove),
++	.remove		= omap4_keypad_remove,
+ 	.driver		= {
+ 		.name	= "omap4-keypad",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/keyboard/opencores-kbd.c b/drivers/input/keyboard/opencores-kbd.c
+index abe728c7b88e..7914ede8e4bf 100644
+--- a/drivers/input/keyboard/opencores-kbd.c
++++ b/drivers/input/keyboard/opencores-kbd.c
+@@ -158,7 +158,7 @@ static int __devexit opencores_kbd_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver opencores_kbd_device_driver = {
+ 	.probe    = opencores_kbd_probe,
+-	.remove   = __devexit_p(opencores_kbd_remove),
++	.remove   = opencores_kbd_remove,
+ 	.driver   = {
+ 		.name = "opencores-kbd",
+ 	},
+diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c
+index 52c34657d301..d3623c5a3eea 100644
+--- a/drivers/input/keyboard/pmic8xxx-keypad.c
++++ b/drivers/input/keyboard/pmic8xxx-keypad.c
+@@ -773,7 +773,7 @@ static SIMPLE_DEV_PM_OPS(pm8xxx_kp_pm_ops,
+ 
+ static struct platform_driver pmic8xxx_kp_driver = {
+ 	.probe		= pmic8xxx_kp_probe,
+-	.remove		= __devexit_p(pmic8xxx_kp_remove),
++	.remove		= pmic8xxx_kp_remove,
+ 	.driver		= {
+ 		.name = PM8XXX_KEYPAD_DEV_NAME,
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
+index cad9d5dd5973..a6bcd3129f0f 100644
+--- a/drivers/input/keyboard/pxa27x_keypad.c
++++ b/drivers/input/keyboard/pxa27x_keypad.c
+@@ -620,7 +620,7 @@ MODULE_ALIAS("platform:pxa27x-keypad");
+ 
+ static struct platform_driver pxa27x_keypad_driver = {
+ 	.probe		= pxa27x_keypad_probe,
+-	.remove		= __devexit_p(pxa27x_keypad_remove),
++	.remove		= pxa27x_keypad_remove,
+ 	.driver		= {
+ 		.name	= "pxa27x-keypad",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/keyboard/pxa930_rotary.c b/drivers/input/keyboard/pxa930_rotary.c
+index 41488f9add20..f8f89d1f230d 100644
+--- a/drivers/input/keyboard/pxa930_rotary.c
++++ b/drivers/input/keyboard/pxa930_rotary.c
+@@ -193,7 +193,7 @@ static struct platform_driver pxa930_rotary_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= pxa930_rotary_probe,
+-	.remove		= __devexit_p(pxa930_rotary_remove),
++	.remove		= pxa930_rotary_remove,
+ };
+ module_platform_driver(pxa930_rotary_driver);
+ 
+diff --git a/drivers/input/keyboard/qt1070.c b/drivers/input/keyboard/qt1070.c
+index ca68f2992d72..eb46405eaad0 100644
+--- a/drivers/input/keyboard/qt1070.c
++++ b/drivers/input/keyboard/qt1070.c
+@@ -256,7 +256,7 @@ static struct i2c_driver qt1070_driver = {
+ 	},
+ 	.id_table	= qt1070_id,
+ 	.probe		= qt1070_probe,
+-	.remove		= __devexit_p(qt1070_remove),
++	.remove		= qt1070_remove,
+ };
+ 
+ module_i2c_driver(qt1070_driver);
+diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c
+index 031eed739903..691fe92a9824 100644
+--- a/drivers/input/keyboard/qt2160.c
++++ b/drivers/input/keyboard/qt2160.c
+@@ -366,7 +366,7 @@ static struct i2c_driver qt2160_driver = {
+ 
+ 	.id_table	= qt2160_idtable,
+ 	.probe		= qt2160_probe,
+-	.remove		= __devexit_p(qt2160_remove),
++	.remove		= qt2160_remove,
+ };
+ 
+ module_i2c_driver(qt2160_driver);
+diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c
+index 9d7a111486f7..f02772aa47df 100644
+--- a/drivers/input/keyboard/samsung-keypad.c
++++ b/drivers/input/keyboard/samsung-keypad.c
+@@ -685,7 +685,7 @@ MODULE_DEVICE_TABLE(platform, samsung_keypad_driver_ids);
+ 
+ static struct platform_driver samsung_keypad_driver = {
+ 	.probe		= samsung_keypad_probe,
+-	.remove		= __devexit_p(samsung_keypad_remove),
++	.remove		= samsung_keypad_remove,
+ 	.driver		= {
+ 		.name	= "samsung-keypad",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c
+index da54ad5db154..07415a36ec1e 100644
+--- a/drivers/input/keyboard/sh_keysc.c
++++ b/drivers/input/keyboard/sh_keysc.c
+@@ -331,7 +331,7 @@ static SIMPLE_DEV_PM_OPS(sh_keysc_dev_pm_ops,
+ 
+ static struct platform_driver sh_keysc_device_driver = {
+ 	.probe		= sh_keysc_probe,
+-	.remove		= __devexit_p(sh_keysc_remove),
++	.remove		= sh_keysc_remove,
+ 	.driver		= {
+ 		.name	= "sh_keysc",
+ 		.pm	= &sh_keysc_dev_pm_ops,
+diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c
+index da914fea0c1c..0c8862343e75 100644
+--- a/drivers/input/keyboard/spear-keyboard.c
++++ b/drivers/input/keyboard/spear-keyboard.c
+@@ -381,7 +381,7 @@ MODULE_DEVICE_TABLE(of, spear_kbd_id_table);
+ 
+ static struct platform_driver spear_kbd_driver = {
+ 	.probe		= spear_kbd_probe,
+-	.remove		= __devexit_p(spear_kbd_remove),
++	.remove		= spear_kbd_remove,
+ 	.driver		= {
+ 		.name	= "keyboard",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c
+index d3d2eaa5f841..286719f5bc0b 100644
+--- a/drivers/input/keyboard/stmpe-keypad.c
++++ b/drivers/input/keyboard/stmpe-keypad.c
+@@ -348,7 +348,7 @@ static struct platform_driver stmpe_keypad_driver = {
+ 	.driver.name	= "stmpe-keypad",
+ 	.driver.owner	= THIS_MODULE,
+ 	.probe		= stmpe_keypad_probe,
+-	.remove		= __devexit_p(stmpe_keypad_remove),
++	.remove		= stmpe_keypad_remove,
+ };
+ module_platform_driver(stmpe_keypad_driver);
+ 
+diff --git a/drivers/input/keyboard/tc3589x-keypad.c b/drivers/input/keyboard/tc3589x-keypad.c
+index 7d498e698508..75fa2b98aaeb 100644
+--- a/drivers/input/keyboard/tc3589x-keypad.c
++++ b/drivers/input/keyboard/tc3589x-keypad.c
+@@ -448,7 +448,7 @@ static struct platform_driver tc3589x_keypad_driver = {
+ 		.pm	= &tc3589x_keypad_dev_pm_ops,
+ 	},
+ 	.probe	= tc3589x_keypad_probe,
+-	.remove	= __devexit_p(tc3589x_keypad_remove),
++	.remove	= tc3589x_keypad_remove,
+ };
+ module_platform_driver(tc3589x_keypad_driver);
+ 
+diff --git a/drivers/input/keyboard/tca6416-keypad.c b/drivers/input/keyboard/tca6416-keypad.c
+index c355cdde8d22..f5fa75aa9db4 100644
+--- a/drivers/input/keyboard/tca6416-keypad.c
++++ b/drivers/input/keyboard/tca6416-keypad.c
+@@ -361,7 +361,7 @@ static struct i2c_driver tca6416_keypad_driver = {
+ 		.pm	= &tca6416_keypad_dev_pm_ops,
+ 	},
+ 	.probe		= tca6416_keypad_probe,
+-	.remove		= __devexit_p(tca6416_keypad_remove),
++	.remove		= tca6416_keypad_remove,
+ 	.id_table	= tca6416_id,
+ };
+ 
+diff --git a/drivers/input/keyboard/tca8418_keypad.c b/drivers/input/keyboard/tca8418_keypad.c
+index 893869b29ed9..672b5f8bcc11 100644
+--- a/drivers/input/keyboard/tca8418_keypad.c
++++ b/drivers/input/keyboard/tca8418_keypad.c
+@@ -408,7 +408,7 @@ static struct i2c_driver tca8418_keypad_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= tca8418_keypad_probe,
+-	.remove		= __devexit_p(tca8418_keypad_remove),
++	.remove		= tca8418_keypad_remove,
+ 	.id_table	= tca8418_id,
+ };
+ 
+diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c
+index 5faaf2553e33..48ef283cef37 100644
+--- a/drivers/input/keyboard/tegra-kbc.c
++++ b/drivers/input/keyboard/tegra-kbc.c
+@@ -954,7 +954,7 @@ MODULE_DEVICE_TABLE(of, tegra_kbc_of_match);
+ 
+ static struct platform_driver tegra_kbc_driver = {
+ 	.probe		= tegra_kbc_probe,
+-	.remove		= __devexit_p(tegra_kbc_remove),
++	.remove		= tegra_kbc_remove,
+ 	.driver	= {
+ 		.name	= "tegra-kbc",
+ 		.owner  = THIS_MODULE,
+diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c
+index 4c34f21fbe2d..05d923c51c1e 100644
+--- a/drivers/input/keyboard/tnetv107x-keypad.c
++++ b/drivers/input/keyboard/tnetv107x-keypad.c
+@@ -319,7 +319,7 @@ static int __devexit keypad_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver keypad_driver = {
+ 	.probe		= keypad_probe,
+-	.remove		= __devexit_p(keypad_remove),
++	.remove		= keypad_remove,
+ 	.driver.name	= "tnetv107x-keypad",
+ 	.driver.owner	= THIS_MODULE,
+ };
+diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c
+index a2c6f79aa101..ae25909d51b1 100644
+--- a/drivers/input/keyboard/twl4030_keypad.c
++++ b/drivers/input/keyboard/twl4030_keypad.c
+@@ -452,7 +452,7 @@ static int __devexit twl4030_kp_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver twl4030_kp_driver = {
+ 	.probe		= twl4030_kp_probe,
+-	.remove		= __devexit_p(twl4030_kp_remove),
++	.remove		= twl4030_kp_remove,
+ 	.driver		= {
+ 		.name	= "twl4030_keypad",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c
+index e0f6cd1ad0fd..a90fdfc0948f 100644
+--- a/drivers/input/keyboard/w90p910_keypad.c
++++ b/drivers/input/keyboard/w90p910_keypad.c
+@@ -257,7 +257,7 @@ static int __devexit w90p910_keypad_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver w90p910_keypad_driver = {
+ 	.probe		= w90p910_keypad_probe,
+-	.remove		= __devexit_p(w90p910_keypad_remove),
++	.remove		= w90p910_keypad_remove,
+ 	.driver		= {
+ 		.name	= "nuc900-kpi",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/misc/88pm80x_onkey.c b/drivers/input/misc/88pm80x_onkey.c
+index 7f26e7b6c228..f77557523bb9 100644
+--- a/drivers/input/misc/88pm80x_onkey.c
++++ b/drivers/input/misc/88pm80x_onkey.c
+@@ -157,7 +157,7 @@ static struct platform_driver pm80x_onkey_driver = {
+ 		   .pm = &pm80x_onkey_pm_ops,
+ 		   },
+ 	.probe = pm80x_onkey_probe,
+-	.remove = __devexit_p(pm80x_onkey_remove),
++	.remove = pm80x_onkey_remove,
+ };
+ 
+ module_platform_driver(pm80x_onkey_driver);
+diff --git a/drivers/input/misc/88pm860x_onkey.c b/drivers/input/misc/88pm860x_onkey.c
+index f9ce1835e4d7..8391a9d86ab5 100644
+--- a/drivers/input/misc/88pm860x_onkey.c
++++ b/drivers/input/misc/88pm860x_onkey.c
+@@ -161,7 +161,7 @@ static struct platform_driver pm860x_onkey_driver = {
+ 		.pm	= &pm860x_onkey_pm_ops,
+ 	},
+ 	.probe		= pm860x_onkey_probe,
+-	.remove		= __devexit_p(pm860x_onkey_remove),
++	.remove		= pm860x_onkey_remove,
+ };
+ module_platform_driver(pm860x_onkey_driver);
+ 
+diff --git a/drivers/input/misc/ab8500-ponkey.c b/drivers/input/misc/ab8500-ponkey.c
+index 84ec691c05aa..ae9c20522dbd 100644
+--- a/drivers/input/misc/ab8500-ponkey.c
++++ b/drivers/input/misc/ab8500-ponkey.c
+@@ -146,7 +146,7 @@ static struct platform_driver ab8500_ponkey_driver = {
+ 		.of_match_table = of_match_ptr(ab8500_ponkey_match),
+ 	},
+ 	.probe		= ab8500_ponkey_probe,
+-	.remove		= __devexit_p(ab8500_ponkey_remove),
++	.remove		= ab8500_ponkey_remove,
+ };
+ module_platform_driver(ab8500_ponkey_driver);
+ 
+diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c
+index c8a79015472a..02e21d4f5e73 100644
+--- a/drivers/input/misc/ad714x-i2c.c
++++ b/drivers/input/misc/ad714x-i2c.c
+@@ -112,7 +112,7 @@ static struct i2c_driver ad714x_i2c_driver = {
+ 		.pm   = &ad714x_i2c_pm,
+ 	},
+ 	.probe    = ad714x_i2c_probe,
+-	.remove   = __devexit_p(ad714x_i2c_remove),
++	.remove   = ad714x_i2c_remove,
+ 	.id_table = ad714x_id,
+ };
+ 
+diff --git a/drivers/input/misc/ad714x-spi.c b/drivers/input/misc/ad714x-spi.c
+index 75f6136d608e..eee820b41356 100644
+--- a/drivers/input/misc/ad714x-spi.c
++++ b/drivers/input/misc/ad714x-spi.c
+@@ -120,7 +120,7 @@ static struct spi_driver ad714x_spi_driver = {
+ 		.pm	= &ad714x_spi_pm,
+ 	},
+ 	.probe		= ad714x_spi_probe,
+-	.remove		= __devexit_p(ad714x_spi_remove),
++	.remove		= ad714x_spi_remove,
+ };
+ 
+ module_spi_driver(ad714x_spi_driver);
+diff --git a/drivers/input/misc/adxl34x-i2c.c b/drivers/input/misc/adxl34x-i2c.c
+index dd1d1c145a7f..09094ca972c7 100644
+--- a/drivers/input/misc/adxl34x-i2c.c
++++ b/drivers/input/misc/adxl34x-i2c.c
+@@ -144,7 +144,7 @@ static struct i2c_driver adxl34x_driver = {
+ 		.pm = &adxl34x_i2c_pm,
+ 	},
+ 	.probe    = adxl34x_i2c_probe,
+-	.remove   = __devexit_p(adxl34x_i2c_remove),
++	.remove   = adxl34x_i2c_remove,
+ 	.id_table = adxl34x_id,
+ };
+ 
+diff --git a/drivers/input/misc/adxl34x-spi.c b/drivers/input/misc/adxl34x-spi.c
+index 820a802a1e6e..756c899bfa7f 100644
+--- a/drivers/input/misc/adxl34x-spi.c
++++ b/drivers/input/misc/adxl34x-spi.c
+@@ -126,7 +126,7 @@ static struct spi_driver adxl34x_driver = {
+ 		.pm = &adxl34x_spi_pm,
+ 	},
+ 	.probe   = adxl34x_spi_probe,
+-	.remove  = __devexit_p(adxl34x_spi_remove),
++	.remove  = adxl34x_spi_remove,
+ };
+ 
+ module_spi_driver(adxl34x_driver);
+diff --git a/drivers/input/misc/bfin_rotary.c b/drivers/input/misc/bfin_rotary.c
+index 1c4146fccfdf..6df3f88a46dd 100644
+--- a/drivers/input/misc/bfin_rotary.c
++++ b/drivers/input/misc/bfin_rotary.c
+@@ -255,7 +255,7 @@ static const struct dev_pm_ops bfin_rotary_pm_ops = {
+ 
+ static struct platform_driver bfin_rotary_device_driver = {
+ 	.probe		= bfin_rotary_probe,
+-	.remove		= __devexit_p(bfin_rotary_remove),
++	.remove		= bfin_rotary_remove,
+ 	.driver		= {
+ 		.name	= "bfin-rotary",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c
+index e2f1e9f952b1..0788c94fb460 100644
+--- a/drivers/input/misc/bma150.c
++++ b/drivers/input/misc/bma150.c
+@@ -670,7 +670,7 @@ static struct i2c_driver bma150_driver = {
+ 	.class		= I2C_CLASS_HWMON,
+ 	.id_table	= bma150_id,
+ 	.probe		= bma150_probe,
+-	.remove		= __devexit_p(bma150_remove),
++	.remove		= bma150_remove,
+ };
+ 
+ module_i2c_driver(bma150_driver);
+diff --git a/drivers/input/misc/cma3000_d0x_i2c.c b/drivers/input/misc/cma3000_d0x_i2c.c
+index fe9b85f07792..523b6aabd7fc 100644
+--- a/drivers/input/misc/cma3000_d0x_i2c.c
++++ b/drivers/input/misc/cma3000_d0x_i2c.c
+@@ -114,7 +114,7 @@ MODULE_DEVICE_TABLE(i2c, cma3000_i2c_id);
+ 
+ static struct i2c_driver cma3000_i2c_driver = {
+ 	.probe		= cma3000_i2c_probe,
+-	.remove		= __devexit_p(cma3000_i2c_remove),
++	.remove		= cma3000_i2c_remove,
+ 	.id_table	= cma3000_i2c_id,
+ 	.driver = {
+ 		.name	= "cma3000_i2c_accl",
+diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c
+index 53e43d295148..659f20df6040 100644
+--- a/drivers/input/misc/cobalt_btns.c
++++ b/drivers/input/misc/cobalt_btns.c
+@@ -157,7 +157,7 @@ MODULE_ALIAS("platform:Cobalt buttons");
+ 
+ static struct platform_driver cobalt_buttons_driver = {
+ 	.probe	= cobalt_buttons_probe,
+-	.remove	= __devexit_p(cobalt_buttons_remove),
++	.remove	= cobalt_buttons_remove,
+ 	.driver	= {
+ 		.name	= "Cobalt buttons",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/misc/da9052_onkey.c b/drivers/input/misc/da9052_onkey.c
+index 3c843cd725fa..acd07e8c32bc 100644
+--- a/drivers/input/misc/da9052_onkey.c
++++ b/drivers/input/misc/da9052_onkey.c
+@@ -156,7 +156,7 @@ static int __devexit da9052_onkey_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver da9052_onkey_driver = {
+ 	.probe	= da9052_onkey_probe,
+-	.remove	= __devexit_p(da9052_onkey_remove),
++	.remove	= da9052_onkey_remove,
+ 	.driver = {
+ 		.name	= "da9052-onkey",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/misc/da9055_onkey.c b/drivers/input/misc/da9055_onkey.c
+index 10ebf15070d7..fe434e07dbfc 100644
+--- a/drivers/input/misc/da9055_onkey.c
++++ b/drivers/input/misc/da9055_onkey.c
+@@ -156,7 +156,7 @@ static int __devexit da9055_onkey_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver da9055_onkey_driver = {
+ 	.probe	= da9055_onkey_probe,
+-	.remove	= __devexit_p(da9055_onkey_remove),
++	.remove	= da9055_onkey_remove,
+ 	.driver = {
+ 		.name	= "da9055-onkey",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/misc/dm355evm_keys.c b/drivers/input/misc/dm355evm_keys.c
+index c1313d8535c3..1afb91cd71fb 100644
+--- a/drivers/input/misc/dm355evm_keys.c
++++ b/drivers/input/misc/dm355evm_keys.c
+@@ -262,7 +262,7 @@ static int __devexit dm355evm_keys_remove(struct platform_device *pdev)
+  */
+ static struct platform_driver dm355evm_keys_driver = {
+ 	.probe		= dm355evm_keys_probe,
+-	.remove		= __devexit_p(dm355evm_keys_remove),
++	.remove		= dm355evm_keys_remove,
+ 	.driver		= {
+ 		.owner	= THIS_MODULE,
+ 		.name	= "dm355evm_keys",
+diff --git a/drivers/input/misc/gp2ap002a00f.c b/drivers/input/misc/gp2ap002a00f.c
+index b6664cfa340a..99ec8d0c6e41 100644
+--- a/drivers/input/misc/gp2ap002a00f.c
++++ b/drivers/input/misc/gp2ap002a00f.c
+@@ -277,7 +277,7 @@ static struct i2c_driver gp2a_i2c_driver = {
+ 		.pm	= &gp2a_pm,
+ 	},
+ 	.probe		= gp2a_probe,
+-	.remove		= __devexit_p(gp2a_remove),
++	.remove		= gp2a_remove,
+ 	.id_table	= gp2a_i2c_id,
+ };
+ 
+diff --git a/drivers/input/misc/gpio_tilt_polled.c b/drivers/input/misc/gpio_tilt_polled.c
+index 277a0574c199..bf97679fe522 100644
+--- a/drivers/input/misc/gpio_tilt_polled.c
++++ b/drivers/input/misc/gpio_tilt_polled.c
+@@ -198,7 +198,7 @@ static int __devexit gpio_tilt_polled_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver gpio_tilt_polled_driver = {
+ 	.probe	= gpio_tilt_polled_probe,
+-	.remove	= __devexit_p(gpio_tilt_polled_remove),
++	.remove	= gpio_tilt_polled_remove,
+ 	.driver	= {
+ 		.name	= DRV_NAME,
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c
+index 50e283068301..18a2970f88ee 100644
+--- a/drivers/input/misc/ixp4xx-beeper.c
++++ b/drivers/input/misc/ixp4xx-beeper.c
+@@ -165,7 +165,7 @@ static struct platform_driver ixp4xx_spkr_platform_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= ixp4xx_spkr_probe,
+-	.remove		= __devexit_p(ixp4xx_spkr_remove),
++	.remove		= ixp4xx_spkr_remove,
+ 	.shutdown	= ixp4xx_spkr_shutdown,
+ };
+ module_platform_driver(ixp4xx_spkr_platform_driver);
+diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
+index f46139f19ff1..8414ddb31815 100644
+--- a/drivers/input/misc/kxtj9.c
++++ b/drivers/input/misc/kxtj9.c
+@@ -663,7 +663,7 @@ static struct i2c_driver kxtj9_driver = {
+ 		.pm	= &kxtj9_pm_ops,
+ 	},
+ 	.probe		= kxtj9_probe,
+-	.remove		= __devexit_p(kxtj9_remove),
++	.remove		= kxtj9_remove,
+ 	.id_table	= kxtj9_id,
+ };
+ 
+diff --git a/drivers/input/misc/m68kspkr.c b/drivers/input/misc/m68kspkr.c
+index 0c64d9bb718e..f3a3c5e14d00 100644
+--- a/drivers/input/misc/m68kspkr.c
++++ b/drivers/input/misc/m68kspkr.c
+@@ -104,7 +104,7 @@ static struct platform_driver m68kspkr_platform_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= m68kspkr_probe,
+-	.remove		= __devexit_p(m68kspkr_remove),
++	.remove		= m68kspkr_remove,
+ 	.shutdown	= m68kspkr_shutdown,
+ };
+ 
+diff --git a/drivers/input/misc/max8925_onkey.c b/drivers/input/misc/max8925_onkey.c
+index 0a12b74140d3..3c3db6787e8f 100644
+--- a/drivers/input/misc/max8925_onkey.c
++++ b/drivers/input/misc/max8925_onkey.c
+@@ -195,7 +195,7 @@ static struct platform_driver max8925_onkey_driver = {
+ 		.pm	= &max8925_onkey_pm_ops,
+ 	},
+ 	.probe		= max8925_onkey_probe,
+-	.remove		= __devexit_p(max8925_onkey_remove),
++	.remove		= max8925_onkey_remove,
+ };
+ module_platform_driver(max8925_onkey_driver);
+ 
+diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c
+index 05b7b8bfaf0a..8db64f652d7a 100644
+--- a/drivers/input/misc/max8997_haptic.c
++++ b/drivers/input/misc/max8997_haptic.c
+@@ -396,7 +396,7 @@ static struct platform_driver max8997_haptic_driver = {
+ 		.pm	= &max8997_haptic_pm_ops,
+ 	},
+ 	.probe		= max8997_haptic_probe,
+-	.remove		= __devexit_p(max8997_haptic_remove),
++	.remove		= max8997_haptic_remove,
+ 	.id_table	= max8997_haptic_id,
+ };
+ module_platform_driver(max8997_haptic_driver);
+diff --git a/drivers/input/misc/mc13783-pwrbutton.c b/drivers/input/misc/mc13783-pwrbutton.c
+index 8428f1e8e83e..a0c35a058318 100644
+--- a/drivers/input/misc/mc13783-pwrbutton.c
++++ b/drivers/input/misc/mc13783-pwrbutton.c
+@@ -257,7 +257,7 @@ static int __devexit mc13783_pwrbutton_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver mc13783_pwrbutton_driver = {
+ 	.probe		= mc13783_pwrbutton_probe,
+-	.remove		= __devexit_p(mc13783_pwrbutton_remove),
++	.remove		= mc13783_pwrbutton_remove,
+ 	.driver		= {
+ 		.name	= "mc13783-pwrbutton",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/misc/mma8450.c b/drivers/input/misc/mma8450.c
+index 873ebced544e..050a246043dc 100644
+--- a/drivers/input/misc/mma8450.c
++++ b/drivers/input/misc/mma8450.c
+@@ -243,7 +243,7 @@ static struct i2c_driver mma8450_driver = {
+ 		.of_match_table = mma8450_dt_ids,
+ 	},
+ 	.probe		= mma8450_probe,
+-	.remove		= __devexit_p(mma8450_remove),
++	.remove		= mma8450_remove,
+ 	.id_table	= mma8450_id,
+ };
+ 
+diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c
+index 306f84c2d8fb..ab114092b9a9 100644
+--- a/drivers/input/misc/mpu3050.c
++++ b/drivers/input/misc/mpu3050.c
+@@ -471,7 +471,7 @@ static struct i2c_driver mpu3050_i2c_driver = {
+ 		.of_match_table = mpu3050_of_match,
+ 	},
+ 	.probe		= mpu3050_probe,
+-	.remove		= __devexit_p(mpu3050_remove),
++	.remove		= mpu3050_remove,
+ 	.id_table	= mpu3050_ids,
+ };
+ 
+diff --git a/drivers/input/misc/pcap_keys.c b/drivers/input/misc/pcap_keys.c
+index e09b4fe81913..afd3f5ae17f9 100644
+--- a/drivers/input/misc/pcap_keys.c
++++ b/drivers/input/misc/pcap_keys.c
+@@ -119,7 +119,7 @@ static int __devexit pcap_keys_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver pcap_keys_device_driver = {
+ 	.probe		= pcap_keys_probe,
+-	.remove		= __devexit_p(pcap_keys_remove),
++	.remove		= pcap_keys_remove,
+ 	.driver		= {
+ 		.name	= "pcap-keys",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/misc/pcf50633-input.c b/drivers/input/misc/pcf50633-input.c
+index 53891de80b0e..3896b0f8e9bb 100644
+--- a/drivers/input/misc/pcf50633-input.c
++++ b/drivers/input/misc/pcf50633-input.c
+@@ -111,7 +111,7 @@ static struct platform_driver pcf50633_input_driver = {
+ 		.name = "pcf50633-input",
+ 	},
+ 	.probe = pcf50633_input_probe,
+-	.remove = __devexit_p(pcf50633_input_remove),
++	.remove = pcf50633_input_remove,
+ };
+ module_platform_driver(pcf50633_input_driver);
+ 
+diff --git a/drivers/input/misc/pcf8574_keypad.c b/drivers/input/misc/pcf8574_keypad.c
+index 544c6635abe9..6c480bf58456 100644
+--- a/drivers/input/misc/pcf8574_keypad.c
++++ b/drivers/input/misc/pcf8574_keypad.c
+@@ -212,7 +212,7 @@ static struct i2c_driver pcf8574_kp_driver = {
+ #endif
+ 	},
+ 	.probe    = pcf8574_kp_probe,
+-	.remove   = __devexit_p(pcf8574_kp_remove),
++	.remove   = pcf8574_kp_remove,
+ 	.id_table = pcf8574_kp_id,
+ };
+ 
+diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c
+index b2484aa07f32..17d6555fec72 100644
+--- a/drivers/input/misc/pcspkr.c
++++ b/drivers/input/misc/pcspkr.c
+@@ -131,7 +131,7 @@ static struct platform_driver pcspkr_platform_driver = {
+ 		.pm	= &pcspkr_pm_ops,
+ 	},
+ 	.probe		= pcspkr_probe,
+-	.remove		= __devexit_p(pcspkr_remove),
++	.remove		= pcspkr_remove,
+ 	.shutdown	= pcspkr_shutdown,
+ };
+ module_platform_driver(pcspkr_platform_driver);
+diff --git a/drivers/input/misc/pm8xxx-vibrator.c b/drivers/input/misc/pm8xxx-vibrator.c
+index dfbfb463ea5d..2e0a3bfeff07 100644
+--- a/drivers/input/misc/pm8xxx-vibrator.c
++++ b/drivers/input/misc/pm8xxx-vibrator.c
+@@ -270,7 +270,7 @@ static SIMPLE_DEV_PM_OPS(pm8xxx_vib_pm_ops, pm8xxx_vib_suspend, NULL);
+ 
+ static struct platform_driver pm8xxx_vib_driver = {
+ 	.probe		= pm8xxx_vib_probe,
+-	.remove		= __devexit_p(pm8xxx_vib_remove),
++	.remove		= pm8xxx_vib_remove,
+ 	.driver		= {
+ 		.name	= "pm8xxx-vib",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c
+index 0f83d0f1d015..b2396e2ad369 100644
+--- a/drivers/input/misc/pmic8xxx-pwrkey.c
++++ b/drivers/input/misc/pmic8xxx-pwrkey.c
+@@ -206,7 +206,7 @@ static int __devexit pmic8xxx_pwrkey_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver pmic8xxx_pwrkey_driver = {
+ 	.probe		= pmic8xxx_pwrkey_probe,
+-	.remove		= __devexit_p(pmic8xxx_pwrkey_remove),
++	.remove		= pmic8xxx_pwrkey_remove,
+ 	.driver		= {
+ 		.name	= PM8XXX_PWRKEY_DEV_NAME,
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c
+index 502544c7e0a0..d40c2f630d5e 100644
+--- a/drivers/input/misc/pwm-beeper.c
++++ b/drivers/input/misc/pwm-beeper.c
+@@ -184,7 +184,7 @@ static const struct of_device_id pwm_beeper_match[] = {
+ 
+ static struct platform_driver pwm_beeper_driver = {
+ 	.probe	= pwm_beeper_probe,
+-	.remove = __devexit_p(pwm_beeper_remove),
++	.remove = pwm_beeper_remove,
+ 	.driver = {
+ 		.name	= "pwm-beeper",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/misc/rb532_button.c b/drivers/input/misc/rb532_button.c
+index aeb02bcf7233..718dd8367b6a 100644
+--- a/drivers/input/misc/rb532_button.c
++++ b/drivers/input/misc/rb532_button.c
+@@ -94,7 +94,7 @@ static int __devexit rb532_button_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver rb532_button_driver = {
+ 	.probe = rb532_button_probe,
+-	.remove = __devexit_p(rb532_button_remove),
++	.remove = rb532_button_remove,
+ 	.driver = {
+ 		.name = DRV_NAME,
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/input/misc/retu-pwrbutton.c b/drivers/input/misc/retu-pwrbutton.c
+index 3767f43ce37e..4500027d82a0 100644
+--- a/drivers/input/misc/retu-pwrbutton.c
++++ b/drivers/input/misc/retu-pwrbutton.c
+@@ -83,7 +83,7 @@ static int __devexit retu_pwrbutton_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver retu_pwrbutton_driver = {
+ 	.probe		= retu_pwrbutton_probe,
+-	.remove		= __devexit_p(retu_pwrbutton_remove),
++	.remove		= retu_pwrbutton_remove,
+ 	.driver		= {
+ 		.name	= "retu-pwrbutton",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c
+index 99a49e4968d2..b183a0e7a21a 100644
+--- a/drivers/input/misc/rotary_encoder.c
++++ b/drivers/input/misc/rotary_encoder.c
+@@ -325,7 +325,7 @@ static int __devexit rotary_encoder_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver rotary_encoder_driver = {
+ 	.probe		= rotary_encoder_probe,
+-	.remove		= __devexit_p(rotary_encoder_remove),
++	.remove		= rotary_encoder_remove,
+ 	.driver		= {
+ 		.name	= DRV_NAME,
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/misc/sgi_btns.c b/drivers/input/misc/sgi_btns.c
+index 5d9fd5571199..fd731e86e316 100644
+--- a/drivers/input/misc/sgi_btns.c
++++ b/drivers/input/misc/sgi_btns.c
+@@ -158,7 +158,7 @@ static int __devexit sgi_buttons_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver sgi_buttons_driver = {
+ 	.probe	= sgi_buttons_probe,
+-	.remove	= __devexit_p(sgi_buttons_remove),
++	.remove	= sgi_buttons_remove,
+ 	.driver	= {
+ 		.name	= "sgibtns",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c
+index 0122f5351577..b9c870251f14 100644
+--- a/drivers/input/misc/sparcspkr.c
++++ b/drivers/input/misc/sparcspkr.c
+@@ -263,7 +263,7 @@ static struct platform_driver bbc_beep_driver = {
+ 		.of_match_table = bbc_beep_match,
+ 	},
+ 	.probe		= bbc_beep_probe,
+-	.remove		= __devexit_p(bbc_remove),
++	.remove		= bbc_remove,
+ 	.shutdown	= sparcspkr_shutdown,
+ };
+ 
+@@ -345,7 +345,7 @@ static struct platform_driver grover_beep_driver = {
+ 		.of_match_table = grover_beep_match,
+ 	},
+ 	.probe		= grover_beep_probe,
+-	.remove		= __devexit_p(grover_remove),
++	.remove		= grover_remove,
+ 	.shutdown	= sparcspkr_shutdown,
+ };
+ 
+diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c
+index 2194a3c7236a..29f2207c5d04 100644
+--- a/drivers/input/misc/twl4030-vibra.c
++++ b/drivers/input/misc/twl4030-vibra.c
+@@ -283,7 +283,7 @@ static int __devexit twl4030_vibra_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver twl4030_vibra_driver = {
+ 	.probe		= twl4030_vibra_probe,
+-	.remove		= __devexit_p(twl4030_vibra_remove),
++	.remove		= twl4030_vibra_remove,
+ 	.driver		= {
+ 		.name	= "twl4030-vibra",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c
+index c8a288ae1d5b..463e96380def 100644
+--- a/drivers/input/misc/twl6040-vibra.c
++++ b/drivers/input/misc/twl6040-vibra.c
+@@ -433,7 +433,7 @@ static int __devexit twl6040_vibra_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver twl6040_vibra_driver = {
+ 	.probe		= twl6040_vibra_probe,
+-	.remove		= __devexit_p(twl6040_vibra_remove),
++	.remove		= twl6040_vibra_remove,
+ 	.driver		= {
+ 		.name	= "twl6040-vibra",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
+index e2bdfd4bea70..3f9ad238e4e9 100644
+--- a/drivers/input/misc/wistron_btns.c
++++ b/drivers/input/misc/wistron_btns.c
+@@ -1334,7 +1334,7 @@ static struct platform_driver wistron_driver = {
+ #endif
+ 	},
+ 	.probe		= wistron_probe,
+-	.remove		= __devexit_p(wistron_remove),
++	.remove		= wistron_remove,
+ };
+ 
+ static int __init wb_module_init(void)
+diff --git a/drivers/input/misc/wm831x-on.c b/drivers/input/misc/wm831x-on.c
+index fa8b3900d981..3a12951ad7fb 100644
+--- a/drivers/input/misc/wm831x-on.c
++++ b/drivers/input/misc/wm831x-on.c
+@@ -138,7 +138,7 @@ static int __devexit wm831x_on_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver wm831x_on_driver = {
+ 	.probe		= wm831x_on_probe,
+-	.remove		= __devexit_p(wm831x_on_remove),
++	.remove		= wm831x_on_remove,
+ 	.driver		= {
+ 		.name	= "wm831x-on",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c
+index 39fe9b737cae..b3a8aa95a2d8 100644
+--- a/drivers/input/mouse/gpio_mouse.c
++++ b/drivers/input/mouse/gpio_mouse.c
+@@ -172,7 +172,7 @@ static int __devexit gpio_mouse_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver gpio_mouse_device_driver = {
+ 	.probe		= gpio_mouse_probe,
+-	.remove		= __devexit_p(gpio_mouse_remove),
++	.remove		= gpio_mouse_remove,
+ 	.driver		= {
+ 		.name	= "gpio_mouse",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/mouse/maplemouse.c b/drivers/input/mouse/maplemouse.c
+index 5f278176eb9b..03ccf02c5475 100644
+--- a/drivers/input/mouse/maplemouse.c
++++ b/drivers/input/mouse/maplemouse.c
+@@ -132,7 +132,7 @@ static struct maple_driver dc_mouse_driver = {
+ 	.drv = {
+ 		.name = "Dreamcast_mouse",
+ 		.probe = probe_maple_mouse,
+-		.remove = __devexit_p(remove_maple_mouse),
++		.remove = remove_maple_mouse,
+ 	},
+ };
+ 
+diff --git a/drivers/input/mouse/navpoint.c b/drivers/input/mouse/navpoint.c
+index c29ae7654d5e..ac4e0771d05a 100644
+--- a/drivers/input/mouse/navpoint.c
++++ b/drivers/input/mouse/navpoint.c
+@@ -353,7 +353,7 @@ static SIMPLE_DEV_PM_OPS(navpoint_pm_ops, navpoint_suspend, navpoint_resume);
+ 
+ static struct platform_driver navpoint_driver = {
+ 	.probe		= navpoint_probe,
+-	.remove		= __devexit_p(navpoint_remove),
++	.remove		= navpoint_remove,
+ 	.driver = {
+ 		.name	= "navpoint",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/mouse/pxa930_trkball.c b/drivers/input/mouse/pxa930_trkball.c
+index 4fe055f2c536..953a0481efc1 100644
+--- a/drivers/input/mouse/pxa930_trkball.c
++++ b/drivers/input/mouse/pxa930_trkball.c
+@@ -248,7 +248,7 @@ static struct platform_driver pxa930_trkball_driver = {
+ 		.name	= "pxa930-trkball",
+ 	},
+ 	.probe		= pxa930_trkball_probe,
+-	.remove		= __devexit_p(pxa930_trkball_remove),
++	.remove		= pxa930_trkball_remove,
+ };
+ module_platform_driver(pxa930_trkball_driver);
+ 
+diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c
+index 063a174d3a88..fa8f162cbee3 100644
+--- a/drivers/input/mouse/synaptics_i2c.c
++++ b/drivers/input/mouse/synaptics_i2c.c
+@@ -662,7 +662,7 @@ static struct i2c_driver synaptics_i2c_driver = {
+ 	},
+ 
+ 	.probe		= synaptics_i2c_probe,
+-	.remove		= __devexit_p(synaptics_i2c_remove),
++	.remove		= synaptics_i2c_remove,
+ 
+ 	.id_table	= synaptics_i2c_id_table,
+ };
+diff --git a/drivers/input/serio/altera_ps2.c b/drivers/input/serio/altera_ps2.c
+index cc11f4efe119..50da8e5634c3 100644
+--- a/drivers/input/serio/altera_ps2.c
++++ b/drivers/input/serio/altera_ps2.c
+@@ -187,7 +187,7 @@ MODULE_DEVICE_TABLE(of, altera_ps2_match);
+  */
+ static struct platform_driver altera_ps2_driver = {
+ 	.probe		= altera_ps2_probe,
+-	.remove		= __devexit_p(altera_ps2_remove),
++	.remove		= altera_ps2_remove,
+ 	.driver	= {
+ 		.name	= DRV_NAME,
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c
+index 2e77246c2e5a..beb08160b39e 100644
+--- a/drivers/input/serio/ambakmi.c
++++ b/drivers/input/serio/ambakmi.c
+@@ -204,7 +204,7 @@ static struct amba_driver ambakmi_driver = {
+ 	},
+ 	.id_table	= amba_kmi_idtable,
+ 	.probe		= amba_kmi_probe,
+-	.remove		= __devexit_p(amba_kmi_remove),
++	.remove		= amba_kmi_remove,
+ 	.resume		= amba_kmi_resume,
+ };
+ 
+diff --git a/drivers/input/serio/arc_ps2.c b/drivers/input/serio/arc_ps2.c
+index 89ad7631848e..72fda8ff4e10 100644
+--- a/drivers/input/serio/arc_ps2.c
++++ b/drivers/input/serio/arc_ps2.c
+@@ -264,7 +264,7 @@ static struct platform_driver arc_ps2_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe	= arc_ps2_probe,
+-	.remove	= __devexit_p(arc_ps2_remove),
++	.remove	= arc_ps2_remove,
+ };
+ 
+ module_platform_driver(arc_ps2_driver);
+diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c
+index 852816567241..64bcd1559c68 100644
+--- a/drivers/input/serio/ct82c710.c
++++ b/drivers/input/serio/ct82c710.c
+@@ -212,7 +212,7 @@ static struct platform_driver ct82c710_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= ct82c710_probe,
+-	.remove		= __devexit_p(ct82c710_remove),
++	.remove		= ct82c710_remove,
+ };
+ 
+ 
+diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c
+index 4225f5d6b15f..49cb7ca55ff6 100644
+--- a/drivers/input/serio/gscps2.c
++++ b/drivers/input/serio/gscps2.c
+@@ -444,7 +444,7 @@ static struct parisc_driver parisc_ps2_driver = {
+ 	.name		= "gsc_ps2",
+ 	.id_table	= gscps2_device_tbl,
+ 	.probe		= gscps2_probe,
+-	.remove		= __devexit_p(gscps2_remove),
++	.remove		= gscps2_remove,
+ };
+ 
+ static int __init gscps2_init(void)
+diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h
+index 395a9af3adcd..3f6c835ae005 100644
+--- a/drivers/input/serio/i8042-sparcio.h
++++ b/drivers/input/serio/i8042-sparcio.h
+@@ -102,7 +102,7 @@ static struct platform_driver sparc_i8042_driver = {
+ 		.of_match_table = sparc_i8042_match,
+ 	},
+ 	.probe		= sparc_i8042_probe,
+-	.remove		= __devexit_p(sparc_i8042_remove),
++	.remove		= sparc_i8042_remove,
+ };
+ 
+ static int __init i8042_platform_init(void)
+diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
+index 86564414b75a..2539195729bd 100644
+--- a/drivers/input/serio/i8042.c
++++ b/drivers/input/serio/i8042.c
+@@ -1455,7 +1455,7 @@ static struct platform_driver i8042_driver = {
+ 		.pm	= &i8042_pm_ops,
+ #endif
+ 	},
+-	.remove		= __devexit_p(i8042_remove),
++	.remove		= i8042_remove,
+ 	.shutdown	= i8042_shutdown,
+ };
+ 
+diff --git a/drivers/input/serio/maceps2.c b/drivers/input/serio/maceps2.c
+index 61da763b1209..2226277089db 100644
+--- a/drivers/input/serio/maceps2.c
++++ b/drivers/input/serio/maceps2.c
+@@ -165,7 +165,7 @@ static struct platform_driver maceps2_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= maceps2_probe,
+-	.remove		= __devexit_p(maceps2_remove),
++	.remove		= maceps2_remove,
+ };
+ 
+ static int __init maceps2_init(void)
+diff --git a/drivers/input/serio/pcips2.c b/drivers/input/serio/pcips2.c
+index 0c42497aaaf4..98093731ae62 100644
+--- a/drivers/input/serio/pcips2.c
++++ b/drivers/input/serio/pcips2.c
+@@ -212,7 +212,7 @@ static struct pci_driver pcips2_driver = {
+ 	.name			= "pcips2",
+ 	.id_table		= pcips2_ids,
+ 	.probe			= pcips2_probe,
+-	.remove			= __devexit_p(pcips2_remove),
++	.remove			= pcips2_remove,
+ };
+ 
+ module_pci_driver(pcips2_driver);
+diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c
+index 0c0df7f73802..530488006105 100644
+--- a/drivers/input/serio/q40kbd.c
++++ b/drivers/input/serio/q40kbd.c
+@@ -190,7 +190,7 @@ static struct platform_driver q40kbd_driver = {
+ 		.name	= "q40kbd",
+ 		.owner	= THIS_MODULE,
+ 	},
+-	.remove		= __devexit_p(q40kbd_remove),
++	.remove		= q40kbd_remove,
+ };
+ 
+ static int __init q40kbd_init(void)
+diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c
+index 2af5df6a8fba..a5100d455e30 100644
+--- a/drivers/input/serio/rpckbd.c
++++ b/drivers/input/serio/rpckbd.c
+@@ -166,7 +166,7 @@ static int __devexit rpckbd_remove(struct platform_device *dev)
+ 
+ static struct platform_driver rpckbd_driver = {
+ 	.probe		= rpckbd_probe,
+-	.remove		= __devexit_p(rpckbd_remove),
++	.remove		= rpckbd_remove,
+ 	.driver		= {
+ 		.name	= "kart",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
+index 389766707534..4aacf4f94e3e 100644
+--- a/drivers/input/serio/sa1111ps2.c
++++ b/drivers/input/serio/sa1111ps2.c
+@@ -357,7 +357,7 @@ static struct sa1111_driver ps2_driver = {
+ 	},
+ 	.devid		= SA1111_DEVID_PS2,
+ 	.probe		= ps2_probe,
+-	.remove		= __devexit_p(ps2_remove),
++	.remove		= ps2_remove,
+ };
+ 
+ static int __init ps2_init(void)
+diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c
+index 1e983bec7d86..73f90dd8eee6 100644
+--- a/drivers/input/serio/xilinx_ps2.c
++++ b/drivers/input/serio/xilinx_ps2.c
+@@ -368,7 +368,7 @@ static struct platform_driver xps2_of_driver = {
+ 		.of_match_table = xps2_of_match,
+ 	},
+ 	.probe		= xps2_of_probe,
+-	.remove		= __devexit_p(xps2_of_remove),
++	.remove		= xps2_of_remove,
+ };
+ module_platform_driver(xps2_of_driver);
+ 
+diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c
+index 326218dbd6e6..e609db85bea1 100644
+--- a/drivers/input/touchscreen/88pm860x-ts.c
++++ b/drivers/input/touchscreen/88pm860x-ts.c
+@@ -310,7 +310,7 @@ static struct platform_driver pm860x_touch_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe	= pm860x_touch_probe,
+-	.remove	= __devexit_p(pm860x_touch_remove),
++	.remove	= pm860x_touch_remove,
+ };
+ module_platform_driver(pm860x_touch_driver);
+ 
+diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c
+index 2c7692108e6c..d2df6a48ba65 100644
+--- a/drivers/input/touchscreen/ad7877.c
++++ b/drivers/input/touchscreen/ad7877.c
+@@ -857,7 +857,7 @@ static struct spi_driver ad7877_driver = {
+ 		.pm	= &ad7877_pm,
+ 	},
+ 	.probe		= ad7877_probe,
+-	.remove		= __devexit_p(ad7877_remove),
++	.remove		= ad7877_remove,
+ };
+ 
+ module_spi_driver(ad7877_driver);
+diff --git a/drivers/input/touchscreen/ad7879-i2c.c b/drivers/input/touchscreen/ad7879-i2c.c
+index 3054354d0dd3..850c95d69198 100644
+--- a/drivers/input/touchscreen/ad7879-i2c.c
++++ b/drivers/input/touchscreen/ad7879-i2c.c
+@@ -98,7 +98,7 @@ static struct i2c_driver ad7879_i2c_driver = {
+ 		.pm	= &ad7879_pm_ops,
+ 	},
+ 	.probe		= ad7879_i2c_probe,
+-	.remove		= __devexit_p(ad7879_i2c_remove),
++	.remove		= ad7879_i2c_remove,
+ 	.id_table	= ad7879_id,
+ };
+ 
+diff --git a/drivers/input/touchscreen/ad7879-spi.c b/drivers/input/touchscreen/ad7879-spi.c
+index db49abf056ba..86b0fdb6046b 100644
+--- a/drivers/input/touchscreen/ad7879-spi.c
++++ b/drivers/input/touchscreen/ad7879-spi.c
+@@ -154,7 +154,7 @@ static struct spi_driver ad7879_spi_driver = {
+ 		.pm	= &ad7879_pm_ops,
+ 	},
+ 	.probe		= ad7879_spi_probe,
+-	.remove		= __devexit_p(ad7879_spi_remove),
++	.remove		= ad7879_spi_remove,
+ };
+ 
+ module_spi_driver(ad7879_spi_driver);
+diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
+index 78e5d9ab0ba7..560484de0bfb 100644
+--- a/drivers/input/touchscreen/ads7846.c
++++ b/drivers/input/touchscreen/ads7846.c
+@@ -1434,7 +1434,7 @@ static struct spi_driver ads7846_driver = {
+ 		.pm	= &ads7846_pm,
+ 	},
+ 	.probe		= ads7846_probe,
+-	.remove		= __devexit_p(ads7846_remove),
++	.remove		= ads7846_remove,
+ };
+ 
+ module_spi_driver(ads7846_driver);
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 1df2396af008..6199303d9d3c 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -1270,7 +1270,7 @@ static struct i2c_driver mxt_driver = {
+ 		.pm	= &mxt_pm_ops,
+ 	},
+ 	.probe		= mxt_probe,
+-	.remove		= __devexit_p(mxt_remove),
++	.remove		= mxt_remove,
+ 	.id_table	= mxt_id,
+ };
+ 
+diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c
+index 201b2d2ec1b3..53712b9142a5 100644
+--- a/drivers/input/touchscreen/atmel_tsadcc.c
++++ b/drivers/input/touchscreen/atmel_tsadcc.c
+@@ -346,7 +346,7 @@ static int __devexit atmel_tsadcc_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver atmel_tsadcc_driver = {
+ 	.probe		= atmel_tsadcc_probe,
+-	.remove		= __devexit_p(atmel_tsadcc_remove),
++	.remove		= atmel_tsadcc_remove,
+ 	.driver		= {
+ 		.name	= "atmel_tsadcc",
+ 	},
+diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c
+index c7047b6bb020..912926dd97c0 100644
+--- a/drivers/input/touchscreen/auo-pixcir-ts.c
++++ b/drivers/input/touchscreen/auo-pixcir-ts.c
+@@ -631,7 +631,7 @@ static struct i2c_driver auo_pixcir_driver = {
+ 		.pm	= &auo_pixcir_pm_ops,
+ 	},
+ 	.probe		= auo_pixcir_probe,
+-	.remove		= __devexit_p(auo_pixcir_remove),
++	.remove		= auo_pixcir_remove,
+ 	.id_table	= auo_pixcir_idtable,
+ };
+ 
+diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c
+index 5c487d23f11c..c2be1fe51923 100644
+--- a/drivers/input/touchscreen/bu21013_ts.c
++++ b/drivers/input/touchscreen/bu21013_ts.c
+@@ -649,7 +649,7 @@ static struct i2c_driver bu21013_driver = {
+ #endif
+ 	},
+ 	.probe		=	bu21013_probe,
+-	.remove		=	__devexit_p(bu21013_remove),
++	.remove		=	bu21013_remove,
+ 	.id_table	=	bu21013_id,
+ };
+ 
+diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c
+index ad6a6640f385..9a2044f978ae 100644
+--- a/drivers/input/touchscreen/cy8ctmg110_ts.c
++++ b/drivers/input/touchscreen/cy8ctmg110_ts.c
+@@ -357,7 +357,7 @@ static struct i2c_driver cy8ctmg110_driver = {
+ 	},
+ 	.id_table	= cy8ctmg110_idtable,
+ 	.probe		= cy8ctmg110_probe,
+-	.remove		= __devexit_p(cy8ctmg110_remove),
++	.remove		= cy8ctmg110_remove,
+ };
+ 
+ module_i2c_driver(cy8ctmg110_driver);
+diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c
+index 2af1d0c52bcd..1a7aca935b26 100644
+--- a/drivers/input/touchscreen/cyttsp_i2c.c
++++ b/drivers/input/touchscreen/cyttsp_i2c.c
+@@ -124,7 +124,7 @@ static struct i2c_driver cyttsp_i2c_driver = {
+ 		.pm	= &cyttsp_pm_ops,
+ 	},
+ 	.probe		= cyttsp_i2c_probe,
+-	.remove		= __devexit_p(cyttsp_i2c_remove),
++	.remove		= cyttsp_i2c_remove,
+ 	.id_table	= cyttsp_i2c_id,
+ };
+ 
+diff --git a/drivers/input/touchscreen/cyttsp_spi.c b/drivers/input/touchscreen/cyttsp_spi.c
+index 9f263410407b..915af4cfe2b2 100644
+--- a/drivers/input/touchscreen/cyttsp_spi.c
++++ b/drivers/input/touchscreen/cyttsp_spi.c
+@@ -188,7 +188,7 @@ static struct spi_driver cyttsp_spi_driver = {
+ 		.pm	= &cyttsp_pm_ops,
+ 	},
+ 	.probe  = cyttsp_spi_probe,
+-	.remove = __devexit_p(cyttsp_spi_remove),
++	.remove = cyttsp_spi_remove,
+ };
+ 
+ module_spi_driver(cyttsp_spi_driver);
+diff --git a/drivers/input/touchscreen/da9034-ts.c b/drivers/input/touchscreen/da9034-ts.c
+index 36b65cf10d7f..ec156a6bf59d 100644
+--- a/drivers/input/touchscreen/da9034-ts.c
++++ b/drivers/input/touchscreen/da9034-ts.c
+@@ -377,7 +377,7 @@ static struct platform_driver da9034_touch_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= da9034_touch_probe,
+-	.remove		= __devexit_p(da9034_touch_remove),
++	.remove		= da9034_touch_remove,
+ };
+ module_platform_driver(da9034_touch_driver);
+ 
+diff --git a/drivers/input/touchscreen/da9052_tsi.c b/drivers/input/touchscreen/da9052_tsi.c
+index e8df341090c0..5dfb39b21c90 100644
+--- a/drivers/input/touchscreen/da9052_tsi.c
++++ b/drivers/input/touchscreen/da9052_tsi.c
+@@ -355,7 +355,7 @@ static int  __devexit da9052_ts_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver da9052_tsi_driver = {
+ 	.probe	= da9052_ts_probe,
+-	.remove	= __devexit_p(da9052_ts_remove),
++	.remove	= da9052_ts_remove,
+ 	.driver	= {
+ 		.name	= "da9052-tsi",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
+index d9c6007e445f..65ed9d958e5f 100644
+--- a/drivers/input/touchscreen/edt-ft5x06.c
++++ b/drivers/input/touchscreen/edt-ft5x06.c
+@@ -883,7 +883,7 @@ static struct i2c_driver edt_ft5x06_ts_driver = {
+ 	},
+ 	.id_table = edt_ft5x06_ts_id,
+ 	.probe    = edt_ft5x06_ts_probe,
+-	.remove   = __devexit_p(edt_ft5x06_ts_remove),
++	.remove   = edt_ft5x06_ts_remove,
+ };
+ 
+ module_i2c_driver(edt_ft5x06_ts_driver);
+diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c
+index 908407efc672..a2d9a65e586d 100644
+--- a/drivers/input/touchscreen/eeti_ts.c
++++ b/drivers/input/touchscreen/eeti_ts.c
+@@ -321,7 +321,7 @@ static struct i2c_driver eeti_ts_driver = {
+ #endif
+ 	},
+ 	.probe = eeti_ts_probe,
+-	.remove = __devexit_p(eeti_ts_remove),
++	.remove = eeti_ts_remove,
+ 	.id_table = eeti_ts_id,
+ };
+ 
+diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c
+index 13fa62fdfb0b..d85078d06497 100644
+--- a/drivers/input/touchscreen/egalax_ts.c
++++ b/drivers/input/touchscreen/egalax_ts.c
+@@ -301,7 +301,7 @@ static struct i2c_driver egalax_ts_driver = {
+ 	},
+ 	.id_table	= egalax_ts_id,
+ 	.probe		= egalax_ts_probe,
+-	.remove		= __devexit_p(egalax_ts_remove),
++	.remove		= egalax_ts_remove,
+ };
+ 
+ module_i2c_driver(egalax_ts_driver);
+diff --git a/drivers/input/touchscreen/htcpen.c b/drivers/input/touchscreen/htcpen.c
+index d13143b68b3e..5cc3240139ec 100644
+--- a/drivers/input/touchscreen/htcpen.c
++++ b/drivers/input/touchscreen/htcpen.c
+@@ -210,7 +210,7 @@ static int htcpen_isa_resume(struct device *dev, unsigned int n)
+ 
+ static struct isa_driver htcpen_isa_driver = {
+ 	.probe		= htcpen_isa_probe,
+-	.remove		= __devexit_p(htcpen_isa_remove),
++	.remove		= htcpen_isa_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= htcpen_isa_suspend,
+ 	.resume		= htcpen_isa_resume,
+diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c
+index 4ac69760ec08..e8fd6c26b76c 100644
+--- a/drivers/input/touchscreen/ili210x.c
++++ b/drivers/input/touchscreen/ili210x.c
+@@ -350,7 +350,7 @@ static struct i2c_driver ili210x_ts_driver = {
+ 	},
+ 	.id_table = ili210x_i2c_id,
+ 	.probe = ili210x_i2c_probe,
+-	.remove = __devexit_p(ili210x_i2c_remove),
++	.remove = ili210x_i2c_remove,
+ };
+ 
+ module_i2c_driver(ili210x_ts_driver);
+diff --git a/drivers/input/touchscreen/intel-mid-touch.c b/drivers/input/touchscreen/intel-mid-touch.c
+index cf299377fc49..f27364f7ad11 100644
+--- a/drivers/input/touchscreen/intel-mid-touch.c
++++ b/drivers/input/touchscreen/intel-mid-touch.c
+@@ -662,7 +662,7 @@ static struct platform_driver mrstouch_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= mrstouch_probe,
+-	.remove		= __devexit_p(mrstouch_remove),
++	.remove		= mrstouch_remove,
+ };
+ module_platform_driver(mrstouch_driver);
+ 
+diff --git a/drivers/input/touchscreen/jornada720_ts.c b/drivers/input/touchscreen/jornada720_ts.c
+index 7f03d1bd916e..ad35c8ceac26 100644
+--- a/drivers/input/touchscreen/jornada720_ts.c
++++ b/drivers/input/touchscreen/jornada720_ts.c
+@@ -168,7 +168,7 @@ MODULE_ALIAS("platform:jornada_ts");
+ 
+ static struct platform_driver jornada720_ts_driver = {
+ 	.probe		= jornada720_ts_probe,
+-	.remove		= __devexit_p(jornada720_ts_remove),
++	.remove		= jornada720_ts_remove,
+ 	.driver		= {
+ 		.name	= "jornada_ts",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/touchscreen/lpc32xx_ts.c b/drivers/input/touchscreen/lpc32xx_ts.c
+index 4c2b8ed3bf16..8134f6100de0 100644
+--- a/drivers/input/touchscreen/lpc32xx_ts.c
++++ b/drivers/input/touchscreen/lpc32xx_ts.c
+@@ -394,7 +394,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_tsc_of_match);
+ 
+ static struct platform_driver lpc32xx_ts_driver = {
+ 	.probe		= lpc32xx_ts_probe,
+-	.remove		= __devexit_p(lpc32xx_ts_remove),
++	.remove		= lpc32xx_ts_remove,
+ 	.driver		= {
+ 		.name	= MOD_NAME,
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/touchscreen/max11801_ts.c b/drivers/input/touchscreen/max11801_ts.c
+index 4eab50b856d7..e3e637f01609 100644
+--- a/drivers/input/touchscreen/max11801_ts.c
++++ b/drivers/input/touchscreen/max11801_ts.c
+@@ -252,7 +252,7 @@ static struct i2c_driver max11801_ts_driver = {
+ 	},
+ 	.id_table	= max11801_ts_id,
+ 	.probe		= max11801_ts_probe,
+-	.remove		= __devexit_p(max11801_ts_remove),
++	.remove		= max11801_ts_remove,
+ };
+ 
+ module_i2c_driver(max11801_ts_driver);
+diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c
+index 48dc5b0d26f1..5c18c5cb9f7a 100644
+--- a/drivers/input/touchscreen/mc13783_ts.c
++++ b/drivers/input/touchscreen/mc13783_ts.c
+@@ -243,7 +243,7 @@ static int __devexit mc13783_ts_remove(struct platform_device *pdev)
+ }
+ 
+ static struct platform_driver mc13783_ts_driver = {
+-	.remove		= __devexit_p(mc13783_ts_remove),
++	.remove		= mc13783_ts_remove,
+ 	.driver		= {
+ 		.owner	= THIS_MODULE,
+ 		.name	= MC13783_TS_NAME,
+diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c
+index b528511861ce..94a4ff6de3f9 100644
+--- a/drivers/input/touchscreen/mcs5000_ts.c
++++ b/drivers/input/touchscreen/mcs5000_ts.c
+@@ -292,7 +292,7 @@ MODULE_DEVICE_TABLE(i2c, mcs5000_ts_id);
+ 
+ static struct i2c_driver mcs5000_ts_driver = {
+ 	.probe		= mcs5000_ts_probe,
+-	.remove		= __devexit_p(mcs5000_ts_remove),
++	.remove		= mcs5000_ts_remove,
+ 	.driver = {
+ 		.name = "mcs5000_ts",
+ #ifdef CONFIG_PM
+diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
+index 3426d2e11a36..f4c1bc8a5a8d 100644
+--- a/drivers/input/touchscreen/mms114.c
++++ b/drivers/input/touchscreen/mms114.c
+@@ -590,7 +590,7 @@ static struct i2c_driver mms114_driver = {
+ 		.of_match_table = of_match_ptr(mms114_dt_match),
+ 	},
+ 	.probe		= mms114_probe,
+-	.remove		= __devexit_p(mms114_remove),
++	.remove		= mms114_remove,
+ 	.id_table	= mms114_id,
+ };
+ 
+diff --git a/drivers/input/touchscreen/pcap_ts.c b/drivers/input/touchscreen/pcap_ts.c
+index f57aeb80f7e3..97f07baa6e8f 100644
+--- a/drivers/input/touchscreen/pcap_ts.c
++++ b/drivers/input/touchscreen/pcap_ts.c
+@@ -245,7 +245,7 @@ static const struct dev_pm_ops pcap_ts_pm_ops = {
+ 
+ static struct platform_driver pcap_ts_driver = {
+ 	.probe		= pcap_ts_probe,
+-	.remove		= __devexit_p(pcap_ts_remove),
++	.remove		= pcap_ts_remove,
+ 	.driver		= {
+ 		.name	= "pcap-ts",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
+index 953b4c105cad..4fcb63e4337b 100644
+--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
++++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
+@@ -218,7 +218,7 @@ static struct i2c_driver pixcir_i2c_ts_driver = {
+ 		.pm	= &pixcir_dev_pm_ops,
+ 	},
+ 	.probe		= pixcir_i2c_ts_probe,
+-	.remove		= __devexit_p(pixcir_i2c_ts_remove),
++	.remove		= pixcir_i2c_ts_remove,
+ 	.id_table	= pixcir_i2c_ts_id,
+ };
+ 
+diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c
+index 549fa29548f8..4dda7656e077 100644
+--- a/drivers/input/touchscreen/s3c2410_ts.c
++++ b/drivers/input/touchscreen/s3c2410_ts.c
+@@ -430,7 +430,7 @@ static struct platform_driver s3c_ts_driver = {
+ 	},
+ 	.id_table	= s3cts_driver_ids,
+ 	.probe		= s3c2410ts_probe,
+-	.remove		= __devexit_p(s3c2410ts_remove),
++	.remove		= s3c2410ts_remove,
+ };
+ module_platform_driver(s3c_ts_driver);
+ 
+diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c
+index 6cb68a1981bf..62a4b5d71643 100644
+--- a/drivers/input/touchscreen/st1232.c
++++ b/drivers/input/touchscreen/st1232.c
+@@ -264,7 +264,7 @@ MODULE_DEVICE_TABLE(of, st1232_ts_dt_ids);
+ 
+ static struct i2c_driver st1232_ts_driver = {
+ 	.probe		= st1232_ts_probe,
+-	.remove		= __devexit_p(st1232_ts_remove),
++	.remove		= st1232_ts_remove,
+ 	.id_table	= st1232_ts_id,
+ 	.driver = {
+ 		.name	= ST1232_TS_NAME,
+diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c
+index 43e796747f4b..f4897545ec6c 100644
+--- a/drivers/input/touchscreen/stmpe-ts.c
++++ b/drivers/input/touchscreen/stmpe-ts.c
+@@ -386,7 +386,7 @@ static struct platform_driver stmpe_ts_driver = {
+ 		   .owner = THIS_MODULE,
+ 		   },
+ 	.probe = stmpe_input_probe,
+-	.remove = __devexit_p(stmpe_ts_remove),
++	.remove = stmpe_ts_remove,
+ };
+ module_platform_driver(stmpe_ts_driver);
+ 
+diff --git a/drivers/input/touchscreen/tnetv107x-ts.c b/drivers/input/touchscreen/tnetv107x-ts.c
+index 368d2c6cf780..62d57e8d49fe 100644
+--- a/drivers/input/touchscreen/tnetv107x-ts.c
++++ b/drivers/input/touchscreen/tnetv107x-ts.c
+@@ -374,7 +374,7 @@ static int __devexit tsc_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver tsc_driver = {
+ 	.probe		= tsc_probe,
+-	.remove		= __devexit_p(tsc_remove),
++	.remove		= tsc_remove,
+ 	.driver.name	= "tnetv107x-ts",
+ 	.driver.owner	= THIS_MODULE,
+ };
+diff --git a/drivers/input/touchscreen/tps6507x-ts.c b/drivers/input/touchscreen/tps6507x-ts.c
+index f7eda3d00fad..e1ec9e074ed3 100644
+--- a/drivers/input/touchscreen/tps6507x-ts.c
++++ b/drivers/input/touchscreen/tps6507x-ts.c
+@@ -367,7 +367,7 @@ static struct platform_driver tps6507x_ts_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = tps6507x_ts_probe,
+-	.remove = __devexit_p(tps6507x_ts_remove),
++	.remove = tps6507x_ts_remove,
+ };
+ module_platform_driver(tps6507x_ts_driver);
+ 
+diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c
+index 5ce3fa8ce646..db472a80bcb2 100644
+--- a/drivers/input/touchscreen/tsc2005.c
++++ b/drivers/input/touchscreen/tsc2005.c
+@@ -745,7 +745,7 @@ static struct spi_driver tsc2005_driver = {
+ 		.pm	= &tsc2005_pm_ops,
+ 	},
+ 	.probe	= tsc2005_probe,
+-	.remove	= __devexit_p(tsc2005_remove),
++	.remove	= tsc2005_remove,
+ };
+ 
+ module_spi_driver(tsc2005_driver);
+diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c
+index 1473d2382afd..3b195835cb03 100644
+--- a/drivers/input/touchscreen/tsc2007.c
++++ b/drivers/input/touchscreen/tsc2007.c
+@@ -396,7 +396,7 @@ static struct i2c_driver tsc2007_driver = {
+ 	},
+ 	.id_table	= tsc2007_idtable,
+ 	.probe		= tsc2007_probe,
+-	.remove		= __devexit_p(tsc2007_remove),
++	.remove		= tsc2007_remove,
+ };
+ 
+ module_i2c_driver(tsc2007_driver);
+diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
+index 46e83ad53f43..780eda612547 100644
+--- a/drivers/input/touchscreen/ucb1400_ts.c
++++ b/drivers/input/touchscreen/ucb1400_ts.c
+@@ -442,7 +442,7 @@ static SIMPLE_DEV_PM_OPS(ucb1400_ts_pm_ops,
+ 
+ static struct platform_driver ucb1400_ts_driver = {
+ 	.probe	= ucb1400_ts_probe,
+-	.remove	= __devexit_p(ucb1400_ts_remove),
++	.remove	= ucb1400_ts_remove,
+ 	.driver	= {
+ 		.name	= "ucb1400_ts",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/touchscreen/w90p910_ts.c b/drivers/input/touchscreen/w90p910_ts.c
+index 9396b21d0e8f..039e4eadb6ac 100644
+--- a/drivers/input/touchscreen/w90p910_ts.c
++++ b/drivers/input/touchscreen/w90p910_ts.c
+@@ -325,7 +325,7 @@ static int __devexit w90x900ts_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver w90x900ts_driver = {
+ 	.probe		= w90x900ts_probe,
+-	.remove		= __devexit_p(w90x900ts_remove),
++	.remove		= w90x900ts_remove,
+ 	.driver		= {
+ 		.name	= "nuc900-ts",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c
+index 0c01657132fd..0c033dfbd73e 100644
+--- a/drivers/input/touchscreen/wacom_i2c.c
++++ b/drivers/input/touchscreen/wacom_i2c.c
+@@ -272,7 +272,7 @@ static struct i2c_driver wacom_i2c_driver = {
+ 	},
+ 
+ 	.probe		= wacom_i2c_probe,
+-	.remove		= __devexit_p(wacom_i2c_remove),
++	.remove		= wacom_i2c_remove,
+ 	.id_table	= wacom_i2c_id,
+ };
+ module_i2c_driver(wacom_i2c_driver);
+diff --git a/drivers/input/touchscreen/wm831x-ts.c b/drivers/input/touchscreen/wm831x-ts.c
+index c7eee56d0087..17f14b69438a 100644
+--- a/drivers/input/touchscreen/wm831x-ts.c
++++ b/drivers/input/touchscreen/wm831x-ts.c
+@@ -398,7 +398,7 @@ static struct platform_driver wm831x_ts_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = wm831x_ts_probe,
+-	.remove = __devexit_p(wm831x_ts_remove),
++	.remove = wm831x_ts_remove,
+ };
+ module_platform_driver(wm831x_ts_driver);
+ 

commit 58b45d166f4c16d21f6aa059c6c5d87a9eeb1ff5
+Author: Bill Pemberton 
+Date:   Thu Nov 22 23:28:57 2012 -0800
+
+    Input: serio - remove CONFIG_HOTPLUG ifdefs
+    
+    Remove conditional code based on CONFIG_HOTPLUG being false.  It's
+    always on now in preparation of it going away as an option.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Dmitry Torokhov 
+
+diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
+index d0f7533dbf88..25fc5971f426 100644
+--- a/drivers/input/serio/serio.c
++++ b/drivers/input/serio/serio.c
+@@ -891,8 +891,6 @@ static int serio_bus_match(struct device *dev, struct device_driver *drv)
+ 	return serio_match_port(serio_drv->id_table, serio);
+ }
+ 
+-#ifdef CONFIG_HOTPLUG
+-
+ #define SERIO_ADD_UEVENT_VAR(fmt, val...)				\
+ 	do {								\
+ 		int err = add_uevent_var(env, fmt, val);		\
+@@ -920,15 +918,6 @@ static int serio_uevent(struct device *dev, struct kobj_uevent_env *env)
+ }
+ #undef SERIO_ADD_UEVENT_VAR
+ 
+-#else
+-
+-static int serio_uevent(struct device *dev, struct kobj_uevent_env *env)
+-{
+-	return -ENODEV;
+-}
+-
+-#endif /* CONFIG_HOTPLUG */
+-
+ #ifdef CONFIG_PM
+ static int serio_suspend(struct device *dev)
+ {

commit 810b7e060c14110d8f580daaf77fab3a7d950483
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:04 2012 -0500
+
+    mtd: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Artem Bityutskiy 
+
+diff --git a/drivers/mtd/devices/bcm47xxsflash.c b/drivers/mtd/devices/bcm47xxsflash.c
+index 113aced64990..4714584aa993 100644
+--- a/drivers/mtd/devices/bcm47xxsflash.c
++++ b/drivers/mtd/devices/bcm47xxsflash.c
+@@ -66,7 +66,7 @@ static int bcm47xxsflash_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit bcm47xxsflash_remove(struct platform_device *pdev)
++static int bcm47xxsflash_remove(struct platform_device *pdev)
+ {
+ 	struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev);
+ 
+diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
+index 681e2ee0f2d6..8debac9efde9 100644
+--- a/drivers/mtd/devices/block2mtd.c
++++ b/drivers/mtd/devices/block2mtd.c
+@@ -433,7 +433,7 @@ static int __init block2mtd_init(void)
+ }
+ 
+ 
+-static void __devexit block2mtd_exit(void)
++static void block2mtd_exit(void)
+ {
+ 	struct list_head *pos, *next;
+ 
+diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
+index ae43b0154003..f402b67a5314 100644
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -972,7 +972,7 @@ static int m25p_probe(struct spi_device *spi)
+ }
+ 
+ 
+-static int __devexit m25p_remove(struct spi_device *spi)
++static int m25p_remove(struct spi_device *spi)
+ {
+ 	struct m25p	*flash = dev_get_drvdata(&spi->dev);
+ 	int		status;
+diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
+index 0b3f17361acb..0caefb400f0c 100644
+--- a/drivers/mtd/devices/mtd_dataflash.c
++++ b/drivers/mtd/devices/mtd_dataflash.c
+@@ -897,7 +897,7 @@ static int dataflash_probe(struct spi_device *spi)
+ 	return status;
+ }
+ 
+-static int __devexit dataflash_remove(struct spi_device *spi)
++static int dataflash_remove(struct spi_device *spi)
+ {
+ 	struct dataflash	*flash = dev_get_drvdata(&spi->dev);
+ 	int			status;
+diff --git a/drivers/mtd/devices/spear_smi.c b/drivers/mtd/devices/spear_smi.c
+index a30cd27ab916..2d2c2a5d4d2a 100644
+--- a/drivers/mtd/devices/spear_smi.c
++++ b/drivers/mtd/devices/spear_smi.c
+@@ -1016,7 +1016,7 @@ static int spear_smi_probe(struct platform_device *pdev)
+  *
+  * free all allocations and delete the partitions.
+  */
+-static int __devexit spear_smi_remove(struct platform_device *pdev)
++static int spear_smi_remove(struct platform_device *pdev)
+ {
+ 	struct spear_smi *dev;
+ 	struct spear_snor_flash *flash;
+diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c
+index e4f233941bf6..8091b0163694 100644
+--- a/drivers/mtd/devices/sst25l.c
++++ b/drivers/mtd/devices/sst25l.c
+@@ -411,7 +411,7 @@ static int sst25l_probe(struct spi_device *spi)
+ 	return 0;
+ }
+ 
+-static int __devexit sst25l_remove(struct spi_device *spi)
++static int sst25l_remove(struct spi_device *spi)
+ {
+ 	struct sst25l_flash *flash = dev_get_drvdata(&spi->dev);
+ 	int ret;
+diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c
+index 1a4f671181f4..31ee5c8dd5f4 100644
+--- a/drivers/mtd/maps/amd76xrom.c
++++ b/drivers/mtd/maps/amd76xrom.c
+@@ -289,7 +289,7 @@ static int amd76xrom_init_one (struct pci_dev *pdev,
+ }
+ 
+ 
+-static void __devexit amd76xrom_remove_one (struct pci_dev *pdev)
++static void amd76xrom_remove_one (struct pci_dev *pdev)
+ {
+ 	struct amd76xrom_window *window = &amd76xrom_window;
+ 
+diff --git a/drivers/mtd/maps/autcpu12-nvram.c b/drivers/mtd/maps/autcpu12-nvram.c
+index b8c858913bbe..a2dc2ae4b24e 100644
+--- a/drivers/mtd/maps/autcpu12-nvram.c
++++ b/drivers/mtd/maps/autcpu12-nvram.c
+@@ -105,7 +105,7 @@ static int autcpu12_nvram_probe(struct platform_device *pdev)
+ 	return -ENOMEM;
+ }
+ 
+-static int __devexit autcpu12_nvram_remove(struct platform_device *pdev)
++static int autcpu12_nvram_remove(struct platform_device *pdev)
+ {
+ 	struct autcpu12_nvram_priv *priv = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c
+index 6057c6404289..7d484de4abea 100644
+--- a/drivers/mtd/maps/bfin-async-flash.c
++++ b/drivers/mtd/maps/bfin-async-flash.c
+@@ -172,7 +172,7 @@ static int bfin_flash_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit bfin_flash_remove(struct platform_device *pdev)
++static int bfin_flash_remove(struct platform_device *pdev)
+ {
+ 	struct async_state *state = platform_get_drvdata(pdev);
+ 	gpio_free(state->enet_flash_pin);
+diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c
+index 65fedb9f296a..0ac41f2e3013 100644
+--- a/drivers/mtd/maps/ck804xrom.c
++++ b/drivers/mtd/maps/ck804xrom.c
+@@ -320,7 +320,7 @@ static int ck804xrom_init_one (struct pci_dev *pdev,
+ }
+ 
+ 
+-static void __devexit ck804xrom_remove_one (struct pci_dev *pdev)
++static void ck804xrom_remove_one (struct pci_dev *pdev)
+ {
+ 	struct ck804xrom_window *window = &ck804xrom_window;
+ 
+diff --git a/drivers/mtd/maps/esb2rom.c b/drivers/mtd/maps/esb2rom.c
+index 664303f11f08..6d6cb8857e40 100644
+--- a/drivers/mtd/maps/esb2rom.c
++++ b/drivers/mtd/maps/esb2rom.c
+@@ -378,7 +378,7 @@ static int esb2rom_init_one(struct pci_dev *pdev,
+ 	return 0;
+ }
+ 
+-static void __devexit esb2rom_remove_one (struct pci_dev *pdev)
++static void esb2rom_remove_one (struct pci_dev *pdev)
+ {
+ 	struct esb2rom_window *window = &esb2rom_window;
+ 	esb2rom_cleanup(window);
+diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c
+index 4babe04dda50..41aa8db36020 100644
+--- a/drivers/mtd/maps/gpio-addr-flash.c
++++ b/drivers/mtd/maps/gpio-addr-flash.c
+@@ -258,7 +258,7 @@ static int gpio_flash_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit gpio_flash_remove(struct platform_device *pdev)
++static int gpio_flash_remove(struct platform_device *pdev)
+ {
+ 	struct async_state *state = platform_get_drvdata(pdev);
+ 	size_t i = 0;
+diff --git a/drivers/mtd/maps/ichxrom.c b/drivers/mtd/maps/ichxrom.c
+index 9673601c3833..03d60efda277 100644
+--- a/drivers/mtd/maps/ichxrom.c
++++ b/drivers/mtd/maps/ichxrom.c
+@@ -315,7 +315,7 @@ static int ichxrom_init_one (struct pci_dev *pdev,
+ }
+ 
+ 
+-static void __devexit ichxrom_remove_one (struct pci_dev *pdev)
++static void ichxrom_remove_one (struct pci_dev *pdev)
+ {
+ 	struct ichxrom_window *window = &ichxrom_window;
+ 	ichxrom_cleanup(window);
+diff --git a/drivers/mtd/maps/intel_vr_nor.c b/drivers/mtd/maps/intel_vr_nor.c
+index 1694c03e4884..3ee2ad1dcbe7 100644
+--- a/drivers/mtd/maps/intel_vr_nor.c
++++ b/drivers/mtd/maps/intel_vr_nor.c
+@@ -63,7 +63,7 @@ struct vr_nor_mtd {
+ #define TIMING_BYTE_EN		(1 <<  0)	/* 8-bit vs 16-bit bus */
+ #define TIMING_MASK		0x3FFF0000
+ 
+-static void __devexit vr_nor_destroy_partitions(struct vr_nor_mtd *p)
++static void vr_nor_destroy_partitions(struct vr_nor_mtd *p)
+ {
+ 	mtd_device_unregister(p->info);
+ }
+@@ -75,7 +75,7 @@ static int vr_nor_init_partitions(struct vr_nor_mtd *p)
+ 	return mtd_device_parse_register(p->info, NULL, NULL, NULL, 0);
+ }
+ 
+-static void __devexit vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p)
++static void vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p)
+ {
+ 	map_destroy(p->info);
+ }
+@@ -96,7 +96,7 @@ static int vr_nor_mtd_setup(struct vr_nor_mtd *p)
+ 	return 0;
+ }
+ 
+-static void __devexit vr_nor_destroy_maps(struct vr_nor_mtd *p)
++static void vr_nor_destroy_maps(struct vr_nor_mtd *p)
+ {
+ 	unsigned int exp_timing_cs0;
+ 
+@@ -176,7 +176,7 @@ static struct pci_device_id vr_nor_pci_ids[] = {
+ 	{0,}
+ };
+ 
+-static void __devexit vr_nor_pci_remove(struct pci_dev *dev)
++static void vr_nor_pci_remove(struct pci_dev *dev)
+ {
+ 	struct vr_nor_mtd *p = pci_get_drvdata(dev);
+ 
+diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c
+index 0cf6c73070fd..3c3c791eb96a 100644
+--- a/drivers/mtd/maps/lantiq-flash.c
++++ b/drivers/mtd/maps/lantiq-flash.c
+@@ -185,7 +185,7 @@ ltq_mtd_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit
++static int
+ ltq_mtd_remove(struct platform_device *pdev)
+ {
+ 	struct ltq_mtd *ltq_mtd = platform_get_drvdata(pdev);
+diff --git a/drivers/mtd/maps/pci.c b/drivers/mtd/maps/pci.c
+index 81a8caf3bd13..ed82914966f5 100644
+--- a/drivers/mtd/maps/pci.c
++++ b/drivers/mtd/maps/pci.c
+@@ -308,7 +308,7 @@ mtd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ 	return err;
+ }
+ 
+-static void __devexit
++static void
+ mtd_pci_remove(struct pci_dev *dev)
+ {
+ 	struct mtd_info *mtd = pci_get_drvdata(dev);
+diff --git a/drivers/mtd/maps/pismo.c b/drivers/mtd/maps/pismo.c
+index 01db0d0b076a..afea93b515d5 100644
+--- a/drivers/mtd/maps/pismo.c
++++ b/drivers/mtd/maps/pismo.c
+@@ -197,7 +197,7 @@ static void pismo_add_one(struct pismo_data *pismo, int i,
+ 	}
+ }
+ 
+-static int __devexit pismo_remove(struct i2c_client *client)
++static int pismo_remove(struct i2c_client *client)
+ {
+ 	struct pismo_data *pismo = i2c_get_clientdata(client);
+ 	int i;
+diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
+index b5120f9e9845..43e3dbb976d9 100644
+--- a/drivers/mtd/maps/pxa2xx-flash.c
++++ b/drivers/mtd/maps/pxa2xx-flash.c
+@@ -105,7 +105,7 @@ static int pxa2xx_flash_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit pxa2xx_flash_remove(struct platform_device *dev)
++static int pxa2xx_flash_remove(struct platform_device *dev)
+ {
+ 	struct pxa2xx_flash_info *info = platform_get_drvdata(dev);
+ 
+diff --git a/drivers/mtd/maps/scb2_flash.c b/drivers/mtd/maps/scb2_flash.c
+index bb1857f70bb1..71796137e97b 100644
+--- a/drivers/mtd/maps/scb2_flash.c
++++ b/drivers/mtd/maps/scb2_flash.c
+@@ -197,7 +197,7 @@ scb2_flash_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+ 	return 0;
+ }
+ 
+-static void __devexit
++static void
+ scb2_flash_remove(struct pci_dev *dev)
+ {
+ 	if (!scb2_mtd)
+diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c
+index 2618e4dd2718..d467f3b11c96 100644
+--- a/drivers/mtd/maps/sun_uflash.c
++++ b/drivers/mtd/maps/sun_uflash.c
+@@ -121,7 +121,7 @@ static int uflash_probe(struct platform_device *op)
+ 	return uflash_devinit(op, dp);
+ }
+ 
+-static int __devexit uflash_remove(struct platform_device *op)
++static int uflash_remove(struct platform_device *op)
+ {
+ 	struct uflash_dev *up = dev_get_drvdata(&op->dev);
+ 
+diff --git a/drivers/mtd/maps/vmu-flash.c b/drivers/mtd/maps/vmu-flash.c
+index 84c3f5a99e12..6b223cfe92b7 100644
+--- a/drivers/mtd/maps/vmu-flash.c
++++ b/drivers/mtd/maps/vmu-flash.c
+@@ -690,7 +690,7 @@ static int vmu_connect(struct maple_device *mdev)
+ 	return error;
+ }
+ 
+-static void __devexit vmu_disconnect(struct maple_device *mdev)
++static void vmu_disconnect(struct maple_device *mdev)
+ {
+ 	struct memcard *card;
+ 	struct mdev_part *mpart;
+@@ -789,7 +789,7 @@ static int probe_maple_vmu(struct device *dev)
+ 	return 0;
+ }
+ 
+-static int __devexit remove_maple_vmu(struct device *dev)
++static int remove_maple_vmu(struct device *dev)
+ {
+ 	struct maple_device *mdev = to_maple_dev(dev);
+ 
+diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c
+index 703e37387135..f1d71cdc8aac 100644
+--- a/drivers/mtd/nand/ams-delta.c
++++ b/drivers/mtd/nand/ams-delta.c
+@@ -270,7 +270,7 @@ static int ams_delta_init(struct platform_device *pdev)
+ /*
+  * Clean up routine
+  */
+-static int __devexit ams_delta_cleanup(struct platform_device *pdev)
++static int ams_delta_cleanup(struct platform_device *pdev)
+ {
+ 	void __iomem *io_base = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
+index 73d6423680ca..217459d02b2f 100644
+--- a/drivers/mtd/nand/au1550nd.c
++++ b/drivers/mtd/nand/au1550nd.c
+@@ -491,7 +491,7 @@ static int au1550nd_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit au1550nd_remove(struct platform_device *pdev)
++static int au1550nd_remove(struct platform_device *pdev)
+ {
+ 	struct au1550nd_ctx *ctx = platform_get_drvdata(pdev);
+ 	struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c
+index 56de9b676385..4271e948d1e2 100644
+--- a/drivers/mtd/nand/bf5xx_nand.c
++++ b/drivers/mtd/nand/bf5xx_nand.c
+@@ -667,7 +667,7 @@ static int bf5xx_nand_add_partition(struct bf5xx_nand_info *info)
+ 	return mtd_device_register(mtd, parts, nr);
+ }
+ 
+-static int __devexit bf5xx_nand_remove(struct platform_device *pdev)
++static int bf5xx_nand_remove(struct platform_device *pdev)
+ {
+ 	struct bf5xx_nand_info *info = to_nand_info(pdev);
+ 
+diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c
+index 480834a98382..010d61266536 100644
+--- a/drivers/mtd/nand/cafe_nand.c
++++ b/drivers/mtd/nand/cafe_nand.c
+@@ -821,7 +821,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit cafe_nand_remove(struct pci_dev *pdev)
++static void cafe_nand_remove(struct pci_dev *pdev)
+ {
+ 	struct mtd_info *mtd = pci_get_drvdata(pdev);
+ 	struct cafe_priv *cafe = mtd->priv;
+diff --git a/drivers/mtd/nand/denali_dt.c b/drivers/mtd/nand/denali_dt.c
+index f9b593c81db6..546f8cb5688d 100644
+--- a/drivers/mtd/nand/denali_dt.c
++++ b/drivers/mtd/nand/denali_dt.c
+@@ -129,7 +129,7 @@ static int denali_dt_probe(struct platform_device *ofdev)
+ 	return ret;
+ }
+ 
+-static int __devexit denali_dt_remove(struct platform_device *ofdev)
++static int denali_dt_remove(struct platform_device *ofdev)
+ {
+ 	struct denali_dt *dt = platform_get_drvdata(ofdev);
+ 
+diff --git a/drivers/mtd/nand/denali_pci.c b/drivers/mtd/nand/denali_pci.c
+index f1f8f896fcc8..e3e46623b2b4 100644
+--- a/drivers/mtd/nand/denali_pci.c
++++ b/drivers/mtd/nand/denali_pci.c
+@@ -137,7 +137,7 @@ static int denali_init_pci(void)
+ }
+ module_init(denali_init_pci);
+ 
+-static void __devexit denali_exit_pci(void)
++static void denali_exit_pci(void)
+ {
+ 	pci_unregister_driver(&denali_pci_driver);
+ }
+diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
+index a5643252584b..5a8f5c4ce512 100644
+--- a/drivers/mtd/nand/fsl_upm.c
++++ b/drivers/mtd/nand/fsl_upm.c
+@@ -318,7 +318,7 @@ static int fun_probe(struct platform_device *ofdev)
+ 	return ret;
+ }
+ 
+-static int __devexit fun_remove(struct platform_device *ofdev)
++static int fun_remove(struct platform_device *ofdev)
+ {
+ 	struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev);
+ 	int i;
+diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c
+index 45f1a240bcbd..7aec5690289a 100644
+--- a/drivers/mtd/nand/gpio.c
++++ b/drivers/mtd/nand/gpio.c
+@@ -231,7 +231,7 @@ gpio_nand_get_io_sync(struct platform_device *pdev)
+ 	return platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ }
+ 
+-static int __devexit gpio_nand_remove(struct platform_device *dev)
++static int gpio_nand_remove(struct platform_device *dev)
+ {
+ 	struct gpiomtd *gpiomtd = platform_get_drvdata(dev);
+ 	struct resource *res;
+diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+index 2a251c95a703..5cd141f7bfc2 100644
+--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
++++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+@@ -1675,7 +1675,7 @@ static int gpmi_nand_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit gpmi_nand_remove(struct platform_device *pdev)
++static int gpmi_nand_remove(struct platform_device *pdev)
+ {
+ 	struct gpmi_nand_data *this = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
+index 5396b6ceb088..72ac26e1ddf4 100644
+--- a/drivers/mtd/nand/jz4740_nand.c
++++ b/drivers/mtd/nand/jz4740_nand.c
+@@ -541,7 +541,7 @@ static int jz_nand_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit jz_nand_remove(struct platform_device *pdev)
++static int jz_nand_remove(struct platform_device *pdev)
+ {
+ 	struct jz_nand *nand = platform_get_drvdata(pdev);
+ 	struct jz_nand_platform_data *pdata = pdev->dev.platform_data;
+diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c
+index bb83daf9c739..f182befa7360 100644
+--- a/drivers/mtd/nand/lpc32xx_mlc.c
++++ b/drivers/mtd/nand/lpc32xx_mlc.c
+@@ -845,7 +845,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
+ /*
+  * Remove NAND device
+  */
+-static int __devexit lpc32xx_nand_remove(struct platform_device *pdev)
++static int lpc32xx_nand_remove(struct platform_device *pdev)
+ {
+ 	struct lpc32xx_nand_host *host = platform_get_drvdata(pdev);
+ 	struct mtd_info *mtd = &host->mtd;
+diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/lpc32xx_slc.c
+index 17267f2819d2..030b78c62895 100644
+--- a/drivers/mtd/nand/lpc32xx_slc.c
++++ b/drivers/mtd/nand/lpc32xx_slc.c
+@@ -949,7 +949,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
+ /*
+  * Remove NAND device.
+  */
+-static int __devexit lpc32xx_nand_remove(struct platform_device *pdev)
++static int lpc32xx_nand_remove(struct platform_device *pdev)
+ {
+ 	uint32_t tmp;
+ 	struct lpc32xx_nand_host *host = platform_get_drvdata(pdev);
+diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
+index 09f75a57e832..3c9cdcbc4cba 100644
+--- a/drivers/mtd/nand/mpc5121_nfc.c
++++ b/drivers/mtd/nand/mpc5121_nfc.c
+@@ -827,7 +827,7 @@ static int mpc5121_nfc_probe(struct platform_device *op)
+ 	return retval;
+ }
+ 
+-static int __devexit mpc5121_nfc_remove(struct platform_device *op)
++static int mpc5121_nfc_remove(struct platform_device *op)
+ {
+ 	struct device *dev = &op->dev;
+ 	struct mtd_info *mtd = dev_get_drvdata(dev);
+diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
+index 77a03cf64dd3..4aef6a355d54 100644
+--- a/drivers/mtd/nand/mxc_nand.c
++++ b/drivers/mtd/nand/mxc_nand.c
+@@ -1538,7 +1538,7 @@ static int mxcnd_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit mxcnd_remove(struct platform_device *pdev)
++static int mxcnd_remove(struct platform_device *pdev)
+ {
+ 	struct mxc_nand_host *host = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
+index 6fa4588d4771..8e148f1478fd 100644
+--- a/drivers/mtd/nand/ndfc.c
++++ b/drivers/mtd/nand/ndfc.c
+@@ -256,7 +256,7 @@ static int ndfc_probe(struct platform_device *ofdev)
+ 	return 0;
+ }
+ 
+-static int __devexit ndfc_remove(struct platform_device *ofdev)
++static int ndfc_remove(struct platform_device *ofdev)
+ {
+ 	struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev);
+ 
+diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c
+index 00766dfe4d3f..a6191198d259 100644
+--- a/drivers/mtd/nand/nuc900_nand.c
++++ b/drivers/mtd/nand/nuc900_nand.c
+@@ -317,7 +317,7 @@ fail1:	kfree(nuc900_nand);
+ 	return retval;
+ }
+ 
+-static int __devexit nuc900_nand_remove(struct platform_device *pdev)
++static int nuc900_nand_remove(struct platform_device *pdev)
+ {
+ 	struct nuc900_nand *nuc900_nand = platform_get_drvdata(pdev);
+ 	struct resource *res;
+diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c
+index e6b296dcb122..cd72b9299f6b 100644
+--- a/drivers/mtd/nand/orion_nand.c
++++ b/drivers/mtd/nand/orion_nand.c
+@@ -194,7 +194,7 @@ static int __init orion_nand_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit orion_nand_remove(struct platform_device *pdev)
++static int orion_nand_remove(struct platform_device *pdev)
+ {
+ 	struct mtd_info *mtd = platform_get_drvdata(pdev);
+ 	struct nand_chip *nc = mtd->priv;
+diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c
+index 2e477cb20b73..5a67082c07ee 100644
+--- a/drivers/mtd/nand/pasemi_nand.c
++++ b/drivers/mtd/nand/pasemi_nand.c
+@@ -184,7 +184,7 @@ static int pasemi_nand_probe(struct platform_device *ofdev)
+ 	return err;
+ }
+ 
+-static int __devexit pasemi_nand_remove(struct platform_device *ofdev)
++static int pasemi_nand_remove(struct platform_device *ofdev)
+ {
+ 	struct nand_chip *chip;
+ 
+diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c
+index 32e2996c9e73..c004566a9ad2 100644
+--- a/drivers/mtd/nand/plat_nand.c
++++ b/drivers/mtd/nand/plat_nand.c
+@@ -134,7 +134,7 @@ static int plat_nand_probe(struct platform_device *pdev)
+ /*
+  * Remove a NAND device.
+  */
+-static int __devexit plat_nand_remove(struct platform_device *pdev)
++static int plat_nand_remove(struct platform_device *pdev)
+ {
+ 	struct plat_nand_data *data = platform_get_drvdata(pdev);
+ 	struct platform_nand_data *pdata = pdev->dev.platform_data;
+diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c
+index e45d6bd2901a..2a215962071f 100644
+--- a/drivers/mtd/nand/sh_flctl.c
++++ b/drivers/mtd/nand/sh_flctl.c
+@@ -1198,7 +1198,7 @@ static int flctl_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit flctl_remove(struct platform_device *pdev)
++static int flctl_remove(struct platform_device *pdev)
+ {
+ 	struct sh_flctl *flctl = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c
+index 870f0ff76c5f..127bc4271821 100644
+--- a/drivers/mtd/nand/sharpsl.c
++++ b/drivers/mtd/nand/sharpsl.c
+@@ -205,7 +205,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev)
+ /*
+  * Clean up routine
+  */
+-static int __devexit sharpsl_nand_remove(struct platform_device *pdev)
++static int sharpsl_nand_remove(struct platform_device *pdev)
+ {
+ 	struct sharpsl_nand *sharpsl = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c
+index c9791fd1ee53..09dde7d27178 100644
+--- a/drivers/mtd/nand/socrates_nand.c
++++ b/drivers/mtd/nand/socrates_nand.c
+@@ -220,7 +220,7 @@ static int socrates_nand_probe(struct platform_device *ofdev)
+ /*
+  * Remove a NAND device.
+  */
+-static int __devexit socrates_nand_remove(struct platform_device *ofdev)
++static int socrates_nand_remove(struct platform_device *ofdev)
+ {
+ 	struct socrates_nand_host *host = dev_get_drvdata(&ofdev->dev);
+ 	struct mtd_info *mtd = &host->mtd;
+diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c
+index 03e6af342423..9f11562f849d 100644
+--- a/drivers/mtd/onenand/generic.c
++++ b/drivers/mtd/onenand/generic.c
+@@ -88,7 +88,7 @@ static int generic_onenand_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit generic_onenand_remove(struct platform_device *pdev)
++static int generic_onenand_remove(struct platform_device *pdev)
+ {
+ 	struct onenand_info *info = platform_get_drvdata(pdev);
+ 	struct resource *res = pdev->resource;
+diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
+index 8c10a2f54158..b364e6c57d26 100644
+--- a/drivers/mtd/onenand/omap2.c
++++ b/drivers/mtd/onenand/omap2.c
+@@ -787,7 +787,7 @@ static int omap2_onenand_probe(struct platform_device *pdev)
+ 	return r;
+ }
+ 
+-static int __devexit omap2_onenand_remove(struct platform_device *pdev)
++static int omap2_onenand_remove(struct platform_device *pdev)
+ {
+ 	struct omap2_onenand *c = dev_get_drvdata(&pdev->dev);
+ 
+diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
+index 3d462cbcdbe4..33f2a8fb8df9 100644
+--- a/drivers/mtd/onenand/samsung.c
++++ b/drivers/mtd/onenand/samsung.c
+@@ -1053,7 +1053,7 @@ static int s3c_onenand_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit s3c_onenand_remove(struct platform_device *pdev)
++static int s3c_onenand_remove(struct platform_device *pdev)
+ {
+ 	struct mtd_info *mtd = platform_get_drvdata(pdev);
+ 

commit 5e75e86e6d1561d5ae8e38412f93609475f19ed1
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:25:12 2012 -0500
+
+    mtd: remove use of __devinitconst
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitconst is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Artem Bityutskiy 
+
+diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c
+index 658a7d06b5eb..6057c6404289 100644
+--- a/drivers/mtd/maps/bfin-async-flash.c
++++ b/drivers/mtd/maps/bfin-async-flash.c
+@@ -30,7 +30,7 @@
+ #include 
+ #include 
+ 
+-#define pr_devinit(fmt, args...) ({ static const __devinitconst char __fmt[] = fmt; printk(__fmt, ## args); })
++#define pr_devinit(fmt, args...) ({ static const char __fmt[] = fmt; printk(__fmt, ## args); })
+ 
+ #define DRIVER_NAME "bfin-async-flash"
+ 
+diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c
+index 9a6a3e153775..4babe04dda50 100644
+--- a/drivers/mtd/maps/gpio-addr-flash.c
++++ b/drivers/mtd/maps/gpio-addr-flash.c
+@@ -26,7 +26,7 @@
+ #include 
+ #include 
+ 
+-#define pr_devinit(fmt, args...) ({ static const __devinitconst char __fmt[] = fmt; printk(__fmt, ## args); })
++#define pr_devinit(fmt, args...) ({ static const char __fmt[] = fmt; printk(__fmt, ## args); })
+ 
+ #define DRIVER_NAME "gpio-addr-flash"
+ #define PFX DRIVER_NAME ": "
+diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c
+index 58d1f61a70b0..0cf6c73070fd 100644
+--- a/drivers/mtd/maps/lantiq-flash.c
++++ b/drivers/mtd/maps/lantiq-flash.c
+@@ -45,7 +45,7 @@ struct ltq_mtd {
+ };
+ 
+ static const char ltq_map_name[] = "ltq_nor";
+-static const char *ltq_probe_types[] __devinitconst = {
++static const char *ltq_probe_types[] = {
+ 					"cmdlinepart", "ofpart", NULL };
+ 
+ static map_word

commit 042a190944675bc54790bcf45b8b2c86e68f003b
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:24:23 2012 -0500
+
+    mtd: remove use of __devinitdata
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitdata is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Artem Bityutskiy 
+
+diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
+index 080cb1c1887d..0b3f17361acb 100644
+--- a/drivers/mtd/devices/mtd_dataflash.c
++++ b/drivers/mtd/devices/mtd_dataflash.c
+@@ -705,7 +705,7 @@ struct flash_info {
+ #define IS_POW2PS	0x0001		/* uses 2^N byte pages */
+ };
+ 
+-static struct flash_info __devinitdata dataflash_data [] = {
++static struct flash_info dataflash_data [] = {
+ 
+ 	/*
+ 	 * NOTE:  chips with SUP_POW2PS (rev D and up) need two entries,
+diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c
+index ab4154deee0f..e4f233941bf6 100644
+--- a/drivers/mtd/devices/sst25l.c
++++ b/drivers/mtd/devices/sst25l.c
+@@ -64,7 +64,7 @@ struct flash_info {
+ 
+ #define to_sst25l_flash(x) container_of(x, struct sst25l_flash, mtd)
+ 
+-static struct flash_info __devinitdata sst25l_flash_info[] = {
++static struct flash_info sst25l_flash_info[] = {
+ 	{"sst25lf020a", 0xbf43, 256, 1024, 4096},
+ 	{"sst25lf040a",	0xbf44,	256, 2048, 4096},
+ };
+diff --git a/drivers/mtd/maps/esb2rom.c b/drivers/mtd/maps/esb2rom.c
+index 3797825ab287..664303f11f08 100644
+--- a/drivers/mtd/maps/esb2rom.c
++++ b/drivers/mtd/maps/esb2rom.c
+@@ -384,7 +384,7 @@ static void __devexit esb2rom_remove_one (struct pci_dev *pdev)
+ 	esb2rom_cleanup(window);
+ }
+ 
+-static struct pci_device_id esb2rom_pci_tbl[] __devinitdata = {
++static struct pci_device_id esb2rom_pci_tbl[] = {
+ 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0,
+ 	  PCI_ANY_ID, PCI_ANY_ID, },
+ 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,
+diff --git a/drivers/mtd/maps/ichxrom.c b/drivers/mtd/maps/ichxrom.c
+index a9bab67d2a87..9673601c3833 100644
+--- a/drivers/mtd/maps/ichxrom.c
++++ b/drivers/mtd/maps/ichxrom.c
+@@ -321,7 +321,7 @@ static void __devexit ichxrom_remove_one (struct pci_dev *pdev)
+ 	ichxrom_cleanup(window);
+ }
+ 
+-static struct pci_device_id ichxrom_pci_tbl[] __devinitdata = {
++static struct pci_device_id ichxrom_pci_tbl[] = {
+ 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0,
+ 	  PCI_ANY_ID, PCI_ANY_ID, },
+ 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,
+diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
+index f779e6a3d4b2..09f75a57e832 100644
+--- a/drivers/mtd/nand/mpc5121_nfc.c
++++ b/drivers/mtd/nand/mpc5121_nfc.c
+@@ -841,7 +841,7 @@ static int __devexit mpc5121_nfc_remove(struct platform_device *op)
+ 	return 0;
+ }
+ 
+-static struct of_device_id mpc5121_nfc_match[] __devinitdata = {
++static struct of_device_id mpc5121_nfc_match[] = {
+ 	{ .compatible = "fsl,mpc5121-nfc", },
+ 	{},
+ };

commit 06f25510692385ed4dadd23f7d3d064d1ab11c2d
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:23:07 2012 -0500
+
+    mtd: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Artem Bityutskiy 
+
+diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
+index bd2d91254c62..ae43b0154003 100644
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -755,7 +755,7 @@ static const struct spi_device_id m25p_ids[] = {
+ };
+ MODULE_DEVICE_TABLE(spi, m25p_ids);
+ 
+-static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
++static const struct spi_device_id *jedec_probe(struct spi_device *spi)
+ {
+ 	int			tmp;
+ 	u8			code = OPCODE_RDID;
+@@ -800,7 +800,7 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
+  * matches what the READ command supports, at least until this driver
+  * understands FAST_READ (for clocks over 25 MHz).
+  */
+-static int __devinit m25p_probe(struct spi_device *spi)
++static int m25p_probe(struct spi_device *spi)
+ {
+ 	const struct spi_device_id	*id = spi_get_device_id(spi);
+ 	struct flash_platform_data	*data;
+diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
+index 23ccc36840f6..080cb1c1887d 100644
+--- a/drivers/mtd/devices/mtd_dataflash.c
++++ b/drivers/mtd/devices/mtd_dataflash.c
+@@ -618,7 +618,7 @@ static char *otp_setup(struct mtd_info *device, char revision)
+ /*
+  * Register DataFlash device with MTD subsystem.
+  */
+-static int __devinit
++static int
+ add_dataflash_otp(struct spi_device *spi, char *name,
+ 		int nr_pages, int pagesize, int pageoffset, char revision)
+ {
+@@ -679,7 +679,7 @@ add_dataflash_otp(struct spi_device *spi, char *name,
+ 	return err;
+ }
+ 
+-static inline int __devinit
++static inline int
+ add_dataflash(struct spi_device *spi, char *name,
+ 		int nr_pages, int pagesize, int pageoffset)
+ {
+@@ -740,7 +740,7 @@ static struct flash_info __devinitdata dataflash_data [] = {
+ 	{ "at45db642d",  0x1f2800, 8192, 1024, 10, SUP_POW2PS | IS_POW2PS},
+ };
+ 
+-static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
++static struct flash_info *jedec_probe(struct spi_device *spi)
+ {
+ 	int			tmp;
+ 	uint8_t			code = OP_READ_ID;
+@@ -823,7 +823,7 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
+  *   AT45DB0642  64Mbit  (8M)    xx111xxx (0x3c)   8192   1056     11
+  *   AT45DB1282  128Mbit (16M)   xx0100xx (0x10)  16384   1056     11
+  */
+-static int __devinit dataflash_probe(struct spi_device *spi)
++static int dataflash_probe(struct spi_device *spi)
+ {
+ 	int status;
+ 	struct flash_info	*info;
+diff --git a/drivers/mtd/devices/spear_smi.c b/drivers/mtd/devices/spear_smi.c
+index e27737c91212..a30cd27ab916 100644
+--- a/drivers/mtd/devices/spear_smi.c
++++ b/drivers/mtd/devices/spear_smi.c
+@@ -756,7 +756,7 @@ static int spear_smi_probe_flash(struct spear_smi *dev, u32 bank)
+ 
+ 
+ #ifdef CONFIG_OF
+-static int __devinit spear_smi_probe_config_dt(struct platform_device *pdev,
++static int spear_smi_probe_config_dt(struct platform_device *pdev,
+ 					       struct device_node *np)
+ {
+ 	struct spear_smi_plat_data *pdata = dev_get_platdata(&pdev->dev);
+@@ -799,7 +799,7 @@ static int __devinit spear_smi_probe_config_dt(struct platform_device *pdev,
+ 	return 0;
+ }
+ #else
+-static int __devinit spear_smi_probe_config_dt(struct platform_device *pdev,
++static int spear_smi_probe_config_dt(struct platform_device *pdev,
+ 					       struct device_node *np)
+ {
+ 	return -ENOSYS;
+@@ -901,7 +901,7 @@ static int spear_smi_setup_banks(struct platform_device *pdev,
+  * and do proper init for any found one.
+  * Returns 0 on success, non zero otherwise
+  */
+-static int __devinit spear_smi_probe(struct platform_device *pdev)
++static int spear_smi_probe(struct platform_device *pdev)
+ {
+ 	struct device_node *np = pdev->dev.of_node;
+ 	struct spear_smi_plat_data *pdata = NULL;
+diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c
+index 9ebf86d8faa8..ab4154deee0f 100644
+--- a/drivers/mtd/devices/sst25l.c
++++ b/drivers/mtd/devices/sst25l.c
+@@ -313,7 +313,7 @@ static int sst25l_write(struct mtd_info *mtd, loff_t to, size_t len,
+ 	return ret;
+ }
+ 
+-static struct flash_info *__devinit sst25l_match_device(struct spi_device *spi)
++static struct flash_info *sst25l_match_device(struct spi_device *spi)
+ {
+ 	struct flash_info *flash_info = NULL;
+ 	struct spi_message m;
+@@ -353,7 +353,7 @@ static struct flash_info *__devinit sst25l_match_device(struct spi_device *spi)
+ 	return flash_info;
+ }
+ 
+-static int __devinit sst25l_probe(struct spi_device *spi)
++static int sst25l_probe(struct spi_device *spi)
+ {
+ 	struct flash_info *flash_info;
+ 	struct sst25l_flash *flash;
+diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c
+index e2875d6fe129..1a4f671181f4 100644
+--- a/drivers/mtd/maps/amd76xrom.c
++++ b/drivers/mtd/maps/amd76xrom.c
+@@ -100,7 +100,7 @@ static void amd76xrom_cleanup(struct amd76xrom_window *window)
+ }
+ 
+ 
+-static int __devinit amd76xrom_init_one (struct pci_dev *pdev,
++static int amd76xrom_init_one (struct pci_dev *pdev,
+ 	const struct pci_device_id *ent)
+ {
+ 	static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
+diff --git a/drivers/mtd/maps/autcpu12-nvram.c b/drivers/mtd/maps/autcpu12-nvram.c
+index ca0313db6fea..b8c858913bbe 100644
+--- a/drivers/mtd/maps/autcpu12-nvram.c
++++ b/drivers/mtd/maps/autcpu12-nvram.c
+@@ -33,7 +33,7 @@ struct autcpu12_nvram_priv {
+ 	struct map_info map;
+ };
+ 
+-static int __devinit autcpu12_nvram_probe(struct platform_device *pdev)
++static int autcpu12_nvram_probe(struct platform_device *pdev)
+ {
+ 	map_word tmp, save0, save1;
+ 	struct resource *res;
+diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c
+index 340e8a260547..658a7d06b5eb 100644
+--- a/drivers/mtd/maps/bfin-async-flash.c
++++ b/drivers/mtd/maps/bfin-async-flash.c
+@@ -123,7 +123,7 @@ static void bfin_flash_copy_to(struct map_info *map, unsigned long to, const voi
+ 
+ static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
+ 
+-static int __devinit bfin_flash_probe(struct platform_device *pdev)
++static int bfin_flash_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 	struct physmap_flash_data *pdata = pdev->dev.platform_data;
+diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c
+index 3d0e762fa5f2..65fedb9f296a 100644
+--- a/drivers/mtd/maps/ck804xrom.c
++++ b/drivers/mtd/maps/ck804xrom.c
+@@ -112,7 +112,7 @@ static void ck804xrom_cleanup(struct ck804xrom_window *window)
+ }
+ 
+ 
+-static int __devinit ck804xrom_init_one (struct pci_dev *pdev,
++static int ck804xrom_init_one (struct pci_dev *pdev,
+ 					 const struct pci_device_id *ent)
+ {
+ 	static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
+diff --git a/drivers/mtd/maps/esb2rom.c b/drivers/mtd/maps/esb2rom.c
+index 08322b1c3e81..3797825ab287 100644
+--- a/drivers/mtd/maps/esb2rom.c
++++ b/drivers/mtd/maps/esb2rom.c
+@@ -144,7 +144,7 @@ static void esb2rom_cleanup(struct esb2rom_window *window)
+ 	pci_dev_put(window->pdev);
+ }
+ 
+-static int __devinit esb2rom_init_one(struct pci_dev *pdev,
++static int esb2rom_init_one(struct pci_dev *pdev,
+ 				      const struct pci_device_id *ent)
+ {
+ 	static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
+diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c
+index 670af9afa786..9a6a3e153775 100644
+--- a/drivers/mtd/maps/gpio-addr-flash.c
++++ b/drivers/mtd/maps/gpio-addr-flash.c
+@@ -185,7 +185,7 @@ static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
+  *	...
+  * };
+  */
+-static int __devinit gpio_flash_probe(struct platform_device *pdev)
++static int gpio_flash_probe(struct platform_device *pdev)
+ {
+ 	size_t i, arr_size;
+ 	struct physmap_flash_data *pdata;
+diff --git a/drivers/mtd/maps/ichxrom.c b/drivers/mtd/maps/ichxrom.c
+index 6689dcb3124d..a9bab67d2a87 100644
+--- a/drivers/mtd/maps/ichxrom.c
++++ b/drivers/mtd/maps/ichxrom.c
+@@ -84,7 +84,7 @@ static void ichxrom_cleanup(struct ichxrom_window *window)
+ }
+ 
+ 
+-static int __devinit ichxrom_init_one (struct pci_dev *pdev,
++static int ichxrom_init_one (struct pci_dev *pdev,
+ 	const struct pci_device_id *ent)
+ {
+ 	static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
+diff --git a/drivers/mtd/maps/intel_vr_nor.c b/drivers/mtd/maps/intel_vr_nor.c
+index f6185d4c6ba9..1694c03e4884 100644
+--- a/drivers/mtd/maps/intel_vr_nor.c
++++ b/drivers/mtd/maps/intel_vr_nor.c
+@@ -68,7 +68,7 @@ static void __devexit vr_nor_destroy_partitions(struct vr_nor_mtd *p)
+ 	mtd_device_unregister(p->info);
+ }
+ 
+-static int __devinit vr_nor_init_partitions(struct vr_nor_mtd *p)
++static int vr_nor_init_partitions(struct vr_nor_mtd *p)
+ {
+ 	/* register the flash bank */
+ 	/* partition the flash bank */
+@@ -80,7 +80,7 @@ static void __devexit vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p)
+ 	map_destroy(p->info);
+ }
+ 
+-static int __devinit vr_nor_mtd_setup(struct vr_nor_mtd *p)
++static int vr_nor_mtd_setup(struct vr_nor_mtd *p)
+ {
+ 	static const char *probe_types[] =
+ 	    { "cfi_probe", "jedec_probe", NULL };
+@@ -116,7 +116,7 @@ static void __devexit vr_nor_destroy_maps(struct vr_nor_mtd *p)
+  * Initialize the map_info structure and map the flash.
+  * Returns 0 on success, nonzero otherwise.
+  */
+-static int __devinit vr_nor_init_maps(struct vr_nor_mtd *p)
++static int vr_nor_init_maps(struct vr_nor_mtd *p)
+ {
+ 	unsigned long csr_phys, csr_len;
+ 	unsigned long win_phys, win_len;
+@@ -189,7 +189,7 @@ static void __devexit vr_nor_pci_remove(struct pci_dev *dev)
+ 	pci_disable_device(dev);
+ }
+ 
+-static int __devinit
++static int
+ vr_nor_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	struct vr_nor_mtd *p = NULL;
+diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c
+index 4c032f168138..58d1f61a70b0 100644
+--- a/drivers/mtd/maps/lantiq-flash.c
++++ b/drivers/mtd/maps/lantiq-flash.c
+@@ -109,7 +109,7 @@ ltq_copy_to(struct map_info *map, unsigned long to,
+ 	spin_unlock_irqrestore(&ebu_lock, flags);
+ }
+ 
+-static int __devinit
++static int
+ ltq_mtd_probe(struct platform_device *pdev)
+ {
+ 	struct mtd_part_parser_data ppdata;
+diff --git a/drivers/mtd/maps/latch-addr-flash.c b/drivers/mtd/maps/latch-addr-flash.c
+index 962a76a283a5..ab0fead56b83 100644
+--- a/drivers/mtd/maps/latch-addr-flash.c
++++ b/drivers/mtd/maps/latch-addr-flash.c
+@@ -125,7 +125,7 @@ static int latch_addr_flash_remove(struct platform_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devinit latch_addr_flash_probe(struct platform_device *dev)
++static int latch_addr_flash_probe(struct platform_device *dev)
+ {
+ 	struct latch_addr_flash_data *latch_addr_data;
+ 	struct latch_addr_flash_info *info;
+diff --git a/drivers/mtd/maps/pci.c b/drivers/mtd/maps/pci.c
+index ddc8c0c56d01..81a8caf3bd13 100644
+--- a/drivers/mtd/maps/pci.c
++++ b/drivers/mtd/maps/pci.c
+@@ -253,7 +253,7 @@ static struct pci_device_id mtd_pci_ids[] = {
+  * Generic code follows.
+  */
+ 
+-static int __devinit
++static int
+ mtd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	struct mtd_pci_info *info = (struct mtd_pci_info *)id->driver_data;
+diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
+index d7f19bc6de4a..cde8bf94338e 100644
+--- a/drivers/mtd/maps/physmap_of.c
++++ b/drivers/mtd/maps/physmap_of.c
+@@ -77,7 +77,7 @@ static int of_flash_remove(struct platform_device *dev)
+ /* Helper function to handle probing of the obsolete "direct-mapped"
+  * compatible binding, which has an extra "probe-type" property
+  * describing the type of flash probe necessary. */
+-static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev,
++static struct mtd_info *obsolete_probe(struct platform_device *dev,
+ 						  struct map_info *map)
+ {
+ 	struct device_node *dp = dev->dev.of_node;
+@@ -116,7 +116,7 @@ static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev,
+    information. */
+ static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot",
+ 					"ofpart", "ofoldpart", NULL };
+-static const char ** __devinit of_get_probes(struct device_node *dp)
++static const char **of_get_probes(struct device_node *dp)
+ {
+ 	const char *cp;
+ 	int cplen;
+@@ -145,14 +145,14 @@ static const char ** __devinit of_get_probes(struct device_node *dp)
+ 	return res;
+ }
+ 
+-static void __devinit of_free_probes(const char **probes)
++static void of_free_probes(const char **probes)
+ {
+ 	if (probes != part_probe_types_def)
+ 		kfree(probes);
+ }
+ 
+ static struct of_device_id of_flash_match[];
+-static int __devinit of_flash_probe(struct platform_device *dev)
++static int of_flash_probe(struct platform_device *dev)
+ {
+ 	const char **part_probe_types;
+ 	const struct of_device_id *match;
+diff --git a/drivers/mtd/maps/pismo.c b/drivers/mtd/maps/pismo.c
+index 9f4e5947c99f..01db0d0b076a 100644
+--- a/drivers/mtd/maps/pismo.c
++++ b/drivers/mtd/maps/pismo.c
+@@ -58,7 +58,7 @@ static void pismo_set_vpp(struct platform_device *pdev, int on)
+ 	pismo->vpp(pismo->vpp_data, on);
+ }
+ 
+-static unsigned int __devinit pismo_width_to_bytes(unsigned int width)
++static unsigned int pismo_width_to_bytes(unsigned int width)
+ {
+ 	width &= 15;
+ 	if (width > 2)
+@@ -66,7 +66,7 @@ static unsigned int __devinit pismo_width_to_bytes(unsigned int width)
+ 	return 1 << width;
+ }
+ 
+-static int __devinit pismo_eeprom_read(struct i2c_client *client, void *buf,
++static int pismo_eeprom_read(struct i2c_client *client, void *buf,
+ 	u8 addr, size_t size)
+ {
+ 	int ret;
+@@ -88,7 +88,7 @@ static int __devinit pismo_eeprom_read(struct i2c_client *client, void *buf,
+ 	return ret == ARRAY_SIZE(msg) ? size : -EIO;
+ }
+ 
+-static int __devinit pismo_add_device(struct pismo_data *pismo, int i,
++static int pismo_add_device(struct pismo_data *pismo, int i,
+ 	struct pismo_mem *region, const char *name, void *pdata, size_t psize)
+ {
+ 	struct platform_device *dev;
+@@ -129,7 +129,7 @@ static int __devinit pismo_add_device(struct pismo_data *pismo, int i,
+ 	return ret;
+ }
+ 
+-static int __devinit pismo_add_nor(struct pismo_data *pismo, int i,
++static int pismo_add_nor(struct pismo_data *pismo, int i,
+ 	struct pismo_mem *region)
+ {
+ 	struct physmap_flash_data data = {
+@@ -143,7 +143,7 @@ static int __devinit pismo_add_nor(struct pismo_data *pismo, int i,
+ 		&data, sizeof(data));
+ }
+ 
+-static int __devinit pismo_add_sram(struct pismo_data *pismo, int i,
++static int pismo_add_sram(struct pismo_data *pismo, int i,
+ 	struct pismo_mem *region)
+ {
+ 	struct platdata_mtd_ram data = {
+@@ -154,7 +154,7 @@ static int __devinit pismo_add_sram(struct pismo_data *pismo, int i,
+ 		&data, sizeof(data));
+ }
+ 
+-static void __devinit pismo_add_one(struct pismo_data *pismo, int i,
++static void pismo_add_one(struct pismo_data *pismo, int i,
+ 	const struct pismo_cs_block *cs, phys_addr_t base)
+ {
+ 	struct device *dev = &pismo->client->dev;
+@@ -210,7 +210,7 @@ static int __devexit pismo_remove(struct i2c_client *client)
+ 	return 0;
+ }
+ 
+-static int __devinit pismo_probe(struct i2c_client *client,
++static int pismo_probe(struct i2c_client *client,
+ 				 const struct i2c_device_id *id)
+ {
+ 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
+index f913a1c3f2b9..b5120f9e9845 100644
+--- a/drivers/mtd/maps/pxa2xx-flash.c
++++ b/drivers/mtd/maps/pxa2xx-flash.c
+@@ -49,7 +49,7 @@ struct pxa2xx_flash_info {
+ static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
+ 
+ 
+-static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
++static int pxa2xx_flash_probe(struct platform_device *pdev)
+ {
+ 	struct flash_platform_data *flash = pdev->dev.platform_data;
+ 	struct pxa2xx_flash_info *info;
+diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
+index a675bdbcb0fe..7aebc82a5c6d 100644
+--- a/drivers/mtd/maps/sa1100-flash.c
++++ b/drivers/mtd/maps/sa1100-flash.c
+@@ -149,8 +149,7 @@ static void sa1100_destroy(struct sa_info *info, struct flash_platform_data *pla
+ 		plat->exit();
+ }
+ 
+-static struct sa_info *__devinit
+-sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *plat)
++static struct sa_info *sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *plat)
+ {
+ 	struct sa_info *info;
+ 	int nr, size, i, ret = 0;
+@@ -246,7 +245,7 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *plat)
+ 
+ static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
+ 
+-static int __devinit sa1100_mtd_probe(struct platform_device *pdev)
++static int sa1100_mtd_probe(struct platform_device *pdev)
+ {
+ 	struct flash_platform_data *plat = pdev->dev.platform_data;
+ 	struct sa_info *info;
+diff --git a/drivers/mtd/maps/scb2_flash.c b/drivers/mtd/maps/scb2_flash.c
+index d527608e5d22..bb1857f70bb1 100644
+--- a/drivers/mtd/maps/scb2_flash.c
++++ b/drivers/mtd/maps/scb2_flash.c
+@@ -69,7 +69,7 @@ static struct map_info scb2_map = {
+ };
+ static int region_fail;
+ 
+-static int __devinit
++static int
+ scb2_fixup_mtd(struct mtd_info *mtd)
+ {
+ 	int i;
+@@ -133,7 +133,7 @@ scb2_fixup_mtd(struct mtd_info *mtd)
+ /* CSB5's 'Function Control Register' has bits for decoding @ >= 0xffc00000 */
+ #define CSB5_FCR	0x41
+ #define CSB5_FCR_DECODE_ALL 0x0e
+-static int __devinit
++static int
+ scb2_flash_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+ {
+ 	u8 reg;
+diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c
+index 1c03ca7c4a74..2618e4dd2718 100644
+--- a/drivers/mtd/maps/sun_uflash.c
++++ b/drivers/mtd/maps/sun_uflash.c
+@@ -108,7 +108,7 @@ int uflash_devinit(struct platform_device *op, struct device_node *dp)
+ 	return 0;
+ }
+ 
+-static int __devinit uflash_probe(struct platform_device *op)
++static int uflash_probe(struct platform_device *op)
+ {
+ 	struct device_node *dp = op->dev.of_node;
+ 
+diff --git a/drivers/mtd/maps/vmu-flash.c b/drivers/mtd/maps/vmu-flash.c
+index 5a83a264eb83..84c3f5a99e12 100644
+--- a/drivers/mtd/maps/vmu-flash.c
++++ b/drivers/mtd/maps/vmu-flash.c
+@@ -596,7 +596,7 @@ static void vmu_queryblocks(struct mapleq *mq)
+ }
+ 
+ /* Handles very basic info about the flash, queries for details */
+-static int __devinit vmu_connect(struct maple_device *mdev)
++static int vmu_connect(struct maple_device *mdev)
+ {
+ 	unsigned long test_flash_data, basic_flash_data;
+ 	int c, error;
+@@ -772,7 +772,7 @@ static void vmu_file_error(struct maple_device *mdev, void *recvbuf)
+ }
+ 
+ 
+-static int __devinit probe_maple_vmu(struct device *dev)
++static int probe_maple_vmu(struct device *dev)
+ {
+ 	int error;
+ 	struct maple_device *mdev = to_maple_dev(dev);
+diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c
+index 51dba43e2879..703e37387135 100644
+--- a/drivers/mtd/nand/ams-delta.c
++++ b/drivers/mtd/nand/ams-delta.c
+@@ -173,7 +173,7 @@ static const struct gpio _mandatory_gpio[] = {
+ /*
+  * Main initialization routine
+  */
+-static int __devinit ams_delta_init(struct platform_device *pdev)
++static int ams_delta_init(struct platform_device *pdev)
+ {
+ 	struct nand_chip *this;
+ 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
+index 914455783302..c9183866a163 100644
+--- a/drivers/mtd/nand/atmel_nand.c
++++ b/drivers/mtd/nand/atmel_nand.c
+@@ -330,13 +330,13 @@ static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
+  *               12-bits                20-bytes                 21-bytes
+  *               24-bits                39-bytes                 42-bytes
+  */
+-static int __devinit pmecc_get_ecc_bytes(int cap, int sector_size)
++static int pmecc_get_ecc_bytes(int cap, int sector_size)
+ {
+ 	int m = 12 + sector_size / 512;
+ 	return (m * cap + 7) / 8;
+ }
+ 
+-static void __devinit pmecc_config_ecc_layout(struct nand_ecclayout *layout,
++static void pmecc_config_ecc_layout(struct nand_ecclayout *layout,
+ 	int oobsize, int ecc_len)
+ {
+ 	int i;
+@@ -352,7 +352,7 @@ static void __devinit pmecc_config_ecc_layout(struct nand_ecclayout *layout,
+ 		oobsize - ecc_len - layout->oobfree[0].offset;
+ }
+ 
+-static void __devinit __iomem *pmecc_get_alpha_to(struct atmel_nand_host *host)
++static void __iomem *pmecc_get_alpha_to(struct atmel_nand_host *host)
+ {
+ 	int table_size;
+ 
+@@ -374,7 +374,7 @@ static void pmecc_data_free(struct atmel_nand_host *host)
+ 	kfree(host->pmecc_delta);
+ }
+ 
+-static int __devinit pmecc_data_alloc(struct atmel_nand_host *host)
++static int pmecc_data_alloc(struct atmel_nand_host *host)
+ {
+ 	const int cap = host->pmecc_corr_cap;
+ 
+@@ -1205,7 +1205,7 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
+ }
+ 
+ #if defined(CONFIG_OF)
+-static int __devinit atmel_of_init_port(struct atmel_nand_host *host,
++static int atmel_of_init_port(struct atmel_nand_host *host,
+ 					 struct device_node *np)
+ {
+ 	u32 val, table_offset;
+@@ -1292,7 +1292,7 @@ static int __devinit atmel_of_init_port(struct atmel_nand_host *host,
+ 	return 0;
+ }
+ #else
+-static int __devinit atmel_of_init_port(struct atmel_nand_host *host,
++static int atmel_of_init_port(struct atmel_nand_host *host,
+ 					 struct device_node *np)
+ {
+ 	return -EINVAL;
+diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
+index d84af46ccc8d..73d6423680ca 100644
+--- a/drivers/mtd/nand/au1550nd.c
++++ b/drivers/mtd/nand/au1550nd.c
+@@ -382,7 +382,7 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
+ 	while(!this->dev_ready(mtd));
+ }
+ 
+-static int __devinit find_nand_cs(unsigned long nand_base)
++static int find_nand_cs(unsigned long nand_base)
+ {
+ 	void __iomem *base =
+ 			(void __iomem *)KSEG1ADDR(AU1000_STATIC_MEM_PHYS_ADDR);
+@@ -403,7 +403,7 @@ static int __devinit find_nand_cs(unsigned long nand_base)
+ 	return -ENODEV;
+ }
+ 
+-static int __devinit au1550nd_probe(struct platform_device *pdev)
++static int au1550nd_probe(struct platform_device *pdev)
+ {
+ 	struct au1550nd_platdata *pd;
+ 	struct au1550nd_ctx *ctx;
+diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c
+index 0afd4ac34248..56de9b676385 100644
+--- a/drivers/mtd/nand/bf5xx_nand.c
++++ b/drivers/mtd/nand/bf5xx_nand.c
+@@ -658,7 +658,7 @@ static int bf5xx_nand_hw_init(struct bf5xx_nand_info *info)
+ /*
+  * Device management interface
+  */
+-static int __devinit bf5xx_nand_add_partition(struct bf5xx_nand_info *info)
++static int bf5xx_nand_add_partition(struct bf5xx_nand_info *info)
+ {
+ 	struct mtd_info *mtd = &info->mtd;
+ 	struct mtd_partition *parts = info->platform->partitions;
+@@ -725,7 +725,7 @@ static int bf5xx_nand_scan(struct mtd_info *mtd)
+  * it can allocate all necessary resources then calls the
+  * nand layer to look for devices
+  */
+-static int __devinit bf5xx_nand_probe(struct platform_device *pdev)
++static int bf5xx_nand_probe(struct platform_device *pdev)
+ {
+ 	struct bf5xx_nand_platform *plat = to_nand_plat(pdev);
+ 	struct bf5xx_nand_info *info = NULL;
+diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c
+index 1b62f043bf7e..480834a98382 100644
+--- a/drivers/mtd/nand/cafe_nand.c
++++ b/drivers/mtd/nand/cafe_nand.c
+@@ -585,7 +585,7 @@ static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
+ }
+ 
+ /* F_2[X]/(X**6+X+1)  */
+-static unsigned short __devinit gf64_mul(u8 a, u8 b)
++static unsigned short gf64_mul(u8 a, u8 b)
+ {
+ 	u8 c;
+ 	unsigned int i;
+@@ -604,7 +604,7 @@ static unsigned short __devinit gf64_mul(u8 a, u8 b)
+ }
+ 
+ /* F_64[X]/(X**2+X+A**-1) with A the generator of F_64[X]  */
+-static u16 __devinit gf4096_mul(u16 a, u16 b)
++static u16 gf4096_mul(u16 a, u16 b)
+ {
+ 	u8 ah, al, bh, bl, ch, cl;
+ 
+@@ -619,14 +619,14 @@ static u16 __devinit gf4096_mul(u16 a, u16 b)
+ 	return (ch << 6) ^ cl;
+ }
+ 
+-static int __devinit cafe_mul(int x)
++static int cafe_mul(int x)
+ {
+ 	if (x == 0)
+ 		return 1;
+ 	return gf4096_mul(x, 0xe01);
+ }
+ 
+-static int __devinit cafe_nand_probe(struct pci_dev *pdev,
++static int cafe_nand_probe(struct pci_dev *pdev,
+ 				     const struct pci_device_id *ent)
+ {
+ 	struct mtd_info *mtd;
+diff --git a/drivers/mtd/nand/denali_dt.c b/drivers/mtd/nand/denali_dt.c
+index 445de7c8bb50..f9b593c81db6 100644
+--- a/drivers/mtd/nand/denali_dt.c
++++ b/drivers/mtd/nand/denali_dt.c
+@@ -57,7 +57,7 @@ MODULE_DEVICE_TABLE(of, denali_nand_dt_ids);
+ 
+ static u64 denali_dma_mask;
+ 
+-static int __devinit denali_dt_probe(struct platform_device *ofdev)
++static int denali_dt_probe(struct platform_device *ofdev)
+ {
+ 	struct resource *denali_reg, *nand_data;
+ 	struct denali_dt *dt;
+diff --git a/drivers/mtd/nand/denali_pci.c b/drivers/mtd/nand/denali_pci.c
+index ea074e6c7622..f1f8f896fcc8 100644
+--- a/drivers/mtd/nand/denali_pci.c
++++ b/drivers/mtd/nand/denali_pci.c
+@@ -130,7 +130,7 @@ static struct pci_driver denali_pci_driver = {
+ 	.remove = denali_pci_remove,
+ };
+ 
+-static int __devinit denali_init_pci(void)
++static int denali_init_pci(void)
+ {
+ 	pr_info("Spectra MTD driver built on %s @ %s\n", __DATE__, __TIME__);
+ 	return pci_register_driver(&denali_pci_driver);
+diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
+index 4c4d3e5bca18..20657209a472 100644
+--- a/drivers/mtd/nand/fsl_elbc_nand.c
++++ b/drivers/mtd/nand/fsl_elbc_nand.c
+@@ -799,7 +799,7 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
+ 
+ static DEFINE_MUTEX(fsl_elbc_nand_mutex);
+ 
+-static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev)
++static int fsl_elbc_nand_probe(struct platform_device *pdev)
+ {
+ 	struct fsl_lbc_regs __iomem *lbc;
+ 	struct fsl_elbc_mtd *priv;
+diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c
+index 53152310804c..ad6222627fed 100644
+--- a/drivers/mtd/nand/fsl_ifc_nand.c
++++ b/drivers/mtd/nand/fsl_ifc_nand.c
+@@ -922,7 +922,7 @@ static int match_bank(struct fsl_ifc_regs __iomem *ifc, int bank,
+ 
+ static DEFINE_MUTEX(fsl_ifc_nand_mutex);
+ 
+-static int __devinit fsl_ifc_nand_probe(struct platform_device *dev)
++static int fsl_ifc_nand_probe(struct platform_device *dev)
+ {
+ 	struct fsl_ifc_regs __iomem *ifc;
+ 	struct fsl_ifc_mtd *priv;
+diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
+index b40661d7160e..a5643252584b 100644
+--- a/drivers/mtd/nand/fsl_upm.c
++++ b/drivers/mtd/nand/fsl_upm.c
+@@ -152,7 +152,7 @@ static void fun_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+ 		fun_wait_rnb(fun);
+ }
+ 
+-static int __devinit fun_chip_init(struct fsl_upm_nand *fun,
++static int fun_chip_init(struct fsl_upm_nand *fun,
+ 				   const struct device_node *upm_np,
+ 				   const struct resource *io_res)
+ {
+@@ -201,7 +201,7 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun,
+ 	return ret;
+ }
+ 
+-static int __devinit fun_probe(struct platform_device *ofdev)
++static int fun_probe(struct platform_device *ofdev)
+ {
+ 	struct fsl_upm_nand *fun;
+ 	struct resource io_res;
+diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
+index 6b592235f847..1d7446434b0e 100644
+--- a/drivers/mtd/nand/fsmc_nand.c
++++ b/drivers/mtd/nand/fsmc_nand.c
+@@ -864,7 +864,7 @@ static bool filter(struct dma_chan *chan, void *slave)
+ }
+ 
+ #ifdef CONFIG_OF
+-static int __devinit fsmc_nand_probe_config_dt(struct platform_device *pdev,
++static int fsmc_nand_probe_config_dt(struct platform_device *pdev,
+ 					       struct device_node *np)
+ {
+ 	struct fsmc_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
+@@ -886,7 +886,7 @@ static int __devinit fsmc_nand_probe_config_dt(struct platform_device *pdev,
+ 	return 0;
+ }
+ #else
+-static int __devinit fsmc_nand_probe_config_dt(struct platform_device *pdev,
++static int fsmc_nand_probe_config_dt(struct platform_device *pdev,
+ 					       struct device_node *np)
+ {
+ 	return -ENOSYS;
+diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c
+index 0b3c815ef80c..45f1a240bcbd 100644
+--- a/drivers/mtd/nand/gpio.c
++++ b/drivers/mtd/nand/gpio.c
+@@ -282,7 +282,7 @@ static void __iomem *request_and_remap(struct resource *res, size_t size,
+ 	return ptr;
+ }
+ 
+-static int __devinit gpio_nand_probe(struct platform_device *dev)
++static int gpio_nand_probe(struct platform_device *dev)
+ {
+ 	struct gpiomtd *gpiomtd;
+ 	struct nand_chip *this;
+diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+index 7ce6d01a3c94..2a251c95a703 100644
+--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
++++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+@@ -319,7 +319,7 @@ int start_dma_with_bch_irq(struct gpmi_nand_data *this,
+ 	return 0;
+ }
+ 
+-static int __devinit
++static int
+ acquire_register_block(struct gpmi_nand_data *this, const char *res_name)
+ {
+ 	struct platform_device *pdev = this->pdev;
+@@ -360,7 +360,7 @@ static void release_register_block(struct gpmi_nand_data *this)
+ 	res->bch_regs = NULL;
+ }
+ 
+-static int __devinit
++static int
+ acquire_bch_irq(struct gpmi_nand_data *this, irq_handler_t irq_h)
+ {
+ 	struct platform_device *pdev = this->pdev;
+@@ -427,7 +427,7 @@ static void release_dma_channels(struct gpmi_nand_data *this)
+ 		}
+ }
+ 
+-static int __devinit acquire_dma_channels(struct gpmi_nand_data *this)
++static int acquire_dma_channels(struct gpmi_nand_data *this)
+ {
+ 	struct platform_device *pdev = this->pdev;
+ 	struct resource *r_dma;
+@@ -492,7 +492,7 @@ static char *extra_clks_for_mx6q[GPMI_CLK_MAX] = {
+ 	"gpmi_apb", "gpmi_bch", "gpmi_bch_apb", "per1_bch",
+ };
+ 
+-static int __devinit gpmi_get_clks(struct gpmi_nand_data *this)
++static int gpmi_get_clks(struct gpmi_nand_data *this)
+ {
+ 	struct resources *r = &this->resources;
+ 	char **extra_clks = NULL;
+@@ -538,7 +538,7 @@ static int __devinit gpmi_get_clks(struct gpmi_nand_data *this)
+ 	return -ENOMEM;
+ }
+ 
+-static int __devinit acquire_resources(struct gpmi_nand_data *this)
++static int acquire_resources(struct gpmi_nand_data *this)
+ {
+ 	struct pinctrl *pinctrl;
+ 	int ret;
+@@ -588,7 +588,7 @@ static void release_resources(struct gpmi_nand_data *this)
+ 	release_dma_channels(this);
+ }
+ 
+-static int __devinit init_hardware(struct gpmi_nand_data *this)
++static int init_hardware(struct gpmi_nand_data *this)
+ {
+ 	int ret;
+ 
+@@ -1542,7 +1542,7 @@ static void gpmi_nfc_exit(struct gpmi_nand_data *this)
+ 	gpmi_free_dma_buffer(this);
+ }
+ 
+-static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this)
++static int gpmi_nfc_init(struct gpmi_nand_data *this)
+ {
+ 	struct mtd_info  *mtd = &this->mtd;
+ 	struct nand_chip *chip = &this->nand;
+@@ -1625,7 +1625,7 @@ static const struct of_device_id gpmi_nand_id_table[] = {
+ };
+ MODULE_DEVICE_TABLE(of, gpmi_nand_id_table);
+ 
+-static int __devinit gpmi_nand_probe(struct platform_device *pdev)
++static int gpmi_nand_probe(struct platform_device *pdev)
+ {
+ 	struct gpmi_nand_data *this;
+ 	const struct of_device_id *of_id;
+diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
+index 2552fe28d050..5396b6ceb088 100644
+--- a/drivers/mtd/nand/jz4740_nand.c
++++ b/drivers/mtd/nand/jz4740_nand.c
+@@ -322,7 +322,7 @@ static inline void jz_nand_iounmap_resource(struct resource *res, void __iomem *
+ 	release_mem_region(res->start, resource_size(res));
+ }
+ 
+-static int __devinit jz_nand_detect_bank(struct platform_device *pdev, struct jz_nand *nand, unsigned char bank, size_t chipnr, uint8_t *nand_maf_id, uint8_t *nand_dev_id) {
++static int jz_nand_detect_bank(struct platform_device *pdev, struct jz_nand *nand, unsigned char bank, size_t chipnr, uint8_t *nand_maf_id, uint8_t *nand_dev_id) {
+ 	int ret;
+ 	int gpio;
+ 	char gpio_name[9];
+@@ -400,7 +400,7 @@ static int __devinit jz_nand_detect_bank(struct platform_device *pdev, struct jz
+ 	return ret;
+ }
+ 
+-static int __devinit jz_nand_probe(struct platform_device *pdev)
++static int jz_nand_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 	struct jz_nand *nand;
+diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c
+index 311564259d28..bb83daf9c739 100644
+--- a/drivers/mtd/nand/lpc32xx_mlc.c
++++ b/drivers/mtd/nand/lpc32xx_mlc.c
+@@ -655,7 +655,7 @@ static struct lpc32xx_nand_cfg_mlc *lpc32xx_parse_dt(struct device *dev)
+ /*
+  * Probe for NAND controller
+  */
+-static int __devinit lpc32xx_nand_probe(struct platform_device *pdev)
++static int lpc32xx_nand_probe(struct platform_device *pdev)
+ {
+ 	struct lpc32xx_nand_host *host;
+ 	struct mtd_info *mtd;
+diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/lpc32xx_slc.c
+index 9e291b71a8cc..17267f2819d2 100644
+--- a/drivers/mtd/nand/lpc32xx_slc.c
++++ b/drivers/mtd/nand/lpc32xx_slc.c
+@@ -755,7 +755,7 @@ static struct lpc32xx_nand_cfg_slc *lpc32xx_parse_dt(struct device *dev)
+ /*
+  * Probe for NAND controller
+  */
+-static int __devinit lpc32xx_nand_probe(struct platform_device *pdev)
++static int lpc32xx_nand_probe(struct platform_device *pdev)
+ {
+ 	struct lpc32xx_nand_host *host;
+ 	struct mtd_info *mtd;
+diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
+index 17fe0c942fb0..f779e6a3d4b2 100644
+--- a/drivers/mtd/nand/mpc5121_nfc.c
++++ b/drivers/mtd/nand/mpc5121_nfc.c
+@@ -626,7 +626,7 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
+ 		iounmap(prv->csreg);
+ }
+ 
+-static int __devinit mpc5121_nfc_probe(struct platform_device *op)
++static int mpc5121_nfc_probe(struct platform_device *op)
+ {
+ 	struct device_node *rootnode, *dn = op->dev.of_node;
+ 	struct device *dev = &op->dev;
+diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
+index a4caf640a307..77a03cf64dd3 100644
+--- a/drivers/mtd/nand/mxc_nand.c
++++ b/drivers/mtd/nand/mxc_nand.c
+@@ -1363,7 +1363,7 @@ static int __init mxcnd_probe_pdata(struct mxc_nand_host *host)
+ 	return 0;
+ }
+ 
+-static int __devinit mxcnd_probe(struct platform_device *pdev)
++static int mxcnd_probe(struct platform_device *pdev)
+ {
+ 	struct nand_chip *this;
+ 	struct mtd_info *mtd;
+diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
+index 32e6bef480dc..6fa4588d4771 100644
+--- a/drivers/mtd/nand/ndfc.c
++++ b/drivers/mtd/nand/ndfc.c
+@@ -197,7 +197,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
+ 	return ret;
+ }
+ 
+-static int __devinit ndfc_probe(struct platform_device *ofdev)
++static int ndfc_probe(struct platform_device *ofdev)
+ {
+ 	struct ndfc_controller *ndfc;
+ 	const __be32 *reg;
+diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c
+index eed134c55326..00766dfe4d3f 100644
+--- a/drivers/mtd/nand/nuc900_nand.c
++++ b/drivers/mtd/nand/nuc900_nand.c
+@@ -246,7 +246,7 @@ static void nuc900_nand_enable(struct nuc900_nand *nand)
+ 	spin_unlock(&nand->lock);
+ }
+ 
+-static int __devinit nuc900_nand_probe(struct platform_device *pdev)
++static int nuc900_nand_probe(struct platform_device *pdev)
+ {
+ 	struct nuc900_nand *nuc900_nand;
+ 	struct nand_chip *chip;
+diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
+index 5b3138620646..b00ccb2a68c7 100644
+--- a/drivers/mtd/nand/omap2.c
++++ b/drivers/mtd/nand/omap2.c
+@@ -1239,7 +1239,7 @@ static void omap3_free_bch(struct mtd_info *mtd)
+ }
+ #endif /* CONFIG_MTD_NAND_OMAP_BCH */
+ 
+-static int __devinit omap_nand_probe(struct platform_device *pdev)
++static int omap_nand_probe(struct platform_device *pdev)
+ {
+ 	struct omap_nand_info		*info;
+ 	struct omap_nand_platform_data	*pdata;
+diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c
+index 1440e51cedcc..2e477cb20b73 100644
+--- a/drivers/mtd/nand/pasemi_nand.c
++++ b/drivers/mtd/nand/pasemi_nand.c
+@@ -89,7 +89,7 @@ int pasemi_device_ready(struct mtd_info *mtd)
+ 	return !!(inl(lpcctl) & LBICTRL_LPCCTL_NR);
+ }
+ 
+-static int __devinit pasemi_nand_probe(struct platform_device *ofdev)
++static int pasemi_nand_probe(struct platform_device *ofdev)
+ {
+ 	struct pci_dev *pdev;
+ 	struct device_node *np = ofdev->dev.of_node;
+diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c
+index 95a1dba150d2..32e2996c9e73 100644
+--- a/drivers/mtd/nand/plat_nand.c
++++ b/drivers/mtd/nand/plat_nand.c
+@@ -28,7 +28,7 @@ static const char *part_probe_types[] = { "cmdlinepart", NULL };
+ /*
+  * Probe for the NAND device.
+  */
+-static int __devinit plat_nand_probe(struct platform_device *pdev)
++static int plat_nand_probe(struct platform_device *pdev)
+ {
+ 	struct platform_nand_data *pdata = pdev->dev.platform_data;
+ 	struct mtd_part_parser_data ppdata;
+diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c
+index d51e3c15d379..e45d6bd2901a 100644
+--- a/drivers/mtd/nand/sh_flctl.c
++++ b/drivers/mtd/nand/sh_flctl.c
+@@ -1086,7 +1086,7 @@ static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev)
+ }
+ #endif /* CONFIG_OF */
+ 
+-static int __devinit flctl_probe(struct platform_device *pdev)
++static int flctl_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res;
+ 	struct sh_flctl *flctl;
+diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c
+index 541fd5117625..870f0ff76c5f 100644
+--- a/drivers/mtd/nand/sharpsl.c
++++ b/drivers/mtd/nand/sharpsl.c
+@@ -106,7 +106,7 @@ static int sharpsl_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat,
+ /*
+  * Main initialization routine
+  */
+-static int __devinit sharpsl_nand_probe(struct platform_device *pdev)
++static int sharpsl_nand_probe(struct platform_device *pdev)
+ {
+ 	struct nand_chip *this;
+ 	struct resource *r;
+diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c
+index 78b1a040b88a..c9791fd1ee53 100644
+--- a/drivers/mtd/nand/socrates_nand.c
++++ b/drivers/mtd/nand/socrates_nand.c
+@@ -140,7 +140,7 @@ static int socrates_nand_device_ready(struct mtd_info *mtd)
+ /*
+  * Probe for the NAND device.
+  */
+-static int __devinit socrates_nand_probe(struct platform_device *ofdev)
++static int socrates_nand_probe(struct platform_device *ofdev)
+ {
+ 	struct socrates_nand_host *host;
+ 	struct mtd_info *mtd;
+diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c
+index 27aa44a6ec26..03e6af342423 100644
+--- a/drivers/mtd/onenand/generic.c
++++ b/drivers/mtd/onenand/generic.c
+@@ -35,7 +35,7 @@ struct onenand_info {
+ 	struct onenand_chip	onenand;
+ };
+ 
+-static int __devinit generic_onenand_probe(struct platform_device *pdev)
++static int generic_onenand_probe(struct platform_device *pdev)
+ {
+ 	struct onenand_info *info;
+ 	struct onenand_platform_data *pdata = pdev->dev.platform_data;
+diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
+index 73dac4c64a90..8c10a2f54158 100644
+--- a/drivers/mtd/onenand/omap2.c
++++ b/drivers/mtd/onenand/omap2.c
+@@ -619,7 +619,7 @@ static int omap2_onenand_disable(struct mtd_info *mtd)
+ 	return ret;
+ }
+ 
+-static int __devinit omap2_onenand_probe(struct platform_device *pdev)
++static int omap2_onenand_probe(struct platform_device *pdev)
+ {
+ 	struct omap_onenand_platform_data *pdata;
+ 	struct omap2_onenand *c;

commit 5153b88cac39b0a14662f0e15439b826bacfe213
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:24 2012 -0500
+
+    mtd: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Artem Bityutskiy 
+
+diff --git a/drivers/mtd/devices/bcm47xxsflash.c b/drivers/mtd/devices/bcm47xxsflash.c
+index 2dc5a6f3fd57..113aced64990 100644
+--- a/drivers/mtd/devices/bcm47xxsflash.c
++++ b/drivers/mtd/devices/bcm47xxsflash.c
+@@ -77,7 +77,7 @@ static int __devexit bcm47xxsflash_remove(struct platform_device *pdev)
+ }
+ 
+ static struct platform_driver bcma_sflash_driver = {
+-	.remove = __devexit_p(bcm47xxsflash_remove),
++	.remove = bcm47xxsflash_remove,
+ 	.driver = {
+ 		.name = "bcma_sflash",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
+index 1518324611a2..bd2d91254c62 100644
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -994,7 +994,7 @@ static struct spi_driver m25p80_driver = {
+ 	},
+ 	.id_table	= m25p_ids,
+ 	.probe	= m25p_probe,
+-	.remove	= __devexit_p(m25p_remove),
++	.remove	= m25p_remove,
+ 
+ 	/* REVISIT: many of these chips have deep power-down modes, which
+ 	 * should clearly be entered on suspend() to minimize power use.
+diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
+index 928fb0e6d73a..23ccc36840f6 100644
+--- a/drivers/mtd/devices/mtd_dataflash.c
++++ b/drivers/mtd/devices/mtd_dataflash.c
+@@ -920,7 +920,7 @@ static struct spi_driver dataflash_driver = {
+ 	},
+ 
+ 	.probe		= dataflash_probe,
+-	.remove		= __devexit_p(dataflash_remove),
++	.remove		= dataflash_remove,
+ 
+ 	/* FIXME:  investigate suspend and resume... */
+ };
+diff --git a/drivers/mtd/devices/spear_smi.c b/drivers/mtd/devices/spear_smi.c
+index 39e95673cdd2..e27737c91212 100644
+--- a/drivers/mtd/devices/spear_smi.c
++++ b/drivers/mtd/devices/spear_smi.c
+@@ -1092,7 +1092,7 @@ static struct platform_driver spear_smi_driver = {
+ #endif
+ 	},
+ 	.probe = spear_smi_probe,
+-	.remove = __devexit_p(spear_smi_remove),
++	.remove = spear_smi_remove,
+ };
+ module_platform_driver(spear_smi_driver);
+ 
+diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c
+index ab8a2f4c8d60..9ebf86d8faa8 100644
+--- a/drivers/mtd/devices/sst25l.c
++++ b/drivers/mtd/devices/sst25l.c
+@@ -428,7 +428,7 @@ static struct spi_driver sst25l_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= sst25l_probe,
+-	.remove		= __devexit_p(sst25l_remove),
++	.remove		= sst25l_remove,
+ };
+ 
+ module_spi_driver(sst25l_driver);
+diff --git a/drivers/mtd/maps/autcpu12-nvram.c b/drivers/mtd/maps/autcpu12-nvram.c
+index 76fb594bb1d9..ca0313db6fea 100644
+--- a/drivers/mtd/maps/autcpu12-nvram.c
++++ b/drivers/mtd/maps/autcpu12-nvram.c
+@@ -121,7 +121,7 @@ static struct platform_driver autcpu12_nvram_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= autcpu12_nvram_probe,
+-	.remove		= __devexit_p(autcpu12_nvram_remove),
++	.remove		= autcpu12_nvram_remove,
+ };
+ module_platform_driver(autcpu12_nvram_driver);
+ 
+diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c
+index ef5cde84a8b3..340e8a260547 100644
+--- a/drivers/mtd/maps/bfin-async-flash.c
++++ b/drivers/mtd/maps/bfin-async-flash.c
+@@ -184,7 +184,7 @@ static int __devexit bfin_flash_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver bfin_flash_driver = {
+ 	.probe		= bfin_flash_probe,
+-	.remove		= __devexit_p(bfin_flash_remove),
++	.remove		= bfin_flash_remove,
+ 	.driver		= {
+ 		.name	= DRIVER_NAME,
+ 	},
+diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c
+index e4de96ba52b3..670af9afa786 100644
+--- a/drivers/mtd/maps/gpio-addr-flash.c
++++ b/drivers/mtd/maps/gpio-addr-flash.c
+@@ -273,7 +273,7 @@ static int __devexit gpio_flash_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver gpio_flash_driver = {
+ 	.probe		= gpio_flash_probe,
+-	.remove		= __devexit_p(gpio_flash_remove),
++	.remove		= gpio_flash_remove,
+ 	.driver		= {
+ 		.name	= DRIVER_NAME,
+ 	},
+diff --git a/drivers/mtd/maps/intel_vr_nor.c b/drivers/mtd/maps/intel_vr_nor.c
+index 93f03175c82d..f6185d4c6ba9 100644
+--- a/drivers/mtd/maps/intel_vr_nor.c
++++ b/drivers/mtd/maps/intel_vr_nor.c
+@@ -256,7 +256,7 @@ vr_nor_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ static struct pci_driver vr_nor_pci_driver = {
+ 	.name = DRV_NAME,
+ 	.probe = vr_nor_pci_probe,
+-	.remove = __devexit_p(vr_nor_pci_remove),
++	.remove = vr_nor_pci_remove,
+ 	.id_table = vr_nor_pci_ids,
+ };
+ 
+diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c
+index c03456f17004..4c032f168138 100644
+--- a/drivers/mtd/maps/lantiq-flash.c
++++ b/drivers/mtd/maps/lantiq-flash.c
+@@ -209,7 +209,7 @@ MODULE_DEVICE_TABLE(of, ltq_mtd_match);
+ 
+ static struct platform_driver ltq_mtd_driver = {
+ 	.probe = ltq_mtd_probe,
+-	.remove = __devexit_p(ltq_mtd_remove),
++	.remove = ltq_mtd_remove,
+ 	.driver = {
+ 		.name = "ltq-nor",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/mtd/maps/latch-addr-flash.c b/drivers/mtd/maps/latch-addr-flash.c
+index 3c7ad17fca78..962a76a283a5 100644
+--- a/drivers/mtd/maps/latch-addr-flash.c
++++ b/drivers/mtd/maps/latch-addr-flash.c
+@@ -218,7 +218,7 @@ static int __devinit latch_addr_flash_probe(struct platform_device *dev)
+ 
+ static struct platform_driver latch_addr_flash_driver = {
+ 	.probe		= latch_addr_flash_probe,
+-	.remove		= __devexit_p(latch_addr_flash_remove),
++	.remove		= latch_addr_flash_remove,
+ 	.driver		= {
+ 		.name	= DRIVER_NAME,
+ 	},
+diff --git a/drivers/mtd/maps/pci.c b/drivers/mtd/maps/pci.c
+index 1c30c1a307f4..ddc8c0c56d01 100644
+--- a/drivers/mtd/maps/pci.c
++++ b/drivers/mtd/maps/pci.c
+@@ -326,7 +326,7 @@ mtd_pci_remove(struct pci_dev *dev)
+ static struct pci_driver mtd_pci_driver = {
+ 	.name =		"MTD PCI",
+ 	.probe =	mtd_pci_probe,
+-	.remove =	__devexit_p(mtd_pci_remove),
++	.remove =	mtd_pci_remove,
+ 	.id_table =	mtd_pci_ids,
+ };
+ 
+diff --git a/drivers/mtd/maps/pismo.c b/drivers/mtd/maps/pismo.c
+index 65bd1cd4d627..9f4e5947c99f 100644
+--- a/drivers/mtd/maps/pismo.c
++++ b/drivers/mtd/maps/pismo.c
+@@ -267,7 +267,7 @@ static struct i2c_driver pismo_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= pismo_probe,
+-	.remove		= __devexit_p(pismo_remove),
++	.remove		= pismo_remove,
+ 	.id_table	= pismo_id,
+ };
+ 
+diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
+index 81884c277405..f913a1c3f2b9 100644
+--- a/drivers/mtd/maps/pxa2xx-flash.c
++++ b/drivers/mtd/maps/pxa2xx-flash.c
+@@ -139,7 +139,7 @@ static struct platform_driver pxa2xx_flash_driver = {
+ 		.owner		= THIS_MODULE,
+ 	},
+ 	.probe		= pxa2xx_flash_probe,
+-	.remove		= __devexit_p(pxa2xx_flash_remove),
++	.remove		= pxa2xx_flash_remove,
+ 	.shutdown	= pxa2xx_flash_shutdown,
+ };
+ 
+diff --git a/drivers/mtd/maps/scb2_flash.c b/drivers/mtd/maps/scb2_flash.c
+index 9dcbc684abdb..d527608e5d22 100644
+--- a/drivers/mtd/maps/scb2_flash.c
++++ b/drivers/mtd/maps/scb2_flash.c
+@@ -231,7 +231,7 @@ static struct pci_driver scb2_flash_driver = {
+ 	.name =     "Intel SCB2 BIOS Flash",
+ 	.id_table = scb2_flash_pci_ids,
+ 	.probe =    scb2_flash_probe,
+-	.remove =   __devexit_p(scb2_flash_remove),
++	.remove =   scb2_flash_remove,
+ };
+ 
+ module_pci_driver(scb2_flash_driver);
+diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c
+index 175e537b444f..1c03ca7c4a74 100644
+--- a/drivers/mtd/maps/sun_uflash.c
++++ b/drivers/mtd/maps/sun_uflash.c
+@@ -155,7 +155,7 @@ static struct platform_driver uflash_driver = {
+ 		.of_match_table = uflash_match,
+ 	},
+ 	.probe		= uflash_probe,
+-	.remove		= __devexit_p(uflash_remove),
++	.remove		= uflash_remove,
+ };
+ 
+ module_platform_driver(uflash_driver);
+diff --git a/drivers/mtd/maps/vmu-flash.c b/drivers/mtd/maps/vmu-flash.c
+index 2e2b0945edc7..5a83a264eb83 100644
+--- a/drivers/mtd/maps/vmu-flash.c
++++ b/drivers/mtd/maps/vmu-flash.c
+@@ -802,7 +802,7 @@ static struct maple_driver vmu_flash_driver = {
+ 	.drv = {
+ 		.name =		"Dreamcast_visual_memory",
+ 		.probe =	probe_maple_vmu,
+-		.remove = 	__devexit_p(remove_maple_vmu),
++		.remove =	remove_maple_vmu,
+ 	},
+ };
+ 
+diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c
+index 9e7723aa7acc..51dba43e2879 100644
+--- a/drivers/mtd/nand/ams-delta.c
++++ b/drivers/mtd/nand/ams-delta.c
+@@ -289,7 +289,7 @@ static int __devexit ams_delta_cleanup(struct platform_device *pdev)
+ 
+ static struct platform_driver ams_delta_nand_driver = {
+ 	.probe		= ams_delta_init,
+-	.remove		= __devexit_p(ams_delta_cleanup),
++	.remove		= ams_delta_cleanup,
+ 	.driver		= {
+ 		.name	= "ams-delta-nand",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
+index 5c47b200045a..d84af46ccc8d 100644
+--- a/drivers/mtd/nand/au1550nd.c
++++ b/drivers/mtd/nand/au1550nd.c
+@@ -509,7 +509,7 @@ static struct platform_driver au1550nd_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= au1550nd_probe,
+-	.remove		= __devexit_p(au1550nd_remove),
++	.remove		= au1550nd_remove,
+ };
+ 
+ module_platform_driver(au1550nd_driver);
+diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c
+index ab0caa74eb43..0afd4ac34248 100644
+--- a/drivers/mtd/nand/bf5xx_nand.c
++++ b/drivers/mtd/nand/bf5xx_nand.c
+@@ -865,7 +865,7 @@ static int bf5xx_nand_resume(struct platform_device *dev)
+ /* driver device registration */
+ static struct platform_driver bf5xx_nand_driver = {
+ 	.probe		= bf5xx_nand_probe,
+-	.remove		= __devexit_p(bf5xx_nand_remove),
++	.remove		= bf5xx_nand_remove,
+ 	.suspend	= bf5xx_nand_suspend,
+ 	.resume		= bf5xx_nand_resume,
+ 	.driver		= {
+diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c
+index 2bb7170502c2..1b62f043bf7e 100644
+--- a/drivers/mtd/nand/cafe_nand.c
++++ b/drivers/mtd/nand/cafe_nand.c
+@@ -887,7 +887,7 @@ static struct pci_driver cafe_nand_pci_driver = {
+ 	.name = "CAFÉ NAND",
+ 	.id_table = cafe_nand_tbl,
+ 	.probe = cafe_nand_probe,
+-	.remove = __devexit_p(cafe_nand_remove),
++	.remove = cafe_nand_remove,
+ 	.resume = cafe_nand_resume,
+ };
+ 
+diff --git a/drivers/mtd/nand/denali_dt.c b/drivers/mtd/nand/denali_dt.c
+index fbabbaa04374..445de7c8bb50 100644
+--- a/drivers/mtd/nand/denali_dt.c
++++ b/drivers/mtd/nand/denali_dt.c
+@@ -142,7 +142,7 @@ static int __devexit denali_dt_remove(struct platform_device *ofdev)
+ 
+ static struct platform_driver denali_dt_driver = {
+ 	.probe		= denali_dt_probe,
+-	.remove		= __devexit_p(denali_dt_remove),
++	.remove		= denali_dt_remove,
+ 	.driver		= {
+ 		.name	= "denali-nand-dt",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
+index 45df542b9c61..b40661d7160e 100644
+--- a/drivers/mtd/nand/fsl_upm.c
++++ b/drivers/mtd/nand/fsl_upm.c
+@@ -350,7 +350,7 @@ static struct platform_driver of_fun_driver = {
+ 		.of_match_table = of_fun_match,
+ 	},
+ 	.probe		= fun_probe,
+-	.remove		= __devexit_p(fun_remove),
++	.remove		= fun_remove,
+ };
+ 
+ module_platform_driver(of_fun_driver);
+diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+index d37619882fa6..7ce6d01a3c94 100644
+--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
++++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+@@ -1692,7 +1692,7 @@ static struct platform_driver gpmi_nand_driver = {
+ 		.of_match_table = gpmi_nand_id_table,
+ 	},
+ 	.probe   = gpmi_nand_probe,
+-	.remove  = __devexit_p(gpmi_nand_remove),
++	.remove  = gpmi_nand_remove,
+ 	.id_table = gpmi_ids,
+ };
+ module_platform_driver(gpmi_nand_driver);
+diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
+index 100b6775e175..2552fe28d050 100644
+--- a/drivers/mtd/nand/jz4740_nand.c
++++ b/drivers/mtd/nand/jz4740_nand.c
+@@ -573,7 +573,7 @@ static int __devexit jz_nand_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver jz_nand_driver = {
+ 	.probe = jz_nand_probe,
+-	.remove = __devexit_p(jz_nand_remove),
++	.remove = jz_nand_remove,
+ 	.driver = {
+ 		.name = "jz4740-nand",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c
+index c29b7ac1f6af..311564259d28 100644
+--- a/drivers/mtd/nand/lpc32xx_mlc.c
++++ b/drivers/mtd/nand/lpc32xx_mlc.c
+@@ -907,7 +907,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_nand_match);
+ 
+ static struct platform_driver lpc32xx_nand_driver = {
+ 	.probe		= lpc32xx_nand_probe,
+-	.remove		= __devexit_p(lpc32xx_nand_remove),
++	.remove		= lpc32xx_nand_remove,
+ 	.resume		= lpc32xx_nand_resume,
+ 	.suspend	= lpc32xx_nand_suspend,
+ 	.driver		= {
+diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/lpc32xx_slc.c
+index 32409c45d479..9e291b71a8cc 100644
+--- a/drivers/mtd/nand/lpc32xx_slc.c
++++ b/drivers/mtd/nand/lpc32xx_slc.c
+@@ -1021,7 +1021,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_nand_match);
+ 
+ static struct platform_driver lpc32xx_nand_driver = {
+ 	.probe		= lpc32xx_nand_probe,
+-	.remove		= __devexit_p(lpc32xx_nand_remove),
++	.remove		= lpc32xx_nand_remove,
+ 	.resume		= lpc32xx_nand_resume,
+ 	.suspend	= lpc32xx_nand_suspend,
+ 	.driver		= {
+diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
+index f776c8577b8c..17fe0c942fb0 100644
+--- a/drivers/mtd/nand/mpc5121_nfc.c
++++ b/drivers/mtd/nand/mpc5121_nfc.c
+@@ -848,7 +848,7 @@ static struct of_device_id mpc5121_nfc_match[] __devinitdata = {
+ 
+ static struct platform_driver mpc5121_nfc_driver = {
+ 	.probe		= mpc5121_nfc_probe,
+-	.remove		= __devexit_p(mpc5121_nfc_remove),
++	.remove		= mpc5121_nfc_remove,
+ 	.driver		= {
+ 		.name = DRV_NAME,
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
+index 72e31d86030d..a4caf640a307 100644
+--- a/drivers/mtd/nand/mxc_nand.c
++++ b/drivers/mtd/nand/mxc_nand.c
+@@ -1556,7 +1556,7 @@ static struct platform_driver mxcnd_driver = {
+ 		   .of_match_table = of_match_ptr(mxcnd_dt_ids),
+ 	},
+ 	.probe = mxcnd_probe,
+-	.remove = __devexit_p(mxcnd_remove),
++	.remove = mxcnd_remove,
+ };
+ module_platform_driver(mxcnd_driver);
+ 
+diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
+index 5fd3f010e3ae..32e6bef480dc 100644
+--- a/drivers/mtd/nand/ndfc.c
++++ b/drivers/mtd/nand/ndfc.c
+@@ -279,7 +279,7 @@ static struct platform_driver ndfc_driver = {
+ 		.of_match_table = ndfc_match,
+ 	},
+ 	.probe = ndfc_probe,
+-	.remove = __devexit_p(ndfc_remove),
++	.remove = ndfc_remove,
+ };
+ 
+ module_platform_driver(ndfc_driver);
+diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c
+index 94dc46bc118c..eed134c55326 100644
+--- a/drivers/mtd/nand/nuc900_nand.c
++++ b/drivers/mtd/nand/nuc900_nand.c
+@@ -340,7 +340,7 @@ static int __devexit nuc900_nand_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver nuc900_nand_driver = {
+ 	.probe		= nuc900_nand_probe,
+-	.remove		= __devexit_p(nuc900_nand_remove),
++	.remove		= nuc900_nand_remove,
+ 	.driver		= {
+ 		.name	= "nuc900-fmi",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c
+index aefaf8cd31ef..e6b296dcb122 100644
+--- a/drivers/mtd/nand/orion_nand.c
++++ b/drivers/mtd/nand/orion_nand.c
+@@ -223,7 +223,7 @@ static struct of_device_id orion_nand_of_match_table[] = {
+ #endif
+ 
+ static struct platform_driver orion_nand_driver = {
+-	.remove		= __devexit_p(orion_nand_remove),
++	.remove		= orion_nand_remove,
+ 	.driver		= {
+ 		.name	= "orion_nand",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c
+index a47ee68a0cfa..95a1dba150d2 100644
+--- a/drivers/mtd/nand/plat_nand.c
++++ b/drivers/mtd/nand/plat_nand.c
+@@ -160,7 +160,7 @@ MODULE_DEVICE_TABLE(of, plat_nand_match);
+ 
+ static struct platform_driver plat_nand_driver = {
+ 	.probe	= plat_nand_probe,
+-	.remove	= __devexit_p(plat_nand_remove),
++	.remove	= plat_nand_remove,
+ 	.driver	= {
+ 		.name		= "gen_nand",
+ 		.owner		= THIS_MODULE,
+diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c
+index 3421e3762a5a..541fd5117625 100644
+--- a/drivers/mtd/nand/sharpsl.c
++++ b/drivers/mtd/nand/sharpsl.c
+@@ -228,7 +228,7 @@ static struct platform_driver sharpsl_nand_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= sharpsl_nand_probe,
+-	.remove		= __devexit_p(sharpsl_nand_remove),
++	.remove		= sharpsl_nand_remove,
+ };
+ 
+ module_platform_driver(sharpsl_nand_driver);
+diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c
+index f3f28fafbf7a..78b1a040b88a 100644
+--- a/drivers/mtd/nand/socrates_nand.c
++++ b/drivers/mtd/nand/socrates_nand.c
+@@ -251,7 +251,7 @@ static struct platform_driver socrates_nand_driver = {
+ 		.of_match_table = socrates_nand_match,
+ 	},
+ 	.probe		= socrates_nand_probe,
+-	.remove		= __devexit_p(socrates_nand_remove),
++	.remove		= socrates_nand_remove,
+ };
+ 
+ module_platform_driver(socrates_nand_driver);
+diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c
+index 1c4f97c63e62..27aa44a6ec26 100644
+--- a/drivers/mtd/onenand/generic.c
++++ b/drivers/mtd/onenand/generic.c
+@@ -112,7 +112,7 @@ static struct platform_driver generic_onenand_driver = {
+ 		.owner		= THIS_MODULE,
+ 	},
+ 	.probe		= generic_onenand_probe,
+-	.remove		= __devexit_p(generic_onenand_remove),
++	.remove		= generic_onenand_remove,
+ };
+ 
+ module_platform_driver(generic_onenand_driver);
+diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
+index 1961be985171..73dac4c64a90 100644
+--- a/drivers/mtd/onenand/omap2.c
++++ b/drivers/mtd/onenand/omap2.c
+@@ -811,7 +811,7 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver omap2_onenand_driver = {
+ 	.probe		= omap2_onenand_probe,
+-	.remove		= __devexit_p(omap2_onenand_remove),
++	.remove		= omap2_onenand_remove,
+ 	.shutdown	= omap2_onenand_shutdown,
+ 	.driver		= {
+ 		.name	= DRIVER_NAME,
+diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
+index 8e4b3f2742ba..3d462cbcdbe4 100644
+--- a/drivers/mtd/onenand/samsung.c
++++ b/drivers/mtd/onenand/samsung.c
+@@ -1130,7 +1130,7 @@ static struct platform_driver s3c_onenand_driver = {
+ 	},
+ 	.id_table	= s3c_onenand_driver_ids,
+ 	.probe          = s3c_onenand_probe,
+-	.remove         = __devexit_p(s3c_onenand_remove),
++	.remove         = s3c_onenand_remove,
+ };
+ 
+ module_platform_driver(s3c_onenand_driver);

commit ae8d8a146725a966bd7c59c94f4d0016dcf7a04f
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:18 2012 -0500
+
+    tty: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Jiri Slaby 
+    Cc: Alan Cox 
+    Acked-by: Tobias Klauser 
+    Cc: Lucas Tavares 
+    Cc: Daniel Walker 
+    Cc: Bryan Huntsman 
+    Cc: "David S. Miller" 
+    Cc: Peter Korsgaard 
+    Cc: Tony Prisk 
+    Acked-by: David Brown 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c
+index 2dff87cdce23..b09c8d1f9a66 100644
+--- a/drivers/tty/cyclades.c
++++ b/drivers/tty/cyclades.c
+@@ -3931,7 +3931,7 @@ static int cy_pci_probe(struct pci_dev *pdev,
+ 	return retval;
+ }
+ 
+-static void __devexit cy_pci_remove(struct pci_dev *pdev)
++static void cy_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct cyclades_card *cinfo = pci_get_drvdata(pdev);
+ 	unsigned int i, channel;
+diff --git a/drivers/tty/hvc/hvc_opal.c b/drivers/tty/hvc/hvc_opal.c
+index 61da5cd093fc..be1a9a1e749e 100644
+--- a/drivers/tty/hvc/hvc_opal.c
++++ b/drivers/tty/hvc/hvc_opal.c
+@@ -222,7 +222,7 @@ static int hvc_opal_probe(struct platform_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devexit hvc_opal_remove(struct platform_device *dev)
++static int hvc_opal_remove(struct platform_device *dev)
+ {
+ 	struct hvc_struct *hp = dev_get_drvdata(&dev->dev);
+ 	int rc, termno;
+diff --git a/drivers/tty/hvc/hvc_vio.c b/drivers/tty/hvc/hvc_vio.c
+index 282d143a6437..ed6f5f1f5a55 100644
+--- a/drivers/tty/hvc/hvc_vio.c
++++ b/drivers/tty/hvc/hvc_vio.c
+@@ -362,7 +362,7 @@ static int hvc_vio_probe(struct vio_dev *vdev,
+ 	return 0;
+ }
+ 
+-static int __devexit hvc_vio_remove(struct vio_dev *vdev)
++static int hvc_vio_remove(struct vio_dev *vdev)
+ {
+ 	struct hvc_struct *hp = dev_get_drvdata(&vdev->dev);
+ 	int rc, termno;
+diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c
+index 5afe3b6041cf..877635733952 100644
+--- a/drivers/tty/hvc/hvcs.c
++++ b/drivers/tty/hvc/hvcs.c
+@@ -332,7 +332,7 @@ static void hvcs_hangup(struct tty_struct * tty);
+ 
+ static int hvcs_probe(struct vio_dev *dev,
+ 		const struct vio_device_id *id);
+-static int __devexit hvcs_remove(struct vio_dev *dev);
++static int hvcs_remove(struct vio_dev *dev);
+ static int __init hvcs_module_init(void);
+ static void __exit hvcs_module_exit(void);
+ static int hvcs_initialize(void);
+@@ -835,7 +835,7 @@ static int hvcs_probe(
+ 	return 0;
+ }
+ 
+-static int __devexit hvcs_remove(struct vio_dev *dev)
++static int hvcs_remove(struct vio_dev *dev)
+ {
+ 	struct hvcs_struct *hvcsd = dev_get_drvdata(&dev->dev);
+ 	unsigned long flags;
+diff --git a/drivers/tty/isicom.c b/drivers/tty/isicom.c
+index 82661889b322..3205b2e9090b 100644
+--- a/drivers/tty/isicom.c
++++ b/drivers/tty/isicom.c
+@@ -148,7 +148,7 @@
+ #endif
+ 
+ static int isicom_probe(struct pci_dev *, const struct pci_device_id *);
+-static void __devexit isicom_remove(struct pci_dev *);
++static void isicom_remove(struct pci_dev *);
+ 
+ static struct pci_device_id isicom_pci_tbl[] = {
+ 	{ PCI_DEVICE(VENDOR_ID, 0x2028) },
+@@ -1635,7 +1635,7 @@ static int isicom_probe(struct pci_dev *pdev,
+ 	return retval;
+ }
+ 
+-static void __devexit isicom_remove(struct pci_dev *pdev)
++static void isicom_remove(struct pci_dev *pdev)
+ {
+ 	struct isi_board *board = pci_get_drvdata(pdev);
+ 	unsigned int i;
+diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c
+index 60ea74e76d3a..f9d28503bdec 100644
+--- a/drivers/tty/moxa.c
++++ b/drivers/tty/moxa.c
+@@ -1020,7 +1020,7 @@ static int moxa_pci_probe(struct pci_dev *pdev,
+ 	return retval;
+ }
+ 
+-static void __devexit moxa_pci_remove(struct pci_dev *pdev)
++static void moxa_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct moxa_board_conf *brd = pci_get_drvdata(pdev);
+ 
+diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c
+index 7f5e0ccf96ea..40113868bec2 100644
+--- a/drivers/tty/mxser.c
++++ b/drivers/tty/mxser.c
+@@ -2658,7 +2658,7 @@ static int mxser_probe(struct pci_dev *pdev,
+ #endif
+ }
+ 
+-static void __devexit mxser_remove(struct pci_dev *pdev)
++static void mxser_remove(struct pci_dev *pdev)
+ {
+ #ifdef CONFIG_PCI
+ 	struct mxser_board *brd = pci_get_drvdata(pdev);
+diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c
+index 2445aa4d2fa4..a0c69ab04399 100644
+--- a/drivers/tty/nozomi.c
++++ b/drivers/tty/nozomi.c
+@@ -1507,7 +1507,7 @@ static int nozomi_card_init(struct pci_dev *pdev,
+ 	return ret;
+ }
+ 
+-static void __devexit tty_exit(struct nozomi *dc)
++static void tty_exit(struct nozomi *dc)
+ {
+ 	unsigned int i;
+ 
+@@ -1530,7 +1530,7 @@ static void __devexit tty_exit(struct nozomi *dc)
+ }
+ 
+ /* Deallocate memory for one device */
+-static void __devexit nozomi_card_exit(struct pci_dev *pdev)
++static void nozomi_card_exit(struct pci_dev *pdev)
+ {
+ 	int i;
+ 	struct ctrl_ul ctrl;
+diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
+index 40ba8cc0985d..2af83a246499 100644
+--- a/drivers/tty/serial/8250/8250.c
++++ b/drivers/tty/serial/8250/8250.c
+@@ -3035,7 +3035,7 @@ static int serial8250_probe(struct platform_device *dev)
+ /*
+  * Remove serial ports registered against a platform device.
+  */
+-static int __devexit serial8250_remove(struct platform_device *dev)
++static int serial8250_remove(struct platform_device *dev)
+ {
+ 	int i;
+ 
+diff --git a/drivers/tty/serial/8250/8250_acorn.c b/drivers/tty/serial/8250/8250_acorn.c
+index ed095eb2e3f2..549aa07c0d27 100644
+--- a/drivers/tty/serial/8250/8250_acorn.c
++++ b/drivers/tty/serial/8250/8250_acorn.c
+@@ -80,7 +80,7 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
+ 	return 0;
+ }
+ 
+-static void __devexit serial_card_remove(struct expansion_card *ec)
++static void serial_card_remove(struct expansion_card *ec)
+ {
+ 	struct serial_card_info *info = ecard_get_drvdata(ec);
+ 	int i;
+diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
+index 7664750c2bd6..1d0dba2d562d 100644
+--- a/drivers/tty/serial/8250/8250_dw.c
++++ b/drivers/tty/serial/8250/8250_dw.c
+@@ -152,7 +152,7 @@ static int dw8250_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit dw8250_remove(struct platform_device *pdev)
++static int dw8250_remove(struct platform_device *pdev)
+ {
+ 	struct dw8250_data *data = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c
+index 430bf42374c0..916cc19fbbda 100644
+--- a/drivers/tty/serial/8250/8250_em.c
++++ b/drivers/tty/serial/8250/8250_em.c
+@@ -152,7 +152,7 @@ static int serial8250_em_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit serial8250_em_remove(struct platform_device *pdev)
++static int serial8250_em_remove(struct platform_device *pdev)
+ {
+ 	struct serial8250_em_priv *priv = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/tty/serial/8250/8250_hp300.c b/drivers/tty/serial/8250/8250_hp300.c
+index 2b945052ee08..5bdaf271d395 100644
+--- a/drivers/tty/serial/8250/8250_hp300.c
++++ b/drivers/tty/serial/8250/8250_hp300.c
+@@ -38,7 +38,7 @@ static struct hp300_port *hp300_ports;
+ 
+ static int hpdca_init_one(struct dio_dev *d,
+ 					const struct dio_device_id *ent);
+-static void __devexit hpdca_remove_one(struct dio_dev *d);
++static void hpdca_remove_one(struct dio_dev *d);
+ 
+ static struct dio_device_id hpdca_dio_tbl[] = {
+ 	{ DIO_ID_DCA0 },
+@@ -288,7 +288,7 @@ static int __init hp300_8250_init(void)
+ }
+ 
+ #ifdef CONFIG_HPDCA
+-static void __devexit hpdca_remove_one(struct dio_dev *d)
++static void hpdca_remove_one(struct dio_dev *d)
+ {
+ 	int line;
+ 
+diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
+index 3252c5d47ff8..97058c1d7d45 100644
+--- a/drivers/tty/serial/8250/8250_pci.c
++++ b/drivers/tty/serial/8250/8250_pci.c
+@@ -288,7 +288,7 @@ static int pci_plx9050_init(struct pci_dev *dev)
+ 	return 0;
+ }
+ 
+-static void __devexit pci_plx9050_exit(struct pci_dev *dev)
++static void pci_plx9050_exit(struct pci_dev *dev)
+ {
+ 	u8 __iomem *p;
+ 
+@@ -313,7 +313,7 @@ static void __devexit pci_plx9050_exit(struct pci_dev *dev)
+ #define NI8420_INT_ENABLE_REG	0x38
+ #define NI8420_INT_ENABLE_BIT	0x2000
+ 
+-static void __devexit pci_ni8420_exit(struct pci_dev *dev)
++static void pci_ni8420_exit(struct pci_dev *dev)
+ {
+ 	void __iomem *p;
+ 	unsigned long base, len;
+@@ -345,7 +345,7 @@ static void __devexit pci_ni8420_exit(struct pci_dev *dev)
+ 
+ #define MITE_LCIMR2_CLR_CPU_IE	(1 << 30)
+ 
+-static void __devexit pci_ni8430_exit(struct pci_dev *dev)
++static void pci_ni8430_exit(struct pci_dev *dev)
+ {
+ 	void __iomem *p;
+ 	unsigned long base, len;
+@@ -422,7 +422,7 @@ static int sbs_init(struct pci_dev *dev)
+  * Disables the global interrupt of PMC-OctalPro
+  */
+ 
+-static void __devexit sbs_exit(struct pci_dev *dev)
++static void sbs_exit(struct pci_dev *dev)
+ {
+ 	u8 __iomem *p;
+ 
+@@ -991,7 +991,7 @@ static int pci_ite887x_init(struct pci_dev *dev)
+ 	return ret;
+ }
+ 
+-static void __devexit pci_ite887x_exit(struct pci_dev *dev)
++static void pci_ite887x_exit(struct pci_dev *dev)
+ {
+ 	u32 ioport;
+ 	/* the ioport is bit 0-15 in POSIO0R */
+@@ -2988,7 +2988,7 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
+ 	return rc;
+ }
+ 
+-static void __devexit pciserial_remove_one(struct pci_dev *dev)
++static void pciserial_remove_one(struct pci_dev *dev)
+ {
+ 	struct serial_private *priv = pci_get_drvdata(dev);
+ 
+diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c
+index 71daae90fb5e..35d9ab95c5cb 100644
+--- a/drivers/tty/serial/8250/8250_pnp.c
++++ b/drivers/tty/serial/8250/8250_pnp.c
+@@ -476,7 +476,7 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
+ 	return 0;
+ }
+ 
+-static void __devexit serial_pnp_remove(struct pnp_dev *dev)
++static void serial_pnp_remove(struct pnp_dev *dev)
+ {
+ 	long line = (long)pnp_get_drvdata(dev);
+ 	if (line)
+diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c
+index ef5c705fa2b3..872f14ae43d2 100644
+--- a/drivers/tty/serial/altera_jtaguart.c
++++ b/drivers/tty/serial/altera_jtaguart.c
+@@ -453,7 +453,7 @@ static int altera_jtaguart_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit altera_jtaguart_remove(struct platform_device *pdev)
++static int altera_jtaguart_remove(struct platform_device *pdev)
+ {
+ 	struct uart_port *port;
+ 	int i = pdev->id;
+diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c
+index 066b5035e10a..684a0808e1c7 100644
+--- a/drivers/tty/serial/altera_uart.c
++++ b/drivers/tty/serial/altera_uart.c
+@@ -598,7 +598,7 @@ static int altera_uart_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit altera_uart_remove(struct platform_device *pdev)
++static int altera_uart_remove(struct platform_device *pdev)
+ {
+ 	struct uart_port *port = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c
+index ad171508b9a9..505c490c0b44 100644
+--- a/drivers/tty/serial/ar933x_uart.c
++++ b/drivers/tty/serial/ar933x_uart.c
+@@ -707,7 +707,7 @@ static int ar933x_uart_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit ar933x_uart_remove(struct platform_device *pdev)
++static int ar933x_uart_remove(struct platform_device *pdev)
+ {
+ 	struct ar933x_uart_port *up;
+ 
+diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
+index 158d798a5203..3e0b3fac6a0e 100644
+--- a/drivers/tty/serial/arc_uart.c
++++ b/drivers/tty/serial/arc_uart.c
+@@ -689,7 +689,7 @@ static int arc_serial_probe(struct platform_device *pdev)
+ 	return uart_add_one_port(&arc_uart_driver, &uart->port);
+ }
+ 
+-static int __devexit arc_serial_remove(struct platform_device *pdev)
++static int arc_serial_remove(struct platform_device *pdev)
+ {
+ 	/* This will never be called */
+ 	return 0;
+diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
+index 02540cbf16a6..d2a98da26133 100644
+--- a/drivers/tty/serial/atmel_serial.c
++++ b/drivers/tty/serial/atmel_serial.c
+@@ -1851,7 +1851,7 @@ static int atmel_serial_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit atmel_serial_remove(struct platform_device *pdev)
++static int atmel_serial_remove(struct platform_device *pdev)
+ {
+ 	struct uart_port *port = platform_get_drvdata(pdev);
+ 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+diff --git a/drivers/tty/serial/bcm63xx_uart.c b/drivers/tty/serial/bcm63xx_uart.c
+index e54d1703be1e..c76a226080f2 100644
+--- a/drivers/tty/serial/bcm63xx_uart.c
++++ b/drivers/tty/serial/bcm63xx_uart.c
+@@ -848,7 +848,7 @@ static int bcm_uart_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit bcm_uart_remove(struct platform_device *pdev)
++static int bcm_uart_remove(struct platform_device *pdev)
+ {
+ 	struct uart_port *port;
+ 
+diff --git a/drivers/tty/serial/bfin_sport_uart.c b/drivers/tty/serial/bfin_sport_uart.c
+index a47e00b056e7..f5d117379b60 100644
+--- a/drivers/tty/serial/bfin_sport_uart.c
++++ b/drivers/tty/serial/bfin_sport_uart.c
+@@ -850,7 +850,7 @@ static int sport_uart_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit sport_uart_remove(struct platform_device *pdev)
++static int sport_uart_remove(struct platform_device *pdev)
+ {
+ 	struct sport_uart_port *sport = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c
+index f1f8210a6130..18cf45a29d40 100644
+--- a/drivers/tty/serial/bfin_uart.c
++++ b/drivers/tty/serial/bfin_uart.c
+@@ -1389,7 +1389,7 @@ static int bfin_serial_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit bfin_serial_remove(struct platform_device *pdev)
++static int bfin_serial_remove(struct platform_device *pdev)
+ {
+ 	struct bfin_serial_port *uart = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c
+index 006d283bbded..3fd2526d121e 100644
+--- a/drivers/tty/serial/clps711x.c
++++ b/drivers/tty/serial/clps711x.c
+@@ -491,7 +491,7 @@ static int uart_clps711x_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit uart_clps711x_remove(struct platform_device *pdev)
++static int uart_clps711x_remove(struct platform_device *pdev)
+ {
+ 	struct clps711x_port *s = platform_get_drvdata(pdev);
+ 	int i;
+diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
+index de3f0f6eba74..ad0caf176808 100644
+--- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c
++++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
+@@ -1396,7 +1396,7 @@ static int cpm_uart_probe(struct platform_device *ofdev)
+ 	return uart_add_one_port(&cpm_reg, &pinfo->port);
+ }
+ 
+-static int __devexit cpm_uart_remove(struct platform_device *ofdev)
++static int cpm_uart_remove(struct platform_device *ofdev)
+ {
+ 	struct uart_cpm_port *pinfo = dev_get_drvdata(&ofdev->dev);
+ 	return uart_remove_one_port(&cpm_reg, &pinfo->port);
+diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c
+index 833c33a2751a..a8cbb2670521 100644
+--- a/drivers/tty/serial/efm32-uart.c
++++ b/drivers/tty/serial/efm32-uart.c
+@@ -764,7 +764,7 @@ static int efm32_uart_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit efm32_uart_remove(struct platform_device *pdev)
++static int efm32_uart_remove(struct platform_device *pdev)
+ {
+ 	struct efm32_uart_port *efm_port = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c
+index a8267956ac88..6197a69adb4d 100644
+--- a/drivers/tty/serial/icom.c
++++ b/drivers/tty/serial/icom.c
+@@ -1596,7 +1596,7 @@ static int icom_probe(struct pci_dev *dev,
+ 	return retval;
+ }
+ 
+-static void __devexit icom_remove(struct pci_dev *dev)
++static void icom_remove(struct pci_dev *dev)
+ {
+ 	struct icom_adapter *icom_adapter;
+ 	struct list_head *tmp;
+diff --git a/drivers/tty/serial/jsm/jsm_driver.c b/drivers/tty/serial/jsm/jsm_driver.c
+index 5b57c8eecfc9..a47d882d6743 100644
+--- a/drivers/tty/serial/jsm/jsm_driver.c
++++ b/drivers/tty/serial/jsm/jsm_driver.c
+@@ -178,7 +178,7 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	return rc;
+ }
+ 
+-static void __devexit jsm_remove_one(struct pci_dev *pdev)
++static void jsm_remove_one(struct pci_dev *pdev)
+ {
+ 	struct jsm_board *brd = pci_get_drvdata(pdev);
+ 	int i = 0;
+diff --git a/drivers/tty/serial/lpc32xx_hs.c b/drivers/tty/serial/lpc32xx_hs.c
+index 3651dab2009f..0e86bff3fe2a 100644
+--- a/drivers/tty/serial/lpc32xx_hs.c
++++ b/drivers/tty/serial/lpc32xx_hs.c
+@@ -740,7 +740,7 @@ static int serial_hs_lpc32xx_probe(struct platform_device *pdev)
+ /*
+  * Remove serial ports registered against a platform device.
+  */
+-static int __devexit serial_hs_lpc32xx_remove(struct platform_device *pdev)
++static int serial_hs_lpc32xx_remove(struct platform_device *pdev)
+ {
+ 	struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c
+index 8dd6189a40ee..7ce3197087bb 100644
+--- a/drivers/tty/serial/max3100.c
++++ b/drivers/tty/serial/max3100.c
+@@ -818,7 +818,7 @@ static int max3100_probe(struct spi_device *spi)
+ 	return 0;
+ }
+ 
+-static int __devexit max3100_remove(struct spi_device *spi)
++static int max3100_remove(struct spi_device *spi)
+ {
+ 	struct max3100_port *s = dev_get_drvdata(&spi->dev);
+ 	int i;
+diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
+index 88a227f9fe8c..3bb809d083aa 100644
+--- a/drivers/tty/serial/max310x.c
++++ b/drivers/tty/serial/max310x.c
+@@ -1202,7 +1202,7 @@ static int max310x_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit max310x_remove(struct spi_device *spi)
++static int max310x_remove(struct spi_device *spi)
+ {
+ 	struct device *dev = &spi->dev;
+ 	struct max310x_port *s = dev_get_drvdata(dev);
+diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c
+index e2b93d2f8f8c..fcd56ab6053f 100644
+--- a/drivers/tty/serial/mcf.c
++++ b/drivers/tty/serial/mcf.c
+@@ -599,7 +599,7 @@ static int mcf_probe(struct platform_device *pdev)
+ 
+ /****************************************************************************/
+ 
+-static int __devexit mcf_remove(struct platform_device *pdev)
++static int mcf_remove(struct platform_device *pdev)
+ {
+ 	struct uart_port *port;
+ 	int i;
+diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c
+index 41497fd3d360..58734d7e746d 100644
+--- a/drivers/tty/serial/mrst_max3110.c
++++ b/drivers/tty/serial/mrst_max3110.c
+@@ -855,7 +855,7 @@ static int serial_m3110_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit serial_m3110_remove(struct spi_device *dev)
++static int serial_m3110_remove(struct spi_device *dev)
+ {
+ 	struct uart_max3110 *max = spi_get_drvdata(dev);
+ 
+diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
+index 033e0bc9ebab..95fd39be2934 100644
+--- a/drivers/tty/serial/msm_serial.c
++++ b/drivers/tty/serial/msm_serial.c
+@@ -917,7 +917,7 @@ static int __init msm_serial_probe(struct platform_device *pdev)
+ 	return uart_add_one_port(&msm_uart_driver, port);
+ }
+ 
+-static int __devexit msm_serial_remove(struct platform_device *pdev)
++static int msm_serial_remove(struct platform_device *pdev)
+ {
+ 	struct msm_port *msm_port = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
+index 02fb63e944eb..1fa92284ade0 100644
+--- a/drivers/tty/serial/msm_serial_hs.c
++++ b/drivers/tty/serial/msm_serial_hs.c
+@@ -401,7 +401,7 @@ static int msm_hs_request_port(struct uart_port *port)
+ 	return 0;
+ }
+ 
+-static int __devexit msm_hs_remove(struct platform_device *pdev)
++static int msm_hs_remove(struct platform_device *pdev)
+ {
+ 
+ 	struct msm_hs_port *msm_uport;
+diff --git a/drivers/tty/serial/mux.c b/drivers/tty/serial/mux.c
+index 27834646d018..e2775b6df5a5 100644
+--- a/drivers/tty/serial/mux.c
++++ b/drivers/tty/serial/mux.c
+@@ -520,7 +520,7 @@ static int __init mux_probe(struct parisc_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devexit mux_remove(struct parisc_device *dev)
++static int mux_remove(struct parisc_device *dev)
+ {
+ 	int i, j;
+ 	int port_count = (long)dev_get_drvdata(&dev->dev);
+diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
+index 18b55c2d1d2e..3860ff27467c 100644
+--- a/drivers/tty/serial/mxs-auart.c
++++ b/drivers/tty/serial/mxs-auart.c
+@@ -1137,7 +1137,7 @@ static int mxs_auart_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit mxs_auart_remove(struct platform_device *pdev)
++static int mxs_auart_remove(struct platform_device *pdev)
+ {
+ 	struct mxs_auart_port *s = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
+index e777b16c4d17..b538e2e4ae5b 100644
+--- a/drivers/tty/serial/omap-serial.c
++++ b/drivers/tty/serial/omap-serial.c
+@@ -1441,7 +1441,7 @@ static int serial_omap_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit serial_omap_remove(struct platform_device *dev)
++static int serial_omap_remove(struct platform_device *dev)
+ {
+ 	struct uart_omap_port *up = platform_get_drvdata(dev);
+ 
+diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
+index 6568beb4d370..82b48f60aa0c 100644
+--- a/drivers/tty/serial/samsung.c
++++ b/drivers/tty/serial/samsung.c
+@@ -1256,7 +1256,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit s3c24xx_serial_remove(struct platform_device *dev)
++static int s3c24xx_serial_remove(struct platform_device *dev)
+ {
+ 	struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
+ 
+diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c
+index 1ddace83263f..418b495e3233 100644
+--- a/drivers/tty/serial/sccnxp.c
++++ b/drivers/tty/serial/sccnxp.c
+@@ -943,7 +943,7 @@ static int sccnxp_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit sccnxp_remove(struct platform_device *pdev)
++static int sccnxp_remove(struct platform_device *pdev)
+ {
+ 	int i;
+ 	struct sccnxp_port *s = platform_get_drvdata(pdev);
+diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c
+index 23b28b8f4670..b52b21aeb250 100644
+--- a/drivers/tty/serial/serial_txx9.c
++++ b/drivers/tty/serial/serial_txx9.c
+@@ -1078,7 +1078,7 @@ static int serial_txx9_register_port(struct uart_port *port)
+  *	Remove one serial port.  This may not be called from interrupt
+  *	context.  We hand the port back to the our control.
+  */
+-static void __devexit serial_txx9_unregister_port(int line)
++static void serial_txx9_unregister_port(int line)
+ {
+ 	struct uart_txx9_port *uart = &serial_txx9_ports[line];
+ 
+@@ -1126,7 +1126,7 @@ static int serial_txx9_probe(struct platform_device *dev)
+ /*
+  * Remove serial ports registered against a platform device.
+  */
+-static int __devexit serial_txx9_remove(struct platform_device *dev)
++static int serial_txx9_remove(struct platform_device *dev)
+ {
+ 	int i;
+ 
+@@ -1217,7 +1217,7 @@ pciserial_txx9_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
+ 	return 0;
+ }
+ 
+-static void __devexit pciserial_txx9_remove_one(struct pci_dev *dev)
++static void pciserial_txx9_remove_one(struct pci_dev *dev)
+ {
+ 	struct uart_txx9_port *up = pci_get_drvdata(dev);
+ 
+diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c
+index cb58867036a0..b9bf9c53f7fd 100644
+--- a/drivers/tty/serial/sunhv.c
++++ b/drivers/tty/serial/sunhv.c
+@@ -598,7 +598,7 @@ static int hv_probe(struct platform_device *op)
+ 	return err;
+ }
+ 
+-static int __devexit hv_remove(struct platform_device *dev)
++static int hv_remove(struct platform_device *dev)
+ {
+ 	struct uart_port *port = dev_get_drvdata(&dev->dev);
+ 
+diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c
+index 9a13c54d5f8a..bd8b3b634103 100644
+--- a/drivers/tty/serial/sunsab.c
++++ b/drivers/tty/serial/sunsab.c
+@@ -1063,7 +1063,7 @@ static int sab_probe(struct platform_device *op)
+ 	return err;
+ }
+ 
+-static int __devexit sab_remove(struct platform_device *op)
++static int sab_remove(struct platform_device *op)
+ {
+ 	struct uart_sunsab_port *up = dev_get_drvdata(&op->dev);
+ 
+diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
+index 049bbc5bc769..220da3f9724f 100644
+--- a/drivers/tty/serial/sunsu.c
++++ b/drivers/tty/serial/sunsu.c
+@@ -1503,7 +1503,7 @@ static int su_probe(struct platform_device *op)
+ 	return err;
+ }
+ 
+-static int __devexit su_remove(struct platform_device *op)
++static int su_remove(struct platform_device *op)
+ {
+ 	struct uart_sunsu_port *up = dev_get_drvdata(&op->dev);
+ 	bool kbdms = false;
+diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c
+index 02c058fbefe5..aef4fab957c3 100644
+--- a/drivers/tty/serial/sunzilog.c
++++ b/drivers/tty/serial/sunzilog.c
+@@ -1507,7 +1507,7 @@ static int zs_probe(struct platform_device *op)
+ 	return 0;
+ }
+ 
+-static void __devexit zs_remove_one(struct uart_sunzilog_port *up)
++static void zs_remove_one(struct uart_sunzilog_port *up)
+ {
+ 	if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up)) {
+ #ifdef CONFIG_SERIO
+@@ -1517,7 +1517,7 @@ static void __devexit zs_remove_one(struct uart_sunzilog_port *up)
+ 		uart_remove_one_port(&sunzilog_reg, &up->port);
+ }
+ 
+-static int __devexit zs_remove(struct platform_device *op)
++static int zs_remove(struct platform_device *op)
+ {
+ 	struct uart_sunzilog_port *up = dev_get_drvdata(&op->dev);
+ 	struct zilog_layout __iomem *regs;
+diff --git a/drivers/tty/serial/timbuart.c b/drivers/tty/serial/timbuart.c
+index c833f50980b6..5be0d68feceb 100644
+--- a/drivers/tty/serial/timbuart.c
++++ b/drivers/tty/serial/timbuart.c
+@@ -492,7 +492,7 @@ static int timbuart_probe(struct platform_device *dev)
+ 	return err;
+ }
+ 
+-static int __devexit timbuart_remove(struct platform_device *dev)
++static int timbuart_remove(struct platform_device *dev)
+ {
+ 	struct timbuart_port *uart = platform_get_drvdata(dev);
+ 
+diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
+index 2d20b012b442..89eee43c4e2d 100644
+--- a/drivers/tty/serial/uartlite.c
++++ b/drivers/tty/serial/uartlite.c
+@@ -542,7 +542,7 @@ static int ulite_assign(struct device *dev, int id, u32 base, int irq)
+  *
+  * @dev: pointer to device structure
+  */
+-static int __devexit ulite_release(struct device *dev)
++static int ulite_release(struct device *dev)
+ {
+ 	struct uart_port *port = dev_get_drvdata(dev);
+ 	int rc = 0;
+@@ -593,7 +593,7 @@ static int ulite_probe(struct platform_device *pdev)
+ 	return ulite_assign(&pdev->dev, id, res->start, res2->start);
+ }
+ 
+-static int __devexit ulite_remove(struct platform_device *pdev)
++static int ulite_remove(struct platform_device *pdev)
+ {
+ 	return ulite_release(&pdev->dev);
+ }
+diff --git a/drivers/tty/serial/vr41xx_siu.c b/drivers/tty/serial/vr41xx_siu.c
+index c046c995534a..62ee0166bc65 100644
+--- a/drivers/tty/serial/vr41xx_siu.c
++++ b/drivers/tty/serial/vr41xx_siu.c
+@@ -901,7 +901,7 @@ static int siu_probe(struct platform_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devexit siu_remove(struct platform_device *dev)
++static int siu_remove(struct platform_device *dev)
+ {
+ 	struct uart_port *port;
+ 	int i;
+diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c
+index 80530c7d0025..8fd181436a6b 100644
+--- a/drivers/tty/serial/vt8500_serial.c
++++ b/drivers/tty/serial/vt8500_serial.c
+@@ -634,7 +634,7 @@ static int vt8500_serial_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit vt8500_serial_remove(struct platform_device *pdev)
++static int vt8500_serial_remove(struct platform_device *pdev)
+ {
+ 	struct vt8500_port *vt8500_port = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
+index 61fa71433a0e..9ab910370c56 100644
+--- a/drivers/tty/serial/xilinx_uartps.c
++++ b/drivers/tty/serial/xilinx_uartps.c
+@@ -997,7 +997,7 @@ static int xuartps_probe(struct platform_device *pdev)
+  *
+  * Returns 0 on success, negative error otherwise
+  **/
+-static int __devexit xuartps_remove(struct platform_device *pdev)
++static int xuartps_remove(struct platform_device *pdev)
+ {
+ 	struct uart_port *port = dev_get_drvdata(&pdev->dev);
+ 	int rc = 0;
+diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c
+index 4798dd5c55dd..9e071f6985f6 100644
+--- a/drivers/tty/synclink.c
++++ b/drivers/tty/synclink.c
+@@ -8117,7 +8117,7 @@ static int synclink_init_one (struct pci_dev *dev,
+ 	return 0;
+ }
+ 
+-static void __devexit synclink_remove_one (struct pci_dev *dev)
++static void synclink_remove_one (struct pci_dev *dev)
+ {
+ }
+ 
+diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c
+index a84c4089f56a..aba1e59f4a88 100644
+--- a/drivers/tty/synclink_gt.c
++++ b/drivers/tty/synclink_gt.c
+@@ -3710,7 +3710,7 @@ static int init_one(struct pci_dev *dev,
+ 	return 0;
+ }
+ 
+-static void __devexit remove_one(struct pci_dev *dev)
++static void remove_one(struct pci_dev *dev)
+ {
+ }
+ 
+diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c
+index d301110b4d1a..fd43fb6f7cee 100644
+--- a/drivers/tty/synclinkmp.c
++++ b/drivers/tty/synclinkmp.c
+@@ -5606,6 +5606,6 @@ static int synclinkmp_init_one (struct pci_dev *dev,
+ 	return 0;
+ }
+ 
+-static void __devexit synclinkmp_remove_one (struct pci_dev *dev)
++static void synclinkmp_remove_one (struct pci_dev *dev)
+ {
+ }

commit 512f82a064e397e437845c3f03a3c6dc3e610e8b
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:25:19 2012 -0500
+
+    tty: remove use of __devinitconst
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitconst is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Alan Cox 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c
+index 61de2a465473..2445aa4d2fa4 100644
+--- a/drivers/tty/nozomi.c
++++ b/drivers/tty/nozomi.c
+@@ -400,7 +400,7 @@ struct buffer {
+ } __attribute__ ((packed));
+ 
+ /*    Global variables */
+-static const struct pci_device_id nozomi_pci_tbl[] __devinitconst = {
++static const struct pci_device_id nozomi_pci_tbl[] = {
+ 	{PCI_DEVICE(0x1931, 0x000c)},	/* Nozomi HSDPA */
+ 	{},
+ };
+diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c
+index f59bff5907c1..430bf42374c0 100644
+--- a/drivers/tty/serial/8250/8250_em.c
++++ b/drivers/tty/serial/8250/8250_em.c
+@@ -163,7 +163,7 @@ static int __devexit serial8250_em_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static const struct of_device_id serial8250_em_dt_ids[] __devinitconst = {
++static const struct of_device_id serial8250_em_dt_ids[] = {
+ 	{ .compatible = "renesas,em-uart", },
+ 	{},
+ };
+diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c
+index 8a74d59270eb..2c01344dc332 100644
+--- a/drivers/tty/serial/mfd.c
++++ b/drivers/tty/serial/mfd.c
+@@ -1459,7 +1459,7 @@ static void serial_hsu_remove(struct pci_dev *pdev)
+ }
+ 
+ /* First 3 are UART ports, and the 4th is the DMA */
+-static const struct pci_device_id pci_ids[] __devinitconst = {
++static const struct pci_device_id pci_ids[] = {
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081B) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081C) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081D) },

commit de88b34042752c03771b779d1d985060909ab44a
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:24:32 2012 -0500
+
+    tty: remove use of __devinitdata
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitdata is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Alan Cox 
+    Cc: Peter Korsgaard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/tty/hvc/hvc_opal.c b/drivers/tty/hvc/hvc_opal.c
+index 79f2b5e17f8d..61da5cd093fc 100644
+--- a/drivers/tty/hvc/hvc_opal.c
++++ b/drivers/tty/hvc/hvc_opal.c
+@@ -41,7 +41,7 @@
+ 
+ static const char hvc_opal_name[] = "hvc_opal";
+ 
+-static struct of_device_id hvc_opal_match[] __devinitdata = {
++static struct of_device_id hvc_opal_match[] = {
+ 	{ .name = "serial", .compatible = "ibm,opal-console-raw" },
+ 	{ .name = "serial", .compatible = "ibm,opal-console-hvsi" },
+ 	{ },
+diff --git a/drivers/tty/hvc/hvc_vio.c b/drivers/tty/hvc/hvc_vio.c
+index 77bde6c2cfa0..282d143a6437 100644
+--- a/drivers/tty/hvc/hvc_vio.c
++++ b/drivers/tty/hvc/hvc_vio.c
+@@ -53,7 +53,7 @@
+ 
+ static const char hvc_driver_name[] = "hvc_console";
+ 
+-static struct vio_device_id hvc_driver_table[] __devinitdata = {
++static struct vio_device_id hvc_driver_table[] = {
+ 	{"serial", "hvterm1"},
+ #ifndef HVC_OLD_HVSI
+ 	{"serial", "hvterm-protocol"},
+diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c
+index d9056dac4ea1..e42009a00529 100644
+--- a/drivers/tty/rocket.c
++++ b/drivers/tty/rocket.c
+@@ -1758,7 +1758,7 @@ static void rp_flush_buffer(struct tty_struct *tty)
+ 
+ #ifdef CONFIG_PCI
+ 
+-static struct pci_device_id __devinitdata __used rocket_pci_ids[] = {
++static struct pci_device_id __used rocket_pci_ids[] = {
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_ANY_ID) },
+ 	{ }
+ };
+diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
+index a5acb57b5ba0..3252c5d47ff8 100644
+--- a/drivers/tty/serial/8250/8250_pci.c
++++ b/drivers/tty/serial/8250/8250_pci.c
+@@ -1987,7 +1987,7 @@ enum pci_board_num_t {
+  * see first lines of serial_in() and serial_out() in 8250.c
+ */
+ 
+-static struct pciserial_board pci_boards[] __devinitdata = {
++static struct pciserial_board pci_boards[] = {
+ 	[pbn_default] = {
+ 		.flags		= FL_BASE0,
+ 		.num_ports	= 1,
+diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c
+index 2b8a6ac173f6..71daae90fb5e 100644
+--- a/drivers/tty/serial/8250/8250_pnp.c
++++ b/drivers/tty/serial/8250/8250_pnp.c
+@@ -370,7 +370,7 @@ static const struct pnp_device_id pnp_dev_table[] = {
+ 
+ MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
+ 
+-static char *modem_names[] __devinitdata = {
++static char *modem_names[] = {
+ 	"MODEM", "Modem", "modem", "FAX", "Fax", "fax",
+ 	"56K", "56k", "K56", "33.6", "28.8", "14.4",
+ 	"33,600", "28,800", "14,400", "33.600", "28.800", "14.400",
+diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
+index 1bce344ca794..e7cae1c2d7d2 100644
+--- a/drivers/tty/serial/of_serial.c
++++ b/drivers/tty/serial/of_serial.c
+@@ -231,7 +231,7 @@ static int of_platform_serial_remove(struct platform_device *ofdev)
+ /*
+  * A few common types, add more as needed.
+  */
+-static struct of_device_id __devinitdata of_platform_serial_table[] = {
++static struct of_device_id of_platform_serial_table[] = {
+ 	{ .compatible = "ns8250",   .data = (void *)PORT_8250, },
+ 	{ .compatible = "ns16450",  .data = (void *)PORT_16450, },
+ 	{ .compatible = "ns16550a", .data = (void *)PORT_16550A, },
+diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c
+index 49849843ff82..5da5cb962769 100644
+--- a/drivers/tty/serial/sirfsoc_uart.c
++++ b/drivers/tty/serial/sirfsoc_uart.c
+@@ -727,7 +727,7 @@ static int sirfsoc_uart_resume(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static struct of_device_id sirfsoc_uart_ids[] __devinitdata = {
++static struct of_device_id sirfsoc_uart_ids[] = {
+ 	{ .compatible = "sirf,prima2-uart", },
+ 	{}
+ };
+diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
+index df9eeb451ae9..2d20b012b442 100644
+--- a/drivers/tty/serial/uartlite.c
++++ b/drivers/tty/serial/uartlite.c
+@@ -562,7 +562,7 @@ static int __devexit ulite_release(struct device *dev)
+ 
+ #if defined(CONFIG_OF)
+ /* Match table for of_platform binding */
+-static struct of_device_id ulite_of_match[] __devinitdata = {
++static struct of_device_id ulite_of_match[] = {
+ 	{ .compatible = "xlnx,opb-uartlite-1.00.b", },
+ 	{ .compatible = "xlnx,xps-uartlite-1.00.a", },
+ 	{}
+diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
+index a1cd2df51c9e..61fa71433a0e 100644
+--- a/drivers/tty/serial/xilinx_uartps.c
++++ b/drivers/tty/serial/xilinx_uartps.c
+@@ -1040,7 +1040,7 @@ static int xuartps_resume(struct platform_device *pdev)
+ }
+ 
+ /* Match table for of_platform binding */
+-static struct of_device_id xuartps_of_match[] __devinitdata = {
++static struct of_device_id xuartps_of_match[] = {
+ 	{ .compatible = "xlnx,xuartps", },
+ 	{}
+ };

commit 6b1cb9305094052d282e039b11a6e667ac48559e
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:24:04 2012 -0500
+
+    tty: remove use of __devinitdata
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitdata is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c
+index 506a28e5564f..5afe3b6041cf 100644
+--- a/drivers/tty/hvc/hvcs.c
++++ b/drivers/tty/hvc/hvcs.c
+@@ -676,7 +676,7 @@ static int khvcsd(void *unused)
+ 	return 0;
+ }
+ 
+-static struct vio_device_id hvcs_driver_table[] __devinitdata= {
++static struct vio_device_id hvcs_driver_table[] = {
+ 	{"serial-server", "hvterm2"},
+ 	{ "", "" }
+ };

commit 9671f09921d93e722a28ae9610d478e092ac5466
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:50 2012 -0500
+
+    tty: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Jiri Slaby 
+    Cc: Alan Cox 
+    Cc: Lucas Tavares 
+    Cc: "David S. Miller" 
+    Cc: Peter Korsgaard 
+    Cc: Tony Prisk 
+    Acked-by: Tobias Klauser 
+    Acked-by: Nicolas Ferre 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c
+index 2f4d84f3c159..2dff87cdce23 100644
+--- a/drivers/tty/cyclades.c
++++ b/drivers/tty/cyclades.c
+@@ -3099,7 +3099,7 @@ static const struct tty_port_operations cyz_port_ops = {
+  * ---------------------------------------------------------------------
+  */
+ 
+-static int __devinit cy_init_card(struct cyclades_card *cinfo)
++static int cy_init_card(struct cyclades_card *cinfo)
+ {
+ 	struct cyclades_port *info;
+ 	unsigned int channel, port;
+@@ -3196,7 +3196,7 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo)
+ 
+ /* initialize chips on Cyclom-Y card -- return number of valid
+    chips (which is number of ports/4) */
+-static unsigned short __devinit cyy_init_card(void __iomem *true_base_addr,
++static unsigned short cyy_init_card(void __iomem *true_base_addr,
+ 		int index)
+ {
+ 	unsigned int chip_number;
+@@ -3405,7 +3405,7 @@ static int __init cy_detect_isa(void)
+ }				/* cy_detect_isa */
+ 
+ #ifdef CONFIG_PCI
+-static inline int __devinit cyc_isfwstr(const char *str, unsigned int size)
++static inline int cyc_isfwstr(const char *str, unsigned int size)
+ {
+ 	unsigned int a;
+ 
+@@ -3420,7 +3420,7 @@ static inline int __devinit cyc_isfwstr(const char *str, unsigned int size)
+ 	return 0;
+ }
+ 
+-static inline void __devinit cyz_fpga_copy(void __iomem *fpga, const u8 *data,
++static inline void cyz_fpga_copy(void __iomem *fpga, const u8 *data,
+ 		unsigned int size)
+ {
+ 	for (; size > 0; size--) {
+@@ -3429,7 +3429,7 @@ static inline void __devinit cyz_fpga_copy(void __iomem *fpga, const u8 *data,
+ 	}
+ }
+ 
+-static void __devinit plx_init(struct pci_dev *pdev, int irq,
++static void plx_init(struct pci_dev *pdev, int irq,
+ 		struct RUNTIME_9060 __iomem *addr)
+ {
+ 	/* Reset PLX */
+@@ -3449,7 +3449,7 @@ static void __devinit plx_init(struct pci_dev *pdev, int irq,
+ 	pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
+ }
+ 
+-static int __devinit __cyz_load_fw(const struct firmware *fw,
++static int __cyz_load_fw(const struct firmware *fw,
+ 		const char *name, const u32 mailbox, void __iomem *base,
+ 		void __iomem *fpga)
+ {
+@@ -3526,7 +3526,7 @@ static int __devinit __cyz_load_fw(const struct firmware *fw,
+ 	return 0;
+ }
+ 
+-static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
++static int cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
+ 		struct RUNTIME_9060 __iomem *ctl_addr, int irq)
+ {
+ 	const struct firmware *fw;
+@@ -3692,7 +3692,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
+ 	return retval;
+ }
+ 
+-static int __devinit cy_pci_probe(struct pci_dev *pdev,
++static int cy_pci_probe(struct pci_dev *pdev,
+ 		const struct pci_device_id *ent)
+ {
+ 	struct cyclades_card *card;
+diff --git a/drivers/tty/ehv_bytechan.c b/drivers/tty/ehv_bytechan.c
+index 4193afb74a02..c117d775a22f 100644
+--- a/drivers/tty/ehv_bytechan.c
++++ b/drivers/tty/ehv_bytechan.c
+@@ -699,7 +699,7 @@ static const struct tty_port_operations ehv_bc_tty_port_ops = {
+ 	.shutdown = ehv_bc_tty_port_shutdown,
+ };
+ 
+-static int __devinit ehv_bc_tty_probe(struct platform_device *pdev)
++static int ehv_bc_tty_probe(struct platform_device *pdev)
+ {
+ 	struct device_node *np = pdev->dev.of_node;
+ 	struct ehv_bc_data *bc;
+diff --git a/drivers/tty/hvc/hvc_opal.c b/drivers/tty/hvc/hvc_opal.c
+index 442bfb0d41da..79f2b5e17f8d 100644
+--- a/drivers/tty/hvc/hvc_opal.c
++++ b/drivers/tty/hvc/hvc_opal.c
+@@ -161,7 +161,7 @@ static const struct hv_ops hvc_opal_hvsi_ops = {
+ 	.tiocmset = hvc_opal_hvsi_tiocmset,
+ };
+ 
+-static int __devinit hvc_opal_probe(struct platform_device *dev)
++static int hvc_opal_probe(struct platform_device *dev)
+ {
+ 	const struct hv_ops *ops;
+ 	struct hvc_struct *hp;
+diff --git a/drivers/tty/hvc/hvc_vio.c b/drivers/tty/hvc/hvc_vio.c
+index 070c0ee68642..77bde6c2cfa0 100644
+--- a/drivers/tty/hvc/hvc_vio.c
++++ b/drivers/tty/hvc/hvc_vio.c
+@@ -293,7 +293,7 @@ static int udbg_hvc_getc(void)
+ 	}
+ }
+ 
+-static int __devinit hvc_vio_probe(struct vio_dev *vdev,
++static int hvc_vio_probe(struct vio_dev *vdev,
+ 				   const struct vio_device_id *id)
+ {
+ 	const struct hv_ops *ops;
+diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c
+index f4abfe238f98..19843ec3f80a 100644
+--- a/drivers/tty/hvc/hvc_xen.c
++++ b/drivers/tty/hvc/hvc_xen.c
+@@ -422,7 +422,7 @@ static int xencons_connect_backend(struct xenbus_device *dev,
+ 	return ret;
+ }
+ 
+-static int __devinit xencons_probe(struct xenbus_device *dev,
++static int xencons_probe(struct xenbus_device *dev,
+ 				  const struct xenbus_device_id *id)
+ {
+ 	int ret, devid;
+diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c
+index 888af583fe75..506a28e5564f 100644
+--- a/drivers/tty/hvc/hvcs.c
++++ b/drivers/tty/hvc/hvcs.c
+@@ -330,12 +330,12 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp);
+ static void hvcs_close(struct tty_struct *tty, struct file *filp);
+ static void hvcs_hangup(struct tty_struct * tty);
+ 
+-static int __devinit hvcs_probe(struct vio_dev *dev,
++static int hvcs_probe(struct vio_dev *dev,
+ 		const struct vio_device_id *id);
+ static int __devexit hvcs_remove(struct vio_dev *dev);
+ static int __init hvcs_module_init(void);
+ static void __exit hvcs_module_exit(void);
+-static int __devinit hvcs_initialize(void);
++static int hvcs_initialize(void);
+ 
+ #define HVCS_SCHED_READ	0x00000001
+ #define HVCS_QUICK_READ	0x00000002
+@@ -756,7 +756,7 @@ static int hvcs_get_index(void)
+ 	return -1;
+ }
+ 
+-static int __devinit hvcs_probe(
++static int hvcs_probe(
+ 	struct vio_dev *dev,
+ 	const struct vio_device_id *id)
+ {
+@@ -1478,7 +1478,7 @@ static void hvcs_free_index_list(void)
+ 	hvcs_index_count = 0;
+ }
+ 
+-static int __devinit hvcs_initialize(void)
++static int hvcs_initialize(void)
+ {
+ 	int rc, num_ttys_to_alloc;
+ 
+diff --git a/drivers/tty/isicom.c b/drivers/tty/isicom.c
+index 774e595e1fba..82661889b322 100644
+--- a/drivers/tty/isicom.c
++++ b/drivers/tty/isicom.c
+@@ -1307,7 +1307,7 @@ static const struct tty_port_operations isicom_port_ops = {
+ 	.shutdown		= isicom_shutdown,
+ };
+ 
+-static int __devinit reset_card(struct pci_dev *pdev,
++static int reset_card(struct pci_dev *pdev,
+ 	const unsigned int card, unsigned int *signature)
+ {
+ 	struct isi_board *board = pci_get_drvdata(pdev);
+@@ -1368,7 +1368,7 @@ static int __devinit reset_card(struct pci_dev *pdev,
+ 	return retval;
+ }
+ 
+-static int __devinit load_firmware(struct pci_dev *pdev,
++static int load_firmware(struct pci_dev *pdev,
+ 	const unsigned int index, const unsigned int signature)
+ {
+ 	struct isi_board *board = pci_get_drvdata(pdev);
+@@ -1548,7 +1548,7 @@ static int __devinit load_firmware(struct pci_dev *pdev,
+  */
+ static unsigned int card_count;
+ 
+-static int __devinit isicom_probe(struct pci_dev *pdev,
++static int isicom_probe(struct pci_dev *pdev,
+ 	const struct pci_device_id *ent)
+ {
+ 	unsigned int uninitialized_var(signature), index;
+diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c
+index e025e065ae9c..60ea74e76d3a 100644
+--- a/drivers/tty/moxa.c
++++ b/drivers/tty/moxa.c
+@@ -945,7 +945,7 @@ static void moxa_board_deinit(struct moxa_board_conf *brd)
+ }
+ 
+ #ifdef CONFIG_PCI
+-static int __devinit moxa_pci_probe(struct pci_dev *pdev,
++static int moxa_pci_probe(struct pci_dev *pdev,
+ 		const struct pci_device_id *ent)
+ {
+ 	struct moxa_board_conf *board;
+diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c
+index a2fd58c336e4..7f5e0ccf96ea 100644
+--- a/drivers/tty/mxser.c
++++ b/drivers/tty/mxser.c
+@@ -487,7 +487,7 @@ static void mxser_disable_must_rx_software_flow_control(unsigned long baseio)
+ }
+ 
+ #ifdef CONFIG_PCI
+-static int __devinit CheckIsMoxaMust(unsigned long io)
++static int CheckIsMoxaMust(unsigned long io)
+ {
+ 	u8 oldmcr, hwid;
+ 	int i;
+@@ -2369,7 +2369,7 @@ static void mxser_release_ISA_res(struct mxser_board *brd)
+ 	mxser_release_vector(brd);
+ }
+ 
+-static int __devinit mxser_initbrd(struct mxser_board *brd,
++static int mxser_initbrd(struct mxser_board *brd,
+ 		struct pci_dev *pdev)
+ {
+ 	struct mxser_port *info;
+@@ -2547,7 +2547,7 @@ static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd)
+ 	return -EIO;
+ }
+ 
+-static int __devinit mxser_probe(struct pci_dev *pdev,
++static int mxser_probe(struct pci_dev *pdev,
+ 		const struct pci_device_id *ent)
+ {
+ #ifdef CONFIG_PCI
+diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c
+index 442efc3d2657..61de2a465473 100644
+--- a/drivers/tty/nozomi.c
++++ b/drivers/tty/nozomi.c
+@@ -1360,7 +1360,7 @@ static void remove_sysfs_files(struct nozomi *dc)
+ }
+ 
+ /* Allocate memory for one device */
+-static int __devinit nozomi_card_init(struct pci_dev *pdev,
++static int nozomi_card_init(struct pci_dev *pdev,
+ 				      const struct pci_device_id *ent)
+ {
+ 	resource_size_t start;
+diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
+index 870c5f2d0c8f..40ba8cc0985d 100644
+--- a/drivers/tty/serial/8250/8250.c
++++ b/drivers/tty/serial/8250/8250.c
+@@ -2989,7 +2989,7 @@ void serial8250_resume_port(int line)
+  * list is terminated with a zero flags entry, which means we expect
+  * all entries to have at least UPF_BOOT_AUTOCONF set.
+  */
+-static int __devinit serial8250_probe(struct platform_device *dev)
++static int serial8250_probe(struct platform_device *dev)
+ {
+ 	struct plat_serial8250_port *p = dev->dev.platform_data;
+ 	struct uart_8250_port uart;
+diff --git a/drivers/tty/serial/8250/8250_acorn.c b/drivers/tty/serial/8250/8250_acorn.c
+index b5e4b494cb07..ed095eb2e3f2 100644
+--- a/drivers/tty/serial/8250/8250_acorn.c
++++ b/drivers/tty/serial/8250/8250_acorn.c
+@@ -38,7 +38,7 @@ struct serial_card_info {
+ 	void __iomem *vaddr;
+ };
+ 
+-static int __devinit
++static int
+ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
+ {
+ 	struct serial_card_info *info;
+diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
+index 2db80d03b0ba..7664750c2bd6 100644
+--- a/drivers/tty/serial/8250/8250_dw.c
++++ b/drivers/tty/serial/8250/8250_dw.c
+@@ -87,7 +87,7 @@ static int dw8250_handle_irq(struct uart_port *p)
+ 	return 0;
+ }
+ 
+-static int __devinit dw8250_probe(struct platform_device *pdev)
++static int dw8250_probe(struct platform_device *pdev)
+ {
+ 	struct uart_8250_port uart = {};
+ 	struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c
+index 80c0a626c13e..f59bff5907c1 100644
+--- a/drivers/tty/serial/8250/8250_em.c
++++ b/drivers/tty/serial/8250/8250_em.c
+@@ -89,7 +89,7 @@ static void serial8250_em_serial_dl_write(struct uart_8250_port *up, int value)
+ 	serial_out(up, UART_DLM_EM, value >> 8 & 0xff);
+ }
+ 
+-static int __devinit serial8250_em_probe(struct platform_device *pdev)
++static int serial8250_em_probe(struct platform_device *pdev)
+ {
+ 	struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ 	struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+diff --git a/drivers/tty/serial/8250/8250_hp300.c b/drivers/tty/serial/8250/8250_hp300.c
+index 89e88559f489..2b945052ee08 100644
+--- a/drivers/tty/serial/8250/8250_hp300.c
++++ b/drivers/tty/serial/8250/8250_hp300.c
+@@ -36,7 +36,7 @@ static struct hp300_port *hp300_ports;
+ 
+ #ifdef CONFIG_HPDCA
+ 
+-static int __devinit hpdca_init_one(struct dio_dev *d,
++static int hpdca_init_one(struct dio_dev *d,
+ 					const struct dio_device_id *ent);
+ static void __devexit hpdca_remove_one(struct dio_dev *d);
+ 
+@@ -159,7 +159,7 @@ int __init hp300_setup_serial_console(void)
+ #endif /* CONFIG_SERIAL_8250_CONSOLE */
+ 
+ #ifdef CONFIG_HPDCA
+-static int __devinit hpdca_init_one(struct dio_dev *d,
++static int hpdca_init_one(struct dio_dev *d,
+ 				const struct dio_device_id *ent)
+ {
+ 	struct uart_8250_port uart;
+diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
+index c049cfa06f55..a5acb57b5ba0 100644
+--- a/drivers/tty/serial/8250/8250_pci.c
++++ b/drivers/tty/serial/8250/8250_pci.c
+@@ -2691,7 +2691,7 @@ static const struct pci_device_id blacklist[] = {
+  * guess what the configuration might be, based on the pitiful PCI
+  * serial specs.  Returns 0 on success, 1 on failure.
+  */
+-static int __devinit
++static int
+ serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
+ {
+ 	const struct pci_device_id *bldev;
+@@ -2917,7 +2917,7 @@ EXPORT_SYMBOL_GPL(pciserial_resume_ports);
+  * Probe one serial board.  Unfortunately, there is no rhyme nor reason
+  * to the arrangement of serial ports on a PCI card.
+  */
+-static int __devinit
++static int
+ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
+ {
+ 	struct pci_serial_quirk *quirk;
+diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c
+index e566220f187d..2b8a6ac173f6 100644
+--- a/drivers/tty/serial/8250/8250_pnp.c
++++ b/drivers/tty/serial/8250/8250_pnp.c
+@@ -377,7 +377,7 @@ static char *modem_names[] __devinitdata = {
+ 	"33600", "28800", "14400", "V.90", "V.34", "V.32", NULL
+ };
+ 
+-static int __devinit check_name(char *name)
++static int check_name(char *name)
+ {
+ 	char **tmp;
+ 
+@@ -388,7 +388,7 @@ static int __devinit check_name(char *name)
+ 	return 0;
+ }
+ 
+-static int __devinit check_resources(struct pnp_dev *dev)
++static int check_resources(struct pnp_dev *dev)
+ {
+ 	resource_size_t base[] = {0x2f8, 0x3f8, 0x2e8, 0x3e8};
+ 	int i;
+@@ -412,7 +412,7 @@ static int __devinit check_resources(struct pnp_dev *dev)
+  * PnP modems, alternatively we must hardcode all modems in pnp_devices[]
+  * table.
+  */
+-static int __devinit serial_pnp_guess_board(struct pnp_dev *dev)
++static int serial_pnp_guess_board(struct pnp_dev *dev)
+ {
+ 	if (!(check_name(pnp_dev_name(dev)) ||
+ 		(dev->card && check_name(dev->card->name))))
+@@ -424,7 +424,7 @@ static int __devinit serial_pnp_guess_board(struct pnp_dev *dev)
+ 	return -ENODEV;
+ }
+ 
+-static int __devinit
++static int
+ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
+ {
+ 	struct uart_8250_port uart;
+diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c
+index ef16b0aa383a..ef5c705fa2b3 100644
+--- a/drivers/tty/serial/altera_jtaguart.c
++++ b/drivers/tty/serial/altera_jtaguart.c
+@@ -406,7 +406,7 @@ static struct uart_driver altera_jtaguart_driver = {
+ 	.cons		= ALTERA_JTAGUART_CONSOLE,
+ };
+ 
+-static int __devinit altera_jtaguart_probe(struct platform_device *pdev)
++static int altera_jtaguart_probe(struct platform_device *pdev)
+ {
+ 	struct altera_jtaguart_platform_uart *platp = pdev->dev.platform_data;
+ 	struct uart_port *port;
+diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c
+index 117ea2c89630..066b5035e10a 100644
+--- a/drivers/tty/serial/altera_uart.c
++++ b/drivers/tty/serial/altera_uart.c
+@@ -532,7 +532,7 @@ static int altera_uart_get_of_uartclk(struct platform_device *pdev,
+ }
+ #endif /* CONFIG_OF */
+ 
+-static int __devinit altera_uart_probe(struct platform_device *pdev)
++static int altera_uart_probe(struct platform_device *pdev)
+ {
+ 	struct altera_uart_platform_uart *platp = pdev->dev.platform_data;
+ 	struct uart_port *port;
+diff --git a/drivers/tty/serial/apbuart.c b/drivers/tty/serial/apbuart.c
+index 7162f70d9260..59ae2b53e765 100644
+--- a/drivers/tty/serial/apbuart.c
++++ b/drivers/tty/serial/apbuart.c
+@@ -554,7 +554,7 @@ static struct uart_driver grlib_apbuart_driver = {
+ /* OF Platform Driver                                                       */
+ /* ======================================================================== */
+ 
+-static int __devinit apbuart_probe(struct platform_device *op)
++static int apbuart_probe(struct platform_device *op)
+ {
+ 	int i;
+ 	struct uart_port *port = NULL;
+diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c
+index 77115448af5f..ad171508b9a9 100644
+--- a/drivers/tty/serial/ar933x_uart.c
++++ b/drivers/tty/serial/ar933x_uart.c
+@@ -627,7 +627,7 @@ static struct uart_driver ar933x_uart_driver = {
+ 	.cons		= AR933X_SERIAL_CONSOLE,
+ };
+ 
+-static int __devinit ar933x_uart_probe(struct platform_device *pdev)
++static int ar933x_uart_probe(struct platform_device *pdev)
+ {
+ 	struct ar933x_uart_platform_data *pdata;
+ 	struct ar933x_uart_port *up;
+diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
+index d6525698db31..158d798a5203 100644
+--- a/drivers/tty/serial/arc_uart.c
++++ b/drivers/tty/serial/arc_uart.c
+@@ -525,7 +525,7 @@ static struct uart_ops arc_serial_pops = {
+ #endif
+ };
+ 
+-static int __devinit
++static int
+ arc_uart_init_one(struct platform_device *pdev, struct arc_uart_port *uart)
+ {
+ 	struct resource *res, *res2;
+@@ -577,7 +577,7 @@ arc_uart_init_one(struct platform_device *pdev, struct arc_uart_port *uart)
+ 
+ #ifdef CONFIG_SERIAL_ARC_CONSOLE
+ 
+-static int __devinit arc_serial_console_setup(struct console *co, char *options)
++static int arc_serial_console_setup(struct console *co, char *options)
+ {
+ 	struct uart_port *port;
+ 	int baud = 115200;
+@@ -655,7 +655,7 @@ static struct __initdata console arc_early_serial_console = {
+ 	.index = -1
+ };
+ 
+-static int __devinit arc_serial_probe_earlyprintk(struct platform_device *pdev)
++static int arc_serial_probe_earlyprintk(struct platform_device *pdev)
+ {
+ 	arc_early_serial_console.index = pdev->id;
+ 
+@@ -667,13 +667,13 @@ static int __devinit arc_serial_probe_earlyprintk(struct platform_device *pdev)
+ 	return 0;
+ }
+ #else
+-static int __devinit arc_serial_probe_earlyprintk(struct platform_device *pdev)
++static int arc_serial_probe_earlyprintk(struct platform_device *pdev)
+ {
+ 	return -ENODEV;
+ }
+ #endif	/* CONFIG_SERIAL_ARC_CONSOLE */
+ 
+-static int __devinit arc_serial_probe(struct platform_device *pdev)
++static int arc_serial_probe(struct platform_device *pdev)
+ {
+ 	struct arc_uart_port *uart;
+ 	int rc;
+diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
+index 27eae4b2355a..02540cbf16a6 100644
+--- a/drivers/tty/serial/atmel_serial.c
++++ b/drivers/tty/serial/atmel_serial.c
+@@ -1423,7 +1423,7 @@ static struct uart_ops atmel_pops = {
+ #endif
+ };
+ 
+-static void __devinit atmel_of_init_port(struct atmel_uart_port *atmel_port,
++static void atmel_of_init_port(struct atmel_uart_port *atmel_port,
+ 					 struct device_node *np)
+ {
+ 	u32 rs485_delay[2];
+@@ -1458,7 +1458,7 @@ static void __devinit atmel_of_init_port(struct atmel_uart_port *atmel_port,
+ /*
+  * Configure the port from the platform device resource info.
+  */
+-static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port,
++static void atmel_init_port(struct atmel_uart_port *atmel_port,
+ 				      struct platform_device *pdev)
+ {
+ 	struct uart_port *port = &atmel_port->uart;
+@@ -1766,7 +1766,7 @@ static int atmel_serial_resume(struct platform_device *pdev)
+ #define atmel_serial_resume NULL
+ #endif
+ 
+-static int __devinit atmel_serial_probe(struct platform_device *pdev)
++static int atmel_serial_probe(struct platform_device *pdev)
+ {
+ 	struct atmel_uart_port *port;
+ 	struct device_node *np = pdev->dev.of_node;
+diff --git a/drivers/tty/serial/bcm63xx_uart.c b/drivers/tty/serial/bcm63xx_uart.c
+index 7f631d4a5c44..e54d1703be1e 100644
+--- a/drivers/tty/serial/bcm63xx_uart.c
++++ b/drivers/tty/serial/bcm63xx_uart.c
+@@ -801,7 +801,7 @@ static struct uart_driver bcm_uart_driver = {
+ /*
+  * platform driver probe/remove callback
+  */
+-static int __devinit bcm_uart_probe(struct platform_device *pdev)
++static int bcm_uart_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res_mem, *res_irq;
+ 	struct uart_port *port;
+diff --git a/drivers/tty/serial/bfin_sport_uart.c b/drivers/tty/serial/bfin_sport_uart.c
+index b4a18c7ffdf7..a47e00b056e7 100644
+--- a/drivers/tty/serial/bfin_sport_uart.c
++++ b/drivers/tty/serial/bfin_sport_uart.c
+@@ -740,7 +740,7 @@ static struct dev_pm_ops bfin_sport_uart_dev_pm_ops = {
+ };
+ #endif
+ 
+-static int __devinit sport_uart_probe(struct platform_device *pdev)
++static int sport_uart_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res;
+ 	struct sport_uart_port *sport;
+diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c
+index d631ef52f4f8..006d283bbded 100644
+--- a/drivers/tty/serial/clps711x.c
++++ b/drivers/tty/serial/clps711x.c
+@@ -429,7 +429,7 @@ static int uart_clps711x_console_setup(struct console *co, char *options)
+ }
+ #endif
+ 
+-static int __devinit uart_clps711x_probe(struct platform_device *pdev)
++static int uart_clps711x_probe(struct platform_device *pdev)
+ {
+ 	struct clps711x_port *s;
+ 	int ret, i;
+diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
+index d0dd9194cecc..de3f0f6eba74 100644
+--- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c
++++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
+@@ -1373,7 +1373,7 @@ static struct uart_driver cpm_reg = {
+ 
+ static int probe_index;
+ 
+-static int __devinit cpm_uart_probe(struct platform_device *ofdev)
++static int cpm_uart_probe(struct platform_device *ofdev)
+ {
+ 	int index = probe_index++;
+ 	struct uart_cpm_port *pinfo = &cpm_uart_ports[index];
+diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c
+index 1e8bacf95b70..833c33a2751a 100644
+--- a/drivers/tty/serial/efm32-uart.c
++++ b/drivers/tty/serial/efm32-uart.c
+@@ -690,7 +690,7 @@ static int efm32_uart_probe_dt(struct platform_device *pdev,
+ 
+ }
+ 
+-static int __devinit efm32_uart_probe(struct platform_device *pdev)
++static int efm32_uart_probe(struct platform_device *pdev)
+ {
+ 	struct efm32_uart_port *efm_port;
+ 	struct resource *res;
+diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c
+index f0fc2fff1701..a8267956ac88 100644
+--- a/drivers/tty/serial/icom.c
++++ b/drivers/tty/serial/icom.c
+@@ -175,7 +175,7 @@ static void free_port_memory(struct icom_port *icom_port)
+ 	}
+ }
+ 
+-static int __devinit get_port_memory(struct icom_port *icom_port)
++static int get_port_memory(struct icom_port *icom_port)
+ {
+ 	int index;
+ 	unsigned long stgAddr;
+@@ -1314,7 +1314,7 @@ static struct uart_driver icom_uart_driver = {
+ 	.cons = ICOM_CONSOLE,
+ };
+ 
+-static int __devinit icom_init_ports(struct icom_adapter *icom_adapter)
++static int icom_init_ports(struct icom_adapter *icom_adapter)
+ {
+ 	u32 subsystem_id = icom_adapter->subsystem_id;
+ 	int i;
+@@ -1381,7 +1381,7 @@ static void icom_port_active(struct icom_port *icom_port, struct icom_adapter *i
+ 			    0x8024 + 2 - 2 * (icom_port->port - 2);
+ 	}
+ }
+-static int __devinit icom_load_ports(struct icom_adapter *icom_adapter)
++static int icom_load_ports(struct icom_adapter *icom_adapter)
+ {
+ 	struct icom_port *icom_port;
+ 	int port_num;
+@@ -1407,7 +1407,7 @@ static int __devinit icom_load_ports(struct icom_adapter *icom_adapter)
+ 	return 0;
+ }
+ 
+-static int __devinit icom_alloc_adapter(struct icom_adapter
++static int icom_alloc_adapter(struct icom_adapter
+ 					**icom_adapter_ref)
+ {
+ 	int adapter_count = 0;
+@@ -1487,7 +1487,7 @@ static void icom_kref_release(struct kref *kref)
+ 	icom_remove_adapter(icom_adapter);
+ }
+ 
+-static int __devinit icom_probe(struct pci_dev *dev,
++static int icom_probe(struct pci_dev *dev,
+ 				const struct pci_device_id *ent)
+ {
+ 	int index;
+diff --git a/drivers/tty/serial/ioc3_serial.c b/drivers/tty/serial/ioc3_serial.c
+index 5ac52898a0bb..d8f1d1d54471 100644
+--- a/drivers/tty/serial/ioc3_serial.c
++++ b/drivers/tty/serial/ioc3_serial.c
+@@ -2010,7 +2010,7 @@ static int ioc3uart_remove(struct ioc3_submodule *is,
+  * @idd: ioc3 driver data for this card
+  */
+ 
+-static int __devinit
++static int
+ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
+ {
+ 	struct pci_dev *pdev = idd->pdev;
+diff --git a/drivers/tty/serial/jsm/jsm_driver.c b/drivers/tty/serial/jsm/jsm_driver.c
+index bbd459226ee0..5b57c8eecfc9 100644
+--- a/drivers/tty/serial/jsm/jsm_driver.c
++++ b/drivers/tty/serial/jsm/jsm_driver.c
+@@ -64,7 +64,7 @@ int jsm_debug;
+ module_param(jsm_debug, int, 0);
+ MODULE_PARM_DESC(jsm_debug, "Driver debugging level");
+ 
+-static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
++static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ 	int rc = 0;
+ 	struct jsm_board *brd;
+diff --git a/drivers/tty/serial/jsm/jsm_tty.c b/drivers/tty/serial/jsm/jsm_tty.c
+index 7d2c1f3aa36b..4c00c5550b1a 100644
+--- a/drivers/tty/serial/jsm/jsm_tty.c
++++ b/drivers/tty/serial/jsm/jsm_tty.c
+@@ -371,7 +371,7 @@ static struct uart_ops jsm_ops = {
+  * Init the tty subsystem.  Called once per board after board has been
+  * downloaded and init'ed.
+  */
+-int __devinit jsm_tty_init(struct jsm_board *brd)
++int jsm_tty_init(struct jsm_board *brd)
+ {
+ 	int i;
+ 	void __iomem *vaddr;
+diff --git a/drivers/tty/serial/lpc32xx_hs.c b/drivers/tty/serial/lpc32xx_hs.c
+index 7b0f5b4e592b..3651dab2009f 100644
+--- a/drivers/tty/serial/lpc32xx_hs.c
++++ b/drivers/tty/serial/lpc32xx_hs.c
+@@ -686,7 +686,7 @@ static struct uart_ops serial_lpc32xx_pops = {
+ /*
+  * Register a set of serial devices attached to a platform device
+  */
+-static int __devinit serial_hs_lpc32xx_probe(struct platform_device *pdev)
++static int serial_hs_lpc32xx_probe(struct platform_device *pdev)
+ {
+ 	struct lpc32xx_hsuart_port *p = &lpc32xx_hs_ports[uarts_registered];
+ 	int ret = 0;
+diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c
+index 2ffd7f091cc0..8dd6189a40ee 100644
+--- a/drivers/tty/serial/max3100.c
++++ b/drivers/tty/serial/max3100.c
+@@ -742,7 +742,7 @@ static struct uart_driver max3100_uart_driver = {
+ };
+ static int uart_driver_registered;
+ 
+-static int __devinit max3100_probe(struct spi_device *spi)
++static int max3100_probe(struct spi_device *spi)
+ {
+ 	int i, retval;
+ 	struct plat_max3100 *pdata;
+diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
+index a332327163a3..88a227f9fe8c 100644
+--- a/drivers/tty/serial/max310x.c
++++ b/drivers/tty/serial/max310x.c
+@@ -378,7 +378,7 @@ static void max310x_wait_pll(struct max310x_port *s)
+ 	}
+ }
+ 
+-static int __devinit max310x_update_best_err(unsigned long f, long *besterr)
++static int max310x_update_best_err(unsigned long f, long *besterr)
+ {
+ 	/* Use baudrate 115200 for calculate error */
+ 	long err = f % (115200 * 16);
+@@ -391,7 +391,7 @@ static int __devinit max310x_update_best_err(unsigned long f, long *besterr)
+ 	return 1;
+ }
+ 
+-static int __devinit max310x_set_ref_clk(struct max310x_port *s)
++static int max310x_set_ref_clk(struct max310x_port *s)
+ {
+ 	unsigned int div, clksrc, pllcfg = 0;
+ 	long besterr = -1;
+@@ -995,7 +995,7 @@ static struct max310x_pdata generic_plat_data = {
+ 	.frequency	= 26000000,
+ };
+ 
+-static int __devinit max310x_probe(struct spi_device *spi)
++static int max310x_probe(struct spi_device *spi)
+ {
+ 	struct max310x_port *s;
+ 	struct device *dev = &spi->dev;
+diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c
+index e3de7856afb3..e2b93d2f8f8c 100644
+--- a/drivers/tty/serial/mcf.c
++++ b/drivers/tty/serial/mcf.c
+@@ -571,7 +571,7 @@ static struct uart_driver mcf_driver = {
+ 
+ /****************************************************************************/
+ 
+-static int __devinit mcf_probe(struct platform_device *pdev)
++static int mcf_probe(struct platform_device *pdev)
+ {
+ 	struct mcf_platform_uart *platp = pdev->dev.platform_data;
+ 	struct uart_port *port;
+diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
+index 8cf577008ad7..7c23c4f4c58d 100644
+--- a/drivers/tty/serial/mpc52xx_uart.c
++++ b/drivers/tty/serial/mpc52xx_uart.c
+@@ -1308,7 +1308,7 @@ static struct of_device_id mpc52xx_uart_of_match[] = {
+ 	{},
+ };
+ 
+-static int __devinit mpc52xx_uart_of_probe(struct platform_device *op)
++static int mpc52xx_uart_of_probe(struct platform_device *op)
+ {
+ 	int idx = -1;
+ 	unsigned int uartclk;
+diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c
+index 649ce126804e..41497fd3d360 100644
+--- a/drivers/tty/serial/mrst_max3110.c
++++ b/drivers/tty/serial/mrst_max3110.c
+@@ -773,7 +773,7 @@ static int serial_m3110_resume(struct spi_device *spi)
+ #define serial_m3110_resume	NULL
+ #endif
+ 
+-static int __devinit serial_m3110_probe(struct spi_device *spi)
++static int serial_m3110_probe(struct spi_device *spi)
+ {
+ 	struct uart_max3110 *max;
+ 	void *buffer;
+diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
+index 1361ad5e1d56..02fb63e944eb 100644
+--- a/drivers/tty/serial/msm_serial_hs.c
++++ b/drivers/tty/serial/msm_serial_hs.c
+@@ -1521,7 +1521,7 @@ static int msm_hs_startup(struct uart_port *uport)
+ }
+ 
+ /* Initialize tx and rx data structures */
+-static int __devinit uartdm_init_port(struct uart_port *uport)
++static int uartdm_init_port(struct uart_port *uport)
+ {
+ 	int ret = 0;
+ 	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+@@ -1614,7 +1614,7 @@ static int __devinit uartdm_init_port(struct uart_port *uport)
+ 	return ret;
+ }
+ 
+-static int __devinit msm_hs_probe(struct platform_device *pdev)
++static int msm_hs_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 	struct uart_port *uport;
+diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
+index 479acc88c17e..18b55c2d1d2e 100644
+--- a/drivers/tty/serial/mxs-auart.c
++++ b/drivers/tty/serial/mxs-auart.c
+@@ -1046,7 +1046,7 @@ static int serial_mxs_probe_dt(struct mxs_auart_port *s,
+ 	return 0;
+ }
+ 
+-static int __devinit mxs_auart_probe(struct platform_device *pdev)
++static int mxs_auart_probe(struct platform_device *pdev)
+ {
+ 	const struct of_device_id *of_id =
+ 			of_match_device(mxs_auart_dt_ids, &pdev->dev);
+diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
+index b9fdccb22590..1bce344ca794 100644
+--- a/drivers/tty/serial/of_serial.c
++++ b/drivers/tty/serial/of_serial.c
+@@ -52,7 +52,7 @@ EXPORT_SYMBOL_GPL(tegra_serial_handle_break);
+ /*
+  * Fill a struct uart_port for a given device node
+  */
+-static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
++static int of_platform_serial_setup(struct platform_device *ofdev,
+ 			int type, struct uart_port *port,
+ 			struct of_serial_info *info)
+ {
+@@ -138,7 +138,7 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
+  * Try to register a serial port
+  */
+ static struct of_device_id of_platform_serial_table[];
+-static int __devinit of_platform_serial_probe(struct platform_device *ofdev)
++static int of_platform_serial_probe(struct platform_device *ofdev)
+ {
+ 	const struct of_device_id *match;
+ 	struct of_serial_info *info;
+diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
+index 24e2375c5792..e777b16c4d17 100644
+--- a/drivers/tty/serial/omap-serial.c
++++ b/drivers/tty/serial/omap-serial.c
+@@ -1238,7 +1238,7 @@ static int serial_omap_resume(struct device *dev)
+ }
+ #endif
+ 
+-static void __devinit omap_serial_fill_features_erratas(struct uart_omap_port *up)
++static void omap_serial_fill_features_erratas(struct uart_omap_port *up)
+ {
+ 	u32 mvr, scheme;
+ 	u16 revision, major, minor;
+@@ -1291,7 +1291,7 @@ static void __devinit omap_serial_fill_features_erratas(struct uart_omap_port *u
+ 	}
+ }
+ 
+-static __devinit struct omap_uart_port_info *of_get_uart_port_info(struct device *dev)
++static struct omap_uart_port_info *of_get_uart_port_info(struct device *dev)
+ {
+ 	struct omap_uart_port_info *omap_up_info;
+ 
+@@ -1304,7 +1304,7 @@ static __devinit struct omap_uart_port_info *of_get_uart_port_info(struct device
+ 	return omap_up_info;
+ }
+ 
+-static int __devinit serial_omap_probe(struct platform_device *pdev)
++static int serial_omap_probe(struct platform_device *pdev)
+ {
+ 	struct uart_omap_port	*up;
+ 	struct resource		*mem, *irq;
+diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
+index f5fb9bd1a14a..8318925fbf6b 100644
+--- a/drivers/tty/serial/pch_uart.c
++++ b/drivers/tty/serial/pch_uart.c
+@@ -1839,7 +1839,7 @@ static DEFINE_PCI_DEVICE_TABLE(pch_uart_pci_id) = {
+ 	{0,},
+ };
+ 
+-static int __devinit pch_uart_pci_probe(struct pci_dev *pdev,
++static int pch_uart_pci_probe(struct pci_dev *pdev,
+ 					const struct pci_device_id *id)
+ {
+ 	int ret;
+diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c
+index 2ca5959ec3fa..da56c8a0fdc9 100644
+--- a/drivers/tty/serial/sa1100.c
++++ b/drivers/tty/serial/sa1100.c
+@@ -637,7 +637,7 @@ static void __init sa1100_init_ports(void)
+ 	PPSR |= PPC_TXD1 | PPC_TXD3;
+ }
+ 
+-void __devinit sa1100_register_uart_fns(struct sa1100_port_fns *fns)
++void sa1100_register_uart_fns(struct sa1100_port_fns *fns)
+ {
+ 	if (fns->get_mctrl)
+ 		sa1100_pops.get_mctrl = fns->get_mctrl;
+diff --git a/drivers/tty/serial/sc26xx.c b/drivers/tty/serial/sc26xx.c
+index 9a40659ec52f..aced1dd923d8 100644
+--- a/drivers/tty/serial/sc26xx.c
++++ b/drivers/tty/serial/sc26xx.c
+@@ -621,7 +621,7 @@ static u8 sc26xx_flags2mask(unsigned int flags, unsigned int bitpos)
+ 	return bit ? (1 << (bit - 1)) : 0;
+ }
+ 
+-static void __devinit sc26xx_init_masks(struct uart_sc26xx_port *up,
++static void sc26xx_init_masks(struct uart_sc26xx_port *up,
+ 					int line, unsigned int data)
+ {
+ 	up->dtr_mask[line] = sc26xx_flags2mask(data,  0);
+@@ -632,7 +632,7 @@ static void __devinit sc26xx_init_masks(struct uart_sc26xx_port *up,
+ 	up->ri_mask[line]  = sc26xx_flags2mask(data, 20);
+ }
+ 
+-static int __devinit sc26xx_probe(struct platform_device *dev)
++static int sc26xx_probe(struct platform_device *dev)
+ {
+ 	struct resource *res;
+ 	struct uart_sc26xx_port *up;
+diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c
+index 810853f5fd0e..1ddace83263f 100644
+--- a/drivers/tty/serial/sccnxp.c
++++ b/drivers/tty/serial/sccnxp.c
+@@ -740,7 +740,7 @@ static int sccnxp_console_setup(struct console *co, char *options)
+ }
+ #endif
+ 
+-static int __devinit sccnxp_probe(struct platform_device *pdev)
++static int sccnxp_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ 	int chiptype = pdev->id_entry->driver_data;
+diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c
+index 9d979a9e41a2..23b28b8f4670 100644
+--- a/drivers/tty/serial/serial_txx9.c
++++ b/drivers/tty/serial/serial_txx9.c
+@@ -1030,7 +1030,7 @@ static DEFINE_MUTEX(serial_txx9_mutex);
+  *
+  *	On success the port is ready to use and the line number is returned.
+  */
+-static int __devinit serial_txx9_register_port(struct uart_port *port)
++static int serial_txx9_register_port(struct uart_port *port)
+ {
+ 	int i;
+ 	struct uart_txx9_port *uart;
+@@ -1096,7 +1096,7 @@ static void __devexit serial_txx9_unregister_port(int line)
+ /*
+  * Register a set of serial devices attached to a platform device.
+  */
+-static int __devinit serial_txx9_probe(struct platform_device *dev)
++static int serial_txx9_probe(struct platform_device *dev)
+ {
+ 	struct uart_port *p = dev->dev.platform_data;
+ 	struct uart_port port;
+@@ -1187,7 +1187,7 @@ static struct platform_driver serial_txx9_plat_driver = {
+  * Probe one serial board.  Unfortunately, there is no rhyme nor reason
+  * to the arrangement of serial ports on a PCI card.
+  */
+-static int __devinit
++static int
+ pciserial_txx9_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
+ {
+ 	struct uart_port port;
+diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
+index d38c0f546032..61477567423f 100644
+--- a/drivers/tty/serial/sh-sci.c
++++ b/drivers/tty/serial/sh-sci.c
+@@ -1126,7 +1126,7 @@ static const char *sci_gpio_str(unsigned int index)
+ 	return sci_gpio_names[index];
+ }
+ 
+-static void __devinit sci_init_gpios(struct sci_port *port)
++static void sci_init_gpios(struct sci_port *port)
+ {
+ 	struct uart_port *up = &port->port;
+ 	int i;
+@@ -2069,7 +2069,7 @@ static struct uart_ops sci_uart_ops = {
+ #endif
+ };
+ 
+-static int __devinit sci_init_single(struct platform_device *dev,
++static int sci_init_single(struct platform_device *dev,
+ 				     struct sci_port *sci_port,
+ 				     unsigned int index,
+ 				     struct plat_sci_port *p)
+@@ -2240,7 +2240,7 @@ static void serial_console_write(struct console *co, const char *s,
+ 	local_irq_restore(flags);
+ }
+ 
+-static int __devinit serial_console_setup(struct console *co, char *options)
++static int serial_console_setup(struct console *co, char *options)
+ {
+ 	struct sci_port *sci_port;
+ 	struct uart_port *port;
+@@ -2294,7 +2294,7 @@ static struct console early_serial_console = {
+ 
+ static char early_serial_buf[32];
+ 
+-static int __devinit sci_probe_earlyprintk(struct platform_device *pdev)
++static int sci_probe_earlyprintk(struct platform_device *pdev)
+ {
+ 	struct plat_sci_port *cfg = pdev->dev.platform_data;
+ 
+@@ -2317,7 +2317,7 @@ static int __devinit sci_probe_earlyprintk(struct platform_device *pdev)
+ #define SCI_CONSOLE	(&serial_console)
+ 
+ #else
+-static inline int __devinit sci_probe_earlyprintk(struct platform_device *pdev)
++static inline int sci_probe_earlyprintk(struct platform_device *pdev)
+ {
+ 	return -EINVAL;
+ }
+@@ -2353,7 +2353,7 @@ static int sci_remove(struct platform_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devinit sci_probe_single(struct platform_device *dev,
++static int sci_probe_single(struct platform_device *dev,
+ 				      unsigned int index,
+ 				      struct plat_sci_port *p,
+ 				      struct sci_port *sciport)
+@@ -2383,7 +2383,7 @@ static int __devinit sci_probe_single(struct platform_device *dev,
+ 	return 0;
+ }
+ 
+-static int __devinit sci_probe(struct platform_device *dev)
++static int sci_probe(struct platform_device *dev)
+ {
+ 	struct plat_sci_port *p = dev->dev.platform_data;
+ 	struct sci_port *sp = &sci_ports[dev->id];
+diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c
+index 949b2d3dcc55..cb58867036a0 100644
+--- a/drivers/tty/serial/sunhv.c
++++ b/drivers/tty/serial/sunhv.c
+@@ -519,7 +519,7 @@ static struct console sunhv_console = {
+ 	.data	=	&sunhv_reg,
+ };
+ 
+-static int __devinit hv_probe(struct platform_device *op)
++static int hv_probe(struct platform_device *op)
+ {
+ 	struct uart_port *port;
+ 	unsigned long minor;
+diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c
+index bbb07bc74f6c..9a13c54d5f8a 100644
+--- a/drivers/tty/serial/sunsab.c
++++ b/drivers/tty/serial/sunsab.c
+@@ -954,7 +954,7 @@ static inline struct console *SUNSAB_CONSOLE(void)
+ #define sunsab_console_init()	do { } while (0)
+ #endif
+ 
+-static int __devinit sunsab_init_one(struct uart_sunsab_port *up,
++static int sunsab_init_one(struct uart_sunsab_port *up,
+ 				     struct platform_device *op,
+ 				     unsigned long offset,
+ 				     int line)
+@@ -1007,7 +1007,7 @@ static int __devinit sunsab_init_one(struct uart_sunsab_port *up,
+ 	return 0;
+ }
+ 
+-static int __devinit sab_probe(struct platform_device *op)
++static int sab_probe(struct platform_device *op)
+ {
+ 	static int inst;
+ 	struct uart_sunsab_port *up;
+diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
+index c0658f0b51a1..049bbc5bc769 100644
+--- a/drivers/tty/serial/sunsu.c
++++ b/drivers/tty/serial/sunsu.c
+@@ -1185,7 +1185,7 @@ static struct uart_driver sunsu_reg = {
+ 	.major			= TTY_MAJOR,
+ };
+ 
+-static int __devinit sunsu_kbd_ms_init(struct uart_sunsu_port *up)
++static int sunsu_kbd_ms_init(struct uart_sunsu_port *up)
+ {
+ 	int quot, baud;
+ #ifdef CONFIG_SERIO
+@@ -1391,7 +1391,7 @@ static inline struct console *SUNSU_CONSOLE(void)
+ #define sunsu_serial_console_init()	do { } while (0)
+ #endif
+ 
+-static enum su_type __devinit su_get_type(struct device_node *dp)
++static enum su_type su_get_type(struct device_node *dp)
+ {
+ 	struct device_node *ap = of_find_node_by_path("/aliases");
+ 
+@@ -1412,7 +1412,7 @@ static enum su_type __devinit su_get_type(struct device_node *dp)
+ 	return SU_PORT_PORT;
+ }
+ 
+-static int __devinit su_probe(struct platform_device *op)
++static int su_probe(struct platform_device *op)
+ {
+ 	static int inst;
+ 	struct device_node *dp = op->dev.of_node;
+diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c
+index c2ef47594d69..02c058fbefe5 100644
+--- a/drivers/tty/serial/sunzilog.c
++++ b/drivers/tty/serial/sunzilog.c
+@@ -1282,7 +1282,7 @@ static inline struct console *SUNZILOG_CONSOLE(void)
+ #define SUNZILOG_CONSOLE()	(NULL)
+ #endif
+ 
+-static void __devinit sunzilog_init_kbdms(struct uart_sunzilog_port *up)
++static void sunzilog_init_kbdms(struct uart_sunzilog_port *up)
+ {
+ 	int baud, brg;
+ 
+@@ -1302,7 +1302,7 @@ static void __devinit sunzilog_init_kbdms(struct uart_sunzilog_port *up)
+ }
+ 
+ #ifdef CONFIG_SERIO
+-static void __devinit sunzilog_register_serio(struct uart_sunzilog_port *up)
++static void sunzilog_register_serio(struct uart_sunzilog_port *up)
+ {
+ 	struct serio *serio = &up->serio;
+ 
+@@ -1331,7 +1331,7 @@ static void __devinit sunzilog_register_serio(struct uart_sunzilog_port *up)
+ }
+ #endif
+ 
+-static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up)
++static void sunzilog_init_hw(struct uart_sunzilog_port *up)
+ {
+ 	struct zilog_channel __iomem *channel;
+ 	unsigned long flags;
+@@ -1400,7 +1400,7 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up)
+ 
+ static int zilog_irq;
+ 
+-static int __devinit zs_probe(struct platform_device *op)
++static int zs_probe(struct platform_device *op)
+ {
+ 	static int kbm_inst, uart_inst;
+ 	int inst;
+diff --git a/drivers/tty/serial/timbuart.c b/drivers/tty/serial/timbuart.c
+index 5fc11f2a8be4..c833f50980b6 100644
+--- a/drivers/tty/serial/timbuart.c
++++ b/drivers/tty/serial/timbuart.c
+@@ -426,7 +426,7 @@ static struct uart_driver timbuart_driver = {
+ 	.nr = 1
+ };
+ 
+-static int __devinit timbuart_probe(struct platform_device *dev)
++static int timbuart_probe(struct platform_device *dev)
+ {
+ 	int err, irq;
+ 	struct timbuart_port *uart;
+diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
+index 1d4438306ae5..df9eeb451ae9 100644
+--- a/drivers/tty/serial/uartlite.c
++++ b/drivers/tty/serial/uartlite.c
+@@ -408,7 +408,7 @@ static void ulite_console_write(struct console *co, const char *s,
+ 		spin_unlock_irqrestore(&port->lock, flags);
+ }
+ 
+-static int __devinit ulite_console_setup(struct console *co, char *options)
++static int ulite_console_setup(struct console *co, char *options)
+ {
+ 	struct uart_port *port;
+ 	int baud = 9600;
+@@ -486,7 +486,7 @@ static struct uart_driver ulite_uart_driver = {
+  *
+  * Returns: 0 on success, <0 otherwise
+  */
+-static int __devinit ulite_assign(struct device *dev, int id, u32 base, int irq)
++static int ulite_assign(struct device *dev, int id, u32 base, int irq)
+ {
+ 	struct uart_port *port;
+ 	int rc;
+@@ -570,7 +570,7 @@ static struct of_device_id ulite_of_match[] __devinitdata = {
+ MODULE_DEVICE_TABLE(of, ulite_of_match);
+ #endif /* CONFIG_OF */
+ 
+-static int __devinit ulite_probe(struct platform_device *pdev)
++static int ulite_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res, *res2;
+ 	int id = pdev->id;
+diff --git a/drivers/tty/serial/vr41xx_siu.c b/drivers/tty/serial/vr41xx_siu.c
+index 9d3bf75e55a4..c046c995534a 100644
+--- a/drivers/tty/serial/vr41xx_siu.c
++++ b/drivers/tty/serial/vr41xx_siu.c
+@@ -823,7 +823,7 @@ static struct console siu_console = {
+ 	.data	= &siu_uart_driver,
+ };
+ 
+-static int __devinit siu_console_init(void)
++static int siu_console_init(void)
+ {
+ 	struct uart_port *port;
+ 	int i;
+@@ -867,7 +867,7 @@ static struct uart_driver siu_uart_driver = {
+ 	.cons		= SERIAL_VR41XX_CONSOLE,
+ };
+ 
+-static int __devinit siu_probe(struct platform_device *dev)
++static int siu_probe(struct platform_device *dev)
+ {
+ 	struct uart_port *port;
+ 	int num, i, retval;
+diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c
+index dbcc909291b2..80530c7d0025 100644
+--- a/drivers/tty/serial/vt8500_serial.c
++++ b/drivers/tty/serial/vt8500_serial.c
+@@ -554,7 +554,7 @@ static struct uart_driver vt8500_uart_driver = {
+ 	.cons		= VT8500_CONSOLE,
+ };
+ 
+-static int __devinit vt8500_serial_probe(struct platform_device *pdev)
++static int vt8500_serial_probe(struct platform_device *pdev)
+ {
+ 	struct vt8500_port *vt8500_port;
+ 	struct resource *mmres, *irqres;
+diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
+index 23efe17be44b..a1cd2df51c9e 100644
+--- a/drivers/tty/serial/xilinx_uartps.c
++++ b/drivers/tty/serial/xilinx_uartps.c
+@@ -939,7 +939,7 @@ static struct uart_driver xuartps_uart_driver = {
+  *
+  * Returns 0 on success, negative error otherwise
+  **/
+-static int __devinit xuartps_probe(struct platform_device *pdev)
++static int xuartps_probe(struct platform_device *pdev)
+ {
+ 	int rc;
+ 	struct uart_port *port;
+diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c
+index 31db13be4697..4798dd5c55dd 100644
+--- a/drivers/tty/synclink.c
++++ b/drivers/tty/synclink.c
+@@ -8065,7 +8065,7 @@ static void hdlcdev_exit(struct mgsl_struct *info)
+ #endif /* CONFIG_HDLC */
+ 
+ 
+-static int __devinit synclink_init_one (struct pci_dev *dev,
++static int synclink_init_one (struct pci_dev *dev,
+ 					const struct pci_device_id *ent)
+ {
+ 	struct mgsl_struct *info;
+diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c
+index 595f2f48193f..a84c4089f56a 100644
+--- a/drivers/tty/synclink_gt.c
++++ b/drivers/tty/synclink_gt.c
+@@ -3698,7 +3698,7 @@ static void device_init(int adapter_num, struct pci_dev *pdev)
+ 	}
+ }
+ 
+-static int __devinit init_one(struct pci_dev *dev,
++static int init_one(struct pci_dev *dev,
+ 			      const struct pci_device_id *ent)
+ {
+ 	if (pci_enable_device(dev)) {
+diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c
+index 71f3eb22c979..d301110b4d1a 100644
+--- a/drivers/tty/synclinkmp.c
++++ b/drivers/tty/synclinkmp.c
+@@ -5595,7 +5595,7 @@ static void write_control_reg(SLMP_INFO * info)
+ }
+ 
+ 
+-static int __devinit synclinkmp_init_one (struct pci_dev *dev,
++static int synclinkmp_init_one (struct pci_dev *dev,
+ 					  const struct pci_device_id *ent)
+ {
+ 	if (pci_enable_device(dev)) {

commit 2d47b7160243b1422006b91debf438484a4fde58
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:34 2012 -0500
+
+    tty: serial: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Alan Cox 
+    Cc: Lucas Tavares 
+    Cc: "David S. Miller" 
+    Cc: Peter Korsgaard 
+    Cc: Tony Prisk 
+    Acked-by: Tobias Klauser 
+    Acked-by: Nicolas Ferre 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
+index 5ccbd90540cf..870c5f2d0c8f 100644
+--- a/drivers/tty/serial/8250/8250.c
++++ b/drivers/tty/serial/8250/8250.c
+@@ -3078,7 +3078,7 @@ static int serial8250_resume(struct platform_device *dev)
+ 
+ static struct platform_driver serial8250_isa_driver = {
+ 	.probe		= serial8250_probe,
+-	.remove		= __devexit_p(serial8250_remove),
++	.remove		= serial8250_remove,
+ 	.suspend	= serial8250_suspend,
+ 	.resume		= serial8250_resume,
+ 	.driver		= {
+diff --git a/drivers/tty/serial/8250/8250_acorn.c b/drivers/tty/serial/8250/8250_acorn.c
+index 857498312a9a..b5e4b494cb07 100644
+--- a/drivers/tty/serial/8250/8250_acorn.c
++++ b/drivers/tty/serial/8250/8250_acorn.c
+@@ -116,7 +116,7 @@ static const struct ecard_id serial_cids[] = {
+ 
+ static struct ecard_driver serial_card_driver = {
+ 	.probe		= serial_card_probe,
+-	.remove 	= __devexit_p(serial_card_remove),
++	.remove		= serial_card_remove,
+ 	.id_table	= serial_cids,
+ 	.drv = {
+ 		.name	= "8250_acorn",
+diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
+index b19b8c547801..2db80d03b0ba 100644
+--- a/drivers/tty/serial/8250/8250_dw.c
++++ b/drivers/tty/serial/8250/8250_dw.c
+@@ -197,7 +197,7 @@ static struct platform_driver dw8250_platform_driver = {
+ 		.of_match_table	= dw8250_match,
+ 	},
+ 	.probe			= dw8250_probe,
+-	.remove			= __devexit_p(dw8250_remove),
++	.remove			= dw8250_remove,
+ 	.suspend		= dw8250_suspend,
+ 	.resume			= dw8250_resume,
+ };
+diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c
+index 3a0363e7f3a7..80c0a626c13e 100644
+--- a/drivers/tty/serial/8250/8250_em.c
++++ b/drivers/tty/serial/8250/8250_em.c
+@@ -176,7 +176,7 @@ static struct platform_driver serial8250_em_platform_driver = {
+ 		.owner		= THIS_MODULE,
+ 	},
+ 	.probe			= serial8250_em_probe,
+-	.remove			= __devexit_p(serial8250_em_remove),
++	.remove			= serial8250_em_remove,
+ };
+ 
+ module_platform_driver(serial8250_em_platform_driver);
+diff --git a/drivers/tty/serial/8250/8250_hp300.c b/drivers/tty/serial/8250/8250_hp300.c
+index f3d0edf46644..89e88559f489 100644
+--- a/drivers/tty/serial/8250/8250_hp300.c
++++ b/drivers/tty/serial/8250/8250_hp300.c
+@@ -52,7 +52,7 @@ static struct dio_driver hpdca_driver = {
+ 	.name      = "hpdca",
+ 	.id_table  = hpdca_dio_tbl,
+ 	.probe     = hpdca_init_one,
+-	.remove    = __devexit_p(hpdca_remove_one),
++	.remove    = hpdca_remove_one,
+ };
+ 
+ #endif
+diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
+index 508063b2a4b8..c049cfa06f55 100644
+--- a/drivers/tty/serial/8250/8250_pci.c
++++ b/drivers/tty/serial/8250/8250_pci.c
+@@ -1314,7 +1314,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ 		.subdevice	= PCI_ANY_ID,
+ 		.init		= pci_ite887x_init,
+ 		.setup		= pci_default_setup,
+-		.exit		= __devexit_p(pci_ite887x_exit),
++		.exit		= pci_ite887x_exit,
+ 	},
+ 	/*
+ 	 * National Instruments
+@@ -1326,7 +1326,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ 		.subdevice	= PCI_ANY_ID,
+ 		.init		= pci_ni8420_init,
+ 		.setup		= pci_default_setup,
+-		.exit		= __devexit_p(pci_ni8420_exit),
++		.exit		= pci_ni8420_exit,
+ 	},
+ 	{
+ 		.vendor		= PCI_VENDOR_ID_NI,
+@@ -1335,7 +1335,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ 		.subdevice	= PCI_ANY_ID,
+ 		.init		= pci_ni8420_init,
+ 		.setup		= pci_default_setup,
+-		.exit		= __devexit_p(pci_ni8420_exit),
++		.exit		= pci_ni8420_exit,
+ 	},
+ 	{
+ 		.vendor		= PCI_VENDOR_ID_NI,
+@@ -1344,7 +1344,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ 		.subdevice	= PCI_ANY_ID,
+ 		.init		= pci_ni8420_init,
+ 		.setup		= pci_default_setup,
+-		.exit		= __devexit_p(pci_ni8420_exit),
++		.exit		= pci_ni8420_exit,
+ 	},
+ 	{
+ 		.vendor		= PCI_VENDOR_ID_NI,
+@@ -1353,7 +1353,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ 		.subdevice	= PCI_ANY_ID,
+ 		.init		= pci_ni8420_init,
+ 		.setup		= pci_default_setup,
+-		.exit		= __devexit_p(pci_ni8420_exit),
++		.exit		= pci_ni8420_exit,
+ 	},
+ 	{
+ 		.vendor		= PCI_VENDOR_ID_NI,
+@@ -1362,7 +1362,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ 		.subdevice	= PCI_ANY_ID,
+ 		.init		= pci_ni8420_init,
+ 		.setup		= pci_default_setup,
+-		.exit		= __devexit_p(pci_ni8420_exit),
++		.exit		= pci_ni8420_exit,
+ 	},
+ 	{
+ 		.vendor		= PCI_VENDOR_ID_NI,
+@@ -1371,7 +1371,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ 		.subdevice	= PCI_ANY_ID,
+ 		.init		= pci_ni8420_init,
+ 		.setup		= pci_default_setup,
+-		.exit		= __devexit_p(pci_ni8420_exit),
++		.exit		= pci_ni8420_exit,
+ 	},
+ 	{
+ 		.vendor		= PCI_VENDOR_ID_NI,
+@@ -1380,7 +1380,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ 		.subdevice	= PCI_ANY_ID,
+ 		.init		= pci_ni8420_init,
+ 		.setup		= pci_default_setup,
+-		.exit		= __devexit_p(pci_ni8420_exit),
++		.exit		= pci_ni8420_exit,
+ 	},
+ 	{
+ 		.vendor		= PCI_VENDOR_ID_NI,
+@@ -1389,7 +1389,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ 		.subdevice	= PCI_ANY_ID,
+ 		.init		= pci_ni8420_init,
+ 		.setup		= pci_default_setup,
+-		.exit		= __devexit_p(pci_ni8420_exit),
++		.exit		= pci_ni8420_exit,
+ 	},
+ 	{
+ 		.vendor		= PCI_VENDOR_ID_NI,
+@@ -1398,7 +1398,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ 		.subdevice	= PCI_ANY_ID,
+ 		.init		= pci_ni8420_init,
+ 		.setup		= pci_default_setup,
+-		.exit		= __devexit_p(pci_ni8420_exit),
++		.exit		= pci_ni8420_exit,
+ 	},
+ 	{
+ 		.vendor		= PCI_VENDOR_ID_NI,
+@@ -1407,7 +1407,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ 		.subdevice	= PCI_ANY_ID,
+ 		.init		= pci_ni8420_init,
+ 		.setup		= pci_default_setup,
+-		.exit		= __devexit_p(pci_ni8420_exit),
++		.exit		= pci_ni8420_exit,
+ 	},
+ 	{
+ 		.vendor		= PCI_VENDOR_ID_NI,
+@@ -1416,7 +1416,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ 		.subdevice	= PCI_ANY_ID,
+ 		.init		= pci_ni8420_init,
+ 		.setup		= pci_default_setup,
+-		.exit		= __devexit_p(pci_ni8420_exit),
++		.exit		= pci_ni8420_exit,
+ 	},
+ 	{
+ 		.vendor		= PCI_VENDOR_ID_NI,
+@@ -1425,7 +1425,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ 		.subdevice	= PCI_ANY_ID,
+ 		.init		= pci_ni8420_init,
+ 		.setup		= pci_default_setup,
+-		.exit		= __devexit_p(pci_ni8420_exit),
++		.exit		= pci_ni8420_exit,
+ 	},
+ 	{
+ 		.vendor		= PCI_VENDOR_ID_NI,
+@@ -1434,7 +1434,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ 		.subdevice	= PCI_ANY_ID,
+ 		.init		= pci_ni8430_init,
+ 		.setup		= pci_ni8430_setup,
+-		.exit		= __devexit_p(pci_ni8430_exit),
++		.exit		= pci_ni8430_exit,
+ 	},
+ 	/*
+ 	 * Panacom
+@@ -1446,7 +1446,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ 		.subdevice	= PCI_ANY_ID,
+ 		.init		= pci_plx9050_init,
+ 		.setup		= pci_default_setup,
+-		.exit		= __devexit_p(pci_plx9050_exit),
++		.exit		= pci_plx9050_exit,
+ 	},
+ 	{
+ 		.vendor		= PCI_VENDOR_ID_PANACOM,
+@@ -1455,7 +1455,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ 		.subdevice	= PCI_ANY_ID,
+ 		.init		= pci_plx9050_init,
+ 		.setup		= pci_default_setup,
+-		.exit		= __devexit_p(pci_plx9050_exit),
++		.exit		= pci_plx9050_exit,
+ 	},
+ 	/*
+ 	 * PLX
+@@ -1474,7 +1474,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ 		.subdevice	= PCI_SUBDEVICE_ID_EXSYS_4055,
+ 		.init		= pci_plx9050_init,
+ 		.setup		= pci_default_setup,
+-		.exit		= __devexit_p(pci_plx9050_exit),
++		.exit		= pci_plx9050_exit,
+ 	},
+ 	{
+ 		.vendor		= PCI_VENDOR_ID_PLX,
+@@ -1483,7 +1483,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ 		.subdevice	= PCI_SUBDEVICE_ID_KEYSPAN_SX2,
+ 		.init		= pci_plx9050_init,
+ 		.setup		= pci_default_setup,
+-		.exit		= __devexit_p(pci_plx9050_exit),
++		.exit		= pci_plx9050_exit,
+ 	},
+ 	{
+ 		.vendor		= PCI_VENDOR_ID_PLX,
+@@ -1492,7 +1492,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ 		.subdevice	= PCI_SUBDEVICE_ID_UNKNOWN_0x1584,
+ 		.init		= pci_plx9050_init,
+ 		.setup		= pci_default_setup,
+-		.exit		= __devexit_p(pci_plx9050_exit),
++		.exit		= pci_plx9050_exit,
+ 	},
+ 	{
+ 		.vendor		= PCI_VENDOR_ID_PLX,
+@@ -1501,7 +1501,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ 		.subdevice	= PCI_DEVICE_ID_PLX_ROMULUS,
+ 		.init		= pci_plx9050_init,
+ 		.setup		= pci_default_setup,
+-		.exit		= __devexit_p(pci_plx9050_exit),
++		.exit		= pci_plx9050_exit,
+ 	},
+ 	/*
+ 	 * SBS Technologies, Inc., PMC-OCTALPRO 232
+@@ -1513,7 +1513,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ 		.subdevice	= PCI_SUBDEVICE_ID_OCTPRO232,
+ 		.init		= sbs_init,
+ 		.setup		= sbs_setup,
+-		.exit		= __devexit_p(sbs_exit),
++		.exit		= sbs_exit,
+ 	},
+ 	/*
+ 	 * SBS Technologies, Inc., PMC-OCTALPRO 422
+@@ -1525,7 +1525,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ 		.subdevice	= PCI_SUBDEVICE_ID_OCTPRO422,
+ 		.init		= sbs_init,
+ 		.setup		= sbs_setup,
+-		.exit		= __devexit_p(sbs_exit),
++		.exit		= sbs_exit,
+ 	},
+ 	/*
+ 	 * SBS Technologies, Inc., P-Octal 232
+@@ -1537,7 +1537,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ 		.subdevice	= PCI_SUBDEVICE_ID_POCTAL232,
+ 		.init		= sbs_init,
+ 		.setup		= sbs_setup,
+-		.exit		= __devexit_p(sbs_exit),
++		.exit		= sbs_exit,
+ 	},
+ 	/*
+ 	 * SBS Technologies, Inc., P-Octal 422
+@@ -1549,7 +1549,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ 		.subdevice	= PCI_SUBDEVICE_ID_POCTAL422,
+ 		.init		= sbs_init,
+ 		.setup		= sbs_setup,
+-		.exit		= __devexit_p(sbs_exit),
++		.exit		= sbs_exit,
+ 	},
+ 	/*
+ 	 * SIIG cards - these may be called via parport_serial
+@@ -4323,7 +4323,7 @@ static const struct pci_error_handlers serial8250_err_handler = {
+ static struct pci_driver serial_pci_driver = {
+ 	.name		= "serial",
+ 	.probe		= pciserial_init_one,
+-	.remove		= __devexit_p(pciserial_remove_one),
++	.remove		= pciserial_remove_one,
+ #ifdef CONFIG_PM
+ 	.suspend	= pciserial_suspend_one,
+ 	.resume		= pciserial_resume_one,
+diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c
+index f8ee25001dd0..e566220f187d 100644
+--- a/drivers/tty/serial/8250/8250_pnp.c
++++ b/drivers/tty/serial/8250/8250_pnp.c
+@@ -511,7 +511,7 @@ static int serial_pnp_resume(struct pnp_dev *dev)
+ static struct pnp_driver serial_pnp_driver = {
+ 	.name		= "serial",
+ 	.probe		= serial_pnp_probe,
+-	.remove		= __devexit_p(serial_pnp_remove),
++	.remove		= serial_pnp_remove,
+ 	.suspend	= serial_pnp_suspend,
+ 	.resume		= serial_pnp_resume,
+ 	.id_table	= pnp_dev_table,
+diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c
+index 530181e49f6b..ef16b0aa383a 100644
+--- a/drivers/tty/serial/altera_jtaguart.c
++++ b/drivers/tty/serial/altera_jtaguart.c
+@@ -477,7 +477,7 @@ MODULE_DEVICE_TABLE(of, altera_jtaguart_match);
+ 
+ static struct platform_driver altera_jtaguart_platform_driver = {
+ 	.probe	= altera_jtaguart_probe,
+-	.remove	= __devexit_p(altera_jtaguart_remove),
++	.remove	= altera_jtaguart_remove,
+ 	.driver	= {
+ 		.name		= DRV_NAME,
+ 		.owner		= THIS_MODULE,
+diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c
+index 15d80b9fb303..117ea2c89630 100644
+--- a/drivers/tty/serial/altera_uart.c
++++ b/drivers/tty/serial/altera_uart.c
+@@ -621,7 +621,7 @@ MODULE_DEVICE_TABLE(of, altera_uart_match);
+ 
+ static struct platform_driver altera_uart_platform_driver = {
+ 	.probe	= altera_uart_probe,
+-	.remove	= __devexit_p(altera_uart_remove),
++	.remove	= altera_uart_remove,
+ 	.driver	= {
+ 		.name		= DRV_NAME,
+ 		.owner		= THIS_MODULE,
+diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c
+index 0f5b28afc2ad..77115448af5f 100644
+--- a/drivers/tty/serial/ar933x_uart.c
++++ b/drivers/tty/serial/ar933x_uart.c
+@@ -725,7 +725,7 @@ static int __devexit ar933x_uart_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver ar933x_uart_platform_driver = {
+ 	.probe		= ar933x_uart_probe,
+-	.remove		= __devexit_p(ar933x_uart_remove),
++	.remove		= ar933x_uart_remove,
+ 	.driver		= {
+ 		.name		= DRIVER_NAME,
+ 		.owner		= THIS_MODULE,
+diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
+index e9c61d1b1c79..d6525698db31 100644
+--- a/drivers/tty/serial/arc_uart.c
++++ b/drivers/tty/serial/arc_uart.c
+@@ -697,7 +697,7 @@ static int __devexit arc_serial_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver arc_platform_driver = {
+ 	.probe = arc_serial_probe,
+-	.remove = __devexit_p(arc_serial_remove),
++	.remove = arc_serial_remove,
+ 	.driver = {
+ 		.name = DRIVER_NAME,
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
+index 3d7e1ee2fa57..27eae4b2355a 100644
+--- a/drivers/tty/serial/atmel_serial.c
++++ b/drivers/tty/serial/atmel_serial.c
+@@ -1876,7 +1876,7 @@ static int __devexit atmel_serial_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver atmel_serial_driver = {
+ 	.probe		= atmel_serial_probe,
+-	.remove		= __devexit_p(atmel_serial_remove),
++	.remove		= atmel_serial_remove,
+ 	.suspend	= atmel_serial_suspend,
+ 	.resume		= atmel_serial_resume,
+ 	.driver		= {
+diff --git a/drivers/tty/serial/bcm63xx_uart.c b/drivers/tty/serial/bcm63xx_uart.c
+index c0b68b9cad91..7f631d4a5c44 100644
+--- a/drivers/tty/serial/bcm63xx_uart.c
++++ b/drivers/tty/serial/bcm63xx_uart.c
+@@ -865,7 +865,7 @@ static int __devexit bcm_uart_remove(struct platform_device *pdev)
+  */
+ static struct platform_driver bcm_uart_platform_driver = {
+ 	.probe	= bcm_uart_probe,
+-	.remove	= __devexit_p(bcm_uart_remove),
++	.remove	= bcm_uart_remove,
+ 	.driver	= {
+ 		.owner = THIS_MODULE,
+ 		.name  = "bcm63xx_uart",
+diff --git a/drivers/tty/serial/bfin_sport_uart.c b/drivers/tty/serial/bfin_sport_uart.c
+index 7fbc3a08f10d..b4a18c7ffdf7 100644
+--- a/drivers/tty/serial/bfin_sport_uart.c
++++ b/drivers/tty/serial/bfin_sport_uart.c
+@@ -871,7 +871,7 @@ static int __devexit sport_uart_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver sport_uart_driver = {
+ 	.probe		= sport_uart_probe,
+-	.remove		= __devexit_p(sport_uart_remove),
++	.remove		= sport_uart_remove,
+ 	.driver		= {
+ 		.name	= DRV_NAME,
+ #ifdef CONFIG_PM
+diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c
+index ca64c4a83ce0..f1f8210a6130 100644
+--- a/drivers/tty/serial/bfin_uart.c
++++ b/drivers/tty/serial/bfin_uart.c
+@@ -1409,7 +1409,7 @@ static int __devexit bfin_serial_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver bfin_serial_driver = {
+ 	.probe		= bfin_serial_probe,
+-	.remove		= __devexit_p(bfin_serial_remove),
++	.remove		= bfin_serial_remove,
+ 	.suspend	= bfin_serial_suspend,
+ 	.resume		= bfin_serial_resume,
+ 	.driver		= {
+diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c
+index a0a6db5c32fe..d631ef52f4f8 100644
+--- a/drivers/tty/serial/clps711x.c
++++ b/drivers/tty/serial/clps711x.c
+@@ -512,7 +512,7 @@ static struct platform_driver clps711x_uart_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe	= uart_clps711x_probe,
+-	.remove	= __devexit_p(uart_clps711x_remove),
++	.remove	= uart_clps711x_remove,
+ };
+ module_platform_driver(clps711x_uart_driver);
+ 
+diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c
+index 615e46470491..1e8bacf95b70 100644
+--- a/drivers/tty/serial/efm32-uart.c
++++ b/drivers/tty/serial/efm32-uart.c
+@@ -791,7 +791,7 @@ MODULE_DEVICE_TABLE(of, efm32_uart_dt_ids);
+ 
+ static struct platform_driver efm32_uart_driver = {
+ 	.probe = efm32_uart_probe,
+-	.remove = __devexit_p(efm32_uart_remove),
++	.remove = efm32_uart_remove,
+ 
+ 	.driver = {
+ 		.name = DRIVER_NAME,
+diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c
+index defc4e3393a3..f0fc2fff1701 100644
+--- a/drivers/tty/serial/icom.c
++++ b/drivers/tty/serial/icom.c
+@@ -1617,7 +1617,7 @@ static struct pci_driver icom_pci_driver = {
+ 	.name = ICOM_DRIVER_NAME,
+ 	.id_table = icom_pci_table,
+ 	.probe = icom_probe,
+-	.remove = __devexit_p(icom_remove),
++	.remove = icom_remove,
+ };
+ 
+ static int __init icom_init(void)
+diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c
+index 91125bb151cf..2783d96ff610 100644
+--- a/drivers/tty/serial/ifx6x60.c
++++ b/drivers/tty/serial/ifx6x60.c
+@@ -1405,7 +1405,7 @@ static struct spi_driver ifx_spi_driver = {
+ 		.owner = THIS_MODULE},
+ 	.probe = ifx_spi_spi_probe,
+ 	.shutdown = ifx_spi_spi_shutdown,
+-	.remove = __devexit_p(ifx_spi_spi_remove),
++	.remove = ifx_spi_spi_remove,
+ 	.suspend = ifx_spi_spi_suspend,
+ 	.resume = ifx_spi_spi_resume,
+ 	.id_table = ifx_id_table
+diff --git a/drivers/tty/serial/jsm/jsm_driver.c b/drivers/tty/serial/jsm/jsm_driver.c
+index 8e05ce94bd46..bbd459226ee0 100644
+--- a/drivers/tty/serial/jsm/jsm_driver.c
++++ b/drivers/tty/serial/jsm/jsm_driver.c
+@@ -217,7 +217,7 @@ static struct pci_driver jsm_driver = {
+ 	.name		= "jsm",
+ 	.id_table	= jsm_pci_tbl,
+ 	.probe		= jsm_probe_one,
+-	.remove		= __devexit_p(jsm_remove_one),
++	.remove		= jsm_remove_one,
+ 	.err_handler    = &jsm_err_handler,
+ };
+ 
+diff --git a/drivers/tty/serial/lpc32xx_hs.c b/drivers/tty/serial/lpc32xx_hs.c
+index ba3af3bf6d43..7b0f5b4e592b 100644
+--- a/drivers/tty/serial/lpc32xx_hs.c
++++ b/drivers/tty/serial/lpc32xx_hs.c
+@@ -783,7 +783,7 @@ MODULE_DEVICE_TABLE(of, serial_hs_lpc32xx_dt_ids);
+ 
+ static struct platform_driver serial_hs_lpc32xx_driver = {
+ 	.probe		= serial_hs_lpc32xx_probe,
+-	.remove		= __devexit_p(serial_hs_lpc32xx_remove),
++	.remove		= serial_hs_lpc32xx_remove,
+ 	.suspend	= serial_hs_lpc32xx_suspend,
+ 	.resume		= serial_hs_lpc32xx_resume,
+ 	.driver		= {
+diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c
+index 0f24486be532..2ffd7f091cc0 100644
+--- a/drivers/tty/serial/max3100.c
++++ b/drivers/tty/serial/max3100.c
+@@ -907,7 +907,7 @@ static struct spi_driver max3100_driver = {
+ 	},
+ 
+ 	.probe		= max3100_probe,
+-	.remove		= __devexit_p(max3100_remove),
++	.remove		= max3100_remove,
+ 	.suspend	= max3100_suspend,
+ 	.resume		= max3100_resume,
+ };
+diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
+index 1ab1d2c66de4..a332327163a3 100644
+--- a/drivers/tty/serial/max310x.c
++++ b/drivers/tty/serial/max310x.c
+@@ -1249,7 +1249,7 @@ static struct spi_driver max310x_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= max310x_probe,
+-	.remove		= __devexit_p(max310x_remove),
++	.remove		= max310x_remove,
+ 	.suspend	= max310x_suspend,
+ 	.resume		= max310x_resume,
+ 	.id_table	= max310x_id_table,
+diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c
+index 9afca093d6ec..e3de7856afb3 100644
+--- a/drivers/tty/serial/mcf.c
++++ b/drivers/tty/serial/mcf.c
+@@ -617,7 +617,7 @@ static int __devexit mcf_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver mcf_platform_driver = {
+ 	.probe		= mcf_probe,
+-	.remove		= __devexit_p(mcf_remove),
++	.remove		= mcf_remove,
+ 	.driver		= {
+ 		.name	= "mcfuart",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c
+index 79fe59b6cc4a..8a74d59270eb 100644
+--- a/drivers/tty/serial/mfd.c
++++ b/drivers/tty/serial/mfd.c
+@@ -1471,7 +1471,7 @@ static struct pci_driver hsu_pci_driver = {
+ 	.name =		"HSU serial",
+ 	.id_table =	pci_ids,
+ 	.probe =	serial_hsu_probe,
+-	.remove =	__devexit_p(serial_hsu_remove),
++	.remove =	serial_hsu_remove,
+ 	.suspend =	serial_hsu_suspend,
+ 	.resume	=	serial_hsu_resume,
+ 	.driver = {
+diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c
+index df2a2240a3ae..649ce126804e 100644
+--- a/drivers/tty/serial/mrst_max3110.c
++++ b/drivers/tty/serial/mrst_max3110.c
+@@ -879,7 +879,7 @@ static struct spi_driver uart_max3110_driver = {
+ 			.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= serial_m3110_probe,
+-	.remove		= __devexit_p(serial_m3110_remove),
++	.remove		= serial_m3110_remove,
+ 	.suspend	= serial_m3110_suspend,
+ 	.resume		= serial_m3110_resume,
+ };
+diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
+index fca13dc73e23..1361ad5e1d56 100644
+--- a/drivers/tty/serial/msm_serial_hs.c
++++ b/drivers/tty/serial/msm_serial_hs.c
+@@ -1838,7 +1838,7 @@ static const struct dev_pm_ops msm_hs_dev_pm_ops = {
+ 
+ static struct platform_driver msm_serial_hs_platform_driver = {
+ 	.probe = msm_hs_probe,
+-	.remove = __devexit_p(msm_hs_remove),
++	.remove = msm_hs_remove,
+ 	.driver = {
+ 		.name = "msm_serial_hs",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/tty/serial/mux.c b/drivers/tty/serial/mux.c
+index 7ea8a263fd9e..27834646d018 100644
+--- a/drivers/tty/serial/mux.c
++++ b/drivers/tty/serial/mux.c
+@@ -571,14 +571,14 @@ static struct parisc_driver builtin_serial_mux_driver = {
+ 	.name =		"builtin_serial_mux",
+ 	.id_table =	builtin_mux_tbl,
+ 	.probe =	mux_probe,
+-	.remove =       __devexit_p(mux_remove),
++	.remove =       mux_remove,
+ };
+ 
+ static struct parisc_driver serial_mux_driver = {
+ 	.name =		"serial_mux",
+ 	.id_table =	mux_tbl,
+ 	.probe =	mux_probe,
+-	.remove =       __devexit_p(mux_remove),
++	.remove =       mux_remove,
+ };
+ 
+ /**
+diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
+index d5b9e3039013..479acc88c17e 100644
+--- a/drivers/tty/serial/mxs-auart.c
++++ b/drivers/tty/serial/mxs-auart.c
+@@ -1155,7 +1155,7 @@ static int __devexit mxs_auart_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver mxs_auart_driver = {
+ 	.probe = mxs_auart_probe,
+-	.remove = __devexit_p(mxs_auart_remove),
++	.remove = mxs_auart_remove,
+ 	.driver = {
+ 		.name = "mxs-auart",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
+index c34735cf6276..24e2375c5792 100644
+--- a/drivers/tty/serial/omap-serial.c
++++ b/drivers/tty/serial/omap-serial.c
+@@ -1586,7 +1586,7 @@ MODULE_DEVICE_TABLE(of, omap_serial_of_match);
+ 
+ static struct platform_driver serial_omap_driver = {
+ 	.probe          = serial_omap_probe,
+-	.remove         = __devexit_p(serial_omap_remove),
++	.remove         = serial_omap_remove,
+ 	.driver		= {
+ 		.name	= DRIVER_NAME,
+ 		.pm	= &serial_omap_dev_pm_ops,
+diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
+index 4cd6c2381528..f5fb9bd1a14a 100644
+--- a/drivers/tty/serial/pch_uart.c
++++ b/drivers/tty/serial/pch_uart.c
+@@ -1869,7 +1869,7 @@ static struct pci_driver pch_uart_pci_driver = {
+ 	.name = "pch_uart",
+ 	.id_table = pch_uart_pci_id,
+ 	.probe = pch_uart_pci_probe,
+-	.remove = __devexit_p(pch_uart_pci_remove),
++	.remove = pch_uart_pci_remove,
+ 	.suspend = pch_uart_pci_suspend,
+ 	.resume = pch_uart_pci_resume,
+ };
+diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
+index 740458ca62cc..6568beb4d370 100644
+--- a/drivers/tty/serial/samsung.c
++++ b/drivers/tty/serial/samsung.c
+@@ -1712,7 +1712,7 @@ MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match);
+ 
+ static struct platform_driver samsung_serial_driver = {
+ 	.probe		= s3c24xx_serial_probe,
+-	.remove		= __devexit_p(s3c24xx_serial_remove),
++	.remove		= s3c24xx_serial_remove,
+ 	.id_table	= s3c24xx_serial_driver_ids,
+ 	.driver		= {
+ 		.name	= "samsung-uart",
+diff --git a/drivers/tty/serial/sc26xx.c b/drivers/tty/serial/sc26xx.c
+index 9d664242b312..9a40659ec52f 100644
+--- a/drivers/tty/serial/sc26xx.c
++++ b/drivers/tty/serial/sc26xx.c
+@@ -733,7 +733,7 @@ static int __exit sc26xx_driver_remove(struct platform_device *dev)
+ 
+ static struct platform_driver sc26xx_driver = {
+ 	.probe	= sc26xx_probe,
+-	.remove	= __devexit_p(sc26xx_driver_remove),
++	.remove	= sc26xx_driver_remove,
+ 	.driver	= {
+ 		.name	= "SC26xx",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c
+index e821068cd95b..810853f5fd0e 100644
+--- a/drivers/tty/serial/sccnxp.c
++++ b/drivers/tty/serial/sccnxp.c
+@@ -981,7 +981,7 @@ static struct platform_driver sccnxp_uart_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= sccnxp_probe,
+-	.remove		= __devexit_p(sccnxp_remove),
++	.remove		= sccnxp_remove,
+ 	.id_table	= sccnxp_id_table,
+ };
+ module_platform_driver(sccnxp_uart_driver);
+diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c
+index 6ae2a58d62f2..9d979a9e41a2 100644
+--- a/drivers/tty/serial/serial_txx9.c
++++ b/drivers/tty/serial/serial_txx9.c
+@@ -1171,7 +1171,7 @@ static int serial_txx9_resume(struct platform_device *dev)
+ 
+ static struct platform_driver serial_txx9_plat_driver = {
+ 	.probe		= serial_txx9_probe,
+-	.remove		= __devexit_p(serial_txx9_remove),
++	.remove		= serial_txx9_remove,
+ #ifdef CONFIG_PM
+ 	.suspend	= serial_txx9_suspend,
+ 	.resume		= serial_txx9_resume,
+@@ -1261,7 +1261,7 @@ static const struct pci_device_id serial_txx9_pci_tbl[] = {
+ static struct pci_driver serial_txx9_pci_driver = {
+ 	.name		= "serial_txx9",
+ 	.probe		= pciserial_txx9_init_one,
+-	.remove		= __devexit_p(pciserial_txx9_remove_one),
++	.remove		= pciserial_txx9_remove_one,
+ #ifdef CONFIG_PM
+ 	.suspend	= pciserial_txx9_suspend_one,
+ 	.resume		= pciserial_txx9_resume_one,
+diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c
+index a9e2bd1ab534..49849843ff82 100644
+--- a/drivers/tty/serial/sirfsoc_uart.c
++++ b/drivers/tty/serial/sirfsoc_uart.c
+@@ -735,7 +735,7 @@ MODULE_DEVICE_TABLE(of, sirfsoc_serial_of_match);
+ 
+ static struct platform_driver sirfsoc_uart_driver = {
+ 	.probe		= sirfsoc_uart_probe,
+-	.remove		= __devexit_p(sirfsoc_uart_remove),
++	.remove		= sirfsoc_uart_remove,
+ 	.suspend	= sirfsoc_uart_suspend,
+ 	.resume		= sirfsoc_uart_resume,
+ 	.driver		= {
+diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c
+index 505961cfd934..949b2d3dcc55 100644
+--- a/drivers/tty/serial/sunhv.c
++++ b/drivers/tty/serial/sunhv.c
+@@ -636,7 +636,7 @@ static struct platform_driver hv_driver = {
+ 		.of_match_table = hv_match,
+ 	},
+ 	.probe		= hv_probe,
+-	.remove		= __devexit_p(hv_remove),
++	.remove		= hv_remove,
+ };
+ 
+ static int __init sunhv_init(void)
+diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c
+index f0d93eb7e6ec..bbb07bc74f6c 100644
+--- a/drivers/tty/serial/sunsab.c
++++ b/drivers/tty/serial/sunsab.c
+@@ -1100,7 +1100,7 @@ static struct platform_driver sab_driver = {
+ 		.of_match_table = sab_match,
+ 	},
+ 	.probe		= sab_probe,
+-	.remove		= __devexit_p(sab_remove),
++	.remove		= sab_remove,
+ };
+ 
+ static int __init sunsab_init(void)
+diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
+index b97913dcdbff..c0658f0b51a1 100644
+--- a/drivers/tty/serial/sunsu.c
++++ b/drivers/tty/serial/sunsu.c
+@@ -1556,7 +1556,7 @@ static struct platform_driver su_driver = {
+ 		.of_match_table = su_match,
+ 	},
+ 	.probe		= su_probe,
+-	.remove		= __devexit_p(su_remove),
++	.remove		= su_remove,
+ };
+ 
+ static int __init sunsu_init(void)
+diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c
+index babd9470982b..c2ef47594d69 100644
+--- a/drivers/tty/serial/sunzilog.c
++++ b/drivers/tty/serial/sunzilog.c
+@@ -1548,7 +1548,7 @@ static struct platform_driver zs_driver = {
+ 		.of_match_table = zs_match,
+ 	},
+ 	.probe		= zs_probe,
+-	.remove		= __devexit_p(zs_remove),
++	.remove		= zs_remove,
+ };
+ 
+ static int __init sunzilog_init(void)
+diff --git a/drivers/tty/serial/timbuart.c b/drivers/tty/serial/timbuart.c
+index 70f97491d8f2..5fc11f2a8be4 100644
+--- a/drivers/tty/serial/timbuart.c
++++ b/drivers/tty/serial/timbuart.c
+@@ -510,7 +510,7 @@ static struct platform_driver timbuart_platform_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= timbuart_probe,
+-	.remove		= __devexit_p(timbuart_remove),
++	.remove		= timbuart_remove,
+ };
+ 
+ module_platform_driver(timbuart_platform_driver);
+diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
+index 6579ffdd8e9b..1d4438306ae5 100644
+--- a/drivers/tty/serial/uartlite.c
++++ b/drivers/tty/serial/uartlite.c
+@@ -603,7 +603,7 @@ MODULE_ALIAS("platform:uartlite");
+ 
+ static struct platform_driver ulite_platform_driver = {
+ 	.probe = ulite_probe,
+-	.remove = __devexit_p(ulite_remove),
++	.remove = ulite_remove,
+ 	.driver = {
+ 		.owner = THIS_MODULE,
+ 		.name  = "uartlite",
+diff --git a/drivers/tty/serial/vr41xx_siu.c b/drivers/tty/serial/vr41xx_siu.c
+index cf0d9485ec08..9d3bf75e55a4 100644
+--- a/drivers/tty/serial/vr41xx_siu.c
++++ b/drivers/tty/serial/vr41xx_siu.c
+@@ -952,7 +952,7 @@ static int siu_resume(struct platform_device *dev)
+ 
+ static struct platform_driver siu_device_driver = {
+ 	.probe		= siu_probe,
+-	.remove		= __devexit_p(siu_remove),
++	.remove		= siu_remove,
+ 	.suspend	= siu_suspend,
+ 	.resume		= siu_resume,
+ 	.driver		= {
+diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c
+index 4354fe565f64..dbcc909291b2 100644
+--- a/drivers/tty/serial/vt8500_serial.c
++++ b/drivers/tty/serial/vt8500_serial.c
+@@ -652,7 +652,7 @@ static const struct of_device_id wmt_dt_ids[] = {
+ 
+ static struct platform_driver vt8500_platform_driver = {
+ 	.probe  = vt8500_serial_probe,
+-	.remove = __devexit_p(vt8500_serial_remove),
++	.remove = vt8500_serial_remove,
+ 	.driver = {
+ 		.name = "vt8500_serial",
+ 		.owner = THIS_MODULE,

commit 91116cba5da0c33f3093b804e487bea02b830bfb
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:06 2012 -0500
+
+    tty: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Jiri Slaby 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c
+index de25774b5ec6..2f4d84f3c159 100644
+--- a/drivers/tty/cyclades.c
++++ b/drivers/tty/cyclades.c
+@@ -3973,7 +3973,7 @@ static struct pci_driver cy_pci_driver = {
+ 	.name = "cyclades",
+ 	.id_table = cy_pci_dev_id,
+ 	.probe = cy_pci_probe,
+-	.remove = __devexit_p(cy_pci_remove)
++	.remove = cy_pci_remove
+ };
+ #endif
+ 
+diff --git a/drivers/tty/hvc/hvc_opal.c b/drivers/tty/hvc/hvc_opal.c
+index 0d2ea0c224c3..442bfb0d41da 100644
+--- a/drivers/tty/hvc/hvc_opal.c
++++ b/drivers/tty/hvc/hvc_opal.c
+@@ -239,7 +239,7 @@ static int __devexit hvc_opal_remove(struct platform_device *dev)
+ 
+ static struct platform_driver hvc_opal_driver = {
+ 	.probe		= hvc_opal_probe,
+-	.remove		= __devexit_p(hvc_opal_remove),
++	.remove		= hvc_opal_remove,
+ 	.driver		= {
+ 		.name	= hvc_opal_name,
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c
+index 744c3b8eea49..888af583fe75 100644
+--- a/drivers/tty/hvc/hvcs.c
++++ b/drivers/tty/hvc/hvcs.c
+@@ -874,7 +874,7 @@ static int __devexit hvcs_remove(struct vio_dev *dev)
+ static struct vio_driver hvcs_vio_driver = {
+ 	.id_table	= hvcs_driver_table,
+ 	.probe		= hvcs_probe,
+-	.remove		= __devexit_p(hvcs_remove),
++	.remove		= hvcs_remove,
+ 	.name		= hvcs_driver_name,
+ };
+ 
+diff --git a/drivers/tty/isicom.c b/drivers/tty/isicom.c
+index 67f288d7e76a..774e595e1fba 100644
+--- a/drivers/tty/isicom.c
++++ b/drivers/tty/isicom.c
+@@ -168,7 +168,7 @@ static struct pci_driver isicom_driver = {
+ 	.name		= "isicom",
+ 	.id_table	= isicom_pci_tbl,
+ 	.probe		= isicom_probe,
+-	.remove		= __devexit_p(isicom_remove)
++	.remove		= isicom_remove
+ };
+ 
+ static int prev_card = 3;	/*	start servicing isi_card[0]	*/
+diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c
+index d628176fb6d8..e025e065ae9c 100644
+--- a/drivers/tty/moxa.c
++++ b/drivers/tty/moxa.c
+@@ -1033,7 +1033,7 @@ static struct pci_driver moxa_pci_driver = {
+ 	.name = "moxa",
+ 	.id_table = moxa_pcibrds,
+ 	.probe = moxa_pci_probe,
+-	.remove = __devexit_p(moxa_pci_remove)
++	.remove = moxa_pci_remove
+ };
+ #endif /* CONFIG_PCI */
+ 
+diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c
+index 802a248e7ab9..a2fd58c336e4 100644
+--- a/drivers/tty/mxser.c
++++ b/drivers/tty/mxser.c
+@@ -2677,7 +2677,7 @@ static struct pci_driver mxser_driver = {
+ 	.name = "mxser",
+ 	.id_table = mxser_pcibrds,
+ 	.probe = mxser_probe,
+-	.remove = __devexit_p(mxser_remove)
++	.remove = mxser_remove
+ };
+ 
+ static int __init mxser_module_init(void)
+diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c
+index cb764d297756..442efc3d2657 100644
+--- a/drivers/tty/nozomi.c
++++ b/drivers/tty/nozomi.c
+@@ -1908,7 +1908,7 @@ static struct pci_driver nozomi_driver = {
+ 	.name = NOZOMI_NAME,
+ 	.id_table = nozomi_pci_tbl,
+ 	.probe = nozomi_card_init,
+-	.remove = __devexit_p(nozomi_card_exit),
++	.remove = nozomi_card_exit,
+ };
+ 
+ static __init int nozomi_init(void)
+diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c
+index e4b5c39fc4ec..31db13be4697 100644
+--- a/drivers/tty/synclink.c
++++ b/drivers/tty/synclink.c
+@@ -898,7 +898,7 @@ static struct pci_driver synclink_pci_driver = {
+ 	.name		= "synclink",
+ 	.id_table	= synclink_pci_tbl,
+ 	.probe		= synclink_init_one,
+-	.remove		= __devexit_p(synclink_remove_one),
++	.remove		= synclink_remove_one,
+ };
+ 
+ static struct tty_driver *serial_driver;
+diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c
+index 6e4c34011b7e..595f2f48193f 100644
+--- a/drivers/tty/synclink_gt.c
++++ b/drivers/tty/synclink_gt.c
+@@ -110,7 +110,7 @@ static struct pci_driver pci_driver = {
+ 	.name		= "synclink_gt",
+ 	.id_table	= pci_table,
+ 	.probe		= init_one,
+-	.remove		= __devexit_p(remove_one),
++	.remove		= remove_one,
+ };
+ 
+ static bool pci_registered;
+diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c
+index 40745beb2585..71f3eb22c979 100644
+--- a/drivers/tty/synclinkmp.c
++++ b/drivers/tty/synclinkmp.c
+@@ -492,7 +492,7 @@ static struct pci_driver synclinkmp_pci_driver = {
+ 	.name		= "synclinkmp",
+ 	.id_table	= synclinkmp_pci_tbl,
+ 	.probe		= synclinkmp_init_one,
+-	.remove		= __devexit_p(synclinkmp_remove_one),
++	.remove		= synclinkmp_remove_one,
+ };
+ 
+ 

commit 1c979395cada4016a7532e6b4b7c63fc5dcb0745
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:27:12 2012 -0500
+
+    staging: solo6x10: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Mauro Carvalho Chehab 
+    Cc: linux-media@vger.kernel.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/media/solo6x10/core.c b/drivers/staging/media/solo6x10/core.c
+index c0319e6a3806..fd83d6d028bf 100644
+--- a/drivers/staging/media/solo6x10/core.c
++++ b/drivers/staging/media/solo6x10/core.c
+@@ -284,7 +284,7 @@ static int solo_pci_probe(struct pci_dev *pdev,
+ 	return ret;
+ }
+ 
+-static void __devexit solo_pci_remove(struct pci_dev *pdev)
++static void solo_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct solo_dev *solo_dev = pci_get_drvdata(pdev);
+ 

commit 4ce7986ddb6c515edeb41eebef9bd08f90772d67
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:27:11 2012 -0500
+
+    staging: dt3155v4l: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Mauro Carvalho Chehab 
+    Cc: linux-media@vger.kernel.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/media/dt3155v4l/dt3155v4l.c b/drivers/staging/media/dt3155v4l/dt3155v4l.c
+index c8af551626fb..238910373f5c 100644
+--- a/drivers/staging/media/dt3155v4l/dt3155v4l.c
++++ b/drivers/staging/media/dt3155v4l/dt3155v4l.c
+@@ -877,7 +877,7 @@ dt3155_alloc_coherent(struct device *dev, size_t size, int flags)
+ 	return 0;
+ }
+ 
+-static void __devexit
++static void
+ dt3155_free_coherent(struct device *dev)
+ {
+ 	struct dma_coherent_mem *mem = dev->dma_mem;
+@@ -956,7 +956,7 @@ dt3155_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	return err;
+ }
+ 
+-static void __devexit
++static void
+ dt3155_remove(struct pci_dev *pdev)
+ {
+ 	struct dt3155_priv *pd = pci_get_drvdata(pdev);

commit 6dd1119528d68e6f3a04874792048fc7be7611d7
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:27:10 2012 -0500
+
+    staging: lirc: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Mauro Carvalho Chehab 
+    Cc: linux-media@vger.kernel.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/media/lirc/lirc_parallel.c b/drivers/staging/media/lirc/lirc_parallel.c
+index f600c67b326f..ec14bc81851b 100644
+--- a/drivers/staging/media/lirc/lirc_parallel.c
++++ b/drivers/staging/media/lirc/lirc_parallel.c
+@@ -588,7 +588,7 @@ static int lirc_parallel_probe(struct platform_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devexit lirc_parallel_remove(struct platform_device *dev)
++static int lirc_parallel_remove(struct platform_device *dev)
+ {
+ 	return 0;
+ }
+diff --git a/drivers/staging/media/lirc/lirc_serial.c b/drivers/staging/media/lirc/lirc_serial.c
+index e182da4a9796..71e3bf2937f9 100644
+--- a/drivers/staging/media/lirc/lirc_serial.c
++++ b/drivers/staging/media/lirc/lirc_serial.c
+@@ -927,7 +927,7 @@ static int lirc_serial_probe(struct platform_device *dev)
+ 	return result;
+ }
+ 
+-static int __devexit lirc_serial_remove(struct platform_device *dev)
++static int lirc_serial_remove(struct platform_device *dev)
+ {
+ 	free_irq(irq, (void *)&hardware);
+ 
+diff --git a/drivers/staging/media/lirc/lirc_sir.c b/drivers/staging/media/lirc/lirc_sir.c
+index 9c211e72ea5b..a45799874a21 100644
+--- a/drivers/staging/media/lirc/lirc_sir.c
++++ b/drivers/staging/media/lirc/lirc_sir.c
+@@ -1223,7 +1223,7 @@ static int lirc_sir_probe(struct platform_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devexit lirc_sir_remove(struct platform_device *dev)
++static int lirc_sir_remove(struct platform_device *dev)
+ {
+ 	return 0;
+ }

commit 2a91a6d1422f6dc3cb27689e18e16b8c98ec1c73
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:17 2012 -0500
+
+    staging: dt3155v4l: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Mauro Carvalho Chehab 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/media/dt3155v4l/dt3155v4l.c b/drivers/staging/media/dt3155v4l/dt3155v4l.c
+index 15f7468a2475..c8af551626fb 100644
+--- a/drivers/staging/media/dt3155v4l/dt3155v4l.c
++++ b/drivers/staging/media/dt3155v4l/dt3155v4l.c
+@@ -718,7 +718,7 @@ static const struct v4l2_ioctl_ops dt3155_ioctl_ops = {
+ */
+ };
+ 
+-static int __devinit
++static int
+ dt3155_init_board(struct pci_dev *pdev)
+ {
+ 	struct dt3155_priv *pd = pci_get_drvdata(pdev);
+@@ -836,7 +836,7 @@ struct dma_coherent_mem {
+ 	unsigned long	*bitmap;
+ };
+ 
+-static int __devinit
++static int
+ dt3155_alloc_coherent(struct device *dev, size_t size, int flags)
+ {
+ 	struct dma_coherent_mem *mem;
+@@ -891,7 +891,7 @@ dt3155_free_coherent(struct device *dev)
+ 	kfree(mem);
+ }
+ 
+-static int __devinit
++static int
+ dt3155_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ 	int err;

commit ffba1bc963ca5efe05836232bcf2d44916f0e3e9
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:16 2012 -0500
+
+    staging: solo6x10: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Mauro Carvalho Chehab 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/media/solo6x10/core.c b/drivers/staging/media/solo6x10/core.c
+index 3ee9b125797f..c0319e6a3806 100644
+--- a/drivers/staging/media/solo6x10/core.c
++++ b/drivers/staging/media/solo6x10/core.c
+@@ -129,7 +129,7 @@ static void free_solo_dev(struct solo_dev *solo_dev)
+ 	kfree(solo_dev);
+ }
+ 
+-static int __devinit solo_pci_probe(struct pci_dev *pdev,
++static int solo_pci_probe(struct pci_dev *pdev,
+ 				    const struct pci_device_id *id)
+ {
+ 	struct solo_dev *solo_dev;

commit fd8413a2b8328801133e95b58d751bfe48b34303
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:15 2012 -0500
+
+    staging: lirc: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Mauro Carvalho Chehab 
+    Cc: linux-media@vger.kernel.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/media/lirc/lirc_parallel.c b/drivers/staging/media/lirc/lirc_parallel.c
+index 610230f535bf..f600c67b326f 100644
+--- a/drivers/staging/media/lirc/lirc_parallel.c
++++ b/drivers/staging/media/lirc/lirc_parallel.c
+@@ -583,7 +583,7 @@ static struct lirc_driver driver = {
+ 
+ static struct platform_device *lirc_parallel_dev;
+ 
+-static int __devinit lirc_parallel_probe(struct platform_device *dev)
++static int lirc_parallel_probe(struct platform_device *dev)
+ {
+ 	return 0;
+ }
+diff --git a/drivers/staging/media/lirc/lirc_serial.c b/drivers/staging/media/lirc/lirc_serial.c
+index 002f3253b9ef..e182da4a9796 100644
+--- a/drivers/staging/media/lirc/lirc_serial.c
++++ b/drivers/staging/media/lirc/lirc_serial.c
+@@ -841,7 +841,7 @@ static int hardware_init_port(void)
+ 	return 0;
+ }
+ 
+-static int __devinit lirc_serial_probe(struct platform_device *dev)
++static int lirc_serial_probe(struct platform_device *dev)
+ {
+ 	int i, nlow, nhigh, result;
+ 
+diff --git a/drivers/staging/media/lirc/lirc_sir.c b/drivers/staging/media/lirc/lirc_sir.c
+index 420e3df466d5..9c211e72ea5b 100644
+--- a/drivers/staging/media/lirc/lirc_sir.c
++++ b/drivers/staging/media/lirc/lirc_sir.c
+@@ -1218,7 +1218,7 @@ static int init_lirc_sir(void)
+ 	return 0;
+ }
+ 
+-static int __devinit lirc_sir_probe(struct platform_device *dev)
++static int lirc_sir_probe(struct platform_device *dev)
+ {
+ 	return 0;
+ }

commit 01f6f49b0abe4c0ca39e7af577f3dd889f0c6d78
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:20:53 2012 -0500
+
+    staging: lirc: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Mauro Carvalho Chehab 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/media/lirc/lirc_parallel.c b/drivers/staging/media/lirc/lirc_parallel.c
+index dd2bca7b56fa..610230f535bf 100644
+--- a/drivers/staging/media/lirc/lirc_parallel.c
++++ b/drivers/staging/media/lirc/lirc_parallel.c
+@@ -606,7 +606,7 @@ static int lirc_parallel_resume(struct platform_device *dev)
+ 
+ static struct platform_driver lirc_parallel_driver = {
+ 	.probe	= lirc_parallel_probe,
+-	.remove	= __devexit_p(lirc_parallel_remove),
++	.remove	= lirc_parallel_remove,
+ 	.suspend	= lirc_parallel_suspend,
+ 	.resume	= lirc_parallel_resume,
+ 	.driver	= {
+diff --git a/drivers/staging/media/lirc/lirc_serial.c b/drivers/staging/media/lirc/lirc_serial.c
+index 97ef67036e3f..002f3253b9ef 100644
+--- a/drivers/staging/media/lirc/lirc_serial.c
++++ b/drivers/staging/media/lirc/lirc_serial.c
+@@ -1148,7 +1148,7 @@ static int lirc_serial_resume(struct platform_device *dev)
+ 
+ static struct platform_driver lirc_serial_driver = {
+ 	.probe		= lirc_serial_probe,
+-	.remove		= __devexit_p(lirc_serial_remove),
++	.remove		= lirc_serial_remove,
+ 	.suspend	= lirc_serial_suspend,
+ 	.resume		= lirc_serial_resume,
+ 	.driver		= {
+diff --git a/drivers/staging/media/lirc/lirc_sir.c b/drivers/staging/media/lirc/lirc_sir.c
+index 4afc3b419738..420e3df466d5 100644
+--- a/drivers/staging/media/lirc/lirc_sir.c
++++ b/drivers/staging/media/lirc/lirc_sir.c
+@@ -1230,7 +1230,7 @@ static int __devexit lirc_sir_remove(struct platform_device *dev)
+ 
+ static struct platform_driver lirc_sir_driver = {
+ 	.probe		= lirc_sir_probe,
+-	.remove		= __devexit_p(lirc_sir_remove),
++	.remove		= lirc_sir_remove,
+ 	.driver		= {
+ 		.name	= "lirc_sir",
+ 		.owner	= THIS_MODULE,

commit 79fc8d891bf746c0f4da88f6fcca0f2cbcf21094
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:20:52 2012 -0500
+
+    staging: dt3155v4l: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Mauro Carvalho Chehab 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/media/dt3155v4l/dt3155v4l.c b/drivers/staging/media/dt3155v4l/dt3155v4l.c
+index 2e7b711c8501..15f7468a2475 100644
+--- a/drivers/staging/media/dt3155v4l/dt3155v4l.c
++++ b/drivers/staging/media/dt3155v4l/dt3155v4l.c
+@@ -983,7 +983,7 @@ static struct pci_driver pci_driver = {
+ 	.name = DT3155_NAME,
+ 	.id_table = pci_ids,
+ 	.probe = dt3155_probe,
+-	.remove = __devexit_p(dt3155_remove),
++	.remove = dt3155_remove,
+ };
+ 
+ module_pci_driver(pci_driver);

commit 29c354420e7af210115bee8e5e5d60ba0f3442a6
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:39 2012 -0500
+
+    ipack: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/ipack/carriers/tpci200.c b/drivers/ipack/carriers/tpci200.c
+index 450a61272fcf..0246b1fddffe 100644
+--- a/drivers/ipack/carriers/tpci200.c
++++ b/drivers/ipack/carriers/tpci200.c
+@@ -599,7 +599,7 @@ static void __tpci200_pci_remove(struct tpci200_board *tpci200)
+ 	kfree(tpci200);
+ }
+ 
+-static void __devexit tpci200_pci_remove(struct pci_dev *dev)
++static void tpci200_pci_remove(struct pci_dev *dev)
+ {
+ 	struct tpci200_board *tpci200 = pci_get_drvdata(dev);
+ 

commit d79251f0fc2fdb7587c99617aae0bf52ff6c5510
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:25:25 2012 -0500
+
+    ipack: remove use of __devinitconst
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitconst is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/include/linux/ipack.h b/include/linux/ipack.h
+index a360c73129a6..fea12cbb2aeb 100644
+--- a/include/linux/ipack.h
++++ b/include/linux/ipack.h
+@@ -229,8 +229,7 @@ void ipack_device_unregister(struct ipack_device *dev);
+  * in a generic manner.
+  */
+ #define DEFINE_IPACK_DEVICE_TABLE(_table) \
+-	const struct ipack_device_id _table[] __devinitconst
+-
++	const struct ipack_device_id _table[]
+ /**
+  * IPACK_DEVICE - macro used to describe a specific IndustryPack device
+  * @_format: the format version (currently either 1 or 2, 8 bit value)

commit c5dee46c8fa5422e2c2217c9f05f7c3f6f3d13fb
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:31 2012 -0500
+
+    ipack: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/ipack/carriers/tpci200.c b/drivers/ipack/carriers/tpci200.c
+index c1a19b274c23..450a61272fcf 100644
+--- a/drivers/ipack/carriers/tpci200.c
++++ b/drivers/ipack/carriers/tpci200.c
+@@ -618,7 +618,7 @@ static struct pci_driver tpci200_pci_drv = {
+ 	.name = "tpci200",
+ 	.id_table = tpci200_idtable,
+ 	.probe = tpci200_pci_probe,
+-	.remove = __devexit_p(tpci200_pci_remove),
++	.remove = tpci200_pci_remove,
+ };
+ 
+ module_pci_driver(tpci200_pci_drv);

commit 0d7fe14f69a7a7322a72b4d76f835fbe4000fe8c
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:58 2012 -0500
+
+    staging: vt6656: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c
+index b3e674638cbe..9a81839d69bb 100644
+--- a/drivers/staging/vt6656/main_usb.c
++++ b/drivers/staging/vt6656/main_usb.c
+@@ -1202,7 +1202,7 @@ device_release_WPADEV(pDevice);
+     return 0;
+ }
+ 
+-static void __devexit vt6656_disconnect(struct usb_interface *intf)
++static void vt6656_disconnect(struct usb_interface *intf)
+ {
+ 	PSDevice device = usb_get_intfdata(intf);
+ 

commit fdfa2339c121ef34361cb8016a7b271f54cd3fc8
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:56 2012 -0500
+
+    staging: crystalhd: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/crystalhd/crystalhd_cmds.c b/drivers/staging/crystalhd/crystalhd_cmds.c
+index 294f9922c2e7..ed99daa6ef46 100644
+--- a/drivers/staging/crystalhd/crystalhd_cmds.c
++++ b/drivers/staging/crystalhd/crystalhd_cmds.c
+@@ -986,7 +986,7 @@ enum BC_STATUS crystalhd_setup_cmd_context(struct crystalhd_cmd *ctx,
+  *
+  * Called at the time of driver un-load.
+  */
+-enum BC_STATUS __devexit crystalhd_delete_cmd_context(struct crystalhd_cmd *ctx)
++enum BC_STATUS crystalhd_delete_cmd_context(struct crystalhd_cmd *ctx)
+ {
+ 	BCMLOG(BCMLOG_DBG, "Deleting Command context..\n");
+ 
+diff --git a/drivers/staging/crystalhd/crystalhd_lnx.c b/drivers/staging/crystalhd/crystalhd_lnx.c
+index de2b0266596b..85f51fb18425 100644
+--- a/drivers/staging/crystalhd/crystalhd_lnx.c
++++ b/drivers/staging/crystalhd/crystalhd_lnx.c
+@@ -418,7 +418,7 @@ static int chd_dec_init_chdev(struct crystalhd_adp *adp)
+ 	return rc;
+ }
+ 
+-static void __devexit chd_dec_release_chdev(struct crystalhd_adp *adp)
++static void chd_dec_release_chdev(struct crystalhd_adp *adp)
+ {
+ 	struct crystalhd_ioctl_data *temp = NULL;
+ 	if (!adp)
+@@ -496,7 +496,7 @@ static int chd_pci_reserve_mem(struct crystalhd_adp *pinfo)
+ 	return 0;
+ }
+ 
+-static void __devexit chd_pci_release_mem(struct crystalhd_adp *pinfo)
++static void chd_pci_release_mem(struct crystalhd_adp *pinfo)
+ {
+ 	if (!pinfo)
+ 		return;
+@@ -511,7 +511,7 @@ static void __devexit chd_pci_release_mem(struct crystalhd_adp *pinfo)
+ }
+ 
+ 
+-static void __devexit chd_dec_pci_remove(struct pci_dev *pdev)
++static void chd_dec_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct crystalhd_adp *pinfo;
+ 	enum BC_STATUS sts = BC_STS_SUCCESS;

commit 8db72ff52144d0ed32c15927c9fd86859453d6d1
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:55 2012 -0500
+
+    staging: xgifb: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
+index 044374e3ac98..e0f745de7e7a 100644
+--- a/drivers/staging/xgifb/XGI_main_26.c
++++ b/drivers/staging/xgifb/XGI_main_26.c
+@@ -2103,7 +2103,7 @@ static int xgifb_probe(struct pci_dev *pdev,
+ /*                PCI DEVICE HANDLING                */
+ /*****************************************************/
+ 
+-static void __devexit xgifb_remove(struct pci_dev *pdev)
++static void xgifb_remove(struct pci_dev *pdev)
+ {
+ 	struct xgifb_video_info *xgifb_info = pci_get_drvdata(pdev);
+ 	struct fb_info *fb_info = xgifb_info->fb_info;

commit f4e1b7c830f813884679dc63bed3a708d0f5653e
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:53 2012 -0500
+
+    staging: vt6655: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c
+index 4e40bc9348d4..453c83d7fe8c 100644
+--- a/drivers/staging/vt6655/device_main.c
++++ b/drivers/staging/vt6655/device_main.c
+@@ -356,7 +356,7 @@ static char* get_chip_name(int chip_id)
+ 	return chip_info_table[i].name;
+ }
+ 
+-static void __devexit vt6655_remove(struct pci_dev *pcid)
++static void vt6655_remove(struct pci_dev *pcid)
+ {
+ 	PSDevice pDevice = pci_get_drvdata(pcid);
+ 

commit f21a8247641329c40ab17b2d70c492c060bb3573
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:52 2012 -0500
+
+    staging: vme: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Martyn Welch 
+    Cc: Manohar Vanga 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/vme/devices/vme_pio2_core.c b/drivers/staging/vme/devices/vme_pio2_core.c
+index 35880a3353fd..0331178ca3b3 100644
+--- a/drivers/staging/vme/devices/vme_pio2_core.c
++++ b/drivers/staging/vme/devices/vme_pio2_core.c
+@@ -43,7 +43,7 @@ static bool loopback;
+ 
+ static int pio2_match(struct vme_dev *);
+ static int pio2_probe(struct vme_dev *);
+-static int __devexit pio2_remove(struct vme_dev *);
++static int pio2_remove(struct vme_dev *);
+ 
+ static int pio2_get_led(struct pio2_card *card)
+ {
+@@ -455,7 +455,7 @@ static int pio2_probe(struct vme_dev *vdev)
+ 	return retval;
+ }
+ 
+-static int __devexit pio2_remove(struct vme_dev *vdev)
++static int pio2_remove(struct vme_dev *vdev)
+ {
+ 	int vec;
+ 	int i;
+diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c
+index e36211056272..4ef852c4c4e1 100644
+--- a/drivers/staging/vme/devices/vme_user.c
++++ b/drivers/staging/vme/devices/vme_user.c
+@@ -138,7 +138,7 @@ static long vme_user_unlocked_ioctl(struct file *, unsigned int, unsigned long);
+ 
+ static int vme_user_match(struct vme_dev *);
+ static int vme_user_probe(struct vme_dev *);
+-static int __devexit vme_user_remove(struct vme_dev *);
++static int vme_user_remove(struct vme_dev *);
+ 
+ static const struct file_operations vme_user_fops = {
+ 	.open = vme_user_open,
+@@ -846,7 +846,7 @@ static int vme_user_probe(struct vme_dev *vdev)
+ 	return err;
+ }
+ 
+-static int __devexit vme_user_remove(struct vme_dev *dev)
++static int vme_user_remove(struct vme_dev *dev)
+ {
+ 	int i;
+ 

commit 37a6520057c98d725be716497ba93b7380c9934f
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:51 2012 -0500
+
+    staging: tidspbridge: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c
+index 053479339935..e6f31d817d6b 100644
+--- a/drivers/staging/tidspbridge/rmgr/drv_interface.c
++++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c
+@@ -527,7 +527,7 @@ static int omap34_xx_bridge_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit omap34_xx_bridge_remove(struct platform_device *pdev)
++static int omap34_xx_bridge_remove(struct platform_device *pdev)
+ {
+ 	dev_t devno;
+ 	int status = 0;

commit b18d5dc8257cb2c47dea2e04168d24aea18d55c0
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:50 2012 -0500
+
+    staging: ste_rmi4: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
+index bc7a561b4ad6..299f51810199 100644
+--- a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
++++ b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
+@@ -1022,7 +1022,7 @@ static int synaptics_rmi4_probe
+  * This function uses to remove the i2c-client
+  * touchscreen driver and returns integer.
+  */
+-static int __devexit synaptics_rmi4_remove(struct i2c_client *client)
++static int synaptics_rmi4_remove(struct i2c_client *client)
+ {
+ 	struct synaptics_rmi4_data *rmi4_data = i2c_get_clientdata(client);
+ 	const struct synaptics_rmi4_platform_data *pdata = rmi4_data->board;

commit 361a2018596604e8e101aa86f296026760a705e1
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:49 2012 -0500
+
+    staging: sm7xxfb: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c
+index 3c0ba60ec4f2..0764bbbfd497 100644
+--- a/drivers/staging/sm7xxfb/sm7xxfb.c
++++ b/drivers/staging/sm7xxfb/sm7xxfb.c
+@@ -928,7 +928,7 @@ static DEFINE_PCI_DEVICE_TABLE(smtcfb_pci_table) = {
+ 	{0,}
+ };
+ 
+-static void __devexit smtcfb_pci_remove(struct pci_dev *pdev)
++static void smtcfb_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct smtcfb_info *sfb;
+ 

commit ecb4f3879d197ed8c248592acfc2741280d20045
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:48 2012 -0500
+
+    staging: slicoss: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c
+index 30def84cea22..78578ee59557 100644
+--- a/drivers/staging/slicoss/slicoss.c
++++ b/drivers/staging/slicoss/slicoss.c
+@@ -3046,7 +3046,7 @@ static void slic_card_cleanup(struct sliccard *card)
+ 	kfree(card);
+ }
+ 
+-static void __devexit slic_entry_remove(struct pci_dev *pcidev)
++static void slic_entry_remove(struct pci_dev *pcidev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pcidev);
+ 	u32 mmio_start = 0;

commit a46303ca3bbbbe153630bc4882f83c38c949d171
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:47 2012 -0500
+
+    staging: sbe-2t3e3: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/sbe-2t3e3/module.c b/drivers/staging/sbe-2t3e3/module.c
+index 33db820dc6a1..ae7af397a992 100644
+--- a/drivers/staging/sbe-2t3e3/module.c
++++ b/drivers/staging/sbe-2t3e3/module.c
+@@ -117,7 +117,7 @@ static int t3e3_init_channel(struct channel *channel, struct pci_dev *pdev, stru
+ 	return err;
+ }
+ 
+-static void __devexit t3e3_remove_card(struct pci_dev *pdev)
++static void t3e3_remove_card(struct pci_dev *pdev)
+ {
+ 	struct channel *channel0 = pci_get_drvdata(pdev);
+ 	struct card *card = channel0->card;

commit 434bd03509dd07cc6f551c46c3be66bb21030f05
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:43 2012 -0500
+
+    staging: omap-thermal: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/omap-thermal/omap-bandgap.c b/drivers/staging/omap-thermal/omap-bandgap.c
+index e8c747efe0d1..8346e3450f83 100644
+--- a/drivers/staging/omap-thermal/omap-bandgap.c
++++ b/drivers/staging/omap-thermal/omap-bandgap.c
+@@ -998,7 +998,7 @@ int omap_bandgap_probe(struct platform_device *pdev)
+ }
+ 
+ static
+-int __devexit omap_bandgap_remove(struct platform_device *pdev)
++int omap_bandgap_remove(struct platform_device *pdev)
+ {
+ 	struct omap_bandgap *bg_ptr = platform_get_drvdata(pdev);
+ 	int i;

commit f7e2f350f16f3fc2cb7920ccc202ba5310daed3e
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:42 2012 -0500
+
+    staging: octeon: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
+index 9276667f4b34..ef32dc1bbc80 100644
+--- a/drivers/staging/octeon/ethernet.c
++++ b/drivers/staging/octeon/ethernet.c
+@@ -813,7 +813,7 @@ static int cvm_oct_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit cvm_oct_remove(struct platform_device *pdev)
++static int cvm_oct_remove(struct platform_device *pdev)
+ {
+ 	int port;
+ 

commit 0cae4685a602a8bf9a86fa2417d6c035c09d6341
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:40 2012 -0500
+
+    staging: net: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/net/pc300_drv.c b/drivers/staging/net/pc300_drv.c
+index 142eab493594..7281797ffe9d 100644
+--- a/drivers/staging/net/pc300_drv.c
++++ b/drivers/staging/net/pc300_drv.c
+@@ -3607,7 +3607,7 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	return err;
+ }
+ 
+-static void __devexit cpc_remove_one(struct pci_dev *pdev)
++static void cpc_remove_one(struct pci_dev *pdev)
+ {
+ 	pc300_t *card = pci_get_drvdata(pdev);
+ 

commit 8aa1be45f9cacc95efd0720bbed497d15ff7cc31
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:38 2012 -0500
+
+    staging: imx-drm: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
+index b1fcf0225705..677e665ca86d 100644
+--- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c
++++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
+@@ -1136,7 +1136,7 @@ static int ipu_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit ipu_remove(struct platform_device *pdev)
++static int ipu_remove(struct platform_device *pdev)
+ {
+ 	struct ipu_soc *ipu = platform_get_drvdata(pdev);
+ 	struct resource *res;
+diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c
+index 46f137f1c2c0..1892006526b5 100644
+--- a/drivers/staging/imx-drm/ipuv3-crtc.c
++++ b/drivers/staging/imx-drm/ipuv3-crtc.c
+@@ -554,7 +554,7 @@ static int ipu_drm_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit ipu_drm_remove(struct platform_device *pdev)
++static int ipu_drm_remove(struct platform_device *pdev)
+ {
+ 	struct ipu_crtc *ipu_crtc = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/staging/imx-drm/parallel-display.c b/drivers/staging/imx-drm/parallel-display.c
+index 9b9f0fe4f5ca..a8064fcc03d1 100644
+--- a/drivers/staging/imx-drm/parallel-display.c
++++ b/drivers/staging/imx-drm/parallel-display.c
+@@ -235,7 +235,7 @@ static int imx_pd_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit imx_pd_remove(struct platform_device *pdev)
++static int imx_pd_remove(struct platform_device *pdev)
+ {
+ 	struct imx_parallel_display *imxpd = platform_get_drvdata(pdev);
+ 	struct drm_connector *connector = &imxpd->connector;

commit 8b1e01264c2f1777c8a20637e91943d723ee8f35
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:24:46 2012 -0500
+
+    staging: sbe-2t3e3: remove use of __devinitdata
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitdata is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/sbe-2t3e3/module.c b/drivers/staging/sbe-2t3e3/module.c
+index 69b451ee830b..33db820dc6a1 100644
+--- a/drivers/staging/sbe-2t3e3/module.c
++++ b/drivers/staging/sbe-2t3e3/module.c
+@@ -188,7 +188,7 @@ static int t3e3_init_card(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	return err;
+ }
+ 
+-static struct pci_device_id t3e3_pci_tbl[] __devinitdata = {
++static struct pci_device_id t3e3_pci_tbl[] = {
+ 	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,
+ 	  PCI_VENDOR_ID_SBE, PCI_SUBDEVICE_ID_SBE_T3E3, 0, 0, 0 },
+ 	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,

commit 4cd2b92de30f511aa6b203cbff2692aa09dc1226
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:14 2012 -0500
+
+    staging: sbe-2t3e3: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/sbe-2t3e3/module.c b/drivers/staging/sbe-2t3e3/module.c
+index 8e1a043b6b9f..69b451ee830b 100644
+--- a/drivers/staging/sbe-2t3e3/module.c
++++ b/drivers/staging/sbe-2t3e3/module.c
+@@ -52,7 +52,7 @@ static void t3e3_remove_channel(struct channel *channel)
+ 	pci_set_drvdata(pdev, NULL);
+ }
+ 
+-static int __devinit t3e3_init_channel(struct channel *channel, struct pci_dev *pdev, struct card *card)
++static int t3e3_init_channel(struct channel *channel, struct pci_dev *pdev, struct card *card)
+ {
+ 	struct net_device *dev;
+ 	unsigned int val;
+@@ -131,7 +131,7 @@ static void __devexit t3e3_remove_card(struct pci_dev *pdev)
+ 	kfree(card);
+ }
+ 
+-static int __devinit t3e3_init_card(struct pci_dev *pdev, const struct pci_device_id *ent)
++static int t3e3_init_card(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ 	/* pdev points to channel #0 */
+ 	struct pci_dev *pdev1 = NULL;

commit db53ac71fe7e16add7be58985a1eb2aeb46dc8b0
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:13 2012 -0500
+
+    staging: omap-thermal: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/omap-thermal/omap-bandgap.c b/drivers/staging/omap-thermal/omap-bandgap.c
+index c17bc955c553..e8c747efe0d1 100644
+--- a/drivers/staging/omap-thermal/omap-bandgap.c
++++ b/drivers/staging/omap-thermal/omap-bandgap.c
+@@ -849,7 +849,7 @@ static struct omap_bandgap *omap_bandgap_build(struct platform_device *pdev)
+ }
+ 
+ static
+-int __devinit omap_bandgap_probe(struct platform_device *pdev)
++int omap_bandgap_probe(struct platform_device *pdev)
+ {
+ 	struct omap_bandgap *bg_ptr;
+ 	int clk_rate, ret = 0, i;

commit c4aabf8d323bb69934f4e627a43042c5bbfcd3cc
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:11 2012 -0500
+
+    staging: imx-drm: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
+index 937c0b61b318..b1fcf0225705 100644
+--- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c
++++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
+@@ -1013,7 +1013,7 @@ static void ipu_irq_exit(struct ipu_soc *ipu)
+ 	irq_free_descs(ipu->irq_start, IPU_NUM_IRQS);
+ }
+ 
+-static int __devinit ipu_probe(struct platform_device *pdev)
++static int ipu_probe(struct platform_device *pdev)
+ {
+ 	const struct of_device_id *of_id =
+ 			of_match_device(imx_ipu_dt_ids, &pdev->dev);
+diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c
+index 33c82fb961e9..46f137f1c2c0 100644
+--- a/drivers/staging/imx-drm/ipuv3-crtc.c
++++ b/drivers/staging/imx-drm/ipuv3-crtc.c
+@@ -530,7 +530,7 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
+ 	return ret;
+ }
+ 
+-static int __devinit ipu_drm_probe(struct platform_device *pdev)
++static int ipu_drm_probe(struct platform_device *pdev)
+ {
+ 	struct ipu_client_platformdata *pdata = pdev->dev.platform_data;
+ 	struct ipu_crtc *ipu_crtc;
+diff --git a/drivers/staging/imx-drm/parallel-display.c b/drivers/staging/imx-drm/parallel-display.c
+index ba53778e2f0c..9b9f0fe4f5ca 100644
+--- a/drivers/staging/imx-drm/parallel-display.c
++++ b/drivers/staging/imx-drm/parallel-display.c
+@@ -189,7 +189,7 @@ static int imx_pd_register(struct imx_parallel_display *imxpd)
+ 	return 0;
+ }
+ 
+-static int __devinit imx_pd_probe(struct platform_device *pdev)
++static int imx_pd_probe(struct platform_device *pdev)
+ {
+ 	struct device_node *np = pdev->dev.of_node;
+ 	const u8 *edidp;

commit 349affa1cec548820ba417523000f303527e0c04
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:10 2012 -0500
+
+    staging: crystalhd: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/crystalhd/crystalhd_cmds.c b/drivers/staging/crystalhd/crystalhd_cmds.c
+index 8b71131732d8..294f9922c2e7 100644
+--- a/drivers/staging/crystalhd/crystalhd_cmds.c
++++ b/drivers/staging/crystalhd/crystalhd_cmds.c
+@@ -951,7 +951,7 @@ enum BC_STATUS crystalhd_user_close(struct crystalhd_cmd *ctx, struct crystalhd_
+  *
+  * Called at the time of driver load.
+  */
+-enum BC_STATUS __devinit crystalhd_setup_cmd_context(struct crystalhd_cmd *ctx,
++enum BC_STATUS crystalhd_setup_cmd_context(struct crystalhd_cmd *ctx,
+ 				    struct crystalhd_adp *adp)
+ {
+ 	int i = 0;
+diff --git a/drivers/staging/crystalhd/crystalhd_lnx.c b/drivers/staging/crystalhd/crystalhd_lnx.c
+index a216dae14eea..de2b0266596b 100644
+--- a/drivers/staging/crystalhd/crystalhd_lnx.c
++++ b/drivers/staging/crystalhd/crystalhd_lnx.c
+@@ -353,7 +353,7 @@ static const struct file_operations chd_dec_fops = {
+ 	.llseek = noop_llseek,
+ };
+ 
+-static int __devinit chd_dec_init_chdev(struct crystalhd_adp *adp)
++static int chd_dec_init_chdev(struct crystalhd_adp *adp)
+ {
+ 	struct crystalhd_ioctl_data *temp;
+ 	struct device *dev;
+@@ -443,7 +443,7 @@ static void __devexit chd_dec_release_chdev(struct crystalhd_adp *adp)
+ 	crystalhd_delete_elem_pool(adp);
+ }
+ 
+-static int __devinit chd_pci_reserve_mem(struct crystalhd_adp *pinfo)
++static int chd_pci_reserve_mem(struct crystalhd_adp *pinfo)
+ {
+ 	int rc;
+ 	unsigned long bar2 = pci_resource_start(pinfo->pdev, 2);
+@@ -537,7 +537,7 @@ static void __devexit chd_dec_pci_remove(struct pci_dev *pdev)
+ 	g_adp_info = NULL;
+ }
+ 
+-static int __devinit chd_dec_pci_probe(struct pci_dev *pdev,
++static int chd_dec_pci_probe(struct pci_dev *pdev,
+ 			     const struct pci_device_id *entry)
+ {
+ 	struct crystalhd_adp *pinfo;
+diff --git a/drivers/staging/crystalhd/crystalhd_misc.c b/drivers/staging/crystalhd/crystalhd_misc.c
+index b3a637814a16..a5f109c632dc 100644
+--- a/drivers/staging/crystalhd/crystalhd_misc.c
++++ b/drivers/staging/crystalhd/crystalhd_misc.c
+@@ -960,7 +960,7 @@ void crystalhd_destroy_dio_pool(struct crystalhd_adp *adp)
+  * Create general purpose list element pool to hold pending,
+  * and active requests.
+  */
+-int __devinit crystalhd_create_elem_pool(struct crystalhd_adp *adp,
++int crystalhd_create_elem_pool(struct crystalhd_adp *adp,
+ 		uint32_t pool_size)
+ {
+ 	uint32_t i;

commit c42ef5d21fc16e44361893eca333344022ede328
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:09 2012 -0500
+
+    staging: net: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/net/pc300_drv.c b/drivers/staging/net/pc300_drv.c
+index b8e0480abad1..142eab493594 100644
+--- a/drivers/staging/net/pc300_drv.c
++++ b/drivers/staging/net/pc300_drv.c
+@@ -3409,7 +3409,7 @@ static void cpc_init_card(pc300_t * card)
+ 	board_nbr++;
+ }
+ 
+-static int __devinit
++static int
+ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ 	int err, eeprom_outdated = 0;

commit 4f2409060aba27120f601b2675e1e38754522b7c
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:06 2012 -0500
+
+    staging: octeon: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
+index b48196a98412..9276667f4b34 100644
+--- a/drivers/staging/octeon/ethernet.c
++++ b/drivers/staging/octeon/ethernet.c
+@@ -169,7 +169,7 @@ static void cvm_oct_periodic_worker(struct work_struct *work)
+ 		queue_delayed_work(cvm_oct_poll_queue, &priv->port_periodic_work, HZ);
+  }
+ 
+-static __devinit void cvm_oct_configure_common_hw(void)
++static void cvm_oct_configure_common_hw(void)
+ {
+ 	/* Setup the FPA */
+ 	cvmx_fpa_enable();
+@@ -586,7 +586,7 @@ static const struct net_device_ops cvm_oct_pow_netdev_ops = {
+ 
+ extern void octeon_mdiobus_force_mod_depencency(void);
+ 
+-static struct device_node * __devinit cvm_oct_of_get_child(const struct device_node *parent,
++static struct device_node *cvm_oct_of_get_child(const struct device_node *parent,
+ 							   int reg_val)
+ {
+ 	struct device_node *node = NULL;
+@@ -604,7 +604,7 @@ static struct device_node * __devinit cvm_oct_of_get_child(const struct device_n
+ 	return node;
+ }
+ 
+-static struct device_node * __devinit cvm_oct_node_for_port(struct device_node *pip,
++static struct device_node *cvm_oct_node_for_port(struct device_node *pip,
+ 							    int interface, int port)
+ {
+ 	struct device_node *ni, *np;
+@@ -619,7 +619,7 @@ static struct device_node * __devinit cvm_oct_node_for_port(struct device_node *
+ 	return np;
+ }
+ 
+-static int __devinit cvm_oct_probe(struct platform_device *pdev)
++static int cvm_oct_probe(struct platform_device *pdev)
+ {
+ 	int num_interfaces;
+ 	int interface;

commit df1f35ebffc3739e43b96d1df689c2ecabf09552
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:03 2012 -0500
+
+    staging: sep: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/sep/sep_main.c b/drivers/staging/sep/sep_main.c
+index 2c8df0e6b6d0..15c6e3d9437c 100644
+--- a/drivers/staging/sep/sep_main.c
++++ b/drivers/staging/sep/sep_main.c
+@@ -4112,7 +4112,7 @@ static int sep_register_driver_with_fs(struct sep_device *sep)
+  *Attempt to set up and configure a SEP device that has been
+  *discovered by the PCI layer. Allocates all required resources.
+  */
+-static int __devinit sep_probe(struct pci_dev *pdev,
++static int sep_probe(struct pci_dev *pdev,
+ 	const struct pci_device_id *ent)
+ {
+ 	int error = 0;

commit a0c2feb18035dfe90bac813504bf1030d54b68f0
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:02 2012 -0500
+
+    staging: slicoss: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c
+index ad85e6e34c52..30def84cea22 100644
+--- a/drivers/staging/slicoss/slicoss.c
++++ b/drivers/staging/slicoss/slicoss.c
+@@ -3678,7 +3678,7 @@ static u32 slic_card_locate(struct adapter *adapter)
+ 	return 0;
+ }
+ 
+-static int __devinit slic_entry_probe(struct pci_dev *pcidev,
++static int slic_entry_probe(struct pci_dev *pcidev,
+ 			       const struct pci_device_id *pci_tbl_entry)
+ {
+ 	static int cards_found;

commit abe118b48f6ba7e28bd97c84eccb4484a2441732
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:01 2012 -0500
+
+    staging: sm7xxfb: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c
+index 5272ba94a790..3c0ba60ec4f2 100644
+--- a/drivers/staging/sm7xxfb/sm7xxfb.c
++++ b/drivers/staging/sm7xxfb/sm7xxfb.c
+@@ -768,7 +768,7 @@ static inline void sm7xx_init_hw(void)
+ 	outb_p(0x11, 0x3c5);
+ }
+ 
+-static int __devinit smtcfb_pci_probe(struct pci_dev *pdev,
++static int smtcfb_pci_probe(struct pci_dev *pdev,
+ 				   const struct pci_device_id *ent)
+ {
+ 	struct smtcfb_info *sfb;

commit 8cd3a48ffbb05f2d41bef61c0681fe44eeaabb2e
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:00 2012 -0500
+
+    staging: ste_rmi4: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
+index 0b717275f10c..bc7a561b4ad6 100644
+--- a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
++++ b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
+@@ -879,7 +879,7 @@ static int synaptics_rmi4_i2c_query_device(struct synaptics_rmi4_data *pdata)
+  * the rmi4 Physical Device Table and enumerate any rmi4 functions that
+  * have data sources associated with them.
+  */
+-static int __devinit synaptics_rmi4_probe
++static int synaptics_rmi4_probe
+ 	(struct i2c_client *client, const struct i2c_device_id *dev_id)
+ {
+ 	int retval;

commit 673abc4411ef9391b949aa43cc77fe42d6a8571d
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:59 2012 -0500
+
+    staging: tidspbridge: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c
+index e33c64312b25..053479339935 100644
+--- a/drivers/staging/tidspbridge/rmgr/drv_interface.c
++++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c
+@@ -471,7 +471,7 @@ static int omap3_bridge_startup(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devinit omap34_xx_bridge_probe(struct platform_device *pdev)
++static int omap34_xx_bridge_probe(struct platform_device *pdev)
+ {
+ 	int err;
+ 	dev_t dev = 0;

commit d7e530d26ba3dc59753e0d0b04fecdbb1f394c38
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:56 2012 -0500
+
+    staging: vme: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Martyn Welch 
+    Cc: Manohar Vanga 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/vme/devices/vme_pio2.h b/drivers/staging/vme/devices/vme_pio2.h
+index 72d9ce0bcb45..d5d94c43c074 100644
+--- a/drivers/staging/vme/devices/vme_pio2.h
++++ b/drivers/staging/vme/devices/vme_pio2.h
+@@ -243,7 +243,7 @@ struct pio2_card {
+ int pio2_cntr_reset(struct pio2_card *);
+ 
+ int pio2_gpio_reset(struct pio2_card *);
+-int __devinit pio2_gpio_init(struct pio2_card *);
++int pio2_gpio_init(struct pio2_card *);
+ void pio2_gpio_exit(struct pio2_card *);
+ 
+ #endif /* _VME_PIO2_H_ */
+diff --git a/drivers/staging/vme/devices/vme_pio2_core.c b/drivers/staging/vme/devices/vme_pio2_core.c
+index 35c5a147849f..35880a3353fd 100644
+--- a/drivers/staging/vme/devices/vme_pio2_core.c
++++ b/drivers/staging/vme/devices/vme_pio2_core.c
+@@ -42,7 +42,7 @@ static int variant_num;
+ static bool loopback;
+ 
+ static int pio2_match(struct vme_dev *);
+-static int __devinit pio2_probe(struct vme_dev *);
++static int pio2_probe(struct vme_dev *);
+ static int __devexit pio2_remove(struct vme_dev *);
+ 
+ static int pio2_get_led(struct pio2_card *card)
+@@ -222,7 +222,7 @@ static int pio2_match(struct vme_dev *vdev)
+ 	return 1;
+ }
+ 
+-static int __devinit pio2_probe(struct vme_dev *vdev)
++static int pio2_probe(struct vme_dev *vdev)
+ {
+ 	struct pio2_card *card;
+ 	int retval;
+diff --git a/drivers/staging/vme/devices/vme_pio2_gpio.c b/drivers/staging/vme/devices/vme_pio2_gpio.c
+index ad76a477825b..69d880517e07 100644
+--- a/drivers/staging/vme/devices/vme_pio2_gpio.c
++++ b/drivers/staging/vme/devices/vme_pio2_gpio.c
+@@ -186,7 +186,7 @@ int pio2_gpio_reset(struct pio2_card *card)
+ 	return 0;
+ }
+ 
+-int __devinit pio2_gpio_init(struct pio2_card *card)
++int pio2_gpio_init(struct pio2_card *card)
+ {
+ 	int retval = 0;
+ 	char *label;
+diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c
+index 8209c2d3c151..e36211056272 100644
+--- a/drivers/staging/vme/devices/vme_user.c
++++ b/drivers/staging/vme/devices/vme_user.c
+@@ -137,7 +137,7 @@ static loff_t vme_user_llseek(struct file *, loff_t, int);
+ static long vme_user_unlocked_ioctl(struct file *, unsigned int, unsigned long);
+ 
+ static int vme_user_match(struct vme_dev *);
+-static int __devinit vme_user_probe(struct vme_dev *);
++static int vme_user_probe(struct vme_dev *);
+ static int __devexit vme_user_remove(struct vme_dev *);
+ 
+ static const struct file_operations vme_user_fops = {
+@@ -673,7 +673,7 @@ static int vme_user_match(struct vme_dev *vdev)
+  * as practical. We will therefore reserve the buffers and request the images
+  * here so that we don't have to do it later.
+  */
+-static int __devinit vme_user_probe(struct vme_dev *vdev)
++static int vme_user_probe(struct vme_dev *vdev)
+ {
+ 	int i, err;
+ 	char name[12];

commit 59cb218e7d3e58dd466f14fe341901695e6a65f4
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:55 2012 -0500
+
+    staging: vt6656: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c
+index f3c44aefa41a..b3e674638cbe 100644
+--- a/drivers/staging/vt6656/main_usb.c
++++ b/drivers/staging/vt6656/main_usb.c
+@@ -711,7 +711,7 @@ static const struct net_device_ops device_netdev_ops = {
+     .ndo_set_rx_mode	    = device_set_multi,
+ };
+ 
+-static int __devinit
++static int
+ vt6656_probe(struct usb_interface *intf, const struct usb_device_id *id)
+ {
+ 	u8 fake_mac[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01};

commit a1179b20ed939792635aacefcbc676d089a9ae2d
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:54 2012 -0500
+
+    staging: vt6655: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c
+index 9e3b3f2bbe53..4e40bc9348d4 100644
+--- a/drivers/staging/vt6655/device_main.c
++++ b/drivers/staging/vt6655/device_main.c
+@@ -902,7 +902,7 @@ static const struct net_device_ops device_netdev_ops = {
+ 	.ndo_set_rx_mode	= device_set_multi,
+ };
+ 
+-static int __devinit
++static int
+ vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent)
+ {
+     static bool bFirst = true;
+@@ -1099,7 +1099,7 @@ static void device_print_info(PSDevice pDevice)
+ 
+ }
+ 
+-static void __devinit vt6655_init_info(struct pci_dev* pcid, PSDevice* ppDevice,
++static void vt6655_init_info(struct pci_dev* pcid, PSDevice* ppDevice,
+     PCHIP_INFO pChip_info) {
+ 
+     PSDevice p;

commit 89f6883c70245323215b9e5786964621e4484382
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:52 2012 -0500
+
+    staging: xgifb: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
+index e9fe27debf7b..044374e3ac98 100644
+--- a/drivers/staging/xgifb/XGI_main_26.c
++++ b/drivers/staging/xgifb/XGI_main_26.c
+@@ -1695,7 +1695,7 @@ static int __init XGIfb_setup(char *options)
+ 	return 0;
+ }
+ 
+-static int __devinit xgifb_probe(struct pci_dev *pdev,
++static int xgifb_probe(struct pci_dev *pdev,
+ 		const struct pci_device_id *ent)
+ {
+ 	u8 reg, reg1;

commit 3cf36aa9951828a6c164f3b3e12d4653af8ba69f
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:33 2012 -0500
+
+    staging: ste_rmi4: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
+index c71366d3deec..0b717275f10c 100644
+--- a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
++++ b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
+@@ -1130,7 +1130,7 @@ static struct i2c_driver synaptics_rmi4_driver = {
+ #endif
+ 	},
+ 	.probe		=	synaptics_rmi4_probe,
+-	.remove		=	__devexit_p(synaptics_rmi4_remove),
++	.remove		=	synaptics_rmi4_remove,
+ 	.id_table	=	synaptics_rmi4_id_table,
+ };
+ 

commit c8ddc220177c9b0aa3207f872ef3401c16da9d6d
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:32 2012 -0500
+
+    staging: olpc_dcon: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c
+index 3fe209ca38cb..54ed6f69e3d4 100644
+--- a/drivers/staging/olpc_dcon/olpc_dcon.c
++++ b/drivers/staging/olpc_dcon/olpc_dcon.c
+@@ -779,7 +779,7 @@ struct i2c_driver dcon_driver = {
+ 	.class = I2C_CLASS_DDC | I2C_CLASS_HWMON,
+ 	.id_table = dcon_idtable,
+ 	.probe = dcon_probe,
+-	.remove = __devexit_p(dcon_remove),
++	.remove = dcon_remove,
+ 	.detect = dcon_detect,
+ 	.address_list = normal_i2c,
+ };

commit 2c4ae9d21867ec2b771085898682ab3db46341c0
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:04 2012 -0500
+
+    staging: xgifb: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
+index 4b213a318f34..e9fe27debf7b 100644
+--- a/drivers/staging/xgifb/XGI_main_26.c
++++ b/drivers/staging/xgifb/XGI_main_26.c
+@@ -2127,7 +2127,7 @@ static struct pci_driver xgifb_driver = {
+ 	.name = "xgifb",
+ 	.id_table = xgifb_pci_table,
+ 	.probe = xgifb_probe,
+-	.remove = __devexit_p(xgifb_remove)
++	.remove = xgifb_remove
+ };
+ 
+ 

commit 38930755b86082b8d44da038d0ec0b912a708679
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:03 2012 -0500
+
+    staging: vme: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Martyn Welch 
+    Cc: Manohar Vanga 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/vme/devices/vme_pio2_core.c b/drivers/staging/vme/devices/vme_pio2_core.c
+index dad8281915bf..35c5a147849f 100644
+--- a/drivers/staging/vme/devices/vme_pio2_core.c
++++ b/drivers/staging/vme/devices/vme_pio2_core.c
+@@ -156,7 +156,7 @@ static struct vme_driver pio2_driver = {
+ 	.name = driver_name,
+ 	.match = pio2_match,
+ 	.probe = pio2_probe,
+-	.remove = __devexit_p(pio2_remove),
++	.remove = pio2_remove,
+ };
+ 
+ 
+diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c
+index e3731eb2bab1..8209c2d3c151 100644
+--- a/drivers/staging/vme/devices/vme_user.c
++++ b/drivers/staging/vme/devices/vme_user.c
+@@ -619,7 +619,7 @@ static struct vme_driver vme_user_driver = {
+ 	.name = driver_name,
+ 	.match = vme_user_match,
+ 	.probe = vme_user_probe,
+-	.remove = __devexit_p(vme_user_remove),
++	.remove = vme_user_remove,
+ };
+ 
+ 

commit f307da94dbc5308ec4163030785e79cf193b5cf7
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:02 2012 -0500
+
+    staging: usbip: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Matt Mooney 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c
+index 7dc8bbaee18f..c3aa2195f1a8 100644
+--- a/drivers/staging/usbip/vhci_hcd.c
++++ b/drivers/staging/usbip/vhci_hcd.c
+@@ -1127,7 +1127,7 @@ static int vhci_hcd_resume(struct platform_device *pdev)
+ 
+ static struct platform_driver vhci_driver = {
+ 	.probe	= vhci_hcd_probe,
+-	.remove	= __devexit_p(vhci_hcd_remove),
++	.remove	= vhci_hcd_remove,
+ 	.suspend = vhci_hcd_suspend,
+ 	.resume	= vhci_hcd_resume,
+ 	.driver	= {

commit 52ec89d34771f3cff3ef7fe0ead2e2d84abb5faf
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:01 2012 -0500
+
+    staging: tidspbridge: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c
+index 701a11ac676d..e33c64312b25 100644
+--- a/drivers/staging/tidspbridge/rmgr/drv_interface.c
++++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c
+@@ -606,7 +606,7 @@ static struct platform_driver bridge_driver = {
+ 		   .name = "omap-dsp",
+ 		   },
+ 	.probe = omap34_xx_bridge_probe,
+-	.remove = __devexit_p(omap34_xx_bridge_remove),
++	.remove = omap34_xx_bridge_remove,
+ #ifdef CONFIG_PM
+ 	.suspend = bridge_suspend,
+ 	.resume = bridge_resume,

commit 38de09a975ec957a616899b11d7bc089071dcb19
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:00 2012 -0500
+
+    staging: sm7xxfb: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c
+index f27182d4dea6..5272ba94a790 100644
+--- a/drivers/staging/sm7xxfb/sm7xxfb.c
++++ b/drivers/staging/sm7xxfb/sm7xxfb.c
+@@ -1027,7 +1027,7 @@ static struct pci_driver smtcfb_driver = {
+ 	.name = "smtcfb",
+ 	.id_table = smtcfb_pci_table,
+ 	.probe = smtcfb_pci_probe,
+-	.remove = __devexit_p(smtcfb_pci_remove),
++	.remove = smtcfb_pci_remove,
+ 	.driver.pm  = SM7XX_PM_OPS,
+ };
+ 

commit 2e0d79c522388209b1ffd857fe6ab7117a945792
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:20:59 2012 -0500
+
+    staging: slicoss: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c
+index ee0f0e4e41ad..ad85e6e34c52 100644
+--- a/drivers/staging/slicoss/slicoss.c
++++ b/drivers/staging/slicoss/slicoss.c
+@@ -3820,7 +3820,7 @@ static struct pci_driver slic_driver = {
+ 	.name = DRV_NAME,
+ 	.id_table = slic_pci_tbl,
+ 	.probe = slic_entry_probe,
+-	.remove = __devexit_p(slic_entry_remove),
++	.remove = slic_entry_remove,
+ };
+ 
+ static int __init slic_module_init(void)

commit 095d0bb5e1644f435a5ee83da95332b410c85d2e
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:20:57 2012 -0500
+
+    staging: octeon_ethernet: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
+index 683bedc74dde..b48196a98412 100644
+--- a/drivers/staging/octeon/ethernet.c
++++ b/drivers/staging/octeon/ethernet.c
+@@ -874,7 +874,7 @@ MODULE_DEVICE_TABLE(of, cvm_oct_match);
+ 
+ static struct platform_driver cvm_oct_driver = {
+ 	.probe		= cvm_oct_probe,
+-	.remove		= __devexit_p(cvm_oct_remove),
++	.remove		= cvm_oct_remove,
+ 	.driver		= {
+ 		.owner	= THIS_MODULE,
+ 		.name	= KBUILD_MODNAME,

commit bbe0bf96cc77b0ca891f1bfb765433e33364c58f
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:20:54 2012 -0500
+
+    staging: pc300: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/net/pc300_drv.c b/drivers/staging/net/pc300_drv.c
+index cb0f8d932b0c..b8e0480abad1 100644
+--- a/drivers/staging/net/pc300_drv.c
++++ b/drivers/staging/net/pc300_drv.c
+@@ -3646,7 +3646,7 @@ static struct pci_driver cpc_driver = {
+ 	.name           = "pc300",
+ 	.id_table       = cpc_pci_dev_id,
+ 	.probe          = cpc_init_one,
+-	.remove         = __devexit_p(cpc_remove_one),
++	.remove         = cpc_remove_one,
+ };
+ 
+ static int __init cpc_init(void)

commit 99c28f10913018e4dae5db1a571120237a97e951
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:20:51 2012 -0500
+
+    staging: drm/imx: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c
+index 1913199ba16e..ecf0f44bc70e 100644
+--- a/drivers/staging/imx-drm/imx-drm-core.c
++++ b/drivers/staging/imx-drm/imx-drm-core.c
+@@ -824,7 +824,7 @@ static int imx_drm_platform_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver imx_drm_pdrv = {
+ 	.probe		= imx_drm_platform_probe,
+-	.remove		= __devexit_p(imx_drm_platform_remove),
++	.remove		= imx_drm_platform_remove,
+ 	.driver		= {
+ 		.owner	= THIS_MODULE,
+ 		.name	= "imx-drm",
+diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
+index cd05718b7044..937c0b61b318 100644
+--- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c
++++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
+@@ -1158,7 +1158,7 @@ static struct platform_driver imx_ipu_driver = {
+ 		.of_match_table = imx_ipu_dt_ids,
+ 	},
+ 	.probe = ipu_probe,
+-	.remove = __devexit_p(ipu_remove),
++	.remove = ipu_remove,
+ };
+ 
+ module_platform_driver(imx_ipu_driver);
+diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c
+index 7e85c5972ae8..33c82fb961e9 100644
+--- a/drivers/staging/imx-drm/ipuv3-crtc.c
++++ b/drivers/staging/imx-drm/ipuv3-crtc.c
+@@ -570,7 +570,7 @@ static struct platform_driver ipu_drm_driver = {
+ 		.name = "imx-ipuv3-crtc",
+ 	},
+ 	.probe = ipu_drm_probe,
+-	.remove = __devexit_p(ipu_drm_remove),
++	.remove = ipu_drm_remove,
+ };
+ module_platform_driver(ipu_drm_driver);
+ 
+diff --git a/drivers/staging/imx-drm/parallel-display.c b/drivers/staging/imx-drm/parallel-display.c
+index 324283c95530..ba53778e2f0c 100644
+--- a/drivers/staging/imx-drm/parallel-display.c
++++ b/drivers/staging/imx-drm/parallel-display.c
+@@ -256,7 +256,7 @@ static const struct of_device_id imx_pd_dt_ids[] = {
+ 
+ static struct platform_driver imx_pd_driver = {
+ 	.probe		= imx_pd_probe,
+-	.remove		= __devexit_p(imx_pd_remove),
++	.remove		= imx_pd_remove,
+ 	.driver		= {
+ 		.of_match_table = imx_pd_dt_ids,
+ 		.name	= "imx-parallel-display",

commit 417696cfbb79170074b66bc0099f1836ffdd3d0e
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:20:49 2012 -0500
+
+    staging: crystalhd: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/crystalhd/crystalhd_lnx.c b/drivers/staging/crystalhd/crystalhd_lnx.c
+index 166203aeb7b4..a216dae14eea 100644
+--- a/drivers/staging/crystalhd/crystalhd_lnx.c
++++ b/drivers/staging/crystalhd/crystalhd_lnx.c
+@@ -711,7 +711,7 @@ MODULE_DEVICE_TABLE(pci, chd_dec_pci_id_table);
+ static struct pci_driver bc_chd_70012_driver = {
+ 	.name     = "Broadcom 70012 Decoder",
+ 	.probe    = chd_dec_pci_probe,
+-	.remove   = __devexit_p(chd_dec_pci_remove),
++	.remove   = chd_dec_pci_remove,
+ 	.id_table = chd_dec_pci_id_table,
+ #ifdef CONFIG_PM
+ 	.suspend  = chd_dec_pci_suspend,

commit 941906647a12749ae769b3414f652f1f03e22f69
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:19:22 2012 -0500
+
+    staging: csr: remove CONFIG_HOTPLUG ifdefs
+    
+    Remove conditional code based on CONFIG_HOTPLUG being false.  It's
+    always on now in preparation of it going away as an option.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/csr/firmware.c b/drivers/staging/csr/firmware.c
+index 1d1c10392ad1..b42a4d6a0c36 100644
+--- a/drivers/staging/csr/firmware.c
++++ b/drivers/staging/csr/firmware.c
+@@ -233,8 +233,6 @@ unifi_fw_read(void *ospriv, void *arg, u32 offset, void *buf, u32 len)
+ int
+ uf_run_unifihelper(unifi_priv_t *priv)
+ {
+-#ifdef CONFIG_HOTPLUG
+-
+ #ifdef ANDROID_BUILD
+     char *prog = "/system/bin/unififw";
+ #else
+@@ -280,10 +278,6 @@ uf_run_unifihelper(unifi_priv_t *priv)
+     r = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
+ 
+     return r;
+-#else
+-    unifi_trace(priv, UDBG1, "Can't automatically download firmware because kernel does not have HOTPLUG\n");
+-    return -1;
+-#endif
+ } /* uf_run_unifihelper() */
+ 
+ #ifdef CSR_WIFI_SPLIT_PATCH

commit e543acf07db78cfc135e45c4ce0ed26ccf774c37
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:38 2012 -0500
+
+    staging: iio: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Jonathan Cameron 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c
+index 9cd5d786e937..9e5791ff2a04 100644
+--- a/drivers/staging/iio/accel/adis16201_core.c
++++ b/drivers/staging/iio/accel/adis16201_core.c
+@@ -242,7 +242,7 @@ static struct spi_driver adis16201_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = adis16201_probe,
+-	.remove = __devexit_p(adis16201_remove),
++	.remove = adis16201_remove,
+ };
+ module_spi_driver(adis16201_driver);
+ 
+diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c
+index 385b94fda8ed..8c235273ff13 100644
+--- a/drivers/staging/iio/accel/adis16203_core.c
++++ b/drivers/staging/iio/accel/adis16203_core.c
+@@ -209,7 +209,7 @@ static struct spi_driver adis16203_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = adis16203_probe,
+-	.remove = __devexit_p(adis16203_remove),
++	.remove = adis16203_remove,
+ };
+ module_spi_driver(adis16203_driver);
+ 
+diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c
+index 0680be5baa5f..f3592668e066 100644
+--- a/drivers/staging/iio/accel/adis16204_core.c
++++ b/drivers/staging/iio/accel/adis16204_core.c
+@@ -249,7 +249,7 @@ static struct spi_driver adis16204_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = adis16204_probe,
+-	.remove = __devexit_p(adis16204_remove),
++	.remove = adis16204_remove,
+ };
+ module_spi_driver(adis16204_driver);
+ 
+diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c
+index 0e0c321b12bb..69c50ee44ce3 100644
+--- a/drivers/staging/iio/accel/adis16209_core.c
++++ b/drivers/staging/iio/accel/adis16209_core.c
+@@ -242,7 +242,7 @@ static struct spi_driver adis16209_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = adis16209_probe,
+-	.remove = __devexit_p(adis16209_remove),
++	.remove = adis16209_remove,
+ };
+ module_spi_driver(adis16209_driver);
+ 
+diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c
+index 4e346891d8ce..370b01aa767a 100644
+--- a/drivers/staging/iio/accel/adis16220_core.c
++++ b/drivers/staging/iio/accel/adis16220_core.c
+@@ -503,7 +503,7 @@ static struct spi_driver adis16220_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = adis16220_probe,
+-	.remove = __devexit_p(adis16220_remove),
++	.remove = adis16220_remove,
+ };
+ module_spi_driver(adis16220_driver);
+ 
+diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c
+index 32195b7f27b3..e97fa0b0233d 100644
+--- a/drivers/staging/iio/accel/adis16240_core.c
++++ b/drivers/staging/iio/accel/adis16240_core.c
+@@ -297,7 +297,7 @@ static struct spi_driver adis16240_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = adis16240_probe,
+-	.remove = __devexit_p(adis16240_remove),
++	.remove = adis16240_remove,
+ };
+ module_spi_driver(adis16240_driver);
+ 
+diff --git a/drivers/staging/iio/accel/kxsd9.c b/drivers/staging/iio/accel/kxsd9.c
+index 9aed044abd1b..318331f08d9c 100644
+--- a/drivers/staging/iio/accel/kxsd9.c
++++ b/drivers/staging/iio/accel/kxsd9.c
+@@ -281,7 +281,7 @@ static struct spi_driver kxsd9_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = kxsd9_probe,
+-	.remove = __devexit_p(kxsd9_remove),
++	.remove = kxsd9_remove,
+ 	.id_table = kxsd9_id,
+ };
+ module_spi_driver(kxsd9_driver);
+diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c
+index 6d88d1e7c0cd..37ed1b8ebb6f 100644
+--- a/drivers/staging/iio/accel/lis3l02dq_core.c
++++ b/drivers/staging/iio/accel/lis3l02dq_core.c
+@@ -810,7 +810,7 @@ static struct spi_driver lis3l02dq_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = lis3l02dq_probe,
+-	.remove = __devexit_p(lis3l02dq_remove),
++	.remove = lis3l02dq_remove,
+ };
+ module_spi_driver(lis3l02dq_driver);
+ 
+diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c
+index 69bdf22707cb..414d3cad55a7 100644
+--- a/drivers/staging/iio/accel/sca3000_core.c
++++ b/drivers/staging/iio/accel/sca3000_core.c
+@@ -1265,7 +1265,7 @@ static struct spi_driver sca3000_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = sca3000_probe,
+-	.remove = __devexit_p(sca3000_remove),
++	.remove = sca3000_remove,
+ 	.id_table = sca3000_id,
+ };
+ module_spi_driver(sca3000_driver);
+diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c
+index b9f22028ab4d..504701940585 100644
+--- a/drivers/staging/iio/adc/ad7192.c
++++ b/drivers/staging/iio/adc/ad7192.c
+@@ -716,7 +716,7 @@ static struct spi_driver ad7192_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= ad7192_probe,
+-	.remove		= __devexit_p(ad7192_remove),
++	.remove		= ad7192_remove,
+ 	.id_table	= ad7192_id,
+ };
+ module_spi_driver(ad7192_driver);
+diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c
+index 9b1a095e79c0..fa81a491e790 100644
+--- a/drivers/staging/iio/adc/ad7280a.c
++++ b/drivers/staging/iio/adc/ad7280a.c
+@@ -981,7 +981,7 @@ static struct spi_driver ad7280_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= ad7280_probe,
+-	.remove		= __devexit_p(ad7280_remove),
++	.remove		= ad7280_remove,
+ 	.id_table	= ad7280_id,
+ };
+ module_spi_driver(ad7280_driver);
+diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c
+index 69a6c9651c66..6e58e36d242c 100644
+--- a/drivers/staging/iio/adc/ad7291.c
++++ b/drivers/staging/iio/adc/ad7291.c
+@@ -706,7 +706,7 @@ static struct i2c_driver ad7291_driver = {
+ 		.name = KBUILD_MODNAME,
+ 	},
+ 	.probe = ad7291_probe,
+-	.remove = __devexit_p(ad7291_remove),
++	.remove = ad7291_remove,
+ 	.id_table = ad7291_id,
+ };
+ module_i2c_driver(ad7291_driver);
+diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/staging/iio/adc/ad7606_par.c
+index 2b42d120c9f5..58cfddea9637 100644
+--- a/drivers/staging/iio/adc/ad7606_par.c
++++ b/drivers/staging/iio/adc/ad7606_par.c
+@@ -164,7 +164,7 @@ MODULE_DEVICE_TABLE(platform, ad7606_driver_ids);
+ 
+ static struct platform_driver ad7606_driver = {
+ 	.probe = ad7606_par_probe,
+-	.remove	= __devexit_p(ad7606_par_remove),
++	.remove	= ad7606_par_remove,
+ 	.id_table = ad7606_driver_ids,
+ 	.driver = {
+ 		.name	 = "ad7606",
+diff --git a/drivers/staging/iio/adc/ad7606_spi.c b/drivers/staging/iio/adc/ad7606_spi.c
+index 1bbb86dcdb8e..6a8ecd73a1a7 100644
+--- a/drivers/staging/iio/adc/ad7606_spi.c
++++ b/drivers/staging/iio/adc/ad7606_spi.c
+@@ -106,7 +106,7 @@ static struct spi_driver ad7606_driver = {
+ 		.pm    = AD7606_SPI_PM_OPS,
+ 	},
+ 	.probe = ad7606_spi_probe,
+-	.remove = __devexit_p(ad7606_spi_remove),
++	.remove = ad7606_spi_remove,
+ 	.id_table = ad7606_id,
+ };
+ module_spi_driver(ad7606_driver);
+diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c
+index 831c9d7a948b..e1f88603d7e0 100644
+--- a/drivers/staging/iio/adc/ad7780.c
++++ b/drivers/staging/iio/adc/ad7780.c
+@@ -283,7 +283,7 @@ static struct spi_driver ad7780_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= ad7780_probe,
+-	.remove		= __devexit_p(ad7780_remove),
++	.remove		= ad7780_remove,
+ 	.id_table	= ad7780_id,
+ };
+ module_spi_driver(ad7780_driver);
+diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c
+index 9084b2d8fe03..b0a57e475410 100644
+--- a/drivers/staging/iio/adc/ad7793.c
++++ b/drivers/staging/iio/adc/ad7793.c
+@@ -556,7 +556,7 @@ static struct spi_driver ad7793_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= ad7793_probe,
+-	.remove		= __devexit_p(ad7793_remove),
++	.remove		= ad7793_remove,
+ 	.id_table	= ad7793_id,
+ };
+ module_spi_driver(ad7793_driver);
+diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c
+index 2dbe68b0ce2f..928477146c2f 100644
+--- a/drivers/staging/iio/adc/ad7816.c
++++ b/drivers/staging/iio/adc/ad7816.c
+@@ -463,7 +463,7 @@ static struct spi_driver ad7816_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = ad7816_probe,
+-	.remove = __devexit_p(ad7816_remove),
++	.remove = ad7816_remove,
+ 	.id_table = ad7816_id,
+ };
+ module_spi_driver(ad7816_driver);
+diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c
+index 7cb90112b2c2..077eedbd0a0c 100644
+--- a/drivers/staging/iio/adc/ad799x_core.c
++++ b/drivers/staging/iio/adc/ad799x_core.c
+@@ -970,7 +970,7 @@ static struct i2c_driver ad799x_driver = {
+ 		.name = "ad799x",
+ 	},
+ 	.probe = ad799x_probe,
+-	.remove = __devexit_p(ad799x_remove),
++	.remove = ad799x_remove,
+ 	.id_table = ad799x_id,
+ };
+ module_i2c_driver(ad799x_driver);
+diff --git a/drivers/staging/iio/adc/adt7410.c b/drivers/staging/iio/adc/adt7410.c
+index d55efe46fac2..35455e160945 100644
+--- a/drivers/staging/iio/adc/adt7410.c
++++ b/drivers/staging/iio/adc/adt7410.c
+@@ -900,7 +900,7 @@ static struct i2c_driver adt7410_driver = {
+ 		.name = "adt7410",
+ 	},
+ 	.probe = adt7410_i2c_probe,
+-	.remove = __devexit_p(adt7410_i2c_remove),
++	.remove = adt7410_i2c_remove,
+ 	.id_table = adt7410_id,
+ };
+ 
+@@ -1053,7 +1053,7 @@ static struct spi_driver adt7310_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = adt7310_spi_probe,
+-	.remove = __devexit_p(adt7310_spi_remove),
++	.remove = adt7310_spi_remove,
+ 	.id_table = adt7310_id,
+ };
+ 
+diff --git a/drivers/staging/iio/adc/lpc32xx_adc.c b/drivers/staging/iio/adc/lpc32xx_adc.c
+index 7b9b9a5cf025..0bf2a6cc79e0 100644
+--- a/drivers/staging/iio/adc/lpc32xx_adc.c
++++ b/drivers/staging/iio/adc/lpc32xx_adc.c
+@@ -233,7 +233,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_adc_match);
+ 
+ static struct platform_driver lpc32xx_adc_driver = {
+ 	.probe		= lpc32xx_adc_probe,
+-	.remove		= __devexit_p(lpc32xx_adc_remove),
++	.remove		= lpc32xx_adc_remove,
+ 	.driver		= {
+ 		.name	= MOD_NAME,
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c
+index c6d00f2f2b17..fb31b457a56a 100644
+--- a/drivers/staging/iio/adc/mxs-lradc.c
++++ b/drivers/staging/iio/adc/mxs-lradc.c
+@@ -579,7 +579,7 @@ static struct platform_driver mxs_lradc_driver = {
+ 		.of_match_table = mxs_lradc_dt_ids,
+ 	},
+ 	.probe	= mxs_lradc_probe,
+-	.remove	= __devexit_p(mxs_lradc_remove),
++	.remove	= mxs_lradc_remove,
+ };
+ 
+ module_platform_driver(mxs_lradc_driver);
+diff --git a/drivers/staging/iio/adc/spear_adc.c b/drivers/staging/iio/adc/spear_adc.c
+index a09a8262e4ff..13052ceb2f2b 100644
+--- a/drivers/staging/iio/adc/spear_adc.c
++++ b/drivers/staging/iio/adc/spear_adc.c
+@@ -424,7 +424,7 @@ MODULE_DEVICE_TABLE(of, spear_adc_dt_ids);
+ 
+ static struct platform_driver spear_adc_driver = {
+ 	.probe		= spear_adc_probe,
+-	.remove		= __devexit_p(spear_adc_remove),
++	.remove		= spear_adc_remove,
+ 	.driver		= {
+ 		.name	= MOD_NAME,
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/staging/iio/addac/adt7316-i2c.c b/drivers/staging/iio/addac/adt7316-i2c.c
+index b86e76c15bc0..ce7d91cb331c 100644
+--- a/drivers/staging/iio/addac/adt7316-i2c.c
++++ b/drivers/staging/iio/addac/adt7316-i2c.c
+@@ -132,7 +132,7 @@ static struct i2c_driver adt7316_driver = {
+ 		.owner  = THIS_MODULE,
+ 	},
+ 	.probe = adt7316_i2c_probe,
+-	.remove = __devexit_p(adt7316_i2c_remove),
++	.remove = adt7316_i2c_remove,
+ 	.id_table = adt7316_i2c_id,
+ };
+ module_i2c_driver(adt7316_driver);
+diff --git a/drivers/staging/iio/addac/adt7316-spi.c b/drivers/staging/iio/addac/adt7316-spi.c
+index c451504ef914..0db8ef5835a0 100644
+--- a/drivers/staging/iio/addac/adt7316-spi.c
++++ b/drivers/staging/iio/addac/adt7316-spi.c
+@@ -140,7 +140,7 @@ static struct spi_driver adt7316_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = adt7316_spi_probe,
+-	.remove = __devexit_p(adt7316_spi_remove),
++	.remove = adt7316_spi_remove,
+ 	.id_table = adt7316_spi_id,
+ };
+ module_spi_driver(adt7316_driver);
+diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c
+index a4d83b68df81..3c608c14dd99 100644
+--- a/drivers/staging/iio/cdc/ad7150.c
++++ b/drivers/staging/iio/cdc/ad7150.c
+@@ -658,7 +658,7 @@ static struct i2c_driver ad7150_driver = {
+ 		.name = "ad7150",
+ 	},
+ 	.probe = ad7150_probe,
+-	.remove = __devexit_p(ad7150_remove),
++	.remove = ad7150_remove,
+ 	.id_table = ad7150_id,
+ };
+ module_i2c_driver(ad7150_driver);
+diff --git a/drivers/staging/iio/cdc/ad7152.c b/drivers/staging/iio/cdc/ad7152.c
+index ec89a065d707..3c92ba3722a8 100644
+--- a/drivers/staging/iio/cdc/ad7152.c
++++ b/drivers/staging/iio/cdc/ad7152.c
+@@ -541,7 +541,7 @@ static struct i2c_driver ad7152_driver = {
+ 		.name = KBUILD_MODNAME,
+ 	},
+ 	.probe = ad7152_probe,
+-	.remove = __devexit_p(ad7152_remove),
++	.remove = ad7152_remove,
+ 	.id_table = ad7152_id,
+ };
+ module_i2c_driver(ad7152_driver);
+diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c
+index f0787eeb8363..466b82ecfbe0 100644
+--- a/drivers/staging/iio/cdc/ad7746.c
++++ b/drivers/staging/iio/cdc/ad7746.c
+@@ -792,7 +792,7 @@ static struct i2c_driver ad7746_driver = {
+ 		.name = KBUILD_MODNAME,
+ 	},
+ 	.probe = ad7746_probe,
+-	.remove = __devexit_p(ad7746_remove),
++	.remove = ad7746_remove,
+ 	.id_table = ad7746_id,
+ };
+ module_i2c_driver(ad7746_driver);
+diff --git a/drivers/staging/iio/frequency/ad5930.c b/drivers/staging/iio/frequency/ad5930.c
+index 027f73b63e04..23777be38b18 100644
+--- a/drivers/staging/iio/frequency/ad5930.c
++++ b/drivers/staging/iio/frequency/ad5930.c
+@@ -141,7 +141,7 @@ static struct spi_driver ad5930_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = ad5930_probe,
+-	.remove = __devexit_p(ad5930_remove),
++	.remove = ad5930_remove,
+ };
+ module_spi_driver(ad5930_driver);
+ 
+diff --git a/drivers/staging/iio/frequency/ad9832.c b/drivers/staging/iio/frequency/ad9832.c
+index ea3c63b79062..4e18380c5141 100644
+--- a/drivers/staging/iio/frequency/ad9832.c
++++ b/drivers/staging/iio/frequency/ad9832.c
+@@ -352,7 +352,7 @@ static struct spi_driver ad9832_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= ad9832_probe,
+-	.remove		= __devexit_p(ad9832_remove),
++	.remove		= ad9832_remove,
+ 	.id_table	= ad9832_id,
+ };
+ module_spi_driver(ad9832_driver);
+diff --git a/drivers/staging/iio/frequency/ad9834.c b/drivers/staging/iio/frequency/ad9834.c
+index f6b583eacafa..5cba3c01f417 100644
+--- a/drivers/staging/iio/frequency/ad9834.c
++++ b/drivers/staging/iio/frequency/ad9834.c
+@@ -454,7 +454,7 @@ static struct spi_driver ad9834_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= ad9834_probe,
+-	.remove		= __devexit_p(ad9834_remove),
++	.remove		= ad9834_remove,
+ 	.id_table	= ad9834_id,
+ };
+ module_spi_driver(ad9834_driver);
+diff --git a/drivers/staging/iio/frequency/ad9850.c b/drivers/staging/iio/frequency/ad9850.c
+index f64702758b5e..104f7a4905a3 100644
+--- a/drivers/staging/iio/frequency/ad9850.c
++++ b/drivers/staging/iio/frequency/ad9850.c
+@@ -127,7 +127,7 @@ static struct spi_driver ad9850_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = ad9850_probe,
+-	.remove = __devexit_p(ad9850_remove),
++	.remove = ad9850_remove,
+ };
+ module_spi_driver(ad9850_driver);
+ 
+diff --git a/drivers/staging/iio/frequency/ad9852.c b/drivers/staging/iio/frequency/ad9852.c
+index 5475c75fd2b2..17ac825b3d26 100644
+--- a/drivers/staging/iio/frequency/ad9852.c
++++ b/drivers/staging/iio/frequency/ad9852.c
+@@ -278,7 +278,7 @@ static struct spi_driver ad9852_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = ad9852_probe,
+-	.remove = __devexit_p(ad9852_remove),
++	.remove = ad9852_remove,
+ };
+ module_spi_driver(ad9852_driver);
+ 
+diff --git a/drivers/staging/iio/frequency/ad9910.c b/drivers/staging/iio/frequency/ad9910.c
+index f79b03b15504..e48f874c1fc2 100644
+--- a/drivers/staging/iio/frequency/ad9910.c
++++ b/drivers/staging/iio/frequency/ad9910.c
+@@ -411,7 +411,7 @@ static struct spi_driver ad9910_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = ad9910_probe,
+-	.remove = __devexit_p(ad9910_remove),
++	.remove = ad9910_remove,
+ };
+ module_spi_driver(ad9910_driver);
+ 
+diff --git a/drivers/staging/iio/frequency/ad9951.c b/drivers/staging/iio/frequency/ad9951.c
+index fb2f77144ad4..8234e3c915c4 100644
+--- a/drivers/staging/iio/frequency/ad9951.c
++++ b/drivers/staging/iio/frequency/ad9951.c
+@@ -222,7 +222,7 @@ static struct spi_driver ad9951_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = ad9951_probe,
+-	.remove = __devexit_p(ad9951_remove),
++	.remove = ad9951_remove,
+ };
+ module_spi_driver(ad9951_driver);
+ 
+diff --git a/drivers/staging/iio/gyro/adis16060_core.c b/drivers/staging/iio/gyro/adis16060_core.c
+index ac806177b655..687c151f9847 100644
+--- a/drivers/staging/iio/gyro/adis16060_core.c
++++ b/drivers/staging/iio/gyro/adis16060_core.c
+@@ -221,7 +221,7 @@ static struct spi_driver adis16060_r_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = adis16060_r_probe,
+-	.remove = __devexit_p(adis16060_r_remove),
++	.remove = adis16060_r_remove,
+ };
+ 
+ static struct spi_driver adis16060_w_driver = {
+@@ -230,7 +230,7 @@ static struct spi_driver adis16060_w_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = adis16060_w_probe,
+-	.remove = __devexit_p(adis16060_w_remove),
++	.remove = adis16060_w_remove,
+ };
+ 
+ static __init int adis16060_init(void)
+diff --git a/drivers/staging/iio/gyro/adis16080_core.c b/drivers/staging/iio/gyro/adis16080_core.c
+index be345b0fd975..3525a68d6a75 100644
+--- a/drivers/staging/iio/gyro/adis16080_core.c
++++ b/drivers/staging/iio/gyro/adis16080_core.c
+@@ -191,7 +191,7 @@ static struct spi_driver adis16080_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = adis16080_probe,
+-	.remove = __devexit_p(adis16080_remove),
++	.remove = adis16080_remove,
+ };
+ module_spi_driver(adis16080_driver);
+ 
+diff --git a/drivers/staging/iio/gyro/adis16130_core.c b/drivers/staging/iio/gyro/adis16130_core.c
+index a6df05d6c5e7..835801ee7e80 100644
+--- a/drivers/staging/iio/gyro/adis16130_core.c
++++ b/drivers/staging/iio/gyro/adis16130_core.c
+@@ -168,7 +168,7 @@ static struct spi_driver adis16130_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = adis16130_probe,
+-	.remove = __devexit_p(adis16130_remove),
++	.remove = adis16130_remove,
+ };
+ module_spi_driver(adis16130_driver);
+ 
+diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c
+index a549b97e14dc..6e80b8c768ae 100644
+--- a/drivers/staging/iio/gyro/adis16260_core.c
++++ b/drivers/staging/iio/gyro/adis16260_core.c
+@@ -417,7 +417,7 @@ static struct spi_driver adis16260_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = adis16260_probe,
+-	.remove = __devexit_p(adis16260_remove),
++	.remove = adis16260_remove,
+ 	.id_table = adis16260_id,
+ };
+ module_spi_driver(adis16260_driver);
+diff --git a/drivers/staging/iio/gyro/adxrs450_core.c b/drivers/staging/iio/gyro/adxrs450_core.c
+index 63f177189e0b..f0ce81da8aca 100644
+--- a/drivers/staging/iio/gyro/adxrs450_core.c
++++ b/drivers/staging/iio/gyro/adxrs450_core.c
+@@ -430,7 +430,7 @@ static struct spi_driver adxrs450_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = adxrs450_probe,
+-	.remove = __devexit_p(adxrs450_remove),
++	.remove = adxrs450_remove,
+ 	.id_table	= adxrs450_id,
+ };
+ module_spi_driver(adxrs450_driver);
+diff --git a/drivers/staging/iio/iio_hwmon.c b/drivers/staging/iio/iio_hwmon.c
+index 5ed147235259..c7a5f97576c7 100644
+--- a/drivers/staging/iio/iio_hwmon.c
++++ b/drivers/staging/iio/iio_hwmon.c
+@@ -189,7 +189,7 @@ static struct platform_driver __refdata iio_hwmon_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = iio_hwmon_probe,
+-	.remove = __devexit_p(iio_hwmon_remove),
++	.remove = iio_hwmon_remove,
+ };
+ 
+ module_platform_driver(iio_hwmon_driver);
+diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c
+index 99b5f8ca0864..779243d24dec 100644
+--- a/drivers/staging/iio/impedance-analyzer/ad5933.c
++++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
+@@ -817,7 +817,7 @@ static struct i2c_driver ad5933_driver = {
+ 		.name = "ad5933",
+ 	},
+ 	.probe = ad5933_probe,
+-	.remove = __devexit_p(ad5933_remove),
++	.remove = ad5933_remove,
+ 	.id_table = ad5933_id,
+ };
+ module_i2c_driver(ad5933_driver);
+diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c
+index 18197f249d85..9c8f5ab7e13b 100644
+--- a/drivers/staging/iio/imu/adis16400_core.c
++++ b/drivers/staging/iio/imu/adis16400_core.c
+@@ -1311,7 +1311,7 @@ static struct spi_driver adis16400_driver = {
+ 	},
+ 	.id_table = adis16400_id,
+ 	.probe = adis16400_probe,
+-	.remove = __devexit_p(adis16400_remove),
++	.remove = adis16400_remove,
+ };
+ module_spi_driver(adis16400_driver);
+ 
+diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c
+index a6242aa6f5c9..b0adac0bf5d5 100644
+--- a/drivers/staging/iio/light/isl29018.c
++++ b/drivers/staging/iio/light/isl29018.c
+@@ -669,7 +669,7 @@ static struct i2c_driver isl29018_driver = {
+ 			.of_match_table = isl29018_of_match,
+ 		    },
+ 	.probe	 = isl29018_probe,
+-	.remove	 = __devexit_p(isl29018_remove),
++	.remove	 = isl29018_remove,
+ 	.id_table = isl29018_id,
+ };
+ module_i2c_driver(isl29018_driver);
+diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c
+index bcf4a8f47b4a..e52af77f7782 100644
+--- a/drivers/staging/iio/light/isl29028.c
++++ b/drivers/staging/iio/light/isl29028.c
+@@ -555,7 +555,7 @@ static struct i2c_driver isl29028_driver = {
+ 		.of_match_table = isl29028_of_match,
+ 	},
+ 	.probe	 = isl29028_probe,
+-	.remove  = __devexit_p(isl29028_remove),
++	.remove  = isl29028_remove,
+ 	.id_table = isl29028_id,
+ };
+ 
+diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c
+index ecd6347950d1..1a9adc020f64 100644
+--- a/drivers/staging/iio/light/tsl2563.c
++++ b/drivers/staging/iio/light/tsl2563.c
+@@ -889,7 +889,7 @@ static struct i2c_driver tsl2563_i2c_driver = {
+ 		.pm	= TSL2563_PM_OPS,
+ 	},
+ 	.probe		= tsl2563_probe,
+-	.remove		= __devexit_p(tsl2563_remove),
++	.remove		= tsl2563_remove,
+ 	.id_table	= tsl2563_id,
+ };
+ module_i2c_driver(tsl2563_i2c_driver);
+diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c
+index 133bac297030..b377dd3b76ad 100644
+--- a/drivers/staging/iio/light/tsl2583.c
++++ b/drivers/staging/iio/light/tsl2583.c
+@@ -947,7 +947,7 @@ static struct i2c_driver taos_driver = {
+ 	},
+ 	.id_table = taos_idtable,
+ 	.probe = taos_probe,
+-	.remove = __devexit_p(taos_remove),
++	.remove = taos_remove,
+ };
+ module_i2c_driver(taos_driver);
+ 
+diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x_core.c
+index 51450e21d3e9..9e50fbbadf9d 100644
+--- a/drivers/staging/iio/light/tsl2x7x_core.c
++++ b/drivers/staging/iio/light/tsl2x7x_core.c
+@@ -2070,7 +2070,7 @@ static struct i2c_driver tsl2x7x_driver = {
+ 	},
+ 	.id_table = tsl2x7x_idtable,
+ 	.probe = tsl2x7x_probe,
+-	.remove = __devexit_p(tsl2x7x_remove),
++	.remove = tsl2x7x_remove,
+ };
+ 
+ module_i2c_driver(tsl2x7x_driver);
+diff --git a/drivers/staging/iio/magnetometer/ak8975.c b/drivers/staging/iio/magnetometer/ak8975.c
+index 22a4addd15f0..28f080e9eeee 100644
+--- a/drivers/staging/iio/magnetometer/ak8975.c
++++ b/drivers/staging/iio/magnetometer/ak8975.c
+@@ -510,7 +510,7 @@ static struct i2c_driver ak8975_driver = {
+ 		.of_match_table = ak8975_of_match,
+ 	},
+ 	.probe		= ak8975_probe,
+-	.remove		= __devexit_p(ak8975_remove),
++	.remove		= ak8975_remove,
+ 	.id_table	= ak8975_id,
+ };
+ module_i2c_driver(ak8975_driver);
+diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c
+index e151fcafecc4..1a520ecfa3e2 100644
+--- a/drivers/staging/iio/magnetometer/hmc5843.c
++++ b/drivers/staging/iio/magnetometer/hmc5843.c
+@@ -755,7 +755,7 @@ static struct i2c_driver hmc5843_driver = {
+ 	},
+ 	.id_table	= hmc5843_id,
+ 	.probe		= hmc5843_probe,
+-	.remove		= __devexit_p(hmc5843_remove),
++	.remove		= hmc5843_remove,
+ 	.detect		= hmc5843_detect,
+ 	.address_list	= normal_i2c,
+ };
+diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c
+index d8b1686f3bc0..51c3bdece785 100644
+--- a/drivers/staging/iio/meter/ade7753.c
++++ b/drivers/staging/iio/meter/ade7753.c
+@@ -572,7 +572,7 @@ static struct spi_driver ade7753_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = ade7753_probe,
+-	.remove = __devexit_p(ade7753_remove),
++	.remove = ade7753_remove,
+ };
+ module_spi_driver(ade7753_driver);
+ 
+diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c
+index 8383c31e269e..b50c89e93993 100644
+--- a/drivers/staging/iio/meter/ade7754.c
++++ b/drivers/staging/iio/meter/ade7754.c
+@@ -594,7 +594,7 @@ static struct spi_driver ade7754_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = ade7754_probe,
+-	.remove = __devexit_p(ade7754_remove),
++	.remove = ade7754_remove,
+ };
+ module_spi_driver(ade7754_driver);
+ 
+diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c
+index f50dacb1719f..3454e5154ed2 100644
+--- a/drivers/staging/iio/meter/ade7758_core.c
++++ b/drivers/staging/iio/meter/ade7758_core.c
+@@ -992,7 +992,7 @@ static struct spi_driver ade7758_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = ade7758_probe,
+-	.remove = __devexit_p(ade7758_remove),
++	.remove = ade7758_remove,
+ 	.id_table = ade7758_id,
+ };
+ module_spi_driver(ade7758_driver);
+diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c
+index 4feb14dc3964..10b911bd3853 100644
+--- a/drivers/staging/iio/meter/ade7759.c
++++ b/drivers/staging/iio/meter/ade7759.c
+@@ -516,7 +516,7 @@ static struct spi_driver ade7759_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = ade7759_probe,
+-	.remove = __devexit_p(ade7759_remove),
++	.remove = ade7759_remove,
+ };
+ module_spi_driver(ade7759_driver);
+ 
+diff --git a/drivers/staging/iio/meter/ade7854-i2c.c b/drivers/staging/iio/meter/ade7854-i2c.c
+index 2f83a540edbf..db9ef6c86c1e 100644
+--- a/drivers/staging/iio/meter/ade7854-i2c.c
++++ b/drivers/staging/iio/meter/ade7854-i2c.c
+@@ -250,7 +250,7 @@ static struct i2c_driver ade7854_i2c_driver = {
+ 		.name = "ade7854",
+ 	},
+ 	.probe    = ade7854_i2c_probe,
+-	.remove   = __devexit_p(ade7854_i2c_remove),
++	.remove   = ade7854_i2c_remove,
+ 	.id_table = ade7854_id,
+ };
+ module_i2c_driver(ade7854_i2c_driver);
+diff --git a/drivers/staging/iio/meter/ade7854-spi.c b/drivers/staging/iio/meter/ade7854-spi.c
+index 35b308aa9b81..f0984fa1cbb9 100644
+--- a/drivers/staging/iio/meter/ade7854-spi.c
++++ b/drivers/staging/iio/meter/ade7854-spi.c
+@@ -351,7 +351,7 @@ static struct spi_driver ade7854_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = ade7854_spi_probe,
+-	.remove = __devexit_p(ade7854_spi_remove),
++	.remove = ade7854_spi_remove,
+ 	.id_table = ade7854_id,
+ };
+ module_spi_driver(ade7854_driver);
+diff --git a/drivers/staging/iio/resolver/ad2s1200.c b/drivers/staging/iio/resolver/ad2s1200.c
+index d7f4efb9e8d1..4fe349914f9a 100644
+--- a/drivers/staging/iio/resolver/ad2s1200.c
++++ b/drivers/staging/iio/resolver/ad2s1200.c
+@@ -170,7 +170,7 @@ static struct spi_driver ad2s1200_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = ad2s1200_probe,
+-	.remove = __devexit_p(ad2s1200_remove),
++	.remove = ad2s1200_remove,
+ 	.id_table = ad2s1200_id,
+ };
+ module_spi_driver(ad2s1200_driver);
+diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c
+index d57c62945e78..ed07a348eb55 100644
+--- a/drivers/staging/iio/resolver/ad2s1210.c
++++ b/drivers/staging/iio/resolver/ad2s1210.c
+@@ -759,7 +759,7 @@ static struct spi_driver ad2s1210_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = ad2s1210_probe,
+-	.remove = __devexit_p(ad2s1210_remove),
++	.remove = ad2s1210_remove,
+ 	.id_table = ad2s1210_id,
+ };
+ module_spi_driver(ad2s1210_driver);
+diff --git a/drivers/staging/iio/resolver/ad2s90.c b/drivers/staging/iio/resolver/ad2s90.c
+index f2aa7ddc7d17..0aecfbcdb992 100644
+--- a/drivers/staging/iio/resolver/ad2s90.c
++++ b/drivers/staging/iio/resolver/ad2s90.c
+@@ -118,7 +118,7 @@ static struct spi_driver ad2s90_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = ad2s90_probe,
+-	.remove = __devexit_p(ad2s90_remove),
++	.remove = ad2s90_remove,
+ 	.id_table = ad2s90_id,
+ };
+ module_spi_driver(ad2s90_driver);
+diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
+index 8c45c7cfca99..42798da575c0 100644
+--- a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
++++ b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
+@@ -296,7 +296,7 @@ static struct platform_driver iio_bfin_tmr_trigger_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = iio_bfin_tmr_trigger_probe,
+-	.remove = __devexit_p(iio_bfin_tmr_trigger_remove),
++	.remove = iio_bfin_tmr_trigger_remove,
+ };
+ 
+ module_platform_driver(iio_bfin_tmr_trigger_driver);
+diff --git a/drivers/staging/iio/trigger/iio-trig-gpio.c b/drivers/staging/iio/trigger/iio-trig-gpio.c
+index c0be7908c087..fcc4cb048c9a 100644
+--- a/drivers/staging/iio/trigger/iio-trig-gpio.c
++++ b/drivers/staging/iio/trigger/iio-trig-gpio.c
+@@ -153,7 +153,7 @@ static int iio_gpio_trigger_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver iio_gpio_trigger_driver = {
+ 	.probe = iio_gpio_trigger_probe,
+-	.remove = __devexit_p(iio_gpio_trigger_remove),
++	.remove = iio_gpio_trigger_remove,
+ 	.driver = {
+ 		.name = "iio_gpio_trigger",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
+index 304b653b5859..9102b1ba2530 100644
+--- a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
++++ b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
+@@ -188,7 +188,7 @@ static int iio_trig_periodic_rtc_remove(struct platform_device *dev)
+ 
+ static struct platform_driver iio_trig_periodic_rtc_driver = {
+ 	.probe = iio_trig_periodic_rtc_probe,
+-	.remove = __devexit_p(iio_trig_periodic_rtc_remove),
++	.remove = iio_trig_periodic_rtc_remove,
+ 	.driver = {
+ 		.name = "iio_prtc_trigger",
+ 		.owner = THIS_MODULE,

commit 447d4f29ee3fa62f13c65688bb7b74d5a9a0d767
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:37 2012 -0500
+
+    staging: iio: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Jonathan Cameron 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c
+index 8cb9fc32d099..9cd5d786e937 100644
+--- a/drivers/staging/iio/accel/adis16201_core.c
++++ b/drivers/staging/iio/accel/adis16201_core.c
+@@ -224,7 +224,7 @@ static int adis16201_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit adis16201_remove(struct spi_device *spi)
++static int adis16201_remove(struct spi_device *spi)
+ {
+ 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ 	struct adis *st = iio_priv(indio_dev);
+diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c
+index 1def6fb0efc9..385b94fda8ed 100644
+--- a/drivers/staging/iio/accel/adis16203_core.c
++++ b/drivers/staging/iio/accel/adis16203_core.c
+@@ -191,7 +191,7 @@ static int adis16203_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit adis16203_remove(struct spi_device *spi)
++static int adis16203_remove(struct spi_device *spi)
+ {
+ 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ 	struct adis *st = iio_priv(indio_dev);
+diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c
+index 2e16703f11c1..0680be5baa5f 100644
+--- a/drivers/staging/iio/accel/adis16204_core.c
++++ b/drivers/staging/iio/accel/adis16204_core.c
+@@ -231,7 +231,7 @@ static int adis16204_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit adis16204_remove(struct spi_device *spi)
++static int adis16204_remove(struct spi_device *spi)
+ {
+ 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ 	struct adis *st = iio_priv(indio_dev);
+diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c
+index edd4f3c7983c..0e0c321b12bb 100644
+--- a/drivers/staging/iio/accel/adis16209_core.c
++++ b/drivers/staging/iio/accel/adis16209_core.c
+@@ -224,7 +224,7 @@ static int adis16209_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit adis16209_remove(struct spi_device *spi)
++static int adis16209_remove(struct spi_device *spi)
+ {
+ 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ 	struct adis *st = iio_priv(indio_dev);
+diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c
+index 8cfdc699edd4..4e346891d8ce 100644
+--- a/drivers/staging/iio/accel/adis16220_core.c
++++ b/drivers/staging/iio/accel/adis16220_core.c
+@@ -484,7 +484,7 @@ static int adis16220_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit adis16220_remove(struct spi_device *spi)
++static int adis16220_remove(struct spi_device *spi)
+ {
+ 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ 
+diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c
+index f0c700915418..32195b7f27b3 100644
+--- a/drivers/staging/iio/accel/adis16240_core.c
++++ b/drivers/staging/iio/accel/adis16240_core.c
+@@ -279,7 +279,7 @@ static int adis16240_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit adis16240_remove(struct spi_device *spi)
++static int adis16240_remove(struct spi_device *spi)
+ {
+ 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ 	struct adis *st = iio_priv(indio_dev);
+diff --git a/drivers/staging/iio/accel/kxsd9.c b/drivers/staging/iio/accel/kxsd9.c
+index 6c5f059f1873..9aed044abd1b 100644
+--- a/drivers/staging/iio/accel/kxsd9.c
++++ b/drivers/staging/iio/accel/kxsd9.c
+@@ -261,7 +261,7 @@ static int kxsd9_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit kxsd9_remove(struct spi_device *spi)
++static int kxsd9_remove(struct spi_device *spi)
+ {
+ 	iio_device_unregister(spi_get_drvdata(spi));
+ 	iio_device_free(spi_get_drvdata(spi));
+diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c
+index cffd563549b4..6d88d1e7c0cd 100644
+--- a/drivers/staging/iio/accel/lis3l02dq_core.c
++++ b/drivers/staging/iio/accel/lis3l02dq_core.c
+@@ -782,7 +782,7 @@ static int lis3l02dq_stop_device(struct iio_dev *indio_dev)
+ }
+ 
+ /* fixme, confirm ordering in this function */
+-static int __devexit lis3l02dq_remove(struct spi_device *spi)
++static int lis3l02dq_remove(struct spi_device *spi)
+ {
+ 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ 	struct lis3l02dq_state *st = iio_priv(indio_dev);
+diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c
+index ef2e825c763c..69bdf22707cb 100644
+--- a/drivers/staging/iio/accel/sca3000_core.c
++++ b/drivers/staging/iio/accel/sca3000_core.c
+@@ -1233,7 +1233,7 @@ static int sca3000_stop_all_interrupts(struct sca3000_state *st)
+ 	return ret;
+ }
+ 
+-static int __devexit sca3000_remove(struct spi_device *spi)
++static int sca3000_remove(struct spi_device *spi)
+ {
+ 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ 	struct sca3000_state *st = iio_priv(indio_dev);
+diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c
+index 41b5fe85f451..b9f22028ab4d 100644
+--- a/drivers/staging/iio/adc/ad7192.c
++++ b/drivers/staging/iio/adc/ad7192.c
+@@ -686,7 +686,7 @@ static int ad7192_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit ad7192_remove(struct spi_device *spi)
++static int ad7192_remove(struct spi_device *spi)
+ {
+ 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ 	struct ad7192_state *st = iio_priv(indio_dev);
+diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c
+index 6e9984373efa..9b1a095e79c0 100644
+--- a/drivers/staging/iio/adc/ad7280a.c
++++ b/drivers/staging/iio/adc/ad7280a.c
+@@ -950,7 +950,7 @@ static int ad7280_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit ad7280_remove(struct spi_device *spi)
++static int ad7280_remove(struct spi_device *spi)
+ {
+ 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ 	struct ad7280_state *st = iio_priv(indio_dev);
+diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c
+index bea5cc4529e3..69a6c9651c66 100644
+--- a/drivers/staging/iio/adc/ad7291.c
++++ b/drivers/staging/iio/adc/ad7291.c
+@@ -674,7 +674,7 @@ static int ad7291_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit ad7291_remove(struct i2c_client *client)
++static int ad7291_remove(struct i2c_client *client)
+ {
+ 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ 	struct ad7291_chip_info *chip = iio_priv(indio_dev);
+diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/staging/iio/adc/ad7606_par.c
+index b45002dfc8b8..2b42d120c9f5 100644
+--- a/drivers/staging/iio/adc/ad7606_par.c
++++ b/drivers/staging/iio/adc/ad7606_par.c
+@@ -100,7 +100,7 @@ static int ad7606_par_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit ad7606_par_remove(struct platform_device *pdev)
++static int ad7606_par_remove(struct platform_device *pdev)
+ {
+ 	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+ 	struct resource *res;
+diff --git a/drivers/staging/iio/adc/ad7606_spi.c b/drivers/staging/iio/adc/ad7606_spi.c
+index 78d68659665e..1bbb86dcdb8e 100644
+--- a/drivers/staging/iio/adc/ad7606_spi.c
++++ b/drivers/staging/iio/adc/ad7606_spi.c
+@@ -55,7 +55,7 @@ static int ad7606_spi_probe(struct spi_device *spi)
+ 	return 0;
+ }
+ 
+-static int __devexit ad7606_spi_remove(struct spi_device *spi)
++static int ad7606_spi_remove(struct spi_device *spi)
+ {
+ 	struct iio_dev *indio_dev = dev_get_drvdata(&spi->dev);
+ 
+diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c
+index eb487d3c8d53..831c9d7a948b 100644
+--- a/drivers/staging/iio/adc/ad7780.c
++++ b/drivers/staging/iio/adc/ad7780.c
+@@ -248,7 +248,7 @@ static int ad7780_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit ad7780_remove(struct spi_device *spi)
++static int ad7780_remove(struct spi_device *spi)
+ {
+ 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ 	struct ad7780_state *st = iio_priv(indio_dev);
+diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c
+index d7a272e7b6b1..9084b2d8fe03 100644
+--- a/drivers/staging/iio/adc/ad7793.c
++++ b/drivers/staging/iio/adc/ad7793.c
+@@ -522,7 +522,7 @@ static int ad7793_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit ad7793_remove(struct spi_device *spi)
++static int ad7793_remove(struct spi_device *spi)
+ {
+ 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ 	struct ad7793_state *st = iio_priv(indio_dev);
+diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c
+index b49fc6c53927..2dbe68b0ce2f 100644
+--- a/drivers/staging/iio/adc/ad7816.c
++++ b/drivers/staging/iio/adc/ad7816.c
+@@ -431,7 +431,7 @@ static int ad7816_probe(struct spi_device *spi_dev)
+ 	return ret;
+ }
+ 
+-static int __devexit ad7816_remove(struct spi_device *spi_dev)
++static int ad7816_remove(struct spi_device *spi_dev)
+ {
+ 	struct iio_dev *indio_dev = dev_get_drvdata(&spi_dev->dev);
+ 	struct ad7816_chip_info *chip = iio_priv(indio_dev);
+diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c
+index 758527987fdd..7cb90112b2c2 100644
+--- a/drivers/staging/iio/adc/ad799x_core.c
++++ b/drivers/staging/iio/adc/ad799x_core.c
+@@ -932,7 +932,7 @@ static int ad799x_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static __devexit int ad799x_remove(struct i2c_client *client)
++static int ad799x_remove(struct i2c_client *client)
+ {
+ 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ 	struct ad799x_state *st = iio_priv(indio_dev);
+diff --git a/drivers/staging/iio/adc/adt7410.c b/drivers/staging/iio/adc/adt7410.c
+index f41994dd8d6d..d55efe46fac2 100644
+--- a/drivers/staging/iio/adc/adt7410.c
++++ b/drivers/staging/iio/adc/adt7410.c
+@@ -792,7 +792,7 @@ static int adt7410_probe(struct device *dev, int irq,
+ 	return ret;
+ }
+ 
+-static int __devexit adt7410_remove(struct device *dev, int irq)
++static int adt7410_remove(struct device *dev, int irq)
+ {
+ 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ 	unsigned long *adt7410_platform_data = dev->platform_data;
+@@ -883,7 +883,7 @@ static int adt7410_i2c_probe(struct i2c_client *client,
+ 		&adt7410_i2c_ops);
+ }
+ 
+-static int __devexit adt7410_i2c_remove(struct i2c_client *client)
++static int adt7410_i2c_remove(struct i2c_client *client)
+ {
+ 	return adt7410_remove(&client->dev, client->irq);
+ }
+@@ -1036,7 +1036,7 @@ static int adt7310_spi_probe(struct spi_device *spi)
+ 		spi_get_device_id(spi)->name, &adt7310_spi_ops);
+ }
+ 
+-static int __devexit adt7310_spi_remove(struct spi_device *spi)
++static int adt7310_spi_remove(struct spi_device *spi)
+ {
+ 	return adt7410_remove(&spi->dev, spi->irq);
+ }
+diff --git a/drivers/staging/iio/adc/lpc32xx_adc.c b/drivers/staging/iio/adc/lpc32xx_adc.c
+index f38aa92146a3..7b9b9a5cf025 100644
+--- a/drivers/staging/iio/adc/lpc32xx_adc.c
++++ b/drivers/staging/iio/adc/lpc32xx_adc.c
+@@ -207,7 +207,7 @@ static int lpc32xx_adc_probe(struct platform_device *pdev)
+ 	return retval;
+ }
+ 
+-static int __devexit lpc32xx_adc_remove(struct platform_device *pdev)
++static int lpc32xx_adc_remove(struct platform_device *pdev)
+ {
+ 	struct iio_dev *iodev = platform_get_drvdata(pdev);
+ 	struct lpc32xx_adc_info *info = iio_priv(iodev);
+diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c
+index b91cf850b078..c6d00f2f2b17 100644
+--- a/drivers/staging/iio/adc/mxs-lradc.c
++++ b/drivers/staging/iio/adc/mxs-lradc.c
+@@ -551,7 +551,7 @@ static int mxs_lradc_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit mxs_lradc_remove(struct platform_device *pdev)
++static int mxs_lradc_remove(struct platform_device *pdev)
+ {
+ 	struct iio_dev *iio = platform_get_drvdata(pdev);
+ 	struct mxs_lradc *lradc = iio_priv(iio);
+diff --git a/drivers/staging/iio/adc/spear_adc.c b/drivers/staging/iio/adc/spear_adc.c
+index e1a55b368a65..a09a8262e4ff 100644
+--- a/drivers/staging/iio/adc/spear_adc.c
++++ b/drivers/staging/iio/adc/spear_adc.c
+@@ -401,7 +401,7 @@ static int spear_adc_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit spear_adc_remove(struct platform_device *pdev)
++static int spear_adc_remove(struct platform_device *pdev)
+ {
+ 	struct iio_dev *iodev = platform_get_drvdata(pdev);
+ 	struct spear_adc_info *info = iio_priv(iodev);
+diff --git a/drivers/staging/iio/addac/adt7316-i2c.c b/drivers/staging/iio/addac/adt7316-i2c.c
+index cde82cf94ee4..b86e76c15bc0 100644
+--- a/drivers/staging/iio/addac/adt7316-i2c.c
++++ b/drivers/staging/iio/addac/adt7316-i2c.c
+@@ -108,7 +108,7 @@ static int adt7316_i2c_probe(struct i2c_client *client,
+ 	return adt7316_probe(&client->dev, &bus, id->name);
+ }
+ 
+-static int __devexit adt7316_i2c_remove(struct i2c_client *client)
++static int adt7316_i2c_remove(struct i2c_client *client)
+ {
+ 	return adt7316_remove(&client->dev);
+ }
+diff --git a/drivers/staging/iio/addac/adt7316-spi.c b/drivers/staging/iio/addac/adt7316-spi.c
+index 99631ed380a9..c451504ef914 100644
+--- a/drivers/staging/iio/addac/adt7316-spi.c
++++ b/drivers/staging/iio/addac/adt7316-spi.c
+@@ -116,7 +116,7 @@ static int adt7316_spi_probe(struct spi_device *spi_dev)
+ 	return adt7316_probe(&spi_dev->dev, &bus, spi_dev->modalias);
+ }
+ 
+-static int __devexit adt7316_spi_remove(struct spi_device *spi_dev)
++static int adt7316_spi_remove(struct spi_device *spi_dev)
+ {
+ 	return adt7316_remove(&spi_dev->dev);
+ }
+diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c
+index 487f5e039872..0b431bc4f627 100644
+--- a/drivers/staging/iio/addac/adt7316.c
++++ b/drivers/staging/iio/addac/adt7316.c
+@@ -2216,7 +2216,7 @@ int adt7316_probe(struct device *dev, struct adt7316_bus *bus,
+ }
+ EXPORT_SYMBOL(adt7316_probe);
+ 
+-int __devexit adt7316_remove(struct device *dev)
++int adt7316_remove(struct device *dev)
+ {
+ 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ 	struct adt7316_chip_info *chip = iio_priv(indio_dev);
+diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c
+index 4ee4bfb4d29c..a4d83b68df81 100644
+--- a/drivers/staging/iio/cdc/ad7150.c
++++ b/drivers/staging/iio/cdc/ad7150.c
+@@ -628,7 +628,7 @@ static int ad7150_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit ad7150_remove(struct i2c_client *client)
++static int ad7150_remove(struct i2c_client *client)
+ {
+ 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/staging/iio/cdc/ad7152.c b/drivers/staging/iio/cdc/ad7152.c
+index e12e99beeb25..ec89a065d707 100644
+--- a/drivers/staging/iio/cdc/ad7152.c
++++ b/drivers/staging/iio/cdc/ad7152.c
+@@ -518,7 +518,7 @@ static int ad7152_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit ad7152_remove(struct i2c_client *client)
++static int ad7152_remove(struct i2c_client *client)
+ {
+ 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c
+index 5c9d204de49d..f0787eeb8363 100644
+--- a/drivers/staging/iio/cdc/ad7746.c
++++ b/drivers/staging/iio/cdc/ad7746.c
+@@ -768,7 +768,7 @@ static int ad7746_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit ad7746_remove(struct i2c_client *client)
++static int ad7746_remove(struct i2c_client *client)
+ {
+ 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/staging/iio/frequency/ad5930.c b/drivers/staging/iio/frequency/ad5930.c
+index 7dfaf801df9d..027f73b63e04 100644
+--- a/drivers/staging/iio/frequency/ad5930.c
++++ b/drivers/staging/iio/frequency/ad5930.c
+@@ -127,7 +127,7 @@ static int ad5930_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit ad5930_remove(struct spi_device *spi)
++static int ad5930_remove(struct spi_device *spi)
+ {
+ 	iio_device_unregister(spi_get_drvdata(spi));
+ 	iio_device_free(spi_get_drvdata(spi));
+diff --git a/drivers/staging/iio/frequency/ad9832.c b/drivers/staging/iio/frequency/ad9832.c
+index 593e1888067e..ea3c63b79062 100644
+--- a/drivers/staging/iio/frequency/ad9832.c
++++ b/drivers/staging/iio/frequency/ad9832.c
+@@ -324,7 +324,7 @@ static int ad9832_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit ad9832_remove(struct spi_device *spi)
++static int ad9832_remove(struct spi_device *spi)
+ {
+ 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ 	struct ad9832_state *st = iio_priv(indio_dev);
+diff --git a/drivers/staging/iio/frequency/ad9834.c b/drivers/staging/iio/frequency/ad9834.c
+index 453698b4d8be..f6b583eacafa 100644
+--- a/drivers/staging/iio/frequency/ad9834.c
++++ b/drivers/staging/iio/frequency/ad9834.c
+@@ -424,7 +424,7 @@ static int ad9834_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit ad9834_remove(struct spi_device *spi)
++static int ad9834_remove(struct spi_device *spi)
+ {
+ 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ 	struct ad9834_state *st = iio_priv(indio_dev);
+diff --git a/drivers/staging/iio/frequency/ad9850.c b/drivers/staging/iio/frequency/ad9850.c
+index 1e6a2b351d63..f64702758b5e 100644
+--- a/drivers/staging/iio/frequency/ad9850.c
++++ b/drivers/staging/iio/frequency/ad9850.c
+@@ -113,7 +113,7 @@ static int ad9850_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit ad9850_remove(struct spi_device *spi)
++static int ad9850_remove(struct spi_device *spi)
+ {
+ 	iio_device_unregister(spi_get_drvdata(spi));
+ 	iio_device_free(spi_get_drvdata(spi));
+diff --git a/drivers/staging/iio/frequency/ad9852.c b/drivers/staging/iio/frequency/ad9852.c
+index 84a4f1d37bbf..5475c75fd2b2 100644
+--- a/drivers/staging/iio/frequency/ad9852.c
++++ b/drivers/staging/iio/frequency/ad9852.c
+@@ -264,7 +264,7 @@ static int ad9852_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit ad9852_remove(struct spi_device *spi)
++static int ad9852_remove(struct spi_device *spi)
+ {
+ 	iio_device_unregister(spi_get_drvdata(spi));
+ 	iio_device_free(spi_get_drvdata(spi));
+diff --git a/drivers/staging/iio/frequency/ad9910.c b/drivers/staging/iio/frequency/ad9910.c
+index 9c569bcb4ae1..f79b03b15504 100644
+--- a/drivers/staging/iio/frequency/ad9910.c
++++ b/drivers/staging/iio/frequency/ad9910.c
+@@ -397,7 +397,7 @@ static int ad9910_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit ad9910_remove(struct spi_device *spi)
++static int ad9910_remove(struct spi_device *spi)
+ {
+ 	iio_device_unregister(spi_get_drvdata(spi));
+ 	iio_device_free(spi_get_drvdata(spi));
+diff --git a/drivers/staging/iio/frequency/ad9951.c b/drivers/staging/iio/frequency/ad9951.c
+index e53d47e35a68..fb2f77144ad4 100644
+--- a/drivers/staging/iio/frequency/ad9951.c
++++ b/drivers/staging/iio/frequency/ad9951.c
+@@ -208,7 +208,7 @@ static int ad9951_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit ad9951_remove(struct spi_device *spi)
++static int ad9951_remove(struct spi_device *spi)
+ {
+ 	iio_device_unregister(spi_get_drvdata(spi));
+ 	iio_device_free(spi_get_drvdata(spi));
+diff --git a/drivers/staging/iio/gyro/adis16060_core.c b/drivers/staging/iio/gyro/adis16060_core.c
+index af1469beb189..ac806177b655 100644
+--- a/drivers/staging/iio/gyro/adis16060_core.c
++++ b/drivers/staging/iio/gyro/adis16060_core.c
+@@ -184,7 +184,7 @@ static int adis16060_r_probe(struct spi_device *spi)
+ }
+ 
+ /* fixme, confirm ordering in this function */
+-static int __devexit adis16060_r_remove(struct spi_device *spi)
++static int adis16060_r_remove(struct spi_device *spi)
+ {
+ 	iio_device_unregister(spi_get_drvdata(spi));
+ 	iio_device_free(spi_get_drvdata(spi));
+@@ -210,7 +210,7 @@ static int adis16060_w_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit adis16060_w_remove(struct spi_device *spi)
++static int adis16060_w_remove(struct spi_device *spi)
+ {
+ 	return 0;
+ }
+diff --git a/drivers/staging/iio/gyro/adis16080_core.c b/drivers/staging/iio/gyro/adis16080_core.c
+index 244e7b09ffd0..be345b0fd975 100644
+--- a/drivers/staging/iio/gyro/adis16080_core.c
++++ b/drivers/staging/iio/gyro/adis16080_core.c
+@@ -177,7 +177,7 @@ static int adis16080_probe(struct spi_device *spi)
+ }
+ 
+ /* fixme, confirm ordering in this function */
+-static int __devexit adis16080_remove(struct spi_device *spi)
++static int adis16080_remove(struct spi_device *spi)
+ {
+ 	iio_device_unregister(spi_get_drvdata(spi));
+ 	iio_device_free(spi_get_drvdata(spi));
+diff --git a/drivers/staging/iio/gyro/adis16130_core.c b/drivers/staging/iio/gyro/adis16130_core.c
+index c778fd07f496..a6df05d6c5e7 100644
+--- a/drivers/staging/iio/gyro/adis16130_core.c
++++ b/drivers/staging/iio/gyro/adis16130_core.c
+@@ -154,7 +154,7 @@ static int adis16130_probe(struct spi_device *spi)
+ }
+ 
+ /* fixme, confirm ordering in this function */
+-static int __devexit adis16130_remove(struct spi_device *spi)
++static int adis16130_remove(struct spi_device *spi)
+ {
+ 	iio_device_unregister(spi_get_drvdata(spi));
+ 	iio_device_free(spi_get_drvdata(spi));
+diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c
+index 030113b991da..a549b97e14dc 100644
+--- a/drivers/staging/iio/gyro/adis16260_core.c
++++ b/drivers/staging/iio/gyro/adis16260_core.c
+@@ -384,7 +384,7 @@ static int adis16260_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit adis16260_remove(struct spi_device *spi)
++static int adis16260_remove(struct spi_device *spi)
+ {
+ 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ 	struct adis16260_state *st = iio_priv(indio_dev);
+diff --git a/drivers/staging/iio/gyro/adxrs450_core.c b/drivers/staging/iio/gyro/adxrs450_core.c
+index 07b86bf9540a..63f177189e0b 100644
+--- a/drivers/staging/iio/gyro/adxrs450_core.c
++++ b/drivers/staging/iio/gyro/adxrs450_core.c
+@@ -409,7 +409,7 @@ static int adxrs450_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit adxrs450_remove(struct spi_device *spi)
++static int adxrs450_remove(struct spi_device *spi)
+ {
+ 	iio_device_unregister(spi_get_drvdata(spi));
+ 	iio_device_free(spi_get_drvdata(spi));
+diff --git a/drivers/staging/iio/iio_hwmon.c b/drivers/staging/iio/iio_hwmon.c
+index a24330884b78..5ed147235259 100644
+--- a/drivers/staging/iio/iio_hwmon.c
++++ b/drivers/staging/iio/iio_hwmon.c
+@@ -170,7 +170,7 @@ static int iio_hwmon_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit iio_hwmon_remove(struct platform_device *pdev)
++static int iio_hwmon_remove(struct platform_device *pdev)
+ {
+ 	struct iio_hwmon_state *st = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c
+index e2689978eb9e..99b5f8ca0864 100644
+--- a/drivers/staging/iio/impedance-analyzer/ad5933.c
++++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
+@@ -787,7 +787,7 @@ static int ad5933_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static __devexit int ad5933_remove(struct i2c_client *client)
++static int ad5933_remove(struct i2c_client *client)
+ {
+ 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ 	struct ad5933_state *st = iio_priv(indio_dev);
+diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c
+index 490359d8b162..18197f249d85 100644
+--- a/drivers/staging/iio/imu/adis16400_core.c
++++ b/drivers/staging/iio/imu/adis16400_core.c
+@@ -1273,7 +1273,7 @@ static int adis16400_probe(struct spi_device *spi)
+ }
+ 
+ /* fixme, confirm ordering in this function */
+-static int __devexit adis16400_remove(struct spi_device *spi)
++static int adis16400_remove(struct spi_device *spi)
+ {
+ 	struct iio_dev *indio_dev =  spi_get_drvdata(spi);
+ 
+diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c
+index e305f050f780..a6242aa6f5c9 100644
+--- a/drivers/staging/iio/light/isl29018.c
++++ b/drivers/staging/iio/light/isl29018.c
+@@ -598,7 +598,7 @@ static int isl29018_probe(struct i2c_client *client,
+ 	return err;
+ }
+ 
+-static int __devexit isl29018_remove(struct i2c_client *client)
++static int isl29018_remove(struct i2c_client *client)
+ {
+ 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c
+index 4b1def75d300..bcf4a8f47b4a 100644
+--- a/drivers/staging/iio/light/isl29028.c
++++ b/drivers/staging/iio/light/isl29028.c
+@@ -526,7 +526,7 @@ static int isl29028_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit isl29028_remove(struct i2c_client *client)
++static int isl29028_remove(struct i2c_client *client)
+ {
+ 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c
+index 2ca586e73dec..ecd6347950d1 100644
+--- a/drivers/staging/iio/light/tsl2563.c
++++ b/drivers/staging/iio/light/tsl2563.c
+@@ -805,7 +805,7 @@ static int tsl2563_probe(struct i2c_client *client,
+ 	return err;
+ }
+ 
+-static int __devexit tsl2563_remove(struct i2c_client *client)
++static int tsl2563_remove(struct i2c_client *client)
+ {
+ 	struct tsl2563_chip *chip = i2c_get_clientdata(client);
+ 	struct iio_dev *indio_dev = iio_priv_to_dev(chip);
+diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c
+index f4b7d914cdf3..133bac297030 100644
+--- a/drivers/staging/iio/light/tsl2583.c
++++ b/drivers/staging/iio/light/tsl2583.c
+@@ -923,7 +923,7 @@ static SIMPLE_DEV_PM_OPS(taos_pm_ops, taos_suspend, taos_resume);
+ #define TAOS_PM_OPS NULL
+ #endif
+ 
+-static int __devexit taos_remove(struct i2c_client *client)
++static int taos_remove(struct i2c_client *client)
+ {
+ 	iio_device_unregister(i2c_get_clientdata(client));
+ 	iio_device_free(i2c_get_clientdata(client));
+diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x_core.c
+index 3864e8af709f..51450e21d3e9 100644
+--- a/drivers/staging/iio/light/tsl2x7x_core.c
++++ b/drivers/staging/iio/light/tsl2x7x_core.c
+@@ -2026,7 +2026,7 @@ static int tsl2x7x_resume(struct device *dev)
+ 	return ret;
+ }
+ 
+-static int __devexit tsl2x7x_remove(struct i2c_client *client)
++static int tsl2x7x_remove(struct i2c_client *client)
+ {
+ 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/staging/iio/magnetometer/ak8975.c b/drivers/staging/iio/magnetometer/ak8975.c
+index 6f0697facb34..22a4addd15f0 100644
+--- a/drivers/staging/iio/magnetometer/ak8975.c
++++ b/drivers/staging/iio/magnetometer/ak8975.c
+@@ -475,7 +475,7 @@ static int ak8975_probe(struct i2c_client *client,
+ 	return err;
+ }
+ 
+-static int __devexit ak8975_remove(struct i2c_client *client)
++static int ak8975_remove(struct i2c_client *client)
+ {
+ 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ 	struct ak8975_data *data = iio_priv(indio_dev);
+diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c
+index c1d96a4bbbc4..e151fcafecc4 100644
+--- a/drivers/staging/iio/magnetometer/hmc5843.c
++++ b/drivers/staging/iio/magnetometer/hmc5843.c
+@@ -704,7 +704,7 @@ static int hmc5843_probe(struct i2c_client *client,
+ 	return err;
+ }
+ 
+-static int __devexit hmc5843_remove(struct i2c_client *client)
++static int hmc5843_remove(struct i2c_client *client)
+ {
+ 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c
+index 7fc2408fbcf7..d8b1686f3bc0 100644
+--- a/drivers/staging/iio/meter/ade7753.c
++++ b/drivers/staging/iio/meter/ade7753.c
+@@ -555,7 +555,7 @@ static int ade7753_probe(struct spi_device *spi)
+ }
+ 
+ /* fixme, confirm ordering in this function */
+-static int __devexit ade7753_remove(struct spi_device *spi)
++static int ade7753_remove(struct spi_device *spi)
+ {
+ 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ 
+diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c
+index 0ee1f264adb0..8383c31e269e 100644
+--- a/drivers/staging/iio/meter/ade7754.c
++++ b/drivers/staging/iio/meter/ade7754.c
+@@ -577,7 +577,7 @@ static int ade7754_probe(struct spi_device *spi)
+ }
+ 
+ /* fixme, confirm ordering in this function */
+-static int __devexit ade7754_remove(struct spi_device *spi)
++static int ade7754_remove(struct spi_device *spi)
+ {
+ 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ 
+diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c
+index 21bda06ab93a..f50dacb1719f 100644
+--- a/drivers/staging/iio/meter/ade7758_core.c
++++ b/drivers/staging/iio/meter/ade7758_core.c
+@@ -962,7 +962,7 @@ static int ade7758_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit ade7758_remove(struct spi_device *spi)
++static int ade7758_remove(struct spi_device *spi)
+ {
+ 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ 	struct ade7758_state *st = iio_priv(indio_dev);
+diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c
+index b3a6c3031cfe..4feb14dc3964 100644
+--- a/drivers/staging/iio/meter/ade7759.c
++++ b/drivers/staging/iio/meter/ade7759.c
+@@ -499,7 +499,7 @@ static int ade7759_probe(struct spi_device *spi)
+ }
+ 
+ /* fixme, confirm ordering in this function */
+-static int __devexit ade7759_remove(struct spi_device *spi)
++static int ade7759_remove(struct spi_device *spi)
+ {
+ 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ 
+diff --git a/drivers/staging/iio/meter/ade7854-i2c.c b/drivers/staging/iio/meter/ade7854-i2c.c
+index 56809266ef8f..2f83a540edbf 100644
+--- a/drivers/staging/iio/meter/ade7854-i2c.c
++++ b/drivers/staging/iio/meter/ade7854-i2c.c
+@@ -231,7 +231,7 @@ static int ade7854_i2c_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit ade7854_i2c_remove(struct i2c_client *client)
++static int ade7854_i2c_remove(struct i2c_client *client)
+ {
+ 	return ade7854_remove(i2c_get_clientdata(client));
+ }
+diff --git a/drivers/staging/iio/meter/ade7854-spi.c b/drivers/staging/iio/meter/ade7854-spi.c
+index 7826f299f8dd..35b308aa9b81 100644
+--- a/drivers/staging/iio/meter/ade7854-spi.c
++++ b/drivers/staging/iio/meter/ade7854-spi.c
+@@ -330,7 +330,7 @@ static int ade7854_spi_probe(struct spi_device *spi)
+ 	return 0;
+ }
+ 
+-static int __devexit ade7854_spi_remove(struct spi_device *spi)
++static int ade7854_spi_remove(struct spi_device *spi)
+ {
+ 	ade7854_remove(spi_get_drvdata(spi));
+ 
+diff --git a/drivers/staging/iio/resolver/ad2s1200.c b/drivers/staging/iio/resolver/ad2s1200.c
+index d102a7e18f6f..d7f4efb9e8d1 100644
+--- a/drivers/staging/iio/resolver/ad2s1200.c
++++ b/drivers/staging/iio/resolver/ad2s1200.c
+@@ -149,7 +149,7 @@ static int ad2s1200_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit ad2s1200_remove(struct spi_device *spi)
++static int ad2s1200_remove(struct spi_device *spi)
+ {
+ 	iio_device_unregister(spi_get_drvdata(spi));
+ 	iio_device_free(spi_get_drvdata(spi));
+diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c
+index 98c653c82c3a..d57c62945e78 100644
+--- a/drivers/staging/iio/resolver/ad2s1210.c
++++ b/drivers/staging/iio/resolver/ad2s1210.c
+@@ -736,7 +736,7 @@ static int ad2s1210_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit ad2s1210_remove(struct spi_device *spi)
++static int ad2s1210_remove(struct spi_device *spi)
+ {
+ 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ 
+diff --git a/drivers/staging/iio/resolver/ad2s90.c b/drivers/staging/iio/resolver/ad2s90.c
+index f9451abd7f53..f2aa7ddc7d17 100644
+--- a/drivers/staging/iio/resolver/ad2s90.c
++++ b/drivers/staging/iio/resolver/ad2s90.c
+@@ -98,7 +98,7 @@ static int ad2s90_probe(struct spi_device *spi)
+ 	return ret;
+ }
+ 
+-static int __devexit ad2s90_remove(struct spi_device *spi)
++static int ad2s90_remove(struct spi_device *spi)
+ {
+ 	iio_device_unregister(spi_get_drvdata(spi));
+ 	iio_device_free(spi_get_drvdata(spi));
+diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
+index 91412e42ca40..8c45c7cfca99 100644
+--- a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
++++ b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
+@@ -275,7 +275,7 @@ static int iio_bfin_tmr_trigger_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit iio_bfin_tmr_trigger_remove(struct platform_device *pdev)
++static int iio_bfin_tmr_trigger_remove(struct platform_device *pdev)
+ {
+ 	struct bfin_tmr_state *st = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/staging/iio/trigger/iio-trig-gpio.c b/drivers/staging/iio/trigger/iio-trig-gpio.c
+index 2dc57121a743..c0be7908c087 100644
+--- a/drivers/staging/iio/trigger/iio-trig-gpio.c
++++ b/drivers/staging/iio/trigger/iio-trig-gpio.c
+@@ -130,7 +130,7 @@ static int iio_gpio_trigger_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit iio_gpio_trigger_remove(struct platform_device *pdev)
++static int iio_gpio_trigger_remove(struct platform_device *pdev)
+ {
+ 	struct iio_trigger *trig, *trig2;
+ 	struct iio_gpio_trigger_info *trig_info;
+diff --git a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
+index 643dcff394c3..304b653b5859 100644
+--- a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
++++ b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
+@@ -167,7 +167,7 @@ static int iio_trig_periodic_rtc_probe(struct platform_device *dev)
+ 	return ret;
+ }
+ 
+-static int __devexit iio_trig_periodic_rtc_remove(struct platform_device *dev)
++static int iio_trig_periodic_rtc_remove(struct platform_device *dev)
+ {
+ 	struct iio_trigger *trig, *trig2;
+ 	struct iio_prtc_trigger_info *trig_info;

commit 4ae1c61ff2ba4fea4e4c1a045cb1f34520608789
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:57 2012 -0500
+
+    staging: iio: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Jonathan Cameron 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c
+index ccdc8d23f6a3..8cb9fc32d099 100644
+--- a/drivers/staging/iio/accel/adis16201_core.c
++++ b/drivers/staging/iio/accel/adis16201_core.c
+@@ -175,7 +175,7 @@ static const struct adis_data adis16201_data = {
+ 		BIT(ADIS16201_DIAG_STAT_POWER_LOW_BIT),
+ };
+ 
+-static int __devinit adis16201_probe(struct spi_device *spi)
++static int adis16201_probe(struct spi_device *spi)
+ {
+ 	int ret;
+ 	struct adis *st;
+diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c
+index 202985ea3531..1def6fb0efc9 100644
+--- a/drivers/staging/iio/accel/adis16203_core.c
++++ b/drivers/staging/iio/accel/adis16203_core.c
+@@ -141,7 +141,7 @@ static const struct adis_data adis16203_data = {
+ 		BIT(ADIS16203_DIAG_STAT_POWER_LOW_BIT),
+ };
+ 
+-static int __devinit adis16203_probe(struct spi_device *spi)
++static int adis16203_probe(struct spi_device *spi)
+ {
+ 	int ret;
+ 	struct iio_dev *indio_dev;
+diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c
+index 6dafad67cd23..2e16703f11c1 100644
+--- a/drivers/staging/iio/accel/adis16204_core.c
++++ b/drivers/staging/iio/accel/adis16204_core.c
+@@ -182,7 +182,7 @@ static const struct adis_data adis16204_data = {
+ 		BIT(ADIS16204_DIAG_STAT_POWER_LOW_BIT),
+ };
+ 
+-static int __devinit adis16204_probe(struct spi_device *spi)
++static int adis16204_probe(struct spi_device *spi)
+ {
+ 	int ret;
+ 	struct adis *st;
+diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c
+index d2921c30a8bb..edd4f3c7983c 100644
+--- a/drivers/staging/iio/accel/adis16209_core.c
++++ b/drivers/staging/iio/accel/adis16209_core.c
+@@ -176,7 +176,7 @@ static const struct adis_data adis16209_data = {
+ };
+ 
+ 
+-static int __devinit adis16209_probe(struct spi_device *spi)
++static int adis16209_probe(struct spi_device *spi)
+ {
+ 	int ret;
+ 	struct adis *st;
+diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c
+index c39ce622eb62..8cfdc699edd4 100644
+--- a/drivers/staging/iio/accel/adis16220_core.c
++++ b/drivers/staging/iio/accel/adis16220_core.c
+@@ -421,7 +421,7 @@ static const struct adis_data adis16220_data = {
+ 		BIT(ADIS16220_DIAG_STAT_POWER_LOW_BIT),
+ };
+ 
+-static int __devinit adis16220_probe(struct spi_device *spi)
++static int adis16220_probe(struct spi_device *spi)
+ {
+ 	int ret;
+ 	struct adis16220_state *st;
+diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c
+index d098b49cc18b..f0c700915418 100644
+--- a/drivers/staging/iio/accel/adis16240_core.c
++++ b/drivers/staging/iio/accel/adis16240_core.c
+@@ -232,7 +232,7 @@ static const struct adis_data adis16240_data = {
+ 		BIT(ADIS16240_DIAG_STAT_POWER_LOW_BIT),
+ };
+ 
+-static int __devinit adis16240_probe(struct spi_device *spi)
++static int adis16240_probe(struct spi_device *spi)
+ {
+ 	int ret;
+ 	struct adis *st;
+diff --git a/drivers/staging/iio/accel/kxsd9.c b/drivers/staging/iio/accel/kxsd9.c
+index e8e6e3fbcec0..6c5f059f1873 100644
+--- a/drivers/staging/iio/accel/kxsd9.c
++++ b/drivers/staging/iio/accel/kxsd9.c
+@@ -200,7 +200,7 @@ static const struct attribute_group kxsd9_attribute_group = {
+ 	.attrs = kxsd9_attributes,
+ };
+ 
+-static int __devinit kxsd9_power_up(struct kxsd9_state *st)
++static int kxsd9_power_up(struct kxsd9_state *st)
+ {
+ 	int ret;
+ 
+@@ -222,7 +222,7 @@ static const struct iio_info kxsd9_info = {
+ 	.driver_module = THIS_MODULE,
+ };
+ 
+-static int __devinit kxsd9_probe(struct spi_device *spi)
++static int kxsd9_probe(struct spi_device *spi)
+ {
+ 	struct iio_dev *indio_dev;
+ 	struct kxsd9_state *st;
+diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c
+index d13c7e98978d..cffd563549b4 100644
+--- a/drivers/staging/iio/accel/lis3l02dq_core.c
++++ b/drivers/staging/iio/accel/lis3l02dq_core.c
+@@ -675,7 +675,7 @@ static const struct iio_info lis3l02dq_info = {
+ 	.attrs = &lis3l02dq_attribute_group,
+ };
+ 
+-static int __devinit lis3l02dq_probe(struct spi_device *spi)
++static int lis3l02dq_probe(struct spi_device *spi)
+ {
+ 	int ret;
+ 	struct lis3l02dq_state *st;
+diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c
+index ffd1697a9db0..ef2e825c763c 100644
+--- a/drivers/staging/iio/accel/sca3000_core.c
++++ b/drivers/staging/iio/accel/sca3000_core.c
+@@ -1139,7 +1139,7 @@ static const struct iio_info sca3000_info_with_temp = {
+ 	.driver_module = THIS_MODULE,
+ };
+ 
+-static int __devinit sca3000_probe(struct spi_device *spi)
++static int sca3000_probe(struct spi_device *spi)
+ {
+ 	int ret;
+ 	struct sca3000_state *st;
+diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c
+index aeaa61d49f51..41b5fe85f451 100644
+--- a/drivers/staging/iio/adc/ad7192.c
++++ b/drivers/staging/iio/adc/ad7192.c
+@@ -606,7 +606,7 @@ static const struct iio_chan_spec ad7192_channels[] = {
+ 	IIO_CHAN_SOFT_TIMESTAMP(8),
+ };
+ 
+-static int __devinit ad7192_probe(struct spi_device *spi)
++static int ad7192_probe(struct spi_device *spi)
+ {
+ 	const struct ad7192_platform_data *pdata = spi->dev.platform_data;
+ 	struct ad7192_state *st;
+diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c
+index e7cb3b2fe67f..6e9984373efa 100644
+--- a/drivers/staging/iio/adc/ad7280a.c
++++ b/drivers/staging/iio/adc/ad7280a.c
+@@ -832,7 +832,7 @@ static const struct ad7280_platform_data ad7793_default_pdata = {
+ 	.thermistor_term_en = true,
+ };
+ 
+-static int __devinit ad7280_probe(struct spi_device *spi)
++static int ad7280_probe(struct spi_device *spi)
+ {
+ 	const struct ad7280_platform_data *pdata = spi->dev.platform_data;
+ 	struct ad7280_state *st;
+diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c
+index 029b39c0ba60..bea5cc4529e3 100644
+--- a/drivers/staging/iio/adc/ad7291.c
++++ b/drivers/staging/iio/adc/ad7291.c
+@@ -580,7 +580,7 @@ static const struct iio_info ad7291_info = {
+ 	.event_attrs = &ad7291_event_attribute_group,
+ };
+ 
+-static int __devinit ad7291_probe(struct i2c_client *client,
++static int ad7291_probe(struct i2c_client *client,
+ 		const struct i2c_device_id *id)
+ {
+ 	struct ad7291_chip_info *chip;
+diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/staging/iio/adc/ad7606_par.c
+index a53faafec070..b45002dfc8b8 100644
+--- a/drivers/staging/iio/adc/ad7606_par.c
++++ b/drivers/staging/iio/adc/ad7606_par.c
+@@ -47,7 +47,7 @@ static const struct ad7606_bus_ops ad7606_par8_bops = {
+ 	.read_block	= ad7606_par8_read_block,
+ };
+ 
+-static int __devinit ad7606_par_probe(struct platform_device *pdev)
++static int ad7606_par_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res;
+ 	struct iio_dev *indio_dev;
+diff --git a/drivers/staging/iio/adc/ad7606_spi.c b/drivers/staging/iio/adc/ad7606_spi.c
+index 099d347da52d..78d68659665e 100644
+--- a/drivers/staging/iio/adc/ad7606_spi.c
++++ b/drivers/staging/iio/adc/ad7606_spi.c
+@@ -39,7 +39,7 @@ static const struct ad7606_bus_ops ad7606_spi_bops = {
+ 	.read_block	= ad7606_spi_read_block,
+ };
+ 
+-static int __devinit ad7606_spi_probe(struct spi_device *spi)
++static int ad7606_spi_probe(struct spi_device *spi)
+ {
+ 	struct iio_dev *indio_dev;
+ 
+diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c
+index 0a1328b8657f..eb487d3c8d53 100644
+--- a/drivers/staging/iio/adc/ad7780.c
++++ b/drivers/staging/iio/adc/ad7780.c
+@@ -164,7 +164,7 @@ static const struct iio_info ad7780_info = {
+ 	.driver_module = THIS_MODULE,
+ };
+ 
+-static int __devinit ad7780_probe(struct spi_device *spi)
++static int ad7780_probe(struct spi_device *spi)
+ {
+ 	struct ad7780_platform_data *pdata = spi->dev.platform_data;
+ 	struct ad7780_state *st;
+diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c
+index 691a7be6f5cb..d7a272e7b6b1 100644
+--- a/drivers/staging/iio/adc/ad7793.c
++++ b/drivers/staging/iio/adc/ad7793.c
+@@ -441,7 +441,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
+ 	},
+ };
+ 
+-static int __devinit ad7793_probe(struct spi_device *spi)
++static int ad7793_probe(struct spi_device *spi)
+ {
+ 	const struct ad7793_platform_data *pdata = spi->dev.platform_data;
+ 	struct ad7793_state *st;
+diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c
+index c5fb9476a2d1..b49fc6c53927 100644
+--- a/drivers/staging/iio/adc/ad7816.c
++++ b/drivers/staging/iio/adc/ad7816.c
+@@ -341,7 +341,7 @@ static const struct iio_info ad7816_info = {
+  * device probe and remove
+  */
+ 
+-static int __devinit ad7816_probe(struct spi_device *spi_dev)
++static int ad7816_probe(struct spi_device *spi_dev)
+ {
+ 	struct ad7816_chip_info *chip;
+ 	struct iio_dev *indio_dev;
+diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c
+index 990050700afc..758527987fdd 100644
+--- a/drivers/staging/iio/adc/ad799x_core.c
++++ b/drivers/staging/iio/adc/ad799x_core.c
+@@ -854,7 +854,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
+ 	},
+ };
+ 
+-static int __devinit ad799x_probe(struct i2c_client *client,
++static int ad799x_probe(struct i2c_client *client,
+ 				   const struct i2c_device_id *id)
+ {
+ 	int ret;
+diff --git a/drivers/staging/iio/adc/adt7410.c b/drivers/staging/iio/adc/adt7410.c
+index 6493cd0a48dd..f41994dd8d6d 100644
+--- a/drivers/staging/iio/adc/adt7410.c
++++ b/drivers/staging/iio/adc/adt7410.c
+@@ -695,7 +695,7 @@ static const struct iio_info adt7410_info = {
+  * device probe and remove
+  */
+ 
+-static int __devinit adt7410_probe(struct device *dev, int irq,
++static int adt7410_probe(struct device *dev, int irq,
+ 	const char *name, const struct adt7410_ops *ops)
+ {
+ 	unsigned long *adt7410_platform_data = dev->platform_data;
+@@ -876,7 +876,7 @@ static const struct adt7410_ops adt7410_i2c_ops = {
+ 	.write_byte = adt7410_i2c_write_byte,
+ };
+ 
+-static int __devinit adt7410_i2c_probe(struct i2c_client *client,
++static int adt7410_i2c_probe(struct i2c_client *client,
+ 	const struct i2c_device_id *id)
+ {
+ 	return adt7410_probe(&client->dev, client->irq, id->name,
+@@ -1030,7 +1030,7 @@ static const struct adt7410_ops adt7310_spi_ops = {
+ 	.write_byte = adt7310_spi_write_byte,
+ };
+ 
+-static int __devinit adt7310_spi_probe(struct spi_device *spi)
++static int adt7310_spi_probe(struct spi_device *spi)
+ {
+ 	return adt7410_probe(&spi->dev, spi->irq,
+ 		spi_get_device_id(spi)->name, &adt7310_spi_ops);
+diff --git a/drivers/staging/iio/adc/lpc32xx_adc.c b/drivers/staging/iio/adc/lpc32xx_adc.c
+index 10c59622671f..f38aa92146a3 100644
+--- a/drivers/staging/iio/adc/lpc32xx_adc.c
++++ b/drivers/staging/iio/adc/lpc32xx_adc.c
+@@ -126,7 +126,7 @@ static irqreturn_t lpc32xx_adc_isr(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit lpc32xx_adc_probe(struct platform_device *pdev)
++static int lpc32xx_adc_probe(struct platform_device *pdev)
+ {
+ 	struct lpc32xx_adc_info *info = NULL;
+ 	struct resource *res;
+diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c
+index 3b467d8c5882..b91cf850b078 100644
+--- a/drivers/staging/iio/adc/mxs-lradc.c
++++ b/drivers/staging/iio/adc/mxs-lradc.c
+@@ -466,7 +466,7 @@ static void mxs_lradc_hw_stop(struct mxs_lradc *lradc)
+ 		writel(0, lradc->base + LRADC_DELAY(i));
+ }
+ 
+-static int __devinit mxs_lradc_probe(struct platform_device *pdev)
++static int mxs_lradc_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	struct mxs_lradc *lradc;
+diff --git a/drivers/staging/iio/adc/spear_adc.c b/drivers/staging/iio/adc/spear_adc.c
+index 0b83e2e1f410..e1a55b368a65 100644
+--- a/drivers/staging/iio/adc/spear_adc.c
++++ b/drivers/staging/iio/adc/spear_adc.c
+@@ -291,7 +291,7 @@ static const struct iio_info spear_adc_iio_info = {
+ 	.driver_module = THIS_MODULE,
+ };
+ 
+-static int __devinit spear_adc_probe(struct platform_device *pdev)
++static int spear_adc_probe(struct platform_device *pdev)
+ {
+ 	struct device_node *np = pdev->dev.of_node;
+ 	struct device *dev = &pdev->dev;
+diff --git a/drivers/staging/iio/addac/adt7316-i2c.c b/drivers/staging/iio/addac/adt7316-i2c.c
+index 9e128dd7d457..cde82cf94ee4 100644
+--- a/drivers/staging/iio/addac/adt7316-i2c.c
++++ b/drivers/staging/iio/addac/adt7316-i2c.c
+@@ -92,7 +92,7 @@ static int adt7316_i2c_multi_write(void *client, u8 reg, u8 count, u8 *data)
+  * device probe and remove
+  */
+ 
+-static int __devinit adt7316_i2c_probe(struct i2c_client *client,
++static int adt7316_i2c_probe(struct i2c_client *client,
+ 		const struct i2c_device_id *id)
+ {
+ 	struct adt7316_bus bus = {
+diff --git a/drivers/staging/iio/addac/adt7316-spi.c b/drivers/staging/iio/addac/adt7316-spi.c
+index 985f7d8a6eb2..99631ed380a9 100644
+--- a/drivers/staging/iio/addac/adt7316-spi.c
++++ b/drivers/staging/iio/addac/adt7316-spi.c
+@@ -89,7 +89,7 @@ static int adt7316_spi_write(void *client, u8 reg, u8 val)
+  * device probe and remove
+  */
+ 
+-static int __devinit adt7316_spi_probe(struct spi_device *spi_dev)
++static int adt7316_spi_probe(struct spi_device *spi_dev)
+ {
+ 	struct adt7316_bus bus = {
+ 		.client = spi_dev,
+diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c
+index 8fb014a046a2..487f5e039872 100644
+--- a/drivers/staging/iio/addac/adt7316.c
++++ b/drivers/staging/iio/addac/adt7316.c
+@@ -2125,7 +2125,7 @@ static const struct iio_info adt7516_info = {
+ /*
+  * device probe and remove
+  */
+-int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus,
++int adt7316_probe(struct device *dev, struct adt7316_bus *bus,
+ 		const char *name)
+ {
+ 	struct adt7316_chip_info *chip;
+diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c
+index c72a6c074b46..4ee4bfb4d29c 100644
+--- a/drivers/staging/iio/cdc/ad7150.c
++++ b/drivers/staging/iio/cdc/ad7150.c
+@@ -551,7 +551,7 @@ static const struct iio_info ad7150_info = {
+  * device probe and remove
+  */
+ 
+-static int __devinit ad7150_probe(struct i2c_client *client,
++static int ad7150_probe(struct i2c_client *client,
+ 		const struct i2c_device_id *id)
+ {
+ 	int ret;
+diff --git a/drivers/staging/iio/cdc/ad7152.c b/drivers/staging/iio/cdc/ad7152.c
+index 288b33e8dadd..e12e99beeb25 100644
+--- a/drivers/staging/iio/cdc/ad7152.c
++++ b/drivers/staging/iio/cdc/ad7152.c
+@@ -474,7 +474,7 @@ static const struct iio_chan_spec ad7152_channels[] = {
+  * device probe and remove
+  */
+ 
+-static int __devinit ad7152_probe(struct i2c_client *client,
++static int ad7152_probe(struct i2c_client *client,
+ 		const struct i2c_device_id *id)
+ {
+ 	int ret = 0;
+diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c
+index e6c11d934ada..5c9d204de49d 100644
+--- a/drivers/staging/iio/cdc/ad7746.c
++++ b/drivers/staging/iio/cdc/ad7746.c
+@@ -694,7 +694,7 @@ static const struct iio_info ad7746_info = {
+  * device probe and remove
+  */
+ 
+-static int __devinit ad7746_probe(struct i2c_client *client,
++static int ad7746_probe(struct i2c_client *client,
+ 		const struct i2c_device_id *id)
+ {
+ 	struct ad7746_platform_data *pdata = client->dev.platform_data;
+diff --git a/drivers/staging/iio/frequency/ad5930.c b/drivers/staging/iio/frequency/ad5930.c
+index 2d541d0eebef..7dfaf801df9d 100644
+--- a/drivers/staging/iio/frequency/ad5930.c
++++ b/drivers/staging/iio/frequency/ad5930.c
+@@ -91,7 +91,7 @@ static const struct iio_info ad5930_info = {
+ 	.driver_module = THIS_MODULE,
+ };
+ 
+-static int __devinit ad5930_probe(struct spi_device *spi)
++static int ad5930_probe(struct spi_device *spi)
+ {
+ 	struct ad5930_state *st;
+ 	struct iio_dev *idev;
+diff --git a/drivers/staging/iio/frequency/ad9832.c b/drivers/staging/iio/frequency/ad9832.c
+index fed39404e34a..593e1888067e 100644
+--- a/drivers/staging/iio/frequency/ad9832.c
++++ b/drivers/staging/iio/frequency/ad9832.c
+@@ -201,7 +201,7 @@ static const struct iio_info ad9832_info = {
+ 	.driver_module = THIS_MODULE,
+ };
+ 
+-static int __devinit ad9832_probe(struct spi_device *spi)
++static int ad9832_probe(struct spi_device *spi)
+ {
+ 	struct ad9832_platform_data *pdata = spi->dev.platform_data;
+ 	struct iio_dev *indio_dev;
+diff --git a/drivers/staging/iio/frequency/ad9834.c b/drivers/staging/iio/frequency/ad9834.c
+index 1b2dc741d2ce..453698b4d8be 100644
+--- a/drivers/staging/iio/frequency/ad9834.c
++++ b/drivers/staging/iio/frequency/ad9834.c
+@@ -314,7 +314,7 @@ static const struct iio_info ad9833_info = {
+ 	.driver_module = THIS_MODULE,
+ };
+ 
+-static int __devinit ad9834_probe(struct spi_device *spi)
++static int ad9834_probe(struct spi_device *spi)
+ {
+ 	struct ad9834_platform_data *pdata = spi->dev.platform_data;
+ 	struct ad9834_state *st;
+diff --git a/drivers/staging/iio/frequency/ad9850.c b/drivers/staging/iio/frequency/ad9850.c
+index 74abee054ac0..1e6a2b351d63 100644
+--- a/drivers/staging/iio/frequency/ad9850.c
++++ b/drivers/staging/iio/frequency/ad9850.c
+@@ -77,7 +77,7 @@ static const struct iio_info ad9850_info = {
+ 	.driver_module = THIS_MODULE,
+ };
+ 
+-static int __devinit ad9850_probe(struct spi_device *spi)
++static int ad9850_probe(struct spi_device *spi)
+ {
+ 	struct ad9850_state *st;
+ 	struct iio_dev *idev;
+diff --git a/drivers/staging/iio/frequency/ad9852.c b/drivers/staging/iio/frequency/ad9852.c
+index fd9d14a413a5..84a4f1d37bbf 100644
+--- a/drivers/staging/iio/frequency/ad9852.c
++++ b/drivers/staging/iio/frequency/ad9852.c
+@@ -226,7 +226,7 @@ static const struct iio_info ad9852_info = {
+ 	.driver_module = THIS_MODULE,
+ };
+ 
+-static int __devinit ad9852_probe(struct spi_device *spi)
++static int ad9852_probe(struct spi_device *spi)
+ {
+ 	struct ad9852_state *st;
+ 	struct iio_dev *idev;
+diff --git a/drivers/staging/iio/frequency/ad9910.c b/drivers/staging/iio/frequency/ad9910.c
+index 5a7ba305b75a..9c569bcb4ae1 100644
+--- a/drivers/staging/iio/frequency/ad9910.c
++++ b/drivers/staging/iio/frequency/ad9910.c
+@@ -361,7 +361,7 @@ static const struct iio_info ad9910_info = {
+ 	.driver_module = THIS_MODULE,
+ };
+ 
+-static int __devinit ad9910_probe(struct spi_device *spi)
++static int ad9910_probe(struct spi_device *spi)
+ {
+ 	struct ad9910_state *st;
+ 	struct iio_dev *idev;
+diff --git a/drivers/staging/iio/frequency/ad9951.c b/drivers/staging/iio/frequency/ad9951.c
+index ba6f49ff09ae..e53d47e35a68 100644
+--- a/drivers/staging/iio/frequency/ad9951.c
++++ b/drivers/staging/iio/frequency/ad9951.c
+@@ -170,7 +170,7 @@ static const struct iio_info ad9951_info = {
+ 	.driver_module = THIS_MODULE,
+ };
+ 
+-static int __devinit ad9951_probe(struct spi_device *spi)
++static int ad9951_probe(struct spi_device *spi)
+ {
+ 	struct ad9951_state *st;
+ 	struct iio_dev *idev;
+diff --git a/drivers/staging/iio/gyro/adis16060_core.c b/drivers/staging/iio/gyro/adis16060_core.c
+index 87151a7cff04..af1469beb189 100644
+--- a/drivers/staging/iio/gyro/adis16060_core.c
++++ b/drivers/staging/iio/gyro/adis16060_core.c
+@@ -145,7 +145,7 @@ static const struct iio_chan_spec adis16060_channels[] = {
+ 	}
+ };
+ 
+-static int __devinit adis16060_r_probe(struct spi_device *spi)
++static int adis16060_r_probe(struct spi_device *spi)
+ {
+ 	int ret;
+ 	struct adis16060_state *st;
+@@ -192,7 +192,7 @@ static int __devexit adis16060_r_remove(struct spi_device *spi)
+ 	return 0;
+ }
+ 
+-static int __devinit adis16060_w_probe(struct spi_device *spi)
++static int adis16060_w_probe(struct spi_device *spi)
+ {
+ 	int ret;
+ 	struct iio_dev *indio_dev = adis16060_iio_dev;
+diff --git a/drivers/staging/iio/gyro/adis16080_core.c b/drivers/staging/iio/gyro/adis16080_core.c
+index a73902573f79..244e7b09ffd0 100644
+--- a/drivers/staging/iio/gyro/adis16080_core.c
++++ b/drivers/staging/iio/gyro/adis16080_core.c
+@@ -138,7 +138,7 @@ static const struct iio_info adis16080_info = {
+ 	.driver_module = THIS_MODULE,
+ };
+ 
+-static int __devinit adis16080_probe(struct spi_device *spi)
++static int adis16080_probe(struct spi_device *spi)
+ {
+ 	int ret;
+ 	struct adis16080_state *st;
+diff --git a/drivers/staging/iio/gyro/adis16130_core.c b/drivers/staging/iio/gyro/adis16130_core.c
+index fbf96b0b6ee8..c778fd07f496 100644
+--- a/drivers/staging/iio/gyro/adis16130_core.c
++++ b/drivers/staging/iio/gyro/adis16130_core.c
+@@ -116,7 +116,7 @@ static const struct iio_info adis16130_info = {
+ 	.driver_module = THIS_MODULE,
+ };
+ 
+-static int __devinit adis16130_probe(struct spi_device *spi)
++static int adis16130_probe(struct spi_device *spi)
+ {
+ 	int ret;
+ 	struct adis16130_state *st;
+diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c
+index b988b4f5bdda..030113b991da 100644
+--- a/drivers/staging/iio/gyro/adis16260_core.c
++++ b/drivers/staging/iio/gyro/adis16260_core.c
+@@ -301,7 +301,7 @@ static const struct adis_data adis16260_data = {
+ 		BIT(ADIS16260_DIAG_STAT_POWER_LOW_BIT),
+ };
+ 
+-static int __devinit adis16260_probe(struct spi_device *spi)
++static int adis16260_probe(struct spi_device *spi)
+ {
+ 	int ret;
+ 	struct adis16260_platform_data *pd = spi->dev.platform_data;
+diff --git a/drivers/staging/iio/gyro/adxrs450_core.c b/drivers/staging/iio/gyro/adxrs450_core.c
+index d93527d15917..07b86bf9540a 100644
+--- a/drivers/staging/iio/gyro/adxrs450_core.c
++++ b/drivers/staging/iio/gyro/adxrs450_core.c
+@@ -365,7 +365,7 @@ static const struct iio_info adxrs450_info = {
+ 	.write_raw = &adxrs450_write_raw,
+ };
+ 
+-static int __devinit adxrs450_probe(struct spi_device *spi)
++static int adxrs450_probe(struct spi_device *spi)
+ {
+ 	int ret;
+ 	struct adxrs450_state *st;
+diff --git a/drivers/staging/iio/iio_hwmon.c b/drivers/staging/iio/iio_hwmon.c
+index 5d491227e01b..a24330884b78 100644
+--- a/drivers/staging/iio/iio_hwmon.c
++++ b/drivers/staging/iio/iio_hwmon.c
+@@ -69,7 +69,7 @@ static void iio_hwmon_free_attrs(struct iio_hwmon_state *st)
+ 		}
+ }
+ 
+-static int __devinit iio_hwmon_probe(struct platform_device *pdev)
++static int iio_hwmon_probe(struct platform_device *pdev)
+ {
+ 	struct iio_hwmon_state *st;
+ 	struct sensor_device_attribute *a;
+diff --git a/drivers/staging/iio/iio_simple_dummy.c b/drivers/staging/iio/iio_simple_dummy.c
+index dc6c728ea47a..a865adf81938 100644
+--- a/drivers/staging/iio/iio_simple_dummy.c
++++ b/drivers/staging/iio/iio_simple_dummy.c
+@@ -378,7 +378,7 @@ static int iio_dummy_init_device(struct iio_dev *indio_dev)
+  *                      const struct i2c_device_id *id)
+  * SPI: iio_dummy_probe(struct spi_device *spi)
+  */
+-static int __devinit iio_dummy_probe(int index)
++static int iio_dummy_probe(int index)
+ {
+ 	int ret;
+ 	struct iio_dev *indio_dev;
+diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c
+index b1fef147d5b5..e2689978eb9e 100644
+--- a/drivers/staging/iio/impedance-analyzer/ad5933.c
++++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
+@@ -697,7 +697,7 @@ static void ad5933_work(struct work_struct *work)
+ 	mutex_unlock(&indio_dev->mlock);
+ }
+ 
+-static int __devinit ad5933_probe(struct i2c_client *client,
++static int ad5933_probe(struct i2c_client *client,
+ 				   const struct i2c_device_id *id)
+ {
+ 	int ret, voltage_uv = 0;
+diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c
+index c3f9bb95c7b3..490359d8b162 100644
+--- a/drivers/staging/iio/imu/adis16400_core.c
++++ b/drivers/staging/iio/imu/adis16400_core.c
+@@ -1206,7 +1206,7 @@ static const struct iio_info adis16400_info = {
+ 	.attrs = &adis16400_attribute_group,
+ };
+ 
+-static int __devinit adis16400_probe(struct spi_device *spi)
++static int adis16400_probe(struct spi_device *spi)
+ {
+ 	int ret;
+ 	struct adis16400_state *st;
+diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c
+index 1d5b294d6e61..e305f050f780 100644
+--- a/drivers/staging/iio/light/isl29018.c
++++ b/drivers/staging/iio/light/isl29018.c
+@@ -543,7 +543,7 @@ static const struct regmap_config isl29018_regmap_config = {
+ 	.cache_type = REGCACHE_RBTREE,
+ };
+ 
+-static int __devinit isl29018_probe(struct i2c_client *client,
++static int isl29018_probe(struct i2c_client *client,
+ 			 const struct i2c_device_id *id)
+ {
+ 	struct isl29018_chip *chip;
+diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c
+index 33a4c3f94a14..4b1def75d300 100644
+--- a/drivers/staging/iio/light/isl29028.c
++++ b/drivers/staging/iio/light/isl29028.c
+@@ -475,7 +475,7 @@ static const struct regmap_config isl29028_regmap_config = {
+ 	.cache_type = REGCACHE_RBTREE,
+ };
+ 
+-static int __devinit isl29028_probe(struct i2c_client *client,
++static int isl29028_probe(struct i2c_client *client,
+ 	const struct i2c_device_id *id)
+ {
+ 	struct isl29028_chip *chip;
+diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c
+index 3f72543b188f..2ca586e73dec 100644
+--- a/drivers/staging/iio/light/tsl2563.c
++++ b/drivers/staging/iio/light/tsl2563.c
+@@ -705,7 +705,7 @@ static const struct iio_info tsl2563_info = {
+ 	.write_event_config = &tsl2563_write_interrupt_config,
+ };
+ 
+-static int __devinit tsl2563_probe(struct i2c_client *client,
++static int tsl2563_probe(struct i2c_client *client,
+ 				const struct i2c_device_id *device_id)
+ {
+ 	struct iio_dev *indio_dev;
+diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c
+index 6d2f4c659e56..f4b7d914cdf3 100644
+--- a/drivers/staging/iio/light/tsl2583.c
++++ b/drivers/staging/iio/light/tsl2583.c
+@@ -799,7 +799,7 @@ static const struct iio_info tsl2583_info = {
+  * Client probe function - When a valid device is found, the driver's device
+  * data structure is updated, and initialization completes successfully.
+  */
+-static int __devinit taos_probe(struct i2c_client *clientp,
++static int taos_probe(struct i2c_client *clientp,
+ 		      const struct i2c_device_id *idp)
+ {
+ 	int i, ret;
+diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x_core.c
+index 497a977ae411..3864e8af709f 100644
+--- a/drivers/staging/iio/light/tsl2x7x_core.c
++++ b/drivers/staging/iio/light/tsl2x7x_core.c
+@@ -1897,7 +1897,7 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = {
+ 	},
+ };
+ 
+-static int __devinit tsl2x7x_probe(struct i2c_client *clientp,
++static int tsl2x7x_probe(struct i2c_client *clientp,
+ 	const struct i2c_device_id *id)
+ {
+ 	int ret;
+diff --git a/drivers/staging/iio/magnetometer/ak8975.c b/drivers/staging/iio/magnetometer/ak8975.c
+index 01b4b07c227b..6f0697facb34 100644
+--- a/drivers/staging/iio/magnetometer/ak8975.c
++++ b/drivers/staging/iio/magnetometer/ak8975.c
+@@ -409,7 +409,7 @@ static const struct iio_info ak8975_info = {
+ 	.driver_module = THIS_MODULE,
+ };
+ 
+-static int __devinit ak8975_probe(struct i2c_client *client,
++static int ak8975_probe(struct i2c_client *client,
+ 			const struct i2c_device_id *id)
+ {
+ 	struct ak8975_data *data;
+diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c
+index f7edf69a3bc4..c1d96a4bbbc4 100644
+--- a/drivers/staging/iio/magnetometer/hmc5843.c
++++ b/drivers/staging/iio/magnetometer/hmc5843.c
+@@ -665,7 +665,7 @@ static const struct iio_info hmc5843_info = {
+ 	.driver_module = THIS_MODULE,
+ };
+ 
+-static int __devinit hmc5843_probe(struct i2c_client *client,
++static int hmc5843_probe(struct i2c_client *client,
+ 			 const struct i2c_device_id *id)
+ {
+ 	struct hmc5843_data *data;
+diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c
+index 8b9eceb66b37..7fc2408fbcf7 100644
+--- a/drivers/staging/iio/meter/ade7753.c
++++ b/drivers/staging/iio/meter/ade7753.c
+@@ -512,7 +512,7 @@ static const struct iio_info ade7753_info = {
+ 	.driver_module = THIS_MODULE,
+ };
+ 
+-static int __devinit ade7753_probe(struct spi_device *spi)
++static int ade7753_probe(struct spi_device *spi)
+ {
+ 	int ret;
+ 	struct ade7753_state *st;
+diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c
+index 76e0adee96ea..0ee1f264adb0 100644
+--- a/drivers/staging/iio/meter/ade7754.c
++++ b/drivers/staging/iio/meter/ade7754.c
+@@ -535,7 +535,7 @@ static const struct iio_info ade7754_info = {
+ 	.driver_module = THIS_MODULE,
+ };
+ 
+-static int __devinit ade7754_probe(struct spi_device *spi)
++static int ade7754_probe(struct spi_device *spi)
+ {
+ 	int ret;
+ 	struct ade7754_state *st;
+diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c
+index a0fef77d8e5e..21bda06ab93a 100644
+--- a/drivers/staging/iio/meter/ade7758_core.c
++++ b/drivers/staging/iio/meter/ade7758_core.c
+@@ -881,7 +881,7 @@ static const struct iio_info ade7758_info = {
+ 	.driver_module = THIS_MODULE,
+ };
+ 
+-static int __devinit ade7758_probe(struct spi_device *spi)
++static int ade7758_probe(struct spi_device *spi)
+ {
+ 	int ret;
+ 	struct ade7758_state *st;
+diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c
+index cb0707cbc347..b3a6c3031cfe 100644
+--- a/drivers/staging/iio/meter/ade7759.c
++++ b/drivers/staging/iio/meter/ade7759.c
+@@ -458,7 +458,7 @@ static const struct iio_info ade7759_info = {
+ 	.driver_module = THIS_MODULE,
+ };
+ 
+-static int __devinit ade7759_probe(struct spi_device *spi)
++static int ade7759_probe(struct spi_device *spi)
+ {
+ 	int ret;
+ 	struct ade7759_state *st;
+diff --git a/drivers/staging/iio/meter/ade7854-i2c.c b/drivers/staging/iio/meter/ade7854-i2c.c
+index 06090465fa5f..56809266ef8f 100644
+--- a/drivers/staging/iio/meter/ade7854-i2c.c
++++ b/drivers/staging/iio/meter/ade7854-i2c.c
+@@ -201,7 +201,7 @@ static int ade7854_i2c_read_reg_32(struct device *dev,
+ 	return ret;
+ }
+ 
+-static int __devinit ade7854_i2c_probe(struct i2c_client *client,
++static int ade7854_i2c_probe(struct i2c_client *client,
+ 		const struct i2c_device_id *id)
+ {
+ 	int ret;
+diff --git a/drivers/staging/iio/meter/ade7854-spi.c b/drivers/staging/iio/meter/ade7854-spi.c
+index 7dae03573428..7826f299f8dd 100644
+--- a/drivers/staging/iio/meter/ade7854-spi.c
++++ b/drivers/staging/iio/meter/ade7854-spi.c
+@@ -300,7 +300,7 @@ static int ade7854_spi_read_reg_32(struct device *dev,
+ 	return ret;
+ }
+ 
+-static int __devinit ade7854_spi_probe(struct spi_device *spi)
++static int ade7854_spi_probe(struct spi_device *spi)
+ {
+ 	int ret;
+ 	struct ade7854_state *st;
+diff --git a/drivers/staging/iio/resolver/ad2s1200.c b/drivers/staging/iio/resolver/ad2s1200.c
+index 8b71eb0e16f5..d102a7e18f6f 100644
+--- a/drivers/staging/iio/resolver/ad2s1200.c
++++ b/drivers/staging/iio/resolver/ad2s1200.c
+@@ -99,7 +99,7 @@ static const struct iio_info ad2s1200_info = {
+ 	.driver_module = THIS_MODULE,
+ };
+ 
+-static int __devinit ad2s1200_probe(struct spi_device *spi)
++static int ad2s1200_probe(struct spi_device *spi)
+ {
+ 	struct ad2s1200_state *st;
+ 	struct iio_dev *indio_dev;
+diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c
+index 4ba4d05ed423..98c653c82c3a 100644
+--- a/drivers/staging/iio/resolver/ad2s1210.c
++++ b/drivers/staging/iio/resolver/ad2s1210.c
+@@ -610,7 +610,7 @@ static const struct attribute_group ad2s1210_attribute_group = {
+ 	.attrs = ad2s1210_attributes,
+ };
+ 
+-static int __devinit ad2s1210_initial(struct ad2s1210_state *st)
++static int ad2s1210_initial(struct ad2s1210_state *st)
+ {
+ 	unsigned char data;
+ 	int ret;
+@@ -681,7 +681,7 @@ static void ad2s1210_free_gpios(struct ad2s1210_state *st)
+ 	gpio_free_array(ad2s1210_gpios, ARRAY_SIZE(ad2s1210_gpios));
+ }
+ 
+-static int __devinit ad2s1210_probe(struct spi_device *spi)
++static int ad2s1210_probe(struct spi_device *spi)
+ {
+ 	struct iio_dev *indio_dev;
+ 	struct ad2s1210_state *st;
+diff --git a/drivers/staging/iio/resolver/ad2s90.c b/drivers/staging/iio/resolver/ad2s90.c
+index a8057228dca1..f9451abd7f53 100644
+--- a/drivers/staging/iio/resolver/ad2s90.c
++++ b/drivers/staging/iio/resolver/ad2s90.c
+@@ -58,7 +58,7 @@ static const struct iio_chan_spec ad2s90_chan = {
+ 	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+ };
+ 
+-static int __devinit ad2s90_probe(struct spi_device *spi)
++static int ad2s90_probe(struct spi_device *spi)
+ {
+ 	struct iio_dev *indio_dev;
+ 	struct ad2s90_state *st;
+diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
+index 52062d786f84..91412e42ca40 100644
+--- a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
++++ b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
+@@ -180,7 +180,7 @@ static const struct iio_trigger_ops iio_bfin_tmr_trigger_ops = {
+ 	.set_trigger_state = iio_bfin_tmr_set_state,
+ };
+ 
+-static int __devinit iio_bfin_tmr_trigger_probe(struct platform_device *pdev)
++static int iio_bfin_tmr_trigger_probe(struct platform_device *pdev)
+ {
+ 	struct iio_bfin_timer_trigger_pdata *pdata = pdev->dev.platform_data;
+ 	struct bfin_tmr_state *st;
+diff --git a/drivers/staging/iio/trigger/iio-trig-gpio.c b/drivers/staging/iio/trigger/iio-trig-gpio.c
+index 5ff4d7fa20fa..2dc57121a743 100644
+--- a/drivers/staging/iio/trigger/iio-trig-gpio.c
++++ b/drivers/staging/iio/trigger/iio-trig-gpio.c
+@@ -51,7 +51,7 @@ static const struct iio_trigger_ops iio_gpio_trigger_ops = {
+ 	.owner = THIS_MODULE,
+ };
+ 
+-static int __devinit iio_gpio_trigger_probe(struct platform_device *pdev)
++static int iio_gpio_trigger_probe(struct platform_device *pdev)
+ {
+ 	struct iio_gpio_trigger_info *trig_info;
+ 	struct iio_trigger *trig, *trig2;
+diff --git a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
+index a3de76d70cdc..643dcff394c3 100644
+--- a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
++++ b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
+@@ -101,7 +101,7 @@ static const struct iio_trigger_ops iio_prtc_trigger_ops = {
+ 	.set_trigger_state = &iio_trig_periodic_rtc_set_state,
+ };
+ 
+-static int __devinit iio_trig_periodic_rtc_probe(struct platform_device *dev)
++static int iio_trig_periodic_rtc_probe(struct platform_device *dev)
+ {
+ 	char **pdata = dev->dev.platform_data;
+ 	struct iio_prtc_trigger_info *trig_info;

commit 1a6a8a8414f740f1dfde762837eeb3f2ce835919
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:41 2012 -0500
+
+    staging: nvec: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Julian Andres Klode 
+    Acked-by: Marc Dietrich 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c
+index d8180f0cd1c7..c59b7b299d37 100644
+--- a/drivers/staging/nvec/nvec.c
++++ b/drivers/staging/nvec/nvec.c
+@@ -853,7 +853,7 @@ static int tegra_nvec_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit tegra_nvec_remove(struct platform_device *pdev)
++static int tegra_nvec_remove(struct platform_device *pdev)
+ {
+ 	struct nvec_chip *nvec = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/staging/nvec/nvec_kbd.c b/drivers/staging/nvec/nvec_kbd.c
+index 9048d597cc6b..7cb149bf3d3f 100644
+--- a/drivers/staging/nvec/nvec_kbd.c
++++ b/drivers/staging/nvec/nvec_kbd.c
+@@ -159,7 +159,7 @@ static int nvec_kbd_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit nvec_kbd_remove(struct platform_device *pdev)
++static int nvec_kbd_remove(struct platform_device *pdev)
+ {
+ 	input_unregister_device(keys_dev.input);
+ 	input_free_device(keys_dev.input);
+diff --git a/drivers/staging/nvec/nvec_paz00.c b/drivers/staging/nvec/nvec_paz00.c
+index 4ac17fb6a0dc..934b796222a2 100644
+--- a/drivers/staging/nvec/nvec_paz00.c
++++ b/drivers/staging/nvec/nvec_paz00.c
+@@ -72,7 +72,7 @@ static int nvec_paz00_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit nvec_paz00_remove(struct platform_device *pdev)
++static int nvec_paz00_remove(struct platform_device *pdev)
+ {
+ 	struct nvec_led *led = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/staging/nvec/nvec_power.c b/drivers/staging/nvec/nvec_power.c
+index 6c702ed7463d..b7b6d54f58ec 100644
+--- a/drivers/staging/nvec/nvec_power.c
++++ b/drivers/staging/nvec/nvec_power.c
+@@ -407,7 +407,7 @@ static int nvec_power_probe(struct platform_device *pdev)
+ 	return power_supply_register(&pdev->dev, psy);
+ }
+ 
+-static int __devexit nvec_power_remove(struct platform_device *pdev)
++static int nvec_power_remove(struct platform_device *pdev)
+ {
+ 	struct nvec_power *power = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/staging/nvec/nvec_ps2.c b/drivers/staging/nvec/nvec_ps2.c
+index 59d8f5a76360..88dd288bf3d7 100644
+--- a/drivers/staging/nvec/nvec_ps2.c
++++ b/drivers/staging/nvec/nvec_ps2.c
+@@ -123,7 +123,7 @@ static int nvec_mouse_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit nvec_mouse_remove(struct platform_device *pdev)
++static int nvec_mouse_remove(struct platform_device *pdev)
+ {
+ 	serio_unregister_port(ps2_dev.ser_dev);
+ 

commit 063f9f6a8705c5da3ee46c667a3e6e01eaf31560
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:25:26 2012 -0500
+
+    staging: nvec: remove use of __devinitconst
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitconst is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Julian Andres Klode 
+    Acked-by: Marc Dietrich 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c
+index 27881a352340..d8180f0cd1c7 100644
+--- a/drivers/staging/nvec/nvec.c
++++ b/drivers/staging/nvec/nvec.c
+@@ -901,7 +901,7 @@ static int nvec_resume(struct device *dev)
+ static const SIMPLE_DEV_PM_OPS(nvec_pm_ops, nvec_suspend, nvec_resume);
+ 
+ /* Match table for of_platform binding */
+-static const struct of_device_id nvidia_nvec_of_match[] __devinitconst = {
++static const struct of_device_id nvidia_nvec_of_match[] = {
+ 	{ .compatible = "nvidia,nvec", },
+ 	{},
+ };

commit 46620803c309d2bc10814b903b39d7647057b440
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:07 2012 -0500
+
+    staging: nvec: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Julian Andres Klode 
+    Acked-by: Marc Dietrich 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c
+index 0258035b4b0e..27881a352340 100644
+--- a/drivers/staging/nvec/nvec.c
++++ b/drivers/staging/nvec/nvec.c
+@@ -716,7 +716,7 @@ static void nvec_power_off(void)
+ 	nvec_write_async(nvec_power_handle, "\x04\x01", 2);
+ }
+ 
+-static int __devinit tegra_nvec_probe(struct platform_device *pdev)
++static int tegra_nvec_probe(struct platform_device *pdev)
+ {
+ 	int err, ret;
+ 	struct clk *i2c_clk;
+diff --git a/drivers/staging/nvec/nvec_kbd.c b/drivers/staging/nvec/nvec_kbd.c
+index 7c8c603da705..9048d597cc6b 100644
+--- a/drivers/staging/nvec/nvec_kbd.c
++++ b/drivers/staging/nvec/nvec_kbd.c
+@@ -100,7 +100,7 @@ static int nvec_kbd_event(struct input_dev *dev, unsigned int type,
+ 	return 0;
+ }
+ 
+-static int __devinit nvec_kbd_probe(struct platform_device *pdev)
++static int nvec_kbd_probe(struct platform_device *pdev)
+ {
+ 	struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent);
+ 	int i, j, err;
+diff --git a/drivers/staging/nvec/nvec_paz00.c b/drivers/staging/nvec/nvec_paz00.c
+index aab234e97d0b..4ac17fb6a0dc 100644
+--- a/drivers/staging/nvec/nvec_paz00.c
++++ b/drivers/staging/nvec/nvec_paz00.c
+@@ -43,7 +43,7 @@ static void nvec_led_brightness_set(struct led_classdev *led_cdev,
+ 
+ }
+ 
+-static int __devinit nvec_paz00_probe(struct platform_device *pdev)
++static int nvec_paz00_probe(struct platform_device *pdev)
+ {
+ 	struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent);
+ 	struct nvec_led *led;
+diff --git a/drivers/staging/nvec/nvec_power.c b/drivers/staging/nvec/nvec_power.c
+index 99e06f661c19..6c702ed7463d 100644
+--- a/drivers/staging/nvec/nvec_power.c
++++ b/drivers/staging/nvec/nvec_power.c
+@@ -368,7 +368,7 @@ static void nvec_power_poll(struct work_struct *work)
+ 	schedule_delayed_work(to_delayed_work(work), msecs_to_jiffies(5000));
+ };
+ 
+-static int __devinit nvec_power_probe(struct platform_device *pdev)
++static int nvec_power_probe(struct platform_device *pdev)
+ {
+ 	struct power_supply *psy;
+ 	struct nvec_power *power;
+diff --git a/drivers/staging/nvec/nvec_ps2.c b/drivers/staging/nvec/nvec_ps2.c
+index 6375e80e77af..59d8f5a76360 100644
+--- a/drivers/staging/nvec/nvec_ps2.c
++++ b/drivers/staging/nvec/nvec_ps2.c
+@@ -93,7 +93,7 @@ static int nvec_ps2_notifier(struct notifier_block *nb,
+ 	return NOTIFY_DONE;
+ }
+ 
+-static int __devinit nvec_mouse_probe(struct platform_device *pdev)
++static int nvec_mouse_probe(struct platform_device *pdev)
+ {
+ 	struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent);
+ 	struct serio *ser_dev;

commit 44b90a3fbcac0f233b71b4041fa76ea325caca33
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:20:55 2012 -0500
+
+    staging: nvec: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Julian Andres Klode 
+    Acked-by: Marc Dietrich 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c
+index 094fdc366f30..0258035b4b0e 100644
+--- a/drivers/staging/nvec/nvec.c
++++ b/drivers/staging/nvec/nvec.c
+@@ -909,7 +909,7 @@ MODULE_DEVICE_TABLE(of, nvidia_nvec_of_match);
+ 
+ static struct platform_driver nvec_device_driver = {
+ 	.probe   = tegra_nvec_probe,
+-	.remove  = __devexit_p(tegra_nvec_remove),
++	.remove  = tegra_nvec_remove,
+ 	.driver  = {
+ 		.name = "nvec",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/staging/nvec/nvec_kbd.c b/drivers/staging/nvec/nvec_kbd.c
+index 6cc30dcd8306..7c8c603da705 100644
+--- a/drivers/staging/nvec/nvec_kbd.c
++++ b/drivers/staging/nvec/nvec_kbd.c
+@@ -169,7 +169,7 @@ static int __devexit nvec_kbd_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver nvec_kbd_driver = {
+ 	.probe  = nvec_kbd_probe,
+-	.remove = __devexit_p(nvec_kbd_remove),
++	.remove = nvec_kbd_remove,
+ 	.driver = {
+ 		.name = "nvec-kbd",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/staging/nvec/nvec_paz00.c b/drivers/staging/nvec/nvec_paz00.c
+index b747e39ff94d..aab234e97d0b 100644
+--- a/drivers/staging/nvec/nvec_paz00.c
++++ b/drivers/staging/nvec/nvec_paz00.c
+@@ -83,7 +83,7 @@ static int __devexit nvec_paz00_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver nvec_paz00_driver = {
+ 	.probe  = nvec_paz00_probe,
+-	.remove = __devexit_p(nvec_paz00_remove),
++	.remove = nvec_paz00_remove,
+ 	.driver = {
+ 		.name  = "nvec-paz00",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/staging/nvec/nvec_power.c b/drivers/staging/nvec/nvec_power.c
+index cc8ccd75e7f4..99e06f661c19 100644
+--- a/drivers/staging/nvec/nvec_power.c
++++ b/drivers/staging/nvec/nvec_power.c
+@@ -425,7 +425,7 @@ static int __devexit nvec_power_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver nvec_power_driver = {
+ 	.probe = nvec_power_probe,
+-	.remove = __devexit_p(nvec_power_remove),
++	.remove = nvec_power_remove,
+ 	.driver = {
+ 		   .name = "nvec-power",
+ 		   .owner = THIS_MODULE,
+diff --git a/drivers/staging/nvec/nvec_ps2.c b/drivers/staging/nvec/nvec_ps2.c
+index d7c651102131..6375e80e77af 100644
+--- a/drivers/staging/nvec/nvec_ps2.c
++++ b/drivers/staging/nvec/nvec_ps2.c
+@@ -164,7 +164,7 @@ static const SIMPLE_DEV_PM_OPS(nvec_mouse_pm_ops, nvec_mouse_suspend,
+ 
+ static struct platform_driver nvec_mouse_driver = {
+ 	.probe  = nvec_mouse_probe,
+-	.remove = __devexit_p(nvec_mouse_remove),
++	.remove = nvec_mouse_remove,
+ 	.driver = {
+ 		.name = "nvec-mouse",
+ 		.owner = THIS_MODULE,

commit 53b800198592b0ff96577ecc5f116f7d902a4362
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:36 2012 -0500
+
+    staging: comedi: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/8255_pci.c b/drivers/staging/comedi/drivers/8255_pci.c
+index 448f18d7560a..e0a79521f35a 100644
+--- a/drivers/staging/comedi/drivers/8255_pci.c
++++ b/drivers/staging/comedi/drivers/8255_pci.c
+@@ -314,7 +314,7 @@ static int pci_8255_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &pci_8255_driver);
+ }
+ 
+-static void __devexit pci_8255_pci_remove(struct pci_dev *dev)
++static void pci_8255_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/addi_apci_035.c b/drivers/staging/comedi/drivers/addi_apci_035.c
+index 8e5e5faae4f3..c981d4b1cc73 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_035.c
++++ b/drivers/staging/comedi/drivers/addi_apci_035.c
+@@ -53,7 +53,7 @@ static int apci035_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &apci035_driver);
+ }
+ 
+-static void __devexit apci035_pci_remove(struct pci_dev *dev)
++static void apci035_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c
+index 15b660bc1a2a..7f9424205a64 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_1032.c
++++ b/drivers/staging/comedi/drivers/addi_apci_1032.c
+@@ -375,7 +375,7 @@ static int apci1032_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &apci1032_driver);
+ }
+ 
+-static void __devexit apci1032_pci_remove(struct pci_dev *dev)
++static void apci1032_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c
+index 80115ccb6c7d..8e686a9b811b 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_1500.c
++++ b/drivers/staging/comedi/drivers/addi_apci_1500.c
+@@ -53,7 +53,7 @@ static int apci1500_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &apci1500_driver);
+ }
+ 
+-static void __devexit apci1500_pci_remove(struct pci_dev *dev)
++static void apci1500_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/addi_apci_1516.c b/drivers/staging/comedi/drivers/addi_apci_1516.c
+index ac32e9fa98e6..8fef04b4d197 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_1516.c
++++ b/drivers/staging/comedi/drivers/addi_apci_1516.c
+@@ -323,7 +323,7 @@ static int apci1516_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &apci1516_driver);
+ }
+ 
+-static void __devexit apci1516_pci_remove(struct pci_dev *dev)
++static void apci1516_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c
+index d03579a1659e..513e536f292f 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_1564.c
++++ b/drivers/staging/comedi/drivers/addi_apci_1564.c
+@@ -50,7 +50,7 @@ static int apci1564_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &apci1564_driver);
+ }
+ 
+-static void __devexit apci1564_pci_remove(struct pci_dev *dev)
++static void apci1564_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/addi_apci_16xx.c b/drivers/staging/comedi/drivers/addi_apci_16xx.c
+index 054578753086..ab9a96ac8180 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_16xx.c
++++ b/drivers/staging/comedi/drivers/addi_apci_16xx.c
+@@ -52,7 +52,7 @@ static int apci16xx_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &apci16xx_driver);
+ }
+ 
+-static void __devexit apci16xx_pci_remove(struct pci_dev *dev)
++static void apci16xx_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/addi_apci_1710.c b/drivers/staging/comedi/drivers/addi_apci_1710.c
+index 1c9ed4785d07..152e7ef9b17b 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_1710.c
++++ b/drivers/staging/comedi/drivers/addi_apci_1710.c
+@@ -128,7 +128,7 @@ static int apci1710_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &apci1710_driver);
+ }
+ 
+-static void __devexit apci1710_pci_remove(struct pci_dev *dev)
++static void apci1710_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c
+index f60720546e32..459e90013ea7 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_2032.c
++++ b/drivers/staging/comedi/drivers/addi_apci_2032.c
+@@ -47,7 +47,7 @@ static int apci2032_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &apci2032_driver);
+ }
+ 
+-static void __devexit apci2032_pci_remove(struct pci_dev *dev)
++static void apci2032_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/addi_apci_2200.c b/drivers/staging/comedi/drivers/addi_apci_2200.c
+index b931e17e3f5d..7c2c5db01218 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_2200.c
++++ b/drivers/staging/comedi/drivers/addi_apci_2200.c
+@@ -45,7 +45,7 @@ static int apci2200_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &apci2200_driver);
+ }
+ 
+-static void __devexit apci2200_pci_remove(struct pci_dev *dev)
++static void apci2200_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c
+index 86e34c406e82..fec2962affc7 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_3120.c
++++ b/drivers/staging/comedi/drivers/addi_apci_3120.c
+@@ -251,7 +251,7 @@ static int apci3120_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &apci3120_driver);
+ }
+ 
+-static void __devexit apci3120_pci_remove(struct pci_dev *dev)
++static void apci3120_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/addi_apci_3200.c b/drivers/staging/comedi/drivers/addi_apci_3200.c
+index bce297308a53..9085b774b48d 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_3200.c
++++ b/drivers/staging/comedi/drivers/addi_apci_3200.c
+@@ -106,7 +106,7 @@ static int apci3200_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &apci3200_driver);
+ }
+ 
+-static void __devexit apci3200_pci_remove(struct pci_dev *dev)
++static void apci3200_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c
+index cff8ff16b0bd..ed297deb8634 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_3501.c
++++ b/drivers/staging/comedi/drivers/addi_apci_3501.c
+@@ -57,7 +57,7 @@ static int apci3501_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &apci3501_driver);
+ }
+ 
+-static void __devexit apci3501_pci_remove(struct pci_dev *dev)
++static void apci3501_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
+index c4fa11df47c1..1562347ed64b 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c
++++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
+@@ -751,7 +751,7 @@ static int apci3xxx_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &apci3xxx_driver);
+ }
+ 
+-static void __devexit apci3xxx_pci_remove(struct pci_dev *dev)
++static void apci3xxx_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c
+index d7ba5e32202e..9a56eed3910f 100644
+--- a/drivers/staging/comedi/drivers/adl_pci6208.c
++++ b/drivers/staging/comedi/drivers/adl_pci6208.c
+@@ -270,7 +270,7 @@ static int adl_pci6208_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &adl_pci6208_driver);
+ }
+ 
+-static void __devexit adl_pci6208_pci_remove(struct pci_dev *dev)
++static void adl_pci6208_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/adl_pci7x3x.c b/drivers/staging/comedi/drivers/adl_pci7x3x.c
+index e94f0db16630..772edc02f5ce 100644
+--- a/drivers/staging/comedi/drivers/adl_pci7x3x.c
++++ b/drivers/staging/comedi/drivers/adl_pci7x3x.c
+@@ -302,7 +302,7 @@ static int adl_pci7x3x_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &adl_pci7x3x_driver);
+ }
+ 
+-static void __devexit adl_pci7x3x_pci_remove(struct pci_dev *dev)
++static void adl_pci7x3x_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c
+index c8135fefe19d..4dd9d707a79d 100644
+--- a/drivers/staging/comedi/drivers/adl_pci8164.c
++++ b/drivers/staging/comedi/drivers/adl_pci8164.c
+@@ -298,7 +298,7 @@ static int adl_pci8164_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &adl_pci8164_driver);
+ }
+ 
+-static void __devexit adl_pci8164_pci_remove(struct pci_dev *dev)
++static void adl_pci8164_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
+index d084db8fe093..a339b9dd27cf 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9111.c
++++ b/drivers/staging/comedi/drivers/adl_pci9111.c
+@@ -963,7 +963,7 @@ static int pci9111_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &adl_pci9111_driver);
+ }
+ 
+-static void __devexit pci9111_pci_remove(struct pci_dev *dev)
++static void pci9111_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
+index c35b25d29781..b6dda809bd13 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9118.c
++++ b/drivers/staging/comedi/drivers/adl_pci9118.c
+@@ -2225,7 +2225,7 @@ static int adl_pci9118_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &adl_pci9118_driver);
+ }
+ 
+-static void __devexit adl_pci9118_pci_remove(struct pci_dev *dev)
++static void adl_pci9118_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
+index b67bb23f63c5..a6fd8c2c16ca 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1710.c
++++ b/drivers/staging/comedi/drivers/adv_pci1710.c
+@@ -1402,7 +1402,7 @@ static int adv_pci1710_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &adv_pci1710_driver);
+ }
+ 
+-static void __devexit adv_pci1710_pci_remove(struct pci_dev *dev)
++static void adv_pci1710_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
+index 03afdd647f4d..5af73146dd85 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1723.c
++++ b/drivers/staging/comedi/drivers/adv_pci1723.c
+@@ -327,7 +327,7 @@ static int adv_pci1723_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &adv_pci1723_driver);
+ }
+ 
+-static void __devexit adv_pci1723_pci_remove(struct pci_dev *dev)
++static void adv_pci1723_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
+index 2ab42c91ad26..05a663e970c6 100644
+--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
++++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
+@@ -1206,7 +1206,7 @@ static int adv_pci_dio_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &adv_pci_dio_driver);
+ }
+ 
+-static void __devexit adv_pci_dio_pci_remove(struct pci_dev *dev)
++static void adv_pci_dio_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
+index 4fd28e3dd807..5f309ba88a1a 100644
+--- a/drivers/staging/comedi/drivers/amplc_dio200.c
++++ b/drivers/staging/comedi/drivers/amplc_dio200.c
+@@ -2079,7 +2079,7 @@ static int amplc_dio200_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &lc_dio200_driver);
+ }
+ 
+-static void __devexit amplc_dio200_pci_remove(struct pci_dev *dev)
++static void amplc_dio200_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
+index 156dd6f0d7e5..289835419577 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc236.c
++++ b/drivers/staging/comedi/drivers/amplc_pc236.c
+@@ -614,7 +614,7 @@ static int amplc_pc236_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &lc_pc236_driver);
+ }
+ 
+-static void __devexit amplc_pc236_pci_remove(struct pci_dev *dev)
++static void amplc_pc236_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
+index ec60e81f712b..dfbff77cd795 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc263.c
++++ b/drivers/staging/comedi/drivers/amplc_pc263.c
+@@ -372,7 +372,7 @@ static int amplc_pc263_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &lc_pc263_driver);
+ }
+ 
+-static void __devexit amplc_pc263_pci_remove(struct pci_dev *dev)
++static void amplc_pc263_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
+index b1b56bab8285..6e2566a2dd57 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci224.c
++++ b/drivers/staging/comedi/drivers/amplc_pci224.c
+@@ -1512,7 +1512,7 @@ static int amplc_pci224_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &lc_pci224_driver);
+ }
+ 
+-static void __devexit amplc_pci224_pci_remove(struct pci_dev *dev)
++static void amplc_pci224_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
+index c16a45a83bb0..366c68be56bd 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci230.c
++++ b/drivers/staging/comedi/drivers/amplc_pci230.c
+@@ -2863,7 +2863,7 @@ static int amplc_pci230_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &lc_pci230_driver);
+ }
+ 
+-static void __devexit amplc_pci230_pci_remove(struct pci_dev *dev)
++static void amplc_pci230_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
+index 87201c4a90ee..aed68639cc9a 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas.c
+@@ -1632,7 +1632,7 @@ static int cb_pcidas_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &cb_pcidas_driver);
+ }
+ 
+-static void __devexit cb_pcidas_pci_remove(struct pci_dev *dev)
++static void cb_pcidas_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
+index 14019b3dbafb..d72b46cc06bc 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
+@@ -4220,7 +4220,7 @@ static int cb_pcidas64_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &cb_pcidas64_driver);
+ }
+ 
+-static void __devexit cb_pcidas64_pci_remove(struct pci_dev *dev)
++static void cb_pcidas64_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
+index 07e98d2da164..7c6029a8c3e1 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidda.c
++++ b/drivers/staging/comedi/drivers/cb_pcidda.c
+@@ -438,7 +438,7 @@ static int cb_pcidda_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &cb_pcidda_driver);
+ }
+ 
+-static void __devexit cb_pcidda_pci_remove(struct pci_dev *dev)
++static void cb_pcidda_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
+index 01404939b4ee..b43a5f80ac26 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
+@@ -299,7 +299,7 @@ static int cb_pcimdas_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &cb_pcimdas_driver);
+ }
+ 
+-static void __devexit cb_pcimdas_pci_remove(struct pci_dev *dev)
++static void cb_pcimdas_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
+index 12eda8e8acfd..699b84f54cc7 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
+@@ -222,7 +222,7 @@ static int cb_pcimdda_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &cb_pcimdda_driver);
+ }
+ 
+-static void __devexit cb_pcimdda_pci_remove(struct pci_dev *dev)
++static void cb_pcimdda_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
+index 0e38f48257ba..1a18fa37bfd0 100644
+--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
++++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
+@@ -130,7 +130,7 @@ static int contec_pci_dio_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &contec_pci_dio_driver);
+ }
+ 
+-static void __devexit contec_pci_dio_pci_remove(struct pci_dev *dev)
++static void contec_pci_dio_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
+index fcabfbe15cb7..992e557e6ae1 100644
+--- a/drivers/staging/comedi/drivers/daqboard2000.c
++++ b/drivers/staging/comedi/drivers/daqboard2000.c
+@@ -799,7 +799,7 @@ static int daqboard2000_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &daqboard2000_driver);
+ }
+ 
+-static void __devexit daqboard2000_pci_remove(struct pci_dev *dev)
++static void daqboard2000_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
+index af595bef6013..b15e05808cb0 100644
+--- a/drivers/staging/comedi/drivers/das08.c
++++ b/drivers/staging/comedi/drivers/das08.c
+@@ -891,7 +891,7 @@ static int das08_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &das08_driver);
+ }
+ 
+-static void __devexit das08_pci_remove(struct pci_dev *dev)
++static void das08_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
+index 80d01a0c7b17..960da8debe17 100644
+--- a/drivers/staging/comedi/drivers/dt3000.c
++++ b/drivers/staging/comedi/drivers/dt3000.c
+@@ -856,7 +856,7 @@ static int dt3000_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &dt3000_driver);
+ }
+ 
+-static void __devexit dt3000_pci_remove(struct pci_dev *dev)
++static void dt3000_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c
+index cb9731967805..8497a36db7db 100644
+--- a/drivers/staging/comedi/drivers/dyna_pci10xx.c
++++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c
+@@ -276,7 +276,7 @@ static int dyna_pci10xx_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &dyna_pci10xx_driver);
+ }
+ 
+-static void __devexit dyna_pci10xx_pci_remove(struct pci_dev *dev)
++static void dyna_pci10xx_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
+index 25708bcefcfe..154598f6d5e3 100644
+--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
++++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
+@@ -946,7 +946,7 @@ static int gsc_hpdi_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &gsc_hpdi_driver);
+ }
+ 
+-static void __devexit gsc_hpdi_pci_remove(struct pci_dev *dev)
++static void gsc_hpdi_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
+index 99e77ce04298..a91a448ba0f0 100644
+--- a/drivers/staging/comedi/drivers/icp_multi.c
++++ b/drivers/staging/comedi/drivers/icp_multi.c
+@@ -623,7 +623,7 @@ static int icp_multi_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &icp_multi_driver);
+ }
+ 
+-static void __devexit icp_multi_pci_remove(struct pci_dev *dev)
++static void icp_multi_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
+index 815b7ef49b07..c756a35ce31a 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -844,7 +844,7 @@ static int jr3_pci_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &jr3_pci_driver);
+ }
+ 
+-static void __devexit jr3_pci_pci_remove(struct pci_dev *dev)
++static void jr3_pci_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c
+index dcce7bb826db..19c94282ac3f 100644
+--- a/drivers/staging/comedi/drivers/ke_counter.c
++++ b/drivers/staging/comedi/drivers/ke_counter.c
+@@ -152,7 +152,7 @@ static int ke_counter_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &ke_counter_driver);
+ }
+ 
+-static void __devexit ke_counter_pci_remove(struct pci_dev *dev)
++static void ke_counter_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
+index f1a561551c02..3c4b0228e8dc 100644
+--- a/drivers/staging/comedi/drivers/me4000.c
++++ b/drivers/staging/comedi/drivers/me4000.c
+@@ -1734,7 +1734,7 @@ static int me4000_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &me4000_driver);
+ }
+ 
+-static void __devexit me4000_pci_remove(struct pci_dev *dev)
++static void me4000_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c
+index 8cbde12b0ecb..ce8e3d3f135c 100644
+--- a/drivers/staging/comedi/drivers/me_daq.c
++++ b/drivers/staging/comedi/drivers/me_daq.c
+@@ -619,7 +619,7 @@ static int me_daq_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &me_daq_driver);
+ }
+ 
+-static void __devexit me_daq_pci_remove(struct pci_dev *dev)
++static void me_daq_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
+index c90a5ab47051..5196b460ce11 100644
+--- a/drivers/staging/comedi/drivers/ni_6527.c
++++ b/drivers/staging/comedi/drivers/ni_6527.c
+@@ -452,7 +452,7 @@ static int ni6527_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &ni6527_driver);
+ }
+ 
+-static void __devexit ni6527_pci_remove(struct pci_dev *dev)
++static void ni6527_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
+index ec733976cd3d..8ef80fd61755 100644
+--- a/drivers/staging/comedi/drivers/ni_65xx.c
++++ b/drivers/staging/comedi/drivers/ni_65xx.c
+@@ -788,7 +788,7 @@ static int ni_65xx_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &ni_65xx_driver);
+ }
+ 
+-static void __devexit ni_65xx_pci_remove(struct pci_dev *dev)
++static void ni_65xx_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
+index 58c9341fe2cf..26baf9c96fff 100644
+--- a/drivers/staging/comedi/drivers/ni_660x.c
++++ b/drivers/staging/comedi/drivers/ni_660x.c
+@@ -1327,7 +1327,7 @@ static int ni_660x_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &ni_660x_driver);
+ }
+ 
+-static void __devexit ni_660x_pci_remove(struct pci_dev *dev)
++static void ni_660x_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
+index 718f8fe172c6..272caeb6ecee 100644
+--- a/drivers/staging/comedi/drivers/ni_670x.c
++++ b/drivers/staging/comedi/drivers/ni_670x.c
+@@ -309,7 +309,7 @@ static int ni_670x_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &ni_670x_driver);
+ }
+ 
+-static void __devexit ni_670x_pci_remove(struct pci_dev *dev)
++static void ni_670x_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
+index 961642549624..d29c4d761bac 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc.c
++++ b/drivers/staging/comedi/drivers/ni_labpc.c
+@@ -2116,7 +2116,7 @@ static int labpc_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &labpc_driver);
+ }
+ 
+-static void __devexit labpc_pci_remove(struct pci_dev *dev)
++static void labpc_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
+index c13e822604fa..084ebea33ab9 100644
+--- a/drivers/staging/comedi/drivers/ni_pcidio.c
++++ b/drivers/staging/comedi/drivers/ni_pcidio.c
+@@ -1224,7 +1224,7 @@ static int ni_pcidio_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &ni_pcidio_driver);
+ }
+ 
+-static void __devexit ni_pcidio_pci_remove(struct pci_dev *dev)
++static void ni_pcidio_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
+index 4497860a12e9..aaac0b2cc9eb 100644
+--- a/drivers/staging/comedi/drivers/ni_pcimio.c
++++ b/drivers/staging/comedi/drivers/ni_pcimio.c
+@@ -1791,7 +1791,7 @@ static int ni_pcimio_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &ni_pcimio_driver);
+ }
+ 
+-static void __devexit ni_pcimio_pci_remove(struct pci_dev *dev)
++static void ni_pcimio_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
+index 790eafe79e55..8d7c948a919c 100644
+--- a/drivers/staging/comedi/drivers/rtd520.c
++++ b/drivers/staging/comedi/drivers/rtd520.c
+@@ -1420,7 +1420,7 @@ static int rtd520_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &rtd520_driver);
+ }
+ 
+-static void __devexit rtd520_pci_remove(struct pci_dev *dev)
++static void rtd520_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
+index 18f3b18a8c5b..6dc1d2812865 100644
+--- a/drivers/staging/comedi/drivers/s626.c
++++ b/drivers/staging/comedi/drivers/s626.c
+@@ -2836,7 +2836,7 @@ static int s626_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &s626_driver);
+ }
+ 
+-static void __devexit s626_pci_remove(struct pci_dev *dev)
++static void s626_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }
+diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c
+index bbf673f419e3..e2d79700a615 100644
+--- a/drivers/staging/comedi/drivers/skel.c
++++ b/drivers/staging/comedi/drivers/skel.c
+@@ -707,7 +707,7 @@ static int skel_pci_probe(struct pci_dev *dev,
+ 	return comedi_pci_auto_config(dev, &skel_driver);
+ }
+ 
+-static void __devexit skel_pci_remove(struct pci_dev *dev)
++static void skel_pci_remove(struct pci_dev *dev)
+ {
+ 	comedi_pci_auto_unconfig(dev);
+ }

commit a690b7e535f2f97a3a05ee570715abeb60a8910f
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:58 2012 -0500
+
+    staging: comedi: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/8255_pci.c b/drivers/staging/comedi/drivers/8255_pci.c
+index c897d39f6b2b..448f18d7560a 100644
+--- a/drivers/staging/comedi/drivers/8255_pci.c
++++ b/drivers/staging/comedi/drivers/8255_pci.c
+@@ -213,7 +213,7 @@ static const void *pci_8255_find_boardinfo(struct comedi_device *dev,
+ 	return NULL;
+ }
+ 
+-static int __devinit pci_8255_auto_attach(struct comedi_device *dev,
++static int pci_8255_auto_attach(struct comedi_device *dev,
+ 					  unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -308,7 +308,7 @@ static struct comedi_driver pci_8255_driver = {
+ 	.detach		= pci_8255_detach,
+ };
+ 
+-static int __devinit pci_8255_pci_probe(struct pci_dev *dev,
++static int pci_8255_pci_probe(struct pci_dev *dev,
+ 					const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &pci_8255_driver);
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+index 8c0fbf43a7ec..90cc43263aee 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+@@ -93,7 +93,7 @@ static const void *addi_find_boardinfo(struct comedi_device *dev,
+ 	return NULL;
+ }
+ 
+-static int __devinit addi_auto_attach(struct comedi_device *dev,
++static int addi_auto_attach(struct comedi_device *dev,
+ 				      unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+diff --git a/drivers/staging/comedi/drivers/addi_apci_035.c b/drivers/staging/comedi/drivers/addi_apci_035.c
+index 489d151fc037..8e5e5faae4f3 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_035.c
++++ b/drivers/staging/comedi/drivers/addi_apci_035.c
+@@ -47,7 +47,7 @@ static struct comedi_driver apci035_driver = {
+ 	.offset		= sizeof(struct addi_board),
+ };
+ 
+-static int __devinit apci035_pci_probe(struct pci_dev *dev,
++static int apci035_pci_probe(struct pci_dev *dev,
+ 				       const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &apci035_driver);
+diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c
+index 9c2e7f745d67..15b660bc1a2a 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_1032.c
++++ b/drivers/staging/comedi/drivers/addi_apci_1032.c
+@@ -285,7 +285,7 @@ static int apci1032_di_insn_bits(struct comedi_device *dev,
+ 	return insn->n;
+ }
+ 
+-static int __devinit apci1032_auto_attach(struct comedi_device *dev,
++static int apci1032_auto_attach(struct comedi_device *dev,
+ 					  unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -369,7 +369,7 @@ static struct comedi_driver apci1032_driver = {
+ 	.detach		= apci1032_detach,
+ };
+ 
+-static int __devinit apci1032_pci_probe(struct pci_dev *dev,
++static int apci1032_pci_probe(struct pci_dev *dev,
+ 					const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &apci1032_driver);
+diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c
+index 67f145d92814..80115ccb6c7d 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_1500.c
++++ b/drivers/staging/comedi/drivers/addi_apci_1500.c
+@@ -47,7 +47,7 @@ static struct comedi_driver apci1500_driver = {
+ 	.offset		= sizeof(struct addi_board),
+ };
+ 
+-static int __devinit apci1500_pci_probe(struct pci_dev *dev,
++static int apci1500_pci_probe(struct pci_dev *dev,
+ 					const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &apci1500_driver);
+diff --git a/drivers/staging/comedi/drivers/addi_apci_1516.c b/drivers/staging/comedi/drivers/addi_apci_1516.c
+index 086445f558f3..ac32e9fa98e6 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_1516.c
++++ b/drivers/staging/comedi/drivers/addi_apci_1516.c
+@@ -225,7 +225,7 @@ static const void *apci1516_find_boardinfo(struct comedi_device *dev,
+ 	return NULL;
+ }
+ 
+-static int __devinit apci1516_auto_attach(struct comedi_device *dev,
++static int apci1516_auto_attach(struct comedi_device *dev,
+ 					  unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -317,7 +317,7 @@ static struct comedi_driver apci1516_driver = {
+ 	.detach		= apci1516_detach,
+ };
+ 
+-static int __devinit apci1516_pci_probe(struct pci_dev *dev,
++static int apci1516_pci_probe(struct pci_dev *dev,
+ 					const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &apci1516_driver);
+diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c
+index 1d51233ca78e..d03579a1659e 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_1564.c
++++ b/drivers/staging/comedi/drivers/addi_apci_1564.c
+@@ -44,7 +44,7 @@ static struct comedi_driver apci1564_driver = {
+ 	.offset		= sizeof(struct addi_board),
+ };
+ 
+-static int __devinit apci1564_pci_probe(struct pci_dev *dev,
++static int apci1564_pci_probe(struct pci_dev *dev,
+ 					const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &apci1564_driver);
+diff --git a/drivers/staging/comedi/drivers/addi_apci_16xx.c b/drivers/staging/comedi/drivers/addi_apci_16xx.c
+index 07d7c9a5d6d1..054578753086 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_16xx.c
++++ b/drivers/staging/comedi/drivers/addi_apci_16xx.c
+@@ -46,7 +46,7 @@ static struct comedi_driver apci16xx_driver = {
+ 	.offset		= sizeof(struct addi_board),
+ };
+ 
+-static int __devinit apci16xx_pci_probe(struct pci_dev *dev,
++static int apci16xx_pci_probe(struct pci_dev *dev,
+ 					const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &apci16xx_driver);
+diff --git a/drivers/staging/comedi/drivers/addi_apci_1710.c b/drivers/staging/comedi/drivers/addi_apci_1710.c
+index 5d263364dbc1..1c9ed4785d07 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_1710.c
++++ b/drivers/staging/comedi/drivers/addi_apci_1710.c
+@@ -52,7 +52,7 @@ static const void *apci1710_find_boardinfo(struct comedi_device *dev,
+ 	return NULL;
+ }
+ 
+-static int __devinit apci1710_auto_attach(struct comedi_device *dev,
++static int apci1710_auto_attach(struct comedi_device *dev,
+ 					  unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -122,7 +122,7 @@ static struct comedi_driver apci1710_driver = {
+ 	.detach		= apci1710_detach,
+ };
+ 
+-static int __devinit apci1710_pci_probe(struct pci_dev *dev,
++static int apci1710_pci_probe(struct pci_dev *dev,
+ 					const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &apci1710_driver);
+diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c
+index a80bf018b762..f60720546e32 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_2032.c
++++ b/drivers/staging/comedi/drivers/addi_apci_2032.c
+@@ -41,7 +41,7 @@ static struct comedi_driver apci2032_driver = {
+ 	.offset		= sizeof(struct addi_board),
+ };
+ 
+-static int __devinit apci2032_pci_probe(struct pci_dev *dev,
++static int apci2032_pci_probe(struct pci_dev *dev,
+ 					const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &apci2032_driver);
+diff --git a/drivers/staging/comedi/drivers/addi_apci_2200.c b/drivers/staging/comedi/drivers/addi_apci_2200.c
+index 9271cfe1b238..b931e17e3f5d 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_2200.c
++++ b/drivers/staging/comedi/drivers/addi_apci_2200.c
+@@ -39,7 +39,7 @@ static struct comedi_driver apci2200_driver = {
+ 	.offset		= sizeof(struct addi_board),
+ };
+ 
+-static int __devinit apci2200_pci_probe(struct pci_dev *dev,
++static int apci2200_pci_probe(struct pci_dev *dev,
+ 					const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &apci2200_driver);
+diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c
+index 77a9fe933f06..86e34c406e82 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_3120.c
++++ b/drivers/staging/comedi/drivers/addi_apci_3120.c
+@@ -60,7 +60,7 @@ static const void *apci3120_find_boardinfo(struct comedi_device *dev,
+ 	return NULL;
+ }
+ 
+-static int __devinit apci3120_auto_attach(struct comedi_device *dev,
++static int apci3120_auto_attach(struct comedi_device *dev,
+ 					  unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -245,7 +245,7 @@ static struct comedi_driver apci3120_driver = {
+ 	.detach		= apci3120_detach,
+ };
+ 
+-static int __devinit apci3120_pci_probe(struct pci_dev *dev,
++static int apci3120_pci_probe(struct pci_dev *dev,
+ 					const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &apci3120_driver);
+diff --git a/drivers/staging/comedi/drivers/addi_apci_3200.c b/drivers/staging/comedi/drivers/addi_apci_3200.c
+index 59120cf88dbc..bce297308a53 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_3200.c
++++ b/drivers/staging/comedi/drivers/addi_apci_3200.c
+@@ -100,7 +100,7 @@ static struct comedi_driver apci3200_driver = {
+ 	.offset		= sizeof(struct addi_board),
+ };
+ 
+-static int __devinit apci3200_pci_probe(struct pci_dev *dev,
++static int apci3200_pci_probe(struct pci_dev *dev,
+ 					const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &apci3200_driver);
+diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c
+index 530d352e4b6a..cff8ff16b0bd 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_3501.c
++++ b/drivers/staging/comedi/drivers/addi_apci_3501.c
+@@ -51,7 +51,7 @@ static struct comedi_driver apci3501_driver = {
+ 	.offset		= sizeof(struct addi_board),
+ };
+ 
+-static int __devinit apci3501_pci_probe(struct pci_dev *dev,
++static int apci3501_pci_probe(struct pci_dev *dev,
+ 					const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &apci3501_driver);
+diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
+index 4a3e346c359f..c4fa11df47c1 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c
++++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
+@@ -745,7 +745,7 @@ static struct comedi_driver apci3xxx_driver = {
+ 	.offset		= sizeof(struct addi_board),
+ };
+ 
+-static int __devinit apci3xxx_pci_probe(struct pci_dev *dev,
++static int apci3xxx_pci_probe(struct pci_dev *dev,
+ 					const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &apci3xxx_driver);
+diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c
+index 67d7ba1e36b6..d7ba5e32202e 100644
+--- a/drivers/staging/comedi/drivers/adl_pci6208.c
++++ b/drivers/staging/comedi/drivers/adl_pci6208.c
+@@ -174,7 +174,7 @@ static const void *pci6208_find_boardinfo(struct comedi_device *dev,
+ 	return NULL;
+ }
+ 
+-static int __devinit pci6208_auto_attach(struct comedi_device *dev,
++static int pci6208_auto_attach(struct comedi_device *dev,
+ 					 unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -264,7 +264,7 @@ static struct comedi_driver adl_pci6208_driver = {
+ 	.detach		= pci6208_detach,
+ };
+ 
+-static int __devinit adl_pci6208_pci_probe(struct pci_dev *dev,
++static int adl_pci6208_pci_probe(struct pci_dev *dev,
+ 					   const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &adl_pci6208_driver);
+diff --git a/drivers/staging/comedi/drivers/adl_pci7x3x.c b/drivers/staging/comedi/drivers/adl_pci7x3x.c
+index 9ac356b6201d..e94f0db16630 100644
+--- a/drivers/staging/comedi/drivers/adl_pci7x3x.c
++++ b/drivers/staging/comedi/drivers/adl_pci7x3x.c
+@@ -168,7 +168,7 @@ static const void *adl_pci7x3x_find_boardinfo(struct comedi_device *dev,
+ 	return NULL;
+ }
+ 
+-static int __devinit adl_pci7x3x_auto_attach(struct comedi_device *dev,
++static int adl_pci7x3x_auto_attach(struct comedi_device *dev,
+ 					     unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -296,7 +296,7 @@ static struct comedi_driver adl_pci7x3x_driver = {
+ 	.detach		= adl_pci7x3x_detach,
+ };
+ 
+-static int __devinit adl_pci7x3x_pci_probe(struct pci_dev *dev,
++static int adl_pci7x3x_pci_probe(struct pci_dev *dev,
+ 					   const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &adl_pci7x3x_driver);
+diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c
+index d5eb68b4f00f..c8135fefe19d 100644
+--- a/drivers/staging/comedi/drivers/adl_pci8164.c
++++ b/drivers/staging/comedi/drivers/adl_pci8164.c
+@@ -212,7 +212,7 @@ static int adl_pci8164_insn_write_buf1(struct comedi_device *dev,
+ 	return 2;
+ }
+ 
+-static int __devinit adl_pci8164_auto_attach(struct comedi_device *dev,
++static int adl_pci8164_auto_attach(struct comedi_device *dev,
+ 					     unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -292,7 +292,7 @@ static struct comedi_driver adl_pci8164_driver = {
+ 	.detach		= adl_pci8164_detach,
+ };
+ 
+-static int __devinit adl_pci8164_pci_probe(struct pci_dev *dev,
++static int adl_pci8164_pci_probe(struct pci_dev *dev,
+ 					   const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &adl_pci8164_driver);
+diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
+index 1fac2f71b2a8..d084db8fe093 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9111.c
++++ b/drivers/staging/comedi/drivers/adl_pci9111.c
+@@ -856,7 +856,7 @@ static int pci9111_reset(struct comedi_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devinit pci9111_auto_attach(struct comedi_device *dev,
++static int pci9111_auto_attach(struct comedi_device *dev,
+ 					 unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -957,7 +957,7 @@ static struct comedi_driver adl_pci9111_driver = {
+ 	.detach		= pci9111_detach,
+ };
+ 
+-static int __devinit pci9111_pci_probe(struct pci_dev *dev,
++static int pci9111_pci_probe(struct pci_dev *dev,
+ 				       const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &adl_pci9111_driver);
+diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
+index c7d0f33e143a..c35b25d29781 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9118.c
++++ b/drivers/staging/comedi/drivers/adl_pci9118.c
+@@ -2155,7 +2155,7 @@ static int pci9118_attach(struct comedi_device *dev,
+ 				     softsshdelay, hw_err_mask);
+ }
+ 
+-static int __devinit pci9118_auto_attach(struct comedi_device *dev,
++static int pci9118_auto_attach(struct comedi_device *dev,
+ 					 unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -2219,7 +2219,7 @@ static struct comedi_driver adl_pci9118_driver = {
+ 	.offset		= sizeof(struct boardtype),
+ };
+ 
+-static int __devinit adl_pci9118_pci_probe(struct pci_dev *dev,
++static int adl_pci9118_pci_probe(struct pci_dev *dev,
+ 					   const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &adl_pci9118_driver);
+diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
+index 59c1d843a08e..b67bb23f63c5 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1710.c
++++ b/drivers/staging/comedi/drivers/adv_pci1710.c
+@@ -1233,7 +1233,7 @@ static const void *pci1710_find_boardinfo(struct comedi_device *dev,
+ 	return NULL;
+ }
+ 
+-static int __devinit pci1710_auto_attach(struct comedi_device *dev,
++static int pci1710_auto_attach(struct comedi_device *dev,
+ 					 unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -1396,7 +1396,7 @@ static struct comedi_driver adv_pci1710_driver = {
+ 	.detach		= pci1710_detach,
+ };
+ 
+-static int __devinit adv_pci1710_pci_probe(struct pci_dev *dev,
++static int adv_pci1710_pci_probe(struct pci_dev *dev,
+ 					   const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &adv_pci1710_driver);
+diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
+index 70e017bfa06c..03afdd647f4d 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1723.c
++++ b/drivers/staging/comedi/drivers/adv_pci1723.c
+@@ -232,7 +232,7 @@ static int pci1723_dio_insn_bits(struct comedi_device *dev,
+ 	return insn->n;
+ }
+ 
+-static int __devinit pci1723_auto_attach(struct comedi_device *dev,
++static int pci1723_auto_attach(struct comedi_device *dev,
+ 					 unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -321,7 +321,7 @@ static struct comedi_driver adv_pci1723_driver = {
+ 	.detach		= pci1723_detach,
+ };
+ 
+-static int __devinit adv_pci1723_pci_probe(struct pci_dev *dev,
++static int adv_pci1723_pci_probe(struct pci_dev *dev,
+ 					   const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &adv_pci1723_driver);
+diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
+index 9e75006c9e74..2ab42c91ad26 100644
+--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
++++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
+@@ -1090,7 +1090,7 @@ static const void *pci_dio_find_boardinfo(struct comedi_device *dev,
+ 	return NULL;
+ }
+ 
+-static int __devinit pci_dio_auto_attach(struct comedi_device *dev,
++static int pci_dio_auto_attach(struct comedi_device *dev,
+ 					 unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -1200,7 +1200,7 @@ static struct comedi_driver adv_pci_dio_driver = {
+ 	.detach		= pci_dio_detach,
+ };
+ 
+-static int __devinit adv_pci_dio_pci_probe(struct pci_dev *dev,
++static int adv_pci_dio_pci_probe(struct pci_dev *dev,
+ 					   const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &adv_pci_dio_driver);
+diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
+index 909acf89f4ff..4fd28e3dd807 100644
+--- a/drivers/staging/comedi/drivers/amplc_dio200.c
++++ b/drivers/staging/comedi/drivers/amplc_dio200.c
+@@ -1925,7 +1925,7 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+  * comedi_pci_auto_config().  dev->board_ptr is NULL on entry.
+  * There should be a board entry matching the supplied PCI device.
+  */
+-static int __devinit dio200_auto_attach(struct comedi_device *dev,
++static int dio200_auto_attach(struct comedi_device *dev,
+ 					unsigned long context_unused)
+ {
+ 	struct pci_dev *pci_dev = comedi_to_pci_dev(dev);
+@@ -2072,7 +2072,7 @@ static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = {
+ 
+ MODULE_DEVICE_TABLE(pci, dio200_pci_table);
+ 
+-static int __devinit amplc_dio200_pci_probe(struct pci_dev *dev,
++static int amplc_dio200_pci_probe(struct pci_dev *dev,
+ 						   const struct pci_device_id
+ 						   *ent)
+ {
+diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
+index 09e096c6b6bd..156dd6f0d7e5 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc236.c
++++ b/drivers/staging/comedi/drivers/amplc_pc236.c
+@@ -526,7 +526,7 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+  * comedi_pci_auto_config().  dev->board_ptr is NULL on entry.
+  * There should be a board entry matching the supplied PCI device.
+  */
+-static int __devinit pc236_auto_attach(struct comedi_device *dev,
++static int pc236_auto_attach(struct comedi_device *dev,
+ 				       unsigned long context_unused)
+ {
+ 	struct pci_dev *pci_dev = comedi_to_pci_dev(dev);
+@@ -608,7 +608,7 @@ static DEFINE_PCI_DEVICE_TABLE(pc236_pci_table) = {
+ 
+ MODULE_DEVICE_TABLE(pci, pc236_pci_table);
+ 
+-static int __devinit amplc_pc236_pci_probe(struct pci_dev *dev,
++static int amplc_pc236_pci_probe(struct pci_dev *dev,
+ 					   const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &lc_pc236_driver);
+diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
+index c041716efb05..ec60e81f712b 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc263.c
++++ b/drivers/staging/comedi/drivers/amplc_pc263.c
+@@ -296,7 +296,7 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+  * comedi_pci_auto_config().  dev->board_ptr is NULL on entry.
+  * There should be a board entry matching the supplied PCI device.
+  */
+-static int __devinit pc263_auto_attach(struct comedi_device *dev,
++static int pc263_auto_attach(struct comedi_device *dev,
+ 				       unsigned long context_unused)
+ {
+ 	struct pci_dev *pci_dev;
+@@ -365,7 +365,7 @@ static DEFINE_PCI_DEVICE_TABLE(pc263_pci_table) = {
+ };
+ MODULE_DEVICE_TABLE(pci, pc263_pci_table);
+ 
+-static int __devinit amplc_pc263_pci_probe(struct pci_dev *dev,
++static int amplc_pc263_pci_probe(struct pci_dev *dev,
+ 						  const struct pci_device_id
+ 						  *ent)
+ {
+diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
+index 1713a6660757..b1b56bab8285 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci224.c
++++ b/drivers/staging/comedi/drivers/amplc_pci224.c
+@@ -1438,7 +1438,7 @@ static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	return pci224_attach_common(dev, pci_dev, it->options);
+ }
+ 
+-static int __devinit
++static int
+ pci224_auto_attach(struct comedi_device *dev, unsigned long context_unused)
+ {
+ 	struct pci_dev *pci_dev = comedi_to_pci_dev(dev);
+@@ -1505,7 +1505,7 @@ static struct comedi_driver amplc_pci224_driver = {
+ 	.num_names	= ARRAY_SIZE(pci224_boards),
+ };
+ 
+-static int __devinit amplc_pci224_pci_probe(struct pci_dev *dev,
++static int amplc_pci224_pci_probe(struct pci_dev *dev,
+ 						   const struct pci_device_id
+ 						   *ent)
+ {
+diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
+index d0ea06992520..c16a45a83bb0 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci230.c
++++ b/drivers/staging/comedi/drivers/amplc_pci230.c
+@@ -2801,7 +2801,7 @@ static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	return pci230_attach_common(dev, pci_dev);
+ }
+ 
+-static int __devinit pci230_auto_attach(struct comedi_device *dev,
++static int pci230_auto_attach(struct comedi_device *dev,
+ 					unsigned long context_unused)
+ {
+ 	struct pci_dev *pci_dev = comedi_to_pci_dev(dev);
+@@ -2857,7 +2857,7 @@ static struct comedi_driver amplc_pci230_driver = {
+ 	.num_names	= ARRAY_SIZE(pci230_boards),
+ };
+ 
+-static int __devinit amplc_pci230_pci_probe(struct pci_dev *dev,
++static int amplc_pci230_pci_probe(struct pci_dev *dev,
+ 					    const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &lc_pci230_driver);
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
+index 857a8d63c9fd..87201c4a90ee 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas.c
+@@ -1436,7 +1436,7 @@ static const void *cb_pcidas_find_boardinfo(struct comedi_device *dev,
+ 	return NULL;
+ }
+ 
+-static int __devinit cb_pcidas_auto_attach(struct comedi_device *dev,
++static int cb_pcidas_auto_attach(struct comedi_device *dev,
+ 					   unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -1626,7 +1626,7 @@ static struct comedi_driver cb_pcidas_driver = {
+ 	.detach		= cb_pcidas_detach,
+ };
+ 
+-static int __devinit cb_pcidas_pci_probe(struct pci_dev *dev,
++static int cb_pcidas_pci_probe(struct pci_dev *dev,
+ 					 const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &cb_pcidas_driver);
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
+index ea2e1e780666..14019b3dbafb 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
+@@ -4043,7 +4043,7 @@ static const struct pcidas64_board
+ 	return NULL;
+ }
+ 
+-static int __devinit auto_attach(struct comedi_device *dev,
++static int auto_attach(struct comedi_device *dev,
+ 				 unsigned long context_unused)
+ {
+ 	const struct pcidas64_board *thisboard;
+@@ -4214,7 +4214,7 @@ static struct comedi_driver cb_pcidas64_driver = {
+ 	.detach		= detach,
+ };
+ 
+-static int __devinit cb_pcidas64_pci_probe(struct pci_dev *dev,
++static int cb_pcidas64_pci_probe(struct pci_dev *dev,
+ 					   const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &cb_pcidas64_driver);
+diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
+index f1a603b00232..07e98d2da164 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidda.c
++++ b/drivers/staging/comedi/drivers/cb_pcidda.c
+@@ -349,7 +349,7 @@ static const void *cb_pcidda_find_boardinfo(struct comedi_device *dev,
+ 	return NULL;
+ }
+ 
+-static int __devinit cb_pcidda_auto_attach(struct comedi_device *dev,
++static int cb_pcidda_auto_attach(struct comedi_device *dev,
+ 					   unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -432,7 +432,7 @@ static struct comedi_driver cb_pcidda_driver = {
+ 	.detach		= cb_pcidda_detach,
+ };
+ 
+-static int __devinit cb_pcidda_pci_probe(struct pci_dev *dev,
++static int cb_pcidda_pci_probe(struct pci_dev *dev,
+ 					 const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &cb_pcidda_driver);
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
+index f171cf9ffd17..01404939b4ee 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
+@@ -205,7 +205,7 @@ static int cb_pcimdas_ao_rinsn(struct comedi_device *dev,
+ 	return i;
+ }
+ 
+-static int __devinit cb_pcimdas_auto_attach(struct comedi_device *dev,
++static int cb_pcimdas_auto_attach(struct comedi_device *dev,
+ 					    unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -293,7 +293,7 @@ static struct comedi_driver cb_pcimdas_driver = {
+ 	.detach		= cb_pcimdas_detach,
+ };
+ 
+-static int __devinit cb_pcimdas_pci_probe(struct pci_dev *dev,
++static int cb_pcimdas_pci_probe(struct pci_dev *dev,
+ 					  const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &cb_pcimdas_driver);
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
+index 78e2ba3f1f24..12eda8e8acfd 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
+@@ -151,7 +151,7 @@ static int cb_pcimdda_ao_rinsn(struct comedi_device *dev,
+ 	return insn->n;
+ }
+ 
+-static int __devinit cb_pcimdda_auto_attach(struct comedi_device *dev,
++static int cb_pcimdda_auto_attach(struct comedi_device *dev,
+ 					    unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -216,7 +216,7 @@ static struct comedi_driver cb_pcimdda_driver = {
+ 	.detach		= cb_pcimdda_detach,
+ };
+ 
+-static int __devinit cb_pcimdda_pci_probe(struct pci_dev *dev,
++static int cb_pcimdda_pci_probe(struct pci_dev *dev,
+ 					  const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &cb_pcimdda_driver);
+diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
+index 3c0ca852d017..0e38f48257ba 100644
+--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
++++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
+@@ -68,7 +68,7 @@ static int contec_di_insn_bits(struct comedi_device *dev,
+ 	return insn->n;
+ }
+ 
+-static int __devinit contec_auto_attach(struct comedi_device *dev,
++static int contec_auto_attach(struct comedi_device *dev,
+ 					unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -124,7 +124,7 @@ static struct comedi_driver contec_pci_dio_driver = {
+ 	.detach		= contec_detach,
+ };
+ 
+-static int __devinit contec_pci_dio_pci_probe(struct pci_dev *dev,
++static int contec_pci_dio_pci_probe(struct pci_dev *dev,
+ 					      const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &contec_pci_dio_driver);
+diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
+index c0fd3b158155..fcabfbe15cb7 100644
+--- a/drivers/staging/comedi/drivers/daqboard2000.c
++++ b/drivers/staging/comedi/drivers/daqboard2000.c
+@@ -688,7 +688,7 @@ static const void *daqboard2000_find_boardinfo(struct comedi_device *dev,
+ 	return NULL;
+ }
+ 
+-static int __devinit daqboard2000_auto_attach(struct comedi_device *dev,
++static int daqboard2000_auto_attach(struct comedi_device *dev,
+ 					      unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -793,7 +793,7 @@ static struct comedi_driver daqboard2000_driver = {
+ 	.detach		= daqboard2000_detach,
+ };
+ 
+-static int __devinit daqboard2000_pci_probe(struct pci_dev *dev,
++static int daqboard2000_pci_probe(struct pci_dev *dev,
+ 					    const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &daqboard2000_driver);
+diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
+index 88f78a0efb2a..af595bef6013 100644
+--- a/drivers/staging/comedi/drivers/das08.c
++++ b/drivers/staging/comedi/drivers/das08.c
+@@ -774,7 +774,7 @@ das08_find_pci_board(struct pci_dev *pdev)
+ }
+ 
+ /* only called in the PCI probe path, via comedi_pci_auto_config() */
+-static int __devinit __maybe_unused
++static int __maybe_unused
+ das08_auto_attach(struct comedi_device *dev, unsigned long context_unused)
+ {
+ 	struct pci_dev *pdev;
+@@ -885,7 +885,7 @@ static DEFINE_PCI_DEVICE_TABLE(das08_pci_table) = {
+ 
+ MODULE_DEVICE_TABLE(pci, das08_pci_table);
+ 
+-static int __devinit das08_pci_probe(struct pci_dev *dev,
++static int das08_pci_probe(struct pci_dev *dev,
+ 					    const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &das08_driver);
+diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
+index b61004b422a6..80d01a0c7b17 100644
+--- a/drivers/staging/comedi/drivers/dt3000.c
++++ b/drivers/staging/comedi/drivers/dt3000.c
+@@ -728,7 +728,7 @@ static const void *dt3000_find_boardinfo(struct comedi_device *dev,
+ 	return NULL;
+ }
+ 
+-static int __devinit dt3000_auto_attach(struct comedi_device *dev,
++static int dt3000_auto_attach(struct comedi_device *dev,
+ 					unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -850,7 +850,7 @@ static struct comedi_driver dt3000_driver = {
+ 	.detach		= dt3000_detach,
+ };
+ 
+-static int __devinit dt3000_pci_probe(struct pci_dev *dev,
++static int dt3000_pci_probe(struct pci_dev *dev,
+ 				      const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &dt3000_driver);
+diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c
+index 8736ef97f3be..cb9731967805 100644
+--- a/drivers/staging/comedi/drivers/dyna_pci10xx.c
++++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c
+@@ -177,7 +177,7 @@ static int dyna_pci10xx_do_insn_bits(struct comedi_device *dev,
+ 	return insn->n;
+ }
+ 
+-static int __devinit dyna_pci10xx_auto_attach(struct comedi_device *dev,
++static int dyna_pci10xx_auto_attach(struct comedi_device *dev,
+ 					      unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -270,7 +270,7 @@ static struct comedi_driver dyna_pci10xx_driver = {
+ 	.detach		= dyna_pci10xx_detach,
+ };
+ 
+-static int __devinit dyna_pci10xx_pci_probe(struct pci_dev *dev,
++static int dyna_pci10xx_pci_probe(struct pci_dev *dev,
+ 					    const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &dyna_pci10xx_driver);
+diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
+index 98926469e693..25708bcefcfe 100644
+--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
++++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
+@@ -474,7 +474,7 @@ static const struct hpdi_board *hpdi_find_board(struct pci_dev *pcidev)
+ 	return NULL;
+ }
+ 
+-static int __devinit hpdi_auto_attach(struct comedi_device *dev,
++static int hpdi_auto_attach(struct comedi_device *dev,
+ 				      unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -940,7 +940,7 @@ static struct comedi_driver gsc_hpdi_driver = {
+ 	.detach		= hpdi_detach,
+ };
+ 
+-static int __devinit gsc_hpdi_pci_probe(struct pci_dev *dev,
++static int gsc_hpdi_pci_probe(struct pci_dev *dev,
+ 					const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &gsc_hpdi_driver);
+diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
+index ee9b40825883..99e77ce04298 100644
+--- a/drivers/staging/comedi/drivers/icp_multi.c
++++ b/drivers/staging/comedi/drivers/icp_multi.c
+@@ -494,7 +494,7 @@ static int icp_multi_reset(struct comedi_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devinit icp_multi_auto_attach(struct comedi_device *dev,
++static int icp_multi_auto_attach(struct comedi_device *dev,
+ 					   unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -617,7 +617,7 @@ static struct comedi_driver icp_multi_driver = {
+ 	.detach		= icp_multi_detach,
+ };
+ 
+-static int __devinit icp_multi_pci_probe(struct pci_dev *dev,
++static int icp_multi_pci_probe(struct pci_dev *dev,
+ 					   const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &icp_multi_driver);
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
+index ad24b7310ea1..815b7ef49b07 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -657,7 +657,7 @@ static void jr3_pci_poll_dev(unsigned long data)
+ 	add_timer(&devpriv->timer);
+ }
+ 
+-static int __devinit jr3_pci_auto_attach(struct comedi_device *dev,
++static int jr3_pci_auto_attach(struct comedi_device *dev,
+ 					 unsigned long context_unused)
+ {
+ 	int result;
+@@ -838,7 +838,7 @@ static struct comedi_driver jr3_pci_driver = {
+ 	.detach		= jr3_pci_detach,
+ };
+ 
+-static int __devinit jr3_pci_pci_probe(struct pci_dev *dev,
++static int jr3_pci_pci_probe(struct pci_dev *dev,
+ 				       const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &jr3_pci_driver);
+diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c
+index 63c3a1af7e51..dcce7bb826db 100644
+--- a/drivers/staging/comedi/drivers/ke_counter.c
++++ b/drivers/staging/comedi/drivers/ke_counter.c
+@@ -87,7 +87,7 @@ static int cnt_rinsn(struct comedi_device *dev,
+ 	return 1;
+ }
+ 
+-static int __devinit cnt_auto_attach(struct comedi_device *dev,
++static int cnt_auto_attach(struct comedi_device *dev,
+ 				     unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -146,7 +146,7 @@ static struct comedi_driver ke_counter_driver = {
+ 	.detach		= cnt_detach,
+ };
+ 
+-static int __devinit ke_counter_pci_probe(struct pci_dev *dev,
++static int ke_counter_pci_probe(struct pci_dev *dev,
+ 					  const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &ke_counter_driver);
+diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
+index 07594c579b18..f1a561551c02 100644
+--- a/drivers/staging/comedi/drivers/me4000.c
++++ b/drivers/staging/comedi/drivers/me4000.c
+@@ -1563,7 +1563,7 @@ static const void *me4000_find_boardinfo(struct comedi_device *dev,
+ 	return NULL;
+ }
+ 
+-static int __devinit me4000_auto_attach(struct comedi_device *dev,
++static int me4000_auto_attach(struct comedi_device *dev,
+ 					unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -1728,7 +1728,7 @@ static struct comedi_driver me4000_driver = {
+ 	.detach		= me4000_detach,
+ };
+ 
+-static int __devinit me4000_pci_probe(struct pci_dev *dev,
++static int me4000_pci_probe(struct pci_dev *dev,
+ 				      const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &me4000_driver);
+diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c
+index b6482dd2a823..8cbde12b0ecb 100644
+--- a/drivers/staging/comedi/drivers/me_daq.c
++++ b/drivers/staging/comedi/drivers/me_daq.c
+@@ -500,7 +500,7 @@ static const void *me_find_boardinfo(struct comedi_device *dev,
+ 	return NULL;
+ }
+ 
+-static int __devinit me_auto_attach(struct comedi_device *dev,
++static int me_auto_attach(struct comedi_device *dev,
+ 				    unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -613,7 +613,7 @@ static struct comedi_driver me_daq_driver = {
+ 	.detach		= me_detach,
+ };
+ 
+-static int __devinit me_daq_pci_probe(struct pci_dev *dev,
++static int me_daq_pci_probe(struct pci_dev *dev,
+ 				      const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &me_daq_driver);
+diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
+index 7ecebb75fe55..c90a5ab47051 100644
+--- a/drivers/staging/comedi/drivers/ni_6527.c
++++ b/drivers/staging/comedi/drivers/ni_6527.c
+@@ -341,7 +341,7 @@ ni6527_find_boardinfo(struct pci_dev *pcidev)
+ 	return NULL;
+ }
+ 
+-static int __devinit ni6527_auto_attach(struct comedi_device *dev,
++static int ni6527_auto_attach(struct comedi_device *dev,
+ 					unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -446,7 +446,7 @@ static struct comedi_driver ni6527_driver = {
+ 	.detach = ni6527_detach,
+ };
+ 
+-static int __devinit ni6527_pci_probe(struct pci_dev *dev,
++static int ni6527_pci_probe(struct pci_dev *dev,
+ 				      const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &ni6527_driver);
+diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
+index d2204c2cebe8..ec733976cd3d 100644
+--- a/drivers/staging/comedi/drivers/ni_65xx.c
++++ b/drivers/staging/comedi/drivers/ni_65xx.c
+@@ -611,7 +611,7 @@ ni_65xx_find_boardinfo(struct pci_dev *pcidev)
+ 	return NULL;
+ }
+ 
+-static int __devinit ni_65xx_auto_attach(struct comedi_device *dev,
++static int ni_65xx_auto_attach(struct comedi_device *dev,
+ 					 unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -782,7 +782,7 @@ static struct comedi_driver ni_65xx_driver = {
+ 	.detach = ni_65xx_detach,
+ };
+ 
+-static int __devinit ni_65xx_pci_probe(struct pci_dev *dev,
++static int ni_65xx_pci_probe(struct pci_dev *dev,
+ 				       const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &ni_65xx_driver);
+diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
+index aaf4fe771eec..58c9341fe2cf 100644
+--- a/drivers/staging/comedi/drivers/ni_660x.c
++++ b/drivers/staging/comedi/drivers/ni_660x.c
+@@ -1166,7 +1166,7 @@ static int ni_660x_dio_insn_config(struct comedi_device *dev,
+ 	return insn->n;
+ }
+ 
+-static int __devinit ni_660x_auto_attach(struct comedi_device *dev,
++static int ni_660x_auto_attach(struct comedi_device *dev,
+ 					 unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -1321,7 +1321,7 @@ static struct comedi_driver ni_660x_driver = {
+ 	.detach		= ni_660x_detach,
+ };
+ 
+-static int __devinit ni_660x_pci_probe(struct pci_dev *dev,
++static int ni_660x_pci_probe(struct pci_dev *dev,
+ 				       const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &ni_660x_driver);
+diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
+index 5080eca0b9ef..718f8fe172c6 100644
+--- a/drivers/staging/comedi/drivers/ni_670x.c
++++ b/drivers/staging/comedi/drivers/ni_670x.c
+@@ -201,7 +201,7 @@ ni_670x_find_boardinfo(struct pci_dev *pcidev)
+ 	return NULL;
+ }
+ 
+-static int __devinit ni_670x_auto_attach(struct comedi_device *dev,
++static int ni_670x_auto_attach(struct comedi_device *dev,
+ 					 unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -303,7 +303,7 @@ static struct comedi_driver ni_670x_driver = {
+ 	.detach		= ni_670x_detach,
+ };
+ 
+-static int __devinit ni_670x_pci_probe(struct pci_dev *dev,
++static int ni_670x_pci_probe(struct pci_dev *dev,
+ 				       const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &ni_670x_driver);
+diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
+index b2e565bf3df0..961642549624 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc.c
++++ b/drivers/staging/comedi/drivers/ni_labpc.c
+@@ -696,7 +696,7 @@ labpc_pci_find_boardinfo(struct pci_dev *pcidev)
+ 	return NULL;
+ }
+ 
+-static int __devinit labpc_auto_attach(struct comedi_device *dev,
++static int labpc_auto_attach(struct comedi_device *dev,
+ 				       unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -2110,7 +2110,7 @@ static DEFINE_PCI_DEVICE_TABLE(labpc_pci_table) = {
+ };
+ MODULE_DEVICE_TABLE(pci, labpc_pci_table);
+ 
+-static int __devinit labpc_pci_probe(struct pci_dev *dev,
++static int labpc_pci_probe(struct pci_dev *dev,
+ 				     const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &labpc_driver);
+diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
+index f4dd5df0d7e1..c13e822604fa 100644
+--- a/drivers/staging/comedi/drivers/ni_pcidio.c
++++ b/drivers/staging/comedi/drivers/ni_pcidio.c
+@@ -1106,7 +1106,7 @@ nidio_find_boardinfo(struct pci_dev *pcidev)
+ 	return NULL;
+ }
+ 
+-static int __devinit nidio_auto_attach(struct comedi_device *dev,
++static int nidio_auto_attach(struct comedi_device *dev,
+ 				       unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -1218,7 +1218,7 @@ static struct comedi_driver ni_pcidio_driver = {
+ 	.detach		= nidio_detach,
+ };
+ 
+-static int __devinit ni_pcidio_pci_probe(struct pci_dev *dev,
++static int ni_pcidio_pci_probe(struct pci_dev *dev,
+ 					 const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &ni_pcidio_driver);
+diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
+index 597a2d3c4a6c..4497860a12e9 100644
+--- a/drivers/staging/comedi/drivers/ni_pcimio.c
++++ b/drivers/staging/comedi/drivers/ni_pcimio.c
+@@ -1620,7 +1620,7 @@ pcimio_find_boardinfo(struct pci_dev *pcidev)
+ 	return NULL;
+ }
+ 
+-static int __devinit pcimio_auto_attach(struct comedi_device *dev,
++static int pcimio_auto_attach(struct comedi_device *dev,
+ 					unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -1785,7 +1785,7 @@ static struct comedi_driver ni_pcimio_driver = {
+ 	.detach		= pcimio_detach,
+ };
+ 
+-static int __devinit ni_pcimio_pci_probe(struct pci_dev *dev,
++static int ni_pcimio_pci_probe(struct pci_dev *dev,
+ 					 const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &ni_pcimio_driver);
+diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
+index 83edc3e85e82..790eafe79e55 100644
+--- a/drivers/staging/comedi/drivers/rtd520.c
++++ b/drivers/staging/comedi/drivers/rtd520.c
+@@ -1272,7 +1272,7 @@ static const void *rtd_find_boardinfo(struct comedi_device *dev,
+ 	return NULL;
+ }
+ 
+-static int __devinit rtd_auto_attach(struct comedi_device *dev,
++static int rtd_auto_attach(struct comedi_device *dev,
+ 				     unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -1414,7 +1414,7 @@ static struct comedi_driver rtd520_driver = {
+ 	.detach		= rtd_detach,
+ };
+ 
+-static int __devinit rtd520_pci_probe(struct pci_dev *dev,
++static int rtd520_pci_probe(struct pci_dev *dev,
+ 				      const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &rtd520_driver);
+diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
+index 30686e2b8a71..18f3b18a8c5b 100644
+--- a/drivers/staging/comedi/drivers/s626.c
++++ b/drivers/staging/comedi/drivers/s626.c
+@@ -2657,7 +2657,7 @@ static void s626_initialize(struct comedi_device *dev)
+ 	/* writel(IRQ_GPIO3 | IRQ_RPS1, devpriv->base_addr + P_IER); */
+ }
+ 
+-static int __devinit s626_auto_attach(struct comedi_device *dev,
++static int s626_auto_attach(struct comedi_device *dev,
+ 				      unsigned long context_unused)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -2830,7 +2830,7 @@ static struct comedi_driver s626_driver = {
+ 	.detach		= s626_detach,
+ };
+ 
+-static int __devinit s626_pci_probe(struct pci_dev *dev,
++static int s626_pci_probe(struct pci_dev *dev,
+ 				    const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &s626_driver);
+diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c
+index 98c1868ab03d..bbf673f419e3 100644
+--- a/drivers/staging/comedi/drivers/skel.c
++++ b/drivers/staging/comedi/drivers/skel.c
+@@ -541,16 +541,12 @@ static int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+  * comedi_usb_auto_config(), etc.) to handle devices that can be attached
+  * to the Comedi core automatically without the COMEDI_DEVCONFIG ioctl.
+  *
+- * For PCI devices, comedi_pci_auto_config() is usually called directly from
+- * the struct pci_driver probe() function, so this _auto_attach() function
+- * can be tagged __devinit.
+- *
+  * The context parameter is usually unused, but if the driver called
+  * comedi_auto_config() directly instead of the comedi_pci_auto_config()
+  * wrapper function, this will be a copy of the context passed to
+  * comedi_auto_config().
+  */
+-static int __devinit skel_auto_attach(struct comedi_device *dev,
++static int skel_auto_attach(struct comedi_device *dev,
+ 				      unsigned long context)
+ {
+ 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+@@ -705,7 +701,7 @@ static DEFINE_PCI_DEVICE_TABLE(skel_pci_table) = {
+ };
+ MODULE_DEVICE_TABLE(pci, skel_pci_table);
+ 
+-static int __devinit skel_pci_probe(struct pci_dev *dev,
++static int skel_pci_probe(struct pci_dev *dev,
+ 					   const struct pci_device_id *ent)
+ {
+ 	return comedi_pci_auto_config(dev, &skel_driver);

commit a471eace7baa40cdf16d3f26b2f78ddce613ca8f
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:37 2012 -0500
+
+    staging: comedi: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/8255_pci.c b/drivers/staging/comedi/drivers/8255_pci.c
+index 71ad619d9c60..c897d39f6b2b 100644
+--- a/drivers/staging/comedi/drivers/8255_pci.c
++++ b/drivers/staging/comedi/drivers/8255_pci.c
+@@ -342,7 +342,7 @@ static struct pci_driver pci_8255_pci_driver = {
+ 	.name		= "8255_pci",
+ 	.id_table	= pci_8255_pci_table,
+ 	.probe		= pci_8255_pci_probe,
+-	.remove		= __devexit_p(pci_8255_pci_remove),
++	.remove		= pci_8255_pci_remove,
+ };
+ module_comedi_pci_driver(pci_8255_driver, pci_8255_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/addi_apci_035.c b/drivers/staging/comedi/drivers/addi_apci_035.c
+index 3055fc2e0a7d..489d151fc037 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_035.c
++++ b/drivers/staging/comedi/drivers/addi_apci_035.c
+@@ -68,7 +68,7 @@ static struct pci_driver apci035_pci_driver = {
+ 	.name		= "addi_apci_035",
+ 	.id_table	= apci035_pci_table,
+ 	.probe		= apci035_pci_probe,
+-	.remove		= __devexit_p(apci035_pci_remove),
++	.remove		= apci035_pci_remove,
+ };
+ module_comedi_pci_driver(apci035_driver, apci035_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c
+index 0f47113ee0b6..9c2e7f745d67 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_1032.c
++++ b/drivers/staging/comedi/drivers/addi_apci_1032.c
+@@ -390,7 +390,7 @@ static struct pci_driver apci1032_pci_driver = {
+ 	.name		= "addi_apci_1032",
+ 	.id_table	= apci1032_pci_table,
+ 	.probe		= apci1032_pci_probe,
+-	.remove		= __devexit_p(apci1032_pci_remove),
++	.remove		= apci1032_pci_remove,
+ };
+ module_comedi_pci_driver(apci1032_driver, apci1032_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c
+index 8528b27f77e7..67f145d92814 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_1500.c
++++ b/drivers/staging/comedi/drivers/addi_apci_1500.c
+@@ -68,7 +68,7 @@ static struct pci_driver apci1500_pci_driver = {
+ 	.name		= "addi_apci_1500",
+ 	.id_table	= apci1500_pci_table,
+ 	.probe		= apci1500_pci_probe,
+-	.remove		= __devexit_p(apci1500_pci_remove),
++	.remove		= apci1500_pci_remove,
+ };
+ module_comedi_pci_driver(apci1500_driver, apci1500_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/addi_apci_1516.c b/drivers/staging/comedi/drivers/addi_apci_1516.c
+index e6aa5226014d..086445f558f3 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_1516.c
++++ b/drivers/staging/comedi/drivers/addi_apci_1516.c
+@@ -340,7 +340,7 @@ static struct pci_driver apci1516_pci_driver = {
+ 	.name		= "addi_apci_1516",
+ 	.id_table	= apci1516_pci_table,
+ 	.probe		= apci1516_pci_probe,
+-	.remove		= __devexit_p(apci1516_pci_remove),
++	.remove		= apci1516_pci_remove,
+ };
+ module_comedi_pci_driver(apci1516_driver, apci1516_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c
+index 926fa088392f..1d51233ca78e 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_1564.c
++++ b/drivers/staging/comedi/drivers/addi_apci_1564.c
+@@ -65,7 +65,7 @@ static struct pci_driver apci1564_pci_driver = {
+ 	.name		= "addi_apci_1564",
+ 	.id_table	= apci1564_pci_table,
+ 	.probe		= apci1564_pci_probe,
+-	.remove		= __devexit_p(apci1564_pci_remove),
++	.remove		= apci1564_pci_remove,
+ };
+ module_comedi_pci_driver(apci1564_driver, apci1564_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/addi_apci_16xx.c b/drivers/staging/comedi/drivers/addi_apci_16xx.c
+index 170d576761a0..07d7c9a5d6d1 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_16xx.c
++++ b/drivers/staging/comedi/drivers/addi_apci_16xx.c
+@@ -68,7 +68,7 @@ static struct pci_driver apci16xx_pci_driver = {
+ 	.name		= "addi_apci_16xx",
+ 	.id_table	= apci16xx_pci_table,
+ 	.probe		= apci16xx_pci_probe,
+-	.remove		= __devexit_p(apci16xx_pci_remove),
++	.remove		= apci16xx_pci_remove,
+ };
+ module_comedi_pci_driver(apci16xx_driver, apci16xx_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/addi_apci_1710.c b/drivers/staging/comedi/drivers/addi_apci_1710.c
+index 485f8214516f..5d263364dbc1 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_1710.c
++++ b/drivers/staging/comedi/drivers/addi_apci_1710.c
+@@ -143,7 +143,7 @@ static struct pci_driver apci1710_pci_driver = {
+ 	.name		= "addi_apci_1710",
+ 	.id_table	= apci1710_pci_table,
+ 	.probe		= apci1710_pci_probe,
+-	.remove		= __devexit_p(apci1710_pci_remove),
++	.remove		= apci1710_pci_remove,
+ };
+ module_comedi_pci_driver(apci1710_driver, apci1710_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c
+index 7758de3146e9..a80bf018b762 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_2032.c
++++ b/drivers/staging/comedi/drivers/addi_apci_2032.c
+@@ -62,7 +62,7 @@ static struct pci_driver apci2032_pci_driver = {
+ 	.name		= "addi_apci_2032",
+ 	.id_table	= apci2032_pci_table,
+ 	.probe		= apci2032_pci_probe,
+-	.remove		= __devexit_p(apci2032_pci_remove),
++	.remove		= apci2032_pci_remove,
+ };
+ module_comedi_pci_driver(apci2032_driver, apci2032_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/addi_apci_2200.c b/drivers/staging/comedi/drivers/addi_apci_2200.c
+index 3041009915f0..9271cfe1b238 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_2200.c
++++ b/drivers/staging/comedi/drivers/addi_apci_2200.c
+@@ -60,7 +60,7 @@ static struct pci_driver apci2200_pci_driver = {
+ 	.name		= "addi_apci_2200",
+ 	.id_table	= apci2200_pci_table,
+ 	.probe		= apci2200_pci_probe,
+-	.remove		= __devexit_p(apci2200_pci_remove),
++	.remove		= apci2200_pci_remove,
+ };
+ module_comedi_pci_driver(apci2200_driver, apci2200_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c
+index 34aab504d350..77a9fe933f06 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_3120.c
++++ b/drivers/staging/comedi/drivers/addi_apci_3120.c
+@@ -267,7 +267,7 @@ static struct pci_driver apci3120_pci_driver = {
+ 	.name		= "addi_apci_3120",
+ 	.id_table	= apci3120_pci_table,
+ 	.probe		= apci3120_pci_probe,
+-	.remove		= __devexit_p(apci3120_pci_remove),
++	.remove		= apci3120_pci_remove,
+ };
+ module_comedi_pci_driver(apci3120_driver, apci3120_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/addi_apci_3200.c b/drivers/staging/comedi/drivers/addi_apci_3200.c
+index e95141dabbd9..59120cf88dbc 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_3200.c
++++ b/drivers/staging/comedi/drivers/addi_apci_3200.c
+@@ -115,6 +115,6 @@ static struct pci_driver apci3200_pci_driver = {
+ 	.name		= "addi_apci_3200",
+ 	.id_table	= apci3200_pci_table,
+ 	.probe		= apci3200_pci_probe,
+-	.remove		= __devexit_p(apci3200_pci_remove),
++	.remove		= apci3200_pci_remove,
+ };
+ module_comedi_pci_driver(apci3200_driver, apci3200_pci_driver);
+diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c
+index 4c60167be2fc..530d352e4b6a 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_3501.c
++++ b/drivers/staging/comedi/drivers/addi_apci_3501.c
+@@ -66,7 +66,7 @@ static struct pci_driver apci3501_pci_driver = {
+ 	.name		= "addi_apci_3501",
+ 	.id_table	= apci3501_pci_table,
+ 	.probe		= apci3501_pci_probe,
+-	.remove		= __devexit_p(apci3501_pci_remove),
++	.remove		= apci3501_pci_remove,
+ };
+ module_comedi_pci_driver(apci3501_driver, apci3501_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
+index cc3938124cdc..4a3e346c359f 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c
++++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
+@@ -790,7 +790,7 @@ static struct pci_driver apci3xxx_pci_driver = {
+ 	.name		= "addi_apci_3xxx",
+ 	.id_table	= apci3xxx_pci_table,
+ 	.probe		= apci3xxx_pci_probe,
+-	.remove		= __devexit_p(apci3xxx_pci_remove),
++	.remove		= apci3xxx_pci_remove,
+ };
+ module_comedi_pci_driver(apci3xxx_driver, apci3xxx_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c
+index 73fd9750327e..67d7ba1e36b6 100644
+--- a/drivers/staging/comedi/drivers/adl_pci6208.c
++++ b/drivers/staging/comedi/drivers/adl_pci6208.c
+@@ -286,7 +286,7 @@ static struct pci_driver adl_pci6208_pci_driver = {
+ 	.name		= "adl_pci6208",
+ 	.id_table	= adl_pci6208_pci_table,
+ 	.probe		= adl_pci6208_pci_probe,
+-	.remove		= __devexit_p(adl_pci6208_pci_remove),
++	.remove		= adl_pci6208_pci_remove,
+ };
+ module_comedi_pci_driver(adl_pci6208_driver, adl_pci6208_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/adl_pci7x3x.c b/drivers/staging/comedi/drivers/adl_pci7x3x.c
+index be01b2021979..9ac356b6201d 100644
+--- a/drivers/staging/comedi/drivers/adl_pci7x3x.c
++++ b/drivers/staging/comedi/drivers/adl_pci7x3x.c
+@@ -322,7 +322,7 @@ static struct pci_driver adl_pci7x3x_pci_driver = {
+ 	.name		= "adl_pci7x3x",
+ 	.id_table	= adl_pci7x3x_pci_table,
+ 	.probe		= adl_pci7x3x_pci_probe,
+-	.remove		= __devexit_p(adl_pci7x3x_pci_remove),
++	.remove		= adl_pci7x3x_pci_remove,
+ };
+ module_comedi_pci_driver(adl_pci7x3x_driver, adl_pci7x3x_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c
+index 41993ec436f6..d5eb68b4f00f 100644
+--- a/drivers/staging/comedi/drivers/adl_pci8164.c
++++ b/drivers/staging/comedi/drivers/adl_pci8164.c
+@@ -313,7 +313,7 @@ static struct pci_driver adl_pci8164_pci_driver = {
+ 	.name		= "adl_pci8164",
+ 	.id_table	= adl_pci8164_pci_table,
+ 	.probe		= adl_pci8164_pci_probe,
+-	.remove		= __devexit_p(adl_pci8164_pci_remove),
++	.remove		= adl_pci8164_pci_remove,
+ };
+ module_comedi_pci_driver(adl_pci8164_driver, adl_pci8164_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
+index 570ccc676ccc..1fac2f71b2a8 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9111.c
++++ b/drivers/staging/comedi/drivers/adl_pci9111.c
+@@ -979,7 +979,7 @@ static struct pci_driver adl_pci9111_pci_driver = {
+ 	.name		= "adl_pci9111",
+ 	.id_table	= pci9111_pci_table,
+ 	.probe		= pci9111_pci_probe,
+-	.remove		= __devexit_p(pci9111_pci_remove),
++	.remove		= pci9111_pci_remove,
+ };
+ module_comedi_pci_driver(adl_pci9111_driver, adl_pci9111_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
+index a6b21cb61da6..c7d0f33e143a 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9118.c
++++ b/drivers/staging/comedi/drivers/adl_pci9118.c
+@@ -2240,7 +2240,7 @@ static struct pci_driver adl_pci9118_pci_driver = {
+ 	.name		= "adl_pci9118",
+ 	.id_table	= adl_pci9118_pci_table,
+ 	.probe		= adl_pci9118_pci_probe,
+-	.remove		= __devexit_p(adl_pci9118_pci_remove),
++	.remove		= adl_pci9118_pci_remove,
+ };
+ module_comedi_pci_driver(adl_pci9118_driver, adl_pci9118_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
+index bdfa9051f4f0..59c1d843a08e 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1710.c
++++ b/drivers/staging/comedi/drivers/adv_pci1710.c
+@@ -1421,7 +1421,7 @@ static struct pci_driver adv_pci1710_pci_driver = {
+ 	.name		= "adv_pci1710",
+ 	.id_table	= adv_pci1710_pci_table,
+ 	.probe		= adv_pci1710_pci_probe,
+-	.remove		= __devexit_p(adv_pci1710_pci_remove),
++	.remove		= adv_pci1710_pci_remove,
+ };
+ module_comedi_pci_driver(adv_pci1710_driver, adv_pci1710_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
+index 490e4347f11e..70e017bfa06c 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1723.c
++++ b/drivers/staging/comedi/drivers/adv_pci1723.c
+@@ -342,7 +342,7 @@ static struct pci_driver adv_pci1723_pci_driver = {
+ 	.name		= "adv_pci1723",
+ 	.id_table	= adv_pci1723_pci_table,
+ 	.probe		= adv_pci1723_pci_probe,
+-	.remove		= __devexit_p(adv_pci1723_pci_remove),
++	.remove		= adv_pci1723_pci_remove,
+ };
+ module_comedi_pci_driver(adv_pci1723_driver, adv_pci1723_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
+index bb69c0d71ce5..9e75006c9e74 100644
+--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
++++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
+@@ -1234,7 +1234,7 @@ static struct pci_driver adv_pci_dio_pci_driver = {
+ 	.name		= "adv_pci_dio",
+ 	.id_table	= adv_pci_dio_pci_table,
+ 	.probe		= adv_pci_dio_pci_probe,
+-	.remove		= __devexit_p(adv_pci_dio_pci_remove),
++	.remove		= adv_pci_dio_pci_remove,
+ };
+ module_comedi_pci_driver(adv_pci_dio_driver, adv_pci_dio_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
+index 57c618b4e989..909acf89f4ff 100644
+--- a/drivers/staging/comedi/drivers/amplc_dio200.c
++++ b/drivers/staging/comedi/drivers/amplc_dio200.c
+@@ -2088,7 +2088,7 @@ static struct pci_driver amplc_dio200_pci_driver = {
+ 	.name = DIO200_DRIVER_NAME,
+ 	.id_table = dio200_pci_table,
+ 	.probe = &lc_dio200_pci_probe,
+-	.remove = __devexit_p(&lc_dio200_pci_remove)
++	.remove = &lc_dio200_pci_remove
+ };
+ module_comedi_pci_driver(amplc_dio200_driver, amplc_dio200_pci_driver);
+ #else
+diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
+index d460b243f37b..09e096c6b6bd 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc236.c
++++ b/drivers/staging/comedi/drivers/amplc_pc236.c
+@@ -623,7 +623,7 @@ static struct pci_driver amplc_pc236_pci_driver = {
+ 	.name = PC236_DRIVER_NAME,
+ 	.id_table = pc236_pci_table,
+ 	.probe = &lc_pc236_pci_probe,
+-	.remove = __devexit_p(&lc_pc236_pci_remove)
++	.remove = &lc_pc236_pci_remove
+ };
+ 
+ module_comedi_pci_driver(amplc_pc236_driver, amplc_pc236_pci_driver);
+diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
+index dc9504914e2b..c041716efb05 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc263.c
++++ b/drivers/staging/comedi/drivers/amplc_pc263.c
+@@ -381,7 +381,7 @@ static struct pci_driver amplc_pc263_pci_driver = {
+ 	.name = PC263_DRIVER_NAME,
+ 	.id_table = pc263_pci_table,
+ 	.probe = &lc_pc263_pci_probe,
+-	.remove = __devexit_p(&lc_pc263_pci_remove)
++	.remove = &lc_pc263_pci_remove
+ };
+ module_comedi_pci_driver(amplc_pc263_driver, amplc_pc263_pci_driver);
+ #else
+diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
+index 0b901d5d2694..1713a6660757 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci224.c
++++ b/drivers/staging/comedi/drivers/amplc_pci224.c
+@@ -1528,7 +1528,7 @@ static struct pci_driver amplc_pci224_pci_driver = {
+ 	.name		= "amplc_pci224",
+ 	.id_table	= amplc_pci224_pci_table,
+ 	.probe		= amplc_pci224_pci_probe,
+-	.remove		= __devexit_p(amplc_pci224_pci_remove),
++	.remove		= amplc_pci224_pci_remove,
+ };
+ module_comedi_pci_driver(amplc_pci224_driver, amplc_pci224_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
+index 7cc48ec1d5f8..d0ea06992520 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci230.c
++++ b/drivers/staging/comedi/drivers/amplc_pci230.c
+@@ -2879,7 +2879,7 @@ static struct pci_driver amplc_pci230_pci_driver = {
+ 	.name		= "amplc_pci230",
+ 	.id_table	= amplc_pci230_pci_table,
+ 	.probe		= amplc_pci230_pci_probe,
+-	.remove		= __devexit_p(amplc_pci230_pci_remove)
++	.remove		= amplc_pci230_pci_remove
+ };
+ module_comedi_pci_driver(amplc_pci230_driver, amplc_pci230_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
+index 9c45e85ec304..857a8d63c9fd 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas.c
+@@ -1654,7 +1654,7 @@ static struct pci_driver cb_pcidas_pci_driver = {
+ 	.name		= "cb_pcidas",
+ 	.id_table	= cb_pcidas_pci_table,
+ 	.probe		= cb_pcidas_pci_probe,
+-	.remove		= __devexit_p(cb_pcidas_pci_remove)
++	.remove		= cb_pcidas_pci_remove
+ };
+ module_comedi_pci_driver(cb_pcidas_driver, cb_pcidas_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
+index 17813aa6bb2e..ea2e1e780666 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
+@@ -4253,7 +4253,7 @@ static struct pci_driver cb_pcidas64_pci_driver = {
+ 	.name		= "cb_pcidas64",
+ 	.id_table	= cb_pcidas64_pci_table,
+ 	.probe		= cb_pcidas64_pci_probe,
+-	.remove		= __devexit_p(cb_pcidas64_pci_remove),
++	.remove		= cb_pcidas64_pci_remove,
+ };
+ module_comedi_pci_driver(cb_pcidas64_driver, cb_pcidas64_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
+index 083bd8636ef9..f1a603b00232 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidda.c
++++ b/drivers/staging/comedi/drivers/cb_pcidda.c
+@@ -458,7 +458,7 @@ static struct pci_driver cb_pcidda_pci_driver = {
+ 	.name		= "cb_pcidda",
+ 	.id_table	= cb_pcidda_pci_table,
+ 	.probe		= cb_pcidda_pci_probe,
+-	.remove		= __devexit_p(cb_pcidda_pci_remove),
++	.remove		= cb_pcidda_pci_remove,
+ };
+ module_comedi_pci_driver(cb_pcidda_driver, cb_pcidda_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
+index f75873740bc3..f171cf9ffd17 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
+@@ -314,7 +314,7 @@ static struct pci_driver cb_pcimdas_pci_driver = {
+ 	.name		= "cb_pcimdas",
+ 	.id_table	= cb_pcimdas_pci_table,
+ 	.probe		= cb_pcimdas_pci_probe,
+-	.remove		= __devexit_p(cb_pcimdas_pci_remove),
++	.remove		= cb_pcimdas_pci_remove,
+ };
+ module_comedi_pci_driver(cb_pcimdas_driver, cb_pcimdas_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
+index 89c70385330e..78e2ba3f1f24 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
+@@ -237,7 +237,7 @@ static struct pci_driver cb_pcimdda_driver_pci_driver = {
+ 	.name		= "cb_pcimdda",
+ 	.id_table	= cb_pcimdda_pci_table,
+ 	.probe		= cb_pcimdda_pci_probe,
+-	.remove		= __devexit_p(cb_pcimdda_pci_remove),
++	.remove		= cb_pcimdda_pci_remove,
+ };
+ module_comedi_pci_driver(cb_pcimdda_driver, cb_pcimdda_driver_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
+index c06b7b682f7d..3c0ca852d017 100644
+--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
++++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
+@@ -145,7 +145,7 @@ static struct pci_driver contec_pci_dio_pci_driver = {
+ 	.name		= "contec_pci_dio",
+ 	.id_table	= contec_pci_dio_pci_table,
+ 	.probe		= contec_pci_dio_pci_probe,
+-	.remove		= __devexit_p(contec_pci_dio_pci_remove),
++	.remove		= contec_pci_dio_pci_remove,
+ };
+ module_comedi_pci_driver(contec_pci_dio_driver, contec_pci_dio_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
+index c5aa6b8d8f7b..c0fd3b158155 100644
+--- a/drivers/staging/comedi/drivers/daqboard2000.c
++++ b/drivers/staging/comedi/drivers/daqboard2000.c
+@@ -814,7 +814,7 @@ static struct pci_driver daqboard2000_pci_driver = {
+ 	.name		= "daqboard2000",
+ 	.id_table	= daqboard2000_pci_table,
+ 	.probe		= daqboard2000_pci_probe,
+-	.remove		= __devexit_p(daqboard2000_pci_remove),
++	.remove		= daqboard2000_pci_remove,
+ };
+ module_comedi_pci_driver(daqboard2000_driver, daqboard2000_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
+index cc654542a6d2..88f78a0efb2a 100644
+--- a/drivers/staging/comedi/drivers/das08.c
++++ b/drivers/staging/comedi/drivers/das08.c
+@@ -900,7 +900,7 @@ static struct pci_driver das08_pci_driver = {
+ 	.id_table = das08_pci_table,
+ 	.name =  DRV_NAME,
+ 	.probe = &das08_pci_probe,
+-	.remove = __devexit_p(&das08_pci_remove)
++	.remove = &das08_pci_remove
+ };
+ #endif /* DO_PCI */
+ 
+diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
+index f6d4ebd6cb59..b61004b422a6 100644
+--- a/drivers/staging/comedi/drivers/dt3000.c
++++ b/drivers/staging/comedi/drivers/dt3000.c
+@@ -877,7 +877,7 @@ static struct pci_driver dt3000_pci_driver = {
+ 	.name		= "dt3000",
+ 	.id_table	= dt3000_pci_table,
+ 	.probe		= dt3000_pci_probe,
+-	.remove		= __devexit_p(dt3000_pci_remove),
++	.remove		= dt3000_pci_remove,
+ };
+ module_comedi_pci_driver(dt3000_driver, dt3000_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c
+index 363b09d217ea..8736ef97f3be 100644
+--- a/drivers/staging/comedi/drivers/dyna_pci10xx.c
++++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c
+@@ -291,7 +291,7 @@ static struct pci_driver dyna_pci10xx_pci_driver = {
+ 	.name		= "dyna_pci10xx",
+ 	.id_table	= dyna_pci10xx_pci_table,
+ 	.probe		= dyna_pci10xx_pci_probe,
+-	.remove		= __devexit_p(dyna_pci10xx_pci_remove),
++	.remove		= dyna_pci10xx_pci_remove,
+ };
+ module_comedi_pci_driver(dyna_pci10xx_driver, dyna_pci10xx_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
+index eb3cb80ff2a5..98926469e693 100644
+--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
++++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
+@@ -962,7 +962,7 @@ static struct pci_driver gsc_hpdi_pci_driver = {
+ 	.name		= "gsc_hpdi",
+ 	.id_table	= gsc_hpdi_pci_table,
+ 	.probe		= gsc_hpdi_pci_probe,
+-	.remove		= __devexit_p(gsc_hpdi_pci_remove)
++	.remove		= gsc_hpdi_pci_remove
+ };
+ module_comedi_pci_driver(gsc_hpdi_driver, gsc_hpdi_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
+index e7bb6031e54b..ee9b40825883 100644
+--- a/drivers/staging/comedi/drivers/icp_multi.c
++++ b/drivers/staging/comedi/drivers/icp_multi.c
+@@ -638,7 +638,7 @@ static struct pci_driver icp_multi_pci_driver = {
+ 	.name		= "icp_multi",
+ 	.id_table	= icp_multi_pci_table,
+ 	.probe		= icp_multi_pci_probe,
+-	.remove		= __devexit_p(icp_multi_pci_remove),
++	.remove		= icp_multi_pci_remove,
+ };
+ module_comedi_pci_driver(icp_multi_driver, icp_multi_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
+index 65d65fe23d6e..ad24b7310ea1 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -863,7 +863,7 @@ static struct pci_driver jr3_pci_pci_driver = {
+ 	.name		= "jr3_pci",
+ 	.id_table	= jr3_pci_pci_table,
+ 	.probe		= jr3_pci_pci_probe,
+-	.remove		= __devexit_p(jr3_pci_pci_remove),
++	.remove		= jr3_pci_pci_remove,
+ };
+ module_comedi_pci_driver(jr3_pci_driver, jr3_pci_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c
+index a59a12b4f193..63c3a1af7e51 100644
+--- a/drivers/staging/comedi/drivers/ke_counter.c
++++ b/drivers/staging/comedi/drivers/ke_counter.c
+@@ -167,7 +167,7 @@ static struct pci_driver ke_counter_pci_driver = {
+ 	.name		= "ke_counter",
+ 	.id_table	= ke_counter_pci_table,
+ 	.probe		= ke_counter_pci_probe,
+-	.remove		= __devexit_p(ke_counter_pci_remove),
++	.remove		= ke_counter_pci_remove,
+ };
+ module_comedi_pci_driver(ke_counter_driver, ke_counter_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
+index a489a6548e75..07594c579b18 100644
+--- a/drivers/staging/comedi/drivers/me4000.c
++++ b/drivers/staging/comedi/drivers/me4000.c
+@@ -1761,7 +1761,7 @@ static struct pci_driver me4000_pci_driver = {
+ 	.name		= "me4000",
+ 	.id_table	= me4000_pci_table,
+ 	.probe		= me4000_pci_probe,
+-	.remove		= __devexit_p(me4000_pci_remove),
++	.remove		= me4000_pci_remove,
+ };
+ module_comedi_pci_driver(me4000_driver, me4000_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c
+index 22cf0f1e5471..b6482dd2a823 100644
+--- a/drivers/staging/comedi/drivers/me_daq.c
++++ b/drivers/staging/comedi/drivers/me_daq.c
+@@ -635,7 +635,7 @@ static struct pci_driver me_daq_pci_driver = {
+ 	.name		= "me_daq",
+ 	.id_table	= me_daq_pci_table,
+ 	.probe		= me_daq_pci_probe,
+-	.remove		= __devexit_p(me_daq_pci_remove),
++	.remove		= me_daq_pci_remove,
+ };
+ module_comedi_pci_driver(me_daq_driver, me_daq_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
+index 24102d1aa82e..7ecebb75fe55 100644
+--- a/drivers/staging/comedi/drivers/ni_6527.c
++++ b/drivers/staging/comedi/drivers/ni_6527.c
+@@ -461,7 +461,7 @@ static struct pci_driver ni6527_pci_driver = {
+ 	.name = DRIVER_NAME,
+ 	.id_table = ni6527_pci_table,
+ 	.probe = ni6527_pci_probe,
+-	.remove = __devexit_p(ni6527_pci_remove)
++	.remove = ni6527_pci_remove
+ };
+ module_comedi_pci_driver(ni6527_driver, ni6527_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
+index 8318081c89be..d2204c2cebe8 100644
+--- a/drivers/staging/comedi/drivers/ni_65xx.c
++++ b/drivers/staging/comedi/drivers/ni_65xx.c
+@@ -797,7 +797,7 @@ static struct pci_driver ni_65xx_pci_driver = {
+ 	.name = "ni_65xx",
+ 	.id_table = ni_65xx_pci_table,
+ 	.probe = ni_65xx_pci_probe,
+-	.remove = __devexit_p(ni_65xx_pci_remove)
++	.remove = ni_65xx_pci_remove
+ };
+ module_comedi_pci_driver(ni_65xx_driver, ni_65xx_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
+index d1561c72e2d3..aaf4fe771eec 100644
+--- a/drivers/staging/comedi/drivers/ni_660x.c
++++ b/drivers/staging/comedi/drivers/ni_660x.c
+@@ -1345,7 +1345,7 @@ static struct pci_driver ni_660x_pci_driver = {
+ 	.name		= "ni_660x",
+ 	.id_table	= ni_660x_pci_table,
+ 	.probe		= ni_660x_pci_probe,
+-	.remove		= __devexit_p(ni_660x_pci_remove),
++	.remove		= ni_660x_pci_remove,
+ };
+ module_comedi_pci_driver(ni_660x_driver, ni_660x_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
+index 7a72131b9358..5080eca0b9ef 100644
+--- a/drivers/staging/comedi/drivers/ni_670x.c
++++ b/drivers/staging/comedi/drivers/ni_670x.c
+@@ -325,7 +325,7 @@ static struct pci_driver ni_670x_pci_driver = {
+ 	.name		= "ni_670x",
+ 	.id_table	= ni_670x_pci_table,
+ 	.probe		= ni_670x_pci_probe,
+-	.remove		= __devexit_p(ni_670x_pci_remove),
++	.remove		= ni_670x_pci_remove,
+ };
+ module_comedi_pci_driver(ni_670x_driver, ni_670x_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
+index b56039bea6a8..b2e565bf3df0 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc.c
++++ b/drivers/staging/comedi/drivers/ni_labpc.c
+@@ -2125,7 +2125,7 @@ static struct pci_driver labpc_pci_driver = {
+ 	.name = DRV_NAME,
+ 	.id_table = labpc_pci_table,
+ 	.probe = labpc_pci_probe,
+-	.remove = __devexit_p(labpc_pci_remove)
++	.remove = labpc_pci_remove
+ };
+ module_comedi_pci_driver(labpc_driver, labpc_pci_driver);
+ #else
+diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
+index 5d442b09c672..f4dd5df0d7e1 100644
+--- a/drivers/staging/comedi/drivers/ni_pcidio.c
++++ b/drivers/staging/comedi/drivers/ni_pcidio.c
+@@ -1241,7 +1241,7 @@ static struct pci_driver ni_pcidio_pci_driver = {
+ 	.name		= "ni_pcidio",
+ 	.id_table	= ni_pcidio_pci_table,
+ 	.probe		= ni_pcidio_pci_probe,
+-	.remove		= __devexit_p(ni_pcidio_pci_remove),
++	.remove		= ni_pcidio_pci_remove,
+ };
+ module_comedi_pci_driver(ni_pcidio_driver, ni_pcidio_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
+index 65e1896c077f..597a2d3c4a6c 100644
+--- a/drivers/staging/comedi/drivers/ni_pcimio.c
++++ b/drivers/staging/comedi/drivers/ni_pcimio.c
+@@ -1858,7 +1858,7 @@ static struct pci_driver ni_pcimio_pci_driver = {
+ 	.name		= "ni_pcimio",
+ 	.id_table	= ni_pcimio_pci_table,
+ 	.probe		= ni_pcimio_pci_probe,
+-	.remove		= __devexit_p(ni_pcimio_pci_remove)
++	.remove		= ni_pcimio_pci_remove
+ };
+ module_comedi_pci_driver(ni_pcimio_driver, ni_pcimio_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
+index 5b31e60ffb54..83edc3e85e82 100644
+--- a/drivers/staging/comedi/drivers/rtd520.c
++++ b/drivers/staging/comedi/drivers/rtd520.c
+@@ -1436,7 +1436,7 @@ static struct pci_driver rtd520_pci_driver = {
+ 	.name		= "rtd520",
+ 	.id_table	= rtd520_pci_table,
+ 	.probe		= rtd520_pci_probe,
+-	.remove		= __devexit_p(rtd520_pci_remove),
++	.remove		= rtd520_pci_remove,
+ };
+ module_comedi_pci_driver(rtd520_driver, rtd520_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
+index e32b54f4bfc2..30686e2b8a71 100644
+--- a/drivers/staging/comedi/drivers/s626.c
++++ b/drivers/staging/comedi/drivers/s626.c
+@@ -2857,7 +2857,7 @@ static struct pci_driver s626_pci_driver = {
+ 	.name		= "s626",
+ 	.id_table	= s626_pci_table,
+ 	.probe		= s626_pci_probe,
+-	.remove		= __devexit_p(s626_pci_remove),
++	.remove		= s626_pci_remove,
+ };
+ module_comedi_pci_driver(s626_driver, s626_pci_driver);
+ 
+diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c
+index deb0bfaf0a3b..98c1868ab03d 100644
+--- a/drivers/staging/comedi/drivers/skel.c
++++ b/drivers/staging/comedi/drivers/skel.c
+@@ -719,7 +719,7 @@ static void __devexit skel_pci_remove(struct pci_dev *dev)
+ static struct pci_driver skel_pci_driver = {
+ 	.id_table = skel_pci_table,
+ 	.probe = &skel_pci_probe,
+-	.remove = __devexit_p(&skel_pci_remove)
++	.remove = &skel_pci_remove
+ };
+ module_comedi_pci_driver(skel_driver, skel_pci_driver);
+ #else

commit b59bc2fbb4bb67e486c40cdb6a306c06acbaec06
+Author: Bill Pemberton 
+Date:   Wed Nov 21 23:13:09 2012 +0100
+
+    ACPI: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
+index 1599566ed1fe..da93c003e953 100644
+--- a/drivers/acpi/apei/ghes.c
++++ b/drivers/acpi/apei/ghes.c
+@@ -994,7 +994,7 @@ static int __devinit ghes_probe(struct platform_device *ghes_dev)
+ 	return rc;
+ }
+ 
+-static int __devexit ghes_remove(struct platform_device *ghes_dev)
++static int ghes_remove(struct platform_device *ghes_dev)
+ {
+ 	struct ghes *ghes;
+ 	struct acpi_hest_generic *generic;
+diff --git a/drivers/acpi/hed.c b/drivers/acpi/hed.c
+index 20a0f2c3ca3b..b514e81e8cfa 100644
+--- a/drivers/acpi/hed.c
++++ b/drivers/acpi/hed.c
+@@ -70,7 +70,7 @@ static int __devinit acpi_hed_add(struct acpi_device *device)
+ 	return 0;
+ }
+ 
+-static int __devexit acpi_hed_remove(struct acpi_device *device, int type)
++static int acpi_hed_remove(struct acpi_device *device, int type)
+ {
+ 	hed_handle = NULL;
+ 	return 0;

commit a4a557e3d44f509a807e80334f012b36ba6894c6
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:46 2012 -0500
+
+    staging: rtl8192u: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
+index 12572fa3a367..56367f23112f 100644
+--- a/drivers/staging/rtl8192u/r8192U_core.c
++++ b/drivers/staging/rtl8192u/r8192U_core.c
+@@ -146,7 +146,7 @@ MODULE_PARM_DESC(channels," Channel bitmask for specific locales. NYI");
+ 
+ static int rtl8192_usb_probe(struct usb_interface *intf,
+ 			 const struct usb_device_id *id);
+-static void __devexit rtl8192_usb_disconnect(struct usb_interface *intf);
++static void rtl8192_usb_disconnect(struct usb_interface *intf);
+ 
+ 
+ static struct usb_driver rtl8192_usb_driver = {
+@@ -5826,7 +5826,7 @@ void rtl8192_cancel_deferred_work(struct r8192_priv* priv)
+ }
+ 
+ 
+-static void __devexit rtl8192_usb_disconnect(struct usb_interface *intf)
++static void rtl8192_usb_disconnect(struct usb_interface *intf)
+ {
+ 	struct net_device *dev = usb_get_intfdata(intf);
+ 

commit 1387b461af6a5802a79bbeaed048c732a05f3735
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:45 2012 -0500
+
+    staging: rtl8192e: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
+index 95a154b930c0..1a70f324552f 100644
+--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
++++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
+@@ -93,7 +93,7 @@ MODULE_DEVICE_TABLE(pci, rtl8192_pci_id_tbl);
+ 
+ static int rtl8192_pci_probe(struct pci_dev *pdev,
+ 			const struct pci_device_id *id);
+-static void __devexit rtl8192_pci_disconnect(struct pci_dev *pdev);
++static void rtl8192_pci_disconnect(struct pci_dev *pdev);
+ 
+ static struct pci_driver rtl8192_pci_driver = {
+ 	.name = DRV_NAME,	/* Driver name   */
+@@ -2982,7 +2982,7 @@ static int rtl8192_pci_probe(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit rtl8192_pci_disconnect(struct pci_dev *pdev)
++static void rtl8192_pci_disconnect(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+ 	struct r8192_priv *priv ;

commit ea7e9f2a49aa570a08bfb211bf218c98abd6a4c2
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:44 2012 -0500
+
+    staging: rtl8187se: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c
+index a6520cfbc7ec..c46b59a8197e 100644
+--- a/drivers/staging/rtl8187se/r8180_core.c
++++ b/drivers/staging/rtl8187se/r8180_core.c
+@@ -77,7 +77,7 @@ MODULE_PARM_DESC(hwwep, " Try to use hardware WEP support. Still broken and not
+ static int rtl8180_pci_probe(struct pci_dev *pdev,
+ 				       const struct pci_device_id *id);
+ 
+-static void __devexit rtl8180_pci_remove(struct pci_dev *pdev);
++static void rtl8180_pci_remove(struct pci_dev *pdev);
+ 
+ static void rtl8180_shutdown(struct pci_dev *pdev)
+ {
+@@ -3288,7 +3288,7 @@ static int rtl8180_pci_probe(struct pci_dev *pdev,
+ 	return ret;
+ }
+ 
+-static void __devexit rtl8180_pci_remove(struct pci_dev *pdev)
++static void rtl8180_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct r8180_priv *priv;
+ 	struct net_device *dev = pci_get_drvdata(pdev);

commit 83f5789c1023983a564a64be671a95618ea7cc69
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:24:45 2012 -0500
+
+    staging: rtl8192e: remove use of __devinitdata
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitdata is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
+index 7f0f802c5d5c..95a154b930c0 100644
+--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
++++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
+@@ -82,7 +82,7 @@ static struct rtl819x_ops rtl819xp_ops = {
+ 	.RxCheckStuckHandler		= rtl8192_HalRxCheckStuck,
+ };
+ 
+-static struct pci_device_id rtl8192_pci_id_tbl[] __devinitdata = {
++static struct pci_device_id rtl8192_pci_id_tbl[] = {
+ 	{RTL_PCI_DEVICE(0x10ec, 0x8192, rtl819xp_ops)},
+ 	{RTL_PCI_DEVICE(0x07aa, 0x0044, rtl819xp_ops)},
+ 	{RTL_PCI_DEVICE(0x07aa, 0x0047, rtl819xp_ops)},

commit 7df813d56f7364eac9a39f7bee2143b79a56203e
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:24:44 2012 -0500
+
+    staging: rtl8187se: remove use of __devinitdata
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitdata is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c
+index 3527ff73332f..a6520cfbc7ec 100644
+--- a/drivers/staging/rtl8187se/r8180_core.c
++++ b/drivers/staging/rtl8187se/r8180_core.c
+@@ -44,7 +44,7 @@
+ 
+ #include "ieee80211/dot11d.h"
+ 
+-static struct pci_device_id rtl8180_pci_id_tbl[] __devinitdata = {
++static struct pci_device_id rtl8180_pci_id_tbl[] = {
+ 	{
+ 		.vendor = PCI_VENDOR_ID_REALTEK,
+ 		.device = 0x8199,

commit 19fc6b57db3f1522259363d88b1908dc814e0aa5
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:08 2012 -0500
+
+    staging: rtl8187se: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c
+index ca097e450642..3527ff73332f 100644
+--- a/drivers/staging/rtl8187se/r8180_core.c
++++ b/drivers/staging/rtl8187se/r8180_core.c
+@@ -74,7 +74,7 @@ module_param(hwwep, int, S_IRUGO|S_IWUSR);
+ 
+ MODULE_PARM_DESC(hwwep, " Try to use hardware WEP support. Still broken and not available on all cards");
+ 
+-static int __devinit rtl8180_pci_probe(struct pci_dev *pdev,
++static int rtl8180_pci_probe(struct pci_dev *pdev,
+ 				       const struct pci_device_id *id);
+ 
+ static void __devexit rtl8180_pci_remove(struct pci_dev *pdev);
+@@ -3175,7 +3175,7 @@ static const struct net_device_ops rtl8180_netdev_ops = {
+ 	.ndo_start_xmit		= ieee80211_rtl_xmit,
+ };
+ 
+-static int __devinit rtl8180_pci_probe(struct pci_dev *pdev,
++static int rtl8180_pci_probe(struct pci_dev *pdev,
+ 				       const struct pci_device_id *id)
+ {
+ 	unsigned long ioaddr = 0;

commit c506fff1ff06cca59a2c5dfef6fad3357eb0908e
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:05 2012 -0500
+
+    staging: rtl8192e: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
+index 3d636c345740..7f0f802c5d5c 100644
+--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
++++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
+@@ -91,7 +91,7 @@ static struct pci_device_id rtl8192_pci_id_tbl[] __devinitdata = {
+ 
+ MODULE_DEVICE_TABLE(pci, rtl8192_pci_id_tbl);
+ 
+-static int __devinit rtl8192_pci_probe(struct pci_dev *pdev,
++static int rtl8192_pci_probe(struct pci_dev *pdev,
+ 			const struct pci_device_id *id);
+ static void __devexit rtl8192_pci_disconnect(struct pci_dev *pdev);
+ 
+@@ -2846,7 +2846,7 @@ static const struct net_device_ops rtl8192_netdev_ops = {
+ 	.ndo_start_xmit = rtllib_xmit,
+ };
+ 
+-static int __devinit rtl8192_pci_probe(struct pci_dev *pdev,
++static int rtl8192_pci_probe(struct pci_dev *pdev,
+ 			const struct pci_device_id *id)
+ {
+ 	unsigned long ioaddr = 0;

commit 2579452a6deff806d06f5ebb7ae1e8d51c39c9d3
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:04 2012 -0500
+
+    staging: rtl8192u: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
+index 5a2fab9fa772..12572fa3a367 100644
+--- a/drivers/staging/rtl8192u/r8192U_core.c
++++ b/drivers/staging/rtl8192u/r8192U_core.c
+@@ -144,7 +144,7 @@ MODULE_PARM_DESC(ifname," Net interface name, wlan%d=default");
+ MODULE_PARM_DESC(hwwep," Try to use hardware security support. ");
+ MODULE_PARM_DESC(channels," Channel bitmask for specific locales. NYI");
+ 
+-static int __devinit rtl8192_usb_probe(struct usb_interface *intf,
++static int rtl8192_usb_probe(struct usb_interface *intf,
+ 			 const struct usb_device_id *id);
+ static void __devexit rtl8192_usb_disconnect(struct usb_interface *intf);
+ 
+@@ -5739,7 +5739,7 @@ static const struct net_device_ops rtl8192_netdev_ops = {
+      ---------------------------- USB_STUFF---------------------------
+ *****************************************************************************/
+ 
+-static int __devinit rtl8192_usb_probe(struct usb_interface *intf,
++static int rtl8192_usb_probe(struct usb_interface *intf,
+ 			 const struct usb_device_id *id)
+ {
+ //	unsigned long ioaddr = 0;

commit c08561c5cffa7053aeb47aac6d39bb1fa38f0248
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:20:58 2012 -0500
+
+    staging: rtl8192e: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
+index f68df241f78e..3d636c345740 100644
+--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
++++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
+@@ -99,7 +99,7 @@ static struct pci_driver rtl8192_pci_driver = {
+ 	.name = DRV_NAME,	/* Driver name   */
+ 	.id_table = rtl8192_pci_id_tbl,	/* PCI_ID table  */
+ 	.probe	= rtl8192_pci_probe,	/* probe fn      */
+-	.remove	 = __devexit_p(rtl8192_pci_disconnect),	/* remove fn */
++	.remove	 = rtl8192_pci_disconnect,	/* remove fn */
+ 	.suspend = rtl8192E_suspend,	/* PM suspend fn */
+ 	.resume = rtl8192E_resume,                 /* PM resume fn  */
+ };

commit 435c78dfb8bfacbb378cb6b929c06667281be325
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:20:56 2012 -0500
+
+    staging: rtl8187se: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c
+index 6a27836f989e..ca097e450642 100644
+--- a/drivers/staging/rtl8187se/r8180_core.c
++++ b/drivers/staging/rtl8187se/r8180_core.c
+@@ -149,7 +149,7 @@ static struct pci_driver rtl8180_pci_driver = {
+ 	.name		= RTL8180_MODULE_NAME,
+ 	.id_table	= rtl8180_pci_id_tbl,
+ 	.probe		= rtl8180_pci_probe,
+-	.remove		= __devexit_p(rtl8180_pci_remove),
++	.remove		= rtl8180_pci_remove,
+ 	.suspend	= rtl8180_suspend,
+ 	.resume		= rtl8180_resume,
+ 	.shutdown	= rtl8180_shutdown,

commit 0b5e4092241eb4015a91e01d9aca32c214ea8b50
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:20:50 2012 -0500
+
+    staging: et131x: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: devel@driverdev.osuosl.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c
+index d017e67d2ffa..525a7cbec1c9 100644
+--- a/drivers/staging/et131x/et131x.c
++++ b/drivers/staging/et131x/et131x.c
+@@ -5099,7 +5099,7 @@ static struct pci_driver et131x_driver = {
+ 	.name		= DRIVER_NAME,
+ 	.id_table	= et131x_pci_table,
+ 	.probe		= et131x_pci_setup,
+-	.remove		= __devexit_p(et131x_pci_remove),
++	.remove		= et131x_pci_remove,
+ 	.driver.pm	= ET131X_PM_OPS,
+ };
+ 

commit fe5c49b3325e38dd350fc3ceaf30b8f8a3f136b8
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:12 2012 -0500
+
+    staging: et131x: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Mark Einon 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c
+index 8bfe756e040c..d017e67d2ffa 100644
+--- a/drivers/staging/et131x/et131x.c
++++ b/drivers/staging/et131x/et131x.c
+@@ -4897,7 +4897,7 @@ static const struct net_device_ops et131x_netdev_ops = {
+  * contained in the pci_device_id table. This routine is the equivalent to
+  * a device insertion routine.
+  */
+-static int __devinit et131x_pci_setup(struct pci_dev *pdev,
++static int et131x_pci_setup(struct pci_dev *pdev,
+ 			       const struct pci_device_id *ent)
+ {
+ 	struct net_device *netdev;

commit 596c5dd302aad8dea6be12d32d5dfa5d2f72673d
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:57 2012 -0500
+
+    staging: et131x: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Mark Einon 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c
+index 5f15a2e175b4..8bfe756e040c 100644
+--- a/drivers/staging/et131x/et131x.c
++++ b/drivers/staging/et131x/et131x.c
+@@ -4034,7 +4034,7 @@ static struct et131x_adapter *et131x_adapter_init(struct net_device *netdev,
+  * PCI subsystem detects that a PCI device which matches the information
+  * contained in the pci_device_id table has been removed.
+  */
+-static void __devexit et131x_pci_remove(struct pci_dev *pdev)
++static void et131x_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct net_device *netdev = pci_get_drvdata(pdev);
+ 	struct et131x_adapter *adapter = netdev_priv(netdev);

commit a1fc9d87a1061299950a0dc9dac595ab6293ff13
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:54 2012 -0500
+
+    staging: wlags49_h2: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/wlags49_h2/wl_pci.c b/drivers/staging/wlags49_h2/wl_pci.c
+index 38bb63ca0af2..6226e5eebf3a 100644
+--- a/drivers/staging/wlags49_h2/wl_pci.c
++++ b/drivers/staging/wlags49_h2/wl_pci.c
+@@ -126,7 +126,7 @@ MODULE_DEVICE_TABLE(pci, wl_pci_tbl);
+  ******************************************************************************/
+ int wl_pci_probe( struct pci_dev *pdev,
+                                 const struct pci_device_id *ent );
+-void __devexit wl_pci_remove(struct pci_dev *pdev);
++void wl_pci_remove(struct pci_dev *pdev);
+ int wl_pci_setup( struct pci_dev *pdev );
+ void wl_pci_enable_cardbus_interrupts( struct pci_dev *pdev );
+ 
+@@ -435,7 +435,7 @@ int wl_pci_probe( struct pci_dev *pdev,
+  *      N/A
+  *
+  ******************************************************************************/
+-void __devexit wl_pci_remove(struct pci_dev *pdev)
++void wl_pci_remove(struct pci_dev *pdev)
+ {
+     struct net_device       *dev = NULL;
+     /*------------------------------------------------------------------------*/

commit cea69a149a496da70a6b66c5ed988043aabaae3a
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:24:47 2012 -0500
+
+    staging: wlags49_h2: remove use of __devinitdata
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitdata is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/wlags49_h2/wl_pci.c b/drivers/staging/wlags49_h2/wl_pci.c
+index 84b24204e4a8..38bb63ca0af2 100644
+--- a/drivers/staging/wlags49_h2/wl_pci.c
++++ b/drivers/staging/wlags49_h2/wl_pci.c
+@@ -111,7 +111,7 @@ extern dbg_info_t *DbgInfo;
+ #endif  // DBG
+ 
+ /* define the PCI device Table Cardname and id tables */
+-static struct pci_device_id wl_pci_tbl[] __devinitdata = {
++static struct pci_device_id wl_pci_tbl[] = {
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_WL_LKM, PCI_DEVICE_ID_WL_LKM_0), },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_WL_LKM, PCI_DEVICE_ID_WL_LKM_1), },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_WL_LKM, PCI_DEVICE_ID_WL_LKM_2), },

commit a7d712aa3a0395ea142d85622205db342ea6b6cd
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:53 2012 -0500
+
+    staging: wlags49_h2: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/wlags49_h2/wl_pci.c b/drivers/staging/wlags49_h2/wl_pci.c
+index 687b29895d45..84b24204e4a8 100644
+--- a/drivers/staging/wlags49_h2/wl_pci.c
++++ b/drivers/staging/wlags49_h2/wl_pci.c
+@@ -124,7 +124,7 @@ MODULE_DEVICE_TABLE(pci, wl_pci_tbl);
+ /*******************************************************************************
+  * function prototypes
+  ******************************************************************************/
+-int __devinit wl_pci_probe( struct pci_dev *pdev,
++int wl_pci_probe( struct pci_dev *pdev,
+                                 const struct pci_device_id *ent );
+ void __devexit wl_pci_remove(struct pci_dev *pdev);
+ int wl_pci_setup( struct pci_dev *pdev );
+@@ -398,7 +398,7 @@ int wl_adapter_is_open( struct net_device *dev )
+  *      errno value otherwise
+  *
+  ******************************************************************************/
+-int __devinit wl_pci_probe( struct pci_dev *pdev,
++int wl_pci_probe( struct pci_dev *pdev,
+                                 const struct pci_device_id *ent )
+ {
+     int result;

commit 1a65e204961969fa967a9aed6e8bab5d9ac66717
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:19:34 2012 -0500
+
+    staging: wlags49_h2: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed, remove it.
+    
+    This also changes the syntax for the initialization of the wl_driver
+    struct to match convention.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/wlags49_h2/wl_pci.c b/drivers/staging/wlags49_h2/wl_pci.c
+index a09c3ac793a2..687b29895d45 100644
+--- a/drivers/staging/wlags49_h2/wl_pci.c
++++ b/drivers/staging/wlags49_h2/wl_pci.c
+@@ -160,14 +160,13 @@ void wl_pci_dma_hcf_reclaim_rx( struct wl_private *lp );
+ /*******************************************************************************
+  * PCI module function registration
+  ******************************************************************************/
+-static struct pci_driver wl_driver =
+-{
+-	name:		MODULE_NAME,
+-    id_table:	wl_pci_tbl,
+-	probe:		wl_pci_probe,
+-	remove:		__devexit_p(wl_pci_remove),
+-    suspend:    NULL,
+-    resume:     NULL,
++static struct pci_driver wl_driver = {
++	.name	  = MODULE_NAME,
++	.id_table = wl_pci_tbl,
++	.probe	  = wl_pci_probe,
++	.remove	  = wl_pci_remove,
++	.suspend  = NULL,
++	.resume	  = NULL
+ };
+ 
+ /*******************************************************************************

commit 9b96c3124b66a959ba061dbca339944a81686cd2
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:19 2012 -0500
+
+    uio: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: "Hans J. Koch" 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c
+index 098d3d008172..cce0f78341cc 100644
+--- a/drivers/uio/uio_pruss.c
++++ b/drivers/uio/uio_pruss.c
+@@ -209,7 +209,7 @@ static int pruss_probe(struct platform_device *dev)
+ 	return ret;
+ }
+ 
+-static int __devexit pruss_remove(struct platform_device *dev)
++static int pruss_remove(struct platform_device *dev)
+ {
+ 	struct uio_pruss_dev *gdev = platform_get_drvdata(dev);
+ 

commit d46f743822ee6e890a6e7971e089a020e6c0000a
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:24:33 2012 -0500
+
+    uio: remove use of __devinitdata
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitdata is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: "Hans J. Koch" 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/uio/uio_cif.c b/drivers/uio/uio_cif.c
+index 674783f785e8..7dd6fc60539d 100644
+--- a/drivers/uio/uio_cif.c
++++ b/drivers/uio/uio_cif.c
+@@ -112,7 +112,7 @@ static void hilscher_pci_remove(struct pci_dev *dev)
+ 	kfree (info);
+ }
+ 
+-static struct pci_device_id hilscher_pci_ids[] __devinitdata = {
++static struct pci_device_id hilscher_pci_ids[] = {
+ 	{
+ 		.vendor =	PCI_VENDOR_ID_PLX,
+ 		.device =	PCI_DEVICE_ID_PLX_9030,
+diff --git a/drivers/uio/uio_sercos3.c b/drivers/uio/uio_sercos3.c
+index 2e87808711cf..81a10a563120 100644
+--- a/drivers/uio/uio_sercos3.c
++++ b/drivers/uio/uio_sercos3.c
+@@ -197,7 +197,7 @@ static void sercos3_pci_remove(struct pci_dev *dev)
+ 	kfree(info);
+ }
+ 
+-static struct pci_device_id sercos3_pci_ids[] __devinitdata = {
++static struct pci_device_id sercos3_pci_ids[] = {
+ 	{
+ 		.vendor =       PCI_VENDOR_ID_PLX,
+ 		.device =       PCI_DEVICE_ID_PLX_9030,

commit b17b75bb524c6c0dfa5ee4a33591b8a7dcc034d2
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:49 2012 -0500
+
+    uio: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: "Hans J. Koch" 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/uio/uio_aec.c b/drivers/uio/uio_aec.c
+index 72b22d44e8b9..1548982db58b 100644
+--- a/drivers/uio/uio_aec.c
++++ b/drivers/uio/uio_aec.c
+@@ -78,7 +78,7 @@ static void print_board_data(struct pci_dev *pdev, struct uio_info *i)
+ 		ioread8(i->priv + 0x07));
+ }
+ 
+-static int __devinit probe(struct pci_dev *pdev, const struct pci_device_id *id)
++static int probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ 	struct uio_info *info;
+ 	int ret;
+diff --git a/drivers/uio/uio_cif.c b/drivers/uio/uio_cif.c
+index a84a451159ed..674783f785e8 100644
+--- a/drivers/uio/uio_cif.c
++++ b/drivers/uio/uio_cif.c
+@@ -40,7 +40,7 @@ static irqreturn_t hilscher_handler(int irq, struct uio_info *dev_info)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit hilscher_pci_probe(struct pci_dev *dev,
++static int hilscher_pci_probe(struct pci_dev *dev,
+ 					const struct pci_device_id *id)
+ {
+ 	struct uio_info *info;
+diff --git a/drivers/uio/uio_netx.c b/drivers/uio/uio_netx.c
+index a879fd5741f8..6a4ba5e83e37 100644
+--- a/drivers/uio/uio_netx.c
++++ b/drivers/uio/uio_netx.c
+@@ -48,7 +48,7 @@ static irqreturn_t netx_handler(int irq, struct uio_info *dev_info)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit netx_pci_probe(struct pci_dev *dev,
++static int netx_pci_probe(struct pci_dev *dev,
+ 					const struct pci_device_id *id)
+ {
+ 	struct uio_info *info;
+diff --git a/drivers/uio/uio_pci_generic.c b/drivers/uio/uio_pci_generic.c
+index 0bd08ef2b394..14aa10c1f6de 100644
+--- a/drivers/uio/uio_pci_generic.c
++++ b/drivers/uio/uio_pci_generic.c
+@@ -53,7 +53,7 @@ static irqreturn_t irqhandler(int irq, struct uio_info *info)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit probe(struct pci_dev *pdev,
++static int probe(struct pci_dev *pdev,
+ 			   const struct pci_device_id *id)
+ {
+ 	struct uio_pci_generic_dev *gdev;
+diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c
+index d877d643433c..098d3d008172 100644
+--- a/drivers/uio/uio_pruss.c
++++ b/drivers/uio/uio_pruss.c
+@@ -112,7 +112,7 @@ static void pruss_cleanup(struct platform_device *dev,
+ 	kfree(gdev);
+ }
+ 
+-static int __devinit pruss_probe(struct platform_device *dev)
++static int pruss_probe(struct platform_device *dev)
+ {
+ 	struct uio_info *p;
+ 	struct uio_pruss_dev *gdev;
+diff --git a/drivers/uio/uio_sercos3.c b/drivers/uio/uio_sercos3.c
+index a187fa14c5c0..2e87808711cf 100644
+--- a/drivers/uio/uio_sercos3.c
++++ b/drivers/uio/uio_sercos3.c
+@@ -116,7 +116,7 @@ static int sercos3_setup_iomem(struct pci_dev *dev, struct uio_info *info,
+ 	return 0;
+ }
+ 
+-static int __devinit sercos3_pci_probe(struct pci_dev *dev,
++static int sercos3_pci_probe(struct pci_dev *dev,
+ 				       const struct pci_device_id *id)
+ {
+ 	struct uio_info *info;

commit 5a59509b4753c281d3003eb996c8137bef62e5a9
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:07 2012 -0500
+
+    uio: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: "Hans J. Koch" 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c
+index 33a7a273b453..d877d643433c 100644
+--- a/drivers/uio/uio_pruss.c
++++ b/drivers/uio/uio_pruss.c
+@@ -220,7 +220,7 @@ static int __devexit pruss_remove(struct platform_device *dev)
+ 
+ static struct platform_driver pruss_driver = {
+ 	.probe = pruss_probe,
+-	.remove = __devexit_p(pruss_remove),
++	.remove = pruss_remove,
+ 	.driver = {
+ 		   .name = DRV_NAME,
+ 		   .owner = THIS_MODULE,

commit fb4e98ab63433c4d3a1588ea91c73f1cd7ebaa00
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:20 2012 -0500
+
+    usb: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Peter Korsgaard 
+    Cc: Alexander Shishkin 
+    Acked-by: Felipe Balbi 
+    Cc: Li Yang 
+    Cc: Alan Stern 
+    Cc: Wan ZongShun 
+    Cc: Ben Dooks 
+    Cc: Kukjin Kim 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/c67x00/c67x00-drv.c b/drivers/usb/c67x00/c67x00-drv.c
+index 21913dfeecce..fe815ecd557e 100644
+--- a/drivers/usb/c67x00/c67x00-drv.c
++++ b/drivers/usb/c67x00/c67x00-drv.c
+@@ -191,7 +191,7 @@ static int c67x00_drv_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit c67x00_drv_remove(struct platform_device *pdev)
++static int c67x00_drv_remove(struct platform_device *pdev)
+ {
+ 	struct c67x00_device *c67x00 = platform_get_drvdata(pdev);
+ 	struct resource *res;
+diff --git a/drivers/usb/chipidea/ci13xxx_imx.c b/drivers/usb/chipidea/ci13xxx_imx.c
+index 126978038f7a..8c291220be7f 100644
+--- a/drivers/usb/chipidea/ci13xxx_imx.c
++++ b/drivers/usb/chipidea/ci13xxx_imx.c
+@@ -220,7 +220,7 @@ static int ci13xxx_imx_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit ci13xxx_imx_remove(struct platform_device *pdev)
++static int ci13xxx_imx_remove(struct platform_device *pdev)
+ {
+ 	struct ci13xxx_imx_data *data = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/usb/chipidea/ci13xxx_msm.c b/drivers/usb/chipidea/ci13xxx_msm.c
+index e8a8ba36b101..7d16681fd3d2 100644
+--- a/drivers/usb/chipidea/ci13xxx_msm.c
++++ b/drivers/usb/chipidea/ci13xxx_msm.c
+@@ -77,7 +77,7 @@ static int ci13xxx_msm_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit ci13xxx_msm_remove(struct platform_device *pdev)
++static int ci13xxx_msm_remove(struct platform_device *pdev)
+ {
+ 	struct platform_device *plat_ci = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/usb/chipidea/ci13xxx_pci.c b/drivers/usb/chipidea/ci13xxx_pci.c
+index cb7eb3ede5e8..9b227e39299a 100644
+--- a/drivers/usb/chipidea/ci13xxx_pci.c
++++ b/drivers/usb/chipidea/ci13xxx_pci.c
+@@ -107,7 +107,7 @@ static int ci13xxx_pci_probe(struct pci_dev *pdev,
+  * first invoking the udc_remove() and then releases
+  * all PCI resources allocated for this USB device controller
+  */
+-static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev)
++static void ci13xxx_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct platform_device *plat_ci = pci_get_drvdata(pdev);
+ 
+diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
+index 7f9c0d21c897..5a4a5eca4194 100644
+--- a/drivers/usb/chipidea/core.c
++++ b/drivers/usb/chipidea/core.c
+@@ -508,7 +508,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit ci_hdrc_remove(struct platform_device *pdev)
++static int ci_hdrc_remove(struct platform_device *pdev)
+ {
+ 	struct ci13xxx *ci = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/usb/chipidea/usbmisc_imx6q.c b/drivers/usb/chipidea/usbmisc_imx6q.c
+index ee6fa872f936..845efe29e6b9 100644
+--- a/drivers/usb/chipidea/usbmisc_imx6q.c
++++ b/drivers/usb/chipidea/usbmisc_imx6q.c
+@@ -127,7 +127,7 @@ static int usbmisc_imx6q_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit usbmisc_imx6q_remove(struct platform_device *pdev)
++static int usbmisc_imx6q_remove(struct platform_device *pdev)
+ {
+ 	usbmisc_unset_ops(&imx6q_usbmisc_ops);
+ 	clk_disable_unprepare(usbmisc->clk);
+diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
+index 71610800cd88..3a4004a620ad 100644
+--- a/drivers/usb/dwc3/core.c
++++ b/drivers/usb/dwc3/core.c
+@@ -547,7 +547,7 @@ static int dwc3_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit dwc3_remove(struct platform_device *pdev)
++static int dwc3_remove(struct platform_device *pdev)
+ {
+ 	struct dwc3	*dwc = platform_get_drvdata(pdev);
+ 	struct resource	*res;
+diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c
+index 33ae98c52781..92604b4f9712 100644
+--- a/drivers/usb/dwc3/debugfs.c
++++ b/drivers/usb/dwc3/debugfs.c
+@@ -703,7 +703,7 @@ int dwc3_debugfs_init(struct dwc3 *dwc)
+ 	return ret;
+ }
+ 
+-void __devexit dwc3_debugfs_exit(struct dwc3 *dwc)
++void dwc3_debugfs_exit(struct dwc3 *dwc)
+ {
+ 	debugfs_remove_recursive(dwc->root);
+ 	dwc->root = NULL;
+diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
+index d43f0760ca63..aae5328ac771 100644
+--- a/drivers/usb/dwc3/dwc3-exynos.c
++++ b/drivers/usb/dwc3/dwc3-exynos.c
+@@ -170,7 +170,7 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit dwc3_exynos_remove(struct platform_device *pdev)
++static int dwc3_exynos_remove(struct platform_device *pdev)
+ {
+ 	struct dwc3_exynos	*exynos = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
+index e114bb58ccf4..f31867fd2574 100644
+--- a/drivers/usb/dwc3/dwc3-omap.c
++++ b/drivers/usb/dwc3/dwc3-omap.c
+@@ -421,7 +421,7 @@ static int dwc3_omap_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit dwc3_omap_remove(struct platform_device *pdev)
++static int dwc3_omap_remove(struct platform_device *pdev)
+ {
+ 	struct dwc3_omap	*omap = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
+index 68e389b589d6..7d70f44567d2 100644
+--- a/drivers/usb/dwc3/dwc3-pci.c
++++ b/drivers/usb/dwc3/dwc3-pci.c
+@@ -194,7 +194,7 @@ static int dwc3_pci_probe(struct pci_dev *pci,
+ 	return ret;
+ }
+ 
+-static void __devexit dwc3_pci_remove(struct pci_dev *pci)
++static void dwc3_pci_remove(struct pci_dev *pci)
+ {
+ 	struct dwc3_pci	*glue = pci_get_drvdata(pci);
+ 
+diff --git a/drivers/usb/gadget/bcm63xx_udc.c b/drivers/usb/gadget/bcm63xx_udc.c
+index 18eff74e3360..47a49931361e 100644
+--- a/drivers/usb/gadget/bcm63xx_udc.c
++++ b/drivers/usb/gadget/bcm63xx_udc.c
+@@ -2433,7 +2433,7 @@ static int bcm63xx_udc_probe(struct platform_device *pdev)
+  * bcm63xx_udc_remove - Remove the device from the system.
+  * @pdev: Platform device struct from the bcm63xx BSP code.
+  */
+-static int __devexit bcm63xx_udc_remove(struct platform_device *pdev)
++static int bcm63xx_udc_remove(struct platform_device *pdev)
+ {
+ 	struct bcm63xx_udc *udc = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
+index b13bc73f56b9..ec50f18c8890 100644
+--- a/drivers/usb/gadget/fsl_qe_udc.c
++++ b/drivers/usb/gadget/fsl_qe_udc.c
+@@ -2651,7 +2651,7 @@ static int qe_udc_resume(struct platform_device *dev)
+ }
+ #endif
+ 
+-static int __devexit qe_udc_remove(struct platform_device *ofdev)
++static int qe_udc_remove(struct platform_device *ofdev)
+ {
+ 	struct qe_udc *udc = dev_get_drvdata(&ofdev->dev);
+ 	struct qe_ep *ep;
+diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c
+index 33deed6e7945..c36260ea8bf2 100644
+--- a/drivers/usb/gadget/hid.c
++++ b/drivers/usb/gadget/hid.c
+@@ -203,7 +203,7 @@ static int __init hidg_plat_driver_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit hidg_plat_driver_remove(struct platform_device *pdev)
++static int hidg_plat_driver_remove(struct platform_device *pdev)
+ {
+ 	struct hidg_func_node *e, *n;
+ 
+diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c
+index 52ad15ce44ac..dd1c9b1fe528 100644
+--- a/drivers/usb/gadget/lpc32xx_udc.c
++++ b/drivers/usb/gadget/lpc32xx_udc.c
+@@ -3352,7 +3352,7 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev)
+ 	return retval;
+ }
+ 
+-static int __devexit lpc32xx_udc_remove(struct platform_device *pdev)
++static int lpc32xx_udc_remove(struct platform_device *pdev)
+ {
+ 	struct lpc32xx_udc *udc = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c
+index 8cfd5b028dbd..b5cea273c957 100644
+--- a/drivers/usb/gadget/mv_u3d_core.c
++++ b/drivers/usb/gadget/mv_u3d_core.c
+@@ -1763,7 +1763,7 @@ static void mv_u3d_gadget_release(struct device *dev)
+ 	dev_dbg(dev, "%s\n", __func__);
+ }
+ 
+-static __devexit int mv_u3d_remove(struct platform_device *dev)
++static int mv_u3d_remove(struct platform_device *dev)
+ {
+ 	struct mv_u3d *u3d = platform_get_drvdata(dev);
+ 
+diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c
+index 24196492ae20..379aac7b82fc 100644
+--- a/drivers/usb/gadget/mv_udc_core.c
++++ b/drivers/usb/gadget/mv_udc_core.c
+@@ -2128,7 +2128,7 @@ static void gadget_release(struct device *_dev)
+ 	complete(udc->done);
+ }
+ 
+-static int __devexit mv_udc_remove(struct platform_device *dev)
++static int mv_udc_remove(struct platform_device *dev)
+ {
+ 	struct mv_udc *udc = the_controller;
+ 	int clk_i;
+diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c
+index a20acc14e694..d226058e3b88 100644
+--- a/drivers/usb/gadget/net2272.c
++++ b/drivers/usb/gadget/net2272.c
+@@ -2193,7 +2193,7 @@ net2272_gadget_release(struct device *_dev)
+ 
+ /*---------------------------------------------------------------------------*/
+ 
+-static void __devexit
++static void
+ net2272_remove(struct net2272 *dev)
+ {
+ 	usb_del_gadget_udc(&dev->gadget);
+@@ -2488,7 +2488,7 @@ net2272_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	return ret;
+ }
+ 
+-static void __devexit
++static void
+ net2272_rdk1_remove(struct pci_dev *pdev, struct net2272 *dev)
+ {
+ 	int i;
+@@ -2510,7 +2510,7 @@ net2272_rdk1_remove(struct pci_dev *pdev, struct net2272 *dev)
+ 	}
+ }
+ 
+-static void __devexit
++static void
+ net2272_rdk2_remove(struct pci_dev *pdev, struct net2272 *dev)
+ {
+ 	int i;
+@@ -2529,7 +2529,7 @@ net2272_rdk2_remove(struct pci_dev *pdev, struct net2272 *dev)
+ 			pci_resource_len(pdev, i));
+ }
+ 
+-static void __devexit
++static void
+ net2272_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct net2272 *dev = pci_get_drvdata(pdev);
+@@ -2660,7 +2660,7 @@ net2272_plat_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit
++static int
+ net2272_plat_remove(struct platform_device *pdev)
+ {
+ 	struct net2272 *dev = platform_get_drvdata(pdev);
+diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
+index cbc07c117af0..9412bf53b864 100644
+--- a/drivers/usb/gadget/omap_udc.c
++++ b/drivers/usb/gadget/omap_udc.c
+@@ -2974,7 +2974,7 @@ static int omap_udc_probe(struct platform_device *pdev)
+ 	return status;
+ }
+ 
+-static int __devexit omap_udc_remove(struct platform_device *pdev)
++static int omap_udc_remove(struct platform_device *pdev)
+ {
+ 	DECLARE_COMPLETION_ONSTACK(done);
+ 
+diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
+index 6fdb1bd98e98..141971d9051e 100644
+--- a/drivers/usb/gadget/s3c-hsotg.c
++++ b/drivers/usb/gadget/s3c-hsotg.c
+@@ -3460,7 +3460,7 @@ static void s3c_hsotg_create_debug(struct s3c_hsotg *hsotg)
+  *
+  * Cleanup (remove) the debugfs files for use on module exit.
+  */
+-static void __devexit s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg)
++static void s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg)
+ {
+ 	unsigned epidx;
+ 
+@@ -3675,7 +3675,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
+  * s3c_hsotg_remove - remove function for hsotg driver
+  * @pdev: The platform information for the driver
+  */
+-static int __devexit s3c_hsotg_remove(struct platform_device *pdev)
++static int s3c_hsotg_remove(struct platform_device *pdev)
+ {
+ 	struct s3c_hsotg *hsotg = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/usb/host/bcma-hcd.c b/drivers/usb/host/bcma-hcd.c
+index 649780b480bc..df13d425e9c5 100644
+--- a/drivers/usb/host/bcma-hcd.c
++++ b/drivers/usb/host/bcma-hcd.c
+@@ -265,7 +265,7 @@ static int bcma_hcd_probe(struct bcma_device *dev)
+ 	return err;
+ }
+ 
+-static void __devexit bcma_hcd_remove(struct bcma_device *dev)
++static void bcma_hcd_remove(struct bcma_device *dev)
+ {
+ 	struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev);
+ 	struct platform_device *ohci_dev = usb_dev->ohci_dev;
+diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
+index 96bf00d32614..27639487f7ac 100644
+--- a/drivers/usb/host/ehci-atmel.c
++++ b/drivers/usb/host/ehci-atmel.c
+@@ -182,7 +182,7 @@ static int ehci_atmel_drv_probe(struct platform_device *pdev)
+ 	return retval;
+ }
+ 
+-static int __devexit ehci_atmel_drv_remove(struct platform_device *pdev)
++static int ehci_atmel_drv_remove(struct platform_device *pdev)
+ {
+ 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
+index e0acfd589a83..88a49c87e748 100644
+--- a/drivers/usb/host/ehci-msm.c
++++ b/drivers/usb/host/ehci-msm.c
+@@ -173,7 +173,7 @@ static int ehci_msm_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit ehci_msm_remove(struct platform_device *pdev)
++static int ehci_msm_remove(struct platform_device *pdev)
+ {
+ 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
+index 615cba016a6f..58fa0c90c7c7 100644
+--- a/drivers/usb/host/ehci-platform.c
++++ b/drivers/usb/host/ehci-platform.c
+@@ -126,7 +126,7 @@ static int ehci_platform_probe(struct platform_device *dev)
+ 	return err;
+ }
+ 
+-static int __devexit ehci_platform_remove(struct platform_device *dev)
++static int ehci_platform_remove(struct platform_device *dev)
+ {
+ 	struct usb_hcd *hcd = platform_get_drvdata(dev);
+ 	struct usb_ehci_pdata *pdata = dev->dev.platform_data;
+diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c
+index 2cf19d1ab4bf..319dcfaa8735 100644
+--- a/drivers/usb/host/ehci-s5p.c
++++ b/drivers/usb/host/ehci-s5p.c
+@@ -189,7 +189,7 @@ static int s5p_ehci_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit s5p_ehci_remove(struct platform_device *pdev)
++static int s5p_ehci_remove(struct platform_device *pdev)
+ {
+ 	struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
+ 	struct s5p_ehci_hcd *s5p_ehci = platform_get_drvdata(pdev);
+diff --git a/drivers/usb/host/ehci-w90x900.c b/drivers/usb/host/ehci-w90x900.c
+index bf8d462c26ac..59e0e24c753f 100644
+--- a/drivers/usb/host/ehci-w90x900.c
++++ b/drivers/usb/host/ehci-w90x900.c
+@@ -155,7 +155,7 @@ static int ehci_w90x900_probe(struct platform_device *pdev)
+ 	return usb_w90x900_probe(&ehci_w90x900_hc_driver, pdev);
+ }
+ 
+-static int __devexit ehci_w90x900_remove(struct platform_device *pdev)
++static int ehci_w90x900_remove(struct platform_device *pdev)
+ {
+ 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c
+index 618f143748a5..0b46542591ff 100644
+--- a/drivers/usb/host/fhci-hcd.c
++++ b/drivers/usb/host/fhci-hcd.c
+@@ -780,7 +780,7 @@ static int of_fhci_probe(struct platform_device *ofdev)
+ 	return ret;
+ }
+ 
+-static int __devexit fhci_remove(struct device *dev)
++static int fhci_remove(struct device *dev)
+ {
+ 	struct usb_hcd *hcd = dev_get_drvdata(dev);
+ 	struct fhci_hcd *fhci = hcd_to_fhci(hcd);
+@@ -803,7 +803,7 @@ static int __devexit fhci_remove(struct device *dev)
+ 	return 0;
+ }
+ 
+-static int __devexit of_fhci_remove(struct platform_device *ofdev)
++static int of_fhci_remove(struct platform_device *ofdev)
+ {
+ 	return fhci_remove(&ofdev->dev);
+ }
+diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
+index 5faf796fc6ca..5105127c1d4b 100644
+--- a/drivers/usb/host/fsl-mph-dr-of.c
++++ b/drivers/usb/host/fsl-mph-dr-of.c
+@@ -224,13 +224,13 @@ static int fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
+ 	return 0;
+ }
+ 
+-static int __devexit __unregister_subdev(struct device *dev, void *d)
++static int __unregister_subdev(struct device *dev, void *d)
+ {
+ 	platform_device_unregister(to_platform_device(dev));
+ 	return 0;
+ }
+ 
+-static int __devexit fsl_usb2_mph_dr_of_remove(struct platform_device *ofdev)
++static int fsl_usb2_mph_dr_of_remove(struct platform_device *ofdev)
+ {
+ 	device_for_each_child(&ofdev->dev, NULL, __unregister_subdev);
+ 	return 0;
+diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
+index 5f8b63ce4bef..974480c516fa 100644
+--- a/drivers/usb/host/isp1362-hcd.c
++++ b/drivers/usb/host/isp1362-hcd.c
+@@ -2645,7 +2645,7 @@ static struct hc_driver isp1362_hc_driver = {
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-static int __devexit isp1362_remove(struct platform_device *pdev)
++static int isp1362_remove(struct platform_device *pdev)
+ {
+ 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ 	struct isp1362_hcd *isp1362_hcd = hcd_to_isp1362_hcd(hcd);
+diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c
+index d752a4c4281a..bbb791bd7617 100644
+--- a/drivers/usb/host/isp1760-if.c
++++ b/drivers/usb/host/isp1760-if.c
+@@ -413,7 +413,7 @@ static int isp1760_plat_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit isp1760_plat_remove(struct platform_device *pdev)
++static int isp1760_plat_remove(struct platform_device *pdev)
+ {
+ 	struct resource *mem_res;
+ 	resource_size_t mem_size;
+diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
+index ff94a7479a75..221850a8c25f 100644
+--- a/drivers/usb/host/ohci-at91.c
++++ b/drivers/usb/host/ohci-at91.c
+@@ -94,7 +94,7 @@ static void at91_stop_hc(struct platform_device *pdev)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-static void __devexit usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);
++static void usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);
+ 
+ /* configure so an HC device and id are always provided */
+ /* always called with process context; sleeping is OK */
+@@ -203,7 +203,7 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
+  * context, "rmmod" or something similar.
+  *
+  */
+-static void __devexit usb_hcd_at91_remove(struct usb_hcd *hcd,
++static void usb_hcd_at91_remove(struct usb_hcd *hcd,
+ 				struct platform_device *pdev)
+ {
+ 	usb_remove_hcd(hcd);
+@@ -641,7 +641,7 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
+ 	return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev);
+ }
+ 
+-static int __devexit ohci_hcd_at91_drv_remove(struct platform_device *pdev)
++static int ohci_hcd_at91_drv_remove(struct platform_device *pdev)
+ {
+ 	struct at91_usbh_data	*pdata = pdev->dev.platform_data;
+ 	int			i;
+diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
+index 1288cdb3137c..aa3b8844bb9f 100644
+--- a/drivers/usb/host/ohci-exynos.c
++++ b/drivers/usb/host/ohci-exynos.c
+@@ -175,7 +175,7 @@ static int exynos_ohci_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit exynos_ohci_remove(struct platform_device *pdev)
++static int exynos_ohci_remove(struct platform_device *pdev)
+ {
+ 	struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data;
+ 	struct exynos_ohci_hcd *exynos_ohci = platform_get_drvdata(pdev);
+diff --git a/drivers/usb/host/ohci-jz4740.c b/drivers/usb/host/ohci-jz4740.c
+index 59feb8738132..8062bb9dea16 100644
+--- a/drivers/usb/host/ohci-jz4740.c
++++ b/drivers/usb/host/ohci-jz4740.c
+@@ -239,7 +239,7 @@ static int jz4740_ohci_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static __devexit int jz4740_ohci_remove(struct platform_device *pdev)
++static int jz4740_ohci_remove(struct platform_device *pdev)
+ {
+ 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ 	struct jz4740_ohci_hcd *jz4740_ohci = hcd_to_jz4740_hcd(hcd);
+diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c
+index b2398aa6c7a2..4382af3a45f9 100644
+--- a/drivers/usb/host/ohci-omap3.c
++++ b/drivers/usb/host/ohci-omap3.c
+@@ -209,7 +209,7 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev)
+  * the HCD's stop() method.  It is always called from a thread
+  * context, normally "rmmod", "apmd", or something similar.
+  */
+-static int __devexit ohci_hcd_omap3_remove(struct platform_device *pdev)
++static int ohci_hcd_omap3_remove(struct platform_device *pdev)
+ {
+ 	struct device *dev	= &pdev->dev;
+ 	struct usb_hcd *hcd	= dev_get_drvdata(dev);
+diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
+index c3f76fa8d7dc..084503b03fcf 100644
+--- a/drivers/usb/host/ohci-platform.c
++++ b/drivers/usb/host/ohci-platform.c
+@@ -149,7 +149,7 @@ static int ohci_platform_probe(struct platform_device *dev)
+ 	return err;
+ }
+ 
+-static int __devexit ohci_platform_remove(struct platform_device *dev)
++static int ohci_platform_remove(struct platform_device *dev)
+ {
+ 	struct usb_hcd *hcd = platform_get_drvdata(dev);
+ 	struct usb_ohci_pdata *pdata = dev->dev.platform_data;
+diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
+index 4f29e0b086b3..ad0f55269603 100644
+--- a/drivers/usb/host/ohci-s3c2410.c
++++ b/drivers/usb/host/ohci-s3c2410.c
+@@ -463,7 +463,7 @@ static int ohci_hcd_s3c2410_drv_probe(struct platform_device *pdev)
+ 	return usb_hcd_s3c2410_probe(&ohci_s3c2410_hc_driver, pdev);
+ }
+ 
+-static int __devexit ohci_hcd_s3c2410_drv_remove(struct platform_device *pdev)
++static int ohci_hcd_s3c2410_drv_remove(struct platform_device *pdev)
+ {
+ 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c
+index 5996a3b0a4d3..d370245a4ee2 100644
+--- a/drivers/usb/host/ohci-tmio.c
++++ b/drivers/usb/host/ohci-tmio.c
+@@ -271,7 +271,7 @@ static int ohci_hcd_tmio_drv_probe(struct platform_device *dev)
+ 	return ret;
+ }
+ 
+-static int __devexit ohci_hcd_tmio_drv_remove(struct platform_device *dev)
++static int ohci_hcd_tmio_drv_remove(struct platform_device *dev)
+ {
+ 	struct usb_hcd *hcd = platform_get_drvdata(dev);
+ 	struct tmio_hcd *tmio = hcd_to_tmio(hcd);
+diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
+index e97dfad526f4..a6fd8f5371df 100644
+--- a/drivers/usb/host/r8a66597-hcd.c
++++ b/drivers/usb/host/r8a66597-hcd.c
+@@ -2391,7 +2391,7 @@ static const struct dev_pm_ops r8a66597_dev_pm_ops = {
+ #define R8A66597_DEV_PM_OPS	NULL
+ #endif
+ 
+-static int __devexit r8a66597_remove(struct platform_device *pdev)
++static int r8a66597_remove(struct platform_device *pdev)
+ {
+ 	struct r8a66597		*r8a66597 = dev_get_drvdata(&pdev->dev);
+ 	struct usb_hcd		*hcd = r8a66597_to_hcd(r8a66597);
+diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
+index 782127d9dfc5..d62f0404baaa 100644
+--- a/drivers/usb/host/sl811-hcd.c
++++ b/drivers/usb/host/sl811-hcd.c
+@@ -1595,7 +1595,7 @@ static struct hc_driver sl811h_hc_driver = {
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-static int __devexit
++static int
+ sl811h_remove(struct platform_device *dev)
+ {
+ 	struct usb_hcd		*hcd = platform_get_drvdata(dev);
+diff --git a/drivers/usb/host/ssb-hcd.c b/drivers/usb/host/ssb-hcd.c
+index bdb9d7055da9..74af2c6287d2 100644
+--- a/drivers/usb/host/ssb-hcd.c
++++ b/drivers/usb/host/ssb-hcd.c
+@@ -206,7 +206,7 @@ static int ssb_hcd_probe(struct ssb_device *dev,
+ 	return err;
+ }
+ 
+-static void __devexit ssb_hcd_remove(struct ssb_device *dev)
++static void ssb_hcd_remove(struct ssb_device *dev)
+ {
+ 	struct ssb_hcd_device *usb_dev = ssb_get_drvdata(dev);
+ 	struct platform_device *ohci_dev = usb_dev->ohci_dev;
+@@ -220,7 +220,7 @@ static void __devexit ssb_hcd_remove(struct ssb_device *dev)
+ 	ssb_device_disable(dev, 0);
+ }
+ 
+-static void __devexit ssb_hcd_shutdown(struct ssb_device *dev)
++static void ssb_hcd_shutdown(struct ssb_device *dev)
+ {
+ 	ssb_device_disable(dev, 0);
+ }
+diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
+index 8bf78e652a8a..5efdffe32365 100644
+--- a/drivers/usb/host/u132-hcd.c
++++ b/drivers/usb/host/u132-hcd.c
+@@ -2990,7 +2990,7 @@ static struct hc_driver u132_hc_driver = {
+ * synchronously - but instead should immediately stop activity to the
+ * device and asynchronously call usb_remove_hcd()
+ */
+-static int __devexit u132_remove(struct platform_device *pdev)
++static int u132_remove(struct platform_device *pdev)
+ {
+ 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ 	if (hcd) {
+diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c
+index a27bb8515674..3d1c71b50f76 100644
+--- a/drivers/usb/musb/am35x.c
++++ b/drivers/usb/musb/am35x.c
+@@ -560,7 +560,7 @@ static int am35x_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit am35x_remove(struct platform_device *pdev)
++static int am35x_remove(struct platform_device *pdev)
+ {
+ 	struct am35x_glue	*glue = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
+index 12beb0e31144..14dab9f9b3d0 100644
+--- a/drivers/usb/musb/blackfin.c
++++ b/drivers/usb/musb/blackfin.c
+@@ -510,7 +510,7 @@ static int bfin_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit bfin_remove(struct platform_device *pdev)
++static int bfin_remove(struct platform_device *pdev)
+ {
+ 	struct bfin_glue		*glue = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
+index c4fb235985ba..97996af2646e 100644
+--- a/drivers/usb/musb/da8xx.c
++++ b/drivers/usb/musb/da8xx.c
+@@ -555,7 +555,7 @@ static int da8xx_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit da8xx_remove(struct platform_device *pdev)
++static int da8xx_remove(struct platform_device *pdev)
+ {
+ 	struct da8xx_glue		*glue = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
+index 8877c1a7dbb7..b1c01cad28b2 100644
+--- a/drivers/usb/musb/davinci.c
++++ b/drivers/usb/musb/davinci.c
+@@ -587,7 +587,7 @@ static int davinci_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit davinci_remove(struct platform_device *pdev)
++static int davinci_remove(struct platform_device *pdev)
+ {
+ 	struct davinci_glue		*glue = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
+index a332bb81aa38..57cc9c6eaa9f 100644
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -2034,7 +2034,7 @@ static int musb_probe(struct platform_device *pdev)
+ 	return status;
+ }
+ 
+-static int __devexit musb_remove(struct platform_device *pdev)
++static int musb_remove(struct platform_device *pdev)
+ {
+ 	struct device	*dev = &pdev->dev;
+ 	struct musb	*musb = dev_to_musb(dev);
+diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
+index 605cd59d149c..9a975aa0dee2 100644
+--- a/drivers/usb/musb/musb_dsps.c
++++ b/drivers/usb/musb/musb_dsps.c
+@@ -668,7 +668,7 @@ static int dsps_probe(struct platform_device *pdev)
+ err0:
+ 	return ret;
+ }
+-static int __devexit dsps_remove(struct platform_device *pdev)
++static int dsps_remove(struct platform_device *pdev)
+ {
+ 	struct dsps_glue *glue = platform_get_drvdata(pdev);
+ 	const struct dsps_musb_wrapper *wrp = glue->wrp;
+diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
+index 06850f22739f..da00af460794 100644
+--- a/drivers/usb/musb/omap2430.c
++++ b/drivers/usb/musb/omap2430.c
+@@ -605,7 +605,7 @@ static int omap2430_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit omap2430_remove(struct platform_device *pdev)
++static int omap2430_remove(struct platform_device *pdev)
+ {
+ 	struct omap2430_glue		*glue = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
+index a03b7befd2e1..8bde6fc5eb75 100644
+--- a/drivers/usb/musb/tusb6010.c
++++ b/drivers/usb/musb/tusb6010.c
+@@ -1215,7 +1215,7 @@ static int tusb_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit tusb_remove(struct platform_device *pdev)
++static int tusb_remove(struct platform_device *pdev)
+ {
+ 	struct tusb6010_glue		*glue = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c
+index 6b12001eb88b..a27ca1a9c994 100644
+--- a/drivers/usb/musb/ux500.c
++++ b/drivers/usb/musb/ux500.c
+@@ -163,7 +163,7 @@ static int ux500_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit ux500_remove(struct platform_device *pdev)
++static int ux500_remove(struct platform_device *pdev)
+ {
+ 	struct ux500_glue	*glue = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c
+index f0ba931f0d5d..2d86f26a0183 100644
+--- a/drivers/usb/otg/ab8500-usb.c
++++ b/drivers/usb/otg/ab8500-usb.c
+@@ -546,7 +546,7 @@ static int ab8500_usb_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit ab8500_usb_remove(struct platform_device *pdev)
++static int ab8500_usb_remove(struct platform_device *pdev)
+ {
+ 	struct ab8500_usb *ab = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/otg/fsl_otg.c
+index 2b9a83856a50..d16adb41eb21 100644
+--- a/drivers/usb/otg/fsl_otg.c
++++ b/drivers/usb/otg/fsl_otg.c
+@@ -1144,7 +1144,7 @@ static int fsl_otg_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit fsl_otg_remove(struct platform_device *pdev)
++static int fsl_otg_remove(struct platform_device *pdev)
+ {
+ 	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+ 
+diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
+index eef0dd276e1b..3b9f0d951132 100644
+--- a/drivers/usb/otg/msm_otg.c
++++ b/drivers/usb/otg/msm_otg.c
+@@ -1606,7 +1606,7 @@ static int __init msm_otg_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit msm_otg_remove(struct platform_device *pdev)
++static int msm_otg_remove(struct platform_device *pdev)
+ {
+ 	struct msm_otg *motg = platform_get_drvdata(pdev);
+ 	struct usb_phy *phy = &motg->phy;
+diff --git a/drivers/usb/otg/mxs-phy.c b/drivers/usb/otg/mxs-phy.c
+index 001fdde12d7a..76302720055a 100644
+--- a/drivers/usb/otg/mxs-phy.c
++++ b/drivers/usb/otg/mxs-phy.c
+@@ -149,7 +149,7 @@ static int mxs_phy_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit mxs_phy_remove(struct platform_device *pdev)
++static int mxs_phy_remove(struct platform_device *pdev)
+ {
+ 	platform_set_drvdata(pdev, NULL);
+ 
+diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c
+index 28f70e21ad61..a3ce24b94a73 100644
+--- a/drivers/usb/otg/nop-usb-xceiv.c
++++ b/drivers/usb/otg/nop-usb-xceiv.c
+@@ -141,7 +141,7 @@ static int nop_usb_xceiv_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev)
++static int nop_usb_xceiv_remove(struct platform_device *pdev)
+ {
+ 	struct nop_usb_xceiv *nop = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/usb/phy/omap-usb2.c b/drivers/usb/phy/omap-usb2.c
+index c10fb8b1fdbc..26ae8f49225c 100644
+--- a/drivers/usb/phy/omap-usb2.c
++++ b/drivers/usb/phy/omap-usb2.c
+@@ -199,7 +199,7 @@ static int omap_usb2_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit omap_usb2_remove(struct platform_device *pdev)
++static int omap_usb2_remove(struct platform_device *pdev)
+ {
+ 	struct omap_usb	*phy = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/usb/phy/rcar-phy.c b/drivers/usb/phy/rcar-phy.c
+index 84ac2a77de72..a35681b0c501 100644
+--- a/drivers/usb/phy/rcar-phy.c
++++ b/drivers/usb/phy/rcar-phy.c
+@@ -196,7 +196,7 @@ static int rcar_usb_phy_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit rcar_usb_phy_remove(struct platform_device *pdev)
++static int rcar_usb_phy_remove(struct platform_device *pdev)
+ {
+ 	struct rcar_usb_phy_priv *priv = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c
+index 2aa7c1a38ce3..38bce046f4d0 100644
+--- a/drivers/usb/renesas_usbhs/common.c
++++ b/drivers/usb/renesas_usbhs/common.c
+@@ -556,7 +556,7 @@ static int usbhs_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit usbhs_remove(struct platform_device *pdev)
++static int usbhs_remove(struct platform_device *pdev)
+ {
+ 	struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
+ 	struct renesas_usbhs_platform_info *info = pdev->dev.platform_data;

commit 2f82686e8c261d96d07bb1594d987cd6d5c64af6
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:25:20 2012 -0500
+
+    usb: remove use of __devinitconst
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitconst is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Li Yang 
+    Acked-by: Felipe Balbi 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
+index 8ad04a0b9e75..b13bc73f56b9 100644
+--- a/drivers/usb/gadget/fsl_qe_udc.c
++++ b/drivers/usb/gadget/fsl_qe_udc.c
+@@ -2710,7 +2710,7 @@ static int __devexit qe_udc_remove(struct platform_device *ofdev)
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+-static const struct of_device_id qe_udc_match[] __devinitconst = {
++static const struct of_device_id qe_udc_match[] = {
+ 	{
+ 		.compatible = "fsl,mpc8323-qe-usb",
+ 		.data = (void *)PORT_QE,
+diff --git a/drivers/usb/host/bcma-hcd.c b/drivers/usb/host/bcma-hcd.c
+index 8c83ed90acba..649780b480bc 100644
+--- a/drivers/usb/host/bcma-hcd.c
++++ b/drivers/usb/host/bcma-hcd.c
+@@ -305,7 +305,7 @@ static int bcma_hcd_resume(struct bcma_device *dev)
+ #define bcma_hcd_resume	NULL
+ #endif /* CONFIG_PM */
+ 
+-static const struct bcma_device_id bcma_hcd_table[] __devinitconst = {
++static const struct bcma_device_id bcma_hcd_table[] = {
+ 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS),
+ 	BCMA_CORETABLE_END
+ };
+diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
+index a018e706c0e1..15cfb06769e6 100644
+--- a/drivers/usb/host/pci-quirks.c
++++ b/drivers/usb/host/pci-quirks.c
+@@ -533,7 +533,7 @@ static void quirk_usb_handoff_ohci(struct pci_dev *pdev)
+ 	iounmap(base);
+ }
+ 
+-static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = {
++static const struct dmi_system_id ehci_dmi_nohandoff_table[] = {
+ 	{
+ 		/*  Pegatron Lucid (ExoPC) */
+ 		.matches = {
+diff --git a/drivers/usb/host/ssb-hcd.c b/drivers/usb/host/ssb-hcd.c
+index 79aa95832b26..bdb9d7055da9 100644
+--- a/drivers/usb/host/ssb-hcd.c
++++ b/drivers/usb/host/ssb-hcd.c
+@@ -248,7 +248,7 @@ static int ssb_hcd_resume(struct ssb_device *dev)
+ #define ssb_hcd_resume	NULL
+ #endif /* CONFIG_PM */
+ 
+-static const struct ssb_device_id ssb_hcd_table[] __devinitconst = {
++static const struct ssb_device_id ssb_hcd_table[] = {
+ 	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV),
+ 	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV),
+ 	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
+diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
+index f8affd7a30c0..605cd59d149c 100644
+--- a/drivers/usb/musb/musb_dsps.c
++++ b/drivers/usb/musb/musb_dsps.c
+@@ -716,7 +716,7 @@ static int dsps_resume(struct device *dev)
+ 
+ static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume);
+ 
+-static const struct dsps_musb_wrapper ti81xx_driver_data __devinitconst = {
++static const struct dsps_musb_wrapper ti81xx_driver_data = {
+ 	.revision		= 0x00,
+ 	.control		= 0x14,
+ 	.status			= 0x18,
+@@ -747,7 +747,7 @@ static const struct dsps_musb_wrapper ti81xx_driver_data __devinitconst = {
+ 	.instances		= 1,
+ };
+ 
+-static const struct platform_device_id musb_dsps_id_table[] __devinitconst = {
++static const struct platform_device_id musb_dsps_id_table[] = {
+ 	{
+ 		.name	= "musb-ti81xx",
+ 		.driver_data	= (kernel_ulong_t) &ti81xx_driver_data,
+@@ -757,7 +757,7 @@ static const struct platform_device_id musb_dsps_id_table[] __devinitconst = {
+ MODULE_DEVICE_TABLE(platform, musb_dsps_id_table);
+ 
+ #ifdef CONFIG_OF
+-static const struct of_device_id musb_dsps_of_match[] __devinitconst = {
++static const struct of_device_id musb_dsps_of_match[] = {
+ 	{ .compatible = "ti,musb-am33xx",
+ 		.data = (void *) &ti81xx_driver_data, },
+ 	{  },

commit d3608b6dafc570bb671c3338288eb2523f8cd52a
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:24:34 2012 -0500
+
+    usb: remove use of __devinitdata
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitdata is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Alexander Shishkin 
+    Acked-by: Felipe Balbi 
+    Cc: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/chipidea/ci13xxx_imx.c b/drivers/usb/chipidea/ci13xxx_imx.c
+index 424bff913527..126978038f7a 100644
+--- a/drivers/usb/chipidea/ci13xxx_imx.c
++++ b/drivers/usb/chipidea/ci13xxx_imx.c
+@@ -85,7 +85,7 @@ EXPORT_SYMBOL_GPL(usbmisc_get_init_data);
+ 
+ /* End of common functions shared by usbmisc drivers*/
+ 
+-static struct ci13xxx_platform_data ci13xxx_imx_platdata __devinitdata  = {
++static struct ci13xxx_platform_data ci13xxx_imx_platdata  = {
+ 	.name			= "ci13xxx_imx",
+ 	.flags			= CI13XXX_REQUIRE_TRANSCEIVER |
+ 				  CI13XXX_PULLUP_ON_VBUS |
+diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c
+index f0103dd2a102..a20acc14e694 100644
+--- a/drivers/usb/gadget/net2272.c
++++ b/drivers/usb/gadget/net2272.c
+@@ -2548,7 +2548,7 @@ net2272_pci_remove(struct pci_dev *pdev)
+ }
+ 
+ /* Table of matching PCI IDs */
+-static struct pci_device_id __devinitdata pci_ids[] = {
++static struct pci_device_id pci_ids[] = {
+ 	{	/* RDK 1 card */
+ 		.class       = ((PCI_CLASS_BRIDGE_OTHER << 8) | 0xfe),
+ 		.class_mask  = 0,
+diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c
+index 3fadff8f8d30..466c1bb5b967 100644
+--- a/drivers/usb/host/ehci-spear.c
++++ b/drivers/usb/host/ehci-spear.c
+@@ -199,7 +199,7 @@ static int spear_ehci_hcd_drv_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static struct of_device_id spear_ehci_id_table[] __devinitdata = {
++static struct of_device_id spear_ehci_id_table[] = {
+ 	{ .compatible = "st,spear600-ehci", },
+ 	{ },
+ };
+diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
+index ef0a6ef7875b..acf17556bd87 100644
+--- a/drivers/usb/host/ehci-tegra.c
++++ b/drivers/usb/host/ehci-tegra.c
+@@ -805,7 +805,7 @@ static void tegra_ehci_hcd_shutdown(struct platform_device *pdev)
+ 		hcd->driver->shutdown(hcd);
+ }
+ 
+-static struct of_device_id tegra_ehci_of_match[] __devinitdata = {
++static struct of_device_id tegra_ehci_of_match[] = {
+ 	{ .compatible = "nvidia,tegra20-ehci", },
+ 	{ },
+ };
+diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
+index dc0aeba35c9b..5faf796fc6ca 100644
+--- a/drivers/usb/host/fsl-mph-dr-of.c
++++ b/drivers/usb/host/fsl-mph-dr-of.c
+@@ -24,7 +24,7 @@ struct fsl_usb2_dev_data {
+ 	enum fsl_usb2_operating_modes op_mode;	/* operating mode */
+ };
+ 
+-struct fsl_usb2_dev_data dr_mode_data[] __devinitdata = {
++struct fsl_usb2_dev_data dr_mode_data[] = {
+ 	{
+ 		.dr_mode = "host",
+ 		.drivers = { "fsl-ehci", NULL, NULL, },
+diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c
+index b7fc2fc56c84..9020bf0e2eca 100644
+--- a/drivers/usb/host/ohci-spear.c
++++ b/drivers/usb/host/ohci-spear.c
+@@ -216,7 +216,7 @@ static int spear_ohci_hcd_drv_resume(struct platform_device *dev)
+ }
+ #endif
+ 
+-static struct of_device_id spear_ohci_id_table[] __devinitdata = {
++static struct of_device_id spear_ohci_id_table[] = {
+ 	{ .compatible = "st,spear600-ohci", },
+ 	{ },
+ };
+diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
+index f17a3e79dbec..a332bb81aa38 100644
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -1040,12 +1040,12 @@ static void musb_shutdown(struct platform_device *pdev)
+ 	|| defined(CONFIG_USB_MUSB_AM35X_MODULE)	\
+ 	|| defined(CONFIG_USB_MUSB_DSPS)		\
+ 	|| defined(CONFIG_USB_MUSB_DSPS_MODULE)
+-static ushort __devinitdata fifo_mode = 4;
++static ushort fifo_mode = 4;
+ #elif defined(CONFIG_USB_MUSB_UX500)			\
+ 	|| defined(CONFIG_USB_MUSB_UX500_MODULE)
+-static ushort __devinitdata fifo_mode = 5;
++static ushort fifo_mode = 5;
+ #else
+-static ushort __devinitdata fifo_mode = 2;
++static ushort fifo_mode = 2;
+ #endif
+ 
+ /* "modprobe ... fifo_mode=1" etc */
+@@ -1058,7 +1058,7 @@ MODULE_PARM_DESC(fifo_mode, "initial endpoint configuration");
+  */
+ 
+ /* mode 0 - fits in 2KB */
+-static struct musb_fifo_cfg __devinitdata mode_0_cfg[] = {
++static struct musb_fifo_cfg mode_0_cfg[] = {
+ { .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, },
+ { .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, },
+ { .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, },
+@@ -1067,7 +1067,7 @@ static struct musb_fifo_cfg __devinitdata mode_0_cfg[] = {
+ };
+ 
+ /* mode 1 - fits in 4KB */
+-static struct musb_fifo_cfg __devinitdata mode_1_cfg[] = {
++static struct musb_fifo_cfg mode_1_cfg[] = {
+ { .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
+ { .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
+ { .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, .mode = BUF_DOUBLE, },
+@@ -1076,7 +1076,7 @@ static struct musb_fifo_cfg __devinitdata mode_1_cfg[] = {
+ };
+ 
+ /* mode 2 - fits in 4KB */
+-static struct musb_fifo_cfg __devinitdata mode_2_cfg[] = {
++static struct musb_fifo_cfg mode_2_cfg[] = {
+ { .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, },
+ { .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, },
+ { .hw_ep_num = 2, .style = FIFO_TX,   .maxpacket = 512, },
+@@ -1086,7 +1086,7 @@ static struct musb_fifo_cfg __devinitdata mode_2_cfg[] = {
+ };
+ 
+ /* mode 3 - fits in 4KB */
+-static struct musb_fifo_cfg __devinitdata mode_3_cfg[] = {
++static struct musb_fifo_cfg mode_3_cfg[] = {
+ { .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
+ { .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
+ { .hw_ep_num = 2, .style = FIFO_TX,   .maxpacket = 512, },
+@@ -1096,7 +1096,7 @@ static struct musb_fifo_cfg __devinitdata mode_3_cfg[] = {
+ };
+ 
+ /* mode 4 - fits in 16KB */
+-static struct musb_fifo_cfg __devinitdata mode_4_cfg[] = {
++static struct musb_fifo_cfg mode_4_cfg[] = {
+ { .hw_ep_num =  1, .style = FIFO_TX,   .maxpacket = 512, },
+ { .hw_ep_num =  1, .style = FIFO_RX,   .maxpacket = 512, },
+ { .hw_ep_num =  2, .style = FIFO_TX,   .maxpacket = 512, },
+@@ -1127,7 +1127,7 @@ static struct musb_fifo_cfg __devinitdata mode_4_cfg[] = {
+ };
+ 
+ /* mode 5 - fits in 8KB */
+-static struct musb_fifo_cfg __devinitdata mode_5_cfg[] = {
++static struct musb_fifo_cfg mode_5_cfg[] = {
+ { .hw_ep_num =  1, .style = FIFO_TX,   .maxpacket = 512, },
+ { .hw_ep_num =  1, .style = FIFO_RX,   .maxpacket = 512, },
+ { .hw_ep_num =  2, .style = FIFO_TX,   .maxpacket = 512, },
+@@ -1234,7 +1234,7 @@ fifo_setup(struct musb *musb, struct musb_hw_ep  *hw_ep,
+ 	return offset + (maxpacket << ((c_size & MUSB_FIFOSZ_DPB) ? 1 : 0));
+ }
+ 
+-static struct musb_fifo_cfg __devinitdata ep0_cfg = {
++static struct musb_fifo_cfg ep0_cfg = {
+ 	.style = FIFO_RXTX, .maxpacket = 64,
+ };
+ 
+@@ -1578,7 +1578,7 @@ irqreturn_t musb_interrupt(struct musb *musb)
+ EXPORT_SYMBOL_GPL(musb_interrupt);
+ 
+ #ifndef CONFIG_MUSB_PIO_ONLY
+-static bool __devinitdata use_dma = 1;
++static bool use_dma = 1;
+ 
+ /* "modprobe ... use_dma=0" etc */
+ module_param(use_dma, bool, 0);

commit 41ac7b3ab7fe1d6175839947a877fdf95cbd2211
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:48 2012 -0500
+
+    usb: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Peter Korsgaard 
+    Cc: Alexander Shishkin 
+    Acked-by: Felipe Balbi 
+    Cc: Li Yang 
+    Acked-by: Alan Stern 
+    Cc: Geoff Levand 
+    Cc: Wan ZongShun 
+    Cc: Olav Kongas 
+    Cc: Lennert Buytenhek 
+    Cc: Ben Dooks 
+    Cc: Kukjin Kim 
+    Acked-by: Nicolas Ferre 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/c67x00/c67x00-drv.c b/drivers/usb/c67x00/c67x00-drv.c
+index 855d538752c4..21913dfeecce 100644
+--- a/drivers/usb/c67x00/c67x00-drv.c
++++ b/drivers/usb/c67x00/c67x00-drv.c
+@@ -116,7 +116,7 @@ static irqreturn_t c67x00_irq(int irq, void *__dev)
+ 
+ /* ------------------------------------------------------------------------- */
+ 
+-static int __devinit c67x00_drv_probe(struct platform_device *pdev)
++static int c67x00_drv_probe(struct platform_device *pdev)
+ {
+ 	struct c67x00_device *c67x00;
+ 	struct c67x00_platform_data *pdata;
+diff --git a/drivers/usb/chipidea/ci13xxx_imx.c b/drivers/usb/chipidea/ci13xxx_imx.c
+index 565973035ca8..424bff913527 100644
+--- a/drivers/usb/chipidea/ci13xxx_imx.c
++++ b/drivers/usb/chipidea/ci13xxx_imx.c
+@@ -93,7 +93,7 @@ static struct ci13xxx_platform_data ci13xxx_imx_platdata __devinitdata  = {
+ 	.capoffset		= DEF_CAPOFFSET,
+ };
+ 
+-static int __devinit ci13xxx_imx_probe(struct platform_device *pdev)
++static int ci13xxx_imx_probe(struct platform_device *pdev)
+ {
+ 	struct ci13xxx_imx_data *data;
+ 	struct platform_device *plat_ci, *phy_pdev;
+diff --git a/drivers/usb/chipidea/ci13xxx_msm.c b/drivers/usb/chipidea/ci13xxx_msm.c
+index 406c5af2da5c..e8a8ba36b101 100644
+--- a/drivers/usb/chipidea/ci13xxx_msm.c
++++ b/drivers/usb/chipidea/ci13xxx_msm.c
+@@ -55,7 +55,7 @@ static struct ci13xxx_platform_data ci13xxx_msm_platdata = {
+ 	.notify_event		= ci13xxx_msm_notify_event,
+ };
+ 
+-static int __devinit ci13xxx_msm_probe(struct platform_device *pdev)
++static int ci13xxx_msm_probe(struct platform_device *pdev)
+ {
+ 	struct platform_device *plat_ci;
+ 
+diff --git a/drivers/usb/chipidea/ci13xxx_pci.c b/drivers/usb/chipidea/ci13xxx_pci.c
+index e1cb2fb2ef33..cb7eb3ede5e8 100644
+--- a/drivers/usb/chipidea/ci13xxx_pci.c
++++ b/drivers/usb/chipidea/ci13xxx_pci.c
+@@ -48,7 +48,7 @@ struct ci13xxx_platform_data penwell_pci_platdata = {
+  * Allocates basic PCI resources for this USB device controller, and then
+  * invokes the udc_probe() method to start the UDC associated with it
+  */
+-static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev,
++static int ci13xxx_pci_probe(struct pci_dev *pdev,
+ 				       const struct pci_device_id *id)
+ {
+ 	struct ci13xxx_platform_data *platdata = (void *)id->driver_data;
+diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
+index 46f23f226ae2..7f9c0d21c897 100644
+--- a/drivers/usb/chipidea/core.c
++++ b/drivers/usb/chipidea/core.c
+@@ -390,7 +390,7 @@ void ci13xxx_remove_device(struct platform_device *pdev)
+ }
+ EXPORT_SYMBOL_GPL(ci13xxx_remove_device);
+ 
+-static int __devinit ci_hdrc_probe(struct platform_device *pdev)
++static int ci_hdrc_probe(struct platform_device *pdev)
+ {
+ 	struct device	*dev = &pdev->dev;
+ 	struct ci13xxx	*ci;
+diff --git a/drivers/usb/chipidea/usbmisc_imx6q.c b/drivers/usb/chipidea/usbmisc_imx6q.c
+index 81238a467296..ee6fa872f936 100644
+--- a/drivers/usb/chipidea/usbmisc_imx6q.c
++++ b/drivers/usb/chipidea/usbmisc_imx6q.c
+@@ -82,7 +82,7 @@ static const struct of_device_id usbmisc_imx6q_dt_ids[] = {
+ 	{ /* sentinel */ }
+ };
+ 
+-static int __devinit usbmisc_imx6q_probe(struct platform_device *pdev)
++static int usbmisc_imx6q_probe(struct platform_device *pdev)
+ {
+ 	struct resource	*res;
+ 	struct imx6q_usbmisc *data;
+diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
+index cc5dac11d305..71610800cd88 100644
+--- a/drivers/usb/dwc3/core.c
++++ b/drivers/usb/dwc3/core.c
+@@ -140,8 +140,7 @@ static void dwc3_free_one_event_buffer(struct dwc3 *dwc,
+  * Returns a pointer to the allocated event buffer structure on success
+  * otherwise ERR_PTR(errno).
+  */
+-static struct dwc3_event_buffer *__devinit
+-dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length)
++static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length)
+ {
+ 	struct dwc3_event_buffer	*evt;
+ 
+@@ -183,7 +182,7 @@ static void dwc3_free_event_buffers(struct dwc3 *dwc)
+  * Returns 0 on success otherwise negative errno. In the error case, dwc
+  * may contain some buffers allocated but not all which were requested.
+  */
+-static int __devinit dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
++static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
+ {
+ 	int			num;
+ 	int			i;
+@@ -260,7 +259,7 @@ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
+ 	}
+ }
+ 
+-static void __devinit dwc3_cache_hwparams(struct dwc3 *dwc)
++static void dwc3_cache_hwparams(struct dwc3 *dwc)
+ {
+ 	struct dwc3_hwparams	*parms = &dwc->hwparams;
+ 
+@@ -281,7 +280,7 @@ static void __devinit dwc3_cache_hwparams(struct dwc3 *dwc)
+  *
+  * Returns 0 on success otherwise negative errno.
+  */
+-static int __devinit dwc3_core_init(struct dwc3 *dwc)
++static int dwc3_core_init(struct dwc3 *dwc)
+ {
+ 	unsigned long		timeout;
+ 	u32			reg;
+@@ -360,7 +359,7 @@ static void dwc3_core_exit(struct dwc3 *dwc)
+ 
+ #define DWC3_ALIGN_MASK		(16 - 1)
+ 
+-static int __devinit dwc3_probe(struct platform_device *pdev)
++static int dwc3_probe(struct platform_device *pdev)
+ {
+ 	struct device_node	*node = pdev->dev.of_node;
+ 	struct resource		*res;
+diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c
+index d4a30f118724..33ae98c52781 100644
+--- a/drivers/usb/dwc3/debugfs.c
++++ b/drivers/usb/dwc3/debugfs.c
+@@ -652,7 +652,7 @@ static const struct file_operations dwc3_link_state_fops = {
+ 	.release		= single_release,
+ };
+ 
+-int __devinit dwc3_debugfs_init(struct dwc3 *dwc)
++int dwc3_debugfs_init(struct dwc3 *dwc)
+ {
+ 	struct dentry		*root;
+ 	struct dentry		*file;
+diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
+index 19a98184e580..d43f0760ca63 100644
+--- a/drivers/usb/dwc3/dwc3-exynos.c
++++ b/drivers/usb/dwc3/dwc3-exynos.c
+@@ -34,7 +34,7 @@ struct dwc3_exynos {
+ 	struct clk		*clk;
+ };
+ 
+-static int __devinit dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
++static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
+ {
+ 	struct nop_usb_xceiv_platform_data pdata;
+ 	struct platform_device	*pdev;
+@@ -90,7 +90,7 @@ static int __devinit dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
+ 
+ static u64 dwc3_exynos_dma_mask = DMA_BIT_MASK(32);
+ 
+-static int __devinit dwc3_exynos_probe(struct platform_device *pdev)
++static int dwc3_exynos_probe(struct platform_device *pdev)
+ {
+ 	struct platform_device	*dwc3;
+ 	struct dwc3_exynos	*exynos;
+diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
+index afbc6e99188c..e114bb58ccf4 100644
+--- a/drivers/usb/dwc3/dwc3-omap.c
++++ b/drivers/usb/dwc3/dwc3-omap.c
+@@ -157,7 +157,7 @@ static inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value)
+ 	writel(value, base + offset);
+ }
+ 
+-static int __devinit dwc3_omap_register_phys(struct dwc3_omap *omap)
++static int dwc3_omap_register_phys(struct dwc3_omap *omap)
+ {
+ 	struct nop_usb_xceiv_platform_data pdata;
+ 	struct platform_device	*pdev;
+@@ -262,7 +262,7 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int __devinit dwc3_omap_probe(struct platform_device *pdev)
++static int dwc3_omap_probe(struct platform_device *pdev)
+ {
+ 	struct dwc3_omap_data	*pdata = pdev->dev.platform_data;
+ 	struct device_node	*node = pdev->dev.of_node;
+diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
+index b3eeec7c6bc8..68e389b589d6 100644
+--- a/drivers/usb/dwc3/dwc3-pci.c
++++ b/drivers/usb/dwc3/dwc3-pci.c
+@@ -58,7 +58,7 @@ struct dwc3_pci {
+ 	struct platform_device	*usb3_phy;
+ };
+ 
+-static int __devinit dwc3_pci_register_phys(struct dwc3_pci *glue)
++static int dwc3_pci_register_phys(struct dwc3_pci *glue)
+ {
+ 	struct nop_usb_xceiv_platform_data pdata;
+ 	struct platform_device	*pdev;
+@@ -112,7 +112,7 @@ static int __devinit dwc3_pci_register_phys(struct dwc3_pci *glue)
+ 	return ret;
+ }
+ 
+-static int __devinit dwc3_pci_probe(struct pci_dev *pci,
++static int dwc3_pci_probe(struct pci_dev *pci,
+ 		const struct pci_device_id *id)
+ {
+ 	struct resource		res[2];
+diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
+index 7b7deddf6a52..2e43b332aae8 100644
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -1579,7 +1579,7 @@ static const struct usb_gadget_ops dwc3_gadget_ops = {
+ 
+ /* -------------------------------------------------------------------------- */
+ 
+-static int __devinit dwc3_gadget_init_endpoints(struct dwc3 *dwc)
++static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
+ {
+ 	struct dwc3_ep			*dep;
+ 	u8				epnum;
+@@ -2374,7 +2374,7 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
+  *
+  * Returns 0 on success otherwise negative errno.
+  */
+-int __devinit dwc3_gadget_init(struct dwc3 *dwc)
++int dwc3_gadget_init(struct dwc3 *dwc)
+ {
+ 	u32					reg;
+ 	int					ret;
+diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
+index 89d90b5fb787..e6135faabc3a 100644
+--- a/drivers/usb/gadget/at91_udc.c
++++ b/drivers/usb/gadget/at91_udc.c
+@@ -1673,7 +1673,7 @@ static void at91udc_shutdown(struct platform_device *dev)
+ 	spin_unlock_irqrestore(&udc->lock, flags);
+ }
+ 
+-static void __devinit at91udc_of_init(struct at91_udc *udc,
++static void at91udc_of_init(struct at91_udc *udc,
+ 				     struct device_node *np)
+ {
+ 	struct at91_udc_data *board = &udc->board;
+@@ -1693,7 +1693,7 @@ static void __devinit at91udc_of_init(struct at91_udc *udc,
+ 	board->pullup_active_low = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0;
+ }
+ 
+-static int __devinit at91udc_probe(struct platform_device *pdev)
++static int at91udc_probe(struct platform_device *pdev)
+ {
+ 	struct device	*dev = &pdev->dev;
+ 	struct at91_udc	*udc;
+diff --git a/drivers/usb/gadget/bcm63xx_udc.c b/drivers/usb/gadget/bcm63xx_udc.c
+index b44e43641d59..18eff74e3360 100644
+--- a/drivers/usb/gadget/bcm63xx_udc.c
++++ b/drivers/usb/gadget/bcm63xx_udc.c
+@@ -2323,7 +2323,7 @@ static void bcm63xx_udc_gadget_release(struct device *dev)
+  * Note that platform data is required, because pd.port_no varies from chip
+  * to chip and is used to switch the correct USB port to device mode.
+  */
+-static int __devinit bcm63xx_udc_probe(struct platform_device *pdev)
++static int bcm63xx_udc_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	struct bcm63xx_usbd_platform_data *pd = dev->platform_data;
+diff --git a/drivers/usb/gadget/f_uac2.c b/drivers/usb/gadget/f_uac2.c
+index 91396a1683eb..d7da258fa3f6 100644
+--- a/drivers/usb/gadget/f_uac2.c
++++ b/drivers/usb/gadget/f_uac2.c
+@@ -402,7 +402,7 @@ static struct snd_pcm_ops uac2_pcm_ops = {
+ 	.prepare = uac2_pcm_null,
+ };
+ 
+-static int __devinit snd_uac2_probe(struct platform_device *pdev)
++static int snd_uac2_probe(struct platform_device *pdev)
+ {
+ 	struct snd_uac2_chip *uac2 = pdev_to_uac2(pdev);
+ 	struct snd_card *card;
+diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
+index 21db1f71d4ce..8ad04a0b9e75 100644
+--- a/drivers/usb/gadget/fsl_qe_udc.c
++++ b/drivers/usb/gadget/fsl_qe_udc.c
+@@ -2347,7 +2347,7 @@ static int fsl_qe_stop(struct usb_gadget *gadget,
+ }
+ 
+ /* udc structure's alloc and setup, include ep-param alloc */
+-static struct qe_udc __devinit *qe_udc_config(struct platform_device *ofdev)
++static struct qe_udc *qe_udc_config(struct platform_device *ofdev)
+ {
+ 	struct qe_udc *udc;
+ 	struct device_node *np = ofdev->dev.of_node;
+@@ -2402,7 +2402,7 @@ static struct qe_udc __devinit *qe_udc_config(struct platform_device *ofdev)
+ }
+ 
+ /* USB Controller register init */
+-static int __devinit qe_udc_reg_init(struct qe_udc *udc)
++static int qe_udc_reg_init(struct qe_udc *udc)
+ {
+ 	struct usb_ctlr __iomem *qe_usbregs;
+ 	qe_usbregs = udc->usb_regs;
+@@ -2420,7 +2420,7 @@ static int __devinit qe_udc_reg_init(struct qe_udc *udc)
+ 	return 0;
+ }
+ 
+-static int __devinit qe_ep_config(struct qe_udc *udc, unsigned char pipe_num)
++static int qe_ep_config(struct qe_udc *udc, unsigned char pipe_num)
+ {
+ 	struct qe_ep *ep = &udc->eps[pipe_num];
+ 
+@@ -2473,7 +2473,7 @@ static void qe_udc_release(struct device *dev)
+ 
+ /* Driver probe functions */
+ static const struct of_device_id qe_udc_match[];
+-static int __devinit qe_udc_probe(struct platform_device *ofdev)
++static int qe_udc_probe(struct platform_device *ofdev)
+ {
+ 	struct qe_udc *udc;
+ 	const struct of_device_id *match;
+diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c
+index ea45224f78c8..24196492ae20 100644
+--- a/drivers/usb/gadget/mv_udc_core.c
++++ b/drivers/usb/gadget/mv_udc_core.c
+@@ -2188,7 +2188,7 @@ static int __devexit mv_udc_remove(struct platform_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devinit mv_udc_probe(struct platform_device *dev)
++static int mv_udc_probe(struct platform_device *dev)
+ {
+ 	struct mv_usb_platform_data *pdata = dev->dev.platform_data;
+ 	struct mv_udc *udc;
+diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c
+index 26c305321c40..f0103dd2a102 100644
+--- a/drivers/usb/gadget/net2272.c
++++ b/drivers/usb/gadget/net2272.c
+@@ -2215,8 +2215,7 @@ net2272_remove(struct net2272 *dev)
+ 	dev_info(dev->dev, "unbind\n");
+ }
+ 
+-static struct net2272 * __devinit
+-net2272_probe_init(struct device *dev, unsigned int irq)
++static struct net2272 *net2272_probe_init(struct device *dev, unsigned int irq)
+ {
+ 	struct net2272 *ret;
+ 
+@@ -2246,7 +2245,7 @@ net2272_probe_init(struct device *dev, unsigned int irq)
+ 	return ret;
+ }
+ 
+-static int __devinit
++static int
+ net2272_probe_fin(struct net2272 *dev, unsigned int irqflags)
+ {
+ 	int ret;
+@@ -2306,7 +2305,7 @@ net2272_probe_fin(struct net2272 *dev, unsigned int irqflags)
+  * don't respond over USB until a gadget driver binds to us
+  */
+ 
+-static int __devinit
++static int
+ net2272_rdk1_probe(struct pci_dev *pdev, struct net2272 *dev)
+ {
+ 	unsigned long resource, len, tmp;
+@@ -2389,7 +2388,7 @@ net2272_rdk1_probe(struct pci_dev *pdev, struct net2272 *dev)
+ 	return ret;
+ }
+ 
+-static int __devinit
++static int
+ net2272_rdk2_probe(struct pci_dev *pdev, struct net2272 *dev)
+ {
+ 	unsigned long resource, len;
+@@ -2447,7 +2446,7 @@ net2272_rdk2_probe(struct pci_dev *pdev, struct net2272 *dev)
+ 	return ret;
+ }
+ 
+-static int __devinit
++static int
+ net2272_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ 	struct net2272 *dev;
+@@ -2595,7 +2594,7 @@ static inline void net2272_pci_unregister(void) { }
+ 
+ /*---------------------------------------------------------------------------*/
+ 
+-static int __devinit
++static int
+ net2272_plat_probe(struct platform_device *pdev)
+ {
+ 	struct net2272 *dev;
+diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
+index b5605ddfbd63..cbc07c117af0 100644
+--- a/drivers/usb/gadget/omap_udc.c
++++ b/drivers/usb/gadget/omap_udc.c
+@@ -2506,7 +2506,7 @@ static inline void remove_proc_file(void) {}
+  * UDC_SYSCON_1.CFG_LOCK is set can now work.  We won't use that
+  * capability yet though.
+  */
+-static unsigned __devinit
++static unsigned
+ omap_ep_setup(char *name, u8 addr, u8 type,
+ 		unsigned buf, unsigned maxp, int dbuf)
+ {
+@@ -2624,7 +2624,7 @@ static void omap_udc_release(struct device *dev)
+ 	udc = NULL;
+ }
+ 
+-static int __devinit
++static int
+ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)
+ {
+ 	unsigned	tmp, buf;
+@@ -2761,7 +2761,7 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)
+ 	return 0;
+ }
+ 
+-static int __devinit omap_udc_probe(struct platform_device *pdev)
++static int omap_udc_probe(struct platform_device *pdev)
+ {
+ 	int			status = -ENODEV;
+ 	int			hmc;
+diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
+index 9fd6e5fdc350..6fdb1bd98e98 100644
+--- a/drivers/usb/gadget/s3c-hsotg.c
++++ b/drivers/usb/gadget/s3c-hsotg.c
+@@ -3072,7 +3072,7 @@ static struct usb_gadget_ops s3c_hsotg_gadget_ops = {
+  * creation) to give to the gadget driver. Setup the endpoint name, any
+  * direction information and other state that may be required.
+  */
+-static void __devinit s3c_hsotg_initep(struct s3c_hsotg *hsotg,
++static void s3c_hsotg_initep(struct s3c_hsotg *hsotg,
+ 				       struct s3c_hsotg_ep *hs_ep,
+ 				       int epnum)
+ {
+@@ -3414,7 +3414,7 @@ static const struct file_operations ep_fops = {
+  * with the same name as the device itself, in case we end up
+  * with multiple blocks in future systems.
+  */
+-static void __devinit s3c_hsotg_create_debug(struct s3c_hsotg *hsotg)
++static void s3c_hsotg_create_debug(struct s3c_hsotg *hsotg)
+ {
+ 	struct dentry *root;
+ 	unsigned epidx;
+@@ -3490,7 +3490,7 @@ static void s3c_hsotg_release(struct device *dev)
+  * @pdev: The platform information for the driver
+  */
+ 
+-static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
++static int s3c_hsotg_probe(struct platform_device *pdev)
+ {
+ 	struct s3c_hsotg_plat *plat = pdev->dev.platform_data;
+ 	struct device *dev = &pdev->dev;
+diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c
+index d8e785d4ad59..52379b11f080 100644
+--- a/drivers/usb/gadget/s3c-hsudc.c
++++ b/drivers/usb/gadget/s3c-hsudc.c
+@@ -1261,7 +1261,7 @@ static struct usb_gadget_ops s3c_hsudc_gadget_ops = {
+ 	.vbus_draw	= s3c_hsudc_vbus_draw,
+ };
+ 
+-static int __devinit s3c_hsudc_probe(struct platform_device *pdev)
++static int s3c_hsudc_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	struct resource *res;
+diff --git a/drivers/usb/host/bcma-hcd.c b/drivers/usb/host/bcma-hcd.c
+index f5143a066add..8c83ed90acba 100644
+--- a/drivers/usb/host/bcma-hcd.c
++++ b/drivers/usb/host/bcma-hcd.c
+@@ -54,7 +54,7 @@ static int bcma_wait_bits(struct bcma_device *dev, u16 reg, u32 bitmask,
+ 	return -ETIMEDOUT;
+ }
+ 
+-static void __devinit bcma_hcd_4716wa(struct bcma_device *dev)
++static void bcma_hcd_4716wa(struct bcma_device *dev)
+ {
+ #ifdef CONFIG_BCMA_DRIVER_MIPS
+ 	/* Work around for 4716 failures. */
+@@ -88,7 +88,7 @@ static void __devinit bcma_hcd_4716wa(struct bcma_device *dev)
+ }
+ 
+ /* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */
+-static void __devinit bcma_hcd_init_chip(struct bcma_device *dev)
++static void bcma_hcd_init_chip(struct bcma_device *dev)
+ {
+ 	u32 tmp;
+ 
+@@ -165,8 +165,7 @@ static const struct usb_ehci_pdata ehci_pdata = {
+ static const struct usb_ohci_pdata ohci_pdata = {
+ };
+ 
+-static struct platform_device * __devinit
+-bcma_hcd_create_pdev(struct bcma_device *dev, bool ohci, u32 addr)
++static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev, bool ohci, u32 addr)
+ {
+ 	struct platform_device *hci_dev;
+ 	struct resource hci_res[2];
+@@ -212,7 +211,7 @@ bcma_hcd_create_pdev(struct bcma_device *dev, bool ohci, u32 addr)
+ 	return ERR_PTR(ret);
+ }
+ 
+-static int __devinit bcma_hcd_probe(struct bcma_device *dev)
++static int bcma_hcd_probe(struct bcma_device *dev)
+ {
+ 	int err;
+ 	u16 chipid_top;
+diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
+index 33f798ec1c7d..96bf00d32614 100644
+--- a/drivers/usb/host/ehci-atmel.c
++++ b/drivers/usb/host/ehci-atmel.c
+@@ -97,7 +97,7 @@ static const struct hc_driver ehci_atmel_hc_driver = {
+ 
+ static u64 at91_ehci_dma_mask = DMA_BIT_MASK(32);
+ 
+-static int __devinit ehci_atmel_drv_probe(struct platform_device *pdev)
++static int ehci_atmel_drv_probe(struct platform_device *pdev)
+ {
+ 	struct usb_hcd *hcd;
+ 	const struct hc_driver *driver = &ehci_atmel_hc_driver;
+diff --git a/drivers/usb/host/ehci-grlib.c b/drivers/usb/host/ehci-grlib.c
+index da4269550fba..1fc89292f5d6 100644
+--- a/drivers/usb/host/ehci-grlib.c
++++ b/drivers/usb/host/ehci-grlib.c
+@@ -82,7 +82,7 @@ static const struct hc_driver ehci_grlib_hc_driver = {
+ };
+ 
+ 
+-static int __devinit ehci_hcd_grlib_probe(struct platform_device *op)
++static int ehci_hcd_grlib_probe(struct platform_device *op)
+ {
+ 	struct device_node *dn = op->dev.of_node;
+ 	struct usb_hcd *hcd;
+diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
+index 96da679becef..f74794c93152 100644
+--- a/drivers/usb/host/ehci-orion.c
++++ b/drivers/usb/host/ehci-orion.c
+@@ -146,7 +146,7 @@ static const struct hc_driver ehci_orion_hc_driver = {
+ 	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+ };
+ 
+-static void __devinit
++static void
+ ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,
+ 			     const struct mbus_dram_target_info *dram)
+ {
+@@ -167,7 +167,7 @@ ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,
+ 	}
+ }
+ 
+-static int __devinit ehci_orion_drv_probe(struct platform_device *pdev)
++static int ehci_orion_drv_probe(struct platform_device *pdev)
+ {
+ 	struct orion_ehci_data *pd = pdev->dev.platform_data;
+ 	const struct mbus_dram_target_info *dram;
+diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
+index b807648876be..615cba016a6f 100644
+--- a/drivers/usb/host/ehci-platform.c
++++ b/drivers/usb/host/ehci-platform.c
+@@ -61,7 +61,7 @@ static const struct ehci_driver_overrides platform_overrides __initdata = {
+ 	.reset =	ehci_platform_reset,
+ };
+ 
+-static int __devinit ehci_platform_probe(struct platform_device *dev)
++static int ehci_platform_probe(struct platform_device *dev)
+ {
+ 	struct usb_hcd *hcd;
+ 	struct resource *res_mem;
+diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c
+index fa937d05a02b..45aceefd0c2b 100644
+--- a/drivers/usb/host/ehci-ppc-of.c
++++ b/drivers/usb/host/ehci-ppc-of.c
+@@ -71,7 +71,7 @@ static const struct hc_driver ehci_ppc_of_hc_driver = {
+  * Fix: Enable Break Memory Transfer (BMT) in INSNREG3
+  */
+ #define PPC440EPX_EHCI0_INSREG_BMT	(0x1 << 0)
+-static int __devinit
++static int
+ ppc44x_enable_bmt(struct device_node *dn)
+ {
+ 	__iomem u32 *insreg_virt;
+@@ -87,7 +87,7 @@ ppc44x_enable_bmt(struct device_node *dn)
+ }
+ 
+ 
+-static int __devinit ehci_hcd_ppc_of_probe(struct platform_device *op)
++static int ehci_hcd_ppc_of_probe(struct platform_device *op)
+ {
+ 	struct device_node *dn = op->dev.of_node;
+ 	struct usb_hcd *hcd;
+diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
+index 45a356e9f138..df5925a4f0db 100644
+--- a/drivers/usb/host/ehci-ps3.c
++++ b/drivers/usb/host/ehci-ps3.c
+@@ -93,7 +93,7 @@ static const struct hc_driver ps3_ehci_hc_driver = {
+ 	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
+ };
+ 
+-static int __devinit ps3_ehci_probe(struct ps3_system_bus_device *dev)
++static int ps3_ehci_probe(struct ps3_system_bus_device *dev)
+ {
+ 	int result;
+ 	struct usb_hcd *hcd;
+diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c
+index f90a8815f4a8..2cf19d1ab4bf 100644
+--- a/drivers/usb/host/ehci-s5p.c
++++ b/drivers/usb/host/ehci-s5p.c
+@@ -85,7 +85,7 @@ static void s5p_setup_vbus_gpio(struct platform_device *pdev)
+ 
+ static u64 ehci_s5p_dma_mask = DMA_BIT_MASK(32);
+ 
+-static int __devinit s5p_ehci_probe(struct platform_device *pdev)
++static int s5p_ehci_probe(struct platform_device *pdev)
+ {
+ 	struct s5p_ehci_platdata *pdata;
+ 	struct s5p_ehci_hcd *s5p_ehci;
+diff --git a/drivers/usb/host/ehci-w90x900.c b/drivers/usb/host/ehci-w90x900.c
+index 7bcb8b2863de..bf8d462c26ac 100644
+--- a/drivers/usb/host/ehci-w90x900.c
++++ b/drivers/usb/host/ehci-w90x900.c
+@@ -18,7 +18,7 @@
+ #define PHY0_CTR	(0xA4)
+ #define PHY1_CTR	(0xA8)
+ 
+-static int __devinit usb_w90x900_probe(const struct hc_driver *driver,
++static int usb_w90x900_probe(const struct hc_driver *driver,
+ 		      struct platform_device *pdev)
+ {
+ 	struct usb_hcd *hcd;
+@@ -147,7 +147,7 @@ static const struct hc_driver ehci_w90x900_hc_driver = {
+ 	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+ };
+ 
+-static int __devinit ehci_w90x900_probe(struct platform_device *pdev)
++static int ehci_w90x900_probe(struct platform_device *pdev)
+ {
+ 	if (usb_disabled())
+ 		return -ENODEV;
+diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c
+index 6a3f921a5d76..4f285e8e404a 100644
+--- a/drivers/usb/host/ehci-xilinx-of.c
++++ b/drivers/usb/host/ehci-xilinx-of.c
+@@ -125,7 +125,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = {
+  * as HS only or HS/FS only, it checks the configuration in the device tree
+  * entry, and sets an appropriate value for hcd->has_tt.
+  */
+-static int __devinit ehci_hcd_xilinx_of_probe(struct platform_device *op)
++static int ehci_hcd_xilinx_of_probe(struct platform_device *op)
+ {
+ 	struct device_node *dn = op->dev.of_node;
+ 	struct usb_hcd *hcd;
+diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c
+index 92f4b99a3ab2..618f143748a5 100644
+--- a/drivers/usb/host/fhci-hcd.c
++++ b/drivers/usb/host/fhci-hcd.c
+@@ -561,7 +561,7 @@ static const struct hc_driver fhci_driver = {
+ 	.hub_control = fhci_hub_control,
+ };
+ 
+-static int __devinit of_fhci_probe(struct platform_device *ofdev)
++static int of_fhci_probe(struct platform_device *ofdev)
+ {
+ 	struct device *dev = &ofdev->dev;
+ 	struct device_node *node = dev->of_node;
+diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
+index 3a5c82f67232..dc0aeba35c9b 100644
+--- a/drivers/usb/host/fsl-mph-dr-of.c
++++ b/drivers/usb/host/fsl-mph-dr-of.c
+@@ -42,7 +42,7 @@ struct fsl_usb2_dev_data dr_mode_data[] __devinitdata = {
+ 	},
+ };
+ 
+-struct fsl_usb2_dev_data * __devinit get_dr_mode_data(struct device_node *np)
++struct fsl_usb2_dev_data *get_dr_mode_data(struct device_node *np)
+ {
+ 	const unsigned char *prop;
+ 	int i;
+@@ -59,7 +59,7 @@ struct fsl_usb2_dev_data * __devinit get_dr_mode_data(struct device_node *np)
+ 	return &dr_mode_data[0]; /* mode not specified, use host */
+ }
+ 
+-static enum fsl_usb2_phy_modes __devinit determine_usb_phy(const char *phy_type)
++static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)
+ {
+ 	if (!phy_type)
+ 		return FSL_USB2_PHY_NONE;
+@@ -75,7 +75,7 @@ static enum fsl_usb2_phy_modes __devinit determine_usb_phy(const char *phy_type)
+ 	return FSL_USB2_PHY_NONE;
+ }
+ 
+-struct platform_device * __devinit fsl_usb2_device_register(
++struct platform_device *fsl_usb2_device_register(
+ 					struct platform_device *ofdev,
+ 					struct fsl_usb2_platform_data *pdata,
+ 					const char *name, int id)
+@@ -154,7 +154,7 @@ static int usb_get_ver_info(struct device_node *np)
+ 	return ver;
+ }
+ 
+-static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
++static int fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
+ {
+ 	struct device_node *np = ofdev->dev.of_node;
+ 	struct platform_device *usb_dev;
+diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c
+index f19e2690c232..bd6a7447ccc9 100644
+--- a/drivers/usb/host/imx21-hcd.c
++++ b/drivers/usb/host/imx21-hcd.c
+@@ -1680,7 +1680,7 @@ static int imx21_hc_reset(struct usb_hcd *hcd)
+ 	return 0;
+ }
+ 
+-static int __devinit imx21_hc_start(struct usb_hcd *hcd)
++static int imx21_hc_start(struct usb_hcd *hcd)
+ {
+ 	struct imx21 *imx21 = hcd_to_imx21(hcd);
+ 	unsigned long flags;
+diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
+index 9e65e3091c8a..b64e661618bb 100644
+--- a/drivers/usb/host/isp116x-hcd.c
++++ b/drivers/usb/host/isp116x-hcd.c
+@@ -1557,7 +1557,7 @@ static int isp116x_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devinit isp116x_probe(struct platform_device *pdev)
++static int isp116x_probe(struct platform_device *pdev)
+ {
+ 	struct usb_hcd *hcd;
+ 	struct isp116x *isp116x;
+diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
+index 1ad9d2007222..5f8b63ce4bef 100644
+--- a/drivers/usb/host/isp1362-hcd.c
++++ b/drivers/usb/host/isp1362-hcd.c
+@@ -2680,7 +2680,7 @@ static int __devexit isp1362_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devinit isp1362_probe(struct platform_device *pdev)
++static int isp1362_probe(struct platform_device *pdev)
+ {
+ 	struct usb_hcd *hcd;
+ 	struct isp1362_hcd *isp1362_hcd;
+diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c
+index 5fb3caee7706..d752a4c4281a 100644
+--- a/drivers/usb/host/isp1760-if.c
++++ b/drivers/usb/host/isp1760-if.c
+@@ -172,7 +172,7 @@ static struct platform_driver isp1760_of_driver = {
+ #endif
+ 
+ #ifdef CONFIG_PCI
+-static int __devinit isp1761_pci_probe(struct pci_dev *dev,
++static int isp1761_pci_probe(struct pci_dev *dev,
+ 		const struct pci_device_id *id)
+ {
+ 	u8 latency, limit;
+@@ -346,7 +346,7 @@ static struct pci_driver isp1761_pci_driver = {
+ };
+ #endif
+ 
+-static int __devinit isp1760_plat_probe(struct platform_device *pdev)
++static int isp1760_plat_probe(struct platform_device *pdev)
+ {
+ 	int ret = 0;
+ 	struct usb_hcd *hcd;
+diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
+index e4480029bc0c..ff94a7479a75 100644
+--- a/drivers/usb/host/ohci-at91.c
++++ b/drivers/usb/host/ohci-at91.c
+@@ -108,7 +108,7 @@ static void __devexit usb_hcd_at91_remove (struct usb_hcd *, struct platform_dev
+  * then invokes the start() method for the HCD associated with it
+  * through the hotplug entry's driver_data.
+  */
+-static int __devinit usb_hcd_at91_probe(const struct hc_driver *driver,
++static int usb_hcd_at91_probe(const struct hc_driver *driver,
+ 			struct platform_device *pdev)
+ {
+ 	int retval;
+@@ -222,7 +222,7 @@ static void __devexit usb_hcd_at91_remove(struct usb_hcd *hcd,
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-static int __devinit
++static int
+ ohci_at91_reset (struct usb_hcd *hcd)
+ {
+ 	struct at91_usbh_data	*board = hcd->self.controller->platform_data;
+@@ -236,7 +236,7 @@ ohci_at91_reset (struct usb_hcd *hcd)
+ 	return 0;
+ }
+ 
+-static int __devinit
++static int
+ ohci_at91_start (struct usb_hcd *hcd)
+ {
+ 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+@@ -506,7 +506,7 @@ MODULE_DEVICE_TABLE(of, at91_ohci_dt_ids);
+ 
+ static u64 at91_ohci_dma_mask = DMA_BIT_MASK(32);
+ 
+-static int __devinit ohci_at91_of_init(struct platform_device *pdev)
++static int ohci_at91_of_init(struct platform_device *pdev)
+ {
+ 	struct device_node *np = pdev->dev.of_node;
+ 	int i, gpio;
+@@ -548,7 +548,7 @@ static int __devinit ohci_at91_of_init(struct platform_device *pdev)
+ 	return 0;
+ }
+ #else
+-static int __devinit ohci_at91_of_init(struct platform_device *pdev)
++static int ohci_at91_of_init(struct platform_device *pdev)
+ {
+ 	return 0;
+ }
+@@ -556,7 +556,7 @@ static int __devinit ohci_at91_of_init(struct platform_device *pdev)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-static int __devinit ohci_hcd_at91_drv_probe(struct platform_device *pdev)
++static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
+ {
+ 	struct at91_usbh_data	*pdata;
+ 	int			i;
+diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
+index a982f04ed787..8704e9fa5a80 100644
+--- a/drivers/usb/host/ohci-ep93xx.c
++++ b/drivers/usb/host/ohci-ep93xx.c
+@@ -107,7 +107,7 @@ static void usb_hcd_ep93xx_remove(struct usb_hcd *hcd,
+ 	usb_put_hcd(hcd);
+ }
+ 
+-static int __devinit ohci_ep93xx_start(struct usb_hcd *hcd)
++static int ohci_ep93xx_start(struct usb_hcd *hcd)
+ {
+ 	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+ 	int ret;
+diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
+index 2f673e872b7d..1288cdb3137c 100644
+--- a/drivers/usb/host/ohci-exynos.c
++++ b/drivers/usb/host/ohci-exynos.c
+@@ -76,7 +76,7 @@ static const struct hc_driver exynos_ohci_hc_driver = {
+ 
+ static u64 ohci_exynos_dma_mask = DMA_BIT_MASK(32);
+ 
+-static int __devinit exynos_ohci_probe(struct platform_device *pdev)
++static int exynos_ohci_probe(struct platform_device *pdev)
+ {
+ 	struct exynos4_ohci_platdata *pdata;
+ 	struct exynos_ohci_hcd *exynos_ohci;
+diff --git a/drivers/usb/host/ohci-jz4740.c b/drivers/usb/host/ohci-jz4740.c
+index b4921b713557..59feb8738132 100644
+--- a/drivers/usb/host/ohci-jz4740.c
++++ b/drivers/usb/host/ohci-jz4740.c
+@@ -145,7 +145,7 @@ static const struct hc_driver ohci_jz4740_hc_driver = {
+ };
+ 
+ 
+-static __devinit int jz4740_ohci_probe(struct platform_device *pdev)
++static int jz4740_ohci_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 	struct usb_hcd *hcd;
+diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c
+index e068f034cb9b..2344040c16d2 100644
+--- a/drivers/usb/host/ohci-nxp.c
++++ b/drivers/usb/host/ohci-nxp.c
+@@ -147,7 +147,7 @@ static void nxp_stop_hc(void)
+ 	__raw_writel(tmp, USB_OTG_STAT_CONTROL);
+ }
+ 
+-static int __devinit ohci_nxp_start(struct usb_hcd *hcd)
++static int ohci_nxp_start(struct usb_hcd *hcd)
+ {
+ 	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+ 	int ret;
+@@ -205,7 +205,7 @@ static const struct hc_driver ohci_nxp_hc_driver = {
+ 	.start_port_reset = ohci_start_port_reset,
+ };
+ 
+-static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev)
++static int usb_hcd_nxp_probe(struct platform_device *pdev)
+ {
+ 	struct usb_hcd *hcd = 0;
+ 	struct ohci_hcd *ohci;
+diff --git a/drivers/usb/host/ohci-octeon.c b/drivers/usb/host/ohci-octeon.c
+index d469bf9b9e54..d44430d009f8 100644
+--- a/drivers/usb/host/ohci-octeon.c
++++ b/drivers/usb/host/ohci-octeon.c
+@@ -42,7 +42,7 @@ static void ohci_octeon_hw_stop(void)
+ 	octeon2_usb_clocks_stop();
+ }
+ 
+-static int __devinit ohci_octeon_start(struct usb_hcd *hcd)
++static int ohci_octeon_start(struct usb_hcd *hcd)
+ {
+ 	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+ 	int ret;
+diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c
+index 6bee6f191c86..b2398aa6c7a2 100644
+--- a/drivers/usb/host/ohci-omap3.c
++++ b/drivers/usb/host/ohci-omap3.c
+@@ -125,7 +125,7 @@ static const struct hc_driver ohci_omap3_hc_driver = {
+  * then invokes the start() method for the HCD associated with it
+  * through the hotplug entry's driver_data.
+  */
+-static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev)
++static int ohci_hcd_omap3_probe(struct platform_device *pdev)
+ {
+ 	struct device		*dev = &pdev->dev;
+ 	struct usb_hcd		*hcd = NULL;
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index 6afa7dc4e4c3..951514ef446d 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -270,7 +270,7 @@ static int ohci_pci_reset (struct usb_hcd *hcd)
+ }
+ 
+ 
+-static int __devinit ohci_pci_start (struct usb_hcd *hcd)
++static int ohci_pci_start (struct usb_hcd *hcd)
+ {
+ 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
+ 	int		ret;
+diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
+index ffe6c9808473..c3f76fa8d7dc 100644
+--- a/drivers/usb/host/ohci-platform.c
++++ b/drivers/usb/host/ohci-platform.c
+@@ -83,7 +83,7 @@ static const struct hc_driver ohci_platform_hc_driver = {
+ 	.start_port_reset	= ohci_start_port_reset,
+ };
+ 
+-static int __devinit ohci_platform_probe(struct platform_device *dev)
++static int ohci_platform_probe(struct platform_device *dev)
+ {
+ 	struct usb_hcd *hcd;
+ 	struct resource *res_mem;
+diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
+index e27d5ae2b9eb..64c2ed9ff95e 100644
+--- a/drivers/usb/host/ohci-ppc-of.c
++++ b/drivers/usb/host/ohci-ppc-of.c
+@@ -19,7 +19,7 @@
+ #include 
+ 
+ 
+-static int __devinit
++static int
+ ohci_ppc_of_start(struct usb_hcd *hcd)
+ {
+ 	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+@@ -81,7 +81,7 @@ static const struct hc_driver ohci_ppc_of_hc_driver = {
+ };
+ 
+ 
+-static int __devinit ohci_hcd_ppc_of_probe(struct platform_device *op)
++static int ohci_hcd_ppc_of_probe(struct platform_device *op)
+ {
+ 	struct device_node *dn = op->dev.of_node;
+ 	struct usb_hcd *hcd;
+diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c
+index 2ee1d8d713d2..7d35cd9e2862 100644
+--- a/drivers/usb/host/ohci-ps3.c
++++ b/drivers/usb/host/ohci-ps3.c
+@@ -30,7 +30,7 @@ static int ps3_ohci_hc_reset(struct usb_hcd *hcd)
+ 	return ohci_init(ohci);
+ }
+ 
+-static int __devinit ps3_ohci_hc_start(struct usb_hcd *hcd)
++static int ps3_ohci_hc_start(struct usb_hcd *hcd)
+ {
+ 	int result;
+ 	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+@@ -76,7 +76,7 @@ static const struct hc_driver ps3_ohci_hc_driver = {
+ #endif
+ };
+ 
+-static int __devinit ps3_ohci_probe(struct ps3_system_bus_device *dev)
++static int ps3_ohci_probe(struct ps3_system_bus_device *dev)
+ {
+ 	int result;
+ 	struct usb_hcd *hcd;
+diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
+index 156d289d3bb5..efe71f3ca477 100644
+--- a/drivers/usb/host/ohci-pxa27x.c
++++ b/drivers/usb/host/ohci-pxa27x.c
+@@ -284,7 +284,7 @@ MODULE_DEVICE_TABLE(of, pxa_ohci_dt_ids);
+ 
+ static u64 pxa_ohci_dma_mask = DMA_BIT_MASK(32);
+ 
+-static int __devinit ohci_pxa_of_init(struct platform_device *pdev)
++static int ohci_pxa_of_init(struct platform_device *pdev)
+ {
+ 	struct device_node *np = pdev->dev.of_node;
+ 	struct pxaohci_platform_data *pdata;
+@@ -330,7 +330,7 @@ static int __devinit ohci_pxa_of_init(struct platform_device *pdev)
+ 	return 0;
+ }
+ #else
+-static int __devinit ohci_pxa_of_init(struct platform_device *pdev)
++static int ohci_pxa_of_init(struct platform_device *pdev)
+ {
+ 	return 0;
+ }
+@@ -471,7 +471,7 @@ void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *pdev)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-static int __devinit
++static int
+ ohci_pxa27x_start (struct usb_hcd *hcd)
+ {
+ 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
+diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
+index 5c5c017850d8..4f29e0b086b3 100644
+--- a/drivers/usb/host/ohci-s3c2410.c
++++ b/drivers/usb/host/ohci-s3c2410.c
+@@ -458,7 +458,7 @@ static const struct hc_driver ohci_s3c2410_hc_driver = {
+ 
+ /* device driver */
+ 
+-static int __devinit ohci_hcd_s3c2410_drv_probe(struct platform_device *pdev)
++static int ohci_hcd_s3c2410_drv_probe(struct platform_device *pdev)
+ {
+ 	return usb_hcd_s3c2410_probe(&ohci_s3c2410_hc_driver, pdev);
+ }
+diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
+index b6cc92520924..17b2a7dad77b 100644
+--- a/drivers/usb/host/ohci-sa1111.c
++++ b/drivers/usb/host/ohci-sa1111.c
+@@ -63,7 +63,7 @@ static int ohci_sa1111_reset(struct usb_hcd *hcd)
+ 	return ohci_init(ohci);
+ }
+ 
+-static int __devinit ohci_sa1111_start(struct usb_hcd *hcd)
++static int ohci_sa1111_start(struct usb_hcd *hcd)
+ {
+ 	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+ 	int ret;
+diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c
+index c69725d9f0cd..b7fc2fc56c84 100644
+--- a/drivers/usb/host/ohci-spear.c
++++ b/drivers/usb/host/ohci-spear.c
+@@ -33,7 +33,7 @@ static void spear_stop_ohci(struct spear_ohci *ohci)
+ 	clk_disable_unprepare(ohci->clk);
+ }
+ 
+-static int __devinit ohci_spear_start(struct usb_hcd *hcd)
++static int ohci_spear_start(struct usb_hcd *hcd)
+ {
+ 	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+ 	int ret;
+diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c
+index 94c6c550a953..5996a3b0a4d3 100644
+--- a/drivers/usb/host/ohci-tmio.c
++++ b/drivers/usb/host/ohci-tmio.c
+@@ -184,7 +184,7 @@ static const struct hc_driver ohci_tmio_hc_driver = {
+ /*-------------------------------------------------------------------------*/
+ static struct platform_driver ohci_hcd_tmio_driver;
+ 
+-static int __devinit ohci_hcd_tmio_drv_probe(struct platform_device *dev)
++static int ohci_hcd_tmio_drv_probe(struct platform_device *dev)
+ {
+ 	const struct mfd_cell *cell = mfd_get_cell(dev);
+ 	struct resource *regs = platform_get_resource(dev, IORESOURCE_MEM, 0);
+diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
+index 39f9e4a9a2d3..a018e706c0e1 100644
+--- a/drivers/usb/host/pci-quirks.c
++++ b/drivers/usb/host/pci-quirks.c
+@@ -443,7 +443,7 @@ static inline int io_type_enabled(struct pci_dev *pdev, unsigned int mask)
+ #define pio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_IO)
+ #define mmio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_MEMORY)
+ 
+-static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev)
++static void quirk_usb_handoff_uhci(struct pci_dev *pdev)
+ {
+ 	unsigned long base = 0;
+ 	int i;
+@@ -461,12 +461,12 @@ static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev)
+ 		uhci_check_and_reset_hc(pdev, base);
+ }
+ 
+-static int __devinit mmio_resource_enabled(struct pci_dev *pdev, int idx)
++static int mmio_resource_enabled(struct pci_dev *pdev, int idx)
+ {
+ 	return pci_resource_start(pdev, idx) && mmio_enabled(pdev);
+ }
+ 
+-static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
++static void quirk_usb_handoff_ohci(struct pci_dev *pdev)
+ {
+ 	void __iomem *base;
+ 	u32 control;
+@@ -558,7 +558,7 @@ static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = {
+ 	{ }
+ };
+ 
+-static void __devinit ehci_bios_handoff(struct pci_dev *pdev,
++static void ehci_bios_handoff(struct pci_dev *pdev,
+ 					void __iomem *op_reg_base,
+ 					u32 cap, u8 offset)
+ {
+@@ -626,7 +626,7 @@ static void __devinit ehci_bios_handoff(struct pci_dev *pdev,
+ 		writel(0, op_reg_base + EHCI_CONFIGFLAG);
+ }
+ 
+-static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
++static void quirk_usb_disable_ehci(struct pci_dev *pdev)
+ {
+ 	void __iomem *base, *op_reg_base;
+ 	u32	hcc_params, cap, val;
+@@ -841,7 +841,7 @@ EXPORT_SYMBOL_GPL(usb_disable_xhci_ports);
+  * and then waits 5 seconds for the BIOS to hand over control.
+  * If we timeout, assume the BIOS is broken and take control anyway.
+  */
+-static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
++static void quirk_usb_handoff_xhci(struct pci_dev *pdev)
+ {
+ 	void __iomem *base;
+ 	int ext_cap_offset;
+@@ -941,7 +941,7 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
+ 	iounmap(base);
+ }
+ 
+-static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
++static void quirk_usb_early_handoff(struct pci_dev *pdev)
+ {
+ 	/* Skip Netlogic mips SoC's internal PCI USB controller.
+ 	 * This device does not need/support EHCI/OHCI handoff
+diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
+index 4e0436fc334d..e97dfad526f4 100644
+--- a/drivers/usb/host/r8a66597-hcd.c
++++ b/drivers/usb/host/r8a66597-hcd.c
+@@ -2405,7 +2405,7 @@ static int __devexit r8a66597_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devinit r8a66597_probe(struct platform_device *pdev)
++static int r8a66597_probe(struct platform_device *pdev)
+ {
+ 	char clk_name[8];
+ 	struct resource *res = NULL, *ires;
+diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
+index 15f20de3e05d..782127d9dfc5 100644
+--- a/drivers/usb/host/sl811-hcd.c
++++ b/drivers/usb/host/sl811-hcd.c
+@@ -1618,7 +1618,7 @@ sl811h_remove(struct platform_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devinit
++static int
+ sl811h_probe(struct platform_device *dev)
+ {
+ 	struct usb_hcd		*hcd;
+diff --git a/drivers/usb/host/ssb-hcd.c b/drivers/usb/host/ssb-hcd.c
+index 4dc9a09dc346..79aa95832b26 100644
+--- a/drivers/usb/host/ssb-hcd.c
++++ b/drivers/usb/host/ssb-hcd.c
+@@ -39,7 +39,7 @@ struct ssb_hcd_device {
+ 	u32 enable_flags;
+ };
+ 
+-static void __devinit ssb_hcd_5354wa(struct ssb_device *dev)
++static void ssb_hcd_5354wa(struct ssb_device *dev)
+ {
+ #ifdef CONFIG_SSB_DRIVER_MIPS
+ 	/* Work around for 5354 failures */
+@@ -53,7 +53,7 @@ static void __devinit ssb_hcd_5354wa(struct ssb_device *dev)
+ #endif
+ }
+ 
+-static void __devinit ssb_hcd_usb20wa(struct ssb_device *dev)
++static void ssb_hcd_usb20wa(struct ssb_device *dev)
+ {
+ 	if (dev->id.coreid == SSB_DEV_USB20_HOST) {
+ 		/*
+@@ -80,7 +80,7 @@ static void __devinit ssb_hcd_usb20wa(struct ssb_device *dev)
+ }
+ 
+ /* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */
+-static u32 __devinit ssb_hcd_init_chip(struct ssb_device *dev)
++static u32 ssb_hcd_init_chip(struct ssb_device *dev)
+ {
+ 	u32 flags = 0;
+ 
+@@ -101,8 +101,7 @@ static const struct usb_ehci_pdata ehci_pdata = {
+ static const struct usb_ohci_pdata ohci_pdata = {
+ };
+ 
+-static struct platform_device * __devinit
+-ssb_hcd_create_pdev(struct ssb_device *dev, bool ohci, u32 addr, u32 len)
++static struct platform_device *ssb_hcd_create_pdev(struct ssb_device *dev, bool ohci, u32 addr, u32 len)
+ {
+ 	struct platform_device *hci_dev;
+ 	struct resource hci_res[2];
+@@ -148,7 +147,7 @@ ssb_hcd_create_pdev(struct ssb_device *dev, bool ohci, u32 addr, u32 len)
+ 	return ERR_PTR(ret);
+ }
+ 
+-static int __devinit ssb_hcd_probe(struct ssb_device *dev,
++static int ssb_hcd_probe(struct ssb_device *dev,
+ 				   const struct ssb_device_id *id)
+ {
+ 	int err, tmp;
+diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
+index 8836898d64de..8bf78e652a8a 100644
+--- a/drivers/usb/host/u132-hcd.c
++++ b/drivers/usb/host/u132-hcd.c
+@@ -3084,7 +3084,7 @@ static void u132_initialise(struct u132 *u132, struct platform_device *pdev)
+ 	mutex_unlock(&u132->sw_lock);
+ }
+ 
+-static int __devinit u132_probe(struct platform_device *pdev)
++static int u132_probe(struct platform_device *pdev)
+ {
+ 	struct usb_hcd *hcd;
+ 	int retval;
+diff --git a/drivers/usb/host/uhci-grlib.c b/drivers/usb/host/uhci-grlib.c
+index f7a62138e3e0..511bfc46dd78 100644
+--- a/drivers/usb/host/uhci-grlib.c
++++ b/drivers/usb/host/uhci-grlib.c
+@@ -85,7 +85,7 @@ static const struct hc_driver uhci_grlib_hc_driver = {
+ };
+ 
+ 
+-static int __devinit uhci_hcd_grlib_probe(struct platform_device *op)
++static int uhci_hcd_grlib_probe(struct platform_device *op)
+ {
+ 	struct device_node *dn = op->dev.of_node;
+ 	struct usb_hcd *hcd;
+diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c
+index 68ebf20e1519..8c4dace4b14a 100644
+--- a/drivers/usb/host/uhci-platform.c
++++ b/drivers/usb/host/uhci-platform.c
+@@ -62,7 +62,7 @@ static const struct hc_driver uhci_platform_hc_driver = {
+ 
+ static u64 platform_uhci_dma_mask = DMA_BIT_MASK(32);
+ 
+-static int __devinit uhci_hcd_platform_probe(struct platform_device *pdev)
++static int uhci_hcd_platform_probe(struct platform_device *pdev)
+ {
+ 	struct usb_hcd *hcd;
+ 	struct uhci_hcd	*uhci;
+diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c
+index 49e8ce7ec26b..a27bb8515674 100644
+--- a/drivers/usb/musb/am35x.c
++++ b/drivers/usb/musb/am35x.c
+@@ -455,7 +455,7 @@ static const struct musb_platform_ops am35x_ops = {
+ 
+ static u64 am35x_dmamask = DMA_BIT_MASK(32);
+ 
+-static int __devinit am35x_probe(struct platform_device *pdev)
++static int am35x_probe(struct platform_device *pdev)
+ {
+ 	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+ 	struct platform_device		*musb;
+diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
+index 7e4d60a41728..12beb0e31144 100644
+--- a/drivers/usb/musb/blackfin.c
++++ b/drivers/usb/musb/blackfin.c
+@@ -448,7 +448,7 @@ static const struct musb_platform_ops bfin_ops = {
+ 
+ static u64 bfin_dmamask = DMA_BIT_MASK(32);
+ 
+-static int __devinit bfin_probe(struct platform_device *pdev)
++static int bfin_probe(struct platform_device *pdev)
+ {
+ 	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+ 	struct platform_device		*musb;
+diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c
+index 3a6c2fd1f913..0968dd7a859d 100644
+--- a/drivers/usb/musb/cppi_dma.c
++++ b/drivers/usb/musb/cppi_dma.c
+@@ -1317,8 +1317,7 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id)
+ EXPORT_SYMBOL_GPL(cppi_interrupt);
+ 
+ /* Instantiate a software object representing a DMA controller. */
+-struct dma_controller *__devinit
+-dma_controller_create(struct musb *musb, void __iomem *mregs)
++struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *mregs)
+ {
+ 	struct cppi		*controller;
+ 	struct device		*dev = musb->controller;
+diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
+index 51ace9bf73df..c4fb235985ba 100644
+--- a/drivers/usb/musb/da8xx.c
++++ b/drivers/usb/musb/da8xx.c
+@@ -471,7 +471,7 @@ static const struct musb_platform_ops da8xx_ops = {
+ 
+ static u64 da8xx_dmamask = DMA_BIT_MASK(32);
+ 
+-static int __devinit da8xx_probe(struct platform_device *pdev)
++static int da8xx_probe(struct platform_device *pdev)
+ {
+ 	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+ 	struct platform_device		*musb;
+diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
+index e01087b44e09..8877c1a7dbb7 100644
+--- a/drivers/usb/musb/davinci.c
++++ b/drivers/usb/musb/davinci.c
+@@ -504,7 +504,7 @@ static const struct musb_platform_ops davinci_ops = {
+ 
+ static u64 davinci_dmamask = DMA_BIT_MASK(32);
+ 
+-static int __devinit davinci_probe(struct platform_device *pdev)
++static int davinci_probe(struct platform_device *pdev)
+ {
+ 	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+ 	struct platform_device		*musb;
+diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
+index 69cfa18bb2df..f17a3e79dbec 100644
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -1163,7 +1163,7 @@ static struct musb_fifo_cfg __devinitdata mode_5_cfg[] = {
+  *
+  * returns negative errno or offset for next fifo.
+  */
+-static int __devinit
++static int
+ fifo_setup(struct musb *musb, struct musb_hw_ep  *hw_ep,
+ 		const struct musb_fifo_cfg *cfg, u16 offset)
+ {
+@@ -1238,7 +1238,7 @@ static struct musb_fifo_cfg __devinitdata ep0_cfg = {
+ 	.style = FIFO_RXTX, .maxpacket = 64,
+ };
+ 
+-static int __devinit ep_config_from_table(struct musb *musb)
++static int ep_config_from_table(struct musb *musb)
+ {
+ 	const struct musb_fifo_cfg	*cfg;
+ 	unsigned		i, n;
+@@ -1329,7 +1329,7 @@ static int __devinit ep_config_from_table(struct musb *musb)
+  * ep_config_from_hw - when MUSB_C_DYNFIFO_DEF is false
+  * @param musb the controller
+  */
+-static int __devinit ep_config_from_hw(struct musb *musb)
++static int ep_config_from_hw(struct musb *musb)
+ {
+ 	u8 epnum = 0;
+ 	struct musb_hw_ep *hw_ep;
+@@ -1376,7 +1376,7 @@ enum { MUSB_CONTROLLER_MHDRC, MUSB_CONTROLLER_HDRC, };
+ /* Initialize MUSB (M)HDRC part of the USB hardware subsystem;
+  * configure endpoints, or take their config from silicon
+  */
+-static int __devinit musb_core_init(u16 musb_type, struct musb *musb)
++static int musb_core_init(u16 musb_type, struct musb *musb)
+ {
+ 	u8 reg;
+ 	char *type;
+@@ -1759,8 +1759,7 @@ static void musb_irq_work(struct work_struct *data)
+  * Init support
+  */
+ 
+-static struct musb *__devinit
+-allocate_instance(struct device *dev,
++static struct musb *allocate_instance(struct device *dev,
+ 		struct musb_hdrc_config *config, void __iomem *mbase)
+ {
+ 	struct musb		*musb;
+@@ -1835,7 +1834,7 @@ static void musb_free(struct musb *musb)
+  * @ctrl: virtual address of controller registers,
+  *	not yet corrected for platform-specific offsets
+  */
+-static int __devinit
++static int
+ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
+ {
+ 	int			status;
+@@ -2010,7 +2009,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
+ /* all implementations (PCI bridge to FPGA, VLYNQ, etc) should just
+  * bridge to a platform device; this driver then suffices.
+  */
+-static int __devinit musb_probe(struct platform_device *pdev)
++static int musb_probe(struct platform_device *pdev)
+ {
+ 	struct device	*dev = &pdev->dev;
+ 	int		irq = platform_get_irq_byname(pdev, "mc");
+diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c
+index 1d6e8af94c06..4c216790e86b 100644
+--- a/drivers/usb/musb/musb_debugfs.c
++++ b/drivers/usb/musb/musb_debugfs.c
+@@ -233,7 +233,7 @@ static const struct file_operations musb_test_mode_fops = {
+ 	.release		= single_release,
+ };
+ 
+-int __devinit musb_init_debugfs(struct musb *musb)
++int musb_init_debugfs(struct musb *musb)
+ {
+ 	struct dentry		*root;
+ 	struct dentry		*file;
+diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h
+index 24d39210d4ab..1b6b827b769f 100644
+--- a/drivers/usb/musb/musb_dma.h
++++ b/drivers/usb/musb/musb_dma.h
+@@ -178,8 +178,7 @@ struct dma_controller {
+ extern void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit);
+ 
+ 
+-extern struct dma_controller *__devinit
+-dma_controller_create(struct musb *, void __iomem *);
++extern struct dma_controller *dma_controller_create(struct musb *, void __iomem *);
+ 
+ extern void dma_controller_destroy(struct dma_controller *);
+ 
+diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
+index 80e2b03965c8..f8affd7a30c0 100644
+--- a/drivers/usb/musb/musb_dsps.c
++++ b/drivers/usb/musb/musb_dsps.c
+@@ -479,7 +479,7 @@ static struct musb_platform_ops dsps_ops = {
+ 
+ static u64 musb_dmamask = DMA_BIT_MASK(32);
+ 
+-static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
++static int dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
+ {
+ 	struct device *dev = glue->dev;
+ 	struct platform_device *pdev = to_platform_device(dev);
+@@ -592,7 +592,7 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
+ 	return ret;
+ }
+ 
+-static int __devinit dsps_probe(struct platform_device *pdev)
++static int dsps_probe(struct platform_device *pdev)
+ {
+ 	struct device_node *np = pdev->dev.of_node;
+ 	const struct of_device_id *match;
+diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
+index 4f23b12a3ae7..876787438c2f 100644
+--- a/drivers/usb/musb/musb_gadget.c
++++ b/drivers/usb/musb/musb_gadget.c
+@@ -1787,7 +1787,7 @@ static void musb_gadget_release(struct device *dev)
+ }
+ 
+ 
+-static void __devinit
++static void
+ init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in)
+ {
+ 	struct musb_hw_ep	*hw_ep = musb->endpoints + epnum;
+@@ -1824,7 +1824,7 @@ init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in)
+  * Initialize the endpoints exposed to peripheral drivers, with backlinks
+  * to the rest of the driver state.
+  */
+-static inline void __devinit musb_g_init_endpoints(struct musb *musb)
++static inline void musb_g_init_endpoints(struct musb *musb)
+ {
+ 	u8			epnum;
+ 	struct musb_hw_ep	*hw_ep;
+@@ -1857,7 +1857,7 @@ static inline void __devinit musb_g_init_endpoints(struct musb *musb)
+ /* called once during driver setup to initialize and link into
+  * the driver model; memory is zeroed.
+  */
+-int __devinit musb_gadget_setup(struct musb *musb)
++int musb_gadget_setup(struct musb *musb)
+ {
+ 	int status;
+ 
+diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
+index 0fc6ca6bc60a..3d1fd52a15a9 100644
+--- a/drivers/usb/musb/musbhsdma.c
++++ b/drivers/usb/musb/musbhsdma.c
+@@ -380,8 +380,7 @@ void dma_controller_destroy(struct dma_controller *c)
+ 	kfree(controller);
+ }
+ 
+-struct dma_controller *__devinit
+-dma_controller_create(struct musb *musb, void __iomem *base)
++struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *base)
+ {
+ 	struct musb_dma_controller *controller;
+ 	struct device *dev = musb->controller;
+diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
+index 1150b4b6a090..06850f22739f 100644
+--- a/drivers/usb/musb/omap2430.c
++++ b/drivers/usb/musb/omap2430.c
+@@ -490,7 +490,7 @@ static const struct musb_platform_ops omap2430_ops = {
+ 
+ static u64 omap2430_dmamask = DMA_BIT_MASK(32);
+ 
+-static int __devinit omap2430_probe(struct platform_device *pdev)
++static int omap2430_probe(struct platform_device *pdev)
+ {
+ 	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+ 	struct omap_musb_board_data	*data;
+diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
+index b816517d8cbf..a03b7befd2e1 100644
+--- a/drivers/usb/musb/tusb6010.c
++++ b/drivers/usb/musb/tusb6010.c
+@@ -1153,7 +1153,7 @@ static const struct musb_platform_ops tusb_ops = {
+ 
+ static u64 tusb_dmamask = DMA_BIT_MASK(32);
+ 
+-static int __devinit tusb_probe(struct platform_device *pdev)
++static int tusb_probe(struct platform_device *pdev)
+ {
+ 	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+ 	struct platform_device		*musb;
+diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
+index 7a62b95dac24..2c46d42e6618 100644
+--- a/drivers/usb/musb/tusb6010_omap.c
++++ b/drivers/usb/musb/tusb6010_omap.c
+@@ -661,8 +661,7 @@ void dma_controller_destroy(struct dma_controller *c)
+ 	kfree(tusb_dma);
+ }
+ 
+-struct dma_controller *__devinit
+-dma_controller_create(struct musb *musb, void __iomem *base)
++struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *base)
+ {
+ 	void __iomem		*tbase = musb->ctrl_base;
+ 	struct tusb_omap_dma	*tusb_dma;
+diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c
+index 1d815578dde5..6b12001eb88b 100644
+--- a/drivers/usb/musb/ux500.c
++++ b/drivers/usb/musb/ux500.c
+@@ -81,7 +81,7 @@ static const struct musb_platform_ops ux500_ops = {
+ 	.exit		= ux500_musb_exit,
+ };
+ 
+-static int __devinit ux500_probe(struct platform_device *pdev)
++static int ux500_probe(struct platform_device *pdev)
+ {
+ 	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+ 	struct platform_device		*musb;
+diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c
+index f1059e725ea8..039e567dd3b6 100644
+--- a/drivers/usb/musb/ux500_dma.c
++++ b/drivers/usb/musb/ux500_dma.c
+@@ -364,8 +364,7 @@ void dma_controller_destroy(struct dma_controller *c)
+ 	kfree(controller);
+ }
+ 
+-struct dma_controller *__devinit
+-dma_controller_create(struct musb *musb, void __iomem *base)
++struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *base)
+ {
+ 	struct ux500_dma_controller *controller;
+ 	struct platform_device *pdev = to_platform_device(musb->controller);
+diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c
+index 62ea0c23c455..f0ba931f0d5d 100644
+--- a/drivers/usb/otg/ab8500-usb.c
++++ b/drivers/usb/otg/ab8500-usb.c
+@@ -468,7 +468,7 @@ static int ab8500_usb_v2_res_setup(struct platform_device *pdev,
+ 	return 0;
+ }
+ 
+-static int __devinit ab8500_usb_probe(struct platform_device *pdev)
++static int ab8500_usb_probe(struct platform_device *pdev)
+ {
+ 	struct ab8500_usb	*ab;
+ 	struct usb_otg		*otg;
+diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/otg/fsl_otg.c
+index 77dad188d2d9..2b9a83856a50 100644
+--- a/drivers/usb/otg/fsl_otg.c
++++ b/drivers/usb/otg/fsl_otg.c
+@@ -1110,7 +1110,7 @@ static const struct file_operations otg_fops = {
+ 	.release = fsl_otg_release,
+ };
+ 
+-static int __devinit fsl_otg_probe(struct platform_device *pdev)
++static int fsl_otg_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+ 
+diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c
+index ceee2119bffa..af9cb11626b2 100644
+--- a/drivers/usb/otg/isp1301_omap.c
++++ b/drivers/usb/otg/isp1301_omap.c
+@@ -1493,7 +1493,7 @@ isp1301_start_hnp(struct usb_otg *otg)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-static int __devinit
++static int
+ isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
+ {
+ 	int			status;
+diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c
+index 0502c2405915..28f70e21ad61 100644
+--- a/drivers/usb/otg/nop-usb-xceiv.c
++++ b/drivers/usb/otg/nop-usb-xceiv.c
+@@ -93,7 +93,7 @@ static int nop_set_host(struct usb_otg *otg, struct usb_bus *host)
+ 	return 0;
+ }
+ 
+-static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev)
++static int nop_usb_xceiv_probe(struct platform_device *pdev)
+ {
+ 	struct nop_usb_xceiv_platform_data *pdata = pdev->dev.platform_data;
+ 	struct nop_usb_xceiv	*nop;
+diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
+index 11b2a1203d40..0a701938ab53 100644
+--- a/drivers/usb/otg/twl4030-usb.c
++++ b/drivers/usb/otg/twl4030-usb.c
+@@ -575,7 +575,7 @@ static int twl4030_set_host(struct usb_otg *otg, struct usb_bus *host)
+ 	return 0;
+ }
+ 
+-static int __devinit twl4030_usb_probe(struct platform_device *pdev)
++static int twl4030_usb_probe(struct platform_device *pdev)
+ {
+ 	struct twl4030_usb_data *pdata = pdev->dev.platform_data;
+ 	struct twl4030_usb	*twl;
+diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c
+index fcadef7864f1..8cd6cf49bdbd 100644
+--- a/drivers/usb/otg/twl6030-usb.c
++++ b/drivers/usb/otg/twl6030-usb.c
+@@ -310,7 +310,7 @@ static int twl6030_set_vbus(struct phy_companion *comparator, bool enabled)
+ 	return 0;
+ }
+ 
+-static int __devinit twl6030_usb_probe(struct platform_device *pdev)
++static int twl6030_usb_probe(struct platform_device *pdev)
+ {
+ 	u32 ret;
+ 	struct twl6030_usb	*twl;
+diff --git a/drivers/usb/phy/mv_u3d_phy.c b/drivers/usb/phy/mv_u3d_phy.c
+index 80cf57ef5502..eaddbe3d4304 100644
+--- a/drivers/usb/phy/mv_u3d_phy.c
++++ b/drivers/usb/phy/mv_u3d_phy.c
+@@ -262,7 +262,7 @@ static int mv_u3d_phy_init(struct usb_phy *phy)
+ 	return 0;
+ }
+ 
+-static int __devinit mv_u3d_phy_probe(struct platform_device *pdev)
++static int mv_u3d_phy_probe(struct platform_device *pdev)
+ {
+ 	struct mv_u3d_phy *mv_u3d_phy;
+ 	struct mv_usb_platform_data *pdata;
+diff --git a/drivers/usb/phy/omap-usb2.c b/drivers/usb/phy/omap-usb2.c
+index f1ed872dd969..c10fb8b1fdbc 100644
+--- a/drivers/usb/phy/omap-usb2.c
++++ b/drivers/usb/phy/omap-usb2.c
+@@ -141,7 +141,7 @@ static int omap_usb2_suspend(struct usb_phy *x, int suspend)
+ 	return 0;
+ }
+ 
+-static int __devinit omap_usb2_probe(struct platform_device *pdev)
++static int omap_usb2_probe(struct platform_device *pdev)
+ {
+ 	struct omap_usb			*phy;
+ 	struct usb_otg			*otg;
+diff --git a/drivers/usb/phy/rcar-phy.c b/drivers/usb/phy/rcar-phy.c
+index 703a29586a7a..84ac2a77de72 100644
+--- a/drivers/usb/phy/rcar-phy.c
++++ b/drivers/usb/phy/rcar-phy.c
+@@ -142,7 +142,7 @@ static void rcar_usb_phy_shutdown(struct usb_phy *phy)
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ }
+ 
+-static int __devinit rcar_usb_phy_probe(struct platform_device *pdev)
++static int rcar_usb_phy_probe(struct platform_device *pdev)
+ {
+ 	struct rcar_usb_phy_priv *priv;
+ 	struct resource *res0, *res1;

commit 7690417db5085f0de03aa70b8ca01b0118e8a1b4
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:08 2012 -0500
+
+    usb: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Peter Korsgaard 
+    Cc: Alexander Shishkin 
+    Acked-by: Felipe Balbi 
+    Cc: Li Yang 
+    Cc: Alan Stern 
+    Cc: Wan ZongShun 
+    Cc: Ben Dooks 
+    Cc: Kukjin Kim 
+    Acked-by: Nicolas Ferre 
+    Acked-by: Peter Korsgaard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/c67x00/c67x00-drv.c b/drivers/usb/c67x00/c67x00-drv.c
+index 6f3b6e267398..855d538752c4 100644
+--- a/drivers/usb/c67x00/c67x00-drv.c
++++ b/drivers/usb/c67x00/c67x00-drv.c
+@@ -219,7 +219,7 @@ static int __devexit c67x00_drv_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver c67x00_driver = {
+ 	.probe	= c67x00_drv_probe,
+-	.remove	= __devexit_p(c67x00_drv_remove),
++	.remove	= c67x00_drv_remove,
+ 	.driver	= {
+ 		.owner = THIS_MODULE,
+ 		.name = "c67x00",
+diff --git a/drivers/usb/chipidea/ci13xxx_imx.c b/drivers/usb/chipidea/ci13xxx_imx.c
+index 0f5ca4bea17f..565973035ca8 100644
+--- a/drivers/usb/chipidea/ci13xxx_imx.c
++++ b/drivers/usb/chipidea/ci13xxx_imx.c
+@@ -252,7 +252,7 @@ MODULE_DEVICE_TABLE(of, ci13xxx_imx_dt_ids);
+ 
+ static struct platform_driver ci13xxx_imx_driver = {
+ 	.probe = ci13xxx_imx_probe,
+-	.remove = __devexit_p(ci13xxx_imx_remove),
++	.remove = ci13xxx_imx_remove,
+ 	.driver = {
+ 		.name = "imx_usb",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/usb/chipidea/ci13xxx_msm.c b/drivers/usb/chipidea/ci13xxx_msm.c
+index b01feb3be92e..406c5af2da5c 100644
+--- a/drivers/usb/chipidea/ci13xxx_msm.c
++++ b/drivers/usb/chipidea/ci13xxx_msm.c
+@@ -89,7 +89,7 @@ static int __devexit ci13xxx_msm_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver ci13xxx_msm_driver = {
+ 	.probe = ci13xxx_msm_probe,
+-	.remove = __devexit_p(ci13xxx_msm_remove),
++	.remove = ci13xxx_msm_remove,
+ 	.driver = { .name = "msm_hsusb", },
+ };
+ 
+diff --git a/drivers/usb/chipidea/ci13xxx_pci.c b/drivers/usb/chipidea/ci13xxx_pci.c
+index 918e14971f2b..e1cb2fb2ef33 100644
+--- a/drivers/usb/chipidea/ci13xxx_pci.c
++++ b/drivers/usb/chipidea/ci13xxx_pci.c
+@@ -147,7 +147,7 @@ static struct pci_driver ci13xxx_pci_driver = {
+ 	.name         =	UDC_DRIVER_NAME,
+ 	.id_table     =	ci13xxx_pci_id_table,
+ 	.probe        =	ci13xxx_pci_probe,
+-	.remove       =	__devexit_p(ci13xxx_pci_remove),
++	.remove       =	ci13xxx_pci_remove,
+ };
+ 
+ module_pci_driver(ci13xxx_pci_driver);
+diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
+index f69d029b4607..46f23f226ae2 100644
+--- a/drivers/usb/chipidea/core.c
++++ b/drivers/usb/chipidea/core.c
+@@ -523,7 +523,7 @@ static int __devexit ci_hdrc_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver ci_hdrc_driver = {
+ 	.probe	= ci_hdrc_probe,
+-	.remove	= __devexit_p(ci_hdrc_remove),
++	.remove	= ci_hdrc_remove,
+ 	.driver	= {
+ 		.name	= "ci_hdrc",
+ 	},
+diff --git a/drivers/usb/chipidea/usbmisc_imx6q.c b/drivers/usb/chipidea/usbmisc_imx6q.c
+index 416e3fc58fd0..81238a467296 100644
+--- a/drivers/usb/chipidea/usbmisc_imx6q.c
++++ b/drivers/usb/chipidea/usbmisc_imx6q.c
+@@ -136,7 +136,7 @@ static int __devexit usbmisc_imx6q_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver usbmisc_imx6q_driver = {
+ 	.probe = usbmisc_imx6q_probe,
+-	.remove = __devexit_p(usbmisc_imx6q_remove),
++	.remove = usbmisc_imx6q_remove,
+ 	.driver = {
+ 		.name = "usbmisc_imx6q",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
+index 516d4007dfce..cc5dac11d305 100644
+--- a/drivers/usb/dwc3/core.c
++++ b/drivers/usb/dwc3/core.c
+@@ -583,7 +583,7 @@ static int __devexit dwc3_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver dwc3_driver = {
+ 	.probe		= dwc3_probe,
+-	.remove		= __devexit_p(dwc3_remove),
++	.remove		= dwc3_remove,
+ 	.driver		= {
+ 		.name	= "dwc3",
+ 	},
+diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
+index dc35c5476f37..19a98184e580 100644
+--- a/drivers/usb/dwc3/dwc3-exynos.c
++++ b/drivers/usb/dwc3/dwc3-exynos.c
+@@ -196,7 +196,7 @@ MODULE_DEVICE_TABLE(of, exynos_dwc3_match);
+ 
+ static struct platform_driver dwc3_exynos_driver = {
+ 	.probe		= dwc3_exynos_probe,
+-	.remove		= __devexit_p(dwc3_exynos_remove),
++	.remove		= dwc3_exynos_remove,
+ 	.driver		= {
+ 		.name	= "exynos-dwc3",
+ 		.of_match_table = of_match_ptr(exynos_dwc3_match),
+diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
+index 900d435f41d1..afbc6e99188c 100644
+--- a/drivers/usb/dwc3/dwc3-omap.c
++++ b/drivers/usb/dwc3/dwc3-omap.c
+@@ -441,7 +441,7 @@ MODULE_DEVICE_TABLE(of, of_dwc3_matach);
+ 
+ static struct platform_driver dwc3_omap_driver = {
+ 	.probe		= dwc3_omap_probe,
+-	.remove		= __devexit_p(dwc3_omap_remove),
++	.remove		= dwc3_omap_remove,
+ 	.driver		= {
+ 		.name	= "omap-dwc3",
+ 		.of_match_table	= of_dwc3_matach,
+diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
+index 13962597f3fe..b3eeec7c6bc8 100644
+--- a/drivers/usb/dwc3/dwc3-pci.c
++++ b/drivers/usb/dwc3/dwc3-pci.c
+@@ -218,7 +218,7 @@ static struct pci_driver dwc3_pci_driver = {
+ 	.name		= "dwc3-pci",
+ 	.id_table	= dwc3_pci_id_table,
+ 	.probe		= dwc3_pci_probe,
+-	.remove		= __devexit_p(dwc3_pci_remove),
++	.remove		= dwc3_pci_remove,
+ };
+ 
+ MODULE_AUTHOR("Felipe Balbi ");
+diff --git a/drivers/usb/gadget/bcm63xx_udc.c b/drivers/usb/gadget/bcm63xx_udc.c
+index 9ca792224cd4..b44e43641d59 100644
+--- a/drivers/usb/gadget/bcm63xx_udc.c
++++ b/drivers/usb/gadget/bcm63xx_udc.c
+@@ -2450,7 +2450,7 @@ static int __devexit bcm63xx_udc_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver bcm63xx_udc_driver = {
+ 	.probe		= bcm63xx_udc_probe,
+-	.remove		= __devexit_p(bcm63xx_udc_remove),
++	.remove		= bcm63xx_udc_remove,
+ 	.driver		= {
+ 		.name	= DRV_MODULE_NAME,
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
+index b09452d6f33a..21db1f71d4ce 100644
+--- a/drivers/usb/gadget/fsl_qe_udc.c
++++ b/drivers/usb/gadget/fsl_qe_udc.c
+@@ -2735,7 +2735,7 @@ static struct platform_driver udc_driver = {
+ 		.of_match_table = qe_udc_match,
+ 	},
+ 	.probe          = qe_udc_probe,
+-	.remove         = __devexit_p(qe_udc_remove),
++	.remove         = qe_udc_remove,
+ #ifdef CONFIG_PM
+ 	.suspend        = qe_udc_suspend,
+ 	.resume         = qe_udc_resume,
+diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c
+index 74130f6c12c0..33deed6e7945 100644
+--- a/drivers/usb/gadget/hid.c
++++ b/drivers/usb/gadget/hid.c
+@@ -229,7 +229,7 @@ static __refdata struct usb_composite_driver hidg_driver = {
+ };
+ 
+ static struct platform_driver hidg_plat_driver = {
+-	.remove		= __devexit_p(hidg_plat_driver_remove),
++	.remove		= hidg_plat_driver_remove,
+ 	.driver		= {
+ 		.owner	= THIS_MODULE,
+ 		.name	= "hidg",
+diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c
+index d1cf1f4db16a..52ad15ce44ac 100644
+--- a/drivers/usb/gadget/lpc32xx_udc.c
++++ b/drivers/usb/gadget/lpc32xx_udc.c
+@@ -3447,7 +3447,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_udc_of_match);
+ #endif
+ 
+ static struct platform_driver lpc32xx_udc_driver = {
+-	.remove		= __devexit_p(lpc32xx_udc_remove),
++	.remove		= lpc32xx_udc_remove,
+ 	.shutdown	= lpc32xx_udc_shutdown,
+ 	.suspend	= lpc32xx_udc_suspend,
+ 	.resume		= lpc32xx_udc_resume,
+diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c
+index c009263a47e3..26c305321c40 100644
+--- a/drivers/usb/gadget/net2272.c
++++ b/drivers/usb/gadget/net2272.c
+@@ -2575,7 +2575,7 @@ static struct pci_driver net2272_pci_driver = {
+ 	.id_table = pci_ids,
+ 
+ 	.probe    = net2272_pci_probe,
+-	.remove   = __devexit_p(net2272_pci_remove),
++	.remove   = net2272_pci_remove,
+ };
+ 
+ static int net2272_pci_register(void)
+@@ -2678,7 +2678,7 @@ net2272_plat_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver net2272_plat_driver = {
+ 	.probe   = net2272_plat_probe,
+-	.remove  = __devexit_p(net2272_plat_remove),
++	.remove  = net2272_plat_remove,
+ 	.driver  = {
+ 		.name  = driver_name,
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
+index 2a4749c3eb3f..b5605ddfbd63 100644
+--- a/drivers/usb/gadget/omap_udc.c
++++ b/drivers/usb/gadget/omap_udc.c
+@@ -3060,7 +3060,7 @@ static int omap_udc_resume(struct platform_device *dev)
+ 
+ static struct platform_driver udc_driver = {
+ 	.probe		= omap_udc_probe,
+-	.remove		= __devexit_p(omap_udc_remove),
++	.remove		= omap_udc_remove,
+ 	.suspend	= omap_udc_suspend,
+ 	.resume		= omap_udc_resume,
+ 	.driver		= {
+diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
+index 6f696ee8b817..9fd6e5fdc350 100644
+--- a/drivers/usb/gadget/s3c-hsotg.c
++++ b/drivers/usb/gadget/s3c-hsotg.c
+@@ -3708,7 +3708,7 @@ static struct platform_driver s3c_hsotg_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= s3c_hsotg_probe,
+-	.remove		= __devexit_p(s3c_hsotg_remove),
++	.remove		= s3c_hsotg_remove,
+ 	.suspend	= s3c_hsotg_suspend,
+ 	.resume		= s3c_hsotg_resume,
+ };
+diff --git a/drivers/usb/host/bcma-hcd.c b/drivers/usb/host/bcma-hcd.c
+index 443da21d73ca..f5143a066add 100644
+--- a/drivers/usb/host/bcma-hcd.c
++++ b/drivers/usb/host/bcma-hcd.c
+@@ -316,7 +316,7 @@ static struct bcma_driver bcma_hcd_driver = {
+ 	.name		= KBUILD_MODNAME,
+ 	.id_table	= bcma_hcd_table,
+ 	.probe		= bcma_hcd_probe,
+-	.remove		= __devexit_p(bcma_hcd_remove),
++	.remove		= bcma_hcd_remove,
+ 	.shutdown	= bcma_hcd_shutdown,
+ 	.suspend	= bcma_hcd_suspend,
+ 	.resume		= bcma_hcd_resume,
+diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
+index d23321ec0e46..33f798ec1c7d 100644
+--- a/drivers/usb/host/ehci-atmel.c
++++ b/drivers/usb/host/ehci-atmel.c
+@@ -207,7 +207,7 @@ MODULE_DEVICE_TABLE(of, atmel_ehci_dt_ids);
+ 
+ static struct platform_driver ehci_atmel_driver = {
+ 	.probe		= ehci_atmel_drv_probe,
+-	.remove		= __devexit_p(ehci_atmel_drv_remove),
++	.remove		= ehci_atmel_drv_remove,
+ 	.shutdown	= usb_hcd_platform_shutdown,
+ 	.driver		= {
+ 		.name	= "atmel-ehci",
+diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
+index 7fa1ba4de789..e0acfd589a83 100644
+--- a/drivers/usb/host/ehci-msm.c
++++ b/drivers/usb/host/ehci-msm.c
+@@ -220,7 +220,7 @@ static const struct dev_pm_ops ehci_msm_dev_pm_ops = {
+ 
+ static struct platform_driver ehci_msm_driver = {
+ 	.probe	= ehci_msm_probe,
+-	.remove	= __devexit_p(ehci_msm_remove),
++	.remove	= ehci_msm_remove,
+ 	.driver = {
+ 		   .name = "msm_hsusb_host",
+ 		   .pm = &ehci_msm_dev_pm_ops,
+diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
+index f14c542b142f..b807648876be 100644
+--- a/drivers/usb/host/ehci-platform.c
++++ b/drivers/usb/host/ehci-platform.c
+@@ -196,7 +196,7 @@ static const struct dev_pm_ops ehci_platform_pm_ops = {
+ static struct platform_driver ehci_platform_driver = {
+ 	.id_table	= ehci_platform_table,
+ 	.probe		= ehci_platform_probe,
+-	.remove		= __devexit_p(ehci_platform_remove),
++	.remove		= ehci_platform_remove,
+ 	.shutdown	= usb_hcd_platform_shutdown,
+ 	.driver		= {
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c
+index abc178d21fe4..f90a8815f4a8 100644
+--- a/drivers/usb/host/ehci-s5p.c
++++ b/drivers/usb/host/ehci-s5p.c
+@@ -274,7 +274,7 @@ MODULE_DEVICE_TABLE(of, exynos_ehci_match);
+ 
+ static struct platform_driver s5p_ehci_driver = {
+ 	.probe		= s5p_ehci_probe,
+-	.remove		= __devexit_p(s5p_ehci_remove),
++	.remove		= s5p_ehci_remove,
+ 	.shutdown	= s5p_ehci_shutdown,
+ 	.driver = {
+ 		.name	= "s5p-ehci",
+diff --git a/drivers/usb/host/ehci-w90x900.c b/drivers/usb/host/ehci-w90x900.c
+index fdd7c4873cf2..7bcb8b2863de 100644
+--- a/drivers/usb/host/ehci-w90x900.c
++++ b/drivers/usb/host/ehci-w90x900.c
+@@ -166,7 +166,7 @@ static int __devexit ehci_w90x900_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver ehci_hcd_w90x900_driver = {
+ 	.probe  = ehci_w90x900_probe,
+-	.remove = __devexit_p(ehci_w90x900_remove),
++	.remove = ehci_w90x900_remove,
+ 	.driver = {
+ 		.name = "w90x900-ehci",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c
+index 7da1a26bed2e..92f4b99a3ab2 100644
+--- a/drivers/usb/host/fhci-hcd.c
++++ b/drivers/usb/host/fhci-hcd.c
+@@ -821,7 +821,7 @@ static struct platform_driver of_fhci_driver = {
+ 		.of_match_table = of_fhci_match,
+ 	},
+ 	.probe		= of_fhci_probe,
+-	.remove		= __devexit_p(of_fhci_remove),
++	.remove		= of_fhci_remove,
+ };
+ 
+ module_platform_driver(of_fhci_driver);
+diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
+index 1e771292383f..3a5c82f67232 100644
+--- a/drivers/usb/host/fsl-mph-dr-of.c
++++ b/drivers/usb/host/fsl-mph-dr-of.c
+@@ -336,7 +336,7 @@ static struct platform_driver fsl_usb2_mph_dr_driver = {
+ 		.of_match_table = fsl_usb2_mph_dr_of_match,
+ 	},
+ 	.probe	= fsl_usb2_mph_dr_of_probe,
+-	.remove	= __devexit_p(fsl_usb2_mph_dr_of_remove),
++	.remove	= fsl_usb2_mph_dr_of_remove,
+ };
+ 
+ module_platform_driver(fsl_usb2_mph_dr_driver);
+diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
+index 256326322cfd..1ad9d2007222 100644
+--- a/drivers/usb/host/isp1362-hcd.c
++++ b/drivers/usb/host/isp1362-hcd.c
+@@ -2856,7 +2856,7 @@ static int isp1362_resume(struct platform_device *pdev)
+ 
+ static struct platform_driver isp1362_driver = {
+ 	.probe = isp1362_probe,
+-	.remove = __devexit_p(isp1362_remove),
++	.remove = isp1362_remove,
+ 
+ 	.suspend = isp1362_suspend,
+ 	.resume = isp1362_resume,
+diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c
+index 958379f9de79..5fb3caee7706 100644
+--- a/drivers/usb/host/isp1760-if.c
++++ b/drivers/usb/host/isp1760-if.c
+@@ -432,7 +432,7 @@ static int __devexit isp1760_plat_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver isp1760_plat_driver = {
+ 	.probe	= isp1760_plat_probe,
+-	.remove	= __devexit_p(isp1760_plat_remove),
++	.remove	= isp1760_plat_remove,
+ 	.driver	= {
+ 		.name	= "isp1760",
+ 	},
+diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
+index 908d84af1dd7..e4480029bc0c 100644
+--- a/drivers/usb/host/ohci-at91.c
++++ b/drivers/usb/host/ohci-at91.c
+@@ -717,7 +717,7 @@ MODULE_ALIAS("platform:at91_ohci");
+ 
+ static struct platform_driver ohci_hcd_at91_driver = {
+ 	.probe		= ohci_hcd_at91_drv_probe,
+-	.remove		= __devexit_p(ohci_hcd_at91_drv_remove),
++	.remove		= ohci_hcd_at91_drv_remove,
+ 	.shutdown	= usb_hcd_platform_shutdown,
+ 	.suspend	= ohci_hcd_at91_drv_suspend,
+ 	.resume		= ohci_hcd_at91_drv_resume,
+diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
+index 6a30fc5bec93..2f673e872b7d 100644
+--- a/drivers/usb/host/ohci-exynos.c
++++ b/drivers/usb/host/ohci-exynos.c
+@@ -275,7 +275,7 @@ MODULE_DEVICE_TABLE(of, exynos_ohci_match);
+ 
+ static struct platform_driver exynos_ohci_driver = {
+ 	.probe		= exynos_ohci_probe,
+-	.remove		= __devexit_p(exynos_ohci_remove),
++	.remove		= exynos_ohci_remove,
+ 	.shutdown	= exynos_ohci_shutdown,
+ 	.driver = {
+ 		.name	= "exynos-ohci",
+diff --git a/drivers/usb/host/ohci-jz4740.c b/drivers/usb/host/ohci-jz4740.c
+index 931d588c3fb5..b4921b713557 100644
+--- a/drivers/usb/host/ohci-jz4740.c
++++ b/drivers/usb/host/ohci-jz4740.c
+@@ -266,7 +266,7 @@ static __devexit int jz4740_ohci_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver ohci_hcd_jz4740_driver = {
+ 	.probe = jz4740_ohci_probe,
+-	.remove = __devexit_p(jz4740_ohci_remove),
++	.remove = jz4740_ohci_remove,
+ 	.driver = {
+ 		.name = "jz4740-ohci",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c
+index 1b8133b6e451..6bee6f191c86 100644
+--- a/drivers/usb/host/ohci-omap3.c
++++ b/drivers/usb/host/ohci-omap3.c
+@@ -232,7 +232,7 @@ static void ohci_hcd_omap3_shutdown(struct platform_device *pdev)
+ 
+ static struct platform_driver ohci_hcd_omap3_driver = {
+ 	.probe		= ohci_hcd_omap3_probe,
+-	.remove		= __devexit_p(ohci_hcd_omap3_remove),
++	.remove		= ohci_hcd_omap3_remove,
+ 	.shutdown	= ohci_hcd_omap3_shutdown,
+ 	.driver		= {
+ 		.name	= "ohci-omap3",
+diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
+index bda4e0bb8ab3..ffe6c9808473 100644
+--- a/drivers/usb/host/ohci-platform.c
++++ b/drivers/usb/host/ohci-platform.c
+@@ -214,7 +214,7 @@ static const struct dev_pm_ops ohci_platform_pm_ops = {
+ static struct platform_driver ohci_platform_driver = {
+ 	.id_table	= ohci_platform_table,
+ 	.probe		= ohci_platform_probe,
+-	.remove		= __devexit_p(ohci_platform_remove),
++	.remove		= ohci_platform_remove,
+ 	.shutdown	= usb_hcd_platform_shutdown,
+ 	.driver		= {
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
+index e84190f25c6b..5c5c017850d8 100644
+--- a/drivers/usb/host/ohci-s3c2410.c
++++ b/drivers/usb/host/ohci-s3c2410.c
+@@ -524,7 +524,7 @@ static const struct dev_pm_ops ohci_hcd_s3c2410_pm_ops = {
+ 
+ static struct platform_driver ohci_hcd_s3c2410_driver = {
+ 	.probe		= ohci_hcd_s3c2410_drv_probe,
+-	.remove		= __devexit_p(ohci_hcd_s3c2410_drv_remove),
++	.remove		= ohci_hcd_s3c2410_drv_remove,
+ 	.shutdown	= usb_hcd_platform_shutdown,
+ 	.driver		= {
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c
+index 2c9ab8f126d4..94c6c550a953 100644
+--- a/drivers/usb/host/ohci-tmio.c
++++ b/drivers/usb/host/ohci-tmio.c
+@@ -363,7 +363,7 @@ static int ohci_hcd_tmio_drv_resume(struct platform_device *dev)
+ 
+ static struct platform_driver ohci_hcd_tmio_driver = {
+ 	.probe		= ohci_hcd_tmio_drv_probe,
+-	.remove		= __devexit_p(ohci_hcd_tmio_drv_remove),
++	.remove		= ohci_hcd_tmio_drv_remove,
+ 	.shutdown	= usb_hcd_platform_shutdown,
+ 	.suspend	= ohci_hcd_tmio_drv_suspend,
+ 	.resume		= ohci_hcd_tmio_drv_resume,
+diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
+index b3eea0ba97a9..4e0436fc334d 100644
+--- a/drivers/usb/host/r8a66597-hcd.c
++++ b/drivers/usb/host/r8a66597-hcd.c
+@@ -2532,7 +2532,7 @@ static int __devinit r8a66597_probe(struct platform_device *pdev)
+ 
+ static struct platform_driver r8a66597_driver = {
+ 	.probe =	r8a66597_probe,
+-	.remove =	__devexit_p(r8a66597_remove),
++	.remove =	r8a66597_remove,
+ 	.driver		= {
+ 		.name = (char *) hcd_name,
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
+index 619b05f42d4f..15f20de3e05d 100644
+--- a/drivers/usb/host/sl811-hcd.c
++++ b/drivers/usb/host/sl811-hcd.c
+@@ -1808,7 +1808,7 @@ sl811h_resume(struct platform_device *dev)
+ /* this driver is exported so sl811_cs can depend on it */
+ struct platform_driver sl811h_driver = {
+ 	.probe =	sl811h_probe,
+-	.remove =	__devexit_p(sl811h_remove),
++	.remove =	sl811h_remove,
+ 
+ 	.suspend =	sl811h_suspend,
+ 	.resume =	sl811h_resume,
+diff --git a/drivers/usb/host/ssb-hcd.c b/drivers/usb/host/ssb-hcd.c
+index c2a29faba076..4dc9a09dc346 100644
+--- a/drivers/usb/host/ssb-hcd.c
++++ b/drivers/usb/host/ssb-hcd.c
+@@ -261,7 +261,7 @@ static struct ssb_driver ssb_hcd_driver = {
+ 	.name		= KBUILD_MODNAME,
+ 	.id_table	= ssb_hcd_table,
+ 	.probe		= ssb_hcd_probe,
+-	.remove		= __devexit_p(ssb_hcd_remove),
++	.remove		= ssb_hcd_remove,
+ 	.shutdown	= ssb_hcd_shutdown,
+ 	.suspend	= ssb_hcd_suspend,
+ 	.resume		= ssb_hcd_resume,
+diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
+index dbbd1ba25224..8836898d64de 100644
+--- a/drivers/usb/host/u132-hcd.c
++++ b/drivers/usb/host/u132-hcd.c
+@@ -3212,7 +3212,7 @@ static int u132_resume(struct platform_device *pdev)
+ */
+ static struct platform_driver u132_platform_driver = {
+ 	.probe = u132_probe,
+-	.remove = __devexit_p(u132_remove),
++	.remove = u132_remove,
+ 	.suspend = u132_suspend,
+ 	.resume = u132_resume,
+ 	.driver = {
+diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c
+index 3baccf765418..49e8ce7ec26b 100644
+--- a/drivers/usb/musb/am35x.c
++++ b/drivers/usb/musb/am35x.c
+@@ -629,7 +629,7 @@ static struct dev_pm_ops am35x_pm_ops = {
+ 
+ static struct platform_driver am35x_driver = {
+ 	.probe		= am35x_probe,
+-	.remove		= __devexit_p(am35x_remove),
++	.remove		= am35x_remove,
+ 	.driver		= {
+ 		.name	= "musb-am35x",
+ 		.pm	= DEV_PM_OPS,
+diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
+index 67b8ae704e9a..51ace9bf73df 100644
+--- a/drivers/usb/musb/da8xx.c
++++ b/drivers/usb/musb/da8xx.c
+@@ -569,7 +569,7 @@ static int __devexit da8xx_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver da8xx_driver = {
+ 	.probe		= da8xx_probe,
+-	.remove		= __devexit_p(da8xx_remove),
++	.remove		= da8xx_remove,
+ 	.driver		= {
+ 		.name	= "musb-da8xx",
+ 	},
+diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
+index b3c0a943950c..e01087b44e09 100644
+--- a/drivers/usb/musb/davinci.c
++++ b/drivers/usb/musb/davinci.c
+@@ -601,7 +601,7 @@ static int __devexit davinci_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver davinci_driver = {
+ 	.probe		= davinci_probe,
+-	.remove		= __devexit_p(davinci_remove),
++	.remove		= davinci_remove,
+ 	.driver		= {
+ 		.name	= "musb-davinci",
+ 	},
+diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
+index 774d8154a286..69cfa18bb2df 100644
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -2288,7 +2288,7 @@ static struct platform_driver musb_driver = {
+ 		.pm		= MUSB_DEV_PM_OPS,
+ 	},
+ 	.probe		= musb_probe,
+-	.remove		= __devexit_p(musb_remove),
++	.remove		= musb_remove,
+ 	.shutdown	= musb_shutdown,
+ };
+ 
+diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
+index b108473e4d5f..80e2b03965c8 100644
+--- a/drivers/usb/musb/musb_dsps.c
++++ b/drivers/usb/musb/musb_dsps.c
+@@ -767,7 +767,7 @@ MODULE_DEVICE_TABLE(of, musb_dsps_of_match);
+ 
+ static struct platform_driver dsps_usbss_driver = {
+ 	.probe		= dsps_probe,
+-	.remove         = __devexit_p(dsps_remove),
++	.remove         = dsps_remove,
+ 	.driver         = {
+ 		.name   = "musb-dsps",
+ 		.pm	= &dsps_pm_ops,
+diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
+index 32f531e7a2e6..1150b4b6a090 100644
+--- a/drivers/usb/musb/omap2430.c
++++ b/drivers/usb/musb/omap2430.c
+@@ -674,7 +674,7 @@ MODULE_DEVICE_TABLE(of, omap2430_id_table);
+ 
+ static struct platform_driver omap2430_driver = {
+ 	.probe		= omap2430_probe,
+-	.remove		= __devexit_p(omap2430_remove),
++	.remove		= omap2430_remove,
+ 	.driver		= {
+ 		.name	= "musb-omap2430",
+ 		.pm	= DEV_PM_OPS,
+diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
+index 812719b683d1..b816517d8cbf 100644
+--- a/drivers/usb/musb/tusb6010.c
++++ b/drivers/usb/musb/tusb6010.c
+@@ -1227,7 +1227,7 @@ static int __devexit tusb_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver tusb_driver = {
+ 	.probe		= tusb_probe,
+-	.remove		= __devexit_p(tusb_remove),
++	.remove		= tusb_remove,
+ 	.driver		= {
+ 		.name	= "musb-tusb",
+ 	},
+diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c
+index 286f1be6594a..1d815578dde5 100644
+--- a/drivers/usb/musb/ux500.c
++++ b/drivers/usb/musb/ux500.c
+@@ -216,7 +216,7 @@ static const struct dev_pm_ops ux500_pm_ops = {
+ 
+ static struct platform_driver ux500_driver = {
+ 	.probe		= ux500_probe,
+-	.remove		= __devexit_p(ux500_remove),
++	.remove		= ux500_remove,
+ 	.driver		= {
+ 		.name	= "musb-ux500",
+ 		.pm	= DEV_PM_OPS,
+diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c
+index ae8ad561f083..62ea0c23c455 100644
+--- a/drivers/usb/otg/ab8500-usb.c
++++ b/drivers/usb/otg/ab8500-usb.c
+@@ -571,7 +571,7 @@ static int __devexit ab8500_usb_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver ab8500_usb_driver = {
+ 	.probe		= ab8500_usb_probe,
+-	.remove		= __devexit_p(ab8500_usb_remove),
++	.remove		= ab8500_usb_remove,
+ 	.driver		= {
+ 		.name	= "ab8500-usb",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/otg/fsl_otg.c
+index c19d1d7173a9..77dad188d2d9 100644
+--- a/drivers/usb/otg/fsl_otg.c
++++ b/drivers/usb/otg/fsl_otg.c
+@@ -1169,7 +1169,7 @@ static int __devexit fsl_otg_remove(struct platform_device *pdev)
+ 
+ struct platform_driver fsl_otg_driver = {
+ 	.probe = fsl_otg_probe,
+-	.remove = __devexit_p(fsl_otg_remove),
++	.remove = fsl_otg_remove,
+ 	.driver = {
+ 		.name = driver_name,
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
+index 9f5fc906041a..eef0dd276e1b 100644
+--- a/drivers/usb/otg/msm_otg.c
++++ b/drivers/usb/otg/msm_otg.c
+@@ -1746,7 +1746,7 @@ static const struct dev_pm_ops msm_otg_dev_pm_ops = {
+ #endif
+ 
+ static struct platform_driver msm_otg_driver = {
+-	.remove = __devexit_p(msm_otg_remove),
++	.remove = msm_otg_remove,
+ 	.driver = {
+ 		.name = DRIVER_NAME,
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/usb/otg/mxs-phy.c b/drivers/usb/otg/mxs-phy.c
+index 9a3caeecc508..001fdde12d7a 100644
+--- a/drivers/usb/otg/mxs-phy.c
++++ b/drivers/usb/otg/mxs-phy.c
+@@ -164,7 +164,7 @@ MODULE_DEVICE_TABLE(of, mxs_phy_dt_ids);
+ 
+ static struct platform_driver mxs_phy_driver = {
+ 	.probe = mxs_phy_probe,
+-	.remove = __devexit_p(mxs_phy_remove),
++	.remove = mxs_phy_remove,
+ 	.driver = {
+ 		.name = DRIVER_NAME,
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c
+index e52e35e7adaf..0502c2405915 100644
+--- a/drivers/usb/otg/nop-usb-xceiv.c
++++ b/drivers/usb/otg/nop-usb-xceiv.c
+@@ -156,7 +156,7 @@ static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver nop_usb_xceiv_driver = {
+ 	.probe		= nop_usb_xceiv_probe,
+-	.remove		= __devexit_p(nop_usb_xceiv_remove),
++	.remove		= nop_usb_xceiv_remove,
+ 	.driver		= {
+ 		.name	= "nop_usb_xceiv",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/usb/phy/mv_u3d_phy.c b/drivers/usb/phy/mv_u3d_phy.c
+index 9f1c5d3c60ec..80cf57ef5502 100644
+--- a/drivers/usb/phy/mv_u3d_phy.c
++++ b/drivers/usb/phy/mv_u3d_phy.c
+@@ -331,7 +331,7 @@ static int __exit mv_u3d_phy_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver mv_u3d_phy_driver = {
+ 	.probe		= mv_u3d_phy_probe,
+-	.remove		= __devexit_p(mv_u3d_phy_remove),
++	.remove		= mv_u3d_phy_remove,
+ 	.driver		= {
+ 		.name	= "mv-u3d-phy",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/usb/phy/omap-usb2.c b/drivers/usb/phy/omap-usb2.c
+index 15ab3d6f2e8c..f1ed872dd969 100644
+--- a/drivers/usb/phy/omap-usb2.c
++++ b/drivers/usb/phy/omap-usb2.c
+@@ -254,7 +254,7 @@ MODULE_DEVICE_TABLE(of, omap_usb2_id_table);
+ 
+ static struct platform_driver omap_usb2_driver = {
+ 	.probe		= omap_usb2_probe,
+-	.remove		= __devexit_p(omap_usb2_remove),
++	.remove		= omap_usb2_remove,
+ 	.driver		= {
+ 		.name	= "omap-usb2",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/usb/phy/rcar-phy.c b/drivers/usb/phy/rcar-phy.c
+index 792f505d630c..703a29586a7a 100644
+--- a/drivers/usb/phy/rcar-phy.c
++++ b/drivers/usb/phy/rcar-phy.c
+@@ -210,7 +210,7 @@ static struct platform_driver rcar_usb_phy_driver = {
+ 		.name	= "rcar_usb_phy",
+ 	},
+ 	.probe		= rcar_usb_phy_probe,
+-	.remove		= __devexit_p(rcar_usb_phy_remove),
++	.remove		= rcar_usb_phy_remove,
+ };
+ 
+ module_platform_driver(rcar_usb_phy_driver);
+diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c
+index 3bf922ab045e..2aa7c1a38ce3 100644
+--- a/drivers/usb/renesas_usbhs/common.c
++++ b/drivers/usb/renesas_usbhs/common.c
+@@ -636,7 +636,7 @@ static struct platform_driver renesas_usbhs_driver = {
+ 		.pm	= &usbhsc_pm_ops,
+ 	},
+ 	.probe		= usbhs_probe,
+-	.remove		= __devexit_p(usbhs_remove),
++	.remove		= usbhs_remove,
+ };
+ 
+ module_platform_driver(renesas_usbhs_driver);

commit 2bd6a021e887c675116ff8cdacc3af49999a2224
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:19:16 2012 -0500
+
+    usb-core: remove CONFIG_HOTPLUG ifdefs
+    
+    Remove conditional code based on CONFIG_HOTPLUG being false.  It's
+    always on now in preparation of it going away as an option.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 6056db7af410..88dde95b6795 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -32,8 +32,6 @@
+ #include "usb.h"
+ 
+ 
+-#ifdef CONFIG_HOTPLUG
+-
+ /*
+  * Adds a new dynamic USBdevice ID to this driver,
+  * and cause the driver to probe for all devices again.
+@@ -194,20 +192,6 @@ static void usb_free_dynids(struct usb_driver *usb_drv)
+ 	}
+ 	spin_unlock(&usb_drv->dynids.lock);
+ }
+-#else
+-static inline int usb_create_newid_files(struct usb_driver *usb_drv)
+-{
+-	return 0;
+-}
+-
+-static void usb_remove_newid_files(struct usb_driver *usb_drv)
+-{
+-}
+-
+-static inline void usb_free_dynids(struct usb_driver *usb_drv)
+-{
+-}
+-#endif
+ 
+ static const struct usb_device_id *usb_match_dynamic_id(struct usb_interface *intf,
+ 							struct usb_driver *drv)
+@@ -790,7 +774,6 @@ static int usb_device_match(struct device *dev, struct device_driver *drv)
+ 	return 0;
+ }
+ 
+-#ifdef	CONFIG_HOTPLUG
+ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
+ {
+ 	struct usb_device *usb_dev;
+@@ -832,14 +815,6 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
+ 	return 0;
+ }
+ 
+-#else
+-
+-static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
+-{
+-	return -ENODEV;
+-}
+-#endif	/* CONFIG_HOTPLUG */
+-
+ /**
+  * usb_register_device_driver - register a USB device (not interface) driver
+  * @new_udriver: USB operations for the device driver
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index a557658f3223..73c5d1a04135 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1540,7 +1540,6 @@ static void usb_release_interface(struct device *dev)
+ 	kfree(intf);
+ }
+ 
+-#ifdef	CONFIG_HOTPLUG
+ static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
+ {
+ 	struct usb_device *usb_dev;
+@@ -1575,14 +1574,6 @@ static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
+ 	return 0;
+ }
+ 
+-#else
+-
+-static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
+-{
+-	return -ENODEV;
+-}
+-#endif	/* CONFIG_HOTPLUG */
+-
+ struct device_type usb_if_device_type = {
+ 	.name =		"usb_interface",
+ 	.release =	usb_release_interface,
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 7d3de09a82e4..f81b92572735 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -233,7 +233,6 @@ static void usb_release_dev(struct device *dev)
+ 	kfree(udev);
+ }
+ 
+-#ifdef	CONFIG_HOTPLUG
+ static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
+ {
+ 	struct usb_device *usb_dev;
+@@ -249,14 +248,6 @@ static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
+ 	return 0;
+ }
+ 
+-#else
+-
+-static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
+-{
+-	return -ENODEV;
+-}
+-#endif	/* CONFIG_HOTPLUG */
+-
+ #ifdef	CONFIG_PM
+ 
+ /* USB device Power-Management thunks.
+diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
+index c15f2e7cefc7..37decb13d7eb 100644
+--- a/drivers/usb/serial/bus.c
++++ b/drivers/usb/serial/bus.c
+@@ -121,7 +121,6 @@ static int usb_serial_device_remove(struct device *dev)
+ 	return retval;
+ }
+ 
+-#ifdef CONFIG_HOTPLUG
+ static ssize_t store_new_id(struct device_driver *driver,
+ 			    const char *buf, size_t count)
+ {
+@@ -159,15 +158,6 @@ static void free_dynids(struct usb_serial_driver *drv)
+ 	spin_unlock(&drv->dynids.lock);
+ }
+ 
+-#else
+-static struct driver_attribute drv_attrs[] = {
+-	__ATTR_NULL,
+-};
+-static inline void free_dynids(struct usb_serial_driver *drv)
+-{
+-}
+-#endif
+-
+ struct bus_type usb_serial_bus_type = {
+ 	.name =		"usb-serial",
+ 	.match =	usb_serial_device_match,

commit 39af33fc458543fd6daaf154e109eba22ab89a8f
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:26 2012 -0500
+
+    char: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: David Airlie 
+    Cc: Olof Johansson 
+    Cc: Mattia Dongili 
+    Cc: Kent Yoder 
+    Cc: Rajiv Andrade 
+    Cc: Marcel Selhorst 
+    Cc: Sirrix AG 
+    Cc: linuxppc-dev@lists.ozlabs.org
+    Cc: linux-arm-kernel@lists.infradead.org
+    Cc: openipmi-developer@lists.sourceforge.net
+    Cc: platform-driver-x86@vger.kernel.org
+    Cc: tpmdd-devel@lists.sourceforge.net
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
+index 9c022df134af..478493543b32 100644
+--- a/drivers/char/agp/ali-agp.c
++++ b/drivers/char/agp/ali-agp.c
+@@ -374,7 +374,7 @@ static int __devinit agp_ali_probe(struct pci_dev *pdev,
+ 	return agp_add_bridge(bridge);
+ }
+ 
+-static void __devexit agp_ali_remove(struct pci_dev *pdev)
++static void agp_ali_remove(struct pci_dev *pdev)
+ {
+ 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+ 
+diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
+index 3c7a2653f161..1b2101160e98 100644
+--- a/drivers/char/agp/amd-k7-agp.c
++++ b/drivers/char/agp/amd-k7-agp.c
+@@ -480,7 +480,7 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev,
+ 	return agp_add_bridge(bridge);
+ }
+ 
+-static void __devexit agp_amdk7_remove(struct pci_dev *pdev)
++static void agp_amdk7_remove(struct pci_dev *pdev)
+ {
+ 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+ 
+diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
+index 444f8b6ab411..061d46209b1a 100644
+--- a/drivers/char/agp/amd64-agp.c
++++ b/drivers/char/agp/amd64-agp.c
+@@ -579,7 +579,7 @@ static int __devinit agp_amd64_probe(struct pci_dev *pdev,
+ 	return 0;
+ }
+ 
+-static void __devexit agp_amd64_remove(struct pci_dev *pdev)
++static void agp_amd64_remove(struct pci_dev *pdev)
+ {
+ 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+ 
+diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
+index d1c4c2340713..ed0433576e74 100644
+--- a/drivers/char/agp/ati-agp.c
++++ b/drivers/char/agp/ati-agp.c
+@@ -533,7 +533,7 @@ static int __devinit agp_ati_probe(struct pci_dev *pdev,
+ 	return agp_add_bridge(bridge);
+ }
+ 
+-static void __devexit agp_ati_remove(struct pci_dev *pdev)
++static void agp_ati_remove(struct pci_dev *pdev)
+ {
+ 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+ 
+diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c
+index d607f53d8afc..55f3e33a309f 100644
+--- a/drivers/char/agp/efficeon-agp.c
++++ b/drivers/char/agp/efficeon-agp.c
+@@ -407,7 +407,7 @@ static int __devinit agp_efficeon_probe(struct pci_dev *pdev,
+ 	return agp_add_bridge(bridge);
+ }
+ 
+-static void __devexit agp_efficeon_remove(struct pci_dev *pdev)
++static void agp_efficeon_remove(struct pci_dev *pdev)
+ {
+ 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+ 
+diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c
+index 75b763cb3ea1..d328b662e50d 100644
+--- a/drivers/char/agp/i460-agp.c
++++ b/drivers/char/agp/i460-agp.c
+@@ -611,7 +611,7 @@ static int __devinit agp_intel_i460_probe(struct pci_dev *pdev,
+ 	return agp_add_bridge(bridge);
+ }
+ 
+-static void __devexit agp_intel_i460_remove(struct pci_dev *pdev)
++static void agp_intel_i460_remove(struct pci_dev *pdev)
+ {
+ 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+ 
+diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
+index b130df0a1958..f3a8f52b5a00 100644
+--- a/drivers/char/agp/intel-agp.c
++++ b/drivers/char/agp/intel-agp.c
+@@ -819,7 +819,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit agp_intel_remove(struct pci_dev *pdev)
++static void agp_intel_remove(struct pci_dev *pdev)
+ {
+ 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+ 
+diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c
+index b9734a978186..66e0868000f4 100644
+--- a/drivers/char/agp/nvidia-agp.c
++++ b/drivers/char/agp/nvidia-agp.c
+@@ -388,7 +388,7 @@ static int __devinit agp_nvidia_probe(struct pci_dev *pdev,
+ 	return agp_add_bridge(bridge);
+ }
+ 
+-static void __devexit agp_nvidia_remove(struct pci_dev *pdev)
++static void agp_nvidia_remove(struct pci_dev *pdev)
+ {
+ 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+ 
+diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c
+index 3a5af2f9b015..a18791d7718a 100644
+--- a/drivers/char/agp/sgi-agp.c
++++ b/drivers/char/agp/sgi-agp.c
+@@ -327,7 +327,7 @@ static int __devinit agp_sgi_init(void)
+ 	return 0;
+ }
+ 
+-static void __devexit agp_sgi_cleanup(void)
++static void agp_sgi_cleanup(void)
+ {
+ 	kfree(sgi_tioca_agp_bridges);
+ 	sgi_tioca_agp_bridges = NULL;
+diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c
+index c93c9e5ee2c2..93d1d31f9d0c 100644
+--- a/drivers/char/agp/sis-agp.c
++++ b/drivers/char/agp/sis-agp.c
+@@ -211,7 +211,7 @@ static int __devinit agp_sis_probe(struct pci_dev *pdev,
+ 	return agp_add_bridge(bridge);
+ }
+ 
+-static void __devexit agp_sis_remove(struct pci_dev *pdev)
++static void agp_sis_remove(struct pci_dev *pdev)
+ {
+ 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+ 
+diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
+index f02f9b07fd4c..26020fb8d7a9 100644
+--- a/drivers/char/agp/sworks-agp.c
++++ b/drivers/char/agp/sworks-agp.c
+@@ -518,7 +518,7 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev,
+ 	return agp_add_bridge(bridge);
+ }
+ 
+-static void __devexit agp_serverworks_remove(struct pci_dev *pdev)
++static void agp_serverworks_remove(struct pci_dev *pdev)
+ {
+ 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+ 
+diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c
+index af02da4da9e3..011967ad3eed 100644
+--- a/drivers/char/agp/uninorth-agp.c
++++ b/drivers/char/agp/uninorth-agp.c
+@@ -663,7 +663,7 @@ static int __devinit agp_uninorth_probe(struct pci_dev *pdev,
+ 	return agp_add_bridge(bridge);
+ }
+ 
+-static void __devexit agp_uninorth_remove(struct pci_dev *pdev)
++static void agp_uninorth_remove(struct pci_dev *pdev)
+ {
+ 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+ 
+diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
+index 97706834bae1..6818595bb863 100644
+--- a/drivers/char/agp/via-agp.c
++++ b/drivers/char/agp/via-agp.c
+@@ -485,7 +485,7 @@ static int __devinit agp_via_probe(struct pci_dev *pdev,
+ 	return agp_add_bridge(bridge);
+ }
+ 
+-static void __devexit agp_via_remove(struct pci_dev *pdev)
++static void agp_via_remove(struct pci_dev *pdev)
+ {
+ 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+ 
+diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c
+index 731c9046cf7b..5a4a6e70478b 100644
+--- a/drivers/char/hw_random/atmel-rng.c
++++ b/drivers/char/hw_random/atmel-rng.c
+@@ -98,7 +98,7 @@ static int atmel_trng_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit atmel_trng_remove(struct platform_device *pdev)
++static int atmel_trng_remove(struct platform_device *pdev)
+ {
+ 	struct atmel_trng *trng = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/char/hw_random/bcm63xx-rng.c b/drivers/char/hw_random/bcm63xx-rng.c
+index aec6a4277caa..ae95bcb18d4a 100644
+--- a/drivers/char/hw_random/bcm63xx-rng.c
++++ b/drivers/char/hw_random/bcm63xx-rng.c
+@@ -145,7 +145,7 @@ static int __devinit bcm63xx_rng_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit bcm63xx_rng_remove(struct platform_device *pdev)
++static int bcm63xx_rng_remove(struct platform_device *pdev)
+ {
+ 	struct hwrng *rng = platform_get_drvdata(pdev);
+ 	struct bcm63xx_rng_priv *priv = to_rng_priv(rng);
+diff --git a/drivers/char/hw_random/exynos-rng.c b/drivers/char/hw_random/exynos-rng.c
+index 232ba9ce579c..bdc852ea7632 100644
+--- a/drivers/char/hw_random/exynos-rng.c
++++ b/drivers/char/hw_random/exynos-rng.c
+@@ -134,7 +134,7 @@ static int __devinit exynos_rng_probe(struct platform_device *pdev)
+ 	return hwrng_register(&exynos_rng->rng);
+ }
+ 
+-static int __devexit exynos_rng_remove(struct platform_device *pdev)
++static int exynos_rng_remove(struct platform_device *pdev)
+ {
+ 	struct exynos_rng *exynos_rng = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c
+index fd57d8a9faff..d68a72a08b51 100644
+--- a/drivers/char/hw_random/n2-drv.c
++++ b/drivers/char/hw_random/n2-drv.c
+@@ -719,7 +719,7 @@ static int __devinit n2rng_probe(struct platform_device *op)
+ 	return err;
+ }
+ 
+-static int __devexit n2rng_remove(struct platform_device *op)
++static int n2rng_remove(struct platform_device *op)
+ {
+ 	struct n2rng *np = dev_get_drvdata(&op->dev);
+ 
+diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c
+index 3a632673aed5..a1f70407cc9e 100644
+--- a/drivers/char/hw_random/pasemi-rng.c
++++ b/drivers/char/hw_random/pasemi-rng.c
+@@ -122,7 +122,7 @@ static int __devinit rng_probe(struct platform_device *ofdev)
+ 	return err;
+ }
+ 
+-static int __devexit rng_remove(struct platform_device *dev)
++static int rng_remove(struct platform_device *dev)
+ {
+ 	void __iomem *rng_regs = (void __iomem *)pasemi_rng.priv;
+ 
+diff --git a/drivers/char/hw_random/picoxcell-rng.c b/drivers/char/hw_random/picoxcell-rng.c
+index 97bd891422c7..d4b24c1dd48e 100644
+--- a/drivers/char/hw_random/picoxcell-rng.c
++++ b/drivers/char/hw_random/picoxcell-rng.c
+@@ -151,7 +151,7 @@ static int picoxcell_trng_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit picoxcell_trng_remove(struct platform_device *pdev)
++static int picoxcell_trng_remove(struct platform_device *pdev)
+ {
+ 	hwrng_unregister(&picoxcell_trng);
+ 	clk_disable(rng_clk);
+diff --git a/drivers/char/hw_random/ppc4xx-rng.c b/drivers/char/hw_random/ppc4xx-rng.c
+index c51762c13031..af6506a69cd9 100644
+--- a/drivers/char/hw_random/ppc4xx-rng.c
++++ b/drivers/char/hw_random/ppc4xx-rng.c
+@@ -111,7 +111,7 @@ static int __devinit ppc4xx_rng_probe(struct platform_device *dev)
+ 	return err;
+ }
+ 
+-static int __devexit ppc4xx_rng_remove(struct platform_device *dev)
++static int ppc4xx_rng_remove(struct platform_device *dev)
+ {
+ 	void __iomem *rng_regs = (void __iomem *) ppc4xx_rng.priv;
+ 
+diff --git a/drivers/char/hw_random/timeriomem-rng.c b/drivers/char/hw_random/timeriomem-rng.c
+index f1a1618db1fb..3a1abc9417e4 100644
+--- a/drivers/char/hw_random/timeriomem-rng.c
++++ b/drivers/char/hw_random/timeriomem-rng.c
+@@ -130,7 +130,7 @@ static int __devinit timeriomem_rng_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit timeriomem_rng_remove(struct platform_device *pdev)
++static int timeriomem_rng_remove(struct platform_device *pdev)
+ {
+ 	del_timer_sync(&timeriomem_rng_timer);
+ 	hwrng_unregister(&timeriomem_rng_ops);
+diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c
+index 5708299507d0..621f595f1a98 100644
+--- a/drivers/char/hw_random/virtio-rng.c
++++ b/drivers/char/hw_random/virtio-rng.c
+@@ -119,7 +119,7 @@ static int virtrng_probe(struct virtio_device *vdev)
+ 	return probe_common(vdev);
+ }
+ 
+-static void __devexit virtrng_remove(struct virtio_device *vdev)
++static void virtrng_remove(struct virtio_device *vdev)
+ {
+ 	remove_common(vdev);
+ }
+diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
+index e55a7ad8ef18..20ab5b3a8915 100644
+--- a/drivers/char/ipmi/ipmi_si_intf.c
++++ b/drivers/char/ipmi/ipmi_si_intf.c
+@@ -2228,7 +2228,7 @@ static int ipmi_pnp_probe(struct pnp_dev *dev,
+ 	return -EINVAL;
+ }
+ 
+-static void __devexit ipmi_pnp_remove(struct pnp_dev *dev)
++static void ipmi_pnp_remove(struct pnp_dev *dev)
+ {
+ 	struct smi_info *info = pnp_get_drvdata(dev);
+ 
+@@ -2529,7 +2529,7 @@ static int ipmi_pci_probe(struct pci_dev *pdev,
+ 	return 0;
+ }
+ 
+-static void __devexit ipmi_pci_remove(struct pci_dev *pdev)
++static void ipmi_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct smi_info *info = pci_get_drvdata(pdev);
+ 	cleanup_one_si(info);
+@@ -2635,7 +2635,7 @@ static int ipmi_probe(struct platform_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devexit ipmi_remove(struct platform_device *dev)
++static int ipmi_remove(struct platform_device *dev)
+ {
+ #ifdef CONFIG_OF
+ 	cleanup_one_si(dev_get_drvdata(&dev->dev));
+diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
+index 861efa48c696..d780295a1473 100644
+--- a/drivers/char/sonypi.c
++++ b/drivers/char/sonypi.c
+@@ -1428,7 +1428,7 @@ static int sonypi_probe(struct platform_device *dev)
+ 	return error;
+ }
+ 
+-static int __devexit sonypi_remove(struct platform_device *dev)
++static int sonypi_remove(struct platform_device *dev)
+ {
+ 	sonypi_disable();
+ 
+diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c
+index 76e3aea27ff7..34c63f85104d 100644
+--- a/drivers/char/tb0219.c
++++ b/drivers/char/tb0219.c
+@@ -318,7 +318,7 @@ static int tb0219_probe(struct platform_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devexit tb0219_remove(struct platform_device *dev)
++static int tb0219_remove(struct platform_device *dev)
+ {
+ 	_machine_restart = old_machine_restart;
+ 
+diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c
+index 5a831aec9d4b..78983b77caf4 100644
+--- a/drivers/char/tpm/tpm_i2c_infineon.c
++++ b/drivers/char/tpm/tpm_i2c_infineon.c
+@@ -656,7 +656,7 @@ static int __devinit tpm_tis_i2c_probe(struct i2c_client *client,
+ 	return rc;
+ }
+ 
+-static int __devexit tpm_tis_i2c_remove(struct i2c_client *client)
++static int tpm_tis_i2c_remove(struct i2c_client *client)
+ {
+ 	struct tpm_chip *chip = tpm_dev.chip;
+ 	release_locality(chip, chip->vendor.locality, 1);
+diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c
+index 3b032dbb9de0..5a72f39d9620 100644
+--- a/drivers/char/tpm/tpm_ibmvtpm.c
++++ b/drivers/char/tpm/tpm_ibmvtpm.c
+@@ -267,7 +267,7 @@ static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm)
+  * Return value:
+  *	0
+  */
+-static int __devexit tpm_ibmvtpm_remove(struct vio_dev *vdev)
++static int tpm_ibmvtpm_remove(struct vio_dev *vdev)
+ {
+ 	struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev);
+ 	int rc = 0;
+diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c
+index 3251a44e8ceb..4dd5f8acecda 100644
+--- a/drivers/char/tpm/tpm_infineon.c
++++ b/drivers/char/tpm/tpm_infineon.c
+@@ -594,7 +594,7 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
+ 	return rc;
+ }
+ 
+-static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev)
++static void tpm_inf_pnp_remove(struct pnp_dev *dev)
+ {
+ 	struct tpm_chip *chip = pnp_get_drvdata(dev);
+ 
+diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
+index 25fee274bdbd..a599cc267fcc 100644
+--- a/drivers/char/tpm/tpm_tis.c
++++ b/drivers/char/tpm/tpm_tis.c
+@@ -783,7 +783,7 @@ static struct pnp_device_id tpm_pnp_tbl[] = {
+ };
+ MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl);
+ 
+-static __devexit void tpm_tis_pnp_remove(struct pnp_dev *dev)
++static void tpm_tis_pnp_remove(struct pnp_dev *dev)
+ {
+ 	struct tpm_chip *chip = pnp_get_drvdata(dev);
+ 
+diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+index d10085f9a0de..5224da5202d3 100644
+--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
++++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+@@ -717,7 +717,7 @@ static struct hwicap_driver_config fifo_icap_config = {
+ 	.reset = fifo_icap_reset,
+ };
+ 
+-static int __devexit hwicap_remove(struct device *dev)
++static int hwicap_remove(struct device *dev)
+ {
+ 	struct hwicap_drvdata *drvdata;
+ 
+@@ -822,7 +822,7 @@ static int hwicap_drv_probe(struct platform_device *pdev)
+ 			&buffer_icap_config, regs);
+ }
+ 
+-static int __devexit hwicap_drv_remove(struct platform_device *pdev)
++static int hwicap_drv_remove(struct platform_device *pdev)
+ {
+ 	return hwicap_remove(&pdev->dev);
+ }

commit aa89ed9e369b345ef3737c56e7c8934af2df4aa6
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:25:02 2012 -0500
+
+    char: remove use of __devinitconst
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitconst is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c
+index f74e892711dd..e5d3e3f7a49b 100644
+--- a/drivers/char/mbcs.c
++++ b/drivers/char/mbcs.c
+@@ -799,7 +799,7 @@ static int mbcs_remove(struct cx_dev *dev)
+ 	return 0;
+ }
+ 
+-static const struct cx_device_id __devinitconst mbcs_id_table[] = {
++static const struct cx_device_id mbcs_id_table[] = {
+ 	{
+ 	 .part_num = MBCS_PART_NUM,
+ 	 .mfg_num = MBCS_MFG_NUM,
+diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+index 547ed74e3d12..d10085f9a0de 100644
+--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
++++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+@@ -785,7 +785,7 @@ static inline int hwicap_of_probe(struct platform_device *op,
+ }
+ #endif /* CONFIG_OF */
+ 
+-static const struct of_device_id __devinitconst hwicap_of_match[];
++static const struct of_device_id hwicap_of_match[];
+ static int hwicap_drv_probe(struct platform_device *pdev)
+ {
+ 	const struct of_device_id *match;
+@@ -829,7 +829,7 @@ static int __devexit hwicap_drv_remove(struct platform_device *pdev)
+ 
+ #ifdef CONFIG_OF
+ /* Match table for device tree binding */
+-static const struct of_device_id __devinitconst hwicap_of_match[] = {
++static const struct of_device_id hwicap_of_match[] = {
+ 	{ .compatible = "xlnx,opb-hwicap-1.00.b", .data = &buffer_icap_config},
+ 	{ .compatible = "xlnx,xps-hwicap-1.00.a", .data = &fifo_icap_config},
+ 	{},

commit 0bbed20e0518f6b9d46b7fe2bd044e3398a6dc40
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:24:36 2012 -0500
+
+    char: remove use of __devinitdata
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitdata is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: David Airlie 
+    Cc: Kent Yoder 
+    Cc: Rajiv Andrade 
+    Cc: Marcel Selhorst 
+    Cc: Sirrix AG 
+    Cc: openipmi-developer@lists.sourceforge.net
+    Cc: tpmdd-devel@lists.sourceforge.net
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
+index fd793519ea2b..9c022df134af 100644
+--- a/drivers/char/agp/ali-agp.c
++++ b/drivers/char/agp/ali-agp.c
+@@ -249,7 +249,7 @@ static const struct agp_bridge_driver ali_m1541_bridge = {
+ };
+ 
+ 
+-static struct agp_device_ids ali_agp_device_ids[] __devinitdata =
++static struct agp_device_ids ali_agp_device_ids[] =
+ {
+ 	{
+ 		.device_id	= PCI_DEVICE_ID_AL_M1541,
+diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
+index f7e88787af97..3c7a2653f161 100644
+--- a/drivers/char/agp/amd-k7-agp.c
++++ b/drivers/char/agp/amd-k7-agp.c
+@@ -388,7 +388,7 @@ static const struct agp_bridge_driver amd_irongate_driver = {
+ 	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
+ };
+ 
+-static struct agp_device_ids amd_agp_device_ids[] __devinitdata =
++static struct agp_device_ids amd_agp_device_ids[] =
+ {
+ 	{
+ 		.device_id	= PCI_DEVICE_ID_AMD_FE_GATE_7006,
+diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
+index dc30e2243494..d1c4c2340713 100644
+--- a/drivers/char/agp/ati-agp.c
++++ b/drivers/char/agp/ati-agp.c
+@@ -445,7 +445,7 @@ static const struct agp_bridge_driver ati_generic_bridge = {
+ };
+ 
+ 
+-static struct agp_device_ids ati_agp_device_ids[] __devinitdata =
++static struct agp_device_ids ati_agp_device_ids[] =
+ {
+ 	{
+ 		.device_id	= PCI_DEVICE_ID_ATI_RS100,
+diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c
+index 08704ae53956..c93c9e5ee2c2 100644
+--- a/drivers/char/agp/sis-agp.c
++++ b/drivers/char/agp/sis-agp.c
+@@ -17,8 +17,8 @@
+ #define PCI_DEVICE_ID_SI_662	0x0662
+ #define PCI_DEVICE_ID_SI_671	0x0671
+ 
+-static bool __devinitdata agp_sis_force_delay = 0;
+-static int __devinitdata agp_sis_agp_spec = -1;
++static bool agp_sis_force_delay = 0;
++static int agp_sis_agp_spec = -1;
+ 
+ static int sis_fetch_size(void)
+ {
+@@ -148,7 +148,7 @@ static struct agp_bridge_driver sis_driver = {
+ };
+ 
+ // chipsets that require the 'delay hack'
+-static int sis_broken_chipsets[] __devinitdata = {
++static int sis_broken_chipsets[] = {
+ 	PCI_DEVICE_ID_SI_648,
+ 	PCI_DEVICE_ID_SI_746,
+ 	0 // terminator
+diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c
+index a32c492baf5c..af02da4da9e3 100644
+--- a/drivers/char/agp/uninorth-agp.c
++++ b/drivers/char/agp/uninorth-agp.c
+@@ -557,7 +557,7 @@ const struct agp_bridge_driver u3_agp_driver = {
+ 	.needs_scratch_page	= true,
+ };
+ 
+-static struct agp_device_ids uninorth_agp_device_ids[] __devinitdata = {
++static struct agp_device_ids uninorth_agp_device_ids[] = {
+ 	{
+ 		.device_id	= PCI_DEVICE_ID_APPLE_UNI_N_AGP,
+ 		.chipset_name	= "UniNorth",
+diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
+index 8bc384937401..97706834bae1 100644
+--- a/drivers/char/agp/via-agp.c
++++ b/drivers/char/agp/via-agp.c
+@@ -224,7 +224,7 @@ static const struct agp_bridge_driver via_driver = {
+ 	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
+ };
+ 
+-static struct agp_device_ids via_agp_device_ids[] __devinitdata =
++static struct agp_device_ids via_agp_device_ids[] =
+ {
+ 	{
+ 		.device_id	= PCI_DEVICE_ID_VIA_82C597_0,
+diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c
+index ebd48f0135da..fd57d8a9faff 100644
+--- a/drivers/char/hw_random/n2-drv.c
++++ b/drivers/char/hw_random/n2-drv.c
+@@ -25,7 +25,7 @@
+ #define DRV_MODULE_VERSION	"0.2"
+ #define DRV_MODULE_RELDATE	"July 27, 2011"
+ 
+-static char version[] __devinitdata =
++static char version[] =
+ 	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+ 
+ MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
+diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
+index 1a465a4974f8..e55a7ad8ef18 100644
+--- a/drivers/char/ipmi/ipmi_si_intf.c
++++ b/drivers/char/ipmi/ipmi_si_intf.c
+@@ -3047,7 +3047,7 @@ static inline void wait_for_timer_and_thread(struct smi_info *smi_info)
+ 	}
+ }
+ 
+-static __devinitdata struct ipmi_default_vals
++static struct ipmi_default_vals
+ {
+ 	int type;
+ 	int port;
+diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c
+index efc4ab36a9d6..3b032dbb9de0 100644
+--- a/drivers/char/tpm/tpm_ibmvtpm.c
++++ b/drivers/char/tpm/tpm_ibmvtpm.c
+@@ -32,7 +32,7 @@
+ 
+ static const char tpm_ibmvtpm_driver_name[] = "tpm_ibmvtpm";
+ 
+-static struct vio_device_id tpm_ibmvtpm_device_table[] __devinitdata = {
++static struct vio_device_id tpm_ibmvtpm_device_table[] = {
+ 	{ "IBM,vtpm", "IBM,vtpm"},
+ 	{ "", "" }
+ };
+diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
+index 6bdf2671254f..25fee274bdbd 100644
+--- a/drivers/char/tpm/tpm_tis.c
++++ b/drivers/char/tpm/tpm_tis.c
+@@ -769,7 +769,7 @@ static int tpm_tis_pnp_resume(struct pnp_dev *dev)
+ 	return ret;
+ }
+ 
+-static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {
++static struct pnp_device_id tpm_pnp_tbl[] = {
+ 	{"PNP0C31", 0},		/* TPM */
+ 	{"ATM1200", 0},		/* Atmel */
+ 	{"IFX0102", 0},		/* Infineon */

commit 2223cbec33ef3a26e7678be89de75cb60c4c257b
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:51 2012 -0500
+
+    char: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Geoff Levand 
+    Cc: Mattia Dongili 
+    Cc: Amit Shah 
+    Cc: openipmi-developer@lists.sourceforge.net
+    Cc: linuxppc-dev@lists.ozlabs.org
+    Cc: cbe-oss-dev@lists.ozlabs.org
+    Cc: platform-driver-x86@vger.kernel.org
+    Cc: virtualization@lists.linux-foundation.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
+index 32a6c7e256bd..1a465a4974f8 100644
+--- a/drivers/char/ipmi/ipmi_si_intf.c
++++ b/drivers/char/ipmi/ipmi_si_intf.c
+@@ -1836,7 +1836,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp)
+ 	return rv;
+ }
+ 
+-static int __devinit hardcode_find_bmc(void)
++static int hardcode_find_bmc(void)
+ {
+ 	int ret = -ENODEV;
+ 	int             i;
+@@ -2023,7 +2023,7 @@ struct SPMITable {
+ 	s8      spmi_id[1]; /* A '\0' terminated array starts here. */
+ };
+ 
+-static int __devinit try_init_spmi(struct SPMITable *spmi)
++static int try_init_spmi(struct SPMITable *spmi)
+ {
+ 	struct smi_info  *info;
+ 
+@@ -2106,7 +2106,7 @@ static int __devinit try_init_spmi(struct SPMITable *spmi)
+ 	return 0;
+ }
+ 
+-static void __devinit spmi_find_bmc(void)
++static void spmi_find_bmc(void)
+ {
+ 	acpi_status      status;
+ 	struct SPMITable *spmi;
+@@ -2128,7 +2128,7 @@ static void __devinit spmi_find_bmc(void)
+ 	}
+ }
+ 
+-static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
++static int ipmi_pnp_probe(struct pnp_dev *dev,
+ 				    const struct pnp_device_id *dev_id)
+ {
+ 	struct acpi_device *acpi_dev;
+@@ -2258,7 +2258,7 @@ struct dmi_ipmi_data {
+ 	u8              slave_addr;
+ };
+ 
+-static int __devinit decode_dmi(const struct dmi_header *dm,
++static int decode_dmi(const struct dmi_header *dm,
+ 				struct dmi_ipmi_data *dmi)
+ {
+ 	const u8	*data = (const u8 *)dm;
+@@ -2320,7 +2320,7 @@ static int __devinit decode_dmi(const struct dmi_header *dm,
+ 	return 0;
+ }
+ 
+-static void __devinit try_init_dmi(struct dmi_ipmi_data *ipmi_data)
++static void try_init_dmi(struct dmi_ipmi_data *ipmi_data)
+ {
+ 	struct smi_info *info;
+ 
+@@ -2388,7 +2388,7 @@ static void __devinit try_init_dmi(struct dmi_ipmi_data *ipmi_data)
+ 		kfree(info);
+ }
+ 
+-static void __devinit dmi_find_bmc(void)
++static void dmi_find_bmc(void)
+ {
+ 	const struct dmi_device *dev = NULL;
+ 	struct dmi_ipmi_data data;
+@@ -2424,7 +2424,7 @@ static void ipmi_pci_cleanup(struct smi_info *info)
+ 	pci_disable_device(pdev);
+ }
+ 
+-static int __devinit ipmi_pci_probe_regspacing(struct smi_info *info)
++static int ipmi_pci_probe_regspacing(struct smi_info *info)
+ {
+ 	if (info->si_type == SI_KCS) {
+ 		unsigned char	status;
+@@ -2456,7 +2456,7 @@ static int __devinit ipmi_pci_probe_regspacing(struct smi_info *info)
+ 	return DEFAULT_REGSPACING;
+ }
+ 
+-static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
++static int ipmi_pci_probe(struct pci_dev *pdev,
+ 				    const struct pci_device_id *ent)
+ {
+ 	int rv;
+@@ -2551,7 +2551,7 @@ static struct pci_driver ipmi_pci_driver = {
+ #endif /* CONFIG_PCI */
+ 
+ static struct of_device_id ipmi_match[];
+-static int __devinit ipmi_probe(struct platform_device *dev)
++static int ipmi_probe(struct platform_device *dev)
+ {
+ #ifdef CONFIG_OF
+ 	const struct of_device_id *match;
+@@ -3059,7 +3059,7 @@ static __devinitdata struct ipmi_default_vals
+ 	{ .port = 0 }
+ };
+ 
+-static void __devinit default_find_bmc(void)
++static void default_find_bmc(void)
+ {
+ 	struct smi_info *info;
+ 	int             i;
+@@ -3359,7 +3359,7 @@ static int try_smi_init(struct smi_info *new_smi)
+ 	return rv;
+ }
+ 
+-static int __devinit init_ipmi_si(void)
++static int init_ipmi_si(void)
+ {
+ 	int  i;
+ 	char *str;
+diff --git a/drivers/char/ps3flash.c b/drivers/char/ps3flash.c
+index 6abdde4da2b7..588063ac9517 100644
+--- a/drivers/char/ps3flash.c
++++ b/drivers/char/ps3flash.c
+@@ -363,7 +363,7 @@ static struct miscdevice ps3flash_misc = {
+ 	.fops	= &ps3flash_fops,
+ };
+ 
+-static int __devinit ps3flash_probe(struct ps3_system_bus_device *_dev)
++static int ps3flash_probe(struct ps3_system_bus_device *_dev)
+ {
+ 	struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
+ 	struct ps3flash_private *priv;
+diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
+index 34f0db34fcd3..861efa48c696 100644
+--- a/drivers/char/sonypi.c
++++ b/drivers/char/sonypi.c
+@@ -1164,7 +1164,7 @@ static struct acpi_driver sonypi_acpi_driver = {
+ };
+ #endif
+ 
+-static int __devinit sonypi_create_input_devices(struct platform_device *pdev)
++static int sonypi_create_input_devices(struct platform_device *pdev)
+ {
+ 	struct input_dev *jog_dev;
+ 	struct input_dev *key_dev;
+@@ -1225,7 +1225,7 @@ static int __devinit sonypi_create_input_devices(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devinit sonypi_setup_ioports(struct sonypi_device *dev,
++static int sonypi_setup_ioports(struct sonypi_device *dev,
+ 				const struct sonypi_ioport_list *ioport_list)
+ {
+ 	/* try to detect if sony-laptop is being used and thus
+@@ -1265,7 +1265,7 @@ static int __devinit sonypi_setup_ioports(struct sonypi_device *dev,
+ 	return -EBUSY;
+ }
+ 
+-static int __devinit sonypi_setup_irq(struct sonypi_device *dev,
++static int sonypi_setup_irq(struct sonypi_device *dev,
+ 				      const struct sonypi_irq_list *irq_list)
+ {
+ 	while (irq_list->irq) {
+@@ -1282,7 +1282,7 @@ static int __devinit sonypi_setup_irq(struct sonypi_device *dev,
+ 	return -EBUSY;
+ }
+ 
+-static void __devinit sonypi_display_info(void)
++static void sonypi_display_info(void)
+ {
+ 	printk(KERN_INFO "sonypi: detected type%d model, "
+ 	       "verbose = %d, fnkeyinit = %s, camera = %s, "
+@@ -1304,7 +1304,7 @@ static void __devinit sonypi_display_info(void)
+ 		       sonypi_misc_device.minor);
+ }
+ 
+-static int __devinit sonypi_probe(struct platform_device *dev)
++static int sonypi_probe(struct platform_device *dev)
+ {
+ 	const struct sonypi_ioport_list *ioport_list;
+ 	const struct sonypi_irq_list *irq_list;
+diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c
+index 6bfe2af844eb..76e3aea27ff7 100644
+--- a/drivers/char/tb0219.c
++++ b/drivers/char/tb0219.c
+@@ -284,7 +284,7 @@ static void tb0219_pci_irq_init(void)
+ 	vr41xx_set_irq_level(TB0219_PCI_SLOT3_PIN, IRQ_LEVEL_LOW);
+ }
+ 
+-static int __devinit tb0219_probe(struct platform_device *dev)
++static int tb0219_probe(struct platform_device *dev)
+ {
+ 	int retval;
+ 
+diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
+index 8ab9c3d4bf13..90493d4ead1f 100644
+--- a/drivers/char/virtio_console.c
++++ b/drivers/char/virtio_console.c
+@@ -1846,7 +1846,7 @@ static void remove_controlq_data(struct ports_device *portdev)
+  * config space to see how many ports the host has spawned.  We
+  * initialize each port found.
+  */
+-static int __devinit virtcons_probe(struct virtio_device *vdev)
++static int virtcons_probe(struct virtio_device *vdev)
+ {
+ 	struct ports_device *portdev;
+ 	int err;
+diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+index 2c5d15beea35..547ed74e3d12 100644
+--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
++++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+@@ -595,7 +595,7 @@ static const struct file_operations hwicap_fops = {
+ 	.llseek = noop_llseek,
+ };
+ 
+-static int __devinit hwicap_setup(struct device *dev, int id,
++static int hwicap_setup(struct device *dev, int id,
+ 		const struct resource *regs_res,
+ 		const struct hwicap_driver_config *config,
+ 		const struct config_registers *config_regs)
+@@ -740,7 +740,7 @@ static int __devexit hwicap_remove(struct device *dev)
+ }
+ 
+ #ifdef CONFIG_OF
+-static int __devinit hwicap_of_probe(struct platform_device *op,
++static int hwicap_of_probe(struct platform_device *op,
+ 				     const struct hwicap_driver_config *config)
+ {
+ 	struct resource res;
+@@ -786,7 +786,7 @@ static inline int hwicap_of_probe(struct platform_device *op,
+ #endif /* CONFIG_OF */
+ 
+ static const struct of_device_id __devinitconst hwicap_of_match[];
+-static int __devinit hwicap_drv_probe(struct platform_device *pdev)
++static int hwicap_drv_probe(struct platform_device *pdev)
+ {
+ 	const struct of_device_id *match;
+ 	struct resource *res;

commit 4dde2d2f3a3b09d282eb399d24fb261ae50425ef
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:19:58 2012 -0500
+
+    char: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Mattia Dongili 
+    Cc: platform-driver-x86@vger.kernel.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
+index 9b4f0116ff21..34f0db34fcd3 100644
+--- a/drivers/char/sonypi.c
++++ b/drivers/char/sonypi.c
+@@ -1491,7 +1491,7 @@ static struct platform_driver sonypi_driver = {
+ 		.pm	= SONYPI_PM,
+ 	},
+ 	.probe		= sonypi_probe,
+-	.remove		= __devexit_p(sonypi_remove),
++	.remove		= sonypi_remove,
+ 	.shutdown	= sonypi_shutdown,
+ };
+ 
+diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c
+index ad264185eb10..6bfe2af844eb 100644
+--- a/drivers/char/tb0219.c
++++ b/drivers/char/tb0219.c
+@@ -334,7 +334,7 @@ static struct platform_device *tb0219_platform_device;
+ 
+ static struct platform_driver tb0219_device_driver = {
+ 	.probe		= tb0219_probe,
+-	.remove		= __devexit_p(tb0219_remove),
++	.remove		= tb0219_remove,
+ 	.driver		= {
+ 		.name	= "TB0219",
+ 		.owner	= THIS_MODULE,

commit 486a5c28c2e7d6a80c393ac7d612b77d80447b84
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:02 2012 -0500
+
+    misc: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: "Michał Mirosław" 
+    Cc: Wolfram Sang 
+    Cc: Eric Piel 
+    Cc: Jiri Slaby 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/misc/ad525x_dpot-i2c.c b/drivers/misc/ad525x_dpot-i2c.c
+index c7bc84df4bdb..705b881e186d 100644
+--- a/drivers/misc/ad525x_dpot-i2c.c
++++ b/drivers/misc/ad525x_dpot-i2c.c
+@@ -68,7 +68,7 @@ static int ad_dpot_i2c_probe(struct i2c_client *client,
+ 	return ad_dpot_probe(&client->dev, &bdata, id->driver_data, id->name);
+ }
+ 
+-static int __devexit ad_dpot_i2c_remove(struct i2c_client *client)
++static int ad_dpot_i2c_remove(struct i2c_client *client)
+ {
+ 	return ad_dpot_remove(&client->dev);
+ }
+diff --git a/drivers/misc/ad525x_dpot-spi.c b/drivers/misc/ad525x_dpot-spi.c
+index 240c59870e7d..9da04ede04f3 100644
+--- a/drivers/misc/ad525x_dpot-spi.c
++++ b/drivers/misc/ad525x_dpot-spi.c
+@@ -87,7 +87,7 @@ static int ad_dpot_spi_probe(struct spi_device *spi)
+ 			     spi_get_device_id(spi)->name);
+ }
+ 
+-static int __devexit ad_dpot_spi_remove(struct spi_device *spi)
++static int ad_dpot_spi_remove(struct spi_device *spi)
+ {
+ 	return ad_dpot_remove(&spi->dev);
+ }
+diff --git a/drivers/misc/apds9802als.c b/drivers/misc/apds9802als.c
+index 0132d15a995c..d648b0893027 100644
+--- a/drivers/misc/apds9802als.c
++++ b/drivers/misc/apds9802als.c
+@@ -254,7 +254,7 @@ static int apds9802als_probe(struct i2c_client *client,
+ 	return res;
+ }
+ 
+-static int __devexit apds9802als_remove(struct i2c_client *client)
++static int apds9802als_remove(struct i2c_client *client)
+ {
+ 	struct als_data *data = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c
+index b2aaf3f04459..0e67f8263cd8 100644
+--- a/drivers/misc/apds990x.c
++++ b/drivers/misc/apds990x.c
+@@ -1181,7 +1181,7 @@ static int apds990x_probe(struct i2c_client *client,
+ 	return err;
+ }
+ 
+-static int __devexit apds990x_remove(struct i2c_client *client)
++static int apds990x_remove(struct i2c_client *client)
+ {
+ 	struct apds990x_chip *chip = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
+index 191c2ce9d5e1..c58f9abcb356 100644
+--- a/drivers/misc/atmel-ssc.c
++++ b/drivers/misc/atmel-ssc.c
+@@ -137,7 +137,7 @@ static int __init ssc_probe(struct platform_device *pdev)
+ 	return retval;
+ }
+ 
+-static int __devexit ssc_remove(struct platform_device *pdev)
++static int ssc_remove(struct platform_device *pdev)
+ {
+ 	struct ssc_device *ssc = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/misc/bh1770glc.c b/drivers/misc/bh1770glc.c
+index 003e8d9ab8a5..2ed8fc3be7e6 100644
+--- a/drivers/misc/bh1770glc.c
++++ b/drivers/misc/bh1770glc.c
+@@ -1285,7 +1285,7 @@ static int bh1770_probe(struct i2c_client *client,
+ 	return err;
+ }
+ 
+-static int __devexit bh1770_remove(struct i2c_client *client)
++static int bh1770_remove(struct i2c_client *client)
+ {
+ 	struct bh1770_chip *chip = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c
+index 3004904d23d4..cf03d0abf33e 100644
+--- a/drivers/misc/bh1780gli.c
++++ b/drivers/misc/bh1780gli.c
+@@ -185,7 +185,7 @@ static int bh1780_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit bh1780_remove(struct i2c_client *client)
++static int bh1780_remove(struct i2c_client *client)
+ {
+ 	struct bh1780_data *ddata;
+ 
+diff --git a/drivers/misc/cb710/core.c b/drivers/misc/cb710/core.c
+index 4fc9c37cd202..2e50f811ff59 100644
+--- a/drivers/misc/cb710/core.c
++++ b/drivers/misc/cb710/core.c
+@@ -305,7 +305,7 @@ static int cb710_probe(struct pci_dev *pdev,
+ 	return err;
+ }
+ 
+-static void __devexit cb710_remove_one(struct pci_dev *pdev)
++static void cb710_remove_one(struct pci_dev *pdev)
+ {
+ 	struct cb710_chip *chip = pci_get_drvdata(pdev);
+ 	unsigned long flags;
+diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
+index 3c36997bdacd..2baeec56edfe 100644
+--- a/drivers/misc/eeprom/at24.c
++++ b/drivers/misc/eeprom/at24.c
+@@ -656,7 +656,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
+ 	return err;
+ }
+ 
+-static int __devexit at24_remove(struct i2c_client *client)
++static int at24_remove(struct i2c_client *client)
+ {
+ 	struct at24_data *at24;
+ 	int i;
+diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
+index fcb237e9bb1a..b08cf8a08789 100644
+--- a/drivers/misc/eeprom/at25.c
++++ b/drivers/misc/eeprom/at25.c
+@@ -459,7 +459,7 @@ static int at25_probe(struct spi_device *spi)
+ 	return err;
+ }
+ 
+-static int __devexit at25_remove(struct spi_device *spi)
++static int at25_remove(struct spi_device *spi)
+ {
+ 	struct at25_data	*at25;
+ 
+diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c
+index 3dd9005fd0e5..a6b5d5e73485 100644
+--- a/drivers/misc/eeprom/eeprom_93xx46.c
++++ b/drivers/misc/eeprom/eeprom_93xx46.c
+@@ -370,7 +370,7 @@ static int eeprom_93xx46_probe(struct spi_device *spi)
+ 	return err;
+ }
+ 
+-static int __devexit eeprom_93xx46_remove(struct spi_device *spi)
++static int eeprom_93xx46_remove(struct spi_device *spi)
+ {
+ 	struct eeprom_93xx46_dev *edev = dev_get_drvdata(&spi->dev);
+ 
+diff --git a/drivers/misc/fsa9480.c b/drivers/misc/fsa9480.c
+index 2baa52f07c7a..e8cbb1c59f4c 100644
+--- a/drivers/misc/fsa9480.c
++++ b/drivers/misc/fsa9480.c
+@@ -462,7 +462,7 @@ static int fsa9480_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit fsa9480_remove(struct i2c_client *client)
++static int fsa9480_remove(struct i2c_client *client)
+ {
+ 	struct fsa9480_usbsw *usbsw = i2c_get_clientdata(client);
+ 	if (client->irq)
+diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c
+index 380e4298ada1..0346d87c5fed 100644
+--- a/drivers/misc/ibmasm/module.c
++++ b/drivers/misc/ibmasm/module.c
+@@ -163,7 +163,7 @@ static int ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	return result;
+ }
+ 
+-static void __devexit ibmasm_remove_one(struct pci_dev *pdev)
++static void ibmasm_remove_one(struct pci_dev *pdev)
+ {
+ 	struct service_processor *sp = (struct service_processor *)pci_get_drvdata(pdev);
+ 
+diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c
+index 3ef92dca5472..06f6ad29ceff 100644
+--- a/drivers/misc/ioc4.c
++++ b/drivers/misc/ioc4.c
+@@ -415,7 +415,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+ }
+ 
+ /* Removes a particular instance of an IOC4 card. */
+-static void __devexit
++static void
+ ioc4_remove(struct pci_dev *pdev)
+ {
+ 	struct ioc4_submodule *is;
+diff --git a/drivers/misc/isl29003.c b/drivers/misc/isl29003.c
+index 9fd4c0c6e599..29b306c6bdb3 100644
+--- a/drivers/misc/isl29003.c
++++ b/drivers/misc/isl29003.c
+@@ -401,7 +401,7 @@ static int isl29003_probe(struct i2c_client *client,
+ 	return err;
+ }
+ 
+-static int __devexit isl29003_remove(struct i2c_client *client)
++static int isl29003_remove(struct i2c_client *client)
+ {
+ 	sysfs_remove_group(&client->dev.kobj, &isl29003_attr_group);
+ 	isl29003_set_power_state(client, 0);
+diff --git a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
+index 66f0483efb03..7c97550240f1 100644
+--- a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
++++ b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
+@@ -191,7 +191,7 @@ static int lis3lv02d_i2c_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit lis3lv02d_i2c_remove(struct i2c_client *client)
++static int lis3lv02d_i2c_remove(struct i2c_client *client)
+ {
+ 	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+ 	struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
+diff --git a/drivers/misc/lis3lv02d/lis3lv02d_spi.c b/drivers/misc/lis3lv02d/lis3lv02d_spi.c
+index 66a751d2ed53..9aa2bd2a71ae 100644
+--- a/drivers/misc/lis3lv02d/lis3lv02d_spi.c
++++ b/drivers/misc/lis3lv02d/lis3lv02d_spi.c
+@@ -100,7 +100,7 @@ static int lis302dl_spi_probe(struct spi_device *spi)
+ 	return lis3lv02d_init_device(&lis3_dev);
+ }
+ 
+-static int __devexit lis302dl_spi_remove(struct spi_device *spi)
++static int lis302dl_spi_remove(struct spi_device *spi)
+ {
+ 	struct lis3lv02d *lis3 = spi_get_drvdata(spi);
+ 	lis3lv02d_joystick_disable(lis3);
+diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
+index 4782c582ae38..43fb52ff98ad 100644
+--- a/drivers/misc/mei/main.c
++++ b/drivers/misc/mei/main.c
+@@ -882,7 +882,7 @@ static int mei_probe(struct pci_dev *pdev,
+  * mei_remove is called by the PCI subsystem to alert the driver
+  * that it should release a PCI device.
+  */
+-static void __devexit mei_remove(struct pci_dev *pdev)
++static void mei_remove(struct pci_dev *pdev)
+ {
+ 	struct mei_device *dev;
+ 
+diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c
+index 3896cff2579f..931e635aa491 100644
+--- a/drivers/misc/pch_phub.c
++++ b/drivers/misc/pch_phub.c
+@@ -819,7 +819,7 @@ static int pch_phub_probe(struct pci_dev *pdev,
+ 	return ret;
+ }
+ 
+-static void __devexit pch_phub_remove(struct pci_dev *pdev)
++static void pch_phub_remove(struct pci_dev *pdev)
+ {
+ 	struct pch_phub_reg *chip = pci_get_drvdata(pdev);
+ 
+diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
+index 035776342a4c..68b7c773d2cf 100644
+--- a/drivers/misc/phantom.c
++++ b/drivers/misc/phantom.c
+@@ -435,7 +435,7 @@ static int phantom_probe(struct pci_dev *pdev,
+ 	return retval;
+ }
+ 
+-static void __devexit phantom_remove(struct pci_dev *pdev)
++static void phantom_remove(struct pci_dev *pdev)
+ {
+ 	struct phantom_device *pht = pci_get_drvdata(pdev);
+ 	unsigned int minor = MINOR(pht->cdev.dev);
+diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c
+index 37d4b5ef9dc7..7003031c9181 100644
+--- a/drivers/misc/pti.c
++++ b/drivers/misc/pti.c
+@@ -879,7 +879,7 @@ static int pti_pci_probe(struct pci_dev *pdev,
+  *		   PCI bus.
+  * @pdev: variable containing pci info of PTI.
+  */
+-static void __devexit pti_pci_remove(struct pci_dev *pdev)
++static void pti_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct pti_dev *drv_data = pci_get_drvdata(pdev);
+ 
+diff --git a/drivers/misc/spear13xx_pcie_gadget.c b/drivers/misc/spear13xx_pcie_gadget.c
+index 7850320462fb..7deb25dc86a7 100644
+--- a/drivers/misc/spear13xx_pcie_gadget.c
++++ b/drivers/misc/spear13xx_pcie_gadget.c
+@@ -853,7 +853,7 @@ static int spear_pcie_gadget_probe(struct platform_device *pdev)
+ 	return status;
+ }
+ 
+-static int __devexit spear_pcie_gadget_remove(struct platform_device *pdev)
++static int spear_pcie_gadget_remove(struct platform_device *pdev)
+ {
+ 	struct resource *res0, *res1;
+ 	static struct pcie_gadget_target *target;
+diff --git a/drivers/misc/ti_dac7512.c b/drivers/misc/ti_dac7512.c
+index 1222f86dfda9..1d86407189eb 100644
+--- a/drivers/misc/ti_dac7512.c
++++ b/drivers/misc/ti_dac7512.c
+@@ -67,7 +67,7 @@ static int dac7512_probe(struct spi_device *spi)
+ 	return sysfs_create_group(&spi->dev.kobj, &dac7512_attr_group);
+ }
+ 
+-static int __devexit dac7512_remove(struct spi_device *spi)
++static int dac7512_remove(struct spi_device *spi)
+ {
+ 	sysfs_remove_group(&spi->dev.kobj, &dac7512_attr_group);
+ 	return 0;
+diff --git a/drivers/misc/tsl2550.c b/drivers/misc/tsl2550.c
+index 18bce70b30f2..1e7bc0eb081e 100644
+--- a/drivers/misc/tsl2550.c
++++ b/drivers/misc/tsl2550.c
+@@ -405,7 +405,7 @@ static int tsl2550_probe(struct i2c_client *client,
+ 	return err;
+ }
+ 
+-static int __devexit tsl2550_remove(struct i2c_client *client)
++static int tsl2550_remove(struct i2c_client *client)
+ {
+ 	sysfs_remove_group(&client->dev.kobj, &tsl2550_attr_group);
+ 

commit b328bfec519875851c4b3d95cd22371aad0a657e
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:25:10 2012 -0500
+
+    misc: remove use of __devinitconst
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitconst is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c
+index e1a898e97f7c..37d4b5ef9dc7 100644
+--- a/drivers/misc/pti.c
++++ b/drivers/misc/pti.c
+@@ -76,7 +76,7 @@ struct pti_dev {
+  */
+ static DEFINE_MUTEX(alloclock);
+ 
+-static const struct pci_device_id pci_ids[] __devinitconst = {
++static const struct pci_device_id pci_ids[] = {
+ 		{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x82B)},
+ 		{0}
+ };

commit 2c68506412e96d0e306be6057e824478a2deccbd
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:24:38 2012 -0500
+
+    misc: remove use of __devinitdata
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitdata is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Jiri Slaby 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
+index 394150df2afe..035776342a4c 100644
+--- a/drivers/misc/phantom.c
++++ b/drivers/misc/phantom.c
+@@ -487,7 +487,7 @@ static int phantom_resume(struct pci_dev *pdev)
+ #define phantom_resume	NULL
+ #endif
+ 
+-static struct pci_device_id phantom_pci_tbl[] __devinitdata = {
++static struct pci_device_id phantom_pci_tbl[] = {
+ 	{ .vendor = PCI_VENDOR_ID_PLX, .device = PCI_DEVICE_ID_PLX_9050,
+ 	  .subvendor = PCI_VENDOR_ID_PLX, .subdevice = PCI_DEVICE_ID_PLX_9050,
+ 	  .class = PCI_CLASS_BRIDGE_OTHER << 8, .class_mask = 0xffff00 },

commit 80c8ae289266529445fad030fabf5fcf01ccda0d
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:23:05 2012 -0500
+
+    misc: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: "Michał Mirosław" 
+    Cc: Eric Piel 
+    Cc: Jiri Slaby 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/misc/ad525x_dpot-i2c.c b/drivers/misc/ad525x_dpot-i2c.c
+index 7254a98a89f6..c7bc84df4bdb 100644
+--- a/drivers/misc/ad525x_dpot-i2c.c
++++ b/drivers/misc/ad525x_dpot-i2c.c
+@@ -51,7 +51,7 @@ static const struct ad_dpot_bus_ops bops = {
+ 	.write_r8d16	= write_r8d16,
+ };
+ 
+-static int __devinit ad_dpot_i2c_probe(struct i2c_client *client,
++static int ad_dpot_i2c_probe(struct i2c_client *client,
+ 				      const struct i2c_device_id *id)
+ {
+ 	struct ad_dpot_bus_data bdata = {
+diff --git a/drivers/misc/ad525x_dpot-spi.c b/drivers/misc/ad525x_dpot-spi.c
+index 67e3073c2a6f..240c59870e7d 100644
+--- a/drivers/misc/ad525x_dpot-spi.c
++++ b/drivers/misc/ad525x_dpot-spi.c
+@@ -75,7 +75,7 @@ static const struct ad_dpot_bus_ops bops = {
+ 	.write_r8d8	= write16,
+ 	.write_r8d16	= write24,
+ };
+-static int __devinit ad_dpot_spi_probe(struct spi_device *spi)
++static int ad_dpot_spi_probe(struct spi_device *spi)
+ {
+ 	struct ad_dpot_bus_data bdata = {
+ 		.client = spi,
+diff --git a/drivers/misc/ad525x_dpot.c b/drivers/misc/ad525x_dpot.c
+index 6938f1be664d..8f99e8e3f0ac 100644
+--- a/drivers/misc/ad525x_dpot.c
++++ b/drivers/misc/ad525x_dpot.c
+@@ -641,7 +641,7 @@ static const struct attribute_group ad525x_group_commands = {
+ 	.attrs = ad525x_attributes_commands,
+ };
+ 
+-__devinit int ad_dpot_add_files(struct device *dev,
++int ad_dpot_add_files(struct device *dev,
+ 		unsigned features, unsigned rdac)
+ {
+ 	int err = sysfs_create_file(&dev->kobj,
+@@ -685,7 +685,7 @@ inline void ad_dpot_remove_files(struct device *dev,
+ 	}
+ }
+ 
+-int __devinit ad_dpot_probe(struct device *dev,
++int ad_dpot_probe(struct device *dev,
+ 		struct ad_dpot_bus_data *bdata, unsigned long devid,
+ 			    const char *name)
+ {
+diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c
+index f955d546f2df..b2aaf3f04459 100644
+--- a/drivers/misc/apds990x.c
++++ b/drivers/misc/apds990x.c
+@@ -1047,7 +1047,7 @@ static struct attribute_group apds990x_attribute_group[] = {
+ 	{.attrs = sysfs_attrs_ctrl },
+ };
+ 
+-static int __devinit apds990x_probe(struct i2c_client *client,
++static int apds990x_probe(struct i2c_client *client,
+ 				const struct i2c_device_id *id)
+ {
+ 	struct apds990x_chip *chip;
+diff --git a/drivers/misc/bh1770glc.c b/drivers/misc/bh1770glc.c
+index c4b65e26a76c..003e8d9ab8a5 100644
+--- a/drivers/misc/bh1770glc.c
++++ b/drivers/misc/bh1770glc.c
+@@ -1162,7 +1162,7 @@ static struct attribute_group bh1770_attribute_group = {
+ 	.attrs = sysfs_attrs
+ };
+ 
+-static int __devinit bh1770_probe(struct i2c_client *client,
++static int bh1770_probe(struct i2c_client *client,
+ 				const struct i2c_device_id *id)
+ {
+ 	struct bh1770_chip *chip;
+diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c
+index 54f6f39f990a..3004904d23d4 100644
+--- a/drivers/misc/bh1780gli.c
++++ b/drivers/misc/bh1780gli.c
+@@ -144,7 +144,7 @@ static const struct attribute_group bh1780_attr_group = {
+ 	.attrs = bh1780_attributes,
+ };
+ 
+-static int __devinit bh1780_probe(struct i2c_client *client,
++static int bh1780_probe(struct i2c_client *client,
+ 						const struct i2c_device_id *id)
+ {
+ 	int ret;
+diff --git a/drivers/misc/bmp085-i2c.c b/drivers/misc/bmp085-i2c.c
+index 08cd7958c147..3abfcecf8424 100644
+--- a/drivers/misc/bmp085-i2c.c
++++ b/drivers/misc/bmp085-i2c.c
+@@ -36,7 +36,7 @@ static int bmp085_i2c_detect(struct i2c_client *client,
+ 	return bmp085_detect(&client->dev);
+ }
+ 
+-static int __devinit bmp085_i2c_probe(struct i2c_client *client,
++static int bmp085_i2c_probe(struct i2c_client *client,
+ 				      const struct i2c_device_id *id)
+ {
+ 	int err;
+diff --git a/drivers/misc/bmp085-spi.c b/drivers/misc/bmp085-spi.c
+index ed34885a6b3f..d6a52659cf24 100644
+--- a/drivers/misc/bmp085-spi.c
++++ b/drivers/misc/bmp085-spi.c
+@@ -22,7 +22,7 @@
+ #include 
+ #include "bmp085.h"
+ 
+-static int __devinit bmp085_spi_probe(struct spi_device *client)
++static int bmp085_spi_probe(struct spi_device *client)
+ {
+ 	int err;
+ 	struct regmap *regmap;
+diff --git a/drivers/misc/bmp085.c b/drivers/misc/bmp085.c
+index 62e418293b7e..849e2fed4da2 100644
+--- a/drivers/misc/bmp085.c
++++ b/drivers/misc/bmp085.c
+@@ -420,7 +420,7 @@ struct regmap_config bmp085_regmap_config = {
+ };
+ EXPORT_SYMBOL_GPL(bmp085_regmap_config);
+ 
+-__devinit int bmp085_probe(struct device *dev, struct regmap *regmap)
++int bmp085_probe(struct device *dev, struct regmap *regmap)
+ {
+ 	struct bmp085_data *data;
+ 	int err = 0;
+diff --git a/drivers/misc/cb710/core.c b/drivers/misc/cb710/core.c
+index 489c468cf965..4fc9c37cd202 100644
+--- a/drivers/misc/cb710/core.c
++++ b/drivers/misc/cb710/core.c
+@@ -30,7 +30,7 @@ void cb710_pci_update_config_reg(struct pci_dev *pdev,
+ EXPORT_SYMBOL_GPL(cb710_pci_update_config_reg);
+ 
+ /* Some magic writes based on Windows driver init code */
+-static int __devinit cb710_pci_configure(struct pci_dev *pdev)
++static int cb710_pci_configure(struct pci_dev *pdev)
+ {
+ 	unsigned int devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
+ 	struct pci_dev *pdev0;
+@@ -96,7 +96,7 @@ static void cb710_release_slot(struct device *dev)
+ #endif
+ }
+ 
+-static int __devinit cb710_register_slot(struct cb710_chip *chip,
++static int cb710_register_slot(struct cb710_chip *chip,
+ 	unsigned slot_mask, unsigned io_offset, const char *name)
+ {
+ 	int nr = chip->slots;
+@@ -201,7 +201,7 @@ static int cb710_resume(struct pci_dev *pdev)
+ 
+ #endif /* CONFIG_PM */
+ 
+-static int __devinit cb710_probe(struct pci_dev *pdev,
++static int cb710_probe(struct pci_dev *pdev,
+ 	const struct pci_device_id *ent)
+ {
+ 	struct cb710_chip *chip;
+diff --git a/drivers/misc/cs5535-mfgpt.c b/drivers/misc/cs5535-mfgpt.c
+index f505a40a8f49..9858f36dad8b 100644
+--- a/drivers/misc/cs5535-mfgpt.c
++++ b/drivers/misc/cs5535-mfgpt.c
+@@ -246,7 +246,7 @@ EXPORT_SYMBOL_GPL(cs5535_mfgpt_write);
+  * Jordan tells me that he and Mitch once played w/ it, but it's unclear
+  * what the results of that were (and they experienced some instability).
+  */
+-static void __devinit reset_all_timers(void)
++static void reset_all_timers(void)
+ {
+ 	uint32_t val, dummy;
+ 
+@@ -262,7 +262,7 @@ static void __devinit reset_all_timers(void)
+  * In other cases (such as with VSAless OpenFirmware), the system firmware
+  * leaves timers available for us to use.
+  */
+-static int __devinit scan_timers(struct cs5535_mfgpt_chip *mfgpt)
++static int scan_timers(struct cs5535_mfgpt_chip *mfgpt)
+ {
+ 	struct cs5535_mfgpt_timer timer = { .chip = mfgpt };
+ 	unsigned long flags;
+@@ -289,7 +289,7 @@ static int __devinit scan_timers(struct cs5535_mfgpt_chip *mfgpt)
+ 	return timers;
+ }
+ 
+-static int __devinit cs5535_mfgpt_probe(struct platform_device *pdev)
++static int cs5535_mfgpt_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res;
+ 	int err = -EIO, t;
+diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c
+index 3dc14eafc5ce..3dd9005fd0e5 100644
+--- a/drivers/misc/eeprom/eeprom_93xx46.c
++++ b/drivers/misc/eeprom/eeprom_93xx46.c
+@@ -309,7 +309,7 @@ static ssize_t eeprom_93xx46_store_erase(struct device *dev,
+ }
+ static DEVICE_ATTR(erase, S_IWUSR, NULL, eeprom_93xx46_store_erase);
+ 
+-static int __devinit eeprom_93xx46_probe(struct spi_device *spi)
++static int eeprom_93xx46_probe(struct spi_device *spi)
+ {
+ 	struct eeprom_93xx46_platform_data *pd;
+ 	struct eeprom_93xx46_dev *edev;
+diff --git a/drivers/misc/fsa9480.c b/drivers/misc/fsa9480.c
+index 38b52b901678..2baa52f07c7a 100644
+--- a/drivers/misc/fsa9480.c
++++ b/drivers/misc/fsa9480.c
+@@ -407,7 +407,7 @@ static int fsa9480_irq_init(struct fsa9480_usbsw *usbsw)
+ 	return 0;
+ }
+ 
+-static int __devinit fsa9480_probe(struct i2c_client *client,
++static int fsa9480_probe(struct i2c_client *client,
+ 			 const struct i2c_device_id *id)
+ {
+ 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c
+index 47a9ce6b16fd..621c7a373390 100644
+--- a/drivers/misc/hpilo.c
++++ b/drivers/misc/hpilo.c
+@@ -686,7 +686,7 @@ static void ilo_unmap_device(struct pci_dev *pdev, struct ilo_hwinfo *hw)
+ 	pci_iounmap(pdev, hw->mmio_vaddr);
+ }
+ 
+-static int __devinit ilo_map_device(struct pci_dev *pdev, struct ilo_hwinfo *hw)
++static int ilo_map_device(struct pci_dev *pdev, struct ilo_hwinfo *hw)
+ {
+ 	int error = -ENOMEM;
+ 
+@@ -751,7 +751,7 @@ static void ilo_remove(struct pci_dev *pdev)
+ 	ilo_hwdev[(minor / max_ccb)] = 0;
+ }
+ 
+-static int __devinit ilo_probe(struct pci_dev *pdev,
++static int ilo_probe(struct pci_dev *pdev,
+ 			       const struct pci_device_id *ent)
+ {
+ 	int devnum, minor, start, error = 0;
+diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c
+index f34a92fd679b..380e4298ada1 100644
+--- a/drivers/misc/ibmasm/module.c
++++ b/drivers/misc/ibmasm/module.c
+@@ -62,7 +62,7 @@ module_param(ibmasm_debug, int , S_IRUGO | S_IWUSR);
+ MODULE_PARM_DESC(ibmasm_debug, " Set debug mode on or off");
+ 
+ 
+-static int __devinit ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
++static int ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ 	int result;
+ 	struct service_processor *sp;
+diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c
+index 794a7e002c87..3ef92dca5472 100644
+--- a/drivers/misc/ioc4.c
++++ b/drivers/misc/ioc4.c
+@@ -139,7 +139,7 @@ ioc4_unregister_submodule(struct ioc4_submodule *is)
+  * even though the following code utilizes external interrupt registers
+  * to perform the speed calculation.
+  */
+-static void __devinit
++static void
+ ioc4_clock_calibrate(struct ioc4_driver_data *idd)
+ {
+ 	union ioc4_int_out int_out;
+@@ -231,7 +231,7 @@ ioc4_clock_calibrate(struct ioc4_driver_data *idd)
+  * on the same PCI bus at slot number 3 to differentiate IO9 from IO10.
+  * If neither is present, it's a PCI-RT.
+  */
+-static unsigned int __devinit
++static unsigned int
+ ioc4_variant(struct ioc4_driver_data *idd)
+ {
+ 	struct pci_dev *pdev = NULL;
+@@ -279,7 +279,7 @@ ioc4_load_modules(struct work_struct *work)
+ static DECLARE_WORK(ioc4_load_modules_work, ioc4_load_modules);
+ 
+ /* Adds a new instance of an IOC4 card */
+-static int __devinit
++static int
+ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+ {
+ 	struct ioc4_driver_data *idd;
+diff --git a/drivers/misc/isl29003.c b/drivers/misc/isl29003.c
+index bef5307296f7..9fd4c0c6e599 100644
+--- a/drivers/misc/isl29003.c
++++ b/drivers/misc/isl29003.c
+@@ -365,7 +365,7 @@ static int isl29003_init_client(struct i2c_client *client)
+  * I2C layer
+  */
+ 
+-static int __devinit isl29003_probe(struct i2c_client *client,
++static int isl29003_probe(struct i2c_client *client,
+ 				    const struct i2c_device_id *id)
+ {
+ 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+diff --git a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
+index 403804c86127..66f0483efb03 100644
+--- a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
++++ b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
+@@ -114,7 +114,7 @@ static struct of_device_id lis3lv02d_i2c_dt_ids[] = {
+ MODULE_DEVICE_TABLE(of, lis3lv02d_i2c_dt_ids);
+ #endif
+ 
+-static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
++static int lis3lv02d_i2c_probe(struct i2c_client *client,
+ 					const struct i2c_device_id *id)
+ {
+ 	int ret = 0;
+diff --git a/drivers/misc/lis3lv02d/lis3lv02d_spi.c b/drivers/misc/lis3lv02d/lis3lv02d_spi.c
+index 0e415c31e035..66a751d2ed53 100644
+--- a/drivers/misc/lis3lv02d/lis3lv02d_spi.c
++++ b/drivers/misc/lis3lv02d/lis3lv02d_spi.c
+@@ -69,7 +69,7 @@ static struct of_device_id lis302dl_spi_dt_ids[] = {
+ MODULE_DEVICE_TABLE(of, lis302dl_spi_dt_ids);
+ #endif
+ 
+-static int __devinit lis302dl_spi_probe(struct spi_device *spi)
++static int lis302dl_spi_probe(struct spi_device *spi)
+ {
+ 	int ret;
+ 
+diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
+index f432b8d7e19b..4782c582ae38 100644
+--- a/drivers/misc/mei/main.c
++++ b/drivers/misc/mei/main.c
+@@ -743,7 +743,7 @@ static struct miscdevice  mei_misc_device = {
+  *
+  * returns true if ME Interface is valid, false otherwise
+  */
+-static bool __devinit mei_quirk_probe(struct pci_dev *pdev,
++static bool mei_quirk_probe(struct pci_dev *pdev,
+ 				const struct pci_device_id *ent)
+ {
+ 	u32 reg;
+@@ -765,7 +765,7 @@ static bool __devinit mei_quirk_probe(struct pci_dev *pdev,
+  *
+  * returns 0 on success, <0 on failure.
+  */
+-static int __devinit mei_probe(struct pci_dev *pdev,
++static int mei_probe(struct pci_dev *pdev,
+ 				const struct pci_device_id *ent)
+ {
+ 	struct mei_device *dev;
+diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c
+index 5581774393c8..3896cff2579f 100644
+--- a/drivers/misc/pch_phub.c
++++ b/drivers/misc/pch_phub.c
+@@ -666,7 +666,7 @@ static struct bin_attribute pch_bin_attr = {
+ 	.write = pch_phub_bin_write,
+ };
+ 
+-static int __devinit pch_phub_probe(struct pci_dev *pdev,
++static int pch_phub_probe(struct pci_dev *pdev,
+ 				    const struct pci_device_id *id)
+ {
+ 	int retval;
+diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
+index 79038e9ced0f..394150df2afe 100644
+--- a/drivers/misc/phantom.c
++++ b/drivers/misc/phantom.c
+@@ -324,7 +324,7 @@ static irqreturn_t phantom_isr(int irq, void *data)
+  * Init and deinit driver
+  */
+ 
+-static unsigned int __devinit phantom_get_free(void)
++static unsigned int phantom_get_free(void)
+ {
+ 	unsigned int i;
+ 
+@@ -335,7 +335,7 @@ static unsigned int __devinit phantom_get_free(void)
+ 	return i;
+ }
+ 
+-static int __devinit phantom_probe(struct pci_dev *pdev,
++static int phantom_probe(struct pci_dev *pdev,
+ 	const struct pci_device_id *pci_id)
+ {
+ 	struct phantom_device *pht;
+diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c
+index 3c5d74638eaf..e1a898e97f7c 100644
+--- a/drivers/misc/pti.c
++++ b/drivers/misc/pti.c
+@@ -796,7 +796,7 @@ static const struct tty_port_operations tty_port_ops = {
+  *	0 for success
+  *	otherwise, error
+  */
+-static int __devinit pti_pci_probe(struct pci_dev *pdev,
++static int pti_pci_probe(struct pci_dev *pdev,
+ 		const struct pci_device_id *ent)
+ {
+ 	unsigned int a;
+diff --git a/drivers/misc/spear13xx_pcie_gadget.c b/drivers/misc/spear13xx_pcie_gadget.c
+index 123ed98eec3e..7850320462fb 100644
+--- a/drivers/misc/spear13xx_pcie_gadget.c
++++ b/drivers/misc/spear13xx_pcie_gadget.c
+@@ -711,7 +711,7 @@ static void spear13xx_pcie_device_init(struct spear_pcie_gadget_config *config)
+ 	spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 1);
+ }
+ 
+-static int __devinit spear_pcie_gadget_probe(struct platform_device *pdev)
++static int spear_pcie_gadget_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res0, *res1;
+ 	unsigned int status = 0;
+diff --git a/drivers/misc/ti_dac7512.c b/drivers/misc/ti_dac7512.c
+index 85989ca7ad25..1222f86dfda9 100644
+--- a/drivers/misc/ti_dac7512.c
++++ b/drivers/misc/ti_dac7512.c
+@@ -54,7 +54,7 @@ static const struct attribute_group dac7512_attr_group = {
+ 	.attrs = dac7512_attributes,
+ };
+ 
+-static int __devinit dac7512_probe(struct spi_device *spi)
++static int dac7512_probe(struct spi_device *spi)
+ {
+ 	int ret;
+ 
+diff --git a/drivers/misc/tsl2550.c b/drivers/misc/tsl2550.c
+index 09ffb0b705f3..18bce70b30f2 100644
+--- a/drivers/misc/tsl2550.c
++++ b/drivers/misc/tsl2550.c
+@@ -347,7 +347,7 @@ static int tsl2550_init_client(struct i2c_client *client)
+  */
+ 
+ static struct i2c_driver tsl2550_driver;
+-static int __devinit tsl2550_probe(struct i2c_client *client,
++static int tsl2550_probe(struct i2c_client *client,
+ 				   const struct i2c_device_id *id)
+ {
+ 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);

commit 2d6bed9ca93e98685bc5038d686984fd449cd978
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:23 2012 -0500
+
+    drivers/misc: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: "Michał Mirosław" 
+    Cc: Wolfram Sang 
+    Cc: Eric Piel 
+    Cc: Jiri Slaby 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/misc/ad525x_dpot-i2c.c b/drivers/misc/ad525x_dpot-i2c.c
+index 820826270b62..7254a98a89f6 100644
+--- a/drivers/misc/ad525x_dpot-i2c.c
++++ b/drivers/misc/ad525x_dpot-i2c.c
+@@ -109,7 +109,7 @@ static struct i2c_driver ad_dpot_i2c_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= ad_dpot_i2c_probe,
+-	.remove		= __devexit_p(ad_dpot_i2c_remove),
++	.remove		= ad_dpot_i2c_remove,
+ 	.id_table	= ad_dpot_id,
+ };
+ 
+diff --git a/drivers/misc/ad525x_dpot-spi.c b/drivers/misc/ad525x_dpot-spi.c
+index f62317540d00..67e3073c2a6f 100644
+--- a/drivers/misc/ad525x_dpot-spi.c
++++ b/drivers/misc/ad525x_dpot-spi.c
+@@ -131,7 +131,7 @@ static struct spi_driver ad_dpot_spi_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= ad_dpot_spi_probe,
+-	.remove		= __devexit_p(ad_dpot_spi_remove),
++	.remove		= ad_dpot_spi_remove,
+ 	.id_table	= ad_dpot_spi_id,
+ };
+ 
+diff --git a/drivers/misc/apds9802als.c b/drivers/misc/apds9802als.c
+index 94923d259910..0132d15a995c 100644
+--- a/drivers/misc/apds9802als.c
++++ b/drivers/misc/apds9802als.c
+@@ -326,7 +326,7 @@ static struct i2c_driver apds9802als_driver = {
+ 		.pm = APDS9802ALS_PM_OPS,
+ 	},
+ 	.probe = apds9802als_probe,
+-	.remove = __devexit_p(apds9802als_remove),
++	.remove = apds9802als_remove,
+ 	.suspend = apds9802als_suspend,
+ 	.resume = apds9802als_resume,
+ 	.id_table = apds9802als_id,
+diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c
+index ee74244aa03b..f955d546f2df 100644
+--- a/drivers/misc/apds990x.c
++++ b/drivers/misc/apds990x.c
+@@ -1275,7 +1275,7 @@ static struct i2c_driver apds990x_driver = {
+ 		.pm	= &apds990x_pm_ops,
+ 	},
+ 	.probe	  = apds990x_probe,
+-	.remove	  = __devexit_p(apds990x_remove),
++	.remove	  = apds990x_remove,
+ 	.id_table = apds990x_id,
+ };
+ 
+diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
+index 5bb187781074..191c2ce9d5e1 100644
+--- a/drivers/misc/atmel-ssc.c
++++ b/drivers/misc/atmel-ssc.c
+@@ -152,7 +152,7 @@ static int __devexit ssc_remove(struct platform_device *pdev)
+ }
+ 
+ static struct platform_driver ssc_driver = {
+-	.remove		= __devexit_p(ssc_remove),
++	.remove		= ssc_remove,
+ 	.driver		= {
+ 		.name		= "ssc",
+ 		.owner		= THIS_MODULE,
+diff --git a/drivers/misc/bh1770glc.c b/drivers/misc/bh1770glc.c
+index 3d56ae7ef8de..c4b65e26a76c 100644
+--- a/drivers/misc/bh1770glc.c
++++ b/drivers/misc/bh1770glc.c
+@@ -1395,7 +1395,7 @@ static struct i2c_driver bh1770_driver = {
+ 		.pm	= &bh1770_pm_ops,
+ 	},
+ 	.probe	  = bh1770_probe,
+-	.remove	  = __devexit_p(bh1770_remove),
++	.remove	  = bh1770_remove,
+ 	.id_table = bh1770_id,
+ };
+ 
+diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c
+index f1f9877f3fdf..54f6f39f990a 100644
+--- a/drivers/misc/bh1780gli.c
++++ b/drivers/misc/bh1780gli.c
+@@ -248,7 +248,7 @@ static const struct i2c_device_id bh1780_id[] = {
+ 
+ static struct i2c_driver bh1780_driver = {
+ 	.probe		= bh1780_probe,
+-	.remove		= __devexit_p(bh1780_remove),
++	.remove		= bh1780_remove,
+ 	.id_table	= bh1780_id,
+ 	.driver = {
+ 		.name = "bh1780",
+diff --git a/drivers/misc/bmp085-i2c.c b/drivers/misc/bmp085-i2c.c
+index a4f33c995ea1..08cd7958c147 100644
+--- a/drivers/misc/bmp085-i2c.c
++++ b/drivers/misc/bmp085-i2c.c
+@@ -71,7 +71,7 @@ static struct i2c_driver bmp085_i2c_driver = {
+ 	},
+ 	.id_table	= bmp085_id,
+ 	.probe		= bmp085_i2c_probe,
+-	.remove		= __devexit_p(bmp085_i2c_remove),
++	.remove		= bmp085_i2c_remove,
+ 
+ 	.detect		= bmp085_i2c_detect,
+ 	.address_list	= normal_i2c
+diff --git a/drivers/misc/bmp085-spi.c b/drivers/misc/bmp085-spi.c
+index 5e982af99730..ed34885a6b3f 100644
+--- a/drivers/misc/bmp085-spi.c
++++ b/drivers/misc/bmp085-spi.c
+@@ -70,7 +70,7 @@ static struct spi_driver bmp085_spi_driver = {
+ 	},
+ 	.id_table	= bmp085_id,
+ 	.probe		= bmp085_spi_probe,
+-	.remove		= __devexit_p(bmp085_spi_remove)
++	.remove		= bmp085_spi_remove
+ };
+ 
+ module_spi_driver(bmp085_spi_driver);
+diff --git a/drivers/misc/cb710/core.c b/drivers/misc/cb710/core.c
+index 9d5eed754666..489c468cf965 100644
+--- a/drivers/misc/cb710/core.c
++++ b/drivers/misc/cb710/core.c
+@@ -332,7 +332,7 @@ static struct pci_driver cb710_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = cb710_pci_tbl,
+ 	.probe = cb710_probe,
+-	.remove = __devexit_p(cb710_remove_one),
++	.remove = cb710_remove_one,
+ #ifdef CONFIG_PM
+ 	.suspend = cb710_suspend,
+ 	.resume = cb710_resume,
+diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
+index ab1ad41786d1..3c36997bdacd 100644
+--- a/drivers/misc/eeprom/at24.c
++++ b/drivers/misc/eeprom/at24.c
+@@ -680,7 +680,7 @@ static struct i2c_driver at24_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = at24_probe,
+-	.remove = __devexit_p(at24_remove),
++	.remove = at24_remove,
+ 	.id_table = at24_ids,
+ };
+ 
+diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
+index 4ed93dd54116..fcb237e9bb1a 100644
+--- a/drivers/misc/eeprom/at25.c
++++ b/drivers/misc/eeprom/at25.c
+@@ -477,7 +477,7 @@ static struct spi_driver at25_driver = {
+ 		.owner		= THIS_MODULE,
+ 	},
+ 	.probe		= at25_probe,
+-	.remove		= __devexit_p(at25_remove),
++	.remove		= at25_remove,
+ };
+ 
+ module_spi_driver(at25_driver);
+diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c
+index ce3fe3633dd7..3dc14eafc5ce 100644
+--- a/drivers/misc/eeprom/eeprom_93xx46.c
++++ b/drivers/misc/eeprom/eeprom_93xx46.c
+@@ -389,7 +389,7 @@ static struct spi_driver eeprom_93xx46_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= eeprom_93xx46_probe,
+-	.remove		= __devexit_p(eeprom_93xx46_remove),
++	.remove		= eeprom_93xx46_remove,
+ };
+ 
+ module_spi_driver(eeprom_93xx46_driver);
+diff --git a/drivers/misc/fsa9480.c b/drivers/misc/fsa9480.c
+index ac96c3a4034a..38b52b901678 100644
+--- a/drivers/misc/fsa9480.c
++++ b/drivers/misc/fsa9480.c
+@@ -533,7 +533,7 @@ static struct i2c_driver fsa9480_i2c_driver = {
+ 		.name = "fsa9480",
+ 	},
+ 	.probe = fsa9480_probe,
+-	.remove = __devexit_p(fsa9480_remove),
++	.remove = fsa9480_remove,
+ 	.resume = fsa9480_resume,
+ 	.suspend = fsa9480_suspend,
+ 	.id_table = fsa9480_id,
+diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c
+index b362d938e929..47a9ce6b16fd 100644
+--- a/drivers/misc/hpilo.c
++++ b/drivers/misc/hpilo.c
+@@ -859,7 +859,7 @@ static struct pci_driver ilo_driver = {
+ 	.name 	  = ILO_NAME,
+ 	.id_table = ilo_devices,
+ 	.probe 	  = ilo_probe,
+-	.remove   = __devexit_p(ilo_remove),
++	.remove   = ilo_remove,
+ };
+ 
+ static int __init ilo_init(void)
+diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c
+index 168d8008f460..f34a92fd679b 100644
+--- a/drivers/misc/ibmasm/module.c
++++ b/drivers/misc/ibmasm/module.c
+@@ -198,7 +198,7 @@ static struct pci_driver ibmasm_driver = {
+ 	.name		= DRIVER_NAME,
+ 	.id_table	= ibmasm_pci_table,
+ 	.probe		= ibmasm_init_one,
+-	.remove		= __devexit_p(ibmasm_remove_one),
++	.remove		= ibmasm_remove_one,
+ };
+ 
+ static void __exit ibmasm_exit (void)
+diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c
+index 6a7710603a90..794a7e002c87 100644
+--- a/drivers/misc/ioc4.c
++++ b/drivers/misc/ioc4.c
+@@ -466,7 +466,7 @@ static struct pci_driver ioc4_driver = {
+ 	.name = "IOC4",
+ 	.id_table = ioc4_id_table,
+ 	.probe = ioc4_probe,
+-	.remove = __devexit_p(ioc4_remove),
++	.remove = ioc4_remove,
+ };
+ 
+ MODULE_DEVICE_TABLE(pci, ioc4_id_table);
+diff --git a/drivers/misc/isl29003.c b/drivers/misc/isl29003.c
+index eb5de2e210d7..bef5307296f7 100644
+--- a/drivers/misc/isl29003.c
++++ b/drivers/misc/isl29003.c
+@@ -451,7 +451,7 @@ static struct i2c_driver isl29003_driver = {
+ 	.suspend = isl29003_suspend,
+ 	.resume	= isl29003_resume,
+ 	.probe	= isl29003_probe,
+-	.remove	= __devexit_p(isl29003_remove),
++	.remove	= isl29003_remove,
+ 	.id_table = isl29003_id,
+ };
+ 
+diff --git a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
+index 60ec8689d6e3..403804c86127 100644
+--- a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
++++ b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
+@@ -280,7 +280,7 @@ static struct i2c_driver lis3lv02d_i2c_driver = {
+ 		.of_match_table = of_match_ptr(lis3lv02d_i2c_dt_ids),
+ 	},
+ 	.probe	= lis3lv02d_i2c_probe,
+-	.remove	= __devexit_p(lis3lv02d_i2c_remove),
++	.remove	= lis3lv02d_i2c_remove,
+ 	.id_table = lis3lv02d_id,
+ };
+ 
+diff --git a/drivers/misc/lis3lv02d/lis3lv02d_spi.c b/drivers/misc/lis3lv02d/lis3lv02d_spi.c
+index ccb6475fa059..0e415c31e035 100644
+--- a/drivers/misc/lis3lv02d/lis3lv02d_spi.c
++++ b/drivers/misc/lis3lv02d/lis3lv02d_spi.c
+@@ -144,7 +144,7 @@ static struct spi_driver lis302dl_spi_driver = {
+ 		.of_match_table = of_match_ptr(lis302dl_spi_dt_ids),
+ 	},
+ 	.probe	= lis302dl_spi_probe,
+-	.remove	= __devexit_p(lis302dl_spi_remove),
++	.remove	= lis302dl_spi_remove,
+ };
+ 
+ module_spi_driver(lis302dl_spi_driver);
+diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c
+index c9f20dae1855..5581774393c8 100644
+--- a/drivers/misc/pch_phub.c
++++ b/drivers/misc/pch_phub.c
+@@ -888,7 +888,7 @@ static struct pci_driver pch_phub_driver = {
+ 	.name = "pch_phub",
+ 	.id_table = pch_phub_pcidev_id,
+ 	.probe = pch_phub_probe,
+-	.remove = __devexit_p(pch_phub_remove),
++	.remove = pch_phub_remove,
+ 	.suspend = pch_phub_suspend,
+ 	.resume = pch_phub_resume
+ };
+diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
+index 21b28fc6d912..79038e9ced0f 100644
+--- a/drivers/misc/phantom.c
++++ b/drivers/misc/phantom.c
+@@ -499,7 +499,7 @@ static struct pci_driver phantom_pci_driver = {
+ 	.name = "phantom",
+ 	.id_table = phantom_pci_tbl,
+ 	.probe = phantom_probe,
+-	.remove = __devexit_p(phantom_remove),
++	.remove = phantom_remove,
+ 	.suspend = phantom_suspend,
+ 	.resume = phantom_resume
+ };
+diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c
+index 4999b34b7a60..3c5d74638eaf 100644
+--- a/drivers/misc/pti.c
++++ b/drivers/misc/pti.c
+@@ -901,7 +901,7 @@ static struct pci_driver pti_pci_driver = {
+ 	.name		= PCINAME,
+ 	.id_table	= pci_ids,
+ 	.probe		= pti_pci_probe,
+-	.remove		= __devexit_p(pti_pci_remove),
++	.remove		= pti_pci_remove,
+ };
+ 
+ /**
+diff --git a/drivers/misc/ti_dac7512.c b/drivers/misc/ti_dac7512.c
+index 5acbba120de0..85989ca7ad25 100644
+--- a/drivers/misc/ti_dac7512.c
++++ b/drivers/misc/ti_dac7512.c
+@@ -79,7 +79,7 @@ static struct spi_driver dac7512_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe	= dac7512_probe,
+-	.remove	= __devexit_p(dac7512_remove),
++	.remove	= dac7512_remove,
+ };
+ 
+ module_spi_driver(dac7512_driver);
+diff --git a/drivers/misc/tsl2550.c b/drivers/misc/tsl2550.c
+index 0beb298a17dd..09ffb0b705f3 100644
+--- a/drivers/misc/tsl2550.c
++++ b/drivers/misc/tsl2550.c
+@@ -450,7 +450,7 @@ static struct i2c_driver tsl2550_driver = {
+ 	.suspend = tsl2550_suspend,
+ 	.resume	= tsl2550_resume,
+ 	.probe	= tsl2550_probe,
+-	.remove	= __devexit_p(tsl2550_remove),
++	.remove	= tsl2550_remove,
+ 	.id_table = tsl2550_id,
+ };
+ 

commit 9306a8b0c29e11d823b258f5796353a4fe3e3be3
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:20:25 2012 -0500
+
+    mei: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Tomas Winkler 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
+index 7c9c381e5c9a..f432b8d7e19b 100644
+--- a/drivers/misc/mei/main.c
++++ b/drivers/misc/mei/main.c
+@@ -1023,8 +1023,8 @@ static struct pci_driver mei_driver = {
+ 	.name = KBUILD_MODNAME,
+ 	.id_table = mei_pci_tbl,
+ 	.probe = mei_probe,
+-	.remove = __devexit_p(mei_remove),
+-	.shutdown = __devexit_p(mei_remove),
++	.remove = mei_remove,
++	.shutdown = mei_remove,
+ 	.driver.pm = MEI_PM_OPS,
+ };
+ 

commit 2c9e9fdc0b2d55886609f0503fb91f96dfec6948
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:19:15 2012 -0500
+
+    w1: remove CONFIG_HOTPLUG ifdefs
+    
+    Remove conditional code based on CONFIG_HOTPLUG being false.  It's
+    always on now in preparation of it going away as an option.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Evgeniy Polyakov 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
+index 1a574370d2cd..7994d933f040 100644
+--- a/drivers/w1/w1.c
++++ b/drivers/w1/w1.c
+@@ -551,7 +551,6 @@ void w1_destroy_master_attributes(struct w1_master *master)
+ 	sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group);
+ }
+ 
+-#ifdef CONFIG_HOTPLUG
+ static int w1_uevent(struct device *dev, struct kobj_uevent_env *env)
+ {
+ 	struct w1_master *md = NULL;
+@@ -587,12 +586,6 @@ static int w1_uevent(struct device *dev, struct kobj_uevent_env *env)
+ end:
+ 	return err;
+ }
+-#else
+-static int w1_uevent(struct device *dev, struct kobj_uevent_env *env)
+-{
+-	return 0;
+-}
+-#endif
+ 
+ static int __w1_attach_slave_device(struct w1_slave *sl)
+ {

commit 82849a93aad04c5a438d811081341b245fdade8c
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:23 2012 -0500
+
+    w1: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Evgeniy Polyakov 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/w1/masters/matrox_w1.c b/drivers/w1/masters/matrox_w1.c
+index 1197f7ec54f2..d8667b0212d7 100644
+--- a/drivers/w1/masters/matrox_w1.c
++++ b/drivers/w1/masters/matrox_w1.c
+@@ -49,7 +49,7 @@ static struct pci_device_id matrox_w1_tbl[] = {
+ MODULE_DEVICE_TABLE(pci, matrox_w1_tbl);
+ 
+ static int matrox_w1_probe(struct pci_dev *, const struct pci_device_id *);
+-static void __devexit matrox_w1_remove(struct pci_dev *);
++static void matrox_w1_remove(struct pci_dev *);
+ 
+ static struct pci_driver matrox_w1_pci_driver = {
+ 	.name = "matrox_w1",
+@@ -220,7 +220,7 @@ static int matrox_w1_probe(struct pci_dev *pdev, const struct pci_device_id *ent
+ 	return err;
+ }
+ 
+-static void __devexit matrox_w1_remove(struct pci_dev *pdev)
++static void matrox_w1_remove(struct pci_dev *pdev)
+ {
+ 	struct matrox_device *dev = pci_get_drvdata(pdev);
+ 
+diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c
+index 23d391757491..d338b56ea2f0 100644
+--- a/drivers/w1/masters/mxc_w1.c
++++ b/drivers/w1/masters/mxc_w1.c
+@@ -167,7 +167,7 @@ static int mxc_w1_probe(struct platform_device *pdev)
+ /*
+  * disassociate the w1 device from the driver
+  */
+-static int __devexit mxc_w1_remove(struct platform_device *pdev)
++static int mxc_w1_remove(struct platform_device *pdev)
+ {
+ 	struct mxc_w1_device *mdev = platform_get_drvdata(pdev);
+ 	struct resource *res;
+diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c
+index d3bdcc320eda..184dbce4abd1 100644
+--- a/drivers/w1/masters/omap_hdq.c
++++ b/drivers/w1/masters/omap_hdq.c
+@@ -70,7 +70,7 @@ struct hdq_data {
+ };
+ 
+ static int omap_hdq_probe(struct platform_device *pdev);
+-static int __devexit omap_hdq_remove(struct platform_device *pdev);
++static int omap_hdq_remove(struct platform_device *pdev);
+ 
+ static struct platform_driver omap_hdq_driver = {
+ 	.probe =	omap_hdq_probe,
+@@ -613,7 +613,7 @@ static int omap_hdq_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit omap_hdq_remove(struct platform_device *pdev)
++static int omap_hdq_remove(struct platform_device *pdev)
+ {
+ 	struct hdq_data *hdq_data = platform_get_drvdata(pdev);
+ 

commit 479e2bcecdf19ae44940d38248a3e2f9fd8f2c44
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:43 2012 -0500
+
+    w1: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Evgeniy Polyakov 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/w1/masters/matrox_w1.c b/drivers/w1/masters/matrox_w1.c
+index 0a3c423a0c9d..1197f7ec54f2 100644
+--- a/drivers/w1/masters/matrox_w1.c
++++ b/drivers/w1/masters/matrox_w1.c
+@@ -48,7 +48,7 @@ static struct pci_device_id matrox_w1_tbl[] = {
+ };
+ MODULE_DEVICE_TABLE(pci, matrox_w1_tbl);
+ 
+-static int __devinit matrox_w1_probe(struct pci_dev *, const struct pci_device_id *);
++static int matrox_w1_probe(struct pci_dev *, const struct pci_device_id *);
+ static void __devexit matrox_w1_remove(struct pci_dev *);
+ 
+ static struct pci_driver matrox_w1_pci_driver = {
+@@ -152,7 +152,7 @@ static void matrox_w1_hw_init(struct matrox_device *dev)
+ 	matrox_w1_write_reg(dev, MATROX_GET_CONTROL, 0x00);
+ }
+ 
+-static int __devinit matrox_w1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
++static int matrox_w1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ 	struct matrox_device *dev;
+ 	int err;
+diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c
+index 53f89fa3bde6..23d391757491 100644
+--- a/drivers/w1/masters/mxc_w1.c
++++ b/drivers/w1/masters/mxc_w1.c
+@@ -103,7 +103,7 @@ static u8 mxc_w1_ds2_touch_bit(void *data, u8 bit)
+ 	return ((__raw_readb(ctrl_addr)) >> 3) & 0x1;
+ }
+ 
+-static int __devinit mxc_w1_probe(struct platform_device *pdev)
++static int mxc_w1_probe(struct platform_device *pdev)
+ {
+ 	struct mxc_w1_device *mdev;
+ 	struct resource *res;
+diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c
+index 652ca7f207e3..d3bdcc320eda 100644
+--- a/drivers/w1/masters/omap_hdq.c
++++ b/drivers/w1/masters/omap_hdq.c
+@@ -69,7 +69,7 @@ struct hdq_data {
+ 	int			init_trans;
+ };
+ 
+-static int __devinit omap_hdq_probe(struct platform_device *pdev);
++static int omap_hdq_probe(struct platform_device *pdev);
+ static int __devexit omap_hdq_remove(struct platform_device *pdev);
+ 
+ static struct platform_driver omap_hdq_driver = {
+@@ -537,7 +537,7 @@ static void omap_w1_write_byte(void *_hdq, u8 byte)
+ 	}
+ }
+ 
+-static int __devinit omap_hdq_probe(struct platform_device *pdev)
++static int omap_hdq_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	struct hdq_data *hdq_data;

commit f91a66c97b38a504827803bb93f83a7b85e50e5a
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:21:14 2012 -0500
+
+    w1: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Evgeniy Polyakov 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/w1/masters/matrox_w1.c b/drivers/w1/masters/matrox_w1.c
+index f667c26b2195..0a3c423a0c9d 100644
+--- a/drivers/w1/masters/matrox_w1.c
++++ b/drivers/w1/masters/matrox_w1.c
+@@ -55,7 +55,7 @@ static struct pci_driver matrox_w1_pci_driver = {
+ 	.name = "matrox_w1",
+ 	.id_table = matrox_w1_tbl,
+ 	.probe = matrox_w1_probe,
+-	.remove = __devexit_p(matrox_w1_remove),
++	.remove = matrox_w1_remove,
+ };
+ 
+ /*
+diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c
+index ca8e60bb2f9c..652ca7f207e3 100644
+--- a/drivers/w1/masters/omap_hdq.c
++++ b/drivers/w1/masters/omap_hdq.c
+@@ -74,7 +74,7 @@ static int __devexit omap_hdq_remove(struct platform_device *pdev);
+ 
+ static struct platform_driver omap_hdq_driver = {
+ 	.probe =	omap_hdq_probe,
+-	.remove =	__devexit_p(omap_hdq_remove),
++	.remove =	omap_hdq_remove,
+ 	.driver =	{
+ 		.name =	"omap_hdq",
+ 	},

commit c0e61cb151f2ff8edd02af23b2bd49f625288124
+Author: Bill Pemberton 
+Date:   Wed Nov 21 01:18:49 2012 +0100
+
+    cpufreq: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c
+index 8d7ebb286e6f..f1fa500ac105 100644
+--- a/drivers/cpufreq/longhaul.c
++++ b/drivers/cpufreq/longhaul.c
+@@ -930,7 +930,7 @@ static int __cpuinit longhaul_cpu_init(struct cpufreq_policy *policy)
+ 	return 0;
+ }
+ 
+-static int __devexit longhaul_cpu_exit(struct cpufreq_policy *policy)
++static int longhaul_cpu_exit(struct cpufreq_policy *policy)
+ {
+ 	cpufreq_frequency_table_put_attr(policy->cpu);
+ 	return 0;
+diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c
+index 1fd0c8a48ed4..056faf6af1a9 100644
+--- a/drivers/cpufreq/powernow-k8.c
++++ b/drivers/cpufreq/powernow-k8.c
+@@ -1186,7 +1186,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
+ 	return -ENODEV;
+ }
+ 
+-static int __devexit powernowk8_cpu_exit(struct cpufreq_policy *pol)
++static int powernowk8_cpu_exit(struct cpufreq_policy *pol)
+ {
+ 	struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);
+ 

commit c5fa4ab5ab417d8d7bd658957ce7b7e6ef0cdaf3
+Author: Bill Pemberton 
+Date:   Wed Nov 21 01:18:40 2012 +0100
+
+    cpufreq: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
+index e9158278c71d..52bf36d599f5 100644
+--- a/drivers/cpufreq/cpufreq-cpu0.c
++++ b/drivers/cpufreq/cpufreq-cpu0.c
+@@ -174,7 +174,7 @@ static struct cpufreq_driver cpu0_cpufreq_driver = {
+ 	.attr = cpu0_cpufreq_attr,
+ };
+ 
+-static int __devinit cpu0_cpufreq_driver_init(void)
++static int cpu0_cpufreq_driver_init(void)
+ {
+ 	struct device_node *np;
+ 	int ret;

commit ce2650d40dff23f2c6f9718bb3ec63e12c5c7f27
+Author: Bill Pemberton 
+Date:   Wed Nov 21 01:18:30 2012 +0100
+
+    cpufreq: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c
+index 53ddbc760af7..8d7ebb286e6f 100644
+--- a/drivers/cpufreq/longhaul.c
++++ b/drivers/cpufreq/longhaul.c
+@@ -946,7 +946,7 @@ static struct cpufreq_driver longhaul_driver = {
+ 	.target	= longhaul_target,
+ 	.get	= longhaul_get,
+ 	.init	= longhaul_cpu_init,
+-	.exit	= __devexit_p(longhaul_cpu_exit),
++	.exit	= longhaul_cpu_exit,
+ 	.name	= "longhaul",
+ 	.owner	= THIS_MODULE,
+ 	.attr	= longhaul_attr,
+diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c
+index e3ebb4fa2c3e..1fd0c8a48ed4 100644
+--- a/drivers/cpufreq/powernow-k8.c
++++ b/drivers/cpufreq/powernow-k8.c
+@@ -1242,7 +1242,7 @@ static struct cpufreq_driver cpufreq_amd64_driver = {
+ 	.target		= powernowk8_target,
+ 	.bios_limit	= acpi_processor_get_bios_limit,
+ 	.init		= powernowk8_cpu_init,
+-	.exit		= __devexit_p(powernowk8_cpu_exit),
++	.exit		= powernowk8_cpu_exit,
+ 	.get		= powernowk8_get,
+ 	.name		= "powernow-k8",
+ 	.owner		= THIS_MODULE,

commit 6939565fa55e5c1dcce98979eb071278e10acf15
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:19:39 2012 -0500
+
+    ASoC: max98088: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed, remove it.
+    
+    Also fix the indentation for the initialization of the
+    max98088_i2c_driver struct to make chkpatch happy.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Jaroslav Kysela 
+    Cc: Takashi Iwai 
+    Cc: alsa-devel@alsa-project.org
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
+index 3264a5169306..b858264235c4 100644
+--- a/sound/soc/codecs/max98088.c
++++ b/sound/soc/codecs/max98088.c
+@@ -2098,13 +2098,13 @@ static const struct i2c_device_id max98088_i2c_id[] = {
+ MODULE_DEVICE_TABLE(i2c, max98088_i2c_id);
+ 
+ static struct i2c_driver max98088_i2c_driver = {
+-       .driver = {
+-               .name = "max98088",
+-               .owner = THIS_MODULE,
+-       },
+-       .probe  = max98088_i2c_probe,
+-       .remove = __devexit_p(max98088_i2c_remove),
+-       .id_table = max98088_i2c_id,
++	.driver = {
++		.name = "max98088",
++		.owner = THIS_MODULE,
++	},
++	.probe  = max98088_i2c_probe,
++	.remove = max98088_i2c_remove,
++	.id_table = max98088_i2c_id,
+ };
+ 
+ module_i2c_driver(max98088_i2c_driver);

commit f6e6574499eeeeee747d9cfc7ba9f4328bb1806d
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:25:33 2012 -0500
+
+    ASoC: remove use of __devinitconst
+    
+    CONFIG_HOTPLUG is going away as an option so __devinitconst is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c
+index 7f567585832e..9f57996ff272 100644
+--- a/sound/soc/codecs/wm5100.c
++++ b/sound/soc/codecs/wm5100.c
+@@ -1233,7 +1233,7 @@ static const struct snd_soc_dapm_route wm5100_dapm_routes[] = {
+ 	{ "PWM2", NULL, "PWM2 Driver" },
+ };
+ 
+-static const __devinitconst struct reg_default wm5100_reva_patches[] = {
++static const struct reg_default wm5100_reva_patches[] = {
+ 	{ WM5100_AUDIO_IF_1_10, 0 },
+ 	{ WM5100_AUDIO_IF_1_11, 1 },
+ 	{ WM5100_AUDIO_IF_1_12, 2 },
+diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
+index 10d21be383f6..2153e19d8208 100644
+--- a/sound/soc/soc-core.c
++++ b/sound/soc/soc-core.c
+@@ -4007,7 +4007,7 @@ int snd_soc_register_codec(struct device *dev,
+ 		codec->reg_size = reg_size;
+ 		/* it is necessary to make a copy of the default register cache
+ 		 * because in the case of using a compression type that requires
+-		 * the default register cache to be marked as __devinitconst the
++		 * the default register cache to be marked as the
+ 		 * kernel might have freed the array by the time we initialize
+ 		 * the cache.
+ 		 */
+diff --git a/sound/soc/tegra/tegra20_das.c b/sound/soc/tegra/tegra20_das.c
+index bf99296bce95..49653375970b 100644
+--- a/sound/soc/tegra/tegra20_das.c
++++ b/sound/soc/tegra/tegra20_das.c
+@@ -210,7 +210,7 @@ static int __devexit tegra20_das_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static const struct of_device_id tegra20_das_of_match[] __devinitconst = {
++static const struct of_device_id tegra20_das_of_match[] = {
+ 	{ .compatible = "nvidia,tegra20-das", },
+ 	{},
+ };
+diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c
+index 0832e8afd73c..2ae8af86edbd 100644
+--- a/sound/soc/tegra/tegra20_i2s.c
++++ b/sound/soc/tegra/tegra20_i2s.c
+@@ -463,12 +463,12 @@ static int __devexit tegra20_i2s_platform_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static const struct of_device_id tegra20_i2s_of_match[] __devinitconst = {
++static const struct of_device_id tegra20_i2s_of_match[] = {
+ 	{ .compatible = "nvidia,tegra20-i2s", },
+ 	{},
+ };
+ 
+-static const struct dev_pm_ops tegra20_i2s_pm_ops __devinitconst = {
++static const struct dev_pm_ops tegra20_i2s_pm_ops = {
+ 	SET_RUNTIME_PM_OPS(tegra20_i2s_runtime_suspend,
+ 			   tegra20_i2s_runtime_resume, NULL)
+ };
+diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c
+index 3ebc8670ba00..d9641ef7b1ee 100644
+--- a/sound/soc/tegra/tegra20_spdif.c
++++ b/sound/soc/tegra/tegra20_spdif.c
+@@ -373,7 +373,7 @@ static int __devexit tegra20_spdif_platform_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static const struct dev_pm_ops tegra20_spdif_pm_ops __devinitconst = {
++static const struct dev_pm_ops tegra20_spdif_pm_ops = {
+ 	SET_RUNTIME_PM_OPS(tegra20_spdif_runtime_suspend,
+ 			   tegra20_spdif_runtime_resume, NULL)
+ };
+diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c
+index bf5610122c76..2269170b0df4 100644
+--- a/sound/soc/tegra/tegra30_ahub.c
++++ b/sound/soc/tegra/tegra30_ahub.c
+@@ -288,7 +288,7 @@ int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif)
+ }
+ EXPORT_SYMBOL_GPL(tegra30_ahub_unset_rx_cif_source);
+ 
+-static const char * const configlink_clocks[] __devinitconst = {
++static const char * const configlink_clocks[] = {
+ 	"i2s0",
+ 	"i2s1",
+ 	"i2s2",
+@@ -603,12 +603,12 @@ static int __devexit tegra30_ahub_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static const struct of_device_id tegra30_ahub_of_match[] __devinitconst = {
++static const struct of_device_id tegra30_ahub_of_match[] = {
+ 	{ .compatible = "nvidia,tegra30-ahub", },
+ 	{},
+ };
+ 
+-static const struct dev_pm_ops tegra30_ahub_pm_ops __devinitconst = {
++static const struct dev_pm_ops tegra30_ahub_pm_ops = {
+ 	SET_RUNTIME_PM_OPS(tegra30_ahub_runtime_suspend,
+ 			   tegra30_ahub_runtime_resume, NULL)
+ };
+diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c
+index 44184228d1f0..bf0e089e7997 100644
+--- a/sound/soc/tegra/tegra30_i2s.c
++++ b/sound/soc/tegra/tegra30_i2s.c
+@@ -508,12 +508,12 @@ static int __devexit tegra30_i2s_platform_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static const struct of_device_id tegra30_i2s_of_match[] __devinitconst = {
++static const struct of_device_id tegra30_i2s_of_match[] = {
+ 	{ .compatible = "nvidia,tegra30-i2s", },
+ 	{},
+ };
+ 
+-static const struct dev_pm_ops tegra30_i2s_pm_ops __devinitconst = {
++static const struct dev_pm_ops tegra30_i2s_pm_ops = {
+ 	SET_RUNTIME_PM_OPS(tegra30_i2s_runtime_suspend,
+ 			   tegra30_i2s_runtime_resume, NULL)
+ };
+diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c
+index 76cb1b363b71..523795a6e83e 100644
+--- a/sound/soc/tegra/tegra_alc5632.c
++++ b/sound/soc/tegra/tegra_alc5632.c
+@@ -242,7 +242,7 @@ static int __devexit tegra_alc5632_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static const struct of_device_id tegra_alc5632_of_match[] __devinitconst = {
++static const struct of_device_id tegra_alc5632_of_match[] = {
+ 	{ .compatible = "nvidia,tegra-audio-alc5632", },
+ 	{},
+ };
+diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c
+index ea9166d5c4eb..effe5b41b5f9 100644
+--- a/sound/soc/tegra/tegra_wm8753.c
++++ b/sound/soc/tegra/tegra_wm8753.c
+@@ -200,7 +200,7 @@ static int __devexit tegra_wm8753_driver_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static const struct of_device_id tegra_wm8753_of_match[] __devinitconst = {
++static const struct of_device_id tegra_wm8753_of_match[] = {
+ 	{ .compatible = "nvidia,tegra-audio-wm8753", },
+ 	{},
+ };
+diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c
+index cee13b7bfb94..0f794126fbe4 100644
+--- a/sound/soc/tegra/tegra_wm8903.c
++++ b/sound/soc/tegra/tegra_wm8903.c
+@@ -417,7 +417,7 @@ static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static const struct of_device_id tegra_wm8903_of_match[] __devinitconst = {
++static const struct of_device_id tegra_wm8903_of_match[] = {
+ 	{ .compatible = "nvidia,tegra-audio-wm8903", },
+ 	{},
+ };
+diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c
+index e69a4f7000d6..4a255a4d0c47 100644
+--- a/sound/soc/tegra/trimslice.c
++++ b/sound/soc/tegra/trimslice.c
+@@ -195,7 +195,7 @@ static int __devexit tegra_snd_trimslice_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static const struct of_device_id trimslice_of_match[] __devinitconst = {
++static const struct of_device_id trimslice_of_match[] = {
+ 	{ .compatible = "nvidia,tegra-audio-trimslice", },
+ 	{},
+ };

commit 8dc995f56ef7aedb41873fdeaa1971f3aa166ebd
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:26:10 2012 -0500
+
+    regulator: remove use of __devexit
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit is no
+    longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c
+index c09b5d97f4e7..2b557119adad 100644
+--- a/drivers/regulator/88pm8607.c
++++ b/drivers/regulator/88pm8607.c
+@@ -454,7 +454,7 @@ static int pm8607_regulator_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit pm8607_regulator_remove(struct platform_device *pdev)
++static int pm8607_regulator_remove(struct platform_device *pdev)
+ {
+ 	struct pm8607_regulator_info *info = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c
+index 4285b304e2b5..8b5876356db9 100644
+--- a/drivers/regulator/aat2870-regulator.c
++++ b/drivers/regulator/aat2870-regulator.c
+@@ -187,7 +187,7 @@ static int aat2870_regulator_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit aat2870_regulator_remove(struct platform_device *pdev)
++static int aat2870_regulator_remove(struct platform_device *pdev)
+ {
+ 	struct regulator_dev *rdev = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c
+index 7a04d5fe4e93..111ec69a3e94 100644
+--- a/drivers/regulator/ab3100.c
++++ b/drivers/regulator/ab3100.c
+@@ -571,7 +571,7 @@ static int ab3100_regulators_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit ab3100_regulators_remove(struct platform_device *pdev)
++static int ab3100_regulators_remove(struct platform_device *pdev)
+ {
+ 	int i;
+ 
+diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c
+index af81325b8e2f..09014f38a948 100644
+--- a/drivers/regulator/ab8500.c
++++ b/drivers/regulator/ab8500.c
+@@ -817,7 +817,7 @@ static int ab8500_regulator_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static __devexit int ab8500_regulator_remove(struct platform_device *pdev)
++static int ab8500_regulator_remove(struct platform_device *pdev)
+ {
+ 	int i;
+ 
+diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c
+index cd855d9ac38a..6b981b5faa70 100644
+--- a/drivers/regulator/ad5398.c
++++ b/drivers/regulator/ad5398.c
+@@ -256,7 +256,7 @@ static int ad5398_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit ad5398_remove(struct i2c_client *client)
++static int ad5398_remove(struct i2c_client *client)
+ {
+ 	struct ad5398_chip_info *chip = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c
+index a900c2992f25..1aa5246c79d9 100644
+--- a/drivers/regulator/anatop-regulator.c
++++ b/drivers/regulator/anatop-regulator.c
+@@ -186,7 +186,7 @@ static int anatop_regulator_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit anatop_regulator_remove(struct platform_device *pdev)
++static int anatop_regulator_remove(struct platform_device *pdev)
+ {
+ 	struct regulator_dev *rdev = platform_get_drvdata(pdev);
+ 	struct anatop_regulator *sreg = rdev_get_drvdata(rdev);
+diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c
+index 7e9ad7cb8676..b44fa6f0e947 100644
+--- a/drivers/regulator/arizona-ldo1.c
++++ b/drivers/regulator/arizona-ldo1.c
+@@ -115,7 +115,7 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static __devexit int arizona_ldo1_remove(struct platform_device *pdev)
++static int arizona_ldo1_remove(struct platform_device *pdev)
+ {
+ 	struct arizona_ldo1 *ldo1 = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c
+index 3c3631c044fd..5ae2d3e794bf 100644
+--- a/drivers/regulator/arizona-micsupp.c
++++ b/drivers/regulator/arizona-micsupp.c
+@@ -166,7 +166,7 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static __devexit int arizona_micsupp_remove(struct platform_device *pdev)
++static int arizona_micsupp_remove(struct platform_device *pdev)
+ {
+ 	struct arizona_micsupp *micsupp = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c
+index ab4a6d677280..2afa5730f324 100644
+--- a/drivers/regulator/da903x.c
++++ b/drivers/regulator/da903x.c
+@@ -499,7 +499,7 @@ static int da903x_regulator_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit da903x_regulator_remove(struct platform_device *pdev)
++static int da903x_regulator_remove(struct platform_device *pdev)
+ {
+ 	struct regulator_dev *rdev = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c
+index ba703d80a21f..d6fbfd3dced5 100644
+--- a/drivers/regulator/da9052-regulator.c
++++ b/drivers/regulator/da9052-regulator.c
+@@ -430,7 +430,7 @@ static int da9052_regulator_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit da9052_regulator_remove(struct platform_device *pdev)
++static int da9052_regulator_remove(struct platform_device *pdev)
+ {
+ 	struct da9052_regulator *regulator = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/regulator/dbx500-prcmu.c b/drivers/regulator/dbx500-prcmu.c
+index afc3e89940ed..261f3d2299bc 100644
+--- a/drivers/regulator/dbx500-prcmu.c
++++ b/drivers/regulator/dbx500-prcmu.c
+@@ -230,7 +230,7 @@ ux500_regulator_debug_init(struct platform_device *pdev,
+ 	return -ENOMEM;
+ }
+ 
+-int __devexit ux500_regulator_debug_exit(void)
++int ux500_regulator_debug_exit(void)
+ {
+ 	debugfs_remove_recursive(rdebug.dir);
+ 	kfree(rdebug.state_after_suspend);
+diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c
+index 199172a3bbfa..9165b0c40ed3 100644
+--- a/drivers/regulator/fan53555.c
++++ b/drivers/regulator/fan53555.c
+@@ -293,7 +293,7 @@ static int fan53555_regulator_probe(struct i2c_client *client,
+ 
+ }
+ 
+-static int __devexit fan53555_regulator_remove(struct i2c_client *client)
++static int fan53555_regulator_remove(struct i2c_client *client)
+ {
+ 	struct fan53555_device_info *di = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
+index 5aa0be00cc31..48d5b7608b00 100644
+--- a/drivers/regulator/fixed.c
++++ b/drivers/regulator/fixed.c
+@@ -234,7 +234,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit reg_fixed_voltage_remove(struct platform_device *pdev)
++static int reg_fixed_voltage_remove(struct platform_device *pdev)
+ {
+ 	struct fixed_voltage_data *drvdata = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c
+index 5ffee5ec3660..3ee79c83ae57 100644
+--- a/drivers/regulator/gpio-regulator.c
++++ b/drivers/regulator/gpio-regulator.c
+@@ -348,7 +348,7 @@ static int gpio_regulator_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit gpio_regulator_remove(struct platform_device *pdev)
++static int gpio_regulator_remove(struct platform_device *pdev)
+ {
+ 	struct gpio_regulator_data *drvdata = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c
+index 1732108dda49..d1e5bee2a26b 100644
+--- a/drivers/regulator/isl6271a-regulator.c
++++ b/drivers/regulator/isl6271a-regulator.c
+@@ -151,7 +151,7 @@ static int isl6271a_probe(struct i2c_client *i2c,
+ 	return err;
+ }
+ 
+-static int __devexit isl6271a_remove(struct i2c_client *i2c)
++static int isl6271a_remove(struct i2c_client *i2c)
+ {
+ 	struct isl_pmic *pmic = i2c_get_clientdata(i2c);
+ 	int i;
+diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c
+index 95b7299e3ed2..5f68ff11a298 100644
+--- a/drivers/regulator/lp3971.c
++++ b/drivers/regulator/lp3971.c
+@@ -472,7 +472,7 @@ static int lp3971_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static int __devexit lp3971_i2c_remove(struct i2c_client *i2c)
++static int lp3971_i2c_remove(struct i2c_client *i2c)
+ {
+ 	struct lp3971 *lp3971 = i2c_get_clientdata(i2c);
+ 	int i;
+diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c
+index acf71beb1f57..69c42c318b87 100644
+--- a/drivers/regulator/lp3972.c
++++ b/drivers/regulator/lp3972.c
+@@ -569,7 +569,7 @@ static int lp3972_i2c_probe(struct i2c_client *i2c,
+ 	return ret;
+ }
+ 
+-static int __devexit lp3972_i2c_remove(struct i2c_client *i2c)
++static int lp3972_i2c_remove(struct i2c_client *i2c)
+ {
+ 	struct lp3972 *lp3972 = i2c_get_clientdata(i2c);
+ 	int i;
+diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c
+index 622ad5e5bab0..9289ead715ca 100644
+--- a/drivers/regulator/lp872x.c
++++ b/drivers/regulator/lp872x.c
+@@ -893,7 +893,7 @@ static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
+ 	return ret;
+ }
+ 
+-static int __devexit lp872x_remove(struct i2c_client *cl)
++static int lp872x_remove(struct i2c_client *cl)
+ {
+ 	struct lp872x *lp = i2c_get_clientdata(cl);
+ 
+diff --git a/drivers/regulator/lp8788-buck.c b/drivers/regulator/lp8788-buck.c
+index 1a3623ac066c..6cc02c35ddb5 100644
+--- a/drivers/regulator/lp8788-buck.c
++++ b/drivers/regulator/lp8788-buck.c
+@@ -542,7 +542,7 @@ static int lp8788_buck_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit lp8788_buck_remove(struct platform_device *pdev)
++static int lp8788_buck_remove(struct platform_device *pdev)
+ {
+ 	struct lp8788_buck *buck = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/regulator/lp8788-ldo.c b/drivers/regulator/lp8788-ldo.c
+index e69a5b62f443..26753a013789 100644
+--- a/drivers/regulator/lp8788-ldo.c
++++ b/drivers/regulator/lp8788-ldo.c
+@@ -749,7 +749,7 @@ static int lp8788_dldo_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit lp8788_dldo_remove(struct platform_device *pdev)
++static int lp8788_dldo_remove(struct platform_device *pdev)
+ {
+ 	struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
+ 
+@@ -805,7 +805,7 @@ static int lp8788_aldo_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit lp8788_aldo_remove(struct platform_device *pdev)
++static int lp8788_aldo_remove(struct platform_device *pdev)
+ {
+ 	struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c
+index 1609810a9a3d..3a035ece83c1 100644
+--- a/drivers/regulator/max1586.c
++++ b/drivers/regulator/max1586.c
+@@ -188,7 +188,7 @@ static int max1586_pmic_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit max1586_pmic_remove(struct i2c_client *client)
++static int max1586_pmic_remove(struct i2c_client *client)
+ {
+ 	struct max1586_data *max1586 = i2c_get_clientdata(client);
+ 	int i;
+diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c
+index da028d055ec7..cb99e9031a64 100644
+--- a/drivers/regulator/max77686.c
++++ b/drivers/regulator/max77686.c
+@@ -337,7 +337,7 @@ static int max77686_pmic_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit max77686_pmic_remove(struct platform_device *pdev)
++static int max77686_pmic_remove(struct platform_device *pdev)
+ {
+ 	struct max77686_data *max77686 = platform_get_drvdata(pdev);
+ 	int i;
+diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c
+index d4397f95f741..3ca14380f22d 100644
+--- a/drivers/regulator/max8649.c
++++ b/drivers/regulator/max8649.c
+@@ -271,7 +271,7 @@ static int max8649_regulator_probe(struct i2c_client *client,
+ 	return 0;
+ }
+ 
+-static int __devexit max8649_regulator_remove(struct i2c_client *client)
++static int max8649_regulator_remove(struct i2c_client *client)
+ {
+ 	struct max8649_regulator_info *info = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c
+index a44589f36a31..4d7c635c36c2 100644
+--- a/drivers/regulator/max8660.c
++++ b/drivers/regulator/max8660.c
+@@ -420,7 +420,7 @@ static int max8660_probe(struct i2c_client *client,
+ 	return ret;
+ }
+ 
+-static int __devexit max8660_remove(struct i2c_client *client)
++static int max8660_remove(struct i2c_client *client)
+ {
+ 	struct max8660 *max8660 = i2c_get_clientdata(client);
+ 	int i;
+diff --git a/drivers/regulator/max8907-regulator.c b/drivers/regulator/max8907-regulator.c
+index 99bae75970f1..d1a77512d83e 100644
+--- a/drivers/regulator/max8907-regulator.c
++++ b/drivers/regulator/max8907-regulator.c
+@@ -368,7 +368,7 @@ static int max8907_regulator_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static __devexit int max8907_regulator_remove(struct platform_device *pdev)
++static int max8907_regulator_remove(struct platform_device *pdev)
+ {
+ 	struct max8907_regulator *pmic = platform_get_drvdata(pdev);
+ 	int i;
+diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c
+index cd06708f4af4..446a85445553 100644
+--- a/drivers/regulator/max8925-regulator.c
++++ b/drivers/regulator/max8925-regulator.c
+@@ -323,7 +323,7 @@ static int max8925_regulator_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit max8925_regulator_remove(struct platform_device *pdev)
++static int max8925_regulator_remove(struct platform_device *pdev)
+ {
+ 	struct regulator_dev *rdev = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c
+index 21862080fdc8..fc7935a19e3a 100644
+--- a/drivers/regulator/max8952.c
++++ b/drivers/regulator/max8952.c
+@@ -247,7 +247,7 @@ static int max8952_pmic_probe(struct i2c_client *client,
+ 	return 0;
+ }
+ 
+-static int __devexit max8952_pmic_remove(struct i2c_client *client)
++static int max8952_pmic_remove(struct i2c_client *client)
+ {
+ 	struct max8952_data *max8952 = i2c_get_clientdata(client);
+ 	struct max8952_platform_data *pdata = max8952->pdata;
+diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c
+index 323ec2b14edb..cea9ec9093eb 100644
+--- a/drivers/regulator/max8997.c
++++ b/drivers/regulator/max8997.c
+@@ -1120,7 +1120,7 @@ static int max8997_pmic_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit max8997_pmic_remove(struct platform_device *pdev)
++static int max8997_pmic_remove(struct platform_device *pdev)
+ {
+ 	struct max8997_data *max8997 = platform_get_drvdata(pdev);
+ 	struct regulator_dev **rdev = max8997->rdev;
+diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c
+index d80ce6c58ee5..b821d08eb64a 100644
+--- a/drivers/regulator/max8998.c
++++ b/drivers/regulator/max8998.c
+@@ -818,7 +818,7 @@ static int max8998_pmic_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit max8998_pmic_remove(struct platform_device *pdev)
++static int max8998_pmic_remove(struct platform_device *pdev)
+ {
+ 	struct max8998_data *max8998 = platform_get_drvdata(pdev);
+ 	struct regulator_dev **rdev = max8998->rdev;
+diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c
+index 54f42b3d964c..c46c6705cd74 100644
+--- a/drivers/regulator/mc13783-regulator.c
++++ b/drivers/regulator/mc13783-regulator.c
+@@ -445,7 +445,7 @@ static int mc13783_regulator_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit mc13783_regulator_remove(struct platform_device *pdev)
++static int mc13783_regulator_remove(struct platform_device *pdev)
+ {
+ 	struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
+ 	struct mc13xxx_regulator_platform_data *pdata =
+diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c
+index 9804a313da2f..0d84b1f33199 100644
+--- a/drivers/regulator/mc13892-regulator.c
++++ b/drivers/regulator/mc13892-regulator.c
+@@ -588,7 +588,7 @@ static int mc13892_regulator_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit mc13892_regulator_remove(struct platform_device *pdev)
++static int mc13892_regulator_remove(struct platform_device *pdev)
+ {
+ 	struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
+ 	int i;
+diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c
+index b04774492bc0..3d445929cc80 100644
+--- a/drivers/regulator/palmas-regulator.c
++++ b/drivers/regulator/palmas-regulator.c
+@@ -868,7 +868,7 @@ static int palmas_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit palmas_remove(struct platform_device *pdev)
++static int palmas_remove(struct platform_device *pdev)
+ {
+ 	struct palmas_pmic *pmic = platform_get_drvdata(pdev);
+ 	int id;
+diff --git a/drivers/regulator/pcap-regulator.c b/drivers/regulator/pcap-regulator.c
+index 4f3e445ec854..4899342f1fc1 100644
+--- a/drivers/regulator/pcap-regulator.c
++++ b/drivers/regulator/pcap-regulator.c
+@@ -255,7 +255,7 @@ static int pcap_regulator_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit pcap_regulator_remove(struct platform_device *pdev)
++static int pcap_regulator_remove(struct platform_device *pdev)
+ {
+ 	struct regulator_dev *rdev = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c
+index 51cb1bb3a2a7..d776f518aa0d 100644
+--- a/drivers/regulator/pcf50633-regulator.c
++++ b/drivers/regulator/pcf50633-regulator.c
+@@ -222,7 +222,7 @@ static int pcf50633_regulator_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit pcf50633_regulator_remove(struct platform_device *pdev)
++static int pcf50633_regulator_remove(struct platform_device *pdev)
+ {
+ 	struct regulator_dev *rdev = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c
+index 7f83f3345405..9e6f78694bf1 100644
+--- a/drivers/regulator/rc5t583-regulator.c
++++ b/drivers/regulator/rc5t583-regulator.c
+@@ -198,7 +198,7 @@ static int rc5t583_regulator_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit rc5t583_regulator_remove(struct platform_device *pdev)
++static int rc5t583_regulator_remove(struct platform_device *pdev)
+ {
+ 	struct rc5t583_regulator *regs = platform_get_drvdata(pdev);
+ 	int id;
+diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
+index c918e99f937a..85fc086c1319 100644
+--- a/drivers/regulator/s2mps11.c
++++ b/drivers/regulator/s2mps11.c
+@@ -307,7 +307,7 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit s2mps11_pmic_remove(struct platform_device *pdev)
++static int s2mps11_pmic_remove(struct platform_device *pdev)
+ {
+ 	struct s2mps11_info *s2mps11 = platform_get_drvdata(pdev);
+ 	int i;
+diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c
+index 15f3ccac758c..2b822bec3c2d 100644
+--- a/drivers/regulator/s5m8767.c
++++ b/drivers/regulator/s5m8767.c
+@@ -773,7 +773,7 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit s5m8767_pmic_remove(struct platform_device *pdev)
++static int s5m8767_pmic_remove(struct platform_device *pdev)
+ {
+ 	struct s5m8767_info *s5m8767 = platform_get_drvdata(pdev);
+ 	struct regulator_dev **rdev = s5m8767->rdev;
+diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c
+index ff79a468cd99..a9c3a4a6cca0 100644
+--- a/drivers/regulator/tps51632-regulator.c
++++ b/drivers/regulator/tps51632-regulator.c
+@@ -290,7 +290,7 @@ static int tps51632_probe(struct i2c_client *client,
+ 	return 0;
+ }
+ 
+-static int __devexit tps51632_remove(struct i2c_client *client)
++static int tps51632_remove(struct i2c_client *client)
+ {
+ 	struct tps51632_chip *tps = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/regulator/tps6105x-regulator.c b/drivers/regulator/tps6105x-regulator.c
+index f8c0c9273399..ec9453ffb77f 100644
+--- a/drivers/regulator/tps6105x-regulator.c
++++ b/drivers/regulator/tps6105x-regulator.c
+@@ -159,7 +159,7 @@ static int tps6105x_regulator_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit tps6105x_regulator_remove(struct platform_device *pdev)
++static int tps6105x_regulator_remove(struct platform_device *pdev)
+ {
+ 	struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev);
+ 	regulator_unregister(tps6105x->regulator);
+diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c
+index 7fba9ffab22c..acbd63fde415 100644
+--- a/drivers/regulator/tps62360-regulator.c
++++ b/drivers/regulator/tps62360-regulator.c
+@@ -490,7 +490,7 @@ static int tps62360_probe(struct i2c_client *client,
+  *
+  * Unregister TPS driver as an i2c client device driver
+  */
+-static int __devexit tps62360_remove(struct i2c_client *client)
++static int tps62360_remove(struct i2c_client *client)
+ {
+ 	struct tps62360_chip *tps = i2c_get_clientdata(client);
+ 
+diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c
+index a039206fd90a..9b9af6d889c8 100644
+--- a/drivers/regulator/tps65023-regulator.c
++++ b/drivers/regulator/tps65023-regulator.c
+@@ -319,7 +319,7 @@ static int tps_65023_probe(struct i2c_client *client,
+ 	return error;
+ }
+ 
+-static int __devexit tps_65023_remove(struct i2c_client *client)
++static int tps_65023_remove(struct i2c_client *client)
+ {
+ 	struct tps_pmic *tps = i2c_get_clientdata(client);
+ 	int i;
+diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c
+index 6c45d5af6f93..0233cfb56560 100644
+--- a/drivers/regulator/tps6507x-regulator.c
++++ b/drivers/regulator/tps6507x-regulator.c
+@@ -439,7 +439,7 @@ static int tps6507x_pmic_probe(struct platform_device *pdev)
+ 	return error;
+ }
+ 
+-static int __devexit tps6507x_pmic_remove(struct platform_device *pdev)
++static int tps6507x_pmic_remove(struct platform_device *pdev)
+ {
+ 	struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev);
+ 	struct tps6507x_pmic *tps = tps6507x_dev->pmic;
+diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c
+index cc5be1f512a8..3974a992220f 100644
+--- a/drivers/regulator/tps65090-regulator.c
++++ b/drivers/regulator/tps65090-regulator.c
+@@ -232,7 +232,7 @@ static int tps65090_regulator_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit tps65090_regulator_remove(struct platform_device *pdev)
++static int tps65090_regulator_remove(struct platform_device *pdev)
+ {
+ 	struct tps65090_regulator *pmic = platform_get_drvdata(pdev);
+ 	struct tps65090_regulator *ri;
+diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c
+index e34fb8689091..73dce7664126 100644
+--- a/drivers/regulator/tps65217-regulator.c
++++ b/drivers/regulator/tps65217-regulator.c
+@@ -397,7 +397,7 @@ static int tps65217_regulator_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit tps65217_regulator_remove(struct platform_device *pdev)
++static int tps65217_regulator_remove(struct platform_device *pdev)
+ {
+ 	struct tps65217 *tps = platform_get_drvdata(pdev);
+ 	unsigned int i;
+diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c
+index 7206f4e3e760..9ce44109f2aa 100644
+--- a/drivers/regulator/tps6586x-regulator.c
++++ b/drivers/regulator/tps6586x-regulator.c
+@@ -461,7 +461,7 @@ static int tps6586x_regulator_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit tps6586x_regulator_remove(struct platform_device *pdev)
++static int tps6586x_regulator_remove(struct platform_device *pdev)
+ {
+ 	struct regulator_dev **rdev = platform_get_drvdata(pdev);
+ 	int id = TPS6586X_ID_MAX_REGULATOR;
+diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c
+index 276eeb5c12ca..6b77bbf32ebc 100644
+--- a/drivers/regulator/tps65910-regulator.c
++++ b/drivers/regulator/tps65910-regulator.c
+@@ -1184,7 +1184,7 @@ static int tps65910_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit tps65910_remove(struct platform_device *pdev)
++static int tps65910_remove(struct platform_device *pdev)
+ {
+ 	struct tps65910_reg *pmic = platform_get_drvdata(pdev);
+ 	int i;
+diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c
+index 35b2a6fb8614..17e994e47dc1 100644
+--- a/drivers/regulator/tps65912-regulator.c
++++ b/drivers/regulator/tps65912-regulator.c
+@@ -525,7 +525,7 @@ static int tps65912_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit tps65912_remove(struct platform_device *pdev)
++static int tps65912_remove(struct platform_device *pdev)
+ {
+ 	struct tps65912_reg *tps65912_reg = platform_get_drvdata(pdev);
+ 	int i;
+diff --git a/drivers/regulator/tps80031-regulator.c b/drivers/regulator/tps80031-regulator.c
+index cdfcbc9c51a3..127d1754fcd3 100644
+--- a/drivers/regulator/tps80031-regulator.c
++++ b/drivers/regulator/tps80031-regulator.c
+@@ -753,7 +753,7 @@ static int tps80031_regulator_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static int __devexit tps80031_regulator_remove(struct platform_device *pdev)
++static int tps80031_regulator_remove(struct platform_device *pdev)
+ {
+ 	struct tps80031_regulator *pmic = platform_get_drvdata(pdev);
+ 	struct tps80031_regulator *ri = NULL;
+diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
+index 66e62a2cb244..493c8c6a241f 100644
+--- a/drivers/regulator/twl-regulator.c
++++ b/drivers/regulator/twl-regulator.c
+@@ -1241,7 +1241,7 @@ static int twlreg_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit twlreg_remove(struct platform_device *pdev)
++static int twlreg_remove(struct platform_device *pdev)
+ {
+ 	struct regulator_dev *rdev = platform_get_drvdata(pdev);
+ 	struct twlreg_info *info = rdev->reg_data;
+diff --git a/drivers/regulator/vexpress.c b/drivers/regulator/vexpress.c
+index 405620197a23..4668c7f8133d 100644
+--- a/drivers/regulator/vexpress.c
++++ b/drivers/regulator/vexpress.c
+@@ -114,7 +114,7 @@ static int vexpress_regulator_probe(struct platform_device *pdev)
+ 	return err;
+ }
+ 
+-static int __devexit vexpress_regulator_remove(struct platform_device *pdev)
++static int vexpress_regulator_remove(struct platform_device *pdev)
+ {
+ 	struct vexpress_regulator *reg = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/regulator/virtual.c b/drivers/regulator/virtual.c
+index be0dd182eab9..01c66e9712a4 100644
+--- a/drivers/regulator/virtual.c
++++ b/drivers/regulator/virtual.c
+@@ -321,7 +321,7 @@ static int regulator_virtual_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit regulator_virtual_remove(struct platform_device *pdev)
++static int regulator_virtual_remove(struct platform_device *pdev)
+ {
+ 	struct virtual_consumer_data *drvdata = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c
+index 54e9778f5080..33297bcce3f8 100644
+--- a/drivers/regulator/wm831x-dcdc.c
++++ b/drivers/regulator/wm831x-dcdc.c
+@@ -562,7 +562,7 @@ static int wm831x_buckv_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static __devexit int wm831x_buckv_remove(struct platform_device *pdev)
++static int wm831x_buckv_remove(struct platform_device *pdev)
+ {
+ 	struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
+ 	struct wm831x *wm831x = dcdc->wm831x;
+@@ -710,7 +710,7 @@ static int wm831x_buckp_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static __devexit int wm831x_buckp_remove(struct platform_device *pdev)
++static int wm831x_buckp_remove(struct platform_device *pdev)
+ {
+ 	struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
+ 
+@@ -845,7 +845,7 @@ static int wm831x_boostp_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static __devexit int wm831x_boostp_remove(struct platform_device *pdev)
++static int wm831x_boostp_remove(struct platform_device *pdev)
+ {
+ 	struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
+ 
+@@ -936,7 +936,7 @@ static int wm831x_epe_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static __devexit int wm831x_epe_remove(struct platform_device *pdev)
++static int wm831x_epe_remove(struct platform_device *pdev)
+ {
+ 	struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/regulator/wm831x-isink.c b/drivers/regulator/wm831x-isink.c
+index ac4bdffef2ea..68586ee3e1cb 100644
+--- a/drivers/regulator/wm831x-isink.c
++++ b/drivers/regulator/wm831x-isink.c
+@@ -221,7 +221,7 @@ static int wm831x_isink_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static __devexit int wm831x_isink_remove(struct platform_device *pdev)
++static int wm831x_isink_remove(struct platform_device *pdev)
+ {
+ 	struct wm831x_isink *isink = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c
+index 90f657fe24ae..1ec379a9a95c 100644
+--- a/drivers/regulator/wm831x-ldo.c
++++ b/drivers/regulator/wm831x-ldo.c
+@@ -334,7 +334,7 @@ static int wm831x_gp_ldo_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static __devexit int wm831x_gp_ldo_remove(struct platform_device *pdev)
++static int wm831x_gp_ldo_remove(struct platform_device *pdev)
+ {
+ 	struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
+ 
+@@ -590,7 +590,7 @@ static int wm831x_aldo_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static __devexit int wm831x_aldo_remove(struct platform_device *pdev)
++static int wm831x_aldo_remove(struct platform_device *pdev)
+ {
+ 	struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
+ 
+@@ -737,7 +737,7 @@ static int wm831x_alive_ldo_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static __devexit int wm831x_alive_ldo_remove(struct platform_device *pdev)
++static int wm831x_alive_ldo_remove(struct platform_device *pdev)
+ {
+ 	struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c
+index c155ec3159b9..c6a32ea80b9d 100644
+--- a/drivers/regulator/wm8400-regulator.c
++++ b/drivers/regulator/wm8400-regulator.c
+@@ -246,7 +246,7 @@ static int wm8400_regulator_probe(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-static int __devexit wm8400_regulator_remove(struct platform_device *pdev)
++static int wm8400_regulator_remove(struct platform_device *pdev)
+ {
+ 	struct regulator_dev *rdev = platform_get_drvdata(pdev);
+ 
+diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c
+index ea0fdd57fbbe..6ff872342648 100644
+--- a/drivers/regulator/wm8994-regulator.c
++++ b/drivers/regulator/wm8994-regulator.c
+@@ -142,7 +142,7 @@ static int wm8994_ldo_probe(struct platform_device *pdev)
+ 	return ret;
+ }
+ 
+-static __devexit int wm8994_ldo_remove(struct platform_device *pdev)
++static int wm8994_ldo_remove(struct platform_device *pdev)
+ {
+ 	struct wm8994_ldo *ldo = platform_get_drvdata(pdev);
+ 

commit a5023574d120ca3b9337cedd4e27de90cae9aff7
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:22:22 2012 -0500
+
+    regulator: remove use of __devinit
+    
+    CONFIG_HOTPLUG is going away as an option so __devinit is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c
+index 2d798ca53809..c09b5d97f4e7 100644
+--- a/drivers/regulator/88pm8607.c
++++ b/drivers/regulator/88pm8607.c
+@@ -394,7 +394,7 @@ static int pm8607_regulator_dt_init(struct platform_device *pdev,
+ #define pm8607_regulator_dt_init(x, y, z)	(-1)
+ #endif
+ 
+-static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
++static int pm8607_regulator_probe(struct platform_device *pdev)
+ {
+ 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+ 	struct pm8607_regulator_info *info = NULL;
+diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c
+index 9fae59d41c0a..7a04d5fe4e93 100644
+--- a/drivers/regulator/ab3100.c
++++ b/drivers/regulator/ab3100.c
+@@ -494,7 +494,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = {
+  * for all the different regulators.
+  */
+ 
+-static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
++static int ab3100_regulators_probe(struct platform_device *pdev)
+ {
+ 	struct ab3100_platform_data *plfdata = pdev->dev.platform_data;
+ 	struct regulator_config config = { };
+diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c
+index 987b047fc40a..af81325b8e2f 100644
+--- a/drivers/regulator/ab8500.c
++++ b/drivers/regulator/ab8500.c
+@@ -641,7 +641,7 @@ static struct ab8500_reg_init ab8500_reg_init[] = {
+ 	REG_INIT(AB8500_REGUCTRLDISCH2,		0x04, 0x44, 0x16),
+ };
+ 
+-static __devinit int
++static int
+ ab8500_regulator_init_registers(struct platform_device *pdev, int id, int value)
+ {
+ 	int err;
+@@ -676,7 +676,7 @@ ab8500_regulator_init_registers(struct platform_device *pdev, int id, int value)
+ 	return 0;
+ }
+ 
+-static __devinit int ab8500_regulator_register(struct platform_device *pdev,
++static int ab8500_regulator_register(struct platform_device *pdev,
+ 					struct regulator_init_data *init_data,
+ 					int id,
+ 					struct device_node *np)
+@@ -735,7 +735,7 @@ static struct of_regulator_match ab8500_regulator_matches[] = {
+ 	{ .name	= "ab8500_ldo_ana",     .driver_data = (void *) AB8500_LDO_ANA, },
+ };
+ 
+-static __devinit int
++static int
+ ab8500_regulator_of_probe(struct platform_device *pdev, struct device_node *np)
+ {
+ 	int err, i;
+@@ -751,7 +751,7 @@ ab8500_regulator_of_probe(struct platform_device *pdev, struct device_node *np)
+ 	return 0;
+ }
+ 
+-static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
++static int ab8500_regulator_probe(struct platform_device *pdev)
+ {
+ 	struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
+ 	struct ab8500_platform_data *pdata;
+diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c
+index 7921d014bcaf..cd855d9ac38a 100644
+--- a/drivers/regulator/ad5398.c
++++ b/drivers/regulator/ad5398.c
+@@ -211,7 +211,7 @@ static const struct i2c_device_id ad5398_id[] = {
+ };
+ MODULE_DEVICE_TABLE(i2c, ad5398_id);
+ 
+-static int __devinit ad5398_probe(struct i2c_client *client,
++static int ad5398_probe(struct i2c_client *client,
+ 				const struct i2c_device_id *id)
+ {
+ 	struct regulator_init_data *init_data = client->dev.platform_data;
+diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c
+index e8ae65657345..a900c2992f25 100644
+--- a/drivers/regulator/anatop-regulator.c
++++ b/drivers/regulator/anatop-regulator.c
+@@ -87,7 +87,7 @@ static struct regulator_ops anatop_rops = {
+ 	.map_voltage = regulator_map_voltage_linear,
+ };
+ 
+-static int __devinit anatop_regulator_probe(struct platform_device *pdev)
++static int anatop_regulator_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	struct device_node *np = dev->of_node;
+diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c
+index 7502394ef6ff..7e9ad7cb8676 100644
+--- a/drivers/regulator/arizona-ldo1.c
++++ b/drivers/regulator/arizona-ldo1.c
+@@ -67,7 +67,7 @@ static const struct regulator_init_data arizona_ldo1_default = {
+ 	.num_consumer_supplies = 1,
+ };
+ 
+-static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
++static int arizona_ldo1_probe(struct platform_device *pdev)
+ {
+ 	struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
+ 	struct regulator_config config = { };
+diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c
+index 8c6eeba766a5..3c3631c044fd 100644
+--- a/drivers/regulator/arizona-micsupp.c
++++ b/drivers/regulator/arizona-micsupp.c
+@@ -115,7 +115,7 @@ static const struct regulator_init_data arizona_micsupp_default = {
+ 	.num_consumer_supplies = 1,
+ };
+ 
+-static __devinit int arizona_micsupp_probe(struct platform_device *pdev)
++static int arizona_micsupp_probe(struct platform_device *pdev)
+ {
+ 	struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
+ 	struct regulator_config config = { };
+diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c
+index 43db3a510cbc..ab4a6d677280 100644
+--- a/drivers/regulator/da903x.c
++++ b/drivers/regulator/da903x.c
+@@ -460,7 +460,7 @@ static inline struct da903x_regulator_info *find_regulator_info(int id)
+ 	return NULL;
+ }
+ 
+-static int __devinit da903x_regulator_probe(struct platform_device *pdev)
++static int da903x_regulator_probe(struct platform_device *pdev)
+ {
+ 	struct da903x_regulator_info *ri = NULL;
+ 	struct regulator_dev *rdev;
+diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c
+index 9caa6e619802..ba703d80a21f 100644
+--- a/drivers/regulator/da9052-regulator.c
++++ b/drivers/regulator/da9052-regulator.c
+@@ -365,7 +365,7 @@ static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id,
+ 	return NULL;
+ }
+ 
+-static int __devinit da9052_regulator_probe(struct platform_device *pdev)
++static int da9052_regulator_probe(struct platform_device *pdev)
+ {
+ 	struct regulator_config config = { };
+ 	struct da9052_regulator *regulator;
+diff --git a/drivers/regulator/db8500-prcmu.c b/drivers/regulator/db8500-prcmu.c
+index 359f8d18fc3f..219d162b651e 100644
+--- a/drivers/regulator/db8500-prcmu.c
++++ b/drivers/regulator/db8500-prcmu.c
+@@ -412,7 +412,7 @@ dbx500_regulator_info[DB8500_NUM_REGULATORS] = {
+ 	},
+ };
+ 
+-static __devinit int db8500_regulator_register(struct platform_device *pdev,
++static int db8500_regulator_register(struct platform_device *pdev,
+ 					struct regulator_init_data *init_data,
+ 					int id,
+ 					struct device_node *np)
+@@ -474,7 +474,7 @@ static struct of_regulator_match db8500_regulator_matches[] = {
+ 	{ .name	= "db8500_esram34_ret",   .driver_data = (void *) DB8500_REGULATOR_SWITCH_ESRAM34RET, },
+ };
+ 
+-static __devinit int
++static int
+ db8500_regulator_of_probe(struct platform_device *pdev,
+ 			struct device_node *np)
+ {
+@@ -491,7 +491,7 @@ db8500_regulator_of_probe(struct platform_device *pdev,
+ 	return 0;
+ }
+ 
+-static int __devinit db8500_regulator_probe(struct platform_device *pdev)
++static int db8500_regulator_probe(struct platform_device *pdev)
+ {
+ 	struct regulator_init_data *db8500_init_data =
+ 					dev_get_platdata(&pdev->dev);
+diff --git a/drivers/regulator/dbx500-prcmu.c b/drivers/regulator/dbx500-prcmu.c
+index f2e5ecdc5864..afc3e89940ed 100644
+--- a/drivers/regulator/dbx500-prcmu.c
++++ b/drivers/regulator/dbx500-prcmu.c
+@@ -173,7 +173,7 @@ int __attribute__((weak)) dbx500_regulator_testcase(
+ 	return 0;
+ }
+ 
+-int __devinit
++int
+ ux500_regulator_debug_init(struct platform_device *pdev,
+ 	struct dbx500_regulator_info *regulator_info,
+ 	int num_regulators)
+diff --git a/drivers/regulator/dummy.c b/drivers/regulator/dummy.c
+index 03a1d7c11ef2..df9f42524abb 100644
+--- a/drivers/regulator/dummy.c
++++ b/drivers/regulator/dummy.c
+@@ -37,7 +37,7 @@ static struct regulator_desc dummy_desc = {
+ 	.ops = &dummy_ops,
+ };
+ 
+-static int __devinit dummy_regulator_probe(struct platform_device *pdev)
++static int dummy_regulator_probe(struct platform_device *pdev)
+ {
+ 	struct regulator_config config = { };
+ 	int ret;
+diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c
+index 5279eff3a53f..199172a3bbfa 100644
+--- a/drivers/regulator/fan53555.c
++++ b/drivers/regulator/fan53555.c
+@@ -230,7 +230,7 @@ static struct regmap_config fan53555_regmap_config = {
+ 	.val_bits = 8,
+ };
+ 
+-static int __devinit fan53555_regulator_probe(struct i2c_client *client,
++static int fan53555_regulator_probe(struct i2c_client *client,
+ 				const struct i2c_device_id *id)
+ {
+ 	struct fan53555_device_info *di;
+diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
+index 73a6a59d703e..5aa0be00cc31 100644
+--- a/drivers/regulator/fixed.c
++++ b/drivers/regulator/fixed.c
+@@ -134,7 +134,7 @@ static struct regulator_ops fixed_voltage_ops = {
+ 	.list_voltage = fixed_voltage_list_voltage,
+ };
+ 
+-static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
++static int reg_fixed_voltage_probe(struct platform_device *pdev)
+ {
+ 	struct fixed_voltage_config *config;
+ 	struct fixed_voltage_data *drvdata;
+diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c
+index 902e041a3304..5ffee5ec3660 100644
+--- a/drivers/regulator/gpio-regulator.c
++++ b/drivers/regulator/gpio-regulator.c
+@@ -220,7 +220,7 @@ static struct regulator_ops gpio_regulator_current_ops = {
+ 	.set_current_limit = gpio_regulator_set_current_limit,
+ };
+ 
+-static int __devinit gpio_regulator_probe(struct platform_device *pdev)
++static int gpio_regulator_probe(struct platform_device *pdev)
+ {
+ 	struct gpio_regulator_config *config = pdev->dev.platform_data;
+ 	struct device_node *np = pdev->dev.of_node;
+diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c
+index 2c415e9eaefc..1732108dda49 100644
+--- a/drivers/regulator/isl6271a-regulator.c
++++ b/drivers/regulator/isl6271a-regulator.c
+@@ -106,7 +106,7 @@ static const struct regulator_desc isl_rd[] = {
+ 	},
+ };
+ 
+-static int __devinit isl6271a_probe(struct i2c_client *i2c,
++static int isl6271a_probe(struct i2c_client *i2c,
+ 				     const struct i2c_device_id *id)
+ {
+ 	struct regulator_config config = { };
+diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c
+index e10726a9f455..95b7299e3ed2 100644
+--- a/drivers/regulator/lp3971.c
++++ b/drivers/regulator/lp3971.c
+@@ -386,7 +386,7 @@ static int lp3971_set_bits(struct lp3971 *lp3971, u8 reg, u16 mask, u16 val)
+ 	return ret;
+ }
+ 
+-static int __devinit setup_regulators(struct lp3971 *lp3971,
++static int setup_regulators(struct lp3971 *lp3971,
+ 				      struct lp3971_platform_data *pdata)
+ {
+ 	int i, err;
+@@ -429,7 +429,7 @@ static int __devinit setup_regulators(struct lp3971 *lp3971,
+ 	return err;
+ }
+ 
+-static int __devinit lp3971_i2c_probe(struct i2c_client *i2c,
++static int lp3971_i2c_probe(struct i2c_client *i2c,
+ 			    const struct i2c_device_id *id)
+ {
+ 	struct lp3971 *lp3971;
+diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c
+index 262f2d2530b0..acf71beb1f57 100644
+--- a/drivers/regulator/lp3972.c
++++ b/drivers/regulator/lp3972.c
+@@ -481,7 +481,7 @@ static const struct regulator_desc regulators[] = {
+ 	},
+ };
+ 
+-static int __devinit setup_regulators(struct lp3972 *lp3972,
++static int setup_regulators(struct lp3972 *lp3972,
+ 	struct lp3972_platform_data *pdata)
+ {
+ 	int i, err;
+@@ -523,7 +523,7 @@ static int __devinit setup_regulators(struct lp3972 *lp3972,
+ 	return err;
+ }
+ 
+-static int __devinit lp3972_i2c_probe(struct i2c_client *i2c,
++static int lp3972_i2c_probe(struct i2c_client *i2c,
+ 			    const struct i2c_device_id *id)
+ {
+ 	struct lp3972 *lp3972;
+diff --git a/drivers/regulator/lp8788-buck.c b/drivers/regulator/lp8788-buck.c
+index 35643d2a80e8..1a3623ac066c 100644
+--- a/drivers/regulator/lp8788-buck.c
++++ b/drivers/regulator/lp8788-buck.c
+@@ -504,7 +504,7 @@ static int lp8788_init_dvs(struct lp8788_buck *buck, enum lp8788_buck_id id)
+ 				  default_dvs_mode[id]);
+ }
+ 
+-static __devinit int lp8788_buck_probe(struct platform_device *pdev)
++static int lp8788_buck_probe(struct platform_device *pdev)
+ {
+ 	struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
+ 	int id = pdev->id;
+diff --git a/drivers/regulator/lp8788-ldo.c b/drivers/regulator/lp8788-ldo.c
+index 93399f151a5d..e69a5b62f443 100644
+--- a/drivers/regulator/lp8788-ldo.c
++++ b/drivers/regulator/lp8788-ldo.c
+@@ -712,7 +712,7 @@ static int lp8788_config_ldo_enable_mode(struct lp8788_ldo *ldo,
+ 				val[enable_id]);
+ }
+ 
+-static __devinit int lp8788_dldo_probe(struct platform_device *pdev)
++static int lp8788_dldo_probe(struct platform_device *pdev)
+ {
+ 	struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
+ 	int id = pdev->id;
+@@ -768,7 +768,7 @@ static struct platform_driver lp8788_dldo_driver = {
+ 	},
+ };
+ 
+-static __devinit int lp8788_aldo_probe(struct platform_device *pdev)
++static int lp8788_aldo_probe(struct platform_device *pdev)
+ {
+ 	struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
+ 	int id = pdev->id;
+diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c
+index 184a92feca70..1609810a9a3d 100644
+--- a/drivers/regulator/max1586.c
++++ b/drivers/regulator/max1586.c
+@@ -125,7 +125,7 @@ static struct regulator_desc max1586_reg[] = {
+ 	},
+ };
+ 
+-static int __devinit max1586_pmic_probe(struct i2c_client *client,
++static int max1586_pmic_probe(struct i2c_client *client,
+ 					const struct i2c_device_id *i2c_id)
+ {
+ 	struct regulator_dev **rdev;
+diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c
+index 7374f5edab0c..da028d055ec7 100644
+--- a/drivers/regulator/max77686.c
++++ b/drivers/regulator/max77686.c
+@@ -280,7 +280,7 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
+ }
+ #endif /* CONFIG_OF */
+ 
+-static __devinit int max77686_pmic_probe(struct platform_device *pdev)
++static int max77686_pmic_probe(struct platform_device *pdev)
+ {
+ 	struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+ 	struct max77686_platform_data *pdata = dev_get_platdata(iodev->dev);
+diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c
+index d78d4aa37167..d4397f95f741 100644
+--- a/drivers/regulator/max8649.c
++++ b/drivers/regulator/max8649.c
+@@ -176,7 +176,7 @@ static struct regmap_config max8649_regmap_config = {
+ 	.val_bits = 8,
+ };
+ 
+-static int __devinit max8649_regulator_probe(struct i2c_client *client,
++static int max8649_regulator_probe(struct i2c_client *client,
+ 					     const struct i2c_device_id *id)
+ {
+ 	struct max8649_platform_data *pdata = client->dev.platform_data;
+diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c
+index b009a5e7942b..a44589f36a31 100644
+--- a/drivers/regulator/max8660.c
++++ b/drivers/regulator/max8660.c
+@@ -305,7 +305,7 @@ static const struct regulator_desc max8660_reg[] = {
+ 	},
+ };
+ 
+-static int __devinit max8660_probe(struct i2c_client *client,
++static int max8660_probe(struct i2c_client *client,
+ 				   const struct i2c_device_id *i2c_id)
+ {
+ 	struct regulator_dev **rdev;
+diff --git a/drivers/regulator/max8907-regulator.c b/drivers/regulator/max8907-regulator.c
+index 882e7cb3c943..99bae75970f1 100644
+--- a/drivers/regulator/max8907-regulator.c
++++ b/drivers/regulator/max8907-regulator.c
+@@ -275,7 +275,7 @@ static inline struct device_node *match_of_node(int index)
+ }
+ #endif
+ 
+-static __devinit int max8907_regulator_probe(struct platform_device *pdev)
++static int max8907_regulator_probe(struct platform_device *pdev)
+ {
+ 	struct max8907 *max8907 = dev_get_drvdata(pdev->dev.parent);
+ 	struct max8907_platform_data *pdata = dev_get_platdata(max8907->dev);
+diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c
+index 85d419ed4a46..cd06708f4af4 100644
+--- a/drivers/regulator/max8925-regulator.c
++++ b/drivers/regulator/max8925-regulator.c
+@@ -274,7 +274,7 @@ static int max8925_regulator_dt_init(struct platform_device *pdev,
+ #define max8925_regulator_dt_init(w, x, y, z)	(-1)
+ #endif
+ 
+-static int __devinit max8925_regulator_probe(struct platform_device *pdev)
++static int max8925_regulator_probe(struct platform_device *pdev)
+ {
+ 	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
+ 	struct regulator_init_data *pdata = pdev->dev.platform_data;
+diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c
+index d575e5f92cdd..21862080fdc8 100644
+--- a/drivers/regulator/max8952.c
++++ b/drivers/regulator/max8952.c
+@@ -126,7 +126,7 @@ static const struct regulator_desc regulator = {
+ 	.owner		= THIS_MODULE,
+ };
+ 
+-static int __devinit max8952_pmic_probe(struct i2c_client *client,
++static int max8952_pmic_probe(struct i2c_client *client,
+ 		const struct i2c_device_id *i2c_id)
+ {
+ 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c
+index 2b97ec8f6a83..323ec2b14edb 100644
+--- a/drivers/regulator/max8997.c
++++ b/drivers/regulator/max8997.c
+@@ -933,7 +933,7 @@ static struct regulator_desc regulators[] = {
+ 				  max8997_charger_fixedstate_ops),
+ };
+ 
+-static __devinit int max8997_pmic_probe(struct platform_device *pdev)
++static int max8997_pmic_probe(struct platform_device *pdev)
+ {
+ 	struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+ 	struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev);
+diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c
+index 1edb01c9bdcd..d80ce6c58ee5 100644
+--- a/drivers/regulator/max8998.c
++++ b/drivers/regulator/max8998.c
+@@ -633,7 +633,7 @@ static struct regulator_desc regulators[] = {
+ 	}
+ };
+ 
+-static __devinit int max8998_pmic_probe(struct platform_device *pdev)
++static int max8998_pmic_probe(struct platform_device *pdev)
+ {
+ 	struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+ 	struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev);
+diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c
+index 940f659f6318..54f42b3d964c 100644
+--- a/drivers/regulator/mc13783-regulator.c
++++ b/drivers/regulator/mc13783-regulator.c
+@@ -392,7 +392,7 @@ static struct regulator_ops mc13783_gpo_regulator_ops = {
+ 	.set_voltage = mc13xxx_fixed_regulator_set_voltage,
+ };
+ 
+-static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
++static int mc13783_regulator_probe(struct platform_device *pdev)
+ {
+ 	struct mc13xxx_regulator_priv *priv;
+ 	struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent);
+diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c
+index f3646cffa7ba..9804a313da2f 100644
+--- a/drivers/regulator/mc13892-regulator.c
++++ b/drivers/regulator/mc13892-regulator.c
+@@ -486,7 +486,7 @@ static unsigned int mc13892_vcam_get_mode(struct regulator_dev *rdev)
+ }
+ 
+ 
+-static int __devinit mc13892_regulator_probe(struct platform_device *pdev)
++static int mc13892_regulator_probe(struct platform_device *pdev)
+ {
+ 	struct mc13xxx_regulator_priv *priv;
+ 	struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent);
+diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c
+index 88cbb832d555..4ed89c654110 100644
+--- a/drivers/regulator/mc13xxx-regulator-core.c
++++ b/drivers/regulator/mc13xxx-regulator-core.c
+@@ -162,7 +162,7 @@ struct regulator_ops mc13xxx_fixed_regulator_ops = {
+ EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_ops);
+ 
+ #ifdef CONFIG_OF
+-int __devinit mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
++int mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
+ {
+ 	struct device_node *parent, *child;
+ 	int num = 0;
+@@ -179,7 +179,7 @@ int __devinit mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
+ }
+ EXPORT_SYMBOL_GPL(mc13xxx_get_num_regulators_dt);
+ 
+-struct mc13xxx_regulator_init_data * __devinit mc13xxx_parse_regulators_dt(
++struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
+ 	struct platform_device *pdev, struct mc13xxx_regulator *regulators,
+ 	int num_regulators)
+ {
+diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c
+index 4e0d3b5934d3..b04774492bc0 100644
+--- a/drivers/regulator/palmas-regulator.c
++++ b/drivers/regulator/palmas-regulator.c
+@@ -595,7 +595,7 @@ static struct of_regulator_match palmas_matches[] = {
+ 	{ .name = "ldousb", },
+ };
+ 
+-static void __devinit palmas_dt_to_pdata(struct device *dev,
++static void palmas_dt_to_pdata(struct device *dev,
+ 		struct device_node *node,
+ 		struct palmas_pmic_platform_data *pdata)
+ {
+@@ -663,7 +663,7 @@ static void __devinit palmas_dt_to_pdata(struct device *dev,
+ }
+ 
+ 
+-static __devinit int palmas_probe(struct platform_device *pdev)
++static int palmas_probe(struct platform_device *pdev)
+ {
+ 	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
+ 	struct palmas_pmic_platform_data *pdata = pdev->dev.platform_data;
+diff --git a/drivers/regulator/pcap-regulator.c b/drivers/regulator/pcap-regulator.c
+index 1f349bfd6717..4f3e445ec854 100644
+--- a/drivers/regulator/pcap-regulator.c
++++ b/drivers/regulator/pcap-regulator.c
+@@ -236,7 +236,7 @@ static const struct regulator_desc pcap_regulators[] = {
+ 	VREG(VAUX4), VREG(VSIM), VREG(VSIM2), VREG(VVIB), VREG(SW1), VREG(SW2),
+ };
+ 
+-static int __devinit pcap_regulator_probe(struct platform_device *pdev)
++static int pcap_regulator_probe(struct platform_device *pdev)
+ {
+ 	struct regulator_dev *rdev;
+ 	void *pcap = dev_get_drvdata(pdev->dev.parent);
+diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c
+index 02c9e1c5d4ca..51cb1bb3a2a7 100644
+--- a/drivers/regulator/pcf50633-regulator.c
++++ b/drivers/regulator/pcf50633-regulator.c
+@@ -196,7 +196,7 @@ static const struct regulator_desc regulators[] = {
+ 	[PCF50633_REGULATOR_MEMLDO] = PCF50633_REGULATOR("memldo", MEMLDO, 28),
+ };
+ 
+-static int __devinit pcf50633_regulator_probe(struct platform_device *pdev)
++static int pcf50633_regulator_probe(struct platform_device *pdev)
+ {
+ 	struct regulator_dev *rdev;
+ 	struct pcf50633 *pcf;
+diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c
+index ca2b5edcdb82..7f83f3345405 100644
+--- a/drivers/regulator/rc5t583-regulator.c
++++ b/drivers/regulator/rc5t583-regulator.c
+@@ -119,7 +119,7 @@ static struct rc5t583_regulator_info rc5t583_reg_info[RC5T583_REGULATOR_MAX] = {
+ 	RC5T583_REG(LDO9, LDOEN1, 1, LDODIS1, 1, 0x7F, 900, 3400, 25000, 133),
+ };
+ 
+-static int __devinit rc5t583_regulator_probe(struct platform_device *pdev)
++static int rc5t583_regulator_probe(struct platform_device *pdev)
+ {
+ 	struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent);
+ 	struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev);
+diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
+index c2723caf15ea..c918e99f937a 100644
+--- a/drivers/regulator/s2mps11.c
++++ b/drivers/regulator/s2mps11.c
+@@ -231,7 +231,7 @@ static struct regulator_desc regulators[] = {
+ 	regulator_desc_buck10,
+ };
+ 
+-static __devinit int s2mps11_pmic_probe(struct platform_device *pdev)
++static int s2mps11_pmic_probe(struct platform_device *pdev)
+ {
+ 	struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+ 	struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
+diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c
+index d606ca0347b6..15f3ccac758c 100644
+--- a/drivers/regulator/s5m8767.c
++++ b/drivers/regulator/s5m8767.c
+@@ -499,7 +499,7 @@ static struct regulator_desc regulators[] = {
+ 	s5m8767_regulator_desc(BUCK9),
+ };
+ 
+-static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
++static int s5m8767_pmic_probe(struct platform_device *pdev)
+ {
+ 	struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+ 	struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
+diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c
+index 687b0ccc5441..ff79a468cd99 100644
+--- a/drivers/regulator/tps51632-regulator.c
++++ b/drivers/regulator/tps51632-regulator.c
+@@ -157,7 +157,7 @@ static struct regulator_ops tps51632_dcdc_ops = {
+ 	.set_ramp_delay		= tps51632_dcdc_set_ramp_delay,
+ };
+ 
+-static int __devinit tps51632_init_dcdc(struct tps51632_chip *tps,
++static int tps51632_init_dcdc(struct tps51632_chip *tps,
+ 		struct tps51632_regulator_platform_data *pdata)
+ {
+ 	int ret;
+@@ -227,7 +227,7 @@ static const struct regmap_config tps51632_regmap_config = {
+ 	.cache_type		= REGCACHE_RBTREE,
+ };
+ 
+-static int __devinit tps51632_probe(struct i2c_client *client,
++static int tps51632_probe(struct i2c_client *client,
+ 				const struct i2c_device_id *id)
+ {
+ 	struct tps51632_regulator_platform_data *pdata;
+diff --git a/drivers/regulator/tps6105x-regulator.c b/drivers/regulator/tps6105x-regulator.c
+index 9516f44474ef..f8c0c9273399 100644
+--- a/drivers/regulator/tps6105x-regulator.c
++++ b/drivers/regulator/tps6105x-regulator.c
+@@ -127,7 +127,7 @@ static const struct regulator_desc tps6105x_regulator_desc = {
+ /*
+  * Registers the chip as a voltage regulator
+  */
+-static int __devinit tps6105x_regulator_probe(struct platform_device *pdev)
++static int tps6105x_regulator_probe(struct platform_device *pdev)
+ {
+ 	struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev);
+ 	struct tps6105x_platform_data *pdata = tps6105x->pdata;
+diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c
+index bd0f9f850b52..7fba9ffab22c 100644
+--- a/drivers/regulator/tps62360-regulator.c
++++ b/drivers/regulator/tps62360-regulator.c
+@@ -243,7 +243,7 @@ static struct regulator_ops tps62360_dcdc_ops = {
+ 	.get_mode		= tps62360_get_mode,
+ };
+ 
+-static int __devinit tps62360_init_dcdc(struct tps62360_chip *tps,
++static int tps62360_init_dcdc(struct tps62360_chip *tps,
+ 		struct tps62360_regulator_platform_data *pdata)
+ {
+ 	int ret;
+@@ -339,7 +339,7 @@ static const struct of_device_id tps62360_of_match[] = {
+ MODULE_DEVICE_TABLE(of, tps62360_of_match);
+ #endif
+ 
+-static int __devinit tps62360_probe(struct i2c_client *client,
++static int tps62360_probe(struct i2c_client *client,
+ 				     const struct i2c_device_id *id)
+ {
+ 	struct regulator_config config = { };
+diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c
+index 427b311f4d2a..a039206fd90a 100644
+--- a/drivers/regulator/tps65023-regulator.c
++++ b/drivers/regulator/tps65023-regulator.c
+@@ -219,7 +219,7 @@ static struct regmap_config tps65023_regmap_config = {
+ 	.val_bits = 8,
+ };
+ 
+-static int __devinit tps_65023_probe(struct i2c_client *client,
++static int tps_65023_probe(struct i2c_client *client,
+ 				     const struct i2c_device_id *id)
+ {
+ 	const struct tps_driver_data *drv_data = (void *)id->driver_data;
+diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c
+index c953e8f54076..6c45d5af6f93 100644
+--- a/drivers/regulator/tps6507x-regulator.c
++++ b/drivers/regulator/tps6507x-regulator.c
+@@ -356,7 +356,7 @@ static struct regulator_ops tps6507x_pmic_ops = {
+ 	.list_voltage = regulator_list_voltage_table,
+ };
+ 
+-static __devinit int tps6507x_pmic_probe(struct platform_device *pdev)
++static int tps6507x_pmic_probe(struct platform_device *pdev)
+ {
+ 	struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent);
+ 	struct tps_info *info = &tps6507x_pmic_regs[0];
+diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c
+index 99c912be739e..cc5be1f512a8 100644
+--- a/drivers/regulator/tps65090-regulator.c
++++ b/drivers/regulator/tps65090-regulator.c
+@@ -83,7 +83,7 @@ static inline bool is_dcdc(int id)
+ 	}
+ }
+ 
+-static int __devinit tps65090_config_ext_control(
++static int tps65090_config_ext_control(
+ 	struct tps65090_regulator *ri, bool enable)
+ {
+ 	int ret;
+@@ -99,7 +99,7 @@ static int __devinit tps65090_config_ext_control(
+ 	return ret;
+ }
+ 
+-static int __devinit tps65090_regulator_disable_ext_control(
++static int tps65090_regulator_disable_ext_control(
+ 		struct tps65090_regulator *ri,
+ 		struct tps65090_regulator_plat_data *tps_pdata)
+ {
+@@ -122,7 +122,7 @@ static int __devinit tps65090_regulator_disable_ext_control(
+ 	return tps65090_config_ext_control(ri, false);
+ }
+ 
+-static void __devinit tps65090_configure_regulator_config(
++static void tps65090_configure_regulator_config(
+ 		struct tps65090_regulator_plat_data *tps_pdata,
+ 		struct regulator_config *config)
+ {
+@@ -138,7 +138,7 @@ static void __devinit tps65090_configure_regulator_config(
+ 	}
+ }
+ 
+-static int __devinit tps65090_regulator_probe(struct platform_device *pdev)
++static int tps65090_regulator_probe(struct platform_device *pdev)
+ {
+ 	struct tps65090 *tps65090_mfd = dev_get_drvdata(pdev->dev.parent);
+ 	struct tps65090_regulator *ri = NULL;
+diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c
+index 73681ea2f5f4..e34fb8689091 100644
+--- a/drivers/regulator/tps65217-regulator.c
++++ b/drivers/regulator/tps65217-regulator.c
+@@ -332,7 +332,7 @@ static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev)
+ }
+ #endif
+ 
+-static int __devinit tps65217_regulator_probe(struct platform_device *pdev)
++static int tps65217_regulator_probe(struct platform_device *pdev)
+ {
+ 	struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
+ 	struct tps65217_board *pdata = dev_get_platdata(tps->dev);
+diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c
+index f5a01bc104ac..843ee0a9bb92 100644
+--- a/drivers/regulator/tps6524x-regulator.c
++++ b/drivers/regulator/tps6524x-regulator.c
+@@ -592,7 +592,7 @@ static int pmic_remove(struct spi_device *spi)
+ 	return 0;
+ }
+ 
+-static int __devinit pmic_probe(struct spi_device *spi)
++static int pmic_probe(struct spi_device *spi)
+ {
+ 	struct tps6524x *hw;
+ 	struct device *dev = &spi->dev;
+diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c
+index 491b16a48758..b91400cdbd95 100644
+--- a/drivers/regulator/tps6586x-regulator.c
++++ b/drivers/regulator/tps6586x-regulator.c
+@@ -298,7 +298,7 @@ static inline struct tps6586x_regulator *find_regulator_info(int id)
+ 	return NULL;
+ }
+ 
+-static int __devinit tps6586x_regulator_probe(struct platform_device *pdev)
++static int tps6586x_regulator_probe(struct platform_device *pdev)
+ {
+ 	struct tps6586x_regulator *ri = NULL;
+ 	struct regulator_config config = { };
+diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c
+index 2e1e57bb0792..276eeb5c12ca 100644
+--- a/drivers/regulator/tps65910-regulator.c
++++ b/drivers/regulator/tps65910-regulator.c
+@@ -1026,7 +1026,7 @@ static inline struct tps65910_board *tps65910_parse_dt_reg_data(
+ }
+ #endif
+ 
+-static __devinit int tps65910_probe(struct platform_device *pdev)
++static int tps65910_probe(struct platform_device *pdev)
+ {
+ 	struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
+ 	struct regulator_config config = { };
+diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c
+index ba7e62335e2b..35b2a6fb8614 100644
+--- a/drivers/regulator/tps65912-regulator.c
++++ b/drivers/regulator/tps65912-regulator.c
+@@ -459,7 +459,7 @@ static struct regulator_ops tps65912_ops_ldo = {
+ 	.list_voltage = tps65912_list_voltage,
+ };
+ 
+-static __devinit int tps65912_probe(struct platform_device *pdev)
++static int tps65912_probe(struct platform_device *pdev)
+ {
+ 	struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent);
+ 	struct regulator_config config = { };
+diff --git a/drivers/regulator/tps80031-regulator.c b/drivers/regulator/tps80031-regulator.c
+index d90c23b44ad4..cdfcbc9c51a3 100644
+--- a/drivers/regulator/tps80031-regulator.c
++++ b/drivers/regulator/tps80031-regulator.c
+@@ -675,7 +675,7 @@ static int check_smps_mode_mult(struct device *parent,
+ 	return 0;
+ }
+ 
+-static int __devinit tps80031_regulator_probe(struct platform_device *pdev)
++static int tps80031_regulator_probe(struct platform_device *pdev)
+ {
+ 	struct tps80031_platform_data *pdata;
+ 	struct tps80031_regulator_platform_data *tps_pdata;
+diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
+index eac854038c28..66e62a2cb244 100644
+--- a/drivers/regulator/twl-regulator.c
++++ b/drivers/regulator/twl-regulator.c
+@@ -1116,7 +1116,7 @@ static const struct of_device_id twl_of_match[] __devinitconst = {
+ };
+ MODULE_DEVICE_TABLE(of, twl_of_match);
+ 
+-static int __devinit twlreg_probe(struct platform_device *pdev)
++static int twlreg_probe(struct platform_device *pdev)
+ {
+ 	int				i, id;
+ 	struct twlreg_info		*info;
+diff --git a/drivers/regulator/virtual.c b/drivers/regulator/virtual.c
+index ec97b3e3fbbb..be0dd182eab9 100644
+--- a/drivers/regulator/virtual.c
++++ b/drivers/regulator/virtual.c
+@@ -285,7 +285,7 @@ static const struct attribute_group regulator_virtual_attr_group = {
+ 	.attrs	= regulator_virtual_attributes,
+ };
+ 
+-static int __devinit regulator_virtual_probe(struct platform_device *pdev)
++static int regulator_virtual_probe(struct platform_device *pdev)
+ {
+ 	char *reg_id = pdev->dev.platform_data;
+ 	struct virtual_consumer_data *drvdata;
+diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c
+index 16d7ebd88016..54e9778f5080 100644
+--- a/drivers/regulator/wm831x-dcdc.c
++++ b/drivers/regulator/wm831x-dcdc.c
+@@ -387,7 +387,7 @@ static struct regulator_ops wm831x_buckv_ops = {
+  * Set up DVS control.  We just log errors since we can still run
+  * (with reduced performance) if we fail.
+  */
+-static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
++static void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
+ 					    struct wm831x_buckv_pdata *pdata)
+ {
+ 	struct wm831x *wm831x = dcdc->wm831x;
+@@ -448,7 +448,7 @@ static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
+ 	}
+ }
+ 
+-static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
++static int wm831x_buckv_probe(struct platform_device *pdev)
+ {
+ 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
+ 	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+@@ -623,7 +623,7 @@ static struct regulator_ops wm831x_buckp_ops = {
+ 	.set_suspend_mode = wm831x_dcdc_set_suspend_mode,
+ };
+ 
+-static __devinit int wm831x_buckp_probe(struct platform_device *pdev)
++static int wm831x_buckp_probe(struct platform_device *pdev)
+ {
+ 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
+ 	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+@@ -771,7 +771,7 @@ static struct regulator_ops wm831x_boostp_ops = {
+ 	.disable = regulator_disable_regmap,
+ };
+ 
+-static __devinit int wm831x_boostp_probe(struct platform_device *pdev)
++static int wm831x_boostp_probe(struct platform_device *pdev)
+ {
+ 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
+ 	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+@@ -883,7 +883,7 @@ static struct regulator_ops wm831x_epe_ops = {
+ 	.get_status = wm831x_dcdc_get_status,
+ };
+ 
+-static __devinit int wm831x_epe_probe(struct platform_device *pdev)
++static int wm831x_epe_probe(struct platform_device *pdev)
+ {
+ 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
+ 	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+diff --git a/drivers/regulator/wm831x-isink.c b/drivers/regulator/wm831x-isink.c
+index 1f807a842db3..ac4bdffef2ea 100644
+--- a/drivers/regulator/wm831x-isink.c
++++ b/drivers/regulator/wm831x-isink.c
+@@ -148,7 +148,7 @@ static irqreturn_t wm831x_isink_irq(int irq, void *data)
+ }
+ 
+ 
+-static __devinit int wm831x_isink_probe(struct platform_device *pdev)
++static int wm831x_isink_probe(struct platform_device *pdev)
+ {
+ 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
+ 	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c
+index 2df06008cf51..90f657fe24ae 100644
+--- a/drivers/regulator/wm831x-ldo.c
++++ b/drivers/regulator/wm831x-ldo.c
+@@ -247,7 +247,7 @@ static struct regulator_ops wm831x_gp_ldo_ops = {
+ 	.disable = regulator_disable_regmap,
+ };
+ 
+-static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev)
++static int wm831x_gp_ldo_probe(struct platform_device *pdev)
+ {
+ 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
+ 	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+@@ -504,7 +504,7 @@ static struct regulator_ops wm831x_aldo_ops = {
+ 	.disable = regulator_disable_regmap,
+ };
+ 
+-static __devinit int wm831x_aldo_probe(struct platform_device *pdev)
++static int wm831x_aldo_probe(struct platform_device *pdev)
+ {
+ 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
+ 	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+@@ -660,7 +660,7 @@ static struct regulator_ops wm831x_alive_ldo_ops = {
+ 	.disable = regulator_disable_regmap,
+ };
+ 
+-static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev)
++static int wm831x_alive_ldo_probe(struct platform_device *pdev)
+ {
+ 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
+ 	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c
+index 1bb155152aa8..c155ec3159b9 100644
+--- a/drivers/regulator/wm8400-regulator.c
++++ b/drivers/regulator/wm8400-regulator.c
+@@ -226,7 +226,7 @@ static struct regulator_desc regulators[] = {
+ 	},
+ };
+ 
+-static int __devinit wm8400_regulator_probe(struct platform_device *pdev)
++static int wm8400_regulator_probe(struct platform_device *pdev)
+ {
+ 	struct wm8400 *wm8400 = container_of(pdev, struct wm8400, regulators[pdev->id]);
+ 	struct regulator_config config = { };
+diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c
+index 28b45481c7d4..ea0fdd57fbbe 100644
+--- a/drivers/regulator/wm8994-regulator.c
++++ b/drivers/regulator/wm8994-regulator.c
+@@ -99,7 +99,7 @@ static const struct regulator_desc wm8994_ldo_desc[] = {
+ 	},
+ };
+ 
+-static __devinit int wm8994_ldo_probe(struct platform_device *pdev)
++static int wm8994_ldo_probe(struct platform_device *pdev)
+ {
+ 	struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent);
+ 	struct wm8994_pdata *pdata = wm8994->dev->platform_data;

commit 5eb9f2b96381ac3fa4a5910c37213c1cb62e9c65
+Author: Bill Pemberton 
+Date:   Mon Nov 19 13:20:42 2012 -0500
+
+    regulator: remove use of __devexit_p
+    
+    CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
+    needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Mark Brown 
+
+diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c
+index 1c5ab0172ea2..2d798ca53809 100644
+--- a/drivers/regulator/88pm8607.c
++++ b/drivers/regulator/88pm8607.c
+@@ -481,7 +481,7 @@ static struct platform_driver pm8607_regulator_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= pm8607_regulator_probe,
+-	.remove		= __devexit_p(pm8607_regulator_remove),
++	.remove		= pm8607_regulator_remove,
+ 	.id_table	= pm8607_regulator_driver_ids,
+ };
+ 
+diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c
+index 167c93f21981..4285b304e2b5 100644
+--- a/drivers/regulator/aat2870-regulator.c
++++ b/drivers/regulator/aat2870-regulator.c
+@@ -201,7 +201,7 @@ static struct platform_driver aat2870_regulator_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe	= aat2870_regulator_probe,
+-	.remove	= __devexit_p(aat2870_regulator_remove),
++	.remove	= aat2870_regulator_remove,
+ };
+ 
+ static int __init aat2870_regulator_init(void)
+diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c
+index df4ad8927f0c..9fae59d41c0a 100644
+--- a/drivers/regulator/ab3100.c
++++ b/drivers/regulator/ab3100.c
+@@ -589,7 +589,7 @@ static struct platform_driver ab3100_regulators_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = ab3100_regulators_probe,
+-	.remove = __devexit_p(ab3100_regulators_remove),
++	.remove = ab3100_regulators_remove,
+ };
+ 
+ static __init int ab3100_regulators_init(void)
+diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c
+index e3d1d063025a..987b047fc40a 100644
+--- a/drivers/regulator/ab8500.c
++++ b/drivers/regulator/ab8500.c
+@@ -836,7 +836,7 @@ static __devexit int ab8500_regulator_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver ab8500_regulator_driver = {
+ 	.probe = ab8500_regulator_probe,
+-	.remove = __devexit_p(ab8500_regulator_remove),
++	.remove = ab8500_regulator_remove,
+ 	.driver         = {
+ 		.name   = "ab8500-regulator",
+ 		.owner  = THIS_MODULE,
+diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c
+index f123f7e3b752..7921d014bcaf 100644
+--- a/drivers/regulator/ad5398.c
++++ b/drivers/regulator/ad5398.c
+@@ -266,7 +266,7 @@ static int __devexit ad5398_remove(struct i2c_client *client)
+ 
+ static struct i2c_driver ad5398_driver = {
+ 	.probe = ad5398_probe,
+-	.remove = __devexit_p(ad5398_remove),
++	.remove = ad5398_remove,
+ 	.driver		= {
+ 		.name	= "ad5398",
+ 	},
+diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c
+index 1af97686f444..e8ae65657345 100644
+--- a/drivers/regulator/anatop-regulator.c
++++ b/drivers/regulator/anatop-regulator.c
+@@ -210,7 +210,7 @@ static struct platform_driver anatop_regulator_driver = {
+ 		.of_match_table = of_anatop_regulator_match_tbl,
+ 	},
+ 	.probe	= anatop_regulator_probe,
+-	.remove	= __devexit_p(anatop_regulator_remove),
++	.remove	= anatop_regulator_remove,
+ };
+ 
+ static int __init anatop_regulator_init(void)
+diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c
+index d184aa35abcb..7502394ef6ff 100644
+--- a/drivers/regulator/arizona-ldo1.c
++++ b/drivers/regulator/arizona-ldo1.c
+@@ -126,7 +126,7 @@ static __devexit int arizona_ldo1_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver arizona_ldo1_driver = {
+ 	.probe = arizona_ldo1_probe,
+-	.remove = __devexit_p(arizona_ldo1_remove),
++	.remove = arizona_ldo1_remove,
+ 	.driver		= {
+ 		.name	= "arizona-ldo1",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c
+index d9b1f82cc5bd..8c6eeba766a5 100644
+--- a/drivers/regulator/arizona-micsupp.c
++++ b/drivers/regulator/arizona-micsupp.c
+@@ -177,7 +177,7 @@ static __devexit int arizona_micsupp_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver arizona_micsupp_driver = {
+ 	.probe = arizona_micsupp_probe,
+-	.remove = __devexit_p(arizona_micsupp_remove),
++	.remove = arizona_micsupp_remove,
+ 	.driver		= {
+ 		.name	= "arizona-micsupp",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c
+index 36c5b92fe0af..43db3a510cbc 100644
+--- a/drivers/regulator/da903x.c
++++ b/drivers/regulator/da903x.c
+@@ -513,7 +513,7 @@ static struct platform_driver da903x_regulator_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= da903x_regulator_probe,
+-	.remove		= __devexit_p(da903x_regulator_remove),
++	.remove		= da903x_regulator_remove,
+ };
+ 
+ static int __init da903x_regulator_init(void)
+diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c
+index 27355b1199e5..9caa6e619802 100644
+--- a/drivers/regulator/da9052-regulator.c
++++ b/drivers/regulator/da9052-regulator.c
+@@ -440,7 +440,7 @@ static int __devexit da9052_regulator_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver da9052_regulator_driver = {
+ 	.probe = da9052_regulator_probe,
+-	.remove = __devexit_p(da9052_regulator_remove),
++	.remove = da9052_regulator_remove,
+ 	.driver = {
+ 		.name = "da9052-regulator",
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c
+index 339f4d732e97..5279eff3a53f 100644
+--- a/drivers/regulator/fan53555.c
++++ b/drivers/regulator/fan53555.c
+@@ -311,7 +311,7 @@ static struct i2c_driver fan53555_regulator_driver = {
+ 		.name = "fan53555-regulator",
+ 	},
+ 	.probe = fan53555_regulator_probe,
+-	.remove = __devexit_p(fan53555_regulator_remove),
++	.remove = fan53555_regulator_remove,
+ 	.id_table = fan53555_id,
+ };
+ 
+diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
+index 185468c4d38f..73a6a59d703e 100644
+--- a/drivers/regulator/fixed.c
++++ b/drivers/regulator/fixed.c
+@@ -255,7 +255,7 @@ MODULE_DEVICE_TABLE(of, fixed_of_match);
+ 
+ static struct platform_driver regulator_fixed_voltage_driver = {
+ 	.probe		= reg_fixed_voltage_probe,
+-	.remove		= __devexit_p(reg_fixed_voltage_remove),
++	.remove		= reg_fixed_voltage_remove,
+ 	.driver		= {
+ 		.name		= "reg-fixed-voltage",
+ 		.owner		= THIS_MODULE,
+diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c
+index dc9260545b80..902e041a3304 100644
+--- a/drivers/regulator/gpio-regulator.c
++++ b/drivers/regulator/gpio-regulator.c
+@@ -371,7 +371,7 @@ static const struct of_device_id regulator_gpio_of_match[] __devinitconst = {
+ 
+ static struct platform_driver gpio_regulator_driver = {
+ 	.probe		= gpio_regulator_probe,
+-	.remove		= __devexit_p(gpio_regulator_remove),
++	.remove		= gpio_regulator_remove,
+ 	.driver		= {
+ 		.name		= "gpio-regulator",
+ 		.owner		= THIS_MODULE,
+diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c
+index d8ecf49a5777..2c415e9eaefc 100644
+--- a/drivers/regulator/isl6271a-regulator.c
++++ b/drivers/regulator/isl6271a-regulator.c
+@@ -174,7 +174,7 @@ static struct i2c_driver isl6271a_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = isl6271a_probe,
+-	.remove = __devexit_p(isl6271a_remove),
++	.remove = isl6271a_remove,
+ 	.id_table = isl6271a_id,
+ };
+ 
+diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c
+index 7c6e3b8ff484..e10726a9f455 100644
+--- a/drivers/regulator/lp3971.c
++++ b/drivers/regulator/lp3971.c
+@@ -498,7 +498,7 @@ static struct i2c_driver lp3971_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe    = lp3971_i2c_probe,
+-	.remove   = __devexit_p(lp3971_i2c_remove),
++	.remove   = lp3971_i2c_remove,
+ 	.id_table = lp3971_i2c_id,
+ };
+ 
+diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c
+index 3cdc755d9b22..262f2d2530b0 100644
+--- a/drivers/regulator/lp3972.c
++++ b/drivers/regulator/lp3972.c
+@@ -594,7 +594,7 @@ static struct i2c_driver lp3972_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe    = lp3972_i2c_probe,
+-	.remove   = __devexit_p(lp3972_i2c_remove),
++	.remove   = lp3972_i2c_remove,
+ 	.id_table = lp3972_i2c_id,
+ };
+ 
+diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c
+index 708f4b6a17dc..622ad5e5bab0 100644
+--- a/drivers/regulator/lp872x.c
++++ b/drivers/regulator/lp872x.c
+@@ -914,7 +914,7 @@ static struct i2c_driver lp872x_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = lp872x_probe,
+-	.remove = __devexit_p(lp872x_remove),
++	.remove = lp872x_remove,
+ 	.id_table = lp872x_ids,
+ };
+ 
+diff --git a/drivers/regulator/lp8788-buck.c b/drivers/regulator/lp8788-buck.c
+index ba3e0aa402de..35643d2a80e8 100644
+--- a/drivers/regulator/lp8788-buck.c
++++ b/drivers/regulator/lp8788-buck.c
+@@ -554,7 +554,7 @@ static int __devexit lp8788_buck_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver lp8788_buck_driver = {
+ 	.probe = lp8788_buck_probe,
+-	.remove = __devexit_p(lp8788_buck_remove),
++	.remove = lp8788_buck_remove,
+ 	.driver = {
+ 		.name = LP8788_DEV_BUCK,
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/regulator/lp8788-ldo.c b/drivers/regulator/lp8788-ldo.c
+index 6796eeb47dc6..93399f151a5d 100644
+--- a/drivers/regulator/lp8788-ldo.c
++++ b/drivers/regulator/lp8788-ldo.c
+@@ -761,7 +761,7 @@ static int __devexit lp8788_dldo_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver lp8788_dldo_driver = {
+ 	.probe = lp8788_dldo_probe,
+-	.remove = __devexit_p(lp8788_dldo_remove),
++	.remove = lp8788_dldo_remove,
+ 	.driver = {
+ 		.name = LP8788_DEV_DLDO,
+ 		.owner = THIS_MODULE,
+@@ -817,7 +817,7 @@ static int __devexit lp8788_aldo_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver lp8788_aldo_driver = {
+ 	.probe = lp8788_aldo_probe,
+-	.remove = __devexit_p(lp8788_aldo_remove),
++	.remove = lp8788_aldo_remove,
+ 	.driver = {
+ 		.name = LP8788_DEV_ALDO,
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c
+index f67af3c1b963..184a92feca70 100644
+--- a/drivers/regulator/max1586.c
++++ b/drivers/regulator/max1586.c
+@@ -207,7 +207,7 @@ MODULE_DEVICE_TABLE(i2c, max1586_id);
+ 
+ static struct i2c_driver max1586_pmic_driver = {
+ 	.probe = max1586_pmic_probe,
+-	.remove = __devexit_p(max1586_pmic_remove),
++	.remove = max1586_pmic_remove,
+ 	.driver		= {
+ 		.name	= "max1586",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c
+index 2a67d08658ad..7374f5edab0c 100644
+--- a/drivers/regulator/max77686.c
++++ b/drivers/regulator/max77686.c
+@@ -360,7 +360,7 @@ static struct platform_driver max77686_pmic_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = max77686_pmic_probe,
+-	.remove = __devexit_p(max77686_pmic_remove),
++	.remove = max77686_pmic_remove,
+ 	.id_table = max77686_pmic_id,
+ };
+ 
+diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c
+index 9d540cd02dab..d78d4aa37167 100644
+--- a/drivers/regulator/max8649.c
++++ b/drivers/regulator/max8649.c
+@@ -291,7 +291,7 @@ MODULE_DEVICE_TABLE(i2c, max8649_id);
+ 
+ static struct i2c_driver max8649_driver = {
+ 	.probe		= max8649_regulator_probe,
+-	.remove		= __devexit_p(max8649_regulator_remove),
++	.remove		= max8649_regulator_remove,
+ 	.driver		= {
+ 		.name	= "max8649",
+ 	},
+diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c
+index 8d531742f593..b009a5e7942b 100644
+--- a/drivers/regulator/max8660.c
++++ b/drivers/regulator/max8660.c
+@@ -440,7 +440,7 @@ MODULE_DEVICE_TABLE(i2c, max8660_id);
+ 
+ static struct i2c_driver max8660_driver = {
+ 	.probe = max8660_probe,
+-	.remove = __devexit_p(max8660_remove),
++	.remove = max8660_remove,
+ 	.driver		= {
+ 		.name	= "max8660",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/regulator/max8907-regulator.c b/drivers/regulator/max8907-regulator.c
+index af7607515ab9..882e7cb3c943 100644
+--- a/drivers/regulator/max8907-regulator.c
++++ b/drivers/regulator/max8907-regulator.c
+@@ -385,7 +385,7 @@ static struct platform_driver max8907_regulator_driver = {
+ 		   .owner = THIS_MODULE,
+ 		   },
+ 	.probe = max8907_regulator_probe,
+-	.remove = __devexit_p(max8907_regulator_remove),
++	.remove = max8907_regulator_remove,
+ };
+ 
+ static int __init max8907_regulator_init(void)
+diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c
+index 2b549791c975..85d419ed4a46 100644
+--- a/drivers/regulator/max8925-regulator.c
++++ b/drivers/regulator/max8925-regulator.c
+@@ -339,7 +339,7 @@ static struct platform_driver max8925_regulator_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= max8925_regulator_probe,
+-	.remove		= __devexit_p(max8925_regulator_remove),
++	.remove		= max8925_regulator_remove,
+ };
+ 
+ static int __init max8925_regulator_init(void)
+diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c
+index 355ca7bad9d5..d575e5f92cdd 100644
+--- a/drivers/regulator/max8952.c
++++ b/drivers/regulator/max8952.c
+@@ -268,7 +268,7 @@ MODULE_DEVICE_TABLE(i2c, max8952_ids);
+ 
+ static struct i2c_driver max8952_pmic_driver = {
+ 	.probe		= max8952_pmic_probe,
+-	.remove		= __devexit_p(max8952_pmic_remove),
++	.remove		= max8952_pmic_remove,
+ 	.driver		= {
+ 		.name	= "max8952",
+ 	},
+diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c
+index e39a0c7260dc..2b97ec8f6a83 100644
+--- a/drivers/regulator/max8997.c
++++ b/drivers/regulator/max8997.c
+@@ -1143,7 +1143,7 @@ static struct platform_driver max8997_pmic_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = max8997_pmic_probe,
+-	.remove = __devexit_p(max8997_pmic_remove),
++	.remove = max8997_pmic_remove,
+ 	.id_table = max8997_pmic_id,
+ };
+ 
+diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c
+index 5dfa920ff0c8..1edb01c9bdcd 100644
+--- a/drivers/regulator/max8998.c
++++ b/drivers/regulator/max8998.c
+@@ -842,7 +842,7 @@ static struct platform_driver max8998_pmic_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = max8998_pmic_probe,
+-	.remove = __devexit_p(max8998_pmic_remove),
++	.remove = max8998_pmic_remove,
+ 	.id_table = max8998_pmic_id,
+ };
+ 
+diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c
+index 0801a6d0c122..940f659f6318 100644
+--- a/drivers/regulator/mc13783-regulator.c
++++ b/drivers/regulator/mc13783-regulator.c
+@@ -465,7 +465,7 @@ static struct platform_driver mc13783_regulator_driver = {
+ 		.name	= "mc13783-regulator",
+ 		.owner	= THIS_MODULE,
+ 	},
+-	.remove		= __devexit_p(mc13783_regulator_remove),
++	.remove		= mc13783_regulator_remove,
+ 	.probe		= mc13783_regulator_probe,
+ };
+ 
+diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c
+index 1fa63812f7ac..f3646cffa7ba 100644
+--- a/drivers/regulator/mc13892-regulator.c
++++ b/drivers/regulator/mc13892-regulator.c
+@@ -606,7 +606,7 @@ static struct platform_driver mc13892_regulator_driver = {
+ 		.name	= "mc13892-regulator",
+ 		.owner	= THIS_MODULE,
+ 	},
+-	.remove	= __devexit_p(mc13892_regulator_remove),
++	.remove	= mc13892_regulator_remove,
+ 	.probe	= mc13892_regulator_probe,
+ };
+ 
+diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c
+index 07aee694ba92..4e0d3b5934d3 100644
+--- a/drivers/regulator/palmas-regulator.c
++++ b/drivers/regulator/palmas-regulator.c
+@@ -890,7 +890,7 @@ static struct platform_driver palmas_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = palmas_probe,
+-	.remove = __devexit_p(palmas_remove),
++	.remove = palmas_remove,
+ };
+ 
+ static int __init palmas_init(void)
+diff --git a/drivers/regulator/pcap-regulator.c b/drivers/regulator/pcap-regulator.c
+index 68777acc099f..1f349bfd6717 100644
+--- a/drivers/regulator/pcap-regulator.c
++++ b/drivers/regulator/pcap-regulator.c
+@@ -271,7 +271,7 @@ static struct platform_driver pcap_regulator_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe	= pcap_regulator_probe,
+-	.remove	= __devexit_p(pcap_regulator_remove),
++	.remove	= pcap_regulator_remove,
+ };
+ 
+ static int __init pcap_regulator_init(void)
+diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c
+index 092e5cb848a1..02c9e1c5d4ca 100644
+--- a/drivers/regulator/pcf50633-regulator.c
++++ b/drivers/regulator/pcf50633-regulator.c
+@@ -237,7 +237,7 @@ static struct platform_driver pcf50633_regulator_driver = {
+ 		.name = "pcf50633-regltr",
+ 	},
+ 	.probe = pcf50633_regulator_probe,
+-	.remove = __devexit_p(pcf50633_regulator_remove),
++	.remove = pcf50633_regulator_remove,
+ };
+ 
+ static int __init pcf50633_regulator_init(void)
+diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c
+index 8bf4e8c9de9a..ca2b5edcdb82 100644
+--- a/drivers/regulator/rc5t583-regulator.c
++++ b/drivers/regulator/rc5t583-regulator.c
+@@ -214,7 +214,7 @@ static struct platform_driver rc5t583_regulator_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= rc5t583_regulator_probe,
+-	.remove		= __devexit_p(rc5t583_regulator_remove),
++	.remove		= rc5t583_regulator_remove,
+ };
+ 
+ static int __init rc5t583_regulator_init(void)
+diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
+index 926f9c8f2fac..c2723caf15ea 100644
+--- a/drivers/regulator/s2mps11.c
++++ b/drivers/regulator/s2mps11.c
+@@ -330,7 +330,7 @@ static struct platform_driver s2mps11_pmic_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = s2mps11_pmic_probe,
+-	.remove = __devexit_p(s2mps11_pmic_remove),
++	.remove = s2mps11_pmic_remove,
+ 	.id_table = s2mps11_pmic_id,
+ };
+ 
+diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c
+index abe64a32aedf..d606ca0347b6 100644
+--- a/drivers/regulator/s5m8767.c
++++ b/drivers/regulator/s5m8767.c
+@@ -798,7 +798,7 @@ static struct platform_driver s5m8767_pmic_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = s5m8767_pmic_probe,
+-	.remove = __devexit_p(s5m8767_pmic_remove),
++	.remove = s5m8767_pmic_remove,
+ 	.id_table = s5m8767_pmic_id,
+ };
+ 
+diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c
+index 34603640d6d9..687b0ccc5441 100644
+--- a/drivers/regulator/tps51632-regulator.c
++++ b/drivers/regulator/tps51632-regulator.c
+@@ -311,7 +311,7 @@ static struct i2c_driver tps51632_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = tps51632_probe,
+-	.remove = __devexit_p(tps51632_remove),
++	.remove = tps51632_remove,
+ 	.id_table = tps51632_id,
+ };
+ 
+diff --git a/drivers/regulator/tps6105x-regulator.c b/drivers/regulator/tps6105x-regulator.c
+index 1378409efaec..9516f44474ef 100644
+--- a/drivers/regulator/tps6105x-regulator.c
++++ b/drivers/regulator/tps6105x-regulator.c
+@@ -172,7 +172,7 @@ static struct platform_driver tps6105x_regulator_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = tps6105x_regulator_probe,
+-	.remove = __devexit_p(tps6105x_regulator_remove),
++	.remove = tps6105x_regulator_remove,
+ };
+ 
+ static __init int tps6105x_regulator_init(void)
+diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c
+index 68729a7c8709..bd0f9f850b52 100644
+--- a/drivers/regulator/tps62360-regulator.c
++++ b/drivers/regulator/tps62360-regulator.c
+@@ -531,7 +531,7 @@ static struct i2c_driver tps62360_i2c_driver = {
+ 		.of_match_table = of_match_ptr(tps62360_of_match),
+ 	},
+ 	.probe = tps62360_probe,
+-	.remove = __devexit_p(tps62360_remove),
++	.remove = tps62360_remove,
+ 	.shutdown = tps62360_shutdown,
+ 	.id_table = tps62360_id,
+ };
+diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c
+index 6998d579d07b..427b311f4d2a 100644
+--- a/drivers/regulator/tps65023-regulator.c
++++ b/drivers/regulator/tps65023-regulator.c
+@@ -446,7 +446,7 @@ static struct i2c_driver tps_65023_i2c_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = tps_65023_probe,
+-	.remove = __devexit_p(tps_65023_remove),
++	.remove = tps_65023_remove,
+ 	.id_table = tps_65023_id,
+ };
+ 
+diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c
+index 07d01ccdf308..c953e8f54076 100644
+--- a/drivers/regulator/tps6507x-regulator.c
++++ b/drivers/regulator/tps6507x-regulator.c
+@@ -456,7 +456,7 @@ static struct platform_driver tps6507x_pmic_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = tps6507x_pmic_probe,
+-	.remove = __devexit_p(tps6507x_pmic_remove),
++	.remove = tps6507x_pmic_remove,
+ };
+ 
+ static int __init tps6507x_pmic_init(void)
+diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c
+index 412413838e12..99c912be739e 100644
+--- a/drivers/regulator/tps65090-regulator.c
++++ b/drivers/regulator/tps65090-regulator.c
+@@ -251,7 +251,7 @@ static struct platform_driver tps65090_regulator_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= tps65090_regulator_probe,
+-	.remove		= __devexit_p(tps65090_regulator_remove),
++	.remove		= tps65090_regulator_remove,
+ };
+ 
+ static int __init tps65090_regulator_init(void)
+diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c
+index ab00cab905b7..73681ea2f5f4 100644
+--- a/drivers/regulator/tps65217-regulator.c
++++ b/drivers/regulator/tps65217-regulator.c
+@@ -415,7 +415,7 @@ static struct platform_driver tps65217_regulator_driver = {
+ 		.name = "tps65217-pmic",
+ 	},
+ 	.probe = tps65217_regulator_probe,
+-	.remove = __devexit_p(tps65217_regulator_remove),
++	.remove = tps65217_regulator_remove,
+ };
+ 
+ static int __init tps65217_regulator_init(void)
+diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c
+index 058d2f2675e9..f5a01bc104ac 100644
+--- a/drivers/regulator/tps6524x-regulator.c
++++ b/drivers/regulator/tps6524x-regulator.c
+@@ -649,7 +649,7 @@ static int __devinit pmic_probe(struct spi_device *spi)
+ 
+ static struct spi_driver pmic_driver = {
+ 	.probe		= pmic_probe,
+-	.remove		= __devexit_p(pmic_remove),
++	.remove		= pmic_remove,
+ 	.driver		= {
+ 		.name	= "tps6524x",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c
+index ce1e7cb8d513..491b16a48758 100644
+--- a/drivers/regulator/tps6586x-regulator.c
++++ b/drivers/regulator/tps6586x-regulator.c
+@@ -349,7 +349,7 @@ static struct platform_driver tps6586x_regulator_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= tps6586x_regulator_probe,
+-	.remove		= __devexit_p(tps6586x_regulator_remove),
++	.remove		= tps6586x_regulator_remove,
+ };
+ 
+ static int __init tps6586x_regulator_init(void)
+diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c
+index 793adda560c3..2e1e57bb0792 100644
+--- a/drivers/regulator/tps65910-regulator.c
++++ b/drivers/regulator/tps65910-regulator.c
+@@ -1231,7 +1231,7 @@ static struct platform_driver tps65910_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = tps65910_probe,
+-	.remove = __devexit_p(tps65910_remove),
++	.remove = tps65910_remove,
+ 	.shutdown = tps65910_shutdown,
+ };
+ 
+diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c
+index 18b2a1dcb4b5..ba7e62335e2b 100644
+--- a/drivers/regulator/tps65912-regulator.c
++++ b/drivers/regulator/tps65912-regulator.c
+@@ -541,7 +541,7 @@ static struct platform_driver tps65912_driver = {
+ 		.owner = THIS_MODULE,
+ 	},
+ 	.probe = tps65912_probe,
+-	.remove = __devexit_p(tps65912_remove),
++	.remove = tps65912_remove,
+ };
+ 
+ static int __init tps65912_init(void)
+diff --git a/drivers/regulator/tps80031-regulator.c b/drivers/regulator/tps80031-regulator.c
+index a37ede80abbf..d90c23b44ad4 100644
+--- a/drivers/regulator/tps80031-regulator.c
++++ b/drivers/regulator/tps80031-regulator.c
+@@ -772,7 +772,7 @@ static struct platform_driver tps80031_regulator_driver = {
+ 		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= tps80031_regulator_probe,
+-	.remove		= __devexit_p(tps80031_regulator_remove),
++	.remove		= tps80031_regulator_remove,
+ };
+ 
+ static int __init tps80031_regulator_init(void)
+diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
+index 7eb986a40746..eac854038c28 100644
+--- a/drivers/regulator/twl-regulator.c
++++ b/drivers/regulator/twl-regulator.c
+@@ -1255,7 +1255,7 @@ MODULE_ALIAS("platform:twl_reg");
+ 
+ static struct platform_driver twlreg_driver = {
+ 	.probe		= twlreg_probe,
+-	.remove		= __devexit_p(twlreg_remove),
++	.remove		= twlreg_remove,
+ 	/* NOTE: short name, to work around driver model truncation of
+ 	 * "twl_regulator.12" (and friends) to "twl_regulator.1".
+ 	 */
+diff --git a/drivers/regulator/vexpress.c b/drivers/regulator/vexpress.c
+index 1d558111d60f..405620197a23 100644
+--- a/drivers/regulator/vexpress.c
++++ b/drivers/regulator/vexpress.c
+@@ -131,7 +131,7 @@ static struct of_device_id vexpress_regulator_of_match[] = {
+ 
+ static struct platform_driver vexpress_regulator_driver = {
+ 	.probe = vexpress_regulator_probe,
+-	.remove = __devexit_p(vexpress_regulator_remove),
++	.remove = vexpress_regulator_remove,
+ 	.driver	= {
+ 		.name = DRVNAME,
+ 		.owner = THIS_MODULE,
+diff --git a/drivers/regulator/virtual.c b/drivers/regulator/virtual.c
+index c038e7422538..ec97b3e3fbbb 100644
+--- a/drivers/regulator/virtual.c
++++ b/drivers/regulator/virtual.c
+@@ -337,7 +337,7 @@ static int __devexit regulator_virtual_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver regulator_virtual_consumer_driver = {
+ 	.probe		= regulator_virtual_probe,
+-	.remove		= __devexit_p(regulator_virtual_remove),
++	.remove		= regulator_virtual_remove,
+ 	.driver		= {
+ 		.name		= "reg-virt-consumer",
+ 		.owner		= THIS_MODULE,
+diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c
+index 782c228a19bd..16d7ebd88016 100644
+--- a/drivers/regulator/wm831x-dcdc.c
++++ b/drivers/regulator/wm831x-dcdc.c
+@@ -582,7 +582,7 @@ static __devexit int wm831x_buckv_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver wm831x_buckv_driver = {
+ 	.probe = wm831x_buckv_probe,
+-	.remove = __devexit_p(wm831x_buckv_remove),
++	.remove = wm831x_buckv_remove,
+ 	.driver		= {
+ 		.name	= "wm831x-buckv",
+ 		.owner	= THIS_MODULE,
+@@ -725,7 +725,7 @@ static __devexit int wm831x_buckp_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver wm831x_buckp_driver = {
+ 	.probe = wm831x_buckp_probe,
+-	.remove = __devexit_p(wm831x_buckp_remove),
++	.remove = wm831x_buckp_remove,
+ 	.driver		= {
+ 		.name	= "wm831x-buckp",
+ 		.owner	= THIS_MODULE,
+@@ -860,7 +860,7 @@ static __devexit int wm831x_boostp_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver wm831x_boostp_driver = {
+ 	.probe = wm831x_boostp_probe,
+-	.remove = __devexit_p(wm831x_boostp_remove),
++	.remove = wm831x_boostp_remove,
+ 	.driver		= {
+ 		.name	= "wm831x-boostp",
+ 		.owner	= THIS_MODULE,
+@@ -948,7 +948,7 @@ static __devexit int wm831x_epe_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver wm831x_epe_driver = {
+ 	.probe = wm831x_epe_probe,
+-	.remove = __devexit_p(wm831x_epe_remove),
++	.remove = wm831x_epe_remove,
+ 	.driver		= {
+ 		.name	= "wm831x-epe",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/regulator/wm831x-isink.c b/drivers/regulator/wm831x-isink.c
+index 2646a1902b33..1f807a842db3 100644
+--- a/drivers/regulator/wm831x-isink.c
++++ b/drivers/regulator/wm831x-isink.c
+@@ -236,7 +236,7 @@ static __devexit int wm831x_isink_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver wm831x_isink_driver = {
+ 	.probe = wm831x_isink_probe,
+-	.remove = __devexit_p(wm831x_isink_remove),
++	.remove = wm831x_isink_remove,
+ 	.driver		= {
+ 		.name	= "wm831x-isink",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c
+index c2dc03993dc7..2df06008cf51 100644
+--- a/drivers/regulator/wm831x-ldo.c
++++ b/drivers/regulator/wm831x-ldo.c
+@@ -349,7 +349,7 @@ static __devexit int wm831x_gp_ldo_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver wm831x_gp_ldo_driver = {
+ 	.probe = wm831x_gp_ldo_probe,
+-	.remove = __devexit_p(wm831x_gp_ldo_remove),
++	.remove = wm831x_gp_ldo_remove,
+ 	.driver		= {
+ 		.name	= "wm831x-ldo",
+ 		.owner	= THIS_MODULE,
+@@ -603,7 +603,7 @@ static __devexit int wm831x_aldo_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver wm831x_aldo_driver = {
+ 	.probe = wm831x_aldo_probe,
+-	.remove = __devexit_p(wm831x_aldo_remove),
++	.remove = wm831x_aldo_remove,
+ 	.driver		= {
+ 		.name	= "wm831x-aldo",
+ 		.owner	= THIS_MODULE,
+@@ -748,7 +748,7 @@ static __devexit int wm831x_alive_ldo_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver wm831x_alive_ldo_driver = {
+ 	.probe = wm831x_alive_ldo_probe,
+-	.remove = __devexit_p(wm831x_alive_ldo_remove),
++	.remove = wm831x_alive_ldo_remove,
+ 	.driver		= {
+ 		.name	= "wm831x-alive-ldo",
+ 		.owner	= THIS_MODULE,
+diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c
+index 27c746ef0636..1bb155152aa8 100644
+--- a/drivers/regulator/wm8400-regulator.c
++++ b/drivers/regulator/wm8400-regulator.c
+@@ -261,7 +261,7 @@ static struct platform_driver wm8400_regulator_driver = {
+ 		.name = "wm8400-regulator",
+ 	},
+ 	.probe = wm8400_regulator_probe,
+-	.remove = __devexit_p(wm8400_regulator_remove),
++	.remove = wm8400_regulator_remove,
+ };
+ 
+ /**
+diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c
+index 86bb48db149e..28b45481c7d4 100644
+--- a/drivers/regulator/wm8994-regulator.c
++++ b/drivers/regulator/wm8994-regulator.c
+@@ -155,7 +155,7 @@ static __devexit int wm8994_ldo_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver wm8994_ldo_driver = {
+ 	.probe = wm8994_ldo_probe,
+-	.remove = __devexit_p(wm8994_ldo_remove),
++	.remove = wm8994_ldo_remove,
+ 	.driver		= {
+ 		.name	= "wm8994-ldo",
+ 		.owner	= THIS_MODULE,

commit 8fdefcb0ab74eff3273a6c3039c4e80ef5f56bdc
+Author: Bill Pemberton 
+Date:   Wed Nov 14 09:13:54 2012 -0500
+
+    staging: dgrp: remove TIOCGSOFTCAR and TIOCSSOFTCAR handling
+    
+    The TIOCGSOFTCAR and TIOCSSOFTCAR ioctls are handled by the tty layer
+    so the dgrp driver shouldn't try to deal with them itself.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/dgrp/dgrp_tty.c b/drivers/staging/dgrp/dgrp_tty.c
+index e125b03598d7..efa62ced7c8a 100644
+--- a/drivers/staging/dgrp/dgrp_tty.c
++++ b/drivers/staging/dgrp/dgrp_tty.c
+@@ -2615,21 +2615,6 @@ static int dgrp_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
+ 		 */
+ 		return 0;
+ 
+-	case TIOCGSOFTCAR:
+-		rc = access_ok(VERIFY_WRITE, (void __user *) arg,
+-			       sizeof(long));
+-		if (rc == 0)
+-			return -EFAULT;
+-		put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) arg);
+-		return 0;
+-
+-	case TIOCSSOFTCAR:
+-		get_user(arg, (unsigned long __user *) arg);
+-		tty->termios.c_cflag =
+-			((tty->termios.c_cflag & ~CLOCAL) |
+-			 (arg ? CLOCAL : 0));
+-		return 0;
+-
+ 	case TIOCMGET:
+ 		rc = access_ok(VERIFY_WRITE, (void __user *) arg,
+ 				 sizeof(unsigned int));

commit 57cf50acbf5b153f331a966ecc08836324c1cd8d
+Author: Bill Pemberton 
+Date:   Thu Oct 25 12:46:22 2012 -0400
+
+    staging: dgrp: remove rawreadok module option
+    
+    The functionality behind this option has been removed in the driver so
+    remove the config option to set/unset it.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/dgrp/dgrp_common.h b/drivers/staging/dgrp/dgrp_common.h
+index 05ff338471ac..0583fe9c7b03 100644
+--- a/drivers/staging/dgrp/dgrp_common.h
++++ b/drivers/staging/dgrp/dgrp_common.h
+@@ -31,7 +31,6 @@
+  * All global storage allocation.
+  ************************************************************************/
+ 
+-extern int dgrp_rawreadok;  /* Allow raw writing of input */
+ extern int dgrp_register_cudevices; /* enable legacy cu devices */
+ extern int dgrp_register_prdevices; /* enable transparent print devices */
+ extern int dgrp_poll_tick;          /* Poll interval - in ms */
+diff --git a/drivers/staging/dgrp/dgrp_driver.c b/drivers/staging/dgrp/dgrp_driver.c
+index 6e4a0ebc0749..aa262588e9b9 100644
+--- a/drivers/staging/dgrp/dgrp_driver.c
++++ b/drivers/staging/dgrp/dgrp_driver.c
+@@ -39,14 +39,10 @@ MODULE_VERSION(DIGI_VERSION);
+ struct list_head nd_struct_list;
+ struct dgrp_poll_data dgrp_poll_data;
+ 
+-int dgrp_rawreadok = 1;		/* Bypass flipbuf on input */
+ int dgrp_register_cudevices = 1;/* Turn on/off registering legacy cu devices */
+ int dgrp_register_prdevices = 1;/* Turn on/off registering transparent print */
+ int dgrp_poll_tick = 20;	/* Poll interval - in ms */
+ 
+-module_param_named(rawreadok, dgrp_rawreadok, int, 0644);
+-MODULE_PARM_DESC(rawreadok, "Bypass flip buffers on input");
+-
+ module_param_named(register_cudevices, dgrp_register_cudevices, int, 0644);
+ MODULE_PARM_DESC(register_cudevices, "Turn on/off registering legacy cu devices");
+ 
+diff --git a/drivers/staging/dgrp/dgrp_specproc.c b/drivers/staging/dgrp/dgrp_specproc.c
+index 24327c3bad83..db91f676508a 100644
+--- a/drivers/staging/dgrp/dgrp_specproc.c
++++ b/drivers/staging/dgrp/dgrp_specproc.c
+@@ -629,8 +629,6 @@ static int info_proc_show(struct seq_file *m, void *v)
+ {
+ 	seq_printf(m, "version: %s\n", DIGI_VERSION);
+ 	seq_puts(m, "register_with_sysfs: 1\n");
+-	seq_printf(m, "rawreadok: 0x%08x\t(%d)\n",
+-		   dgrp_rawreadok, dgrp_rawreadok);
+ 	seq_printf(m, "pollrate: 0x%08x\t(%d)\n",
+ 		   dgrp_poll_tick, dgrp_poll_tick);
+ 
+diff --git a/drivers/staging/dgrp/dgrp_sysfs.c b/drivers/staging/dgrp/dgrp_sysfs.c
+index e5a3c88d016e..8b513e9111c1 100644
+--- a/drivers/staging/dgrp/dgrp_sysfs.c
++++ b/drivers/staging/dgrp/dgrp_sysfs.c
+@@ -55,23 +55,6 @@ static DEVICE_ATTR(register_with_sysfs, 0400,
+ 		   dgrp_class_register_with_sysfs_show, NULL);
+ 
+ 
+-static ssize_t dgrp_class_rawreadok_show(struct device *c,
+-					 struct device_attribute *attr,
+-					 char *buf)
+-{
+-	return snprintf(buf, PAGE_SIZE, "%d\n", dgrp_rawreadok);
+-}
+-static ssize_t dgrp_class_rawreadok_store(struct device *c,
+-					  struct device_attribute *attr,
+-					  const char *buf, size_t count)
+-{
+-	sscanf(buf, "0x%x\n", &dgrp_rawreadok);
+-	return count;
+-}
+-static DEVICE_ATTR(rawreadok, 0600, dgrp_class_rawreadok_show,
+-		   dgrp_class_rawreadok_store);
+-
+-
+ static ssize_t dgrp_class_pollrate_show(struct device *c,
+ 					struct device_attribute *attr,
+ 					char *buf)
+@@ -91,7 +74,6 @@ static DEVICE_ATTR(pollrate, 0600, dgrp_class_pollrate_show,
+ 
+ static struct attribute *dgrp_sysfs_global_settings_entries[] = {
+ 	&dev_attr_pollrate.attr,
+-	&dev_attr_rawreadok.attr,
+ 	&dev_attr_register_with_sysfs.attr,
+ 	NULL
+ };

commit e3224111b3a527eb8f9b9b6deed83b727522941e
+Author: Bill Pemberton 
+Date:   Thu Oct 25 12:46:21 2012 -0400
+
+    staging: dgrp: remove use of real_raw and read_cnt in dgrp_input
+    
+    dgrp_input used real_raw and read_cnt from struct tty_struct.  Those
+    members have gone away.  Rework the code to not use them.
+    
+    Reported-by: Fengguang Wu 
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/dgrp/dgrp_net_ops.c b/drivers/staging/dgrp/dgrp_net_ops.c
+index ab839ea3b44c..0788357fd3ca 100644
+--- a/drivers/staging/dgrp/dgrp_net_ops.c
++++ b/drivers/staging/dgrp/dgrp_net_ops.c
+@@ -151,20 +151,15 @@ static void dgrp_read_data_block(struct ch_struct *ch, u8 *flipbuf,
+  * Copys the rbuf to the flipbuf and sends to line discipline.
+  * Sends input buffer data to the line discipline.
+  *
+- * There are several modes to consider here:
+- *    rawreadok, tty->real_raw, and IF_PARMRK
+  */
+ static void dgrp_input(struct ch_struct *ch)
+ {
+ 	struct nd_struct *nd;
+ 	struct tty_struct *tty;
+-	int remain;
+ 	int data_len;
+ 	int len;
+-	int flip_len;
+ 	int tty_count;
+ 	ulong lock_flags;
+-	struct tty_ldisc *ld;
+ 	u8  *myflipbuf;
+ 	u8  *myflipflagbuf;
+ 
+@@ -212,37 +207,11 @@ static void dgrp_input(struct ch_struct *ch)
+ 
+ 	spin_unlock_irqrestore(&nd->nd_lock, lock_flags);
+ 
+-	/* Decide how much data we can send into the tty layer */
+-	if (dgrp_rawreadok && tty->real_raw)
+-		flip_len = MYFLIPLEN;
+-	else
+-		flip_len = TTY_FLIPBUF_SIZE;
+-
+ 	/* data_len should be the number of chars that we read in */
+ 	data_len = (ch->ch_rin - ch->ch_rout) & RBUF_MASK;
+-	remain = data_len;
+ 
+ 	/* len is the amount of data we are going to transfer here */
+-	len = min(data_len, flip_len);
+-
+-	/* take into consideration length of ldisc */
+-	len = min(len, (N_TTY_BUF_SIZE - 1) - tty->read_cnt);
+-
+-	ld = tty_ldisc_ref(tty);
+-
+-	/*
+-	 * If we were unable to get a reference to the ld,
+-	 * don't flush our buffer, and act like the ld doesn't
+-	 * have any space to put the data right now.
+-	 */
+-	if (!ld) {
+-		len = 0;
+-	} else if (!ld->ops->receive_buf) {
+-		spin_lock_irqsave(&nd->nd_lock, lock_flags);
+-		ch->ch_rout = ch->ch_rin;
+-		spin_unlock_irqrestore(&nd->nd_lock, lock_flags);
+-		len = 0;
+-	}
++	len = tty_buffer_request_room(tty, data_len);
+ 
+ 	/* Check DPA flow control */
+ 	if ((nd->nd_dpa_debug) &&
+@@ -254,42 +223,22 @@ static void dgrp_input(struct ch_struct *ch)
+ 
+ 		dgrp_read_data_block(ch, myflipbuf, len);
+ 
+-		/*
+-		 * In high performance mode, we don't have to update
+-		 * flag_buf or any of the counts or pointers into flip buf.
+-		 */
+-		if (!dgrp_rawreadok || !tty->real_raw) {
+-			if (I_PARMRK(tty) || I_BRKINT(tty) || I_INPCK(tty))
+-				parity_scan(ch, myflipbuf, myflipflagbuf, &len);
+-			else
+-				memset(myflipflagbuf, TTY_NORMAL, len);
+-		}
++		if (I_PARMRK(tty) || I_BRKINT(tty) || I_INPCK(tty))
++			parity_scan(ch, myflipbuf, myflipflagbuf, &len);
++		else
++			memset(myflipflagbuf, TTY_NORMAL, len);
+ 
+ 		if ((nd->nd_dpa_debug) &&
+ 		    (nd->nd_dpa_port == PORT_NUM(MINOR(tty_devnum(tty)))))
+ 			dgrp_dpa_data(nd, 1, myflipbuf, len);
+ 
+-		/*
+-		 * If we're doing raw reads, jam it right into the
+-		 * line disc bypassing the flip buffers.
+-		 */
+-		if (dgrp_rawreadok && tty->real_raw)
+-			ld->ops->receive_buf(tty, myflipbuf, NULL, len);
+-		else {
+-			len = tty_buffer_request_room(tty, len);
+-			tty_insert_flip_string_flags(tty, myflipbuf,
+-						     myflipflagbuf, len);
+-
+-			/* Tell the tty layer its okay to "eat" the data now */
+-			tty_flip_buffer_push(tty);
+-		}
++		tty_insert_flip_string_flags(tty, myflipbuf,
++					     myflipflagbuf, len);
++		tty_flip_buffer_push(tty);
+ 
+ 		ch->ch_rxcount += len;
+ 	}
+ 
+-	if (ld)
+-		tty_ldisc_deref(ld);
+-
+ 	/*
+ 	 * Wake up any sleepers (maybe dgrp close) that might be waiting
+ 	 * for a channel flag state change.

commit 178e485a0ebbfdb7165b4363d8fea2a07d650c0b
+Author: Bill Pemberton 
+Date:   Tue Oct 9 14:18:20 2012 -0400
+
+    staging: dgrp: check return value of alloc_tty_driver
+    
+    alloc_tty_driver was always assumed to succeed.  Add code to check the
+    return value and return -ENOMEM if alloc_tty_driver fails.
+    
+    Reported-by: Fengguang Wu 
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/dgrp/dgrp_tty.c b/drivers/staging/dgrp/dgrp_tty.c
+index 72f6fcfa9878..e125b03598d7 100644
+--- a/drivers/staging/dgrp/dgrp_tty.c
++++ b/drivers/staging/dgrp/dgrp_tty.c
+@@ -3173,6 +3173,9 @@ dgrp_tty_init(struct nd_struct *nd)
+ 	 */
+ 
+ 	nd->nd_serial_ttdriver = alloc_tty_driver(CHAN_MAX);
++	if (!nd->nd_serial_ttdriver)
++		return -ENOMEM;
++
+ 	sprintf(nd->nd_serial_name,  "tty_dgrp_%s_", id);
+ 
+ 	nd->nd_serial_ttdriver->owner = THIS_MODULE;
+@@ -3232,6 +3235,9 @@ dgrp_tty_init(struct nd_struct *nd)
+ 	}
+ 
+ 	nd->nd_callout_ttdriver = alloc_tty_driver(CHAN_MAX);
++	if (!nd->nd_callout_ttdriver)
++		return -ENOMEM;
++
+ 	sprintf(nd->nd_callout_name, "cu_dgrp_%s_",  id);
+ 
+ 	nd->nd_callout_ttdriver->owner = THIS_MODULE;
+@@ -3269,6 +3275,9 @@ dgrp_tty_init(struct nd_struct *nd)
+ 
+ 
+ 	nd->nd_xprint_ttdriver = alloc_tty_driver(CHAN_MAX);
++	if (!nd->nd_xprint_ttdriver)
++		return -ENOMEM;
++
+ 	sprintf(nd->nd_xprint_name,  "pr_dgrp_%s_", id);
+ 
+ 	nd->nd_xprint_ttdriver->owner = THIS_MODULE;

commit d7c4660c12adc5c66351253af381259686fa08a4
+Author: Bill Pemberton 
+Date:   Tue Oct 9 14:18:19 2012 -0400
+
+    staging: dgrp: check for NULL pointer in (un)register_proc_table
+    
+    register_proc_table and unregister_proc_table didn't deal with the
+    possibility that the *table pointer could be NULL.  Check for this and
+    return if table is NULL.
+    
+    Reported-by: Fengguang Wu 
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/dgrp/dgrp_specproc.c b/drivers/staging/dgrp/dgrp_specproc.c
+index a5840e7d6665..24327c3bad83 100644
+--- a/drivers/staging/dgrp/dgrp_specproc.c
++++ b/drivers/staging/dgrp/dgrp_specproc.c
+@@ -229,6 +229,9 @@ static void register_proc_table(struct dgrp_proc_entry *table,
+ 	int len;
+ 	mode_t mode;
+ 
++	if (table == NULL)
++		return;
++
+ 	for (; table->id; table++) {
+ 		/* Can't do anything without a proc name. */
+ 		if (!table->name)
+@@ -297,6 +300,9 @@ static void unregister_proc_table(struct dgrp_proc_entry *table,
+ 	struct proc_dir_entry *de;
+ 	struct nd_struct *tmp;
+ 
++	if (table == NULL)
++		return;
++
+ 	list_for_each_entry(tmp, &nd_struct_list, list) {
+ 		if ((table == dgrp_net_table) && (tmp->nd_net_de)) {
+ 			unregister_dgrp_device(tmp->nd_net_de);

commit ad0c6e367ee0d08c4caa19ad0dbd3d752bd39de0
+Author: Bill Pemberton 
+Date:   Mon Sep 24 17:02:08 2012 -0400
+
+    staging: dgrp: fix potential call to strncpy with a negative number
+    
+    In dgrp_receive() there is:
+    
+       desclen = ((plen - 12) > MAX_DESC_LEN) ? MAX_DESC_LEN :
+                                plen - 12;
+       strncpy(nd->nd_ps_desc, b + 12, desclen);
+    
+    However, it's possible for plen to be <= 12 here so we'd be passing a
+    negative number into the strncpy().  Fix this to not make the strncpy
+    call and report an error if desclen is <= 0
+    
+    Reported-by: Dan Carpenter 
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/dgrp/dgrp_net_ops.c b/drivers/staging/dgrp/dgrp_net_ops.c
+index d9d6b6709e4e..ab839ea3b44c 100644
+--- a/drivers/staging/dgrp/dgrp_net_ops.c
++++ b/drivers/staging/dgrp/dgrp_net_ops.c
+@@ -3156,6 +3156,12 @@ static void dgrp_receive(struct nd_struct *nd)
+ 						nd->nd_hw_id = b[6];
+ 						desclen = ((plen - 12) > MAX_DESC_LEN) ? MAX_DESC_LEN :
+ 							plen - 12;
++
++						if (desclen <= 0) {
++							error = "Response Packet desclen error";
++							goto prot_error;
++						}
++
+ 						strncpy(nd->nd_ps_desc, b + 12, desclen);
+ 						nd->nd_ps_desc[desclen] = 0;
+ 					}

commit 7b6d45c211a401a9bdeebfa96f8a4c811bd3eeaf
+Author: Bill Pemberton 
+Date:   Thu Sep 20 16:55:28 2012 -0400
+
+    staging: dgrp: add dgrp to the build
+    
+    Kconfig and Makefile changes to add dgrp to the build system.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
+index e3402d5644dd..21114512fcb2 100644
+--- a/drivers/staging/Kconfig
++++ b/drivers/staging/Kconfig
+@@ -136,4 +136,6 @@ source "drivers/staging/csr/Kconfig"
+ 
+ source "drivers/staging/omap-thermal/Kconfig"
+ 
++source "drivers/staging/dgrp/Kconfig"
++
+ endif # STAGING
+diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
+index 3be59d02cae4..17c43c4cacaa 100644
+--- a/drivers/staging/Makefile
++++ b/drivers/staging/Makefile
+@@ -60,3 +60,4 @@ obj-$(CONFIG_USB_G_CCG)		+= ccg/
+ obj-$(CONFIG_WIMAX_GDM72XX)	+= gdm72xx/
+ obj-$(CONFIG_CSR_WIFI)		+= csr/
+ obj-$(CONFIG_OMAP_BANDGAP)	+= omap-thermal/
++obj-$(CONFIG_DGRP)		+= dgrp/
+diff --git a/drivers/staging/dgrp/TODO b/drivers/staging/dgrp/TODO
+index 63341ade90d4..3ef2611bc6d7 100644
+--- a/drivers/staging/dgrp/TODO
++++ b/drivers/staging/dgrp/TODO
+@@ -1,7 +1,13 @@
+ - Use configfs for config stuff.  This will require changes to the
+   user space code.
+ 
+-- Check the calls to tty_register_device.  In particular, check to see
+-  if there should be some handling for IS_ERR(classp).
+-
+ - dgrp_send() and dgrp_receive() could use some refactoring
++
++- Don't automatically create CHAN_MAX (64) channel array entries for
++  every device as many devices are going to have much less than 64
++  channels.
++
++- The locking needs to be checked.  It seems haphazardly done in most
++  places.
++
++- Check Kconfig dependencies

commit 0b52b74972712479ca285c04452db0d4b9025f80
+Author: Bill Pemberton 
+Date:   Thu Sep 20 16:55:27 2012 -0400
+
+    staging: Add dgrp driver for Digi Realport devices
+    
+    This is based on dgrp-1.9 available from
+    ftp://ftp1.digi.com/support/beta/linux/dgrp/dgrp-1.9.tgz
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/dgrp/Kconfig b/drivers/staging/dgrp/Kconfig
+new file mode 100644
+index 000000000000..39f4bb65ec83
+--- /dev/null
++++ b/drivers/staging/dgrp/Kconfig
+@@ -0,0 +1,9 @@
++config DGRP
++       tristate "Digi Realport driver"
++       default n
++       depends on SYSFS
++       ---help---
++       Support for Digi Realport devices.  These devices allow you to
++       access remote serial ports as if they are local tty devices.  This
++       will build the kernel driver, you will still need the userspace
++       component to make your Realport device work.
+diff --git a/drivers/staging/dgrp/Makefile b/drivers/staging/dgrp/Makefile
+new file mode 100644
+index 000000000000..d9c3b88d7162
+--- /dev/null
++++ b/drivers/staging/dgrp/Makefile
+@@ -0,0 +1,12 @@
++obj-$(CONFIG_DGRP) += dgrp.o
++
++dgrp-y := 			\
++	dgrp_common.o 		\
++	dgrp_dpa_ops.o 		\
++	dgrp_driver.o 		\
++	dgrp_mon_ops.o 	 	\
++	dgrp_net_ops.o 		\
++	dgrp_ports_ops.o 	\
++	dgrp_specproc.o 	\
++	dgrp_tty.o 		\
++	dgrp_sysfs.o
+diff --git a/drivers/staging/dgrp/README b/drivers/staging/dgrp/README
+new file mode 100644
+index 000000000000..1d8aaee270e8
+--- /dev/null
++++ b/drivers/staging/dgrp/README
+@@ -0,0 +1,2 @@
++The user space code to work with this driver is located at
++https://github.com/wfp5p/dgrp-utils
+diff --git a/drivers/staging/dgrp/TODO b/drivers/staging/dgrp/TODO
+new file mode 100644
+index 000000000000..63341ade90d4
+--- /dev/null
++++ b/drivers/staging/dgrp/TODO
+@@ -0,0 +1,7 @@
++- Use configfs for config stuff.  This will require changes to the
++  user space code.
++
++- Check the calls to tty_register_device.  In particular, check to see
++  if there should be some handling for IS_ERR(classp).
++
++- dgrp_send() and dgrp_receive() could use some refactoring
+diff --git a/drivers/staging/dgrp/dgrp_common.c b/drivers/staging/dgrp/dgrp_common.c
+new file mode 100644
+index 000000000000..fce74e7fb834
+--- /dev/null
++++ b/drivers/staging/dgrp/dgrp_common.c
+@@ -0,0 +1,200 @@
++/*
++ *
++ * Copyright 1999 Digi International (www.digi.com)
++ *     James Puzzo 
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
++ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
++ * PURPOSE.  See the GNU General Public License for more details.
++ *
++ */
++
++/*
++ *
++ *  Filename:
++ *
++ *     dgrp_common.c
++ *
++ *  Description:
++ *
++ *     Definitions of global variables and functions which are either
++ *     shared by the tty, mon, and net drivers; or which cross them
++ *     functionally (like the poller).
++ *
++ *  Author:
++ *
++ *     James A. Puzzo
++ *
++ */
++
++#include 
++#include 
++#include 
++#include 
++
++#include "dgrp_common.h"
++
++/**
++ * dgrp_carrier -- check for carrier change state and act
++ * @ch: struct ch_struct *
++ */
++void dgrp_carrier(struct ch_struct *ch)
++{
++	struct nd_struct *nd;
++
++	int virt_carrier = 0;
++	int phys_carrier = 0;
++
++	/* fix case when the tty has already closed. */
++
++	if (!ch)
++		return;
++	nd  = ch->ch_nd;
++	if (!nd)
++		return;
++
++	/*
++	 *  If we are currently waiting to determine the status of the port,
++	 *  we don't yet know the state of the modem lines.  As a result,
++	 *  we ignore state changes when we are waiting for the modem lines
++	 *  to be established.  We know, as a result of code in dgrp_net_ops,
++	 *  that we will be called again immediately following the reception
++	 *  of the status message with the true modem status flags in it.
++	 */
++	if (ch->ch_expect & RR_STATUS)
++		return;
++
++	/*
++	 * If CH_HANGUP is set, we gotta keep trying to get all the processes
++	 * that have the port open to close the port.
++	 * So lets just keep sending a hangup every time we get here.
++	 */
++	if ((ch->ch_flag & CH_HANGUP) &&
++	    (ch->ch_tun.un_open_count > 0))
++		tty_hangup(ch->ch_tun.un_tty);
++
++	/*
++	 *  Compute the effective state of both the physical and virtual
++	 *  senses of carrier.
++	 */
++
++	if (ch->ch_s_mlast & DM_CD)
++		phys_carrier = 1;
++
++	if ((ch->ch_s_mlast & DM_CD) ||
++	    (ch->ch_digi.digi_flags & DIGI_FORCEDCD) ||
++	    (ch->ch_flag & CH_CLOCAL))
++		virt_carrier = 1;
++
++	/*
++	 *  Test for a VIRTUAL carrier transition to HIGH.
++	 *
++	 *  The CH_HANGUP condition is intended to prevent any action
++	 *  except for close.  As a result, we ignore positive carrier
++	 *  transitions during CH_HANGUP.
++	 */
++	if (((ch->ch_flag & CH_HANGUP)  == 0) &&
++	    ((ch->ch_flag & CH_VIRT_CD) == 0) &&
++	    (virt_carrier == 1)) {
++		/*
++		 * When carrier rises, wake any threads waiting
++		 * for carrier in the open routine.
++		 */
++		nd->nd_tx_work = 1;
++
++		if (waitqueue_active(&ch->ch_flag_wait))
++			wake_up_interruptible(&ch->ch_flag_wait);
++	}
++
++	/*
++	 *  Test for a PHYSICAL transition to low, so long as we aren't
++	 *  currently ignoring physical transitions (which is what "virtual
++	 *  carrier" indicates).
++	 *
++	 *  The transition of the virtual carrier to low really doesn't
++	 *  matter... it really only means "ignore carrier state", not
++	 *  "make pretend that carrier is there".
++	 */
++	if ((virt_carrier == 0) &&
++	    ((ch->ch_flag & CH_PHYS_CD) != 0) &&
++	    (phys_carrier == 0)) {
++		/*
++		 * When carrier drops:
++		 *
++		 *   Do a Hard Hangup if that is called for.
++		 *
++		 *   Drop carrier on all open units.
++		 *
++		 *   Flush queues, waking up any task waiting in the
++		 *   line discipline.
++		 *
++		 *   Send a hangup to the control terminal.
++		 *
++		 *   Enable all select calls.
++		 */
++
++		nd->nd_tx_work = 1;
++
++		ch->ch_flag &= ~(CH_LOW | CH_EMPTY | CH_DRAIN | CH_INPUT);
++
++		if (waitqueue_active(&ch->ch_flag_wait))
++			wake_up_interruptible(&ch->ch_flag_wait);
++
++		if (ch->ch_tun.un_open_count > 0)
++			tty_hangup(ch->ch_tun.un_tty);
++
++		if (ch->ch_pun.un_open_count > 0)
++			tty_hangup(ch->ch_pun.un_tty);
++	}
++
++	/*
++	 *  Make sure that our cached values reflect the current reality.
++	 */
++	if (virt_carrier == 1)
++		ch->ch_flag |= CH_VIRT_CD;
++	else
++		ch->ch_flag &= ~CH_VIRT_CD;
++
++	if (phys_carrier == 1)
++		ch->ch_flag |= CH_PHYS_CD;
++	else
++		ch->ch_flag &= ~CH_PHYS_CD;
++
++}
++
++/**
++ * dgrp_chk_perm() -- check permissions for net device
++ * @inode: pointer to inode structure for the net communication device
++ * @op: operation to be tested
++ *
++ * The file permissions and ownerships are tested to determine whether
++ * the operation "op" is permitted on the file pointed to by the inode.
++ * Returns 0 if the operation is permitted, -EACCESS otherwise
++ */
++int dgrp_chk_perm(int mode, int op)
++{
++	if (!current_euid())
++		mode >>= 6;
++	else if (in_egroup_p(0))
++		mode >>= 3;
++
++	if ((mode & op & 0007) == op)
++		return 0;
++
++	if (capable(CAP_SYS_ADMIN))
++		return 0;
++
++	return -EACCES;
++}
++
++/* dgrp_chk_perm wrapper for permission call in struct inode_operations */
++int dgrp_inode_permission(struct inode *inode, int op)
++{
++	return dgrp_chk_perm(inode->i_mode, op);
++}
+diff --git a/drivers/staging/dgrp/dgrp_common.h b/drivers/staging/dgrp/dgrp_common.h
+new file mode 100644
+index 000000000000..05ff338471ac
+--- /dev/null
++++ b/drivers/staging/dgrp/dgrp_common.h
+@@ -0,0 +1,208 @@
++/*
++ *
++ * Copyright 1999 Digi International (www.digi.com)
++ *     James Puzzo 
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
++ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
++ * PURPOSE.  See the GNU General Public License for more details.
++ *
++ */
++
++#ifndef __DGRP_COMMON_H
++#define __DGRP_COMMON_H
++
++#define DIGI_VERSION "1.9-29"
++
++#include 
++#include 
++#include "drp.h"
++
++#define DGRP_TTIME 100
++#define DGRP_RTIME 100
++
++/************************************************************************
++ * All global storage allocation.
++ ************************************************************************/
++
++extern int dgrp_rawreadok;  /* Allow raw writing of input */
++extern int dgrp_register_cudevices; /* enable legacy cu devices */
++extern int dgrp_register_prdevices; /* enable transparent print devices */
++extern int dgrp_poll_tick;          /* Poll interval - in ms */
++
++extern struct list_head nd_struct_list;
++
++struct dgrp_poll_data {
++	spinlock_t poll_lock;
++	struct timer_list timer;
++	int poll_tick;
++	ulong poll_round;	/* Timer rouding factor */
++	long node_active_count;
++};
++
++extern struct dgrp_poll_data dgrp_poll_data;
++extern void dgrp_poll_handler(unsigned long arg);
++
++/* from dgrp_mon_ops.c */
++extern void dgrp_register_mon_hook(struct proc_dir_entry *de);
++
++/* from dgrp_tty.c */
++extern int dgrp_tty_init(struct nd_struct *nd);
++extern void dgrp_tty_uninit(struct nd_struct *nd);
++
++/* from dgrp_ports_ops.c */
++extern void dgrp_register_ports_hook(struct proc_dir_entry *de);
++
++/* from dgrp_net_ops.c */
++extern void dgrp_register_net_hook(struct proc_dir_entry *de);
++
++/* from dgrp_dpa_ops.c */
++extern void dgrp_register_dpa_hook(struct proc_dir_entry *de);
++extern void dgrp_dpa_data(struct nd_struct *, int, u8 *, int);
++
++/* from dgrp_sysfs.c */
++extern void dgrp_create_class_sysfs_files(void);
++extern void dgrp_remove_class_sysfs_files(void);
++
++extern void dgrp_create_node_class_sysfs_files(struct nd_struct *nd);
++extern void dgrp_remove_node_class_sysfs_files(struct nd_struct *nd);
++
++extern void dgrp_create_tty_sysfs(struct un_struct *un, struct device *c);
++extern void dgrp_remove_tty_sysfs(struct device *c);
++
++/* from dgrp_specproc.c */
++/*
++ *  The list of DGRP entries with r/w capabilities.  These
++ *  magic numbers are used for identification purposes.
++ */
++enum {
++	DGRP_CONFIG = 1,	/* Configure portservers */
++	DGRP_NETDIR = 2,	/* Directory for "net" devices */
++	DGRP_MONDIR = 3,	/* Directory for "mon" devices */
++	DGRP_PORTSDIR = 4,	/* Directory for "ports" devices */
++	DGRP_INFO = 5,		/* Get info. about the running module */
++	DGRP_NODEINFO = 6,	/* Get info. about the configured nodes */
++	DGRP_DPADIR = 7,	/* Directory for the "dpa" devices */
++};
++
++/*
++ *  Directions for proc handlers
++ */
++enum {
++	INBOUND = 1,		/* Data being written to kernel */
++	OUTBOUND = 2,		/* Data being read from the kernel */
++};
++
++/**
++ * dgrp_proc_entry: structure for dgrp proc dirs
++ * @id: ID number associated with this particular entry.  Should be
++ *    unique across all of DGRP.
++ * @name: text name associated with the /proc entry
++ * @mode: file access permisssions for the /proc entry
++ * @child: pointer to table describing a subdirectory for this entry
++ * @de: pointer to directory entry for this object once registered.  Used
++ *    to grab the handle of the object for unregistration
++ * @excl_sem: semaphore to provide exclusive to struct
++ * @excl_cnt: counter of current accesses
++ *
++ *  Each entry in a DGRP proc directory is described with a
++ *  dgrp_proc_entry structure.  A collection of these
++ *  entries (in an array) represents the members associated
++ *  with a particular /proc directory, and is referred to
++ *  as a table.  All tables are terminated by an entry with
++ *  zeros for every member.
++ */
++struct dgrp_proc_entry {
++	int                  id;          /* Integer identifier */
++	const char        *name;          /* ASCII identifier */
++	mode_t             mode;          /* File access permissions */
++	struct dgrp_proc_entry *child;    /* Child pointer */
++
++	/* file ops to use, pass NULL to use default */
++	struct file_operations *proc_file_ops;
++
++	struct proc_dir_entry *de;        /* proc entry pointer */
++	struct semaphore   excl_sem;      /* Protects exclusive access var */
++	int                excl_cnt;      /* Counts number of curr accesses */
++};
++
++extern void dgrp_unregister_proc(void);
++extern void dgrp_register_proc(void);
++
++/*-----------------------------------------------------------------------*
++ *
++ *  Declarations for common operations:
++ *
++ *      (either used by more than one of net, mon, or tty,
++ *       or in interrupt context (i.e. the poller))
++ *
++ *-----------------------------------------------------------------------*/
++
++void dgrp_carrier(struct ch_struct *ch);
++extern int dgrp_inode_permission(struct inode *inode, int op);
++extern int dgrp_chk_perm(int mode, int op);
++
++
++/*
++ *  ID manipulation macros (where c1 & c2 are characters, i is
++ *  a long integer, and s is a character array of at least three members
++ */
++
++static inline void ID_TO_CHAR(long i, char *s)
++{
++	s[0] = ((i & 0xff00)>>8);
++	s[1] = (i & 0xff);
++	s[2] = 0;
++}
++
++static inline long CHAR_TO_ID(char *s)
++{
++	return ((s[0] & 0xff) << 8) | (s[1] & 0xff);
++}
++
++static inline struct nd_struct *nd_struct_get(long major)
++{
++	struct nd_struct *nd;
++
++	list_for_each_entry(nd, &nd_struct_list, list) {
++		if (major == nd->nd_major)
++			return nd;
++	}
++
++	return NULL;
++}
++
++static inline int nd_struct_add(struct nd_struct *entry)
++{
++	struct nd_struct *ptr;
++
++	ptr = nd_struct_get(entry->nd_major);
++
++	if (ptr)
++		return -EBUSY;
++
++	list_add_tail(&entry->list, &nd_struct_list);
++
++	return 0;
++}
++
++static inline int nd_struct_del(struct nd_struct *entry)
++{
++	struct nd_struct *nd;
++
++	nd = nd_struct_get(entry->nd_major);
++
++	if (!nd)
++		return -ENODEV;
++
++	list_del(&nd->list);
++	return 0;
++}
++
++#endif /* __DGRP_COMMON_H */
+diff --git a/drivers/staging/dgrp/dgrp_dpa_ops.c b/drivers/staging/dgrp/dgrp_dpa_ops.c
+new file mode 100644
+index 000000000000..49e670915e5c
+--- /dev/null
++++ b/drivers/staging/dgrp/dgrp_dpa_ops.c
+@@ -0,0 +1,556 @@
++/*
++ *
++ * Copyright 1999 Digi International (www.digi.com)
++ *     James Puzzo 
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
++ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
++ * PURPOSE.  See the GNU General Public License for more details.
++ *
++ */
++
++/*
++ *
++ *  Filename:
++ *
++ *     dgrp_dpa_ops.c
++ *
++ *  Description:
++ *
++ *     Handle the file operations required for the "dpa" devices.
++ *     Includes those functions required to register the "dpa" devices
++ *     in "/proc".
++ *
++ *  Author:
++ *
++ *     James A. Puzzo
++ *
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include "dgrp_common.h"
++
++/* File operation declarations */
++static int dgrp_dpa_open(struct inode *, struct file *);
++static int dgrp_dpa_release(struct inode *, struct file *);
++static ssize_t dgrp_dpa_read(struct file *, char __user *, size_t, loff_t *);
++static long dgrp_dpa_ioctl(struct file *file, unsigned int cmd,
++			   unsigned long arg);
++static unsigned int dgrp_dpa_select(struct file *, struct poll_table_struct *);
++
++static const struct file_operations dpa_ops = {
++	.owner   =  THIS_MODULE,
++	.read    =  dgrp_dpa_read,
++	.poll    =  dgrp_dpa_select,
++	.unlocked_ioctl =  dgrp_dpa_ioctl,
++	.open    =  dgrp_dpa_open,
++	.release =  dgrp_dpa_release,
++};
++
++static struct inode_operations dpa_inode_ops = {
++	.permission = dgrp_inode_permission
++};
++
++
++
++struct digi_node {
++	uint	nd_state;		/* Node state: 1 = up, 0 = down. */
++	uint	nd_chan_count;		/* Number of channels found */
++	uint	nd_tx_byte;		/* Tx data count */
++	uint	nd_rx_byte;		/* RX data count */
++	u8	nd_ps_desc[MAX_DESC_LEN]; /* Description from PS */
++};
++
++#define DIGI_GETNODE      (('d'<<8) | 249)	/* get board info */
++
++
++struct digi_chan {
++	uint	ch_port;	/* Port number to get info on */
++	uint	ch_open;	/* 1 if open, 0 if not */
++	uint	ch_txcount;	/* TX data count  */
++	uint	ch_rxcount;	/* RX data count  */
++	uint	ch_s_brate;	/* Realport BRATE */
++	uint	ch_s_estat;	/* Realport ELAST */
++	uint	ch_s_cflag;	/* Realport CFLAG */
++	uint	ch_s_iflag;	/* Realport IFLAG */
++	uint	ch_s_oflag;	/* Realport OFLAG */
++	uint	ch_s_xflag;	/* Realport XFLAG */
++	uint	ch_s_mstat;	/* Realport MLAST */
++};
++
++#define DIGI_GETCHAN      (('d'<<8) | 248)	/* get channel info */
++
++
++struct digi_vpd {
++	int vpd_len;
++	char vpd_data[VPDSIZE];
++};
++
++#define DIGI_GETVPD       (('d'<<8) | 246)	/* get VPD info */
++
++
++struct digi_debug {
++	int onoff;
++	int port;
++};
++
++#define DIGI_SETDEBUG      (('d'<<8) | 247)	/* set debug info */
++
++
++void dgrp_register_dpa_hook(struct proc_dir_entry *de)
++{
++	struct nd_struct *node = de->data;
++
++	de->proc_iops = &dpa_inode_ops;
++	de->proc_fops = &dpa_ops;
++
++	node->nd_dpa_de = de;
++	spin_lock_init(&node->nd_dpa_lock);
++}
++
++/*
++ * dgrp_dpa_open -- open the DPA device for a particular PortServer
++ */
++static int dgrp_dpa_open(struct inode *inode, struct file *file)
++{
++	struct nd_struct *nd;
++	int rtn = 0;
++
++	struct proc_dir_entry *de;
++
++	rtn = try_module_get(THIS_MODULE);
++	if (!rtn)
++		return -ENXIO;
++
++	rtn = 0;
++
++	if (!capable(CAP_SYS_ADMIN)) {
++		rtn = -EPERM;
++		goto done;
++	}
++
++	/*
++	 *  Make sure that the "private_data" field hasn't already been used.
++	 */
++	if (file->private_data) {
++		rtn = -EINVAL;
++		goto done;
++	}
++
++	/*
++	 *  Get the node pointer, and fail if it doesn't exist.
++	 */
++	de = PDE(inode);
++	if (!de) {
++		rtn = -ENXIO;
++		goto done;
++	}
++	nd = (struct nd_struct *)de->data;
++	if (!nd) {
++		rtn = -ENXIO;
++		goto done;
++	}
++
++	file->private_data = (void *) nd;
++
++	/*
++	 * Allocate the DPA buffer.
++	 */
++
++	if (nd->nd_dpa_buf) {
++		rtn = -EBUSY;
++	} else {
++		nd->nd_dpa_buf = kmalloc(DPA_MAX, GFP_KERNEL);
++
++		if (!nd->nd_dpa_buf) {
++			rtn = -ENOMEM;
++		} else {
++			nd->nd_dpa_out = 0;
++			nd->nd_dpa_in = 0;
++			nd->nd_dpa_lbolt = jiffies;
++		}
++	}
++
++done:
++
++	if (rtn)
++		module_put(THIS_MODULE);
++	return rtn;
++}
++
++/*
++ * dgrp_dpa_release -- close the DPA device for a particular PortServer
++ */
++static int dgrp_dpa_release(struct inode *inode, struct file *file)
++{
++	struct nd_struct *nd;
++	u8 *buf;
++	unsigned long lock_flags;
++
++	/*
++	 *  Get the node pointer, and quit if it doesn't exist.
++	 */
++	nd = (struct nd_struct *)(file->private_data);
++	if (!nd)
++		goto done;
++
++	/*
++	 *  Free the dpa buffer.
++	 */
++
++	spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags);
++
++	buf = nd->nd_dpa_buf;
++
++	nd->nd_dpa_buf = NULL;
++	nd->nd_dpa_out = nd->nd_dpa_in;
++
++	/*
++	 *  Wakeup any thread waiting for buffer space.
++	 */
++
++	if (nd->nd_dpa_flag & DPA_WAIT_SPACE) {
++		nd->nd_dpa_flag &= ~DPA_WAIT_SPACE;
++		wake_up_interruptible(&nd->nd_dpa_wqueue);
++	}
++
++	spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
++
++	kfree(buf);
++
++done:
++	module_put(THIS_MODULE);
++	file->private_data = NULL;
++	return 0;
++}
++
++/*
++ * dgrp_dpa_read
++ *
++ * Copy data from the monitoring buffer to the user, freeing space
++ * in the monitoring buffer for more messages
++ */
++static ssize_t dgrp_dpa_read(struct file *file, char __user *buf, size_t count,
++			     loff_t *ppos)
++{
++	struct nd_struct *nd;
++	int n;
++	int r;
++	int offset = 0;
++	int res = 0;
++	ssize_t rtn;
++	unsigned long lock_flags;
++
++	/*
++	 *  Get the node pointer, and quit if it doesn't exist.
++	 */
++	nd = (struct nd_struct *)(file->private_data);
++	if (!nd)
++		return -ENXIO;
++
++	/*
++	 *  Wait for some data to appear in the buffer.
++	 */
++
++	spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags);
++
++	for (;;) {
++		n = (nd->nd_dpa_in - nd->nd_dpa_out) & DPA_MASK;
++
++		if (n != 0)
++			break;
++
++		nd->nd_dpa_flag |= DPA_WAIT_DATA;
++
++		spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
++
++		/*
++		 * Go to sleep waiting until the condition becomes true.
++		 */
++		rtn = wait_event_interruptible(nd->nd_dpa_wqueue,
++			((nd->nd_dpa_flag & DPA_WAIT_DATA) == 0));
++
++		if (rtn)
++			return rtn;
++
++		spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags);
++	}
++
++	/*
++	 *  Read whatever is there.
++	 */
++
++	if (n > count)
++		n = count;
++
++	res = n;
++
++	r = DPA_MAX - nd->nd_dpa_out;
++
++	if (r <= n) {
++
++		spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
++		rtn = copy_to_user((void __user *)buf,
++				   nd->nd_dpa_buf + nd->nd_dpa_out, r);
++		spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags);
++
++		if (rtn) {
++			rtn = -EFAULT;
++			goto done;
++		}
++
++		nd->nd_dpa_out = 0;
++		n -= r;
++		offset = r;
++	}
++
++	spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
++	rtn = copy_to_user((void __user *)buf + offset,
++			   nd->nd_dpa_buf + nd->nd_dpa_out, n);
++	spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags);
++
++	if (rtn) {
++		rtn = -EFAULT;
++		goto done;
++	}
++
++	nd->nd_dpa_out += n;
++
++	*ppos += res;
++
++	rtn = res;
++
++	/*
++	 *  Wakeup any thread waiting for buffer space.
++	 */
++
++	n = (nd->nd_dpa_in - nd->nd_dpa_out) & DPA_MASK;
++
++	if (nd->nd_dpa_flag & DPA_WAIT_SPACE &&
++	    (DPA_MAX - n) > DPA_HIGH_WATER) {
++		nd->nd_dpa_flag &= ~DPA_WAIT_SPACE;
++		wake_up_interruptible(&nd->nd_dpa_wqueue);
++	}
++
++ done:
++	spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
++	return rtn;
++}
++
++static unsigned int dgrp_dpa_select(struct file *file,
++				    struct poll_table_struct *table)
++{
++	unsigned int retval = 0;
++	struct nd_struct *nd = file->private_data;
++
++	if (nd->nd_dpa_out != nd->nd_dpa_in)
++		retval |= POLLIN | POLLRDNORM; /* Conditionally readable */
++
++	retval |= POLLOUT | POLLWRNORM;        /* Always writeable */
++
++	return retval;
++}
++
++static long dgrp_dpa_ioctl(struct file *file, unsigned int cmd,
++			   unsigned long arg)
++{
++
++	struct nd_struct  *nd;
++	struct digi_chan getchan;
++	struct digi_node getnode;
++	struct ch_struct *ch;
++	struct digi_debug setdebug;
++	struct digi_vpd vpd;
++	unsigned int port;
++	void __user *uarg = (void __user *) arg;
++
++	nd = file->private_data;
++
++	switch (cmd) {
++	case DIGI_GETCHAN:
++		if (copy_from_user(&getchan, uarg, sizeof(struct digi_chan)))
++			return -EFAULT;
++
++		port = getchan.ch_port;
++
++		if (port < 0 || port > nd->nd_chan_count)
++			return -EINVAL;
++
++		ch = nd->nd_chan + port;
++
++		getchan.ch_open = (ch->ch_open_count > 0) ? 1 : 0;
++		getchan.ch_txcount = ch->ch_txcount;
++		getchan.ch_rxcount = ch->ch_rxcount;
++		getchan.ch_s_brate = ch->ch_s_brate;
++		getchan.ch_s_estat = ch->ch_s_elast;
++		getchan.ch_s_cflag = ch->ch_s_cflag;
++		getchan.ch_s_iflag = ch->ch_s_iflag;
++		getchan.ch_s_oflag = ch->ch_s_oflag;
++		getchan.ch_s_xflag = ch->ch_s_xflag;
++		getchan.ch_s_mstat = ch->ch_s_mlast;
++
++		if (copy_to_user(uarg, &getchan, sizeof(struct digi_chan)))
++			return -EFAULT;
++		break;
++
++
++	case DIGI_GETNODE:
++		getnode.nd_state = (nd->nd_state & NS_READY) ? 1 : 0;
++		getnode.nd_chan_count = nd->nd_chan_count;
++		getnode.nd_tx_byte = nd->nd_tx_byte;
++		getnode.nd_rx_byte = nd->nd_rx_byte;
++
++		memset(&getnode.nd_ps_desc, 0, MAX_DESC_LEN);
++		strncpy(getnode.nd_ps_desc, nd->nd_ps_desc, MAX_DESC_LEN);
++
++		if (copy_to_user(uarg, &getnode, sizeof(struct digi_node)))
++			return -EFAULT;
++		break;
++
++
++	case DIGI_SETDEBUG:
++		if (copy_from_user(&setdebug, uarg, sizeof(struct digi_debug)))
++			return -EFAULT;
++
++		nd->nd_dpa_debug = setdebug.onoff;
++		nd->nd_dpa_port = setdebug.port;
++		break;
++
++
++	case DIGI_GETVPD:
++		if (nd->nd_vpd_len > 0) {
++			vpd.vpd_len = nd->nd_vpd_len;
++			memcpy(&vpd.vpd_data, &nd->nd_vpd, nd->nd_vpd_len);
++		} else {
++			vpd.vpd_len = 0;
++		}
++
++		if (copy_to_user(uarg, &vpd, sizeof(struct digi_vpd)))
++			return -EFAULT;
++		break;
++	}
++
++	return 0;
++}
++
++/**
++ * dgrp_dpa() -- send data to the device monitor queue
++ * @nd: pointer to a node structure
++ * @buf: buffer of data to copy to the monitoring buffer
++ * @len: number of bytes to transfer to the buffer
++ *
++ * Called by the net device routines to send data to the device
++ * monitor queue.  If the device monitor buffer is too full to
++ * accept the data, it waits until the buffer is ready.
++ */
++static void dgrp_dpa(struct nd_struct *nd, u8 *buf, int nbuf)
++{
++	int n;
++	int r;
++	unsigned long lock_flags;
++
++	/*
++	 *  Grab DPA lock.
++	 */
++	spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags);
++
++	/*
++	 *  Loop while data remains.
++	 */
++	while (nbuf > 0 && nd->nd_dpa_buf != NULL) {
++
++		n = (nd->nd_dpa_out - nd->nd_dpa_in - 1) & DPA_MASK;
++
++		/*
++		 * Enforce flow control on the DPA device.
++		 */
++		if (n < (DPA_MAX - DPA_HIGH_WATER))
++			nd->nd_dpa_flag |= DPA_WAIT_SPACE;
++
++		/*
++		 * This should never happen, as the flow control above
++		 * should have stopped things before they got to this point.
++		 */
++		if (n == 0) {
++			spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
++			return;
++		}
++
++		/*
++		 * Copy as much data as will fit.
++		 */
++
++		if (n > nbuf)
++			n = nbuf;
++
++		r = DPA_MAX - nd->nd_dpa_in;
++
++		if (r <= n) {
++			memcpy(nd->nd_dpa_buf + nd->nd_dpa_in, buf, r);
++
++			n -= r;
++
++			nd->nd_dpa_in = 0;
++
++			buf += r;
++			nbuf -= r;
++		}
++
++		memcpy(nd->nd_dpa_buf + nd->nd_dpa_in, buf, n);
++
++		nd->nd_dpa_in += n;
++
++		buf += n;
++		nbuf -= n;
++
++		if (nd->nd_dpa_in >= DPA_MAX)
++			pr_info_ratelimited("%s - nd->nd_dpa_in (%i) >= DPA_MAX\n",
++					    __func__, nd->nd_dpa_in);
++
++		/*
++		 *  Wakeup any thread waiting for data
++		 */
++		if (nd->nd_dpa_flag & DPA_WAIT_DATA) {
++			nd->nd_dpa_flag &= ~DPA_WAIT_DATA;
++			wake_up_interruptible(&nd->nd_dpa_wqueue);
++		}
++	}
++
++	/*
++	 *  Release the DPA lock.
++	 */
++	spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
++}
++
++/**
++ * dgrp_monitor_data() -- builds a DPA data packet
++ * @nd: pointer to a node structure
++ * @type: type of message to be logged in the DPA buffer
++ * @buf: buffer of data to be logged in the DPA buffer
++ * @size -- number of bytes in the "buf" buffer
++ */
++void dgrp_dpa_data(struct nd_struct *nd, int type, u8 *buf, int size)
++{
++	u8 header[5];
++
++	header[0] = type;
++
++	put_unaligned_be32(size, header + 1);
++
++	dgrp_dpa(nd, header, sizeof(header));
++	dgrp_dpa(nd, buf, size);
++}
+diff --git a/drivers/staging/dgrp/dgrp_driver.c b/drivers/staging/dgrp/dgrp_driver.c
+new file mode 100644
+index 000000000000..6e4a0ebc0749
+--- /dev/null
++++ b/drivers/staging/dgrp/dgrp_driver.c
+@@ -0,0 +1,110 @@
++/*
++ *
++ * Copyright 1999-2003 Digi International (www.digi.com)
++ *     Jeff Randall
++ *     James Puzzo  
++ *     Scott Kilau  
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
++ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
++ * PURPOSE.  See the GNU General Public License for more details.
++ *
++ */
++
++/*
++ *	Driver specific includes
++ */
++#include 
++#include 
++#include 
++#include 
++
++/*
++ *  PortServer includes
++ */
++#include "dgrp_common.h"
++
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Digi International, http://www.digi.com");
++MODULE_DESCRIPTION("RealPort driver for Digi's ethernet-based serial connectivity product line");
++MODULE_VERSION(DIGI_VERSION);
++
++struct list_head nd_struct_list;
++struct dgrp_poll_data dgrp_poll_data;
++
++int dgrp_rawreadok = 1;		/* Bypass flipbuf on input */
++int dgrp_register_cudevices = 1;/* Turn on/off registering legacy cu devices */
++int dgrp_register_prdevices = 1;/* Turn on/off registering transparent print */
++int dgrp_poll_tick = 20;	/* Poll interval - in ms */
++
++module_param_named(rawreadok, dgrp_rawreadok, int, 0644);
++MODULE_PARM_DESC(rawreadok, "Bypass flip buffers on input");
++
++module_param_named(register_cudevices, dgrp_register_cudevices, int, 0644);
++MODULE_PARM_DESC(register_cudevices, "Turn on/off registering legacy cu devices");
++
++module_param_named(register_prdevices, dgrp_register_prdevices, int, 0644);
++MODULE_PARM_DESC(register_prdevices, "Turn on/off registering transparent print devices");
++
++module_param_named(pollrate, dgrp_poll_tick, int, 0644);
++MODULE_PARM_DESC(pollrate, "Poll interval in ms");
++
++/* Driver load/unload functions */
++static int dgrp_init_module(void);
++static void dgrp_cleanup_module(void);
++
++module_init(dgrp_init_module);
++module_exit(dgrp_cleanup_module);
++
++/*
++ * init_module()
++ *
++ * Module load.  This is where it all starts.
++ */
++static int dgrp_init_module(void)
++{
++	INIT_LIST_HEAD(&nd_struct_list);
++
++	spin_lock_init(&dgrp_poll_data.poll_lock);
++	init_timer(&dgrp_poll_data.timer);
++	dgrp_poll_data.poll_tick = dgrp_poll_tick;
++	dgrp_poll_data.timer.function = dgrp_poll_handler;
++	dgrp_poll_data.timer.data = (unsigned long) &dgrp_poll_data;
++
++	dgrp_create_class_sysfs_files();
++
++	dgrp_register_proc();
++
++	return 0;
++}
++
++
++/*
++ *	Module unload.  This is where it all ends.
++ */
++static void dgrp_cleanup_module(void)
++{
++	struct nd_struct *nd, *next;
++
++	/*
++	 *	Attempting to free resources in backwards
++	 *	order of allocation, in case that helps
++	 *	memory pool fragmentation.
++	 */
++	dgrp_unregister_proc();
++
++	dgrp_remove_class_sysfs_files();
++
++
++	list_for_each_entry_safe(nd, next, &nd_struct_list, list) {
++		dgrp_tty_uninit(nd);
++		kfree(nd);
++	}
++}
+diff --git a/drivers/staging/dgrp/dgrp_mon_ops.c b/drivers/staging/dgrp/dgrp_mon_ops.c
+new file mode 100644
+index 000000000000..268dcb95204b
+--- /dev/null
++++ b/drivers/staging/dgrp/dgrp_mon_ops.c
+@@ -0,0 +1,346 @@
++/*****************************************************************************
++ *
++ * Copyright 1999 Digi International (www.digi.com)
++ *     James Puzzo 
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
++ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
++ * PURPOSE.  See the GNU General Public License for more details.
++ *
++ */
++
++/*
++ *
++ *  Filename:
++ *
++ *     dgrp_mon_ops.c
++ *
++ *  Description:
++ *
++ *     Handle the file operations required for the "monitor" devices.
++ *     Includes those functions required to register the "mon" devices
++ *     in "/proc".
++ *
++ *  Author:
++ *
++ *     James A. Puzzo
++ *
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include "dgrp_common.h"
++
++/* File operation declarations */
++static int dgrp_mon_open(struct inode *, struct file *);
++static int dgrp_mon_release(struct inode *, struct file *);
++static ssize_t dgrp_mon_read(struct file *, char __user *, size_t, loff_t *);
++static long dgrp_mon_ioctl(struct file *file, unsigned int cmd,
++			   unsigned long arg);
++
++static const struct file_operations mon_ops = {
++	.owner   = THIS_MODULE,
++	.read    = dgrp_mon_read,
++	.unlocked_ioctl = dgrp_mon_ioctl,
++	.open    = dgrp_mon_open,
++	.release = dgrp_mon_release,
++};
++
++static struct inode_operations mon_inode_ops = {
++	.permission = dgrp_inode_permission
++};
++
++void dgrp_register_mon_hook(struct proc_dir_entry *de)
++{
++	struct nd_struct *node = de->data;
++
++	de->proc_iops = &mon_inode_ops;
++	de->proc_fops = &mon_ops;
++	node->nd_mon_de = de;
++	sema_init(&node->nd_mon_semaphore, 1);
++}
++
++/**
++ * dgrp_mon_open() -- open /proc/dgrp/ports device for a PortServer
++ * @inode: struct inode *
++ * @file: struct file *
++ *
++ * Open function to open the /proc/dgrp/ports device for a PortServer.
++ */
++static int dgrp_mon_open(struct inode *inode, struct file *file)
++{
++	struct nd_struct *nd;
++	struct proc_dir_entry *de;
++	struct timeval tv;
++	uint32_t time;
++	u8 *buf;
++	int rtn;
++
++	rtn = try_module_get(THIS_MODULE);
++	if (!rtn)
++		return -ENXIO;
++
++	rtn = 0;
++
++	if (!capable(CAP_SYS_ADMIN)) {
++		rtn = -EPERM;
++		goto done;
++	}
++
++	/*
++	 *  Make sure that the "private_data" field hasn't already been used.
++	 */
++	if (file->private_data) {
++		rtn = -EINVAL;
++		goto done;
++	}
++
++	/*
++	 *  Get the node pointer, and fail if it doesn't exist.
++	 */
++	de = PDE(inode);
++	if (!de) {
++		rtn = -ENXIO;
++		goto done;
++	}
++
++	nd = (struct nd_struct *)de->data;
++	if (!nd) {
++		rtn = -ENXIO;
++		goto done;
++	}
++
++	file->private_data = (void *) nd;
++
++	/*
++	 * Allocate the monitor buffer.
++	 */
++
++	/*
++	 *  Grab the MON lock.
++	 */
++	down(&nd->nd_mon_semaphore);
++
++	if (nd->nd_mon_buf) {
++		rtn = -EBUSY;
++		goto done_up;
++	}
++
++	nd->nd_mon_buf = kmalloc(MON_MAX, GFP_KERNEL);
++
++	if (!nd->nd_mon_buf) {
++		rtn = -ENOMEM;
++		goto done_up;
++	}
++
++	/*
++	 *  Enter an RPDUMP file header into the buffer.
++	 */
++
++	buf = nd->nd_mon_buf;
++
++	strcpy(buf, RPDUMP_MAGIC);
++	buf += strlen(buf) + 1;
++
++	do_gettimeofday(&tv);
++
++	/*
++	 *  tv.tv_sec might be a 64 bit quantity.  Pare
++	 *  it down to 32 bits before attempting to encode
++	 *  it.
++	 */
++	time = (uint32_t) (tv.tv_sec & 0xffffffff);
++
++	put_unaligned_be32(time, buf);
++	put_unaligned_be16(0, buf + 4);
++	buf += 6;
++
++	if (nd->nd_tx_module) {
++		buf[0] = RPDUMP_CLIENT;
++		put_unaligned_be32(0, buf + 1);
++		put_unaligned_be16(1, buf + 5);
++		buf[7] = 0xf0 + nd->nd_tx_module;
++		buf += 8;
++	}
++
++	if (nd->nd_rx_module) {
++		buf[0] = RPDUMP_SERVER;
++		put_unaligned_be32(0, buf + 1);
++		put_unaligned_be16(1, buf + 5);
++		buf[7] = 0xf0 + nd->nd_rx_module;
++		buf += 8;
++	}
++
++	nd->nd_mon_out = 0;
++	nd->nd_mon_in  = buf - nd->nd_mon_buf;
++	nd->nd_mon_lbolt = jiffies;
++
++done_up:
++	up(&nd->nd_mon_semaphore);
++
++done:
++	if (rtn)
++		module_put(THIS_MODULE);
++	return rtn;
++}
++
++
++/**
++ * dgrp_mon_release() - Close the MON device for a particular PortServer
++ * @inode: struct inode *
++ * @file: struct file *
++ */
++static int dgrp_mon_release(struct inode *inode, struct file *file)
++{
++	struct nd_struct *nd;
++
++	/*
++	 *  Get the node pointer, and quit if it doesn't exist.
++	 */
++	nd = (struct nd_struct *)(file->private_data);
++	if (!nd)
++		goto done;
++
++	/*
++	 *  Free the monitor buffer.
++	 */
++
++	down(&nd->nd_mon_semaphore);
++
++	kfree(nd->nd_mon_buf);
++	nd->nd_mon_buf = NULL;
++	nd->nd_mon_out = nd->nd_mon_in;
++
++	/*
++	 *  Wakeup any thread waiting for buffer space.
++	 */
++
++	if (nd->nd_mon_flag & MON_WAIT_SPACE) {
++		nd->nd_mon_flag &= ~MON_WAIT_SPACE;
++		wake_up_interruptible(&nd->nd_mon_wqueue);
++	}
++
++	up(&nd->nd_mon_semaphore);
++
++	/*
++	 *  Make sure there is no thread in the middle of writing a packet.
++	 */
++	down(&nd->nd_net_semaphore);
++	up(&nd->nd_net_semaphore);
++
++done:
++	module_put(THIS_MODULE);
++	file->private_data = NULL;
++	return 0;
++}
++
++/**
++ * dgrp_mon_read() -- Copy data from the monitoring buffer to the user
++ */
++static ssize_t dgrp_mon_read(struct file *file, char __user *buf, size_t count,
++			     loff_t *ppos)
++{
++	struct nd_struct *nd;
++	int r;
++	int offset = 0;
++	int res = 0;
++	ssize_t rtn;
++
++	/*
++	 *  Get the node pointer, and quit if it doesn't exist.
++	 */
++	nd = (struct nd_struct *)(file->private_data);
++	if (!nd)
++		return -ENXIO;
++
++	/*
++	 *  Wait for some data to appear in the buffer.
++	 */
++
++	down(&nd->nd_mon_semaphore);
++
++	for (;;) {
++		res = (nd->nd_mon_in - nd->nd_mon_out) & MON_MASK;
++
++		if (res)
++			break;
++
++		nd->nd_mon_flag |= MON_WAIT_DATA;
++
++		up(&nd->nd_mon_semaphore);
++
++		/*
++		 * Go to sleep waiting until the condition becomes true.
++		 */
++		rtn = wait_event_interruptible(nd->nd_mon_wqueue,
++					       ((nd->nd_mon_flag & MON_WAIT_DATA) == 0));
++
++		if (rtn)
++			return rtn;
++
++		down(&nd->nd_mon_semaphore);
++	}
++
++	/*
++	 *  Read whatever is there.
++	 */
++
++	if (res > count)
++		res = count;
++
++	r = MON_MAX - nd->nd_mon_out;
++
++	if (r <= res) {
++		rtn = copy_to_user((void __user *)buf,
++				   nd->nd_mon_buf + nd->nd_mon_out, r);
++		if (rtn) {
++			up(&nd->nd_mon_semaphore);
++			return -EFAULT;
++		}
++
++		nd->nd_mon_out = 0;
++		res -= r;
++		offset = r;
++	}
++
++	rtn = copy_to_user((void __user *) buf + offset,
++			   nd->nd_mon_buf + nd->nd_mon_out, res);
++	if (rtn) {
++		up(&nd->nd_mon_semaphore);
++		return -EFAULT;
++	}
++
++	nd->nd_mon_out += res;
++
++	*ppos += res;
++
++	up(&nd->nd_mon_semaphore);
++
++	/*
++	 *  Wakeup any thread waiting for buffer space.
++	 */
++
++	if (nd->nd_mon_flag & MON_WAIT_SPACE) {
++		nd->nd_mon_flag &= ~MON_WAIT_SPACE;
++		wake_up_interruptible(&nd->nd_mon_wqueue);
++	}
++
++	return res;
++}
++
++/*  ioctl is not valid on monitor device */
++static long dgrp_mon_ioctl(struct file *file, unsigned int cmd,
++			   unsigned long arg)
++{
++	return -EINVAL;
++}
+diff --git a/drivers/staging/dgrp/dgrp_net_ops.c b/drivers/staging/dgrp/dgrp_net_ops.c
+new file mode 100644
+index 000000000000..d9d6b6709e4e
+--- /dev/null
++++ b/drivers/staging/dgrp/dgrp_net_ops.c
+@@ -0,0 +1,3731 @@
++/*
++ *
++ * Copyright 1999 Digi International (www.digi.com)
++ *     James Puzzo  
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
++ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
++ * PURPOSE.  See the GNU General Public License for more details.
++ *
++ */
++
++/*
++ *
++ *  Filename:
++ *
++ *     dgrp_net_ops.c
++ *
++ *  Description:
++ *
++ *     Handle the file operations required for the "network" devices.
++ *     Includes those functions required to register the "net" devices
++ *     in "/proc".
++ *
++ *  Author:
++ *
++ *     James A. Puzzo
++ *
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#define MYFLIPLEN	TBUF_MAX
++
++#include "dgrp_common.h"
++
++#define TTY_FLIPBUF_SIZE 512
++#define DEVICE_NAME_SIZE 50
++
++/*
++ *  Generic helper function declarations
++ */
++static void   parity_scan(struct ch_struct *ch, unsigned char *cbuf,
++				unsigned char *fbuf, int *len);
++
++/*
++ *  File operation declarations
++ */
++static int dgrp_net_open(struct inode *, struct file *);
++static int dgrp_net_release(struct inode *, struct file *);
++static ssize_t dgrp_net_read(struct file *, char __user *, size_t, loff_t *);
++static ssize_t dgrp_net_write(struct file *, const char __user *, size_t,
++			      loff_t *);
++static long dgrp_net_ioctl(struct file *file, unsigned int cmd,
++			   unsigned long arg);
++static unsigned int dgrp_net_select(struct file *file,
++				    struct poll_table_struct *table);
++
++static const struct file_operations net_ops = {
++	.owner   =  THIS_MODULE,
++	.read    =  dgrp_net_read,
++	.write   =  dgrp_net_write,
++	.poll    =  dgrp_net_select,
++	.unlocked_ioctl =  dgrp_net_ioctl,
++	.open    =  dgrp_net_open,
++	.release =  dgrp_net_release,
++};
++
++static struct inode_operations net_inode_ops = {
++	.permission = dgrp_inode_permission
++};
++
++void dgrp_register_net_hook(struct proc_dir_entry *de)
++{
++	struct nd_struct *node = de->data;
++
++	de->proc_iops = &net_inode_ops;
++	de->proc_fops = &net_ops;
++	node->nd_net_de = de;
++	sema_init(&node->nd_net_semaphore, 1);
++	node->nd_state = NS_CLOSED;
++	dgrp_create_node_class_sysfs_files(node);
++}
++
++
++/**
++ * dgrp_dump() -- prints memory for debugging purposes.
++ * @mem: Memory location which should be printed to the console
++ * @len: Number of bytes to be dumped
++ */
++static void dgrp_dump(u8 *mem, int len)
++{
++	int i;
++
++	pr_debug("dgrp dump length = %d, data = ", len);
++	for (i = 0; i < len; ++i)
++		pr_debug("%.2x ", mem[i]);
++	pr_debug("\n");
++}
++
++/**
++ * dgrp_read_data_block() -- Read a data block
++ * @ch: struct ch_struct *
++ * @flipbuf: u8 *
++ * @flipbuf_size: size of flipbuf
++ */
++static void dgrp_read_data_block(struct ch_struct *ch, u8 *flipbuf,
++				 int flipbuf_size)
++{
++	int t;
++	int n;
++
++	if (flipbuf_size <= 0)
++		return;
++
++	t = RBUF_MAX - ch->ch_rout;
++	n = flipbuf_size;
++
++	if (n >= t) {
++		memcpy(flipbuf, ch->ch_rbuf + ch->ch_rout, t);
++		flipbuf += t;
++		n -= t;
++		ch->ch_rout = 0;
++	}
++
++	memcpy(flipbuf, ch->ch_rbuf + ch->ch_rout, n);
++	flipbuf += n;
++	ch->ch_rout += n;
++}
++
++
++/**
++ * dgrp_input() -- send data to the line disipline
++ * @ch: pointer to channel struct
++ *
++ * Copys the rbuf to the flipbuf and sends to line discipline.
++ * Sends input buffer data to the line discipline.
++ *
++ * There are several modes to consider here:
++ *    rawreadok, tty->real_raw, and IF_PARMRK
++ */
++static void dgrp_input(struct ch_struct *ch)
++{
++	struct nd_struct *nd;
++	struct tty_struct *tty;
++	int remain;
++	int data_len;
++	int len;
++	int flip_len;
++	int tty_count;
++	ulong lock_flags;
++	struct tty_ldisc *ld;
++	u8  *myflipbuf;
++	u8  *myflipflagbuf;
++
++	if (!ch)
++		return;
++
++	nd = ch->ch_nd;
++
++	if (!nd)
++		return;
++
++	spin_lock_irqsave(&nd->nd_lock, lock_flags);
++
++	myflipbuf = nd->nd_inputbuf;
++	myflipflagbuf = nd->nd_inputflagbuf;
++
++	if (!ch->ch_open_count) {
++		ch->ch_rout = ch->ch_rin;
++		goto out;
++	}
++
++	if (ch->ch_tun.un_flag & UN_CLOSING) {
++		ch->ch_rout = ch->ch_rin;
++		goto out;
++	}
++
++	tty = (ch->ch_tun).un_tty;
++
++
++	if (!tty || tty->magic != TTY_MAGIC) {
++		ch->ch_rout = ch->ch_rin;
++		goto out;
++	}
++
++	tty_count = tty->count;
++	if (!tty_count) {
++		ch->ch_rout = ch->ch_rin;
++		goto out;
++	}
++
++	if (tty->closing || test_bit(TTY_CLOSING, &tty->flags)) {
++		ch->ch_rout = ch->ch_rin;
++		goto out;
++	}
++
++	spin_unlock_irqrestore(&nd->nd_lock, lock_flags);
++
++	/* Decide how much data we can send into the tty layer */
++	if (dgrp_rawreadok && tty->real_raw)
++		flip_len = MYFLIPLEN;
++	else
++		flip_len = TTY_FLIPBUF_SIZE;
++
++	/* data_len should be the number of chars that we read in */
++	data_len = (ch->ch_rin - ch->ch_rout) & RBUF_MASK;
++	remain = data_len;
++
++	/* len is the amount of data we are going to transfer here */
++	len = min(data_len, flip_len);
++
++	/* take into consideration length of ldisc */
++	len = min(len, (N_TTY_BUF_SIZE - 1) - tty->read_cnt);
++
++	ld = tty_ldisc_ref(tty);
++
++	/*
++	 * If we were unable to get a reference to the ld,
++	 * don't flush our buffer, and act like the ld doesn't
++	 * have any space to put the data right now.
++	 */
++	if (!ld) {
++		len = 0;
++	} else if (!ld->ops->receive_buf) {
++		spin_lock_irqsave(&nd->nd_lock, lock_flags);
++		ch->ch_rout = ch->ch_rin;
++		spin_unlock_irqrestore(&nd->nd_lock, lock_flags);
++		len = 0;
++	}
++
++	/* Check DPA flow control */
++	if ((nd->nd_dpa_debug) &&
++	    (nd->nd_dpa_flag & DPA_WAIT_SPACE) &&
++	    (nd->nd_dpa_port == MINOR(tty_devnum(ch->ch_tun.un_tty))))
++		len = 0;
++
++	if ((len) && !(ch->ch_flag & CH_RXSTOP)) {
++
++		dgrp_read_data_block(ch, myflipbuf, len);
++
++		/*
++		 * In high performance mode, we don't have to update
++		 * flag_buf or any of the counts or pointers into flip buf.
++		 */
++		if (!dgrp_rawreadok || !tty->real_raw) {
++			if (I_PARMRK(tty) || I_BRKINT(tty) || I_INPCK(tty))
++				parity_scan(ch, myflipbuf, myflipflagbuf, &len);
++			else
++				memset(myflipflagbuf, TTY_NORMAL, len);
++		}
++
++		if ((nd->nd_dpa_debug) &&
++		    (nd->nd_dpa_port == PORT_NUM(MINOR(tty_devnum(tty)))))
++			dgrp_dpa_data(nd, 1, myflipbuf, len);
++
++		/*
++		 * If we're doing raw reads, jam it right into the
++		 * line disc bypassing the flip buffers.
++		 */
++		if (dgrp_rawreadok && tty->real_raw)
++			ld->ops->receive_buf(tty, myflipbuf, NULL, len);
++		else {
++			len = tty_buffer_request_room(tty, len);
++			tty_insert_flip_string_flags(tty, myflipbuf,
++						     myflipflagbuf, len);
++
++			/* Tell the tty layer its okay to "eat" the data now */
++			tty_flip_buffer_push(tty);
++		}
++
++		ch->ch_rxcount += len;
++	}
++
++	if (ld)
++		tty_ldisc_deref(ld);
++
++	/*
++	 * Wake up any sleepers (maybe dgrp close) that might be waiting
++	 * for a channel flag state change.
++	 */
++	wake_up_interruptible(&ch->ch_flag_wait);
++	return;
++
++out:
++	spin_unlock_irqrestore(&nd->nd_lock, lock_flags);
++}
++
++
++/*
++ *  parity_scan
++ *
++ *  Loop to inspect each single character or 0xFF escape.
++ *
++ *  if PARMRK & ~DOSMODE:
++ *     0xFF  0xFF           Normal 0xFF character, escaped
++ *                          to eliminate confusion.
++ *     0xFF  0x00  0x00     Break
++ *     0xFF  0x00  CC       Error character CC.
++ *     CC                   Normal character CC.
++ *
++ *  if PARMRK & DOSMODE:
++ *     0xFF  0x18  0x00     Break
++ *     0xFF  0x08  0x00     Framing Error
++ *     0xFF  0x04  0x00     Parity error
++ *     0xFF  0x0C  0x00     Both Framing and Parity error
++ *
++ *  TODO:  do we need to do the XMODEM, XOFF, XON, XANY processing??
++ *         as per protocol
++ */
++static void parity_scan(struct ch_struct *ch, unsigned char *cbuf,
++			unsigned char *fbuf, int *len)
++{
++	int l = *len;
++	int count = 0;
++	int DOS = ((ch->ch_iflag & IF_DOSMODE) == 0 ? 0 : 1);
++	unsigned char *cout; /* character buffer */
++	unsigned char *fout; /* flag buffer */
++	unsigned char *in;
++	unsigned char c;
++
++	in = cbuf;
++	cout = cbuf;
++	fout = fbuf;
++
++	while (l--) {
++		c = *in;
++		in++;
++
++		switch (ch->ch_pscan_state) {
++		default:
++			/* reset to sanity and fall through */
++			ch->ch_pscan_state = 0 ;
++
++		case 0:
++			/* No FF seen yet */
++			if (c == 0xff) /* delete this character from stream */
++				ch->ch_pscan_state = 1;
++			else {
++				*cout++ = c;
++				*fout++ = TTY_NORMAL;
++				count += 1;
++			}
++			break;
++
++		case 1:
++			/* first FF seen */
++			if (c == 0xff) {
++				/* doubled ff, transform to single ff */
++				*cout++ = c;
++				*fout++ = TTY_NORMAL;
++				count += 1;
++				ch->ch_pscan_state = 0;
++			} else {
++				/* save value examination in next state */
++				ch->ch_pscan_savechar = c;
++				ch->ch_pscan_state = 2;
++			}
++			break;
++
++		case 2:
++			/* third character of ff sequence */
++			*cout++ = c;
++			if (DOS) {
++				if (ch->ch_pscan_savechar & 0x10)
++					*fout++ = TTY_BREAK;
++				else if (ch->ch_pscan_savechar & 0x08)
++					*fout++ = TTY_FRAME;
++				else
++					/*
++					 * either marked as a parity error,
++					 * indeterminate, or not in DOSMODE
++					 * call it a parity error
++					 */
++					*fout++ = TTY_PARITY;
++			} else {
++				/* case FF XX ?? where XX is not 00 */
++				if (ch->ch_pscan_savechar & 0xff) {
++					/* this should not happen */
++					pr_info("%s: parity_scan: error unexpected byte\n",
++						__func__);
++					*fout++ = TTY_PARITY;
++				}
++				/* case FF 00 XX where XX is not 00 */
++				else if (c == 0xff)
++					*fout++ = TTY_PARITY;
++				/* case FF 00 00 */
++				else
++					*fout++ = TTY_BREAK;
++
++			}
++			count += 1;
++			ch->ch_pscan_state = 0;
++		}
++	}
++	*len = count;
++}
++
++
++/**
++ * dgrp_net_idle() -- Idle the network connection
++ * @nd: pointer to node structure to idle
++ */
++static void dgrp_net_idle(struct nd_struct *nd)
++{
++	struct ch_struct *ch;
++	int i;
++
++	nd->nd_tx_work = 1;
++
++	nd->nd_state = NS_IDLE;
++	nd->nd_flag = 0;
++
++	for (i = nd->nd_seq_out; ; i = (i + 1) & SEQ_MASK) {
++		if (!nd->nd_seq_wait[i]) {
++			nd->nd_seq_wait[i] = 0;
++			wake_up_interruptible(&nd->nd_seq_wque[i]);
++		}
++
++		if (i == nd->nd_seq_in)
++			break;
++	}
++
++	nd->nd_seq_out = nd->nd_seq_in;
++
++	nd->nd_unack = 0;
++	nd->nd_remain = 0;
++
++	nd->nd_tx_module = 0x10;
++	nd->nd_rx_module = 0x00;
++
++	for (i = 0, ch = nd->nd_chan; i < CHAN_MAX; i++, ch++) {
++		ch->ch_state = CS_IDLE;
++
++		ch->ch_otype = 0;
++		ch->ch_otype_waiting = 0;
++	}
++}
++
++/*
++ *  Increase the number of channels, waking up any
++ *  threads that might be waiting for the channels
++ *  to appear.
++ */
++static void increase_channel_count(struct nd_struct *nd, int n)
++{
++	struct ch_struct *ch;
++	struct device *classp;
++	char name[DEVICE_NAME_SIZE];
++	int ret;
++	u8 *buf;
++	int i;
++
++	for (i = nd->nd_chan_count; i < n; ++i) {
++		ch = nd->nd_chan + i;
++
++		/* FIXME: return a useful error instead! */
++		buf = kmalloc(TBUF_MAX, GFP_KERNEL);
++		if (!buf)
++			return;
++
++		if (ch->ch_tbuf)
++			pr_info_ratelimited("%s - ch_tbuf was not NULL\n",
++					    __func__);
++
++		ch->ch_tbuf = buf;
++
++		buf = kmalloc(RBUF_MAX, GFP_KERNEL);
++		if (!buf)
++			return;
++
++		if (ch->ch_rbuf)
++			pr_info("%s - ch_rbuf was not NULL\n",
++				__func__);
++		ch->ch_rbuf = buf;
++
++		classp = tty_port_register_device(&ch->port,
++						  nd->nd_serial_ttdriver, i,
++						  NULL);
++
++		ch->ch_tun.un_sysfs = classp;
++		snprintf(name, DEVICE_NAME_SIZE, "tty_%d", i);
++
++		dgrp_create_tty_sysfs(&ch->ch_tun, classp);
++		ret = sysfs_create_link(&nd->nd_class_dev->kobj,
++					&classp->kobj, name);
++
++		/* NOTE: We don't support "cu" devices anymore,
++		 * so you will notice we don't register them
++		 * here anymore. */
++		if (dgrp_register_prdevices) {
++			classp = tty_register_device(nd->nd_xprint_ttdriver,
++						     i, NULL);
++			ch->ch_pun.un_sysfs = classp;
++			snprintf(name, DEVICE_NAME_SIZE, "pr_%d", i);
++
++			dgrp_create_tty_sysfs(&ch->ch_pun, classp);
++			ret = sysfs_create_link(&nd->nd_class_dev->kobj,
++						&classp->kobj, name);
++		}
++
++		nd->nd_chan_count = i + 1;
++		wake_up_interruptible(&ch->ch_flag_wait);
++	}
++}
++
++/*
++ * Decrease the number of channels, and wake up any threads that might
++ * be waiting on the channels that vanished.
++ */
++static void decrease_channel_count(struct nd_struct *nd, int n)
++{
++	struct ch_struct *ch;
++	char name[DEVICE_NAME_SIZE];
++	int i;
++
++	for (i = nd->nd_chan_count - 1; i >= n; --i) {
++		ch = nd->nd_chan + i;
++
++		/*
++		 *  Make any open ports inoperative.
++		 */
++		ch->ch_state = CS_IDLE;
++
++		ch->ch_otype = 0;
++		ch->ch_otype_waiting = 0;
++
++		/*
++		 *  Only "HANGUP" if we care about carrier
++		 *  transitions and we are already open.
++		 */
++		if (ch->ch_open_count != 0) {
++			ch->ch_flag |= CH_HANGUP;
++			dgrp_carrier(ch);
++		}
++
++		/*
++		 * Unlike the CH_HANGUP flag above, use another
++		 * flag to indicate to the RealPort state machine
++		 * that this port has disappeared.
++		 */
++		if (ch->ch_open_count != 0)
++			ch->ch_flag |= CH_PORT_GONE;
++
++		wake_up_interruptible(&ch->ch_flag_wait);
++
++		nd->nd_chan_count = i;
++
++		kfree(ch->ch_tbuf);
++		ch->ch_tbuf = NULL;
++
++		kfree(ch->ch_rbuf);
++		ch->ch_rbuf = NULL;
++
++		nd->nd_chan_count = i;
++
++		dgrp_remove_tty_sysfs(ch->ch_tun.un_sysfs);
++		snprintf(name, DEVICE_NAME_SIZE, "tty_%d", i);
++		sysfs_remove_link(&nd->nd_class_dev->kobj, name);
++		tty_unregister_device(nd->nd_serial_ttdriver, i);
++
++		/*
++		 * NOTE: We don't support "cu" devices anymore, so don't
++		 * unregister them here anymore.
++		 */
++
++		if (dgrp_register_prdevices) {
++			dgrp_remove_tty_sysfs(ch->ch_pun.un_sysfs);
++			snprintf(name, DEVICE_NAME_SIZE, "pr_%d", i);
++			sysfs_remove_link(&nd->nd_class_dev->kobj, name);
++			tty_unregister_device(nd->nd_xprint_ttdriver, i);
++		}
++	}
++}
++
++/**
++ * dgrp_chan_count() -- Adjust the node channel count.
++ * @nd: pointer to a node structure
++ * @n: new value for channel count
++ *
++ * Adjusts the node channel count.  If new ports have appeared, it tries
++ * to signal those processes that might have been waiting for ports to
++ * appear.  If ports have disappeared it tries to signal those processes
++ * that might be hung waiting for a response for the now non-existant port.
++ */
++static void dgrp_chan_count(struct nd_struct *nd, int n)
++{
++	if (n == nd->nd_chan_count)
++		return;
++
++	if (n > nd->nd_chan_count)
++		increase_channel_count(nd, n);
++
++	if (n < nd->nd_chan_count)
++		decrease_channel_count(nd, n);
++}
++
++/**
++ * dgrp_monitor() -- send data to the device monitor queue
++ * @nd: pointer to a node structure
++ * @buf: data to copy to the monitoring buffer
++ * @len: number of bytes to transfer to the buffer
++ *
++ * Called by the net device routines to send data to the device
++ * monitor queue.  If the device monitor buffer is too full to
++ * accept the data, it waits until the buffer is ready.
++ */
++static void dgrp_monitor(struct nd_struct *nd, u8 *buf, int len)
++{
++	int n;
++	int r;
++	int rtn;
++
++	/*
++	 *  Grab monitor lock.
++	 */
++	down(&nd->nd_mon_semaphore);
++
++	/*
++	 *  Loop while data remains.
++	 */
++	while ((len > 0) && (nd->nd_mon_buf)) {
++		/*
++		 *  Determine the amount of available space left in the
++		 *  buffer.  If there's none, wait until some appears.
++		 */
++
++		n = (nd->nd_mon_out - nd->nd_mon_in - 1) & MON_MASK;
++
++		if (!n) {
++			nd->nd_mon_flag |= MON_WAIT_SPACE;
++
++			up(&nd->nd_mon_semaphore);
++
++			/*
++			 * Go to sleep waiting until the condition becomes true.
++			 */
++			rtn = wait_event_interruptible(nd->nd_mon_wqueue,
++						       ((nd->nd_mon_flag & MON_WAIT_SPACE) == 0));
++
++/* FIXME: really ignore rtn? */
++
++			/*
++			 *  We can't exit here if we receive a signal, since
++			 *  to do so would trash the debug stream.
++			 */
++
++			down(&nd->nd_mon_semaphore);
++
++			continue;
++		}
++
++		/*
++		 * Copy as much data as will fit.
++		 */
++
++		if (n > len)
++			n = len;
++
++		r = MON_MAX - nd->nd_mon_in;
++
++		if (r <= n) {
++			memcpy(nd->nd_mon_buf + nd->nd_mon_in, buf, r);
++
++			n -= r;
++
++			nd->nd_mon_in = 0;
++
++			buf += r;
++			len -= r;
++		}
++
++		memcpy(nd->nd_mon_buf + nd->nd_mon_in, buf, n);
++
++		nd->nd_mon_in += n;
++
++		buf += n;
++		len -= n;
++
++		if (nd->nd_mon_in >= MON_MAX)
++			pr_info_ratelimited("%s - nd_mon_in (%i) >= MON_MAX\n",
++					    __func__, nd->nd_mon_in);
++
++		/*
++		 *  Wakeup any thread waiting for data
++		 */
++
++		if (nd->nd_mon_flag & MON_WAIT_DATA) {
++			nd->nd_mon_flag &= ~MON_WAIT_DATA;
++			wake_up_interruptible(&nd->nd_mon_wqueue);
++		}
++	}
++
++	/*
++	 *  Release the monitor lock.
++	 */
++	up(&nd->nd_mon_semaphore);
++}
++
++/**
++ * dgrp_encode_time() -- Encodes rpdump time into a 4-byte quantity.
++ * @nd: pointer to a node structure
++ * @buf: destination buffer
++ *
++ * Encodes "rpdump" time into a 4-byte quantity.  Time is measured since
++ * open.
++ */
++static void dgrp_encode_time(struct nd_struct *nd, u8 *buf)
++{
++	ulong t;
++
++	/*
++	 *  Convert time in HZ since open to time in milliseconds
++	 *  since open.
++	 */
++	t = jiffies - nd->nd_mon_lbolt;
++	t = 1000 * (t / HZ) + 1000 * (t % HZ) / HZ;
++
++	put_unaligned_be32((uint)(t & 0xffffffff), buf);
++}
++
++
++
++/**
++ * dgrp_monitor_message() -- Builds a rpdump style message.
++ * @nd: pointer to a node structure
++ * @message: destination buffer
++ */
++static void dgrp_monitor_message(struct nd_struct *nd, char *message)
++{
++	u8 header[7];
++	int n;
++
++	header[0] = RPDUMP_MESSAGE;
++
++	dgrp_encode_time(nd, header + 1);
++
++	n = strlen(message);
++
++	put_unaligned_be16(n, header + 5);
++
++	dgrp_monitor(nd, header, sizeof(header));
++	dgrp_monitor(nd, (u8 *) message, n);
++}
++
++
++
++/**
++ * dgrp_monitor_reset() -- Note a reset in the monitoring buffer.
++ * @nd: pointer to a node structure
++ */
++static void dgrp_monitor_reset(struct nd_struct *nd)
++{
++	u8 header[5];
++
++	header[0] = RPDUMP_RESET;
++
++	dgrp_encode_time(nd, header + 1);
++
++	dgrp_monitor(nd, header, sizeof(header));
++}
++
++/**
++ * dgrp_monitor_data() -- builds a monitor data packet
++ * @nd: pointer to a node structure
++ * @type: type of message to be logged
++ * @buf: data to be logged
++ * @size: number of bytes in the buffer
++ */
++static void dgrp_monitor_data(struct nd_struct *nd, u8 type, u8 *buf, int size)
++{
++	u8 header[7];
++
++	header[0] = type;
++
++	dgrp_encode_time(nd, header + 1);
++
++	put_unaligned_be16(size, header + 5);
++
++	dgrp_monitor(nd, header, sizeof(header));
++	dgrp_monitor(nd, buf, size);
++}
++
++static int alloc_nd_buffers(struct nd_struct *nd)
++{
++
++	nd->nd_iobuf = NULL;
++	nd->nd_writebuf = NULL;
++	nd->nd_inputbuf = NULL;
++	nd->nd_inputflagbuf = NULL;
++
++	/*
++	 *  Allocate the network read/write buffer.
++	 */
++	nd->nd_iobuf = kzalloc(UIO_MAX + 10, GFP_KERNEL);
++	if (!nd->nd_iobuf)
++		goto out_err;
++
++	/*
++	 * Allocate a buffer for doing the copy from user space to
++	 * kernel space in the write routines.
++	 */
++	nd->nd_writebuf = kzalloc(WRITEBUFLEN, GFP_KERNEL);
++	if (!nd->nd_writebuf)
++		goto out_err;
++
++	/*
++	 * Allocate a buffer for doing the copy from kernel space to
++	 * tty buffer space in the read routines.
++	 */
++	nd->nd_inputbuf = kzalloc(MYFLIPLEN, GFP_KERNEL);
++	if (!nd->nd_inputbuf)
++		goto out_err;
++
++	/*
++	 * Allocate a buffer for doing the copy from kernel space to
++	 * tty buffer space in the read routines.
++	 */
++	nd->nd_inputflagbuf = kzalloc(MYFLIPLEN, GFP_KERNEL);
++	if (!nd->nd_inputflagbuf)
++		goto out_err;
++
++	return 0;
++
++out_err:
++	kfree(nd->nd_iobuf);
++	kfree(nd->nd_writebuf);
++	kfree(nd->nd_inputbuf);
++	kfree(nd->nd_inputflagbuf);
++	return -ENOMEM;
++}
++
++/*
++ * dgrp_net_open() -- Open the NET device for a particular PortServer
++ */
++static int dgrp_net_open(struct inode *inode, struct file *file)
++{
++	struct nd_struct *nd;
++	struct proc_dir_entry *de;
++	ulong  lock_flags;
++	int rtn;
++
++	rtn = try_module_get(THIS_MODULE);
++	if (!rtn)
++		return -EAGAIN;
++
++	if (!capable(CAP_SYS_ADMIN)) {
++		rtn = -EPERM;
++		goto done;
++	}
++
++	/*
++	 *  Make sure that the "private_data" field hasn't already been used.
++	 */
++	if (file->private_data) {
++		rtn = -EINVAL;
++		goto done;
++	}
++
++	/*
++	 *  Get the node pointer, and fail if it doesn't exist.
++	 */
++	de = PDE(inode);
++	if (!de) {
++		rtn = -ENXIO;
++		goto done;
++	}
++
++	nd = (struct nd_struct *) de->data;
++	if (!nd) {
++		rtn = -ENXIO;
++		goto done;
++	}
++
++	file->private_data = (void *) nd;
++
++	/*
++	 *  Grab the NET lock.
++	 */
++	down(&nd->nd_net_semaphore);
++
++	if (nd->nd_state != NS_CLOSED) {
++		rtn = -EBUSY;
++		goto unlock;
++	}
++
++	/*
++	 *  Initialize the link speed parameters.
++	 */
++
++	nd->nd_link.lk_fast_rate = UIO_MAX;
++	nd->nd_link.lk_slow_rate = UIO_MAX;
++
++	nd->nd_link.lk_fast_delay = 1000;
++	nd->nd_link.lk_slow_delay = 1000;
++
++	nd->nd_link.lk_header_size = 46;
++
++
++	rtn = alloc_nd_buffers(nd);
++	if (rtn)
++		goto unlock;
++
++	/*
++	 *  The port is now open, so move it to the IDLE state
++	 */
++	dgrp_net_idle(nd);
++
++	nd->nd_tx_time = jiffies;
++
++	/*
++	 *  If the polling routing is not running, start it running here
++	 */
++	spin_lock_irqsave(&dgrp_poll_data.poll_lock, lock_flags);
++
++	if (!dgrp_poll_data.node_active_count) {
++		dgrp_poll_data.node_active_count = 2;
++		dgrp_poll_data.timer.expires = jiffies +
++			dgrp_poll_tick * HZ / 1000;
++		add_timer(&dgrp_poll_data.timer);
++	}
++
++	spin_unlock_irqrestore(&dgrp_poll_data.poll_lock, lock_flags);
++
++	dgrp_monitor_message(nd, "Net Open");
++
++unlock:
++	/*
++	 *  Release the NET lock.
++	 */
++	up(&nd->nd_net_semaphore);
++
++done:
++	if (rtn)
++		module_put(THIS_MODULE);
++
++	return rtn;
++}
++
++/* dgrp_net_release() -- close the NET device for a particular PortServer */
++static int dgrp_net_release(struct inode *inode, struct file *file)
++{
++	struct nd_struct *nd;
++	ulong  lock_flags;
++
++	nd = (struct nd_struct *)(file->private_data);
++	if (!nd)
++		goto done;
++
++/* TODO : historical locking placeholder */
++/*
++ *  In the HPUX version of the RealPort driver (which served as a basis
++ *  for this driver) this locking code was used.  Saved if ever we need
++ *  to review the locking under Linux.
++ */
++/*	spinlock(&nd->nd_lock); */
++
++
++	/*
++	 *  Grab the NET lock.
++	 */
++	down(&nd->nd_net_semaphore);
++
++	/*
++	 *  Before "closing" the internal connection, make sure all
++	 *  ports are "idle".
++	 */
++	dgrp_net_idle(nd);
++
++	nd->nd_state = NS_CLOSED;
++	nd->nd_flag = 0;
++
++	/*
++	 *  TODO ... must the wait queue be reset on close?
++	 *  should any pending waiters be reset?
++	 *  Let's decide to assert that the waitq is empty... and see
++	 *  how soon we break.
++	 */
++	if (waitqueue_active(&nd->nd_tx_waitq))
++		pr_info("%s - expected waitqueue_active to be false\n",
++			__func__);
++
++	nd->nd_send = 0;
++
++	kfree(nd->nd_iobuf);
++	nd->nd_iobuf = NULL;
++
++/* TODO : historical locking placeholder */
++/*
++ *  In the HPUX version of the RealPort driver (which served as a basis
++ *  for this driver) this locking code was used.  Saved if ever we need
++ *  to review the locking under Linux.
++ */
++/*	spinunlock( &nd->nd_lock ); */
++
++
++	kfree(nd->nd_writebuf);
++	nd->nd_writebuf = NULL;
++
++	kfree(nd->nd_inputbuf);
++	nd->nd_inputbuf = NULL;
++
++	kfree(nd->nd_inputflagbuf);
++	nd->nd_inputflagbuf = NULL;
++
++/* TODO : historical locking placeholder */
++/*
++ *  In the HPUX version of the RealPort driver (which served as a basis
++ *  for this driver) this locking code was used.  Saved if ever we need
++ *  to review the locking under Linux.
++ */
++/*	spinlock(&nd->nd_lock); */
++
++	/*
++	 *  Set the active port count to zero.
++	 */
++	dgrp_chan_count(nd, 0);
++
++/* TODO : historical locking placeholder */
++/*
++ *  In the HPUX version of the RealPort driver (which served as a basis
++ *  for this driver) this locking code was used.  Saved if ever we need
++ *  to review the locking under Linux.
++ */
++/*	spinunlock(&nd->nd_lock); */
++
++	/*
++	 *  Release the NET lock.
++	 */
++	up(&nd->nd_net_semaphore);
++
++	/*
++	 *  Cause the poller to stop scheduling itself if this is
++	 *  the last active node.
++	 */
++	spin_lock_irqsave(&dgrp_poll_data.poll_lock, lock_flags);
++
++	if (dgrp_poll_data.node_active_count == 2) {
++		del_timer(&dgrp_poll_data.timer);
++		dgrp_poll_data.node_active_count = 0;
++	}
++
++	spin_unlock_irqrestore(&dgrp_poll_data.poll_lock, lock_flags);
++
++done:
++	down(&nd->nd_net_semaphore);
++
++	dgrp_monitor_message(nd, "Net Close");
++
++	up(&nd->nd_net_semaphore);
++
++	module_put(THIS_MODULE);
++	file->private_data = NULL;
++	return 0;
++}
++
++/* used in dgrp_send to setup command header */
++static inline u8 *set_cmd_header(u8 *b, u8 port, u8 cmd)
++{
++	*b++ = 0xb0 + (port & 0x0f);
++	*b++ = cmd;
++	return b;
++}
++
++/**
++ * dgrp_send() -- build a packet for transmission to the server
++ * @nd: pointer to a node structure
++ * @tmax: maximum bytes to transmit
++ *
++ * returns number of bytes sent
++ */
++static int dgrp_send(struct nd_struct *nd, long tmax)
++{
++	struct ch_struct *ch = nd->nd_chan;
++	u8 *b;
++	u8 *buf;
++	u8 *mbuf;
++	u8 port;
++	int mod;
++	long send;
++	int maxport;
++	long lastport = -1;
++	ushort rwin;
++	long in;
++	ushort n;
++	long t;
++	long ttotal;
++	long tchan;
++	long tsend;
++	ushort tsafe;
++	long work;
++	long send_sync;
++	long wanted_sync_port = -1;
++	ushort tdata[CHAN_MAX];
++	long used_buffer;
++
++	mbuf = nd->nd_iobuf + UIO_BASE;
++	buf = b = mbuf;
++
++	send_sync = nd->nd_link.lk_slow_rate < UIO_MAX;
++
++	ttotal = 0;
++	tchan = 0;
++
++	memset(tdata, 0, sizeof(tdata));
++
++
++	/*
++	 * If there are any outstanding requests to be serviced,
++	 * service them here.
++	 */
++	if (nd->nd_send & NR_PASSWORD) {
++
++		/*
++		 *  Send Password response.
++		 */
++
++		b[0] = 0xfc;
++		b[1] = 0x20;
++		put_unaligned_be16(strlen(nd->password), b + 2);
++		b += 4;
++		b += strlen(nd->password);
++		nd->nd_send &= ~(NR_PASSWORD);
++	}
++
++
++	/*
++	 *  Loop over all modules to generate commands, and determine
++	 *  the amount of data queued for transmit.
++	 */
++
++	for (mod = 0, port = 0; port < nd->nd_chan_count; mod++) {
++		/*
++		 *  If this is not the current module, enter a module select
++		 *  code in the buffer.
++		 */
++
++		if (mod != nd->nd_tx_module)
++			mbuf = ++b;
++
++		/*
++		 *  Loop to process one module.
++		 */
++
++		maxport = port + 16;
++
++		if (maxport > nd->nd_chan_count)
++			maxport = nd->nd_chan_count;
++
++		for (; port < maxport; port++, ch++) {
++			/*
++			 *  Switch based on channel state.
++			 */
++
++			switch (ch->ch_state) {
++			/*
++			 *  Send requests when the port is closed, and there
++			 *  are no Open, Close or Cancel requests expected.
++			 */
++
++			case CS_IDLE:
++				/*
++				 * Wait until any open error code
++				 * has been delivered to all
++				 * associated ports.
++				 */
++
++				if (ch->ch_open_error) {
++					if (ch->ch_wait_count[ch->ch_otype]) {
++						work = 1;
++						break;
++					}
++
++					ch->ch_open_error = 0;
++				}
++
++				/*
++				 *  Wait until the channel HANGUP flag is reset
++				 *  before sending the first open.  We can only
++				 *  get to this state after a server disconnect.
++				 */
++
++				if ((ch->ch_flag & CH_HANGUP) != 0)
++					break;
++
++				/*
++				 *  If recovering from a TCP disconnect, or if
++				 *  there is an immediate open pending, send an
++				 *  Immediate Open request.
++				 */
++				if ((ch->ch_flag & CH_PORT_GONE) ||
++				    ch->ch_wait_count[OTYPE_IMMEDIATE] != 0) {
++					b = set_cmd_header(b, port, 10);
++					*b++ = 0;
++
++					ch->ch_state = CS_WAIT_OPEN;
++					ch->ch_otype = OTYPE_IMMEDIATE;
++					break;
++				}
++
++	/*
++	 *  If there is no Persistent or Incoming Open on the wait
++	 *  list in the server, and a thread is waiting for a
++	 *  Persistent or Incoming Open, send a Persistent or Incoming
++	 *  Open Request.
++	 */
++				if (ch->ch_otype_waiting == 0) {
++					if (ch->ch_wait_count[OTYPE_PERSISTENT] != 0) {
++						b = set_cmd_header(b, port, 10);
++						*b++ = 1;
++
++						ch->ch_state = CS_WAIT_OPEN;
++						ch->ch_otype = OTYPE_PERSISTENT;
++					} else if (ch->ch_wait_count[OTYPE_INCOMING] != 0) {
++						b = set_cmd_header(b, port, 10);
++						*b++ = 2;
++
++						ch->ch_state = CS_WAIT_OPEN;
++						ch->ch_otype = OTYPE_INCOMING;
++					}
++					break;
++				}
++
++				/*
++				 *  If a Persistent or Incoming Open is pending in
++				 *  the server, but there is no longer an open
++				 *  thread waiting for it, cancel the request.
++				 */
++
++				if (ch->ch_wait_count[ch->ch_otype_waiting] == 0) {
++					b = set_cmd_header(b, port, 10);
++					*b++ = 4;
++
++					ch->ch_state = CS_WAIT_CANCEL;
++					ch->ch_otype = ch->ch_otype_waiting;
++				}
++				break;
++
++				/*
++				 *  Send port parameter queries.
++				 */
++			case CS_SEND_QUERY:
++				/*
++				 *  Clear out all FEP state that might remain
++				 *  from the last connection.
++				 */
++
++				ch->ch_flag |= CH_PARAM;
++
++				ch->ch_flag &= ~CH_RX_FLUSH;
++
++				ch->ch_expect = 0;
++
++				ch->ch_s_tin   = 0;
++				ch->ch_s_tpos  = 0;
++				ch->ch_s_tsize = 0;
++				ch->ch_s_treq  = 0;
++				ch->ch_s_elast = 0;
++
++				ch->ch_s_rin   = 0;
++				ch->ch_s_rwin  = 0;
++				ch->ch_s_rsize = 0;
++
++				ch->ch_s_tmax  = 0;
++				ch->ch_s_ttime = 0;
++				ch->ch_s_rmax  = 0;
++				ch->ch_s_rtime = 0;
++				ch->ch_s_rlow  = 0;
++				ch->ch_s_rhigh = 0;
++
++				ch->ch_s_brate = 0;
++				ch->ch_s_iflag = 0;
++				ch->ch_s_cflag = 0;
++				ch->ch_s_oflag = 0;
++				ch->ch_s_xflag = 0;
++
++				ch->ch_s_mout  = 0;
++				ch->ch_s_mflow = 0;
++				ch->ch_s_mctrl = 0;
++				ch->ch_s_xon   = 0;
++				ch->ch_s_xoff  = 0;
++				ch->ch_s_lnext = 0;
++				ch->ch_s_xxon  = 0;
++				ch->ch_s_xxoff = 0;
++
++				/* Send Sequence Request */
++				b = set_cmd_header(b, port, 14);
++
++				/* Configure Event Conditions Packet */
++				b = set_cmd_header(b, port, 42);
++				put_unaligned_be16(0x02c0, b);
++				b += 2;
++				*b++ = (DM_DTR | DM_RTS | DM_CTS |
++					DM_DSR | DM_RI | DM_CD);
++
++				/* Send Status Request */
++				b = set_cmd_header(b, port, 16);
++
++				/* Send Buffer Request  */
++				b = set_cmd_header(b, port, 20);
++
++				/* Send Port Capability Request */
++				b = set_cmd_header(b, port, 22);
++
++				ch->ch_expect = (RR_SEQUENCE |
++						 RR_STATUS  |
++						 RR_BUFFER |
++						 RR_CAPABILITY);
++
++				ch->ch_state = CS_WAIT_QUERY;
++
++				/* Raise modem signals */
++				b = set_cmd_header(b, port, 44);
++
++				if (ch->ch_flag & CH_PORT_GONE)
++					ch->ch_s_mout = ch->ch_mout;
++				else
++					ch->ch_s_mout = ch->ch_mout = DM_DTR | DM_RTS;
++
++				*b++ = ch->ch_mout;
++				*b++ = ch->ch_s_mflow = 0;
++				*b++ = ch->ch_s_mctrl = ch->ch_mctrl = 0;
++
++				if (ch->ch_flag & CH_PORT_GONE)
++					ch->ch_flag &= ~CH_PORT_GONE;
++
++				break;
++
++			/*
++			 *  Handle normal open and ready mode.
++			 */
++
++			case CS_READY:
++
++				/*
++				 *  If the port is not open, and there are no
++				 *  no longer any ports requesting an open,
++				 *  then close the port.
++				 */
++
++				if (ch->ch_open_count == 0 &&
++				    ch->ch_wait_count[ch->ch_otype] == 0) {
++					goto send_close;
++				}
++
++	/*
++	 *  Process waiting input.
++	 *
++	 *  If there is no one to read it, discard the data.
++	 *
++	 *  Otherwise if we are not in fastcook mode, or if there is a
++	 *  fastcook thread waiting for data, send the data to the
++	 *  line discipline.
++	 */
++				if (ch->ch_rin != ch->ch_rout) {
++					if (ch->ch_tun.un_open_count == 0 ||
++					     (ch->ch_tun.un_flag & UN_CLOSING) ||
++					    (ch->ch_cflag & CF_CREAD) == 0) {
++						ch->ch_rout = ch->ch_rin;
++					} else if ((ch->ch_flag & CH_FAST_READ) == 0 ||
++							ch->ch_inwait != 0) {
++						dgrp_input(ch);
++
++						if (ch->ch_rin != ch->ch_rout)
++							work = 1;
++					}
++				}
++
++				/*
++				 *  Handle receive flush, and changes to
++				 *  server port parameters.
++				 */
++
++				if (ch->ch_flag & (CH_RX_FLUSH | CH_PARAM)) {
++				/*
++				 *  If we are in receive flush mode,
++				 *  and enough data has gone by, reset
++				 *  receive flush mode.
++				 */
++					if (ch->ch_flag & CH_RX_FLUSH) {
++						if (((ch->ch_flush_seq - nd->nd_seq_out) & SEQ_MASK) >
++						    ((nd->nd_seq_in - nd->nd_seq_out) & SEQ_MASK))
++							ch->ch_flag &= ~CH_RX_FLUSH;
++						else
++							work = 1;
++					}
++
++					/*
++					 *  Send TMAX, TTIME.
++					 */
++
++					if (ch->ch_s_tmax  != ch->ch_tmax ||
++					    ch->ch_s_ttime != ch->ch_ttime) {
++						b = set_cmd_header(b, port, 48);
++
++						ch->ch_s_tmax = ch->ch_tmax;
++						ch->ch_s_ttime = ch->ch_ttime;
++
++						put_unaligned_be16(ch->ch_s_tmax,
++								   b);
++						b += 2;
++
++						put_unaligned_be16(ch->ch_s_ttime,
++								   b);
++						b += 2;
++					}
++
++					/*
++					 *  Send RLOW, RHIGH.
++					 */
++
++					if (ch->ch_s_rlow  != ch->ch_rlow ||
++					    ch->ch_s_rhigh != ch->ch_rhigh) {
++						b = set_cmd_header(b, port, 45);
++
++						ch->ch_s_rlow  = ch->ch_rlow;
++						ch->ch_s_rhigh = ch->ch_rhigh;
++
++						put_unaligned_be16(ch->ch_s_rlow,
++								   b);
++						b += 2;
++
++						put_unaligned_be16(ch->ch_s_rhigh,
++								   b);
++						b += 2;
++					}
++
++					/*
++					 *  Send BRATE, CFLAG, IFLAG,
++					 *  OFLAG, XFLAG.
++					 */
++
++					if (ch->ch_s_brate != ch->ch_brate ||
++					    ch->ch_s_cflag != ch->ch_cflag ||
++					    ch->ch_s_iflag != ch->ch_iflag ||
++					    ch->ch_s_oflag != ch->ch_oflag ||
++					    ch->ch_s_xflag != ch->ch_xflag) {
++						b = set_cmd_header(b, port, 40);
++
++						ch->ch_s_brate = ch->ch_brate;
++						ch->ch_s_cflag = ch->ch_cflag;
++						ch->ch_s_iflag = ch->ch_iflag;
++						ch->ch_s_oflag = ch->ch_oflag;
++						ch->ch_s_xflag = ch->ch_xflag;
++
++						put_unaligned_be16(ch->ch_s_brate,
++								   b);
++						b += 2;
++
++						put_unaligned_be16(ch->ch_s_cflag,
++								   b);
++						b += 2;
++
++						put_unaligned_be16(ch->ch_s_iflag,
++								   b);
++						b += 2;
++
++						put_unaligned_be16(ch->ch_s_oflag,
++								   b);
++						b += 2;
++
++						put_unaligned_be16(ch->ch_s_xflag,
++								   b);
++						b += 2;
++					}
++
++					/*
++					 *  Send MOUT, MFLOW, MCTRL.
++					 */
++
++					if (ch->ch_s_mout  != ch->ch_mout  ||
++					    ch->ch_s_mflow != ch->ch_mflow ||
++					    ch->ch_s_mctrl != ch->ch_mctrl) {
++						b = set_cmd_header(b, port, 44);
++
++						*b++ = ch->ch_s_mout  = ch->ch_mout;
++						*b++ = ch->ch_s_mflow = ch->ch_mflow;
++						*b++ = ch->ch_s_mctrl = ch->ch_mctrl;
++					}
++
++					/*
++					 *  Send Flow control characters.
++					 */
++
++					if (ch->ch_s_xon   != ch->ch_xon   ||
++					    ch->ch_s_xoff  != ch->ch_xoff  ||
++					    ch->ch_s_lnext != ch->ch_lnext ||
++					    ch->ch_s_xxon  != ch->ch_xxon  ||
++					    ch->ch_s_xxoff != ch->ch_xxoff) {
++						b = set_cmd_header(b, port, 46);
++
++						*b++ = ch->ch_s_xon   = ch->ch_xon;
++						*b++ = ch->ch_s_xoff  = ch->ch_xoff;
++						*b++ = ch->ch_s_lnext = ch->ch_lnext;
++						*b++ = ch->ch_s_xxon  = ch->ch_xxon;
++						*b++ = ch->ch_s_xxoff = ch->ch_xxoff;
++					}
++
++					/*
++					 *  Send RMAX, RTIME.
++					 */
++
++					if (ch->ch_s_rmax != ch->ch_rmax ||
++					    ch->ch_s_rtime != ch->ch_rtime) {
++						b = set_cmd_header(b, port, 47);
++
++						ch->ch_s_rmax  = ch->ch_rmax;
++						ch->ch_s_rtime = ch->ch_rtime;
++
++						put_unaligned_be16(ch->ch_s_rmax,
++								   b);
++						b += 2;
++
++						put_unaligned_be16(ch->ch_s_rtime,
++								   b);
++						b += 2;
++					}
++
++					ch->ch_flag &= ~CH_PARAM;
++					wake_up_interruptible(&ch->ch_flag_wait);
++				}
++
++
++				/*
++				 *  Handle action commands.
++				 */
++
++				if (ch->ch_send != 0) {
++					/* int send = ch->ch_send & ~ch->ch_expect; */
++					send = ch->ch_send & ~ch->ch_expect;
++
++					/* Send character immediate */
++					if ((send & RR_TX_ICHAR) != 0) {
++						b = set_cmd_header(b, port, 60);
++
++						*b++ = ch->ch_xon;
++						ch->ch_expect |= RR_TX_ICHAR;
++					}
++
++					/* BREAK request */
++					if ((send & RR_TX_BREAK) != 0) {
++						if (ch->ch_break_time != 0) {
++							b = set_cmd_header(b, port, 61);
++							put_unaligned_be16(ch->ch_break_time,
++									   b);
++							b += 2;
++
++							ch->ch_expect |= RR_TX_BREAK;
++							ch->ch_break_time = 0;
++						} else {
++							ch->ch_send &= ~RR_TX_BREAK;
++							ch->ch_flag &= ~CH_TX_BREAK;
++							wake_up_interruptible(&ch->ch_flag_wait);
++						}
++					}
++
++					/*
++					 *  Flush input/output buffers.
++					 */
++
++					if ((send & (RR_RX_FLUSH | RR_TX_FLUSH)) != 0) {
++						b = set_cmd_header(b, port, 62);
++
++						*b++ = ((send & RR_TX_FLUSH) == 0 ? 1 :
++							(send & RR_RX_FLUSH) == 0 ? 2 : 3);
++
++						if (send & RR_RX_FLUSH) {
++							ch->ch_flush_seq = nd->nd_seq_in;
++							ch->ch_flag |= CH_RX_FLUSH;
++							work = 1;
++							send_sync = 1;
++							wanted_sync_port = port;
++						}
++
++						ch->ch_send &= ~(RR_RX_FLUSH | RR_TX_FLUSH);
++					}
++
++					/*  Pause input/output */
++					if ((send & (RR_RX_STOP | RR_TX_STOP)) != 0) {
++						b = set_cmd_header(b, port, 63);
++						*b = 0;
++
++						if ((send & RR_TX_STOP) != 0)
++							*b |= EV_OPU;
++
++						if ((send & RR_RX_STOP) != 0)
++							*b |= EV_IPU;
++
++						b++;
++
++						ch->ch_send &= ~(RR_RX_STOP | RR_TX_STOP);
++					}
++
++					/* Start input/output */
++					if ((send & (RR_RX_START | RR_TX_START)) != 0) {
++						b = set_cmd_header(b, port, 64);
++						*b = 0;
++
++						if ((send & RR_TX_START) != 0)
++							*b |= EV_OPU | EV_OPS | EV_OPX;
++
++						if ((send & RR_RX_START) != 0)
++							*b |= EV_IPU | EV_IPS;
++
++						b++;
++
++						ch->ch_send &= ~(RR_RX_START | RR_TX_START);
++					}
++				}
++
++
++				/*
++				 *  Send a window sequence to acknowledge received data.
++				 */
++
++				rwin = (ch->ch_s_rin +
++					((ch->ch_rout - ch->ch_rin - 1) & RBUF_MASK));
++
++				n = (rwin - ch->ch_s_rwin) & 0xffff;
++
++				if (n >= RBUF_MAX / 4) {
++					b[0] = 0xa0 + (port & 0xf);
++					ch->ch_s_rwin = rwin;
++					put_unaligned_be16(rwin, b + 1);
++					b += 3;
++				}
++
++				/*
++				 *  If the terminal is waiting on LOW
++				 *  water or EMPTY, and the condition
++				 *  is now satisfied, call the line
++				 *  discipline to put more data in the
++				 *  buffer.
++				 */
++
++				n = (ch->ch_tin - ch->ch_tout) & TBUF_MASK;
++
++				if ((ch->ch_tun.un_flag & (UN_EMPTY|UN_LOW)) != 0) {
++					if ((ch->ch_tun.un_flag & UN_LOW) != 0 ?
++					    (n <= TBUF_LOW) :
++					    (n == 0 && ch->ch_s_tpos == ch->ch_s_tin)) {
++						ch->ch_tun.un_flag &= ~(UN_EMPTY|UN_LOW);
++
++						if (waitqueue_active(&((ch->ch_tun.un_tty)->write_wait)))
++							wake_up_interruptible(&((ch->ch_tun.un_tty)->write_wait));
++						tty_wakeup(ch->ch_tun.un_tty);
++						n = (ch->ch_tin - ch->ch_tout) & TBUF_MASK;
++					}
++				}
++
++				/*
++				 * If the printer is waiting on LOW
++				 * water, TIME, EMPTY or PWAIT, and is
++				 * now ready to put more data in the
++				 * buffer, call the line discipline to
++				 * do the job.
++				 */
++
++				if (ch->ch_pun.un_open_count &&
++				    (ch->ch_pun.un_flag &
++				    (UN_EMPTY|UN_TIME|UN_LOW|UN_PWAIT)) != 0) {
++
++					if ((ch->ch_pun.un_flag & UN_LOW) != 0 ?
++					    (n <= TBUF_LOW) :
++					    (ch->ch_pun.un_flag & UN_TIME) != 0 ?
++					    ((jiffies - ch->ch_waketime) >= 0) :
++					    (n == 0 && ch->ch_s_tpos == ch->ch_s_tin) &&
++					    ((ch->ch_pun.un_flag & UN_EMPTY) != 0 ||
++					    ((ch->ch_tun.un_open_count &&
++					      ch->ch_tun.un_tty->ops->chars_in_buffer) ?
++					     (ch->ch_tun.un_tty->ops->chars_in_buffer)(ch->ch_tun.un_tty) == 0
++					     : 1
++					    )
++					    )) {
++						ch->ch_pun.un_flag &= ~(UN_EMPTY | UN_TIME | UN_LOW | UN_PWAIT);
++
++						if (waitqueue_active(&((ch->ch_pun.un_tty)->write_wait)))
++							wake_up_interruptible(&((ch->ch_pun.un_tty)->write_wait));
++						tty_wakeup(ch->ch_pun.un_tty);
++						n = (ch->ch_tin - ch->ch_tout) & TBUF_MASK;
++
++					} else if ((ch->ch_pun.un_flag & UN_TIME) != 0) {
++						work = 1;
++					}
++				}
++
++
++				/*
++				 *  Determine the max number of bytes
++				 *  this port can send, including
++				 *  packet header overhead.
++				 */
++
++				t = ((ch->ch_s_tsize + ch->ch_s_tpos - ch->ch_s_tin) & 0xffff);
++
++				if (n > t)
++					n = t;
++
++				if (n != 0) {
++					n += (n <= 8 ? 1 : n <= 255 ? 2 : 3);
++
++					tdata[tchan++] = n;
++					ttotal += n;
++				}
++				break;
++
++			/*
++			 *  Close the port.
++			 */
++
++send_close:
++			case CS_SEND_CLOSE:
++				b = set_cmd_header(b, port, 10);
++				if (ch->ch_otype == OTYPE_IMMEDIATE)
++					*b++ = 3;
++				else
++					*b++ = 4;
++
++				ch->ch_state = CS_WAIT_CLOSE;
++				break;
++
++			/*
++			 *  Wait for a previous server request.
++			 */
++
++			case CS_WAIT_OPEN:
++			case CS_WAIT_CANCEL:
++			case CS_WAIT_FAIL:
++			case CS_WAIT_QUERY:
++			case CS_WAIT_CLOSE:
++				break;
++
++			default:
++				pr_info("%s - unexpected channel state (%i)\n",
++					__func__, ch->ch_state);
++			}
++		}
++
++		/*
++		 *  If a module select code is needed, drop one in.  If space
++		 *  was reserved for one, but none is needed, recover the space.
++		 */
++
++		if (mod != nd->nd_tx_module) {
++			if (b != mbuf) {
++				mbuf[-1] = 0xf0 | mod;
++				nd->nd_tx_module = mod;
++			} else {
++				b--;
++			}
++		}
++	}
++
++	/*
++	 *  Adjust "tmax" so that under worst case conditions we do
++	 *  not overflow either the daemon buffer or the internal
++	 *  buffer in the loop that follows.   Leave a safe area
++	 *  of 64 bytes so we start getting asserts before we start
++	 *  losing data or clobbering memory.
++	 */
++
++	n = UIO_MAX - UIO_BASE;
++
++	if (tmax > n)
++		tmax = n;
++
++	tmax -= 64;
++
++	tsafe = tmax;
++
++	/*
++	 *  Allocate space for 5 Module Selects, 1 Sequence Request,
++	 *  and 1 Set TREQ for each active channel.
++	 */
++
++	tmax -= 5 + 3 + 4 * nd->nd_chan_count;
++
++	/*
++	 *  Further reduce "tmax" to the available transmit credit.
++	 *  Note that this is a soft constraint;  The transmit credit
++	 *  can go negative for a time and then recover.
++	 */
++
++	n = nd->nd_tx_deposit - nd->nd_tx_charge - nd->nd_link.lk_header_size;
++
++	if (tmax > n)
++		tmax = n;
++
++	/*
++	 *  Finally reduce tmax by the number of bytes already in
++	 *  the buffer.
++	 */
++
++	tmax -= b - buf;
++
++	/*
++	 *  Suspend data transmit unless every ready channel can send
++	 *  at least 1 character.
++	 */
++	if (tmax < 2 * nd->nd_chan_count) {
++		tsend = 1;
++
++	} else if (tchan > 1 && ttotal > tmax) {
++
++		/*
++		 *  If transmit is limited by the credit budget, find the
++		 *  largest number of characters we can send without driving
++		 *  the credit negative.
++		 */
++
++		long tm = tmax;
++		int tc = tchan;
++		int try;
++
++		tsend = tm / tc;
++
++		for (try = 0; try < 3; try++) {
++			int i;
++			int c = 0;
++
++			for (i = 0; i < tc; i++) {
++				if (tsend < tdata[i])
++					tdata[c++] = tdata[i];
++				else
++					tm -= tdata[i];
++			}
++
++			if (c == tc)
++				break;
++
++			tsend = tm / c;
++
++			if (c == 1)
++				break;
++
++			tc = c;
++		}
++
++		tsend = tm / nd->nd_chan_count;
++
++		if (tsend < 2)
++			tsend = 1;
++
++	} else {
++		/*
++		 *  If no budgetary constraints, or only one channel ready
++		 *  to send, set the character limit to the remaining
++		 *  buffer size.
++		 */
++
++		tsend = tmax;
++	}
++
++	tsend -= (tsend <= 9) ? 1 : (tsend <= 257) ? 2 : 3;
++
++	/*
++	 *  Loop over all channels, sending queued data.
++	 */
++
++	port = 0;
++	ch = nd->nd_chan;
++	used_buffer = tmax;
++
++	for (mod = 0; port < nd->nd_chan_count; mod++) {
++		/*
++		 *  If this is not the current module, enter a module select
++		 *  code in the buffer.
++		 */
++
++		if (mod != nd->nd_tx_module)
++			mbuf = ++b;
++
++		/*
++		 *  Loop to process one module.
++		 */
++
++		maxport = port + 16;
++
++		if (maxport > nd->nd_chan_count)
++			maxport = nd->nd_chan_count;
++
++		for (; port < maxport; port++, ch++) {
++			if (ch->ch_state != CS_READY)
++				continue;
++
++			lastport = port;
++
++			n = (ch->ch_tin - ch->ch_tout) & TBUF_MASK;
++
++			/*
++			 *  If there is data that can be sent, send it.
++			 */
++
++			if (n != 0 && used_buffer > 0) {
++				t = (ch->ch_s_tsize + ch->ch_s_tpos - ch->ch_s_tin) & 0xffff;
++
++				if (n > t)
++					n = t;
++
++				if (n > tsend) {
++					work = 1;
++					n = tsend;
++				}
++
++				if (n > used_buffer) {
++					work = 1;
++					n = used_buffer;
++				}
++
++				if (n <= 0)
++					continue;
++
++				/*
++				 *  Create the correct size transmit header,
++				 *  depending on the amount of data to transmit.
++				 */
++
++				if (n <= 8) {
++
++					b[0] = ((n - 1) << 4) + (port & 0xf);
++					b += 1;
++
++				} else if (n <= 255) {
++
++					b[0] = 0x80 + (port & 0xf);
++					b[1] = n;
++					b += 2;
++
++				} else {
++
++					b[0] = 0x90 + (port & 0xf);
++					put_unaligned_be16(n, b + 1);
++					b += 3;
++				}
++
++				ch->ch_s_tin = (ch->ch_s_tin + n) & 0xffff;
++
++				/*
++				 *  Copy transmit data to the packet.
++				 */
++
++				t = TBUF_MAX - ch->ch_tout;
++
++				if (n >= t) {
++					memcpy(b, ch->ch_tbuf + ch->ch_tout, t);
++					b += t;
++					n -= t;
++					used_buffer -= t;
++					ch->ch_tout = 0;
++				}
++
++				memcpy(b, ch->ch_tbuf + ch->ch_tout, n);
++				b += n;
++				used_buffer -= n;
++				ch->ch_tout += n;
++				n = (ch->ch_tin - ch->ch_tout) & TBUF_MASK;
++			}
++
++			/*
++			 *  Wake any terminal unit process waiting in the
++			 *  dgrp_write routine for low water.
++			 */
++
++			if (n > TBUF_LOW)
++				continue;
++
++			if ((ch->ch_flag & CH_LOW) != 0) {
++				ch->ch_flag &= ~CH_LOW;
++				wake_up_interruptible(&ch->ch_flag_wait);
++			}
++
++			/* selwakeup tty_sel */
++			if (ch->ch_tun.un_open_count) {
++				struct tty_struct *tty = (ch->ch_tun.un_tty);
++
++				if (waitqueue_active(&tty->write_wait))
++					wake_up_interruptible(&tty->write_wait);
++
++				tty_wakeup(tty);
++			}
++
++			if (ch->ch_pun.un_open_count) {
++				struct tty_struct *tty = (ch->ch_pun.un_tty);
++
++				if (waitqueue_active(&tty->write_wait))
++					wake_up_interruptible(&tty->write_wait);
++
++				tty_wakeup(tty);
++			}
++
++			/*
++			 *  Do EMPTY processing.
++			 */
++
++			if (n != 0)
++				continue;
++
++			if ((ch->ch_flag & (CH_EMPTY | CH_DRAIN)) != 0 ||
++			    (ch->ch_pun.un_flag & UN_EMPTY) != 0) {
++				/*
++				 *  If there is still data in the server, ask the server
++				 *  to notify us when its all gone.
++				 */
++
++				if (ch->ch_s_treq != ch->ch_s_tin) {
++					b = set_cmd_header(b, port, 43);
++
++					ch->ch_s_treq = ch->ch_s_tin;
++					put_unaligned_be16(ch->ch_s_treq,
++							   b);
++					b += 2;
++				}
++
++				/*
++				 *  If there is a thread waiting for buffer empty,
++				 *  and we are truly empty, wake the thread.
++				 */
++
++				else if ((ch->ch_flag & CH_EMPTY) != 0 &&
++					(ch->ch_send & RR_TX_BREAK) == 0) {
++					ch->ch_flag &= ~CH_EMPTY;
++
++					wake_up_interruptible(&ch->ch_flag_wait);
++				}
++			}
++		}
++
++		/*
++		 *  If a module select code is needed, drop one in.  If space
++		 *  was reserved for one, but none is needed, recover the space.
++		 */
++
++		if (mod != nd->nd_tx_module) {
++			if (b != mbuf) {
++				mbuf[-1] = 0xf0 | mod;
++				nd->nd_tx_module = mod;
++			} else {
++				b--;
++			}
++		}
++	}
++
++	/*
++	 *  Send a synchronization sequence associated with the last open
++	 *  channel that sent data, and remember the time when the data was
++	 *  sent.
++	 */
++
++	in = nd->nd_seq_in;
++
++	if ((send_sync || nd->nd_seq_wait[in] != 0) && lastport >= 0) {
++		u8 *bb = b;
++
++		/*
++		 * Attempt the use the port that really wanted the sync.
++		 * This gets around a race condition where the "lastport" is in
++		 * the middle of the close() routine, and by the time we
++		 * send this command, it will have already acked the close, and
++		 * thus not send the sync response.
++		 */
++		if (wanted_sync_port >= 0)
++			lastport = wanted_sync_port;
++		/*
++		 * Set a flag just in case the port is in the middle of a close,
++		 * it will not be permitted to actually close until we get an
++		 * sync response, and clear the flag there.
++		 */
++		ch = nd->nd_chan + lastport;
++		ch->ch_flag |= CH_WAITING_SYNC;
++
++		mod = lastport >> 4;
++
++		if (mod != nd->nd_tx_module) {
++			bb[0] = 0xf0 + mod;
++			bb += 1;
++
++			nd->nd_tx_module = mod;
++		}
++
++		bb = set_cmd_header(bb, lastport, 12);
++		*bb++ = in;
++
++		nd->nd_seq_size[in] = bb - buf;
++		nd->nd_seq_time[in] = jiffies;
++
++		if (++in >= SEQ_MAX)
++			in = 0;
++
++		if (in != nd->nd_seq_out) {
++			b = bb;
++			nd->nd_seq_in = in;
++			nd->nd_unack += b - buf;
++		}
++	}
++
++	/*
++	 *  If there are no open ports, a sync cannot be sent.
++	 *  There is nothing left to wait for anyway, so wake any
++	 *  thread waiting for an acknowledgement.
++	 */
++
++	else if (nd->nd_seq_wait[in] != 0) {
++		nd->nd_seq_wait[in] = 0;
++
++		wake_up_interruptible(&nd->nd_seq_wque[in]);
++	}
++
++	/*
++	 *  If there is no traffic for an interval of IDLE_MAX, then
++	 *  send a single byte packet.
++	 */
++
++	if (b != buf) {
++		nd->nd_tx_time = jiffies;
++	} else if ((ulong)(jiffies - nd->nd_tx_time) >= IDLE_MAX) {
++		*b++ = 0xf0 | nd->nd_tx_module;
++		nd->nd_tx_time = jiffies;
++	}
++
++	n = b - buf;
++
++	if (n >= tsafe)
++		pr_info("%s - n(%i) >= tsafe(%i)\n",
++			__func__, n, tsafe);
++
++	if (tsend < 0)
++		dgrp_dump(buf, n);
++
++	nd->nd_tx_work = work;
++
++	return n;
++}
++
++/*
++ * dgrp_net_read()
++ * Data to be sent TO the PortServer from the "async." half of the driver.
++ */
++static ssize_t dgrp_net_read(struct file *file, char __user *buf, size_t count,
++			     loff_t *ppos)
++{
++	struct nd_struct *nd;
++	long n;
++	u8 *local_buf;
++	u8 *b;
++	ssize_t rtn;
++
++	/*
++	 *  Get the node pointer, and quit if it doesn't exist.
++	 */
++	nd = (struct nd_struct *)(file->private_data);
++	if (!nd)
++		return -ENXIO;
++
++	if (count < UIO_MIN)
++		return -EINVAL;
++
++	/*
++	 *  Only one read/write operation may be in progress at
++	 *  any given time.
++	 */
++
++	/*
++	 *  Grab the NET lock.
++	 */
++	down(&nd->nd_net_semaphore);
++
++	nd->nd_read_count++;
++
++	nd->nd_tx_ready = 0;
++
++	/*
++	 *  Determine the effective size of the buffer.
++	 */
++
++	if (nd->nd_remain > UIO_BASE)
++		pr_info_ratelimited("%s - nd_remain(%i) > UIO_BASE\n",
++				    __func__, nd->nd_remain);
++
++	b = local_buf = nd->nd_iobuf + UIO_BASE;
++
++	/*
++	 *  Generate data according to the node state.
++	 */
++
++	switch (nd->nd_state) {
++	/*
++	 *  Initialize the connection.
++	 */
++
++	case NS_IDLE:
++		if (nd->nd_mon_buf)
++			dgrp_monitor_reset(nd);
++
++		/*
++		 *  Request a Product ID Packet.
++		 */
++
++		b[0] = 0xfb;
++		b[1] = 0x01;
++		b += 2;
++
++		nd->nd_expect |= NR_IDENT;
++
++		/*
++		 *  Request a Server Capability ID Response.
++		 */
++
++		b[0] = 0xfb;
++		b[1] = 0x02;
++		b += 2;
++
++		nd->nd_expect |= NR_CAPABILITY;
++
++		/*
++		 *  Request a Server VPD Response.
++		 */
++
++		b[0] = 0xfb;
++		b[1] = 0x18;
++		b += 2;
++
++		nd->nd_expect |= NR_VPD;
++
++		nd->nd_state = NS_WAIT_QUERY;
++		break;
++
++	/*
++	 *  We do serious communication with the server only in
++	 *  the READY state.
++	 */
++
++	case NS_READY:
++		b = dgrp_send(nd, count) + local_buf;
++		break;
++
++	/*
++	 *  Send off an error after receiving a bogus message
++	 *  from the server.
++	 */
++
++	case NS_SEND_ERROR:
++		n = strlen(nd->nd_error);
++
++		b[0] = 0xff;
++		b[1] = n;
++		memcpy(b + 2, nd->nd_error, n);
++		b += 2 + n;
++
++		dgrp_net_idle(nd);
++		/*
++		 *  Set the active port count to zero.
++		 */
++		dgrp_chan_count(nd, 0);
++		break;
++
++	default:
++		break;
++	}
++
++	n = b - local_buf;
++
++	if (n != 0) {
++		nd->nd_send_count++;
++
++		nd->nd_tx_byte   += n + nd->nd_link.lk_header_size;
++		nd->nd_tx_charge += n + nd->nd_link.lk_header_size;
++	}
++
++	rtn = copy_to_user((void __user *)buf, local_buf, n);
++	if (rtn) {
++		rtn = -EFAULT;
++		goto done;
++	}
++
++	*ppos += n;
++
++	rtn = n;
++
++	if (nd->nd_mon_buf)
++		dgrp_monitor_data(nd, RPDUMP_CLIENT, local_buf, n);
++
++	/*
++	 *  Release the NET lock.
++	 */
++done:
++	up(&nd->nd_net_semaphore);
++
++	return rtn;
++}
++
++/**
++ * dgrp_receive() -- decode data packets received from the remote PortServer.
++ * @nd: pointer to a node structure
++ */
++static void dgrp_receive(struct nd_struct *nd)
++{
++	struct ch_struct *ch;
++	u8 *buf;
++	u8 *b;
++	u8 *dbuf;
++	char *error;
++	long port;
++	long dlen;
++	long plen;
++	long remain;
++	long n;
++	long mlast;
++	long elast;
++	long mstat;
++	long estat;
++
++	char ID[3];
++
++	nd->nd_tx_time = jiffies;
++
++	ID_TO_CHAR(nd->nd_ID, ID);
++
++	b = buf = nd->nd_iobuf;
++	remain = nd->nd_remain;
++
++	/*
++	 *  Loop to process Realport protocol packets.
++	 */
++
++	while (remain > 0) {
++		int n0 = b[0] >> 4;
++		int n1 = b[0] & 0x0f;
++
++		if (n0 <= 12) {
++			port = (nd->nd_rx_module << 4) + n1;
++
++			if (port >= nd->nd_chan_count) {
++				error = "Improper Port Number";
++				goto prot_error;
++			}
++
++			ch = nd->nd_chan + port;
++		} else {
++			port = -1;
++			ch = NULL;
++		}
++
++		/*
++		 *  Process by major packet type.
++		 */
++
++		switch (n0) {
++
++		/*
++		 *  Process 1-byte header data packet.
++		 */
++
++		case 0:
++		case 1:
++		case 2:
++		case 3:
++		case 4:
++		case 5:
++		case 6:
++		case 7:
++			dlen = n0 + 1;
++			plen = dlen + 1;
++
++			dbuf = b + 1;
++			goto data;
++
++		/*
++		 *  Process 2-byte header data packet.
++		 */
++
++		case 8:
++			if (remain < 3)
++				goto done;
++
++			dlen = b[1];
++			plen = dlen + 2;
++
++			dbuf = b + 2;
++			goto data;
++
++		/*
++		 *  Process 3-byte header data packet.
++		 */
++
++		case 9:
++			if (remain < 4)
++				goto done;
++
++			dlen = get_unaligned_be16(b + 1);
++			plen = dlen + 3;
++
++			dbuf = b + 3;
++
++		/*
++		 *  Common packet handling code.
++		 */
++
++data:
++			nd->nd_tx_work = 1;
++
++			/*
++			 *  Otherwise data should appear only when we are
++			 *  in the CS_READY state.
++			 */
++
++			if (ch->ch_state < CS_READY) {
++				error = "Data received before RWIN established";
++				goto prot_error;
++			}
++
++			/*
++			 *  Assure that the data received is within the
++			 *  allowable window.
++			 */
++
++			n = (ch->ch_s_rwin - ch->ch_s_rin) & 0xffff;
++
++			if (dlen > n) {
++				error = "Receive data overrun";
++				goto prot_error;
++			}
++
++			/*
++			 *  If we received 3 or less characters,
++			 *  assume it is a human typing, and set RTIME
++			 *  to 10 milliseconds.
++			 *
++			 *  If we receive 10 or more characters,
++			 *  assume its not a human typing, and set RTIME
++			 *  to 100 milliseconds.
++			 */
++
++			if (ch->ch_edelay != DGRP_RTIME) {
++				if (ch->ch_rtime != ch->ch_edelay) {
++					ch->ch_rtime = ch->ch_edelay;
++					ch->ch_flag |= CH_PARAM;
++				}
++			} else if (dlen <= 3) {
++				if (ch->ch_rtime != 10) {
++					ch->ch_rtime = 10;
++					ch->ch_flag |= CH_PARAM;
++				}
++			} else {
++				if (ch->ch_rtime != DGRP_RTIME) {
++					ch->ch_rtime = DGRP_RTIME;
++					ch->ch_flag |= CH_PARAM;
++				}
++			}
++
++			/*
++			 *  If a portion of the packet is outside the
++			 *  buffer, shorten the effective length of the
++			 *  data packet to be the amount of data received.
++			 */
++
++			if (remain < plen)
++				dlen -= plen - remain;
++
++			/*
++			 *  Detect if receive flush is now complete.
++			 */
++
++			if ((ch->ch_flag & CH_RX_FLUSH) != 0 &&
++			    ((ch->ch_flush_seq - nd->nd_seq_out) & SEQ_MASK) >=
++			    ((nd->nd_seq_in    - nd->nd_seq_out) & SEQ_MASK)) {
++				ch->ch_flag &= ~CH_RX_FLUSH;
++			}
++
++			/*
++			 *  If we are ready to receive, move the data into
++			 *  the receive buffer.
++			 */
++
++			ch->ch_s_rin = (ch->ch_s_rin + dlen) & 0xffff;
++
++			if (ch->ch_state == CS_READY &&
++			    (ch->ch_tun.un_open_count != 0) &&
++			    (ch->ch_tun.un_flag & UN_CLOSING) == 0 &&
++			    (ch->ch_cflag & CF_CREAD) != 0 &&
++			    (ch->ch_flag & (CH_BAUD0 | CH_RX_FLUSH)) == 0 &&
++			    (ch->ch_send & RR_RX_FLUSH) == 0) {
++
++				if (ch->ch_rin + dlen >= RBUF_MAX) {
++					n = RBUF_MAX - ch->ch_rin;
++
++					memcpy(ch->ch_rbuf + ch->ch_rin, dbuf, n);
++
++					ch->ch_rin = 0;
++					dbuf += n;
++					dlen -= n;
++				}
++
++				memcpy(ch->ch_rbuf + ch->ch_rin, dbuf, dlen);
++
++				ch->ch_rin += dlen;
++
++
++				/*
++				 *  If we are not in fastcook mode, or
++				 *  if there is a fastcook thread
++				 *  waiting for data, send the data to
++				 *  the line discipline.
++				 */
++
++				if ((ch->ch_flag & CH_FAST_READ) == 0 ||
++				    ch->ch_inwait != 0) {
++					dgrp_input(ch);
++				}
++
++				/*
++				 *  If there is a read thread waiting
++				 *  in select, and we are in fastcook
++				 *  mode, wake him up.
++				 */
++
++				if (waitqueue_active(&ch->ch_tun.un_tty->read_wait) &&
++				    (ch->ch_flag & CH_FAST_READ) != 0)
++					wake_up_interruptible(&ch->ch_tun.un_tty->read_wait);
++
++				/*
++				 * Wake any thread waiting in the
++				 * fastcook loop.
++				 */
++
++				if ((ch->ch_flag & CH_INPUT) != 0) {
++					ch->ch_flag &= ~CH_INPUT;
++
++					wake_up_interruptible(&ch->ch_flag_wait);
++				}
++			}
++
++			/*
++			 *  Fabricate and insert a data packet header to
++			 *  preceed the remaining data when it comes in.
++			 */
++
++			if (remain < plen) {
++				dlen = plen - remain;
++				b = buf;
++
++				b[0] = 0x90 + n1;
++				put_unaligned_be16(dlen, b + 1);
++
++				remain = 3;
++				goto done;
++			}
++			break;
++
++		/*
++		 *  Handle Window Sequence packets.
++		 */
++
++		case 10:
++			plen = 3;
++			if (remain < plen)
++				goto done;
++
++			nd->nd_tx_work = 1;
++
++			{
++				ushort tpos   = get_unaligned_be16(b + 1);
++
++				ushort ack    = (tpos          - ch->ch_s_tpos) & 0xffff;
++				ushort unack  = (ch->ch_s_tin  - ch->ch_s_tpos) & 0xffff;
++				ushort notify = (ch->ch_s_treq - ch->ch_s_tpos) & 0xffff;
++
++				if (ch->ch_state < CS_READY || ack > unack) {
++					error = "Improper Window Sequence";
++					goto prot_error;
++				}
++
++				ch->ch_s_tpos = tpos;
++
++				if (notify <= ack)
++					ch->ch_s_treq = tpos;
++			}
++			break;
++
++		/*
++		 *  Handle Command response packets.
++		 */
++
++		case 11:
++
++			/*
++			 * RealPort engine fix - 03/11/2004
++			 *
++			 * This check did not used to be here.
++			 *
++			 * We were using b[1] without verifying that the data
++			 * is actually there and valid. On a split packet, it
++			 * might not be yet.
++			 *
++			 * NOTE:  I have never actually seen the failure happen
++			 *        under Linux,  but since I have seen it occur
++			 *        under both Solaris and HP-UX,  the assumption
++			 *        is that it *could* happen here as well...
++			 */
++			if (remain < 2)
++				goto done;
++
++
++			switch (b[1]) {
++
++			/*
++			 *  Handle Open Response.
++			 */
++
++			case 11:
++				plen = 6;
++				if (remain < plen)
++					goto done;
++
++				nd->nd_tx_work = 1;
++
++				{
++					int req = b[2];
++					int resp = b[3];
++					port = get_unaligned_be16(b + 4);
++
++					if (port >= nd->nd_chan_count) {
++						error = "Open channel number out of range";
++						goto prot_error;
++					}
++
++					ch = nd->nd_chan + port;
++
++					/*
++					 *  How we handle an open response depends primarily
++					 *  on our current channel state.
++					 */
++
++					switch (ch->ch_state) {
++					case CS_IDLE:
++
++						/*
++						 *  Handle a delayed open.
++						 */
++
++						if (ch->ch_otype_waiting != 0 &&
++						    req == ch->ch_otype_waiting &&
++						    resp == 0) {
++							ch->ch_otype = req;
++							ch->ch_otype_waiting = 0;
++							ch->ch_state = CS_SEND_QUERY;
++							break;
++						}
++						goto open_error;
++
++					case CS_WAIT_OPEN:
++
++						/*
++						 *  Handle the open response.
++						 */
++
++						if (req == ch->ch_otype) {
++							switch (resp) {
++
++							/*
++							 *  On successful response, open the
++							 *  port and proceed normally.
++							 */
++
++							case 0:
++								ch->ch_state = CS_SEND_QUERY;
++								break;
++
++							/*
++							 *  On a busy response to a persistent open,
++							 *  remember that the open is pending.
++							 */
++
++							case 1:
++							case 2:
++								if (req != OTYPE_IMMEDIATE) {
++									ch->ch_otype_waiting = req;
++									ch->ch_state = CS_IDLE;
++									break;
++								}
++
++							/*
++							 *  Otherwise the server open failed.  If
++							 *  the Unix port is open, hang it up.
++							 */
++
++							default:
++								if (ch->ch_open_count != 0) {
++									ch->ch_flag |= CH_HANGUP;
++									dgrp_carrier(ch);
++									ch->ch_state = CS_IDLE;
++									break;
++								}
++
++								ch->ch_open_error = resp;
++								ch->ch_state = CS_IDLE;
++
++								wake_up_interruptible(&ch->ch_flag_wait);
++							}
++							break;
++						}
++
++						/*
++						 *  Handle delayed response arrival preceeding
++						 *  the open response we are waiting for.
++						 */
++
++						if (ch->ch_otype_waiting != 0 &&
++						    req == ch->ch_otype_waiting &&
++						    resp == 0) {
++							ch->ch_otype = ch->ch_otype_waiting;
++							ch->ch_otype_waiting = 0;
++							ch->ch_state = CS_WAIT_FAIL;
++							break;
++						}
++						goto open_error;
++
++
++					case CS_WAIT_FAIL:
++
++						/*
++						 *  Handle response to immediate open arriving
++						 *  after a delayed open success.
++						 */
++
++						if (req == OTYPE_IMMEDIATE) {
++							ch->ch_state = CS_SEND_QUERY;
++							break;
++						}
++						goto open_error;
++
++
++					case CS_WAIT_CANCEL:
++						/*
++						 *  Handle delayed open response arriving before
++						 *  the cancel response.
++						 */
++
++						if (req == ch->ch_otype_waiting &&
++						    resp == 0) {
++							ch->ch_otype_waiting = 0;
++							break;
++						}
++
++						/*
++						 *  Handle cancel response.
++						 */
++
++						if (req == 4 && resp == 0) {
++							ch->ch_otype_waiting = 0;
++							ch->ch_state = CS_IDLE;
++							break;
++						}
++						goto open_error;
++
++
++					case CS_WAIT_CLOSE:
++						/*
++						 *  Handle a successful response to a port
++						 *  close.
++						 */
++
++						if (req >= 3) {
++							ch->ch_state = CS_IDLE;
++							break;
++						}
++						goto open_error;
++
++open_error:
++					default:
++						{
++							error = "Improper Open Response";
++							goto prot_error;
++						}
++					}
++				}
++				break;
++
++			/*
++			 *  Handle Synchronize Response.
++			 */
++
++			case 13:
++				plen = 3;
++				if (remain < plen)
++					goto done;
++				{
++					int seq = b[2];
++					int s;
++
++					/*
++					 * If channel was waiting for this sync response,
++					 * unset the flag, and wake up anyone waiting
++					 * on the event.
++					 */
++					if (ch->ch_flag & CH_WAITING_SYNC) {
++						ch->ch_flag &= ~(CH_WAITING_SYNC);
++						wake_up_interruptible(&ch->ch_flag_wait);
++					}
++
++					if (((seq - nd->nd_seq_out) & SEQ_MASK) >=
++					    ((nd->nd_seq_in - nd->nd_seq_out) & SEQ_MASK)) {
++						break;
++					}
++
++					for (s = nd->nd_seq_out;; s = (s + 1) & SEQ_MASK) {
++						if (nd->nd_seq_wait[s] != 0) {
++							nd->nd_seq_wait[s] = 0;
++
++							wake_up_interruptible(&nd->nd_seq_wque[s]);
++						}
++
++						nd->nd_unack -= nd->nd_seq_size[s];
++
++						if (s == seq)
++							break;
++					}
++
++					nd->nd_seq_out = (seq + 1) & SEQ_MASK;
++				}
++				break;
++
++			/*
++			 *  Handle Sequence Response.
++			 */
++
++			case 15:
++				plen = 6;
++				if (remain < plen)
++					goto done;
++
++				{
++				/* Record that we have received the Sequence
++				 * Response, but we aren't interested in the
++				 * sequence numbers.  We were using RIN like it
++				 * was ROUT and that was causing problems,
++				 * fixed 7-13-2001 David Fries. See comment in
++				 * drp.h for ch_s_rin variable.
++					int rin = get_unaligned_be16(b + 2);
++					int tpos = get_unaligned_be16(b + 4);
++				*/
++
++					ch->ch_send   &= ~RR_SEQUENCE;
++					ch->ch_expect &= ~RR_SEQUENCE;
++				}
++				goto check_query;
++
++			/*
++			 *  Handle Status Response.
++			 */
++
++			case 17:
++				plen = 5;
++				if (remain < plen)
++					goto done;
++
++				{
++					ch->ch_s_elast = get_unaligned_be16(b + 2);
++					ch->ch_s_mlast = b[4];
++
++					ch->ch_expect &= ~RR_STATUS;
++					ch->ch_send   &= ~RR_STATUS;
++
++					/*
++					 *  CH_PHYS_CD is cleared because something _could_ be
++					 *  waiting for the initial sense of carrier... and if
++					 *  carrier is high immediately, we want to be sure to
++					 *  wake them as soon as possible.
++					 */
++					ch->ch_flag &= ~CH_PHYS_CD;
++
++					dgrp_carrier(ch);
++				}
++				goto check_query;
++
++			/*
++			 *  Handle Line Error Response.
++			 */
++
++			case 19:
++				plen = 14;
++				if (remain < plen)
++					goto done;
++
++				break;
++
++			/*
++			 *  Handle Buffer Response.
++			 */
++
++			case 21:
++				plen = 6;
++				if (remain < plen)
++					goto done;
++
++				{
++					ch->ch_s_rsize = get_unaligned_be16(b + 2);
++					ch->ch_s_tsize = get_unaligned_be16(b + 4);
++
++					ch->ch_send   &= ~RR_BUFFER;
++					ch->ch_expect &= ~RR_BUFFER;
++				}
++				goto check_query;
++
++			/*
++			 *  Handle Port Capability Response.
++			 */
++
++			case 23:
++				plen = 32;
++				if (remain < plen)
++					goto done;
++
++				{
++					ch->ch_send   &= ~RR_CAPABILITY;
++					ch->ch_expect &= ~RR_CAPABILITY;
++				}
++
++			/*
++			 *  When all queries are complete, set those parameters
++			 *  derived from the query results, then transition
++			 *  to the READY state.
++			 */
++
++check_query:
++				if (ch->ch_state == CS_WAIT_QUERY &&
++				    (ch->ch_expect & (RR_SEQUENCE |
++							RR_STATUS |
++							RR_BUFFER |
++							RR_CAPABILITY)) == 0) {
++					ch->ch_tmax  = ch->ch_s_tsize / 4;
++
++					if (ch->ch_edelay == DGRP_TTIME)
++						ch->ch_ttime = DGRP_TTIME;
++					else
++						ch->ch_ttime = ch->ch_edelay;
++
++					ch->ch_rmax = ch->ch_s_rsize / 4;
++
++					if (ch->ch_edelay == DGRP_RTIME)
++						ch->ch_rtime = DGRP_RTIME;
++					else
++						ch->ch_rtime = ch->ch_edelay;
++
++					ch->ch_rlow  = 2 * ch->ch_s_rsize / 8;
++					ch->ch_rhigh = 6 * ch->ch_s_rsize / 8;
++
++					ch->ch_state = CS_READY;
++
++					nd->nd_tx_work = 1;
++					wake_up_interruptible(&ch->ch_flag_wait);
++
++				}
++				break;
++
++			default:
++				goto decode_error;
++			}
++			break;
++
++		/*
++		 *  Handle Events.
++		 */
++
++		case 12:
++			plen = 4;
++			if (remain < plen)
++				goto done;
++
++			mlast = ch->ch_s_mlast;
++			elast = ch->ch_s_elast;
++
++			mstat = ch->ch_s_mlast = b[1];
++			estat = ch->ch_s_elast = get_unaligned_be16(b + 2);
++
++			/*
++			 *  Handle modem changes.
++			 */
++
++			if (((mstat ^ mlast) & DM_CD) != 0)
++				dgrp_carrier(ch);
++
++
++			/*
++			 *  Handle received break.
++			 */
++
++			if ((estat & ~elast & EV_RXB) != 0 &&
++			    (ch->ch_tun.un_open_count != 0) &&
++			    I_BRKINT(ch->ch_tun.un_tty) &&
++			    !(I_IGNBRK(ch->ch_tun.un_tty))) {
++
++				tty_buffer_request_room(ch->ch_tun.un_tty, 1);
++				tty_insert_flip_char(ch->ch_tun.un_tty, 0, TTY_BREAK);
++				tty_flip_buffer_push(ch->ch_tun.un_tty);
++
++			}
++
++			/*
++			 *  On transmit break complete, if more break traffic
++			 *  is waiting then send it.  Otherwise wake any threads
++			 *  waiting for transmitter empty.
++			 */
++
++			if ((~estat & elast & EV_TXB) != 0 &&
++			    (ch->ch_expect & RR_TX_BREAK) != 0) {
++
++				nd->nd_tx_work = 1;
++
++				ch->ch_expect &= ~RR_TX_BREAK;
++
++				if (ch->ch_break_time != 0) {
++					ch->ch_send |= RR_TX_BREAK;
++				} else {
++					ch->ch_send &= ~RR_TX_BREAK;
++					ch->ch_flag &= ~CH_TX_BREAK;
++					wake_up_interruptible(&ch->ch_flag_wait);
++				}
++			}
++			break;
++
++		case 13:
++		case 14:
++			error = "Unrecognized command";
++			goto prot_error;
++
++		/*
++		 *  Decode Special Codes.
++		 */
++
++		case 15:
++			switch (n1) {
++			/*
++			 *  One byte module select.
++			 */
++
++			case 0:
++			case 1:
++			case 2:
++			case 3:
++			case 4:
++			case 5:
++			case 6:
++			case 7:
++				plen = 1;
++				nd->nd_rx_module = n1;
++				break;
++
++			/*
++			 *  Two byte module select.
++			 */
++
++			case 8:
++				plen = 2;
++				if (remain < plen)
++					goto done;
++
++				nd->nd_rx_module = b[1];
++				break;
++
++			/*
++			 *  ID Request packet.
++			 */
++
++			case 11:
++				if (remain < 4)
++					goto done;
++
++				plen = get_unaligned_be16(b + 2);
++
++				if (plen < 12 || plen > 1000) {
++					error = "Response Packet length error";
++					goto prot_error;
++				}
++
++				nd->nd_tx_work = 1;
++
++				switch (b[1]) {
++				/*
++				 *  Echo packet.
++				 */
++
++				case 0:
++					nd->nd_send |= NR_ECHO;
++					break;
++
++				/*
++				 *  ID Response packet.
++				 */
++
++				case 1:
++					nd->nd_send |= NR_IDENT;
++					break;
++
++				/*
++				 *  ID Response packet.
++				 */
++
++				case 32:
++					nd->nd_send |= NR_PASSWORD;
++					break;
++
++				}
++				break;
++
++			/*
++			 *  Various node-level response packets.
++			 */
++
++			case 12:
++				if (remain < 4)
++					goto done;
++
++				plen = get_unaligned_be16(b + 2);
++
++				if (plen < 4 || plen > 1000) {
++					error = "Response Packet length error";
++					goto prot_error;
++				}
++
++				nd->nd_tx_work = 1;
++
++				switch (b[1]) {
++				/*
++				 *  Echo packet.
++				 */
++
++				case 0:
++					nd->nd_expect &= ~NR_ECHO;
++					break;
++
++				/*
++				 *  Product Response Packet.
++				 */
++
++				case 1:
++					{
++						int desclen;
++
++						nd->nd_hw_ver = (b[8] << 8) | b[9];
++						nd->nd_sw_ver = (b[10] << 8) | b[11];
++						nd->nd_hw_id = b[6];
++						desclen = ((plen - 12) > MAX_DESC_LEN) ? MAX_DESC_LEN :
++							plen - 12;
++						strncpy(nd->nd_ps_desc, b + 12, desclen);
++						nd->nd_ps_desc[desclen] = 0;
++					}
++
++					nd->nd_expect &= ~NR_IDENT;
++					break;
++
++				/*
++				 *  Capability Response Packet.
++				 */
++
++				case 2:
++					{
++						int nn = get_unaligned_be16(b + 4);
++
++						if (nn > CHAN_MAX)
++							nn = CHAN_MAX;
++
++						dgrp_chan_count(nd, nn);
++					}
++
++					nd->nd_expect &= ~NR_CAPABILITY;
++					break;
++
++				/*
++				 *  VPD Response Packet.
++				 */
++
++				case 15:
++					/*
++					 * NOTE: case 15 is here ONLY because the EtherLite
++					 * is broken, and sends a response to 24 back as 15.
++					 * To resolve this, the EtherLite firmware is now
++					 * fixed to send back 24 correctly, but, for backwards
++					 * compatibility, we now have reserved 15 for the
++					 * bad EtherLite response to 24 as well.
++					 */
++
++					/* Fallthru! */
++
++				case 24:
++
++					/*
++					 * If the product doesn't support VPD,
++					 * it will send back a null IDRESP,
++					 * which is a length of 4 bytes.
++					 */
++					if (plen > 4) {
++						memcpy(nd->nd_vpd, b + 4, min(plen - 4, (long) VPDSIZE));
++						nd->nd_vpd_len = min(plen - 4, (long) VPDSIZE);
++					}
++
++					nd->nd_expect &= ~NR_VPD;
++					break;
++
++				default:
++					goto decode_error;
++				}
++
++				if (nd->nd_expect == 0 &&
++				    nd->nd_state == NS_WAIT_QUERY) {
++					nd->nd_state = NS_READY;
++				}
++				break;
++
++			/*
++			 *  Debug packet.
++			 */
++
++			case 14:
++				if (remain < 4)
++					goto done;
++
++				plen = get_unaligned_be16(b + 2) + 4;
++
++				if (plen > 1000) {
++					error = "Debug Packet too large";
++					goto prot_error;
++				}
++
++				if (remain < plen)
++					goto done;
++				break;
++
++			/*
++			 *  Handle reset packet.
++			 */
++
++			case 15:
++				if (remain < 2)
++					goto done;
++
++				plen = 2 + b[1];
++
++				if (remain < plen)
++					goto done;
++
++				nd->nd_tx_work = 1;
++
++				n = b[plen];
++				b[plen] = 0;
++
++				b[plen] = n;
++
++				error = "Client Reset Acknowledge";
++				goto prot_error;
++
++			default:
++				goto decode_error;
++			}
++			break;
++
++		default:
++			goto decode_error;
++		}
++
++		b += plen;
++		remain -= plen;
++	}
++
++	/*
++	 *  When the buffer is exhausted, copy any data left at the
++	 *  top of the buffer back down to the bottom for the next
++	 *  read request.
++	 */
++
++done:
++	if (remain > 0 && b != buf)
++		memcpy(buf, b, remain);
++
++	nd->nd_remain = remain;
++	return;
++
++/*
++ *  Handle a decode error.
++ */
++
++decode_error:
++	error = "Protocol decode error";
++
++/*
++ *  Handle a general protocol error.
++ */
++
++prot_error:
++	nd->nd_remain = 0;
++	nd->nd_state = NS_SEND_ERROR;
++	nd->nd_error = error;
++}
++
++/*
++ * dgrp_net_write() -- write data to the network device.
++ *
++ * A zero byte write indicates that the connection to the RealPort
++ * device has been broken.
++ *
++ * A non-zero write indicates data from the RealPort device.
++ */
++static ssize_t dgrp_net_write(struct file *file, const char __user *buf,
++			      size_t count, loff_t *ppos)
++{
++	struct nd_struct *nd;
++	ssize_t rtn = 0;
++	long n;
++	long total = 0;
++
++	/*
++	 *  Get the node pointer, and quit if it doesn't exist.
++	 */
++	nd = (struct nd_struct *)(file->private_data);
++	if (!nd)
++		return -ENXIO;
++
++	/*
++	 *  Grab the NET lock.
++	 */
++	down(&nd->nd_net_semaphore);
++
++	nd->nd_write_count++;
++
++	/*
++	 *  Handle disconnect.
++	 */
++
++	if (count == 0) {
++		dgrp_net_idle(nd);
++		/*
++		 *  Set the active port count to zero.
++		 */
++		dgrp_chan_count(nd, 0);
++		goto unlock;
++	}
++
++	/*
++	 *  Loop to process entire receive packet.
++	 */
++
++	while (count > 0) {
++		n = UIO_MAX - nd->nd_remain;
++
++		if (n > count)
++			n = count;
++
++		nd->nd_rx_byte += n + nd->nd_link.lk_header_size;
++
++		rtn = copy_from_user(nd->nd_iobuf + nd->nd_remain,
++				     (void __user *) buf + total, n);
++		if (rtn) {
++			rtn = -EFAULT;
++			goto unlock;
++		}
++
++		*ppos += n;
++
++		total += n;
++
++		count -= n;
++
++		if (nd->nd_mon_buf)
++			dgrp_monitor_data(nd, RPDUMP_SERVER,
++					  nd->nd_iobuf + nd->nd_remain, n);
++
++		nd->nd_remain += n;
++
++		dgrp_receive(nd);
++	}
++
++	rtn = total;
++
++unlock:
++	/*
++	 *  Release the NET lock.
++	 */
++	up(&nd->nd_net_semaphore);
++
++	return rtn;
++}
++
++
++/*
++ * dgrp_net_select()
++ *  Determine whether a device is ready to be read or written to, and
++ *  sleep if not.
++ */
++static unsigned int dgrp_net_select(struct file *file,
++				    struct poll_table_struct *table)
++{
++	unsigned int retval = 0;
++	struct nd_struct *nd = file->private_data;
++
++	poll_wait(file, &nd->nd_tx_waitq, table);
++
++	if (nd->nd_tx_ready)
++		retval |= POLLIN | POLLRDNORM; /* Conditionally readable */
++
++	retval |= POLLOUT | POLLWRNORM;        /* Always writeable */
++
++	return retval;
++}
++
++/*
++ * dgrp_net_ioctl
++ *
++ * Implement those functions which allow the network daemon to control
++ * the network parameters in the driver.  The ioctls include ones to
++ * get and set the link speed parameters for the PortServer.
++ */
++static long dgrp_net_ioctl(struct file *file, unsigned int cmd,
++			   unsigned long arg)
++{
++	struct nd_struct  *nd;
++	int    rtn = 0;
++	long   size = _IOC_SIZE(cmd);
++	struct link_struct link;
++
++	nd = file->private_data;
++
++	if (_IOC_DIR(cmd) & _IOC_READ)
++		rtn = access_ok(VERIFY_WRITE, (void __user *) arg, size);
++	else if (_IOC_DIR(cmd) & _IOC_WRITE)
++		rtn = access_ok(VERIFY_READ,  (void __user *) arg, size);
++
++	if (!rtn)
++		return rtn;
++
++	switch (cmd) {
++	case DIGI_SETLINK:
++		if (size != sizeof(struct link_struct))
++			return -EINVAL;
++
++		if (copy_from_user((void *)(&link), (void __user *) arg, size))
++			return -EFAULT;
++
++		if (link.lk_fast_rate < 9600)
++			link.lk_fast_rate = 9600;
++
++		if (link.lk_slow_rate < 2400)
++			link.lk_slow_rate = 2400;
++
++		if (link.lk_fast_rate > 10000000)
++			link.lk_fast_rate = 10000000;
++
++		if (link.lk_slow_rate > link.lk_fast_rate)
++			link.lk_slow_rate = link.lk_fast_rate;
++
++		if (link.lk_fast_delay > 2000)
++			link.lk_fast_delay = 2000;
++
++		if (link.lk_slow_delay > 10000)
++			link.lk_slow_delay = 10000;
++
++		if (link.lk_fast_delay < 60)
++			link.lk_fast_delay = 60;
++
++		if (link.lk_slow_delay < link.lk_fast_delay)
++			link.lk_slow_delay = link.lk_fast_delay;
++
++		if (link.lk_header_size < 2)
++			link.lk_header_size = 2;
++
++		if (link.lk_header_size > 128)
++			link.lk_header_size = 128;
++
++		link.lk_fast_rate /= 8 * 1000 / dgrp_poll_tick;
++		link.lk_slow_rate /= 8 * 1000 / dgrp_poll_tick;
++
++		link.lk_fast_delay /= dgrp_poll_tick;
++		link.lk_slow_delay /= dgrp_poll_tick;
++
++		nd->nd_link = link;
++
++		break;
++
++	case DIGI_GETLINK:
++		if (size != sizeof(struct link_struct))
++			return -EINVAL;
++
++		if (copy_to_user((void __user *)arg, (void *)(&nd->nd_link),
++				 size))
++			return -EFAULT;
++
++		break;
++
++	default:
++		return -EINVAL;
++
++	}
++
++	return 0;
++}
++
++/**
++ * dgrp_poll_handler() -- handler for poll timer
++ *
++ * As each timer expires, it determines (a) whether the "transmit"
++ * waiter needs to be woken up, and (b) whether the poller needs to
++ * be rescheduled.
++ */
++void dgrp_poll_handler(unsigned long arg)
++{
++	struct dgrp_poll_data *poll_data;
++	struct nd_struct *nd;
++	struct link_struct *lk;
++	ulong time;
++	ulong poll_time;
++	ulong freq;
++	ulong lock_flags;
++
++	poll_data = (struct dgrp_poll_data *) arg;
++	freq = 1000 / poll_data->poll_tick;
++	poll_data->poll_round += 17;
++
++	if (poll_data->poll_round >= freq)
++		poll_data->poll_round -= freq;
++
++	/*
++	 * Loop to process all open nodes.
++	 *
++	 * For each node, determine the rate at which it should
++	 * be transmitting data.  Then if the node should wake up
++	 * and transmit data now, enable the net receive select
++	 * to get the transmit going.
++	 */
++
++	list_for_each_entry(nd, &nd_struct_list, list) {
++
++		lk = &nd->nd_link;
++
++		/*
++		 * Decrement statistics.  These are only for use with
++		 * KME, so don't worry that the operations are done
++		 * unlocked, and so the results are occassionally wrong.
++		 */
++
++		nd->nd_read_count -= (nd->nd_read_count +
++				      poll_data->poll_round) / freq;
++		nd->nd_write_count -= (nd->nd_write_count +
++				       poll_data->poll_round) / freq;
++		nd->nd_send_count -= (nd->nd_send_count +
++				      poll_data->poll_round) / freq;
++		nd->nd_tx_byte -= (nd->nd_tx_byte +
++				   poll_data->poll_round) / freq;
++		nd->nd_rx_byte -= (nd->nd_rx_byte +
++				   poll_data->poll_round) / freq;
++
++		/*
++		 * Wake the daemon to transmit data only when there is
++		 * enough byte credit to send data.
++		 *
++		 * The results are approximate because the operations
++		 * are performed unlocked, and we are inspecting
++		 * data asynchronously updated elsewhere.  The whole
++		 * thing is just approximation anyway, so that should
++		 * be okay.
++		 */
++
++		if (lk->lk_slow_rate >= UIO_MAX) {
++
++			nd->nd_delay = 0;
++			nd->nd_rate = UIO_MAX;
++
++			nd->nd_tx_deposit = nd->nd_tx_charge + 3 * UIO_MAX;
++			nd->nd_tx_credit  = 3 * UIO_MAX;
++
++		} else {
++
++			long rate;
++			long delay;
++			long deposit;
++			long charge;
++			long size;
++			long excess;
++
++			long seq_in = nd->nd_seq_in;
++			long seq_out = nd->nd_seq_out;
++
++			/*
++			 * If there are no outstanding packets, run at the
++			 * fastest rate.
++			 */
++
++			if (seq_in == seq_out) {
++				delay = 0;
++				rate = lk->lk_fast_rate;
++			}
++
++			/*
++			 * Otherwise compute the transmit rate based on the
++			 * delay since the oldest packet.
++			 */
++
++			else {
++				/*
++				 * The actual delay is computed as the
++				 * time since the oldest unacknowledged
++				 * packet was sent, minus the time it
++				 * took to send that packet to the server.
++				 */
++
++				delay = ((jiffies - nd->nd_seq_time[seq_out])
++					- (nd->nd_seq_size[seq_out] /
++					lk->lk_fast_rate));
++
++				/*
++				 * If the delay is less than the "fast"
++				 * delay, transmit full speed.  If greater
++				 * than the "slow" delay, transmit at the
++				 * "slow" speed.   In between, interpolate
++				 * between the fast and slow speeds.
++				 */
++
++				rate =
++				  (delay <= lk->lk_fast_delay ?
++				    lk->lk_fast_rate :
++				    delay >= lk->lk_slow_delay ?
++				      lk->lk_slow_rate :
++				      (lk->lk_slow_rate +
++				       (lk->lk_slow_delay - delay) *
++				       (lk->lk_fast_rate - lk->lk_slow_rate) /
++				       (lk->lk_slow_delay - lk->lk_fast_delay)
++				      )
++				  );
++			}
++
++			nd->nd_delay = delay;
++			nd->nd_rate = rate;
++
++			/*
++			 * Increase the transmit credit by depositing the
++			 * current transmit rate.
++			 */
++
++			deposit = nd->nd_tx_deposit;
++			charge  = nd->nd_tx_charge;
++
++			deposit += rate;
++
++			/*
++			 * If the available transmit credit becomes too large,
++			 * reduce the deposit to correct the value.
++			 *
++			 * Too large is the max of:
++			 *		6 times the header size
++			 *		3 times the current transmit rate.
++			 */
++
++			size = 2 * nd->nd_link.lk_header_size;
++
++			if (size < rate)
++				size = rate;
++
++			size *= 3;
++
++			excess = deposit - charge - size;
++
++			if (excess > 0)
++				deposit -= excess;
++
++			nd->nd_tx_deposit = deposit;
++			nd->nd_tx_credit  = deposit - charge;
++
++			/*
++			 * Wake the transmit task only if the transmit credit
++			 * is at least 3 times the transmit header size.
++			 */
++
++			size = 3 * lk->lk_header_size;
++
++			if (nd->nd_tx_credit < size)
++				continue;
++		}
++
++
++		/*
++		 * Enable the READ select to wake the daemon if there
++		 * is useful work for the drp_read routine to perform.
++		 */
++
++		if (waitqueue_active(&nd->nd_tx_waitq) &&
++		    (nd->nd_tx_work != 0 ||
++		    (ulong)(jiffies - nd->nd_tx_time) >= IDLE_MAX)) {
++			nd->nd_tx_ready = 1;
++
++			wake_up_interruptible(&nd->nd_tx_waitq);
++
++			/* not needed */
++			/* nd->nd_flag &= ~ND_SELECT; */
++		}
++	}
++
++
++	/*
++	 * Schedule ourself back at the nominal wakeup interval.
++	 */
++	spin_lock_irqsave(&poll_data->poll_lock, lock_flags);
++
++	poll_data->node_active_count--;
++	if (poll_data->node_active_count > 0) {
++		poll_data->node_active_count++;
++		poll_time = poll_data->timer.expires +
++			poll_data->poll_tick * HZ / 1000;
++
++		time = poll_time - jiffies;
++
++		if (time >= 2 * poll_data->poll_tick)
++			poll_time = jiffies + dgrp_poll_tick * HZ / 1000;
++
++		poll_data->timer.expires = poll_time;
++		add_timer(&poll_data->timer);
++	}
++
++	spin_unlock_irqrestore(&poll_data->poll_lock, lock_flags);
++}
+diff --git a/drivers/staging/dgrp/dgrp_ports_ops.c b/drivers/staging/dgrp/dgrp_ports_ops.c
+new file mode 100644
+index 000000000000..cd1fc2088624
+--- /dev/null
++++ b/drivers/staging/dgrp/dgrp_ports_ops.c
+@@ -0,0 +1,170 @@
++/*
++ *
++ * Copyright 1999-2000 Digi International (www.digi.com)
++ *     James Puzzo 
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
++ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
++ * PURPOSE.  See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++/*
++ *
++ *  Filename:
++ *
++ *     dgrp_ports_ops.c
++ *
++ *  Description:
++ *
++ *     Handle the file operations required for the /proc/dgrp/ports/...
++ *     devices.  Basically gathers tty status for the node and returns it.
++ *
++ *  Author:
++ *
++ *     James A. Puzzo
++ *
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include "dgrp_common.h"
++
++/* File operation declarations */
++static int dgrp_ports_open(struct inode *, struct file *);
++
++static const struct file_operations ports_ops = {
++	.owner   = THIS_MODULE,
++	.open    = dgrp_ports_open,
++	.read    = seq_read,
++	.llseek	 = seq_lseek,
++	.release = seq_release
++};
++
++static struct inode_operations ports_inode_ops = {
++	.permission = dgrp_inode_permission
++};
++
++
++void dgrp_register_ports_hook(struct proc_dir_entry *de)
++{
++	struct nd_struct *node = de->data;
++
++	de->proc_iops = &ports_inode_ops;
++	de->proc_fops = &ports_ops;
++	node->nd_ports_de = de;
++}
++
++static void *dgrp_ports_seq_start(struct seq_file *seq, loff_t *pos)
++{
++	if (*pos == 0)
++		seq_puts(seq, "#num tty_open pr_open tot_wait MSTAT  IFLAG  OFLAG  CFLAG  BPS    DIGIFLAGS\n");
++
++	return pos;
++}
++
++static void *dgrp_ports_seq_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++	struct nd_struct *nd = seq->private;
++
++	if (*pos >= nd->nd_chan_count)
++		return NULL;
++
++	*pos += 1;
++
++	return pos;
++}
++
++static void dgrp_ports_seq_stop(struct seq_file *seq, void *v)
++{
++}
++
++static int dgrp_ports_seq_show(struct seq_file *seq, void *v)
++{
++	loff_t *pos = v;
++	struct nd_struct *nd;
++	struct ch_struct *ch;
++	struct un_struct *tun, *pun;
++	unsigned int totcnt;
++
++	nd = seq->private;
++	if (!nd)
++		return 0;
++
++	if (*pos >= nd->nd_chan_count)
++		return 0;
++
++	ch = &nd->nd_chan[*pos];
++	tun = &ch->ch_tun;
++	pun = &ch->ch_pun;
++
++	/*
++	 * If port is not open and no one is waiting to
++	 * open it, the modem signal values can't be
++	 * trusted, and will be zeroed.
++	 */
++	totcnt = tun->un_open_count +
++		pun->un_open_count +
++		ch->ch_wait_count[0] +
++		ch->ch_wait_count[1] +
++		ch->ch_wait_count[2];
++
++	seq_printf(seq, "%02d      %02d      %02d      %02d     0x%04X 0x%04X 0x%04X 0x%04X %-6d 0x%04X\n",
++		   (int) *pos,
++		   tun->un_open_count,
++		   pun->un_open_count,
++		   ch->ch_wait_count[0] +
++		   ch->ch_wait_count[1] +
++		   ch->ch_wait_count[2],
++		   (totcnt ? ch->ch_s_mlast : 0),
++		   ch->ch_s_iflag,
++		   ch->ch_s_oflag,
++		   ch->ch_s_cflag,
++		   (ch->ch_s_brate ? (1843200 / ch->ch_s_brate) : 0),
++		   ch->ch_digi.digi_flags);
++
++	return 0;
++}
++
++static const struct seq_operations ports_seq_ops = {
++	.start = dgrp_ports_seq_start,
++	.next  = dgrp_ports_seq_next,
++	.stop  = dgrp_ports_seq_stop,
++	.show  = dgrp_ports_seq_show,
++};
++
++/**
++ * dgrp_ports_open -- open the /proc/dgrp/ports/... device
++ * @inode: struct inode *
++ * @file: struct file *
++ *
++ * Open function to open the /proc/dgrp/ports device for a PortServer.
++ * This is the open function for struct file_operations
++ */
++static int dgrp_ports_open(struct inode *inode, struct file *file)
++{
++	struct seq_file *seq;
++	int rtn;
++
++	rtn = seq_open(file, &ports_seq_ops);
++	if (!rtn) {
++		seq = file->private_data;
++		seq->private = PDE(inode)->data;
++	}
++
++	return rtn;
++}
+diff --git a/drivers/staging/dgrp/dgrp_specproc.c b/drivers/staging/dgrp/dgrp_specproc.c
+new file mode 100644
+index 000000000000..259d23aa6c29
+--- /dev/null
++++ b/drivers/staging/dgrp/dgrp_specproc.c
+@@ -0,0 +1,821 @@
++/*
++ *
++ * Copyright 1999 Digi International (www.digi.com)
++ *     James Puzzo  
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
++ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
++ * PURPOSE.  See the GNU General Public License for more details.
++ *
++ */
++
++/*
++ *
++ *  Filename:
++ *
++ *     dgrp_specproc.c
++ *
++ *  Description:
++ *
++ *     Handle the "config" proc entry for the linux realport device driver
++ *     and provide slots for the "net" and "mon" devices
++ *
++ *  Author:
++ *
++ *     James A. Puzzo
++ *
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include "dgrp_common.h"
++
++static struct dgrp_proc_entry dgrp_table[];
++static struct proc_dir_entry *dgrp_proc_dir_entry;
++
++static int dgrp_add_id(long id);
++static int dgrp_remove_nd(struct nd_struct *nd);
++static void unregister_dgrp_device(struct proc_dir_entry *de);
++static void register_dgrp_device(struct nd_struct *node,
++				 struct proc_dir_entry *root,
++				 void (*register_hook)(struct proc_dir_entry *de));
++
++/* File operation declarations */
++static int dgrp_gen_proc_open(struct inode *, struct file *);
++static int dgrp_gen_proc_close(struct inode *, struct file *);
++static int parse_write_config(char *);
++
++
++static const struct file_operations dgrp_proc_file_ops = {
++	.owner   = THIS_MODULE,
++	.open    = dgrp_gen_proc_open,
++	.release = dgrp_gen_proc_close,
++};
++
++static struct inode_operations proc_inode_ops = {
++	.permission = dgrp_inode_permission
++};
++
++
++static void register_proc_table(struct dgrp_proc_entry *,
++				struct proc_dir_entry *);
++static void unregister_proc_table(struct dgrp_proc_entry *,
++				  struct proc_dir_entry *);
++
++static struct dgrp_proc_entry dgrp_net_table[];
++static struct dgrp_proc_entry dgrp_mon_table[];
++static struct dgrp_proc_entry dgrp_ports_table[];
++static struct dgrp_proc_entry dgrp_dpa_table[];
++
++static ssize_t config_proc_write(struct file *file, const char __user *buffer,
++				 size_t count, loff_t *pos);
++
++static int nodeinfo_proc_open(struct inode *inode, struct file *file);
++static int info_proc_open(struct inode *inode, struct file *file);
++static int config_proc_open(struct inode *inode, struct file *file);
++
++static struct file_operations config_proc_file_ops = {
++	.owner	 = THIS_MODULE,
++	.open	 = config_proc_open,
++	.read	 = seq_read,
++	.llseek	 = seq_lseek,
++	.release = seq_release,
++	.write   = config_proc_write
++};
++
++static struct file_operations info_proc_file_ops = {
++	.owner	 = THIS_MODULE,
++	.open	 = info_proc_open,
++	.read	 = seq_read,
++	.llseek	 = seq_lseek,
++	.release = seq_release,
++};
++
++static struct file_operations nodeinfo_proc_file_ops = {
++	.owner	 = THIS_MODULE,
++	.open	 = nodeinfo_proc_open,
++	.read	 = seq_read,
++	.llseek	 = seq_lseek,
++	.release = seq_release,
++};
++
++static struct dgrp_proc_entry dgrp_table[] = {
++	{
++		.id = DGRP_CONFIG,
++		.name = "config",
++		.mode = 0644,
++		.proc_file_ops = &config_proc_file_ops,
++	},
++	{
++		.id = DGRP_INFO,
++		.name = "info",
++		.mode = 0644,
++		.proc_file_ops = &info_proc_file_ops,
++	},
++	{
++		.id = DGRP_NODEINFO,
++		.name = "nodeinfo",
++		.mode = 0644,
++		.proc_file_ops = &nodeinfo_proc_file_ops,
++	},
++	{
++		.id = DGRP_NETDIR,
++		.name = "net",
++		.mode = 0500,
++		.child = dgrp_net_table
++	},
++	{
++		.id = DGRP_MONDIR,
++		.name = "mon",
++		.mode = 0500,
++		.child = dgrp_mon_table
++	},
++	{
++		.id = DGRP_PORTSDIR,
++		.name = "ports",
++		.mode = 0500,
++		.child = dgrp_ports_table
++	},
++	{
++		.id = DGRP_DPADIR,
++		.name = "dpa",
++		.mode = 0500,
++		.child = dgrp_dpa_table
++	}
++};
++
++static struct proc_dir_entry *net_entry_pointer;
++static struct proc_dir_entry *mon_entry_pointer;
++static struct proc_dir_entry *dpa_entry_pointer;
++static struct proc_dir_entry *ports_entry_pointer;
++
++static struct dgrp_proc_entry dgrp_net_table[] = {
++	{0}
++};
++
++static struct dgrp_proc_entry dgrp_mon_table[] = {
++	{0}
++};
++
++static struct dgrp_proc_entry dgrp_ports_table[] = {
++	{0}
++};
++
++static struct dgrp_proc_entry dgrp_dpa_table[] = {
++	{0}
++};
++
++void dgrp_unregister_proc(void)
++{
++	unregister_proc_table(dgrp_table, dgrp_proc_dir_entry);
++	net_entry_pointer = NULL;
++	mon_entry_pointer = NULL;
++	dpa_entry_pointer = NULL;
++	ports_entry_pointer = NULL;
++
++	if (dgrp_proc_dir_entry) {
++		remove_proc_entry(dgrp_proc_dir_entry->name,
++				  dgrp_proc_dir_entry->parent);
++		dgrp_proc_dir_entry = NULL;
++	}
++
++}
++
++void dgrp_register_proc(void)
++{
++	/*
++	 *	Register /proc/dgrp
++	 */
++	dgrp_proc_dir_entry = proc_create("dgrp", S_IFDIR, NULL,
++					  &dgrp_proc_file_ops);
++	register_proc_table(dgrp_table, dgrp_proc_dir_entry);
++}
++
++/*
++ * /proc/sys support
++ */
++static int dgrp_proc_match(int len, const char *name, struct proc_dir_entry *de)
++{
++	if (!de || !de->low_ino)
++		return 0;
++	if (de->namelen != len)
++		return 0;
++	return !memcmp(name, de->name, len);
++}
++
++
++/*
++ *  Scan the entries in table and add them all to /proc at the position
++ *  referred to by "root"
++ */
++static void register_proc_table(struct dgrp_proc_entry *table,
++				struct proc_dir_entry *root)
++{
++	struct proc_dir_entry *de;
++	int len;
++	mode_t mode;
++
++	for (; table->id; table++) {
++		/* Can't do anything without a proc name. */
++		if (!table->name)
++			continue;
++
++		/* Maybe we can't do anything with it... */
++		if (!table->proc_file_ops &&
++		    !table->child) {
++			pr_warn("dgrp: Can't register %s\n",
++				table->name);
++			continue;
++		}
++
++		len = strlen(table->name);
++		mode = table->mode;
++
++		de = NULL;
++		if (!table->child)
++			mode |= S_IFREG;
++		else {
++			mode |= S_IFDIR;
++			for (de = root->subdir; de; de = de->next) {
++				if (dgrp_proc_match(len, table->name, de))
++					break;
++			}
++			/* If the subdir exists already, de is non-NULL */
++		}
++
++		if (!de) {
++			de = create_proc_entry(table->name, mode, root);
++			if (!de)
++				continue;
++			de->data = (void *) table;
++			if (!table->child) {
++				de->proc_iops = &proc_inode_ops;
++				if (table->proc_file_ops)
++					de->proc_fops = table->proc_file_ops;
++				else
++					de->proc_fops = &dgrp_proc_file_ops;
++			}
++		}
++		table->de = de;
++		if (de->mode & S_IFDIR)
++			register_proc_table(table->child, de);
++
++		if (table->id == DGRP_NETDIR)
++			net_entry_pointer = de;
++
++		if (table->id == DGRP_MONDIR)
++			mon_entry_pointer = de;
++
++		if (table->id == DGRP_DPADIR)
++			dpa_entry_pointer = de;
++
++		if (table->id == DGRP_PORTSDIR)
++			ports_entry_pointer = de;
++	}
++}
++
++/*
++ * Unregister a /proc sysctl table and any subdirectories.
++ */
++static void unregister_proc_table(struct dgrp_proc_entry *table,
++				  struct proc_dir_entry *root)
++{
++	struct proc_dir_entry *de;
++	struct nd_struct *tmp;
++
++	list_for_each_entry(tmp, &nd_struct_list, list) {
++		if ((table == dgrp_net_table) && (tmp->nd_net_de)) {
++			unregister_dgrp_device(tmp->nd_net_de);
++			dgrp_remove_node_class_sysfs_files(tmp);
++		}
++
++		if ((table == dgrp_mon_table) && (tmp->nd_mon_de))
++			unregister_dgrp_device(tmp->nd_mon_de);
++
++		if ((table == dgrp_dpa_table) && (tmp->nd_dpa_de))
++			unregister_dgrp_device(tmp->nd_dpa_de);
++
++		if ((table == dgrp_ports_table) && (tmp->nd_ports_de))
++			unregister_dgrp_device(tmp->nd_ports_de);
++	}
++
++	for (; table->id; table++) {
++		de = table->de;
++
++		if (!de)
++			continue;
++		if (de->mode & S_IFDIR) {
++			if (!table->child) {
++				pr_alert("dgrp: malformed sysctl tree on free\n");
++				continue;
++			}
++			unregister_proc_table(table->child, de);
++
++	/* Don't unregister directories which still have entries */
++			if (de->subdir)
++				continue;
++		}
++
++		/* Don't unregister proc entries that are still being used.. */
++		if ((atomic_read(&de->count)) != 1) {
++			pr_alert("proc entry %s in use, not removing\n",
++				de->name);
++			continue;
++		}
++
++		remove_proc_entry(de->name, de->parent);
++		table->de = NULL;
++	}
++}
++
++static int dgrp_gen_proc_open(struct inode *inode, struct file *file)
++{
++	struct proc_dir_entry *de;
++	struct dgrp_proc_entry *entry;
++	int ret = 0;
++
++	de = (struct proc_dir_entry *) PDE(file->f_dentry->d_inode);
++	if (!de || !de->data) {
++		ret = -ENXIO;
++		goto done;
++	}
++
++	entry = (struct dgrp_proc_entry *) de->data;
++	if (!entry) {
++		ret = -ENXIO;
++		goto done;
++	}
++
++	down(&entry->excl_sem);
++
++	if (entry->excl_cnt)
++		ret = -EBUSY;
++	else
++		entry->excl_cnt++;
++
++	up(&entry->excl_sem);
++
++done:
++	return ret;
++}
++
++static int dgrp_gen_proc_close(struct inode *inode, struct file *file)
++{
++	struct proc_dir_entry *de;
++	struct dgrp_proc_entry *entry;
++
++	de = (struct proc_dir_entry *) PDE(file->f_dentry->d_inode);
++	if (!de || !de->data)
++		goto done;
++
++	entry = (struct dgrp_proc_entry *) de->data;
++	if (!entry)
++		goto done;
++
++	down(&entry->excl_sem);
++
++	if (entry->excl_cnt)
++		entry->excl_cnt = 0;
++
++	up(&entry->excl_sem);
++
++done:
++	return 0;
++}
++
++static void *config_proc_start(struct seq_file *m, loff_t *pos)
++{
++	return seq_list_start_head(&nd_struct_list, *pos);
++}
++
++static void *config_proc_next(struct seq_file *p, void *v, loff_t *pos)
++{
++	return seq_list_next(v, &nd_struct_list, pos);
++}
++
++static void config_proc_stop(struct seq_file *m, void *v)
++{
++}
++
++static int config_proc_show(struct seq_file *m, void *v)
++{
++	struct nd_struct *nd;
++	char tmp_id[4];
++
++	if (v == &nd_struct_list) {
++		seq_puts(m, "#-----------------------------------------------------------------------------\n");
++		seq_puts(m, "#                        Avail\n");
++		seq_puts(m, "# ID  Major  State       Ports\n");
++		return 0;
++	}
++
++	nd = list_entry(v, struct nd_struct, list);
++
++	ID_TO_CHAR(nd->nd_ID, tmp_id);
++
++	seq_printf(m, "  %-2.2s  %-5ld  %-10.10s  %-5d\n",
++		   tmp_id,
++		   nd->nd_major,
++		   ND_STATE_STR(nd->nd_state),
++		   nd->nd_chan_count);
++
++	return 0;
++}
++
++static const struct seq_operations proc_config_ops = {
++	.start = config_proc_start,
++	.next  = config_proc_next,
++	.stop  = config_proc_stop,
++	.show  = config_proc_show
++};
++
++static int config_proc_open(struct inode *inode, struct file *file)
++{
++	return seq_open(file, &proc_config_ops);
++}
++
++
++/*
++ *  When writing configuration information, each "record" (i.e. each
++ *  write) is treated as an independent request.  See the "parse"
++ *  description for more details.
++ */
++static ssize_t config_proc_write(struct file *file, const char __user *buffer,
++				 size_t count, loff_t *pos)
++{
++	ssize_t retval;
++	char *inbuf, *sp;
++	char *line, *ldelim;
++
++	if (count > 32768)
++		return -EINVAL;
++
++	inbuf = sp = vzalloc(count + 1);
++	if (!inbuf)
++		return -ENOMEM;
++
++	if (copy_from_user(inbuf, buffer, count)) {
++		retval = -EFAULT;
++		goto done;
++	}
++
++	inbuf[count] = 0;
++
++	ldelim = "\n";
++
++	line = strpbrk(sp, ldelim);
++	while (line) {
++		*line = 0;
++		retval = parse_write_config(sp);
++		if (retval)
++			goto done;
++
++		sp = line + 1;
++		line = strpbrk(sp, ldelim);
++	}
++
++	retval = count;
++done:
++	vfree(inbuf);
++	return retval;
++}
++
++/*
++ *  ------------------------------------------------------------------------
++ *
++ *  The following are the functions to parse input
++ *
++ *  ------------------------------------------------------------------------
++ */
++static inline char *skip_past_ws(const char *str)
++{
++	while ((*str) && !isspace(*str))
++		++str;
++
++	return skip_spaces(str);
++}
++
++static int parse_id(char **c, char *cID)
++{
++	int tmp = **c;
++
++	if (isalnum(tmp) || (tmp == '_'))
++		cID[0] = tmp;
++	else
++		return -EINVAL;
++
++	(*c)++; tmp = **c;
++
++	if (isalnum(tmp) || (tmp == '_')) {
++		cID[1] = tmp;
++		(*c)++;
++	} else
++		cID[1] = 0;
++
++	return 0;
++}
++
++static int parse_add_config(char *buf)
++{
++	char *c = buf;
++	int  retval;
++	char cID[2];
++	long ID;
++
++	c = skip_past_ws(c);
++
++	retval = parse_id(&c, cID);
++	if (retval < 0)
++		return retval;
++
++	ID = CHAR_TO_ID(cID);
++
++	c = skip_past_ws(c);
++
++	return dgrp_add_id(ID);
++}
++
++static int parse_del_config(char *buf)
++{
++	char *c = buf;
++	int  retval;
++	struct nd_struct *nd;
++	char cID[2];
++	long ID;
++	long major;
++
++	c = skip_past_ws(c);
++
++	retval = parse_id(&c, cID);
++	if (retval < 0)
++		return retval;
++
++	ID = CHAR_TO_ID(cID);
++
++	c = skip_past_ws(c);
++
++	retval = kstrtol(c, 10, &major);
++	if (retval)
++		return retval;
++
++	nd = nd_struct_get(major);
++	if (!nd)
++		return -EINVAL;
++
++	if ((nd->nd_major != major) || (nd->nd_ID != ID))
++		return -EINVAL;
++
++	return dgrp_remove_nd(nd);
++}
++
++static int parse_chg_config(char *buf)
++{
++	return -EINVAL;
++}
++
++/*
++ *  The passed character buffer represents a single configuration request.
++ *  If the first character is a "+", it is parsed as a request to add a
++ *     PortServer
++ *  If the first character is a "-", it is parsed as a request to delete a
++ *     PortServer
++ *  If the first character is a "*", it is parsed as a request to change a
++ *     PortServer
++ *  Any other character (including whitespace) causes the record to be
++ *     ignored.
++ */
++static int parse_write_config(char *buf)
++{
++	int retval;
++
++	switch (buf[0]) {
++	case '+':
++		retval = parse_add_config(buf);
++		break;
++	case '-':
++		retval = parse_del_config(buf);
++		break;
++	case '*':
++		retval = parse_chg_config(buf);
++		break;
++	default:
++		retval = -EINVAL;
++	}
++
++	return retval;
++}
++
++static int info_proc_show(struct seq_file *m, void *v)
++{
++	seq_printf(m, "version: %s\n", DIGI_VERSION);
++	seq_puts(m, "register_with_sysfs: 1\n");
++	seq_printf(m, "rawreadok: 0x%08x\t(%d)\n",
++		   dgrp_rawreadok, dgrp_rawreadok);
++	seq_printf(m, "pollrate: 0x%08x\t(%d)\n",
++		   dgrp_poll_tick, dgrp_poll_tick);
++
++	return 0;
++}
++
++static int info_proc_open(struct inode *inode, struct file *file)
++{
++	return single_open(file, info_proc_show, NULL);
++}
++
++
++static void *nodeinfo_start(struct seq_file *m, loff_t *pos)
++{
++	return seq_list_start_head(&nd_struct_list, *pos);
++}
++
++static void *nodeinfo_next(struct seq_file *p, void *v, loff_t *pos)
++{
++	return seq_list_next(v, &nd_struct_list, pos);
++}
++
++static void nodeinfo_stop(struct seq_file *m, void *v)
++{
++}
++
++static int nodeinfo_show(struct seq_file *m, void *v)
++{
++	struct nd_struct *nd;
++	char hwver[8];
++	char swver[8];
++	char tmp_id[4];
++
++	if (v == &nd_struct_list) {
++		seq_puts(m, "#-----------------------------------------------------------------------------\n");
++		seq_puts(m, "#                 HW       HW   SW\n");
++		seq_puts(m, "# ID  State       Version  ID   Version  Description\n");
++		return 0;
++	}
++
++	nd = list_entry(v, struct nd_struct, list);
++
++	ID_TO_CHAR(nd->nd_ID, tmp_id);
++
++	if (nd->nd_state == NS_READY) {
++		sprintf(hwver, "%d.%d", (nd->nd_hw_ver >> 8) & 0xff,
++			nd->nd_hw_ver & 0xff);
++		sprintf(swver, "%d.%d", (nd->nd_sw_ver >> 8) & 0xff,
++			nd->nd_sw_ver & 0xff);
++		seq_printf(m, "  %-2.2s  %-10.10s  %-7.7s  %-3d  %-7.7s  %-35.35s\n",
++			   tmp_id,
++			   ND_STATE_STR(nd->nd_state),
++			   hwver,
++			   nd->nd_hw_id,
++			   swver,
++			   nd->nd_ps_desc);
++
++	} else {
++		seq_printf(m, "  %-2.2s  %-10.10s\n",
++			   tmp_id,
++			   ND_STATE_STR(nd->nd_state));
++	}
++
++	return 0;
++}
++
++
++static const struct seq_operations nodeinfo_ops = {
++	.start = nodeinfo_start,
++	.next  = nodeinfo_next,
++	.stop  = nodeinfo_stop,
++	.show  = nodeinfo_show
++};
++
++static int nodeinfo_proc_open(struct inode *inode, struct file *file)
++{
++	return seq_open(file, &nodeinfo_ops);
++}
++
++/**
++ * dgrp_add_id() -- creates new nd struct and adds it to list
++ * @id: id of device to add
++ */
++static int dgrp_add_id(long id)
++{
++	struct nd_struct *nd;
++	int ret;
++	int i;
++
++	nd = kzalloc(sizeof(struct nd_struct), GFP_KERNEL);
++	if (!nd)
++		return -ENOMEM;
++
++	nd->nd_major = 0;
++	nd->nd_ID = id;
++
++	spin_lock_init(&nd->nd_lock);
++
++	init_waitqueue_head(&nd->nd_tx_waitq);
++	init_waitqueue_head(&nd->nd_mon_wqueue);
++	init_waitqueue_head(&nd->nd_dpa_wqueue);
++	for (i = 0; i < SEQ_MAX; i++)
++		init_waitqueue_head(&nd->nd_seq_wque[i]);
++
++	/* setup the structures to get the major number */
++	ret = dgrp_tty_init(nd);
++	if (ret)
++		goto error_out;
++
++	nd->nd_major = nd->nd_serial_ttdriver->major;
++
++	ret = nd_struct_add(nd);
++	if (ret)
++		goto error_out;
++
++	register_dgrp_device(nd, net_entry_pointer, dgrp_register_net_hook);
++	register_dgrp_device(nd, mon_entry_pointer, dgrp_register_mon_hook);
++	register_dgrp_device(nd, dpa_entry_pointer, dgrp_register_dpa_hook);
++	register_dgrp_device(nd, ports_entry_pointer,
++			      dgrp_register_ports_hook);
++
++	return 0;
++
++error_out:
++	kfree(nd);
++	return ret;
++
++}
++
++static int dgrp_remove_nd(struct nd_struct *nd)
++{
++	int ret;
++
++	/* Check to see if the selected structure is in use */
++	if (nd->nd_tty_ref_cnt)
++		return -EBUSY;
++
++	if (nd->nd_net_de) {
++		unregister_dgrp_device(nd->nd_net_de);
++		dgrp_remove_node_class_sysfs_files(nd);
++	}
++
++	if (nd->nd_mon_de)
++		unregister_dgrp_device(nd->nd_mon_de);
++
++	if (nd->nd_ports_de)
++		unregister_dgrp_device(nd->nd_ports_de);
++
++	if (nd->nd_dpa_de)
++		unregister_dgrp_device(nd->nd_dpa_de);
++
++	dgrp_tty_uninit(nd);
++
++	ret = nd_struct_del(nd);
++	if (ret)
++		return ret;
++
++	kfree(nd);
++	return 0;
++}
++
++static void register_dgrp_device(struct nd_struct *node,
++				 struct proc_dir_entry *root,
++				 void (*register_hook)(struct proc_dir_entry *de))
++{
++	char buf[3];
++	struct proc_dir_entry *de;
++
++	ID_TO_CHAR(node->nd_ID, buf);
++
++	de = create_proc_entry(buf, 0600 | S_IFREG, root);
++	if (!de)
++		return;
++
++	de->data = (void *) node;
++
++	if (register_hook)
++		register_hook(de);
++
++}
++
++static void unregister_dgrp_device(struct proc_dir_entry *de)
++{
++	if (!de)
++		return;
++
++	/* Don't unregister proc entries that are still being used.. */
++	if ((atomic_read(&de->count)) != 1) {
++		pr_alert("%s - proc entry %s in use. Not removing.\n",
++			 __func__, de->name);
++		return;
++	}
++
++	remove_proc_entry(de->name, de->parent);
++	de = NULL;
++}
+diff --git a/drivers/staging/dgrp/dgrp_sysfs.c b/drivers/staging/dgrp/dgrp_sysfs.c
+new file mode 100644
+index 000000000000..e5a3c88d016e
+--- /dev/null
++++ b/drivers/staging/dgrp/dgrp_sysfs.c
+@@ -0,0 +1,555 @@
++/*
++ * Copyright 2004 Digi International (www.digi.com)
++ *      Scott H Kilau 
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
++ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
++ * PURPOSE.  See the GNU General Public License for more details.
++ *
++ */
++
++#include "dgrp_common.h"
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++
++#define PORTSERVER_DIVIDEND 1843200
++#define SERIAL_TYPE_NORMAL      1
++#define SERIAL_TYPE_CALLOUT     2
++#define SERIAL_TYPE_XPRINT      3
++
++
++static struct class *dgrp_class;
++static struct device *dgrp_class_nodes_dev;
++static struct device *dgrp_class_global_settings_dev;
++
++
++static ssize_t dgrp_class_version_show(struct class *class,
++				       struct class_attribute *attr, char *buf)
++{
++	return snprintf(buf, PAGE_SIZE, "%s\n", DIGI_VERSION);
++}
++static CLASS_ATTR(driver_version, 0400, dgrp_class_version_show, NULL);
++
++
++static ssize_t dgrp_class_register_with_sysfs_show(struct device *c,
++						   struct device_attribute *attr,
++						   char *buf)
++{
++	return snprintf(buf, PAGE_SIZE, "1\n");
++}
++static DEVICE_ATTR(register_with_sysfs, 0400,
++		   dgrp_class_register_with_sysfs_show, NULL);
++
++
++static ssize_t dgrp_class_rawreadok_show(struct device *c,
++					 struct device_attribute *attr,
++					 char *buf)
++{
++	return snprintf(buf, PAGE_SIZE, "%d\n", dgrp_rawreadok);
++}
++static ssize_t dgrp_class_rawreadok_store(struct device *c,
++					  struct device_attribute *attr,
++					  const char *buf, size_t count)
++{
++	sscanf(buf, "0x%x\n", &dgrp_rawreadok);
++	return count;
++}
++static DEVICE_ATTR(rawreadok, 0600, dgrp_class_rawreadok_show,
++		   dgrp_class_rawreadok_store);
++
++
++static ssize_t dgrp_class_pollrate_show(struct device *c,
++					struct device_attribute *attr,
++					char *buf)
++{
++	return snprintf(buf, PAGE_SIZE, "%d\n", dgrp_poll_tick);
++}
++
++static ssize_t dgrp_class_pollrate_store(struct device *c,
++					 struct device_attribute *attr,
++					 const char *buf, size_t count)
++{
++	sscanf(buf, "0x%x\n", &dgrp_poll_tick);
++	return count;
++}
++static DEVICE_ATTR(pollrate, 0600, dgrp_class_pollrate_show,
++		   dgrp_class_pollrate_store);
++
++static struct attribute *dgrp_sysfs_global_settings_entries[] = {
++	&dev_attr_pollrate.attr,
++	&dev_attr_rawreadok.attr,
++	&dev_attr_register_with_sysfs.attr,
++	NULL
++};
++
++
++static struct attribute_group dgrp_global_settings_attribute_group = {
++	.name = NULL,
++	.attrs = dgrp_sysfs_global_settings_entries,
++};
++
++
++
++void dgrp_create_class_sysfs_files(void)
++{
++	int ret = 0;
++	int max_majors = 1U << (32 - MINORBITS);
++
++	dgrp_class = class_create(THIS_MODULE, "digi_realport");
++	ret = class_create_file(dgrp_class, &class_attr_driver_version);
++
++	dgrp_class_global_settings_dev = device_create(dgrp_class, NULL,
++		MKDEV(0, max_majors + 1), NULL, "driver_settings");
++
++	ret = sysfs_create_group(&dgrp_class_global_settings_dev->kobj,
++		&dgrp_global_settings_attribute_group);
++	if (ret) {
++		pr_alert("%s: failed to create sysfs global settings device attributes.\n",
++			__func__);
++		sysfs_remove_group(&dgrp_class_global_settings_dev->kobj,
++			&dgrp_global_settings_attribute_group);
++		return;
++	}
++
++	dgrp_class_nodes_dev = device_create(dgrp_class, NULL,
++		MKDEV(0, max_majors + 2), NULL, "nodes");
++
++}
++
++
++void dgrp_remove_class_sysfs_files(void)
++{
++	struct nd_struct *nd;
++	int max_majors = 1U << (32 - MINORBITS);
++
++	list_for_each_entry(nd, &nd_struct_list, list)
++		dgrp_remove_node_class_sysfs_files(nd);
++
++	sysfs_remove_group(&dgrp_class_global_settings_dev->kobj,
++		&dgrp_global_settings_attribute_group);
++
++	class_remove_file(dgrp_class, &class_attr_driver_version);
++
++	device_destroy(dgrp_class, MKDEV(0, max_majors + 1));
++	device_destroy(dgrp_class, MKDEV(0, max_majors + 2));
++	class_destroy(dgrp_class);
++}
++
++static ssize_t dgrp_node_state_show(struct device *c,
++				    struct device_attribute *attr, char *buf)
++{
++	struct nd_struct *nd;
++
++	if (!c)
++		return 0;
++	nd = (struct nd_struct *) dev_get_drvdata(c);
++	if (!nd)
++		return 0;
++
++	return snprintf(buf, PAGE_SIZE, "%s\n", ND_STATE_STR(nd->nd_state));
++}
++
++static DEVICE_ATTR(state, 0600, dgrp_node_state_show, NULL);
++
++static ssize_t dgrp_node_description_show(struct device *c,
++					  struct device_attribute *attr,
++					  char *buf)
++{
++	struct nd_struct *nd;
++
++	if (!c)
++		return 0;
++	nd = (struct nd_struct *) dev_get_drvdata(c);
++	if (!nd)
++		return 0;
++
++	if (nd->nd_state == NS_READY && nd->nd_ps_desc)
++		return snprintf(buf, PAGE_SIZE, "%s\n", nd->nd_ps_desc);
++	return 0;
++}
++static DEVICE_ATTR(description_info, 0600, dgrp_node_description_show, NULL);
++
++static ssize_t dgrp_node_hw_version_show(struct device *c,
++					 struct device_attribute *attr,
++					 char *buf)
++{
++	struct nd_struct *nd;
++
++	if (!c)
++		return 0;
++	nd = (struct nd_struct *) dev_get_drvdata(c);
++	if (!nd)
++		return 0;
++
++	if (nd->nd_state == NS_READY)
++		return snprintf(buf, PAGE_SIZE, "%d.%d\n",
++				(nd->nd_hw_ver >> 8) & 0xff,
++				nd->nd_hw_ver & 0xff);
++
++	return 0;
++}
++static DEVICE_ATTR(hw_version_info, 0600, dgrp_node_hw_version_show, NULL);
++
++static ssize_t dgrp_node_hw_id_show(struct device *c,
++				    struct device_attribute *attr, char *buf)
++{
++	struct nd_struct *nd;
++
++	if (!c)
++		return 0;
++	nd = (struct nd_struct *) dev_get_drvdata(c);
++	if (!nd)
++		return 0;
++
++
++	if (nd->nd_state == NS_READY)
++		return snprintf(buf, PAGE_SIZE, "%d\n", nd->nd_hw_id);
++	return 0;
++}
++static DEVICE_ATTR(hw_id_info, 0600, dgrp_node_hw_id_show, NULL);
++
++static ssize_t dgrp_node_sw_version_show(struct device *c,
++					 struct device_attribute *attr,
++					 char *buf)
++{
++	struct nd_struct *nd;
++
++	if (!c)
++		return 0;
++
++	nd = (struct nd_struct *) dev_get_drvdata(c);
++	if (!nd)
++		return 0;
++
++	if (nd->nd_state == NS_READY)
++		return snprintf(buf, PAGE_SIZE, "%d.%d\n",
++				(nd->nd_sw_ver >> 8) & 0xff,
++				nd->nd_sw_ver & 0xff);
++
++	return 0;
++}
++static DEVICE_ATTR(sw_version_info, 0600, dgrp_node_sw_version_show, NULL);
++
++
++static struct attribute *dgrp_sysfs_node_entries[] = {
++	&dev_attr_state.attr,
++	&dev_attr_description_info.attr,
++	&dev_attr_hw_version_info.attr,
++	&dev_attr_hw_id_info.attr,
++	&dev_attr_sw_version_info.attr,
++	NULL
++};
++
++
++static struct attribute_group dgrp_node_attribute_group = {
++	.name = NULL,
++	.attrs = dgrp_sysfs_node_entries,
++};
++
++
++void dgrp_create_node_class_sysfs_files(struct nd_struct *nd)
++{
++	int ret;
++	char name[10];
++
++	if (nd->nd_ID)
++		ID_TO_CHAR(nd->nd_ID, name);
++	else
++		sprintf(name, "node%ld", nd->nd_major);
++
++	nd->nd_class_dev = device_create(dgrp_class, dgrp_class_nodes_dev,
++		MKDEV(0, nd->nd_major), NULL, name);
++
++	ret = sysfs_create_group(&nd->nd_class_dev->kobj,
++				 &dgrp_node_attribute_group);
++
++	if (ret) {
++		pr_alert("%s: failed to create sysfs node device attributes.\n",
++			__func__);
++		sysfs_remove_group(&nd->nd_class_dev->kobj,
++				   &dgrp_node_attribute_group);
++		return;
++	}
++
++	dev_set_drvdata(nd->nd_class_dev, nd);
++
++}
++
++
++void dgrp_remove_node_class_sysfs_files(struct nd_struct *nd)
++{
++	if (nd->nd_class_dev) {
++		sysfs_remove_group(&nd->nd_class_dev->kobj,
++				   &dgrp_node_attribute_group);
++
++		device_destroy(dgrp_class, MKDEV(0, nd->nd_major));
++		nd->nd_class_dev = NULL;
++	}
++}
++
++
++
++static ssize_t dgrp_tty_state_show(struct device *d,
++				   struct device_attribute *attr, char *buf)
++{
++	struct un_struct *un;
++
++	if (!d)
++		return 0;
++	un = (struct un_struct *) dev_get_drvdata(d);
++	if (!un)
++		return 0;
++
++	return snprintf(buf, PAGE_SIZE, "%s\n",
++			un->un_open_count ? "Open" : "Closed");
++}
++static DEVICE_ATTR(state_info, 0600, dgrp_tty_state_show, NULL);
++
++static ssize_t dgrp_tty_baud_show(struct device *d,
++				  struct device_attribute *attr, char *buf)
++{
++	struct ch_struct *ch;
++	struct un_struct *un;
++
++	if (!d)
++		return 0;
++	un = (struct un_struct *) dev_get_drvdata(d);
++	if (!un)
++		return 0;
++	ch = un->un_ch;
++	if (!ch)
++		return 0;
++	return snprintf(buf, PAGE_SIZE, "%d\n",
++		un->un_open_count ? (PORTSERVER_DIVIDEND / ch->ch_s_brate) : 0);
++}
++static DEVICE_ATTR(baud_info, 0400, dgrp_tty_baud_show, NULL);
++
++
++static ssize_t dgrp_tty_msignals_show(struct device *d,
++				      struct device_attribute *attr, char *buf)
++{
++	struct ch_struct *ch;
++	struct un_struct *un;
++
++	if (!d)
++		return 0;
++	un = (struct un_struct *) dev_get_drvdata(d);
++	if (!un)
++		return 0;
++	ch = un->un_ch;
++	if (!ch)
++		return 0;
++
++	if (ch->ch_open_count) {
++		return snprintf(buf, PAGE_SIZE, "%s %s %s %s %s %s\n",
++			(ch->ch_s_mlast & DM_RTS) ? "RTS" : "",
++			(ch->ch_s_mlast & DM_CTS) ? "CTS" : "",
++			(ch->ch_s_mlast & DM_DTR) ? "DTR" : "",
++			(ch->ch_s_mlast & DM_DSR) ? "DSR" : "",
++			(ch->ch_s_mlast & DM_CD) ? "DCD" : "",
++			(ch->ch_s_mlast & DM_RI)  ? "RI"  : "");
++	}
++	return 0;
++}
++static DEVICE_ATTR(msignals_info, 0400, dgrp_tty_msignals_show, NULL);
++
++
++static ssize_t dgrp_tty_iflag_show(struct device *d,
++				   struct device_attribute *attr, char *buf)
++{
++	struct ch_struct *ch;
++	struct un_struct *un;
++
++	if (!d)
++		return 0;
++	un = (struct un_struct *) dev_get_drvdata(d);
++	if (!un)
++		return 0;
++	ch = un->un_ch;
++	if (!ch)
++		return 0;
++	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_s_iflag);
++}
++static DEVICE_ATTR(iflag_info, 0600, dgrp_tty_iflag_show, NULL);
++
++
++static ssize_t dgrp_tty_cflag_show(struct device *d,
++				   struct device_attribute *attr, char *buf)
++{
++	struct ch_struct *ch;
++	struct un_struct *un;
++
++	if (!d)
++		return 0;
++	un = (struct un_struct *) dev_get_drvdata(d);
++	if (!un)
++		return 0;
++	ch = un->un_ch;
++	if (!ch)
++		return 0;
++	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_s_cflag);
++}
++static DEVICE_ATTR(cflag_info, 0600, dgrp_tty_cflag_show, NULL);
++
++
++static ssize_t dgrp_tty_oflag_show(struct device *d,
++				   struct device_attribute *attr, char *buf)
++{
++	struct ch_struct *ch;
++	struct un_struct *un;
++
++	if (!d)
++		return 0;
++	un = (struct un_struct *) dev_get_drvdata(d);
++	if (!un)
++		return 0;
++	ch = un->un_ch;
++	if (!ch)
++		return 0;
++	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_s_oflag);
++}
++static DEVICE_ATTR(oflag_info, 0600, dgrp_tty_oflag_show, NULL);
++
++
++static ssize_t dgrp_tty_digi_flag_show(struct device *d,
++				       struct device_attribute *attr, char *buf)
++{
++	struct ch_struct *ch;
++	struct un_struct *un;
++
++	if (!d)
++		return 0;
++	un = (struct un_struct *) dev_get_drvdata(d);
++	if (!un)
++		return 0;
++	ch = un->un_ch;
++	if (!ch)
++		return 0;
++	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags);
++}
++static DEVICE_ATTR(digi_flag_info, 0600, dgrp_tty_digi_flag_show, NULL);
++
++
++static ssize_t dgrp_tty_rxcount_show(struct device *d,
++				     struct device_attribute *attr, char *buf)
++{
++	struct ch_struct *ch;
++	struct un_struct *un;
++
++	if (!d)
++		return 0;
++	un = (struct un_struct *) dev_get_drvdata(d);
++	if (!un)
++		return 0;
++	ch = un->un_ch;
++	if (!ch)
++		return 0;
++	return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_rxcount);
++}
++static DEVICE_ATTR(rxcount_info, 0600, dgrp_tty_rxcount_show, NULL);
++
++
++static ssize_t dgrp_tty_txcount_show(struct device *d,
++				     struct device_attribute *attr, char *buf)
++{
++	struct ch_struct *ch;
++	struct un_struct *un;
++
++	if (!d)
++		return 0;
++	un = (struct un_struct *) dev_get_drvdata(d);
++	if (!un)
++		return 0;
++	ch = un->un_ch;
++	if (!ch)
++		return 0;
++	return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_txcount);
++}
++static DEVICE_ATTR(txcount_info, 0600, dgrp_tty_txcount_show, NULL);
++
++
++static ssize_t dgrp_tty_name_show(struct device *d,
++				  struct device_attribute *attr, char *buf)
++{
++	struct nd_struct *nd;
++	struct ch_struct *ch;
++	struct un_struct *un;
++	char name[10];
++
++	if (!d)
++		return 0;
++	un = (struct un_struct *) dev_get_drvdata(d);
++	if (!un)
++		return 0;
++	ch = un->un_ch;
++	if (!ch)
++		return 0;
++	nd = ch->ch_nd;
++	if (!nd)
++		return 0;
++
++	ID_TO_CHAR(nd->nd_ID, name);
++
++	return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
++		un->un_type == SERIAL_TYPE_XPRINT ? "pr" : "tty",
++		name, ch->ch_portnum);
++}
++static DEVICE_ATTR(custom_name, 0600, dgrp_tty_name_show, NULL);
++
++
++static struct attribute *dgrp_sysfs_tty_entries[] = {
++	&dev_attr_state_info.attr,
++	&dev_attr_baud_info.attr,
++	&dev_attr_msignals_info.attr,
++	&dev_attr_iflag_info.attr,
++	&dev_attr_cflag_info.attr,
++	&dev_attr_oflag_info.attr,
++	&dev_attr_digi_flag_info.attr,
++	&dev_attr_rxcount_info.attr,
++	&dev_attr_txcount_info.attr,
++	&dev_attr_custom_name.attr,
++	NULL
++};
++
++
++static struct attribute_group dgrp_tty_attribute_group = {
++	.name = NULL,
++	.attrs = dgrp_sysfs_tty_entries,
++};
++
++
++void dgrp_create_tty_sysfs(struct un_struct *un, struct device *c)
++{
++	int ret;
++
++	ret = sysfs_create_group(&c->kobj, &dgrp_tty_attribute_group);
++	if (ret) {
++		pr_alert("%s: failed to create sysfs tty device attributes.\n",
++			__func__);
++		sysfs_remove_group(&c->kobj, &dgrp_tty_attribute_group);
++		return;
++	}
++
++	dev_set_drvdata(c, un);
++
++}
++
++
++void dgrp_remove_tty_sysfs(struct device *c)
++{
++	sysfs_remove_group(&c->kobj, &dgrp_tty_attribute_group);
++}
+diff --git a/drivers/staging/dgrp/dgrp_tty.c b/drivers/staging/dgrp/dgrp_tty.c
+new file mode 100644
+index 000000000000..7d7de873870c
+--- /dev/null
++++ b/drivers/staging/dgrp/dgrp_tty.c
+@@ -0,0 +1,3331 @@
++/*
++ *
++ * Copyright 1999 Digi International (www.digi.com)
++ *     Gene Olson    
++ *     James Puzzo   
++ *     Jeff Randall
++ *     Scott Kilau   
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
++ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
++ * PURPOSE.  See the GNU General Public License for more details.
++ *
++ */
++
++/*
++ *
++ *  Filename:
++ *
++ *     dgrp_tty.c
++ *
++ *  Description:
++ *
++ *     This file implements the tty driver functionality for the
++ *     RealPort driver software.
++ *
++ *  Author:
++ *
++ *     James A. Puzzo
++ *     Ann-Marie Westgate
++ *
++ */
++
++#include 
++#include 
++#include 
++#include 
++
++#include "dgrp_common.h"
++
++#ifndef _POSIX_VDISABLE
++#define   _POSIX_VDISABLE ('\0')
++#endif
++
++/*
++ *	forward declarations
++ */
++
++static void drp_param(struct ch_struct *);
++static void dgrp_tty_close(struct tty_struct *, struct file *);
++
++/* ioctl helper functions */
++static int set_modem_info(struct ch_struct *, unsigned int, unsigned int *);
++static int get_modem_info(struct ch_struct *, unsigned int *);
++static void dgrp_set_custom_speed(struct ch_struct *, int);
++static int dgrp_tty_digigetedelay(struct tty_struct *, int *);
++static int dgrp_tty_digisetedelay(struct tty_struct *, int *);
++static int dgrp_send_break(struct ch_struct *, int);
++
++static ushort  tty_to_ch_flags(struct tty_struct *, char);
++static tcflag_t ch_to_tty_flags(unsigned short, char);
++
++static void dgrp_tty_input_start(struct tty_struct *);
++static void dgrp_tty_input_stop(struct tty_struct *);
++
++static void drp_wmove(struct ch_struct *, int, void*, int);
++
++static int dgrp_tty_open(struct tty_struct *, struct file *);
++static void dgrp_tty_close(struct tty_struct *, struct file *);
++static int dgrp_tty_write(struct tty_struct *, const unsigned char *, int);
++static int dgrp_tty_write_room(struct tty_struct *);
++static void dgrp_tty_flush_buffer(struct tty_struct *);
++static int dgrp_tty_chars_in_buffer(struct tty_struct *);
++static int dgrp_tty_ioctl(struct tty_struct *, unsigned int, unsigned long);
++static void dgrp_tty_set_termios(struct tty_struct *, struct ktermios *);
++static void dgrp_tty_stop(struct tty_struct *);
++static void dgrp_tty_start(struct tty_struct *);
++static void dgrp_tty_throttle(struct tty_struct *);
++static void dgrp_tty_unthrottle(struct tty_struct *);
++static void dgrp_tty_hangup(struct tty_struct *);
++static int dgrp_tty_put_char(struct tty_struct *, unsigned char);
++static int dgrp_tty_tiocmget(struct tty_struct *);
++static int dgrp_tty_tiocmset(struct tty_struct *, unsigned int, unsigned int);
++static int dgrp_tty_send_break(struct tty_struct *, int);
++static void dgrp_tty_send_xchar(struct tty_struct *, char);
++
++/*
++ *	tty defines
++ */
++#define	SERIAL_TYPE_NORMAL	1
++#define	SERIAL_TYPE_CALLOUT	2
++#define	SERIAL_TYPE_XPRINT	3
++
++
++/*
++ *	tty globals/statics
++ */
++
++
++#define PORTSERVER_DIVIDEND	1843200
++
++/*
++ *  Default transparent print information.
++ */
++static struct digi_struct digi_init = {
++	.digi_flags   = DIGI_COOK,	/* Flags			*/
++	.digi_maxcps  = 100,		/* Max CPS			*/
++	.digi_maxchar = 50,		/* Max chars in print queue	*/
++	.digi_bufsize = 100,		/* Printer buffer size		*/
++	.digi_onlen   = 4,		/* size of printer on string	*/
++	.digi_offlen  = 4,		/* size of printer off string	*/
++	.digi_onstr   = "\033[5i",	/* ANSI printer on string	*/
++	.digi_offstr  = "\033[4i",	/* ANSI printer off string	*/
++	.digi_term    = "ansi"		/* default terminal type	*/
++};
++
++/*
++ *	Define a local default termios struct. All ports will be created
++ *	with this termios initially.
++ *
++ *	This defines a raw port at 9600 baud, 8 data bits, no parity,
++ *	1 stop bit.
++ */
++static struct ktermios DefaultTermios = {
++	.c_iflag = (ICRNL | IXON),
++	.c_oflag = (OPOST | ONLCR),
++	.c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
++	.c_lflag = (ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL
++		    | ECHOKE | IEXTEN),
++	.c_cc    = INIT_C_CC,
++	.c_line  = 0,
++};
++
++/* Define our tty operations struct */
++static const struct tty_operations dgrp_tty_ops = {
++	.open            = dgrp_tty_open,
++	.close           = dgrp_tty_close,
++	.write           = dgrp_tty_write,
++	.write_room      = dgrp_tty_write_room,
++	.flush_buffer    = dgrp_tty_flush_buffer,
++	.chars_in_buffer = dgrp_tty_chars_in_buffer,
++	.flush_chars     = NULL,
++	.ioctl           = dgrp_tty_ioctl,
++	.set_termios     = dgrp_tty_set_termios,
++	.stop            = dgrp_tty_stop,
++	.start           = dgrp_tty_start,
++	.throttle        = dgrp_tty_throttle,
++	.unthrottle      = dgrp_tty_unthrottle,
++	.hangup          = dgrp_tty_hangup,
++	.put_char        = dgrp_tty_put_char,
++	.tiocmget        = dgrp_tty_tiocmget,
++	.tiocmset        = dgrp_tty_tiocmset,
++	.break_ctl       = dgrp_tty_send_break,
++	.send_xchar      = dgrp_tty_send_xchar
++};
++
++
++static int calc_baud_rate(struct un_struct *un)
++{
++	int i;
++	int brate;
++
++	struct baud_rates {
++		unsigned int rate;
++		unsigned int cflag;
++	};
++
++	static struct baud_rates baud_rates[] = {
++		{ 921600, B921600 },
++		{ 460800, B460800 },
++		{ 230400, B230400 },
++		{ 115200, B115200 },
++		{  57600, B57600  },
++		{  38400, B38400  },
++		{  19200, B19200  },
++		{   9600, B9600   },
++		{   4800, B4800   },
++		{   2400, B2400   },
++		{   1200, B1200   },
++		{    600, B600    },
++		{    300, B300    },
++		{    200, B200    },
++		{    150, B150    },
++		{    134, B134    },
++		{    110, B110    },
++		{     75, B75     },
++		{     50, B50     },
++		{      0, B9600  }
++	};
++
++	brate = C_BAUD(un->un_tty);
++
++	for (i = 0; baud_rates[i].rate; i++) {
++		if (baud_rates[i].cflag == brate)
++			break;
++	}
++
++	return baud_rates[i].rate;
++}
++
++static int calc_fastbaud_rate(struct un_struct *un, struct ktermios *uts)
++{
++	int i;
++	int brate;
++
++	ulong bauds[2][16] = {
++		{ /* fastbaud*/
++			0,      57600,	 76800,	115200,
++			131657, 153600, 230400, 460800,
++			921600, 1200,   1800,	2400,
++			4800,   9600,	19200,	38400 },
++		{ /* fastbaud & CBAUDEX */
++			0,      57600,	115200,	230400,
++			460800, 150,    200,    921600,
++			600,    1200,   1800,	2400,
++			4800,   9600,	19200,	38400 }
++	};
++
++	brate = C_BAUD(un->un_tty) & 0xff;
++
++	i = (uts->c_cflag & CBAUDEX) ? 1 : 0;
++
++
++	if ((i >= 0) && (i < 2) && (brate >= 0) && (brate < 16))
++		brate = bauds[i][brate];
++	else
++		brate = 0;
++
++	return brate;
++}
++
++/**
++ * drp_param() -- send parameter values to be sent to the node
++ * @ch: channel structure of port to modify
++ *
++ * Interprets the tty and modem changes made by an application
++ * program (by examining the termios structures) and sets up
++ * parameter values to be sent to the node.
++ */
++static void drp_param(struct ch_struct *ch)
++{
++	struct nd_struct *nd;
++	struct un_struct *un;
++	int   brate;
++	int   mflow;
++	int   xflag;
++	int   iflag;
++	struct ktermios *tts, *pts, *uts;
++
++	nd = ch->ch_nd;
++
++	/*
++	 *  If the terminal device is open, use it to set up all tty
++	 *  modes and functions.  Otherwise use the printer device.
++	 */
++
++	if (ch->ch_tun.un_open_count) {
++
++		un = &ch->ch_tun;
++		tts = &ch->ch_tun.un_tty->termios;
++
++		/*
++		 *  If both devices are open, copy critical line
++		 *  parameters from the tty device to the printer,
++		 *  so that if the tty is closed, the printer will
++		 *  continue without disruption.
++		 */
++
++		if (ch->ch_pun.un_open_count) {
++
++			pts = &ch->ch_pun.un_tty->termios;
++
++			pts->c_cflag ^=
++				(pts->c_cflag ^ tts->c_cflag) &
++				(CBAUD  | CSIZE | CSTOPB | CREAD | PARENB |
++				 PARODD | HUPCL | CLOCAL);
++
++			pts->c_iflag ^=
++				(pts->c_iflag ^ tts->c_iflag) &
++				(IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK |
++				 ISTRIP | IXON   | IXANY  | IXOFF);
++
++			pts->c_cc[VSTART] = tts->c_cc[VSTART];
++			pts->c_cc[VSTOP] = tts->c_cc[VSTOP];
++		}
++	} else if (ch->ch_pun.un_open_count == 0) {
++		pr_warn("%s - ch_pun.un_open_count shouldn't be 0\n",
++		       __func__);
++		return;
++	} else {
++		un = &ch->ch_pun;
++	}
++
++	uts = &un->un_tty->termios;
++
++	/*
++	 * Determine if FAST writes can be performed.
++	 */
++
++	if ((ch->ch_digi.digi_flags & DIGI_COOK) != 0 &&
++	    (ch->ch_tun.un_open_count != 0)  &&
++	    !((un->un_tty)->ldisc->ops->flags & LDISC_FLAG_DEFINED) &&
++	    !(L_XCASE(un->un_tty))) {
++		ch->ch_flag |= CH_FAST_WRITE;
++	} else {
++		ch->ch_flag &= ~CH_FAST_WRITE;
++	}
++
++	/*
++	 *  If FAST writes can be performed, and OPOST is on in the
++	 *  terminal device, do OPOST handling in the server.
++	 */
++
++	if ((ch->ch_flag & CH_FAST_WRITE) &&
++	      O_OPOST(un->un_tty) != 0) {
++		int oflag = tty_to_ch_flags(un->un_tty, 'o');
++
++		/* add to ch_ocook any processing flags set in the termio */
++		ch->ch_ocook |= oflag & (OF_OLCUC |
++					 OF_ONLCR |
++					 OF_OCRNL |
++					 OF_ONLRET |
++					 OF_TABDLY);
++
++		/*
++		 * the hpux driver clears any flags set in ch_ocook
++		 * from the termios oflag.  It is STILL reported though
++		 * by a TCGETA
++		 */
++
++		oflag = ch_to_tty_flags(ch->ch_ocook, 'o');
++		uts->c_oflag &= ~oflag;
++
++	} else {
++		/* clear the ch->ch_ocook flag */
++		int oflag = ch_to_tty_flags(ch->ch_ocook, 'o');
++		uts->c_oflag |= oflag;
++		ch->ch_ocook = 0;
++	}
++
++	ch->ch_oflag = ch->ch_ocook;
++
++
++	ch->ch_flag &= ~CH_FAST_READ;
++
++	/*
++	 *  Generate channel flags
++	 */
++
++	if (C_BAUD(un->un_tty) == B0) {
++		if (!(ch->ch_flag & CH_BAUD0)) {
++			/* TODO : the HPUX driver flushes line */
++			/* TODO : discipline, I assume I don't have to */
++
++			ch->ch_tout = ch->ch_tin;
++			ch->ch_rout = ch->ch_rin;
++
++			ch->ch_break_time = 0;
++
++			ch->ch_send |= RR_TX_FLUSH | RR_RX_FLUSH;
++
++			ch->ch_mout &= ~(DM_DTR | DM_RTS);
++
++			ch->ch_flag |= CH_BAUD0;
++		}
++	} else if (ch->ch_custom_speed) {
++		ch->ch_brate = PORTSERVER_DIVIDEND / ch->ch_custom_speed ;
++
++		if (ch->ch_flag & CH_BAUD0) {
++			ch->ch_mout |= DM_DTR | DM_RTS;
++
++			ch->ch_flag &= ~CH_BAUD0;
++		}
++	} else {
++		/*
++		 * Baud rate mapping.
++		 *
++		 * If FASTBAUD isn't on, we can scan the new baud rate list
++		 * as required.
++		 *
++		 * However, if FASTBAUD is on, we must go to the old
++		 * baud rate mapping that existed many many moons ago,
++		 * for compatibility reasons.
++		 */
++
++		if (!(ch->ch_digi.digi_flags & DIGI_FAST))
++			brate = calc_baud_rate(un);
++		else
++			brate = calc_fastbaud_rate(un, uts);
++
++		if (brate == 0)
++			brate = 9600;
++
++		ch->ch_brate = PORTSERVER_DIVIDEND / brate;
++
++		if (ch->ch_flag & CH_BAUD0) {
++			ch->ch_mout |= DM_DTR | DM_RTS;
++
++			ch->ch_flag &= ~CH_BAUD0;
++		}
++	}
++
++	/*
++	 *  Generate channel cflags from the termio.
++	 */
++
++	ch->ch_cflag = tty_to_ch_flags(un->un_tty, 'c');
++
++	/*
++	 *  Generate channel iflags from the termio.
++	 */
++
++	iflag = (int) tty_to_ch_flags(un->un_tty, 'i');
++
++	if (START_CHAR(un->un_tty) == _POSIX_VDISABLE ||
++	    STOP_CHAR(un->un_tty) == _POSIX_VDISABLE) {
++		iflag &= ~(IF_IXON | IF_IXANY | IF_IXOFF);
++	}
++
++	ch->ch_iflag = iflag;
++
++	/*
++	 *  Generate flow control characters
++	 */
++
++	/*
++	 * From the POSIX.1 spec (7.1.2.6): "If {_POSIX_VDISABLE}
++	 * is defined for the terminal device file, and the value
++	 * of one of the changable special control characters (see
++	 * 7.1.1.9) is {_POSIX_VDISABLE}, that function shall be
++	 * disabled, that is, no input data shall be recognized as
++	 * the disabled special character."
++	 *
++	 * OK, so we don't ever assign S/DXB XON or XOFF to _POSIX_VDISABLE.
++	 */
++
++	if (uts->c_cc[VSTART] != _POSIX_VDISABLE)
++		ch->ch_xon = uts->c_cc[VSTART];
++	if (uts->c_cc[VSTOP] != _POSIX_VDISABLE)
++		ch->ch_xoff = uts->c_cc[VSTOP];
++
++	ch->ch_lnext = (uts->c_cc[VLNEXT] == _POSIX_VDISABLE ? 0 :
++			uts->c_cc[VLNEXT]);
++
++	/*
++	 * Also, if either c_cc[START] or c_cc[STOP] is set to
++	 * _POSIX_VDISABLE, we can't really do software flow
++	 * control--in either direction--so we turn it off as
++	 * far as S/DXB is concerned.  In essence, if you disable
++	 * one, you disable the other too.
++	 */
++	if ((uts->c_cc[VSTART] == _POSIX_VDISABLE) ||
++	    (uts->c_cc[VSTOP] == _POSIX_VDISABLE))
++		ch->ch_iflag &= ~(IF_IXOFF | IF_IXON);
++
++	/*
++	 *  Update xflags.
++	 */
++
++	xflag = 0;
++
++	if (ch->ch_digi.digi_flags & DIGI_AIXON)
++		xflag = XF_XIXON;
++
++	if ((ch->ch_xxon == _POSIX_VDISABLE) ||
++	    (ch->ch_xxoff == _POSIX_VDISABLE))
++		xflag &= ~XF_XIXON;
++
++	ch->ch_xflag = xflag;
++
++
++	/*
++	 *  Figure effective DCD value.
++	 */
++
++	if (C_CLOCAL(un->un_tty))
++		ch->ch_flag |= CH_CLOCAL;
++	else
++		ch->ch_flag &= ~CH_CLOCAL;
++
++	/*
++	 *  Check modem signals
++	 */
++
++	dgrp_carrier(ch);
++
++	/*
++	 *  Get hardware handshake value.
++	 */
++
++	mflow = 0;
++
++	if (C_CRTSCTS(un->un_tty))
++		mflow |= (DM_RTS | DM_CTS);
++
++	if (ch->ch_digi.digi_flags & RTSPACE)
++		mflow |= DM_RTS;
++
++	if (ch->ch_digi.digi_flags & DTRPACE)
++		mflow |= DM_DTR;
++
++	if (ch->ch_digi.digi_flags & CTSPACE)
++		mflow |= DM_CTS;
++
++	if (ch->ch_digi.digi_flags & DSRPACE)
++		mflow |= DM_DSR;
++
++	if (ch->ch_digi.digi_flags & DCDPACE)
++		mflow |= DM_CD;
++
++	if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE)
++		mflow |= DM_RTS_TOGGLE;
++
++	ch->ch_mflow = mflow;
++
++	/*
++	 *  Send the changes to the server.
++	 */
++
++	ch->ch_flag |= CH_PARAM;
++	(ch->ch_nd)->nd_tx_work = 1;
++
++	if (waitqueue_active(&ch->ch_flag_wait))
++		wake_up_interruptible(&ch->ch_flag_wait);
++}
++
++/*
++ * This function is just used as a callback for timeouts
++ * waiting on the ch_sleep flag.
++ */
++static void wake_up_drp_sleep_timer(unsigned long ptr)
++{
++	struct ch_struct *ch = (struct ch_struct *) ptr;
++	if (ch)
++		wake_up(&ch->ch_sleep);
++}
++
++
++/*
++ * Set up our own sleep that can't be cancelled
++ * until our timeout occurs.
++ */
++static void drp_my_sleep(struct ch_struct *ch)
++{
++	struct timer_list drp_wakeup_timer;
++	DECLARE_WAITQUEUE(wait, current);
++
++	/*
++	 * First make sure we're ready to receive the wakeup.
++	 */
++
++	add_wait_queue(&ch->ch_sleep, &wait);
++	current->state = TASK_UNINTERRUPTIBLE;
++
++	/*
++	 * Since we are uninterruptible, set a timer to
++	 * unset the uninterruptable state in 1 second.
++	 */
++
++	init_timer(&drp_wakeup_timer);
++	drp_wakeup_timer.function = wake_up_drp_sleep_timer;
++	drp_wakeup_timer.data = (unsigned long) ch;
++	drp_wakeup_timer.expires = jiffies + (1 * HZ);
++	add_timer(&drp_wakeup_timer);
++
++	schedule();
++
++	del_timer(&drp_wakeup_timer);
++
++	remove_wait_queue(&ch->ch_sleep, &wait);
++}
++
++/*
++ * dgrp_tty_open()
++ *
++ * returns:
++ *    -EBUSY    - this is a callout device and the normal device is active
++ *              - there is an error in opening the tty
++ *    -ENODEV   - the channel does not exist
++ *    -EAGAIN   - we are in the middle of hanging up or closing
++ *              - IMMEDIATE_OPEN fails
++ *    -ENXIO or -EAGAIN
++ *              - if the port is outside physical range
++ *    -EINTR    - the open is interrupted
++ *
++ */
++static int dgrp_tty_open(struct tty_struct *tty, struct file *file)
++{
++	int    retval = 0;
++	struct nd_struct  *nd;
++	struct ch_struct *ch;
++	struct un_struct  *un;
++	int    port;
++	int    delay_error;
++	int    otype;
++	int    unf;
++	int    wait_carrier;
++	int    category;
++	int    counts_were_incremented = 0;
++	ulong lock_flags;
++	DECLARE_WAITQUEUE(wait, current);
++
++	/*
++	 * Do some initial checks to see if the node and port exist
++	 */
++
++	nd = nd_struct_get(MAJOR(tty_devnum(tty)));
++	port = PORT_NUM(MINOR(tty_devnum(tty)));
++	category = OPEN_CATEGORY(MINOR(tty_devnum(tty)));
++
++	if (!nd)
++		return -ENODEV;
++
++	if (port >= CHAN_MAX)
++		return -ENODEV;
++
++	/*
++	 *  The channel exists.
++	 */
++
++	ch = nd->nd_chan + port;
++
++	un = IS_PRINT(MINOR(tty_devnum(tty))) ? &ch->ch_pun : &ch->ch_tun;
++	un->un_tty = tty;
++	tty->driver_data = un;
++
++	/*
++	 * If we are in the middle of hanging up,
++	 * then return an error
++	 */
++	if (tty_hung_up_p(file)) {
++		retval = ((un->un_flag & UN_HUP_NOTIFY) ?
++			   -EAGAIN : -ERESTARTSYS);
++		goto done;
++	}
++
++	/*
++	 * If the port is in the middle of closing, then block
++	 * until it is done, then try again.
++	 */
++	retval = wait_event_interruptible(un->un_close_wait,
++			((un->un_flag & UN_CLOSING) == 0));
++
++	if (retval)
++		goto done;
++
++	/*
++	 * If the port is in the middle of a reopen after a network disconnect,
++	 * wait until it is done, then try again.
++	 */
++	retval = wait_event_interruptible(ch->ch_flag_wait,
++			((ch->ch_flag & CH_PORT_GONE) == 0));
++
++	if (retval)
++		goto done;
++
++	/*
++	 * If this is a callout device, then just make sure the normal
++	 * device isn't being used.
++	 */
++
++	if (tty->driver->subtype == SERIAL_TYPE_CALLOUT) {
++		if (un->un_flag & UN_NORMAL_ACTIVE) {
++			retval = -EBUSY;
++			goto done;
++		} else {
++			un->un_flag |= UN_CALLOUT_ACTIVE;
++		}
++	}
++
++	/*
++	 *  Loop waiting until the open can be successfully completed.
++	 */
++
++	spin_lock_irqsave(&nd->nd_lock, lock_flags);
++
++	nd->nd_tx_work = 1;
++
++	for (;;) {
++		wait_carrier = 0;
++
++		/*
++		 * Determine the open type from the flags provided.
++		 */
++
++		/*
++		 * If the port is not enabled, then exit
++		 */
++		if (test_bit(TTY_IO_ERROR, &tty->flags)) {
++			/* there was an error in opening the tty */
++			if (un->un_flag & UN_CALLOUT_ACTIVE)
++				retval = -EBUSY;
++			else
++				un->un_flag |= UN_NORMAL_ACTIVE;
++			goto unlock;
++		}
++
++		if (file->f_flags & O_NONBLOCK) {
++
++			/*
++			 * if the O_NONBLOCK is set, errors on read and write
++			 * must return -EAGAIN immediately and NOT sleep
++			 * on the waitqs.
++			 */
++			otype = OTYPE_IMMEDIATE;
++			delay_error = -EAGAIN;
++
++		} else if (!OPEN_WAIT_AVAIL(category) ||
++			  (file->f_flags & O_NDELAY) != 0) {
++			otype = OTYPE_IMMEDIATE;
++			delay_error = -EBUSY;
++
++		} else if (!OPEN_WAIT_CARRIER(category) ||
++			  ((ch->ch_digi.digi_flags & DIGI_FORCEDCD) != 0) ||
++			  C_CLOCAL(tty)) {
++			otype = OTYPE_PERSISTENT;
++			delay_error = 0;
++
++		} else {
++			otype = OTYPE_INCOMING;
++			delay_error = 0;
++		}
++
++		/*
++		 * Handle port currently outside physical port range.
++		 */
++
++		if (port >= nd->nd_chan_count) {
++			if (otype == OTYPE_IMMEDIATE) {
++				retval = (nd->nd_state == NS_READY) ?
++						-ENXIO : -EAGAIN;
++				goto unlock;
++			}
++		}
++
++		/*
++		 *  Handle port not currently open.
++		 */
++
++		else if (ch->ch_open_count == 0) {
++			/*
++			 * Return an error when an Incoming Open
++			 * response indicates the port is busy.
++			 */
++
++			if (ch->ch_open_error != 0 && otype == ch->ch_otype) {
++				retval = (ch->ch_open_error <= 2) ?
++					  delay_error : -ENXIO ;
++				goto unlock;
++			}
++
++			/*
++			 * Fail any new Immediate open if we do not have
++			 * a normal connection to the server.
++			 */
++
++			if (nd->nd_state != NS_READY &&
++			    otype == OTYPE_IMMEDIATE) {
++				retval = -EAGAIN;
++				goto unlock;
++			}
++
++			/*
++			 * If a Realport open of the correct type has
++			 * succeeded, complete the open.
++			 */
++
++			if (ch->ch_state == CS_READY && ch->ch_otype == otype)
++				break;
++		}
++
++		/*
++		 * Handle port already open and active as a device
++		 * of same category.
++		 */
++
++		else if ((ch->ch_category == category) ||
++			  IS_PRINT(MINOR(tty_devnum(tty)))) {
++			/*
++			 * Fail if opening the device now would
++			 * violate exclusive use.
++			 */
++			unf = ch->ch_tun.un_flag | ch->ch_pun.un_flag;
++
++			if ((file->f_flags & O_EXCL) || (unf & UN_EXCL)) {
++				retval = -EBUSY;
++				goto unlock;
++			}
++
++			/*
++			 * If the open device is in the hangup state, all
++			 * system calls fail except close().
++			 */
++
++			/* TODO : check on hangup_p calls */
++
++			if (ch->ch_flag & CH_HANGUP) {
++				retval = -ENXIO;
++				goto unlock;
++			}
++
++			/*
++			 * If the port is ready, and carrier is ignored
++			 * or present, then complete the open.
++			 */
++
++			if (ch->ch_state == CS_READY &&
++			    (otype != OTYPE_INCOMING ||
++			    ch->ch_flag & CH_VIRT_CD))
++				break;
++
++			wait_carrier = 1;
++		}
++
++		/*
++		 *  Handle port active with a different category device.
++		 */
++
++		else {
++			if (otype == OTYPE_IMMEDIATE) {
++				retval = delay_error;
++				goto unlock;
++			}
++		}
++
++		/*
++		 * Wait until conditions change, then take another
++		 * try at the open.
++		 */
++
++		ch->ch_wait_count[otype]++;
++
++		if (wait_carrier)
++			ch->ch_wait_carrier++;
++
++		/*
++		 * Prepare the task to accept the wakeup, then
++		 * release our locks and release control.
++		 */
++
++		add_wait_queue(&ch->ch_flag_wait, &wait);
++		current->state = TASK_INTERRUPTIBLE;
++
++		spin_unlock_irqrestore(&nd->nd_lock, lock_flags);
++
++		/*
++		 * Give up control, we'll come back if we're
++		 * interrupted or are woken up.
++		 */
++		schedule();
++		remove_wait_queue(&ch->ch_flag_wait, &wait);
++
++		spin_lock_irqsave(&nd->nd_lock, lock_flags);
++
++		current->state = TASK_RUNNING;
++
++		ch->ch_wait_count[otype]--;
++
++		if (wait_carrier)
++			ch->ch_wait_carrier--;
++
++		nd->nd_tx_work = 1;
++
++		if (signal_pending(current)) {
++			retval = -EINTR;
++			goto unlock;
++		}
++	} /* end for(;;) */
++
++	/*
++	 *  The open has succeeded.  No turning back.
++	 */
++	counts_were_incremented = 1;
++	un->un_open_count++;
++	ch->ch_open_count++;
++
++	/*
++	 * Initialize the channel, if it's not already open.
++	 */
++
++	if (ch->ch_open_count == 1) {
++		ch->ch_flag = 0;
++		ch->ch_inwait = 0;
++		ch->ch_category = category;
++		ch->ch_pscan_state = 0;
++
++		/* TODO : find out what PS-1 bug Gene was referring to */
++		/* TODO : in the following comment. */
++
++		ch->ch_send = RR_TX_START | RR_RX_START;  /* PS-1 bug */
++
++		if (C_CLOCAL(tty) ||
++		    ch->ch_s_mlast & DM_CD ||
++		    ch->ch_digi.digi_flags & DIGI_FORCEDCD)
++			ch->ch_flag |= CH_VIRT_CD;
++		else if (OPEN_FORCES_CARRIER(category))
++			ch->ch_flag |= CH_VIRT_CD;
++
++	}
++
++	/*
++	 *  Initialize the unit, if it is not already open.
++	 */
++
++	if (un->un_open_count == 1) {
++		/*
++		 *  Since all terminal options are always sticky in Linux,
++		 *  we don't need the UN_STICKY flag to be handled specially.
++		 */
++		/* clears all the digi flags, leaves serial flags */
++		un->un_flag &= ~UN_DIGI_MASK;
++
++		if (file->f_flags & O_EXCL)
++			un->un_flag |= UN_EXCL;
++
++		/* TODO : include "session" and "pgrp" */
++
++		/*
++		 *  In Linux, all terminal parameters are intended to be sticky.
++		 *  as a result, we "remove" the code which once reset the ports
++		 *  to sane values.
++		 */
++
++		drp_param(ch);
++
++	}
++
++	un->un_flag |= UN_INITIALIZED;
++
++	retval = 0;
++
++unlock:
++
++	spin_unlock_irqrestore(&nd->nd_lock, lock_flags);
++
++done:
++	/*
++	 * Linux does a close for every open, even failed ones!
++	 */
++	if (!counts_were_incremented) {
++		un->un_open_count++;
++		ch->ch_open_count++;
++	}
++
++	if (retval)
++		dev_err(tty->dev, "tty open bad return (%i)\n", retval);
++
++	return retval;
++}
++
++
++
++
++/*
++ * dgrp_tty_close() -- close function for tty_operations
++ */
++static void dgrp_tty_close(struct tty_struct *tty, struct file *file)
++{
++	struct ch_struct *ch;
++	struct un_struct *un;
++	struct nd_struct *nd;
++	int	tpos;
++	int	port;
++	int	err = 0;
++	int	s = 0;
++	ulong  waketime;
++	ulong  lock_flags;
++	int sent_printer_offstr = 0;
++
++	port = PORT_NUM(MINOR(tty_devnum(tty)));
++
++	un = tty->driver_data;
++
++	if (!un)
++		return;
++
++	ch = un->un_ch;
++
++	if (!ch)
++		return;
++
++	nd = ch->ch_nd;
++
++	if (!nd)
++		return;
++
++	spin_lock_irqsave(&nd->nd_lock, lock_flags);
++
++
++	/* Used to be on channel basis, now we check on a unit basis. */
++	if (un->un_open_count != 1)
++		goto unlock;
++
++	/*
++	 * OK, its the last close on the unit
++	 */
++	un->un_flag |= UN_CLOSING;
++
++	/*
++	 * Notify the discipline to only process XON/XOFF characters.
++	 */
++	tty->closing = 1;
++
++	/*
++	 * Wait for output to drain only if this is
++	 * the last close against the channel
++	 */
++
++	if (ch->ch_open_count == 1) {
++		/*
++		 * If its the print device, we need to ensure at all costs that
++		 * the offstr will fit. If it won't, flush our tbuf.
++		 */
++		if (IS_PRINT(MINOR(tty_devnum(tty))) &&
++		    (((ch->ch_tout - ch->ch_tin - 1) & TBUF_MASK) <
++		    ch->ch_digi.digi_offlen))
++			ch->ch_tin = ch->ch_tout;
++
++		/*
++		 * Turn off the printer.  Don't bother checking to see if its
++		 * IS_PRINT... Since this is the last close the flag is going
++		 * to be cleared, so we MUST make sure the offstr gets inserted
++		 * into tbuf.
++		 */
++
++		if ((ch->ch_flag & CH_PRON) != 0) {
++			drp_wmove(ch, 0, ch->ch_digi.digi_offstr,
++				  ch->ch_digi.digi_offlen);
++			ch->ch_flag &= ~CH_PRON;
++			sent_printer_offstr = 1;
++		}
++	}
++
++	/*
++	 *  Wait until either the output queue has drained, or we see
++	 *  absolutely no progress for 15 seconds.
++	 */
++
++	tpos = ch->ch_s_tpos;
++
++	waketime = jiffies + 15 * HZ;
++
++	for (;;) {
++
++		/*
++		 *  Make sure the port still exists.
++		 */
++
++		if (port >= nd->nd_chan_count) {
++			err = 1;
++			break;
++		}
++
++		if (signal_pending(current)) {
++			err = 1;
++			break;
++		}
++
++		/*
++		 * If the port is idle (not opened on the server), we have
++		 * no way of draining/flushing/closing the port on that server.
++		 * So break out of loop.
++		 */
++		if (ch->ch_state == CS_IDLE)
++			break;
++
++		nd->nd_tx_work = 1;
++
++		/*
++		 *  Exit if the queues for this unit are empty,
++		 *  and either the other unit is still open or all
++		 *  data has drained.
++		 */
++
++		if ((un->un_tty)->ops->chars_in_buffer ?
++		    ((un->un_tty)->ops->chars_in_buffer)(un->un_tty) == 0 : 1) {
++
++			/*
++			 * We don't need to wait for a buffer to drain
++			 * if the other unit is open.
++			 */
++
++			if (ch->ch_open_count != un->un_open_count)
++				break;
++
++			/*
++			 *  The wait is complete when all queues are
++			 *  drained, and any break in progress is complete.
++			 */
++
++			if (ch->ch_tin == ch->ch_tout &&
++			    ch->ch_s_tin == ch->ch_s_tpos &&
++			    (ch->ch_send & RR_TX_BREAK) == 0) {
++				break;
++			}
++		}
++
++		/*
++		 * Flush TX data and exit the wait if NDELAY is set,
++		 * or this is not a DIGI printer, and the close timeout
++		 * expires.
++		 */
++
++		if ((file->f_flags & (O_NDELAY | O_NONBLOCK)) ||
++		    ((long)(jiffies - waketime) >= 0 &&
++		      (ch->ch_digi.digi_flags & DIGI_PRINTER) == 0)) {
++
++				/*
++				 * If we sent the printer off string, we cannot
++				 * flush our internal buffers, or we might lose
++				 * the offstr.
++				 */
++				if (!sent_printer_offstr)
++					dgrp_tty_flush_buffer(tty);
++
++				tty_ldisc_flush(tty);
++				break;
++		}
++
++		/*
++		 *  Otherwise take a short nap.
++		 */
++
++		ch->ch_flag |= CH_DRAIN;
++
++		spin_unlock_irqrestore(&nd->nd_lock, lock_flags);
++
++		schedule_timeout_interruptible(1);
++		s = signal_pending(current);
++
++		spin_lock_irqsave(&nd->nd_lock, lock_flags);
++
++		if (s) {
++			/*
++			 * If we had sent the printer off string, we now have
++			 * some problems.
++			 *
++			 * The system won't let us sleep since we got an error
++			 * back from sleep, presumably because the user did
++			 * a ctrl-c...
++			 * But we need to ensure that the offstr gets sent!
++			 * Thus, we have to do something else besides sleeping.
++			 * The plan:
++			 * 1) Make this task uninterruptable.
++			 * 2) Set up a timer to go off in 1 sec.
++			 * 3) Act as tho we just got out of the sleep above.
++			 *
++			 * Thankfully, in the real world, this just
++			 * never happens.
++			 */
++
++			if (sent_printer_offstr) {
++				spin_unlock_irqrestore(&nd->nd_lock,
++						       lock_flags);
++				drp_my_sleep(ch);
++				spin_lock_irqsave(&nd->nd_lock, lock_flags);
++			} else {
++				err = 1;
++				break;
++			}
++		}
++
++		/*
++		 *  Restart the wait if any progress is seen.
++		 */
++
++		if (ch->ch_s_tpos != tpos) {
++			tpos = ch->ch_s_tpos;
++
++			/* TODO:  this gives us timeout problems with nist ?? */
++			waketime = jiffies + 15 * HZ;
++		}
++	}
++
++	/*
++	 *  Close the line discipline
++	 */
++
++	/* this is done in tty_io.c */
++	/* if ((un->un_tty)->ldisc.close)
++	 *	((un->un_tty)->ldisc.close)(un->un_tty);
++	 */
++
++	/* don't do this here */
++	/* un->un_flag = 0; */
++
++	/*
++	 *  Flush the receive buffer on terminal unit close only.
++	 */
++
++	if (!IS_PRINT(MINOR(tty_devnum(tty))))
++		ch->ch_rout = ch->ch_rin;
++
++
++	/*
++	 * Don't permit the close to happen until we get any pending
++	 * sync request responses.
++	 * There could be other ports depending upon the response as well.
++	 *
++	 * Also, don't permit the close to happen until any parameter
++	 * changes have been sent out from the state machine as well.
++	 * This is required because of a ditty -a race with -HUPCL
++	 * We MUST make sure all channel parameters have been sent to the
++	 * Portserver before sending a close.
++	 */
++
++	if ((err != 1) && (ch->ch_state != CS_IDLE)) {
++		spin_unlock_irqrestore(&nd->nd_lock, lock_flags);
++		s = wait_event_interruptible(ch->ch_flag_wait,
++			((ch->ch_flag & (CH_WAITING_SYNC | CH_PARAM)) == 0));
++		spin_lock_irqsave(&nd->nd_lock, lock_flags);
++	}
++
++	/*
++	 * Cleanup the channel if last unit open.
++	 */
++
++	if (ch->ch_open_count == 1) {
++		ch->ch_flag = 0;
++		ch->ch_category = 0;
++		ch->ch_send = 0;
++		ch->ch_expect = 0;
++		ch->ch_tout = ch->ch_tin;
++		/* (un->un_tty)->device = 0; */
++
++		if (ch->ch_state == CS_READY)
++			ch->ch_state = CS_SEND_CLOSE;
++	}
++
++	/*
++	 * Send the changes to the server
++	 */
++	if (ch->ch_state != CS_IDLE) {
++		ch->ch_flag |= CH_PARAM;
++		wake_up_interruptible(&ch->ch_flag_wait);
++	}
++
++	nd->nd_tx_work = 1;
++	nd->nd_tx_ready = 1;
++
++unlock:
++	tty->closing = 0;
++
++	if (ch->ch_open_count <= 0)
++		dev_info(tty->dev,
++			 "%s - unexpected value for ch->ch_open_count: %i\n",
++			 __func__, ch->ch_open_count);
++	else
++		ch->ch_open_count--;
++
++	if (un->un_open_count <= 0)
++		dev_info(tty->dev,
++			 "%s - unexpected value for un->un_open_count: %i\n",
++			 __func__, un->un_open_count);
++	else
++		un->un_open_count--;
++
++	un->un_flag &= ~(UN_NORMAL_ACTIVE | UN_CALLOUT_ACTIVE | UN_CLOSING);
++	if (waitqueue_active(&un->un_close_wait))
++		wake_up_interruptible(&un->un_close_wait);
++
++	spin_unlock_irqrestore(&nd->nd_lock, lock_flags);
++
++	return;
++
++}
++
++static void drp_wmove(struct ch_struct *ch, int from_user, void *buf, int count)
++{
++	int n;
++	int ret = 0;
++
++	ch->ch_nd->nd_tx_work = 1;
++
++	n = TBUF_MAX - ch->ch_tin;
++
++	if (count >= n) {
++		if (from_user)
++			ret = copy_from_user(ch->ch_tbuf + ch->ch_tin,
++					     (void __user *) buf, n);
++		else
++			memcpy(ch->ch_tbuf + ch->ch_tin, buf, n);
++
++		buf = (char *) buf + n;
++		count -= n;
++		ch->ch_tin = 0;
++	}
++
++	if (from_user)
++		ret = copy_from_user(ch->ch_tbuf + ch->ch_tin,
++				     (void __user *) buf, count);
++	else
++		memcpy(ch->ch_tbuf + ch->ch_tin, buf, count);
++
++	ch->ch_tin += count;
++}
++
++
++static int dgrp_calculate_txprint_bounds(struct ch_struct *ch, int space,
++					 int *un_flag)
++{
++	clock_t tt;
++	clock_t mt;
++	unsigned short tmax = 0;
++
++	/*
++	 * If the terminal device is busy, reschedule when
++	 * the terminal device becomes idle.
++	 */
++
++	if (ch->ch_tun.un_open_count != 0 &&
++	    ch->ch_tun.un_tty->ops->chars_in_buffer &&
++	    ((ch->ch_tun.un_tty->ops->chars_in_buffer)(ch->ch_tun.un_tty) != 0)) {
++		*un_flag = UN_PWAIT;
++		return 0;
++	}
++
++	/*
++	 * Assure that whenever there is printer data in the output
++	 * buffer, there always remains enough space after it to
++	 * turn the printer off.
++	 */
++	space -= ch->ch_digi.digi_offlen;
++
++	if (space <= 0) {
++		*un_flag = UN_EMPTY;
++		return 0;
++	}
++
++	/*
++	 * We measure printer CPS speed by incrementing
++	 * ch_cpstime by (HZ / digi_maxcps) for every
++	 * character we output, restricting output so
++	 * that ch_cpstime never exceeds lbolt.
++	 *
++	 * However if output has not been done for some
++	 * time, lbolt will grow to very much larger than
++	 * ch_cpstime, which would allow essentially
++	 * unlimited amounts of output until ch_cpstime
++	 * finally caught up.   To avoid this, we adjust
++	 * cps_time when necessary so the difference
++	 * between lbolt and ch_cpstime never results
++	 * in sending more than digi_bufsize characters.
++	 *
++	 * This nicely models a printer with an internal
++	 * buffer of digi_bufsize characters.
++	 *
++	 * Get the time between lbolt and ch->ch_cpstime;
++	 */
++
++	tt = jiffies - ch->ch_cpstime;
++
++	/*
++	 * Compute the time required to send digi_bufsize
++	 * characters.
++	 */
++
++	mt = HZ * ch->ch_digi.digi_bufsize / ch->ch_digi.digi_maxcps;
++
++	/*
++	 * Compute the number of characters that can be sent
++	 * without violating the time constraint.   If the
++	 * direct calculation of this number is bigger than
++	 * digi_bufsize, limit the number to digi_bufsize,
++	 * and adjust cpstime to match.
++	 */
++
++	if ((clock_t)(tt + HZ) > (clock_t)(mt + HZ)) {
++		tmax = ch->ch_digi.digi_bufsize;
++		ch->ch_cpstime = jiffies - mt;
++	} else {
++		tmax = ch->ch_digi.digi_maxcps * tt / HZ;
++	}
++
++	/*
++	 * If the time constraint now binds, limit the transmit
++	 * count accordingly, and tentatively arrange to be
++	 * rescheduled based on time.
++	 */
++
++	if (tmax < space) {
++		*un_flag = UN_TIME;
++		space = tmax;
++	}
++
++	/*
++	 * Compute the total number of characters we can
++	 * output before the total number of characters known
++	 * to be in the output queue exceeds digi_maxchar.
++	 */
++
++	tmax = (ch->ch_digi.digi_maxchar -
++		((ch->ch_tin - ch->ch_tout) & TBUF_MASK) -
++		((ch->ch_s_tin - ch->ch_s_tpos) & 0xffff));
++
++
++	/*
++	 * If the digi_maxchar constraint now holds, limit
++	 * the transmit count accordingly, and arrange to
++	 * be rescheduled when the queue becomes empty.
++	 */
++
++	if (space > tmax) {
++		*un_flag = UN_EMPTY;
++		space = tmax;
++	}
++
++	if (space <= 0)
++		*un_flag |= UN_EMPTY;
++
++	return space;
++}
++
++
++static int dgrp_tty_write(struct tty_struct *tty,
++			  const unsigned char *buf,
++			  int count)
++{
++	struct nd_struct *nd;
++	struct un_struct *un;
++	struct ch_struct *ch;
++	int	space;
++	int	n;
++	int	t;
++	int sendcount;
++	int un_flag;
++	ulong lock_flags;
++
++	if (tty == NULL)
++		return 0;
++
++	un = tty->driver_data;
++	if (!un)
++		return 0;
++
++	ch = un->un_ch;
++	if (!ch)
++		return 0;
++
++	nd = ch->ch_nd;
++	if (!nd)
++		return 0;
++
++	/*
++	 * Ignore the request if the channel is not ready.
++	 */
++	if (ch->ch_state != CS_READY)
++		return 0;
++
++	spin_lock_irqsave(&dgrp_poll_data.poll_lock, lock_flags);
++
++	/*
++	 * Ignore the request if output is blocked.
++	 */
++	if ((un->un_flag & (UN_EMPTY | UN_LOW | UN_TIME | UN_PWAIT)) != 0) {
++		count = 0;
++		goto out;
++	}
++
++	/*
++	 * Also ignore the request if DPA has this port open,
++	 * and is flow controlled on reading more data.
++	 */
++	if (nd->nd_dpa_debug && nd->nd_dpa_flag & DPA_WAIT_SPACE &&
++		nd->nd_dpa_port == MINOR(tty_devnum(ch->ch_tun.un_tty))) {
++		count = 0;
++		goto out;
++	}
++
++	/*
++	 *	Limit amount we will write to the amount of space
++	 *	available in the channel buffer.
++	 */
++	sendcount = 0;
++
++	space = (ch->ch_tout - ch->ch_tin - 1) & TBUF_MASK;
++
++	/*
++	 * Handle the printer device.
++	 */
++
++	un_flag = UN_LOW;
++
++	if (IS_PRINT(MINOR(tty_devnum(tty)))) {
++		clock_t tt;
++		clock_t mt;
++		unsigned short tmax = 0;
++
++		/*
++		 * If the terminal device is busy, reschedule when
++		 * the terminal device becomes idle.
++		 */
++
++		if (ch->ch_tun.un_open_count != 0 &&
++		    ((ch->ch_tun.un_tty->ops->chars_in_buffer)(ch->ch_tun.un_tty) != 0)) {
++			un->un_flag |= UN_PWAIT;
++			count = 0;
++			goto out;
++		}
++
++		/*
++		 * Assure that whenever there is printer data in the output
++		 * buffer, there always remains enough space after it to
++		 * turn the printer off.
++		 */
++		space -= ch->ch_digi.digi_offlen;
++
++		/*
++		 * Output the printer on string.
++		 */
++
++		if ((ch->ch_flag & CH_PRON) == 0) {
++			space -= ch->ch_digi.digi_onlen;
++
++			if (space < 0) {
++				un->un_flag |= UN_EMPTY;
++				(ch->ch_nd)->nd_tx_work = 1;
++				count = 0;
++				goto out;
++			}
++
++			drp_wmove(ch, 0, ch->ch_digi.digi_onstr,
++				ch->ch_digi.digi_onlen);
++
++			ch->ch_flag |= CH_PRON;
++		}
++
++		/*
++		 * We measure printer CPS speed by incrementing
++		 * ch_cpstime by (HZ / digi_maxcps) for every
++		 * character we output, restricting output so
++		 * that ch_cpstime never exceeds lbolt.
++		 *
++		 * However if output has not been done for some
++		 * time, lbolt will grow to very much larger than
++		 * ch_cpstime, which would allow essentially
++		 * unlimited amounts of output until ch_cpstime
++		 * finally caught up.   To avoid this, we adjust
++		 * cps_time when necessary so the difference
++		 * between lbolt and ch_cpstime never results
++		 * in sending more than digi_bufsize characters.
++		 *
++		 * This nicely models a printer with an internal
++		 * buffer of digi_bufsize characters.
++		 *
++		 * Get the time between lbolt and ch->ch_cpstime;
++		 */
++
++		tt = jiffies - ch->ch_cpstime;
++
++		/*
++		 * Compute the time required to send digi_bufsize
++		 * characters.
++		 */
++
++		mt = HZ * ch->ch_digi.digi_bufsize / ch->ch_digi.digi_maxcps;
++
++		/*
++		 * Compute the number of characters that can be sent
++		 * without violating the time constraint.   If the
++		 * direct calculation of this number is bigger than
++		 * digi_bufsize, limit the number to digi_bufsize,
++		 * and adjust cpstime to match.
++		 */
++
++		if ((clock_t)(tt + HZ) > (clock_t)(mt + HZ)) {
++			tmax = ch->ch_digi.digi_bufsize;
++			ch->ch_cpstime = jiffies - mt;
++		} else {
++			tmax = ch->ch_digi.digi_maxcps * tt / HZ;
++		}
++
++		/*
++		 * If the time constraint now binds, limit the transmit
++		 * count accordingly, and tentatively arrange to be
++		 * rescheduled based on time.
++		 */
++
++		if (tmax < space) {
++			space = tmax;
++			un_flag = UN_TIME;
++		}
++
++		/*
++		 * Compute the total number of characters we can
++		 * output before the total number of characters known
++		 * to be in the output queue exceeds digi_maxchar.
++		 */
++
++		tmax = (ch->ch_digi.digi_maxchar -
++			((ch->ch_tin - ch->ch_tout) & TBUF_MASK) -
++			((ch->ch_s_tin - ch->ch_s_tpos) & 0xffff));
++
++
++		/*
++		 * If the digi_maxchar constraint now holds, limit
++		 * the transmit count accordingly, and arrange to
++		 * be rescheduled when the queue becomes empty.
++		 */
++
++		if (space > tmax) {
++			space = tmax;
++			un_flag = UN_EMPTY;
++		}
++
++	}
++	/*
++	 * Handle the terminal device.
++	 */
++	else {
++
++		/*
++		 * If the printer device is on, turn it off.
++		 */
++
++		if ((ch->ch_flag & CH_PRON) != 0) {
++
++			space -= ch->ch_digi.digi_offlen;
++
++			drp_wmove(ch, 0, ch->ch_digi.digi_offstr,
++				  ch->ch_digi.digi_offlen);
++
++			ch->ch_flag &= ~CH_PRON;
++		}
++	}
++
++	/*
++	 *	If space is 0 and its because the ch->tbuf
++	 *	is full, then Linux will handle a callback when queue
++	 *	space becomes available.
++	 *	tty_write returns count = 0
++	 */
++
++	if (space <= 0) {
++		/* the linux tty_io.c handles this if we return 0 */
++		/* if (fp->flags & O_NONBLOCK) return -EAGAIN; */
++
++		un->un_flag |= UN_EMPTY;
++		(ch->ch_nd)->nd_tx_work = 1;
++		count = 0;
++		goto out;
++	}
++
++	count = min(count, space);
++
++	if (count > 0) {
++
++		un->un_tbusy++;
++
++		/*
++		 *	Copy the buffer contents to the ch_tbuf
++		 *	being careful to wrap around the circular queue
++		 */
++
++		t = TBUF_MAX - ch->ch_tin;
++		n = count;
++
++		if (n >= t) {
++			memcpy(ch->ch_tbuf + ch->ch_tin, buf, t);
++			if (nd->nd_dpa_debug && nd->nd_dpa_port == PORT_NUM(MINOR(tty_devnum(un->un_tty))))
++				dgrp_dpa_data(nd, 0, (char *) buf, t);
++			buf += t;
++			n -= t;
++			ch->ch_tin = 0;
++			sendcount += n;
++		}
++
++		memcpy(ch->ch_tbuf + ch->ch_tin, buf, n);
++		if (nd->nd_dpa_debug && nd->nd_dpa_port == PORT_NUM(MINOR(tty_devnum(un->un_tty))))
++			dgrp_dpa_data(nd, 0, (char *) buf, n);
++		buf += n;
++		ch->ch_tin += n;
++		sendcount += n;
++
++		un->un_tbusy--;
++		(ch->ch_nd)->nd_tx_work = 1;
++		if (ch->ch_edelay != DGRP_RTIME) {
++			(ch->ch_nd)->nd_tx_ready = 1;
++			wake_up_interruptible(&nd->nd_tx_waitq);
++		}
++	}
++
++	ch->ch_txcount += count;
++
++	if (IS_PRINT(MINOR(tty_devnum(tty)))) {
++
++		/*
++		 * Adjust ch_cpstime to account
++		 * for the characters just output.
++		 */
++
++		if (sendcount > 0) {
++			int cc = HZ * sendcount + ch->ch_cpsrem;
++
++			ch->ch_cpstime += cc / ch->ch_digi.digi_maxcps;
++			ch->ch_cpsrem   = cc % ch->ch_digi.digi_maxcps;
++		}
++
++		/*
++		 * If we are now waiting on time, schedule ourself
++		 * back when we'll be able to send a block of
++		 * digi_maxchar characters.
++		 */
++
++		if ((un_flag & UN_TIME) != 0) {
++			ch->ch_waketime = (ch->ch_cpstime +
++				(ch->ch_digi.digi_maxchar * HZ /
++				ch->ch_digi.digi_maxcps));
++		}
++	}
++
++	/*
++	 * If the printer unit is waiting for completion
++	 * of terminal output, get him going again.
++	 */
++
++	if ((ch->ch_pun.un_flag & UN_PWAIT) != 0)
++		(ch->ch_nd)->nd_tx_work = 1;
++
++out:
++	spin_unlock_irqrestore(&dgrp_poll_data.poll_lock, lock_flags);
++
++	return count;
++}
++
++
++/*
++ *	Put a character into ch->ch_buf
++ *
++ *	- used by the line discipline for OPOST processing
++ */
++
++static int dgrp_tty_put_char(struct tty_struct *tty, unsigned char new_char)
++{
++	struct un_struct *un;
++	struct ch_struct *ch;
++	ulong  lock_flags;
++	int space;
++	int retval = 0;
++
++	if (tty == NULL)
++		return 0;
++
++	un = tty->driver_data;
++	if (!un)
++		return 0;
++
++	ch = un->un_ch;
++	if (!ch)
++		return 0;
++
++	if (ch->ch_state != CS_READY)
++		return 0;
++
++	spin_lock_irqsave(&dgrp_poll_data.poll_lock, lock_flags);
++
++
++	/*
++	 *	If space is 0 and its because the ch->tbuf
++	 *	Warn and dump the character, there isn't anything else
++	 *	we can do about it.  David_Fries@digi.com
++	 */
++
++	space = (ch->ch_tout - ch->ch_tin - 1) & TBUF_MASK;
++
++	un->un_tbusy++;
++
++	/*
++	 * Output the printer on string if device is TXPrint.
++	 */
++	if (IS_PRINT(MINOR(tty_devnum(tty))) && (ch->ch_flag & CH_PRON) == 0) {
++		if (space < ch->ch_digi.digi_onlen) {
++			un->un_tbusy--;
++			goto out;
++		}
++		space -= ch->ch_digi.digi_onlen;
++		drp_wmove(ch, 0, ch->ch_digi.digi_onstr,
++			  ch->ch_digi.digi_onlen);
++		ch->ch_flag |= CH_PRON;
++	}
++
++	/*
++	 * Output the printer off string if device is NOT TXPrint.
++	 */
++
++	if (!IS_PRINT(MINOR(tty_devnum(tty))) &&
++	    ((ch->ch_flag & CH_PRON) != 0)) {
++		if (space < ch->ch_digi.digi_offlen) {
++			un->un_tbusy--;
++			goto out;
++		}
++
++		space -= ch->ch_digi.digi_offlen;
++		drp_wmove(ch, 0, ch->ch_digi.digi_offstr,
++			  ch->ch_digi.digi_offlen);
++		ch->ch_flag &= ~CH_PRON;
++	}
++
++	if (!space) {
++		un->un_tbusy--;
++		goto out;
++	}
++
++	/*
++	 *	Copy the character to the ch_tbuf being
++	 *	careful to wrap around the circular queue
++	 */
++	ch->ch_tbuf[ch->ch_tin] = new_char;
++	ch->ch_tin = (1 + ch->ch_tin) & TBUF_MASK;
++
++	if (IS_PRINT(MINOR(tty_devnum(tty)))) {
++
++		/*
++		 * Adjust ch_cpstime to account
++		 * for the character just output.
++		 */
++
++		int cc = HZ + ch->ch_cpsrem;
++
++		ch->ch_cpstime += cc / ch->ch_digi.digi_maxcps;
++		ch->ch_cpsrem   = cc % ch->ch_digi.digi_maxcps;
++
++		/*
++		 * If we are now waiting on time, schedule ourself
++		 * back when we'll be able to send a block of
++		 * digi_maxchar characters.
++		 */
++
++		ch->ch_waketime = (ch->ch_cpstime +
++			(ch->ch_digi.digi_maxchar * HZ /
++			ch->ch_digi.digi_maxcps));
++	}
++
++
++	un->un_tbusy--;
++	(ch->ch_nd)->nd_tx_work = 1;
++
++	retval = 1;
++out:
++	spin_unlock_irqrestore(&dgrp_poll_data.poll_lock, lock_flags);
++	return retval;
++}
++
++
++
++/*
++ *	Flush TX buffer (make in == out)
++ *
++ *	check tty_ioctl.c  -- this is called after TCOFLUSH
++ */
++static void dgrp_tty_flush_buffer(struct tty_struct *tty)
++{
++	struct un_struct *un;
++	struct ch_struct *ch;
++
++	if (!tty)
++		return;
++	un = tty->driver_data;
++	if (!un)
++		return;
++
++	ch = un->un_ch;
++	if (!ch)
++		return;
++
++	ch->ch_tout = ch->ch_tin;
++	/* do NOT do this here! */
++	/* ch->ch_s_tpos = ch->ch_s_tin = 0; */
++
++	/* send the flush output command now */
++	ch->ch_send |= RR_TX_FLUSH;
++	(ch->ch_nd)->nd_tx_ready = 1;
++	(ch->ch_nd)->nd_tx_work = 1;
++	wake_up_interruptible(&(ch->ch_nd)->nd_tx_waitq);
++
++	if (waitqueue_active(&tty->write_wait))
++		wake_up_interruptible(&tty->write_wait);
++
++	tty_wakeup(tty);
++
++}
++
++/*
++ *	Return space available in Tx buffer
++ *	count = ( ch->ch_tout - ch->ch_tin ) mod (TBUF_MAX - 1)
++ */
++static int dgrp_tty_write_room(struct tty_struct *tty)
++{
++	struct un_struct *un;
++	struct ch_struct *ch;
++	int	count;
++
++	if (!tty)
++		return 0;
++
++	un = tty->driver_data;
++	if (!un)
++		return 0;
++
++	ch = un->un_ch;
++	if (!ch)
++		return 0;
++
++	count = (ch->ch_tout - ch->ch_tin - 1) & TBUF_MASK;
++
++	/* We *MUST* check this, and return 0 if the Printer Unit cannot
++	 * take any more data within its time constraints...  If we don't
++	 * return 0 and the printer has hit it time constraint, the ld will
++	 * call us back doing a put_char, which cannot be rejected!!!
++	 */
++	if (IS_PRINT(MINOR(tty_devnum(tty)))) {
++		int un_flag = 0;
++		count = dgrp_calculate_txprint_bounds(ch, count, &un_flag);
++		if (count <= 0)
++			count = 0;
++
++		ch->ch_pun.un_flag |= un_flag;
++		(ch->ch_nd)->nd_tx_work = 1;
++	}
++
++	return count;
++}
++
++/*
++ *	Return number of characters that have not been transmitted yet.
++ *	chars_in_buffer = ( ch->ch_tin - ch->ch_tout ) mod (TBUF_MAX - 1)
++ *			+ ( ch->ch_s_tin - ch->ch_s_tout ) mod (0xffff)
++ *			= number of characters "in transit"
++ *
++ * Remember that sequence number math is always with a sixteen bit
++ * mask, not the TBUF_MASK.
++ */
++
++static int dgrp_tty_chars_in_buffer(struct tty_struct *tty)
++{
++	struct un_struct *un;
++	struct ch_struct *ch;
++	int	count;
++	int	count1;
++
++	if (!tty)
++		return 0;
++
++	un = tty->driver_data;
++	if (!un)
++		return 0;
++
++	ch = un->un_ch;
++	if (!ch)
++		return 0;
++
++	count1 = count = (ch->ch_tin - ch->ch_tout) & TBUF_MASK;
++	count += (ch->ch_s_tin - ch->ch_s_tpos) & 0xffff;
++	/* one for tbuf, one for the PS */
++
++	/*
++	 * If we are busy transmitting add 1
++	 */
++	count += un->un_tbusy;
++
++	return count;
++}
++
++
++/*****************************************************************************
++ *
++ * Helper applications for dgrp_tty_ioctl()
++ *
++ *****************************************************************************
++ */
++
++
++/**
++ * ch_to_tty_flags() -- convert channel flags to termio flags
++ * @ch_flag: Digi channel flags
++ * @flagtype: type of ch_flag (iflag, oflag or cflag)
++ *
++ * take the channel flags of the specified type and return the
++ * corresponding termio flag
++ */
++static tcflag_t ch_to_tty_flags(ushort ch_flag, char flagtype)
++{
++	tcflag_t retval = 0;
++
++	switch (flagtype) {
++	case 'i':
++		retval = ((ch_flag & IF_IGNBRK) ? IGNBRK : 0)
++		     | ((ch_flag & IF_BRKINT) ? BRKINT : 0)
++		     | ((ch_flag & IF_IGNPAR) ? IGNPAR : 0)
++		     | ((ch_flag & IF_PARMRK) ? PARMRK : 0)
++		     | ((ch_flag & IF_INPCK) ? INPCK  : 0)
++		     | ((ch_flag & IF_ISTRIP) ? ISTRIP : 0)
++		     | ((ch_flag & IF_IXON) ? IXON   : 0)
++		     | ((ch_flag & IF_IXANY) ? IXANY  : 0)
++		     | ((ch_flag & IF_IXOFF) ? IXOFF  : 0);
++		break;
++
++	case 'o':
++		retval = ((ch_flag & OF_OLCUC) ? OLCUC : 0)
++		     | ((ch_flag & OF_ONLCR) ? ONLCR  : 0)
++		     | ((ch_flag & OF_OCRNL) ? OCRNL  : 0)
++		     | ((ch_flag & OF_ONOCR) ? ONOCR  : 0)
++		     | ((ch_flag & OF_ONLRET) ? ONLRET : 0)
++		  /* | ((ch_flag & OF_OTAB3) ? OFILL  : 0) */
++		     | ((ch_flag & OF_TABDLY) ? TABDLY : 0);
++		break;
++
++	case 'c':
++		retval = ((ch_flag & CF_CSTOPB) ? CSTOPB : 0)
++		     | ((ch_flag & CF_CREAD) ? CREAD  : 0)
++		     | ((ch_flag & CF_PARENB) ? PARENB : 0)
++		     | ((ch_flag & CF_PARODD) ? PARODD : 0)
++		     | ((ch_flag & CF_HUPCL) ? HUPCL  : 0);
++
++		switch (ch_flag & CF_CSIZE) {
++		case CF_CS5:
++			retval |= CS5;
++			break;
++		case CF_CS6:
++			retval |= CS6;
++			break;
++		case CF_CS7:
++			retval |= CS7;
++			break;
++		case CF_CS8:
++			retval |= CS8;
++			break;
++		default:
++			retval |= CS8;
++			break;
++		}
++		break;
++	case 'x':
++		break;
++	case 'l':
++		break;
++	default:
++		return 0;
++	}
++
++	return retval;
++}
++
++
++/**
++ * tty_to_ch_flags() -- convert termio flags to digi channel flags
++ * @tty: pointer to a TTY structure holding flag to be converted
++ * @flagtype: identifies which flag (iflags, oflags, or cflags) should
++ *                 be converted
++ *
++ * take the termio flag of the specified type and return the
++ * corresponding Digi version of the flags
++ */
++static ushort tty_to_ch_flags(struct tty_struct *tty, char flagtype)
++{
++	ushort retval = 0;
++	tcflag_t tflag = 0;
++
++	switch (flagtype) {
++	case 'i':
++		tflag  = tty->termios.c_iflag;
++		retval = (I_IGNBRK(tty) ? IF_IGNBRK : 0)
++		      | (I_BRKINT(tty) ? IF_BRKINT : 0)
++		      | (I_IGNPAR(tty) ? IF_IGNPAR : 0)
++		      | (I_PARMRK(tty) ? IF_PARMRK : 0)
++		      | (I_INPCK(tty)  ? IF_INPCK  : 0)
++		      | (I_ISTRIP(tty) ? IF_ISTRIP : 0)
++		      | (I_IXON(tty)   ? IF_IXON   : 0)
++		      | (I_IXANY(tty)  ? IF_IXANY  : 0)
++		      | (I_IXOFF(tty)  ? IF_IXOFF  : 0);
++		break;
++	case 'o':
++		tflag  = tty->termios.c_oflag;
++		/*
++		 * If OPOST is set, then do the post processing in the
++		 * firmware by setting all the processing flags on.
++		 * If ~OPOST, then make sure we are not doing any
++		 * output processing!!
++		 */
++		if (!O_OPOST(tty))
++			retval = 0;
++		else
++			retval = (O_OLCUC(tty) ? OF_OLCUC : 0)
++			     | (O_ONLCR(tty)  ? OF_ONLCR  : 0)
++			     | (O_OCRNL(tty)  ? OF_OCRNL  : 0)
++			     | (O_ONOCR(tty)  ? OF_ONOCR  : 0)
++			     | (O_ONLRET(tty) ? OF_ONLRET : 0)
++			  /* | (O_OFILL(tty)  ? OF_TAB3   : 0) */
++			     | (O_TABDLY(tty) ? OF_TABDLY : 0);
++		break;
++	case 'c':
++		tflag  = tty->termios.c_cflag;
++		retval = (C_CSTOPB(tty) ? CF_CSTOPB : 0)
++		     | (C_CREAD(tty)  ? CF_CREAD  : 0)
++		     | (C_PARENB(tty) ? CF_PARENB : 0)
++		     | (C_PARODD(tty) ? CF_PARODD : 0)
++		     | (C_HUPCL(tty)  ? CF_HUPCL  : 0);
++		switch (C_CSIZE(tty)) {
++		case CS8:
++			retval |= CF_CS8;
++			break;
++		case CS7:
++			retval |= CF_CS7;
++			break;
++		case CS6:
++			retval |= CF_CS6;
++			break;
++		case CS5:
++			retval |= CF_CS5;
++			break;
++		default:
++			retval |= CF_CS8;
++			break;
++		}
++		break;
++	case 'x':
++		break;
++	case 'l':
++		break;
++	default:
++		return 0;
++	}
++
++	return retval;
++}
++
++
++static int dgrp_tty_send_break(struct tty_struct *tty, int msec)
++{
++	struct un_struct *un;
++	struct ch_struct *ch;
++	int ret = -EIO;
++
++	if (!tty)
++		return ret;
++
++	un = tty->driver_data;
++	if (!un)
++		return ret;
++
++	ch = un->un_ch;
++	if (!ch)
++		return ret;
++
++	dgrp_send_break(ch, msec);
++	return 0;
++}
++
++
++/*
++ * This routine sends a break character out the serial port.
++ *
++ * duration is in 1/1000's of a second
++ */
++static int dgrp_send_break(struct ch_struct *ch, int msec)
++{
++	ulong x;
++
++	wait_event_interruptible(ch->ch_flag_wait,
++		((ch->ch_flag & CH_TX_BREAK) == 0));
++	ch->ch_break_time += max(msec, 250);
++	ch->ch_send |= RR_TX_BREAK;
++	ch->ch_flag |= CH_TX_BREAK;
++	(ch->ch_nd)->nd_tx_work = 1;
++
++	x = (msec * HZ) / 1000;
++	wake_up_interruptible(&(ch->ch_nd)->nd_tx_waitq);
++
++	return 0;
++}
++
++
++/*
++ * Return modem signals to ld.
++ */
++static int dgrp_tty_tiocmget(struct tty_struct *tty)
++{
++	unsigned int mlast;
++	struct un_struct *un = tty->driver_data;
++	struct ch_struct *ch;
++
++	if (!un)
++		return -ENODEV;
++
++	ch = un->un_ch;
++	if (!ch)
++		return -ENODEV;
++
++	mlast = ((ch->ch_s_mlast & ~(DM_RTS | DM_DTR)) |
++		(ch->ch_mout & (DM_RTS | DM_DTR)));
++
++	/* defined in /usr/include/asm/termios.h */
++	mlast =   ((mlast & DM_RTS) ? TIOCM_RTS : 0)
++		| ((mlast & DM_DTR) ? TIOCM_DTR : 0)
++		| ((mlast & DM_CD)  ? TIOCM_CAR : 0)
++		| ((mlast & DM_RI)  ? TIOCM_RNG : 0)
++		| ((mlast & DM_DSR) ? TIOCM_DSR : 0)
++		| ((mlast & DM_CTS) ? TIOCM_CTS : 0);
++
++	return mlast;
++}
++
++
++/*
++ *      Set modem lines
++ */
++static int dgrp_tty_tiocmset(struct tty_struct *tty,
++			     unsigned int set, unsigned int clear)
++{
++	ulong lock_flags;
++	struct un_struct *un = tty->driver_data;
++	struct ch_struct *ch;
++
++	if (!un)
++		return -ENODEV;
++
++	ch = un->un_ch;
++	if (!ch)
++		return -ENODEV;
++
++	if (set & TIOCM_RTS)
++		ch->ch_mout |= DM_RTS;
++
++	if (set & TIOCM_DTR)
++		ch->ch_mout |= DM_DTR;
++
++	if (clear & TIOCM_RTS)
++		ch->ch_mout &= ~(DM_RTS);
++
++	if (clear & TIOCM_DTR)
++		ch->ch_mout &= ~(DM_DTR);
++
++	spin_lock_irqsave(&(ch->ch_nd)->nd_lock, lock_flags);
++	ch->ch_flag |= CH_PARAM;
++	(ch->ch_nd)->nd_tx_work = 1;
++	wake_up_interruptible(&ch->ch_flag_wait);
++
++	spin_unlock_irqrestore(&(ch->ch_nd)->nd_lock, lock_flags);
++
++	return 0;
++}
++
++
++
++/*
++ *      Get current modem status
++ */
++static int get_modem_info(struct ch_struct *ch, unsigned int *value)
++{
++	unsigned int mlast;
++
++	mlast = ((ch->ch_s_mlast & ~(DM_RTS | DM_DTR)) |
++		(ch->ch_mout    &  (DM_RTS | DM_DTR)));
++
++	/* defined in /usr/include/asm/termios.h */
++	mlast =   ((mlast & DM_RTS) ? TIOCM_RTS : 0)
++		| ((mlast & DM_DTR) ? TIOCM_DTR : 0)
++		| ((mlast & DM_CD)  ? TIOCM_CAR : 0)
++		| ((mlast & DM_RI)  ? TIOCM_RNG : 0)
++		| ((mlast & DM_DSR) ? TIOCM_DSR : 0)
++		| ((mlast & DM_CTS) ? TIOCM_CTS : 0);
++	put_user(mlast, (unsigned int __user *) value);
++
++	return 0;
++}
++
++/*
++ *      Set modem lines
++ */
++static int set_modem_info(struct ch_struct *ch, unsigned int command,
++			  unsigned int *value)
++{
++	int error;
++	unsigned int arg;
++	int mval = 0;
++	ulong lock_flags;
++
++	error = access_ok(VERIFY_READ, (void __user *) value, sizeof(int));
++	if (error == 0)
++		return -EFAULT;
++
++	get_user(arg, (unsigned int __user *) value);
++	mval |= ((arg & TIOCM_RTS) ? DM_RTS : 0)
++		| ((arg & TIOCM_DTR) ? DM_DTR : 0);
++
++	switch (command) {
++	case TIOCMBIS:  /* set flags */
++		ch->ch_mout |= mval;
++		break;
++	case TIOCMBIC:  /* clear flags */
++		ch->ch_mout &= ~mval;
++		break;
++	case TIOCMSET:
++		ch->ch_mout = mval;
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	spin_lock_irqsave(&(ch->ch_nd)->nd_lock, lock_flags);
++
++	ch->ch_flag |= CH_PARAM;
++	(ch->ch_nd)->nd_tx_work = 1;
++	wake_up_interruptible(&ch->ch_flag_wait);
++
++	spin_unlock_irqrestore(&(ch->ch_nd)->nd_lock, lock_flags);
++
++	return 0;
++}
++
++
++/*
++ *  Assign the custom baud rate to the channel structure
++ */
++static void dgrp_set_custom_speed(struct ch_struct *ch, int newrate)
++{
++	int testdiv;
++	int testrate_high;
++	int testrate_low;
++
++	int deltahigh, deltalow;
++
++	if (newrate < 0)
++		newrate = 0;
++
++	/*
++	 * Since the divisor is stored in a 16-bit integer, we make sure
++	 * we don't allow any rates smaller than a 16-bit integer would allow.
++	 * And of course, rates above the dividend won't fly.
++	 */
++	if (newrate && newrate < ((PORTSERVER_DIVIDEND / 0xFFFF) + 1))
++		newrate = ((PORTSERVER_DIVIDEND / 0xFFFF) + 1);
++	if (newrate && newrate > PORTSERVER_DIVIDEND)
++		newrate = PORTSERVER_DIVIDEND;
++
++	while (newrate > 0) {
++		testdiv = PORTSERVER_DIVIDEND / newrate;
++
++		/*
++		 * If we try to figure out what rate the PortServer would use
++		 * with the test divisor, it will be either equal or higher
++		 * than the requested baud rate.  If we then determine the
++		 * rate with a divisor one higher, we will get the next lower
++		 * supported rate below the requested.
++		 */
++		testrate_high = PORTSERVER_DIVIDEND / testdiv;
++		testrate_low  = PORTSERVER_DIVIDEND / (testdiv + 1);
++
++		/*
++		 * If the rate for the requested divisor is correct, just
++		 * use it and be done.
++		 */
++		if (testrate_high == newrate)
++			break;
++
++		/*
++		 * Otherwise, pick the rate that is closer (i.e. whichever rate
++		 * has a smaller delta).
++		 */
++		deltahigh = testrate_high - newrate;
++		deltalow = newrate - testrate_low;
++
++		if (deltahigh < deltalow)
++			newrate = testrate_high;
++		else
++			newrate = testrate_low;
++
++		break;
++	}
++
++	ch->ch_custom_speed = newrate;
++
++	drp_param(ch);
++
++	return;
++}
++
++
++/*
++ # dgrp_tty_digiseta()
++ *
++ * Ioctl to set the information from ditty.
++ *
++ * NOTE: DIGI_IXON, DSRPACE, DCDPACE, and DTRPACE are unsupported.  JAR 990922
++ */
++static int dgrp_tty_digiseta(struct tty_struct *tty,
++			     struct digi_struct *new_info)
++{
++	struct un_struct *un = tty->driver_data;
++	struct ch_struct *ch;
++
++	if (!un)
++		return -ENODEV;
++
++	ch = un->un_ch;
++	if (!ch)
++		return -ENODEV;
++
++	if (copy_from_user(&ch->ch_digi, (void __user *) new_info,
++			   sizeof(struct digi_struct)))
++		return -EFAULT;
++
++	if ((ch->ch_digi.digi_flags & RTSPACE) ||
++	    (ch->ch_digi.digi_flags & CTSPACE))
++		tty->termios.c_cflag |= CRTSCTS;
++	else
++		tty->termios.c_cflag &= ~CRTSCTS;
++
++	if (ch->ch_digi.digi_maxcps < 1)
++		ch->ch_digi.digi_maxcps = 1;
++
++	if (ch->ch_digi.digi_maxcps > 10000)
++		ch->ch_digi.digi_maxcps = 10000;
++
++	if (ch->ch_digi.digi_bufsize < 10)
++		ch->ch_digi.digi_bufsize = 10;
++
++	if (ch->ch_digi.digi_maxchar < 1)
++		ch->ch_digi.digi_maxchar = 1;
++
++	if (ch->ch_digi.digi_maxchar > ch->ch_digi.digi_bufsize)
++		ch->ch_digi.digi_maxchar = ch->ch_digi.digi_bufsize;
++
++	if (ch->ch_digi.digi_onlen > DIGI_PLEN)
++		ch->ch_digi.digi_onlen = DIGI_PLEN;
++
++	if (ch->ch_digi.digi_offlen > DIGI_PLEN)
++		ch->ch_digi.digi_offlen = DIGI_PLEN;
++
++	/* make the changes now */
++	drp_param(ch);
++
++	return 0;
++}
++
++
++
++/*
++ * dgrp_tty_digigetedelay()
++ *
++ * Ioctl to get the current edelay setting.
++ *
++ *
++ *
++ */
++static int dgrp_tty_digigetedelay(struct tty_struct *tty, int *retinfo)
++{
++	struct un_struct *un;
++	struct ch_struct *ch;
++	int tmp;
++
++	if (!retinfo)
++		return -EFAULT;
++
++	if (!tty || tty->magic != TTY_MAGIC)
++		return -EFAULT;
++
++	un = tty->driver_data;
++
++	if (!un)
++		return -ENODEV;
++
++	ch = un->un_ch;
++	if (!ch)
++		return -ENODEV;
++
++	tmp = ch->ch_edelay;
++
++	if (copy_to_user((void __user *) retinfo, &tmp, sizeof(*retinfo)))
++		return -EFAULT;
++
++	return 0;
++}
++
++
++/*
++ * dgrp_tty_digisetedelay()
++ *
++ * Ioctl to set the EDELAY setting
++ *
++ */
++static int dgrp_tty_digisetedelay(struct tty_struct *tty, int *new_info)
++{
++	struct un_struct *un;
++	struct ch_struct *ch;
++	int new_digi;
++
++	if (!tty || tty->magic != TTY_MAGIC)
++		return -EFAULT;
++
++	un = tty->driver_data;
++
++	if (!un)
++		return -ENODEV;
++
++	ch = un->un_ch;
++	if (!ch)
++		return -ENODEV;
++
++	if (copy_from_user(&new_digi, (void __user *)new_info, sizeof(int)))
++		return -EFAULT;
++
++	ch->ch_edelay = new_digi;
++
++	/* make the changes now */
++	drp_param(ch);
++
++	return 0;
++}
++
++
++/*
++ *	The usual assortment of ioctl's
++ *
++ *	note:  use tty_check_change to make sure that we are not
++ *	changing the state of a terminal when we are not a process
++ *	in the forground.  See tty_io.c
++ *		rc = tty_check_change(tty);
++ *		if (rc) return rc;
++ */
++static int dgrp_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
++			  unsigned long arg)
++{
++	struct un_struct *un;
++	struct ch_struct *ch;
++	int rc;
++	struct digiflow_struct   dflow;
++
++	if (!tty)
++		return -ENODEV;
++
++	un = tty->driver_data;
++	if (!un)
++		return -ENODEV;
++
++	ch = un->un_ch;
++	if (!ch)
++		return -ENODEV;
++
++	switch (cmd) {
++
++	/*
++	 * Here are all the standard ioctl's that we MUST implement
++	 */
++
++	case TCSBRK:
++		/*
++		 * TCSBRK is SVID version: non-zero arg --> no break
++		 * this behaviour is exploited by tcdrain().
++		 *
++		 * According to POSIX.1 spec (7.2.2.1.2) breaks should be
++		 * between 0.25 and 0.5 seconds
++		 */
++
++		rc = tty_check_change(tty);
++		if (rc)
++			return rc;
++		tty_wait_until_sent(tty, 0);
++
++		if (!arg)
++			rc = dgrp_send_break(ch, 250); /* 1/4 second */
++
++		if (dgrp_tty_chars_in_buffer(tty) != 0)
++			return -EINTR;
++
++		return 0;
++
++	case TCSBRKP:
++		/* support for POSIX tcsendbreak()
++		 *
++		 * According to POSIX.1 spec (7.2.2.1.2) breaks should be
++		 * between 0.25 and 0.5 seconds so we'll ask for something
++		 * in the middle: 0.375 seconds.
++		 */
++		rc = tty_check_change(tty);
++		if (rc)
++			return rc;
++		tty_wait_until_sent(tty, 0);
++
++		rc = dgrp_send_break(ch, arg ? arg*250 : 250);
++
++		if (dgrp_tty_chars_in_buffer(tty) != 0)
++			return -EINTR;
++		return 0;
++
++	case TIOCSBRK:
++		rc = tty_check_change(tty);
++		if (rc)
++			return rc;
++		tty_wait_until_sent(tty, 0);
++
++		/*
++		 * RealPort doesn't support turning on a break unconditionally.
++		 * The RealPort device will stop sending a break automatically
++		 * after the specified time value that we send in.
++		 */
++		rc = dgrp_send_break(ch, 250); /* 1/4 second */
++
++		if (dgrp_tty_chars_in_buffer(tty) != 0)
++			return -EINTR;
++		return 0;
++
++	case TIOCCBRK:
++		/*
++		 * RealPort doesn't support turning off a break unconditionally.
++		 * The RealPort device will stop sending a break automatically
++		 * after the specified time value that was sent when turning on
++		 * the break.
++		 */
++		return 0;
++
++	case TIOCGSOFTCAR:
++		rc = access_ok(VERIFY_WRITE, (void __user *) arg,
++			       sizeof(long));
++		if (rc == 0)
++			return -EFAULT;
++		put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) arg);
++		return 0;
++
++	case TIOCSSOFTCAR:
++		get_user(arg, (unsigned long __user *) arg);
++		tty->termios.c_cflag =
++			((tty->termios.c_cflag & ~CLOCAL) |
++			 (arg ? CLOCAL : 0));
++		return 0;
++
++	case TIOCMGET:
++		rc = access_ok(VERIFY_WRITE, (void __user *) arg,
++				 sizeof(unsigned int));
++		if (rc == 0)
++			return -EFAULT;
++		return get_modem_info(ch, (unsigned int *) arg);
++
++	case TIOCMBIS:
++	case TIOCMBIC:
++	case TIOCMSET:
++		return set_modem_info(ch, cmd, (unsigned int *) arg);
++
++	/*
++	 * Here are any additional ioctl's that we want to implement
++	 */
++
++	case TCFLSH:
++		/*
++		 * The linux tty driver doesn't have a flush
++		 * input routine for the driver, assuming all backed
++		 * up data is in the line disc. buffers.  However,
++		 * we all know that's not the case.  Here, we
++		 * act on the ioctl, but then lie and say we didn't
++		 * so the line discipline will process the flush
++		 * also.
++		 */
++		rc = tty_check_change(tty);
++		if (rc)
++			return rc;
++
++		switch (arg) {
++		case TCIFLUSH:
++		case TCIOFLUSH:
++			/* only flush input if this is the only open unit */
++			if (!IS_PRINT(MINOR(tty_devnum(tty)))) {
++				ch->ch_rout = ch->ch_rin;
++				ch->ch_send |= RR_RX_FLUSH;
++				(ch->ch_nd)->nd_tx_work = 1;
++				(ch->ch_nd)->nd_tx_ready = 1;
++				wake_up_interruptible(&(ch->ch_nd)->nd_tx_waitq);
++			}
++			if (arg == TCIFLUSH)
++				break;
++
++		case TCOFLUSH: /* flush output, or the receive buffer */
++			/*
++			 * This is handled in the tty_ioctl.c code
++			 * calling tty_flush_buffer
++			 */
++			break;
++
++		default:
++			/* POSIX.1 says return EINVAL if we got a bad arg */
++			return -EINVAL;
++		}
++		/* pretend we didn't recognize this IOCTL */
++		return -ENOIOCTLCMD;
++
++#ifdef TIOCGETP
++	case TIOCGETP:
++#endif
++	/*****************************************
++	Linux		HPUX		Function
++	TCSETA		TCSETA		- set the termios
++	TCSETAF		TCSETAF		- wait for drain first, then set termios
++	TCSETAW		TCSETAW		- wait for drain, flush the input queue, then set termios
++	- looking at the tty_ioctl code, these command all call our
++	tty_set_termios at the driver's end, when a TCSETA* is sent,
++	it is expecting the tty to have a termio structure,
++	NOT a termios stucture.  These two structures differ in size
++	and the tty_ioctl code does a conversion before processing them both.
++	- we should treat the TCSETAW TCSETAF ioctls the same, and let
++	the tty_ioctl code do the conversion stuff.
++
++	TCSETS
++	TCSETSF		(none)
++	TCSETSW
++	- the associated tty structure has a termios structure.
++	*****************************************/
++
++	case TCGETS:
++	case TCGETA:
++		return -ENOIOCTLCMD;
++
++	case TCSETAW:
++	case TCSETAF:
++	case TCSETSF:
++	case TCSETSW:
++		/*
++		 * The linux tty driver doesn't have a flush
++		 * input routine for the driver, assuming all backed
++		 * up data is in the line disc. buffers.  However,
++		 * we all know that's not the case.  Here, we
++		 * act on the ioctl, but then lie and say we didn't
++		 * so the line discipline will process the flush
++		 * also.
++		 */
++
++		/*
++		 * Also, now that we have TXPrint, we have to check
++		 * if this is the TXPrint device and the terminal
++		 * device is open. If so, do NOT run check_change,
++		 * as the terminal device is ALWAYS the parent.
++		 */
++		if (!IS_PRINT(MINOR(tty_devnum(tty))) ||
++		    !ch->ch_tun.un_open_count) {
++			rc = tty_check_change(tty);
++			if (rc)
++				return rc;
++		}
++
++		/* wait for all the characters in tbuf to drain */
++		tty_wait_until_sent(tty, 0);
++
++		if ((cmd == TCSETSF) || (cmd == TCSETAF)) {
++			/* flush the contents of the rbuf queue */
++			/* TODO:  check if this is print device? */
++			ch->ch_send |= RR_RX_FLUSH;
++			(ch->ch_nd)->nd_tx_ready = 1;
++			(ch->ch_nd)->nd_tx_work = 1;
++			wake_up_interruptible(&(ch->ch_nd)->nd_tx_waitq);
++			/* do we need to do this?  just to be safe! */
++			ch->ch_rout = ch->ch_rin;
++		}
++
++		/* pretend we didn't recognize this */
++		return -ENOIOCTLCMD;
++
++	case TCXONC:
++		/*
++		 * The Linux Line Discipline (LD) would do this for us if we
++		 * let it, but we have the special firmware options to do this
++		 * the "right way" regardless of hardware or software flow
++		 * control so we'll do it outselves instead of letting the LD
++		 * do it.
++		 */
++		rc = tty_check_change(tty);
++		if (rc)
++			return rc;
++
++		switch (arg) {
++		case TCOON:
++			dgrp_tty_start(tty);
++			return 0;
++		case TCOOFF:
++			dgrp_tty_stop(tty);
++			return 0;
++		case TCION:
++			dgrp_tty_input_start(tty);
++			return 0;
++		case TCIOFF:
++			dgrp_tty_input_stop(tty);
++			return 0;
++		default:
++			return -EINVAL;
++		}
++
++	case DIGI_GETA:
++		/* get information for ditty */
++		if (copy_to_user((struct digi_struct __user *) arg,
++				 &ch->ch_digi, sizeof(struct digi_struct)))
++			return -EFAULT;
++		break;
++
++	case DIGI_SETAW:
++	case DIGI_SETAF:
++		/* wait for all the characters in tbuf to drain */
++		tty_wait_until_sent(tty, 0);
++
++		if (cmd == DIGI_SETAF) {
++			/* flush the contents of the rbuf queue */
++			/* send down a packet with RR_RX_FLUSH set */
++			ch->ch_send |= RR_RX_FLUSH;
++			(ch->ch_nd)->nd_tx_ready = 1;
++			(ch->ch_nd)->nd_tx_work = 1;
++			wake_up_interruptible(&(ch->ch_nd)->nd_tx_waitq);
++			/* do we need to do this?  just to be safe! */
++			ch->ch_rout = ch->ch_rin;
++		}
++
++		/* pretend we didn't recognize this */
++
++	case DIGI_SETA:
++		return dgrp_tty_digiseta(tty, (struct digi_struct *) arg);
++
++	case DIGI_SEDELAY:
++		return dgrp_tty_digisetedelay(tty, (int *) arg);
++
++	case DIGI_GEDELAY:
++		return dgrp_tty_digigetedelay(tty, (int *) arg);
++
++	case DIGI_GETFLOW:
++	case DIGI_GETAFLOW:
++		if (cmd == (DIGI_GETFLOW)) {
++			dflow.startc = tty->termios.c_cc[VSTART];
++			dflow.stopc = tty->termios.c_cc[VSTOP];
++		} else {
++			dflow.startc = ch->ch_xxon;
++			dflow.stopc = ch->ch_xxoff;
++		}
++
++		if (copy_to_user((char __user *)arg, &dflow, sizeof(dflow)))
++			return -EFAULT;
++		break;
++
++	case DIGI_SETFLOW:
++	case DIGI_SETAFLOW:
++
++		if (copy_from_user(&dflow, (char __user *)arg, sizeof(dflow)))
++			return -EFAULT;
++
++		if (cmd == (DIGI_SETFLOW)) {
++			tty->termios.c_cc[VSTART] = dflow.startc;
++			tty->termios.c_cc[VSTOP] = dflow.stopc;
++		} else {
++			ch->ch_xxon = dflow.startc;
++			ch->ch_xxoff = dflow.stopc;
++		}
++		break;
++
++	case DIGI_GETCUSTOMBAUD:
++		rc = access_ok(VERIFY_WRITE, (void __user *) arg, sizeof(int));
++		if (rc == 0)
++			return -EFAULT;
++		put_user(ch->ch_custom_speed, (unsigned int __user *) arg);
++		break;
++
++	case DIGI_SETCUSTOMBAUD:
++	{
++		int new_rate;
++
++		get_user(new_rate, (unsigned int __user *) arg);
++		dgrp_set_custom_speed(ch, new_rate);
++
++		break;
++	}
++
++	default:
++		return -ENOIOCTLCMD;
++	}
++
++	return 0;
++}
++
++/*
++ *  This routine allows the tty driver to be notified when
++ *  the device's termios setting have changed.  Note that we
++ *  should be prepared to accept the case where old == NULL
++ *  and try to do something rational.
++ *
++ *  So we need to make sure that our copies of ch_oflag,
++ *  ch_clag, and ch_iflag reflect the tty->termios flags.
++ */
++static void dgrp_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
++{
++	struct ktermios *ts;
++	struct ch_struct *ch;
++	struct un_struct *un;
++
++	/* seems silly, but we have to check all these! */
++	if (!tty)
++		return;
++
++	un = tty->driver_data;
++	if (!un)
++		return;
++
++	ts = &tty->termios;
++
++	ch = un->un_ch;
++	if (!ch)
++		return;
++
++	drp_param(ch);
++
++	/* the CLOCAL flag has just been set */
++	if (!(old->c_cflag & CLOCAL) && C_CLOCAL(tty))
++		wake_up_interruptible(&un->un_open_wait);
++}
++
++
++/*
++ *	Throttle receiving data.  We just set a bit and stop reading
++ *	data out of the channel buffer.  It will back up and the
++ *	FEP will do whatever is necessary to stop the far end.
++ */
++static void dgrp_tty_throttle(struct tty_struct *tty)
++{
++	struct ch_struct *ch;
++
++	if (!tty)
++		return;
++
++	ch = ((struct un_struct *) tty->driver_data)->un_ch;
++	if (!ch)
++		return;
++
++	ch->ch_flag |= CH_RXSTOP;
++}
++
++
++static void dgrp_tty_unthrottle(struct tty_struct *tty)
++{
++	struct ch_struct *ch;
++
++	if (!tty)
++		return;
++
++	ch = ((struct un_struct *) tty->driver_data)->un_ch;
++	if (!ch)
++		return;
++
++	ch->ch_flag &= ~CH_RXSTOP;
++}
++
++/*
++ *	Stop the transmitter
++ */
++static void dgrp_tty_stop(struct tty_struct *tty)
++{
++	struct ch_struct *ch;
++
++	if (!tty)
++		return;
++
++	ch = ((struct un_struct *) tty->driver_data)->un_ch;
++	if (!ch)
++		return;
++
++	ch->ch_send |= RR_TX_STOP;
++	ch->ch_send &= ~RR_TX_START;
++
++	/* make the change NOW! */
++	(ch->ch_nd)->nd_tx_ready = 1;
++	if (waitqueue_active(&(ch->ch_nd)->nd_tx_waitq))
++		wake_up_interruptible(&(ch->ch_nd)->nd_tx_waitq);
++}
++
++/*
++ *	Start the transmitter
++ */
++static void dgrp_tty_start(struct tty_struct *tty)
++{
++	struct ch_struct *ch;
++
++	if (!tty)
++		return;
++
++	ch = ((struct un_struct *) tty->driver_data)->un_ch;
++	if (!ch)
++		return;
++
++	/* TODO: don't do anything if the transmitter is not stopped */
++
++	ch->ch_send |= RR_TX_START;
++	ch->ch_send &= ~RR_TX_STOP;
++
++	/* make the change NOW! */
++	(ch->ch_nd)->nd_tx_ready = 1;
++	(ch->ch_nd)->nd_tx_work = 1;
++	if (waitqueue_active(&(ch->ch_nd)->nd_tx_waitq))
++		wake_up_interruptible(&(ch->ch_nd)->nd_tx_waitq);
++
++}
++
++/*
++ *	Stop the reciever
++ */
++static void dgrp_tty_input_stop(struct tty_struct *tty)
++{
++	struct ch_struct *ch;
++
++	if (!tty)
++		return;
++
++	ch = ((struct un_struct *) tty->driver_data)->un_ch;
++	if (!ch)
++		return;
++
++	ch->ch_send |= RR_RX_STOP;
++	ch->ch_send &= ~RR_RX_START;
++	(ch->ch_nd)->nd_tx_ready = 1;
++	if (waitqueue_active(&(ch->ch_nd)->nd_tx_waitq))
++		wake_up_interruptible(&(ch->ch_nd)->nd_tx_waitq);
++
++}
++
++
++static void dgrp_tty_send_xchar(struct tty_struct *tty, char c)
++{
++	struct un_struct *un;
++	struct ch_struct *ch;
++
++	if (!tty)
++		return;
++
++	un = tty->driver_data;
++	if (!un)
++		return;
++
++	ch = un->un_ch;
++	if (!ch)
++		return;
++	if (c == STOP_CHAR(tty))
++		ch->ch_send |= RR_RX_STOP;
++	else if (c == START_CHAR(tty))
++		ch->ch_send |= RR_RX_START;
++
++	ch->ch_nd->nd_tx_ready = 1;
++	ch->ch_nd->nd_tx_work = 1;
++
++	return;
++}
++
++
++static void dgrp_tty_input_start(struct tty_struct *tty)
++{
++	struct ch_struct *ch;
++
++	if (!tty)
++		return;
++
++	ch = ((struct un_struct *) tty->driver_data)->un_ch;
++	if (!ch)
++		return;
++
++	ch->ch_send |= RR_RX_START;
++	ch->ch_send &= ~RR_RX_STOP;
++	(ch->ch_nd)->nd_tx_ready = 1;
++	(ch->ch_nd)->nd_tx_work = 1;
++	if (waitqueue_active(&(ch->ch_nd)->nd_tx_waitq))
++		wake_up_interruptible(&(ch->ch_nd)->nd_tx_waitq);
++
++}
++
++
++/*
++ *	Hangup the port.  Like a close, but don't wait for output
++ *	to drain.
++ *
++ *	How do we close all the channels that are open?
++ */
++static void dgrp_tty_hangup(struct tty_struct *tty)
++{
++	struct ch_struct *ch;
++	struct nd_struct *nd;
++	struct un_struct *un;
++
++	if (!tty)
++		return;
++
++	un = tty->driver_data;
++	if (!un)
++		return;
++
++	ch = un->un_ch;
++	if (!ch)
++		return;
++
++	nd = ch->ch_nd;
++
++	if (C_HUPCL(tty)) {
++		/* LOWER DTR */
++		ch->ch_mout &= ~DM_DTR;
++		/* Don't do this here */
++		/* ch->ch_flag |= CH_HANGUP; */
++		ch->ch_nd->nd_tx_ready = 1;
++		ch->ch_nd->nd_tx_work  = 1;
++		if (waitqueue_active(&ch->ch_flag_wait))
++			wake_up_interruptible(&ch->ch_flag_wait);
++	}
++
++}
++
++/************************************************************************/
++/*                                                                      */
++/*       TTY Initialization/Cleanup Functions                           */
++/*                                                                      */
++/************************************************************************/
++
++/*
++ *	Uninitialize the TTY portion of the supplied node.  Free all
++ *      memory and resources associated with this node.  Do it in reverse
++ *      allocation order: this might possibly result in less fragmentation
++ *      of memory, though I don't know this for sure.
++ */
++void
++dgrp_tty_uninit(struct nd_struct *nd)
++{
++	char id[3];
++
++	ID_TO_CHAR(nd->nd_ID, id);
++
++	if (nd->nd_ttdriver_flags & SERIAL_TTDRV_REG) {
++		tty_unregister_driver(nd->nd_serial_ttdriver);
++
++		kfree(nd->nd_serial_ttdriver->ttys);
++		nd->nd_serial_ttdriver->ttys = NULL;
++
++		put_tty_driver(nd->nd_serial_ttdriver);
++		nd->nd_ttdriver_flags &= ~SERIAL_TTDRV_REG;
++	}
++
++	if (nd->nd_ttdriver_flags & CALLOUT_TTDRV_REG) {
++		tty_unregister_driver(nd->nd_callout_ttdriver);
++
++		kfree(nd->nd_callout_ttdriver->ttys);
++		nd->nd_callout_ttdriver->ttys = NULL;
++
++		put_tty_driver(nd->nd_callout_ttdriver);
++		nd->nd_ttdriver_flags &= ~CALLOUT_TTDRV_REG;
++	}
++
++	if (nd->nd_ttdriver_flags & XPRINT_TTDRV_REG) {
++		tty_unregister_driver(nd->nd_xprint_ttdriver);
++
++		kfree(nd->nd_xprint_ttdriver->ttys);
++		nd->nd_xprint_ttdriver->ttys = NULL;
++
++		put_tty_driver(nd->nd_xprint_ttdriver);
++		nd->nd_ttdriver_flags &= ~XPRINT_TTDRV_REG;
++	}
++}
++
++
++
++/*
++ *     Initialize the TTY portion of the supplied node.
++ */
++int
++dgrp_tty_init(struct nd_struct *nd)
++{
++	char id[3];
++	int  rc;
++	int  i;
++
++	ID_TO_CHAR(nd->nd_ID, id);
++
++	/*
++	 *  Initialize the TTDRIVER structures.
++	 */
++
++	nd->nd_serial_ttdriver = alloc_tty_driver(CHAN_MAX);
++	sprintf(nd->nd_serial_name,  "tty_dgrp_%s_", id);
++
++	nd->nd_serial_ttdriver->owner = THIS_MODULE;
++	nd->nd_serial_ttdriver->name = nd->nd_serial_name;
++	nd->nd_serial_ttdriver->name_base = 0;
++	nd->nd_serial_ttdriver->major = 0;
++	nd->nd_serial_ttdriver->minor_start = 0;
++	nd->nd_serial_ttdriver->type = TTY_DRIVER_TYPE_SERIAL;
++	nd->nd_serial_ttdriver->subtype = SERIAL_TYPE_NORMAL;
++	nd->nd_serial_ttdriver->init_termios = DefaultTermios;
++	nd->nd_serial_ttdriver->driver_name = "dgrp";
++	nd->nd_serial_ttdriver->flags = (TTY_DRIVER_REAL_RAW |
++					 TTY_DRIVER_DYNAMIC_DEV |
++					 TTY_DRIVER_HARDWARE_BREAK);
++
++	/* The kernel wants space to store pointers to tty_structs. */
++	nd->nd_serial_ttdriver->ttys =
++		kzalloc(CHAN_MAX * sizeof(struct tty_struct *), GFP_KERNEL);
++	if (!nd->nd_serial_ttdriver->ttys)
++		return -ENOMEM;
++
++	tty_set_operations(nd->nd_serial_ttdriver, &dgrp_tty_ops);
++
++	if (!(nd->nd_ttdriver_flags & SERIAL_TTDRV_REG)) {
++		/*
++		 *   Register tty devices
++		 */
++		rc = tty_register_driver(nd->nd_serial_ttdriver);
++		if (rc < 0) {
++			/*
++			 * If errno is EBUSY, this means there are no more
++			 * slots available to have us auto-majored.
++			 * (Which is currently supported up to 256)
++			 *
++			 * We can still request majors above 256,
++			 * we just have to do it manually.
++			 */
++			if (rc == -EBUSY) {
++				int i;
++				int max_majors = 1U << (32 - MINORBITS);
++				for (i = 256; i < max_majors; i++) {
++					nd->nd_serial_ttdriver->major = i;
++					rc = tty_register_driver(nd->nd_serial_ttdriver);
++					if (rc >= 0)
++						break;
++				}
++				/* Really fail now, since we ran out
++				 * of majors to try. */
++				if (i == max_majors)
++					return rc;
++
++			} else {
++				return rc;
++			}
++		}
++		nd->nd_ttdriver_flags |= SERIAL_TTDRV_REG;
++	}
++
++	nd->nd_callout_ttdriver = alloc_tty_driver(CHAN_MAX);
++	sprintf(nd->nd_callout_name, "cu_dgrp_%s_",  id);
++
++	nd->nd_callout_ttdriver->owner = THIS_MODULE;
++	nd->nd_callout_ttdriver->name = nd->nd_callout_name;
++	nd->nd_callout_ttdriver->name_base = 0;
++	nd->nd_callout_ttdriver->major = nd->nd_serial_ttdriver->major;
++	nd->nd_callout_ttdriver->minor_start = 0x40;
++	nd->nd_callout_ttdriver->type = TTY_DRIVER_TYPE_SERIAL;
++	nd->nd_callout_ttdriver->subtype = SERIAL_TYPE_CALLOUT;
++	nd->nd_callout_ttdriver->init_termios = DefaultTermios;
++	nd->nd_callout_ttdriver->driver_name = "dgrp";
++	nd->nd_callout_ttdriver->flags = (TTY_DRIVER_REAL_RAW |
++					  TTY_DRIVER_DYNAMIC_DEV |
++					  TTY_DRIVER_HARDWARE_BREAK);
++
++	/* The kernel wants space to store pointers to tty_structs. */
++	nd->nd_callout_ttdriver->ttys =
++		kzalloc(CHAN_MAX * sizeof(struct tty_struct *), GFP_KERNEL);
++	if (!nd->nd_callout_ttdriver->ttys)
++		return -ENOMEM;
++
++	tty_set_operations(nd->nd_callout_ttdriver, &dgrp_tty_ops);
++
++	if (dgrp_register_cudevices) {
++		if (!(nd->nd_ttdriver_flags & CALLOUT_TTDRV_REG)) {
++			/*
++			 *   Register cu devices
++			 */
++			rc = tty_register_driver(nd->nd_callout_ttdriver);
++			if (rc < 0)
++				return rc;
++			nd->nd_ttdriver_flags |= CALLOUT_TTDRV_REG;
++		}
++	}
++
++
++	nd->nd_xprint_ttdriver = alloc_tty_driver(CHAN_MAX);
++	sprintf(nd->nd_xprint_name,  "pr_dgrp_%s_", id);
++
++	nd->nd_xprint_ttdriver->owner = THIS_MODULE;
++	nd->nd_xprint_ttdriver->name = nd->nd_xprint_name;
++	nd->nd_xprint_ttdriver->name_base = 0;
++	nd->nd_xprint_ttdriver->major = nd->nd_serial_ttdriver->major;
++	nd->nd_xprint_ttdriver->minor_start = 0x80;
++	nd->nd_xprint_ttdriver->type = TTY_DRIVER_TYPE_SERIAL;
++	nd->nd_xprint_ttdriver->subtype = SERIAL_TYPE_XPRINT;
++	nd->nd_xprint_ttdriver->init_termios = DefaultTermios;
++	nd->nd_xprint_ttdriver->driver_name = "dgrp";
++	nd->nd_xprint_ttdriver->flags = (TTY_DRIVER_REAL_RAW |
++					 TTY_DRIVER_DYNAMIC_DEV |
++					 TTY_DRIVER_HARDWARE_BREAK);
++
++	/* The kernel wants space to store pointers to tty_structs. */
++	nd->nd_xprint_ttdriver->ttys =
++		kzalloc(CHAN_MAX * sizeof(struct tty_struct *), GFP_KERNEL);
++	if (!nd->nd_xprint_ttdriver->ttys)
++		return -ENOMEM;
++
++	tty_set_operations(nd->nd_xprint_ttdriver, &dgrp_tty_ops);
++
++	if (dgrp_register_prdevices) {
++		if (!(nd->nd_ttdriver_flags & XPRINT_TTDRV_REG)) {
++			/*
++			 *   Register transparent print devices
++			 */
++			rc = tty_register_driver(nd->nd_xprint_ttdriver);
++			if (rc < 0)
++				return rc;
++			nd->nd_ttdriver_flags |= XPRINT_TTDRV_REG;
++		}
++	}
++
++	for (i = 0; i < CHAN_MAX; i++) {
++		struct ch_struct *ch = nd->nd_chan + i;
++
++		ch->ch_nd = nd;
++		ch->ch_digi = digi_init;
++		ch->ch_edelay = 100;
++		ch->ch_custom_speed = 0;
++		ch->ch_portnum = i;
++		ch->ch_tun.un_ch = ch;
++		ch->ch_pun.un_ch = ch;
++		ch->ch_tun.un_type = SERIAL_TYPE_NORMAL;
++		ch->ch_pun.un_type = SERIAL_TYPE_XPRINT;
++
++		init_waitqueue_head(&(ch->ch_flag_wait));
++		init_waitqueue_head(&(ch->ch_sleep));
++
++		init_waitqueue_head(&(ch->ch_tun.un_open_wait));
++		init_waitqueue_head(&(ch->ch_tun.un_close_wait));
++
++		init_waitqueue_head(&(ch->ch_pun.un_open_wait));
++		init_waitqueue_head(&(ch->ch_pun.un_close_wait));
++		tty_port_init(&ch->port);
++		tty_port_init(&ch->port);
++	}
++	return 0;
++}
+diff --git a/drivers/staging/dgrp/digirp.h b/drivers/staging/dgrp/digirp.h
+new file mode 100644
+index 000000000000..33c1394fade7
+--- /dev/null
++++ b/drivers/staging/dgrp/digirp.h
+@@ -0,0 +1,129 @@
++/************************************************************************
++ * HP-UX Realport Daemon interface file.
++ *
++ * Copyright (C) 1998, by Digi International.  All Rights Reserved.
++ ************************************************************************/
++
++#ifndef _DIGIDRP_H
++#define _DIGIDRP_H
++
++/************************************************************************
++ * This file contains defines for the ioctl() interface to
++ * the realport driver.   This ioctl() interface is used by the
++ * daemon to set speed setup parameters honored by the driver.
++ ************************************************************************/
++
++struct link_struct {
++	int lk_fast_rate;  /* Fast line rate to be used
++			      when the delay is less-equal
++			      to lk_fast_delay */
++
++	int lk_fast_delay; /* Fast line rate delay in
++			      milliseconds */
++
++	int lk_slow_rate;  /* Slow line rate to be used when
++			      the delay is greater-equal
++			      to lk_slow_delay */
++
++	int lk_slow_delay; /* Slow line rate delay in
++			      milliseconds */
++
++	int lk_header_size; /* Estimated packet header size
++			       when sent across the slowest
++			       link.  */
++};
++
++#define DIGI_GETLINK	_IOW('e', 103, struct link_struct)	/* Get link parameters */
++#define DIGI_SETLINK	_IOW('e', 104, struct link_struct)	/* Set link parameters */
++
++
++/************************************************************************
++ * This module provides application access to special Digi
++ * serial line enhancements which are not standard UNIX(tm) features.
++ ************************************************************************/
++
++struct	digiflow_struct {
++	unsigned char	startc;				/* flow cntl start char	*/
++	unsigned char	stopc;				/* flow cntl stop char	*/
++};
++
++/************************************************************************
++ * Values for digi_flags
++ ************************************************************************/
++#define DIGI_IXON	0x0001		/* Handle IXON in the FEP	*/
++#define DIGI_FAST	0x0002		/* Fast baud rates		*/
++#define RTSPACE		0x0004		/* RTS input flow control	*/
++#define CTSPACE		0x0008		/* CTS output flow control	*/
++#define DSRPACE		0x0010		/* DSR output flow control	*/
++#define DCDPACE		0x0020		/* DCD output flow control	*/
++#define DTRPACE		0x0040		/* DTR input flow control	*/
++#define DIGI_COOK	0x0080		/* Cooked processing done in FEP */
++#define DIGI_FORCEDCD	0x0100		/* Force carrier		*/
++#define	DIGI_ALTPIN	0x0200		/* Alternate RJ-45 pin config	*/
++#define	DIGI_AIXON	0x0400		/* Aux flow control in fep	*/
++#define	DIGI_PRINTER	0x0800		/* Hold port open for flow cntrl */
++#define DIGI_PP_INPUT	0x1000		/* Change parallel port to input */
++#define DIGI_422	0x4000		/* Change parallel port to input */
++#define DIGI_RTS_TOGGLE	0x8000		/* Support RTS Toggle		 */
++
++
++/************************************************************************
++ * Values associated with transparent print
++ ************************************************************************/
++#define DIGI_PLEN	8		/* String length */
++#define	DIGI_TSIZ	10		/* Terminal string len */
++
++
++/************************************************************************
++ * Structure used with ioctl commands for DIGI parameters.
++ ************************************************************************/
++struct digi_struct {
++	unsigned short	digi_flags;		/* Flags (see above)	*/
++	unsigned short	digi_maxcps;		/* Max printer CPS	*/
++	unsigned short	digi_maxchar;		/* Max chars in print queue */
++	unsigned short	digi_bufsize;		/* Buffer size		*/
++	unsigned char	digi_onlen;		/* Length of ON string	*/
++	unsigned char	digi_offlen;		/* Length of OFF string	*/
++	char		digi_onstr[DIGI_PLEN];	/* Printer on string	*/
++	char		digi_offstr[DIGI_PLEN];	/* Printer off string	*/
++	char		digi_term[DIGI_TSIZ];	/* terminal string	*/
++};
++
++/************************************************************************
++ * Ioctl command arguments for DIGI parameters.
++ ************************************************************************/
++/* Read params */
++#define DIGI_GETA	_IOR('e', 94, struct digi_struct)
++
++/* Set params */
++#define DIGI_SETA	_IOW('e', 95, struct digi_struct)
++
++/* Drain & set params	*/
++#define DIGI_SETAW	_IOW('e', 96, struct digi_struct)
++
++/* Drain, flush & set params */
++#define DIGI_SETAF	_IOW('e', 97, struct digi_struct)
++
++/* Get startc/stopc flow control characters */
++#define	DIGI_GETFLOW	_IOR('e', 99, struct digiflow_struct)
++
++/* Set startc/stopc flow control characters */
++#define	DIGI_SETFLOW	_IOW('e', 100, struct digiflow_struct)
++
++/* Get Aux. startc/stopc flow control chars */
++#define	DIGI_GETAFLOW	_IOR('e', 101, struct digiflow_struct)
++
++/* Set Aux. startc/stopc flow control chars */
++#define	DIGI_SETAFLOW	_IOW('e', 102, struct digiflow_struct)
++
++/* Set integer baud rate */
++#define	DIGI_SETCUSTOMBAUD	_IOW('e', 106, int)
++
++/* Get integer baud rate */
++#define	DIGI_GETCUSTOMBAUD	_IOR('e', 107, int)
++
++#define	DIGI_GEDELAY	_IOR('d', 246, int)	/* Get edelay */
++#define	DIGI_SEDELAY	_IOW('d', 247, int)	/* Get edelay */
++
++
++#endif /* _DIGIDRP_H */
+diff --git a/drivers/staging/dgrp/drp.h b/drivers/staging/dgrp/drp.h
+new file mode 100644
+index 000000000000..84a1e7be4899
+--- /dev/null
++++ b/drivers/staging/dgrp/drp.h
+@@ -0,0 +1,693 @@
++/*
++ *
++ * Copyright 1999 Digi International (www.digi.com)
++ *     Gene Olson  
++ *     James Puzzo 
++ *     Scott Kilau 
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
++ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
++ * PURPOSE.  See the GNU General Public License for more details.
++ *
++ */
++
++/************************************************************************
++ * Master include file for Linux Realport Driver.
++ ************************************************************************/
++
++#ifndef __DRP_H
++#define __DRP_H
++
++#include 
++#include 
++#include 
++#include 
++
++
++#include "digirp.h"
++
++/************************************************************************
++ * Tuning parameters.
++ ************************************************************************/
++
++#define CHAN_MAX	64		/* Max # ports per server */
++
++#define SEQ_MAX		128		/* Max # transmit sequences (2^n) */
++#define SEQ_MASK	(SEQ_MAX-1)	/* Sequence buffer modulus mask */
++
++#define TBUF_MAX	4096		/* Size of transmit buffer (2^n) */
++#define RBUF_MAX	4096		/* Size of receive buffer (2^n) */
++
++#define TBUF_MASK	(TBUF_MAX-1)	/* Transmit buffer modulus mask */
++#define RBUF_MASK	(RBUF_MAX-1)	/* Receive buffer modulus mask */
++
++#define TBUF_LOW	1000		/* Transmit low water mark */
++
++#define UIO_BASE	1000		/* Base for write operations */
++#define UIO_MIN		2000		/* Minimum size application buffer */
++#define UIO_MAX		8100		/* Unix I/O buffer size */
++
++#define MON_MAX		65536		/* Monitor buffer size (2^n) */
++#define MON_MASK	(MON_MAX-1)	/* Monitor wrap mask */
++
++#define DPA_MAX		65536		/* DPA buffer size (2^n) */
++#define DPA_MASK	(DPA_MAX-1)	/* DPA wrap mask */
++#define DPA_HIGH_WATER	58000		/* Enforce flow control when
++					 * over this amount
++					 */
++
++#define IDLE_MAX	(20 * HZ)	/* Max TCP link idle time */
++
++#define MAX_DESC_LEN	100		/* Maximum length of stored PS
++					 * description
++					 */
++
++#define WRITEBUFLEN	((4096) + 4)    /* 4 extra for alignment play space */
++
++#define VPDSIZE		512
++
++/************************************************************************
++ * Minor device decoding conventions.
++ ************************************************************************
++ *
++ * For Linux, the net and mon devices are handled via "proc", so we
++ * only have to mux the "tty" devices.  Since every PortServer will
++ * have an individual major number, the PortServer number does not
++ * need to be encoded, and in fact, does not need to exist.
++ *
++ */
++
++/*
++ * Port device decoding conventions:
++ *
++ *	Device 00 - 3f        64 dial-in modem devices. (tty)
++ *	Device 40 - 7f        64 dial-out tty devices.  (cu)
++ *	Device 80 - bf        64 dial-out printer devices.
++ *
++ *  IS_PRINT(dev)		This is a printer device.
++ *
++ *  OPEN_CATEGORY(dev)		Specifies the device category.  No two
++ *				devices of different categories may be open
++ *				at the same time.
++ *
++ * The following require the category returned by OPEN_CATEGORY().
++ *
++ *  OPEN_WAIT_AVAIL(cat)	Waits on open until the device becomes
++ *				available.  Fails if NDELAY specified.
++ *
++ *  OPEN_WAIT_CARRIER(cat)	Waits on open if carrier is not present.
++ *				Succeeds if NDELAY is given.
++ *
++ *  OPEN_FORCES_CARRIER(cat)	Carrier is forced high on open.
++ *
++ */
++
++#define PORT_NUM(dev)			((dev) & 0x3f)
++
++#define OPEN_CATEGORY(dev)		((((dev) & 0x80) & 0x40))
++#define IS_PRINT(dev)			(((dev) & 0xff) >= 0x80)
++
++#define OPEN_WAIT_AVAIL(cat)		(((cat) & 0x40) == 0x000)
++#define OPEN_WAIT_CARRIER(cat)		(((cat) & 0x40) == 0x000)
++#define OPEN_FORCES_CARRIER(cat)	(((cat) & 0x40) != 0x000)
++
++
++/************************************************************************
++ * Modem signal defines for 16450/16550 compatible FEP.
++ * set in ch_mout, ch_mflow, ch_mlast etc
++ ************************************************************************/
++
++/* TODO : Re-verify that these modem signal definitions are correct */
++
++#define DM_DTR		0x01
++#define DM_RTS		0x02
++#define DM_RTS_TOGGLE	0x04
++
++#define DM_OUT1		0x04
++#define DM_OUT2		0x08
++
++#define DM_CTS		0x10
++#define DM_DSR		0x20
++#define DM_RI		0x40
++#define DM_CD		0x80		/* This is the DCD flag */
++
++
++/************************************************************************
++ * Realport Event Flags.
++ ************************************************************************/
++
++#define EV_OPU		0x0001		/* Ouput paused by client */
++#define EV_OPS		0x0002		/* Output paused by XOFF */
++#define EV_OPX		0x0004		/* Output paused by XXOFF */
++#define EV_OPH		0x0008		/* Output paused by MFLOW */
++#define EV_IPU		0x0010		/* Input paused by client */
++#define EV_IPS		0x0020		/* Input paused by hi/low water */
++#define EV_TXB		0x0040		/* Transmit break pending */
++#define EV_TXI		0x0080		/* Transmit immediate pending */
++#define EV_TXF		0x0100		/* Transmit flow control pending */
++#define EV_RXB		0x0200		/* Break received */
++
++
++/************************************************************************
++ * Realport CFLAGS.
++ ************************************************************************/
++
++#define CF_CS5		0x0000		/* 5 bit characters */
++#define CF_CS6		0x0010		/* 6 bit characters */
++#define CF_CS7		0x0020		/* 7 bit characters */
++#define CF_CS8		0x0030		/* 8 bit characters */
++#define CF_CSIZE	0x0030		/* Character size */
++#define CF_CSTOPB	0x0040		/* Two stop bits */
++#define CF_CREAD	0x0080		/* Enable receiver */
++#define CF_PARENB	0x0100		/* Enable parity */
++#define CF_PARODD	0x0200		/* Odd parity */
++#define CF_HUPCL	0x0400		/* Drop DTR on close */
++
++
++/************************************************************************
++ * Realport XFLAGS.
++ ************************************************************************/
++
++#define XF_XPAR		0x0001		/* Enable Mark/Space Parity */
++#define XF_XMODEM	0x0002		/* Enable in-band modem signalling */
++#define XF_XCASE	0x0004		/* Convert special characters */
++#define XF_XEDATA	0x0008		/* Error data in stream */
++#define XF_XTOSS	0x0010		/* Toss IXANY characters */
++#define XF_XIXON	0x0020		/* xxon/xxoff enable */
++
++
++/************************************************************************
++ * Realport IFLAGS.
++ ************************************************************************/
++
++#define IF_IGNBRK	0x0001		/* Ignore input break */
++#define IF_BRKINT	0x0002		/* Break interrupt */
++#define IF_IGNPAR	0x0004		/* Ignore error characters */
++#define IF_PARMRK	0x0008		/* Error chars marked with 0xff */
++#define IF_INPCK	0x0010		/* Input parity checking enabled */
++#define IF_ISTRIP	0x0020		/* Input chars masked with 0x7F */
++#define IF_IXON		0x0400		/* Output software flow control */
++#define IF_IXANY	0x0800		/* Restart output on any char */
++#define	IF_IXOFF	0x1000		/* Input software flow control */
++#define IF_DOSMODE	0x8000		/* 16450-compatible errors */
++
++
++/************************************************************************
++ * Realport OFLAGS.
++ ************************************************************************/
++
++#define OF_OLCUC	0x0002		/* Map lower to upper case */
++#define OF_ONLCR	0x0004		/* Map NL to CR-NL */
++#define OF_OCRNL	0x0008		/* Map CR to NL */
++#define OF_ONOCR	0x0010		/* No CR output at column 0 */
++#define OF_ONLRET	0x0020		/* Assume NL does NL/CR */
++#define OF_TAB3		0x1800		/* Tabs expand to 8 spaces */
++#define OF_TABDLY	0x1800		/* Tab delay */
++
++/************************************************************************
++ * Unit flag definitions for un_flag.
++ ************************************************************************/
++
++/* These are the DIGI unit flags */
++#define UN_EXCL		0x00010000	/* Exclusive open */
++#define UN_STICKY	0x00020000	/* TTY Settings are now sticky */
++#define UN_BUSY		0x00040000	/* Some work this channel */
++#define UN_PWAIT	0x00080000	/* Printer waiting for terminal */
++#define UN_TIME		0x00100000	/* Waiting on time */
++#define UN_EMPTY	0x00200000	/* Waiting output queue empty */
++#define UN_LOW		0x00400000	/* Waiting output low water */
++#define UN_DIGI_MASK	0x00FF0000	/* Waiting output low water */
++
++/*
++ * Definitions for async_struct (and serial_struct) flags field
++ *
++ * these are the ASYNC flags copied from serial.h
++ *
++ */
++#define UN_HUP_NOTIFY	0x0001 /* Notify getty on hangups and
++				* closes on the callout port
++				*/
++#define UN_FOURPORT	0x0002	/* Set OU1, OUT2 per AST Fourport settings */
++#define UN_SAK		0x0004	/* Secure Attention Key (Orange book) */
++#define UN_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */
++
++#define UN_SPD_MASK	0x0030
++#define UN_SPD_HI	0x0010	/* Use 56000 instead of 38400 bps */
++#define UN_SPD_VHI	0x0020	/* Use 115200 instead of 38400 bps */
++#define UN_SPD_CUST	0x0030	/* Use user-specified divisor */
++
++#define UN_SKIP_TEST	0x0040 /* Skip UART test during autoconfiguration */
++#define UN_AUTO_IRQ	0x0080 /* Do automatic IRQ during autoconfiguration */
++
++#define UN_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */
++#define UN_PGRP_LOCKOUT	   0x0200 /* Lock out cua opens based on pgrp */
++#define UN_CALLOUT_NOHUP   0x0400 /* Don't do hangups for cua device */
++
++#define UN_FLAGS	0x0FFF	/* Possible legal async flags */
++#define UN_USR_MASK	0x0430	/* Legal flags that non-privileged
++				 * users can set or reset
++				 */
++
++#define UN_INITIALIZED		0x80000000 /* Serial port was initialized */
++#define UN_CALLOUT_ACTIVE	0x40000000 /* Call out device is active */
++#define UN_NORMAL_ACTIVE	0x20000000 /* Normal device is active */
++#define UN_BOOT_AUTOCONF	0x10000000 /* Autoconfigure port on bootup */
++#define UN_CLOSING		0x08000000 /* Serial port is closing */
++#define UN_CTS_FLOW		0x04000000 /* Do CTS flow control */
++#define UN_CHECK_CD		0x02000000 /* i.e., CLOCAL */
++#define UN_SHARE_IRQ		0x01000000 /* for multifunction cards */
++
++
++/************************************************************************
++ * Structure for terminal or printer unit.  struct un_struct
++ *
++ * Note that in some places the code assumes the "tty_t" is placed
++ * first in the structure.
++ ************************************************************************/
++
++struct un_struct {
++	struct tty_struct *un_tty;		/* System TTY struct */
++	struct ch_struct *un_ch;		/* Associated channel */
++
++	ushort     un_open_count;		/* Successful open count */
++	int		un_flag;		/* Unit flags */
++	ushort     un_tbusy;		/* Busy transmit count */
++
++	wait_queue_head_t  un_open_wait;
++	wait_queue_head_t  un_close_wait;
++	ushort	un_type;
++	struct device *un_sysfs;
++};
++
++
++/************************************************************************
++ * Channel State Numbers for ch_state.
++ ************************************************************************/
++
++/*
++ * The ordering is important.
++ *
++ *    state <= CS_WAIT_CANCEL implies the channel is definitely closed.
++ *
++ *    state >= CS_WAIT_FAIL  implies the channel is definitely open.
++ *
++ *    state >= CS_READY implies data is allowed on the channel.
++ */
++
++enum dgrp_ch_state_t {
++	CS_IDLE = 0,	    /* Channel is idle */
++	CS_WAIT_OPEN = 1,   /* Waiting for Immediate Open Resp */
++	CS_WAIT_CANCEL = 2, /* Waiting for Per/Incom Cancel Resp */
++	CS_WAIT_FAIL = 3,   /* Waiting for Immed Open Failure */
++	CS_SEND_QUERY = 4,  /* Ready to send Port Query */
++	CS_WAIT_QUERY = 5,  /* Waiting for Port Query Response */
++	CS_READY = 6,	    /* Ready to accept commands and data */
++	CS_SEND_CLOSE =	7,  /* Ready to send Close Request */
++	CS_WAIT_CLOSE =	8   /* Waiting for Close Response */
++};
++
++/************************************************************************
++ * Device flag definitions for ch_flag.
++ ************************************************************************/
++
++/*
++ *  Note that the state of the two carrier based flags is key.	When
++ *  we check for carrier state transitions, we look at the current
++ *  physical state of the DCD line and compare it with PHYS_CD (which
++ *  was the state the last time we checked), and we also determine
++ *  a new virtual state (composite of the physical state, FORCEDCD,
++ *  CLOCAL, etc.) and compare it with VIRT_CD.
++ *
++ *  VIRTUAL transitions high will have the side effect of waking blocked
++ *  opens.
++ *
++ *  PHYSICAL transitions low will cause hangups to occur _IF_ the virtual
++ *  state is also low.	We DON'T want to hangup on a PURE virtual drop.
++ */
++
++#define CH_HANGUP	0x00002		/* Server port ready to close */
++
++#define CH_VIRT_CD	0x00004		/* Carrier was virtually present */
++#define CH_PHYS_CD	0x00008		/* Carrier was physically present */
++
++#define CH_CLOCAL	0x00010		/* CLOCAL set in cflags */
++#define CH_BAUD0	0x00020		/* Baud rate zero hangup */
++
++#define CH_FAST_READ	0x00040		/* Fast reads are enabled */
++#define CH_FAST_WRITE	0x00080		/* Fast writes are enabled */
++
++#define CH_PRON		0x00100		/* Printer on string active */
++#define CH_RX_FLUSH	0x00200		/* Flushing receive data */
++#define CH_LOW		0x00400		/* Thread waiting for LOW water */
++#define CH_EMPTY	0x00800		/* Thread waiting for EMPTY */
++#define CH_DRAIN	0x01000		/* Close is waiting to drain */
++#define CH_INPUT	0x02000		/* Thread waiting for INPUT */
++#define CH_RXSTOP	0x04000		/* Stop output to ldisc */
++#define CH_PARAM	0x08000		/* A parameter was updated */
++#define CH_WAITING_SYNC 0x10000		/* A pending sync was assigned
++					 * to this port.
++					 */
++#define CH_PORT_GONE	0x20000		/* Port has disappeared */
++#define CH_TX_BREAK	0x40000		/* TX Break to be sent,
++					 * but has not yet.
++					 */
++
++/************************************************************************
++ * Types of Open Requests for ch_otype.
++ ************************************************************************/
++
++#define OTYPE_IMMEDIATE	  0		/* Immediate Open */
++#define OTYPE_PERSISTENT  1		/* Persistent Open */
++#define OTYPE_INCOMING	  2		/* Incoming Open */
++
++
++/************************************************************************
++ * Request/Response flags.
++ ************************************************************************/
++
++#define RR_SEQUENCE	0x0001		/* Get server RLAST, TIN */
++#define RR_STATUS	0x0002		/* Get server MINT, EINT */
++#define RR_BUFFER	0x0004		/* Get server RSIZE, TSIZE */
++#define RR_CAPABILITY	0x0008		/* Get server port capabilities */
++
++#define RR_TX_FLUSH	0x0040		/* Flush output buffers */
++#define RR_RX_FLUSH	0x0080		/* Flush input buffers */
++
++#define RR_TX_STOP	0x0100		/* Pause output */
++#define RR_RX_STOP	0x0200		/* Pause input */
++#define RR_TX_START	0x0400		/* Start output */
++#define RR_RX_START	0x0800		/* Start input */
++
++#define RR_TX_BREAK	0x1000		/* Send BREAK */
++#define RR_TX_ICHAR	0x2000		/* Send character immediate */
++
++
++/************************************************************************
++ * Channel information structure.   struct ch_struct
++ ************************************************************************/
++
++struct ch_struct {
++	struct digi_struct ch_digi;		/* Digi variables */
++	int	ch_edelay;		/* Digi edelay */
++
++	struct tty_port port;
++	struct un_struct ch_tun;	/* Terminal unit info */
++	struct un_struct ch_pun;	/* Printer unit info */
++
++	struct nd_struct *ch_nd;	/* Node pointer */
++	u8  *ch_tbuf;		/* Local Transmit Buffer */
++	u8  *ch_rbuf;		/* Local Receive Buffer */
++	ulong	ch_cpstime;		/* Printer CPS time */
++	ulong	ch_waketime;		/* Printer wake time */
++
++	ulong	ch_flag;		/* CH_* flags */
++
++	enum dgrp_ch_state_t ch_state;		/* CS_* Protocol state */
++	ushort	ch_send;		/* Bit vector of RR_* requests */
++	ushort	ch_expect;		/* Bit vector of RR_* responses */
++	ushort	ch_wait_carrier;	/* Thread count waiting for carrier */
++	ushort	ch_wait_count[3];	/* Thread count waiting by otype */
++
++	ushort	ch_portnum;		/* Port number */
++	ushort	ch_open_count;		/* Successful open count */
++	ushort	ch_category;		/* Device category */
++	ushort	ch_open_error;		/* Last open error number */
++	ushort	ch_break_time;		/* Pending break request time */
++	ushort	ch_cpsrem;		/* Printer CPS remainder */
++	ushort	ch_ocook;		/* Realport fastcook oflags */
++	ushort	ch_inwait;		/* Thread count in CLIST input */
++
++	ushort	ch_tin;			/* Local transmit buffer in ptr */
++	ushort	ch_tout;		/* Local transmit buffer out ptr */
++	ushort	ch_s_tin;		/* Realport TIN */
++	ushort	ch_s_tpos;		/* Realport TPOS */
++	ushort	ch_s_tsize;		/* Realport TSIZE */
++	ushort	ch_s_treq;		/* Realport TREQ */
++	ushort	ch_s_elast;		/* Realport ELAST */
++
++	ushort	ch_rin;			/* Local receive buffer in ptr */
++	ushort	ch_rout;		/* Local receive buffer out ptr */
++	ushort	ch_s_rin;		/* Realport RIN */
++	/* David Fries 7-13-2001, ch_s_rin should be renamed ch_s_rout because
++	 * the variable we want to represent is the PortServer's ROUT, which is
++	 * the sequence number for the next byte the PortServer will send us.
++	 * RIN is the sequence number for the next byte the PortServer will
++	 * receive from the uart.  The port server will send data as long as
++	 * ROUT is less than RWIN.  What would happen is the port is opened, it
++	 * receives data, it gives the value of RIN, we set the RWIN to
++	 * RIN+RBUF_MAX-1, it sends us RWIN-ROUT bytes which overflows.	 ROUT
++	 * is set to zero when the port is opened, so we start at zero and
++	 * count up as data is received.
++	 */
++	ushort	ch_s_rwin;		/* Realport RWIN */
++	ushort	ch_s_rsize;		/* Realport RSIZE */
++
++	ushort	ch_tmax;		/* Local TMAX */
++	ushort	ch_ttime;		/* Local TTIME */
++	ushort	ch_rmax;		/* Local RMAX */
++	ushort	ch_rtime;		/* Local RTIME */
++	ushort	ch_rlow;		/* Local RLOW */
++	ushort	ch_rhigh;		/* Local RHIGH */
++
++	ushort	ch_s_tmax;		/* Realport TMAX */
++	ushort	ch_s_ttime;		/* Realport TTIME */
++	ushort	ch_s_rmax;		/* Realport RMAX */
++	ushort	ch_s_rtime;		/* Realport RTIME */
++	ushort	ch_s_rlow;		/* Realport RLOW */
++	ushort	ch_s_rhigh;		/* Realport RHIGH */
++
++	ushort	ch_brate;		/* Local baud rate */
++	ushort	ch_cflag;		/* Local tty cflags */
++	ushort	ch_iflag;		/* Local tty iflags */
++	ushort	ch_oflag;		/* Local tty oflags */
++	ushort	ch_xflag;		/* Local tty xflags */
++
++	ushort	ch_s_brate;		/* Realport BRATE */
++	ushort	ch_s_cflag;		/* Realport CFLAG */
++	ushort	ch_s_iflag;		/* Realport IFLAG */
++	ushort	ch_s_oflag;		/* Realport OFLAG */
++	ushort	ch_s_xflag;		/* Realport XFLAG */
++
++	u8	ch_otype;		/* Open request type */
++	u8	ch_pscan_savechar;	/* Last character read by parity scan */
++	u8	ch_pscan_state;		/* PScan State based on last 2 chars */
++	u8	ch_otype_waiting;	/* Type of open pending in server */
++	u8	ch_flush_seq;		/* Receive flush end sequence */
++	u8	ch_s_mlast;		/* Realport MLAST */
++
++	u8	ch_mout;		/* Local MOUT */
++	u8	ch_mflow;		/* Local MFLOW */
++	u8	ch_mctrl;		/* Local MCTRL */
++	u8	ch_xon;			/* Local XON */
++	u8	ch_xoff;		/* Local XOFF */
++	u8	ch_lnext;		/* Local LNEXT */
++	u8	ch_xxon;		/* Local XXON */
++	u8	ch_xxoff;		/* Local XXOFF */
++
++	u8	ch_s_mout;		/* Realport MOUT */
++	u8	ch_s_mflow;		/* Realport MFLOW */
++	u8	ch_s_mctrl;		/* Realport MCTRL */
++	u8	ch_s_xon;		/* Realport XON */
++	u8	ch_s_xoff;		/* Realport XOFF */
++	u8	ch_s_lnext;		/* Realport LNEXT */
++	u8	ch_s_xxon;		/* Realport XXON */
++	u8	ch_s_xxoff;		/* Realport XXOFF */
++
++	wait_queue_head_t ch_flag_wait;	/* Wait queue for ch_flag changes */
++	wait_queue_head_t ch_sleep;	/* Wait queue for my_sleep() */
++
++	int	ch_custom_speed;	/* Realport custom speed */
++	int	ch_txcount;		/* Running TX count */
++	int	ch_rxcount;		/* Running RX count */
++};
++
++
++/************************************************************************
++ * Node State definitions.
++ ************************************************************************/
++
++enum dgrp_nd_state_t {
++	NS_CLOSED = 0,	   /* Network device is closed */
++	NS_IDLE = 1,	   /* Network connection inactive */
++	NS_SEND_QUERY =	2, /* Send server query */
++	NS_WAIT_QUERY =	3, /* Wait for query response */
++	NS_READY = 4,	   /* Network ready */
++	NS_SEND_ERROR =	5  /* Must send error hangup */
++};
++
++#define ND_STATE_STR(x) \
++	((x) == NS_CLOSED     ? "CLOSED"     : \
++	((x) == NS_IDLE	      ? "IDLE"	     : \
++	((x) == NS_SEND_QUERY ? "SEND_QUERY" : \
++	((x) == NS_WAIT_QUERY ? "WAIT_QUERY" : \
++	((x) == NS_READY      ? "READY"	     : \
++	((x) == NS_SEND_ERROR ? "SEND_ERROR" : "UNKNOWN"))))))
++
++/************************************************************************
++ * Node Flag definitions.
++ ************************************************************************/
++
++#define ND_SELECT	0x0001		/* Multiple net read selects */
++#define ND_DEB_WAIT	0x0002		/* Debug Device waiting */
++
++
++/************************************************************************
++ * Monitoring flag definitions.
++ ************************************************************************/
++
++#define MON_WAIT_DATA	0x0001		/* Waiting for buffer data */
++#define MON_WAIT_SPACE	0x0002		/* Waiting for buffer space */
++
++/************************************************************************
++ * DPA flag definitions.
++ ************************************************************************/
++
++#define DPA_WAIT_DATA	0x0001		/* Waiting for buffer data */
++#define DPA_WAIT_SPACE	0x0002		/* Waiting for buffer space */
++
++
++/************************************************************************
++ * Definitions taken from Realport Dump.
++ ************************************************************************/
++
++#define RPDUMP_MAGIC	"Digi-RealPort-1.0"
++
++#define RPDUMP_MESSAGE	0xE2		/* Descriptive message */
++#define RPDUMP_RESET	0xE7		/* Connection reset */
++#define RPDUMP_CLIENT	0xE8		/* Client data */
++#define RPDUMP_SERVER	0xE9		/* Server data */
++
++
++/************************************************************************
++ * Node request/response definitions.
++ ************************************************************************/
++
++#define NR_ECHO		0x0001		/* Server echo packet */
++#define NR_IDENT	0x0002		/* Server Product ID */
++#define NR_CAPABILITY	0x0004		/* Server Capabilties */
++#define NR_VPD		0x0008		/* Server VPD, if any */
++#define NR_PASSWORD	0x0010		/* Server Password */
++
++/************************************************************************
++ * Registration status of the node's Linux struct tty_driver structures.
++ ************************************************************************/
++#define SERIAL_TTDRV_REG   0x0001     /* nd_serial_ttdriver registered	*/
++#define CALLOUT_TTDRV_REG  0x0002     /* nd_callout_ttdriver registered */
++#define XPRINT_TTDRV_REG   0x0004     /* nd_xprint_ttdriver registered	*/
++
++
++/************************************************************************
++ * Node structure.  There exists one of these for each associated
++ * realport server.
++ ************************************************************************/
++
++struct nd_struct {
++	struct list_head	list;
++	long	      nd_major;		   /* Node's major number	    */
++	long	      nd_ID;		   /* Node's ID code		    */
++
++	char	      nd_serial_name[50];   /* "tty_dgrp__" + null	    */
++	char	      nd_callout_name[50];  /* "cu_dgrp__" + null	    */
++	char	      nd_xprint_name[50];   /* "pr_dgrp__" + null	    */
++
++	char	     password[16];	  /* Password for server, if needed */
++	int	     nd_tty_ref_cnt;	  /* Linux tty reference count	   */
++
++	struct proc_dir_entry *nd_net_de; /* Dir entry for /proc/dgrp/net  */
++	struct proc_dir_entry *nd_mon_de; /* Dir entry for /proc/dgrp/mon  */
++	struct proc_dir_entry *nd_ports_de; /* Dir entry for /proc/dgrp/ports*/
++	struct proc_dir_entry *nd_dpa_de; /* Dir entry for /proc/dgrp/dpa  */
++
++	spinlock_t nd_lock;		  /* General node lock		   */
++
++	struct semaphore nd_net_semaphore; /* Net read/write lock	    */
++	struct semaphore nd_mon_semaphore; /* Monitor buffer lock	    */
++	spinlock_t nd_dpa_lock;		/* DPA buffer lock	     */
++
++	enum dgrp_nd_state_t nd_state;	  /* NS_* network state */
++	int	      nd_chan_count;	   /* # active channels		    */
++	int	      nd_flag;		   /* Node flags		    */
++	int	      nd_send;		   /* Responses to send		    */
++	int	      nd_expect;	   /* Responses we expect	    */
++
++	u8	 *nd_iobuf;	       /* Network R/W Buffer		*/
++	wait_queue_head_t nd_tx_waitq;	  /* Network select wait queue	   */
++
++	u8	 *nd_inputbuf;	       /* Input Buffer			*/
++	u8	 *nd_inputflagbuf;     /* Input Flags Buffer		*/
++
++	int	      nd_tx_deposit;	   /* Accumulated transmit deposits */
++	int	      nd_tx_charge;	   /* Accumulated transmit charges  */
++	int	      nd_tx_credit;	   /* Current TX credit		    */
++	int	      nd_tx_ready;	   /* Ready to transmit		    */
++	int	      nd_tx_work;	   /* TX work waiting		    */
++	ulong	     nd_tx_time;	  /* Last transmit time		   */
++	ulong	     nd_poll_time;	  /* Next scheduled poll time	   */
++
++	int	      nd_delay;		   /* Current TX delay		    */
++	int	      nd_rate;		   /* Current TX rate		    */
++	struct link_struct nd_link;		/* Link speed params.		 */
++
++	int	      nd_seq_in;	   /* TX seq in ptr		    */
++	int	      nd_seq_out;	   /* TX seq out ptr		    */
++	int	      nd_unack;		   /* Unacknowledged byte count	    */
++	int	      nd_remain;	   /* Remaining receive bytes	    */
++	int	      nd_tx_module;	   /* Current TX module #	    */
++	int	      nd_rx_module;	   /* Current RX module #	    */
++	char	     *nd_error;		   /* Protocol error message	    */
++
++	int	      nd_write_count;	   /* drp_write() call count	    */
++	int	      nd_read_count;	   /* drp_read() count		    */
++	int	      nd_send_count;	   /* TCP message sent		    */
++	int	      nd_tx_byte;	   /* Transmit byte count	    */
++	int	      nd_rx_byte;	   /* Receive byte count	    */
++
++	ulong	     nd_mon_lbolt;	 /* Monitor start time		   */
++	int	      nd_mon_flag;	  /* Monitor flags		    */
++	int	      nd_mon_in;	  /* Monitor in pointer		    */
++	int	      nd_mon_out;	  /* Monitor out pointer	    */
++	wait_queue_head_t nd_mon_wqueue;  /* Monitor wait queue (on flags)  */
++	u8	 *nd_mon_buf;	      /* Monitor buffer			*/
++
++	ulong	     nd_dpa_lbolt;	/* DPA start time	      */
++	int	     nd_dpa_flag;	/* DPA flags		      */
++	int	     nd_dpa_in;		/* DPA in pointer	      */
++	int	     nd_dpa_out;	/* DPA out pointer	      */
++	wait_queue_head_t nd_dpa_wqueue; /* DPA wait queue (on flags)  */
++	u8	  *nd_dpa_buf;	/* DPA buffer		      */
++
++	uint	     nd_dpa_debug;
++	uint	     nd_dpa_port;
++
++	wait_queue_head_t nd_seq_wque[SEQ_MAX];	  /* TX thread wait queues */
++	u8	  nd_seq_wait[SEQ_MAX];	  /* Transmit thread wait count */
++
++	ushort	     nd_seq_size[SEQ_MAX];   /* Transmit seq packet size   */
++	ulong	     nd_seq_time[SEQ_MAX];   /* Transmit seq packet time   */
++
++	ushort	     nd_hw_ver;		  /* HW version returned from PS   */
++	ushort	     nd_sw_ver;		  /* SW version returned from PS   */
++	uint	     nd_hw_id;		  /* HW ID returned from PS	   */
++	u8	  nd_ps_desc[MAX_DESC_LEN+1];  /* Description from PS	*/
++	uint	     nd_vpd_len;		/* VPD len, if any */
++	u8	     nd_vpd[VPDSIZE];		/* VPD, if any */
++
++	ulong	     nd_ttdriver_flags;	  /* Registration status	    */
++	struct tty_driver *nd_serial_ttdriver;	/* Linux TTYDRIVER structure */
++	struct tty_driver *nd_callout_ttdriver; /* Linux TTYDRIVER structure */
++	struct tty_driver *nd_xprint_ttdriver;	/* Linux TTYDRIVER structure */
++
++	u8	     *nd_writebuf;		/* Used to cache data read
++						 * from user
++						 */
++	struct ch_struct nd_chan[CHAN_MAX];  /* Channel array		    */
++	struct device *nd_class_dev;	/* Hang our sysfs stuff off of here */
++};
++
++#endif /* __DRP_H */

commit 45f4c81d690a57838822d4d01ad4c03651b76b95
+Author: Bill Pemberton 
+Date:   Thu Aug 9 09:23:23 2012 -0400
+
+    localmodconfig: Use my variable for loop in streamline_config.pl
+    
+    perlcritic complains about $kconfig being reused in the foreach loop
+    at the end of read_kconfig.  Change it to a my variable.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Steven Rostedt 
+
+diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl
+index 22b66cada779..39b6314fe634 100644
+--- a/scripts/kconfig/streamline_config.pl
++++ b/scripts/kconfig/streamline_config.pl
+@@ -252,7 +252,7 @@ sub read_kconfig {
+     close($kinfile);
+ 
+     # read in any configs that were found.
+-    foreach $kconfig (@kconfigs) {
++    foreach my $kconfig (@kconfigs) {
+ 	if (!defined($read_kconfigs{$kconfig})) {
+ 	    $read_kconfigs{$kconfig} = 1;
+ 	    read_kconfig($kconfig);

commit e0d28694d33dc7f37832b4fe4fe229655a64f991
+Author: Bill Pemberton 
+Date:   Thu Aug 9 09:23:22 2012 -0400
+
+    localmodconfig: Use 3 parameter open in streamline_config.pl
+    
+    Convert remaining open calls to use the perl's preferred 3 parameter
+    open.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Steven Rostedt 
+
+diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl
+index 62d64ce5c581..22b66cada779 100644
+--- a/scripts/kconfig/streamline_config.pl
++++ b/scripts/kconfig/streamline_config.pl
+@@ -171,8 +171,8 @@ sub read_kconfig {
+ 	$source =~ s/\$$env/$ENV{$env}/;
+     }
+ 
+-    open(KIN, "$source") || die "Can't open $kconfig";
+-    while () {
++    open(my $kinfile, '<', $source) || die "Can't open $kconfig";
++    while (<$kinfile>) {
+ 	chomp;
+ 
+ 	# Make sure that lines ending with \ continue
+@@ -249,7 +249,7 @@ sub read_kconfig {
+ 	    $state = "NONE";
+ 	}
+     }
+-    close(KIN);
++    close($kinfile);
+ 
+     # read in any configs that were found.
+     foreach $kconfig (@kconfigs) {
+@@ -293,8 +293,8 @@ foreach my $makefile (@makefiles) {
+     my $line = "";
+     my %make_vars;
+ 
+-    open(MIN,$makefile) || die "Can't open $makefile";
+-    while () {
++    open(my $infile, '<', $makefile) || die "Can't open $makefile";
++    while (<$infile>) {
+ 	# if this line ends with a backslash, continue
+ 	chomp;
+ 	if (/^(.*)\\$/) {
+@@ -341,10 +341,11 @@ foreach my $makefile (@makefiles) {
+ 	    }
+ 	}
+     }
+-    close(MIN);
++    close($infile);
+ }
+ 
+ my %modules;
++my $linfile;
+ 
+ if (defined($lsmod_file)) {
+     if ( ! -f $lsmod_file) {
+@@ -354,13 +355,10 @@ if (defined($lsmod_file)) {
+ 		die "$lsmod_file not found";
+ 	}
+     }
+-    if ( -x $lsmod_file) {
+-	# the file is executable, run it
+-	open(LIN, "$lsmod_file|");
+-    } else {
+-	# Just read the contents
+-	open(LIN, "$lsmod_file");
+-    }
++
++    my $otype = ( -x $lsmod_file) ? '-|' : '<';
++    open($linfile, $otype, $lsmod_file);
++
+ } else {
+ 
+     # see what modules are loaded on this system
+@@ -377,16 +375,16 @@ if (defined($lsmod_file)) {
+ 	$lsmod = "lsmod";
+     }
+ 
+-    open(LIN,"$lsmod|") || die "Can not call lsmod with $lsmod";
++    open($linfile, '-|', $lsmod) || die "Can not call lsmod with $lsmod";
+ }
+ 
+-while () {
++while (<$linfile>) {
+ 	next if (/^Module/);  # Skip the first line.
+ 	if (/^(\S+)/) {
+ 		$modules{$1} = 1;
+ 	}
+ }
+-close (LIN);
++close ($linfile);
+ 
+ # add to the configs hash all configs that are needed to enable
+ # a loaded module. This is a direct obj-${CONFIG_FOO} += bar.o

commit 3f0c54131679889d64e8b1831bac40c0d64cf511
+Author: Bill Pemberton 
+Date:   Thu Aug 9 09:23:21 2012 -0400
+
+    localmodconfig: Rework find_config in streamline_config.pl
+    
+    Change find_config function to read_config.  It now finds the config,
+    reads the config into an array, and returns the array.  This makes it
+    a little cleaner and changes the open to use perl's 3 option open.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Steven Rostedt 
+
+diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl
+index e3687f98e0c8..62d64ce5c581 100644
+--- a/scripts/kconfig/streamline_config.pl
++++ b/scripts/kconfig/streamline_config.pl
+@@ -100,7 +100,7 @@ my @searchconfigs = (
+ 	},
+ );
+ 
+-sub find_config {
++sub read_config {
+     foreach my $conf (@searchconfigs) {
+ 	my $file = $conf->{"file"};
+ 
+@@ -115,17 +115,15 @@ sub find_config {
+ 
+ 	print STDERR "using config: '$file'\n";
+ 
+-	open(CIN, "$exec $file |") || die "Failed to run $exec $file";
+-	return;
++	open(my $infile, '-|', "$exec $file") || die "Failed to run $exec $file";
++	my @x = <$infile>;
++	close $infile;
++	return @x;
+     }
+     die "No config file found";
+ }
+ 
+-find_config;
+-
+-# Read in the entire config file into config_file
+-my @config_file = ;
+-close CIN;
++my @config_file = read_config;
+ 
+ # Parse options
+ my $localmodconfig = 0;

commit 224a257190694f253f7a4c533fd6958d2e5fa669
+Author: Bill Pemberton 
+Date:   Thu Aug 9 09:23:20 2012 -0400
+
+    localmodconfig: Set default value for ksource in streamline_config.pl
+    
+    Running streamline_config.pl as it's shown it in the comment header,
+    you will get a warning about $ksource being uninitialized.  This is
+    because $ksource is set to ARGV[0], but the examples don't require any
+    arguments.  Fix by setting ksource to . if no ARGV[0] is given.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Steven Rostedt 
+
+diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl
+index 2fbbbc1ddea0..e3687f98e0c8 100644
+--- a/scripts/kconfig/streamline_config.pl
++++ b/scripts/kconfig/streamline_config.pl
+@@ -135,7 +135,7 @@ GetOptions("localmodconfig" => \$localmodconfig,
+ 	   "localyesconfig" => \$localyesconfig);
+ 
+ # Get the build source and top level Kconfig file (passed in)
+-my $ksource = $ARGV[0];
++my $ksource = ($ARGV[0] ? $ARGV[0] : '.');
+ my $kconfig = $ARGV[1];
+ my $lsmod_file = $ENV{'LSMOD'};
+ 

commit c50f2af8e1a33e95e4d3b7af9db05ed9096c6072
+Author: Bill Pemberton 
+Date:   Tue Jun 19 10:34:07 2012 -0400
+
+    USB: serial: Remove unused serial_priv variable
+    
+    qt2_open() and qt2_close() both set a serial_priv variable but never
+    used it.  Remove the variable from the functions.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c
+index 8dd88ebe9863..151670b6b72a 100644
+--- a/drivers/usb/serial/quatech2.c
++++ b/drivers/usb/serial/quatech2.c
+@@ -345,7 +345,6 @@ static void qt2_set_termios(struct tty_struct *tty,
+ static int qt2_open(struct tty_struct *tty, struct usb_serial_port *port)
+ {
+ 	struct usb_serial *serial;
+-	struct qt2_serial_private *serial_priv;
+ 	struct qt2_port_private *port_priv;
+ 	u8 *data;
+ 	u16 device_port;
+@@ -357,7 +356,6 @@ static int qt2_open(struct tty_struct *tty, struct usb_serial_port *port)
+ 	serial = port->serial;
+ 
+ 	port_priv = usb_get_serial_port_data(port);
+-	serial_priv = usb_get_serial_data(serial);
+ 
+ 	/* set the port to RS232 mode */
+ 	status = qt2_control_msg(serial->dev, QT2_GET_SET_QMCR,
+@@ -417,13 +415,11 @@ static int qt2_open(struct tty_struct *tty, struct usb_serial_port *port)
+ static void qt2_close(struct usb_serial_port *port)
+ {
+ 	struct usb_serial *serial;
+-	struct qt2_serial_private *serial_priv;
+ 	struct qt2_port_private *port_priv;
+ 	unsigned long flags;
+ 	int i;
+ 
+ 	serial = port->serial;
+-	serial_priv = usb_get_serial_data(serial);
+ 	port_priv = usb_get_serial_port_data(port);
+ 
+ 	port_priv->is_open = false;

commit 996a776544cc8a71653ffa95a89c317f33d2cb4a
+Author: Bill Pemberton 
+Date:   Tue Jun 19 10:34:06 2012 -0400
+
+    USB: serial: Remove unused s_priv variable
+    
+    s_priv was set but never used in keyspan_open() and keyspan_close(),
+    remove it.
+    
+    This also makes the serial variable in keyspan_open() unused since
+    it's only use was to set s_priv, so it is also removed.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
+index a1b99243dac9..9a0ca8355905 100644
+--- a/drivers/usb/serial/keyspan.c
++++ b/drivers/usb/serial/keyspan.c
+@@ -1036,15 +1036,12 @@ static int keyspan_write_room(struct tty_struct *tty)
+ static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port)
+ {
+ 	struct keyspan_port_private 	*p_priv;
+-	struct keyspan_serial_private 	*s_priv;
+-	struct usb_serial 		*serial = port->serial;
+ 	const struct keyspan_device_details	*d_details;
+ 	int				i, err;
+ 	int				baud_rate, device_port;
+ 	struct urb			*urb;
+ 	unsigned int			cflag = 0;
+ 
+-	s_priv = usb_get_serial_data(serial);
+ 	p_priv = usb_get_serial_port_data(port);
+ 	d_details = p_priv->device_details;
+ 
+@@ -1130,10 +1127,8 @@ static void keyspan_close(struct usb_serial_port *port)
+ {
+ 	int			i;
+ 	struct usb_serial	*serial = port->serial;
+-	struct keyspan_serial_private 	*s_priv;
+ 	struct keyspan_port_private 	*p_priv;
+ 
+-	s_priv = usb_get_serial_data(serial);
+ 	p_priv = usb_get_serial_port_data(port);
+ 
+ 	p_priv->rts_state = 0;

commit f88e6a30da1088143092f7b92ec2c8bd3b128350
+Author: Bill Pemberton 
+Date:   Thu May 10 16:57:39 2012 -0400
+
+    USB: serial: add copyright and license to quatech2
+    
+    Add a copyright and license statement to the head of quatech.c source
+    file.  No code change here.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c
+index 3aa63f1f6dfe..8dd88ebe9863 100644
+--- a/drivers/usb/serial/quatech2.c
++++ b/drivers/usb/serial/quatech2.c
+@@ -1,6 +1,12 @@
+ /*
+  * usb-serial driver for Quatech USB 2 devices
+  *
++ * Copyright (C) 2012 Bill Pemberton (wfp5p@virginia.edu)
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation.
++ *
+  *
+  *  These devices all have only 1 bulk in and 1 bulk out that is shared
+  *  for all serial ports.

commit f7a33e608d9ae022b7f49307921627e34e9484ed
+Author: Bill Pemberton 
+Date:   Thu May 10 15:36:02 2012 -0400
+
+    USB: serial: add quatech2 usb to serial driver
+    
+    This supports the Quatech USB 2 usb to serial adapters.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
+index 7141d6599060..325d2910f9f9 100644
+--- a/drivers/usb/serial/Kconfig
++++ b/drivers/usb/serial/Kconfig
+@@ -669,6 +669,15 @@ config USB_SERIAL_SSU100
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called ssu100.
+ 
++config USB_SERIAL_QT2
++	tristate "USB Quatech Serial Driver for USB 2 devices"
++	help
++	  Say Y here if you want to use the Quatech USB 2
++	  serial adapters.
++
++	  To compile this driver as a module, choose M here: the
++	  module will be called quatech-serial.
++
+ config USB_SERIAL_DEBUG
+ 	tristate "USB Debugging Device"
+ 	help
+diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
+index 07f198ee0486..1dc483a8bfc7 100644
+--- a/drivers/usb/serial/Makefile
++++ b/drivers/usb/serial/Makefile
+@@ -49,6 +49,7 @@ obj-$(CONFIG_USB_SERIAL_OTI6858)		+= oti6858.o
+ obj-$(CONFIG_USB_SERIAL_PL2303)			+= pl2303.o
+ obj-$(CONFIG_USB_SERIAL_QCAUX)			+= qcaux.o
+ obj-$(CONFIG_USB_SERIAL_QUALCOMM)		+= qcserial.o
++obj-$(CONFIG_USB_SERIAL_QT2)			+= quatech2.o
+ obj-$(CONFIG_USB_SERIAL_SAFE)			+= safe_serial.o
+ obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI)		+= siemens_mpi.o
+ obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS)		+= sierra.o
+diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c
+new file mode 100644
+index 000000000000..3aa63f1f6dfe
+--- /dev/null
++++ b/drivers/usb/serial/quatech2.c
+@@ -0,0 +1,1149 @@
++/*
++ * usb-serial driver for Quatech USB 2 devices
++ *
++ *
++ *  These devices all have only 1 bulk in and 1 bulk out that is shared
++ *  for all serial ports.
++ *
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++static bool debug;
++
++/* default urb timeout for usb operations */
++#define QT2_USB_TIMEOUT USB_CTRL_SET_TIMEOUT
++
++#define QT_OPEN_CLOSE_CHANNEL       0xca
++#define QT_SET_GET_DEVICE           0xc2
++#define QT_SET_GET_REGISTER         0xc0
++#define QT_GET_SET_PREBUF_TRIG_LVL  0xcc
++#define QT_SET_ATF                  0xcd
++#define QT_TRANSFER_IN              0xc0
++#define QT_HW_FLOW_CONTROL_MASK     0xc5
++#define QT_SW_FLOW_CONTROL_MASK     0xc6
++#define QT2_BREAK_CONTROL	    0xc8
++#define QT2_GET_SET_UART            0xc1
++#define QT2_FLUSH_DEVICE	    0xc4
++#define QT2_GET_SET_QMCR            0xe1
++#define QT2_QMCR_RS232              0x40
++#define QT2_QMCR_RS422              0x10
++
++#define  SERIAL_CRTSCTS ((UART_MCR_RTS << 8) | UART_MSR_CTS)
++
++#define  SERIAL_EVEN_PARITY         (UART_LCR_PARITY | UART_LCR_EPAR)
++
++/* status bytes for the device */
++#define QT2_CONTROL_BYTE    0x1b
++#define QT2_LINE_STATUS     0x00  /* following 1 byte is line status */
++#define QT2_MODEM_STATUS    0x01  /* following 1 byte is modem status */
++#define QT2_XMIT_HOLD       0x02  /* following 2 bytes are ?? */
++#define QT2_CHANGE_PORT     0x03  /* following 1 byte is port to change to */
++#define QT2_REC_FLUSH       0x04  /* no following info */
++#define QT2_XMIT_FLUSH      0x05  /* no following info */
++#define QT2_CONTROL_ESCAPE  0xff  /* pass through previous 2 control bytes */
++
++#define  MAX_BAUD_RATE              921600
++#define  DEFAULT_BAUD_RATE          9600
++
++#define QT2_WRITE_BUFFER_SIZE   512  /* size of write buffer */
++#define QT2_WRITE_CONTROL_SIZE  5    /* control bytes used for a write */
++
++/* Version Information */
++#define DRIVER_VERSION "v0.1"
++#define DRIVER_DESC "Quatech 2nd gen USB to Serial Driver"
++
++#define	USB_VENDOR_ID_QUATECH	0x061d
++#define QUATECH_SSU2_100	0xC120	/* RS232 single port */
++#define QUATECH_DSU2_100	0xC140	/* RS232 dual port */
++#define QUATECH_DSU2_400	0xC150	/* RS232/422/485 dual port */
++#define QUATECH_QSU2_100	0xC160	/* RS232 four port */
++#define QUATECH_QSU2_400	0xC170	/* RS232/422/485 four port */
++#define QUATECH_ESU2_100	0xC1A0	/* RS232 eight port */
++#define QUATECH_ESU2_400	0xC180	/* RS232/422/485 eight port */
++
++struct qt2_device_detail {
++	int product_id;
++	int num_ports;
++};
++
++#define QT_DETAILS(prod, ports)	\
++	.product_id = (prod),   \
++	.num_ports = (ports)
++
++static const struct qt2_device_detail qt2_device_details[] = {
++	{QT_DETAILS(QUATECH_SSU2_100, 1)},
++	{QT_DETAILS(QUATECH_DSU2_400, 2)},
++	{QT_DETAILS(QUATECH_DSU2_100, 2)},
++	{QT_DETAILS(QUATECH_QSU2_400, 4)},
++	{QT_DETAILS(QUATECH_QSU2_100, 4)},
++	{QT_DETAILS(QUATECH_ESU2_400, 8)},
++	{QT_DETAILS(QUATECH_ESU2_100, 8)},
++	{QT_DETAILS(0, 0)}	/* Terminating entry */
++};
++
++static const struct usb_device_id id_table[] = {
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU2_100)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU2_100)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU2_400)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU2_100)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU2_400)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU2_100)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU2_400)},
++	{}			/* Terminating entry */
++};
++MODULE_DEVICE_TABLE(usb, id_table);
++
++struct qt2_serial_private {
++	unsigned char current_port;  /* current port for incoming data */
++
++	struct urb	*read_urb;   /* shared among all ports */
++	char		read_buffer[512];
++};
++
++struct qt2_port_private {
++	bool is_open;
++	u8   device_port;
++
++	spinlock_t urb_lock;
++	bool       urb_in_use;
++	struct urb *write_urb;
++	char       write_buffer[QT2_WRITE_BUFFER_SIZE];
++
++	spinlock_t  lock;
++	u8          shadowLSR;
++	u8          shadowMSR;
++
++	wait_queue_head_t   delta_msr_wait; /* Used for TIOCMIWAIT */
++	struct async_icount icount;
++
++	struct usb_serial_port *port;
++};
++
++static void qt2_update_lsr(struct usb_serial_port *port, unsigned char *ch);
++static void qt2_update_msr(struct usb_serial_port *port, unsigned char *ch);
++static void qt2_write_bulk_callback(struct urb *urb);
++static void qt2_read_bulk_callback(struct urb *urb);
++
++static void qt2_release(struct usb_serial *serial)
++{
++	int i;
++
++	kfree(usb_get_serial_data(serial));
++
++	for (i = 0; i < serial->num_ports; i++)
++		kfree(usb_get_serial_port_data(serial->port[i]));
++}
++
++static inline int calc_baud_divisor(int baudrate)
++{
++	int divisor, rem;
++
++	divisor = MAX_BAUD_RATE / baudrate;
++	rem = MAX_BAUD_RATE % baudrate;
++	/* Round to nearest divisor */
++	if (((rem * 2) >= baudrate) && (baudrate != 110))
++		divisor++;
++
++	return divisor;
++}
++
++static inline int qt2_set_port_config(struct usb_device *dev,
++				      unsigned char port_number,
++				      u16 baudrate, u16 lcr)
++{
++	int divisor = calc_baud_divisor(baudrate);
++	u16 index = ((u16) (lcr << 8) | (u16) (port_number));
++
++	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
++			       QT2_GET_SET_UART, 0x40,
++			       divisor, index, NULL, 0, QT2_USB_TIMEOUT);
++}
++
++static inline int qt2_control_msg(struct usb_device *dev,
++				  u8 request, u16 data, u16 index)
++{
++	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
++			       request, 0x40, data, index,
++			       NULL, 0, QT2_USB_TIMEOUT);
++}
++
++static inline int qt2_setdevice(struct usb_device *dev, u8 *data)
++{
++	u16 x = ((u16) (data[1] << 8) | (u16) (data[0]));
++
++	return qt2_control_msg(dev, QT_SET_GET_DEVICE, x, 0);
++}
++
++
++static inline int qt2_getdevice(struct usb_device *dev, u8 *data)
++{
++	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
++			       QT_SET_GET_DEVICE, 0xc0, 0, 0,
++			       data, 3, QT2_USB_TIMEOUT);
++}
++
++static inline int qt2_getregister(struct usb_device *dev,
++				  u8 uart,
++				  u8 reg,
++				  u8 *data)
++{
++	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
++			       QT_SET_GET_REGISTER, 0xc0, reg,
++			       uart, data, sizeof(*data), QT2_USB_TIMEOUT);
++
++}
++
++static inline int qt2_setregister(struct usb_device *dev,
++				  u8 uart, u8 reg, u16 data)
++{
++	u16 value = (data << 8) | reg;
++
++	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
++			       QT_SET_GET_REGISTER, 0x40, value, uart,
++			       NULL, 0, QT2_USB_TIMEOUT);
++}
++
++static inline int update_mctrl(struct qt2_port_private *port_priv,
++			       unsigned int set, unsigned int clear)
++{
++	struct usb_serial_port *port = port_priv->port;
++	struct usb_device *dev = port->serial->dev;
++	unsigned urb_value;
++	int status;
++
++	if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) {
++		dev_dbg(&port->dev,
++			"update_mctrl - DTR|RTS not being set|cleared\n");
++		return 0;	/* no change */
++	}
++
++	clear &= ~set;	/* 'set' takes precedence over 'clear' */
++	urb_value = 0;
++	if (set & TIOCM_DTR)
++		urb_value |= UART_MCR_DTR;
++	if (set & TIOCM_RTS)
++		urb_value |= UART_MCR_RTS;
++
++	status = qt2_setregister(dev, port_priv->device_port, UART_MCR,
++				 urb_value);
++	if (status < 0)
++		dev_err(&port->dev,
++			"update_mctrl - Error from MODEM_CTRL urb: %i\n",
++			status);
++	return status;
++}
++
++static int qt2_calc_num_ports(struct usb_serial *serial)
++{
++	struct qt2_device_detail d;
++	int i;
++
++	for (i = 0; d = qt2_device_details[i], d.product_id != 0; i++) {
++		if (d.product_id == le16_to_cpu(serial->dev->descriptor.idProduct))
++			return d.num_ports;
++	}
++
++	/* we didn't recognize the device */
++	dev_err(&serial->dev->dev,
++		 "don't know the number of ports, assuming 1\n");
++
++	return 1;
++}
++
++static void qt2_set_termios(struct tty_struct *tty,
++			    struct usb_serial_port *port,
++			    struct ktermios *old_termios)
++{
++	struct usb_device *dev = port->serial->dev;
++	struct qt2_port_private *port_priv;
++	struct ktermios *termios = tty->termios;
++	u16 baud;
++	unsigned int cflag = termios->c_cflag;
++	u16 new_lcr = 0;
++	int status;
++
++	port_priv = usb_get_serial_port_data(port);
++
++	if (cflag & PARENB) {
++		if (cflag & PARODD)
++			new_lcr |= UART_LCR_PARITY;
++		else
++			new_lcr |= SERIAL_EVEN_PARITY;
++	}
++
++	switch (cflag & CSIZE) {
++	case CS5:
++		new_lcr |= UART_LCR_WLEN5;
++		break;
++	case CS6:
++		new_lcr |= UART_LCR_WLEN6;
++		break;
++	case CS7:
++		new_lcr |= UART_LCR_WLEN7;
++		break;
++	default:
++	case CS8:
++		new_lcr |= UART_LCR_WLEN8;
++		break;
++	}
++
++	baud = tty_get_baud_rate(tty);
++	if (!baud)
++		baud = 9600;
++
++	status = qt2_set_port_config(dev, port_priv->device_port, baud,
++				     new_lcr);
++	if (status < 0)
++		dev_err(&port->dev, "%s - qt2_set_port_config failed: %i\n",
++			__func__, status);
++
++	if (cflag & CRTSCTS)
++		status = qt2_control_msg(dev, QT_HW_FLOW_CONTROL_MASK,
++					 SERIAL_CRTSCTS,
++					 port_priv->device_port);
++	else
++		status = qt2_control_msg(dev, QT_HW_FLOW_CONTROL_MASK,
++					 0, port_priv->device_port);
++	if (status < 0)
++		dev_err(&port->dev, "%s - set HW flow control failed: %i\n",
++			__func__, status);
++
++	if (I_IXOFF(tty) || I_IXON(tty)) {
++		u16 x = ((u16) (START_CHAR(tty) << 8) | (u16) (STOP_CHAR(tty)));
++
++		status = qt2_control_msg(dev, QT_SW_FLOW_CONTROL_MASK,
++					 x, port_priv->device_port);
++	} else
++		status = qt2_control_msg(dev, QT_SW_FLOW_CONTROL_MASK,
++					 0, port_priv->device_port);
++
++	if (status < 0)
++		dev_err(&port->dev, "%s - set SW flow control failed: %i\n",
++			__func__, status);
++
++}
++
++static int qt2_open(struct tty_struct *tty, struct usb_serial_port *port)
++{
++	struct usb_serial *serial;
++	struct qt2_serial_private *serial_priv;
++	struct qt2_port_private *port_priv;
++	u8 *data;
++	u16 device_port;
++	int status;
++	unsigned long flags;
++
++	device_port = (u16) (port->number - port->serial->minor);
++
++	serial = port->serial;
++
++	port_priv = usb_get_serial_port_data(port);
++	serial_priv = usb_get_serial_data(serial);
++
++	/* set the port to RS232 mode */
++	status = qt2_control_msg(serial->dev, QT2_GET_SET_QMCR,
++				 QT2_QMCR_RS232, device_port);
++	if (status < 0) {
++		dev_err(&port->dev,
++			"%s failed to set RS232 mode for port %i error %i\n",
++			__func__, device_port, status);
++		return status;
++	}
++
++	data = kzalloc(2, GFP_KERNEL);
++	if (!data)
++		return -ENOMEM;
++
++	/* open the port */
++	status = usb_control_msg(serial->dev,
++				 usb_rcvctrlpipe(serial->dev, 0),
++				 QT_OPEN_CLOSE_CHANNEL,
++				 0xc0, 0,
++				 device_port, data, 2, QT2_USB_TIMEOUT);
++
++	if (status < 0) {
++		dev_err(&port->dev, "%s - open port failed %i", __func__,
++			status);
++		kfree(data);
++		return status;
++	}
++
++	spin_lock_irqsave(&port_priv->lock, flags);
++	port_priv->shadowLSR = data[0];
++	port_priv->shadowMSR = data[1];
++	spin_unlock_irqrestore(&port_priv->lock, flags);
++
++	kfree(data);
++
++	/* set to default speed and 8bit word size */
++	status = qt2_set_port_config(serial->dev, device_port,
++				     DEFAULT_BAUD_RATE, UART_LCR_WLEN8);
++	if (status < 0) {
++		dev_err(&port->dev,
++			"%s - initial setup failed for port %i (%i)\n",
++			__func__, port->number, device_port);
++		return status;
++	}
++
++	port_priv->is_open = true;
++	port_priv->device_port = (u8) device_port;
++
++	if (tty)
++		qt2_set_termios(tty, port, tty->termios);
++
++	return 0;
++
++}
++
++static void qt2_close(struct usb_serial_port *port)
++{
++	struct usb_serial *serial;
++	struct qt2_serial_private *serial_priv;
++	struct qt2_port_private *port_priv;
++	unsigned long flags;
++	int i;
++
++	serial = port->serial;
++	serial_priv = usb_get_serial_data(serial);
++	port_priv = usb_get_serial_port_data(port);
++
++	port_priv->is_open = false;
++
++	spin_lock_irqsave(&port_priv->urb_lock, flags);
++	if (port_priv->write_urb->status == -EINPROGRESS)
++		usb_kill_urb(port_priv->write_urb);
++	port_priv->urb_in_use = false;
++	spin_unlock_irqrestore(&port_priv->urb_lock, flags);
++
++	/* flush the port transmit buffer */
++	i = usb_control_msg(serial->dev,
++			    usb_rcvctrlpipe(serial->dev, 0),
++			    QT2_FLUSH_DEVICE, 0x40, 1,
++			    port_priv->device_port, NULL, 0, QT2_USB_TIMEOUT);
++
++	if (i < 0)
++		dev_err(&port->dev, "%s - transmit buffer flush failed: %i\n",
++			__func__, i);
++
++	/* flush the port receive buffer */
++	i = usb_control_msg(serial->dev,
++			    usb_rcvctrlpipe(serial->dev, 0),
++			    QT2_FLUSH_DEVICE, 0x40, 0,
++			    port_priv->device_port, NULL, 0, QT2_USB_TIMEOUT);
++
++	if (i < 0)
++		dev_err(&port->dev, "%s - receive buffer flush failed: %i\n",
++			__func__, i);
++
++	/* close the port */
++	i = usb_control_msg(serial->dev,
++			    usb_sndctrlpipe(serial->dev, 0),
++			    QT_OPEN_CLOSE_CHANNEL,
++			    0x40, 0,
++			    port_priv->device_port, NULL, 0, QT2_USB_TIMEOUT);
++
++	if (i < 0)
++		dev_err(&port->dev, "%s - close port failed %i\n",
++			__func__, i);
++
++}
++
++static void qt2_disconnect(struct usb_serial *serial)
++{
++	struct qt2_serial_private *serial_priv = usb_get_serial_data(serial);
++	struct qt2_port_private *port_priv;
++	int i;
++
++	if (serial_priv->read_urb->status == -EINPROGRESS)
++		usb_kill_urb(serial_priv->read_urb);
++
++	usb_free_urb(serial_priv->read_urb);
++
++	for (i = 0; i < serial->num_ports; i++) {
++		port_priv = usb_get_serial_port_data(serial->port[i]);
++
++		if (port_priv->write_urb->status == -EINPROGRESS)
++			usb_kill_urb(port_priv->write_urb);
++		usb_free_urb(port_priv->write_urb);
++	}
++}
++
++static int get_serial_info(struct usb_serial_port *port,
++			   struct serial_struct __user *retinfo)
++{
++	struct serial_struct tmp;
++
++	if (!retinfo)
++		return -EFAULT;
++
++	memset(&tmp, 0, sizeof(tmp));
++	tmp.line		= port->serial->minor;
++	tmp.port		= 0;
++	tmp.irq			= 0;
++	tmp.flags		= ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
++	tmp.xmit_fifo_size	= port->bulk_out_size;
++	tmp.baud_base		= 9600;
++	tmp.close_delay		= 5*HZ;
++	tmp.closing_wait	= 30*HZ;
++
++	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
++		return -EFAULT;
++	return 0;
++}
++
++static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
++{
++	struct qt2_port_private *priv = usb_get_serial_port_data(port);
++	struct async_icount prev, cur;
++	unsigned long flags;
++
++	spin_lock_irqsave(&priv->lock, flags);
++	prev = priv->icount;
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	while (1) {
++		wait_event_interruptible(priv->delta_msr_wait,
++					 ((priv->icount.rng != prev.rng) ||
++					  (priv->icount.dsr != prev.dsr) ||
++					  (priv->icount.dcd != prev.dcd) ||
++					  (priv->icount.cts != prev.cts)));
++
++		if (signal_pending(current))
++			return -ERESTARTSYS;
++
++		spin_lock_irqsave(&priv->lock, flags);
++		cur = priv->icount;
++		spin_unlock_irqrestore(&priv->lock, flags);
++
++		if ((prev.rng == cur.rng) &&
++		    (prev.dsr == cur.dsr) &&
++		    (prev.dcd == cur.dcd) &&
++		    (prev.cts == cur.cts))
++			return -EIO;
++
++		if ((arg & TIOCM_RNG && (prev.rng != cur.rng)) ||
++		    (arg & TIOCM_DSR && (prev.dsr != cur.dsr)) ||
++		    (arg & TIOCM_CD && (prev.dcd != cur.dcd)) ||
++		    (arg & TIOCM_CTS && (prev.cts != cur.cts)))
++			return 0;
++	}
++	return 0;
++}
++
++static int qt2_get_icount(struct tty_struct *tty,
++			  struct serial_icounter_struct *icount)
++{
++	struct usb_serial_port *port = tty->driver_data;
++	struct qt2_port_private *priv = usb_get_serial_port_data(port);
++	struct async_icount cnow = priv->icount;
++
++	icount->cts = cnow.cts;
++	icount->dsr = cnow.dsr;
++	icount->rng = cnow.rng;
++	icount->dcd = cnow.dcd;
++	icount->rx = cnow.rx;
++	icount->tx = cnow.tx;
++	icount->frame = cnow.frame;
++	icount->overrun = cnow.overrun;
++	icount->parity = cnow.parity;
++	icount->brk = cnow.brk;
++	icount->buf_overrun = cnow.buf_overrun;
++
++	return 0;
++}
++
++static int qt2_ioctl(struct tty_struct *tty,
++		     unsigned int cmd, unsigned long arg)
++{
++	struct usb_serial_port *port = tty->driver_data;
++
++	switch (cmd) {
++	case TIOCGSERIAL:
++		return get_serial_info(port,
++				       (struct serial_struct __user *)arg);
++
++	case TIOCMIWAIT:
++		return wait_modem_info(port, arg);
++
++	default:
++		break;
++	}
++
++	return -ENOIOCTLCMD;
++}
++
++static void qt2_process_status(struct usb_serial_port *port, unsigned char *ch)
++{
++	switch (*ch) {
++	case QT2_LINE_STATUS:
++		qt2_update_lsr(port, ch + 1);
++		break;
++	case QT2_MODEM_STATUS:
++		qt2_update_msr(port, ch + 1);
++		break;
++	}
++}
++
++/* not needed, kept to document functionality */
++static void qt2_process_xmit_empty(struct usb_serial_port *port,
++				   unsigned char *ch)
++{
++	int bytes_written;
++
++	bytes_written = (int)(*ch) + (int)(*(ch + 1) << 4);
++}
++
++/* not needed, kept to document functionality */
++static void qt2_process_flush(struct usb_serial_port *port, unsigned char *ch)
++{
++	return;
++}
++
++void qt2_process_read_urb(struct urb *urb)
++{
++	struct usb_serial *serial;
++	struct qt2_serial_private *serial_priv;
++	struct usb_serial_port *port;
++	struct qt2_port_private *port_priv;
++	struct tty_struct *tty;
++	bool escapeflag;
++	unsigned char *ch;
++	int i;
++	unsigned char newport;
++	int len = urb->actual_length;
++
++	if (!len)
++		return;
++
++	ch = urb->transfer_buffer;
++	tty = NULL;
++	serial = urb->context;
++	serial_priv = usb_get_serial_data(serial);
++	port = serial->port[serial_priv->current_port];
++	port_priv = usb_get_serial_port_data(port);
++
++	if (port_priv->is_open)
++		tty = tty_port_tty_get(&port->port);
++
++	for (i = 0; i < urb->actual_length; i++) {
++		ch = (unsigned char *)urb->transfer_buffer + i;
++		if ((i <= (len - 3)) &&
++		    (*ch == QT2_CONTROL_BYTE) &&
++		    (*(ch + 1) == QT2_CONTROL_BYTE)) {
++			escapeflag = false;
++			switch (*(ch + 2)) {
++			case QT2_LINE_STATUS:
++			case QT2_MODEM_STATUS:
++				if (i > (len - 4)) {
++					dev_warn(&port->dev,
++						 "%s - status message too short\n",
++						__func__);
++					break;
++				}
++				qt2_process_status(port, ch + 2);
++				i += 3;
++				escapeflag = true;
++				break;
++			case QT2_XMIT_HOLD:
++				if (i > (len - 5)) {
++					dev_warn(&port->dev,
++						 "%s - xmit_empty message too short\n",
++						 __func__);
++					break;
++				}
++				qt2_process_xmit_empty(port, ch + 3);
++				i += 4;
++				escapeflag = true;
++				break;
++			case QT2_CHANGE_PORT:
++				if (i > (len - 4)) {
++					dev_warn(&port->dev,
++						 "%s - change_port message too short\n",
++						 __func__);
++					break;
++				}
++				if (tty) {
++					tty_flip_buffer_push(tty);
++					tty_kref_put(tty);
++				}
++
++				newport = *(ch + 3);
++
++				if (newport > serial->num_ports) {
++					dev_err(&port->dev,
++						"%s - port change to invalid port: %i\n",
++						__func__, newport);
++					break;
++				}
++
++				serial_priv->current_port = newport;
++				port = serial->port[serial_priv->current_port];
++				port_priv = usb_get_serial_port_data(port);
++				if (port_priv->is_open)
++					tty = tty_port_tty_get(&port->port);
++				else
++					tty = NULL;
++				i += 3;
++				escapeflag = true;
++				break;
++			case QT2_REC_FLUSH:
++			case QT2_XMIT_FLUSH:
++				qt2_process_flush(port, ch + 2);
++				i += 2;
++				escapeflag = true;
++				break;
++			case QT2_CONTROL_ESCAPE:
++				tty_buffer_request_room(tty, 2);
++				tty_insert_flip_string(tty, ch, 2);
++				i += 2;
++				escapeflag = true;
++				break;
++			default:
++				dev_warn(&port->dev,
++					 "%s - unsupported command %i\n",
++					 __func__, *(ch + 2));
++				break;
++			}
++			if (escapeflag)
++				continue;
++		}
++
++		if (tty) {
++			tty_buffer_request_room(tty, 1);
++			tty_insert_flip_string(tty, ch, 1);
++		}
++	}
++
++	if (tty) {
++		tty_flip_buffer_push(tty);
++		tty_kref_put(tty);
++	}
++}
++
++static void qt2_write_bulk_callback(struct urb *urb)
++{
++	struct usb_serial_port *port;
++	struct qt2_port_private *port_priv;
++
++	port = urb->context;
++	port_priv = usb_get_serial_port_data(port);
++
++	spin_lock(&port_priv->urb_lock);
++
++	port_priv->urb_in_use = false;
++	usb_serial_port_softint(port);
++
++	spin_unlock(&port_priv->urb_lock);
++
++}
++
++static void qt2_read_bulk_callback(struct urb *urb)
++{
++	struct usb_serial *serial = urb->context;
++	int status;
++
++	if (urb->status) {
++		dev_warn(&serial->dev->dev,
++			 "%s - non-zero urb status: %i\n", __func__,
++			 urb->status);
++		return;
++	}
++
++	qt2_process_read_urb(urb);
++
++	status = usb_submit_urb(urb, GFP_ATOMIC);
++	if (status != 0)
++		dev_err(&serial->dev->dev,
++			"%s - resubmit read urb failed: %i\n",
++			__func__, status);
++}
++
++static int qt2_setup_urbs(struct usb_serial *serial)
++{
++	struct usb_serial_port *port;
++	struct usb_serial_port *port0;
++	struct qt2_serial_private *serial_priv;
++	struct qt2_port_private *port_priv;
++	int pcount, status;
++
++	port0 = serial->port[0];
++
++	serial_priv = usb_get_serial_data(serial);
++	serial_priv->read_urb = usb_alloc_urb(0, GFP_KERNEL);
++	if (!serial_priv->read_urb) {
++		dev_err(&serial->dev->dev, "No free urbs available\n");
++		return -ENOMEM;
++	}
++
++	usb_fill_bulk_urb(serial_priv->read_urb, serial->dev,
++			  usb_rcvbulkpipe(serial->dev,
++					  port0->bulk_in_endpointAddress),
++			  serial_priv->read_buffer,
++			  sizeof(serial_priv->read_buffer),
++			  qt2_read_bulk_callback, serial);
++
++	/* setup write_urb for each port */
++	for (pcount = 0; pcount < serial->num_ports; pcount++) {
++
++		port = serial->port[pcount];
++		port_priv = usb_get_serial_port_data(port);
++
++		port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL);
++		if (!port_priv->write_urb) {
++			dev_err(&serial->dev->dev,
++				"failed to alloc write_urb for port %i\n",
++				pcount);
++			return -ENOMEM;
++		}
++
++		usb_fill_bulk_urb(port_priv->write_urb,
++				  serial->dev,
++				  usb_sndbulkpipe(serial->dev,
++						  port0->
++						  bulk_out_endpointAddress),
++				  port_priv->write_buffer,
++				  sizeof(port_priv->write_buffer),
++				  qt2_write_bulk_callback, port);
++	}
++
++	status = usb_submit_urb(serial_priv->read_urb, GFP_KERNEL);
++	if (status != 0) {
++		dev_err(&serial->dev->dev,
++			"%s - submit read urb failed %i\n", __func__, status);
++		return status;
++	}
++
++	return 0;
++
++}
++
++static int qt2_attach(struct usb_serial *serial)
++{
++	struct qt2_serial_private *serial_priv;
++	struct qt2_port_private *port_priv;
++	int status, pcount;
++
++	/* power on unit */
++	status = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
++				 0xc2, 0x40, 0x8000, 0, NULL, 0,
++				 QT2_USB_TIMEOUT);
++	if (status < 0) {
++		dev_err(&serial->dev->dev,
++			"%s - failed to power on unit: %i\n", __func__, status);
++		return status;
++	}
++
++	serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL);
++	if (!serial_priv) {
++		dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
++		return -ENOMEM;
++	}
++
++	usb_set_serial_data(serial, serial_priv);
++
++	for (pcount = 0; pcount < serial->num_ports; pcount++) {
++		port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
++		if (!port_priv) {
++			dev_err(&serial->dev->dev,
++				"%s- kmalloc(%Zd) failed.\n", __func__,
++				sizeof(*port_priv));
++			pcount--;
++			status = -ENOMEM;
++			goto attach_failed;
++		}
++
++		spin_lock_init(&port_priv->lock);
++		spin_lock_init(&port_priv->urb_lock);
++		init_waitqueue_head(&port_priv->delta_msr_wait);
++
++		port_priv->port = serial->port[pcount];
++
++		usb_set_serial_port_data(serial->port[pcount], port_priv);
++	}
++
++	status = qt2_setup_urbs(serial);
++	if (status != 0)
++		goto attach_failed;
++
++	return 0;
++
++attach_failed:
++	for (/* empty */; pcount >= 0; pcount--) {
++		port_priv = usb_get_serial_port_data(serial->port[pcount]);
++		kfree(port_priv);
++	}
++	kfree(serial_priv);
++	return status;
++}
++
++static int qt2_tiocmget(struct tty_struct *tty)
++{
++	struct usb_serial_port *port = tty->driver_data;
++	struct usb_device *dev = port->serial->dev;
++	struct qt2_port_private *port_priv = usb_get_serial_port_data(port);
++	u8 *d;
++	int r;
++
++	d = kzalloc(2, GFP_KERNEL);
++	if (!d)
++		return -ENOMEM;
++
++	r = qt2_getregister(dev, port_priv->device_port, UART_MCR, d);
++	if (r < 0)
++		goto mget_out;
++
++	r = qt2_getregister(dev, port_priv->device_port, UART_MSR, d + 1);
++	if (r < 0)
++		goto mget_out;
++
++	r = (d[0] & UART_MCR_DTR ? TIOCM_DTR : 0) |
++	    (d[0] & UART_MCR_RTS ? TIOCM_RTS : 0) |
++	    (d[1] & UART_MSR_CTS ? TIOCM_CTS : 0) |
++	    (d[1] & UART_MSR_DCD ? TIOCM_CAR : 0) |
++	    (d[1] & UART_MSR_RI ? TIOCM_RI : 0) |
++	    (d[1] & UART_MSR_DSR ? TIOCM_DSR : 0);
++
++mget_out:
++	kfree(d);
++	return r;
++}
++
++static int qt2_tiocmset(struct tty_struct *tty,
++			unsigned int set, unsigned int clear)
++{
++	struct qt2_port_private *port_priv;
++
++	port_priv = usb_get_serial_port_data(tty->driver_data);
++	return update_mctrl(port_priv, set, clear);
++}
++
++static void qt2_break_ctl(struct tty_struct *tty, int break_state)
++{
++	struct usb_serial_port *port = tty->driver_data;
++	struct qt2_port_private *port_priv;
++	int status;
++	u16 val;
++
++	port_priv = usb_get_serial_port_data(port);
++
++	if (!port_priv->is_open) {
++		dev_err(&port->dev,
++			"%s - port is not open\n", __func__);
++		return;
++	}
++
++	val = (break_state == -1) ? 1 : 0;
++
++	status = qt2_control_msg(port->serial->dev, QT2_BREAK_CONTROL,
++				 val, port_priv->device_port);
++	if (status < 0)
++		dev_warn(&port->dev,
++			 "%s - failed to send control message: %i\n", __func__,
++			 status);
++}
++
++
++
++static void qt2_dtr_rts(struct usb_serial_port *port, int on)
++{
++	struct usb_device *dev = port->serial->dev;
++	struct qt2_port_private *port_priv = usb_get_serial_port_data(port);
++
++	mutex_lock(&port->serial->disc_mutex);
++	if (!port->serial->disconnected) {
++		/* Disable flow control */
++		if (!on && qt2_setregister(dev, port_priv->device_port,
++					   UART_MCR, 0) < 0)
++			dev_warn(&port->dev, "error from flowcontrol urb\n");
++		/* drop RTS and DTR */
++		if (on)
++			update_mctrl(port_priv, TIOCM_DTR | TIOCM_RTS, 0);
++		else
++			update_mctrl(port_priv, 0, TIOCM_DTR | TIOCM_RTS);
++	}
++	mutex_unlock(&port->serial->disc_mutex);
++}
++
++static void qt2_update_msr(struct usb_serial_port *port, unsigned char *ch)
++{
++	struct qt2_port_private *port_priv;
++	u8 newMSR = (u8) *ch;
++	unsigned long flags;
++
++	port_priv = usb_get_serial_port_data(port);
++
++	spin_lock_irqsave(&port_priv->lock, flags);
++	port_priv->shadowMSR = newMSR;
++	spin_unlock_irqrestore(&port_priv->lock, flags);
++
++	if (newMSR & UART_MSR_ANY_DELTA) {
++		/* update input line counters */
++		if (newMSR & UART_MSR_DCTS)
++			port_priv->icount.cts++;
++
++		if (newMSR & UART_MSR_DDSR)
++			port_priv->icount.dsr++;
++
++		if (newMSR & UART_MSR_DDCD)
++			port_priv->icount.dcd++;
++
++		if (newMSR & UART_MSR_TERI)
++			port_priv->icount.rng++;
++
++		wake_up_interruptible(&port_priv->delta_msr_wait);
++	}
++}
++
++static void qt2_update_lsr(struct usb_serial_port *port, unsigned char *ch)
++{
++	struct qt2_port_private *port_priv;
++	struct async_icount *icount;
++	unsigned long flags;
++	u8 newLSR = (u8) *ch;
++
++	port_priv = usb_get_serial_port_data(port);
++
++	if (newLSR & UART_LSR_BI)
++		newLSR &= (u8) (UART_LSR_OE | UART_LSR_BI);
++
++	spin_lock_irqsave(&port_priv->lock, flags);
++	port_priv->shadowLSR = newLSR;
++	spin_unlock_irqrestore(&port_priv->lock, flags);
++
++	icount = &port_priv->icount;
++
++	if (newLSR & UART_LSR_BRK_ERROR_BITS) {
++
++		if (newLSR & UART_LSR_BI)
++			icount->brk++;
++
++		if (newLSR & UART_LSR_OE)
++			icount->overrun++;
++
++		if (newLSR & UART_LSR_PE)
++			icount->parity++;
++
++		if (newLSR & UART_LSR_FE)
++			icount->frame++;
++	}
++
++}
++
++static int qt2_write_room(struct tty_struct *tty)
++{
++	struct usb_serial_port *port = tty->driver_data;
++	struct qt2_port_private *port_priv;
++	unsigned long flags = 0;
++	int r;
++
++	port_priv = usb_get_serial_port_data(port);
++
++	spin_lock_irqsave(&port_priv->urb_lock, flags);
++
++	if (port_priv->urb_in_use)
++		r = 0;
++	else
++		r = QT2_WRITE_BUFFER_SIZE - QT2_WRITE_CONTROL_SIZE;
++
++	spin_unlock_irqrestore(&port_priv->urb_lock, flags);
++
++	return r;
++}
++
++static int qt2_write(struct tty_struct *tty,
++		     struct usb_serial_port *port,
++		     const unsigned char *buf, int count)
++{
++	struct qt2_port_private *port_priv;
++	struct urb *write_urb;
++	unsigned char *data;
++	unsigned long flags;
++	int status;
++	int bytes_out = 0;
++
++	port_priv = usb_get_serial_port_data(port);
++
++	if (port_priv->write_urb == NULL) {
++		dev_err(&port->dev, "%s - no output urb\n", __func__);
++		return 0;
++	}
++	write_urb = port_priv->write_urb;
++
++	count = min(count, QT2_WRITE_BUFFER_SIZE - QT2_WRITE_CONTROL_SIZE);
++
++	data = write_urb->transfer_buffer;
++	spin_lock_irqsave(&port_priv->urb_lock, flags);
++	if (port_priv->urb_in_use == true) {
++		printk(KERN_INFO "qt2_write - urb is in use\n");
++		goto write_out;
++	}
++
++	*data++ = QT2_CONTROL_BYTE;
++	*data++ = QT2_CONTROL_BYTE;
++	*data++ = port_priv->device_port;
++	put_unaligned_le16(count, data);
++	data += 2;
++	memcpy(data, buf, count);
++
++	write_urb->transfer_buffer_length = count + QT2_WRITE_CONTROL_SIZE;
++
++	status = usb_submit_urb(write_urb, GFP_ATOMIC);
++	if (status == 0) {
++		port_priv->urb_in_use = true;
++		bytes_out += count;
++	}
++
++write_out:
++	spin_unlock_irqrestore(&port_priv->urb_lock, flags);
++	return bytes_out;
++}
++
++
++static struct usb_serial_driver qt2_device = {
++	.driver = {
++		.owner = THIS_MODULE,
++		.name = "quatech-serial",
++	},
++	.description	     = DRIVER_DESC,
++	.id_table	     = id_table,
++	.open		     = qt2_open,
++	.close		     = qt2_close,
++	.write               = qt2_write,
++	.write_room          = qt2_write_room,
++	.calc_num_ports      = qt2_calc_num_ports,
++	.attach              = qt2_attach,
++	.release             = qt2_release,
++	.disconnect          = qt2_disconnect,
++	.dtr_rts             = qt2_dtr_rts,
++	.break_ctl           = qt2_break_ctl,
++	.tiocmget            = qt2_tiocmget,
++	.tiocmset            = qt2_tiocmset,
++	.get_icount	     = qt2_get_icount,
++	.ioctl               = qt2_ioctl,
++	.set_termios         = qt2_set_termios,
++};
++
++static struct usb_serial_driver *const serial_drivers[] = {
++	&qt2_device, NULL
++};
++
++module_usb_serial_driver(serial_drivers, id_table);
++
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_LICENSE("GPL");
++
++module_param(debug, bool, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(debug, "Debug enabled or not");

commit 7cbf3c7cd59288fb5e9f31815c74773549668d43
+Author: Bill Pemberton 
+Date:   Mon Aug 29 13:48:54 2011 -0400
+
+    staging: serqt_usb2: remove ssu100 from supported devices
+    
+    The serqt_usb2 driver will not work properly with the ssu100 device
+    even though it claims to support it.  The ssu100 is supported by the
+    ssu100 driver in mainline so there is no need to have it claimed by
+    serqt_usb2.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c
+index 2ea82c104d57..c44e41af2880 100644
+--- a/drivers/staging/serqt_usb2/serqt_usb2.c
++++ b/drivers/staging/serqt_usb2/serqt_usb2.c
+@@ -24,7 +24,6 @@ static int debug;
+ #define DRIVER_DESC "Quatech USB to Serial Driver"
+ 
+ #define	USB_VENDOR_ID_QUATECH			0x061d	/* Quatech VID */
+-#define QUATECH_SSU100	0xC020	/* SSU100 */
+ #define QUATECH_SSU200	0xC030	/* SSU200 */
+ #define QUATECH_DSU100	0xC040	/* DSU100 */
+ #define QUATECH_DSU200	0xC050	/* DSU200 */
+@@ -127,7 +126,6 @@ static int debug;
+ #define RS232_MODE          0x00
+ 
+ static const struct usb_device_id serqt_id_table[] = {
+-	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU100)},
+ 	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU200)},
+ 	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU100)},
+ 	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU200)},
+@@ -775,7 +773,6 @@ static int qt_startup(struct usb_serial *serial)
+ 	}
+ 
+ 	switch (serial->dev->descriptor.idProduct) {
+-	case QUATECH_SSU100:
+ 	case QUATECH_DSU100:
+ 	case QUATECH_QSU100:
+ 	case QUATECH_ESU100A:

commit f7043ecbb3f7b8632a6d6470f8f95160ac868d0f
+Author: Bill Pemberton 
+Date:   Thu Oct 21 14:43:05 2010 -0400
+
+    USB: ssu100: remove max_packet_size calculation
+    
+    The max_packet_size logic is taken from ftdi_sio, but it's not needed
+    for this device.  This also makes proces_read_urb simpler.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
+index f5312dd3331b..8359ec798959 100644
+--- a/drivers/usb/serial/ssu100.c
++++ b/drivers/usb/serial/ssu100.c
+@@ -79,7 +79,6 @@ struct ssu100_port_private {
+ 	u8 shadowLSR;
+ 	u8 shadowMSR;
+ 	wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
+-	unsigned short max_packet_size;
+ 	struct async_icount icount;
+ };
+ 
+@@ -464,36 +463,6 @@ static int ssu100_ioctl(struct tty_struct *tty, struct file *file,
+ 	return -ENOIOCTLCMD;
+ }
+ 
+-static void ssu100_set_max_packet_size(struct usb_serial_port *port)
+-{
+-	struct ssu100_port_private *priv = usb_get_serial_port_data(port);
+-	struct usb_serial *serial = port->serial;
+-	struct usb_device *udev = serial->dev;
+-
+-	struct usb_interface *interface = serial->interface;
+-	struct usb_endpoint_descriptor *ep_desc = &interface->cur_altsetting->endpoint[1].desc;
+-
+-	unsigned num_endpoints;
+-	int i;
+-	unsigned long flags;
+-
+-	num_endpoints = interface->cur_altsetting->desc.bNumEndpoints;
+-	dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints);
+-
+-	for (i = 0; i < num_endpoints; i++) {
+-		dev_info(&udev->dev, "Endpoint %d MaxPacketSize %d\n", i+1,
+-			interface->cur_altsetting->endpoint[i].desc.wMaxPacketSize);
+-		ep_desc = &interface->cur_altsetting->endpoint[i].desc;
+-	}
+-
+-	/* set max packet size based on descriptor */
+-	spin_lock_irqsave(&priv->status_lock, flags);
+-	priv->max_packet_size = ep_desc->wMaxPacketSize;
+-	spin_unlock_irqrestore(&priv->status_lock, flags);
+-
+-	dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size);
+-}
+-
+ static int ssu100_attach(struct usb_serial *serial)
+ {
+ 	struct ssu100_port_private *priv;
+@@ -511,7 +480,6 @@ static int ssu100_attach(struct usb_serial *serial)
+ 	spin_lock_init(&priv->status_lock);
+ 	init_waitqueue_head(&priv->delta_msr_wait);
+ 	usb_set_serial_port_data(port, priv);
+-	ssu100_set_max_packet_size(port);
+ 
+ 	return ssu100_initdevice(serial->dev);
+ }
+@@ -641,13 +609,14 @@ static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr,
+ 
+ }
+ 
+-static int ssu100_process_packet(struct tty_struct *tty,
+-				 struct usb_serial_port *port,
+-				 struct ssu100_port_private *priv,
+-				 char *packet, int len)
++static int ssu100_process_packet(struct urb *urb,
++				 struct tty_struct *tty)
+ {
+-	int i;
++	struct usb_serial_port *port = urb->context;
++	char *packet = (char *)urb->transfer_buffer;
+ 	char flag = TTY_NORMAL;
++	u32 len = urb->actual_length;
++	int i;
+ 	char *ch;
+ 
+ 	dbg("%s - port %d", __func__, port->number);
+@@ -685,12 +654,8 @@ static int ssu100_process_packet(struct tty_struct *tty,
+ static void ssu100_process_read_urb(struct urb *urb)
+ {
+ 	struct usb_serial_port *port = urb->context;
+-	struct ssu100_port_private *priv = usb_get_serial_port_data(port);
+-	char *data = (char *)urb->transfer_buffer;
+ 	struct tty_struct *tty;
+-	int count = 0;
+-	int i;
+-	int len;
++	int count;
+ 
+ 	dbg("%s", __func__);
+ 
+@@ -698,10 +663,7 @@ static void ssu100_process_read_urb(struct urb *urb)
+ 	if (!tty)
+ 		return;
+ 
+-	for (i = 0; i < urb->actual_length; i += priv->max_packet_size) {
+-		len = min_t(int, urb->actual_length - i, priv->max_packet_size);
+-		count += ssu100_process_packet(tty, port, priv, &data[i], len);
+-	}
++	count = ssu100_process_packet(urb, tty);
+ 
+ 	if (count)
+ 		tty_flip_buffer_push(tty);
+@@ -717,8 +679,6 @@ static struct usb_serial_driver ssu100_device = {
+ 	.id_table	     = id_table,
+ 	.usb_driver	     = &ssu100_driver,
+ 	.num_ports	     = 1,
+-	.bulk_in_size        = 256,
+-	.bulk_out_size       = 256,
+ 	.open		     = ssu100_open,
+ 	.close		     = ssu100_close,
+ 	.attach              = ssu100_attach,

commit 50c1126ee1990920705a067a6f3f9bb892369b08
+Author: Bill Pemberton 
+Date:   Tue Aug 3 15:18:43 2010 -0400
+
+    PCI: aerdrv: fix uninitialized variable warning
+    
+    quiet the warning about use of uninitialized e_src in
+    aer_isr()  e_src is initialized by get_e_source()
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Jesse Barnes 
+
+diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
+index 29e268fadf14..43421fbe080a 100644
+--- a/drivers/pci/pcie/aer/aerdrv_core.c
++++ b/drivers/pci/pcie/aer/aerdrv_core.c
+@@ -754,7 +754,7 @@ void aer_isr(struct work_struct *work)
+ {
+ 	struct aer_rpc *rpc = container_of(work, struct aer_rpc, dpc_handler);
+ 	struct pcie_device *p_device = rpc->rpd;
+-	struct aer_err_source e_src;
++	struct aer_err_source uninitialized_var(e_src);
+ 
+ 	mutex_lock(&rpc->rpc_mutex);
+ 	while (get_e_source(rpc, &e_src))

commit 3c35b002da0c749ec15cf25cfe58f06aa230ae9c
+Author: Bill Pemberton 
+Date:   Wed Aug 25 18:21:23 2010 -0400
+
+    USB: ssu100: turn off debug flag
+    
+    Remove the hard coding of the debug flag to 1.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
+index 68c18fdfc6da..e986002b3844 100644
+--- a/drivers/usb/serial/ssu100.c
++++ b/drivers/usb/serial/ssu100.c
+@@ -46,7 +46,7 @@
+ #define FULLPWRBIT          0x00000080
+ #define NEXT_BOARD_POWER_BIT        0x00000004
+ 
+-static int debug = 1;
++static int debug;
+ 
+ /* Version Information */
+ #define DRIVER_VERSION "v0.1"

commit 6b8f1ca5581bf9783069cd6bde65ba7a3a470aab
+Author: Bill Pemberton 
+Date:   Fri Aug 13 09:59:31 2010 -0400
+
+    USB: ssu100: set tty_flags in ssu100_process_packet
+    
+    flag was never set in ssu100_process_packet.  Add logic to set it
+    before calling tty_insert_flip_*
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
+index 55e9672d286a..660c31f14999 100644
+--- a/drivers/usb/serial/ssu100.c
++++ b/drivers/usb/serial/ssu100.c
+@@ -602,7 +602,8 @@ static void ssu100_update_msr(struct usb_serial_port *port, u8 msr)
+ 	}
+ }
+ 
+-static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr)
++static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr,
++			      char *tty_flag)
+ {
+ 	struct ssu100_port_private *priv = usb_get_serial_port_data(port);
+ 	unsigned long flags;
+@@ -611,16 +612,32 @@ static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr)
+ 	priv->shadowLSR = lsr;
+ 	spin_unlock_irqrestore(&priv->status_lock, flags);
+ 
++	*tty_flag = TTY_NORMAL;
+ 	if (lsr & UART_LSR_BRK_ERROR_BITS) {
+-		if (lsr & UART_LSR_BI)
++		/* we always want to update icount, but we only want to
++		 * update tty_flag for one case */
++		if (lsr & UART_LSR_BI) {
+ 			priv->icount.brk++;
+-		if (lsr & UART_LSR_FE)
+-			priv->icount.frame++;
+-		if (lsr & UART_LSR_PE)
++			*tty_flag = TTY_BREAK;
++			usb_serial_handle_break(port);
++		}
++		if (lsr & UART_LSR_PE) {
+ 			priv->icount.parity++;
+-		if (lsr & UART_LSR_OE)
++			if (*tty_flag == TTY_NORMAL)
++				*tty_flag = TTY_PARITY;
++		}
++		if (lsr & UART_LSR_FE) {
++			priv->icount.frame++;
++			if (*tty_flag == TTY_NORMAL)
++				*tty_flag = TTY_FRAME;
++		}
++		if (lsr & UART_LSR_OE){
+ 			priv->icount.overrun++;
++			if (*tty_flag == TTY_NORMAL)
++				*tty_flag = TTY_OVERRUN;
++		}
+ 	}
++
+ }
+ 
+ static int ssu100_process_packet(struct tty_struct *tty,
+@@ -629,7 +646,7 @@ static int ssu100_process_packet(struct tty_struct *tty,
+ 				 char *packet, int len)
+ {
+ 	int i;
+-	char flag;
++	char flag = TTY_NORMAL;
+ 	char *ch;
+ 
+ 	dbg("%s - port %d", __func__, port->number);
+@@ -637,8 +654,11 @@ static int ssu100_process_packet(struct tty_struct *tty,
+ 	if ((len >= 4) &&
+ 	    (packet[0] == 0x1b) && (packet[1] == 0x1b) &&
+ 	    ((packet[2] == 0x00) || (packet[2] == 0x01))) {
+-		if (packet[2] == 0x00)
+-			ssu100_update_lsr(port, packet[3]);
++		if (packet[2] == 0x00) {
++			ssu100_update_lsr(port, packet[3], &flag);
++			if (flag == TTY_OVERRUN)
++				tty_insert_flip_char(tty, 0, TTY_OVERRUN);
++		}
+ 		if (packet[2] == 0x01)
+ 			ssu100_update_msr(port, packet[3]);
+ 

commit 85dee135b84f1c7cad252fa4a619ea692077a7fc
+Author: Bill Pemberton 
+Date:   Thu Aug 5 17:01:11 2010 -0400
+
+    USB: ssu100: add disconnect function for ssu100
+    
+    Add a disconnect function to the functions of this device.  The
+    disconnect is a call to usb_serial_generic_disconnect() so it requires
+    that symbol to be exported from generic.c.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
+index e244491b1a0d..55e9672d286a 100644
+--- a/drivers/usb/serial/ssu100.c
++++ b/drivers/usb/serial/ssu100.c
+@@ -687,7 +687,6 @@ static void ssu100_process_read_urb(struct urb *urb)
+ 	tty_kref_put(tty);
+ }
+ 
+-
+ static struct usb_serial_driver ssu100_device = {
+ 	.driver = {
+ 		.owner = THIS_MODULE,
+@@ -709,6 +708,7 @@ static struct usb_serial_driver ssu100_device = {
+ 	.tiocmset            = ssu100_tiocmset,
+ 	.ioctl               = ssu100_ioctl,
+ 	.set_termios         = ssu100_set_termios,
++	.disconnect          = usb_serial_generic_disconnect,
+ };
+ 
+ static int __init ssu100_init(void)

commit 5c7efeb76e7dc5145b467657fa049f3c1bd9cf58
+Author: Bill Pemberton 
+Date:   Thu Aug 5 17:01:10 2010 -0400
+
+    USB: serial: export symbol usb_serial_generic_disconnect
+    
+    This is needed by the ssu100 driver to use this function.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
+index ca92f67747cc..0b1a13384c6d 100644
+--- a/drivers/usb/serial/generic.c
++++ b/drivers/usb/serial/generic.c
+@@ -518,6 +518,7 @@ void usb_serial_generic_disconnect(struct usb_serial *serial)
+ 	for (i = 0; i < serial->num_ports; ++i)
+ 		generic_cleanup(serial->port[i]);
+ }
++EXPORT_SYMBOL_GPL(usb_serial_generic_disconnect);
+ 
+ void usb_serial_generic_release(struct usb_serial *serial)
+ {

commit f81c83db563334d8377b26ad45585261f604605a
+Author: Bill Pemberton 
+Date:   Thu Aug 5 17:01:09 2010 -0400
+
+    USB: ssu100: rework logic for TIOCMIWAIT
+    
+    Rework the logic for TIOCMIWAIT to use wait_event_interruptible.
+    
+    This also adds support for TIOCGICOUNT.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
+index ad5f9ae40687..e244491b1a0d 100644
+--- a/drivers/usb/serial/ssu100.c
++++ b/drivers/usb/serial/ssu100.c
+@@ -80,6 +80,7 @@ struct ssu100_port_private {
+ 	u8 shadowMSR;
+ 	wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
+ 	unsigned short max_packet_size;
++	struct async_icount icount;
+ };
+ 
+ static void ssu100_release(struct usb_serial *serial)
+@@ -330,11 +331,8 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port)
+ 	}
+ 
+ 	spin_lock_irqsave(&priv->status_lock, flags);
+-	priv->shadowLSR = data[0]  & (UART_LSR_OE | UART_LSR_PE |
+-				      UART_LSR_FE | UART_LSR_BI);
+-
+-	priv->shadowMSR = data[1]  & (UART_MSR_CTS | UART_MSR_DSR |
+-				      UART_MSR_RI | UART_MSR_DCD);
++	priv->shadowLSR = data[0];
++	priv->shadowMSR = data[1];
+ 	spin_unlock_irqrestore(&priv->status_lock, flags);
+ 
+ 	kfree(data);
+@@ -379,11 +377,51 @@ static int get_serial_info(struct usb_serial_port *port,
+ 	return 0;
+ }
+ 
++static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
++{
++	struct ssu100_port_private *priv = usb_get_serial_port_data(port);
++	struct async_icount prev, cur;
++	unsigned long flags;
++
++	spin_lock_irqsave(&priv->status_lock, flags);
++	prev = priv->icount;
++	spin_unlock_irqrestore(&priv->status_lock, flags);
++
++	while (1) {
++		wait_event_interruptible(priv->delta_msr_wait,
++					 ((priv->icount.rng != prev.rng) ||
++					  (priv->icount.dsr != prev.dsr) ||
++					  (priv->icount.dcd != prev.dcd) ||
++					  (priv->icount.cts != prev.cts)));
++
++		if (signal_pending(current))
++			return -ERESTARTSYS;
++
++		spin_lock_irqsave(&priv->status_lock, flags);
++		cur = priv->icount;
++		spin_unlock_irqrestore(&priv->status_lock, flags);
++
++		if ((prev.rng == cur.rng) &&
++		    (prev.dsr == cur.dsr) &&
++		    (prev.dcd == cur.dcd) &&
++		    (prev.cts == cur.cts))
++			return -EIO;
++
++		if ((arg & TIOCM_RNG && (prev.rng != cur.rng)) ||
++		    (arg & TIOCM_DSR && (prev.dsr != cur.dsr)) ||
++		    (arg & TIOCM_CD  && (prev.dcd != cur.dcd)) ||
++		    (arg & TIOCM_CTS && (prev.cts != cur.cts)))
++			return 0;
++	}
++	return 0;
++}
++
+ static int ssu100_ioctl(struct tty_struct *tty, struct file *file,
+ 		    unsigned int cmd, unsigned long arg)
+ {
+ 	struct usb_serial_port *port = tty->driver_data;
+ 	struct ssu100_port_private *priv = usb_get_serial_port_data(port);
++	void __user *user_arg = (void __user *)arg;
+ 
+ 	dbg("%s cmd 0x%04x", __func__, cmd);
+ 
+@@ -393,28 +431,28 @@ static int ssu100_ioctl(struct tty_struct *tty, struct file *file,
+ 				       (struct serial_struct __user *) arg);
+ 
+ 	case TIOCMIWAIT:
+-		while (priv != NULL) {
+-			u8 prevMSR = priv->shadowMSR & SERIAL_MSR_MASK;
+-			interruptible_sleep_on(&priv->delta_msr_wait);
+-			/* see if a signal did it */
+-			if (signal_pending(current))
+-				return -ERESTARTSYS;
+-			else {
+-				u8 diff = (priv->shadowMSR & SERIAL_MSR_MASK) ^ prevMSR;
+-				if (!diff)
+-					return -EIO; /* no change => error */
+-
+-				/* Return 0 if caller wanted to know about
+-				   these bits */
+-
+-				if (((arg & TIOCM_RNG) && (diff & UART_MSR_RI)) ||
+-				    ((arg & TIOCM_DSR) && (diff & UART_MSR_DSR)) ||
+-				    ((arg & TIOCM_CD) && (diff & UART_MSR_DCD)) ||
+-				    ((arg & TIOCM_CTS) && (diff & UART_MSR_CTS)))
+-					return 0;
+-			}
+-		}
++		return wait_modem_info(port, arg);
++
++	case TIOCGICOUNT:
++	{
++		struct serial_icounter_struct icount;
++		struct async_icount cnow = priv->icount;
++		memset(&icount, 0, sizeof(icount));
++		icount.cts = cnow.cts;
++		icount.dsr = cnow.dsr;
++		icount.rng = cnow.rng;
++		icount.dcd = cnow.dcd;
++		icount.rx = cnow.rx;
++		icount.tx = cnow.tx;
++		icount.frame = cnow.frame;
++		icount.overrun = cnow.overrun;
++		icount.parity = cnow.parity;
++		icount.brk = cnow.brk;
++		icount.buf_overrun = cnow.buf_overrun;
++		if (copy_to_user(user_arg, &icount, sizeof(icount)))
++			return -EFAULT;
+ 		return 0;
++	}
+ 
+ 	default:
+ 		break;
+@@ -541,6 +579,50 @@ static void ssu100_dtr_rts(struct usb_serial_port *port, int on)
+ 	mutex_unlock(&port->serial->disc_mutex);
+ }
+ 
++static void ssu100_update_msr(struct usb_serial_port *port, u8 msr)
++{
++	struct ssu100_port_private *priv = usb_get_serial_port_data(port);
++	unsigned long flags;
++
++	spin_lock_irqsave(&priv->status_lock, flags);
++	priv->shadowMSR = msr;
++	spin_unlock_irqrestore(&priv->status_lock, flags);
++
++	if (msr & UART_MSR_ANY_DELTA) {
++		/* update input line counters */
++		if (msr & UART_MSR_DCTS)
++			priv->icount.cts++;
++		if (msr & UART_MSR_DDSR)
++			priv->icount.dsr++;
++		if (msr & UART_MSR_DDCD)
++			priv->icount.dcd++;
++		if (msr & UART_MSR_TERI)
++			priv->icount.rng++;
++		wake_up_interruptible(&priv->delta_msr_wait);
++	}
++}
++
++static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr)
++{
++	struct ssu100_port_private *priv = usb_get_serial_port_data(port);
++	unsigned long flags;
++
++	spin_lock_irqsave(&priv->status_lock, flags);
++	priv->shadowLSR = lsr;
++	spin_unlock_irqrestore(&priv->status_lock, flags);
++
++	if (lsr & UART_LSR_BRK_ERROR_BITS) {
++		if (lsr & UART_LSR_BI)
++			priv->icount.brk++;
++		if (lsr & UART_LSR_FE)
++			priv->icount.frame++;
++		if (lsr & UART_LSR_PE)
++			priv->icount.parity++;
++		if (lsr & UART_LSR_OE)
++			priv->icount.overrun++;
++	}
++}
++
+ static int ssu100_process_packet(struct tty_struct *tty,
+ 				 struct usb_serial_port *port,
+ 				 struct ssu100_port_private *priv,
+@@ -556,15 +638,9 @@ static int ssu100_process_packet(struct tty_struct *tty,
+ 	    (packet[0] == 0x1b) && (packet[1] == 0x1b) &&
+ 	    ((packet[2] == 0x00) || (packet[2] == 0x01))) {
+ 		if (packet[2] == 0x00)
+-			priv->shadowLSR = packet[3] & (UART_LSR_OE |
+-						       UART_LSR_PE |
+-						       UART_LSR_FE |
+-						       UART_LSR_BI);
+-
+-		if (packet[2] == 0x01) {
+-			priv->shadowMSR = packet[3];
+-			wake_up_interruptible(&priv->delta_msr_wait);
+-		}
++			ssu100_update_lsr(port, packet[3]);
++		if (packet[2] == 0x01)
++			ssu100_update_msr(port, packet[3]);
+ 
+ 		len -= 4;
+ 		ch = packet + 4;

commit 556f1a0e9c178193e584209b47cf1cb9f669bd51
+Author: Bill Pemberton 
+Date:   Thu Aug 5 17:01:08 2010 -0400
+
+    USB: ssu100: add register parameter to ssu100_setregister
+    
+    The function ssu100_setregister was hard coded to only set the MCR
+    register.  Add a register parameter so that other registers can be
+    set.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
+index 3c586b5790e1..ad5f9ae40687 100644
+--- a/drivers/usb/serial/ssu100.c
++++ b/drivers/usb/serial/ssu100.c
+@@ -127,9 +127,10 @@ static inline int ssu100_getregister(struct usb_device *dev,
+ 
+ static inline int ssu100_setregister(struct usb_device *dev,
+ 				     unsigned short uart,
++				     unsigned short reg,
+ 				     u16 data)
+ {
+-	u16 value = (data << 8) | UART_MCR;
++	u16 value = (data << 8) | reg;
+ 
+ 	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ 			       QT_SET_GET_REGISTER, 0x40, value, uart,
+@@ -159,7 +160,7 @@ static inline int update_mctrl(struct usb_device *dev, unsigned int set,
+ 	if (set & TIOCM_RTS)
+ 		urb_value |= UART_MCR_RTS;
+ 
+-	result = ssu100_setregister(dev, 0, urb_value);
++	result = ssu100_setregister(dev, 0, UART_MCR, urb_value);
+ 	if (result < 0)
+ 		dbg("%s Error from MODEM_CTRL urb", __func__);
+ 
+@@ -529,7 +530,7 @@ static void ssu100_dtr_rts(struct usb_serial_port *port, int on)
+ 	if (!port->serial->disconnected) {
+ 		/* Disable flow control */
+ 		if (!on &&
+-		    ssu100_setregister(dev, 0, 0) < 0)
++		    ssu100_setregister(dev, 0, UART_MCR, 0) < 0)
+ 			dev_err(&port->dev, "error from flowcontrol urb\n");
+ 		/* drop RTS and DTR */
+ 		if (on)

commit 79f203a26a07a9d5701c404925e85eb161b72cde
+Author: Bill Pemberton 
+Date:   Thu Aug 5 17:01:07 2010 -0400
+
+    USB: ssu100: remove duplicate #defines in ssu100
+    
+    The ssu100 uses a TI16C550C UART so the SERIAL_ defines in this code
+    are duplicates of those found in serial_reg.h.  Remove the defines in
+    ssu100.c and use the ones in the header file.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
+index c7193880a2b6..3c586b5790e1 100644
+--- a/drivers/usb/serial/ssu100.c
++++ b/drivers/usb/serial/ssu100.c
+@@ -15,6 +15,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ 
+ #define QT_OPEN_CLOSE_CHANNEL       0xca
+@@ -27,36 +28,11 @@
+ #define QT_HW_FLOW_CONTROL_MASK     0xc5
+ #define QT_SW_FLOW_CONTROL_MASK     0xc6
+ 
+-#define MODEM_CTL_REGISTER         0x04
+-#define MODEM_STATUS_REGISTER      0x06
+-
+-
+-#define SERIAL_LSR_OE       0x02
+-#define SERIAL_LSR_PE       0x04
+-#define SERIAL_LSR_FE       0x08
+-#define SERIAL_LSR_BI       0x10
+-
+-#define SERIAL_LSR_TEMT     0x40
+-
+-#define  SERIAL_MCR_DTR             0x01
+-#define  SERIAL_MCR_RTS             0x02
+-#define  SERIAL_MCR_LOOP            0x10
+-
+-#define  SERIAL_MSR_CTS             0x10
+-#define  SERIAL_MSR_CD              0x80
+-#define  SERIAL_MSR_RI              0x40
+-#define  SERIAL_MSR_DSR             0x20
+ #define  SERIAL_MSR_MASK            0xf0
+ 
+-#define  SERIAL_CRTSCTS ((SERIAL_MCR_RTS << 8) | SERIAL_MSR_CTS)
+-
+-#define  SERIAL_8_DATA              0x03
+-#define  SERIAL_7_DATA              0x02
+-#define  SERIAL_6_DATA              0x01
+-#define  SERIAL_5_DATA              0x00
++#define  SERIAL_CRTSCTS ((UART_MCR_RTS << 8) | UART_MSR_CTS)
+ 
+-#define  SERIAL_ODD_PARITY          0X08
+-#define  SERIAL_EVEN_PARITY         0X18
++#define  SERIAL_EVEN_PARITY         (UART_LCR_PARITY | UART_LCR_EPAR)
+ 
+ #define  MAX_BAUD_RATE              460800
+ 
+@@ -153,7 +129,7 @@ static inline int ssu100_setregister(struct usb_device *dev,
+ 				     unsigned short uart,
+ 				     u16 data)
+ {
+-	u16 value = (data << 8) | MODEM_CTL_REGISTER;
++	u16 value = (data << 8) | UART_MCR;
+ 
+ 	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ 			       QT_SET_GET_REGISTER, 0x40, value, uart,
+@@ -179,9 +155,9 @@ static inline int update_mctrl(struct usb_device *dev, unsigned int set,
+ 	clear &= ~set;	/* 'set' takes precedence over 'clear' */
+ 	urb_value = 0;
+ 	if (set & TIOCM_DTR)
+-		urb_value |= SERIAL_MCR_DTR;
++		urb_value |= UART_MCR_DTR;
+ 	if (set & TIOCM_RTS)
+-		urb_value |= SERIAL_MCR_RTS;
++		urb_value |= UART_MCR_RTS;
+ 
+ 	result = ssu100_setregister(dev, 0, urb_value);
+ 	if (result < 0)
+@@ -265,24 +241,24 @@ static void ssu100_set_termios(struct tty_struct *tty,
+ 
+ 	if (cflag & PARENB) {
+ 		if (cflag & PARODD)
+-			urb_value |= SERIAL_ODD_PARITY;
++			urb_value |= UART_LCR_PARITY;
+ 		else
+ 			urb_value |= SERIAL_EVEN_PARITY;
+ 	}
+ 
+ 	switch (cflag & CSIZE) {
+ 	case CS5:
+-		urb_value |= SERIAL_5_DATA;
++		urb_value |= UART_LCR_WLEN5;
+ 		break;
+ 	case CS6:
+-		urb_value |= SERIAL_6_DATA;
++		urb_value |= UART_LCR_WLEN6;
+ 		break;
+ 	case CS7:
+-		urb_value |= SERIAL_7_DATA;
++		urb_value |= UART_LCR_WLEN7;
+ 		break;
+ 	default:
+ 	case CS8:
+-		urb_value |= SERIAL_8_DATA;
++		urb_value |= UART_LCR_WLEN8;
+ 		break;
+ 	}
+ 
+@@ -353,11 +329,11 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port)
+ 	}
+ 
+ 	spin_lock_irqsave(&priv->status_lock, flags);
+-	priv->shadowLSR = data[0]  & (SERIAL_LSR_OE | SERIAL_LSR_PE |
+-				      SERIAL_LSR_FE | SERIAL_LSR_BI);
++	priv->shadowLSR = data[0]  & (UART_LSR_OE | UART_LSR_PE |
++				      UART_LSR_FE | UART_LSR_BI);
+ 
+-	priv->shadowMSR = data[1]  & (SERIAL_MSR_CTS | SERIAL_MSR_DSR |
+-				      SERIAL_MSR_RI | SERIAL_MSR_CD);
++	priv->shadowMSR = data[1]  & (UART_MSR_CTS | UART_MSR_DSR |
++				      UART_MSR_RI | UART_MSR_DCD);
+ 	spin_unlock_irqrestore(&priv->status_lock, flags);
+ 
+ 	kfree(data);
+@@ -430,10 +406,10 @@ static int ssu100_ioctl(struct tty_struct *tty, struct file *file,
+ 				/* Return 0 if caller wanted to know about
+ 				   these bits */
+ 
+-				if (((arg & TIOCM_RNG) && (diff & SERIAL_MSR_RI)) ||
+-				    ((arg & TIOCM_DSR) && (diff & SERIAL_MSR_DSR)) ||
+-				    ((arg & TIOCM_CD) && (diff & SERIAL_MSR_CD)) ||
+-				    ((arg & TIOCM_CTS) && (diff & SERIAL_MSR_CTS)))
++				if (((arg & TIOCM_RNG) && (diff & UART_MSR_RI)) ||
++				    ((arg & TIOCM_DSR) && (diff & UART_MSR_DSR)) ||
++				    ((arg & TIOCM_CD) && (diff & UART_MSR_DCD)) ||
++				    ((arg & TIOCM_CTS) && (diff & UART_MSR_CTS)))
+ 					return 0;
+ 			}
+ 		}
+@@ -513,20 +489,20 @@ static int ssu100_tiocmget(struct tty_struct *tty, struct file *file)
+ 	if (!d)
+ 		return -ENOMEM;
+ 
+-	r = ssu100_getregister(dev, 0, MODEM_CTL_REGISTER, d);
++	r = ssu100_getregister(dev, 0, UART_MCR, d);
+ 	if (r < 0)
+ 		goto mget_out;
+ 
+-	r = ssu100_getregister(dev, 0, MODEM_STATUS_REGISTER, d+1);
++	r = ssu100_getregister(dev, 0, UART_MSR, d+1);
+ 	if (r < 0)
+ 		goto mget_out;
+ 
+-	r = (d[0] & SERIAL_MCR_DTR ? TIOCM_DTR : 0) |
+-		(d[0] & SERIAL_MCR_RTS ? TIOCM_RTS : 0) |
+-		(d[1] & SERIAL_MSR_CTS ? TIOCM_CTS : 0) |
+-		(d[1] & SERIAL_MSR_CD ? TIOCM_CAR : 0) |
+-		(d[1] & SERIAL_MSR_RI ? TIOCM_RI : 0) |
+-		(d[1] & SERIAL_MSR_DSR ? TIOCM_DSR : 0);
++	r = (d[0] & UART_MCR_DTR ? TIOCM_DTR : 0) |
++		(d[0] & UART_MCR_RTS ? TIOCM_RTS : 0) |
++		(d[1] & UART_MSR_CTS ? TIOCM_CTS : 0) |
++		(d[1] & UART_MSR_DCD ? TIOCM_CAR : 0) |
++		(d[1] & UART_MSR_RI ? TIOCM_RI : 0) |
++		(d[1] & UART_MSR_DSR ? TIOCM_DSR : 0);
+ 
+ mget_out:
+ 	kfree(d);
+@@ -579,10 +555,10 @@ static int ssu100_process_packet(struct tty_struct *tty,
+ 	    (packet[0] == 0x1b) && (packet[1] == 0x1b) &&
+ 	    ((packet[2] == 0x00) || (packet[2] == 0x01))) {
+ 		if (packet[2] == 0x00)
+-			priv->shadowLSR = packet[3] & (SERIAL_LSR_OE |
+-						       SERIAL_LSR_PE |
+-						       SERIAL_LSR_FE |
+-						       SERIAL_LSR_BI);
++			priv->shadowLSR = packet[3] & (UART_LSR_OE |
++						       UART_LSR_PE |
++						       UART_LSR_FE |
++						       UART_LSR_BI);
+ 
+ 		if (packet[2] == 0x01) {
+ 			priv->shadowMSR = packet[3];

commit 9b2cef31f2823558eb92a35624d37439599f3f9f
+Author: Bill Pemberton 
+Date:   Thu Aug 5 17:01:06 2010 -0400
+
+    USB: ssu100: refine process_packet in ssu100
+    
+    The status information does not appear at the start of each incoming
+    packet so the check for len < 4 at the start of ssu100_process_packet
+    is wrong.  Remove it.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
+index 2826f013752d..c7193880a2b6 100644
+--- a/drivers/usb/serial/ssu100.c
++++ b/drivers/usb/serial/ssu100.c
+@@ -575,12 +575,8 @@ static int ssu100_process_packet(struct tty_struct *tty,
+ 
+ 	dbg("%s - port %d", __func__, port->number);
+ 
+-	if (len < 4) {
+-		dbg("%s - malformed packet", __func__);
+-		return 0;
+-	}
+-
+-	if ((packet[0] == 0x1b) && (packet[1] == 0x1b) &&
++	if ((len >= 4) &&
++	    (packet[0] == 0x1b) && (packet[1] == 0x1b) &&
+ 	    ((packet[2] == 0x00) || (packet[2] == 0x01))) {
+ 		if (packet[2] == 0x00)
+ 			priv->shadowLSR = packet[3] & (SERIAL_LSR_OE |

commit 175230587bcca6dee0a1d6832a8a2138e32ab6ab
+Author: Bill Pemberton 
+Date:   Thu Aug 5 17:01:05 2010 -0400
+
+    USB: ssu100: add locking for port private data in ssu100
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
+index 6e82d4f54bc8..2826f013752d 100644
+--- a/drivers/usb/serial/ssu100.c
++++ b/drivers/usb/serial/ssu100.c
+@@ -99,6 +99,7 @@ static struct usb_driver ssu100_driver = {
+ };
+ 
+ struct ssu100_port_private {
++	spinlock_t status_lock;
+ 	u8 shadowLSR;
+ 	u8 shadowMSR;
+ 	wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
+@@ -333,6 +334,7 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port)
+ 	struct ssu100_port_private *priv = usb_get_serial_port_data(port);
+ 	u8 *data;
+ 	int result;
++	unsigned long flags;
+ 
+ 	dbg("%s - port %d", __func__, port->number);
+ 
+@@ -350,11 +352,13 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port)
+ 		return result;
+ 	}
+ 
++	spin_lock_irqsave(&priv->status_lock, flags);
+ 	priv->shadowLSR = data[0]  & (SERIAL_LSR_OE | SERIAL_LSR_PE |
+ 				      SERIAL_LSR_FE | SERIAL_LSR_BI);
+ 
+ 	priv->shadowMSR = data[1]  & (SERIAL_MSR_CTS | SERIAL_MSR_DSR |
+ 				      SERIAL_MSR_RI | SERIAL_MSR_CD);
++	spin_unlock_irqrestore(&priv->status_lock, flags);
+ 
+ 	kfree(data);
+ 
+@@ -455,6 +459,7 @@ static void ssu100_set_max_packet_size(struct usb_serial_port *port)
+ 
+ 	unsigned num_endpoints;
+ 	int i;
++	unsigned long flags;
+ 
+ 	num_endpoints = interface->cur_altsetting->desc.bNumEndpoints;
+ 	dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints);
+@@ -466,7 +471,9 @@ static void ssu100_set_max_packet_size(struct usb_serial_port *port)
+ 	}
+ 
+ 	/* set max packet size based on descriptor */
++	spin_lock_irqsave(&priv->status_lock, flags);
+ 	priv->max_packet_size = ep_desc->wMaxPacketSize;
++	spin_unlock_irqrestore(&priv->status_lock, flags);
+ 
+ 	dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size);
+ }
+@@ -485,9 +492,9 @@ static int ssu100_attach(struct usb_serial *serial)
+ 		return -ENOMEM;
+ 	}
+ 
++	spin_lock_init(&priv->status_lock);
+ 	init_waitqueue_head(&priv->delta_msr_wait);
+ 	usb_set_serial_port_data(port, priv);
+-
+ 	ssu100_set_max_packet_size(port);
+ 
+ 	return ssu100_initdevice(serial->dev);

commit 52af954599396e5945a895035525c703f2761b20
+Author: Bill Pemberton 
+Date:   Thu Jul 29 11:05:41 2010 -0400
+
+    USB: add USB serial ssu100 driver
+    
+    Add support for the Quatech SSU-100 single port usb to serial device.
+    This driver is based on the ftdi_sio.c driver and the original
+    serqt_usb driver from Quatech.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
+index bd8aab0ef1cf..916b2b6d765f 100644
+--- a/drivers/usb/serial/Kconfig
++++ b/drivers/usb/serial/Kconfig
+@@ -642,6 +642,15 @@ config USB_SERIAL_ZIO
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called zio.
+ 
++config USB_SERIAL_SSU100
++	tristate "USB Quatech SSU-100 Single Port Serial Driver"
++	help
++	  Say Y here if you want to use the Quatech SSU-100 single
++	  port usb to serial adapter.
++
++	  To compile this driver as a module, choose M here: the
++	  module will be called ssu100.
++
+ config USB_SERIAL_DEBUG
+ 	tristate "USB Debugging Device"
+ 	help
+diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
+index e54c728c016e..40ebe17b6ea8 100644
+--- a/drivers/usb/serial/Makefile
++++ b/drivers/usb/serial/Makefile
+@@ -51,6 +51,7 @@ obj-$(CONFIG_USB_SERIAL_SAFE)			+= safe_serial.o
+ obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI)		+= siemens_mpi.o
+ obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS)		+= sierra.o
+ obj-$(CONFIG_USB_SERIAL_SPCP8X5)		+= spcp8x5.o
++obj-$(CONFIG_USB_SERIAL_SSU100)			+= ssu100.o
+ obj-$(CONFIG_USB_SERIAL_SYMBOL)			+= symbolserial.o
+ obj-$(CONFIG_USB_SERIAL_WWAN)			+= usb_wwan.o
+ obj-$(CONFIG_USB_SERIAL_TI)			+= ti_usb_3410_5052.o
+diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
+new file mode 100644
+index 000000000000..6e82d4f54bc8
+--- /dev/null
++++ b/drivers/usb/serial/ssu100.c
+@@ -0,0 +1,698 @@
++/*
++ * usb-serial driver for Quatech SSU-100
++ *
++ * based on ftdi_sio.c and the original serqt_usb.c from Quatech
++ *
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#define QT_OPEN_CLOSE_CHANNEL       0xca
++#define QT_SET_GET_DEVICE           0xc2
++#define QT_SET_GET_REGISTER         0xc0
++#define QT_GET_SET_PREBUF_TRIG_LVL  0xcc
++#define QT_SET_ATF                  0xcd
++#define QT_GET_SET_UART             0xc1
++#define QT_TRANSFER_IN              0xc0
++#define QT_HW_FLOW_CONTROL_MASK     0xc5
++#define QT_SW_FLOW_CONTROL_MASK     0xc6
++
++#define MODEM_CTL_REGISTER         0x04
++#define MODEM_STATUS_REGISTER      0x06
++
++
++#define SERIAL_LSR_OE       0x02
++#define SERIAL_LSR_PE       0x04
++#define SERIAL_LSR_FE       0x08
++#define SERIAL_LSR_BI       0x10
++
++#define SERIAL_LSR_TEMT     0x40
++
++#define  SERIAL_MCR_DTR             0x01
++#define  SERIAL_MCR_RTS             0x02
++#define  SERIAL_MCR_LOOP            0x10
++
++#define  SERIAL_MSR_CTS             0x10
++#define  SERIAL_MSR_CD              0x80
++#define  SERIAL_MSR_RI              0x40
++#define  SERIAL_MSR_DSR             0x20
++#define  SERIAL_MSR_MASK            0xf0
++
++#define  SERIAL_CRTSCTS ((SERIAL_MCR_RTS << 8) | SERIAL_MSR_CTS)
++
++#define  SERIAL_8_DATA              0x03
++#define  SERIAL_7_DATA              0x02
++#define  SERIAL_6_DATA              0x01
++#define  SERIAL_5_DATA              0x00
++
++#define  SERIAL_ODD_PARITY          0X08
++#define  SERIAL_EVEN_PARITY         0X18
++
++#define  MAX_BAUD_RATE              460800
++
++#define ATC_DISABLED                0x00
++#define DUPMODE_BITS        0xc0
++#define RR_BITS             0x03
++#define LOOPMODE_BITS       0x41
++#define RS232_MODE          0x00
++#define RTSCTS_TO_CONNECTOR 0x40
++#define CLKS_X4             0x02
++#define FULLPWRBIT          0x00000080
++#define NEXT_BOARD_POWER_BIT        0x00000004
++
++static int debug = 1;
++
++/* Version Information */
++#define DRIVER_VERSION "v0.1"
++#define DRIVER_DESC "Quatech SSU-100 USB to Serial Driver"
++
++#define	USB_VENDOR_ID_QUATECH	0x061d	/* Quatech VID */
++#define QUATECH_SSU100	0xC020	/* SSU100 */
++
++static const struct usb_device_id id_table[] = {
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU100)},
++	{}			/* Terminating entry */
++};
++
++MODULE_DEVICE_TABLE(usb, id_table);
++
++
++static struct usb_driver ssu100_driver = {
++	.name			       = "ssu100",
++	.probe			       = usb_serial_probe,
++	.disconnect		       = usb_serial_disconnect,
++	.id_table		       = id_table,
++	.suspend		       = usb_serial_suspend,
++	.resume			       = usb_serial_resume,
++	.no_dynamic_id		       = 1,
++	.supports_autosuspend	       = 1,
++};
++
++struct ssu100_port_private {
++	u8 shadowLSR;
++	u8 shadowMSR;
++	wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
++	unsigned short max_packet_size;
++};
++
++static void ssu100_release(struct usb_serial *serial)
++{
++	struct ssu100_port_private *priv = usb_get_serial_port_data(*serial->port);
++
++	dbg("%s", __func__);
++	kfree(priv);
++}
++
++static inline int ssu100_control_msg(struct usb_device *dev,
++				     u8 request, u16 data, u16 index)
++{
++	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
++			       request, 0x40, data, index,
++			       NULL, 0, 300);
++}
++
++static inline int ssu100_setdevice(struct usb_device *dev, u8 *data)
++{
++	u16 x = ((u16)(data[1] << 8) | (u16)(data[0]));
++
++	return ssu100_control_msg(dev, QT_SET_GET_DEVICE, x, 0);
++}
++
++
++static inline int ssu100_getdevice(struct usb_device *dev, u8 *data)
++{
++	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
++			       QT_SET_GET_DEVICE, 0xc0, 0, 0,
++			       data, 3, 300);
++}
++
++static inline int ssu100_getregister(struct usb_device *dev,
++				     unsigned short uart,
++				     unsigned short reg,
++				     u8 *data)
++{
++	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
++			       QT_SET_GET_REGISTER, 0xc0, reg,
++			       uart, data, sizeof(*data), 300);
++
++}
++
++
++static inline int ssu100_setregister(struct usb_device *dev,
++				     unsigned short uart,
++				     u16 data)
++{
++	u16 value = (data << 8) | MODEM_CTL_REGISTER;
++
++	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
++			       QT_SET_GET_REGISTER, 0x40, value, uart,
++			       NULL, 0, 300);
++
++}
++
++#define set_mctrl(dev, set)		update_mctrl((dev), (set), 0)
++#define clear_mctrl(dev, clear)	update_mctrl((dev), 0, (clear))
++
++/* these do not deal with device that have more than 1 port */
++static inline int update_mctrl(struct usb_device *dev, unsigned int set,
++			       unsigned int clear)
++{
++	unsigned urb_value;
++	int result;
++
++	if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) {
++		dbg("%s - DTR|RTS not being set|cleared", __func__);
++		return 0;	/* no change */
++	}
++
++	clear &= ~set;	/* 'set' takes precedence over 'clear' */
++	urb_value = 0;
++	if (set & TIOCM_DTR)
++		urb_value |= SERIAL_MCR_DTR;
++	if (set & TIOCM_RTS)
++		urb_value |= SERIAL_MCR_RTS;
++
++	result = ssu100_setregister(dev, 0, urb_value);
++	if (result < 0)
++		dbg("%s Error from MODEM_CTRL urb", __func__);
++
++	return result;
++}
++
++static int ssu100_initdevice(struct usb_device *dev)
++{
++	u8 *data;
++	int result = 0;
++
++	dbg("%s", __func__);
++
++	data = kzalloc(3, GFP_KERNEL);
++	if (!data)
++		return -ENOMEM;
++
++	result = ssu100_getdevice(dev, data);
++	if (result < 0) {
++		dbg("%s - get_device failed %i", __func__, result);
++		goto out;
++	}
++
++	data[1] &= ~FULLPWRBIT;
++
++	result = ssu100_setdevice(dev, data);
++	if (result < 0) {
++		dbg("%s - setdevice failed %i", __func__, result);
++		goto out;
++	}
++
++	result = ssu100_control_msg(dev, QT_GET_SET_PREBUF_TRIG_LVL, 128, 0);
++	if (result < 0) {
++		dbg("%s - set prebuffer level failed %i", __func__, result);
++		goto out;
++	}
++
++	result = ssu100_control_msg(dev, QT_SET_ATF, ATC_DISABLED, 0);
++	if (result < 0) {
++		dbg("%s - set ATFprebuffer level failed %i", __func__, result);
++		goto out;
++	}
++
++	result = ssu100_getdevice(dev, data);
++	if (result < 0) {
++		dbg("%s - get_device failed %i", __func__, result);
++		goto out;
++	}
++
++	data[0] &= ~(RR_BITS | DUPMODE_BITS);
++	data[0] |= CLKS_X4;
++	data[1] &= ~(LOOPMODE_BITS);
++	data[1] |= RS232_MODE;
++
++	result = ssu100_setdevice(dev, data);
++	if (result < 0) {
++		dbg("%s - setdevice failed %i", __func__, result);
++		goto out;
++	}
++
++out:	kfree(data);
++	return result;
++
++}
++
++
++static void ssu100_set_termios(struct tty_struct *tty,
++			       struct usb_serial_port *port,
++			       struct ktermios *old_termios)
++{
++	struct usb_device *dev = port->serial->dev;
++	struct ktermios *termios = tty->termios;
++	u16 baud, divisor, remainder;
++	unsigned int cflag = termios->c_cflag;
++	u16 urb_value = 0; /* will hold the new flags */
++	int result;
++
++	dbg("%s", __func__);
++
++	if (cflag & PARENB) {
++		if (cflag & PARODD)
++			urb_value |= SERIAL_ODD_PARITY;
++		else
++			urb_value |= SERIAL_EVEN_PARITY;
++	}
++
++	switch (cflag & CSIZE) {
++	case CS5:
++		urb_value |= SERIAL_5_DATA;
++		break;
++	case CS6:
++		urb_value |= SERIAL_6_DATA;
++		break;
++	case CS7:
++		urb_value |= SERIAL_7_DATA;
++		break;
++	default:
++	case CS8:
++		urb_value |= SERIAL_8_DATA;
++		break;
++	}
++
++	baud = tty_get_baud_rate(tty);
++	if (!baud)
++		baud = 9600;
++
++	dbg("%s - got baud = %d\n", __func__, baud);
++
++
++	divisor = MAX_BAUD_RATE / baud;
++	remainder = MAX_BAUD_RATE % baud;
++	if (((remainder * 2) >= baud) && (baud != 110))
++		divisor++;
++
++	urb_value = urb_value << 8;
++
++	result = ssu100_control_msg(dev, QT_GET_SET_UART, divisor, urb_value);
++	if (result < 0)
++		dbg("%s - set uart failed", __func__);
++
++	if (cflag & CRTSCTS)
++		result = ssu100_control_msg(dev, QT_HW_FLOW_CONTROL_MASK,
++					    SERIAL_CRTSCTS, 0);
++	else
++		result = ssu100_control_msg(dev, QT_HW_FLOW_CONTROL_MASK,
++					    0, 0);
++	if (result < 0)
++		dbg("%s - set HW flow control failed", __func__);
++
++	if (I_IXOFF(tty) || I_IXON(tty)) {
++		u16 x = ((u16)(START_CHAR(tty) << 8) | (u16)(STOP_CHAR(tty)));
++
++		result = ssu100_control_msg(dev, QT_SW_FLOW_CONTROL_MASK,
++					    x, 0);
++	} else
++		result = ssu100_control_msg(dev, QT_SW_FLOW_CONTROL_MASK,
++					    0, 0);
++
++	if (result < 0)
++		dbg("%s - set SW flow control failed", __func__);
++
++}
++
++
++static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port)
++{
++	struct usb_device *dev = port->serial->dev;
++	struct ssu100_port_private *priv = usb_get_serial_port_data(port);
++	u8 *data;
++	int result;
++
++	dbg("%s - port %d", __func__, port->number);
++
++	data = kzalloc(2, GFP_KERNEL);
++	if (!data)
++		return -ENOMEM;
++
++	result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
++				 QT_OPEN_CLOSE_CHANNEL,
++				 QT_TRANSFER_IN, 0x01,
++				 0, data, 2, 300);
++	if (result < 0) {
++		dbg("%s - open failed %i", __func__, result);
++		kfree(data);
++		return result;
++	}
++
++	priv->shadowLSR = data[0]  & (SERIAL_LSR_OE | SERIAL_LSR_PE |
++				      SERIAL_LSR_FE | SERIAL_LSR_BI);
++
++	priv->shadowMSR = data[1]  & (SERIAL_MSR_CTS | SERIAL_MSR_DSR |
++				      SERIAL_MSR_RI | SERIAL_MSR_CD);
++
++	kfree(data);
++
++/* set to 9600 */
++	result = ssu100_control_msg(dev, QT_GET_SET_UART, 0x30, 0x0300);
++	if (result < 0)
++		dbg("%s - set uart failed", __func__);
++
++	if (tty)
++		ssu100_set_termios(tty, port, tty->termios);
++
++	return usb_serial_generic_open(tty, port);
++}
++
++static void ssu100_close(struct usb_serial_port *port)
++{
++	dbg("%s", __func__);
++	usb_serial_generic_close(port);
++}
++
++static int get_serial_info(struct usb_serial_port *port,
++			   struct serial_struct __user *retinfo)
++{
++	struct serial_struct tmp;
++
++	if (!retinfo)
++		return -EFAULT;
++
++	memset(&tmp, 0, sizeof(tmp));
++	tmp.line		= port->serial->minor;
++	tmp.port		= 0;
++	tmp.irq			= 0;
++	tmp.flags		= ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
++	tmp.xmit_fifo_size	= port->bulk_out_size;
++	tmp.baud_base		= 9600;
++	tmp.close_delay		= 5*HZ;
++	tmp.closing_wait	= 30*HZ;
++
++	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
++		return -EFAULT;
++	return 0;
++}
++
++static int ssu100_ioctl(struct tty_struct *tty, struct file *file,
++		    unsigned int cmd, unsigned long arg)
++{
++	struct usb_serial_port *port = tty->driver_data;
++	struct ssu100_port_private *priv = usb_get_serial_port_data(port);
++
++	dbg("%s cmd 0x%04x", __func__, cmd);
++
++	switch (cmd) {
++	case TIOCGSERIAL:
++		return get_serial_info(port,
++				       (struct serial_struct __user *) arg);
++
++	case TIOCMIWAIT:
++		while (priv != NULL) {
++			u8 prevMSR = priv->shadowMSR & SERIAL_MSR_MASK;
++			interruptible_sleep_on(&priv->delta_msr_wait);
++			/* see if a signal did it */
++			if (signal_pending(current))
++				return -ERESTARTSYS;
++			else {
++				u8 diff = (priv->shadowMSR & SERIAL_MSR_MASK) ^ prevMSR;
++				if (!diff)
++					return -EIO; /* no change => error */
++
++				/* Return 0 if caller wanted to know about
++				   these bits */
++
++				if (((arg & TIOCM_RNG) && (diff & SERIAL_MSR_RI)) ||
++				    ((arg & TIOCM_DSR) && (diff & SERIAL_MSR_DSR)) ||
++				    ((arg & TIOCM_CD) && (diff & SERIAL_MSR_CD)) ||
++				    ((arg & TIOCM_CTS) && (diff & SERIAL_MSR_CTS)))
++					return 0;
++			}
++		}
++		return 0;
++
++	default:
++		break;
++	}
++
++	dbg("%s arg not supported", __func__);
++
++	return -ENOIOCTLCMD;
++}
++
++static void ssu100_set_max_packet_size(struct usb_serial_port *port)
++{
++	struct ssu100_port_private *priv = usb_get_serial_port_data(port);
++	struct usb_serial *serial = port->serial;
++	struct usb_device *udev = serial->dev;
++
++	struct usb_interface *interface = serial->interface;
++	struct usb_endpoint_descriptor *ep_desc = &interface->cur_altsetting->endpoint[1].desc;
++
++	unsigned num_endpoints;
++	int i;
++
++	num_endpoints = interface->cur_altsetting->desc.bNumEndpoints;
++	dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints);
++
++	for (i = 0; i < num_endpoints; i++) {
++		dev_info(&udev->dev, "Endpoint %d MaxPacketSize %d\n", i+1,
++			interface->cur_altsetting->endpoint[i].desc.wMaxPacketSize);
++		ep_desc = &interface->cur_altsetting->endpoint[i].desc;
++	}
++
++	/* set max packet size based on descriptor */
++	priv->max_packet_size = ep_desc->wMaxPacketSize;
++
++	dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size);
++}
++
++static int ssu100_attach(struct usb_serial *serial)
++{
++	struct ssu100_port_private *priv;
++	struct usb_serial_port *port = *serial->port;
++
++	dbg("%s", __func__);
++
++	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
++	if (!priv) {
++		dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__,
++			sizeof(*priv));
++		return -ENOMEM;
++	}
++
++	init_waitqueue_head(&priv->delta_msr_wait);
++	usb_set_serial_port_data(port, priv);
++
++	ssu100_set_max_packet_size(port);
++
++	return ssu100_initdevice(serial->dev);
++}
++
++static int ssu100_tiocmget(struct tty_struct *tty, struct file *file)
++{
++	struct usb_serial_port *port = tty->driver_data;
++	struct usb_device *dev = port->serial->dev;
++	u8 *d;
++	int r;
++
++	dbg("%s\n", __func__);
++
++	d = kzalloc(2, GFP_KERNEL);
++	if (!d)
++		return -ENOMEM;
++
++	r = ssu100_getregister(dev, 0, MODEM_CTL_REGISTER, d);
++	if (r < 0)
++		goto mget_out;
++
++	r = ssu100_getregister(dev, 0, MODEM_STATUS_REGISTER, d+1);
++	if (r < 0)
++		goto mget_out;
++
++	r = (d[0] & SERIAL_MCR_DTR ? TIOCM_DTR : 0) |
++		(d[0] & SERIAL_MCR_RTS ? TIOCM_RTS : 0) |
++		(d[1] & SERIAL_MSR_CTS ? TIOCM_CTS : 0) |
++		(d[1] & SERIAL_MSR_CD ? TIOCM_CAR : 0) |
++		(d[1] & SERIAL_MSR_RI ? TIOCM_RI : 0) |
++		(d[1] & SERIAL_MSR_DSR ? TIOCM_DSR : 0);
++
++mget_out:
++	kfree(d);
++	return r;
++}
++
++static int ssu100_tiocmset(struct tty_struct *tty, struct file *file,
++			   unsigned int set, unsigned int clear)
++{
++	struct usb_serial_port *port = tty->driver_data;
++	struct usb_device *dev = port->serial->dev;
++
++	dbg("%s\n", __func__);
++	return update_mctrl(dev, set, clear);
++}
++
++static void ssu100_dtr_rts(struct usb_serial_port *port, int on)
++{
++	struct usb_device *dev = port->serial->dev;
++
++	dbg("%s\n", __func__);
++
++	mutex_lock(&port->serial->disc_mutex);
++	if (!port->serial->disconnected) {
++		/* Disable flow control */
++		if (!on &&
++		    ssu100_setregister(dev, 0, 0) < 0)
++			dev_err(&port->dev, "error from flowcontrol urb\n");
++		/* drop RTS and DTR */
++		if (on)
++			set_mctrl(dev, TIOCM_DTR | TIOCM_RTS);
++		else
++			clear_mctrl(dev, TIOCM_DTR | TIOCM_RTS);
++	}
++	mutex_unlock(&port->serial->disc_mutex);
++}
++
++static int ssu100_process_packet(struct tty_struct *tty,
++				 struct usb_serial_port *port,
++				 struct ssu100_port_private *priv,
++				 char *packet, int len)
++{
++	int i;
++	char flag;
++	char *ch;
++
++	dbg("%s - port %d", __func__, port->number);
++
++	if (len < 4) {
++		dbg("%s - malformed packet", __func__);
++		return 0;
++	}
++
++	if ((packet[0] == 0x1b) && (packet[1] == 0x1b) &&
++	    ((packet[2] == 0x00) || (packet[2] == 0x01))) {
++		if (packet[2] == 0x00)
++			priv->shadowLSR = packet[3] & (SERIAL_LSR_OE |
++						       SERIAL_LSR_PE |
++						       SERIAL_LSR_FE |
++						       SERIAL_LSR_BI);
++
++		if (packet[2] == 0x01) {
++			priv->shadowMSR = packet[3];
++			wake_up_interruptible(&priv->delta_msr_wait);
++		}
++
++		len -= 4;
++		ch = packet + 4;
++	} else
++		ch = packet;
++
++	if (!len)
++		return 0;	/* status only */
++
++	if (port->port.console && port->sysrq) {
++		for (i = 0; i < len; i++, ch++) {
++			if (!usb_serial_handle_sysrq_char(tty, port, *ch))
++				tty_insert_flip_char(tty, *ch, flag);
++		}
++	} else
++		tty_insert_flip_string_fixed_flag(tty, ch, flag, len);
++
++	return len;
++}
++
++static void ssu100_process_read_urb(struct urb *urb)
++{
++	struct usb_serial_port *port = urb->context;
++	struct ssu100_port_private *priv = usb_get_serial_port_data(port);
++	char *data = (char *)urb->transfer_buffer;
++	struct tty_struct *tty;
++	int count = 0;
++	int i;
++	int len;
++
++	dbg("%s", __func__);
++
++	tty = tty_port_tty_get(&port->port);
++	if (!tty)
++		return;
++
++	for (i = 0; i < urb->actual_length; i += priv->max_packet_size) {
++		len = min_t(int, urb->actual_length - i, priv->max_packet_size);
++		count += ssu100_process_packet(tty, port, priv, &data[i], len);
++	}
++
++	if (count)
++		tty_flip_buffer_push(tty);
++	tty_kref_put(tty);
++}
++
++
++static struct usb_serial_driver ssu100_device = {
++	.driver = {
++		.owner = THIS_MODULE,
++		.name = "ssu100",
++	},
++	.description	     = DRIVER_DESC,
++	.id_table	     = id_table,
++	.usb_driver	     = &ssu100_driver,
++	.num_ports	     = 1,
++	.bulk_in_size        = 256,
++	.bulk_out_size       = 256,
++	.open		     = ssu100_open,
++	.close		     = ssu100_close,
++	.attach              = ssu100_attach,
++	.release             = ssu100_release,
++	.dtr_rts             = ssu100_dtr_rts,
++	.process_read_urb    = ssu100_process_read_urb,
++	.tiocmget            = ssu100_tiocmget,
++	.tiocmset            = ssu100_tiocmset,
++	.ioctl               = ssu100_ioctl,
++	.set_termios         = ssu100_set_termios,
++};
++
++static int __init ssu100_init(void)
++{
++	int retval;
++
++	dbg("%s", __func__);
++
++	/* register with usb-serial */
++	retval = usb_serial_register(&ssu100_device);
++
++	if (retval)
++		goto failed_usb_sio_register;
++
++	retval = usb_register(&ssu100_driver);
++	if (retval)
++		goto failed_usb_register;
++
++	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++	       DRIVER_DESC "\n");
++
++	return 0;
++
++failed_usb_register:
++	usb_serial_deregister(&ssu100_device);
++failed_usb_sio_register:
++	return retval;
++}
++
++static void __exit ssu100_exit(void)
++{
++	usb_deregister(&ssu100_driver);
++	usb_serial_deregister(&ssu100_device);
++}
++
++module_init(ssu100_init);
++module_exit(ssu100_exit);
++
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_LICENSE("GPL");
++
++module_param(debug, bool, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(debug, "Debug enabled or not");

commit ffc18879903e55487bc5ac3c774b99a07de06029
+Author: Bill Pemberton 
+Date:   Tue Aug 3 15:19:30 2010 -0400
+
+    omfs: fix uninitialized variable warning
+    
+    quiet the warning:
+    fs/omfs/file.c: In function 'omfs_get_block':
+    fs/omfs/file.c:225: warning: 'new_block' may be used uninitialized in
+    this function
+    
+    new_block is used properly by the call to omfs_grow_extent()
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Bob Copeland 
+
+diff --git a/fs/omfs/file.c b/fs/omfs/file.c
+index 76bc21b91a8a..d821d468e5a2 100644
+--- a/fs/omfs/file.c
++++ b/fs/omfs/file.c
+@@ -222,7 +222,7 @@ static int omfs_get_block(struct inode *inode, sector_t block,
+ 	struct buffer_head *bh;
+ 	sector_t next, offset;
+ 	int ret;
+-	u64 new_block;
++	u64 uninitialized_var(new_block);
+ 	u32 max_extents;
+ 	int extent_count;
+ 	struct omfs_extent *oe;

commit 6e5db771e10fccde1e48bf665dc900372826bc38
+Author: Bill Pemberton 
+Date:   Thu Jun 17 13:10:57 2010 -0400
+
+    Staging: xgifb: increase VBIOS_VER_MAX_LENGTH to 5
+    
+    VBIOS_VER_MAX_LENGTH was set to 4, but the value "0.84" is strcpy'd
+    into it.  That value is 5 long including the trailing NULL.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Arnaud Patard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h
+index 8702a7a78996..df839eeb5efd 100644
+--- a/drivers/staging/xgifb/vgatypes.h
++++ b/drivers/staging/xgifb/vgatypes.h
+@@ -5,7 +5,7 @@
+ #include 
+ 
+ #ifndef VBIOS_VER_MAX_LENGTH
+-#define VBIOS_VER_MAX_LENGTH    4
++#define VBIOS_VER_MAX_LENGTH    5
+ #endif
+ 
+ #ifndef XGI_VB_CHIP_TYPE

commit 6eed8dc793c3122471c8dc9a12e331386b783141
+Author: Bill Pemberton 
+Date:   Thu Jun 17 13:10:56 2010 -0400
+
+    Staging: xgifb: remove externs in XGI_accel.c
+    
+    Remove 2 extern variables definations from XGI_accel.c that were
+    defined in other .h files.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Arnaud Patard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/XGI_accel.c b/drivers/staging/xgifb/XGI_accel.c
+index feda029fa82a..79549742cff1 100644
+--- a/drivers/staging/xgifb/XGI_accel.c
++++ b/drivers/staging/xgifb/XGI_accel.c
+@@ -48,10 +48,6 @@
+ #include "XGIfb.h"
+ #include "XGI_accel.h"
+ 
+-
+-extern struct     video_info xgi_video_info;
+-extern int XGIfb_accel;
+-
+ static const int XGIALUConv[] =
+ {
+     0x00,       /* dest = 0;            0,      GXclear,        0 */

commit a9253883a6d34fd5087ebc461e862613f38d72ec
+Author: Bill Pemberton 
+Date:   Thu Jun 17 13:10:55 2010 -0400
+
+    Staging: xgifb: remove __KERNEL__ #ifdef in XGIfb.h
+    
+    The code inside this #ifdef declared a couple extern functions that
+    weren't used anywhere, so remove the whole #ifdef
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Arnaud Patard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/XGIfb.h b/drivers/staging/xgifb/XGIfb.h
+index 4c29cf043741..ef86a64d6996 100644
+--- a/drivers/staging/xgifb/XGIfb.h
++++ b/drivers/staging/xgifb/XGIfb.h
+@@ -205,9 +205,4 @@ struct video_info{
+ 
+ extern struct video_info xgi_video_info;
+ 
+-#ifdef __KERNEL__
+-//extern void xgi_malloc(struct xgi_memreq *req);
+-extern void xgi_free(unsigned long base);
+-extern void xgi_dispinfo(struct ap_data *rec);
+-#endif
+ #endif

commit b06bce772768640039bd0eea51c52935f8bc701a
+Author: Bill Pemberton 
+Date:   Thu Jun 17 13:10:54 2010 -0400
+
+    Staging: xgifb: remove XGI.h
+    
+    This was not included anywhere and just defined a debugging macro.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Arnaud Patard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/XGI.h b/drivers/staging/xgifb/XGI.h
+deleted file mode 100644
+index 87803dd032de..000000000000
+--- a/drivers/staging/xgifb/XGI.h
++++ /dev/null
+@@ -1,10 +0,0 @@
+-#ifndef _XGI_H
+-#define _XGI_H
+-
+-#if 1
+-#define TWDEBUG(x)
+-#else
+-#define TWDEBUG(x) printk(KERN_INFO x "\n");
+-#endif
+-
+-#endif

commit a3e735a5a2fcf40819f26411e2605fde2064d6ca
+Author: Bill Pemberton 
+Date:   Thu Jun 17 13:10:53 2010 -0400
+
+    Staging: xgifb: Remove XGI_TV_PLUG typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Arnaud Patard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/XGIfb.h b/drivers/staging/xgifb/XGIfb.h
+index 46954d7de328..4c29cf043741 100644
+--- a/drivers/staging/xgifb/XGIfb.h
++++ b/drivers/staging/xgifb/XGIfb.h
+@@ -95,7 +95,7 @@ struct XGIfb_info {
+ 
+ 
+ 
+-typedef enum _TVPLUGTYPE {	// vicki@030226
++enum xgi_tv_plug {	/* vicki@030226 */
+ //	TVPLUG_Legacy = 0,
+ //	TVPLUG_COMPOSITE,
+ //	TVPLUG_SVIDEO,
+@@ -111,7 +111,7 @@ typedef enum _TVPLUGTYPE {	// vicki@030226
+     	TVPLUG_YPBPR_750P = 7,
+     	TVPLUG_YPBPR_1080i = 8,
+ 	TVPLUG_TOTAL
+-} XGI_TV_PLUG;
++};
+ 
+ 
+ struct mode_info {
+@@ -133,7 +133,7 @@ struct ap_data {
+ 	enum XGI_CHIP_TYPE chip;
+ 	unsigned char hasVB;
+ 	enum xgi_tvtype TV_type;
+-	XGI_TV_PLUG TV_plug;
++	enum xgi_tv_plug TV_plug;
+ 	unsigned long version;
+ 	char reserved[256];
+ };

commit 716083c63bf31649e08df25a4f4548689451330d
+Author: Bill Pemberton 
+Date:   Thu Jun 17 13:10:52 2010 -0400
+
+    Staging: xgifb: Remove typedefs in XGIfb.h
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Arnaud Patard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
+index 67d3874fb73d..976c39bb2866 100644
+--- a/drivers/staging/xgifb/XGI_main_26.c
++++ b/drivers/staging/xgifb/XGI_main_26.c
+@@ -1615,7 +1615,7 @@ static int XGIfb_ioctl(struct fb_info *info, unsigned int cmd,
+ 		break;
+ 	   case XGIFB_GET_INFO:  /* TW: New for communication with X driver */
+ 	        {
+-			XGIfb_info *x = (XGIfb_info *)arg;
++			struct XGIfb_info *x = (struct XGIfb_info *)arg;
+ 
+ 			//x->XGIfb_id = XGIFB_ID;
+ 			x->XGIfb_version = VER_MAJOR;
+diff --git a/drivers/staging/xgifb/XGIfb.h b/drivers/staging/xgifb/XGIfb.h
+index 41bf163d4e6b..46954d7de328 100644
+--- a/drivers/staging/xgifb/XGIfb.h
++++ b/drivers/staging/xgifb/XGIfb.h
+@@ -27,7 +27,7 @@
+ #define XGIFB_ID          0x53495346    /* Identify myself with 'XGIF' */
+ #endif
+ 
+-typedef enum _XGI_CHIP_TYPE {
++enum XGI_CHIP_TYPE {
+     XGI_VGALegacy = 0,
+     XGI_300,
+     XGI_630,
+@@ -53,9 +53,9 @@ typedef enum _XGI_CHIP_TYPE {
+     XG21,
+     XG27,
+     MAX_XGI_CHIP
+-} XGI_CHIP_TYPE;
++};
+ 
+-typedef enum _TVTYPE {
++enum xgi_tvtype {
+ 	TVMODE_NTSC = 0,
+ 	TVMODE_PAL,
+ 	TVMODE_HIVISION,
+@@ -63,13 +63,11 @@ typedef enum _TVTYPE {
+     	TVTYPE_PALN,	// vicki@030226
+     	TVTYPE_NTSCJ,	// vicki@030226
+ 	TVMODE_TOTAL
+-} XGI_TV_TYPE;
+-
++};
+ 
+-typedef struct _XGIFB_INFO XGIfb_info;
+-struct _XGIFB_INFO {
+ 
+-unsigned long XGIfb_id;
++struct XGIfb_info {
++	unsigned long XGIfb_id;
+  	int    chip_id;			/* PCI ID of detected chip */
+ 	int    memory;			/* video memory in KB which XGIfb manages */
+ 	int    heapstart;               /* heap start (= XGIfb "mem" argument) in KB */
+@@ -132,9 +130,9 @@ struct ap_data {
+ 	unsigned long iobase;
+ 	unsigned int  mem_size;
+ 	unsigned long disp_state;
+-	XGI_CHIP_TYPE chip;
++	enum XGI_CHIP_TYPE chip;
+ 	unsigned char hasVB;
+-	XGI_TV_TYPE TV_type;
++	enum xgi_tvtype TV_type;
+ 	XGI_TV_PLUG TV_plug;
+ 	unsigned long version;
+ 	char reserved[256];
+@@ -184,7 +182,7 @@ struct video_info{
+         unsigned char TV_type;
+         unsigned char TV_plug;
+ 
+-        XGI_CHIP_TYPE chip;
++	enum XGI_CHIP_TYPE chip;
+         unsigned char revision_id;
+ 
+         unsigned short DstColor;

commit 80adad85ea26ace7c39c3aba9c23527f9e9e14da
+Author: Bill Pemberton 
+Date:   Thu Jun 17 13:10:51 2010 -0400
+
+    Staging: xgifb: Remove typedefs in vb_struct.h
+    
+    This removes all the remaining typedefs in vb_struct.h
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Arnaud Patard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/XGI_main.h b/drivers/staging/xgifb/XGI_main.h
+index b628582fd0cc..fd1152eb2c92 100644
+--- a/drivers/staging/xgifb/XGI_main.h
++++ b/drivers/staging/xgifb/XGI_main.h
+@@ -376,7 +376,7 @@ unsigned char XGIfb_detectedlcda = 0xff;
+ struct xgi_hw_device_info XGIhw_ext;
+ 
+ /* TW: XGI private structure */
+-VB_DEVICE_INFO  XGI_Pr;
++struct vb_device_info  XGI_Pr;
+ 
+ /* card parameters */
+ static unsigned long XGIfb_mmio_size = 0;
+@@ -820,7 +820,7 @@ extern int      XGIfb_mode_rate_to_ddata(VB_DEVICE_INFO *XGI_Pr, struct xgi_hw_d
+ */
+ extern unsigned char XGI_SearchModeID(unsigned short ModeNo,
+ 				unsigned short *ModeIdIndex,
+-				PVB_DEVICE_INFO);
++				struct vb_device_info *);
+ static int      XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
+ 			      struct fb_info *info);
+ 
+@@ -887,31 +887,31 @@ unsigned char XGIfb_query_VGA_config_space(struct xgi_hw_device_info *pXGIhw_ext
+ 
+ 
+ /* Routines from init.c/init301.c */
+-extern void     InitTo330Pointer(unsigned char, PVB_DEVICE_INFO pVBInfo);
++extern void     InitTo330Pointer(unsigned char, struct vb_device_info *pVBInfo);
+ extern unsigned char  XGIInitNew(struct xgi_hw_device_info *HwDeviceExtension);
+ extern unsigned char XGISetModeNew(struct xgi_hw_device_info *HwDeviceExtension,
+ 				   unsigned short ModeNo);
+ //extern void     XGI_SetEnableDstn(VB_DEVICE_INFO *XGI_Pr);
+-extern void     XGI_LongWait(VB_DEVICE_INFO *XGI_Pr);
++extern void     XGI_LongWait(struct vb_device_info *XGI_Pr);
+ extern unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
+ 					 unsigned short ModeNo,
+ 					 unsigned short ModeIdIndex,
+-					 PVB_DEVICE_INFO pVBInfo);
++					 struct vb_device_info *pVBInfo);
+ /* TW: Chrontel TV functions */
+-extern unsigned short XGI_GetCH700x(VB_DEVICE_INFO *XGI_Pr,
++extern unsigned short XGI_GetCH700x(struct vb_device_info *XGI_Pr,
+ 				    unsigned short tempbx);
+-extern void XGI_SetCH700x(VB_DEVICE_INFO *XGI_Pr, unsigned short tempbx);
+-extern unsigned short XGI_GetCH701x(VB_DEVICE_INFO *XGI_Pr,
++extern void XGI_SetCH700x(struct vb_device_info *XGI_Pr, unsigned short tempbx);
++extern unsigned short XGI_GetCH701x(struct vb_device_info *XGI_Pr,
+ 				    unsigned short tempbx);
+-extern void XGI_SetCH701x(VB_DEVICE_INFO *XGI_Pr, unsigned short tempbx);
+-extern void XGI_SetCH70xxANDOR(VB_DEVICE_INFO *XGI_Pr,
++extern void XGI_SetCH701x(struct vb_device_info *XGI_Pr, unsigned short tempbx);
++extern void XGI_SetCH70xxANDOR(struct vb_device_info *XGI_Pr,
+ 			       unsigned short tempax,
+ 			       unsigned short tempbh);
+-extern void XGI_DDC2Delay(VB_DEVICE_INFO *XGI_Pr, unsigned short delaytime);
++extern void XGI_DDC2Delay(struct vb_device_info *XGI_Pr, unsigned short delaytime);
+ 
+ /* TW: Sensing routines */
+ void            XGI_Sense30x(void);
+ int             XGIDoSense(int tempbl, int tempbh, int tempcl, int tempch);
+ 
+-extern XGI21_LVDSCapStruct XGI21_LCDCapList[13];
++extern struct XGI21_LVDSCapStruct XGI21_LCDCapList[13];
+ #endif
+diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
+index b3454a9e992b..67d3874fb73d 100644
+--- a/drivers/staging/xgifb/XGI_main_26.c
++++ b/drivers/staging/xgifb/XGI_main_26.c
+@@ -162,7 +162,7 @@ struct video_info  xgi_video_info;
+ /* --------------- Hardware Access Routines -------------------------- */
+ 
+ int
+-XGIfb_mode_rate_to_dclock(VB_DEVICE_INFO *XGI_Pr, struct xgi_hw_device_info *HwDeviceExtension,
++XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr, struct xgi_hw_device_info *HwDeviceExtension,
+ 			  unsigned char modeno, unsigned char rateindex)
+ {
+     unsigned short ModeNo = modeno;
+@@ -197,7 +197,7 @@ XGIfb_mode_rate_to_dclock(VB_DEVICE_INFO *XGI_Pr, struct xgi_hw_device_info *HwD
+ }
+ 
+ int
+-XGIfb_mode_rate_to_ddata(VB_DEVICE_INFO *XGI_Pr, struct xgi_hw_device_info *HwDeviceExtension,
++XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr, struct xgi_hw_device_info *HwDeviceExtension,
+ 			 unsigned char modeno, unsigned char rateindex,
+ 			 u32 *left_margin, u32 *right_margin,
+ 			 u32 *upper_margin, u32 *lower_margin,
+@@ -377,7 +377,7 @@ XGIfb_mode_rate_to_ddata(VB_DEVICE_INFO *XGI_Pr, struct xgi_hw_device_info *HwDe
+ 
+ 
+ 
+-void XGIRegInit(VB_DEVICE_INFO *XGI_Pr, unsigned long BaseAddr)
++void XGIRegInit(struct vb_device_info *XGI_Pr, unsigned long BaseAddr)
+ {
+    XGI_Pr->RelIO = BaseAddr;
+    XGI_Pr->P3c4 = BaseAddr + 0x14;
+@@ -610,7 +610,8 @@ int XGIfb_GetXG21LVDSData(void)
+                 i += 25;
+                 j--;
+                 k++;
+-        } while ( (j>0) && ( k < (sizeof(XGI21_LCDCapList)/sizeof(XGI21_LVDSCapStruct)) ) );
++	} while ((j > 0) &&
++		 (k < (sizeof(XGI21_LCDCapList)/sizeof(struct XGI21_LVDSCapStruct))));
+         return 1;
+     }
+     return 0;
+@@ -3132,7 +3133,7 @@ int __devinit xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 		    xgi_video_info.disp_state = DISPTYPE_LCD;
+         	    if (!XGIfb_GetXG21LVDSData()) {
+ 			    int m;
+-			    for (m=0; m < sizeof(XGI21_LCDCapList)/sizeof(XGI21_LVDSCapStruct); m++) {
++			    for (m = 0; m < sizeof(XGI21_LCDCapList)/sizeof(struct XGI21_LVDSCapStruct); m++) {
+ 				    if ((XGI21_LCDCapList[m].LVDSHDE == XGIbios_mode[xgifb_mode_idx].xres) &&
+ 					(XGI21_LCDCapList[m].LVDSVDE == XGIbios_mode[xgifb_mode_idx].yres)) {
+ 						XGINew_SetReg1( XGI_Pr.P3d4 , 0x36, m) ;
+diff --git a/drivers/staging/xgifb/vb_ext.c b/drivers/staging/xgifb/vb_ext.c
+index 712af839e825..1ecf9e3e85fb 100644
+--- a/drivers/staging/xgifb/vb_ext.c
++++ b/drivers/staging/xgifb/vb_ext.c
+@@ -14,27 +14,27 @@ extern   unsigned char XGI330_OutputSelect;
+ extern   unsigned short XGI330_RGBSenseData2;
+ extern   unsigned short XGI330_YCSenseData2;
+ extern   unsigned short XGI330_VideoSenseData2;
+-void     XGI_GetSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+-unsigned char  XGINew_GetPanelID(PVB_DEVICE_INFO pVBInfo);
++void     XGI_GetSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
++unsigned char  XGINew_GetPanelID(struct vb_device_info *pVBInfo);
+ unsigned short XGINew_SenseLCD(struct xgi_hw_device_info *,
+-			       PVB_DEVICE_INFO pVBInfo);
++			       struct vb_device_info *pVBInfo);
+ unsigned char XGINew_GetLCDDDCInfo(struct xgi_hw_device_info *HwDeviceExtension,
+-			     PVB_DEVICE_INFO pVBInfo);
++			     struct vb_device_info *pVBInfo);
+ void XGISetDPMS(struct xgi_hw_device_info *pXGIHWDE,
+ 		unsigned long VESA_POWER_STATE);
+-unsigned char XGINew_BridgeIsEnable(struct xgi_hw_device_info *, PVB_DEVICE_INFO pVBInfo);
++unsigned char XGINew_BridgeIsEnable(struct xgi_hw_device_info *, struct vb_device_info *pVBInfo);
+ unsigned char XGINew_Sense(unsigned short tempbx, unsigned short tempcx,
+-		     PVB_DEVICE_INFO pVBInfo);
++		     struct vb_device_info *pVBInfo);
+ unsigned char XGINew_SenseHiTV(struct xgi_hw_device_info *HwDeviceExtension,
+-			       PVB_DEVICE_INFO pVBInfo);
++			       struct vb_device_info *pVBInfo);
+ 
+ /**************************************************************
+ 	Dynamic Sense
+ *************************************************************/
+ 
+ void XGI_WaitDisplay(void);
+-unsigned char XGI_Is301C(PVB_DEVICE_INFO);
+-unsigned char XGI_Is301LV(PVB_DEVICE_INFO);
++unsigned char XGI_Is301C(struct vb_device_info *);
++unsigned char XGI_Is301LV(struct vb_device_info *);
+ 
+ 
+ 
+@@ -44,7 +44,7 @@ unsigned char XGI_Is301LV(PVB_DEVICE_INFO);
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGINew_Is301B(PVB_DEVICE_INFO pVBInfo)
++unsigned char XGINew_Is301B(struct vb_device_info *pVBInfo)
+ {
+     unsigned short flag ;
+ 
+@@ -62,7 +62,7 @@ unsigned char XGINew_Is301B(PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGI_Is301C(PVB_DEVICE_INFO pVBInfo)
++unsigned char XGI_Is301C(struct vb_device_info *pVBInfo)
+ {
+     if ( ( XGINew_GetReg1( pVBInfo->Part4Port , 0x01 ) & 0xF0 ) == 0xC0 )
+         return( 1 ) ;
+@@ -83,7 +83,7 @@ unsigned char XGI_Is301C(PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGI_Is301LV(PVB_DEVICE_INFO pVBInfo)
++unsigned char XGI_Is301LV(struct vb_device_info *pVBInfo)
+ {
+     if ( XGINew_GetReg1( pVBInfo->Part4Port , 0x01 ) >= 0xD0 )
+     {
+@@ -104,7 +104,7 @@ unsigned char XGI_Is301LV(PVB_DEVICE_INFO pVBInfo)
+ /* --------------------------------------------------------------------- */
+ unsigned char XGINew_Sense(unsigned short tempbx,
+ 		     unsigned short tempcx,
+-		     PVB_DEVICE_INFO pVBInfo)
++		     struct vb_device_info *pVBInfo)
+ {
+     unsigned short temp, i, tempch;
+ 
+@@ -140,8 +140,8 @@ void XGISetDPMS(struct xgi_hw_device_info *pXGIHWDE,
+ {
+     unsigned short ModeNo, ModeIdIndex;
+     unsigned char temp;
+-    VB_DEVICE_INFO VBINF;
+-    PVB_DEVICE_INFO pVBInfo = &VBINF;
++    struct vb_device_info VBINF;
++    struct vb_device_info *pVBInfo = &VBINF;
+     pVBInfo->BaseAddr = (unsigned long)pXGIHWDE->pjIOAddress ;
+     pVBInfo->ROMAddr  = pXGIHWDE->pjVirtualRomBase ;
+ 
+@@ -359,7 +359,7 @@ void XGISetDPMS(struct xgi_hw_device_info *pXGIHWDE,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_GetSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGI_GetSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempax = 0 , tempbx , tempcx , temp ,
+            P2reg0 = 0 , SenseModeNo = 0 , OutputSelect = *pVBInfo->pOutputSelect ,
+@@ -559,7 +559,7 @@ void XGI_GetSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ unsigned short XGINew_SenseLCD(struct xgi_hw_device_info *HwDeviceExtension,
+-			       PVB_DEVICE_INFO pVBInfo)
++			       struct vb_device_info *pVBInfo)
+ {
+     /* unsigned short SoftSetting ; */
+     unsigned short temp ;
+@@ -582,7 +582,7 @@ unsigned short XGINew_SenseLCD(struct xgi_hw_device_info *HwDeviceExtension,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGINew_GetLCDDDCInfo(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++unsigned char XGINew_GetLCDDDCInfo(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+     unsigned short temp ;
+ 
+@@ -635,7 +635,7 @@ unsigned char XGINew_GetLCDDDCInfo(struct xgi_hw_device_info *HwDeviceExtension,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGINew_GetPanelID(PVB_DEVICE_INFO pVBInfo )
++unsigned char XGINew_GetPanelID(struct vb_device_info *pVBInfo)
+ {
+ 	unsigned short PanelTypeTable[16] = {
+ 		SyncNN | PanelRGB18Bit | Panel800x600  | _PanelType00,
+@@ -708,7 +708,7 @@ unsigned char XGINew_GetPanelID(PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGINew_BridgeIsEnable(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++unsigned char XGINew_BridgeIsEnable(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+     unsigned short flag ;
+ 
+@@ -735,7 +735,7 @@ unsigned char XGINew_BridgeIsEnable(struct xgi_hw_device_info *HwDeviceExtension
+ /* Output : */
+ /* Description : */
+ /* ------------------------------------------------------ */
+-unsigned char XGINew_SenseHiTV(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++unsigned char XGINew_SenseHiTV(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempbx , tempcx , temp , i , tempch;
+ 
+@@ -816,7 +816,7 @@ unsigned char XGINew_SenseHiTV(struct xgi_hw_device_info *HwDeviceExtension, PVB
+ ;		     DX: PAnel V. resolution
+ ;-----------------------------------------------------------------------------
+ */
+-void XGI_XG21Fun14Sub70( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
++void XGI_XG21Fun14Sub70(struct vb_device_info *pVBInfo, PX86_REGS pBiosArguments)
+ {
+ 
+     unsigned short ModeIdIndex;
+@@ -859,7 +859,7 @@ void XGI_XG21Fun14Sub70( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
+ ;
+ ;-----------------------------------------------------------------------------
+ */
+-void XGI_XG21Fun14Sub71( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
++void XGI_XG21Fun14Sub71(struct vb_device_info *pVBInfo, PX86_REGS pBiosArguments)
+ {
+ 
+     unsigned short EModeCount;
+@@ -905,7 +905,7 @@ void XGI_XG21Fun14Sub71( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
+ ;
+ ;-----------------------------------------------------------------------------
+ */
+-void XGI_XG21Fun14Sub72( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
++void XGI_XG21Fun14Sub72(struct vb_device_info *pVBInfo, PX86_REGS pBiosArguments)
+ {
+     unsigned short ModeIdIndex, resindex;
+     unsigned short ModeNo;
+@@ -964,7 +964,7 @@ void XGI_XG21Fun14Sub72( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
+ ;                       BX[6]: *Value1 D[6] Panel H. Polarity
+ ;-----------------------------------------------------------------------------
+ */
+-void XGI_XG21Fun14Sub73( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
++void XGI_XG21Fun14Sub73(struct vb_device_info *pVBInfo, PX86_REGS pBiosArguments)
+ {
+     unsigned char Select;
+ 
+@@ -1000,8 +1000,8 @@ void XGI_XG21Fun14Sub73( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
+ 
+ void XGI_XG21Fun14(struct xgi_hw_device_info *pXGIHWDE, PX86_REGS pBiosArguments)
+ {
+-    VB_DEVICE_INFO VBINF;
+-    PVB_DEVICE_INFO pVBInfo = &VBINF;
++    struct vb_device_info VBINF;
++    struct vb_device_info *pVBInfo = &VBINF;
+ 
+     pVBInfo->IF_DEF_LVDS = 0 ;
+     pVBInfo->IF_DEF_CH7005 = 0 ;
+diff --git a/drivers/staging/xgifb/vb_ext.h b/drivers/staging/xgifb/vb_ext.h
+index 2933b16887ad..5cc4d12c2254 100644
+--- a/drivers/staging/xgifb/vb_ext.h
++++ b/drivers/staging/xgifb/vb_ext.h
+@@ -24,11 +24,11 @@ typedef union   _X86_REGS    {
+ extern   void     XGI_XG21Fun14(struct xgi_hw_device_info *pXGIHWDE, PX86_REGS pBiosArguments);
+ extern void XGISetDPMS(struct xgi_hw_device_info *pXGIHWDE,
+ 		       unsigned long VESA_POWER_STATE);
+-extern   void     XGI_GetSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+-extern   void     XGINew_SetModeScratch(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) ;
++extern   void     XGI_GetSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
++extern   void     XGINew_SetModeScratch(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo) ;
+ extern void ReadVBIOSTablData(unsigned char ChipType,
+-			      PVB_DEVICE_INFO pVBInfo);
++			      struct vb_device_info *pVBInfo);
+ extern unsigned short XGINew_SenseLCD(struct xgi_hw_device_info *,
+-				      PVB_DEVICE_INFO pVBInfo);
++				      struct vb_device_info *pVBInfo);
+ 
+ #endif
+diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
+index 254c368c8cfe..e02722d05f68 100644
+--- a/drivers/staging/xgifb/vb_init.c
++++ b/drivers/staging/xgifb/vb_init.c
+@@ -72,39 +72,39 @@ unsigned short XGINew_DDRDRAM_TYPE20[12][5] = {
+ 	{ 2, 12,  9,  8, 0x35},
+ 	{ 2, 12,  8,  4, 0x31} };
+ 
+-void     XGINew_SetDRAMSize_340(struct xgi_hw_device_info *, PVB_DEVICE_INFO);
+-void     XGINew_SetDRAMSize_310(struct xgi_hw_device_info *, PVB_DEVICE_INFO);
+-void     XGINew_SetMemoryClock(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO);
+-void     XGINew_SetDRAMModeRegister(PVB_DEVICE_INFO );
++void     XGINew_SetDRAMSize_340(struct xgi_hw_device_info *, struct vb_device_info *);
++void     XGINew_SetDRAMSize_310(struct xgi_hw_device_info *, struct vb_device_info *);
++void     XGINew_SetMemoryClock(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *);
++void     XGINew_SetDRAMModeRegister(struct vb_device_info *);
+ void     XGINew_SetDRAMModeRegister340(struct xgi_hw_device_info *HwDeviceExtension);
+ void XGINew_SetDRAMDefaultRegister340(struct xgi_hw_device_info *HwDeviceExtension,
+-				      unsigned long, PVB_DEVICE_INFO);
++				      unsigned long, struct vb_device_info *);
+ unsigned char XGINew_GetXG20DRAMType(struct xgi_hw_device_info *HwDeviceExtension,
+-				     PVB_DEVICE_INFO pVBInfo);
++				     struct vb_device_info *pVBInfo);
+ unsigned char XGIInitNew(struct xgi_hw_device_info *HwDeviceExtension);
+ 
+-int      XGINew_DDRSizing340(struct xgi_hw_device_info *, PVB_DEVICE_INFO);
+-void     XGINew_DisableRefresh(struct xgi_hw_device_info *, PVB_DEVICE_INFO) ;
+-void     XGINew_CheckBusWidth_310( PVB_DEVICE_INFO) ;
+-int      XGINew_SDRSizing(PVB_DEVICE_INFO);
+-int      XGINew_DDRSizing( PVB_DEVICE_INFO );
+-void     XGINew_EnableRefresh(struct xgi_hw_device_info *, PVB_DEVICE_INFO);
++int      XGINew_DDRSizing340(struct xgi_hw_device_info *, struct vb_device_info *);
++void     XGINew_DisableRefresh(struct xgi_hw_device_info *, struct vb_device_info *) ;
++void     XGINew_CheckBusWidth_310(struct vb_device_info *) ;
++int      XGINew_SDRSizing(struct vb_device_info *);
++int      XGINew_DDRSizing(struct vb_device_info *);
++void     XGINew_EnableRefresh(struct xgi_hw_device_info *, struct vb_device_info *);
+ int      XGINew_RAMType;                  /*int      ModeIDOffset,StandTable,CRT1Table,ScreenOffset,REFIndex;*/
+ unsigned long	 UNIROM;			  /* UNIROM */
+-unsigned char  ChkLFB(PVB_DEVICE_INFO);
++unsigned char  ChkLFB(struct vb_device_info *);
+ void     XGINew_Delay15us(unsigned long);
+ void     SetPowerConsume(struct xgi_hw_device_info *HwDeviceExtension,
+ 			 unsigned long XGI_P3d4Port);
+-void     ReadVBIOSTablData(unsigned char ChipType, PVB_DEVICE_INFO pVBInfo);
+-void     XGINew_DDR1x_MRS_XG20(unsigned long P3c4, PVB_DEVICE_INFO pVBInfo);
++void     ReadVBIOSTablData(unsigned char ChipType, struct vb_device_info *pVBInfo);
++void     XGINew_DDR1x_MRS_XG20(unsigned long P3c4, struct vb_device_info *pVBInfo);
+ void     XGINew_SetDRAMModeRegister_XG20(struct xgi_hw_device_info *HwDeviceExtension);
+ void     XGINew_SetDRAMModeRegister_XG27(struct xgi_hw_device_info *HwDeviceExtension);
+-void     XGINew_ChkSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) ;
+-void     XGINew_SetModeScratch(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) ;
+-void     XGINew_GetXG21Sense(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) ;
+-unsigned char    GetXG21FPBits(PVB_DEVICE_INFO pVBInfo);
+-void     XGINew_GetXG27Sense(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) ;
+-unsigned char    GetXG27FPBits(PVB_DEVICE_INFO pVBInfo);
++void     XGINew_ChkSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo) ;
++void     XGINew_SetModeScratch(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo) ;
++void     XGINew_GetXG21Sense(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo) ;
++unsigned char    GetXG21FPBits(struct vb_device_info *pVBInfo);
++void     XGINew_GetXG27Sense(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo) ;
++unsigned char    GetXG27FPBits(struct vb_device_info *pVBInfo);
+ 
+ void DelayUS(unsigned long MicroSeconds)
+ {
+@@ -121,8 +121,8 @@ void DelayUS(unsigned long MicroSeconds)
+ unsigned char XGIInitNew(struct xgi_hw_device_info *HwDeviceExtension)
+ {
+ 
+-    VB_DEVICE_INFO VBINF;
+-    PVB_DEVICE_INFO pVBInfo = &VBINF;
++    struct vb_device_info VBINF;
++    struct vb_device_info *pVBInfo = &VBINF;
+     unsigned char   i, temp = 0, temp1 ;
+      //       VBIOSVersion[ 5 ] ;
+     volatile unsigned char *pVideoMemory;
+@@ -547,7 +547,7 @@ return 1;
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ unsigned char XGINew_GetXG20DRAMType(struct xgi_hw_device_info *HwDeviceExtension,
+-				     PVB_DEVICE_INFO pVBInfo)
++				     struct vb_device_info *pVBInfo)
+ {
+     unsigned char data, temp;
+ 
+@@ -617,7 +617,7 @@ unsigned char XGINew_GetXG20DRAMType(struct xgi_hw_device_info *HwDeviceExtensio
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGINew_Get310DRAMType(PVB_DEVICE_INFO pVBInfo)
++unsigned char XGINew_Get310DRAMType(struct vb_device_info *pVBInfo)
+ {
+     unsigned char data ;
+ 
+@@ -653,7 +653,7 @@ void XGINew_Delay15us(unsigned long ulMicrsoSec)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_SDR_MRS(  PVB_DEVICE_INFO pVBInfo )
++void XGINew_SDR_MRS(struct vb_device_info *pVBInfo)
+ {
+     unsigned short data ;
+ 
+@@ -673,7 +673,7 @@ void XGINew_SDR_MRS(  PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_DDR1x_MRS_340(unsigned long P3c4 , PVB_DEVICE_INFO pVBInfo)
++void XGINew_DDR1x_MRS_340(unsigned long P3c4, struct vb_device_info *pVBInfo)
+ {
+     XGINew_SetReg1( P3c4 , 0x18 , 0x01 ) ;
+     XGINew_SetReg1( P3c4 , 0x19 , 0x20 ) ;
+@@ -711,7 +711,7 @@ void XGINew_DDR1x_MRS_340(unsigned long P3c4 , PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_DDR2x_MRS_340(unsigned long P3c4 , PVB_DEVICE_INFO pVBInfo)
++void XGINew_DDR2x_MRS_340(unsigned long P3c4, struct vb_device_info *pVBInfo)
+ {
+     XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ;
+     XGINew_SetReg1( P3c4 , 0x19 , 0x20 ) ;
+@@ -741,7 +741,7 @@ void XGINew_DDR2x_MRS_340(unsigned long P3c4 , PVB_DEVICE_INFO pVBInfo)
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ void XGINew_DDRII_Bootup_XG27(struct xgi_hw_device_info *HwDeviceExtension,
+-			      unsigned long P3c4, PVB_DEVICE_INFO pVBInfo)
++			      unsigned long P3c4, struct vb_device_info *pVBInfo)
+ {
+     unsigned long P3d4 = P3c4 + 0x10 ;
+     XGINew_RAMType = ( int )XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo ) ;
+@@ -820,7 +820,7 @@ void XGINew_DDRII_Bootup_XG27(struct xgi_hw_device_info *HwDeviceExtension,
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ void XGINew_DDR2_MRS_XG20(struct xgi_hw_device_info *HwDeviceExtension,
+-			  unsigned long P3c4, PVB_DEVICE_INFO pVBInfo)
++			  unsigned long P3c4, struct vb_device_info *pVBInfo)
+ {
+     unsigned long P3d4 = P3c4 + 0x10 ;
+ 
+@@ -873,7 +873,7 @@ void XGINew_DDR2_MRS_XG20(struct xgi_hw_device_info *HwDeviceExtension,
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ void XGINew_DDR2_MRS_XG27(struct xgi_hw_device_info *HwDeviceExtension,
+-			  unsigned long P3c4, PVB_DEVICE_INFO pVBInfo)
++			  unsigned long P3c4, struct vb_device_info *pVBInfo)
+ {
+     unsigned long P3d4 = P3c4 + 0x10 ;
+ 
+@@ -952,7 +952,7 @@ void XGINew_DDR2_MRS_XG27(struct xgi_hw_device_info *HwDeviceExtension,
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ void XGINew_DDR1x_DefaultRegister(struct xgi_hw_device_info *HwDeviceExtension,
+-				  unsigned long Port, PVB_DEVICE_INFO pVBInfo)
++				  unsigned long Port, struct vb_device_info *pVBInfo)
+ {
+     unsigned long P3d4 = Port ,
+            P3c4 = Port - 0x10 ;
+@@ -1013,7 +1013,7 @@ void XGINew_DDR1x_DefaultRegister(struct xgi_hw_device_info *HwDeviceExtension,
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ void XGINew_DDR2x_DefaultRegister(struct xgi_hw_device_info *HwDeviceExtension,
+-				  unsigned long Port, PVB_DEVICE_INFO pVBInfo)
++				  unsigned long Port, struct vb_device_info *pVBInfo)
+ {
+     unsigned long P3d4 = Port ,
+            P3c4 = Port - 0x10 ;
+@@ -1065,7 +1065,7 @@ void XGINew_DDR2x_DefaultRegister(struct xgi_hw_device_info *HwDeviceExtension,
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ void XGINew_DDR2_DefaultRegister(struct xgi_hw_device_info *HwDeviceExtension,
+-				 unsigned long Port, PVB_DEVICE_INFO pVBInfo)
++				 unsigned long Port, struct vb_device_info *pVBInfo)
+ {
+     unsigned long P3d4 = Port ,
+            P3c4 = Port - 0x10 ;
+@@ -1104,7 +1104,7 @@ void XGINew_DDR2_DefaultRegister(struct xgi_hw_device_info *HwDeviceExtension,
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ void XGINew_SetDRAMDefaultRegister340(struct xgi_hw_device_info *HwDeviceExtension,
+-				      unsigned long Port, PVB_DEVICE_INFO pVBInfo)
++				      unsigned long Port, struct vb_device_info *pVBInfo)
+ {
+     unsigned char temp, temp1, temp2, temp3 ,
+           i , j , k ;
+@@ -1247,7 +1247,7 @@ void XGINew_SetDRAMDefaultRegister340(struct xgi_hw_device_info *HwDeviceExtensi
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_DDR_MRS(PVB_DEVICE_INFO pVBInfo)
++void XGINew_DDR_MRS(struct vb_device_info *pVBInfo)
+ {
+     unsigned short data ;
+ 
+@@ -1315,7 +1315,7 @@ void XGINew_DDR_MRS(PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_VerifyMclk(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGINew_VerifyMclk(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+     unsigned char *pVideoMemory = pVBInfo->FBAddr ;
+     unsigned char i, j ;
+@@ -1361,7 +1361,7 @@ void XGINew_VerifyMclk(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_SetDRAMSize_340(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGINew_SetDRAMSize_340(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+     unsigned short  data ;
+ 
+@@ -1390,7 +1390,7 @@ void XGINew_SetDRAMSize_340(struct xgi_hw_device_info *HwDeviceExtension, PVB_DE
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_SetDRAMSize_310(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGINew_SetDRAMSize_310(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+     unsigned short data ;
+     pVBInfo->ROMAddr  = HwDeviceExtension->pjVirtualRomBase ,
+@@ -1457,8 +1457,8 @@ void XGINew_SetDRAMSize_310(struct xgi_hw_device_info *HwDeviceExtension, PVB_DE
+ void XGINew_SetDRAMModeRegister340(struct xgi_hw_device_info *HwDeviceExtension)
+ {
+     unsigned char data ;
+-    VB_DEVICE_INFO VBINF;
+-    PVB_DEVICE_INFO pVBInfo = &VBINF;
++    struct vb_device_info VBINF;
++    struct vb_device_info *pVBInfo = &VBINF;
+     pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+     pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+     pVBInfo->BaseAddr = (unsigned long)HwDeviceExtension->pjIOAddress ;
+@@ -1508,7 +1508,7 @@ void XGINew_SetDRAMModeRegister340(struct xgi_hw_device_info *HwDeviceExtension)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_SetDRAMModeRegister( PVB_DEVICE_INFO pVBInfo)
++void XGINew_SetDRAMModeRegister(struct vb_device_info *pVBInfo)
+ {
+     if ( XGINew_Get310DRAMType( pVBInfo ) < 2 )
+     {
+@@ -1528,7 +1528,7 @@ void XGINew_SetDRAMModeRegister( PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_DisableRefresh(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGINew_DisableRefresh(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+     unsigned short  data ;
+ 
+@@ -1546,7 +1546,7 @@ void XGINew_DisableRefresh(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEV
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_EnableRefresh(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGINew_EnableRefresh(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+ 
+     XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , pVBInfo->SR15[ 3 ][ XGINew_RAMType ] ) ;	/* SR1B */
+@@ -1563,7 +1563,7 @@ void XGINew_EnableRefresh(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVI
+ /* --------------------------------------------------------------------- */
+ void XGINew_DisableChannelInterleaving(int index,
+ 				       unsigned short XGINew_DDRDRAM_TYPE[][5],
+-				       PVB_DEVICE_INFO pVBInfo)
++				       struct vb_device_info *pVBInfo)
+ {
+     unsigned short data ;
+ 
+@@ -1599,7 +1599,7 @@ void XGINew_DisableChannelInterleaving(int index,
+ /* --------------------------------------------------------------------- */
+ void XGINew_SetDRAMSizingType(int index,
+ 			      unsigned short DRAMTYPE_TABLE[][5],
+-			      PVB_DEVICE_INFO pVBInfo)
++			      struct vb_device_info *pVBInfo)
+ {
+     unsigned short data;
+ 
+@@ -1616,7 +1616,7 @@ void XGINew_SetDRAMSizingType(int index,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_CheckBusWidth_310(  PVB_DEVICE_INFO pVBInfo)
++void XGINew_CheckBusWidth_310(struct vb_device_info *pVBInfo)
+ {
+     unsigned short data ;
+     volatile unsigned long *pVideoMemory ;
+@@ -1754,7 +1754,7 @@ int XGINew_SetRank(int index,
+ 		   unsigned char RankNo,
+ 		   unsigned char XGINew_ChannelAB,
+ 		   unsigned short DRAMTYPE_TABLE[][5],
+-		   PVB_DEVICE_INFO pVBInfo)
++		   struct vb_device_info *pVBInfo)
+ {
+     unsigned short data;
+     int RankSize ;
+@@ -1795,7 +1795,7 @@ int XGINew_SetDDRChannel(int index,
+ 			 unsigned char ChannelNo,
+ 			 unsigned char XGINew_ChannelAB,
+ 			 unsigned short DRAMTYPE_TABLE[][5],
+-			 PVB_DEVICE_INFO pVBInfo)
++			 struct vb_device_info *pVBInfo)
+ {
+     unsigned short data;
+     int RankSize ;
+@@ -1833,7 +1833,7 @@ int XGINew_SetDDRChannel(int index,
+ /* --------------------------------------------------------------------- */
+ int XGINew_CheckColumn(int index,
+ 		       unsigned short DRAMTYPE_TABLE[][5],
+-		       PVB_DEVICE_INFO pVBInfo)
++		       struct vb_device_info *pVBInfo)
+ {
+     int i ;
+     unsigned long Increment , Position ;
+@@ -1867,7 +1867,7 @@ int XGINew_CheckColumn(int index,
+ /* --------------------------------------------------------------------- */
+ int XGINew_CheckBanks(int index,
+ 		      unsigned short DRAMTYPE_TABLE[][5],
+-		      PVB_DEVICE_INFO pVBInfo)
++		      struct vb_device_info *pVBInfo)
+ {
+     int i ;
+     unsigned long Increment , Position ;
+@@ -1900,7 +1900,7 @@ int XGINew_CheckBanks(int index,
+ /* --------------------------------------------------------------------- */
+ int XGINew_CheckRank(int RankNo, int index,
+ 		     unsigned short DRAMTYPE_TABLE[][5],
+-		     PVB_DEVICE_INFO pVBInfo)
++		     struct vb_device_info *pVBInfo)
+ {
+     int i ;
+     unsigned long Increment , Position ;
+@@ -1936,7 +1936,7 @@ int XGINew_CheckRank(int RankNo, int index,
+ /* --------------------------------------------------------------------- */
+ int XGINew_CheckDDRRank(int RankNo, int index,
+ 			unsigned short DRAMTYPE_TABLE[][5],
+-			PVB_DEVICE_INFO pVBInfo)
++			struct vb_device_info *pVBInfo)
+ {
+     unsigned long Increment , Position ;
+     unsigned short data ;
+@@ -1980,7 +1980,7 @@ int XGINew_CheckDDRRank(int RankNo, int index,
+ /* --------------------------------------------------------------------- */
+ int XGINew_CheckRanks(int RankNo, int index,
+ 		      unsigned short DRAMTYPE_TABLE[][5],
+-		      PVB_DEVICE_INFO pVBInfo)
++		      struct vb_device_info *pVBInfo)
+ {
+     int r ;
+ 
+@@ -2008,7 +2008,7 @@ int XGINew_CheckRanks(int RankNo, int index,
+ /* --------------------------------------------------------------------- */
+ int XGINew_CheckDDRRanks(int RankNo, int index,
+ 			 unsigned short DRAMTYPE_TABLE[][5],
+-			 PVB_DEVICE_INFO pVBInfo)
++			 struct vb_device_info *pVBInfo)
+ {
+     int r ;
+ 
+@@ -2034,7 +2034,7 @@ int XGINew_CheckDDRRanks(int RankNo, int index,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-int XGINew_SDRSizing(PVB_DEVICE_INFO pVBInfo)
++int XGINew_SDRSizing(struct vb_device_info *pVBInfo)
+ {
+     int    i ;
+     unsigned char  j ;
+@@ -2067,7 +2067,7 @@ int XGINew_SDRSizing(PVB_DEVICE_INFO pVBInfo)
+ /* --------------------------------------------------------------------- */
+ unsigned short XGINew_SetDRAMSizeReg(int index,
+ 				     unsigned short DRAMTYPE_TABLE[][5],
+-				     PVB_DEVICE_INFO pVBInfo)
++				     struct vb_device_info *pVBInfo)
+ {
+     unsigned short data = 0 , memsize = 0;
+     int RankSize ;
+@@ -2118,7 +2118,7 @@ unsigned short XGINew_SetDRAMSizeReg(int index,
+ /* --------------------------------------------------------------------- */
+ unsigned short XGINew_SetDRAMSize20Reg(int index,
+ 				       unsigned short DRAMTYPE_TABLE[][5],
+-				       PVB_DEVICE_INFO pVBInfo)
++				       struct vb_device_info *pVBInfo)
+ {
+     unsigned short data = 0 , memsize = 0;
+     int RankSize ;
+@@ -2169,7 +2169,7 @@ unsigned short XGINew_SetDRAMSize20Reg(int index,
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ int XGINew_ReadWriteRest(unsigned short StopAddr, unsigned short StartAddr,
+-			 PVB_DEVICE_INFO pVBInfo)
++			 struct vb_device_info *pVBInfo)
+ {
+     int i ;
+     unsigned long Position = 0 ;
+@@ -2205,7 +2205,7 @@ int XGINew_ReadWriteRest(unsigned short StopAddr, unsigned short StartAddr,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGINew_CheckFrequence(PVB_DEVICE_INFO pVBInfo)
++unsigned char XGINew_CheckFrequence(struct vb_device_info *pVBInfo)
+ {
+     unsigned char data ;
+ 
+@@ -2228,7 +2228,7 @@ unsigned char XGINew_CheckFrequence(PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+     unsigned char data;
+ 
+@@ -2509,7 +2509,7 @@ void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVIC
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-int XGINew_DDRSizing340(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++int XGINew_DDRSizing340(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+     int i ;
+     unsigned short memsize , addr ;
+@@ -2564,7 +2564,7 @@ int XGINew_DDRSizing340(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-int XGINew_DDRSizing(PVB_DEVICE_INFO pVBInfo)
++int XGINew_DDRSizing(struct vb_device_info *pVBInfo)
+ {
+     int    i ;
+     unsigned char  j ;
+@@ -2595,7 +2595,7 @@ int XGINew_DDRSizing(PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_SetMemoryClock(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGINew_SetMemoryClock(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+ 
+ 
+@@ -2627,7 +2627,7 @@ void XGINew_SetMemoryClock(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEV
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char ChkLFB(PVB_DEVICE_INFO pVBInfo)
++unsigned char ChkLFB(struct vb_device_info *pVBInfo)
+ {
+ 	if (LFBDRAMTrap & XGINew_GetReg1(pVBInfo->P3d4 , 0x78))
+ 		return 1;
+@@ -2673,7 +2673,7 @@ void SetPowerConsume(struct xgi_hw_device_info *HwDeviceExtension,
+ }
+ 
+ 
+-void XGINew_InitVBIOSData(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGINew_InitVBIOSData(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+ 
+ 	/* unsigned long ROMAddr = (unsigned long)HwDeviceExtension->pjVirtualRomBase; */
+@@ -2722,7 +2722,7 @@ void XGINew_InitVBIOSData(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVI
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void ReadVBIOSTablData(unsigned char ChipType, PVB_DEVICE_INFO pVBInfo)
++void ReadVBIOSTablData(unsigned char ChipType, struct vb_device_info *pVBInfo)
+ {
+ 	volatile unsigned char *pVideoMemory = (unsigned char *)pVBInfo->ROMAddr;
+     unsigned long   i ;
+@@ -2761,7 +2761,8 @@ void ReadVBIOSTablData(unsigned char ChipType, PVB_DEVICE_INFO pVBInfo)
+                 i += 25;
+                 j--;
+                 k++;
+-              } while ( (j>0) && ( k < (sizeof(XGI21_LCDCapList)/sizeof(XGI21_LVDSCapStruct)) ) );
++	      } while ((j > 0) &&
++		       (k < (sizeof(XGI21_LCDCapList)/sizeof(struct XGI21_LVDSCapStruct))));
+             }
+             else
+             {
+@@ -2792,7 +2793,7 @@ void ReadVBIOSTablData(unsigned char ChipType, PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_DDR1x_MRS_XG20(unsigned long P3c4, PVB_DEVICE_INFO pVBInfo)
++void XGINew_DDR1x_MRS_XG20(unsigned long P3c4, struct vb_device_info *pVBInfo)
+ {
+ 
+     XGINew_SetReg1( P3c4 , 0x18 , 0x01 ) ;
+@@ -2830,8 +2831,8 @@ void XGINew_DDR1x_MRS_XG20(unsigned long P3c4, PVB_DEVICE_INFO pVBInfo)
+ /* --------------------------------------------------------------------- */
+ void XGINew_SetDRAMModeRegister_XG20(struct xgi_hw_device_info *HwDeviceExtension)
+ {
+-    VB_DEVICE_INFO VBINF;
+-    PVB_DEVICE_INFO pVBInfo = &VBINF;
++    struct vb_device_info VBINF;
++    struct vb_device_info *pVBInfo = &VBINF;
+     pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+     pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+     pVBInfo->BaseAddr = (unsigned long)HwDeviceExtension->pjIOAddress ;
+@@ -2869,8 +2870,8 @@ void XGINew_SetDRAMModeRegister_XG20(struct xgi_hw_device_info *HwDeviceExtensio
+ 
+ void XGINew_SetDRAMModeRegister_XG27(struct xgi_hw_device_info *HwDeviceExtension)
+ {
+-    VB_DEVICE_INFO VBINF;
+-    PVB_DEVICE_INFO pVBInfo = &VBINF;
++    struct vb_device_info VBINF;
++    struct vb_device_info *pVBInfo = &VBINF;
+     pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+     pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+     pVBInfo->BaseAddr = (unsigned long)HwDeviceExtension->pjIOAddress ;
+@@ -2913,8 +2914,8 @@ void XGINew_SetDRAMModeRegister_XG27(struct xgi_hw_device_info *HwDeviceExtensio
+ {
+ 
+     unsigned char data ;
+-    VB_DEVICE_INFO VBINF;
+-    PVB_DEVICE_INFO pVBInfo = &VBINF;
++    struct vb_device_info VBINF;
++    struct vb_device_info *pVBInfo = &VBINF;
+     pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+     pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+     pVBInfo->BaseAddr = HwDeviceExtension->pjIOAddress ;
+@@ -2956,7 +2957,7 @@ void XGINew_SetDRAMModeRegister_XG27(struct xgi_hw_device_info *HwDeviceExtensio
+ /* Output : */
+ /* Description : */
+ /* -------------------------------------------------------- */
+-void XGINew_ChkSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGINew_ChkSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempbx = 0, temp, tempcx, CR3CData;
+ 
+@@ -3017,7 +3018,7 @@ void XGINew_ChkSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEV
+ /* Output : */
+ /* Description : */
+ /* -------------------------------------------------------- */
+-void XGINew_SetModeScratch(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGINew_SetModeScratch(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+     unsigned short temp , tempcl = 0 , tempch = 0 , CR31Data , CR38Data;
+ 
+@@ -3114,7 +3115,7 @@ void XGINew_SetModeScratch(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEV
+ /* Output : */
+ /* Description : */
+ /* -------------------------------------------------------- */
+-void XGINew_GetXG21Sense(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGINew_GetXG21Sense(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+     unsigned char Temp;
+     volatile unsigned char *pVideoMemory = (unsigned char *)pVBInfo->ROMAddr;
+@@ -3156,7 +3157,7 @@ void XGINew_GetXG21Sense(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVIC
+ /* Output : */
+ /* Description : */
+ /* -------------------------------------------------------- */
+-void XGINew_GetXG27Sense(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGINew_GetXG27Sense(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+ 	unsigned char Temp, bCR4A;
+ 
+@@ -3180,7 +3181,7 @@ void XGINew_GetXG27Sense(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVIC
+ 
+ }
+ 
+-unsigned char GetXG21FPBits(PVB_DEVICE_INFO pVBInfo)
++unsigned char GetXG21FPBits(struct vb_device_info *pVBInfo)
+ {
+ 	unsigned char CR38, CR4A, temp;
+ 
+@@ -3200,7 +3201,7 @@ unsigned char GetXG21FPBits(PVB_DEVICE_INFO pVBInfo)
+     return temp;
+ }
+ 
+-unsigned char GetXG27FPBits(PVB_DEVICE_INFO pVBInfo)
++unsigned char GetXG27FPBits(struct vb_device_info *pVBInfo)
+ {
+ 	unsigned char CR4A, temp;
+ 
+diff --git a/drivers/staging/xgifb/vb_init.h b/drivers/staging/xgifb/vb_init.h
+index 8803253fe0e4..b47352b8e34a 100644
+--- a/drivers/staging/xgifb/vb_init.h
++++ b/drivers/staging/xgifb/vb_init.h
+@@ -1,7 +1,7 @@
+ #ifndef  _VBINIT_
+ #define  _VBINIT_
+ extern   unsigned char    XGIInitNew(struct xgi_hw_device_info *HwDeviceExtension) ;
+-extern XGI21_LVDSCapStruct  XGI21_LCDCapList[13];
++extern struct XGI21_LVDSCapStruct  XGI21_LCDCapList[13];
+ 
+ #endif
+ 
+diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c
+index 158789cface5..d90bf06bf62f 100644
+--- a/drivers/staging/xgifb/vb_setmode.c
++++ b/drivers/staging/xgifb/vb_setmode.c
+@@ -20,169 +20,173 @@
+ 
+ 
+ 
+-unsigned char  XGI_IsLCDDualLink(PVB_DEVICE_INFO pVBInfo);
++unsigned char  XGI_IsLCDDualLink(struct vb_device_info *pVBInfo);
+ unsigned char  XGI_SetCRT2Group301(unsigned short ModeNo,
+ 			     struct xgi_hw_device_info *HwDeviceExtension,
+-			     PVB_DEVICE_INFO pVBInfo);
+-unsigned char  XGI_BacklightByDrv(PVB_DEVICE_INFO pVBInfo);
++			     struct vb_device_info *pVBInfo);
++unsigned char  XGI_BacklightByDrv(struct vb_device_info *pVBInfo);
+ 
+-unsigned char  XGI_IsLCDON(PVB_DEVICE_INFO pVBInfo);
+-unsigned char  XGI_DisableChISLCD(PVB_DEVICE_INFO pVBInfo);
+-unsigned char  XGI_EnableChISLCD(PVB_DEVICE_INFO pVBInfo);
++unsigned char  XGI_IsLCDON(struct vb_device_info *pVBInfo);
++unsigned char  XGI_DisableChISLCD(struct vb_device_info *pVBInfo);
++unsigned char  XGI_EnableChISLCD(struct vb_device_info *pVBInfo);
+ unsigned char  XGI_AjustCRT2Rate(unsigned short ModeNo,
+ 			   unsigned short ModeIdIndex,
+ 			   unsigned short RefreshRateTableIndex,
+-			   unsigned short *i, PVB_DEVICE_INFO pVBInfo);
++			   unsigned short *i, struct vb_device_info *pVBInfo);
+ unsigned char  XGI_SearchModeID(unsigned short ModeNo,
+ 			  unsigned short *ModeIdIndex,
+-			  PVB_DEVICE_INFO pVBInfo);
++			  struct vb_device_info *pVBInfo);
+ unsigned char  XGI_GetLCDInfo(unsigned short ModeNo,
+ 			unsigned short ModeIdIndex,
+-			PVB_DEVICE_INFO pVBInfo);
++			struct vb_device_info *pVBInfo);
+ unsigned char  XGISetModeNew(struct xgi_hw_device_info *HwDeviceExtension,
+ 		       unsigned short ModeNo);
+-unsigned char  XGI_BridgeIsOn(PVB_DEVICE_INFO pVBInfo);
++unsigned char  XGI_BridgeIsOn(struct vb_device_info *pVBInfo);
+ unsigned char    XGI_GetModePtr(unsigned short ModeNo,
+ 			unsigned short ModeIdIndex,
+-			PVB_DEVICE_INFO pVBInfo);
++			struct vb_device_info *pVBInfo);
+ unsigned short XGI_GetOffset(unsigned short ModeNo,
+ 			     unsigned short ModeIdIndex,
+ 			     unsigned short RefreshRateTableIndex,
+ 			     struct xgi_hw_device_info *HwDeviceExtension,
+-			     PVB_DEVICE_INFO pVBInfo);
++			     struct vb_device_info *pVBInfo);
+ unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
+ 				  unsigned short ModeNo,
+ 				  unsigned short ModeIdIndex,
+-				  PVB_DEVICE_INFO pVBInfo);
++				  struct vb_device_info *pVBInfo);
+ unsigned short XGI_GetResInfo(unsigned short ModeNo,
+ 			      unsigned short ModeIdIndex,
+-			      PVB_DEVICE_INFO pVBInfo);
++			      struct vb_device_info *pVBInfo);
+ unsigned short XGI_GetColorDepth(unsigned short ModeNo,
+ 				 unsigned short ModeIdIndex,
+-				 PVB_DEVICE_INFO pVBInfo);
+-unsigned short XGI_GetVGAHT2(PVB_DEVICE_INFO pVBInfo);
++				 struct vb_device_info *pVBInfo);
++unsigned short XGI_GetVGAHT2(struct vb_device_info *pVBInfo);
+ unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo,
+ 			       unsigned short ModeIdIndex,
+ 			       unsigned short RefreshRateTableIndex,
+ 			       struct xgi_hw_device_info *HwDeviceExtension,
+-			       PVB_DEVICE_INFO pVBInfo);
+-void     XGI_VBLongWait(PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SaveCRT2Info(unsigned short ModeNo, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_GetCRT2ResInfo(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_PreSetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetGroup3(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetGroup5(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+-void     *XGI_GetLcdPtr(unsigned short BX,  unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     *XGI_GetTVPtr(unsigned short BX, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void 	 XGI_FirePWDEnable(PVB_DEVICE_INFO pVBInfo);
+-void     XGI_EnableGatingCRT(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_DisableGatingCRT(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetPanelDelay(unsigned short tempbl, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetPanelPower(unsigned short tempah, unsigned short tempbl, PVB_DEVICE_INFO pVBInfo);
+-void 	 XGI_EnablePWD( PVB_DEVICE_INFO pVBInfo);
+-void 	 XGI_DisablePWD( PVB_DEVICE_INFO pVBInfo);
+-void     XGI_AutoThreshold( PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetTap4Regs( PVB_DEVICE_INFO pVBInfo);
+-
+-void     XGI_DisplayOn(struct xgi_hw_device_info *, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_DisplayOff(struct xgi_hw_device_info *, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetCRT1Group(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetXG21CRTC(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetXG21LCD(PVB_DEVICE_INFO pVBInfo, unsigned short RefreshRateTableIndex, unsigned short ModeNo);
+-void     XGI_SetXG27CRTC(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetXG27LCD(PVB_DEVICE_INFO pVBInfo, unsigned short RefreshRateTableIndex, unsigned short ModeNo);
+-void	 XGI_UpdateXG21CRTC(unsigned short ModeNo, PVB_DEVICE_INFO pVBInfo, unsigned short RefreshRateTableIndex);
+-void     XGI_WaitDisply(PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SenseCRT1(PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetSeqRegs(unsigned short ModeNo, unsigned short StandTableIndex, unsigned short ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetMiscRegs(unsigned short StandTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetCRTCRegs(struct xgi_hw_device_info *HwDeviceExtension, unsigned short StandTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetATTRegs(unsigned short ModeNo, unsigned short StandTableIndex, unsigned short ModeIdIndex,PVB_DEVICE_INFO pVBInfo );
+-void     XGI_SetGRCRegs(unsigned short StandTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_ClearExt1Regs(PVB_DEVICE_INFO pVBInfo);
+-
+-void     XGI_SetSync(unsigned short RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetCRT1CRTC(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo, struct xgi_hw_device_info *HwDeviceExtension);
+-void     XGI_SetCRT1Timing_H(PVB_DEVICE_INFO pVBInfo, struct xgi_hw_device_info *HwDeviceExtension);
+-void     XGI_SetCRT1Timing_V(unsigned short ModeIdIndex, unsigned short ModeNo,PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetCRT1DE(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetCRT1VCLK(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetCRT1FIFO(unsigned short ModeNo, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetVCLKState(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-
+-void     XGI_LoadDAC(unsigned short ModeNo, unsigned short ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
+-void     XGI_WriteDAC(unsigned short dl, unsigned short ah, unsigned short al, unsigned short dh, PVB_DEVICE_INFO pVBInfo);
+-/*void     XGI_ClearBuffer(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo, PVB_DEVICE_INFO pVBInfo);*/
+-void     XGI_SetLCDAGroup(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO  pVBInfo);
+-void     XGI_GetLVDSResInfo(unsigned short ModeNo, unsigned short ModeIdIndex,PVB_DEVICE_INFO  pVBInfo);
+-void     XGI_GetLVDSData(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,PVB_DEVICE_INFO  pVBInfo);
+-void     XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO  pVBInfo);
+-void     XGI_SetLVDSRegs(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,PVB_DEVICE_INFO  pVBInfo);
+-void     XGI_UpdateModeInfo(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO  pVBInfo);
+-void     XGI_GetVGAType(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO  pVBInfo);
+-void     XGI_GetVBType(PVB_DEVICE_INFO  pVBInfo);
+-void     XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO  pVBInfo);
+-void     XGI_GetTVInfo(unsigned short ModeNo, unsigned short ModeIdIndex,PVB_DEVICE_INFO  pVBInfo);
+-void     XGI_SetCRT2ECLK(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,PVB_DEVICE_INFO  pVBInfo);
+-void     InitTo330Pointer(unsigned char, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_GetLCDSync(unsigned short *HSyncWidth, unsigned short *VSyncWidth, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_DisableBridge(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_EnableBridge(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetCRT2VCLK(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_OEM310Setting(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetDelayComp(PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetLCDCap(PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetLCDCap_A(unsigned short tempcx,PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetLCDCap_B(unsigned short tempcx,PVB_DEVICE_INFO pVBInfo);
+-void     SetSpectrum(PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetAntiFlicker(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetEdgeEnhance(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetPhaseIncr(PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetYFilter(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
++			       struct vb_device_info *pVBInfo);
++void     XGI_VBLongWait(struct vb_device_info *pVBInfo);
++void     XGI_SaveCRT2Info(unsigned short ModeNo, struct vb_device_info *pVBInfo);
++void     XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
++void     XGI_GetCRT2ResInfo(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
++void     XGI_PreSetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
++void     XGI_SetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
++void     XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
++void     XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
++void     XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
++void     XGI_SetGroup3(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
++void     XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
++void     XGI_SetGroup5(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
++void     *XGI_GetLcdPtr(unsigned short BX,  unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
++void     *XGI_GetTVPtr(unsigned short BX, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
++void     XGI_FirePWDEnable(struct vb_device_info *pVBInfo);
++void     XGI_EnableGatingCRT(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
++void     XGI_DisableGatingCRT(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
++void     XGI_SetPanelDelay(unsigned short tempbl, struct vb_device_info *pVBInfo);
++void     XGI_SetPanelPower(unsigned short tempah, unsigned short tempbl, struct vb_device_info *pVBInfo);
++void     XGI_EnablePWD(struct vb_device_info *pVBInfo);
++void     XGI_DisablePWD(struct vb_device_info *pVBInfo);
++void     XGI_AutoThreshold(struct vb_device_info *pVBInfo);
++void     XGI_SetTap4Regs(struct vb_device_info *pVBInfo);
++
++void     XGI_DisplayOn(struct xgi_hw_device_info *, struct vb_device_info *pVBInfo);
++void     XGI_DisplayOff(struct xgi_hw_device_info *, struct vb_device_info *pVBInfo);
++void     XGI_SetCRT1Group(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
++void     XGI_SetXG21CRTC(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
++void     XGI_SetXG21LCD(struct vb_device_info *pVBInfo, unsigned short RefreshRateTableIndex, unsigned short ModeNo);
++void     XGI_SetXG27CRTC(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
++void     XGI_SetXG27LCD(struct vb_device_info *pVBInfo, unsigned short RefreshRateTableIndex, unsigned short ModeNo);
++void	 XGI_UpdateXG21CRTC(unsigned short ModeNo, struct vb_device_info *pVBInfo, unsigned short RefreshRateTableIndex);
++void     XGI_WaitDisply(struct vb_device_info *pVBInfo);
++void     XGI_SenseCRT1(struct vb_device_info *pVBInfo);
++void     XGI_SetSeqRegs(unsigned short ModeNo, unsigned short StandTableIndex, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
++void     XGI_SetMiscRegs(unsigned short StandTableIndex, struct vb_device_info *pVBInfo);
++void     XGI_SetCRTCRegs(struct xgi_hw_device_info *HwDeviceExtension, unsigned short StandTableIndex, struct vb_device_info *pVBInfo);
++void     XGI_SetATTRegs(unsigned short ModeNo, unsigned short StandTableIndex, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
++void     XGI_SetGRCRegs(unsigned short StandTableIndex, struct vb_device_info *pVBInfo);
++void     XGI_ClearExt1Regs(struct vb_device_info *pVBInfo);
++
++void     XGI_SetSync(unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
++void     XGI_SetCRT1CRTC(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo, struct xgi_hw_device_info *HwDeviceExtension);
++void     XGI_SetCRT1Timing_H(struct vb_device_info *pVBInfo, struct xgi_hw_device_info *HwDeviceExtension);
++void     XGI_SetCRT1Timing_V(unsigned short ModeIdIndex, unsigned short ModeNo, struct vb_device_info *pVBInfo);
++void     XGI_SetCRT1DE(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
++void     XGI_SetCRT1VCLK(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
++void     XGI_SetCRT1FIFO(unsigned short ModeNo, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
++void     XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
++void     XGI_SetVCLKState(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
++
++void     XGI_LoadDAC(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
++void     XGI_WriteDAC(unsigned short dl, unsigned short ah, unsigned short al, unsigned short dh, struct vb_device_info *pVBInfo);
++/*void     XGI_ClearBuffer(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo, struct vb_device_info *pVBInfo);*/
++void     XGI_SetLCDAGroup(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
++void     XGI_GetLVDSResInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
++			    struct vb_device_info *pVBInfo);
++void     XGI_GetLVDSData(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
++void     XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex,
++			 unsigned short RefreshRateTableIndex,
++			 struct xgi_hw_device_info *HwDeviceExtension,
++			 struct vb_device_info *pVBInfo);
++void     XGI_SetLVDSRegs(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
++void     XGI_UpdateModeInfo(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
++void     XGI_GetVGAType(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
++void     XGI_GetVBType(struct vb_device_info *pVBInfo);
++void     XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
++void     XGI_GetTVInfo(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
++void     XGI_SetCRT2ECLK(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
++void     InitTo330Pointer(unsigned char, struct vb_device_info *pVBInfo);
++void     XGI_GetLCDSync(unsigned short *HSyncWidth, unsigned short *VSyncWidth, struct vb_device_info *pVBInfo);
++void     XGI_DisableBridge(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
++void     XGI_EnableBridge(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
++void     XGI_SetCRT2VCLK(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
++void     XGI_OEM310Setting(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
++void     XGI_SetDelayComp(struct vb_device_info *pVBInfo);
++void     XGI_SetLCDCap(struct vb_device_info *pVBInfo);
++void     XGI_SetLCDCap_A(unsigned short tempcx, struct vb_device_info *pVBInfo);
++void     XGI_SetLCDCap_B(unsigned short tempcx, struct vb_device_info *pVBInfo);
++void     SetSpectrum(struct vb_device_info *pVBInfo);
++void     XGI_SetAntiFlicker(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
++void     XGI_SetEdgeEnhance(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
++void     XGI_SetPhaseIncr(struct vb_device_info *pVBInfo);
++void     XGI_SetYFilter(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
+ void     XGI_GetTVPtrIndex2(unsigned short *tempbx, unsigned char* tempcl,
+-			    unsigned char *tempch, PVB_DEVICE_INFO pVBInfo);
+-unsigned short   XGI_GetTVPtrIndex(PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetCRT2ModeRegs(unsigned short ModeNo, struct xgi_hw_device_info *, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_CloseCRTC(struct xgi_hw_device_info *, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_OpenCRTC(struct xgi_hw_device_info *, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_GetRAMDAC2DATA(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_UnLockCRT2(struct xgi_hw_device_info *, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_LockCRT2(struct xgi_hw_device_info *, PVB_DEVICE_INFO pVBInfo);
+-void     XGINew_EnableCRT2(PVB_DEVICE_INFO pVBInfo);
+-void     XGINew_LCD_Wait_Time(unsigned char DelayTime, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_LongWait(PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetCRT1Offset(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
++			    unsigned char *tempch, struct vb_device_info *pVBInfo);
++unsigned short   XGI_GetTVPtrIndex(struct vb_device_info *pVBInfo);
++void     XGI_SetCRT2ModeRegs(unsigned short ModeNo, struct xgi_hw_device_info *, struct vb_device_info *pVBInfo);
++void     XGI_CloseCRTC(struct xgi_hw_device_info *, struct vb_device_info *pVBInfo);
++void     XGI_OpenCRTC(struct xgi_hw_device_info *, struct vb_device_info *pVBInfo);
++void     XGI_GetRAMDAC2DATA(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
++void     XGI_UnLockCRT2(struct xgi_hw_device_info *, struct vb_device_info *pVBInfo);
++void     XGI_LockCRT2(struct xgi_hw_device_info *, struct vb_device_info *pVBInfo);
++void     XGINew_EnableCRT2(struct vb_device_info *pVBInfo);
++void     XGINew_LCD_Wait_Time(unsigned char DelayTime, struct vb_device_info *pVBInfo);
++void     XGI_LongWait(struct vb_device_info *pVBInfo);
++void     XGI_SetCRT1Offset(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
+ void     XGI_GetLCDVCLKPtr(unsigned char *di_0, unsigned char *di_1,
+-			   PVB_DEVICE_INFO pVBInfo);
++			   struct vb_device_info *pVBInfo);
+ unsigned char    XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex,
+ 				unsigned short ModeNo,
+ 				unsigned short ModeIdIndex,
+-				PVB_DEVICE_INFO pVBInfo);
++				struct vb_device_info *pVBInfo);
+ void     XGI_GetVCLKLen(unsigned char tempal, unsigned char *di_0,
+-			unsigned char *di_1, PVB_DEVICE_INFO pVBInfo);
+-unsigned short   XGI_GetLCDCapPtr(PVB_DEVICE_INFO pVBInfo);
+-unsigned short   XGI_GetLCDCapPtr1(PVB_DEVICE_INFO pVBInfo);
+-XGI301C_Tap4TimingStruct *XGI_GetTap4Ptr(unsigned short tempcx, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetXG21FPBits(PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetXG27FPBits(PVB_DEVICE_INFO pVBInfo);
+-unsigned char    XGI_XG21GetPSCValue(PVB_DEVICE_INFO pVBInfo);
+-unsigned char    XGI_XG27GetPSCValue(PVB_DEVICE_INFO pVBInfo);
+-void     XGI_XG21BLSignalVDD(unsigned short tempbh, unsigned short tempbl, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_XG27BLSignalVDD(unsigned short tempbh, unsigned short tempbl, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_XG21SetPanelDelay(unsigned short tempbl, PVB_DEVICE_INFO pVBInfo);
+-unsigned char  XGI_XG21CheckLVDSMode(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetXG21LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
+-void     XGI_SetXG27LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
+-unsigned char  XGI_SetDefaultVCLK(PVB_DEVICE_INFO pVBInfo);
+-
+-extern void ReadVBIOSTablData(unsigned char ChipType, PVB_DEVICE_INFO pVBInfo);
++			unsigned char *di_1, struct vb_device_info *pVBInfo);
++unsigned short   XGI_GetLCDCapPtr(struct vb_device_info *pVBInfo);
++unsigned short   XGI_GetLCDCapPtr1(struct vb_device_info *pVBInfo);
++struct XGI301C_Tap4TimingStruct *XGI_GetTap4Ptr(unsigned short tempcx, struct vb_device_info *pVBInfo);
++void     XGI_SetXG21FPBits(struct vb_device_info *pVBInfo);
++void     XGI_SetXG27FPBits(struct vb_device_info *pVBInfo);
++unsigned char    XGI_XG21GetPSCValue(struct vb_device_info *pVBInfo);
++unsigned char    XGI_XG27GetPSCValue(struct vb_device_info *pVBInfo);
++void     XGI_XG21BLSignalVDD(unsigned short tempbh, unsigned short tempbl, struct vb_device_info *pVBInfo);
++void     XGI_XG27BLSignalVDD(unsigned short tempbh, unsigned short tempbl, struct vb_device_info *pVBInfo);
++void     XGI_XG21SetPanelDelay(unsigned short tempbl, struct vb_device_info *pVBInfo);
++unsigned char  XGI_XG21CheckLVDSMode(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
++void     XGI_SetXG21LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
++void     XGI_SetXG27LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
++unsigned char  XGI_SetDefaultVCLK(struct vb_device_info *pVBInfo);
++
++extern void ReadVBIOSTablData(unsigned char ChipType, struct vb_device_info *pVBInfo);
+ 
+ /* unsigned short XGINew_flag_clearbuffer; 0: no clear frame buffer 1:clear frame buffer */
+ 
+@@ -236,35 +240,35 @@ unsigned short XGINew_VGA_DAC[] = {
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void InitTo330Pointer(unsigned char ChipType, PVB_DEVICE_INFO pVBInfo)
++void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo)
+ {
+-    pVBInfo->SModeIDTable = (XGI_StStruct *) XGI330_SModeIDTable ;
+-    pVBInfo->StandTable = (XGI_StandTableStruct *) XGI330_StandTable ;
+-    pVBInfo->EModeIDTable = (XGI_ExtStruct *) XGI330_EModeIDTable ;
+-    pVBInfo->RefIndex = (XGI_Ext2Struct *) XGI330_RefIndex ;
+-    pVBInfo->XGINEWUB_CRT1Table = (XGI_CRT1TableStruct *) XGI_CRT1Table ;
++    pVBInfo->SModeIDTable = (struct XGI_StStruct *) XGI330_SModeIDTable ;
++    pVBInfo->StandTable = (struct XGI_StandTableStruct *) XGI330_StandTable ;
++    pVBInfo->EModeIDTable = (struct XGI_ExtStruct *) XGI330_EModeIDTable ;
++    pVBInfo->RefIndex = (struct XGI_Ext2Struct *) XGI330_RefIndex ;
++    pVBInfo->XGINEWUB_CRT1Table = (struct XGI_CRT1TableStruct *) XGI_CRT1Table ;
+ 
+     /* add for new UNIVGABIOS */
+-    /* XGINew_UBLCDDataTable = (XGI_LCDDataTablStruct *) XGI_LCDDataTable ; */
++    /* XGINew_UBLCDDataTable = (struct XGI_LCDDataTablStruct *) XGI_LCDDataTable ; */
+     /* XGINew_UBTVDataTable = (XGI_TVDataTablStruct *) XGI_TVDataTable ; */
+ 
+ 
+     if ( ChipType >= XG40 )
+     {
+-        pVBInfo->MCLKData = (XGI_MCLKDataStruct *) XGI340New_MCLKData ;
+-        pVBInfo->ECLKData = (XGI_ECLKDataStruct *) XGI340_ECLKData ;
++	pVBInfo->MCLKData = (struct XGI_MCLKDataStruct *) XGI340New_MCLKData;
++	pVBInfo->ECLKData = (struct XGI_ECLKDataStruct *) XGI340_ECLKData;
+     }
+     else
+     {
+-        pVBInfo->MCLKData = (XGI_MCLKDataStruct *) XGI330New_MCLKData ;
+-        pVBInfo->ECLKData = (XGI_ECLKDataStruct *) XGI330_ECLKData ;
++	pVBInfo->MCLKData = (struct XGI_MCLKDataStruct *) XGI330New_MCLKData;
++	pVBInfo->ECLKData = (struct XGI_ECLKDataStruct *) XGI330_ECLKData;
+     }
+ 
+-    pVBInfo->VCLKData = (XGI_VCLKDataStruct *) XGI_VCLKData ;
+-    pVBInfo->VBVCLKData = (XGI_VBVCLKDataStruct *) XGI_VBVCLKData ;
++    pVBInfo->VCLKData = (struct XGI_VCLKDataStruct *) XGI_VCLKData ;
++    pVBInfo->VBVCLKData = (struct XGI_VBVCLKDataStruct *) XGI_VBVCLKData ;
+     pVBInfo->ScreenOffset = XGI330_ScreenOffset ;
+-    pVBInfo->StResInfo = (XGI_StResInfoStruct *) XGI330_StResInfo ;
+-    pVBInfo->ModeResInfo = (XGI_ModeResInfoStruct *) XGI330_ModeResInfo ;
++    pVBInfo->StResInfo = (struct XGI_StResInfoStruct *) XGI330_StResInfo ;
++    pVBInfo->ModeResInfo = (struct XGI_ModeResInfoStruct *) XGI330_ModeResInfo ;
+ 
+     pVBInfo->pOutputSelect = &XGI330_OutputSelect ;
+     pVBInfo->pSoftSetting = &XGI330_SoftSetting ;
+@@ -328,9 +332,9 @@ void InitTo330Pointer(unsigned char ChipType, PVB_DEVICE_INFO pVBInfo)
+     pVBInfo->Ren750pGroup3 = XGI330_Ren750pGroup3 ;
+ 
+ 
+-    pVBInfo->TimingH = (XGI_TimingHStruct *) XGI_TimingH ;
+-    pVBInfo->TimingV = (XGI_TimingVStruct *) XGI_TimingV ;
+-    pVBInfo->UpdateCRT1 = (XGI_XG21CRT1Struct *) XGI_UpdateCRT1Table ;
++    pVBInfo->TimingH = (struct XGI_TimingHStruct *) XGI_TimingH ;
++    pVBInfo->TimingV = (struct XGI_TimingVStruct *) XGI_TimingV ;
++    pVBInfo->UpdateCRT1 = (struct XGI_XG21CRT1Struct *) XGI_UpdateCRT1Table ;
+ 
+     pVBInfo->CHTVVCLKUNTSC = XGI330_CHTVVCLKUNTSC ;
+     pVBInfo->CHTVVCLKONTSC = XGI330_CHTVVCLKONTSC ;
+@@ -357,7 +361,7 @@ void InitTo330Pointer(unsigned char ChipType, PVB_DEVICE_INFO pVBInfo)
+ 
+     if ( ChipType == XG27 )
+     {
+-        pVBInfo->MCLKData = (XGI_MCLKDataStruct *) XGI27New_MCLKData ;
++	pVBInfo->MCLKData = (struct XGI_MCLKDataStruct *) XGI27New_MCLKData;
+         pVBInfo->CR40 = XGI27_cr41 ;
+     	pVBInfo->pXGINew_CR97 = &XG27_CR97 ;
+     	pVBInfo->pSR36 = &XG27_SR36 ;
+@@ -396,8 +400,8 @@ unsigned char XGISetModeNew(struct xgi_hw_device_info *HwDeviceExtension,
+ {
+     unsigned short ModeIdIndex ;
+         /* unsigned char *pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ; */
+-    VB_DEVICE_INFO VBINF;
+-    PVB_DEVICE_INFO pVBInfo = &VBINF;
++    struct vb_device_info VBINF;
++    struct vb_device_info *pVBInfo = &VBINF;
+     pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+     pVBInfo->BaseAddr = (unsigned long)HwDeviceExtension->pjIOAddress ;
+     pVBInfo->IF_DEF_LVDS = 0 ;
+@@ -617,7 +621,7 @@ unsigned char XGISetModeNew(struct xgi_hw_device_info *HwDeviceExtension,
+ /* --------------------------------------------------------------------- */
+ void XGI_SetCRT1Group(struct xgi_hw_device_info *HwDeviceExtension,
+ 		      unsigned short ModeNo,
+-		      unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
++		      unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
+ {
+     unsigned short StandTableIndex ,
+            RefreshRateTableIndex ,
+@@ -738,7 +742,7 @@ void XGI_SetCRT1Group(struct xgi_hw_device_info *HwDeviceExtension,
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ unsigned char XGI_GetModePtr(unsigned short ModeNo, unsigned short ModeIdIndex,
+-		     PVB_DEVICE_INFO pVBInfo)
++		     struct vb_device_info *pVBInfo)
+ {
+     unsigned char index ;
+ 
+@@ -786,7 +790,7 @@ unsigned char XGI_GetModePtr(unsigned short ModeNo, unsigned short ModeIdIndex,
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ void XGI_SetSeqRegs(unsigned short ModeNo, unsigned short StandTableIndex,
+-		    unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
++		    unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
+ {
+     unsigned char tempah ,
+           SRdata ;
+@@ -833,7 +837,7 @@ void XGI_SetSeqRegs(unsigned short ModeNo, unsigned short StandTableIndex,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetMiscRegs(unsigned short StandTableIndex, PVB_DEVICE_INFO pVBInfo )
++void XGI_SetMiscRegs(unsigned short StandTableIndex, struct vb_device_info *pVBInfo)
+ {
+     unsigned char Miscdata ;
+ 
+@@ -859,7 +863,7 @@ void XGI_SetMiscRegs(unsigned short StandTableIndex, PVB_DEVICE_INFO pVBInfo )
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ void XGI_SetCRTCRegs(struct xgi_hw_device_info *HwDeviceExtension,
+-		     unsigned short StandTableIndex, PVB_DEVICE_INFO pVBInfo)
++		     unsigned short StandTableIndex, struct vb_device_info *pVBInfo)
+ {
+     unsigned char CRTCdata ;
+     unsigned short i ;
+@@ -895,7 +899,7 @@ void XGI_SetCRTCRegs(struct xgi_hw_device_info *HwDeviceExtension,
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ void XGI_SetATTRegs(unsigned short ModeNo, unsigned short StandTableIndex,
+-		    unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
++		    unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
+ {
+     unsigned char ARdata ;
+     unsigned short i, modeflag;
+@@ -944,7 +948,7 @@ void XGI_SetATTRegs(unsigned short ModeNo, unsigned short StandTableIndex,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetGRCRegs(unsigned short StandTableIndex, PVB_DEVICE_INFO pVBInfo )
++void XGI_SetGRCRegs(unsigned short StandTableIndex, struct vb_device_info *pVBInfo)
+ {
+     unsigned char GRdata ;
+     unsigned short i ;
+@@ -970,7 +974,7 @@ void XGI_SetGRCRegs(unsigned short StandTableIndex, PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_ClearExt1Regs(PVB_DEVICE_INFO pVBInfo)
++void XGI_ClearExt1Regs(struct vb_device_info *pVBInfo)
+ {
+     unsigned short i ;
+ 
+@@ -985,7 +989,7 @@ void XGI_ClearExt1Regs(PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGI_SetDefaultVCLK(PVB_DEVICE_INFO pVBInfo)
++unsigned char XGI_SetDefaultVCLK(struct vb_device_info *pVBInfo)
+ {
+ 
+     XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x31 , ~0x30 , 0x20 ) ;
+@@ -1010,7 +1014,7 @@ unsigned char XGI_SetDefaultVCLK(PVB_DEVICE_INFO pVBInfo)
+ unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
+ 				  unsigned short ModeNo,
+ 				  unsigned short ModeIdIndex,
+-				  PVB_DEVICE_INFO pVBInfo)
++				  struct vb_device_info *pVBInfo)
+ {
+     short LCDRefreshIndex[] = { 0x00 , 0x00 , 0x03 , 0x01 } ,
+            LCDARefreshIndex[] = { 0x00 , 0x00 , 0x03 , 0x01 , 0x01 , 0x01 , 0x01 } ;
+@@ -1148,7 +1152,7 @@ unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
+ /* --------------------------------------------------------------------- */
+ unsigned char XGI_AjustCRT2Rate(unsigned short ModeNo, unsigned short ModeIdIndex,
+ 				unsigned short RefreshRateTableIndex,
+-				unsigned short *i, PVB_DEVICE_INFO pVBInfo)
++				unsigned short *i, struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempax, tempbx, resinfo, modeflag, infoflag;
+ 
+@@ -1320,7 +1324,7 @@ unsigned char XGI_AjustCRT2Rate(unsigned short ModeNo, unsigned short ModeIdInde
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetSync(unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
++void XGI_SetSync(unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo)
+ {
+     unsigned short sync ,
+            temp ;
+@@ -1341,7 +1345,7 @@ void XGI_SetSync(unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+ /* --------------------------------------------------------------------- */
+ void XGI_SetCRT1CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
+ 		     unsigned short RefreshRateTableIndex,
+-		     PVB_DEVICE_INFO pVBInfo,
++		     struct vb_device_info *pVBInfo,
+ 		     struct xgi_hw_device_info *HwDeviceExtension)
+ {
+     unsigned char index, data;
+@@ -1378,7 +1382,7 @@ void XGI_SetCRT1CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetCRT1Timing_H(PVB_DEVICE_INFO pVBInfo, struct xgi_hw_device_info *HwDeviceExtension)
++void XGI_SetCRT1Timing_H(struct vb_device_info *pVBInfo, struct xgi_hw_device_info *HwDeviceExtension)
+ {
+     unsigned char data, data1, pushax;
+     unsigned short i, j;
+@@ -1452,7 +1456,7 @@ void XGI_SetCRT1Timing_H(PVB_DEVICE_INFO pVBInfo, struct xgi_hw_device_info *HwD
+ /* --------------------------------------------------------------------- */
+ void XGI_SetCRT1Timing_V(unsigned short ModeIdIndex,
+ 			 unsigned short ModeNo,
+-			 PVB_DEVICE_INFO pVBInfo)
++			 struct vb_device_info *pVBInfo)
+ {
+     unsigned char data;
+     unsigned short i, j;
+@@ -1514,7 +1518,7 @@ void XGI_SetCRT1Timing_V(unsigned short ModeIdIndex,
+ /* --------------------------------------------------------------------- */
+ void XGI_SetXG21CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
+ 		     unsigned short RefreshRateTableIndex,
+-		     PVB_DEVICE_INFO pVBInfo)
++		     struct vb_device_info *pVBInfo)
+ {
+   unsigned char StandTableIndex, index, Tempax, Tempbx, Tempcx, Tempdx;
+   unsigned short Temp1, Temp2, Temp3;
+@@ -1655,7 +1659,7 @@ void XGI_SetXG21CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
+ 
+ void XGI_SetXG27CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
+ 		     unsigned short RefreshRateTableIndex,
+-		     PVB_DEVICE_INFO pVBInfo)
++		     struct vb_device_info *pVBInfo)
+ {
+ 	unsigned short StandTableIndex, index, Tempax, Tempbx, Tempcx, Tempdx;
+ 
+@@ -1778,7 +1782,7 @@ void XGI_SetXG27CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
+ /* Output : FCLK duty cycle, FCLK delay compensation */
+ /* Description : All values set zero */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetXG21LCD(PVB_DEVICE_INFO pVBInfo,
++void XGI_SetXG21LCD(struct vb_device_info *pVBInfo,
+ 		    unsigned short RefreshRateTableIndex,
+ 		    unsigned short ModeNo)
+ {
+@@ -1830,7 +1834,7 @@ void XGI_SetXG21LCD(PVB_DEVICE_INFO pVBInfo,
+   }
+ }
+ 
+-void XGI_SetXG27LCD(PVB_DEVICE_INFO pVBInfo,
++void XGI_SetXG27LCD(struct vb_device_info *pVBInfo,
+ 		    unsigned short RefreshRateTableIndex,
+ 		    unsigned short ModeNo)
+ {
+@@ -1891,7 +1895,7 @@ void XGI_SetXG27LCD(PVB_DEVICE_INFO pVBInfo,
+ /* Description : Modify CRT1 Hsync/Vsync to fix LCD mode timing */
+ /* --------------------------------------------------------------------- */
+ void XGI_UpdateXG21CRTC(unsigned short ModeNo,
+-			PVB_DEVICE_INFO pVBInfo,
++			struct vb_device_info *pVBInfo,
+ 			unsigned short RefreshRateTableIndex)
+ {
+   int i , index = -1;
+@@ -1939,7 +1943,7 @@ void XGI_SetCRT1DE(struct xgi_hw_device_info *HwDeviceExtension,
+ 		   unsigned short ModeNo,
+ 		   unsigned short ModeIdIndex,
+ 		   unsigned short RefreshRateTableIndex,
+-		   PVB_DEVICE_INFO pVBInfo)
++		   struct vb_device_info *pVBInfo)
+ {
+ 	unsigned short resindex, tempax, tempbx, tempcx, temp, modeflag;
+ 
+@@ -2023,7 +2027,7 @@ void XGI_SetCRT1DE(struct xgi_hw_device_info *HwDeviceExtension,
+ /* --------------------------------------------------------------------- */
+ unsigned short XGI_GetResInfo(unsigned short ModeNo,
+ 			      unsigned short ModeIdIndex,
+-			      PVB_DEVICE_INFO pVBInfo)
++			      struct vb_device_info *pVBInfo)
+ {
+ 	unsigned short resindex;
+ 
+@@ -2049,7 +2053,7 @@ void XGI_SetCRT1Offset(unsigned short ModeNo,
+ 		       unsigned short ModeIdIndex,
+ 		       unsigned short RefreshRateTableIndex,
+ 		       struct xgi_hw_device_info *HwDeviceExtension,
+-		       PVB_DEVICE_INFO pVBInfo)
++		       struct vb_device_info *pVBInfo)
+ {
+     unsigned short temp ,
+            ah ,
+@@ -2145,7 +2149,7 @@ void XGI_SetCRT1Offset(unsigned short ModeNo,
+ void XGI_SetCRT1VCLK(unsigned short ModeNo, unsigned short ModeIdIndex,
+ 		     struct xgi_hw_device_info *HwDeviceExtension,
+ 		     unsigned short RefreshRateTableIndex,
+-		     PVB_DEVICE_INFO pVBInfo)
++		     struct vb_device_info *pVBInfo)
+ {
+ 	unsigned char index, data;
+     unsigned short vclkindex ;
+@@ -2207,7 +2211,7 @@ void XGI_SetCRT1VCLK(unsigned short ModeNo, unsigned short ModeIdIndex,
+ /* --------------------------------------------------------------------- */
+ void XGI_SetCRT1FIFO(unsigned short ModeNo,
+ 		     struct xgi_hw_device_info *HwDeviceExtension,
+-		     PVB_DEVICE_INFO pVBInfo)
++		     struct vb_device_info *pVBInfo)
+ {
+     unsigned short data ;
+ 
+@@ -2259,7 +2263,7 @@ void XGI_SetCRT1FIFO(unsigned short ModeNo,
+ void XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension,
+ 			 unsigned short ModeNo, unsigned short ModeIdIndex,
+ 			 unsigned short RefreshRateTableIndex,
+-			 PVB_DEVICE_INFO pVBInfo)
++			 struct vb_device_info *pVBInfo)
+ {
+     unsigned short data ,
+            data2 ,
+@@ -2399,7 +2403,7 @@ void XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension,
+ void XGI_SetVCLKState(struct xgi_hw_device_info *HwDeviceExtension,
+ 		      unsigned short ModeNo,
+ 		      unsigned short RefreshRateTableIndex,
+-		      PVB_DEVICE_INFO pVBInfo)
++		      struct vb_device_info *pVBInfo)
+ {
+     unsigned short data ,
+            data2 = 0 ;
+@@ -2463,7 +2467,7 @@ void XGI_SetVCLKState(struct xgi_hw_device_info *HwDeviceExtension,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-/*void XGI_VesaLowResolution(unsigned short ModeNo , unsigned short ModeIdIndex ,PVB_DEVICE_INFO pVBInfo)
++/*void XGI_VesaLowResolution(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
+ {
+     unsigned short modeflag;
+ 
+@@ -2508,7 +2512,7 @@ void XGI_SetVCLKState(struct xgi_hw_device_info *HwDeviceExtension,
+ /* --------------------------------------------------------------------- */
+ void XGI_LoadDAC(unsigned short ModeNo,
+ 		 unsigned short ModeIdIndex,
+-		 PVB_DEVICE_INFO pVBInfo)
++		 struct vb_device_info *pVBInfo)
+ {
+     unsigned short data , data2 , time ,
+            i  , j , k , m , n , o ,
+@@ -2619,7 +2623,7 @@ void XGI_LoadDAC(unsigned short ModeNo,
+ /* --------------------------------------------------------------------- */
+ void XGI_WriteDAC(unsigned short dl, unsigned short ah,
+ 		  unsigned short al, unsigned short dh,
+-		  PVB_DEVICE_INFO pVBInfo)
++		  struct vb_device_info *pVBInfo)
+ {
+     unsigned short temp , bh , bl ;
+ 
+@@ -2658,7 +2662,7 @@ void XGI_WriteDAC(unsigned short dl, unsigned short ah,
+ void XGI_SetLCDAGroup(unsigned short ModeNo,
+ 		      unsigned short ModeIdIndex,
+ 		      struct xgi_hw_device_info *HwDeviceExtension,
+-		      PVB_DEVICE_INFO  pVBInfo)
++		      struct vb_device_info *pVBInfo)
+ {
+     unsigned short RefreshRateTableIndex ;
+     /* unsigned short temp ; */
+@@ -2683,7 +2687,7 @@ void XGI_SetLCDAGroup(unsigned short ModeNo,
+ /* --------------------------------------------------------------------- */
+ void XGI_GetLVDSResInfo(unsigned short ModeNo,
+ 			unsigned short ModeIdIndex,
+-			PVB_DEVICE_INFO  pVBInfo)
++			struct vb_device_info *pVBInfo)
+ {
+     unsigned short resindex , xres , yres , modeflag ;
+ 
+@@ -2754,17 +2758,17 @@ void XGI_GetLVDSResInfo(unsigned short ModeNo,
+ void XGI_GetLVDSData(unsigned short ModeNo,
+ 		     unsigned short ModeIdIndex,
+ 		     unsigned short RefreshRateTableIndex,
+-		     PVB_DEVICE_INFO pVBInfo)
++		     struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempbx ;
+-    XGI330_LVDSDataStruct *LCDPtr = NULL ;
+-    XGI330_CHTVDataStruct  *TVPtr = NULL ;
++    struct XGI330_LVDSDataStruct *LCDPtr = NULL ;
++    struct XGI330_CHTVDataStruct  *TVPtr = NULL ;
+ 
+     tempbx = 2 ;
+ 
+     if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+     {
+-        LCDPtr = ( XGI330_LVDSDataStruct * )XGI_GetLcdPtr( tempbx, ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo) ;
++	LCDPtr = (struct XGI330_LVDSDataStruct *)XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+         pVBInfo->VGAHT = LCDPtr->VGAHT ;
+         pVBInfo->VGAVT = LCDPtr->VGAVT ;
+         pVBInfo->HT = LCDPtr->LCDHT ;
+@@ -2774,7 +2778,7 @@ void XGI_GetLVDSData(unsigned short ModeNo,
+     {
+         if ( pVBInfo->VBInfo & SetCRT2ToTV )
+         {
+-            TVPtr = ( XGI330_CHTVDataStruct * )XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
++	    TVPtr = (struct XGI330_CHTVDataStruct *)XGI_GetTVPtr(tempbx, ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+             pVBInfo->VGAHT = TVPtr->VGAHT ;
+             pVBInfo->VGAVT = TVPtr->VGAVT ;
+             pVBInfo->HT = TVPtr->LCDHT ;
+@@ -2820,15 +2824,15 @@ void XGI_GetLVDSData(unsigned short ModeNo,
+ void XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex,
+ 		     unsigned short RefreshRateTableIndex,
+ 		     struct xgi_hw_device_info *HwDeviceExtension,
+-		     PVB_DEVICE_INFO pVBInfo)
++		     struct vb_device_info *pVBInfo)
+ {
+     unsigned char index;
+     unsigned short tempbx , i ;
+-    XGI_LVDSCRT1HDataStruct  *LCDPtr = NULL ;
+-    XGI_LVDSCRT1VDataStruct  *LCDPtr1 =NULL ;
+-    /* XGI330_CHTVDataStruct *TVPtr = NULL ; */
+-    XGI_CH7007TV_TimingHStruct *CH7007TV_TimingHPtr = NULL;
+-    XGI_CH7007TV_TimingVStruct *CH7007TV_TimingVPtr = NULL;
++    struct XGI_LVDSCRT1HDataStruct  *LCDPtr = NULL;
++    struct XGI_LVDSCRT1VDataStruct  *LCDPtr1 = NULL;
++    /* struct XGI330_CHTVDataStruct *TVPtr = NULL ; */
++    struct XGI_CH7007TV_TimingHStruct *CH7007TV_TimingHPtr = NULL;
++    struct XGI_CH7007TV_TimingVStruct *CH7007TV_TimingVPtr = NULL;
+ 
+     if( ModeNo <= 0x13 )
+         index = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ;
+@@ -2843,7 +2847,7 @@ void XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex,
+ 
+         if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+         {
+-            LCDPtr = ( XGI_LVDSCRT1HDataStruct * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
++	    LCDPtr = (struct XGI_LVDSCRT1HDataStruct *)XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+ 
+             for( i = 0 ; i < 8 ; i++ )
+                 pVBInfo->TimingH[ 0 ].data[ i ] = LCDPtr[ 0 ].Reg[ i ] ;
+@@ -2853,7 +2857,7 @@ void XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex,
+         {
+             if ( pVBInfo->VBInfo & SetCRT2ToTV )
+             {
+-                CH7007TV_TimingHPtr = ( XGI_CH7007TV_TimingHStruct *)XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
++		CH7007TV_TimingHPtr = (struct XGI_CH7007TV_TimingHStruct *)XGI_GetTVPtr(tempbx, ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+ 
+                 for( i = 0 ; i < 8 ; i++ )
+                     pVBInfo->TimingH[ 0 ].data[ i ] = CH7007TV_TimingHPtr[ 0 ].data[ i ] ;
+@@ -2863,7 +2867,7 @@ void XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex,
+         /* if ( pVBInfo->IF_DEF_CH7017 == 1 )
+         {
+             if ( pVBInfo->VBInfo & SetCRT2ToTV )
+-                TVPtr = ( XGI330_CHTVDataStruct *)XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
++		TVPtr = ( struct XGI330_CHTVDataStruct *)XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+         } */
+ 
+         XGI_SetCRT1Timing_H(pVBInfo,HwDeviceExtension) ;
+@@ -2878,7 +2882,7 @@ void XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex,
+ 
+         if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+         {
+-            LCDPtr1 = ( XGI_LVDSCRT1VDataStruct * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
++	    LCDPtr1 = (struct XGI_LVDSCRT1VDataStruct *)XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+             for( i = 0 ; i < 7 ; i++ )
+                 pVBInfo->TimingV[ 0 ].data[ i ] = LCDPtr1[ 0 ].Reg[ i ] ;
+         }
+@@ -2887,7 +2891,7 @@ void XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex,
+         {
+             if ( pVBInfo->VBInfo & SetCRT2ToTV )
+             {
+-                CH7007TV_TimingVPtr = ( XGI_CH7007TV_TimingVStruct *)XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
++		CH7007TV_TimingVPtr = (struct XGI_CH7007TV_TimingVStruct *)XGI_GetTVPtr(tempbx, ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+ 
+                 for( i = 0 ; i < 7 ; i++ )
+                     pVBInfo->TimingV[ 0 ].data[ i ] = CH7007TV_TimingVPtr[ 0 ].data[ i ] ;
+@@ -2896,7 +2900,7 @@ void XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex,
+         /* if ( pVBInfo->IF_DEF_CH7017 == 1 )
+         {
+             if ( pVBInfo->VBInfo & SetCRT2ToTV )
+-                TVPtr = ( XGI330_CHTVDataStruct *)XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
++		TVPtr = ( struct XGI330_CHTVDataStruct *)XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+         } */
+ 
+         XGI_SetCRT1Timing_V( ModeIdIndex , ModeNo , pVBInfo) ;
+@@ -2921,12 +2925,12 @@ void XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex,
+ /* --------------------------------------------------------------------- */
+ void XGI_SetLVDSRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
+ 		     unsigned short RefreshRateTableIndex,
+-		     PVB_DEVICE_INFO pVBInfo)
++		     struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempbx , tempax , tempcx , tempdx , push1 , push2 , modeflag ;
+     unsigned long temp , temp1 , temp2 , temp3 , push3 ;
+-    XGI330_LCDDataDesStruct  *LCDPtr = NULL ;
+-    XGI330_LCDDataDesStruct2  *LCDPtr1 = NULL ;
++    struct XGI330_LCDDataDesStruct  *LCDPtr = NULL ;
++    struct XGI330_LCDDataDesStruct2  *LCDPtr1 = NULL ;
+ 
+     if ( ModeNo > 0x13 )
+         modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+@@ -2940,16 +2944,16 @@ void XGI_SetLVDSRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
+             if ( pVBInfo->IF_DEF_OEMUtil == 1 )
+             {
+     	        tempbx = 8 ;
+-    	        LCDPtr = ( XGI330_LCDDataDesStruct * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
++		LCDPtr = (struct XGI330_LCDDataDesStruct *)XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+             }
+ 
+             if ( ( pVBInfo->IF_DEF_OEMUtil == 0 ) || ( LCDPtr == 0 ) )
+             {
+                 tempbx = 3 ;
+                 if ( pVBInfo->LCDInfo & EnableScalingLCD )
+-                    LCDPtr1 = ( XGI330_LCDDataDesStruct2 * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
++		    LCDPtr1 = (struct XGI330_LCDDataDesStruct2 *)XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+                 else
+-                    LCDPtr = ( XGI330_LCDDataDesStruct * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
++		    LCDPtr = (struct XGI330_LCDDataDesStruct *)XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+             }
+ 
+             XGI_GetLCDSync( &tempax , &tempbx ,pVBInfo) ;
+@@ -3187,7 +3191,7 @@ void XGI_SetLVDSRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetCRT2ECLK(unsigned short ModeNo , unsigned short ModeIdIndex , unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO  pVBInfo )
++void XGI_SetCRT2ECLK(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo)
+ {
+     unsigned char di_0, di_1, tempal;
+     int i ;
+@@ -3224,7 +3228,7 @@ void XGI_SetCRT2ECLK(unsigned short ModeNo , unsigned short ModeIdIndex , unsign
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_UpdateModeInfo(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO  pVBInfo)
++void XGI_UpdateModeInfo(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempcl ,
+            tempch ,
+@@ -3332,7 +3336,7 @@ void XGI_UpdateModeInfo(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_GetVGAType(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO  pVBInfo)
++void XGI_GetVGAType(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+     /*
+     if ( HwDeviceExtension->jChipType >= XG20 )
+@@ -3354,7 +3358,7 @@ void XGI_GetVGAType(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INF
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_GetVBType(PVB_DEVICE_INFO  pVBInfo)
++void XGI_GetVBType(struct vb_device_info *pVBInfo)
+ {
+     unsigned short flag , tempbx , tempah ;
+ 
+@@ -3417,7 +3421,7 @@ void XGI_GetVBType(PVB_DEVICE_INFO  pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO  pVBInfo)
++void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempax ,
+            push ,
+@@ -3658,7 +3662,7 @@ void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_GetTVInfo(unsigned short ModeNo , unsigned short ModeIdIndex ,PVB_DEVICE_INFO  pVBInfo )
++void XGI_GetTVInfo(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
+ {
+     unsigned short temp ,
+            tempbx = 0 ,
+@@ -3794,7 +3798,7 @@ void XGI_GetTVInfo(unsigned short ModeNo , unsigned short ModeIdIndex ,PVB_DEVIC
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ unsigned char XGI_GetLCDInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
+-			     PVB_DEVICE_INFO pVBInfo)
++			     struct vb_device_info *pVBInfo)
+ {
+     unsigned short temp ,
+            tempax ,
+@@ -4005,7 +4009,7 @@ unsigned char XGI_GetLCDInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
+ /* --------------------------------------------------------------------- */
+ unsigned char XGI_SearchModeID(unsigned short ModeNo,
+ 			       unsigned short *ModeIdIndex,
+-			       PVB_DEVICE_INFO pVBInfo)
++			       struct vb_device_info *pVBInfo)
+ {
+ 
+ 
+@@ -4016,7 +4020,7 @@ unsigned char XGI_SearchModeID(unsigned short ModeNo,
+         ModeNo |= 1 ;
+     if ( ModeNo <= 0x13 )
+     {
+-        /* for (*ModeIdIndex=0;*ModeIdIndexSModeIDTable)/sizeof(XGI_StStruct);(*ModeIdIndex)++) */
++	/* for (*ModeIdIndex=0;*ModeIdIndexSModeIDTable)/sizeof(struct XGI_StStruct);(*ModeIdIndex)++) */
+         for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ )
+         {
+ 		if (pVBInfo->SModeIDTable[*ModeIdIndex].St_ModeID == ModeNo)
+@@ -4034,7 +4038,7 @@ unsigned char XGI_SearchModeID(unsigned short ModeNo,
+     }
+     else
+     {
+-        /* for (*ModeIdIndex=0;*ModeIdIndexEModeIDTable)/sizeof(XGI_ExtStruct);(*ModeIdIndex)++) */
++	/* for (*ModeIdIndex=0;*ModeIdIndexEModeIDTable)/sizeof(struct XGI_ExtStruct);(*ModeIdIndex)++) */
+         for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ )
+         {
+ 		if (pVBInfo->EModeIDTable[*ModeIdIndex].Ext_ModeID == ModeNo)
+@@ -4063,7 +4067,7 @@ unsigned char XGI_SearchModeID(unsigned short ModeNo,
+ unsigned char XGINew_CheckMemorySize(struct xgi_hw_device_info *HwDeviceExtension,
+ 				     unsigned short ModeNo,
+ 				     unsigned short ModeIdIndex,
+-				     PVB_DEVICE_INFO pVBInfo)
++				     struct vb_device_info *pVBInfo)
+ {
+     unsigned short memorysize ,
+            modeflag ,
+@@ -4145,7 +4149,7 @@ unsigned char XGINew_CheckMemorySize(struct xgi_hw_device_info *HwDeviceExtensio
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-/*void XGINew_IsLowResolution(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned char XGINew_CheckMemorySize(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
++/*void XGINew_IsLowResolution(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned char XGINew_CheckMemorySize(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
+ {
+     unsigned short data ;
+     unsigned short ModeFlag ;
+@@ -4177,7 +4181,7 @@ unsigned char XGINew_CheckMemorySize(struct xgi_hw_device_info *HwDeviceExtensio
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_DisplayOn(struct xgi_hw_device_info *pXGIHWDE, PVB_DEVICE_INFO pVBInfo)
++void XGI_DisplayOn(struct xgi_hw_device_info *pXGIHWDE, struct vb_device_info *pVBInfo)
+ {
+ 
+     XGINew_SetRegANDOR(pVBInfo->P3c4,0x01,0xDF,0x00);
+@@ -4241,7 +4245,7 @@ void XGI_DisplayOn(struct xgi_hw_device_info *pXGIHWDE, PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_DisplayOff(struct xgi_hw_device_info *pXGIHWDE, PVB_DEVICE_INFO pVBInfo)
++void XGI_DisplayOff(struct xgi_hw_device_info *pXGIHWDE, struct vb_device_info *pVBInfo)
+ {
+ 
+     if ( pXGIHWDE->jChipType == XG21 )
+@@ -4289,7 +4293,7 @@ void XGI_DisplayOff(struct xgi_hw_device_info *pXGIHWDE, PVB_DEVICE_INFO pVBInfo
+ /* Output : */
+ /* Description : chiawen for sensecrt1 */
+ /* --------------------------------------------------------------------- */
+-void XGI_WaitDisply( PVB_DEVICE_INFO pVBInfo )
++void XGI_WaitDisply(struct vb_device_info *pVBInfo)
+ {
+     while( ( XGINew_GetReg2( pVBInfo->P3da ) & 0x01 ) )
+         break ;
+@@ -4305,7 +4309,7 @@ void XGI_WaitDisply( PVB_DEVICE_INFO pVBInfo )
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ 
+-void XGI_SenseCRT1( PVB_DEVICE_INFO pVBInfo )
++void XGI_SenseCRT1(struct vb_device_info *pVBInfo)
+ {
+ 	unsigned char CRTCData[17] = {
+ 		0x5F , 0x4F , 0x50 , 0x82 , 0x55 , 0x81 ,
+@@ -4425,7 +4429,7 @@ void XGI_SenseCRT1( PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_WaitDisplay( PVB_DEVICE_INFO pVBInfo )
++void XGI_WaitDisplay(struct vb_device_info *pVBInfo)
+ {
+     while( !( XGINew_GetReg2( pVBInfo->P3da ) & 0x01 ) ) ;
+ 
+@@ -4443,7 +4447,7 @@ void XGI_WaitDisplay( PVB_DEVICE_INFO pVBInfo )
+ /* --------------------------------------------------------------------- */
+ unsigned char XGI_SetCRT2Group301(unsigned short ModeNo,
+ 				  struct xgi_hw_device_info *HwDeviceExtension,
+-				  PVB_DEVICE_INFO pVBInfo)
++				  struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempbx ,
+            ModeIdIndex ,
+@@ -4478,7 +4482,7 @@ unsigned char XGI_SetCRT2Group301(unsigned short ModeNo,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_AutoThreshold(  PVB_DEVICE_INFO pVBInfo )
++void XGI_AutoThreshold(struct vb_device_info *pVBInfo)
+ {
+     if ( !( pVBInfo->SetFlag & Win9xDOSMode ) )
+       XGINew_SetRegOR( pVBInfo->Part1Port , 0x01 , 0x40 ) ;
+@@ -4491,7 +4495,7 @@ void XGI_AutoThreshold(  PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SaveCRT2Info(unsigned short ModeNo , PVB_DEVICE_INFO pVBInfo)
++void XGI_SaveCRT2Info(unsigned short ModeNo, struct vb_device_info *pVBInfo)
+ {
+     unsigned short temp1 ,
+            temp2 ;
+@@ -4511,7 +4515,7 @@ void XGI_SaveCRT2Info(unsigned short ModeNo , PVB_DEVICE_INFO pVBInfo)
+ /* --------------------------------------------------------------------- */
+ void XGI_GetCRT2ResInfo(unsigned short ModeNo,
+ 			unsigned short ModeIdIndex,
+-			PVB_DEVICE_INFO pVBInfo )
++			struct vb_device_info *pVBInfo)
+ {
+     unsigned short xres ,
+            yres ,
+@@ -4608,7 +4612,7 @@ void XGI_GetCRT2ResInfo(unsigned short ModeNo,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGI_IsLCDDualLink(PVB_DEVICE_INFO pVBInfo)
++unsigned char XGI_IsLCDDualLink(struct vb_device_info *pVBInfo)
+ {
+ 
+     if ( ( ( ( pVBInfo->VBInfo & SetCRT2ToLCD ) | SetCRT2ToLCDA ) ) && ( pVBInfo->LCDInfo & SetLCDDualLink ) ) /* shampoo0129 */
+@@ -4624,15 +4628,15 @@ unsigned char XGI_IsLCDDualLink(PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_GetCRT2Data(  unsigned short ModeNo , unsigned short ModeIdIndex , unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
++void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempax = 0,
+            tempbx ,
+            modeflag ,
+            resinfo ;
+ 
+-    XGI_LCDDataStruct *LCDPtr = NULL ;
+-    XGI_TVDataStruct  *TVPtr = NULL ;
++    struct XGI_LCDDataStruct *LCDPtr = NULL ;
++    struct XGI_TVDataStruct  *TVPtr = NULL ;
+ 
+     if ( ModeNo <= 0x13 )
+     {
+@@ -4658,7 +4662,7 @@ void XGI_GetCRT2Data(  unsigned short ModeNo , unsigned short ModeIdIndex , unsi
+ 
+     if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+     {
+-        LCDPtr = (XGI_LCDDataStruct* )XGI_GetLcdPtr( tempbx, ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
++	LCDPtr = (struct XGI_LCDDataStruct *)XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+ 
+         pVBInfo->RVBHCMAX = LCDPtr->RVBHCMAX ;
+         pVBInfo->RVBHCFACT = LCDPtr->RVBHCFACT ;
+@@ -4762,7 +4766,7 @@ void XGI_GetCRT2Data(  unsigned short ModeNo , unsigned short ModeIdIndex , unsi
+     if ( pVBInfo->VBInfo & ( SetCRT2ToTV ) )
+     {
+         tempbx = 4 ;
+-        TVPtr = ( XGI_TVDataStruct * )XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
++	TVPtr = (struct XGI_TVDataStruct *)XGI_GetTVPtr(tempbx, ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+ 
+         pVBInfo->RVBHCMAX = TVPtr->RVBHCMAX ;
+         pVBInfo->RVBHCFACT = TVPtr->RVBHCFACT ;
+@@ -4850,7 +4854,7 @@ void XGI_GetCRT2Data(  unsigned short ModeNo , unsigned short ModeIdIndex , unsi
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetCRT2VCLK(unsigned short ModeNo , unsigned short ModeIdIndex , unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
++void XGI_SetCRT2VCLK(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo)
+ {
+ 	unsigned char di_0, di_1, tempal;
+ 
+@@ -4886,7 +4890,7 @@ void XGI_SetCRT2VCLK(unsigned short ModeNo , unsigned short ModeIdIndex , unsign
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ void XGI_GetLCDVCLKPtr(unsigned char *di_0, unsigned char *di_1,
+-		       PVB_DEVICE_INFO pVBInfo)
++		       struct vb_device_info *pVBInfo)
+ {
+     unsigned short index ;
+ 
+@@ -4924,7 +4928,7 @@ void XGI_GetLCDVCLKPtr(unsigned char *di_0, unsigned char *di_1,
+ /* --------------------------------------------------------------------- */
+ unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex,
+ 			     unsigned short ModeNo, unsigned short ModeIdIndex,
+-			     PVB_DEVICE_INFO pVBInfo)
++			     struct vb_device_info *pVBInfo)
+ {
+ 
+     unsigned short index ,
+@@ -5105,7 +5109,7 @@ unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex,
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ void XGI_GetVCLKLen(unsigned char tempal, unsigned char *di_0,
+-		    unsigned char *di_1, PVB_DEVICE_INFO pVBInfo)
++		    unsigned char *di_1, struct vb_device_info *pVBInfo)
+ {
+     if ( pVBInfo->IF_DEF_CH7007 == 1 ) /* [Billy] 2007/05/16 */
+     {
+@@ -5139,7 +5143,7 @@ void XGI_SetCRT2Offset(unsigned short ModeNo,
+ 		       unsigned short ModeIdIndex,
+ 		       unsigned short RefreshRateTableIndex,
+ 		       struct xgi_hw_device_info *HwDeviceExtension,
+-		       PVB_DEVICE_INFO pVBInfo)
++		       struct vb_device_info *pVBInfo)
+ {
+     unsigned short offset ;
+     unsigned char temp;
+@@ -5165,7 +5169,7 @@ void XGI_SetCRT2Offset(unsigned short ModeNo,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned short XGI_GetOffset(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++unsigned short XGI_GetOffset(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+     unsigned short temp ,
+            colordepth ,
+@@ -5214,7 +5218,7 @@ unsigned short XGI_GetOffset(unsigned short ModeNo, unsigned short ModeIdIndex,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetCRT2FIFO( PVB_DEVICE_INFO pVBInfo)
++void XGI_SetCRT2FIFO(struct vb_device_info *pVBInfo)
+ {
+     XGINew_SetReg1( pVBInfo->Part1Port , 0x01 , 0x3B ) ;			/* threshold high ,disable auto threshold */
+     XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x02 , ~( 0x3F ) , 0x04 ) ;	/* threshold low default 04h */
+@@ -5230,7 +5234,7 @@ void XGI_SetCRT2FIFO( PVB_DEVICE_INFO pVBInfo)
+ void XGI_PreSetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
+ 		      struct xgi_hw_device_info *HwDeviceExtension,
+ 		      unsigned short RefreshRateTableIndex,
+-		      PVB_DEVICE_INFO pVBInfo)
++		      struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempcx = 0 ,
+            CRT1Index = 0 ,
+@@ -5266,7 +5270,7 @@ void XGI_PreSetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
+ void XGI_SetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
+ 		   struct xgi_hw_device_info *HwDeviceExtension,
+ 		   unsigned short RefreshRateTableIndex,
+-		   PVB_DEVICE_INFO pVBInfo)
++		   struct vb_device_info *pVBInfo)
+ {
+     unsigned short temp = 0 ,
+            tempax = 0 ,
+@@ -5444,7 +5448,7 @@ void XGI_SetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
+ void  XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
+ 		      struct xgi_hw_device_info *HwDeviceExtension,
+ 		      unsigned short RefreshRateTableIndex,
+-		      PVB_DEVICE_INFO pVBInfo)
++		      struct vb_device_info *pVBInfo)
+ {
+     unsigned short push1 ,
+            push2 ,
+@@ -5891,7 +5895,7 @@ void  XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,
+-		   struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++		   struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+     unsigned short i ,
+            j ,
+@@ -6409,7 +6413,7 @@ void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned s
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void  XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo)
++void  XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo)
+ {
+     unsigned short push1 ,
+            push2 ,
+@@ -6425,7 +6429,7 @@ void  XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex, struct x
+            modeflag ,
+            CRT1Index ;
+ 
+-    XGI_LCDDesStruct *LCDBDesPtr = NULL ;
++    struct XGI_LCDDesStruct *LCDBDesPtr = NULL ;
+ 
+ 
+     if ( ModeNo <= 0x13 )
+@@ -6495,7 +6499,7 @@ void  XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex, struct x
+ 
+     /* Customized LCDB Des no add */
+     tempbx = 5 ;
+-    LCDBDesPtr = ( XGI_LCDDesStruct * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
++    LCDBDesPtr = (struct XGI_LCDDesStruct *)XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+     tempah = pVBInfo->LCDResInfo ;
+     tempah &= PanelResInfo ;
+ 
+@@ -6663,14 +6667,14 @@ void  XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex, struct x
+ /* Output : di -> Tap4 Reg. Setting Pointer */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-XGI301C_Tap4TimingStruct *XGI_GetTap4Ptr(unsigned short tempcx,
+-					 PVB_DEVICE_INFO pVBInfo)
++struct XGI301C_Tap4TimingStruct *XGI_GetTap4Ptr(unsigned short tempcx,
++					 struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempax ,
+            tempbx ,
+            i ;
+ 
+-    XGI301C_Tap4TimingStruct *Tap4TimingPtr ;
++    struct XGI301C_Tap4TimingStruct *Tap4TimingPtr ;
+ 
+     if ( tempcx == 0 )
+     {
+@@ -6724,12 +6728,12 @@ XGI301C_Tap4TimingStruct *XGI_GetTap4Ptr(unsigned short tempcx,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetTap4Regs( PVB_DEVICE_INFO pVBInfo)
++void XGI_SetTap4Regs(struct vb_device_info *pVBInfo)
+ {
+     unsigned short i ,
+            j ;
+ 
+-    XGI301C_Tap4TimingStruct *Tap4TimingPtr ;
++    struct XGI301C_Tap4TimingStruct *Tap4TimingPtr ;
+ 
+     if ( !( pVBInfo->VBType & VB_XGI301C ) )
+         return ;
+@@ -6762,7 +6766,7 @@ void XGI_SetTap4Regs( PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetGroup3(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
++void XGI_SetGroup3(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
+ {
+     unsigned short i;
+     unsigned char *tempdi;
+@@ -6849,7 +6853,7 @@ void XGI_SetGroup3(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempax ,
+            tempcx ,
+@@ -7100,7 +7104,7 @@ void XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned s
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetGroup5(unsigned short ModeNo , unsigned short ModeIdIndex , PVB_DEVICE_INFO pVBInfo)
++void XGI_SetGroup5(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
+ {
+     unsigned short Pindex ,
+            Pdata ;
+@@ -7129,7 +7133,7 @@ void *XGI_GetLcdPtr(unsigned short BX,
+ 		    unsigned short ModeNo,
+ 		    unsigned short ModeIdIndex,
+ 		    unsigned short RefreshRateTableIndex,
+-		    PVB_DEVICE_INFO pVBInfo)
++		    struct vb_device_info *pVBInfo)
+ {
+     unsigned short i ,
+            tempdx ,
+@@ -7139,7 +7143,7 @@ void *XGI_GetLcdPtr(unsigned short BX,
+            modeflag ,
+            table ;
+ 
+-    XGI330_LCDDataTablStruct *tempdi = 0 ;
++    struct XGI330_LCDDataTablStruct *tempdi = 0 ;
+ 
+ 
+     tempbx = BX;
+@@ -7634,10 +7638,10 @@ void *XGI_GetLcdPtr(unsigned short BX,
+ void *XGI_GetTVPtr(unsigned short BX, unsigned short ModeNo,
+ 		   unsigned short ModeIdIndex,
+ 		   unsigned short RefreshRateTableIndex,
+-		   PVB_DEVICE_INFO pVBInfo)
++		   struct vb_device_info *pVBInfo)
+ {
+     unsigned short i , tempdx , tempbx , tempal , modeflag , table ;
+-    XGI330_TVDataTablStruct *tempdi = 0 ;
++    struct XGI330_TVDataTablStruct *tempdi = 0 ;
+ 
+     tempbx = BX ;
+ 
+@@ -7799,7 +7803,7 @@ void *XGI_GetTVPtr(unsigned short BX, unsigned short ModeNo,
+ /* Output : 1 -> Skip backlight control */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGI_BacklightByDrv(PVB_DEVICE_INFO pVBInfo)
++unsigned char XGI_BacklightByDrv(struct vb_device_info *pVBInfo)
+ {
+     unsigned char tempah ;
+ 
+@@ -7818,7 +7822,7 @@ unsigned char XGI_BacklightByDrv(PVB_DEVICE_INFO pVBInfo)
+ /* Description : Turn off VDD & Backlight : Fire disable procedure */
+ /* --------------------------------------------------------------------- */
+ /*
+-void XGI_FirePWDDisable( PVB_DEVICE_INFO pVBInfo )
++void XGI_FirePWDDisable(struct vb_device_info *pVBInfo)
+ {
+     XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x26 , 0x00 , 0xFC ) ;
+ }
+@@ -7830,7 +7834,7 @@ void XGI_FirePWDDisable( PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : Turn on VDD & Backlight : Fire enable procedure */
+ /* --------------------------------------------------------------------- */
+-void XGI_FirePWDEnable(PVB_DEVICE_INFO pVBInfo )
++void XGI_FirePWDEnable(struct vb_device_info *pVBInfo)
+ {
+     XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x26 , 0x03 , 0xFC ) ;
+ }
+@@ -7842,7 +7846,7 @@ void XGI_FirePWDEnable(PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_EnableGatingCRT(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGI_EnableGatingCRT(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+     XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x63 , 0xBF , 0x40 ) ;
+ }
+@@ -7854,7 +7858,7 @@ void XGI_EnableGatingCRT(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVIC
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_DisableGatingCRT(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGI_DisableGatingCRT(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+ 
+     XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x63 , 0xBF , 0x00 ) ;
+@@ -7871,7 +7875,7 @@ void XGI_DisableGatingCRT(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVI
+ /* : bl : 3 ; T3 : the duration between CPL off and signal off */
+ /* : bl : 4 ; T4 : the duration signal off and Vdd off */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetPanelDelay(unsigned short tempbl, PVB_DEVICE_INFO pVBInfo)
++void XGI_SetPanelDelay(unsigned short tempbl, struct vb_device_info *pVBInfo)
+ {
+     unsigned short index ;
+ 
+@@ -7901,7 +7905,7 @@ void XGI_SetPanelDelay(unsigned short tempbl, PVB_DEVICE_INFO pVBInfo)
+ /* = 1011b = 0Bh ; Backlight off, Power on */
+ /* = 1111b = 0Fh ; Backlight off, Power off */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetPanelPower(unsigned short tempah, unsigned short tempbl, PVB_DEVICE_INFO pVBInfo)
++void XGI_SetPanelPower(unsigned short tempah, unsigned short tempbl, struct vb_device_info *pVBInfo)
+ {
+     if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+         XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x26 , tempbl , tempah ) ;
+@@ -7930,7 +7934,7 @@ unsigned char XG21GPIODataTransfer(unsigned char ujDate)
+ /*      bl[1] : LVDS backlight                                                */
+ /*      bl[0] : LVDS VDD                                                      */
+ /*----------------------------------------------------------------------------*/
+-unsigned char XGI_XG21GetPSCValue(PVB_DEVICE_INFO pVBInfo)
++unsigned char XGI_XG21GetPSCValue(struct vb_device_info *pVBInfo)
+ {
+     unsigned char CR4A, temp;
+ 
+@@ -7951,7 +7955,7 @@ unsigned char XGI_XG21GetPSCValue(PVB_DEVICE_INFO pVBInfo)
+ /*      bl[1] : LVDS backlight                                                */
+ /*      bl[0] : LVDS VDD                                                      */
+ /*----------------------------------------------------------------------------*/
+-unsigned char XGI_XG27GetPSCValue(PVB_DEVICE_INFO pVBInfo)
++unsigned char XGI_XG27GetPSCValue(struct vb_device_info *pVBInfo)
+ {
+     unsigned char CR4A, CRB4, temp;
+ 
+@@ -7976,7 +7980,7 @@ unsigned char XGI_XG27GetPSCValue(PVB_DEVICE_INFO pVBInfo)
+ /*          000010b : clear bit 1, to set bit1                                */
+ /*          000001b : clear bit 0, to set bit0                                */
+ /*----------------------------------------------------------------------------*/
+-void XGI_XG21BLSignalVDD(unsigned short tempbh, unsigned short tempbl, PVB_DEVICE_INFO pVBInfo)
++void XGI_XG21BLSignalVDD(unsigned short tempbh, unsigned short tempbl, struct vb_device_info *pVBInfo)
+ {
+     unsigned char CR4A, temp;
+ 
+@@ -8001,7 +8005,7 @@ void XGI_XG21BLSignalVDD(unsigned short tempbh, unsigned short tempbl, PVB_DEVIC
+     XGINew_SetReg1( pVBInfo->P3d4 , 0x48 , temp ) ;
+ }
+ 
+-void XGI_XG27BLSignalVDD(unsigned short tempbh, unsigned short tempbl, PVB_DEVICE_INFO pVBInfo)
++void XGI_XG27BLSignalVDD(unsigned short tempbh, unsigned short tempbl, struct vb_device_info *pVBInfo)
+ {
+     unsigned char CR4A, temp;
+     unsigned short tempbh0, tempbl0;
+@@ -8032,15 +8036,13 @@ void XGI_XG27BLSignalVDD(unsigned short tempbh, unsigned short tempbl, PVB_DEVIC
+ }
+ 
+ /* --------------------------------------------------------------------- */
+-unsigned short XGI_GetLVDSOEMTableIndex(PVB_DEVICE_INFO pVBInfo)
++unsigned short XGI_GetLVDSOEMTableIndex(struct vb_device_info *pVBInfo)
+ {
+     unsigned short index ;
+ 
+     index = XGINew_GetReg1( pVBInfo->P3d4 , 0x36 ) ;
+-    if (indexPart4Port , 0x27 , 0x7F ) ;	/* disable PWD */
+ }
+@@ -8584,7 +8586,7 @@ void XGI_DisablePWD( PVB_DEVICE_INFO pVBInfo )
+ /* Output : 0 -> Not LCD Mode */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGI_DisableChISLCD(PVB_DEVICE_INFO pVBInfo)
++unsigned char XGI_DisableChISLCD(struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempbx ,
+            tempah ;
+@@ -8614,7 +8616,7 @@ unsigned char XGI_DisableChISLCD(PVB_DEVICE_INFO pVBInfo)
+ /* Output : 0 -> Not LCD mode */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGI_EnableChISLCD(PVB_DEVICE_INFO pVBInfo)
++unsigned char XGI_EnableChISLCD(struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempbx ,
+            tempah ;
+@@ -8645,7 +8647,7 @@ unsigned char XGI_EnableChISLCD(PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned short XGI_GetLCDCapPtr(PVB_DEVICE_INFO pVBInfo)
++unsigned short XGI_GetLCDCapPtr(struct vb_device_info *pVBInfo)
+ {
+     unsigned char tempal ,
+           tempah ,
+@@ -8684,7 +8686,7 @@ unsigned short XGI_GetLCDCapPtr(PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned short XGI_GetLCDCapPtr1(PVB_DEVICE_INFO pVBInfo)
++unsigned short XGI_GetLCDCapPtr1(struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempah ,
+            tempal ,
+@@ -8730,7 +8732,7 @@ unsigned short XGI_GetLCDCapPtr1(PVB_DEVICE_INFO pVBInfo)
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ void XGI_GetLCDSync(unsigned short *HSyncWidth , unsigned short *VSyncWidth,
+-		    PVB_DEVICE_INFO pVBInfo)
++		    struct vb_device_info *pVBInfo)
+ {
+     unsigned short Index ;
+ 
+@@ -8749,7 +8751,7 @@ void XGI_GetLCDSync(unsigned short *HSyncWidth , unsigned short *VSyncWidth,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_EnableBridge(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGI_EnableBridge(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempbl ,
+            tempah ;
+@@ -8962,7 +8964,7 @@ void XGI_EnableBridge(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_I
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_DisableBridge(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGI_DisableBridge(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempax ,
+            tempbx ,
+@@ -9143,7 +9145,7 @@ void XGI_DisableBridge(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_
+ /* A : Ext750p */
+ /* B : St750p */
+ /* --------------------------------------------------------------------- */
+-unsigned short XGI_GetTVPtrIndex(PVB_DEVICE_INFO pVBInfo)
++unsigned short XGI_GetTVPtrIndex(struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempbx = 0 ;
+ 
+@@ -9170,7 +9172,7 @@ unsigned short XGI_GetTVPtrIndex(PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : Customized Param. for 301 */
+ /* --------------------------------------------------------------------- */
+-void XGI_OEM310Setting(unsigned short ModeNo , unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
++void XGI_OEM310Setting(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
+ {
+     if ( pVBInfo->SetFlag & Win9xDOSMode )
+         return ;
+@@ -9200,7 +9202,7 @@ void XGI_OEM310Setting(unsigned short ModeNo , unsigned short ModeIdIndex, PVB_D
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetDelayComp( PVB_DEVICE_INFO pVBInfo )
++void XGI_SetDelayComp(struct vb_device_info *pVBInfo)
+ {
+     unsigned short index ;
+ 
+@@ -9278,7 +9280,7 @@ void XGI_SetDelayComp( PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetLCDCap( PVB_DEVICE_INFO pVBInfo )
++void XGI_SetLCDCap(struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempcx ;
+ 
+@@ -9321,7 +9323,7 @@ void XGI_SetLCDCap( PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetLCDCap_A(unsigned short tempcx, PVB_DEVICE_INFO pVBInfo)
++void XGI_SetLCDCap_A(unsigned short tempcx, struct vb_device_info *pVBInfo)
+ {
+     unsigned short temp ;
+ 
+@@ -9361,7 +9363,7 @@ void XGI_SetLCDCap_A(unsigned short tempcx, PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetLCDCap_B(unsigned short tempcx, PVB_DEVICE_INFO pVBInfo)
++void XGI_SetLCDCap_B(unsigned short tempcx, struct vb_device_info *pVBInfo)
+ {
+     if ( tempcx & EnableLCD24bpp )	/* 24bits */
+ 	    XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x1A, 0xE0,
+@@ -9378,7 +9380,7 @@ void XGI_SetLCDCap_B(unsigned short tempcx, PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void SetSpectrum( PVB_DEVICE_INFO pVBInfo )
++void SetSpectrum(struct vb_device_info *pVBInfo)
+ {
+     unsigned short index ;
+ 
+@@ -9405,7 +9407,7 @@ void SetSpectrum( PVB_DEVICE_INFO pVBInfo )
+ /* Description : Set TV Customized Param. */
+ /* --------------------------------------------------------------------- */
+ void XGI_SetAntiFlicker(unsigned short ModeNo, unsigned short ModeIdIndex,
+-			PVB_DEVICE_INFO pVBInfo)
++			struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempbx ,
+            index ;
+@@ -9441,7 +9443,7 @@ void XGI_SetAntiFlicker(unsigned short ModeNo, unsigned short ModeIdIndex,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetEdgeEnhance(unsigned short ModeNo , unsigned short ModeIdIndex , PVB_DEVICE_INFO pVBInfo)
++void XGI_SetEdgeEnhance(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempbx ,
+            index ;
+@@ -9475,7 +9477,7 @@ void XGI_SetEdgeEnhance(unsigned short ModeNo , unsigned short ModeIdIndex , PVB
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetPhaseIncr( PVB_DEVICE_INFO pVBInfo )
++void XGI_SetPhaseIncr(struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempbx ;
+ 
+@@ -9505,7 +9507,7 @@ void XGI_SetPhaseIncr( PVB_DEVICE_INFO pVBInfo )
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ void XGI_SetYFilter(unsigned short ModeNo, unsigned short ModeIdIndex,
+-		    PVB_DEVICE_INFO pVBInfo)
++		    struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempbx ,
+            index ;
+@@ -9610,7 +9612,7 @@ void XGI_SetYFilter(unsigned short ModeNo, unsigned short ModeIdIndex,
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ void XGI_GetTVPtrIndex2(unsigned short *tempbx, unsigned char *tempcl,
+-			unsigned char *tempch, PVB_DEVICE_INFO pVBInfo)
++			unsigned char *tempch, struct vb_device_info *pVBInfo)
+ {
+     *tempbx = 0 ;
+     *tempcl = 0 ;
+@@ -9654,7 +9656,7 @@ void XGI_GetTVPtrIndex2(unsigned short *tempbx, unsigned char *tempcl,
+ /* --------------------------------------------------------------------- */
+ void XGI_SetCRT2ModeRegs(unsigned short ModeNo,
+ 			 struct xgi_hw_device_info *HwDeviceExtension,
+-			 PVB_DEVICE_INFO pVBInfo)
++			 struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempbl ;
+     short  tempcl ;
+@@ -9883,7 +9885,7 @@ void XGI_SetCRT2ModeRegs(unsigned short ModeNo,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_CloseCRTC(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGI_CloseCRTC(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempbx ;
+ 
+@@ -9902,7 +9904,7 @@ void XGI_CloseCRTC(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_OpenCRTC(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGI_OpenCRTC(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempbx ;
+ 
+@@ -9918,7 +9920,7 @@ void XGI_OpenCRTC(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_GetRAMDAC2DATA(unsigned short ModeNo , unsigned short ModeIdIndex , unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
++void XGI_GetRAMDAC2DATA(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempax ,
+            tempbx ,
+@@ -9983,7 +9985,7 @@ void XGI_GetRAMDAC2DATA(unsigned short ModeNo , unsigned short ModeIdIndex , uns
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned short XGI_GetColorDepth(unsigned short ModeNo , unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
++unsigned short XGI_GetColorDepth(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
+ {
+     unsigned short ColorDepth[ 6 ] = { 1 , 2 , 4 , 4 , 6 , 8 } ;
+     short index ;
+@@ -10014,7 +10016,7 @@ unsigned short XGI_GetColorDepth(unsigned short ModeNo , unsigned short ModeIdIn
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_UnLockCRT2(struct xgi_hw_device_info *HwDeviceExtension,  PVB_DEVICE_INFO pVBInfo)
++void XGI_UnLockCRT2(struct xgi_hw_device_info *HwDeviceExtension,  struct vb_device_info *pVBInfo)
+ {
+ 
+     XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2f , 0xFF , 0x01 ) ;
+@@ -10028,7 +10030,7 @@ void XGI_UnLockCRT2(struct xgi_hw_device_info *HwDeviceExtension,  PVB_DEVICE_IN
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_LockCRT2(struct xgi_hw_device_info *HwDeviceExtension,  PVB_DEVICE_INFO pVBInfo)
++void XGI_LockCRT2(struct xgi_hw_device_info *HwDeviceExtension,  struct vb_device_info *pVBInfo)
+ {
+ 
+     XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2F , 0xFE , 0x00 ) ;
+@@ -10043,7 +10045,7 @@ void XGI_LockCRT2(struct xgi_hw_device_info *HwDeviceExtension,  PVB_DEVICE_INFO
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_EnableCRT2( PVB_DEVICE_INFO pVBInfo)
++void XGINew_EnableCRT2(struct vb_device_info *pVBInfo)
+ {
+     XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x1E , 0xFF , 0x20 ) ;
+ }
+@@ -10056,7 +10058,7 @@ void XGINew_EnableCRT2( PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_LCD_Wait_Time(unsigned char DelayTime, PVB_DEVICE_INFO pVBInfo)
++void XGINew_LCD_Wait_Time(unsigned char DelayTime, struct vb_device_info *pVBInfo)
+ {
+     unsigned short i ,
+            j ;
+@@ -10093,7 +10095,7 @@ void XGINew_LCD_Wait_Time(unsigned char DelayTime, PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGI_BridgeIsOn(PVB_DEVICE_INFO pVBInfo)
++unsigned char XGI_BridgeIsOn(struct vb_device_info *pVBInfo)
+ {
+     unsigned short flag ;
+ 
+@@ -10119,7 +10121,7 @@ unsigned char XGI_BridgeIsOn(PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_LongWait(PVB_DEVICE_INFO pVBInfo)
++void XGI_LongWait(struct vb_device_info *pVBInfo)
+ {
+     unsigned short i ;
+ 
+@@ -10148,7 +10150,7 @@ void XGI_LongWait(PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_VBLongWait( PVB_DEVICE_INFO pVBInfo )
++void XGI_VBLongWait(struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempal ,
+            temp ,
+@@ -10207,7 +10209,7 @@ return ;
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned short XGI_GetVGAHT2( PVB_DEVICE_INFO pVBInfo )
++unsigned short XGI_GetVGAHT2(struct vb_device_info *pVBInfo)
+ {
+     unsigned long tempax ,
+           tempbx ;
+@@ -10230,7 +10232,7 @@ unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo,
+ 			       unsigned short ModeIdIndex,
+ 			       unsigned short RefreshRateTableIndex,
+ 			       struct xgi_hw_device_info *HwDeviceExtension,
+-			       PVB_DEVICE_INFO pVBInfo)
++			       struct vb_device_info *pVBInfo)
+ {
+     unsigned short tempbx ;
+ 
+diff --git a/drivers/staging/xgifb/vb_setmode.h b/drivers/staging/xgifb/vb_setmode.h
+index 0d061d730072..0dcc29796176 100644
+--- a/drivers/staging/xgifb/vb_setmode.h
++++ b/drivers/staging/xgifb/vb_setmode.h
+@@ -1,42 +1,42 @@
+ #ifndef  _VBSETMODE_
+ #define  _VBSETMODE_
+ 
+-extern   void     InitTo330Pointer(unsigned char, PVB_DEVICE_INFO);
+-extern   void     XGI_UnLockCRT2(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO);
+-extern   void     XGI_LockCRT2(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO);
+-extern   void     XGI_LongWait( PVB_DEVICE_INFO );
++extern   void     InitTo330Pointer(unsigned char, struct vb_device_info *);
++extern   void     XGI_UnLockCRT2(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *);
++extern   void     XGI_LockCRT2(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *);
++extern   void     XGI_LongWait(struct vb_device_info *);
+ extern   void     XGI_SetCRT2ModeRegs(unsigned short ModeNo,
+ 				      struct xgi_hw_device_info *,
+-				      PVB_DEVICE_INFO);
+-extern   void     XGI_DisableBridge(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO);
+-extern   void     XGI_EnableBridge(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO);
+-extern   void     XGI_DisplayOff(struct xgi_hw_device_info *, PVB_DEVICE_INFO);
+-extern   void     XGI_DisplayOn(struct xgi_hw_device_info *, PVB_DEVICE_INFO);
+-extern   void     XGI_GetVBType(PVB_DEVICE_INFO);
+-extern   void     XGI_SenseCRT1(PVB_DEVICE_INFO );
+-extern   void     XGI_GetVGAType(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO);
+-extern   void     XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO);
+-extern   void     XGI_GetTVInfo(unsigned short ModeNo,unsigned short ModeIdIndex, PVB_DEVICE_INFO );
+-extern   void     XGI_SetCRT1Offset(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO);
+-extern   void     XGI_SetLCDAGroup(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO);
+-extern   void     XGI_WaitDisply( PVB_DEVICE_INFO );
+-extern   unsigned short   XGI_GetResInfo(unsigned short ModeNo,unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
++				      struct vb_device_info *);
++extern   void     XGI_DisableBridge(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *);
++extern   void     XGI_EnableBridge(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *);
++extern   void     XGI_DisplayOff(struct xgi_hw_device_info *, struct vb_device_info *);
++extern   void     XGI_DisplayOn(struct xgi_hw_device_info *, struct vb_device_info *);
++extern   void     XGI_GetVBType(struct vb_device_info *);
++extern   void     XGI_SenseCRT1(struct vb_device_info *);
++extern   void     XGI_GetVGAType(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *);
++extern   void     XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *);
++extern   void     XGI_GetTVInfo(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *);
++extern   void     XGI_SetCRT1Offset(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *);
++extern   void     XGI_SetLCDAGroup(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *);
++extern   void     XGI_WaitDisply(struct vb_device_info *);
++extern   unsigned short   XGI_GetResInfo(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
+ 
+ extern   unsigned char  XGISetModeNew(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo) ;
+ 
+-extern   unsigned char  XGI_SearchModeID( unsigned short ModeNo,unsigned short  *ModeIdIndex, PVB_DEVICE_INFO );
+-extern   unsigned char  XGI_GetLCDInfo(unsigned short ModeNo,unsigned short ModeIdIndex,PVB_DEVICE_INFO );
+-extern   unsigned char  XGI_BridgeIsOn( PVB_DEVICE_INFO );
+-extern   unsigned char  XGI_SetCRT2Group301(unsigned short ModeNo, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO);
+-extern   unsigned short   XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE, unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO);
++extern   unsigned char  XGI_SearchModeID(unsigned short ModeNo, unsigned short  *ModeIdIndex, struct vb_device_info *);
++extern   unsigned char  XGI_GetLCDInfo(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *);
++extern   unsigned char  XGI_BridgeIsOn(struct vb_device_info *);
++extern   unsigned char  XGI_SetCRT2Group301(unsigned short ModeNo, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *);
++extern   unsigned short   XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE, unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *);
+ 
+-extern   void     XGI_SetXG21FPBits(PVB_DEVICE_INFO pVBInfo);
+-extern   void     XGI_SetXG27FPBits(PVB_DEVICE_INFO pVBInfo);
+-extern   void     XGI_XG21BLSignalVDD(unsigned short tempbh,unsigned short tempbl, PVB_DEVICE_INFO pVBInfo);
+-extern   void     XGI_XG27BLSignalVDD(unsigned short tempbh,unsigned short tempbl, PVB_DEVICE_INFO pVBInfo);
+-extern   void     XGI_XG21SetPanelDelay(unsigned short tempbl, PVB_DEVICE_INFO pVBInfo);
+-extern   unsigned char  XGI_XG21CheckLVDSMode(unsigned short ModeNo,unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
+-extern   void     XGI_SetXG21LVDSPara(unsigned short ModeNo,unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
+-extern   unsigned short XGI_GetLVDSOEMTableIndex(PVB_DEVICE_INFO pVBInfo);
++extern   void     XGI_SetXG21FPBits(struct vb_device_info *pVBInfo);
++extern   void     XGI_SetXG27FPBits(struct vb_device_info *pVBInfo);
++extern   void     XGI_XG21BLSignalVDD(unsigned short tempbh, unsigned short tempbl, struct vb_device_info *pVBInfo);
++extern   void     XGI_XG27BLSignalVDD(unsigned short tempbh, unsigned short tempbl, struct vb_device_info *pVBInfo);
++extern   void     XGI_XG21SetPanelDelay(unsigned short tempbl, struct vb_device_info *pVBInfo);
++extern   unsigned char  XGI_XG21CheckLVDSMode(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
++extern   void     XGI_SetXG21LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
++extern   unsigned short XGI_GetLVDSOEMTableIndex(struct vb_device_info *pVBInfo);
+ 
+ #endif
+diff --git a/drivers/staging/xgifb/vb_struct.h b/drivers/staging/xgifb/vb_struct.h
+index 1d401c04de8e..9c6e0c7ac781 100644
+--- a/drivers/staging/xgifb/vb_struct.h
++++ b/drivers/staging/xgifb/vb_struct.h
+@@ -10,12 +10,12 @@
+ 
+ 
+ 
+-typedef struct _XGI_PanelDelayTblStruct
++struct XGI_PanelDelayTblStruct
+ {
+  unsigned char timer[2];
+-} XGI_PanelDelayTblStruct;
++};
+ 
+-typedef struct _XGI_LCDDataStruct
++struct XGI_LCDDataStruct
+ {
+  unsigned short RVBHCMAX;
+  unsigned short RVBHCFACT;
+@@ -23,20 +23,21 @@ typedef struct _XGI_LCDDataStruct
+  unsigned short VGAVT;
+  unsigned short LCDHT;
+  unsigned short LCDVT;
+-} XGI_LCDDataStruct;
++};
+ 
+ 
+-typedef struct _XGI_LVDSCRT1HDataStruct
++struct XGI_LVDSCRT1HDataStruct
+ {
+  unsigned char Reg[8];
+-} XGI_LVDSCRT1HDataStruct;
+-typedef struct _XGI_LVDSCRT1VDataStruct
++};
++
++struct XGI_LVDSCRT1VDataStruct
+ {
+  unsigned char Reg[7];
+-} XGI_LVDSCRT1VDataStruct;
++};
+ 
+ 
+-typedef struct _XGI_TVDataStruct
++struct XGI_TVDataStruct
+ {
+  unsigned short RVBHCMAX;
+  unsigned short RVBHCFACT;
+@@ -51,31 +52,30 @@ typedef struct _XGI_TVDataStruct
+  unsigned char RY2COE;
+  unsigned char RY3COE;
+  unsigned char RY4COE;
+-} XGI_TVDataStruct;
++};
+ 
+-typedef struct _XGI_LVDSDataStruct
++struct XGI_LVDSDataStruct
+ {
+  unsigned short VGAHT;
+  unsigned short VGAVT;
+  unsigned short LCDHT;
+  unsigned short LCDVT;
+-} XGI_LVDSDataStruct;
++};
+ 
+-typedef struct _XGI_LVDSDesStruct
++struct XGI_LVDSDesStruct
+ {
+  unsigned short LCDHDES;
+  unsigned short LCDVDES;
+-} XGI_LVDSDesStruct;
++};
+ 
+-typedef struct _XGI_LVDSCRT1DataStruct
++struct XGI_LVDSCRT1DataStruct
+ {
+  unsigned char CR[15];
+-} XGI_LVDSCRT1DataStruct;
++};
+ 
+ /*add for LCDA*/
+ 
+-
+-typedef struct _XGI_StStruct
++struct XGI_StStruct
+ {
+  unsigned char St_ModeID;
+  unsigned short St_ModeFlag;
+@@ -86,9 +86,9 @@ typedef struct _XGI_StStruct
+  unsigned char VB_StTVFlickerIndex;
+  unsigned char VB_StTVEdgeIndex;
+  unsigned char VB_StTVYFilterIndex;
+-} XGI_StStruct;
++};
+ 
+-typedef struct _XGI_StandTableStruct
++struct XGI_StandTableStruct
+ {
+  unsigned char CRT_COLS;
+  unsigned char ROWS;
+@@ -99,9 +99,9 @@ typedef struct _XGI_StandTableStruct
+  unsigned char CRTC[0x19];
+  unsigned char ATTR[0x14];
+  unsigned char GRC[9];
+-} XGI_StandTableStruct;
++};
+ 
+-typedef struct _XGI_ExtStruct
++struct XGI_ExtStruct
+ {
+  unsigned char Ext_ModeID;
+  unsigned short Ext_ModeFlag;
+@@ -114,9 +114,9 @@ typedef struct _XGI_ExtStruct
+  unsigned char VB_ExtTVEdgeIndex;
+  unsigned char VB_ExtTVYFilterIndex;
+  unsigned char REFindex;
+-} XGI_ExtStruct;
++};
+ 
+-typedef struct _XGI_Ext2Struct
++struct XGI_Ext2Struct
+ {
+  unsigned short Ext_InfoFlag;
+  unsigned char Ext_CRT1CRTC;
+@@ -127,93 +127,93 @@ typedef struct _XGI_Ext2Struct
+  unsigned short XRes;
+  unsigned short YRes;
+  /* unsigned short ROM_OFFSET; */
+-} XGI_Ext2Struct;
++};
+ 
+ 
+-typedef struct _XGI_MCLKDataStruct
++struct XGI_MCLKDataStruct
+ {
+  unsigned char SR28, SR29, SR2A;
+  unsigned short CLOCK;
+-} XGI_MCLKDataStruct;
++};
+ 
+-typedef struct _XGI_ECLKDataStruct
++struct XGI_ECLKDataStruct
+ {
+  unsigned char SR2E, SR2F, SR30;
+  unsigned short CLOCK;
+-} XGI_ECLKDataStruct;
++};
+ 
+-typedef struct _XGI_VCLKDataStruct
++struct XGI_VCLKDataStruct
+ {
+  unsigned char SR2B, SR2C;
+  unsigned short CLOCK;
+-} XGI_VCLKDataStruct;
++};
+ 
+-typedef struct _XGI_VBVCLKDataStruct
++struct XGI_VBVCLKDataStruct
+ {
+  unsigned char Part4_A, Part4_B;
+  unsigned short CLOCK;
+-} XGI_VBVCLKDataStruct;
++};
+ 
+-typedef struct _XGI_StResInfoStruct
++struct XGI_StResInfoStruct
+ {
+  unsigned short HTotal;
+  unsigned short VTotal;
+-} XGI_StResInfoStruct;
++};
+ 
+-typedef struct _XGI_ModeResInfoStruct
++struct XGI_ModeResInfoStruct
+ {
+  unsigned short HTotal;
+  unsigned short VTotal;
+  unsigned char  XChar;
+  unsigned char  YChar;
+-} XGI_ModeResInfoStruct;
++};
+ 
+-typedef struct _XGI_LCDNBDesStruct
++struct XGI_LCDNBDesStruct
+ {
+   unsigned char NB[12];
+-} XGI_LCDNBDesStruct;
++};
+  /*add for new UNIVGABIOS*/
+-typedef struct _XGI_LCDDesStruct
++struct XGI_LCDDesStruct
+ {
+  unsigned short LCDHDES;
+  unsigned short LCDHRS;
+  unsigned short LCDVDES;
+  unsigned short LCDVRS;
+-} XGI_LCDDesStruct;
++};
+ 
+-typedef struct _XGI_LCDDataTablStruct
++struct XGI_LCDDataTablStruct
+ {
+  unsigned char  PANELID;
+  unsigned short MASK;
+  unsigned short CAP;
+  unsigned short DATAPTR;
+-} XGI_LCDDataTablStruct;
++};
+ 
+-typedef struct _XGI_TVTablDataStruct
++struct XGI_TVTablDataStruct
+ {
+  unsigned short MASK;
+  unsigned short CAP;
+  unsigned short DATAPTR;
+-} XGI_TVDataTablStruct;
++};
+ 
+-typedef struct _XGI330_LCDDesDataStruct
++struct XGI330_LCDDataDesStruct
+ {
+  unsigned short LCDHDES;
+  unsigned short LCDHRS;
+  unsigned short LCDVDES;
+  unsigned short LCDVRS;
+-} XGI330_LCDDataDesStruct;
++};
+ 
+ 
+-typedef struct _XGI330_LVDSDataStruct
++struct XGI330_LVDSDataStruct
+ {
+  unsigned short VGAHT;
+  unsigned short VGAVT;
+  unsigned short LCDHT;
+  unsigned short LCDVT;
+-} XGI330_LVDSDataStruct;
++};
+ 
+-typedef struct _XGI330_LCDDesDataStruct2
++struct XGI330_LCDDataDesStruct2
+ {
+  unsigned short LCDHDES;
+  unsigned short LCDHRS;
+@@ -221,9 +221,9 @@ typedef struct _XGI330_LCDDesDataStruct2
+  unsigned short LCDVRS;
+  unsigned short LCDHSync;
+  unsigned short LCDVSync;
+-} XGI330_LCDDataDesStruct2;
++};
+ 
+-typedef struct _XGI330_LCDDataStruct
++struct XGI330_LCDDataStruct
+ {
+  unsigned short RVBHCMAX;
+  unsigned short RVBHCFACT;
+@@ -231,10 +231,10 @@ typedef struct _XGI330_LCDDataStruct
+  unsigned short VGAVT;
+  unsigned short LCDHT;
+  unsigned short LCDVT;
+-} XGI330_LCDDataStruct;
++};
+ 
+ 
+-typedef struct _XGI330_TVDataStruct
++struct XGI330_TVDataStruct
+ {
+  unsigned short RVBHCMAX;
+  unsigned short RVBHCFACT;
+@@ -245,63 +245,63 @@ typedef struct _XGI330_TVDataStruct
+  unsigned short RVBHRS;
+  unsigned char FlickerMode;
+  unsigned short HALFRVBHRS;
+-} XGI330_TVDataStruct;
++};
+ 
+-typedef struct _XGI330_LCDDataTablStruct
++struct XGI330_LCDDataTablStruct
+ {
+  unsigned char  PANELID;
+  unsigned short MASK;
+  unsigned short CAP;
+  unsigned short DATAPTR;
+-} XGI330_LCDDataTablStruct;
++};
+ 
+-typedef struct _XGI330_TVDataTablStruct
++struct XGI330_TVDataTablStruct
+ {
+  unsigned short MASK;
+  unsigned short CAP;
+  unsigned short DATAPTR;
+-} XGI330_TVDataTablStruct;
++};
+ 
+ 
+-typedef struct _XGI330_CHTVDataStruct
++struct XGI330_CHTVDataStruct
+ {
+  unsigned short VGAHT;
+  unsigned short VGAVT;
+  unsigned short LCDHT;
+  unsigned short LCDVT;
+-} XGI330_CHTVDataStruct;
++};
+ 
+-typedef struct _XGI_TimingHStruct
++struct XGI_TimingHStruct
+ {
+   unsigned char data[8];
+-} XGI_TimingHStruct;
++};
+ 
+-typedef struct _XGI_TimingVStruct
++struct XGI_TimingVStruct
+ {
+   unsigned char data[7];
+-} XGI_TimingVStruct;
++};
+ 
+-typedef struct _XGI_CH7007TV_TimingHStruct
++struct XGI_CH7007TV_TimingHStruct
+ {
+   unsigned char data[10];
+-} XGI_CH7007TV_TimingHStruct;
++};
+ 
+-typedef struct _XGI_CH7007TV_TimingVStruct
++struct XGI_CH7007TV_TimingVStruct
+ {
+   unsigned char data[10];
+-} XGI_CH7007TV_TimingVStruct;
++};
+ 
+-typedef struct _XGI_XG21CRT1Struct
++struct XGI_XG21CRT1Struct
+ {
+  unsigned char ModeID, CR02, CR03, CR15, CR16;
+-} XGI_XG21CRT1Struct;
++};
+ 
+-typedef struct _XGI330_CHTVRegDataStruct
++struct XGI330_CHTVRegDataStruct
+ {
+  unsigned char Reg[16];
+-} XGI330_CHTVRegDataStruct;
++};
+ 
+-typedef struct _XGI330_LCDCapStruct
++struct XGI330_LCDCapStruct
+ {
+ 		unsigned char	   LCD_ID;
+ 		unsigned short	   LCD_Capability;
+@@ -328,9 +328,9 @@ typedef struct _XGI330_LCDCapStruct
+ 		unsigned char	   Spectrum_32;
+ 		unsigned char	   Spectrum_33;
+ 		unsigned char	   Spectrum_34;
+-} XGI330_LCDCapStruct;
++};
+ 
+-typedef struct _XGI21_LVDSCapStruct
++struct XGI21_LVDSCapStruct
+ {
+ 		unsigned short	   LVDS_Capability;
+ 		unsigned short	   LVDSHT;
+@@ -348,27 +348,27 @@ typedef struct _XGI21_LVDSCapStruct
+ 		unsigned char	   PSC_S3;
+ 		unsigned char	   PSC_S4;
+ 		unsigned char	   PSC_S5;
+-} XGI21_LVDSCapStruct;
++};
+ 
+-typedef struct _XGI_CRT1TableStruct
++struct XGI_CRT1TableStruct
+ {
+   unsigned char CR[16];
+-} XGI_CRT1TableStruct;
++};
+ 
+ 
+-typedef struct _XGI330_VCLKDataStruct
++struct XGI330_VCLKDataStruct
+ {
+     unsigned char SR2B, SR2C;
+     unsigned short CLOCK;
+-} XGI330_VCLKDataStruct;
++};
+ 
+-typedef struct _XGI301C_Tap4TimingStruct
++struct XGI301C_Tap4TimingStruct
+ {
+     unsigned short DE;
+     unsigned char  Reg[64];   /* C0-FF */
+-} XGI301C_Tap4TimingStruct;
++};
+ 
+-typedef struct _XGI_New_StandTableStruct
++struct XGI_New_StandTableStruct
+ {
+ 	unsigned char  CRT_COLS;
+ 	unsigned char  ROWS;
+@@ -379,17 +379,9 @@ typedef struct _XGI_New_StandTableStruct
+ 	unsigned char  CRTC[0x19];
+ 	unsigned char  ATTR[0x14];
+ 	unsigned char  GRC[9];
+-} XGI_New_StandTableStruct;
+-
+-typedef unsigned char DRAM8Type[8];
+-typedef unsigned char DRAM4Type[4];
+-typedef unsigned char DRAM32Type[32];
+-typedef unsigned char DRAM2Type[2];
++};
+ 
+-typedef struct _VB_DEVICE_INFO  VB_DEVICE_INFO;
+-typedef VB_DEVICE_INFO *	PVB_DEVICE_INFO;
+-
+-struct _VB_DEVICE_INFO
++struct vb_device_info
+ {
+     unsigned char  ISXPDOS;
+     unsigned long   P3c4,P3d4,P3c0,P3ce,P3c2,P3cc;
+@@ -420,13 +412,14 @@ struct _VB_DEVICE_INFO
+     unsigned long BaseAddr;
+     unsigned long RelIO;
+ 
+-    DRAM4Type  *CR6B;
+-    DRAM4Type  *CR6E;
+-    DRAM32Type *CR6F;
+-    DRAM2Type  *CR89;
++	unsigned char (*CR6B)[4];
++	unsigned char (*CR6E)[4];
++	unsigned char (*CR6F)[32];
++	unsigned char (*CR89)[2];
++
++	unsigned char (*SR15)[8];
++	unsigned char (*CR40)[8];
+ 
+-    DRAM8Type  *SR15; /* pointer : point to array */
+-    DRAM8Type  *CR40;
+     unsigned char  *pSoftSetting;
+     unsigned char  *pOutputSelect;
+ 
+@@ -466,8 +459,8 @@ struct _VB_DEVICE_INFO
+     unsigned char  *pCRT2Data_4_D;
+     unsigned char  *pCRT2Data_4_E;
+     unsigned char  *pCRT2Data_4_10;
+-    XGI_MCLKDataStruct  *MCLKData;
+-    XGI_ECLKDataStruct  *ECLKData;
++    struct XGI_MCLKDataStruct  *MCLKData;
++    struct XGI_ECLKDataStruct  *ECLKData;
+ 
+     unsigned char   *XGI_TVDelayList;
+     unsigned char   *XGI_TVDelayList2;
+@@ -494,27 +487,27 @@ struct _VB_DEVICE_INFO
+     unsigned char   *pXGINew_I2CDefinition ;
+     unsigned char   *pXGINew_CR97 ;
+ 
+-    XGI330_LCDCapStruct  *LCDCapList;
+-    XGI21_LVDSCapStruct  *XG21_LVDSCapList;
++    struct XGI330_LCDCapStruct  *LCDCapList;
++    struct XGI21_LVDSCapStruct  *XG21_LVDSCapList;
+ 
+-    XGI_TimingHStruct  *TimingH;
+-    XGI_TimingVStruct  *TimingV;
++    struct XGI_TimingHStruct  *TimingH;
++    struct XGI_TimingVStruct  *TimingV;
+ 
+-    XGI_StStruct          *SModeIDTable;
+-    XGI_StandTableStruct  *StandTable;
+-    XGI_ExtStruct         *EModeIDTable;
+-    XGI_Ext2Struct        *RefIndex;
++    struct XGI_StStruct          *SModeIDTable;
++    struct XGI_StandTableStruct  *StandTable;
++    struct XGI_ExtStruct         *EModeIDTable;
++    struct XGI_Ext2Struct        *RefIndex;
+     /* XGINew_CRT1TableStruct *CRT1Table; */
+-    XGI_CRT1TableStruct    *XGINEWUB_CRT1Table;
+-    XGI_VCLKDataStruct    *VCLKData;
+-    XGI_VBVCLKDataStruct  *VBVCLKData;
+-    XGI_StResInfoStruct   *StResInfo;
+-    XGI_ModeResInfoStruct *ModeResInfo;
+-    XGI_XG21CRT1Struct	  *UpdateCRT1;
+-};  /* _VB_DEVICE_INFO */
++    struct XGI_CRT1TableStruct    *XGINEWUB_CRT1Table;
++    struct XGI_VCLKDataStruct    *VCLKData;
++    struct XGI_VBVCLKDataStruct  *VBVCLKData;
++    struct XGI_StResInfoStruct   *StResInfo;
++    struct XGI_ModeResInfoStruct *ModeResInfo;
++    struct XGI_XG21CRT1Struct	  *UpdateCRT1;
++};  /* _struct vb_device_info */
+ 
+ 
+-typedef struct
++struct TimingInfo
+ {
+     unsigned short    Horizontal_ACTIVE;
+     unsigned short    Horizontal_FP;
+@@ -528,7 +521,7 @@ typedef struct
+     unsigned char     FrameRate;
+     unsigned char     Interlace;
+     unsigned short    Margin;
+-} TimingInfo;
++};
+ 
+ #define _VB_STRUCT_
+ #endif /* _VB_STRUCT_ */
+diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h
+index 5f394d065764..510ef7678685 100644
+--- a/drivers/staging/xgifb/vb_table.h
++++ b/drivers/staging/xgifb/vb_table.h
+@@ -1,7 +1,7 @@
+ #define  Tap4
+ 
+ 
+-XGI_MCLKDataStruct XGI330New_MCLKData[]=
++struct XGI_MCLKDataStruct XGI330New_MCLKData[] =
+ {
+  { 0x5c,0x23,0x01,166},
+  { 0x5c,0x23,0x01,166},
+@@ -13,7 +13,7 @@ XGI_MCLKDataStruct XGI330New_MCLKData[]=
+  { 0x29,0x01,0x81,300}
+ };
+ //yilin modify for xgi20
+-XGI_MCLKDataStruct XGI340New_MCLKData[]=
++struct XGI_MCLKDataStruct XGI340New_MCLKData[] =
+ {
+  { 0x16,0x01,0x01,166},
+  { 0x19,0x02,0x01,124},
+@@ -25,7 +25,7 @@ XGI_MCLKDataStruct XGI340New_MCLKData[]=
+  { 0x5c,0x23,0x01,166}
+ };
+ 
+-XGI_MCLKDataStruct XGI27New_MCLKData[]=
++struct XGI_MCLKDataStruct XGI27New_MCLKData[] =
+ {
+  { 0x5c,0x23,0x01,166},
+  { 0x19,0x02,0x01,124},
+@@ -37,7 +37,7 @@ XGI_MCLKDataStruct XGI27New_MCLKData[]=
+  { 0x5c,0x23,0x01,166}
+ };
+ 
+-XGI_ECLKDataStruct XGI330_ECLKData[]=
++struct XGI_ECLKDataStruct XGI330_ECLKData[] =
+ {
+  { 0x7c,0x08,0x01,200},
+  { 0x7c,0x08,0x01,200},
+@@ -49,7 +49,7 @@ XGI_ECLKDataStruct XGI330_ECLKData[]=
+  { 0x29,0x01,0x81,300}
+ };
+ //yilin modify for xgi20
+-XGI_ECLKDataStruct XGI340_ECLKData[]=
++struct XGI_ECLKDataStruct XGI340_ECLKData[] =
+ {
+  { 0x5c,0x23,0x01,166},
+  { 0x55,0x84,0x01,123},
+@@ -211,7 +211,7 @@ unsigned char XGI330_SR33 = 0x00;
+ unsigned char XG40_CRCF = 0x13;
+ unsigned char XG40_DRAMTypeDefinition = 0xFF ;
+ 
+-XGI_StStruct XGI330_SModeIDTable[]=
++struct XGI_StStruct XGI330_SModeIDTable[] =
+ {
+  {0x01,0x9208,0x01,0x00,0x10,0x00,0x00,0x01,0x00},
+  {0x01,0x1210,0x14,0x01,0x00,0x01,0x00,0x01,0x00},
+@@ -236,7 +236,7 @@ XGI_StStruct XGI330_SModeIDTable[]=
+ };
+ 
+ 
+-XGI_ExtStruct  XGI330_EModeIDTable[]=
++struct XGI_ExtStruct  XGI330_EModeIDTable[] =
+ {
+  {0x6a,0x2212,0x0407,0x3a81,0x0102,0x08,0x07,0x00,0x00,0x07,0x0e},
+  {0x2e,0x0a1b,0x0306,0x3a57,0x0101,0x08,0x06,0x00,0x00,0x05,0x06},
+@@ -308,7 +308,7 @@ XGI_ExtStruct  XGI330_EModeIDTable[]=
+  {0xff,0x0000,0x0000,0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00}
+ };
+ 
+-XGI_StandTableStruct XGI330_StandTable[]=
++struct XGI_StandTableStruct XGI330_StandTable[] =
+ {
+ /* MD_0_200 */
+  {
+@@ -746,13 +746,13 @@ XGI_StandTableStruct XGI330_StandTable[]=
+  }
+ };
+ 
+-XGI_TimingHStruct XGI_TimingH[]=
++struct XGI_TimingHStruct XGI_TimingH[] =
+ {{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}};
+ 
+-XGI_TimingVStruct XGI_TimingV[]=
++struct XGI_TimingVStruct XGI_TimingV[] =
+ {{{0x00,0x00,0x00,0x00,0x00,0x00,0x00}}};
+ 
+-XGI_XG21CRT1Struct XGI_UpdateCRT1Table[]=
++struct XGI_XG21CRT1Struct XGI_UpdateCRT1Table[] =
+ {
+  {0x01,0x27,0x91,0x8f,0xc0},	/* 00 */
+  {0x03,0x4f,0x83,0x8f,0xc0},	/* 01 */
+@@ -773,7 +773,7 @@ XGI_XG21CRT1Struct XGI_UpdateCRT1Table[]=
+  {0x59,0x27,0x91,0x8f,0xc0}	/* 16 */
+ };
+ 
+-XGI_CRT1TableStruct XGI_CRT1Table[]=
++struct XGI_CRT1TableStruct XGI_CRT1Table[] =
+ {
+  {{0x2d,0x28,0x90,0x2c,0x90,0x00,0x04,0x00,
+     0xbf,0x1f,0x9c,0x8e,0x96,0xb9,0x30}}, /* 0x0 */
+@@ -921,7 +921,7 @@ XGI_CRT1TableStruct XGI_CRT1Table[]=
+     0x03,0xDE,0xC0,0x84,0xBF,0x04,0x90}}  /* 0x47 */
+ };
+ 
+-XGI330_CHTVRegDataStruct XGI_CHTVRegUNTSC[] = {
++struct XGI330_CHTVRegDataStruct XGI_CHTVRegUNTSC[] = {
+                 /* Index:000h,001h,002h,004h,003h,005h,006h,007h,008h,015h,01Fh,00Ch,00Dh,00Eh,00Fh,010h */
+                 {{      0x4A,0x77,0xBB,0x94,0x84,0x48,0xFE,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01  }},/* 00 (640x200,640x400) */
+                 {{      0x4A,0x77,0xBB,0x94,0x84,0x48,0xFE,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01  }},/* 01 (640x350) */
+@@ -932,7 +932,7 @@ XGI330_CHTVRegDataStruct XGI_CHTVRegUNTSC[] = {
+                 {{      0xEE,0x77,0xBB,0x66,0x87,0x32,0x01,0x5A,0x04,0x00,0x80,0x1B,0xD4,0x2F,0x6F,0x00  }}/* 06 (1024x768) ;;5/6/02 */
+           };
+ 
+-XGI330_CHTVRegDataStruct XGI_CHTVRegONTSC[]= {
++struct XGI330_CHTVRegDataStruct XGI_CHTVRegONTSC[] = {
+                 /* Index:000h,001h,002h,004h,003h,005h,006h,007h,008h,015h,01Fh,00Ch,00Dh,00Eh,00Fh,010h */
+                 {{      0x49,0x77,0xBB,0x7B,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01  }},/* 00 (640x200,640x400) */
+                 {{      0x49,0x77,0xBB,0x7B,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01  }},/* 01 (640x350) */
+@@ -943,7 +943,7 @@ XGI330_CHTVRegDataStruct XGI_CHTVRegONTSC[]= {
+                 {{      0xED,0x77,0xBB,0x66,0x8C,0x21,0x02,0x5A,0x04,0x00,0x80,0x1F,0xA0,0x7E,0x73,0x00  }}/* 06 (1024x768) ;;5/6/02 */
+           };
+ 
+-XGI330_CHTVRegDataStruct XGI_CHTVRegUPAL[]=  {
++struct XGI330_CHTVRegDataStruct XGI_CHTVRegUPAL[] = {
+                 /* Index:000h,001h,002h,004h,003h,005h,006h,007h,008h,015h,01Fh,00Ch,00Dh,00Eh,00Fh,010h */
+                 {{      0x41,0x7F,0xB7,0x34,0xAD,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01  }},/* ; 00 (640x200,640x400) */
+                 {{      0x41,0x7F,0xB7,0x80,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01  }},/* ; 01 (640x350) */
+@@ -954,7 +954,7 @@ XGI330_CHTVRegDataStruct XGI_CHTVRegUPAL[]=  {
+                 {{      0xE5,0x7F,0xB7,0x1D,0xA7,0x3E,0x04,0x5A,0x05,0x00,0x80,0x20,0x3E,0xE4,0x22,0x00  }}/* ; 06 (1024x768) ;;1/12/02 */
+ 	  };
+ 
+-XGI330_CHTVRegDataStruct XGI_CHTVRegOPAL[]={
++struct XGI330_CHTVRegDataStruct XGI_CHTVRegOPAL[] = {
+                 /* Index:000,0x01,0x02,0x04,0x03,0x05,0x06,0x07,0x08,0x15,0x1F,0x0C,0x0D,0x0E,0x0F,0x10h */
+                 {{      0x41,0x7F,0xB7,0x36,0xAD,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 00 (640x200,640x400) */
+                 {{      0x41,0x7F,0xB7,0x86,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 01 (640x350) */
+@@ -972,7 +972,7 @@ unsigned char XGI_CH7017LV1400x1050[] = {0x60, 0x03, 0x11, 0x00, 0x40, 0xE3, 0xA
+ 
+ 
+ /*add for new UNIVGABIOS*/
+-XGI330_LCDDataStruct  XGI_StLCD1024x768Data[]=
++struct XGI330_LCDDataStruct  XGI_StLCD1024x768Data[] =
+ {
+  {   62,  25, 800, 546,1344, 806},
+  {   32,  15, 930, 546,1344, 806},
+@@ -983,7 +983,7 @@ XGI330_LCDDataStruct  XGI_StLCD1024x768Data[]=
+  {    1,   1,1344, 806,1344, 806}
+ };
+ 
+-XGI330_LCDDataStruct  XGI_ExtLCD1024x768Data[]=
++struct XGI330_LCDDataStruct  XGI_ExtLCD1024x768Data[] =
+ {
+  {   42,  25,1536, 419,1344, 806}, /* { 12, 5, 896, 512,1344, 806}, // alan 09/12/2003 */
+  {   48,  25,1536, 369,1344, 806}, /* { 12, 5, 896, 510,1344, 806}, // alan 09/12/2003 */
+@@ -1000,7 +1000,7 @@ XGI330_LCDDataStruct  XGI_ExtLCD1024x768Data[]=
+  {    1,   1,1344, 806,1344, 806}
+ };
+ 
+-/*XGI330_LCDDataStruct  XGI_St2LCD1024x768Data[]=
++/*struct XGI330_LCDDataStruct  XGI_St2LCD1024x768Data[] =
+ {
+  {   62,  25, 800, 546,1344, 806},
+  {   32,  15, 930, 546,1344, 806},
+@@ -1011,7 +1011,7 @@ XGI330_LCDDataStruct  XGI_ExtLCD1024x768Data[]=
+  {    1,   1,1344, 806,1344, 806}
+ };*/
+ 
+-XGI330_LCDDataStruct  XGI_CetLCD1024x768Data[]=
++struct XGI330_LCDDataStruct  XGI_CetLCD1024x768Data[] =
+ {
+ 	{         1,1,1344,806,1344,806           }, /* ; 00 (320x200,320x400,640x200,640x400) */
+         {         1,1,1344,806,1344,806           }, /* 01 (320x350,640x350) */
+@@ -1022,7 +1022,7 @@ XGI330_LCDDataStruct  XGI_CetLCD1024x768Data[]=
+         {         1,1,1344,806,1344,806           }  /* 06 (1024x768x60Hz) */
+ };
+ 
+-XGI330_LCDDataStruct  XGI_StLCD1280x1024Data[]=
++struct XGI330_LCDDataStruct  XGI_StLCD1280x1024Data[] =
+ {
+  {   22,   5, 800, 510,1650,1088},
+  {   22,   5, 800, 510,1650,1088},
+@@ -1034,7 +1034,7 @@ XGI330_LCDDataStruct  XGI_StLCD1280x1024Data[]=
+  {    1,   1,1688,1066,1688,1066}
+ };
+ 
+-XGI330_LCDDataStruct  XGI_ExtLCD1280x1024Data[]=
++struct XGI330_LCDDataStruct  XGI_ExtLCD1280x1024Data[] =
+ {
+  {  211,  60,1024, 501,1688,1066},
+  {  211,  60,1024, 508,1688,1066},
+@@ -1046,7 +1046,7 @@ XGI330_LCDDataStruct  XGI_ExtLCD1280x1024Data[]=
+  {    1,   1,1688,1066,1688,1066}
+ };
+ 
+-XGI330_LCDDataStruct  XGI_St2LCD1280x1024Data[]=
++struct XGI330_LCDDataStruct  XGI_St2LCD1280x1024Data[] =
+ {
+  {   22,   5, 800, 510,1650,1088},
+  {   22,   5, 800, 510,1650,1088},
+@@ -1058,7 +1058,7 @@ XGI330_LCDDataStruct  XGI_St2LCD1280x1024Data[]=
+  {    1,   1,1688,1066,1688,1066}
+ };
+ 
+-XGI330_LCDDataStruct  XGI_CetLCD1280x1024Data[]=
++struct XGI330_LCDDataStruct  XGI_CetLCD1280x1024Data[] =
+ {
+ 	{         1,1,1688,1066,1688,1066         }, /* 00 (320x200,320x400,640x200,640x400) */
+         {         1,1,1688,1066,1688,1066         }, /* 01 (320x350,640x350) */
+@@ -1071,7 +1071,7 @@ XGI330_LCDDataStruct  XGI_CetLCD1280x1024Data[]=
+         {         1,1,1688,1066,1688,1066         } /* 08 (1400x1050x60Hz) */
+ };
+ 
+-XGI330_LCDDataStruct  XGI_StLCD1400x1050Data[]=
++struct XGI330_LCDDataStruct  XGI_StLCD1400x1050Data[] =
+ {
+ 	{         211,100,2100,408,1688,1066      }, /* 00 (320x200,320x400,640x200,640x400) */
+         {         211,64,1536,358,1688,1066       }, /* 01 (320x350,640x350) */
+@@ -1084,7 +1084,7 @@ XGI330_LCDDataStruct  XGI_StLCD1400x1050Data[]=
+         {         1,1,1688,1066,1688,1066         }  /* 08 (1400x1050x60Hz) */
+ };
+ 
+-XGI330_LCDDataStruct  XGI_ExtLCD1400x1050Data[]=
++struct XGI330_LCDDataStruct  XGI_ExtLCD1400x1050Data[] =
+ {
+ 	{         211,100,2100,408,1688,1066      }, /* 00 (320x200,320x400,640x200,640x400) */
+         {         211,64,1536,358,1688,1066       }, /* 01 (320x350,640x350) */
+@@ -1097,7 +1097,7 @@ XGI330_LCDDataStruct  XGI_ExtLCD1400x1050Data[]=
+         {         1,1,1688,1066,1688,1066         }  /* 08 (1400x1050x60Hz) */
+ };
+ 
+-XGI330_LCDDataStruct  XGI_ExtLCD1600x1200Data[]=
++struct XGI330_LCDDataStruct  XGI_ExtLCD1600x1200Data[] =
+ {
+         {         4,1,1620,420,2160,1250          }, /* { 3,1,2160,425,2160,1250 }, // 00 (320x200,320x400,640x200,640x400) // alan 10/14/2003 */
+         {         27,7,1920,375,2160,1250         }, /* 01 (320x350,640x350) */
+@@ -1111,7 +1111,7 @@ XGI330_LCDDataStruct  XGI_ExtLCD1600x1200Data[]=
+         {         1,1,2160,1250,2160,1250         }  /* 09 (1600x1200x60Hz) ;302lv */
+ };
+ 
+-XGI330_LCDDataStruct  XGI_StLCD1600x1200Data[]=
++struct XGI330_LCDDataStruct  XGI_StLCD1600x1200Data[] =
+ {
+         {         27,4,800,500,2160,1250          },/* 00 (320x200,320x400,640x200,640x400) */
+         {         27,4,800,500,2160,1250          },/* 01 (320x350,640x350) */
+@@ -1125,7 +1125,7 @@ XGI330_LCDDataStruct  XGI_StLCD1600x1200Data[]=
+         {         1,1,2160,1250,2160,1250         } /* 09 (1600x1200) */
+ };
+ 
+-XGI330_LCDDataStruct  XGI_CetLCD1400x1050Data[]=
++struct XGI330_LCDDataStruct  XGI_CetLCD1400x1050Data[] =
+ {
+ 	{         1,1,1688,1066,1688,1066         }, /* 00 (320x200,320x400,640x200,640x400) */
+         {         1,1,1688,1066,1688,1066         }, /* 01 (320x350,640x350) */
+@@ -1138,7 +1138,7 @@ XGI330_LCDDataStruct  XGI_CetLCD1400x1050Data[]=
+         {         1,1,1688,1066,1688,1066         }  /* 08 (1400x1050x60Hz) */
+ };
+ 
+-XGI330_LCDDataStruct  XGI_NoScalingData[]=
++struct XGI330_LCDDataStruct  XGI_NoScalingData[] =
+ {
+  {    1,   1, 800, 449, 800, 449},
+  {    1,   1, 800, 449, 800, 449},
+@@ -1150,7 +1150,7 @@ XGI330_LCDDataStruct  XGI_NoScalingData[]=
+  {    1,   1,1688,1066,1688,1066}
+ };
+ 
+-XGI330_LCDDataStruct  XGI_ExtLCD1024x768x75Data[]=
++struct XGI330_LCDDataStruct  XGI_ExtLCD1024x768x75Data[] =
+ {
+         {42,25,1536,419,1344,806 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+         {48,25,1536,369,1344,806 }, /* ; 01 (320x350,640x350) */
+@@ -1161,7 +1161,7 @@ XGI330_LCDDataStruct  XGI_ExtLCD1024x768x75Data[]=
+         {1,1,1312,800,1312,800   }  /* ; 06 (1024x768x75Hz) */
+ };
+ 
+-XGI330_LCDDataStruct  XGI_StLCD1024x768x75Data[]=
++struct XGI330_LCDDataStruct  XGI_StLCD1024x768x75Data[] =
+ {
+         {42,25,1536,419,1344,806 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+         {48,25,1536,369,1344,806 }, /* ; 01 (320x350,640x350) */
+@@ -1172,7 +1172,7 @@ XGI330_LCDDataStruct  XGI_StLCD1024x768x75Data[]=
+         {1,1,1312,800,1312,800   }  /* ; 06 (1024x768x75Hz) */
+ };
+ 
+-XGI330_LCDDataStruct  XGI_CetLCD1024x768x75Data[]=
++struct XGI330_LCDDataStruct  XGI_CetLCD1024x768x75Data[] =
+ {
+         {1,1,1312,800,1312,800}, /* ; 00 (320x200,320x400,640x200,640x400) */
+         {1,1,1312,800,1312,800}, /* ; 01 (320x350,640x350) */
+@@ -1183,7 +1183,7 @@ XGI330_LCDDataStruct  XGI_CetLCD1024x768x75Data[]=
+         {1,1,1312,800,1312,800} /* ; 06 (1024x768x75Hz) */
+ };
+ 
+-XGI330_LCDDataStruct  XGI_ExtLCD1280x1024x75Data[]=
++struct XGI330_LCDDataStruct  XGI_ExtLCD1280x1024x75Data[] =
+ {
+         {211,60,1024,501,1688,1066   }, /* ; 00 (320x200,320x400,640x200,640x400) */
+         {211,60,1024,508,1688,1066   }, /* ; 01 (320x350,640x350) */
+@@ -1195,7 +1195,7 @@ XGI330_LCDDataStruct  XGI_ExtLCD1280x1024x75Data[]=
+         {1,1,1688,1066,1688,1066     }  /* ; 07 (1280x1024x75Hz) */
+ };
+ 
+-XGI330_LCDDataStruct  XGI_StLCD1280x1024x75Data[]=
++struct XGI330_LCDDataStruct  XGI_StLCD1280x1024x75Data[] =
+ {
+         {211,60,1024,501,1688,1066 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+         {211,60,1024,508,1688,1066 }, /* ; 01 (320x350,640x350) */
+@@ -1207,7 +1207,7 @@ XGI330_LCDDataStruct  XGI_StLCD1280x1024x75Data[]=
+         {1,1,1688,1066,1688,1066   }  /* ; 07 (1280x1024x75Hz) */
+ };
+ 
+-XGI330_LCDDataStruct  XGI_CetLCD1280x1024x75Data[]=
++struct XGI330_LCDDataStruct  XGI_CetLCD1280x1024x75Data[] =
+ {
+         {1,1,1688,1066,1688,1066}, /* ; 00 (320x200,320x400,640x200,640x400) */
+         {1,1,1688,1066,1688,1066}, /* ; 01 (320x350,640x350) */
+@@ -1219,7 +1219,7 @@ XGI330_LCDDataStruct  XGI_CetLCD1280x1024x75Data[]=
+         {1,1,1688,1066,1688,1066}  /* ; 07 (1280x1024x75Hz) */
+ };
+ 
+-XGI330_LCDDataStruct  XGI_NoScalingDatax75[]=
++struct XGI330_LCDDataStruct  XGI_NoScalingDatax75[] =
+ {
+         {1,1,800,449,800,449    }, /* ; 00 (320x200,320x400,640x200,640x400) */
+         {1,1,800,449,800,449    }, /* ; 01 (320x350,640x350) */
+@@ -1234,7 +1234,7 @@ XGI330_LCDDataStruct  XGI_NoScalingDatax75[]=
+         {1,1,1688,806,1688,806  }  /* ; 0A (1280x768x75Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct  XGI_ExtLCDDes1024x768Data[]=
++struct XGI330_LCDDataDesStruct  XGI_ExtLCDDes1024x768Data[] =
+ {
+    {  9,1057,0, 771  }, /* ; 00 (320x200,320x400,640x200,640x400) */
+    {  9,1057,0, 771  }, /* ; 01 (320x350,640x350) */
+@@ -1245,7 +1245,7 @@ XGI330_LCDDataDesStruct  XGI_ExtLCDDes1024x768Data[]=
+    {  9,1057,805, 770  }  /* ; 06 (1024x768x60Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct  XGI_StLCDDes1024x768Data[]=
++struct XGI330_LCDDataDesStruct  XGI_StLCDDes1024x768Data[] =
+ {
+         { 9,1057,737,703   }, /* ; 00 (320x200,320x400,640x200,640x400) */
+         { 9,1057,686,651   }, /* ; 01 (320x350,640x350) */
+@@ -1256,7 +1256,7 @@ XGI330_LCDDataDesStruct  XGI_StLCDDes1024x768Data[]=
+         { 9,1057,805,770   }  /* ; 06 (1024x768x60Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct  XGI_CetLCDDes1024x768Data[]=
++struct XGI330_LCDDataDesStruct  XGI_CetLCDDes1024x768Data[] =
+ {
+        	{      1152,856,622,587   }, /* ; 00 (320x200,320x400,640x200,640x400) */
+         {      1152,856,597,562   }, /* ; 01 (320x350,640x350) */
+@@ -1267,7 +1267,7 @@ XGI330_LCDDataDesStruct  XGI_CetLCDDes1024x768Data[]=
+         {      0,1048,805,770   }  /* ; 06 (1024x768x60Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct XGI_ExtLCDDLDes1280x1024Data[]=
++struct XGI330_LCDDataDesStruct XGI_ExtLCDDLDes1280x1024Data[] =
+ {
+         {      18,1346,981,940     },/* 00 (320x200,320x400,640x200,640x400) */
+         {      18,1346,926,865     },/* 01 (320x350,640x350) */
+@@ -1279,7 +1279,7 @@ XGI330_LCDDataDesStruct XGI_ExtLCDDLDes1280x1024Data[]=
+         {      18,1346,1065,1024     }/* 07 (1280x1024x60Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct XGI_StLCDDLDes1280x1024Data[]=
++struct XGI330_LCDDataDesStruct XGI_StLCDDLDes1280x1024Data[] =
+ {
+         {      18,1346,970,907     },/* 00 (320x200,320x400,640x200,640x400) */
+         {      18,1346,917,854     },/* 01 (320x350,640x350) */
+@@ -1291,7 +1291,7 @@ XGI330_LCDDataDesStruct XGI_StLCDDLDes1280x1024Data[]=
+         {      18,1346,1065,1024     }/* 07 (1280x1024x60Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct  XGI_CetLCDDLDes1280x1024Data[]=
++struct XGI330_LCDDataDesStruct  XGI_CetLCDDLDes1280x1024Data[] =
+ {
+         {      1368,1008,752,711    }, /* 00 (320x200,320x400,640x200,640x400) */
+         {      1368,1008,729,688    }, /* 01 (320x350,640x350) */
+@@ -1303,7 +1303,7 @@ XGI330_LCDDataDesStruct  XGI_CetLCDDLDes1280x1024Data[]=
+         {      18,1346,1065,1024    }  /* 07 (1280x1024x60Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct  XGI_ExtLCDDes1280x1024Data[]=
++struct XGI330_LCDDataDesStruct  XGI_ExtLCDDes1280x1024Data[] =
+ {
+         {      9,1337,981,940    }, /* ; 00 (320x200,320x400,640x200,640x400) */
+         {      9,1337,926,884    }, /* ; 01 (320x350,640x350) alan, 2003/09/30 */
+@@ -1315,7 +1315,7 @@ XGI330_LCDDataDesStruct  XGI_ExtLCDDes1280x1024Data[]=
+         {      9,1337,1065,1024    }  /* ; 07 (1280x1024x60Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct  XGI_StLCDDes1280x1024Data[]=
++struct XGI330_LCDDataDesStruct  XGI_StLCDDes1280x1024Data[] =
+ {
+         {      9,1337,970,907    }, /* ; 00 (320x200,320x400,640x200,640x400) */
+         {      9,1337,917,854    }, /* ; 01 (320x350,640x350) */
+@@ -1327,7 +1327,7 @@ XGI330_LCDDataDesStruct  XGI_StLCDDes1280x1024Data[]=
+         {      9,1337,1065,1024    }  /* ; 07 (1280x1024x60Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct  XGI_CetLCDDes1280x1024Data[]=
++struct XGI330_LCDDataDesStruct  XGI_CetLCDDes1280x1024Data[] =
+ {
+         {      1368,1008,752,711    }, /* 00 (320x200,320x400,640x200,640x400) */
+         {      1368,1008,729,688    }, /* 01 (320x350,640x350) */
+@@ -1339,7 +1339,7 @@ XGI330_LCDDataDesStruct  XGI_CetLCDDes1280x1024Data[]=
+         {      9,1337,1065,1024    }  /* 07 (1280x1024x60Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct  XGI_StLCDDLDes1400x1050Data[]=
++struct XGI330_LCDDataDesStruct  XGI_StLCDDLDes1400x1050Data[] =
+ {
+         {      18,1464,0,1051    }, /* 00 (320x200,320x400,640x200,640x400) */
+         {      18,1464,0,1051    }, /* 01 (320x350,640x350) */
+@@ -1352,7 +1352,7 @@ XGI330_LCDDataDesStruct  XGI_StLCDDLDes1400x1050Data[]=
+         {      18,1464,0,1051    }  /* 08 (1400x1050x60Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct  XGI_ExtLCDDLDes1400x1050Data[]=
++struct XGI330_LCDDataDesStruct  XGI_ExtLCDDLDes1400x1050Data[] =
+ {
+         {      18,1464,0,1051    }, /* 00 (320x200,320x400,640x200,640x400) */
+         {      18,1464,0,1051    }, /* 01 (320x350,640x350) */
+@@ -1365,7 +1365,7 @@ XGI330_LCDDataDesStruct  XGI_ExtLCDDLDes1400x1050Data[]=
+         {      18,1464,0,1051    }  /* 08 (1400x1050x60Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct  XGI_StLCDDes1400x1050Data[]=
++struct XGI330_LCDDataDesStruct  XGI_StLCDDes1400x1050Data[] =
+ {
+         {      9,1455,0,1051     },/* 00 (320x200,320x400,640x200,640x400) */
+         {      9,1455,0,1051     },/* 01 (320x350,640x350) */
+@@ -1378,7 +1378,7 @@ XGI330_LCDDataDesStruct  XGI_StLCDDes1400x1050Data[]=
+         {      9,1455,0,1051     } /* 08 (1400x1050x60Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct  XGI_ExtLCDDes1400x1050Data[]=
++struct XGI330_LCDDataDesStruct  XGI_ExtLCDDes1400x1050Data[] =
+ {
+         {      9,1455,0,1051     },/* 00 (320x200,320x400,640x200,640x400) */
+         {      9,1455,0,1051     },/* 01 (320x350,640x350) */
+@@ -1391,7 +1391,7 @@ XGI330_LCDDataDesStruct  XGI_ExtLCDDes1400x1050Data[]=
+         {      9,1455,0,1051     } /* 08 (1400x1050x60Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct  XGI_CetLCDDes1400x1050Data[]=
++struct XGI330_LCDDataDesStruct  XGI_CetLCDDes1400x1050Data[] =
+ {
+         {      1308,1068,781,766    }, /* 00 (320x200,320x400,640x200,640x400) */
+         {      1308,1068,781,766    }, /* 01 (320x350,640x350) */
+@@ -1404,7 +1404,7 @@ XGI330_LCDDataDesStruct  XGI_CetLCDDes1400x1050Data[]=
+         {      18,1464,0,1051    } /* 08 (1400x1050x60Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct  XGI_CetLCDDes1400x1050Data2[]=
++struct XGI330_LCDDataDesStruct  XGI_CetLCDDes1400x1050Data2[] =
+ {
+         {      0,1448,0,1051    }, /* 00 (320x200,320x400,640x200,640x400) */
+         {      0,1448,0,1051    }, /* 01 (320x350,640x350) */
+@@ -1415,7 +1415,7 @@ XGI330_LCDDataDesStruct  XGI_CetLCDDes1400x1050Data2[]=
+ 
+ 
+ 
+-XGI330_LCDDataDesStruct  XGI_ExtLCDDLDes1600x1200Data[]=
++struct XGI330_LCDDataDesStruct  XGI_ExtLCDDLDes1600x1200Data[] =
+ {
+ 	{      18,1682,0,1201    }, /* 00 (320x200,320x400,640x200,640x400) */
+         {      18,1682,0,1201    }, /* 01 (320x350,640x350) */
+@@ -1429,7 +1429,7 @@ XGI330_LCDDataDesStruct  XGI_ExtLCDDLDes1600x1200Data[]=
+         {      18,1682,0,1201    }  /* 09 (1600x1200x60Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct  XGI_StLCDDLDes1600x1200Data[]=
++struct XGI330_LCDDataDesStruct  XGI_StLCDDLDes1600x1200Data[] =
+ {
+         {      18,1682,1150,1101    }, /* 00 (320x200,320x400,640x200,640x400) */
+         {      18,1682,1083,1034    }, /* 01 (320x350,640x350) */
+@@ -1443,7 +1443,7 @@ XGI330_LCDDataDesStruct  XGI_StLCDDLDes1600x1200Data[]=
+         {      18,1682,0,1201    } /* 09 (1600x1200x60Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct  XGI_ExtLCDDes1600x1200Data[]=
++struct XGI330_LCDDataDesStruct  XGI_ExtLCDDes1600x1200Data[] =
+ {
+         {      9,1673,0,1201     },/* 00 (320x200,320x400,640x200,640x400) */
+         {      9,1673,0,1201     },/* 01 (320x350,640x350) */
+@@ -1457,7 +1457,7 @@ XGI330_LCDDataDesStruct  XGI_ExtLCDDes1600x1200Data[]=
+         {      9,1673,0,1201     } /* 09 (1600x1200x60Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct  XGI_StLCDDes1600x1200Data[]=
++struct XGI330_LCDDataDesStruct  XGI_StLCDDes1600x1200Data[] =
+ {
+ 	{      9,1673,1150,1101     },/* 00 (320x200,320x400,640x200,640x400) */
+         {      9,1673,1083,1034     },/* 01 (320x350,640x350) */
+@@ -1471,7 +1471,7 @@ XGI330_LCDDataDesStruct  XGI_StLCDDes1600x1200Data[]=
+         {      9,1673,0,1201     } /* 09 (1600x1200x60Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct2  XGI_NoScalingDesData[]=
++struct XGI330_LCDDataDesStruct2  XGI_NoScalingDesData[] =
+ {
+         {     9,657,448,405,96,2  }, /* 00 (320x200,320x400,640x200,640x400) */
+         {     9,657,448,355,96,2  }, /* 01 (320x350,640x350) */
+@@ -1486,7 +1486,7 @@ XGI330_LCDDataDesStruct2  XGI_NoScalingDesData[]=
+         {     9,1337,0,771,112,6  }  /* 0A (1280x768x60Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct  XGI_ExtLCDDes1024x768x75Data[]=		/* ;;1024x768x75Hz */
++struct XGI330_LCDDataDesStruct  XGI_ExtLCDDes1024x768x75Data[] =		/* ;;1024x768x75Hz */
+ {
+         {9,1049,0,769},    /* ; 00 (320x200,320x400,640x200,640x400) */
+         {9,1049,0,769},    /* ; 01 (320x350,640x350) */
+@@ -1497,7 +1497,7 @@ XGI330_LCDDataDesStruct  XGI_ExtLCDDes1024x768x75Data[]=		/* ;;1024x768x75Hz */
+         {9,1049,0,769}     /* ; 06 (1024x768x75Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct  XGI_StLCDDes1024x768x75Data[]=
++struct XGI330_LCDDataDesStruct  XGI_StLCDDes1024x768x75Data[] =
+ {
+         {9,1049,0,769},    /* ; 00 (320x200,320x400,640x200,640x400) */
+         {9,1049,0,769},    /* ; 01 (320x350,640x350) */
+@@ -1508,7 +1508,7 @@ XGI330_LCDDataDesStruct  XGI_StLCDDes1024x768x75Data[]=
+         {9,1049,0,769}     /* ; 06 (1024x768x75Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct  XGI_CetLCDDes1024x768x75Data[]=	/* ;;1024x768x75Hz */
++struct XGI330_LCDDataDesStruct  XGI_CetLCDDes1024x768x75Data[] =	/* ;;1024x768x75Hz */
+ {
+         {1152,856,622,587},     /* ; 00 (320x200,320x400,640x200,640x400) */
+         {1152,856,597,562},     /* ; 01 (320x350,640x350) */
+@@ -1519,7 +1519,7 @@ XGI330_LCDDataDesStruct  XGI_CetLCDDes1024x768x75Data[]=	/* ;;1024x768x75Hz */
+         {9,1049,0,769} 	   	/* ; 06 (1024x768x75Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct  XGI_ExtLCDDLDes1280x1024x75Data[]=         /* ;;1280x1024x75Hz */
++struct XGI330_LCDDataDesStruct  XGI_ExtLCDDLDes1280x1024x75Data[] =         /* ;;1280x1024x75Hz */
+ {
+         {18,1314,0,1025     },/* ; 00 (320x200,320x400,640x200,640x400) */
+         {18,1314,0,1025     },/* ; 01 (320x350,640x350) */
+@@ -1531,7 +1531,7 @@ XGI330_LCDDataDesStruct  XGI_ExtLCDDLDes1280x1024x75Data[]=         /* ;;1280x10
+         {18,1314,0,1025     }/* ; 07 (1280x1024x60Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct  XGI_StLCDDLDes1280x1024x75Data[]=
++struct XGI330_LCDDataDesStruct  XGI_StLCDDLDes1280x1024x75Data[] =
+ {
+         {18,1314,0,1025     },/* ; 00 (320x200,320x400,640x200,640x400) */
+         {18,1314,0,1025     },/* ; 01 (320x350,640x350) */
+@@ -1543,7 +1543,7 @@ XGI330_LCDDataDesStruct  XGI_StLCDDLDes1280x1024x75Data[]=
+         {18,1314,0,1025     }/* ; 07 (1280x1024x60Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct  XGI_CetLCDDLDes1280x1024x75Data[]=	/* 1280x1024x75Hz */
++struct XGI330_LCDDataDesStruct  XGI_CetLCDDLDes1280x1024x75Data[] =	/* 1280x1024x75Hz */
+ {
+         {1368,1008,752,711},    /* ; 00 (320x200,320x400,640x200,640x400) */
+         {1368,1008,729,688},    /* ; 01 (320x350,640x350) */
+@@ -1555,7 +1555,7 @@ XGI330_LCDDataDesStruct  XGI_CetLCDDLDes1280x1024x75Data[]=	/* 1280x1024x75Hz */
+         {18,1314,0,1025}     	  /* ; 07 (1280x1024x75Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct  XGI_ExtLCDDes1280x1024x75Data[]=         /* ;;1280x1024x75Hz */
++struct XGI330_LCDDataDesStruct  XGI_ExtLCDDes1280x1024x75Data[] =         /* ;;1280x1024x75Hz */
+ {
+ 	{9,1305,0,1025},/* ; 00 (320x200,320x400,640x200,640x400) */
+         {9,1305,0,1025},/* ; 01 (320x350,640x350) */
+@@ -1567,7 +1567,7 @@ XGI330_LCDDataDesStruct  XGI_ExtLCDDes1280x1024x75Data[]=         /* ;;1280x1024
+         {9,1305,0,1025} /* ; 07 (1280x1024x60Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct  XGI_StLCDDes1280x1024x75Data[]=
++struct XGI330_LCDDataDesStruct  XGI_StLCDDes1280x1024x75Data[] =
+ {
+ 	{9,1305,0,1025},/* ; 00 (320x200,320x400,640x200,640x400) */
+         {9,1305,0,1025},/* ; 01 (320x350,640x350) */
+@@ -1579,7 +1579,7 @@ XGI330_LCDDataDesStruct  XGI_StLCDDes1280x1024x75Data[]=
+         {9,1305,0,1025} /* ; 07 (1280x1024x60Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct  XGI_CetLCDDes1280x1024x75Data[]=	/* 1280x1024x75Hz */
++struct XGI330_LCDDataDesStruct  XGI_CetLCDDes1280x1024x75Data[] =	/* 1280x1024x75Hz */
+ {
+         {1368,1008,752,711},    /* ; 00 (320x200,320x400,640x200,640x400) */
+         {1368,1008,729,688},    /* ; 01 (320x350,640x350) */
+@@ -1591,7 +1591,7 @@ XGI330_LCDDataDesStruct  XGI_CetLCDDes1280x1024x75Data[]=	/* 1280x1024x75Hz */
+         {9,1305,0,1025}     	  /* ; 07 (1280x1024x75Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct2 XGI_NoScalingDesDatax75[]= /* Scaling LCD 75Hz */
++struct XGI330_LCDDataDesStruct2 XGI_NoScalingDesDatax75[] = /* Scaling LCD 75Hz */
+ {
+ 	{9,657,448,405,96,2},   /* ; 00 (320x200,320x400,640x200,640x400) */
+         {9,657,448,355,96,2},   /* ; 01 (320x350,640x350) */
+@@ -1606,7 +1606,7 @@ XGI330_LCDDataDesStruct2 XGI_NoScalingDesDatax75[]= /* Scaling LCD 75Hz */
+         {9,1337,0,771,112,6}    /* ; 0A (1280x768x60Hz) */
+ };
+ 
+-XGI330_TVDataStruct  XGI_StPALData[]=
++struct XGI330_TVDataStruct  XGI_StPALData[] =
+ {
+  {    1,   1, 864, 525,1270, 400, 100,   0, 760},
+  {    1,   1, 864, 525,1270, 350, 100,   0, 760},
+@@ -1616,7 +1616,7 @@ XGI330_TVDataStruct  XGI_StPALData[]=
+  {    1,   1, 864, 525,1270, 600,  50,   0,   0}
+ };
+ 
+-XGI330_TVDataStruct  XGI_ExtPALData[]=
++struct XGI330_TVDataStruct  XGI_ExtPALData[] =
+ {
+  {    2,   1,1080, 463,1270, 500,  50,   0,  50},
+  {   15,   7,1152, 413,1270, 500,  50,   0,  50},
+@@ -1628,7 +1628,7 @@ XGI330_TVDataStruct  XGI_ExtPALData[]=
+  {    3,   2,1080, 619,1270, 540, 438,   0, 438}
+ };
+ 
+-XGI330_TVDataStruct  XGI_StNTSCData[]=
++struct XGI330_TVDataStruct  XGI_StNTSCData[] =
+ {
+  {    1,   1, 858, 525,1270, 400,  50,   0, 760},
+  {    1,   1, 858, 525,1270, 350,  50,   0, 640},
+@@ -1637,7 +1637,7 @@ XGI330_TVDataStruct  XGI_StNTSCData[]=
+  {    1,   1, 858, 525,1270, 480,   0,   0, 760}
+ };
+ 
+-XGI330_TVDataStruct  XGI_ExtNTSCData[]=
++struct XGI330_TVDataStruct  XGI_ExtNTSCData[] =
+ {
+  {    9,  5, 1001, 453,1270, 420, 171,   0, 171},
+  {   12,  5,  858, 403,1270, 420, 171,   0, 171},
+@@ -1650,7 +1650,7 @@ XGI330_TVDataStruct  XGI_ExtNTSCData[]=
+  {    3,   2,1001, 533,1270, 420,   0,   0,   0}
+ };
+ 
+-XGI330_TVDataStruct  XGI_St1HiTVData[]=
++struct XGI330_TVDataStruct  XGI_St1HiTVData[] =
+ {
+     	{        1,1,892,563,690,800,0,0,0               }, /* 00 (320x200,320x400,640x200,640x400) */
+         {        1,1,892,563,690,700,0,0,0               }, /* 01 (320x350,640x350) */
+@@ -1660,7 +1660,7 @@ XGI330_TVDataStruct  XGI_St1HiTVData[]=
+         {        8,5,1050,683,1648,960,0x150,1,0         }  /* 05 (400x300,800x600) */
+ };
+ 
+-XGI330_TVDataStruct  XGI_St2HiTVData[]=
++struct XGI330_TVDataStruct  XGI_St2HiTVData[] =
+ {
+         {        3,1,840,483,1648,960,0x032,0,0          }, /* 00 (320x200,320x400,640x200,640x400) */
+         {        1,1,892,563,690,700,0,0,0               }, /* 01 (320x350,640x350) */
+@@ -1671,7 +1671,7 @@ XGI330_TVDataStruct  XGI_St2HiTVData[]=
+ 
+ };
+ 
+-XGI330_TVDataStruct  XGI_ExtHiTVData[]=
++struct XGI330_TVDataStruct  XGI_ExtHiTVData[] =
+ {
+         {        6,1,840,563,1632,960,0,0,0              }, /* 00 (320x200,320x400,640x200,640x400) */
+         {        3,1,960,563,1632,960,0,0,0              }, /* 01 (320x350,640x350) */
+@@ -1687,7 +1687,7 @@ XGI330_TVDataStruct  XGI_ExtHiTVData[]=
+ 
+ };
+ 
+-XGI330_TVDataStruct  XGI_ExtYPbPr525iData[]=
++struct XGI330_TVDataStruct  XGI_ExtYPbPr525iData[] =
+ {
+  {    9,  5, 1001, 453,1270, 420, 171,   0, 171},
+  {   12,  5,  858, 403,1270, 420, 171,   0, 171},
+@@ -1700,7 +1700,7 @@ XGI330_TVDataStruct  XGI_ExtYPbPr525iData[]=
+  {    3,   2,1001, 533,1250, 420,   0,   0,   0}
+ };
+ 
+-XGI330_TVDataStruct  XGI_StYPbPr525iData[]=
++struct XGI330_TVDataStruct  XGI_StYPbPr525iData[] =
+ {
+  {    1,   1, 858, 525,1270, 400,  50,   0, 760},
+  {    1,   1, 858, 525,1270, 350,  50,   0, 640},
+@@ -1709,7 +1709,7 @@ XGI330_TVDataStruct  XGI_StYPbPr525iData[]=
+  {    1,   1, 858, 525,1270, 480,   0,   0, 760},
+ };
+ 
+-XGI330_TVDataStruct  XGI_ExtYPbPr525pData[]=
++struct XGI330_TVDataStruct  XGI_ExtYPbPr525pData[] =
+ {
+  {    9,  5, 1001, 453,1270, 420, 171,   0, 171},
+  {   12,  5,  858, 403,1270, 420, 171,   0, 171},
+@@ -1722,7 +1722,7 @@ XGI330_TVDataStruct  XGI_ExtYPbPr525pData[]=
+  {    3,   2,1001, 533,1270, 420,   0,   0,   0}
+  };
+ 
+-XGI330_TVDataStruct  XGI_StYPbPr525pData[]=
++struct XGI330_TVDataStruct  XGI_StYPbPr525pData[] =
+ {
+  {    1,   1,1716, 525,1270, 400,  50,   0, 760},
+  {    1,   1,1716, 525,1270, 350,  50,   0, 640},
+@@ -1731,7 +1731,7 @@ XGI330_TVDataStruct  XGI_StYPbPr525pData[]=
+  {    1,   1,1716, 525,1270, 480,   0,   0, 760},
+ };
+ 
+-XGI330_TVDataStruct  XGI_ExtYPbPr750pData[]=
++struct XGI330_TVDataStruct  XGI_ExtYPbPr750pData[] =
+ {
+  {    3,   1, 935, 470,1130, 680,  50,   0,   0},       /* 00 (320x200,320x400,640x200,640x400) */
+  {   24,   7, 935, 420,1130, 680,  50,   0,   0},       /* 01 (320x350,640x350) */
+@@ -1746,7 +1746,7 @@ XGI330_TVDataStruct  XGI_ExtYPbPr750pData[]=
+  {   10,   9,1320, 830,1130, 640,  50,   0,   0}
+ };
+ 
+-XGI330_TVDataStruct  XGI_StYPbPr750pData[]=
++struct XGI330_TVDataStruct  XGI_StYPbPr750pData[] =
+ {
+  {    1,   1,1650, 750,1280, 400,  50,   0, 760},
+  {    1,   1,1650, 750,1280, 350,  50,   0, 640},
+@@ -1928,7 +1928,7 @@ unsigned char XGI330_Ren750pGroup3[] =
+   0x18,0x1D,0x23,0x28,0x4C,0xAA,0x01
+ };
+ 
+-XGI_PanelDelayTblStruct XGI330_PanelDelayTbl[]=
++struct XGI_PanelDelayTblStruct XGI330_PanelDelayTbl[] =
+ {
+ {{0x00,0x00}},
+ {{0x00,0x00}},
+@@ -1948,7 +1948,7 @@ XGI_PanelDelayTblStruct XGI330_PanelDelayTbl[]=
+ {{0x00,0x00}}
+ };
+ 
+-XGI330_LVDSDataStruct  XGI330_LVDS320x480Data_1[]=
++struct XGI330_LVDSDataStruct  XGI330_LVDS320x480Data_1[] =
+ {
+  {848, 433,400,525},
+  {848, 389,400,525},
+@@ -1961,7 +1961,7 @@ XGI330_LVDSDataStruct  XGI330_LVDS320x480Data_1[]=
+  {800, 525,1000, 635}
+ };
+ 
+-XGI330_LVDSDataStruct  XGI330_LVDS800x600Data_1[]=
++struct XGI330_LVDSDataStruct  XGI330_LVDS800x600Data_1[] =
+ {
+  {848, 433,1060, 629},
+  {848, 389,1060, 629},
+@@ -1974,7 +1974,7 @@ XGI330_LVDSDataStruct  XGI330_LVDS800x600Data_1[]=
+  {800, 525,1000, 635}
+ };
+ 
+-XGI330_LVDSDataStruct  XGI330_LVDS800x600Data_2[]=
++struct XGI330_LVDSDataStruct  XGI330_LVDS800x600Data_2[] =
+ {
+  {1056, 628,1056, 628},
+  {1056, 628,1056, 628},
+@@ -1987,7 +1987,7 @@ XGI330_LVDSDataStruct  XGI330_LVDS800x600Data_2[]=
+  {800, 525,1000, 635}
+ };
+ 
+-XGI330_LVDSDataStruct  XGI_LVDS1024x768Data_1[]=
++struct XGI330_LVDSDataStruct  XGI_LVDS1024x768Data_1[] =
+ {
+  { 960 , 438 , 1344 , 806 } ,	/* 00 (320x200,320x400,640x200,640x400) */
+  { 960 , 388 , 1344 , 806 } ,	/* 01 (320x350,640x350) */
+@@ -1999,7 +1999,7 @@ XGI330_LVDSDataStruct  XGI_LVDS1024x768Data_1[]=
+ };
+ 
+ 
+-XGI330_LVDSDataStruct  XGI_LVDS1024x768Data_2[]=
++struct XGI330_LVDSDataStruct  XGI_LVDS1024x768Data_2[] =
+ {
+  {1344, 806,1344, 806},
+  {1344, 806,1344, 806},
+@@ -2012,7 +2012,7 @@ XGI330_LVDSDataStruct  XGI_LVDS1024x768Data_2[]=
+  {800, 525,1280, 813}
+ };
+ 
+-XGI330_LVDSDataStruct  XGI_LVDS1280x1024Data_1[]=
++struct XGI330_LVDSDataStruct  XGI_LVDS1280x1024Data_1[] =
+ {
+  {1048, 442,1688, 1066},
+  {1048, 392,1688, 1066},
+@@ -2024,7 +2024,7 @@ XGI330_LVDSDataStruct  XGI_LVDS1280x1024Data_1[]=
+  {1688, 1066,1688, 1066}
+ };
+ 
+-XGI330_LVDSDataStruct  XGI_LVDS1280x1024Data_2[]=
++struct XGI330_LVDSDataStruct  XGI_LVDS1280x1024Data_2[] =
+ {
+  {1344, 806,1344, 806},
+  {1344, 806,1344, 806},
+@@ -2037,7 +2037,7 @@ XGI330_LVDSDataStruct  XGI_LVDS1280x1024Data_2[]=
+  {800, 525,1280, 813}
+ };
+ /*
+-XGI330_LVDSDataStruct  XGI_LVDS1280x768Data_1[]=
++struct XGI330_LVDSDataStruct  XGI_LVDS1280x768Data_1[] =
+ {
+  {768,438,1408,806},
+  {768,388,1408,806},
+@@ -2050,7 +2050,7 @@ XGI330_LVDSDataStruct  XGI_LVDS1280x768Data_1[]=
+  {1408,806,1408,806}
+ };
+ 
+-XGI330_LVDSDataStruct  XGI_LVDS1280x768Data_2[]=
++struct XGI330_LVDSDataStruct  XGI_LVDS1280x768Data_2[] =
+ {
+  {1408, 806,1408, 806},
+  {1408, 806,1408, 806},
+@@ -2063,7 +2063,7 @@ XGI330_LVDSDataStruct  XGI_LVDS1280x768Data_2[]=
+  {1408, 806,1408, 806}
+ };
+ 
+-XGI330_LVDSDataStruct  XGI_LVDS1280x768NData_1[]=
++struct XGI330_LVDSDataStruct  XGI_LVDS1280x768NData_1[] =
+ {
+  {704, 438,1344, 806},
+  {704, 388,1344, 806},
+@@ -2076,7 +2076,7 @@ XGI330_LVDSDataStruct  XGI_LVDS1280x768NData_1[]=
+  {1344, 806,1344, 806}
+ };
+ 
+-XGI330_LVDSDataStruct  XGI_LVDS1280x768NData_2[]=
++struct XGI330_LVDSDataStruct  XGI_LVDS1280x768NData_2[] =
+ {
+  {1344, 806,1344, 806},
+  {1344, 806,1344, 806},
+@@ -2089,7 +2089,7 @@ XGI330_LVDSDataStruct  XGI_LVDS1280x768NData_2[]=
+  {1344, 806,1344, 806}
+ };
+ 
+-XGI330_LVDSDataStruct  XGI_LVDS1280x768SData_1[]=
++struct XGI330_LVDSDataStruct  XGI_LVDS1280x768SData_1[] =
+ {
+  {1048,438,1688,806},
+  {1048,388,1688,806},
+@@ -2102,7 +2102,7 @@ XGI330_LVDSDataStruct  XGI_LVDS1280x768SData_1[]=
+  {1688,806,1688,806}
+ };
+ 
+-XGI330_LVDSDataStruct  XGI_LVDS1280x768SData_2[]=
++struct XGI330_LVDSDataStruct  XGI_LVDS1280x768SData_2[] =
+ {
+  {1688,806,1688,806},
+  {1688,806,1688,806},
+@@ -2115,7 +2115,7 @@ XGI330_LVDSDataStruct  XGI_LVDS1280x768SData_2[]=
+  {1688,806,1688,806}
+ };
+ */
+-XGI330_LVDSDataStruct  XGI_LVDS1400x1050Data_1[]=
++struct XGI330_LVDSDataStruct  XGI_LVDS1400x1050Data_1[] =
+ {
+  {928,416,1688,1066},
+  {928,366,1688,1066},
+@@ -2128,7 +2128,7 @@ XGI330_LVDSDataStruct  XGI_LVDS1400x1050Data_1[]=
+  {1688,1066,1688,1066}
+ };
+ 
+-XGI330_LVDSDataStruct  XGI_LVDS1400x1050Data_2[]=
++struct XGI330_LVDSDataStruct  XGI_LVDS1400x1050Data_2[] =
+ {
+  {1688,1066,1688,1066},
+  {1688,1066,1688,1066},
+@@ -2141,7 +2141,7 @@ XGI330_LVDSDataStruct  XGI_LVDS1400x1050Data_2[]=
+  {1688,1066,1688,1066}
+ };
+ 
+-XGI330_LVDSDataStruct XGI_LVDS1600x1200Data_1[]=
++struct XGI330_LVDSDataStruct XGI_LVDS1600x1200Data_1[] =
+ {      /* ;;[ycchen] 12/05/02 LCDHTxLCDVT=2048x1320 */
+         {        1088,520,2048,1320      },/* 00 (320x200,320x400,640x200,640x400) */
+         {        1088,470,2048,1320      },/* 01 (320x350,640x350) */
+@@ -2155,7 +2155,7 @@ XGI330_LVDSDataStruct XGI_LVDS1600x1200Data_1[]=
+         {        2048,1320,2048,1320     } /* 09 (1600x1200) */
+ };
+ 
+-XGI330_LVDSDataStruct XGI_LVDSNoScalingData[]=
++struct XGI330_LVDSDataStruct XGI_LVDSNoScalingData[] =
+ {
+         {        800,449,800,449             }, /* 00 (320x200,320x400,640x200,640x400) */
+         {        800,449,800,449             }, /* 01 (320x350,640x350) */
+@@ -2170,7 +2170,7 @@ XGI330_LVDSDataStruct XGI_LVDSNoScalingData[]=
+         {        1688,806,1688,806           }  /* 0A (1280x768x60Hz) */
+ };
+ 
+-XGI330_LVDSDataStruct XGI_LVDS1024x768Data_1x75[]=
++struct XGI330_LVDSDataStruct XGI_LVDS1024x768Data_1x75[] =
+ {
+ 	{960,438,1312,800  }, /* 00 (320x200,320x400,640x200,640x400) */
+         {960,388,1312,800  }, /* 01 (320x350,640x350) */
+@@ -2182,7 +2182,7 @@ XGI330_LVDSDataStruct XGI_LVDS1024x768Data_1x75[]=
+ };
+ 
+ 
+-XGI330_LVDSDataStruct XGI_LVDS1024x768Data_2x75[]=
++struct XGI330_LVDSDataStruct XGI_LVDS1024x768Data_2x75[] =
+ {
+         {1312,800,1312,800}, /* ; 00 (320x200,320x400,640x200,640x400) */
+         {1312,800,1312,800}, /* ; 01 (320x350,640x350) */
+@@ -2193,7 +2193,7 @@ XGI330_LVDSDataStruct XGI_LVDS1024x768Data_2x75[]=
+         {1312,800,1312,800}, /* ; 06 (512x384,1024x768) */
+ };
+ 
+-XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_1x75[]=
++struct XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_1x75[] =
+ {
+         {1048,442,1688,1066  }, /* ; 00 (320x200,320x400,640x200,640x400) */
+         {1048,392,1688,1066  }, /* ; 01 (320x350,640x350) */
+@@ -2205,7 +2205,7 @@ XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_1x75[]=
+         {1688,1066,1688,1066 }, /* ; 06; 07 (640x512,1280x1024) */
+ };
+ 
+-XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_2x75[]=
++struct XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_2x75[] =
+ {
+         {1688,1066,1688,1066 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+         {1688,1066,1688,1066 }, /* ; 01 (320x350,640x350) */
+@@ -2217,7 +2217,7 @@ XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_2x75[]=
+         {1688,1066,1688,1066 }, /* ; 06; 07 (640x512,1280x1024) */
+ };
+ 
+-XGI330_LVDSDataStruct XGI_LVDSNoScalingDatax75[]=
++struct XGI330_LVDSDataStruct XGI_LVDSNoScalingDatax75[] =
+ {
+         {800,449,800,449     }, /* ; 00 (320x200,320x400,640x200,640x400) */
+         {800,449,800,449     }, /* ; 01 (320x350,640x350) */
+@@ -2232,7 +2232,7 @@ XGI330_LVDSDataStruct XGI_LVDSNoScalingDatax75[]=
+         {1688,806,1688,806   }, /* ; 0A (1280x768x75Hz) */
+ };
+ 
+-XGI330_LVDSDataStruct XGI_LVDS1024x768Des_1[]=
++struct XGI330_LVDSDataStruct XGI_LVDS1024x768Des_1[] =
+ {
+ 	{      0,1048,   0, 771     }, /* 00 (320x200,320x400,640x200,640x400) */
+         {      0,1048,   0, 771     }, /* 01 (320x350,640x350) */
+@@ -2243,7 +2243,7 @@ XGI330_LVDSDataStruct XGI_LVDS1024x768Des_1[]=
+         {      0,1048, 805, 770     }  /* 06 (1024x768x60Hz) */
+ } ;
+ 
+-XGI330_LVDSDataStruct XGI_LVDS1024x768Des_2[]=
++struct XGI330_LVDSDataStruct XGI_LVDS1024x768Des_2[] =
+ {
+     	{      1142, 856, 622, 587     }, /* 00 (320x200,320x400,640x200,640x400) */
+         {      1142, 856, 597, 562     }, /* 01 (320x350,640x350) */
+@@ -2254,7 +2254,7 @@ XGI330_LVDSDataStruct XGI_LVDS1024x768Des_2[]=
+         {         0,1048, 805, 771     }  /* 06 (1024x768x60Hz) */
+ };
+ 
+-XGI330_LVDSDataStruct XGI_LVDS1024x768Des_3[]=
++struct XGI330_LVDSDataStruct XGI_LVDS1024x768Des_3[] =
+ {
+     	{       320,  24, 622, 587     }, /* 00 (320x200,320x400,640x200,640x400) */
+         {       320,  24, 597, 562     }, /* 01 (320x350,640x350) */
+@@ -2263,7 +2263,7 @@ XGI330_LVDSDataStruct XGI_LVDS1024x768Des_3[]=
+         {       320,  24, 722, 687     }  /* 04 (640x480x60Hz) */
+ };
+ 
+-XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_1[]=
++struct XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_1[] =
+ {
+     	{      0,1328,    0, 1025     }, /* 00 (320x200,320x400,640x200,640x400) */
+         {      0,1328,    0, 1025     }, /* 01 (320x350,640x350) */
+@@ -2276,7 +2276,7 @@ XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_1[]=
+ };
+ 
+  /* The Display setting for DE Mode Panel */
+-XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_2[]=
++struct XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_2[] =
+ {
+     	{      1368,1008,752,711     }, /* 00 (320x200,320x400,640x200,640x400) */
+         {      1368,1008,729,688     }, /* 01 (320x350,640x350) */
+@@ -2288,7 +2288,7 @@ XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_2[]=
+         {      0000,1328,0,1025     }  /* 07 (1280x1024x60Hz) */
+ };
+ 
+-XGI330_LVDSDataStruct XGI_LVDS1400x1050Des_1[]=
++struct XGI330_LVDSDataStruct XGI_LVDS1400x1050Des_1[] =
+ {
+     	{      0,1448,0,1051     }, /* 00 (320x200,320x400,640x200,640x400) */
+         {      0,1448,0,1051     }, /* 01 (320x350,640x350) */
+@@ -2301,7 +2301,7 @@ XGI330_LVDSDataStruct XGI_LVDS1400x1050Des_1[]=
+         {      0,1448,0,1051     }  /* 08 (1400x1050x60Hz) */
+ };
+ 
+-XGI330_LVDSDataStruct XGI_LVDS1400x1050Des_2[]=
++struct XGI330_LVDSDataStruct XGI_LVDS1400x1050Des_2[] =
+ {
+     	{      1308,1068, 781, 766     }, /* 00 (320x200,320x400,640x200,640x400) */
+         {      1308,1068, 781, 766     }, /* 01 (320x350,640x350) */
+@@ -2314,7 +2314,7 @@ XGI330_LVDSDataStruct XGI_LVDS1400x1050Des_2[]=
+         {      0,1448,0,1051     }  /* 08 (1400x1050x60Hz) */
+ };
+ 
+-XGI330_LVDSDataStruct XGI_LVDS1600x1200Des_1[]=
++struct XGI330_LVDSDataStruct XGI_LVDS1600x1200Des_1[] =
+ {
+     	{      0,1664,0,1201     }, /* 00 (320x200,320x400,640x200,640x400) */
+         {      0,1664,0,1201     }, /* 01 (320x350,640x350) */
+@@ -2330,7 +2330,7 @@ XGI330_LVDSDataStruct XGI_LVDS1600x1200Des_1[]=
+ 
+ 
+ 
+-XGI330_LCDDataDesStruct2  XGI_LVDSNoScalingDesData[]=
++struct XGI330_LCDDataDesStruct2  XGI_LVDSNoScalingDesData[] =
+ {
+     	{     0, 648, 448, 405,  96,   2   }, /* 00 (320x200,320x400,640x200,640x400) */
+         {     0, 648, 448, 355,  96,   2   }, /* 01 (320x350,640x350) */
+@@ -2345,7 +2345,7 @@ XGI330_LCDDataDesStruct2  XGI_LVDSNoScalingDesData[]=
+         {     0,1328,0,0771, 112,   6   }  /* 0A (1280x768x60Hz) */
+ };
+ 
+-XGI330_LVDSDataStruct XGI_LVDS1024x768Des_1x75[]=			/* ; 1024x768 Full-screen */
++struct XGI330_LVDSDataStruct XGI_LVDS1024x768Des_1x75[] =			/* ; 1024x768 Full-screen */
+ {
+         {0,1040,0,769}, /* ; 00 (320x200,320x400,640x200,640x400) */
+         {0,1040,0,769}, /* ; 01 (320x350,640x350) */
+@@ -2356,7 +2356,7 @@ XGI330_LVDSDataStruct XGI_LVDS1024x768Des_1x75[]=			/* ; 1024x768 Full-screen */
+         {0,1040,0,769} /* ; 06 (1024x768x75Hz) */
+ };
+ 
+-XGI330_LVDSDataStruct XGI_LVDS1024x768Des_2x75[]= /* ; 1024x768 center-screen (Enh. Mode) */
++struct XGI330_LVDSDataStruct XGI_LVDS1024x768Des_2x75[] = /* ; 1024x768 center-screen (Enh. Mode) */
+ {
+         {1142, 856,622,587 }, /* 00 (320x200,320x400,640x200,640x400) */
+         {1142, 856,597,562 }, /* 01 (320x350,640x350) */
+@@ -2367,7 +2367,7 @@ XGI330_LVDSDataStruct XGI_LVDS1024x768Des_2x75[]= /* ; 1024x768 center-screen (E
+         {   0,1048,805,771 }  /* 06 (1024x768x60Hz) */
+ };
+ 
+-XGI330_LVDSDataStruct XGI_LVDS1024x768Des_3x75[]= /* ; 1024x768 center-screen (St.Mode) */
++struct XGI330_LVDSDataStruct XGI_LVDS1024x768Des_3x75[] = /* ; 1024x768 center-screen (St.Mode) */
+ {
+         {320,24,622,587  }, /* ; 00 (320x200,320x400,640x200,640x400) */
+         {320,24,597,562  }, /* ; 01 (320x350,640x350) */
+@@ -2376,7 +2376,7 @@ XGI330_LVDSDataStruct XGI_LVDS1024x768Des_3x75[]= /* ; 1024x768 center-screen (S
+         {320,24,722,687  } /* ; 04 (640x480x60Hz) */
+ };
+ 
+-XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_1x75[]=
++struct XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_1x75[] =
+ {
+         {0,1296,0,1025}, /* ; 00 (320x200,320x400,640x200,640x400) */
+         {0,1296,0,1025}, /* ; 01 (320x350,640x350) */
+@@ -2389,7 +2389,7 @@ XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_1x75[]=
+ };
+ 
+ /* The Display setting for DE Mode Panel */
+-XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_2x75[]=   /* [ycchen] 02/18/03 Set DE as default */
++struct XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_2x75[] =   /* [ycchen] 02/18/03 Set DE as default */
+ {
+         {1368,976,752,711 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+         {1368,976,729,688 }, /* ; 01 (320x350,640x350) */
+@@ -2401,7 +2401,7 @@ XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_2x75[]=   /* [ycchen] 02/18/03 Set DE
+         {0,1296,0,1025    } /* ; 07 (1280x1024x75Hz) */
+ };
+ 
+-XGI330_LCDDataDesStruct2 XGI_LVDSNoScalingDesDatax75[]=  /* Scaling LCD 75Hz */
++struct XGI330_LCDDataDesStruct2 XGI_LVDSNoScalingDesDatax75[] =  /* Scaling LCD 75Hz */
+ {
+        { 0,648,448,405,96,2  }, /* ; 00 (320x200,320x400,640x200,640x400) */
+        { 0,648,448,355,96,2  }, /* ; 01 (320x350,640x350) */
+@@ -2416,7 +2416,7 @@ XGI330_LCDDataDesStruct2 XGI_LVDSNoScalingDesDatax75[]=  /* Scaling LCD 75Hz */
+        { 0,1328,0,771,112,6  }  /* ; 0A (1280x768x75Hz) */
+ };
+ 
+-XGI330_LVDSDataStruct  XGI330_LVDS640x480Data_1[]=
++struct XGI330_LVDSDataStruct  XGI330_LVDS640x480Data_1[] =
+ {
+  {800, 449, 800, 449},
+  {800, 449, 800, 449},
+@@ -2429,7 +2429,7 @@ XGI330_LVDSDataStruct  XGI330_LVDS640x480Data_1[]=
+  {1056, 628,1056, 628}
+ };
+ 
+-XGI330_CHTVDataStruct  XGI_CHTVUNTSCData[]=
++struct XGI330_CHTVDataStruct  XGI_CHTVUNTSCData[] =
+ {
+  {840, 600, 840, 600},
+  {840, 600, 840, 600},
+@@ -2439,7 +2439,7 @@ XGI330_CHTVDataStruct  XGI_CHTVUNTSCData[]=
+  {1064, 750,1064, 750}
+ };
+ 
+-XGI330_CHTVDataStruct  XGI_CHTVONTSCData[]=
++struct XGI330_CHTVDataStruct  XGI_CHTVONTSCData[] =
+ {
+  {840, 525, 840, 525},
+  {840, 525, 840, 525},
+@@ -2449,7 +2449,7 @@ XGI330_CHTVDataStruct  XGI_CHTVONTSCData[]=
+  {1040, 700,1040, 700}
+ };
+ 
+-XGI330_CHTVDataStruct  XGI_CHTVUPALData[]=
++struct XGI330_CHTVDataStruct  XGI_CHTVUPALData[] =
+ {
+  {1008, 625,1008, 625},
+  {1008, 625,1008, 625},
+@@ -2459,7 +2459,7 @@ XGI330_CHTVDataStruct  XGI_CHTVUPALData[]=
+  {936, 836, 936, 836}
+ };
+ 
+-XGI330_CHTVDataStruct  XGI_CHTVOPALData[]=
++struct XGI330_CHTVDataStruct  XGI_CHTVOPALData[] =
+ {
+  {1008, 625,1008, 625},
+  {1008, 625,1008, 625},
+@@ -2469,7 +2469,7 @@ XGI330_CHTVDataStruct  XGI_CHTVOPALData[]=
+  {960, 750, 960, 750}
+ };
+ 
+-XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11024x768_1_H[]=
++struct XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11024x768_1_H[] =
+ {
+ 	        /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+                 {{      0x4B,0x27,0x8F,0x32,0x1B,0x00,0x45,0x00 }}, /* 00 (320x) */
+@@ -2482,7 +2482,7 @@ XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11024x768_1_H[]=
+                 {{      0xA3,0x7F,0x87,0x86,0x97,0x00,0x02,0x00 }} /* 07 (1024x) */
+ };
+ 
+-XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11280x1024_1_H[]=
++struct XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11280x1024_1_H[] =
+ {
+ 		/* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+                 {{      0x56,0x27,0x9A,0x30,0x1E,0x00,0x05,0x00 }}, /* 00 (320x) */
+@@ -2496,7 +2496,7 @@ XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11280x1024_1_H[]=
+                 {{      0xCE,0x9F,0x92,0xA8,0x16,0x00,0x07,0x00 }} /* 08 (1280x) */
+ };
+ 
+-XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11024x768_2_H[]=
++struct XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11024x768_2_H[] =
+ {
+ 		/* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+                 {{      0x63,0x27,0x87,0x3B,0x8C,0x00,0x01,0x00 }}, /* 00 (320x) */
+@@ -2509,7 +2509,7 @@ XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11024x768_2_H[]=
+                 {{      0xA3,0x7F,0x87,0x86,0x97,0x00,0x02,0x00 }} /* 07 (1024x) */
+ };
+ 
+-XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11280x1024_2_H[]=
++struct XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11280x1024_2_H[] =
+ {
+                 /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+                 {{      0x7E,0x3B,0x9A,0x44,0x12,0x00,0x01,0x00 }}, /* 00 (320x) */
+@@ -2523,7 +2523,7 @@ XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11280x1024_2_H[]=
+                 {{      0xCE,0x9F,0x92,0xA8,0x16,0x00,0x07,0x00 }} /* 08 (1280x) */
+ };
+ 
+-XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11400x1050_1_H[]=
++struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11400x1050_1_H[] =
+ {               /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+                 {{      0x47,0x27,0x8B,0x2C,0x1A,0x00,0x05,0x00 }}, /* 00 (320x) */
+                 {{      0x47,0x27,0x8B,0x30,0x1E,0x00,0x05,0x00 }}, /* 01 (360x) */
+@@ -2537,7 +2537,7 @@ XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11400x1050_1_H[]=
+                 {{      0xCE,0xAE,0x92,0xB3,0x01,0x00,0x03,0x00 }} /* 09 (1400x) */
+ };
+ 
+-XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11400x1050_2_H[]=
++struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11400x1050_2_H[] =
+ {               /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+                 {{      0x76,0x3F,0x83,0x45,0x8C,0x00,0x41,0x00 }}, /* 00 (320x) */
+                 {{      0x76,0x3F,0x83,0x45,0x8C,0x00,0x41,0x00 }}, /* 01 (360x) */
+@@ -2551,7 +2551,7 @@ XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11400x1050_2_H[]=
+                 {{      0xCE,0xAE,0x92,0xBC,0x0A,0x00,0x03,0x00 }} /* 09 (1400x) */
+ };
+ 
+-XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11600x1200_1_H[]=
++struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11600x1200_1_H[] =
+ /* ;302lv channelA [ycchen] 12/05/02 LCDHT=2048 */
+ {   /* ; CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+                 {{      0x5B,0x27,0x9F,0x32,0x0A,0x00,0x01,0x00 }},/* 00 (320x) */
+@@ -2567,7 +2567,7 @@ XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11600x1200_1_H[]=
+ 		{{      0xFB,0xC7,0x9F,0xC9,0x81,0x00,0x07,0x00 }} /* 0A (1600x) */
+ };
+ 
+-XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_1_V[]=
++struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_1_V[] =
+ {               /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A+CR09(5->7) */
+                 {{      0x97,0x1F,0x60,0x87,0x5D,0x83,0x10      }}, /* 00 (x350) */
+                 {{      0xB4,0x1F,0x92,0x89,0x8F,0xB5,0x30      }}, /* 01 (x400) */
+@@ -2576,7 +2576,7 @@ XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_1_V[]=
+                 {{      0x24,0xF5,0x02,0x88,0xFF,0x25,0x90      }} /* 04 (x768) */
+ };
+ 
+-XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_2_V[]=
++struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_2_V[] =
+ {               /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
+                 {{      0x24,0xBB,0x31,0x87,0x5D,0x25,0x30      }}, /* 00 (x350) */
+                 {{      0x24,0xBB,0x4A,0x80,0x8F,0x25,0x30      }}, /* 01 (x400) */
+@@ -2585,7 +2585,7 @@ XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_2_V[]=
+                 {{      0x24,0xF5,0x02,0x88,0xFF,0x25,0x90      }} /* 04 (x768) */
+ };
+ 
+-XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_1_V[]=
++struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_1_V[] =
+ {               /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
+                 {{       0x86,0x1F,0x5E,0x82,0x5D,0x87,0x00     }}, /* 00 (x350) */
+                 {{       0xB8,0x1F,0x90,0x84,0x8F,0xB9,0x30     }}, /* 01 (x400) */
+@@ -2595,7 +2595,7 @@ XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_1_V[]=
+                 {{       0x28,0x5A,0x13,0x87,0xFF,0x29,0xA9     }} /* 05 (x1024) */
+ };
+ 
+-XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_2_V[]=
++struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_2_V[] =
+ {               /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
+                 {{      0x28,0xD2,0xAF,0x83,0xAE,0xD8,0xA1      }}, /* 00 (x350) */
+                 {{      0x28,0xD2,0xC8,0x8C,0xC7,0xF2,0x81      }}, /* 01 (x400) */
+@@ -2605,7 +2605,7 @@ XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_2_V[]=
+                 {{      0x28,0x5A,0x13,0x87,0xFF,0x29,0xA9      }} /* 05 (x1024) */
+ };
+ 
+-XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11400x1050_1_V[]=
++struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11400x1050_1_V[] =
+ {               /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
+                 {{      0x6C,0x1F,0x60,0x84,0x5D,0x6D,0x10      }}, /* 00 (x350) */
+                 {{      0x9E,0x1F,0x93,0x86,0x8F,0x9F,0x30      }}, /* 01 (x400) */
+@@ -2616,7 +2616,7 @@ XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11400x1050_1_V[]=
+                 {{      0x28,0x10,0x1A,0x80,0x19,0x29,0x0F      }} /* 06 (x1050) */
+ };
+ 
+-XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11400x1050_2_V[]=
++struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11400x1050_2_V[] =
+ {              /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
+                 {{      0x28,0x92,0xB6,0x83,0xB5,0xCF,0x81      }}, /* 00 (x350) */
+                 {{      0x28,0x92,0xD5,0x82,0xD4,0xEE,0x81      }}, /* 01 (x400) */
+@@ -2627,7 +2627,7 @@ XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11400x1050_2_V[]=
+                 {{      0x28,0x10,0x1A,0x87,0x19,0x29,0x8F      }} /* 06 (x1050) */
+ };
+ 
+-XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11600x1200_1_V[]=
++struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11600x1200_1_V[] =
+ {
+                /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A+CR09(5->7) */
+                 {{      0xd4,0x1F,0x81,0x84,0x5D,0xd5,0x10      }}, /* 00 (x350) */
+@@ -2640,7 +2640,7 @@ XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11600x1200_1_V[]=
+                 {{      0x26,0x11,0xd3,0x86,0xaF,0x27,0x3f      }} /* 07 (x1200) */
+ };
+ 
+-XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_1_Hx75[]=
++struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_1_Hx75[] =
+ { 	/* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+     {{      0x4B,0x27,0x8F,0x32,0x1B,0x00,0x45,0x00 }},/* ; 00 (320x) */
+     {{      0x4B,0x27,0x8F,0x2B,0x03,0x00,0x44,0x00 }},/* ; 01 (360x) */
+@@ -2652,7 +2652,7 @@ XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_1_Hx75[]=
+     {{      0x9F,0x7F,0x83,0x85,0x91,0x00,0x02,0x00 }} /* ; 07 (1024x) */
+ };
+ 
+-XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_1_Vx75[]=
++struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_1_Vx75[] =
+ {	/* CR06,CR07,CR10,CR11,CR15,CR16,SR0A+CR09(5->7) */
+     {{      0x97,0x1F,0x60,0x87,0x5D,0x83,0x10      }},/* ; 00 (x350) */
+     {{      0xB4,0x1F,0x92,0x89,0x8F,0xB5,0x30      }},/* ; 01 (x400) */
+@@ -2661,7 +2661,7 @@ XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_1_Vx75[]=
+     {{      0x1E,0xF5,0x00,0x83,0xFF,0x1F,0x90      }} /* ; 04 (x768) */
+ };
+ 
+-XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_2_Hx75[]=
++struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_2_Hx75[] =
+ {       /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+     {{      0x63,0x27,0x87,0x3B,0x8C,0x00,0x01,0x00 }},/* ; 00 (320x) */
+     {{      0x63,0x27,0x87,0x3B,0x8C,0x00,0x01,0x00 }},/* ; 01 (360x) */
+@@ -2673,7 +2673,7 @@ XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_2_Hx75[]=
+     {{      0xA3,0x7F,0x87,0x86,0x97,0x00,0x02,0x00 }} /* ; 07 (1024x) */
+ };
+ 
+-XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_2_Vx75[]=
++struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_2_Vx75[] =
+ {       /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
+     {{      0x24,0xBB,0x31,0x87,0x5D,0x25,0x30      }},/* ; 00 (x350) */
+     {{      0x24,0xBB,0x4A,0x80,0x8F,0x25,0x30      }},/* ; 01 (x400) */
+@@ -2682,7 +2682,7 @@ XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_2_Vx75[]=
+     {{      0x24,0xF5,0x02,0x88,0xFF,0x25,0x90      }} /* ; 04 (x768) */
+ };
+ 
+-XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_1_Hx75[]=
++struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_1_Hx75[] =
+ {      /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+     {{      0x56,0x27,0x9A,0x30,0x1E,0x00,0x05,0x00 }},/* ; 00 (320x) */
+     {{      0x56,0x27,0x9A,0x30,0x1E,0x00,0x05,0x00 }},/* ; 01 (360x) */
+@@ -2695,7 +2695,7 @@ XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_1_Hx75[]=
+     {{      0xCE,0x9F,0x92,0xA5,0x17,0x00,0x07,0x00 }} /* ; 08 (1280x) */
+ };
+ 
+-XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_1_Vx75[]=
++struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_1_Vx75[] =
+ {	/* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
+     {{      0x86,0xD1,0xBC,0x80,0xBB,0xE5,0x00      }},/* ; 00 (x350) */
+     {{      0xB8,0x1F,0x90,0x84,0x8F,0xB9,0x30      }},/* ; 01 (x400) */
+@@ -2705,7 +2705,7 @@ XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_1_Vx75[]=
+     {{      0x28,0x5A,0x13,0x87,0xFF,0x29,0xA9      }} /* ; 05 (x1024) */
+ };
+ 
+-XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_2_Hx75[]=
++struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_2_Hx75[] =
+ {
+ 	/* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+     {{      0x7E,0x3B,0x9A,0x44,0x12,0x00,0x01,0x00 }},/* ; 00 (320x) */
+@@ -2719,7 +2719,7 @@ XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_2_Hx75[]=
+     {{      0xCE,0x9F,0x92,0xA8,0x16,0x00,0x07,0x00 }} /* ; 08 (1280x) */
+ };
+ 
+-XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_2_Vx75[]=
++struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_2_Vx75[] =
+ {
+         /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
+      {{     0x28,0xD2,0xAF,0x83,0xAE,0xD8,0xA1     }},/* ; 00 (x350) */
+@@ -2730,7 +2730,7 @@ XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_2_Vx75[]=
+      {{     0x28,0x5A,0x13,0x87,0xFF,0x29,0xA9     }} /* ; 05 (x1024) */
+ };
+ 
+-XGI_LVDSCRT1DataStruct  XGI_CHTVCRT1UNTSC[]=
++struct XGI_LVDSCRT1DataStruct  XGI_CHTVCRT1UNTSC[] =
+ {
+  {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
+     0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,0x00 }},
+@@ -2746,7 +2746,7 @@ XGI_LVDSCRT1DataStruct  XGI_CHTVCRT1UNTSC[]=
+    0x90,0x8c,0x57,0xed,0x20,0x00,0x06,0x01 }}
+ };
+ 
+-XGI_LVDSCRT1DataStruct  XGI_CHTVCRT1ONTSC[]=
++struct XGI_LVDSCRT1DataStruct  XGI_CHTVCRT1ONTSC[] =
+ {
+  {{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
+     0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,0x00 }},
+@@ -2762,7 +2762,7 @@ XGI_LVDSCRT1DataStruct  XGI_CHTVCRT1ONTSC[]=
+    0x7f,0x86,0x57,0xbb,0x00,0x00,0x06,0x01 }}
+ };
+ 
+-XGI_LVDSCRT1DataStruct  XGI_CHTVCRT1UPAL[]=
++struct XGI_LVDSCRT1DataStruct  XGI_CHTVCRT1UPAL[] =
+ {
+  {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+     0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,0x00 }},
+@@ -2778,7 +2778,7 @@ XGI_LVDSCRT1DataStruct  XGI_CHTVCRT1UPAL[]=
+    0xc8,0x8c,0x57,0xe9,0x20,0x00,0x05,0x01 }}
+ };
+ 
+-XGI_LVDSCRT1DataStruct  XGI_CHTVCRT1OPAL[]=
++struct XGI_LVDSCRT1DataStruct  XGI_CHTVCRT1OPAL[] =
+ {
+  {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+     0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,0x00 }},
+@@ -2795,7 +2795,7 @@ XGI_LVDSCRT1DataStruct  XGI_CHTVCRT1OPAL[]=
+ };
+ 
+ /*add for new UNIVGABIOS*/
+-XGI330_LCDDataTablStruct XGI_LCDDataTable[]=
++struct XGI330_LCDDataTablStruct XGI_LCDDataTable[] =
+ {
+   {Panel1024x768,0x0019,0x0001,0},  /* XGI_ExtLCD1024x768Data */
+   {Panel1024x768,0x0019,0x0000,1},  /* XGI_StLCD1024x768Data */
+@@ -2819,7 +2819,7 @@ XGI330_LCDDataTablStruct XGI_LCDDataTable[]=
+   {0xFF,0x0000,0x0000,0}   		/* End of table */
+ };
+ 
+-XGI330_LCDDataTablStruct XGI_LCDDesDataTable[]=
++struct XGI330_LCDDataTablStruct XGI_LCDDesDataTable[] =
+ {
+   {Panel1024x768,0x0019,0x0001,0}, /* XGI_ExtLCDDes1024x768Data */
+   {Panel1024x768,0x0019,0x0000,1}, /* XGI_StLCDDes1024x768Data */
+@@ -2844,7 +2844,7 @@ XGI330_LCDDataTablStruct XGI_LCDDesDataTable[]=
+   {0xFF,0x0000,0x0000,0}
+ };
+ 
+-XGI330_LCDDataTablStruct XGI_EPLLCDCRT1Ptr_H[]=
++struct XGI330_LCDDataTablStruct XGI_EPLLCDCRT1Ptr_H[] =
+ {
+   {Panel1024x768,0x0018,0x0000,0}, /* XGI_LVDSCRT11024x768_1_H */
+   {Panel1024x768,0x0018,0x0010,1}, /* XGI_LVDSCRT11024x768_2_H */
+@@ -2860,7 +2860,7 @@ XGI330_LCDDataTablStruct XGI_EPLLCDCRT1Ptr_H[]=
+   {0xFF,0x0000,0x0000,0}
+ };
+ 
+-XGI330_LCDDataTablStruct XGI_EPLLCDCRT1Ptr_V[]=
++struct XGI330_LCDDataTablStruct XGI_EPLLCDCRT1Ptr_V[] =
+ {
+   {Panel1024x768,0x0018,0x0000,0}, /* XGI_LVDSCRT11024x768_1_V */
+   {Panel1024x768,0x0018,0x0010,1}, /* XGI_LVDSCRT11024x768_2_V */
+@@ -2876,7 +2876,7 @@ XGI330_LCDDataTablStruct XGI_EPLLCDCRT1Ptr_V[]=
+   {0xFF,0x0000,0x0000,0}
+ };
+ 
+-XGI330_LCDDataTablStruct XGI_EPLLCDDataPtr[]=
++struct XGI330_LCDDataTablStruct XGI_EPLLCDDataPtr[] =
+ {
+   {Panel1024x768,0x0018,0x0000,0}, /* XGI_LVDS1024x768Data_1 */
+   {Panel1024x768,0x0018,0x0010,1}, /* XGI_LVDS1024x768Data_2 */
+@@ -2894,7 +2894,7 @@ XGI330_LCDDataTablStruct XGI_EPLLCDDataPtr[]=
+   {0xFF,0x0000,0x0000,0}
+ };
+ 
+-XGI330_LCDDataTablStruct XGI_EPLLCDDesDataPtr[]=
++struct XGI330_LCDDataTablStruct XGI_EPLLCDDesDataPtr[] =
+ {
+   {Panel1024x768,0x0018,0x0000,0}, /* XGI_LVDS1024x768Des_1 */
+   {Panel1024x768,0x0618,0x0410,1}, /* XGI_LVDS1024x768Des_3 */
+@@ -2914,14 +2914,14 @@ XGI330_LCDDataTablStruct XGI_EPLLCDDesDataPtr[]=
+   {0xFF,0x0000,0x0000,0}
+ };
+ 
+-XGI330_LCDDataTablStruct XGI_EPLCHLCDRegPtr[]=
++struct XGI330_LCDDataTablStruct XGI_EPLCHLCDRegPtr[] =
+ {
+   {Panel1024x768,0x0000,0x0000,0}, /* XGI_CH7017LV1024x768 */
+   {Panel1400x1050,0x0000,0x0000,1}, /* XGI_CH7017LV1400x1050 */
+   {0xFF,0x0000,0x0000,0}
+ };
+ 
+-XGI330_TVDataTablStruct XGI_TVDataTable[]=
++struct XGI330_TVDataTablStruct XGI_TVDataTable[] =
+ {
+  {0x09E1,0x0001,0},	/* XGI_ExtPALData */
+  {0x09E1,0x0000,1},	/* XGI_ExtNTSCData */
+@@ -2952,7 +2952,7 @@ unsigned short TVLenList[] =
+ } ;
+ 
+ /* Chrontel 7017 TV CRT1 Timing List */
+-XGI330_TVDataTablStruct XGI_EPLCHTVCRT1Ptr[]=
++struct XGI330_TVDataTablStruct XGI_EPLCHTVCRT1Ptr[] =
+ {
+   {0x0011,0x0000,0}, /* XGI_CHTVCRT1UNTSC */
+   {0x0011,0x0010,1}, /* XGI_CHTVCRT1ONTSC */
+@@ -2962,7 +2962,7 @@ XGI330_TVDataTablStruct XGI_EPLCHTVCRT1Ptr[]=
+ };
+ 
+ /* ;;Chrontel 7017 TV Timing List */
+-XGI330_TVDataTablStruct XGI_EPLCHTVDataPtr[]=
++struct XGI330_TVDataTablStruct XGI_EPLCHTVDataPtr[] =
+ {
+   {0x0011,0x0000,0}, /* XGI_CHTVUNTSCData */
+   {0x0011,0x0010,1}, /* XGI_CHTVONTSCData */
+@@ -2972,7 +2972,7 @@ XGI330_TVDataTablStruct XGI_EPLCHTVDataPtr[]=
+ };
+ 
+ /* ;;Chrontel 7017 TV Reg. List */
+-XGI330_TVDataTablStruct XGI_EPLCHTVRegPtr[]=
++struct XGI330_TVDataTablStruct XGI_EPLCHTVRegPtr[] =
+ {
+   {0x0011,0x0000,0}, /* XGI_CHTVRegUNTSC */
+   {0x0011,0x0010,1}, /* XGI_CHTVRegONTSC */
+@@ -2995,7 +2995,7 @@ unsigned short LCDLenList[] =
+    0
+ } ;
+ 
+-XGI330_LCDCapStruct  XGI660_LCDDLCapList[]=  /* 660, Dual link */
++struct XGI330_LCDCapStruct  XGI660_LCDDLCapList[] =  /* 660, Dual link */
+ {
+ /* LCDCap1024x768 */
+ 		{Panel1024x768, DefaultLCDCap, 0, 0x014, 0x88, 0x06, VCLK65,
+@@ -3027,7 +3027,7 @@ XGI330_LCDCapStruct  XGI660_LCDDLCapList[]=  /* 660, Dual link */
+ 		0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}
+ };
+ 
+-XGI330_LCDCapStruct  XGI_LCDDLCapList[]=  /* Dual link only */
++struct XGI330_LCDCapStruct  XGI_LCDDLCapList[] =  /* Dual link only */
+ {
+ /* LCDCap1024x768 */
+ 		{Panel1024x768, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65,
+@@ -3059,7 +3059,7 @@ XGI330_LCDCapStruct  XGI_LCDDLCapList[]=  /* Dual link only */
+ 		0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}
+ };
+ 
+-XGI330_LCDCapStruct  XGI660_LCDCapList[]=
++struct XGI330_LCDCapStruct  XGI660_LCDCapList[] =
+ {
+ /* LCDCap1024x768 */
+                 {Panel1024x768, DefaultLCDCap, 0, 0x014, 0x88, 0x06, VCLK65,
+@@ -3091,7 +3091,7 @@ XGI330_LCDCapStruct  XGI660_LCDCapList[]=
+ 		0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}
+ };
+ 
+-XGI330_LCDCapStruct  XGI_LCDCapList[]=
++struct XGI330_LCDCapStruct  XGI_LCDCapList[] =
+ {
+ /* LCDCap1024x768 */
+ 		{Panel1024x768, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65,
+@@ -3123,7 +3123,7 @@ XGI330_LCDCapStruct  XGI_LCDCapList[]=
+ 		0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}
+ };
+ 
+-XGI21_LVDSCapStruct XGI21_LCDCapList[]=
++struct XGI21_LVDSCapStruct XGI21_LCDCapList[] =
+ {
+     {DisableLCD24bpp + LCDPolarity,
+      2160,1250,1600,1200,  64,  1,  192,   3,
+@@ -3152,7 +3152,7 @@ XGI21_LVDSCapStruct XGI21_LCDCapList[]=
+ 
+ };
+ 
+-XGI_Ext2Struct XGI330_RefIndex[]=
++struct XGI_Ext2Struct XGI330_RefIndex[] =
+ {
+ {Support32Bpp + SupportAllCRT2 + SyncPN,			RES320x200,	 VCLK25_175, 0x00,0x10,0x59, 320, 200},/* 00 */
+ {Support32Bpp + SupportAllCRT2 + SyncPN,			RES320x200,	 VCLK25_175, 0x00,0x10,0x00, 320, 400},/* 01 */
+@@ -3231,7 +3231,7 @@ XGI_Ext2Struct XGI330_RefIndex[]=
+ 
+ 
+ 
+-XGI330_VCLKDataStruct XGI330_VCLKData[]=
++struct XGI330_VCLKDataStruct XGI330_VCLKData[] =
+ {
+  { 0x1b,0xe1, 25}, /* 0x0 */
+  { 0x4e,0xe4, 28}, /* 0x1 */
+@@ -3315,7 +3315,7 @@ XGI330_VCLKDataStruct XGI330_VCLKData[]=
+  { 0x3b,0x61,108}  /* 0x4f */
+ };
+ 
+-XGI_VBVCLKDataStruct XGI330_VBVCLKData[]=
++struct XGI_VBVCLKDataStruct XGI330_VBVCLKData[] =
+ {
+  { 0x1b,0xe1, 25}, /* 0x0 */
+  { 0x4e,0xe4, 28}, /* 0x1 */
+@@ -3397,7 +3397,7 @@ unsigned char XGI330_ScreenOffset[] = { 0x14, 0x19, 0x20, 0x28, 0x32, 0x40,
+ 					0x50, 0x64, 0x78, 0x80, 0x2d, 0x35,
+ 					0x57, 0x48};
+ 
+-XGI_StResInfoStruct XGI330_StResInfo[]=
++struct XGI_StResInfoStruct XGI330_StResInfo[] =
+ {
+  { 640,400},
+  { 640,350},
+@@ -3406,7 +3406,7 @@ XGI_StResInfoStruct XGI330_StResInfo[]=
+  { 640,480}
+ };
+ 
+-XGI_ModeResInfoStruct XGI330_ModeResInfo[]=
++struct XGI_ModeResInfoStruct XGI330_ModeResInfo[] =
+ {
+  {  320, 200, 8, 8},
+  {  320, 240, 8, 8},
+@@ -3543,7 +3543,7 @@ unsigned char XGI7007_CHTVVCLKOPAL[] = {CH7007TVVCLK31_5,
+                               CH7007TVVCLK36
+                              };
+ 
+-XGI330_VCLKDataStruct XGI_CH7007VCLKData[]=
++struct XGI330_VCLKDataStruct XGI_CH7007VCLKData[] =
+ {
+  { 0x60,0x36,30},  /* 0 30.2 MHZ */
+  { 0x40,0x4A,28},  /* 1 28.19 MHZ */
+@@ -3558,7 +3558,7 @@ XGI330_VCLKDataStruct XGI_CH7007VCLKData[]=
+  { 0xFF,0x00,0 }   /* End mark      */
+ };
+ 
+-XGI330_VCLKDataStruct XGI_VCLKData[]=
++struct XGI330_VCLKDataStruct XGI_VCLKData[] =
+ {
+                	/* SR2B,SR2C,SR2D */
+  		{      0x1B,0xE1,25               },/* 00 (25.175MHz) */
+@@ -3759,7 +3759,7 @@ XGI330_VCLKDataStruct XGI_VCLKData[]=
+                 {      0xFF,0x00,0                }/* End mark */
+  }  ;
+ 
+-XGI330_VCLKDataStruct XGI_VBVCLKData[]=
++struct XGI330_VCLKDataStruct XGI_VBVCLKData[] =
+ {
+                 {      0x1B,0xE1,25               },/* 00 (25.175MHz) */
+ 
+@@ -4048,7 +4048,7 @@ unsigned char TVEdgeList[] =
+       0x00             /* ; 1 HiTV */
+ };
+ 
+-unsigned long TVPhaseList[]=
++unsigned long TVPhaseList[] =
+ {      0x08BAED21, /* ; 0 NTSC phase */
+        0x00E3052A, /* ; 1 PAL phase */
+        0x9B2EE421, /* ; 2 PAL-M phase */
+@@ -4166,7 +4166,7 @@ unsigned char XGI_NTSC1024AdjTime[] =
+       0x58,0xe4,0x73,0xd0,0x13
+ };
+ 
+-XGI301C_Tap4TimingStruct HiTVTap4Timing[]=
++struct XGI301C_Tap4TimingStruct HiTVTap4Timing[] =
+ {
+ 	{0,{
+ 	0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F, /* ; C0-C7 */
+@@ -4181,7 +4181,7 @@ XGI301C_Tap4TimingStruct HiTVTap4Timing[]=
+ 	}
+ };
+ 
+-XGI301C_Tap4TimingStruct EnlargeTap4Timing[]=
++struct XGI301C_Tap4TimingStruct EnlargeTap4Timing[] =
+ {
+ 	{0,{
+ 	0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F, /* ; C0-C7 */
+@@ -4196,7 +4196,7 @@ XGI301C_Tap4TimingStruct EnlargeTap4Timing[]=
+ 	}
+ };
+ 
+-XGI301C_Tap4TimingStruct NoScaleTap4Timing[]=
++struct XGI301C_Tap4TimingStruct NoScaleTap4Timing[] =
+ {
+ 	{0,{
+ 	0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F, /* ; C0-C7 */
+@@ -4211,7 +4211,7 @@ XGI301C_Tap4TimingStruct NoScaleTap4Timing[]=
+ 	}
+ };
+ 
+-XGI301C_Tap4TimingStruct PALTap4Timing[]=
++struct XGI301C_Tap4TimingStruct PALTap4Timing[] =
+ {
+ 	{600,  {
+                 0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E, /* ; C0-C7 */
+@@ -4249,7 +4249,7 @@ XGI301C_Tap4TimingStruct PALTap4Timing[]=
+         }
+ };
+ 
+-XGI301C_Tap4TimingStruct NTSCTap4Timing[]=
++struct XGI301C_Tap4TimingStruct NTSCTap4Timing[] =
+ {
+ 	{480,	{
+               	0x04,0x1A,0x04,0x7E,0x03,0x1A,0x06,0x7D, /* ; C0-C7 */
+@@ -4287,7 +4287,7 @@ XGI301C_Tap4TimingStruct NTSCTap4Timing[]=
+         }
+ };
+ 
+-XGI301C_Tap4TimingStruct YPbPr525pTap4Timing[]=
++struct XGI301C_Tap4TimingStruct YPbPr525pTap4Timing[] =
+ {
+ 	{480,	{
+               	0x04,0x1A,0x04,0x7E,0x03,0x1A,0x06,0x7D, /* ; C0-C7 */
+@@ -4325,7 +4325,7 @@ XGI301C_Tap4TimingStruct YPbPr525pTap4Timing[]=
+         }
+ };
+ 
+-XGI301C_Tap4TimingStruct YPbPr525iTap4Timing[]=
++struct XGI301C_Tap4TimingStruct YPbPr525iTap4Timing[] =
+ {
+ 	{480,	{
+               	0x04,0x1A,0x04,0x7E,0x03,0x1A,0x06,0x7D, /* ; C0-C7 */
+@@ -4363,7 +4363,7 @@ XGI301C_Tap4TimingStruct YPbPr525iTap4Timing[]=
+         }
+ };
+ 
+-XGI301C_Tap4TimingStruct YPbPr750pTap4Timing[]=
++struct XGI301C_Tap4TimingStruct YPbPr750pTap4Timing[] =
+ {        {0xFFFF,
+                {
+                0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E, /* ; C0-C7 */

commit e4147abe8b4bcc46811fc9d01ba79e850decb998
+Author: Bill Pemberton 
+Date:   Thu Jun 17 13:10:50 2010 -0400
+
+    Staging: xgifb: Remove XGI_HW_DEVICE_INFO and PXGI_HW_DEVICE_INFO typedefs
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Arnaud Patard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/XGI_main.h b/drivers/staging/xgifb/XGI_main.h
+index 472d124be346..b628582fd0cc 100644
+--- a/drivers/staging/xgifb/XGI_main.h
++++ b/drivers/staging/xgifb/XGI_main.h
+@@ -248,9 +248,6 @@ MODULE_DEVICE_TABLE(pci, xgifb_pci_table);
+ #define BRI_DRAM_SIZE_32MB        0x04
+ #define BRI_DRAM_SIZE_64MB        0x05
+ 
+-#define HW_DEVICE_EXTENSION	  XGI_HW_DEVICE_INFO
+-#define PHW_DEVICE_EXTENSION      PXGI_HW_DEVICE_INFO
+-
+ #define SR_BUFFER_SIZE            5
+ #define CR_BUFFER_SIZE            5
+ 
+@@ -376,7 +373,7 @@ unsigned char XGIfb_detectedlcda = 0xff;
+ /* XGIfb_info XGIfbinfo; */
+ 
+ /* TW: Hardware extension; contains data on hardware */
+-HW_DEVICE_EXTENSION XGIhw_ext;
++struct xgi_hw_device_info XGIhw_ext;
+ 
+ /* TW: XGI private structure */
+ VB_DEVICE_INFO  XGI_Pr;
+@@ -812,9 +809,9 @@ static int XGIfb_ioctl(struct fb_info *info, unsigned int cmd,
+ 
+ /*
+ extern int	XGIfb_mode_rate_to_dclock(VB_DEVICE_INFO *XGI_Pr,
+-			      PXGI_HW_DEVICE_INFO HwDeviceExtension,
++			      struct xgi_hw_device_info *HwDeviceExtension,
+ 			      unsigned char modeno, unsigned char rateindex);
+-extern int      XGIfb_mode_rate_to_ddata(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExtension,
++extern int      XGIfb_mode_rate_to_ddata(VB_DEVICE_INFO *XGI_Pr, struct xgi_hw_device_info *HwDeviceExtension,
+ 			 unsigned char modeno, unsigned char rateindex,
+ 			 unsigned int *left_margin, unsigned int *right_margin,
+ 			 unsigned int *upper_margin, unsigned int *lower_margin,
+@@ -881,20 +878,22 @@ static XGI_OH   *XGIfb_poh_free(unsigned long base);
+ static void     XGIfb_free_node(XGI_OH *poh);
+ 
+ /* Internal routines to access PCI configuration space */
+-unsigned char         XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
+-	          	unsigned long offset, unsigned long set, unsigned long *value);
++unsigned char XGIfb_query_VGA_config_space(struct xgi_hw_device_info *pXGIhw_ext,
++					   unsigned long offset,
++					   unsigned long set,
++					   unsigned long *value);
+ //BOOLEAN         XGIfb_query_north_bridge_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
+ //	         	unsigned long offset, unsigned long set, unsigned long *value);
+ 
+ 
+ /* Routines from init.c/init301.c */
+ extern void     InitTo330Pointer(unsigned char, PVB_DEVICE_INFO pVBInfo);
+-extern unsigned char  XGIInitNew(PXGI_HW_DEVICE_INFO HwDeviceExtension);
+-extern unsigned char XGISetModeNew(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+-			     unsigned short ModeNo);
++extern unsigned char  XGIInitNew(struct xgi_hw_device_info *HwDeviceExtension);
++extern unsigned char XGISetModeNew(struct xgi_hw_device_info *HwDeviceExtension,
++				   unsigned short ModeNo);
+ //extern void     XGI_SetEnableDstn(VB_DEVICE_INFO *XGI_Pr);
+ extern void     XGI_LongWait(VB_DEVICE_INFO *XGI_Pr);
+-extern unsigned short XGI_GetRatePtrCRT2(PXGI_HW_DEVICE_INFO pXGIHWDE,
++extern unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
+ 					 unsigned short ModeNo,
+ 					 unsigned short ModeIdIndex,
+ 					 PVB_DEVICE_INFO pVBInfo);
+diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
+index 51392040ec72..b3454a9e992b 100644
+--- a/drivers/staging/xgifb/XGI_main_26.c
++++ b/drivers/staging/xgifb/XGI_main_26.c
+@@ -162,7 +162,7 @@ struct video_info  xgi_video_info;
+ /* --------------- Hardware Access Routines -------------------------- */
+ 
+ int
+-XGIfb_mode_rate_to_dclock(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExtension,
++XGIfb_mode_rate_to_dclock(VB_DEVICE_INFO *XGI_Pr, struct xgi_hw_device_info *HwDeviceExtension,
+ 			  unsigned char modeno, unsigned char rateindex)
+ {
+     unsigned short ModeNo = modeno;
+@@ -197,7 +197,7 @@ XGIfb_mode_rate_to_dclock(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceEx
+ }
+ 
+ int
+-XGIfb_mode_rate_to_ddata(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExtension,
++XGIfb_mode_rate_to_ddata(VB_DEVICE_INFO *XGI_Pr, struct xgi_hw_device_info *HwDeviceExtension,
+ 			 unsigned char modeno, unsigned char rateindex,
+ 			 u32 *left_margin, u32 *right_margin,
+ 			 u32 *upper_margin, u32 *lower_margin,
+@@ -416,7 +416,7 @@ u32 XGIfb_get_reg3(u16 port)
+ /* ------------ Interface for init & mode switching code ------------- */
+ 
+ unsigned char
+-XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
++XGIfb_query_VGA_config_space(struct xgi_hw_device_info *pXGIhw_ext,
+ 	unsigned long offset, unsigned long set, unsigned long *value)
+ {
+ 	static struct pci_dev *pdev = NULL;
+@@ -450,7 +450,7 @@ XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
+ 	return 1;
+ }
+ 
+-/*unsigned char XGIfb_query_north_bridge_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
++/*unsigned char XGIfb_query_north_bridge_space(struct xgi_hw_device_info *pXGIhw_ext,
+ 	unsigned long offset, unsigned long set, unsigned long *value)
+ {
+ 	static struct pci_dev *pdev = NULL;
+@@ -2881,7 +2881,7 @@ int __devinit xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 
+ 	XGIfb_registered = 0;
+ 
+-	memset(&XGIhw_ext, 0, sizeof(HW_DEVICE_EXTENSION));
++	memset(&XGIhw_ext, 0, sizeof(struct xgi_hw_device_info));
+ 	  fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);
+ 	  if(!fb_info) return -ENOMEM;
+ 
+diff --git a/drivers/staging/xgifb/vb_ext.c b/drivers/staging/xgifb/vb_ext.c
+index f1566380e149..712af839e825 100644
+--- a/drivers/staging/xgifb/vb_ext.c
++++ b/drivers/staging/xgifb/vb_ext.c
+@@ -14,18 +14,18 @@ extern   unsigned char XGI330_OutputSelect;
+ extern   unsigned short XGI330_RGBSenseData2;
+ extern   unsigned short XGI330_YCSenseData2;
+ extern   unsigned short XGI330_VideoSenseData2;
+-void     XGI_GetSenseStatus( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo );
++void     XGI_GetSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+ unsigned char  XGINew_GetPanelID(PVB_DEVICE_INFO pVBInfo);
+-unsigned short XGINew_SenseLCD(PXGI_HW_DEVICE_INFO,
++unsigned short XGINew_SenseLCD(struct xgi_hw_device_info *,
+ 			       PVB_DEVICE_INFO pVBInfo);
+-unsigned char XGINew_GetLCDDDCInfo(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++unsigned char XGINew_GetLCDDDCInfo(struct xgi_hw_device_info *HwDeviceExtension,
+ 			     PVB_DEVICE_INFO pVBInfo);
+-void XGISetDPMS(PXGI_HW_DEVICE_INFO pXGIHWDE,
++void XGISetDPMS(struct xgi_hw_device_info *pXGIHWDE,
+ 		unsigned long VESA_POWER_STATE);
+-unsigned char XGINew_BridgeIsEnable(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
++unsigned char XGINew_BridgeIsEnable(struct xgi_hw_device_info *, PVB_DEVICE_INFO pVBInfo);
+ unsigned char XGINew_Sense(unsigned short tempbx, unsigned short tempcx,
+ 		     PVB_DEVICE_INFO pVBInfo);
+-unsigned char XGINew_SenseHiTV(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++unsigned char XGINew_SenseHiTV(struct xgi_hw_device_info *HwDeviceExtension,
+ 			       PVB_DEVICE_INFO pVBInfo);
+ 
+ /**************************************************************
+@@ -135,7 +135,7 @@ unsigned char XGINew_Sense(unsigned short tempbx,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGISetDPMS(PXGI_HW_DEVICE_INFO pXGIHWDE,
++void XGISetDPMS(struct xgi_hw_device_info *pXGIHWDE,
+ 		unsigned long VESA_POWER_STATE)
+ {
+     unsigned short ModeNo, ModeIdIndex;
+@@ -359,7 +359,7 @@ void XGISetDPMS(PXGI_HW_DEVICE_INFO pXGIHWDE,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_GetSenseStatus( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
++void XGI_GetSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short tempax = 0 , tempbx , tempcx , temp ,
+            P2reg0 = 0 , SenseModeNo = 0 , OutputSelect = *pVBInfo->pOutputSelect ,
+@@ -558,7 +558,7 @@ void XGI_GetSenseStatus( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned short XGINew_SenseLCD(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++unsigned short XGINew_SenseLCD(struct xgi_hw_device_info *HwDeviceExtension,
+ 			       PVB_DEVICE_INFO pVBInfo)
+ {
+     /* unsigned short SoftSetting ; */
+@@ -582,7 +582,7 @@ unsigned short XGINew_SenseLCD(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGINew_GetLCDDDCInfo( PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo)
++unsigned char XGINew_GetLCDDDCInfo(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short temp ;
+ 
+@@ -708,7 +708,7 @@ unsigned char XGINew_GetPanelID(PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGINew_BridgeIsEnable( PXGI_HW_DEVICE_INFO HwDeviceExtension ,PVB_DEVICE_INFO pVBInfo)
++unsigned char XGINew_BridgeIsEnable(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short flag ;
+ 
+@@ -735,7 +735,7 @@ unsigned char XGINew_BridgeIsEnable( PXGI_HW_DEVICE_INFO HwDeviceExtension ,PVB_
+ /* Output : */
+ /* Description : */
+ /* ------------------------------------------------------ */
+-unsigned char XGINew_SenseHiTV( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo )
++unsigned char XGINew_SenseHiTV(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short tempbx , tempcx , temp , i , tempch;
+ 
+@@ -998,7 +998,7 @@ void XGI_XG21Fun14Sub73( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
+ }
+ 
+ 
+-void XGI_XG21Fun14( PXGI_HW_DEVICE_INFO pXGIHWDE, PX86_REGS pBiosArguments)
++void XGI_XG21Fun14(struct xgi_hw_device_info *pXGIHWDE, PX86_REGS pBiosArguments)
+ {
+     VB_DEVICE_INFO VBINF;
+     PVB_DEVICE_INFO pVBInfo = &VBINF;
+diff --git a/drivers/staging/xgifb/vb_ext.h b/drivers/staging/xgifb/vb_ext.h
+index 768aebefc415..2933b16887ad 100644
+--- a/drivers/staging/xgifb/vb_ext.h
++++ b/drivers/staging/xgifb/vb_ext.h
+@@ -21,14 +21,14 @@ typedef union   _X86_REGS    {
+     struct  BYTEREGS h;
+ } X86_REGS, *PX86_REGS;
+ 
+-extern   void     XGI_XG21Fun14( PXGI_HW_DEVICE_INFO pXGIHWDE, PX86_REGS pBiosArguments);
+-extern void XGISetDPMS(PXGI_HW_DEVICE_INFO pXGIHWDE,
++extern   void     XGI_XG21Fun14(struct xgi_hw_device_info *pXGIHWDE, PX86_REGS pBiosArguments);
++extern void XGISetDPMS(struct xgi_hw_device_info *pXGIHWDE,
+ 		       unsigned long VESA_POWER_STATE);
+-extern   void     XGI_GetSenseStatus( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo );
+-extern   void     XGINew_SetModeScratch ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) ;
++extern   void     XGI_GetSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
++extern   void     XGINew_SetModeScratch(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) ;
+ extern void ReadVBIOSTablData(unsigned char ChipType,
+ 			      PVB_DEVICE_INFO pVBInfo);
+-extern unsigned short XGINew_SenseLCD(PXGI_HW_DEVICE_INFO,
++extern unsigned short XGINew_SenseLCD(struct xgi_hw_device_info *,
+ 				      PVB_DEVICE_INFO pVBInfo);
+ 
+ #endif
+diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
+index 06e229c70bcd..254c368c8cfe 100644
+--- a/drivers/staging/xgifb/vb_init.c
++++ b/drivers/staging/xgifb/vb_init.c
+@@ -72,38 +72,38 @@ unsigned short XGINew_DDRDRAM_TYPE20[12][5] = {
+ 	{ 2, 12,  9,  8, 0x35},
+ 	{ 2, 12,  8,  4, 0x31} };
+ 
+-void     XGINew_SetDRAMSize_340(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO);
+-void     XGINew_SetDRAMSize_310(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO);
+-void     XGINew_SetMemoryClock(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
++void     XGINew_SetDRAMSize_340(struct xgi_hw_device_info *, PVB_DEVICE_INFO);
++void     XGINew_SetDRAMSize_310(struct xgi_hw_device_info *, PVB_DEVICE_INFO);
++void     XGINew_SetMemoryClock(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO);
+ void     XGINew_SetDRAMModeRegister(PVB_DEVICE_INFO );
+-void     XGINew_SetDRAMModeRegister340( PXGI_HW_DEVICE_INFO HwDeviceExtension );
+-void XGINew_SetDRAMDefaultRegister340(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++void     XGINew_SetDRAMModeRegister340(struct xgi_hw_device_info *HwDeviceExtension);
++void XGINew_SetDRAMDefaultRegister340(struct xgi_hw_device_info *HwDeviceExtension,
+ 				      unsigned long, PVB_DEVICE_INFO);
+-unsigned char XGINew_GetXG20DRAMType(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++unsigned char XGINew_GetXG20DRAMType(struct xgi_hw_device_info *HwDeviceExtension,
+ 				     PVB_DEVICE_INFO pVBInfo);
+-unsigned char XGIInitNew(PXGI_HW_DEVICE_INFO HwDeviceExtension);
++unsigned char XGIInitNew(struct xgi_hw_device_info *HwDeviceExtension);
+ 
+-int      XGINew_DDRSizing340( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO );
+-void     XGINew_DisableRefresh( PXGI_HW_DEVICE_INFO ,PVB_DEVICE_INFO) ;
++int      XGINew_DDRSizing340(struct xgi_hw_device_info *, PVB_DEVICE_INFO);
++void     XGINew_DisableRefresh(struct xgi_hw_device_info *, PVB_DEVICE_INFO) ;
+ void     XGINew_CheckBusWidth_310( PVB_DEVICE_INFO) ;
+ int      XGINew_SDRSizing(PVB_DEVICE_INFO);
+ int      XGINew_DDRSizing( PVB_DEVICE_INFO );
+-void     XGINew_EnableRefresh( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO);
++void     XGINew_EnableRefresh(struct xgi_hw_device_info *, PVB_DEVICE_INFO);
+ int      XGINew_RAMType;                  /*int      ModeIDOffset,StandTable,CRT1Table,ScreenOffset,REFIndex;*/
+ unsigned long	 UNIROM;			  /* UNIROM */
+ unsigned char  ChkLFB(PVB_DEVICE_INFO);
+ void     XGINew_Delay15us(unsigned long);
+-void     SetPowerConsume(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++void     SetPowerConsume(struct xgi_hw_device_info *HwDeviceExtension,
+ 			 unsigned long XGI_P3d4Port);
+ void     ReadVBIOSTablData(unsigned char ChipType, PVB_DEVICE_INFO pVBInfo);
+ void     XGINew_DDR1x_MRS_XG20(unsigned long P3c4, PVB_DEVICE_INFO pVBInfo);
+-void     XGINew_SetDRAMModeRegister_XG20( PXGI_HW_DEVICE_INFO HwDeviceExtension );
+-void     XGINew_SetDRAMModeRegister_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension );
+-void 	 XGINew_ChkSenseStatus ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) ;
+-void     XGINew_SetModeScratch ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) ;
+-void     XGINew_GetXG21Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) ;
++void     XGINew_SetDRAMModeRegister_XG20(struct xgi_hw_device_info *HwDeviceExtension);
++void     XGINew_SetDRAMModeRegister_XG27(struct xgi_hw_device_info *HwDeviceExtension);
++void     XGINew_ChkSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) ;
++void     XGINew_SetModeScratch(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) ;
++void     XGINew_GetXG21Sense(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) ;
+ unsigned char    GetXG21FPBits(PVB_DEVICE_INFO pVBInfo);
+-void     XGINew_GetXG27Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) ;
++void     XGINew_GetXG27Sense(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) ;
+ unsigned char    GetXG27FPBits(PVB_DEVICE_INFO pVBInfo);
+ 
+ void DelayUS(unsigned long MicroSeconds)
+@@ -118,7 +118,7 @@ void DelayUS(unsigned long MicroSeconds)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGIInitNew(PXGI_HW_DEVICE_INFO HwDeviceExtension)
++unsigned char XGIInitNew(struct xgi_hw_device_info *HwDeviceExtension)
+ {
+ 
+     VB_DEVICE_INFO VBINF;
+@@ -546,7 +546,7 @@ return 1;
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGINew_GetXG20DRAMType(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++unsigned char XGINew_GetXG20DRAMType(struct xgi_hw_device_info *HwDeviceExtension,
+ 				     PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned char data, temp;
+@@ -740,7 +740,7 @@ void XGINew_DDR2x_MRS_340(unsigned long P3c4 , PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_DDRII_Bootup_XG27(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++void XGINew_DDRII_Bootup_XG27(struct xgi_hw_device_info *HwDeviceExtension,
+ 			      unsigned long P3c4, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned long P3d4 = P3c4 + 0x10 ;
+@@ -819,7 +819,7 @@ void XGINew_DDRII_Bootup_XG27(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_DDR2_MRS_XG20(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++void XGINew_DDR2_MRS_XG20(struct xgi_hw_device_info *HwDeviceExtension,
+ 			  unsigned long P3c4, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned long P3d4 = P3c4 + 0x10 ;
+@@ -872,7 +872,7 @@ void XGINew_DDR2_MRS_XG20(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_DDR2_MRS_XG27(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++void XGINew_DDR2_MRS_XG27(struct xgi_hw_device_info *HwDeviceExtension,
+ 			  unsigned long P3c4, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned long P3d4 = P3c4 + 0x10 ;
+@@ -951,7 +951,7 @@ void XGINew_DDR2_MRS_XG27(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_DDR1x_DefaultRegister(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++void XGINew_DDR1x_DefaultRegister(struct xgi_hw_device_info *HwDeviceExtension,
+ 				  unsigned long Port, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned long P3d4 = Port ,
+@@ -1012,7 +1012,7 @@ void XGINew_DDR1x_DefaultRegister(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_DDR2x_DefaultRegister(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++void XGINew_DDR2x_DefaultRegister(struct xgi_hw_device_info *HwDeviceExtension,
+ 				  unsigned long Port, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned long P3d4 = Port ,
+@@ -1064,7 +1064,7 @@ void XGINew_DDR2x_DefaultRegister(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_DDR2_DefaultRegister(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++void XGINew_DDR2_DefaultRegister(struct xgi_hw_device_info *HwDeviceExtension,
+ 				 unsigned long Port, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned long P3d4 = Port ,
+@@ -1103,7 +1103,7 @@ void XGINew_DDR2_DefaultRegister(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_SetDRAMDefaultRegister340(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++void XGINew_SetDRAMDefaultRegister340(struct xgi_hw_device_info *HwDeviceExtension,
+ 				      unsigned long Port, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned char temp, temp1, temp2, temp3 ,
+@@ -1315,7 +1315,7 @@ void XGINew_DDR_MRS(PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_VerifyMclk( PXGI_HW_DEVICE_INFO  HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
++void XGINew_VerifyMclk(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned char *pVideoMemory = pVBInfo->FBAddr ;
+     unsigned char i, j ;
+@@ -1361,7 +1361,7 @@ void XGINew_VerifyMclk( PXGI_HW_DEVICE_INFO  HwDeviceExtension , PVB_DEVICE_INFO
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_SetDRAMSize_340( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
++void XGINew_SetDRAMSize_340(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short  data ;
+ 
+@@ -1390,7 +1390,7 @@ void XGINew_SetDRAMSize_340( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_SetDRAMSize_310( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
++void XGINew_SetDRAMSize_310(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short data ;
+     pVBInfo->ROMAddr  = HwDeviceExtension->pjVirtualRomBase ,
+@@ -1454,7 +1454,7 @@ void XGINew_SetDRAMSize_310( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ 
+-void XGINew_SetDRAMModeRegister340( PXGI_HW_DEVICE_INFO HwDeviceExtension )
++void XGINew_SetDRAMModeRegister340(struct xgi_hw_device_info *HwDeviceExtension)
+ {
+     unsigned char data ;
+     VB_DEVICE_INFO VBINF;
+@@ -1528,7 +1528,7 @@ void XGINew_SetDRAMModeRegister( PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_DisableRefresh( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
++void XGINew_DisableRefresh(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short  data ;
+ 
+@@ -1546,7 +1546,7 @@ void XGINew_DisableRefresh( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_I
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_EnableRefresh( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
++void XGINew_EnableRefresh(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+ 
+     XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , pVBInfo->SR15[ 3 ][ XGINew_RAMType ] ) ;	/* SR1B */
+@@ -2228,7 +2228,7 @@ unsigned char XGINew_CheckFrequence(PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_CheckChannel( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned char data;
+ 
+@@ -2509,7 +2509,7 @@ void XGINew_CheckChannel( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-int XGINew_DDRSizing340( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++int XGINew_DDRSizing340(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+     int i ;
+     unsigned short memsize , addr ;
+@@ -2595,7 +2595,7 @@ int XGINew_DDRSizing(PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_SetMemoryClock( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGINew_SetMemoryClock(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+ 
+ 
+@@ -2644,7 +2644,7 @@ unsigned char ChkLFB(PVB_DEVICE_INFO pVBInfo)
+ /* in second chip, assume CR A1 D[6]="1" in this case */
+ /* output : none */
+ /* --------------------------------------------------------------------- */
+-void SetPowerConsume(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++void SetPowerConsume(struct xgi_hw_device_info *HwDeviceExtension,
+ 		     unsigned long XGI_P3d4Port)
+ {
+     unsigned long   lTemp ;
+@@ -2673,7 +2673,7 @@ void SetPowerConsume(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ }
+ 
+ 
+-void XGINew_InitVBIOSData(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGINew_InitVBIOSData(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+ 
+ 	/* unsigned long ROMAddr = (unsigned long)HwDeviceExtension->pjVirtualRomBase; */
+@@ -2828,7 +2828,7 @@ void XGINew_DDR1x_MRS_XG20(unsigned long P3c4, PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_SetDRAMModeRegister_XG20( PXGI_HW_DEVICE_INFO HwDeviceExtension )
++void XGINew_SetDRAMModeRegister_XG20(struct xgi_hw_device_info *HwDeviceExtension)
+ {
+     VB_DEVICE_INFO VBINF;
+     PVB_DEVICE_INFO pVBInfo = &VBINF;
+@@ -2867,7 +2867,7 @@ void XGINew_SetDRAMModeRegister_XG20( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+     XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , 0x03 ) ;
+ }
+ 
+-void XGINew_SetDRAMModeRegister_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension )
++void XGINew_SetDRAMModeRegister_XG27(struct xgi_hw_device_info *HwDeviceExtension)
+ {
+     VB_DEVICE_INFO VBINF;
+     PVB_DEVICE_INFO pVBInfo = &VBINF;
+@@ -2909,7 +2909,7 @@ void XGINew_SetDRAMModeRegister_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+ 
+ }
+ /*
+-void XGINew_SetDRAMModeRegister_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension )
++void XGINew_SetDRAMModeRegister_XG27(struct xgi_hw_device_info *HwDeviceExtension)
+ {
+ 
+     unsigned char data ;
+@@ -2956,7 +2956,7 @@ void XGINew_SetDRAMModeRegister_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+ /* Output : */
+ /* Description : */
+ /* -------------------------------------------------------- */
+-void XGINew_ChkSenseStatus ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
++void XGINew_ChkSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short tempbx = 0, temp, tempcx, CR3CData;
+ 
+@@ -3017,7 +3017,7 @@ void XGINew_ChkSenseStatus ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_
+ /* Output : */
+ /* Description : */
+ /* -------------------------------------------------------- */
+-void XGINew_SetModeScratch ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo )
++void XGINew_SetModeScratch(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short temp , tempcl = 0 , tempch = 0 , CR31Data , CR38Data;
+ 
+@@ -3114,7 +3114,7 @@ void XGINew_SetModeScratch ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_
+ /* Output : */
+ /* Description : */
+ /* -------------------------------------------------------- */
+-void XGINew_GetXG21Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGINew_GetXG21Sense(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned char Temp;
+     volatile unsigned char *pVideoMemory = (unsigned char *)pVBInfo->ROMAddr;
+@@ -3156,7 +3156,7 @@ void XGINew_GetXG21Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO
+ /* Output : */
+ /* Description : */
+ /* -------------------------------------------------------- */
+-void XGINew_GetXG27Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGINew_GetXG27Sense(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+ 	unsigned char Temp, bCR4A;
+ 
+diff --git a/drivers/staging/xgifb/vb_init.h b/drivers/staging/xgifb/vb_init.h
+index ab6939f58586..8803253fe0e4 100644
+--- a/drivers/staging/xgifb/vb_init.h
++++ b/drivers/staging/xgifb/vb_init.h
+@@ -1,6 +1,6 @@
+ #ifndef  _VBINIT_
+ #define  _VBINIT_
+-extern   unsigned char    XGIInitNew( PXGI_HW_DEVICE_INFO HwDeviceExtension ) ;
++extern   unsigned char    XGIInitNew(struct xgi_hw_device_info *HwDeviceExtension) ;
+ extern XGI21_LVDSCapStruct  XGI21_LCDCapList[13];
+ 
+ #endif
+diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c
+index 5a74c595d78a..158789cface5 100644
+--- a/drivers/staging/xgifb/vb_setmode.c
++++ b/drivers/staging/xgifb/vb_setmode.c
+@@ -22,7 +22,7 @@
+ 
+ unsigned char  XGI_IsLCDDualLink(PVB_DEVICE_INFO pVBInfo);
+ unsigned char  XGI_SetCRT2Group301(unsigned short ModeNo,
+-			     PXGI_HW_DEVICE_INFO HwDeviceExtension,
++			     struct xgi_hw_device_info *HwDeviceExtension,
+ 			     PVB_DEVICE_INFO pVBInfo);
+ unsigned char  XGI_BacklightByDrv(PVB_DEVICE_INFO pVBInfo);
+ 
+@@ -39,7 +39,7 @@ unsigned char  XGI_SearchModeID(unsigned short ModeNo,
+ unsigned char  XGI_GetLCDInfo(unsigned short ModeNo,
+ 			unsigned short ModeIdIndex,
+ 			PVB_DEVICE_INFO pVBInfo);
+-unsigned char  XGISetModeNew(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++unsigned char  XGISetModeNew(struct xgi_hw_device_info *HwDeviceExtension,
+ 		       unsigned short ModeNo);
+ unsigned char  XGI_BridgeIsOn(PVB_DEVICE_INFO pVBInfo);
+ unsigned char    XGI_GetModePtr(unsigned short ModeNo,
+@@ -48,9 +48,9 @@ unsigned char    XGI_GetModePtr(unsigned short ModeNo,
+ unsigned short XGI_GetOffset(unsigned short ModeNo,
+ 			     unsigned short ModeIdIndex,
+ 			     unsigned short RefreshRateTableIndex,
+-			     PXGI_HW_DEVICE_INFO HwDeviceExtension,
++			     struct xgi_hw_device_info *HwDeviceExtension,
+ 			     PVB_DEVICE_INFO pVBInfo);
+-unsigned short XGI_GetRatePtrCRT2(PXGI_HW_DEVICE_INFO pXGIHWDE,
++unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
+ 				  unsigned short ModeNo,
+ 				  unsigned short ModeIdIndex,
+ 				  PVB_DEVICE_INFO pVBInfo);
+@@ -64,25 +64,25 @@ unsigned short XGI_GetVGAHT2(PVB_DEVICE_INFO pVBInfo);
+ unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo,
+ 			       unsigned short ModeIdIndex,
+ 			       unsigned short RefreshRateTableIndex,
+-			       PXGI_HW_DEVICE_INFO HwDeviceExtension,
++			       struct xgi_hw_device_info *HwDeviceExtension,
+ 			       PVB_DEVICE_INFO pVBInfo);
+ void     XGI_VBLongWait(PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SaveCRT2Info(unsigned short ModeNo, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_GetCRT2ResInfo(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_PreSetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
++void     XGI_PreSetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SetGroup3(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SetGroup5(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+ void     *XGI_GetLcdPtr(unsigned short BX,  unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+ void     *XGI_GetTVPtr(unsigned short BX, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+ void 	 XGI_FirePWDEnable(PVB_DEVICE_INFO pVBInfo);
+-void 	 XGI_EnableGatingCRT(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+-void 	 XGI_DisableGatingCRT(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
++void     XGI_EnableGatingCRT(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
++void     XGI_DisableGatingCRT(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SetPanelDelay(unsigned short tempbl, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SetPanelPower(unsigned short tempah, unsigned short tempbl, PVB_DEVICE_INFO pVBInfo);
+ void 	 XGI_EnablePWD( PVB_DEVICE_INFO pVBInfo);
+@@ -90,9 +90,9 @@ void 	 XGI_DisablePWD( PVB_DEVICE_INFO pVBInfo);
+ void     XGI_AutoThreshold( PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SetTap4Regs( PVB_DEVICE_INFO pVBInfo);
+ 
+-void     XGI_DisplayOn(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_DisplayOff( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo );
+-void     XGI_SetCRT1Group(PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
++void     XGI_DisplayOn(struct xgi_hw_device_info *, PVB_DEVICE_INFO pVBInfo);
++void     XGI_DisplayOff(struct xgi_hw_device_info *, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetCRT1Group(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SetXG21CRTC(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SetXG21LCD(PVB_DEVICE_INFO pVBInfo, unsigned short RefreshRateTableIndex, unsigned short ModeNo);
+ void     XGI_SetXG27CRTC(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+@@ -102,39 +102,39 @@ void     XGI_WaitDisply(PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SenseCRT1(PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SetSeqRegs(unsigned short ModeNo, unsigned short StandTableIndex, unsigned short ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SetMiscRegs(unsigned short StandTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetCRTCRegs(PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short StandTableIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetCRTCRegs(struct xgi_hw_device_info *HwDeviceExtension, unsigned short StandTableIndex, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SetATTRegs(unsigned short ModeNo, unsigned short StandTableIndex, unsigned short ModeIdIndex,PVB_DEVICE_INFO pVBInfo );
+ void     XGI_SetGRCRegs(unsigned short StandTableIndex, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_ClearExt1Regs(PVB_DEVICE_INFO pVBInfo);
+ 
+ void     XGI_SetSync(unsigned short RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetCRT1CRTC(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo,PXGI_HW_DEVICE_INFO HwDeviceExtension);
+-void     XGI_SetCRT1Timing_H(PVB_DEVICE_INFO pVBInfo,PXGI_HW_DEVICE_INFO HwDeviceExtension);
++void     XGI_SetCRT1CRTC(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo, struct xgi_hw_device_info *HwDeviceExtension);
++void     XGI_SetCRT1Timing_H(PVB_DEVICE_INFO pVBInfo, struct xgi_hw_device_info *HwDeviceExtension);
+ void     XGI_SetCRT1Timing_V(unsigned short ModeIdIndex, unsigned short ModeNo,PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetCRT1DE(PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetCRT1VCLK(unsigned short ModeNo, unsigned short ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetCRT1FIFO(unsigned short ModeNo,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetCRT1ModeRegs(PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetVCLKState(PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short ModeNo, unsigned short RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetCRT1DE(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetCRT1VCLK(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetCRT1FIFO(unsigned short ModeNo, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetVCLKState(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+ 
+ void     XGI_LoadDAC(unsigned short ModeNo, unsigned short ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
+ void     XGI_WriteDAC(unsigned short dl, unsigned short ah, unsigned short al, unsigned short dh, PVB_DEVICE_INFO pVBInfo);
+-/*void     XGI_ClearBuffer(PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short ModeNo,PVB_DEVICE_INFO pVBInfo);*/
+-void     XGI_SetLCDAGroup(unsigned short ModeNo, unsigned short ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO  pVBInfo);
++/*void     XGI_ClearBuffer(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo, PVB_DEVICE_INFO pVBInfo);*/
++void     XGI_SetLCDAGroup(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO  pVBInfo);
+ void     XGI_GetLVDSResInfo(unsigned short ModeNo, unsigned short ModeIdIndex,PVB_DEVICE_INFO  pVBInfo);
+ void     XGI_GetLVDSData(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,PVB_DEVICE_INFO  pVBInfo);
+-void     XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO  pVBInfo);
++void     XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO  pVBInfo);
+ void     XGI_SetLVDSRegs(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,PVB_DEVICE_INFO  pVBInfo);
+-void     XGI_UpdateModeInfo(PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO  pVBInfo);
+-void     XGI_GetVGAType(PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO  pVBInfo);
++void     XGI_UpdateModeInfo(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO  pVBInfo);
++void     XGI_GetVGAType(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO  pVBInfo);
+ void     XGI_GetVBType(PVB_DEVICE_INFO  pVBInfo);
+-void     XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO  pVBInfo);
++void     XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO  pVBInfo);
+ void     XGI_GetTVInfo(unsigned short ModeNo, unsigned short ModeIdIndex,PVB_DEVICE_INFO  pVBInfo);
+ void     XGI_SetCRT2ECLK(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,PVB_DEVICE_INFO  pVBInfo);
+ void     InitTo330Pointer(unsigned char, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_GetLCDSync(unsigned short *HSyncWidth, unsigned short *VSyncWidth, PVB_DEVICE_INFO pVBInfo);
+-void 	 XGI_DisableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+-void  	 XGI_EnableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
++void     XGI_DisableBridge(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
++void     XGI_EnableBridge(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SetCRT2VCLK(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_OEM310Setting(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SetDelayComp(PVB_DEVICE_INFO pVBInfo);
+@@ -149,16 +149,16 @@ void     XGI_SetYFilter(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_D
+ void     XGI_GetTVPtrIndex2(unsigned short *tempbx, unsigned char* tempcl,
+ 			    unsigned char *tempch, PVB_DEVICE_INFO pVBInfo);
+ unsigned short   XGI_GetTVPtrIndex(PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetCRT2ModeRegs(unsigned short ModeNo,PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo );
+-void     XGI_CloseCRTC(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_OpenCRTC(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetCRT2ModeRegs(unsigned short ModeNo, struct xgi_hw_device_info *, PVB_DEVICE_INFO pVBInfo);
++void     XGI_CloseCRTC(struct xgi_hw_device_info *, PVB_DEVICE_INFO pVBInfo);
++void     XGI_OpenCRTC(struct xgi_hw_device_info *, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_GetRAMDAC2DATA(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_UnLockCRT2(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_LockCRT2(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
++void     XGI_UnLockCRT2(struct xgi_hw_device_info *, PVB_DEVICE_INFO pVBInfo);
++void     XGI_LockCRT2(struct xgi_hw_device_info *, PVB_DEVICE_INFO pVBInfo);
+ void     XGINew_EnableCRT2(PVB_DEVICE_INFO pVBInfo);
+ void     XGINew_LCD_Wait_Time(unsigned char DelayTime, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_LongWait(PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetCRT1Offset(unsigned short ModeNo , unsigned short ModeIdIndex , unsigned short RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo );
++void     XGI_SetCRT1Offset(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_GetLCDVCLKPtr(unsigned char *di_0, unsigned char *di_1,
+ 			   PVB_DEVICE_INFO pVBInfo);
+ unsigned char    XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex,
+@@ -391,7 +391,7 @@ void InitTo330Pointer(unsigned char ChipType, PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGISetModeNew(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++unsigned char XGISetModeNew(struct xgi_hw_device_info *HwDeviceExtension,
+ 			    unsigned short ModeNo)
+ {
+     unsigned short ModeIdIndex ;
+@@ -615,7 +615,7 @@ unsigned char XGISetModeNew(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetCRT1Group(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++void XGI_SetCRT1Group(struct xgi_hw_device_info *HwDeviceExtension,
+ 		      unsigned short ModeNo,
+ 		      unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+ {
+@@ -858,7 +858,7 @@ void XGI_SetMiscRegs(unsigned short StandTableIndex, PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetCRTCRegs(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++void XGI_SetCRTCRegs(struct xgi_hw_device_info *HwDeviceExtension,
+ 		     unsigned short StandTableIndex, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned char CRTCdata ;
+@@ -1007,7 +1007,7 @@ unsigned char XGI_SetDefaultVCLK(PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned short XGI_GetRatePtrCRT2(PXGI_HW_DEVICE_INFO pXGIHWDE,
++unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
+ 				  unsigned short ModeNo,
+ 				  unsigned short ModeIdIndex,
+ 				  PVB_DEVICE_INFO pVBInfo)
+@@ -1342,7 +1342,7 @@ void XGI_SetSync(unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+ void XGI_SetCRT1CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
+ 		     unsigned short RefreshRateTableIndex,
+ 		     PVB_DEVICE_INFO pVBInfo,
+-		     PXGI_HW_DEVICE_INFO HwDeviceExtension)
++		     struct xgi_hw_device_info *HwDeviceExtension)
+ {
+     unsigned char index, data;
+     unsigned short i;
+@@ -1378,7 +1378,7 @@ void XGI_SetCRT1CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetCRT1Timing_H( PVB_DEVICE_INFO pVBInfo, PXGI_HW_DEVICE_INFO HwDeviceExtension )
++void XGI_SetCRT1Timing_H(PVB_DEVICE_INFO pVBInfo, struct xgi_hw_device_info *HwDeviceExtension)
+ {
+     unsigned char data, data1, pushax;
+     unsigned short i, j;
+@@ -1935,7 +1935,7 @@ void XGI_UpdateXG21CRTC(unsigned short ModeNo,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetCRT1DE(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++void XGI_SetCRT1DE(struct xgi_hw_device_info *HwDeviceExtension,
+ 		   unsigned short ModeNo,
+ 		   unsigned short ModeIdIndex,
+ 		   unsigned short RefreshRateTableIndex,
+@@ -2048,7 +2048,7 @@ unsigned short XGI_GetResInfo(unsigned short ModeNo,
+ void XGI_SetCRT1Offset(unsigned short ModeNo,
+ 		       unsigned short ModeIdIndex,
+ 		       unsigned short RefreshRateTableIndex,
+-		       PXGI_HW_DEVICE_INFO HwDeviceExtension,
++		       struct xgi_hw_device_info *HwDeviceExtension,
+ 		       PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short temp ,
+@@ -2143,7 +2143,7 @@ void XGI_SetCRT1Offset(unsigned short ModeNo,
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ void XGI_SetCRT1VCLK(unsigned short ModeNo, unsigned short ModeIdIndex,
+-		     PXGI_HW_DEVICE_INFO HwDeviceExtension,
++		     struct xgi_hw_device_info *HwDeviceExtension,
+ 		     unsigned short RefreshRateTableIndex,
+ 		     PVB_DEVICE_INFO pVBInfo)
+ {
+@@ -2206,7 +2206,7 @@ void XGI_SetCRT1VCLK(unsigned short ModeNo, unsigned short ModeIdIndex,
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ void XGI_SetCRT1FIFO(unsigned short ModeNo,
+-		     PXGI_HW_DEVICE_INFO HwDeviceExtension,
++		     struct xgi_hw_device_info *HwDeviceExtension,
+ 		     PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short data ;
+@@ -2256,7 +2256,7 @@ void XGI_SetCRT1FIFO(unsigned short ModeNo,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetCRT1ModeRegs(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++void XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension,
+ 			 unsigned short ModeNo, unsigned short ModeIdIndex,
+ 			 unsigned short RefreshRateTableIndex,
+ 			 PVB_DEVICE_INFO pVBInfo)
+@@ -2396,7 +2396,7 @@ void XGI_SetCRT1ModeRegs(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetVCLKState(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++void XGI_SetVCLKState(struct xgi_hw_device_info *HwDeviceExtension,
+ 		      unsigned short ModeNo,
+ 		      unsigned short RefreshRateTableIndex,
+ 		      PVB_DEVICE_INFO pVBInfo)
+@@ -2657,7 +2657,7 @@ void XGI_WriteDAC(unsigned short dl, unsigned short ah,
+ /* --------------------------------------------------------------------- */
+ void XGI_SetLCDAGroup(unsigned short ModeNo,
+ 		      unsigned short ModeIdIndex,
+-		      PXGI_HW_DEVICE_INFO HwDeviceExtension,
++		      struct xgi_hw_device_info *HwDeviceExtension,
+ 		      PVB_DEVICE_INFO  pVBInfo)
+ {
+     unsigned short RefreshRateTableIndex ;
+@@ -2819,7 +2819,7 @@ void XGI_GetLVDSData(unsigned short ModeNo,
+ /* --------------------------------------------------------------------- */
+ void XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex,
+ 		     unsigned short RefreshRateTableIndex,
+-		     PXGI_HW_DEVICE_INFO HwDeviceExtension,
++		     struct xgi_hw_device_info *HwDeviceExtension,
+ 		     PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned char index;
+@@ -3224,7 +3224,7 @@ void XGI_SetCRT2ECLK(unsigned short ModeNo , unsigned short ModeIdIndex , unsign
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_UpdateModeInfo( PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO  pVBInfo )
++void XGI_UpdateModeInfo(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO  pVBInfo)
+ {
+     unsigned short tempcl ,
+            tempch ,
+@@ -3332,7 +3332,7 @@ void XGI_UpdateModeInfo( PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_GetVGAType( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO  pVBInfo)
++void XGI_GetVGAType(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO  pVBInfo)
+ {
+     /*
+     if ( HwDeviceExtension->jChipType >= XG20 )
+@@ -3417,7 +3417,7 @@ void XGI_GetVBType(PVB_DEVICE_INFO  pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_GetVBInfo(unsigned short ModeNo , unsigned short ModeIdIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO  pVBInfo )
++void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO  pVBInfo)
+ {
+     unsigned short tempax ,
+            push ,
+@@ -4060,7 +4060,7 @@ unsigned char XGI_SearchModeID(unsigned short ModeNo,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGINew_CheckMemorySize(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++unsigned char XGINew_CheckMemorySize(struct xgi_hw_device_info *HwDeviceExtension,
+ 				     unsigned short ModeNo,
+ 				     unsigned short ModeIdIndex,
+ 				     PVB_DEVICE_INFO pVBInfo)
+@@ -4145,7 +4145,7 @@ unsigned char XGINew_CheckMemorySize(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-/*void XGINew_IsLowResolution(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned char XGINew_CheckMemorySize(PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex,PVB_DEVICE_INFO pVBInfo)
++/*void XGINew_IsLowResolution(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned char XGINew_CheckMemorySize(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short data ;
+     unsigned short ModeFlag ;
+@@ -4177,7 +4177,7 @@ unsigned char XGINew_CheckMemorySize(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_DisplayOn( PXGI_HW_DEVICE_INFO pXGIHWDE , PVB_DEVICE_INFO pVBInfo )
++void XGI_DisplayOn(struct xgi_hw_device_info *pXGIHWDE, PVB_DEVICE_INFO pVBInfo)
+ {
+ 
+     XGINew_SetRegANDOR(pVBInfo->P3c4,0x01,0xDF,0x00);
+@@ -4241,7 +4241,7 @@ void XGI_DisplayOn( PXGI_HW_DEVICE_INFO pXGIHWDE , PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_DisplayOff( PXGI_HW_DEVICE_INFO pXGIHWDE , PVB_DEVICE_INFO pVBInfo )
++void XGI_DisplayOff(struct xgi_hw_device_info *pXGIHWDE, PVB_DEVICE_INFO pVBInfo)
+ {
+ 
+     if ( pXGIHWDE->jChipType == XG21 )
+@@ -4442,7 +4442,7 @@ void XGI_WaitDisplay( PVB_DEVICE_INFO pVBInfo )
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ unsigned char XGI_SetCRT2Group301(unsigned short ModeNo,
+-				  PXGI_HW_DEVICE_INFO HwDeviceExtension,
++				  struct xgi_hw_device_info *HwDeviceExtension,
+ 				  PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short tempbx ,
+@@ -5138,7 +5138,7 @@ void XGI_GetVCLKLen(unsigned char tempal, unsigned char *di_0,
+ void XGI_SetCRT2Offset(unsigned short ModeNo,
+ 		       unsigned short ModeIdIndex,
+ 		       unsigned short RefreshRateTableIndex,
+-		       PXGI_HW_DEVICE_INFO HwDeviceExtension,
++		       struct xgi_hw_device_info *HwDeviceExtension,
+ 		       PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short offset ;
+@@ -5165,7 +5165,7 @@ void XGI_SetCRT2Offset(unsigned short ModeNo,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned short XGI_GetOffset(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo)
++unsigned short XGI_GetOffset(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short temp ,
+            colordepth ,
+@@ -5228,7 +5228,7 @@ void XGI_SetCRT2FIFO( PVB_DEVICE_INFO pVBInfo)
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ void XGI_PreSetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
+-		      PXGI_HW_DEVICE_INFO HwDeviceExtension,
++		      struct xgi_hw_device_info *HwDeviceExtension,
+ 		      unsigned short RefreshRateTableIndex,
+ 		      PVB_DEVICE_INFO pVBInfo)
+ {
+@@ -5264,7 +5264,7 @@ void XGI_PreSetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ void XGI_SetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
+-		   PXGI_HW_DEVICE_INFO HwDeviceExtension,
++		   struct xgi_hw_device_info *HwDeviceExtension,
+ 		   unsigned short RefreshRateTableIndex,
+ 		   PVB_DEVICE_INFO pVBInfo)
+ {
+@@ -5442,7 +5442,7 @@ void XGI_SetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ void  XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
+-		      PXGI_HW_DEVICE_INFO HwDeviceExtension,
++		      struct xgi_hw_device_info *HwDeviceExtension,
+ 		      unsigned short RefreshRateTableIndex,
+ 		      PVB_DEVICE_INFO pVBInfo)
+ {
+@@ -5891,7 +5891,7 @@ void  XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,
+-                    PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
++		   struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short i ,
+            j ,
+@@ -6409,7 +6409,7 @@ void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned s
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void  XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo)
++void  XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short push1 ,
+            push2 ,
+@@ -6849,7 +6849,7 @@ void XGI_SetGroup3(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short tempax ,
+            tempcx ,
+@@ -7842,7 +7842,7 @@ void XGI_FirePWDEnable(PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_EnableGatingCRT(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGI_EnableGatingCRT(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+     XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x63 , 0xBF , 0x40 ) ;
+ }
+@@ -7854,7 +7854,7 @@ void XGI_EnableGatingCRT(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_DisableGatingCRT(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGI_DisableGatingCRT(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+ 
+     XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x63 , 0xBF , 0x00 ) ;
+@@ -8749,7 +8749,7 @@ void XGI_GetLCDSync(unsigned short *HSyncWidth , unsigned short *VSyncWidth,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_EnableBridge( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
++void XGI_EnableBridge(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short tempbl ,
+            tempah ;
+@@ -8962,7 +8962,7 @@ void XGI_EnableBridge( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO p
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_DisableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGI_DisableBridge(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short tempax ,
+            tempbx ,
+@@ -9653,7 +9653,7 @@ void XGI_GetTVPtrIndex2(unsigned short *tempbx, unsigned char *tempcl,
+ /* Description : Origin code for crt2group */
+ /* --------------------------------------------------------------------- */
+ void XGI_SetCRT2ModeRegs(unsigned short ModeNo,
+-			 PXGI_HW_DEVICE_INFO HwDeviceExtension,
++			 struct xgi_hw_device_info *HwDeviceExtension,
+ 			 PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short tempbl ;
+@@ -9883,7 +9883,7 @@ void XGI_SetCRT2ModeRegs(unsigned short ModeNo,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_CloseCRTC( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
++void XGI_CloseCRTC(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short tempbx ;
+ 
+@@ -9902,7 +9902,7 @@ void XGI_CloseCRTC( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBIn
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_OpenCRTC( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
++void XGI_OpenCRTC(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short tempbx ;
+ 
+@@ -10014,7 +10014,7 @@ unsigned short XGI_GetColorDepth(unsigned short ModeNo , unsigned short ModeIdIn
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_UnLockCRT2( PXGI_HW_DEVICE_INFO HwDeviceExtension,  PVB_DEVICE_INFO pVBInfo )
++void XGI_UnLockCRT2(struct xgi_hw_device_info *HwDeviceExtension,  PVB_DEVICE_INFO pVBInfo)
+ {
+ 
+     XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2f , 0xFF , 0x01 ) ;
+@@ -10028,7 +10028,7 @@ void XGI_UnLockCRT2( PXGI_HW_DEVICE_INFO HwDeviceExtension,  PVB_DEVICE_INFO pVB
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_LockCRT2( PXGI_HW_DEVICE_INFO HwDeviceExtension,  PVB_DEVICE_INFO pVBInfo )
++void XGI_LockCRT2(struct xgi_hw_device_info *HwDeviceExtension,  PVB_DEVICE_INFO pVBInfo)
+ {
+ 
+     XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2F , 0xFE , 0x00 ) ;
+@@ -10226,7 +10226,11 @@ unsigned short XGI_GetVGAHT2( PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo , unsigned short ModeIdIndex , unsigned short RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension ,PVB_DEVICE_INFO pVBInfo)
++unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo,
++			       unsigned short ModeIdIndex,
++			       unsigned short RefreshRateTableIndex,
++			       struct xgi_hw_device_info *HwDeviceExtension,
++			       PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short tempbx ;
+ 
+diff --git a/drivers/staging/xgifb/vb_setmode.h b/drivers/staging/xgifb/vb_setmode.h
+index 1c37f809dadb..0d061d730072 100644
+--- a/drivers/staging/xgifb/vb_setmode.h
++++ b/drivers/staging/xgifb/vb_setmode.h
+@@ -2,31 +2,33 @@
+ #define  _VBSETMODE_
+ 
+ extern   void     InitTo330Pointer(unsigned char, PVB_DEVICE_INFO);
+-extern   void     XGI_UnLockCRT2(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+-extern   void     XGI_LockCRT2(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
++extern   void     XGI_UnLockCRT2(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO);
++extern   void     XGI_LockCRT2(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO);
+ extern   void     XGI_LongWait( PVB_DEVICE_INFO );
+-extern   void     XGI_SetCRT2ModeRegs(unsigned short ModeNo,PXGI_HW_DEVICE_INFO,  PVB_DEVICE_INFO  );
+-extern   void     XGI_DisableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+-extern   void  	  XGI_EnableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+-extern   void     XGI_DisplayOff( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO );
+-extern   void     XGI_DisplayOn( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO );
++extern   void     XGI_SetCRT2ModeRegs(unsigned short ModeNo,
++				      struct xgi_hw_device_info *,
++				      PVB_DEVICE_INFO);
++extern   void     XGI_DisableBridge(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO);
++extern   void     XGI_EnableBridge(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO);
++extern   void     XGI_DisplayOff(struct xgi_hw_device_info *, PVB_DEVICE_INFO);
++extern   void     XGI_DisplayOn(struct xgi_hw_device_info *, PVB_DEVICE_INFO);
+ extern   void     XGI_GetVBType(PVB_DEVICE_INFO);
+ extern   void     XGI_SenseCRT1(PVB_DEVICE_INFO );
+-extern   void     XGI_GetVGAType(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+-extern   void     XGI_GetVBInfo(unsigned short ModeNo,unsigned short ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
++extern   void     XGI_GetVGAType(struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO);
++extern   void     XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO);
+ extern   void     XGI_GetTVInfo(unsigned short ModeNo,unsigned short ModeIdIndex, PVB_DEVICE_INFO );
+-extern   void     XGI_SetCRT1Offset(unsigned short ModeNo,unsigned short ModeIdIndex,unsigned short RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+-extern   void     XGI_SetLCDAGroup(unsigned short ModeNo,unsigned short ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
++extern   void     XGI_SetCRT1Offset(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO);
++extern   void     XGI_SetLCDAGroup(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO);
+ extern   void     XGI_WaitDisply( PVB_DEVICE_INFO );
+ extern   unsigned short   XGI_GetResInfo(unsigned short ModeNo,unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+ 
+-extern   unsigned char  XGISetModeNew( PXGI_HW_DEVICE_INFO HwDeviceExtension , unsigned short ModeNo ) ;
++extern   unsigned char  XGISetModeNew(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo) ;
+ 
+ extern   unsigned char  XGI_SearchModeID( unsigned short ModeNo,unsigned short  *ModeIdIndex, PVB_DEVICE_INFO );
+ extern   unsigned char  XGI_GetLCDInfo(unsigned short ModeNo,unsigned short ModeIdIndex,PVB_DEVICE_INFO );
+ extern   unsigned char  XGI_BridgeIsOn( PVB_DEVICE_INFO );
+-extern   unsigned char  XGI_SetCRT2Group301(unsigned short ModeNo, PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO);
+-extern   unsigned short   XGI_GetRatePtrCRT2( PXGI_HW_DEVICE_INFO pXGIHWDE, unsigned short ModeNo,unsigned short ModeIdIndex, PVB_DEVICE_INFO );
++extern   unsigned char  XGI_SetCRT2Group301(unsigned short ModeNo, struct xgi_hw_device_info *HwDeviceExtension, PVB_DEVICE_INFO);
++extern   unsigned short   XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE, unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO);
+ 
+ extern   void     XGI_SetXG21FPBits(PVB_DEVICE_INFO pVBInfo);
+ extern   void     XGI_SetXG27FPBits(PVB_DEVICE_INFO pVBInfo);
+diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h
+index bf9058d89c37..8702a7a78996 100644
+--- a/drivers/staging/xgifb/vgatypes.h
++++ b/drivers/staging/xgifb/vgatypes.h
+@@ -58,14 +58,7 @@ struct XGI_DSReg
+   unsigned char  jVal;
+ };
+ 
+-
+-#ifndef XGI_HW_DEVICE_INFO
+-
+-typedef struct _XGI_HW_DEVICE_INFO  XGI_HW_DEVICE_INFO, *PXGI_HW_DEVICE_INFO;
+-
+-typedef unsigned char (*PXGI_QUERYSPACE)   (PXGI_HW_DEVICE_INFO, unsigned long, unsigned long, unsigned long *);
+-
+-struct _XGI_HW_DEVICE_INFO
++struct xgi_hw_device_info
+ {
+     unsigned long  ulExternalChip;       /* NO VB or other video bridge*/
+                                  /* if ujVBChipID = VB_CHIP_UNKNOWN, */
+@@ -124,18 +117,18 @@ struct _XGI_HW_DEVICE_INFO
+                                  /* end data :(idx, val) =  (FF, FF) */
+                                  /* Note : restore cR registers if  */
+                                  /* bSkipDramSizing = 1 */
+-/*
+-#endif
+-*/
+ 
+-    PXGI_QUERYSPACE  pQueryVGAConfigSpace;
++	unsigned char(*pQueryVGAConfigSpace)(struct xgi_hw_device_info *,
++					    unsigned long, unsigned long,
++					    unsigned long *);
+ 
+-    PXGI_QUERYSPACE  pQueryNorthBridgeSpace;
++	unsigned char(*pQueryNorthBridgeSpace)(struct xgi_hw_device_info *,
++					      unsigned long, unsigned long,
++					      unsigned long *);
+ 
+     unsigned char szVBIOSVer[VBIOS_VER_MAX_LENGTH];
+ 
+ };
+-#endif
+ 
+ /* Addtional IOCTL for communication xgifb <> X driver        */
+ /* If changing this, xgifb.h must also be changed (for xgifb) */

commit 1d9f9a9ba8a51fc6ac750aa33432a5a52eff039a
+Author: Bill Pemberton 
+Date:   Thu Jun 17 13:10:49 2010 -0400
+
+    Staging: xgifb: Remove XGI_DSReg and PXGI_DSReg typedefs
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Arnaud Patard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
+index faea2e740e4b..51392040ec72 100644
+--- a/drivers/staging/xgifb/XGI_main_26.c
++++ b/drivers/staging/xgifb/XGI_main_26.c
+@@ -2994,7 +2994,7 @@ int __devinit xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	  strcpy(XGIhw_ext.szVBIOSVer, "0.84");
+ 
+ 
+-    XGIhw_ext.pSR = vmalloc(sizeof(XGI_DSReg) * SR_BUFFER_SIZE);
++    XGIhw_ext.pSR = vmalloc(sizeof(struct XGI_DSReg) * SR_BUFFER_SIZE);
+ 	  if (XGIhw_ext.pSR == NULL)
+ 	  {
+ 		    printk(KERN_ERR "XGIfb: Fatal error: Allocating SRReg space failed.\n");
+@@ -3002,7 +3002,7 @@ int __devinit xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	  }
+ 	  XGIhw_ext.pSR[0].jIdx = XGIhw_ext.pSR[0].jVal = 0xFF;
+ 
+-	  XGIhw_ext.pCR = vmalloc(sizeof(XGI_DSReg) * CR_BUFFER_SIZE);
++	  XGIhw_ext.pCR = vmalloc(sizeof(struct XGI_DSReg) * CR_BUFFER_SIZE);
+ 	  if (XGIhw_ext.pCR == NULL)
+ 	  {
+ 	      vfree(XGIhw_ext.pSR);
+diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
+index 343be2527a0e..06e229c70bcd 100644
+--- a/drivers/staging/xgifb/vb_init.c
++++ b/drivers/staging/xgifb/vb_init.c
+@@ -129,7 +129,7 @@ unsigned char XGIInitNew(PXGI_HW_DEVICE_INFO HwDeviceExtension)
+ 
+     /* unsigned long j, k ; */
+ 
+-    PXGI_DSReg pSR ;
++    struct XGI_DSReg *pSR ;
+ 
+     unsigned long Temp ;
+ 
+diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h
+index c7d4eaf96e79..bf9058d89c37 100644
+--- a/drivers/staging/xgifb/vgatypes.h
++++ b/drivers/staging/xgifb/vgatypes.h
+@@ -52,13 +52,12 @@ enum XGI_LCD_TYPE {
+ };
+ #endif
+ 
+-#ifndef PXGI_DSReg
+-typedef struct _XGI_DSReg
++struct XGI_DSReg
+ {
+   unsigned char  jIdx;
+   unsigned char  jVal;
+-} XGI_DSReg, *PXGI_DSReg;
+-#endif
++};
++
+ 
+ #ifndef XGI_HW_DEVICE_INFO
+ 
+@@ -116,12 +115,12 @@ struct _XGI_HW_DEVICE_INFO
+     unsigned char bIsPowerSaving;     /* True: XGIInit() is invoked by power management,
+                                    otherwise by 2nd adapter's initialzation */
+ 
+-    PXGI_DSReg  pSR;             /* restore SR registers in initial function. */
++    struct XGI_DSReg  *pSR;             /* restore SR registers in initial function. */
+                                  /* end data :(idx, val) =  (FF, FF). */
+                                  /* Note : restore SR registers if  */
+                                  /* bSkipDramSizing = 1 */
+ 
+-    PXGI_DSReg  pCR;             /* restore CR registers in initial function. */
++    struct XGI_DSReg  *pCR;             /* restore CR registers in initial function. */
+                                  /* end data :(idx, val) =  (FF, FF) */
+                                  /* Note : restore cR registers if  */
+                                  /* bSkipDramSizing = 1 */

commit 621a683fe8003850cb9e9257f379b7c020157912
+Author: Bill Pemberton 
+Date:   Thu Jun 17 13:10:48 2010 -0400
+
+    Staging: xgifb: Remove XGI_LCD_TYPE and XGI_VB_CHIP_TYPE typedefs
+    
+    There is no need for these to be typedefs as a simple enum will do.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Arnaud Patard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h
+index a518d27c0d11..c7d4eaf96e79 100644
+--- a/drivers/staging/xgifb/vgatypes.h
++++ b/drivers/staging/xgifb/vgatypes.h
+@@ -9,7 +9,7 @@
+ #endif
+ 
+ #ifndef XGI_VB_CHIP_TYPE
+-typedef enum _XGI_VB_CHIP_TYPE {
++enum XGI_VB_CHIP_TYPE {
+     VB_CHIP_Legacy = 0,
+     VB_CHIP_301,
+     VB_CHIP_301B,
+@@ -21,11 +21,11 @@ typedef enum _XGI_VB_CHIP_TYPE {
+     VB_CHIP_302ELV,
+     VB_CHIP_UNKNOWN, /* other video bridge or no video bridge */
+     MAX_VB_CHIP
+-} XGI_VB_CHIP_TYPE;
++};
+ #endif
+ 
+ #ifndef XGI_LCD_TYPE
+-typedef enum _XGI_LCD_TYPE {
++enum XGI_LCD_TYPE {
+     LCD_INVALID = 0,
+     LCD_320x480,       /* FSTN, DSTN */
+     LCD_640x480,
+@@ -49,7 +49,7 @@ typedef enum _XGI_LCD_TYPE {
+     LCD_2048x1536,
+     LCD_CUSTOM,
+     LCD_UNKNOWN
+-} XGI_LCD_TYPE;
++};
+ #endif
+ 
+ #ifndef PXGI_DSReg

commit 108afbf8aef6520f2f34b3add94b059b60c44139
+Author: Bill Pemberton 
+Date:   Thu Jun 17 13:10:47 2010 -0400
+
+    Staging: xgifb: Remove SHORT, UCHAR, and LONG typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Arnaud Patard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/XGI_main.h b/drivers/staging/xgifb/XGI_main.h
+index fcb1816e387a..472d124be346 100644
+--- a/drivers/staging/xgifb/XGI_main.h
++++ b/drivers/staging/xgifb/XGI_main.h
+@@ -888,7 +888,7 @@ unsigned char         XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ex
+ 
+ 
+ /* Routines from init.c/init301.c */
+-extern void     InitTo330Pointer(UCHAR,PVB_DEVICE_INFO pVBInfo);
++extern void     InitTo330Pointer(unsigned char, PVB_DEVICE_INFO pVBInfo);
+ extern unsigned char  XGIInitNew(PXGI_HW_DEVICE_INFO HwDeviceExtension);
+ extern unsigned char XGISetModeNew(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ 			     unsigned short ModeNo);
+diff --git a/drivers/staging/xgifb/vb_ext.c b/drivers/staging/xgifb/vb_ext.c
+index aabab059e5c9..f1566380e149 100644
+--- a/drivers/staging/xgifb/vb_ext.c
++++ b/drivers/staging/xgifb/vb_ext.c
+@@ -9,8 +9,8 @@
+ #include "vb_util.h"
+ #include "vb_setmode.h"
+ #include "vb_ext.h"
+-extern   UCHAR XGI330_SoftSetting;
+-extern   UCHAR XGI330_OutputSelect;
++extern   unsigned char XGI330_SoftSetting;
++extern   unsigned char XGI330_OutputSelect;
+ extern   unsigned short XGI330_RGBSenseData2;
+ extern   unsigned short XGI330_YCSenseData2;
+ extern   unsigned short XGI330_VideoSenseData2;
+@@ -139,7 +139,7 @@ void XGISetDPMS(PXGI_HW_DEVICE_INFO pXGIHWDE,
+ 		unsigned long VESA_POWER_STATE)
+ {
+     unsigned short ModeNo, ModeIdIndex;
+-    UCHAR  temp ;
++    unsigned char temp;
+     VB_DEVICE_INFO VBINF;
+     PVB_DEVICE_INFO pVBInfo = &VBINF;
+     pVBInfo->BaseAddr = (unsigned long)pXGIHWDE->pjIOAddress ;
+@@ -209,18 +209,18 @@ void XGISetDPMS(PXGI_HW_DEVICE_INFO pXGIHWDE,
+     }
+ 
+     if ( VESA_POWER_STATE == 0x00000400 )
+-      XGINew_SetReg1( pVBInfo->Part4Port , 0x31 , ( UCHAR )( XGINew_GetReg1( pVBInfo->Part4Port , 0x31 ) & 0xFE ) ) ;
++	    XGINew_SetReg1(pVBInfo->Part4Port, 0x31, (unsigned char)(XGINew_GetReg1(pVBInfo->Part4Port, 0x31) & 0xFE));
+     else
+-      XGINew_SetReg1( pVBInfo->Part4Port , 0x31 , ( UCHAR )( XGINew_GetReg1( pVBInfo->Part4Port , 0x31 ) | 0x01 ) ) ;
++	    XGINew_SetReg1(pVBInfo->Part4Port, 0x31, (unsigned char)(XGINew_GetReg1(pVBInfo->Part4Port, 0x31) | 0x01));
+ 
+-    temp = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x1f ) ;
++    temp = (unsigned char)XGINew_GetReg1(pVBInfo->P3c4, 0x1f);
+     temp &= 0x3f ;
+     switch ( VESA_POWER_STATE )
+     {
+         case 0x00000000: /* on */
+             if ( ( pXGIHWDE->ujVBChipID == VB_CHIP_301 ) || ( pXGIHWDE->ujVBChipID == VB_CHIP_302 ) )
+             {
+-                XGINew_SetReg1( pVBInfo->P3c4 , 0x1f , ( UCHAR )( temp | 0x00 ) ) ;
++		XGINew_SetReg1(pVBInfo->P3c4, 0x1f, (unsigned char)(temp | 0x00));
+                 XGI_EnableBridge( pXGIHWDE, pVBInfo ) ;
+             }
+             else
+@@ -278,7 +278,7 @@ void XGISetDPMS(PXGI_HW_DEVICE_INFO pXGIHWDE,
+                 XGI_DisplayOff( pXGIHWDE, pVBInfo );
+             }
+ 
+-            XGINew_SetReg1( pVBInfo->P3c4 , 0x1f , ( UCHAR )( temp | 0x40 ) ) ;
++	    XGINew_SetReg1(pVBInfo->P3c4, 0x1f, (unsigned char)(temp | 0x40));
+             break ;
+         case 0x00000200: /* suspend */
+             if ( pXGIHWDE->jChipType == XG21 )
+@@ -291,12 +291,12 @@ void XGISetDPMS(PXGI_HW_DEVICE_INFO pXGIHWDE,
+                 XGI_DisplayOff( pXGIHWDE, pVBInfo );
+                 XGI_XG27BLSignalVDD( 0x20 , 0x00, pVBInfo ) ; /* LVDS signal off */
+             }
+-            XGINew_SetReg1( pVBInfo->P3c4 , 0x1f , ( UCHAR )( temp | 0x80 ) ) ;
++	    XGINew_SetReg1(pVBInfo->P3c4, 0x1f, (unsigned char)(temp | 0x80));
+             break ;
+         case 0x00000400: /* off */
+             if ( (pXGIHWDE->ujVBChipID == VB_CHIP_301 ) || ( pXGIHWDE->ujVBChipID == VB_CHIP_302 ) )
+             {
+-                XGINew_SetReg1( pVBInfo->P3c4 , 0x1f , ( UCHAR )( temp | 0xc0 ) ) ;
++		XGINew_SetReg1(pVBInfo->P3c4, 0x1f, (unsigned char)(temp | 0xc0));
+                 XGI_DisableBridge( pXGIHWDE, pVBInfo ) ;
+             }
+             else
+@@ -837,7 +837,7 @@ void XGI_XG21Fun14Sub70( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
+         ModeNo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeID;
+         if ( pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeID == 0xFF )
+         {
+-            pBiosArguments->h.bh = (UCHAR) EModeCount;
++	    pBiosArguments->h.bh = (unsigned char) EModeCount;
+             return;
+         }
+         if ( !XGI_XG21CheckLVDSMode( ModeNo , ModeIdIndex, pVBInfo) )
+@@ -883,7 +883,7 @@ void XGI_XG21Fun14Sub71( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
+         if (EModeCount == EModeIndex)
+         {
+             resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
+-            pBiosArguments->h.bl = (UCHAR) ModeNo;
++	    pBiosArguments->h.bl = (unsigned char) ModeNo;
+             pBiosArguments->x.cx = pVBInfo->ModeResInfo[ resindex ].HTotal ;			  /* xres->ax */
+             pBiosArguments->x.dx = pVBInfo->ModeResInfo[ resindex ].VTotal ;			  /* yres->bx */
+             pBiosArguments->x.ax = 0x0014;
+@@ -966,7 +966,7 @@ void XGI_XG21Fun14Sub72( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
+ */
+ void XGI_XG21Fun14Sub73( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
+ {
+-    UCHAR Select;
++    unsigned char Select;
+ 
+     unsigned short lvdstableindex;
+ 
+diff --git a/drivers/staging/xgifb/vb_ext.h b/drivers/staging/xgifb/vb_ext.h
+index 5cb1862d9542..768aebefc415 100644
+--- a/drivers/staging/xgifb/vb_ext.h
++++ b/drivers/staging/xgifb/vb_ext.h
+@@ -11,7 +11,8 @@ struct WORDREGS {
+ };
+ 
+ struct BYTEREGS {
+-    UCHAR   al, ah, hi_al, hi_ah, bl, bh, hi_bl, hi_bh, cl, ch, hi_cl, hi_ch, dl, dh, hi_dl, hi_dh;
++     unsigned char al, ah, hi_al, hi_ah, bl, bh, hi_bl, hi_bh, cl, ch,
++	     hi_cl, hi_ch, dl, dh, hi_dl, hi_dh;
+ };
+ 
+ typedef union   _X86_REGS    {
+@@ -25,7 +26,8 @@ extern void XGISetDPMS(PXGI_HW_DEVICE_INFO pXGIHWDE,
+ 		       unsigned long VESA_POWER_STATE);
+ extern   void     XGI_GetSenseStatus( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo );
+ extern   void     XGINew_SetModeScratch ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) ;
+-extern   void 	  ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo);
++extern void ReadVBIOSTablData(unsigned char ChipType,
++			      PVB_DEVICE_INFO pVBInfo);
+ extern unsigned short XGINew_SenseLCD(PXGI_HW_DEVICE_INFO,
+ 				      PVB_DEVICE_INFO pVBInfo);
+ 
+diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
+index 3f0e34bd0d05..343be2527a0e 100644
+--- a/drivers/staging/xgifb/vb_init.c
++++ b/drivers/staging/xgifb/vb_init.c
+@@ -18,7 +18,7 @@
+ 
+ 
+ 
+-UCHAR    XGINew_ChannelAB,XGINew_DataBusWidth;
++unsigned char XGINew_ChannelAB, XGINew_DataBusWidth;
+ 
+ unsigned short XGINew_DRAMType[17][5] = {
+ 	{0x0C, 0x0A, 0x02, 0x40, 0x39}, {0x0D, 0x0A, 0x01, 0x40, 0x48},
+@@ -79,8 +79,9 @@ void     XGINew_SetDRAMModeRegister(PVB_DEVICE_INFO );
+ void     XGINew_SetDRAMModeRegister340( PXGI_HW_DEVICE_INFO HwDeviceExtension );
+ void XGINew_SetDRAMDefaultRegister340(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ 				      unsigned long, PVB_DEVICE_INFO);
+-UCHAR    XGINew_GetXG20DRAMType( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo);
+-unsigned char  XGIInitNew( PXGI_HW_DEVICE_INFO HwDeviceExtension) ;
++unsigned char XGINew_GetXG20DRAMType(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++				     PVB_DEVICE_INFO pVBInfo);
++unsigned char XGIInitNew(PXGI_HW_DEVICE_INFO HwDeviceExtension);
+ 
+ int      XGINew_DDRSizing340( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO );
+ void     XGINew_DisableRefresh( PXGI_HW_DEVICE_INFO ,PVB_DEVICE_INFO) ;
+@@ -90,20 +91,20 @@ int      XGINew_DDRSizing( PVB_DEVICE_INFO );
+ void     XGINew_EnableRefresh( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO);
+ int      XGINew_RAMType;                  /*int      ModeIDOffset,StandTable,CRT1Table,ScreenOffset,REFIndex;*/
+ unsigned long	 UNIROM;			  /* UNIROM */
+-unsigned char  ChkLFB( PVB_DEVICE_INFO );
++unsigned char  ChkLFB(PVB_DEVICE_INFO);
+ void     XGINew_Delay15us(unsigned long);
+ void     SetPowerConsume(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ 			 unsigned long XGI_P3d4Port);
+-void 	 ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo);
++void     ReadVBIOSTablData(unsigned char ChipType, PVB_DEVICE_INFO pVBInfo);
+ void     XGINew_DDR1x_MRS_XG20(unsigned long P3c4, PVB_DEVICE_INFO pVBInfo);
+ void     XGINew_SetDRAMModeRegister_XG20( PXGI_HW_DEVICE_INFO HwDeviceExtension );
+ void     XGINew_SetDRAMModeRegister_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension );
+ void 	 XGINew_ChkSenseStatus ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) ;
+ void     XGINew_SetModeScratch ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) ;
+ void     XGINew_GetXG21Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) ;
+-UCHAR    GetXG21FPBits(PVB_DEVICE_INFO pVBInfo);
++unsigned char    GetXG21FPBits(PVB_DEVICE_INFO pVBInfo);
+ void     XGINew_GetXG27Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) ;
+-UCHAR    GetXG27FPBits(PVB_DEVICE_INFO pVBInfo);
++unsigned char    GetXG27FPBits(PVB_DEVICE_INFO pVBInfo);
+ 
+ void DelayUS(unsigned long MicroSeconds)
+ {
+@@ -117,12 +118,12 @@ void DelayUS(unsigned long MicroSeconds)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGIInitNew( PXGI_HW_DEVICE_INFO HwDeviceExtension )
++unsigned char XGIInitNew(PXGI_HW_DEVICE_INFO HwDeviceExtension)
+ {
+ 
+     VB_DEVICE_INFO VBINF;
+     PVB_DEVICE_INFO pVBInfo = &VBINF;
+-    UCHAR   i , temp = 0 , temp1 ;
++    unsigned char   i, temp = 0, temp1 ;
+      //       VBIOSVersion[ 5 ] ;
+     volatile unsigned char *pVideoMemory;
+ 
+@@ -363,8 +364,8 @@ printk("15");
+     XGI_UnLockCRT2( HwDeviceExtension, pVBInfo) ;
+     XGINew_SetRegANDOR( pVBInfo->Part0Port , 0x3F , 0xEF , 0x00 ) ;	/* alan, disable VideoCapture */
+     XGINew_SetReg1( pVBInfo->Part1Port , 0x00 , 0x00 ) ;
+-    temp1 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x7B ) ;		/* chk if BCLK>=100MHz */
+-    temp = ( UCHAR )( ( temp1 >> 4 ) & 0x0F ) ;
++    temp1 = (unsigned char)XGINew_GetReg1(pVBInfo->P3d4, 0x7B);	/* chk if BCLK>=100MHz */
++    temp = (unsigned char)((temp1 >> 4) & 0x0F);
+ 
+ 
+         XGINew_SetReg1( pVBInfo->Part1Port , 0x02 , ( *pVBInfo->pCRT2Data_1_2 ) ) ;
+@@ -489,7 +490,7 @@ printk("22");
+     /* SetDefExt2Regs begin */
+ /*
+     AGP = 1 ;
+-    temp =( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x3A ) ;
++    temp =(unsigned char)XGINew_GetReg1(pVBInfo->P3c4, 0x3A) ;
+     temp &= 0x30 ;
+     if ( temp == 0x30 )
+         AGP = 0 ;
+@@ -508,7 +509,7 @@ printk("22");
+ //    Temp = ( InPortLong( 0xcfc ) & 0xFFFF ) ;
+ //    if ( Temp == 0x1039 )
+ //    {
+-        XGINew_SetReg1( pVBInfo->P3c4 , 0x22 , ( UCHAR )( ( *pVBInfo->pSR22 ) & 0xFE ) ) ;
++	XGINew_SetReg1(pVBInfo->P3c4, 0x22, (unsigned char)((*pVBInfo->pSR22) & 0xFE));
+ //    }
+ //    else
+ //    {
+@@ -545,9 +546,10 @@ return 1;
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-UCHAR XGINew_GetXG20DRAMType( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
++unsigned char XGINew_GetXG20DRAMType(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++				     PVB_DEVICE_INFO pVBInfo)
+ {
+-    UCHAR data, temp ;
++    unsigned char data, temp;
+ 
+     if ( HwDeviceExtension->jChipType < XG20 )
+     {
+@@ -615,9 +617,9 @@ UCHAR XGINew_GetXG20DRAMType( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-UCHAR XGINew_Get310DRAMType(PVB_DEVICE_INFO pVBInfo)
++unsigned char XGINew_Get310DRAMType(PVB_DEVICE_INFO pVBInfo)
+ {
+-    UCHAR data ;
++    unsigned char data ;
+ 
+   /* index = XGINew_GetReg1( pVBInfo->P3c4 , 0x1A ) ; */
+   /* index &= 07 ; */
+@@ -1104,7 +1106,7 @@ void XGINew_DDR2_DefaultRegister(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ void XGINew_SetDRAMDefaultRegister340(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ 				      unsigned long Port, PVB_DEVICE_INFO pVBInfo)
+ {
+-    UCHAR temp , temp1 , temp2 , temp3 ,
++    unsigned char temp, temp1, temp2, temp3 ,
+           i , j , k ;
+ 
+     unsigned long P3d4 = Port ,
+@@ -1316,7 +1318,7 @@ void XGINew_DDR_MRS(PVB_DEVICE_INFO pVBInfo)
+ void XGINew_VerifyMclk( PXGI_HW_DEVICE_INFO  HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned char *pVideoMemory = pVBInfo->FBAddr ;
+-    UCHAR i , j ;
++    unsigned char i, j ;
+     unsigned short Temp , SR21 ;
+ 
+     pVideoMemory[ 0 ] = 0xaa ; 		/* alan */
+@@ -1454,7 +1456,7 @@ void XGINew_SetDRAMSize_310( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_
+ 
+ void XGINew_SetDRAMModeRegister340( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+ {
+-    UCHAR data ;
++    unsigned char data ;
+     VB_DEVICE_INFO VBINF;
+     PVB_DEVICE_INFO pVBInfo = &VBINF;
+     pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+@@ -1749,8 +1751,8 @@ void XGINew_CheckBusWidth_310(  PVB_DEVICE_INFO pVBInfo)
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ int XGINew_SetRank(int index,
+-		   UCHAR RankNo,
+-		   UCHAR XGINew_ChannelAB,
++		   unsigned char RankNo,
++		   unsigned char XGINew_ChannelAB,
+ 		   unsigned short DRAMTYPE_TABLE[][5],
+ 		   PVB_DEVICE_INFO pVBInfo)
+ {
+@@ -1790,8 +1792,8 @@ int XGINew_SetRank(int index,
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ int XGINew_SetDDRChannel(int index,
+-			 UCHAR ChannelNo,
+-			 UCHAR XGINew_ChannelAB,
++			 unsigned char ChannelNo,
++			 unsigned char XGINew_ChannelAB,
+ 			 unsigned short DRAMTYPE_TABLE[][5],
+ 			 PVB_DEVICE_INFO pVBInfo)
+ {
+@@ -2035,7 +2037,7 @@ int XGINew_CheckDDRRanks(int RankNo, int index,
+ int XGINew_SDRSizing(PVB_DEVICE_INFO pVBInfo)
+ {
+     int    i ;
+-    UCHAR  j ;
++    unsigned char  j ;
+ 
+     for( i = 0 ; i < 13 ; i++ )
+     {
+@@ -2043,7 +2045,8 @@ int XGINew_SDRSizing(PVB_DEVICE_INFO pVBInfo)
+ 
+         for( j = 2 ; j > 0 ; j-- )
+         {
+-            if ( !XGINew_SetRank( i , ( UCHAR )j , XGINew_ChannelAB , XGINew_SDRDRAM_TYPE , pVBInfo) )
++	    if (!XGINew_SetRank(i, (unsigned char)j, XGINew_ChannelAB,
++				 XGINew_SDRDRAM_TYPE, pVBInfo))
+                 continue ;
+             else
+             {
+@@ -2068,7 +2071,7 @@ unsigned short XGINew_SetDRAMSizeReg(int index,
+ {
+     unsigned short data = 0 , memsize = 0;
+     int RankSize ;
+-    UCHAR ChannelNo ;
++    unsigned char ChannelNo ;
+ 
+     RankSize = DRAMTYPE_TABLE[ index ][ 3 ] * XGINew_DataBusWidth / 32 ;
+     data = XGINew_GetReg1( pVBInfo->P3c4 , 0x13 ) ;
+@@ -2119,7 +2122,7 @@ unsigned short XGINew_SetDRAMSize20Reg(int index,
+ {
+     unsigned short data = 0 , memsize = 0;
+     int RankSize ;
+-    UCHAR ChannelNo ;
++    unsigned char ChannelNo ;
+ 
+     RankSize = DRAMTYPE_TABLE[ index ][ 3 ] * XGINew_DataBusWidth / 8 ;
+     data = XGINew_GetReg1( pVBInfo->P3c4 , 0x13 ) ;
+@@ -2202,9 +2205,9 @@ int XGINew_ReadWriteRest(unsigned short StopAddr, unsigned short StartAddr,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-UCHAR XGINew_CheckFrequence( PVB_DEVICE_INFO pVBInfo )
++unsigned char XGINew_CheckFrequence(PVB_DEVICE_INFO pVBInfo)
+ {
+-    UCHAR data ;
++    unsigned char data ;
+ 
+     data = XGINew_GetReg1( pVBInfo->P3d4 , 0x97 ) ;
+ 
+@@ -2227,7 +2230,7 @@ UCHAR XGINew_CheckFrequence( PVB_DEVICE_INFO pVBInfo )
+ /* --------------------------------------------------------------------- */
+ void XGINew_CheckChannel( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+-    UCHAR data;
++    unsigned char data;
+ 
+     switch( HwDeviceExtension->jChipType )
+     {
+@@ -2564,7 +2567,7 @@ int XGINew_DDRSizing340( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO
+ int XGINew_DDRSizing(PVB_DEVICE_INFO pVBInfo)
+ {
+     int    i ;
+-    UCHAR  j ;
++    unsigned char  j ;
+ 
+     for( i = 0 ; i < 4 ; i++ )
+     {
+@@ -2573,7 +2576,8 @@ int XGINew_DDRSizing(PVB_DEVICE_INFO pVBInfo)
+         for( j = 2 ; j > 0 ; j-- )
+         {
+             XGINew_SetDDRChannel( i , j , XGINew_ChannelAB , XGINew_DDRDRAM_TYPE , pVBInfo ) ;
+-            if ( !XGINew_SetRank( i , ( UCHAR )j , XGINew_ChannelAB , XGINew_DDRDRAM_TYPE, pVBInfo ) )
++	    if (!XGINew_SetRank(i, (unsigned char)j, XGINew_ChannelAB,
++				XGINew_DDRDRAM_TYPE, pVBInfo))
+                 continue ;
+             else
+             {
+@@ -2612,9 +2616,7 @@ void XGINew_SetMemoryClock( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_IN
+       if ( ( pVBInfo->MCLKData[ XGINew_RAMType ].SR28 == 0x1C ) && ( pVBInfo->MCLKData[ XGINew_RAMType ].SR29 == 0x01 )
+         && ( ( ( pVBInfo->ECLKData[ XGINew_RAMType ].SR2E == 0x1C ) && ( pVBInfo->ECLKData[ XGINew_RAMType ].SR2F == 0x01 ) )
+         || ( ( pVBInfo->ECLKData[ XGINew_RAMType ].SR2E == 0x22 ) && ( pVBInfo->ECLKData[ XGINew_RAMType ].SR2F == 0x01 ) ) ) )
+-      {
+-      	XGINew_SetReg1( pVBInfo->P3c4 , 0x32 , ( ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x32 ) & 0xFC ) | 0x02 ) ;
+-      }
++	      XGINew_SetReg1(pVBInfo->P3c4, 0x32, ((unsigned char)XGINew_GetReg1(pVBInfo->P3c4, 0x32) & 0xFC) | 0x02);
+     }
+ }
+ 
+@@ -2625,7 +2627,7 @@ void XGINew_SetMemoryClock( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_IN
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char ChkLFB( PVB_DEVICE_INFO pVBInfo )
++unsigned char ChkLFB(PVB_DEVICE_INFO pVBInfo)
+ {
+ 	if (LFBDRAMTrap & XGINew_GetReg1(pVBInfo->P3d4 , 0x78))
+ 		return 1;
+@@ -2646,14 +2648,14 @@ void SetPowerConsume(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ 		     unsigned long XGI_P3d4Port)
+ {
+     unsigned long   lTemp ;
+-    UCHAR   bTemp;
++    unsigned char   bTemp;
+ 
+     HwDeviceExtension->pQueryVGAConfigSpace( HwDeviceExtension , 0x08 , 0 , &lTemp ) ; /* Get */
+     if ((lTemp&0xFF)==0)
+     {
+         /* set CR58 D[5]=0 D[3]=0 */
+         XGINew_SetRegAND( XGI_P3d4Port , 0x58 , 0xD7 ) ;
+-        bTemp = (UCHAR) XGINew_GetReg1( XGI_P3d4Port , 0xCB ) ;
++	bTemp = (unsigned char) XGINew_GetReg1(XGI_P3d4Port, 0xCB);
+     	if (bTemp&0x20)
+     	{
+             if (!(bTemp&0x10))
+@@ -2720,11 +2722,11 @@ void XGINew_InitVBIOSData(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo)
++void ReadVBIOSTablData(unsigned char ChipType, PVB_DEVICE_INFO pVBInfo)
+ {
+ 	volatile unsigned char *pVideoMemory = (unsigned char *)pVBInfo->ROMAddr;
+     unsigned long   i ;
+-    UCHAR   j , k ;
++    unsigned char   j, k ;
+     /* Volari customize data area end */
+ 
+     if ( ChipType == XG21 )
+@@ -2910,7 +2912,7 @@ void XGINew_SetDRAMModeRegister_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+ void XGINew_SetDRAMModeRegister_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+ {
+ 
+-    UCHAR data ;
++    unsigned char data ;
+     VB_DEVICE_INFO VBINF;
+     PVB_DEVICE_INFO pVBInfo = &VBINF;
+     pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+@@ -3114,7 +3116,7 @@ void XGINew_SetModeScratch ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_
+ /* -------------------------------------------------------- */
+ void XGINew_GetXG21Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+-    UCHAR Temp;
++    unsigned char Temp;
+     volatile unsigned char *pVideoMemory = (unsigned char *)pVBInfo->ROMAddr;
+ 
+     pVBInfo->IF_DEF_LVDS = 0 ;
+@@ -3156,7 +3158,7 @@ void XGINew_GetXG21Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO
+ /* -------------------------------------------------------- */
+ void XGINew_GetXG27Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+-    UCHAR Temp,bCR4A;
++	unsigned char Temp, bCR4A;
+ 
+      pVBInfo->IF_DEF_LVDS = 0 ;
+      bCR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
+@@ -3178,9 +3180,9 @@ void XGINew_GetXG27Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO
+ 
+ }
+ 
+-UCHAR GetXG21FPBits(PVB_DEVICE_INFO pVBInfo)
++unsigned char GetXG21FPBits(PVB_DEVICE_INFO pVBInfo)
+ {
+-    UCHAR CR38,CR4A,temp;
++	unsigned char CR38, CR4A, temp;
+ 
+     CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
+     XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x4A , ~0x10 , 0x10 ) ; /* enable GPIOE read */
+@@ -3198,9 +3200,9 @@ UCHAR GetXG21FPBits(PVB_DEVICE_INFO pVBInfo)
+     return temp;
+ }
+ 
+-UCHAR GetXG27FPBits(PVB_DEVICE_INFO pVBInfo)
++unsigned char GetXG27FPBits(PVB_DEVICE_INFO pVBInfo)
+ {
+-    UCHAR CR4A,temp;
++	unsigned char CR4A, temp;
+ 
+     CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
+     XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x4A , ~0x03 , 0x03 ) ; /* enable GPIOA/B/C read */
+diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c
+index f27259e80987..5a74c595d78a 100644
+--- a/drivers/staging/xgifb/vb_setmode.c
++++ b/drivers/staging/xgifb/vb_setmode.c
+@@ -42,7 +42,7 @@ unsigned char  XGI_GetLCDInfo(unsigned short ModeNo,
+ unsigned char  XGISetModeNew(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ 		       unsigned short ModeNo);
+ unsigned char  XGI_BridgeIsOn(PVB_DEVICE_INFO pVBInfo);
+-UCHAR    XGI_GetModePtr(unsigned short ModeNo,
++unsigned char    XGI_GetModePtr(unsigned short ModeNo,
+ 			unsigned short ModeIdIndex,
+ 			PVB_DEVICE_INFO pVBInfo);
+ unsigned short XGI_GetOffset(unsigned short ModeNo,
+@@ -131,7 +131,7 @@ void     XGI_GetVBType(PVB_DEVICE_INFO  pVBInfo);
+ void     XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO  pVBInfo);
+ void     XGI_GetTVInfo(unsigned short ModeNo, unsigned short ModeIdIndex,PVB_DEVICE_INFO  pVBInfo);
+ void     XGI_SetCRT2ECLK(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,PVB_DEVICE_INFO  pVBInfo);
+-void     InitTo330Pointer(UCHAR,PVB_DEVICE_INFO pVBInfo);
++void     InitTo330Pointer(unsigned char, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_GetLCDSync(unsigned short *HSyncWidth, unsigned short *VSyncWidth, PVB_DEVICE_INFO pVBInfo);
+ void 	 XGI_DisableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+ void  	 XGI_EnableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+@@ -146,7 +146,8 @@ void     XGI_SetAntiFlicker(unsigned short ModeNo, unsigned short ModeIdIndex, P
+ void     XGI_SetEdgeEnhance(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SetPhaseIncr(PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SetYFilter(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_GetTVPtrIndex2(unsigned short *tempbx,UCHAR* tempcl,UCHAR* tempch, PVB_DEVICE_INFO pVBInfo);
++void     XGI_GetTVPtrIndex2(unsigned short *tempbx, unsigned char* tempcl,
++			    unsigned char *tempch, PVB_DEVICE_INFO pVBInfo);
+ unsigned short   XGI_GetTVPtrIndex(PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SetCRT2ModeRegs(unsigned short ModeNo,PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo );
+ void     XGI_CloseCRTC(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
+@@ -155,28 +156,33 @@ void     XGI_GetRAMDAC2DATA(unsigned short ModeNo, unsigned short ModeIdIndex, u
+ void     XGI_UnLockCRT2(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_LockCRT2(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
+ void     XGINew_EnableCRT2(PVB_DEVICE_INFO pVBInfo);
+-void     XGINew_LCD_Wait_Time(UCHAR DelayTime, PVB_DEVICE_INFO pVBInfo);
++void     XGINew_LCD_Wait_Time(unsigned char DelayTime, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_LongWait(PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SetCRT1Offset(unsigned short ModeNo , unsigned short ModeIdIndex , unsigned short RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo );
+-void     XGI_GetLCDVCLKPtr(UCHAR* di_0,UCHAR *di_1, PVB_DEVICE_INFO pVBInfo);
+-UCHAR    XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex, unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_GetVCLKLen(UCHAR tempal,UCHAR* di_0,UCHAR* di_1, PVB_DEVICE_INFO pVBInfo);
++void     XGI_GetLCDVCLKPtr(unsigned char *di_0, unsigned char *di_1,
++			   PVB_DEVICE_INFO pVBInfo);
++unsigned char    XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex,
++				unsigned short ModeNo,
++				unsigned short ModeIdIndex,
++				PVB_DEVICE_INFO pVBInfo);
++void     XGI_GetVCLKLen(unsigned char tempal, unsigned char *di_0,
++			unsigned char *di_1, PVB_DEVICE_INFO pVBInfo);
+ unsigned short   XGI_GetLCDCapPtr(PVB_DEVICE_INFO pVBInfo);
+ unsigned short   XGI_GetLCDCapPtr1(PVB_DEVICE_INFO pVBInfo);
+ XGI301C_Tap4TimingStruct *XGI_GetTap4Ptr(unsigned short tempcx, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SetXG21FPBits(PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SetXG27FPBits(PVB_DEVICE_INFO pVBInfo);
+-UCHAR    XGI_XG21GetPSCValue(PVB_DEVICE_INFO pVBInfo);
+-UCHAR    XGI_XG27GetPSCValue(PVB_DEVICE_INFO pVBInfo);
++unsigned char    XGI_XG21GetPSCValue(PVB_DEVICE_INFO pVBInfo);
++unsigned char    XGI_XG27GetPSCValue(PVB_DEVICE_INFO pVBInfo);
+ void     XGI_XG21BLSignalVDD(unsigned short tempbh, unsigned short tempbl, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_XG27BLSignalVDD(unsigned short tempbh, unsigned short tempbl, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_XG21SetPanelDelay(unsigned short tempbl, PVB_DEVICE_INFO pVBInfo);
+-unsigned char  XGI_XG21CheckLVDSMode(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
++unsigned char  XGI_XG21CheckLVDSMode(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SetXG21LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
+ void     XGI_SetXG27LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
+-UCHAR    XGI_SetDefaultVCLK( PVB_DEVICE_INFO pVBInfo );
++unsigned char  XGI_SetDefaultVCLK(PVB_DEVICE_INFO pVBInfo);
+ 
+-extern   void 	  ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo);
++extern void ReadVBIOSTablData(unsigned char ChipType, PVB_DEVICE_INFO pVBInfo);
+ 
+ /* unsigned short XGINew_flag_clearbuffer; 0: no clear frame buffer 1:clear frame buffer */
+ 
+@@ -230,7 +236,7 @@ unsigned short XGINew_VGA_DAC[] = {
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void InitTo330Pointer( UCHAR ChipType ,PVB_DEVICE_INFO pVBInfo)
++void InitTo330Pointer(unsigned char ChipType, PVB_DEVICE_INFO pVBInfo)
+ {
+     pVBInfo->SModeIDTable = (XGI_StStruct *) XGI330_SModeIDTable ;
+     pVBInfo->StandTable = (XGI_StandTableStruct *) XGI330_StandTable ;
+@@ -385,10 +391,11 @@ void InitTo330Pointer( UCHAR ChipType ,PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGISetModeNew(PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short ModeNo)
++unsigned char XGISetModeNew(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++			    unsigned short ModeNo)
+ {
+     unsigned short ModeIdIndex ;
+-        /* PUCHAR pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ; */
++        /* unsigned char *pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ; */
+     VB_DEVICE_INFO VBINF;
+     PVB_DEVICE_INFO pVBInfo = &VBINF;
+     pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+@@ -668,14 +675,14 @@ void XGI_SetCRT1Group(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+     	{
+     	    XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , 0x4E) ;
+     	    XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , 0xE9) ;
+-    	    b3CC =(UCHAR) XGINew_GetReg2(XGINew_P3cc) ;
++	    b3CC = (unsigned char) XGINew_GetReg2(XGINew_P3cc) ;
+     	    XGINew_SetReg3(XGINew_P3cc ,  (b3CC |= 0x0C) ) ;
+     	}
+     	else if ( ( ModeNo == 0x04) | ( ModeNo == 0x05) | ( ModeNo == 0x0D) )
+     	{
+     	    XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , 0x1B) ;
+     	    XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , 0xE3) ;
+-    	    b3CC = (UCHAR)XGINew_GetReg2(XGINew_P3cc) ;
++	    b3CC = (unsigned char)XGINew_GetReg2(XGINew_P3cc) ;
+     	    XGINew_SetReg3(XGINew_P3cc ,  (b3CC |= 0x0C) ) ;
+     	}
+     }
+@@ -730,10 +737,10 @@ void XGI_SetCRT1Group(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-UCHAR XGI_GetModePtr(unsigned short ModeNo, unsigned short ModeIdIndex,
++unsigned char XGI_GetModePtr(unsigned short ModeNo, unsigned short ModeIdIndex,
+ 		     PVB_DEVICE_INFO pVBInfo)
+ {
+-    UCHAR index ;
++    unsigned char index ;
+ 
+     if ( ModeNo <= 0x13 )
+         index = pVBInfo->SModeIDTable[ ModeIdIndex ].St_StTableIndex ;
+@@ -754,7 +761,7 @@ UCHAR XGI_GetModePtr(unsigned short ModeNo, unsigned short ModeIdIndex,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-/*UCHAR XGI_SetBIOSData(unsigned short ModeNo , unsigned short ModeIdIndex )
++/*unsigned char XGI_SetBIOSData(unsigned short ModeNo, unsigned short ModeIdIndex)
+ {
+     return( 0 ) ;
+ }
+@@ -766,7 +773,7 @@ UCHAR XGI_GetModePtr(unsigned short ModeNo, unsigned short ModeIdIndex,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-/*UCHAR XGI_ClearBankRegs(unsigned short ModeNo , unsigned short ModeIdIndex )
++/*unsigned char XGI_ClearBankRegs(unsigned short ModeNo, unsigned short ModeIdIndex)
+ {
+     return( 0 ) ;
+ }
+@@ -781,7 +788,7 @@ UCHAR XGI_GetModePtr(unsigned short ModeNo, unsigned short ModeIdIndex,
+ void XGI_SetSeqRegs(unsigned short ModeNo, unsigned short StandTableIndex,
+ 		    unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+ {
+-    UCHAR tempah ,
++    unsigned char tempah ,
+           SRdata ;
+ 
+     unsigned short i ,
+@@ -828,7 +835,7 @@ void XGI_SetSeqRegs(unsigned short ModeNo, unsigned short StandTableIndex,
+ /* --------------------------------------------------------------------- */
+ void XGI_SetMiscRegs(unsigned short StandTableIndex, PVB_DEVICE_INFO pVBInfo )
+ {
+-    UCHAR Miscdata ;
++    unsigned char Miscdata ;
+ 
+     Miscdata = pVBInfo->StandTable[ StandTableIndex ].MISC ;	/* Get Misc from file */
+ /*
+@@ -851,13 +858,13 @@ void XGI_SetMiscRegs(unsigned short StandTableIndex, PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetCRTCRegs(PXGI_HW_DEVICE_INFO HwDeviceExtension ,
++void XGI_SetCRTCRegs(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ 		     unsigned short StandTableIndex, PVB_DEVICE_INFO pVBInfo)
+ {
+-    UCHAR CRTCdata ;
++    unsigned char CRTCdata ;
+     unsigned short i ;
+ 
+-    CRTCdata = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;
++    CRTCdata = (unsigned char)XGINew_GetReg1(pVBInfo->P3d4, 0x11);
+     CRTCdata &= 0x7f ;
+     XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , CRTCdata ) ;		/* Unlock CRTC */
+ 
+@@ -890,7 +897,7 @@ void XGI_SetCRTCRegs(PXGI_HW_DEVICE_INFO HwDeviceExtension ,
+ void XGI_SetATTRegs(unsigned short ModeNo, unsigned short StandTableIndex,
+ 		    unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+ {
+-    UCHAR ARdata ;
++    unsigned char ARdata ;
+     unsigned short i, modeflag;
+ 
+     if ( ModeNo <= 0x13 )
+@@ -939,7 +946,7 @@ void XGI_SetATTRegs(unsigned short ModeNo, unsigned short StandTableIndex,
+ /* --------------------------------------------------------------------- */
+ void XGI_SetGRCRegs(unsigned short StandTableIndex, PVB_DEVICE_INFO pVBInfo )
+ {
+-    UCHAR GRdata ;
++    unsigned char GRdata ;
+     unsigned short i ;
+ 
+     for( i = 0 ; i <= 0x08 ; i++ )
+@@ -950,7 +957,7 @@ void XGI_SetGRCRegs(unsigned short StandTableIndex, PVB_DEVICE_INFO pVBInfo )
+ 
+     if ( pVBInfo->ModeType > ModeVGA )
+     {
+-        GRdata = ( UCHAR )XGINew_GetReg1( pVBInfo->P3ce , 0x05 ) ;
++	GRdata = (unsigned char)XGINew_GetReg1(pVBInfo->P3ce, 0x05);
+         GRdata &= 0xBF ;						/* 256 color disable */
+         XGINew_SetReg1( pVBInfo->P3ce , 0x05 , GRdata ) ;
+     }
+@@ -978,7 +985,7 @@ void XGI_ClearExt1Regs(PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-UCHAR XGI_SetDefaultVCLK( PVB_DEVICE_INFO pVBInfo )
++unsigned char XGI_SetDefaultVCLK(PVB_DEVICE_INFO pVBInfo)
+ {
+ 
+     XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x31 , ~0x30 , 0x20 ) ;
+@@ -1005,7 +1012,7 @@ unsigned short XGI_GetRatePtrCRT2(PXGI_HW_DEVICE_INFO pXGIHWDE,
+ 				  unsigned short ModeIdIndex,
+ 				  PVB_DEVICE_INFO pVBInfo)
+ {
+-    SHORT  LCDRefreshIndex[] = { 0x00 , 0x00 , 0x03 , 0x01 } ,
++    short LCDRefreshIndex[] = { 0x00 , 0x00 , 0x03 , 0x01 } ,
+            LCDARefreshIndex[] = { 0x00 , 0x00 , 0x03 , 0x01 , 0x01 , 0x01 , 0x01 } ;
+ 
+     unsigned short RefreshRateTableIndex, i, modeflag, index, temp;
+@@ -1140,8 +1147,8 @@ unsigned short XGI_GetRatePtrCRT2(PXGI_HW_DEVICE_INFO pXGIHWDE,
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ unsigned char XGI_AjustCRT2Rate(unsigned short ModeNo, unsigned short ModeIdIndex,
+-			  unsigned short RefreshRateTableIndex,
+-			  unsigned short *i, PVB_DEVICE_INFO pVBInfo)
++				unsigned short RefreshRateTableIndex,
++				unsigned short *i, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short tempax, tempbx, resinfo, modeflag, infoflag;
+ 
+@@ -1337,15 +1344,13 @@ void XGI_SetCRT1CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
+ 		     PVB_DEVICE_INFO pVBInfo,
+ 		     PXGI_HW_DEVICE_INFO HwDeviceExtension)
+ {
+-    UCHAR  index ,
+-           data ;
+-
++    unsigned char index, data;
+     unsigned short i;
+ 
+     index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ;	/* Get index */
+     index = index&IndexMask ;
+ 
+-    data =( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;
++    data = (unsigned char)XGINew_GetReg1(pVBInfo->P3d4, 0x11);
+     data &= 0x7F ;
+     XGINew_SetReg1(pVBInfo->P3d4,0x11,data);				/* Unlock CRTC */
+ 
+@@ -1375,14 +1380,14 @@ void XGI_SetCRT1CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
+ /* --------------------------------------------------------------------- */
+ void XGI_SetCRT1Timing_H( PVB_DEVICE_INFO pVBInfo, PXGI_HW_DEVICE_INFO HwDeviceExtension )
+ {
+-    UCHAR data , data1, pushax;
++    unsigned char data, data1, pushax;
+     unsigned short i, j;
+ 
+     /* XGINew_SetReg1( pVBInfo->P3d4 , 0x51 , 0 ) ; */
+     /* XGINew_SetReg1( pVBInfo->P3d4 , 0x56 , 0 ) ; */
+     /* XGINew_SetRegANDOR( pVBInfo->P3d4 ,0x11 , 0x7f , 0x00 ) ; */
+ 
+-    data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;		/* unlock cr0-7 */
++    data = (unsigned char)XGINew_GetReg1(pVBInfo->P3d4, 0x11); /* unlock cr0-7 */
+     data &= 0x7F ;
+     XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , data ) ;
+ 
+@@ -1401,7 +1406,7 @@ void XGI_SetCRT1Timing_H( PVB_DEVICE_INFO pVBInfo, PXGI_HW_DEVICE_INFO HwDeviceE
+ 	XGINew_SetReg1(pVBInfo->P3c4, (unsigned short)(i + 6), data);
+     }
+ 
+-    j = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x0e ) ;
++    j = (unsigned char)XGINew_GetReg1(pVBInfo->P3c4, 0x0e);
+     j &= 0x1F ;
+     data = pVBInfo->TimingH[ 0 ].data[ 7 ] ;
+     data &= 0xE0 ;
+@@ -1410,17 +1415,17 @@ void XGI_SetCRT1Timing_H( PVB_DEVICE_INFO pVBInfo, PXGI_HW_DEVICE_INFO HwDeviceE
+ 
+     if ( HwDeviceExtension->jChipType >= XG20 )
+     {
+-    	data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x04 ) ;
++	data = (unsigned char)XGINew_GetReg1(pVBInfo->P3d4, 0x04);
+     	data = data - 1 ;
+     	XGINew_SetReg1( pVBInfo->P3d4 , 0x04 , data ) ;
+-    	data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x05 ) ;
++	data = (unsigned char)XGINew_GetReg1(pVBInfo->P3d4, 0x05);
+     	data1 = data ;
+     	data1 &= 0xE0 ;
+     	data &= 0x1F ;
+     	if ( data == 0 )
+     	{
+     	    pushax = data ;
+-    	    data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x0c ) ;
++	    data = (unsigned char)XGINew_GetReg1(pVBInfo->P3c4, 0x0c);
+     	    data &= 0xFB ;
+     	    XGINew_SetReg1( pVBInfo->P3c4 , 0x0c , data ) ;
+     	    data = pushax ;
+@@ -1428,7 +1433,7 @@ void XGI_SetCRT1Timing_H( PVB_DEVICE_INFO pVBInfo, PXGI_HW_DEVICE_INFO HwDeviceE
+     	data = data - 1 ;
+     	data |= data1 ;
+     	XGINew_SetReg1( pVBInfo->P3d4 , 0x05 , data ) ;
+-    	data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x0e ) ;
++	data = (unsigned char)XGINew_GetReg1(pVBInfo->P3c4, 0x0e);
+     	data = data >> 5 ;
+     	data = data + 3 ;
+     	if ( data > 7 )
+@@ -1449,7 +1454,7 @@ void XGI_SetCRT1Timing_V(unsigned short ModeIdIndex,
+ 			 unsigned short ModeNo,
+ 			 PVB_DEVICE_INFO pVBInfo)
+ {
+-    UCHAR data ;
++    unsigned char data;
+     unsigned short i, j;
+ 
+     /* XGINew_SetReg1( pVBInfo->P3d4 , 0x51 , 0 ) ; */
+@@ -1474,7 +1479,7 @@ void XGI_SetCRT1Timing_V(unsigned short ModeIdIndex,
+ 	XGINew_SetReg1(pVBInfo->P3d4, (unsigned short)(i + 0x11), data);
+     }
+ 
+-    j = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x0a ) ;
++    j = (unsigned char)XGINew_GetReg1(pVBInfo->P3c4, 0x0a);
+     j &= 0xC0 ;
+     data = pVBInfo->TimingV[ 0 ].data[ 6 ] ;
+     data &= 0x3F ;
+@@ -1494,7 +1499,7 @@ void XGI_SetCRT1Timing_V(unsigned short ModeIdIndex,
+     if ( i )
+         data |= 0x80 ;
+ 
+-    j = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x09 ) ;
++    j = (unsigned char)XGINew_GetReg1(pVBInfo->P3d4, 0x09);
+     j &= 0x5F ;
+     data |= j ;
+     XGINew_SetReg1( pVBInfo->P3d4 , 0x09 , data ) ;
+@@ -1511,7 +1516,7 @@ void XGI_SetXG21CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
+ 		     unsigned short RefreshRateTableIndex,
+ 		     PVB_DEVICE_INFO pVBInfo)
+ {
+-  UCHAR StandTableIndex, index, Tempax, Tempbx, Tempcx, Tempdx ;
++  unsigned char StandTableIndex, index, Tempax, Tempbx, Tempcx, Tempdx;
+   unsigned short Temp1, Temp2, Temp3;
+ 
+   if ( ModeNo <= 0x13 )
+@@ -1541,7 +1546,7 @@ void XGI_SetXG21CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
+     Tempdx |= Tempcx ;							/* Tempdx: VRS[8:1] */
+     XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , Tempdx ) ;    		/* SR34[7:0]: VRS[8:1] */
+ 
+-    Temp1 = Tempcx << 1 ;						/* Temp1[8]: VRS[8] UCHAR -> unsigned short */
++    Temp1 = Tempcx << 1 ;						/* Temp1[8]: VRS[8] unsigned char -> unsigned short */
+     Temp1 |= Tempbx ;							/* Temp1[8:0]: VRS[8:0] */
+     Tempax &= 0x80 ;							/* Tempax[7]: CR7[7] */
+     Temp2 = Tempax << 2 ;						/* Temp2[9]: VRS[9] */
+@@ -1555,11 +1560,11 @@ void XGI_SetXG21CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
+     if ( Tempax < Temp3 )						/* VRE[3:0]>= 9 ;							/* [10:9]->[1:0] */
+-    Tempbx = (UCHAR)Temp1 ;						/* Tempbx[1:0]: VRS[10:9] */
++    Tempbx = (unsigned char)Temp1;					/* Tempbx[1:0]: VRS[10:9] */
+     Tempax |= Tempbx ;							/* VRE[5:0]VRS[10:9] */
+     Tempax &= 0x7F ;
+     XGINew_SetReg1( pVBInfo->P3c4 , 0x3F , Tempax ) ;   		/* SR3F D[7:2]->VRE D[1:0]->VRS */
+@@ -1593,7 +1598,7 @@ void XGI_SetXG21CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
+       Temp2 |= 0x40 ;                                                   /* Temp2 + 0x40 */
+ 
+     Temp2 &= 0xFF ;
+-    Tempax = (UCHAR)Temp2 ;						/* Tempax: HRE[7:0] */
++    Tempax = (unsigned char)Temp2;					/* Tempax: HRE[7:0] */
+     Tempax <<= 2 ;							/* Tempax[7:2]: HRE[5:0] */
+     Tempdx >>= 6 ;							/* Tempdx[7:6]->[1:0] HRS[9:8] */
+     Tempax |= Tempdx ;							/* HRE[5:0]HRS[9:8] */
+@@ -1637,11 +1642,11 @@ void XGI_SetXG21CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
+       Temp2 |= 0x20 ;							/* VRE + 0x20 */
+ 
+     Temp2 &= 0xFF ;
+-    Tempax = (UCHAR)Temp2 ;						/* Tempax: VRE[7:0] */
++    Tempax = (unsigned char)Temp2;					/* Tempax: VRE[7:0] */
+     Tempax <<= 2 ;							/* Tempax[7:0]; VRE[5:0]00 */
+     Temp1 &= 0x600 ;							/* Temp1[10:9]: VRS[10:9] */
+     Temp1 >>= 9 ;  							/* Temp1[1:0]: VRS[10:9] */
+-    Tempbx = (UCHAR)Temp1 ;
++    Tempbx = (unsigned char)Temp1;
+     Tempax |= Tempbx ;							/* Tempax[7:0]: VRE[5:0]VRS[10:9] */
+     Tempax &= 0x7F ;
+     XGINew_SetReg1( pVBInfo->P3c4 , 0x3F , Tempax ) ;   		/* SR3F D[7:2]->VRE D[1:0]->VRS */
+@@ -1689,7 +1694,7 @@ void XGI_SetXG27CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
+     Tempbx |= Tempax ;							/* Tempbx[9:0]: VRE[9:0] */
+     if ( Tempax <= (Tempcx & 0x0F) )					/* VRE[3:0]<=VRS[3:0] */
+       Tempbx |= 0x10 ;							/* Tempbx: VRE + 0x10 */
+-    Tempax = (UCHAR)Tempbx & 0xFF;					/* Tempax[7:0]: VRE[7:0] */
++    Tempax = (unsigned char)Tempbx & 0xFF;				/* Tempax[7:0]: VRE[7:0] */
+     Tempax <<= 2 ;							/* Tempax << 2: VRE[5:0] */
+     Tempcx = (Tempcx&0x600)>>8;                                         /* Tempcx VRS[10:9] */
+     XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x3F , ~0xFC, Tempax ) ;        /* SR3F D[7:2]->VRE D[5:0] */
+@@ -1809,7 +1814,7 @@ void XGI_SetXG21LCD(PVB_DEVICE_INFO pVBInfo,
+ 
+   if ( ModeNo <= 0x13 )
+   {
+-    b3CC = (UCHAR) XGINew_GetReg2( XGI_P3cc ) ;
++    b3CC = (unsigned char) XGINew_GetReg2(XGI_P3cc);
+     if ( b3CC & 0x40 )
+       XGINew_SetRegOR( pVBInfo->P3c4 , 0x30 , 0x20 ) ; /* Hsync polarity */
+     if ( b3CC & 0x80 )
+@@ -1863,7 +1868,7 @@ void XGI_SetXG27LCD(PVB_DEVICE_INFO pVBInfo,
+ 
+   if ( ModeNo <= 0x13 )
+   {
+-    b3CC = (UCHAR) XGINew_GetReg2( XGI_P3cc ) ;
++    b3CC = (unsigned char) XGINew_GetReg2(XGI_P3cc);
+     if ( b3CC & 0x40 )
+       XGINew_SetRegOR( pVBInfo->P3c4 , 0x30 , 0x20 ) ; /* Hsync polarity */
+     if ( b3CC & 0x80 )
+@@ -1938,7 +1943,7 @@ void XGI_SetCRT1DE(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ {
+ 	unsigned short resindex, tempax, tempbx, tempcx, temp, modeflag;
+ 
+-    UCHAR data ;
++    unsigned char data;
+ 
+     resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
+ 
+@@ -1981,8 +1986,8 @@ void XGI_SetCRT1DE(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+     tempax -= 1 ;
+     tempbx -= 1 ;
+     tempcx = tempax ;
+-    temp = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;
+-    data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;
++    temp = (unsigned char)XGINew_GetReg1(pVBInfo->P3d4, 0x11);
++    data = (unsigned char)XGINew_GetReg1(pVBInfo->P3d4, 0x11);
+     data &= 0x7F ;
+     XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , data ) ;		/* Unlock CRTC */
+     XGINew_SetReg1(pVBInfo->P3d4, 0x01, (unsigned short)(tempcx & 0xff));
+@@ -1998,7 +2003,7 @@ void XGI_SetCRT1DE(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+         tempax |= 0x40 ;
+ 
+     XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x42 , tempax ) ;
+-    data =( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x07 ) ;
++    data = (unsigned char)XGINew_GetReg1(pVBInfo->P3d4, 0x07);
+     data &= 0xFF ;
+     tempax = 0 ;
+ 
+@@ -2105,7 +2110,7 @@ void XGI_SetCRT1Offset(unsigned short ModeNo,
+     i |= temp ;
+     XGINew_SetReg1( pVBInfo->P3c4 , 0x0E , i ) ;
+ 
+-    temp =( UCHAR )temp2 ;
++    temp = (unsigned char)temp2;
+     temp &= 0xFF ;		/* al */
+     XGINew_SetReg1( pVBInfo->P3d4 , 0x13 , temp ) ;
+ 
+@@ -2142,7 +2147,7 @@ void XGI_SetCRT1VCLK(unsigned short ModeNo, unsigned short ModeIdIndex,
+ 		     unsigned short RefreshRateTableIndex,
+ 		     PVB_DEVICE_INFO pVBInfo)
+ {
+-    UCHAR index , data ;
++	unsigned char index, data;
+     unsigned short vclkindex ;
+ 
+     if ( pVBInfo->IF_DEF_LVDS == 1 )
+@@ -2398,9 +2403,9 @@ void XGI_SetVCLKState(PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ {
+     unsigned short data ,
+            data2 = 0 ;
+-    SHORT  VCLK ;
++    short VCLK ;
+ 
+-    UCHAR  index ;
++    unsigned char index;
+ 
+     if ( ModeNo <= 0x13 )
+         VCLK = 0 ;
+@@ -2817,7 +2822,7 @@ void XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex,
+ 		     PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ 		     PVB_DEVICE_INFO pVBInfo)
+ {
+-    UCHAR index ;
++    unsigned char index;
+     unsigned short tempbx , i ;
+     XGI_LVDSCRT1HDataStruct  *LCDPtr = NULL ;
+     XGI_LVDSCRT1VDataStruct  *LCDPtr1 =NULL ;
+@@ -3184,7 +3189,7 @@ void XGI_SetLVDSRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
+ /* --------------------------------------------------------------------- */
+ void XGI_SetCRT2ECLK(unsigned short ModeNo , unsigned short ModeIdIndex , unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO  pVBInfo )
+ {
+-    UCHAR di_0 , di_1 , tempal ;
++    unsigned char di_0, di_1, tempal;
+     int i ;
+ 
+     tempal = XGI_GetVCLKPtr( RefreshRateTableIndex , ModeNo , ModeIdIndex, pVBInfo ) ;
+@@ -3788,7 +3793,8 @@ void XGI_GetTVInfo(unsigned short ModeNo , unsigned short ModeIdIndex ,PVB_DEVIC
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGI_GetLCDInfo(unsigned short ModeNo , unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
++unsigned char XGI_GetLCDInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
++			     PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short temp ,
+            tempax ,
+@@ -3997,7 +4003,9 @@ unsigned char XGI_GetLCDInfo(unsigned short ModeNo , unsigned short ModeIdIndex,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGI_SearchModeID(unsigned short ModeNo , unsigned short *ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
++unsigned char XGI_SearchModeID(unsigned short ModeNo,
++			       unsigned short *ModeIdIndex,
++			       PVB_DEVICE_INFO pVBInfo)
+ {
+ 
+ 
+@@ -4052,7 +4060,10 @@ unsigned char XGI_SearchModeID(unsigned short ModeNo , unsigned short *ModeIdInd
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGINew_CheckMemorySize(PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex,PVB_DEVICE_INFO pVBInfo)
++unsigned char XGINew_CheckMemorySize(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++				     unsigned short ModeNo,
++				     unsigned short ModeIdIndex,
++				     PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short memorysize ,
+            modeflag ,
+@@ -4134,7 +4145,7 @@ unsigned char XGINew_CheckMemorySize(PXGI_HW_DEVICE_INFO HwDeviceExtension, unsi
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-/*void XGINew_IsLowResolution(unsigned short ModeNo , unsigned short ModeIdIndex, unsigned char XGINew_CheckMemorySize(PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex,PVB_DEVICE_INFO pVBInfo)
++/*void XGINew_IsLowResolution(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned char XGINew_CheckMemorySize(PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex,PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short data ;
+     unsigned short ModeFlag ;
+@@ -4296,40 +4307,41 @@ void XGI_WaitDisply( PVB_DEVICE_INFO pVBInfo )
+ 
+ void XGI_SenseCRT1( PVB_DEVICE_INFO pVBInfo )
+ {
+-    UCHAR CRTCData[ 17 ] = { 0x5F , 0x4F , 0x50 , 0x82 , 0x55 , 0x81 ,
+-                             0x0B , 0x3E , 0xE9 , 0x0B , 0xDF , 0xE7 ,
+-                             0x04 , 0x00 , 0x00 , 0x05 , 0x00 } ;
++	unsigned char CRTCData[17] = {
++		0x5F , 0x4F , 0x50 , 0x82 , 0x55 , 0x81 ,
++		0x0B , 0x3E , 0xE9 , 0x0B , 0xDF , 0xE7 ,
++		0x04 , 0x00 , 0x00 , 0x05 , 0x00 };
+ 
+-    UCHAR SR01 = 0 , SR1F = 0 , SR07 = 0 , SR06 = 0 ;
++	unsigned char SR01 = 0, SR1F = 0, SR07 = 0, SR06 = 0;
+ 
+-    UCHAR CR17 , CR63 , SR31 ;
+-    unsigned short temp ;
+-    UCHAR DAC_TEST_PARMS[ 3 ] = { 0x0F , 0x0F , 0x0F } ;
++	unsigned char CR17, CR63, SR31;
++	unsigned short temp ;
++	unsigned char DAC_TEST_PARMS[3] = { 0x0F, 0x0F, 0x0F } ;
+ 
+     int i ;
+     XGINew_SetReg1( pVBInfo->P3c4 , 0x05 , 0x86 ) ;
+ 
+     /* [2004/05/06] Vicent to fix XG42 single LCD sense to CRT+LCD */
+     XGINew_SetReg1( pVBInfo->P3d4 , 0x57 , 0x4A ) ;
+-    XGINew_SetReg1( pVBInfo->P3d4 , 0x53 , ( UCHAR )( XGINew_GetReg1( pVBInfo->P3d4 , 0x53 ) | 0x02 ) ) ;
++    XGINew_SetReg1(pVBInfo->P3d4, 0x53, (unsigned char)(XGINew_GetReg1(pVBInfo->P3d4, 0x53) | 0x02));
+ 
+-    SR31 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x31 ) ;
+-    CR63 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x63 ) ;
+-    SR01 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x01 ) ;
++    SR31 = (unsigned char)XGINew_GetReg1(pVBInfo->P3c4, 0x31);
++    CR63 = (unsigned char)XGINew_GetReg1(pVBInfo->P3d4, 0x63);
++    SR01 = (unsigned char)XGINew_GetReg1(pVBInfo->P3c4, 0x01);
+ 
+-    XGINew_SetReg1( pVBInfo->P3c4 , 0x01 , ( UCHAR )( SR01 & 0xDF ) ) ;
+-    XGINew_SetReg1( pVBInfo->P3d4 , 0x63 , ( UCHAR )( CR63 & 0xBF ) ) ;
++    XGINew_SetReg1(pVBInfo->P3c4, 0x01, (unsigned char)(SR01 & 0xDF));
++    XGINew_SetReg1(pVBInfo->P3d4, 0x63, (unsigned char)(CR63 & 0xBF));
+ 
+-    CR17 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x17 ) ;
+-    XGINew_SetReg1( pVBInfo->P3d4 , 0x17 , ( UCHAR )( CR17 | 0x80 ) ) ;
++    CR17 = (unsigned char)XGINew_GetReg1(pVBInfo->P3d4, 0x17);
++    XGINew_SetReg1(pVBInfo->P3d4, 0x17, (unsigned char)(CR17 | 0x80)) ;
+ 
+-    SR1F = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x1F ) ;
+-    XGINew_SetReg1( pVBInfo->P3c4 , 0x1F , ( UCHAR )( SR1F | 0x04 ) ) ;
++    SR1F = (unsigned char)XGINew_GetReg1(pVBInfo->P3c4, 0x1F);
++    XGINew_SetReg1(pVBInfo->P3c4, 0x1F, (unsigned char)(SR1F | 0x04));
+ 
+-    SR07 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x07 ) ;
+-    XGINew_SetReg1( pVBInfo->P3c4 , 0x07 , ( UCHAR )( SR07 & 0xFB ) ) ;
+-    SR06 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x06 ) ;
+-    XGINew_SetReg1( pVBInfo->P3c4 , 0x06 , ( UCHAR )( SR06 & 0xC3 ) ) ;
++    SR07 = (unsigned char)XGINew_GetReg1(pVBInfo->P3c4, 0x07);
++    XGINew_SetReg1(pVBInfo->P3c4, 0x07, (unsigned char)(SR07 & 0xFB));
++    SR06 = (unsigned char)XGINew_GetReg1(pVBInfo->P3c4, 0x06);
++    XGINew_SetReg1(pVBInfo->P3c4, 0x06, (unsigned char)(SR06 & 0xC3));
+ 
+     XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , 0x00 ) ;
+ 
+@@ -4345,7 +4357,7 @@ void XGI_SenseCRT1( PVB_DEVICE_INFO pVBInfo )
+     for( i = 13 ; i < 16 ; i++ )
+ 	    XGINew_SetReg1(pVBInfo->P3c4, (unsigned short)(i - 3), CRTCData[i]);
+ 
+-    XGINew_SetReg1(pVBInfo->P3c4, 0x0E, (UCHAR)(CRTCData[16] & 0xE0));
++    XGINew_SetReg1(pVBInfo->P3c4, 0x0E, (unsigned char)(CRTCData[16] & 0xE0));
+ 
+     XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , 0x00 ) ;
+     XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , 0x1B ) ;
+@@ -4355,9 +4367,9 @@ void XGI_SenseCRT1( PVB_DEVICE_INFO pVBInfo )
+ 
+     for( i = 0 ; i < 256 ; i++ )
+     {
+-        XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , ( UCHAR )DAC_TEST_PARMS[ 0 ] ) ;
+-        XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , ( UCHAR )DAC_TEST_PARMS[ 1 ] ) ;
+-        XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , ( UCHAR )DAC_TEST_PARMS[ 2 ] ) ;
++	XGINew_SetReg3((pVBInfo->P3c8 + 1), (unsigned char)DAC_TEST_PARMS[0]);
++	XGINew_SetReg3((pVBInfo->P3c8 + 1), (unsigned char)DAC_TEST_PARMS[1]);
++	XGINew_SetReg3((pVBInfo->P3c8 + 1), (unsigned char)DAC_TEST_PARMS[2]);
+     }
+ 
+     XGI_VBLongWait( pVBInfo ) ;
+@@ -4393,8 +4405,9 @@ void XGI_SenseCRT1( PVB_DEVICE_INFO pVBInfo )
+     XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , SR31 ) ;
+ 
+     /* [2004/05/11] Vicent */
+-    XGINew_SetReg1( pVBInfo->P3d4 , 0x53 , ( UCHAR )( XGINew_GetReg1( pVBInfo->P3d4 , 0x53 ) & 0xFD ) ) ;
+-    XGINew_SetReg1( pVBInfo->P3c4 , 0x1F , ( UCHAR ) SR1F ) ;
++    XGINew_SetReg1(pVBInfo->P3d4, 0x53,
++		   (unsigned char)(XGINew_GetReg1(pVBInfo->P3d4, 0x53) & 0xFD));
++    XGINew_SetReg1(pVBInfo->P3c4, 0x1F, (unsigned char)SR1F);
+ }
+ 
+ 
+@@ -4428,7 +4441,9 @@ void XGI_WaitDisplay( PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGI_SetCRT2Group301(unsigned short ModeNo , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
++unsigned char XGI_SetCRT2Group301(unsigned short ModeNo,
++				  PXGI_HW_DEVICE_INFO HwDeviceExtension,
++				  PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short tempbx ,
+            ModeIdIndex ,
+@@ -4593,7 +4608,7 @@ void XGI_GetCRT2ResInfo(unsigned short ModeNo,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGI_IsLCDDualLink( PVB_DEVICE_INFO pVBInfo )
++unsigned char XGI_IsLCDDualLink(PVB_DEVICE_INFO pVBInfo)
+ {
+ 
+     if ( ( ( ( pVBInfo->VBInfo & SetCRT2ToLCD ) | SetCRT2ToLCDA ) ) && ( pVBInfo->LCDInfo & SetLCDDualLink ) ) /* shampoo0129 */
+@@ -4837,9 +4852,7 @@ void XGI_GetCRT2Data(  unsigned short ModeNo , unsigned short ModeIdIndex , unsi
+ /* --------------------------------------------------------------------- */
+ void XGI_SetCRT2VCLK(unsigned short ModeNo , unsigned short ModeIdIndex , unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+ {
+-    UCHAR di_0 ,
+-          di_1 ,
+-          tempal ;
++	unsigned char di_0, di_1, tempal;
+ 
+     tempal = XGI_GetVCLKPtr( RefreshRateTableIndex , ModeNo , ModeIdIndex, pVBInfo ) ;
+     XGI_GetVCLKLen( tempal, &di_0 , &di_1, pVBInfo ) ;
+@@ -4872,7 +4885,8 @@ void XGI_SetCRT2VCLK(unsigned short ModeNo , unsigned short ModeIdIndex , unsign
+ /* Output : al -> VCLK Index */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_GetLCDVCLKPtr( UCHAR* di_0 , UCHAR *di_1, PVB_DEVICE_INFO pVBInfo )
++void XGI_GetLCDVCLKPtr(unsigned char *di_0, unsigned char *di_1,
++		       PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short index ;
+ 
+@@ -4908,14 +4922,16 @@ void XGI_GetLCDVCLKPtr( UCHAR* di_0 , UCHAR *di_1, PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-UCHAR XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex, unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
++unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex,
++			     unsigned short ModeNo, unsigned short ModeIdIndex,
++			     PVB_DEVICE_INFO pVBInfo)
+ {
+ 
+     unsigned short index ,
+            modeflag ;
+     unsigned short tempbx ;
+-    UCHAR tempal ;
+-    UCHAR *CHTVVCLKPtr = NULL ;
++    unsigned char tempal;
++    unsigned char *CHTVVCLKPtr = NULL;
+ 
+     if ( ModeNo <= 0x13 )
+         modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;      /* si+St_ResInfo */
+@@ -5067,7 +5083,7 @@ UCHAR XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex, unsigned short ModeNo
+ 
+     }
+ 
+-    tempal = ( UCHAR )XGINew_GetReg2( ( pVBInfo->P3ca + 0x02 ) ) ;
++    tempal = (unsigned char)XGINew_GetReg2((pVBInfo->P3ca + 0x02));
+     tempal = tempal >> 2 ;
+     tempal &= 0x03 ;
+ 
+@@ -5088,19 +5104,20 @@ UCHAR XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex, unsigned short ModeNo
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_GetVCLKLen(UCHAR tempal,UCHAR* di_0,UCHAR* di_1, PVB_DEVICE_INFO pVBInfo)
++void XGI_GetVCLKLen(unsigned char tempal, unsigned char *di_0,
++		    unsigned char *di_1, PVB_DEVICE_INFO pVBInfo)
+ {
+     if ( pVBInfo->IF_DEF_CH7007 == 1 ) /* [Billy] 2007/05/16 */
+     {
+        /* VideoDebugPrint((0, "XGI_GetVCLKLen: pVBInfo->IF_DEF_CH7007==1\n")); */
+-        *di_0 = ( UCHAR )XGI_CH7007VCLKData[ tempal ].SR2B ;
+-        *di_1 = ( UCHAR )XGI_CH7007VCLKData[ tempal ].SR2C ;
++	*di_0 = (unsigned char)XGI_CH7007VCLKData[tempal].SR2B;
++	*di_1 = (unsigned char)XGI_CH7007VCLKData[tempal].SR2C;
+     }
+     else if ( pVBInfo->VBType & ( VB_XGI301 | VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+     {
+         if ( ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) ) && ( pVBInfo->SetFlag & ProgrammingCRT2 ) )
+         {
+-            *di_0 = ( UCHAR )XGI_VBVCLKData[ tempal ].SR2B ;
++	    *di_0 = (unsigned char)XGI_VBVCLKData[tempal].SR2B;
+             *di_1 = XGI_VBVCLKData[ tempal ].SR2C ;
+         }
+     }
+@@ -5118,11 +5135,14 @@ void XGI_GetVCLKLen(UCHAR tempal,UCHAR* di_0,UCHAR* di_1, PVB_DEVICE_INFO pVBInf
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetCRT2Offset(unsigned short ModeNo ,
+-				   unsigned short ModeIdIndex , unsigned short RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
++void XGI_SetCRT2Offset(unsigned short ModeNo,
++		       unsigned short ModeIdIndex,
++		       unsigned short RefreshRateTableIndex,
++		       PXGI_HW_DEVICE_INFO HwDeviceExtension,
++		       PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short offset ;
+-    UCHAR temp ;
++    unsigned char temp;
+ 
+     if ( pVBInfo->VBInfo & SetInSlaveMode )
+     {
+@@ -5130,12 +5150,12 @@ void XGI_SetCRT2Offset(unsigned short ModeNo ,
+     }
+ 
+     offset = XGI_GetOffset(  ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ;
+-    temp = ( UCHAR )( offset & 0xFF ) ;
++    temp = (unsigned char)(offset & 0xFF);
+     XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , temp ) ;
+-    temp =( UCHAR)( ( offset & 0xFF00 ) >> 8 ) ;
+-    XGINew_SetReg1( pVBInfo->Part1Port , 0x09 , temp ) ;
+-    temp =( UCHAR )( ( ( offset >> 3 ) & 0xFF ) + 1 ) ;
+-    XGINew_SetReg1( pVBInfo->Part1Port , 0x03 , temp ) ;
++    temp = (unsigned char)((offset & 0xFF00) >> 8);
++    XGINew_SetReg1(pVBInfo->Part1Port , 0x09 , temp);
++    temp = (unsigned char)(((offset >> 3) & 0xFF) + 1) ;
++    XGINew_SetReg1(pVBInfo->Part1Port, 0x03, temp);
+ }
+ 
+ 
+@@ -5884,7 +5904,7 @@ void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned s
+            modeflag ,
+            resinfo ,
+            crt2crtc ;
+-    UCHAR *TimingPoint ;
++    unsigned char *TimingPoint ;
+ 
+     unsigned long longtemp ,
+           tempeax ,
+@@ -6360,7 +6380,7 @@ void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned s
+ 
+     if ( pVBInfo->TVInfo & SetPALMTV )
+     {
+-        tempax = ( UCHAR )XGINew_GetReg1( pVBInfo->Part2Port , 0x01 ) ;
++	tempax = (unsigned char)XGINew_GetReg1(pVBInfo->Part2Port, 0x01);
+         tempax-- ;
+         XGINew_SetRegAND( pVBInfo->Part2Port , 0x01 , tempax ) ;
+ 
+@@ -6745,7 +6765,7 @@ void XGI_SetTap4Regs( PVB_DEVICE_INFO pVBInfo)
+ void XGI_SetGroup3(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short i;
+-    UCHAR *tempdi;
++    unsigned char *tempdi;
+     unsigned short  modeflag;
+ 
+     if(ModeNo<=0x13)
+@@ -7781,9 +7801,9 @@ void *XGI_GetTVPtr(unsigned short BX, unsigned short ModeNo,
+ /* --------------------------------------------------------------------- */
+ unsigned char XGI_BacklightByDrv(PVB_DEVICE_INFO pVBInfo)
+ {
+-    UCHAR tempah ;
++    unsigned char tempah ;
+ 
+-    tempah = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x3A ) ;
++    tempah = (unsigned char)XGINew_GetReg1(pVBInfo->P3d4, 0x3A) ;
+     if (tempah & BacklightControlBit)
+ 	    return 1;
+     else
+@@ -7889,10 +7909,10 @@ void XGI_SetPanelPower(unsigned short tempah, unsigned short tempbl, PVB_DEVICE_
+         XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x11 , tempbl , tempah ) ;
+ }
+ 
+-UCHAR XG21GPIODataTransfer(UCHAR ujDate)
++unsigned char XG21GPIODataTransfer(unsigned char ujDate)
+ {
+-    UCHAR  ujRet = 0;
+-    UCHAR  i = 0;
++    unsigned char  ujRet = 0;
++    unsigned char  i = 0;
+ 
+     for (i=0; i<8; i++)
+ 	{
+@@ -7910,9 +7930,9 @@ UCHAR XG21GPIODataTransfer(UCHAR ujDate)
+ /*      bl[1] : LVDS backlight                                                */
+ /*      bl[0] : LVDS VDD                                                      */
+ /*----------------------------------------------------------------------------*/
+-UCHAR XGI_XG21GetPSCValue(PVB_DEVICE_INFO pVBInfo)
++unsigned char XGI_XG21GetPSCValue(PVB_DEVICE_INFO pVBInfo)
+ {
+-    UCHAR CR4A,temp;
++    unsigned char CR4A, temp;
+ 
+     CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
+     XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x23 ) ; /* enable GPIO write */
+@@ -7931,9 +7951,9 @@ UCHAR XGI_XG21GetPSCValue(PVB_DEVICE_INFO pVBInfo)
+ /*      bl[1] : LVDS backlight                                                */
+ /*      bl[0] : LVDS VDD                                                      */
+ /*----------------------------------------------------------------------------*/
+-UCHAR XGI_XG27GetPSCValue(PVB_DEVICE_INFO pVBInfo)
++unsigned char XGI_XG27GetPSCValue(PVB_DEVICE_INFO pVBInfo)
+ {
+-    UCHAR CR4A,CRB4,temp;
++    unsigned char CR4A, CRB4, temp;
+ 
+     CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
+     XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x0C ) ; /* enable GPIO write */
+@@ -7958,7 +7978,7 @@ UCHAR XGI_XG27GetPSCValue(PVB_DEVICE_INFO pVBInfo)
+ /*----------------------------------------------------------------------------*/
+ void XGI_XG21BLSignalVDD(unsigned short tempbh, unsigned short tempbl, PVB_DEVICE_INFO pVBInfo)
+ {
+-    UCHAR CR4A,temp;
++    unsigned char CR4A, temp;
+ 
+     CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
+     tempbh &= 0x23;
+@@ -7983,7 +8003,7 @@ void XGI_XG21BLSignalVDD(unsigned short tempbh, unsigned short tempbl, PVB_DEVIC
+ 
+ void XGI_XG27BLSignalVDD(unsigned short tempbh, unsigned short tempbl, PVB_DEVICE_INFO pVBInfo)
+ {
+-    UCHAR CR4A,temp;
++    unsigned char CR4A, temp;
+     unsigned short tempbh0, tempbl0;
+ 
+     tempbh0 = tempbh;
+@@ -8118,7 +8138,7 @@ unsigned char XGI_XG21CheckLVDSMode(unsigned short ModeNo,
+ 
+ void XGI_SetXG21FPBits(PVB_DEVICE_INFO pVBInfo)
+ {
+-    UCHAR temp;
++    unsigned char temp;
+ 
+     temp = XGINew_GetReg1( pVBInfo->P3d4  , 0x37 ) ;  /* D[0] 1: 18bit */
+     temp = ( temp & 1 ) << 6;
+@@ -8129,7 +8149,7 @@ void XGI_SetXG21FPBits(PVB_DEVICE_INFO pVBInfo)
+ 
+ void XGI_SetXG27FPBits(PVB_DEVICE_INFO pVBInfo)
+ {
+-    UCHAR temp;
++    unsigned char temp;
+ 
+     temp = XGINew_GetReg1( pVBInfo->P3d4  , 0x37 ) ;  /* D[1:0] 01: 18bit, 00: dual 12, 10: single 24 */
+     temp = ( temp & 3 ) << 6;
+@@ -8141,7 +8161,7 @@ void XGI_SetXG27FPBits(PVB_DEVICE_INFO pVBInfo)
+ void XGI_SetXG21LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex,
+ 			 PVB_DEVICE_INFO pVBInfo)
+ {
+-    UCHAR temp,Miscdata;
++    unsigned char temp, Miscdata;
+     unsigned short xres ,
+            yres ,
+            modeflag ,
+@@ -8153,13 +8173,13 @@ void XGI_SetXG21LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex,
+ 
+     lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo );
+ 
+-    temp = (UCHAR) ( ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability & (LCDPolarity << 8 ) ) >> 8 );
++    temp = (unsigned char) ((pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability & (LCDPolarity << 8)) >> 8);
+     temp &= LCDPolarity;
+-    Miscdata =(UCHAR) XGINew_GetReg2(pVBInfo->P3cc) ;
++    Miscdata = (unsigned char) XGINew_GetReg2(pVBInfo->P3cc) ;
+ 
+     XGINew_SetReg3( pVBInfo->P3c2 , (Miscdata & 0x3F) | temp ) ;
+ 
+-    temp = (UCHAR) ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability & LCDPolarity ) ;
++    temp = (unsigned char) (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability & LCDPolarity) ;
+     XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x80 , temp&0x80 ) ;      /* SR35[7] FP VSync polarity */
+     XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x30 , ~0x20 , (temp&0x40)>>1 ) ;   /* SR30[5] FP HSync polarity */
+ 
+@@ -8215,7 +8235,7 @@ void XGI_SetXG21LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex,
+ 
+     LVDSVBE = LVDSVBS + LVDSVT - pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE ;
+ 
+-    temp = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;
++    temp = (unsigned char)XGINew_GetReg1(pVBInfo->P3d4, 0x11) ;
+     XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , temp & 0x7f ) ;		/* Unlock CRTC */
+ 
+     if (!( modeflag & Charx8Dot ))
+@@ -8325,7 +8345,7 @@ void XGI_SetXG21LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex,
+ void XGI_SetXG27LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex,
+ 			 PVB_DEVICE_INFO pVBInfo)
+ {
+-    UCHAR temp,Miscdata;
++    unsigned char temp, Miscdata;
+     unsigned short xres ,
+            yres ,
+            modeflag ,
+@@ -8336,13 +8356,13 @@ void XGI_SetXG27LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex,
+     unsigned short value;
+ 
+     lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo );
+-    temp = (UCHAR) ( ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability & (LCDPolarity << 8 ) ) >> 8 );
++    temp = (unsigned char) ((pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability & (LCDPolarity << 8)) >> 8);
+     temp &= LCDPolarity;
+-    Miscdata =(UCHAR) XGINew_GetReg2(pVBInfo->P3cc) ;
++    Miscdata = (unsigned char) XGINew_GetReg2(pVBInfo->P3cc);
+ 
+     XGINew_SetReg3( pVBInfo->P3c2 , (Miscdata & 0x3F) | temp ) ;
+ 
+-    temp = (UCHAR) ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability & LCDPolarity ) ;
++    temp = (unsigned char) (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability & LCDPolarity) ;
+     XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x80 , temp&0x80 ) ;      /* SR35[7] FP VSync polarity */
+     XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x30 , ~0x20 , (temp&0x40)>>1 ) ;   /* SR30[5] FP HSync polarity */
+ 
+@@ -8398,7 +8418,7 @@ void XGI_SetXG27LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex,
+ 
+     LVDSVBE = LVDSVBS + LVDSVT - pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE ;
+ 
+-    temp = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;
++    temp = (unsigned char)XGINew_GetReg1(pVBInfo->P3d4, 0x11) ;
+     XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , temp & 0x7f ) ;		/* Unlock CRTC */
+ 
+     if (!( modeflag & Charx8Dot ))
+@@ -8627,7 +8647,7 @@ unsigned char XGI_EnableChISLCD(PVB_DEVICE_INFO pVBInfo)
+ /* --------------------------------------------------------------------- */
+ unsigned short XGI_GetLCDCapPtr(PVB_DEVICE_INFO pVBInfo)
+ {
+-    UCHAR tempal ,
++    unsigned char tempal ,
+           tempah ,
+           tempbl ,
+           i ;
+@@ -8800,7 +8820,7 @@ void XGI_EnableBridge( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO p
+         {
+             if ( ( pVBInfo->SetFlag & EnableChB ) || ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToTV | SetCRT2ToRAMDAC ) ) )
+             {
+-                tempah = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x32 ) ;
++		tempah = (unsigned char)XGINew_GetReg1(pVBInfo->P3c4, 0x32);
+                 tempah &= 0xDF;
+                 if ( pVBInfo->VBInfo & SetInSlaveMode )
+                 {
+@@ -8810,8 +8830,7 @@ void XGI_EnableBridge( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO p
+                 XGINew_SetReg1( pVBInfo->P3c4 , 0x32 , tempah ) ;
+                 XGINew_SetRegOR( pVBInfo->P3c4 , 0x1E , 0x20 ) ;
+ 
+-
+-                tempah = ( UCHAR )XGINew_GetReg1( pVBInfo->Part1Port , 0x2E ) ;
++		tempah = (unsigned char)XGINew_GetReg1(pVBInfo->Part1Port, 0x2E);
+ 
+                 if ( !( tempah & 0x80 ) )
+                     XGINew_SetRegOR( pVBInfo->Part1Port , 0x2E , 0x80 ) ;   	/* BVBDOENABLE = 1 */
+@@ -8892,7 +8911,7 @@ void XGI_EnableBridge( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO p
+ 
+ 
+ 
+-        tempah = ( UCHAR )XGINew_GetReg1( pVBInfo->Part1Port , 0x2E ) ;
++	tempah = (unsigned char)XGINew_GetReg1(pVBInfo->Part1Port, 0x2E);
+         if ( !( tempah & 0x80 ) )
+             XGINew_SetRegOR( pVBInfo->Part1Port , 0x2E , 0x80 ) ;	/* BVBDOENABLE = 1 */
+ 
+@@ -9185,7 +9204,7 @@ void XGI_SetDelayComp( PVB_DEVICE_INFO pVBInfo )
+ {
+     unsigned short index ;
+ 
+-    UCHAR  tempah ,
++    unsigned char  tempah ,
+            tempbl ,
+            tempbh ;
+ 
+@@ -9270,7 +9289,7 @@ void XGI_SetLCDCap( PVB_DEVICE_INFO pVBInfo )
+         if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+         {        				/* 301LV/302LV only */
+             /* Set 301LV Capability */
+-		XGINew_SetReg1(pVBInfo->Part4Port, 0x24, (UCHAR)(tempcx & 0x1F));
++		XGINew_SetReg1(pVBInfo->Part4Port, 0x24, (unsigned char)(tempcx & 0x1F));
+ 	}
+         /* VB Driving */
+ 	XGINew_SetRegANDOR(pVBInfo->Part4Port, 0x0D,
+@@ -9391,7 +9410,7 @@ void XGI_SetAntiFlicker(unsigned short ModeNo, unsigned short ModeIdIndex,
+     unsigned short tempbx ,
+            index ;
+ 
+-    UCHAR tempah ;
++    unsigned char tempah ;
+ 
+     if (pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) )
+         return ;
+@@ -9427,7 +9446,7 @@ void XGI_SetEdgeEnhance(unsigned short ModeNo , unsigned short ModeIdIndex , PVB
+     unsigned short tempbx ,
+            index ;
+ 
+-    UCHAR tempah ;
++    unsigned char tempah ;
+ 
+ 
+     tempbx = XGI_GetTVPtrIndex(pVBInfo ) ;
+@@ -9460,7 +9479,7 @@ void XGI_SetPhaseIncr( PVB_DEVICE_INFO pVBInfo )
+ {
+     unsigned short tempbx ;
+ 
+-    UCHAR tempcl ,
++    unsigned char tempcl ,
+           tempch ;
+ 
+     unsigned long tempData ;
+@@ -9491,7 +9510,7 @@ void XGI_SetYFilter(unsigned short ModeNo, unsigned short ModeIdIndex,
+     unsigned short tempbx ,
+            index ;
+ 
+-    UCHAR tempcl ,
++    unsigned char tempcl ,
+           tempch ,
+           tempal ,
+           *filterPtr ;
+@@ -9590,7 +9609,8 @@ void XGI_SetYFilter(unsigned short ModeNo, unsigned short ModeIdIndex,
+ /* 1 : 301B/302B/301LV/302LV */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_GetTVPtrIndex2(unsigned short *tempbx,UCHAR* tempcl,UCHAR* tempch, PVB_DEVICE_INFO pVBInfo)
++void XGI_GetTVPtrIndex2(unsigned short *tempbx, unsigned char *tempcl,
++			unsigned char *tempch, PVB_DEVICE_INFO pVBInfo)
+ {
+     *tempbx = 0 ;
+     *tempcl = 0 ;
+@@ -9637,9 +9657,9 @@ void XGI_SetCRT2ModeRegs(unsigned short ModeNo,
+ 			 PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short tempbl ;
+-    SHORT  tempcl ;
++    short  tempcl ;
+ 
+-    UCHAR  tempah ;
++    unsigned char  tempah ;
+ 
+     /* XGINew_SetReg1( pVBInfo->Part1Port , 0x03 , 0x00 ) ; // fix write part1 index 0 BTDRAM bit Bug */
+     tempah=0;
+@@ -9966,7 +9986,7 @@ void XGI_GetRAMDAC2DATA(unsigned short ModeNo , unsigned short ModeIdIndex , uns
+ unsigned short XGI_GetColorDepth(unsigned short ModeNo , unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short ColorDepth[ 6 ] = { 1 , 2 , 4 , 4 , 6 , 8 } ;
+-    SHORT  index ;
++    short index ;
+     unsigned short modeflag ;
+ 
+     if ( ModeNo <= 0x13 )
+@@ -10036,7 +10056,7 @@ void XGINew_EnableCRT2( PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_LCD_Wait_Time(UCHAR DelayTime, PVB_DEVICE_INFO pVBInfo)
++void XGINew_LCD_Wait_Time(unsigned char DelayTime, PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short i ,
+            j ;
+@@ -10073,7 +10093,7 @@ void XGINew_LCD_Wait_Time(UCHAR DelayTime, PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-unsigned char XGI_BridgeIsOn( PVB_DEVICE_INFO pVBInfo )
++unsigned char XGI_BridgeIsOn(PVB_DEVICE_INFO pVBInfo)
+ {
+     unsigned short flag ;
+ 
+@@ -10218,7 +10238,7 @@ unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo , unsigned short ModeIdInde
+ 
+     unsigned short CRT2Index , VCLKIndex ;
+     unsigned short modeflag , resinfo ;
+-    UCHAR *CHTVVCLKPtr = NULL ;
++    unsigned char *CHTVVCLKPtr = NULL ;
+ 
+     if ( ModeNo <= 0x13 )
+     {
+@@ -10333,7 +10353,7 @@ unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo , unsigned short ModeIdInde
+             }
+             else
+             {	/* for CRT2 */
+-                VCLKIndex = ( UCHAR )XGINew_GetReg2( ( pVBInfo->P3ca + 0x02 ) ) ;	/* Port 3cch */
++		VCLKIndex = (unsigned char)XGINew_GetReg2((pVBInfo->P3ca + 0x02));	/* Port 3cch */
+ 		VCLKIndex = ( ( VCLKIndex >> 2 ) & 0x03 ) ;
+                 if ( ModeNo > 0x13 )
+                 {
+diff --git a/drivers/staging/xgifb/vb_setmode.h b/drivers/staging/xgifb/vb_setmode.h
+index 67a56b9d4c14..1c37f809dadb 100644
+--- a/drivers/staging/xgifb/vb_setmode.h
++++ b/drivers/staging/xgifb/vb_setmode.h
+@@ -1,7 +1,7 @@
+ #ifndef  _VBSETMODE_
+ #define  _VBSETMODE_
+ 
+-extern   void     InitTo330Pointer(UCHAR,PVB_DEVICE_INFO);
++extern   void     InitTo330Pointer(unsigned char, PVB_DEVICE_INFO);
+ extern   void     XGI_UnLockCRT2(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+ extern   void     XGI_LockCRT2(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+ extern   void     XGI_LongWait( PVB_DEVICE_INFO );
+diff --git a/drivers/staging/xgifb/vb_struct.h b/drivers/staging/xgifb/vb_struct.h
+index c0498d87327b..1d401c04de8e 100644
+--- a/drivers/staging/xgifb/vb_struct.h
++++ b/drivers/staging/xgifb/vb_struct.h
+@@ -12,7 +12,7 @@
+ 
+ typedef struct _XGI_PanelDelayTblStruct
+ {
+- UCHAR timer[2];
++ unsigned char timer[2];
+ } XGI_PanelDelayTblStruct;
+ 
+ typedef struct _XGI_LCDDataStruct
+@@ -28,11 +28,11 @@ typedef struct _XGI_LCDDataStruct
+ 
+ typedef struct _XGI_LVDSCRT1HDataStruct
+ {
+- UCHAR Reg[8];
++ unsigned char Reg[8];
+ } XGI_LVDSCRT1HDataStruct;
+ typedef struct _XGI_LVDSCRT1VDataStruct
+ {
+- UCHAR Reg[7];
++ unsigned char Reg[7];
+ } XGI_LVDSCRT1VDataStruct;
+ 
+ 
+@@ -45,12 +45,12 @@ typedef struct _XGI_TVDataStruct
+  unsigned short TVHDE;
+  unsigned short TVVDE;
+  unsigned short RVBHRS;
+- UCHAR FlickerMode;
++ unsigned char FlickerMode;
+  unsigned short HALFRVBHRS;
+- UCHAR RY1COE;
+- UCHAR RY2COE;
+- UCHAR RY3COE;
+- UCHAR RY4COE;
++ unsigned char RY1COE;
++ unsigned char RY2COE;
++ unsigned char RY3COE;
++ unsigned char RY4COE;
+ } XGI_TVDataStruct;
+ 
+ typedef struct _XGI_LVDSDataStruct
+@@ -69,7 +69,7 @@ typedef struct _XGI_LVDSDesStruct
+ 
+ typedef struct _XGI_LVDSCRT1DataStruct
+ {
+- UCHAR CR[15];
++ unsigned char CR[15];
+ } XGI_LVDSCRT1DataStruct;
+ 
+ /*add for LCDA*/
+@@ -77,53 +77,53 @@ typedef struct _XGI_LVDSCRT1DataStruct
+ 
+ typedef struct _XGI_StStruct
+ {
+- UCHAR St_ModeID;
++ unsigned char St_ModeID;
+  unsigned short St_ModeFlag;
+- UCHAR St_StTableIndex;
+- UCHAR St_CRT2CRTC;
+- UCHAR St_CRT2CRTC2;
+- UCHAR St_ResInfo;
+- UCHAR VB_StTVFlickerIndex;
+- UCHAR VB_StTVEdgeIndex;
+- UCHAR VB_StTVYFilterIndex;
++ unsigned char St_StTableIndex;
++ unsigned char St_CRT2CRTC;
++ unsigned char St_CRT2CRTC2;
++ unsigned char St_ResInfo;
++ unsigned char VB_StTVFlickerIndex;
++ unsigned char VB_StTVEdgeIndex;
++ unsigned char VB_StTVYFilterIndex;
+ } XGI_StStruct;
+ 
+ typedef struct _XGI_StandTableStruct
+ {
+- UCHAR CRT_COLS;
+- UCHAR ROWS;
+- UCHAR CHAR_HEIGHT;
++ unsigned char CRT_COLS;
++ unsigned char ROWS;
++ unsigned char CHAR_HEIGHT;
+  unsigned short CRT_LEN;
+- UCHAR SR[4];
+- UCHAR MISC;
+- UCHAR CRTC[0x19];
+- UCHAR ATTR[0x14];
+- UCHAR GRC[9];
++ unsigned char SR[4];
++ unsigned char MISC;
++ unsigned char CRTC[0x19];
++ unsigned char ATTR[0x14];
++ unsigned char GRC[9];
+ } XGI_StandTableStruct;
+ 
+ typedef struct _XGI_ExtStruct
+ {
+- UCHAR Ext_ModeID;
++ unsigned char Ext_ModeID;
+  unsigned short Ext_ModeFlag;
+  unsigned short Ext_ModeInfo;
+  unsigned short Ext_Point;
+  unsigned short Ext_VESAID;
+- UCHAR Ext_VESAMEMSize;
+- UCHAR Ext_RESINFO;
+- UCHAR VB_ExtTVFlickerIndex;
+- UCHAR VB_ExtTVEdgeIndex;
+- UCHAR VB_ExtTVYFilterIndex;
+- UCHAR REFindex;
++ unsigned char Ext_VESAMEMSize;
++ unsigned char Ext_RESINFO;
++ unsigned char VB_ExtTVFlickerIndex;
++ unsigned char VB_ExtTVEdgeIndex;
++ unsigned char VB_ExtTVYFilterIndex;
++ unsigned char REFindex;
+ } XGI_ExtStruct;
+ 
+ typedef struct _XGI_Ext2Struct
+ {
+  unsigned short Ext_InfoFlag;
+- UCHAR Ext_CRT1CRTC;
+- UCHAR Ext_CRTVCLK;
+- UCHAR Ext_CRT2CRTC;
+- UCHAR Ext_CRT2CRTC2;
+- UCHAR  ModeID;
++ unsigned char Ext_CRT1CRTC;
++ unsigned char Ext_CRTVCLK;
++ unsigned char Ext_CRT2CRTC;
++ unsigned char Ext_CRT2CRTC2;
++ unsigned char  ModeID;
+  unsigned short XRes;
+  unsigned short YRes;
+  /* unsigned short ROM_OFFSET; */
+@@ -132,25 +132,25 @@ typedef struct _XGI_Ext2Struct
+ 
+ typedef struct _XGI_MCLKDataStruct
+ {
+- UCHAR SR28,SR29,SR2A;
++ unsigned char SR28, SR29, SR2A;
+  unsigned short CLOCK;
+ } XGI_MCLKDataStruct;
+ 
+ typedef struct _XGI_ECLKDataStruct
+ {
+- UCHAR SR2E,SR2F,SR30;
++ unsigned char SR2E, SR2F, SR30;
+  unsigned short CLOCK;
+ } XGI_ECLKDataStruct;
+ 
+ typedef struct _XGI_VCLKDataStruct
+ {
+- UCHAR SR2B,SR2C;
++ unsigned char SR2B, SR2C;
+  unsigned short CLOCK;
+ } XGI_VCLKDataStruct;
+ 
+ typedef struct _XGI_VBVCLKDataStruct
+ {
+- UCHAR Part4_A,Part4_B;
++ unsigned char Part4_A, Part4_B;
+  unsigned short CLOCK;
+ } XGI_VBVCLKDataStruct;
+ 
+@@ -164,13 +164,13 @@ typedef struct _XGI_ModeResInfoStruct
+ {
+  unsigned short HTotal;
+  unsigned short VTotal;
+- UCHAR  XChar;
+- UCHAR  YChar;
++ unsigned char  XChar;
++ unsigned char  YChar;
+ } XGI_ModeResInfoStruct;
+ 
+ typedef struct _XGI_LCDNBDesStruct
+ {
+-  UCHAR NB[12];
++  unsigned char NB[12];
+ } XGI_LCDNBDesStruct;
+  /*add for new UNIVGABIOS*/
+ typedef struct _XGI_LCDDesStruct
+@@ -183,7 +183,7 @@ typedef struct _XGI_LCDDesStruct
+ 
+ typedef struct _XGI_LCDDataTablStruct
+ {
+- UCHAR  PANELID;
++ unsigned char  PANELID;
+  unsigned short MASK;
+  unsigned short CAP;
+  unsigned short DATAPTR;
+@@ -243,13 +243,13 @@ typedef struct _XGI330_TVDataStruct
+  unsigned short TVHDE;
+  unsigned short TVVDE;
+  unsigned short RVBHRS;
+- UCHAR FlickerMode;
++ unsigned char FlickerMode;
+  unsigned short HALFRVBHRS;
+ } XGI330_TVDataStruct;
+ 
+ typedef struct _XGI330_LCDDataTablStruct
+ {
+- UCHAR  PANELID;
++ unsigned char  PANELID;
+  unsigned short MASK;
+  unsigned short CAP;
+  unsigned short DATAPTR;
+@@ -273,61 +273,61 @@ typedef struct _XGI330_CHTVDataStruct
+ 
+ typedef struct _XGI_TimingHStruct
+ {
+-  UCHAR data[8];
++  unsigned char data[8];
+ } XGI_TimingHStruct;
+ 
+ typedef struct _XGI_TimingVStruct
+ {
+-  UCHAR data[7];
++  unsigned char data[7];
+ } XGI_TimingVStruct;
+ 
+ typedef struct _XGI_CH7007TV_TimingHStruct
+ {
+-  UCHAR data[10];
++  unsigned char data[10];
+ } XGI_CH7007TV_TimingHStruct;
+ 
+ typedef struct _XGI_CH7007TV_TimingVStruct
+ {
+-  UCHAR data[10];
++  unsigned char data[10];
+ } XGI_CH7007TV_TimingVStruct;
+ 
+ typedef struct _XGI_XG21CRT1Struct
+ {
+- UCHAR ModeID,CR02,CR03,CR15,CR16;
++ unsigned char ModeID, CR02, CR03, CR15, CR16;
+ } XGI_XG21CRT1Struct;
+ 
+ typedef struct _XGI330_CHTVRegDataStruct
+ {
+- UCHAR Reg[16];
++ unsigned char Reg[16];
+ } XGI330_CHTVRegDataStruct;
+ 
+ typedef struct _XGI330_LCDCapStruct
+ {
+- 		UCHAR      LCD_ID;
++		unsigned char	   LCD_ID;
+ 		unsigned short	   LCD_Capability;
+-                UCHAR      LCD_SetFlag;
+-                UCHAR      LCD_DelayCompensation;
+-                UCHAR      LCD_HSyncWidth;
+-                UCHAR      LCD_VSyncWidth;
+-                UCHAR      LCD_VCLK;
+-                UCHAR      LCDA_VCLKData1;
+-                UCHAR      LCDA_VCLKData2;
+-                UCHAR      LCUCHAR_VCLKData1;
+-                UCHAR      LCUCHAR_VCLKData2;
+-                UCHAR      PSC_S1;
+-                UCHAR      PSC_S2;
+-                UCHAR      PSC_S3;
+-                UCHAR      PSC_S4;
+-                UCHAR      PSC_S5;
+-                UCHAR      PWD_2B;
+-                UCHAR      PWD_2C;
+-                UCHAR      PWD_2D;
+-                UCHAR      PWD_2E;
+-                UCHAR      PWD_2F;
+-                UCHAR      Spectrum_31;
+-                UCHAR      Spectrum_32;
+-                UCHAR      Spectrum_33;
+-                UCHAR      Spectrum_34;
++		unsigned char	   LCD_SetFlag;
++		unsigned char	   LCD_DelayCompensation;
++		unsigned char	   LCD_HSyncWidth;
++		unsigned char	   LCD_VSyncWidth;
++		unsigned char	   LCD_VCLK;
++		unsigned char	   LCDA_VCLKData1;
++		unsigned char	   LCDA_VCLKData2;
++		unsigned char	   LCUCHAR_VCLKData1;
++		unsigned char	   LCUCHAR_VCLKData2;
++		unsigned char	   PSC_S1;
++		unsigned char	   PSC_S2;
++		unsigned char	   PSC_S3;
++		unsigned char	   PSC_S4;
++		unsigned char	   PSC_S5;
++		unsigned char	   PWD_2B;
++		unsigned char	   PWD_2C;
++		unsigned char	   PWD_2D;
++		unsigned char	   PWD_2E;
++		unsigned char	   PWD_2F;
++		unsigned char	   Spectrum_31;
++		unsigned char	   Spectrum_32;
++		unsigned char	   Spectrum_33;
++		unsigned char	   Spectrum_34;
+ } XGI330_LCDCapStruct;
+ 
+ typedef struct _XGI21_LVDSCapStruct
+@@ -341,50 +341,50 @@ typedef struct _XGI21_LVDSCapStruct
+ 		unsigned short	   LVDSVFP;
+ 		unsigned short	   LVDSHSYNC;
+ 		unsigned short	   LVDSVSYNC;
+-                UCHAR      VCLKData1;
+-                UCHAR      VCLKData2;
+-                UCHAR      PSC_S1;
+-                UCHAR      PSC_S2;
+-                UCHAR      PSC_S3;
+-                UCHAR      PSC_S4;
+-                UCHAR      PSC_S5;
++		unsigned char	   VCLKData1;
++		unsigned char	   VCLKData2;
++		unsigned char	   PSC_S1;
++		unsigned char	   PSC_S2;
++		unsigned char	   PSC_S3;
++		unsigned char	   PSC_S4;
++		unsigned char	   PSC_S5;
+ } XGI21_LVDSCapStruct;
+ 
+ typedef struct _XGI_CRT1TableStruct
+ {
+-  UCHAR CR[16];
++  unsigned char CR[16];
+ } XGI_CRT1TableStruct;
+ 
+ 
+ typedef struct _XGI330_VCLKDataStruct
+ {
+-    UCHAR SR2B,SR2C;
++    unsigned char SR2B, SR2C;
+     unsigned short CLOCK;
+ } XGI330_VCLKDataStruct;
+ 
+ typedef struct _XGI301C_Tap4TimingStruct
+ {
+     unsigned short DE;
+-    UCHAR  Reg[64];   /* C0-FF */
++    unsigned char  Reg[64];   /* C0-FF */
+ } XGI301C_Tap4TimingStruct;
+ 
+ typedef struct _XGI_New_StandTableStruct
+ {
+-	UCHAR  CRT_COLS;
+-	UCHAR  ROWS;
+-	UCHAR  CHAR_HEIGHT;
++	unsigned char  CRT_COLS;
++	unsigned char  ROWS;
++	unsigned char  CHAR_HEIGHT;
+ 	unsigned short CRT_LEN;
+-	UCHAR  SR[4];
+-	UCHAR  MISC;
+-	UCHAR  CRTC[0x19];
+-	UCHAR  ATTR[0x14];
+-	UCHAR  GRC[9];
++	unsigned char  SR[4];
++	unsigned char  MISC;
++	unsigned char  CRTC[0x19];
++	unsigned char  ATTR[0x14];
++	unsigned char  GRC[9];
+ } XGI_New_StandTableStruct;
+ 
+-typedef UCHAR DRAM8Type[8];
+-typedef UCHAR DRAM4Type[4];
+-typedef UCHAR DRAM32Type[32];
+-typedef UCHAR DRAM2Type[2];
++typedef unsigned char DRAM8Type[8];
++typedef unsigned char DRAM4Type[4];
++typedef unsigned char DRAM32Type[32];
++typedef unsigned char DRAM2Type[2];
+ 
+ typedef struct _VB_DEVICE_INFO  VB_DEVICE_INFO;
+ typedef VB_DEVICE_INFO *	PVB_DEVICE_INFO;
+@@ -427,8 +427,8 @@ struct _VB_DEVICE_INFO
+ 
+     DRAM8Type  *SR15; /* pointer : point to array */
+     DRAM8Type  *CR40;
+-    UCHAR  *pSoftSetting;
+-    UCHAR  *pOutputSelect;
++    unsigned char  *pSoftSetting;
++    unsigned char  *pOutputSelect;
+ 
+     unsigned short *pRGBSenseData;
+     unsigned short *pRGBSenseData2; /*301b*/
+@@ -437,62 +437,62 @@ struct _VB_DEVICE_INFO
+     unsigned short *pYCSenseData;
+     unsigned short *pYCSenseData2;
+ 
+-    UCHAR  *pSR07;
+-    UCHAR  *CR49;
+-    UCHAR  *pSR1F;
+-    UCHAR  *AGPReg;
+-    UCHAR  *SR16;
+-    UCHAR  *pSR21;
+-    UCHAR  *pSR22;
+-    UCHAR  *pSR23;
+-    UCHAR  *pSR24;
+-    UCHAR  *SR25;
+-    UCHAR  *pSR31;
+-    UCHAR  *pSR32;
+-    UCHAR  *pSR33;
+-    UCHAR  *pSR36;      /* alan 12/07/2006 */
+-    UCHAR  *pCRCF;
+-    UCHAR  *pCRD0;      /* alan 12/07/2006 */
+-    UCHAR  *pCRDE;      /* alan 12/07/2006 */
+-    UCHAR  *pCR8F;      /* alan 12/07/2006 */
+-    UCHAR  *pSR40;      /* alan 12/07/2006 */
+-    UCHAR  *pSR41;      /* alan 12/07/2006 */
+-    UCHAR  *pDVOSetting;
+-    UCHAR  *pCR2E;
+-    UCHAR  *pCR2F;
+-    UCHAR  *pCR46;
+-    UCHAR  *pCR47;
+-    UCHAR  *pCRT2Data_1_2;
+-    UCHAR  *pCRT2Data_4_D;
+-    UCHAR  *pCRT2Data_4_E;
+-    UCHAR  *pCRT2Data_4_10;
++    unsigned char  *pSR07;
++    unsigned char  *CR49;
++    unsigned char  *pSR1F;
++    unsigned char  *AGPReg;
++    unsigned char  *SR16;
++    unsigned char  *pSR21;
++    unsigned char  *pSR22;
++    unsigned char  *pSR23;
++    unsigned char  *pSR24;
++    unsigned char  *SR25;
++    unsigned char  *pSR31;
++    unsigned char  *pSR32;
++    unsigned char  *pSR33;
++    unsigned char  *pSR36;      /* alan 12/07/2006 */
++    unsigned char  *pCRCF;
++    unsigned char  *pCRD0;      /* alan 12/07/2006 */
++    unsigned char  *pCRDE;      /* alan 12/07/2006 */
++    unsigned char  *pCR8F;      /* alan 12/07/2006 */
++    unsigned char  *pSR40;      /* alan 12/07/2006 */
++    unsigned char  *pSR41;      /* alan 12/07/2006 */
++    unsigned char  *pDVOSetting;
++    unsigned char  *pCR2E;
++    unsigned char  *pCR2F;
++    unsigned char  *pCR46;
++    unsigned char  *pCR47;
++    unsigned char  *pCRT2Data_1_2;
++    unsigned char  *pCRT2Data_4_D;
++    unsigned char  *pCRT2Data_4_E;
++    unsigned char  *pCRT2Data_4_10;
+     XGI_MCLKDataStruct  *MCLKData;
+     XGI_ECLKDataStruct  *ECLKData;
+ 
+-    UCHAR   *XGI_TVDelayList;
+-    UCHAR   *XGI_TVDelayList2;
+-    UCHAR   *CHTVVCLKUNTSC;
+-    UCHAR   *CHTVVCLKONTSC;
+-    UCHAR   *CHTVVCLKUPAL;
+-    UCHAR   *CHTVVCLKOPAL;
+-    UCHAR   *NTSCTiming;
+-    UCHAR   *PALTiming;
+-    UCHAR   *HiTVExtTiming;
+-    UCHAR   *HiTVSt1Timing;
+-    UCHAR   *HiTVSt2Timing;
+-    UCHAR   *HiTVTextTiming;
+-    UCHAR   *YPbPr750pTiming;
+-    UCHAR   *YPbPr525pTiming;
+-    UCHAR   *YPbPr525iTiming;
+-    UCHAR   *HiTVGroup3Data;
+-    UCHAR   *HiTVGroup3Simu;
+-    UCHAR   *HiTVGroup3Text;
+-    UCHAR   *Ren525pGroup3;
+-    UCHAR   *Ren750pGroup3;
+-    UCHAR   *ScreenOffset;
+-    UCHAR   *pXGINew_DRAMTypeDefinition;
+-    UCHAR   *pXGINew_I2CDefinition ;
+-    UCHAR   *pXGINew_CR97 ;
++    unsigned char   *XGI_TVDelayList;
++    unsigned char   *XGI_TVDelayList2;
++    unsigned char   *CHTVVCLKUNTSC;
++    unsigned char   *CHTVVCLKONTSC;
++    unsigned char   *CHTVVCLKUPAL;
++    unsigned char   *CHTVVCLKOPAL;
++    unsigned char   *NTSCTiming;
++    unsigned char   *PALTiming;
++    unsigned char   *HiTVExtTiming;
++    unsigned char   *HiTVSt1Timing;
++    unsigned char   *HiTVSt2Timing;
++    unsigned char   *HiTVTextTiming;
++    unsigned char   *YPbPr750pTiming;
++    unsigned char   *YPbPr525pTiming;
++    unsigned char   *YPbPr525iTiming;
++    unsigned char   *HiTVGroup3Data;
++    unsigned char   *HiTVGroup3Simu;
++    unsigned char   *HiTVGroup3Text;
++    unsigned char   *Ren525pGroup3;
++    unsigned char   *Ren750pGroup3;
++    unsigned char   *ScreenOffset;
++    unsigned char   *pXGINew_DRAMTypeDefinition;
++    unsigned char   *pXGINew_I2CDefinition ;
++    unsigned char   *pXGINew_CR97 ;
+ 
+     XGI330_LCDCapStruct  *LCDCapList;
+     XGI21_LVDSCapStruct  *XG21_LVDSCapList;
+@@ -525,8 +525,8 @@ typedef struct
+     unsigned short    Vertical_SYNC;
+     unsigned short    Vertical_BP;
+     double    DCLK;
+-    UCHAR     FrameRate;
+-    UCHAR     Interlace;
++    unsigned char     FrameRate;
++    unsigned char     Interlace;
+     unsigned short    Margin;
+ } TimingInfo;
+ 
+diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h
+index 5e06afe368b0..5f394d065764 100644
+--- a/drivers/staging/xgifb/vb_table.h
++++ b/drivers/staging/xgifb/vb_table.h
+@@ -63,14 +63,14 @@ XGI_ECLKDataStruct XGI340_ECLKData[]=
+ 
+ 
+ 
+-UCHAR XGI340_SR13[4][8]={
++unsigned char XGI340_SR13[4][8] = {
+ {0x35,0x45,0xb1,0x00,0x00,0x00,0x00,0x00},/* SR13 */
+ {0x41,0x51,0x5c,0x00,0x00,0x00,0x00,0x00},/* SR14 */
+ {0x31,0x42,0x42,0x00,0x00,0x00,0x00,0x00},/* SR18 */
+ {0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00}/* SR1B */
+ };
+ 
+-UCHAR XGI340_cr41[24][8]=
++unsigned char XGI340_cr41[24][8] =
+ {{0x20,0x50,0x60,0x00,0x00,0x00,0x00,0x00},/* 0 CR41 */
+ {0xc4,0x40,0x84,0x00,0x00,0x00,0x00,0x00},/* 1 CR8A */
+ {0xc4,0x40,0x84,0x00,0x00,0x00,0x00,0x00},/* 2 CR8B */
+@@ -98,7 +98,7 @@ UCHAR XGI340_cr41[24][8]=
+ };
+ 
+ 
+-UCHAR XGI27_cr41[24][8]=
++unsigned char XGI27_cr41[24][8] =
+ {
+ {0x20,0x40,0x60,0x00,0x00,0x00,0x00,0x00},/* 0 CR41 */
+ {0xC4,0x40,0x84,0x00,0x00,0x00,0x00,0x00},/* 1 CR8A */
+@@ -126,7 +126,7 @@ UCHAR XGI27_cr41[24][8]=
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}/* 23 CRC5 */
+ };
+ 
+-UCHAR XGI340_CR6B[8][4]={
++unsigned char XGI340_CR6B[8][4] = {
+ {0xaa,0xaa,0xaa,0xaa},
+ {0xaa,0xaa,0xaa,0xaa},
+ {0xaa,0xaa,0xaa,0xaa},
+@@ -137,7 +137,7 @@ UCHAR XGI340_CR6B[8][4]={
+ {0x00,0x00,0x00,0x00}
+ };
+ 
+-UCHAR XGI340_CR6E[8][4]={
++unsigned char XGI340_CR6E[8][4] = {
+ {0x00,0x00,0x00,0x00},
+ {0x00,0x00,0x00,0x00},
+ {0x00,0x00,0x00,0x00},
+@@ -148,7 +148,7 @@ UCHAR XGI340_CR6E[8][4]={
+ {0x00,0x00,0x00,0x00}
+ };
+ 
+-UCHAR XGI340_CR6F[8][32]={
++unsigned char XGI340_CR6F[8][32] = {
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+@@ -159,7 +159,7 @@ UCHAR XGI340_CR6F[8][32]={
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
+ };
+ 
+-UCHAR XGI340_CR89[8][2]={
++unsigned char XGI340_CR89[8][2] = {
+ {0x00,0x00},
+ {0x00,0x00},
+ {0x00,0x00},
+@@ -170,11 +170,12 @@ UCHAR XGI340_CR89[8][2]={
+ {0x00,0x00}
+ };
+ 			 /* CR47,CR48,CR49,CR4A,CR4B,CR4C,CR70,CR71,CR74,CR75,CR76,CR77 */
+-UCHAR XGI340_AGPReg[12]={0x28,0x23,0x00,0x20,0x00,0x20,0x00,0x05,0xd0,0x10,0x10,0x00};
++unsigned char XGI340_AGPReg[12] = {0x28, 0x23, 0x00, 0x20, 0x00, 0x20, 0x00,
++				   0x05, 0xd0, 0x10, 0x10, 0x00};
+ 
+-UCHAR XGI340_SR16[4]={0x03,0x83,0x03,0x83};
++unsigned char XGI340_SR16[4] = {0x03, 0x83, 0x03, 0x83};
+ 
+-UCHAR XGI330_SR15_1[8][8]={
++unsigned char XGI330_SR15_1[8][8] = {
+ {0x0,0x0,0x00,0x00,0x20,0x20,0x00,0x00},
+ {0x5,0x15,0x15,0x15,0x15,0x15,0x00,0x00},
+ {0xba,0xba,0xba,0xba,0xBA,0xBA,0x00,0x00},
+@@ -185,7 +186,7 @@ UCHAR XGI330_SR15_1[8][8]={
+ {0x0,0xa5,0xfb,0xf6,0xF6,0xF6,0x00,0x00}
+ };
+ 
+-UCHAR XGI330_cr40_1[15][8]={
++unsigned char XGI330_cr40_1[15][8] = {
+ {0x66,0x40,0x40,0x28,0x24,0x24,0x00,0x00},
+ {0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+@@ -203,12 +204,12 @@ UCHAR XGI330_cr40_1[15][8]={
+ {0x00,0xA2,0x00,0x00,0xA2,0xA2,0x00,0x00},
+ };
+ 
+-UCHAR XGI330_sr25[]={0x00,0x0};
+-UCHAR XGI330_sr31=0xc0;
+-UCHAR XGI330_sr32=0x11;
+-UCHAR XGI330_SR33=0x00;
+-UCHAR XG40_CRCF=0x13;
+-UCHAR XG40_DRAMTypeDefinition=0xFF ;
++unsigned char XGI330_sr25[] = {0x00, 0x0};
++unsigned char XGI330_sr31 = 0xc0;
++unsigned char XGI330_sr32 = 0x11;
++unsigned char XGI330_SR33 = 0x00;
++unsigned char XG40_CRCF = 0x13;
++unsigned char XG40_DRAMTypeDefinition = 0xFF ;
+ 
+ XGI_StStruct XGI330_SModeIDTable[]=
+ {
+@@ -964,10 +965,10 @@ XGI330_CHTVRegDataStruct XGI_CHTVRegOPAL[]={
+                 {{      0xE4,0x7F,0xB7,0x1E,0xAF,0x29,0x37,0x5A,0x05,0x00,0x80,0x25,0x8C,0xB2,0x2A,0x00 }}/* 06 (1024x768) ;;1/12/02 */
+ 	     };
+ 
+-UCHAR XGI_CH7017LV1024x768[]={0x60,0x02,0x00,0x07,0x40,0xED,0xA3,
+-                   			0xC8,0xC7,0xAC,0xE0,0x02};
+-UCHAR XGI_CH7017LV1400x1050[]={0x60,0x03,0x11,0x00,0x40,0xE3,0xAD,
+-                   			0xDB,0xF6,0xAC,0xE0,0x02};
++unsigned char XGI_CH7017LV1024x768[] = {0x60, 0x02, 0x00, 0x07, 0x40, 0xED, 0xA3,
++					0xC8, 0xC7, 0xAC, 0xE0, 0x02};
++unsigned char XGI_CH7017LV1400x1050[] = {0x60, 0x03, 0x11, 0x00, 0x40, 0xE3, 0xAD,
++					 0xDB, 0xF6, 0xAC, 0xE0, 0x02};
+ 
+ 
+ /*add for new UNIVGABIOS*/
+@@ -1754,7 +1755,7 @@ XGI330_TVDataStruct  XGI_StYPbPr750pData[]=
+  {    1,   1,1650, 750,1280, 480,   0,   0, 760},
+ };
+ 
+-UCHAR XGI330_NTSCTiming[] = {
++unsigned char XGI330_NTSCTiming[] = {
+   0x17,0x1d,0x03,0x09,0x05,0x06,0x0c,0x0c,
+   0x94,0x49,0x01,0x0a,0x06,0x0d,0x04,0x0a,
+   0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x1b,
+@@ -1764,7 +1765,7 @@ UCHAR XGI330_NTSCTiming[] = {
+   0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x50,
+   0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00};
+ 
+-UCHAR XGI330_PALTiming[] = {
++unsigned char XGI330_PALTiming[] = {
+   0x21,0x5A,0x35,0x6e,0x04,0x38,0x3d,0x70,
+   0x94,0x49,0x01,0x12,0x06,0x3e,0x35,0x6d,
+   0x06,0x14,0x3e,0x35,0x6d,0x00,0x45,0x2b,
+@@ -1774,7 +1775,7 @@ UCHAR XGI330_PALTiming[] = {
+   0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x63,
+   0x00,0x40,0x3e,0x00,0xe1,0x02,0x28,0x00};
+ 
+-UCHAR XGI330_HiTVExtTiming[] =
++unsigned char XGI330_HiTVExtTiming[] =
+ {
+       0x2D,0x60,0x2C,0x5F,0x08,0x31,0x3A,0x64,
+       0x28,0x02,0x01,0x3D,0x06,0x3E,0x35,0x6D,
+@@ -1788,7 +1789,7 @@ UCHAR XGI330_HiTVExtTiming[] =
+ 
+ };
+ 
+-UCHAR XGI330_HiTVSt1Timing[] =
++unsigned char XGI330_HiTVSt1Timing[] =
+ {
+       0x32,0x65,0x2C,0x5F,0x08,0x31,0x3A,0x65,
+       0x28,0x02,0x01,0x3D,0x06,0x3E,0x35,0x6D,
+@@ -1801,7 +1802,7 @@ UCHAR XGI330_HiTVSt1Timing[] =
+       0x0E,0x00,0xfc,0xff,0x2d,0x00
+ };
+ 
+-UCHAR XGI330_HiTVSt2Timing[] =
++unsigned char XGI330_HiTVSt2Timing[] =
+ {
+       0x32,0x65,0x2C,0x5F,0x08,0x31,0x3A,0x64,
+       0x28,0x02,0x01,0x3D,0x06,0x3E,0x35,0x6D,
+@@ -1814,7 +1815,7 @@ UCHAR XGI330_HiTVSt2Timing[] =
+       0x27,0x00,0xFC,0xff,0x6a,0x00
+ };
+ 
+-UCHAR XGI330_HiTVTextTiming[] =
++unsigned char XGI330_HiTVTextTiming[] =
+ {
+       0x32,0x65,0x2C,0x5F,0x08,0x31,0x3A,0x65,
+       0x28,0x02,0x01,0x3D,0x06,0x3E,0x35,0x6D,
+@@ -1827,7 +1828,7 @@ UCHAR XGI330_HiTVTextTiming[] =
+       0x11,0x00,0xFC,0xFF,0x32,0x00
+ };
+ 
+-UCHAR XGI330_YPbPr750pTiming[] =
++unsigned char XGI330_YPbPr750pTiming[] =
+ {
+       0x30,0x1d,0xe8,0x09,0x09,0xed,0x0c,0x0c,
+       0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a,
+@@ -1840,7 +1841,7 @@ UCHAR XGI330_YPbPr750pTiming[] =
+       0x11,0x00,0xfc,0xff,0x32,0x00
+ };
+ 
+-UCHAR XGI330_YPbPr525pTiming[] =
++unsigned char XGI330_YPbPr525pTiming[] =
+ {
+       0x3E,0x11,0x06,0x09,0x0b,0x0c,0x0c,0x0c,
+       0x98,0x0a,0x01,0x0d,0x06,0x0d,0x04,0x0a,
+@@ -1853,7 +1854,7 @@ UCHAR XGI330_YPbPr525pTiming[] =
+       0x11,0x00,0xFC,0xFF,0x32,0x00
+ };
+ 
+-UCHAR XGI330_YPbPr525iTiming[] =
++unsigned char XGI330_YPbPr525iTiming[] =
+ {
+       0x1B,0x21,0x03,0x09,0x05,0x06,0x0C,0x0C,
+       0x94,0x49,0x01,0x0A,0x06,0x0D,0x04,0x0A,
+@@ -1867,7 +1868,7 @@ UCHAR XGI330_YPbPr525iTiming[] =
+ 
+ };
+ 
+-UCHAR XGI330_HiTVGroup3Data[] =
++unsigned char XGI330_HiTVGroup3Data[] =
+ {
+       0x00,0x1A,0x22,0x63,0x62,0x22,0x08,0x5F,
+       0x05,0x21,0xB2,0xB2,0x55,0x77,0x2A,0xA6,
+@@ -1879,7 +1880,7 @@ UCHAR XGI330_HiTVGroup3Data[] =
+       0x18,0x05,0x18,0x05,0x4C,0xA8,0x01
+ };
+ 
+-UCHAR XGI330_HiTVGroup3Simu[] =
++unsigned char XGI330_HiTVGroup3Simu[] =
+ {
+       0x00,0x1A,0x22,0x63,0x62,0x22,0x08,0x95,
+       0xDB,0x20,0xB8,0xB8,0x55,0x47,0x2A,0xA6,
+@@ -1891,7 +1892,7 @@ UCHAR XGI330_HiTVGroup3Simu[] =
+       0x18,0x05,0x18,0x05,0x4C,0xA8,0x01
+ };
+ 
+-UCHAR XGI330_HiTVGroup3Text[] =
++unsigned char XGI330_HiTVGroup3Text[] =
+ {
+       0x00,0x1A,0x22,0x63,0x62,0x22,0x08,0xA7,
+       0xF5,0x20,0xCE,0xCE,0x55,0x47,0x2A,0xA6,
+@@ -1903,7 +1904,7 @@ UCHAR XGI330_HiTVGroup3Text[] =
+       0x18,0x05,0x18,0x05,0x4C,0xA8,0x01
+ };
+ 
+-UCHAR XGI330_Ren525pGroup3[] =
++unsigned char XGI330_Ren525pGroup3[] =
+ {
+   0x00,0x14,0x15,0x25,0x55,0x15,0x0b,0x13,
+   0xB1,0x41,0x62,0x62,0xFF,0xF4,0x45,0xa6,
+@@ -1915,7 +1916,7 @@ UCHAR XGI330_Ren525pGroup3[] =
+   0x1a,0x1F,0x25,0x2a,0x4C,0xAA,0x01
+ };
+ 
+-UCHAR XGI330_Ren750pGroup3[] =
++unsigned char XGI330_Ren750pGroup3[] =
+ {
+   0x00,0x14,0x15,0x25,0x55,0x15,0x0b,0x7a,
+   0x54,0x41,0xE7,0xE7,0xFF,0xF4,0x45,0xa6,
+@@ -3392,7 +3393,9 @@ XGI_VBVCLKDataStruct XGI330_VBVCLKData[]=
+  { 0x70,0x44,108}, /* 0x49 chiawen for 1400x1050*/
+ };
+ 
+-UCHAR XGI330_ScreenOffset[]={ 0x14,0x19,0x20,0x28,0x32,0x40,0x50,0x64,0x78,0x80,0x2d,0x35,0x57,0x48 };
++unsigned char XGI330_ScreenOffset[] = { 0x14, 0x19, 0x20, 0x28, 0x32, 0x40,
++					0x50, 0x64, 0x78, 0x80, 0x2d, 0x35,
++					0x57, 0x48};
+ 
+ XGI_StResInfoStruct XGI330_StResInfo[]=
+ {
+@@ -3430,10 +3433,10 @@ XGI_ModeResInfoStruct XGI330_ModeResInfo[]=
+  { 1152, 864, 8,16}
+ };
+ 
+-UCHAR XGI330_OutputSelect =0x40;
+-UCHAR XGI330_SoftSetting = 0x30;
+-UCHAR XGI330_SR07=0x18;
+-UCHAR XGI330New_SR15[8][8]={
++unsigned char XGI330_OutputSelect = 0x40;
++unsigned char XGI330_SoftSetting = 0x30;
++unsigned char XGI330_SR07 = 0x18;
++unsigned char XGI330New_SR15[8][8] = {
+ {0x0,0x4,0x60,0x60},
+ {0xf,0xf,0xf,0xf},
+ {0xba,0xba,0xba,0xba},
+@@ -3444,7 +3447,7 @@ UCHAR XGI330New_SR15[8][8]={
+ {0x0,0xa5,0xfb,0xf6}
+ };
+ 
+-UCHAR XGI330New_CR40[5][8]={
++unsigned char XGI330New_CR40[5][8] = {
+ {0x77,0x77,0x44,0x44},
+ {0x77,0x77,0x44,0x44},
+ {0x0,0x0,0x0,0x0},
+@@ -3452,63 +3455,63 @@ UCHAR XGI330New_CR40[5][8]={
+ {0x0,0x0,0xf0,0xf8}
+ };
+ 
+-UCHAR XGI330_CR49[]={0xaa,0x88};
+-UCHAR XGI330_SR1F=0x0;
+-UCHAR XGI330_SR21=0xa3;
+-UCHAR XGI330_650_SR21=0xa7;
+-UCHAR XGI330_SR22=0xfb;
+-UCHAR XGI330_SR23=0xf6;
+-UCHAR XGI330_SR24=0xd;
+-
+-UCHAR XGI660_SR21=0xa3;/* 2003.0312 */
+-UCHAR XGI660_SR22=0xf3;/* 2003.0312 */
+-
+-UCHAR XGI330_LVDS_SR32=0x00;   /* ynlai for 650 LVDS */
+-UCHAR XGI330_LVDS_SR33=0x00;	/* chiawen for 650 LVDS */
+-UCHAR XGI330_650_SR31=0x40;
+-UCHAR XGI330_650_SR33=0x04;
+-UCHAR XGI330_CRT2Data_1_2 = 0x0;
+-UCHAR XGI330_CRT2Data_4_D = 0x0;
+-UCHAR XGI330_CRT2Data_4_E = 0x0;
+-UCHAR XGI330_CRT2Data_4_10 = 0x80;
++unsigned char XGI330_CR49[] = {0xaa, 0x88};
++unsigned char XGI330_SR1F = 0x0;
++unsigned char XGI330_SR21 = 0xa3;
++unsigned char XGI330_650_SR21 = 0xa7;
++unsigned char XGI330_SR22 = 0xfb;
++unsigned char XGI330_SR23 = 0xf6;
++unsigned char XGI330_SR24 = 0xd;
++
++unsigned char XGI660_SR21 = 0xa3;/* 2003.0312 */
++unsigned char XGI660_SR22 = 0xf3;/* 2003.0312 */
++
++unsigned char XGI330_LVDS_SR32 = 0x00;   /* ynlai for 650 LVDS */
++unsigned char XGI330_LVDS_SR33 = 0x00;	/* chiawen for 650 LVDS */
++unsigned char XGI330_650_SR31 = 0x40;
++unsigned char XGI330_650_SR33 = 0x04;
++unsigned char XGI330_CRT2Data_1_2 = 0x0;
++unsigned char XGI330_CRT2Data_4_D = 0x0;
++unsigned char XGI330_CRT2Data_4_E = 0x0;
++unsigned char XGI330_CRT2Data_4_10 = 0x80;
+ unsigned short XGI330_RGBSenseData = 0xd1;
+ unsigned short XGI330_VideoSenseData = 0xb9;
+ unsigned short XGI330_YCSenseData = 0xb3;
+ unsigned short XGI330_RGBSenseData2 = 0x0190;     /*301b*/
+ unsigned short XGI330_VideoSenseData2 = 0x0110;
+ unsigned short XGI330_YCSenseData2 = 0x016B;
+-UCHAR XGI330_NTSCPhase[] = {0x21,0xed,0x8a,0x8};
+-UCHAR XGI330_PALPhase[] = {0x2a,0x5,0xd3,0x0};
+-UCHAR XGI330_NTSCPhase2[] = {0x21,0xF0,0x7B,0xD6};/*301b*/
+-UCHAR XGI330_PALPhase2[] = {0x2a,0x09,0x86,0xe9};
+-UCHAR XGI330_PALMPhase[] = {0x21,0xE4,0x2E,0x9B};   /*palmn*/
+-UCHAR XGI330_PALNPhase[] = {0x21,0xF4,0x3E,0xBA};
+-UCHAR XG40_I2CDefinition = 0x00 ;
+-UCHAR XG20_CR97 = 0x10 ;
+-
+-UCHAR XG21_DVOSetting = 0x00 ;
+-UCHAR XG21_CR2E = 0x00 ;
+-UCHAR XG21_CR2F = 0x00 ;
+-UCHAR XG21_CR46 = 0x00 ;
+-UCHAR XG21_CR47 = 0x00 ;
+-
+-UCHAR XG27_CR97 = 0xC1 ;
+-UCHAR XG27_SR36 = 0x30 ;
+-UCHAR XG27_CR8F = 0x0C ;
+-UCHAR XG27_CRD0[] = {0,0,0,0,0,0,0,0x82,0x00,0x66,0x01,0x00} ;
+-UCHAR XG27_CRDE[] = {0,0} ;
+-UCHAR XG27_SR40 = 0x04 ;
+-UCHAR XG27_SR41 = 0x00 ;
+-
+-UCHAR XGI330_CHTVVCLKUNTSC[]={0x00 };
+-
+-UCHAR XGI330_CHTVVCLKONTSC[]={0x00 };
+-
+-UCHAR XGI330_CHTVVCLKUPAL[]={0x00 };
+-
+-UCHAR XGI330_CHTVVCLKOPAL[]={0x00 };
+-
+-UCHAR XGI7007_CHTVVCLKUNTSC[]={CH7007TVVCLK30_2,
++unsigned char XGI330_NTSCPhase[] = {0x21, 0xed, 0x8a, 0x8};
++unsigned char XGI330_PALPhase[] = {0x2a, 0x5, 0xd3, 0x0};
++unsigned char XGI330_NTSCPhase2[] = {0x21, 0xF0, 0x7B, 0xD6};/*301b*/
++unsigned char XGI330_PALPhase2[] = {0x2a, 0x09, 0x86, 0xe9};
++unsigned char XGI330_PALMPhase[] = {0x21, 0xE4, 0x2E, 0x9B};   /*palmn*/
++unsigned char XGI330_PALNPhase[] = {0x21, 0xF4, 0x3E, 0xBA};
++unsigned char XG40_I2CDefinition = 0x00 ;
++unsigned char XG20_CR97 = 0x10 ;
++
++unsigned char XG21_DVOSetting = 0x00 ;
++unsigned char XG21_CR2E = 0x00 ;
++unsigned char XG21_CR2F = 0x00 ;
++unsigned char XG21_CR46 = 0x00 ;
++unsigned char XG21_CR47 = 0x00 ;
++
++unsigned char XG27_CR97 = 0xC1 ;
++unsigned char XG27_SR36 = 0x30 ;
++unsigned char XG27_CR8F = 0x0C ;
++unsigned char XG27_CRD0[] = {0, 0, 0, 0, 0, 0, 0, 0x82, 0x00, 0x66, 0x01, 0x00};
++unsigned char XG27_CRDE[] = {0, 0};
++unsigned char XG27_SR40 = 0x04 ;
++unsigned char XG27_SR41 = 0x00 ;
++
++unsigned char XGI330_CHTVVCLKUNTSC[] = {0x00};
++
++unsigned char XGI330_CHTVVCLKONTSC[] = {0x00};
++
++unsigned char XGI330_CHTVVCLKUPAL[] = {0x00};
++
++unsigned char XGI330_CHTVVCLKOPAL[] = {0x00};
++
++unsigned char XGI7007_CHTVVCLKUNTSC[] = {CH7007TVVCLK30_2,
+                                CH7007TVVCLK30_2,
+                                CH7007TVVCLK30_2,
+                                CH7007TVVCLK30_2,
+@@ -3516,7 +3519,7 @@ UCHAR XGI7007_CHTVVCLKUNTSC[]={CH7007TVVCLK30_2,
+                                CH7007TVVCLK47_8
+                               };
+ 
+-UCHAR XGI7007_CHTVVCLKONTSC[]={CH7007TVVCLK26_4,
++unsigned char XGI7007_CHTVVCLKONTSC[] = {CH7007TVVCLK26_4,
+                                CH7007TVVCLK26_4,
+                                CH7007TVVCLK26_4,
+                                CH7007TVVCLK26_4,
+@@ -3524,7 +3527,7 @@ UCHAR XGI7007_CHTVVCLKONTSC[]={CH7007TVVCLK26_4,
+                                CH7007TVVCLK43_6
+                               };
+ 
+-UCHAR XGI7007_CHTVVCLKUPAL[]={CH7007TVVCLK31_5,
++unsigned char XGI7007_CHTVVCLKUPAL[] = {CH7007TVVCLK31_5,
+                               CH7007TVVCLK31_5,
+                               CH7007TVVCLK31_5,
+                               CH7007TVVCLK31_5,
+@@ -3532,7 +3535,7 @@ UCHAR XGI7007_CHTVVCLKUPAL[]={CH7007TVVCLK31_5,
+                               CH7007TVVCLK39
+                              };
+ 
+-UCHAR XGI7007_CHTVVCLKOPAL[]={CH7007TVVCLK31_5,
++unsigned char XGI7007_CHTVVCLKOPAL[] = {CH7007TVVCLK31_5,
+                               CH7007TVVCLK31_5,
+                               CH7007TVVCLK31_5,
+                               CH7007TVVCLK31_5,
+@@ -3957,7 +3960,7 @@ XGI330_VCLKDataStruct XGI_VBVCLKData[]=
+                 {      0xFF,0x00,0                }      /* End mark */
+ };
+ 
+-UCHAR XGI660_TVDelayList[]=
++unsigned char XGI660_TVDelayList[] =
+ {
+           0x44,            /* ; 0 ExtNTSCDelay */
+           0x44,            /* ; 1 StNTSCDelay */
+@@ -3973,7 +3976,7 @@ UCHAR XGI660_TVDelayList[]=
+           0x44             /* ; B StYPbPrDealy(750p) */
+ };
+ 
+-UCHAR XGI660_TVDelayList2[]=
++unsigned char XGI660_TVDelayList2[] =
+ {
+           0x44,           /* ; 0 ExtNTSCDelay */
+           0x44,           /* ; 1 StNTSCDelay */
+@@ -3989,7 +3992,7 @@ UCHAR XGI660_TVDelayList2[]=
+           0x44            /* ; B StYPbPrDealy(750p) */
+ };
+ 
+-UCHAR XGI301TVDelayList[]=
++unsigned char XGI301TVDelayList[] =
+ {
+ 	0x22,            /* ; 0 ExtNTSCDelay */
+ 	0x22,            /* ; 1 StNTSCDelay */
+@@ -4005,7 +4008,7 @@ UCHAR XGI301TVDelayList[]=
+ 	0x22            /* B StYPbPrDealy(750p) */
+ };
+ 
+-UCHAR XGI301TVDelayList2[]=
++unsigned char XGI301TVDelayList2[] =
+ {
+ 	0x22,           /* ; 0 ExtNTSCDelay */
+ 	0x22,           /* ; 1 StNTSCDelay */
+@@ -4022,7 +4025,7 @@ UCHAR XGI301TVDelayList2[]=
+ };
+ 
+ 
+-UCHAR TVAntiFlickList[]=
++unsigned char TVAntiFlickList[] =
+ {/* NTSCAntiFlicker */
+                       0x04,           /* ; 0 Adaptive */
+                       0x00,           /* ; 1 new anti-flicker ? */
+@@ -4035,7 +4038,7 @@ UCHAR TVAntiFlickList[]=
+ };
+ 
+ 
+-UCHAR TVEdgeList[]=
++unsigned char TVEdgeList[] =
+ {
+       0x00,            /* ; 0 NTSC No Edge enhance */
+       0x04,            /* ; 1 NTSC Adaptive Edge enhance */
+@@ -4062,7 +4065,7 @@ unsigned long TVPhaseList[]=
+        0xE00A831E  /* ; D PAL-M 1024x768 */
+ };
+ 
+-UCHAR NTSCYFilter1[]=
++unsigned char NTSCYFilter1[] =
+ {
+ 		      0x00,0xF4,0x10,0x38     ,/* 0 : 320x text mode */
+                       0x00,0xF4,0x10,0x38     ,/* 1 : 360x text mode */
+@@ -4073,7 +4076,7 @@ UCHAR NTSCYFilter1[]=
+                       0xEB,0x15,0x25,0xF6     /* 6 : 800x gra. mode */
+ };
+ 
+-UCHAR PALYFilter1[]=
++unsigned char PALYFilter1[] =
+ {
+ 		      0x00,0xF4,0x10,0x38, /* 0 : 320x text mode */
+                       0x00,0xF4,0x10,0x38     ,/* 1 : 360x text mode */
+@@ -4084,7 +4087,7 @@ UCHAR PALYFilter1[]=
+                       0xFC,0xFB,0x14,0x2A     /* 6 : 800x gra. mode */
+ };
+ 
+-UCHAR PALMYFilter1[]=
++unsigned char PALMYFilter1[] =
+ {
+ 		      0x00,0xF4,0x10,0x38, /* 0 : 320x text mode */
+                       0x00,0xF4,0x10,0x38, /* 1 : 360x text mode */
+@@ -4096,7 +4099,7 @@ UCHAR PALMYFilter1[]=
+                       0xFF,0xFF,0xFF,0xFF  /* End of Table */
+ };
+ 
+-UCHAR PALNYFilter1[]=
++unsigned char PALNYFilter1[] =
+ {
+ 		      0x00,0xF4,0x10,0x38, /* 0 : 320x text mode */
+                       0x00,0xF4,0x10,0x38, /* 1 : 360x text mode */
+@@ -4108,7 +4111,7 @@ UCHAR PALNYFilter1[]=
+                       0xFF,0xFF,0xFF,0xFF  /* End of Table */
+ };
+ 
+-UCHAR NTSCYFilter2[]=
++unsigned char NTSCYFilter2[] =
+ {
+ 		      0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 0 : 320x text mode */
+                       0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 1 : 360x text mode */
+@@ -4120,7 +4123,7 @@ UCHAR NTSCYFilter2[]=
+                       0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28  /* 7 : 1024xgra. mode */
+ };
+ 
+-UCHAR PALYFilter2[]=
++unsigned char PALYFilter2[] =
+ {
+ 		      0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 0 : 320x text mode */
+                       0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 1 : 360x text mode */
+@@ -4132,7 +4135,7 @@ UCHAR PALYFilter2[]=
+                       0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28  /* 7 : 1024xgra. mode */
+ };
+ 
+-UCHAR PALMYFilter2[]=
++unsigned char PALMYFilter2[] =
+ {
+ 		      0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 0 : 320x text mode */
+                       0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 1 : 360x text mode */
+@@ -4144,7 +4147,7 @@ UCHAR PALMYFilter2[]=
+                       0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28  /* 7 : 1024xgra. mode */
+ };
+ 
+-UCHAR PALNYFilter2[]=
++unsigned char PALNYFilter2[] =
+ {
+ 		      0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 0 : 320x text mode */
+                       0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 1 : 360x text mode */
+@@ -4156,7 +4159,7 @@ UCHAR PALNYFilter2[]=
+                       0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28  /* 7 : 1024xgra. mode */
+ };
+ 
+-UCHAR XGI_NTSC1024AdjTime[]=
++unsigned char XGI_NTSC1024AdjTime[] =
+ {
+       0xa7,0x07,0xf2,0x6e,0x17,0x8b,0x73,0x53,
+       0x13,0x40,0x34,0xF4,0x63,0xBB,0xCC,0x7A,
+diff --git a/drivers/staging/xgifb/vb_util.c b/drivers/staging/xgifb/vb_util.c
+index 5e32afda28c2..2c40368ceee2 100644
+--- a/drivers/staging/xgifb/vb_util.c
++++ b/drivers/staging/xgifb/vb_util.c
+@@ -10,8 +10,8 @@ void XGINew_SetReg1(unsigned long,unsigned short,unsigned short);
+ void XGINew_SetReg2(unsigned long,unsigned short,unsigned short);
+ void XGINew_SetReg3(unsigned long,unsigned short);
+ void XGINew_SetReg4(unsigned long,unsigned long);
+-UCHAR XGINew_GetReg1(unsigned long,unsigned short);
+-UCHAR XGINew_GetReg2(unsigned long);
++unsigned char XGINew_GetReg1(unsigned long, unsigned short);
++unsigned char XGINew_GetReg2(unsigned long);
+ unsigned long XGINew_GetReg3(unsigned long);
+ void XGINew_ClearDAC(unsigned char *);
+ void XGINew_SetRegANDOR(unsigned long Port,unsigned short Index,
+@@ -43,7 +43,7 @@ void XGINew_SetReg1( unsigned long port , unsigned short index , unsigned short
+ /* --------------------------------------------------------------------- */
+ /*void XGINew_SetReg2( unsigned long port , unsigned short index , unsigned short data )
+ {
+-    InPortByte( ( PUCHAR )port + 0x3da - 0x3c0 ) ;
++    InPortByte((P unsigned char )port + 0x3da - 0x3c0) ;
+     OutPortByte( XGINew_P3c0 , index ) ;
+     OutPortByte( XGINew_P3c0 , data ) ;
+     OutPortByte( XGINew_P3c0 , 0x20 ) ;
+@@ -80,9 +80,9 @@ void XGINew_SetReg4( unsigned long port , unsigned long data )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-UCHAR XGINew_GetReg1( unsigned long port , unsigned short index )
++unsigned char XGINew_GetReg1(unsigned long port, unsigned short index)
+ {
+-    UCHAR data ;
++    unsigned char data ;
+ 
+     outb(index, port);
+     data = inb(port + 1) ;
+@@ -96,9 +96,9 @@ UCHAR XGINew_GetReg1( unsigned long port , unsigned short index )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-UCHAR XGINew_GetReg2( unsigned long port )
++unsigned char XGINew_GetReg2(unsigned long port)
+ {
+-    UCHAR data ;
++    unsigned char data ;
+ 
+     data = inb(port) ;
+ 
+@@ -197,7 +197,7 @@ void NewDelaySeconds( int seconds )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void Newdebugcode( UCHAR code )
++void Newdebugcode(unsigned char code)
+ {
+ //    OutPortByte ( 0x80 , code ) ;
+     /* OutPortByte ( 0x300 , code ) ; */
+diff --git a/drivers/staging/xgifb/vb_util.h b/drivers/staging/xgifb/vb_util.h
+index aaaf361477ab..156f6445c88d 100644
+--- a/drivers/staging/xgifb/vb_util.h
++++ b/drivers/staging/xgifb/vb_util.h
+@@ -1,11 +1,11 @@
+ #ifndef _VBUTIL_
+ #define _VBUTIL_
+ extern   void     NewDelaySeconds( int );
+-extern   void     Newdebugcode( UCHAR );
++extern   void     Newdebugcode(unsigned char);
+ extern   void     XGINew_SetReg1(unsigned long, unsigned short, unsigned short);
+ extern   void     XGINew_SetReg3(unsigned long, unsigned short);
+-extern   UCHAR    XGINew_GetReg1(unsigned long, unsigned short);
+-extern   UCHAR    XGINew_GetReg2(unsigned long);
++extern    unsigned char     XGINew_GetReg1(unsigned long, unsigned short);
++extern    unsigned char     XGINew_GetReg2(unsigned long);
+ extern   void     XGINew_SetReg4(unsigned long, unsigned long);
+ extern   unsigned long    XGINew_GetReg3(unsigned long);
+ extern   void     XGINew_SetRegOR(unsigned long Port,unsigned short Index,unsigned short DataOR);
+diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h
+index a85f21a7aebc..a518d27c0d11 100644
+--- a/drivers/staging/xgifb/vgatypes.h
++++ b/drivers/staging/xgifb/vgatypes.h
+@@ -4,25 +4,6 @@
+ 
+ #include 
+ 
+-#ifndef CHAR
+-typedef char CHAR;
+-#endif
+-
+-#ifndef SHORT
+-typedef short SHORT;
+-#endif
+-
+-#ifndef LONG
+-typedef long  LONG;
+-#endif
+-
+-#ifndef UCHAR
+-typedef unsigned char UCHAR;
+-#endif
+-
+-typedef unsigned long XGIIOADDRESS;
+-
+-
+ #ifndef VBIOS_VER_MAX_LENGTH
+ #define VBIOS_VER_MAX_LENGTH    4
+ #endif
+@@ -74,8 +55,8 @@ typedef enum _XGI_LCD_TYPE {
+ #ifndef PXGI_DSReg
+ typedef struct _XGI_DSReg
+ {
+-  UCHAR  jIdx;
+-  UCHAR  jVal;
++  unsigned char  jIdx;
++  unsigned char  jVal;
+ } XGI_DSReg, *PXGI_DSReg;
+ #endif
+ 
+@@ -109,13 +90,13 @@ struct _XGI_HW_DEVICE_INFO
+     unsigned long  ul2ndVideoMemorySize;
+ 
+     unsigned char *pj2ndIOAddress;
+-    UCHAR  jChipType;            /* Used to Identify Graphics Chip */
++    unsigned char  jChipType;            /* Used to Identify Graphics Chip */
+                                  /* defined in the data structure type  */
+                                  /* "XGI_CHIP_TYPE" */
+ 
+-    UCHAR  jChipRevision;        /* Used to Identify Graphics Chip Revision */
++    unsigned char  jChipRevision;        /* Used to Identify Graphics Chip Revision */
+ 
+-    UCHAR  ujVBChipID;           /* the ID of video bridge */
++    unsigned char  ujVBChipID;           /* the ID of video bridge */
+                                  /* defined in the data structure type */
+                                  /* "XGI_VB_CHIP_TYPE" */
+ 
+@@ -152,7 +133,7 @@ struct _XGI_HW_DEVICE_INFO
+ 
+     PXGI_QUERYSPACE  pQueryNorthBridgeSpace;
+ 
+-    UCHAR  szVBIOSVer[VBIOS_VER_MAX_LENGTH];
++    unsigned char szVBIOSVer[VBIOS_VER_MAX_LENGTH];
+ 
+ };
+ #endif

commit 82d6eb5b2ecd4ccdd44a23115fc499ecefc77706
+Author: Bill Pemberton 
+Date:   Thu Jun 17 13:10:46 2010 -0400
+
+    Staging: xgifb: Remove USHORT, ULONG, BOOLEAN, and VOID typedefs
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Arnaud Patard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/XGI_main.h b/drivers/staging/xgifb/XGI_main.h
+index 7c643a6a0632..fcb1816e387a 100644
+--- a/drivers/staging/xgifb/XGI_main.h
++++ b/drivers/staging/xgifb/XGI_main.h
+@@ -499,13 +499,13 @@ u8  XGIfb_mode_no  = 0;
+ u8  XGIfb_rate_idx = 0;
+ 
+ /* TW: CR36 evaluation */
+-const USHORT XGI300paneltype[] =
++const unsigned short XGI300paneltype[] =
+     { LCD_UNKNOWN,   LCD_800x600,  LCD_1024x768,  LCD_1280x1024,
+       LCD_1280x960,  LCD_640x480,  LCD_1024x600,  LCD_1152x768,
+        LCD_1024x768, LCD_1024x768,  LCD_1024x768,
+       LCD_1024x768,  LCD_1024x768, LCD_1024x768,  LCD_1024x768 };
+ 
+-const USHORT XGI310paneltype[] =
++const unsigned short XGI310paneltype[] =
+     { LCD_UNKNOWN,   LCD_800x600,  LCD_1024x768,  LCD_1280x1024,
+       LCD_640x480,   LCD_1024x600, LCD_1152x864,  LCD_1280x960,
+       LCD_1152x768,  LCD_1400x1050,LCD_1280x768,  LCD_1600x1200,
+@@ -821,7 +821,9 @@ extern int      XGIfb_mode_rate_to_ddata(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_
+ 			 unsigned int *hsync_len, unsigned int *vsync_len,
+ 			 unsigned int *sync, unsigned int *vmode);
+ */
+-			extern   BOOLEAN  XGI_SearchModeID( USHORT ModeNo,USHORT  *ModeIdIndex, PVB_DEVICE_INFO );
++extern unsigned char XGI_SearchModeID(unsigned short ModeNo,
++				unsigned short *ModeIdIndex,
++				PVB_DEVICE_INFO);
+ static int      XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
+ 			      struct fb_info *info);
+ 
+@@ -841,10 +843,10 @@ static int      XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
+ static void     XGIfb_pre_setmode(void);
+ static void     XGIfb_post_setmode(void);
+ 
+-static BOOLEAN  XGIfb_CheckVBRetrace(void);
+-static BOOLEAN  XGIfbcheckvretracecrt2(void);
+-static BOOLEAN  XGIfbcheckvretracecrt1(void);
+-static BOOLEAN  XGIfb_bridgeisslave(void);
++static unsigned char  XGIfb_CheckVBRetrace(void);
++static unsigned char  XGIfbcheckvretracecrt2(void);
++static unsigned char  XGIfbcheckvretracecrt1(void);
++static unsigned char  XGIfb_bridgeisslave(void);
+ 
+ struct XGI_memreq {
+ 	unsigned long offset;
+@@ -879,7 +881,7 @@ static XGI_OH   *XGIfb_poh_free(unsigned long base);
+ static void     XGIfb_free_node(XGI_OH *poh);
+ 
+ /* Internal routines to access PCI configuration space */
+-BOOLEAN         XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
++unsigned char         XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
+ 	          	unsigned long offset, unsigned long set, unsigned long *value);
+ //BOOLEAN         XGIfb_query_north_bridge_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
+ //	         	unsigned long offset, unsigned long set, unsigned long *value);
+@@ -887,18 +889,26 @@ BOOLEAN         XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
+ 
+ /* Routines from init.c/init301.c */
+ extern void     InitTo330Pointer(UCHAR,PVB_DEVICE_INFO pVBInfo);
+-extern BOOLEAN  XGIInitNew(PXGI_HW_DEVICE_INFO HwDeviceExtension);
+-extern BOOLEAN  XGISetModeNew(PXGI_HW_DEVICE_INFO HwDeviceExtension, USHORT ModeNo);
++extern unsigned char  XGIInitNew(PXGI_HW_DEVICE_INFO HwDeviceExtension);
++extern unsigned char XGISetModeNew(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++			     unsigned short ModeNo);
+ //extern void     XGI_SetEnableDstn(VB_DEVICE_INFO *XGI_Pr);
+ extern void     XGI_LongWait(VB_DEVICE_INFO *XGI_Pr);
+-extern USHORT   XGI_GetRatePtrCRT2( PXGI_HW_DEVICE_INFO pXGIHWDE, USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo );
++extern unsigned short XGI_GetRatePtrCRT2(PXGI_HW_DEVICE_INFO pXGIHWDE,
++					 unsigned short ModeNo,
++					 unsigned short ModeIdIndex,
++					 PVB_DEVICE_INFO pVBInfo);
+ /* TW: Chrontel TV functions */
+-extern USHORT 	XGI_GetCH700x(VB_DEVICE_INFO *XGI_Pr, USHORT tempbx);
+-extern void 	XGI_SetCH700x(VB_DEVICE_INFO *XGI_Pr, USHORT tempbx);
+-extern USHORT 	XGI_GetCH701x(VB_DEVICE_INFO *XGI_Pr, USHORT tempbx);
+-extern void 	XGI_SetCH701x(VB_DEVICE_INFO *XGI_Pr, USHORT tempbx);
+-extern void     XGI_SetCH70xxANDOR(VB_DEVICE_INFO *XGI_Pr, USHORT tempax,USHORT tempbh);
+-extern void     XGI_DDC2Delay(VB_DEVICE_INFO *XGI_Pr, USHORT delaytime);
++extern unsigned short XGI_GetCH700x(VB_DEVICE_INFO *XGI_Pr,
++				    unsigned short tempbx);
++extern void XGI_SetCH700x(VB_DEVICE_INFO *XGI_Pr, unsigned short tempbx);
++extern unsigned short XGI_GetCH701x(VB_DEVICE_INFO *XGI_Pr,
++				    unsigned short tempbx);
++extern void XGI_SetCH701x(VB_DEVICE_INFO *XGI_Pr, unsigned short tempbx);
++extern void XGI_SetCH70xxANDOR(VB_DEVICE_INFO *XGI_Pr,
++			       unsigned short tempax,
++			       unsigned short tempbh);
++extern void XGI_DDC2Delay(VB_DEVICE_INFO *XGI_Pr, unsigned short delaytime);
+ 
+ /* TW: Sensing routines */
+ void            XGI_Sense30x(void);
+diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
+index e3f837337fba..faea2e740e4b 100644
+--- a/drivers/staging/xgifb/XGI_main_26.c
++++ b/drivers/staging/xgifb/XGI_main_26.c
+@@ -165,11 +165,11 @@ int
+ XGIfb_mode_rate_to_dclock(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ 			  unsigned char modeno, unsigned char rateindex)
+ {
+-    USHORT ModeNo = modeno;
+-    USHORT ModeIdIndex = 0, ClockIndex = 0;
+-    USHORT RefreshRateTableIndex = 0;
++    unsigned short ModeNo = modeno;
++    unsigned short ModeIdIndex = 0, ClockIndex = 0;
++    unsigned short RefreshRateTableIndex = 0;
+ 
+-    /*ULONG  temp = 0;*/
++    /*unsigned long  temp = 0;*/
+     int    Clock;
+     XGI_Pr->ROMAddr  = HwDeviceExtension->pjVirtualRomBase;
+     InitTo330Pointer( HwDeviceExtension->jChipType, XGI_Pr ) ;
+@@ -204,9 +204,9 @@ XGIfb_mode_rate_to_ddata(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExt
+ 			 u32 *hsync_len, u32 *vsync_len,
+ 			 u32 *sync, u32 *vmode)
+ {
+-    USHORT ModeNo = modeno;
+-    USHORT ModeIdIndex = 0, index = 0;
+-    USHORT RefreshRateTableIndex = 0;
++    unsigned short ModeNo = modeno;
++    unsigned short ModeIdIndex = 0, index = 0;
++    unsigned short RefreshRateTableIndex = 0;
+ 
+     unsigned short VRE, VBE, VRS, VBS, VDE, VT;
+     unsigned short HRE, HBE, HRS, HBS, HDE, HT;
+@@ -377,7 +377,7 @@ XGIfb_mode_rate_to_ddata(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExt
+ 
+ 
+ 
+-void XGIRegInit(VB_DEVICE_INFO *XGI_Pr, ULONG BaseAddr)
++void XGIRegInit(VB_DEVICE_INFO *XGI_Pr, unsigned long BaseAddr)
+ {
+    XGI_Pr->RelIO = BaseAddr;
+    XGI_Pr->P3c4 = BaseAddr + 0x14;
+@@ -415,7 +415,7 @@ u32 XGIfb_get_reg3(u16 port)
+ 
+ /* ------------ Interface for init & mode switching code ------------- */
+ 
+-BOOLEAN
++unsigned char
+ XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
+ 	unsigned long offset, unsigned long set, unsigned long *value)
+ {
+@@ -450,7 +450,7 @@ XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
+ 	return 1;
+ }
+ 
+-/*BOOLEAN XGIfb_query_north_bridge_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
++/*unsigned char XGIfb_query_north_bridge_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
+ 	unsigned long offset, unsigned long set, unsigned long *value)
+ {
+ 	static struct pci_dev *pdev = NULL;
+@@ -937,7 +937,7 @@ static void XGIfb_search_tvstd(const char *name)
+ 	}
+ }
+ 
+-static BOOLEAN XGIfb_bridgeisslave(void)
++static unsigned char XGIfb_bridgeisslave(void)
+ {
+    unsigned char usScratchP1_00;
+ 
+@@ -951,7 +951,7 @@ static BOOLEAN XGIfb_bridgeisslave(void)
+ 	   return 0;
+ }
+ 
+-static BOOLEAN XGIfbcheckvretracecrt1(void)
++static unsigned char XGIfbcheckvretracecrt1(void)
+ {
+    unsigned char temp;
+ 
+@@ -970,7 +970,7 @@ static BOOLEAN XGIfbcheckvretracecrt1(void)
+ 	   return 0;
+ }
+ 
+-static BOOLEAN XGIfbcheckvretracecrt2(void)
++static unsigned char XGIfbcheckvretracecrt2(void)
+ {
+    unsigned char temp;
+    if (xgi_video_info.hasVB == HASVB_NONE)
+@@ -982,7 +982,7 @@ static BOOLEAN XGIfbcheckvretracecrt2(void)
+ 	   return 1;
+ }
+ 
+-static BOOLEAN XGIfb_CheckVBRetrace(void)
++static unsigned char XGIfb_CheckVBRetrace(void)
+ {
+    if(xgi_video_info.disp_state & DISPTYPE_DISP2) {
+       if(XGIfb_bridgeisslave()) {
+@@ -2588,7 +2588,7 @@ static void XGIfb_pre_setmode(void)
+ static void XGIfb_post_setmode(void)
+ {
+ 	u8 reg;
+-	BOOLEAN doit = 1;
++	unsigned char doit = 1;
+ /*	outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
+ 	outXGIIDXREG(XGICR,0x13,0x00);
+ 	setXGIIDXREG(XGISR,0x0E,0xF0,0x01);
+@@ -2826,7 +2826,7 @@ XGIINITSTATIC int __init XGIfb_setup(char *options)
+ 
+ static unsigned char VBIOS_BUF[65535];
+ 
+-unsigned char* attempt_map_rom(struct pci_dev *dev,void *copy_address)
++unsigned char *attempt_map_rom(struct pci_dev *dev, void *copy_address)
+ {
+     u32 rom_size      = 0;
+     u32 rom_address   = 0;
+@@ -2909,7 +2909,7 @@ int __devinit xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	  if (pci_enable_device(pdev))
+ 	          return -EIO;
+ 
+-    XGIRegInit(&XGI_Pr, (ULONG)XGIhw_ext.pjIOAddress);
++    XGIRegInit(&XGI_Pr, (unsigned long)XGIhw_ext.pjIOAddress);
+ 
+     outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
+     inXGIIDXREG(XGISR, IND_XGI_PASSWORD, reg1);
+diff --git a/drivers/staging/xgifb/vb_ext.c b/drivers/staging/xgifb/vb_ext.c
+index 4358d96bad7e..aabab059e5c9 100644
+--- a/drivers/staging/xgifb/vb_ext.c
++++ b/drivers/staging/xgifb/vb_ext.c
+@@ -11,25 +11,30 @@
+ #include "vb_ext.h"
+ extern   UCHAR XGI330_SoftSetting;
+ extern   UCHAR XGI330_OutputSelect;
+-extern   USHORT XGI330_RGBSenseData2;
+-extern   USHORT XGI330_YCSenseData2;
+-extern   USHORT XGI330_VideoSenseData2;
++extern   unsigned short XGI330_RGBSenseData2;
++extern   unsigned short XGI330_YCSenseData2;
++extern   unsigned short XGI330_VideoSenseData2;
+ void     XGI_GetSenseStatus( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo );
+-BOOLEAN  XGINew_GetPanelID(PVB_DEVICE_INFO pVBInfo);
+-USHORT   XGINew_SenseLCD(PXGI_HW_DEVICE_INFO,PVB_DEVICE_INFO pVBInfo);
+-BOOLEAN  XGINew_GetLCDDDCInfo(PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo);
+-void XGISetDPMS( PXGI_HW_DEVICE_INFO pXGIHWDE , ULONG VESA_POWER_STATE ) ;
+-BOOLEAN  XGINew_BridgeIsEnable(PXGI_HW_DEVICE_INFO,PVB_DEVICE_INFO pVBInfo );
+-BOOLEAN  XGINew_Sense(USHORT tempbx,USHORT tempcx, PVB_DEVICE_INFO pVBInfo);
+-BOOLEAN  XGINew_SenseHiTV( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) ;
++unsigned char  XGINew_GetPanelID(PVB_DEVICE_INFO pVBInfo);
++unsigned short XGINew_SenseLCD(PXGI_HW_DEVICE_INFO,
++			       PVB_DEVICE_INFO pVBInfo);
++unsigned char XGINew_GetLCDDDCInfo(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++			     PVB_DEVICE_INFO pVBInfo);
++void XGISetDPMS(PXGI_HW_DEVICE_INFO pXGIHWDE,
++		unsigned long VESA_POWER_STATE);
++unsigned char XGINew_BridgeIsEnable(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
++unsigned char XGINew_Sense(unsigned short tempbx, unsigned short tempcx,
++		     PVB_DEVICE_INFO pVBInfo);
++unsigned char XGINew_SenseHiTV(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++			       PVB_DEVICE_INFO pVBInfo);
+ 
+ /**************************************************************
+ 	Dynamic Sense
+ *************************************************************/
+ 
+ void XGI_WaitDisplay(void);
+-BOOLEAN XGI_Is301C(PVB_DEVICE_INFO);
+-BOOLEAN XGI_Is301LV(PVB_DEVICE_INFO);
++unsigned char XGI_Is301C(PVB_DEVICE_INFO);
++unsigned char XGI_Is301LV(PVB_DEVICE_INFO);
+ 
+ 
+ 
+@@ -39,9 +44,9 @@ BOOLEAN XGI_Is301LV(PVB_DEVICE_INFO);
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-BOOLEAN XGINew_Is301B( PVB_DEVICE_INFO pVBInfo )
++unsigned char XGINew_Is301B(PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT flag ;
++    unsigned short flag ;
+ 
+     flag = XGINew_GetReg1( pVBInfo->Part4Port , 0x01 ) ;
+ 
+@@ -57,7 +62,7 @@ BOOLEAN XGINew_Is301B( PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-BOOLEAN XGI_Is301C( PVB_DEVICE_INFO pVBInfo )
++unsigned char XGI_Is301C(PVB_DEVICE_INFO pVBInfo)
+ {
+     if ( ( XGINew_GetReg1( pVBInfo->Part4Port , 0x01 ) & 0xF0 ) == 0xC0 )
+         return( 1 ) ;
+@@ -78,7 +83,7 @@ BOOLEAN XGI_Is301C( PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-BOOLEAN XGI_Is301LV( PVB_DEVICE_INFO pVBInfo )
++unsigned char XGI_Is301LV(PVB_DEVICE_INFO pVBInfo)
+ {
+     if ( XGINew_GetReg1( pVBInfo->Part4Port , 0x01 ) >= 0xD0 )
+     {
+@@ -97,9 +102,11 @@ BOOLEAN XGI_Is301LV( PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-BOOLEAN XGINew_Sense(  USHORT tempbx , USHORT tempcx, PVB_DEVICE_INFO pVBInfo )
++unsigned char XGINew_Sense(unsigned short tempbx,
++		     unsigned short tempcx,
++		     PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT temp , i , tempch ;
++    unsigned short temp, i, tempch;
+ 
+     temp = tempbx & 0xFF ;
+     XGINew_SetReg1( pVBInfo->Part4Port , 0x11 , temp ) ;
+@@ -128,13 +135,14 @@ BOOLEAN XGINew_Sense(  USHORT tempbx , USHORT tempcx, PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-VOID XGISetDPMS( PXGI_HW_DEVICE_INFO pXGIHWDE , ULONG VESA_POWER_STATE )
++void XGISetDPMS(PXGI_HW_DEVICE_INFO pXGIHWDE,
++		unsigned long VESA_POWER_STATE)
+ {
+-    USHORT ModeNo, ModeIdIndex ;
++    unsigned short ModeNo, ModeIdIndex;
+     UCHAR  temp ;
+     VB_DEVICE_INFO VBINF;
+     PVB_DEVICE_INFO pVBInfo = &VBINF;
+-    pVBInfo->BaseAddr = (ULONG)pXGIHWDE->pjIOAddress ;
++    pVBInfo->BaseAddr = (unsigned long)pXGIHWDE->pjIOAddress ;
+     pVBInfo->ROMAddr  = pXGIHWDE->pjVirtualRomBase ;
+ 
+ 
+@@ -353,10 +361,10 @@ VOID XGISetDPMS( PXGI_HW_DEVICE_INFO pXGIHWDE , ULONG VESA_POWER_STATE )
+ /* --------------------------------------------------------------------- */
+ void XGI_GetSenseStatus( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT tempax = 0 , tempbx , tempcx , temp ,
++    unsigned short tempax = 0 , tempbx , tempcx , temp ,
+            P2reg0 = 0 , SenseModeNo = 0 , OutputSelect = *pVBInfo->pOutputSelect ,
+            ModeIdIndex , i ;
+-    pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
++    pVBInfo->BaseAddr = (unsigned long)HwDeviceExtension->pjIOAddress ;
+ 
+     if ( pVBInfo->IF_DEF_LVDS == 1 )
+     {
+@@ -550,10 +558,11 @@ void XGI_GetSenseStatus( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-USHORT XGINew_SenseLCD( PXGI_HW_DEVICE_INFO HwDeviceExtension ,PVB_DEVICE_INFO pVBInfo)
++unsigned short XGINew_SenseLCD(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++			       PVB_DEVICE_INFO pVBInfo)
+ {
+-    /* USHORT SoftSetting ; */
+-    USHORT temp ;
++    /* unsigned short SoftSetting ; */
++    unsigned short temp ;
+ 
+     if ( ( HwDeviceExtension->jChipType >= XG20 ) || ( HwDeviceExtension->jChipType >= XG40 ) )
+         temp = 0 ;
+@@ -573,9 +582,9 @@ USHORT XGINew_SenseLCD( PXGI_HW_DEVICE_INFO HwDeviceExtension ,PVB_DEVICE_INFO p
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-BOOLEAN XGINew_GetLCDDDCInfo( PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo)
++unsigned char XGINew_GetLCDDDCInfo( PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT temp ;
++    unsigned short temp ;
+ 
+     /* add lcd sense */
+     if ( HwDeviceExtension->ulCRT2LCDType == LCD_UNKNOWN )
+@@ -584,7 +593,7 @@ BOOLEAN XGINew_GetLCDDDCInfo( PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_I
+     }
+     else
+     {
+-        temp = ( USHORT )HwDeviceExtension->ulCRT2LCDType ;
++	    temp = (unsigned short)HwDeviceExtension->ulCRT2LCDType ;
+         switch( HwDeviceExtension->ulCRT2LCDType )
+         {
+             case LCD_INVALID:
+@@ -626,26 +635,27 @@ BOOLEAN XGINew_GetLCDDDCInfo( PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_I
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-BOOLEAN XGINew_GetPanelID(PVB_DEVICE_INFO pVBInfo )
++unsigned char XGINew_GetPanelID(PVB_DEVICE_INFO pVBInfo )
+ {
+-    USHORT PanelTypeTable[ 16 ] = { SyncNN | PanelRGB18Bit | Panel800x600  | _PanelType00 ,
+-                                    SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType01 ,
+-                                    SyncNN | PanelRGB18Bit | Panel800x600  | _PanelType02 ,
+-                                    SyncNN | PanelRGB18Bit | Panel640x480  | _PanelType03 ,
+-                                    SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType04 ,
+-                                    SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType05 ,
+-                                    SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType06 ,
+-                                    SyncNN | PanelRGB24Bit | Panel1024x768 | _PanelType07 ,
+-                                    SyncNN | PanelRGB18Bit | Panel800x600  | _PanelType08 ,
+-                                    SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType09 ,
+-                                    SyncNN | PanelRGB18Bit | Panel800x600  | _PanelType0A ,
+-                                    SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0B ,
+-                                    SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0C ,
+-                                    SyncNN | PanelRGB24Bit | Panel1024x768 | _PanelType0D ,
+-                                    SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0E ,
+-                                    SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0F } ;
+-    USHORT tempax , tempbx , temp ;
+-    /* USHORT return_flag ; */
++	unsigned short PanelTypeTable[16] = {
++		SyncNN | PanelRGB18Bit | Panel800x600  | _PanelType00,
++		SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType01,
++		SyncNN | PanelRGB18Bit | Panel800x600  | _PanelType02,
++		SyncNN | PanelRGB18Bit | Panel640x480  | _PanelType03,
++		SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType04,
++		SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType05,
++		SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType06,
++		SyncNN | PanelRGB24Bit | Panel1024x768 | _PanelType07,
++		SyncNN | PanelRGB18Bit | Panel800x600  | _PanelType08,
++		SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType09,
++		SyncNN | PanelRGB18Bit | Panel800x600  | _PanelType0A,
++		SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0B,
++		SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0C,
++		SyncNN | PanelRGB24Bit | Panel1024x768 | _PanelType0D,
++		SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0E,
++		SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0F };
++	unsigned short tempax , tempbx, temp;
++    /* unsigned short return_flag ; */
+ 
+     tempax = XGINew_GetReg1( pVBInfo->P3c4 , 0x1A ) ;
+     tempbx = tempax & 0x1E ;
+@@ -698,9 +708,9 @@ BOOLEAN XGINew_GetPanelID(PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-BOOLEAN XGINew_BridgeIsEnable( PXGI_HW_DEVICE_INFO HwDeviceExtension ,PVB_DEVICE_INFO pVBInfo)
++unsigned char XGINew_BridgeIsEnable( PXGI_HW_DEVICE_INFO HwDeviceExtension ,PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT flag ;
++    unsigned short flag ;
+ 
+     if ( XGI_BridgeIsOn( pVBInfo ) == 0 )
+     {
+@@ -725,9 +735,9 @@ BOOLEAN XGINew_BridgeIsEnable( PXGI_HW_DEVICE_INFO HwDeviceExtension ,PVB_DEVICE
+ /* Output : */
+ /* Description : */
+ /* ------------------------------------------------------ */
+-BOOLEAN XGINew_SenseHiTV( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo )
++unsigned char XGINew_SenseHiTV( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo )
+ {
+-    USHORT tempbx , tempcx , temp , i , tempch;
++    unsigned short tempbx , tempcx , temp , i , tempch;
+ 
+     tempbx = *pVBInfo->pYCSenseData2 ;
+ 
+@@ -809,11 +819,11 @@ BOOLEAN XGINew_SenseHiTV( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INF
+ void XGI_XG21Fun14Sub70( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
+ {
+ 
+-    USHORT ModeIdIndex;
+-    USHORT ModeNo;
++    unsigned short ModeIdIndex;
++    unsigned short ModeNo;
+ 
+-    USHORT EModeCount;
+-    USHORT lvdstableindex;
++    unsigned short EModeCount;
++    unsigned short lvdstableindex;
+ 
+     lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo );
+     pBiosArguments->h.bl = 0x81;
+@@ -852,10 +862,10 @@ void XGI_XG21Fun14Sub70( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
+ void XGI_XG21Fun14Sub71( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
+ {
+ 
+-    USHORT EModeCount;
+-    USHORT ModeIdIndex,resindex;
+-    USHORT ModeNo;
+-    USHORT EModeIndex = pBiosArguments->h.bh;
++    unsigned short EModeCount;
++    unsigned short ModeIdIndex, resindex;
++    unsigned short ModeNo;
++    unsigned short EModeIndex = pBiosArguments->h.bh;
+ 
+     EModeCount = 0;
+     for( ModeIdIndex = 0 ; ;  ModeIdIndex ++ )
+@@ -897,8 +907,8 @@ void XGI_XG21Fun14Sub71( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
+ */
+ void XGI_XG21Fun14Sub72( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
+ {
+-    USHORT ModeIdIndex,resindex;
+-    USHORT ModeNo;
++    unsigned short ModeIdIndex, resindex;
++    unsigned short ModeNo;
+ 
+ 
+     ModeNo = pBiosArguments->h.bl ;
+@@ -958,7 +968,7 @@ void XGI_XG21Fun14Sub73( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
+ {
+     UCHAR Select;
+ 
+-    USHORT lvdstableindex;
++    unsigned short lvdstableindex;
+ 
+     lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo );
+     Select = pBiosArguments->h.bl;
+diff --git a/drivers/staging/xgifb/vb_ext.h b/drivers/staging/xgifb/vb_ext.h
+index 3a52a6a93bd5..5cb1862d9542 100644
+--- a/drivers/staging/xgifb/vb_ext.h
++++ b/drivers/staging/xgifb/vb_ext.h
+@@ -2,11 +2,12 @@
+ #define  _VBEXT_
+ 
+ struct DWORDREGS {
+-    ULONG    Eax, Ebx, Ecx, Edx, Esi, Edi, Ebp;
++    unsigned long    Eax, Ebx, Ecx, Edx, Esi, Edi, Ebp;
+ };
+ 
+ struct WORDREGS {
+-    USHORT    ax, hi_ax, bx, hi_bx, cx, hi_cx, dx, hi_dx, si, hi_si, di ,hi_di, bp, hi_bp;
++    unsigned short ax, hi_ax, bx, hi_bx, cx, hi_cx, dx, hi_dx, si,
++	    hi_si, di, hi_di, bp, hi_bp;
+ };
+ 
+ struct BYTEREGS {
+@@ -20,10 +21,12 @@ typedef union   _X86_REGS    {
+ } X86_REGS, *PX86_REGS;
+ 
+ extern   void     XGI_XG21Fun14( PXGI_HW_DEVICE_INFO pXGIHWDE, PX86_REGS pBiosArguments);
+-extern   void     XGISetDPMS( PXGI_HW_DEVICE_INFO pXGIHWDE , ULONG VESA_POWER_STATE ) ;
++extern void XGISetDPMS(PXGI_HW_DEVICE_INFO pXGIHWDE,
++		       unsigned long VESA_POWER_STATE);
+ extern   void     XGI_GetSenseStatus( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo );
+ extern   void     XGINew_SetModeScratch ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) ;
+ extern   void 	  ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo);
+-extern   USHORT   XGINew_SenseLCD(PXGI_HW_DEVICE_INFO,PVB_DEVICE_INFO pVBInfo);
++extern unsigned short XGINew_SenseLCD(PXGI_HW_DEVICE_INFO,
++				      PVB_DEVICE_INFO pVBInfo);
+ 
+ #endif
+diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
+index 2abdd24ef52b..3f0e34bd0d05 100644
+--- a/drivers/staging/xgifb/vb_init.c
++++ b/drivers/staging/xgifb/vb_init.c
+@@ -20,71 +20,67 @@
+ 
+ UCHAR    XGINew_ChannelAB,XGINew_DataBusWidth;
+ 
+-USHORT XGINew_DRAMType[17][5]={{0x0C,0x0A,0x02,0x40,0x39},{0x0D,0x0A,0x01,0x40,0x48},
+-                     {0x0C,0x09,0x02,0x20,0x35},{0x0D,0x09,0x01,0x20,0x44},
+-                     {0x0C,0x08,0x02,0x10,0x31},{0x0D,0x08,0x01,0x10,0x40},
+-                     {0x0C,0x0A,0x01,0x20,0x34},{0x0C,0x09,0x01,0x08,0x32},
+-                     {0x0B,0x08,0x02,0x08,0x21},{0x0C,0x08,0x01,0x08,0x30},
+-                     {0x0A,0x08,0x02,0x04,0x11},{0x0B,0x0A,0x01,0x10,0x28},
+-                     {0x09,0x08,0x02,0x02,0x01},{0x0B,0x09,0x01,0x08,0x24},
+-                     {0x0B,0x08,0x01,0x04,0x20},{0x0A,0x08,0x01,0x02,0x10},
+-                     {0x09,0x08,0x01,0x01,0x00}};
+-
+-USHORT XGINew_SDRDRAM_TYPE[13][5]=
+-{
+-{ 2,12, 9,64,0x35},
+-{ 1,13, 9,64,0x44},
+-{ 2,12, 8,32,0x31},
+-{ 2,11, 9,32,0x25},
+-{ 1,12, 9,32,0x34},
+-{ 1,13, 8,32,0x40},
+-{ 2,11, 8,16,0x21},
+-{ 1,12, 8,16,0x30},
+-{ 1,11, 9,16,0x24},
+-{ 1,11, 8, 8,0x20},
+-{ 2, 9, 8, 4,0x01},
+-{ 1,10, 8, 4,0x10},
+-{ 1, 9, 8, 2,0x00}
+-};
+-
+-USHORT XGINew_DDRDRAM_TYPE[4][5]=
+-{
+-{ 2,12, 9,64,0x35},
+-{ 2,12, 8,32,0x31},
+-{ 2,11, 8,16,0x21},
+-{ 2, 9, 8, 4,0x01}
+-};
+-USHORT XGINew_DDRDRAM_TYPE340[4][5]=
+-{
+-{ 2,13, 9,64,0x45},
+-{ 2,12, 9,32,0x35},
+-{ 2,12, 8,16,0x31},
+-{ 2,11, 8, 8,0x21}
+-};
+-USHORT XGINew_DDRDRAM_TYPE20[12][5]=
+-{
+-{ 2,14,11,128,0x5D},
+-{ 2,14,10,64,0x59},
+-{ 2,13,11,64,0x4D},
+-{ 2,14, 9,32,0x55},
+-{ 2,13,10,32,0x49},
+-{ 2,12,11,32,0x3D},
+-{ 2,14, 8,16,0x51},
+-{ 2,13, 9,16,0x45},
+-{ 2,12,10,16,0x39},
+-{ 2,13, 8, 8,0x41},
+-{ 2,12, 9, 8,0x35},
+-{ 2,12, 8, 4,0x31}
+-};
++unsigned short XGINew_DRAMType[17][5] = {
++	{0x0C, 0x0A, 0x02, 0x40, 0x39}, {0x0D, 0x0A, 0x01, 0x40, 0x48},
++	{0x0C, 0x09, 0x02, 0x20, 0x35}, {0x0D, 0x09, 0x01, 0x20, 0x44},
++	{0x0C, 0x08, 0x02, 0x10, 0x31}, {0x0D, 0x08, 0x01, 0x10, 0x40},
++	{0x0C, 0x0A, 0x01, 0x20, 0x34}, {0x0C, 0x09, 0x01, 0x08, 0x32},
++	{0x0B, 0x08, 0x02, 0x08, 0x21}, {0x0C, 0x08, 0x01, 0x08, 0x30},
++	{0x0A, 0x08, 0x02, 0x04, 0x11}, {0x0B, 0x0A, 0x01, 0x10, 0x28},
++	{0x09, 0x08, 0x02, 0x02, 0x01}, {0x0B, 0x09, 0x01, 0x08, 0x24},
++	{0x0B, 0x08, 0x01, 0x04, 0x20}, {0x0A, 0x08, 0x01, 0x02, 0x10},
++	{0x09, 0x08, 0x01, 0x01, 0x00} };
++
++unsigned short XGINew_SDRDRAM_TYPE[13][5] = {
++	{ 2, 12, 9, 64, 0x35},
++	{ 1, 13, 9, 64, 0x44},
++	{ 2, 12, 8, 32, 0x31},
++	{ 2, 11, 9, 32, 0x25},
++	{ 1, 12, 9, 32, 0x34},
++	{ 1, 13, 8, 32, 0x40},
++	{ 2, 11, 8, 16, 0x21},
++	{ 1, 12, 8, 16, 0x30},
++	{ 1, 11, 9, 16, 0x24},
++	{ 1, 11, 8,  8, 0x20},
++	{ 2,  9, 8,  4, 0x01},
++	{ 1, 10, 8,  4, 0x10},
++	{ 1,  9, 8,  2, 0x00} };
++
++unsigned short XGINew_DDRDRAM_TYPE[4][5] = {
++	{ 2, 12, 9, 64, 0x35},
++	{ 2, 12, 8, 32, 0x31},
++	{ 2, 11, 8, 16, 0x21},
++	{ 2,  9, 8,  4, 0x01} };
++
++unsigned short XGINew_DDRDRAM_TYPE340[4][5] = {
++	{ 2, 13, 9, 64, 0x45},
++	{ 2, 12, 9, 32, 0x35},
++	{ 2, 12, 8, 16, 0x31},
++	{ 2, 11, 8,  8, 0x21} };
++
++unsigned short XGINew_DDRDRAM_TYPE20[12][5] = {
++	{ 2, 14, 11, 128, 0x5D},
++	{ 2, 14, 10, 64, 0x59},
++	{ 2, 13, 11, 64, 0x4D},
++	{ 2, 14,  9, 32, 0x55},
++	{ 2, 13, 10, 32, 0x49},
++	{ 2, 12, 11, 32, 0x3D},
++	{ 2, 14,  8, 16, 0x51},
++	{ 2, 13,  9, 16, 0x45},
++	{ 2, 12, 10, 16, 0x39},
++	{ 2, 13,  8,  8, 0x41},
++	{ 2, 12,  9,  8, 0x35},
++	{ 2, 12,  8,  4, 0x31} };
+ 
+ void     XGINew_SetDRAMSize_340(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO);
+ void     XGINew_SetDRAMSize_310(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO);
+ void     XGINew_SetMemoryClock(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+ void     XGINew_SetDRAMModeRegister(PVB_DEVICE_INFO );
+ void     XGINew_SetDRAMModeRegister340( PXGI_HW_DEVICE_INFO HwDeviceExtension );
+-void 	 XGINew_SetDRAMDefaultRegister340(PXGI_HW_DEVICE_INFO HwDeviceExtension, ULONG, PVB_DEVICE_INFO );
++void XGINew_SetDRAMDefaultRegister340(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++				      unsigned long, PVB_DEVICE_INFO);
+ UCHAR    XGINew_GetXG20DRAMType( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo);
+-BOOLEAN  XGIInitNew( PXGI_HW_DEVICE_INFO HwDeviceExtension) ;
++unsigned char  XGIInitNew( PXGI_HW_DEVICE_INFO HwDeviceExtension) ;
+ 
+ int      XGINew_DDRSizing340( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO );
+ void     XGINew_DisableRefresh( PXGI_HW_DEVICE_INFO ,PVB_DEVICE_INFO) ;
+@@ -93,12 +89,13 @@ int      XGINew_SDRSizing(PVB_DEVICE_INFO);
+ int      XGINew_DDRSizing( PVB_DEVICE_INFO );
+ void     XGINew_EnableRefresh( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO);
+ int      XGINew_RAMType;                  /*int      ModeIDOffset,StandTable,CRT1Table,ScreenOffset,REFIndex;*/
+-ULONG	 UNIROM;			  /* UNIROM */
+-BOOLEAN  ChkLFB( PVB_DEVICE_INFO );
+-void     XGINew_Delay15us(ULONG);
+-void     SetPowerConsume (PXGI_HW_DEVICE_INFO HwDeviceExtension,ULONG XGI_P3d4Port);
++unsigned long	 UNIROM;			  /* UNIROM */
++unsigned char  ChkLFB( PVB_DEVICE_INFO );
++void     XGINew_Delay15us(unsigned long);
++void     SetPowerConsume(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++			 unsigned long XGI_P3d4Port);
+ void 	 ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo);
+-void 	 XGINew_DDR1x_MRS_XG20( ULONG P3c4 , PVB_DEVICE_INFO pVBInfo);
++void     XGINew_DDR1x_MRS_XG20(unsigned long P3c4, PVB_DEVICE_INFO pVBInfo);
+ void     XGINew_SetDRAMModeRegister_XG20( PXGI_HW_DEVICE_INFO HwDeviceExtension );
+ void     XGINew_SetDRAMModeRegister_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension );
+ void 	 XGINew_ChkSenseStatus ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) ;
+@@ -108,7 +105,7 @@ UCHAR    GetXG21FPBits(PVB_DEVICE_INFO pVBInfo);
+ void     XGINew_GetXG27Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) ;
+ UCHAR    GetXG27FPBits(PVB_DEVICE_INFO pVBInfo);
+ 
+-void DelayUS(ULONG MicroSeconds)
++void DelayUS(unsigned long MicroSeconds)
+ {
+ 	udelay(MicroSeconds);
+ }
+@@ -120,7 +117,7 @@ void DelayUS(ULONG MicroSeconds)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-BOOLEAN XGIInitNew( PXGI_HW_DEVICE_INFO HwDeviceExtension )
++unsigned char XGIInitNew( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+ {
+ 
+     VB_DEVICE_INFO VBINF;
+@@ -129,17 +126,17 @@ BOOLEAN XGIInitNew( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+      //       VBIOSVersion[ 5 ] ;
+     volatile unsigned char *pVideoMemory;
+ 
+-    /* ULONG j, k ; */
++    /* unsigned long j, k ; */
+ 
+     PXGI_DSReg pSR ;
+ 
+-    ULONG Temp ;
++    unsigned long Temp ;
+ 
+     pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+ 
+     pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+ 
+-    pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
++    pVBInfo->BaseAddr = (unsigned long)HwDeviceExtension->pjIOAddress ;
+ 
+     pVideoMemory = (unsigned char *)pVBInfo->ROMAddr;
+ 
+@@ -642,7 +639,7 @@ UCHAR XGINew_Get310DRAMType(PVB_DEVICE_INFO pVBInfo)
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ /*
+-void XGINew_Delay15us(ULONG ulMicrsoSec)
++void XGINew_Delay15us(unsigned long ulMicrsoSec)
+ {
+ }
+ */
+@@ -656,7 +653,7 @@ void XGINew_Delay15us(ULONG ulMicrsoSec)
+ /* --------------------------------------------------------------------- */
+ void XGINew_SDR_MRS(  PVB_DEVICE_INFO pVBInfo )
+ {
+-    USHORT data ;
++    unsigned short data ;
+ 
+     data = XGINew_GetReg1( pVBInfo->P3c4 , 0x16 ) ;
+     data &= 0x3F ;          /* SR16 D7=0,D6=0 */
+@@ -674,7 +671,7 @@ void XGINew_SDR_MRS(  PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_DDR1x_MRS_340( ULONG P3c4 , PVB_DEVICE_INFO pVBInfo)
++void XGINew_DDR1x_MRS_340(unsigned long P3c4 , PVB_DEVICE_INFO pVBInfo)
+ {
+     XGINew_SetReg1( P3c4 , 0x18 , 0x01 ) ;
+     XGINew_SetReg1( P3c4 , 0x19 , 0x20 ) ;
+@@ -712,7 +709,7 @@ void XGINew_DDR1x_MRS_340( ULONG P3c4 , PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_DDR2x_MRS_340( ULONG P3c4 , PVB_DEVICE_INFO pVBInfo)
++void XGINew_DDR2x_MRS_340(unsigned long P3c4 , PVB_DEVICE_INFO pVBInfo)
+ {
+     XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ;
+     XGINew_SetReg1( P3c4 , 0x19 , 0x20 ) ;
+@@ -741,9 +738,10 @@ void XGINew_DDR2x_MRS_340( ULONG P3c4 , PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_DDRII_Bootup_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension ,  ULONG P3c4 , PVB_DEVICE_INFO pVBInfo)
++void XGINew_DDRII_Bootup_XG27(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++			      unsigned long P3c4, PVB_DEVICE_INFO pVBInfo)
+ {
+-    ULONG P3d4 = P3c4 + 0x10 ;
++    unsigned long P3d4 = P3c4 + 0x10 ;
+     XGINew_RAMType = ( int )XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo ) ;
+     XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ;
+ 
+@@ -819,9 +817,10 @@ void XGINew_DDRII_Bootup_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension ,  ULONG P3
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_DDR2_MRS_XG20( PXGI_HW_DEVICE_INFO HwDeviceExtension ,  ULONG P3c4 , PVB_DEVICE_INFO pVBInfo)
++void XGINew_DDR2_MRS_XG20(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++			  unsigned long P3c4, PVB_DEVICE_INFO pVBInfo)
+ {
+-    ULONG P3d4 = P3c4 + 0x10 ;
++    unsigned long P3d4 = P3c4 + 0x10 ;
+ 
+     XGINew_RAMType = ( int )XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo ) ;
+     XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ;
+@@ -871,9 +870,10 @@ void XGINew_DDR2_MRS_XG20( PXGI_HW_DEVICE_INFO HwDeviceExtension ,  ULONG P3c4 ,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_DDR2_MRS_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension ,  ULONG P3c4 , PVB_DEVICE_INFO pVBInfo)
++void XGINew_DDR2_MRS_XG27(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++			  unsigned long P3c4, PVB_DEVICE_INFO pVBInfo)
+ {
+-    ULONG P3d4 = P3c4 + 0x10 ;
++    unsigned long P3d4 = P3c4 + 0x10 ;
+ 
+      XGINew_RAMType = ( int )XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo ) ;
+      XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ;
+@@ -949,9 +949,10 @@ void XGINew_DDR2_MRS_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension ,  ULONG P3c4 ,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_DDR1x_DefaultRegister( PXGI_HW_DEVICE_INFO HwDeviceExtension ,  ULONG Port , PVB_DEVICE_INFO pVBInfo)
++void XGINew_DDR1x_DefaultRegister(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++				  unsigned long Port, PVB_DEVICE_INFO pVBInfo)
+ {
+-    ULONG P3d4 = Port ,
++    unsigned long P3d4 = Port ,
+            P3c4 = Port - 0x10 ;
+ 
+     if ( HwDeviceExtension->jChipType >= XG20 )
+@@ -1009,9 +1010,10 @@ void XGINew_DDR1x_DefaultRegister( PXGI_HW_DEVICE_INFO HwDeviceExtension ,  ULON
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_DDR2x_DefaultRegister( PXGI_HW_DEVICE_INFO HwDeviceExtension ,  ULONG Port ,PVB_DEVICE_INFO pVBInfo)
++void XGINew_DDR2x_DefaultRegister(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++				  unsigned long Port, PVB_DEVICE_INFO pVBInfo)
+ {
+-    ULONG P3d4 = Port ,
++    unsigned long P3d4 = Port ,
+            P3c4 = Port - 0x10 ;
+ 
+     XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ;
+@@ -1060,9 +1062,10 @@ void XGINew_DDR2x_DefaultRegister( PXGI_HW_DEVICE_INFO HwDeviceExtension ,  ULON
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_DDR2_DefaultRegister( PXGI_HW_DEVICE_INFO HwDeviceExtension, ULONG Port , PVB_DEVICE_INFO pVBInfo)
++void XGINew_DDR2_DefaultRegister(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++				 unsigned long Port, PVB_DEVICE_INFO pVBInfo)
+ {
+-    ULONG P3d4 = Port ,
++    unsigned long P3d4 = Port ,
+            P3c4 = Port - 0x10 ;
+ 
+     /* keep following setting sequence, each setting in the same reg insert idle */
+@@ -1098,12 +1101,13 @@ void XGINew_DDR2_DefaultRegister( PXGI_HW_DEVICE_INFO HwDeviceExtension, ULONG P
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_SetDRAMDefaultRegister340( PXGI_HW_DEVICE_INFO HwDeviceExtension ,  ULONG Port , PVB_DEVICE_INFO pVBInfo)
++void XGINew_SetDRAMDefaultRegister340(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++				      unsigned long Port, PVB_DEVICE_INFO pVBInfo)
+ {
+     UCHAR temp , temp1 , temp2 , temp3 ,
+           i , j , k ;
+ 
+-    ULONG P3d4 = Port ,
++    unsigned long P3d4 = Port ,
+            P3c4 = Port - 0x10 ;
+ 
+     XGINew_SetReg1( P3d4 , 0x6D , pVBInfo->CR40[ 8 ][ XGINew_RAMType ] ) ;
+@@ -1243,7 +1247,7 @@ void XGINew_SetDRAMDefaultRegister340( PXGI_HW_DEVICE_INFO HwDeviceExtension ,
+ /* --------------------------------------------------------------------- */
+ void XGINew_DDR_MRS(PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT data ;
++    unsigned short data ;
+ 
+     volatile unsigned char *pVideoMemory = (unsigned char *)pVBInfo->ROMAddr;
+ 
+@@ -1313,7 +1317,7 @@ void XGINew_VerifyMclk( PXGI_HW_DEVICE_INFO  HwDeviceExtension , PVB_DEVICE_INFO
+ {
+     unsigned char *pVideoMemory = pVBInfo->FBAddr ;
+     UCHAR i , j ;
+-    USHORT Temp , SR21 ;
++    unsigned short Temp , SR21 ;
+ 
+     pVideoMemory[ 0 ] = 0xaa ; 		/* alan */
+     pVideoMemory[ 16 ] = 0x55 ; 	/* note: PCI read cache is off */
+@@ -1357,7 +1361,7 @@ void XGINew_VerifyMclk( PXGI_HW_DEVICE_INFO  HwDeviceExtension , PVB_DEVICE_INFO
+ /* --------------------------------------------------------------------- */
+ void XGINew_SetDRAMSize_340( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT  data ;
++    unsigned short  data ;
+ 
+     pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+     pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+@@ -1366,7 +1370,7 @@ void XGINew_SetDRAMSize_340( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_
+ 
+ 
+     data = XGINew_GetReg1( pVBInfo->P3c4 , 0x21 ) ;
+-    XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , ( USHORT )( data & 0xDF ) ) ;	/* disable read cache */
++    XGINew_SetReg1(pVBInfo->P3c4, 0x21, (unsigned short)(data & 0xDF));	/* disable read cache */
+     XGI_DisplayOff( HwDeviceExtension, pVBInfo );
+ 
+     /*data = XGINew_GetReg1( pVBInfo->P3c4 , 0x1 ) ;*/
+@@ -1374,8 +1378,7 @@ void XGINew_SetDRAMSize_340( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_
+     /*XGINew_SetReg1( pVBInfo->P3c4 , 0x01 , data ) ;*/			/* Turn OFF Display */
+     XGINew_DDRSizing340( HwDeviceExtension, pVBInfo ) ;
+     data=XGINew_GetReg1( pVBInfo->P3c4 , 0x21 ) ;
+-    XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , ( USHORT )( data | 0x20 ) ) ;	/* enable read cache */
+-
++    XGINew_SetReg1(pVBInfo->P3c4, 0x21, (unsigned short)(data | 0x20)); /* enable read cache */
+ }
+ 
+ 
+@@ -1387,7 +1390,7 @@ void XGINew_SetDRAMSize_340( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_
+ /* --------------------------------------------------------------------- */
+ void XGINew_SetDRAMSize_310( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT data ;
++    unsigned short data ;
+     pVBInfo->ROMAddr  = HwDeviceExtension->pjVirtualRomBase ,
+     pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+ #ifdef XGI301
+@@ -1403,7 +1406,7 @@ void XGINew_SetDRAMSize_310( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_
+     XGISetModeNew( HwDeviceExtension , 0x2e ) ;
+ 
+     data = XGINew_GetReg1( pVBInfo->P3c4 , 0x21 ) ;
+-    XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , ( USHORT )( data & 0xDF ) ) ;	/* disable read cache */
++    XGINew_SetReg1(pVBInfo->P3c4, 0x21, (unsigned short)(data & 0xDF));	/* disable read cache */
+ 
+     data = XGINew_GetReg1( pVBInfo->P3c4 , 0x1 ) ;
+     data |= 0x20 ;
+@@ -1412,7 +1415,7 @@ void XGINew_SetDRAMSize_310( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_
+     data = XGINew_GetReg1( pVBInfo->P3c4 , 0x16 ) ;
+ 
+ 
+-    XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , ( USHORT )( data | 0x0F ) ) ;		/* assume lowest speed DRAM */
++    XGINew_SetReg1(pVBInfo->P3c4, 0x16, (unsigned short)(data | 0x0F));	/* assume lowest speed DRAM */
+ 
+     XGINew_SetDRAMModeRegister( pVBInfo ) ;
+     XGINew_DisableRefresh( HwDeviceExtension, pVBInfo ) ;
+@@ -1433,11 +1436,11 @@ void XGINew_SetDRAMSize_310( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_
+ 
+ 
+ 
+-    XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , pVBInfo->SR15[ 1 ][ XGINew_RAMType ] ) ;	/* restore SR16 */
++    XGINew_SetReg1(pVBInfo->P3c4, 0x16, pVBInfo->SR15[1][XGINew_RAMType]); /* restore SR16 */
+ 
+     XGINew_EnableRefresh(  HwDeviceExtension, pVBInfo ) ;
+     data=XGINew_GetReg1( pVBInfo->P3c4 ,0x21 ) ;
+-    XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , ( USHORT )( data | 0x20 ) ) ;	/* enable read cache */
++    XGINew_SetReg1(pVBInfo->P3c4, 0x21, (unsigned short)(data | 0x20));	/* enable read cache */
+ }
+ 
+ 
+@@ -1456,7 +1459,7 @@ void XGINew_SetDRAMModeRegister340( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+     PVB_DEVICE_INFO pVBInfo = &VBINF;
+     pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+     pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+-    pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
++    pVBInfo->BaseAddr = (unsigned long)HwDeviceExtension->pjIOAddress ;
+     pVBInfo->ISXPDOS = 0 ;
+ 
+     pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
+@@ -1525,7 +1528,7 @@ void XGINew_SetDRAMModeRegister( PVB_DEVICE_INFO pVBInfo)
+ /* --------------------------------------------------------------------- */
+ void XGINew_DisableRefresh( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT  data ;
++    unsigned short  data ;
+ 
+ 
+     data = XGINew_GetReg1( pVBInfo->P3c4 , 0x1B ) ;
+@@ -1556,9 +1559,11 @@ void XGINew_EnableRefresh( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_IN
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_DisableChannelInterleaving( int index , USHORT XGINew_DDRDRAM_TYPE[][ 5 ] , PVB_DEVICE_INFO pVBInfo)
++void XGINew_DisableChannelInterleaving(int index,
++				       unsigned short XGINew_DDRDRAM_TYPE[][5],
++				       PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT data ;
++    unsigned short data ;
+ 
+     data = XGINew_GetReg1( pVBInfo->P3c4 , 0x15 ) ;
+     data &= 0x1F ;
+@@ -1590,9 +1595,11 @@ void XGINew_DisableChannelInterleaving( int index , USHORT XGINew_DDRDRAM_TYPE[]
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_SetDRAMSizingType( int index , USHORT DRAMTYPE_TABLE[][ 5 ] ,PVB_DEVICE_INFO pVBInfo)
++void XGINew_SetDRAMSizingType(int index,
++			      unsigned short DRAMTYPE_TABLE[][5],
++			      PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT data ;
++    unsigned short data;
+ 
+     data = DRAMTYPE_TABLE[ index ][ 4 ] ;
+     XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x13 , 0x80 , data ) ;
+@@ -1609,7 +1616,7 @@ void XGINew_SetDRAMSizingType( int index , USHORT DRAMTYPE_TABLE[][ 5 ] ,PVB_DEV
+ /* --------------------------------------------------------------------- */
+ void XGINew_CheckBusWidth_310(  PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT data ;
++    unsigned short data ;
+     volatile unsigned long *pVideoMemory ;
+ 
+     pVideoMemory = (unsigned long *) pVBInfo->FBAddr;
+@@ -1638,7 +1645,7 @@ void XGINew_CheckBusWidth_310(  PVB_DEVICE_INFO pVBInfo)
+             XGINew_DataBusWidth = 64 ;
+             XGINew_ChannelAB = 0 ;
+             data=XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) ;
+-            XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , ( USHORT )( data & 0xFD ) ) ;
++	    XGINew_SetReg1(pVBInfo->P3c4, 0x14, (unsigned short)(data & 0xFD));
+         }
+ 
+         if ( ( pVideoMemory[ 1 ] != 0x456789ABL ) || ( pVideoMemory[ 0 ] != 0x01234567L ) )
+@@ -1647,7 +1654,8 @@ void XGINew_CheckBusWidth_310(  PVB_DEVICE_INFO pVBInfo)
+             XGINew_DataBusWidth = 64 ;
+             XGINew_ChannelAB = 1 ;
+             data=XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) ;
+-            XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , ( USHORT )( ( data & 0xFD ) | 0x01 ) ) ;
++	    XGINew_SetReg1(pVBInfo->P3c4, 0x14,
++			   (unsigned short)((data & 0xFD) | 0x01));
+         }
+ 
+         return ;
+@@ -1740,9 +1748,13 @@ void XGINew_CheckBusWidth_310(  PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-int XGINew_SetRank( int index , UCHAR RankNo , UCHAR XGINew_ChannelAB , USHORT DRAMTYPE_TABLE[][ 5 ] , PVB_DEVICE_INFO pVBInfo)
++int XGINew_SetRank(int index,
++		   UCHAR RankNo,
++		   UCHAR XGINew_ChannelAB,
++		   unsigned short DRAMTYPE_TABLE[][5],
++		   PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT data ;
++    unsigned short data;
+     int RankSize ;
+ 
+     if ( ( RankNo == 2 ) && ( DRAMTYPE_TABLE[ index ][ 0 ] == 2 ) )
+@@ -1777,9 +1789,13 @@ int XGINew_SetRank( int index , UCHAR RankNo , UCHAR XGINew_ChannelAB , USHORT D
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-int XGINew_SetDDRChannel( int index , UCHAR ChannelNo , UCHAR XGINew_ChannelAB , USHORT DRAMTYPE_TABLE[][ 5 ] , PVB_DEVICE_INFO pVBInfo)
++int XGINew_SetDDRChannel(int index,
++			 UCHAR ChannelNo,
++			 UCHAR XGINew_ChannelAB,
++			 unsigned short DRAMTYPE_TABLE[][5],
++			 PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT  data ;
++    unsigned short data;
+     int RankSize ;
+ 
+     RankSize = DRAMTYPE_TABLE[index][3]/2 * XGINew_DataBusWidth/32;
+@@ -1813,10 +1829,12 @@ int XGINew_SetDDRChannel( int index , UCHAR ChannelNo , UCHAR XGINew_ChannelAB ,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-int XGINew_CheckColumn( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
++int XGINew_CheckColumn(int index,
++		       unsigned short DRAMTYPE_TABLE[][5],
++		       PVB_DEVICE_INFO pVBInfo)
+ {
+     int i ;
+-    ULONG Increment , Position ;
++    unsigned long Increment , Position ;
+ 
+     /* Increment = 1 << ( DRAMTYPE_TABLE[ index ][ 2 ] + XGINew_DataBusWidth / 64 + 1 ) ; */
+     Increment = 1 << ( 10 + XGINew_DataBusWidth / 64 ) ;
+@@ -1845,10 +1863,12 @@ int XGINew_CheckColumn( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INF
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-int XGINew_CheckBanks( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
++int XGINew_CheckBanks(int index,
++		      unsigned short DRAMTYPE_TABLE[][5],
++		      PVB_DEVICE_INFO pVBInfo)
+ {
+     int i ;
+-    ULONG Increment , Position ;
++    unsigned long Increment , Position ;
+ 
+     Increment = 1 << ( DRAMTYPE_TABLE[ index ][ 2 ] + XGINew_DataBusWidth / 64 + 2 ) ;
+ 
+@@ -1876,10 +1896,12 @@ int XGINew_CheckBanks( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-int XGINew_CheckRank( int RankNo , int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
++int XGINew_CheckRank(int RankNo, int index,
++		     unsigned short DRAMTYPE_TABLE[][5],
++		     PVB_DEVICE_INFO pVBInfo)
+ {
+     int i ;
+-    ULONG Increment , Position ;
++    unsigned long Increment , Position ;
+ 
+     Increment = 1 << ( DRAMTYPE_TABLE[ index ][ 2 ] + DRAMTYPE_TABLE[ index ][ 1 ] +
+                   DRAMTYPE_TABLE[ index ][ 0 ] + XGINew_DataBusWidth / 64 + RankNo ) ;
+@@ -1910,10 +1932,12 @@ int XGINew_CheckRank( int RankNo , int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-int XGINew_CheckDDRRank( int RankNo , int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
++int XGINew_CheckDDRRank(int RankNo, int index,
++			unsigned short DRAMTYPE_TABLE[][5],
++			PVB_DEVICE_INFO pVBInfo)
+ {
+-    ULONG Increment , Position ;
+-    USHORT data ;
++    unsigned long Increment , Position ;
++    unsigned short data ;
+ 
+     Increment = 1 << ( DRAMTYPE_TABLE[ index ][ 2 ] + DRAMTYPE_TABLE[ index ][ 1 ] +
+                        DRAMTYPE_TABLE[ index ][ 0 ] + XGINew_DataBusWidth / 64 + RankNo ) ;
+@@ -1952,7 +1976,9 @@ int XGINew_CheckDDRRank( int RankNo , int index , USHORT DRAMTYPE_TABLE[][ 5 ],
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-int XGINew_CheckRanks( int RankNo , int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
++int XGINew_CheckRanks(int RankNo, int index,
++		      unsigned short DRAMTYPE_TABLE[][5],
++		      PVB_DEVICE_INFO pVBInfo)
+ {
+     int r ;
+ 
+@@ -1978,7 +2004,9 @@ int XGINew_CheckRanks( int RankNo , int index , USHORT DRAMTYPE_TABLE[][ 5 ], PV
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-int XGINew_CheckDDRRanks( int RankNo , int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
++int XGINew_CheckDDRRanks(int RankNo, int index,
++			 unsigned short DRAMTYPE_TABLE[][5],
++			 PVB_DEVICE_INFO pVBInfo)
+ {
+     int r ;
+ 
+@@ -2034,9 +2062,11 @@ int XGINew_SDRSizing(PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-USHORT XGINew_SetDRAMSizeReg( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
++unsigned short XGINew_SetDRAMSizeReg(int index,
++				     unsigned short DRAMTYPE_TABLE[][5],
++				     PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT data = 0 , memsize = 0 ;
++    unsigned short data = 0 , memsize = 0;
+     int RankSize ;
+     UCHAR ChannelNo ;
+ 
+@@ -2083,9 +2113,11 @@ USHORT XGINew_SetDRAMSizeReg( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVI
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-USHORT XGINew_SetDRAMSize20Reg( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
++unsigned short XGINew_SetDRAMSize20Reg(int index,
++				       unsigned short DRAMTYPE_TABLE[][5],
++				       PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT data = 0 , memsize = 0 ;
++    unsigned short data = 0 , memsize = 0;
+     int RankSize ;
+     UCHAR ChannelNo ;
+ 
+@@ -2133,10 +2165,11 @@ USHORT XGINew_SetDRAMSize20Reg( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DE
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-int XGINew_ReadWriteRest( USHORT StopAddr , USHORT StartAddr, PVB_DEVICE_INFO pVBInfo)
++int XGINew_ReadWriteRest(unsigned short StopAddr, unsigned short StartAddr,
++			 PVB_DEVICE_INFO pVBInfo)
+ {
+     int i ;
+-    ULONG Position = 0 ;
++    unsigned long Position = 0 ;
+ 
+     *((unsigned long *)(pVBInfo->FBAddr + Position)) = Position;
+ 
+@@ -2476,7 +2509,7 @@ void XGINew_CheckChannel( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO
+ int XGINew_DDRSizing340( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+     int i ;
+-    USHORT memsize , addr ;
++    unsigned short memsize , addr ;
+ 
+     XGINew_SetReg1( pVBInfo->P3c4 , 0x15 , 0x00 ) ;	/* noninterleaving */
+     XGINew_SetReg1( pVBInfo->P3c4 , 0x1C , 0x00 ) ;	/* nontiling */
+@@ -2493,7 +2526,7 @@ int XGINew_DDRSizing340( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO
+             continue ;
+ 
+         addr = memsize + ( XGINew_ChannelAB - 2 ) + 20 ;
+-        if ( ( HwDeviceExtension->ulVideoMemorySize - 1 ) < ( ULONG )( 1 << addr ) )
++	if ((HwDeviceExtension->ulVideoMemorySize - 1) < (unsigned long)(1 << addr))
+             continue ;
+ 
+         if ( XGINew_ReadWriteRest( addr , 5, pVBInfo ) == 1 )
+@@ -2511,7 +2544,7 @@ int XGINew_DDRSizing340( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO
+             continue ;
+ 
+         addr = memsize + ( XGINew_ChannelAB - 2 ) + 20 ;
+-        if ( ( HwDeviceExtension->ulVideoMemorySize - 1 ) < ( ULONG )( 1 << addr ) )
++	if ((HwDeviceExtension->ulVideoMemorySize - 1) < (unsigned long)(1 << addr))
+             continue ;
+ 
+         if ( XGINew_ReadWriteRest( addr , 9, pVBInfo ) == 1 )
+@@ -2592,7 +2625,7 @@ void XGINew_SetMemoryClock( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_IN
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-BOOLEAN ChkLFB( PVB_DEVICE_INFO pVBInfo )
++unsigned char ChkLFB( PVB_DEVICE_INFO pVBInfo )
+ {
+ 	if (LFBDRAMTrap & XGINew_GetReg1(pVBInfo->P3d4 , 0x78))
+ 		return 1;
+@@ -2609,9 +2642,10 @@ BOOLEAN ChkLFB( PVB_DEVICE_INFO pVBInfo )
+ /* in second chip, assume CR A1 D[6]="1" in this case */
+ /* output : none */
+ /* --------------------------------------------------------------------- */
+-void SetPowerConsume ( PXGI_HW_DEVICE_INFO HwDeviceExtension , ULONG XGI_P3d4Port )
++void SetPowerConsume(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++		     unsigned long XGI_P3d4Port)
+ {
+-    ULONG   lTemp ;
++    unsigned long   lTemp ;
+     UCHAR   bTemp;
+ 
+     HwDeviceExtension->pQueryVGAConfigSpace( HwDeviceExtension , 0x08 , 0 , &lTemp ) ; /* Get */
+@@ -2640,10 +2674,10 @@ void SetPowerConsume ( PXGI_HW_DEVICE_INFO HwDeviceExtension , ULONG XGI_P3d4Por
+ void XGINew_InitVBIOSData(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+ 
+-	/* ULONG ROMAddr = (ULONG)HwDeviceExtension->pjVirtualRomBase; */
++	/* unsigned long ROMAddr = (unsigned long)HwDeviceExtension->pjVirtualRomBase; */
+     pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+     pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+-    pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
++    pVBInfo->BaseAddr = (unsigned long)HwDeviceExtension->pjIOAddress ;
+     pVBInfo->ISXPDOS = 0 ;
+ 
+     pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
+@@ -2689,7 +2723,7 @@ void XGINew_InitVBIOSData(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO
+ void ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo)
+ {
+ 	volatile unsigned char *pVideoMemory = (unsigned char *)pVBInfo->ROMAddr;
+-    ULONG   i ;
++    unsigned long   i ;
+     UCHAR   j , k ;
+     /* Volari customize data area end */
+ 
+@@ -2756,7 +2790,7 @@ void ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_DDR1x_MRS_XG20( ULONG P3c4 , PVB_DEVICE_INFO pVBInfo)
++void XGINew_DDR1x_MRS_XG20(unsigned long P3c4, PVB_DEVICE_INFO pVBInfo)
+ {
+ 
+     XGINew_SetReg1( P3c4 , 0x18 , 0x01 ) ;
+@@ -2798,7 +2832,7 @@ void XGINew_SetDRAMModeRegister_XG20( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+     PVB_DEVICE_INFO pVBInfo = &VBINF;
+     pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+     pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+-    pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
++    pVBInfo->BaseAddr = (unsigned long)HwDeviceExtension->pjIOAddress ;
+     pVBInfo->ISXPDOS = 0 ;
+ 
+     pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
+@@ -2837,7 +2871,7 @@ void XGINew_SetDRAMModeRegister_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+     PVB_DEVICE_INFO pVBInfo = &VBINF;
+     pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+     pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+-    pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
++    pVBInfo->BaseAddr = (unsigned long)HwDeviceExtension->pjIOAddress ;
+     pVBInfo->ISXPDOS = 0 ;
+ 
+     pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
+@@ -2922,7 +2956,7 @@ void XGINew_SetDRAMModeRegister_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+ /* -------------------------------------------------------- */
+ void XGINew_ChkSenseStatus ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT tempbx=0 , temp , tempcx , CR3CData;
++    unsigned short tempbx = 0, temp, tempcx, CR3CData;
+ 
+     temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x32 ) ;
+ 
+@@ -2983,7 +3017,7 @@ void XGINew_ChkSenseStatus ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_
+ /* -------------------------------------------------------- */
+ void XGINew_SetModeScratch ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo )
+ {
+-    USHORT temp , tempcl = 0 , tempch = 0 , CR31Data , CR38Data;
++    unsigned short temp , tempcl = 0 , tempch = 0 , CR31Data , CR38Data;
+ 
+     temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x3d ) ;
+     temp |= XGINew_GetReg1( pVBInfo->P3d4 , 0x3e ) << 8 ;
+diff --git a/drivers/staging/xgifb/vb_init.h b/drivers/staging/xgifb/vb_init.h
+index 1f39d9c74cdd..ab6939f58586 100644
+--- a/drivers/staging/xgifb/vb_init.h
++++ b/drivers/staging/xgifb/vb_init.h
+@@ -1,6 +1,6 @@
+ #ifndef  _VBINIT_
+ #define  _VBINIT_
+-extern   BOOLEAN    XGIInitNew( PXGI_HW_DEVICE_INFO HwDeviceExtension ) ;
++extern   unsigned char    XGIInitNew( PXGI_HW_DEVICE_INFO HwDeviceExtension ) ;
+ extern XGI21_LVDSCapStruct  XGI21_LCDCapList[13];
+ 
+ #endif
+diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c
+index 4a2fa32e7d94..f27259e80987 100644
+--- a/drivers/staging/xgifb/vb_setmode.c
++++ b/drivers/staging/xgifb/vb_setmode.c
+@@ -20,44 +20,71 @@
+ 
+ 
+ 
+-BOOLEAN  XGI_IsLCDDualLink(PVB_DEVICE_INFO pVBInfo);
+-BOOLEAN  XGI_SetCRT2Group301(USHORT ModeNo, PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo);
+-BOOLEAN  XGI_BacklightByDrv(PVB_DEVICE_INFO pVBInfo);
+-
+-BOOLEAN  XGI_IsLCDON(PVB_DEVICE_INFO pVBInfo);
+-BOOLEAN  XGI_DisableChISLCD(PVB_DEVICE_INFO pVBInfo);
+-BOOLEAN  XGI_EnableChISLCD(PVB_DEVICE_INFO pVBInfo);
+-BOOLEAN  XGI_AjustCRT2Rate(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,USHORT *i, PVB_DEVICE_INFO pVBInfo);
+-BOOLEAN  XGI_SearchModeID( USHORT ModeNo,USHORT  *ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+-BOOLEAN  XGI_GetLCDInfo(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+-BOOLEAN  XGISetModeNew( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo ) ;
+-BOOLEAN  XGI_BridgeIsOn(PVB_DEVICE_INFO pVBInfo);
+-UCHAR    XGI_GetModePtr( USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
+-USHORT   XGI_GetOffset(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo);
+-USHORT   XGI_GetRatePtrCRT2( PXGI_HW_DEVICE_INFO pXGIHWDE, USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo );
+-USHORT   XGI_GetResInfo(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+-USHORT   XGI_GetColorDepth(USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
+-USHORT   XGI_GetVGAHT2(PVB_DEVICE_INFO pVBInfo);
+-USHORT   XGI_GetVCLK2Ptr(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo);
++unsigned char  XGI_IsLCDDualLink(PVB_DEVICE_INFO pVBInfo);
++unsigned char  XGI_SetCRT2Group301(unsigned short ModeNo,
++			     PXGI_HW_DEVICE_INFO HwDeviceExtension,
++			     PVB_DEVICE_INFO pVBInfo);
++unsigned char  XGI_BacklightByDrv(PVB_DEVICE_INFO pVBInfo);
++
++unsigned char  XGI_IsLCDON(PVB_DEVICE_INFO pVBInfo);
++unsigned char  XGI_DisableChISLCD(PVB_DEVICE_INFO pVBInfo);
++unsigned char  XGI_EnableChISLCD(PVB_DEVICE_INFO pVBInfo);
++unsigned char  XGI_AjustCRT2Rate(unsigned short ModeNo,
++			   unsigned short ModeIdIndex,
++			   unsigned short RefreshRateTableIndex,
++			   unsigned short *i, PVB_DEVICE_INFO pVBInfo);
++unsigned char  XGI_SearchModeID(unsigned short ModeNo,
++			  unsigned short *ModeIdIndex,
++			  PVB_DEVICE_INFO pVBInfo);
++unsigned char  XGI_GetLCDInfo(unsigned short ModeNo,
++			unsigned short ModeIdIndex,
++			PVB_DEVICE_INFO pVBInfo);
++unsigned char  XGISetModeNew(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++		       unsigned short ModeNo);
++unsigned char  XGI_BridgeIsOn(PVB_DEVICE_INFO pVBInfo);
++UCHAR    XGI_GetModePtr(unsigned short ModeNo,
++			unsigned short ModeIdIndex,
++			PVB_DEVICE_INFO pVBInfo);
++unsigned short XGI_GetOffset(unsigned short ModeNo,
++			     unsigned short ModeIdIndex,
++			     unsigned short RefreshRateTableIndex,
++			     PXGI_HW_DEVICE_INFO HwDeviceExtension,
++			     PVB_DEVICE_INFO pVBInfo);
++unsigned short XGI_GetRatePtrCRT2(PXGI_HW_DEVICE_INFO pXGIHWDE,
++				  unsigned short ModeNo,
++				  unsigned short ModeIdIndex,
++				  PVB_DEVICE_INFO pVBInfo);
++unsigned short XGI_GetResInfo(unsigned short ModeNo,
++			      unsigned short ModeIdIndex,
++			      PVB_DEVICE_INFO pVBInfo);
++unsigned short XGI_GetColorDepth(unsigned short ModeNo,
++				 unsigned short ModeIdIndex,
++				 PVB_DEVICE_INFO pVBInfo);
++unsigned short XGI_GetVGAHT2(PVB_DEVICE_INFO pVBInfo);
++unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo,
++			       unsigned short ModeIdIndex,
++			       unsigned short RefreshRateTableIndex,
++			       PXGI_HW_DEVICE_INFO HwDeviceExtension,
++			       PVB_DEVICE_INFO pVBInfo);
+ void     XGI_VBLongWait(PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SaveCRT2Info(USHORT ModeNo, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_GetCRT2Data(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_GetCRT2ResInfo(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_PreSetGroup1(USHORT ModeNo,USHORT ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetGroup1(USHORT ModeNo,USHORT ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetLockRegs(USHORT ModeNo,USHORT ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetLCDRegs(USHORT ModeNo,USHORT ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetGroup2(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetGroup3(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetGroup4(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetGroup5(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+-void*    XGI_GetLcdPtr(USHORT BX,  USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void*    XGI_GetTVPtr(USHORT BX, USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SaveCRT2Info(unsigned short ModeNo, PVB_DEVICE_INFO pVBInfo);
++void     XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_GetCRT2ResInfo(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_PreSetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetGroup3(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetGroup5(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
++void     *XGI_GetLcdPtr(unsigned short BX,  unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
++void     *XGI_GetTVPtr(unsigned short BX, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+ void 	 XGI_FirePWDEnable(PVB_DEVICE_INFO pVBInfo);
+ void 	 XGI_EnableGatingCRT(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+ void 	 XGI_DisableGatingCRT(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+-void 	 XGI_SetPanelDelay(USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
+-void 	 XGI_SetPanelPower(USHORT tempah,USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetPanelDelay(unsigned short tempbl, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetPanelPower(unsigned short tempah, unsigned short tempbl, PVB_DEVICE_INFO pVBInfo);
+ void 	 XGI_EnablePWD( PVB_DEVICE_INFO pVBInfo);
+ void 	 XGI_DisablePWD( PVB_DEVICE_INFO pVBInfo);
+ void     XGI_AutoThreshold( PVB_DEVICE_INFO pVBInfo);
+@@ -65,136 +92,136 @@ void     XGI_SetTap4Regs( PVB_DEVICE_INFO pVBInfo);
+ 
+ void     XGI_DisplayOn(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_DisplayOff( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo );
+-void     XGI_SetCRT1Group(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetXG21CRTC(USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetXG21LCD(PVB_DEVICE_INFO pVBInfo,USHORT RefreshRateTableIndex,USHORT ModeNo);
+-void     XGI_SetXG27CRTC(USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetXG27LCD(PVB_DEVICE_INFO pVBInfo,USHORT RefreshRateTableIndex,USHORT ModeNo);
+-void	 XGI_UpdateXG21CRTC(USHORT ModeNo, PVB_DEVICE_INFO pVBInfo, USHORT RefreshRateTableIndex);
++void     XGI_SetCRT1Group(PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetXG21CRTC(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetXG21LCD(PVB_DEVICE_INFO pVBInfo, unsigned short RefreshRateTableIndex, unsigned short ModeNo);
++void     XGI_SetXG27CRTC(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetXG27LCD(PVB_DEVICE_INFO pVBInfo, unsigned short RefreshRateTableIndex, unsigned short ModeNo);
++void	 XGI_UpdateXG21CRTC(unsigned short ModeNo, PVB_DEVICE_INFO pVBInfo, unsigned short RefreshRateTableIndex);
+ void     XGI_WaitDisply(PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SenseCRT1(PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetSeqRegs(USHORT ModeNo,USHORT StandTableIndex,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetMiscRegs(USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetCRTCRegs(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetATTRegs(USHORT ModeNo,USHORT StandTableIndex,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo );
+-void     XGI_SetGRCRegs(USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetSeqRegs(unsigned short ModeNo, unsigned short StandTableIndex, unsigned short ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetMiscRegs(unsigned short StandTableIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetCRTCRegs(PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short StandTableIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetATTRegs(unsigned short ModeNo, unsigned short StandTableIndex, unsigned short ModeIdIndex,PVB_DEVICE_INFO pVBInfo );
++void     XGI_SetGRCRegs(unsigned short StandTableIndex, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_ClearExt1Regs(PVB_DEVICE_INFO pVBInfo);
+ 
+-void     XGI_SetSync(USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetCRT1CRTC(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo,PXGI_HW_DEVICE_INFO HwDeviceExtension);
++void     XGI_SetSync(unsigned short RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetCRT1CRTC(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo,PXGI_HW_DEVICE_INFO HwDeviceExtension);
+ void     XGI_SetCRT1Timing_H(PVB_DEVICE_INFO pVBInfo,PXGI_HW_DEVICE_INFO HwDeviceExtension);
+-void     XGI_SetCRT1Timing_V(USHORT ModeIdIndex,USHORT ModeNo,PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetCRT1DE(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetCRT1VCLK(USHORT ModeNo,USHORT ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetCRT1FIFO(USHORT ModeNo,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetCRT1ModeRegs(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetVCLKState(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
+-
+-void     XGI_LoadDAC(USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
+-void     XGI_WriteDAC(USHORT dl, USHORT ah, USHORT al, USHORT dh, PVB_DEVICE_INFO pVBInfo);
+-/*void     XGI_ClearBuffer(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,PVB_DEVICE_INFO pVBInfo);*/
+-void     XGI_SetLCDAGroup(USHORT ModeNo,USHORT ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO  pVBInfo);
+-void     XGI_GetLVDSResInfo( USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO  pVBInfo);
+-void     XGI_GetLVDSData(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO  pVBInfo);
+-void     XGI_ModCRT1Regs(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO  pVBInfo);
+-void     XGI_SetLVDSRegs(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO  pVBInfo);
++void     XGI_SetCRT1Timing_V(unsigned short ModeIdIndex, unsigned short ModeNo,PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetCRT1DE(PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetCRT1VCLK(unsigned short ModeNo, unsigned short ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetCRT1FIFO(unsigned short ModeNo,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetCRT1ModeRegs(PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetVCLKState(PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short ModeNo, unsigned short RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
++
++void     XGI_LoadDAC(unsigned short ModeNo, unsigned short ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
++void     XGI_WriteDAC(unsigned short dl, unsigned short ah, unsigned short al, unsigned short dh, PVB_DEVICE_INFO pVBInfo);
++/*void     XGI_ClearBuffer(PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short ModeNo,PVB_DEVICE_INFO pVBInfo);*/
++void     XGI_SetLCDAGroup(unsigned short ModeNo, unsigned short ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO  pVBInfo);
++void     XGI_GetLVDSResInfo(unsigned short ModeNo, unsigned short ModeIdIndex,PVB_DEVICE_INFO  pVBInfo);
++void     XGI_GetLVDSData(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,PVB_DEVICE_INFO  pVBInfo);
++void     XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO  pVBInfo);
++void     XGI_SetLVDSRegs(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,PVB_DEVICE_INFO  pVBInfo);
+ void     XGI_UpdateModeInfo(PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO  pVBInfo);
+ void     XGI_GetVGAType(PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO  pVBInfo);
+ void     XGI_GetVBType(PVB_DEVICE_INFO  pVBInfo);
+-void     XGI_GetVBInfo(USHORT ModeNo,USHORT ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO  pVBInfo);
+-void     XGI_GetTVInfo(USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO  pVBInfo);
+-void     XGI_SetCRT2ECLK( USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO  pVBInfo);
++void     XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO  pVBInfo);
++void     XGI_GetTVInfo(unsigned short ModeNo, unsigned short ModeIdIndex,PVB_DEVICE_INFO  pVBInfo);
++void     XGI_SetCRT2ECLK(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,PVB_DEVICE_INFO  pVBInfo);
+ void     InitTo330Pointer(UCHAR,PVB_DEVICE_INFO pVBInfo);
+-void     XGI_GetLCDSync(USHORT* HSyncWidth, USHORT* VSyncWidth, PVB_DEVICE_INFO pVBInfo);
++void     XGI_GetLCDSync(unsigned short *HSyncWidth, unsigned short *VSyncWidth, PVB_DEVICE_INFO pVBInfo);
+ void 	 XGI_DisableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+ void  	 XGI_EnableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetCRT2VCLK(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_OEM310Setting(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetCRT2VCLK(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_OEM310Setting(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SetDelayComp(PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SetLCDCap(PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetLCDCap_A(USHORT tempcx,PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetLCDCap_B(USHORT tempcx,PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetLCDCap_A(unsigned short tempcx,PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetLCDCap_B(unsigned short tempcx,PVB_DEVICE_INFO pVBInfo);
+ void     SetSpectrum(PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetAntiFlicker(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetEdgeEnhance(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetAntiFlicker(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetEdgeEnhance(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SetPhaseIncr(PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetYFilter(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_GetTVPtrIndex2(USHORT* tempbx,UCHAR* tempcl,UCHAR* tempch, PVB_DEVICE_INFO pVBInfo);
+-USHORT   XGI_GetTVPtrIndex(  PVB_DEVICE_INFO pVBInfo );
+-void     XGI_SetCRT2ModeRegs(USHORT ModeNo,PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo );
++void     XGI_SetYFilter(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_GetTVPtrIndex2(unsigned short *tempbx,UCHAR* tempcl,UCHAR* tempch, PVB_DEVICE_INFO pVBInfo);
++unsigned short   XGI_GetTVPtrIndex(PVB_DEVICE_INFO pVBInfo);
++void     XGI_SetCRT2ModeRegs(unsigned short ModeNo,PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo );
+ void     XGI_CloseCRTC(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_OpenCRTC(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_GetRAMDAC2DATA(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
++void     XGI_GetRAMDAC2DATA(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_UnLockCRT2(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_LockCRT2(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
+ void     XGINew_EnableCRT2(PVB_DEVICE_INFO pVBInfo);
+ void     XGINew_LCD_Wait_Time(UCHAR DelayTime, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_LongWait(PVB_DEVICE_INFO pVBInfo);
+-void     XGI_SetCRT1Offset( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo );
++void     XGI_SetCRT1Offset(unsigned short ModeNo , unsigned short ModeIdIndex , unsigned short RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo );
+ void     XGI_GetLCDVCLKPtr(UCHAR* di_0,UCHAR *di_1, PVB_DEVICE_INFO pVBInfo);
+-UCHAR    XGI_GetVCLKPtr(USHORT RefreshRateTableIndex,USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
++UCHAR    XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex, unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_GetVCLKLen(UCHAR tempal,UCHAR* di_0,UCHAR* di_1, PVB_DEVICE_INFO pVBInfo);
+-USHORT   XGI_GetLCDCapPtr(PVB_DEVICE_INFO pVBInfo);
+-USHORT   XGI_GetLCDCapPtr1(PVB_DEVICE_INFO pVBInfo);
+-XGI301C_Tap4TimingStruct* XGI_GetTap4Ptr(USHORT tempcx, PVB_DEVICE_INFO pVBInfo);
++unsigned short   XGI_GetLCDCapPtr(PVB_DEVICE_INFO pVBInfo);
++unsigned short   XGI_GetLCDCapPtr1(PVB_DEVICE_INFO pVBInfo);
++XGI301C_Tap4TimingStruct *XGI_GetTap4Ptr(unsigned short tempcx, PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SetXG21FPBits(PVB_DEVICE_INFO pVBInfo);
+ void     XGI_SetXG27FPBits(PVB_DEVICE_INFO pVBInfo);
+ UCHAR    XGI_XG21GetPSCValue(PVB_DEVICE_INFO pVBInfo);
+ UCHAR    XGI_XG27GetPSCValue(PVB_DEVICE_INFO pVBInfo);
+-void     XGI_XG21BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_XG27BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
+-void     XGI_XG21SetPanelDelay(USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
+-BOOLEAN  XGI_XG21CheckLVDSMode(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
+-void     XGI_SetXG21LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
+-void     XGI_SetXG27LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
++void     XGI_XG21BLSignalVDD(unsigned short tempbh, unsigned short tempbl, PVB_DEVICE_INFO pVBInfo);
++void     XGI_XG27BLSignalVDD(unsigned short tempbh, unsigned short tempbl, PVB_DEVICE_INFO pVBInfo);
++void     XGI_XG21SetPanelDelay(unsigned short tempbl, PVB_DEVICE_INFO pVBInfo);
++unsigned char  XGI_XG21CheckLVDSMode(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
++void     XGI_SetXG21LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
++void     XGI_SetXG27LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
+ UCHAR    XGI_SetDefaultVCLK( PVB_DEVICE_INFO pVBInfo );
+ 
+ extern   void 	  ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo);
+ 
+-/* USHORT XGINew_flag_clearbuffer; 0: no clear frame buffer 1:clear frame buffer */
+-
+-
+-
+-
+-
+-USHORT XGINew_MDA_DAC[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+-               0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+-               0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+-               0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
+-               0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+-               0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+-               0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+-               0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F};
+-
+-USHORT XGINew_CGA_DAC[]={0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+-               0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+-               0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+-               0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+-               0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+-               0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+-               0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+-               0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F};
+-
+-USHORT XGINew_EGA_DAC[]={0x00,0x10,0x04,0x14,0x01,0x11,0x05,0x15,
+-               0x20,0x30,0x24,0x34,0x21,0x31,0x25,0x35,
+-               0x08,0x18,0x0C,0x1C,0x09,0x19,0x0D,0x1D,
+-               0x28,0x38,0x2C,0x3C,0x29,0x39,0x2D,0x3D,
+-               0x02,0x12,0x06,0x16,0x03,0x13,0x07,0x17,
+-               0x22,0x32,0x26,0x36,0x23,0x33,0x27,0x37,
+-               0x0A,0x1A,0x0E,0x1E,0x0B,0x1B,0x0F,0x1F,
+-               0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F};
+-
+-USHORT XGINew_VGA_DAC[]={0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+-               0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+-               0x00,0x05,0x08,0x0B,0x0E,0x11,0x14,0x18,
+-               0x1C,0x20,0x24,0x28,0x2D,0x32,0x38,0x3F,
+-
+-               0x00,0x10,0x1F,0x2F,0x3F,0x1F,0x27,0x2F,
+-               0x37,0x3F,0x2D,0x31,0x36,0x3A,0x3F,0x00,
+-               0x07,0x0E,0x15,0x1C,0x0E,0x11,0x15,0x18,
+-               0x1C,0x14,0x16,0x18,0x1A,0x1C,0x00,0x04,
+-               0x08,0x0C,0x10,0x08,0x0A,0x0C,0x0E,0x10,
+-               0x0B,0x0C,0x0D,0x0F,0x10};
++/* unsigned short XGINew_flag_clearbuffer; 0: no clear frame buffer 1:clear frame buffer */
++
++
++unsigned short XGINew_MDA_DAC[] = {
++	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++	0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
++	0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
++	0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
++	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++	0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
++	0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
++	0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F};
++
++unsigned short XGINew_CGA_DAC[] = {
++	0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
++	0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
++	0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
++	0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
++	0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
++	0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
++	0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
++	0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F};
++
++unsigned short XGINew_EGA_DAC[] = {
++	0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x05, 0x15,
++	0x20, 0x30, 0x24, 0x34, 0x21, 0x31, 0x25, 0x35,
++	0x08, 0x18, 0x0C, 0x1C, 0x09, 0x19, 0x0D, 0x1D,
++	0x28, 0x38, 0x2C, 0x3C, 0x29, 0x39, 0x2D, 0x3D,
++	0x02, 0x12, 0x06, 0x16, 0x03, 0x13, 0x07, 0x17,
++	0x22, 0x32, 0x26, 0x36, 0x23, 0x33, 0x27, 0x37,
++	0x0A, 0x1A, 0x0E, 0x1E, 0x0B, 0x1B, 0x0F, 0x1F,
++	0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F};
++
++unsigned short XGINew_VGA_DAC[] = {
++	0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
++	0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
++	0x00, 0x05, 0x08, 0x0B, 0x0E, 0x11, 0x14, 0x18,
++	0x1C, 0x20, 0x24, 0x28, 0x2D, 0x32, 0x38, 0x3F,
++	0x00, 0x10, 0x1F, 0x2F, 0x3F, 0x1F, 0x27, 0x2F,
++	0x37, 0x3F, 0x2D, 0x31, 0x36, 0x3A, 0x3F, 0x00,
++	0x07, 0x0E, 0x15, 0x1C, 0x0E, 0x11, 0x15, 0x18,
++	0x1C, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x00, 0x04,
++	0x08, 0x0C, 0x10, 0x08, 0x0A, 0x0C, 0x0E, 0x10,
++	0x0B, 0x0C, 0x0D, 0x0F, 0x10};
+ 
+ 
+ /* --------------------------------------------------------------------- */
+@@ -358,14 +385,14 @@ void InitTo330Pointer( UCHAR ChipType ,PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-BOOLEAN XGISetModeNew( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo )
++unsigned char XGISetModeNew(PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short ModeNo)
+ {
+-    USHORT ModeIdIndex ;
++    unsigned short ModeIdIndex ;
+         /* PUCHAR pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ; */
+     VB_DEVICE_INFO VBINF;
+     PVB_DEVICE_INFO pVBInfo = &VBINF;
+     pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+-    pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
++    pVBInfo->BaseAddr = (unsigned long)HwDeviceExtension->pjIOAddress ;
+     pVBInfo->IF_DEF_LVDS = 0 ;
+     pVBInfo->IF_DEF_CH7005 = 0 ;
+     pVBInfo->IF_DEF_LCDA = 1 ;
+@@ -581,14 +608,16 @@ BOOLEAN XGISetModeNew( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetCRT1Group( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
++void XGI_SetCRT1Group(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++		      unsigned short ModeNo,
++		      unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT StandTableIndex ,
++    unsigned short StandTableIndex ,
+            RefreshRateTableIndex ,
+            b3CC ,
+            temp ;
+ 
+-    USHORT XGINew_P3cc =  pVBInfo->P3cc;
++    unsigned short XGINew_P3cc =  pVBInfo->P3cc;
+ 
+     /* XGINew_CRT1Mode = ModeNo ; // SaveModeID */
+     StandTableIndex = XGI_GetModePtr( ModeNo , ModeIdIndex, pVBInfo ) ;
+@@ -701,7 +730,8 @@ void XGI_SetCRT1Group( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo , U
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-UCHAR XGI_GetModePtr( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
++UCHAR XGI_GetModePtr(unsigned short ModeNo, unsigned short ModeIdIndex,
++		     PVB_DEVICE_INFO pVBInfo)
+ {
+     UCHAR index ;
+ 
+@@ -724,7 +754,7 @@ UCHAR XGI_GetModePtr( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInf
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-/*UCHAR XGI_SetBIOSData( USHORT ModeNo , USHORT ModeIdIndex )
++/*UCHAR XGI_SetBIOSData(unsigned short ModeNo , unsigned short ModeIdIndex )
+ {
+     return( 0 ) ;
+ }
+@@ -736,7 +766,7 @@ UCHAR XGI_GetModePtr( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInf
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-/*UCHAR XGI_ClearBankRegs( USHORT ModeNo , USHORT ModeIdIndex )
++/*UCHAR XGI_ClearBankRegs(unsigned short ModeNo , unsigned short ModeIdIndex )
+ {
+     return( 0 ) ;
+ }
+@@ -748,12 +778,13 @@ UCHAR XGI_GetModePtr( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInf
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetSeqRegs(  USHORT ModeNo , USHORT StandTableIndex , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
++void XGI_SetSeqRegs(unsigned short ModeNo, unsigned short StandTableIndex,
++		    unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+ {
+     UCHAR tempah ,
+           SRdata ;
+ 
+-    USHORT i ,
++    unsigned short i ,
+            modeflag ;
+ 
+     if ( ModeNo <= 0x13 )
+@@ -795,7 +826,7 @@ void XGI_SetSeqRegs(  USHORT ModeNo , USHORT StandTableIndex , USHORT ModeIdInde
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetMiscRegs( USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo )
++void XGI_SetMiscRegs(unsigned short StandTableIndex, PVB_DEVICE_INFO pVBInfo )
+ {
+     UCHAR Miscdata ;
+ 
+@@ -820,10 +851,11 @@ void XGI_SetMiscRegs( USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetCRTCRegs( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo )
++void XGI_SetCRTCRegs(PXGI_HW_DEVICE_INFO HwDeviceExtension ,
++		     unsigned short StandTableIndex, PVB_DEVICE_INFO pVBInfo)
+ {
+     UCHAR CRTCdata ;
+-    USHORT i ;
++    unsigned short i ;
+ 
+     CRTCdata = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;
+     CRTCdata &= 0x7f ;
+@@ -855,11 +887,11 @@ void XGI_SetCRTCRegs( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT StandTableI
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetATTRegs( USHORT ModeNo , USHORT StandTableIndex , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
++void XGI_SetATTRegs(unsigned short ModeNo, unsigned short StandTableIndex,
++		    unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+ {
+     UCHAR ARdata ;
+-    USHORT i ,
+-           modeflag ;
++    unsigned short i, modeflag;
+ 
+     if ( ModeNo <= 0x13 )
+         modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+@@ -905,10 +937,10 @@ void XGI_SetATTRegs( USHORT ModeNo , USHORT StandTableIndex , USHORT ModeIdIndex
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetGRCRegs( USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo )
++void XGI_SetGRCRegs(unsigned short StandTableIndex, PVB_DEVICE_INFO pVBInfo )
+ {
+     UCHAR GRdata ;
+-    USHORT i ;
++    unsigned short i ;
+ 
+     for( i = 0 ; i <= 0x08 ; i++ )
+     {
+@@ -933,7 +965,7 @@ void XGI_SetGRCRegs( USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo )
+ /* --------------------------------------------------------------------- */
+ void XGI_ClearExt1Regs(PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT i ;
++    unsigned short i ;
+ 
+     for( i = 0x0A ; i <= 0x0E ; i++ )
+         XGINew_SetReg1( pVBInfo->P3c4 , i , 0x00 ) ;	/* Clear SR0A-SR0E */
+@@ -968,13 +1000,15 @@ UCHAR XGI_SetDefaultVCLK( PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-USHORT XGI_GetRatePtrCRT2( PXGI_HW_DEVICE_INFO pXGIHWDE, USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
++unsigned short XGI_GetRatePtrCRT2(PXGI_HW_DEVICE_INFO pXGIHWDE,
++				  unsigned short ModeNo,
++				  unsigned short ModeIdIndex,
++				  PVB_DEVICE_INFO pVBInfo)
+ {
+     SHORT  LCDRefreshIndex[] = { 0x00 , 0x00 , 0x03 , 0x01 } ,
+            LCDARefreshIndex[] = { 0x00 , 0x00 , 0x03 , 0x01 , 0x01 , 0x01 , 0x01 } ;
+ 
+-    USHORT RefreshRateTableIndex , i ,
+-         modeflag , index , temp ;
++    unsigned short RefreshRateTableIndex, i, modeflag, index, temp;
+ 
+     if ( ModeNo <= 0x13 )
+     {
+@@ -1105,13 +1139,11 @@ USHORT XGI_GetRatePtrCRT2( PXGI_HW_DEVICE_INFO pXGIHWDE, USHORT ModeNo , USHORT
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-BOOLEAN XGI_AjustCRT2Rate( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex , USHORT *i, PVB_DEVICE_INFO pVBInfo )
++unsigned char XGI_AjustCRT2Rate(unsigned short ModeNo, unsigned short ModeIdIndex,
++			  unsigned short RefreshRateTableIndex,
++			  unsigned short *i, PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT tempax ,
+-           tempbx ,
+-           resinfo ,
+-           modeflag ,
+-           infoflag ;
++    unsigned short tempax, tempbx, resinfo, modeflag, infoflag;
+ 
+     if ( ModeNo <= 0x13 )
+     {
+@@ -1281,9 +1313,9 @@ BOOLEAN XGI_AjustCRT2Rate( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRa
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetSync(USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
++void XGI_SetSync(unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+ {
+-    USHORT sync ,
++    unsigned short sync ,
+            temp ;
+ 
+     sync = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag >> 8 ;	/* di+0x00 */
+@@ -1300,12 +1332,15 @@ void XGI_SetSync(USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetCRT1CRTC( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo, PXGI_HW_DEVICE_INFO HwDeviceExtension )
++void XGI_SetCRT1CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
++		     unsigned short RefreshRateTableIndex,
++		     PVB_DEVICE_INFO pVBInfo,
++		     PXGI_HW_DEVICE_INFO HwDeviceExtension)
+ {
+     UCHAR  index ,
+            data ;
+ 
+-    USHORT i ;
++    unsigned short i;
+ 
+     index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ;	/* Get index */
+     index = index&IndexMask ;
+@@ -1341,7 +1376,7 @@ void XGI_SetCRT1CRTC( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTab
+ void XGI_SetCRT1Timing_H( PVB_DEVICE_INFO pVBInfo, PXGI_HW_DEVICE_INFO HwDeviceExtension )
+ {
+     UCHAR data , data1, pushax;
+-    USHORT i , j ;
++    unsigned short i, j;
+ 
+     /* XGINew_SetReg1( pVBInfo->P3d4 , 0x51 , 0 ) ; */
+     /* XGINew_SetReg1( pVBInfo->P3d4 , 0x56 , 0 ) ; */
+@@ -1357,13 +1392,13 @@ void XGI_SetCRT1Timing_H( PVB_DEVICE_INFO pVBInfo, PXGI_HW_DEVICE_INFO HwDeviceE
+     for( i = 0x01 ; i <= 0x04 ; i++ )
+     {
+         data = pVBInfo->TimingH[ 0 ].data[ i ] ;
+-        XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 1 ) , data ) ;
++	XGINew_SetReg1( pVBInfo->P3d4, (unsigned short)(i + 1), data);
+     }
+ 
+     for( i = 0x05 ; i <= 0x06 ; i++ )
+     {
+         data = pVBInfo->TimingH[ 0 ].data[ i ];
+-        XGINew_SetReg1( pVBInfo->P3c4 ,( USHORT )( i + 6 ) , data ) ;
++	XGINew_SetReg1(pVBInfo->P3c4, (unsigned short)(i + 6), data);
+     }
+ 
+     j = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x0e ) ;
+@@ -1410,10 +1445,12 @@ void XGI_SetCRT1Timing_H( PVB_DEVICE_INFO pVBInfo, PXGI_HW_DEVICE_INFO HwDeviceE
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetCRT1Timing_V( USHORT ModeIdIndex , USHORT ModeNo,PVB_DEVICE_INFO pVBInfo )
++void XGI_SetCRT1Timing_V(unsigned short ModeIdIndex,
++			 unsigned short ModeNo,
++			 PVB_DEVICE_INFO pVBInfo)
+ {
+     UCHAR data ;
+-    USHORT i , j ;
++    unsigned short i, j;
+ 
+     /* XGINew_SetReg1( pVBInfo->P3d4 , 0x51 , 0 ) ; */
+     /* XGINew_SetReg1( pVBInfo->P3d4 , 0x56 , 0 ) ; */
+@@ -1422,19 +1459,19 @@ void XGI_SetCRT1Timing_V( USHORT ModeIdIndex , USHORT ModeNo,PVB_DEVICE_INFO pVB
+     for( i = 0x00 ; i <= 0x01 ; i++ )
+     {
+         data = pVBInfo->TimingV[ 0 ].data[ i ] ;
+-        XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 6 ) , data ) ;
++	XGINew_SetReg1(pVBInfo->P3d4, (unsigned short)(i + 6), data);
+     }
+ 
+     for( i = 0x02 ; i <= 0x03 ; i++ )
+     {
+         data = pVBInfo->TimingV[ 0 ].data[ i ] ;
+-        XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 0x0e ) , data ) ;
++	XGINew_SetReg1(pVBInfo->P3d4, (unsigned short)(i + 0x0e), data);
+     }
+ 
+     for( i = 0x04 ; i <= 0x05 ; i++ )
+     {
+         data = pVBInfo->TimingV[ 0 ].data[ i ] ;
+-        XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 0x11 ) , data ) ;
++	XGINew_SetReg1(pVBInfo->P3d4, (unsigned short)(i + 0x11), data);
+     }
+ 
+     j = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x0a ) ;
+@@ -1470,10 +1507,12 @@ void XGI_SetCRT1Timing_V( USHORT ModeIdIndex , USHORT ModeNo,PVB_DEVICE_INFO pVB
+ /* Output : Fill CRT Hsync/Vsync to SR2E/SR2F/SR30/SR33/SR34/SR3F */
+ /* Description : Set LCD timing */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetXG21CRTC(USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo)
++void XGI_SetXG21CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
++		     unsigned short RefreshRateTableIndex,
++		     PVB_DEVICE_INFO pVBInfo)
+ {
+   UCHAR StandTableIndex, index, Tempax, Tempbx, Tempcx, Tempdx ;
+-  USHORT Temp1, Temp2, Temp3 ;
++  unsigned short Temp1, Temp2, Temp3;
+ 
+   if ( ModeNo <= 0x13 )
+   {
+@@ -1502,7 +1541,7 @@ void XGI_SetXG21CRTC(USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableI
+     Tempdx |= Tempcx ;							/* Tempdx: VRS[8:1] */
+     XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , Tempdx ) ;    		/* SR34[7:0]: VRS[8:1] */
+ 
+-    Temp1 = Tempcx << 1 ;						/* Temp1[8]: VRS[8] UCHAR -> USHORT */
++    Temp1 = Tempcx << 1 ;						/* Temp1[8]: VRS[8] UCHAR -> unsigned short */
+     Temp1 |= Tempbx ;							/* Temp1[8:0]: VRS[8:0] */
+     Tempax &= 0x80 ;							/* Tempax[7]: CR7[7] */
+     Temp2 = Tempax << 2 ;						/* Temp2[9]: VRS[9] */
+@@ -1609,9 +1648,11 @@ void XGI_SetXG21CRTC(USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableI
+   }
+ }
+ 
+-void XGI_SetXG27CRTC(USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo)
++void XGI_SetXG27CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
++		     unsigned short RefreshRateTableIndex,
++		     PVB_DEVICE_INFO pVBInfo)
+ {
+-  USHORT StandTableIndex, index, Tempax, Tempbx, Tempcx, Tempdx ;
++	unsigned short StandTableIndex, index, Tempax, Tempbx, Tempcx, Tempdx;
+ 
+   if ( ModeNo <= 0x13 )
+   {
+@@ -1732,10 +1773,12 @@ void XGI_SetXG27CRTC(USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableI
+ /* Output : FCLK duty cycle, FCLK delay compensation */
+ /* Description : All values set zero */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetXG21LCD(PVB_DEVICE_INFO pVBInfo,USHORT RefreshRateTableIndex,USHORT ModeNo)
++void XGI_SetXG21LCD(PVB_DEVICE_INFO pVBInfo,
++		    unsigned short RefreshRateTableIndex,
++		    unsigned short ModeNo)
+ {
+-  USHORT Data , Temp , b3CC ;
+-  USHORT XGI_P3cc ;
++	unsigned short Data, Temp, b3CC;
++	unsigned short XGI_P3cc;
+ 
+   XGI_P3cc = pVBInfo->P3cc ;
+ 
+@@ -1782,10 +1825,12 @@ void XGI_SetXG21LCD(PVB_DEVICE_INFO pVBInfo,USHORT RefreshRateTableIndex,USHORT
+   }
+ }
+ 
+-void XGI_SetXG27LCD(PVB_DEVICE_INFO pVBInfo,USHORT RefreshRateTableIndex,USHORT ModeNo)
++void XGI_SetXG27LCD(PVB_DEVICE_INFO pVBInfo,
++		    unsigned short RefreshRateTableIndex,
++		    unsigned short ModeNo)
+ {
+-  USHORT Data , Temp , b3CC ;
+-  USHORT XGI_P3cc ;
++  unsigned short Data , Temp , b3CC ;
++  unsigned short XGI_P3cc ;
+ 
+   XGI_P3cc = pVBInfo->P3cc ;
+ 
+@@ -1840,7 +1885,9 @@ void XGI_SetXG27LCD(PVB_DEVICE_INFO pVBInfo,USHORT RefreshRateTableIndex,USHORT
+ /* Output : CRT1 CRTC */
+ /* Description : Modify CRT1 Hsync/Vsync to fix LCD mode timing */
+ /* --------------------------------------------------------------------- */
+-void XGI_UpdateXG21CRTC( USHORT ModeNo , PVB_DEVICE_INFO pVBInfo , USHORT RefreshRateTableIndex )
++void XGI_UpdateXG21CRTC(unsigned short ModeNo,
++			PVB_DEVICE_INFO pVBInfo,
++			unsigned short RefreshRateTableIndex)
+ {
+   int i , index = -1;
+ 
+@@ -1883,14 +1930,13 @@ void XGI_UpdateXG21CRTC( USHORT ModeNo , PVB_DEVICE_INFO pVBInfo , USHORT Refres
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetCRT1DE( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo,USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
++void XGI_SetCRT1DE(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++		   unsigned short ModeNo,
++		   unsigned short ModeIdIndex,
++		   unsigned short RefreshRateTableIndex,
++		   PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT resindex ,
+-           tempax ,
+-           tempbx ,
+-           tempcx ,
+-           temp ,
+-           modeflag ;
++	unsigned short resindex, tempax, tempbx, tempcx, temp, modeflag;
+ 
+     UCHAR data ;
+ 
+@@ -1939,9 +1985,9 @@ void XGI_SetCRT1DE( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo,USHORT
+     data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;
+     data &= 0x7F ;
+     XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , data ) ;		/* Unlock CRTC */
+-    XGINew_SetReg1( pVBInfo->P3d4 , 0x01 , ( USHORT )( tempcx & 0xff ) ) ;
+-    XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x0b , ~0x0c , ( USHORT )( ( tempcx & 0x0ff00 ) >> 10 ) ) ;
+-    XGINew_SetReg1( pVBInfo->P3d4 , 0x12 , ( USHORT )( tempbx & 0xff ) ) ;
++    XGINew_SetReg1(pVBInfo->P3d4, 0x01, (unsigned short)(tempcx & 0xff));
++    XGINew_SetRegANDOR(pVBInfo->P3d4, 0x0b, ~0x0c, (unsigned short)((tempcx & 0x0ff00) >> 10));
++    XGINew_SetReg1(pVBInfo->P3d4, 0x12, (unsigned short)(tempbx & 0xff));
+     tempax = 0 ;
+     tempbx = tempbx >> 8 ;
+ 
+@@ -1970,9 +2016,11 @@ void XGI_SetCRT1DE( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo,USHORT
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-USHORT 	XGI_GetResInfo(USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
++unsigned short XGI_GetResInfo(unsigned short ModeNo,
++			      unsigned short ModeIdIndex,
++			      PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT resindex ;
++	unsigned short resindex;
+ 
+     if ( ModeNo <= 0x13 )
+     {
+@@ -1992,9 +2040,13 @@ USHORT 	XGI_GetResInfo(USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBIn
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetCRT1Offset(  USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
++void XGI_SetCRT1Offset(unsigned short ModeNo,
++		       unsigned short ModeIdIndex,
++		       unsigned short RefreshRateTableIndex,
++		       PXGI_HW_DEVICE_INFO HwDeviceExtension,
++		       PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT temp ,
++    unsigned short temp ,
+            ah ,
+            al ,
+            temp2 ,
+@@ -2085,11 +2137,13 @@ void XGI_SetCRT1Offset(  USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRate
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetCRT1VCLK( USHORT ModeNo , USHORT ModeIdIndex ,
+-                        PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
++void XGI_SetCRT1VCLK(unsigned short ModeNo, unsigned short ModeIdIndex,
++		     PXGI_HW_DEVICE_INFO HwDeviceExtension,
++		     unsigned short RefreshRateTableIndex,
++		     PVB_DEVICE_INFO pVBInfo)
+ {
+     UCHAR index , data ;
+-    USHORT vclkindex ;
++    unsigned short vclkindex ;
+ 
+     if ( pVBInfo->IF_DEF_LVDS == 1 )
+     {
+@@ -2146,9 +2200,11 @@ void XGI_SetCRT1VCLK( USHORT ModeNo , USHORT ModeIdIndex ,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetCRT1FIFO( USHORT ModeNo , PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo )
++void XGI_SetCRT1FIFO(unsigned short ModeNo,
++		     PXGI_HW_DEVICE_INFO HwDeviceExtension,
++		     PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT data ;
++    unsigned short data ;
+ 
+     data = XGINew_GetReg1( pVBInfo->P3c4 , 0x3D ) ;
+     data &= 0xfe ;
+@@ -2195,10 +2251,12 @@ void XGI_SetCRT1FIFO( USHORT ModeNo , PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetCRT1ModeRegs( PXGI_HW_DEVICE_INFO HwDeviceExtension ,
+-                            USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo )
++void XGI_SetCRT1ModeRegs(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++			 unsigned short ModeNo, unsigned short ModeIdIndex,
++			 unsigned short RefreshRateTableIndex,
++			 PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT data ,
++    unsigned short data ,
+            data2 ,
+            data3 ,
+            infoflag = 0 ,
+@@ -2333,9 +2391,12 @@ void XGI_SetCRT1ModeRegs( PXGI_HW_DEVICE_INFO HwDeviceExtension ,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetVCLKState(  PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo , USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo )
++void XGI_SetVCLKState(PXGI_HW_DEVICE_INFO HwDeviceExtension,
++		      unsigned short ModeNo,
++		      unsigned short RefreshRateTableIndex,
++		      PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT data ,
++    unsigned short data ,
+            data2 = 0 ;
+     SHORT  VCLK ;
+ 
+@@ -2397,9 +2458,9 @@ void XGI_SetVCLKState(  PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo ,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-/*void XGI_VesaLowResolution( USHORT ModeNo , USHORT ModeIdIndex ,PVB_DEVICE_INFO pVBInfo)
++/*void XGI_VesaLowResolution(unsigned short ModeNo , unsigned short ModeIdIndex ,PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT modeflag;
++    unsigned short modeflag;
+ 
+     if ( ModeNo > 0x13 )
+         modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+@@ -2440,9 +2501,11 @@ void XGI_SetVCLKState(  PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo ,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_LoadDAC( USHORT ModeNo , USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo )
++void XGI_LoadDAC(unsigned short ModeNo,
++		 unsigned short ModeIdIndex,
++		 PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT data , data2 , time ,
++    unsigned short data , data2 , time ,
+            i  , j , k , m , n , o ,
+            si , di , bx , dl , al , ah , dh ,
+            *table = NULL ;
+@@ -2549,9 +2612,11 @@ void XGI_LoadDAC( USHORT ModeNo , USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_WriteDAC( USHORT dl , USHORT ah , USHORT al , USHORT dh,PVB_DEVICE_INFO pVBInfo )
++void XGI_WriteDAC(unsigned short dl, unsigned short ah,
++		  unsigned short al, unsigned short dh,
++		  PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT temp , bh , bl ;
++    unsigned short temp , bh , bl ;
+ 
+     bh = ah ;
+     bl = al ;
+@@ -2574,9 +2639,9 @@ void XGI_WriteDAC( USHORT dl , USHORT ah , USHORT al , USHORT dh,PVB_DEVICE_INFO
+             bh = temp ;
+         }
+     }
+-    XGINew_SetReg3( pVBInfo->P3c9 , ( USHORT )dh ) ;
+-    XGINew_SetReg3( pVBInfo->P3c9 , ( USHORT )bh ) ;
+-    XGINew_SetReg3( pVBInfo->P3c9 , ( USHORT )bl ) ;
++    XGINew_SetReg3(pVBInfo->P3c9, (unsigned short)dh);
++    XGINew_SetReg3(pVBInfo->P3c9, (unsigned short)bh);
++    XGINew_SetReg3(pVBInfo->P3c9, (unsigned short)bl);
+ }
+ 
+ /* --------------------------------------------------------------------- */
+@@ -2585,10 +2650,13 @@ void XGI_WriteDAC( USHORT dl , USHORT ah , USHORT al , USHORT dh,PVB_DEVICE_INFO
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetLCDAGroup( USHORT ModeNo , USHORT ModeIdIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO  pVBInfo )
++void XGI_SetLCDAGroup(unsigned short ModeNo,
++		      unsigned short ModeIdIndex,
++		      PXGI_HW_DEVICE_INFO HwDeviceExtension,
++		      PVB_DEVICE_INFO  pVBInfo)
+ {
+-    USHORT RefreshRateTableIndex ;
+-    /* USHORT temp ; */
++    unsigned short RefreshRateTableIndex ;
++    /* unsigned short temp ; */
+ 
+     /* pVBInfo->SelectCRT2Rate = 0 ; */
+ 
+@@ -2608,9 +2676,11 @@ void XGI_SetLCDAGroup( USHORT ModeNo , USHORT ModeIdIndex , PXGI_HW_DEVICE_INFO
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_GetLVDSResInfo( USHORT ModeNo , USHORT ModeIdIndex,PVB_DEVICE_INFO  pVBInfo )
++void XGI_GetLVDSResInfo(unsigned short ModeNo,
++			unsigned short ModeIdIndex,
++			PVB_DEVICE_INFO  pVBInfo)
+ {
+-    USHORT resindex , xres , yres , modeflag ;
++    unsigned short resindex , xres , yres , modeflag ;
+ 
+     if ( ModeNo <= 0x13 )
+     {
+@@ -2676,9 +2746,12 @@ void XGI_GetLVDSResInfo( USHORT ModeNo , USHORT ModeIdIndex,PVB_DEVICE_INFO  pVB
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_GetLVDSData(  USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO  pVBInfo )
++void XGI_GetLVDSData(unsigned short ModeNo,
++		     unsigned short ModeIdIndex,
++		     unsigned short RefreshRateTableIndex,
++		     PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT tempbx ;
++    unsigned short tempbx ;
+     XGI330_LVDSDataStruct *LCDPtr = NULL ;
+     XGI330_CHTVDataStruct  *TVPtr = NULL ;
+ 
+@@ -2739,11 +2812,13 @@ void XGI_GetLVDSData(  USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTa
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_ModCRT1Regs( USHORT ModeNo , USHORT ModeIdIndex ,
+-                        USHORT RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO  pVBInfo )
++void XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex,
++		     unsigned short RefreshRateTableIndex,
++		     PXGI_HW_DEVICE_INFO HwDeviceExtension,
++		     PVB_DEVICE_INFO pVBInfo)
+ {
+     UCHAR index ;
+-    USHORT tempbx , i ;
++    unsigned short tempbx , i ;
+     XGI_LVDSCRT1HDataStruct  *LCDPtr = NULL ;
+     XGI_LVDSCRT1VDataStruct  *LCDPtr1 =NULL ;
+     /* XGI330_CHTVDataStruct *TVPtr = NULL ; */
+@@ -2839,9 +2914,11 @@ void XGI_ModCRT1Regs( USHORT ModeNo , USHORT ModeIdIndex ,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetLVDSRegs( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO  pVBInfo )
++void XGI_SetLVDSRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
++		     unsigned short RefreshRateTableIndex,
++		     PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT tempbx , tempax , tempcx , tempdx , push1 , push2 , modeflag ;
++    unsigned short tempbx , tempax , tempcx , tempdx , push1 , push2 , modeflag ;
+     unsigned long temp , temp1 , temp2 , temp3 , push3 ;
+     XGI330_LCDDataDesStruct  *LCDPtr = NULL ;
+     XGI330_LCDDataDesStruct2  *LCDPtr1 = NULL ;
+@@ -2929,8 +3006,8 @@ void XGI_SetLVDSRegs( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTab
+             tempcx = tempcx >> 3 ;
+             tempbx = tempbx >> 3 ;
+ 
+-            XGINew_SetReg1( pVBInfo->Part1Port , 0x16 , ( USHORT )( tempbx & 0xff ) ) ;
+-            XGINew_SetReg1( pVBInfo->Part1Port , 0x17 , ( USHORT )( tempcx & 0xff ) ) ;
++	    XGINew_SetReg1(pVBInfo->Part1Port, 0x16, (unsigned short)(tempbx & 0xff));
++	    XGINew_SetReg1(pVBInfo->Part1Port, 0x17, (unsigned short)(tempcx & 0xff));
+ 
+             tempax = pVBInfo->HT ;
+ 
+@@ -2958,7 +3035,7 @@ void XGI_SetLVDSRegs( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTab
+             tempax |= tempcx ;
+ 
+             XGINew_SetReg1( pVBInfo->Part1Port , 0x15 , tempax ) ;
+-            XGINew_SetReg1( pVBInfo->Part1Port , 0x14 , ( USHORT )( tempbx & 0xff ) ) ;
++	    XGINew_SetReg1(pVBInfo->Part1Port, 0x14, (unsigned short)(tempbx & 0xff));
+ 
+             tempax = pVBInfo->VT ;
+             if ( pVBInfo->LCDInfo & EnableScalingLCD )
+@@ -2972,13 +3049,13 @@ void XGI_SetLVDSRegs( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTab
+             if ( tempcx >= tempax )
+                 tempcx -= tempax ;
+ 
+-            XGINew_SetReg1( pVBInfo->Part1Port , 0x1b , ( USHORT )( tempbx & 0xff ) ) ;
+-            XGINew_SetReg1( pVBInfo->Part1Port , 0x1c , ( USHORT )( tempcx & 0xff ) ) ;
++	    XGINew_SetReg1(pVBInfo->Part1Port, 0x1b, (unsigned short)(tempbx & 0xff));
++	    XGINew_SetReg1(pVBInfo->Part1Port, 0x1c, (unsigned short)(tempcx & 0xff));
+ 
+             tempbx = ( tempbx >> 8 ) & 0x07 ;
+             tempcx = ( tempcx >> 8 ) & 0x07 ;
+ 
+-            XGINew_SetReg1( pVBInfo->Part1Port , 0x1d , ( USHORT )( ( tempcx << 3 ) | tempbx ) ) ;
++	    XGINew_SetReg1(pVBInfo->Part1Port, 0x1d, (unsigned short)((tempcx << 3) | tempbx));
+ 
+             tempax = pVBInfo->VT ;
+             if ( pVBInfo->LCDInfo & EnableScalingLCD )
+@@ -2996,8 +3073,8 @@ void XGI_SetLVDSRegs( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTab
+             if ( tempcx >= tempax )
+                 tempcx -= tempax ;
+ 
+-            XGINew_SetReg1( pVBInfo->Part1Port , 0x18 , ( USHORT )( tempbx & 0xff ) ) ;
+-            XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x19 , ~0x0f , ( USHORT )( tempcx & 0x0f ) ) ;
++	    XGINew_SetReg1(pVBInfo->Part1Port, 0x18, (unsigned short)(tempbx & 0xff));
++	    XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x19, ~0x0f, (unsigned short)(tempcx & 0x0f));
+ 
+             tempax = ( ( tempbx >> 8 ) & 0x07 ) << 3 ;
+ 
+@@ -3018,7 +3095,7 @@ void XGI_SetLVDSRegs( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTab
+             temp = tempax ;            /* 0430 ylshieh */
+             temp1 = ( temp << 18 ) / tempbx ;
+ 
+-            tempdx = ( USHORT )( ( temp << 18 ) % tempbx ) ;
++	    tempdx = (unsigned short)((temp << 18) % tempbx);
+ 
+             if ( tempdx != 0 )
+             temp1 += 1 ;
+@@ -3026,10 +3103,10 @@ void XGI_SetLVDSRegs( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTab
+             temp2 = temp1 ;
+             push3 = temp2 ;
+ 
+-            XGINew_SetReg1( pVBInfo->Part1Port , 0x37 , ( USHORT )( temp2 & 0xff ) ) ;
+-            XGINew_SetReg1( pVBInfo->Part1Port , 0x36 , ( USHORT )( ( temp2 >> 8 ) & 0xff ) ) ;
++	    XGINew_SetReg1(pVBInfo->Part1Port, 0x37, (unsigned short)(temp2 & 0xff));
++	    XGINew_SetReg1(pVBInfo->Part1Port, 0x36, (unsigned short)((temp2 >> 8) & 0xff));
+ 
+-            tempbx = ( USHORT )( temp2 >> 16 ) ;
++	    tempbx = (unsigned short)(temp2 >> 16);
+             tempax = tempbx & 0x03 ;
+ 
+             tempbx = pVBInfo->VGAVDE ;
+@@ -3041,10 +3118,10 @@ void XGI_SetLVDSRegs( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTab
+             if ( pVBInfo->VBType & VB_XGI301C )
+             {
+                 temp2 = push3 ;
+-      	        XGINew_SetReg1( pVBInfo->Part4Port , 0x3c , ( USHORT )( temp2 & 0xff ) ) ;
+-      	        XGINew_SetReg1( pVBInfo->Part4Port , 0x3b , ( USHORT )( ( temp2 >> 8 ) & 0xff ) ) ;
+-      	        tempbx = ( USHORT )( temp2 >> 16 ) ;
+-      	        XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x3a , ~0xc0 , ( USHORT )( ( tempbx & 0xff ) << 6 ) ) ;
++		XGINew_SetReg1(pVBInfo->Part4Port, 0x3c, (unsigned short)(temp2 & 0xff));
++		XGINew_SetReg1(pVBInfo->Part4Port, 0x3b, (unsigned short)((temp2 >> 8) & 0xff));
++		tempbx = (unsigned short)(temp2 >> 16);
++		XGINew_SetRegANDOR(pVBInfo->Part4Port, 0x3a, ~0xc0, (unsigned short)((tempbx & 0xff) << 6));
+ 
+                 tempcx = pVBInfo->VGAVDE ;
+                 if ( tempcx == pVBInfo->VDE )
+@@ -3058,7 +3135,7 @@ void XGI_SetLVDSRegs( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTab
+ 
+             temp1 = tempcx << 16 ;
+ 
+-            tempax = ( USHORT )( temp1 / tempbx ) ;
++	    tempax = (unsigned short)(temp1 / tempbx);
+ 
+             if ( ( tempbx & 0xffff ) == ( tempcx & 0xffff ) )
+                 tempax = 65535 ;
+@@ -3072,28 +3149,28 @@ void XGI_SetLVDSRegs( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTab
+ 
+             temp3 = ( temp3 & 0xffff0000 ) + ( temp1 & 0xffff ) ;
+ 
+-            tempax = ( USHORT )( temp3 & 0xff ) ;
++	    tempax = (unsigned short)(temp3 & 0xff);
+             XGINew_SetReg1( pVBInfo->Part1Port , 0x1f , tempax ) ;
+ 
+             temp1 = pVBInfo->VGAVDE << 18 ;
+             temp1 = temp1 / push3 ;
+-            tempbx = ( USHORT )( temp1 & 0xffff ) ;
++	    tempbx = (unsigned short)(temp1 & 0xffff);
+ 
+             if ( pVBInfo->LCDResInfo == Panel1024x768 )
+                 tempbx -= 1 ;
+ 
+             tempax = ( ( tempbx >> 8 ) & 0xff ) << 3 ;
+-            tempax |= ( USHORT )( ( temp3 >> 8 ) & 0x07 ) ;
+-            XGINew_SetReg1( pVBInfo->Part1Port , 0x20 , ( USHORT )( tempax & 0xff ) ) ;
+-            XGINew_SetReg1( pVBInfo->Part1Port , 0x21 , ( USHORT )( tempbx & 0xff ) ) ;
++	    tempax |= (unsigned short)((temp3 >> 8) & 0x07);
++	    XGINew_SetReg1(pVBInfo->Part1Port, 0x20, (unsigned short)(tempax & 0xff));
++	    XGINew_SetReg1(pVBInfo->Part1Port, 0x21, (unsigned short)(tempbx & 0xff));
+ 
+             temp3 = temp3 >> 16 ;
+ 
+             if ( modeflag & HalfDCLK )
+                 temp3 = temp3 >> 1 ;
+ 
+-            XGINew_SetReg1(pVBInfo->Part1Port , 0x22 , ( USHORT )( ( temp3 >> 8 ) & 0xff ) ) ;
+-            XGINew_SetReg1(pVBInfo->Part1Port , 0x23 , ( USHORT )( temp3 & 0xff ) ) ;
++	    XGINew_SetReg1(pVBInfo->Part1Port , 0x22, (unsigned short)((temp3 >> 8) & 0xff));
++	    XGINew_SetReg1(pVBInfo->Part1Port , 0x23, (unsigned short)(temp3 & 0xff));
+         }
+     }
+ }
+@@ -3105,7 +3182,7 @@ void XGI_SetLVDSRegs( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTab
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetCRT2ECLK( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO  pVBInfo )
++void XGI_SetCRT2ECLK(unsigned short ModeNo , unsigned short ModeIdIndex , unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO  pVBInfo )
+ {
+     UCHAR di_0 , di_1 , tempal ;
+     int i ;
+@@ -3116,7 +3193,7 @@ void XGI_SetCRT2ECLK( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTab
+ 
+     for( i = 0 ; i < 4 ; i++ )
+     {
+-        XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x31 , ~0x30 , ( USHORT )( 0x10 * i ) ) ;
++	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x31, ~0x30, (unsigned short)(0x10 * i));
+         if ( pVBInfo->IF_DEF_CH7007 == 1 )
+         {
+             XGINew_SetReg1( pVBInfo->P3c4 , 0x2b , di_0 ) ;
+@@ -3144,7 +3221,7 @@ void XGI_SetCRT2ECLK( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTab
+ /* --------------------------------------------------------------------- */
+ void XGI_UpdateModeInfo( PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO  pVBInfo )
+ {
+-    USHORT tempcl ,
++    unsigned short tempcl ,
+            tempch ,
+            temp ,
+            tempbl ,
+@@ -3274,7 +3351,7 @@ void XGI_GetVGAType( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO  pVB
+ /* --------------------------------------------------------------------- */
+ void XGI_GetVBType(PVB_DEVICE_INFO  pVBInfo)
+ {
+-    USHORT flag , tempbx , tempah ;
++    unsigned short flag , tempbx , tempah ;
+ 
+     if ( pVBInfo->IF_DEF_CH7007 == 1 )
+     {
+@@ -3335,9 +3412,9 @@ void XGI_GetVBType(PVB_DEVICE_INFO  pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_GetVBInfo( USHORT ModeNo , USHORT ModeIdIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO  pVBInfo )
++void XGI_GetVBInfo(unsigned short ModeNo , unsigned short ModeIdIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO  pVBInfo )
+ {
+-    USHORT tempax ,
++    unsigned short tempax ,
+            push ,
+            tempbx ,
+            temp ,
+@@ -3576,9 +3653,9 @@ void XGI_GetVBInfo( USHORT ModeNo , USHORT ModeIdIndex , PXGI_HW_DEVICE_INFO HwD
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_GetTVInfo( USHORT ModeNo , USHORT ModeIdIndex ,PVB_DEVICE_INFO  pVBInfo )
++void XGI_GetTVInfo(unsigned short ModeNo , unsigned short ModeIdIndex ,PVB_DEVICE_INFO  pVBInfo )
+ {
+-    USHORT temp ,
++    unsigned short temp ,
+            tempbx = 0 ,
+            resinfo = 0 ,
+            modeflag ,
+@@ -3711,9 +3788,9 @@ void XGI_GetTVInfo( USHORT ModeNo , USHORT ModeIdIndex ,PVB_DEVICE_INFO  pVBInfo
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-BOOLEAN XGI_GetLCDInfo( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
++unsigned char XGI_GetLCDInfo(unsigned short ModeNo , unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT temp ,
++    unsigned short temp ,
+            tempax ,
+            tempbx ,
+            modeflag ,
+@@ -3920,7 +3997,7 @@ BOOLEAN XGI_GetLCDInfo( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBI
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-BOOLEAN XGI_SearchModeID( USHORT ModeNo , USHORT *ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
++unsigned char XGI_SearchModeID(unsigned short ModeNo , unsigned short *ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
+ {
+ 
+ 
+@@ -3975,9 +4052,9 @@ BOOLEAN XGI_SearchModeID( USHORT ModeNo , USHORT *ModeIdIndex, PVB_DEVICE_INFO p
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-BOOLEAN XGINew_CheckMemorySize(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo)
++unsigned char XGINew_CheckMemorySize(PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex,PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT memorysize ,
++    unsigned short memorysize ,
+            modeflag ,
+            temp ,
+            temp1 ,
+@@ -4057,10 +4134,10 @@ BOOLEAN XGINew_CheckMemorySize(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT Mode
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-/*void XGINew_IsLowResolution( USHORT ModeNo , USHORT ModeIdIndex, BOOLEAN XGINew_CheckMemorySize(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo)
++/*void XGINew_IsLowResolution(unsigned short ModeNo , unsigned short ModeIdIndex, unsigned char XGINew_CheckMemorySize(PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex,PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT data ;
+-    USHORT ModeFlag ;
++    unsigned short data ;
++    unsigned short ModeFlag ;
+ 
+     data = XGINew_GetReg1( pVBInfo->P3c4 , 0x0F ) ;
+     data &= 0x7F ;
+@@ -4226,7 +4303,7 @@ void XGI_SenseCRT1( PVB_DEVICE_INFO pVBInfo )
+     UCHAR SR01 = 0 , SR1F = 0 , SR07 = 0 , SR06 = 0 ;
+ 
+     UCHAR CR17 , CR63 , SR31 ;
+-    USHORT temp ;
++    unsigned short temp ;
+     UCHAR DAC_TEST_PARMS[ 3 ] = { 0x0F , 0x0F , 0x0F } ;
+ 
+     int i ;
+@@ -4257,18 +4334,18 @@ void XGI_SenseCRT1( PVB_DEVICE_INFO pVBInfo )
+     XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , 0x00 ) ;
+ 
+     for( i = 0 ; i < 8 ; i++ )
+-        XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )i , CRTCData[ i ] ) ;
++	    XGINew_SetReg1(pVBInfo->P3d4, (unsigned short)i, CRTCData[i]);
+ 
+     for( i = 8 ; i < 11 ; i++ )
+-        XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 8 ) , CRTCData[ i ] ) ;
++	    XGINew_SetReg1(pVBInfo->P3d4, (unsigned short)(i + 8), CRTCData[i]);
+ 
+     for( i = 11 ; i < 13 ; i++ )
+-        XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 4 ) , CRTCData[ i ] ) ;
++	    XGINew_SetReg1(pVBInfo->P3d4, (unsigned short)(i + 4), CRTCData[i]);
+ 
+     for( i = 13 ; i < 16 ; i++ )
+-        XGINew_SetReg1( pVBInfo->P3c4 , ( USHORT )( i - 3 ) , CRTCData[ i ] ) ;
++	    XGINew_SetReg1(pVBInfo->P3c4, (unsigned short)(i - 3), CRTCData[i]);
+ 
+-    XGINew_SetReg1( pVBInfo->P3c4 , 0x0E , ( UCHAR )( CRTCData[ 16 ] & 0xE0 ) ) ;
++    XGINew_SetReg1(pVBInfo->P3c4, 0x0E, (UCHAR)(CRTCData[16] & 0xE0));
+ 
+     XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , 0x00 ) ;
+     XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , 0x1B ) ;
+@@ -4351,9 +4428,9 @@ void XGI_WaitDisplay( PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-BOOLEAN XGI_SetCRT2Group301( USHORT ModeNo , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
++unsigned char XGI_SetCRT2Group301(unsigned short ModeNo , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
+ {
+-    USHORT tempbx ,
++    unsigned short tempbx ,
+            ModeIdIndex ,
+            RefreshRateTableIndex ;
+ 
+@@ -4399,9 +4476,9 @@ void XGI_AutoThreshold(  PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SaveCRT2Info( USHORT ModeNo , PVB_DEVICE_INFO pVBInfo)
++void XGI_SaveCRT2Info(unsigned short ModeNo , PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT temp1 ,
++    unsigned short temp1 ,
+            temp2 ;
+ 
+     XGINew_SetReg1( pVBInfo->P3d4 , 0x34 , ModeNo ) ;  /* reserve CR34 for CRT1 Mode No */
+@@ -4417,9 +4494,11 @@ void XGI_SaveCRT2Info( USHORT ModeNo , PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_GetCRT2ResInfo( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
++void XGI_GetCRT2ResInfo(unsigned short ModeNo,
++			unsigned short ModeIdIndex,
++			PVB_DEVICE_INFO pVBInfo )
+ {
+-    USHORT xres ,
++    unsigned short xres ,
+            yres ,
+            modeflag ,
+            resindex ;
+@@ -4514,7 +4593,7 @@ void XGI_GetCRT2ResInfo( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVB
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-BOOLEAN XGI_IsLCDDualLink( PVB_DEVICE_INFO pVBInfo )
++unsigned char XGI_IsLCDDualLink( PVB_DEVICE_INFO pVBInfo )
+ {
+ 
+     if ( ( ( ( pVBInfo->VBInfo & SetCRT2ToLCD ) | SetCRT2ToLCDA ) ) && ( pVBInfo->LCDInfo & SetLCDDualLink ) ) /* shampoo0129 */
+@@ -4530,9 +4609,9 @@ BOOLEAN XGI_IsLCDDualLink( PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_GetCRT2Data(  USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
++void XGI_GetCRT2Data(  unsigned short ModeNo , unsigned short ModeIdIndex , unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+ {
+-    USHORT tempax = 0,
++    unsigned short tempax = 0,
+            tempbx ,
+            modeflag ,
+            resinfo ;
+@@ -4756,7 +4835,7 @@ void XGI_GetCRT2Data(  USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTa
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetCRT2VCLK( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
++void XGI_SetCRT2VCLK(unsigned short ModeNo , unsigned short ModeIdIndex , unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+ {
+     UCHAR di_0 ,
+           di_1 ,
+@@ -4795,7 +4874,7 @@ void XGI_SetCRT2VCLK( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTab
+ /* --------------------------------------------------------------------- */
+ void XGI_GetLCDVCLKPtr( UCHAR* di_0 , UCHAR *di_1, PVB_DEVICE_INFO pVBInfo )
+ {
+-    USHORT index ;
++    unsigned short index ;
+ 
+     if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+     {
+@@ -4829,12 +4908,12 @@ void XGI_GetLCDVCLKPtr( UCHAR* di_0 , UCHAR *di_1, PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-UCHAR XGI_GetVCLKPtr(USHORT RefreshRateTableIndex,USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
++UCHAR XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex, unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+ {
+ 
+-    USHORT index ,
++    unsigned short index ,
+            modeflag ;
+-    USHORT tempbx ;
++    unsigned short tempbx ;
+     UCHAR tempal ;
+     UCHAR *CHTVVCLKPtr = NULL ;
+ 
+@@ -5039,10 +5118,10 @@ void XGI_GetVCLKLen(UCHAR tempal,UCHAR* di_0,UCHAR* di_1, PVB_DEVICE_INFO pVBInf
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetCRT2Offset( USHORT ModeNo ,
+-				   USHORT ModeIdIndex , USHORT RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
++void XGI_SetCRT2Offset(unsigned short ModeNo ,
++				   unsigned short ModeIdIndex , unsigned short RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
+ {
+-    USHORT offset ;
++    unsigned short offset ;
+     UCHAR temp ;
+ 
+     if ( pVBInfo->VBInfo & SetInSlaveMode )
+@@ -5066,9 +5145,9 @@ void XGI_SetCRT2Offset( USHORT ModeNo ,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-USHORT XGI_GetOffset(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo)
++unsigned short XGI_GetOffset(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT temp ,
++    unsigned short temp ,
+            colordepth ,
+            modeinfo ,
+            index ,
+@@ -5128,10 +5207,12 @@ void XGI_SetCRT2FIFO( PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_PreSetGroup1(USHORT ModeNo , USHORT ModeIdIndex ,PXGI_HW_DEVICE_INFO HwDeviceExtension,
+-                       USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
++void XGI_PreSetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
++		      PXGI_HW_DEVICE_INFO HwDeviceExtension,
++		      unsigned short RefreshRateTableIndex,
++		      PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT tempcx = 0 ,
++    unsigned short tempcx = 0 ,
+            CRT1Index = 0 ,
+            resinfo = 0 ;
+ 
+@@ -5162,10 +5243,12 @@ void XGI_PreSetGroup1(USHORT ModeNo , USHORT ModeIdIndex ,PXGI_HW_DEVICE_INFO Hw
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetGroup1( USHORT ModeNo , USHORT ModeIdIndex ,
+-                            PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
++void XGI_SetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
++		   PXGI_HW_DEVICE_INFO HwDeviceExtension,
++		   unsigned short RefreshRateTableIndex,
++		   PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT temp = 0 ,
++    unsigned short temp = 0 ,
+            tempax = 0 ,
+            tempbx = 0 ,
+            tempcx = 0 ,
+@@ -5338,10 +5421,12 @@ void XGI_SetGroup1( USHORT ModeNo , USHORT ModeIdIndex ,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void  XGI_SetLockRegs( USHORT ModeNo , USHORT ModeIdIndex ,
+-                                PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
++void  XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
++		      PXGI_HW_DEVICE_INFO HwDeviceExtension,
++		      unsigned short RefreshRateTableIndex,
++		      PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT push1 ,
++    unsigned short push1 ,
+            push2 ,
+            tempax ,
+            tempbx = 0 ,
+@@ -5785,10 +5870,10 @@ void  XGI_SetLockRegs( USHORT ModeNo , USHORT ModeIdIndex ,
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetGroup2( USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex,
++void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,
+                     PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
+ {
+-    USHORT i ,
++    unsigned short i ,
+            j ,
+            tempax ,
+            tempbx ,
+@@ -5801,7 +5886,7 @@ void XGI_SetGroup2( USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIn
+            crt2crtc ;
+     UCHAR *TimingPoint ;
+ 
+-    ULONG longtemp ,
++    unsigned long longtemp ,
+           tempeax ,
+           tempebx ,
+           temp2 ,
+@@ -5910,7 +5995,7 @@ void XGI_SetGroup2( USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIn
+         tempax = ( tempax & 0x00FF ) | ( ( tempax & 0x00FF ) << 8 ) ;
+         push1 = tempax ;
+         temp = ( tempax & 0xFF00 ) >> 8 ;
+-        temp += ( USHORT )TimingPoint[ 0 ] ;
++	temp += (unsigned short)TimingPoint[0];
+ 
+         if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+         {
+@@ -6187,7 +6272,7 @@ void XGI_SetGroup2( USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIn
+             tempeax += 1 ;
+         }
+ 
+-        tempax = ( USHORT )tempeax ;
++	tempax = (unsigned short)tempeax;
+ 
+ 	/* 301b */
+         if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+@@ -6197,8 +6282,8 @@ void XGI_SetGroup2( USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIn
+         /* end 301b */
+ 
+         tempbx = push1 ;
+-        tempbx =( USHORT )( ( ( tempeax & 0x0000FF00 ) & 0x1F00 ) | ( tempbx & 0x00FF ) ) ;
+-        tempax =( USHORT )( ( ( tempeax & 0x000000FF ) << 8 ) | ( tempax & 0x00FF ) ) ;
++	tempbx = (unsigned short)(((tempeax & 0x0000FF00) & 0x1F00) | (tempbx & 0x00FF));
++	tempax = (unsigned short)(((tempeax & 0x000000FF) << 8) | (tempax & 0x00FF));
+         temp = ( tempax & 0xFF00 ) >> 8 ;
+     }
+     else
+@@ -6251,7 +6336,7 @@ void XGI_SetGroup2( USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIn
+ 
+     XGINew_SetReg1( pVBInfo->Part2Port , 0x4d , temp ) ;
+     temp=XGINew_GetReg1( pVBInfo->Part2Port , 0x43 ) ;		/* 301b change */
+-    XGINew_SetReg1( pVBInfo->Part2Port , 0x43 , ( USHORT )( temp - 3 ) ) ;
++    XGINew_SetReg1( pVBInfo->Part2Port , 0x43, (unsigned short)( temp - 3 ) ) ;
+ 
+     if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) ) )
+     {
+@@ -6304,9 +6389,9 @@ void XGI_SetGroup2( USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIn
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void  XGI_SetLCDRegs(USHORT ModeNo,USHORT ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo)
++void  XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension, unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT push1 ,
++    unsigned short push1 ,
+            push2 ,
+            pushbx ,
+            tempax ,
+@@ -6558,9 +6643,10 @@ void  XGI_SetLCDRegs(USHORT ModeNo,USHORT ModeIdIndex, PXGI_HW_DEVICE_INFO HwDev
+ /* Output : di -> Tap4 Reg. Setting Pointer */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-XGI301C_Tap4TimingStruct* XGI_GetTap4Ptr(USHORT tempcx, PVB_DEVICE_INFO pVBInfo)
++XGI301C_Tap4TimingStruct *XGI_GetTap4Ptr(unsigned short tempcx,
++					 PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT tempax ,
++    unsigned short tempax ,
+            tempbx ,
+            i ;
+ 
+@@ -6620,7 +6706,7 @@ XGI301C_Tap4TimingStruct* XGI_GetTap4Ptr(USHORT tempcx, PVB_DEVICE_INFO pVBInfo)
+ /* --------------------------------------------------------------------- */
+ void XGI_SetTap4Regs( PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT i ,
++    unsigned short i ,
+            j ;
+ 
+     XGI301C_Tap4TimingStruct *Tap4TimingPtr ;
+@@ -6656,11 +6742,11 @@ void XGI_SetTap4Regs( PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetGroup3(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
++void XGI_SetGroup3(unsigned short ModeNo, unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT i;
++    unsigned short i;
+     UCHAR *tempdi;
+-    USHORT  modeflag;
++    unsigned short  modeflag;
+ 
+     if(ModeNo<=0x13)
+     {
+@@ -6743,16 +6829,16 @@ void XGI_SetGroup3(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetGroup4(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT tempax ,
++    unsigned short tempax ,
+            tempcx ,
+            tempbx ,
+            modeflag ,
+            temp ,
+            temp2 ;
+ 
+-    ULONG tempebx ,
++    unsigned long tempebx ,
+           tempeax ,
+           templong ;
+ 
+@@ -6874,12 +6960,12 @@ void XGI_SetGroup4(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex
+     }
+ 
+ 
+-    temp = ( USHORT )( tempebx & 0x000000FF ) ;
++    temp = (unsigned short)(tempebx & 0x000000FF);
+     XGINew_SetReg1( pVBInfo->Part4Port , 0x1B , temp ) ;
+ 
+-    temp = ( USHORT )( ( tempebx & 0x0000FF00 ) >> 8 ) ;
++    temp = (unsigned short)((tempebx & 0x0000FF00) >> 8);
+     XGINew_SetReg1( pVBInfo->Part4Port , 0x1A , temp ) ;
+-    tempbx = ( USHORT )( tempebx >> 16 ) ;
++    tempbx = (unsigned short)(tempebx >> 16);
+     temp = tempbx & 0x00FF ;
+     temp = temp << 4 ;
+     temp |= ( ( tempcx & 0xFF00 ) >> 8 ) ;
+@@ -6994,9 +7080,9 @@ void XGI_SetGroup4(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetGroup5( USHORT ModeNo , USHORT ModeIdIndex , PVB_DEVICE_INFO pVBInfo)
++void XGI_SetGroup5(unsigned short ModeNo , unsigned short ModeIdIndex , PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT Pindex ,
++    unsigned short Pindex ,
+            Pdata ;
+ 
+     Pindex = pVBInfo->Part5Port ;
+@@ -7019,9 +7105,13 @@ void XGI_SetGroup5( USHORT ModeNo , USHORT ModeIdIndex , PVB_DEVICE_INFO pVBInfo
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void* XGI_GetLcdPtr( USHORT BX , USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
++void *XGI_GetLcdPtr(unsigned short BX,
++		    unsigned short ModeNo,
++		    unsigned short ModeIdIndex,
++		    unsigned short RefreshRateTableIndex,
++		    PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT i ,
++    unsigned short i ,
+            tempdx ,
+            tempcx ,
+            tempbx ,
+@@ -7521,9 +7611,12 @@ void* XGI_GetLcdPtr( USHORT BX , USHORT ModeNo , USHORT ModeIdIndex , USHORT Ref
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void* XGI_GetTVPtr (USHORT BX,USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
++void *XGI_GetTVPtr(unsigned short BX, unsigned short ModeNo,
++		   unsigned short ModeIdIndex,
++		   unsigned short RefreshRateTableIndex,
++		   PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT i , tempdx , tempbx , tempal , modeflag , table ;
++    unsigned short i , tempdx , tempbx , tempal , modeflag , table ;
+     XGI330_TVDataTablStruct *tempdi = 0 ;
+ 
+     tempbx = BX ;
+@@ -7686,7 +7779,7 @@ void* XGI_GetTVPtr (USHORT BX,USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRat
+ /* Output : 1 -> Skip backlight control */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-BOOLEAN XGI_BacklightByDrv( PVB_DEVICE_INFO pVBInfo )
++unsigned char XGI_BacklightByDrv(PVB_DEVICE_INFO pVBInfo)
+ {
+     UCHAR tempah ;
+ 
+@@ -7758,9 +7851,9 @@ void XGI_DisableGatingCRT(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO
+ /* : bl : 3 ; T3 : the duration between CPL off and signal off */
+ /* : bl : 4 ; T4 : the duration signal off and Vdd off */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetPanelDelay(USHORT tempbl, PVB_DEVICE_INFO pVBInfo)
++void XGI_SetPanelDelay(unsigned short tempbl, PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT index ;
++    unsigned short index ;
+ 
+     index = XGI_GetLCDCapPtr(pVBInfo) ;
+ 
+@@ -7788,7 +7881,7 @@ void XGI_SetPanelDelay(USHORT tempbl, PVB_DEVICE_INFO pVBInfo)
+ /* = 1011b = 0Bh ; Backlight off, Power on */
+ /* = 1111b = 0Fh ; Backlight off, Power off */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetPanelPower(USHORT tempah,USHORT tempbl, PVB_DEVICE_INFO pVBInfo)
++void XGI_SetPanelPower(unsigned short tempah, unsigned short tempbl, PVB_DEVICE_INFO pVBInfo)
+ {
+     if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+         XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x26 , tempbl , tempah ) ;
+@@ -7863,7 +7956,7 @@ UCHAR XGI_XG27GetPSCValue(PVB_DEVICE_INFO pVBInfo)
+ /*          000010b : clear bit 1, to set bit1                                */
+ /*          000001b : clear bit 0, to set bit0                                */
+ /*----------------------------------------------------------------------------*/
+-void XGI_XG21BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo)
++void XGI_XG21BLSignalVDD(unsigned short tempbh, unsigned short tempbl, PVB_DEVICE_INFO pVBInfo)
+ {
+     UCHAR CR4A,temp;
+ 
+@@ -7888,10 +7981,10 @@ void XGI_XG21BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo)
+     XGINew_SetReg1( pVBInfo->P3d4 , 0x48 , temp ) ;
+ }
+ 
+-void XGI_XG27BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo)
++void XGI_XG27BLSignalVDD(unsigned short tempbh, unsigned short tempbl, PVB_DEVICE_INFO pVBInfo)
+ {
+     UCHAR CR4A,temp;
+-    USHORT tempbh0,tempbl0;
++    unsigned short tempbh0, tempbl0;
+ 
+     tempbh0 = tempbh;
+     tempbl0 = tempbl;
+@@ -7919,9 +8012,9 @@ void XGI_XG27BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo)
+ }
+ 
+ /* --------------------------------------------------------------------- */
+-USHORT XGI_GetLVDSOEMTableIndex(PVB_DEVICE_INFO pVBInfo)
++unsigned short XGI_GetLVDSOEMTableIndex(PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT index ;
++    unsigned short index ;
+ 
+     index = XGINew_GetReg1( pVBInfo->P3d4 , 0x36 ) ;
+     if (indexXG21_LVDSCapList[ index ].PSC_S4, pVBInfo ) ;
+ }
+ 
+-BOOLEAN XGI_XG21CheckLVDSMode(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
++unsigned char XGI_XG21CheckLVDSMode(unsigned short ModeNo,
++				    unsigned short ModeIdIndex,
++				    PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT xres ,
++    unsigned short xres ,
+            yres ,
+            colordepth ,
+            modeflag ,
+@@ -8043,17 +8138,18 @@ void XGI_SetXG27FPBits(PVB_DEVICE_INFO pVBInfo)
+ 
+ }
+ 
+-void XGI_SetXG21LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
++void XGI_SetXG21LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex,
++			 PVB_DEVICE_INFO pVBInfo)
+ {
+     UCHAR temp,Miscdata;
+-    USHORT xres ,
++    unsigned short xres ,
+            yres ,
+            modeflag ,
+            resindex ,
+            lvdstableindex ;
+-    USHORT LVDSHT,LVDSHBS,LVDSHRS,LVDSHRE,LVDSHBE;
+-    USHORT LVDSVT,LVDSVBS,LVDSVRS,LVDSVRE,LVDSVBE;
+-    USHORT value;
++    unsigned short LVDSHT,LVDSHBS,LVDSHRS,LVDSHRE,LVDSHBE;
++    unsigned short LVDSVT,LVDSVBS,LVDSVRS,LVDSVRE,LVDSVBE;
++    unsigned short value;
+ 
+     lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo );
+ 
+@@ -8226,17 +8322,18 @@ void XGI_SetXG21LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBIn
+ }
+ 
+ /* no shadow case */
+-void XGI_SetXG27LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
++void XGI_SetXG27LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex,
++			 PVB_DEVICE_INFO pVBInfo)
+ {
+     UCHAR temp,Miscdata;
+-    USHORT xres ,
++    unsigned short xres ,
+            yres ,
+            modeflag ,
+            resindex ,
+            lvdstableindex ;
+-    USHORT LVDSHT,LVDSHBS,LVDSHRS,LVDSHRE,LVDSHBE;
+-    USHORT LVDSVT,LVDSVBS,LVDSVRS,LVDSVRE,LVDSVBE;
+-    USHORT value;
++    unsigned short LVDSHT,LVDSHBS,LVDSHRS,LVDSHRE,LVDSHBE;
++    unsigned short LVDSVT,LVDSVBS,LVDSVRS,LVDSVRE,LVDSVBE;
++    unsigned short value;
+ 
+     lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo );
+     temp = (UCHAR) ( ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability & (LCDPolarity << 8 ) ) >> 8 );
+@@ -8413,9 +8510,9 @@ void XGI_SetXG27LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBIn
+ /* 1: Disable PSC */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-BOOLEAN XGI_IsLCDON(PVB_DEVICE_INFO pVBInfo)
++unsigned char XGI_IsLCDON(PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT tempax ;
++    unsigned short tempax ;
+ 
+     tempax = pVBInfo->VBInfo ;
+     if ( tempax & SetCRT2ToDualEdge )
+@@ -8435,7 +8532,7 @@ BOOLEAN XGI_IsLCDON(PVB_DEVICE_INFO pVBInfo)
+ /* --------------------------------------------------------------------- */
+ void XGI_EnablePWD(  PVB_DEVICE_INFO pVBInfo )
+ {
+-    USHORT index ,
++    unsigned short index ,
+            temp ;
+ 
+     index = XGI_GetLCDCapPtr(pVBInfo) ;
+@@ -8467,13 +8564,13 @@ void XGI_DisablePWD( PVB_DEVICE_INFO pVBInfo )
+ /* Output : 0 -> Not LCD Mode */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-BOOLEAN XGI_DisableChISLCD(PVB_DEVICE_INFO pVBInfo)
++unsigned char XGI_DisableChISLCD(PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT tempbx ,
++    unsigned short tempbx ,
+            tempah ;
+ 
+     tempbx = pVBInfo->SetFlag & ( DisableChA | DisableChB ) ;
+-    tempah = ~( ( USHORT )XGINew_GetReg1( pVBInfo->Part1Port  , 0x2E ) ) ;
++    tempah = ~((unsigned short) XGINew_GetReg1(pVBInfo->Part1Port, 0x2E));
+ 
+     if ( tempbx & ( EnableChA | DisableChA ) )
+     {
+@@ -8497,14 +8594,14 @@ BOOLEAN XGI_DisableChISLCD(PVB_DEVICE_INFO pVBInfo)
+ /* Output : 0 -> Not LCD mode */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-BOOLEAN XGI_EnableChISLCD(PVB_DEVICE_INFO pVBInfo)
++unsigned char XGI_EnableChISLCD(PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT tempbx ,
++    unsigned short tempbx ,
+            tempah ;
+ 
+ 
+     tempbx = pVBInfo->SetFlag & ( EnableChA | EnableChB ) ;
+-    tempah = ~( ( USHORT )XGINew_GetReg1( pVBInfo->Part1Port , 0x2E ) ) ;
++    tempah = ~( (unsigned short)XGINew_GetReg1( pVBInfo->Part1Port , 0x2E ) ) ;
+ 
+     if ( tempbx & ( EnableChA | DisableChA ) )
+     {
+@@ -8528,7 +8625,7 @@ BOOLEAN XGI_EnableChISLCD(PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-USHORT XGI_GetLCDCapPtr(  PVB_DEVICE_INFO pVBInfo )
++unsigned short XGI_GetLCDCapPtr(PVB_DEVICE_INFO pVBInfo)
+ {
+     UCHAR tempal ,
+           tempah ,
+@@ -8567,9 +8664,9 @@ USHORT XGI_GetLCDCapPtr(  PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-USHORT XGI_GetLCDCapPtr1( PVB_DEVICE_INFO pVBInfo )
++unsigned short XGI_GetLCDCapPtr1(PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT tempah ,
++    unsigned short tempah ,
+            tempal ,
+            tempbl ,
+            i ;
+@@ -8612,9 +8709,10 @@ USHORT XGI_GetLCDCapPtr1( PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_GetLCDSync( USHORT* HSyncWidth , USHORT* VSyncWidth, PVB_DEVICE_INFO pVBInfo )
++void XGI_GetLCDSync(unsigned short *HSyncWidth , unsigned short *VSyncWidth,
++		    PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT Index ;
++    unsigned short Index ;
+ 
+     Index = XGI_GetLCDCapPtr(pVBInfo) ;
+     *HSyncWidth = pVBInfo->LCDCapList[ Index ].LCD_HSyncWidth ;
+@@ -8633,7 +8731,7 @@ void XGI_GetLCDSync( USHORT* HSyncWidth , USHORT* VSyncWidth, PVB_DEVICE_INFO pV
+ /* --------------------------------------------------------------------- */
+ void XGI_EnableBridge( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT tempbl ,
++    unsigned short tempbl ,
+            tempah ;
+ 
+     if ( pVBInfo->SetFlag == Win9xDOSMode )
+@@ -8847,7 +8945,7 @@ void XGI_EnableBridge( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO p
+ /* --------------------------------------------------------------------- */
+ void XGI_DisableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT tempax ,
++    unsigned short tempax ,
+            tempbx ,
+            tempah = 0 ,
+            tempbl = 0 ;
+@@ -9026,9 +9124,9 @@ void XGI_DisableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pV
+ /* A : Ext750p */
+ /* B : St750p */
+ /* --------------------------------------------------------------------- */
+-USHORT XGI_GetTVPtrIndex(  PVB_DEVICE_INFO pVBInfo )
++unsigned short XGI_GetTVPtrIndex(PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT tempbx = 0 ;
++    unsigned short tempbx = 0 ;
+ 
+     if ( pVBInfo->TVInfo & SetPALTV )
+         tempbx = 2 ;
+@@ -9053,7 +9151,7 @@ USHORT XGI_GetTVPtrIndex(  PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : Customized Param. for 301 */
+ /* --------------------------------------------------------------------- */
+-void XGI_OEM310Setting( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
++void XGI_OEM310Setting(unsigned short ModeNo , unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+ {
+     if ( pVBInfo->SetFlag & Win9xDOSMode )
+         return ;
+@@ -9085,7 +9183,7 @@ void XGI_OEM310Setting( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBI
+ /* --------------------------------------------------------------------- */
+ void XGI_SetDelayComp( PVB_DEVICE_INFO pVBInfo )
+ {
+-    USHORT index ;
++    unsigned short index ;
+ 
+     UCHAR  tempah ,
+            tempbl ,
+@@ -9163,7 +9261,7 @@ void XGI_SetDelayComp( PVB_DEVICE_INFO pVBInfo )
+ /* --------------------------------------------------------------------- */
+ void XGI_SetLCDCap( PVB_DEVICE_INFO pVBInfo )
+ {
+-    USHORT tempcx ;
++    unsigned short tempcx ;
+ 
+     tempcx = pVBInfo->LCDCapList[ XGI_GetLCDCapPtr(pVBInfo) ].LCD_Capability ;
+ 
+@@ -9172,10 +9270,12 @@ void XGI_SetLCDCap( PVB_DEVICE_INFO pVBInfo )
+         if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+         {        				/* 301LV/302LV only */
+             /* Set 301LV Capability */
+-            XGINew_SetReg1( pVBInfo->Part4Port , 0x24 , ( UCHAR )( tempcx & 0x1F ) ) ;
++		XGINew_SetReg1(pVBInfo->Part4Port, 0x24, (UCHAR)(tempcx & 0x1F));
+ 	}
+         /* VB Driving */
+-        XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x0D , ~( ( EnableVBCLKDRVLOW | EnablePLLSPLOW ) >> 8 ) , ( USHORT )( ( tempcx & ( EnableVBCLKDRVLOW | EnablePLLSPLOW ) ) >> 8 ) ) ;
++	XGINew_SetRegANDOR(pVBInfo->Part4Port, 0x0D,
++			   ~((EnableVBCLKDRVLOW | EnablePLLSPLOW) >> 8),
++			   (unsigned short)((tempcx & (EnableVBCLKDRVLOW | EnablePLLSPLOW)) >> 8));
+     }
+ 
+     if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+@@ -9202,32 +9302,34 @@ void XGI_SetLCDCap( PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetLCDCap_A(USHORT tempcx,PVB_DEVICE_INFO pVBInfo)
++void XGI_SetLCDCap_A(unsigned short tempcx, PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT temp ;
++    unsigned short temp ;
+ 
+     temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x37 ) ;
+ 
+     if ( temp & LCDRGB18Bit )
+     {
+-        XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x19 , 0x0F , ( USHORT )( 0x20 | ( tempcx & 0x00C0 ) ) ) ; /* Enable Dither */
++	XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x19, 0x0F,
++			   (unsigned short)(0x20 | (tempcx & 0x00C0))); /* Enable Dither */
+         XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x1A , 0x7F , 0x80 ) ;
+     }
+     else
+     {
+-        XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x19 , 0x0F , ( USHORT )( 0x30 | ( tempcx & 0x00C0 ) ) ) ;
++	XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x19, 0x0F,
++			   (unsigned short)(0x30 | (tempcx & 0x00C0)));
+         XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x1A , 0x7F , 0x00 ) ;
+     }
+ 
+ /*
+     if ( tempcx & EnableLCD24bpp )	// 24bits
+     {
+-        XGINew_SetRegANDOR(pVBInfo->Part1Port,0x19, 0x0F,(USHORT)(0x30|(tempcx&0x00C0)) );
++	XGINew_SetRegANDOR(pVBInfo->Part1Port,0x19, 0x0F,(unsigned short)(0x30|(tempcx&0x00C0)) );
+         XGINew_SetRegANDOR(pVBInfo->Part1Port,0x1A,0x7F,0x00);
+     }
+     else
+     {
+-        XGINew_SetRegANDOR(pVBInfo->Part1Port,0x19, 0x0F,(USHORT)(0x20|(tempcx&0x00C0)) );//Enable Dither
++	XGINew_SetRegANDOR(pVBInfo->Part1Port,0x19, 0x0F,(unsigned short)(0x20|(tempcx&0x00C0)) ); // Enable Dither
+         XGINew_SetRegANDOR(pVBInfo->Part1Port,0x1A,0x7F,0x80);
+     }
+ */
+@@ -9240,12 +9342,14 @@ void XGI_SetLCDCap_A(USHORT tempcx,PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetLCDCap_B(USHORT tempcx,PVB_DEVICE_INFO pVBInfo)
++void XGI_SetLCDCap_B(unsigned short tempcx, PVB_DEVICE_INFO pVBInfo)
+ {
+     if ( tempcx & EnableLCD24bpp )	/* 24bits */
+-        XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x1A , 0xE0 , ( USHORT )( ( ( tempcx & 0x00ff ) >> 6 ) | 0x0c ) ) ;
++	    XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x1A, 0xE0,
++			       (unsigned short)(((tempcx & 0x00ff) >> 6) | 0x0c));
+     else
+-        XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x1A , 0xE0 , ( USHORT )( ( ( tempcx & 0x00ff ) >> 6 ) | 0x18 ) ) ; /* Enable Dither */
++	    XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x1A, 0xE0,
++			       (unsigned short)(((tempcx & 0x00ff) >> 6) | 0x18)); /* Enable Dither */
+ }
+ 
+ 
+@@ -9257,7 +9361,7 @@ void XGI_SetLCDCap_B(USHORT tempcx,PVB_DEVICE_INFO pVBInfo)
+ /* --------------------------------------------------------------------- */
+ void SetSpectrum( PVB_DEVICE_INFO pVBInfo )
+ {
+-    USHORT index ;
++    unsigned short index ;
+ 
+     index = XGI_GetLCDCapPtr(pVBInfo) ;
+ 
+@@ -9281,9 +9385,10 @@ void SetSpectrum( PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : Set TV Customized Param. */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetAntiFlicker( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
++void XGI_SetAntiFlicker(unsigned short ModeNo, unsigned short ModeIdIndex,
++			PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT tempbx ,
++    unsigned short tempbx ,
+            index ;
+ 
+     UCHAR tempah ;
+@@ -9317,9 +9422,9 @@ void XGI_SetAntiFlicker( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVB
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetEdgeEnhance( USHORT ModeNo , USHORT ModeIdIndex , PVB_DEVICE_INFO pVBInfo)
++void XGI_SetEdgeEnhance(unsigned short ModeNo , unsigned short ModeIdIndex , PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT tempbx ,
++    unsigned short tempbx ,
+            index ;
+ 
+     UCHAR tempah ;
+@@ -9353,20 +9458,24 @@ void XGI_SetEdgeEnhance( USHORT ModeNo , USHORT ModeIdIndex , PVB_DEVICE_INFO pV
+ /* --------------------------------------------------------------------- */
+ void XGI_SetPhaseIncr( PVB_DEVICE_INFO pVBInfo )
+ {
+-    USHORT tempbx ;
++    unsigned short tempbx ;
+ 
+     UCHAR tempcl ,
+           tempch ;
+ 
+-    ULONG tempData ;
++    unsigned long tempData ;
+ 
+     XGI_GetTVPtrIndex2( &tempbx , &tempcl , &tempch, pVBInfo ) ; /* bx, cl, ch */
+     tempData = TVPhaseList[ tempbx ] ;
+ 
+-    XGINew_SetReg1( pVBInfo->Part2Port , 0x31 , ( USHORT )( tempData & 0x000000FF ) ) ;
+-    XGINew_SetReg1( pVBInfo->Part2Port , 0x32 , ( USHORT )( ( tempData & 0x0000FF00 ) >> 8 ) ) ;
+-    XGINew_SetReg1( pVBInfo->Part2Port , 0x33 , ( USHORT )( ( tempData & 0x00FF0000 ) >> 16 ) ) ;
+-    XGINew_SetReg1( pVBInfo->Part2Port , 0x34 , ( USHORT )( ( tempData & 0xFF000000 ) >> 24 ) ) ;
++    XGINew_SetReg1(pVBInfo->Part2Port, 0x31,
++		   (unsigned short)(tempData & 0x000000FF));
++    XGINew_SetReg1(pVBInfo->Part2Port, 0x32,
++		   (unsigned short)((tempData & 0x0000FF00) >> 8));
++    XGINew_SetReg1(pVBInfo->Part2Port, 0x33,
++		   (unsigned short)((tempData & 0x00FF0000) >> 16));
++    XGINew_SetReg1(pVBInfo->Part2Port, 0x34,
++		   (unsigned short)((tempData & 0xFF000000) >> 24));
+ }
+ 
+ 
+@@ -9376,9 +9485,10 @@ void XGI_SetPhaseIncr( PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetYFilter( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
++void XGI_SetYFilter(unsigned short ModeNo, unsigned short ModeIdIndex,
++		    PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT tempbx ,
++    unsigned short tempbx ,
+            index ;
+ 
+     UCHAR tempcl ,
+@@ -9480,7 +9590,7 @@ void XGI_SetYFilter( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo
+ /* 1 : 301B/302B/301LV/302LV */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_GetTVPtrIndex2(USHORT* tempbx,UCHAR* tempcl,UCHAR* tempch, PVB_DEVICE_INFO pVBInfo)
++void XGI_GetTVPtrIndex2(unsigned short *tempbx,UCHAR* tempcl,UCHAR* tempch, PVB_DEVICE_INFO pVBInfo)
+ {
+     *tempbx = 0 ;
+     *tempcl = 0 ;
+@@ -9522,9 +9632,11 @@ void XGI_GetTVPtrIndex2(USHORT* tempbx,UCHAR* tempcl,UCHAR* tempch, PVB_DEVICE_I
+ /* Output : */
+ /* Description : Origin code for crt2group */
+ /* --------------------------------------------------------------------- */
+-void XGI_SetCRT2ModeRegs(USHORT ModeNo,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
++void XGI_SetCRT2ModeRegs(unsigned short ModeNo,
++			 PXGI_HW_DEVICE_INFO HwDeviceExtension,
++			 PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT tempbl ;
++    unsigned short tempbl ;
+     SHORT  tempcl ;
+ 
+     UCHAR  tempah ;
+@@ -9753,7 +9865,7 @@ void XGI_SetCRT2ModeRegs(USHORT ModeNo,PXGI_HW_DEVICE_INFO HwDeviceExtension, PV
+ /* --------------------------------------------------------------------- */
+ void XGI_CloseCRTC( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
+ {
+-    USHORT tempbx ;
++    unsigned short tempbx ;
+ 
+     tempbx = 0 ;
+ 
+@@ -9772,7 +9884,7 @@ void XGI_CloseCRTC( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBIn
+ /* --------------------------------------------------------------------- */
+ void XGI_OpenCRTC( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
+ {
+-    USHORT tempbx ;
++    unsigned short tempbx ;
+ 
+     tempbx = 0 ;
+ 
+@@ -9786,9 +9898,9 @@ void XGI_OpenCRTC( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInf
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGI_GetRAMDAC2DATA(USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
++void XGI_GetRAMDAC2DATA(unsigned short ModeNo , unsigned short ModeIdIndex , unsigned short RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+ {
+-    USHORT tempax ,
++    unsigned short tempax ,
+            tempbx ,
+            temp1 ,
+            temp2 ,
+@@ -9813,15 +9925,15 @@ void XGI_GetRAMDAC2DATA(USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateT
+         modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+         CRT1Index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ;
+         CRT1Index &= IndexMask ;
+-        temp1 = ( USHORT )pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 0 ] ;
+-        temp2 = ( USHORT )pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 5 ] ;
++	temp1 = (unsigned short)pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[0];
++	temp2 = (unsigned short)pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[5];
+ 	tempax = ( temp1 & 0xFF ) | ( ( temp2 & 0x03 ) << 8 ) ;
+-        tempbx = ( USHORT )pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 8 ] ;
+-        tempcx = ( USHORT )pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 14 ] << 8 ;
++	tempbx = (unsigned short)pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[8];
++	tempcx = (unsigned short)pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[14] << 8;
+ 	tempcx &= 0x0100 ;
+ 	tempcx = tempcx << 2 ;
+ 	tempbx |= tempcx;
+-        temp1 = ( USHORT )pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 9 ] ;
++	temp1 = (unsigned short)pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[9];
+     }
+ 
+     if ( temp1 & 0x01 )
+@@ -9851,11 +9963,11 @@ void XGI_GetRAMDAC2DATA(USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateT
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-USHORT XGI_GetColorDepth(USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
++unsigned short XGI_GetColorDepth(unsigned short ModeNo , unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT ColorDepth[ 6 ] = { 1 , 2 , 4 , 4 , 6 , 8 } ;
++    unsigned short ColorDepth[ 6 ] = { 1 , 2 , 4 , 4 , 6 , 8 } ;
+     SHORT  index ;
+-    USHORT modeflag ;
++    unsigned short modeflag ;
+ 
+     if ( ModeNo <= 0x13 )
+     {
+@@ -9926,10 +10038,10 @@ void XGINew_EnableCRT2( PVB_DEVICE_INFO pVBInfo)
+ /* --------------------------------------------------------------------- */
+ void XGINew_LCD_Wait_Time(UCHAR DelayTime, PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT i ,
++    unsigned short i ,
+            j ;
+ 
+-    ULONG temp ,
++    unsigned long temp ,
+           flag ;
+ 
+     flag = 0 ;
+@@ -9961,9 +10073,9 @@ void XGINew_LCD_Wait_Time(UCHAR DelayTime, PVB_DEVICE_INFO pVBInfo)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-BOOLEAN XGI_BridgeIsOn( PVB_DEVICE_INFO pVBInfo )
++unsigned char XGI_BridgeIsOn( PVB_DEVICE_INFO pVBInfo )
+ {
+-    USHORT flag ;
++    unsigned short flag ;
+ 
+     if ( pVBInfo->IF_DEF_LVDS == 1 )
+     {
+@@ -9989,7 +10101,7 @@ BOOLEAN XGI_BridgeIsOn( PVB_DEVICE_INFO pVBInfo )
+ /* --------------------------------------------------------------------- */
+ void XGI_LongWait(PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT i ;
++    unsigned short i ;
+ 
+     i = XGINew_GetReg1( pVBInfo->P3c4 , 0x1F ) ;
+ 
+@@ -10018,7 +10130,7 @@ void XGI_LongWait(PVB_DEVICE_INFO pVBInfo)
+ /* --------------------------------------------------------------------- */
+ void XGI_VBLongWait( PVB_DEVICE_INFO pVBInfo )
+ {
+-    USHORT tempal ,
++    unsigned short tempal ,
+            temp ,
+            i ,
+            j ;
+@@ -10075,16 +10187,16 @@ return ;
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-USHORT XGI_GetVGAHT2( PVB_DEVICE_INFO pVBInfo )
++unsigned short XGI_GetVGAHT2( PVB_DEVICE_INFO pVBInfo )
+ {
+-    ULONG tempax ,
++    unsigned long tempax ,
+           tempbx ;
+ 
+     tempbx = ( ( pVBInfo->VGAVT - pVBInfo->VGAVDE ) * pVBInfo->RVBHCMAX ) & 0xFFFF ;
+     tempax = ( pVBInfo->VT - pVBInfo->VDE ) * pVBInfo->RVBHCFACT ;
+     tempax = ( tempax * pVBInfo->HT ) /tempbx ;
+ 
+-    return( ( USHORT )tempax ) ;
++    return( (unsigned short)tempax ) ;
+ }
+ 
+ 
+@@ -10094,18 +10206,18 @@ USHORT XGI_GetVGAHT2( PVB_DEVICE_INFO pVBInfo )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-USHORT XGI_GetVCLK2Ptr( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension ,PVB_DEVICE_INFO pVBInfo)
++unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo , unsigned short ModeIdIndex , unsigned short RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension ,PVB_DEVICE_INFO pVBInfo)
+ {
+-    USHORT tempbx ;
++    unsigned short tempbx ;
+ 
+-    USHORT LCDXlat1VCLK[ 4 ] = { VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 } ;
+-    USHORT LCDXlat2VCLK[ 4 ] = { VCLK108_2 + 5 , VCLK108_2 + 5 , VCLK108_2 + 5 , VCLK108_2 + 5 } ;
+-    USHORT LVDSXlat1VCLK[ 4 ] = { VCLK40 , VCLK40 , VCLK40 , VCLK40 } ;
+-    USHORT LVDSXlat2VCLK[ 4 ] = { VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 } ;
+-    USHORT LVDSXlat3VCLK[ 4 ] = { VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 } ;
++    unsigned short LCDXlat1VCLK[ 4 ] = { VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 } ;
++    unsigned short LCDXlat2VCLK[ 4 ] = { VCLK108_2 + 5 , VCLK108_2 + 5 , VCLK108_2 + 5 , VCLK108_2 + 5 } ;
++    unsigned short LVDSXlat1VCLK[ 4 ] = { VCLK40 , VCLK40 , VCLK40 , VCLK40 } ;
++    unsigned short LVDSXlat2VCLK[ 4 ] = { VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 } ;
++    unsigned short LVDSXlat3VCLK[ 4 ] = { VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 } ;
+ 
+-    USHORT CRT2Index , VCLKIndex ;
+-    USHORT modeflag , resinfo ;
++    unsigned short CRT2Index , VCLKIndex ;
++    unsigned short modeflag , resinfo ;
+     UCHAR *CHTVVCLKPtr = NULL ;
+ 
+     if ( ModeNo <= 0x13 )
+diff --git a/drivers/staging/xgifb/vb_setmode.h b/drivers/staging/xgifb/vb_setmode.h
+index 09753d706665..67a56b9d4c14 100644
+--- a/drivers/staging/xgifb/vb_setmode.h
++++ b/drivers/staging/xgifb/vb_setmode.h
+@@ -5,7 +5,7 @@ extern   void     InitTo330Pointer(UCHAR,PVB_DEVICE_INFO);
+ extern   void     XGI_UnLockCRT2(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+ extern   void     XGI_LockCRT2(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+ extern   void     XGI_LongWait( PVB_DEVICE_INFO );
+-extern   void     XGI_SetCRT2ModeRegs(USHORT ModeNo,PXGI_HW_DEVICE_INFO,  PVB_DEVICE_INFO  );
++extern   void     XGI_SetCRT2ModeRegs(unsigned short ModeNo,PXGI_HW_DEVICE_INFO,  PVB_DEVICE_INFO  );
+ extern   void     XGI_DisableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+ extern   void  	  XGI_EnableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+ extern   void     XGI_DisplayOff( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO );
+@@ -13,28 +13,28 @@ extern   void     XGI_DisplayOn( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO );
+ extern   void     XGI_GetVBType(PVB_DEVICE_INFO);
+ extern   void     XGI_SenseCRT1(PVB_DEVICE_INFO );
+ extern   void     XGI_GetVGAType(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+-extern   void     XGI_GetVBInfo(USHORT ModeNo,USHORT ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+-extern   void     XGI_GetTVInfo(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO );
+-extern   void     XGI_SetCRT1Offset(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+-extern   void     XGI_SetLCDAGroup(USHORT ModeNo,USHORT ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
++extern   void     XGI_GetVBInfo(unsigned short ModeNo,unsigned short ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
++extern   void     XGI_GetTVInfo(unsigned short ModeNo,unsigned short ModeIdIndex, PVB_DEVICE_INFO );
++extern   void     XGI_SetCRT1Offset(unsigned short ModeNo,unsigned short ModeIdIndex,unsigned short RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
++extern   void     XGI_SetLCDAGroup(unsigned short ModeNo,unsigned short ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+ extern   void     XGI_WaitDisply( PVB_DEVICE_INFO );
+-extern   USHORT   XGI_GetResInfo(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
++extern   unsigned short   XGI_GetResInfo(unsigned short ModeNo,unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+ 
+-extern   BOOLEAN  XGISetModeNew( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo ) ;
++extern   unsigned char  XGISetModeNew( PXGI_HW_DEVICE_INFO HwDeviceExtension , unsigned short ModeNo ) ;
+ 
+-extern   BOOLEAN  XGI_SearchModeID( USHORT ModeNo,USHORT  *ModeIdIndex, PVB_DEVICE_INFO );
+-extern   BOOLEAN  XGI_GetLCDInfo(USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO );
+-extern   BOOLEAN  XGI_BridgeIsOn( PVB_DEVICE_INFO );
+-extern   BOOLEAN  XGI_SetCRT2Group301(USHORT ModeNo, PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO);
+-extern   USHORT   XGI_GetRatePtrCRT2( PXGI_HW_DEVICE_INFO pXGIHWDE, USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO );
++extern   unsigned char  XGI_SearchModeID( unsigned short ModeNo,unsigned short  *ModeIdIndex, PVB_DEVICE_INFO );
++extern   unsigned char  XGI_GetLCDInfo(unsigned short ModeNo,unsigned short ModeIdIndex,PVB_DEVICE_INFO );
++extern   unsigned char  XGI_BridgeIsOn( PVB_DEVICE_INFO );
++extern   unsigned char  XGI_SetCRT2Group301(unsigned short ModeNo, PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO);
++extern   unsigned short   XGI_GetRatePtrCRT2( PXGI_HW_DEVICE_INFO pXGIHWDE, unsigned short ModeNo,unsigned short ModeIdIndex, PVB_DEVICE_INFO );
+ 
+ extern   void     XGI_SetXG21FPBits(PVB_DEVICE_INFO pVBInfo);
+ extern   void     XGI_SetXG27FPBits(PVB_DEVICE_INFO pVBInfo);
+-extern   void     XGI_XG21BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
+-extern   void     XGI_XG27BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
+-extern   void     XGI_XG21SetPanelDelay(USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
+-extern   BOOLEAN  XGI_XG21CheckLVDSMode(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
+-extern   void     XGI_SetXG21LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
+-extern   USHORT XGI_GetLVDSOEMTableIndex(PVB_DEVICE_INFO pVBInfo);
++extern   void     XGI_XG21BLSignalVDD(unsigned short tempbh,unsigned short tempbl, PVB_DEVICE_INFO pVBInfo);
++extern   void     XGI_XG27BLSignalVDD(unsigned short tempbh,unsigned short tempbl, PVB_DEVICE_INFO pVBInfo);
++extern   void     XGI_XG21SetPanelDelay(unsigned short tempbl, PVB_DEVICE_INFO pVBInfo);
++extern   unsigned char  XGI_XG21CheckLVDSMode(unsigned short ModeNo,unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
++extern   void     XGI_SetXG21LVDSPara(unsigned short ModeNo,unsigned short ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
++extern   unsigned short XGI_GetLVDSOEMTableIndex(PVB_DEVICE_INFO pVBInfo);
+ 
+ #endif
+diff --git a/drivers/staging/xgifb/vb_struct.h b/drivers/staging/xgifb/vb_struct.h
+index 1ee619f65978..c0498d87327b 100644
+--- a/drivers/staging/xgifb/vb_struct.h
++++ b/drivers/staging/xgifb/vb_struct.h
+@@ -17,12 +17,12 @@ typedef struct _XGI_PanelDelayTblStruct
+ 
+ typedef struct _XGI_LCDDataStruct
+ {
+- USHORT RVBHCMAX;
+- USHORT RVBHCFACT;
+- USHORT VGAHT;
+- USHORT VGAVT;
+- USHORT LCDHT;
+- USHORT LCDVT;
++ unsigned short RVBHCMAX;
++ unsigned short RVBHCFACT;
++ unsigned short VGAHT;
++ unsigned short VGAVT;
++ unsigned short LCDHT;
++ unsigned short LCDVT;
+ } XGI_LCDDataStruct;
+ 
+ 
+@@ -38,15 +38,15 @@ typedef struct _XGI_LVDSCRT1VDataStruct
+ 
+ typedef struct _XGI_TVDataStruct
+ {
+- USHORT RVBHCMAX;
+- USHORT RVBHCFACT;
+- USHORT VGAHT;
+- USHORT VGAVT;
+- USHORT TVHDE;
+- USHORT TVVDE;
+- USHORT RVBHRS;
++ unsigned short RVBHCMAX;
++ unsigned short RVBHCFACT;
++ unsigned short VGAHT;
++ unsigned short VGAVT;
++ unsigned short TVHDE;
++ unsigned short TVVDE;
++ unsigned short RVBHRS;
+  UCHAR FlickerMode;
+- USHORT HALFRVBHRS;
++ unsigned short HALFRVBHRS;
+  UCHAR RY1COE;
+  UCHAR RY2COE;
+  UCHAR RY3COE;
+@@ -55,16 +55,16 @@ typedef struct _XGI_TVDataStruct
+ 
+ typedef struct _XGI_LVDSDataStruct
+ {
+- USHORT VGAHT;
+- USHORT VGAVT;
+- USHORT LCDHT;
+- USHORT LCDVT;
++ unsigned short VGAHT;
++ unsigned short VGAVT;
++ unsigned short LCDHT;
++ unsigned short LCDVT;
+ } XGI_LVDSDataStruct;
+ 
+ typedef struct _XGI_LVDSDesStruct
+ {
+- USHORT LCDHDES;
+- USHORT LCDVDES;
++ unsigned short LCDHDES;
++ unsigned short LCDVDES;
+ } XGI_LVDSDesStruct;
+ 
+ typedef struct _XGI_LVDSCRT1DataStruct
+@@ -78,7 +78,7 @@ typedef struct _XGI_LVDSCRT1DataStruct
+ typedef struct _XGI_StStruct
+ {
+  UCHAR St_ModeID;
+- USHORT St_ModeFlag;
++ unsigned short St_ModeFlag;
+  UCHAR St_StTableIndex;
+  UCHAR St_CRT2CRTC;
+  UCHAR St_CRT2CRTC2;
+@@ -93,7 +93,7 @@ typedef struct _XGI_StandTableStruct
+  UCHAR CRT_COLS;
+  UCHAR ROWS;
+  UCHAR CHAR_HEIGHT;
+- USHORT CRT_LEN;
++ unsigned short CRT_LEN;
+  UCHAR SR[4];
+  UCHAR MISC;
+  UCHAR CRTC[0x19];
+@@ -104,10 +104,10 @@ typedef struct _XGI_StandTableStruct
+ typedef struct _XGI_ExtStruct
+ {
+  UCHAR Ext_ModeID;
+- USHORT Ext_ModeFlag;
+- USHORT Ext_ModeInfo;
+- USHORT Ext_Point;
+- USHORT Ext_VESAID;
++ unsigned short Ext_ModeFlag;
++ unsigned short Ext_ModeInfo;
++ unsigned short Ext_Point;
++ unsigned short Ext_VESAID;
+  UCHAR Ext_VESAMEMSize;
+  UCHAR Ext_RESINFO;
+  UCHAR VB_ExtTVFlickerIndex;
+@@ -118,52 +118,52 @@ typedef struct _XGI_ExtStruct
+ 
+ typedef struct _XGI_Ext2Struct
+ {
+- USHORT Ext_InfoFlag;
++ unsigned short Ext_InfoFlag;
+  UCHAR Ext_CRT1CRTC;
+  UCHAR Ext_CRTVCLK;
+  UCHAR Ext_CRT2CRTC;
+  UCHAR Ext_CRT2CRTC2;
+  UCHAR  ModeID;
+- USHORT XRes;
+- USHORT YRes;
+- /* USHORT ROM_OFFSET; */
++ unsigned short XRes;
++ unsigned short YRes;
++ /* unsigned short ROM_OFFSET; */
+ } XGI_Ext2Struct;
+ 
+ 
+ typedef struct _XGI_MCLKDataStruct
+ {
+  UCHAR SR28,SR29,SR2A;
+- USHORT CLOCK;
++ unsigned short CLOCK;
+ } XGI_MCLKDataStruct;
+ 
+ typedef struct _XGI_ECLKDataStruct
+ {
+  UCHAR SR2E,SR2F,SR30;
+- USHORT CLOCK;
++ unsigned short CLOCK;
+ } XGI_ECLKDataStruct;
+ 
+ typedef struct _XGI_VCLKDataStruct
+ {
+  UCHAR SR2B,SR2C;
+- USHORT CLOCK;
++ unsigned short CLOCK;
+ } XGI_VCLKDataStruct;
+ 
+ typedef struct _XGI_VBVCLKDataStruct
+ {
+  UCHAR Part4_A,Part4_B;
+- USHORT CLOCK;
++ unsigned short CLOCK;
+ } XGI_VBVCLKDataStruct;
+ 
+ typedef struct _XGI_StResInfoStruct
+ {
+- USHORT HTotal;
+- USHORT VTotal;
++ unsigned short HTotal;
++ unsigned short VTotal;
+ } XGI_StResInfoStruct;
+ 
+ typedef struct _XGI_ModeResInfoStruct
+ {
+- USHORT HTotal;
+- USHORT VTotal;
++ unsigned short HTotal;
++ unsigned short VTotal;
+  UCHAR  XChar;
+  UCHAR  YChar;
+ } XGI_ModeResInfoStruct;
+@@ -175,100 +175,100 @@ typedef struct _XGI_LCDNBDesStruct
+  /*add for new UNIVGABIOS*/
+ typedef struct _XGI_LCDDesStruct
+ {
+- USHORT LCDHDES;
+- USHORT LCDHRS;
+- USHORT LCDVDES;
+- USHORT LCDVRS;
++ unsigned short LCDHDES;
++ unsigned short LCDHRS;
++ unsigned short LCDVDES;
++ unsigned short LCDVRS;
+ } XGI_LCDDesStruct;
+ 
+ typedef struct _XGI_LCDDataTablStruct
+ {
+  UCHAR  PANELID;
+- USHORT MASK;
+- USHORT CAP;
+- USHORT DATAPTR;
++ unsigned short MASK;
++ unsigned short CAP;
++ unsigned short DATAPTR;
+ } XGI_LCDDataTablStruct;
+ 
+ typedef struct _XGI_TVTablDataStruct
+ {
+- USHORT MASK;
+- USHORT CAP;
+- USHORT DATAPTR;
++ unsigned short MASK;
++ unsigned short CAP;
++ unsigned short DATAPTR;
+ } XGI_TVDataTablStruct;
+ 
+ typedef struct _XGI330_LCDDesDataStruct
+ {
+- USHORT LCDHDES;
+- USHORT LCDHRS;
+- USHORT LCDVDES;
+- USHORT LCDVRS;
++ unsigned short LCDHDES;
++ unsigned short LCDHRS;
++ unsigned short LCDVDES;
++ unsigned short LCDVRS;
+ } XGI330_LCDDataDesStruct;
+ 
+ 
+ typedef struct _XGI330_LVDSDataStruct
+ {
+- USHORT VGAHT;
+- USHORT VGAVT;
+- USHORT LCDHT;
+- USHORT LCDVT;
++ unsigned short VGAHT;
++ unsigned short VGAVT;
++ unsigned short LCDHT;
++ unsigned short LCDVT;
+ } XGI330_LVDSDataStruct;
+ 
+ typedef struct _XGI330_LCDDesDataStruct2
+ {
+- USHORT LCDHDES;
+- USHORT LCDHRS;
+- USHORT LCDVDES;
+- USHORT LCDVRS;
+- USHORT LCDHSync;
+- USHORT LCDVSync;
++ unsigned short LCDHDES;
++ unsigned short LCDHRS;
++ unsigned short LCDVDES;
++ unsigned short LCDVRS;
++ unsigned short LCDHSync;
++ unsigned short LCDVSync;
+ } XGI330_LCDDataDesStruct2;
+ 
+ typedef struct _XGI330_LCDDataStruct
+ {
+- USHORT RVBHCMAX;
+- USHORT RVBHCFACT;
+- USHORT VGAHT;
+- USHORT VGAVT;
+- USHORT LCDHT;
+- USHORT LCDVT;
++ unsigned short RVBHCMAX;
++ unsigned short RVBHCFACT;
++ unsigned short VGAHT;
++ unsigned short VGAVT;
++ unsigned short LCDHT;
++ unsigned short LCDVT;
+ } XGI330_LCDDataStruct;
+ 
+ 
+ typedef struct _XGI330_TVDataStruct
+ {
+- USHORT RVBHCMAX;
+- USHORT RVBHCFACT;
+- USHORT VGAHT;
+- USHORT VGAVT;
+- USHORT TVHDE;
+- USHORT TVVDE;
+- USHORT RVBHRS;
++ unsigned short RVBHCMAX;
++ unsigned short RVBHCFACT;
++ unsigned short VGAHT;
++ unsigned short VGAVT;
++ unsigned short TVHDE;
++ unsigned short TVVDE;
++ unsigned short RVBHRS;
+  UCHAR FlickerMode;
+- USHORT HALFRVBHRS;
++ unsigned short HALFRVBHRS;
+ } XGI330_TVDataStruct;
+ 
+ typedef struct _XGI330_LCDDataTablStruct
+ {
+  UCHAR  PANELID;
+- USHORT MASK;
+- USHORT CAP;
+- USHORT DATAPTR;
++ unsigned short MASK;
++ unsigned short CAP;
++ unsigned short DATAPTR;
+ } XGI330_LCDDataTablStruct;
+ 
+ typedef struct _XGI330_TVDataTablStruct
+ {
+- USHORT MASK;
+- USHORT CAP;
+- USHORT DATAPTR;
++ unsigned short MASK;
++ unsigned short CAP;
++ unsigned short DATAPTR;
+ } XGI330_TVDataTablStruct;
+ 
+ 
+ typedef struct _XGI330_CHTVDataStruct
+ {
+- USHORT VGAHT;
+- USHORT VGAVT;
+- USHORT LCDHT;
+- USHORT LCDVT;
++ unsigned short VGAHT;
++ unsigned short VGAVT;
++ unsigned short LCDHT;
++ unsigned short LCDVT;
+ } XGI330_CHTVDataStruct;
+ 
+ typedef struct _XGI_TimingHStruct
+@@ -304,7 +304,7 @@ typedef struct _XGI330_CHTVRegDataStruct
+ typedef struct _XGI330_LCDCapStruct
+ {
+  		UCHAR      LCD_ID;
+-                USHORT     LCD_Capability;
++		unsigned short	   LCD_Capability;
+                 UCHAR      LCD_SetFlag;
+                 UCHAR      LCD_DelayCompensation;
+                 UCHAR      LCD_HSyncWidth;
+@@ -332,15 +332,15 @@ typedef struct _XGI330_LCDCapStruct
+ 
+ typedef struct _XGI21_LVDSCapStruct
+ {
+-                USHORT     LVDS_Capability;
+-                USHORT     LVDSHT;
+-                USHORT     LVDSVT;
+-                USHORT     LVDSHDE;
+-                USHORT     LVDSVDE;
+-                USHORT     LVDSHFP;
+-                USHORT     LVDSVFP;
+-                USHORT     LVDSHSYNC;
+-                USHORT     LVDSVSYNC;
++		unsigned short	   LVDS_Capability;
++		unsigned short	   LVDSHT;
++		unsigned short	   LVDSVT;
++		unsigned short	   LVDSHDE;
++		unsigned short	   LVDSVDE;
++		unsigned short	   LVDSHFP;
++		unsigned short	   LVDSVFP;
++		unsigned short	   LVDSHSYNC;
++		unsigned short	   LVDSVSYNC;
+                 UCHAR      VCLKData1;
+                 UCHAR      VCLKData2;
+                 UCHAR      PSC_S1;
+@@ -359,12 +359,12 @@ typedef struct _XGI_CRT1TableStruct
+ typedef struct _XGI330_VCLKDataStruct
+ {
+     UCHAR SR2B,SR2C;
+-    USHORT CLOCK;
++    unsigned short CLOCK;
+ } XGI330_VCLKDataStruct;
+ 
+ typedef struct _XGI301C_Tap4TimingStruct
+ {
+-    USHORT DE;
++    unsigned short DE;
+     UCHAR  Reg[64];   /* C0-FF */
+ } XGI301C_Tap4TimingStruct;
+ 
+@@ -373,7 +373,7 @@ typedef struct _XGI_New_StandTableStruct
+ 	UCHAR  CRT_COLS;
+ 	UCHAR  ROWS;
+ 	UCHAR  CHAR_HEIGHT;
+-	USHORT CRT_LEN;
++	unsigned short CRT_LEN;
+ 	UCHAR  SR[4];
+ 	UCHAR  MISC;
+ 	UCHAR  CRTC[0x19];
+@@ -391,34 +391,34 @@ typedef VB_DEVICE_INFO *	PVB_DEVICE_INFO;
+ 
+ struct _VB_DEVICE_INFO
+ {
+-    BOOLEAN  ISXPDOS;
+-    ULONG   P3c4,P3d4,P3c0,P3ce,P3c2,P3cc;
+-    ULONG   P3ca,P3c6,P3c7,P3c8,P3c9,P3da;
+-    ULONG   Part0Port,Part1Port,Part2Port;
+-    ULONG   Part3Port,Part4Port,Part5Port;
+-    USHORT   RVBHCFACT,RVBHCMAX,RVBHRS;
+-    USHORT   VGAVT,VGAHT,VGAVDE,VGAHDE;
+-    USHORT   VT,HT,VDE,HDE;
+-    USHORT   LCDHRS,LCDVRS,LCDHDES,LCDVDES;
+-
+-    USHORT   ModeType;
+-    USHORT   IF_DEF_LVDS,IF_DEF_TRUMPION,IF_DEF_DSTN;/* ,IF_DEF_FSTN; add for dstn */
+-    USHORT   IF_DEF_CRT2Monitor,IF_DEF_VideoCapture;
+-    USHORT   IF_DEF_LCDA,IF_DEF_CH7017,IF_DEF_YPbPr,IF_DEF_ScaleLCD,IF_DEF_OEMUtil,IF_DEF_PWD;
+-    USHORT   IF_DEF_ExpLink;
+-    USHORT   IF_DEF_CH7005,IF_DEF_HiVision;
+-    USHORT   IF_DEF_CH7007; /* Billy 2007/05/03 */
+-    USHORT   LCDResInfo,LCDTypeInfo, VBType;/*301b*/
+-    USHORT   VBInfo,TVInfo,LCDInfo, Set_VGAType;
+-    USHORT   VBExtInfo;/*301lv*/
+-    USHORT   SetFlag;
+-    USHORT   NewFlickerMode;
+-    USHORT   SelectCRT2Rate;
++    unsigned char  ISXPDOS;
++    unsigned long   P3c4,P3d4,P3c0,P3ce,P3c2,P3cc;
++    unsigned long   P3ca,P3c6,P3c7,P3c8,P3c9,P3da;
++    unsigned long   Part0Port,Part1Port,Part2Port;
++    unsigned long   Part3Port,Part4Port,Part5Port;
++    unsigned short   RVBHCFACT,RVBHCMAX,RVBHRS;
++    unsigned short   VGAVT,VGAHT,VGAVDE,VGAHDE;
++    unsigned short   VT,HT,VDE,HDE;
++    unsigned short   LCDHRS,LCDVRS,LCDHDES,LCDVDES;
++
++    unsigned short   ModeType;
++    unsigned short   IF_DEF_LVDS,IF_DEF_TRUMPION,IF_DEF_DSTN;/* ,IF_DEF_FSTN; add for dstn */
++    unsigned short   IF_DEF_CRT2Monitor,IF_DEF_VideoCapture;
++    unsigned short   IF_DEF_LCDA,IF_DEF_CH7017,IF_DEF_YPbPr,IF_DEF_ScaleLCD,IF_DEF_OEMUtil,IF_DEF_PWD;
++    unsigned short   IF_DEF_ExpLink;
++    unsigned short   IF_DEF_CH7005,IF_DEF_HiVision;
++    unsigned short   IF_DEF_CH7007; /* Billy 2007/05/03 */
++    unsigned short   LCDResInfo,LCDTypeInfo, VBType;/*301b*/
++    unsigned short   VBInfo,TVInfo,LCDInfo, Set_VGAType;
++    unsigned short   VBExtInfo;/*301lv*/
++    unsigned short   SetFlag;
++    unsigned short   NewFlickerMode;
++    unsigned short   SelectCRT2Rate;
+ 
+     unsigned char *ROMAddr;
+     unsigned char *FBAddr;
+-    ULONG BaseAddr;
+-    ULONG RelIO;
++    unsigned long BaseAddr;
++    unsigned long RelIO;
+ 
+     DRAM4Type  *CR6B;
+     DRAM4Type  *CR6E;
+@@ -430,12 +430,12 @@ struct _VB_DEVICE_INFO
+     UCHAR  *pSoftSetting;
+     UCHAR  *pOutputSelect;
+ 
+-    USHORT *pRGBSenseData;
+-    USHORT *pRGBSenseData2; /*301b*/
+-    USHORT *pVideoSenseData;
+-    USHORT *pVideoSenseData2;
+-    USHORT *pYCSenseData;
+-    USHORT *pYCSenseData2;
++    unsigned short *pRGBSenseData;
++    unsigned short *pRGBSenseData2; /*301b*/
++    unsigned short *pVideoSenseData;
++    unsigned short *pVideoSenseData2;
++    unsigned short *pYCSenseData;
++    unsigned short *pYCSenseData2;
+ 
+     UCHAR  *pSR07;
+     UCHAR  *CR49;
+@@ -516,18 +516,18 @@ struct _VB_DEVICE_INFO
+ 
+ typedef struct
+ {
+-    USHORT    Horizontal_ACTIVE;
+-    USHORT    Horizontal_FP;
+-    USHORT    Horizontal_SYNC;
+-    USHORT    Horizontal_BP;
+-    USHORT    Vertical_ACTIVE;
+-    USHORT    Vertical_FP;
+-    USHORT    Vertical_SYNC;
+-    USHORT    Vertical_BP;
++    unsigned short    Horizontal_ACTIVE;
++    unsigned short    Horizontal_FP;
++    unsigned short    Horizontal_SYNC;
++    unsigned short    Horizontal_BP;
++    unsigned short    Vertical_ACTIVE;
++    unsigned short    Vertical_FP;
++    unsigned short    Vertical_SYNC;
++    unsigned short    Vertical_BP;
+     double    DCLK;
+     UCHAR     FrameRate;
+     UCHAR     Interlace;
+-    USHORT    Margin;
++    unsigned short    Margin;
+ } TimingInfo;
+ 
+ #define _VB_STRUCT_
+diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h
+index f804dfac6902..5e06afe368b0 100644
+--- a/drivers/staging/xgifb/vb_table.h
++++ b/drivers/staging/xgifb/vb_table.h
+@@ -2938,7 +2938,7 @@ XGI330_TVDataTablStruct XGI_TVDataTable[]=
+  {0xffff,0x0000,12}  	/* END */
+ };
+ 
+-USHORT TVLenList[]=
++unsigned short TVLenList[] =
+ {
+    LVDSCRT1Len_H,
+    LVDSCRT1Len_V,
+@@ -2980,7 +2980,7 @@ XGI330_TVDataTablStruct XGI_EPLCHTVRegPtr[]=
+   {0xFFFF,0x0000,4}
+ };
+ 
+-USHORT LCDLenList[]=
++unsigned short LCDLenList[] =
+ {
+    LVDSCRT1Len_H,
+    LVDSCRT1Len_V,
+@@ -3471,12 +3471,12 @@ UCHAR XGI330_CRT2Data_1_2 = 0x0;
+ UCHAR XGI330_CRT2Data_4_D = 0x0;
+ UCHAR XGI330_CRT2Data_4_E = 0x0;
+ UCHAR XGI330_CRT2Data_4_10 = 0x80;
+-USHORT XGI330_RGBSenseData = 0xd1;
+-USHORT XGI330_VideoSenseData = 0xb9;
+-USHORT XGI330_YCSenseData = 0xb3;
+-USHORT XGI330_RGBSenseData2 = 0x0190;     /*301b*/
+-USHORT XGI330_VideoSenseData2 = 0x0110;
+-USHORT XGI330_YCSenseData2 = 0x016B;
++unsigned short XGI330_RGBSenseData = 0xd1;
++unsigned short XGI330_VideoSenseData = 0xb9;
++unsigned short XGI330_YCSenseData = 0xb3;
++unsigned short XGI330_RGBSenseData2 = 0x0190;     /*301b*/
++unsigned short XGI330_VideoSenseData2 = 0x0110;
++unsigned short XGI330_YCSenseData2 = 0x016B;
+ UCHAR XGI330_NTSCPhase[] = {0x21,0xed,0x8a,0x8};
+ UCHAR XGI330_PALPhase[] = {0x2a,0x5,0xd3,0x0};
+ UCHAR XGI330_NTSCPhase2[] = {0x21,0xF0,0x7B,0xD6};/*301b*/
+@@ -4045,7 +4045,7 @@ UCHAR TVEdgeList[]=
+       0x00             /* ; 1 HiTV */
+ };
+ 
+-ULONG TVPhaseList[]=
++unsigned long TVPhaseList[]=
+ {      0x08BAED21, /* ; 0 NTSC phase */
+        0x00E3052A, /* ; 1 PAL phase */
+        0x9B2EE421, /* ; 2 PAL-M phase */
+diff --git a/drivers/staging/xgifb/vb_util.c b/drivers/staging/xgifb/vb_util.c
+index 0842cb68b834..5e32afda28c2 100644
+--- a/drivers/staging/xgifb/vb_util.c
++++ b/drivers/staging/xgifb/vb_util.c
+@@ -6,17 +6,20 @@
+ #include 
+ #include 
+ 
+-void XGINew_SetReg1( ULONG , USHORT , USHORT ) ;
+-void XGINew_SetReg2( ULONG , USHORT , USHORT ) ;
+-void XGINew_SetReg3( ULONG , USHORT ) ;
+-void XGINew_SetReg4( ULONG , ULONG ) ;
+-UCHAR XGINew_GetReg1( ULONG , USHORT) ;
+-UCHAR XGINew_GetReg2( ULONG ) ;
+-ULONG XGINew_GetReg3( ULONG ) ;
+-void XGINew_ClearDAC(unsigned char *) ;
+-void     XGINew_SetRegANDOR(ULONG Port,USHORT Index,USHORT DataAND,USHORT DataOR);
+-void     XGINew_SetRegOR(ULONG Port,USHORT Index,USHORT DataOR);
+-void     XGINew_SetRegAND(ULONG Port,USHORT Index,USHORT DataAND);
++void XGINew_SetReg1(unsigned long,unsigned short,unsigned short);
++void XGINew_SetReg2(unsigned long,unsigned short,unsigned short);
++void XGINew_SetReg3(unsigned long,unsigned short);
++void XGINew_SetReg4(unsigned long,unsigned long);
++UCHAR XGINew_GetReg1(unsigned long,unsigned short);
++UCHAR XGINew_GetReg2(unsigned long);
++unsigned long XGINew_GetReg3(unsigned long);
++void XGINew_ClearDAC(unsigned char *);
++void XGINew_SetRegANDOR(unsigned long Port,unsigned short Index,
++			unsigned short DataAND,unsigned short DataOR);
++void XGINew_SetRegOR(unsigned long Port,unsigned short Index,
++		     unsigned short DataOR);
++void XGINew_SetRegAND(unsigned long Port,unsigned short Index,
++		      unsigned short DataAND);
+ 
+ 
+ /* --------------------------------------------------------------------- */
+@@ -25,7 +28,7 @@ void     XGINew_SetRegAND(ULONG Port,USHORT Index,USHORT DataAND);
+ /* Output : */
+ /* Description : SR CRTC GR */
+ /* --------------------------------------------------------------------- */
+-void XGINew_SetReg1( ULONG port , USHORT index , USHORT data )
++void XGINew_SetReg1( unsigned long port , unsigned short index , unsigned short data )
+ {
+ 	outb(index, port);
+ 	outb(data, port + 1);
+@@ -38,7 +41,7 @@ void XGINew_SetReg1( ULONG port , USHORT index , USHORT data )
+ /* Output : */
+ /* Description : AR( 3C0 ) */
+ /* --------------------------------------------------------------------- */
+-/*void XGINew_SetReg2( ULONG port , USHORT index , USHORT data )
++/*void XGINew_SetReg2( unsigned long port , unsigned short index , unsigned short data )
+ {
+     InPortByte( ( PUCHAR )port + 0x3da - 0x3c0 ) ;
+     OutPortByte( XGINew_P3c0 , index ) ;
+@@ -53,7 +56,7 @@ void XGINew_SetReg1( ULONG port , USHORT index , USHORT data )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_SetReg3( ULONG port , USHORT data )
++void XGINew_SetReg3( unsigned long port , unsigned short data )
+ {
+ 	outb(data, port);
+ }
+@@ -65,7 +68,7 @@ void XGINew_SetReg3( ULONG port , USHORT data )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_SetReg4( ULONG port , ULONG data )
++void XGINew_SetReg4( unsigned long port , unsigned long data )
+ {
+ 	outl(data, port);
+ }
+@@ -77,7 +80,7 @@ void XGINew_SetReg4( ULONG port , ULONG data )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-UCHAR XGINew_GetReg1( ULONG port , USHORT index )
++UCHAR XGINew_GetReg1( unsigned long port , unsigned short index )
+ {
+     UCHAR data ;
+ 
+@@ -93,7 +96,7 @@ UCHAR XGINew_GetReg1( ULONG port , USHORT index )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-UCHAR XGINew_GetReg2( ULONG port )
++UCHAR XGINew_GetReg2( unsigned long port )
+ {
+     UCHAR data ;
+ 
+@@ -109,9 +112,9 @@ UCHAR XGINew_GetReg2( ULONG port )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-ULONG XGINew_GetReg3( ULONG port )
++unsigned long XGINew_GetReg3( unsigned long port )
+ {
+-    ULONG data ;
++    unsigned long data ;
+ 
+     data = inl(port) ;
+ 
+@@ -126,9 +129,9 @@ ULONG XGINew_GetReg3( ULONG port )
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_SetRegANDOR( ULONG Port , USHORT Index , USHORT DataAND , USHORT DataOR )
++void XGINew_SetRegANDOR( unsigned long Port , unsigned short Index , unsigned short DataAND , unsigned short DataOR )
+ {
+-    USHORT temp ;
++    unsigned short temp ;
+ 
+     temp = XGINew_GetReg1( Port , Index ) ;		/* XGINew_Part1Port index 02 */
+     temp = ( temp & ( DataAND ) ) | DataOR ;
+@@ -142,9 +145,9 @@ void XGINew_SetRegANDOR( ULONG Port , USHORT Index , USHORT DataAND , USHORT Dat
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_SetRegAND(ULONG Port,USHORT Index,USHORT DataAND)
++void XGINew_SetRegAND(unsigned long Port,unsigned short Index,unsigned short DataAND)
+ {
+-    USHORT temp ;
++    unsigned short temp ;
+ 
+     temp = XGINew_GetReg1( Port , Index ) ;	/* XGINew_Part1Port index 02 */
+     temp &= DataAND ;
+@@ -158,9 +161,9 @@ void XGINew_SetRegAND(ULONG Port,USHORT Index,USHORT DataAND)
+ /* Output : */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+-void XGINew_SetRegOR( ULONG Port , USHORT Index , USHORT DataOR )
++void XGINew_SetRegOR( unsigned long Port , unsigned short Index , unsigned short DataOR )
+ {
+-    USHORT temp ;
++    unsigned short temp ;
+ 
+     temp = XGINew_GetReg1( Port , Index ) ;	/* XGINew_Part1Port index 02 */
+     temp |= DataOR ;
+diff --git a/drivers/staging/xgifb/vb_util.h b/drivers/staging/xgifb/vb_util.h
+index 91779d8cfdc6..aaaf361477ab 100644
+--- a/drivers/staging/xgifb/vb_util.h
++++ b/drivers/staging/xgifb/vb_util.h
+@@ -2,14 +2,14 @@
+ #define _VBUTIL_
+ extern   void     NewDelaySeconds( int );
+ extern   void     Newdebugcode( UCHAR );
+-extern   void     XGINew_SetReg1(ULONG, USHORT, USHORT);
+-extern   void     XGINew_SetReg3(ULONG, USHORT);
+-extern   UCHAR    XGINew_GetReg1(ULONG, USHORT);
+-extern   UCHAR    XGINew_GetReg2(ULONG);
+-extern   void     XGINew_SetReg4(ULONG, ULONG);
+-extern   ULONG    XGINew_GetReg3(ULONG);
+-extern   void     XGINew_SetRegOR(ULONG Port,USHORT Index,USHORT DataOR);
+-extern   void     XGINew_SetRegAND(ULONG Port,USHORT Index,USHORT DataAND);
+-extern   void     XGINew_SetRegANDOR(ULONG Port,USHORT Index,USHORT DataAND,USHORT DataOR);
++extern   void     XGINew_SetReg1(unsigned long, unsigned short, unsigned short);
++extern   void     XGINew_SetReg3(unsigned long, unsigned short);
++extern   UCHAR    XGINew_GetReg1(unsigned long, unsigned short);
++extern   UCHAR    XGINew_GetReg2(unsigned long);
++extern   void     XGINew_SetReg4(unsigned long, unsigned long);
++extern   unsigned long    XGINew_GetReg3(unsigned long);
++extern   void     XGINew_SetRegOR(unsigned long Port,unsigned short Index,unsigned short DataOR);
++extern   void     XGINew_SetRegAND(unsigned long Port,unsigned short Index,unsigned short DataAND);
++extern   void     XGINew_SetRegANDOR(unsigned long Port,unsigned short Index,unsigned short DataAND,unsigned short DataOR);
+ #endif
+ 
+diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h
+index 0d5472ec9297..a85f21a7aebc 100644
+--- a/drivers/staging/xgifb/vgatypes.h
++++ b/drivers/staging/xgifb/vgatypes.h
+@@ -20,26 +20,6 @@ typedef long  LONG;
+ typedef unsigned char UCHAR;
+ #endif
+ 
+-#ifndef USHORT
+-typedef unsigned short USHORT;
+-#endif
+-
+-#ifndef ULONG
+-typedef unsigned long ULONG;
+-#endif
+-
+-#ifndef VOID
+-typedef void VOID;
+-#endif
+-
+-#ifndef BOOLEAN
+-typedef UCHAR BOOLEAN;
+-#endif
+-/*
+-#ifndef bool
+-typedef UCHAR bool;
+-#endif
+-*/
+ typedef unsigned long XGIIOADDRESS;
+ 
+ 
+@@ -103,30 +83,30 @@ typedef struct _XGI_DSReg
+ 
+ typedef struct _XGI_HW_DEVICE_INFO  XGI_HW_DEVICE_INFO, *PXGI_HW_DEVICE_INFO;
+ 
+-typedef BOOLEAN (*PXGI_QUERYSPACE)   (PXGI_HW_DEVICE_INFO, ULONG, ULONG, ULONG *);
++typedef unsigned char (*PXGI_QUERYSPACE)   (PXGI_HW_DEVICE_INFO, unsigned long, unsigned long, unsigned long *);
+ 
+ struct _XGI_HW_DEVICE_INFO
+ {
+-    ULONG  ulExternalChip;       /* NO VB or other video bridge*/
++    unsigned long  ulExternalChip;       /* NO VB or other video bridge*/
+                                  /* if ujVBChipID = VB_CHIP_UNKNOWN, */
+ 
+     unsigned char *pjVirtualRomBase;    /* ROM image */
+ 
+-    BOOLEAN UseROM;		 /* Use the ROM image if provided */
++    unsigned char UseROM;		 /* Use the ROM image if provided */
+ 
+     void *pDevice;
+ 
+     unsigned char *pjVideoMemoryAddress;/* base virtual memory address */
+                                  /* of Linear VGA memory */
+ 
+-    ULONG  ulVideoMemorySize;    /* size, in bytes, of the memory on the board */
++    unsigned long  ulVideoMemorySize;    /* size, in bytes, of the memory on the board */
+ 
+     unsigned char *pjIOAddress;          /* base I/O address of VGA ports (0x3B0) */
+ 
+     unsigned char *pjCustomizedROMImage;
+ 
+     unsigned char *pj2ndVideoMemoryAddress;
+-    ULONG  ul2ndVideoMemorySize;
++    unsigned long  ul2ndVideoMemorySize;
+ 
+     unsigned char *pj2ndIOAddress;
+     UCHAR  jChipType;            /* Used to Identify Graphics Chip */
+@@ -139,20 +119,20 @@ struct _XGI_HW_DEVICE_INFO
+                                  /* defined in the data structure type */
+                                  /* "XGI_VB_CHIP_TYPE" */
+ 
+-    BOOLEAN    bNewScratch;
++    unsigned char    bNewScratch;
+ 
+-    ULONG  ulCRT2LCDType;        /* defined in the data structure type */
++    unsigned long  ulCRT2LCDType;        /* defined in the data structure type */
+ 
+-    ULONG usExternalChip;       /* NO VB or other video bridge (other than  */
++    unsigned long usExternalChip;       /* NO VB or other video bridge (other than  */
+                                  /*  video bridge) */
+ 
+-    BOOLEAN bIntegratedMMEnabled;/* supporting integration MM enable */
++    unsigned char bIntegratedMMEnabled;/* supporting integration MM enable */
+ 
+-    BOOLEAN bSkipDramSizing;     /* True: Skip video memory sizing. */
++    unsigned char bSkipDramSizing;     /* True: Skip video memory sizing. */
+ 
+-    BOOLEAN bSkipSense;
++    unsigned char bSkipSense;
+ 
+-    BOOLEAN bIsPowerSaving;     /* True: XGIInit() is invoked by power management,
++    unsigned char bIsPowerSaving;     /* True: XGIInit() is invoked by power management,
+                                    otherwise by 2nd adapter's initialzation */
+ 
+     PXGI_DSReg  pSR;             /* restore SR registers in initial function. */

commit 490ce818c6ff60257b543207aa042991e32017af
+Author: Bill Pemberton 
+Date:   Thu Jun 17 13:10:45 2010 -0400
+
+    Staging: xgifb: Remove unused code
+    
+    Remove code that was removed using #if 0
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Arnaud Patard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/XGI_accel.c b/drivers/staging/xgifb/XGI_accel.c
+index 85af55c32091..feda029fa82a 100644
+--- a/drivers/staging/xgifb/XGI_accel.c
++++ b/drivers/staging/xgifb/XGI_accel.c
+@@ -97,102 +97,12 @@ static const unsigned char myrops[] = {
+    };
+ 
+ /* 300 series */
+-#if 0
+-static void
+-XGI300Sync(void)
+-{
+-	XGI300Idle
+-}
+-#endif
+ static void
+ XGI310Sync(void)
+ {
+ 	XGI310Idle
+ }
+-#if 0
+-static void
+-XGI300SetupForScreenToScreenCopy(int xdir, int ydir, int rop,
+-                                unsigned int planemask, int trans_color)
+-{
+-	XGI300SetupDSTColorDepth(xgi_video_info.DstColor);
+-	XGI300SetupSRCPitch(xgi_video_info.video_linelength)
+-	XGI300SetupDSTRect(xgi_video_info.video_linelength, 0xFFF)
+-
+-	if(trans_color != -1) {
+-		XGI300SetupROP(0x0A)
+-		XGI300SetupSRCTrans(trans_color)
+-		XGI300SetupCMDFlag(TRANSPARENT_BITBLT)
+-	} else {
+-	        XGI300SetupROP(XGIALUConv[rop])
+-	}
+-	if(xdir > 0) {
+-		XGI300SetupCMDFlag(X_INC)
+-	}
+-	if(ydir > 0) {
+-		XGI300SetupCMDFlag(Y_INC)
+-	}
+-}
+-
+-static void
+-XGI300SubsequentScreenToScreenCopy(int src_x, int src_y, int dst_x, int dst_y,
+-                                int width, int height)
+-{
+-	long srcbase, dstbase;
+-
+-	srcbase = dstbase = 0;
+-	if (src_y >= 2048) {
+-		srcbase = xgi_video_info.video_linelength * src_y;
+-		src_y = 0;
+-	}
+-	if (dst_y >= 2048) {
+-		dstbase = xgi_video_info.video_linelength * dst_y;
+-		dst_y = 0;
+-	}
+ 
+-	XGI300SetupSRCBase(srcbase);
+-	XGI300SetupDSTBase(dstbase);
+-
+-	if(!(xgi_video_info.CommandReg & X_INC))  {
+-		src_x += width-1;
+-		dst_x += width-1;
+-	}
+-	if(!(xgi_video_info.CommandReg & Y_INC))  {
+-		src_y += height-1;
+-		dst_y += height-1;
+-	}
+-	XGI300SetupRect(width, height)
+-	XGI300SetupSRCXY(src_x, src_y)
+-	XGI300SetupDSTXY(dst_x, dst_y)
+-	XGI300DoCMD
+-}
+-
+-static void
+-XGI300SetupForSolidFill(int color, int rop, unsigned int planemask)
+-{
+-	XGI300SetupPATFG(color)
+-	XGI300SetupDSTRect(xgi_video_info.video_linelength, 0xFFF)
+-	XGI300SetupDSTColorDepth(xgi_video_info.DstColor);
+-	XGI300SetupROP(XGIPatALUConv[rop])
+-	XGI300SetupCMDFlag(PATFG)
+-}
+-
+-static void
+-XGI300SubsequentSolidFillRect(int x, int y, int w, int h)
+-{
+-	long dstbase;
+-
+-	dstbase = 0;
+-	if(y >= 2048) {
+-		dstbase = xgi_video_info.video_linelength * y;
+-		y = 0;
+-	}
+-	XGI300SetupDSTBase(dstbase)
+-	XGI300SetupDSTXY(x,y)
+-	XGI300SetupRect(w,h)
+-	XGI300SetupCMDFlag(X_INC | Y_INC | BITBLT)
+-	XGI300DoCMD
+-}
+-#endif
+ /* 310/325 series ------------------------------------------------ */
+ 
+ static void
+diff --git a/drivers/staging/xgifb/XGI_main.h b/drivers/staging/xgifb/XGI_main.h
+index a3862a98803e..7c643a6a0632 100644
+--- a/drivers/staging/xgifb/XGI_main.h
++++ b/drivers/staging/xgifb/XGI_main.h
+@@ -805,10 +805,6 @@ extern void     fbcon_XGI_fillrect(struct fb_info *info,
+                                    const struct fb_fillrect *rect);
+ extern void     fbcon_XGI_copyarea(struct fb_info *info,
+                                    const struct fb_copyarea *area);
+-#if 0
+-extern void     cfb_imageblit(struct fb_info *info,
+-                              const struct fb_image *image);
+-#endif
+ extern int      fbcon_XGI_sync(struct fb_info *info);
+ 
+ static int XGIfb_ioctl(struct fb_info *info, unsigned int cmd,
+diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
+index c3483b60cf31..e3f837337fba 100644
+--- a/drivers/staging/xgifb/XGI_main_26.c
++++ b/drivers/staging/xgifb/XGI_main_26.c
+@@ -371,18 +371,6 @@ XGIfb_mode_rate_to_ddata(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExt
+       }
+     }
+ 
+-#if 0  /* That's bullshit, only the resolution needs to be shifted */
+-    if((*vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+-       *upper_margin <<= 1;
+-       *lower_margin <<= 1;
+-       *vsync_len <<= 1;
+-    } else if((*vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+-       *upper_margin >>= 1;
+-       *lower_margin >>= 1;
+-       *vsync_len >>= 1;
+-    }
+-#endif
+-
+     return 1;
+ }
+ 
+@@ -1537,58 +1525,7 @@ static int XGIfb_pan_display( struct fb_var_screeninfo *var,
+ }
+ #endif
+ 
+-#if 0
+-static int XGIfb_mmap(struct fb_info *info, struct file *file,
+-		      struct vm_area_struct *vma)
+-{
+-	unsigned long start;
+-	unsigned long off;
+-	u32 len, mmio_off;
+-
+-	DEBUGPRN("inside mmap");
+-	if(vma->vm_pgoff > (~0UL >> PAGE_SHIFT))  return -EINVAL;
+-
+-	off = vma->vm_pgoff << PAGE_SHIFT;
+ 
+-	start = (unsigned long) xgi_video_info.video_base;
+-	len = PAGE_ALIGN((start & ~PAGE_MASK) + xgi_video_info.video_size);
+-	start &= PAGE_MASK;
+-#if 0
+-	if (off >= len) {
+-		off -= len;
+-#endif
+-	/* By Jake Page: Treat mmap request with offset beyond heapstart
+-	 *               as request for mapping the mmio area
+-	 */
+-	#if 1
+-	mmio_off = PAGE_ALIGN((start & ~PAGE_MASK) + xgi_video_info.heapstart);
+-	if(off >= mmio_off) {
+-		off -= mmio_off;
+-		if(info->var.accel_flags) return -EINVAL;
+-
+-		start = (unsigned long) xgi_video_info.mmio_base;
+-		len = PAGE_ALIGN((start & ~PAGE_MASK) + XGIfb_mmio_size);
+-	}
+-	start &= PAGE_MASK;
+-	#endif
+-	if((vma->vm_end - vma->vm_start + off) > len)	return -EINVAL;
+-
+-	off += start;
+-	vma->vm_pgoff = off >> PAGE_SHIFT;
+-	vma->vm_flags |= VM_IO;   /* by Jake Page; is that really needed? */
+-
+-#if defined(__i386__) || defined(__x86_64__)
+-	if (boot_cpu_data.x86 > 3)
+-		pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
+-#endif
+-	if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, vma->vm_end - vma->vm_start,
+-				vma->vm_page_prot))
+-		return -EAGAIN;
+-
+-        DEBUGPRN("end of mmap");
+-	return 0;
+-}
+-#endif
+ static int XGIfb_blank(int blank, struct fb_info *info)
+ {
+ 	u8 reg;
+@@ -2652,12 +2589,6 @@ static void XGIfb_post_setmode(void)
+ {
+ 	u8 reg;
+ 	BOOLEAN doit = 1;
+-#if 0	/* TW: Wrong: Is not in MMIO space, but in RAM */
+-	/* Backup mode number to MMIO space */
+-	if(xgi_video_info.mmio_vbase) {
+-	  *(volatile u8 *)(((u8*)xgi_video_info.mmio_vbase) + 0x449) = (unsigned char)XGIfb_mode_no;
+-	}
+-#endif
+ /*	outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
+ 	outXGIIDXREG(XGICR,0x13,0x00);
+ 	setXGIIDXREG(XGISR,0x0E,0xF0,0x01);
+@@ -3445,20 +3376,6 @@ int __devinit xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 
+ 	        }
+ 
+-
+-#if 0
+-#ifdef XGIFB_PAN
+-		if(XGIfb_ypan) {
+-	    		default_var.yres_virtual =
+-				xgi_video_info.heapstart / (default_var.xres * (default_var.bits_per_pixel >> 3));
+-	    		if(default_var.yres_virtual <= default_var.yres) {
+-	        		default_var.yres_virtual = default_var.yres;
+-	    		}
+-		}
+-#endif
+-#endif
+-
+-
+ 		xgi_video_info.accel = 0;
+ 		if(XGIfb_accel) {
+ 		   xgi_video_info.accel = -1;
+diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
+index 04e6f6ef922e..2abdd24ef52b 100644
+--- a/drivers/staging/xgifb/vb_init.c
++++ b/drivers/staging/xgifb/vb_init.c
+@@ -476,15 +476,6 @@ printk("19");
+         }   	/* SkipDramSizing */
+         else
+         {
+-#if 0
+-           if ( HwDeviceExtension->jChipType == XG20 )
+-            {
+-            	XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , pVBInfo->SR15[0][XGINew_RAMType] ) ;
+-                XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , pVBInfo->SR15[1][XGINew_RAMType] ) ;
+-                XGINew_SetReg1( pVBInfo->P3c4 , 0x20 , 0x20 ) ;
+-            }
+-            else
+-#endif
+ {
+ printk("20");
+ 
+@@ -2700,195 +2691,6 @@ void ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo)
+ 	volatile unsigned char *pVideoMemory = (unsigned char *)pVBInfo->ROMAddr;
+     ULONG   i ;
+     UCHAR   j , k ;
+-#if 0
+-    ULONG   ii , jj ;
+-    i = pVideoMemory[ 0x1CF ] | ( pVideoMemory[ 0x1D0 ] << 8 ) ;		/* UniROM */
+-    if ( i != 0 )
+-        UNIROM = 1 ;
+-
+-    ii = 0x90 ;
+-    for( jj = 0x00 ; jj < 0x08 ; jj++ )
+-    {
+-        pVBInfo->MCLKData[ jj ].SR28 = pVideoMemory[ ii ] ;
+-        pVBInfo->MCLKData[ jj ].SR29 = pVideoMemory[ ii + 1] ;
+-        pVBInfo->MCLKData[ jj ].SR2A = pVideoMemory[ ii + 2] ;
+-        pVBInfo->MCLKData[ jj ].CLOCK = pVideoMemory[ ii + 3 ] | ( pVideoMemory[ ii + 4 ] << 8 ) ;
+-        ii += 0x05 ;
+-    }
+-
+-    ii = 0xB8 ;
+-    for( jj = 0x00 ; jj < 0x08 ; jj++ )
+-    {
+-        pVBInfo->ECLKData[ jj ].SR2E = pVideoMemory[ ii ] ;
+-        pVBInfo->ECLKData[ jj ].SR2F=pVideoMemory[ ii + 1 ] ;
+-        pVBInfo->ECLKData[ jj ].SR30= pVideoMemory[ ii + 2 ] ;
+-        pVBInfo->ECLKData[ jj ].CLOCK= pVideoMemory[ ii + 3 ] | ( pVideoMemory[ ii + 4 ] << 8 ) ;
+-        ii += 0x05 ;
+-    }
+-
+-    /* Volari customize data area start */
+-    /* if ( ChipType == XG40 ) */
+-    if ( ChipType >= XG40 )
+-    {
+-        ii = 0xE0 ;
+-        for( jj = 0x00 ; jj < 0x03 ; jj++ )
+-        {
+-            pVBInfo->SR15[ jj ][ 0 ] = pVideoMemory[ ii ] ;		/* SR13, SR14, and SR18 */
+-            pVBInfo->SR15[ jj ][ 1 ] = pVideoMemory[ ii + 1 ] ;
+-            pVBInfo->SR15[ jj ][ 2 ] = pVideoMemory[ ii + 2 ] ;
+-            pVBInfo->SR15[ jj ][ 3 ] = pVideoMemory[ ii + 3 ] ;
+-            pVBInfo->SR15[ jj ][ 4 ] = pVideoMemory[ ii + 4 ] ;
+-            pVBInfo->SR15[ jj ][ 5 ] = pVideoMemory[ ii + 5 ] ;
+-            pVBInfo->SR15[ jj ][ 6 ] = pVideoMemory[ ii + 6 ] ;
+-            pVBInfo->SR15[ jj ][ 7 ] = pVideoMemory[ ii + 7 ] ;
+-            ii += 0x08 ;
+-        }
+-        ii = 0x110 ;
+-        jj = 0x03 ;
+-        pVBInfo->SR15[ jj ][ 0 ] = pVideoMemory[ ii ] ;		/* SR1B */
+-        pVBInfo->SR15[ jj ][ 1 ] = pVideoMemory[ ii + 1 ] ;
+-        pVBInfo->SR15[ jj ][ 2 ] = pVideoMemory[ ii + 2 ] ;
+-        pVBInfo->SR15[ jj ][ 3 ] = pVideoMemory[ ii + 3 ] ;
+-        pVBInfo->SR15[ jj ][ 4 ] = pVideoMemory[ ii + 4 ] ;
+-        pVBInfo->SR15[ jj ][ 5 ] = pVideoMemory[ ii + 5 ] ;
+-        pVBInfo->SR15[ jj ][ 6 ] = pVideoMemory[ ii + 6 ] ;
+-        pVBInfo->SR15[ jj ][ 7 ] = pVideoMemory[ ii + 7 ] ;
+-
+-        *pVBInfo->pSR07 = pVideoMemory[ 0x74 ] ;
+-        *pVBInfo->pSR1F = pVideoMemory[ 0x75 ] ;
+-        *pVBInfo->pSR21 = pVideoMemory[ 0x76 ] ;
+-        *pVBInfo->pSR22 = pVideoMemory[ 0x77 ] ;
+-        *pVBInfo->pSR23 = pVideoMemory[ 0x78 ] ;
+-        *pVBInfo->pSR24 = pVideoMemory[ 0x79 ] ;
+-        pVBInfo->SR25[ 0 ] = pVideoMemory[ 0x7A ] ;
+-        *pVBInfo->pSR31 = pVideoMemory[ 0x7B ] ;
+-        *pVBInfo->pSR32 = pVideoMemory[ 0x7C ] ;
+-        *pVBInfo->pSR33 = pVideoMemory[ 0x7D ] ;
+-        ii = 0xF8 ;
+-
+-        for( jj = 0 ; jj < 3 ; jj++ )
+-        {
+-            pVBInfo->CR40[ jj ][ 0 ] = pVideoMemory[ ii ] ;
+-            pVBInfo->CR40[ jj ][ 1 ] = pVideoMemory[ ii + 1 ] ;
+-            pVBInfo->CR40[ jj ][ 2 ] = pVideoMemory[ ii + 2 ] ;
+-            pVBInfo->CR40[ jj ][ 3 ] = pVideoMemory[ ii + 3 ] ;
+-            pVBInfo->CR40[ jj ][ 4 ] = pVideoMemory[ ii + 4 ] ;
+-            pVBInfo->CR40[ jj ][ 5 ] = pVideoMemory[ ii + 5 ] ;
+-            pVBInfo->CR40[ jj ][ 6 ] = pVideoMemory[ ii + 6 ] ;
+-            pVBInfo->CR40[ jj ][ 7 ] = pVideoMemory[ ii + 7 ] ;
+-            ii += 0x08 ;
+-        }
+-
+-        ii = 0x118 ;
+-        for( j = 3 ; j < 24 ; j++ )
+-        {
+-            pVBInfo->CR40[ j ][ 0 ] = pVideoMemory[ ii ] ;
+-            pVBInfo->CR40[ j ][ 1 ] = pVideoMemory[ ii + 1 ] ;
+-            pVBInfo->CR40[ j ][ 2 ] = pVideoMemory[ ii + 2 ] ;
+-            pVBInfo->CR40[ j ][ 3 ] = pVideoMemory[ ii + 3 ] ;
+-            pVBInfo->CR40[ j ][ 4 ] = pVideoMemory[ ii + 4 ] ;
+-            pVBInfo->CR40[ j ][ 5 ] = pVideoMemory[ ii + 5 ] ;
+-            pVBInfo->CR40[ j ][ 6 ] = pVideoMemory[ ii + 6 ] ;
+-            pVBInfo->CR40[ j ][ 7 ] = pVideoMemory[ ii + 7 ] ;
+-            ii += 0x08 ;
+-        }
+-
+-        i = pVideoMemory[ 0x1C0 ] | ( pVideoMemory[ 0x1C1 ] << 8 ) ;
+-
+-        for( j = 0 ; j < 8 ; j++ )
+-        {
+-            for( k = 0 ; k < 4 ; k++ )
+-                pVBInfo->CR6B[ j ][ k ] = pVideoMemory[ i + 4 * j + k ] ;
+-        }
+-
+-        i = pVideoMemory[ 0x1C2 ] | ( pVideoMemory[ 0x1C3 ] << 8 ) ;
+-
+-        for( j = 0 ; j < 8 ; j++ )
+-        {
+-            for( k = 0 ; k < 4 ; k++ )
+-                pVBInfo->CR6E[ j ][ k ] = pVideoMemory[ i + 4 * j + k ] ;
+-        }
+-
+-        i = pVideoMemory[ 0x1C4 ] | ( pVideoMemory[ 0x1C5 ] << 8 ) ;
+-        for( j = 0 ; j < 8 ; j++ )
+-        {
+-            for( k = 0 ; k < 32 ; k++ )
+-                pVBInfo->CR6F[ j ][ k ] = pVideoMemory[ i + 32 * j + k ] ;
+-        }
+-
+-        i = pVideoMemory[ 0x1C6 ] | ( pVideoMemory[ 0x1C7 ] << 8 ) ;
+-
+-        for( j = 0 ; j < 8 ; j++ )
+-        {
+-            for( k = 0 ; k < 2 ; k++ )
+-                pVBInfo->CR89[ j ][ k ] = pVideoMemory[ i + 2 * j + k ] ;
+-        }
+-
+-        i = pVideoMemory[ 0x1C8 ] | ( pVideoMemory[ 0x1C9 ] << 8 ) ;
+-        for( j = 0 ; j < 12 ; j++ )
+-            pVBInfo->AGPReg[ j ] = pVideoMemory[ i + j ] ;
+-
+-        i = pVideoMemory[ 0x1CF ] | ( pVideoMemory[ 0x1D0 ] << 8 ) ;
+-        for( j = 0 ; j < 4 ; j++ )
+-            pVBInfo->SR16[ j ] = pVideoMemory[ i + j ] ;
+-
+-        if ( ChipType == XG21 )
+-        {
+-            if (pVideoMemory[ 0x67 ] & 0x80)
+-            {
+-                *pVBInfo->pDVOSetting = pVideoMemory[ 0x67 ];
+-            }
+-            if ( (pVideoMemory[ 0x67 ] & 0xC0) == 0xC0 )
+-            {
+-                *pVBInfo->pCR2E = pVideoMemory[ i + 4 ] ;
+-                *pVBInfo->pCR2F = pVideoMemory[ i + 5 ] ;
+-                *pVBInfo->pCR46 = pVideoMemory[ i + 6 ] ;
+-                *pVBInfo->pCR47 = pVideoMemory[ i + 7 ] ;
+-            }
+-        }
+-
+-        if ( ChipType == XG27 )
+-        {
+-            jj = i+j;
+-            for( i = 0 ; i <= 0xB ; i++,jj++ )
+-              pVBInfo->pCRD0[i] = pVideoMemory[ jj ] ;
+-            for( i = 0x0 ; i <= 0x1 ; i++,jj++ )
+-              pVBInfo->pCRDE[i] = pVideoMemory[ jj ] ;
+-
+-            *pVBInfo->pSR40 = pVideoMemory[ jj ] ;
+-            jj++;
+-            *pVBInfo->pSR41 = pVideoMemory[ jj ] ;
+-
+-            if (pVideoMemory[ 0x67 ] & 0x80)
+-            {
+-                *pVBInfo->pDVOSetting = pVideoMemory[ 0x67 ];
+-            }
+-            if ( (pVideoMemory[ 0x67 ] & 0xC0) == 0xC0 )
+-            {
+-                jj++;
+-                *pVBInfo->pCR2E = pVideoMemory[ jj ] ;
+-                *pVBInfo->pCR2F = pVideoMemory[ jj + 1 ] ;
+-                *pVBInfo->pCR46 = pVideoMemory[ jj + 2 ] ;
+-                *pVBInfo->pCR47 = pVideoMemory[ jj + 3 ] ;
+-            }
+-
+-        }
+-
+-        *pVBInfo->pCRCF = pVideoMemory[ 0x1CA ] ;
+-        *pVBInfo->pXGINew_DRAMTypeDefinition = pVideoMemory[ 0x1CB ] ;
+-        *pVBInfo->pXGINew_I2CDefinition = pVideoMemory[ 0x1D1 ] ;
+-        if ( ChipType >= XG20 )
+-        {
+-           *pVBInfo->pXGINew_CR97 = pVideoMemory[ 0x1D2 ] ;
+-           if ( ChipType == XG27 )
+-           {
+-             *pVBInfo->pSR36 = pVideoMemory[ 0x1D3 ] ;
+-             *pVBInfo->pCR8F = pVideoMemory[ 0x1D5 ] ;
+-           }
+-        }
+-
+-    }
+-#endif
+     /* Volari customize data area end */
+ 
+     if ( ChipType == XG21 )
+diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c
+index 662ca77f79e4..4a2fa32e7d94 100644
+--- a/drivers/staging/xgifb/vb_setmode.c
++++ b/drivers/staging/xgifb/vb_setmode.c
+@@ -2579,53 +2579,6 @@ void XGI_WriteDAC( USHORT dl , USHORT ah , USHORT al , USHORT dh,PVB_DEVICE_INFO
+     XGINew_SetReg3( pVBInfo->P3c9 , ( USHORT )bl ) ;
+ }
+ 
+-#if 0
+-/* --------------------------------------------------------------------- */
+-/* Function : XGI_ClearBuffer */
+-/* Input : */
+-/* Output : */
+-/* Description : */
+-/* --------------------------------------------------------------------- */
+-void XGI_ClearBuffer( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo, PVB_DEVICE_INFO  pVBInfo)
+-{
+-    void *VideoMemoryAddress = (void *)HwDeviceExtension->pjVideoMemoryAddress;
+-    ULONG AdapterMemorySize  = ( ULONG )HwDeviceExtension->ulVideoMemorySize ;
+-    unsigned short *pBuffer ;
+-    int i ;
+-
+-    if ( pVBInfo->ModeType >= ModeEGA )
+-    {
+-        if ( ModeNo > 0x13 )
+-        {
+-            AdapterMemorySize = 0x40000 ;	/* clear 256k */
+-            /* GetDRAMSize( HwDeviceExtension ) ; */
+-	    memset(VideoMemoryAddress, 0, AdapterMemorySize);
+-        }
+-        else
+-        {
+-/*
+-            pBuffer = VideoMemoryAddress ;
+-            for( i = 0 ; i < 0x4000 ; i++ )
+-                pBuffer[ i ] = 0x0000 ;
+-*/
+-        }
+-    }
+-    else
+-    {
+-        pBuffer = VideoMemoryAddress ;
+-        if ( pVBInfo->ModeType < ModeCGA )
+-        {
+-/*
+-            for ( i = 0 ; i < 0x4000 ; i++ )
+-                pBuffer[ i ] = 0x0720 ;
+-*/
+-        }
+-        else
+-		memset(VideoMemoryAddress , 0, 0x8000);
+-    }
+-}
+-
+-#endif
+ /* --------------------------------------------------------------------- */
+ /* Function : XGI_SetLCDAGroup */
+ /* Input : */
+diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h
+index 781caefc56b1..f804dfac6902 100644
+--- a/drivers/staging/xgifb/vb_table.h
++++ b/drivers/staging/xgifb/vb_table.h
+@@ -126,36 +126,6 @@ UCHAR XGI27_cr41[24][8]=
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}/* 23 CRC5 */
+ };
+ 
+-
+-#if 0
+-UCHAR XGI27_cr41[24][8]=
+-{
+-{0x20,0x60,0x60,0x00,0x00,0x00,0x00,0x00},/* 0 CR41 */
+-{0x04,0x44,0x84,0x00,0x00,0x00,0x00,0x00},/* 1 CR8A */
+-{0x04,0x40,0x84,0x00,0x00,0x00,0x00,0x00},/* 2 CR8B */
+-{0xb5,0x03,0xa4,0x00,0x00,0x00,0x00,0x00},/* 3 CR40[7],CR99[2:0],CR45[3:0]*/
+-{0xf0,0xf5,0xf0,0x00,0x00,0x00,0x00,0x00},/* 4 CR59 */
+-{0xa4,0x1C,0x24,0x00,0x00,0x00,0x00,0x00},/* 5 CR68 */
+-{0x77,0x77,0x44,0x00,0x00,0x00,0x00,0x00},/* 6 CR69 */
+-{0x77,0x77,0x44,0x00,0x00,0x00,0x00,0x00},/* 7 CR6A */
+-{0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00},/* 8 CR6D */
+-{0x55,0x55,0x55,0x00,0x00,0x00,0x00,0x00},/* 9 CR80 */
+-{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/* 10 CR81 */
+-{0x48,0xa8,0x48,0x00,0x00,0x00,0x00,0x00},/* 11 CR82 */
+-{0x77,0x88,0x77,0x00,0x00,0x00,0x00,0x00},/* 12 CR85 */
+-{0x88,0x88,0x88,0x00,0x00,0x00,0x00,0x00},/* 13 CR86 */
+-{0x44,0x32,0x44,0x00,0x00,0x00,0x00,0x00},/* 14 CR90 */
+-{0x44,0x33,0x44,0x00,0x00,0x00,0x00,0x00},/* 15 CR91 */
+-{0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00},/* 16 CR92 */
+-{0x44,0x63,0x44,0x00,0x00,0x00,0x00,0x00},/* 17 CR93 */
+-{0x0A,0x14,0x0A,0x00,0x00,0x00,0x00,0x00},/* 18 CR94 */
+-{0x0C,0x0B,0x0C,0x00,0x00,0x00,0x00,0x00},/* 19 CR95 */
+-{0x05,0x22,0x05,0x00,0x00,0x00,0x00,0x00},/* 20 CR96 */
+-{0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00},/* 21 CRC3 */
+-{0x03,0x00,0x02,0x00,0x00,0x00,0x00,0x00},/* 22 CRC4 */
+-{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}/* 23 CRC5 */
+-};
+-#endif
+ UCHAR XGI340_CR6B[8][4]={
+ {0xaa,0xaa,0xaa,0xaa},
+ {0xaa,0xaa,0xaa,0xaa},

commit fc3678a6c0ee4eb59244a5ba2da58ca47fd20501
+Author: Bill Pemberton 
+Date:   Thu Jun 17 13:10:44 2010 -0400
+
+    Staging: xgifb: Remove PUSHORT, PLONGU, and PVOID typedefs
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Arnaud Patard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
+index 7d4beda828d3..04e6f6ef922e 100644
+--- a/drivers/staging/xgifb/vb_init.c
++++ b/drivers/staging/xgifb/vb_init.c
+@@ -1619,9 +1619,9 @@ void XGINew_SetDRAMSizingType( int index , USHORT DRAMTYPE_TABLE[][ 5 ] ,PVB_DEV
+ void XGINew_CheckBusWidth_310(  PVB_DEVICE_INFO pVBInfo)
+ {
+     USHORT data ;
+-    PULONG volatile pVideoMemory ;
++    volatile unsigned long *pVideoMemory ;
+ 
+-    pVideoMemory = (PULONG) pVBInfo->FBAddr;
++    pVideoMemory = (unsigned long *) pVBInfo->FBAddr;
+ 
+     if ( XGINew_Get310DRAMType( pVBInfo ) < 2 )
+     {
+@@ -1832,17 +1832,17 @@ int XGINew_CheckColumn( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INF
+ 
+     for( i = 0 , Position = 0 ; i < 2 ; i++ )
+     {
+-        *( ( PULONG )( pVBInfo->FBAddr + Position ) ) = Position ;
+-        Position += Increment ;
++	    *((unsigned long *)(pVBInfo->FBAddr + Position)) = Position;
++	    Position += Increment ;
+     }
+ 
+ 
+     for( i = 0 , Position = 0 ; i < 2 ; i++ )
+     {
+         /* if ( pVBInfo->FBAddr[ Position ] != Position ) */
+-        if ( ( *( PULONG )( pVBInfo->FBAddr + Position ) ) != Position )
+-            return( 0 ) ;
+-        Position += Increment ;
++	    if ((*(unsigned long *)(pVBInfo->FBAddr + Position)) != Position)
++		    return 0;
++	    Position += Increment;
+     }
+     return( 1 ) ;
+ }
+@@ -1864,16 +1864,16 @@ int XGINew_CheckBanks( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO
+     for( i = 0 , Position = 0 ; i < 4 ; i++ )
+     {
+         /* pVBInfo->FBAddr[ Position ] = Position ; */
+-        *( ( PULONG )( pVBInfo->FBAddr + Position ) ) = Position ;
+-        Position += Increment ;
++	    *((unsigned long *)(pVBInfo->FBAddr + Position)) = Position;
++	    Position += Increment ;
+     }
+ 
+     for( i = 0 , Position = 0 ; i < 4 ; i++ )
+     {
+         /* if (pVBInfo->FBAddr[ Position ] != Position ) */
+-        if ( ( *( PULONG )( pVBInfo->FBAddr + Position ) ) != Position )
+-            return( 0 ) ;
+-        Position += Increment ;
++	    if ((*(unsigned long *)(pVBInfo->FBAddr + Position)) != Position)
++		    return 0;
++	    Position += Increment;
+     }
+     return( 1 ) ;
+ }
+@@ -1896,18 +1896,18 @@ int XGINew_CheckRank( int RankNo , int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB
+     for( i = 0 , Position = 0 ; i < 2 ; i++ )
+     {
+         /* pVBInfo->FBAddr[ Position ] = Position ; */
+-        /* *( ( PULONG )( pVBInfo->FBAddr ) ) = Position ; */
+-        *( ( PULONG )( pVBInfo->FBAddr + Position ) ) = Position ;
+-        Position += Increment ;
++        /* *( (unsigned long *)( pVBInfo->FBAddr ) ) = Position ; */
++	    *((unsigned long *)(pVBInfo->FBAddr + Position)) = Position;
++	    Position += Increment;
+     }
+ 
+     for( i = 0 , Position = 0 ; i < 2 ; i++ )
+     {
+         /* if ( pVBInfo->FBAddr[ Position ] != Position ) */
+-        /* if ( ( *( PULONG )( pVBInfo->FBAddr ) ) != Position ) */
+-        if ( ( *( PULONG )( pVBInfo->FBAddr + Position ) ) != Position )
+-            return( 0 ) ;
+-        Position += Increment ;
++        /* if ( ( *(unsigned long *)( pVBInfo->FBAddr ) ) != Position ) */
++	    if ((*(unsigned long *)(pVBInfo->FBAddr + Position)) != Position)
++		    return 0;
++	    Position += Increment;
+     }
+     return( 1 );
+ }
+@@ -1930,18 +1930,18 @@ int XGINew_CheckDDRRank( int RankNo , int index , USHORT DRAMTYPE_TABLE[][ 5 ],
+     Increment += Increment / 2 ;
+ 
+     Position = 0;
+-    *( ( PULONG )( pVBInfo->FBAddr + Position + 0 ) ) = 0x01234567 ;
+-    *( ( PULONG )( pVBInfo->FBAddr + Position + 1 ) ) = 0x456789AB ;
+-    *( ( PULONG )( pVBInfo->FBAddr + Position + 2 ) ) = 0x55555555 ;
+-    *( ( PULONG )( pVBInfo->FBAddr + Position + 3 ) ) = 0x55555555 ;
+-    *( ( PULONG )( pVBInfo->FBAddr + Position + 4 ) ) = 0xAAAAAAAA ;
+-    *( ( PULONG )( pVBInfo->FBAddr + Position + 5 ) ) = 0xAAAAAAAA ;
+-
+-    if ( ( *( PULONG )( pVBInfo->FBAddr + 1 ) ) == 0x456789AB )
+-        return( 1 ) ;
++    *((unsigned long *)(pVBInfo->FBAddr + Position + 0)) = 0x01234567;
++    *((unsigned long *)(pVBInfo->FBAddr + Position + 1)) = 0x456789AB;
++    *((unsigned long *)(pVBInfo->FBAddr + Position + 2)) = 0x55555555;
++    *((unsigned long *)(pVBInfo->FBAddr + Position + 3)) = 0x55555555;
++    *((unsigned long *)(pVBInfo->FBAddr + Position + 4)) = 0xAAAAAAAA;
++    *((unsigned long *)(pVBInfo->FBAddr + Position + 5)) = 0xAAAAAAAA;
+ 
+-    if ( ( *( PULONG )( pVBInfo->FBAddr + 0 ) ) == 0x01234567 )
+-        return( 0 ) ;
++    if ((*(unsigned long *)(pVBInfo->FBAddr + 1)) == 0x456789AB)
++	    return 1;
++
++    if ((*(unsigned long *)(pVBInfo->FBAddr + 0)) == 0x01234567)
++	    return 0;
+ 
+     data = XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) ;
+     data &= 0xF3 ;
+@@ -2147,26 +2147,26 @@ int XGINew_ReadWriteRest( USHORT StopAddr , USHORT StartAddr, PVB_DEVICE_INFO pV
+     int i ;
+     ULONG Position = 0 ;
+ 
+-   *( ( PULONG )( pVBInfo->FBAddr + Position ) ) = Position ;
++    *((unsigned long *)(pVBInfo->FBAddr + Position)) = Position;
+ 
+     for( i = StartAddr ; i <= StopAddr ; i++ )
+     {
+         Position = 1 << i ;
+-        *( ( PULONG )( pVBInfo->FBAddr + Position ) ) = Position ;
++	*((unsigned long *)(pVBInfo->FBAddr + Position)) = Position;
+     }
+ 
+     DelayUS( 500 ) ;	/* [Vicent] 2004/04/16. Fix #1759 Memory Size error in Multi-Adapter. */
+ 
+     Position = 0 ;
+ 
+-   if ( ( *( PULONG )( pVBInfo->FBAddr + Position ) ) != Position )
+-        return( 0 ) ;
++   if ((*(unsigned long *)(pVBInfo->FBAddr + Position)) != Position)
++	   return 0;
+ 
+     for( i = StartAddr ; i <= StopAddr ; i++ )
+     {
+         Position = 1 << i ;
+-        if ( ( *( PULONG )( pVBInfo->FBAddr + Position ) ) != Position )
+-            return( 0 ) ;
++	if ((*(unsigned long *)(pVBInfo->FBAddr + Position)) != Position)
++		return 0;
+     }
+     return( 1 ) ;
+ }
+diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c
+index a0ccce07f125..662ca77f79e4 100644
+--- a/drivers/staging/xgifb/vb_setmode.c
++++ b/drivers/staging/xgifb/vb_setmode.c
+@@ -2588,9 +2588,9 @@ void XGI_WriteDAC( USHORT dl , USHORT ah , USHORT al , USHORT dh,PVB_DEVICE_INFO
+ /* --------------------------------------------------------------------- */
+ void XGI_ClearBuffer( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo, PVB_DEVICE_INFO  pVBInfo)
+ {
+-    PVOID VideoMemoryAddress = ( PVOID )HwDeviceExtension->pjVideoMemoryAddress ;
++    void *VideoMemoryAddress = (void *)HwDeviceExtension->pjVideoMemoryAddress;
+     ULONG AdapterMemorySize  = ( ULONG )HwDeviceExtension->ulVideoMemorySize ;
+-    PUSHORT pBuffer ;
++    unsigned short *pBuffer ;
+     int i ;
+ 
+     if ( pVBInfo->ModeType >= ModeEGA )
+diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h
+index ec4c83f7a7c4..0d5472ec9297 100644
+--- a/drivers/staging/xgifb/vgatypes.h
++++ b/drivers/staging/xgifb/vgatypes.h
+@@ -28,22 +28,10 @@ typedef unsigned short USHORT;
+ typedef unsigned long ULONG;
+ #endif
+ 
+-#ifndef PUSHORT
+-typedef USHORT *PUSHORT;
+-#endif
+-
+-#ifndef PLONGU
+-typedef ULONG *PULONG;
+-#endif
+-
+ #ifndef VOID
+ typedef void VOID;
+ #endif
+ 
+-#ifndef PVOID
+-typedef void *PVOID;
+-#endif
+-
+ #ifndef BOOLEAN
+ typedef UCHAR BOOLEAN;
+ #endif
+@@ -126,7 +114,7 @@ struct _XGI_HW_DEVICE_INFO
+ 
+     BOOLEAN UseROM;		 /* Use the ROM image if provided */
+ 
+-    PVOID   pDevice;
++    void *pDevice;
+ 
+     unsigned char *pjVideoMemoryAddress;/* base virtual memory address */
+                                  /* of Linear VGA memory */

commit 274afb73bd14558d8363898c51d4ee708bba73b7
+Author: Bill Pemberton 
+Date:   Thu Jun 17 13:10:43 2010 -0400
+
+    Staging: xgifb: Remove PUCHAR typedef
+    
+    PUCHAR was unsigned char *, use that instead
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Arnaud Patard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
+index 403b5d4c2b54..c3483b60cf31 100644
+--- a/drivers/staging/xgifb/XGI_main_26.c
++++ b/drivers/staging/xgifb/XGI_main_26.c
+@@ -2970,9 +2970,10 @@ int __devinit xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	  xgi_video_info.mmio_base = pci_resource_start(pdev, 1);
+ 	  XGIfb_mmio_size =  pci_resource_len(pdev, 1);
+ 	  xgi_video_info.vga_base = pci_resource_start(pdev, 2) + 0x30;
+-	  XGIhw_ext.pjIOAddress = (PUCHAR)xgi_video_info.vga_base;
++	  XGIhw_ext.pjIOAddress = (unsigned char *)xgi_video_info.vga_base;
+ 	  //XGI_Pr.RelIO  = ioremap(pci_resource_start(pdev, 2), 128) + 0x30;
+-	  printk("XGIfb: Relocate IO address: %lx [%08lx] \n", (unsigned long)pci_resource_start(pdev, 2), XGI_Pr.RelIO);
++	  printk("XGIfb: Relocate IO address: %lx [%08lx]\n",
++		 (unsigned long)pci_resource_start(pdev, 2), XGI_Pr.RelIO);
+ 
+ 	  if (pci_enable_device(pdev))
+ 	          return -EIO;
+diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
+index da8f84fcf5e0..7d4beda828d3 100644
+--- a/drivers/staging/xgifb/vb_init.c
++++ b/drivers/staging/xgifb/vb_init.c
+@@ -127,7 +127,7 @@ BOOLEAN XGIInitNew( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+     PVB_DEVICE_INFO pVBInfo = &VBINF;
+     UCHAR   i , temp = 0 , temp1 ;
+      //       VBIOSVersion[ 5 ] ;
+-    PUCHAR  volatile pVideoMemory;
++    volatile unsigned char *pVideoMemory;
+ 
+     /* ULONG j, k ; */
+ 
+@@ -141,7 +141,7 @@ BOOLEAN XGIInitNew( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+ 
+     pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
+ 
+-    pVideoMemory = ( PUCHAR )pVBInfo->ROMAddr;
++    pVideoMemory = (unsigned char *)pVBInfo->ROMAddr;
+ 
+ 
+ //    Newdebugcode( 0x99 ) ;
+@@ -1254,7 +1254,7 @@ void XGINew_DDR_MRS(PVB_DEVICE_INFO pVBInfo)
+ {
+     USHORT data ;
+ 
+-    PUCHAR volatile pVideoMemory = ( PUCHAR )pVBInfo->ROMAddr ;
++    volatile unsigned char *pVideoMemory = (unsigned char *)pVBInfo->ROMAddr;
+ 
+     /* SR16 <- 1F,DF,2F,AF */
+     /* yriver modified SR16 <- 0F,DF,0F,AF */
+@@ -1320,7 +1320,7 @@ void XGINew_DDR_MRS(PVB_DEVICE_INFO pVBInfo)
+ /* --------------------------------------------------------------------- */
+ void XGINew_VerifyMclk( PXGI_HW_DEVICE_INFO  HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
+ {
+-    PUCHAR pVideoMemory = pVBInfo->FBAddr ;
++    unsigned char *pVideoMemory = pVBInfo->FBAddr ;
+     UCHAR i , j ;
+     USHORT Temp , SR21 ;
+ 
+@@ -2697,7 +2697,7 @@ void XGINew_InitVBIOSData(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO
+ /* --------------------------------------------------------------------- */
+ void ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo)
+ {
+-    PUCHAR  volatile pVideoMemory = ( PUCHAR )pVBInfo->ROMAddr ;
++	volatile unsigned char *pVideoMemory = (unsigned char *)pVBInfo->ROMAddr;
+     ULONG   i ;
+     UCHAR   j , k ;
+ #if 0
+@@ -3279,7 +3279,7 @@ void XGINew_SetModeScratch ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_
+ void XGINew_GetXG21Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+     UCHAR Temp;
+-    PUCHAR  volatile pVideoMemory = ( PUCHAR )pVBInfo->ROMAddr ;
++    volatile unsigned char *pVideoMemory = (unsigned char *)pVBInfo->ROMAddr;
+ 
+     pVBInfo->IF_DEF_LVDS = 0 ;
+ 
+diff --git a/drivers/staging/xgifb/vb_struct.h b/drivers/staging/xgifb/vb_struct.h
+index bb25c0e2785e..1ee619f65978 100644
+--- a/drivers/staging/xgifb/vb_struct.h
++++ b/drivers/staging/xgifb/vb_struct.h
+@@ -415,8 +415,8 @@ struct _VB_DEVICE_INFO
+     USHORT   NewFlickerMode;
+     USHORT   SelectCRT2Rate;
+ 
+-    PUCHAR ROMAddr;
+-    PUCHAR FBAddr;
++    unsigned char *ROMAddr;
++    unsigned char *FBAddr;
+     ULONG BaseAddr;
+     ULONG RelIO;
+ 
+diff --git a/drivers/staging/xgifb/vb_util.c b/drivers/staging/xgifb/vb_util.c
+index f83aee7ea90e..0842cb68b834 100644
+--- a/drivers/staging/xgifb/vb_util.c
++++ b/drivers/staging/xgifb/vb_util.c
+@@ -13,7 +13,7 @@ void XGINew_SetReg4( ULONG , ULONG ) ;
+ UCHAR XGINew_GetReg1( ULONG , USHORT) ;
+ UCHAR XGINew_GetReg2( ULONG ) ;
+ ULONG XGINew_GetReg3( ULONG ) ;
+-void XGINew_ClearDAC( PUCHAR ) ;
++void XGINew_ClearDAC(unsigned char *) ;
+ void     XGINew_SetRegANDOR(ULONG Port,USHORT Index,USHORT DataAND,USHORT DataOR);
+ void     XGINew_SetRegOR(ULONG Port,USHORT Index,USHORT DataOR);
+ void     XGINew_SetRegAND(ULONG Port,USHORT Index,USHORT DataAND);
+diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h
+index c1c798562ddd..ec4c83f7a7c4 100644
+--- a/drivers/staging/xgifb/vgatypes.h
++++ b/drivers/staging/xgifb/vgatypes.h
+@@ -28,10 +28,6 @@ typedef unsigned short USHORT;
+ typedef unsigned long ULONG;
+ #endif
+ 
+-#ifndef PUCHAR
+-typedef UCHAR *PUCHAR;
+-#endif
+-
+ #ifndef PUSHORT
+ typedef USHORT *PUSHORT;
+ #endif
+@@ -126,25 +122,25 @@ struct _XGI_HW_DEVICE_INFO
+     ULONG  ulExternalChip;       /* NO VB or other video bridge*/
+                                  /* if ujVBChipID = VB_CHIP_UNKNOWN, */
+ 
+-    PUCHAR  pjVirtualRomBase;    /* ROM image */
++    unsigned char *pjVirtualRomBase;    /* ROM image */
+ 
+     BOOLEAN UseROM;		 /* Use the ROM image if provided */
+ 
+     PVOID   pDevice;
+ 
+-    PUCHAR  pjVideoMemoryAddress;/* base virtual memory address */
++    unsigned char *pjVideoMemoryAddress;/* base virtual memory address */
+                                  /* of Linear VGA memory */
+ 
+     ULONG  ulVideoMemorySize;    /* size, in bytes, of the memory on the board */
+ 
+-    PUCHAR pjIOAddress;          /* base I/O address of VGA ports (0x3B0) */
++    unsigned char *pjIOAddress;          /* base I/O address of VGA ports (0x3B0) */
+ 
+-    PUCHAR pjCustomizedROMImage;
++    unsigned char *pjCustomizedROMImage;
+ 
+-    PUCHAR pj2ndVideoMemoryAddress;
++    unsigned char *pj2ndVideoMemoryAddress;
+     ULONG  ul2ndVideoMemorySize;
+ 
+-    PUCHAR pj2ndIOAddress;
++    unsigned char *pj2ndIOAddress;
+     UCHAR  jChipType;            /* Used to Identify Graphics Chip */
+                                  /* defined in the data structure type  */
+                                  /* "XGI_CHIP_TYPE" */

commit dda08c59680d5fce058430ad59678d27fa0448c2
+Author: Bill Pemberton 
+Date:   Thu Jun 17 13:10:42 2010 -0400
+
+    Staging: xgifb: Remove defines for TRUE, FALSE, and NULL
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Arnaud Patard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
+index c7ad6cdffff9..403b5d4c2b54 100644
+--- a/drivers/staging/xgifb/XGI_main_26.c
++++ b/drivers/staging/xgifb/XGI_main_26.c
+@@ -440,10 +440,10 @@ XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
+ 		DPRINTK("XGIfb: Set offset 0x%lx to 0x%lx\n", offset, *value);
+ 
+ 	if (!init) {
+-		init = TRUE;
++		init = 1;
+ 		pdev = pci_get_device(PCI_VENDOR_ID_XG, xgi_video_info.chip_id, pdev);
+ 		if (pdev) {
+-			valid_pdev = TRUE;
++			valid_pdev = 1;
+ 			pci_dev_put(pdev);
+ 		}
+ 	}
+@@ -451,7 +451,7 @@ XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
+ 	if (!valid_pdev) {
+ 		printk(KERN_DEBUG "XGIfb: Can't find XGI %d VGA device.\n",
+ 				xgi_video_info.chip_id);
+-		return FALSE;
++		return 0;
+ 	}
+ 
+ 	if (set == 0)
+@@ -459,7 +459,7 @@ XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
+ 	else
+ 		pci_write_config_dword(pdev, offset, (u32)(*value));
+ 
+-	return TRUE;
++	return 1;
+ }
+ 
+ /*BOOLEAN XGIfb_query_north_bridge_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
+@@ -470,7 +470,7 @@ XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
+ 	u16 nbridge_id = 0;
+ 
+ 	if (!init) {
+-		init = TRUE;
++		init = 1;
+ 		switch (xgi_video_info.chip) {
+ 		case XGI_540:
+ 			nbridge_id = PCI_DEVICE_ID_XG_540;
+@@ -497,13 +497,13 @@ XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
+ 
+ 		pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridge_id, pdev);
+ 		if (pdev)
+-			valid_pdev = TRUE;
++			valid_pdev = 1;
+ 	}
+ 
+ 	if (!valid_pdev) {
+ 		printk(KERN_DEBUG "XGIfb: Can't find XGI %d North Bridge device.\n",
+ 				nbridge_id);
+-		return FALSE;
++		return 0;
+ 	}
+ 
+ 	if (set == 0)
+@@ -511,7 +511,7 @@ XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
+ 	else
+ 		pci_write_config_dword(pdev, offset, (u32)(*value));
+ 
+-	return TRUE;
++	return 1;
+ }
+ */
+ /* ------------------ Internal helper routines ----------------- */
+@@ -953,14 +953,14 @@ static BOOLEAN XGIfb_bridgeisslave(void)
+ {
+    unsigned char usScratchP1_00;
+ 
+-   if(xgi_video_info.hasVB == HASVB_NONE) return FALSE;
++   if (xgi_video_info.hasVB == HASVB_NONE)
++	   return 0;
+ 
+    inXGIIDXREG(XGIPART1,0x00,usScratchP1_00);
+-   if( (usScratchP1_00 & 0x50) == 0x10)  {
+-	   return TRUE;
+-   } else {
+-           return FALSE;
+-   }
++   if ((usScratchP1_00 & 0x50) == 0x10)
++	   return 1;
++   else
++	   return 0;
+ }
+ 
+ static BOOLEAN XGIfbcheckvretracecrt1(void)
+@@ -968,24 +968,30 @@ static BOOLEAN XGIfbcheckvretracecrt1(void)
+    unsigned char temp;
+ 
+    inXGIIDXREG(XGICR,0x17,temp);
+-   if(!(temp & 0x80)) return FALSE;
++   if (!(temp & 0x80))
++	   return 0;
+ 
+ 
+    inXGIIDXREG(XGISR,0x1f,temp);
+-   if(temp & 0xc0) return FALSE;
+-
++   if (temp & 0xc0)
++	   return 0;
+ 
+-   if(inXGIREG(XGIINPSTAT) & 0x08) return TRUE;
+-   else 			   return FALSE;
++   if (inXGIREG(XGIINPSTAT) & 0x08)
++	   return 1;
++   else
++	   return 0;
+ }
+ 
+ static BOOLEAN XGIfbcheckvretracecrt2(void)
+ {
+    unsigned char temp;
+-   if(xgi_video_info.hasVB == HASVB_NONE) return FALSE;
++   if (xgi_video_info.hasVB == HASVB_NONE)
++	   return 0;
+    inXGIIDXREG(XGIPART1, 0x30, temp);
+-   if(temp & 0x02) return FALSE;
+-   else 	   return TRUE;
++   if (temp & 0x02)
++	   return 0;
++   else
++	   return 1;
+ }
+ 
+ static BOOLEAN XGIfb_CheckVBRetrace(void)
+@@ -1989,9 +1995,9 @@ static int XGIfb_has_VB(void)
+ 		break;
+ 	   default:
+ 		xgi_video_info.hasVB = HASVB_NONE;
+-		return FALSE;
++		return 0;
+ 	}
+-	return TRUE;
++	return 1;
+ }
+ 
+ 
+@@ -2645,7 +2651,7 @@ static void XGIfb_pre_setmode(void)
+ static void XGIfb_post_setmode(void)
+ {
+ 	u8 reg;
+-	BOOLEAN doit = TRUE;
++	BOOLEAN doit = 1;
+ #if 0	/* TW: Wrong: Is not in MMIO space, but in RAM */
+ 	/* Backup mode number to MMIO space */
+ 	if(xgi_video_info.mmio_vbase) {
+@@ -2659,11 +2665,11 @@ static void XGIfb_post_setmode(void)
+ 	if (xgi_video_info.video_bpp == 8) {
+ 		/* TW: We can't switch off CRT1 on LVDS/Chrontel in 8bpp Modes */
+ 		if ((xgi_video_info.hasVB == HASVB_LVDS) || (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL)) {
+-			doit = FALSE;
++			doit = 0;
+ 		}
+ 		/* TW: We can't switch off CRT1 on 301B-DH in 8bpp Modes if using LCD */
+ 		if  (xgi_video_info.disp_state & DISPTYPE_LCD)  {
+-	        	doit = FALSE;
++			doit = 0;
+ 	        }
+ 	}
+ 
+@@ -2672,14 +2678,15 @@ static void XGIfb_post_setmode(void)
+ 		inXGIIDXREG(XGIPART1, 0x00, reg);
+ 
+ 
+-		if((reg & 0x50) == 0x10) {
+-			doit = FALSE;
+-		}
++		if ((reg & 0x50) == 0x10)
++			doit = 0;
+ 
+-	} else XGIfb_crt1off = 0;
++
++	} else
++		XGIfb_crt1off = 0;
+ 
+ 	inXGIIDXREG(XGICR, 0x17, reg);
+-	if((XGIfb_crt1off) && (doit))
++	if ((XGIfb_crt1off) && (doit))
+ 		reg &= ~0x80;
+ 	else
+ 		reg |= 0x80;
+@@ -3027,7 +3034,7 @@ int __devinit xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 		   case XG20:
+ 		   case XG21:
+                    case XG27:
+-                   XGIhw_ext.bIntegratedMMEnabled = TRUE;
++			   XGIhw_ext.bIntegratedMMEnabled = 1;
+ 			break;
+ 
+ 		   default:
+@@ -3316,14 +3323,14 @@ int __devinit xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	          inXGIIDXREG(XGICR,0x38,tmp);
+ 		      if((tmp & 0x03) == 0x03)
+ 		      {
+-//		          XGI_Pr.XGI_UseLCDA = TRUE;
++/*		          XGI_Pr.XGI_UseLCDA = 1; */
+ 		      }else
+ 		      {
+ 		     //  Currently on LCDA? (Some newer BIOSes set D0 in CR35)
+ 		         inXGIIDXREG(XGICR,0x35,tmp);
+ 		         if(tmp & 0x01)
+ 		         {
+-//		              XGI_Pr.XGI_UseLCDA = TRUE;
++/*		              XGI_Pr.XGI_UseLCDA = 1; */
+ 		           }else
+ 		           {
+ 		               inXGIIDXREG(XGICR,0x30,tmp);
+@@ -3332,7 +3339,7 @@ int __devinit xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 		                   inXGIIDXREG(XGIPART1,0x13,tmp);
+ 			               if(tmp & 0x04)
+ 			               {
+-//			                XGI_Pr.XGI_UseLCDA = TRUE;
++/*			                XGI_Pr.XGI_UseLCDA = 1; */
+ 			               }
+ 		               }
+ 		           }
+diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
+index c5c7284ab679..da8f84fcf5e0 100644
+--- a/drivers/staging/xgifb/vb_init.c
++++ b/drivers/staging/xgifb/vb_init.c
+@@ -148,18 +148,16 @@ BOOLEAN XGIInitNew( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+ 
+ 
+    /* if ( pVBInfo->ROMAddr == 0 ) */
+-   /* return( FALSE ) ; */
++   /* return( 0 ) ; */
+ 
+-    if ( pVBInfo->FBAddr == 0 )
+-{
++    if (pVBInfo->FBAddr == 0) {
+        printk("\n pVBInfo->FBAddr == 0 ");
+-       return( FALSE ) ;
+-}
++       return 0;
++    }
+ printk("1");
+-    if ( pVBInfo->BaseAddr == 0 )
+-{
+-       printk("\npVBInfo->BaseAddr == 0 ");
+-        return( FALSE ) ;
++if (pVBInfo->BaseAddr == 0) {
++	printk("\npVBInfo->BaseAddr == 0 ");
++	return 0;
+ }
+ printk("2");
+ 
+@@ -169,9 +167,8 @@ printk("2");
+ printk("3");
+ 
+ if ( !HwDeviceExtension->bIntegratedMMEnabled )
+-{
+-        return( FALSE ) ;	/* alan */
+-}
++	return 0;	/* alan */
++
+ printk("4");
+ 
+  //   VBIOSVersion[ 4 ] = 0x0 ;
+@@ -422,15 +419,14 @@ printk("18");
+         XGINew_SetReg1( pVBInfo->P3d4 , 0x83 , 0x00 ) ;
+ printk("181");
+ 
+-    if ( HwDeviceExtension->bSkipSense == FALSE )
+-    {
+-printk("182");
++if (HwDeviceExtension->bSkipSense == 0) {
++	printk("182");
+ 
+         XGI_SenseCRT1(pVBInfo) ;
+ 
+-printk("183");
++	printk("183");
+         /* XGINew_DetectMonitor( HwDeviceExtension ) ; */
+-pVBInfo->IF_DEF_CH7007 = 0;
++	pVBInfo->IF_DEF_CH7007 = 0;
+         if ( ( HwDeviceExtension->jChipType == XG21 ) && (pVBInfo->IF_DEF_CH7007) )
+         {
+ printk("184");
+@@ -466,8 +462,7 @@ printk("19");
+ 
+         XGINew_SetDRAMDefaultRegister340( HwDeviceExtension ,  pVBInfo->P3d4,  pVBInfo ) ;
+ 
+-        if ( HwDeviceExtension->bSkipDramSizing == TRUE )
+-        {
++	if (HwDeviceExtension->bSkipDramSizing == 1) {
+             pSR = HwDeviceExtension->pSR ;
+             if ( pSR!=NULL )
+             {
+@@ -547,7 +542,7 @@ XGINew_SetReg1( pVBInfo->P3d4 , 0x8c , 0x87);
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x31);
+ printk("25");
+ 
+-    return( TRUE ) ;
++return 1;
+ } /* end of init */
+ 
+ 
+@@ -2608,10 +2603,10 @@ void XGINew_SetMemoryClock( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_IN
+ /* --------------------------------------------------------------------- */
+ BOOLEAN ChkLFB( PVB_DEVICE_INFO pVBInfo )
+ {
+-    if ( LFBDRAMTrap & XGINew_GetReg1( pVBInfo->P3d4 , 0x78 ) )
+-        return( TRUE ) ;
+-    else
+-        return( FALSE );
++	if (LFBDRAMTrap & XGINew_GetReg1(pVBInfo->P3d4 , 0x78))
++		return 1;
++	else
++		return 0;
+ }
+ 
+ 
+diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c
+index dc4e186f987e..a0ccce07f125 100644
+--- a/drivers/staging/xgifb/vb_setmode.c
++++ b/drivers/staging/xgifb/vb_setmode.c
+@@ -510,15 +510,9 @@ BOOLEAN XGISetModeNew( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo )
+     }	/* !XG20 */
+     else
+     {
+-
+-
+-        if ( pVBInfo->IF_DEF_LVDS == 1 )
+-        {
+-            if ( !XGI_XG21CheckLVDSMode(ModeNo , ModeIdIndex, pVBInfo) )
+-            {
+-              return FALSE;
+-            }
+-        }
++	    if (pVBInfo->IF_DEF_LVDS == 1)
++		    if (!XGI_XG21CheckLVDSMode(ModeNo , ModeIdIndex, pVBInfo))
++			    return 0;
+ 
+         if ( ModeNo <= 0x13 )
+         {
+@@ -577,7 +571,7 @@ BOOLEAN XGISetModeNew( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo )
+     XGI_LockCRT2( HwDeviceExtension, pVBInfo ) ;
+ }
+ 
+-    return( TRUE ) ;
++    return 1;
+ }
+ 
+ 
+@@ -3987,10 +3981,10 @@ BOOLEAN XGI_SearchModeID( USHORT ModeNo , USHORT *ModeIdIndex, PVB_DEVICE_INFO p
+         /* for (*ModeIdIndex=0;*ModeIdIndexSModeIDTable)/sizeof(XGI_StStruct);(*ModeIdIndex)++) */
+         for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ )
+         {
+-            if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == ModeNo )
+-                break ;
+-            if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == 0xFF )
+-                return( FALSE ) ;
++		if (pVBInfo->SModeIDTable[*ModeIdIndex].St_ModeID == ModeNo)
++			break;
++		if (pVBInfo->SModeIDTable[*ModeIdIndex].St_ModeID == 0xFF)
++			return 0;
+         }
+ 
+         if ( ModeNo == 0x07 )
+@@ -4005,16 +3999,16 @@ BOOLEAN XGI_SearchModeID( USHORT ModeNo , USHORT *ModeIdIndex, PVB_DEVICE_INFO p
+         /* for (*ModeIdIndex=0;*ModeIdIndexEModeIDTable)/sizeof(XGI_ExtStruct);(*ModeIdIndex)++) */
+         for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ )
+         {
+-            if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == ModeNo )
+-                break ;
+-            if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == 0xFF )
+-                return( FALSE ) ;
++		if (pVBInfo->EModeIDTable[*ModeIdIndex].Ext_ModeID == ModeNo)
++			break;
++		if (pVBInfo->EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF)
++			return 0;
+         }
+     }
+ 
+ #endif
+ 
+-    return( TRUE ) ;
++    return 1;
+ }
+ 
+ 
+@@ -4039,7 +4033,7 @@ BOOLEAN XGINew_CheckMemorySize(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT Mode
+ /*  if ( ( HwDeviceExtension->jChipType == XGI_650 ) ||
+          ( HwDeviceExtension->jChipType == XGI_650M ) )
+     {
+-        return( TRUE ) ;
++	return 1;
+     } */
+ 
+     if ( ModeNo <= 0x13 )
+@@ -4097,10 +4091,10 @@ BOOLEAN XGINew_CheckMemorySize(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT Mode
+             temp <<= 1 ;
+         }
+     }
+-    if ( temp < memorysize )
+-        return( FALSE ) ;
++    if (temp < memorysize)
++	    return 0;
+     else
+-        return( TRUE ) ;
++	    return 1;
+ }
+ 
+ 
+@@ -7736,7 +7730,7 @@ void* XGI_GetTVPtr (USHORT BX,USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRat
+ /* --------------------------------------------------------------------- */
+ /* Function : XGI_BacklightByDrv */
+ /* Input : */
+-/* Output : TRUE -> Skip backlight control */
++/* Output : 1 -> Skip backlight control */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ BOOLEAN XGI_BacklightByDrv( PVB_DEVICE_INFO pVBInfo )
+@@ -7744,10 +7738,10 @@ BOOLEAN XGI_BacklightByDrv( PVB_DEVICE_INFO pVBInfo )
+     UCHAR tempah ;
+ 
+     tempah = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x3A ) ;
+-    if ( tempah & BacklightControlBit )
+-        return TRUE ;
++    if (tempah & BacklightControlBit)
++	    return 1;
+     else
+-        return FALSE ;
++	    return 0;
+ }
+ 
+ 
+@@ -8055,10 +8049,10 @@ BOOLEAN XGI_XG21CheckLVDSMode(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO
+ 
+     lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo );
+     if ( xres > (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE) )
+-      return FALSE;
++	    return 0;
+ 
+     if ( yres > (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE) )
+-      return FALSE;
++	    return 0;
+ 
+     if ( ModeNo > 0x13 )
+     {
+@@ -8066,13 +8060,12 @@ BOOLEAN XGI_XG21CheckLVDSMode(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO
+            ( yres != (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE)) )
+       {
+           colordepth = XGI_GetColorDepth( ModeNo , ModeIdIndex, pVBInfo ) ;
+-          if ( colordepth > 2 )
+-          {
+-            return FALSE;
+-          }
++	  if (colordepth > 2)
++		  return 0;
++
+       }
+     }
+-    return TRUE;
++    return 1;
+ }
+ 
+ void XGI_SetXG21FPBits(PVB_DEVICE_INFO pVBInfo)
+@@ -8463,8 +8456,8 @@ void XGI_SetXG27LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBIn
+ /* --------------------------------------------------------------------- */
+ /* Function : XGI_IsLCDON */
+ /* Input : */
+-/* Output : FALSE : Skip PSC Control */
+-/* TRUE: Disable PSC */
++/* Output : 0 : Skip PSC Control */
++/* 1: Disable PSC */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ BOOLEAN XGI_IsLCDON(PVB_DEVICE_INFO pVBInfo)
+@@ -8473,11 +8466,11 @@ BOOLEAN XGI_IsLCDON(PVB_DEVICE_INFO pVBInfo)
+ 
+     tempax = pVBInfo->VBInfo ;
+     if ( tempax & SetCRT2ToDualEdge )
+-        return FALSE ;
++	    return 0;
+     else if ( tempax & ( DisableCRT2Display | SwitchToCRT2 | SetSimuScanMode ) )
+-        return TRUE ;
++	    return 1;
+ 
+-    return FALSE ;
++    return 0;
+ }
+ 
+ 
+@@ -8518,7 +8511,7 @@ void XGI_DisablePWD( PVB_DEVICE_INFO pVBInfo )
+ /* --------------------------------------------------------------------- */
+ /* Function : XGI_DisableChISLCD */
+ /* Input : */
+-/* Output : FALSE -> Not LCD Mode */
++/* Output : 0 -> Not LCD Mode */
+ /* Description : */
+ /* --------------------------------------------------------------------- */
+ BOOLEAN XGI_DisableChISLCD(PVB_DEVICE_INFO pVBInfo)
+@@ -8532,16 +8525,16 @@ BOOLEAN XGI_DisableChISLCD(PVB_DEVICE_INFO pVBInfo)
+     if ( tempbx & ( EnableChA | DisableChA ) )
+     {
+         if ( !( tempah & 0x08 ) )		/* Chk LCDA Mode */
+-            return FALSE ;
++		return 0 ;
+     }
+ 
+     if ( !( tempbx & ( EnableChB | DisableChB ) ) )
+-        return FALSE ;
++	    return 0;
+ 
+     if ( tempah & 0x01 )       /* Chk LCDB Mode */
+-        return TRUE ;
++	    return 1;
+ 
+-    return FALSE ;
++    return 0;
+ }
+ 
+ 
+@@ -8563,16 +8556,16 @@ BOOLEAN XGI_EnableChISLCD(PVB_DEVICE_INFO pVBInfo)
+     if ( tempbx & ( EnableChA | DisableChA ) )
+     {
+         if ( !( tempah & 0x08 ) )		/* Chk LCDA Mode */
+-            return FALSE ;
++		return 0;
+     }
+ 
+     if ( !( tempbx & ( EnableChB | DisableChB ) ) )
+-        return FALSE ;
++	    return 0;
+ 
+     if ( tempah & 0x01 )       /* Chk LCDB Mode */
+-        return TRUE ;
++	    return 1;
+ 
+-    return FALSE ;
++    return 0;
+ }
+ 
+ 
+diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h
+index 83fea8e37a30..c1c798562ddd 100644
+--- a/drivers/staging/xgifb/vgatypes.h
++++ b/drivers/staging/xgifb/vgatypes.h
+@@ -4,18 +4,6 @@
+ 
+ #include 
+ 
+-#ifndef FALSE
+-#define FALSE   0
+-#endif
+-
+-#ifndef TRUE
+-#define TRUE    1
+-#endif
+-
+-#ifndef NULL
+-#define NULL    0
+-#endif
+-
+ #ifndef CHAR
+ typedef char CHAR;
+ #endif
+@@ -186,12 +174,12 @@ struct _XGI_HW_DEVICE_INFO
+     PXGI_DSReg  pSR;             /* restore SR registers in initial function. */
+                                  /* end data :(idx, val) =  (FF, FF). */
+                                  /* Note : restore SR registers if  */
+-                                 /* bSkipDramSizing = TRUE */
++                                 /* bSkipDramSizing = 1 */
+ 
+     PXGI_DSReg  pCR;             /* restore CR registers in initial function. */
+                                  /* end data :(idx, val) =  (FF, FF) */
+                                  /* Note : restore cR registers if  */
+-                                 /* bSkipDramSizing = TRUE */
++                                 /* bSkipDramSizing = 1 */
+ /*
+ #endif
+ */

commit 1e59f7119f0a998e3d453614b3d074962b84bc83
+Author: Bill Pemberton 
+Date:   Thu Jun 17 13:10:41 2010 -0400
+
+    Staging: xgifb: Remove port macros in osdef.h
+    
+    The port related macros in osdef.h are replaced with calls to out?()
+    and in?().  This removes the last macros defined in osdef.h, so this
+    file is no longer needed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Arnaud Patard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/XGI_accel.c b/drivers/staging/xgifb/XGI_accel.c
+index 24f454d93772..85af55c32091 100644
+--- a/drivers/staging/xgifb/XGI_accel.c
++++ b/drivers/staging/xgifb/XGI_accel.c
+@@ -43,7 +43,6 @@
+ #include 
+ #endif
+ 
+-#include "osdef.h"
+ #include "vgatypes.h"
+ #include "vb_struct.h"
+ #include "XGIfb.h"
+diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
+index e9551d347a88..c7ad6cdffff9 100644
+--- a/drivers/staging/xgifb/XGI_main_26.c
++++ b/drivers/staging/xgifb/XGI_main_26.c
+@@ -29,8 +29,6 @@
+ #include 
+ #include 
+ 
+-#include "osdef.h"
+-
+ 
+ #ifndef XGIFB_PAN
+ #define XGIFB_PAN
+diff --git a/drivers/staging/xgifb/osdef.h b/drivers/staging/xgifb/osdef.h
+deleted file mode 100644
+index 7d05ea47c72f..000000000000
+--- a/drivers/staging/xgifb/osdef.h
++++ /dev/null
+@@ -1,37 +0,0 @@
+-#ifndef _OSDEF_H_
+-#define _OSDEF_H_
+-
+-/**********************************************************************/
+-
+-#ifdef OutPortByte
+-#undef OutPortByte
+-#endif /* OutPortByte */
+-
+-#ifdef OutPortWord
+-#undef OutPortWord
+-#endif /* OutPortWord */
+-
+-#ifdef OutPortLong
+-#undef OutPortLong
+-#endif /* OutPortLong */
+-
+-#ifdef InPortByte
+-#undef InPortByte
+-#endif /* InPortByte */
+-
+-#ifdef InPortWord
+-#undef InPortWord
+-#endif /* InPortWord */
+-
+-#ifdef InPortLong
+-#undef InPortLong
+-#endif /* InPortLong */
+-
+-#define OutPortByte(p,v) outb((u8)(v),(p))
+-#define OutPortWord(p,v) outw((u16)(v),(p))
+-#define OutPortLong(p,v) outl((u32)(v),(p))
+-#define InPortByte(p)    inb(p)
+-#define InPortWord(p)    inw(p)
+-#define InPortLong(p)    inl(p)
+-
+-#endif // _OSDEF_H_
+diff --git a/drivers/staging/xgifb/vb_ext.c b/drivers/staging/xgifb/vb_ext.c
+index f4969c2ced61..4358d96bad7e 100644
+--- a/drivers/staging/xgifb/vb_ext.c
++++ b/drivers/staging/xgifb/vb_ext.c
+@@ -1,5 +1,3 @@
+-#include "osdef.h"
+-
+ #include 
+ #include 
+ #include 
+diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
+index dc1218463ea0..c5c7284ab679 100644
+--- a/drivers/staging/xgifb/vb_init.c
++++ b/drivers/staging/xgifb/vb_init.c
+@@ -1,4 +1,3 @@
+-#include "osdef.h"
+ #include "vgatypes.h"
+ 
+ #include 
+diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c
+index 95efa8bb0de0..dc4e186f987e 100644
+--- a/drivers/staging/xgifb/vb_setmode.c
++++ b/drivers/staging/xgifb/vb_setmode.c
+@@ -1,7 +1,3 @@
+-#include "osdef.h"
+-
+-
+-
+ 
+ #include 
+ #include 
+diff --git a/drivers/staging/xgifb/vb_util.c b/drivers/staging/xgifb/vb_util.c
+index 753b1c550727..f83aee7ea90e 100644
+--- a/drivers/staging/xgifb/vb_util.c
++++ b/drivers/staging/xgifb/vb_util.c
+@@ -1,4 +1,3 @@
+-#include "osdef.h"
+ #include "vb_def.h"
+ #include "vgatypes.h"
+ #include "vb_struct.h"
+@@ -28,8 +27,8 @@ void     XGINew_SetRegAND(ULONG Port,USHORT Index,USHORT DataAND);
+ /* --------------------------------------------------------------------- */
+ void XGINew_SetReg1( ULONG port , USHORT index , USHORT data )
+ {
+-    OutPortByte( port , index ) ;
+-    OutPortByte( port + 1 , data ) ;
++	outb(index, port);
++	outb(data, port + 1);
+ }
+ 
+ 
+@@ -56,7 +55,7 @@ void XGINew_SetReg1( ULONG port , USHORT index , USHORT data )
+ /* --------------------------------------------------------------------- */
+ void XGINew_SetReg3( ULONG port , USHORT data )
+ {
+-    OutPortByte( port , data ) ;
++	outb(data, port);
+ }
+ 
+ 
+@@ -68,7 +67,7 @@ void XGINew_SetReg3( ULONG port , USHORT data )
+ /* --------------------------------------------------------------------- */
+ void XGINew_SetReg4( ULONG port , ULONG data )
+ {
+-    OutPortLong( port , data ) ;
++	outl(data, port);
+ }
+ 
+ 
+@@ -82,9 +81,8 @@ UCHAR XGINew_GetReg1( ULONG port , USHORT index )
+ {
+     UCHAR data ;
+ 
+-    OutPortByte( port , index ) ;
+-    data = InPortByte( port + 1 ) ;
+-
++    outb(index, port);
++    data = inb(port + 1) ;
+     return( data ) ;
+ }
+ 
+@@ -99,7 +97,7 @@ UCHAR XGINew_GetReg2( ULONG port )
+ {
+     UCHAR data ;
+ 
+-    data = InPortByte( port ) ;
++    data = inb(port) ;
+ 
+     return( data ) ;
+ }
+@@ -115,7 +113,7 @@ ULONG XGINew_GetReg3( ULONG port )
+ {
+     ULONG data ;
+ 
+-    data = InPortLong( port ) ;
++    data = inl(port) ;
+ 
+     return( data ) ;
+ }
+diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h
+index 745c993e057e..83fea8e37a30 100644
+--- a/drivers/staging/xgifb/vgatypes.h
++++ b/drivers/staging/xgifb/vgatypes.h
+@@ -2,8 +2,6 @@
+ #ifndef _VGATYPES_
+ #define _VGATYPES_
+ 
+-#include "osdef.h"
+-
+ #include 
+ 
+ #ifndef FALSE

commit cc75bb02db530748515f0bf95039c4a15b3ef0be
+Author: Bill Pemberton 
+Date:   Thu Jun 17 13:10:40 2010 -0400
+
+    Staging: xgifb: Remove XGI_SetMemory and XGI_MemoryCopy
+    
+    These were just macros for memset and memcpy, so use those instead.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Arnaud Patard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/osdef.h b/drivers/staging/xgifb/osdef.h
+index fb1d41149caa..7d05ea47c72f 100644
+--- a/drivers/staging/xgifb/osdef.h
++++ b/drivers/staging/xgifb/osdef.h
+@@ -1,10 +1,6 @@
+ #ifndef _OSDEF_H_
+ #define _OSDEF_H_
+ 
+-#define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
+-
+-#define XGI_MemoryCopy(Destination,Soruce,Length) memcpy(Destination,Soruce,Length)
+-
+ /**********************************************************************/
+ 
+ #ifdef OutPortByte
+diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
+index 94fa48b9f9f5..dc1218463ea0 100644
+--- a/drivers/staging/xgifb/vb_init.c
++++ b/drivers/staging/xgifb/vb_init.c
+@@ -175,8 +175,6 @@ if ( !HwDeviceExtension->bIntegratedMMEnabled )
+ }
+ printk("4");
+ 
+-//    XGI_MemoryCopy( VBIOSVersion , HwDeviceExtension->szVBIOSVer , 4 ) ;
+-
+  //   VBIOSVersion[ 4 ] = 0x0 ;
+ 
+     /* 09/07/99 modify by domao */
+diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c
+index daf7b3c739c0..95efa8bb0de0 100644
+--- a/drivers/staging/xgifb/vb_setmode.c
++++ b/drivers/staging/xgifb/vb_setmode.c
+@@ -2609,7 +2609,7 @@ void XGI_ClearBuffer( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo, PVB
+         {
+             AdapterMemorySize = 0x40000 ;	/* clear 256k */
+             /* GetDRAMSize( HwDeviceExtension ) ; */
+-            XGI_SetMemory( VideoMemoryAddress , AdapterMemorySize , 0 ) ;
++	    memset(VideoMemoryAddress, 0, AdapterMemorySize);
+         }
+         else
+         {
+@@ -2631,7 +2631,7 @@ void XGI_ClearBuffer( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo, PVB
+ */
+         }
+         else
+-            XGI_SetMemory( VideoMemoryAddress , 0x8000 , 0 ) ;
++		memset(VideoMemoryAddress , 0, 0x8000);
+     }
+ }
+ 

commit f2f58e14efe5d1de1003a05fbdb82a66fc22dfb8
+Author: Bill Pemberton 
+Date:   Thu Jun 17 13:10:39 2010 -0400
+
+    Staging: xgifb: Remove use of LINUX_KERNEL define
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Arnaud Patard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
+index f2658c41b7d6..e9551d347a88 100644
+--- a/drivers/staging/xgifb/XGI_main_26.c
++++ b/drivers/staging/xgifb/XGI_main_26.c
+@@ -163,7 +163,6 @@ struct video_info  xgi_video_info;
+ 
+ /* --------------- Hardware Access Routines -------------------------- */
+ 
+-#ifdef LINUX_KERNEL
+ int
+ XGIfb_mode_rate_to_dclock(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ 			  unsigned char modeno, unsigned char rateindex)
+@@ -389,7 +388,6 @@ XGIfb_mode_rate_to_ddata(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExt
+     return 1;
+ }
+ 
+-#endif
+ 
+ 
+ 
+diff --git a/drivers/staging/xgifb/osdef.h b/drivers/staging/xgifb/osdef.h
+index ffb683819e41..fb1d41149caa 100644
+--- a/drivers/staging/xgifb/osdef.h
++++ b/drivers/staging/xgifb/osdef.h
+@@ -1,30 +1,9 @@
+ #ifndef _OSDEF_H_
+ #define _OSDEF_H_
+ 
+-#define LINUX_KERNEL
+-
+-/**********************************************************************/
+-#ifdef LINUX_KERNEL
+-//#include 
+-#endif
+-
+-
+-/**********************************************************************/
+-#ifdef LINUX_KERNEL
+-#define LINUX
+-#endif
+-
+-/**********************************************************************/
+-#ifdef LINUX_KERNEL
+ #define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
+-#endif
+-/**********************************************************************/
+-
+-/**********************************************************************/
+ 
+-#ifdef LINUX_KERNEL
+ #define XGI_MemoryCopy(Destination,Soruce,Length) memcpy(Destination,Soruce,Length)
+-#endif
+ 
+ /**********************************************************************/
+ 
+@@ -52,33 +31,11 @@
+ #undef InPortLong
+ #endif /* InPortLong */
+ 
+-/**********************************************************************/
+-/*  TC                                                                */
+-/**********************************************************************/
+-
+-
+-/**********************************************************************/
+-/*  LINUX XF86                                                        */
+-/**********************************************************************/
+-
+-
+-#ifdef LINUX_KERNEL
+ #define OutPortByte(p,v) outb((u8)(v),(p))
+ #define OutPortWord(p,v) outw((u16)(v),(p))
+ #define OutPortLong(p,v) outl((u32)(v),(p))
+ #define InPortByte(p)    inb(p)
+ #define InPortWord(p)    inw(p)
+ #define InPortLong(p)    inl(p)
+-#endif
+-
+-/**********************************************************************/
+-/*  WIN 2000                                                          */
+-/**********************************************************************/
+-
+-
+-
+-/**********************************************************************/
+-/*  WIN CE                                                          */
+-/**********************************************************************/
+ 
+ #endif // _OSDEF_H_
+diff --git a/drivers/staging/xgifb/vb_def.h b/drivers/staging/xgifb/vb_def.h
+index 17a7ada4926e..4de182b23d41 100644
+--- a/drivers/staging/xgifb/vb_def.h
++++ b/drivers/staging/xgifb/vb_def.h
+@@ -6,7 +6,7 @@
+ #define NewScratch
+ #endif
+ /* shampoo */
+-#ifdef LINUX_KERNEL
++
+ #define SEQ_ADDRESS_PORT	  0x0014
+ #define SEQ_DATA_PORT		  0x0015
+ #define MISC_OUTPUT_REG_READ_PORT 0x001C
+@@ -17,7 +17,7 @@
+ #define CRTC_ADDRESS_PORT_COLOR   0x0024
+ #define VIDEO_SUBSYSTEM_ENABLE_PORT 0x0013
+ #define PCI_COMMAND		0x04
+-#endif
++
+ /* ~shampoo */
+ 
+ 
+diff --git a/drivers/staging/xgifb/vb_ext.c b/drivers/staging/xgifb/vb_ext.c
+index 683558513799..f4969c2ced61 100644
+--- a/drivers/staging/xgifb/vb_ext.c
++++ b/drivers/staging/xgifb/vb_ext.c
+@@ -1,18 +1,9 @@
+ #include "osdef.h"
+ 
+-
+-
+-
+-
+-
+-#ifdef LINUX_KERNEL
+ #include 
+ #include 
+ #include 
+ #include "XGIfb.h"
+-#endif
+-
+-
+ 
+ #include "vb_def.h"
+ #include "vgatypes.h"
+diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
+index d3201d2470f1..94fa48b9f9f5 100644
+--- a/drivers/staging/xgifb/vb_init.c
++++ b/drivers/staging/xgifb/vb_init.c
+@@ -1,19 +1,10 @@
+ #include "osdef.h"
+ #include "vgatypes.h"
+ 
+-
+-#ifdef LINUX_KERNEL
+ #include 
+ #include 
+ #include  /* udelay */
+ #include "XGIfb.h"
+-/*#if LINUX_VERSxION_CODE >= KERNEL_VERSION(2,5,0)
+-#include 

commit 84c7603c3888da8ee69802ad4f4647f94d18e2c5
+Author: Bill Pemberton 
+Date:   Thu Jun 17 13:10:38 2010 -0400
+
+    Staging: xgifb: Remove use of LINUX_XF86 define
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Arnaud Patard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/osdef.h b/drivers/staging/xgifb/osdef.h
+index 01a87202b76f..ffb683819e41 100644
+--- a/drivers/staging/xgifb/osdef.h
++++ b/drivers/staging/xgifb/osdef.h
+@@ -2,7 +2,6 @@
+ #define _OSDEF_H_
+ 
+ #define LINUX_KERNEL
+-/* #define LINUX_XF86 */
+ 
+ /**********************************************************************/
+ #ifdef LINUX_KERNEL
+@@ -11,17 +10,11 @@
+ 
+ 
+ /**********************************************************************/
+-#ifdef LINUX_XF86
+-#define LINUX
+-#endif
+ #ifdef LINUX_KERNEL
+ #define LINUX
+ #endif
+ 
+ /**********************************************************************/
+-#ifdef LINUX_XF86
+-#define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
+-#endif
+ #ifdef LINUX_KERNEL
+ #define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
+ #endif
+@@ -29,9 +22,6 @@
+ 
+ /**********************************************************************/
+ 
+-#ifdef LINUX_XF86
+-#define XGI_MemoryCopy(Destination,Soruce,Length) memcpy(Destination,Soruce,Length)
+-#endif
+ #ifdef LINUX_KERNEL
+ #define XGI_MemoryCopy(Destination,Soruce,Length) memcpy(Destination,Soruce,Length)
+ #endif
+@@ -71,14 +61,6 @@
+ /*  LINUX XF86                                                        */
+ /**********************************************************************/
+ 
+-#ifdef LINUX_XF86
+-#define OutPortByte(p,v) outb((CARD16)(p),(CARD8)(v))
+-#define OutPortWord(p,v) outw((CARD16)(p),(CARD16)(v))
+-#define OutPortLong(p,v) outl((CARD16)(p),(CARD32)(v))
+-#define InPortByte(p)    inb((CARD16)(p))
+-#define InPortWord(p)    inw((CARD16)(p))
+-#define InPortLong(p)    inl((CARD16)(p))
+-#endif
+ 
+ #ifdef LINUX_KERNEL
+ #define OutPortByte(p,v) outb((u8)(v),(p))
+diff --git a/drivers/staging/xgifb/vb_ext.c b/drivers/staging/xgifb/vb_ext.c
+index 7a96dad686c6..683558513799 100644
+--- a/drivers/staging/xgifb/vb_ext.c
++++ b/drivers/staging/xgifb/vb_ext.c
+@@ -4,12 +4,6 @@
+ 
+ 
+ 
+-#ifdef LINUX_XF86
+-#include "xf86.h"
+-#include "xf86PciInfo.h"
+-#include "xgi.h"
+-#include "xgi_regs.h"
+-#endif
+ 
+ #ifdef LINUX_KERNEL
+ #include 
+diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
+index dfa047338513..d3201d2470f1 100644
+--- a/drivers/staging/xgifb/vb_init.c
++++ b/drivers/staging/xgifb/vb_init.c
+@@ -22,12 +22,6 @@
+ #include "vb_init.h"
+ #include "vb_ext.h"
+ 
+-#ifdef LINUX_XF86
+-#include "xf86.h"
+-#include "xf86PciInfo.h"
+-#include "xgi.h"
+-#include "xgi_regs.h"
+-#endif
+ 
+ #ifdef LINUX_KERNEL
+ #include 
+@@ -2674,7 +2668,7 @@ void SetPowerConsume ( PXGI_HW_DEVICE_INFO HwDeviceExtension , ULONG XGI_P3d4Por
+ 
+ 
+ 
+-#if defined(LINUX_XF86)||defined(LINUX_KERNEL)
++#if defined(LINUX_KERNEL)
+ void XGINew_InitVBIOSData(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+ {
+ 
+@@ -3103,9 +3097,8 @@ void XGINew_SetDRAMModeRegister_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+ /*
+ void XGINew_SetDRAMModeRegister_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+ {
+-#ifndef LINUX_XF86
++
+     UCHAR data ;
+-#endif
+     VB_DEVICE_INFO VBINF;
+     PVB_DEVICE_INFO pVBInfo = &VBINF;
+     pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c
+index 9f5ce8c98c1e..5078788f48d0 100644
+--- a/drivers/staging/xgifb/vb_setmode.c
++++ b/drivers/staging/xgifb/vb_setmode.c
+@@ -2,12 +2,6 @@
+ 
+ 
+ 
+-#ifdef LINUX_XF86
+-#include "xf86.h"
+-#include "xf86PciInfo.h"
+-#include "xgi.h"
+-#include "xgi_regs.h"
+-#endif
+ 
+ #ifdef LINUX_KERNEL
+ #include 
+@@ -2609,9 +2603,7 @@ void XGI_ClearBuffer( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo, PVB
+     PVOID VideoMemoryAddress = ( PVOID )HwDeviceExtension->pjVideoMemoryAddress ;
+     ULONG AdapterMemorySize  = ( ULONG )HwDeviceExtension->ulVideoMemorySize ;
+     PUSHORT pBuffer ;
+-#ifndef LINUX_XF86
+     int i ;
+-#endif
+ 
+     if ( pVBInfo->ModeType >= ModeEGA )
+     {
+@@ -4901,10 +4893,7 @@ UCHAR XGI_GetVCLKPtr(USHORT RefreshRateTableIndex,USHORT ModeNo,USHORT ModeIdInd
+ 
+     USHORT index ,
+            modeflag ;
+-#ifndef LINUX_XF86
+     USHORT tempbx ;
+-#endif
+-
+     UCHAR tempal ;
+     UCHAR *CHTVVCLKPtr = NULL ;
+ 
+diff --git a/drivers/staging/xgifb/vb_util.c b/drivers/staging/xgifb/vb_util.c
+index 4c8ec25211f2..b9ccce070738 100644
+--- a/drivers/staging/xgifb/vb_util.c
++++ b/drivers/staging/xgifb/vb_util.c
+@@ -9,18 +9,6 @@
+ #include 
+ #endif
+ 
+-
+-
+-#ifdef LINUX_XF86
+-#include "xf86.h"
+-#include "xf86PciInfo.h"
+-#include "xgi.h"
+-#include "xgi_regs.h"
+-#endif
+-
+-
+-
+-
+ void XGINew_SetReg1( ULONG , USHORT , USHORT ) ;
+ void XGINew_SetReg2( ULONG , USHORT , USHORT ) ;
+ void XGINew_SetReg3( ULONG , USHORT ) ;
+@@ -42,13 +30,8 @@ void     XGINew_SetRegAND(ULONG Port,USHORT Index,USHORT DataAND);
+ /* --------------------------------------------------------------------- */
+ void XGINew_SetReg1( ULONG port , USHORT index , USHORT data )
+ {
+-#ifdef LINUX_XF86
+-    OutPortByte( ( PUCHAR )(ULONG)port , index ) ;
+-    OutPortByte( ( PUCHAR )(ULONG)port + 1 , data ) ;
+-#else
+     OutPortByte( port , index ) ;
+     OutPortByte( port + 1 , data ) ;
+-#endif
+ }
+ 
+ 
+@@ -101,13 +84,8 @@ UCHAR XGINew_GetReg1( ULONG port , USHORT index )
+ {
+     UCHAR data ;
+ 
+-#ifdef LINUX_XF86
+-    OutPortByte( ( PUCHAR )(ULONG)port , index ) ;
+-    data = InPortByte( ( PUCHAR )(ULONG)port + 1 ) ;
+-#else
+     OutPortByte( port , index ) ;
+     data = InPortByte( port + 1 ) ;
+-#endif
+ 
+     return( data ) ;
+ }
+diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h
+index 5a09c942203b..256ef26c2789 100644
+--- a/drivers/staging/xgifb/vgatypes.h
++++ b/drivers/staging/xgifb/vgatypes.h
+@@ -4,10 +4,6 @@
+ 
+ #include "osdef.h"
+ 
+-#ifdef LINUX_XF86
+-#include "xf86Version.h"
+-#include "xf86Pci.h"
+-#endif
+ 
+ #ifdef LINUX_KERNEL  /* We don't want the X driver to depend on kernel source */
+ #include 
+@@ -81,14 +77,6 @@ typedef UCHAR bool;
+ typedef unsigned long XGIIOADDRESS;
+ #endif
+ 
+-#ifdef LINUX_XF86
+-#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,0,0,0)
+-typedef unsigned char IOADDRESS;
+-typedef unsigned char XGIIOADDRESS;
+-#else
+-typedef IOADDRESS XGIIOADDRESS;
+-#endif
+-#endif
+ 
+ #ifndef VBIOS_VER_MAX_LENGTH
+ #define VBIOS_VER_MAX_LENGTH    4
+@@ -98,10 +86,6 @@ typedef IOADDRESS XGIIOADDRESS;
+ #ifndef XGI_CHIP_TYPE
+ typedef enum _XGI_CHIP_TYPE {
+     XGI_VGALegacy = 0,
+-#ifdef LINUX_XF86
+-    XGI_530,
+-    XGI_OLD,
+-#endif
+     XGI_300,
+     XGI_630,
+     XGI_640,
+@@ -190,9 +174,6 @@ struct _XGI_HW_DEVICE_INFO
+ {
+     ULONG  ulExternalChip;       /* NO VB or other video bridge*/
+                                  /* if ujVBChipID = VB_CHIP_UNKNOWN, */
+-#ifdef LINUX_XF86
+-    PCITAG PciTag;		 /* PCI Tag */
+-#endif
+ 
+     PUCHAR  pjVirtualRomBase;    /* ROM image */
+ 
+@@ -264,55 +245,6 @@ struct _XGI_HW_DEVICE_INFO
+ /* Addtional IOCTL for communication xgifb <> X driver        */
+ /* If changing this, xgifb.h must also be changed (for xgifb) */
+ 
+-#ifdef LINUX_XF86  /* We don't want the X driver to depend on the kernel source */
+-
+-/* ioctl for identifying and giving some info (esp. memory heap start) */
+-#define XGIFB_GET_INFO    0x80046ef8  /* Wow, what a terrible hack... */
+-
+-/* Structure argument for XGIFB_GET_INFO ioctl  */
+-typedef struct _XGIFB_INFO xgifb_info, *pxgifb_info;
+-
+-struct _XGIFB_INFO {
+-	CARD32 	xgifb_id;         	/* for identifying xgifb */
+-#ifndef XGIFB_ID
+-#define XGIFB_ID	  0x53495346    /* Identify myself with 'XGIF' */
+-#endif
+- 	CARD32 	chip_id;		/* PCI ID of detected chip */
+-	CARD32	memory;			/* video memory in KB which xgifb manages */
+-	CARD32	heapstart;             	/* heap start (= xgifb "mem" argument) in KB */
+-	CARD8 	fbvidmode;		/* current xgifb mode */
+-
+-	CARD8 	xgifb_version;
+-	CARD8	xgifb_revision;
+-	CARD8 	xgifb_patchlevel;
+-
+-	CARD8 	xgifb_caps;		/* xgifb's capabilities */
+-
+-	CARD32 	xgifb_tqlen;		/* turbo queue length (in KB) */
+-
+-	CARD32 	xgifb_pcibus;      	/* The card's PCI ID */
+-	CARD32 	xgifb_pcislot;
+-	CARD32 	xgifb_pcifunc;
+-
+-	CARD8 	xgifb_lcdpdc;
+-
+-	CARD8	xgifb_lcda;
+-
+-	CARD32	xgifb_vbflags;
+-	CARD32	xgifb_currentvbflags;
+-
+-	CARD32 	xgifb_scalelcd;
+-	CARD32 	xgifb_specialtiming;
+-
+-	CARD8 	xgifb_haveemi;
+-	CARD8 	xgifb_emi30,xgifb_emi31,xgifb_emi32,xgifb_emi33;
+-	CARD8 	xgifb_haveemilcd;
+-
+-	CARD8 	xgifb_lcdpdca;
+-
+-	CARD8 reserved[212]; 		/* for future use */
+-};
+-#endif
+ 
+ #endif
+ 

commit 784cfe1d07259ba7faaa4f64a8d59c56d7a55641
+Author: Bill Pemberton 
+Date:   Thu Jun 17 13:10:37 2010 -0400
+
+    Staging: xgifb: Remove use of TC define
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Arnaud Patard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/osdef.h b/drivers/staging/xgifb/osdef.h
+index 83fffe181ef9..01a87202b76f 100644
+--- a/drivers/staging/xgifb/osdef.h
++++ b/drivers/staging/xgifb/osdef.h
+@@ -1,7 +1,6 @@
+ #ifndef _OSDEF_H_
+ #define _OSDEF_H_
+ 
+-/* #define TC */
+ #define LINUX_KERNEL
+ /* #define LINUX_XF86 */
+ 
+@@ -12,8 +11,6 @@
+ 
+ 
+ /**********************************************************************/
+-#ifdef TC
+-#endif
+ #ifdef LINUX_XF86
+ #define LINUX
+ #endif
+@@ -22,9 +19,6 @@
+ #endif
+ 
+ /**********************************************************************/
+-#ifdef TC
+-#define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize);
+-#endif
+ #ifdef LINUX_XF86
+ #define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
+ #endif
+@@ -35,9 +29,6 @@
+ 
+ /**********************************************************************/
+ 
+-#ifdef TC
+-#define XGI_MemoryCopy(Destination,Soruce,Length) memmove(Destination, Soruce, Length);
+-#endif
+ #ifdef LINUX_XF86
+ #define XGI_MemoryCopy(Destination,Soruce,Length) memcpy(Destination,Soruce,Length)
+ #endif
+@@ -75,14 +66,6 @@
+ /*  TC                                                                */
+ /**********************************************************************/
+ 
+-#ifdef TC
+-#define OutPortByte(p,v) outp((unsigned short)(p),(unsigned char)(v))
+-#define OutPortWord(p,v) outp((unsigned short)(p),(unsigned short)(v))
+-#define OutPortLong(p,v) outp((unsigned short)(p),(unsigned long)(v))
+-#define InPortByte(p)    inp((unsigned short)(p))
+-#define InPortWord(p)    inp((unsigned short)(p))
+-#define InPortLong(p)    ((inp((unsigned short)(p+2))<<16) | inp((unsigned short)(p)))
+-#endif
+ 
+ /**********************************************************************/
+ /*  LINUX XF86                                                        */
+diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c
+index 8da9715ce4fd..9f5ce8c98c1e 100644
+--- a/drivers/staging/xgifb/vb_setmode.c
++++ b/drivers/staging/xgifb/vb_setmode.c
+@@ -1,11 +1,5 @@
+ #include "osdef.h"
+ 
+-#ifdef TC
+-#include 
+-#include 
+-#include 
+-#include 
+-#endif
+ 
+ 
+ #ifdef LINUX_XF86
+@@ -3996,57 +3990,6 @@ BOOLEAN XGI_GetLCDInfo( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBI
+ BOOLEAN XGI_SearchModeID( USHORT ModeNo , USHORT *ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
+ {
+ 
+-#ifdef TC
+-
+-    if ( ModeNo <= 5 )
+-        ModeNo |= 1 ;
+-
+-    if ( ModeNo <= 0x13 )
+-    {
+-        /* for (*ModeIdIndex=0;*ModeIdIndexSModeIDTable)/sizeof(XGI_StStruct);(*ModeIdIndex)++) */
+-        for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ )
+-        {
+-            if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == ModeNo )
+-                break ;
+-            if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == 0xFF )
+-                return( FALSE ) ;
+-        }
+-
+-        VGA_INFO = ( PUCHAR )MK_FP( 0 , 0x489 ) ;
+-
+-        if ( ModeNo == 0x07 )
+-        {
+-            if ( ( *VGA_INFO & 0x10 ) != 0 )
+-                ( *ModeIdIndex )++ ; /* 400 lines */
+-            /* else 350 lines */
+-        }
+-
+-        if ( ModeNo <= 3 )
+-        {
+-            if ( ( *VGA_INFO & 0x80 ) == 0 )
+-            {
+-                ( *ModeIdIndex )++ ;
+-                if ( ( *VGA_INFO & 0x10 ) != 0 )
+-                    ( *ModeIdIndex )++ ; /* 400 lines */
+-                /* else 350 lines */
+-            }
+-            /* else 200 lines */
+-        }
+-    }
+-    else
+-    {
+-        /* for (*ModeIdIndex=0;*ModeIdIndexEModeIDTable)/sizeof(XGI_ExtStruct);(*ModeIdIndex)++) */
+-        for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ )
+-        {
+-            if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == ModeNo )
+-                break ;
+-            if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == 0xFF )
+-                return( FALSE ) ;
+-        }
+-    }
+-
+-
+-#endif
+ 
+ 
+ #ifdef LINUX /* chiawen for linux solution */
+@@ -4448,141 +4391,10 @@ void XGI_SenseCRT1( PVB_DEVICE_INFO pVBInfo )
+ 
+ 
+ 
+-#ifdef TC
+-/* --------------------------------------------------------------------- */
+-/* Function : INT1AReturnCode */
+-/* Input : */
+-/* Output : */
+-/* Description : */
+-/* --------------------------------------------------------------------- */
+-int INT1AReturnCode( union REGS regs )
+-{
+-    if ( regs.x.cflag )
+-    {
+-        /* printf( "Error to find pci device!\n" ) ; */
+-        return( 1 ) ;
+-    }
+-
+-    switch(regs.h.ah)
+-    {
+-        case 0: return 0;
+-            break ;
+-        case 0x81:
+-            printf( "Function not support\n" ) ;
+-            break ;
+-        case 0x83:
+-            printf( "bad vendor id\n" ) ;
+-            break ;
+-        case 0x86:
+-            printf( "device not found\n" ) ;
+-            break ;
+-        case 0x87:
+-            printf( "bad register number\n" ) ;
+-            break ;
+-        case 0x88:
+-            printf( "set failed\n" ) ;
+-            break ;
+-        case 0x89:
+-            printf( "buffer too small" ) ;
+-            break ;
+-        default:
+-            break ;
+-    }
+-    return( 1 ) ;
+-}
+-
+-
+-/* --------------------------------------------------------------------- */
+-/* Function : FindPCIIOBase */
+-/* Input : */
+-/* Output : */
+-/* Description : */
+-/* --------------------------------------------------------------------- */
+-unsigned FindPCIIOBase( unsigned index , unsigned deviceid )
+-{
+-    union REGS regs ;
+-
+-    regs.h.ah = 0xb1 ;	/* PCI_FUNCTION_ID */
+-    regs.h.al = 0x02 ;	/* FIND_PCI_DEVICE */
+-    regs.x.cx = deviceid ;
+-    regs.x.dx = 0x1039 ;
+-    regs.x.si = index ;	/* find n-th device */
+-
+-    int86( 0x1A , ®s , ®s ) ;
+-
+-    if ( INT1AReturnCode( regs ) != 0 )
+-        return( 0 ) ;
+-
+-    /* regs.h.bh bus number */
+-    /* regs.h.bl device number */
+-    regs.h.ah = 0xb1 ;  /* PCI_FUNCTION_ID */
+-    regs.h.al = 0x09 ;  /* READ_CONFIG_WORD */
+-    regs.x.cx = deviceid ;
+-    regs.x.dx = 0x1039 ;
+-    regs.x.di = 0x18 ;  /* register number */
+-    int86( 0x1A , ®s , ®s ) ;
+-
+-    if ( INT1AReturnCode( regs ) != 0 )
+-        return( 0 ) ;
+-
+-    return( regs.x.cx ) ;
+-}
+-
+-#endif
+-
+-
+-
+-#ifdef TC
+-/* --------------------------------------------------------------------- */
+-/* Function : main */
+-/* Input : */
+-/* Output : */
+-/* Description : */
+-/* --------------------------------------------------------------------- */
+-void main(int argc, char *argv[])
+-{
+-    XGI_HW_DEVICE_INFO HwDeviceExtension ;
+-    USHORT temp ;
+-    USHORT ModeNo ;
+-
+-    /* HwDeviceExtension.pjVirtualRomBase =(PUCHAR) MK_FP(0xC000,0); */
+-    /* HwDeviceExtension.pjVideoMemoryAddress = (PUCHAR)MK_FP(0xA000,0); */
+-
+ 
+-    HwDeviceExtension.pjIOAddress = ( FindPCIIOBase( 0 ,0x6300 ) & 0xFF80 ) + 0x30 ;
+-    HwDeviceExtension.jChipType = XGI_340 ;
+ 
+ 
+ 
+-    /* HwDeviceExtension.pjIOAddress = ( FindPCIIOBase( 0 , 0x5315 ) & 0xFF80 ) + 0x30 ; */
+-
+-    HwDeviceExtension.pjIOAddress = ( FindPCIIOBase( 0 , 0x330 ) & 0xFF80 ) + 0x30 ;
+-    HwDeviceExtension.jChipType = XGI_340 ;
+-
+-
+-    HwDeviceExtension.ujVBChipID = VB_CHIP_301 ;
+-    StrCpy(HwDeviceExtension.szVBIOSVer , "0.84" ) ;
+-    HwDeviceExtension.bSkipDramSizing = FALSE ;
+-    HwDeviceExtension.ulVideoMemorySize = 0 ;
+-
+-    if ( argc == 2 )
+-    {
+-        ModeNo = atoi( argv[ 1 ] ) ;
+-    }
+-    else
+-    {
+-        ModeNo = 0x2e ;
+-        /* ModeNo = 0x37 ; 1024x768x 4bpp */
+-        /* ModeNo = 0x38 ; 1024x768x 8bpp */
+-        /* ModeNo = 0x4A ; 1024x768x 16bpp */
+-        /* ModeNo = 0x47 ; 800x600x 16bpp */
+-    }
+-
+-    /* XGIInitNew( &HwDeviceExtension ) ; */
+-    XGISetModeNew( &HwDeviceExtension , ModeNo ) ;
+-}
+-#endif
+-
+ 
+ /* --------------------------------------------------------------------- */
+ /* Function : XGI_WaitDisplay */
+diff --git a/drivers/staging/xgifb/vb_util.c b/drivers/staging/xgifb/vb_util.c
+index cd8ddb957cb5..4c8ec25211f2 100644
+--- a/drivers/staging/xgifb/vb_util.c
++++ b/drivers/staging/xgifb/vb_util.c
+@@ -9,12 +9,6 @@
+ #include 
+ #endif
+ 
+-#ifdef TC
+-#include 
+-#include 
+-#include 
+-#include 
+-#endif
+ 
+ 
+ #ifdef LINUX_XF86
+@@ -213,9 +207,6 @@ void NewDelaySeconds( int seconds )
+ 
+     for( i = 0 ; i < seconds ; i++ )
+     {
+-#ifdef TC
+-        delay( 1000 ) ;
+-#endif
+ 
+ 
+ 

commit af49a7c9ec9adab8da132e616471837663db5db1
+Author: Bill Pemberton 
+Date:   Thu Jun 17 13:10:36 2010 -0400
+
+    Staging: xgifb: Remove use of WINCE_HEADER define
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Arnaud Patard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/osdef.h b/drivers/staging/xgifb/osdef.h
+index 453ffad1c1f8..83fffe181ef9 100644
+--- a/drivers/staging/xgifb/osdef.h
++++ b/drivers/staging/xgifb/osdef.h
+@@ -1,7 +1,6 @@
+ #ifndef _OSDEF_H_
+ #define _OSDEF_H_
+ 
+-/* #define WINCE_HEADER*/
+ /* #define TC */
+ #define LINUX_KERNEL
+ /* #define LINUX_XF86 */
+@@ -15,8 +14,6 @@
+ /**********************************************************************/
+ #ifdef TC
+ #endif
+-#ifdef WINCE_HEADER
+-#endif
+ #ifdef LINUX_XF86
+ #define LINUX
+ #endif
+@@ -28,9 +25,6 @@
+ #ifdef TC
+ #define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize);
+ #endif
+-#ifdef WINCE_HEADER
+-#define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize);
+-#endif
+ #ifdef LINUX_XF86
+ #define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
+ #endif
+@@ -44,9 +38,6 @@
+ #ifdef TC
+ #define XGI_MemoryCopy(Destination,Soruce,Length) memmove(Destination, Soruce, Length);
+ #endif
+-#ifdef WINCE_HEADER
+-#define XGI_MemoryCopy(Destination,Soruce,Length) memmove(Destination, Soruce, Length);
+-#endif
+ #ifdef LINUX_XF86
+ #define XGI_MemoryCopy(Destination,Soruce,Length) memcpy(Destination,Soruce,Length)
+ #endif
+@@ -125,12 +116,4 @@
+ /*  WIN CE                                                          */
+ /**********************************************************************/
+ 
+-#ifdef WINCE_HEADER
+-#define OutPortByte(p,v) WRITE_PORT_UCHAR ((PUCHAR) (p), (UCHAR) (v))
+-#define OutPortWord(p,v) WRITE_PORT_USHORT((PUSHORT) (p), (USHORT) (v))
+-#define OutPortLong(p,v) WRITE_PORT_ULONG ((PULONG) (p), (ULONG) (v))
+-#define InPortByte(p)    READ_PORT_UCHAR  ((PUCHAR) (p))
+-#define InPortWord(p)    READ_PORT_USHORT ((PUSHORT) (p))
+-#define InPortLong(p)    READ_PORT_ULONG  ((PULONG) (p))
+-#endif
+ #endif // _OSDEF_H_
+diff --git a/drivers/staging/xgifb/vb_util.c b/drivers/staging/xgifb/vb_util.c
+index fa766e06395b..cd8ddb957cb5 100644
+--- a/drivers/staging/xgifb/vb_util.c
++++ b/drivers/staging/xgifb/vb_util.c
+@@ -218,8 +218,6 @@ void NewDelaySeconds( int seconds )
+ #endif
+ 
+ 
+-#ifdef WINCE_HEADER
+-#endif
+ 
+ #ifdef LINUX_KERNEL
+ #endif

commit bf4fc6ac016eb27e5f99296394f231def05d0a96
+Author: Bill Pemberton 
+Date:   Thu Jun 17 13:10:35 2010 -0400
+
+    Staging: xgifb: Remove code for WIN2000
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Arnaud Patard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/osdef.h b/drivers/staging/xgifb/osdef.h
+index 4bc7d3a7440c..453ffad1c1f8 100644
+--- a/drivers/staging/xgifb/osdef.h
++++ b/drivers/staging/xgifb/osdef.h
+@@ -2,7 +2,6 @@
+ #define _OSDEF_H_
+ 
+ /* #define WINCE_HEADER*/
+-/*#define WIN2000*/
+ /* #define TC */
+ #define LINUX_KERNEL
+ /* #define LINUX_XF86 */
+@@ -16,8 +15,6 @@
+ /**********************************************************************/
+ #ifdef TC
+ #endif
+-#ifdef WIN2000
+-#endif
+ #ifdef WINCE_HEADER
+ #endif
+ #ifdef LINUX_XF86
+@@ -31,9 +28,6 @@
+ #ifdef TC
+ #define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize);
+ #endif
+-#ifdef WIN2000
+-#define XGI_SetMemory(MemoryAddress,MemorySize,value) MemFill((PVOID) MemoryAddress,(ULONG) MemorySize,(UCHAR) value);
+-#endif
+ #ifdef WINCE_HEADER
+ #define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize);
+ #endif
+@@ -50,9 +44,6 @@
+ #ifdef TC
+ #define XGI_MemoryCopy(Destination,Soruce,Length) memmove(Destination, Soruce, Length);
+ #endif
+-#ifdef WIN2000
+-#define XGI_MemoryCopy(Destination,Soruce,Length)  /*VideoPortMoveMemory((PUCHAR)Destination , Soruce,length);*/
+-#endif
+ #ifdef WINCE_HEADER
+ #define XGI_MemoryCopy(Destination,Soruce,Length) memmove(Destination, Soruce, Length);
+ #endif
+@@ -128,14 +119,6 @@
+ /*  WIN 2000                                                          */
+ /**********************************************************************/
+ 
+-#ifdef WIN2000
+-#define OutPortByte(p,v) VideoPortWritePortUchar ((PUCHAR) (p), (UCHAR) (v))
+-#define OutPortWord(p,v) VideoPortWritePortUshort((PUSHORT) (p), (USHORT) (v))
+-#define OutPortLong(p,v) VideoPortWritePortUlong ((PULONG) (p), (ULONG) (v))
+-#define InPortByte(p)    VideoPortReadPortUchar  ((PUCHAR) (p))
+-#define InPortWord(p)    VideoPortReadPortUshort ((PUSHORT) (p))
+-#define InPortLong(p)    VideoPortReadPortUlong  ((PULONG) (p))
+-#endif
+ 
+ 
+ /**********************************************************************/
+diff --git a/drivers/staging/xgifb/vb_ext.c b/drivers/staging/xgifb/vb_ext.c
+index 91568fa6916f..7a96dad686c6 100644
+--- a/drivers/staging/xgifb/vb_ext.c
++++ b/drivers/staging/xgifb/vb_ext.c
+@@ -3,17 +3,6 @@
+ 
+ 
+ 
+-#ifdef WIN2000
+-
+-#include 
+-#include 
+-#include 
+-#include 
+-#include 
+-#include "xgiv.h"
+-#include "dd_i2c.h"
+-#include "tools.h"
+-#endif /* WIN2000 */
+ 
+ #ifdef LINUX_XF86
+ #include "xf86.h"
+@@ -42,9 +31,6 @@ extern   UCHAR XGI330_OutputSelect;
+ extern   USHORT XGI330_RGBSenseData2;
+ extern   USHORT XGI330_YCSenseData2;
+ extern   USHORT XGI330_VideoSenseData2;
+-#ifdef WIN2000
+-extern   UCHAR SenseCHTV(PHW_DEVICE_EXTENSION pHWDE);       /* 2007/05/17 Billy */
+-#endif
+ void     XGI_GetSenseStatus( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo );
+ BOOLEAN  XGINew_GetPanelID(PVB_DEVICE_INFO pVBInfo);
+ USHORT   XGINew_SenseLCD(PXGI_HW_DEVICE_INFO,PVB_DEVICE_INFO pVBInfo);
+@@ -62,18 +48,6 @@ void XGI_WaitDisplay(void);
+ BOOLEAN XGI_Is301C(PVB_DEVICE_INFO);
+ BOOLEAN XGI_Is301LV(PVB_DEVICE_INFO);
+ 
+-#ifdef WIN2000
+-UCHAR XGI_SenseLCD(PHW_DEVICE_EXTENSION, PVB_DEVICE_INFO);
+-UCHAR XGI_GetLCDDDCInfo(PHW_DEVICE_EXTENSION,PVB_DEVICE_INFO);
+-
+-extern BOOL bGetDdcInfo(
+-PHW_DEVICE_EXTENSION  pHWDE,
+-ULONG                 ulWhichOne,
+-PUCHAR                pjQueryBuffer,
+-ULONG                 ulBufferSize
+-   );
+-
+-#endif
+ 
+ 
+ /* --------------------------------------------------------------------- */
+@@ -164,284 +138,6 @@ BOOLEAN XGINew_Sense(  USHORT tempbx , USHORT tempcx, PVB_DEVICE_INFO pVBInfo )
+         return( 0 ) ;
+ }
+ 
+-#ifdef WIN2000
+-/* --------------------------------------------------------------------- */
+-/* Function : XGI_SenseLCD */
+-/* Input : */
+-/* Output : */
+-/* Description : */
+-/* --------------------------------------------------------------------- */
+-UCHAR XGI_SenseLCD( PHW_DEVICE_EXTENSION pHWDE, PVB_DEVICE_INFO pVBInfo)
+-{
+-    USHORT tempax , tempbx , tempcx ;
+-    UCHAR SoftSetting = XGI330_SoftSetting ;
+-
+-    if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV ) )
+-        return( 1 ) ;
+-
+-
+-    if ( SoftSetting & HotPlugFunction )	/* Hot Plug Detection */
+-    {
+-        XGINew_SetRegAND( pVBInfo->Part4Port , 0x0F , 0x3F ) ;
+-        tempbx = 0 ;
+-        tempcx = 0x9010 ;
+-        if ( XGINew_Sense( tempbx , tempcx, pVBInfo ) )
+-            return( 1 ) ;
+-
+-        return( 0 ) ;
+-    }
+-    else	/* Get LCD Info from EDID */
+-        return(XGI_GetLCDDDCInfo(pHWDE, pVBInfo));
+-}
+-
+-
+-/* --------------------------------------------------------------------- */
+-/* Function : XGI_GetLCDDDCInfo */
+-/* Input : */
+-/* Output : */
+-/* Description : */
+-/* --------------------------------------------------------------------- */
+-UCHAR XGI_GetLCDDDCInfo( PHW_DEVICE_EXTENSION pHWDE , PVB_DEVICE_INFO pVBInfo)
+-{
+-    UCHAR tempah , tempbl , tempbh ;
+-    USHORT tempbx , temp ;
+-    UCHAR pjEDIDBuf[ 256 ] ;
+-    ULONG ulBufferSize = 256 ;
+-    UCHAR bMASK_OUTPUTSTATE_CRT2LCD = 2 ; /* 0423 shampoo */
+-
+-    bGetDdcInfo( pHWDE , MASK_OUTPUTSTATE_CRT2LCD , pjEDIDBuf , ulBufferSize ) ;
+-    if ( ( *( ( PULONG )pjEDIDBuf ) == 0xFFFFFF00 ) && ( *( ( PULONG )( pjEDIDBuf + 4 ) ) == 0x00FFFFFF ) )
+-    {
+-        tempah = Panel1024x768 ;
+-        tempbl=( *( pjEDIDBuf + 0x3A ) ) & 0xf0 ;
+-
+-        if ( tempbl != 0x40 )
+-        {
+-            tempah = Panel1600x1200 ;
+-            if ( tempbl != 0x60 )
+-            {
+-                tempah = Panel1280x1024 ;
+-                tempbh = ( *( pjEDIDBuf + 0x3B ) ) ;
+-                if ( tempbh != 0x00 )
+-                {
+-                    tempah = Panel1280x960 ;
+-                    if ( tempbh != 0x0C0 )
+-                    {
+-                        tempbx = ( ( *( pjEDIDBuf + 0x24 ) ) << 8 ) | ( *( pjEDIDBuf + 0x23 ) ) ;
+-                        tempah = Panel1280x1024 ;
+-                        if ( !( tempbx & 0x0100 ) )
+-                        {
+-                            tempah = Panel1024x768 ;
+-                            if ( !( tempbx & 0x0E00 ) )
+-                            {
+-                                tempah = Panel1280x1024 ;
+-                            }
+-                        }
+-                    }
+-
+-                    if ( tempbx & 0x00FF )
+-                    {
+-                        temp = ScalingLCD ;
+-                        XGINew_SetRegOR( pVBInfo->P3d4 , 0x37 , temp ) ;
+-                    }
+-                }
+-            }
+-        }
+-        XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x36 , ( ~0x07 ) , tempah ) ;
+-        tempah = ( ( *( pjEDIDBuf + 0x47 ) ) & 0x06 ) ;		/* Polarity */
+-        tempah = ( tempah ^ 0x06 ) << 4 ;
+-        tempah |= LCDSync ;
+-        XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x37 , ( ~LCDSyncBit ) , tempah ) ;
+-        tempbh= XGINew_GetReg1( pVBInfo->P3d4 , 0x36 ) ;
+-        tempbh &= 0x07 ;
+-        if ( tempbh == Panel1280x960 )
+-            XGINew_SetRegAND( pVBInfo->P3d4 , 0x37 , 0x0E ) ;
+-    }
+-    else if ( *pjEDIDBuf == 0x20 )
+-    {
+-        tempah = Panel1024x768 ;
+-        XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x36 , ( ~0x07 ) , tempah ) ;
+-    }
+-    else
+-    {
+-        return( 0 ) ;
+-    }
+-
+-    return( 1 ) ;
+-}
+-
+-
+-/* --------------------------------------------------------------------- */
+-/* Function : XGI_DySense */
+-/* Input : */
+-/* Output : */
+-/* Description : */
+-/* --------------------------------------------------------------------- */
+-BOOLEAN XGI_DySense( PHW_DEVICE_EXTENSION pHWDE , PUCHAR ujConnectStatus)
+-{
+-    UCHAR pre_CRD,pre_SR1E , pre_Part2_0 , pre_Part4_D ;
+-    USHORT tempax , tempbx , tempcx , pushax , temp ;
+-    VB_DEVICE_INFO VBINF;
+-    PVB_DEVICE_INFO pVBInfo = &VBINF;
+-    UCHAR OutputSelect = XGI330_OutputSelect ;
+-    PXGI_HW_DEVICE_INFO HwDeviceExtension= pHWDE->pXGIHWDE ;
+-    UCHAR   bConnectStatus = 0 ;
+-    pVBInfo->BaseAddr = HwDeviceExtension->pjIOAddress ;
+-    pVBInfo->ROMAddr  = pHWDE->pjVirtualRomBase ;
+-
+-    pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
+-    pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
+-    pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
+-    pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
+-    pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
+-    pushax = XGINew_GetReg1( pVBInfo->P3d4 , 0x17 ) ;	/* 0512 Fix Dysense hanged */
+-    temp = ( pushax & 0x00FF ) | 0x80 ;
+-    XGINew_SetRegOR( pVBInfo->P3d4 , 0x17 , temp ) ;
+-    XGINew_SetReg1( pVBInfo->P3c4 , 0x05 , 0x86 ) ;
+-    /* beginning of dynamic sense CRT1 */
+-
+-    pVBInfo->IF_DEF_CH7007 = 0;
+-    if (pHWDE->bCH7007)
+-    {
+-    	InitTo330Pointer( pHWDE->pXGIHWDE->jChipType, pVBInfo ) ;
+-        HwDeviceExtension->pDevice = (PVOID)pHWDE;
+-        pVBInfo->IF_DEF_CH7007 = 1;
+-        /* [Billy] 2007/05/14 For CH7007 */
+-        if ( pVBInfo->IF_DEF_CH7007 == 1 )
+-        {
+-           bConnectStatus = SenseCHTV(HwDeviceExtension->pDevice) ; /* 07/05/28 */
+-           XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , ~0x03 , (UCHAR)bConnectStatus ) ;
+-        }
+-    }
+-    if(( pHWDE->jChipID >= XG40 ) || ( pHWDE->jChipID >= XG20 ))
+-    {
+-
+-        if ( pHWDE->jChipID >= XG40 )
+-    	    XGINew_SetReg1( pVBInfo->P3d4 , 0x57 , 0x4A ) ;	/* write sense pattern 30->4a */
+-    	else
+-            XGINew_SetReg1( pVBInfo->P3d4 , 0x57 , 0x5F ) ;	/* write sense pattern */
+-
+-        XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x53 , 0xFF , 0x02 ) ;	/* enable sense DAC */
+-        XGI_WaitDisply(pVBInfo) ;
+-
+-        if(XGINew_GetReg2( pVBInfo->P3c2 ) & 0x10 )
+-            bConnectStatus |= Monitor1Sense ;
+-
+-        XGINew_SetRegAND( pVBInfo->P3d4 , 0x53 , 0xFD ) ;	/* disable sense DAC */
+-        XGINew_SetRegAND( pVBInfo->P3d4 , 0x57 , 0x00 ) ;	/* clear sense pattern */
+-
+-
+-        /* ---------- End of dynamic sense CRT1 ----------- */
+-
+-        /* ---------- beginning of dynamic sense VB ------------ */
+-        pre_SR1E = XGINew_GetReg1( pVBInfo->P3c4 , 0x1E ) ;
+-        XGINew_SetRegOR( pVBInfo->P3c4 , 0x1E , 0x20 ) ;	/* Enable CRT2,work-a-round for 301B/301LV/302LV */
+-        pre_Part2_0 = XGINew_GetReg1( pVBInfo->Part2Port , 0x00 ) ;
+-        pre_Part4_D = XGINew_GetReg1( pVBInfo->Part4Port , 0x0D ) ;
+-
+-        if ( XGI_Is301C( pVBInfo ) )	/* 301C only */
+-            XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x0D , ~0x07 , 0x01 ) ;	/* Set Part4 0x0D D[2:0] to 001b */
+-
+-        /* tempax = 0 ; */
+-        if ( !XGI_Is301LV( pVBInfo ) )
+-        {
+-           tempbx = XGI330_RGBSenseData2 ;
+-            tempcx = 0x0E08 ;
+-            if(XGINew_Sense( tempbx , tempcx, pVBInfo ) )
+-            {
+-                bConnectStatus |= Monitor2Sense ;
+-                if ( OutputSelect & SetSCARTOutput )
+-                {
+-                    bConnectStatus ^= ( Monitor2Sense | SCARTSense ) ;
+-                }
+-            }
+-        }
+-        if ( XGI_Is301C( pVBInfo ) )	/* 301C only */
+-            XGINew_SetRegOR( pVBInfo->Part4Port , 0x0D , 0x04 ) ;	/* Set Part4 0x0D D[2]=1 for dynamic sense */
+-
+-        if ( ( XGINew_Is301B( pVBInfo ) ) )
+-            XGINew_SetRegOR( pVBInfo->Part2Port , 0x00 , 0x0C ) ;    /* ????????? */
+-
+-	if ( XGINew_SenseHiTV( HwDeviceExtension , pVBInfo) )		/* add by kuku for Dysense HiTV //start */
+-	{
+-	    bConnectStatus|= YPbPrSense ;
+-	}
+-	else
+-	{
+-        tempbx = XGI330_YCSenseData2 ;	/* Y/C Sense Data Ptr */
+-        tempcx = 0x0604 ;
+-        if ( XGINew_Sense( tempbx , tempcx , pVBInfo) )
+-            bConnectStatus |= SVIDEOSense ;
+-
+-        if ( OutputSelect & BoardTVType )
+-        {
+-            tempbx = XGI330_VideoSenseData2 ;
+-            tempcx = 0x0804 ;
+-            if ( XGINew_Sense(tempbx , tempcx, pVBInfo) )
+-                bConnectStatus|= AVIDEOSense ;
+-        }
+-        else
+-        {
+-            if ( !( bConnectStatus & SVIDEOSense ) )
+-            {
+-                tempbx = XGI330_VideoSenseData2 ;
+-                tempcx = 0x0804 ;
+-                if ( XGINew_Sense( tempbx , tempcx, pVBInfo ) )
+-                    bConnectStatus |= AVIDEOSense ;
+-            }
+-        }
+-    	} /* end */
+-        /* DySenseVBCnt */
+-
+-        tempbx = 0 ;
+-        tempcx = 0 ;
+-        XGINew_Sense(tempbx , tempcx, pVBInfo ) ;
+-
+-        if ( !( bConnectStatus & Monitor2Sense ) )
+-        {
+-            if ( XGI_SenseLCD( pHWDE , pVBInfo ) )
+-                bConnectStatus |= LCDSense ;
+-        }
+-
+-        XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , ~( AVIDEOSense | SVIDEOSense | LCDSense | Monitor2Sense | Monitor1Sense ) , bConnectStatus ) ;
+-
+-        XGINew_SetReg1( pVBInfo->Part4Port , 0x0D , pre_Part4_D ) ;
+-        XGINew_SetReg1( pVBInfo->Part2Port , 0x00 , pre_Part2_0 ) ;
+-        XGINew_SetReg1( pVBInfo->P3c4 , 0x1E , pre_SR1E ) ;
+-
+-        if ( XGI_Is301C( pVBInfo ) )	/* 301C only */
+-        {
+-            tempax = XGINew_GetReg1( pVBInfo->Part2Port , 0x00 ) ;
+-            if ( tempax & 0x20 )
+-            {
+-                /* Reset VBPro */
+-                for( tempcx = 2 ; tempcx > 0 ; tempcx-- )
+-                {
+-                    tempax ^= 0x20 ;
+-                    XGINew_SetReg1( pVBInfo->Part2Port , 0x00 , tempax ) ;
+-                }
+-            }
+-        }
+-        /* End of dynamic sense VB */
+-    }
+-    else
+-    {
+-        XGI_SenseCRT1(pVBInfo) ;
+-        XGI_GetSenseStatus( HwDeviceExtension, pVBInfo ) ;	/* sense CRT2 */
+-        bConnectStatus = XGINew_GetReg1( pVBInfo->P3d4 , 0x32 ) ;
+-    }
+-    temp = pushax & 0x00FF ;		/* 0512 Fix Dysense hanged */
+-    XGINew_SetReg1( pVBInfo->P3d4 , 0x17 , temp ) ;
+-    if ( bConnectStatus )
+-    {
+-        *ujConnectStatus = bConnectStatus ;
+-        return( 1 ) ;
+-    }
+-    else
+-        return( 0 ) ;
+-}
+-
+-#endif /* WIN2000 */
+ 
+ /* --------------------------------------------------------------------- */
+ /* Function : XGISetDPMS */
+diff --git a/drivers/staging/xgifb/vb_ext.h b/drivers/staging/xgifb/vb_ext.h
+index 9a72f5ecb713..3a52a6a93bd5 100644
+--- a/drivers/staging/xgifb/vb_ext.h
++++ b/drivers/staging/xgifb/vb_ext.h
+@@ -25,8 +25,5 @@ extern   void     XGI_GetSenseStatus( PXGI_HW_DEVICE_INFO HwDeviceExtension , PV
+ extern   void     XGINew_SetModeScratch ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) ;
+ extern   void 	  ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo);
+ extern   USHORT   XGINew_SenseLCD(PXGI_HW_DEVICE_INFO,PVB_DEVICE_INFO pVBInfo);
+-#ifdef WIN2000
+-extern   BOOLEAN  XGI_DySense( PHW_DEVICE_EXTENSION pHWDE , PUCHAR ujConnectStatus );
+-#endif /* WIN2000 */
+ 
+ #endif
+diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
+index 08a02e3aaa5a..dfa047338513 100644
+--- a/drivers/staging/xgifb/vb_init.c
++++ b/drivers/staging/xgifb/vb_init.c
+@@ -14,16 +14,6 @@
+ #endif */
+ #endif
+ 
+-#ifdef WIN2000
+-#include 
+-#include 
+-#include 
+-#include 
+-#include 
+-#include "xgiv.h"
+-#include "dd_i2c.h"
+-#include "tools.h"
+-#endif
+ 
+ #include "vb_def.h"
+ #include "vb_struct.h"
+@@ -136,11 +126,6 @@ UCHAR    GetXG21FPBits(PVB_DEVICE_INFO pVBInfo);
+ void     XGINew_GetXG27Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) ;
+ UCHAR    GetXG27FPBits(PVB_DEVICE_INFO pVBInfo);
+ 
+-#ifdef WIN2000
+-/* [Billy] 2007/05/20 For CH7007 */
+-extern  UCHAR CH7007TVReg_UNTSC[][8],CH7007TVReg_ONTSC[][8],CH7007TVReg_UPAL[][8],CH7007TVReg_OPAL[][8];
+-extern  UCHAR XGI7007_CHTVVCLKUNTSC[],XGI7007_CHTVVCLKONTSC[],XGI7007_CHTVVCLKUPAL[],XGI7007_CHTVVCLKOPAL[];
+-#endif
+ 
+ #ifdef LINUX_KERNEL
+ void DelayUS(ULONG MicroSeconds)
+@@ -1878,9 +1863,6 @@ int XGINew_CheckColumn( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INF
+         Position += Increment ;
+     }
+ 
+-#ifdef WIN2000  /* chiawen for linux solution */
+-    DelayUS( 100 ) ;
+-#endif
+ 
+     for( i = 0 , Position = 0 ; i < 2 ; i++ )
+     {
+@@ -3332,16 +3314,6 @@ void XGINew_GetXG21Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO
+ 
+     pVBInfo->IF_DEF_LVDS = 0 ;
+ 
+-#ifdef WIN2000
+-   pVBInfo->IF_DEF_CH7007 = 0 ;
+-    if ( ( pVideoMemory[ 0x65 ] & 0x02 ) )			/* For XG21 CH7007 */
+-    {
+-        /* VideoDebugPrint((0, "ReadVBIOSTablData: pVideoMemory[ 0x65 ] =%x\n",pVideoMemory[ 0x65 ])); */
+-        pVBInfo->IF_DEF_CH7007 = 1 ;                            /* [Billy] 07/05/03 */
+-        XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x38 , ~0xE0 , 0x60 ) ; /* CH7007 on chip */
+-    }
+-    else
+-#endif
+ #if 1
+     if (( pVideoMemory[ 0x65 ] & 0x01 ) )			/* For XG21 LVDS */
+     {
+diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c
+index 2000cec07723..8da9715ce4fd 100644
+--- a/drivers/staging/xgifb/vb_setmode.c
++++ b/drivers/staging/xgifb/vb_setmode.c
+@@ -22,17 +22,6 @@
+ #include "XGIfb.h"
+ #endif
+ 
+-#ifdef WIN2000
+-#include 
+-#include 
+-#include 
+-#include 
+-#include 
+-
+-#include "xgiv.h"
+-#include "dd_i2c.h"
+-#include "tools.h"
+-#endif
+ 
+ #include "vb_def.h"
+ #include "vgatypes.h"
+@@ -179,19 +168,6 @@ void     XGI_SetXG27LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO p
+ UCHAR    XGI_SetDefaultVCLK( PVB_DEVICE_INFO pVBInfo );
+ 
+ extern   void 	  ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo);
+-#ifdef WIN2000
+-/* [Billy] 2007/05/17 For CH7007 */
+-extern  UCHAR CH7007TVReg_UNTSC[][8],CH7007TVReg_ONTSC[][8],CH7007TVReg_UPAL[][8],CH7007TVReg_OPAL[][8];
+-extern  UCHAR CH7007TVCRT1UNTSC_H[][10],CH7007TVCRT1ONTSC_H[][10],CH7007TVCRT1UPAL_H[][10],CH7007TVCRT1OPAL_H[][10] ;
+-extern  UCHAR CH7007TVCRT1UNTSC_V[][10],CH7007TVCRT1ONTSC_V[][10],CH7007TVCRT1UPAL_V[][10],CH7007TVCRT1OPAL_V[][10] ;
+-extern  UCHAR XGI7007_CHTVVCLKUNTSC[],XGI7007_CHTVVCLKONTSC[],XGI7007_CHTVVCLKUPAL[],XGI7007_CHTVVCLKOPAL[];
+-
+-extern  BOOLEAN XGI_XG21CheckCH7007TVMode(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo ) ;
+-extern  void SetCH7007Regs(PXGI_HW_DEVICE_INFO HwDeviceExtension, USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO  pVBInfo ) ;
+-extern  VP_STATUS TurnOnCH7007(PHW_DEVICE_EXTENSION pHWDE) ;
+-extern  VP_STATUS TurnOffCH7007(PHW_DEVICE_EXTENSION pHWDE) ;
+-extern  BOOLEAN IsCH7007TVMode(PVB_DEVICE_INFO pVBInfo) ;
+-#endif
+ 
+ /* USHORT XGINew_flag_clearbuffer; 0: no clear frame buffer 1:clear frame buffer */
+ 
+@@ -480,9 +456,6 @@ BOOLEAN XGISetModeNew( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo )
+     XGI_GetVBType( pVBInfo ) ;
+ 
+     InitTo330Pointer( HwDeviceExtension->jChipType, pVBInfo ) ;
+-#ifdef WIN2000
+-    ReadVBIOSTablData( HwDeviceExtension->jChipType , pVBInfo) ;
+-#endif
+     if ( ModeNo & 0x80 )
+     {
+         ModeNo = ModeNo & 0x7F ;
+@@ -555,21 +528,6 @@ BOOLEAN XGISetModeNew( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo )
+     }	/* !XG20 */
+     else
+     {
+-#ifdef WIN2000
+-        if ( pVBInfo->IF_DEF_CH7007 == 1 )
+-        {
+-
+-            VideoDebugPrint((0, "XGISetModeNew: pVBIfo->IF_DEF_CH7007==1\n"));
+-            pVBInfo->VBType = VB_CH7007 ;
+-            XGI_GetVBInfo(ModeNo , ModeIdIndex , HwDeviceExtension, pVBInfo ) ;
+-            XGI_GetTVInfo(ModeNo , ModeIdIndex, pVBInfo ) ;
+-            XGI_GetLCDInfo(ModeNo , ModeIdIndex, pVBInfo ) ;
+-            if( !(XGI_XG21CheckCH7007TVMode(ModeNo, ModeIdIndex, pVBInfo )) )
+-            {
+-              return FALSE;
+-            }
+-        }
+-#endif
+ 
+ 
+         if ( pVBInfo->IF_DEF_LVDS == 1 )
+@@ -758,13 +716,6 @@ void XGI_SetCRT1Group( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo , U
+ 
+     XGI_LoadDAC( ModeNo , ModeIdIndex, pVBInfo ) ;
+     /* XGI_ClearBuffer( HwDeviceExtension , ModeNo, pVBInfo ) ; */
+-#ifdef WIN2000
+-   if ( pVBInfo->IF_DEF_CH7007 == 1 )  /* [Billy]  2007/05/14  */
+-   {
+-       VideoDebugPrint((0, "XGI_SetCRT1Group: VBInfo->IF_DEF_CH7007==1\n"));
+-       SetCH7007Regs(HwDeviceExtension, ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo ) ; /* 07/05/28 */
+-   }
+-#endif
+ }
+ 
+ 
+@@ -4097,41 +4048,6 @@ BOOLEAN XGI_SearchModeID( USHORT ModeNo , USHORT *ModeIdIndex, PVB_DEVICE_INFO p
+ 
+ #endif
+ 
+-#ifdef WIN2000
+-
+-    if ( ModeNo <= 5 )
+-        ModeNo |= 1 ;
+-    if ( ModeNo <= 0x13 )
+-    {
+-        /* for (*ModeIdIndex=0;*ModeIdIndexSModeIDTable)/sizeof(XGI_StStruct);(*ModeIdIndex)++) */
+-        for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ )
+-        {
+-            if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == ModeNo )
+-                break ;
+-            if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == 0xFF )
+-                return( FALSE ) ;
+-        }
+-
+-        if ( ModeNo == 0x07 )
+-            ( *ModeIdIndex )++ ; /* 400 lines */
+-
+-        if ( ModeNo <=3 )
+-            ( *ModeIdIndex ) += 2 ; /* 400 lines */
+-        /* else 350 lines */
+-    }
+-    else
+-    {
+-        /* for (*ModeIdIndex=0;*ModeIdIndexEModeIDTable)/sizeof(XGI_ExtStruct);(*ModeIdIndex)++) */
+-        for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ )
+-        {
+-            if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == ModeNo )
+-                break ;
+-            if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == 0xFF )
+-                return( FALSE ) ;
+-        }
+-    }
+-
+-#endif
+ 
+ #ifdef LINUX /* chiawen for linux solution */
+ 
+@@ -4326,12 +4242,6 @@ void XGI_DisplayOn( PXGI_HW_DEVICE_INFO pXGIHWDE , PVB_DEVICE_INFO pVBInfo )
+ 
+     if (pVBInfo->IF_DEF_CH7007 == 1) /* [Billy] 07/05/23 For CH7007 */
+     {
+-#ifdef WIN2000
+-       if ( IsCH7007TVMode( pVBInfo ) )
+-       {
+-           TurnOnCH7007(pXGIHWDE->pDevice) ; /* 07/05/28 */
+-       }
+-#endif
+ 
+     }
+ 
+@@ -4387,9 +4297,6 @@ void XGI_DisplayOff( PXGI_HW_DEVICE_INFO pXGIHWDE , PVB_DEVICE_INFO pVBInfo )
+     {
+        /* if( IsCH7007TVMode( pVBInfo ) == 0 ) */
+        {
+-#ifdef WIN2000
+-         TurnOffCH7007(pXGIHWDE->pDevice) ;  /* 07/05/28 */
+-#endif
+        }
+     }
+ 
+@@ -7950,53 +7857,9 @@ void* XGI_GetTVPtr (USHORT BX,USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRat
+ 
+     if ( table == 0x00 ) /* 07/05/22 */
+     {
+-#ifdef WIN2000
+-        if ( pVBInfo->IF_DEF_CH7007 == 1 )
+-        {
+-          switch( tempdi[ i ].DATAPTR )
+-          {
+-            case 0:
+-                return &CH7007TVCRT1UNTSC_H[ tempal ] ;
+-                break ;
+-            case 1:
+-                return &CH7007TVCRT1ONTSC_H[ tempal ] ;
+-                break ;
+-            case 2:
+-                return &CH7007TVCRT1UPAL_H[ tempal ] ;
+-                break ;
+-            case 3:
+-                return &CH7007TVCRT1OPAL_H[ tempal ] ;
+-                break ;
+-            default:
+-                break ;
+-          }
+-        }
+-#endif
+     }
+     else if ( table == 0x01 )
+     {
+-#ifdef WIN2000
+-        if ( pVBInfo->IF_DEF_CH7007 == 1 )
+-        {
+-          switch( tempdi[ i ].DATAPTR )
+-          {
+-            case 0:
+-                return &CH7007TVCRT1UNTSC_V[ tempal ] ;
+-                break ;
+-            case 1:
+-                return &CH7007TVCRT1ONTSC_V[ tempal ] ;
+-                break ;
+-            case 2:
+-                return &CH7007TVCRT1UPAL_V[ tempal ] ;
+-                break ;
+-            case 3:
+-                return &CH7007TVCRT1OPAL_V[ tempal ] ;
+-                break ;
+-            default:
+-                break ;
+-          }
+-        }
+-#endif
+     }
+     else if ( table == 0x04 )
+     {
+@@ -8070,49 +7933,6 @@ void* XGI_GetTVPtr (USHORT BX,USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRat
+     }
+     else if( table == 0x06 )
+     {
+-#ifdef WIN2000
+-        if ( pVBInfo->IF_DEF_CH7007 == 1 )
+-        {
+-          /* VideoDebugPrint((0, "XGI_GetTVPtr: pVBInfo->IF_DEF_CH7007==1\n")); */
+-          switch( tempdi[ i ].DATAPTR )
+-          {
+-            case 0:
+-                return &CH7007TVReg_UNTSC[ tempal ] ;
+-                break ;
+-            case 1:
+-                return &CH7007TVReg_ONTSC[ tempal ] ;
+-                break ;
+-            case 2:
+-                return &CH7007TVReg_UPAL[ tempal ] ;
+-                break ;
+-            case 3:
+-                return &CH7007TVReg_OPAL[ tempal ] ;
+-                break ;
+-            default:
+-                break ;
+-          }
+-        }
+-        else
+-        {
+-            switch( tempdi[ i ].DATAPTR )
+-            {
+-              case 0:
+-                return &XGI_CHTVRegUNTSC[ tempal ] ;
+-                break ;
+-              case 1:
+-                return &XGI_CHTVRegONTSC[ tempal ] ;
+-                break ;
+-              case 2:
+-                return &XGI_CHTVRegUPAL[ tempal ] ;
+-                break ;
+-              case 3:
+-                return &XGI_CHTVRegOPAL[ tempal ] ;
+-                break ;
+-              default:
+-                break ;
+-            }
+-        }
+-#endif
+     }
+     return( 0 ) ;
+ }
+diff --git a/drivers/staging/xgifb/vb_util.c b/drivers/staging/xgifb/vb_util.c
+index 87531b49b739..fa766e06395b 100644
+--- a/drivers/staging/xgifb/vb_util.c
++++ b/drivers/staging/xgifb/vb_util.c
+@@ -16,17 +16,6 @@
+ #include 
+ #endif
+ 
+-#ifdef WIN2000
+-#include 
+-#include 
+-#include 
+-#include 
+-#include 
+-
+-#include "xgiv.h"
+-#include "dd_i2c.h"
+-#include "tools.h"
+-#endif
+ 
+ #ifdef LINUX_XF86
+ #include "xf86.h"
+@@ -219,9 +208,6 @@ void XGINew_SetRegOR( ULONG Port , USHORT Index , USHORT DataOR )
+ /* --------------------------------------------------------------------- */
+ void NewDelaySeconds( int seconds )
+ {
+-#ifdef WIN2000
+-    int j ;
+-#endif
+     int i ;
+ 
+ 
+@@ -231,11 +217,6 @@ void NewDelaySeconds( int seconds )
+         delay( 1000 ) ;
+ #endif
+ 
+-#ifdef WIN2000
+-
+-        for ( j = 0 ; j < 20000 ; j++ )
+-            VideoPortStallExecution( 50 ) ;
+-#endif
+ 
+ #ifdef WINCE_HEADER
+ #endif
+diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h
+index 295ea860ae47..5a09c942203b 100644
+--- a/drivers/staging/xgifb/vgatypes.h
++++ b/drivers/staging/xgifb/vgatypes.h
+@@ -94,8 +94,6 @@ typedef IOADDRESS XGIIOADDRESS;
+ #define VBIOS_VER_MAX_LENGTH    4
+ #endif
+ 
+-#ifndef WIN2000
+-
+ #ifndef LINUX_KERNEL   /* For the linux kernel, this is defined in xgifb.h */
+ #ifndef XGI_CHIP_TYPE
+ typedef enum _XGI_CHIP_TYPE {
+@@ -174,8 +172,6 @@ typedef enum _XGI_LCD_TYPE {
+ } XGI_LCD_TYPE;
+ #endif
+ 
+-#endif   /* not WIN2000 */
+-
+ #ifndef PXGI_DSReg
+ typedef struct _XGI_DSReg
+ {
+@@ -217,9 +213,6 @@ struct _XGI_HW_DEVICE_INFO
+     ULONG  ul2ndVideoMemorySize;
+ 
+     PUCHAR pj2ndIOAddress;
+-/*#ifndef WIN2000
+-    XGIIOADDRESS pjIOAddress;   //  base I/O address of VGA ports (0x3B0)
+-#endif */
+     UCHAR  jChipType;            /* Used to Identify Graphics Chip */
+                                  /* defined in the data structure type  */
+                                  /* "XGI_CHIP_TYPE" */

commit 23aada9cc34759352e9a82c1a157d0e1ba3712bc
+Author: Bill Pemberton 
+Date:   Thu Jun 17 13:10:34 2010 -0400
+
+    Staging: xgifb: remove use of LINUX_VERSION_CODE
+    
+    Remove ifdefs that check LINUX_VERSION_CODE as this is
+    not needed in the staging tree.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Arnaud Patard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/XGI_accel.c b/drivers/staging/xgifb/XGI_accel.c
+index 86ec3421942f..24f454d93772 100644
+--- a/drivers/staging/xgifb/XGI_accel.c
++++ b/drivers/staging/xgifb/XGI_accel.c
+@@ -37,27 +37,12 @@
+ #include 
+ 
+ #include 
+-/*
+-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+-#include 
+-#else
+-#include 

commit acf82e050150490e7a2d795594b2c6cb54243bfd
+Author: Bill Pemberton 
+Date:   Thu Jun 17 13:10:33 2010 -0400
+
+    Staging: xgifb: use %lx instead of %x in printk format
+    
+    This fixes compiler warning  format '%x' expects type 'unsigned int',
+    but argument 2 has type 'long unsigned int'
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Arnaud Patard 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
+index 68bc1d839ad6..4d8dadd17d93 100644
+--- a/drivers/staging/xgifb/XGI_main_26.c
++++ b/drivers/staging/xgifb/XGI_main_26.c
+@@ -3510,7 +3510,8 @@ int __devinit xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 
+ 		XGIfb_registered = 1;
+ 
+-		printk(KERN_INFO "XGIfb: Installed XGIFB_GET_INFO ioctl (%x)\n", XGIFB_GET_INFO);
++		printk(KERN_INFO "XGIfb: Installed XGIFB_GET_INFO ioctl (%lx)\n",
++		       XGIFB_GET_INFO);
+ 
+ /*		printk(KERN_INFO "XGIfb: 2D acceleration is %s, scrolling mode %s\n",
+ 		     XGIfb_accel ? "enabled" : "disabled",

commit 993e33b032cfc072898bab78b8fa8b21bc666c7e
+Author: Bill Pemberton 
+Date:   Wed Apr 28 16:59:36 2010 -0400
+
+    usb: sisusb_con.c: fix shadows sparse warning
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c
+index b271b0557a1f..411e605f448a 100644
+--- a/drivers/usb/misc/sisusbvga/sisusb_con.c
++++ b/drivers/usb/misc/sisusbvga/sisusb_con.c
+@@ -1187,9 +1187,9 @@ sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,
+ 		 * And so is the hi_font_mask.
+ 		 */
+ 		for (i = 0; i < MAX_NR_CONSOLES; i++) {
+-			struct vc_data *c = vc_cons[i].d;
+-			if (c && c->vc_sw == &sisusb_con)
+-				c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
++			struct vc_data *d = vc_cons[i].d;
++			if (d && d->vc_sw == &sisusb_con)
++				d->vc_hi_font_mask = ch512 ? 0x0800 : 0;
+ 		}
+ 
+ 		sisusb->current_font_512 = ch512;
+@@ -1249,7 +1249,7 @@ sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,
+ 		mutex_unlock(&sisusb->lock);
+ 
+ 	if (dorecalc && c) {
+-		int i, rows = c->vc_scan_lines / fh;
++		int rows = c->vc_scan_lines / fh;
+ 
+ 		/* Now adjust our consoles' size */
+ 

commit 7d7917bcbd9bdc61e7daa46ce74f7032aa4bfb3d
+Author: Bill Pemberton 
+Date:   Wed Apr 28 16:59:35 2010 -0400
+
+    USB: oti6858: declare send_data() as static
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
+index deeacdea05db..525d8523df95 100644
+--- a/drivers/usb/serial/oti6858.c
++++ b/drivers/usb/serial/oti6858.c
+@@ -295,7 +295,7 @@ static void setup_line(struct work_struct *work)
+ 	}
+ }
+ 
+-void send_data(struct work_struct *work)
++static void send_data(struct work_struct *work)
+ {
+ 	struct oti6858_private *priv = container_of(work,
+ 			struct oti6858_private, delayed_write_work.work);

commit 277aa97254533c7e49a04244dfbdccbae70a7f0e
+Author: Bill Pemberton 
+Date:   Wed Apr 28 16:59:33 2010 -0400
+
+    USB: whci: declare functions as static
+    
+    qset_print() was not declared static although it is not used
+    outside of debug.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/whci/debug.c b/drivers/usb/host/whci/debug.c
+index c5305b599ca0..767af265e002 100644
+--- a/drivers/usb/host/whci/debug.c
++++ b/drivers/usb/host/whci/debug.c
+@@ -30,7 +30,7 @@ struct whc_dbg {
+ 	struct dentry *pzl_f;
+ };
+ 
+-void qset_print(struct seq_file *s, struct whc_qset *qset)
++static void qset_print(struct seq_file *s, struct whc_qset *qset)
+ {
+ 	static const char *qh_type[] = {
+ 		"ctrl", "isoc", "bulk", "intr", "rsvd", "rsvd", "rsvd", "lpintr", };

commit e8d5373d664caacce2d7623810c91b43f08eabab
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:57 2010 -0400
+
+    staging: hv: remove ASSERT in logging.h
+    
+    ASSERT is no longer used in hv, so remove the define
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/logging.h b/drivers/staging/hv/logging.h
+index 9e55617bd670..ad4cfcfb7b11 100644
+--- a/drivers/staging/hv/logging.h
++++ b/drivers/staging/hv/logging.h
+@@ -61,13 +61,6 @@
+ 
+ extern unsigned int vmbus_loglevel;
+ 
+-#define ASSERT(expr)	\
+-	if (!(expr)) {	\
+-		printk(KERN_CRIT "Assertion failed! %s,%s,%s,line=%d\n", \
+-		       #expr, __FILE__, __func__, __LINE__);	\
+-		__asm__ __volatile__("int3");	\
+-	}
+-
+ #define DPRINT(mod, lvl, fmt, args...) do {\
+ 	if ((mod & (HIWORD(vmbus_loglevel))) &&	\
+ 	    (lvl <= LOWORD(vmbus_loglevel)))	\

commit 790696847dfad8b2d968ce82cc1be58ebacefead
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:56 2010 -0400
+
+    staging: hv: remove ASSERT() and return -EINVAL in NetVsc.c
+    
+    return -EINVAL instead of calling ASSERT()
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/NetVsc.c b/drivers/staging/hv/NetVsc.c
+index ddde39136b6e..f852984950a8 100644
+--- a/drivers/staging/hv/NetVsc.c
++++ b/drivers/staging/hv/NetVsc.c
+@@ -354,7 +354,11 @@ static int NetVscInitializeSendBufferWithNetVsp(struct hv_device *Device)
+ 		DPRINT_EXIT(NETVSC);
+ 		return -1;
+ 	}
+-	ASSERT(netDevice->SendBufferSize > 0);
++	if (netDevice->SendBufferSize <= 0) {
++		ret = -EINVAL;
++		goto Cleanup;
++	}
++
+ 	/* page-size grandularity */
+ 	/* ASSERT((netDevice->SendBufferSize & (PAGE_SIZE - 1)) == 0); */
+ 

commit 7a09876d2a68aab6c7a7d9df60eb0eb13467af11
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:55 2010 -0400
+
+    staging: hv: replace ASSERT() with WARN_ON() in NetVsc.c
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/NetVsc.c b/drivers/staging/hv/NetVsc.c
+index 9863ca252bd9..ddde39136b6e 100644
+--- a/drivers/staging/hv/NetVsc.c
++++ b/drivers/staging/hv/NetVsc.c
+@@ -92,7 +92,7 @@ static struct netvsc_device *AllocNetDevice(struct hv_device *Device)
+ 
+ static void FreeNetDevice(struct netvsc_device *Device)
+ {
+-	ASSERT(atomic_read(&Device->RefCount) == 0);
++	WARN_ON(atomic_read(&Device->RefCount) == 0);
+ 	Device->Device->Extension = NULL;
+ 	kfree(Device);
+ }

commit 972b9529ccfa604bd473c43589f5120066161edd
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:54 2010 -0400
+
+    staging: hv: remove ASSERT()s
+    
+    These ASSERT()s serve no purpose other than for debugging.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/BlkVsc.c b/drivers/staging/hv/BlkVsc.c
+index a48ee3a12646..b2f600551f10 100644
+--- a/drivers/staging/hv/BlkVsc.c
++++ b/drivers/staging/hv/BlkVsc.c
+@@ -78,7 +78,7 @@ int BlkVscInitialize(struct hv_driver *Driver)
+ 	storDriver = (struct storvsc_driver_object *)Driver;
+ 
+ 	/* Make sure we are at least 2 pages since 1 page is used for control */
+-	ASSERT(storDriver->RingBufferSize >= (PAGE_SIZE << 1));
++	/* ASSERT(storDriver->RingBufferSize >= (PAGE_SIZE << 1)); */
+ 
+ 	Driver->name = gBlkDriverName;
+ 	memcpy(&Driver->deviceType, &gBlkVscDeviceType, sizeof(struct hv_guid));
+diff --git a/drivers/staging/hv/Connection.c b/drivers/staging/hv/Connection.c
+index e590eb4b6e76..3a01d3ca4ad0 100644
+--- a/drivers/staging/hv/Connection.c
++++ b/drivers/staging/hv/Connection.c
+@@ -254,7 +254,7 @@ static void VmbusProcessChannelEvent(void *context)
+ 	struct vmbus_channel *channel;
+ 	u32 relId = (u32)(unsigned long)context;
+ 
+-	ASSERT(relId > 0);
++	/* ASSERT(relId > 0); */
+ 
+ 	/*
+ 	 * Find the channel based on this relid and invokes the
+diff --git a/drivers/staging/hv/NetVsc.c b/drivers/staging/hv/NetVsc.c
+index d3154e711776..9863ca252bd9 100644
+--- a/drivers/staging/hv/NetVsc.c
++++ b/drivers/staging/hv/NetVsc.c
+@@ -131,7 +131,7 @@ static void PutNetDevice(struct hv_device *Device)
+ 	struct netvsc_device *netDevice;
+ 
+ 	netDevice = Device->Extension;
+-	ASSERT(netDevice);
++	/* ASSERT(netDevice); */
+ 
+ 	atomic_dec(&netDevice->RefCount);
+ }
+@@ -184,14 +184,15 @@ int NetVscInitialize(struct hv_driver *drv)
+ 		   sizeof(struct vmtransfer_page_packet_header));
+ 
+ 	/* Make sure we are at least 2 pages since 1 page is used for control */
+-	ASSERT(driver->RingBufferSize >= (PAGE_SIZE << 1));
++	/* ASSERT(driver->RingBufferSize >= (PAGE_SIZE << 1)); */
+ 
+ 	drv->name = gDriverName;
+ 	memcpy(&drv->deviceType, &gNetVscDeviceType, sizeof(struct hv_guid));
+ 
+ 	/* Make sure it is set by the caller */
+-	ASSERT(driver->OnReceiveCallback);
+-	ASSERT(driver->OnLinkStatusChanged);
++	/* FIXME: These probably should still be tested in some way */
++	/* ASSERT(driver->OnReceiveCallback); */
++	/* ASSERT(driver->OnLinkStatusChanged); */
+ 
+ 	/* Setup the dispatch table */
+ 	driver->Base.OnDeviceAdd	= NetVscOnDeviceAdd;
+@@ -222,9 +223,9 @@ static int NetVscInitializeReceiveBufferWithNetVsp(struct hv_device *Device)
+ 		DPRINT_EXIT(NETVSC);
+ 		return -1;
+ 	}
+-	ASSERT(netDevice->ReceiveBufferSize > 0);
++	/* ASSERT(netDevice->ReceiveBufferSize > 0); */
+ 	/* page-size grandularity */
+-	ASSERT((netDevice->ReceiveBufferSize & (PAGE_SIZE - 1)) == 0);
++	/* ASSERT((netDevice->ReceiveBufferSize & (PAGE_SIZE - 1)) == 0); */
+ 
+ 	netDevice->ReceiveBuffer =
+ 		osd_PageAlloc(netDevice->ReceiveBufferSize >> PAGE_SHIFT);
+@@ -236,8 +237,8 @@ static int NetVscInitializeReceiveBufferWithNetVsp(struct hv_device *Device)
+ 		goto Cleanup;
+ 	}
+ 	/* page-aligned buffer */
+-	ASSERT(((unsigned long)netDevice->ReceiveBuffer & (PAGE_SIZE - 1)) ==
+-		0);
++	/* ASSERT(((unsigned long)netDevice->ReceiveBuffer & (PAGE_SIZE - 1)) == */
++	/* 	0); */
+ 
+ 	DPRINT_INFO(NETVSC, "Establishing receive buffer's GPADL...");
+ 
+@@ -294,8 +295,8 @@ static int NetVscInitializeReceiveBufferWithNetVsp(struct hv_device *Device)
+ 	}
+ 
+ 	/* Parse the response */
+-	ASSERT(netDevice->ReceiveSectionCount == 0);
+-	ASSERT(netDevice->ReceiveSections == NULL);
++	/* ASSERT(netDevice->ReceiveSectionCount == 0); */
++	/* ASSERT(netDevice->ReceiveSections == NULL); */
+ 
+ 	netDevice->ReceiveSectionCount = initPacket->Messages.Version1Messages.SendReceiveBufferComplete.NumSections;
+ 
+@@ -355,7 +356,7 @@ static int NetVscInitializeSendBufferWithNetVsp(struct hv_device *Device)
+ 	}
+ 	ASSERT(netDevice->SendBufferSize > 0);
+ 	/* page-size grandularity */
+-	ASSERT((netDevice->SendBufferSize & (PAGE_SIZE - 1)) == 0);
++	/* ASSERT((netDevice->SendBufferSize & (PAGE_SIZE - 1)) == 0); */
+ 
+ 	netDevice->SendBuffer =
+ 		osd_PageAlloc(netDevice->SendBufferSize >> PAGE_SHIFT);
+@@ -366,7 +367,7 @@ static int NetVscInitializeSendBufferWithNetVsp(struct hv_device *Device)
+ 		goto Cleanup;
+ 	}
+ 	/* page-aligned buffer */
+-	ASSERT(((unsigned long)netDevice->SendBuffer & (PAGE_SIZE - 1)) == 0);
++	/* ASSERT(((unsigned long)netDevice->SendBuffer & (PAGE_SIZE - 1)) == 0); */
+ 
+ 	DPRINT_INFO(NETVSC, "Establishing send buffer's GPADL...");
+ 
+@@ -912,7 +913,7 @@ static void NetVscOnSendCompletion(struct hv_device *Device,
+ 		   NvspMessage1TypeSendRNDISPacketComplete) {
+ 		/* Get the send context */
+ 		nvscPacket = (struct hv_netvsc_packet *)(unsigned long)Packet->TransactionId;
+-		ASSERT(nvscPacket);
++		/* ASSERT(nvscPacket); */
+ 
+ 		/* Notify the layer above us */
+ 		nvscPacket->Completion.Send.OnSendCompletion(nvscPacket->Completion.Send.SendCompletionContext);
+@@ -1096,8 +1097,8 @@ static void NetVscOnReceive(struct hv_device *Device,
+ 
+ 	/* This is how much we can satisfy */
+ 	xferpagePacket->Count = count - 1;
+-	ASSERT(xferpagePacket->Count > 0 && xferpagePacket->Count <=
+-		vmxferpagePacket->RangeCount);
++	/* ASSERT(xferpagePacket->Count > 0 && xferpagePacket->Count <= */
++	/* 	vmxferpagePacket->RangeCount); */
+ 
+ 	if (xferpagePacket->Count != vmxferpagePacket->RangeCount) {
+ 		DPRINT_INFO(NETVSC, "Needed %d netvsc pkts to satisy this xfer "
+@@ -1125,9 +1126,9 @@ static void NetVscOnReceive(struct hv_device *Device,
+ 					vmxferpagePacket->Ranges[i].ByteCount;
+ 		netvscPacket->PageBufferCount = 1;
+ 
+-		ASSERT(vmxferpagePacket->Ranges[i].ByteOffset +
+-			vmxferpagePacket->Ranges[i].ByteCount <
+-			netDevice->ReceiveBufferSize);
++		/* ASSERT(vmxferpagePacket->Ranges[i].ByteOffset + */
++		/* 	vmxferpagePacket->Ranges[i].ByteCount < */
++		/* 	netDevice->ReceiveBufferSize); */
+ 
+ 		netvscPacket->PageBuffers[0].Length =
+ 					vmxferpagePacket->Ranges[i].ByteCount;
+@@ -1165,7 +1166,7 @@ static void NetVscOnReceive(struct hv_device *Device,
+ 				if (bytesRemain == 0)
+ 					break;
+ 			}
+-			ASSERT(bytesRemain == 0);
++			/* ASSERT(bytesRemain == 0); */
+ 		}
+ 		DPRINT_DBG(NETVSC, "[%d] - (abs offset %u len %u) => "
+ 			   "(pfn %llx, offset %u, len %u)", i,
+@@ -1181,7 +1182,7 @@ static void NetVscOnReceive(struct hv_device *Device,
+ 		NetVscOnReceiveCompletion(netvscPacket->Completion.Recv.ReceiveCompletionContext);
+ 	}
+ 
+-	ASSERT(list_empty(&listHead));
++	/* ASSERT(list_empty(&listHead)); */
+ 
+ 	PutNetDevice(Device);
+ 	DPRINT_EXIT(NETVSC);
+@@ -1245,7 +1246,7 @@ static void NetVscOnReceiveCompletion(void *Context)
+ 
+ 	DPRINT_ENTER(NETVSC);
+ 
+-	ASSERT(packet->XferPagePacket);
++	/* ASSERT(packet->XferPagePacket); */
+ 
+ 	/*
+ 	 * Even though it seems logical to do a GetOutboundNetDevice() here to
+@@ -1263,7 +1264,7 @@ static void NetVscOnReceiveCompletion(void *Context)
+ 	/* Overloading use of the lock. */
+ 	spin_lock_irqsave(&netDevice->receive_packet_list_lock, flags);
+ 
+-	ASSERT(packet->XferPagePacket->Count > 0);
++	/* ASSERT(packet->XferPagePacket->Count > 0); */
+ 	packet->XferPagePacket->Count--;
+ 
+ 	/*
+@@ -1305,7 +1306,7 @@ static void NetVscOnChannelCallback(void *Context)
+ 
+ 	DPRINT_ENTER(NETVSC);
+ 
+-	ASSERT(device);
++	/* ASSERT(device); */
+ 
+ 	packet = kzalloc(NETVSC_PACKET_SIZE * sizeof(unsigned char),
+ 			 GFP_KERNEL);
+@@ -1377,8 +1378,6 @@ static void NetVscOnChannelCallback(void *Context)
+ 			}
+ 
+ 			bufferlen = bytesRecvd;
+-		} else {
+-			ASSERT(0);
+ 		}
+ 	} while (1);
+ 

commit a3810b0ef61d23f37ace99ed0fb180b62fcb3f68
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:51 2010 -0400
+
+    staging: hv: remove ASSERT()s in vmbus_drv.c
+    
+    These ASSERT()s serve no purpose other than for debugging.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c
+index d2a82aa3bbd8..a715b3db87ce 100644
+--- a/drivers/staging/hv/vmbus_drv.c
++++ b/drivers/staging/hv/vmbus_drv.c
+@@ -923,7 +923,7 @@ static void vmbus_msg_dpc(unsigned long data)
+ 
+ 	DPRINT_ENTER(VMBUS_DRV);
+ 
+-	ASSERT(vmbus_drv_obj->OnMsgDpc != NULL);
++	/* ASSERT(vmbus_drv_obj->OnMsgDpc != NULL); */
+ 
+ 	/* Call to bus driver to handle interrupt */
+ 	vmbus_drv_obj->OnMsgDpc(&vmbus_drv_obj->Base);
+@@ -940,7 +940,7 @@ static void vmbus_event_dpc(unsigned long data)
+ 
+ 	DPRINT_ENTER(VMBUS_DRV);
+ 
+-	ASSERT(vmbus_drv_obj->OnEventDpc != NULL);
++	/* ASSERT(vmbus_drv_obj->OnEventDpc != NULL); */
+ 
+ 	/* Call to bus driver to handle interrupt */
+ 	vmbus_drv_obj->OnEventDpc(&vmbus_drv_obj->Base);
+@@ -955,7 +955,7 @@ static irqreturn_t vmbus_isr(int irq, void *dev_id)
+ 
+ 	DPRINT_ENTER(VMBUS_DRV);
+ 
+-	ASSERT(vmbus_driver_obj->OnIsr != NULL);
++	/* ASSERT(vmbus_driver_obj->OnIsr != NULL); */
+ 
+ 	/* Call to bus driver to handle interrupt */
+ 	ret = vmbus_driver_obj->OnIsr(&vmbus_driver_obj->Base);

commit a16e1485c758c236915ac1956694d11bff5e5daa
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:50 2010 -0400
+
+    staging: hv: remove ASSERT()s and return -EINVAL in RingBuffer.c
+    
+    return -EINVAL instead of calling ASSERT() for these conditionals.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/RingBuffer.c b/drivers/staging/hv/RingBuffer.c
+index 69f3ebae15a9..64f8d0f9e05c 100644
+--- a/drivers/staging/hv/RingBuffer.c
++++ b/drivers/staging/hv/RingBuffer.c
+@@ -490,7 +490,8 @@ int RingBufferRead(RING_BUFFER_INFO *InRingInfo, void *Buffer,
+ 	u64 prevIndices = 0;
+ 	unsigned long flags;
+ 
+-	ASSERT(BufferLen > 0);
++	if (BufferLen <= 0)
++		return -EINVAL;
+ 
+ 	spin_lock_irqsave(&InRingInfo->ring_lock, flags);
+ 

commit 3324fb405340cf52fe361697a86d235587402d9c
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:49 2010 -0400
+
+    staging: hv: check return value of RingBufferInit()
+    
+    RingBufferInit() would always return sucess and instead relied on an
+    ASSERT() to test for an error condition.  Remove the ASSERT() and
+    return -EINVAL instead.  The return value of RingBufferInit() was also
+    never checked, so check it.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/Channel.c b/drivers/staging/hv/Channel.c
+index a1431e4ac8be..158f62d8553a 100644
+--- a/drivers/staging/hv/Channel.c
++++ b/drivers/staging/hv/Channel.c
+@@ -203,9 +203,18 @@ int VmbusChannelOpen(struct vmbus_channel *NewChannel, u32 SendRingBufferSize,
+ 	NewChannel->RingBufferPageCount = (SendRingBufferSize +
+ 					   RecvRingBufferSize) >> PAGE_SHIFT;
+ 
+-	RingBufferInit(&NewChannel->Outbound, out, SendRingBufferSize);
++	ret = RingBufferInit(&NewChannel->Outbound, out, SendRingBufferSize);
++	if (!ret) {
++		err = ret;
++		goto errorout;
++	}
++
++	ret = RingBufferInit(&NewChannel->Inbound, in, RecvRingBufferSize);
++	if (!ret) {
++		err = ret;
++		goto errorout;
++	}
+ 
+-	RingBufferInit(&NewChannel->Inbound, in, RecvRingBufferSize);
+ 
+ 	/* Establish the gpadl for the ring buffer */
+ 	DPRINT_DBG(VMBUS, "Establishing ring buffer's gpadl for channel %p...",
+diff --git a/drivers/staging/hv/RingBuffer.c b/drivers/staging/hv/RingBuffer.c
+index ee481fd972b7..69f3ebae15a9 100644
+--- a/drivers/staging/hv/RingBuffer.c
++++ b/drivers/staging/hv/RingBuffer.c
+@@ -301,7 +301,8 @@ u32 GetRingBufferInterruptMask(RING_BUFFER_INFO *rbi)
+ --*/
+ int RingBufferInit(RING_BUFFER_INFO *RingInfo, void *Buffer, u32 BufferLen)
+ {
+-	ASSERT(sizeof(RING_BUFFER) == PAGE_SIZE);
++	if (sizeof(RING_BUFFER) != PAGE_SIZE)
++		return -EINVAL;
+ 
+ 	memset(RingInfo, 0, sizeof(RING_BUFFER_INFO));
+ 

commit 1bbdd7a5380239533c4bb648c5d5d9510f12974b
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:48 2010 -0400
+
+    staging: hv: remove ASSERT()s in RingBuffer.c
+    
+    These ASSERT()s serve no purpose other than for debugging.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/RingBuffer.c b/drivers/staging/hv/RingBuffer.c
+index 08b3c5567e9c..ee481fd972b7 100644
+--- a/drivers/staging/hv/RingBuffer.c
++++ b/drivers/staging/hv/RingBuffer.c
+@@ -72,7 +72,7 @@ GetNextWriteLocation(RING_BUFFER_INFO *RingInfo)
+ {
+ 	u32 next = RingInfo->RingBuffer->WriteIndex;
+ 
+-	ASSERT(next < RingInfo->RingDataSize);
++	/* ASSERT(next < RingInfo->RingDataSize); */
+ 
+ 	return next;
+ }
+@@ -106,7 +106,7 @@ GetNextReadLocation(RING_BUFFER_INFO *RingInfo)
+ {
+ 	u32 next = RingInfo->RingBuffer->ReadIndex;
+ 
+-	ASSERT(next < RingInfo->RingDataSize);
++	/* ASSERT(next < RingInfo->RingDataSize); */
+ 
+ 	return next;
+ }
+@@ -126,7 +126,7 @@ GetNextReadLocationWithOffset(RING_BUFFER_INFO *RingInfo, u32 Offset)
+ {
+ 	u32 next = RingInfo->RingBuffer->ReadIndex;
+ 
+-	ASSERT(next < RingInfo->RingDataSize);
++	/* ASSERT(next < RingInfo->RingDataSize); */
+ 	next += Offset;
+ 	next %= RingInfo->RingDataSize;
+ 

commit 8a62d7168af111bb80d041e6ccf74987056c79d3
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:47 2010 -0400
+
+    staging: hv: remove ASSERT()s in RndisFilter.c
+    
+    return -EINVAL instead of calling ASSERT() for these conditionals.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/RndisFilter.c b/drivers/staging/hv/RndisFilter.c
+index f0aacc0c84c9..597c972f22c2 100644
+--- a/drivers/staging/hv/RndisFilter.c
++++ b/drivers/staging/hv/RndisFilter.c
+@@ -391,7 +391,9 @@ static int RndisFilterOnReceive(struct hv_device *Device,
+ 
+ 	DPRINT_ENTER(NETVSC);
+ 
+-	ASSERT(netDevice);
++	if (!netDevice)
++		return -EINVAL;
++
+ 	/* Make sure the rndis device state is initialized */
+ 	if (!netDevice->Extension) {
+ 		DPRINT_ERR(NETVSC, "got rndis message but no rndis device..."
+@@ -492,7 +494,8 @@ static int RndisFilterQueryDevice(struct rndis_device *Device, u32 Oid,
+ 
+ 	DPRINT_ENTER(NETVSC);
+ 
+-	ASSERT(Result);
++	if (!Result)
++		return -EINVAL;
+ 
+ 	*ResultSize = 0;
+ 	request = GetRndisRequest(Device, REMOTE_NDIS_QUERY_MSG,
+@@ -885,7 +888,9 @@ int RndisFilterOnOpen(struct hv_device *Device)
+ 
+ 	DPRINT_ENTER(NETVSC);
+ 
+-	ASSERT(netDevice);
++	if (!netDevice)
++		return -EINVAL;
++
+ 	ret = RndisFilterOpenDevice(netDevice->Extension);
+ 
+ 	DPRINT_EXIT(NETVSC);
+@@ -900,7 +905,9 @@ int RndisFilterOnClose(struct hv_device *Device)
+ 
+ 	DPRINT_ENTER(NETVSC);
+ 
+-	ASSERT(netDevice);
++	if (!netDevice)
++		return -EINVAL;
++
+ 	ret = RndisFilterCloseDevice(netDevice->Extension);
+ 
+ 	DPRINT_EXIT(NETVSC);

commit 45e4431468f24748ba089b741713c740e854fccc
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:46 2010 -0400
+
+    staging: hv: remove ASSERT()s in RndisFilter.c
+    
+    These ASSERT()s serve no purpose other than for debugging.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/RndisFilter.c b/drivers/staging/hv/RndisFilter.c
+index de4bc80341c3..f0aacc0c84c9 100644
+--- a/drivers/staging/hv/RndisFilter.c
++++ b/drivers/staging/hv/RndisFilter.c
+@@ -356,8 +356,8 @@ static void RndisFilterReceiveData(struct rndis_device *Device,
+ 	DPRINT_ENTER(NETVSC);
+ 
+ 	/* empty ethernet frame ?? */
+-	ASSERT(Packet->PageBuffers[0].Length >
+-		RNDIS_MESSAGE_SIZE(struct rndis_packet));
++	/* ASSERT(Packet->PageBuffers[0].Length > */
++	/* 	RNDIS_MESSAGE_SIZE(struct rndis_packet)); */
+ 
+ 	rndisPacket = &Message->Message.Packet;
+ 
+@@ -567,8 +567,8 @@ static int RndisFilterSetPacketFilter(struct rndis_device *Device,
+ 
+ 	DPRINT_ENTER(NETVSC);
+ 
+-	ASSERT(RNDIS_MESSAGE_SIZE(struct rndis_set_request) + sizeof(u32) <=
+-		sizeof(struct rndis_message));
++	/* ASSERT(RNDIS_MESSAGE_SIZE(struct rndis_set_request) + sizeof(u32) <= */
++	/* 	sizeof(struct rndis_message)); */
+ 
+ 	request = GetRndisRequest(Device, REMOTE_NDIS_SET_MSG,
+ 			RNDIS_MESSAGE_SIZE(struct rndis_set_request) +
+@@ -640,8 +640,8 @@ int RndisFilterInit(struct netvsc_driver *Driver)
+ 					Driver->Base.OnDeviceRemove;
+ 	gRndisFilter.InnerDriver.Base.OnCleanup = Driver->Base.OnCleanup;
+ 
+-	ASSERT(Driver->OnSend);
+-	ASSERT(Driver->OnReceiveCallback);
++	/* ASSERT(Driver->OnSend); */
++	/* ASSERT(Driver->OnReceiveCallback); */
+ 	gRndisFilter.InnerDriver.OnSend = Driver->OnSend;
+ 	gRndisFilter.InnerDriver.OnReceiveCallback = Driver->OnReceiveCallback;
+ 	gRndisFilter.InnerDriver.OnLinkStatusChanged =
+@@ -811,8 +811,8 @@ static int RndisFilterOnDeviceAdd(struct hv_device *Device,
+ 
+ 	/* Initialize the rndis device */
+ 	netDevice = Device->Extension;
+-	ASSERT(netDevice);
+-	ASSERT(netDevice->Device);
++	/* ASSERT(netDevice); */
++	/* ASSERT(netDevice->Device); */
+ 
+ 	netDevice->Extension = rndisDevice;
+ 	rndisDevice->NetDevice = netDevice;
+@@ -921,7 +921,7 @@ static int RndisFilterOnSend(struct hv_device *Device,
+ 
+ 	/* Add the rndis header */
+ 	filterPacket = (struct rndis_filter_packet *)Packet->Extension;
+-	ASSERT(filterPacket);
++	/* ASSERT(filterPacket); */
+ 
+ 	memset(filterPacket, 0, sizeof(struct rndis_filter_packet));
+ 

commit e2e64432e9b76e8170d64b25a40feec991822555
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:45 2010 -0400
+
+    staging: hv: remove ASSERT()s in StorVsc.c
+    
+    These ASSERT()s serve no purpose other than for debugging.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/StorVsc.c b/drivers/staging/hv/StorVsc.c
+index 4d0fbce229e2..e73130e49cce 100644
+--- a/drivers/staging/hv/StorVsc.c
++++ b/drivers/staging/hv/StorVsc.c
+@@ -100,7 +100,7 @@ static inline struct storvsc_device *AllocStorDevice(struct hv_device *Device)
+ 
+ static inline void FreeStorDevice(struct storvsc_device *Device)
+ {
+-	ASSERT(atomic_read(&Device->RefCount) == 0);
++	/* ASSERT(atomic_read(&Device->RefCount) == 0); */
+ 	kfree(Device);
+ }
+ 
+@@ -137,10 +137,10 @@ static inline void PutStorDevice(struct hv_device *Device)
+ 	struct storvsc_device *storDevice;
+ 
+ 	storDevice = (struct storvsc_device *)Device->Extension;
+-	ASSERT(storDevice);
++	/* ASSERT(storDevice); */
+ 
+ 	atomic_dec(&storDevice->RefCount);
+-	ASSERT(atomic_read(&storDevice->RefCount));
++	/* ASSERT(atomic_read(&storDevice->RefCount)); */
+ }
+ 
+ /* Drop ref count to 1 to effectively disable GetStorDevice() */
+@@ -149,7 +149,7 @@ static inline struct storvsc_device *ReleaseStorDevice(struct hv_device *Device)
+ 	struct storvsc_device *storDevice;
+ 
+ 	storDevice = (struct storvsc_device *)Device->Extension;
+-	ASSERT(storDevice);
++	/* ASSERT(storDevice); */
+ 
+ 	/* Busy wait until the ref drop to 2, then set it to 1 */
+ 	while (atomic_cmpxchg(&storDevice->RefCount, 2, 1) != 2)
+@@ -165,7 +165,7 @@ static inline struct storvsc_device *FinalReleaseStorDevice(
+ 	struct storvsc_device *storDevice;
+ 
+ 	storDevice = (struct storvsc_device *)Device->Extension;
+-	ASSERT(storDevice);
++	/* ASSERT(storDevice); */
+ 
+ 	/* Busy wait until the ref drop to 1, then set it to 0 */
+ 	while (atomic_cmpxchg(&storDevice->RefCount, 1, 0) != 1)
+@@ -370,12 +370,12 @@ static void StorVscOnIOCompletion(struct hv_device *Device,
+ 		   "completed bytes xfer %u", RequestExt,
+ 		   VStorPacket->VmSrb.DataTransferLength);
+ 
+-	ASSERT(RequestExt != NULL);
+-	ASSERT(RequestExt->Request != NULL);
++	/* ASSERT(RequestExt != NULL); */
++	/* ASSERT(RequestExt->Request != NULL); */
+ 
+ 	request = RequestExt->Request;
+ 
+-	ASSERT(request->OnIOCompletion != NULL);
++	/* ASSERT(request->OnIOCompletion != NULL); */
+ 
+ 	/* Copy over the status...etc */
+ 	request->Status = VStorPacket->VmSrb.ScsiStatus;
+@@ -395,8 +395,8 @@ static void StorVscOnIOCompletion(struct hv_device *Device,
+ 				    "valid - len %d\n", RequestExt,
+ 				    VStorPacket->VmSrb.SenseInfoLength);
+ 
+-			ASSERT(VStorPacket->VmSrb.SenseInfoLength <=
+-				request->SenseBufferSize);
++			/* ASSERT(VStorPacket->VmSrb.SenseInfoLength <= */
++			/* 	request->SenseBufferSize); */
+ 			memcpy(request->SenseBuffer,
+ 			       VStorPacket->VmSrb.SenseData,
+ 			       VStorPacket->VmSrb.SenseInfoLength);
+@@ -451,7 +451,7 @@ static void StorVscOnChannelCallback(void *context)
+ 
+ 	DPRINT_ENTER(STORVSC);
+ 
+-	ASSERT(device);
++	/* ASSERT(device); */
+ 
+ 	storDevice = MustGetStorDevice(device);
+ 	if (!storDevice) {
+@@ -474,7 +474,7 @@ static void StorVscOnChannelCallback(void *context)
+ 
+ 			request = (struct storvsc_request_extension *)
+ 					(unsigned long)requestId;
+-			ASSERT(request);
++			/* ASSERT(request);c */
+ 
+ 			/* if (vstorPacket.Flags & SYNTHETIC_FLAG) */
+ 			if ((request == &storDevice->InitRequest) ||
+@@ -821,7 +821,7 @@ int StorVscInitialize(struct hv_driver *Driver)
+ 		   sizeof(struct vmscsi_request));
+ 
+ 	/* Make sure we are at least 2 pages since 1 page is used for control */
+-	ASSERT(storDriver->RingBufferSize >= (PAGE_SIZE << 1));
++	/* ASSERT(storDriver->RingBufferSize >= (PAGE_SIZE << 1)); */
+ 
+ 	Driver->name = gDriverName;
+ 	memcpy(&Driver->deviceType, &gStorVscDeviceType,

commit 4e5166b5d83e748014f6f22a4f8a3537294ced9b
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:44 2010 -0400
+
+    staging: hv: remove ASSERT()s in blkvsc_drv.c
+    
+    These ASSERT()s serve no purpose other than for debugging.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c
+index 8a25154c06f5..78fc348334e7 100644
+--- a/drivers/staging/hv/blkvsc_drv.c
++++ b/drivers/staging/hv/blkvsc_drv.c
+@@ -288,8 +288,8 @@ static int blkvsc_probe(struct device *device)
+ 	/* Initialize what we can here */
+ 	spin_lock_init(&blkdev->lock);
+ 
+-	ASSERT(sizeof(struct blkvsc_request_group) <=
+-		sizeof(struct blkvsc_request));
++	/* ASSERT(sizeof(struct blkvsc_request_group) <= */
++	/* 	sizeof(struct blkvsc_request)); */
+ 
+ 	blkdev->request_pool = kmem_cache_create(dev_name(&device_ctx->device),
+ 					sizeof(struct blkvsc_request) +
+@@ -808,8 +808,8 @@ static int blkvsc_remove(struct device *device)
+ 
+ static void blkvsc_init_rw(struct blkvsc_request *blkvsc_req)
+ {
+-	ASSERT(blkvsc_req->req);
+-	ASSERT(blkvsc_req->sector_count <= (MAX_MULTIPAGE_BUFFER_COUNT*8));
++	/* ASSERT(blkvsc_req->req); */
++	/* ASSERT(blkvsc_req->sector_count <= (MAX_MULTIPAGE_BUFFER_COUNT*8)); */
+ 
+ 	blkvsc_req->cmd_len = 16;
+ 
+@@ -1116,7 +1116,7 @@ static void blkvsc_request_completion(struct hv_storvsc_request *request)
+ 	unsigned long flags;
+ 	struct blkvsc_request *comp_req, *tmp;
+ 
+-	ASSERT(blkvsc_req->group);
++	/* ASSERT(blkvsc_req->group); */
+ 
+ 	DPRINT_DBG(BLKVSC_DRV, "blkdev %p blkvsc_req %p group %p type %s "
+ 		   "sect_start %lu sect_count %ld len %d group outstd %d "

commit 5afd06ccd6b309f6a47d7e8fa4ea349b25738d97
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:43 2010 -0400
+
+    staging: hv: make the block driver depend on LBDAF
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/Kconfig b/drivers/staging/hv/Kconfig
+index 79afb1e96c33..97480f5c6599 100644
+--- a/drivers/staging/hv/Kconfig
++++ b/drivers/staging/hv/Kconfig
+@@ -17,7 +17,7 @@ config HYPERV_STORAGE
+ 
+ config HYPERV_BLOCK
+ 	tristate "Microsoft Hyper-V virtual block driver"
+-	depends on BLOCK && SCSI
++	depends on BLOCK && SCSI && LBDAF
+ 	default HYPERV
+ 	help
+ 	  Select this option to enable the Hyper-V virtual block driver.
+diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c
+index b6a2cb8752d3..8a25154c06f5 100644
+--- a/drivers/staging/hv/blkvsc_drv.c
++++ b/drivers/staging/hv/blkvsc_drv.c
+@@ -1489,7 +1489,7 @@ static int __init blkvsc_init(void)
+ {
+ 	int ret;
+ 
+-	ASSERT(sizeof(sector_t) == 8); /* Make sure CONFIG_LBD is set */
++	BUILD_BUG_ON(sizeof(sector_t) != 8);
+ 
+ 	DPRINT_ENTER(BLKVSC_DRV);
+ 

commit ee3503762d86c13bb94ed1db200d4601517b1b9b
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:42 2010 -0400
+
+    staging: hv: return error instead calling ASSERT in blkvsc_drv.c
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c
+index 8f8637e51d9e..b6a2cb8752d3 100644
+--- a/drivers/staging/hv/blkvsc_drv.c
++++ b/drivers/staging/hv/blkvsc_drv.c
+@@ -1213,7 +1213,10 @@ static int blkvsc_cancel_pending_reqs(struct block_device_context *blkdev)
+ 					(!comp_req->request.Status ? 0 : -EIO),
+ 					comp_req->sector_count *
+ 					blkdev->sector_size);
+-				ASSERT(ret != 0);
++
++				/* FIXME: shouldn't this do more than return? */
++				if (ret)
++					goto out;
+ 			}
+ 
+ 			kmem_cache_free(blkdev->request_pool, comp_req);
+@@ -1245,6 +1248,7 @@ static int blkvsc_cancel_pending_reqs(struct block_device_context *blkdev)
+ 		kmem_cache_free(blkdev->request_pool, pend_req);
+ 	}
+ 
++out:
+ 	return ret;
+ }
+ 

commit b856e7382f7d1b184a3dac200275e23a27488ce1
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:41 2010 -0400
+
+    staging: hv: remove ASSERT()s in storvsc_drv.c
+    
+    These ASSERT()s serve no purpose other than for debugging.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
+index 26b35a6c679a..d9649e37e11c 100644
+--- a/drivers/staging/hv/storvsc_drv.c
++++ b/drivers/staging/hv/storvsc_drv.c
+@@ -385,11 +385,11 @@ static void storvsc_commmand_completion(struct hv_storvsc_request *request)
+ 	void (*scsi_done_fn)(struct scsi_cmnd *);
+ 	struct scsi_sense_hdr sense_hdr;
+ 
+-	ASSERT(request == &cmd_request->request);
+-	ASSERT(scmnd);
+-	ASSERT((unsigned long)scmnd->host_scribble ==
+-		(unsigned long)cmd_request);
+-	ASSERT(scmnd->scsi_done);
++	/* ASSERT(request == &cmd_request->request); */
++	/* ASSERT(scmnd); */
++	/* ASSERT((unsigned long)scmnd->host_scribble == */
++	/*        (unsigned long)cmd_request); */
++	/* ASSERT(scmnd->scsi_done); */
+ 
+ 	DPRINT_ENTER(STORVSC_DRV);
+ 
+@@ -413,7 +413,7 @@ static void storvsc_commmand_completion(struct hv_storvsc_request *request)
+ 			scsi_print_sense_hdr("storvsc", &sense_hdr);
+ 	}
+ 
+-	ASSERT(request->BytesXfer <= request->DataBuffer.Length);
++	/* ASSERT(request->BytesXfer <= request->DataBuffer.Length); */
+ 	scsi_set_resid(scmnd, request->DataBuffer.Length - request->BytesXfer);
+ 
+ 	scsi_done_fn = scmnd->scsi_done;
+@@ -522,7 +522,7 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
+ 		src = src_addr;
+ 		srclen = orig_sgl[i].length;
+ 
+-		ASSERT(orig_sgl[i].offset + orig_sgl[i].length <= PAGE_SIZE);
++		/* ASSERT(orig_sgl[i].offset + orig_sgl[i].length <= PAGE_SIZE); */
+ 
+ 		if (j == 0)
+ 			bounce_addr = (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), KM_IRQ0);
+@@ -583,7 +583,7 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
+ 					KM_IRQ0) + orig_sgl[i].offset;
+ 		dest = dest_addr;
+ 		destlen = orig_sgl[i].length;
+-		ASSERT(orig_sgl[i].offset + orig_sgl[i].length <= PAGE_SIZE);
++		/* ASSERT(orig_sgl[i].offset + orig_sgl[i].length <= PAGE_SIZE); */
+ 
+ 		if (j == 0)
+ 			bounce_addr = (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), KM_IRQ0);
+@@ -655,7 +655,7 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd,
+ 
+ 	/* If retrying, no need to prep the cmd */
+ 	if (scmnd->host_scribble) {
+-		ASSERT(scmnd->scsi_done != NULL);
++		/* ASSERT(scmnd->scsi_done != NULL); */
+ 
+ 		cmd_request =
+ 			(struct storvsc_cmd_request *)scmnd->host_scribble;
+@@ -665,8 +665,8 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd,
+ 		goto retry_request;
+ 	}
+ 
+-	ASSERT(scmnd->scsi_done == NULL);
+-	ASSERT(scmnd->host_scribble == NULL);
++	/* ASSERT(scmnd->scsi_done == NULL); */
++	/* ASSERT(scmnd->host_scribble == NULL); */
+ 
+ 	scmnd->scsi_done = done;
+ 
+@@ -717,7 +717,7 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd,
+ 	request->TargetId = scmnd->device->id;
+ 	request->LunId = scmnd->device->lun;
+ 
+-	ASSERT(scmnd->cmd_len <= 16);
++	/* ASSERT(scmnd->cmd_len <= 16); */
+ 	request->CdbLen = scmnd->cmd_len;
+ 	request->Cdb = scmnd->cmnd;
+ 
+@@ -773,13 +773,11 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd,
+ 					page_to_pfn(sg_page((&sgl[i])));
+ 		}
+ 	} else if (scsi_sglist(scmnd)) {
+-		ASSERT(scsi_bufflen(scmnd) <= PAGE_SIZE);
++		/* ASSERT(scsi_bufflen(scmnd) <= PAGE_SIZE); */
+ 		request->DataBuffer.Offset =
+ 			virt_to_phys(scsi_sglist(scmnd)) & (PAGE_SIZE-1);
+ 		request->DataBuffer.PfnArray[0] =
+ 			virt_to_phys(scsi_sglist(scmnd)) >> PAGE_SHIFT;
+-	} else {
+-		ASSERT(scsi_bufflen(scmnd) == 0);
+ 	}
+ 
+ retry_request:

commit 0ace247ead760a6a56a7bb3b5926c28fef1d4c6c
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:40 2010 -0400
+
+    staging: hv: remove ASSERT()s in Channel.c
+    
+    These ASSERT()s serve no purpose other than for debugging.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/Channel.c b/drivers/staging/hv/Channel.c
+index 0a9ca336ede9..a1431e4ac8be 100644
+--- a/drivers/staging/hv/Channel.c
++++ b/drivers/staging/hv/Channel.c
+@@ -183,8 +183,8 @@ int VmbusChannelOpen(struct vmbus_channel *NewChannel, u32 SendRingBufferSize,
+ 	DPRINT_ENTER(VMBUS);
+ 
+ 	/* Aligned to page size */
+-	ASSERT(!(SendRingBufferSize & (PAGE_SIZE - 1)));
+-	ASSERT(!(RecvRingBufferSize & (PAGE_SIZE - 1)));
++	/* ASSERT(!(SendRingBufferSize & (PAGE_SIZE - 1))); */
++	/* ASSERT(!(RecvRingBufferSize & (PAGE_SIZE - 1))); */
+ 
+ 	NewChannel->OnChannelCallback = OnChannelCallback;
+ 	NewChannel->ChannelCallbackContext = Context;
+@@ -195,7 +195,7 @@ int VmbusChannelOpen(struct vmbus_channel *NewChannel, u32 SendRingBufferSize,
+ 	if (!out)
+ 		return -ENOMEM;
+ 
+-	ASSERT(((unsigned long)out & (PAGE_SIZE-1)) == 0);
++	/* ASSERT(((unsigned long)out & (PAGE_SIZE-1)) == 0); */
+ 
+ 	in = (void *)((unsigned long)out + SendRingBufferSize);
+ 
+@@ -373,7 +373,7 @@ static int VmbusChannelCreateGpadlHeader(void *Kbuffer, u32 Size,
+ 	int pfnSum, pfnCount, pfnLeft, pfnCurr, pfnSize;
+ 
+ 	/* ASSERT((kbuffer & (PAGE_SIZE-1)) == 0); */
+-	ASSERT((Size & (PAGE_SIZE-1)) == 0);
++	/* ASSERT((Size & (PAGE_SIZE-1)) == 0); */
+ 
+ 	pageCount = Size >> PAGE_SHIFT;
+ 	pfn = virt_to_phys(Kbuffer) >> PAGE_SHIFT;
+@@ -601,7 +601,7 @@ int VmbusChannelTeardownGpadl(struct vmbus_channel *Channel, u32 GpadlHandle)
+ 
+ 	DPRINT_ENTER(VMBUS);
+ 
+-	ASSERT(GpadlHandle != 0);
++	/* ASSERT(GpadlHandle != 0); */
+ 
+ 	info = kmalloc(sizeof(*info) +
+ 		       sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL);
+@@ -746,7 +746,7 @@ int VmbusChannelSendPacket(struct vmbus_channel *Channel, const void *Buffer,
+ 
+ 	DumpVmbusChannel(Channel);
+ 
+-	ASSERT((packetLenAligned - packetLen) < sizeof(u64));
++	/* ASSERT((packetLenAligned - packetLen) < sizeof(u64)); */
+ 
+ 	/* Setup the descriptor */
+ 	desc.Type = Type; /* VmbusPacketTypeDataInBand; */
+@@ -808,7 +808,7 @@ int VmbusChannelSendPacketPageBuffer(struct vmbus_channel *Channel,
+ 	packetLen = descSize + BufferLen;
+ 	packetLenAligned = ALIGN_UP(packetLen, sizeof(u64));
+ 
+-	ASSERT((packetLenAligned - packetLen) < sizeof(u64));
++	/* ASSERT((packetLenAligned - packetLen) < sizeof(u64)); */
+ 
+ 	/* Setup the descriptor */
+ 	desc.Type = VmbusPacketTypeDataUsingGpaDirect;
+@@ -878,7 +878,7 @@ int VmbusChannelSendPacketMultiPageBuffer(struct vmbus_channel *Channel,
+ 	packetLen = descSize + BufferLen;
+ 	packetLenAligned = ALIGN_UP(packetLen, sizeof(u64));
+ 
+-	ASSERT((packetLenAligned - packetLen) < sizeof(u64));
++	/* ASSERT((packetLenAligned - packetLen) < sizeof(u64)); */
+ 
+ 	/* Setup the descriptor */
+ 	desc.Type = VmbusPacketTypeDataUsingGpaDirect;
+@@ -1056,7 +1056,7 @@ int VmbusChannelRecvPacketRaw(struct vmbus_channel *Channel, void *Buffer,
+ void VmbusChannelOnChannelEvent(struct vmbus_channel *Channel)
+ {
+ 	DumpVmbusChannel(Channel);
+-	ASSERT(Channel->OnChannelCallback);
++	/* ASSERT(Channel->OnChannelCallback); */
+ 
+ 	Channel->OnChannelCallback(Channel->ChannelCallbackContext);
+ 

commit 002b53ea5713910daf215037b72c5820413e2f95
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:39 2010 -0400
+
+    Staging: hv: return -EINVAL instead of calling ASSERT()
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/Channel.c b/drivers/staging/hv/Channel.c
+index bd1a33608fcf..0a9ca336ede9 100644
+--- a/drivers/staging/hv/Channel.c
++++ b/drivers/staging/hv/Channel.c
+@@ -793,7 +793,8 @@ int VmbusChannelSendPacketPageBuffer(struct vmbus_channel *Channel,
+ 
+ 	DPRINT_ENTER(VMBUS);
+ 
+-	ASSERT(PageCount <= MAX_PAGE_BUFFER_COUNT);
++	if (PageCount > MAX_PAGE_BUFFER_COUNT)
++		return -EINVAL;
+ 
+ 	DumpVmbusChannel(Channel);
+ 
+@@ -864,8 +865,8 @@ int VmbusChannelSendPacketMultiPageBuffer(struct vmbus_channel *Channel,
+ 	DPRINT_DBG(VMBUS, "data buffer - offset %u len %u pfn count %u",
+ 		   MultiPageBuffer->Offset, MultiPageBuffer->Length, PfnCount);
+ 
+-	ASSERT(PfnCount > 0);
+-	ASSERT(PfnCount <= MAX_MULTIPAGE_BUFFER_COUNT);
++	if ((PfnCount < 0) || (PfnCount > MAX_MULTIPAGE_BUFFER_COUNT))
++		return -EINVAL;
+ 
+ 	/*
+ 	 * Adjust the size down since VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER is

commit c827f944f51e02894d68f036da843783e622ec2a
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:38 2010 -0400
+
+    Staging: hv: remove ASSERT() in Channel.c
+    
+    VmbusChannelOpen() will now return -EINVAL if UserDataLen is too big.
+    Previously this was handled by an assert.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/Channel.c b/drivers/staging/hv/Channel.c
+index fdd441174f23..bd1a33608fcf 100644
+--- a/drivers/staging/hv/Channel.c
++++ b/drivers/staging/hv/Channel.c
+@@ -258,7 +258,11 @@ int VmbusChannelOpen(struct vmbus_channel *NewChannel, u32 SendRingBufferSize,
+ 						  PAGE_SHIFT;
+ 	openMsg->ServerContextAreaGpadlHandle = 0; /* TODO */
+ 
+-	ASSERT(UserDataLen <= MAX_USER_DEFINED_BYTES);
++	if (UserDataLen > MAX_USER_DEFINED_BYTES) {
++		err = -EINVAL;
++		goto errorout;
++	}
++
+ 	if (UserDataLen)
+ 		memcpy(openMsg->UserData, UserData, UserDataLen);
+ 

commit b94ef345b26b4d75e5028617e43fb51d7dd0162b
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:37 2010 -0400
+
+    Staging: hv: test return value of VmbusChannelEstablishGpadl()
+    
+    The return value of VmbusChannelEstablishGpadl() was not examined in
+    Channel.c
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/Channel.c b/drivers/staging/hv/Channel.c
+index 8c30540b725d..fdd441174f23 100644
+--- a/drivers/staging/hv/Channel.c
++++ b/drivers/staging/hv/Channel.c
+@@ -175,7 +175,7 @@ int VmbusChannelOpen(struct vmbus_channel *NewChannel, u32 SendRingBufferSize,
+ 		     void (*OnChannelCallback)(void *context), void *Context)
+ {
+ 	struct vmbus_channel_open_channel *openMsg;
+-	struct vmbus_channel_msginfo *openInfo;
++	struct vmbus_channel_msginfo *openInfo = NULL;
+ 	void *in, *out;
+ 	unsigned long flags;
+ 	int ret, err = 0;
+@@ -218,7 +218,11 @@ int VmbusChannelOpen(struct vmbus_channel *NewChannel, u32 SendRingBufferSize,
+ 					 SendRingBufferSize +
+ 					 RecvRingBufferSize,
+ 					 &NewChannel->RingBufferGpadlHandle);
+-/* FIXME: the value of ret is not checked */
++
++	if (!ret) {
++		err = ret;
++		goto errorout;
++	}
+ 
+ 	DPRINT_DBG(VMBUS, "channel %p ",
+@@ -250,7 +254,6 @@ int VmbusChannelOpen(struct vmbus_channel *NewChannel, u32 SendRingBufferSize,
+ 	openMsg->OpenId = NewChannel->OfferMsg.ChildRelId; /* FIXME */
+ 	openMsg->ChildRelId = NewChannel->OfferMsg.ChildRelId;
+ 	openMsg->RingBufferGpadlHandle = NewChannel->RingBufferGpadlHandle;
+-	ASSERT(openMsg->RingBufferGpadlHandle);
+ 	openMsg->DownstreamRingBufferPageOffset = SendRingBufferSize >>
+ 						  PAGE_SHIFT;
+ 	openMsg->ServerContextAreaGpadlHandle = 0; /* TODO */
+@@ -295,6 +298,8 @@ int VmbusChannelOpen(struct vmbus_channel *NewChannel, u32 SendRingBufferSize,
+ 	return 0;
+ 
+ errorout:
++	RingBufferCleanup(&NewChannel->Outbound);
++	RingBufferCleanup(&NewChannel->Inbound);
+ 	osd_PageFree(out, (SendRingBufferSize + RecvRingBufferSize)
+ 		     >> PAGE_SHIFT);
+ 	kfree(openInfo);

commit 99259159c0eb58a539ed399677c8294e3792722b
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:36 2010 -0400
+
+    Staging: hv: remove ASSERT() in Channel.c
+    
+    return an error instead of calling ASSERT() if VmbusPostMessage()
+    fails.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/Channel.c b/drivers/staging/hv/Channel.c
+index 2d8c086228cc..8c30540b725d 100644
+--- a/drivers/staging/hv/Channel.c
++++ b/drivers/staging/hv/Channel.c
+@@ -551,7 +551,9 @@ int VmbusChannelEstablishGpadl(struct vmbus_channel *Channel, void *Kbuffer,
+ 			ret = VmbusPostMessage(gpadlBody,
+ 					       subMsgInfo->MessageSize -
+ 					       sizeof(*subMsgInfo));
+-			ASSERT(ret == 0);
++			if (!ret)
++				goto Cleanup;
++
+ 		}
+ 	}
+ 	osd_WaitEventWait(msgInfo->WaitEvent);

commit d1c250bb5df9afb5af3f290d1006dfe601a51e2e
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:35 2010 -0400
+
+    Staging: hv: remove ASSERT() in Channel.c
+    
+    check memory allocation in VmbusChannelCreateGpadlHeader() and
+    return -ENOMEM if it fails
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/Channel.c b/drivers/staging/hv/Channel.c
+index 79c013b48170..2d8c086228cc 100644
+--- a/drivers/staging/hv/Channel.c
++++ b/drivers/staging/hv/Channel.c
+@@ -382,6 +382,8 @@ static int VmbusChannelCreateGpadlHeader(void *Kbuffer, u32 Size,
+ 			  sizeof(struct vmbus_channel_gpadl_header) +
+ 			  sizeof(struct gpa_range) + pfnCount * sizeof(u64);
+ 		msgHeader =  kzalloc(msgSize, GFP_KERNEL);
++		if (!msgHeader)
++			goto nomem;
+ 
+ 		INIT_LIST_HEAD(&msgHeader->SubMsgList);
+ 		msgHeader->MessageSize = msgSize;
+@@ -416,7 +418,9 @@ static int VmbusChannelCreateGpadlHeader(void *Kbuffer, u32 Size,
+ 				  sizeof(struct vmbus_channel_gpadl_body) +
+ 				  pfnCurr * sizeof(u64);
+ 			msgBody = kzalloc(msgSize, GFP_KERNEL);
+-			ASSERT(msgBody);
++			/* FIXME: we probably need to more if this fails */
++			if (!msgBody)
++				goto nomem;
+ 			msgBody->MessageSize = msgSize;
+ 			(*MessageCount)++;
+ 			gpadlBody =
+@@ -459,6 +463,10 @@ static int VmbusChannelCreateGpadlHeader(void *Kbuffer, u32 Size,
+ 	}
+ 
+ 	return 0;
++nomem:
++	kfree(msgHeader);
++	kfree(msgBody);
++	return -ENOMEM;
+ }
+ 
+ /*

commit c3bf2e26b30f4ea54f3825e8ebda7cb10ec204de
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:34 2010 -0400
+
+    Staging: hv: remove ASSERT()s in Channel.c
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/Channel.c b/drivers/staging/hv/Channel.c
+index d939723db335..79c013b48170 100644
+--- a/drivers/staging/hv/Channel.c
++++ b/drivers/staging/hv/Channel.c
+@@ -178,7 +178,7 @@ int VmbusChannelOpen(struct vmbus_channel *NewChannel, u32 SendRingBufferSize,
+ 	struct vmbus_channel_msginfo *openInfo;
+ 	void *in, *out;
+ 	unsigned long flags;
+-	int ret;
++	int ret, err = 0;
+ 
+ 	DPRINT_ENTER(VMBUS);
+ 
+@@ -218,6 +218,7 @@ int VmbusChannelOpen(struct vmbus_channel *NewChannel, u32 SendRingBufferSize,
+ 					 SendRingBufferSize +
+ 					 RecvRingBufferSize,
+ 					 &NewChannel->RingBufferGpadlHandle);
++/* FIXME: the value of ret is not checked */
+ 
+ 	DPRINT_DBG(VMBUS, "channel %p ",
+@@ -233,9 +234,16 @@ int VmbusChannelOpen(struct vmbus_channel *NewChannel, u32 SendRingBufferSize,
+ 	openInfo = kmalloc(sizeof(*openInfo) +
+ 			   sizeof(struct vmbus_channel_open_channel),
+ 			   GFP_KERNEL);
+-	ASSERT(openInfo != NULL);
++	if (!openInfo) {
++		err = -ENOMEM;
++		goto errorout;
++	}
+ 
+ 	openInfo->WaitEvent = osd_WaitEventCreate();
++	if (!openInfo->WaitEvent) {
++		err = -ENOMEM;
++		goto errorout;
++	}
+ 
+ 	openMsg = (struct vmbus_channel_open_channel *)openInfo->Msg;
+ 	openMsg->Header.MessageType = ChannelMessageOpenChannel;
+@@ -285,6 +293,12 @@ int VmbusChannelOpen(struct vmbus_channel *NewChannel, u32 SendRingBufferSize,
+ 	DPRINT_EXIT(VMBUS);
+ 
+ 	return 0;
++
++errorout:
++	osd_PageFree(out, (SendRingBufferSize + RecvRingBufferSize)
++		     >> PAGE_SHIFT);
++	kfree(openInfo);
++	return err;
+ }
+ 
+ /*
+@@ -461,24 +475,29 @@ int VmbusChannelEstablishGpadl(struct vmbus_channel *Channel, void *Kbuffer,
+ 	struct vmbus_channel_gpadl_header *gpadlMsg;
+ 	struct vmbus_channel_gpadl_body *gpadlBody;
+ 	/* struct vmbus_channel_gpadl_created *gpadlCreated; */
+-	struct vmbus_channel_msginfo *msgInfo;
++	struct vmbus_channel_msginfo *msgInfo = NULL;
+ 	struct vmbus_channel_msginfo *subMsgInfo;
+ 	u32 msgCount;
+ 	struct list_head *curr;
+ 	u32 nextGpadlHandle;
+ 	unsigned long flags;
+-	int ret;
++	int ret = 0;
+ 
+ 	DPRINT_ENTER(VMBUS);
+ 
+ 	nextGpadlHandle = atomic_read(&gVmbusConnection.NextGpadlHandle);
+ 	atomic_inc(&gVmbusConnection.NextGpadlHandle);
+ 
+-	VmbusChannelCreateGpadlHeader(Kbuffer, Size, &msgInfo, &msgCount);
+-	ASSERT(msgInfo != NULL);
+-	ASSERT(msgCount > 0);
++	ret = VmbusChannelCreateGpadlHeader(Kbuffer, Size, &msgInfo, &msgCount);
++	if (ret)
++		return ret;
+ 
+ 	msgInfo->WaitEvent = osd_WaitEventCreate();
++	if (!msgInfo->WaitEvent) {
++		ret = -ENOMEM;
++		goto Cleanup;
++	}
++
+ 	gpadlMsg = (struct vmbus_channel_gpadl_header *)msgInfo->Msg;
+ 	gpadlMsg->Header.MessageType = ChannelMessageGpadlHeader;
+ 	gpadlMsg->ChildRelId = Channel->OfferMsg.ChildRelId;
+@@ -567,9 +586,14 @@ int VmbusChannelTeardownGpadl(struct vmbus_channel *Channel, u32 GpadlHandle)
+ 
+ 	info = kmalloc(sizeof(*info) +
+ 		       sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL);
+-	ASSERT(info != NULL);
++	if (!info)
++		return -ENOMEM;
+ 
+ 	info->WaitEvent = osd_WaitEventCreate();
++	if (!info->WaitEvent) {
++		kfree(info);
++		return -ENOMEM;
++	}
+ 
+ 	msg = (struct vmbus_channel_gpadl_teardown *)info->Msg;
+ 
+@@ -623,7 +647,10 @@ void VmbusChannelClose(struct vmbus_channel *Channel)
+ 	/* Send a closing message */
+ 	info = kmalloc(sizeof(*info) +
+ 		       sizeof(struct vmbus_channel_close_channel), GFP_KERNEL);
+-	ASSERT(info != NULL);
++        /* FIXME: can't do anything other than return here because the
++	 *        function is void */
++	if (!info)
++		return;
+ 
+ 	/* info->waitEvent = osd_WaitEventCreate(); */
+ 

commit 80d11b2ae26543656f7226b44ed9d6a184766e85
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:33 2010 -0400
+
+    Staging: hv: test return value of osd_WaitEventCreate()
+    
+    The return value of osd_WaitEventCreate() was not examined in some
+    places.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/Connection.c b/drivers/staging/hv/Connection.c
+index 1e4111412ab6..e590eb4b6e76 100644
+--- a/drivers/staging/hv/Connection.c
++++ b/drivers/staging/hv/Connection.c
+@@ -98,6 +98,11 @@ int VmbusConnect(void)
+ 	}
+ 
+ 	msgInfo->WaitEvent = osd_WaitEventCreate();
++	if (!msgInfo->WaitEvent) {
++		ret = -ENOMEM;
++		goto Cleanup;
++	}
++
+ 	msg = (struct vmbus_channel_initiate_contact *)msgInfo->Msg;
+ 
+ 	msg->Header.MessageType = ChannelMessageInitiateContact;
+diff --git a/drivers/staging/hv/NetVsc.c b/drivers/staging/hv/NetVsc.c
+index 27516d40b6ed..d3154e711776 100644
+--- a/drivers/staging/hv/NetVsc.c
++++ b/drivers/staging/hv/NetVsc.c
+@@ -749,6 +749,10 @@ static int NetVscOnDeviceAdd(struct hv_device *Device, void *AdditionalInfo)
+ 			      &netDevice->ReceivePacketList);
+ 	}
+ 	netDevice->ChannelInitEvent = osd_WaitEventCreate();
++	if (!netDevice->ChannelInitEvent) {
++		ret = -ENOMEM;
++		goto Cleanup;
++	}
+ 
+ 	/* Open the channel */
+ 	ret = Device->Driver->VmbusChannelInterface.Open(Device,
+diff --git a/drivers/staging/hv/StorVsc.c b/drivers/staging/hv/StorVsc.c
+index 7372317fe836..4d0fbce229e2 100644
+--- a/drivers/staging/hv/StorVsc.c
++++ b/drivers/staging/hv/StorVsc.c
+@@ -199,6 +199,10 @@ static int StorVscChannelInit(struct hv_device *Device)
+ 	 */
+ 	memset(request, 0, sizeof(struct storvsc_request_extension));
+ 	request->WaitEvent = osd_WaitEventCreate();
++	if (!request->WaitEvent) {
++		ret = -ENOMEM;
++		goto nomem;
++	}
+ 
+ 	vstorPacket->Operation = VStorOperationBeginInitialization;
+ 	vstorPacket->Flags = REQUEST_COMPLETION_FLAG;
+@@ -338,7 +342,7 @@ static int StorVscChannelInit(struct hv_device *Device)
+ Cleanup:
+ 	kfree(request->WaitEvent);
+ 	request->WaitEvent = NULL;
+-
++nomem:
+ 	PutStorDevice(Device);
+ 
+ 	DPRINT_EXIT(STORVSC);
+@@ -649,6 +653,10 @@ int StorVscOnHostReset(struct hv_device *Device)
+ 	vstorPacket = &request->VStorPacket;
+ 
+ 	request->WaitEvent = osd_WaitEventCreate();
++	if (!request->WaitEvent) {
++		ret = -ENOMEM;
++		goto Cleanup;
++	}
+ 
+ 	vstorPacket->Operation = VStorOperationResetBus;
+ 	vstorPacket->Flags = REQUEST_COMPLETION_FLAG;

commit 8cad0af9a1a1882cd00f12f8f7c79690f563b1d7
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:32 2010 -0400
+
+    Staging: hv: return correct error values in Connection.c
+    
+    Also check the kzalloc call return value.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/Connection.c b/drivers/staging/hv/Connection.c
+index dbf00560e0ac..1e4111412ab6 100644
+--- a/drivers/staging/hv/Connection.c
++++ b/drivers/staging/hv/Connection.c
+@@ -93,7 +93,7 @@ int VmbusConnect(void)
+ 			  sizeof(struct vmbus_channel_initiate_contact),
+ 			  GFP_KERNEL);
+ 	if (msgInfo == NULL) {
+-		ret = -1;
++		ret = -ENOMEM;
+ 		goto Cleanup;
+ 	}
+ 
+@@ -195,6 +195,8 @@ int VmbusDisconnect(void)
+ 		return -1;
+ 
+ 	msg = kzalloc(sizeof(struct vmbus_channel_message_header), GFP_KERNEL);
++	if (!msg)
++		return -ENOMEM;
+ 
+ 	msg->MessageType = ChannelMessageUnload;
+ 

commit 7e052d98f2bbcaaaa6d509081d78e600927cfe60
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:30 2010 -0400
+
+    Staging: hv: check return value of osd_PageAlloc()
+    
+    The return value of osd_PageAlloc() was checked using an ASSERT().
+    Change that to more useful behaviour.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/Channel.c b/drivers/staging/hv/Channel.c
+index de2ccb1082ce..d939723db335 100644
+--- a/drivers/staging/hv/Channel.c
++++ b/drivers/staging/hv/Channel.c
+@@ -192,7 +192,9 @@ int VmbusChannelOpen(struct vmbus_channel *NewChannel, u32 SendRingBufferSize,
+ 	/* Allocate the ring buffer */
+ 	out = osd_PageAlloc((SendRingBufferSize + RecvRingBufferSize)
+ 			     >> PAGE_SHIFT);
+-	ASSERT(out);
++	if (!out)
++		return -ENOMEM;
++
+ 	ASSERT(((unsigned long)out & (PAGE_SIZE-1)) == 0);
+ 
+ 	in = (void *)((unsigned long)out + SendRingBufferSize);

commit 75910f236a30bded00f078cab994f35a7171c39b
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:31 2010 -0400
+
+    Staging: hv: remove ASSERT()s in ChannelMgt.c
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/ChannelMgmt.c b/drivers/staging/hv/ChannelMgmt.c
+index 445506d45edb..05e6699e3c78 100644
+--- a/drivers/staging/hv/ChannelMgmt.c
++++ b/drivers/staging/hv/ChannelMgmt.c
+@@ -753,9 +753,15 @@ int VmbusChannelRequestOffers(void)
+ 	msgInfo = kmalloc(sizeof(*msgInfo) +
+ 			  sizeof(struct vmbus_channel_message_header),
+ 			  GFP_KERNEL);
+-	ASSERT(msgInfo != NULL);
++	if (!msgInfo)
++		return -ENOMEM;
+ 
+ 	msgInfo->WaitEvent = osd_WaitEventCreate();
++	if (!msgInfo->WaitEvent) {
++		kfree(msgInfo);
++		return -ENOMEM;
++	}
++
+ 	msg = (struct vmbus_channel_message_header *)msgInfo->Msg;
+ 
+ 	msg->MessageType = ChannelMessageRequestOffers;

commit 1e19c054434c7d3ad618129c2ff5c3d81efa6949
+Author: Bill Pemberton 
+Date:   Wed May 5 15:27:29 2010 -0400
+
+    Staging: hv: Remove check for NULL before calling kfree()
+    
+    kfree() knows how to deal with NULL, so there's no reason to check for
+    NULL before passing something to it.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/Hv.c b/drivers/staging/hv/Hv.c
+index bfcb75008bf5..2418651772b8 100644
+--- a/drivers/staging/hv/Hv.c
++++ b/drivers/staging/hv/Hv.c
+@@ -305,11 +305,9 @@ void HvCleanup(void)
+ 
+ 	DPRINT_ENTER(VMBUS);
+ 
+-	if (gHvContext.SignalEventBuffer) {
+-		gHvContext.SignalEventBuffer = NULL;
+-		gHvContext.SignalEventParam = NULL;
+-		kfree(gHvContext.SignalEventBuffer);
+-	}
++	kfree(gHvContext.SignalEventBuffer);
++	gHvContext.SignalEventBuffer = NULL;
++	gHvContext.SignalEventParam = NULL;
+ 
+ 	if (gHvContext.HypercallPage) {
+ 		hypercallMsr.AsUINT64 = 0;

commit 8566ea7c6f9660623a6f04bc73431f761dee32c7
+Author: Bill Pemberton 
+Date:   Mon May 3 17:50:45 2010 -0400
+
+    Staging: hv: move ASSERT(scmnd) to a more useful location
+    
+    There's not much point to make sure scmnd is not NULL after an assert
+    that would dereference scmnd.  The ASSERT()'s should be removed, but
+    until they are at least they at least can be in the right order.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
+index 5e28e4c36434..26b35a6c679a 100644
+--- a/drivers/staging/hv/storvsc_drv.c
++++ b/drivers/staging/hv/storvsc_drv.c
+@@ -386,9 +386,9 @@ static void storvsc_commmand_completion(struct hv_storvsc_request *request)
+ 	struct scsi_sense_hdr sense_hdr;
+ 
+ 	ASSERT(request == &cmd_request->request);
++	ASSERT(scmnd);
+ 	ASSERT((unsigned long)scmnd->host_scribble ==
+ 		(unsigned long)cmd_request);
+-	ASSERT(scmnd);
+ 	ASSERT(scmnd->scsi_done);
+ 
+ 	DPRINT_ENTER(STORVSC_DRV);

commit b1a5fad4c36117b1399ed65899088fcb907e2cbd
+Author: Bill Pemberton 
+Date:   Wed Apr 28 16:40:11 2010 -0400
+
+    Staging: vme: declare vme_calc_slot() as static
+    
+    vme_calc_slot() is not used anywhere other than vme.c so it should be
+    declared as static.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Martyn Welch 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/vme/vme.c b/drivers/staging/vme/vme.c
+index 58aa276764f3..093fbffbf557 100644
+--- a/drivers/staging/vme/vme.c
++++ b/drivers/staging/vme/vme.c
+@@ -1408,7 +1408,7 @@ EXPORT_SYMBOL(vme_unregister_driver);
+ 
+ /* - Bus Registration ------------------------------------------------------ */
+ 
+-int vme_calc_slot(struct device *dev)
++static int vme_calc_slot(struct device *dev)
+ {
+ 	struct vme_bridge *bridge;
+ 	int num;

commit 1fe923ec740ad8d87e616afc50f5b00d88a75ed2
+Author: Bill Pemberton 
+Date:   Wed Apr 28 16:40:10 2010 -0400
+
+    Staging: vme: declare vme_bus_num_mtx static
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Martyn Welch 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/vme/vme.c b/drivers/staging/vme/vme.c
+index 934283a19ca5..58aa276764f3 100644
+--- a/drivers/staging/vme/vme.c
++++ b/drivers/staging/vme/vme.c
+@@ -36,7 +36,7 @@
+ 
+ /* Bitmask and mutex to keep track of bridge numbers */
+ static unsigned int vme_bus_numbers;
+-DEFINE_MUTEX(vme_bus_num_mtx);
++static DEFINE_MUTEX(vme_bus_num_mtx);
+ 
+ static void __exit vme_exit(void);
+ static int __init vme_init(void);

commit 81b571b77134aed29b9725f161dec6a37b48db68
+Author: Bill Pemberton 
+Date:   Tue Apr 27 16:23:48 2010 -0400
+
+    Staging: hv: declare NetVscOnChannelCallback() static
+    
+    NetVscOnChannelCallback() was prototyped as static, but the actual
+    declartion of the function was not static.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/NetVsc.c b/drivers/staging/hv/NetVsc.c
+index a48e6376ce21..27516d40b6ed 100644
+--- a/drivers/staging/hv/NetVsc.c
++++ b/drivers/staging/hv/NetVsc.c
+@@ -1286,7 +1286,7 @@ static void NetVscOnReceiveCompletion(void *Context)
+ 	DPRINT_EXIT(NETVSC);
+ }
+ 
+-void NetVscOnChannelCallback(void *Context)
++static void NetVscOnChannelCallback(void *Context)
+ {
+ 	int ret;
+ 	struct hv_device *device = Context;

commit c6fcf0baa6367fecd3e025253700b64ccff8c1eb
+Author: Bill Pemberton 
+Date:   Tue Apr 27 16:23:47 2010 -0400
+
+    Staging: hv: don't use dynamic sized array
+    
+    NetVscOnChannelCallback() used a dynamic sized array that also made
+    the frame size over 2048.  Replace it with a buffer allocated from
+    kzalloc.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/NetVsc.c b/drivers/staging/hv/NetVsc.c
+index f84942df3bbf..a48e6376ce21 100644
+--- a/drivers/staging/hv/NetVsc.c
++++ b/drivers/staging/hv/NetVsc.c
+@@ -1288,28 +1288,33 @@ static void NetVscOnReceiveCompletion(void *Context)
+ 
+ void NetVscOnChannelCallback(void *Context)
+ {
+-	const int netPacketSize = 2048;
+ 	int ret;
+ 	struct hv_device *device = Context;
+ 	struct netvsc_device *netDevice;
+ 	u32 bytesRecvd;
+ 	u64 requestId;
+-	unsigned char packet[netPacketSize];
++	unsigned char *packet;
+ 	struct vmpacket_descriptor *desc;
+-	unsigned char *buffer = packet;
+-	int bufferlen = netPacketSize;
++	unsigned char *buffer;
++	int bufferlen = NETVSC_PACKET_SIZE;
+ 
+ 
+ 	DPRINT_ENTER(NETVSC);
+ 
+ 	ASSERT(device);
+ 
++	packet = kzalloc(NETVSC_PACKET_SIZE * sizeof(unsigned char),
++			 GFP_KERNEL);
++	if (!packet)
++		return;
++	buffer = packet;
++
+ 	netDevice = GetInboundNetDevice(device);
+ 	if (!netDevice) {
+ 		DPRINT_ERR(NETVSC, "net device (%p) shutting down..."
+ 			   "ignoring inbound packets", netDevice);
+ 		DPRINT_EXIT(NETVSC);
+-		return;
++		goto out;
+ 	}
+ 
+ 	do {
+@@ -1341,17 +1346,17 @@ void NetVscOnChannelCallback(void *Context)
+ 				}
+ 
+ 				/* reset */
+-				if (bufferlen > netPacketSize) {
++				if (bufferlen > NETVSC_PACKET_SIZE) {
+ 					kfree(buffer);
+ 					buffer = packet;
+-					bufferlen = netPacketSize;
++					bufferlen = NETVSC_PACKET_SIZE;
+ 				}
+ 			} else {
+ 				/* reset */
+-				if (bufferlen > netPacketSize) {
++				if (bufferlen > NETVSC_PACKET_SIZE) {
+ 					kfree(buffer);
+ 					buffer = packet;
+-					bufferlen = netPacketSize;
++					bufferlen = NETVSC_PACKET_SIZE;
+ 				}
+ 
+ 				break;
+@@ -1375,5 +1380,7 @@ void NetVscOnChannelCallback(void *Context)
+ 
+ 	PutNetDevice(device);
+ 	DPRINT_EXIT(NETVSC);
++out:
++	kfree(buffer);
+ 	return;
+ }
+diff --git a/drivers/staging/hv/NetVsc.h b/drivers/staging/hv/NetVsc.h
+index 6e0e03494126..a6264db8388a 100644
+--- a/drivers/staging/hv/NetVsc.h
++++ b/drivers/staging/hv/NetVsc.h
+@@ -289,6 +289,7 @@ struct nvsp_message {
+ /* Preallocated receive packets */
+ #define NETVSC_RECEIVE_PACKETLIST_COUNT		256
+ 
++#define NETVSC_PACKET_SIZE                      2048
+ 
+ /* Per netvsc channel-specific */
+ struct netvsc_device {

commit 83897badcb20243465b67a5826dfdda50a052eb5
+Author: Bill Pemberton 
+Date:   Fri Apr 30 09:34:29 2010 -0400
+
+    agp: use NULL instead of 0 when pointer is needed
+    
+    Fixes sparse warning:
+    
+    drivers/char/agp/generic.c:1217:33: warning: Using plain integer as
+    NULL pointer
+    
+    Signed-off-by: Bill Pemberton 
+    CC: linux-kernel@vger.kernel.org
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
+index fb86708e47ed..4b51982fd23a 100644
+--- a/drivers/char/agp/generic.c
++++ b/drivers/char/agp/generic.c
+@@ -1214,7 +1214,7 @@ struct agp_memory *agp_generic_alloc_user(size_t page_count, int type)
+ 		return NULL;
+ 
+ 	for (i = 0; i < page_count; i++)
+-		new->pages[i] = 0;
++		new->pages[i] = NULL;
+ 	new->page_count = 0;
+ 	new->type = type;
+ 	new->num_scratch_pages = pages;

commit 758ef749f3b1a4c5e6ba5b5bca5eae968a2c0c5f
+Author: Bill Pemberton 
+Date:   Fri Apr 30 09:34:38 2010 -0400
+
+    rtc-v3020: make bitfield unsigned
+    
+    Fix sparse warning:
+    
+    include/linux/rtc-v3020.h:18:23: error: dubious one-bit signed bitfield
+    
+    Signed-off-by: Bill Pemberton 
+    CC: p_gortmaker@yahoo.com
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/include/linux/rtc-v3020.h b/include/linux/rtc-v3020.h
+index 8ba646e610d9..e55d82cebf80 100644
+--- a/include/linux/rtc-v3020.h
++++ b/include/linux/rtc-v3020.h
+@@ -15,7 +15,7 @@
+ struct v3020_platform_data {
+ 	int leftshift; /* (1<<(leftshift)) & readl() */
+ 
+-	int use_gpio:1;
++	unsigned int use_gpio:1;
+ 	unsigned int gpio_cs;
+ 	unsigned int gpio_wr;
+ 	unsigned int gpio_rd;

commit 8356dda2a573775b651ed13625d3a9ec48e0116c
+Author: Bill Pemberton 
+Date:   Fri Apr 30 09:34:28 2010 -0400
+
+    PCI: make bitfield unsigned
+    
+    Fix sparse warning:
+    
+    drivers/pci/pci.h:247:25: error: dubious one-bit signed bitfield
+    
+    Signed-off-by: Bill Pemberton 
+    CC: linux-pci@vger.kernel.org
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
+index 4eb10f48d270..f8077b3c8c8c 100644
+--- a/drivers/pci/pci.h
++++ b/drivers/pci/pci.h
+@@ -244,7 +244,7 @@ struct pci_ats {
+ 	int stu;	/* Smallest Translation Unit */
+ 	int qdep;	/* Invalidate Queue Depth */
+ 	int ref_cnt;	/* Physical Function reference count */
+-	int is_enabled:1;	/* Enable bit is set */
++	unsigned int is_enabled:1;	/* Enable bit is set */
+ };
+ 
+ #ifdef CONFIG_PCI_IOV

commit 8ac97b74bca1fc8a63b28cc6121519d1cfa2af99
+Author: Bill Pemberton 
+Date:   Fri Apr 30 09:34:31 2010 -0400
+
+    jbd2: use NULL instead of 0 when pointer is needed
+    
+    Fixes sparse warning:
+    
+    fs/jbd2/journal.c:1892:9: warning: Using plain integer as NULL pointer
+    
+    Signed-off-by: Bill Pemberton 
+    CC: linux-ext4@vger.kernel.org
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index c03d4dce4d76..bc2ff5932769 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -1889,7 +1889,7 @@ static struct kmem_cache *get_slab(size_t size)
+ 	BUG_ON(i >= JBD2_MAX_SLABS);
+ 	if (unlikely(i < 0))
+ 		i = 0;
+-	BUG_ON(jbd2_slab[i] == 0);
++	BUG_ON(jbd2_slab[i] == NULL);
+ 	return jbd2_slab[i];
+ }
+ 

commit c2d45b4da042720ae94648b417d0e051742441d4
+Author: Bill Pemberton 
+Date:   Fri Apr 30 09:34:32 2010 -0400
+
+    cciss: fix shadows sparse warning
+    
+    Fix sparse warnings:
+    
+    drivers/block/cciss.c:1591:37: warning: symbol 'i' shadows an earlier one
+    drivers/block/cciss.c:2437:21: warning: symbol 'i' shadows an earlier one
+    
+    Signed-off-by: Bill Pemberton 
+    Acked-by: Mike Miller 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
+index eb5ff0531cfb..51ceaee98f9f 100644
+--- a/drivers/block/cciss.c
++++ b/drivers/block/cciss.c
+@@ -1588,7 +1588,6 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
+ 
+ 			c->Request = ioc->Request;
+ 			if (ioc->buf_size > 0) {
+-				int i;
+ 				for (i = 0; i < sg_used; i++) {
+ 					temp64.val =
+ 					    pci_map_single(host->pdev, buff[i],
+@@ -2434,7 +2433,7 @@ static int deregister_disk(ctlr_info_t *h, int drv_index,
+ 
+ 	/* if it was the last disk, find the new hightest lun */
+ 	if (clear_all && recalculate_highest_lun) {
+-		int i, newhighest = -1;
++		int newhighest = -1;
+ 		for (i = 0; i <= h->highest_lun; i++) {
+ 			/* if the disk has size > 0, it is available */
+ 			if (h->drv[i] && h->drv[i]->heads)

commit 05be7a868e229b26a5a7de217343f39b4dfed205
+Author: Bill Pemberton 
+Date:   Tue Apr 27 16:20:15 2010 -0400
+
+    doc: Change urls for sparse
+    
+    The location of the sparse web page and git tree were no longer
+    valid.  This changes them to point to the current versions.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/Documentation/sparse.txt b/Documentation/sparse.txt
+index 34c76a55bc04..9b659c79a547 100644
+--- a/Documentation/sparse.txt
++++ b/Documentation/sparse.txt
+@@ -54,12 +54,12 @@ Getting sparse
+ ~~~~~~~~~~~~~~
+ 
+ You can get latest released versions from the Sparse homepage at
+-http://www.kernel.org/pub/linux/kernel/people/josh/sparse/
++https://sparse.wiki.kernel.org/index.php/Main_Page
+ 
+ Alternatively, you can get snapshots of the latest development version
+ of sparse using git to clone..
+ 
+-        git://git.kernel.org/pub/scm/linux/kernel/git/josh/sparse.git
++        git://git.kernel.org/pub/scm/devel/sparse/sparse.git
+ 
+ DaveJ has hourly generated tarballs of the git tree available at..
+ 

commit 2b0b39517d1af5294128dbc2fd7ed39c8effa540
+Author: Bill Pemberton 
+Date:   Fri Apr 16 08:01:20 2010 -0500
+
+    jfs: fix diAllocExt error in resizing filesystem
+    
+    Resizing the filesystem would result in an diAllocExt error in some
+    instances because changes in bmp->db_agsize would not get noticed if
+    goto extendBmap was called.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Dave Kleikamp 
+    Cc: jfs-discussion@lists.sourceforge.net
+    Cc: linux-kernel@vger.kernel.org
+
+diff --git a/fs/jfs/resize.c b/fs/jfs/resize.c
+index 7f24a0bb08ca..1aba0039f1c9 100644
+--- a/fs/jfs/resize.c
++++ b/fs/jfs/resize.c
+@@ -81,6 +81,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
+ 	struct inode *iplist[1];
+ 	struct jfs_superblock *j_sb, *j_sb2;
+ 	uint old_agsize;
++	int agsizechanged = 0;
+ 	struct buffer_head *bh, *bh2;
+ 
+ 	/* If the volume hasn't grown, get out now */
+@@ -333,6 +334,9 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
+ 	 */
+ 	if ((rc = dbExtendFS(ipbmap, XAddress, nblocks)))
+ 		goto error_out;
++
++	agsizechanged |= (bmp->db_agsize != old_agsize);
++
+ 	/*
+ 	 * the map now has extended to cover additional nblocks:
+ 	 * dn_mapsize = oldMapsize + nblocks;
+@@ -432,7 +436,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
+ 	 * will correctly identify the new ag);
+ 	 */
+ 	/* if new AG size the same as old AG size, done! */
+-	if (bmp->db_agsize != old_agsize) {
++	if (agsizechanged) {
+ 		if ((rc = diExtendFS(ipimap, ipbmap)))
+ 			goto error_out;
+ 

commit 2386b331802b1b2664c35f9f4c7aef778aac725f
+Author: Bill Pemberton 
+Date:   Thu Aug 6 15:22:01 2009 -0400
+
+    Staging: serqt_usb2: fix qt_open parameters
+    
+    The parameter list for qt_open() was from the old non usb-serial
+    driver.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c
+index 0fdf8c6dc648..52af44cfbe83 100644
+--- a/drivers/staging/serqt_usb2/serqt_usb2.c
++++ b/drivers/staging/serqt_usb2/serqt_usb2.c
+@@ -874,7 +874,7 @@ static void qt_release(struct usb_serial *serial)
+ }
+ 
+ static int qt_open(struct tty_struct *tty,
+-	    struct usb_serial_port *port, struct file *filp)
++		   struct usb_serial_port *port)
+ {
+ 	struct usb_serial *serial;
+ 	struct quatech_port *quatech_port;

commit 19d7810624d9a05d73c03b567145b7743c22b8a4
+Author: Bill Pemberton 
+Date:   Fri Sep 11 21:46:46 2009 -0400
+
+    Staging: hv: Remove List.h
+    
+    List.h is no longer used and can be removed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/List.h b/drivers/staging/hv/List.h
+deleted file mode 100644
+index 735a938a2189..000000000000
+--- a/drivers/staging/hv/List.h
++++ /dev/null
+@@ -1,263 +0,0 @@
+-/*
+- *
+- * Copyright (c) 2009, Microsoft Corporation.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms and conditions of the GNU General Public License,
+- * version 2, as published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License along with
+- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+- * Place - Suite 330, Boston, MA 02111-1307 USA.
+- *
+- * Authors:
+- *   Haiyang Zhang 
+- *   Hank Janssen  
+- *
+- */
+-
+-
+-#ifndef _LIST_H_
+-#define _LIST_H_
+-
+-/*
+- *
+- *  Doubly-linked list manipulation routines.  Implemented as macros
+- *  but logically these are procedures.
+- *
+- */
+-
+-typedef struct _LIST_ENTRY {
+-	struct _LIST_ENTRY *Flink;
+-	struct _LIST_ENTRY *Blink;
+-} LIST_ENTRY, *PLIST_ENTRY;
+-
+-/*
+- *  void
+- *  InitializeListHead(
+- *      PLIST_ENTRY ListHead
+- *      );
+- */
+-#define INITIALIZE_LIST_HEAD	InitializeListHead
+-
+-#define InitializeListHead(ListHead) (\
+-    (ListHead)->Flink = (ListHead)->Blink = (ListHead))
+-
+-
+-/*
+- *  bool
+- *  IsListEmpty(
+- *      PLIST_ENTRY ListHead
+- *      );
+- */
+-#define IS_LIST_EMPTY			IsListEmpty
+-
+-#define IsListEmpty(ListHead) \
+-    ((ListHead)->Flink == (ListHead))
+-
+-
+-/*
+- *  PLIST_ENTRY
+- *  NextListEntry(
+- *      PLIST_ENTRY Entry
+- *      );
+- */
+-#define	NEXT_LIST_ENTRY			NextListEntry
+-
+-#define NextListEntry(Entry) \
+-    (Entry)->Flink
+-
+-
+-/*
+- *  PLIST_ENTRY
+- *  PrevListEntry(
+- *      PLIST_ENTRY Entry
+- *      );
+- */
+-#define	PREV_LIST_ENTRY			PrevListEntry
+-
+-#define PrevListEntry(Entry) \
+-    (Entry)->Blink
+-
+-
+-/*
+- *  PLIST_ENTRY
+- *  TopListEntry(
+- *      PLIST_ENTRY ListHead
+- *      );
+- */
+-#define	TOP_LIST_ENTRY			TopListEntry
+-
+-#define TopListEntry(ListHead) \
+-    (ListHead)->Flink
+-
+-
+-
+-/*
+- *  PLIST_ENTRY
+- *  RemoveHeadList(
+- *      PLIST_ENTRY ListHead
+- *      );
+- */
+-
+-#define	REMOVE_HEAD_LIST		RemoveHeadList
+-
+-#define RemoveHeadList(ListHead) \
+-    (ListHead)->Flink;\
+-    {RemoveEntryList((ListHead)->Flink)}
+-
+-
+-/*
+- *  PLIST_ENTRY
+- *  RemoveTailList(
+- *      PLIST_ENTRY ListHead
+- *      );
+- */
+-#define	REMOVE_TAIL_LIST		RemoveTailList
+-
+-#define RemoveTailList(ListHead) \
+-    (ListHead)->Blink;\
+-    {RemoveEntryList((ListHead)->Blink)}
+-
+-
+-/*
+- *  void
+- *  RemoveEntryList(
+- *      PLIST_ENTRY Entry
+- *      );
+- */
+-#define	REMOVE_ENTRY_LIST		RemoveEntryList
+-
+-#define RemoveEntryList(Entry) {\
+-    PLIST_ENTRY _EX_Flink = (Entry)->Flink;\
+-    PLIST_ENTRY _EX_Blink = (Entry)->Blink;\
+-    _EX_Blink->Flink = _EX_Flink;\
+-    _EX_Flink->Blink = _EX_Blink;\
+-	}
+-
+-
+-/*
+- *  void
+- *  AttachList(
+- *      PLIST_ENTRY ListHead,
+- *      PLIST_ENTRY ListEntry
+- *      );
+- */
+-#define	ATTACH_LIST		AttachList
+-
+-#define AttachList(ListHead,ListEntry) {\
+-    PLIST_ENTRY _EX_ListHead = (ListHead);\
+-    PLIST_ENTRY _EX_Blink = (ListHead)->Blink;\
+-    (ListEntry)->Blink->Flink = _EX_ListHead;\
+-    _EX_Blink->Flink = (ListEntry);\
+-    _EX_ListHead->Blink = (ListEntry)->Blink;\
+-    (ListEntry)->Blink = _EX_Blink;\
+-    }
+-
+-
+-
+-/*
+- *  void
+- *  InsertTailList(
+- *      PLIST_ENTRY ListHead,
+- *      PLIST_ENTRY Entry
+- *      );
+- */
+-
+-#define	INSERT_TAIL_LIST		InsertTailList
+-
+-#define InsertTailList(ListHead,Entry) {\
+-    PLIST_ENTRY _EX_ListHead = (ListHead);\
+-    PLIST_ENTRY _EX_Blink = (ListHead)->Blink;\
+-    (Entry)->Flink = _EX_ListHead;\
+-    (Entry)->Blink = _EX_Blink;\
+-    _EX_Blink->Flink = (Entry);\
+-    _EX_ListHead->Blink = (Entry);\
+-    }
+-
+-
+-/*
+- *  void
+- *  InsertHeadList(
+- *      PLIST_ENTRY ListHead,
+- *      PLIST_ENTRY Entry
+- *      );
+- */
+-#define	INSERT_HEAD_LIST		InsertHeadList
+-
+-#define InsertHeadList(ListHead,Entry) {\
+-    PLIST_ENTRY _EX_ListHead = (ListHead);\
+-    PLIST_ENTRY _EX_Flink = (ListHead)->Flink;\
+-    (Entry)->Flink = _EX_Flink;\
+-    (Entry)->Blink = _EX_ListHead;\
+-    _EX_Flink->Blink = (Entry);\
+-    _EX_ListHead->Flink = (Entry);\
+-    }
+-
+-
+-/*
+- *  void
+- *  IterateListEntries(
+- *      PLIST_ENTRY anchor,
+- *      PLIST_ENTRY index,
+- *		PLIST_ENTRY listp
+- *      );
+- */
+-
+-#define	ITERATE_LIST_ENTRIES	IterateListEntries
+-
+-#define IterateListEntries(anchor, index, listp) \
+-	(anchor) = (LIST_ENTRY *)(listp); \
+-	for((index) = (anchor)->Flink; (index) != (anchor); (index) = (index)->Flink)
+-
+-
+-
+-/*
+- *  PSINGLE_LIST_ENTRY
+- *  PopEntryList(
+- *      PSINGLE_LIST_ENTRY ListHead
+- *      );
+- */
+-
+-#define	POP_ENTRY_LIST		PopEntryList
+-
+-#define PopEntryList(ListHead) \
+-    (ListHead)->Next;\
+-    {\
+-        PSINGLE_LIST_ENTRY FirstEntry;\
+-        FirstEntry = (ListHead)->Next;\
+-        if (FirstEntry != NULL) {     \
+-            (ListHead)->Next = FirstEntry->Next;\
+-        }                             \
+-    }
+-
+-
+-
+-/*
+- *  void
+- *  PushEntryList(
+- *      PSINGLE_LIST_ENTRY ListHead,
+- *		PSINGLE_LIST_ENTRY Entry
+- *      );
+- */
+-
+-#define	PUSH_ENTRY_LIST			PushEntryList
+-
+-#define PushEntryList(ListHead,Entry) \
+-    (Entry)->Next = (ListHead)->Next; \
+-    (ListHead)->Next = (Entry)
+-
+-#ifndef CONTAINING_RECORD
+-#define CONTAINING_RECORD(address, type, field) ((type *)( \
+-                                                  (char *)(address) - \
+-                                                  (char *)(&((type *)0)->field)))
+-#endif /* CONTAINING_RECORD */
+-
+-#endif /* _LIST_H_ */
+-
+-/* EOF */
+diff --git a/drivers/staging/hv/NetVscApi.h b/drivers/staging/hv/NetVscApi.h
+index 34e8fd79205c..1ce2b74a34a7 100644
+--- a/drivers/staging/hv/NetVscApi.h
++++ b/drivers/staging/hv/NetVscApi.h
+@@ -26,7 +26,6 @@
+ #define _NETVSC_API_H_
+ 
+ #include "VmbusApi.h"
+-#include "List.h"
+ 
+ /* Defines */
+ #define NETVSC_DEVICE_RING_BUFFER_SIZE	(64*PAGE_SIZE)
+diff --git a/drivers/staging/hv/TODO b/drivers/staging/hv/TODO
+index fc754abc3ad6..1e272a77078f 100644
+--- a/drivers/staging/hv/TODO
++++ b/drivers/staging/hv/TODO
+@@ -1,7 +1,6 @@
+ TODO:
+ 	- fix checkpatch warnings/errors
+ 	- fix sparse issues
+-	- remove List.h usage to use in-kernel list.h instead
+ 	- remove RingBuffer.c to us in-kernel ringbuffer functions instead.
+ 	- fix HANDLE usage to be "real" pointers
+ 	- audit the vmbus to verify it is working properly with the

commit 1f5459bcb1d944d3c1b4112fa14cac2eda981db8
+Author: Bill Pemberton 
+Date:   Fri Sep 11 21:46:45 2009 -0400
+
+    Staging: hv: remove use of internal list routines in RndisFilter
+    
+    The hv driver has it's own linked list routines.  This removes them
+    from RndisFilter.c
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/RndisFilter.c b/drivers/staging/hv/RndisFilter.c
+index cfe2f02f319e..26d79975387c 100644
+--- a/drivers/staging/hv/RndisFilter.c
++++ b/drivers/staging/hv/RndisFilter.c
+@@ -47,13 +47,13 @@ struct rndis_device {
+ 	atomic_t NewRequestId;
+ 
+ 	spinlock_t request_lock;
+-	LIST_ENTRY RequestList;
++	struct list_head RequestList;
+ 
+ 	unsigned char HwMacAddr[HW_MACADDR_LEN];
+ };
+ 
+ struct rndis_request {
+-	LIST_ENTRY ListEntry;
++	struct list_head ListEntry;
+ 	struct osd_waitevent *WaitEvent;
+ 
+ 	/*
+@@ -110,7 +110,7 @@ static struct rndis_device *GetRndisDevice(void)
+ 
+ 	spin_lock_init(&device->request_lock);
+ 
+-	INITIALIZE_LIST_HEAD(&device->RequestList);
++	INIT_LIST_HEAD(&device->RequestList);
+ 
+ 	device->State = RNDIS_DEV_UNINITIALIZED;
+ 
+@@ -150,7 +150,7 @@ static struct rndis_request *GetRndisRequest(struct rndis_device *Device,
+ 
+ 	/* Add to the request list */
+ 	spin_lock_irqsave(&Device->request_lock, flags);
+-	INSERT_TAIL_LIST(&Device->RequestList, &request->ListEntry);
++	list_add_tail(&request->ListEntry, &Device->RequestList);
+ 	spin_unlock_irqrestore(&Device->request_lock, flags);
+ 
+ 	return request;
+@@ -162,7 +162,7 @@ static void PutRndisRequest(struct rndis_device *Device,
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&Device->request_lock, flags);
+-	REMOVE_ENTRY_LIST(&Request->ListEntry);
++	list_del(&Request->ListEntry);
+ 	spin_unlock_irqrestore(&Device->request_lock, flags);
+ 
+ 	kfree(Request->WaitEvent);
+@@ -273,8 +273,6 @@ static int RndisFilterSendRequest(struct rndis_device *Device,
+ static void RndisFilterReceiveResponse(struct rndis_device *Device,
+ 				       struct rndis_message *Response)
+ {
+-	LIST_ENTRY *anchor;
+-	LIST_ENTRY *curr;
+ 	struct rndis_request *request = NULL;
+ 	bool found = false;
+ 	unsigned long flags;
+@@ -282,10 +280,7 @@ static void RndisFilterReceiveResponse(struct rndis_device *Device,
+ 	DPRINT_ENTER(NETVSC);
+ 
+ 	spin_lock_irqsave(&Device->request_lock, flags);
+-	ITERATE_LIST_ENTRIES(anchor, curr, &Device->RequestList) {
+-		request = CONTAINING_RECORD(curr, struct rndis_request,
+-					    ListEntry);
+-
++	list_for_each_entry(request, &Device->RequestList, ListEntry) {
+ 		/*
+ 		 * All request/response message contains RequestId as the 1st
+ 		 * field

commit 53af545b277508d6b4829e90546cbd1beef536a9
+Author: Bill Pemberton 
+Date:   Fri Sep 11 21:46:44 2009 -0400
+
+    Staging: hv: remove more usages of internal list routines
+    
+    The hv driver has it's own linked list routines.  This removes them
+    from more places in hv.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/Channel.c b/drivers/staging/hv/Channel.c
+index ed94e3656e71..d649ee169d95 100644
+--- a/drivers/staging/hv/Channel.c
++++ b/drivers/staging/hv/Channel.c
+@@ -247,8 +247,8 @@ int VmbusChannelOpen(struct vmbus_channel *NewChannel, u32 SendRingBufferSize,
+ 		memcpy(openMsg->UserData, UserData, UserDataLen);
+ 
+ 	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
+-	INSERT_TAIL_LIST(&gVmbusConnection.ChannelMsgList,
+-			 &openInfo->MsgListEntry);
++	list_add_tail(&openInfo->MsgListEntry,
++		      &gVmbusConnection.ChannelMsgList);
+ 	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
+ 
+ 	DPRINT_DBG(VMBUS, "Sending channel open msg...");
+@@ -271,7 +271,7 @@ int VmbusChannelOpen(struct vmbus_channel *NewChannel, u32 SendRingBufferSize,
+ 
+ Cleanup:
+ 	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
+-	REMOVE_ENTRY_LIST(&openInfo->MsgListEntry);
++	list_del(&openInfo->MsgListEntry);
+ 	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
+ 
+ 	kfree(openInfo->WaitEvent);
+@@ -362,7 +362,7 @@ static int VmbusChannelCreateGpadlHeader(void *Kbuffer, u32 Size,
+ 			  sizeof(struct gpa_range) + pfnCount * sizeof(u64);
+ 		msgHeader =  kzalloc(msgSize, GFP_KERNEL);
+ 
+-		INITIALIZE_LIST_HEAD(&msgHeader->SubMsgList);
++		INIT_LIST_HEAD(&msgHeader->SubMsgList);
+ 		msgHeader->MessageSize = msgSize;
+ 
+ 		gpaHeader = (struct vmbus_channel_gpadl_header *)msgHeader->Msg;
+@@ -411,8 +411,8 @@ static int VmbusChannelCreateGpadlHeader(void *Kbuffer, u32 Size,
+ 				gpadlBody->Pfn[i] = pfn + pfnSum + i;
+ 
+ 			/* add to msg header */
+-			INSERT_TAIL_LIST(&msgHeader->SubMsgList,
+-					 &msgBody->MsgListEntry);
++			list_add_tail(&msgBody->MsgListEntry,
++				      &msgHeader->SubMsgList);
+ 			pfnSum += pfnCurr;
+ 			pfnLeft -= pfnCurr;
+ 		}
+@@ -457,8 +457,7 @@ int VmbusChannelEstablishGpadl(struct vmbus_channel *Channel, void *Kbuffer,
+ 	struct vmbus_channel_msginfo *msgInfo;
+ 	struct vmbus_channel_msginfo *subMsgInfo;
+ 	u32 msgCount;
+-	LIST_ENTRY *anchor;
+-	LIST_ENTRY *curr;
++	struct list_head *curr;
+ 	u32 nextGpadlHandle;
+ 	unsigned long flags;
+ 	int ret;
+@@ -481,10 +480,10 @@ int VmbusChannelEstablishGpadl(struct vmbus_channel *Channel, void *Kbuffer,
+ 	DumpGpadlHeader(gpadlMsg);
+ 
+ 	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
+-	INSERT_TAIL_LIST(&gVmbusConnection.ChannelMsgList,
+-			 &msgInfo->MsgListEntry);
+-	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
++	list_add_tail(&msgInfo->MsgListEntry,
++		      &gVmbusConnection.ChannelMsgList);
+ 
++	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
+ 	DPRINT_DBG(VMBUS, "buffer %p, size %d msg cnt %d",
+ 		   Kbuffer, Size, msgCount);
+ 
+@@ -499,7 +498,9 @@ int VmbusChannelEstablishGpadl(struct vmbus_channel *Channel, void *Kbuffer,
+ 	}
+ 
+ 	if (msgCount > 1) {
+-		ITERATE_LIST_ENTRIES(anchor, curr, &msgInfo->SubMsgList) {
++		list_for_each(curr, &msgInfo->SubMsgList) {
++
++			/* FIXME: should this use list_entry() instead ? */
+ 			subMsgInfo = (struct vmbus_channel_msginfo *)curr;
+ 			gpadlBody =
+ 			     (struct vmbus_channel_gpadl_body *)subMsgInfo->Msg;
+@@ -532,7 +533,7 @@ int VmbusChannelEstablishGpadl(struct vmbus_channel *Channel, void *Kbuffer,
+ 
+ Cleanup:
+ 	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
+-	REMOVE_ENTRY_LIST(&msgInfo->MsgListEntry);
++	list_del(&msgInfo->MsgListEntry);
+ 	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
+ 
+ 	kfree(msgInfo->WaitEvent);
+@@ -570,7 +571,8 @@ int VmbusChannelTeardownGpadl(struct vmbus_channel *Channel, u32 GpadlHandle)
+ 	msg->Gpadl = GpadlHandle;
+ 
+ 	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
+-	INSERT_TAIL_LIST(&gVmbusConnection.ChannelMsgList, &info->MsgListEntry);
++	list_add_tail(&info->MsgListEntry,
++		      &gVmbusConnection.ChannelMsgList);
+ 	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
+ 
+ 	ret = VmbusPostMessage(msg,
+@@ -584,7 +586,7 @@ int VmbusChannelTeardownGpadl(struct vmbus_channel *Channel, u32 GpadlHandle)
+ 
+ 	/* Received a torndown response */
+ 	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
+-	REMOVE_ENTRY_LIST(&info->MsgListEntry);
++	list_del(&info->MsgListEntry);
+ 	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
+ 
+ 	kfree(info->WaitEvent);
+@@ -651,7 +653,7 @@ void VmbusChannelClose(struct vmbus_channel *Channel)
+ 
+ 	if (Channel->State == CHANNEL_OPEN_STATE) {
+ 		spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
+-		REMOVE_ENTRY_LIST(&Channel->ListEntry);
++		list_del(&Channel->ListEntry);
+ 		spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
+ 
+ 		FreeVmbusChannel(Channel);
+diff --git a/drivers/staging/hv/ChannelMgmt.c b/drivers/staging/hv/ChannelMgmt.c
+index 4a014ea7cf1b..3db62caedcff 100644
+--- a/drivers/staging/hv/ChannelMgmt.c
++++ b/drivers/staging/hv/ChannelMgmt.c
+@@ -20,6 +20,7 @@
+  */
+ #include 
+ #include 
++#include 
+ #include "osd.h"
+ #include "logging.h"
+ #include "VmbusPrivate.h"
+@@ -136,8 +137,6 @@ static void VmbusChannelProcessOffer(void *context)
+ {
+ 	struct vmbus_channel *newChannel = context;
+ 	struct vmbus_channel *channel;
+-	LIST_ENTRY *anchor;
+-	LIST_ENTRY *curr;
+ 	bool fNew = true;
+ 	int ret;
+ 	unsigned long flags;
+@@ -147,10 +146,7 @@ static void VmbusChannelProcessOffer(void *context)
+ 	/* Make sure this is a new offer */
+ 	spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
+ 
+-	ITERATE_LIST_ENTRIES(anchor, curr, &gVmbusConnection.ChannelList) {
+-		channel = CONTAINING_RECORD(curr, struct vmbus_channel,
+-					    ListEntry);
+-
++	list_for_each_entry(channel, &gVmbusConnection.ChannelList, ListEntry) {
+ 		if (!memcmp(&channel->OfferMsg.Offer.InterfaceType,
+ 			    &newChannel->OfferMsg.Offer.InterfaceType,
+ 			    sizeof(struct hv_guid)) &&
+@@ -163,8 +159,8 @@ static void VmbusChannelProcessOffer(void *context)
+ 	}
+ 
+ 	if (fNew)
+-		INSERT_TAIL_LIST(&gVmbusConnection.ChannelList,
+-				 &newChannel->ListEntry);
++		list_add_tail(&newChannel->ListEntry,
++			      &gVmbusConnection.ChannelList);
+ 
+ 	spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
+ 
+@@ -201,7 +197,7 @@ static void VmbusChannelProcessOffer(void *context)
+ 			   newChannel->OfferMsg.ChildRelId);
+ 
+ 		spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
+-		REMOVE_ENTRY_LIST(&newChannel->ListEntry);
++		list_del(&newChannel->ListEntry);
+ 		spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
+ 
+ 		FreeVmbusChannel(newChannel);
+@@ -360,8 +356,7 @@ static void VmbusChannelOnOffersDelivered(
+ static void VmbusChannelOnOpenResult(struct vmbus_channel_message_header *hdr)
+ {
+ 	struct vmbus_channel_open_result *result;
+-	LIST_ENTRY *anchor;
+-	LIST_ENTRY *curr;
++	struct list_head *curr;
+ 	struct vmbus_channel_msginfo *msgInfo;
+ 	struct vmbus_channel_message_header *requestHeader;
+ 	struct vmbus_channel_open_channel *openMsg;
+@@ -377,7 +372,8 @@ static void VmbusChannelOnOpenResult(struct vmbus_channel_message_header *hdr)
+ 	 */
+ 	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
+ 
+-	ITERATE_LIST_ENTRIES(anchor, curr, &gVmbusConnection.ChannelMsgList) {
++	list_for_each(curr, &gVmbusConnection.ChannelMsgList) {
++/* FIXME: this should probably use list_entry() instead */
+ 		msgInfo = (struct vmbus_channel_msginfo *)curr;
+ 		requestHeader = (struct vmbus_channel_message_header *)msgInfo->Msg;
+ 
+@@ -408,8 +404,7 @@ static void VmbusChannelOnOpenResult(struct vmbus_channel_message_header *hdr)
+ static void VmbusChannelOnGpadlCreated(struct vmbus_channel_message_header *hdr)
+ {
+ 	struct vmbus_channel_gpadl_created *gpadlCreated;
+-	LIST_ENTRY *anchor;
+-	LIST_ENTRY *curr;
++	struct list_head *curr;
+ 	struct vmbus_channel_msginfo *msgInfo;
+ 	struct vmbus_channel_message_header *requestHeader;
+ 	struct vmbus_channel_gpadl_header *gpadlHeader;
+@@ -427,7 +422,8 @@ static void VmbusChannelOnGpadlCreated(struct vmbus_channel_message_header *hdr)
+ 	 */
+ 	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
+ 
+-	ITERATE_LIST_ENTRIES(anchor, curr, &gVmbusConnection.ChannelMsgList) {
++	list_for_each(curr, &gVmbusConnection.ChannelMsgList) {
++/* FIXME: this should probably use list_entry() instead */
+ 		msgInfo = (struct vmbus_channel_msginfo *)curr;
+ 		requestHeader = (struct vmbus_channel_message_header *)msgInfo->Msg;
+ 
+@@ -461,8 +457,7 @@ static void VmbusChannelOnGpadlTorndown(
+ 			struct vmbus_channel_message_header *hdr)
+ {
+ 	struct vmbus_channel_gpadl_torndown *gpadlTorndown;
+-	LIST_ENTRY *anchor;
+-	LIST_ENTRY *curr;
++	struct list_head *curr;
+ 	struct vmbus_channel_msginfo *msgInfo;
+ 	struct vmbus_channel_message_header *requestHeader;
+ 	struct vmbus_channel_gpadl_teardown *gpadlTeardown;
+@@ -477,7 +472,8 @@ static void VmbusChannelOnGpadlTorndown(
+ 	 */
+ 	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
+ 
+-	ITERATE_LIST_ENTRIES(anchor, curr, &gVmbusConnection.ChannelMsgList) {
++	list_for_each(curr, &gVmbusConnection.ChannelMsgList) {
++/* FIXME: this should probably use list_entry() instead */
+ 		msgInfo = (struct vmbus_channel_msginfo *)curr;
+ 		requestHeader = (struct vmbus_channel_message_header *)msgInfo->Msg;
+ 
+@@ -508,8 +504,7 @@ static void VmbusChannelOnGpadlTorndown(
+ static void VmbusChannelOnVersionResponse(
+ 		struct vmbus_channel_message_header *hdr)
+ {
+-	LIST_ENTRY *anchor;
+-	LIST_ENTRY *curr;
++	struct list_head *curr;
+ 	struct vmbus_channel_msginfo *msgInfo;
+ 	struct vmbus_channel_message_header *requestHeader;
+ 	struct vmbus_channel_initiate_contact *initiate;
+@@ -521,7 +516,8 @@ static void VmbusChannelOnVersionResponse(
+ 	versionResponse = (struct vmbus_channel_version_response *)hdr;
+ 	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
+ 
+-	ITERATE_LIST_ENTRIES(anchor, curr, &gVmbusConnection.ChannelMsgList) {
++	list_for_each(curr, &gVmbusConnection.ChannelMsgList) {
++/* FIXME: this should probably use list_entry() instead */
+ 		msgInfo = (struct vmbus_channel_msginfo *)curr;
+ 		requestHeader = (struct vmbus_channel_message_header *)msgInfo->Msg;
+ 
+@@ -659,23 +655,19 @@ int VmbusChannelRequestOffers(void)
+  */
+ void VmbusChannelReleaseUnattachedChannels(void)
+ {
+-	LIST_ENTRY *entry;
+-	struct vmbus_channel *channel;
++	struct vmbus_channel *channel, *pos;
+ 	struct vmbus_channel *start = NULL;
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
+ 
+-	while (!IsListEmpty(&gVmbusConnection.ChannelList)) {
+-		entry = TOP_LIST_ENTRY(&gVmbusConnection.ChannelList);
+-		channel = CONTAINING_RECORD(entry, struct vmbus_channel,
+-					    ListEntry);
+-
++	list_for_each_entry_safe(channel, pos, &gVmbusConnection.ChannelList,
++				 ListEntry) {
+ 		if (channel == start)
+ 			break;
+ 
+ 		if (!channel->DeviceObject->Driver) {
+-			REMOVE_ENTRY_LIST(&channel->ListEntry);
++			list_del(&channel->ListEntry);
+ 			DPRINT_INFO(VMBUS,
+ 				    "Releasing unattached device object %p",
+ 				    channel->DeviceObject);
+diff --git a/drivers/staging/hv/ChannelMgmt.h b/drivers/staging/hv/ChannelMgmt.h
+index 0730182fe202..a839d8fe6cec 100644
+--- a/drivers/staging/hv/ChannelMgmt.h
++++ b/drivers/staging/hv/ChannelMgmt.h
+@@ -25,7 +25,7 @@
+ #ifndef _CHANNEL_MGMT_H_
+ #define _CHANNEL_MGMT_H_
+ 
+-#include "List.h"
++#include 
+ #include "RingBuffer.h"
+ #include "VmbusChannelInterface.h"
+ #include "VmbusPacketFormat.h"
+@@ -225,7 +225,7 @@ enum vmbus_channel_state {
+ };
+ 
+ struct vmbus_channel {
+-	LIST_ENTRY ListEntry;
++	struct list_head ListEntry;
+ 
+ 	struct hv_device *DeviceObject;
+ 
+@@ -281,10 +281,10 @@ struct vmbus_channel_debug_info {
+  */
+ struct vmbus_channel_msginfo {
+ 	/* Bookkeeping stuff */
+-	LIST_ENTRY MsgListEntry;
++	struct list_head MsgListEntry;
+ 
+ 	/* So far, this is only used to handle gpadl body message */
+-	LIST_ENTRY SubMsgList;
++	struct list_head SubMsgList;
+ 
+ 	/* Synchronize the request/response if needed */
+ 	struct osd_waitevent *WaitEvent;
+diff --git a/drivers/staging/hv/Connection.c b/drivers/staging/hv/Connection.c
+index e574389615b6..43c2e6855015 100644
+--- a/drivers/staging/hv/Connection.c
++++ b/drivers/staging/hv/Connection.c
+@@ -57,10 +57,10 @@ int VmbusConnect(void)
+ 		goto Cleanup;
+ 	}
+ 
+-	INITIALIZE_LIST_HEAD(&gVmbusConnection.ChannelMsgList);
++	INIT_LIST_HEAD(&gVmbusConnection.ChannelMsgList);
+ 	spin_lock_init(&gVmbusConnection.channelmsg_lock);
+ 
+-	INITIALIZE_LIST_HEAD(&gVmbusConnection.ChannelList);
++	INIT_LIST_HEAD(&gVmbusConnection.ChannelList);
+ 	spin_lock_init(&gVmbusConnection.channel_lock);
+ 
+ 	/*
+@@ -112,8 +112,9 @@ int VmbusConnect(void)
+ 	 * receive the response before returning from this routine
+ 	 */
+ 	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
+-	INSERT_TAIL_LIST(&gVmbusConnection.ChannelMsgList,
+-			 &msgInfo->MsgListEntry);
++	list_add_tail(&msgInfo->MsgListEntry,
++		      &gVmbusConnection.ChannelMsgList);
++
+ 	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
+ 
+ 	DPRINT_DBG(VMBUS, "Vmbus connection - interrupt pfn %llx, "
+@@ -124,14 +125,14 @@ int VmbusConnect(void)
+ 	ret = VmbusPostMessage(msg,
+ 			       sizeof(struct vmbus_channel_initiate_contact));
+ 	if (ret != 0) {
+-		REMOVE_ENTRY_LIST(&msgInfo->MsgListEntry);
++		list_del(&msgInfo->MsgListEntry);
+ 		goto Cleanup;
+ 	}
+ 
+ 	/* Wait for the connection response */
+ 	osd_WaitEventWait(msgInfo->WaitEvent);
+ 
+-	REMOVE_ENTRY_LIST(&msgInfo->MsgListEntry);
++	list_del(&msgInfo->MsgListEntry);
+ 
+ 	/* Check if successful */
+ 	if (msgInfo->Response.VersionResponse.VersionSupported) {
+@@ -223,15 +224,10 @@ struct vmbus_channel *GetChannelFromRelId(u32 relId)
+ {
+ 	struct vmbus_channel *channel;
+ 	struct vmbus_channel *foundChannel  = NULL;
+-	LIST_ENTRY *anchor;
+-	LIST_ENTRY *curr;
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
+-	ITERATE_LIST_ENTRIES(anchor, curr, &gVmbusConnection.ChannelList) {
+-		channel = CONTAINING_RECORD(curr, struct vmbus_channel,
+-					    ListEntry);
+-
++	list_for_each_entry(channel, &gVmbusConnection.ChannelList, ListEntry) {
+ 		if (channel->OfferMsg.ChildRelId == relId) {
+ 			foundChannel = channel;
+ 			break;
+diff --git a/drivers/staging/hv/VmbusPrivate.h b/drivers/staging/hv/VmbusPrivate.h
+index 4aabb974348e..05ad2c9380d5 100644
+--- a/drivers/staging/hv/VmbusPrivate.h
++++ b/drivers/staging/hv/VmbusPrivate.h
+@@ -31,7 +31,7 @@
+ #include "ChannelMgmt.h"
+ #include "ChannelInterface.h"
+ #include "RingBuffer.h"
+-#include "List.h"
++#include 
+ 
+ 
+ /*
+@@ -76,11 +76,11 @@ struct VMBUS_CONNECTION {
+ 	 * is child->parent notification
+ 	 */
+ 	void *MonitorPages;
+-	LIST_ENTRY ChannelMsgList;
++	struct list_head ChannelMsgList;
+ 	spinlock_t channelmsg_lock;
+ 
+ 	/* List of channels */
+-	LIST_ENTRY ChannelList;
++	struct list_head ChannelList;
+ 	spinlock_t channel_lock;
+ 
+ 	struct workqueue_struct *WorkQueue;
+@@ -89,7 +89,7 @@ struct VMBUS_CONNECTION {
+ 
+ struct VMBUS_MSGINFO {
+ 	/* Bookkeeping stuff */
+-	LIST_ENTRY MsgListEntry;
++	struct list_head MsgListEntry;
+ 
+ 	/* Synchronize the request/response if needed */
+ 	struct osd_waitevent *WaitEvent;

commit d29274efb73735c6a94f20214b1e4ea994da8848
+Author: Bill Pemberton 
+Date:   Fri Sep 11 21:46:43 2009 -0400
+
+    Staging: hv: remove use of internal list routines in NetVsc
+    
+    The hv driver has it's own linked list routines.  This removes them
+    from NetVsc and uses the kernels routines instead.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Cc: Haiyang Zhang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/NetVsc.c b/drivers/staging/hv/NetVsc.c
+index 92f956578962..1610b845198f 100644
+--- a/drivers/staging/hv/NetVsc.c
++++ b/drivers/staging/hv/NetVsc.c
+@@ -711,8 +711,7 @@ static int NetVscOnDeviceAdd(struct hv_device *Device, void *AdditionalInfo)
+ 	int ret = 0;
+ 	int i;
+ 	struct netvsc_device *netDevice;
+-	struct hv_netvsc_packet *packet;
+-	LIST_ENTRY *entry;
++	struct hv_netvsc_packet *packet, *pos;
+ 	struct netvsc_driver *netDriver =
+ 				(struct netvsc_driver *)Device->Driver;
+ 
+@@ -732,7 +731,7 @@ static int NetVscOnDeviceAdd(struct hv_device *Device, void *AdditionalInfo)
+ 
+ 	netDevice->SendBufferSize = NETVSC_SEND_BUFFER_SIZE;
+ 
+-	INITIALIZE_LIST_HEAD(&netDevice->ReceivePacketList);
++	INIT_LIST_HEAD(&netDevice->ReceivePacketList);
+ 
+ 	for (i = 0; i < NETVSC_RECEIVE_PACKETLIST_COUNT; i++) {
+ 		packet = kzalloc(sizeof(struct hv_netvsc_packet) +
+@@ -744,9 +743,8 @@ static int NetVscOnDeviceAdd(struct hv_device *Device, void *AdditionalInfo)
+ 				   NETVSC_RECEIVE_PACKETLIST_COUNT, i);
+ 			break;
+ 		}
+-
+-		INSERT_TAIL_LIST(&netDevice->ReceivePacketList,
+-				 &packet->ListEntry);
++		list_add_tail(&packet->ListEntry,
++			      &netDevice->ReceivePacketList);
+ 	}
+ 	netDevice->ChannelInitEvent = osd_WaitEventCreate();
+ 
+@@ -790,11 +788,10 @@ static int NetVscOnDeviceAdd(struct hv_device *Device, void *AdditionalInfo)
+ 	if (netDevice) {
+ 		kfree(netDevice->ChannelInitEvent);
+ 
+-		while (!IsListEmpty(&netDevice->ReceivePacketList)) {
+-			entry = REMOVE_HEAD_LIST(&netDevice->ReceivePacketList);
+-			packet = CONTAINING_RECORD(entry,
+-						   struct hv_netvsc_packet,
+-						   ListEntry);
++		list_for_each_entry_safe(packet, pos,
++					 &netDevice->ReceivePacketList,
++					 ListEntry) {
++			list_del(&packet->ListEntry);
+ 			kfree(packet);
+ 		}
+ 
+@@ -814,8 +811,7 @@ static int NetVscOnDeviceAdd(struct hv_device *Device, void *AdditionalInfo)
+ static int NetVscOnDeviceRemove(struct hv_device *Device)
+ {
+ 	struct netvsc_device *netDevice;
+-	struct hv_netvsc_packet *netvscPacket;
+-	LIST_ENTRY *entry;
++	struct hv_netvsc_packet *netvscPacket, *pos;
+ 
+ 	DPRINT_ENTER(NETVSC);
+ 
+@@ -853,12 +849,9 @@ static int NetVscOnDeviceRemove(struct hv_device *Device)
+ 	Device->Driver->VmbusChannelInterface.Close(Device);
+ 
+ 	/* Release all resources */
+-	while (!IsListEmpty(&netDevice->ReceivePacketList)) {
+-		entry = REMOVE_HEAD_LIST(&netDevice->ReceivePacketList);
+-		netvscPacket = CONTAINING_RECORD(entry,
+-						 struct hv_netvsc_packet,
+-						 ListEntry);
+-
++	list_for_each_entry_safe(netvscPacket, pos,
++				 &netDevice->ReceivePacketList, ListEntry) {
++		list_del(&netvscPacket->ListEntry);
+ 		kfree(netvscPacket);
+ 	}
+ 
+@@ -994,15 +987,14 @@ static void NetVscOnReceive(struct hv_device *Device,
+ 	struct vmtransfer_page_packet_header *vmxferpagePacket;
+ 	struct nvsp_message *nvspPacket;
+ 	struct hv_netvsc_packet *netvscPacket = NULL;
+-	LIST_ENTRY *entry;
+ 	unsigned long start;
+ 	unsigned long end, endVirtual;
+ 	/* struct netvsc_driver *netvscDriver; */
+ 	struct xferpage_packet *xferpagePacket = NULL;
+-	LIST_ENTRY listHead;
+ 	int i, j;
+ 	int count = 0, bytesRemain = 0;
+ 	unsigned long flags;
++	LIST_HEAD(listHead);
+ 
+ 	DPRINT_ENTER(NETVSC);
+ 
+@@ -1052,8 +1044,6 @@ static void NetVscOnReceive(struct hv_device *Device,
+ 	DPRINT_DBG(NETVSC, "xfer page - range count %d",
+ 		   vmxferpagePacket->RangeCount);
+ 
+-	INITIALIZE_LIST_HEAD(&listHead);
+-
+ 	/*
+ 	 * Grab free packets (range count + 1) to represent this xfer
+ 	 * page packet. +1 to represent the xfer page packet itself.
+@@ -1061,14 +1051,8 @@ static void NetVscOnReceive(struct hv_device *Device,
+ 	 * fulfil
+ 	 */
+ 	spin_lock_irqsave(&netDevice->receive_packet_list_lock, flags);
+-	while (!IsListEmpty(&netDevice->ReceivePacketList)) {
+-		entry = REMOVE_HEAD_LIST(&netDevice->ReceivePacketList);
+-		netvscPacket = CONTAINING_RECORD(entry,
+-						 struct hv_netvsc_packet,
+-						 ListEntry);
+-
+-		INSERT_TAIL_LIST(&listHead, &netvscPacket->ListEntry);
+-
++	while (!list_empty(&netDevice->ReceivePacketList)) {
++		list_move_tail(&netDevice->ReceivePacketList, &listHead);
+ 		if (++count == vmxferpagePacket->RangeCount + 1)
+ 			break;
+ 	}
+@@ -1087,13 +1071,8 @@ static void NetVscOnReceive(struct hv_device *Device,
+ 		/* Return it to the freelist */
+ 		spin_lock_irqsave(&netDevice->receive_packet_list_lock, flags);
+ 		for (i = count; i != 0; i--) {
+-			entry = REMOVE_HEAD_LIST(&listHead);
+-			netvscPacket = CONTAINING_RECORD(entry,
+-						struct hv_netvsc_packet,
+-						ListEntry);
+-
+-			INSERT_TAIL_LIST(&netDevice->ReceivePacketList,
+-					 &netvscPacket->ListEntry);
++			list_move_tail(&listHead,
++				       &netDevice->ReceivePacketList);
+ 		}
+ 		spin_unlock_irqrestore(&netDevice->receive_packet_list_lock,
+ 				       flags);
+@@ -1106,9 +1085,10 @@ static void NetVscOnReceive(struct hv_device *Device,
+ 	}
+ 
+ 	/* Remove the 1st packet to represent the xfer page packet itself */
+-	entry = REMOVE_HEAD_LIST(&listHead);
+-	xferpagePacket = CONTAINING_RECORD(entry, struct xferpage_packet,
+-					   ListEntry);
++	xferpagePacket = list_entry(&listHead, struct xferpage_packet,
++				    ListEntry);
++	list_del(&xferpagePacket->ListEntry);
++
+ 	/* This is how much we can satisfy */
+ 	xferpagePacket->Count = count - 1;
+ 	ASSERT(xferpagePacket->Count > 0 && xferpagePacket->Count <=
+@@ -1122,10 +1102,9 @@ static void NetVscOnReceive(struct hv_device *Device,
+ 
+ 	/* Each range represents 1 RNDIS pkt that contains 1 ethernet frame */
+ 	for (i = 0; i < (count - 1); i++) {
+-		entry = REMOVE_HEAD_LIST(&listHead);
+-		netvscPacket = CONTAINING_RECORD(entry,
+-						 struct hv_netvsc_packet,
+-						 ListEntry);
++		netvscPacket = list_entry(&listHead, struct hv_netvsc_packet,
++					  ListEntry);
++		list_del(&netvscPacket->ListEntry);
+ 
+ 		/* Initialize the netvsc packet */
+ 		netvscPacket->XferPagePacket = xferpagePacket;
+@@ -1198,7 +1177,7 @@ static void NetVscOnReceive(struct hv_device *Device,
+ 		NetVscOnReceiveCompletion(netvscPacket->Completion.Recv.ReceiveCompletionContext);
+ 	}
+ 
+-	ASSERT(IsListEmpty(&listHead));
++	ASSERT(list_empty(&listHead));
+ 
+ 	PutNetDevice(Device);
+ 	DPRINT_EXIT(NETVSC);
+@@ -1290,13 +1269,13 @@ static void NetVscOnReceiveCompletion(void *Context)
+ 	if (packet->XferPagePacket->Count == 0) {
+ 		fSendReceiveComp = true;
+ 		transactionId = packet->Completion.Recv.ReceiveCompletionTid;
++		list_add_tail(&packet->XferPagePacket->ListEntry,
++			      &netDevice->ReceivePacketList);
+ 
+-		INSERT_TAIL_LIST(&netDevice->ReceivePacketList,
+-				 &packet->XferPagePacket->ListEntry);
+ 	}
+ 
+ 	/* Put the packet back */
+-	INSERT_TAIL_LIST(&netDevice->ReceivePacketList, &packet->ListEntry);
++	list_add_tail(&packet->ListEntry, &netDevice->ReceivePacketList);
+ 	spin_unlock_irqrestore(&netDevice->receive_packet_list_lock, flags);
+ 
+ 	/* Send a receive completion for the xfer page packet */
+diff --git a/drivers/staging/hv/NetVsc.h b/drivers/staging/hv/NetVsc.h
+index 89ba02b1d607..3e7112f7c755 100644
+--- a/drivers/staging/hv/NetVsc.h
++++ b/drivers/staging/hv/NetVsc.h
+@@ -24,9 +24,9 @@
+ #ifndef _NETVSC_H_
+ #define _NETVSC_H_
+ 
++#include 
+ #include "VmbusPacketFormat.h"
+ #include "VmbusChannelInterface.h"
+-#include "List.h"
+ #include "NetVscApi.h"
+ 
+ 
+@@ -299,7 +299,7 @@ struct netvsc_device {
+ 	 * List of free preallocated hv_netvsc_packet to represent receive
+ 	 * packet
+ 	 */
+-	LIST_ENTRY ReceivePacketList;
++	struct list_head ReceivePacketList;
+ 	spinlock_t receive_packet_list_lock;
+ 
+ 	/* Send buffer allocated by us but manages by NetVSP */
+diff --git a/drivers/staging/hv/NetVscApi.h b/drivers/staging/hv/NetVscApi.h
+index 1cf12871dbc9..34e8fd79205c 100644
+--- a/drivers/staging/hv/NetVscApi.h
++++ b/drivers/staging/hv/NetVscApi.h
+@@ -37,7 +37,7 @@ struct hv_netvsc_packet;
+ 
+ /* Represent the xfer page packet which contains 1 or more netvsc packet */
+ struct xferpage_packet {
+-	LIST_ENTRY ListEntry;
++	struct list_head ListEntry;
+ 
+ 	/* # of netvsc packets this xfer packet contains */
+ 	u32 Count;
+@@ -52,7 +52,7 @@ struct xferpage_packet {
+  */
+ struct hv_netvsc_packet {
+ 	/* Bookkeeping stuff */
+-	LIST_ENTRY ListEntry;
++	struct list_head ListEntry;
+ 
+ 	struct hv_device *Device;
+ 	bool IsDataPacket;

commit 45da89e559219d24a639f24a8d95a6c71d54736f
+Author: Bill Pemberton 
+Date:   Wed Jul 29 17:00:15 2009 -0400
+
+    Staging: hv: remove wrapper functions around kmap_
+    
+    Remove PageMapVirtualAddress() and PageUnmapVirtualAddress() which
+    were wrappers around kmap_atomic() and kunmap_atomic()
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/RndisFilter.c b/drivers/staging/hv/RndisFilter.c
+index 98d82f92c029..362efb0704b2 100644
+--- a/drivers/staging/hv/RndisFilter.c
++++ b/drivers/staging/hv/RndisFilter.c
+@@ -22,7 +22,9 @@
+  */
+ 
+ #include 
+-#include 
++#include 
++#include 
++
+ #include "include/logging.h"
+ 
+ #include "include/NetVscApi.h"
+@@ -518,7 +520,7 @@ RndisFilterOnReceive(
+ 		return -1;
+ 	}
+ 
+-	rndisHeader = (RNDIS_MESSAGE*)PageMapVirtualAddress(Packet->PageBuffers[0].Pfn);
++	rndisHeader = (RNDIS_MESSAGE *)kmap_atomic(pfn_to_page(Packet->PageBuffers[0].Pfn), KM_IRQ0);
+ 
+ 	rndisHeader = (void*)((unsigned long)rndisHeader + Packet->PageBuffers[0].Offset);
+ 
+@@ -528,7 +530,7 @@ RndisFilterOnReceive(
+ #if 0
+ 	if ( Packet->TotalDataBufferLength != rndisHeader->MessageLength )
+ 	{
+-		PageUnmapVirtualAddress((void*)(unsigned long)rndisHeader - Packet->PageBuffers[0].Offset);
++		kunmap_atomic(rndisHeader - Packet->PageBuffers[0].Offset, KM_IRQ0);
+ 
+ 		DPRINT_ERR(NETVSC, "invalid rndis message? (expected %u bytes got %u)...dropping this message!",
+ 			rndisHeader->MessageLength, Packet->TotalDataBufferLength);
+@@ -545,7 +547,7 @@ RndisFilterOnReceive(
+ 
+ 	memcpy(&rndisMessage, rndisHeader, (rndisHeader->MessageLength > sizeof(RNDIS_MESSAGE))?sizeof(RNDIS_MESSAGE):rndisHeader->MessageLength);
+ 
+-	PageUnmapVirtualAddress((void*)(unsigned long)rndisHeader - Packet->PageBuffers[0].Offset);
++	kunmap_atomic(rndisHeader - Packet->PageBuffers[0].Offset, KM_IRQ0);
+ 
+ 	DumpRndisMessage(&rndisMessage);
+ 
+diff --git a/drivers/staging/hv/include/osd.h b/drivers/staging/hv/include/osd.h
+index f8b5411426da..6eeb87ebdac0 100644
+--- a/drivers/staging/hv/include/osd.h
++++ b/drivers/staging/hv/include/osd.h
+@@ -138,10 +138,6 @@ unsigned long Logical2PhysicalAddr(void * LogicalAddr);
+ 
+ unsigned long Virtual2Physical(void * VirtAddr);
+ 
+-void* PageMapVirtualAddress(unsigned long Pfn);
+-void PageUnmapVirtualAddress(void* VirtAddr);
+-
+-
+ int osd_schedule_callback(struct workqueue_struct *wq,
+ 			  void (*func)(void *),
+ 			  void *data);
+diff --git a/drivers/staging/hv/osd.c b/drivers/staging/hv/osd.c
+index f19b9c9ea1e6..ad883c93ec9c 100644
+--- a/drivers/staging/hv/osd.c
++++ b/drivers/staging/hv/osd.c
+@@ -88,17 +88,6 @@ void PageFree(void* page, unsigned int count)
+ 	__free_page(p);*/
+ }
+ 
+-
+-void* PageMapVirtualAddress(unsigned long Pfn)
+-{
+-	return kmap_atomic(pfn_to_page(Pfn), KM_IRQ0);
+-}
+-
+-void PageUnmapVirtualAddress(void* VirtAddr)
+-{
+-	kunmap_atomic(VirtAddr, KM_IRQ0);
+-}
+-
+ void *MemMapIO(unsigned long phys, unsigned long size)
+ {
+ 	return (void*)GetVirtualAddress(phys); /* return ioremap_nocache(phys, size); */

commit b7c947f04888b8bb2dc79832c10ede73c5b8dae2
+Author: Bill Pemberton 
+Date:   Wed Jul 29 17:00:13 2009 -0400
+
+    Staging: hv: remove wrapper function VirtualFree
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/Hv.c b/drivers/staging/hv/Hv.c
+index 36e0d860f14d..334812fdc84b 100644
+--- a/drivers/staging/hv/Hv.c
++++ b/drivers/staging/hv/Hv.c
+@@ -21,7 +21,7 @@
+  *
+  */
+ 
+-
++#include 
+ #include "include/logging.h"
+ #include "VmbusPrivate.h"
+ 
+@@ -330,7 +330,7 @@ HvInit (
+ 			WriteMsr(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
+ 		}
+ 
+-		VirtualFree(virtAddr);
++		vfree(virtAddr);
+ 	}
+ 	ret = -1;
+ 	DPRINT_EXIT(VMBUS);
+@@ -370,7 +370,7 @@ HvCleanup (
+ 		{
+ 			hypercallMsr.AsUINT64 = 0;
+ 			WriteMsr(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
+-			VirtualFree(gHvContext.HypercallPage);
++			vfree(gHvContext.HypercallPage);
+ 			gHvContext.HypercallPage = NULL;
+ 		}
+ 	}
+diff --git a/drivers/staging/hv/include/osd.h b/drivers/staging/hv/include/osd.h
+index bf010fcec6f8..f8b5411426da 100644
+--- a/drivers/staging/hv/include/osd.h
++++ b/drivers/staging/hv/include/osd.h
+@@ -110,7 +110,6 @@ static inline void do_cpuid(unsigned int op, unsigned int *eax, unsigned int *eb
+ /* Osd routines */
+ 
+ extern void* VirtualAllocExec(unsigned int size);
+-extern void VirtualFree(void* VirtAddr);
+ 
+ extern void* PageAlloc(unsigned int count);
+ extern void PageFree(void* page, unsigned int count);
+diff --git a/drivers/staging/hv/osd.c b/drivers/staging/hv/osd.c
+index 1d338721194e..f19b9c9ea1e6 100644
+--- a/drivers/staging/hv/osd.c
++++ b/drivers/staging/hv/osd.c
+@@ -65,11 +65,6 @@ void* VirtualAllocExec(unsigned int size)
+ #endif
+ }
+ 
+-void VirtualFree(void* VirtAddr)
+-{
+-	return vfree(VirtAddr);
+-}
+-
+ void* PageAlloc(unsigned int count)
+ {
+ 	void *p;

commit f4888417083723c4f5cbfdf4895653279ffdc31e
+Author: Bill Pemberton 
+Date:   Wed Jul 29 17:00:12 2009 -0400
+
+    Staging: hv: remove wrapper functions for atomic operations
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/Channel.c b/drivers/staging/hv/Channel.c
+index 4b5e3e40aa3a..61fc345211e9 100644
+--- a/drivers/staging/hv/Channel.c
++++ b/drivers/staging/hv/Channel.c
+@@ -540,8 +540,8 @@ VmbusChannelEstablishGpadl(
+ 
+ 	DPRINT_ENTER(VMBUS);
+ 
+-	nextGpadlHandle = gVmbusConnection.NextGpadlHandle;
+-	InterlockedIncrement((int*)&gVmbusConnection.NextGpadlHandle);
++	nextGpadlHandle = atomic_read(&gVmbusConnection.NextGpadlHandle);
++	atomic_inc(&gVmbusConnection.NextGpadlHandle);
+ 
+ 	VmbusChannelCreateGpadlHeader(Kbuffer, Size, &msgInfo, &msgCount);
+ 	ASSERT(msgInfo != NULL);
+diff --git a/drivers/staging/hv/Connection.c b/drivers/staging/hv/Connection.c
+index b7df7e7a38e6..d7091ad130f3 100644
+--- a/drivers/staging/hv/Connection.c
++++ b/drivers/staging/hv/Connection.c
+@@ -31,7 +31,7 @@
+ 
+ struct VMBUS_CONNECTION gVmbusConnection = {
+ 	.ConnectState		= Disconnected,
+-	.NextGpadlHandle	= 0xE1E10,
++	.NextGpadlHandle	= ATOMIC_INIT(0xE1E10),
+ };
+ 
+ 
+diff --git a/drivers/staging/hv/NetVsc.c b/drivers/staging/hv/NetVsc.c
+index dea54098e510..8e71ce6406e9 100644
+--- a/drivers/staging/hv/NetVsc.c
++++ b/drivers/staging/hv/NetVsc.c
+@@ -122,7 +122,7 @@ static inline struct NETVSC_DEVICE *AllocNetDevice(struct hv_device *Device)
+ 		return NULL;
+ 
+ 	/* Set to 2 to allow both inbound and outbound traffic */
+-	InterlockedCompareExchange(&netDevice->RefCount, 2, 0);
++	atomic_cmpxchg(&netDevice->RefCount, 0, 2);
+ 
+ 	netDevice->Device = Device;
+ 	Device->Extension = netDevice;
+@@ -132,7 +132,7 @@ static inline struct NETVSC_DEVICE *AllocNetDevice(struct hv_device *Device)
+ 
+ static inline void FreeNetDevice(struct NETVSC_DEVICE *Device)
+ {
+-	ASSERT(Device->RefCount == 0);
++	ASSERT(atomic_read(&Device->RefCount) == 0);
+ 	Device->Device->Extension = NULL;
+ 	kfree(Device);
+ }
+@@ -144,14 +144,10 @@ static inline struct NETVSC_DEVICE *GetOutboundNetDevice(struct hv_device *Devic
+ 	struct NETVSC_DEVICE *netDevice;
+ 
+ 	netDevice = (struct NETVSC_DEVICE*)Device->Extension;
+-	if (netDevice && netDevice->RefCount > 1)
+-	{
+-		InterlockedIncrement(&netDevice->RefCount);
+-	}
++	if (netDevice && atomic_read(&netDevice->RefCount) > 1)
++		atomic_inc(&netDevice->RefCount);
+ 	else
+-	{
+ 		netDevice = NULL;
+-	}
+ 
+ 	return netDevice;
+ }
+@@ -162,14 +158,10 @@ static inline struct NETVSC_DEVICE *GetInboundNetDevice(struct hv_device *Device
+ 	struct NETVSC_DEVICE *netDevice;
+ 
+ 	netDevice = (struct NETVSC_DEVICE*)Device->Extension;
+-	if (netDevice && netDevice->RefCount)
+-	{
+-		InterlockedIncrement(&netDevice->RefCount);
+-	}
++	if (netDevice && atomic_read(&netDevice->RefCount))
++		atomic_inc(&netDevice->RefCount);
+ 	else
+-	{
+ 		netDevice = NULL;
+-	}
+ 
+ 	return netDevice;
+ }
+@@ -181,7 +173,7 @@ static inline void PutNetDevice(struct hv_device *Device)
+ 	netDevice = (struct NETVSC_DEVICE*)Device->Extension;
+ 	ASSERT(netDevice);
+ 
+-	InterlockedDecrement(&netDevice->RefCount);
++	atomic_dec(&netDevice->RefCount);
+ }
+ 
+ static inline struct NETVSC_DEVICE *ReleaseOutboundNetDevice(struct hv_device *Device)
+@@ -193,7 +185,7 @@ static inline struct NETVSC_DEVICE *ReleaseOutboundNetDevice(struct hv_device *D
+ 		return NULL;
+ 
+ 	/* Busy wait until the ref drop to 2, then set it to 1 */
+-	while (InterlockedCompareExchange(&netDevice->RefCount, 1, 2) != 2)
++	while (atomic_cmpxchg(&netDevice->RefCount, 2, 1) != 2)
+ 	{
+ 		udelay(100);
+ 	}
+@@ -210,7 +202,7 @@ static inline struct NETVSC_DEVICE *ReleaseInboundNetDevice(struct hv_device *De
+ 		return NULL;
+ 
+ 	/* Busy wait until the ref drop to 1, then set it to 0 */
+-	while (InterlockedCompareExchange(&netDevice->RefCount, 0, 1) != 1)
++	while (atomic_cmpxchg(&netDevice->RefCount, 1, 0) != 1)
+ 	{
+ 		udelay(100);
+ 	}
+@@ -932,9 +924,9 @@ NetVscOnDeviceRemove(
+ 	}
+ 
+ 	/* Wait for all send completions */
+-	while (netDevice->NumOutstandingSends)
++	while (atomic_read(&netDevice->NumOutstandingSends))
+ 	{
+-		DPRINT_INFO(NETVSC, "waiting for %d requests to complete...", netDevice->NumOutstandingSends);
++		DPRINT_INFO(NETVSC, "waiting for %d requests to complete...", atomic_read(&netDevice->NumOutstandingSends));
+ 
+ 		udelay(100);
+ 	}
+@@ -1032,7 +1024,7 @@ NetVscOnSendCompletion(
+ 		/* Notify the layer above us */
+ 		nvscPacket->Completion.Send.OnSendCompletion(nvscPacket->Completion.Send.SendCompletionContext);
+ 
+-		InterlockedDecrement(&netDevice->NumOutstandingSends);
++		atomic_dec(&netDevice->NumOutstandingSends);
+ 	}
+ 	else
+ 	{
+@@ -1101,7 +1093,7 @@ NetVscOnSend(
+ 		DPRINT_ERR(NETVSC, "Unable to send packet %p ret %d", Packet, ret);
+ 	}
+ 
+-	InterlockedIncrement(&netDevice->NumOutstandingSends);
++	atomic_inc(&netDevice->NumOutstandingSends);
+ 	PutNetDevice(Device);
+ 
+ 	DPRINT_EXIT(NETVSC);
+diff --git a/drivers/staging/hv/NetVsc.h b/drivers/staging/hv/NetVsc.h
+index 0389318f2a2c..770a7b46c2c9 100644
+--- a/drivers/staging/hv/NetVsc.h
++++ b/drivers/staging/hv/NetVsc.h
+@@ -57,9 +57,8 @@
+ struct NETVSC_DEVICE {
+ 	struct hv_device *Device;
+ 
+-	int								RefCount;
+-
+-	int								NumOutstandingSends;
++	atomic_t RefCount;
++	atomic_t NumOutstandingSends;
+ 	/* List of free preallocated hv_netvsc_packet to represent receive packet */
+ 	LIST_ENTRY						ReceivePacketList;
+ 	spinlock_t receive_packet_list_lock;
+diff --git a/drivers/staging/hv/RndisFilter.c b/drivers/staging/hv/RndisFilter.c
+index 5b992dfdb0f6..98d82f92c029 100644
+--- a/drivers/staging/hv/RndisFilter.c
++++ b/drivers/staging/hv/RndisFilter.c
+@@ -50,7 +50,7 @@ typedef struct _RNDIS_DEVICE {
+ 
+ 	RNDIS_DEVICE_STATE		State;
+ 	u32					LinkStatus;
+-	u32					NewRequestId;
++	atomic_t NewRequestId;
+ 
+ 	spinlock_t request_lock;
+ 	LIST_ENTRY				RequestList;
+@@ -255,7 +255,7 @@ static inline RNDIS_REQUEST* GetRndisRequest(RNDIS_DEVICE *Device, u32 MessageTy
+ 	/* Set the request id. This field is always after the rndis header for request/response packet types so */
+ 	/* we just used the SetRequest as a template */
+ 	set = &rndisMessage->Message.SetRequest;
+-	set->RequestId = InterlockedIncrement((int*)&Device->NewRequestId);
++	set->RequestId = atomic_inc_return(&Device->NewRequestId);
+ 
+ 	/* Add to the request list */
+ 	spin_lock_irqsave(&Device->request_lock, flags);
+@@ -863,7 +863,7 @@ RndisFilterHaltDevice(
+ 
+ 	/* Setup the rndis set */
+ 	halt = &request->RequestMessage.Message.HaltRequest;
+-	halt->RequestId = InterlockedIncrement((int*)&Device->NewRequestId);
++	halt->RequestId = atomic_inc_return(&Device->NewRequestId);
+ 
+ 	/* Ignore return since this msg is optional. */
+ 	RndisFilterSendRequest(Device, request);
+diff --git a/drivers/staging/hv/StorVsc.c b/drivers/staging/hv/StorVsc.c
+index ef8031fd3850..09e3eda78e36 100644
+--- a/drivers/staging/hv/StorVsc.c
++++ b/drivers/staging/hv/StorVsc.c
+@@ -57,9 +57,9 @@ typedef struct _STORVSC_REQUEST_EXTENSION {
+ typedef struct _STORVSC_DEVICE{
+ 	struct hv_device *Device;
+ 
+-	int							RefCount; /* 0 indicates the device is being destroyed */
++	atomic_t RefCount; /* 0 indicates the device is being destroyed */
+ 
+-	int							NumOutstandingRequests;
++	atomic_t NumOutstandingRequests;
+ 
+ 	/*
+ 	 * Each unique Port/Path/Target represents 1 channel ie scsi
+@@ -155,7 +155,7 @@ static inline STORVSC_DEVICE* AllocStorDevice(struct hv_device *Device)
+ 
+ 	/* Set to 2 to allow both inbound and outbound traffics */
+ 	/* (ie GetStorDevice() and MustGetStorDevice()) to proceed. */
+-	InterlockedCompareExchange(&storDevice->RefCount, 2, 0);
++	atomic_cmpxchg(&storDevice->RefCount, 0, 2);
+ 
+ 	storDevice->Device = Device;
+ 	Device->Extension = storDevice;
+@@ -165,7 +165,7 @@ static inline STORVSC_DEVICE* AllocStorDevice(struct hv_device *Device)
+ 
+ static inline void FreeStorDevice(STORVSC_DEVICE *Device)
+ {
+-	ASSERT(Device->RefCount == 0);
++	ASSERT( atomic_read(&Device->RefCount) == 0);
+ 	kfree(Device);
+ }
+ 
+@@ -175,14 +175,10 @@ static inline STORVSC_DEVICE* GetStorDevice(struct hv_device *Device)
+ 	STORVSC_DEVICE *storDevice;
+ 
+ 	storDevice = (STORVSC_DEVICE*)Device->Extension;
+-	if (storDevice && storDevice->RefCount > 1)
+-	{
+-		InterlockedIncrement(&storDevice->RefCount);
+-	}
++	if (storDevice && atomic_read(&storDevice->RefCount) > 1)
++		atomic_inc(&storDevice->RefCount);
+ 	else
+-	{
+ 		storDevice = NULL;
+-	}
+ 
+ 	return storDevice;
+ }
+@@ -193,14 +189,10 @@ static inline STORVSC_DEVICE* MustGetStorDevice(struct hv_device *Device)
+ 	STORVSC_DEVICE *storDevice;
+ 
+ 	storDevice = (STORVSC_DEVICE*)Device->Extension;
+-	if (storDevice && storDevice->RefCount)
+-	{
+-		InterlockedIncrement(&storDevice->RefCount);
+-	}
++	if (storDevice && atomic_read(&storDevice->RefCount))
++		atomic_inc(&storDevice->RefCount);
+ 	else
+-	{
+ 		storDevice = NULL;
+-	}
+ 
+ 	return storDevice;
+ }
+@@ -212,8 +204,8 @@ static inline void PutStorDevice(struct hv_device *Device)
+ 	storDevice = (STORVSC_DEVICE*)Device->Extension;
+ 	ASSERT(storDevice);
+ 
+-	InterlockedDecrement(&storDevice->RefCount);
+-	ASSERT(storDevice->RefCount);
++	atomic_dec(&storDevice->RefCount);
++	ASSERT(atomic_read(&storDevice->RefCount));
+ }
+ 
+ /* Drop ref count to 1 to effectively disable GetStorDevice() */
+@@ -225,7 +217,7 @@ static inline STORVSC_DEVICE* ReleaseStorDevice(struct hv_device *Device)
+ 	ASSERT(storDevice);
+ 
+ 	/* Busy wait until the ref drop to 2, then set it to 1 */
+-	while (InterlockedCompareExchange(&storDevice->RefCount, 1, 2) != 2)
++	while (atomic_cmpxchg(&storDevice->RefCount, 2, 1) != 2)
+ 	{
+ 		udelay(100);
+ 	}
+@@ -242,7 +234,7 @@ static inline STORVSC_DEVICE* FinalReleaseStorDevice(struct hv_device *Device)
+ 	ASSERT(storDevice);
+ 
+ 	/* Busy wait until the ref drop to 1, then set it to 0 */
+-	while (InterlockedCompareExchange(&storDevice->RefCount, 0, 1) != 1)
++	while (atomic_cmpxchg(&storDevice->RefCount, 1, 0) != 1)
+ 	{
+ 		udelay(100);
+ 	}
+@@ -591,9 +583,9 @@ StorVscOnDeviceRemove(
+ 	 * only allow inbound traffic (responses) to proceed so that
+ 	 * outstanding requests can be completed.
+ 	 */
+-	while (storDevice->NumOutstandingRequests)
++	while (atomic_read(&storDevice->NumOutstandingRequests))
+ 	{
+-		DPRINT_INFO(STORVSC, "waiting for %d requests to complete...", storDevice->NumOutstandingRequests);
++		DPRINT_INFO(STORVSC, "waiting for %d requests to complete...", atomic_read(&storDevice->NumOutstandingRequests));
+ 
+ 		udelay(100);
+ 	}
+@@ -788,7 +780,7 @@ StorVscOnIORequest(
+ 		DPRINT_DBG(STORVSC, "Unable to send packet %p ret %d", vstorPacket, ret);
+ 	}
+ 
+-	InterlockedIncrement(&storDevice->NumOutstandingRequests);
++	atomic_inc(&storDevice->NumOutstandingRequests);
+ 
+ 	PutStorDevice(Device);
+ 
+@@ -877,7 +869,7 @@ StorVscOnIOCompletion(
+ 
+ 	request->OnIOCompletion(request);
+ 
+-	InterlockedDecrement(&storDevice->NumOutstandingRequests);
++	atomic_dec(&storDevice->NumOutstandingRequests);
+ 
+ 	PutStorDevice(Device);
+ 
+diff --git a/drivers/staging/hv/VmbusPrivate.h b/drivers/staging/hv/VmbusPrivate.h
+index bf47408258e0..906736bfd9eb 100644
+--- a/drivers/staging/hv/VmbusPrivate.h
++++ b/drivers/staging/hv/VmbusPrivate.h
+@@ -67,7 +67,7 @@ struct VMBUS_CONNECTION {
+ 
+ 	enum VMBUS_CONNECT_STATE					ConnectState;
+ 
+-	u32								NextGpadlHandle;
++	atomic_t NextGpadlHandle;
+ 
+ 	/*
+ 	 * Represents channel interrupts. Each bit position represents
+diff --git a/drivers/staging/hv/include/osd.h b/drivers/staging/hv/include/osd.h
+index ee44e7e9547d..bf010fcec6f8 100644
+--- a/drivers/staging/hv/include/osd.h
++++ b/drivers/staging/hv/include/osd.h
+@@ -109,10 +109,6 @@ static inline void do_cpuid(unsigned int op, unsigned int *eax, unsigned int *eb
+ 
+ /* Osd routines */
+ 
+-extern int InterlockedIncrement(int *val);
+-extern int InterlockedDecrement(int *val);
+-extern int InterlockedCompareExchange(int *val, int new, int curr);
+-
+ extern void* VirtualAllocExec(unsigned int size);
+ extern void VirtualFree(void* VirtAddr);
+ 
+diff --git a/drivers/staging/hv/osd.c b/drivers/staging/hv/osd.c
+index ff01a7b9c120..1d338721194e 100644
+--- a/drivers/staging/hv/osd.c
++++ b/drivers/staging/hv/osd.c
+@@ -56,26 +56,6 @@ struct osd_callback_struct {
+ 	void *data;
+ };
+ 
+-int InterlockedIncrement(int *val)
+-{
+-	return atomic_inc_return((atomic_t*)val);
+-}
+-
+-int InterlockedDecrement(int *val)
+-{
+-	return atomic_dec_return((atomic_t*)val);
+-}
+-
+-#ifndef atomic_cmpxchg
+-#define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new))
+-#endif
+-int InterlockedCompareExchange(int *val, int new, int curr)
+-{
+-	/* return ((int)cmpxchg(((atomic_t*)val), curr, new)); */
+-	return atomic_cmpxchg((atomic_t*)val, curr, new);
+-
+-}
+-
+ void* VirtualAllocExec(unsigned int size)
+ {
+ #ifdef __x86_64__
+diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c
+index 375dde94eb16..0e13d778c003 100644
+--- a/drivers/staging/hv/vmbus_drv.c
++++ b/drivers/staging/hv/vmbus_drv.c
+@@ -606,7 +606,7 @@ static int vmbus_child_device_register(struct hv_device *root_device_obj, struct
+ 	int ret=0;
+ 	struct device_context *root_device_ctx = to_device_context(root_device_obj);
+ 	struct device_context *child_device_ctx = to_device_context(child_device_obj);
+-	static int device_num=0;
++	static atomic_t device_num = ATOMIC_INIT(0);
+ 
+ 	DPRINT_ENTER(VMBUS_DRV);
+ 
+@@ -623,7 +623,7 @@ static int vmbus_child_device_register(struct hv_device *root_device_obj, struct
+ 	}
+ 
+ 	/* Set the device bus id. Otherwise, device_register()will fail. */
+-	dev_set_name(&child_device_ctx->device, "vmbus_0_%d", InterlockedIncrement(&device_num));
++	dev_set_name(&child_device_ctx->device, "vmbus_0_%d", atomic_inc_return(&device_num));
+ 
+ 	/* The new device belongs to this bus */
+ 	child_device_ctx->device.bus = &g_vmbus_drv.bus; /* device->dev.bus; */

commit 7c369f405bc918f3245c7ee0b0ad6c6b6c750166
+Author: Bill Pemberton 
+Date:   Wed Jul 29 17:00:11 2009 -0400
+
+    Staging: hv: remove wrapper functions for bit operations
+    
+    There were several Bit* functions that did nothing but call the kernel
+    functions with the parameters reversed.  Remove these and call the
+    functions directly.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/Channel.c b/drivers/staging/hv/Channel.c
+index e6337418767a..4b5e3e40aa3a 100644
+--- a/drivers/staging/hv/Channel.c
++++ b/drivers/staging/hv/Channel.c
+@@ -104,12 +104,16 @@ VmbusChannelSetEvent(
+ 	if (Channel->OfferMsg.MonitorAllocated)
+ 	{
+ 		/* Each u32 represents 32 channels */
+-		BitSet((u32*)gVmbusConnection.SendInterruptPage + (Channel->OfferMsg.ChildRelId >> 5), Channel->OfferMsg.ChildRelId & 31);
++		set_bit(Channel->OfferMsg.ChildRelId & 31,
++			(unsigned long *) gVmbusConnection.SendInterruptPage +
++			(Channel->OfferMsg.ChildRelId >> 5) );
+ 
+ 		monitorPage = (HV_MONITOR_PAGE*)gVmbusConnection.MonitorPages;
+ 		monitorPage++; /* Get the child to parent monitor page */
+ 
+-		BitSet((u32*) &monitorPage->TriggerGroup[Channel->MonitorGroup].Pending, Channel->MonitorBit);
++		set_bit(Channel->MonitorBit,
++			(unsigned long *) &monitorPage->TriggerGroup[Channel->MonitorGroup].Pending);
++
+ 	}
+ 	else
+ 	{
+@@ -132,12 +136,14 @@ VmbusChannelClearEvent(
+ 	if (Channel->OfferMsg.MonitorAllocated)
+ 	{
+ 		/* Each u32 represents 32 channels */
+-		BitClear((u32*)gVmbusConnection.SendInterruptPage + (Channel->OfferMsg.ChildRelId >> 5), Channel->OfferMsg.ChildRelId & 31);
++		clear_bit(Channel->OfferMsg.ChildRelId & 31,
++			  (unsigned long *) gVmbusConnection.SendInterruptPage + (Channel->OfferMsg.ChildRelId >> 5));
+ 
+ 		monitorPage = (HV_MONITOR_PAGE*)gVmbusConnection.MonitorPages;
+ 		monitorPage++; /* Get the child to parent monitor page */
+ 
+-		BitClear((u32*) &monitorPage->TriggerGroup[Channel->MonitorGroup].Pending, Channel->MonitorBit);
++		clear_bit(Channel->MonitorBit,
++			  (unsigned long *) &monitorPage->TriggerGroup[Channel->MonitorGroup].Pending);
+ 	}
+ 
+ 	DPRINT_EXIT(VMBUS);
+diff --git a/drivers/staging/hv/Connection.c b/drivers/staging/hv/Connection.c
+index 8d76bd45db87..b7df7e7a38e6 100644
+--- a/drivers/staging/hv/Connection.c
++++ b/drivers/staging/hv/Connection.c
+@@ -358,7 +358,7 @@ VmbusOnEvents(
+ 			{
+ 				for (bit = 0; bit < 32; bit++)
+ 				{
+-					if (BitTestAndClear(&recvInterruptPage[dword], bit))
++					if (test_and_clear_bit(bit, (unsigned long *) &recvInterruptPage[dword]))
+ 					{
+ 						relid = (dword << 5) + bit;
+ 
+@@ -432,7 +432,9 @@ VmbusSetEvent(u32 childRelId)
+ 	DPRINT_ENTER(VMBUS);
+ 
+ 	/* Each u32 represents 32 channels */
+-	BitSet((u32*)gVmbusConnection.SendInterruptPage + (childRelId >> 5), childRelId & 31);
++	set_bit(childRelId & 31,
++		(unsigned long *) gVmbusConnection.SendInterruptPage + (childRelId >> 5));
++
+ 	ret = HvSignalEvent();
+ 
+ 	DPRINT_EXIT(VMBUS);
+diff --git a/drivers/staging/hv/Vmbus.c b/drivers/staging/hv/Vmbus.c
+index 13d7ac80d6b4..fa8c58f57829 100644
+--- a/drivers/staging/hv/Vmbus.c
++++ b/drivers/staging/hv/Vmbus.c
+@@ -511,7 +511,7 @@ VmbusOnISR(
+ 	event = (HV_SYNIC_EVENT_FLAGS*)page_addr + VMBUS_MESSAGE_SINT;
+ 
+ 	/* Since we are a child, we only need to check bit 0 */
+-	if (BitTestAndClear(&event->Flags32[0], 0))
++	if (test_and_clear_bit(0, (unsigned long *) &event->Flags32[0]))
+ 	{
+ 		DPRINT_DBG(VMBUS, "received event %d", event->Flags32[0]);
+ 		ret |= 0x2;
+diff --git a/drivers/staging/hv/include/osd.h b/drivers/staging/hv/include/osd.h
+index e1f37879f52d..ee44e7e9547d 100644
+--- a/drivers/staging/hv/include/osd.h
++++ b/drivers/staging/hv/include/osd.h
+@@ -109,12 +109,6 @@ static inline void do_cpuid(unsigned int op, unsigned int *eax, unsigned int *eb
+ 
+ /* Osd routines */
+ 
+-extern void BitSet(unsigned int* addr, int value);
+-extern void BitClear(unsigned int* addr, int value);
+-extern int BitTest(unsigned int* addr, int value);
+-extern int BitTestAndClear(unsigned int* addr, int value);
+-extern int BitTestAndSet(unsigned int* addr, int value);
+-
+ extern int InterlockedIncrement(int *val);
+ extern int InterlockedDecrement(int *val);
+ extern int InterlockedCompareExchange(int *val, int new, int curr);
+diff --git a/drivers/staging/hv/osd.c b/drivers/staging/hv/osd.c
+index 8ca56a4fce2b..ff01a7b9c120 100644
+--- a/drivers/staging/hv/osd.c
++++ b/drivers/staging/hv/osd.c
+@@ -56,33 +56,6 @@ struct osd_callback_struct {
+ 	void *data;
+ };
+ 
+-
+-void BitSet(unsigned int* addr, int bit)
+-{
+-	set_bit(bit, (unsigned long*)addr);
+-}
+-
+-int BitTest(unsigned int* addr, int bit)
+-{
+-	return test_bit(bit, (unsigned long*)addr);
+-}
+-
+-void BitClear(unsigned int* addr, int bit)
+-{
+-	clear_bit(bit, (unsigned long*)addr);
+-}
+-
+-int BitTestAndClear(unsigned int* addr, int bit)
+-{
+-	return test_and_clear_bit(bit, (unsigned long*)addr);
+-}
+-
+-int BitTestAndSet(unsigned int* addr, int bit)
+-{
+-	return test_and_set_bit(bit, (unsigned long*)addr);
+-}
+-
+-
+ int InterlockedIncrement(int *val)
+ {
+ 	return atomic_inc_return((atomic_t*)val);

commit 420beac4fcc9efd6f7d838ef7cc5693c58c98015
+Author: Bill Pemberton 
+Date:   Wed Jul 29 17:00:10 2009 -0400
+
+    Staging: hv: remove WaitEventClose()
+    
+    All WaitEventClose() close did was call kfree(), so get rid of it and
+    replace it with a call to kfree()
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/Channel.c b/drivers/staging/hv/Channel.c
+index 34c86628422c..e6337418767a 100644
+--- a/drivers/staging/hv/Channel.c
++++ b/drivers/staging/hv/Channel.c
+@@ -309,7 +309,7 @@ VmbusChannelOpen(
+ 	REMOVE_ENTRY_LIST(&openInfo->MsgListEntry);
+ 	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
+ 
+-	WaitEventClose(openInfo->WaitEvent);
++	kfree(openInfo->WaitEvent);
+ 	kfree(openInfo);
+ 
+ 	DPRINT_EXIT(VMBUS);
+@@ -596,7 +596,7 @@ VmbusChannelEstablishGpadl(
+ 	REMOVE_ENTRY_LIST(&msgInfo->MsgListEntry);
+ 	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
+ 
+-	WaitEventClose(msgInfo->WaitEvent);
++	kfree(msgInfo->WaitEvent);
+ 	kfree(msgInfo);
+ 
+ 	DPRINT_EXIT(VMBUS);
+@@ -658,7 +658,7 @@ VmbusChannelTeardownGpadl(
+ 	REMOVE_ENTRY_LIST(&info->MsgListEntry);
+ 	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
+ 
+-	WaitEventClose(info->WaitEvent);
++	kfree(info->WaitEvent);
+ 	kfree(info);
+ 
+ 	DPRINT_EXIT(VMBUS);
+diff --git a/drivers/staging/hv/ChannelMgmt.c b/drivers/staging/hv/ChannelMgmt.c
+index 2c4f4c8e5e72..7ef1f2ba19d2 100644
+--- a/drivers/staging/hv/ChannelMgmt.c
++++ b/drivers/staging/hv/ChannelMgmt.c
+@@ -762,7 +762,7 @@ VmbusChannelRequestOffers(
+ Cleanup:
+ 	if (msgInfo)
+ 	{
+-		WaitEventClose(msgInfo->WaitEvent);
++		kfree(msgInfo->WaitEvent);
+ 		kfree(msgInfo);
+ 	}
+ 
+diff --git a/drivers/staging/hv/Connection.c b/drivers/staging/hv/Connection.c
+index 33e5628b88c3..8d76bd45db87 100644
+--- a/drivers/staging/hv/Connection.c
++++ b/drivers/staging/hv/Connection.c
+@@ -155,7 +155,7 @@ VmbusConnect(void)
+ 	}
+ 
+ 
+-	WaitEventClose(msgInfo->WaitEvent);
++	kfree(msgInfo->WaitEvent);
+ 	kfree(msgInfo);
+ 	DPRINT_EXIT(VMBUS);
+ 
+@@ -183,7 +183,7 @@ VmbusConnect(void)
+ 	if (msgInfo)
+ 	{
+ 		if (msgInfo->WaitEvent)
+-			WaitEventClose(msgInfo->WaitEvent);
++			kfree(msgInfo->WaitEvent);
+ 
+ 		kfree(msgInfo);
+ 	}
+diff --git a/drivers/staging/hv/NetVsc.c b/drivers/staging/hv/NetVsc.c
+index 9445e36423b9..dea54098e510 100644
+--- a/drivers/staging/hv/NetVsc.c
++++ b/drivers/staging/hv/NetVsc.c
+@@ -880,7 +880,7 @@ NetVscOnDeviceAdd(
+ 
+ 	if (netDevice)
+ 	{
+-		WaitEventClose(netDevice->ChannelInitEvent);
++		kfree(netDevice->ChannelInitEvent);
+ 
+ 		while (!IsListEmpty(&netDevice->ReceivePacketList))
+ 		{
+@@ -963,7 +963,7 @@ NetVscOnDeviceRemove(
+ 		kfree(netvscPacket);
+ 	}
+ 
+-	WaitEventClose(netDevice->ChannelInitEvent);
++	kfree(netDevice->ChannelInitEvent);
+ 	FreeNetDevice(netDevice);
+ 
+ 	DPRINT_EXIT(NETVSC);
+diff --git a/drivers/staging/hv/RndisFilter.c b/drivers/staging/hv/RndisFilter.c
+index c6b9dfd2f2e4..5b992dfdb0f6 100644
+--- a/drivers/staging/hv/RndisFilter.c
++++ b/drivers/staging/hv/RndisFilter.c
+@@ -273,7 +273,7 @@ static inline void PutRndisRequest(RNDIS_DEVICE *Device, RNDIS_REQUEST *Request)
+ 	REMOVE_ENTRY_LIST(&Request->ListEntry);
+ 	spin_unlock_irqrestore(&Device->request_lock, flags);
+ 
+-	WaitEventClose(Request->WaitEvent);
++	kfree(Request->WaitEvent);
+ 	kfree(Request);
+ }
+ 
+diff --git a/drivers/staging/hv/StorVsc.c b/drivers/staging/hv/StorVsc.c
+index 1c82e7923ff0..ef8031fd3850 100644
+--- a/drivers/staging/hv/StorVsc.c
++++ b/drivers/staging/hv/StorVsc.c
+@@ -516,7 +516,7 @@ static int StorVscChannelInit(struct hv_device *Device)
+ Cleanup:
+ 	if (request->WaitEvent)
+ 	{
+-		WaitEventClose(request->WaitEvent);
++		kfree(request->WaitEvent);
+ 		request->WaitEvent = NULL;
+ 	}
+ 
+@@ -678,7 +678,7 @@ StorVscOnHostReset(
+ 	/* FIXME: Add a timeout */
+ 	WaitEventWait(request->WaitEvent);
+ 
+-	WaitEventClose(request->WaitEvent);
++	kfree(request->WaitEvent);
+ 	DPRINT_INFO(STORVSC, "host adapter reset completed");
+ 
+ 	/*
+diff --git a/drivers/staging/hv/include/osd.h b/drivers/staging/hv/include/osd.h
+index 4147aba5d314..e1f37879f52d 100644
+--- a/drivers/staging/hv/include/osd.h
++++ b/drivers/staging/hv/include/osd.h
+@@ -134,7 +134,6 @@ extern int TimerStop(struct osd_timer *t);
+ extern void TimerStart(struct osd_timer *t, u32 expirationInUs);
+ 
+ extern struct osd_waitevent *WaitEventCreate(void);
+-extern void WaitEventClose(struct osd_waitevent *waitEvent);
+ extern void WaitEventSet(struct osd_waitevent *waitEvent);
+ extern int	WaitEventWait(struct osd_waitevent *waitEvent);
+ 
+diff --git a/drivers/staging/hv/osd.c b/drivers/staging/hv/osd.c
+index 46cdf88cf9d5..8ca56a4fce2b 100644
+--- a/drivers/staging/hv/osd.c
++++ b/drivers/staging/hv/osd.c
+@@ -216,11 +216,6 @@ struct osd_waitevent *WaitEventCreate(void)
+ 	return wait;
+ }
+ 
+-void WaitEventClose(struct osd_waitevent *waitEvent)
+-{
+-	kfree(waitEvent);
+-}
+-
+ void WaitEventSet(struct osd_waitevent *waitEvent)
+ {
+ 	waitEvent->condition = 1;

commit de65a38406bdf712abc2a845fe1f3db7d1a083ed
+Author: Bill Pemberton 
+Date:   Wed Jul 29 17:00:09 2009 -0400
+
+    Staging: hv: rework use of workqueues in osd
+    
+    Change the usage of workqueues to be consistant with other parts of
+    the kernel.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/ChannelMgmt.c b/drivers/staging/hv/ChannelMgmt.c
+index c5efc6ec6c36..2c4f4c8e5e72 100644
+--- a/drivers/staging/hv/ChannelMgmt.c
++++ b/drivers/staging/hv/ChannelMgmt.c
+@@ -149,7 +149,7 @@ static VMBUS_CHANNEL* AllocVmbusChannel(void)
+ 	}
+ 
+ 	/* channel->dataWorkQueue = WorkQueueCreate("data"); */
+-	channel->ControlWQ = WorkQueueCreate("control");
++	channel->ControlWQ = create_workqueue("hv_vmbus_ctl");
+ 	if (!channel->ControlWQ)
+ 	{
+ 		TimerClose(channel->PollTimer);
+@@ -176,7 +176,7 @@ static inline void ReleaseVmbusChannel(void* Context)
+ 	DPRINT_ENTER(VMBUS);
+ 
+ 	DPRINT_DBG(VMBUS, "releasing channel (%p)", channel);
+-	WorkQueueClose(channel->ControlWQ);
++	destroy_workqueue(channel->ControlWQ);
+ 	DPRINT_DBG(VMBUS, "channel released (%p)", channel);
+ 
+ 	kfree(channel);
+@@ -199,7 +199,8 @@ static void FreeVmbusChannel(VMBUS_CHANNEL* Channel)
+ 
+ 	/* We have to release the channel's workqueue/thread in the vmbus's workqueue/thread context */
+ 	/* ie we can't destroy ourselves. */
+-	WorkQueueQueueWorkItem(gVmbusConnection.WorkQueue, ReleaseVmbusChannel, (void*)Channel);
++	osd_schedule_callback(gVmbusConnection.WorkQueue, ReleaseVmbusChannel,
++			      (void *)Channel);
+ }
+ 
+ 
+@@ -389,7 +390,8 @@ VmbusChannelOnOffer(
+ 	newChannel->MonitorBit = (u8)offer->MonitorId % 32;
+ 
+ 	/* TODO: Make sure the offer comes from our parent partition */
+-	WorkQueueQueueWorkItem(newChannel->ControlWQ, VmbusChannelProcessOffer, newChannel);
++	osd_schedule_callback(newChannel->ControlWQ, VmbusChannelProcessOffer,
++			      newChannel);
+ 
+ 	DPRINT_EXIT(VMBUS);
+ }
+@@ -422,7 +424,9 @@ VmbusChannelOnOfferRescind(
+ 		return;
+ 	}
+ 
+-	WorkQueueQueueWorkItem(channel->ControlWQ, VmbusChannelProcessRescindOffer, channel);
++	osd_schedule_callback(channel->ControlWQ,
++			      VmbusChannelProcessRescindOffer,
++			      channel);
+ 
+ 	DPRINT_EXIT(VMBUS);
+ }
+diff --git a/drivers/staging/hv/Connection.c b/drivers/staging/hv/Connection.c
+index a2888cb46709..33e5628b88c3 100644
+--- a/drivers/staging/hv/Connection.c
++++ b/drivers/staging/hv/Connection.c
+@@ -60,7 +60,12 @@ VmbusConnect(void)
+ 
+ 	/* Initialize the vmbus connection */
+ 	gVmbusConnection.ConnectState = Connecting;
+-	gVmbusConnection.WorkQueue = WorkQueueCreate("vmbusQ");
++	gVmbusConnection.WorkQueue = create_workqueue("hv_vmbus_con");
++	if (!gVmbusConnection.WorkQueue)
++	{
++		ret = -1;
++		goto Cleanup;
++	}
+ 
+ 	INITIALIZE_LIST_HEAD(&gVmbusConnection.ChannelMsgList);
+ 	spin_lock_init(&gVmbusConnection.channelmsg_lock);
+@@ -160,7 +165,8 @@ VmbusConnect(void)
+ 
+ 	gVmbusConnection.ConnectState = Disconnected;
+ 
+-	WorkQueueClose(gVmbusConnection.WorkQueue);
++	if (gVmbusConnection.WorkQueue)
++		destroy_workqueue(gVmbusConnection.WorkQueue);
+ 
+ 	if (gVmbusConnection.InterruptPage)
+ 	{
+@@ -226,7 +232,7 @@ VmbusDisconnect(
+ 
+ 	/* TODO: iterate thru the msg list and free up */
+ 
+-	WorkQueueClose(gVmbusConnection.WorkQueue);
++	destroy_workqueue(gVmbusConnection.WorkQueue);
+ 
+ 	gVmbusConnection.ConnectState = Disconnected;
+ 
+diff --git a/drivers/staging/hv/Vmbus.c b/drivers/staging/hv/Vmbus.c
+index c8e0df6c4805..13d7ac80d6b4 100644
+--- a/drivers/staging/hv/Vmbus.c
++++ b/drivers/staging/hv/Vmbus.c
+@@ -423,7 +423,9 @@ VmbusOnMsgDPC(
+ 			}
+ 
+ 			memcpy(copied, msg, sizeof(HV_MESSAGE));
+-			WorkQueueQueueWorkItem(gVmbusConnection.WorkQueue, VmbusOnChannelMessage, (void*)copied);
++			osd_schedule_callback(gVmbusConnection.WorkQueue,
++					      VmbusOnChannelMessage,
++					      (void *)copied);
+ 		}
+ 
+ 		msg->Header.MessageType = HvMessageTypeNone;
+diff --git a/drivers/staging/hv/include/osd.h b/drivers/staging/hv/include/osd.h
+index 2a47d149b83e..4147aba5d314 100644
+--- a/drivers/staging/hv/include/osd.h
++++ b/drivers/staging/hv/include/osd.h
+@@ -47,7 +47,6 @@ typedef struct _DLIST_ENTRY {
+ 
+ /* typedef unsigned char		GUID[16]; */
+ 
+-typedef void (*PFN_WORKITEM_CALLBACK)(void* context);
+ typedef void (*PFN_TIMER_CALLBACK)(void* context);
+ 
+ 
+@@ -155,12 +154,8 @@ void* PageMapVirtualAddress(unsigned long Pfn);
+ void PageUnmapVirtualAddress(void* VirtAddr);
+ 
+ 
+-extern struct workqueue_struct *WorkQueueCreate(char* name);
+-extern void WorkQueueClose(struct workqueue_struct *hWorkQueue);
+-extern int WorkQueueQueueWorkItem(struct workqueue_struct *hWorkQueue,
+-				  PFN_WORKITEM_CALLBACK workItem,
+-				  void *context);
+-
+-extern void QueueWorkItem(PFN_WORKITEM_CALLBACK workItem, void* context);
++int osd_schedule_callback(struct workqueue_struct *wq,
++			  void (*func)(void *),
++			  void *data);
+ 
+ #endif /* _OSD_H_ */
+diff --git a/drivers/staging/hv/osd.c b/drivers/staging/hv/osd.c
+index ea3e226f178a..46cdf88cf9d5 100644
+--- a/drivers/staging/hv/osd.c
++++ b/drivers/staging/hv/osd.c
+@@ -50,11 +50,11 @@
+ /* Data types */
+ 
+ 
+-typedef struct _WORKITEM {
++struct osd_callback_struct {
+ 	struct work_struct work;
+-	PFN_WORKITEM_CALLBACK callback;
+-	void* context;
+-} WORKITEM;
++	void (*callback)(void *);
++	void *data;
++};
+ 
+ 
+ void BitSet(unsigned int* addr, int bit)
+@@ -269,56 +269,32 @@ unsigned long Virtual2Physical(void * VirtAddr)
+ 	return pfn << PAGE_SHIFT;
+ }
+ 
+-static void WorkItemCallback(struct work_struct *work)
++static void osd_callback_work(struct work_struct *work)
+ {
+-	WORKITEM* w = (WORKITEM*)work;
++	struct osd_callback_struct *cb = container_of(work,
++						      struct osd_callback_struct,
++						      work);
++	(cb->callback)(cb->data);
+ 
+-	w->callback(w->context);
+-
+-	kfree(w);
+-}
+-
+-struct workqueue_struct *WorkQueueCreate(char *name)
+-{
+-	struct workqueue_struct *wq;
+-	wq = create_workqueue(name);
+-	if (unlikely(!wq))
+-		return NULL;
+-	return wq;
++	kfree(cb);
+ }
+ 
+-void WorkQueueClose(struct workqueue_struct *hWorkQueue)
++int osd_schedule_callback(struct workqueue_struct *wq,
++			  void (*func)(void *),
++			  void *data)
+ {
+-	destroy_workqueue(hWorkQueue);
+-	return;
+-}
++	struct osd_callback_struct *cb;
+ 
+-int WorkQueueQueueWorkItem(struct workqueue_struct *hWorkQueue,
+-			   PFN_WORKITEM_CALLBACK workItem,
+-			   void* context)
+-{
+-	WORKITEM* w = kmalloc(sizeof(WORKITEM), GFP_ATOMIC);
+-	if (!w)
++	cb = kmalloc(sizeof(*cb), GFP_KERNEL);
++	if (!cb)
+ 	{
++		printk(KERN_ERR "unable to allocate memory in osd_schedule_callback");
+ 		return -1;
+ 	}
+ 
+-	w->callback = workItem,
+-	w->context = context;
+-	INIT_WORK(&w->work, WorkItemCallback);
+-	return queue_work(hWorkQueue, &w->work);
++	cb->callback = func;
++	cb->data = data;
++	INIT_WORK(&cb->work, osd_callback_work);
++	return queue_work(wq, &cb->work);
+ }
+ 
+-void QueueWorkItem(PFN_WORKITEM_CALLBACK workItem, void* context)
+-{
+-	WORKITEM* w = kmalloc(sizeof(WORKITEM), GFP_ATOMIC);
+-	if (!w)
+-	{
+-		return;
+-	}
+-
+-	w->callback = workItem,
+-	w->context = context;
+-	INIT_WORK(&w->work, WorkItemCallback);
+-	schedule_work(&w->work);
+-}

commit 44f357f835d8a8223b922984eea01aaea29a5f0f
+Author: Bill Pemberton 
+Date:   Tue Jul 28 13:46:26 2009 -0400
+
+    Staging: hv: remove HANDLE typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/Hv.c b/drivers/staging/hv/Hv.c
+index 2a8a652c1f74..0883179cf847 100644
+--- a/drivers/staging/hv/Hv.c
++++ b/drivers/staging/hv/Hv.c
+@@ -235,8 +235,8 @@ HvInit (
+ 
+ 	DPRINT_ENTER(VMBUS);
+ 
+-	memset(gHvContext.synICEventPage, 0, sizeof(HANDLE)*MAX_NUM_CPUS);
+-	memset(gHvContext.synICMessagePage, 0, sizeof(HANDLE)*MAX_NUM_CPUS);
++	memset(gHvContext.synICEventPage, 0, sizeof(void *) * MAX_NUM_CPUS);
++	memset(gHvContext.synICMessagePage, 0, sizeof(void *) * MAX_NUM_CPUS);
+ 
+ 	if (!HvQueryHypervisorPresence())
+ 	{
+diff --git a/drivers/staging/hv/Hv.h b/drivers/staging/hv/Hv.h
+index a62ac33d97d2..b5ea3dcc6f1b 100644
+--- a/drivers/staging/hv/Hv.h
++++ b/drivers/staging/hv/Hv.h
+@@ -119,8 +119,8 @@ typedef struct {
+ 	HV_INPUT_SIGNAL_EVENT_BUFFER *SignalEventBuffer;
+ 	HV_INPUT_SIGNAL_EVENT *SignalEventParam; /* 8-bytes aligned of the buffer above */
+ 
+-	HANDLE	synICMessagePage[MAX_NUM_CPUS];
+-	HANDLE	synICEventPage[MAX_NUM_CPUS];
++	void *synICMessagePage[MAX_NUM_CPUS];
++	void *synICEventPage[MAX_NUM_CPUS];
+ } HV_CONTEXT;
+ 
+ extern HV_CONTEXT gHvContext;
+diff --git a/drivers/staging/hv/include/osd.h b/drivers/staging/hv/include/osd.h
+index 2cd2cf034044..2a47d149b83e 100644
+--- a/drivers/staging/hv/include/osd.h
++++ b/drivers/staging/hv/include/osd.h
+@@ -46,7 +46,6 @@ typedef struct _DLIST_ENTRY {
+ /* Other types */
+ 
+ /* typedef unsigned char		GUID[16]; */
+-typedef void*				HANDLE;
+ 
+ typedef void (*PFN_WORKITEM_CALLBACK)(void* context);
+ typedef void (*PFN_TIMER_CALLBACK)(void* context);

commit 06d2e318b749689d659b3f0c90a157f1ebb31f15
+Author: Bill Pemberton 
+Date:   Tue Jul 28 13:46:25 2009 -0400
+
+    Staging: hv remove TIMER typedef
+    
+    Remove the TIMER typedef and also replace HANDLE types that use
+    the timer calls.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/ChannelMgmt.h b/drivers/staging/hv/ChannelMgmt.h
+index 7cf01738e42c..71173d0f537e 100644
+--- a/drivers/staging/hv/ChannelMgmt.h
++++ b/drivers/staging/hv/ChannelMgmt.h
+@@ -47,7 +47,7 @@ typedef struct _VMBUS_CHANNEL {
+ 
+ 	struct hv_device *DeviceObject;
+ 
+-	HANDLE						PollTimer; /* SA-111 workaround */
++	struct osd_timer *PollTimer; /* SA-111 workaround */
+ 
+ 	VMBUS_CHANNEL_STATE			State;
+ 
+diff --git a/drivers/staging/hv/include/osd.h b/drivers/staging/hv/include/osd.h
+index 470d8021b030..2cd2cf034044 100644
+--- a/drivers/staging/hv/include/osd.h
++++ b/drivers/staging/hv/include/osd.h
+@@ -48,6 +48,10 @@ typedef struct _DLIST_ENTRY {
+ /* typedef unsigned char		GUID[16]; */
+ typedef void*				HANDLE;
+ 
++typedef void (*PFN_WORKITEM_CALLBACK)(void* context);
++typedef void (*PFN_TIMER_CALLBACK)(void* context);
++
++
+ typedef struct {
+ 	unsigned char	Data[16];
+ } GUID;
+@@ -57,9 +61,12 @@ struct osd_waitevent {
+ 	wait_queue_head_t event;
+ };
+ 
++struct osd_timer {
++	struct timer_list timer;
++	PFN_TIMER_CALLBACK callback;
++	void* context;
++};
+ 
+-typedef void (*PFN_WORKITEM_CALLBACK)(void* context);
+-typedef void (*PFN_TIMER_CALLBACK)(void* context);
+ 
+ 
+ #ifdef __x86_64__
+@@ -123,10 +130,10 @@ extern void PageFree(void* page, unsigned int count);
+ extern void* MemMapIO(unsigned long phys, unsigned long size);
+ extern void MemUnmapIO(void* virt);
+ 
+-extern HANDLE TimerCreate(PFN_TIMER_CALLBACK pfnTimerCB, void* context);
+-extern void TimerClose(HANDLE hTimer);
+-extern int TimerStop(HANDLE hTimer);
+-extern void TimerStart(HANDLE hTimer, u32 expirationInUs);
++extern struct osd_timer *TimerCreate(PFN_TIMER_CALLBACK pfnTimerCB, void* context);
++extern void TimerClose(struct osd_timer *t);
++extern int TimerStop(struct osd_timer *t);
++extern void TimerStart(struct osd_timer *t, u32 expirationInUs);
+ 
+ extern struct osd_waitevent *WaitEventCreate(void);
+ extern void WaitEventClose(struct osd_waitevent *waitEvent);
+diff --git a/drivers/staging/hv/osd.c b/drivers/staging/hv/osd.c
+index 50a2ca7dde2e..35c9ac2f3158 100644
+--- a/drivers/staging/hv/osd.c
++++ b/drivers/staging/hv/osd.c
+@@ -49,11 +49,6 @@
+ 
+ /* Data types */
+ 
+-typedef struct _TIMER {
+-	struct timer_list timer;
+-	PFN_TIMER_CALLBACK callback;
+-	void* context;
+-}TIMER;
+ 
+ typedef struct _WORKITEM {
+ 	struct work_struct work;
+@@ -168,14 +163,14 @@ void MemUnmapIO(void *virt)
+ 
+ void TimerCallback(unsigned long data)
+ {
+-	TIMER* t = (TIMER*)data;
++	struct osd_timer *t = (struct osd_timer *) data;
+ 
+ 	t->callback(t->context);
+ }
+ 
+-HANDLE TimerCreate(PFN_TIMER_CALLBACK pfnTimerCB, void* context)
++struct osd_timer *TimerCreate(PFN_TIMER_CALLBACK pfnTimerCB, void* context)
+ {
+-	TIMER* t = kmalloc(sizeof(TIMER), GFP_KERNEL);
++	struct osd_timer *t = kmalloc(sizeof(struct osd_timer), GFP_KERNEL);
+ 	if (!t)
+ 	{
+ 		return NULL;
+@@ -191,25 +186,19 @@ HANDLE TimerCreate(PFN_TIMER_CALLBACK pfnTimerCB, void* context)
+ 	return t;
+ }
+ 
+-void TimerStart(HANDLE hTimer, u32 expirationInUs)
++void TimerStart(struct osd_timer *t, u32 expirationInUs)
+ {
+-	TIMER* t  = (TIMER* )hTimer;
+-
+ 	t->timer.expires = jiffies + usecs_to_jiffies(expirationInUs);
+ 	add_timer(&t->timer);
+ }
+ 
+-int TimerStop(HANDLE hTimer)
++int TimerStop(struct osd_timer *t)
+ {
+-	TIMER* t  = (TIMER* )hTimer;
+-
+ 	return del_timer(&t->timer);
+ }
+ 
+-void TimerClose(HANDLE hTimer)
++void TimerClose(struct osd_timer *t)
+ {
+-	TIMER* t  = (TIMER* )hTimer;
+-
+ 	del_timer(&t->timer);
+ 	kfree(t);
+ }

commit aedb444a577184f7e113e1461fccc0ef10ffde55
+Author: Bill Pemberton 
+Date:   Tue Jul 28 13:46:24 2009 -0400
+
+    Staging: hv: remove WAITEVENT typedef
+    
+    Remove the WAITEVENT typedef and also replace HANDLE types that use
+    the WaitEvent calls with struct osd_waitevent.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/ChannelMgmt.h b/drivers/staging/hv/ChannelMgmt.h
+index 6208cd847e10..7cf01738e42c 100644
+--- a/drivers/staging/hv/ChannelMgmt.h
++++ b/drivers/staging/hv/ChannelMgmt.h
+@@ -115,7 +115,7 @@ typedef struct _VMBUS_CHANNEL_MSGINFO {
+ 	LIST_ENTRY		SubMsgList;
+ 
+ 	/* Synchronize the request/response if needed */
+-	HANDLE			WaitEvent;
++	struct osd_waitevent *WaitEvent;
+ 
+ 	VMBUS_CHANNEL_MESSAGE_RESPONSE Response;
+ 
+diff --git a/drivers/staging/hv/NetVsc.h b/drivers/staging/hv/NetVsc.h
+index f7c16801eb3e..7636654c2528 100644
+--- a/drivers/staging/hv/NetVsc.h
++++ b/drivers/staging/hv/NetVsc.h
+@@ -78,7 +78,7 @@ struct NETVSC_DEVICE {
+ 	PNVSP_1_RECEIVE_BUFFER_SECTION	ReceiveSections;
+ 
+ 	/* Used for NetVSP initialization protocol */
+-	HANDLE							ChannelInitEvent;
++	struct osd_waitevent *ChannelInitEvent;
+ 	NVSP_MESSAGE					ChannelInitPacket;
+ 
+ 	NVSP_MESSAGE					RevokePacket;
+diff --git a/drivers/staging/hv/RndisFilter.c b/drivers/staging/hv/RndisFilter.c
+index cac07273ca30..38b9a11542a6 100644
+--- a/drivers/staging/hv/RndisFilter.c
++++ b/drivers/staging/hv/RndisFilter.c
+@@ -61,7 +61,7 @@ typedef struct _RNDIS_DEVICE {
+ 
+ typedef struct _RNDIS_REQUEST {
+ 	LIST_ENTRY					ListEntry;
+-	HANDLE						WaitEvent;
++	struct osd_waitevent *WaitEvent;
+ 
+ 	/* FIXME: We assumed a fixed size response here. If we do ever need to handle a bigger response, */
+ 	/* we can either define a max response message or add a response buffer variable above this field */
+diff --git a/drivers/staging/hv/StorVsc.c b/drivers/staging/hv/StorVsc.c
+index 26d3f1418318..c55146c6c7a4 100644
+--- a/drivers/staging/hv/StorVsc.c
++++ b/drivers/staging/hv/StorVsc.c
+@@ -47,7 +47,7 @@ typedef struct _STORVSC_REQUEST_EXTENSION {
+ 	struct hv_device *Device;
+ 
+ 	/* Synchronize the request/response if needed */
+-	HANDLE							WaitEvent;
++	struct osd_waitevent *WaitEvent;
+ 
+ 	VSTOR_PACKET					VStorPacket;
+ } STORVSC_REQUEST_EXTENSION;
+diff --git a/drivers/staging/hv/VmbusPrivate.h b/drivers/staging/hv/VmbusPrivate.h
+index 75013bc9e255..bf47408258e0 100644
+--- a/drivers/staging/hv/VmbusPrivate.h
++++ b/drivers/staging/hv/VmbusPrivate.h
+@@ -102,7 +102,7 @@ struct VMBUS_MSGINFO {
+ 	LIST_ENTRY			MsgListEntry;
+ 
+ 	/* Synchronize the request/response if needed */
+-	HANDLE				WaitEvent;
++	struct osd_waitevent *WaitEvent;
+ 
+ 	/* The message itself */
+ 	unsigned char		Msg[0];
+diff --git a/drivers/staging/hv/include/osd.h b/drivers/staging/hv/include/osd.h
+index 6a5675f4b266..470d8021b030 100644
+--- a/drivers/staging/hv/include/osd.h
++++ b/drivers/staging/hv/include/osd.h
+@@ -52,6 +52,12 @@ typedef struct {
+ 	unsigned char	Data[16];
+ } GUID;
+ 
++struct osd_waitevent {
++	int	condition;
++	wait_queue_head_t event;
++};
++
++
+ typedef void (*PFN_WORKITEM_CALLBACK)(void* context);
+ typedef void (*PFN_TIMER_CALLBACK)(void* context);
+ 
+@@ -122,13 +128,13 @@ extern void TimerClose(HANDLE hTimer);
+ extern int TimerStop(HANDLE hTimer);
+ extern void TimerStart(HANDLE hTimer, u32 expirationInUs);
+ 
+-extern HANDLE WaitEventCreate(void);
+-extern void WaitEventClose(HANDLE hWait);
+-extern void WaitEventSet(HANDLE hWait);
+-extern int	WaitEventWait(HANDLE hWait);
++extern struct osd_waitevent *WaitEventCreate(void);
++extern void WaitEventClose(struct osd_waitevent *waitEvent);
++extern void WaitEventSet(struct osd_waitevent *waitEvent);
++extern int	WaitEventWait(struct osd_waitevent *waitEvent);
+ 
+-/* If >0, hWait got signaled. If ==0, timeout. If < 0, error */
+-extern int	WaitEventWaitEx(HANDLE hWait, u32 TimeoutInMs);
++/* If >0, waitEvent got signaled. If ==0, timeout. If < 0, error */
++extern int	WaitEventWaitEx(struct osd_waitevent *waitEvent, u32 TimeoutInMs);
+ 
+ 
+ #define GetVirtualAddress Physical2LogicalAddr
+diff --git a/drivers/staging/hv/osd.c b/drivers/staging/hv/osd.c
+index 4cee746d01c4..50a2ca7dde2e 100644
+--- a/drivers/staging/hv/osd.c
++++ b/drivers/staging/hv/osd.c
+@@ -55,12 +55,6 @@ typedef struct _TIMER {
+ 	void* context;
+ }TIMER;
+ 
+-
+-typedef struct _WAITEVENT {
+-	int	condition;
+-	wait_queue_head_t event;
+-} WAITEVENT;
+-
+ typedef struct _WORKITEM {
+ 	struct work_struct work;
+ 	PFN_WORKITEM_CALLBACK callback;
+@@ -220,9 +214,9 @@ void TimerClose(HANDLE hTimer)
+ 	kfree(t);
+ }
+ 
+-HANDLE WaitEventCreate(void)
++struct osd_waitevent *WaitEventCreate(void)
+ {
+-	WAITEVENT* wait = kmalloc(sizeof(WAITEVENT), GFP_KERNEL);
++	struct osd_waitevent *wait = kmalloc(sizeof(struct osd_waitevent), GFP_KERNEL);
+ 	if (!wait)
+ 	{
+ 		return NULL;
+@@ -233,38 +227,34 @@ HANDLE WaitEventCreate(void)
+ 	return wait;
+ }
+ 
+-void WaitEventClose(HANDLE hWait)
++void WaitEventClose(struct osd_waitevent *waitEvent)
+ {
+-	WAITEVENT* waitEvent = (WAITEVENT* )hWait;
+ 	kfree(waitEvent);
+ }
+ 
+-void WaitEventSet(HANDLE hWait)
++void WaitEventSet(struct osd_waitevent *waitEvent)
+ {
+-	WAITEVENT* waitEvent = (WAITEVENT* )hWait;
+ 	waitEvent->condition = 1;
+ 	wake_up_interruptible(&waitEvent->event);
+ }
+ 
+-int WaitEventWait(HANDLE hWait)
++int WaitEventWait(struct osd_waitevent *waitEvent)
+ {
+ 	int ret=0;
+-	WAITEVENT* waitEvent = (WAITEVENT* )hWait;
+ 
+-	ret= wait_event_interruptible(waitEvent->event,
+-		waitEvent->condition);
++	ret = wait_event_interruptible(waitEvent->event,
++				       waitEvent->condition);
+ 	waitEvent->condition = 0;
+ 	return ret;
+ }
+ 
+-int WaitEventWaitEx(HANDLE hWait, u32 TimeoutInMs)
++int WaitEventWaitEx(struct osd_waitevent *waitEvent, u32 TimeoutInMs)
+ {
+ 	int ret=0;
+-	WAITEVENT* waitEvent = (WAITEVENT* )hWait;
+ 
+-	ret= wait_event_interruptible_timeout(waitEvent->event,
+-											waitEvent->condition,
+-											msecs_to_jiffies(TimeoutInMs));
++	ret = wait_event_interruptible_timeout(waitEvent->event,
++					       waitEvent->condition,
++					       msecs_to_jiffies(TimeoutInMs));
+ 	waitEvent->condition = 0;
+ 	return ret;
+ }

commit b578852955765bfbe12bd31ac1e7888a3deaff40
+Author: Bill Pemberton 
+Date:   Tue Jul 28 13:46:23 2009 -0400
+
+    Staging: hv: comment out blkdev variable in blkvsc_ioctl
+    
+    This variable generated an unused variable warning due to other code
+    in the fuction being commented out.  This comments out the variable
+    defination so that the code compiles without warnings.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c
+index dff950b591c1..988de64be675 100644
+--- a/drivers/staging/hv/blkvsc_drv.c
++++ b/drivers/staging/hv/blkvsc_drv.c
+@@ -1461,7 +1461,7 @@ int blkvsc_getgeo(struct block_device *bd, struct hd_geometry *hg)
+ static int blkvsc_ioctl(struct block_device *bd, fmode_t mode,
+ 			unsigned cmd, unsigned long argument)
+ {
+-	struct block_device_context *blkdev = bd->bd_disk->private_data;
++/*	struct block_device_context *blkdev = bd->bd_disk->private_data; */
+ 	int ret=0;
+ 
+ 	switch (cmd)

commit 2295ba2e7c4141e864f66830b07e635245233a3d
+Author: Bill Pemberton 
+Date:   Tue Jul 28 13:46:22 2009 -0400
+
+    Staging: hv: check return value of driver_for_each_device()
+    
+    The return value of driver_for_each_device() is now checked.  A
+    non-zero value simply generates a warning message, but it's better
+    than not checking at all.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c
+index d595c3b9cdf6..dff950b591c1 100644
+--- a/drivers/staging/hv/blkvsc_drv.c
++++ b/drivers/staging/hv/blkvsc_drv.c
+@@ -218,8 +218,8 @@ void blkvsc_drv_exit(void)
+ {
+ 	STORVSC_DRIVER_OBJECT *storvsc_drv_obj=&g_blkvsc_drv.drv_obj;
+ 	struct driver_context *drv_ctx=&g_blkvsc_drv.drv_ctx;
+-
+ 	struct device *current_dev=NULL;
++	int ret;
+ 
+ 	DPRINT_ENTER(BLKVSC_DRV);
+ 
+@@ -228,7 +228,14 @@ void blkvsc_drv_exit(void)
+ 		current_dev = NULL;
+ 
+ 		/* Get the device */
+-		driver_for_each_device(&drv_ctx->driver, NULL, (void*)¤t_dev, blkvsc_drv_exit_cb);
++		ret = driver_for_each_device(&drv_ctx->driver, NULL,
++					     (void *) ¤t_dev,
++					     blkvsc_drv_exit_cb);
++
++		if (ret)
++			DPRINT_WARN(BLKVSC_DRV,
++				    "driver_for_each_device returned %d", ret);
++
+ 
+ 		if (current_dev == NULL)
+ 			break;
+diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c
+index f0df216028ad..9010f0e2ce68 100644
+--- a/drivers/staging/hv/netvsc_drv.c
++++ b/drivers/staging/hv/netvsc_drv.c
+@@ -638,8 +638,8 @@ void netvsc_drv_exit(void)
+ {
+ 	NETVSC_DRIVER_OBJECT *netvsc_drv_obj=&g_netvsc_drv.drv_obj;
+ 	struct driver_context *drv_ctx=&g_netvsc_drv.drv_ctx;
+-
+ 	struct device *current_dev=NULL;
++	int ret;
+ 
+ 	DPRINT_ENTER(NETVSC_DRV);
+ 
+@@ -648,7 +648,14 @@ void netvsc_drv_exit(void)
+ 		current_dev = NULL;
+ 
+ 		/* Get the device */
+-		driver_for_each_device(&drv_ctx->driver, NULL, (void*)¤t_dev, netvsc_drv_exit_cb);
++		ret = driver_for_each_device(&drv_ctx->driver, NULL,
++					     (void *) ¤t_dev,
++					     netvsc_drv_exit_cb);
++
++		if (ret)
++			DPRINT_WARN(NETVSC_DRV,
++				    "driver_for_each_device returned %d", ret);
++
+ 
+ 		if (current_dev == NULL)
+ 			break;
+diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
+index 385e84bd52cc..120ec52fe9fd 100644
+--- a/drivers/staging/hv/storvsc_drv.c
++++ b/drivers/staging/hv/storvsc_drv.c
+@@ -188,8 +188,8 @@ void storvsc_drv_exit(void)
+ {
+ 	STORVSC_DRIVER_OBJECT *storvsc_drv_obj=&g_storvsc_drv.drv_obj;
+ 	struct driver_context *drv_ctx=&g_storvsc_drv.drv_ctx;
+-
+ 	struct device *current_dev=NULL;
++	int ret;
+ 
+ 	DPRINT_ENTER(STORVSC_DRV);
+ 
+@@ -198,7 +198,13 @@ void storvsc_drv_exit(void)
+ 		current_dev = NULL;
+ 
+ 		/* Get the device */
+-		driver_for_each_device(&drv_ctx->driver, NULL, (void*)¤t_dev, storvsc_drv_exit_cb);
++		ret = driver_for_each_device(&drv_ctx->driver, NULL,
++					     (void *) ¤t_dev,
++					     storvsc_drv_exit_cb);
++
++		if (ret)
++			DPRINT_WARN(STORVSC_DRV,
++				    "driver_for_each_device returned %d", ret);
+ 
+ 		if (current_dev == NULL)
+ 			break;

commit df8d9b1f6deb468dd6752f0cd1029157c15248fd
+Author: Bill Pemberton 
+Date:   Mon Jul 27 16:47:45 2009 -0400
+
+    Staging: hv: Remove WORKQUEUE typedef
+    
+    WORKQUEUE was a wrapper around struct workqueue_struct so just use
+    that instead.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/ChannelMgmt.h b/drivers/staging/hv/ChannelMgmt.h
+index c4aa95c3f39a..5831d1929f7e 100644
+--- a/drivers/staging/hv/ChannelMgmt.h
++++ b/drivers/staging/hv/ChannelMgmt.h
+@@ -64,7 +64,7 @@ typedef struct _VMBUS_CHANNEL {
+ 	RING_BUFFER_INFO			Outbound;	/* send to parent */
+ 	RING_BUFFER_INFO			Inbound;	/* receive from parent */
+ 	spinlock_t inbound_lock;
+-	HANDLE						ControlWQ;
++	struct workqueue_struct *ControlWQ;
+ 
+ 	/* Channel callback are invoked in this workqueue context */
+ 	/* HANDLE						dataWorkQueue; */
+diff --git a/drivers/staging/hv/VmbusPrivate.h b/drivers/staging/hv/VmbusPrivate.h
+index 40e5962dfb72..7182d4d200f3 100644
+--- a/drivers/staging/hv/VmbusPrivate.h
++++ b/drivers/staging/hv/VmbusPrivate.h
+@@ -93,7 +93,7 @@ struct VMBUS_CONNECTION {
+ 	LIST_ENTRY							ChannelList;
+ 	spinlock_t channel_lock;
+ 
+-	HANDLE								WorkQueue;
++	struct workqueue_struct *WorkQueue;
+ };
+ 
+ 
+diff --git a/drivers/staging/hv/include/osd.h b/drivers/staging/hv/include/osd.h
+index faae7cc5ec0d..6a5675f4b266 100644
+--- a/drivers/staging/hv/include/osd.h
++++ b/drivers/staging/hv/include/osd.h
+@@ -143,9 +143,11 @@ void* PageMapVirtualAddress(unsigned long Pfn);
+ void PageUnmapVirtualAddress(void* VirtAddr);
+ 
+ 
+-extern HANDLE WorkQueueCreate(char* name);
+-extern void WorkQueueClose(HANDLE hWorkQueue);
+-extern int WorkQueueQueueWorkItem(HANDLE hWorkQueue, PFN_WORKITEM_CALLBACK workItem, void* context);
++extern struct workqueue_struct *WorkQueueCreate(char* name);
++extern void WorkQueueClose(struct workqueue_struct *hWorkQueue);
++extern int WorkQueueQueueWorkItem(struct workqueue_struct *hWorkQueue,
++				  PFN_WORKITEM_CALLBACK workItem,
++				  void *context);
+ 
+ extern void QueueWorkItem(PFN_WORKITEM_CALLBACK workItem, void* context);
+ 
+diff --git a/drivers/staging/hv/osd.c b/drivers/staging/hv/osd.c
+index e683735706d1..4cee746d01c4 100644
+--- a/drivers/staging/hv/osd.c
++++ b/drivers/staging/hv/osd.c
+@@ -61,10 +61,6 @@ typedef struct _WAITEVENT {
+ 	wait_queue_head_t event;
+ } WAITEVENT;
+ 
+-typedef struct _WORKQUEUE {
+-	struct workqueue_struct *queue;
+-} WORKQUEUE;
+-
+ typedef struct _WORKITEM {
+ 	struct work_struct work;
+ 	PFN_WORKITEM_CALLBACK callback;
+@@ -303,31 +299,25 @@ void WorkItemCallback(struct work_struct *work)
+ 	kfree(w);
+ }
+ 
+-HANDLE WorkQueueCreate(char* name)
++struct workqueue_struct *WorkQueueCreate(char *name)
+ {
+-	WORKQUEUE *wq = kmalloc(sizeof(WORKQUEUE), GFP_KERNEL);
+-	if (!wq)
+-	{
++	struct workqueue_struct *wq;
++	wq = create_workqueue(name);
++	if (unlikely(!wq))
+ 		return NULL;
+-	}
+-	wq->queue = create_workqueue(name);
+-
+ 	return wq;
+ }
+ 
+-void WorkQueueClose(HANDLE hWorkQueue)
++void WorkQueueClose(struct workqueue_struct *hWorkQueue)
+ {
+-	WORKQUEUE *wq = (WORKQUEUE *)hWorkQueue;
+-
+-	destroy_workqueue(wq->queue);
+-
++	destroy_workqueue(hWorkQueue);
+ 	return;
+ }
+ 
+-int WorkQueueQueueWorkItem(HANDLE hWorkQueue, PFN_WORKITEM_CALLBACK workItem, void* context)
++int WorkQueueQueueWorkItem(struct workqueue_struct *hWorkQueue,
++			   PFN_WORKITEM_CALLBACK workItem,
++			   void* context)
+ {
+-	WORKQUEUE *wq = (WORKQUEUE *)hWorkQueue;
+-
+ 	WORKITEM* w = kmalloc(sizeof(WORKITEM), GFP_ATOMIC);
+ 	if (!w)
+ 	{
+@@ -337,7 +327,7 @@ int WorkQueueQueueWorkItem(HANDLE hWorkQueue, PFN_WORKITEM_CALLBACK workItem, vo
+ 	w->callback = workItem,
+ 	w->context = context;
+ 	INIT_WORK(&w->work, WorkItemCallback);
+-	return queue_work(wq->queue, &w->work);
++	return queue_work(hWorkQueue, &w->work);
+ }
+ 
+ void QueueWorkItem(PFN_WORKITEM_CALLBACK workItem, void* context)

commit d1af1db7d6cd7818e92531e170cc65510dd57692
+Author: Bill Pemberton 
+Date:   Mon Jul 27 16:47:44 2009 -0400
+
+    Staging: hv: remove NETVSC_DEVICE typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/NetVsc.c b/drivers/staging/hv/NetVsc.c
+index 111e149d88bb..c0d5dc39ccd1 100644
+--- a/drivers/staging/hv/NetVsc.c
++++ b/drivers/staging/hv/NetVsc.c
+@@ -71,12 +71,12 @@ NetVscInitializeReceiveBufferWithNetVsp(
+ 
+ static int
+ NetVscDestroySendBuffer(
+-	NETVSC_DEVICE	*NetDevice
++	struct NETVSC_DEVICE	*NetDevice
+ 	);
+ 
+ static int
+ NetVscDestroyReceiveBuffer(
+-	NETVSC_DEVICE	*NetDevice
++	struct NETVSC_DEVICE	*NetDevice
+ 	);
+ 
+ static int
+@@ -113,11 +113,11 @@ NetVscSendReceiveCompletion(
+ 	u64			TransactionId
+ 	);
+ 
+-static inline NETVSC_DEVICE* AllocNetDevice(DEVICE_OBJECT *Device)
++static inline struct NETVSC_DEVICE *AllocNetDevice(DEVICE_OBJECT *Device)
+ {
+-	NETVSC_DEVICE *netDevice;
++	struct NETVSC_DEVICE *netDevice;
+ 
+-	netDevice = kzalloc(sizeof(NETVSC_DEVICE), GFP_KERNEL);
++	netDevice = kzalloc(sizeof(struct NETVSC_DEVICE), GFP_KERNEL);
+ 	if (!netDevice)
+ 		return NULL;
+ 
+@@ -130,7 +130,7 @@ static inline NETVSC_DEVICE* AllocNetDevice(DEVICE_OBJECT *Device)
+ 	return netDevice;
+ }
+ 
+-static inline void FreeNetDevice(NETVSC_DEVICE *Device)
++static inline void FreeNetDevice(struct NETVSC_DEVICE *Device)
+ {
+ 	ASSERT(Device->RefCount == 0);
+ 	Device->Device->Extension = NULL;
+@@ -139,11 +139,11 @@ static inline void FreeNetDevice(NETVSC_DEVICE *Device)
+ 
+ 
+ /* Get the net device object iff exists and its refcount > 1 */
+-static inline NETVSC_DEVICE* GetOutboundNetDevice(DEVICE_OBJECT	*Device)
++static inline struct NETVSC_DEVICE *GetOutboundNetDevice(DEVICE_OBJECT	*Device)
+ {
+-	NETVSC_DEVICE *netDevice;
++	struct NETVSC_DEVICE *netDevice;
+ 
+-	netDevice = (NETVSC_DEVICE*)Device->Extension;
++	netDevice = (struct NETVSC_DEVICE*)Device->Extension;
+ 	if (netDevice && netDevice->RefCount > 1)
+ 	{
+ 		InterlockedIncrement(&netDevice->RefCount);
+@@ -157,11 +157,11 @@ static inline NETVSC_DEVICE* GetOutboundNetDevice(DEVICE_OBJECT	*Device)
+ }
+ 
+ /* Get the net device object iff exists and its refcount > 0 */
+-static inline NETVSC_DEVICE* GetInboundNetDevice(DEVICE_OBJECT	*Device)
++static inline struct NETVSC_DEVICE *GetInboundNetDevice(DEVICE_OBJECT	*Device)
+ {
+-	NETVSC_DEVICE *netDevice;
++	struct NETVSC_DEVICE *netDevice;
+ 
+-	netDevice = (NETVSC_DEVICE*)Device->Extension;
++	netDevice = (struct NETVSC_DEVICE*)Device->Extension;
+ 	if (netDevice && netDevice->RefCount)
+ 	{
+ 		InterlockedIncrement(&netDevice->RefCount);
+@@ -176,19 +176,19 @@ static inline NETVSC_DEVICE* GetInboundNetDevice(DEVICE_OBJECT	*Device)
+ 
+ static inline void PutNetDevice(DEVICE_OBJECT *Device)
+ {
+-	NETVSC_DEVICE *netDevice;
++	struct NETVSC_DEVICE *netDevice;
+ 
+-	netDevice = (NETVSC_DEVICE*)Device->Extension;
++	netDevice = (struct NETVSC_DEVICE*)Device->Extension;
+ 	ASSERT(netDevice);
+ 
+ 	InterlockedDecrement(&netDevice->RefCount);
+ }
+ 
+-static inline NETVSC_DEVICE* ReleaseOutboundNetDevice(DEVICE_OBJECT *Device)
++static inline struct NETVSC_DEVICE *ReleaseOutboundNetDevice(DEVICE_OBJECT *Device)
+ {
+-	NETVSC_DEVICE *netDevice;
++	struct NETVSC_DEVICE *netDevice;
+ 
+-	netDevice = (NETVSC_DEVICE*)Device->Extension;
++	netDevice = (struct NETVSC_DEVICE*)Device->Extension;
+ 	if (netDevice == NULL)
+ 		return NULL;
+ 
+@@ -201,11 +201,11 @@ static inline NETVSC_DEVICE* ReleaseOutboundNetDevice(DEVICE_OBJECT *Device)
+ 	return netDevice;
+ }
+ 
+-static inline NETVSC_DEVICE* ReleaseInboundNetDevice(DEVICE_OBJECT *Device)
++static inline struct NETVSC_DEVICE *ReleaseInboundNetDevice(DEVICE_OBJECT *Device)
+ {
+-	NETVSC_DEVICE *netDevice;
++	struct NETVSC_DEVICE *netDevice;
+ 
+-	netDevice = (NETVSC_DEVICE*)Device->Extension;
++	netDevice = (struct NETVSC_DEVICE*)Device->Extension;
+ 	if (netDevice == NULL)
+ 		return NULL;
+ 
+@@ -272,7 +272,7 @@ NetVscInitializeReceiveBufferWithNetVsp(
+ 	)
+ {
+ 	int ret=0;
+-	NETVSC_DEVICE *netDevice;
++	struct NETVSC_DEVICE *netDevice;
+ 	NVSP_MESSAGE *initPacket;
+ 
+ 	DPRINT_ENTER(NETVSC);
+@@ -401,7 +401,7 @@ NetVscInitializeSendBufferWithNetVsp(
+ 	)
+ {
+ 	int ret=0;
+-	NETVSC_DEVICE *netDevice;
++	struct NETVSC_DEVICE *netDevice;
+ 	NVSP_MESSAGE *initPacket;
+ 
+ 	DPRINT_ENTER(NETVSC);
+@@ -496,7 +496,7 @@ NetVscInitializeSendBufferWithNetVsp(
+ 
+ static int
+ NetVscDestroyReceiveBuffer(
+-	NETVSC_DEVICE	*NetDevice
++	struct NETVSC_DEVICE	*NetDevice
+ 	)
+ {
+ 	NVSP_MESSAGE *revokePacket;
+@@ -584,7 +584,7 @@ NetVscDestroyReceiveBuffer(
+ 
+ static int
+ NetVscDestroySendBuffer(
+-	NETVSC_DEVICE	*NetDevice
++	struct NETVSC_DEVICE	*NetDevice
+ 	)
+ {
+ 	NVSP_MESSAGE *revokePacket;
+@@ -665,7 +665,7 @@ NetVscConnectToVsp(
+ 	)
+ {
+ 	int ret=0;
+-	NETVSC_DEVICE *netDevice;
++	struct NETVSC_DEVICE *netDevice;
+ 	NVSP_MESSAGE *initPacket;
+ 	int ndisVersion;
+ 
+@@ -771,7 +771,7 @@ NetVscConnectToVsp(
+ 
+ static void
+ NetVscDisconnectFromVsp(
+-	NETVSC_DEVICE	*NetDevice
++	struct NETVSC_DEVICE	*NetDevice
+ 	)
+ {
+ 	DPRINT_ENTER(NETVSC);
+@@ -801,7 +801,7 @@ NetVscOnDeviceAdd(
+ 	int ret=0;
+ 	int i;
+ 
+-	NETVSC_DEVICE* netDevice;
++	struct NETVSC_DEVICE *netDevice;
+ 	NETVSC_PACKET* packet;
+ 	LIST_ENTRY *entry;
+ 
+@@ -914,7 +914,7 @@ NetVscOnDeviceRemove(
+ 	DEVICE_OBJECT *Device
+ 	)
+ {
+-	NETVSC_DEVICE *netDevice;
++	struct NETVSC_DEVICE *netDevice;
+ 	NETVSC_PACKET *netvscPacket;
+ 	int ret=0;
+ 	LIST_ENTRY *entry;
+@@ -997,7 +997,7 @@ NetVscOnSendCompletion(
+ 	VMPACKET_DESCRIPTOR *Packet
+ 	)
+ {
+-	NETVSC_DEVICE* netDevice;
++	struct NETVSC_DEVICE *netDevice;
+ 	NVSP_MESSAGE *nvspPacket;
+ 	NETVSC_PACKET *nvscPacket;
+ 
+@@ -1051,7 +1051,7 @@ NetVscOnSend(
+ 	NETVSC_PACKET *Packet
+ 	)
+ {
+-	NETVSC_DEVICE* netDevice;
++	struct NETVSC_DEVICE *netDevice;
+ 	int ret=0;
+ 
+ 	NVSP_MESSAGE sendMessage;
+@@ -1115,7 +1115,7 @@ NetVscOnReceive(
+ 	VMPACKET_DESCRIPTOR *Packet
+ 	)
+ {
+-	NETVSC_DEVICE* netDevice;
++	struct NETVSC_DEVICE *netDevice;
+ 	VMTRANSFER_PAGE_PACKET_HEADER *vmxferpagePacket;
+ 	NVSP_MESSAGE *nvspPacket;
+ 	NETVSC_PACKET *netvscPacket=NULL;
+@@ -1359,7 +1359,7 @@ NetVscOnReceiveCompletion(
+ {
+ 	NETVSC_PACKET *packet = (NETVSC_PACKET*)Context;
+ 	DEVICE_OBJECT *device = (DEVICE_OBJECT*)packet->Device;
+-	NETVSC_DEVICE* netDevice;
++	struct NETVSC_DEVICE *netDevice;
+ 	u64	transactionId=0;
+ 	bool fSendReceiveComp = false;
+ 	unsigned long flags;
+@@ -1418,7 +1418,7 @@ NetVscOnChannelCallback(
+ 	const int netPacketSize=2048;
+ 	int ret=0;
+ 	DEVICE_OBJECT *device=(DEVICE_OBJECT*)Context;
+-	NETVSC_DEVICE *netDevice;
++	struct NETVSC_DEVICE *netDevice;
+ 
+ 	u32 bytesRecvd;
+ 	u64 requestId;
+diff --git a/drivers/staging/hv/NetVsc.h b/drivers/staging/hv/NetVsc.h
+index acc4217fd41a..145b1c5317c1 100644
+--- a/drivers/staging/hv/NetVsc.h
++++ b/drivers/staging/hv/NetVsc.h
+@@ -54,7 +54,7 @@
+ 
+ 
+ /* Per netvsc channel-specific */
+-typedef struct _NETVSC_DEVICE {
++struct NETVSC_DEVICE {
+ 	DEVICE_OBJECT					*Device;
+ 
+ 	int								RefCount;
+@@ -86,6 +86,6 @@ typedef struct _NETVSC_DEVICE {
+ 
+ 	/* Holds rndis device info */
+ 	void							*Extension;
+-} NETVSC_DEVICE;
++};
+ 
+ #endif /* _NETVSC_H_ */
+diff --git a/drivers/staging/hv/RndisFilter.c b/drivers/staging/hv/RndisFilter.c
+index 919166761743..fd483fc88aaf 100644
+--- a/drivers/staging/hv/RndisFilter.c
++++ b/drivers/staging/hv/RndisFilter.c
+@@ -46,7 +46,7 @@ typedef enum {
+ } RNDIS_DEVICE_STATE;
+ 
+ typedef struct _RNDIS_DEVICE {
+-	NETVSC_DEVICE			*NetDevice;
++	struct NETVSC_DEVICE			*NetDevice;
+ 
+ 	RNDIS_DEVICE_STATE		State;
+ 	u32					LinkStatus;
+@@ -494,7 +494,7 @@ RndisFilterOnReceive(
+ 	NETVSC_PACKET		*Packet
+ 	)
+ {
+-	NETVSC_DEVICE *netDevice = (NETVSC_DEVICE*)Device->Extension;
++	struct NETVSC_DEVICE *netDevice = (struct NETVSC_DEVICE*)Device->Extension;
+ 	RNDIS_DEVICE *rndisDevice;
+ 	RNDIS_MESSAGE rndisMessage;
+ 	RNDIS_MESSAGE *rndisHeader;
+@@ -933,7 +933,7 @@ RndisFilterOnDeviceAdd(
+ 	)
+ {
+ 	int ret;
+-	NETVSC_DEVICE *netDevice;
++	struct NETVSC_DEVICE *netDevice;
+ 	RNDIS_DEVICE *rndisDevice;
+ 	NETVSC_DEVICE_INFO *deviceInfo = (NETVSC_DEVICE_INFO*)AdditionalInfo;
+ 
+@@ -962,7 +962,7 @@ RndisFilterOnDeviceAdd(
+ 
+ 	/* Initialize the rndis device */
+ 
+-	netDevice = (NETVSC_DEVICE*)Device->Extension;
++	netDevice = (struct NETVSC_DEVICE*)Device->Extension;
+ 	ASSERT(netDevice);
+ 	ASSERT(netDevice->Device);
+ 
+@@ -1010,7 +1010,7 @@ RndisFilterOnDeviceRemove(
+ 	DEVICE_OBJECT *Device
+ 	)
+ {
+-	NETVSC_DEVICE *netDevice = (NETVSC_DEVICE*)Device->Extension;
++	struct NETVSC_DEVICE *netDevice = (struct NETVSC_DEVICE*)Device->Extension;
+ 	RNDIS_DEVICE *rndisDevice = (RNDIS_DEVICE*)netDevice->Extension;
+ 
+ 	DPRINT_ENTER(NETVSC);
+@@ -1046,7 +1046,7 @@ RndisFilterOnOpen(
+ 	)
+ {
+ 	int ret;
+-	NETVSC_DEVICE *netDevice = (NETVSC_DEVICE*)Device->Extension;
++	struct NETVSC_DEVICE *netDevice = (struct NETVSC_DEVICE*)Device->Extension;
+ 
+ 	DPRINT_ENTER(NETVSC);
+ 
+@@ -1064,7 +1064,7 @@ RndisFilterOnClose(
+ 	)
+ {
+ 	int ret;
+-	NETVSC_DEVICE *netDevice = (NETVSC_DEVICE*)Device->Extension;
++	struct NETVSC_DEVICE *netDevice = (struct NETVSC_DEVICE*)Device->Extension;
+ 
+ 	DPRINT_ENTER(NETVSC);
+ 

commit a9a71354b07dc1a3ee6a4053b43d5219fcda7a42
+Author: Bill Pemberton 
+Date:   Mon Jul 27 16:47:43 2009 -0400
+
+    Staging: hv: remove VMBUS_MSGINFO typedef
+    
+    Note that this struct doesn't appear to be used anywhere and can
+    probably be removed.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/VmbusPrivate.h b/drivers/staging/hv/VmbusPrivate.h
+index 0adc02abf66b..40e5962dfb72 100644
+--- a/drivers/staging/hv/VmbusPrivate.h
++++ b/drivers/staging/hv/VmbusPrivate.h
+@@ -97,7 +97,7 @@ struct VMBUS_CONNECTION {
+ };
+ 
+ 
+-typedef struct _VMBUS_MSGINFO {
++struct VMBUS_MSGINFO {
+ 	/* Bookkeeping stuff */
+ 	LIST_ENTRY			MsgListEntry;
+ 
+@@ -106,7 +106,7 @@ typedef struct _VMBUS_MSGINFO {
+ 
+ 	/* The message itself */
+ 	unsigned char		Msg[0];
+-} VMBUS_MSGINFO;
++};
+ 
+ 
+ 

commit 662e66b0e4f91f08e0d57e30b0bd83421e04bf79
+Author: Bill Pemberton 
+Date:   Mon Jul 27 16:47:42 2009 -0400
+
+    Staging: hv: remove VMBUS_CONNECTION typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/Connection.c b/drivers/staging/hv/Connection.c
+index 68f3a07371ed..7b480f0de5b0 100644
+--- a/drivers/staging/hv/Connection.c
++++ b/drivers/staging/hv/Connection.c
+@@ -29,7 +29,7 @@
+ /* Globals */
+ 
+ 
+-VMBUS_CONNECTION gVmbusConnection = {
++struct VMBUS_CONNECTION gVmbusConnection = {
+ 	.ConnectState		= Disconnected,
+ 	.NextGpadlHandle	= 0xE1E10,
+ };
+diff --git a/drivers/staging/hv/VmbusPrivate.h b/drivers/staging/hv/VmbusPrivate.h
+index ec9bfa409550..0adc02abf66b 100644
+--- a/drivers/staging/hv/VmbusPrivate.h
++++ b/drivers/staging/hv/VmbusPrivate.h
+@@ -63,7 +63,7 @@ enum VMBUS_CONNECT_STATE {
+ 
+ #define MAX_SIZE_CHANNEL_MESSAGE			HV_MESSAGE_PAYLOAD_BYTE_COUNT
+ 
+-typedef struct _VMBUS_CONNECTION {
++struct VMBUS_CONNECTION {
+ 
+ 	enum VMBUS_CONNECT_STATE					ConnectState;
+ 
+@@ -94,7 +94,7 @@ typedef struct _VMBUS_CONNECTION {
+ 	spinlock_t channel_lock;
+ 
+ 	HANDLE								WorkQueue;
+-} VMBUS_CONNECTION;
++};
+ 
+ 
+ typedef struct _VMBUS_MSGINFO {
+@@ -112,7 +112,7 @@ typedef struct _VMBUS_MSGINFO {
+ 
+ /* Externs */
+ 
+-extern VMBUS_CONNECTION gVmbusConnection;
++extern struct VMBUS_CONNECTION gVmbusConnection;
+ 
+ 
+ /* General vmbus interface */

commit 5c3e375cf5cf709c95c705d564001c5a0ca3c50e
+Author: Bill Pemberton 
+Date:   Mon Jul 27 16:47:41 2009 -0400
+
+    Staging: hv: remove VMBUS_CONNECT_STATE typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/VmbusPrivate.h b/drivers/staging/hv/VmbusPrivate.h
+index ad17088f601e..ec9bfa409550 100644
+--- a/drivers/staging/hv/VmbusPrivate.h
++++ b/drivers/staging/hv/VmbusPrivate.h
+@@ -54,18 +54,18 @@
+ /* Data types */
+ 
+ 
+-typedef enum {
++enum VMBUS_CONNECT_STATE {
+ 	Disconnected,
+ 	Connecting,
+ 	Connected,
+ 	Disconnecting
+-} VMBUS_CONNECT_STATE;
++};
+ 
+ #define MAX_SIZE_CHANNEL_MESSAGE			HV_MESSAGE_PAYLOAD_BYTE_COUNT
+ 
+ typedef struct _VMBUS_CONNECTION {
+ 
+-	VMBUS_CONNECT_STATE					ConnectState;
++	enum VMBUS_CONNECT_STATE					ConnectState;
+ 
+ 	u32								NextGpadlHandle;
+ 

commit 3fcc523adca8e979eb710d54f467f8fc890a77da
+Author: Bill Pemberton 
+Date:   Mon Jul 27 16:47:40 2009 -0400
+
+    Staging: hv: remove VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/Channel.c b/drivers/staging/hv/Channel.c
+index e2c833fb923f..674f141a648f 100644
+--- a/drivers/staging/hv/Channel.c
++++ b/drivers/staging/hv/Channel.c
+@@ -912,7 +912,7 @@ VmbusChannelSendPacketMultiPageBuffer(
+ )
+ {
+ 	int ret=0;
+-	VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER desc;
++	struct VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER desc;
+ 	u32 descSize;
+ 	u32 packetLen;
+ 	u32 packetLenAligned;
+@@ -930,7 +930,7 @@ VmbusChannelSendPacketMultiPageBuffer(
+ 	ASSERT(PfnCount <= MAX_MULTIPAGE_BUFFER_COUNT);
+ 
+ 	/* Adjust the size down since VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER is the largest size we support */
+-	descSize = sizeof(VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER) - ((MAX_MULTIPAGE_BUFFER_COUNT - PfnCount)*sizeof(u64));
++	descSize = sizeof(struct VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER) - ((MAX_MULTIPAGE_BUFFER_COUNT - PfnCount)*sizeof(u64));
+ 	packetLen = descSize + BufferLen;
+ 	packetLenAligned = ALIGN_UP(packetLen, sizeof(u64));
+ 
+diff --git a/drivers/staging/hv/Channel.h b/drivers/staging/hv/Channel.h
+index 54b79f083fbf..5dac07b7b18c 100644
+--- a/drivers/staging/hv/Channel.h
++++ b/drivers/staging/hv/Channel.h
+@@ -45,7 +45,7 @@ struct VMBUS_CHANNEL_PACKET_PAGE_BUFFER {
+ 
+ 
+ /* The format must be the same as VMDATA_GPA_DIRECT */
+-typedef struct _VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER {
++struct VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER {
+     u16				Type;
+     u16				DataOffset8;
+     u16				Length8;
+@@ -54,7 +54,7 @@ typedef struct _VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER {
+ 	u32				Reserved;
+ 	u32				RangeCount;		/* Always 1 in this case */
+ 	MULTIPAGE_BUFFER	Range;
+-} VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER;
++};
+ 
+ #pragma pack(pop)
+ 
+diff --git a/drivers/staging/hv/Vmbus.c b/drivers/staging/hv/Vmbus.c
+index cc5c61a94843..91b226f73415 100644
+--- a/drivers/staging/hv/Vmbus.c
++++ b/drivers/staging/hv/Vmbus.c
+@@ -126,7 +126,7 @@ VmbusInitialize(
+ 	DPRINT_INFO(VMBUS, "+++++++ Vmbus using SINT %d +++++++", VMBUS_MESSAGE_SINT);
+ 
+ 	DPRINT_DBG(VMBUS, "sizeof(VMBUS_CHANNEL_PACKET_PAGE_BUFFER)=%ld, sizeof(VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER)=%ld",
+-		sizeof(struct VMBUS_CHANNEL_PACKET_PAGE_BUFFER), sizeof(VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER));
++		sizeof(struct VMBUS_CHANNEL_PACKET_PAGE_BUFFER), sizeof(struct VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER));
+ 
+ 	drv->name = gDriverName;
+ 	memcpy(&drv->deviceType, &gVmbusDeviceType, sizeof(GUID));

commit 0cf4fa80781dcdb5bf6096fa221f3fc6c7073405
+Author: Bill Pemberton 
+Date:   Mon Jul 27 16:47:39 2009 -0400
+
+    Staging: hv: remove VMBUS_CHANNEL_PACKET_PAGE_BUFFER typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/Channel.c b/drivers/staging/hv/Channel.c
+index bd82154e69f1..e2c833fb923f 100644
+--- a/drivers/staging/hv/Channel.c
++++ b/drivers/staging/hv/Channel.c
+@@ -831,7 +831,7 @@ VmbusChannelSendPacketPageBuffer(
+ {
+ 	int ret=0;
+ 	int i=0;
+-	VMBUS_CHANNEL_PACKET_PAGE_BUFFER desc;
++	struct VMBUS_CHANNEL_PACKET_PAGE_BUFFER desc;
+ 	u32 descSize;
+ 	u32 packetLen;
+ 	u32 packetLenAligned;
+@@ -845,7 +845,7 @@ VmbusChannelSendPacketPageBuffer(
+ 	DumpVmbusChannel(Channel);
+ 
+ 	/* Adjust the size down since VMBUS_CHANNEL_PACKET_PAGE_BUFFER is the largest size we support */
+-	descSize = sizeof(VMBUS_CHANNEL_PACKET_PAGE_BUFFER) - ((MAX_PAGE_BUFFER_COUNT - PageCount)*sizeof(PAGE_BUFFER));
++	descSize = sizeof(struct VMBUS_CHANNEL_PACKET_PAGE_BUFFER) - ((MAX_PAGE_BUFFER_COUNT - PageCount)*sizeof(PAGE_BUFFER));
+ 	packetLen = descSize + BufferLen;
+ 	packetLenAligned = ALIGN_UP(packetLen, sizeof(u64));
+ 
+diff --git a/drivers/staging/hv/Channel.h b/drivers/staging/hv/Channel.h
+index be65d64e4590..54b79f083fbf 100644
+--- a/drivers/staging/hv/Channel.h
++++ b/drivers/staging/hv/Channel.h
+@@ -32,7 +32,7 @@
+ 
+ 
+ /* The format must be the same as VMDATA_GPA_DIRECT */
+-typedef struct _VMBUS_CHANNEL_PACKET_PAGE_BUFFER {
++struct VMBUS_CHANNEL_PACKET_PAGE_BUFFER {
+     u16				Type;
+     u16				DataOffset8;
+     u16				Length8;
+@@ -41,7 +41,7 @@ typedef struct _VMBUS_CHANNEL_PACKET_PAGE_BUFFER {
+ 	u32				Reserved;
+ 	u32				RangeCount;
+     PAGE_BUFFER			Range[MAX_PAGE_BUFFER_COUNT];
+-} VMBUS_CHANNEL_PACKET_PAGE_BUFFER;
++};
+ 
+ 
+ /* The format must be the same as VMDATA_GPA_DIRECT */
+diff --git a/drivers/staging/hv/Vmbus.c b/drivers/staging/hv/Vmbus.c
+index 81b86c270661..cc5c61a94843 100644
+--- a/drivers/staging/hv/Vmbus.c
++++ b/drivers/staging/hv/Vmbus.c
+@@ -126,7 +126,7 @@ VmbusInitialize(
+ 	DPRINT_INFO(VMBUS, "+++++++ Vmbus using SINT %d +++++++", VMBUS_MESSAGE_SINT);
+ 
+ 	DPRINT_DBG(VMBUS, "sizeof(VMBUS_CHANNEL_PACKET_PAGE_BUFFER)=%ld, sizeof(VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER)=%ld",
+-		sizeof(VMBUS_CHANNEL_PACKET_PAGE_BUFFER), sizeof(VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER));
++		sizeof(struct VMBUS_CHANNEL_PACKET_PAGE_BUFFER), sizeof(VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER));
+ 
+ 	drv->name = gDriverName;
+ 	memcpy(&drv->deviceType, &gVmbusDeviceType, sizeof(GUID));

commit b75f9c8cd2b0ed58f07142af84ddc68be45068c3
+Author: Bill Pemberton 
+Date:   Mon Jul 27 16:47:38 2009 -0400
+
+    Staging: hv: Hv.c: remove unused physAddr
+    
+    physAddr was declared but never used in HvInit()
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/Hv.c b/drivers/staging/hv/Hv.c
+index 264a90f8f8ed..2a8a652c1f74 100644
+--- a/drivers/staging/hv/Hv.c
++++ b/drivers/staging/hv/Hv.c
+@@ -232,7 +232,6 @@ HvInit (
+     int maxLeaf;
+ 	HV_X64_MSR_HYPERCALL_CONTENTS hypercallMsr;
+ 	void* virtAddr=0;
+-	unsigned long physAddr=0;
+ 
+ 	DPRINT_ENTER(VMBUS);
+ 

commit 25fb66ce44fc7bf54a7d57b5d740fca4c2cf0297
+Author: Bill Pemberton 
+Date:   Mon Jul 27 16:47:37 2009 -0400
+
+    Staging: hv: vmbus_drv.c: remove unused structs
+    
+    vmbus_ctl_table_hdr, vmbus_dev_ctl_table, vmbus_ctl_table, and
+    vmus_root_ctl_table were never used.  This removes them.
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c
+index fd6f18e148d1..406fd86110d7 100644
+--- a/drivers/staging/hv/vmbus_drv.c
++++ b/drivers/staging/hv/vmbus_drv.c
+@@ -101,34 +101,6 @@ static int vmbus_irq = VMBUS_IRQ;
+ 
+ /* Setup /proc/sys/bus/vmbus/vmbus_loglevel */
+ /* Allow usage of sysctl cmd to set the logging level */
+-static struct ctl_table_header *vmbus_ctl_table_hdr;
+-
+-static ctl_table vmbus_dev_ctl_table[] = {
+-	{ .ctl_name	= 8461,
+-	  .procname	= "vmbus_loglevel",
+-	  .data		= &vmbus_loglevel,
+-	  .maxlen	= sizeof(vmbus_loglevel),
+-	  .mode		= 0644,
+-	  .proc_handler	= &proc_dointvec },
+-	{ }
+-};
+-
+-static ctl_table vmbus_ctl_table[] = {
+-	{ .ctl_name	= CTL_DEV,
+-	  .procname	= "vmbus",
+-	  .mode		= 0555,
+-	  .child	= vmbus_dev_ctl_table },
+-	{ }
+-};
+-
+-static ctl_table vmus_root_ctl_table[] = {
+-	{ .ctl_name	= CTL_BUS,
+-	  .procname	= "bus",
+-	  .mode		= 0555,
+-	  .child	= vmbus_ctl_table },
+-	{ }
+-};
+-
+ 
+ /* Set up per device attributes in /sys/bus/vmbus/devices/ */
+ 

commit 5d48a1c20268871395299672dce5c1989c9c94e4
+Author: Bill Pemberton 
+Date:   Mon Jul 27 16:47:36 2009 -0400
+
+    Staging: hv: check return value of device_register()
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c
+index 5322e570bd8c..f1efc3e65c1f 100644
+--- a/drivers/staging/hv/blkvsc_drv.c
++++ b/drivers/staging/hv/blkvsc_drv.c
+@@ -192,7 +192,7 @@ int blkvsc_drv_init(PFN_DRIVERINITIALIZE pfn_drv_init)
+ 	drv_ctx->shutdown = blkvsc_shutdown;
+ 
+ 	/* The driver belongs to vmbus */
+-	vmbus_child_driver_register(drv_ctx);
++	ret = vmbus_child_driver_register(drv_ctx);
+ 
+ 	DPRINT_EXIT(BLKVSC_DRV);
+ 
+diff --git a/drivers/staging/hv/include/vmbus.h b/drivers/staging/hv/include/vmbus.h
+index 463f77ef3cd9..c1a8c553edaa 100644
+--- a/drivers/staging/hv/include/vmbus.h
++++ b/drivers/staging/hv/include/vmbus.h
+@@ -82,8 +82,7 @@ static inline struct driver_context *driver_to_driver_context(struct device_driv
+ 
+ /* Vmbus interface */
+ 
+-void
+-vmbus_child_driver_register(
++int vmbus_child_driver_register(
+ 	struct driver_context* driver_ctx
+ 	);
+ 
+diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c
+index 8cf552a33e53..82f77008b9b5 100644
+--- a/drivers/staging/hv/netvsc_drv.c
++++ b/drivers/staging/hv/netvsc_drv.c
+@@ -114,7 +114,7 @@ int netvsc_drv_init(PFN_DRIVERINITIALIZE pfn_drv_init)
+ 	drv_ctx->remove = netvsc_remove;
+ 
+ 	/* The driver belongs to vmbus */
+-	vmbus_child_driver_register(drv_ctx);
++	ret = vmbus_child_driver_register(drv_ctx);
+ 
+ 	DPRINT_EXIT(NETVSC_DRV);
+ 
+diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
+index 3c677f015c47..cbea8a2f0541 100644
+--- a/drivers/staging/hv/storvsc_drv.c
++++ b/drivers/staging/hv/storvsc_drv.c
+@@ -162,7 +162,7 @@ int storvsc_drv_init(PFN_DRIVERINITIALIZE pfn_drv_init)
+ 	drv_ctx->remove = storvsc_remove;
+ 
+ 	/* The driver belongs to vmbus */
+-	vmbus_child_driver_register(drv_ctx);
++	ret = vmbus_child_driver_register(drv_ctx);
+ 
+ 	DPRINT_EXIT(STORVSC_DRV);
+ 
+diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c
+index cede0ace9ad5..fd6f18e148d1 100644
+--- a/drivers/staging/hv/vmbus_drv.c
++++ b/drivers/staging/hv/vmbus_drv.c
+@@ -435,7 +435,18 @@ int vmbus_bus_init(PFN_DRIVERINITIALIZE pfn_drv_init)
+ 	dev_ctx->device.release = vmbus_bus_release;
+ 
+ 	/* Setup the bus as root device */
+-	device_register(&dev_ctx->device);
++	ret = device_register(&dev_ctx->device);
++	if (ret)
++	{
++		DPRINT_ERR(VMBUS_DRV, "ERROR - Unable to register vmbus root device");
++
++		free_irq(vmbus_irq, NULL);
++		bus_unregister(&vmbus_drv_ctx->bus);
++
++		ret = -1;
++		goto cleanup;
++	}
++
+ 
+ 	vmbus_drv_obj->GetChannelOffers();
+ 
+@@ -491,9 +502,10 @@ Name:	vmbus_child_driver_register()
+ Desc:	Register a vmbus's child driver
+ 
+ --*/
+-void vmbus_child_driver_register(struct driver_context* driver_ctx)
++int vmbus_child_driver_register(struct driver_context* driver_ctx)
+ {
+ 	VMBUS_DRIVER_OBJECT *vmbus_drv_obj=&g_vmbus_drv.drv_obj;
++	int ret;
+ 
+ 	DPRINT_ENTER(VMBUS_DRV);
+ 
+@@ -502,11 +514,13 @@ void vmbus_child_driver_register(struct driver_context* driver_ctx)
+ 	/* The child driver on this vmbus */
+ 	driver_ctx->driver.bus = &g_vmbus_drv.bus;
+ 
+-	driver_register(&driver_ctx->driver);
++	ret = driver_register(&driver_ctx->driver);
+ 
+ 	vmbus_drv_obj->GetChannelOffers();
+ 
+ 	DPRINT_EXIT(VMBUS_DRV);
++
++	return ret;
+ }
+ 
+ EXPORT_SYMBOL(vmbus_child_driver_register);

commit c19fbca307c19bd0d49e86b9417613c90eb9de95
+Author: Bill Pemberton 
+Date:   Mon Jul 27 16:47:35 2009 -0400
+
+    Staging: hv: check return value of bus_register()
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c
+index 74419a7eb32d..cede0ace9ad5 100644
+--- a/drivers/staging/hv/vmbus_drv.c
++++ b/drivers/staging/hv/vmbus_drv.c
+@@ -380,7 +380,12 @@ int vmbus_bus_init(PFN_DRIVERINITIALIZE pfn_drv_init)
+ 	tasklet_init(&vmbus_drv_ctx->event_dpc, vmbus_event_dpc, (unsigned long)vmbus_drv_obj);
+ 
+ 	/* Now, register the bus driver with LDM */
+-	bus_register(&vmbus_drv_ctx->bus);
++	ret = bus_register(&vmbus_drv_ctx->bus);
++	if (ret)
++	{
++		ret = -1;
++		goto cleanup;
++	}
+ 
+ 	/* Get the interrupt resource */
+ 	ret = request_irq(vmbus_irq,

commit b2aba7cc7105de5ce7769d7b5ddb0b0bc28909c5
+Author: Bill Pemberton 
+Date:   Mon Jul 27 16:47:34 2009 -0400
+
+    Staging: hv: vmbus_drv.c: fix print formatting
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c
+index a86e4043d174..74419a7eb32d 100644
+--- a/drivers/staging/hv/vmbus_drv.c
++++ b/drivers/staging/hv/vmbus_drv.c
+@@ -647,7 +647,7 @@ static int vmbus_child_device_register(DEVICE_OBJECT* root_device_obj, DEVICE_OB
+ 	ret = child_device_ctx->probe_error;
+ 
+ 	if (ret)
+-		DPRINT_ERR(VMBUS_DRV, "unable to register child device (%p) (%d)", &child_device_ctx->device);
++		DPRINT_ERR(VMBUS_DRV, "unable to register child device (%p)", &child_device_ctx->device);
+ 	else
+ 		DPRINT_INFO(VMBUS_DRV, "child device (%p) registered", &child_device_ctx->device);
+ 

commit 7f6f27d65cfd94cab66b64cf4a1ef87f1bd8ea86
+Author: Bill Pemberton 
+Date:   Mon Jul 27 16:47:33 2009 -0400
+
+    Staging: hv: storvsc_drv.c: fix print formatting
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
+index 648708ab44e6..3c677f015c47 100644
+--- a/drivers/staging/hv/storvsc_drv.c
++++ b/drivers/staging/hv/storvsc_drv.c
+@@ -943,7 +943,7 @@ static void storvsc_host_rescan_callback(struct work_struct *work)
+ 		return;
+ 	}
+ 
+-	DPRINT_INFO(STORVSC_DRV, "rescanning host for new scsi devices...", device_obj, host_device_ctx->target, host_device_ctx->path);
++	DPRINT_INFO(STORVSC_DRV, "rescanning host for new scsi devices...");
+ 
+ 	/* Rescan for new device */
+ 	scsi_scan_target(&host->shost_gendev, host_device_ctx->path, host_device_ctx->target, SCAN_WILD_CARD, 1);

commit 38d3af06737c6724e6f785fddf2679da02275dcb
+Author: Bill Pemberton 
+Date:   Mon Jul 27 16:47:32 2009 -0400
+
+    Staging: hv: RndisFilter.c: fix print formatting
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/RndisFilter.c b/drivers/staging/hv/RndisFilter.c
+index d971e866218c..919166761743 100644
+--- a/drivers/staging/hv/RndisFilter.c
++++ b/drivers/staging/hv/RndisFilter.c
+@@ -409,7 +409,7 @@ RndisFilterReceiveResponse(
+ 		}
+ 		else
+ 		{
+-			DPRINT_ERR(NETVSC, "rndis response buffer overflow detected (size %u max %u)", Response->MessageLength, sizeof(RNDIS_FILTER_PACKET));
++			DPRINT_ERR(NETVSC, "rndis response buffer overflow detected (size %u max %lu)", Response->MessageLength, sizeof(RNDIS_FILTER_PACKET));
+ 
+ 			if (Response->NdisMessageType == REMOTE_NDIS_RESET_CMPLT) /* does not have a request id field */
+ 			{
+@@ -539,7 +539,7 @@ RndisFilterOnReceive(
+ 
+ 	if ((rndisHeader->NdisMessageType != REMOTE_NDIS_PACKET_MSG) && (rndisHeader->MessageLength > sizeof(RNDIS_MESSAGE)))
+ 	{
+-		DPRINT_ERR(NETVSC, "incoming rndis message buffer overflow detected (got %u, max %u)...marking it an error!",
++		DPRINT_ERR(NETVSC, "incoming rndis message buffer overflow detected (got %u, max %lu)...marking it an error!",
+ 			rndisHeader->MessageLength, sizeof(RNDIS_MESSAGE));
+ 	}
+ 
+@@ -744,7 +744,7 @@ RndisFilterInit(
+ {
+ 	DPRINT_ENTER(NETVSC);
+ 
+-	DPRINT_DBG(NETVSC, "sizeof(RNDIS_FILTER_PACKET) == %d", sizeof(RNDIS_FILTER_PACKET));
++	DPRINT_DBG(NETVSC, "sizeof(RNDIS_FILTER_PACKET) == %ld", sizeof(RNDIS_FILTER_PACKET));
+ 
+ 	Driver->RequestExtSize = sizeof(RNDIS_FILTER_PACKET);
+ 	Driver->AdditionalRequestPageBufferCount = 1; /* For rndis header */

commit 4d4a0e22418b517907340248460583bbd22d0609
+Author: Bill Pemberton 
+Date:   Mon Jul 27 16:47:31 2009 -0400
+
+    Staging: hv: NetVsc.c: fix print formatting
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/NetVsc.c b/drivers/staging/hv/NetVsc.c
+index 72d41cc4829c..111e149d88bb 100644
+--- a/drivers/staging/hv/NetVsc.c
++++ b/drivers/staging/hv/NetVsc.c
+@@ -239,7 +239,7 @@ NetVscInitialize(
+ 
+ 	DPRINT_ENTER(NETVSC);
+ 
+-	DPRINT_DBG(NETVSC, "sizeof(NETVSC_PACKET)=%d, sizeof(NVSP_MESSAGE)=%d, sizeof(VMTRANSFER_PAGE_PACKET_HEADER)=%d",
++	DPRINT_DBG(NETVSC, "sizeof(NETVSC_PACKET)=%ld, sizeof(NVSP_MESSAGE)=%ld, sizeof(VMTRANSFER_PAGE_PACKET_HEADER)=%ld",
+ 		sizeof(NETVSC_PACKET), sizeof(NVSP_MESSAGE), sizeof(VMTRANSFER_PAGE_PACKET_HEADER));
+ 
+ 	/* Make sure we are at least 2 pages since 1 page is used for control */

commit ed39aa6ac482f37e72634bb9fc95d976b2fd13d3
+Author: Bill Pemberton 
+Date:   Mon Jul 27 16:47:30 2009 -0400
+
+    Staging: hv: Remove X2V_LINUX check
+    
+    Remove preprocessor check for X2V_LINUX in osd.c
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/osd.c b/drivers/staging/hv/osd.c
+index 442cc7de0f0a..e683735706d1 100644
+--- a/drivers/staging/hv/osd.c
++++ b/drivers/staging/hv/osd.c
+@@ -168,15 +168,7 @@ void PageUnmapVirtualAddress(void* VirtAddr)
+ 
+ void *MemMapIO(unsigned long phys, unsigned long size)
+ {
+-#if X2V_LINUX
+-#ifdef __x86_64__
+-	return (void*)(phys + 0xFFFF83000C000000);
+-#else /* i386 */
+-	return (void*)(phys + 0xfb000000);
+-#endif
+-#else
+ 	return (void*)GetVirtualAddress(phys); /* return ioremap_nocache(phys, size); */
+-#endif
+ }
+ 
+ void MemUnmapIO(void *virt)

commit dfe8b2d9d809fef5df24280e1e275fcd30776bd5
+Author: Bill Pemberton 
+Date:   Mon Jul 27 16:47:29 2009 -0400
+
+    Staging: hv: fix blkvsc_ioctl() parameters
+    
+    blkvsc_ioctl() had the wrong parameter list for  struct
+    block_device_operations
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c
+index 4bf77eeece7a..5322e570bd8c 100644
+--- a/drivers/staging/hv/blkvsc_drv.c
++++ b/drivers/staging/hv/blkvsc_drv.c
+@@ -129,8 +129,8 @@ static int blkvsc_release(struct gendisk *disk, fmode_t mode);
+ static int blkvsc_media_changed(struct gendisk *gd);
+ static int blkvsc_revalidate_disk(struct gendisk *gd);
+ static int blkvsc_getgeo(struct block_device *bd, struct hd_geometry *hg);
+-static int blkvsc_ioctl(struct inode *inode, struct file *filep, unsigned cmd, unsigned long arg);
+-
++static int blkvsc_ioctl(struct block_device *bd, fmode_t mode,
++			unsigned cmd, unsigned long argument);
+ static void blkvsc_request(struct request_queue *queue);
+ static void blkvsc_request_completion(STORVSC_REQUEST* request);
+ static int blkvsc_do_request(struct block_device_context *blkdev, struct request *req);
+@@ -1451,9 +1451,9 @@ int blkvsc_getgeo(struct block_device *bd, struct hd_geometry *hg)
+     return 0;
+ }
+ 
+-static int blkvsc_ioctl(struct inode *inode, struct file *filep, unsigned cmd, unsigned long arg)
++static int blkvsc_ioctl(struct block_device *bd, fmode_t mode,
++			unsigned cmd, unsigned long argument)
+ {
+-	struct block_device *bd = inode->i_bdev;
+ 	struct block_device_context *blkdev = bd->bd_disk->private_data;
+ 	int ret=0;
+ 

commit 77d2d9da7c74678b69170485909e63ff21e4af07
+Author: Bill Pemberton 
+Date:   Mon Jul 27 16:47:28 2009 -0400
+
+    Staging: hv: fix blkvsc_release() parameters
+    
+    blkvsc_release() had the wrong parameter list for  struct
+    block_device_operations
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c
+index d8a3b2539045..4bf77eeece7a 100644
+--- a/drivers/staging/hv/blkvsc_drv.c
++++ b/drivers/staging/hv/blkvsc_drv.c
+@@ -125,7 +125,7 @@ static int blkvsc_remove(struct device *device);
+ static void blkvsc_shutdown(struct device *device);
+ 
+ static int blkvsc_open(struct block_device *bdev,  fmode_t mode);
+-static int blkvsc_release(struct inode *inode, struct file *filep);
++static int blkvsc_release(struct gendisk *disk, fmode_t mode);
+ static int blkvsc_media_changed(struct gendisk *gd);
+ static int blkvsc_revalidate_disk(struct gendisk *gd);
+ static int blkvsc_getgeo(struct block_device *bd, struct hd_geometry *hg);
+@@ -1341,9 +1341,9 @@ static int blkvsc_open(struct block_device *bdev,  fmode_t mode)
+ 	return 0;
+ }
+ 
+-static int blkvsc_release(struct inode *inode, struct file *filep)
++static int blkvsc_release(struct gendisk *disk, fmode_t mode)
+ {
+-	struct block_device_context *blkdev = inode->i_bdev->bd_disk->private_data;
++	struct block_device_context *blkdev = disk->private_data;
+ 
+ 	DPRINT_DBG(BLKVSC_DRV, "- users %d disk %s\n", blkdev->users, blkdev->gd->disk_name);
+ 

commit 39635f7d8de679d97e2773e6c5d2749a420bed87
+Author: Bill Pemberton 
+Date:   Mon Jul 27 16:47:27 2009 -0400
+
+    Staging: hv: fix blkvsc_open() parameters
+    
+    blkvsc_open() had the wrong parameter list for  struct
+    block_device_operations
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c
+index 8f70b405aebe..d8a3b2539045 100644
+--- a/drivers/staging/hv/blkvsc_drv.c
++++ b/drivers/staging/hv/blkvsc_drv.c
+@@ -124,7 +124,7 @@ static int blkvsc_probe(struct device *dev);
+ static int blkvsc_remove(struct device *device);
+ static void blkvsc_shutdown(struct device *device);
+ 
+-static int blkvsc_open(struct inode *inode, struct file *filep);
++static int blkvsc_open(struct block_device *bdev,  fmode_t mode);
+ static int blkvsc_release(struct inode *inode, struct file *filep);
+ static int blkvsc_media_changed(struct gendisk *gd);
+ static int blkvsc_revalidate_disk(struct gendisk *gd);
+@@ -1320,9 +1320,9 @@ static void blkvsc_request(struct request_queue *queue)
+ 	}
+ }
+ 
+-static int blkvsc_open(struct inode *inode, struct file *filep)
++static int blkvsc_open(struct block_device *bdev,  fmode_t mode)
+ {
+-	struct block_device_context *blkdev = inode->i_bdev->bd_disk->private_data;
++	struct block_device_context *blkdev = bdev->bd_disk->private_data;
+ 
+ 	DPRINT_DBG(BLKVSC_DRV, "- users %d disk %s\n", blkdev->users, blkdev->gd->disk_name);
+ 
+@@ -1331,7 +1331,7 @@ static int blkvsc_open(struct inode *inode, struct file *filep)
+ 	if (!blkdev->users && blkdev->device_type == DVD_TYPE)
+ 	{
+ 		spin_unlock(&blkdev->lock);
+-		check_disk_change(inode->i_bdev);
++		check_disk_change(bdev);
+ 		spin_lock(&blkdev->lock);
+ 	}
+ 

commit 627c156d75582c6e678efabc64d33d4b1c66b4ce
+Author: Bill Pemberton 
+Date:   Mon Jul 27 16:47:26 2009 -0400
+
+    Staging: hv: blkvsc_drv.c: fix print formatting
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c
+index 9c4bfb6dea92..8f70b405aebe 100644
+--- a/drivers/staging/hv/blkvsc_drv.c
++++ b/drivers/staging/hv/blkvsc_drv.c
+@@ -411,7 +411,7 @@ static int blkvsc_probe(struct device *device)
+ 	/* go! */
+ 	add_disk(blkdev->gd);
+ 
+-	DPRINT_INFO(BLKVSC_DRV, "%s added!! capacity %llu sector_size %d", blkdev->gd->disk_name, blkdev->capacity, blkdev->sector_size);
++	DPRINT_INFO(BLKVSC_DRV, "%s added!! capacity %lu sector_size %d", blkdev->gd->disk_name, (unsigned long) blkdev->capacity, blkdev->sector_size);
+ 
+ 	return ret;
+ 
+@@ -904,10 +904,10 @@ static int blkvsc_submit_request(struct blkvsc_request *blkvsc_req, void (*reque
+ 
+ 	STORVSC_REQUEST *storvsc_req;
+ 
+-	DPRINT_DBG(BLKVSC_DRV, "blkvsc_submit_request() - req %p type %s start_sector %llu count %ld offset %d len %d\n",
++	DPRINT_DBG(BLKVSC_DRV, "blkvsc_submit_request() - req %p type %s start_sector %lu count %ld offset %d len %d\n",
+ 		blkvsc_req,
+ 		(blkvsc_req->write)?"WRITE":"READ",
+-		blkvsc_req->sector_start,
++		(unsigned long) blkvsc_req->sector_start,
+ 		blkvsc_req->sector_count,
+ 		blkvsc_req->request.DataBuffer.Offset,
+ 		blkvsc_req->request.DataBuffer.Length);
+@@ -972,7 +972,7 @@ static int blkvsc_do_request(struct block_device_context *blkdev, struct request
+ 	int pending=0;
+ 	struct blkvsc_request_group *group=NULL;
+ 
+-	DPRINT_DBG(BLKVSC_DRV, "blkdev %p req %p sect %llu \n", blkdev, req, blk_rq_pos(req));
++	DPRINT_DBG(BLKVSC_DRV, "blkdev %p req %p sect %lu \n", blkdev, req, (unsigned long) blk_rq_pos(req));
+ 
+ 	/* Create a group to tie req to list of blkvsc_reqs */
+ 	group = (struct blkvsc_request_group*)kmem_cache_alloc(blkdev->request_pool, GFP_ATOMIC);
+@@ -1075,8 +1075,8 @@ static int blkvsc_do_request(struct block_device_context *blkdev, struct request
+ 	{
+ 		if (pending)
+ 		{
+-			DPRINT_DBG(BLKVSC_DRV, "adding blkvsc_req to pending_list - blkvsc_req %p start_sect %llu sect_count %ld (%llu %ld)\n",
+-				blkvsc_req, blkvsc_req->sector_start, blkvsc_req->sector_count, start_sector, num_sectors);
++			DPRINT_DBG(BLKVSC_DRV, "adding blkvsc_req to pending_list - blkvsc_req %p start_sect %lu sect_count %ld (%lu %ld)\n",
++				blkvsc_req, blkvsc_req->sector_start, blkvsc_req->sector_count, (unsigned long) start_sector, (unsigned long) num_sectors);
+ 
+ 			list_add_tail(&blkvsc_req->pend_entry, &blkdev->pending_list);
+ 		}
+@@ -1089,8 +1089,8 @@ static int blkvsc_do_request(struct block_device_context *blkdev, struct request
+ 				list_add_tail(&blkvsc_req->pend_entry, &blkdev->pending_list);
+ 			}
+ 
+-			DPRINT_DBG(BLKVSC_DRV, "submitted blkvsc_req %p start_sect %llu sect_count %ld (%llu %ld) ret %d\n",
+-				blkvsc_req, blkvsc_req->sector_start, blkvsc_req->sector_count, start_sector, num_sectors, ret);
++			DPRINT_DBG(BLKVSC_DRV, "submitted blkvsc_req %p start_sect %lu sect_count %ld (%lu %ld) ret %d\n",
++				blkvsc_req, (unsigned long) blkvsc_req->sector_start, blkvsc_req->sector_count, (unsigned long) start_sector, num_sectors, ret);
+ 		}
+ 	}
+ 
+@@ -1129,12 +1129,12 @@ static void blkvsc_request_completion(STORVSC_REQUEST* request)
+ 
+ 	ASSERT(blkvsc_req->group);
+ 
+-	DPRINT_DBG(BLKVSC_DRV, "blkdev %p blkvsc_req %p group %p type %s sect_start %llu sect_count %ld len %d group outstd %d total outstd %d\n",
++	DPRINT_DBG(BLKVSC_DRV, "blkdev %p blkvsc_req %p group %p type %s sect_start %lu sect_count %ld len %d group outstd %d total outstd %d\n",
+ 		blkdev,
+ 		blkvsc_req,
+ 		blkvsc_req->group,
+ 		(blkvsc_req->write)?"WRITE":"READ",
+-		blkvsc_req->sector_start,
++		(unsigned long) blkvsc_req->sector_start,
+ 		blkvsc_req->sector_count,
+ 		blkvsc_req->request.DataBuffer.Length,
+ 		blkvsc_req->group->outstanding,
+@@ -1154,9 +1154,9 @@ static void blkvsc_request_completion(STORVSC_REQUEST* request)
+ 	{
+ 		list_for_each_entry_safe(comp_req, tmp, &blkvsc_req->group->blkvsc_req_list, req_entry)
+ 		{
+-			DPRINT_DBG(BLKVSC_DRV, "completing blkvsc_req %p sect_start %llu sect_count %ld \n",
++			DPRINT_DBG(BLKVSC_DRV, "completing blkvsc_req %p sect_start %lu sect_count %ld \n",
+ 				comp_req,
+-				comp_req->sector_start,
++				(unsigned long) comp_req->sector_start,
+ 				comp_req->sector_count);
+ 
+ 			list_del(&comp_req->req_entry);
+@@ -1204,9 +1204,9 @@ static int blkvsc_cancel_pending_reqs(struct block_device_context *blkdev)
+ 		 */
+ 		list_for_each_entry_safe(comp_req, tmp2, &pend_req->group->blkvsc_req_list, req_entry)
+ 		{
+-			DPRINT_DBG(BLKVSC_DRV, "completing blkvsc_req %p sect_start %llu sect_count %ld \n",
++			DPRINT_DBG(BLKVSC_DRV, "completing blkvsc_req %p sect_start %lu sect_count %ld \n",
+ 				comp_req,
+-				comp_req->sector_start,
++				(unsigned long) comp_req->sector_start,
+ 				comp_req->sector_count);
+ 
+ 			if (comp_req == pend_req)

commit 78cd20035dc28f308e8c3d7a285ddfd23f129e65
+Author: Bill Pemberton 
+Date:   Mon Jul 27 16:47:25 2009 -0400
+
+    Staging: hv: StorVsc.c: fix print formatting
+    
+    There were a few places that used %lx when they should have used %x
+    and a few places that used %d when they should have used %ld
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/StorVsc.c b/drivers/staging/hv/StorVsc.c
+index ee6d88e16d6c..50057e6320af 100644
+--- a/drivers/staging/hv/StorVsc.c
++++ b/drivers/staging/hv/StorVsc.c
+@@ -271,7 +271,7 @@ StorVscInitialize(
+ 
+ 	DPRINT_ENTER(STORVSC);
+ 
+-	DPRINT_DBG(STORVSC, "sizeof(STORVSC_REQUEST)=%d sizeof(STORVSC_REQUEST_EXTENSION)=%d sizeof(VSTOR_PACKET)=%d, sizeof(VMSCSI_REQUEST)=%d",
++	DPRINT_DBG(STORVSC, "sizeof(STORVSC_REQUEST)=%ld sizeof(STORVSC_REQUEST_EXTENSION)=%ld sizeof(VSTOR_PACKET)=%ld, sizeof(VMSCSI_REQUEST)=%ld",
+ 		sizeof(STORVSC_REQUEST), sizeof(STORVSC_REQUEST_EXTENSION), sizeof(VSTOR_PACKET), sizeof(VMSCSI_REQUEST));
+ 
+ 	/* Make sure we are at least 2 pages since 1 page is used for control */
+@@ -357,7 +357,7 @@ StorVscOnDeviceAdd(
+ 	deviceInfo->PathId = storDevice->PathId;
+ 	deviceInfo->TargetId = storDevice->TargetId;
+ 
+-	DPRINT_DBG(STORVSC, "assigned port %lu, path %u target %u\n", storDevice->PortNumber, storDevice->PathId, storDevice->TargetId);
++	DPRINT_DBG(STORVSC, "assigned port %u, path %u target %u\n", storDevice->PortNumber, storDevice->PathId, storDevice->TargetId);
+ 
+ Cleanup:
+ 	DPRINT_EXIT(STORVSC);
+@@ -413,7 +413,7 @@ static int StorVscChannelInit(DEVICE_OBJECT *Device)
+ 
+ 	if (vstorPacket->Operation != VStorOperationCompleteIo || vstorPacket->Status != 0)
+ 	{
+-		DPRINT_ERR(STORVSC, "BEGIN_INITIALIZATION_OPERATION failed (op %d status 0x%lx)", vstorPacket->Operation, vstorPacket->Status);
++		DPRINT_ERR(STORVSC, "BEGIN_INITIALIZATION_OPERATION failed (op %d status 0x%x)", vstorPacket->Operation, vstorPacket->Status);
+ 		goto Cleanup;
+ 	}
+ 
+@@ -444,7 +444,7 @@ static int StorVscChannelInit(DEVICE_OBJECT *Device)
+ 	/* TODO: Check returned version */
+ 	if (vstorPacket->Operation != VStorOperationCompleteIo || vstorPacket->Status != 0)
+ 	{
+-		DPRINT_ERR(STORVSC, "QUERY_PROTOCOL_VERSION_OPERATION failed (op %d status 0x%lx)", vstorPacket->Operation, vstorPacket->Status);
++		DPRINT_ERR(STORVSC, "QUERY_PROTOCOL_VERSION_OPERATION failed (op %d status 0x%x)", vstorPacket->Operation, vstorPacket->Status);
+ 		goto Cleanup;
+ 	}
+ 
+@@ -474,7 +474,7 @@ static int StorVscChannelInit(DEVICE_OBJECT *Device)
+ 	/* TODO: Check returned version */
+ 	if (vstorPacket->Operation != VStorOperationCompleteIo || vstorPacket->Status != 0)
+ 	{
+-		DPRINT_ERR(STORVSC, "QUERY_PROPERTIES_OPERATION failed (op %d status 0x%lx)", vstorPacket->Operation, vstorPacket->Status);
++		DPRINT_ERR(STORVSC, "QUERY_PROPERTIES_OPERATION failed (op %d status 0x%x)", vstorPacket->Operation, vstorPacket->Status);
+ 		goto Cleanup;
+ 	}
+ 
+@@ -482,7 +482,7 @@ static int StorVscChannelInit(DEVICE_OBJECT *Device)
+ 	storDevice->PathId = vstorPacket->StorageChannelProperties.PathId;
+ 	storDevice->TargetId = vstorPacket->StorageChannelProperties.TargetId;
+ 
+-	DPRINT_DBG(STORVSC, "channel flag 0x%lx, max xfer len 0x%lx", vstorPacket->StorageChannelProperties.Flags, vstorPacket->StorageChannelProperties.MaxTransferBytes);
++	DPRINT_DBG(STORVSC, "channel flag 0x%x, max xfer len 0x%x", vstorPacket->StorageChannelProperties.Flags, vstorPacket->StorageChannelProperties.MaxTransferBytes);
+ 
+ 	DPRINT_INFO(STORVSC, "END_INITIALIZATION_OPERATION...");
+ 
+@@ -507,7 +507,7 @@ static int StorVscChannelInit(DEVICE_OBJECT *Device)
+ 
+ 	if (vstorPacket->Operation != VStorOperationCompleteIo || vstorPacket->Status != 0)
+ 	{
+-		DPRINT_ERR(STORVSC, "END_INITIALIZATION_OPERATION failed (op %d status 0x%lx)", vstorPacket->Operation, vstorPacket->Status);
++		DPRINT_ERR(STORVSC, "END_INITIALIZATION_OPERATION failed (op %d status 0x%x)", vstorPacket->Operation, vstorPacket->Status);
+ 		goto Cleanup;
+ 	}
+ 
+@@ -549,7 +549,7 @@ StorVscConnectToVsp(
+ 		Device
+ 		);
+ 
+-	DPRINT_DBG(STORVSC, "storage props: path id %d, tgt id %d, max xfer %ld", props.PathId, props.TargetId, props.MaxTransferBytes);
++	DPRINT_DBG(STORVSC, "storage props: path id %d, tgt id %d, max xfer %d", props.PathId, props.TargetId, props.MaxTransferBytes);
+ 
+ 	if (ret != 0)
+ 	{
+@@ -835,7 +835,7 @@ StorVscOnIOCompletion(
+ 		return;
+ 	}
+ 
+-	DPRINT_DBG(STORVSC, "IO_COMPLETE_OPERATION - request extension %p completed bytes xfer %lu",
++	DPRINT_DBG(STORVSC, "IO_COMPLETE_OPERATION - request extension %p completed bytes xfer %u",
+ 		RequestExt, VStorPacket->VmSrb.DataTransferLength);
+ 
+ 	ASSERT(RequestExt != NULL);

commit 454f18a963cf6519bf317e74e6b9781ffef8d253
+Author: Bill Pemberton 
+Date:   Mon Jul 27 16:47:24 2009 -0400
+
+    Staging: hv: Remove C99 comments
+    
+    Remove C99 // comments with traditional /* */ comments
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/BlkVsc.c b/drivers/staging/hv/BlkVsc.c
+index dc91aae6272b..7903a773ce42 100644
+--- a/drivers/staging/hv/BlkVsc.c
++++ b/drivers/staging/hv/BlkVsc.c
+@@ -26,12 +26,12 @@
+ 
+ static const char* gBlkDriverName="blkvsc";
+ 
+-//{32412632-86cb-44a2-9b5c-50d1417354f5}
++/* {32412632-86cb-44a2-9b5c-50d1417354f5} */
+ static const GUID gBlkVscDeviceType={
+ 	.Data = {0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5}
+ };
+ 
+-// Static routines
++/* Static routines */
+ static int
+ BlkVscOnDeviceAdd(
+ 	DEVICE_OBJECT	*Device,
+@@ -49,21 +49,21 @@ BlkVscInitialize(
+ 
+ 	DPRINT_ENTER(BLKVSC);
+ 
+-	// Make sure we are at least 2 pages since 1 page is used for control
++	/* Make sure we are at least 2 pages since 1 page is used for control */
+ 	ASSERT(storDriver->RingBufferSize >= (PAGE_SIZE << 1));
+ 
+ 	Driver->name = gBlkDriverName;
+ 	memcpy(&Driver->deviceType, &gBlkVscDeviceType, sizeof(GUID));
+ 
+ 	storDriver->RequestExtSize			= sizeof(STORVSC_REQUEST_EXTENSION);
+-	// Divide the ring buffer data size (which is 1 page less than the ring buffer size since that page is reserved for the ring buffer indices)
+-	// by the max request size (which is VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER + VSTOR_PACKET + u64)
++	/* Divide the ring buffer data size (which is 1 page less than the ring buffer size since that page is reserved for the ring buffer indices) */
++	/* by the max request size (which is VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER + VSTOR_PACKET + u64) */
+ 	storDriver->MaxOutstandingRequestsPerChannel =
+ 		((storDriver->RingBufferSize - PAGE_SIZE) / ALIGN_UP(MAX_MULTIPAGE_BUFFER_PACKET + sizeof(VSTOR_PACKET) + sizeof(u64),sizeof(u64)));
+ 
+ 	DPRINT_INFO(BLKVSC, "max io outstd %u", storDriver->MaxOutstandingRequestsPerChannel);
+ 
+-	// Setup the dispatch table
++	/* Setup the dispatch table */
+ 	storDriver->Base.OnDeviceAdd		= BlkVscOnDeviceAdd;
+ 	storDriver->Base.OnDeviceRemove		= StorVscOnDeviceRemove;
+ 	storDriver->Base.OnCleanup			= StorVscOnCleanup;
+@@ -95,8 +95,8 @@ BlkVscOnDeviceAdd(
+ 		return ret;
+ 	}
+ 
+-	// We need to use the device instance guid to set the path and target id. For IDE devices, the
+-	// device instance id is formatted as  -  - 8899 - 000000000000.
++	/* We need to use the device instance guid to set the path and target id. For IDE devices, the */
++	/* device instance id is formatted as  -  - 8899 - 000000000000. */
+ 	deviceInfo->PathId = Device->deviceInstance.Data[3] << 24 | Device->deviceInstance.Data[2] << 16 |
+ 		Device->deviceInstance.Data[1] << 8 |Device->deviceInstance.Data[0];
+ 
+diff --git a/drivers/staging/hv/Channel.c b/drivers/staging/hv/Channel.c
+index 2af8959e03e7..bd82154e69f1 100644
+--- a/drivers/staging/hv/Channel.c
++++ b/drivers/staging/hv/Channel.c
+@@ -27,13 +27,11 @@
+ 
+ #include "VmbusPrivate.h"
+ 
+-//
+-// Internal routines
+-//
++/* Internal routines */
+ static int
+ VmbusChannelCreateGpadlHeader(
+-	void *					Kbuffer,	// must be phys and virt contiguous
+-	u32					Size,		// page-size multiple
++	void *					Kbuffer,	/* must be phys and virt contiguous */
++	u32					Size,		/* page-size multiple */
+ 	VMBUS_CHANNEL_MSGINFO	**msgInfo,
+ 	u32					*MessageCount
+ 	);
+@@ -105,11 +103,11 @@ VmbusChannelSetEvent(
+ 
+ 	if (Channel->OfferMsg.MonitorAllocated)
+ 	{
+-		// Each u32 represents 32 channels
++		/* Each u32 represents 32 channels */
+ 		BitSet((u32*)gVmbusConnection.SendInterruptPage + (Channel->OfferMsg.ChildRelId >> 5), Channel->OfferMsg.ChildRelId & 31);
+ 
+ 		monitorPage = (HV_MONITOR_PAGE*)gVmbusConnection.MonitorPages;
+-		monitorPage++; // Get the child to parent monitor page
++		monitorPage++; /* Get the child to parent monitor page */
+ 
+ 		BitSet((u32*) &monitorPage->TriggerGroup[Channel->MonitorGroup].Pending, Channel->MonitorBit);
+ 	}
+@@ -133,11 +131,11 @@ VmbusChannelClearEvent(
+ 
+ 	if (Channel->OfferMsg.MonitorAllocated)
+ 	{
+-		// Each u32 represents 32 channels
++		/* Each u32 represents 32 channels */
+ 		BitClear((u32*)gVmbusConnection.SendInterruptPage + (Channel->OfferMsg.ChildRelId >> 5), Channel->OfferMsg.ChildRelId & 31);
+ 
+ 		monitorPage = (HV_MONITOR_PAGE*)gVmbusConnection.MonitorPages;
+-		monitorPage++; // Get the child to parent monitor page
++		monitorPage++; /* Get the child to parent monitor page */
+ 
+ 		BitClear((u32*) &monitorPage->TriggerGroup[Channel->MonitorGroup].Pending, Channel->MonitorBit);
+ 	}
+@@ -164,7 +162,7 @@ VmbusChannelGetDebugInfo(
+ 	HV_MONITOR_PAGE *monitorPage;
+     u8 monitorGroup    = (u8)Channel->OfferMsg.MonitorId / 32;
+     u8 monitorOffset   = (u8)Channel->OfferMsg.MonitorId % 32;
+-	//u32 monitorBit	= 1 << monitorOffset;
++	/* u32 monitorBit	= 1 << monitorOffset; */
+ 
+ 	DebugInfo->RelId = Channel->OfferMsg.ChildRelId;
+ 	DebugInfo->State = Channel->State;
+@@ -218,16 +216,16 @@ VmbusChannelOpen(
+ 
+ 	DPRINT_ENTER(VMBUS);
+ 
+-	// Aligned to page size
++	/* Aligned to page size */
+ 	ASSERT(!(SendRingBufferSize & (PAGE_SIZE -1)));
+ 	ASSERT(!(RecvRingBufferSize & (PAGE_SIZE -1)));
+ 
+ 	NewChannel->OnChannelCallback = pfnOnChannelCallback;
+ 	NewChannel->ChannelCallbackContext = Context;
+ 
+-	// Allocate the ring buffer
++	/* Allocate the ring buffer */
+ 	out = PageAlloc((SendRingBufferSize + RecvRingBufferSize) >> PAGE_SHIFT);
+-	//out = kzalloc(sendRingBufferSize + recvRingBufferSize, GFP_KERNEL);
++	/* out = kzalloc(sendRingBufferSize + recvRingBufferSize, GFP_KERNEL); */
+ 	ASSERT(out);
+ 	ASSERT(((unsigned long)out & (PAGE_SIZE-1)) == 0);
+ 
+@@ -240,7 +238,7 @@ VmbusChannelOpen(
+ 
+ 	RingBufferInit(&NewChannel->Inbound, in, RecvRingBufferSize);
+ 
+-	// Establish the gpadl for the ring buffer
++	/* Establish the gpadl for the ring buffer */
+ 	DPRINT_DBG(VMBUS, "Establishing ring buffer's gpadl for channel %p...", NewChannel);
+ 
+ 	NewChannel->RingBufferGpadlHandle = 0;
+@@ -260,7 +258,7 @@ VmbusChannelOpen(
+ 		NewChannel->Inbound.RingSize,
+ 		SendRingBufferSize);
+ 
+-	// Create and init the channel open message
++	/* Create and init the channel open message */
+ 	openInfo = kmalloc(sizeof(VMBUS_CHANNEL_MSGINFO) + sizeof(VMBUS_CHANNEL_OPEN_CHANNEL), GFP_KERNEL);
+ 	ASSERT(openInfo != NULL);
+ 
+@@ -268,12 +266,12 @@ VmbusChannelOpen(
+ 
+ 	openMsg = (VMBUS_CHANNEL_OPEN_CHANNEL*)openInfo->Msg;
+ 	openMsg->Header.MessageType				= ChannelMessageOpenChannel;
+-	openMsg->OpenId							= NewChannel->OfferMsg.ChildRelId; // FIXME
++	openMsg->OpenId							= NewChannel->OfferMsg.ChildRelId; /* FIXME */
+     openMsg->ChildRelId						= NewChannel->OfferMsg.ChildRelId;
+     openMsg->RingBufferGpadlHandle			= NewChannel->RingBufferGpadlHandle;
+     ASSERT(openMsg->RingBufferGpadlHandle);
+     openMsg->DownstreamRingBufferPageOffset		= SendRingBufferSize >> PAGE_SHIFT;
+-    openMsg->ServerContextAreaGpadlHandle	= 0; // TODO
++    openMsg->ServerContextAreaGpadlHandle	= 0; /* TODO */
+ 
+ 	ASSERT(UserDataLen <= MAX_USER_DEFINED_BYTES);
+ 	if (UserDataLen)
+@@ -294,7 +292,7 @@ VmbusChannelOpen(
+ 		goto Cleanup;
+ 	}
+ 
+-	// FIXME: Need to time-out here
++	/* FIXME: Need to time-out here */
+ 	WaitEventWait(openInfo->WaitEvent);
+ 
+ 	if (openInfo->Response.OpenResult.Status == 0)
+@@ -392,8 +390,8 @@ static void DumpGpadlHeader(
+ --*/
+ static int
+ VmbusChannelCreateGpadlHeader(
+-	void *					Kbuffer,	// from kmalloc()
+-	u32					Size,		// page-size multiple
++	void *					Kbuffer,	/* from kmalloc() */
++	u32					Size,		/* page-size multiple */
+ 	VMBUS_CHANNEL_MSGINFO	**MsgInfo,
+ 	u32					*MessageCount)
+ {
+@@ -408,19 +406,19 @@ VmbusChannelCreateGpadlHeader(
+ 
+ 	int pfnSum, pfnCount, pfnLeft, pfnCurr, pfnSize;
+ 
+-	//ASSERT( (kbuffer & (PAGE_SIZE-1)) == 0);
++	/* ASSERT( (kbuffer & (PAGE_SIZE-1)) == 0); */
+ 	ASSERT( (Size & (PAGE_SIZE-1)) == 0);
+ 
+ 	pageCount = Size >> PAGE_SHIFT;
+ 	pfn = GetPhysicalAddress(Kbuffer) >> PAGE_SHIFT;
+ 
+-	// do we need a gpadl body msg
++	/* do we need a gpadl body msg */
+ 	pfnSize = MAX_SIZE_CHANNEL_MESSAGE - sizeof(VMBUS_CHANNEL_GPADL_HEADER) - sizeof(GPA_RANGE);
+ 	pfnCount = pfnSize / sizeof(u64);
+ 
+-	if (pageCount > pfnCount) // we need a gpadl body
++	if (pageCount > pfnCount) /* we need a gpadl body */
+ 	{
+-		// fill in the header
++		/* fill in the header */
+ 		msgSize = sizeof(VMBUS_CHANNEL_MSGINFO) + sizeof(VMBUS_CHANNEL_GPADL_HEADER) + sizeof(GPA_RANGE) + pfnCount*sizeof(u64);
+ 		msgHeader =  kzalloc(msgSize, GFP_KERNEL);
+ 
+@@ -442,11 +440,11 @@ VmbusChannelCreateGpadlHeader(
+ 		pfnSum = pfnCount;
+ 		pfnLeft = pageCount - pfnCount;
+ 
+-		// how many pfns can we fit
++		/* how many pfns can we fit */
+ 		pfnSize = MAX_SIZE_CHANNEL_MESSAGE - sizeof(VMBUS_CHANNEL_GPADL_BODY);
+ 		pfnCount = pfnSize / sizeof(u64);
+ 
+-		// fill in the body
++		/* fill in the body */
+ 		while (pfnLeft)
+ 		{
+ 			if (pfnLeft > pfnCount)
+@@ -465,14 +463,14 @@ VmbusChannelCreateGpadlHeader(
+ 			(*MessageCount)++;
+ 			gpadlBody = (VMBUS_CHANNEL_GPADL_BODY*)msgBody->Msg;
+ 
+-			// FIXME: Gpadl is u32 and we are using a pointer which could be 64-bit
+-			//gpadlBody->Gpadl = kbuffer;
++			/* FIXME: Gpadl is u32 and we are using a pointer which could be 64-bit */
++			/* gpadlBody->Gpadl = kbuffer; */
+ 			for (i=0; iPfn[i] = pfn + pfnSum + i;
+ 			}
+ 
+-			// add to msg header
++			/* add to msg header */
+ 			INSERT_TAIL_LIST(&msgHeader->SubMsgList, &msgBody->MsgListEntry);
+ 			pfnSum += pfnCurr;
+ 			pfnLeft -= pfnCurr;
+@@ -480,7 +478,7 @@ VmbusChannelCreateGpadlHeader(
+ 	}
+ 	else
+ 	{
+-		// everything fits in a header
++		/* everything fits in a header */
+ 		msgSize = sizeof(VMBUS_CHANNEL_MSGINFO) + sizeof(VMBUS_CHANNEL_GPADL_HEADER) + sizeof(GPA_RANGE) + pageCount*sizeof(u64);
+ 		msgHeader = kzalloc(msgSize, GFP_KERNEL);
+ 		msgHeader->MessageSize=msgSize;
+@@ -515,15 +513,15 @@ VmbusChannelCreateGpadlHeader(
+ int
+ VmbusChannelEstablishGpadl(
+ 	VMBUS_CHANNEL	*Channel,
+-	void *			Kbuffer,	// from kmalloc()
+-	u32			Size,		// page-size multiple
++	void *			Kbuffer,	/* from kmalloc() */
++	u32			Size,		/* page-size multiple */
+ 	u32			*GpadlHandle
+ 	)
+ {
+ 	int ret=0;
+ 	VMBUS_CHANNEL_GPADL_HEADER* gpadlMsg;
+ 	VMBUS_CHANNEL_GPADL_BODY* gpadlBody;
+-	//VMBUS_CHANNEL_GPADL_CREATED* gpadlCreated;
++	/* VMBUS_CHANNEL_GPADL_CREATED* gpadlCreated; */
+ 
+ 	VMBUS_CHANNEL_MSGINFO *msgInfo;
+ 	VMBUS_CHANNEL_MSGINFO *subMsgInfo;
+@@ -585,7 +583,7 @@ VmbusChannelEstablishGpadl(
+ 	}
+ 	WaitEventWait(msgInfo->WaitEvent);
+ 
+-	// At this point, we received the gpadl created msg
++	/* At this point, we received the gpadl created msg */
+ 	DPRINT_DBG(VMBUS, "Received GPADL created (relid %d, status %d handle %x)",
+ 		Channel->OfferMsg.ChildRelId,
+ 		msgInfo->Response.GpadlCreated.CreationStatus,
+@@ -650,12 +648,12 @@ VmbusChannelTeardownGpadl(
+ 	ret = VmbusPostMessage(msg, sizeof(VMBUS_CHANNEL_GPADL_TEARDOWN));
+ 	if (ret != 0)
+ 	{
+-		// TODO:
++		/* TODO: */
+ 	}
+ 
+ 	WaitEventWait(info->WaitEvent);
+ 
+-	// Received a torndown response
++	/* Received a torndown response */
+ 	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
+ 	REMOVE_ENTRY_LIST(&info->MsgListEntry);
+ 	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
+@@ -690,15 +688,15 @@ VmbusChannelClose(
+ 
+ 	DPRINT_ENTER(VMBUS);
+ 
+-	// Stop callback and cancel the timer asap
++	/* Stop callback and cancel the timer asap */
+ 	Channel->OnChannelCallback = NULL;
+ 	TimerStop(Channel->PollTimer);
+ 
+-	// Send a closing message
++	/* Send a closing message */
+ 	info = kmalloc(sizeof(VMBUS_CHANNEL_MSGINFO) + sizeof(VMBUS_CHANNEL_CLOSE_CHANNEL), GFP_KERNEL);
+ 	ASSERT(info != NULL);
+ 
+-	//info->waitEvent = WaitEventCreate();
++	/* info->waitEvent = WaitEventCreate(); */
+ 
+ 	msg = (VMBUS_CHANNEL_CLOSE_CHANNEL*)info->Msg;
+ 	msg->Header.MessageType				= ChannelMessageCloseChannel;
+@@ -707,18 +705,18 @@ VmbusChannelClose(
+ 	ret = VmbusPostMessage(msg, sizeof(VMBUS_CHANNEL_CLOSE_CHANNEL));
+ 	if (ret != 0)
+ 	{
+-		// TODO:
++		/* TODO: */
+ 	}
+ 
+-	// Tear down the gpadl for the channel's ring buffer
++	/* Tear down the gpadl for the channel's ring buffer */
+ 	if (Channel->RingBufferGpadlHandle)
+ 	{
+ 		VmbusChannelTeardownGpadl(Channel, Channel->RingBufferGpadlHandle);
+ 	}
+ 
+-	// TODO: Send a msg to release the childRelId
++	/* TODO: Send a msg to release the childRelId */
+ 
+-	// Cleanup the ring buffers for this channel
++	/* Cleanup the ring buffers for this channel */
+ 	RingBufferCleanup(&Channel->Outbound);
+ 	RingBufferCleanup(&Channel->Inbound);
+ 
+@@ -726,8 +724,13 @@ VmbusChannelClose(
+ 
+ 	kfree(info);
+ 
+-	// If we are closing the channel during an error path in opening the channel, don't free the channel
+-	// since the caller will free the channel
++
++	/*
++	 * If we are closing the channel during an error path in
++	 * opening the channel, don't free the channel since the
++	 * caller will free the channel
++	 */
++
+ 	if (Channel->State == CHANNEL_OPEN_STATE)
+ 	{
+ 		spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
+@@ -774,12 +777,12 @@ VmbusChannelSendPacket(
+ 
+ 	ASSERT((packetLenAligned - packetLen) < sizeof(u64));
+ 
+-	// Setup the descriptor
+-	desc.Type = Type;//VmbusPacketTypeDataInBand;
+-	desc.Flags = Flags;//VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
+-    desc.DataOffset8 = sizeof(VMPACKET_DESCRIPTOR) >> 3; // in 8-bytes granularity
+-    desc.Length8 = (u16)(packetLenAligned >> 3);
+-    desc.TransactionId = RequestId;
++	/* Setup the descriptor */
++	desc.Type = Type; /* VmbusPacketTypeDataInBand; */
++	desc.Flags = Flags; /* VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; */
++	desc.DataOffset8 = sizeof(VMPACKET_DESCRIPTOR) >> 3; /* in 8-bytes granularity */
++	desc.Length8 = (u16)(packetLenAligned >> 3);
++	desc.TransactionId = RequestId;
+ 
+ 	bufferList[0].Data = &desc;
+ 	bufferList[0].Length = sizeof(VMPACKET_DESCRIPTOR);
+@@ -795,7 +798,7 @@ VmbusChannelSendPacket(
+ 		bufferList,
+ 		3);
+ 
+-	// TODO: We should determine if this is optional
++	/* TODO: We should determine if this is optional */
+ 	if (ret == 0 && !GetRingBufferInterruptMask(&Channel->Outbound))
+ 	{
+ 		VmbusChannelSetEvent(Channel);
+@@ -841,19 +844,19 @@ VmbusChannelSendPacketPageBuffer(
+ 
+ 	DumpVmbusChannel(Channel);
+ 
+-	// Adjust the size down since VMBUS_CHANNEL_PACKET_PAGE_BUFFER is the largest size we support
++	/* Adjust the size down since VMBUS_CHANNEL_PACKET_PAGE_BUFFER is the largest size we support */
+ 	descSize = sizeof(VMBUS_CHANNEL_PACKET_PAGE_BUFFER) - ((MAX_PAGE_BUFFER_COUNT - PageCount)*sizeof(PAGE_BUFFER));
+ 	packetLen = descSize + BufferLen;
+ 	packetLenAligned = ALIGN_UP(packetLen, sizeof(u64));
+ 
+ 	ASSERT((packetLenAligned - packetLen) < sizeof(u64));
+ 
+-	// Setup the descriptor
++	/* Setup the descriptor */
+ 	desc.Type = VmbusPacketTypeDataUsingGpaDirect;
+ 	desc.Flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
+-    desc.DataOffset8 = descSize >> 3; // in 8-bytes grandularity
+-    desc.Length8 = (u16)(packetLenAligned >> 3);
+-    desc.TransactionId = RequestId;
++	desc.DataOffset8 = descSize >> 3; /* in 8-bytes grandularity */
++	desc.Length8 = (u16)(packetLenAligned >> 3);
++	desc.TransactionId = RequestId;
+ 	desc.RangeCount = PageCount;
+ 
+ 	for (i=0; iOutbound))
+ 	{
+ 		VmbusChannelSetEvent(Channel);
+@@ -926,19 +929,19 @@ VmbusChannelSendPacketMultiPageBuffer(
+ 	ASSERT(PfnCount > 0);
+ 	ASSERT(PfnCount <= MAX_MULTIPAGE_BUFFER_COUNT);
+ 
+-	// Adjust the size down since VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER is the largest size we support
++	/* Adjust the size down since VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER is the largest size we support */
+ 	descSize = sizeof(VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER) - ((MAX_MULTIPAGE_BUFFER_COUNT - PfnCount)*sizeof(u64));
+ 	packetLen = descSize + BufferLen;
+ 	packetLenAligned = ALIGN_UP(packetLen, sizeof(u64));
+ 
+ 	ASSERT((packetLenAligned - packetLen) < sizeof(u64));
+ 
+-	// Setup the descriptor
++	/* Setup the descriptor */
+ 	desc.Type = VmbusPacketTypeDataUsingGpaDirect;
+ 	desc.Flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
+-    desc.DataOffset8 = descSize >> 3; // in 8-bytes grandularity
+-    desc.Length8 = (u16)(packetLenAligned >> 3);
+-    desc.TransactionId = RequestId;
++	desc.DataOffset8 = descSize >> 3; /* in 8-bytes grandularity */
++	desc.Length8 = (u16)(packetLenAligned >> 3);
++	desc.TransactionId = RequestId;
+ 	desc.RangeCount = 1;
+ 
+ 	desc.Range.Length = MultiPageBuffer->Length;
+@@ -960,7 +963,7 @@ VmbusChannelSendPacketMultiPageBuffer(
+ 		bufferList,
+ 		3);
+ 
+-	// TODO: We should determine if this is optional
++	/* TODO: We should determine if this is optional */
+ 	if (ret == 0 && !GetRingBufferInterruptMask(&Channel->Outbound))
+ 	{
+ 		VmbusChannelSetEvent(Channel);
+@@ -981,7 +984,7 @@ VmbusChannelSendPacketMultiPageBuffer(
+ 	Retrieve the user packet on the specified channel
+ 
+ --*/
+-// TODO: Do we ever receive a gpa direct packet other than the ones we send ?
++/* TODO: Do we ever receive a gpa direct packet other than the ones we send ? */
+ int
+ VmbusChannelRecvPacket(
+ 	VMBUS_CHANNEL		*Channel,
+@@ -1009,16 +1012,16 @@ VmbusChannelRecvPacket(
+ 	{
+ 		spin_unlock_irqrestore(&Channel->inbound_lock, flags);
+ 
+-		//DPRINT_DBG(VMBUS, "nothing to read!!");
++		/* DPRINT_DBG(VMBUS, "nothing to read!!"); */
+ 		DPRINT_EXIT(VMBUS);
+ 		return 0;
+ 	}
+ 
+-	//VmbusChannelClearEvent(Channel);
++	/* VmbusChannelClearEvent(Channel); */
+ 
+ 	packetLen = desc.Length8 << 3;
+ 	userLen = packetLen - (desc.DataOffset8 << 3);
+-	//ASSERT(userLen > 0);
++	/* ASSERT(userLen > 0); */
+ 
+ 	DPRINT_DBG(VMBUS, "packet received on channel %p relid %d  ",
+ 		Channel,
+@@ -1041,7 +1044,7 @@ VmbusChannelRecvPacket(
+ 
+ 	*RequestId = desc.TransactionId;
+ 
+-	// Copy over the packet to the user buffer
++	/* Copy over the packet to the user buffer */
+ 	ret = RingBufferRead(&Channel->Inbound, Buffer, userLen, (desc.DataOffset8 << 3));
+ 
+ 	spin_unlock_irqrestore(&Channel->inbound_lock, flags);
+@@ -1087,12 +1090,12 @@ VmbusChannelRecvPacketRaw(
+ 	{
+ 		spin_unlock_irqrestore(&Channel->inbound_lock, flags);
+ 
+-		//DPRINT_DBG(VMBUS, "nothing to read!!");
++		/* DPRINT_DBG(VMBUS, "nothing to read!!"); */
+ 		DPRINT_EXIT(VMBUS);
+ 		return 0;
+ 	}
+ 
+-	//VmbusChannelClearEvent(Channel);
++	/* VmbusChannelClearEvent(Channel); */
+ 
+ 	packetLen = desc.Length8 << 3;
+ 	userLen = packetLen - (desc.DataOffset8 << 3);
+@@ -1117,7 +1120,7 @@ VmbusChannelRecvPacketRaw(
+ 
+ 	*RequestId = desc.TransactionId;
+ 
+-	// Copy over the entire packet to the user buffer
++	/* Copy over the entire packet to the user buffer */
+ 	ret = RingBufferRead(&Channel->Inbound, Buffer, packetLen, 0);
+ 
+ 	spin_unlock_irqrestore(&Channel->inbound_lock, flags);
+@@ -1199,4 +1202,4 @@ DumpVmbusChannel(
+ }
+ 
+ 
+-// eof
++/* eof */
+diff --git a/drivers/staging/hv/Channel.h b/drivers/staging/hv/Channel.h
+index dee444c35137..be65d64e4590 100644
+--- a/drivers/staging/hv/Channel.h
++++ b/drivers/staging/hv/Channel.h
+@@ -31,7 +31,7 @@
+ #pragma pack(push,1)
+ 
+ 
+-// The format must be the same as VMDATA_GPA_DIRECT
++/* The format must be the same as VMDATA_GPA_DIRECT */
+ typedef struct _VMBUS_CHANNEL_PACKET_PAGE_BUFFER {
+     u16				Type;
+     u16				DataOffset8;
+@@ -44,7 +44,7 @@ typedef struct _VMBUS_CHANNEL_PACKET_PAGE_BUFFER {
+ } VMBUS_CHANNEL_PACKET_PAGE_BUFFER;
+ 
+ 
+-// The format must be the same as VMDATA_GPA_DIRECT
++/* The format must be the same as VMDATA_GPA_DIRECT */
+ typedef struct _VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER {
+     u16				Type;
+     u16				DataOffset8;
+@@ -52,15 +52,15 @@ typedef struct _VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER {
+     u16				Flags;
+     u64				TransactionId;
+ 	u32				Reserved;
+-	u32				RangeCount;		// Always 1 in this case
++	u32				RangeCount;		/* Always 1 in this case */
+ 	MULTIPAGE_BUFFER	Range;
+ } VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER;
+ 
+ #pragma pack(pop)
+ 
+-//
+-// Routines
+-//
++
++/* Routines */
++
+ 
+ static int
+ VmbusChannelOpen(
+@@ -110,8 +110,8 @@ VmbusChannelSendPacketMultiPageBuffer(
+ static int
+ VmbusChannelEstablishGpadl(
+ 	VMBUS_CHANNEL		*Channel,
+-	void *				Kbuffer,	// from kmalloc()
+-	u32				Size,		// page-size multiple
++	void *				Kbuffer,	/* from kmalloc() */
++	u32				Size,		/* page-size multiple */
+ 	u32				*GpadlHandle
+ 	);
+ 
+@@ -154,4 +154,4 @@ static void
+ VmbusChannelOnTimer(
+ 	void		*Context
+ 	);
+-#endif //_CHANNEL_H_
++#endif /* _CHANNEL_H_ */
+diff --git a/drivers/staging/hv/ChannelInterface.h b/drivers/staging/hv/ChannelInterface.h
+index c459e0e23fd5..edd1c37f5730 100644
+--- a/drivers/staging/hv/ChannelInterface.h
++++ b/drivers/staging/hv/ChannelInterface.h
+@@ -38,4 +38,4 @@ GetChannelInfo(
+ 	DEVICE_INFO			*DeviceInfo
+ 	);
+ 
+-#endif // _CHANNEL_INTERFACE_H_
++#endif /* _CHANNEL_INTERFACE_H_ */
+diff --git a/drivers/staging/hv/ChannelMgmt.c b/drivers/staging/hv/ChannelMgmt.c
+index 0af4402789bb..9da574082743 100644
+--- a/drivers/staging/hv/ChannelMgmt.c
++++ b/drivers/staging/hv/ChannelMgmt.c
+@@ -27,13 +27,7 @@
+ 
+ #include "VmbusPrivate.h"
+ 
+-//
+-// Defines
+-//
+-
+-//
+-// Data types
+-//
++/* Data types */
+ 
+ typedef void (*PFN_CHANNEL_MESSAGE_HANDLER)(VMBUS_CHANNEL_MESSAGE_HEADER* msg);
+ 
+@@ -42,9 +36,7 @@ typedef struct _VMBUS_CHANNEL_MESSAGE_TABLE_ENTRY {
+ 	PFN_CHANNEL_MESSAGE_HANDLER messageHandler;
+ } VMBUS_CHANNEL_MESSAGE_TABLE_ENTRY;
+ 
+-//
+-// Internal routines
+-//
++/* Internal routines */
+ 
+ static void
+ VmbusChannelOnOffer(
+@@ -91,25 +83,23 @@ VmbusChannelProcessRescindOffer(
+ 	);
+ 
+ 
+-//
+-// Globals
+-//
++/* Globals */
+ 
+ #define MAX_NUM_DEVICE_CLASSES_SUPPORTED 4
+ 
+ const GUID gSupportedDeviceClasses[MAX_NUM_DEVICE_CLASSES_SUPPORTED]= {
+-	//{ba6163d9-04a1-4d29-b605-72e2ffb1dc7f}
+-	{.Data  = {0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f}},// Storage - SCSI
+-	//{F8615163-DF3E-46c5-913F-F2D2F965ED0E}
+-	{.Data = {0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E}},	// Network
+-	//{CFA8B69E-5B4A-4cc0-B98B-8BA1A1F3F95A}
+-	{.Data = {0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c, 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A}}, // Input
+-	//{32412632-86cb-44a2-9b5c-50d1417354f5}
+-	{.Data = {0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5}}, // IDE
++	/* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */
++	{.Data  = {0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f}},/* Storage - SCSI */
++	/* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */
++	{.Data = {0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E}},	/* Network */
++	/* {CFA8B69E-5B4A-4cc0-B98B-8BA1A1F3F95A} */
++	{.Data = {0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c, 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A}}, /* Input */
++	/* {32412632-86cb-44a2-9b5c-50d1417354f5} */
++	{.Data = {0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5}}, /* IDE */
+ 
+ };
+ 
+-// Channel message dispatch table
++/* Channel message dispatch table */
+ VMBUS_CHANNEL_MESSAGE_TABLE_ENTRY gChannelMessageTable[ChannelMessageCount]= {
+     {ChannelMessageInvalid,					NULL},
+     {ChannelMessageOfferChannel,            VmbusChannelOnOffer},
+@@ -158,7 +148,7 @@ VMBUS_CHANNEL* AllocVmbusChannel(void)
+ 		return NULL;
+ 	}
+ 
+-	//channel->dataWorkQueue = WorkQueueCreate("data");
++	/* channel->dataWorkQueue = WorkQueueCreate("data"); */
+ 	channel->ControlWQ = WorkQueueCreate("control");
+ 	if (!channel->ControlWQ)
+ 	{
+@@ -207,8 +197,8 @@ void FreeVmbusChannel(VMBUS_CHANNEL* Channel)
+ {
+ 	TimerClose(Channel->PollTimer);
+ 
+-	// We have to release the channel's workqueue/thread in the vmbus's workqueue/thread context
+-	// ie we can't destroy ourselves.
++	/* We have to release the channel's workqueue/thread in the vmbus's workqueue/thread context */
++	/* ie we can't destroy ourselves. */
+ 	WorkQueueQueueWorkItem(gVmbusConnection.WorkQueue, ReleaseVmbusChannel, (void*)Channel);
+ }
+ 
+@@ -237,7 +227,7 @@ VmbusChannelProcessOffer(
+ 
+ 	DPRINT_ENTER(VMBUS);
+ 
+-	// Make sure this is a new offer
++	/* Make sure this is a new offer */
+ 	spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
+ 
+ 	ITERATE_LIST_ENTRIES(anchor, curr, &gVmbusConnection.ChannelList)
+@@ -266,8 +256,8 @@ VmbusChannelProcessOffer(
+ 		return;
+ 	}
+ 
+-	// Start the process of binding this offer to the driver
+-	// We need to set the DeviceObject field before calling VmbusChildDeviceAdd()
++	/* Start the process of binding this offer to the driver */
++	/* We need to set the DeviceObject field before calling VmbusChildDeviceAdd() */
+ 	newChannel->DeviceObject = VmbusChildDeviceCreate(
+ 		newChannel->OfferMsg.Offer.InterfaceType,
+ 		newChannel->OfferMsg.Offer.InterfaceInstance,
+@@ -275,8 +265,12 @@ VmbusChannelProcessOffer(
+ 
+ 	DPRINT_DBG(VMBUS, "child device object allocated - %p", newChannel->DeviceObject);
+ 
+-	// Add the new device to the bus. This will kick off device-driver binding
+-	// which eventually invokes the device driver's AddDevice() method.
++	/*
++	 * Add the new device to the bus. This will kick off device-driver
++	 * binding which eventually invokes the device driver's AddDevice()
++	 * method.
++	 */
++
+ 	ret = VmbusChildDeviceAdd(newChannel->DeviceObject);
+ 	if (ret != 0)
+ 	{
+@@ -291,8 +285,11 @@ VmbusChannelProcessOffer(
+ 	}
+ 	else
+ 	{
+-		// This state is used to indicate a successful open so that when we do close the channel normally,
+-		// we can cleanup properly
++		/*
++		 * This state is used to indicate a successful open
++		 * so that when we do close the channel normally, we
++		 * can cleanup properly
++		 */
+ 		newChannel->State = CHANNEL_OPEN_STATE;
+ 	}
+ 	DPRINT_EXIT(VMBUS);
+@@ -377,7 +374,7 @@ VmbusChannelOnOffer(
+ 		guidType->Data[3], guidType->Data[2], guidType->Data[1], guidType->Data[0], guidType->Data[5], guidType->Data[4], guidType->Data[7], guidType->Data[6], guidType->Data[8], guidType->Data[9], guidType->Data[10], guidType->Data[11], guidType->Data[12], guidType->Data[13], guidType->Data[14], guidType->Data[15],
+ 		guidInstance->Data[3], guidInstance->Data[2], guidInstance->Data[1], guidInstance->Data[0], guidInstance->Data[5], guidInstance->Data[4], guidInstance->Data[7], guidInstance->Data[6], guidInstance->Data[8], guidInstance->Data[9], guidInstance->Data[10], guidInstance->Data[11], guidInstance->Data[12], guidInstance->Data[13], guidInstance->Data[14], guidInstance->Data[15]);
+ 
+-	// Allocate the channel object and save this offer.
++	/* Allocate the channel object and save this offer. */
+ 	newChannel = AllocVmbusChannel();
+ 	if (!newChannel)
+ 	{
+@@ -391,7 +388,7 @@ VmbusChannelOnOffer(
+ 	newChannel->MonitorGroup = (u8)offer->MonitorId / 32;
+ 	newChannel->MonitorBit = (u8)offer->MonitorId % 32;
+ 
+-	// TODO: Make sure the offer comes from our parent partition
++	/* TODO: Make sure the offer comes from our parent partition */
+ 	WorkQueueQueueWorkItem(newChannel->ControlWQ, VmbusChannelProcessOffer, newChannel);
+ 
+ 	DPRINT_EXIT(VMBUS);
+@@ -479,7 +476,7 @@ VmbusChannelOnOpenResult(
+ 
+ 	DPRINT_DBG(VMBUS, "vmbus open result - %d", result->Status);
+ 
+-	// Find the open msg, copy the result and signal/unblock the wait event
++	/* Find the open msg, copy the result and signal/unblock the wait event */
+ 	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
+ 
+ 	ITERATE_LIST_ENTRIES(anchor, curr, &gVmbusConnection.ChannelMsgList)
+@@ -533,7 +530,7 @@ VmbusChannelOnGpadlCreated(
+ 
+ 	DPRINT_DBG(VMBUS, "vmbus gpadl created result - %d", gpadlCreated->CreationStatus);
+ 
+-	// Find the establish msg, copy the result and signal/unblock the wait event
++	/* Find the establish msg, copy the result and signal/unblock the wait event */
+ 	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
+ 
+ 	ITERATE_LIST_ENTRIES(anchor, curr, &gVmbusConnection.ChannelMsgList)
+@@ -586,7 +583,7 @@ VmbusChannelOnGpadlTorndown(
+ 
+ 	DPRINT_ENTER(VMBUS);
+ 
+-	// Find the open msg, copy the result and signal/unblock the wait event
++	/* Find the open msg, copy the result and signal/unblock the wait event */
+ 	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
+ 
+ 	ITERATE_LIST_ENTRIES(anchor, curr, &gVmbusConnection.ChannelMsgList)
+@@ -702,7 +699,7 @@ VmbusOnChannelMessage(
+ 		DPRINT_ERR(VMBUS, "Unhandled channel message type %d", hdr->MessageType);
+ 	}
+ 
+-	// Free the msg that was allocated in VmbusOnMsgDPC()
++	/* Free the msg that was allocated in VmbusOnMsgDPC() */
+ 	kfree(msg);
+ 	DPRINT_EXIT(VMBUS);
+ }
+@@ -751,7 +748,7 @@ VmbusChannelRequestOffers(
+ 
+ 		goto Cleanup;
+ 	}
+-	//WaitEventWait(msgInfo->waitEvent);
++	/* WaitEventWait(msgInfo->waitEvent); */
+ 
+ 	/*SpinlockAcquire(gVmbusConnection.channelMsgLock);
+ 	REMOVE_ENTRY_LIST(&msgInfo->msgListEntry);
+@@ -819,5 +816,4 @@ VmbusChannelReleaseUnattachedChannels(
+ 	spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
+ }
+ 
+-// eof
+-
++/* eof */
+diff --git a/drivers/staging/hv/ChannelMgmt.h b/drivers/staging/hv/ChannelMgmt.h
+index b7afecad0459..c4aa95c3f39a 100644
+--- a/drivers/staging/hv/ChannelMgmt.h
++++ b/drivers/staging/hv/ChannelMgmt.h
+@@ -47,27 +47,27 @@ typedef struct _VMBUS_CHANNEL {
+ 
+ 	DEVICE_OBJECT*				DeviceObject;
+ 
+-	HANDLE						PollTimer; // SA-111 workaround
++	HANDLE						PollTimer; /* SA-111 workaround */
+ 
+ 	VMBUS_CHANNEL_STATE			State;
+ 
+ 	VMBUS_CHANNEL_OFFER_CHANNEL OfferMsg;
+-	// These are based on the OfferMsg.MonitorId. Save it here for easy access.
++	/* These are based on the OfferMsg.MonitorId. Save it here for easy access. */
+ 	u8						MonitorGroup;
+ 	u8						MonitorBit;
+ 
+ 	u32						RingBufferGpadlHandle;
+ 
+-	// Allocated memory for ring buffer
++	/* Allocated memory for ring buffer */
+ 	void *						RingBufferPages;
+ 	u32						RingBufferPageCount;
+-	RING_BUFFER_INFO			Outbound;	// send to parent
+-	RING_BUFFER_INFO			Inbound;	// receive from parent
++	RING_BUFFER_INFO			Outbound;	/* send to parent */
++	RING_BUFFER_INFO			Inbound;	/* receive from parent */
+ 	spinlock_t inbound_lock;
+ 	HANDLE						ControlWQ;
+ 
+-	// Channel callback are invoked in this workqueue context
+-	//HANDLE						dataWorkQueue;
++	/* Channel callback are invoked in this workqueue context */
++	/* HANDLE						dataWorkQueue; */
+ 
+ 	PFN_CHANNEL_CALLBACK		OnChannelCallback;
+ 	void *						ChannelCallbackContext;
+@@ -102,31 +102,31 @@ typedef union {
+ } VMBUS_CHANNEL_MESSAGE_RESPONSE;
+ 
+ 
+-// Represents each channel msg on the vmbus connection
+-// This is a variable-size data structure depending on
+-// the msg type itself
++/*
++ * Represents each channel msg on the vmbus connection This is a
++ * variable-size data structure depending on the msg type itself
++ */
++
+ typedef struct _VMBUS_CHANNEL_MSGINFO {
+-	// Bookkeeping stuff
++	/* Bookkeeping stuff */
+ 	LIST_ENTRY		MsgListEntry;
+ 
+-	// So far, this is only used to handle gpadl body message
++	/* So far, this is only used to handle gpadl body message */
+ 	LIST_ENTRY		SubMsgList;
+ 
+-	// Synchronize the request/response if needed
++	/* Synchronize the request/response if needed */
+ 	HANDLE			WaitEvent;
+ 
+ 	VMBUS_CHANNEL_MESSAGE_RESPONSE Response;
+ 
+ 	u32			MessageSize;
+-	// The channel message that goes out on the "wire".
+-	// It will contain at minimum the VMBUS_CHANNEL_MESSAGE_HEADER header
++	/* The channel message that goes out on the "wire". */
++	/* It will contain at minimum the VMBUS_CHANNEL_MESSAGE_HEADER header */
+ 	unsigned char	Msg[0];
+ } VMBUS_CHANNEL_MSGINFO;
+ 
+ 
+-//
+-// Routines
+-//
++/* Routines */
+ 
+ static VMBUS_CHANNEL*
+ AllocVmbusChannel(
+@@ -153,4 +153,4 @@ VmbusChannelReleaseUnattachedChannels(
+ 	void
+ 	);
+ 
+-#endif //_CHANNEL_MGMT_H_
++#endif /* _CHANNEL_MGMT_H_ */
+diff --git a/drivers/staging/hv/Connection.c b/drivers/staging/hv/Connection.c
+index 78889bdda931..68f3a07371ed 100644
+--- a/drivers/staging/hv/Connection.c
++++ b/drivers/staging/hv/Connection.c
+@@ -26,9 +26,7 @@
+ 
+ #include "VmbusPrivate.h"
+ 
+-//
+-// Globals
+-//
++/* Globals */
+ 
+ 
+ VMBUS_CONNECTION gVmbusConnection = {
+@@ -57,11 +55,11 @@ VmbusConnect(
+ 
+ 	DPRINT_ENTER(VMBUS);
+ 
+-	// Make sure we are not connecting or connected
++	/* Make sure we are not connecting or connected */
+ 	if (gVmbusConnection.ConnectState != Disconnected)
+ 		return -1;
+ 
+-	// Initialize the vmbus connection
++	/* Initialize the vmbus connection */
+ 	gVmbusConnection.ConnectState = Connecting;
+ 	gVmbusConnection.WorkQueue = WorkQueueCreate("vmbusQ");
+ 
+@@ -71,7 +69,10 @@ VmbusConnect(
+ 	INITIALIZE_LIST_HEAD(&gVmbusConnection.ChannelList);
+ 	spin_lock_init(&gVmbusConnection.channel_lock);
+ 
+-	// Setup the vmbus event connection for channel interrupt abstraction stuff
++	/*
++	 * Setup the vmbus event connection for channel interrupt
++	 * abstraction stuff
++	 */
+ 	gVmbusConnection.InterruptPage = PageAlloc(1);
+ 	if (gVmbusConnection.InterruptPage == NULL)
+ 	{
+@@ -82,7 +83,10 @@ VmbusConnect(
+ 	gVmbusConnection.RecvInterruptPage = gVmbusConnection.InterruptPage;
+ 	gVmbusConnection.SendInterruptPage = (void*)((unsigned long)gVmbusConnection.InterruptPage + (PAGE_SIZE >> 1));
+ 
+-	// Setup the monitor notification facility. The 1st page for parent->child and the 2nd page for child->parent
++	/* Setup the monitor
++	 * notification facility. The 1st page for parent->child and
++	 * the 2nd page for child->parent
++	 */
+ 	gVmbusConnection.MonitorPages = PageAlloc(2);
+ 	if (gVmbusConnection.MonitorPages == NULL)
+ 	{
+@@ -106,8 +110,10 @@ VmbusConnect(
+ 	msg->MonitorPage1 = GetPhysicalAddress(gVmbusConnection.MonitorPages);
+ 	msg->MonitorPage2 = GetPhysicalAddress((void *)((unsigned long)gVmbusConnection.MonitorPages + PAGE_SIZE));
+ 
+-	// Add to list before we send the request since we may receive the response
+-	// before returning from this routine
++	/*
++	 * Add to list before we send the request since we may
++	 * receive the response before returning from this routine
++	 */
+ 	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
+ 	INSERT_TAIL_LIST(&gVmbusConnection.ChannelMsgList, &msgInfo->MsgListEntry);
+ 	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
+@@ -124,12 +130,12 @@ VmbusConnect(
+ 		goto Cleanup;
+ 	}
+ 
+-	// Wait for the connection response
++	/* Wait for the connection response */
+ 	WaitEventWait(msgInfo->WaitEvent);
+ 
+ 	REMOVE_ENTRY_LIST(&msgInfo->MsgListEntry);
+ 
+-	// Check if successful
++	/* Check if successful */
+ 	if (msgInfo->Response.VersionResponse.VersionSupported)
+ 	{
+ 		DPRINT_INFO(VMBUS, "Vmbus connected!!");
+@@ -202,7 +208,7 @@ VmbusDisconnect(
+ 
+ 	DPRINT_ENTER(VMBUS);
+ 
+-	// Make sure we are connected
++	/* Make sure we are connected */
+ 	if (gVmbusConnection.ConnectState != Connected)
+ 		return -1;
+ 
+@@ -219,7 +225,7 @@ VmbusDisconnect(
+ 
+ 	PageFree(gVmbusConnection.InterruptPage, 1);
+ 
+-	// TODO: iterate thru the msg list and free up
++	/* TODO: iterate thru the msg list and free up */
+ 
+ 	WorkQueueClose(gVmbusConnection.WorkQueue);
+ 
+@@ -296,18 +302,20 @@ VmbusProcessChannelEvent(
+ 
+ 	ASSERT(relId > 0);
+ 
+-	// Find the channel based on this relid and invokes
+-	// the channel callback to process the event
++	/*
++	 * Find the channel based on this relid and invokes the
++	 * channel callback to process the event
++	 */
+ 	channel = GetChannelFromRelId(relId);
+ 
+ 	if (channel)
+ 	{
+ 		VmbusChannelOnChannelEvent(channel);
+-		//WorkQueueQueueWorkItem(channel->dataWorkQueue, VmbusChannelOnChannelEvent, (void*)channel);
++		/* WorkQueueQueueWorkItem(channel->dataWorkQueue, VmbusChannelOnChannelEvent, (void*)channel); */
+ 	}
+ 	else
+ 	{
+-        DPRINT_ERR(VMBUS, "channel not found for relid - %d.", relId);
++	DPRINT_ERR(VMBUS, "channel not found for relid - %d.", relId);
+ 	}
+ }
+ 
+@@ -327,16 +335,16 @@ VmbusOnEvents(
+ 	)
+ {
+ 	int dword;
+-	//int maxdword = PAGE_SIZE >> 3; // receive size is 1/2 page and divide that by 4 bytes
++	/* int maxdword = PAGE_SIZE >> 3; // receive size is 1/2 page and divide that by 4 bytes */
+ 	int maxdword = MAX_NUM_CHANNELS_SUPPORTED >> 5;
+ 	int bit;
+ 	int relid;
+ 	u32* recvInterruptPage = gVmbusConnection.RecvInterruptPage;
+-	//VMBUS_CHANNEL_MESSAGE* receiveMsg;
++	/* VMBUS_CHANNEL_MESSAGE* receiveMsg; */
+ 
+ 	DPRINT_ENTER(VMBUS);
+ 
+-	// Check events
++	/* Check events */
+ 	if (recvInterruptPage)
+ 	{
+ 		for (dword = 0; dword < maxdword; dword++)
+@@ -351,15 +359,15 @@ VmbusOnEvents(
+ 
+ 						DPRINT_DBG(VMBUS, "event detected for relid - %d", relid);
+ 
+-						if (relid == 0) // special case - vmbus channel protocol msg
++						if (relid == 0) /* special case - vmbus channel protocol msg */
+ 						{
+ 							DPRINT_DBG(VMBUS, "invalid relid - %d", relid);
+ 
+ 							continue;						}
+ 						else
+ 						{
+-							//QueueWorkItem(VmbusProcessEvent, (void*)relid);
+-							//ret = WorkQueueQueueWorkItem(gVmbusConnection.workQueue, VmbusProcessChannelEvent, (void*)relid);
++							/* QueueWorkItem(VmbusProcessEvent, (void*)relid); */
++							/* ret = WorkQueueQueueWorkItem(gVmbusConnection.workQueue, VmbusProcessChannelEvent, (void*)relid); */
+ 							VmbusProcessChannelEvent((void*)(unsigned long)relid);
+ 						}
+ 					}
+@@ -418,7 +426,7 @@ VmbusSetEvent(u32 childRelId)
+ 
+ 	DPRINT_ENTER(VMBUS);
+ 
+-	// Each u32 represents 32 channels
++	/* Each u32 represents 32 channels */
+ 	BitSet((u32*)gVmbusConnection.SendInterruptPage + (childRelId >> 5), childRelId & 31);
+ 	ret = HvSignalEvent();
+ 
+@@ -427,4 +435,4 @@ VmbusSetEvent(u32 childRelId)
+ 	return ret;
+ }
+ 
+-// EOF
++/* EOF */
+diff --git a/drivers/staging/hv/Hv.c b/drivers/staging/hv/Hv.c
+index 3a833ad55d48..264a90f8f8ed 100644
+--- a/drivers/staging/hv/Hv.c
++++ b/drivers/staging/hv/Hv.c
+@@ -25,11 +25,9 @@
+ #include "include/logging.h"
+ #include "VmbusPrivate.h"
+ 
+-//
+-// Globals
+-//
++/* Globals */
+ 
+-// The one and only
++/* The one and only */
+ HV_CONTEXT gHvContext={
+ 	.SynICInitialized = false,
+ 	.HypercallPage = NULL,
+@@ -90,10 +88,11 @@ HvQueryHypervisorInfo (
+     unsigned int maxLeaf;
+     unsigned int op;
+ 
+-    //
+-    // Its assumed that this is called after confirming that Viridian is present.
+-    // Query id and revision.
+-    //
++    /*
++     * Its assumed that this is called after confirming that Viridian
++     * is present. Query id and revision.
++     */
++
+ 
+     eax = 0;
+     ebx = 0;
+@@ -103,18 +102,18 @@ HvQueryHypervisorInfo (
+     do_cpuid(op, &eax, &ebx, &ecx, &edx);
+ 
+     DPRINT_INFO(VMBUS, "Vendor ID: %c%c%c%c%c%c%c%c%c%c%c%c",
+-           (ebx & 0xFF),
+-           ((ebx >> 8) & 0xFF),
+-           ((ebx >> 16) & 0xFF),
+-           ((ebx >> 24) & 0xFF),
+-           (ecx & 0xFF),
+-           ((ecx >> 8) & 0xFF),
+-           ((ecx >> 16) & 0xFF),
+-           ((ecx >> 24) & 0xFF),
+-           (edx & 0xFF),
+-           ((edx >> 8) & 0xFF),
+-           ((edx >> 16) & 0xFF),
+-           ((edx >> 24) & 0xFF));
++	   (ebx & 0xFF),
++	   ((ebx >> 8) & 0xFF),
++	   ((ebx >> 16) & 0xFF),
++	   ((ebx >> 24) & 0xFF),
++	   (ecx & 0xFF),
++	   ((ecx >> 8) & 0xFF),
++	   ((ecx >> 16) & 0xFF),
++	   ((ecx >> 24) & 0xFF),
++	   (edx & 0xFF),
++	   ((edx >> 8) & 0xFF),
++	   ((edx >> 16) & 0xFF),
++	   ((edx >> 24) & 0xFF));
+ 
+     maxLeaf = eax;
+     eax = 0;
+@@ -125,25 +124,25 @@ HvQueryHypervisorInfo (
+     do_cpuid(op, &eax, &ebx, &ecx, &edx);
+ 
+     DPRINT_INFO(VMBUS, "Interface ID: %c%c%c%c",
+-           (eax & 0xFF),
+-           ((eax >> 8) & 0xFF),
+-           ((eax >> 16) & 0xFF),
+-           ((eax >> 24) & 0xFF));
++	   (eax & 0xFF),
++	   ((eax >> 8) & 0xFF),
++	   ((eax >> 16) & 0xFF),
++	   ((eax >> 24) & 0xFF));
+ 
+ 	 if (maxLeaf >= HvCpuIdFunctionMsHvVersion) {
+-        eax = 0;
+-        ebx = 0;
+-        ecx = 0;
+-        edx = 0;
+-        op = HvCpuIdFunctionMsHvVersion;
+-        do_cpuid(op, &eax, &ebx, &ecx, &edx);
+-        DPRINT_INFO(VMBUS, "OS Build:%d-%d.%d-%d-%d.%d",
+-               eax,
+-               ebx >> 16,
+-               ebx & 0xFFFF,
+-               ecx,
+-               edx >> 24,
+-               edx & 0xFFFFFF);
++	eax = 0;
++	ebx = 0;
++	ecx = 0;
++	edx = 0;
++	op = HvCpuIdFunctionMsHvVersion;
++	do_cpuid(op, &eax, &ebx, &ecx, &edx);
++	DPRINT_INFO(VMBUS, "OS Build:%d-%d.%d-%d-%d.%d",
++	       eax,
++	       ebx >> 16,
++	       ebx & 0xFFFF,
++	       ecx,
++	       edx >> 24,
++	       edx & 0xFFFFFF);
+     }
+     return maxLeaf;
+ }
+@@ -211,7 +210,7 @@ HvDoHypercall (
+     DPRINT_DBG(VMBUS, "Hypercall ",  hvStatusLo | ((u64)hvStatusHi << 32));
+ 
+     return (hvStatusLo | ((u64)hvStatusHi << 32));
+-#endif // x86_64
++#endif /* x86_64 */
+ }
+ 
+ /*++
+@@ -249,26 +248,26 @@ HvInit (
+ 	DPRINT_INFO(VMBUS, "Windows hypervisor detected! Retrieving more info...");
+ 
+     maxLeaf = HvQueryHypervisorInfo();
+-    //HvQueryHypervisorFeatures(maxLeaf);
++    /* HvQueryHypervisorFeatures(maxLeaf); */
+ 
+-	// Determine if we are running on xenlinux (ie x2v shim) or native linux
++	/* Determine if we are running on xenlinux (ie x2v shim) or native linux */
+ 	gHvContext.GuestId = ReadMsr(HV_X64_MSR_GUEST_OS_ID);
+ 
+ 	if (gHvContext.GuestId == 0)
+ 	{
+-		// Write our OS info
++		/* Write our OS info */
+ 		WriteMsr(HV_X64_MSR_GUEST_OS_ID, HV_LINUX_GUEST_ID);
+ 
+ 		gHvContext.GuestId = HV_LINUX_GUEST_ID;
+ 	}
+ 
+-	// See if the hypercall page is already set
++	/* See if the hypercall page is already set */
+ 	hypercallMsr.AsUINT64 = ReadMsr(HV_X64_MSR_HYPERCALL);
+ 
+ 	if (gHvContext.GuestId == HV_LINUX_GUEST_ID)
+ 	{
+-		// Allocate the hypercall page memory
+-		//virtAddr = PageAlloc(1);
++		/* Allocate the hypercall page memory */
++		/* virtAddr = PageAlloc(1); */
+ 		virtAddr = VirtualAllocExec(PAGE_SIZE);
+ 
+ 		if (!virtAddr)
+@@ -278,11 +277,11 @@ HvInit (
+ 		}
+ 
+ 		hypercallMsr.Enable = 1;
+-		//hypercallMsr.GuestPhysicalAddress = Logical2PhysicalAddr(virtAddr) >> PAGE_SHIFT;
++		/* hypercallMsr.GuestPhysicalAddress = Logical2PhysicalAddr(virtAddr) >> PAGE_SHIFT; */
+ 		hypercallMsr.GuestPhysicalAddress = Virtual2Physical(virtAddr) >> PAGE_SHIFT;
+ 		WriteMsr(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
+ 
+-        // Confirm that hypercall page did get setup.
++	/* Confirm that hypercall page did get setup. */
+ 		hypercallMsr.AsUINT64 = 0;
+ 		hypercallMsr.AsUINT64 = ReadMsr(HV_X64_MSR_HYPERCALL);
+ 
+@@ -304,7 +303,7 @@ HvInit (
+ 		    gHvContext.HypercallPage,
+ 		    (u64)hypercallMsr.GuestPhysicalAddress << PAGE_SHIFT);
+ 
+-	// Setup the global signal event param for the signal event hypercall
++	/* Setup the global signal event param for the signal event hypercall */
+ 	gHvContext.SignalEventBuffer = kmalloc(sizeof(HV_INPUT_SIGNAL_EVENT_BUFFER), GFP_KERNEL);
+ 	if (!gHvContext.SignalEventBuffer)
+ 	{
+@@ -317,7 +316,7 @@ HvInit (
+ 	gHvContext.SignalEventParam->FlagNumber = 0;
+ 	gHvContext.SignalEventParam->RsvdZ = 0;
+ 
+-    //DPRINT_DBG(VMBUS, "My id %llu", HvGetCurrentPartitionId());
++    /* DPRINT_DBG(VMBUS, "My id %llu", HvGetCurrentPartitionId()); */
+ 
+ 	DPRINT_EXIT(VMBUS);
+ 
+@@ -490,12 +489,12 @@ HvSynicInit (
+ 		return ret;
+ 	}
+ 
+-	// Check the version
++	/* Check the version */
+ 	version = ReadMsr(HV_X64_MSR_SVERSION);
+ 
+ 	DPRINT_INFO(VMBUS, "SynIC version: %llx", version);
+ 
+-	// TODO: Handle SMP
++	/* TODO: Handle SMP */
+ 	if (gHvContext.GuestId == HV_XENLINUX_GUEST_ID)
+ 	{
+ 		DPRINT_INFO(VMBUS, "Skipping SIMP and SIEFP setup since it is already set.");
+@@ -505,7 +504,7 @@ HvSynicInit (
+ 
+ 		DPRINT_DBG(VMBUS, "Simp: %llx, Sifep: %llx", simp.AsUINT64, siefp.AsUINT64);
+ 
+-		// Determine if we are running on xenlinux (ie x2v shim) or native linux
++		/* Determine if we are running on xenlinux (ie x2v shim) or native linux */
+ 		guestID = ReadMsr(HV_X64_MSR_GUEST_OS_ID);
+ 
+ 		if (guestID == HV_LINUX_GUEST_ID)
+@@ -536,9 +535,7 @@ HvSynicInit (
+ 			goto Cleanup;
+ 		}
+ 
+-		//
+-		// Setup the Synic's message page
+-		//
++		/* Setup the Synic's message page */
+ 		simp.AsUINT64 = ReadMsr(HV_X64_MSR_SIMP);
+ 		simp.SimpEnabled = 1;
+ 		simp.BaseSimpGpa = GetPhysicalAddress(gHvContext.synICMessagePage[0]) >> PAGE_SHIFT;
+@@ -547,9 +544,7 @@ HvSynicInit (
+ 
+ 		WriteMsr(HV_X64_MSR_SIMP, simp.AsUINT64);
+ 
+-		//
+-		// Setup the Synic's event page
+-		//
++		/* Setup the Synic's event page */
+ 		siefp.AsUINT64 = ReadMsr(HV_X64_MSR_SIEFP);
+ 		siefp.SiefpEnabled = 1;
+ 		siefp.BaseSiefpGpa = GetPhysicalAddress(gHvContext.synICEventPage[0]) >> PAGE_SHIFT;
+@@ -558,31 +553,27 @@ HvSynicInit (
+ 
+ 		WriteMsr(HV_X64_MSR_SIEFP, siefp.AsUINT64);
+ 	}
+-	//
+-    // Setup the interception SINT.
+-    //
+-	//WriteMsr((HV_X64_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX),
+-    //             interceptionSint.AsUINT64);
+-
+-    //
+-    // Setup the shared SINT.
+-    //
++    /* Setup the interception SINT. */
++	/* WriteMsr((HV_X64_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX), */
++    /*             interceptionSint.AsUINT64); */
++
++    /* Setup the shared SINT. */
+ 	sharedSint.AsUINT64 = ReadMsr(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT);
+ 
+ 	sharedSint.AsUINT64 = 0;
+-    sharedSint.Vector = irqVector; //HV_SHARED_SINT_IDT_VECTOR + 0x20;
+-    sharedSint.Masked = false;
+-    sharedSint.AutoEoi = true;
++	sharedSint.Vector = irqVector; /* HV_SHARED_SINT_IDT_VECTOR + 0x20; */
++	sharedSint.Masked = false;
++	sharedSint.AutoEoi = true;
+ 
+ 	DPRINT_DBG(VMBUS, "HV_X64_MSR_SINT1 msr set to: %llx", sharedSint.AsUINT64);
+ 
+ 	WriteMsr(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64);
+ 
+-	// Enable the global synic bit
++	/* Enable the global synic bit */
+ 	sctrl.AsUINT64 = ReadMsr(HV_X64_MSR_SCONTROL);
+ 	sctrl.Enable = 1;
+ 
+-    WriteMsr(HV_X64_MSR_SCONTROL, sctrl.AsUINT64);
++	WriteMsr(HV_X64_MSR_SCONTROL, sctrl.AsUINT64);
+ 
+ 	gHvContext.SynICInitialized = true;
+ 
+@@ -642,11 +633,14 @@ HvSynicCleanup(
+ 
+ 	sharedSint.Masked = 1;
+ 
+-	// Disable the interrupt
++	/* Disable the interrupt */
+     WriteMsr(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64);
+ 
+-	// Disable and free the resources only if we are running as native linux
+-	// since in xenlinux, we are sharing the resources with the x2v shim
++	/*
++	 * Disable and free the resources only if we are running as
++	 * native linux since in xenlinux, we are sharing the
++	 * resources with the x2v shim
++	 */
+ 	if (gHvContext.GuestId == HV_LINUX_GUEST_ID)
+ 	{
+ 		simp.AsUINT64 = ReadMsr(HV_X64_MSR_SIMP);
+@@ -669,4 +663,4 @@ HvSynicCleanup(
+ }
+ 
+ 
+-// eof
++/* eof */
+diff --git a/drivers/staging/hv/Hv.h b/drivers/staging/hv/Hv.h
+index dbe9bb899f11..a62ac33d97d2 100644
+--- a/drivers/staging/hv/Hv.h
++++ b/drivers/staging/hv/Hv.h
+@@ -29,17 +29,17 @@
+ 
+ #include "include/HvTypes.h"
+ #include "include/HvStatus.h"
+-//#include "HvVmApi.h"
+-//#include "HvKeApi.h"
+-//#include "HvMmApi.h"
+-//#include "HvCpuApi.h"
++/* #include "HvVmApi.h" */
++/* #include "HvKeApi.h" */
++/* #include "HvMmApi.h" */
++/* #include "HvCpuApi.h" */
+ #include "include/HvHalApi.h"
+ #include "include/HvVpApi.h"
+-//#include "HvTrApi.h"
++/* #include "HvTrApi.h" */
+ #include "include/HvSynicApi.h"
+-//#include "HvAmApi.h"
+-//#include "HvHkApi.h"
+-//#include "HvValApi.h"
++/* #include "HvAmApi.h" */
++/* #include "HvHkApi.h" */
++/* #include "HvValApi.h" */
+ #include "include/HvHcApi.h"
+ #include "include/HvPtApi.h"
+ 
+@@ -53,9 +53,9 @@ enum
+     VMBUS_MONITOR_PORT_ID       = 3,
+     VMBUS_MESSAGE_SINT          = 2
+ };
+-//
+-// #defines
+-//
++
++/* #defines */
++
+ #define HV_PRESENT_BIT				0x80000000
+ 
+ #define HV_XENLINUX_GUEST_ID_LO     0x00000000
+@@ -75,9 +75,9 @@ enum
+ 
+ #define HV_HYPERCALL_PARAM_ALIGN	sizeof(u64)
+ 
+-//
+-// Service definitions
+-//
++
++/* Service definitions */
++
+ #define HV_SERVICE_PARENT_PORT (0)
+ #define HV_SERVICE_PARENT_CONNECTION (0)
+ 
+@@ -95,10 +95,10 @@ enum
+ #define HV_SERVICE_PROTOCOL_VERSION (0x0010)
+ #define HV_CONNECT_PAYLOAD_BYTE_COUNT 64
+ 
+-//#define VMBUS_REVISION_NUMBER	6
+-//#define VMBUS_PORT_ID			11		// Our local vmbus's port and connection id. Anything >0 is fine
++/* #define VMBUS_REVISION_NUMBER	6 */
++/* #define VMBUS_PORT_ID			11		// Our local vmbus's port and connection id. Anything >0 is fine */
+ 
+-// 628180B8-308D-4c5e-B7DB-1BEB62E62EF4
++/* 628180B8-308D-4c5e-B7DB-1BEB62E62EF4 */
+ static const GUID VMBUS_SERVICE_ID = {.Data = {0xb8, 0x80, 0x81, 0x62, 0x8d, 0x30, 0x5e, 0x4c, 0xb7, 0xdb, 0x1b, 0xeb, 0x62, 0xe6, 0x2e, 0xf4} };
+ 
+ #define MAX_NUM_CPUS	1
+@@ -110,14 +110,14 @@ typedef struct {
+ } HV_INPUT_SIGNAL_EVENT_BUFFER;
+ 
+ typedef struct {
+-	u64	GuestId;			// XenLinux or native Linux. If XenLinux, the hypercall and synic pages has already been initialized
++	u64	GuestId;			/* XenLinux or native Linux. If XenLinux, the hypercall and synic pages has already been initialized */
+ 	void*	HypercallPage;
+ 
+ 	bool	SynICInitialized;
+-	// This is used as an input param to HvCallSignalEvent hypercall. The input param is immutable
+-	// in our usage and must be dynamic mem (vs stack or global).
++	/* This is used as an input param to HvCallSignalEvent hypercall. The input param is immutable */
++	/* in our usage and must be dynamic mem (vs stack or global). */
+ 	HV_INPUT_SIGNAL_EVENT_BUFFER *SignalEventBuffer;
+-	HV_INPUT_SIGNAL_EVENT *SignalEventParam; // 8-bytes aligned of the buffer above
++	HV_INPUT_SIGNAL_EVENT *SignalEventParam; /* 8-bytes aligned of the buffer above */
+ 
+ 	HANDLE	synICMessagePage[MAX_NUM_CPUS];
+ 	HANDLE	synICEventPage[MAX_NUM_CPUS];
+@@ -126,9 +126,9 @@ typedef struct {
+ extern HV_CONTEXT gHvContext;
+ 
+ 
+-//
+-// Inline routines
+-//
++
++/* Inline routines */
++
+ static inline unsigned long long ReadMsr(int msr)
+ {
+ 	unsigned long long val;
+@@ -145,9 +145,9 @@ static inline void WriteMsr(int msr, u64 val)
+ 	return;
+ }
+ 
+-//
+-// Hv Interface
+-//
++
++/* Hv Interface */
++
+ static int
+ HvInit(
+     void
+@@ -181,4 +181,4 @@ HvSynicCleanup(
+ 	void
+ 	);
+ 
+-#endif // __HV_H__
++#endif /* __HV_H__ */
+diff --git a/drivers/staging/hv/NetVsc.c b/drivers/staging/hv/NetVsc.c
+index b4b701012e94..72d41cc4829c 100644
+--- a/drivers/staging/hv/NetVsc.c
++++ b/drivers/staging/hv/NetVsc.c
+@@ -28,20 +28,16 @@
+ #include "RndisFilter.h"
+ 
+ 
+-//
+-// Globals
+-//
++/* Globals */
+ static const char* gDriverName="netvsc";
+ 
+-// {F8615163-DF3E-46c5-913F-F2D2F965ED0E}
++/* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */
+ static const GUID gNetVscDeviceType={
+ 	.Data = {0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E}
+ };
+ 
+ 
+-//
+-// Internal routines
+-//
++/* Internal routines */
+ static int
+ NetVscOnDeviceAdd(
+ 	DEVICE_OBJECT	*Device,
+@@ -125,7 +121,7 @@ static inline NETVSC_DEVICE* AllocNetDevice(DEVICE_OBJECT *Device)
+ 	if (!netDevice)
+ 		return NULL;
+ 
+-	// Set to 2 to allow both inbound and outbound traffic
++	/* Set to 2 to allow both inbound and outbound traffic */
+ 	InterlockedCompareExchange(&netDevice->RefCount, 2, 0);
+ 
+ 	netDevice->Device = Device;
+@@ -142,7 +138,7 @@ static inline void FreeNetDevice(NETVSC_DEVICE *Device)
+ }
+ 
+ 
+-// Get the net device object iff exists and its refcount > 1
++/* Get the net device object iff exists and its refcount > 1 */
+ static inline NETVSC_DEVICE* GetOutboundNetDevice(DEVICE_OBJECT	*Device)
+ {
+ 	NETVSC_DEVICE *netDevice;
+@@ -160,7 +156,7 @@ static inline NETVSC_DEVICE* GetOutboundNetDevice(DEVICE_OBJECT	*Device)
+ 	return netDevice;
+ }
+ 
+-// Get the net device object iff exists and its refcount > 0
++/* Get the net device object iff exists and its refcount > 0 */
+ static inline NETVSC_DEVICE* GetInboundNetDevice(DEVICE_OBJECT	*Device)
+ {
+ 	NETVSC_DEVICE *netDevice;
+@@ -196,7 +192,7 @@ static inline NETVSC_DEVICE* ReleaseOutboundNetDevice(DEVICE_OBJECT *Device)
+ 	if (netDevice == NULL)
+ 		return NULL;
+ 
+-	// Busy wait until the ref drop to 2, then set it to 1
++	/* Busy wait until the ref drop to 2, then set it to 1 */
+ 	while (InterlockedCompareExchange(&netDevice->RefCount, 1, 2) != 2)
+ 	{
+ 		udelay(100);
+@@ -213,7 +209,7 @@ static inline NETVSC_DEVICE* ReleaseInboundNetDevice(DEVICE_OBJECT *Device)
+ 	if (netDevice == NULL)
+ 		return NULL;
+ 
+-	// Busy wait until the ref drop to 1, then set it to 0
++	/* Busy wait until the ref drop to 1, then set it to 0 */
+ 	while (InterlockedCompareExchange(&netDevice->RefCount, 0, 1) != 1)
+ 	{
+ 		udelay(100);
+@@ -246,17 +242,17 @@ NetVscInitialize(
+ 	DPRINT_DBG(NETVSC, "sizeof(NETVSC_PACKET)=%d, sizeof(NVSP_MESSAGE)=%d, sizeof(VMTRANSFER_PAGE_PACKET_HEADER)=%d",
+ 		sizeof(NETVSC_PACKET), sizeof(NVSP_MESSAGE), sizeof(VMTRANSFER_PAGE_PACKET_HEADER));
+ 
+-	// Make sure we are at least 2 pages since 1 page is used for control
++	/* Make sure we are at least 2 pages since 1 page is used for control */
+ 	ASSERT(driver->RingBufferSize >= (PAGE_SIZE << 1));
+ 
+ 	drv->name = gDriverName;
+ 	memcpy(&drv->deviceType, &gNetVscDeviceType, sizeof(GUID));
+ 
+-	// Make sure it is set by the caller
++	/* Make sure it is set by the caller */
+ 	ASSERT(driver->OnReceiveCallback);
+ 	ASSERT(driver->OnLinkStatusChanged);
+ 
+-	// Setup the dispatch table
++	/* Setup the dispatch table */
+ 	driver->Base.OnDeviceAdd		= NetVscOnDeviceAdd;
+ 	driver->Base.OnDeviceRemove		= NetVscOnDeviceRemove;
+ 	driver->Base.OnCleanup			= NetVscOnCleanup;
+@@ -289,7 +285,7 @@ NetVscInitializeReceiveBufferWithNetVsp(
+ 		return -1;
+ 	}
+ 	ASSERT(netDevice->ReceiveBufferSize > 0);
+-	ASSERT((netDevice->ReceiveBufferSize & (PAGE_SIZE-1)) == 0); // page-size grandularity
++	ASSERT((netDevice->ReceiveBufferSize & (PAGE_SIZE-1)) == 0); /* page-size grandularity */
+ 
+ 	netDevice->ReceiveBuffer = PageAlloc(netDevice->ReceiveBufferSize >> PAGE_SHIFT);
+ 	if (!netDevice->ReceiveBuffer)
+@@ -298,13 +294,15 @@ NetVscInitializeReceiveBufferWithNetVsp(
+ 		ret = -1;
+ 		goto Cleanup;
+ 	}
+-	ASSERT(((unsigned long)netDevice->ReceiveBuffer & (PAGE_SIZE-1)) == 0); // page-aligned buffer
++	ASSERT(((unsigned long)netDevice->ReceiveBuffer & (PAGE_SIZE-1)) == 0); /* page-aligned buffer */
+ 
+ 	DPRINT_INFO(NETVSC, "Establishing receive buffer's GPADL...");
+ 
+-	// Establish the gpadl handle for this buffer on this channel.
+-	// Note: This call uses the vmbus connection rather than the channel to establish
+-	// the gpadl handle.
++	/*
++	 * Establish the gpadl handle for this buffer on this
++	 * channel.  Note: This call uses the vmbus connection rather
++	 * than the channel to establish the gpadl handle.
++	 */
+ 	ret = Device->Driver->VmbusChannelInterface.EstablishGpadl(Device,
+ 																netDevice->ReceiveBuffer,
+ 																netDevice->ReceiveBufferSize,
+@@ -316,9 +314,9 @@ NetVscInitializeReceiveBufferWithNetVsp(
+ 		goto Cleanup;
+ 	}
+ 
+-	//WaitEventWait(ext->ChannelInitEvent);
++	/* WaitEventWait(ext->ChannelInitEvent); */
+ 
+-	// Notify the NetVsp of the gpadl handle
++	/* Notify the NetVsp of the gpadl handle */
+ 	DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendReceiveBuffer...");
+ 
+ 	initPacket = &netDevice->ChannelInitPacket;
+@@ -329,7 +327,7 @@ NetVscInitializeReceiveBufferWithNetVsp(
+     initPacket->Messages.Version1Messages.SendReceiveBuffer.GpadlHandle = netDevice->ReceiveBufferGpadlHandle;
+     initPacket->Messages.Version1Messages.SendReceiveBuffer.Id = NETVSC_RECEIVE_BUFFER_ID;
+ 
+-	// Send the gpadl notification request
++	/* Send the gpadl notification request */
+ 	ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
+ 															initPacket,
+ 															sizeof(NVSP_MESSAGE),
+@@ -344,7 +342,7 @@ NetVscInitializeReceiveBufferWithNetVsp(
+ 
+ 	WaitEventWait(netDevice->ChannelInitEvent);
+ 
+-	// Check the response
++	/* Check the response */
+ 	if (initPacket->Messages.Version1Messages.SendReceiveBufferComplete.Status != NvspStatusSuccess)
+ 	{
+ 		DPRINT_ERR(NETVSC,
+@@ -354,7 +352,7 @@ NetVscInitializeReceiveBufferWithNetVsp(
+ 		goto Cleanup;
+ 	}
+ 
+-	// Parse the response
++	/* Parse the response */
+ 	ASSERT(netDevice->ReceiveSectionCount == 0);
+ 	ASSERT(netDevice->ReceiveSections == NULL);
+ 
+@@ -377,7 +375,7 @@ NetVscInitializeReceiveBufferWithNetVsp(
+ 		netDevice->ReceiveSections[0].SubAllocationSize, netDevice->ReceiveSections[0].NumSubAllocations);
+ 
+ 
+-	//For 1st release, there should only be 1 section that represents the entire receive buffer
++	/* For 1st release, there should only be 1 section that represents the entire receive buffer */
+ 	if (netDevice->ReceiveSectionCount != 1 ||
+ 		netDevice->ReceiveSections->Offset != 0 )
+ 	{
+@@ -416,7 +414,7 @@ NetVscInitializeSendBufferWithNetVsp(
+ 		return -1;
+ 	}
+ 	ASSERT(netDevice->SendBufferSize > 0);
+-	ASSERT((netDevice->SendBufferSize & (PAGE_SIZE-1)) == 0); // page-size grandularity
++	ASSERT((netDevice->SendBufferSize & (PAGE_SIZE-1)) == 0); /* page-size grandularity */
+ 
+ 	netDevice->SendBuffer = PageAlloc(netDevice->SendBufferSize >> PAGE_SHIFT);
+ 	if (!netDevice->SendBuffer)
+@@ -425,17 +423,19 @@ NetVscInitializeSendBufferWithNetVsp(
+ 		ret = -1;
+ 		goto Cleanup;
+ 	}
+-	ASSERT(((unsigned long)netDevice->SendBuffer & (PAGE_SIZE-1)) == 0); // page-aligned buffer
++	ASSERT(((unsigned long)netDevice->SendBuffer & (PAGE_SIZE-1)) == 0); /* page-aligned buffer */
+ 
+ 	DPRINT_INFO(NETVSC, "Establishing send buffer's GPADL...");
+ 
+-	// Establish the gpadl handle for this buffer on this channel.
+-	// Note: This call uses the vmbus connection rather than the channel to establish
+-	// the gpadl handle.
++	/*
++	 * Establish the gpadl handle for this buffer on this
++	 * channel.  Note: This call uses the vmbus connection rather
++	 * than the channel to establish the gpadl handle.
++	 */
+ 	ret = Device->Driver->VmbusChannelInterface.EstablishGpadl(Device,
+-																netDevice->SendBuffer,
+-																netDevice->SendBufferSize,
+-																&netDevice->SendBufferGpadlHandle);
++								   netDevice->SendBuffer,
++								   netDevice->SendBufferSize,
++								   &netDevice->SendBufferGpadlHandle);
+ 
+ 	if (ret != 0)
+ 	{
+@@ -443,9 +443,9 @@ NetVscInitializeSendBufferWithNetVsp(
+ 		goto Cleanup;
+ 	}
+ 
+-	//WaitEventWait(ext->ChannelInitEvent);
++	/* WaitEventWait(ext->ChannelInitEvent); */
+ 
+-	// Notify the NetVsp of the gpadl handle
++	/* Notify the NetVsp of the gpadl handle */
+ 	DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendSendBuffer...");
+ 
+ 	initPacket = &netDevice->ChannelInitPacket;
+@@ -456,7 +456,7 @@ NetVscInitializeSendBufferWithNetVsp(
+     initPacket->Messages.Version1Messages.SendReceiveBuffer.GpadlHandle = netDevice->SendBufferGpadlHandle;
+     initPacket->Messages.Version1Messages.SendReceiveBuffer.Id = NETVSC_SEND_BUFFER_ID;
+ 
+-	// Send the gpadl notification request
++	/* Send the gpadl notification request */
+ 	ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
+ 															initPacket,
+ 															sizeof(NVSP_MESSAGE),
+@@ -471,7 +471,7 @@ NetVscInitializeSendBufferWithNetVsp(
+ 
+ 	WaitEventWait(netDevice->ChannelInitEvent);
+ 
+-	// Check the response
++	/* Check the response */
+ 	if (initPacket->Messages.Version1Messages.SendSendBufferComplete.Status != NvspStatusSuccess)
+ 	{
+ 		DPRINT_ERR(NETVSC,
+@@ -505,13 +505,17 @@ NetVscDestroyReceiveBuffer(
+ 
+ 	DPRINT_ENTER(NETVSC);
+ 
+-	// If we got a section count, it means we received a SendReceiveBufferComplete msg
+-	// (ie sent NvspMessage1TypeSendReceiveBuffer msg) therefore, we need to send a revoke msg here
++	/*
++	 * If we got a section count, it means we received a
++	 * SendReceiveBufferComplete msg (ie sent
++	 * NvspMessage1TypeSendReceiveBuffer msg) therefore, we need
++	 * to send a revoke msg here
++	 */
+ 	if (NetDevice->ReceiveSectionCount)
+ 	{
+ 		DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeRevokeReceiveBuffer...");
+ 
+-		// Send the revoke receive buffer
++		/* Send the revoke receive buffer */
+ 		revokePacket = &NetDevice->RevokePacket;
+ 		memset(revokePacket, 0, sizeof(NVSP_MESSAGE));
+ 
+@@ -524,7 +528,10 @@ NetVscDestroyReceiveBuffer(
+ 																			(unsigned long)revokePacket,
+ 																			VmbusPacketTypeDataInBand,
+ 																			0);
+-		// If we failed here, we might as well return and have a leak rather than continue and a bugchk
++		/*
++		 * If we failed here, we might as well return and
++		 * have a leak rather than continue and a bugchk
++		 */
+ 		if (ret != 0)
+ 		{
+ 			DPRINT_ERR(NETVSC, "unable to send revoke receive buffer to netvsp");
+@@ -533,7 +540,7 @@ NetVscDestroyReceiveBuffer(
+ 		}
+ 	}
+ 
+-	// Teardown the gpadl on the vsp end
++	/* Teardown the gpadl on the vsp end */
+ 	if (NetDevice->ReceiveBufferGpadlHandle)
+ 	{
+ 		DPRINT_INFO(NETVSC, "Tearing down receive buffer's GPADL...");
+@@ -541,7 +548,7 @@ NetVscDestroyReceiveBuffer(
+ 		ret = NetDevice->Device->Driver->VmbusChannelInterface.TeardownGpadl(NetDevice->Device,
+ 																				NetDevice->ReceiveBufferGpadlHandle);
+ 
+-		// If we failed here, we might as well return and have a leak rather than continue and a bugchk
++		/* If we failed here, we might as well return and have a leak rather than continue and a bugchk */
+ 		if (ret != 0)
+ 		{
+ 			DPRINT_ERR(NETVSC, "unable to teardown receive buffer's gpadl");
+@@ -555,7 +562,7 @@ NetVscDestroyReceiveBuffer(
+ 	{
+ 		DPRINT_INFO(NETVSC, "Freeing up receive buffer...");
+ 
+-		// Free up the receive buffer
++		/* Free up the receive buffer */
+ 		PageFree(NetDevice->ReceiveBuffer, NetDevice->ReceiveBufferSize >> PAGE_SHIFT);
+ 		NetDevice->ReceiveBuffer = NULL;
+ 	}
+@@ -586,13 +593,17 @@ NetVscDestroySendBuffer(
+ 
+ 	DPRINT_ENTER(NETVSC);
+ 
+-	// If we got a section count, it means we received a SendReceiveBufferComplete msg
+-	// (ie sent NvspMessage1TypeSendReceiveBuffer msg) therefore, we need to send a revoke msg here
++	/*
++	 * If we got a section count, it means we received a
++	 *  SendReceiveBufferComplete msg (ie sent
++	 *  NvspMessage1TypeSendReceiveBuffer msg) therefore, we need
++	 *  to send a revoke msg here
++	 */
+ 	if (NetDevice->SendSectionSize)
+ 	{
+ 		DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeRevokeSendBuffer...");
+ 
+-		// Send the revoke send buffer
++		/* Send the revoke send buffer */
+ 		revokePacket = &NetDevice->RevokePacket;
+ 		memset(revokePacket, 0, sizeof(NVSP_MESSAGE));
+ 
+@@ -605,7 +616,7 @@ NetVscDestroySendBuffer(
+ 																			(unsigned long)revokePacket,
+ 																			VmbusPacketTypeDataInBand,
+ 																			0);
+-		// If we failed here, we might as well return and have a leak rather than continue and a bugchk
++		/* If we failed here, we might as well return and have a leak rather than continue and a bugchk */
+ 		if (ret != 0)
+ 		{
+ 			DPRINT_ERR(NETVSC, "unable to send revoke send buffer to netvsp");
+@@ -614,7 +625,7 @@ NetVscDestroySendBuffer(
+ 		}
+ 	}
+ 
+-	// Teardown the gpadl on the vsp end
++	/* Teardown the gpadl on the vsp end */
+ 	if (NetDevice->SendBufferGpadlHandle)
+ 	{
+ 		DPRINT_INFO(NETVSC, "Tearing down send buffer's GPADL...");
+@@ -622,7 +633,7 @@ NetVscDestroySendBuffer(
+ 		ret = NetDevice->Device->Driver->VmbusChannelInterface.TeardownGpadl(NetDevice->Device,
+ 																				NetDevice->SendBufferGpadlHandle);
+ 
+-		// If we failed here, we might as well return and have a leak rather than continue and a bugchk
++		/* If we failed here, we might as well return and have a leak rather than continue and a bugchk */
+ 		if (ret != 0)
+ 		{
+ 			DPRINT_ERR(NETVSC, "unable to teardown send buffer's gpadl");
+@@ -636,7 +647,7 @@ NetVscDestroySendBuffer(
+ 	{
+ 		DPRINT_INFO(NETVSC, "Freeing up send buffer...");
+ 
+-		// Free up the receive buffer
++		/* Free up the receive buffer */
+ 		PageFree(NetDevice->SendBuffer, NetDevice->SendBufferSize >> PAGE_SHIFT);
+ 		NetDevice->SendBuffer = NULL;
+ 	}
+@@ -677,7 +688,7 @@ NetVscConnectToVsp(
+ 
+ 	DPRINT_INFO(NETVSC, "Sending NvspMessageTypeInit...");
+ 
+-	// Send the init request
++	/* Send the init request */
+ 	ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
+ 															initPacket,
+ 															sizeof(NVSP_MESSAGE),
+@@ -693,8 +704,8 @@ NetVscConnectToVsp(
+ 
+ 	WaitEventWait(netDevice->ChannelInitEvent);
+ 
+-	// Now, check the response
+-	//ASSERT(initPacket->Messages.InitMessages.InitComplete.MaximumMdlChainLength <= MAX_MULTIPAGE_BUFFER_COUNT);
++	/* Now, check the response */
++	/* ASSERT(initPacket->Messages.InitMessages.InitComplete.MaximumMdlChainLength <= MAX_MULTIPAGE_BUFFER_COUNT); */
+ 	DPRINT_INFO(NETVSC, "NvspMessageTypeInit status(%d) max mdl chain (%d)",
+ 		initPacket->Messages.InitMessages.InitComplete.Status,
+ 		initPacket->Messages.InitMessages.InitComplete.MaximumMdlChainLength);
+@@ -715,7 +726,7 @@ NetVscConnectToVsp(
+ 	}
+ 	DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendNdisVersion...");
+ 
+-	// Send the ndis version
++	/* Send the ndis version */
+ 	memset(initPacket, 0, sizeof(NVSP_MESSAGE));
+ 
+     ndisVersion = 0x00050000;
+@@ -724,7 +735,7 @@ NetVscConnectToVsp(
+     initPacket->Messages.Version1Messages.SendNdisVersion.NdisMajorVersion = (ndisVersion & 0xFFFF0000) >> 16;
+     initPacket->Messages.Version1Messages.SendNdisVersion.NdisMinorVersion = ndisVersion & 0xFFFF;
+ 
+-	// Send the init request
++	/* Send the init request */
+ 	ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
+ 															initPacket,
+ 															sizeof(NVSP_MESSAGE),
+@@ -737,12 +748,15 @@ NetVscConnectToVsp(
+ 		ret = -1;
+ 		goto Cleanup;
+ 	}
+-	//
+-	// BUGBUG - We have to wait for the above msg since the netvsp uses KMCL which acknowledges packet (completion packet)
+-	// since our Vmbus always set the VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED flag
+-	//WaitEventWait(NetVscChannel->ChannelInitEvent);
+-
+-	// Post the big receive buffer to NetVSP
++	/*
++	 * BUGBUG - We have to wait for the above msg since the
++	 * netvsp uses KMCL which acknowledges packet (completion
++	 * packet) since our Vmbus always set the
++	 * VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED flag
++	 */
++	 /* WaitEventWait(NetVscChannel->ChannelInitEvent); */
++
++	/* Post the big receive buffer to NetVSP */
+ 	ret = NetVscInitializeReceiveBufferWithNetVsp(Device);
+ 	if (ret == 0)
+ 	{
+@@ -804,7 +818,7 @@ NetVscOnDeviceAdd(
+ 
+ 	DPRINT_DBG(NETVSC, "netvsc channel object allocated - %p", netDevice);
+ 
+-	// Initialize the NetVSC channel extension
++	/* Initialize the NetVSC channel extension */
+ 	netDevice->ReceiveBufferSize = NETVSC_RECEIVE_BUFFER_SIZE;
+ 	spin_lock_init(&netDevice->receive_packet_list_lock);
+ 
+@@ -825,14 +839,14 @@ NetVscOnDeviceAdd(
+ 	}
+ 	netDevice->ChannelInitEvent = WaitEventCreate();
+ 
+-	// Open the channel
++	/* Open the channel */
+ 	ret = Device->Driver->VmbusChannelInterface.Open(Device,
+-														netDriver->RingBufferSize,
+-														netDriver->RingBufferSize,
+-														NULL, 0,
+-														NetVscOnChannelCallback,
+-														Device
+-														);
++							 netDriver->RingBufferSize,
++							 netDriver->RingBufferSize,
++							 NULL, 0,
++							 NetVscOnChannelCallback,
++							 Device
++							 );
+ 
+ 	if (ret != 0)
+ 	{
+@@ -841,10 +855,10 @@ NetVscOnDeviceAdd(
+ 		goto Cleanup;
+ 	}
+ 
+-	// Channel is opened
++	/* Channel is opened */
+ 	DPRINT_INFO(NETVSC, "*** NetVSC channel opened successfully! ***");
+ 
+-	// Connect with the NetVsp
++	/* Connect with the NetVsp */
+ 	ret = NetVscConnectToVsp(Device);
+ 	if (ret != 0)
+ 	{
+@@ -859,7 +873,7 @@ NetVscOnDeviceAdd(
+ 	return ret;
+ 
+ Close:
+-	// Now, we can close the channel safely
++	/* Now, we can close the channel safely */
+ 	Device->Driver->VmbusChannelInterface.Close(Device);
+ 
+ Cleanup:
+@@ -909,7 +923,7 @@ NetVscOnDeviceRemove(
+ 
+ 	DPRINT_INFO(NETVSC, "Disabling outbound traffic on net device (%p)...", Device->Extension);
+ 
+-	// Stop outbound traffic ie sends and receives completions
++	/* Stop outbound traffic ie sends and receives completions */
+ 	netDevice = ReleaseOutboundNetDevice(Device);
+ 	if (!netDevice)
+ 	{
+@@ -917,7 +931,7 @@ NetVscOnDeviceRemove(
+ 		return -1;
+ 	}
+ 
+-	// Wait for all send completions
++	/* Wait for all send completions */
+ 	while (netDevice->NumOutstandingSends)
+ 	{
+ 		DPRINT_INFO(NETVSC, "waiting for %d requests to complete...", netDevice->NumOutstandingSends);
+@@ -931,16 +945,16 @@ NetVscOnDeviceRemove(
+ 
+ 	DPRINT_INFO(NETVSC, "Disabling inbound traffic on net device (%p)...", Device->Extension);
+ 
+-	// Stop inbound traffic ie receives and sends completions
++	/* Stop inbound traffic ie receives and sends completions */
+ 	netDevice = ReleaseInboundNetDevice(Device);
+ 
+-	// At this point, no one should be accessing netDevice except in here
++	/* At this point, no one should be accessing netDevice except in here */
+ 	DPRINT_INFO(NETVSC, "net device (%p) safe to remove", netDevice);
+ 
+-	// Now, we can close the channel safely
++	/* Now, we can close the channel safely */
+ 	Device->Driver->VmbusChannelInterface.Close(Device);
+ 
+-	// Release all resources
++	/* Release all resources */
+ 	while (!IsListEmpty(&netDevice->ReceivePacketList))
+ 	{
+ 		entry = REMOVE_HEAD_LIST(&netDevice->ReceivePacketList);
+@@ -1005,17 +1019,17 @@ NetVscOnSendCompletion(
+ 		nvspPacket->Header.MessageType == NvspMessage1TypeSendReceiveBufferComplete ||
+ 		nvspPacket->Header.MessageType == NvspMessage1TypeSendSendBufferComplete)
+ 	{
+-		// Copy the response back
++		/* Copy the response back */
+ 		memcpy(&netDevice->ChannelInitPacket, nvspPacket, sizeof(NVSP_MESSAGE));
+ 		WaitEventSet(netDevice->ChannelInitEvent);
+ 	}
+ 	else if (nvspPacket->Header.MessageType == NvspMessage1TypeSendRNDISPacketComplete)
+ 	{
+-		// Get the send context
++		/* Get the send context */
+ 		nvscPacket = (NETVSC_PACKET *)(unsigned long)Packet->TransactionId;
+ 		ASSERT(nvscPacket);
+ 
+-		// Notify the layer above us
++		/* Notify the layer above us */
+ 		nvscPacket->Completion.Send.OnSendCompletion(nvscPacket->Completion.Send.SendCompletionContext);
+ 
+ 		InterlockedDecrement(&netDevice->NumOutstandingSends);
+@@ -1054,11 +1068,11 @@ NetVscOnSend(
+ 
+ 	sendMessage.Header.MessageType = NvspMessage1TypeSendRNDISPacket;
+ 	if (Packet->IsDataPacket)
+-	    sendMessage.Messages.Version1Messages.SendRNDISPacket.ChannelType = 0;// 0 is RMC_DATA;
++	    sendMessage.Messages.Version1Messages.SendRNDISPacket.ChannelType = 0;/* 0 is RMC_DATA; */
+ 	else
+-		sendMessage.Messages.Version1Messages.SendRNDISPacket.ChannelType = 1;// 1 is RMC_CONTROL;
++		sendMessage.Messages.Version1Messages.SendRNDISPacket.ChannelType = 1;/* 1 is RMC_CONTROL; */
+ 
+-	// Not using send buffer section
++	/* Not using send buffer section */
+     sendMessage.Messages.Version1Messages.SendRNDISPacket.SendBufferSectionIndex = 0xFFFFFFFF;
+     sendMessage.Messages.Version1Messages.SendRNDISPacket.SendBufferSectionSize = 0;
+ 
+@@ -1108,7 +1122,7 @@ NetVscOnReceive(
+ 	LIST_ENTRY* entry;
+ 	unsigned long start;
+ 	unsigned long end, endVirtual;
+-	//NETVSC_DRIVER_OBJECT *netvscDriver;
++	/* NETVSC_DRIVER_OBJECT *netvscDriver; */
+ 	XFERPAGE_PACKET *xferpagePacket=NULL;
+ 	LIST_ENTRY listHead;
+ 
+@@ -1126,7 +1140,7 @@ NetVscOnReceive(
+ 		return;
+ 	}
+ 
+-	// All inbound packets other than send completion should be xfer page packet
++	/* All inbound packets other than send completion should be xfer page packet */
+ 	if (Packet->Type != VmbusPacketTypeDataUsingTransferPages)
+ 	{
+ 		DPRINT_ERR(NETVSC, "Unknown packet type received - %d", Packet->Type);
+@@ -1136,7 +1150,7 @@ NetVscOnReceive(
+ 
+ 	nvspPacket = (NVSP_MESSAGE*)((unsigned long)Packet + (Packet->DataOffset8 << 3));
+ 
+-	// Make sure this is a valid nvsp packet
++	/* Make sure this is a valid nvsp packet */
+ 	if (nvspPacket->Header.MessageType != NvspMessage1TypeSendRNDISPacket )
+ 	{
+ 		DPRINT_ERR(NETVSC, "Unknown nvsp packet type received - %d", nvspPacket->Header.MessageType);
+@@ -1159,8 +1173,12 @@ NetVscOnReceive(
+ 
+ 	INITIALIZE_LIST_HEAD(&listHead);
+ 
+-	// Grab free packets (range count + 1) to represent this xfer page packet. +1 to represent
+-	// the xfer page packet itself. We grab it here so that we know exactly how many we can fulfil
++	/*
++	 * Grab free packets (range count + 1) to represent this xfer
++	 * page packet. +1 to represent the xfer page packet itself.
++	 * We grab it here so that we know exactly how many we can
++	 * fulfil
++	 */
+ 	spin_lock_irqsave(&netDevice->receive_packet_list_lock, flags);
+ 	while (!IsListEmpty(&netDevice->ReceivePacketList))
+ 	{
+@@ -1174,13 +1192,16 @@ NetVscOnReceive(
+ 	}
+ 	spin_unlock_irqrestore(&netDevice->receive_packet_list_lock, flags);
+ 
+-	// We need at least 2 netvsc pkts (1 to represent the xfer page and at least 1 for the range)
+-	// i.e. we can handled some of the xfer page packet ranges...
++	/*
++	 * We need at least 2 netvsc pkts (1 to represent the xfer
++	 * page and at least 1 for the range) i.e. we can handled
++	 * some of the xfer page packet ranges...
++	 */
+ 	if (count < 2)
+ 	{
+ 		DPRINT_ERR(NETVSC, "Got only %d netvsc pkt...needed %d pkts. Dropping this xfer page packet completely!", count, vmxferpagePacket->RangeCount+1);
+ 
+-		// Return it to the freelist
++		/* Return it to the freelist */
+ 		spin_lock_irqsave(&netDevice->receive_packet_list_lock, flags);
+ 		for (i=count; i != 0; i--)
+ 		{
+@@ -1197,10 +1218,10 @@ NetVscOnReceive(
+ 		return;
+ 	}
+ 
+-	// Remove the 1st packet to represent the xfer page packet itself
++	/* Remove the 1st packet to represent the xfer page packet itself */
+ 	entry = REMOVE_HEAD_LIST(&listHead);
+ 	xferpagePacket = CONTAINING_RECORD(entry, XFERPAGE_PACKET, ListEntry);
+-	xferpagePacket->Count = count - 1; // This is how much we can satisfy
++	xferpagePacket->Count = count - 1; /* This is how much we can satisfy */
+ 	ASSERT(xferpagePacket->Count > 0 && xferpagePacket->Count <= vmxferpagePacket->RangeCount);
+ 
+ 	if (xferpagePacket->Count != vmxferpagePacket->RangeCount)
+@@ -1208,18 +1229,18 @@ NetVscOnReceive(
+ 		DPRINT_INFO(NETVSC, "Needed %d netvsc pkts to satisy this xfer page...got %d", vmxferpagePacket->RangeCount, xferpagePacket->Count);
+ 	}
+ 
+-	// Each range represents 1 RNDIS pkt that contains 1 ethernet frame
++	/* Each range represents 1 RNDIS pkt that contains 1 ethernet frame */
+ 	for (i=0; i < (count - 1); i++)
+ 	{
+ 		entry = REMOVE_HEAD_LIST(&listHead);
+ 		netvscPacket = CONTAINING_RECORD(entry, NETVSC_PACKET, ListEntry);
+ 
+-		// Initialize the netvsc packet
++		/* Initialize the netvsc packet */
+ 		netvscPacket->XferPagePacket = xferpagePacket;
+ 		netvscPacket->Completion.Recv.OnReceiveCompletion = NetVscOnReceiveCompletion;
+ 		netvscPacket->Completion.Recv.ReceiveCompletionContext = netvscPacket;
+ 		netvscPacket->Device = Device;
+-		netvscPacket->Completion.Recv.ReceiveCompletionTid = vmxferpagePacket->d.TransactionId; // Save this so that we can send it back
++		netvscPacket->Completion.Recv.ReceiveCompletionTid = vmxferpagePacket->d.TransactionId; /* Save this so that we can send it back */
+ 
+ 		netvscPacket->TotalDataBufferLength = vmxferpagePacket->Ranges[i].ByteCount;
+ 		netvscPacket->PageBufferCount = 1;
+@@ -1236,10 +1257,10 @@ NetVscOnReceive(
+ 		    + vmxferpagePacket->Ranges[i].ByteCount -1;
+ 		end = GetPhysicalAddress((void*)endVirtual);
+ 
+-		// Calculate the page relative offset
++		/* Calculate the page relative offset */
+ 		netvscPacket->PageBuffers[0].Offset = vmxferpagePacket->Ranges[i].ByteOffset & (PAGE_SIZE -1);
+ 		if ((end >> PAGE_SHIFT) != (start>>PAGE_SHIFT)) {
+-		    //Handle frame across multiple pages:
++		    /* Handle frame across multiple pages: */
+ 		    netvscPacket->PageBuffers[0].Length =
+ 			(netvscPacket->PageBuffers[0].Pfn <TotalDataBufferLength - netvscPacket->PageBuffers[0].Length;
+@@ -1268,7 +1289,7 @@ NetVscOnReceive(
+ 			netvscPacket->PageBuffers[0].Offset,
+ 			netvscPacket->PageBuffers[0].Length);
+ 
+-		// Pass it to the upper layer
++		/* Pass it to the upper layer */
+ 		((NETVSC_DRIVER_OBJECT*)Device->Driver)->OnReceiveCallback(Device, netvscPacket);
+ 
+ 		NetVscOnReceiveCompletion(netvscPacket->Completion.Recv.ReceiveCompletionContext);
+@@ -1295,22 +1316,22 @@ NetVscSendReceiveCompletion(
+ 
+ 	recvcompMessage.Header.MessageType = NvspMessage1TypeSendRNDISPacketComplete;
+ 
+-	// FIXME: Pass in the status
++	/* FIXME: Pass in the status */
+ 	recvcompMessage.Messages.Version1Messages.SendRNDISPacketComplete.Status = NvspStatusSuccess;
+ 
+ retry_send_cmplt:
+-	// Send the completion
++	/* Send the completion */
+ 	ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
+ 															&recvcompMessage,
+ 															sizeof(NVSP_MESSAGE),
+ 															TransactionId,
+ 															VmbusPacketTypeCompletion,
+ 															0);
+-	if (ret == 0) // success
++	if (ret == 0) /* success */
+ 	{
+-		// no-op
++		/* no-op */
+ 	}
+-	else if (ret == -1) // no more room...wait a bit and attempt to retry 3 times
++	else if (ret == -1) /* no more room...wait a bit and attempt to retry 3 times */
+ 	{
+ 		retries++;
+ 		DPRINT_ERR(NETVSC, "unable to send receive completion pkt (tid %llx)...retrying %d", TransactionId, retries);
+@@ -1331,9 +1352,7 @@ NetVscSendReceiveCompletion(
+ 	}
+ }
+ 
+-//
+-// Send a receive completion packet to RNDIS device (ie NetVsp)
+-//
++/* Send a receive completion packet to RNDIS device (ie NetVsp) */
+ static void
+ NetVscOnReceiveCompletion(
+ 	void * Context)
+@@ -1349,8 +1368,8 @@ NetVscOnReceiveCompletion(
+ 
+ 	ASSERT(packet->XferPagePacket);
+ 
+-	// Even though it seems logical to do a GetOutboundNetDevice() here to send out receive completion,
+-	// we are using GetInboundNetDevice() since we may have disable outbound traffic already.
++	/* Even though it seems logical to do a GetOutboundNetDevice() here to send out receive completion, */
++	/* we are using GetInboundNetDevice() since we may have disable outbound traffic already. */
+ 	netDevice = GetInboundNetDevice(device);
+ 	if (!netDevice)
+ 	{
+@@ -1359,14 +1378,14 @@ NetVscOnReceiveCompletion(
+ 		return;
+ 	}
+ 
+-	// Overloading use of the lock.
++	/* Overloading use of the lock. */
+ 	spin_lock_irqsave(&netDevice->receive_packet_list_lock, flags);
+ 
+ 	ASSERT(packet->XferPagePacket->Count > 0);
+ 	packet->XferPagePacket->Count--;
+ 
+-	// Last one in the line that represent 1 xfer page packet.
+-	// Return the xfer page packet itself to the freelist
++	/* Last one in the line that represent 1 xfer page packet. */
++	/* Return the xfer page packet itself to the freelist */
+ 	if (packet->XferPagePacket->Count == 0)
+ 	{
+ 		fSendReceiveComp = true;
+@@ -1375,11 +1394,11 @@ NetVscOnReceiveCompletion(
+ 		INSERT_TAIL_LIST(&netDevice->ReceivePacketList, &packet->XferPagePacket->ListEntry);
+ 	}
+ 
+-	// Put the packet back
++	/* Put the packet back */
+ 	INSERT_TAIL_LIST(&netDevice->ReceivePacketList, &packet->ListEntry);
+ 	spin_unlock_irqrestore(&netDevice->receive_packet_list_lock, flags);
+ 
+-	// Send a receive completion for the xfer page packet
++	/* Send a receive completion for the xfer page packet */
+ 	if (fSendReceiveComp)
+ 	{
+ 		NetVscSendReceiveCompletion(device, transactionId);
+@@ -1451,7 +1470,7 @@ NetVscOnChannelCallback(
+ 						break;
+ 				}
+ 
+-				// reset
++				/* reset */
+ 				if (bufferlen > netPacketSize)
+ 				{
+ 					kfree(buffer);
+@@ -1462,9 +1481,9 @@ NetVscOnChannelCallback(
+ 			}
+ 			else
+ 			{
+-				//DPRINT_DBG(NETVSC, "nothing else to read...");
++				/* DPRINT_DBG(NETVSC, "nothing else to read..."); */
+ 
+-				// reset
++				/* reset */
+ 				if (bufferlen > netPacketSize)
+ 				{
+ 					kfree(buffer);
+@@ -1476,12 +1495,12 @@ NetVscOnChannelCallback(
+ 				break;
+ 			}
+ 		}
+-		else if (ret == -2) // Handle large packet
++		else if (ret == -2) /* Handle large packet */
+ 		{
+ 			buffer = kmalloc(bytesRecvd, GFP_ATOMIC);
+ 			if (buffer == NULL)
+ 			{
+-				// Try again next time around
++				/* Try again next time around */
+ 				DPRINT_ERR(NETVSC, "unable to allocate buffer of size (%d)!!", bytesRecvd);
+ 				break;
+ 			}
+diff --git a/drivers/staging/hv/NetVsc.h b/drivers/staging/hv/NetVsc.h
+index d6b0d678c81c..acc4217fd41a 100644
+--- a/drivers/staging/hv/NetVsc.h
++++ b/drivers/staging/hv/NetVsc.h
+@@ -30,62 +30,62 @@
+ #include "include/List.h"
+ 
+ #include "include/NetVscApi.h"
+-//
+-// #defines
+-//
+-//#define NVSC_MIN_PROTOCOL_VERSION                       1
+-//#define NVSC_MAX_PROTOCOL_VERSION                       1
+ 
+-#define NETVSC_SEND_BUFFER_SIZE				64*1024 // 64K
++/* #defines */
++
++/* #define NVSC_MIN_PROTOCOL_VERSION                       1 */
++/* #define NVSC_MAX_PROTOCOL_VERSION                       1 */
++
++#define NETVSC_SEND_BUFFER_SIZE				64*1024 /* 64K */
+ #define NETVSC_SEND_BUFFER_ID				0xface
+ 
+ 
+-#define NETVSC_RECEIVE_BUFFER_SIZE			1024*1024 // 1MB
++#define NETVSC_RECEIVE_BUFFER_SIZE			1024*1024 /* 1MB */
+ 
+ #define NETVSC_RECEIVE_BUFFER_ID			0xcafe
+ 
+ #define NETVSC_RECEIVE_SG_COUNT				1
+ 
+-// Preallocated receive packets
++/* Preallocated receive packets */
+ #define NETVSC_RECEIVE_PACKETLIST_COUNT		256
+ 
+-//
+-// Data types
+-//
+ 
+-// Per netvsc channel-specific
++/* Data types */
++
++
++/* Per netvsc channel-specific */
+ typedef struct _NETVSC_DEVICE {
+ 	DEVICE_OBJECT					*Device;
+ 
+ 	int								RefCount;
+ 
+ 	int								NumOutstandingSends;
+-	// List of free preallocated NETVSC_PACKET to represent receive packet
++	/* List of free preallocated NETVSC_PACKET to represent receive packet */
+ 	LIST_ENTRY						ReceivePacketList;
+ 	spinlock_t receive_packet_list_lock;
+ 
+-	// Send buffer allocated by us but manages by NetVSP
++	/* Send buffer allocated by us but manages by NetVSP */
+ 	void *							SendBuffer;
+ 	u32							SendBufferSize;
+ 	u32							SendBufferGpadlHandle;
+ 	u32							SendSectionSize;
+ 
+-	// Receive buffer allocated by us but manages by NetVSP
++	/* Receive buffer allocated by us but manages by NetVSP */
+ 	void *							ReceiveBuffer;
+ 	u32							ReceiveBufferSize;
+ 	u32							ReceiveBufferGpadlHandle;
+ 	u32							ReceiveSectionCount;
+ 	PNVSP_1_RECEIVE_BUFFER_SECTION	ReceiveSections;
+ 
+-	// Used for NetVSP initialization protocol
++	/* Used for NetVSP initialization protocol */
+ 	HANDLE							ChannelInitEvent;
+ 	NVSP_MESSAGE					ChannelInitPacket;
+ 
+ 	NVSP_MESSAGE					RevokePacket;
+-	//unsigned char							HwMacAddr[HW_MACADDR_LEN];
++	/* unsigned char							HwMacAddr[HW_MACADDR_LEN]; */
+ 
+-	// Holds rndis device info
++	/* Holds rndis device info */
+ 	void							*Extension;
+ } NETVSC_DEVICE;
+ 
+-#endif // _NETVSC_H_
++#endif /* _NETVSC_H_ */
+diff --git a/drivers/staging/hv/RingBuffer.c b/drivers/staging/hv/RingBuffer.c
+index e99546835f28..6a9f568cc3f4 100644
+--- a/drivers/staging/hv/RingBuffer.c
++++ b/drivers/staging/hv/RingBuffer.c
+@@ -25,11 +25,11 @@
+ #include "include/logging.h"
+ #include "RingBuffer.h"
+ 
+-//
+-// #defines
+-//
+ 
+-// Amount of space to write to
++/* #defines */
++
++
++/* Amount of space to write to */
+ #define BYTES_AVAIL_TO_WRITE(r, w, z) ((w) >= (r))?((z) - ((w) - (r))):((r) - (w))
+ 
+ 
+@@ -48,7 +48,7 @@ GetRingBufferAvailBytes(RING_BUFFER_INFO *rbi, u32 *read, u32 *write)
+ {
+ 	u32 read_loc,write_loc;
+ 
+-	// Capture the read/write indices before they changed
++	/* Capture the read/write indices before they changed */
+ 	read_loc = rbi->RingBuffer->ReadIndex;
+ 	write_loc = rbi->RingBuffer->WriteIndex;
+ 
+@@ -221,9 +221,9 @@ DumpRingInfo(RING_BUFFER_INFO* RingInfo, char *Prefix)
+ 		RingInfo->RingBuffer->WriteIndex);
+ }
+ 
+-//
+-// Internal routines
+-//
++
++/* Internal routines */
++
+ static u32
+ CopyToRingBuffer(
+ 	RING_BUFFER_INFO	*RingInfo,
+@@ -376,10 +376,10 @@ RingBufferWrite(
+ 
+ 	DPRINT_DBG(VMBUS, "Writing %u bytes...", totalBytesToWrite);
+ 
+-	//DumpRingInfo(OutRingInfo, "BEFORE ");
++	/* DumpRingInfo(OutRingInfo, "BEFORE "); */
+ 
+-	// If there is only room for the packet, assume it is full. Otherwise, the next time around, we think the ring buffer
+-	// is empty since the read index == write index
++	/* If there is only room for the packet, assume it is full. Otherwise, the next time around, we think the ring buffer */
++	/* is empty since the read index == write index */
+ 	if (byteAvailToWrite <= totalBytesToWrite)
+ 	{
+ 		DPRINT_DBG(VMBUS, "No more space left on outbound ring buffer (needed %u, avail %u)", totalBytesToWrite, byteAvailToWrite);
+@@ -391,7 +391,7 @@ RingBufferWrite(
+ 		return -1;
+ 	}
+ 
+-	// Write to the ring buffer
++	/* Write to the ring buffer */
+ 	nextWriteLocation = GetNextWriteLocation(OutRingInfo);
+ 
+ 	for (i=0; i < SgBufferCount; i++)
+@@ -402,7 +402,7 @@ RingBufferWrite(
+ 												SgBuffers[i].Length);
+ 	}
+ 
+-	// Set previous packet start
++	/* Set previous packet start */
+ 	prevIndices = GetRingBufferIndices(OutRingInfo);
+ 
+ 	nextWriteLocation = CopyToRingBuffer(OutRingInfo,
+@@ -410,13 +410,13 @@ RingBufferWrite(
+ 												&prevIndices,
+ 												sizeof(u64));
+ 
+-	// Make sure we flush all writes before updating the writeIndex
++	/* Make sure we flush all writes before updating the writeIndex */
+ 	mb();
+ 
+-	// Now, update the write location
++	/* Now, update the write location */
+ 	SetNextWriteLocation(OutRingInfo, nextWriteLocation);
+ 
+-	//DumpRingInfo(OutRingInfo, "AFTER ");
++	/* DumpRingInfo(OutRingInfo, "AFTER "); */
+ 
+ 	spin_unlock_irqrestore(&OutRingInfo->ring_lock, flags);
+ 
+@@ -451,17 +451,17 @@ RingBufferPeek(
+ 
+ 	GetRingBufferAvailBytes(InRingInfo, &bytesAvailToRead, &bytesAvailToWrite);
+ 
+-	// Make sure there is something to read
++	/* Make sure there is something to read */
+ 	if (bytesAvailToRead < BufferLen )
+ 	{
+-		//DPRINT_DBG(VMBUS, "got callback but not enough to read !!", bytesAvailToRead, BufferLen);
++		/* DPRINT_DBG(VMBUS, "got callback but not enough to read !!", bytesAvailToRead, BufferLen); */
+ 
+ 		spin_unlock_irqrestore(&InRingInfo->ring_lock, flags);
+ 
+ 		return -1;
+ 	}
+ 
+-	// Convert to byte offset
++	/* Convert to byte offset */
+ 	nextReadLocation = GetNextReadLocation(InRingInfo);
+ 
+ 	nextReadLocation = CopyFromRingBuffer(InRingInfo,
+@@ -506,9 +506,9 @@ RingBufferRead(
+ 
+ 	DPRINT_DBG(VMBUS, "Reading %u bytes...", BufferLen);
+ 
+-	//DumpRingInfo(InRingInfo, "BEFORE ");
++	/* DumpRingInfo(InRingInfo, "BEFORE "); */
+ 
+-	// Make sure there is something to read
++	/* Make sure there is something to read */
+ 	if (bytesAvailToRead < BufferLen )
+ 	{
+ 		DPRINT_DBG(VMBUS, "got callback but not enough to read !!", bytesAvailToRead, BufferLen);
+@@ -530,14 +530,14 @@ RingBufferRead(
+ 											sizeof(u64),
+ 											nextReadLocation);
+ 
+-	// Make sure all reads are done before we update the read index since
+-	// the writer may start writing to the read area once the read index is updated
++	/* Make sure all reads are done before we update the read index since */
++	/* the writer may start writing to the read area once the read index is updated */
+ 	mb();
+ 
+-	// Update the read index
++	/* Update the read index */
+ 	SetNextReadLocation(InRingInfo, nextReadLocation);
+ 
+-	//DumpRingInfo(InRingInfo, "AFTER ");
++	/* DumpRingInfo(InRingInfo, "AFTER "); */
+ 
+ 	spin_unlock_irqrestore(&InRingInfo->ring_lock, flags);
+ 
+@@ -566,7 +566,7 @@ CopyToRingBuffer(
+ 	u32 ringBufferSize=GetRingBufferSize(RingInfo);
+ 	u32 fragLen;
+ 
+-	if (SrcLen > ringBufferSize - StartWriteOffset) // wrap-around detected!
++	if (SrcLen > ringBufferSize - StartWriteOffset) /* wrap-around detected! */
+ 	{
+ 		DPRINT_DBG(VMBUS, "wrap-around detected!");
+ 
+@@ -608,7 +608,7 @@ CopyFromRingBuffer(
+ 
+ 	u32 fragLen;
+ 
+-	if (DestLen > ringBufferSize - StartReadOffset) // wrap-around detected at the src
++	if (DestLen > ringBufferSize - StartReadOffset) /* wrap-around detected at the src */
+ 	{
+ 		DPRINT_DBG(VMBUS, "src wrap-around detected!");
+ 
+@@ -629,4 +629,4 @@ CopyFromRingBuffer(
+ }
+ 
+ 
+-// eof
++/* eof */
+diff --git a/drivers/staging/hv/RingBuffer.h b/drivers/staging/hv/RingBuffer.h
+index 4217259890b0..a0b6e0e9f879 100644
+--- a/drivers/staging/hv/RingBuffer.h
++++ b/drivers/staging/hv/RingBuffer.h
+@@ -33,24 +33,24 @@ typedef struct _SG_BUFFER_LIST {
+ } SG_BUFFER_LIST;
+ 
+ typedef struct _RING_BUFFER {
+-    volatile u32	WriteIndex;     // Offset in bytes from the start of ring data below
+-    volatile u32	ReadIndex;      // Offset in bytes from the start of ring data below
++    volatile u32	WriteIndex;     /* Offset in bytes from the start of ring data below */
++    volatile u32	ReadIndex;      /* Offset in bytes from the start of ring data below */
+ 
+ 	volatile u32 InterruptMask;
+-	u8	Reserved[4084];			// Pad it to PAGE_SIZE so that data starts on page boundary
+-	// NOTE: The InterruptMask field is used only for channels but since our vmbus connection
+-	// also uses this data structure and its data starts here, we commented out this field.
+-	// volatile u32 InterruptMask;
+-	// Ring data starts here + RingDataStartOffset !!! DO NOT place any fields below this !!!
++	u8	Reserved[4084];			/* Pad it to PAGE_SIZE so that data starts on page boundary */
++	/* NOTE: The InterruptMask field is used only for channels but since our vmbus connection */
++	/* also uses this data structure and its data starts here, we commented out this field. */
++	/* volatile u32 InterruptMask; */
++	/* Ring data starts here + RingDataStartOffset !!! DO NOT place any fields below this !!! */
+     u8		Buffer[0];
+ } __attribute__((packed)) RING_BUFFER;
+ 
+ typedef struct _RING_BUFFER_INFO {
+     RING_BUFFER*	RingBuffer;
+-    u32			RingSize;			// Include the shared header
++    u32			RingSize;			/* Include the shared header */
+ 	spinlock_t ring_lock;
+ 
+-    u32			RingDataSize;		// < ringSize
++    u32			RingDataSize;		/* < ringSize */
+ 	u32			RingDataStartOffset;
+ 
+ } RING_BUFFER_INFO;
+@@ -65,9 +65,9 @@ typedef struct _RING_BUFFER_DEBUG_INFO {
+ }RING_BUFFER_DEBUG_INFO;
+ 
+ 
+-//
+-// Interface
+-//
++
++/* Interface */
++
+ 
+ static int
+ RingBufferInit(
+@@ -120,4 +120,4 @@ RingBufferGetDebugInfo(
+ 	RING_BUFFER_DEBUG_INFO	*DebugInfo
+ 	);
+ 
+-#endif // _RING_BUFFER_H_
++#endif /* _RING_BUFFER_H_ */
+diff --git a/drivers/staging/hv/RndisFilter.c b/drivers/staging/hv/RndisFilter.c
+index 714f23e7b0ed..d971e866218c 100644
+--- a/drivers/staging/hv/RndisFilter.c
++++ b/drivers/staging/hv/RndisFilter.c
+@@ -28,12 +28,12 @@
+ #include "include/NetVscApi.h"
+ #include "RndisFilter.h"
+ 
+-//
+-// Data types
+-//
++
++/* Data types */
++
+ 
+ typedef struct _RNDIS_FILTER_DRIVER_OBJECT {
+-	// The original driver
++	/* The original driver */
+ 	NETVSC_DRIVER_OBJECT		InnerDriver;
+ 
+ } RNDIS_FILTER_DRIVER_OBJECT;
+@@ -63,14 +63,14 @@ typedef struct _RNDIS_REQUEST {
+ 	LIST_ENTRY					ListEntry;
+ 	HANDLE						WaitEvent;
+ 
+-	// FIXME: We assumed a fixed size response here. If we do ever need to handle a bigger response,
+-	// we can either define a max response message or add a response buffer variable above this field
++	/* FIXME: We assumed a fixed size response here. If we do ever need to handle a bigger response, */
++	/* we can either define a max response message or add a response buffer variable above this field */
+ 	RNDIS_MESSAGE				ResponseMessage;
+ 
+-	// Simplify allocation by having a netvsc packet inline
++	/* Simplify allocation by having a netvsc packet inline */
+ 	NETVSC_PACKET				Packet;
+ 	PAGE_BUFFER					Buffer;
+-	// FIXME: We assumed a fixed size request here.
++	/* FIXME: We assumed a fixed size request here. */
+ 	RNDIS_MESSAGE				RequestMessage;
+ } RNDIS_REQUEST;
+ 
+@@ -82,9 +82,9 @@ typedef struct _RNDIS_FILTER_PACKET {
+ 	RNDIS_MESSAGE				Message;
+ } RNDIS_FILTER_PACKET;
+ 
+-//
+-// Internal routines
+-//
++
++/* Internal routines */
++
+ static int
+ RndisFilterSendRequest(
+ 	RNDIS_DEVICE	*Device,
+@@ -197,11 +197,11 @@ RndisFilterOnSendRequestCompletion(
+    void *Context
+ 	);
+ 
+-//
+-// Global var
+-//
+ 
+-// The one and only
++/* Global var */
++
++
++/* The one and only */
+ RNDIS_FILTER_DRIVER_OBJECT gRndisFilter;
+ 
+ static inline RNDIS_DEVICE* GetRndisDevice(void)
+@@ -252,12 +252,12 @@ static inline RNDIS_REQUEST* GetRndisRequest(RNDIS_DEVICE *Device, u32 MessageTy
+ 	rndisMessage->NdisMessageType = MessageType;
+ 	rndisMessage->MessageLength = MessageLength;
+ 
+-	// Set the request id. This field is always after the rndis header for request/response packet types so
+-	// we just used the SetRequest as a template
++	/* Set the request id. This field is always after the rndis header for request/response packet types so */
++	/* we just used the SetRequest as a template */
+ 	set = &rndisMessage->Message.SetRequest;
+ 	set->RequestId = InterlockedIncrement((int*)&Device->NewRequestId);
+ 
+-	// Add to the request list
++	/* Add to the request list */
+ 	spin_lock_irqsave(&Device->request_lock, flags);
+ 	INSERT_TAIL_LIST(&Device->RequestList, &request->ListEntry);
+ 	spin_unlock_irqrestore(&Device->request_lock, flags);
+@@ -349,7 +349,7 @@ RndisFilterSendRequest(
+ 
+ 	DPRINT_ENTER(NETVSC);
+ 
+-	// Setup the packet to send it
++	/* Setup the packet to send it */
+ 	packet = &Request->Packet;
+ 
+ 	packet->IsDataPacket = false;
+@@ -360,7 +360,7 @@ RndisFilterSendRequest(
+ 	packet->PageBuffers[0].Length = Request->RequestMessage.MessageLength;
+ 	packet->PageBuffers[0].Offset = (unsigned long)&Request->RequestMessage & (PAGE_SIZE -1);
+ 
+-	packet->Completion.Send.SendCompletionContext = Request;//packet;
++	packet->Completion.Send.SendCompletionContext = Request;/* packet; */
+ 	packet->Completion.Send.OnSendCompletion = RndisFilterOnSendRequestCompletion;
+ 	packet->Completion.Send.SendCompletionTid = (unsigned long)Device;
+ 
+@@ -389,7 +389,7 @@ RndisFilterReceiveResponse(
+ 	{
+ 		request = CONTAINING_RECORD(curr, RNDIS_REQUEST, ListEntry);
+ 
+-		// All request/response message contains RequestId as the 1st field
++		/* All request/response message contains RequestId as the 1st field */
+ 		if (request->RequestMessage.Message.InitializeRequest.RequestId == Response->Message.InitializeComplete.RequestId)
+ 		{
+ 			DPRINT_DBG(NETVSC, "found rndis request for this response (id 0x%x req type 0x%x res type 0x%x)",
+@@ -411,7 +411,7 @@ RndisFilterReceiveResponse(
+ 		{
+ 			DPRINT_ERR(NETVSC, "rndis response buffer overflow detected (size %u max %u)", Response->MessageLength, sizeof(RNDIS_FILTER_PACKET));
+ 
+-			if (Response->NdisMessageType == REMOTE_NDIS_RESET_CMPLT) // does not have a request id field
++			if (Response->NdisMessageType == REMOTE_NDIS_RESET_CMPLT) /* does not have a request id field */
+ 			{
+ 				request->ResponseMessage.Message.ResetComplete.Status = STATUS_BUFFER_OVERFLOW;
+ 			}
+@@ -450,7 +450,7 @@ RndisFilterReceiveIndicateStatus(
+ 	}
+ 	else
+ 	{
+-		// TODO:
++		/* TODO: */
+ 	}
+ }
+ 
+@@ -466,15 +466,15 @@ RndisFilterReceiveData(
+ 
+ 	DPRINT_ENTER(NETVSC);
+ 
+-	// empty ethernet frame ??
++	/* empty ethernet frame ?? */
+ 	ASSERT(Packet->PageBuffers[0].Length > RNDIS_MESSAGE_SIZE(RNDIS_PACKET));
+ 
+ 	rndisPacket = &Message->Message.Packet;
+ 
+-	// FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this
+-	// netvsc packet (ie TotalDataBufferLength != MessageLength)
++	/* FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this */
++	/* netvsc packet (ie TotalDataBufferLength != MessageLength) */
+ 
+-	// Remove the rndis header and pass it back up the stack
++	/* Remove the rndis header and pass it back up the stack */
+ 	dataOffset = RNDIS_HEADER_SIZE + rndisPacket->DataOffset;
+ 
+ 	Packet->TotalDataBufferLength -= dataOffset;
+@@ -502,7 +502,7 @@ RndisFilterOnReceive(
+ 	DPRINT_ENTER(NETVSC);
+ 
+ 	ASSERT(netDevice);
+-	//Make sure the rndis device state is initialized
++	/* Make sure the rndis device state is initialized */
+ 	if (!netDevice->Extension)
+ 	{
+ 		DPRINT_ERR(NETVSC, "got rndis message but no rndis device...dropping this message!");
+@@ -522,9 +522,9 @@ RndisFilterOnReceive(
+ 
+ 	rndisHeader = (void*)((unsigned long)rndisHeader + Packet->PageBuffers[0].Offset);
+ 
+-	// Make sure we got a valid rndis message
+-	// FIXME: There seems to be a bug in set completion msg where its MessageLength is 16 bytes but
+-	// the ByteCount field in the xfer page range shows 52 bytes
++	/* Make sure we got a valid rndis message */
++	/* FIXME: There seems to be a bug in set completion msg where its MessageLength is 16 bytes but */
++	/* the ByteCount field in the xfer page range shows 52 bytes */
+ #if 0
+ 	if ( Packet->TotalDataBufferLength != rndisHeader->MessageLength )
+ 	{
+@@ -551,21 +551,21 @@ RndisFilterOnReceive(
+ 
+ 	switch (rndisMessage.NdisMessageType)
+ 	{
+-		// data msg
++		/* data msg */
+ 	case REMOTE_NDIS_PACKET_MSG:
+ 		RndisFilterReceiveData(rndisDevice, &rndisMessage, Packet);
+ 		break;
+ 
+-		// completion msgs
++		/* completion msgs */
+ 	case REMOTE_NDIS_INITIALIZE_CMPLT:
+ 	case REMOTE_NDIS_QUERY_CMPLT:
+ 	case REMOTE_NDIS_SET_CMPLT:
+-	//case REMOTE_NDIS_RESET_CMPLT:
+-	//case REMOTE_NDIS_KEEPALIVE_CMPLT:
++	/* case REMOTE_NDIS_RESET_CMPLT: */
++	/* case REMOTE_NDIS_KEEPALIVE_CMPLT: */
+ 		RndisFilterReceiveResponse(rndisDevice, &rndisMessage);
+ 		break;
+ 
+-		// notification msgs
++		/* notification msgs */
+ 	case REMOTE_NDIS_INDICATE_STATUS_MSG:
+ 		RndisFilterReceiveIndicateStatus(rndisDevice, &rndisMessage);
+ 		break;
+@@ -605,7 +605,7 @@ RndisFilterQueryDevice(
+ 		goto Cleanup;
+ 	}
+ 
+-	// Setup the rndis query
++	/* Setup the rndis query */
+ 	query = &request->RequestMessage.Message.QueryRequest;
+ 	query->Oid = Oid;
+ 	query->InformationBufferOffset = sizeof(RNDIS_QUERY_REQUEST);
+@@ -620,7 +620,7 @@ RndisFilterQueryDevice(
+ 
+ 	WaitEventWait(request->WaitEvent);
+ 
+-	// Copy the response back
++	/* Copy the response back */
+ 	queryComplete = &request->ResponseMessage.Message.QueryComplete;
+ 
+ 	if (queryComplete->InformationBufferLength > inresultSize)
+@@ -694,7 +694,7 @@ RndisFilterSetPacketFilter(
+ 		goto Cleanup;
+ 	}
+ 
+-	// Setup the rndis set
++	/* Setup the rndis set */
+ 	set = &request->RequestMessage.Message.SetRequest;
+ 	set->Oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
+ 	set->InformationBufferLength = sizeof(u32);
+@@ -713,7 +713,7 @@ RndisFilterSetPacketFilter(
+ 	{
+ 		ret = -1;
+ 		DPRINT_ERR(NETVSC, "timeout before we got a set response...");
+-		// We cant deallocate the request since we may still receive a send completion for it.
++		/* We cant deallocate the request since we may still receive a send completion for it. */
+ 		goto Exit;
+ 	}
+ 	else
+@@ -747,9 +747,9 @@ RndisFilterInit(
+ 	DPRINT_DBG(NETVSC, "sizeof(RNDIS_FILTER_PACKET) == %d", sizeof(RNDIS_FILTER_PACKET));
+ 
+ 	Driver->RequestExtSize = sizeof(RNDIS_FILTER_PACKET);
+-	Driver->AdditionalRequestPageBufferCount = 1; // For rndis header
++	Driver->AdditionalRequestPageBufferCount = 1; /* For rndis header */
+ 
+-	//Driver->Context = rndisDriver;
++	/* Driver->Context = rndisDriver; */
+ 
+ 	memset(&gRndisFilter, 0, sizeof(RNDIS_FILTER_DRIVER_OBJECT));
+ 
+@@ -758,7 +758,7 @@ RndisFilterInit(
+ 	ASSERT(Driver->OnLinkStatusChanged);
+ 	rndisDriver->OnLinkStatusChanged = Driver->OnLinkStatusChanged;*/
+ 
+-	// Save the original dispatch handlers before we override it
++	/* Save the original dispatch handlers before we override it */
+ 	gRndisFilter.InnerDriver.Base.OnDeviceAdd = Driver->Base.OnDeviceAdd;
+ 	gRndisFilter.InnerDriver.Base.OnDeviceRemove = Driver->Base.OnDeviceRemove;
+ 	gRndisFilter.InnerDriver.Base.OnCleanup = Driver->Base.OnCleanup;
+@@ -769,14 +769,14 @@ RndisFilterInit(
+ 	gRndisFilter.InnerDriver.OnReceiveCallback = Driver->OnReceiveCallback;
+ 	gRndisFilter.InnerDriver.OnLinkStatusChanged = Driver->OnLinkStatusChanged;
+ 
+-	// Override
++	/* Override */
+ 	Driver->Base.OnDeviceAdd = RndisFilterOnDeviceAdd;
+ 	Driver->Base.OnDeviceRemove = RndisFilterOnDeviceRemove;
+ 	Driver->Base.OnCleanup = RndisFilterOnCleanup;
+ 	Driver->OnSend = RndisFilterOnSend;
+ 	Driver->OnOpen = RndisFilterOnOpen;
+ 	Driver->OnClose = RndisFilterOnClose;
+-	//Driver->QueryLinkStatus = RndisFilterQueryDeviceLinkStatus;
++	/* Driver->QueryLinkStatus = RndisFilterQueryDeviceLinkStatus; */
+ 	Driver->OnReceiveCallback = RndisFilterOnReceive;
+ 
+ 	DPRINT_EXIT(NETVSC);
+@@ -804,11 +804,11 @@ RndisFilterInitDevice(
+ 		goto Cleanup;
+ 	}
+ 
+-	// Setup the rndis set
++	/* Setup the rndis set */
+ 	init = &request->RequestMessage.Message.InitializeRequest;
+ 	init->MajorVersion = RNDIS_MAJOR_VERSION;
+ 	init->MinorVersion = RNDIS_MINOR_VERSION;
+-	init->MaxTransferSize = 2048; // FIXME: Use 1536 - rounded ethernet frame size
++	init->MaxTransferSize = 2048; /* FIXME: Use 1536 - rounded ethernet frame size */
+ 
+ 	Device->State = RNDIS_DEV_INITIALIZING;
+ 
+@@ -854,18 +854,18 @@ RndisFilterHaltDevice(
+ 
+ 	DPRINT_ENTER(NETVSC);
+ 
+-	// Attempt to do a rndis device halt
++	/* Attempt to do a rndis device halt */
+ 	request = GetRndisRequest(Device, REMOTE_NDIS_HALT_MSG, RNDIS_MESSAGE_SIZE(RNDIS_HALT_REQUEST));
+ 	if (!request)
+ 	{
+ 		goto Cleanup;
+ 	}
+ 
+-	// Setup the rndis set
++	/* Setup the rndis set */
+ 	halt = &request->RequestMessage.Message.HaltRequest;
+ 	halt->RequestId = InterlockedIncrement((int*)&Device->NewRequestId);
+ 
+-	// Ignore return since this msg is optional.
++	/* Ignore return since this msg is optional. */
+ 	RndisFilterSendRequest(Device, request);
+ 
+ 	Device->State = RNDIS_DEV_UNINITIALIZED;
+@@ -948,9 +948,9 @@ RndisFilterOnDeviceAdd(
+ 
+ 	DPRINT_DBG(NETVSC, "rndis device object allocated - %p", rndisDevice);
+ 
+-	// Let the inner driver handle this first to create the netvsc channel
+-	// NOTE! Once the channel is created, we may get a receive callback
+-	// (RndisFilterOnReceive()) before this call is completed
++	/* Let the inner driver handle this first to create the netvsc channel */
++	/* NOTE! Once the channel is created, we may get a receive callback */
++	/* (RndisFilterOnReceive()) before this call is completed */
+ 	ret = gRndisFilter.InnerDriver.Base.OnDeviceAdd(Device, AdditionalInfo);
+ 	if (ret != 0)
+ 	{
+@@ -959,9 +959,9 @@ RndisFilterOnDeviceAdd(
+ 		return ret;
+ 	}
+ 
+-	//
+-	// Initialize the rndis device
+-	//
++
++	/* Initialize the rndis device */
++
+ 	netDevice = (NETVSC_DEVICE*)Device->Extension;
+ 	ASSERT(netDevice);
+ 	ASSERT(netDevice->Device);
+@@ -969,18 +969,18 @@ RndisFilterOnDeviceAdd(
+ 	netDevice->Extension = rndisDevice;
+ 	rndisDevice->NetDevice = netDevice;
+ 
+-	// Send the rndis initialization message
++	/* Send the rndis initialization message */
+ 	ret = RndisFilterInitDevice(rndisDevice);
+ 	if (ret != 0)
+ 	{
+-		// TODO: If rndis init failed, we will need to shut down the channel
++		/* TODO: If rndis init failed, we will need to shut down the channel */
+ 	}
+ 
+-	// Get the mac address
++	/* Get the mac address */
+ 	ret = RndisFilterQueryDeviceMac(rndisDevice);
+ 	if (ret != 0)
+ 	{
+-		// TODO: shutdown rndis device and the channel
++		/* TODO: shutdown rndis device and the channel */
+ 	}
+ 
+ 	DPRINT_INFO(NETVSC, "Device 0x%p mac addr %02x%02x%02x%02x%02x%02x",
+@@ -1015,13 +1015,13 @@ RndisFilterOnDeviceRemove(
+ 
+ 	DPRINT_ENTER(NETVSC);
+ 
+-	// Halt and release the rndis device
++	/* Halt and release the rndis device */
+ 	RndisFilterHaltDevice(rndisDevice);
+ 
+ 	PutRndisDevice(rndisDevice);
+ 	netDevice->Extension = NULL;
+ 
+-	// Pass control to inner driver to remove the device
++	/* Pass control to inner driver to remove the device */
+ 	gRndisFilter.InnerDriver.Base.OnDeviceRemove(Device);
+ 
+ 	DPRINT_EXIT(NETVSC);
+@@ -1091,7 +1091,7 @@ RndisFilterOnSend(
+ 
+ 	DPRINT_ENTER(NETVSC);
+ 
+-	// Add the rndis header
++	/* Add the rndis header */
+ 	filterPacket = (RNDIS_FILTER_PACKET*)Packet->Extension;
+ 	ASSERT(filterPacket);
+ 
+@@ -1112,18 +1112,18 @@ RndisFilterOnSend(
+ 	Packet->PageBuffers[0].Offset	= (unsigned long)rndisMessage & (PAGE_SIZE-1);
+ 	Packet->PageBuffers[0].Length	= rndisMessageSize;
+ 
+-	// Save the packet send completion and context
++	/* Save the packet send completion and context */
+ 	filterPacket->OnCompletion = Packet->Completion.Send.OnSendCompletion;
+ 	filterPacket->CompletionContext = Packet->Completion.Send.SendCompletionContext;
+ 
+-	// Use ours
++	/* Use ours */
+ 	Packet->Completion.Send.OnSendCompletion = RndisFilterOnSendCompletion;
+ 	Packet->Completion.Send.SendCompletionContext = filterPacket;
+ 
+ 	ret = gRndisFilter.InnerDriver.OnSend(Device, Packet);
+ 	if (ret != 0)
+ 	{
+-		// Reset the completion to originals to allow retries from above
++		/* Reset the completion to originals to allow retries from above */
+ 		Packet->Completion.Send.OnSendCompletion = filterPacket->OnCompletion;
+ 		Packet->Completion.Send.SendCompletionContext = filterPacket->CompletionContext;
+ 	}
+@@ -1141,7 +1141,7 @@ RndisFilterOnSendCompletion(
+ 
+ 	DPRINT_ENTER(NETVSC);
+ 
+-	// Pass it back to the original handler
++	/* Pass it back to the original handler */
+ 	filterPacket->OnCompletion(filterPacket->CompletionContext);
+ 
+ 	DPRINT_EXIT(NETVSC);
+@@ -1155,6 +1155,6 @@ RndisFilterOnSendRequestCompletion(
+ {
+ 	DPRINT_ENTER(NETVSC);
+ 
+-	// Noop
++	/* Noop */
+ 	DPRINT_EXIT(NETVSC);
+ }
+diff --git a/drivers/staging/hv/RndisFilter.h b/drivers/staging/hv/RndisFilter.h
+index 1231d6fd94d9..ebacbe01c92d 100644
+--- a/drivers/staging/hv/RndisFilter.h
++++ b/drivers/staging/hv/RndisFilter.h
+@@ -49,13 +49,13 @@
+ 
+ 
+ 
+-//
+-// Interface
+-//
++
++/* Interface */
++
+ int
+ RndisFilterInit(
+ 	NETVSC_DRIVER_OBJECT *Driver
+ 	);
+ 
+ 
+-#endif // _RNDISFILTER_H_
++#endif /* _RNDISFILTER_H_ */
+diff --git a/drivers/staging/hv/StorVsc.c b/drivers/staging/hv/StorVsc.c
+index 439c447d2246..ee6d88e16d6c 100644
+--- a/drivers/staging/hv/StorVsc.c
++++ b/drivers/staging/hv/StorVsc.c
+@@ -32,45 +32,48 @@
+ #include "include/vstorage.h"
+ 
+ 
+-//
+-// #defines
+-//
+ 
+-//
+-// Data types
+-//
++/* #defines */
++
++
++
++/* Data types */
++
+ 
+ typedef struct _STORVSC_REQUEST_EXTENSION {
+-	//LIST_ENTRY						ListEntry;
++	/* LIST_ENTRY						ListEntry; */
+ 
+ 	STORVSC_REQUEST					*Request;
+ 	DEVICE_OBJECT					*Device;
+ 
+-	// Synchronize the request/response if needed
++	/* Synchronize the request/response if needed */
+ 	HANDLE							WaitEvent;
+ 
+ 	VSTOR_PACKET					VStorPacket;
+ } STORVSC_REQUEST_EXTENSION;
+ 
+ 
+-// A storvsc device is a device object that contains a vmbus channel
++/* A storvsc device is a device object that contains a vmbus channel */
+ typedef struct _STORVSC_DEVICE{
+ 	DEVICE_OBJECT				*Device;
+ 
+-	int							RefCount; // 0 indicates the device is being destroyed
++	int							RefCount; /* 0 indicates the device is being destroyed */
+ 
+ 	int							NumOutstandingRequests;
+ 
+-	//  Each unique Port/Path/Target represents 1 channel ie scsi controller. In reality, the pathid, targetid is always 0
+-	// and the port is set by us
++	/*
++	 * Each unique Port/Path/Target represents 1 channel ie scsi
++	 * controller. In reality, the pathid, targetid is always 0
++	 * and the port is set by us
++	 */
+ 	unsigned int						PortNumber;
+     unsigned char						PathId;
+     unsigned char						TargetId;
+ 
+-	//LIST_ENTRY					OutstandingRequestList;
+-	//HANDLE						OutstandingRequestLock;
++	/* LIST_ENTRY					OutstandingRequestList; */
++	/* HANDLE						OutstandingRequestLock; */
+ 
+-	// Used for vsc/vsp channel reset process
++	/* Used for vsc/vsp channel reset process */
+ 	STORVSC_REQUEST_EXTENSION	InitRequest;
+ 
+ 	STORVSC_REQUEST_EXTENSION	ResetRequest;
+@@ -78,19 +81,19 @@ typedef struct _STORVSC_DEVICE{
+ } STORVSC_DEVICE;
+ 
+ 
+-//
+-// Globals
+-//
++
++/* Globals */
++
+ static const char* gDriverName="storvsc";
+ 
+-//{ba6163d9-04a1-4d29-b605-72e2ffb1dc7f}
++/* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */
+ static const GUID gStorVscDeviceType={
+ 	.Data = {0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f}
+ };
+ 
+-//
+-// Internal routines
+-//
++
++/* Internal routines */
++
+ static int
+ StorVscOnDeviceAdd(
+ 	DEVICE_OBJECT	*Device,
+@@ -150,8 +153,8 @@ static inline STORVSC_DEVICE* AllocStorDevice(DEVICE_OBJECT *Device)
+ 	if (!storDevice)
+ 		return NULL;
+ 
+-	// Set to 2 to allow both inbound and outbound traffics
+-	// (ie GetStorDevice() and MustGetStorDevice()) to proceed.
++	/* Set to 2 to allow both inbound and outbound traffics */
++	/* (ie GetStorDevice() and MustGetStorDevice()) to proceed. */
+ 	InterlockedCompareExchange(&storDevice->RefCount, 2, 0);
+ 
+ 	storDevice->Device = Device;
+@@ -166,7 +169,7 @@ static inline void FreeStorDevice(STORVSC_DEVICE *Device)
+ 	kfree(Device);
+ }
+ 
+-// Get the stordevice object iff exists and its refcount > 1
++/* Get the stordevice object iff exists and its refcount > 1 */
+ static inline STORVSC_DEVICE* GetStorDevice(DEVICE_OBJECT *Device)
+ {
+ 	STORVSC_DEVICE *storDevice;
+@@ -184,7 +187,7 @@ static inline STORVSC_DEVICE* GetStorDevice(DEVICE_OBJECT *Device)
+ 	return storDevice;
+ }
+ 
+-// Get the stordevice object iff exists and its refcount > 0
++/* Get the stordevice object iff exists and its refcount > 0 */
+ static inline STORVSC_DEVICE* MustGetStorDevice(DEVICE_OBJECT *Device)
+ {
+ 	STORVSC_DEVICE *storDevice;
+@@ -213,7 +216,7 @@ static inline void PutStorDevice(DEVICE_OBJECT *Device)
+ 	ASSERT(storDevice->RefCount);
+ }
+ 
+-// Drop ref count to 1 to effectively disable GetStorDevice()
++/* Drop ref count to 1 to effectively disable GetStorDevice() */
+ static inline STORVSC_DEVICE* ReleaseStorDevice(DEVICE_OBJECT *Device)
+ {
+ 	STORVSC_DEVICE *storDevice;
+@@ -221,7 +224,7 @@ static inline STORVSC_DEVICE* ReleaseStorDevice(DEVICE_OBJECT *Device)
+ 	storDevice = (STORVSC_DEVICE*)Device->Extension;
+ 	ASSERT(storDevice);
+ 
+-	// Busy wait until the ref drop to 2, then set it to 1
++	/* Busy wait until the ref drop to 2, then set it to 1 */
+ 	while (InterlockedCompareExchange(&storDevice->RefCount, 1, 2) != 2)
+ 	{
+ 		udelay(100);
+@@ -230,7 +233,7 @@ static inline STORVSC_DEVICE* ReleaseStorDevice(DEVICE_OBJECT *Device)
+ 	return storDevice;
+ }
+ 
+-// Drop ref count to 0. No one can use StorDevice object.
++/* Drop ref count to 0. No one can use StorDevice object. */
+ static inline STORVSC_DEVICE* FinalReleaseStorDevice(DEVICE_OBJECT *Device)
+ {
+ 	STORVSC_DEVICE *storDevice;
+@@ -238,7 +241,7 @@ static inline STORVSC_DEVICE* FinalReleaseStorDevice(DEVICE_OBJECT *Device)
+ 	storDevice = (STORVSC_DEVICE*)Device->Extension;
+ 	ASSERT(storDevice);
+ 
+-	// Busy wait until the ref drop to 1, then set it to 0
++	/* Busy wait until the ref drop to 1, then set it to 0 */
+ 	while (InterlockedCompareExchange(&storDevice->RefCount, 0, 1) != 1)
+ 	{
+ 		udelay(100);
+@@ -271,7 +274,7 @@ StorVscInitialize(
+ 	DPRINT_DBG(STORVSC, "sizeof(STORVSC_REQUEST)=%d sizeof(STORVSC_REQUEST_EXTENSION)=%d sizeof(VSTOR_PACKET)=%d, sizeof(VMSCSI_REQUEST)=%d",
+ 		sizeof(STORVSC_REQUEST), sizeof(STORVSC_REQUEST_EXTENSION), sizeof(VSTOR_PACKET), sizeof(VMSCSI_REQUEST));
+ 
+-	// Make sure we are at least 2 pages since 1 page is used for control
++	/* Make sure we are at least 2 pages since 1 page is used for control */
+ 	ASSERT(storDriver->RingBufferSize >= (PAGE_SIZE << 1));
+ 
+ 	Driver->name = gDriverName;
+@@ -279,14 +282,18 @@ StorVscInitialize(
+ 
+ 	storDriver->RequestExtSize			= sizeof(STORVSC_REQUEST_EXTENSION);
+ 
+-	// Divide the ring buffer data size (which is 1 page less than the ring buffer size since that page is reserved for the ring buffer indices)
+-	// by the max request size (which is VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER + VSTOR_PACKET + u64)
++	/*
++	 * Divide the ring buffer data size (which is 1 page less
++	 * than the ring buffer size since that page is reserved for
++	 * the ring buffer indices) by the max request size (which is
++	 * VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER + VSTOR_PACKET + u64)
++	 */
+ 	storDriver->MaxOutstandingRequestsPerChannel =
+ 		((storDriver->RingBufferSize - PAGE_SIZE) / ALIGN_UP(MAX_MULTIPAGE_BUFFER_PACKET + sizeof(VSTOR_PACKET) + sizeof(u64),sizeof(u64)));
+ 
+ 	DPRINT_INFO(STORVSC, "max io %u, currently %u\n", storDriver->MaxOutstandingRequestsPerChannel, STORVSC_MAX_IO_REQUESTS);
+ 
+-	// Setup the dispatch table
++	/* Setup the dispatch table */
+ 	storDriver->Base.OnDeviceAdd			= StorVscOnDeviceAdd;
+ 	storDriver->Base.OnDeviceRemove		= StorVscOnDeviceRemove;
+ 	storDriver->Base.OnCleanup			= StorVscOnCleanup;
+@@ -316,7 +323,7 @@ StorVscOnDeviceAdd(
+ {
+ 	int ret=0;
+ 	STORVSC_DEVICE *storDevice;
+-	//VMSTORAGE_CHANNEL_PROPERTIES *props;
++	/* VMSTORAGE_CHANNEL_PROPERTIES *props; */
+ 	STORVSC_DEVICE_INFO *deviceInfo = (STORVSC_DEVICE_INFO*)AdditionalInfo;
+ 
+ 	DPRINT_ENTER(STORVSC);
+@@ -328,21 +335,25 @@ StorVscOnDeviceAdd(
+ 		goto Cleanup;
+ 	}
+ 
+-	// Save the channel properties to our storvsc channel
+-	//props = (VMSTORAGE_CHANNEL_PROPERTIES*) channel->offerMsg.Offer.u.Standard.UserDefined;
++	/* Save the channel properties to our storvsc channel */
++	/* props = (VMSTORAGE_CHANNEL_PROPERTIES*) channel->offerMsg.Offer.u.Standard.UserDefined; */
++
++	/* FIXME: */
++	/*
++	 * If we support more than 1 scsi channel, we need to set the
++	 * port number here to the scsi channel but how do we get the
++	 * scsi channel prior to the bus scan
++	 */
+ 
+-	// FIXME:
+-	// If we support more than 1 scsi channel, we need to set the port number here
+-	// to the scsi channel but how do we get the scsi channel prior to the bus scan
+-	/*storChannel->PortNumber = 0;
++	/* storChannel->PortNumber = 0;
+ 	storChannel->PathId = props->PathId;
+-	storChannel->TargetId = props->TargetId;*/
++	storChannel->TargetId = props->TargetId; */
+ 
+ 	storDevice->PortNumber = deviceInfo->PortNumber;
+-	// Send it back up
++	/* Send it back up */
+ 	ret = StorVscConnectToVsp(Device);
+ 
+-	//deviceInfo->PortNumber = storDevice->PortNumber;
++	/* deviceInfo->PortNumber = storDevice->PortNumber; */
+ 	deviceInfo->PathId = storDevice->PathId;
+ 	deviceInfo->TargetId = storDevice->TargetId;
+ 
+@@ -372,7 +383,7 @@ static int StorVscChannelInit(DEVICE_OBJECT *Device)
+ 	request = &storDevice->InitRequest;
+ 	vstorPacket = &request->VStorPacket;
+ 
+-	// Now, initiate the vsc/vsp initialization protocol on the open channel
++	/* Now, initiate the vsc/vsp initialization protocol on the open channel */
+ 
+ 	memset(request, sizeof(STORVSC_REQUEST_EXTENSION), 0);
+ 	request->WaitEvent = WaitEventCreate();
+@@ -408,7 +419,7 @@ static int StorVscChannelInit(DEVICE_OBJECT *Device)
+ 
+ 	DPRINT_INFO(STORVSC, "QUERY_PROTOCOL_VERSION_OPERATION...");
+ 
+-	// reuse the packet for version range supported
++	/* reuse the packet for version range supported */
+ 	memset(vstorPacket, sizeof(VSTOR_PACKET), 0);
+ 	vstorPacket->Operation = VStorOperationQueryProtocolVersion;
+ 	vstorPacket->Flags = REQUEST_COMPLETION_FLAG;
+@@ -430,14 +441,14 @@ static int StorVscChannelInit(DEVICE_OBJECT *Device)
+ 
+ 	WaitEventWait(request->WaitEvent);
+ 
+-	// TODO: Check returned version
++	/* TODO: Check returned version */
+ 	if (vstorPacket->Operation != VStorOperationCompleteIo || vstorPacket->Status != 0)
+ 	{
+ 		DPRINT_ERR(STORVSC, "QUERY_PROTOCOL_VERSION_OPERATION failed (op %d status 0x%lx)", vstorPacket->Operation, vstorPacket->Status);
+ 		goto Cleanup;
+ 	}
+ 
+-	// Query channel properties
++	/* Query channel properties */
+ 	DPRINT_INFO(STORVSC, "QUERY_PROPERTIES_OPERATION...");
+ 
+ 	memset(vstorPacket, sizeof(VSTOR_PACKET), 0);
+@@ -460,14 +471,14 @@ static int StorVscChannelInit(DEVICE_OBJECT *Device)
+ 
+ 	WaitEventWait(request->WaitEvent);
+ 
+-	// TODO: Check returned version
++	/* TODO: Check returned version */
+ 	if (vstorPacket->Operation != VStorOperationCompleteIo || vstorPacket->Status != 0)
+ 	{
+ 		DPRINT_ERR(STORVSC, "QUERY_PROPERTIES_OPERATION failed (op %d status 0x%lx)", vstorPacket->Operation, vstorPacket->Status);
+ 		goto Cleanup;
+ 	}
+ 
+-	//storDevice->PortNumber = vstorPacket->StorageChannelProperties.PortNumber;
++	/* storDevice->PortNumber = vstorPacket->StorageChannelProperties.PortNumber; */
+ 	storDevice->PathId = vstorPacket->StorageChannelProperties.PathId;
+ 	storDevice->TargetId = vstorPacket->StorageChannelProperties.TargetId;
+ 
+@@ -528,7 +539,7 @@ StorVscConnectToVsp(
+ 
+ 	memset(&props, sizeof(VMSTORAGE_CHANNEL_PROPERTIES), 0);
+ 
+-	// Open the channel
++	/* Open the channel */
+ 	ret = Device->Driver->VmbusChannelInterface.Open(Device,
+ 		storDriver->RingBufferSize,
+ 		storDriver->RingBufferSize,
+@@ -575,8 +586,11 @@ StorVscOnDeviceRemove(
+ 
+ 	storDevice = ReleaseStorDevice(Device);
+ 
+-	// At this point, all outbound traffic should be disable. We only allow inbound traffic (responses) to proceed
+-	// so that outstanding requests can be completed.
++	/*
++	 * At this point, all outbound traffic should be disable. We
++	 * only allow inbound traffic (responses) to proceed so that
++	 * outstanding requests can be completed.
++	 */
+ 	while (storDevice->NumOutstandingRequests)
+ 	{
+ 		DPRINT_INFO(STORVSC, "waiting for %d requests to complete...", storDevice->NumOutstandingRequests);
+@@ -590,7 +604,7 @@ StorVscOnDeviceRemove(
+ 
+ 	DPRINT_INFO(STORVSC, "storage device (%p) safe to remove", storDevice);
+ 
+-	// Close the channel
++	/* Close the channel */
+ 	Device->Driver->VmbusChannelInterface.Close(Device);
+ 
+ 	FreeStorDevice(storDevice);
+@@ -599,22 +613,23 @@ StorVscOnDeviceRemove(
+ 	return ret;
+ }
+ 
++/* ***************
++static void
++StorVscOnTargetRescan(
++void *Context
++)
++{
++DEVICE_OBJECT *device=(DEVICE_OBJECT*)Context;
++STORVSC_DRIVER_OBJECT *storDriver;
+ 
+-//static void
+-//StorVscOnTargetRescan(
+-//	void *Context
+-//	)
+-//{
+-//	DEVICE_OBJECT *device=(DEVICE_OBJECT*)Context;
+-//	STORVSC_DRIVER_OBJECT *storDriver;
+-//
+-//	DPRINT_ENTER(STORVSC);
+-//
+-//	storDriver = (STORVSC_DRIVER_OBJECT*) device->Driver;
+-//	storDriver->OnHostRescan(device);
+-//
+-//	DPRINT_EXIT(STORVSC);
+-//}
++DPRINT_ENTER(STORVSC);
++
++storDriver = (STORVSC_DRIVER_OBJECT*) device->Driver;
++storDriver->OnHostRescan(device);
++
++DPRINT_EXIT(STORVSC);
++}
++*********** */
+ 
+ int
+ StorVscOnHostReset(
+@@ -660,13 +675,16 @@ StorVscOnHostReset(
+ 		goto Cleanup;
+ 	}
+ 
+-	// FIXME: Add a timeout
++	/* FIXME: Add a timeout */
+ 	WaitEventWait(request->WaitEvent);
+ 
+ 	WaitEventClose(request->WaitEvent);
+ 	DPRINT_INFO(STORVSC, "host adapter reset completed");
+ 
+-	// At this point, all outstanding requests in the adapter should have been flushed out and return to us
++	/*
++	 * At this point, all outstanding requests in the adapter
++	 * should have been flushed out and return to us
++	 */
+ 
+ Cleanup:
+ 	PutStorDevice(Device);
+@@ -729,7 +747,7 @@ StorVscOnIORequest(
+ 
+ 	vstorPacket->VmSrb.SenseInfoLength = SENSE_BUFFER_SIZE;
+ 
+-	// Copy over the scsi command descriptor block
++	/* Copy over the scsi command descriptor block */
+     vstorPacket->VmSrb.CdbLength = Request->CdbLen;
+ 	memcpy(&vstorPacket->VmSrb.Cdb, Request->Cdb, Request->CdbLen);
+ 
+@@ -827,7 +845,7 @@ StorVscOnIOCompletion(
+ 
+ 	ASSERT(request->OnIOCompletion != NULL);
+ 
+-	// Copy over the status...etc
++	/* Copy over the status...etc */
+ 	request->Status = VStorPacket->VmSrb.ScsiStatus;
+ 
+ 	if (request->Status != 0 || VStorPacket->VmSrb.SrbStatus != 1)
+@@ -838,9 +856,9 @@ StorVscOnIOCompletion(
+ 			VStorPacket->VmSrb.SrbStatus);
+ 	}
+ 
+-	if ((request->Status & 0xFF) == 0x02) // CHECK_CONDITION
++	if ((request->Status & 0xFF) == 0x02) /* CHECK_CONDITION */
+ 	{
+-		if (VStorPacket->VmSrb.SrbStatus & 0x80) // autosense data available
++		if (VStorPacket->VmSrb.SrbStatus & 0x80) /* autosense data available */
+ 		{
+ 			DPRINT_WARN(STORVSC, "storvsc pkt %p autosense data valid - len %d\n",
+ 				RequestExt, VStorPacket->VmSrb.SenseInfoLength);
+@@ -854,7 +872,7 @@ StorVscOnIOCompletion(
+ 		}
+ 	}
+ 
+-	// TODO:
++	/* TODO: */
+ 	request->BytesXfer = VStorPacket->VmSrb.DataTransferLength;
+ 
+ 	request->OnIOCompletion(request);
+@@ -882,17 +900,17 @@ StorVscOnReceive(
+ 			StorVscOnIOCompletion(Device, VStorPacket, RequestExt);
+ 			break;
+ 
+-		//case ENUMERATE_DEVICE_OPERATION:
++		/* case ENUMERATE_DEVICE_OPERATION: */
+ 
+-		//	DPRINT_INFO(STORVSC, "ENUMERATE_DEVICE_OPERATION");
++		/* DPRINT_INFO(STORVSC, "ENUMERATE_DEVICE_OPERATION"); */
+ 
+-		//	StorVscOnTargetRescan(Device);
+-		//	break;
++		/* StorVscOnTargetRescan(Device); */
++		/* break; */
+ 
+-        case VStorOperationRemoveDevice:
++	case VStorOperationRemoveDevice:
+ 
+ 			DPRINT_INFO(STORVSC, "REMOVE_DEVICE_OPERATION");
+-			// TODO:
++			/* TODO: */
+ 			break;
+ 
+ 		default:
+@@ -937,15 +955,15 @@ StorVscOnChannelCallback(
+ 		{
+ 			DPRINT_DBG(STORVSC, "receive %d bytes - tid %llx", bytesRecvd, requestId);
+ 
+-			//ASSERT(bytesRecvd == sizeof(VSTOR_PACKET));
++			/* ASSERT(bytesRecvd == sizeof(VSTOR_PACKET)); */
+ 
+ 			request = (STORVSC_REQUEST_EXTENSION*)(unsigned long)requestId;
+ 			ASSERT(request);
+ 
+-			//if (vstorPacket.Flags & SYNTHETIC_FLAG)
++			/* if (vstorPacket.Flags & SYNTHETIC_FLAG) */
+ 			if ((request == &storDevice->InitRequest) || (request == &storDevice->ResetRequest))
+ 			{
+-				//DPRINT_INFO(STORVSC, "reset completion - operation %u status %u", vstorPacket.Operation, vstorPacket.Status);
++				/* DPRINT_INFO(STORVSC, "reset completion - operation %u status %u", vstorPacket.Operation, vstorPacket.Status); */
+ 
+ 				memcpy(&request->VStorPacket, packet, sizeof(VSTOR_PACKET));
+ 
+@@ -958,7 +976,7 @@ StorVscOnChannelCallback(
+ 		}
+ 		else
+ 		{
+-			//DPRINT_DBG(STORVSC, "nothing else to read...");
++			/* DPRINT_DBG(STORVSC, "nothing else to read..."); */
+ 			break;
+ 		}
+ 	} while (1);
+diff --git a/drivers/staging/hv/Vmbus.c b/drivers/staging/hv/Vmbus.c
+index a202a2d4e0e8..81b86c270661 100644
+--- a/drivers/staging/hv/Vmbus.c
++++ b/drivers/staging/hv/Vmbus.c
+@@ -27,29 +27,31 @@
+ #include "VersionInfo.h"
+ #include "VmbusPrivate.h"
+ 
+-//
+-// Globals
+-//
++
++/* Globals */
++
+ static const char* gDriverName="vmbus";
+ 
+-// Windows vmbus does not defined this. We defined this to be consistent with other devices
+-//{c5295816-f63a-4d5f-8d1a-4daf999ca185}
++/* Windows vmbus does not defined this.
++ * We defined this to be consistent with other devices
++ */
++/* {c5295816-f63a-4d5f-8d1a-4daf999ca185} */
+ static const GUID gVmbusDeviceType={
+ 	.Data = {0x16, 0x58, 0x29, 0xc5, 0x3a, 0xf6, 0x5f, 0x4d, 0x8d, 0x1a, 0x4d, 0xaf, 0x99, 0x9c, 0xa1, 0x85}
+ };
+ 
+-//{ac3760fc-9adf-40aa-9427-a70ed6de95c5}
++/* {ac3760fc-9adf-40aa-9427-a70ed6de95c5} */
+ static const GUID gVmbusDeviceId={
+ 	.Data = {0xfc, 0x60, 0x37, 0xac, 0xdf, 0x9a, 0xaa, 0x40, 0x94, 0x27, 0xa7, 0x0e, 0xd6, 0xde, 0x95, 0xc5}
+ };
+ 
+-static DRIVER_OBJECT* gDriver; // vmbus driver object
+-static DEVICE_OBJECT* gDevice; // vmbus root device
++static DRIVER_OBJECT* gDriver; /* vmbus driver object */
++static DEVICE_OBJECT* gDevice; /* vmbus root device */
++
++
+ 
++/* Internal routines */
+ 
+-//
+-// Internal routines
+-//
+ 
+ static void
+ VmbusGetChannelInterface(
+@@ -129,7 +131,7 @@ VmbusInitialize(
+ 	drv->name = gDriverName;
+ 	memcpy(&drv->deviceType, &gVmbusDeviceType, sizeof(GUID));
+ 
+-	// Setup dispatch table
++	/* Setup dispatch table */
+ 	driver->Base.OnDeviceAdd		= VmbusOnDeviceAdd;
+ 	driver->Base.OnDeviceRemove		= VmbusOnDeviceRemove;
+ 	driver->Base.OnCleanup			= VmbusOnCleanup;
+@@ -140,7 +142,7 @@ VmbusInitialize(
+ 	driver->GetChannelInterface		= VmbusGetChannelInterface;
+ 	driver->GetChannelInfo			= VmbusGetChannelInfo;
+ 
+-	// Hypervisor initialization...setup hypercall page..etc
++	/* Hypervisor initialization...setup hypercall page..etc */
+ 	ret = HvInit();
+ 	if (ret != 0)
+ 	{
+@@ -283,15 +285,18 @@ VmbusChildDeviceRemove(
+ 	Release the child device from the vmbus
+ 
+ --*/
+-//void
+-//VmbusChildDeviceDestroy(
+-//	DEVICE_OBJECT* ChildDevice
+-//	)
+-//{
+-//	VMBUS_DRIVER_OBJECT* vmbusDriver = (VMBUS_DRIVER_OBJECT*)gDriver;
+-//
+-//	vmbusDriver->OnChildDeviceDestroy(ChildDevice);
+-//}
++
++/* **************
++void
++VmbusChildDeviceDestroy(
++DEVICE_OBJECT* ChildDevice
++)
++{
++VMBUS_DRIVER_OBJECT* vmbusDriver = (VMBUS_DRIVER_OBJECT*)gDriver;
++
++vmbusDriver->OnChildDeviceDestroy(ChildDevice);
++}
++************* */
+ 
+ /*++
+ 
+@@ -318,14 +323,14 @@ VmbusOnDeviceAdd(
+ 	memcpy(&gDevice->deviceType, &gVmbusDeviceType, sizeof(GUID));
+ 	memcpy(&gDevice->deviceInstance, &gVmbusDeviceId, sizeof(GUID));
+ 
+-	//strcpy(dev->name, "vmbus");
+-	// SynIC setup...
++	/* strcpy(dev->name, "vmbus"); */
++	/* SynIC setup... */
+ 	ret = HvSynicInit(*irqvector);
+ 
+-	// Connect to VMBus in the root partition
++	/* Connect to VMBus in the root partition */
+ 	ret = VmbusConnect();
+ 
+-	//VmbusSendEvent(device->localPortId+1);
++	/* VmbusSendEvent(device->localPortId+1); */
+ 	DPRINT_EXIT(VMBUS);
+ 
+ 	return ret;
+@@ -375,7 +380,7 @@ VmbusOnCleanup(
+ 	DRIVER_OBJECT* drv
+ 	)
+ {
+-	//VMBUS_DRIVER_OBJECT* driver = (VMBUS_DRIVER_OBJECT*)drv;
++	/* VMBUS_DRIVER_OBJECT* driver = (VMBUS_DRIVER_OBJECT*)drv; */
+ 
+ 	DPRINT_ENTER(VMBUS);
+ 
+@@ -405,7 +410,7 @@ VmbusOnMsgDPC(
+ 	HV_MESSAGE *copied;
+ 	while (1)
+ 	{
+-		if (msg->Header.MessageType == HvMessageTypeNone) // no msg
++		if (msg->Header.MessageType == HvMessageTypeNone) /* no msg */
+ 		{
+ 			break;
+ 		}
+@@ -423,14 +428,22 @@ VmbusOnMsgDPC(
+ 
+ 		msg->Header.MessageType = HvMessageTypeNone;
+ 
+-		// Make sure the write to MessageType (ie set to HvMessageTypeNone) happens
+-		// before we read the MessagePending and EOMing. Otherwise, the EOMing will not deliver
+-		// any more messages since there is no empty slot
++		/*
++		 * Make sure the write to MessageType (ie set to
++		 * HvMessageTypeNone) happens before we read the
++		 * MessagePending and EOMing. Otherwise, the EOMing
++		 * will not deliver any more messages since there is
++		 * no empty slot
++		 */
+ 		mb();
+ 
+ 		if (msg->Header.MessageFlags.MessagePending)
+ 		{
+-			// This will cause message queue rescan to possibly deliver another msg from the hypervisor
++			/*
++			 * This will cause message queue rescan to
++			 * possibly deliver another msg from the
++			 * hypervisor
++			 */
+ 			WriteMsr(HV_X64_MSR_EOM, 0);
+ 		}
+ 	}
+@@ -450,7 +463,7 @@ VmbusOnEventDPC(
+ 	DRIVER_OBJECT* drv
+ 	)
+ {
+-	// TODO: Process any events
++	/* TODO: Process any events */
+ 	VmbusOnEvents();
+ }
+ 
+@@ -469,33 +482,33 @@ VmbusOnISR(
+ 	DRIVER_OBJECT* drv
+ 	)
+ {
+-	//VMBUS_DRIVER_OBJECT* driver = (VMBUS_DRIVER_OBJECT*)drv;
++	/* VMBUS_DRIVER_OBJECT* driver = (VMBUS_DRIVER_OBJECT*)drv; */
+ 
+ 	int ret=0;
+-	//struct page* page;
++	/* struct page* page; */
+ 	void *page_addr;
+ 	HV_MESSAGE* msg;
+ 	HV_SYNIC_EVENT_FLAGS* event;
+ 
+-	//page = SynICMessagePage[0];
+-	//page_addr = page_address(page);
++	/* page = SynICMessagePage[0]; */
++	/* page_addr = page_address(page); */
+ 	page_addr = gHvContext.synICMessagePage[0];
+ 	msg = (HV_MESSAGE*)page_addr + VMBUS_MESSAGE_SINT;
+ 
+ 	DPRINT_ENTER(VMBUS);
+ 
+-	// Check if there are actual msgs to be process
++	/* Check if there are actual msgs to be process */
+ 	if (msg->Header.MessageType != HvMessageTypeNone)
+     {
+ 		DPRINT_DBG(VMBUS, "received msg type %d size %d", msg->Header.MessageType, msg->Header.PayloadSize);
+ 		ret |= 0x1;
+     }
+ 
+-	// TODO: Check if there are events to be process
++	/* TODO: Check if there are events to be process */
+ 	page_addr = gHvContext.synICEventPage[0];
+ 	event = (HV_SYNIC_EVENT_FLAGS*)page_addr + VMBUS_MESSAGE_SINT;
+ 
+-	// Since we are a child, we only need to check bit 0
++	/* Since we are a child, we only need to check bit 0 */
+ 	if (BitTestAndClear(&event->Flags32[0], 0))
+ 	{
+ 		DPRINT_DBG(VMBUS, "received event %d", event->Flags32[0]);
+@@ -506,4 +519,4 @@ VmbusOnISR(
+ 	return ret;
+ }
+ 
+-// eof
++/* eof */
+diff --git a/drivers/staging/hv/VmbusPrivate.h b/drivers/staging/hv/VmbusPrivate.h
+index 686d05f21ed8..ad17088f601e 100644
+--- a/drivers/staging/hv/VmbusPrivate.h
++++ b/drivers/staging/hv/VmbusPrivate.h
+@@ -30,26 +30,29 @@
+ #include "Channel.h"
+ #include "ChannelMgmt.h"
+ #include "ChannelInterface.h"
+-//#include "ChannelMessages.h"
++/* #include "ChannelMessages.h" */
+ #include "RingBuffer.h"
+-//#include "Packet.h"
++/* #include "Packet.h" */
+ #include "include/List.h"
+ 
+-//
+-// Defines
+-//
+ 
+-// Maximum channels is determined by the size of the interrupt page which is PAGE_SIZE. 1/2 of PAGE_SIZE is for
+-// send endpoint interrupt and the other is receive endpoint interrupt
+-#define MAX_NUM_CHANNELS				(PAGE_SIZE >> 1) << 3  // 16348 channels
++/* Defines */
+ 
+-// The value here must be in multiple of 32
+-// TODO: Need to make this configurable
++
++/*
++ * Maximum channels is determined by the size of the interrupt page
++ * which is PAGE_SIZE. 1/2 of PAGE_SIZE is for send endpoint interrupt
++ * and the other is receive endpoint interrupt
++ */
++#define MAX_NUM_CHANNELS				(PAGE_SIZE >> 1) << 3  /* 16348 channels */
++
++/* The value here must be in multiple of 32 */
++/* TODO: Need to make this configurable */
+ #define MAX_NUM_CHANNELS_SUPPORTED		256
+ 
+-//
+-// Data types
+-//
++
++/* Data types */
++
+ 
+ typedef enum {
+ 	Disconnected,
+@@ -66,23 +69,27 @@ typedef struct _VMBUS_CONNECTION {
+ 
+ 	u32								NextGpadlHandle;
+ 
+-	// Represents channel interrupts. Each bit position
+-	// represents a channel.
+-	// When a channel sends an interrupt via VMBUS, it
+-	// finds its bit in the sendInterruptPage, set it and
+-	// calls Hv to generate a port event. The other end
+-	// receives the port event and parse the recvInterruptPage
+-	// to see which bit is set
++	/*
++	 * Represents channel interrupts. Each bit position represents
++         * a channel.  When a channel sends an interrupt via VMBUS, it
++         * finds its bit in the sendInterruptPage, set it and calls Hv
++         * to generate a port event. The other end receives the port
++         * event and parse the recvInterruptPage to see which bit is
++         * set
++	 */
+ 	void *								InterruptPage;
+ 	void *								SendInterruptPage;
+ 	void *								RecvInterruptPage;
+ 
+-	// 2 pages - 1st page for parent->child notification and 2nd is child->parent notification
++	/*
++	 * 2 pages - 1st page for parent->child notification and 2nd
++	 * is child->parent notification
++	 */
+ 	void *								MonitorPages;
+ 	LIST_ENTRY							ChannelMsgList;
+ 	spinlock_t channelmsg_lock;
+ 
+-	// List of channels
++	/* List of channels */
+ 	LIST_ENTRY							ChannelList;
+ 	spinlock_t channel_lock;
+ 
+@@ -91,25 +98,25 @@ typedef struct _VMBUS_CONNECTION {
+ 
+ 
+ typedef struct _VMBUS_MSGINFO {
+-	// Bookkeeping stuff
++	/* Bookkeeping stuff */
+ 	LIST_ENTRY			MsgListEntry;
+ 
+-	// Synchronize the request/response if needed
++	/* Synchronize the request/response if needed */
+ 	HANDLE				WaitEvent;
+ 
+-	// The message itself
++	/* The message itself */
+ 	unsigned char		Msg[0];
+ } VMBUS_MSGINFO;
+ 
+ 
+-//
+-// Externs
+-//
++
++/* Externs */
++
+ extern VMBUS_CONNECTION gVmbusConnection;
+ 
+-//
+-// General vmbus interface
+-//
++
++/* General vmbus interface */
++
+ static DEVICE_OBJECT*
+ VmbusChildDeviceCreate(
+ 	GUID deviceType,
+@@ -124,18 +131,18 @@ static void
+ VmbusChildDeviceRemove(
+    DEVICE_OBJECT* Device);
+ 
+-//static void
+-//VmbusChildDeviceDestroy(
+-//	DEVICE_OBJECT*);
++/* static void */
++/* VmbusChildDeviceDestroy( */
++/* DEVICE_OBJECT*); */
+ 
+ static VMBUS_CHANNEL*
+ GetChannelFromRelId(
+ 	u32 relId
+ 	);
+ 
+-//
+-// Connection interface
+-//
++
++/* Connection interface */
++
+ static int
+ VmbusConnect(
+ 	void
+@@ -163,4 +170,4 @@ VmbusOnEvents(
+ 	);
+ 
+ 
+-#endif // _VMBUS_PRIVATE_H_
++#endif /* _VMBUS_PRIVATE_H_ */
+diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c
+index d90265370ab6..9c4bfb6dea92 100644
+--- a/drivers/staging/hv/blkvsc_drv.c
++++ b/drivers/staging/hv/blkvsc_drv.c
+@@ -38,38 +38,41 @@
+ 
+ #include "include/StorVscApi.h"
+ 
+-//
+-// #defines
+-//
++
++/* #defines */
++
+ #define BLKVSC_MINORS	64
+ 
+-//
+-// Data types
+-//
++
++/* Data types */
++
+ enum blkvsc_device_type {
+ 	UNKNOWN_DEV_TYPE,
+ 	HARDDISK_TYPE,
+ 	DVD_TYPE,
+ };
+ 
+-// This request ties the struct request and struct blkvsc_request/STORVSC_REQUEST together
+-// A struct request may be represented by 1 or more struct blkvsc_request
++/*
++ * This request ties the struct request and struct
++ * blkvsc_request/STORVSC_REQUEST together A struct request may be
++ * represented by 1 or more struct blkvsc_request
++ */
+ struct blkvsc_request_group {
+ 	int					outstanding;
+ 	int					status;
+ 
+-	struct list_head	blkvsc_req_list;	// list of blkvsc_requests
++	struct list_head	blkvsc_req_list;	/* list of blkvsc_requests */
+ };
+ 
+ 
+ struct blkvsc_request {
+-	struct list_head	req_entry;			// blkvsc_request_group.blkvsc_req_list
++	struct list_head	req_entry;			/* blkvsc_request_group.blkvsc_req_list */
+ 
+-	struct list_head	pend_entry;			// block_device_context.pending_list
++	struct list_head	pend_entry;			/* block_device_context.pending_list */
+ 
+-	struct request		*req;				// This may be null if we generate a request internally
++	struct request		*req;				/* This may be null if we generate a request internally */
+ 	struct block_device_context	*dev;
+-	struct blkvsc_request_group	*group;		// The group this request is part of. Maybe null
++	struct blkvsc_request_group	*group;		/* The group this request is part of. Maybe null */
+ 
+ 	wait_queue_head_t	wevent;
+ 	int cond;
+@@ -83,13 +86,13 @@ struct blkvsc_request {
+ 	unsigned char cmnd[MAX_COMMAND_SIZE];
+ 
+ 	STORVSC_REQUEST		request;
+-	// !!!DO NOT ADD ANYTHING BELOW HERE!!! Otherwise, memory can overlap, because -
+-	// The extension buffer falls right here and is pointed to by request.Extension;
++	/* !!!DO NOT ADD ANYTHING BELOW HERE!!! Otherwise, memory can overlap, because - */
++	/* The extension buffer falls right here and is pointed to by request.Extension; */
+ };
+ 
+-// Per device structure
++/* Per device structure */
+ struct block_device_context {
+-	struct device_context	*device_ctx; // point back to our device context
++	struct device_context	*device_ctx; /* point back to our device context */
+ 	struct kmem_cache	*request_pool;
+ 	spinlock_t				lock;
+ 	struct gendisk			*gd;
+@@ -109,14 +112,14 @@ struct block_device_context {
+ 	int						users;
+ };
+ 
+-// Per driver
++/* Per driver */
+ struct blkvsc_driver_context {
+-	// !! These must be the first 2 fields !!
++	/* !! These must be the first 2 fields !! */
+ 	struct driver_context	drv_ctx;
+ 	STORVSC_DRIVER_OBJECT	drv_obj;
+ };
+ 
+-// Static decl
++/* Static decl */
+ static int blkvsc_probe(struct device *dev);
+ static int blkvsc_remove(struct device *device);
+ static void blkvsc_shutdown(struct device *device);
+@@ -144,7 +147,7 @@ static int blkvsc_do_pending_reqs(struct block_device_context *blkdev);
+ 
+ static int blkvsc_ringbuffer_size = BLKVSC_RING_BUFFER_SIZE;
+ 
+-// The one and only one
++/* The one and only one */
+ static struct blkvsc_driver_context g_blkvsc_drv;
+ 
+ 
+@@ -178,7 +181,7 @@ int blkvsc_drv_init(PFN_DRIVERINITIALIZE pfn_drv_init)
+ 
+ 	storvsc_drv_obj->RingBufferSize = blkvsc_ringbuffer_size;
+ 
+-	// Callback to client driver to complete the initialization
++	/* Callback to client driver to complete the initialization */
+ 	pfn_drv_init(&storvsc_drv_obj->Base);
+ 
+ 	drv_ctx->driver.name = storvsc_drv_obj->Base.name;
+@@ -188,7 +191,7 @@ int blkvsc_drv_init(PFN_DRIVERINITIALIZE pfn_drv_init)
+ 	drv_ctx->remove = blkvsc_remove;
+ 	drv_ctx->shutdown = blkvsc_shutdown;
+ 
+-	// The driver belongs to vmbus
++	/* The driver belongs to vmbus */
+ 	vmbus_child_driver_register(drv_ctx);
+ 
+ 	DPRINT_EXIT(BLKVSC_DRV);
+@@ -201,7 +204,7 @@ static int blkvsc_drv_exit_cb(struct device *dev, void *data)
+ {
+ 	struct device **curr = (struct device **)data;
+ 	*curr = dev;
+-	return 1; // stop iterating
++	return 1; /* stop iterating */
+ }
+ 
+ /*++
+@@ -224,13 +227,13 @@ void blkvsc_drv_exit(void)
+ 	{
+ 		current_dev = NULL;
+ 
+-		// Get the device
++		/* Get the device */
+ 		driver_for_each_device(&drv_ctx->driver, NULL, (void*)¤t_dev, blkvsc_drv_exit_cb);
+ 
+ 		if (current_dev == NULL)
+ 			break;
+ 
+-		// Initiate removal from the top-down
++		/* Initiate removal from the top-down */
+ 		device_unregister(current_dev);
+ 	}
+ 
+@@ -291,14 +294,14 @@ static int blkvsc_probe(struct device *device)
+ 
+ 	INIT_LIST_HEAD(&blkdev->pending_list);
+ 
+-	// Initialize what we can here
++	/* Initialize what we can here */
+ 	spin_lock_init(&blkdev->lock);
+ 
+ 	ASSERT(sizeof(struct blkvsc_request_group) <= sizeof(struct blkvsc_request));
+ 
+-        blkdev->request_pool = kmem_cache_create(dev_name(&device_ctx->device),
+-                sizeof(struct blkvsc_request) + storvsc_drv_obj->RequestExtSize, 0,
+-                SLAB_HWCACHE_ALIGN, NULL);
++	blkdev->request_pool = kmem_cache_create(dev_name(&device_ctx->device),
++		sizeof(struct blkvsc_request) + storvsc_drv_obj->RequestExtSize, 0,
++		SLAB_HWCACHE_ALIGN, NULL);
+ 	if (!blkdev->request_pool)
+ 	{
+ 		ret = -ENOMEM;
+@@ -306,7 +309,7 @@ static int blkvsc_probe(struct device *device)
+ 	}
+ 
+ 
+-	// Call to the vsc driver to add the device
++	/* Call to the vsc driver to add the device */
+ 	ret = storvsc_drv_obj->Base.OnDeviceAdd(device_obj, &device_info);
+ 	if (ret != 0)
+ 	{
+@@ -315,16 +318,16 @@ static int blkvsc_probe(struct device *device)
+ 	}
+ 
+ 	blkdev->device_ctx = device_ctx;
+-	blkdev->target = device_info.TargetId; // this identified the device 0 or 1
+-	blkdev->path = device_info.PathId; // this identified the ide ctrl 0 or 1
++	blkdev->target = device_info.TargetId; /* this identified the device 0 or 1 */
++	blkdev->path = device_info.PathId; /* this identified the ide ctrl 0 or 1 */
+ 
+ 	dev_set_drvdata(device, blkdev);
+ 
+-	// Calculate the major and device num
++	/* Calculate the major and device num */
+ 	if (blkdev->path == 0)
+ 	{
+ 		major = IDE0_MAJOR;
+-		devnum = blkdev->path + blkdev->target;		// 0 or 1
++		devnum = blkdev->path + blkdev->target;		/* 0 or 1 */
+ 
+ 		if (!ide0_registered)
+ 		{
+@@ -341,7 +344,7 @@ static int blkvsc_probe(struct device *device)
+ 	else if (blkdev->path == 1)
+ 	{
+ 		major = IDE1_MAJOR;
+-		devnum = blkdev->path + blkdev->target + 1; // 2 or 3
++		devnum = blkdev->path + blkdev->target + 1; /* 2 or 3 */
+ 
+ 		if (!ide1_registered)
+ 		{
+@@ -405,7 +408,7 @@ static int blkvsc_probe(struct device *device)
+ 
+ 	set_capacity(blkdev->gd, blkdev->capacity * (blkdev->sector_size/512));
+ 	blk_queue_logical_block_size(blkdev->gd->queue, blkdev->sector_size);
+-	// go!
++	/* go! */
+ 	add_disk(blkdev->gd);
+ 
+ 	DPRINT_INFO(BLKVSC_DRV, "%s added!! capacity %llu sector_size %d", blkdev->gd->disk_name, blkdev->capacity, blkdev->sector_size);
+@@ -494,7 +497,7 @@ static int blkvsc_do_flush(struct block_device_context *blkdev)
+ 	blkvsc_req->cmnd[0] = SYNCHRONIZE_CACHE;
+ 	blkvsc_req->cmd_len = 10;
+ 
+-	// Set this here since the completion routine may be invoked and completed before we return
++	/* Set this here since the completion routine may be invoked and completed before we return */
+ 	blkvsc_req->cond =0;
+ 	blkvsc_submit_request(blkvsc_req, blkvsc_cmd_completion);
+ 
+@@ -505,7 +508,7 @@ static int blkvsc_do_flush(struct block_device_context *blkdev)
+ 	return 0;
+ }
+ 
+-// Do a scsi INQUIRY cmd here to get the device type (ie disk or dvd)
++/* Do a scsi INQUIRY cmd here to get the device type (ie disk or dvd) */
+ static int blkvsc_do_inquiry(struct block_device_context *blkdev)
+ {
+ 	struct blkvsc_request *blkvsc_req=NULL;
+@@ -539,12 +542,12 @@ static int blkvsc_do_inquiry(struct block_device_context *blkdev)
+ 	blkvsc_req->request.DataBuffer.Length = 64;
+ 
+ 	blkvsc_req->cmnd[0] = INQUIRY;
+-	blkvsc_req->cmnd[1] = 0x1;		// Get product data
+-	blkvsc_req->cmnd[2] = 0x83;		// mode page 83
++	blkvsc_req->cmnd[1] = 0x1;		/* Get product data */
++	blkvsc_req->cmnd[2] = 0x83;		/* mode page 83 */
+ 	blkvsc_req->cmnd[4] = 64;
+ 	blkvsc_req->cmd_len = 6;
+ 
+-	// Set this here since the completion routine may be invoked and completed before we return
++	/* Set this here since the completion routine may be invoked and completed before we return */
+ 	blkvsc_req->cond =0;
+ 
+ 	blkvsc_submit_request(blkvsc_req, blkvsc_cmd_completion);
+@@ -556,7 +559,7 @@ static int blkvsc_do_inquiry(struct block_device_context *blkdev)
+ 	buf = kmap(page_buf);
+ 
+ 	/* print_hex_dump_bytes("", DUMP_PREFIX_NONE, buf, 64); */
+-	// be to le
++	/* be to le */
+ 	device_type = buf[0] & 0x1F;
+ 
+ 	if (device_type == 0x0)
+@@ -569,7 +572,7 @@ static int blkvsc_do_inquiry(struct block_device_context *blkdev)
+ 	}
+ 	else
+ 	{
+-		// TODO: this is currently unsupported device type
++		/* TODO: this is currently unsupported device type */
+ 		blkdev->device_type = UNKNOWN_DEV_TYPE;
+ 	}
+ 
+@@ -581,7 +584,7 @@ static int blkvsc_do_inquiry(struct block_device_context *blkdev)
+ 
+ 	memcpy(blkdev->device_id, &buf[8], blkdev->device_id_len);
+ 	/* printk_hex_dump_bytes("", DUMP_PREFIX_NONE, blkdev->device_id,
+-	 * 			 blkdev->device_id_len); */
++	 * blkdev->device_id_len); */
+ 
+ 	kunmap(page_buf);
+ 
+@@ -592,7 +595,7 @@ static int blkvsc_do_inquiry(struct block_device_context *blkdev)
+ 	return 0;
+ }
+ 
+-// Do a scsi READ_CAPACITY cmd here to get the size of the disk
++/* Do a scsi READ_CAPACITY cmd here to get the size of the disk */
+ static int blkvsc_do_read_capacity(struct block_device_context *blkdev)
+ {
+ 	struct blkvsc_request *blkvsc_req=NULL;
+@@ -604,7 +607,7 @@ static int blkvsc_do_read_capacity(struct block_device_context *blkdev)
+ 
+ 	blkdev->sector_size = 0;
+ 	blkdev->capacity = 0;
+-	blkdev->media_not_present = 0; // assume a disk is present
++	blkdev->media_not_present = 0; /* assume a disk is present */
+ 
+ 	blkvsc_req = kmem_cache_alloc(blkdev->request_pool, GFP_KERNEL);
+ 	if (!blkvsc_req)
+@@ -632,7 +635,10 @@ static int blkvsc_do_read_capacity(struct block_device_context *blkdev)
+ 	blkvsc_req->cmnd[0] = READ_CAPACITY;
+ 	blkvsc_req->cmd_len = 16;
+ 
+-	// Set this here since the completion routine may be invoked and completed before we return
++	/*
++	 * Set this here since the completion routine may be invoked
++	 * and completed before we return
++	 */
+ 	blkvsc_req->cond =0;
+ 
+ 	blkvsc_submit_request(blkvsc_req, blkvsc_cmd_completion);
+@@ -641,12 +647,12 @@ static int blkvsc_do_read_capacity(struct block_device_context *blkdev)
+ 
+ 	wait_event_interruptible(blkvsc_req->wevent, blkvsc_req->cond);
+ 
+-	// check error
++	/* check error */
+ 	if (blkvsc_req->request.Status)
+ 	{
+ 		scsi_normalize_sense(blkvsc_req->sense_buffer, SCSI_SENSE_BUFFERSIZE, &sense_hdr);
+ 
+-		if (sense_hdr.asc == 0x3A) // Medium not present
++		if (sense_hdr.asc == 0x3A) /* Medium not present */
+ 		{
+ 			blkdev->media_not_present = 1;
+ 		}
+@@ -655,7 +661,7 @@ static int blkvsc_do_read_capacity(struct block_device_context *blkdev)
+ 	}
+ 	buf = kmap(page_buf);
+ 
+-	// be to le
++	/* be to le */
+ 	blkdev->capacity = ((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]) + 1;
+ 	blkdev->sector_size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
+ 
+@@ -680,7 +686,7 @@ static int blkvsc_do_read_capacity16(struct block_device_context *blkdev)
+ 
+ 	blkdev->sector_size = 0;
+ 	blkdev->capacity = 0;
+-	blkdev->media_not_present = 0; // assume a disk is present
++	blkdev->media_not_present = 0; /* assume a disk is present */
+ 
+ 	blkvsc_req = kmem_cache_alloc(blkdev->request_pool, GFP_KERNEL);
+ 	if (!blkvsc_req)
+@@ -705,10 +711,13 @@ static int blkvsc_do_read_capacity16(struct block_device_context *blkdev)
+ 	blkvsc_req->request.DataBuffer.Offset = 0;
+ 	blkvsc_req->request.DataBuffer.Length = 12;
+ 
+-	blkvsc_req->cmnd[0] = 0x9E; //READ_CAPACITY16;
++	blkvsc_req->cmnd[0] = 0x9E; /* READ_CAPACITY16; */
+ 	blkvsc_req->cmd_len = 16;
+ 
+-	// Set this here since the completion routine may be invoked and completed before we return
++	/*
++	 * Set this here since the completion routine may be invoked
++	 * and completed before we return
++	 */
+ 	blkvsc_req->cond =0;
+ 
+ 	blkvsc_submit_request(blkvsc_req, blkvsc_cmd_completion);
+@@ -717,12 +726,12 @@ static int blkvsc_do_read_capacity16(struct block_device_context *blkdev)
+ 
+ 	wait_event_interruptible(blkvsc_req->wevent, blkvsc_req->cond);
+ 
+-	// check error
++	/* check error */
+ 	if (blkvsc_req->request.Status)
+ 	{
+ 		scsi_normalize_sense(blkvsc_req->sense_buffer, SCSI_SENSE_BUFFERSIZE, &sense_hdr);
+ 
+-		if (sense_hdr.asc == 0x3A) // Medium not present
++		if (sense_hdr.asc == 0x3A) /* Medium not present */
+ 		{
+ 			blkdev->media_not_present = 1;
+ 		}
+@@ -731,12 +740,12 @@ static int blkvsc_do_read_capacity16(struct block_device_context *blkdev)
+ 	}
+ 	buf = kmap(page_buf);
+ 
+-	// be to le
++	/* be to le */
+ 	blkdev->capacity = be64_to_cpu(*(unsigned long long*) &buf[0]) + 1;
+ 	blkdev->sector_size = be32_to_cpu(*(unsigned int*)&buf[8]);
+ 
+-	//blkdev->capacity = ((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]) + 1;
+-	//blkdev->sector_size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
++	/* blkdev->capacity = ((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]) + 1; */
++	/* blkdev->sector_size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]; */
+ 
+ 	kunmap(page_buf);
+ 
+@@ -777,15 +786,15 @@ static int blkvsc_remove(struct device *device)
+ 		return -1;
+ 	}
+ 
+-	// Call to the vsc driver to let it know that the device is being removed
++	/* Call to the vsc driver to let it know that the device is being removed */
+ 	ret = storvsc_drv_obj->Base.OnDeviceRemove(device_obj);
+ 	if (ret != 0)
+ 	{
+-		// TODO:
++		/* TODO: */
+ 		DPRINT_ERR(BLKVSC_DRV, "unable to remove blkvsc device (ret %d)", ret);
+ 	}
+ 
+-	// Get to a known state
++	/* Get to a known state */
+ 	spin_lock_irqsave(&blkdev->lock, flags);
+ 
+ 	blkdev->shutting_down = 1;
+@@ -922,7 +931,7 @@ static int blkvsc_submit_request(struct blkvsc_request *blkvsc_req, void (*reque
+ 	storvsc_req->Host = blkdev->port;
+ 	storvsc_req->Bus = blkdev->path;
+ 	storvsc_req->TargetId = blkdev->target;
+-	storvsc_req->LunId = 0;	 // this is not really used at all
++	storvsc_req->LunId = 0;	 /* this is not really used at all */
+ 
+ 	storvsc_req->CdbLen = blkvsc_req->cmd_len;
+ 	storvsc_req->Cdb = blkvsc_req->cmnd;
+@@ -939,11 +948,13 @@ static int blkvsc_submit_request(struct blkvsc_request *blkvsc_req, void (*reque
+ 	return ret;
+ }
+ 
+-//
+-// We break the request into 1 or more blkvsc_requests and submit them.
+-// If we cant submit them all, we put them on the pending_list. The
+-// blkvsc_request() will work on the pending_list.
+-//
++
++/*
++ * We break the request into 1 or more blkvsc_requests and submit
++ * them.  If we cant submit them all, we put them on the
++ * pending_list. The blkvsc_request() will work on the pending_list.
++ */
++
+ static int blkvsc_do_request(struct block_device_context *blkdev, struct request *req)
+ {
+ 	struct bio *bio=NULL;
+@@ -963,7 +974,7 @@ static int blkvsc_do_request(struct block_device_context *blkdev, struct request
+ 
+ 	DPRINT_DBG(BLKVSC_DRV, "blkdev %p req %p sect %llu \n", blkdev, req, blk_rq_pos(req));
+ 
+-	// Create a group to tie req to list of blkvsc_reqs
++	/* Create a group to tie req to list of blkvsc_reqs */
+ 	group = (struct blkvsc_request_group*)kmem_cache_alloc(blkdev->request_pool, GFP_ATOMIC);
+ 	if (!group)
+ 	{
+@@ -975,23 +986,23 @@ static int blkvsc_do_request(struct block_device_context *blkdev, struct request
+ 
+ 	start_sector = blk_rq_pos(req);
+ 
+-	// foreach bio in the request
++	/* foreach bio in the request */
+ 	if (req->bio)
+ 	 for (bio = req->bio; bio; bio = bio->bi_next)
+ 	{
+-		// Map this bio into an existing or new storvsc request
++		/* Map this bio into an existing or new storvsc request */
+ 		bio_for_each_segment (bvec, bio, seg_idx)
+ 		{
+ 			DPRINT_DBG(BLKVSC_DRV, "bio_for_each_segment() - req %p bio %p bvec %p seg_idx %d databuf_idx %d\n",
+ 							req, bio, bvec, seg_idx, databuf_idx);
+ 
+-			// Get a new storvsc request
+-			if ( (!blkvsc_req) ||									// 1st-time
++			/* Get a new storvsc request */
++			if ( (!blkvsc_req) ||									/* 1st-time */
+ 				 (databuf_idx >= MAX_MULTIPAGE_BUFFER_COUNT) ||
+-				 (bvec->bv_offset != 0) ||							// hole at the begin of page
+-				 (prev_bvec && (prev_bvec->bv_len != PAGE_SIZE)) )	// hold at the end of page
++				 (bvec->bv_offset != 0) ||							/* hole at the begin of page */
++				 (prev_bvec && (prev_bvec->bv_len != PAGE_SIZE)) )	/* hold at the end of page */
+ 			{
+-				// submit the prev one
++				/* submit the prev one */
+ 				if (blkvsc_req)
+ 				{
+ 					blkvsc_req->sector_start = start_sector;
+@@ -1002,11 +1013,11 @@ static int blkvsc_do_request(struct block_device_context *blkdev, struct request
+ 					blkvsc_init_rw(blkvsc_req);
+ 				}
+ 
+-				// Create new blkvsc_req to represent the current bvec
++				/* Create new blkvsc_req to represent the current bvec */
+ 				blkvsc_req = kmem_cache_alloc(blkdev->request_pool, GFP_ATOMIC);
+ 				if (!blkvsc_req)
+ 				{
+-					// free up everything
++					/* free up everything */
+ 					list_for_each_entry_safe(blkvsc_req, tmp, &group->blkvsc_req_list, req_entry)
+ 					{
+ 						list_del(&blkvsc_req->req_entry);
+@@ -1024,7 +1035,7 @@ static int blkvsc_do_request(struct block_device_context *blkdev, struct request
+ 				blkvsc_req->request.DataBuffer.Offset = bvec->bv_offset;
+ 				blkvsc_req->request.DataBuffer.Length = 0;
+ 
+-				// Add to the group
++				/* Add to the group */
+ 				blkvsc_req->group = group;
+ 				blkvsc_req->group->outstanding++;
+ 				list_add_tail(&blkvsc_req->req_entry, &blkvsc_req->group->blkvsc_req_list);
+@@ -1034,7 +1045,7 @@ static int blkvsc_do_request(struct block_device_context *blkdev, struct request
+ 				databuf_idx = 0;
+ 			}
+ 
+-			// Add the curr bvec/segment to the curr blkvsc_req
++			/* Add the curr bvec/segment to the curr blkvsc_req */
+ 			blkvsc_req->request.DataBuffer.PfnArray[databuf_idx] = page_to_pfn(bvec->bv_page);
+ 			blkvsc_req->request.DataBuffer.Length += bvec->bv_len;
+ 
+@@ -1043,11 +1054,11 @@ static int blkvsc_do_request(struct block_device_context *blkdev, struct request
+ 			databuf_idx++;
+ 			num_sectors += bvec->bv_len >> 9;
+ 
+-		} // bio_for_each_segment
++		} /* bio_for_each_segment */
+ 
+-	} // rq_for_each_bio
++	} /* rq_for_each_bio */
+ 
+-	// Handle the last one
++	/* Handle the last one */
+ 	if (blkvsc_req)
+ 	{
+ 		DPRINT_DBG(BLKVSC_DRV, "blkdev %p req %p group %p count %d\n", blkdev, req, blkvsc_req->group, blkvsc_req->group->outstanding);
+@@ -1134,8 +1145,11 @@ static void blkvsc_request_completion(STORVSC_REQUEST* request)
+ 	blkdev->num_outstanding_reqs--;
+ 	blkvsc_req->group->outstanding--;
+ 
+-	// Only start processing when all the blkvsc_reqs are completed. This guarantees no out-of-order
+-	// blkvsc_req completion when calling end_that_request_first()
++	/*
++	 * Only start processing when all the blkvsc_reqs are
++	 * completed. This guarantees no out-of-order blkvsc_req
++	 * completion when calling end_that_request_first()
++	 */
+ 	if (blkvsc_req->group->outstanding == 0)
+ 	{
+ 		list_for_each_entry_safe(comp_req, tmp, &blkvsc_req->group->blkvsc_req_list, req_entry)
+@@ -1152,7 +1166,7 @@ static void blkvsc_request_completion(STORVSC_REQUEST* request)
+ 				(!comp_req->request.Status ? 0: -EIO),
+ 				comp_req->sector_count * blkdev->sector_size))
+ 			{
+-				//All the sectors have been xferred ie the request is done
++				/* All the sectors have been xferred ie the request is done */
+ 				DPRINT_DBG(BLKVSC_DRV, "req %p COMPLETED\n", comp_req->req);
+ 				kmem_cache_free(blkdev->request_pool, comp_req->group);
+ 			}
+@@ -1180,11 +1194,14 @@ static int blkvsc_cancel_pending_reqs(struct block_device_context *blkdev)
+ 
+ 	DPRINT_DBG(BLKVSC_DRV, "blkvsc_cancel_pending_reqs()");
+ 
+-	// Flush the pending list first
++	/* Flush the pending list first */
+ 	list_for_each_entry_safe(pend_req, tmp, &blkdev->pending_list, pend_entry)
+ 	{
+-		// The pend_req could be part of a partially completed request. If so, complete those req first
+-		// until we hit the pend_req
++		/*
++		 * The pend_req could be part of a partially completed
++		 * request. If so, complete those req first until we
++		 * hit the pend_req
++		 */
+ 		list_for_each_entry_safe(comp_req, tmp2, &pend_req->group->blkvsc_req_list, req_entry)
+ 		{
+ 			DPRINT_DBG(BLKVSC_DRV, "completing blkvsc_req %p sect_start %llu sect_count %ld \n",
+@@ -1222,7 +1239,7 @@ static int blkvsc_cancel_pending_reqs(struct block_device_context *blkdev)
+ 			-EIO,
+ 			pend_req->sector_count * blkdev->sector_size))
+ 		{
+-			//All the sectors have been xferred ie the request is done
++			/* All the sectors have been xferred ie the request is done */
+ 			DPRINT_DBG(BLKVSC_DRV, "blkvsc_cancel_pending_reqs() - req %p COMPLETED\n", pend_req->req);
+ 			kmem_cache_free(blkdev->request_pool, pend_req->group);
+ 		}
+@@ -1239,7 +1256,7 @@ static int blkvsc_do_pending_reqs(struct block_device_context *blkdev)
+ 	struct blkvsc_request *pend_req, *tmp;
+ 	int ret=0;
+ 
+-	// Flush the pending list first
++	/* Flush the pending list first */
+ 	list_for_each_entry_safe(pend_req, tmp, &blkdev->pending_list, pend_entry)
+ 	{
+ 		DPRINT_DBG(BLKVSC_DRV, "working off pending_list - %p\n", pend_req);
+@@ -1378,51 +1395,51 @@ int blkvsc_getgeo(struct block_device *bd, struct hd_geometry *hg)
+ 	int rem=0;
+ 
+     if (total_sectors > (65535 * 16 * 255)) {
+-        total_sectors = (65535 * 16 * 255);
++	total_sectors = (65535 * 16 * 255);
+     }
+ 
+     if (total_sectors >= (65535 * 16 * 63)) {
+-        sectors_per_track = 255;
+-        heads = 16;
++	sectors_per_track = 255;
++	heads = 16;
+ 
+ 		cylinder_times_heads = total_sectors;
+-		rem = sector_div(cylinder_times_heads, sectors_per_track); // sector_div stores the quotient in cylinder_times_heads
++		rem = sector_div(cylinder_times_heads, sectors_per_track); /* sector_div stores the quotient in cylinder_times_heads */
+     }
+ 	else
+ 	{
+-        sectors_per_track = 17;
++	sectors_per_track = 17;
+ 
+ 		cylinder_times_heads = total_sectors;
+-        rem = sector_div(cylinder_times_heads, sectors_per_track); 	// sector_div stores the quotient in cylinder_times_heads
++	rem = sector_div(cylinder_times_heads, sectors_per_track);	/* sector_div stores the quotient in cylinder_times_heads */
+ 
+ 		temp = cylinder_times_heads + 1023;
+-		rem = sector_div(temp, 1024); 	// sector_div stores the quotient in temp
++		rem = sector_div(temp, 1024);	/* sector_div stores the quotient in temp */
+ 
+ 		heads = temp;
+ 
+-        if (heads < 4) {
+-            heads = 4;
+-        }
++	if (heads < 4) {
++	    heads = 4;
++	}
+ 
+-        if (cylinder_times_heads >= (heads * 1024) || (heads > 16)) {
+-            sectors_per_track = 31;
+-            heads = 16;
++	if (cylinder_times_heads >= (heads * 1024) || (heads > 16)) {
++	    sectors_per_track = 31;
++	    heads = 16;
+ 
+ 			cylinder_times_heads = total_sectors;
+-            rem = sector_div(cylinder_times_heads, sectors_per_track); // sector_div stores the quotient in cylinder_times_heads
+-        }
++	    rem = sector_div(cylinder_times_heads, sectors_per_track); /* sector_div stores the quotient in cylinder_times_heads */
++	}
+ 
+-        if (cylinder_times_heads >= (heads * 1024)) {
+-            sectors_per_track = 63;
+-            heads = 16;
++	if (cylinder_times_heads >= (heads * 1024)) {
++	    sectors_per_track = 63;
++	    heads = 16;
+ 
+ 			cylinder_times_heads = total_sectors;
+-            rem = sector_div(cylinder_times_heads, sectors_per_track); // sector_div stores the quotient in cylinder_times_heads
+-        }
++	    rem = sector_div(cylinder_times_heads, sectors_per_track); /* sector_div stores the quotient in cylinder_times_heads */
++	}
+     }
+ 
+ 	temp = cylinder_times_heads;
+-    rem = sector_div(temp, heads); // sector_div stores the quotient in temp
++    rem = sector_div(temp, heads); /* sector_div stores the quotient in temp */
+ 	cylinders = temp;
+ 
+ 	hg->heads = heads;
+@@ -1442,8 +1459,8 @@ static int blkvsc_ioctl(struct inode *inode, struct file *filep, unsigned cmd, u
+ 
+ 	switch (cmd)
+ 	{
+-	// TODO: I think there is certain format for HDIO_GET_IDENTITY rather than just
+-	// a GUID. Commented it out for now.
++	/* TODO: I think there is certain format for HDIO_GET_IDENTITY rather than just */
++	/* a GUID. Commented it out for now. */
+ 	/*case HDIO_GET_IDENTITY:
+ 		DPRINT_INFO(BLKVSC_DRV, "HDIO_GET_IDENTITY\n");
+ 
+@@ -1468,7 +1485,7 @@ static int __init blkvsc_init(void)
+ {
+ 	int ret;
+ 
+-	ASSERT(sizeof(sector_t) == 8); // Make sure CONFIG_LBD is set
++	ASSERT(sizeof(sector_t) == 8); /* Make sure CONFIG_LBD is set */
+ 
+ 	DPRINT_ENTER(BLKVSC_DRV);
+ 
+@@ -1495,4 +1512,4 @@ module_param(blkvsc_ringbuffer_size, int, S_IRUGO);
+ module_init(blkvsc_init);
+ module_exit(blkvsc_exit);
+ 
+-// eof
++/* eof */
+diff --git a/drivers/staging/hv/include/ChannelMessages.h b/drivers/staging/hv/include/ChannelMessages.h
+index 6a6342ab4d78..097e1c11e915 100644
+--- a/drivers/staging/hv/include/ChannelMessages.h
++++ b/drivers/staging/hv/include/ChannelMessages.h
+@@ -31,9 +31,9 @@ typedef u32 NTSTATUS;
+ 
+ #pragma pack(push,1)
+ 
+-//
+-// Version 1 messages
+-//
++
++/* Version 1 messages */
++
+ 
+ typedef enum _VMBUS_CHANNEL_MESSAGE_TYPE
+ {
+@@ -61,9 +61,9 @@ typedef enum _VMBUS_CHANNEL_MESSAGE_TYPE
+     ChannelMessageCount
+ } VMBUS_CHANNEL_MESSAGE_TYPE, *PVMBUS_CHANNEL_MESSAGE_TYPE;
+ 
+-// begin_wpp config
+-// CUSTOM_TYPE(ChannelMessageType, ItemEnum(_VMBUS_CHANNEL_MESSAGE_TYPE));
+-// end_wpp
++/* begin_wpp config */
++/* CUSTOM_TYPE(ChannelMessageType, ItemEnum(_VMBUS_CHANNEL_MESSAGE_TYPE)); */
++/* end_wpp */
+ 
+ typedef struct _VMBUS_CHANNEL_MESSAGE_HEADER
+ {
+@@ -71,21 +71,21 @@ typedef struct _VMBUS_CHANNEL_MESSAGE_HEADER
+     u32                      Padding;
+ } VMBUS_CHANNEL_MESSAGE_HEADER, *PVMBUS_CHANNEL_MESSAGE_HEADER;
+ 
+-// Query VMBus Version parameters
++/* Query VMBus Version parameters */
+ typedef struct _VMBUS_CHANNEL_QUERY_VMBUS_VERSION
+ {
+     VMBUS_CHANNEL_MESSAGE_HEADER Header;
+     u32 Version;
+ } VMBUS_CHANNEL_QUERY_VMBUS_VERSION, *PVMBUS_CHANNEL_QUERY_VMBUS_VERSION;
+ 
+-// VMBus Version Supported parameters
++/* VMBus Version Supported parameters */
+ typedef struct _VMBUS_CHANNEL_VERSION_SUPPORTED
+ {
+     VMBUS_CHANNEL_MESSAGE_HEADER Header;
+     bool VersionSupported;
+ } VMBUS_CHANNEL_VERSION_SUPPORTED, *PVMBUS_CHANNEL_VERSION_SUPPORTED;
+ 
+-// Offer Channel parameters
++/* Offer Channel parameters */
+ typedef struct _VMBUS_CHANNEL_OFFER_CHANNEL
+ {
+     VMBUS_CHANNEL_MESSAGE_HEADER Header;
+@@ -95,67 +95,69 @@ typedef struct _VMBUS_CHANNEL_OFFER_CHANNEL
+     bool MonitorAllocated;
+ } VMBUS_CHANNEL_OFFER_CHANNEL, *PVMBUS_CHANNEL_OFFER_CHANNEL;
+ 
+-//
+-// Make sure VMBUS_CHANNEL_OFFER_CHANNEL fits into Synic message.
+-//
++
++/* Make sure VMBUS_CHANNEL_OFFER_CHANNEL fits into Synic message. */
++
+ C_ASSERT(sizeof(VMBUS_CHANNEL_OFFER_CHANNEL) <= MAXIMUM_SYNIC_MESSAGE_BYTES);
+ 
+-// Rescind Offer parameters
++/* Rescind Offer parameters */
+ typedef struct _VMBUS_CHANNEL_RESCIND_OFFER
+ {
+     VMBUS_CHANNEL_MESSAGE_HEADER Header;
+     u32          ChildRelId;
+ } VMBUS_CHANNEL_RESCIND_OFFER, *PVMBUS_CHANNEL_RESCIND_OFFER;
+ 
+-// Request Offer -- no parameters, SynIC message contains the partition ID
+-// Set Snoop -- no parameters, SynIC message contains the partition ID
+-// Clear Snoop -- no parameters, SynIC message contains the partition ID
+-// All Offers Delivered -- no parameters, SynIC message contains the partition ID
+-// Flush Client -- no parameters, SynIC message contains the partition ID
++/* Request Offer -- no parameters, SynIC message contains the partition ID */
++/* Set Snoop -- no parameters, SynIC message contains the partition ID */
++/* Clear Snoop -- no parameters, SynIC message contains the partition ID */
++/* All Offers Delivered -- no parameters, SynIC message contains the partition ID */
++/* Flush Client -- no parameters, SynIC message contains the partition ID */
+ 
+-// Open Channel parameters
++/* Open Channel parameters */
+ typedef struct _VMBUS_CHANNEL_OPEN_CHANNEL
+ {
+     VMBUS_CHANNEL_MESSAGE_HEADER Header;
+ 
+-    //
+-    // Identifies the specific VMBus channel that is being opened.
+-    //
++
++    /* Identifies the specific VMBus channel that is being opened. */
++
+     u32          ChildRelId;
+ 
+-    //
+-    // ID making a particular open request at a channel offer unique.
+-    //
++
++    /* ID making a particular open request at a channel offer unique. */
++
+     u32          OpenId;
+ 
+-    //
+-    // GPADL for the channel's ring buffer.
+-    //
++
++    /* GPADL for the channel's ring buffer. */
++
+     GPADL_HANDLE    RingBufferGpadlHandle;
+ 
+-    //
+-    // GPADL for the channel's server context save area.
+-    //
++
++    /* GPADL for the channel's server context save area. */
++
+     GPADL_HANDLE    ServerContextAreaGpadlHandle;
+ 
+-    //
+-    // The upstream ring buffer begins at offset zero in the memory described
+-    // by RingBufferGpadlHandle. The downstream ring buffer follows it at this
+-    // offset (in pages).
+-    //
++
++    /*
++     * The upstream ring buffer begins at offset zero in the memory
++     * described by RingBufferGpadlHandle. The downstream ring buffer
++     * follows it at this offset (in pages).
++     */
++
+     u32          DownstreamRingBufferPageOffset;
+ 
+-    //
+-    // User-specific data to be passed along to the server endpoint.
+-    //
++
++    /* User-specific data to be passed along to the server endpoint. */
++
+     unsigned char           UserData[MAX_USER_DEFINED_BYTES];
+ 
+ } VMBUS_CHANNEL_OPEN_CHANNEL, *PVMBUS_CHANNEL_OPEN_CHANNEL;
+ 
+-// Reopen Channel parameters;
++/* Reopen Channel parameters; */
+ typedef VMBUS_CHANNEL_OPEN_CHANNEL VMBUS_CHANNEL_REOPEN_CHANNEL, *PVMBUS_CHANNEL_REOPEN_CHANNEL;
+ 
+-// Open Channel Result parameters
++/* Open Channel Result parameters */
+ typedef struct _VMBUS_CHANNEL_OPEN_RESULT
+ {
+     VMBUS_CHANNEL_MESSAGE_HEADER Header;
+@@ -164,24 +166,26 @@ typedef struct _VMBUS_CHANNEL_OPEN_RESULT
+     NTSTATUS    Status;
+ } VMBUS_CHANNEL_OPEN_RESULT, *PVMBUS_CHANNEL_OPEN_RESULT;
+ 
+-// Close channel parameters;
++/* Close channel parameters; */
+ typedef struct _VMBUS_CHANNEL_CLOSE_CHANNEL
+ {
+     VMBUS_CHANNEL_MESSAGE_HEADER Header;
+     u32      ChildRelId;
+ } VMBUS_CHANNEL_CLOSE_CHANNEL, *PVMBUS_CHANNEL_CLOSE_CHANNEL;
+ 
+-// Channel Message GPADL
++/* Channel Message GPADL */
+ #define GPADL_TYPE_RING_BUFFER          1
+ #define GPADL_TYPE_SERVER_SAVE_AREA     2
+ #define GPADL_TYPE_TRANSACTION          8
+ 
+-//
+-// The number of PFNs in a GPADL message is defined by the number of pages
+-// that would be spanned by ByteCount and ByteOffset.  If the implied number
+-// of PFNs won't fit in this packet, there will be a follow-up packet that
+-// contains more.
+-//
++
++/*
++ * The number of PFNs in a GPADL message is defined by the number of
++ * pages that would be spanned by ByteCount and ByteOffset.  If the
++ * implied number of PFNs won't fit in this packet, there will be a
++ * follow-up packet that contains more.
++ */
++
+ 
+ typedef struct _VMBUS_CHANNEL_GPADL_HEADER
+ {
+@@ -194,9 +198,9 @@ typedef struct _VMBUS_CHANNEL_GPADL_HEADER
+ } VMBUS_CHANNEL_GPADL_HEADER, *PVMBUS_CHANNEL_GPADL_HEADER;
+ 
+ 
+-//
+-// This is the followup packet that contains more PFNs.
+-//
++
++/* This is the followup packet that contains more PFNs. */
++
+ 
+ typedef struct _VMBUS_CHANNEL_GPADL_BODY
+ {
+@@ -269,10 +273,10 @@ typedef struct _VMBUS_CHANNEL_VERSION_RESPONSE
+ 
+ typedef VMBUS_CHANNEL_MESSAGE_HEADER VMBUS_CHANNEL_UNLOAD, *PVMBUS_CHANNEL_UNLOAD;
+ 
+-//
+-// Kind of a table to use the preprocessor to get us the right type for a
+-// specified message ID. Used with ChAllocateSendMessage()
+-//
++
++/* Kind of a table to use the preprocessor to get us the right type for a */
++/* specified message ID. Used with ChAllocateSendMessage() */
++
+ #define ChannelMessageQueryVmbusVersion_TYPE    VMBUS_CHANNEL_MESSAGE_HEADER
+ #define ChannelMessageVmbusVersionSupported_TYPE VMBUS_CHANNEL_VERSION_SUPPORTED
+ #define ChannelMessageOfferChannel_TYPE         VMBUS_CHANNEL_OFFER_CHANNEL
+@@ -295,18 +299,17 @@ typedef VMBUS_CHANNEL_MESSAGE_HEADER VMBUS_CHANNEL_UNLOAD, *PVMBUS_CHANNEL_UNLOA
+ #define ChannelMessageVersionResponse_TYPE      VMBUS_CHANNEL_VERSION_RESPONSE
+ #define ChannelMessageUnload_TYPE               VMBUS_CHANNEL_UNLOAD
+ 
+-//
+-// Preprocessor wrapper to ChAllocateSendMessageSize() converting the return
+-// value to the correct pointer and calculate the needed size.
+-//
+-// Argument:
+-//
+-//  Id - the numberic ID (type VMBUS_CHANNEL_MESSAGE_TYPE) of the message to
+-//       send.
+-//
++
++/* Preprocessor wrapper to ChAllocateSendMessageSize() converting the return */
++/* value to the correct pointer and calculate the needed size. */
++
++/* Argument: */
++
++/*  Id - the numberic ID (type VMBUS_CHANNEL_MESSAGE_TYPE) of the message to */
++/*       send. */
++
+ #define ChAllocateSendMessage(Id, Fn, Context)   \
+     (Id##_TYPE*)ChAllocateSendMessageSized(sizeof(Id##_TYPE), Id, Fn, Context)
+ 
+ 
+ #pragma pack(pop)
+-
+diff --git a/drivers/staging/hv/include/HvHalApi.h b/drivers/staging/hv/include/HvHalApi.h
+index ad7ba4dafefd..cda369e8398f 100644
+--- a/drivers/staging/hv/include/HvHalApi.h
++++ b/drivers/staging/hv/include/HvHalApi.h
+@@ -25,8 +25,8 @@
+ #pragma once
+ 
+ 
+-//
+-// Time in the hypervisor is measured in 100 nanosecond units
+-//
++
++/* Time in the hypervisor is measured in 100 nanosecond units */
++
+ typedef u64 HV_NANO100_TIME,     *PHV_NANO100_TIME;
+ typedef u64 HV_NANO100_DURATION, *PHV_NANO100_DURATION;
+diff --git a/drivers/staging/hv/include/HvHcApi.h b/drivers/staging/hv/include/HvHcApi.h
+index d304305fddfa..034bab79c0a8 100644
+--- a/drivers/staging/hv/include/HvHcApi.h
++++ b/drivers/staging/hv/include/HvHcApi.h
+@@ -24,9 +24,9 @@
+ 
+ #pragma once
+ 
+-//
+-// Declare the various hypercall operations.
+-//
++
++/* Declare the various hypercall operations. */
++
+ typedef enum _HV_CALL_CODE
+ {
+ 
+@@ -34,9 +34,9 @@ typedef enum _HV_CALL_CODE
+     HvCallSignalEvent                   = 0x005d,
+ 
+ } HV_CALL_CODE, *PHV_CALL_CODE;
+-//
+-// Definition of the HvPostMessage hypercall input structure.
+-//
++
++/* Definition of the HvPostMessage hypercall input structure. */
++
+ 
+ typedef struct _HV_INPUT_POST_MESSAGE
+ {
+@@ -48,9 +48,9 @@ typedef struct _HV_INPUT_POST_MESSAGE
+ } HV_INPUT_POST_MESSAGE, *PHV_INPUT_POST_MESSAGE;
+ 
+ 
+-//
+-// Definition of the HvSignalEvent hypercall input structure.
+-//
++
++/* Definition of the HvSignalEvent hypercall input structure. */
++
+ 
+ typedef struct _HV_INPUT_SIGNAL_EVENT
+ {
+diff --git a/drivers/staging/hv/include/HvPtApi.h b/drivers/staging/hv/include/HvPtApi.h
+index b79e543a0c66..c32dbf660ae7 100644
+--- a/drivers/staging/hv/include/HvPtApi.h
++++ b/drivers/staging/hv/include/HvPtApi.h
+@@ -24,15 +24,15 @@
+ 
+ #pragma once
+ 
+-//
+-// Versioning definitions used for guests reporting themselves to the
+-// hypervisor, and visa versa.
+-// ==================================================================
+-//
+-
+-//
+-// Version info reported by guest OS's
+-//
++
++/* Versioning definitions used for guests reporting themselves to the */
++/* hypervisor, and visa versa. */
++/* ================================================================== */
++
++
++
++/* Version info reported by guest OS's */
++
+ typedef enum _HV_GUEST_OS_VENDOR
+ {
+     HvGuestOsVendorMicrosoft        = 0x0001
+@@ -50,9 +50,9 @@ typedef enum _HV_GUEST_OS_MICROSOFT_IDS
+ 
+ } HV_GUEST_OS_MICROSOFT_IDS, *PHV_GUEST_OS_MICROSOFT_IDS;
+ 
+-//
+-// Declare the MSR used to identify the guest OS.
+-//
++
++/* Declare the MSR used to identify the guest OS. */
++
+ #define HV_X64_MSR_GUEST_OS_ID 0x40000000
+ 
+ typedef union _HV_X64_MSR_GUEST_OS_ID_CONTENTS
+@@ -61,17 +61,17 @@ typedef union _HV_X64_MSR_GUEST_OS_ID_CONTENTS
+     struct
+     {
+         u64 BuildNumber    : 16;
+-        u64 ServiceVersion : 8; // Service Pack, etc.
++        u64 ServiceVersion : 8; /* Service Pack, etc. */
+         u64 MinorVersion   : 8;
+         u64 MajorVersion   : 8;
+-        u64 OsId           : 8; // HV_GUEST_OS_MICROSOFT_IDS (If Vendor=MS)
+-        u64 VendorId       : 16; // HV_GUEST_OS_VENDOR
++        u64 OsId           : 8; /* HV_GUEST_OS_MICROSOFT_IDS (If Vendor=MS) */
++        u64 VendorId       : 16; /* HV_GUEST_OS_VENDOR */
+     };
+ } HV_X64_MSR_GUEST_OS_ID_CONTENTS, *PHV_X64_MSR_GUEST_OS_ID_CONTENTS;
+ 
+-//
+-// Declare the MSR used to setup pages used to communicate with the hypervisor.
+-//
++
++/* Declare the MSR used to setup pages used to communicate with the hypervisor. */
++
+ #define HV_X64_MSR_HYPERCALL 0x40000001
+ 
+ typedef union _HV_X64_MSR_HYPERCALL_CONTENTS
+diff --git a/drivers/staging/hv/include/HvStatus.h b/drivers/staging/hv/include/HvStatus.h
+index 3db3dbda135c..c747e7e7159f 100644
+--- a/drivers/staging/hv/include/HvStatus.h
++++ b/drivers/staging/hv/include/HvStatus.h
+@@ -22,697 +22,697 @@
+  */
+ 
+ 
+-// begin_hvgdk
+-//
+-// Status codes for hypervisor operations.
+-//
++/* begin_hvgdk */
++
++/* Status codes for hypervisor operations. */
++
+ typedef u16 HV_STATUS, *PHV_STATUS;
+ 
+-//
+-// MessageId: HV_STATUS_SUCCESS
+-//
+-// MessageText:
+-//
+-// The specified hypercall succeeded
+-//
++
++/* MessageId: HV_STATUS_SUCCESS */
++
++/* MessageText: */
++
++/* The specified hypercall succeeded */
++
+ #define HV_STATUS_SUCCESS                ((HV_STATUS)0x0000)
+ 
+-//
+-// MessageId: HV_STATUS_INVALID_HYPERCALL_CODE
+-//
+-// MessageText:
+-//
+-// The hypervisor does not support the operation because the specified hypercall code is not supported.
+-//
++
++/* MessageId: HV_STATUS_INVALID_HYPERCALL_CODE */
++
++/* MessageText: */
++
++/* The hypervisor does not support the operation because the specified hypercall code is not supported. */
++
+ #define HV_STATUS_INVALID_HYPERCALL_CODE ((HV_STATUS)0x0002)
+ 
+-//
+-// MessageId: HV_STATUS_INVALID_HYPERCALL_INPUT
+-//
+-// MessageText:
+-//
+-// The hypervisor does not support the operation because the encoding for the hypercall input register is not supported.
+-//
++
++/* MessageId: HV_STATUS_INVALID_HYPERCALL_INPUT */
++
++/* MessageText: */
++
++/* The hypervisor does not support the operation because the encoding for the hypercall input register is not supported. */
++
+ #define HV_STATUS_INVALID_HYPERCALL_INPUT ((HV_STATUS)0x0003)
+ 
+-//
+-// MessageId: HV_STATUS_INVALID_ALIGNMENT
+-//
+-// MessageText:
+-//
+-// The hypervisor could not perform the operation beacuse a parameter has an invalid alignment.
+-//
++
++/* MessageId: HV_STATUS_INVALID_ALIGNMENT */
++
++/* MessageText: */
++
++/* The hypervisor could not perform the operation beacuse a parameter has an invalid alignment. */
++
+ #define HV_STATUS_INVALID_ALIGNMENT      ((HV_STATUS)0x0004)
+ 
+-//
+-// MessageId: HV_STATUS_INVALID_PARAMETER
+-//
+-// MessageText:
+-//
+-// The hypervisor could not perform the operation beacuse an invalid parameter was specified.
+-//
++
++/* MessageId: HV_STATUS_INVALID_PARAMETER */
++
++/* MessageText: */
++
++/* The hypervisor could not perform the operation beacuse an invalid parameter was specified. */
++
+ #define HV_STATUS_INVALID_PARAMETER      ((HV_STATUS)0x0005)
+ 
+-//
+-// MessageId: HV_STATUS_ACCESS_DENIED
+-//
+-// MessageText:
+-//
+-// Access to the specified object was denied.
+-//
++
++/* MessageId: HV_STATUS_ACCESS_DENIED */
++
++/* MessageText: */
++
++/* Access to the specified object was denied. */
++
+ #define HV_STATUS_ACCESS_DENIED          ((HV_STATUS)0x0006)
+ 
+-//
+-// MessageId: HV_STATUS_INVALID_PARTITION_STATE
+-//
+-// MessageText:
+-//
+-// The hypervisor could not perform the operation because the partition is entering or in an invalid state.
+-//
++
++/* MessageId: HV_STATUS_INVALID_PARTITION_STATE */
++
++/* MessageText: */
++
++/* The hypervisor could not perform the operation because the partition is entering or in an invalid state. */
++
+ #define HV_STATUS_INVALID_PARTITION_STATE ((HV_STATUS)0x0007)
+ 
+-//
+-// MessageId: HV_STATUS_OPERATION_DENIED
+-//
+-// MessageText:
+-//
+-// The operation is not allowed in the current state.
+-//
++
++/* MessageId: HV_STATUS_OPERATION_DENIED */
++
++/* MessageText: */
++
++/* The operation is not allowed in the current state. */
++
+ #define HV_STATUS_OPERATION_DENIED       ((HV_STATUS)0x0008)
+ 
+-//
+-// MessageId: HV_STATUS_UNKNOWN_PROPERTY
+-//
+-// MessageText:
+-//
+-// The hypervisor does not recognize the specified partition property.
+-//
++
++/* MessageId: HV_STATUS_UNKNOWN_PROPERTY */
++
++/* MessageText: */
++
++/* The hypervisor does not recognize the specified partition property. */
++
+ #define HV_STATUS_UNKNOWN_PROPERTY       ((HV_STATUS)0x0009)
+ 
+-//
+-// MessageId: HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE
+-//
+-// MessageText:
+-//
+-// The specified value of a partition property is out of range or violates an invariant.
+-//
++
++/* MessageId: HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE */
++
++/* MessageText: */
++
++/* The specified value of a partition property is out of range or violates an invariant. */
++
+ #define HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE ((HV_STATUS)0x000A)
+ 
+-//
+-// MessageId: HV_STATUS_INSUFFICIENT_MEMORY
+-//
+-// MessageText:
+-//
+-// There is not enough memory in the hypervisor pool to complete the operation.
+-//
++
++/* MessageId: HV_STATUS_INSUFFICIENT_MEMORY */
++
++/* MessageText: */
++
++/* There is not enough memory in the hypervisor pool to complete the operation. */
++
+ #define HV_STATUS_INSUFFICIENT_MEMORY    ((HV_STATUS)0x000B)
+ 
+-//
+-// MessageId: HV_STATUS_PARTITION_TOO_DEEP
+-//
+-// MessageText:
+-//
+-// The maximum partition depth has been exceeded for the partition hierarchy.
+-//
++
++/* MessageId: HV_STATUS_PARTITION_TOO_DEEP */
++
++/* MessageText: */
++
++/* The maximum partition depth has been exceeded for the partition hierarchy. */
++
+ #define HV_STATUS_PARTITION_TOO_DEEP     ((HV_STATUS)0x000C)
+ 
+-//
+-// MessageId: HV_STATUS_INVALID_PARTITION_ID
+-//
+-// MessageText:
+-//
+-// A partition with the specified partition Id does not exist.
+-//
++
++/* MessageId: HV_STATUS_INVALID_PARTITION_ID */
++
++/* MessageText: */
++
++/* A partition with the specified partition Id does not exist. */
++
+ #define HV_STATUS_INVALID_PARTITION_ID   ((HV_STATUS)0x000D)
+ 
+-//
+-// MessageId: HV_STATUS_INVALID_VP_INDEX
+-//
+-// MessageText:
+-//
+-// The hypervisor could not perform the operation because the specified VP index is invalid.
+-//
++
++/* MessageId: HV_STATUS_INVALID_VP_INDEX */
++
++/* MessageText: */
++
++/* The hypervisor could not perform the operation because the specified VP index is invalid. */
++
+ #define HV_STATUS_INVALID_VP_INDEX       ((HV_STATUS)0x000E)
+ 
+-//
+-// MessageId: HV_STATUS_NOT_FOUND
+-//
+-// MessageText:
+-//
+-// The iteration is complete; no addition items in the iteration could be found.
+-//
++
++/* MessageId: HV_STATUS_NOT_FOUND */
++
++/* MessageText: */
++
++/* The iteration is complete; no addition items in the iteration could be found. */
++
+ #define HV_STATUS_NOT_FOUND              ((HV_STATUS)0x0010)
+ 
+-//
+-// MessageId: HV_STATUS_INVALID_PORT_ID
+-//
+-// MessageText:
+-//
+-// The hypervisor could not perform the operation because the specified port identifier is invalid.
+-//
++
++/* MessageId: HV_STATUS_INVALID_PORT_ID */
++
++/* MessageText: */
++
++/* The hypervisor could not perform the operation because the specified port identifier is invalid. */
++
+ #define HV_STATUS_INVALID_PORT_ID        ((HV_STATUS)0x0011)
+ 
+-//
+-// MessageId: HV_STATUS_INVALID_CONNECTION_ID
+-//
+-// MessageText:
+-//
+-// The hypervisor could not perform the operation because the specified connection identifier is invalid.
+-//
++
++/* MessageId: HV_STATUS_INVALID_CONNECTION_ID */
++
++/* MessageText: */
++
++/* The hypervisor could not perform the operation because the specified connection identifier is invalid. */
++
+ #define HV_STATUS_INVALID_CONNECTION_ID  ((HV_STATUS)0x0012)
+ 
+-//
+-// MessageId: HV_STATUS_INSUFFICIENT_BUFFERS
+-//
+-// MessageText:
+-//
+-// You did not supply enough message buffers to send a message.
+-//
++
++/* MessageId: HV_STATUS_INSUFFICIENT_BUFFERS */
++
++/* MessageText: */
++
++/* You did not supply enough message buffers to send a message. */
++
+ #define HV_STATUS_INSUFFICIENT_BUFFERS   ((HV_STATUS)0x0013)
+ 
+-//
+-// MessageId: HV_STATUS_NOT_ACKNOWLEDGED
+-//
+-// MessageText:
+-//
+-// The previous virtual interrupt has not been acknowledged.
+-//
++
++/* MessageId: HV_STATUS_NOT_ACKNOWLEDGED */
++
++/* MessageText: */
++
++/* The previous virtual interrupt has not been acknowledged. */
++
+ #define HV_STATUS_NOT_ACKNOWLEDGED       ((HV_STATUS)0x0014)
+ 
+-//
+-// MessageId: HV_STATUS_INVALID_VP_STATE
+-//
+-// MessageText:
+-//
+-// A virtual processor is not in the correct state for the performance of the indicated operation.
+-//
++
++/* MessageId: HV_STATUS_INVALID_VP_STATE */
++
++/* MessageText: */
++
++/* A virtual processor is not in the correct state for the performance of the indicated operation. */
++
+ #define HV_STATUS_INVALID_VP_STATE       ((HV_STATUS)0x0015)
+ 
+-//
+-// MessageId: HV_STATUS_ACKNOWLEDGED
+-//
+-// MessageText:
+-//
+-// The previous virtual interrupt has already been acknowledged.
+-//
++
++/* MessageId: HV_STATUS_ACKNOWLEDGED */
++
++/* MessageText: */
++
++/* The previous virtual interrupt has already been acknowledged. */
++
+ #define HV_STATUS_ACKNOWLEDGED           ((HV_STATUS)0x0016)
+ 
+-//
+-// MessageId: HV_STATUS_INVALID_SAVE_RESTORE_STATE
+-//
+-// MessageText:
+-//
+-// The indicated partition is not in a valid state for saving or restoring.
+-//
++
++/* MessageId: HV_STATUS_INVALID_SAVE_RESTORE_STATE */
++
++/* MessageText: */
++
++/* The indicated partition is not in a valid state for saving or restoring. */
++
+ #define HV_STATUS_INVALID_SAVE_RESTORE_STATE ((HV_STATUS)0x0017)
+ 
+-//
+-// MessageId: HV_STATUS_INVALID_SYNIC_STATE
+-//
+-// MessageText:
+-//
+-// The hypervisor could not complete the operation because a required feature of the synthetic interrupt controller (SynIC) was disabled.
+-//
++
++/* MessageId: HV_STATUS_INVALID_SYNIC_STATE */
++
++/* MessageText: */
++
++/* The hypervisor could not complete the operation because a required feature of the synthetic interrupt controller (SynIC) was disabled. */
++
+ #define HV_STATUS_INVALID_SYNIC_STATE    ((HV_STATUS)0x0018)
+ 
+-//
+-// MessageId: HV_STATUS_OBJECT_IN_USE
+-//
+-// MessageText:
+-//
+-// The hypervisor could not perform the operation because the object or value was either already in use or being used for a purpose that would not permit completing the operation.
+-//
++
++/* MessageId: HV_STATUS_OBJECT_IN_USE */
++
++/* MessageText: */
++
++/* The hypervisor could not perform the operation because the object or value was either already in use or being used for a purpose that would not permit completing the operation. */
++
+ #define HV_STATUS_OBJECT_IN_USE          ((HV_STATUS)0x0019)
+ 
+-//
+-// MessageId: HV_STATUS_INVALID_PROXIMITY_DOMAIN_INFO
+-//
+-// MessageText:
+-//
+-// The proximity domain information is invalid.
+-//
++
++/* MessageId: HV_STATUS_INVALID_PROXIMITY_DOMAIN_INFO */
++
++/* MessageText: */
++
++/* The proximity domain information is invalid. */
++
+ #define HV_STATUS_INVALID_PROXIMITY_DOMAIN_INFO ((HV_STATUS)0x001A)
+ 
+-//
+-// MessageId: HV_STATUS_NO_DATA
+-//
+-// MessageText:
+-//
+-// An attempt to retrieve debugging data failed because none was available.
+-//
++
++/* MessageId: HV_STATUS_NO_DATA */
++
++/* MessageText: */
++
++/* An attempt to retrieve debugging data failed because none was available. */
++
+ #define HV_STATUS_NO_DATA                ((HV_STATUS)0x001B)
+ 
+-//
+-// MessageId: HV_STATUS_INACTIVE
+-//
+-// MessageText:
+-//
+-// The physical connection being used for debuggging has not recorded any receive activity since the last operation.
+-//
++
++/* MessageId: HV_STATUS_INACTIVE */
++
++/* MessageText: */
++
++/* The physical connection being used for debuggging has not recorded any receive activity since the last operation. */
++
+ #define HV_STATUS_INACTIVE               ((HV_STATUS)0x001C)
+ 
+-//
+-// MessageId: HV_STATUS_NO_RESOURCES
+-//
+-// MessageText:
+-//
+-// There are not enough resources to complete the operation.
+-//
++
++/* MessageId: HV_STATUS_NO_RESOURCES */
++
++/* MessageText: */
++
++/* There are not enough resources to complete the operation. */
++
+ #define HV_STATUS_NO_RESOURCES           ((HV_STATUS)0x001D)
+ 
+-//
+-// MessageId: HV_STATUS_FEATURE_UNAVAILABLE
+-//
+-// MessageText:
+-//
+-// A hypervisor feature is not available to the user.
+-//
++
++/* MessageId: HV_STATUS_FEATURE_UNAVAILABLE */
++
++/* MessageText: */
++
++/* A hypervisor feature is not available to the user. */
++
+ #define HV_STATUS_FEATURE_UNAVAILABLE    ((HV_STATUS)0x001E)
+ 
+-// end_hvgdk
++/* end_hvgdk */
++
++
++/* MessageId: HV_STATUS_UNSUCCESSFUL */
++
++/* MessageText: */
++
++/* {Operation Failed} */
++/* The requested operation was unsuccessful. */
+ 
+-//
+-// MessageId: HV_STATUS_UNSUCCESSFUL
+-//
+-// MessageText:
+-//
+-// {Operation Failed}
+-// The requested operation was unsuccessful.
+-//
+ #define HV_STATUS_UNSUCCESSFUL           ((HV_STATUS)0x1001)
+ 
+-//
+-// MessageId: HV_STATUS_INSUFFICIENT_BUFFER
+-//
+-// MessageText:
+-//
+-// The specified buffer was too small to contain all of the requested data.
+-//
++
++/* MessageId: HV_STATUS_INSUFFICIENT_BUFFER */
++
++/* MessageText: */
++
++/* The specified buffer was too small to contain all of the requested data. */
++
+ #define HV_STATUS_INSUFFICIENT_BUFFER    ((HV_STATUS)0x1002)
+ 
+-//
+-// MessageId: HV_STATUS_GPA_NOT_PRESENT
+-//
+-// MessageText:
+-//
+-// The guest physical address is not currently associated with a system physical address.
+-//
++
++/* MessageId: HV_STATUS_GPA_NOT_PRESENT */
++
++/* MessageText: */
++
++/* The guest physical address is not currently associated with a system physical address. */
++
+ #define HV_STATUS_GPA_NOT_PRESENT        ((HV_STATUS)0x1003)
+ 
+-//
+-// MessageId: HV_STATUS_GUEST_PAGE_FAULT
+-//
+-// MessageText:
+-//
+-// The operation would have resulted in a page fault in the guest.
+-//
++
++/* MessageId: HV_STATUS_GUEST_PAGE_FAULT */
++
++/* MessageText: */
++
++/* The operation would have resulted in a page fault in the guest. */
++
+ #define HV_STATUS_GUEST_PAGE_FAULT       ((HV_STATUS)0x1004)
+ 
+-//
+-// MessageId: HV_STATUS_RUNDOWN_DISABLED
+-//
+-// MessageText:
+-//
+-// The operation cannot proceed as the rundown object was marked disabled.
+-//
++
++/* MessageId: HV_STATUS_RUNDOWN_DISABLED */
++
++/* MessageText: */
++
++/* The operation cannot proceed as the rundown object was marked disabled. */
++
+ #define HV_STATUS_RUNDOWN_DISABLED       ((HV_STATUS)0x1005)
+ 
+-//
+-// MessageId: HV_STATUS_KEY_ALREADY_EXISTS
+-//
+-// MessageText:
+-//
+-// The entry cannot be added as another entry with the same key already exists.
+-//
++
++/* MessageId: HV_STATUS_KEY_ALREADY_EXISTS */
++
++/* MessageText: */
++
++/* The entry cannot be added as another entry with the same key already exists. */
++
+ #define HV_STATUS_KEY_ALREADY_EXISTS     ((HV_STATUS)0x1006)
+ 
+-//
+-// MessageId: HV_STATUS_GPA_INTERCEPT
+-//
+-// MessageText:
+-//
+-// The operation resulted an intercept on a region of guest physical memory.
+-//
++
++/* MessageId: HV_STATUS_GPA_INTERCEPT */
++
++/* MessageText: */
++
++/* The operation resulted an intercept on a region of guest physical memory. */
++
+ #define HV_STATUS_GPA_INTERCEPT          ((HV_STATUS)0x1007)
+ 
+-//
+-// MessageId: HV_STATUS_GUEST_GENERAL_PROTECTION_FAULT
+-//
+-// MessageText:
+-//
+-// The operation would have resulted in a general protection fault in the guest.
+-//
++
++/* MessageId: HV_STATUS_GUEST_GENERAL_PROTECTION_FAULT */
++
++/* MessageText: */
++
++/* The operation would have resulted in a general protection fault in the guest. */
++
+ #define HV_STATUS_GUEST_GENERAL_PROTECTION_FAULT ((HV_STATUS)0x1008)
+ 
+-//
+-// MessageId: HV_STATUS_GUEST_STACK_FAULT
+-//
+-// MessageText:
+-//
+-// The operation would have resulted in a stack fault in the guest.
+-//
++
++/* MessageId: HV_STATUS_GUEST_STACK_FAULT */
++
++/* MessageText: */
++
++/* The operation would have resulted in a stack fault in the guest. */
++
+ #define HV_STATUS_GUEST_STACK_FAULT      ((HV_STATUS)0x1009)
+ 
+-//
+-// MessageId: HV_STATUS_GUEST_INVALID_OPCODE_FAULT
+-//
+-// MessageText:
+-//
+-// The operation would have resulted in an invalid opcode fault in the guest.
+-//
++
++/* MessageId: HV_STATUS_GUEST_INVALID_OPCODE_FAULT */
++
++/* MessageText: */
++
++/* The operation would have resulted in an invalid opcode fault in the guest. */
++
+ #define HV_STATUS_GUEST_INVALID_OPCODE_FAULT ((HV_STATUS)0x100A)
+ 
+-//
+-// MessageId: HV_STATUS_FINALIZE_INCOMPLETE
+-//
+-// MessageText:
+-//
+-// The partition is not completely finalized.
+-//
++
++/* MessageId: HV_STATUS_FINALIZE_INCOMPLETE */
++
++/* MessageText: */
++
++/* The partition is not completely finalized. */
++
+ #define HV_STATUS_FINALIZE_INCOMPLETE    ((HV_STATUS)0x100B)
+ 
+-//
+-// MessageId: HV_STATUS_GUEST_MACHINE_CHECK_ABORT
+-//
+-// MessageText:
+-//
+-// The operation would have resulted in an machine check abort in the guest.
+-//
++
++/* MessageId: HV_STATUS_GUEST_MACHINE_CHECK_ABORT */
++
++/* MessageText: */
++
++/* The operation would have resulted in an machine check abort in the guest. */
++
+ #define HV_STATUS_GUEST_MACHINE_CHECK_ABORT ((HV_STATUS)0x100C)
+ 
+-//
+-// MessageId: HV_STATUS_ILLEGAL_OVERLAY_ACCESS
+-//
+-// MessageText:
+-//
+-// An illegal access was attempted to an overlay page.
+-//
++
++/* MessageId: HV_STATUS_ILLEGAL_OVERLAY_ACCESS */
++
++/* MessageText: */
++
++/* An illegal access was attempted to an overlay page. */
++
+ #define HV_STATUS_ILLEGAL_OVERLAY_ACCESS ((HV_STATUS)0x100D)
+ 
+-//
+-// MessageId: HV_STATUS_INSUFFICIENT_SYSTEM_VA
+-//
+-// MessageText:
+-//
+-// There is not enough system VA space available to satisfy the request,
+-//
++
++/* MessageId: HV_STATUS_INSUFFICIENT_SYSTEM_VA */
++
++/* MessageText: */
++
++/* There is not enough system VA space available to satisfy the request, */
++
+ #define HV_STATUS_INSUFFICIENT_SYSTEM_VA ((HV_STATUS)0x100E)
+ 
+-//
+-// MessageId: HV_STATUS_VIRTUAL_ADDRESS_NOT_MAPPED
+-//
+-// MessageText:
+-//
+-// The passed virtual address was not mapped in the hypervisor address space.
+-//
++
++/* MessageId: HV_STATUS_VIRTUAL_ADDRESS_NOT_MAPPED */
++
++/* MessageText: */
++
++/* The passed virtual address was not mapped in the hypervisor address space. */
++
+ #define HV_STATUS_VIRTUAL_ADDRESS_NOT_MAPPED ((HV_STATUS)0x100F)
+ 
+-//
+-// MessageId: HV_STATUS_NOT_IMPLEMENTED
+-//
+-// MessageText:
+-//
+-// The requested operation is not implemented in this version of the hypervisor.
+-//
++
++/* MessageId: HV_STATUS_NOT_IMPLEMENTED */
++
++/* MessageText: */
++
++/* The requested operation is not implemented in this version of the hypervisor. */
++
+ #define HV_STATUS_NOT_IMPLEMENTED        ((HV_STATUS)0x1010)
+ 
+-//
+-// MessageId: HV_STATUS_VMX_INSTRUCTION_FAILED
+-//
+-// MessageText:
+-//
+-// The requested VMX instruction failed to complete succesfully.
+-//
++
++/* MessageId: HV_STATUS_VMX_INSTRUCTION_FAILED */
++
++/* MessageText: */
++
++/* The requested VMX instruction failed to complete succesfully. */
++
+ #define HV_STATUS_VMX_INSTRUCTION_FAILED ((HV_STATUS)0x1011)
+ 
+-//
+-// MessageId: HV_STATUS_VMX_INSTRUCTION_FAILED_WITH_STATUS
+-//
+-// MessageText:
+-//
+-// The requested VMX instruction failed to complete succesfully indicating status.
+-//
++
++/* MessageId: HV_STATUS_VMX_INSTRUCTION_FAILED_WITH_STATUS */
++
++/* MessageText: */
++
++/* The requested VMX instruction failed to complete succesfully indicating status. */
++
+ #define HV_STATUS_VMX_INSTRUCTION_FAILED_WITH_STATUS ((HV_STATUS)0x1012)
+ 
+-//
+-// MessageId: HV_STATUS_MSR_ACCESS_FAILED
+-//
+-// MessageText:
+-//
+-// The requested access to the model specific register failed.
+-//
++
++/* MessageId: HV_STATUS_MSR_ACCESS_FAILED */
++
++/* MessageText: */
++
++/* The requested access to the model specific register failed. */
++
+ #define HV_STATUS_MSR_ACCESS_FAILED      ((HV_STATUS)0x1013)
+ 
+-//
+-// MessageId: HV_STATUS_CR_ACCESS_FAILED
+-//
+-// MessageText:
+-//
+-// The requested access to the control register failed.
+-//
++
++/* MessageId: HV_STATUS_CR_ACCESS_FAILED */
++
++/* MessageText: */
++
++/* The requested access to the control register failed. */
++
+ #define HV_STATUS_CR_ACCESS_FAILED       ((HV_STATUS)0x1014)
+ 
+-//
+-// MessageId: HV_STATUS_TIMEOUT
+-//
+-// MessageText:
+-//
+-// The specified timeout expired before the operation completed.
+-//
++
++/* MessageId: HV_STATUS_TIMEOUT */
++
++/* MessageText: */
++
++/* The specified timeout expired before the operation completed. */
++
+ #define HV_STATUS_TIMEOUT                ((HV_STATUS)0x1016)
+ 
+-//
+-// MessageId: HV_STATUS_MSR_INTERCEPT
+-//
+-// MessageText:
+-//
+-// The requested access to the model specific register generated an intercept.
+-//
++
++/* MessageId: HV_STATUS_MSR_INTERCEPT */
++
++/* MessageText: */
++
++/* The requested access to the model specific register generated an intercept. */
++
+ #define HV_STATUS_MSR_INTERCEPT          ((HV_STATUS)0x1017)
+ 
+-//
+-// MessageId: HV_STATUS_CPUID_INTERCEPT
+-//
+-// MessageText:
+-//
+-// The CPUID instruction generated an intercept.
+-//
++
++/* MessageId: HV_STATUS_CPUID_INTERCEPT */
++
++/* MessageText: */
++
++/* The CPUID instruction generated an intercept. */
++
+ #define HV_STATUS_CPUID_INTERCEPT        ((HV_STATUS)0x1018)
+ 
+-//
+-// MessageId: HV_STATUS_REPEAT_INSTRUCTION
+-//
+-// MessageText:
+-//
+-// The current instruction should be repeated and the instruction pointer not advanced.
+-//
++
++/* MessageId: HV_STATUS_REPEAT_INSTRUCTION */
++
++/* MessageText: */
++
++/* The current instruction should be repeated and the instruction pointer not advanced. */
++
+ #define HV_STATUS_REPEAT_INSTRUCTION     ((HV_STATUS)0x1019)
+ 
+-//
+-// MessageId: HV_STATUS_PAGE_PROTECTION_VIOLATION
+-//
+-// MessageText:
+-//
+-// The current instruction should be repeated and the instruction pointer not advanced.
+-//
++
++/* MessageId: HV_STATUS_PAGE_PROTECTION_VIOLATION */
++
++/* MessageText: */
++
++/* The current instruction should be repeated and the instruction pointer not advanced. */
++
+ #define HV_STATUS_PAGE_PROTECTION_VIOLATION ((HV_STATUS)0x101A)
+ 
+-//
+-// MessageId: HV_STATUS_PAGE_TABLE_INVALID
+-//
+-// MessageText:
+-//
+-// The current instruction should be repeated and the instruction pointer not advanced.
+-//
++
++/* MessageId: HV_STATUS_PAGE_TABLE_INVALID */
++
++/* MessageText: */
++
++/* The current instruction should be repeated and the instruction pointer not advanced. */
++
+ #define HV_STATUS_PAGE_TABLE_INVALID     ((HV_STATUS)0x101B)
+ 
+-//
+-// MessageId: HV_STATUS_PAGE_NOT_PRESENT
+-//
+-// MessageText:
+-//
+-// The current instruction should be repeated and the instruction pointer not advanced.
+-//
++
++/* MessageId: HV_STATUS_PAGE_NOT_PRESENT */
++
++/* MessageText: */
++
++/* The current instruction should be repeated and the instruction pointer not advanced. */
++
+ #define HV_STATUS_PAGE_NOT_PRESENT       ((HV_STATUS)0x101C)
+ 
+-//
+-// MessageId: HV_STATUS_IO_INTERCEPT
+-//
+-// MessageText:
+-//
+-// The requested access to the I/O port generated an intercept.
+-//
++
++/* MessageId: HV_STATUS_IO_INTERCEPT */
++
++/* MessageText: */
++
++/* The requested access to the I/O port generated an intercept. */
++
+ #define HV_STATUS_IO_INTERCEPT           ((HV_STATUS)0x101D)
+ 
+-//
+-// MessageId: HV_STATUS_NOTHING_TO_DO
+-//
+-// MessageText:
+-//
+-// There is nothing to do.
+-//
++
++/* MessageId: HV_STATUS_NOTHING_TO_DO */
++
++/* MessageText: */
++
++/* There is nothing to do. */
++
+ #define HV_STATUS_NOTHING_TO_DO          ((HV_STATUS)0x101E)
+ 
+-//
+-// MessageId: HV_STATUS_THREAD_TERMINATING
+-//
+-// MessageText:
+-//
+-// The requested thread is terminating.
+-//
++
++/* MessageId: HV_STATUS_THREAD_TERMINATING */
++
++/* MessageText: */
++
++/* The requested thread is terminating. */
++
+ #define HV_STATUS_THREAD_TERMINATING     ((HV_STATUS)0x101F)
+ 
+-//
+-// MessageId: HV_STATUS_SECTION_ALREADY_CONSTRUCTED
+-//
+-// MessageText:
+-//
+-// The specified section was already constructed.
+-//
++
++/* MessageId: HV_STATUS_SECTION_ALREADY_CONSTRUCTED */
++
++/* MessageText: */
++
++/* The specified section was already constructed. */
++
+ #define HV_STATUS_SECTION_ALREADY_CONSTRUCTED ((HV_STATUS)0x1020)
+ 
+-//
+-// MessageId: HV_STATUS_SECTION_NOT_ALREADY_CONSTRUCTED
+-//
+-// MessageText:
+-//
+-// The specified section was not already constructed.
+-//
++
++/* MessageId: HV_STATUS_SECTION_NOT_ALREADY_CONSTRUCTED */
++
++/* MessageText: */
++
++/* The specified section was not already constructed. */
++
+ #define HV_STATUS_SECTION_NOT_ALREADY_CONSTRUCTED ((HV_STATUS)0x1021)
+ 
+-//
+-// MessageId: HV_STATUS_PAGE_ALREADY_COMMITTED
+-//
+-// MessageText:
+-//
+-// The specified virtual address was already backed by physical memory.
+-//
++
++/* MessageId: HV_STATUS_PAGE_ALREADY_COMMITTED */
++
++/* MessageText: */
++
++/* The specified virtual address was already backed by physical memory. */
++
+ #define HV_STATUS_PAGE_ALREADY_COMMITTED ((HV_STATUS)0x1022)
+ 
+-//
+-// MessageId: HV_STATUS_PAGE_NOT_ALREADY_COMMITTED
+-//
+-// MessageText:
+-//
+-// The specified virtual address was not already backed by physical memory.
+-//
++
++/* MessageId: HV_STATUS_PAGE_NOT_ALREADY_COMMITTED */
++
++/* MessageText: */
++
++/* The specified virtual address was not already backed by physical memory. */
++
+ #define HV_STATUS_PAGE_NOT_ALREADY_COMMITTED ((HV_STATUS)0x1023)
+ 
+-//
+-// MessageId: HV_STATUS_COMMITTED_PAGES_REMAIN
+-//
+-// MessageText:
+-//
+-// Committed pages remain in the section.
+-//
++
++/* MessageId: HV_STATUS_COMMITTED_PAGES_REMAIN */
++
++/* MessageText: */
++
++/* Committed pages remain in the section. */
++
+ #define HV_STATUS_COMMITTED_PAGES_REMAIN ((HV_STATUS)0x1024)
+ 
+-//
+-// MessageId: HV_STATUS_NO_REMAINING_COMMITTED_PAGES
+-//
+-// MessageText:
+-//
+-// No additional committed pages beyond the specified page exist in the section.
+-//
++
++/* MessageId: HV_STATUS_NO_REMAINING_COMMITTED_PAGES */
++
++/* MessageText: */
++
++/* No additional committed pages beyond the specified page exist in the section. */
++
+ #define HV_STATUS_NO_REMAINING_COMMITTED_PAGES ((HV_STATUS)0x1025)
+ 
+-//
+-// MessageId: HV_STATUS_INSUFFICIENT_COMPARTMENT_VA
+-//
+-// MessageText:
+-//
+-// The VA space of the compartment is exhausted.
+-//
++
++/* MessageId: HV_STATUS_INSUFFICIENT_COMPARTMENT_VA */
++
++/* MessageText: */
++
++/* The VA space of the compartment is exhausted. */
++
+ #define HV_STATUS_INSUFFICIENT_COMPARTMENT_VA ((HV_STATUS)0x1026)
+ 
+-//
+-// MessageId: HV_STATUS_DEREF_SPA_LIST_FULL
+-//
+-// MessageText:
+-//
+-// The SPA dereference list is full, and there are additional entries
+-// to be added to it.
+-//
++
++/* MessageId: HV_STATUS_DEREF_SPA_LIST_FULL */
++
++/* MessageText: */
++
++/* The SPA dereference list is full, and there are additional entries */
++/* to be added to it. */
++
+ #define HV_STATUS_DEREF_SPA_LIST_FULL ((HV_STATUS)0x1027)
+ 
+-//
+-// MessageId: HV_STATUS_GPA_OUT_OF_RANGE
+-//
+-// MessageText:
+-//
+-// The supplied GPA is out of range.
+-//
++
++/* MessageId: HV_STATUS_GPA_OUT_OF_RANGE */
++
++/* MessageText: */
++
++/* The supplied GPA is out of range. */
++
+ #define HV_STATUS_GPA_OUT_OF_RANGE ((HV_STATUS)0x1027)
+ 
+-//
+-// MessageId: HV_STATUS_NONVOLATILE_XMM_STALE
+-//
+-// MessageText:
+-//
+-// The XMM register that was being accessed is stale.
+-//
++
++/* MessageId: HV_STATUS_NONVOLATILE_XMM_STALE */
++
++/* MessageText: */
++
++/* The XMM register that was being accessed is stale. */
++
+ #define HV_STATUS_NONVOLATILE_XMM_STALE ((HV_STATUS)0x1028)
+ 
+-//
+-// MessageId: HV_STATUS_UNSUPPORTED_PROCESSOR
+-//
+-// MessageText:
+-//
+-// The hypervisor does not support the processors in this system.
+-//
++
++/* MessageId: HV_STATUS_UNSUPPORTED_PROCESSOR */
++
++/* MessageText: */
++
++/* The hypervisor does not support the processors in this system. */
++
+ #define HV_STATUS_UNSUPPORTED_PROCESSOR ((HV_STATUS)0x1029)
+ 
+-//
+-// MessageId: HV_STATUS_INSUFFICIENT_CROM_SPACE
+-//
+-// MessageText:
+-//
+-// Insufficient space existed for copying over the CROM contents.
+-//
++
++/* MessageId: HV_STATUS_INSUFFICIENT_CROM_SPACE */
++
++/* MessageText: */
++
++/* Insufficient space existed for copying over the CROM contents. */
++
+ #define HV_STATUS_INSUFFICIENT_CROM_SPACE ((HV_STATUS)0x2000)
+ 
+-//
+-// MessageId: HV_STATUS_BAD_CROM_FORMAT
+-//
+-// MessageText:
+-//
+-// The contents of the CROM failed validation attempts.
+-//
++
++/* MessageId: HV_STATUS_BAD_CROM_FORMAT */
++
++/* MessageText: */
++
++/* The contents of the CROM failed validation attempts. */
++
+ #define HV_STATUS_BAD_CROM_FORMAT        ((HV_STATUS)0x2001)
+ 
+-//
+-// MessageId: HV_STATUS_UNSUPPORTED_CROM_FORMAT
+-//
+-// MessageText:
+-//
+-// The contents of the CROM contain contents the parser doesn't support.
+-//
++
++/* MessageId: HV_STATUS_UNSUPPORTED_CROM_FORMAT */
++
++/* MessageText: */
++
++/* The contents of the CROM contain contents the parser doesn't support. */
++
+ #define HV_STATUS_UNSUPPORTED_CROM_FORMAT ((HV_STATUS)0x2002)
+ 
+-//
+-// MessageId: HV_STATUS_UNSUPPORTED_CONTROLLER
+-//
+-// MessageText:
+-//
+-// The register format of the OHCI controller specified for debugging is not supported.
+-//
++
++/* MessageId: HV_STATUS_UNSUPPORTED_CONTROLLER */
++
++/* MessageText: */
++
++/* The register format of the OHCI controller specified for debugging is not supported. */
++
+ #define HV_STATUS_UNSUPPORTED_CONTROLLER ((HV_STATUS)0x2003)
+ 
+-//
+-// MessageId: HV_STATUS_CROM_TOO_LARGE
+-//
+-// MessageText:
+-//
+-// The CROM contents were to large to copy over.
+-//
++
++/* MessageId: HV_STATUS_CROM_TOO_LARGE */
++
++/* MessageText: */
++
++/* The CROM contents were to large to copy over. */
++
+ #define HV_STATUS_CROM_TOO_LARGE         ((HV_STATUS)0x2004)
+ 
+-//
+-// MessageId: HV_STATUS_CONTROLLER_IN_USE
+-//
+-// MessageText:
+-//
+-// The OHCI controller specified for debugging cannot be used as it is already in use.
+-//
++
++/* MessageId: HV_STATUS_CONTROLLER_IN_USE */
++
++/* MessageText: */
++
++/* The OHCI controller specified for debugging cannot be used as it is already in use. */
++
+ #define HV_STATUS_CONTROLLER_IN_USE      ((HV_STATUS)0x2005)
+ 
+diff --git a/drivers/staging/hv/include/HvSynicApi.h b/drivers/staging/hv/include/HvSynicApi.h
+index 79084e510254..17e2187d5c07 100644
+--- a/drivers/staging/hv/include/HvSynicApi.h
++++ b/drivers/staging/hv/include/HvSynicApi.h
+@@ -23,24 +23,24 @@
+ 
+ #pragma once
+ 
+-//
+-// Define the virtual APIC registers
+-//
++
++/* Define the virtual APIC registers */
++
+ #define HV_X64_MSR_EOI                  (0x40000070)
+ #define HV_X64_MSR_ICR                  (0x40000071)
+ #define HV_X64_MSR_TPR                  (0x40000072)
+ #define HV_X64_MSR_APIC_ASSIST_PAGE     (0x40000073)
+ 
+-//
+-// Define version of the synthetic interrupt controller.
+-//
++
++/* Define version of the synthetic interrupt controller. */
++
+ 
+ #define HV_SYNIC_VERSION        (1)
+ 
+ 
+-//
+-// Define synthetic interrupt controller model specific registers.
+-//
++
++/* Define synthetic interrupt controller model specific registers. */
++
+ 
+ #define HV_X64_MSR_SCONTROL   (0x40000080)
+ #define HV_X64_MSR_SVERSION   (0x40000081)
+@@ -64,61 +64,61 @@
+ #define HV_X64_MSR_SINT14     (0x4000009E)
+ #define HV_X64_MSR_SINT15     (0x4000009F)
+ 
+-//
+-// Define the expected SynIC version.
+-//
++
++/* Define the expected SynIC version. */
++
+ #define HV_SYNIC_VERSION_1 (0x1)
+ 
+-//
+-// Define synthetic interrupt controller message constants.
+-//
++
++/* Define synthetic interrupt controller message constants. */
++
+ 
+ #define HV_MESSAGE_SIZE                 (256)
+ #define HV_MESSAGE_PAYLOAD_BYTE_COUNT   (240)
+ #define HV_MESSAGE_PAYLOAD_QWORD_COUNT  (30)
+ #define HV_ANY_VP                       (0xFFFFFFFF)
+ 
+-//
+-// Define synthetic interrupt controller flag constants.
+-//
++
++/* Define synthetic interrupt controller flag constants. */
++
+ 
+ #define HV_EVENT_FLAGS_COUNT        (256 * 8)
+ #define HV_EVENT_FLAGS_BYTE_COUNT   (256)
+ #define HV_EVENT_FLAGS_DWORD_COUNT  (256 / sizeof(u32))
+ 
+-//
+-// Define hypervisor message types.
+-//
++
++/* Define hypervisor message types. */
++
+ typedef enum _HV_MESSAGE_TYPE
+ {
+     HvMessageTypeNone = 0x00000000,
+ 
+-    //
+-    // Memory access messages.
+-    //
++
++    /* Memory access messages. */
++
+     HvMessageTypeUnmappedGpa = 0x80000000,
+     HvMessageTypeGpaIntercept = 0x80000001,
+ 
+-    //
+-    // Timer notification messages.
+-    //
++
++    /* Timer notification messages. */
++
+     HvMessageTimerExpired = 0x80000010,
+ 
+-    //
+-    // Error messages.
+-    //
++
++    /* Error messages. */
++
+     HvMessageTypeInvalidVpRegisterValue = 0x80000020,
+     HvMessageTypeUnrecoverableException = 0x80000021,
+     HvMessageTypeUnsupportedFeature = 0x80000022,
+ 
+-    //
+-    // Trace buffer complete messages.
+-    //
++
++    /* Trace buffer complete messages. */
++
+     HvMessageTypeEventLogBufferComplete = 0x80000040,
+ 
+-    //
+-    // Platform-specific processor intercept messages.
+-    //
++
++    /* Platform-specific processor intercept messages. */
++
+     HvMessageTypeX64IoPortIntercept = 0x80010000,
+     HvMessageTypeX64MsrIntercept = 0x80010001,
+     HvMessageTypeX64CpuidIntercept = 0x80010002,
+@@ -128,33 +128,33 @@ typedef enum _HV_MESSAGE_TYPE
+ 
+ } HV_MESSAGE_TYPE, *PHV_MESSAGE_TYPE;
+ 
+-//
+-// Define the number of synthetic interrupt sources.
+-//
++
++/* Define the number of synthetic interrupt sources. */
++
+ 
+ #define HV_SYNIC_SINT_COUNT (16)
+ #define HV_SYNIC_STIMER_COUNT (4)
+ 
+-//
+-// Define the synthetic interrupt source index type.
+-//
++
++/* Define the synthetic interrupt source index type. */
++
+ 
+ typedef u32 HV_SYNIC_SINT_INDEX, *PHV_SYNIC_SINT_INDEX;
+ 
+-//
+-// Define partition identifier type.
+-//
++
++/* Define partition identifier type. */
++
+ 
+ typedef u64 HV_PARTITION_ID, *PHV_PARTITION_ID;
+ 
+-//
+-// Define invalid partition identifier.
+-//
++
++/* Define invalid partition identifier. */
++
+ #define HV_PARTITION_ID_INVALID ((HV_PARTITION_ID) 0x0)
+ 
+-//
+-// Define connection identifier type.
+-//
++
++/* Define connection identifier type. */
++
+ 
+ typedef union _HV_CONNECTION_ID
+ {
+@@ -162,15 +162,15 @@ typedef union _HV_CONNECTION_ID
+ 
+     struct
+     {
+-        u32 Id:24;
+-        u32 Reserved:8;
++	u32 Id:24;
++	u32 Reserved:8;
+     } u;
+ 
+ } HV_CONNECTION_ID, *PHV_CONNECTION_ID;
+ 
+-//
+-// Define port identifier type.
+-//
++
++/* Define port identifier type. */
++
+ 
+ typedef union _HV_PORT_ID
+ {
+@@ -178,15 +178,15 @@ typedef union _HV_PORT_ID
+ 
+     struct
+     {
+-        u32 Id:24;
+-        u32 Reserved:8;
++	u32 Id:24;
++	u32 Reserved:8;
+     } u ;
+ 
+ } HV_PORT_ID, *PHV_PORT_ID;
+ 
+-//
+-// Define port type.
+-//
++
++/* Define port type. */
++
+ 
+ typedef enum _HV_PORT_TYPE
+ {
+@@ -195,9 +195,9 @@ typedef enum _HV_PORT_TYPE
+     HvPortTypeMonitor   = 3
+ } HV_PORT_TYPE, *PHV_PORT_TYPE;
+ 
+-//
+-// Define port information structure.
+-//
++
++/* Define port information structure. */
++
+ 
+ typedef struct _HV_PORT_INFO
+ {
+@@ -206,27 +206,27 @@ typedef struct _HV_PORT_INFO
+ 
+     union
+     {
+-        struct
+-        {
+-            HV_SYNIC_SINT_INDEX TargetSint;
+-            HV_VP_INDEX TargetVp;
+-            u64 RsvdZ;
+-        } MessagePortInfo;
+-
+-        struct
+-        {
+-            HV_SYNIC_SINT_INDEX TargetSint;
+-            HV_VP_INDEX TargetVp;
+-            u16 BaseFlagNumber;
+-            u16 FlagCount;
+-            u32 RsvdZ;
+-        } EventPortInfo;
+-
+-        struct
+-        {
+-            HV_GPA MonitorAddress;
+-            u64 RsvdZ;
+-        } MonitorPortInfo;
++	struct
++	{
++	    HV_SYNIC_SINT_INDEX TargetSint;
++	    HV_VP_INDEX TargetVp;
++	    u64 RsvdZ;
++	} MessagePortInfo;
++
++	struct
++	{
++	    HV_SYNIC_SINT_INDEX TargetSint;
++	    HV_VP_INDEX TargetVp;
++	    u16 BaseFlagNumber;
++	    u16 FlagCount;
++	    u32 RsvdZ;
++	} EventPortInfo;
++
++	struct
++	{
++	    HV_GPA MonitorAddress;
++	    u64 RsvdZ;
++	} MonitorPortInfo;
+     };
+ } HV_PORT_INFO, *PHV_PORT_INFO;
+ 
+@@ -239,43 +239,43 @@ typedef struct _HV_CONNECTION_INFO
+ 
+     union
+     {
+-        struct
+-        {
+-            u64 RsvdZ;
+-        } MessageConnectionInfo;
+-
+-        struct
+-        {
+-            u64 RsvdZ;
+-        } EventConnectionInfo;
+-
+-        struct
+-        {
+-            HV_GPA MonitorAddress;
+-        } MonitorConnectionInfo;
++	struct
++	{
++	    u64 RsvdZ;
++	} MessageConnectionInfo;
++
++	struct
++	{
++	    u64 RsvdZ;
++	} EventConnectionInfo;
++
++	struct
++	{
++	    HV_GPA MonitorAddress;
++	} MonitorConnectionInfo;
+     };
+ } HV_CONNECTION_INFO, *PHV_CONNECTION_INFO;
+ 
+ typedef const HV_CONNECTION_INFO *PCHV_CONNECTION_INFO;
+ 
+-//
+-// Define synthetic interrupt controller message flags.
+-//
++
++/* Define synthetic interrupt controller message flags. */
++
+ 
+ typedef union _HV_MESSAGE_FLAGS
+ {
+     u8 Asu8;
+     struct
+     {
+-        u8 MessagePending:1;
+-        u8 Reserved:7;
++	u8 MessagePending:1;
++	u8 Reserved:7;
+     };
+ } HV_MESSAGE_FLAGS, *PHV_MESSAGE_FLAGS;
+ 
+ 
+-//
+-// Define synthetic interrupt controller message header.
+-//
++
++/* Define synthetic interrupt controller message header. */
++
+ 
+ typedef struct _HV_MESSAGE_HEADER
+ {
+@@ -285,45 +285,45 @@ typedef struct _HV_MESSAGE_HEADER
+     u8               Reserved[2];
+     union
+     {
+-        HV_PARTITION_ID Sender;
+-        HV_PORT_ID      Port;
++	HV_PARTITION_ID Sender;
++	HV_PORT_ID      Port;
+     };
+ 
+ } HV_MESSAGE_HEADER, *PHV_MESSAGE_HEADER;
+ 
+-//
+-// Define timer message payload structure.
+-//
++
++/* Define timer message payload structure. */
++
+ typedef struct _HV_TIMER_MESSAGE_PAYLOAD
+ {
+     u32          TimerIndex;
+     u32          Reserved;
+-    HV_NANO100_TIME ExpirationTime;     // When the timer expired
+-    HV_NANO100_TIME DeliveryTime;       // When the message was delivered
++    HV_NANO100_TIME ExpirationTime;     /* When the timer expired */
++    HV_NANO100_TIME DeliveryTime;       /* When the message was delivered */
+ } HV_TIMER_MESSAGE_PAYLOAD, *PHV_TIMER_MESSAGE_PAYLOAD;
+ 
+-//
+-// Define synthetic interrupt controller message format.
+-//
++
++/* Define synthetic interrupt controller message format. */
++
+ 
+ typedef struct _HV_MESSAGE
+ {
+     HV_MESSAGE_HEADER Header;
+     union
+     {
+-        u64 Payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
++	u64 Payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
+     } u ;
+ } HV_MESSAGE, *PHV_MESSAGE;
+ 
+-//
+-// Define the number of message buffers associated with each port.
+-//
++
++/* Define the number of message buffers associated with each port. */
++
+ 
+ #define HV_PORT_MESSAGE_BUFFER_COUNT (16)
+ 
+-//
+-// Define the synthetic interrupt message page layout.
+-//
++
++/* Define the synthetic interrupt message page layout. */
++
+ 
+ typedef struct _HV_MESSAGE_PAGE
+ {
+@@ -331,9 +331,9 @@ typedef struct _HV_MESSAGE_PAGE
+ } HV_MESSAGE_PAGE, *PHV_MESSAGE_PAGE;
+ 
+ 
+-//
+-// Define the synthetic interrupt controller event flags format.
+-//
++
++/* Define the synthetic interrupt controller event flags format. */
++
+ 
+ typedef union _HV_SYNIC_EVENT_FLAGS
+ {
+@@ -342,9 +342,9 @@ typedef union _HV_SYNIC_EVENT_FLAGS
+ } HV_SYNIC_EVENT_FLAGS, *PHV_SYNIC_EVENT_FLAGS;
+ 
+ 
+-//
+-// Define the synthetic interrupt flags page layout.
+-//
++
++/* Define the synthetic interrupt flags page layout. */
++
+ 
+ typedef struct _HV_SYNIC_EVENT_FLAGS_PAGE
+ {
+@@ -352,69 +352,69 @@ typedef struct _HV_SYNIC_EVENT_FLAGS_PAGE
+ } HV_SYNIC_EVENT_FLAGS_PAGE, *PHV_SYNIC_EVENT_FLAGS_PAGE;
+ 
+ 
+-//
+-// Define SynIC control register.
+-//
++
++/* Define SynIC control register. */
++
+ typedef union _HV_SYNIC_SCONTROL
+ {
+     u64 AsUINT64;
+     struct
+     {
+-        u64 Enable:1;
+-        u64 Reserved:63;
++	u64 Enable:1;
++	u64 Reserved:63;
+     };
+ } HV_SYNIC_SCONTROL, *PHV_SYNIC_SCONTROL;
+ 
+-//
+-// Define synthetic interrupt source.
+-//
++
++/* Define synthetic interrupt source. */
++
+ 
+ typedef union _HV_SYNIC_SINT
+ {
+     u64 AsUINT64;
+     struct
+     {
+-        u64 Vector    :8;
+-        u64 Reserved1 :8;
+-        u64 Masked    :1;
+-        u64 AutoEoi   :1;
+-        u64 Reserved2 :46;
++	u64 Vector    :8;
++	u64 Reserved1 :8;
++	u64 Masked    :1;
++	u64 AutoEoi   :1;
++	u64 Reserved2 :46;
+     };
+ } HV_SYNIC_SINT, *PHV_SYNIC_SINT;
+ 
+-//
+-// Define the format of the SIMP register
+-//
++
++/* Define the format of the SIMP register */
++
+ 
+ typedef union _HV_SYNIC_SIMP
+ {
+     u64 AsUINT64;
+     struct
+     {
+-        u64 SimpEnabled : 1;
+-        u64 Preserved   : 11;
+-        u64 BaseSimpGpa : 52;
++	u64 SimpEnabled : 1;
++	u64 Preserved   : 11;
++	u64 BaseSimpGpa : 52;
+     };
+ } HV_SYNIC_SIMP, *PHV_SYNIC_SIMP;
+ 
+-//
+-// Define the format of the SIEFP register
+-//
++
++/* Define the format of the SIEFP register */
++
+ 
+ typedef union _HV_SYNIC_SIEFP
+ {
+     u64 AsUINT64;
+     struct
+     {
+-        u64 SiefpEnabled : 1;
+-        u64 Preserved   : 11;
+-        u64 BaseSiefpGpa : 52;
++	u64 SiefpEnabled : 1;
++	u64 Preserved   : 11;
++	u64 BaseSiefpGpa : 52;
+     };
+ } HV_SYNIC_SIEFP, *PHV_SYNIC_SIEFP;
+ 
+-//
+-// Definitions for the monitored notification facility
+-//
++
++/* Definitions for the monitored notification facility */
++
+ 
+ typedef union _HV_MONITOR_TRIGGER_GROUP
+ {
+@@ -422,8 +422,8 @@ typedef union _HV_MONITOR_TRIGGER_GROUP
+ 
+     struct
+     {
+-        u32 Pending;
+-        u32 Armed;
++	u32 Pending;
++	u32 Armed;
+     };
+ 
+ } HV_MONITOR_TRIGGER_GROUP, *PHV_MONITOR_TRIGGER_GROUP;
+@@ -441,32 +441,32 @@ typedef union _HV_MONITOR_TRIGGER_STATE
+ 
+     struct
+     {
+-        u32 GroupEnable : 4;
+-        u32 RsvdZ       : 28;
++	u32 GroupEnable : 4;
++	u32 RsvdZ       : 28;
+     };
+ 
+ } HV_MONITOR_TRIGGER_STATE, *PHV_MONITOR_TRIGGER_STATE;
+ 
+-//
+-// HV_MONITOR_PAGE Layout
+-// ------------------------------------------------------
+-// | 0   | TriggerState (4 bytes) | Rsvd1 (4 bytes)     |
+-// | 8   | TriggerGroup[0]                              |
+-// | 10  | TriggerGroup[1]                              |
+-// | 18  | TriggerGroup[2]                              |
+-// | 20  | TriggerGroup[3]                              |
+-// | 28  | Rsvd2[0]                                     |
+-// | 30  | Rsvd2[1]                                     |
+-// | 38  | Rsvd2[2]                                     |
+-// | 40  | NextCheckTime[0][0]    | NextCheckTime[0][1] |
+-// | ...                                                |
+-// | 240 | Latency[0][0..3]                             |
+-// | 340 | Rsvz3[0]                                     |
+-// | 440 | Parameter[0][0]                              |
+-// | 448 | Parameter[0][1]                              |
+-// | ...                                                |
+-// | 840 | Rsvd4[0]                                     |
+-// ------------------------------------------------------
++
++/* HV_MONITOR_PAGE Layout */
++/* ------------------------------------------------------ */
++/* | 0   | TriggerState (4 bytes) | Rsvd1 (4 bytes)     | */
++/* | 8   | TriggerGroup[0]                              | */
++/* | 10  | TriggerGroup[1]                              | */
++/* | 18  | TriggerGroup[2]                              | */
++/* | 20  | TriggerGroup[3]                              | */
++/* | 28  | Rsvd2[0]                                     | */
++/* | 30  | Rsvd2[1]                                     | */
++/* | 38  | Rsvd2[2]                                     | */
++/* | 40  | NextCheckTime[0][0]    | NextCheckTime[0][1] | */
++/* | ...                                                | */
++/* | 240 | Latency[0][0..3]                             | */
++/* | 340 | Rsvz3[0]                                     | */
++/* | 440 | Parameter[0][0]                              | */
++/* | 448 | Parameter[0][1]                              | */
++/* | ...                                                | */
++/* | 840 | Rsvd4[0]                                     | */
++/* ------------------------------------------------------ */
+ 
+ typedef struct _HV_MONITOR_PAGE
+ {
+diff --git a/drivers/staging/hv/include/HvVpApi.h b/drivers/staging/hv/include/HvVpApi.h
+index 910a9e5983ee..ce0784c335a8 100644
+--- a/drivers/staging/hv/include/HvVpApi.h
++++ b/drivers/staging/hv/include/HvVpApi.h
+@@ -23,16 +23,16 @@
+ 
+ 
+ #pragma once
+-//
+-// Virtual Processor Indices
+-//
++
++/* Virtual Processor Indices */
++
+ typedef u32 HV_VP_INDEX, *PHV_VP_INDEX;
+ 
+-//
+-// The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent
+-// is set by CPUID(HvCpuIdFunctionVersionAndFeatures).
+-// ==========================================================================
+-//
++
++/* The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent */
++/* is set by CPUID(HvCpuIdFunctionVersionAndFeatures). */
++/* ========================================================================== */
++
+ 
+ typedef enum _HV_CPUID_FUNCTION
+ {
+@@ -40,9 +40,9 @@ typedef enum _HV_CPUID_FUNCTION
+     HvCpuIdFunctionHvVendorAndMaxFunction       = 0x40000000,
+     HvCpuIdFunctionHvInterface                  = 0x40000001,
+ 
+-    //
+-    // The remaining functions depend on the value of HvCpuIdFunctionInterface
+-    //
++
++    /* The remaining functions depend on the value of HvCpuIdFunctionInterface */
++
+     HvCpuIdFunctionMsHvVersion                  = 0x40000002,
+     HvCpuIdFunctionMsHvFeatures                 = 0x40000003,
+     HvCpuIdFunctionMsHvEnlightenmentInformation = 0x40000004,
+diff --git a/drivers/staging/hv/include/List.h b/drivers/staging/hv/include/List.h
+index 581fe534013f..31c129696435 100644
+--- a/drivers/staging/hv/include/List.h
++++ b/drivers/staging/hv/include/List.h
+@@ -36,10 +36,10 @@
+ typedef DLIST_ENTRY LIST_ENTRY;
+ typedef DLIST_ENTRY *PLIST_ENTRY;
+ 
+-//typedef struct LIST_ENTRY {
+-//   struct LIST_ENTRY * volatile Flink;
+-//   struct LIST_ENTRY * volatile Blink;
+-//} LIST_ENTRY, *PLIST_ENTRY;
++/* typedef struct LIST_ENTRY { */
++/*   struct LIST_ENTRY * volatile Flink; */
++/*   struct LIST_ENTRY * volatile Blink; */
++/* } LIST_ENTRY, *PLIST_ENTRY; */
+ 
+ 
+ 
+diff --git a/drivers/staging/hv/include/NetVscApi.h b/drivers/staging/hv/include/NetVscApi.h
+index 626054bcda7d..fdd8ad99ac21 100644
+--- a/drivers/staging/hv/include/NetVscApi.h
++++ b/drivers/staging/hv/include/NetVscApi.h
+@@ -27,22 +27,22 @@
+ 
+ #include "VmbusApi.h"
+ 
+-//
+-// Defines
+-//
++
++/* Defines */
++
+ #define NETVSC_DEVICE_RING_BUFFER_SIZE			64*PAGE_SIZE
+ 
+ #define HW_MACADDR_LEN		6
+ 
+-//
+-// Fwd declaration
+-//
++
++/* Fwd declaration */
++
+ typedef struct _NETVSC_PACKET	*PNETVSC_PACKET;
+ 
+ 
+-//
+-// Data types
+-//
++
++/* Data types */
++
+ 
+ typedef int (*PFN_ON_OPEN)(DEVICE_OBJECT *Device);
+ typedef int (*PFN_ON_CLOSE)(DEVICE_OBJECT *Device);
+@@ -54,27 +54,33 @@ typedef void (*PFN_ON_SENDRECVCOMPLETION)(void * Context);
+ typedef int (*PFN_ON_RECVCALLBACK)(DEVICE_OBJECT *dev, PNETVSC_PACKET packet);
+ typedef void (*PFN_ON_LINKSTATUS_CHANGED)(DEVICE_OBJECT *dev, u32 Status);
+ 
+-// Represent the xfer page packet which contains 1 or more netvsc packet
++/* Represent the xfer page packet which contains 1 or more netvsc packet */
+ typedef struct _XFERPAGE_PACKET {
+ 	DLIST_ENTRY			ListEntry;
+ 
+-	// # of netvsc packets this xfer packet contains
++	/* # of netvsc packets this xfer packet contains */
+ 	u32				Count;
+ } XFERPAGE_PACKET;
+ 
+ 
+-// The number of pages which are enough to cover jumbo frame buffer.
++/* The number of pages which are enough to cover jumbo frame buffer. */
+ #define NETVSC_PACKET_MAXPAGE  4
+ 
+-// Represent netvsc packet which contains 1 RNDIS and 1 ethernet frame within the RNDIS
++/*
++ * Represent netvsc packet which contains 1 RNDIS and 1 ethernet frame
++ * within the RNDIS
++ */
+ typedef struct _NETVSC_PACKET {
+-	// Bookkeeping stuff
++	/* Bookkeeping stuff */
+ 	DLIST_ENTRY				ListEntry;
+ 
+ 	DEVICE_OBJECT			*Device;
+ 	bool					IsDataPacket;
+ 
+-	// Valid only for receives when we break a xfer page packet into multiple netvsc packets
++	/*
++	 * Valid only for receives when we break a xfer page packet
++	 * into multiple netvsc packets
++	 */
+ 	XFERPAGE_PACKET		*XferPagePacket;
+ 
+ 	union {
+@@ -90,40 +96,42 @@ typedef struct _NETVSC_PACKET {
+ 		} Send;
+ 	} Completion;
+ 
+-	// This points to the memory after PageBuffers
++	/* This points to the memory after PageBuffers */
+ 	void *					Extension;
+ 
+ 	u32					TotalDataBufferLength;
+-	// Points to the send/receive buffer where the ethernet frame is
++	/* Points to the send/receive buffer where the ethernet frame is */
+ 	u32					PageBufferCount;
+ 	PAGE_BUFFER				PageBuffers[NETVSC_PACKET_MAXPAGE];
+ 
+ } NETVSC_PACKET;
+ 
+ 
+-// Represents the net vsc driver
++/* Represents the net vsc driver */
+ typedef struct _NETVSC_DRIVER_OBJECT {
+-	DRIVER_OBJECT				Base; // Must be the first field
++	DRIVER_OBJECT				Base; /* Must be the first field */
+ 
+ 	u32						RingBufferSize;
+ 	u32						RequestExtSize;
+ 
+-	// Additional num  of page buffers to allocate
++	/* Additional num  of page buffers to allocate */
+ 	u32						AdditionalRequestPageBufferCount;
+ 
+-	// This is set by the caller to allow us to callback when we receive a packet
+-	// from the "wire"
++	/*
++	 * This is set by the caller to allow us to callback when we
++	 * receive a packet from the "wire"
++	 */
+ 	PFN_ON_RECVCALLBACK			OnReceiveCallback;
+ 
+ 	PFN_ON_LINKSTATUS_CHANGED	OnLinkStatusChanged;
+ 
+-	// Specific to this driver
++	/* Specific to this driver */
+ 	PFN_ON_OPEN					OnOpen;
+ 	PFN_ON_CLOSE				OnClose;
+ 	PFN_ON_SEND					OnSend;
+-	//PFN_ON_RECVCOMPLETION	OnReceiveCompletion;
++	/* PFN_ON_RECVCOMPLETION	OnReceiveCompletion; */
+ 
+-	//PFN_QUERY_LINKSTATUS		QueryLinkStatus;
++	/* PFN_QUERY_LINKSTATUS		QueryLinkStatus; */
+ 
+ 	void*						Context;
+ } NETVSC_DRIVER_OBJECT;
+@@ -131,15 +139,15 @@ typedef struct _NETVSC_DRIVER_OBJECT {
+ 
+ typedef struct _NETVSC_DEVICE_INFO {
+     unsigned char	MacAddr[6];
+-    bool	LinkState;	// 0 - link up, 1 - link down
++    bool	LinkState;	/* 0 - link up, 1 - link down */
+ } NETVSC_DEVICE_INFO;
+ 
+-//
+-// Interface
+-//
++
++/* Interface */
++
+ int
+ NetVscInitialize(
+ 	DRIVER_OBJECT* drv
+ 	);
+ 
+-#endif // _NETVSC_API_H_
++#endif /* _NETVSC_API_H_ */
+diff --git a/drivers/staging/hv/include/StorVscApi.h b/drivers/staging/hv/include/StorVscApi.h
+index f50fee7bafd6..785506b13647 100644
+--- a/drivers/staging/hv/include/StorVscApi.h
++++ b/drivers/staging/hv/include/StorVscApi.h
+@@ -27,33 +27,35 @@
+ 
+ #include "VmbusApi.h"
+ 
+-//
+-// Defines
+-//
++
++/* Defines */
++
+ 
+ #define STORVSC_RING_BUFFER_SIZE			10*PAGE_SIZE
+ #define BLKVSC_RING_BUFFER_SIZE				20*PAGE_SIZE
+ 
+ #define STORVSC_MAX_IO_REQUESTS				64
+ 
+-// In Hyper-V, each port/path/target maps to 1 scsi host adapter.
+-// In reality, the path/target is not used (ie always set to 0) so
+-// our scsi host adapter essentially has 1 bus with 1 target that contains
+-// up to 256 luns.
++/*
++ * In Hyper-V, each port/path/target maps to 1 scsi host adapter.  In
++ * reality, the path/target is not used (ie always set to 0) so our
++ * scsi host adapter essentially has 1 bus with 1 target that contains
++ * up to 256 luns.
++ */
+ 
+ #define STORVSC_MAX_LUNS_PER_TARGET			64
+ #define STORVSC_MAX_TARGETS					1
+ #define STORVSC_MAX_CHANNELS				1
+ 
+ 
+-// Fwd decl
+-//
+-//struct VMBUS_CHANNEL;
++/* Fwd decl */
++
++/* struct VMBUS_CHANNEL; */
+ typedef struct _STORVSC_REQUEST* PSTORVSC_REQUEST;
+ 
+-//
+-// Data types
+-//
++
++/* Data types */
++
+ typedef int (*PFN_ON_IO_REQUEST)(PDEVICE_OBJECT Device, PSTORVSC_REQUEST Request);
+ typedef void (*PFN_ON_IO_REQUEST_COMPLTN)(PSTORVSC_REQUEST Request);
+ 
+@@ -61,7 +63,7 @@ typedef int (*PFN_ON_HOST_RESET)(PDEVICE_OBJECT Device);
+ typedef void (*PFN_ON_HOST_RESCAN)(PDEVICE_OBJECT Device);
+ 
+ 
+-// Matches Windows-end
++/* Matches Windows-end */
+ typedef enum _STORVSC_REQUEST_TYPE{
+ 	WRITE_TYPE,
+ 	READ_TYPE,
+@@ -87,30 +89,30 @@ typedef struct _STORVSC_REQUEST {
+ 
+ 	PFN_ON_IO_REQUEST_COMPLTN	OnIOCompletion;
+ 
+-	// This points to the memory after DataBuffer
++	/* This points to the memory after DataBuffer */
+ 	void *					Extension;
+ 
+ 	MULTIPAGE_BUFFER		DataBuffer;
+ } STORVSC_REQUEST;
+ 
+ 
+-// Represents the block vsc driver
++/* Represents the block vsc driver */
+ typedef struct _STORVSC_DRIVER_OBJECT {
+-	DRIVER_OBJECT			Base; // Must be the first field
++	DRIVER_OBJECT			Base; /* Must be the first field */
+ 
+-	// Set by caller (in bytes)
++	/* Set by caller (in bytes) */
+ 	u32					RingBufferSize;
+ 
+-	// Allocate this much private extension for each I/O request
++	/* Allocate this much private extension for each I/O request */
+ 	u32					RequestExtSize;
+ 
+-	// Maximum # of requests in flight per channel/device
++	/* Maximum # of requests in flight per channel/device */
+ 	u32					MaxOutstandingRequestsPerChannel;
+ 
+-	// Set by the caller to allow us to re-enumerate the bus on the host
++	/* Set by the caller to allow us to re-enumerate the bus on the host */
+ 	PFN_ON_HOST_RESCAN		OnHostRescan;
+ 
+-	// Specific to this driver
++	/* Specific to this driver */
+ 	PFN_ON_IO_REQUEST		OnIORequest;
+ 	PFN_ON_HOST_RESET		OnHostReset;
+ 
+@@ -122,9 +124,9 @@ typedef struct _STORVSC_DEVICE_INFO {
+     unsigned char	TargetId;
+ } STORVSC_DEVICE_INFO;
+ 
+-//
+-// Interface
+-//
++
++/* Interface */
++
+ int
+ StorVscInitialize(
+ 	DRIVER_OBJECT	*Driver
+@@ -134,4 +136,4 @@ int
+ BlkVscInitialize(
+ 	DRIVER_OBJECT	*Driver
+ 	);
+-#endif // _STORVSC_API_H_
++#endif /* _STORVSC_API_H_ */
+diff --git a/drivers/staging/hv/include/VmbusApi.h b/drivers/staging/hv/include/VmbusApi.h
+index 40b8f1e43e02..b9862e54d5aa 100644
+--- a/drivers/staging/hv/include/VmbusApi.h
++++ b/drivers/staging/hv/include/VmbusApi.h
+@@ -27,57 +27,57 @@
+ 
+ #include "osd.h"
+ 
+-//
+-// Defines
+-//
++
++/* Defines */
++
+ 
+ #define MAX_PAGE_BUFFER_COUNT				16
+-#define MAX_MULTIPAGE_BUFFER_COUNT			32 // 128K
++#define MAX_MULTIPAGE_BUFFER_COUNT			32 /* 128K */
++
++
+ 
++/* Fwd declarations */
+ 
+-//
+-// Fwd declarations
+-//
+ typedef struct _DRIVER_OBJECT *PDRIVER_OBJECT;
+ typedef struct _DEVICE_OBJECT *PDEVICE_OBJECT;
+ 
+-//
+-// Data types
+-//
++
++/* Data types */
++
+ 
+ #pragma pack(push,1)
+ 
+-// Single-page buffer
++/* Single-page buffer */
+ typedef struct _PAGE_BUFFER {
+ 	u32	Length;
+ 	u32	Offset;
+ 	u64	Pfn;
+ } PAGE_BUFFER;
+ 
+-// Multiple-page buffer
++/* Multiple-page buffer */
+ typedef struct _MULTIPAGE_BUFFER {
+-	// Length and Offset determines the # of pfns in the array
++	/* Length and Offset determines the # of pfns in the array */
+ 	u32	Length;
+ 	u32	Offset;
+ 	u64	PfnArray[MAX_MULTIPAGE_BUFFER_COUNT];
+ }MULTIPAGE_BUFFER;
+ 
+-//0x18 includes the proprietary packet header
++/* 0x18 includes the proprietary packet header */
+ #define MAX_PAGE_BUFFER_PACKET			(0x18 + (sizeof(PAGE_BUFFER) * MAX_PAGE_BUFFER_COUNT))
+ #define MAX_MULTIPAGE_BUFFER_PACKET		(0x18 + sizeof(MULTIPAGE_BUFFER))
+ 
+ 
+ #pragma pack(pop)
+ 
+-// All drivers
++/* All drivers */
+ typedef int (*PFN_ON_DEVICEADD)(PDEVICE_OBJECT Device, void* AdditionalInfo);
+ typedef int (*PFN_ON_DEVICEREMOVE)(PDEVICE_OBJECT Device);
+ typedef char** (*PFN_ON_GETDEVICEIDS)(void);
+ typedef void (*PFN_ON_CLEANUP)(PDRIVER_OBJECT Driver);
+ 
+-// Vmbus extensions
+-//typedef int (*PFN_ON_MATCH)(PDEVICE_OBJECT dev, PDRIVER_OBJECT drv);
+-//typedef int (*PFN_ON_PROBE)(PDEVICE_OBJECT dev);
++/* Vmbus extensions */
++/* typedef int (*PFN_ON_MATCH)(PDEVICE_OBJECT dev, PDRIVER_OBJECT drv); */
++/* typedef int (*PFN_ON_PROBE)(PDEVICE_OBJECT dev); */
+ typedef int	(*PFN_ON_ISR)(PDRIVER_OBJECT drv);
+ typedef void (*PFN_ON_DPC)(PDRIVER_OBJECT drv);
+ typedef void (*PFN_GET_CHANNEL_OFFERS)(void);
+@@ -87,7 +87,7 @@ typedef void (*PFN_ON_CHILDDEVICE_DESTROY)(PDEVICE_OBJECT Device);
+ typedef int (*PFN_ON_CHILDDEVICE_ADD)(PDEVICE_OBJECT RootDevice, PDEVICE_OBJECT ChildDevice);
+ typedef void (*PFN_ON_CHILDDEVICE_REMOVE)(PDEVICE_OBJECT Device);
+ 
+-// Vmbus channel interface
++/* Vmbus channel interface */
+ typedef void (*VMBUS_CHANNEL_CALLBACK)(void * context);
+ 
+ typedef int	(*VMBUS_CHANNEL_OPEN)(
+@@ -148,8 +148,8 @@ typedef int	(*VMBUS_CHANNEL_RECV_PACKET_PAW)(
+ 
+ typedef int	(*VMBUS_CHANNEL_ESTABLISH_GPADL)(
+ 	PDEVICE_OBJECT		Device,
+-	void *				Buffer,	// from kmalloc()
+-	u32				BufferLen,		// page-size multiple
++	void *				Buffer,	/* from kmalloc() */
++	u32				BufferLen,		/* page-size multiple */
+ 	u32*				GpadlHandle
+ 	);
+ 
+@@ -203,44 +203,44 @@ typedef struct _VMBUS_CHANNEL_INTERFACE {
+ 
+ typedef void (*VMBUS_GET_CHANNEL_INTERFACE)(VMBUS_CHANNEL_INTERFACE *Interface);
+ 
+-// Base driver object
++/* Base driver object */
+ typedef struct _DRIVER_OBJECT {
+ 	const char*				name;
+-	GUID					deviceType; // the device type supported by this driver
++	GUID					deviceType; /* the device type supported by this driver */
+ 
+ 	PFN_ON_DEVICEADD		OnDeviceAdd;
+ 	PFN_ON_DEVICEREMOVE		OnDeviceRemove;
+-	PFN_ON_GETDEVICEIDS		OnGetDeviceIds; // device ids supported by this driver
++	PFN_ON_GETDEVICEIDS		OnGetDeviceIds; /* device ids supported by this driver */
+ 	PFN_ON_CLEANUP			OnCleanup;
+ 
+ 	VMBUS_CHANNEL_INTERFACE VmbusChannelInterface;
+ } DRIVER_OBJECT;
+ 
+ 
+-// Base device object
++/* Base device object */
+ typedef struct _DEVICE_OBJECT {
+-	DRIVER_OBJECT*		Driver;		// the driver for this device
++	DRIVER_OBJECT*		Driver;		/* the driver for this device */
+ 	char				name[64];
+-	GUID				deviceType; // the device type id of this device
+-	GUID				deviceInstance; // the device instance id of this device
++	GUID				deviceType; /* the device type id of this device */
++	GUID				deviceInstance; /* the device instance id of this device */
+ 	void*				context;
+-	void*				Extension;		// Device extension;
++	void*				Extension;		/* Device extension; */
+ } DEVICE_OBJECT;
+ 
+ 
+-// Vmbus driver object
++/* Vmbus driver object */
+ typedef struct _VMBUS_DRIVER_OBJECT {
+-	DRIVER_OBJECT		Base; // !! Must be the 1st field !!
++	DRIVER_OBJECT		Base; /* !! Must be the 1st field !! */
+ 
+-	// Set by the caller
++	/* Set by the caller */
+ 	PFN_ON_CHILDDEVICE_CREATE	OnChildDeviceCreate;
+ 	PFN_ON_CHILDDEVICE_DESTROY	OnChildDeviceDestroy;
+ 	PFN_ON_CHILDDEVICE_ADD		OnChildDeviceAdd;
+ 	PFN_ON_CHILDDEVICE_REMOVE	OnChildDeviceRemove;
+ 
+-	// Set by the callee
+-	//PFN_ON_MATCH		OnMatch;
+-	//PFN_ON_PROBE		OnProbe;
++	/* Set by the callee */
++	/* PFN_ON_MATCH		OnMatch; */
++	/* PFN_ON_PROBE		OnProbe; */
+ 	PFN_ON_ISR				OnIsr;
+ 	PFN_ON_DPC				OnMsgDpc;
+ 	PFN_ON_DPC				OnEventDpc;
+@@ -251,12 +251,12 @@ typedef struct _VMBUS_DRIVER_OBJECT {
+ } VMBUS_DRIVER_OBJECT;
+ 
+ 
+-//
+-// Interface
+-//
++
++/* Interface */
++
+ int
+ VmbusInitialize(
+ 	DRIVER_OBJECT* drv
+ 	);
+ 
+-#endif // _VMBUS_API_H_
++#endif /* _VMBUS_API_H_ */
+diff --git a/drivers/staging/hv/include/VmbusChannelInterface.h b/drivers/staging/hv/include/VmbusChannelInterface.h
+index ead74f28b54f..881c22d4c0e4 100644
+--- a/drivers/staging/hv/include/VmbusChannelInterface.h
++++ b/drivers/staging/hv/include/VmbusChannelInterface.h
+@@ -23,42 +23,42 @@
+ 
+ 
+ #pragma once
+-// allow nameless unions
+-//#pragma warning(disable : 4201)
++/* allow nameless unions */
++/* #pragma warning(disable : 4201) */
++
++
++/* A revision number of vmbus that is used for ensuring both ends on a */
++/* partition are using compatible versions. */
+ 
+-//
+-// A revision number of vmbus that is used for ensuring both ends on a
+-// partition are using compatible versions.
+-//
+ #define VMBUS_REVISION_NUMBER       13
+ 
+-//
+-// Make maximum size of pipe payload of 16K
+-//
+-#define MAX_PIPE_DATA_PAYLOAD 		(sizeof(BYTE) * 16384)
+ 
+-//
+-// Define PipeMode values.
+-//
++/* Make maximum size of pipe payload of 16K */
++
++#define MAX_PIPE_DATA_PAYLOAD		(sizeof(BYTE) * 16384)
++
++
++/* Define PipeMode values. */
++
+ #define VMBUS_PIPE_TYPE_BYTE                    0x00000000
+ #define VMBUS_PIPE_TYPE_MESSAGE                 0x00000004
+ 
+-//
+-// The size of the user defined data buffer for non-pipe offers.
+-//
++
++/* The size of the user defined data buffer for non-pipe offers. */
++
+ #define MAX_USER_DEFINED_BYTES                  120
+ 
+-//
+-// The size of the user defined data buffer for pipe offers.
+-//
++
++/* The size of the user defined data buffer for pipe offers. */
++
+ #define MAX_PIPE_USER_DEFINED_BYTES             116
+ 
+ 
+-//
+-// At the center of the Channel Management library is
+-// the Channel Offer. This struct contains the
+-// fundamental information about an offer.
+-//
++
++/* At the center of the Channel Management library is */
++/* the Channel Offer. This struct contains the */
++/* fundamental information about an offer. */
++
+ #pragma pack(push,1)
+ 
+ typedef struct
+@@ -68,30 +68,30 @@ typedef struct
+     GUID    InterfaceInstance;
+     u64  InterruptLatencyIn100nsUnits;
+     u32  InterfaceRevision;
+-    u32  ServerContextAreaSize;  // in bytes
++    u32  ServerContextAreaSize;  /* in bytes */
+     u16  ChannelFlags;
+-    u16  MmioMegabytes;          // in bytes * 1024 * 1024
++    u16  MmioMegabytes;          /* in bytes * 1024 * 1024 */
+ 
+     union
+     {
+-        //
+-        // Non-pipes: The user has MAX_USER_DEFINED_BYTES bytes.
+-        //
+-        struct
+-        {
+-            unsigned char   UserDefined[MAX_USER_DEFINED_BYTES];
+-        } Standard;
+-
+-        //
+-        // Pipes: The following sructure is an integrated pipe protocol, which
+-        //        is implemented on top of standard user-defined data. Pipe clients
+-        //        have MAX_PIPE_USER_DEFINED_BYTES left for their own use.
+-        //
+-        struct
+-        {
+-            u32  PipeMode;
+-            unsigned char   UserDefined[MAX_PIPE_USER_DEFINED_BYTES];
+-        } Pipe;
++
++	/* Non-pipes: The user has MAX_USER_DEFINED_BYTES bytes. */
++
++	struct
++	{
++	    unsigned char   UserDefined[MAX_USER_DEFINED_BYTES];
++	} Standard;
++
++
++	/* Pipes: The following sructure is an integrated pipe protocol, which */
++	/*        is implemented on top of standard user-defined data. Pipe clients */
++	/*        have MAX_PIPE_USER_DEFINED_BYTES left for their own use. */
++
++	struct
++	{
++	    u32  PipeMode;
++	    unsigned char   UserDefined[MAX_PIPE_USER_DEFINED_BYTES];
++	} Pipe;
+     } u;
+ 	u32	Padding;
+ } VMBUS_CHANNEL_OFFER, *PVMBUS_CHANNEL_OFFER;
+@@ -100,9 +100,9 @@ typedef struct
+ 
+ typedef u32 GPADL_HANDLE;
+ 
+-//
+-// Server Flags
+-//
++
++/* Server Flags */
++
+ 
+ #define VMBUS_CHANNEL_ENUMERATE_DEVICE_INTERFACE           1
+ #define VMBUS_CHANNEL_SERVER_SUPPORTS_TRANSFER_PAGES       2
+@@ -112,11 +112,10 @@ typedef u32 GPADL_HANDLE;
+ #define VMBUS_CHANNEL_PARENT_OFFER                     0x200
+ #define VMBUS_CHANNEL_REQUEST_MONITORED_NOTIFICATION   0x400
+ 
+-//
+-// TEMPTEMP -- move this next define to devioctl.h some day
+-//
++
++/* TEMPTEMP -- move this next define to devioctl.h some day */
++
+ 
+ #ifndef FILE_DEVICE_VMBUS
+ #define FILE_DEVICE_VMBUS   0x0000003E
+ #endif
+-
+diff --git a/drivers/staging/hv/include/VmbusPacketFormat.h b/drivers/staging/hv/include/VmbusPacketFormat.h
+index 9689f941e8dc..f6600a995519 100644
+--- a/drivers/staging/hv/include/VmbusPacketFormat.h
++++ b/drivers/staging/hv/include/VmbusPacketFormat.h
+@@ -24,33 +24,33 @@
+ 
+ #pragma once
+ 
+-//#ifndef PAGE_SIZE
+-//#if defined(_IA64_)
+-//#error This does not work for IA64
+-//#else
+-//#define PAGE_SIZE 0x1000
+-//#endif
+-//#endif
++/* #ifndef PAGE_SIZE */
++/* #if defined(_IA64_) */
++/* #error This does not work for IA64 */
++/* #else */
++/* #define PAGE_SIZE 0x1000 */
++/* #endif */
++/* #endif */
+ 
+-// allow nameless unions
+-//#pragma warning(disable : 4201)
++/* allow nameless unions */
++/* #pragma warning(disable : 4201) */
+ 
+ typedef struct
+ {
+     union
+     {
+-        struct
+-        {
+-            volatile u32  In;        // Offset in bytes from the ring base
+-            volatile u32  Out;       // Offset in bytes from the ring base
+-        };
+-        volatile long long InOut;
++	struct
++	{
++	    volatile u32  In;        /* Offset in bytes from the ring base */
++	    volatile u32  Out;       /* Offset in bytes from the ring base */
++	};
++	volatile long long InOut;
+     };
+ 
+-    //
+-    // If the receiving endpoint sets this to some non-zero value, the sending
+-    // endpoint should not send any interrupts.
+-    //
++
++    /* If the receiving endpoint sets this to some non-zero value, the sending */
++    /* endpoint should not send any interrupts. */
++
+ 
+     volatile u32 InterruptMask;
+ 
+@@ -60,18 +60,18 @@ typedef struct
+ {
+     union
+     {
+-        struct
+-        {
+-            VMRCB Control;
+-        };
++	struct
++	{
++	    VMRCB Control;
++	};
+ 
+-        u8 Reserved[PAGE_SIZE];
++	u8 Reserved[PAGE_SIZE];
+     };
+ 
+-    //
+-    // Beginning of the ring data.  Note: It must be guaranteed that
+-    // this data does not share a page with the control structure.
+-    //
++
++    /* Beginning of the ring data.  Note: It must be guaranteed that */
++    /* this data does not share a page with the control structure. */
++
+     u8 Data[1];
+ } VMRING, *PVMRING;
+ 
+@@ -159,10 +159,10 @@ typedef struct _VMADD_REMOVE_TRANSFER_PAGE_SET {
+ 
+ #pragma pack(pop)
+ 
+-//
+-// This structure defines a range in guest physical space that can be made
+-// to look virtually contiguous.
+-//
++
++/* This structure defines a range in guest physical space that can be made */
++/* to look virtually contiguous. */
++
+ 
+ typedef struct _GPA_RANGE {
+ 
+@@ -176,13 +176,13 @@ typedef struct _GPA_RANGE {
+ 
+ #pragma pack(push, 1)
+ 
+-//
+-// This is the format for an Establish Gpadl packet, which contains a handle
+-// by which this GPADL will be known and a set of GPA ranges associated with
+-// it.  This can be converted to a MDL by the guest OS.  If there are multiple
+-// GPA ranges, then the resulting MDL will be "chained," representing multiple
+-// VA ranges.
+-//
++
++/* This is the format for an Establish Gpadl packet, which contains a handle */
++/* by which this GPADL will be known and a set of GPA ranges associated with */
++/* it.  This can be converted to a MDL by the guest OS.  If there are multiple */
++/* GPA ranges, then the resulting MDL will be "chained," representing multiple */
++/* VA ranges. */
++
+ 
+ #ifdef __cplusplus
+ 
+@@ -203,10 +203,10 @@ typedef struct _VMESTABLISH_GPADL {
+ } VMESTABLISH_GPADL, *PVMESTABLISH_GPADL;
+ 
+ 
+-//
+-// This is the format for a Teardown Gpadl packet, which indicates that the
+-// GPADL handle in the Establish Gpadl packet will never be referenced again.
+-//
++
++/* This is the format for a Teardown Gpadl packet, which indicates that the */
++/* GPADL handle in the Establish Gpadl packet will never be referenced again. */
++
+ 
+ #ifdef __cplusplus
+ 
+@@ -221,14 +221,14 @@ typedef struct _VMTEARDOWN_GPADL {
+ #endif
+ 
+     u32  Gpadl;
+-    u32  Reserved; // for alignment to a 8-byte boundary
++    u32  Reserved; /* for alignment to a 8-byte boundary */
+ } VMTEARDOWN_GPADL, *PVMTEARDOWN_GPADL;
+ 
+ 
+-//
+-// This is the format for a GPA-Direct packet, which contains a set of GPA
+-// ranges, in addition to commands and/or data.
+-//
++
++/* This is the format for a GPA-Direct packet, which contains a set of GPA */
++/* ranges, in addition to commands and/or data. */
++
+ 
+ #ifdef __cplusplus
+ 
+@@ -250,9 +250,9 @@ typedef struct _VMDATA_GPA_DIRECT {
+ 
+ 
+ 
+-//
+-// This is the format for a Additional Data Packet.
+-//
++
++/* This is the format for a Additional Data Packet. */
++
+ 
+ #ifdef __cplusplus
+ 
+@@ -318,5 +318,3 @@ typedef enum {
+ } VMBUS_PACKET_TYPE, *PVMBUS_PACKET_TYPE;
+ 
+ #define VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED    1
+-
+-
+diff --git a/drivers/staging/hv/include/logging.h b/drivers/staging/hv/include/logging.h
+index f77c5172eb2e..8609269ca195 100644
+--- a/drivers/staging/hv/include/logging.h
++++ b/drivers/staging/hv/include/logging.h
+@@ -25,8 +25,8 @@
+ #ifndef _LOGGING_H_
+ #define _LOGGING_H_
+ 
+-//#include 
+-//#include 
++/* #include  */
++/* #include  */
+ 
+ #include "osd.h"
+ 
+@@ -52,7 +52,7 @@
+ 							INPUTVSC_DRV|\
+ 							BLKVSC_DRV)
+ 
+-// Logging Level
++/* Logging Level */
+ #define ERROR_LVL				3
+ #define WARNING_LVL				4
+ #define INFO_LVL				6
+@@ -117,4 +117,4 @@ extern unsigned int vmbus_loglevel;
+ #define DPRINT_EXIT(mod)
+ #endif
+ 
+-#endif //_LOGGING_H_
++#endif /* _LOGGING_H_ */
+diff --git a/drivers/staging/hv/include/nvspprotocol.h b/drivers/staging/hv/include/nvspprotocol.h
+index 702f904ee8d3..2ee9dbf0899a 100644
+--- a/drivers/staging/hv/include/nvspprotocol.h
++++ b/drivers/staging/hv/include/nvspprotocol.h
+@@ -36,17 +36,17 @@ typedef enum _NVSP_MESSAGE_TYPE
+ {
+     NvspMessageTypeNone = 0,
+ 
+-    //
+-    // Init Messages
+-    //
++
++    /* Init Messages */
++
+     NvspMessageTypeInit                         = 1,
+     NvspMessageTypeInitComplete                 = 2,
+ 
+     NvspVersionMessageStart                     = 100,
+ 
+-    //
+-    // Version 1 Messages
+-    //
++
++    /* Version 1 Messages */
++
+     NvspMessage1TypeSendNdisVersion             = NvspVersionMessageStart,
+ 
+     NvspMessage1TypeSendReceiveBuffer,
+@@ -60,10 +60,10 @@ typedef enum _NVSP_MESSAGE_TYPE
+     NvspMessage1TypeSendRNDISPacket,
+     NvspMessage1TypeSendRNDISPacketComplete,
+ 
+-    //
+-    // This should be set to the number of messages for the version
+-    // with the maximum number of messages.
+-    //
++
++    /* This should be set to the number of messages for the version */
++    /* with the maximum number of messages. */
++
+     NvspNumMessagePerVersion                    = 9,
+ 
+ } NVSP_MESSAGE_TYPE, *PNVSP_MESSAGE_TYPE;
+@@ -87,27 +87,27 @@ typedef struct _NVSP_MESSAGE_HEADER
+     u32                                  MessageType;
+ } NVSP_MESSAGE_HEADER, *PNVSP_MESSAGE_HEADER;
+ 
+-//
+-// Init Messages
+-//
+ 
+-//
+-// This message is used by the VSC to initialize the channel
+-// after the channels has been opened. This message should
+-// never include anything other then versioning (i.e. this
+-// message will be the same for ever).
+-//
++/* Init Messages */
++
++
++
++/* This message is used by the VSC to initialize the channel */
++/* after the channels has been opened. This message should */
++/* never include anything other then versioning (i.e. this */
++/* message will be the same for ever). */
++
+ typedef struct _NVSP_MESSAGE_INIT
+ {
+     u32                                  MinProtocolVersion;
+     u32                                  MaxProtocolVersion;
+ } NVSP_MESSAGE_INIT, *PNVSP_MESSAGE_INIT;
+ 
+-//
+-// This message is used by the VSP to complete the initialization
+-// of the channel. This message should never include anything other
+-// then versioning (i.e. this message will be the same for ever).
+-//
++
++/* This message is used by the VSP to complete the initialization */
++/* of the channel. This message should never include anything other */
++/* then versioning (i.e. this message will be the same for ever). */
++
+ typedef struct _NVSP_MESSAGE_INIT_COMPLETE
+ {
+     u32                                  NegotiatedProtocolVersion;
+@@ -121,26 +121,26 @@ typedef union _NVSP_MESSAGE_INIT_UBER
+     NVSP_MESSAGE_INIT_COMPLETE              InitComplete;
+ } NVSP_MESSAGE_INIT_UBER;
+ 
+-//
+-// Version 1 Messages
+-//
+ 
+-//
+-// This message is used by the VSC to send the NDIS version
+-// to the VSP. The VSP can use this information when handling
+-// OIDs sent by the VSC.
+-//
++/* Version 1 Messages */
++
++
++
++/* This message is used by the VSC to send the NDIS version */
++/* to the VSP. The VSP can use this information when handling */
++/* OIDs sent by the VSC. */
++
+ typedef struct _NVSP_1_MESSAGE_SEND_NDIS_VERSION
+ {
+     u32                                  NdisMajorVersion;
+     u32                                  NdisMinorVersion;
+ } NVSP_1_MESSAGE_SEND_NDIS_VERSION, *PNVSP_1_MESSAGE_SEND_NDIS_VERSION;
+ 
+-//
+-// This message is used by the VSC to send a receive buffer
+-// to the VSP. The VSP can then use the receive buffer to
+-// send data to the VSC.
+-//
++
++/* This message is used by the VSC to send a receive buffer */
++/* to the VSP. The VSP can then use the receive buffer to */
++/* send data to the VSC. */
++
+ typedef struct _NVSP_1_MESSAGE_SEND_RECEIVE_BUFFER
+ {
+     GPADL_HANDLE                            GpadlHandle;
+@@ -155,117 +155,117 @@ typedef struct _NVSP_1_RECEIVE_BUFFER_SECTION
+     u32                                  EndOffset;
+ } NVSP_1_RECEIVE_BUFFER_SECTION, *PNVSP_1_RECEIVE_BUFFER_SECTION;
+ 
+-//
+-// This message is used by the VSP to acknowledge a receive
+-// buffer send by the VSC. This message must be sent by the
+-// VSP before the VSP uses the receive buffer.
+-//
++
++/* This message is used by the VSP to acknowledge a receive */
++/* buffer send by the VSC. This message must be sent by the */
++/* VSP before the VSP uses the receive buffer. */
++
+ typedef struct _NVSP_1_MESSAGE_SEND_RECEIVE_BUFFER_COMPLETE
+ {
+     u32                                  Status;
+     u32                                  NumSections;
+ 
+-    //
+-    // The receive buffer is split into two parts, a large
+-    // suballocation section and a small suballocation
+-    // section. These sections are then suballocated by a
+-    // certain size.
+-    //
+-    // For example, the following break up of the receive
+-    // buffer has 6 large suballocations and 10 small
+-    // suballocations.
+-    //
+-    // |            Large Section          |  |   Small Section   |
+-    // ------------------------------------------------------------
+-    // |     |     |     |     |     |     |  | | | | | | | | | | |
+-    // |                                      |
+-    // LargeOffset                            SmallOffset
+-    //
++
++    /* The receive buffer is split into two parts, a large */
++    /* suballocation section and a small suballocation */
++    /* section. These sections are then suballocated by a */
++    /* certain size. */
++
++    /* For example, the following break up of the receive */
++    /* buffer has 6 large suballocations and 10 small */
++    /* suballocations. */
++
++    /* |            Large Section          |  |   Small Section   | */
++    /* ------------------------------------------------------------ */
++    /* |     |     |     |     |     |     |  | | | | | | | | | | | */
++    /* |                                      | */
++    /* LargeOffset                            SmallOffset */
++
+     NVSP_1_RECEIVE_BUFFER_SECTION           Sections[1];
+ 
+ } NVSP_1_MESSAGE_SEND_RECEIVE_BUFFER_COMPLETE, *PNVSP_1_MESSAGE_SEND_RECEIVE_BUFFER_COMPLETE;
+ 
+-//
+-// This message is sent by the VSC to revoke the receive buffer.
+-// After the VSP completes this transaction, the vsp should never
+-// use the receive buffer again.
+-//
++
++/* This message is sent by the VSC to revoke the receive buffer. */
++/* After the VSP completes this transaction, the vsp should never */
++/* use the receive buffer again. */
++
+ typedef struct _NVSP_1_MESSAGE_REVOKE_RECEIVE_BUFFER
+ {
+     u16                                  Id;
+ } NVSP_1_MESSAGE_REVOKE_RECEIVE_BUFFER, *PNVSP_1_MESSAGE_REVOKE_RECEIVE_BUFFER;
+ 
+-//
+-// This message is used by the VSC to send a send buffer
+-// to the VSP. The VSC can then use the send buffer to
+-// send data to the VSP.
+-//
++
++/* This message is used by the VSC to send a send buffer */
++/* to the VSP. The VSC can then use the send buffer to */
++/* send data to the VSP. */
++
+ typedef struct _NVSP_1_MESSAGE_SEND_SEND_BUFFER
+ {
+     GPADL_HANDLE                            GpadlHandle;
+     u16                                  Id;
+ } NVSP_1_MESSAGE_SEND_SEND_BUFFER, *PNVSP_1_MESSAGE_SEND_SEND_BUFFER;
+ 
+-//
+-// This message is used by the VSP to acknowledge a send
+-// buffer sent by the VSC. This message must be sent by the
+-// VSP before the VSP uses the sent buffer.
+-//
++
++/* This message is used by the VSP to acknowledge a send */
++/* buffer sent by the VSC. This message must be sent by the */
++/* VSP before the VSP uses the sent buffer. */
++
+ typedef struct _NVSP_1_MESSAGE_SEND_SEND_BUFFER_COMPLETE
+ {
+     u32                                  Status;
+ 
+-    //
+-    // The VSC gets to choose the size of the send buffer and
+-    // the VSP gets to choose the sections size of the buffer.
+-    // This was done to enable dynamic reconfigurations when
+-    // the cost of GPA-direct buffers decreases.
+-    //
++
++    /* The VSC gets to choose the size of the send buffer and */
++    /* the VSP gets to choose the sections size of the buffer. */
++    /* This was done to enable dynamic reconfigurations when */
++    /* the cost of GPA-direct buffers decreases. */
++
+     u32                                  SectionSize;
+ } NVSP_1_MESSAGE_SEND_SEND_BUFFER_COMPLETE, *PNVSP_1_MESSAGE_SEND_SEND_BUFFER_COMPLETE;
+ 
+-//
+-// This message is sent by the VSC to revoke the send buffer.
+-// After the VSP completes this transaction, the vsp should never
+-// use the send buffer again.
+-//
++
++/* This message is sent by the VSC to revoke the send buffer. */
++/* After the VSP completes this transaction, the vsp should never */
++/* use the send buffer again. */
++
+ typedef struct _NVSP_1_MESSAGE_REVOKE_SEND_BUFFER
+ {
+     u16                                  Id;
+ } NVSP_1_MESSAGE_REVOKE_SEND_BUFFER, *PNVSP_1_MESSAGE_REVOKE_SEND_BUFFER;
+ 
+-//
+-// This message is used by both the VSP and the VSC to send
+-// a RNDIS message to the opposite channel endpoint.
+-//
++
++/* This message is used by both the VSP and the VSC to send */
++/* a RNDIS message to the opposite channel endpoint. */
++
+ typedef struct _NVSP_1_MESSAGE_SEND_RNDIS_PACKET
+ {
+-    //
+-    // This field is specified by RNIDS. They assume there's
+-    // two different channels of communication. However,
+-    // the Network VSP only has one. Therefore, the channel
+-    // travels with the RNDIS packet.
+-    //
++
++    /* This field is specified by RNIDS. They assume there's */
++    /* two different channels of communication. However, */
++    /* the Network VSP only has one. Therefore, the channel */
++    /* travels with the RNDIS packet. */
++
+     u32                                  ChannelType;
+ 
+-    //
+-    // This field is used to send part or all of the data
+-    // through a send buffer. This values specifies an
+-    // index into the send buffer. If the index is
+-    // 0xFFFFFFFF, then the send buffer is not being used
+-    // and all of the data was sent through other VMBus
+-    // mechanisms.
+-    //
++
++    /* This field is used to send part or all of the data */
++    /* through a send buffer. This values specifies an */
++    /* index into the send buffer. If the index is */
++    /* 0xFFFFFFFF, then the send buffer is not being used */
++    /* and all of the data was sent through other VMBus */
++    /* mechanisms. */
++
+     u32                                  SendBufferSectionIndex;
+     u32                                  SendBufferSectionSize;
+ } NVSP_1_MESSAGE_SEND_RNDIS_PACKET, *PNVSP_1_MESSAGE_SEND_RNDIS_PACKET;
+ 
+-//
+-// This message is used by both the VSP and the VSC to complete
+-// a RNDIS message to the opposite channel endpoint. At this
+-// point, the initiator of this message cannot use any resources
+-// associated with the original RNDIS packet.
+-//
++
++/* This message is used by both the VSP and the VSC to complete */
++/* a RNDIS message to the opposite channel endpoint. At this */
++/* point, the initiator of this message cannot use any resources */
++/* associated with the original RNDIS packet. */
++
+ typedef struct _NVSP_1_MESSAGE_SEND_RNDIS_PACKET_COMPLETE
+ {
+     u32                                  Status;
+@@ -294,9 +294,9 @@ typedef union _NVSP_ALL_MESSAGES
+ 
+ } NVSP_ALL_MESSAGES;
+ 
+-//
+-// ALL Messages
+-//
++
++/* ALL Messages */
++
+ typedef struct _NVSP_MESSAGE
+ {
+     NVSP_MESSAGE_HEADER                     Header;
+diff --git a/drivers/staging/hv/include/osd.h b/drivers/staging/hv/include/osd.h
+index 3878a2fe77b7..faae7cc5ec0d 100644
+--- a/drivers/staging/hv/include/osd.h
++++ b/drivers/staging/hv/include/osd.h
+@@ -25,9 +25,9 @@
+ #ifndef _OSD_H_
+ #define _OSD_H_
+ 
+-//
+-// Defines
+-//
++
++/* Defines */
++
+ 
+ 
+ #define ALIGN_UP(value, align)			( ((value) & (align-1))? ( ((value) + (align-1)) & ~(align-1) ): (value) )
+@@ -42,10 +42,10 @@ typedef struct _DLIST_ENTRY {
+    struct _DLIST_ENTRY *Blink;
+ } DLIST_ENTRY;
+ 
+-//
+-// Other types
+-//
+-//typedef unsigned char		GUID[16];
++
++/* Other types */
++
++/* typedef unsigned char		GUID[16]; */
+ typedef void*				HANDLE;
+ 
+ typedef struct {
+@@ -95,9 +95,9 @@ static inline void do_cpuid(unsigned int op, unsigned int *eax, unsigned int *eb
+ 	__asm__ __volatile__("cpuid" : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) : "0" (op), "c" (ecx));
+ }
+ 
+-//
+-// Osd routines
+-//
++
++/* Osd routines */
++
+ extern void BitSet(unsigned int* addr, int value);
+ extern void BitClear(unsigned int* addr, int value);
+ extern int BitTest(unsigned int* addr, int value);
+@@ -127,7 +127,7 @@ extern void WaitEventClose(HANDLE hWait);
+ extern void WaitEventSet(HANDLE hWait);
+ extern int	WaitEventWait(HANDLE hWait);
+ 
+-// If >0, hWait got signaled. If ==0, timeout. If < 0, error
++/* If >0, hWait got signaled. If ==0, timeout. If < 0, error */
+ extern int	WaitEventWaitEx(HANDLE hWait, u32 TimeoutInMs);
+ 
+ 
+@@ -149,4 +149,4 @@ extern int WorkQueueQueueWorkItem(HANDLE hWorkQueue, PFN_WORKITEM_CALLBACK workI
+ 
+ extern void QueueWorkItem(PFN_WORKITEM_CALLBACK workItem, void* context);
+ 
+-#endif // _OSD_H_
++#endif /* _OSD_H_ */
+diff --git a/drivers/staging/hv/include/rndis.h b/drivers/staging/hv/include/rndis.h
+index baabd0ad8ec6..58fd4eb4f1f7 100644
+--- a/drivers/staging/hv/include/rndis.h
++++ b/drivers/staging/hv/include/rndis.h
+@@ -25,9 +25,9 @@
+ #ifndef _RNDIS_H_
+ #define _RNDIS_H_
+ 
+-//
+-//  Basic types
+-//
++
++/*  Basic types */
++
+ typedef u32                                  RNDIS_REQUEST_ID;
+ typedef u32                                  RNDIS_HANDLE;
+ typedef u32                                  RNDIS_STATUS;
+@@ -44,9 +44,9 @@ typedef u32                                  *PRNDIS_CLASS_ID;
+ typedef u32                                  *PRNDIS_MEDIUM;
+ typedef u32                                  RNDIS_AF;
+ 
+-//
+-//  Status codes
+-//
++
++/*  Status codes */
++
+ 
+ #ifndef STATUS_SUCCESS
+ #define STATUS_SUCCESS                          (0x00000000L)
+@@ -150,13 +150,13 @@ typedef u32                                  RNDIS_AF;
+ #define RNDIS_STATUS_TOKEN_RING_OPEN_ERROR      ((RNDIS_STATUS)0xC0011000L)
+ 
+ 
+-//
+-// Object Identifiers used by NdisRequest Query/Set Information
+-//
+ 
+-//
+-// General Objects
+-//
++/* Object Identifiers used by NdisRequest Query/Set Information */
++
++
++
++/* General Objects */
++
+ 
+ #define RNDIS_OID_GEN_SUPPORTED_LIST                    0x00010101
+ #define RNDIS_OID_GEN_HARDWARE_STATUS                   0x00010102
+@@ -210,10 +210,10 @@ typedef u32                                  RNDIS_AF;
+ #define RNDIS_OID_GEN_GET_TIME_CAPS                     0x0002020F
+ #define RNDIS_OID_GEN_GET_NETCARD_TIME                  0x00020210
+ 
+-//
+-// These are connection-oriented general OIDs.
+-// These replace the above OIDs for connection-oriented media.
+-//
++
++/* These are connection-oriented general OIDs. */
++/* These replace the above OIDs for connection-oriented media. */
++
+ #define RNDIS_OID_GEN_CO_SUPPORTED_LIST                 0x00010101
+ #define RNDIS_OID_GEN_CO_HARDWARE_STATUS                0x00010102
+ #define RNDIS_OID_GEN_CO_MEDIA_SUPPORTED                0x00010103
+@@ -231,9 +231,9 @@ typedef u32                                  RNDIS_AF;
+ #define RNDIS_OID_GEN_CO_GET_TIME_CAPS                  0x00010201
+ #define RNDIS_OID_GEN_CO_GET_NETCARD_TIME               0x00010202
+ 
+-//
+-// These are connection-oriented statistics OIDs.
+-//
++
++/* These are connection-oriented statistics OIDs. */
++
+ #define RNDIS_OID_GEN_CO_XMIT_PDUS_OK                   0x00020101
+ #define RNDIS_OID_GEN_CO_RCV_PDUS_OK                    0x00020102
+ #define RNDIS_OID_GEN_CO_XMIT_PDUS_ERROR                0x00020103
+@@ -248,9 +248,9 @@ typedef u32                                  RNDIS_AF;
+ #define RNDIS_OID_GEN_CO_BYTES_XMIT_OUTSTANDING         0x00020205
+ #define RNDIS_OID_GEN_CO_NETCARD_LOAD                   0x00020206
+ 
+-//
+-// These are objects for Connection-oriented media call-managers.
+-//
++
++/* These are objects for Connection-oriented media call-managers. */
++
+ #define RNDIS_OID_CO_ADD_PVC                            0xFF000001
+ #define RNDIS_OID_CO_DELETE_PVC                         0xFF000002
+ #define RNDIS_OID_CO_GET_CALL_INFORMATION               0xFF000003
+@@ -262,9 +262,9 @@ typedef u32                                  RNDIS_AF;
+ #define RNDIS_OID_CO_SIGNALING_DISABLED                 0xFF000009
+ 
+ 
+-//
+-// 802.3 Objects (Ethernet)
+-//
++
++/* 802.3 Objects (Ethernet) */
++
+ 
+ #define RNDIS_OID_802_3_PERMANENT_ADDRESS               0x01010101
+ #define RNDIS_OID_802_3_CURRENT_ADDRESS                 0x01010102
+@@ -272,8 +272,8 @@ typedef u32                                  RNDIS_AF;
+ #define RNDIS_OID_802_3_MAXIMUM_LIST_SIZE               0x01010104
+ #define RNDIS_OID_802_3_MAC_OPTIONS                     0x01010105
+ 
+-//
+-//
++
++
+ #define NDIS_802_3_MAC_OPTION_PRIORITY                  0x00000001
+ 
+ #define RNDIS_OID_802_3_RCV_ERROR_ALIGNMENT             0x01020101
+@@ -289,9 +289,9 @@ typedef u32                                  RNDIS_AF;
+ #define RNDIS_OID_802_3_XMIT_LATE_COLLISIONS            0x01020207
+ 
+ 
+-//
+-// Remote NDIS message types
+-//
++
++/* Remote NDIS message types */
++
+ #define REMOTE_NDIS_PACKET_MSG                  0x00000001
+ #define REMOTE_NDIS_INITIALIZE_MSG              0x00000002
+ #define REMOTE_NDIS_HALT_MSG                    0x00000003
+@@ -308,7 +308,7 @@ typedef u32                                  RNDIS_AF;
+ #define REMOTE_CONDIS_INDICATE_STATUS_MSG       0x00008007
+ 
+ 
+-// Remote NDIS message completion types
++/* Remote NDIS message completion types */
+ #define REMOTE_NDIS_INITIALIZE_CMPLT            0x80000002
+ #define REMOTE_NDIS_QUERY_CMPLT                 0x80000004
+ #define REMOTE_NDIS_SET_CMPLT                   0x80000005
+@@ -320,24 +320,24 @@ typedef u32                                  RNDIS_AF;
+ #define REMOTE_CONDIS_MP_ACTIVATE_VC_CMPLT      0x80008005
+ #define REMOTE_CONDIS_MP_DEACTIVATE_VC_CMPLT    0x80008006
+ 
+-//
+-// Reserved message type for private communication between lower-layer
+-// host driver and remote device, if necessary.
+-//
++
++/* Reserved message type for private communication between lower-layer */
++/* host driver and remote device, if necessary. */
++
+ #define REMOTE_NDIS_BUS_MSG                     0xff000001
+ 
+ 
+ 
+-//
+-//  Defines for DeviceFlags in RNDIS_INITIALIZE_COMPLETE
+-//
++
++/*  Defines for DeviceFlags in RNDIS_INITIALIZE_COMPLETE */
++
+ #define RNDIS_DF_CONNECTIONLESS             0x00000001
+ #define RNDIS_DF_CONNECTION_ORIENTED        0x00000002
+ #define RNDIS_DF_RAW_DATA                   0x00000004
+ 
+-//
+-//  Remote NDIS medium types.
+-//
++
++/*  Remote NDIS medium types. */
++
+ #define RNdisMedium802_3                    0x00000000
+ #define RNdisMedium802_5                    0x00000001
+ #define RNdisMediumFddi                     0x00000002
+@@ -349,23 +349,23 @@ typedef u32                                  RNDIS_AF;
+ #define RNdisMediumWirelessWan              0x00000009
+ #define RNdisMediumIrda                     0x0000000a
+ #define RNdisMediumCoWan                    0x0000000b
+-#define RNdisMediumMax                      0x0000000d     // Not a real medium, defined as an upper-bound
++#define RNdisMediumMax                      0x0000000d     /* Not a real medium, defined as an upper-bound */
++
++
++/* Remote NDIS medium connection states. */
+ 
+-//
+-// Remote NDIS medium connection states.
+-//
+ #define RNdisMediaStateConnected            0x00000000
+ #define RNdisMediaStateDisconnected         0x00000001
+ 
+-//
+-//  Remote NDIS version numbers
+-//
++
++/*  Remote NDIS version numbers */
++
+ #define RNDIS_MAJOR_VERSION                 0x00000001
+ #define RNDIS_MINOR_VERSION                 0x00000000
+ 
+-//
+-//  NdisInitialize message
+-//
++
++/*  NdisInitialize message */
++
+ typedef struct _RNDIS_INITIALIZE_REQUEST
+ {
+     RNDIS_REQUEST_ID                        RequestId;
+@@ -375,9 +375,9 @@ typedef struct _RNDIS_INITIALIZE_REQUEST
+ } RNDIS_INITIALIZE_REQUEST, *PRNDIS_INITIALIZE_REQUEST;
+ 
+ 
+-//
+-//  Response to NdisInitialize
+-//
++
++/*  Response to NdisInitialize */
++
+ typedef struct _RNDIS_INITIALIZE_COMPLETE
+ {
+     RNDIS_REQUEST_ID                        RequestId;
+@@ -394,10 +394,10 @@ typedef struct _RNDIS_INITIALIZE_COMPLETE
+ } RNDIS_INITIALIZE_COMPLETE, *PRNDIS_INITIALIZE_COMPLETE;
+ 
+ 
+-//
+-//  Call manager devices only: Information about an address family
+-//  supported by the device is appended to the response to NdisInitialize.
+-//
++
++/*  Call manager devices only: Information about an address family */
++/*  supported by the device is appended to the response to NdisInitialize. */
++
+ typedef struct _RNDIS_CO_ADDRESS_FAMILY
+ {
+     RNDIS_AF                                AddressFamily;
+@@ -406,18 +406,18 @@ typedef struct _RNDIS_CO_ADDRESS_FAMILY
+ } RNDIS_CO_ADDRESS_FAMILY, *PRNDIS_CO_ADDRESS_FAMILY;
+ 
+ 
+-//
+-//  NdisHalt message
+-//
++
++/*  NdisHalt message */
++
+ typedef struct _RNDIS_HALT_REQUEST
+ {
+     RNDIS_REQUEST_ID                        RequestId;
+ } RNDIS_HALT_REQUEST, *PRNDIS_HALT_REQUEST;
+ 
+ 
+-//
+-// NdisQueryRequest message
+-//
++
++/* NdisQueryRequest message */
++
+ typedef struct _RNDIS_QUERY_REQUEST
+ {
+     RNDIS_REQUEST_ID                        RequestId;
+@@ -428,9 +428,9 @@ typedef struct _RNDIS_QUERY_REQUEST
+ } RNDIS_QUERY_REQUEST, *PRNDIS_QUERY_REQUEST;
+ 
+ 
+-//
+-//  Response to NdisQueryRequest
+-//
++
++/*  Response to NdisQueryRequest */
++
+ typedef struct _RNDIS_QUERY_COMPLETE
+ {
+     RNDIS_REQUEST_ID                        RequestId;
+@@ -440,9 +440,9 @@ typedef struct _RNDIS_QUERY_COMPLETE
+ } RNDIS_QUERY_COMPLETE, *PRNDIS_QUERY_COMPLETE;
+ 
+ 
+-//
+-//  NdisSetRequest message
+-//
++
++/*  NdisSetRequest message */
++
+ typedef struct _RNDIS_SET_REQUEST
+ {
+     RNDIS_REQUEST_ID                        RequestId;
+@@ -453,9 +453,9 @@ typedef struct _RNDIS_SET_REQUEST
+ } RNDIS_SET_REQUEST, *PRNDIS_SET_REQUEST;
+ 
+ 
+-//
+-//  Response to NdisSetRequest
+-//
++
++/*  Response to NdisSetRequest */
++
+ typedef struct _RNDIS_SET_COMPLETE
+ {
+     RNDIS_REQUEST_ID                        RequestId;
+@@ -463,17 +463,17 @@ typedef struct _RNDIS_SET_COMPLETE
+ } RNDIS_SET_COMPLETE, *PRNDIS_SET_COMPLETE;
+ 
+ 
+-//
+-//  NdisReset message
+-//
++
++/*  NdisReset message */
++
+ typedef struct _RNDIS_RESET_REQUEST
+ {
+     u32                                  Reserved;
+ } RNDIS_RESET_REQUEST, *PRNDIS_RESET_REQUEST;
+ 
+-//
+-//  Response to NdisReset
+-//
++
++/*  Response to NdisReset */
++
+ typedef struct _RNDIS_RESET_COMPLETE
+ {
+     RNDIS_STATUS                            Status;
+@@ -481,9 +481,9 @@ typedef struct _RNDIS_RESET_COMPLETE
+ } RNDIS_RESET_COMPLETE, *PRNDIS_RESET_COMPLETE;
+ 
+ 
+-//
+-//  NdisMIndicateStatus message
+-//
++
++/*  NdisMIndicateStatus message */
++
+ typedef struct _RNDIS_INDICATE_STATUS
+ {
+     RNDIS_STATUS                            Status;
+@@ -492,10 +492,10 @@ typedef struct _RNDIS_INDICATE_STATUS
+ } RNDIS_INDICATE_STATUS, *PRNDIS_INDICATE_STATUS;
+ 
+ 
+-//
+-//  Diagnostic information passed as the status buffer in
+-//  RNDIS_INDICATE_STATUS messages signifying error conditions.
+-//
++
++/*  Diagnostic information passed as the status buffer in */
++/*  RNDIS_INDICATE_STATUS messages signifying error conditions. */
++
+ typedef struct _RNDIS_DIAGNOSTIC_INFO
+ {
+     RNDIS_STATUS                            DiagStatus;
+@@ -504,18 +504,18 @@ typedef struct _RNDIS_DIAGNOSTIC_INFO
+ 
+ 
+ 
+-//
+-//  NdisKeepAlive message
+-//
++
++/*  NdisKeepAlive message */
++
+ typedef struct _RNDIS_KEEPALIVE_REQUEST
+ {
+     RNDIS_REQUEST_ID                        RequestId;
+ } RNDIS_KEEPALIVE_REQUEST, *PRNDIS_KEEPALIVE_REQUEST;
+ 
+ 
+-//
+-// Response to NdisKeepAlive
+-//
++
++/* Response to NdisKeepAlive */
++
+ typedef struct _RNDIS_KEEPALIVE_COMPLETE
+ {
+     RNDIS_REQUEST_ID                        RequestId;
+@@ -523,12 +523,12 @@ typedef struct _RNDIS_KEEPALIVE_COMPLETE
+ } RNDIS_KEEPALIVE_COMPLETE, *PRNDIS_KEEPALIVE_COMPLETE;
+ 
+ 
+-//
+-//  Data message. All Offset fields contain byte offsets from the beginning
+-//  of the RNDIS_PACKET structure. All Length fields are in bytes.
+-//  VcHandle is set to 0 for connectionless data, otherwise it
+-//  contains the VC handle.
+-//
++
++/*  Data message. All Offset fields contain byte offsets from the beginning */
++/*  of the RNDIS_PACKET structure. All Length fields are in bytes. */
++/*  VcHandle is set to 0 for connectionless data, otherwise it */
++/*  contains the VC handle. */
++
+ typedef struct _RNDIS_PACKET
+ {
+     u32                                  DataOffset;
+@@ -542,9 +542,9 @@ typedef struct _RNDIS_PACKET
+     u32                                  Reserved;
+ } RNDIS_PACKET, *PRNDIS_PACKET;
+ 
+-//
+-//  Optional Out of Band data associated with a Data message.
+-//
++
++/*  Optional Out of Band data associated with a Data message. */
++
+ typedef struct _RNDIS_OOBD
+ {
+     u32                                  Size;
+@@ -552,9 +552,9 @@ typedef struct _RNDIS_OOBD
+     u32                                  ClassInformationOffset;
+ } RNDIS_OOBD, *PRNDIS_OOBD;
+ 
+-//
+-//  Packet extension field contents associated with a Data message.
+-//
++
++/*  Packet extension field contents associated with a Data message. */
++
+ typedef struct _RNDIS_PER_PACKET_INFO
+ {
+     u32                                  Size;
+@@ -563,10 +563,10 @@ typedef struct _RNDIS_PER_PACKET_INFO
+ } RNDIS_PER_PACKET_INFO, *PRNDIS_PER_PACKET_INFO;
+ 
+ 
+-//
+-//  Format of Information buffer passed in a SetRequest for the OID
+-//  OID_GEN_RNDIS_CONFIG_PARAMETER.
+-//
++
++/*  Format of Information buffer passed in a SetRequest for the OID */
++/*  OID_GEN_RNDIS_CONFIG_PARAMETER. */
++
+ typedef struct _RNDIS_CONFIG_PARAMETER_INFO
+ {
+     u32                                  ParameterNameOffset;
+@@ -576,30 +576,30 @@ typedef struct _RNDIS_CONFIG_PARAMETER_INFO
+     u32                                  ParameterValueLength;
+ } RNDIS_CONFIG_PARAMETER_INFO, *PRNDIS_CONFIG_PARAMETER_INFO;
+ 
+-//
+-//  Values for ParameterType in RNDIS_CONFIG_PARAMETER_INFO
+-//
++
++/*  Values for ParameterType in RNDIS_CONFIG_PARAMETER_INFO */
++
+ #define RNDIS_CONFIG_PARAM_TYPE_INTEGER     0
+ #define RNDIS_CONFIG_PARAM_TYPE_STRING      2
+ 
+ 
+-//
+-//  CONDIS Miniport messages for connection oriented devices
+-//  that do not implement a call manager.
+-//
+ 
+-//
+-//  CoNdisMiniportCreateVc message
+-//
++/*  CONDIS Miniport messages for connection oriented devices */
++/*  that do not implement a call manager. */
++
++
++
++/*  CoNdisMiniportCreateVc message */
++
+ typedef struct _RCONDIS_MP_CREATE_VC
+ {
+     RNDIS_REQUEST_ID                        RequestId;
+     RNDIS_HANDLE                            NdisVcHandle;
+ } RCONDIS_MP_CREATE_VC, *PRCONDIS_MP_CREATE_VC;
+ 
+-//
+-//  Response to CoNdisMiniportCreateVc
+-//
++
++/*  Response to CoNdisMiniportCreateVc */
++
+ typedef struct _RCONDIS_MP_CREATE_VC_COMPLETE
+ {
+     RNDIS_REQUEST_ID                        RequestId;
+@@ -608,18 +608,18 @@ typedef struct _RCONDIS_MP_CREATE_VC_COMPLETE
+ } RCONDIS_MP_CREATE_VC_COMPLETE, *PRCONDIS_MP_CREATE_VC_COMPLETE;
+ 
+ 
+-//
+-//  CoNdisMiniportDeleteVc message
+-//
++
++/*  CoNdisMiniportDeleteVc message */
++
+ typedef struct _RCONDIS_MP_DELETE_VC
+ {
+     RNDIS_REQUEST_ID                        RequestId;
+     RNDIS_HANDLE                            DeviceVcHandle;
+ } RCONDIS_MP_DELETE_VC, *PRCONDIS_MP_DELETE_VC;
+ 
+-//
+-//  Response to CoNdisMiniportDeleteVc
+-//
++
++/*  Response to CoNdisMiniportDeleteVc */
++
+ typedef struct _RCONDIS_MP_DELETE_VC_COMPLETE
+ {
+     RNDIS_REQUEST_ID                        RequestId;
+@@ -627,9 +627,9 @@ typedef struct _RCONDIS_MP_DELETE_VC_COMPLETE
+ } RCONDIS_MP_DELETE_VC_COMPLETE, *PRCONDIS_MP_DELETE_VC_COMPLETE;
+ 
+ 
+-//
+-//  CoNdisMiniportQueryRequest message
+-//
++
++/*  CoNdisMiniportQueryRequest message */
++
+ typedef struct _RCONDIS_MP_QUERY_REQUEST
+ {
+     RNDIS_REQUEST_ID                        RequestId;
+@@ -641,9 +641,9 @@ typedef struct _RCONDIS_MP_QUERY_REQUEST
+ } RCONDIS_MP_QUERY_REQUEST, *PRCONDIS_MP_QUERY_REQUEST;
+ 
+ 
+-//
+-//  CoNdisMiniportSetRequest message
+-//
++
++/*  CoNdisMiniportSetRequest message */
++
+ typedef struct _RCONDIS_MP_SET_REQUEST
+ {
+     RNDIS_REQUEST_ID                        RequestId;
+@@ -655,9 +655,9 @@ typedef struct _RCONDIS_MP_SET_REQUEST
+ } RCONDIS_MP_SET_REQUEST, *PRCONDIS_MP_SET_REQUEST;
+ 
+ 
+-//
+-//  CoNdisIndicateStatus message
+-//
++
++/*  CoNdisIndicateStatus message */
++
+ typedef struct _RCONDIS_INDICATE_STATUS
+ {
+     RNDIS_HANDLE                            NdisVcHandle;
+@@ -667,9 +667,9 @@ typedef struct _RCONDIS_INDICATE_STATUS
+ } RCONDIS_INDICATE_STATUS, *PRCONDIS_INDICATE_STATUS;
+ 
+ 
+-//
+-//  CONDIS Call/VC parameters
+-//
++
++/*  CONDIS Call/VC parameters */
++
+ 
+ typedef struct _RCONDIS_SPECIFIC_PARAMETERS
+ {
+@@ -706,9 +706,9 @@ typedef struct _RCONDIS_CALL_MANAGER_PARAMETERS
+     RCONDIS_SPECIFIC_PARAMETERS             CallMgrSpecific;
+ } RCONDIS_CALL_MANAGER_PARAMETERS, *PRCONDIS_CALL_MANAGER_PARAMETERS;
+ 
+-//
+-//  CoNdisMiniportActivateVc message
+-//
++
++/*  CoNdisMiniportActivateVc message */
++
+ typedef struct _RCONDIS_MP_ACTIVATE_VC_REQUEST
+ {
+     RNDIS_REQUEST_ID                        RequestId;
+@@ -720,9 +720,9 @@ typedef struct _RCONDIS_MP_ACTIVATE_VC_REQUEST
+     u32                                  CallMgrParamsLength;
+ } RCONDIS_MP_ACTIVATE_VC_REQUEST, *PRCONDIS_MP_ACTIVATE_VC_REQUEST;
+ 
+-//
+-//  Response to CoNdisMiniportActivateVc
+-//
++
++/*  Response to CoNdisMiniportActivateVc */
++
+ typedef struct _RCONDIS_MP_ACTIVATE_VC_COMPLETE
+ {
+     RNDIS_REQUEST_ID                        RequestId;
+@@ -730,9 +730,9 @@ typedef struct _RCONDIS_MP_ACTIVATE_VC_COMPLETE
+ } RCONDIS_MP_ACTIVATE_VC_COMPLETE, *PRCONDIS_MP_ACTIVATE_VC_COMPLETE;
+ 
+ 
+-//
+-//  CoNdisMiniportDeactivateVc message
+-//
++
++/*  CoNdisMiniportDeactivateVc message */
++
+ typedef struct _RCONDIS_MP_DEACTIVATE_VC_REQUEST
+ {
+     RNDIS_REQUEST_ID                        RequestId;
+@@ -740,9 +740,9 @@ typedef struct _RCONDIS_MP_DEACTIVATE_VC_REQUEST
+     RNDIS_HANDLE                            DeviceVcHandle;
+ } RCONDIS_MP_DEACTIVATE_VC_REQUEST, *PRCONDIS_MP_DEACTIVATE_VC_REQUEST;
+ 
+-//
+-//  Response to CoNdisMiniportDeactivateVc
+-//
++
++/*  Response to CoNdisMiniportDeactivateVc */
++
+ typedef struct _RCONDIS_MP_DEACTIVATE_VC_COMPLETE
+ {
+     RNDIS_REQUEST_ID                        RequestId;
+@@ -750,9 +750,9 @@ typedef struct _RCONDIS_MP_DEACTIVATE_VC_COMPLETE
+ } RCONDIS_MP_DEACTIVATE_VC_COMPLETE, *PRCONDIS_MP_DEACTIVATE_VC_COMPLETE;
+ 
+ 
+-//
+-// union with all of the RNDIS messages
+-//
++
++/* union with all of the RNDIS messages */
++
+ typedef union _RNDIS_MESSAGE_CONTAINER
+ {
+     RNDIS_PACKET                        Packet;
+@@ -781,56 +781,56 @@ typedef union _RNDIS_MESSAGE_CONTAINER
+ 
+ } RNDIS_MESSAGE_CONTAINER, *PRNDIS_MESSAGE_CONTAINER;
+ 
+-//
+-// Remote NDIS message format
+-//
++
++/* Remote NDIS message format */
++
+ typedef __struct_bcount(MessageLength) struct _RNDIS_MESSAGE
+ {
+     u32                                  NdisMessageType;
+ 
+-    //
+-    // Total length of this message, from the beginning
+-    // of the RNDIS_MESSAGE struct, in bytes.
+-    //
++
++    /* Total length of this message, from the beginning */
++    /* of the RNDIS_MESSAGE struct, in bytes. */
++
+     u32                                  MessageLength;
+ 
+-    // Actual message
++    /* Actual message */
+     RNDIS_MESSAGE_CONTAINER                 Message;
+ 
+ } RNDIS_MESSAGE, *PRNDIS_MESSAGE;
+ 
+ 
+ 
+-//
+-// Handy macros
+ 
+-// get the size of an RNDIS message. Pass in the message type,
+-// RNDIS_SET_REQUEST, RNDIS_PACKET for example
++/* Handy macros */
++
++/* get the size of an RNDIS message. Pass in the message type, */
++/* RNDIS_SET_REQUEST, RNDIS_PACKET for example */
+ #define RNDIS_MESSAGE_SIZE(Message)                             \
+     (sizeof(Message) + (sizeof(RNDIS_MESSAGE) - sizeof(RNDIS_MESSAGE_CONTAINER)))
+ 
+-// get pointer to info buffer with message pointer
++/* get pointer to info buffer with message pointer */
+ #define MESSAGE_TO_INFO_BUFFER(Message)                         \
+     (((unsigned char *)(Message)) + Message->InformationBufferOffset)
+ 
+-// get pointer to status buffer with message pointer
++/* get pointer to status buffer with message pointer */
+ #define MESSAGE_TO_STATUS_BUFFER(Message)                       \
+     (((unsigned char *)(Message)) + Message->StatusBufferOffset)
+ 
+-// get pointer to OOBD buffer with message pointer
++/* get pointer to OOBD buffer with message pointer */
+ #define MESSAGE_TO_OOBD_BUFFER(Message)                         \
+     (((unsigned char *)(Message)) + Message->OOBDataOffset)
+ 
+-// get pointer to data buffer with message pointer
++/* get pointer to data buffer with message pointer */
+ #define MESSAGE_TO_DATA_BUFFER(Message)                         \
+     (((unsigned char *)(Message)) + Message->PerPacketInfoOffset)
+ 
+-// get pointer to contained message from NDIS_MESSAGE pointer
++/* get pointer to contained message from NDIS_MESSAGE pointer */
+ #define RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(RndisMessage)          \
+     ((void *) &RndisMessage->Message)
+ 
+-// get pointer to contained message from NDIS_MESSAGE pointer
++/* get pointer to contained message from NDIS_MESSAGE pointer */
+ #define RNDIS_MESSAGE_RAW_PTR_TO_MESSAGE_PTR(RndisMessage)      \
+     ((void *) RndisMessage)
+ 
+-#endif // _RNDIS_H_
++#endif /* _RNDIS_H_ */
+diff --git a/drivers/staging/hv/include/vmbus.h b/drivers/staging/hv/include/vmbus.h
+index 62ddc1d643f1..463f77ef3cd9 100644
+--- a/drivers/staging/hv/include/vmbus.h
++++ b/drivers/staging/hv/include/vmbus.h
+@@ -29,9 +29,9 @@
+ 
+ #include "VmbusApi.h"
+ 
+-//
+-// Data types
+-//
++
++/* Data types */
++
+ 
+ typedef int (*PFN_DRIVERINITIALIZE)(DRIVER_OBJECT *drv);
+ typedef int (*PFN_DRIVEREXIT)(DRIVER_OBJECT *drv);
+@@ -41,7 +41,7 @@ struct driver_context {
+ 
+ 	struct device_driver	driver;
+ 
+-	// Use these methods instead of the struct device_driver so 2.6 kernel stops complaining
++	/* Use these methods instead of the struct device_driver so 2.6 kernel stops complaining */
+ 	int (*probe)(struct device *);
+ 	int (*remove)(struct device *);
+ 	void (*shutdown)(struct device *);
+@@ -57,13 +57,13 @@ struct device_context {
+ };
+ 
+ 
+-//
+-// Global
+-//
+ 
+-//
+-// Inlines
+-//
++/* Global */
++
++
++
++/* Inlines */
++
+ static inline struct device_context *to_device_context(DEVICE_OBJECT *device_obj)
+ {
+ 	return container_of(device_obj, struct device_context, device_obj);
+@@ -79,9 +79,9 @@ static inline struct driver_context *driver_to_driver_context(struct device_driv
+ 	return container_of(driver, struct driver_context, driver);
+ }
+ 
+-//
+-// Vmbus interface
+-//
++
++/* Vmbus interface */
++
+ void
+ vmbus_child_driver_register(
+ 	struct driver_context* driver_ctx
+@@ -97,4 +97,4 @@ vmbus_get_interface(
+ 	VMBUS_CHANNEL_INTERFACE *interface
+ 	);
+ 
+-#endif // _VMBUS_H_
++#endif /* _VMBUS_H_ */
+diff --git a/drivers/staging/hv/include/vstorage.h b/drivers/staging/hv/include/vstorage.h
+index ada1f649e9ec..33646e76da7c 100644
+--- a/drivers/staging/hv/include/vstorage.h
++++ b/drivers/staging/hv/include/vstorage.h
+@@ -24,28 +24,28 @@
+ 
+ #pragma once
+ 
+-//#include 
+-//#include 
++/* #include  */
++/* #include  */
+ 
+ #define C_ASSERT(x)
+-//
+-//  public interface to the server
+-//
+ 
+-//
+-//  Storvsp device interface guid
+-//
++/*  public interface to the server */
+ 
+ 
+-//
+-//  Protocol versions.
+-//
+ 
+-//
+-// vstorage.w revision number.  This is used in the case of a version match,
+-// to alert the user that structure sizes may be mismatched even though the
+-// protocol versions match.
+-//
++/*  Storvsp device interface guid */
++
++
++
++
++/*  Protocol versions. */
++
++
++
++/* vstorage.w revision number.  This is used in the case of a version match, */
++/* to alert the user that structure sizes may be mismatched even though the */
++/* protocol versions match. */
++
+ 
+ #define REVISION_STRING(REVISION_) #REVISION_
+ #define FILL_VMSTOR_REVISION(RESULT_LVALUE_)                     \
+@@ -54,53 +54,53 @@
+     RESULT_LVALUE_ = 0;                                          \
+     while (*revisionString >= '0' && *revisionString <= '9')     \
+     {                                                            \
+-        RESULT_LVALUE_ *= 10;                                    \
+-        RESULT_LVALUE_ += *revisionString - '0';                 \
+-        revisionString++;                                        \
++	RESULT_LVALUE_ *= 10;                                    \
++	RESULT_LVALUE_ += *revisionString - '0';                 \
++	revisionString++;                                        \
+     }                                                            \
+ }
+ 
+-//
+-// Major/minor macros.  Minor version is in LSB, meaning that earlier flat
+-// version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1).
+-//
++
++/* Major/minor macros.  Minor version is in LSB, meaning that earlier flat */
++/* version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1). */
++
+ 
+ #define VMSTOR_PROTOCOL_MAJOR(VERSION_)         (((VERSION_) >> 8) & 0xff)
+ #define VMSTOR_PROTOCOL_MINOR(VERSION_)         (((VERSION_)     ) & 0xff)
+ #define VMSTOR_PROTOCOL_VERSION(MAJOR_, MINOR_) ((((MAJOR_) & 0xff) << 8) | \
+-                                                 (((MINOR_) & 0xff)     ))
++						 (((MINOR_) & 0xff)     ))
++
++
++/* Invalid version. */
+ 
+-//
+-// Invalid version.
+-//
+ 
+ #define VMSTOR_INVALID_PROTOCOL_VERSION  -1
+ 
+-//
+-// Version history:
+-// V1 Beta                    0.1
+-// V1 RC < 2008/1/31          1.0
+-// V1 RC > 2008/1/31          2.0
+-//
++
++/* Version history: */
++/* V1 Beta                    0.1 */
++/* V1 RC < 2008/1/31          1.0 */
++/* V1 RC > 2008/1/31          2.0 */
++
+ #define VMSTOR_PROTOCOL_VERSION_CURRENT VMSTOR_PROTOCOL_VERSION(2, 0)
+ 
+ 
+-//
+-//  This will get replaced with the max transfer length that is possible on
+-//  the host adapter.
+-//  The max transfer length will be published when we offer a vmbus channel.
+-//
++
++/*  This will get replaced with the max transfer length that is possible on */
++/*  the host adapter. */
++/*  The max transfer length will be published when we offer a vmbus channel. */
++
+ 
+ #define MAX_TRANSFER_LENGTH 0x40000
+ #define DEFAULT_PACKET_SIZE (sizeof(VMDATA_GPA_DIRECT) +                            \
+-                             sizeof(VSTOR_PACKET) +                                 \
+-                             (sizeof(u64) * (MAX_TRANSFER_LENGTH / PAGE_SIZE)))
++			     sizeof(VSTOR_PACKET) +                                 \
++			     (sizeof(u64) * (MAX_TRANSFER_LENGTH / PAGE_SIZE)))
++
++
+ 
+ 
++/*  Packet structure describing virtual storage requests. */
+ 
+-//
+-//  Packet structure describing virtual storage requests.
+-//
+ 
+ typedef enum
+ {
+@@ -119,11 +119,11 @@ typedef enum
+ } VSTOR_PACKET_OPERATION;
+ 
+ 
+-//
+-//  Platform neutral description of a scsi request -
+-//  this remains the same across the write regardless of 32/64 bit
+-//  note: it's patterned off the SCSI_PASS_THROUGH structure
+-//
++
++/*  Platform neutral description of a scsi request - */
++/*  this remains the same across the write regardless of 32/64 bit */
++/*  note: it's patterned off the SCSI_PASS_THROUGH structure */
++
+ 
+ 
+ #pragma pack(push,1)
+@@ -159,11 +159,11 @@ typedef struct
+ 
+     union
+     {
+-        unsigned char Cdb[CDB16GENERIC_LENGTH];
++	unsigned char Cdb[CDB16GENERIC_LENGTH];
+ 
+-        unsigned char SenseData[SENSE_BUFFER_SIZE];
++	unsigned char SenseData[SENSE_BUFFER_SIZE];
+ 
+-        unsigned char ReservedArray[MAX_DATA_BUFFER_LENGTH_WITH_PADDING];
++	unsigned char ReservedArray[MAX_DATA_BUFFER_LENGTH_WITH_PADDING];
+     };
+ 
+ } VMSCSI_REQUEST, *PVMSCSI_REQUEST;
+@@ -171,10 +171,10 @@ typedef struct
+ C_ASSERT((sizeof(VMSCSI_REQUEST) % 4) == 0);
+ 
+ 
+-//
+-//  This structure is sent during the intialization phase to get the different
+-//  properties of the channel.
+-//
++
++/*  This structure is sent during the intialization phase to get the different */
++/*  properties of the channel. */
++
+ 
+ typedef struct
+ {
+@@ -182,19 +182,19 @@ typedef struct
+     unsigned char  PathId;
+     unsigned char  TargetId;
+ 
+-    //
+-    // Note: port number is only really known on the client side
+-    //
++
++    /* Note: port number is only really known on the client side */
++
+     unsigned int  PortNumber;
+ 
+     unsigned int  Flags;
+ 
+     unsigned int  MaxTransferBytes;
+ 
+-    //
+-    //  This id is unique for each channel and will correspond with
+-    //  vendor specific data in the inquirydata
+-    //
++
++    /*  This id is unique for each channel and will correspond with */
++    /*  vendor specific data in the inquirydata */
++
+ 
+     unsigned long long UniqueId;
+ 
+@@ -203,24 +203,24 @@ typedef struct
+ C_ASSERT((sizeof(VMSTORAGE_CHANNEL_PROPERTIES) % 4) == 0);
+ 
+ 
+-//
+-//  This structure is sent during the storage protocol negotiations.
+-//
++
++/*  This structure is sent during the storage protocol negotiations. */
++
+ 
+ typedef struct
+ {
+-    //
+-    // Major (MSW) and minor (LSW) version numbers.
+-    //
++
++    /* Major (MSW) and minor (LSW) version numbers. */
++
+ 
+     unsigned short MajorMinor;
+ 
+ 
+-    //
+-    // Revision number is auto-incremented whenever this file is changed
+-    // (See FILL_VMSTOR_REVISION macro above).  Mismatch does not definitely
+-    // indicate incompatibility--but it does indicate mismatched builds.
+-    //
++
++    /* Revision number is auto-incremented whenever this file is changed */
++    /* (See FILL_VMSTOR_REVISION macro above).  Mismatch does not definitely */
++    /* indicate incompatibility--but it does indicate mismatched builds. */
++
+ 
+     unsigned short Revision;
+ 
+@@ -229,9 +229,9 @@ typedef struct
+ C_ASSERT((sizeof(VMSTORAGE_PROTOCOL_VERSION) % 4) == 0);
+ 
+ 
+-//
+-// Channel Property Flags
+-//
++
++/* Channel Property Flags */
++
+ 
+ #define STORAGE_CHANNEL_REMOVABLE_FLAG                  0x1
+ #define STORAGE_CHANNEL_EMULATED_IDE_FLAG               0x2
+@@ -239,71 +239,69 @@ C_ASSERT((sizeof(VMSTORAGE_PROTOCOL_VERSION) % 4) == 0);
+ 
+ typedef struct _VSTOR_PACKET
+ {
+-    //
+-    // Requested operation type
+-    //
++
++    /* Requested operation type */
++
+ 
+     VSTOR_PACKET_OPERATION Operation;
+ 
+-    //
+-    //  Flags - see below for values
+-    //
++
++    /*  Flags - see below for values */
++
+ 
+     unsigned int     Flags;
+ 
+-    //
+-    // Status of the request returned from the server side.
+-    //
++
++    /* Status of the request returned from the server side. */
++
+ 
+     unsigned int     Status;
+ 
+-    //
+-    // Data payload area
+-    //
++
++    /* Data payload area */
++
+ 
+     union
+     {
+-        //
+-        //  Structure used to forward SCSI commands from the client to the server.
+-        //
+ 
+-        VMSCSI_REQUEST VmSrb;
++	/*  Structure used to forward SCSI commands from the client to the server. */
+ 
+-        //
+-        // Structure used to query channel properties.
+-        //
+ 
+-        VMSTORAGE_CHANNEL_PROPERTIES StorageChannelProperties;
++	VMSCSI_REQUEST VmSrb;
+ 
+-        //
+-        // Used during version negotiations.
+-        //
+ 
+-        VMSTORAGE_PROTOCOL_VERSION Version;
++	/* Structure used to query channel properties. */
++
++
++	VMSTORAGE_CHANNEL_PROPERTIES StorageChannelProperties;
++
++
++	/* Used during version negotiations. */
++
++
++	VMSTORAGE_PROTOCOL_VERSION Version;
+     };
+ 
+ } VSTOR_PACKET, *PVSTOR_PACKET;
+ 
+ C_ASSERT((sizeof(VSTOR_PACKET) % 4) == 0);
+ 
+-//
+-//  Packet flags
+-//
+ 
+-//
+-//  This flag indicates that the server should send back a completion for this
+-//  packet.
+-//
++/*  Packet flags */
++
++
++
++/*  This flag indicates that the server should send back a completion for this */
++/*  packet. */
++
+ 
+ #define REQUEST_COMPLETION_FLAG 0x1
+ 
+-//
+-//  This is the set of flags that the vsc can set in any packets it sends
+-//
+ 
+-#define VSC_LEGAL_FLAGS (REQUEST_COMPLETION_FLAG)
++/*  This is the set of flags that the vsc can set in any packets it sends */
+ 
+ 
+-#pragma pack(pop)
++#define VSC_LEGAL_FLAGS (REQUEST_COMPLETION_FLAG)
+ 
+ 
++#pragma pack(pop)
+diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c
+index 20adcc6cbdd5..8cf552a33e53 100644
+--- a/drivers/staging/hv/netvsc_drv.c
++++ b/drivers/staging/hv/netvsc_drv.c
+@@ -43,9 +43,9 @@
+ 
+ MODULE_LICENSE("GPL");
+ 
+-//
+-// Static decl
+-//
++
++/* Static decl */
++
+ static int netvsc_probe(struct device *device);
+ static int netvsc_remove(struct device *device);
+ static int netvsc_open(struct net_device *net);
+@@ -56,32 +56,32 @@ static int netvsc_close(struct net_device *net);
+ static struct net_device_stats *netvsc_get_stats(struct net_device *net);
+ static void netvsc_linkstatus_callback(DEVICE_OBJECT *device_obj, unsigned int status);
+ 
+-//
+-// Data types
+-//
++
++/* Data types */
++
+ struct net_device_context {
+-	struct device_context	*device_ctx; // point back to our device context
++	struct device_context	*device_ctx; /* point back to our device context */
+ 	struct net_device_stats stats;
+ };
+ 
+ struct netvsc_driver_context {
+-	// !! These must be the first 2 fields !!
++	/* !! These must be the first 2 fields !! */
+ 	struct driver_context	drv_ctx;
+ 	NETVSC_DRIVER_OBJECT	drv_obj;
+ };
+ 
+-//
+-// Globals
+-//
++
++/* Globals */
++
+ 
+ static int netvsc_ringbuffer_size = NETVSC_DEVICE_RING_BUFFER_SIZE;
+ 
+-// The one and only one
++/* The one and only one */
+ static struct netvsc_driver_context g_netvsc_drv;
+ 
+-//
+-// Routines
+-//
++
++/* Routines */
++
+ 
+ /*++
+ 
+@@ -104,7 +104,7 @@ int netvsc_drv_init(PFN_DRIVERINITIALIZE pfn_drv_init)
+ 	net_drv_obj->OnReceiveCallback = netvsc_recv_callback;
+ 	net_drv_obj->OnLinkStatusChanged = netvsc_linkstatus_callback;
+ 
+-	// Callback to client driver to complete the initialization
++	/* Callback to client driver to complete the initialization */
+ 	pfn_drv_init(&net_drv_obj->Base);
+ 
+ 	drv_ctx->driver.name = net_drv_obj->Base.name;
+@@ -113,7 +113,7 @@ int netvsc_drv_init(PFN_DRIVERINITIALIZE pfn_drv_init)
+ 	drv_ctx->probe = netvsc_probe;
+ 	drv_ctx->remove = netvsc_remove;
+ 
+-	// The driver belongs to vmbus
++	/* The driver belongs to vmbus */
+ 	vmbus_child_driver_register(drv_ctx);
+ 
+ 	DPRINT_EXIT(NETVSC_DRV);
+@@ -186,13 +186,13 @@ static int netvsc_probe(struct device *device)
+ 	}
+ 
+ 	net = alloc_netdev(sizeof(struct net_device_context), "seth%d", ether_setup);
+-	//net = alloc_etherdev(sizeof(struct net_device_context));
++	/* net = alloc_etherdev(sizeof(struct net_device_context)); */
+ 	if (!net)
+ 	{
+ 		return -1;
+ 	}
+ 
+-	// Set initial state
++	/* Set initial state */
+ 	netif_carrier_off(net);
+ 	netif_stop_queue(net);
+ 
+@@ -200,7 +200,7 @@ static int netvsc_probe(struct device *device)
+ 	net_device_ctx->device_ctx = device_ctx;
+ 	dev_set_drvdata(device, net);
+ 
+-	// Notify the netvsc driver of the new device
++	/* Notify the netvsc driver of the new device */
+ 	ret = net_drv_obj->Base.OnDeviceAdd(device_obj, (void*)&device_info);
+ 	if (ret != 0)
+ 	{
+@@ -211,8 +211,8 @@ static int netvsc_probe(struct device *device)
+ 		return ret;
+ 	}
+ 
+-	// If carrier is still off ie we did not get a link status callback, update it if necessary
+-	// FIXME: We should use a atomic or test/set instead to avoid getting out of sync with the device's link status
++	/* If carrier is still off ie we did not get a link status callback, update it if necessary */
++	/* FIXME: We should use a atomic or test/set instead to avoid getting out of sync with the device's link status */
+ 	if (!netif_carrier_ok(net))
+ 	{
+ 		if (!device_info.LinkState)
+@@ -230,7 +230,7 @@ static int netvsc_probe(struct device *device)
+ 	ret = register_netdev(net);
+ 	if (ret != 0)
+ 	{
+-		// Remove the device and release the resource
++		/* Remove the device and release the resource */
+ 		net_drv_obj->Base.OnDeviceRemove(device_obj);
+ 		free_netdev(net);
+ 	}
+@@ -266,17 +266,17 @@ static int netvsc_remove(struct device *device)
+ 		return -1;
+ 	}
+ 
+-	// Stop outbound asap
++	/* Stop outbound asap */
+ 	netif_stop_queue(net);
+-	//netif_carrier_off(net);
++	/* netif_carrier_off(net); */
+ 
+ 	unregister_netdev(net);
+ 
+-	// Call to the vsc driver to let it know that the device is being removed
++	/* Call to the vsc driver to let it know that the device is being removed */
+ 	ret = net_drv_obj->Base.OnDeviceRemove(device_obj);
+ 	if (ret != 0)
+ 	{
+-		// TODO:
++		/* TODO: */
+ 		DPRINT_ERR(NETVSC, "unable to remove vsc device (ret %d)", ret);
+ 	}
+ 
+@@ -310,7 +310,7 @@ static int netvsc_open(struct net_device *net)
+ 	{
+ 		memset(&net_device_ctx->stats, 0 , sizeof(struct net_device_stats));
+ 
+-		// Open up the device
++		/* Open up the device */
+ 		ret = net_drv_obj->OnOpen(device_obj);
+ 		if (ret != 0)
+ 		{
+@@ -418,16 +418,16 @@ static int netvsc_start_xmit (struct sk_buff *skb, struct net_device *net)
+ 
+ 	DPRINT_ENTER(NETVSC_DRV);
+ 
+-	// Support only 1 chain of frags
++	/* Support only 1 chain of frags */
+ 	ASSERT(skb_shinfo(skb)->frag_list == NULL);
+ 	ASSERT(skb->dev == net);
+ 
+ 	DPRINT_DBG(NETVSC_DRV, "xmit packet - len %d data_len %d", skb->len, skb->data_len);
+ 
+-	// Add 1 for skb->data and any additional ones requested
++	/* Add 1 for skb->data and any additional ones requested */
+ 	num_frags = skb_shinfo(skb)->nr_frags + 1 + net_drv_obj->AdditionalRequestPageBufferCount;
+ 
+-	// Allocate a netvsc packet based on # of frags.
++	/* Allocate a netvsc packet based on # of frags. */
+ 	packet = kzalloc(sizeof(NETVSC_PACKET) + (num_frags * sizeof(PAGE_BUFFER)) + net_drv_obj->RequestExtSize, GFP_ATOMIC);
+ 	if (!packet)
+ 	{
+@@ -437,17 +437,17 @@ static int netvsc_start_xmit (struct sk_buff *skb, struct net_device *net)
+ 
+ 	packet->Extension = (void*)(unsigned long)packet + sizeof(NETVSC_PACKET) + (num_frags * sizeof(PAGE_BUFFER)) ;
+ 
+-	// Setup the rndis header
++	/* Setup the rndis header */
+ 	packet->PageBufferCount = num_frags;
+ 
+-	// TODO: Flush all write buffers/ memory fence ???
+-	//wmb();
++	/* TODO: Flush all write buffers/ memory fence ??? */
++	/* wmb(); */
+ 
+-	// Initialize it from the skb
++	/* Initialize it from the skb */
+ 	ASSERT(skb->data);
+ 	packet->TotalDataBufferLength	= skb->len;
+ 
+-	// Start filling in the page buffers starting at AdditionalRequestPageBufferCount offset
++	/* Start filling in the page buffers starting at AdditionalRequestPageBufferCount offset */
+ 	packet->PageBuffers[net_drv_obj->AdditionalRequestPageBufferCount].Pfn		= virt_to_phys(skb->data) >> PAGE_SHIFT;
+ 	packet->PageBuffers[net_drv_obj->AdditionalRequestPageBufferCount].Offset	= (unsigned long)skb->data & (PAGE_SIZE -1);
+ 	packet->PageBuffers[net_drv_obj->AdditionalRequestPageBufferCount].Length	= skb->len - skb->data_len;
+@@ -461,7 +461,7 @@ static int netvsc_start_xmit (struct sk_buff *skb, struct net_device *net)
+ 		packet->PageBuffers[i].Length	= skb_shinfo(skb)->frags[i-(net_drv_obj->AdditionalRequestPageBufferCount+1)].size;
+ 	}
+ 
+-	// Set the completion routine
++	/* Set the completion routine */
+ 	packet->Completion.Send.OnSendCompletion = netvsc_xmit_completion;
+ 	packet->Completion.Send.SendCompletionContext = packet;
+ 	packet->Completion.Send.SendCompletionTid = (unsigned long)skb;
+@@ -485,7 +485,7 @@ static int netvsc_start_xmit (struct sk_buff *skb, struct net_device *net)
+ 			goto retry_send;
+ 		}
+ 
+-		// no more room or we are shutting down
++		/* no more room or we are shutting down */
+ 		DPRINT_ERR(NETVSC_DRV, "unable to send (%d)...marking net device (%p) busy", ret, net);
+ 		DPRINT_INFO(NETVSC_DRV, "net device (%p) stopping", net);
+ 
+@@ -494,10 +494,10 @@ static int netvsc_start_xmit (struct sk_buff *skb, struct net_device *net)
+ 
+ 		netif_stop_queue(net);
+ 
+-		// Null it since the caller will free it instead of the completion routine
++		/* Null it since the caller will free it instead of the completion routine */
+ 		packet->Completion.Send.SendCompletionTid = 0;
+ 
+-		// Release the resources since we will not get any send completion
++		/* Release the resources since we will not get any send completion */
+ 		netvsc_xmit_completion((void*)packet);
+ 	}
+ 
+@@ -571,18 +571,18 @@ static int netvsc_recv_callback(DEVICE_OBJECT *device_obj, NETVSC_PACKET* packet
+ 
+ 	net_device_ctx = netdev_priv(net);
+ 
+-	// Allocate a skb - TODO preallocate this
+-	//skb = alloc_skb(packet->TotalDataBufferLength, GFP_ATOMIC);
+-	skb = dev_alloc_skb(packet->TotalDataBufferLength + 2); // Pad 2-bytes to align IP header to 16 bytes
++	/* Allocate a skb - TODO preallocate this */
++	/* skb = alloc_skb(packet->TotalDataBufferLength, GFP_ATOMIC); */
++	skb = dev_alloc_skb(packet->TotalDataBufferLength + 2); /* Pad 2-bytes to align IP header to 16 bytes */
+ 	ASSERT(skb);
+ 	skb_reserve(skb, 2);
+ 	skb->dev = net;
+ 
+-	// for kmap_atomic
++	/* for kmap_atomic */
+ 	local_irq_save(flags);
+ 
+-	// Copy to skb. This copy is needed here since the memory pointed by NETVSC_PACKET
+-	// cannot be deallocated
++	/* Copy to skb. This copy is needed here since the memory pointed by NETVSC_PACKET */
++	/* cannot be deallocated */
+ 	for (i=0; iPageBufferCount; i++)
+ 	{
+ 	    data = kmap_atomic(pfn_to_page(packet->PageBuffers[i].Pfn), KM_IRQ1);
+@@ -599,7 +599,7 @@ static int netvsc_recv_callback(DEVICE_OBJECT *device_obj, NETVSC_PACKET* packet
+ 
+ 	skb->ip_summed = CHECKSUM_NONE;
+ 
+-	// Pass the skb back up. Network stack will deallocate the skb when it is done
++	/* Pass the skb back up. Network stack will deallocate the skb when it is done */
+ 	ret = netif_rx(skb);
+ 
+ 	switch (ret)
+@@ -624,7 +624,7 @@ static int netvsc_drv_exit_cb(struct device *dev, void *data)
+ {
+ 	struct device **curr = (struct device **)data;
+ 	*curr = dev;
+-	return 1; // stop iterating
++	return 1; /* stop iterating */
+ }
+ 
+ /*++
+@@ -647,13 +647,13 @@ void netvsc_drv_exit(void)
+ 	{
+ 		current_dev = NULL;
+ 
+-		// Get the device
++		/* Get the device */
+ 		driver_for_each_device(&drv_ctx->driver, NULL, (void*)¤t_dev, netvsc_drv_exit_cb);
+ 
+ 		if (current_dev == NULL)
+ 			break;
+ 
+-		// Initiate removal from the top-down
++		/* Initiate removal from the top-down */
+ 		DPRINT_INFO(NETVSC_DRV, "unregistering device (%p)...", current_dev);
+ 
+ 		device_unregister(current_dev);
+diff --git a/drivers/staging/hv/osd.c b/drivers/staging/hv/osd.c
+index 3cc2bb3caac8..442cc7de0f0a 100644
+--- a/drivers/staging/hv/osd.c
++++ b/drivers/staging/hv/osd.c
+@@ -46,9 +46,9 @@
+ 
+ #include "include/osd.h"
+ 
+-//
+-// Data types
+-//
++
++/* Data types */
++
+ typedef struct _TIMER {
+ 	struct timer_list timer;
+ 	PFN_TIMER_CALLBACK callback;
+@@ -113,7 +113,7 @@ int InterlockedDecrement(int *val)
+ #endif
+ int InterlockedCompareExchange(int *val, int new, int curr)
+ {
+-	//return ((int)cmpxchg(((atomic_t*)val), curr, new));
++	/* return ((int)cmpxchg(((atomic_t*)val), curr, new)); */
+ 	return atomic_cmpxchg((atomic_t*)val, curr, new);
+ 
+ }
+@@ -139,13 +139,13 @@ void* PageAlloc(unsigned int count)
+ 	if (p) memset(p, 0, count * PAGE_SIZE);
+ 	return p;
+ 
+-	//struct page* page = alloc_page(GFP_KERNEL|__GFP_ZERO);
+-	//void *p;
++	/* struct page* page = alloc_page(GFP_KERNEL|__GFP_ZERO); */
++	/* void *p; */
+ 
+-	////BUGBUG: We need to use kmap in case we are in HIMEM region
+-	//p = page_address(page);
+-	//if (p) memset(p, 0, PAGE_SIZE);
+-	//return p;
++	/* BUGBUG: We need to use kmap in case we are in HIMEM region */
++	/* p = page_address(page); */
++	/* if (p) memset(p, 0, PAGE_SIZE); */
++	/* return p; */
+ }
+ 
+ void PageFree(void* page, unsigned int count)
+@@ -171,17 +171,17 @@ void *MemMapIO(unsigned long phys, unsigned long size)
+ #if X2V_LINUX
+ #ifdef __x86_64__
+ 	return (void*)(phys + 0xFFFF83000C000000);
+-#else // i386
++#else /* i386 */
+ 	return (void*)(phys + 0xfb000000);
+ #endif
+ #else
+-	return (void*)GetVirtualAddress(phys); //return ioremap_nocache(phys, size);
++	return (void*)GetVirtualAddress(phys); /* return ioremap_nocache(phys, size); */
+ #endif
+ }
+ 
+ void MemUnmapIO(void *virt)
+ {
+-	//iounmap(virt);
++	/* iounmap(virt); */
+ }
+ 
+ void TimerCallback(unsigned long data)
+diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
+index b4a82eb001e1..648708ab44e6 100644
+--- a/drivers/staging/hv/storvsc_drv.c
++++ b/drivers/staging/hv/storvsc_drv.c
+@@ -41,16 +41,16 @@
+ 
+ #include "include/StorVscApi.h"
+ 
+-//
+-// #defines
+-//
+ 
+-//
+-// Data types
+-//
++/* #defines */
++
++
++
++/* Data types */
++
+ struct host_device_context {
+-    struct work_struct		host_rescan_work;  //must be 1st field
+-    struct device_context	*device_ctx; // point back to our device context
++    struct work_struct		host_rescan_work;  /* must be 1st field */
++    struct device_context	*device_ctx; /* point back to our device context */
+     struct kmem_cache               *request_pool;
+     unsigned int			port;
+     unsigned char			path;
+@@ -65,17 +65,17 @@ struct storvsc_cmd_request {
+ 	struct scatterlist	*bounce_sgl;
+ 
+ 	STORVSC_REQUEST		request;
+-	// !!!DO NOT ADD ANYTHING BELOW HERE!!!
+-	// The extension buffer falls right here and is pointed to by request.Extension;
++	/* !!!DO NOT ADD ANYTHING BELOW HERE!!! */
++	/* The extension buffer falls right here and is pointed to by request.Extension; */
+ };
+ 
+ struct storvsc_driver_context {
+-	// !! These must be the first 2 fields !!
++	/* !! These must be the first 2 fields !! */
+ 	struct driver_context	drv_ctx;
+ 	STORVSC_DRIVER_OBJECT	drv_obj;
+ };
+ 
+-// Static decl
++/* Static decl */
+ static int storvsc_probe(struct device *dev);
+ static int storvsc_queuecommand(struct scsi_cmnd *scmnd, void (*done)(struct scsi_cmnd *));
+ static int storvsc_device_alloc(struct scsi_device *);
+@@ -97,10 +97,10 @@ static int storvsc_get_chs(struct scsi_device *sdev, struct block_device * bdev,
+ 
+ static int storvsc_ringbuffer_size = STORVSC_RING_BUFFER_SIZE;
+ 
+-// The one and only one
++/* The one and only one */
+ static struct storvsc_driver_context g_storvsc_drv;
+ 
+-// Scsi driver
++/* Scsi driver */
+ static struct scsi_host_template scsi_driver = {
+ 	.module						= THIS_MODULE,
+ 	.name						= "storvsc_host_t",
+@@ -110,15 +110,15 @@ static struct scsi_host_template scsi_driver = {
+ 	.slave_alloc				= storvsc_device_alloc,
+ 	.slave_configure			= storvsc_device_configure,
+ 	.cmd_per_lun				= 1,
+-	.can_queue					= STORVSC_MAX_IO_REQUESTS*STORVSC_MAX_TARGETS, // 64 max_queue * 1 target
++	.can_queue					= STORVSC_MAX_IO_REQUESTS*STORVSC_MAX_TARGETS, /* 64 max_queue * 1 target */
+ 	.this_id					= -1,
+-	// no use setting to 0 since ll_blk_rw reset it to 1
+-	.sg_tablesize				= MAX_MULTIPAGE_BUFFER_COUNT,// currently 32
+-	// ENABLE_CLUSTERING allows mutiple physically contig bio_vecs to merge into 1 sg element. If set, we must
+-	// limit the max_segment_size to PAGE_SIZE, otherwise we may get 1 sg element that represents multiple
+-	// physically contig pfns (ie sg[x].length > PAGE_SIZE).
++	/* no use setting to 0 since ll_blk_rw reset it to 1 */
++	.sg_tablesize				= MAX_MULTIPAGE_BUFFER_COUNT,/* currently 32 */
++	/* ENABLE_CLUSTERING allows mutiple physically contig bio_vecs to merge into 1 sg element. If set, we must */
++	/* limit the max_segment_size to PAGE_SIZE, otherwise we may get 1 sg element that represents multiple */
++	/* physically contig pfns (ie sg[x].length > PAGE_SIZE). */
+ 	.use_clustering				= ENABLE_CLUSTERING,
+-	// Make sure we dont get a sg segment crosses a page boundary
++	/* Make sure we dont get a sg segment crosses a page boundary */
+ 	.dma_boundary				= PAGE_SIZE-1,
+ };
+ 
+@@ -143,7 +143,7 @@ int storvsc_drv_init(PFN_DRIVERINITIALIZE pfn_drv_init)
+ 	storvsc_drv_obj->RingBufferSize = storvsc_ringbuffer_size;
+ 	storvsc_drv_obj->OnHostRescan = storvsc_host_rescan;
+ 
+-	// Callback to client driver to complete the initialization
++	/* Callback to client driver to complete the initialization */
+ 	pfn_drv_init(&storvsc_drv_obj->Base);
+ 
+ 	DPRINT_INFO(STORVSC_DRV, "request extension size %u, max outstanding reqs %u", storvsc_drv_obj->RequestExtSize, storvsc_drv_obj->MaxOutstandingRequestsPerChannel);
+@@ -161,7 +161,7 @@ int storvsc_drv_init(PFN_DRIVERINITIALIZE pfn_drv_init)
+ 	drv_ctx->probe = storvsc_probe;
+ 	drv_ctx->remove = storvsc_remove;
+ 
+-	// The driver belongs to vmbus
++	/* The driver belongs to vmbus */
+ 	vmbus_child_driver_register(drv_ctx);
+ 
+ 	DPRINT_EXIT(STORVSC_DRV);
+@@ -174,7 +174,7 @@ static int storvsc_drv_exit_cb(struct device *dev, void *data)
+ {
+ 	struct device **curr = (struct device **)data;
+ 	*curr = dev;
+-	return 1; // stop iterating
++	return 1; /* stop iterating */
+ }
+ 
+ /*++
+@@ -197,13 +197,13 @@ void storvsc_drv_exit(void)
+ 	{
+ 		current_dev = NULL;
+ 
+-		// Get the device
++		/* Get the device */
+ 		driver_for_each_device(&drv_ctx->driver, NULL, (void*)¤t_dev, storvsc_drv_exit_cb);
+ 
+ 		if (current_dev == NULL)
+ 			break;
+ 
+-		// Initiate removal from the top-down
++		/* Initiate removal from the top-down */
+ 		device_unregister(current_dev);
+ 	}
+ 
+@@ -277,7 +277,7 @@ static int storvsc_probe(struct device *device)
+ 	}
+ 
+ 	device_info.PortNumber = host->host_no;
+-	// Call to the vsc driver to add the device
++	/* Call to the vsc driver to add the device */
+ 	ret = storvsc_drv_obj->Base.OnDeviceAdd(device_obj, (void*)&device_info);
+ 	if (ret != 0)
+ 	{
+@@ -289,15 +289,15 @@ static int storvsc_probe(struct device *device)
+ 		return -1;
+ 	}
+ 
+-	//host_device_ctx->port = device_info.PortNumber;
++	/* host_device_ctx->port = device_info.PortNumber; */
+ 	host_device_ctx->path = device_info.PathId;
+ 	host_device_ctx->target = device_info.TargetId;
+ 
+-	host->max_lun = STORVSC_MAX_LUNS_PER_TARGET;	// max # of devices per target
+-	host->max_id = STORVSC_MAX_TARGETS;			// max # of targets per channel
+-	host->max_channel = STORVSC_MAX_CHANNELS -1;	// max # of channels
++	host->max_lun = STORVSC_MAX_LUNS_PER_TARGET;	/* max # of devices per target */
++	host->max_id = STORVSC_MAX_TARGETS;			/* max # of targets per channel */
++	host->max_channel = STORVSC_MAX_CHANNELS -1;	/* max # of channels */
+ 
+-	// Register the HBA and start the scsi bus scan
++	/* Register the HBA and start the scsi bus scan */
+ 	ret = scsi_add_host(host, device);
+ 	if (ret != 0)
+ 	{
+@@ -350,11 +350,11 @@ static int storvsc_remove(struct device *device)
+ 		return -1;
+ 	}
+ 
+-	// Call to the vsc driver to let it know that the device is being removed
++	/* Call to the vsc driver to let it know that the device is being removed */
+ 	ret = storvsc_drv_obj->Base.OnDeviceRemove(device_obj);
+ 	if (ret != 0)
+ 	{
+-		// TODO:
++		/* TODO: */
+ 		DPRINT_ERR(STORVSC, "unable to remove vsc device (ret %d)", ret);
+ 	}
+ 
+@@ -397,11 +397,11 @@ static void storvsc_commmand_completion(STORVSC_REQUEST* request)
+ 
+ 	DPRINT_ENTER(STORVSC_DRV);
+ 
+-	if (cmd_request->bounce_sgl_count)// using bounce buffer
++	if (cmd_request->bounce_sgl_count)/* using bounce buffer */
+ 	{
+-		//printk("copy_from_bounce_buffer\n");
++		/* printk("copy_from_bounce_buffer\n"); */
+ 
+-		// FIXME: We can optimize on writes by just skipping this
++		/* FIXME: We can optimize on writes by just skipping this */
+ 		copy_from_bounce_buffer(scsi_sglist(scmnd), cmd_request->bounce_sgl, scsi_sg_count(scmnd));
+ 		destroy_bounce_buffer(cmd_request->bounce_sgl, cmd_request->bounce_sgl_count);
+ 	}
+@@ -424,7 +424,7 @@ static void storvsc_commmand_completion(STORVSC_REQUEST* request)
+ 	scmnd->host_scribble = NULL;
+ 	scmnd->scsi_done = NULL;
+ 
+-	// !!DO NOT MODIFY the scmnd after this call
++	/* !!DO NOT MODIFY the scmnd after this call */
+ 	scsi_done_fn(scmnd);
+ 
+ 	kmem_cache_free(host_device_ctx->request_pool, cmd_request);
+@@ -436,24 +436,24 @@ static int do_bounce_buffer(struct scatterlist *sgl, unsigned int sg_count)
+ {
+ 	int i=0;
+ 
+-	// No need to check
++	/* No need to check */
+ 	if (sg_count < 2)
+ 		return -1;
+ 
+-	// We have at least 2 sg entries
++	/* We have at least 2 sg entries */
+ 	for ( i=0; idevice->queue_depth,
+ 		scmnd->device->tagged_supported);
+ 
+-	// If retrying, no need to prep the cmd
++	/* If retrying, no need to prep the cmd */
+ 	if (scmnd->host_scribble)
+ 	{
+ 		ASSERT(scmnd->scsi_done != NULL);
+@@ -705,7 +705,7 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd, void (*done)(struct scs
+ 		return SCSI_MLQUEUE_DEVICE_BUSY;
+ 	}
+ 
+-	// Setup the cmd request
++	/* Setup the cmd request */
+ 	cmd_request->bounce_sgl_count = 0;
+ 	cmd_request->bounce_sgl = NULL;
+ 	cmd_request->cmd = scmnd;
+@@ -717,7 +717,7 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd, void (*done)(struct scs
+ 	request->Extension = (void*)((unsigned long)cmd_request + request_size);
+ 	DPRINT_DBG(STORVSC_DRV, "req %p size %d ext %d", request, request_size, storvsc_drv_obj->RequestExtSize);
+ 
+-	// Build the SRB
++	/* Build the SRB */
+ 	switch(scmnd->sc_data_direction)
+ 	{
+ 	case DMA_TO_DEVICE:
+@@ -732,9 +732,9 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd, void (*done)(struct scs
+ 	}
+ 
+ 	request->OnIOCompletion = storvsc_commmand_completion;
+-	request->Context = cmd_request;//scmnd;
++	request->Context = cmd_request;/* scmnd; */
+ 
+-	//request->PortId = scmnd->device->channel;
++	/* request->PortId = scmnd->device->channel; */
+ 	request->Host = host_device_ctx->port;
+ 	request->Bus = scmnd->device->channel;
+ 	request->TargetId = scmnd->device->id;
+@@ -753,7 +753,7 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd, void (*done)(struct scs
+ 	{
+ 		sgl = (struct scatterlist*)scsi_sglist(scmnd);
+ 
+-		// check if we need to bounce the sgl
++		/* check if we need to bounce the sgl */
+ 		if (do_bounce_buffer(sgl, scsi_sg_count(scmnd)) != -1)
+ 		{
+ 			DPRINT_INFO(STORVSC_DRV, "need to bounce buffer for this scmnd %p", scmnd);
+@@ -771,9 +771,9 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd, void (*done)(struct scs
+ 
+ 			cmd_request->bounce_sgl_count = ALIGN_UP(scsi_bufflen(scmnd), PAGE_SIZE) >> PAGE_SHIFT;
+ 
+-			//printk("bouncing buffer allocated %p original buffer %p\n", bounce_sgl, sgl);
+-			//printk("copy_to_bounce_buffer\n");
+-			// FIXME: We can optimize on reads by just skipping this
++			/* printk("bouncing buffer allocated %p original buffer %p\n", bounce_sgl, sgl); */
++			/* printk("copy_to_bounce_buffer\n"); */
++			/* FIXME: We can optimize on reads by just skipping this */
+ 			copy_to_bounce_buffer(sgl, cmd_request->bounce_sgl, scsi_sg_count(scmnd));
+ 
+ 			sgl = cmd_request->bounce_sgl;
+@@ -801,15 +801,15 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd, void (*done)(struct scs
+ 
+ retry_request:
+ 
+-	// Invokes the vsc to start an IO
++	/* Invokes the vsc to start an IO */
+ 	ret = storvsc_drv_obj->OnIORequest(&device_ctx->device_obj, &cmd_request->request);
+-	if (ret == -1) // no more space
++	if (ret == -1) /* no more space */
+ 	{
+ 		DPRINT_ERR(STORVSC_DRV, "scmnd (%p) - queue FULL...marking queue busy", scmnd);
+ 
+ 		if (cmd_request->bounce_sgl_count)
+ 		{
+-			// FIXME: We can optimize on writes by just skipping this
++			/* FIXME: We can optimize on writes by just skipping this */
+ 			copy_from_bounce_buffer(scsi_sglist(scmnd), cmd_request->bounce_sgl, scsi_sg_count(scmnd));
+ 			destroy_bounce_buffer(cmd_request->bounce_sgl, cmd_request->bounce_sgl_count);
+ 		}
+@@ -829,7 +829,7 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd, void (*done)(struct scs
+ 
+ static int storvsc_merge_bvec(struct request_queue *q, struct bvec_merge_data *bmd, struct bio_vec *bvec)
+ {
+-	return bvec->bv_len; //checking done by caller.
++	return bvec->bv_len; /* checking done by caller. */
+ }
+ 
+ /*++
+@@ -842,7 +842,7 @@ Desc:	Configure the specified scsi device
+ static int storvsc_device_alloc(struct scsi_device *sdevice)
+ {
+ 	DPRINT_DBG(STORVSC_DRV, "sdev (%p) - setting device flag to %d", sdevice, BLIST_SPARSELUN);
+-	// This enables luns to be located sparsely. Otherwise, we may not discovered them.
++	/* This enables luns to be located sparsely. Otherwise, we may not discovered them. */
+ 	sdevice->sdev_bflags |= BLIST_SPARSELUN | BLIST_LARGELUN;
+ 	return 0;
+ }
+@@ -861,7 +861,7 @@ static int storvsc_device_configure(struct scsi_device *sdevice)
+ 	blk_queue_merge_bvec(sdevice->request_queue, storvsc_merge_bvec);
+ 
+ 	blk_queue_bounce_limit(sdevice->request_queue, BLK_BOUNCE_ANY);
+-	//sdevice->timeout = (2000 * HZ);//(75 * HZ);
++	/* sdevice->timeout = (2000 * HZ);//(75 * HZ); */
+ 
+ 	return 0;
+ }
+@@ -887,7 +887,7 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
+ 
+ 	DPRINT_INFO(STORVSC_DRV, "sdev (%p) dev obj (%p) - host resetting...", scmnd->device, &device_ctx->device_obj);
+ 
+-	// Invokes the vsc to reset the host/bus
++	/* Invokes the vsc to reset the host/bus */
+ 	ASSERT(storvsc_drv_obj->OnHostReset);
+ 	ret = storvsc_drv_obj->OnHostReset(&device_ctx->device_obj);
+ 	if (ret != 0)
+@@ -945,12 +945,12 @@ static void storvsc_host_rescan_callback(struct work_struct *work)
+ 
+ 	DPRINT_INFO(STORVSC_DRV, "rescanning host for new scsi devices...", device_obj, host_device_ctx->target, host_device_ctx->path);
+ 
+-	// Rescan for new device
++	/* Rescan for new device */
+ 	scsi_scan_target(&host->shost_gendev, host_device_ctx->path, host_device_ctx->target, SCAN_WILD_CARD, 1);
+ 
+ 	DPRINT_INFO(STORVSC_DRV, "rescanning host for removed scsi device...");
+ 
+-	// Use the 1st device to send the report luns cmd
++	/* Use the 1st device to send the report luns cmd */
+ 	shost_for_each_device(sdev, host)
+ 	{
+ 		lun_count=STORVSC_MAX_LUNS_PER_TARGET;
+@@ -968,12 +968,12 @@ static void storvsc_host_rescan_callback(struct work_struct *work)
+ 		DPRINT_INFO(STORVSC_DRV, "%d) lun %u", i, lun_list[i]);
+ 	}
+ 
+-	// Rescan for devices that may have been removed.
+-	// We do not have to worry that new devices may have been added since
+-	// this callback is serialized by the workqueue ie add/remove are done here.
++	/* Rescan for devices that may have been removed. */
++	/* We do not have to worry that new devices may have been added since */
++	/* this callback is serialized by the workqueue ie add/remove are done here. */
+ 	shost_for_each_device(sdev, host)
+ 	{
+-		// See if this device is still here
++		/* See if this device is still here */
+ 		found = 0;
+ 		for (i=0; ilun);
+ 
+-		// make sure it is not removed from underneath us
++		/* make sure it is not removed from underneath us */
+ 		if (!scsi_device_get(sdevs_remove_list[i]))
+ 		{
+ 			scsi_remove_device(sdevs_remove_list[i]);
+@@ -1021,7 +1021,7 @@ static int storvsc_report_luns(struct scsi_device *sdev, unsigned int luns[], un
+ 	unsigned char *data;
+ 	struct scsi_sense_hdr sshdr;
+ 	unsigned char cmd[16]={0};
+-	unsigned int report_len = 8*(STORVSC_MAX_LUNS_PER_TARGET+1); // Add 1 to cover the report_lun header
++	unsigned int report_len = 8*(STORVSC_MAX_LUNS_PER_TARGET+1); /* Add 1 to cover the report_lun header */
+ 	unsigned long long *report_luns;
+ 	const unsigned int in_lun_count = *lun_count;
+ 
+@@ -1035,7 +1035,7 @@ static int storvsc_report_luns(struct scsi_device *sdev, unsigned int luns[], un
+ 
+ 	cmd[0] = REPORT_LUNS;
+ 
+-	// cmd length
++	/* cmd length */
+ 	*(unsigned int*)&cmd[6] = cpu_to_be32(report_len);
+ 
+ 	result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, (unsigned char*)report_luns, report_len, &sshdr, 30*HZ, 3, NULL);
+@@ -1045,7 +1045,7 @@ static int storvsc_report_luns(struct scsi_device *sdev, unsigned int luns[], un
+ 		return -EBUSY;
+ 	}
+ 
+-	// get the length from the first four bytes
++	/* get the length from the first four bytes */
+ 	report_len = be32_to_cpu(*(unsigned int*)&report_luns[0]);
+ 
+ 	num_luns = (report_len / sizeof(unsigned long long));
+@@ -1059,7 +1059,7 @@ static int storvsc_report_luns(struct scsi_device *sdev, unsigned int luns[], un
+ 
+ 	DPRINT_DBG(STORVSC_DRV, "report luns on scsi device (%p) found %u luns ", sdev, num_luns);
+ 
+-	// lun id starts at 1
++	/* lun id starts at 1 */
+ 	for (i=1; i< num_luns+1; i++)
+ 	{
+ 		lun = 0;
+@@ -1088,8 +1088,8 @@ static void storvsc_host_rescan(DEVICE_OBJECT* device_obj)
+ 
+ 	DPRINT_INFO(STORVSC_DRV, "initiating rescan on dev obj (%p) target (%u) bus (%u)...", device_obj, host_device_ctx->target, host_device_ctx->path);
+ 
+-	// We need to queue this since the scanning may block and the caller may be in an intr context
+-	//scsi_queue_work(host, &host_device_ctx->host_rescan_work);
++	/* We need to queue this since the scanning may block and the caller may be in an intr context */
++	/* scsi_queue_work(host, &host_device_ctx->host_rescan_work); */
+ 	schedule_work(&host_device_ctx->host_rescan_work);
+ 	DPRINT_EXIT(STORVSC_DRV);
+ }
+@@ -1114,17 +1114,17 @@ static int storvsc_get_chs(struct scsi_device *sdev, struct block_device * bdev,
+         heads = 16;
+ 
+ 		cylinder_times_heads = total_sectors;
+-		rem = sector_div(cylinder_times_heads, sectors_per_track); // sector_div stores the quotient in cylinder_times_heads
++		rem = sector_div(cylinder_times_heads, sectors_per_track); /* sector_div stores the quotient in cylinder_times_heads */
+     }
+ 	else
+ 	{
+         sectors_per_track = 17;
+ 
+ 		cylinder_times_heads = total_sectors;
+-        rem = sector_div(cylinder_times_heads, sectors_per_track); 	// sector_div stores the quotient in cylinder_times_heads
++        rem = sector_div(cylinder_times_heads, sectors_per_track); 	/* sector_div stores the quotient in cylinder_times_heads */
+ 
+ 		temp = cylinder_times_heads + 1023;
+-		rem = sector_div(temp, 1024); 	// sector_div stores the quotient in temp
++		rem = sector_div(temp, 1024); 	/* sector_div stores the quotient in temp */
+ 
+ 		heads = temp;
+ 
+@@ -1137,7 +1137,7 @@ static int storvsc_get_chs(struct scsi_device *sdev, struct block_device * bdev,
+             heads = 16;
+ 
+ 			cylinder_times_heads = total_sectors;
+-            rem = sector_div(cylinder_times_heads, sectors_per_track); // sector_div stores the quotient in cylinder_times_heads
++            rem = sector_div(cylinder_times_heads, sectors_per_track); /* sector_div stores the quotient in cylinder_times_heads */
+         }
+ 
+         if (cylinder_times_heads >= (heads * 1024)) {
+@@ -1145,12 +1145,12 @@ static int storvsc_get_chs(struct scsi_device *sdev, struct block_device * bdev,
+             heads = 16;
+ 
+ 			cylinder_times_heads = total_sectors;
+-            rem = sector_div(cylinder_times_heads, sectors_per_track); // sector_div stores the quotient in cylinder_times_heads
++            rem = sector_div(cylinder_times_heads, sectors_per_track); /* sector_div stores the quotient in cylinder_times_heads */
+         }
+     }
+ 
+ 	temp = cylinder_times_heads;
+-    rem = sector_div(temp, heads); // sector_div stores the quotient in temp
++    rem = sector_div(temp, heads); /* sector_div stores the quotient in temp */
+ 	cylinders = temp;
+ 
+ 	info[0] = heads;
+@@ -1193,4 +1193,4 @@ module_param(storvsc_ringbuffer_size, int, S_IRUGO);
+ module_init(storvsc_init);
+ module_exit(storvsc_exit);
+ 
+-// eof
++/* eof */
+diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c
+index e615610ffbfb..a86e4043d174 100644
+--- a/drivers/staging/hv/vmbus_drv.c
++++ b/drivers/staging/hv/vmbus_drv.c
+@@ -32,22 +32,22 @@
+ #include "include/logging.h"
+ #include "include/vmbus.h"
+ 
+-//
+-// Defines
+-//
+ 
+-// FIXME! We need to do this dynamically for PIC and APIC system
++/* Defines */
++
++
++/* FIXME! We need to do this dynamically for PIC and APIC system */
+ #define VMBUS_IRQ				0x5
+ #define VMBUS_IRQ_VECTOR     IRQ5_VECTOR
+-//
+-// Data types
+-//
+ 
+-// Main vmbus driver data structure
++/* Data types */
++
++
++/* Main vmbus driver data structure */
+ struct vmbus_driver_context {
+-	// !! These must be the first 2 fields !!
+-	// The driver field is not used in here. Instead, the bus field is
+-	// used to represent the driver
++	/* !! These must be the first 2 fields !! */
++	/* The driver field is not used in here. Instead, the bus field is */
++	/* used to represent the driver */
+ 	struct driver_context	drv_ctx;
+ 	VMBUS_DRIVER_OBJECT		drv_obj;
+ 
+@@ -55,13 +55,13 @@ struct vmbus_driver_context {
+ 	struct tasklet_struct	msg_dpc;
+ 	struct tasklet_struct	event_dpc;
+ 
+-	// The bus root device
++	/* The bus root device */
+ 	struct device_context	device_ctx;
+ };
+ 
+-//
+-// Static decl
+-//
++
++/* Static decl */
++
+ static int vmbus_match(struct device *device, struct device_driver *driver);
+ static int vmbus_probe(struct device *device);
+ static int vmbus_remove(struct device *device);
+@@ -81,26 +81,26 @@ static int vmbus_child_device_register(DEVICE_OBJECT* root_device_obj, DEVICE_OB
+ static void vmbus_child_device_unregister(DEVICE_OBJECT* child_device_obj);
+ static void vmbus_child_device_get_info(DEVICE_OBJECT *device_obj, DEVICE_INFO *device_info);
+ 
+-//static ssize_t vmbus_show_class_id(struct device *dev, struct device_attribute *attr, char *buf);
+-//static ssize_t vmbus_show_device_id(struct device *dev, struct device_attribute *attr, char *buf);
++/* static ssize_t vmbus_show_class_id(struct device *dev, struct device_attribute *attr, char *buf); */
++/* static ssize_t vmbus_show_device_id(struct device *dev, struct device_attribute *attr, char *buf); */
+ 
+ static ssize_t vmbus_show_device_attr(struct device *dev, struct device_attribute *dev_attr, char *buf);
+ 
+-//
+-// Global
+-//
+ 
+-// Global logging setting
++/* Global */
++
+ 
+-//unsigned int vmbus_loglevel= (((VMBUS | VMBUS_DRV)<<16) | DEBUG_LVL_ENTEREXIT);
+-//unsigned int vmbus_loglevel= (ALL_MODULES << 16 | DEBUG_LVL_ENTEREXIT);
++/* Global logging setting */
++
++/* unsigned int vmbus_loglevel= (((VMBUS | VMBUS_DRV)<<16) | DEBUG_LVL_ENTEREXIT); */
++/* unsigned int vmbus_loglevel= (ALL_MODULES << 16 | DEBUG_LVL_ENTEREXIT); */
+ unsigned int vmbus_loglevel= (ALL_MODULES << 16 | INFO_LVL);
+ EXPORT_SYMBOL(vmbus_loglevel);
+ 
+ static int vmbus_irq = VMBUS_IRQ;
+ 
+-// Setup /proc/sys/bus/vmbus/vmbus_loglevel
+-// Allow usage of sysctl cmd to set the logging level
++/* Setup /proc/sys/bus/vmbus/vmbus_loglevel */
++/* Allow usage of sysctl cmd to set the logging level */
+ static struct ctl_table_header *vmbus_ctl_table_hdr;
+ 
+ static ctl_table vmbus_dev_ctl_table[] = {
+@@ -129,9 +129,9 @@ static ctl_table vmus_root_ctl_table[] = {
+ 	{ }
+ };
+ 
+-//
+-// Set up per device attributes in /sys/bus/vmbus/devices/
+-//
++
++/* Set up per device attributes in /sys/bus/vmbus/devices/ */
++
+ static struct device_attribute vmbus_device_attrs[] = {
+ 	__ATTR(id, S_IRUGO, vmbus_show_device_attr, NULL),
+ 	__ATTR(state, S_IRUGO, vmbus_show_device_attr, NULL),
+@@ -161,7 +161,7 @@ static struct device_attribute vmbus_device_attrs[] = {
+ 	__ATTR_NULL
+ };
+ 
+-// The one and only one
++/* The one and only one */
+ static struct vmbus_driver_context g_vmbus_drv={
+ 	.bus.name	= "vmbus",
+ 	.bus.match	= vmbus_match,
+@@ -172,9 +172,9 @@ static struct vmbus_driver_context g_vmbus_drv={
+ 	.bus.dev_attrs = vmbus_device_attrs,
+ };
+ 
+-//
+-// Routines
+-//
++
++/* Routines */
++
+ 
+ 
+ /*++
+@@ -299,15 +299,15 @@ Name:	vmbus_show_class_id()
+ Desc:	Show the device class id in sysfs
+ 
+ --*/
+-//static ssize_t vmbus_show_class_id(struct device *dev, struct device_attribute *attr, char *buf)
+-//{
+-//	struct device_context *device_ctx = device_to_device_context(dev);
+-//	return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x}\n",
+-//		device_ctx->class_id[3], device_ctx->class_id[2], device_ctx->class_id[1], device_ctx->class_id[0],
+-//		device_ctx->class_id[5], device_ctx->class_id[4],
+-//		device_ctx->class_id[7], device_ctx->class_id[6],
+-//		device_ctx->class_id[8], device_ctx->class_id[9], device_ctx->class_id[10], device_ctx->class_id[11], device_ctx->class_id[12], device_ctx->class_id[13], device_ctx->class_id[14], device_ctx->class_id[15]);
+-//}
++/* static ssize_t vmbus_show_class_id(struct device *dev, struct device_attribute *attr, char *buf) */
++/* { */
++/* struct device_context *device_ctx = device_to_device_context(dev); */
++/* return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x}\n", */
++/*	device_ctx->class_id[3], device_ctx->class_id[2], device_ctx->class_id[1], device_ctx->class_id[0], */
++/*	device_ctx->class_id[5], device_ctx->class_id[4], */
++/*	device_ctx->class_id[7], device_ctx->class_id[6], */
++/*	device_ctx->class_id[8], device_ctx->class_id[9], device_ctx->class_id[10], device_ctx->class_id[11], device_ctx->class_id[12], device_ctx->class_id[13], device_ctx->class_id[14], device_ctx->class_id[15]); */
++/* } */
+ 
+ /*++
+ 
+@@ -316,15 +316,15 @@ Name:	vmbus_show_device_id()
+ Desc:	Show the device instance id in sysfs
+ 
+ --*/
+-//static ssize_t vmbus_show_device_id(struct device *dev, struct device_attribute *attr, char *buf)
+-//{
+-//	struct device_context *device_ctx = device_to_device_context(dev);
+-//	return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x}\n",
+-//		device_ctx->device_id[3], device_ctx->device_id[2], device_ctx->device_id[1], device_ctx->device_id[0],
+-//		device_ctx->device_id[5], device_ctx->device_id[4],
+-//		device_ctx->device_id[7], device_ctx->device_id[6],
+-//		device_ctx->device_id[8], device_ctx->device_id[9], device_ctx->device_id[10], device_ctx->device_id[11], device_ctx->device_id[12], device_ctx->device_id[13], device_ctx->device_id[14], device_ctx->device_id[15]);
+-//}
++/* static ssize_t vmbus_show_device_id(struct device *dev, struct device_attribute *attr, char *buf) */
++/* { */
++/* struct device_context *device_ctx = device_to_device_context(dev); */
++/* return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x}\n", */
++/*	device_ctx->device_id[3], device_ctx->device_id[2], device_ctx->device_id[1], device_ctx->device_id[0], */
++/*	device_ctx->device_id[5], device_ctx->device_id[4], */
++/*	device_ctx->device_id[7], device_ctx->device_id[6], */
++/*	device_ctx->device_id[8], device_ctx->device_id[9], device_ctx->device_id[10], device_ctx->device_id[11], device_ctx->device_id[12], device_ctx->device_id[13], device_ctx->device_id[14], device_ctx->device_id[15]); */
++/* } */
+ 
+ /*++
+ 
+@@ -351,13 +351,13 @@ int vmbus_bus_init(PFN_DRIVERINITIALIZE pfn_drv_init)
+ 
+ 	DPRINT_ENTER(VMBUS_DRV);
+ 
+-	// Set this up to allow lower layer to callback to add/remove child devices on the bus
++	/* Set this up to allow lower layer to callback to add/remove child devices on the bus */
+ 	vmbus_drv_obj->OnChildDeviceCreate = vmbus_child_device_create;
+ 	vmbus_drv_obj->OnChildDeviceDestroy = vmbus_child_device_destroy;
+ 	vmbus_drv_obj->OnChildDeviceAdd = vmbus_child_device_register;
+ 	vmbus_drv_obj->OnChildDeviceRemove = vmbus_child_device_unregister;
+ 
+-	// Call to bus driver to initialize
++	/* Call to bus driver to initialize */
+ 	ret = pfn_drv_init(&vmbus_drv_obj->Base);
+ 	if (ret != 0)
+ 	{
+@@ -365,7 +365,7 @@ int vmbus_bus_init(PFN_DRIVERINITIALIZE pfn_drv_init)
+ 		goto cleanup;
+ 	}
+ 
+-	// Sanity checks
++	/* Sanity checks */
+ 	if (!vmbus_drv_obj->Base.OnDeviceAdd)
+ 	{
+ 		DPRINT_ERR(VMBUS_DRV, "OnDeviceAdd() routine not set");
+@@ -375,14 +375,14 @@ int vmbus_bus_init(PFN_DRIVERINITIALIZE pfn_drv_init)
+ 
+ 	vmbus_drv_ctx->bus.name = vmbus_drv_obj->Base.name;
+ 
+-	// Initialize the bus context
++	/* Initialize the bus context */
+ 	tasklet_init(&vmbus_drv_ctx->msg_dpc, vmbus_msg_dpc, (unsigned long)vmbus_drv_obj);
+ 	tasklet_init(&vmbus_drv_ctx->event_dpc, vmbus_event_dpc, (unsigned long)vmbus_drv_obj);
+ 
+-	// Now, register the bus driver with LDM
++	/* Now, register the bus driver with LDM */
+ 	bus_register(&vmbus_drv_ctx->bus);
+ 
+-	// Get the interrupt resource
++	/* Get the interrupt resource */
+ 	ret = request_irq(vmbus_irq,
+ 			  vmbus_isr,
+ 			  IRQF_SAMPLE_RANDOM,
+@@ -402,7 +402,7 @@ int vmbus_bus_init(PFN_DRIVERINITIALIZE pfn_drv_init)
+ 
+ 	DPRINT_INFO(VMBUS_DRV, "irq 0x%x vector 0x%x", vmbus_irq, vector);
+ 
+-	// Call to bus driver to add the root device
++	/* Call to bus driver to add the root device */
+ 	memset(dev_ctx, 0, sizeof(struct device_context));
+ 
+ 	ret = vmbus_drv_obj->Base.OnDeviceAdd(&dev_ctx->device_obj, &vector);
+@@ -417,19 +417,19 @@ int vmbus_bus_init(PFN_DRIVERINITIALIZE pfn_drv_init)
+ 		ret = -1;
+ 		goto cleanup;
+ 	}
+-	//strcpy(dev_ctx->device.bus_id, dev_ctx->device_obj.name);
++	/* strcpy(dev_ctx->device.bus_id, dev_ctx->device_obj.name); */
+ 	dev_set_name(&dev_ctx->device, "vmbus_0_0");
+ 	memcpy(&dev_ctx->class_id, &dev_ctx->device_obj.deviceType, sizeof(GUID));
+ 	memcpy(&dev_ctx->device_id, &dev_ctx->device_obj.deviceInstance, sizeof(GUID));
+ 
+-	// No need to bind a driver to the root device.
++	/* No need to bind a driver to the root device. */
+ 	dev_ctx->device.parent = NULL;
+-	dev_ctx->device.bus = &vmbus_drv_ctx->bus; //NULL; // vmbus_remove() does not get invoked
++	dev_ctx->device.bus = &vmbus_drv_ctx->bus; /* NULL; vmbus_remove() does not get invoked */
+ 
+-	// Setup the device dispatch table
++	/* Setup the device dispatch table */
+ 	dev_ctx->device.release = vmbus_bus_release;
+ 
+-	// Setup the bus as root device
++	/* Setup the bus as root device */
+ 	device_register(&dev_ctx->device);
+ 
+ 	vmbus_drv_obj->GetChannelOffers();
+@@ -457,14 +457,14 @@ void vmbus_bus_exit(void)
+ 
+ 	DPRINT_ENTER(VMBUS_DRV);
+ 
+-	// Remove the root device
++	/* Remove the root device */
+ 	if (vmbus_drv_obj->Base.OnDeviceRemove)
+ 		vmbus_drv_obj->Base.OnDeviceRemove(&dev_ctx->device_obj);
+ 
+ 	if (vmbus_drv_obj->Base.OnCleanup)
+ 		vmbus_drv_obj->Base.OnCleanup(&vmbus_drv_obj->Base);
+ 
+-	// Unregister the root bus device
++	/* Unregister the root bus device */
+ 	device_unregister(&dev_ctx->device);
+ 
+ 	bus_unregister(&vmbus_drv_ctx->bus);
+@@ -494,7 +494,7 @@ void vmbus_child_driver_register(struct driver_context* driver_ctx)
+ 
+ 	DPRINT_INFO(VMBUS_DRV, "child driver (%p) registering - name %s", driver_ctx, driver_ctx->driver.name);
+ 
+-	// The child driver on this vmbus
++	/* The child driver on this vmbus */
+ 	driver_ctx->driver.bus = &g_vmbus_drv.bus;
+ 
+ 	driver_register(&driver_ctx->driver);
+@@ -573,7 +573,7 @@ static DEVICE_OBJECT* vmbus_child_device_create(GUID type, GUID instance, void*
+ 
+ 	DPRINT_ENTER(VMBUS_DRV);
+ 
+-	// Allocate the new child device
++	/* Allocate the new child device */
+ 	child_device_ctx = kzalloc(sizeof(struct device_context), GFP_KERNEL);
+ 	if (!child_device_ctx)
+ 	{
+@@ -620,9 +620,9 @@ static int vmbus_child_device_register(DEVICE_OBJECT* root_device_obj, DEVICE_OB
+ 	DPRINT_ENTER(VMBUS_DRV);
+ 
+ 	DPRINT_DBG(VMBUS_DRV, "child device (%p) registering", child_device_ctx);
+-	//
+-	// Make sure we are not registered already
+-	//
++
++	/* Make sure we are not registered already */
++
+ 	if (strlen(dev_name(&child_device_ctx->device)) != 0)
+ 	{
+ 		DPRINT_ERR(VMBUS_DRV, "child device (%p) already registered - busid %s", child_device_ctx, dev_name(&child_device_ctx->device));
+@@ -631,19 +631,19 @@ static int vmbus_child_device_register(DEVICE_OBJECT* root_device_obj, DEVICE_OB
+ 		goto Cleanup;
+ 	}
+ 
+-	// Set the device bus id. Otherwise, device_register()will fail.
++	/* Set the device bus id. Otherwise, device_register()will fail. */
+ 	dev_set_name(&child_device_ctx->device, "vmbus_0_%d", InterlockedIncrement(&device_num));
+ 
+-	// The new device belongs to this bus
+-	child_device_ctx->device.bus = &g_vmbus_drv.bus; //device->dev.bus;
++	/* The new device belongs to this bus */
++	child_device_ctx->device.bus = &g_vmbus_drv.bus; /* device->dev.bus; */
+ 	child_device_ctx->device.parent = &root_device_ctx->device;
+ 	child_device_ctx->device.release = vmbus_device_release;
+ 
+-	// Register with the LDM. This will kick off the driver/device binding...which will
+-	// eventually call vmbus_match() and vmbus_probe()
++	/* Register with the LDM. This will kick off the driver/device binding...which will */
++	/* eventually call vmbus_match() and vmbus_probe() */
+ 	ret = device_register(&child_device_ctx->device);
+ 
+-	// vmbus_probe() error does not get propergate to device_register().
++	/* vmbus_probe() error does not get propergate to device_register(). */
+ 	ret = child_device_ctx->probe_error;
+ 
+ 	if (ret)
+@@ -672,8 +672,8 @@ static void vmbus_child_device_unregister(DEVICE_OBJECT* device_obj)
+ 
+ 	DPRINT_INFO(VMBUS_DRV, "unregistering child device (%p)", &device_ctx->device);
+ 
+-	// Kick off the process of unregistering the device.
+-	// This will call vmbus_remove() and eventually vmbus_device_release()
++	/* Kick off the process of unregistering the device. */
++	/* This will call vmbus_remove() and eventually vmbus_device_release() */
+ 	device_unregister(&device_ctx->device);
+ 
+ 	DPRINT_INFO(VMBUS_DRV, "child device (%p) unregistered", &device_ctx->device);
+@@ -770,11 +770,11 @@ static int vmbus_match(struct device *device, struct device_driver *driver)
+ 
+ 	DPRINT_ENTER(VMBUS_DRV);
+ 
+-	// We found our driver ?
++	/* We found our driver ? */
+ 	if (memcmp(&device_ctx->class_id, &driver_ctx->class_id, sizeof(GUID)) == 0)
+ 	{
+-		// !! NOTE: The driver_ctx is not a vmbus_drv_ctx. We typecast it here to access the
+-		// DRIVER_OBJECT field
++		/* !! NOTE: The driver_ctx is not a vmbus_drv_ctx. We typecast it here to access the */
++		/* DRIVER_OBJECT field */
+ 		struct vmbus_driver_context *vmbus_drv_ctx = (struct vmbus_driver_context*)driver_ctx;
+ 		device_ctx->device_obj.Driver = &vmbus_drv_ctx->drv_obj.Base;
+ 		DPRINT_INFO(VMBUS_DRV, "device object (%p) set to driver object (%p)", &device_ctx->device_obj, device_ctx->device_obj.Driver);
+@@ -804,11 +804,11 @@ static void vmbus_probe_failed_cb(struct work_struct *context)
+ 
+ 	DPRINT_ENTER(VMBUS_DRV);
+ 
+-	// Kick off the process of unregistering the device.
+-	// This will call vmbus_remove() and eventually vmbus_device_release()
++	/* Kick off the process of unregistering the device. */
++	/* This will call vmbus_remove() and eventually vmbus_device_release() */
+ 	device_unregister(&device_ctx->device);
+ 
+-	//put_device(&device_ctx->device);
++	/* put_device(&device_ctx->device); */
+ 	DPRINT_EXIT(VMBUS_DRV);
+ }
+ 
+@@ -828,7 +828,7 @@ static int vmbus_probe(struct device *child_device)
+ 
+ 	DPRINT_ENTER(VMBUS_DRV);
+ 
+-	// Let the specific open-source driver handles the probe if it can
++	/* Let the specific open-source driver handles the probe if it can */
+ 	if (driver_ctx->probe)
+ 	{
+ 		ret = device_ctx->probe_error = driver_ctx->probe(child_device);
+@@ -865,10 +865,10 @@ static int vmbus_remove(struct device *child_device)
+ 
+ 	DPRINT_ENTER(VMBUS_DRV);
+ 
+-	// Special case root bus device
++	/* Special case root bus device */
+ 	if (child_device->parent == NULL)
+ 	{
+-		// No-op since it is statically defined and handle in vmbus_bus_exit()
++		/* No-op since it is statically defined and handle in vmbus_bus_exit() */
+ 		DPRINT_EXIT(VMBUS_DRV);
+ 		return 0;
+ 	}
+@@ -877,7 +877,7 @@ static int vmbus_remove(struct device *child_device)
+ 	{
+ 		driver_ctx = driver_to_driver_context(child_device->driver);
+ 
+-		// Let the specific open-source driver handles the removal if it can
++		/* Let the specific open-source driver handles the removal if it can */
+ 		if (driver_ctx->remove)
+ 		{
+ 			ret = driver_ctx->remove(child_device);
+@@ -911,15 +911,15 @@ static void vmbus_shutdown(struct device *child_device)
+ 
+ 	DPRINT_ENTER(VMBUS_DRV);
+ 
+-	// Special case root bus device
++	/* Special case root bus device */
+ 	if (child_device->parent == NULL)
+ 	{
+-		// No-op since it is statically defined and handle in vmbus_bus_exit()
++		/* No-op since it is statically defined and handle in vmbus_bus_exit() */
+ 		DPRINT_EXIT(VMBUS_DRV);
+ 		return;
+ 	}
+ 
+-	// The device may not be attached yet
++	/* The device may not be attached yet */
+ 	if (!child_device->driver)
+ 	{
+ 		DPRINT_EXIT(VMBUS_DRV);
+@@ -928,7 +928,7 @@ static void vmbus_shutdown(struct device *child_device)
+ 
+ 	driver_ctx = driver_to_driver_context(child_device->driver);
+ 
+-	// Let the specific open-source driver handles the removal if it can
++	/* Let the specific open-source driver handles the removal if it can */
+ 	if (driver_ctx->shutdown)
+ 	{
+ 		driver_ctx->shutdown(child_device);
+@@ -965,10 +965,10 @@ static void vmbus_device_release(struct device *device)
+ 
+ 	DPRINT_ENTER(VMBUS_DRV);
+ 
+-	//vmbus_child_device_destroy(&device_ctx->device_obj);
++	/* vmbus_child_device_destroy(&device_ctx->device_obj); */
+ 	kfree(device_ctx);
+ 
+-	// !!DO NOT REFERENCE device_ctx anymore at this point!!
++	/* !!DO NOT REFERENCE device_ctx anymore at this point!! */
+ 
+ 	DPRINT_EXIT(VMBUS_DRV);
+ 
+@@ -990,7 +990,7 @@ static void vmbus_msg_dpc(unsigned long data)
+ 
+ 	ASSERT(vmbus_drv_obj->OnMsgDpc != NULL);
+ 
+-	// Call to bus driver to handle interrupt
++	/* Call to bus driver to handle interrupt */
+ 	vmbus_drv_obj->OnMsgDpc(&vmbus_drv_obj->Base);
+ 
+ 	DPRINT_EXIT(VMBUS_DRV);
+@@ -1011,7 +1011,7 @@ static void vmbus_event_dpc(unsigned long data)
+ 
+ 	ASSERT(vmbus_drv_obj->OnEventDpc != NULL);
+ 
+-	// Call to bus driver to handle interrupt
++	/* Call to bus driver to handle interrupt */
+ 	vmbus_drv_obj->OnEventDpc(&vmbus_drv_obj->Base);
+ 
+ 	DPRINT_EXIT(VMBUS_DRV);
+@@ -1033,10 +1033,10 @@ static irqreturn_t vmbus_isr(int irq, void* dev_id)
+ 
+ 	ASSERT(vmbus_driver_obj->OnIsr != NULL);
+ 
+-	// Call to bus driver to handle interrupt
++	/* Call to bus driver to handle interrupt */
+ 	ret = vmbus_driver_obj->OnIsr(&vmbus_driver_obj->Base);
+ 
+-	// Schedules a dpc if necessary
++	/* Schedules a dpc if necessary */
+ 	if (ret > 0)
+ 	{
+ 		if (test_bit(0, (unsigned long*)&ret))
+@@ -1078,7 +1078,7 @@ static int __init vmbus_init(void)
+ 	DPRINT_INFO(VMBUS_DRV,
+ 		"Vmbus initializing.... current log level 0x%x (%x,%x)",
+ 		vmbus_loglevel, HIWORD(vmbus_loglevel), LOWORD(vmbus_loglevel));
+-//Todo: it is used for loglevel, to be ported to new kernel.
++/* Todo: it is used for loglevel, to be ported to new kernel. */
+ 
+ 	ret = vmbus_bus_init(VmbusInitialize);
+ 
+@@ -1100,7 +1100,7 @@ static void __exit vmbus_exit(void)
+ 	DPRINT_ENTER(VMBUS_DRV);
+ 
+ 	vmbus_bus_exit();
+-//Todo: it is used for loglevel, to be ported to new kernel.
++/* Todo: it is used for loglevel, to be ported to new kernel. */
+ 	DPRINT_EXIT(VMBUS_DRV);
+ 
+ 	return;
+@@ -1111,4 +1111,4 @@ module_param(vmbus_loglevel, int, S_IRUGO);
+ 
+ module_init(vmbus_init);
+ module_exit(vmbus_exit);
+-// eof
++/* eof */

commit 226408a4998041d7832123ab9ccd743e878197ed
+Author: Bill Pemberton 
+Date:   Mon Jul 27 16:47:23 2009 -0400
+
+    Staging: hv: Use %ld instead of %d for a long ints
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Hank Janssen 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/hv/Channel.c b/drivers/staging/hv/Channel.c
+index 196c7a6e549e..2af8959e03e7 100644
+--- a/drivers/staging/hv/Channel.c
++++ b/drivers/staging/hv/Channel.c
+@@ -557,7 +557,7 @@ VmbusChannelEstablishGpadl(
+ 
+ 	DPRINT_DBG(VMBUS, "buffer %p, size %d msg cnt %d", Kbuffer, Size, msgCount);
+ 
+-	DPRINT_DBG(VMBUS, "Sending GPADL Header - len %d", msgInfo->MessageSize - sizeof(VMBUS_CHANNEL_MSGINFO));
++	DPRINT_DBG(VMBUS, "Sending GPADL Header - len %ld", msgInfo->MessageSize - sizeof(VMBUS_CHANNEL_MSGINFO));
+ 
+ 	ret = VmbusPostMessage(gpadlMsg, msgInfo->MessageSize - sizeof(VMBUS_CHANNEL_MSGINFO));
+ 	if (ret != 0)
+@@ -576,7 +576,7 @@ VmbusChannelEstablishGpadl(
+ 			gpadlBody->Header.MessageType = ChannelMessageGpadlBody;
+ 			gpadlBody->Gpadl = nextGpadlHandle;
+ 
+-			DPRINT_DBG(VMBUS, "Sending GPADL Body - len %d", subMsgInfo->MessageSize - sizeof(VMBUS_CHANNEL_MSGINFO));
++			DPRINT_DBG(VMBUS, "Sending GPADL Body - len %ld", subMsgInfo->MessageSize - sizeof(VMBUS_CHANNEL_MSGINFO));
+ 
+ 			DumpGpadlBody(gpadlBody, subMsgInfo->MessageSize - sizeof(VMBUS_CHANNEL_MSGINFO));
+ 			ret = VmbusPostMessage(gpadlBody, subMsgInfo->MessageSize - sizeof(VMBUS_CHANNEL_MSGINFO));
+diff --git a/drivers/staging/hv/Vmbus.c b/drivers/staging/hv/Vmbus.c
+index 72bb08f24392..a202a2d4e0e8 100644
+--- a/drivers/staging/hv/Vmbus.c
++++ b/drivers/staging/hv/Vmbus.c
+@@ -123,7 +123,7 @@ VmbusInitialize(
+ 	DPRINT_INFO(VMBUS, "+++++++ Vmbus supported version = %d +++++++", VMBUS_REVISION_NUMBER);
+ 	DPRINT_INFO(VMBUS, "+++++++ Vmbus using SINT %d +++++++", VMBUS_MESSAGE_SINT);
+ 
+-	DPRINT_DBG(VMBUS, "sizeof(VMBUS_CHANNEL_PACKET_PAGE_BUFFER)=%d, sizeof(VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER)=%d",
++	DPRINT_DBG(VMBUS, "sizeof(VMBUS_CHANNEL_PACKET_PAGE_BUFFER)=%ld, sizeof(VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER)=%ld",
+ 		sizeof(VMBUS_CHANNEL_PACKET_PAGE_BUFFER), sizeof(VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER));
+ 
+ 	drv->name = gDriverName;

commit f3a756883ac028c536479e2eb283477fec80c828
+Author: Bill Pemberton 
+Date:   Tue Jul 14 15:33:52 2009 -0400
+
+    Staging: serqt_usb2: add missing calls to tty_kref_put()
+    
+    tty_port_tty_get() was called without a corresponding tty_kref_put()
+    in qt_read_bulk_callback() and qt_close().
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c
+index a9bd4106beb7..f9ff9c266780 100644
+--- a/drivers/staging/serqt_usb2/serqt_usb2.c
++++ b/drivers/staging/serqt_usb2/serqt_usb2.c
+@@ -360,18 +360,18 @@ static void qt_read_bulk_callback(struct urb *urb)
+ 	if (port_paranoia_check(port, __func__) != 0) {
+ 		dbg("%s - port_paranoia_check, exiting\n", __func__);
+ 		qt_port->ReadBulkStopped = 1;
+-		return;
++		goto exit;
+ 	}
+ 
+ 	if (!serial) {
+ 		dbg("%s - bad serial pointer, exiting\n", __func__);
+-		return;
++		goto exit;
+ 	}
+ 	if (qt_port->closePending == 1) {
+ 		/* Were closing , stop reading */
+ 		dbg("%s - (qt_port->closepending == 1\n", __func__);
+ 		qt_port->ReadBulkStopped = 1;
+-		return;
++		goto exit;
+ 	}
+ 
+ 	/*
+@@ -381,7 +381,7 @@ static void qt_read_bulk_callback(struct urb *urb)
+ 	 */
+ 	if (qt_port->RxHolding == 1) {
+ 		qt_port->ReadBulkStopped = 1;
+-		return;
++		goto exit;
+ 	}
+ 
+ 	if (urb->status) {
+@@ -389,7 +389,7 @@ static void qt_read_bulk_callback(struct urb *urb)
+ 
+ 		dbg("%s - nonzero read bulk status received: %d\n",
+ 		    __func__, urb->status);
+-		return;
++		goto exit;
+ 	}
+ 
+ 	if (tty && RxCount) {
+@@ -463,6 +463,8 @@ static void qt_read_bulk_callback(struct urb *urb)
+ 	}
+ 
+ 	schedule_work(&port->work);
++exit:
++	tty_kref_put(tty);
+ }
+ 
+ /*
+@@ -1041,7 +1043,7 @@ static void qt_block_until_empty(struct tty_struct *tty,
+ 	}
+ }
+ 
+-static void qt_close( struct usb_serial_port *port)
++static void qt_close(struct usb_serial_port *port)
+ {
+ 	struct usb_serial *serial = port->serial;
+ 	struct quatech_port *qt_port;
+@@ -1068,6 +1070,7 @@ static void qt_close( struct usb_serial_port *port)
+ 	/* wait up to for transmitter to empty */
+ 	if (serial->dev)
+ 		qt_block_until_empty(tty, qt_port);
++	tty_kref_put(tty);
+ 
+ 	/* Close uart channel */
+ 	status = qt_close_channel(serial, index);

commit 35e2bed559ab80641f1764aae570d92711ddc2fa
+Author: Bill Pemberton 
+Date:   Fri Jun 19 12:32:57 2009 -0400
+
+    Staging: serqt_usb2: declare qt_open static in serqt_usb2
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c
+index 4e5db192e2d8..a9bd4106beb7 100644
+--- a/drivers/staging/serqt_usb2/serqt_usb2.c
++++ b/drivers/staging/serqt_usb2/serqt_usb2.c
+@@ -866,7 +866,7 @@ static void qt_release(struct usb_serial *serial)
+ 
+ }
+ 
+-int qt_open(struct tty_struct *tty,
++static int qt_open(struct tty_struct *tty,
+ 	    struct usb_serial_port *port, struct file *filp)
+ {
+ 	struct usb_serial *serial;

commit d9dea3c1c0814a87cc579b425e9776b8ed46b31f
+Author: Bill Pemberton 
+Date:   Fri Jun 19 12:32:56 2009 -0400
+
+    Staging: serqt_usb2: fix qt_close parameters in serqt_usb2
+    
+    The parameter list for qt_close() was from the old non usb-serial
+    driver.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c
+index 90b29b564631..4e5db192e2d8 100644
+--- a/drivers/staging/serqt_usb2/serqt_usb2.c
++++ b/drivers/staging/serqt_usb2/serqt_usb2.c
+@@ -1041,17 +1041,19 @@ static void qt_block_until_empty(struct tty_struct *tty,
+ 	}
+ }
+ 
+-static void qt_close(struct tty_struct *tty, struct usb_serial_port *port,
+-		     struct file *filp)
++static void qt_close( struct usb_serial_port *port)
+ {
+ 	struct usb_serial *serial = port->serial;
+ 	struct quatech_port *qt_port;
+ 	struct quatech_port *port0;
++	struct tty_struct *tty;
+ 	int status;
+ 	unsigned int index;
+ 	status = 0;
+ 
+ 	dbg("%s - port %d\n", __func__, port->number);
++
++	tty = tty_port_tty_get(&port->port);
+ 	index = tty->index - serial->minor;
+ 
+ 	qt_port = qt_get_port_private(port);

commit 8ba911c793c526c394eeddbe66f675c58a922449
+Author: Bill Pemberton 
+Date:   Sun May 31 15:49:42 2009 -0400
+
+    Staging: serqt_usb2 add the driver to the build
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
+index 07998730d8e7..a28091fc8500 100644
+--- a/drivers/staging/Kconfig
++++ b/drivers/staging/Kconfig
+@@ -115,12 +115,12 @@ source "drivers/staging/heci/Kconfig"
+ 
+ source "drivers/staging/line6/Kconfig"
+ 
+-source "drivers/staging/serqt_usb/Kconfig"
+-
+ source "drivers/gpu/drm/radeon/Kconfig"
+ 
+ source "drivers/staging/octeon/Kconfig"
+ 
++source "drivers/staging/serqt_usb2/Kconfig"
++
+ source "drivers/staging/vt6655/Kconfig"
+ 
+ source "drivers/staging/cpc-usb/Kconfig"
+diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
+index 8fb84310bb38..b0e0c60c1332 100644
+--- a/drivers/staging/Makefile
++++ b/drivers/staging/Makefile
+@@ -41,6 +41,7 @@ obj-$(CONFIG_PLAN9AUTH)		+= p9auth/
+ obj-$(CONFIG_HECI)		+= heci/
+ obj-$(CONFIG_LINE6_USB)		+= line6/
+ obj-$(CONFIG_USB_SERIAL_QUATECH_ESU100)	+= serqt_usb/
++obj-$(CONFIG_USB_SERIAL_QUATECH2)	+= serqt_usb2/
+ obj-$(CONFIG_OCTEON_ETHERNET)	+= octeon/
+ obj-$(CONFIG_VT6655)		+= vt6655/
+ obj-$(CONFIG_USB_CPC)		+= cpc-usb/

commit d75662e164d5175c5e5f9339ff4d6f6980613d96
+Author: Bill Pemberton 
+Date:   Sun May 31 15:49:43 2009 -0400
+
+    Staging: Add serqt_usb2, a rewrite of serqt_usb for the usb-serial layer
+    
+    This is the serqt_usb driver rewritten to use usb-serial.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/serqt_usb2/Kconfig b/drivers/staging/serqt_usb2/Kconfig
+new file mode 100644
+index 000000000000..f4fed40e23dd
+--- /dev/null
++++ b/drivers/staging/serqt_usb2/Kconfig
+@@ -0,0 +1,9 @@
++config USB_SERIAL_QUATECH2
++	tristate "USB Quatech ESU-100 8 Port Serial Driver"
++	depends on USB_SERIAL
++	help
++	  Say Y here if you want to use the Quatech ESU-100 8 port usb to
++	  serial adapter.
++
++	  To compile this driver as a module, choose M here: the
++	  module will be called serqt_usb2.
+diff --git a/drivers/staging/serqt_usb2/Makefile b/drivers/staging/serqt_usb2/Makefile
+new file mode 100644
+index 000000000000..21578617f7e8
+--- /dev/null
++++ b/drivers/staging/serqt_usb2/Makefile
+@@ -0,0 +1 @@
++obj-$(CONFIG_USB_SERIAL_QUATECH2)		+= serqt_usb2.o
+diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c
+new file mode 100644
+index 000000000000..581232b719fd
+--- /dev/null
++++ b/drivers/staging/serqt_usb2/serqt_usb2.c
+@@ -0,0 +1,1664 @@
++/*
++ * This code was developed for the Quatech USB line for linux, it used
++ * much of the code developed by Greg Kroah-Hartman for USB serial devices
++ *
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++static int debug;
++
++/* Version Information */
++#define DRIVER_VERSION "v2.14"
++#define DRIVER_AUTHOR "Tim Gobeli, Quatech, Inc"
++#define DRIVER_DESC "Quatech USB to Serial Driver"
++
++#define	USB_VENDOR_ID_QUATECH			0x061d	/* Quatech VID */
++#define QUATECH_SSU100	0xC020	/* SSU100 */
++#define QUATECH_SSU200	0xC030	/* SSU200 */
++#define QUATECH_DSU100	0xC040	/* DSU100 */
++#define QUATECH_DSU200	0xC050	/* DSU200 */
++#define QUATECH_QSU100	0xC060	/* QSU100 */
++#define QUATECH_QSU200	0xC070	/* QSU200 */
++#define QUATECH_ESU100A	0xC080	/* ESU100A */
++#define QUATECH_ESU100B	0xC081	/* ESU100B */
++#define QUATECH_ESU200A	0xC0A0	/* ESU200A */
++#define QUATECH_ESU200B	0xC0A1	/* ESU200B */
++#define QUATECH_HSU100A	0xC090	/* HSU100A */
++#define QUATECH_HSU100B	0xC091	/* HSU100B */
++#define QUATECH_HSU100C	0xC092	/* HSU100C */
++#define QUATECH_HSU100D	0xC093	/* HSU100D */
++#define QUATECH_HSU200A	0xC0B0	/* HSU200A */
++#define QUATECH_HSU200B	0xC0B1	/* HSU200B */
++#define QUATECH_HSU200C	0xC0B2	/* HSU200C */
++#define QUATECH_HSU200D	0xC0B3	/* HSU200D */
++#define QUATECH_SSU100_2  0xC120	/* SSU100_2 */
++#define QUATECH_DSU100_2  0xC140	/* DSU100_2 */
++#define QUATECH_DSU400_2  0xC150	/* DSU400_2 */
++#define QUATECH_QSU100_2  0xC160	/* QSU100_2 */
++#define QUATECH_QSU400_2  0xC170	/* QSU400_2 */
++#define QUATECH_ESU400_2  0xC180	/* ESU400_2 */
++#define QUATECH_ESU100_2  0xC1A0	/* ESU100_2 */
++
++#define QT_SET_GET_DEVICE           0xc2
++#define QT_OPEN_CLOSE_CHANNEL       0xca
++#define QT_GET_SET_PREBUF_TRIG_LVL  0xcc
++#define QT_SET_ATF                  0xcd
++#define QT_GET_SET_REGISTER         0xc0
++#define QT_GET_SET_UART             0xc1
++#define QT_HW_FLOW_CONTROL_MASK     0xc5
++#define QT_SW_FLOW_CONTROL_MASK     0xc6
++#define QT_SW_FLOW_CONTROL_DISABLE  0xc7
++#define QT_BREAK_CONTROL            0xc8
++
++#define USBD_TRANSFER_DIRECTION_IN    0xc0
++#define USBD_TRANSFER_DIRECTION_OUT   0x40
++
++#define  MAX_BAUD_RATE              460800
++#define  MAX_BAUD_REMAINDER         4608
++
++#define  DIV_LATCH_LS               0x00
++#define  XMT_HOLD_REGISTER          0x00
++#define  XVR_BUFFER_REGISTER        0x00
++#define  DIV_LATCH_MS               0x01
++#define  FIFO_CONTROL_REGISTER      0x02
++#define  LINE_CONTROL_REGISTER      0x03
++#define  MODEM_CONTROL_REGISTER     0x04
++#define  LINE_STATUS_REGISTER       0x05
++#define  MODEM_STATUS_REGISTER      0x06
++
++#define  SERIAL_MCR_DTR             0x01
++#define  SERIAL_MCR_RTS             0x02
++#define  SERIAL_MCR_LOOP            0x10
++
++#define  SERIAL_MSR_CTS             0x10
++#define  SERIAL_MSR_CD              0x80
++#define  SERIAL_MSR_RI              0x40
++#define  SERIAL_MSR_DSR             0x20
++#define  SERIAL_MSR_MASK            0xf0
++
++#define  SERIAL_8_DATA              0x03
++#define  SERIAL_7_DATA              0x02
++#define  SERIAL_6_DATA              0x01
++#define  SERIAL_5_DATA              0x00
++
++#define  SERIAL_ODD_PARITY          0X08
++#define  SERIAL_EVEN_PARITY         0X18
++#define  SERIAL_TWO_STOPB           0x04
++#define  SERIAL_ONE_STOPB           0x00
++
++#define DEFAULT_DIVISOR  0x30	/* gives 9600 baud rate */
++#define DEFAULT_LCR SERIAL_8_DATA	/* 8, none , 1 */
++
++#define FULLPWRBIT          0x00000080
++#define NEXT_BOARD_POWER_BIT        0x00000004
++
++#define SERIAL_LSR_OE       0x02
++#define SERIAL_LSR_PE       0x04
++#define SERIAL_LSR_FE       0x08
++#define SERIAL_LSR_BI       0x10
++
++#define  SERIAL_MSR_CTS             0x10
++#define  SERIAL_MSR_CD              0x80
++#define  SERIAL_MSR_RI              0x40
++#define  SERIAL_MSR_DSR             0x20
++#define  SERIAL_MSR_MASK            0xf0
++
++#define PREFUFF_LEVEL_CONSERVATIVE  128
++#define ATC_DISABLED                0x0
++
++#define RR_BITS             0x03	/* for clearing clock bits */
++#define DUPMODE_BITS        0xc0
++#define CLKS_X4             0x02
++
++#define LOOPMODE_BITS       0x41	/* LOOP1 = b6, LOOP0 = b0 (PORT B) */
++#define ALL_LOOPBACK        0x01
++#define MODEM_CTRL          0x40
++#define RS232_MODE          0x00
++
++static struct usb_device_id serqt_id_table[] = {
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU100)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU200)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU100)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU200)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU100)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU200)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU100A)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU100B)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU200A)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU200B)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU100A)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU100B)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU100C)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU100D)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU200A)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU200B)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU200C)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU200D)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU100_2)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU100_2)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU400_2)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU100_2)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU400_2)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU400_2)},
++	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU100_2)},
++	{}			/* Terminating entry */
++};
++
++MODULE_DEVICE_TABLE(usb, serqt_id_table);
++
++struct qt_get_device_data {
++	__u8 porta;
++	__u8 portb;
++	__u8 portc;
++};
++
++struct qt_open_channel_data {
++	__u8 line_status;
++	__u8 modem_status;
++};
++
++struct quatech_port {
++	int port_num;		/* number of the port */
++	struct urb *write_urb;	/* write URB for this port */
++	struct urb *read_urb;	/* read URB for this port */
++	struct urb *int_urb;
++
++	__u8 shadowLCR;		/* last LCR value received */
++	__u8 shadowMCR;		/* last MCR value received */
++	__u8 shadowMSR;		/* last MSR value received */
++	__u8 shadowLSR;		/* last LSR value received */
++	char open_ports;
++
++	/* Used for TIOCMIWAIT */
++	wait_queue_head_t msr_wait;
++	char prev_status, diff_status;
++
++	wait_queue_head_t wait;
++
++	struct async_icount icount;
++
++	struct usb_serial_port *port;	/* owner of this object */
++	struct qt_get_device_data DeviceData;
++	spinlock_t lock;
++	bool read_urb_busy;
++	int RxHolding;
++	int ReadBulkStopped;
++	char closePending;
++};
++
++static struct usb_driver serqt_usb_driver = {
++	.name = "quatech-usb-serial",
++	.probe = usb_serial_probe,
++	.disconnect = usb_serial_disconnect,
++	.id_table = serqt_id_table,
++	.no_dynamic_id = 1,
++};
++
++static int port_paranoia_check(struct usb_serial_port *port,
++			       const char *function)
++{
++	if (!port) {
++		dbg("%s - port == NULL", function);
++		return -1;
++	}
++	if (!port->serial) {
++		dbg("%s - port->serial == NULL\n", function);
++		return -1;
++	}
++
++	return 0;
++}
++
++static int serial_paranoia_check(struct usb_serial *serial,
++				 const char *function)
++{
++	if (!serial) {
++		dbg("%s - serial == NULL\n", function);
++		return -1;
++	}
++
++	if (!serial->type) {
++		dbg("%s - serial->type == NULL!", function);
++		return -1;
++	}
++
++	return 0;
++}
++
++static inline struct quatech_port *qt_get_port_private(struct usb_serial_port
++						       *port)
++{
++	return (struct quatech_port *)usb_get_serial_port_data(port);
++}
++
++static inline void qt_set_port_private(struct usb_serial_port *port,
++				       struct quatech_port *data)
++{
++	usb_set_serial_port_data(port, (void *)data);
++}
++
++static struct usb_serial *get_usb_serial(struct usb_serial_port *port,
++					 const char *function)
++{
++	/* if no port was specified, or it fails a paranoia check */
++	if (!port ||
++	    port_paranoia_check(port, function) ||
++	    serial_paranoia_check(port->serial, function)) {
++		/*
++		 * then say that we dont have a valid usb_serial thing,
++		 * which will end up genrating -ENODEV return values
++		 */
++		return NULL;
++	}
++
++	return port->serial;
++}
++
++static void ProcessLineStatus(struct quatech_port *qt_port,
++			      unsigned char line_status)
++{
++
++	qt_port->shadowLSR =
++	    line_status & (SERIAL_LSR_OE | SERIAL_LSR_PE | SERIAL_LSR_FE |
++			   SERIAL_LSR_BI);
++	return;
++}
++
++static void ProcessModemStatus(struct quatech_port *qt_port,
++			       unsigned char modem_status)
++{
++
++	qt_port->shadowMSR = modem_status;
++	wake_up_interruptible(&qt_port->wait);
++	return;
++}
++
++static void ProcessRxChar(struct usb_serial_port *port, unsigned char Data)
++{
++	struct tty_struct *tty;
++	struct urb *urb = port->read_urb;
++	tty = tty_port_tty_get(&port->port);
++
++	/* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
++
++	if (tty && urb->actual_length) {
++		tty_buffer_request_room(tty, 1);
++		tty_insert_flip_string(tty, &Data, 1);
++		/* tty_flip_buffer_push(tty); */
++	}
++
++	return;
++}
++
++static void qt_write_bulk_callback(struct urb *urb)
++{
++	struct tty_struct *tty;
++	int status;
++	struct quatech_port *quatech_port;
++
++	status = urb->status;
++
++	if (status) {
++		dbg("nonzero write bulk status received:%d\n", status);
++		return;
++	}
++
++	quatech_port = urb->context;
++
++	dbg("%s - port %d\n", __func__, quatech_port->port_num);
++
++	tty = tty_port_tty_get(&quatech_port->port->port);
++
++	if (tty)
++		tty_wakeup(tty);
++	tty_kref_put(tty);
++}
++
++static void qt_interrupt_callback(struct urb *urb)
++{
++	/* FIXME */
++}
++
++static void qt_read_bulk_callback(struct urb *urb)
++{
++
++	struct usb_serial_port *port = urb->context;
++	struct usb_serial *serial = get_usb_serial(port, __func__);
++	struct quatech_port *qt_port = qt_get_port_private(port);
++	unsigned char *data;
++	struct tty_struct *tty;
++	unsigned int index;
++	unsigned int RxCount;
++	int i, result;
++	int flag, flag_data;
++
++	if (urb->status) {
++		qt_port->ReadBulkStopped = 1;
++		dbg("%s - nonzero write bulk status received: %d\n",
++		    __func__, urb->status);
++		return;
++	}
++
++	tty = tty_port_tty_get(&port->port);
++	if (!tty) {
++		dbg("%s - bad tty pointer - exiting", __func__);
++		return;
++	}
++
++	data = urb->transfer_buffer;
++
++	RxCount = urb->actual_length;
++
++	/* index = MINOR(port->tty->device) - serial->minor; */
++	index = tty->index - serial->minor;
++
++	dbg("%s - port %d\n", __func__, port->number);
++	dbg("%s - port->RxHolding = %d\n", __func__, qt_port->RxHolding);
++
++	if (port_paranoia_check(port, __func__) != 0) {
++		dbg("%s - port_paranoia_check, exiting\n", __func__);
++		qt_port->ReadBulkStopped = 1;
++		return;
++	}
++
++	if (!serial) {
++		dbg("%s - bad serial pointer, exiting\n", __func__);
++		return;
++	}
++	if (qt_port->closePending == 1) {
++		/* Were closing , stop reading */
++		dbg("%s - (qt_port->closepending == 1\n", __func__);
++		qt_port->ReadBulkStopped = 1;
++		return;
++	}
++
++	/*
++	 * RxHolding is asserted by throttle, if we assert it, we're not
++	 * receiving any more characters and let the box handle the flow
++	 * control
++	 */
++	if (qt_port->RxHolding == 1) {
++		qt_port->ReadBulkStopped = 1;
++		return;
++	}
++
++	if (urb->status) {
++		qt_port->ReadBulkStopped = 1;
++
++		dbg("%s - nonzero read bulk status received: %d\n",
++		    __func__, urb->status);
++		return;
++	}
++
++	if (tty && RxCount) {
++		flag_data = 0;
++		for (i = 0; i < RxCount; ++i) {
++			/* Look ahead code here */
++			if ((i <= (RxCount - 3)) && (data[i] == 0x1b)
++			    && (data[i + 1] == 0x1b)) {
++				flag = 0;
++				switch (data[i + 2]) {
++				case 0x00:
++					/* line status change 4th byte must follow */
++					if (i > (RxCount - 4)) {
++						dbg("Illegal escape seuences in received data\n");
++						break;
++					}
++					ProcessLineStatus(qt_port, data[i + 3]);
++					i += 3;
++					flag = 1;
++					break;
++
++				case 0x01:
++					/* Modem status status change 4th byte must follow */
++					dbg("Modem status status. \n");
++					if (i > (RxCount - 4)) {
++						dbg("Illegal escape sequences in received data\n");
++						break;
++					}
++					ProcessModemStatus(qt_port,
++							   data[i + 3]);
++					i += 3;
++					flag = 1;
++					break;
++				case 0xff:
++					dbg("No status sequence. \n");
++
++					ProcessRxChar(port, data[i]);
++					ProcessRxChar(port, data[i + 1]);
++					i += 2;
++					break;
++				}
++				if (flag == 1)
++					continue;
++			}
++
++			if (tty && urb->actual_length) {
++				tty_buffer_request_room(tty, 1);
++				tty_insert_flip_string(tty, (data + i), 1);
++			}
++
++		}
++		tty_flip_buffer_push(tty);
++	}
++
++	/* Continue trying to always read  */
++	usb_fill_bulk_urb(port->read_urb, serial->dev,
++			  usb_rcvbulkpipe(serial->dev,
++					  port->bulk_in_endpointAddress),
++			  port->read_urb->transfer_buffer,
++			  port->read_urb->transfer_buffer_length,
++			  qt_read_bulk_callback, port);
++	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
++	if (result)
++		dbg("%s - failed resubmitting read urb, error %d",
++		    __func__, result);
++	else {
++		if (tty && RxCount) {
++			tty_flip_buffer_push(tty);
++			tty_schedule_flip(tty);
++		}
++	}
++
++	schedule_work(&port->work);
++}
++
++/*
++ * qt_get_device
++ *   Issue a GET_DEVICE vendor-specific request on the default control pipe If
++ *   successful, fills in the qt_get_device_data structure pointed to by
++ *   device_data, otherwise return a negative error number of the problem.
++ */
++
++static int qt_get_device(struct usb_serial *serial,
++			 struct qt_get_device_data *device_data)
++{
++	int result;
++	unsigned char *transfer_buffer;
++
++	transfer_buffer =
++	    kmalloc(sizeof(struct qt_get_device_data), GFP_KERNEL);
++	if (!transfer_buffer)
++		return -ENOMEM;
++
++	result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
++				 QT_SET_GET_DEVICE, 0xc0, 0, 0,
++				 transfer_buffer,
++				 sizeof(struct qt_get_device_data), 300);
++	if (result > 0)
++		memcpy(device_data, transfer_buffer,
++		       sizeof(struct qt_get_device_data));
++	kfree(transfer_buffer);
++
++	return result;
++}
++
++/****************************************************************************
++ *  BoxSetPrebufferLevel
++   TELLS BOX WHEN TO ASSERT FLOW CONTROL
++ ****************************************************************************/
++static int BoxSetPrebufferLevel(struct usb_serial *serial)
++{
++	int result;
++	__u16 buffer_length;
++
++	buffer_length = PREFUFF_LEVEL_CONSERVATIVE;
++	result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
++				 QT_GET_SET_PREBUF_TRIG_LVL, 0x40,
++				 buffer_length, 0, NULL, 0, 300);
++	return result;
++}
++
++/****************************************************************************
++ *  BoxSetATC
++   TELLS BOX WHEN TO ASSERT automatic transmitter control
++   ****************************************************************************/
++static int BoxSetATC(struct usb_serial *serial, __u16 n_Mode)
++{
++	int result;
++	__u16 buffer_length;
++
++	buffer_length = PREFUFF_LEVEL_CONSERVATIVE;
++
++	result =
++	    usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
++			    QT_SET_ATF, 0x40, n_Mode, 0, NULL, 0, 300);
++
++	return result;
++}
++
++/**
++ * qt_set_device
++ *   Issue a SET_DEVICE vendor-specific request on the default control pipe If
++ *   successful returns the number of bytes written, otherwise it returns a
++ *   negative error number of the problem.
++ */
++static int qt_set_device(struct usb_serial *serial,
++			 struct qt_get_device_data *device_data)
++{
++	int result;
++	__u16 length;
++	__u16 PortSettings;
++
++	PortSettings = ((__u16) (device_data->portb));
++	PortSettings = (PortSettings << 8);
++	PortSettings += ((__u16) (device_data->porta));
++
++	length = sizeof(struct qt_get_device_data);
++	dbg("%s - PortSettings = 0x%x\n", __func__, PortSettings);
++
++	result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
++				 QT_SET_GET_DEVICE, 0x40, PortSettings,
++				 0, NULL, 0, 300);
++	return result;
++}
++
++static int qt_open_channel(struct usb_serial *serial, __u16 Uart_Number,
++			   struct qt_open_channel_data *pDeviceData)
++{
++	int result;
++
++	result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
++				 QT_OPEN_CLOSE_CHANNEL,
++				 USBD_TRANSFER_DIRECTION_IN, 1, Uart_Number,
++				 pDeviceData,
++				 sizeof(struct qt_open_channel_data), 300);
++
++	return result;
++
++}
++
++static int qt_close_channel(struct usb_serial *serial, __u16 Uart_Number)
++{
++	int result;
++
++	result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
++				 QT_OPEN_CLOSE_CHANNEL,
++				 USBD_TRANSFER_DIRECTION_OUT, 0, Uart_Number,
++				 NULL, 0, 300);
++
++	return result;
++
++}
++
++/****************************************************************************
++* BoxGetRegister
++*	issuse a GET_REGISTER vendor-spcific request on the default control pipe
++*	If successful, fills in the  pValue with the register value asked for
++****************************************************************************/
++static int BoxGetRegister(struct usb_serial *serial, unsigned short Uart_Number,
++			  unsigned short Register_Num, __u8 *pValue)
++{
++	int result;
++	__u16 current_length;
++
++	current_length = sizeof(struct qt_get_device_data);
++
++	result =
++	    usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
++			    QT_GET_SET_REGISTER, 0xC0, Register_Num,
++			    Uart_Number, (void *)pValue, sizeof(*pValue), 300);
++
++	return result;
++}
++
++/****************************************************************************
++* BoxSetRegister
++*	issuse a GET_REGISTER vendor-spcific request on the default control pipe
++*	If successful, fills in the  pValue with the register value asked for
++****************************************************************************/
++static int BoxSetRegister(struct usb_serial *serial, unsigned short Uart_Number,
++			  unsigned short Register_Num, unsigned short Value)
++{
++	int result;
++	unsigned short RegAndByte;
++
++	RegAndByte = Value;
++	RegAndByte = RegAndByte << 8;
++	RegAndByte = RegAndByte + Register_Num;
++
++/*
++	result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
++				 QT_GET_SET_REGISTER, 0xC0, Register_Num,
++				 Uart_Number, NULL, 0, 300);
++*/
++
++	result =
++	    usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
++			    QT_GET_SET_REGISTER, 0x40, RegAndByte, Uart_Number,
++			    NULL, 0, 300);
++
++	return result;
++}
++
++/*
++ * qt_setuart
++ * issuse a SET_UART vendor-spcific request on the default control pipe
++ * If successful sets baud rate divisor and LCR value
++ */
++static int qt_setuart(struct usb_serial *serial, unsigned short Uart_Number,
++		      unsigned short default_divisor, unsigned char default_LCR)
++{
++	int result;
++	unsigned short UartNumandLCR;
++
++	UartNumandLCR = (default_LCR << 8) + Uart_Number;
++
++	result =
++	    usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
++			    QT_GET_SET_UART, 0x40, default_divisor,
++			    UartNumandLCR, NULL, 0, 300);
++
++	return result;
++}
++
++static int BoxSetHW_FlowCtrl(struct usb_serial *serial, unsigned int index,
++			     int bSet)
++{
++	__u8 mcr = 0;
++	__u8 msr = 0, MOUT_Value = 0;
++	unsigned int status;
++
++	if (bSet == 1) {
++		/* flow control, box will clear RTS line to prevent remote */
++		mcr = SERIAL_MCR_RTS;
++	} /* device from xmitting more chars */
++	else {
++		/* no flow control to remote device */
++		mcr = 0;
++
++	}
++	MOUT_Value = mcr << 8;
++
++	if (bSet == 1) {
++		/* flow control, box will inhibit xmit data if CTS line is
++		 * asserted */
++		msr = SERIAL_MSR_CTS;
++	} else {
++		/* Box will not inhimbe xmit data due to CTS line */
++		msr = 0;
++	}
++	MOUT_Value |= msr;
++
++	status =
++	    usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
++			    QT_HW_FLOW_CONTROL_MASK, 0x40, MOUT_Value,
++			    index, NULL, 0, 300);
++	return status;
++
++}
++
++static int BoxSetSW_FlowCtrl(struct usb_serial *serial, __u16 index,
++			     unsigned char stop_char, unsigned char start_char)
++{
++	__u16 nSWflowout;
++	int result;
++
++	nSWflowout = start_char << 8;
++	nSWflowout = (unsigned short)stop_char;
++
++	result =
++	    usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
++			    QT_SW_FLOW_CONTROL_MASK, 0x40, nSWflowout,
++			    index, NULL, 0, 300);
++	return result;
++
++}
++
++static int BoxDisable_SW_FlowCtrl(struct usb_serial *serial, __u16 index)
++{
++	int result;
++
++	result =
++	    usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
++			    QT_SW_FLOW_CONTROL_DISABLE, 0x40, 0, index,
++			    NULL, 0, 300);
++	return result;
++
++}
++
++static int qt_startup(struct usb_serial *serial)
++{
++	struct usb_serial_port *port;
++	struct quatech_port *qt_port;
++	struct qt_get_device_data DeviceData;
++	int i;
++	int status;
++
++	dbg("enterting %s", __func__);
++
++	/* Now setup per port private data */
++	for (i = 0; i < serial->num_ports; i++) {
++		port = serial->port[i];
++		qt_port = kzalloc(sizeof(*qt_port), GFP_KERNEL);
++		if (!qt_port) {
++			dbg("%s: kmalloc for quatech_port (%d) failed!.",
++			    __func__, i);
++			return -ENOMEM;
++		}
++		spin_lock_init(&qt_port->lock);
++
++		usb_set_serial_port_data(port, qt_port);
++
++	}
++
++	status = qt_get_device(serial, &DeviceData);
++	if (status < 0) {
++		dbg(__FILE__ "box_get_device failed");
++		goto startup_error;
++	}
++
++	dbg(__FILE__ "DeviceData.portb = 0x%x", DeviceData.portb);
++
++	DeviceData.portb &= ~FULLPWRBIT;
++	dbg(__FILE__ "Changing DeviceData.portb to 0x%x", DeviceData.portb);
++
++	status = qt_set_device(serial, &DeviceData);
++	if (status < 0) {
++		dbg(__FILE__ "qt_set_device failed\n");
++		goto startup_error;
++	}
++
++	status = qt_get_device(serial, &DeviceData);
++	if (status < 0) {
++		dbg(__FILE__ "qt_get_device failed");
++		goto startup_error;
++	}
++
++	switch (serial->dev->descriptor.idProduct) {
++	case QUATECH_SSU100:
++	case QUATECH_DSU100:
++	case QUATECH_QSU100:
++	case QUATECH_ESU100A:
++	case QUATECH_ESU100B:
++	case QUATECH_HSU100A:
++	case QUATECH_HSU100B:
++	case QUATECH_HSU100C:
++	case QUATECH_HSU100D:
++		DeviceData.porta &= ~(RR_BITS | DUPMODE_BITS);
++		DeviceData.porta |= CLKS_X4;
++		DeviceData.portb &= ~(LOOPMODE_BITS);
++		DeviceData.portb |= RS232_MODE;
++		break;
++
++	case QUATECH_SSU200:
++	case QUATECH_DSU200:
++	case QUATECH_QSU200:
++	case QUATECH_ESU200A:
++	case QUATECH_ESU200B:
++	case QUATECH_HSU200A:
++	case QUATECH_HSU200B:
++	case QUATECH_HSU200C:
++	case QUATECH_HSU200D:
++		DeviceData.porta &= ~(RR_BITS | DUPMODE_BITS);
++		DeviceData.porta |= CLKS_X4;
++		DeviceData.portb &= ~(LOOPMODE_BITS);
++		DeviceData.portb |= ALL_LOOPBACK;
++		break;
++	default:
++		DeviceData.porta &= ~(RR_BITS | DUPMODE_BITS);
++		DeviceData.porta |= CLKS_X4;
++		DeviceData.portb &= ~(LOOPMODE_BITS);
++		DeviceData.portb |= RS232_MODE;
++		break;
++
++	}
++
++	status = BoxSetPrebufferLevel(serial);	/* sets to default value */
++	if (status < 0) {
++		dbg(__FILE__ "BoxSetPrebufferLevel failed\n");
++		goto startup_error;
++	}
++
++	status = BoxSetATC(serial, ATC_DISABLED);
++	if (status < 0) {
++		dbg(__FILE__ "BoxSetATC failed\n");
++		goto startup_error;
++	}
++
++	dbg(__FILE__ "DeviceData.portb = 0x%x", DeviceData.portb);
++
++	DeviceData.portb |= NEXT_BOARD_POWER_BIT;
++	dbg(__FILE__ "Changing DeviceData.portb to 0x%x", DeviceData.portb);
++
++	status = qt_set_device(serial, &DeviceData);
++	if (status < 0) {
++		dbg(__FILE__ "qt_set_device failed\n");
++		goto startup_error;
++	}
++
++	dbg("Exit Success %s\n", __func__);
++
++	return 0;
++
++startup_error:
++	for (i = 0; i < serial->num_ports; i++) {
++		port = serial->port[i];
++		qt_port = qt_get_port_private(port);
++		kfree(qt_port);
++		usb_set_serial_port_data(port, NULL);
++	}
++
++	dbg("Exit fail %s\n", __func__);
++
++	return -EIO;
++}
++
++static void qt_release(struct usb_serial *serial)
++{
++	struct usb_serial_port *port;
++	struct quatech_port *qt_port;
++	int i;
++
++	dbg("enterting %s", __func__);
++
++	for (i = 0; i < serial->num_ports; i++) {
++		port = serial->port[i];
++		if (!port)
++			continue;
++
++		qt_port = usb_get_serial_port_data(port);
++		kfree(qt_port);
++		usb_set_serial_port_data(port, NULL);
++	}
++
++}
++
++int qt_open(struct tty_struct *tty,
++	    struct usb_serial_port *port, struct file *filp)
++{
++	struct usb_serial *serial;
++	struct quatech_port *quatech_port;
++	struct quatech_port *port0;
++	struct qt_open_channel_data ChannelData;
++
++	int result;
++
++	if (port_paranoia_check(port, __func__))
++		return -ENODEV;
++
++	dbg("%s - port %d\n", __func__, port->number);
++
++	serial = port->serial;
++
++	if (serial_paranoia_check(serial, __func__))
++		return -ENODEV;
++
++	quatech_port = qt_get_port_private(port);
++	port0 = qt_get_port_private(serial->port[0]);
++
++	if (quatech_port == NULL || port0 == NULL)
++		return -ENODEV;
++
++	usb_clear_halt(serial->dev, port->write_urb->pipe);
++	usb_clear_halt(serial->dev, port->read_urb->pipe);
++	port0->open_ports++;
++
++	result = qt_get_device(serial, &port0->DeviceData);
++
++	/* Port specific setups */
++	result = qt_open_channel(serial, port->number, &ChannelData);
++	if (result < 0) {
++		dbg(__FILE__ "qt_open_channel failed\n");
++		return result;
++	}
++	dbg(__FILE__ "qt_open_channel completed.\n");
++
++/* FIXME: are these needed?  Does it even do anything useful? */
++	quatech_port->shadowLSR = ChannelData.line_status &
++	    (SERIAL_LSR_OE | SERIAL_LSR_PE | SERIAL_LSR_FE | SERIAL_LSR_BI);
++
++	quatech_port->shadowMSR = ChannelData.modem_status &
++	    (SERIAL_MSR_CTS | SERIAL_MSR_DSR | SERIAL_MSR_RI | SERIAL_MSR_CD);
++
++	/* Set Baud rate to default and turn off (default)flow control here */
++	result = qt_setuart(serial, port->number, DEFAULT_DIVISOR, DEFAULT_LCR);
++	if (result < 0) {
++		dbg(__FILE__ "qt_setuart failed\n");
++		return result;
++	}
++	dbg(__FILE__ "qt_setuart completed.\n");
++
++	/*
++	 * Put this here to make it responsive to stty and defauls set by
++	 * the tty layer
++	 */
++	/* FIXME: is this needed? */
++	/* qt_set_termios(tty, port, NULL); */
++
++	/*  Check to see if we've set up our endpoint info yet */
++	if (port0->open_ports == 1) {
++		if (serial->port[0]->interrupt_in_buffer == NULL) {
++			/* set up interrupt urb */
++			usb_fill_int_urb(serial->port[0]->interrupt_in_urb,
++					 serial->dev,
++					 usb_rcvintpipe(serial->dev,
++							serial->port[0]->interrupt_in_endpointAddress),
++					 serial->port[0]->interrupt_in_buffer,
++					 serial->port[0]->
++					 interrupt_in_urb->transfer_buffer_length,
++					 qt_interrupt_callback, serial,
++					 serial->port[0]->
++					 interrupt_in_urb->interval);
++
++			result =
++			    usb_submit_urb(serial->port[0]->interrupt_in_urb,
++					   GFP_KERNEL);
++			if (result) {
++				dev_err(&port->dev,
++					"%s - Error %d submitting "
++					"interrupt urb\n", __func__, result);
++			}
++
++		}
++
++	}
++
++	dbg("port number is %d \n", port->number);
++	dbg("serial number is %d \n", port->serial->minor);
++	dbg("Bulkin endpoint is %d \n", port->bulk_in_endpointAddress);
++	dbg("BulkOut endpoint is %d \n", port->bulk_out_endpointAddress);
++	dbg("Interrupt endpoint is %d \n", port->interrupt_in_endpointAddress);
++	dbg("port's number in the device is %d\n", quatech_port->port_num);
++	quatech_port->read_urb = port->read_urb;
++
++	/* set up our bulk in urb */
++
++	usb_fill_bulk_urb(quatech_port->read_urb,
++			  serial->dev,
++			  usb_rcvbulkpipe(serial->dev,
++					  port->bulk_in_endpointAddress),
++			  port->bulk_in_buffer,
++			  quatech_port->read_urb->transfer_buffer_length,
++			  qt_read_bulk_callback, quatech_port);
++
++	dbg("qt_open: bulkin endpoint is %d\n", port->bulk_in_endpointAddress);
++	quatech_port->read_urb_busy = true;
++	result = usb_submit_urb(quatech_port->read_urb, GFP_KERNEL);
++	if (result) {
++		dev_err(&port->dev,
++			"%s - Error %d submitting control urb\n",
++			__func__, result);
++		quatech_port->read_urb_busy = false;
++	}
++
++	/* initialize our wait queues */
++	init_waitqueue_head(&quatech_port->wait);
++	init_waitqueue_head(&quatech_port->msr_wait);
++
++	/* initialize our icount structure */
++	memset(&(quatech_port->icount), 0x00, sizeof(quatech_port->icount));
++
++	return 0;
++
++}
++
++static int qt_chars_in_buffer(struct tty_struct *tty)
++{
++	struct usb_serial_port *port = tty->driver_data;
++	struct usb_serial *serial;
++	int chars = 0;
++
++	serial = get_usb_serial(port, __func__);
++
++	dbg("%s - port %d\n", __func__, port->number);
++
++	if (serial->num_bulk_out) {
++		if (port->write_urb->status == -EINPROGRESS)
++			chars = port->write_urb->transfer_buffer_length;
++	}
++
++	dbg("%s - returns %d\n", __func__, chars);
++
++	return chars;
++}
++
++static void qt_block_until_empty(struct tty_struct *tty,
++				 struct quatech_port *qt_port)
++{
++	int timeout = HZ / 10;
++	int wait = 30;
++	int count;
++
++	while (1) {
++
++		count = qt_chars_in_buffer(tty);
++
++		if (count <= 0)
++			return;
++
++		interruptible_sleep_on_timeout(&qt_port->wait, timeout);
++
++		wait--;
++		if (wait == 0) {
++			dbg("%s - TIMEOUT", __func__);
++			return;
++		} else {
++			wait = 30;
++		}
++	}
++}
++
++static void qt_close(struct tty_struct *tty, struct usb_serial_port *port,
++		     struct file *filp)
++{
++	struct usb_serial *serial = port->serial;
++	struct quatech_port *qt_port;
++	struct quatech_port *port0;
++	int status;
++	unsigned int index;
++	status = 0;
++
++	dbg("%s - port %d\n", __func__, port->number);
++	index = tty->index - serial->minor;
++
++	qt_port = qt_get_port_private(port);
++	port0 = qt_get_port_private(serial->port[0]);
++
++	/* shutdown any bulk reads that might be going on */
++	if (serial->num_bulk_out)
++		usb_unlink_urb(port->write_urb);
++	if (serial->num_bulk_in)
++		usb_unlink_urb(port->read_urb);
++
++	/* wait up to for transmitter to empty */
++	if (serial->dev)
++		qt_block_until_empty(tty, qt_port);
++
++	/* Close uart channel */
++	status = qt_close_channel(serial, index);
++	if (status < 0)
++		dbg("%s - port %d qt_close_channel failed.\n",
++		    __func__, port->number);
++
++	port0->open_ports--;
++
++	dbg("qt_num_open_ports in close%d:in port%d\n",
++	    port0->open_ports, port->number);
++
++	if (port0->open_ports == 0) {
++		if (serial->port[0]->interrupt_in_urb) {
++			dbg("%s", "Shutdown interrupt_in_urb\n");
++			usb_kill_urb(serial->port[0]->interrupt_in_urb);
++		}
++
++	}
++
++	if (qt_port->write_urb) {
++		/* if this urb had a transfer buffer already (old tx) free it */
++		if (qt_port->write_urb->transfer_buffer != NULL)
++			kfree(qt_port->write_urb->transfer_buffer);
++		usb_free_urb(qt_port->write_urb);
++	}
++
++}
++
++static int qt_write(struct tty_struct *tty, struct usb_serial_port *port,
++		    const unsigned char *buf, int count)
++{
++	int result;
++	struct usb_serial *serial = get_usb_serial(port, __func__);
++
++	if (serial == NULL)
++		return -ENODEV;
++
++	dbg("%s - port %d\n", __func__, port->number);
++
++	if (count == 0) {
++		dbg("%s - write request of 0 bytes\n", __func__);
++		return 0;
++	}
++
++	/* only do something if we have a bulk out endpoint */
++	if (serial->num_bulk_out) {
++		if (port->write_urb->status == -EINPROGRESS) {
++			dbg("%s - already writing\n", __func__);
++			return 0;
++		}
++
++		count =
++		    (count > port->bulk_out_size) ? port->bulk_out_size : count;
++		memcpy(port->write_urb->transfer_buffer, buf, count);
++
++		/* set up our urb */
++
++		usb_fill_bulk_urb(port->write_urb, serial->dev,
++				  usb_sndbulkpipe(serial->dev,
++						  port->
++						  bulk_out_endpointAddress),
++				  port->write_urb->transfer_buffer, count,
++				  qt_write_bulk_callback, port);
++
++		/* send the data out the bulk port */
++		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
++		if (result)
++			dbg("%s - failed submitting write urb, error %d\n",
++			    __func__, result);
++		else
++			result = count;
++
++		return result;
++	}
++
++	/* no bulk out, so return 0 bytes written */
++	return 0;
++}
++
++static int qt_write_room(struct tty_struct *tty)
++{
++	struct usb_serial_port *port = tty->driver_data;
++	struct usb_serial *serial;
++	struct quatech_port *qt_port;
++	unsigned long flags;
++
++	int retval = -EINVAL;
++
++	if (port_paranoia_check(port, __func__)) {
++		dbg("%s", "Invalid port\n");
++		return -1;
++	}
++
++	serial = get_usb_serial(port, __func__);
++
++	if (!serial)
++		return -ENODEV;
++
++	qt_port = qt_get_port_private(port);
++
++	spin_lock_irqsave(&qt_port->lock, flags);
++
++	dbg("%s - port %d\n", __func__, port->number);
++
++	if (serial->num_bulk_out) {
++		if (port->write_urb->status != -EINPROGRESS)
++			retval = port->bulk_out_size;
++	}
++
++	spin_unlock_irqrestore(&qt_port->lock, flags);
++	return retval;
++
++}
++
++static int qt_ioctl(struct tty_struct *tty, struct file *file,
++		    unsigned int cmd, unsigned long arg)
++{
++	struct usb_serial_port *port = tty->driver_data;
++	struct quatech_port *qt_port = qt_get_port_private(port);
++	struct usb_serial *serial = get_usb_serial(port, __func__);
++	unsigned int index;
++
++	dbg("%s cmd 0x%04x", __func__, cmd);
++
++	index = tty->index - serial->minor;
++
++	if (cmd == TIOCMIWAIT) {
++		while (qt_port != NULL) {
++			interruptible_sleep_on(&qt_port->msr_wait);
++			if (signal_pending(current))
++				return -ERESTARTSYS;
++			else {
++				char diff = qt_port->diff_status;
++
++				if (diff == 0)
++					return -EIO;	/* no change => error */
++
++				/* Consume all events */
++				qt_port->diff_status = 0;
++
++				if (((arg & TIOCM_RNG)
++				     && (diff & SERIAL_MSR_RI))
++				    || ((arg & TIOCM_DSR)
++					&& (diff & SERIAL_MSR_DSR))
++				    || ((arg & TIOCM_CD)
++					&& (diff & SERIAL_MSR_CD))
++				    || ((arg & TIOCM_CTS)
++					&& (diff & SERIAL_MSR_CTS))) {
++					return 0;
++				}
++			}
++		}
++		return 0;
++	}
++
++	dbg("%s -No ioctl for that one.  port = %d\n", __func__, port->number);
++	return -ENOIOCTLCMD;
++}
++
++static void qt_set_termios(struct tty_struct *tty,
++			   struct usb_serial_port *port,
++			   struct ktermios *old_termios)
++{
++	struct ktermios *termios = tty->termios;
++	unsigned char new_LCR = 0;
++	unsigned int cflag = termios->c_cflag;
++	unsigned int index;
++	int baud, divisor, remainder;
++	int status;
++
++	dbg("%s", __func__);
++
++	index = tty->index - port->serial->minor;
++
++	switch (cflag) {
++	case CS5:
++		new_LCR |= SERIAL_5_DATA;
++		break;
++	case CS6:
++		new_LCR |= SERIAL_6_DATA;
++		break;
++	case CS7:
++		new_LCR |= SERIAL_7_DATA;
++		break;
++	default:
++	case CS8:
++		new_LCR |= SERIAL_8_DATA;
++		break;
++	}
++
++	/* Parity stuff */
++	if (cflag & PARENB) {
++		if (cflag & PARODD)
++			new_LCR |= SERIAL_ODD_PARITY;
++		else
++			new_LCR |= SERIAL_EVEN_PARITY;
++	}
++	if (cflag & CSTOPB)
++		new_LCR |= SERIAL_TWO_STOPB;
++	else
++		new_LCR |= SERIAL_TWO_STOPB;
++
++	dbg("%s - 4\n", __func__);
++
++	/* Thats the LCR stuff, go ahead and set it */
++	baud = tty_get_baud_rate(tty);
++	if (!baud)
++		/* pick a default, any default... */
++		baud = 9600;
++
++	dbg("%s - got baud = %d\n", __func__, baud);
++
++	divisor = MAX_BAUD_RATE / baud;
++	remainder = MAX_BAUD_RATE % baud;
++	/* Round to nearest divisor */
++	if (((remainder * 2) >= baud) && (baud != 110))
++		divisor++;
++
++	/*
++	 * Set Baud rate to default and turn off (default)flow control here
++	 */
++	status =
++	    qt_setuart(port->serial, index, (unsigned short)divisor, new_LCR);
++	if (status < 0) {
++		dbg(__FILE__ "qt_setuart failed\n");
++		return;
++	}
++
++	/* Now determine flow control */
++	if (cflag & CRTSCTS) {
++		dbg("%s - Enabling HW flow control port %d\n", __func__,
++		    port->number);
++
++		/* Enable RTS/CTS flow control */
++		status = BoxSetHW_FlowCtrl(port->serial, index, 1);
++
++		if (status < 0) {
++			dbg(__FILE__ "BoxSetHW_FlowCtrl failed\n");
++			return;
++		}
++	} else {
++		/* Disable RTS/CTS flow control */
++		dbg("%s - disabling HW flow control port %d\n", __func__,
++		    port->number);
++
++		status = BoxSetHW_FlowCtrl(port->serial, index, 0);
++		if (status < 0) {
++			dbg(__FILE__ "BoxSetHW_FlowCtrl failed\n");
++			return;
++		}
++
++	}
++
++	/* if we are implementing XON/XOFF, set the start and stop character in
++	 * the device */
++	if (I_IXOFF(tty) || I_IXON(tty)) {
++		unsigned char stop_char = STOP_CHAR(tty);
++		unsigned char start_char = START_CHAR(tty);
++		status =
++		    BoxSetSW_FlowCtrl(port->serial, index, stop_char,
++				      start_char);
++		if (status < 0)
++			dbg(__FILE__ "BoxSetSW_FlowCtrl (enabled) failed\n");
++
++	} else {
++		/* disable SW flow control */
++		status = BoxDisable_SW_FlowCtrl(port->serial, index);
++		if (status < 0)
++			dbg(__FILE__ "BoxSetSW_FlowCtrl (diabling) failed\n");
++
++	}
++	tty->termios->c_cflag &= ~CMSPAR;
++	/* FIXME: Error cases should be returning the actual bits changed only */
++}
++
++static void qt_break(struct tty_struct *tty, int break_state)
++{
++	struct usb_serial_port *port = tty->driver_data;
++	struct usb_serial *serial = get_usb_serial(port, __func__);
++	struct quatech_port *qt_port;
++	u16 index, onoff;
++	unsigned int result;
++	unsigned long flags;
++
++	index = tty->index - serial->minor;
++
++	qt_port = qt_get_port_private(port);
++
++	if (break_state == -1)
++		onoff = 1;
++	else
++		onoff = 0;
++
++	spin_lock_irqsave(&qt_port->lock, flags);
++
++	dbg("%s - port %d\n", __func__, port->number);
++
++	result =
++	    usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
++			    QT_BREAK_CONTROL, 0x40, onoff, index, NULL, 0, 300);
++
++	spin_unlock_irqrestore(&qt_port->lock, flags);
++}
++
++static inline int qt_real_tiocmget(struct tty_struct *tty,
++				   struct usb_serial_port *port,
++				   struct file *file, struct usb_serial *serial)
++{
++
++	u8 mcr;
++	u8 msr;
++	unsigned int result = 0;
++	int status;
++	unsigned int index;
++
++	dbg("%s - port %d, tty =0x%p\n", __func__, port->number, tty);
++
++	index = tty->index - serial->minor;
++	status =
++	    BoxGetRegister(port->serial, index, MODEM_CONTROL_REGISTER, &mcr);
++	if (status >= 0) {
++		status =
++		    BoxGetRegister(port->serial, index,
++				   MODEM_STATUS_REGISTER, &msr);
++
++	}
++
++	if (status >= 0) {
++		result = ((mcr & SERIAL_MCR_DTR) ? TIOCM_DTR : 0)
++		    /* DTR IS SET */
++		    | ((mcr & SERIAL_MCR_RTS) ? TIOCM_RTS : 0)
++		    /* RTS IS SET */
++		    | ((msr & SERIAL_MSR_CTS) ? TIOCM_CTS : 0)
++		    /* CTS is set */
++		    | ((msr & SERIAL_MSR_CD) ? TIOCM_CAR : 0)
++		    /* Carrier detect is set */
++		    | ((msr & SERIAL_MSR_RI) ? TIOCM_RI : 0)
++		    /* Ring indicator set */
++		    | ((msr & SERIAL_MSR_DSR) ? TIOCM_DSR : 0);
++		/* DSR is set */
++		return result;
++
++	} else
++		return -ESPIPE;
++}
++
++static inline int qt_real_tiocmset(struct tty_struct *tty,
++				   struct usb_serial_port *port,
++				   struct file *file,
++				   struct usb_serial *serial,
++				   unsigned int value)
++{
++
++	u8 mcr;
++	int status;
++	unsigned int index;
++
++	dbg("%s - port %d\n", __func__, port->number);
++
++	index = tty->index - serial->minor;
++	status =
++	    BoxGetRegister(port->serial, index, MODEM_CONTROL_REGISTER, &mcr);
++	if (status < 0)
++		return -ESPIPE;
++
++	/*
++	 * Turn off the RTS and DTR and loopbcck and then only turn on what was
++	 * asked for
++	 */
++	mcr &= ~(SERIAL_MCR_RTS | SERIAL_MCR_DTR | SERIAL_MCR_LOOP);
++	if (value & TIOCM_RTS)
++		mcr |= SERIAL_MCR_RTS;
++	if (value & TIOCM_DTR)
++		mcr |= SERIAL_MCR_DTR;
++	if (value & TIOCM_LOOP)
++		mcr |= SERIAL_MCR_LOOP;
++
++	status =
++	    BoxSetRegister(port->serial, index, MODEM_CONTROL_REGISTER, mcr);
++	if (status < 0)
++		return -ESPIPE;
++	else
++		return 0;
++}
++
++static int qt_tiocmget(struct tty_struct *tty, struct file *file)
++{
++	struct usb_serial_port *port = tty->driver_data;
++	struct usb_serial *serial = get_usb_serial(port, __func__);
++	struct quatech_port *qt_port = qt_get_port_private(port);
++	int retval = -ENODEV;
++	unsigned long flags;
++
++	dbg("In %s \n", __func__);
++
++	if (!serial)
++		return -ENODEV;
++
++	spin_lock_irqsave(&qt_port->lock, flags);
++
++	dbg("%s - port %d\n", __func__, port->number);
++	dbg("%s - port->RxHolding = %d\n", __func__, qt_port->RxHolding);
++
++	retval = qt_real_tiocmget(tty, port, file, serial);
++
++	spin_unlock_irqrestore(&qt_port->lock, flags);
++	return retval;
++}
++
++static int qt_tiocmset(struct tty_struct *tty, struct file *file,
++		       unsigned int set, unsigned int clear)
++{
++
++	struct usb_serial_port *port = tty->driver_data;
++	struct usb_serial *serial = get_usb_serial(port, __func__);
++	struct quatech_port *qt_port = qt_get_port_private(port);
++	unsigned long flags;
++	int retval = -ENODEV;
++
++	dbg("In %s \n", __func__);
++
++	if (!serial)
++		return -ENODEV;
++
++	spin_lock_irqsave(&qt_port->lock, flags);
++
++	dbg("%s - port %d \n", __func__, port->number);
++	dbg("%s - qt_port->RxHolding = %d\n", __func__, qt_port->RxHolding);
++
++	retval = qt_real_tiocmset(tty, port, file, serial, set);
++
++	spin_unlock_irqrestore(&qt_port->lock, flags);
++	return retval;
++}
++
++static void qt_throttle(struct tty_struct *tty)
++{
++	struct usb_serial_port *port = tty->driver_data;
++	struct usb_serial *serial = get_usb_serial(port, __func__);
++	struct quatech_port *qt_port;
++	unsigned long flags;
++
++	dbg("%s - port %d\n", __func__, port->number);
++
++	if (!serial)
++		return;
++
++	qt_port = qt_get_port_private(port);
++
++	spin_lock_irqsave(&qt_port->lock, flags);
++
++	/* pass on to the driver specific version of this function */
++	qt_port->RxHolding = 1;
++	dbg("%s - port->RxHolding = 1\n", __func__);
++
++	spin_unlock_irqrestore(&qt_port->lock, flags);
++	return;
++}
++
++static void qt_unthrottle(struct tty_struct *tty)
++{
++	struct usb_serial_port *port = tty->driver_data;
++	struct usb_serial *serial = get_usb_serial(port, __func__);
++	struct quatech_port *qt_port;
++	unsigned long flags;
++	unsigned int result;
++
++	if (!serial)
++		return;
++
++	qt_port = qt_get_port_private(port);
++
++	spin_lock_irqsave(&qt_port->lock, flags);
++
++	dbg("%s - port %d\n", __func__, port->number);
++
++	if (qt_port->RxHolding == 1) {
++		dbg("%s -qt_port->RxHolding == 1\n", __func__);
++
++		qt_port->RxHolding = 0;
++		dbg("%s - qt_port->RxHolding = 0\n", __func__);
++
++		/* if we have a bulk endpoint, start it up */
++		if ((serial->num_bulk_in) && (qt_port->ReadBulkStopped == 1)) {
++			/* Start reading from the device */
++			usb_fill_bulk_urb(port->read_urb, serial->dev,
++					  usb_rcvbulkpipe(serial->dev,
++							  port->bulk_in_endpointAddress),
++					  port->read_urb->transfer_buffer,
++					  port->read_urb->
++					  transfer_buffer_length,
++					  qt_read_bulk_callback, port);
++			result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
++			if (result)
++				err("%s - failed restarting read urb, error %d",
++				    __func__, result);
++		}
++	}
++	spin_unlock_irqrestore(&qt_port->lock, flags);
++	return;
++
++}
++
++static int qt_calc_num_ports(struct usb_serial *serial)
++{
++	int num_ports;
++
++	dbg("numberofendpoints: %d \n",
++	    (int)serial->interface->cur_altsetting->desc.bNumEndpoints);
++	dbg("numberofendpoints: %d \n",
++	    (int)serial->interface->altsetting->desc.bNumEndpoints);
++
++	num_ports =
++	    (serial->interface->cur_altsetting->desc.bNumEndpoints - 1) / 2;
++
++	return num_ports;
++}
++
++static struct usb_serial_driver quatech_device = {
++	.driver = {
++		   .owner = THIS_MODULE,
++		   .name = "serqt",
++		   },
++	.description = DRIVER_DESC,
++	.usb_driver = &serqt_usb_driver,
++	.id_table = serqt_id_table,
++	.num_ports = 8,
++	.open = qt_open,
++	.close = qt_close,
++	.write = qt_write,
++	.write_room = qt_write_room,
++	.chars_in_buffer = qt_chars_in_buffer,
++	.throttle = qt_throttle,
++	.unthrottle = qt_unthrottle,
++	.calc_num_ports = qt_calc_num_ports,
++	.ioctl = qt_ioctl,
++	.set_termios = qt_set_termios,
++	.break_ctl = qt_break,
++	.tiocmget = qt_tiocmget,
++	.tiocmset = qt_tiocmset,
++	.attach = qt_startup,
++	.release = qt_release,
++};
++
++static int __init serqt_usb_init(void)
++{
++	int retval;
++
++	dbg("%s\n", __func__);
++
++	/* register with usb-serial */
++	retval = usb_serial_register(&quatech_device);
++
++	if (retval)
++		goto failed_usb_serial_register;
++
++	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
++	       DRIVER_DESC "\n");
++
++	/* register with usb */
++
++	retval = usb_register(&serqt_usb_driver);
++	if (retval == 0)
++		return 0;
++
++	/* if we're here, usb_register() failed */
++	usb_serial_deregister(&quatech_device);
++failed_usb_serial_register:
++	return retval;
++}
++
++static void __exit serqt_usb_exit(void)
++{
++	usb_deregister(&serqt_usb_driver);
++	usb_serial_deregister(&quatech_device);
++}
++
++module_init(serqt_usb_init);
++module_exit(serqt_usb_exit);
++
++MODULE_AUTHOR(DRIVER_AUTHOR);
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_LICENSE("GPL");
++
++module_param(debug, bool, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(debug, "Debug enabled or not");

commit dc8284611bf7ee2e871919fa441a9c7afe4d5486
+Author: Bill Pemberton 
+Date:   Wed Apr 22 08:59:15 2009 -0400
+
+    Staging: pohmelfs: Remove braces around single statements
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Evgeniy Polyakov 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/pohmelfs/dir.c b/drivers/staging/pohmelfs/dir.c
+index 71210b1c86c9..4c58e22c1fbe 100644
+--- a/drivers/staging/pohmelfs/dir.c
++++ b/drivers/staging/pohmelfs/dir.c
+@@ -692,9 +692,9 @@ static int pohmelfs_remove_entry(struct inode *dir, struct dentry *dentry)
+ 	n = pohmelfs_search_hash(parent, str.hash);
+ 	if (n) {
+ 		pohmelfs_fix_offset(parent, n);
+-		if (test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state)) {
++		if (test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state))
+ 			pohmelfs_remove_child(pi, n);
+-		}
++
+ 		pohmelfs_name_free(parent, n);
+ 		err = 0;
+ 	}
+@@ -1006,9 +1006,8 @@ static int pohmelfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 	pi = POHMELFS_I(inode);
+ 	old_parent = POHMELFS_I(old_dir);
+ 
+-	if (new_dir) {
++	if (new_dir)
+ 		new_dir->i_sb->s_op->write_inode(new_dir, 0);
+-	}
+ 
+ 	old_hash = jhash(old_dentry->d_name.name, old_dentry->d_name.len, 0);
+ 	str.hash = jhash(new_dentry->d_name.name, new_dentry->d_name.len, 0);
+diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c
+index 6256c5c7a5ad..882c619c01d0 100644
+--- a/drivers/staging/pohmelfs/inode.c
++++ b/drivers/staging/pohmelfs/inode.c
+@@ -1529,9 +1529,9 @@ static void pohmelfs_drop_scan(struct work_struct *work)
+ 	struct pohmelfs_inode *pi;
+ 	unsigned int count = 0;
+ 
+-	while ((pi = pohmelfs_get_inode_from_list(psb, &psb->drop_list, &count))) {
++	while ((pi = pohmelfs_get_inode_from_list(psb, &psb->drop_list, &count)))
+ 		pohmelfs_put_inode_count(pi, count);
+-	}
++
+ 	pohmelfs_check_states(psb);
+ 
+ 	if (psb->drop_scan_timeout)
+@@ -1568,9 +1568,8 @@ static void pohmelfs_trans_scan_state(struct netfs_state *st)
+ 		rb_node = rb_next(rb_node);
+ 
+ 		err = -ETIMEDOUT;
+-		if (timeout && (++dst->retries < psb->trans_retries)) {
++		if (timeout && (++dst->retries < psb->trans_retries))
+ 			err = netfs_trans_resend(t, psb);
+-		}
+ 
+ 		if (err || (t->flags & NETFS_TRANS_SINGLE_DST)) {
+ 			if (netfs_trans_remove_nolock(dst, st))
+diff --git a/drivers/staging/pohmelfs/net.c b/drivers/staging/pohmelfs/net.c
+index 3d1c0bc5558d..5f312c91aab6 100644
+--- a/drivers/staging/pohmelfs/net.c
++++ b/drivers/staging/pohmelfs/net.c
+@@ -914,9 +914,9 @@ static int pohmelfs_recv(void *data)
+ 				unsigned char *hash = e->data;
+ 
+ 				dprintk("%s: received hash: ", __func__);
+-				for (i=0; icsize; ++i) {
++				for (i=0; icsize; ++i)
+ 					printk("%02x ", hash[i]);
+-				}
++
+ 				printk("\n");
+ 			}
+ #endif
+diff --git a/drivers/staging/pohmelfs/trans.c b/drivers/staging/pohmelfs/trans.c
+index 2a4568d58012..4587f6d546aa 100644
+--- a/drivers/staging/pohmelfs/trans.c
++++ b/drivers/staging/pohmelfs/trans.c
+@@ -178,9 +178,9 @@ int netfs_trans_send(struct netfs_trans *t, struct netfs_state *st)
+ 
+ err_out_unlock_return:
+ 
+-	if (st->need_reset) {
++	if (st->need_reset)
+ 		netfs_state_exit(st);
+-	}
++
+ 	netfs_state_unlock_send(st);
+ 
+ 	dprintk("%s: t: %p, gen: %u, err: %d.\n",

commit 3bafeab78116bb58be3cafb06b401b2973a71ed4
+Author: Bill Pemberton 
+Date:   Wed Apr 22 08:59:14 2009 -0400
+
+    Staging: pohmelfs: Remove C99 comments
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Evgeniy Polyakov 
+
+diff --git a/drivers/staging/pohmelfs/dir.c b/drivers/staging/pohmelfs/dir.c
+index b5799842fb84..71210b1c86c9 100644
+--- a/drivers/staging/pohmelfs/dir.c
++++ b/drivers/staging/pohmelfs/dir.c
+@@ -562,7 +562,7 @@ struct dentry *pohmelfs_lookup(struct inode *dir, struct dentry *dentry, struct
+ 		if (!inode) {
+ 			dprintk("%s: No inode for ino: %lu, name: '%s', hash: %x.\n",
+ 				__func__, ino, str.name, str.hash);
+-			//return NULL;
++			/* return NULL; */
+ 			return ERR_PTR(-EACCES);
+ 		}
+ 	} else {
+diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c
+index b2eaf9047266..6256c5c7a5ad 100644
+--- a/drivers/staging/pohmelfs/inode.c
++++ b/drivers/staging/pohmelfs/inode.c
+@@ -386,7 +386,7 @@ static int pohmelfs_write_inode_create_children(struct inode *inode)
+ 		if (inode && (inode->i_state & I_DIRTY)) {
+ 			struct pohmelfs_inode *pi = POHMELFS_I(inode);
+ 			pohmelfs_write_create_inode(pi);
+-			//pohmelfs_meta_command(pi, NETFS_INODE_INFO, 0, NULL, NULL, 0);
++			/* pohmelfs_meta_command(pi, NETFS_INODE_INFO, 0, NULL, NULL, 0); */
+ 			iput(inode);
+ 		}
+ 	}
+@@ -845,7 +845,7 @@ static void pohmelfs_destroy_inode(struct inode *inode)
+ 	struct pohmelfs_sb *psb = POHMELFS_SB(sb);
+ 	struct pohmelfs_inode *pi = POHMELFS_I(inode);
+ 
+-	//pohmelfs_data_unlock(pi, 0, inode->i_size, POHMELFS_READ_LOCK);
++	/* pohmelfs_data_unlock(pi, 0, inode->i_size, POHMELFS_READ_LOCK); */
+ 
+ 	pohmelfs_inode_del_inode(psb, pi);
+ 
+@@ -1777,7 +1777,7 @@ static int pohmelfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
+ 		seq_printf(m, "%u ", ctl->idx);
+ 		if (ctl->addr.sa_family == AF_INET) {
+ 			struct sockaddr_in *sin = (struct sockaddr_in *)&st->ctl.addr;
+-			//seq_printf(m, "%pi4:%u", &sin->sin_addr.s_addr, ntohs(sin->sin_port));
++			/* seq_printf(m, "%pi4:%u", &sin->sin_addr.s_addr, ntohs(sin->sin_port)); */
+ 			seq_printf(m, "%u.%u.%u.%u:%u", NIPQUAD(sin->sin_addr.s_addr), ntohs(sin->sin_port));
+ 		} else if (ctl->addr.sa_family == AF_INET6) {
+ 			struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&st->ctl.addr;
+diff --git a/drivers/staging/pohmelfs/netfs.h b/drivers/staging/pohmelfs/netfs.h
+index 7ef2769f353d..3b60c611ba80 100644
+--- a/drivers/staging/pohmelfs/netfs.h
++++ b/drivers/staging/pohmelfs/netfs.h
+@@ -844,7 +844,7 @@ static inline int pohmelfs_need_lock(struct pohmelfs_inode *pi, int type)
+ int __init pohmelfs_mcache_init(void);
+ void pohmelfs_mcache_exit(void);
+ 
+-//#define CONFIG_POHMELFS_DEBUG
++/* #define CONFIG_POHMELFS_DEBUG */
+ 
+ #ifdef CONFIG_POHMELFS_DEBUG
+ #define dprintka(f, a...) printk(f, ##a)

commit 385e3f1a1464b4ec27bbd92a999f05de0dabaa85
+Author: Bill Pemberton 
+Date:   Wed Apr 22 08:59:13 2009 -0400
+
+    Staging: pohmelfs: move open brace to same line on structs
+    
+    Signed-off-by: Bill Pemberton 
+    Cc: Evgeniy Polyakov 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/pohmelfs/crypto.c b/drivers/staging/pohmelfs/crypto.c
+index 31d765de92ce..19781ad782fb 100644
+--- a/drivers/staging/pohmelfs/crypto.c
++++ b/drivers/staging/pohmelfs/crypto.c
+@@ -832,8 +832,7 @@ int pohmelfs_trans_crypt(struct netfs_trans *trans, struct pohmelfs_sb *psb)
+ 	return pohmelfs_crypto_thread_get(psb, pohmelfs_trans_crypt_action, trans);
+ }
+ 
+-struct pohmelfs_crypto_input_action_data
+-{
++struct pohmelfs_crypto_input_action_data {
+ 	struct page			*page;
+ 	struct pohmelfs_crypto_engine	*e;
+ 	u64				iv;
+diff --git a/drivers/staging/pohmelfs/net.c b/drivers/staging/pohmelfs/net.c
+index 11ecac026ca7..3d1c0bc5558d 100644
+--- a/drivers/staging/pohmelfs/net.c
++++ b/drivers/staging/pohmelfs/net.c
+@@ -168,8 +168,7 @@ int pohmelfs_data_recv_and_check(struct netfs_state *st, void *data, unsigned in
+  * Polling machinery.
+  */
+ 
+-struct netfs_poll_helper
+-{
++struct netfs_poll_helper {
+ 	poll_table 		pt;
+ 	struct netfs_state	*st;
+ };
+diff --git a/drivers/staging/pohmelfs/netfs.h b/drivers/staging/pohmelfs/netfs.h
+index c78cfcb042fb..7ef2769f353d 100644
+--- a/drivers/staging/pohmelfs/netfs.h
++++ b/drivers/staging/pohmelfs/netfs.h
+@@ -30,8 +30,7 @@
+  * Network command structure.
+  * Will be extended.
+  */
+-struct netfs_cmd
+-{
++struct netfs_cmd {
+ 	__u16			cmd;	/* Command number */
+ 	__u16			csize;	/* Attached crypto information size */
+ 	__u16			cpad;	/* Attached padding size */
+@@ -96,8 +95,7 @@ enum {
+  */
+ #define _K_SS_MAXSIZE	128
+ 
+-struct saddr
+-{
++struct saddr {
+ 	unsigned short		sa_family;
+ 	char			addr[_K_SS_MAXSIZE];
+ };
+@@ -107,8 +105,7 @@ enum {
+ 	POHMELFS_CRYPTO_CIPHER,
+ };
+ 
+-struct pohmelfs_crypto
+-{
++struct pohmelfs_crypto {
+ 	unsigned int		idx;		/* Config index */
+ 	unsigned short		strlen;		/* Size of the attached crypto string including 0-byte
+ 						 * "cbc(aes)" for example */
+@@ -123,8 +120,7 @@ struct pohmelfs_crypto
+ /*
+  * Configuration command used to create table of different remote servers.
+  */
+-struct pohmelfs_ctl
+-{
++struct pohmelfs_ctl {
+ 	__u32			idx;		/* Config index */
+ 	__u32			type;		/* Socket type */
+ 	__u32			proto;		/* Socket protocol */
+@@ -137,8 +133,7 @@ struct pohmelfs_ctl
+ /*
+  * Ack for userspace about requested command.
+  */
+-struct pohmelfs_cn_ack
+-{
++struct pohmelfs_cn_ack {
+ 	struct cn_msg		msg;
+ 	int			error;
+ 	int			msg_num;
+@@ -150,8 +145,7 @@ struct pohmelfs_cn_ack
+  * Inode info structure used to sync with server.
+  * Check what stat() returns.
+  */
+-struct netfs_inode_info
+-{
++struct netfs_inode_info {
+ 	unsigned int		mode;
+ 	unsigned int		nlink;
+ 	unsigned int		uid;
+@@ -205,8 +199,7 @@ enum pohmelfs_capabilities {
+ /* Extended attributes support on/off */
+ #define POHMELFS_FLAGS_XATTR		(1<<1)
+ 
+-struct netfs_root_capabilities
+-{
++struct netfs_root_capabilities {
+ 	__u64			nr_files;
+ 	__u64			used, avail;
+ 	__u64			flags;
+@@ -220,8 +213,7 @@ static inline void netfs_convert_root_capabilities(struct netfs_root_capabilitie
+ 	cap->flags = __cpu_to_be64(cap->flags);
+ }
+ 
+-struct netfs_crypto_capabilities
+-{
++struct netfs_crypto_capabilities {
+ 	unsigned short		hash_strlen;	/* Hash string length, like "hmac(sha1) including 0 byte "*/
+ 	unsigned short		cipher_strlen;	/* Cipher string length with the same format */
+ 	unsigned int		cipher_keysize;	/* Cipher key size */
+@@ -241,8 +233,7 @@ enum pohmelfs_lock_type {
+ 	POHMELFS_WRITE_LOCK,
+ };
+ 
+-struct netfs_lock
+-{
++struct netfs_lock {
+ 	__u64			start;
+ 	__u64			ino;
+ 	__u32			size;
+@@ -268,8 +259,7 @@ static inline void netfs_convert_lock(struct netfs_lock *lock)
+ /*
+  * Private POHMELFS cache of objects in directory.
+  */
+-struct pohmelfs_name
+-{
++struct pohmelfs_name {
+ 	struct rb_node		hash_node;
+ 
+ 	struct list_head	sync_create_entry;
+@@ -286,8 +276,7 @@ struct pohmelfs_name
+ /*
+  * POHMELFS inode. Main object.
+  */
+-struct pohmelfs_inode
+-{
++struct pohmelfs_inode {
+ 	struct list_head	inode_entry;		/* Entry in superblock list.
+ 							 * Objects which are not bound to dentry require to be dropped
+ 							 * in ->put_super()
+@@ -318,8 +307,7 @@ typedef int (* netfs_trans_complete_t)(struct page **pages, unsigned int page_nu
+ struct netfs_state;
+ struct pohmelfs_sb;
+ 
+-struct netfs_trans
+-{
++struct netfs_trans {
+ 	/*
+ 	 * Transaction header and attached contiguous data live here.
+ 	 */
+@@ -426,8 +414,7 @@ static inline void netfs_trans_reset(struct netfs_trans *t)
+ 	t->complete = NULL;
+ }
+ 
+-struct netfs_trans_dst
+-{
++struct netfs_trans_dst {
+ 	struct list_head		trans_entry;
+ 	struct rb_node			state_entry;
+ 
+@@ -456,8 +443,7 @@ int netfs_trans_remove_nolock(struct netfs_trans_dst *dst, struct netfs_state *s
+ int netfs_trans_init(void);
+ void netfs_trans_exit(void);
+ 
+-struct pohmelfs_crypto_engine
+-{
++struct pohmelfs_crypto_engine {
+ 	u64				iv;		/* Crypto IV for current operation */
+ 	unsigned long			timeout;	/* Crypto waiting timeout */
+ 	unsigned int			size;		/* Size of crypto scratchpad */
+@@ -474,8 +460,7 @@ struct pohmelfs_crypto_engine
+ 	unsigned int			page_num;
+ };
+ 
+-struct pohmelfs_crypto_thread
+-{
++struct pohmelfs_crypto_thread {
+ 	struct list_head		thread_entry;
+ 
+ 	struct task_struct		*thread;
+@@ -497,8 +482,7 @@ void pohmelfs_crypto_thread_make_ready(struct pohmelfs_crypto_thread *th);
+ /*
+  * Network state, attached to one server.
+  */
+-struct netfs_state
+-{
++struct netfs_state {
+ 	struct mutex		__state_lock;		/* Can not allow to use the same socket simultaneously */
+ 	struct mutex		__state_send_lock;
+ 	struct netfs_cmd 	cmd;			/* Cached command */
+@@ -580,8 +564,7 @@ static inline unsigned int netfs_state_poll(struct netfs_state *st)
+ 
+ struct pohmelfs_config;
+ 
+-struct pohmelfs_sb
+-{
++struct pohmelfs_sb {
+ 	struct rb_root		mcache_root;
+ 	struct mutex		mcache_lock;
+ 	atomic_long_t		mcache_gen;
+@@ -718,15 +701,13 @@ static inline void pohmelfs_put_inode(struct pohmelfs_inode *pi)
+ 	spin_unlock(&psb->ino_lock);
+ }
+ 
+-struct pohmelfs_config
+-{
++struct pohmelfs_config {
+ 	struct list_head	config_entry;
+ 
+ 	struct netfs_state	state;
+ };
+ 
+-struct pohmelfs_config_group
+-{
++struct pohmelfs_config_group {
+ 	/*
+ 	 * Entry in the global config group list.
+ 	 */
+@@ -814,8 +795,7 @@ void pohmelfs_switch_active(struct pohmelfs_sb *psb);
+ int pohmelfs_construct_path_string(struct pohmelfs_inode *pi, void *data, int len);
+ int pohmelfs_path_length(struct pohmelfs_inode *pi);
+ 
+-struct pohmelfs_crypto_completion
+-{
++struct pohmelfs_crypto_completion {
+ 	struct completion	complete;
+ 	int			error;
+ };
+@@ -891,8 +871,7 @@ static inline void netfs_trans_put(struct netfs_trans *t)
+ 	}
+ }
+ 
+-struct pohmelfs_mcache
+-{
++struct pohmelfs_mcache {
+ 	struct rb_node			mcache_entry;
+ 	struct completion		complete;
+ 

commit 0b8f754a6220158f2348bc6eae2772bc64bc98a2
+Author: Bill Pemberton 
+Date:   Thu May 14 15:24:29 2009 -0400
+
+    staging: comedi: Move pcm do_cmdtest function into a single source file
+    
+    Many of the comedi source code has functions that were created with
+    cut and paste, this moves the do_cmdtest function into a single file.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile
+index 4b56c07823b7..df2854d543cc 100644
+--- a/drivers/staging/comedi/drivers/Makefile
++++ b/drivers/staging/comedi/drivers/Makefile
+@@ -6,6 +6,7 @@ obj-$(CONFIG_COMEDI)			+= comedi_fc.o
+ obj-$(CONFIG_COMEDI)			+= comedi_bond.o
+ obj-$(CONFIG_COMEDI)			+= comedi_test.o
+ obj-$(CONFIG_COMEDI)			+= comedi_parport.o
++obj-$(CONFIG_COMEDI)			+= pcm_common.o
+ 
+ # Comedi PCI drivers
+ obj-$(CONFIG_COMEDI_PCI_DRIVERS)	+= 8255.o
+diff --git a/drivers/staging/comedi/drivers/pcm_common.c b/drivers/staging/comedi/drivers/pcm_common.c
+new file mode 100644
+index 000000000000..ebd9838232af
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/pcm_common.c
+@@ -0,0 +1,111 @@
++#include "../comedidev.h"
++#include "pcm_common.h"
++
++/*
++ * 'do_cmdtest' function for an 'INTERRUPT' subdevice.  This is for
++ * the PCM drivers.
++ */
++int comedi_pcm_cmdtest(struct comedi_device *dev,
++		       struct comedi_subdevice *s, struct comedi_cmd *cmd)
++{
++	int err = 0;
++	unsigned int tmp;
++
++	/* step 1: make sure trigger sources are trivially valid */
++
++	tmp = cmd->start_src;
++	cmd->start_src &= (TRIG_NOW | TRIG_INT);
++	if (!cmd->start_src || tmp != cmd->start_src)
++		err++;
++
++	tmp = cmd->scan_begin_src;
++	cmd->scan_begin_src &= TRIG_EXT;
++	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
++		err++;
++
++	tmp = cmd->convert_src;
++	cmd->convert_src &= TRIG_NOW;
++	if (!cmd->convert_src || tmp != cmd->convert_src)
++		err++;
++
++	tmp = cmd->scan_end_src;
++	cmd->scan_end_src &= TRIG_COUNT;
++	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
++		err++;
++
++	tmp = cmd->stop_src;
++	cmd->stop_src &= (TRIG_COUNT | TRIG_NONE);
++	if (!cmd->stop_src || tmp != cmd->stop_src)
++		err++;
++
++	if (err)
++		return 1;
++
++	/* step 2: make sure trigger sources are unique and mutually compatible */
++
++	/* these tests are true if more than one _src bit is set */
++	if ((cmd->start_src & (cmd->start_src - 1)) != 0)
++		err++;
++	if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
++		err++;
++	if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
++		err++;
++	if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
++		err++;
++	if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
++		err++;
++
++	if (err)
++		return 2;
++
++	/* step 3: make sure arguments are trivially compatible */
++
++	/* cmd->start_src == TRIG_NOW || cmd->start_src == TRIG_INT */
++	if (cmd->start_arg != 0) {
++		cmd->start_arg = 0;
++		err++;
++	}
++
++	/* cmd->scan_begin_src == TRIG_EXT */
++	if (cmd->scan_begin_arg != 0) {
++		cmd->scan_begin_arg = 0;
++		err++;
++	}
++
++	/* cmd->convert_src == TRIG_NOW */
++	if (cmd->convert_arg != 0) {
++		cmd->convert_arg = 0;
++		err++;
++	}
++
++	/* cmd->scan_end_src == TRIG_COUNT */
++	if (cmd->scan_end_arg != cmd->chanlist_len) {
++		cmd->scan_end_arg = cmd->chanlist_len;
++		err++;
++	}
++
++	switch (cmd->stop_src) {
++	case TRIG_COUNT:
++		/* any count allowed */
++		break;
++	case TRIG_NONE:
++		if (cmd->stop_arg != 0) {
++			cmd->stop_arg = 0;
++			err++;
++		}
++		break;
++	default:
++		break;
++	}
++
++	if (err)
++		return 3;
++
++	/* step 4: fix up any arguments */
++
++	/* if (err) return 4; */
++
++	return 0;
++}
++
++EXPORT_SYMBOL(comedi_pcm_cmdtest);
+diff --git a/drivers/staging/comedi/drivers/pcm_common.h b/drivers/staging/comedi/drivers/pcm_common.h
+new file mode 100644
+index 000000000000..cd4840c11444
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/pcm_common.h
+@@ -0,0 +1,8 @@
++#ifndef _comedi_common_H
++#define _comedi_common_H
++
++extern int comedi_pcm_cmdtest(struct comedi_device *dev,
++			      struct comedi_subdevice *s,
++			      struct comedi_cmd *cmd);
++
++#endif
+diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
+index e1ad03e234b7..cdf501afa14e 100644
+--- a/drivers/staging/comedi/drivers/pcmmio.c
++++ b/drivers/staging/comedi/drivers/pcmmio.c
+@@ -75,6 +75,7 @@ Configuration Options:
+ 
+ #include 
+ #include "../comedidev.h"
++#include "pcm_common.h"
+ #include 		/* for PCI devices */
+ 
+ /* This stuff is all from pcmuio.c -- it refers to the DIO subdevices only */
+@@ -1073,110 +1074,10 @@ static int pcmmio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ 	return 0;
+ }
+ 
+-/*
+- * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
+- */
+ static int
+ pcmmio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd)
+ {
+-	int err = 0;
+-	unsigned int tmp;
+-
+-	/* step 1: make sure trigger sources are trivially valid */
+-
+-	tmp = cmd->start_src;
+-	cmd->start_src &= (TRIG_NOW | TRIG_INT);
+-	if (!cmd->start_src || tmp != cmd->start_src)
+-		err++;
+-
+-	tmp = cmd->scan_begin_src;
+-	cmd->scan_begin_src &= TRIG_EXT;
+-	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
+-		err++;
+-
+-	tmp = cmd->convert_src;
+-	cmd->convert_src &= TRIG_NOW;
+-	if (!cmd->convert_src || tmp != cmd->convert_src)
+-		err++;
+-
+-	tmp = cmd->scan_end_src;
+-	cmd->scan_end_src &= TRIG_COUNT;
+-	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
+-		err++;
+-
+-	tmp = cmd->stop_src;
+-	cmd->stop_src &= (TRIG_COUNT | TRIG_NONE);
+-	if (!cmd->stop_src || tmp != cmd->stop_src)
+-		err++;
+-
+-	if (err)
+-		return 1;
+-
+-	/* step 2: make sure trigger sources are unique and mutually compatible */
+-
+-	/* these tests are true if more than one _src bit is set */
+-	if ((cmd->start_src & (cmd->start_src - 1)) != 0)
+-		err++;
+-	if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
+-		err++;
+-	if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
+-		err++;
+-	if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
+-		err++;
+-	if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
+-		err++;
+-
+-	if (err)
+-		return 2;
+-
+-	/* step 3: make sure arguments are trivially compatible */
+-
+-	/* cmd->start_src == TRIG_NOW || cmd->start_src == TRIG_INT */
+-	if (cmd->start_arg != 0) {
+-		cmd->start_arg = 0;
+-		err++;
+-	}
+-
+-	/* cmd->scan_begin_src == TRIG_EXT */
+-	if (cmd->scan_begin_arg != 0) {
+-		cmd->scan_begin_arg = 0;
+-		err++;
+-	}
+-
+-	/* cmd->convert_src == TRIG_NOW */
+-	if (cmd->convert_arg != 0) {
+-		cmd->convert_arg = 0;
+-		err++;
+-	}
+-
+-	/* cmd->scan_end_src == TRIG_COUNT */
+-	if (cmd->scan_end_arg != cmd->chanlist_len) {
+-		cmd->scan_end_arg = cmd->chanlist_len;
+-		err++;
+-	}
+-
+-	switch (cmd->stop_src) {
+-	case TRIG_COUNT:
+-		/* any count allowed */
+-		break;
+-	case TRIG_NONE:
+-		if (cmd->stop_arg != 0) {
+-			cmd->stop_arg = 0;
+-			err++;
+-		}
+-		break;
+-	default:
+-		break;
+-	}
+-
+-	if (err)
+-		return 3;
+-
+-	/* step 4: fix up any arguments */
+-
+-	/* if (err) return 4; */
+-
+-	return 0;
++	return comedi_pcm_cmdtest(dev, s, cmd);
+ }
+ 
+ static int adc_wait_ready(unsigned long iobase)
+diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
+index ce0aa6b87fb0..81ee7cdc0caf 100644
+--- a/drivers/staging/comedi/drivers/pcmuio.c
++++ b/drivers/staging/comedi/drivers/pcmuio.c
+@@ -77,6 +77,7 @@ Configuration Options:
+ 
+ #include 
+ #include "../comedidev.h"
++#include "pcm_common.h"
+ 
+ #include 		/* for PCI devices */
+ 
+@@ -984,110 +985,10 @@ static int pcmuio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ 	return 0;
+ }
+ 
+-/*
+- * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
+- */
+ static int
+ pcmuio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd)
+ {
+-	int err = 0;
+-	unsigned int tmp;
+-
+-	/* step 1: make sure trigger sources are trivially valid */
+-
+-	tmp = cmd->start_src;
+-	cmd->start_src &= (TRIG_NOW | TRIG_INT);
+-	if (!cmd->start_src || tmp != cmd->start_src)
+-		err++;
+-
+-	tmp = cmd->scan_begin_src;
+-	cmd->scan_begin_src &= TRIG_EXT;
+-	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
+-		err++;
+-
+-	tmp = cmd->convert_src;
+-	cmd->convert_src &= TRIG_NOW;
+-	if (!cmd->convert_src || tmp != cmd->convert_src)
+-		err++;
+-
+-	tmp = cmd->scan_end_src;
+-	cmd->scan_end_src &= TRIG_COUNT;
+-	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
+-		err++;
+-
+-	tmp = cmd->stop_src;
+-	cmd->stop_src &= (TRIG_COUNT | TRIG_NONE);
+-	if (!cmd->stop_src || tmp != cmd->stop_src)
+-		err++;
+-
+-	if (err)
+-		return 1;
+-
+-	/* step 2: make sure trigger sources are unique and mutually compatible */
+-
+-	/* these tests are true if more than one _src bit is set */
+-	if ((cmd->start_src & (cmd->start_src - 1)) != 0)
+-		err++;
+-	if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
+-		err++;
+-	if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
+-		err++;
+-	if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
+-		err++;
+-	if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
+-		err++;
+-
+-	if (err)
+-		return 2;
+-
+-	/* step 3: make sure arguments are trivially compatible */
+-
+-	/* cmd->start_src == TRIG_NOW || cmd->start_src == TRIG_INT */
+-	if (cmd->start_arg != 0) {
+-		cmd->start_arg = 0;
+-		err++;
+-	}
+-
+-	/* cmd->scan_begin_src == TRIG_EXT */
+-	if (cmd->scan_begin_arg != 0) {
+-		cmd->scan_begin_arg = 0;
+-		err++;
+-	}
+-
+-	/* cmd->convert_src == TRIG_NOW */
+-	if (cmd->convert_arg != 0) {
+-		cmd->convert_arg = 0;
+-		err++;
+-	}
+-
+-	/* cmd->scan_end_src == TRIG_COUNT */
+-	if (cmd->scan_end_arg != cmd->chanlist_len) {
+-		cmd->scan_end_arg = cmd->chanlist_len;
+-		err++;
+-	}
+-
+-	switch (cmd->stop_src) {
+-	case TRIG_COUNT:
+-		/* any count allowed */
+-		break;
+-	case TRIG_NONE:
+-		if (cmd->stop_arg != 0) {
+-			cmd->stop_arg = 0;
+-			err++;
+-		}
+-		break;
+-	default:
+-		break;
+-	}
+-
+-	if (err)
+-		return 3;
+-
+-	/* step 4: fix up any arguments */
+-
+-	/* if (err) return 4; */
+-
+-	return 0;
++	return comedi_pcm_cmdtest(dev, s, cmd);
+ }
+ 
+ /*

commit 214e7b5c8281bf41238f575128e4fec5652ed797
+Author: Bill Pemberton 
+Date:   Thu May 14 15:24:28 2009 -0400
+
+    staging: comedi: Remove MIN macro
+    
+    Remove the MIN() macro and instead use the min() provided by kernel.h
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c
+index f1a8cdfaaa48..6e172a6b1cb2 100644
+--- a/drivers/staging/comedi/drivers/pcmda12.c
++++ b/drivers/staging/comedi/drivers/pcmda12.c
+@@ -55,7 +55,6 @@ Configuration Options:
+ 
+ #include 		/* for PCI devices */
+ 
+-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+ #define SDEV_NO ((int)(s - dev->subdevices))
+ #define CHANS 8
+ #define IOSIZE 16
+diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
+index 6931f1075089..e1ad03e234b7 100644
+--- a/drivers/staging/comedi/drivers/pcmmio.c
++++ b/drivers/staging/comedi/drivers/pcmmio.c
+@@ -77,8 +77,6 @@ Configuration Options:
+ #include "../comedidev.h"
+ #include 		/* for PCI devices */
+ 
+-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+-
+ /* This stuff is all from pcmuio.c -- it refers to the DIO subdevices only */
+ #define CHANS_PER_PORT   8
+ #define PORTS_PER_ASIC   6
+@@ -436,7 +434,7 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 		s->type = COMEDI_SUBD_DIO;
+ 		s->insn_bits = pcmmio_dio_insn_bits;
+ 		s->insn_config = pcmmio_dio_insn_config;
+-		s->n_chan = MIN(chans_left, MAX_CHANS_PER_SUBDEV);
++		s->n_chan = min(chans_left, MAX_CHANS_PER_SUBDEV);
+ 		subpriv->dio.intr.asic = -1;
+ 		subpriv->dio.intr.first_chan = -1;
+ 		subpriv->dio.intr.asic_chan = -1;
+diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
+index 8df67c37795b..ce0aa6b87fb0 100644
+--- a/drivers/staging/comedi/drivers/pcmuio.c
++++ b/drivers/staging/comedi/drivers/pcmuio.c
+@@ -80,7 +80,6 @@ Configuration Options:
+ 
+ #include 		/* for PCI devices */
+ 
+-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+ #define CHANS_PER_PORT   8
+ #define PORTS_PER_ASIC   6
+ #define INTR_PORTS_PER_ASIC   3
+@@ -360,7 +359,7 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 		s->type = COMEDI_SUBD_DIO;
+ 		s->insn_bits = pcmuio_dio_insn_bits;
+ 		s->insn_config = pcmuio_dio_insn_config;
+-		s->n_chan = MIN(chans_left, MAX_CHANS_PER_SUBDEV);
++		s->n_chan = min(chans_left, MAX_CHANS_PER_SUBDEV);
+ 		subpriv->intr.asic = -1;
+ 		subpriv->intr.first_chan = -1;
+ 		subpriv->intr.asic_chan = -1;

commit ba7834b3f335f6bdef95e416d72245f6687cc660
+Author: Bill Pemberton 
+Date:   Sun Apr 26 14:45:12 2009 -0400
+
+    Staging: comedi: simply read and write functions in adl_pci8164
+    
+    There are several read and write functions in adl_pci8164 that are
+    essentially the same thing.  They were created with a cut and paste.
+    Change them to use a common function.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c
+index 2fe577a973af..2d7d68af6b1e 100644
+--- a/drivers/staging/comedi/drivers/adl_pci8164.c
++++ b/drivers/staging/comedi/drivers/adl_pci8164.c
+@@ -208,8 +208,16 @@ static int adl_pci8164_detach(struct comedi_device *dev)
+ 	return 0;
+ }
+ 
+-static int adl_pci8164_insn_read_msts(struct comedi_device *dev, struct comedi_subdevice *s,
+-	struct comedi_insn *insn, unsigned int *data)
++/*
++ all the read commands are the same except for the addition a constant
++ * const to the data for inw()
++ */
++static void adl_pci8164_insn_read(struct comedi_device *dev,
++				  struct comedi_subdevice *s,
++				  struct comedi_insn *insn,
++				  unsigned int *data,
++				  char *action,
++				  unsigned short offset)
+ {
+ 	int axis, axis_reg;
+ 	char *axisname;
+@@ -238,127 +246,51 @@ static int adl_pci8164_insn_read_msts(struct comedi_device *dev, struct comedi_s
+ 		axisname = "X";
+ 	}
+ 
+-	data[0] = inw(dev->iobase + axis_reg + PCI8164_MSTS);
+-	printk("comedi: pci8164 MSTS read -> %04X:%04X on axis %s\n", data[0],
++	data[0] = inw(dev->iobase + axis_reg + offset);
++	printk("comedi: pci8164 %s read -> %04X:%04X on axis %s\n", action, data[0],
+ 		data[1], axisname);
++}
+ 
++static int adl_pci8164_insn_read_msts(struct comedi_device *dev,
++				      struct comedi_subdevice *s,
++				      struct comedi_insn *insn,
++				      unsigned int *data)
++{
++	adl_pci8164_insn_read(dev, s, insn, data, "MSTS", PCI8164_MSTS);
+ 	return 2;
+ }
+ 
+ static int adl_pci8164_insn_read_ssts(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	struct comedi_insn *insn, unsigned int *data)
+ {
+-	int axis, axis_reg;
+-	char *axisname;
+-
+-	axis = CR_CHAN(insn->chanspec);
+-
+-	switch (axis) {
+-	case 0:
+-		axis_reg = PCI8164_AXIS_X;
+-		axisname = "X";
+-		break;
+-	case 1:
+-		axis_reg = PCI8164_AXIS_Y;
+-		axisname = "Y";
+-		break;
+-	case 2:
+-		axis_reg = PCI8164_AXIS_Z;
+-		axisname = "Z";
+-		break;
+-	case 3:
+-		axis_reg = PCI8164_AXIS_U;
+-		axisname = "U";
+-		break;
+-	default:
+-		axis_reg = PCI8164_AXIS_X;
+-		axisname = "X";
+-	}
+-
+-	data[0] = inw(dev->iobase + axis_reg + PCI8164_SSTS);
+-	printk("comedi: pci8164 SSTS read -> %04X:%04X on axis %s\n", data[0],
+-		data[1], axisname);
+-
++	adl_pci8164_insn_read(dev, s, insn, data, "SSTS", PCI8164_SSTS);
+ 	return 2;
+ }
+ 
+ static int adl_pci8164_insn_read_buf0(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	struct comedi_insn *insn, unsigned int *data)
+ {
+-	int axis, axis_reg;
+-	char *axisname;
+-
+-	axis = CR_CHAN(insn->chanspec);
+-
+-	switch (axis) {
+-	case 0:
+-		axis_reg = PCI8164_AXIS_X;
+-		axisname = "X";
+-		break;
+-	case 1:
+-		axis_reg = PCI8164_AXIS_Y;
+-		axisname = "Y";
+-		break;
+-	case 2:
+-		axis_reg = PCI8164_AXIS_Z;
+-		axisname = "Z";
+-		break;
+-	case 3:
+-		axis_reg = PCI8164_AXIS_U;
+-		axisname = "U";
+-		break;
+-	default:
+-		axis_reg = PCI8164_AXIS_X;
+-		axisname = "X";
+-	}
+-
+-	data[0] = inw(dev->iobase + axis_reg + PCI8164_BUF0);
+-	printk("comedi: pci8164 BUF0 read -> %04X:%04X on axis %s\n", data[0],
+-		data[1], axisname);
+-
++	adl_pci8164_insn_read(dev, s, insn, data, "BUF0", PCI8164_BUF0);
+ 	return 2;
+ }
+ 
+ static int adl_pci8164_insn_read_buf1(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	struct comedi_insn *insn, unsigned int *data)
+ {
+-	int axis, axis_reg;
+-
+-	char *axisname;
+-
+-	axis = CR_CHAN(insn->chanspec);
+-
+-	switch (axis) {
+-	case 0:
+-		axis_reg = PCI8164_AXIS_X;
+-		axisname = "X";
+-		break;
+-	case 1:
+-		axis_reg = PCI8164_AXIS_Y;
+-		axisname = "Y";
+-		break;
+-	case 2:
+-		axis_reg = PCI8164_AXIS_Z;
+-		axisname = "Z";
+-		break;
+-	case 3:
+-		axis_reg = PCI8164_AXIS_U;
+-		axisname = "U";
+-		break;
+-	default:
+-		axis_reg = PCI8164_AXIS_X;
+-		axisname = "X";
+-	}
+-
+-	data[0] = inw(dev->iobase + axis_reg + PCI8164_BUF1);
+-	printk("comedi: pci8164 BUF1 read -> %04X:%04X on axis %s\n", data[0],
+-		data[1], axisname);
+-
++	adl_pci8164_insn_read(dev, s, insn, data, "BUF1", PCI8164_BUF1);
+ 	return 2;
+ }
+ 
+-static int adl_pci8164_insn_write_cmd(struct comedi_device *dev, struct comedi_subdevice *s,
+-	struct comedi_insn *insn, unsigned int *data)
++/*
++ all the write commands are the same except for the addition a constant
++ * const to the data for outw()
++ */
++static void adl_pci8164_insn_out(struct comedi_device *dev,
++					struct comedi_subdevice *s,
++					struct comedi_insn *insn,
++					unsigned int *data,
++					char *action,
++					unsigned short offset)
+ {
+ 	unsigned int axis, axis_reg;
+ 
+@@ -388,124 +320,39 @@ static int adl_pci8164_insn_write_cmd(struct comedi_device *dev, struct comedi_s
+ 		axisname = "X";
+ 	}
+ 
+-	outw(data[0], dev->iobase + axis_reg + PCI8164_CMD);
+-	printk("comedi: pci8164 CMD write -> %04X:%04X on axis %s\n", data[0],
+-		data[1], axisname);
++	outw(data[0], dev->iobase + axis_reg + offset);
+ 
++	printk("comedi: pci8164 %s write -> %04X:%04X on axis %s\n", action,
++	       data[0], data[1], axisname);
++
++}
++
++
++static int adl_pci8164_insn_write_cmd(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
++{
++	adl_pci8164_insn_out(dev, s, insn, data, "CMD", PCI8164_CMD);
+ 	return 2;
+ }
+ 
+ static int adl_pci8164_insn_write_otp(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	struct comedi_insn *insn, unsigned int *data)
+ {
+-	int axis, axis_reg;
+-
+-	char *axisname;
+-
+-	axis = CR_CHAN(insn->chanspec);
+-
+-	switch (axis) {
+-	case 0:
+-		axis_reg = PCI8164_AXIS_X;
+-		axisname = "X";
+-		break;
+-	case 1:
+-		axis_reg = PCI8164_AXIS_Y;
+-		axisname = "Y";
+-		break;
+-	case 2:
+-		axis_reg = PCI8164_AXIS_Z;
+-		axisname = "Z";
+-		break;
+-	case 3:
+-		axis_reg = PCI8164_AXIS_U;
+-		axisname = "U";
+-		break;
+-	default:
+-		axis_reg = PCI8164_AXIS_X;
+-		axisname = "X";
+-	}
+-
+-	outw(data[0], dev->iobase + axis_reg + PCI8164_OTP);
+-	printk("comedi: pci8164 OTP write -> %04X:%04X on axis %s\n", data[0],
+-		data[1], axisname);
+-
++	adl_pci8164_insn_out(dev, s, insn, data, "OTP", PCI8164_OTP);
+ 	return 2;
+ }
+ 
+ static int adl_pci8164_insn_write_buf0(struct comedi_device *dev,
+ 	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+-	int axis, axis_reg;
+-
+-	char *axisname;
+-
+-	axis = CR_CHAN(insn->chanspec);
+-
+-	switch (axis) {
+-	case 0:
+-		axis_reg = PCI8164_AXIS_X;
+-		axisname = "X";
+-		break;
+-	case 1:
+-		axis_reg = PCI8164_AXIS_Y;
+-		axisname = "Y";
+-		break;
+-	case 2:
+-		axis_reg = PCI8164_AXIS_Z;
+-		axisname = "Z";
+-		break;
+-	case 3:
+-		axis_reg = PCI8164_AXIS_U;
+-		axisname = "U";
+-		break;
+-	default:
+-		axis_reg = PCI8164_AXIS_X;
+-		axisname = "X";
+-	}
+-
+-	outw(data[0], dev->iobase + axis_reg + PCI8164_BUF0);
+-	printk("comedi: pci8164 BUF0 write -> %04X:%04X on axis %s\n", data[0],
+-		data[1], axisname);
+-
++	adl_pci8164_insn_out(dev, s, insn, data, "BUF0", PCI8164_BUF0);
+ 	return 2;
+ }
+ 
+ static int adl_pci8164_insn_write_buf1(struct comedi_device *dev,
+ 	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+-	int axis, axis_reg;
+-
+-	char *axisname;
+-
+-	axis = CR_CHAN(insn->chanspec);
+-
+-	switch (axis) {
+-	case 0:
+-		axis_reg = PCI8164_AXIS_X;
+-		axisname = "X";
+-		break;
+-	case 1:
+-		axis_reg = PCI8164_AXIS_Y;
+-		axisname = "Y";
+-		break;
+-	case 2:
+-		axis_reg = PCI8164_AXIS_Z;
+-		axisname = "Z";
+-		break;
+-	case 3:
+-		axis_reg = PCI8164_AXIS_U;
+-		axisname = "U";
+-		break;
+-	default:
+-		axis_reg = PCI8164_AXIS_X;
+-		axisname = "X";
+-	}
+-
+-	outw(data[0], dev->iobase + axis_reg + PCI8164_BUF1);
+-	printk("comedi: pci8164 BUF1 write -> %04X:%04X on axis %s\n", data[0],
+-		data[1], axisname);
+-
++	adl_pci8164_insn_out(dev, s, insn, data, "BUF1", PCI8164_BUF1);
+ 	return 2;
+ }
+ 

commit 8605b3aa0c107b5df59e99dbde2e708aa0012efd
+Author: Bill Pemberton 
+Date:   Sun Apr 26 14:45:11 2009 -0400
+
+    Staging: comedi: replace for loop with msleep()
+    
+    Replace 2 attempts to use a for loop as a sleep with a call to msleep().
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
+index 556ed46d78a7..6e9e7ed4dba9 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
+@@ -180,7 +180,7 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 			}
+ 
+ 			/* Sleep */
+-			for (i = 0; i < 10000; i++) ;
++			msleep(1);
+ 
+ 		}
+ 		w_ReadWord =
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+index 89d4e21b9954..9b53255bd45b 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+@@ -224,7 +224,7 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 
+ 
+ 			/* Sleep */
+-			for (i = 0; i < 10000; i++) ;
++			msleep(1);
+ 
+ 		}
+ 		w_ReadWord =

commit ff89514f8d46f470ffafeda129138ce73efd4c60
+Author: Bill Pemberton 
+Date:   Thu Apr 23 15:54:58 2009 -0400
+
+    Staging: comedi: move while to same line as } in do loops
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+index a94b98093826..a445dab50eac 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+@@ -477,9 +477,8 @@ int i_APCI1710_InsnReadSSIValue(struct comedi_device *dev, struct comedi_subdevi
+ 								s_BoardInfos.
+ 								ui_Address +
+ 								(64 * b_ModulNbr));
+-						}
+-						while ((dw_StatusReg & 0x1) !=
+-							0);
++						} while ((dw_StatusReg & 0x1)
++							 != 0);
+ 
+ 		    /******************************/
+ 						/* Read the SSI counter value */
+@@ -608,8 +607,7 @@ int i_APCI1710_InsnReadSSIValue(struct comedi_device *dev, struct comedi_subdevi
+ 							s_BoardInfos.
+ 							ui_Address +
+ 							(64 * b_ModulNbr));
+-					}
+-					while ((dw_StatusReg & 0x1) != 0);
++					} while ((dw_StatusReg & 0x1) != 0);
+ 
+ 					for (b_SSICpt = 0; b_SSICpt < 3;
+ 						b_SSICpt++) {
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
+index 6ada45a46d67..556ed46d78a7 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
+@@ -88,8 +88,7 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 				inl(dw_PCIBoardEepromAddress +
+ 				AMCC_OP_REG_MCSR);
+ 			dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+-		}
+-		while (dw_eeprom_busy == EEPROM_BUSY);
++		} while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+ 		for (i_Counter = 0; i_Counter < 2; i_Counter++) {
+ 			b_SelectedAddressLow = (w_EepromStartAddress + i_Counter) % 256;	/* Read the low 8 bit part */
+@@ -106,8 +105,7 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 					inl(dw_PCIBoardEepromAddress +
+ 					AMCC_OP_REG_MCSR);
+ 				dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+-			}
+-			while (dw_eeprom_busy == EEPROM_BUSY);
++			} while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+ 			/* Load the low address */
+ 			outb(b_SelectedAddressLow,
+@@ -120,8 +118,7 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 					inl(dw_PCIBoardEepromAddress +
+ 					AMCC_OP_REG_MCSR);
+ 				dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+-			}
+-			while (dw_eeprom_busy == EEPROM_BUSY);
++			} while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+ 			/* Select the load high address mode */
+ 			outb(NVCMD_LOAD_HIGH,
+@@ -134,8 +131,7 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 					inl(dw_PCIBoardEepromAddress +
+ 					AMCC_OP_REG_MCSR);
+ 				dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+-			}
+-			while (dw_eeprom_busy == EEPROM_BUSY);
++			} while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+ 			/* Load the high address */
+ 			outb(b_SelectedAddressHigh,
+@@ -148,8 +144,7 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 					inl(dw_PCIBoardEepromAddress +
+ 					AMCC_OP_REG_MCSR);
+ 				dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+-			}
+-			while (dw_eeprom_busy == EEPROM_BUSY);
++			} while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+ 			/* Select the READ mode */
+ 			outb(NVCMD_BEGIN_READ,
+@@ -162,8 +157,7 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 					inl(dw_PCIBoardEepromAddress +
+ 					AMCC_OP_REG_MCSR);
+ 				dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+-			}
+-			while (dw_eeprom_busy == EEPROM_BUSY);
++			} while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+ 			/* Read data into the EEPROM */
+ 			*pb_ReadByte =
+@@ -176,8 +170,7 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 					inl(dw_PCIBoardEepromAddress +
+ 					AMCC_OP_REG_MCSR);
+ 				dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+-			}
+-			while (dw_eeprom_busy == EEPROM_BUSY);
++			} while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+ 			/* Select the upper address part */
+ 			if (i_Counter == 0) {
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+index 208ade70ad0c..69b427390e53 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+@@ -411,8 +411,7 @@ void v_EepromWaitBusy(unsigned short w_PCIBoardEepromAddress)
+ 		b_EepromBusy = inb(w_PCIBoardEepromAddress + 0x3F);
+ 		b_EepromBusy = b_EepromBusy & 0x80;
+ 
+-	}
+-	while (b_EepromBusy == 0x80);
++	} while (b_EepromBusy == 0x80);
+ 
+ }
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+index 26aaeaf25683..69d5c3a92f08 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+@@ -368,9 +368,8 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev, struct comedi_subd
+ 					us_TmpValue =
+ 						inw(devpriv->iobase +
+ 						APCI3120_RD_STATUS);
+-				}
+-				while ((us_TmpValue & APCI3120_EOS) !=
+-					APCI3120_EOS);
++				} while ((us_TmpValue & APCI3120_EOS) !=
++					 APCI3120_EOS);
+ 
+ 				for (i = 0; i < devpriv->ui_AiNbrofChannels;
+ 					i++) {
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+index 7dda06653402..89d4e21b9954 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+@@ -132,8 +132,7 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 				inl(dw_PCIBoardEepromAddress +
+ 				AMCC_OP_REG_MCSR);
+ 			dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+-		}
+-		while (dw_eeprom_busy == EEPROM_BUSY);
++		} while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+ 		for (i_Counter = 0; i_Counter < 2; i_Counter++) {
+ 			b_SelectedAddressLow = (w_EepromStartAddress + i_Counter) % 256;	/* Read the low 8 bit part */
+@@ -150,8 +149,7 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 					inl(dw_PCIBoardEepromAddress +
+ 					AMCC_OP_REG_MCSR);
+ 				dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+-			}
+-			while (dw_eeprom_busy == EEPROM_BUSY);
++			} while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+ 			/* Load the low address */
+ 			outb(b_SelectedAddressLow,
+@@ -164,8 +162,7 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 					inl(dw_PCIBoardEepromAddress +
+ 					AMCC_OP_REG_MCSR);
+ 				dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+-			}
+-			while (dw_eeprom_busy == EEPROM_BUSY);
++			} while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+ 			/* Select the load high address mode */
+ 			outb(NVCMD_LOAD_HIGH,
+@@ -178,8 +175,7 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 					inl(dw_PCIBoardEepromAddress +
+ 					AMCC_OP_REG_MCSR);
+ 				dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+-			}
+-			while (dw_eeprom_busy == EEPROM_BUSY);
++			} while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+ 			/* Load the high address */
+ 			outb(b_SelectedAddressHigh,
+@@ -192,8 +188,7 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 					inl(dw_PCIBoardEepromAddress +
+ 					AMCC_OP_REG_MCSR);
+ 				dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+-			}
+-			while (dw_eeprom_busy == EEPROM_BUSY);
++			} while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+ 			/* Select the READ mode */
+ 			outb(NVCMD_BEGIN_READ,
+@@ -206,8 +201,7 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 					inl(dw_PCIBoardEepromAddress +
+ 					AMCC_OP_REG_MCSR);
+ 				dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+-			}
+-			while (dw_eeprom_busy == EEPROM_BUSY);
++			} while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+ 			/* Read data into the EEPROM */
+ 			*pb_ReadByte =
+@@ -220,15 +214,14 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 					inl(dw_PCIBoardEepromAddress +
+ 					AMCC_OP_REG_MCSR);
+ 				dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+-			}
+-			while (dw_eeprom_busy == EEPROM_BUSY);
++			} while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+ 			/* Select the upper address part */
+-			if (i_Counter == 0) {
++			if (i_Counter == 0)
+ 				b_ReadLowByte = pb_ReadByte[0];
+-			} else {
++			else
+ 				b_ReadHighByte = pb_ReadByte[0];
+-			}
++
+ 
+ 			/* Sleep */
+ 			for (i = 0; i < 10000; i++) ;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+index 30594c8acd35..338727879827 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+@@ -535,8 +535,7 @@ int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device *dev,
+ 								dw_Temp =
+ 									dw_Temp
+ 									& 1;
+-							}
+-							while (dw_Temp != 1);
++							} while (dw_Temp != 1);
+ 
+ 			  /*************************/
+ 							/* Read the analog value */
+@@ -729,8 +728,7 @@ int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device *dev,
+ 					dw_Status =
+ 						readl((void *)(devpriv->
+ 							dw_AiBase + 96));
+-				}
+-				while ((dw_Status & 0x100) != 0x100);
++				} while ((dw_Status & 0x100) != 0x100);
+ 			} else {
+ 		 /***************************/
+ 				/* Channel not initialised */

commit c4d30ee861c3a3a361f934e6f96b1d07a2889976
+Author: Bill Pemberton 
+Date:   Thu Apr 23 15:54:57 2009 -0400
+
+    Staging: comedi: comment out useless if
+    
+    This if test doesn't do anything, so comment it out.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c
+index 2e181f01d39d..bdc3957bceb8 100644
+--- a/drivers/staging/comedi/drivers/8255.c
++++ b/drivers/staging/comedi/drivers/8255.c
+@@ -361,8 +361,10 @@ int subdev_8255_init_irq(struct comedi_device *dev, struct comedi_subdevice * s,
+ void subdev_8255_cleanup(struct comedi_device *dev, struct comedi_subdevice * s)
+ {
+ 	if (s->private) {
+-		if (subdevpriv->have_irq) {
+-		}
++		/* this test does nothing, so comment it out
++		 * if (subdevpriv->have_irq) {
++		 * }
++		 */
+ 
+ 		kfree(s->private);
+ 	}

commit 8629efa4cbf6f89a54a85af4b8bc31762af01800
+Author: Bill Pemberton 
+Date:   Thu Apr 23 15:54:56 2009 -0400
+
+    Staging: comedi: make use of ARRAY_SIZE macro
+    
+    Replace instances of computing number of elements in an array with
+    sizeof(foo)/sizeof(struct footype) with the ARRAY_SIZE macro.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
+index cabbf090f60b..e5185ac3604c 100644
+--- a/drivers/staging/comedi/drivers.c
++++ b/drivers/staging/comedi/drivers.c
+@@ -853,7 +853,8 @@ int comedi_pci_auto_config(struct pci_dev *pcidev, const char *board_name)
+ 	/*  pci slot */
+ 	options[1] = PCI_SLOT(pcidev->devfn);
+ 
+-	return comedi_auto_config(&pcidev->dev, board_name, options, sizeof(options) / sizeof(options[0]));
++	return comedi_auto_config(&pcidev->dev, board_name,
++				  options, ARRAY_SIZE(options));
+ }
+ 
+ void comedi_pci_auto_unconfig(struct pci_dev *pcidev)
+diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c
+index 7cd6043ed49f..b4807fc7eb01 100644
+--- a/drivers/staging/comedi/drivers/adl_pci6208.c
++++ b/drivers/staging/comedi/drivers/adl_pci6208.c
+@@ -110,9 +110,6 @@ struct pci6208_private {
+ static int pci6208_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int pci6208_detach(struct comedi_device *dev);
+ 
+-#define pci6208_board_nbr \
+-	(sizeof(pci6208_boards) / sizeof(struct pci6208_board))
+-
+ static struct comedi_driver driver_pci6208 = {
+ 	.driver_name = PCI6208_DRIVER_NAME,
+ 	.module = THIS_MODULE,
+@@ -315,7 +312,7 @@ static int pci6208_find_device(struct comedi_device *dev, int bus, int slot)
+ 		pci_dev != NULL;
+ 		pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) {
+ 		if (pci_dev->vendor == PCI_VENDOR_ID_ADLINK) {
+-			for (i = 0; i < pci6208_board_nbr; i++) {
++			for (i = 0; i < ARRAY_SIZE(pci6208_boards); i++) {
+ 				if (pci6208_boards[i].dev_id == pci_dev->device) {
+ 					/*  was a particular bus/slot requested? */
+ 					if ((bus != 0) || (slot != 0)) {
+diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c
+index 54724653a792..c51e9ba58808 100644
+--- a/drivers/staging/comedi/drivers/adq12b.c
++++ b/drivers/staging/comedi/drivers/adq12b.c
+@@ -171,7 +171,7 @@ static struct comedi_driver driver_adq12b={
+         detach:         adq12b_detach,
+         board_name:     &adq12b_boards[0].name,
+         offset:         sizeof(struct adq12b_board),
+-        num_names:      sizeof(adq12b_boards) / sizeof(struct adq12b_board),
++        num_names:      ARRAY_SIZE(adq12b_boards),
+ };
+ 
+ static int adq12b_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c
+index 764cac2fd7d2..d062f8619b6e 100644
+--- a/drivers/staging/comedi/drivers/aio_iiro_16.c
++++ b/drivers/staging/comedi/drivers/aio_iiro_16.c
+@@ -78,7 +78,7 @@ static struct comedi_driver driver_aio_iiro_16 = {
+ 	.detach = aio_iiro_16_detach,
+ 	.board_name = &aio_iiro_16_boards[0].name,
+ 	.offset = sizeof(struct aio_iiro_16_board),
+-	.num_names = sizeof(aio_iiro_16_boards) / sizeof(struct aio_iiro_16_board),
++	.num_names = ARRAY_SIZE(aio_iiro_16_boards),
+ };
+ 
+ static int aio_iiro_16_dio_insn_bits_read(struct comedi_device *dev,
+diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
+index 582d6a2cfef6..ddf58d4866eb 100644
+--- a/drivers/staging/comedi/drivers/amplc_dio200.c
++++ b/drivers/staging/comedi/drivers/amplc_dio200.c
+@@ -484,7 +484,7 @@ static struct comedi_driver driver_amplc_dio200 = {
+ 	.detach = dio200_detach,
+ 	.board_name = &dio200_boards[0].name,
+ 	.offset = sizeof(struct dio200_board),
+-	.num_names = sizeof(dio200_boards) / sizeof(struct dio200_board),
++	.num_names = ARRAY_SIZE(dio200_boards),
+ };
+ 
+ #ifdef CONFIG_COMEDI_PCI
+diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
+index 3befe507ce2f..235cbfffa14b 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc236.c
++++ b/drivers/staging/comedi/drivers/amplc_pc236.c
+@@ -176,7 +176,7 @@ static struct comedi_driver driver_amplc_pc236 = {
+ 	.detach = pc236_detach,
+ 	.board_name = &pc236_boards[0].name,
+ 	.offset = sizeof(struct pc236_board),
+-	.num_names = sizeof(pc236_boards) / sizeof(struct pc236_board),
++	.num_names = ARRAY_SIZE(pc236_boards),
+ };
+ 
+ #ifdef CONFIG_COMEDI_PCI
+diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
+index 1d516b1f1591..c804c7c649c1 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc263.c
++++ b/drivers/staging/comedi/drivers/amplc_pc263.c
+@@ -141,7 +141,7 @@ static struct comedi_driver driver_amplc_pc263 = {
+ 	.detach = pc263_detach,
+ 	.board_name = &pc263_boards[0].name,
+ 	.offset = sizeof(struct pc263_board),
+-	.num_names = sizeof(pc263_boards) / sizeof(struct pc263_board),
++	.num_names = ARRAY_SIZE(pc263_boards),
+ };
+ 
+ static int pc263_request_region(unsigned minor, unsigned long from,
+diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
+index 19e4428c3380..6b53cb4b93f9 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci224.c
++++ b/drivers/staging/comedi/drivers/amplc_pci224.c
+@@ -437,7 +437,7 @@ static struct comedi_driver driver_amplc_pci224 = {
+ 	.detach = pci224_detach,
+ 	.board_name = &pci224_boards[0].name,
+ 	.offset = sizeof(struct pci224_board),
+-	.num_names = sizeof(pci224_boards) / sizeof(struct pci224_board),
++	.num_names = ARRAY_SIZE(pci224_boards),
+ };
+ 
+ COMEDI_PCI_INITCLEANUP(driver_amplc_pci224, pci224_pci_table);
+diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
+index 1d675173cd32..057443551c23 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci230.c
++++ b/drivers/staging/comedi/drivers/amplc_pci230.c
+@@ -612,7 +612,7 @@ static struct comedi_driver driver_amplc_pci230 = {
+ 	.detach = pci230_detach,
+ 	.board_name = &pci230_boards[0].name,
+ 	.offset = sizeof(pci230_boards[0]),
+-	.num_names = sizeof(pci230_boards) / sizeof(pci230_boards[0]),
++	.num_names = ARRAY_SIZE(pci230_boards),
+ };
+ 
+ COMEDI_PCI_INITCLEANUP(driver_amplc_pci230, pci230_pci_table);
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
+index 17dec7567481..11212b01d493 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas.c
+@@ -375,9 +375,6 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = {
+ 		},
+ };
+ 
+-/* Number of boards in cb_pcidas_boards */
+-#define N_BOARDS	(sizeof(cb_pcidas_boards) / sizeof(struct cb_pcidas_board))
+-
+ static DEFINE_PCI_DEVICE_TABLE(cb_pcidas_pci_table) = {
+ 	{PCI_VENDOR_ID_CB, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ 	{PCI_VENDOR_ID_CB, 0x000f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+@@ -536,7 +533,7 @@ static int cb_pcidas_attach(struct comedi_device *dev, struct comedi_devconfig *
+ 		if (pcidev->vendor != PCI_VENDOR_ID_CB)
+ 			continue;
+ 		/*  loop through cards supported by this driver */
+-		for (index = 0; index < N_BOARDS; index++) {
++		for (index = 0; index < ARRAY_SIZE(cb_pcidas_boards); index++) {
+ 			if (cb_pcidas_boards[index].device_id != pcidev->device)
+ 				continue;
+ 			/*  was a particular bus/slot requested? */
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
+index adce530adc53..caa8b568871d 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
+@@ -1014,12 +1014,6 @@ static const struct pcidas64_board pcidas64_boards[] = {
+ #endif
+ };
+ 
+-/* Number of boards in cb_pcidas_boards */
+-static inline unsigned int num_boards(void)
+-{
+-	return sizeof(pcidas64_boards) / sizeof(struct pcidas64_board);
+-}
+-
+ static DEFINE_PCI_DEVICE_TABLE(pcidas64_pci_table) = {
+ 	{PCI_VENDOR_ID_COMPUTERBOARDS, 0x001d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ 	{PCI_VENDOR_ID_COMPUTERBOARDS, 0x001e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+@@ -1702,7 +1696,7 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 		if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS)
+ 			continue;
+ 		/*  loop through cards supported by this driver */
+-		for (index = 0; index < num_boards(); index++) {
++		for (index = 0; index < ARRAY_SIZE(pcidas64_boards); index++) {
+ 			if (pcidas64_boards[index].device_id != pcidev->device)
+ 				continue;
+ 			/*  was a particular bus/slot requested? */
+diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c
+index 799b5aded13c..dc701273167c 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidio.c
++++ b/drivers/staging/comedi/drivers/cb_pcidio.c
+@@ -204,7 +204,7 @@ static int pcidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 			continue;
+ 		/*  loop through cards supported by this driver */
+ 		for (index = 0;
+-			index < sizeof pcidio_boards / sizeof(struct pcidio_board);
++			index < ARRAY_SIZE(pcidio_boards);
+ 			index++) {
+ 			if (pcidio_pci_table[index].device != pcidev->device)
+ 				continue;
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
+index 3ce133c69e27..57bb1182480d 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
+@@ -135,8 +135,6 @@ static const struct board_struct boards[] = {
+  */
+ #define thisboard    ((const struct board_struct *)dev->board_ptr)
+ 
+-/* Number of boards in boards[] */
+-#define N_BOARDS	(sizeof(boards) / sizeof(struct board_struct))
+ #define REG_SZ (thisboard->reg_sz)
+ #define REGS_BADRINDEX (thisboard->regs_badrindex)
+ 
+@@ -439,7 +437,7 @@ static int probe(struct comedi_device *dev, const struct comedi_devconfig *it)
+ 		if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS)
+ 			continue;
+ 		/*  loop through cards supported by this driver */
+-		for (index = 0; index < N_BOARDS; index++) {
++		for (index = 0; index < ARRAY_SIZE(boards); index++) {
+ 			if (boards[index].device_id != pcidev->device)
+ 				continue;
+ 			/*  was a particular bus/slot requested? */
+diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c
+index 1ee489864d3b..45cd41f7fd29 100644
+--- a/drivers/staging/comedi/drivers/comedi_bond.c
++++ b/drivers/staging/comedi/drivers/comedi_bond.c
+@@ -210,7 +210,7 @@ static struct comedi_driver driver_bonding = {
+ 	 */
+       .board_name =	&bondingBoards[0].name,
+       .offset =		sizeof(struct BondingBoard),
+-      .num_names =	sizeof(bondingBoards) / sizeof(struct BondingBoard),
++      .num_names =	ARRAY_SIZE(bondingBoards),
+ };
+ 
+ static int bonding_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
+diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c
+index e679328a4f8f..93ed1a0ae126 100644
+--- a/drivers/staging/comedi/drivers/comedi_test.c
++++ b/drivers/staging/comedi/drivers/comedi_test.c
+@@ -102,7 +102,7 @@ static struct comedi_driver driver_waveform = {
+       .detach =		waveform_detach,
+       .board_name =	&waveform_boards[0].name,
+       .offset =		sizeof(struct waveform_board),
+-      .num_names =	sizeof(waveform_boards) / sizeof(struct waveform_board),
++      .num_names =	ARRAY_SIZE(waveform_boards),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_waveform);
+diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
+index 982837d879ce..6ca888429e6a 100644
+--- a/drivers/staging/comedi/drivers/das16.c
++++ b/drivers/staging/comedi/drivers/das16.c
+@@ -696,8 +696,6 @@ static const struct das16_board das16_boards[] = {
+ #endif
+ };
+ 
+-#define n_das16_boards ((sizeof(das16_boards))/(sizeof(struct das16_board)))
+-
+ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int das16_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_das16 = {
+@@ -706,7 +704,7 @@ static struct comedi_driver driver_das16 = {
+ 	.attach = das16_attach,
+ 	.detach = das16_detach,
+ 	.board_name = &das16_boards[0].name,
+-	.num_names = n_das16_boards,
++	.num_names = ARRAY_SIZE(das16_boards),
+ 	.offset = sizeof(das16_boards[0]),
+ };
+ 
+diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
+index 91b1a0e7575c..e22f546e8162 100644
+--- a/drivers/staging/comedi/drivers/das16m1.c
++++ b/drivers/staging/comedi/drivers/das16m1.c
+@@ -164,8 +164,6 @@ static const struct das16m1_board das16m1_boards[] = {
+ 		},
+ };
+ 
+-#define das16m1_num_boards ((sizeof(das16m1_boards)) / (sizeof(das16m1_boards[0])))
+-
+ static int das16m1_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int das16m1_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_das16m1 = {
+@@ -174,7 +172,7 @@ static struct comedi_driver driver_das16m1 = {
+ 	.attach = das16m1_attach,
+ 	.detach = das16m1_detach,
+ 	.board_name = &das16m1_boards[0].name,
+-	.num_names = das16m1_num_boards,
++	.num_names = ARRAY_SIZE(das16m1_boards),
+ 	.offset = sizeof(das16m1_boards[0]),
+ };
+ 
+diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
+index 9c6c9b89558a..7fbcfb107e6d 100644
+--- a/drivers/staging/comedi/drivers/das1800.c
++++ b/drivers/staging/comedi/drivers/das1800.c
+@@ -509,7 +509,7 @@ static struct comedi_driver driver_das1800 = {
+ 	.module = THIS_MODULE,
+ 	.attach = das1800_attach,
+ 	.detach = das1800_detach,
+-	.num_names = sizeof(das1800_boards) / sizeof(struct das1800_board),
++	.num_names = ARRAY_SIZE(das1800_boards),
+ 	.board_name = &das1800_boards[0].name,
+ 	.offset = sizeof(struct das1800_board),
+ };
+diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
+index db646598619e..6ee9648e5e18 100644
+--- a/drivers/staging/comedi/drivers/das800.c
++++ b/drivers/staging/comedi/drivers/das800.c
+@@ -251,7 +251,7 @@ static struct comedi_driver driver_das800 = {
+ 	.module = THIS_MODULE,
+ 	.attach = das800_attach,
+ 	.detach = das800_detach,
+-	.num_names = sizeof(das800_boards) / sizeof(struct das800_board),
++	.num_names = ARRAY_SIZE(das800_boards),
+ 	.board_name = &das800_boards[0].name,
+ 	.offset = sizeof(struct das800_board),
+ };
+diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
+index e7c5130de8d0..47b3ebc34a68 100644
+--- a/drivers/staging/comedi/drivers/dmm32at.c
++++ b/drivers/staging/comedi/drivers/dmm32at.c
+@@ -285,7 +285,7 @@ static struct comedi_driver driver_dmm32at = {
+  */
+ 	.board_name = &dmm32at_boards[0].name,
+ 	.offset = sizeof(struct dmm32at_board),
+-	.num_names = sizeof(dmm32at_boards) / sizeof(struct dmm32at_board),
++	.num_names = ARRAY_SIZE(dmm32at_boards),
+ };
+ 
+ /* prototypes for driver functions below */
+diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c
+index 335e3a0660cf..9b100405b8b7 100644
+--- a/drivers/staging/comedi/drivers/dt2801.c
++++ b/drivers/staging/comedi/drivers/dt2801.c
+@@ -217,7 +217,6 @@ static const struct dt2801_board boardtypes[] = {
+ 	.dabits = 12},
+ };
+ 
+-#define n_boardtypes ((sizeof(boardtypes))/(sizeof(boardtypes[0])))
+ #define boardtype (*(const struct dt2801_board *)dev->board_ptr)
+ 
+ struct dt2801_private {
+@@ -506,7 +505,7 @@ static int dt2801_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	if (!board_code)
+ 		board_code = dt2801_reset(dev);
+ 
+-	for (type = 0; type < n_boardtypes; type++) {
++	for (type = 0; type < ARRAY_SIZE(boardtypes); type++) {
+ 		if (boardtypes[type].boardcode == board_code)
+ 			goto havetype;
+ 	}
+diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c
+index 7e6995ed886d..f05b3e711157 100644
+--- a/drivers/staging/comedi/drivers/dt2811.c
++++ b/drivers/staging/comedi/drivers/dt2811.c
+@@ -222,7 +222,7 @@ static struct comedi_driver driver_dt2811 = {
+ 	.attach = dt2811_attach,
+ 	.detach = dt2811_detach,
+ 	.board_name = &boardtypes[0].name,
+-	.num_names = sizeof(boardtypes) / sizeof(struct dt2811_board),
++	.num_names = ARRAY_SIZE(boardtypes),
+ 	.offset = sizeof(struct dt2811_board),
+ };
+ 
+diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
+index 098a78e9307a..a344e2cebde1 100644
+--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
++++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
+@@ -283,11 +283,6 @@ static const struct hpdi_board hpdi_boards[] = {
+ #endif
+ };
+ 
+-static inline unsigned int num_boards(void)
+-{
+-	return sizeof(hpdi_boards) / sizeof(struct hpdi_board);
+-}
+-
+ static DEFINE_PCI_DEVICE_TABLE(hpdi_pci_table) = {
+ 	{PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9080, PCI_VENDOR_ID_PLX, 0x2400,
+ 		0, 0, 0},
+@@ -568,7 +563,7 @@ static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 		return -ENOMEM;
+ 
+ 	pcidev = NULL;
+-	for (i = 0; i < num_boards() && dev->board_ptr == NULL; i++) {
++	for (i = 0; i < ARRAY_SIZE(hpdi_boards) && dev->board_ptr == NULL; i++) {
+ 		do {
+ 			pcidev = pci_get_subsys(PCI_VENDOR_ID_PLX,
+ 				hpdi_boards[i].device_id, PCI_VENDOR_ID_PLX,
+diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
+index c3db3b80eba4..bffa3cf91c84 100644
+--- a/drivers/staging/comedi/drivers/me4000.c
++++ b/drivers/staging/comedi/drivers/me4000.c
+@@ -113,7 +113,7 @@ static const struct me4000_board me4000_boards[] = {
+ 	{0},
+ };
+ 
+-#define ME4000_BOARD_VERSIONS (sizeof(me4000_boards) / sizeof(struct me4000_board) - 1)
++#define ME4000_BOARD_VERSIONS (ARRAY_SIZE(me4000_boards) - 1)
+ 
+ /*-----------------------------------------------------------------------------
+   Comedi function prototypes
+diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c
+index 1b752f615002..4e8bf9ed167c 100644
+--- a/drivers/staging/comedi/drivers/ni_at_ao.c
++++ b/drivers/staging/comedi/drivers/ni_at_ao.c
+@@ -190,7 +190,7 @@ static struct comedi_driver driver_atao = {
+ 	.detach = atao_detach,
+ 	.board_name = &atao_boards[0].name,
+ 	.offset = sizeof(struct atao_board),
+-	.num_names = sizeof(atao_boards) / sizeof(struct atao_board),
++	.num_names = ARRAY_SIZE(atao_boards),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_atao);
+diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
+index 3f0c1b3694dc..f01c0b008b50 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_700.c
++++ b/drivers/staging/comedi/drivers/ni_daq_700.c
+@@ -104,7 +104,7 @@ static struct comedi_driver driver_dio700 = {
+ 	.module = THIS_MODULE,
+ 	.attach = dio700_attach,
+ 	.detach = dio700_detach,
+-	.num_names = sizeof(dio700_boards) / sizeof(struct dio700_board),
++	.num_names = ARRAY_SIZE(dio700_boards),
+ 	.board_name = &dio700_boards[0].name,
+ 	.offset = sizeof(struct dio700_board),
+ };
+diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
+index a0b3dd254384..68c3121c1b32 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
++++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
+@@ -104,7 +104,7 @@ static struct comedi_driver driver_dio24 = {
+ 	.module = THIS_MODULE,
+ 	.attach = dio24_attach,
+ 	.detach = dio24_detach,
+-	.num_names = sizeof(dio24_boards) / sizeof(struct dio24_board_struct),
++	.num_names = ARRAY_SIZE(dio24_boards),
+ 	.board_name = &dio24_boards[0].name,
+ 	.offset = sizeof(struct dio24_board_struct),
+ };
+diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
+index d1a2b5065036..031d994ed227 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc.c
++++ b/drivers/staging/comedi/drivers/ni_labpc.c
+@@ -434,7 +434,7 @@ static struct comedi_driver driver_labpc = {
+ 	.module = THIS_MODULE,
+ 	.attach = labpc_attach,
+ 	.detach = labpc_common_detach,
+-	.num_names = sizeof(labpc_boards) / sizeof(struct labpc_board_struct),
++	.num_names = ARRAY_SIZE(labpc_boards),
+ 	.board_name = &labpc_boards[0].name,
+ 	.offset = sizeof(struct labpc_board_struct),
+ };
+diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
+index 41538c3c80ff..fb56c03a1b9f 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
++++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
+@@ -121,7 +121,7 @@ static struct comedi_driver driver_labpc_cs = {
+ 	.module = THIS_MODULE,
+ 	.attach = &labpc_attach,
+ 	.detach = &labpc_common_detach,
+-	.num_names = sizeof(labpc_cs_boards) / sizeof(struct labpc_board_struct),
++	.num_names = ARRAY_SIZE(labpc_cs_boards),
+ 	.board_name = &labpc_cs_boards[0].name,
+ 	.offset = sizeof(struct labpc_board_struct),
+ };
+diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h
+index d4d352b6b465..f97b18181534 100644
+--- a/drivers/staging/comedi/drivers/ni_stc.h
++++ b/drivers/staging/comedi/drivers/ni_stc.h
+@@ -1084,7 +1084,7 @@ static inline int M_Offset_Static_AI_Control(int i)
+ 		0x262,
+ 		0x263,
+ 	};
+-	if (((unsigned)i) >= sizeof(offset) / sizeof(offset[0])) {
++	if (((unsigned)i) >= ARRAY_SIZE(offset)) {
+ 		rt_printk("%s: invalid channel=%i\n", __func__, i);
+ 		return offset[0];
+ 	}
+@@ -1098,7 +1098,7 @@ static inline int M_Offset_AO_Reference_Attenuation(int channel)
+ 		0x266,
+ 		0x267
+ 	};
+-	if (((unsigned)channel) >= sizeof(offset) / sizeof(offset[0])) {
++	if (((unsigned)channel) >= ARRAY_SIZE(offset)) {
+ 		rt_printk("%s: invalid channel=%i\n", __func__, channel);
+ 		return offset[0];
+ 	}
+diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c
+index 7bc4d7ef9505..f1a8cdfaaa48 100644
+--- a/drivers/staging/comedi/drivers/pcmda12.c
++++ b/drivers/staging/comedi/drivers/pcmda12.c
+@@ -137,7 +137,7 @@ static struct comedi_driver driver = {
+ 	 */
+ 	.board_name = &pcmda12_boards[0].name,
+ 	.offset = sizeof(struct pcmda12_board),
+-	.num_names = sizeof(pcmda12_boards) / sizeof(struct pcmda12_board),
++	.num_names = ARRAY_SIZE(pcmda12_boards),
+ };
+ 
+ static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
+diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
+index 9d025ab5b9f3..2ff2fe94b704 100644
+--- a/drivers/staging/comedi/drivers/pcmmio.c
++++ b/drivers/staging/comedi/drivers/pcmmio.c
+@@ -292,7 +292,7 @@ static struct comedi_driver driver = {
+ 	 */
+ 	.board_name = &pcmmio_boards[0].name,
+ 	.offset = sizeof(struct pcmmio_board),
+-	.num_names = sizeof(pcmmio_boards) / sizeof(struct pcmmio_board),
++	.num_names = ARRAY_SIZE(pcmmio_boards),
+ };
+ 
+ static int pcmmio_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
+diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
+index e515eadc0fb5..c28e6dfd0f9c 100644
+--- a/drivers/staging/comedi/drivers/pcmuio.c
++++ b/drivers/staging/comedi/drivers/pcmuio.c
+@@ -250,7 +250,7 @@ static struct comedi_driver driver = {
+ 	 */
+ 	.board_name = &pcmuio_boards[0].name,
+ 	.offset = sizeof(struct pcmuio_board),
+-	.num_names = sizeof(pcmuio_boards) / sizeof(struct pcmuio_board),
++	.num_names = ARRAY_SIZE(pcmuio_boards),
+ };
+ 
+ static int pcmuio_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
+diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
+index 0e765641838b..6af081b04a0c 100644
+--- a/drivers/staging/comedi/drivers/rtd520.c
++++ b/drivers/staging/comedi/drivers/rtd520.c
+@@ -757,7 +757,7 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 				continue;
+ 			}
+ 		}
+-		for (i = 0; i < sizeof (rtd520Boards) / sizeof (rtd520Boards[0]); ++i)
++		for (i = 0; i < ARRAY_SIZE(rtd520Boards); ++i)
+ 		{
+ 			if (pcidev->device == rtd520Boards[i].device_id)
+ 			{
+diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c
+index 57541d52a159..3986459a1645 100644
+--- a/drivers/staging/comedi/drivers/rti800.c
++++ b/drivers/staging/comedi/drivers/rti800.c
+@@ -138,7 +138,7 @@ static struct comedi_driver driver_rti800 = {
+ 	.module = THIS_MODULE,
+ 	.attach = rti800_attach,
+ 	.detach = rti800_detach,
+-	.num_names = sizeof(boardtypes) / sizeof(struct rti800_board),
++	.num_names = ARRAY_SIZE(boardtypes),
+ 	.board_name = &boardtypes[0].name,
+ 	.offset = sizeof(struct rti800_board),
+ };
+@@ -199,8 +199,7 @@ static int rti800_ai_insn_read(struct comedi_device *dev, struct comedi_subdevic
+ 		/* without a delay here, the RTI_OVERRUN bit
+ 		 * gets set, and you will have an error. */
+ 		if (insn->n > 0) {
+-			BUG_ON(gain >=
+-				sizeof(gaindelay) / sizeof(gaindelay[0]));
++			BUG_ON(gain >= ARRAY_SIZE(gaindelay));
+ 			comedi_udelay(gaindelay[gain]);
+ 		}
+ 	}
+diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
+index d9b8f837bfdb..7a6be1ee8f61 100644
+--- a/drivers/staging/comedi/drivers/s526.c
++++ b/drivers/staging/comedi/drivers/s526.c
+@@ -244,7 +244,7 @@ static struct comedi_driver driver_s526 = {
+ 	 */
+ 	.board_name = &s526_boards[0].name,
+ 	.offset = sizeof(struct s526_board),
+-	.num_names = sizeof(s526_boards) / sizeof(struct s526_board),
++	.num_names = ARRAY_SIZE(s526_boards),
+ };
+ 
+ static int s526_gpct_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
+diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
+index 6e78194fe551..ff8ec589298c 100644
+--- a/drivers/staging/comedi/drivers/s626.c
++++ b/drivers/staging/comedi/drivers/s626.c
+@@ -2358,7 +2358,7 @@ static void LoadTrimDACs(struct comedi_device *dev)
+ 	register uint8_t i;
+ 
+ 	/*  Copy TrimDac setpoint values from EEPROM to TrimDacs. */
+-	for (i = 0; i < (sizeof(trimchan) / sizeof(trimchan[0])); i++)
++	for (i = 0; i < ARRAY_SIZE(trimchan); i++)
+ 		WriteTrimDAC(dev, i, I2Cread(dev, trimadrs[i]));
+ }
+ 
+diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
+index cf3e925261a0..89f97e85eff3 100644
+--- a/drivers/staging/comedi/drivers/serial2002.c
++++ b/drivers/staging/comedi/drivers/serial2002.c
+@@ -98,7 +98,7 @@ struct comedi_driver driver_serial2002 = {
+ 	.detach = serial2002_detach,
+ 	.board_name = &serial2002_boards[0].name,
+ 	.offset = sizeof(struct serial2002_board),
+-	.num_names = sizeof(serial2002_boards) / sizeof(struct serial2002_board),
++	.num_names = ARRAY_SIZE(serial2002_boards),
+ };
+ 
+ static int serial2002_di_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
+diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c
+index a0764f81917b..b73518129f85 100644
+--- a/drivers/staging/comedi/drivers/skel.c
++++ b/drivers/staging/comedi/drivers/skel.c
+@@ -181,7 +181,7 @@ static struct comedi_driver driver_skel = {
+ 	 */
+ 	.board_name = &skel_boards[0].name,
+ 	.offset = sizeof(struct skel_board),
+-	.num_names = sizeof(skel_boards) / sizeof(struct skel_board),
++	.num_names = ARRAY_SIZE(skel_boards),
+ };
+ 
+ static int skel_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
+diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c
+index b12c42991bba..13c29bb99100 100644
+--- a/drivers/staging/comedi/drivers/ssv_dnp.c
++++ b/drivers/staging/comedi/drivers/ssv_dnp.c
+@@ -99,7 +99,7 @@ static struct comedi_driver driver_dnp = {
+ 	.board_name = &dnp_boards[0].name,
+ 	/* only necessary for non-PnP devs   */
+ 	.offset = sizeof(struct dnp_board),/* like ISA-PnP, PCI or PCMCIA.      */
+-	.num_names = sizeof(dnp_boards) / sizeof(struct dnp_board),
++	.num_names = ARRAY_SIZE(dnp_boards),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_dnp);

commit b4918808debc62daaa189ecbdfca489c00b1061d
+Author: Bill Pemberton 
+Date:   Thu Apr 23 15:54:55 2009 -0400
+
+    Staging: comedi: more fix the way structs are initialized.
+    
+    Change from the foo: bar format to the .foo = bar format.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
+index 83af347934be..0e765641838b 100644
+--- a/drivers/staging/comedi/drivers/rtd520.c
++++ b/drivers/staging/comedi/drivers/rtd520.c
+@@ -278,22 +278,22 @@ struct rtdBoard {
+ 
+ static const struct rtdBoard rtd520Boards[] = {
+ 	{
+-	      name:	"DM7520",
+-	      device_id : 0x7520,
+-	      aiChans:	16,
+-	      aiBits:	12,
+-	      aiMaxGain:32,
+-	      range10Start:6,
+-	      rangeUniStart:12,
++	.name = "DM7520",
++	.device_id = 0x7520,
++	.aiChans = 16,
++	.aiBits = 12,
++	.aiMaxGain = 32,
++	.range10Start = 6,
++	.rangeUniStart = 12,
+ 		},
+ 	{
+-	      name:	"PCI4520",
+-	      device_id : 0x4520,
+-	      aiChans:	16,
+-	      aiBits:	12,
+-	      aiMaxGain:128,
+-	      range10Start:8,
+-	      rangeUniStart:16,
++	.name = "PCI4520",
++	.device_id = 0x4520,
++	.aiChans = 16,
++	.aiBits = 12,
++	.aiMaxGain = 128,
++	.range10Start = 8,
++	.rangeUniStart = 16,
+ 		},
+ };
+ 
+@@ -684,10 +684,10 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int rtd_detach(struct comedi_device *dev);
+ 
+ static struct comedi_driver rtd520Driver = {
+-      driver_name: DRV_NAME,
+-      module : THIS_MODULE,
+-      attach : rtd_attach,
+-      detach : rtd_detach,
++	.driver_name = DRV_NAME,
++	.module = THIS_MODULE,
++	.attach = rtd_attach,
++	.detach = rtd_detach,
+ };
+ 
+ static int rtd_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
+diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
+index d8f014563c1e..6e78194fe551 100644
+--- a/drivers/staging/comedi/drivers/s626.c
++++ b/drivers/staging/comedi/drivers/s626.c
+@@ -95,14 +95,14 @@ struct s626_board {
+ 
+ static const struct s626_board s626_boards[] = {
+ 	{
+-	      name:	"s626",
+-	      ai_chans : S626_ADC_CHANNELS,
+-	      ai_bits:	14,
+-	      ao_chans : S626_DAC_CHANNELS,
+-	      ao_bits:	13,
+-	      dio_chans : S626_DIO_CHANNELS,
+-	      dio_banks : S626_DIO_BANKS,
+-	      enc_chans : S626_ENCODER_CHANNELS,
++	.name = "s626",
++	.ai_chans = S626_ADC_CHANNELS,
++	.ai_bits = 14,
++	.ao_chans = S626_DAC_CHANNELS,
++	.ao_bits = 13,
++	.dio_chans = S626_DIO_CHANNELS,
++	.dio_banks = S626_DIO_BANKS,
++	.enc_chans = S626_ENCODER_CHANNELS,
+ 		}
+ };
+ 
+@@ -122,10 +122,10 @@ static int s626_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int s626_detach(struct comedi_device *dev);
+ 
+ static struct comedi_driver driver_s626 = {
+-      driver_name:"s626",
+-      module : THIS_MODULE,
+-      attach : s626_attach,
+-      detach : s626_detach,
++	.driver_name = "s626",
++	.module = THIS_MODULE,
++	.attach = s626_attach,
++	.detach = s626_detach,
+ };
+ 
+ struct s626_private {
+@@ -173,39 +173,39 @@ struct dio_private {
+ };
+ 
+ static struct dio_private dio_private_A = {
+-      RDDIn:LP_RDDINA,
+-      WRDOut : LP_WRDOUTA,
+-      RDEdgSel : LP_RDEDGSELA,
+-      WREdgSel : LP_WREDGSELA,
+-      RDCapSel : LP_RDCAPSELA,
+-      WRCapSel : LP_WRCAPSELA,
+-      RDCapFlg : LP_RDCAPFLGA,
+-      RDIntSel : LP_RDINTSELA,
+-      WRIntSel : LP_WRINTSELA,
++	.RDDIn = LP_RDDINA,
++	.WRDOut = LP_WRDOUTA,
++	.RDEdgSel = LP_RDEDGSELA,
++	.WREdgSel = LP_WREDGSELA,
++	.RDCapSel = LP_RDCAPSELA,
++	.WRCapSel = LP_WRCAPSELA,
++	.RDCapFlg = LP_RDCAPFLGA,
++	.RDIntSel = LP_RDINTSELA,
++	.WRIntSel = LP_WRINTSELA,
+ };
+ 
+ static struct dio_private dio_private_B = {
+-      RDDIn:LP_RDDINB,
+-      WRDOut : LP_WRDOUTB,
+-      RDEdgSel : LP_RDEDGSELB,
+-      WREdgSel : LP_WREDGSELB,
+-      RDCapSel : LP_RDCAPSELB,
+-      WRCapSel : LP_WRCAPSELB,
+-      RDCapFlg : LP_RDCAPFLGB,
+-      RDIntSel : LP_RDINTSELB,
+-      WRIntSel : LP_WRINTSELB,
++	.RDDIn = LP_RDDINB,
++	.WRDOut = LP_WRDOUTB,
++	.RDEdgSel = LP_RDEDGSELB,
++	.WREdgSel = LP_WREDGSELB,
++	.RDCapSel = LP_RDCAPSELB,
++	.WRCapSel = LP_WRCAPSELB,
++	.RDCapFlg = LP_RDCAPFLGB,
++	.RDIntSel = LP_RDINTSELB,
++	.WRIntSel = LP_WRINTSELB,
+ };
+ 
+ static struct dio_private dio_private_C = {
+-      RDDIn:LP_RDDINC,
+-      WRDOut : LP_WRDOUTC,
+-      RDEdgSel : LP_RDEDGSELC,
+-      WREdgSel : LP_WREDGSELC,
+-      RDCapSel : LP_RDCAPSELC,
+-      WRCapSel : LP_WRCAPSELC,
+-      RDCapFlg : LP_RDCAPFLGC,
+-      RDIntSel : LP_RDINTSELC,
+-      WRIntSel : LP_WRINTSELC,
++	.RDDIn = LP_RDDINC,
++	.WRDOut = LP_WRDOUTC,
++	.RDEdgSel = LP_RDEDGSELC,
++	.WREdgSel = LP_WREDGSELC,
++	.RDCapSel = LP_RDCAPSELC,
++	.WRCapSel = LP_WRCAPSELC,
++	.RDCapFlg = LP_RDCAPFLGC,
++	.RDIntSel = LP_RDINTSELC,
++	.WRIntSel = LP_WRINTSELC,
+ };
+ 
+ /* to group dio devices (48 bits mask and data are not allowed ???)
+@@ -355,100 +355,100 @@ static void CountersInit(struct comedi_device *dev);
+ /* struct enc_private; */
+ static struct enc_private enc_private_data[] = {
+ 	{
+-	      GetEnable:GetEnable_A,
+-	      GetIntSrc : GetIntSrc_A,
+-	      GetLoadTrig : GetLoadTrig_A,
+-	      GetMode :	GetMode_A,
+-	      PulseIndex : PulseIndex_A,
+-	      SetEnable : SetEnable_A,
+-	      SetIntSrc : SetIntSrc_A,
+-	      SetLoadTrig : SetLoadTrig_A,
+-	      SetMode :	SetMode_A,
+-	      ResetCapFlags : ResetCapFlags_A,
+-	      MyCRA :	LP_CR0A,
+-	      MyCRB :	LP_CR0B,
+-	      MyLatchLsw : LP_CNTR0ALSW,
+-	      MyEventBits : EVBITS(0),
++	.GetEnable = GetEnable_A,
++	.GetIntSrc = GetIntSrc_A,
++	.GetLoadTrig = GetLoadTrig_A,
++	.GetMode = GetMode_A,
++	.PulseIndex = PulseIndex_A,
++	.SetEnable = SetEnable_A,
++	.SetIntSrc = SetIntSrc_A,
++	.SetLoadTrig = SetLoadTrig_A,
++	.SetMode = SetMode_A,
++	.ResetCapFlags = ResetCapFlags_A,
++	.MyCRA = LP_CR0A,
++	.MyCRB = LP_CR0B,
++	.MyLatchLsw = LP_CNTR0ALSW,
++	.MyEventBits = EVBITS(0),
+ 		},
+ 	{
+-	      GetEnable:GetEnable_A,
+-	      GetIntSrc : GetIntSrc_A,
+-	      GetLoadTrig : GetLoadTrig_A,
+-	      GetMode :	GetMode_A,
+-	      PulseIndex : PulseIndex_A,
+-	      SetEnable : SetEnable_A,
+-	      SetIntSrc : SetIntSrc_A,
+-	      SetLoadTrig : SetLoadTrig_A,
+-	      SetMode :	SetMode_A,
+-	      ResetCapFlags : ResetCapFlags_A,
+-	      MyCRA :	LP_CR1A,
+-	      MyCRB :	LP_CR1B,
+-	      MyLatchLsw : LP_CNTR1ALSW,
+-	      MyEventBits : EVBITS(1),
++	.GetEnable = GetEnable_A,
++	.GetIntSrc = GetIntSrc_A,
++	.GetLoadTrig = GetLoadTrig_A,
++	.GetMode = GetMode_A,
++	.PulseIndex = PulseIndex_A,
++	.SetEnable = SetEnable_A,
++	.SetIntSrc = SetIntSrc_A,
++	.SetLoadTrig = SetLoadTrig_A,
++	.SetMode = SetMode_A,
++	.ResetCapFlags = ResetCapFlags_A,
++	.MyCRA = LP_CR1A,
++	.MyCRB = LP_CR1B,
++	.MyLatchLsw = LP_CNTR1ALSW,
++	.MyEventBits = EVBITS(1),
+ 		},
+ 	{
+-	      GetEnable:GetEnable_A,
+-	      GetIntSrc : GetIntSrc_A,
+-	      GetLoadTrig : GetLoadTrig_A,
+-	      GetMode :	GetMode_A,
+-	      PulseIndex : PulseIndex_A,
+-	      SetEnable : SetEnable_A,
+-	      SetIntSrc : SetIntSrc_A,
+-	      SetLoadTrig : SetLoadTrig_A,
+-	      SetMode :	SetMode_A,
+-	      ResetCapFlags : ResetCapFlags_A,
+-	      MyCRA :	LP_CR2A,
+-	      MyCRB :	LP_CR2B,
+-	      MyLatchLsw : LP_CNTR2ALSW,
+-	      MyEventBits : EVBITS(2),
++	.GetEnable = GetEnable_A,
++	.GetIntSrc = GetIntSrc_A,
++	.GetLoadTrig = GetLoadTrig_A,
++	.GetMode = GetMode_A,
++	.PulseIndex = PulseIndex_A,
++	.SetEnable = SetEnable_A,
++	.SetIntSrc = SetIntSrc_A,
++	.SetLoadTrig = SetLoadTrig_A,
++	.SetMode = SetMode_A,
++	.ResetCapFlags = ResetCapFlags_A,
++	.MyCRA = LP_CR2A,
++	.MyCRB = LP_CR2B,
++	.MyLatchLsw = LP_CNTR2ALSW,
++	.MyEventBits = EVBITS(2),
+ 		},
+ 	{
+-	      GetEnable:GetEnable_B,
+-	      GetIntSrc : GetIntSrc_B,
+-	      GetLoadTrig : GetLoadTrig_B,
+-	      GetMode :	GetMode_B,
+-	      PulseIndex : PulseIndex_B,
+-	      SetEnable : SetEnable_B,
+-	      SetIntSrc : SetIntSrc_B,
+-	      SetLoadTrig : SetLoadTrig_B,
+-	      SetMode :	SetMode_B,
+-	      ResetCapFlags : ResetCapFlags_B,
+-	      MyCRA :	LP_CR0A,
+-	      MyCRB :	LP_CR0B,
+-	      MyLatchLsw : LP_CNTR0BLSW,
+-	      MyEventBits : EVBITS(3),
++	.GetEnable = GetEnable_B,
++	.GetIntSrc = GetIntSrc_B,
++	.GetLoadTrig = GetLoadTrig_B,
++	.GetMode = GetMode_B,
++	.PulseIndex = PulseIndex_B,
++	.SetEnable = SetEnable_B,
++	.SetIntSrc = SetIntSrc_B,
++	.SetLoadTrig = SetLoadTrig_B,
++	.SetMode = SetMode_B,
++	.ResetCapFlags = ResetCapFlags_B,
++	.MyCRA = LP_CR0A,
++	.MyCRB = LP_CR0B,
++	.MyLatchLsw = LP_CNTR0BLSW,
++	.MyEventBits = EVBITS(3),
+ 		},
+ 	{
+-	      GetEnable:GetEnable_B,
+-	      GetIntSrc : GetIntSrc_B,
+-	      GetLoadTrig : GetLoadTrig_B,
+-	      GetMode :	GetMode_B,
+-	      PulseIndex : PulseIndex_B,
+-	      SetEnable : SetEnable_B,
+-	      SetIntSrc : SetIntSrc_B,
+-	      SetLoadTrig : SetLoadTrig_B,
+-	      SetMode :	SetMode_B,
+-	      ResetCapFlags : ResetCapFlags_B,
+-	      MyCRA :	LP_CR1A,
+-	      MyCRB :	LP_CR1B,
+-	      MyLatchLsw : LP_CNTR1BLSW,
+-	      MyEventBits : EVBITS(4),
++	.GetEnable = GetEnable_B,
++	.GetIntSrc = GetIntSrc_B,
++	.GetLoadTrig = GetLoadTrig_B,
++	.GetMode = GetMode_B,
++	.PulseIndex = PulseIndex_B,
++	.SetEnable = SetEnable_B,
++	.SetIntSrc = SetIntSrc_B,
++	.SetLoadTrig = SetLoadTrig_B,
++	.SetMode = SetMode_B,
++	.ResetCapFlags = ResetCapFlags_B,
++	.MyCRA = LP_CR1A,
++	.MyCRB = LP_CR1B,
++	.MyLatchLsw = LP_CNTR1BLSW,
++	.MyEventBits = EVBITS(4),
+ 		},
+ 	{
+-	      GetEnable:GetEnable_B,
+-	      GetIntSrc : GetIntSrc_B,
+-	      GetLoadTrig : GetLoadTrig_B,
+-	      GetMode :	GetMode_B,
+-	      PulseIndex : PulseIndex_B,
+-	      SetEnable : SetEnable_B,
+-	      SetIntSrc : SetIntSrc_B,
+-	      SetLoadTrig : SetLoadTrig_B,
+-	      SetMode :	SetMode_B,
+-	      ResetCapFlags : ResetCapFlags_B,
+-	      MyCRA :	LP_CR2A,
+-	      MyCRB :	LP_CR2B,
+-	      MyLatchLsw : LP_CNTR2BLSW,
+-	      MyEventBits : EVBITS(5),
++	.GetEnable = GetEnable_B,
++	.GetIntSrc = GetIntSrc_B,
++	.GetLoadTrig = GetLoadTrig_B,
++	.GetMode = GetMode_B,
++	.PulseIndex = PulseIndex_B,
++	.SetEnable = SetEnable_B,
++	.SetIntSrc = SetIntSrc_B,
++	.SetLoadTrig = SetLoadTrig_B,
++	.SetMode = SetMode_B,
++	.ResetCapFlags = ResetCapFlags_B,
++	.MyCRA = LP_CR2A,
++	.MyCRB = LP_CR2B,
++	.MyLatchLsw = LP_CNTR2BLSW,
++	.MyEventBits = EVBITS(5),
+ 		},
+ };
+ 

commit 814900c904140cfe7f3e48cabec06b3eec57e0ea
+Author: Bill Pemberton 
+Date:   Thu Apr 23 15:54:54 2009 -0400
+
+    Staging: comedi: more fix "foo * bar" should be "foo *bar"
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+index 8bb0f9a1abbb..208ade70ad0c 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+@@ -124,23 +124,23 @@ int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
+ 
+ int i_EepromReadDigitalInputHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+-	struct str_DigitalInputHeader * s_Header);
++	struct str_DigitalInputHeader *s_Header);
+ 
+ int i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+-	struct str_DigitalOutputHeader * s_Header);
++	struct str_DigitalOutputHeader *s_Header);
+ 
+ int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+-	struct str_TimerMainHeader * s_Header);
++	struct str_TimerMainHeader *s_Header);
+ 
+ int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+-	str_AnalogOutputHeader * s_Header);
++	str_AnalogOutputHeader *s_Header);
+ 
+ int i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+-	struct str_AnalogInputHeader * s_Header);
++	struct str_AnalogInputHeader *s_Header);
+ 
+ 		/******************************************/
+ 		/*      Eeprom Specific Functions                         */
+@@ -1082,7 +1082,7 @@ int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
+ 
+ int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+-	str_AnalogOutputHeader * s_Header)
++	str_AnalogOutputHeader *s_Header)
+ {
+ 	unsigned short w_Temp;
+ 	/*  No of channels for 1st hard component */
+diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
+index 57e57c670ec8..3befe507ce2f 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc236.c
++++ b/drivers/staging/comedi/drivers/amplc_pc236.c
+@@ -187,15 +187,15 @@ COMEDI_INITCLEANUP(driver_amplc_pc236);
+ 
+ static int pc236_request_region(unsigned minor, unsigned long from,
+ 	unsigned long extent);
+-static void pc236_intr_disable(struct comedi_device * dev);
+-static void pc236_intr_enable(struct comedi_device * dev);
+-static int pc236_intr_check(struct comedi_device * dev);
+-static int pc236_intr_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int pc236_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd);
+-static int pc236_intr_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int pc236_intr_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
++static void pc236_intr_disable(struct comedi_device *dev);
++static void pc236_intr_enable(struct comedi_device *dev);
++static int pc236_intr_check(struct comedi_device *dev);
++static int pc236_intr_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int pc236_intr_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd);
++static int pc236_intr_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
++static int pc236_intr_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
+ static irqreturn_t pc236_interrupt(int irq, void *d);
+ 
+ /*
+diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
+index 94f45029a9cf..1d675173cd32 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci230.c
++++ b/drivers/staging/comedi/drivers/amplc_pci230.c
+@@ -617,32 +617,32 @@ static struct comedi_driver driver_amplc_pci230 = {
+ 
+ COMEDI_PCI_INITCLEANUP(driver_amplc_pci230, pci230_pci_table);
+ 
+-static int pci230_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int pci230_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int pci230_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static void pci230_ct_setup_ns_mode(struct comedi_device * dev, unsigned int ct,
++static int pci230_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int pci230_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int pci230_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct,
+ 	unsigned int mode, uint64_t ns, unsigned int round);
+ static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round);
+-static void pci230_cancel_ct(struct comedi_device * dev, unsigned int ct);
++static void pci230_cancel_ct(struct comedi_device *dev, unsigned int ct);
+ static irqreturn_t pci230_interrupt(int irq, void *d);
+-static int pci230_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd);
+-static int pci230_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int pci230_ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+-static void pci230_ao_stop(struct comedi_device * dev, struct comedi_subdevice * s);
+-static void pci230_handle_ao_nofifo(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int pci230_handle_ao_fifo(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int pci230_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd);
+-static int pci230_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int pci230_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+-static void pci230_ai_stop(struct comedi_device * dev, struct comedi_subdevice * s);
+-static void pci230_handle_ai(struct comedi_device * dev, struct comedi_subdevice * s);
+-
+-static short pci230_ai_read(struct comedi_device * dev)
++static int pci230_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd);
++static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
++static int pci230_ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
++static void pci230_ao_stop(struct comedi_device *dev, struct comedi_subdevice *s);
++static void pci230_handle_ao_nofifo(struct comedi_device *dev, struct comedi_subdevice *s);
++static int pci230_handle_ao_fifo(struct comedi_device *dev, struct comedi_subdevice *s);
++static int pci230_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd);
++static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
++static int pci230_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
++static void pci230_ai_stop(struct comedi_device *dev, struct comedi_subdevice *s);
++static void pci230_handle_ai(struct comedi_device *dev, struct comedi_subdevice *s);
++
++static short pci230_ai_read(struct comedi_device *dev)
+ {
+ 	/* Read sample. */
+ 	short data = (short) inw(dev->iobase + PCI230_ADCDATA);
+diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
+index 3199249a8fc4..516d2ccdaf28 100644
+--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
++++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
+@@ -109,25 +109,25 @@ static const struct comedi_lrange das16cs_ai_range = { 4, {
+ };
+ 
+ static irqreturn_t das16cs_interrupt(int irq, void *d);
+-static int das16cs_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int das16cs_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int das16cs_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd);
+-static int das16cs_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int das16cs_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int das16cs_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int das16cs_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int das16cs_timer_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int das16cs_timer_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-
+-static int get_prodid(struct comedi_device * dev, struct pcmcia_device *link)
++static int das16cs_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int das16cs_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
++static int das16cs_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd);
++static int das16cs_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int das16cs_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int das16cs_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int das16cs_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int das16cs_timer_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int das16cs_timer_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++
++static int get_prodid(struct comedi_device *dev, struct pcmcia_device *link)
+ {
+ 	tuple_t tuple;
+ 	u_short buf[128];
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
+index 112480c969ab..17dec7567481 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas.c
+@@ -451,56 +451,56 @@ static struct comedi_driver driver_cb_pcidas = {
+ };
+ 
+ static int cb_pcidas_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int cb_pcidas_ao_nofifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int cb_pcidas_ao_fifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int cb_pcidas_ao_readback_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int cb_pcidas_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int cb_pcidas_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd);
+-static int cb_pcidas_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
++	struct comedi_insn *insn, unsigned int *data);
++static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int cb_pcidas_ao_nofifo_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int cb_pcidas_ao_fifo_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int cb_pcidas_ao_readback_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int cb_pcidas_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
++static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd);
++static int cb_pcidas_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
+ static int cb_pcidas_ao_inttrig(struct comedi_device *dev,
+ 				struct comedi_subdevice *subdev,
+ 				unsigned int trig_num);
+-static int cb_pcidas_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd);
++static int cb_pcidas_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd);
+ static irqreturn_t cb_pcidas_interrupt(int irq, void *d);
+-static void handle_ao_interrupt(struct comedi_device * dev, unsigned int status);
+-static int cb_pcidas_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int cb_pcidas_ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+-static void cb_pcidas_load_counters(struct comedi_device * dev, unsigned int *ns,
++static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status);
++static int cb_pcidas_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
++static int cb_pcidas_ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
++static void cb_pcidas_load_counters(struct comedi_device *dev, unsigned int *ns,
+ 	int round_flags);
+-static int eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int caldac_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int caldac_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int trimpot_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int cb_pcidas_trimpot_write(struct comedi_device * dev, unsigned int channel,
++static int eeprom_read_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int caldac_read_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int caldac_write_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int trimpot_read_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int cb_pcidas_trimpot_write(struct comedi_device *dev, unsigned int channel,
+ 	unsigned int value);
+-static int trimpot_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int dac08_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int dac08_write(struct comedi_device * dev, unsigned int value);
+-static int dac08_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int caldac_8800_write(struct comedi_device * dev, unsigned int address,
++static int trimpot_write_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int dac08_read_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int dac08_write(struct comedi_device *dev, unsigned int value);
++static int dac08_write_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int caldac_8800_write(struct comedi_device *dev, unsigned int address,
+ 	uint8_t value);
+-static int trimpot_7376_write(struct comedi_device * dev, uint8_t value);
+-static int trimpot_8402_write(struct comedi_device * dev, unsigned int channel,
++static int trimpot_7376_write(struct comedi_device *dev, uint8_t value);
++static int trimpot_8402_write(struct comedi_device *dev, unsigned int channel,
+ 	uint8_t value);
+-static int nvram_read(struct comedi_device * dev, unsigned int address,
+-	uint8_t * data);
++static int nvram_read(struct comedi_device *dev, unsigned int address,
++	uint8_t *data);
+ 
+-static inline unsigned int cal_enable_bits(struct comedi_device * dev)
++static inline unsigned int cal_enable_bits(struct comedi_device *dev)
+ {
+ 	return CAL_EN_BIT | CAL_SRC_BITS(devpriv->calibration_source);
+ }
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
+index 49dfd8f09e27..adce530adc53 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
+@@ -1137,73 +1137,73 @@ static struct comedi_driver driver_cb_pcidas = {
+ 	.detach = detach,
+ };
+ 
+-static int ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int ao_readback_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd);
+-static int ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int ao_inttrig(struct comedi_device * dev, struct comedi_subdevice * subdev,
++static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int ao_readback_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
++static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd);
++static int ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
++static int ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *subdev,
+ 	unsigned int trig_num);
+-static int ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd);
++static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd);
+ static irqreturn_t handle_interrupt(int irq, void *d);
+-static int ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
++static int ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
++static int ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
+ static int dio_callback(int dir, int port, int data, unsigned long arg);
+ static int dio_callback_4020(int dir, int port, int data, unsigned long arg);
+-static int di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int dio_60xx_config_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int dio_60xx_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int calib_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int calib_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int ad8402_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static void ad8402_write(struct comedi_device * dev, unsigned int channel,
++static int di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int dio_60xx_config_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int dio_60xx_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int calib_read_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int calib_write_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int ad8402_read_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static void ad8402_write(struct comedi_device *dev, unsigned int channel,
+ 	unsigned int value);
+-static int ad8402_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static void check_adc_timing(struct comedi_device * dev, struct comedi_cmd * cmd);
++static int ad8402_write_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int eeprom_read_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static void check_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd);
+ static unsigned int get_divisor(unsigned int ns, unsigned int flags);
+-static void i2c_write(struct comedi_device * dev, unsigned int address,
+-	const uint8_t * data, unsigned int length);
+-static void caldac_write(struct comedi_device * dev, unsigned int channel,
++static void i2c_write(struct comedi_device *dev, unsigned int address,
++	const uint8_t *data, unsigned int length);
++static void caldac_write(struct comedi_device *dev, unsigned int channel,
+ 	unsigned int value);
+-static int caldac_8800_write(struct comedi_device * dev, unsigned int address,
++static int caldac_8800_write(struct comedi_device *dev, unsigned int address,
+ 	uint8_t value);
+ /* static int dac_1590_write(struct comedi_device *dev, unsigned int dac_a, unsigned int dac_b); */
+-static int caldac_i2c_write(struct comedi_device * dev, unsigned int caldac_channel,
++static int caldac_i2c_write(struct comedi_device *dev, unsigned int caldac_channel,
+ 	unsigned int value);
+-static void abort_dma(struct comedi_device * dev, unsigned int channel);
+-static void disable_plx_interrupts(struct comedi_device * dev);
+-static int set_ai_fifo_size(struct comedi_device * dev, unsigned int num_samples);
+-static unsigned int ai_fifo_size(struct comedi_device * dev);
+-static int set_ai_fifo_segment_length(struct comedi_device * dev,
++static void abort_dma(struct comedi_device *dev, unsigned int channel);
++static void disable_plx_interrupts(struct comedi_device *dev);
++static int set_ai_fifo_size(struct comedi_device *dev, unsigned int num_samples);
++static unsigned int ai_fifo_size(struct comedi_device *dev);
++static int set_ai_fifo_segment_length(struct comedi_device *dev,
+ 	unsigned int num_entries);
+-static void disable_ai_pacing(struct comedi_device * dev);
+-static void disable_ai_interrupts(struct comedi_device * dev);
+-static void enable_ai_interrupts(struct comedi_device * dev, const struct comedi_cmd * cmd);
++static void disable_ai_pacing(struct comedi_device *dev);
++static void disable_ai_interrupts(struct comedi_device *dev);
++static void enable_ai_interrupts(struct comedi_device *dev, const struct comedi_cmd *cmd);
+ static unsigned int get_ao_divisor(unsigned int ns, unsigned int flags);
+-static void load_ao_dma(struct comedi_device * dev, const struct comedi_cmd * cmd);
++static void load_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd);
+ 
+ COMEDI_PCI_INITCLEANUP(driver_cb_pcidas, pcidas64_pci_table);
+ 
+-static unsigned int ai_range_bits_6xxx(const struct comedi_device * dev,
++static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev,
+ 	unsigned int range_index)
+ {
+ 	const struct comedi_krange *range =
+diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
+index 4433f6446b3f..982837d879ce 100644
+--- a/drivers/staging/comedi/drivers/das16.c
++++ b/drivers/staging/comedi/drivers/das16.c
+@@ -326,34 +326,34 @@ struct munge_info {
+ 	unsigned have_byte:1;
+ };
+ 
+-static int das16_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int das16_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int das16_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int das16_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-
+-static int das16_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd);
+-static int das16_cmd_exec(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int das16_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+-static void das16_ai_munge(struct comedi_device * dev, struct comedi_subdevice * s,
++static int das16_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int das16_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int das16_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int das16_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++
++static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd);
++static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s);
++static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
++static void das16_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	void *array, unsigned int num_bytes, unsigned int start_chan_index);
+ 
+-static void das16_reset(struct comedi_device * dev);
++static void das16_reset(struct comedi_device *dev);
+ static irqreturn_t das16_dma_interrupt(int irq, void *d);
+ static void das16_timer_interrupt(unsigned long arg);
+-static void das16_interrupt(struct comedi_device * dev);
++static void das16_interrupt(struct comedi_device *dev);
+ 
+-static unsigned int das16_set_pacer(struct comedi_device * dev, unsigned int ns,
++static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
+ 	int flags);
+-static int das1600_mode_detect(struct comedi_device * dev);
+-static unsigned int das16_suggest_transfer_size(struct comedi_device * dev,
++static int das1600_mode_detect(struct comedi_device *dev);
++static unsigned int das16_suggest_transfer_size(struct comedi_device *dev,
+ 	struct comedi_cmd cmd);
+ 
+-static void reg_dump(struct comedi_device * dev);
++static void reg_dump(struct comedi_device *dev);
+ 
+ struct das16_board {
+ 	const char *name;
+diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
+index 031d6307c09d..91b1a0e7575c 100644
+--- a/drivers/staging/comedi/drivers/das16m1.c
++++ b/drivers/staging/comedi/drivers/das16m1.c
+@@ -131,23 +131,23 @@ static const struct comedi_lrange range_das16m1 = { 9,
+ 		}
+ };
+ 
+-static int das16m1_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int das16m1_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int das16m1_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-
+-static int das16m1_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd);
+-static int das16m1_cmd_exec(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int das16m1_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+-
+-static int das16m1_poll(struct comedi_device * dev, struct comedi_subdevice * s);
++static int das16m1_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int das16m1_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int das16m1_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++
++static int das16m1_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd);
++static int das16m1_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s);
++static int das16m1_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
++
++static int das16m1_poll(struct comedi_device *dev, struct comedi_subdevice *s);
+ static irqreturn_t das16m1_interrupt(int irq, void *d);
+-static void das16m1_handler(struct comedi_device * dev, unsigned int status);
++static void das16m1_handler(struct comedi_device *dev, unsigned int status);
+ 
+-static unsigned int das16m1_set_pacer(struct comedi_device * dev, unsigned int ns,
++static unsigned int das16m1_set_pacer(struct comedi_device *dev, unsigned int ns,
+ 	int round_flag);
+ 
+ static int das16m1_irq_bits(unsigned int irq);
+diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
+index b420e7649bc9..9c6c9b89558a 100644
+--- a/drivers/staging/comedi/drivers/das1800.c
++++ b/drivers/staging/comedi/drivers/das1800.c
+@@ -180,37 +180,37 @@ enum {
+ 	das1802hr, das1802hr_da, das1801hc, das1802hc, das1801ao, das1802ao
+ };
+ 
+-static int das1800_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int das1800_detach(struct comedi_device * dev);
+-static int das1800_probe(struct comedi_device * dev);
+-static int das1800_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
++static int das1800_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int das1800_detach(struct comedi_device *dev);
++static int das1800_probe(struct comedi_device *dev);
++static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
+ static irqreturn_t das1800_interrupt(int irq, void *d);
+-static int das1800_ai_poll(struct comedi_device * dev, struct comedi_subdevice * s);
+-static void das1800_ai_handler(struct comedi_device * dev);
+-static void das1800_handle_dma(struct comedi_device * dev, struct comedi_subdevice * s,
++static int das1800_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s);
++static void das1800_ai_handler(struct comedi_device *dev);
++static void das1800_handle_dma(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int status);
+-static void das1800_flush_dma(struct comedi_device * dev, struct comedi_subdevice * s);
+-static void das1800_flush_dma_channel(struct comedi_device * dev, struct comedi_subdevice * s,
+-	unsigned int channel, uint16_t * buffer);
+-static void das1800_handle_fifo_half_full(struct comedi_device * dev,
+-	struct comedi_subdevice * s);
+-static void das1800_handle_fifo_not_empty(struct comedi_device * dev,
+-	struct comedi_subdevice * s);
+-static int das1800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd);
+-static int das1800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int das1800_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int das1800_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int das1800_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int das1800_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-
+-static int das1800_set_frequency(struct comedi_device * dev);
++static void das1800_flush_dma(struct comedi_device *dev, struct comedi_subdevice *s);
++static void das1800_flush_dma_channel(struct comedi_device *dev, struct comedi_subdevice *s,
++	unsigned int channel, uint16_t *buffer);
++static void das1800_handle_fifo_half_full(struct comedi_device *dev,
++	struct comedi_subdevice *s);
++static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
++	struct comedi_subdevice *s);
++static int das1800_ai_do_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd);
++static int das1800_ai_do_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
++static int das1800_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int das1800_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int das1800_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int das1800_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++
++static int das1800_set_frequency(struct comedi_device *dev);
+ static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode);
+-static unsigned int suggest_transfer_size(struct comedi_cmd * cmd);
++static unsigned int suggest_transfer_size(struct comedi_cmd *cmd);
+ 
+ /* analog input ranges */
+ static const struct comedi_lrange range_ai_das1801 = {
+diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
+index 71aeae3d57a8..db646598619e 100644
+--- a/drivers/staging/comedi/drivers/das800.c
++++ b/drivers/staging/comedi/drivers/das800.c
+@@ -257,22 +257,22 @@ static struct comedi_driver driver_das800 = {
+ };
+ 
+ static irqreturn_t das800_interrupt(int irq, void *d);
+-static void enable_das800(struct comedi_device * dev);
+-static void disable_das800(struct comedi_device * dev);
+-static int das800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd);
+-static int das800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int das800_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int das800_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int das800_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int das800_probe(struct comedi_device * dev);
+-static int das800_set_frequency(struct comedi_device * dev);
++static void enable_das800(struct comedi_device *dev);
++static void disable_das800(struct comedi_device *dev);
++static int das800_ai_do_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd);
++static int das800_ai_do_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
++static int das800_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int das800_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int das800_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int das800_probe(struct comedi_device *dev);
++static int das800_set_frequency(struct comedi_device *dev);
+ 
+ /* checks and probes das-800 series board type */
+-static int das800_probe(struct comedi_device * dev)
++static int das800_probe(struct comedi_device *dev)
+ {
+ 	int id_bits;
+ 	unsigned long irq_flags;
+diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
+index ce53d161a690..e7c5130de8d0 100644
+--- a/drivers/staging/comedi/drivers/dmm32at.c
++++ b/drivers/staging/comedi/drivers/dmm32at.c
+@@ -289,23 +289,23 @@ static struct comedi_driver driver_dmm32at = {
+ };
+ 
+ /* prototypes for driver functions below */
+-static int dmm32at_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int dmm32at_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int dmm32at_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int dmm32at_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int dmm32at_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int dmm32at_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd);
+-static int dmm32at_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int dmm32at_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
++static int dmm32at_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int dmm32at_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int dmm32at_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int dmm32at_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int dmm32at_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int dmm32at_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd);
++static int dmm32at_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
++static int dmm32at_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
+ static int dmm32at_ns_to_timer(unsigned int *ns, int round);
+ static irqreturn_t dmm32at_isr(int irq, void *d);
+-void dmm32at_setaitimer(struct comedi_device * dev, unsigned int nansec);
++void dmm32at_setaitimer(struct comedi_device *dev, unsigned int nansec);
+ 
+ /*
+  * Attach is called by the Comedi core to configure the driver
+diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
+index 567dd5290e8f..098a78e9307a 100644
+--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
++++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
+@@ -52,15 +52,15 @@ support could be added to this driver.
+ #include "plx9080.h"
+ #include "comedi_fc.h"
+ 
+-static int hpdi_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int hpdi_detach(struct comedi_device * dev);
+-void abort_dma(struct comedi_device * dev, unsigned int channel);
+-static int hpdi_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int hpdi_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd);
+-static int hpdi_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
++static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int hpdi_detach(struct comedi_device *dev);
++void abort_dma(struct comedi_device *dev, unsigned int channel);
++static int hpdi_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
++static int hpdi_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd);
++static int hpdi_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
+ static irqreturn_t handle_interrupt(int irq, void *d);
+-static int dio_config_block_size(struct comedi_device * dev, unsigned int * data);
++static int dio_config_block_size(struct comedi_device *dev, unsigned int *data);
+ 
+ #undef HPDI_DEBUG		/*  disable debugging messages */
+ /* #define HPDI_DEBUG      enable debugging code */
+diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
+index 0e42f18cdbfe..e6afc42d5d37 100644
+--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
++++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
+@@ -181,15 +181,15 @@ static struct comedi_driver driver_a2150 = {
+ };
+ 
+ static irqreturn_t a2150_interrupt(int irq, void *d);
+-static int a2150_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd);
+-static int a2150_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int a2150_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int a2150_get_timing(struct comedi_device * dev, unsigned int *period,
++static int a2150_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd);
++static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
++static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int a2150_get_timing(struct comedi_device *dev, unsigned int *period,
+ 	int flags);
+-static int a2150_probe(struct comedi_device * dev);
+-static int a2150_set_chanlist(struct comedi_device * dev, unsigned int start_channel,
++static int a2150_probe(struct comedi_device *dev);
++static int a2150_set_chanlist(struct comedi_device *dev, unsigned int start_channel,
+ 	unsigned int num_channels);
+ /*
+  * A convenient macro that defines init_module() and cleanup_module(),
+diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
+index b02d2f33d528..215f7a0e9d36 100644
+--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
++++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
+@@ -125,15 +125,15 @@ static const struct atmio16_board_t atmio16_boards[] = {
+ #define boardtype ((const struct atmio16_board_t *)dev->board_ptr)
+ 
+ /* function prototypes */
+-static int atmio16d_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int atmio16d_detach(struct comedi_device * dev);
++static int atmio16d_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int atmio16d_detach(struct comedi_device *dev);
+ static irqreturn_t atmio16d_interrupt(int irq, void *d);
+-static int atmio16d_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd);
+-static int atmio16d_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int atmio16d_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+-static void reset_counters(struct comedi_device * dev);
+-static void reset_atmio16d(struct comedi_device * dev);
++static int atmio16d_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd);
++static int atmio16d_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
++static int atmio16d_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
++static void reset_counters(struct comedi_device *dev);
++static void reset_atmio16d(struct comedi_device *dev);
+ 
+ /* main driver struct */
+ static struct comedi_driver driver_atmio16d = {
+diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
+index e6ee7d94ca9a..d1a2b5065036 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc.c
++++ b/drivers/staging/comedi/drivers/ni_labpc.c
+@@ -163,46 +163,46 @@ NI manuals:
+ #define   INIT_A1_BITS	0x70	/*  put hardware conversion counter output in harmless state (a1 mode 0) */
+ #define COUNTER_B_BASE_REG	0x18
+ 
+-static int labpc_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int labpc_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
++static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
+ static irqreturn_t labpc_interrupt(int irq, void *d);
+-static int labpc_drain_fifo(struct comedi_device * dev);
+-static void labpc_drain_dma(struct comedi_device * dev);
+-static void handle_isa_dma(struct comedi_device * dev);
+-static void labpc_drain_dregs(struct comedi_device * dev);
+-static int labpc_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd);
+-static int labpc_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int labpc_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int labpc_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int labpc_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int labpc_calib_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int labpc_calib_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int labpc_eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int labpc_eeprom_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int labpc_drain_fifo(struct comedi_device *dev);
++static void labpc_drain_dma(struct comedi_device *dev);
++static void handle_isa_dma(struct comedi_device *dev);
++static void labpc_drain_dregs(struct comedi_device *dev);
++static int labpc_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd);
++static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
++static int labpc_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int labpc_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int labpc_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int labpc_calib_read_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int labpc_calib_write_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int labpc_eeprom_read_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int labpc_eeprom_write_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd);
+-static void labpc_adc_timing(struct comedi_device * dev, struct comedi_cmd * cmd);
++static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd);
+ #ifdef CONFIG_COMEDI_PCI
+ static int labpc_find_device(struct comedi_device *dev, int bus, int slot);
+ #endif
+ static int labpc_dio_mem_callback(int dir, int port, int data,
+ 	unsigned long arg);
+-static void labpc_serial_out(struct comedi_device * dev, unsigned int value,
++static void labpc_serial_out(struct comedi_device *dev, unsigned int value,
+ 	unsigned int num_bits);
+-static unsigned int labpc_serial_in(struct comedi_device * dev);
+-static unsigned int labpc_eeprom_read(struct comedi_device * dev,
++static unsigned int labpc_serial_in(struct comedi_device *dev);
++static unsigned int labpc_eeprom_read(struct comedi_device *dev,
+ 	unsigned int address);
+-static unsigned int labpc_eeprom_read_status(struct comedi_device * dev);
+-static unsigned int labpc_eeprom_write(struct comedi_device * dev,
++static unsigned int labpc_eeprom_read_status(struct comedi_device *dev);
++static unsigned int labpc_eeprom_write(struct comedi_device *dev,
+ 	unsigned int address, unsigned int value);
+-static void write_caldac(struct comedi_device * dev, unsigned int channel,
++static void write_caldac(struct comedi_device *dev, unsigned int channel,
+ 	unsigned int value);
+ 
+ enum scan_mode {
+diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
+index de444fff8d3e..9d025ab5b9f3 100644
+--- a/drivers/staging/comedi/drivers/pcmmio.c
++++ b/drivers/staging/comedi/drivers/pcmmio.c
+@@ -295,24 +295,24 @@ static struct comedi_driver driver = {
+ 	.num_names = sizeof(pcmmio_boards) / sizeof(struct pcmmio_board),
+ };
+ 
+-static int pcmmio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int pcmmio_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int pcmmio_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int pcmmio_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+ static irqreturn_t interrupt_pcmmio(int irq, void *d);
+ static void pcmmio_stop_intr(struct comedi_device *, struct comedi_subdevice *);
+-static int pcmmio_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int pcmmio_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int pcmmio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd);
++static int pcmmio_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
++static int pcmmio_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
++static int pcmmio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd);
+ 
+ /* some helper functions to deal with specifics of this device's registers */
+-static void init_asics(struct comedi_device * dev);	/* sets up/clears ASIC chips to defaults */
+-static void switch_page(struct comedi_device * dev, int asic, int page);
++static void init_asics(struct comedi_device *dev);	/* sets up/clears ASIC chips to defaults */
++static void switch_page(struct comedi_device *dev, int asic, int page);
+ #ifdef notused
+-static void lock_port(struct comedi_device * dev, int asic, int port);
+-static void unlock_port(struct comedi_device * dev, int asic, int port);
++static void lock_port(struct comedi_device *dev, int asic, int port);
++static void unlock_port(struct comedi_device *dev, int asic, int port);
+ #endif
+ 
+ /*
+diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
+index bf419e0445b4..e515eadc0fb5 100644
+--- a/drivers/staging/comedi/drivers/pcmuio.c
++++ b/drivers/staging/comedi/drivers/pcmuio.c
+@@ -253,24 +253,24 @@ static struct comedi_driver driver = {
+ 	.num_names = sizeof(pcmuio_boards) / sizeof(struct pcmuio_board),
+ };
+ 
+-static int pcmuio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int pcmuio_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int pcmuio_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int pcmuio_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+ static irqreturn_t interrupt_pcmuio(int irq, void *d);
+ static void pcmuio_stop_intr(struct comedi_device *, struct comedi_subdevice *);
+-static int pcmuio_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int pcmuio_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int pcmuio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd);
++static int pcmuio_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
++static int pcmuio_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
++static int pcmuio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd);
+ 
+ /* some helper functions to deal with specifics of this device's registers */
+-static void init_asics(struct comedi_device * dev);	/* sets up/clears ASIC chips to defaults */
+-static void switch_page(struct comedi_device * dev, int asic, int page);
++static void init_asics(struct comedi_device *dev);	/* sets up/clears ASIC chips to defaults */
++static void switch_page(struct comedi_device *dev, int asic, int page);
+ #ifdef notused
+-static void lock_port(struct comedi_device * dev, int asic, int port);
+-static void unlock_port(struct comedi_device * dev, int asic, int port);
++static void lock_port(struct comedi_device *dev, int asic, int port);
++static void unlock_port(struct comedi_device *dev, int asic, int port);
+ #endif
+ 
+ /*

commit 9b9bcba0cafa2578cebbe0eca01eaafd49f3e43b
+Author: Bill Pemberton 
+Date:   Thu Apr 23 15:54:53 2009 -0400
+
+    Staging: comedi: remove space after ampersand
+    
+    Change calses of & foo to &foo as suggested by checkpatch.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+index a6115f480546..60213d292a5f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+@@ -695,7 +695,7 @@ int i_APCI1710_InsnBitsTimer(struct comedi_device *dev, struct comedi_subdevice
+ 		i_ReturnValue = i_APCI1710_ReadTimerValue(dev,
+ 							  (unsigned char)CR_AREF(insn->chanspec),
+ 							  (unsigned char)CR_CHAN(insn->chanspec),
+-							  (unsigned int *) & data[0]);
++							  (unsigned int *) &data[0]);
+ 		break;
+ 
+ 	case APCI1710_TIMER_GETOUTPUTLEVEL:
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+index 6aab4290cea2..ccb109a851f2 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+@@ -1101,25 +1101,25 @@ int i_APCI1710_InsnReadChrono(struct comedi_device *dev, struct comedi_subdevice
+ 	switch (b_ReadType) {
+ 	case APCI1710_CHRONO_PROGRESS_STATUS:
+ 		i_ReturnValue = i_APCI1710_GetChronoProgressStatus(dev,
+-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) & data[0]);
++			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
+ 		break;
+ 
+ 	case APCI1710_CHRONO_READVALUE:
+ 		i_ReturnValue = i_APCI1710_ReadChronoValue(dev,
+ 			(unsigned char) CR_AREF(insn->chanspec),
+ 			(unsigned int) insn->unused[0],
+-			(unsigned char *) & data[0], (unsigned int *) & data[1]);
++			(unsigned char *) &data[0], (unsigned int *) &data[1]);
+ 		break;
+ 
+ 	case APCI1710_CHRONO_CONVERTVALUE:
+ 		i_ReturnValue = i_APCI1710_ConvertChronoValue(dev,
+ 			(unsigned char) CR_AREF(insn->chanspec),
+ 			(unsigned int) insn->unused[0],
+-			(unsigned int *) & data[0],
+-			(unsigned char *) & data[1],
+-			(unsigned char *) & data[2],
+-			(unsigned int *) & data[3],
+-			(unsigned int *) & data[4], (unsigned int *) & data[5]);
++			(unsigned int *) &data[0],
++			(unsigned char *) &data[1],
++			(unsigned char *) &data[2],
++			(unsigned int *) &data[3],
++			(unsigned int *) &data[4], (unsigned int *) &data[5]);
+ 		break;
+ 
+ 	case APCI1710_CHRONO_READINTERRUPT:
+@@ -1962,7 +1962,7 @@ int i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,
+ 		 /**********************************/
+ 					/* Test the digital input channel */
+ 		 /**********************************/
+-					pb_ChannelStatus = (unsigned char *) & data[0];
++					pb_ChannelStatus = (unsigned char *) &data[0];
+ 					b_InputChannel =
+ 						(unsigned char) CR_CHAN(insn->chanspec);
+ 
+@@ -1992,7 +1992,7 @@ int i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,
+ 
+ 				case APCI1710_CHRONO_READ_PORT:
+ 
+-					pb_PortValue = (unsigned char *) & data[0];
++					pb_PortValue = (unsigned char *) &data[0];
+ 
+ 					dw_Status =
+ 						inl(devpriv->s_BoardInfos.
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+index 2047c46f1389..f3e47e5791db 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+@@ -303,7 +303,7 @@ int i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device *dev,
+ 	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+ 	b_InputChannel = (unsigned char) CR_CHAN(insn->chanspec);
+ 	data[0] = 0;
+-	pb_ChannelStatus = (unsigned char *) & data[0];
++	pb_ChannelStatus = (unsigned char *) &data[0];
+ 	i_ReturnValue = insn->n;
+ 
+ 	/**************************/
+@@ -747,7 +747,7 @@ int i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device *dev,
+ 	b_PortOnOFF = (unsigned char) data[1];	/*  if output then On or Off */
+ 	b_PortValue = (unsigned char) data[2];	/*  if out put then Value */
+ 	i_ReturnValue = insn->n;
+-	pb_PortValue = (unsigned char *) & data[0];
++	pb_PortValue = (unsigned char *) &data[0];
+ /* if input then read value */
+ 
+ 	switch (b_PortOperation) {
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+index db03acf99f49..6c092efee7bd 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+@@ -96,7 +96,7 @@ int i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev, struct comedi_subdevi
+ 
+ 	case APCI1710_INCCPT_COUNTERAUTOTEST:
+ 		i_ReturnValue = i_APCI1710_CounterAutoTest(dev,
+-			(unsigned char *) & data[0]);
++			(unsigned char *) &data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_INITINDEX:
+@@ -126,7 +126,7 @@ int i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev, struct comedi_subdevi
+ 		i_ReturnValue = i_APCI1710_InitFrequencyMeasurement(dev,
+ 			CR_AREF(insn->chanspec),
+ 			(unsigned char) data[0],
+-			(unsigned char) data[1], (unsigned int) data[2], (unsigned int *) & data[0]);
++			(unsigned char) data[1], (unsigned int) data[2], (unsigned int *) &data[0]);
+ 		break;
+ 
+ 	default:
+@@ -4062,69 +4062,69 @@ int i_APCI1710_InsnReadINCCPT(struct comedi_device *dev, struct comedi_subdevice
+ 	case APCI1710_INCCPT_READLATCHREGISTERSTATUS:
+ 		i_ReturnValue = i_APCI1710_ReadLatchRegisterStatus(dev,
+ 			(unsigned char) CR_AREF(insn->chanspec),
+-			(unsigned char) CR_RANGE(insn->chanspec), (unsigned char *) & data[0]);
++			(unsigned char) CR_RANGE(insn->chanspec), (unsigned char *) &data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_READLATCHREGISTERVALUE:
+ 		i_ReturnValue = i_APCI1710_ReadLatchRegisterValue(dev,
+ 			(unsigned char) CR_AREF(insn->chanspec),
+-			(unsigned char) CR_RANGE(insn->chanspec), (unsigned int *) & data[0]);
++			(unsigned char) CR_RANGE(insn->chanspec), (unsigned int *) &data[0]);
+ 		printk("Latch Register Value %d\n", data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_READ16BITCOUNTERVALUE:
+ 		i_ReturnValue = i_APCI1710_Read16BitCounterValue(dev,
+ 			(unsigned char) CR_AREF(insn->chanspec),
+-			(unsigned char) CR_RANGE(insn->chanspec), (unsigned int *) & data[0]);
++			(unsigned char) CR_RANGE(insn->chanspec), (unsigned int *) &data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_READ32BITCOUNTERVALUE:
+ 		i_ReturnValue = i_APCI1710_Read32BitCounterValue(dev,
+-			(unsigned char) CR_AREF(insn->chanspec), (unsigned int *) & data[0]);
++			(unsigned char) CR_AREF(insn->chanspec), (unsigned int *) &data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_GETINDEXSTATUS:
+ 		i_ReturnValue = i_APCI1710_GetIndexStatus(dev,
+-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) & data[0]);
++			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_GETREFERENCESTATUS:
+ 		i_ReturnValue = i_APCI1710_GetReferenceStatus(dev,
+-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) & data[0]);
++			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_GETUASSTATUS:
+ 		i_ReturnValue = i_APCI1710_GetUASStatus(dev,
+-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) & data[0]);
++			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_GETCBSTATUS:
+ 		i_ReturnValue = i_APCI1710_GetCBStatus(dev,
+-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) & data[0]);
++			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_GET16BITCBSTATUS:
+ 		i_ReturnValue = i_APCI1710_Get16BitCBStatus(dev,
+ 			(unsigned char) CR_AREF(insn->chanspec),
+-			(unsigned char *) & data[0], (unsigned char *) & data[1]);
++			(unsigned char *) &data[0], (unsigned char *) &data[1]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_GETUDSTATUS:
+ 		i_ReturnValue = i_APCI1710_GetUDStatus(dev,
+-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) & data[0]);
++			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
+ 
+ 		break;
+ 
+ 	case APCI1710_INCCPT_GETINTERRUPTUDLATCHEDSTATUS:
+ 		i_ReturnValue = i_APCI1710_GetInterruptUDLatchedStatus(dev,
+-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) & data[0]);
++			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_READFREQUENCYMEASUREMENT:
+ 		i_ReturnValue = i_APCI1710_ReadFrequencyMeasurement(dev,
+ 			(unsigned char) CR_AREF(insn->chanspec),
+-			(unsigned char *) & data[0],
+-			(unsigned char *) & data[1], (unsigned int *) & data[2]);
++			(unsigned char *) &data[0],
++			(unsigned char *) &data[1], (unsigned int *) &data[2]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_READINTERRUPT:
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+index b6e2e3fd49ff..0fc2285c9ef8 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+@@ -724,8 +724,8 @@ int i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device *dev,
+ 	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+ 	b_Type = (unsigned char) data[0];
+ 	b_PulseEncoderNbr = (unsigned char) data[1];
+-	pb_Status = (unsigned char *) & data[0];
+-	pul_ReadValue = (unsigned int *) & data[1];
++	pb_Status = (unsigned char *) &data[0];
++	pul_ReadValue = (unsigned int *) &data[1];
+ 
+ 	/***********************************/
+ 	/* Test the selected module number */
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+index f330093ee3bb..138a84f572c8 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+@@ -85,23 +85,23 @@ int i_APCI1710_InsnConfigPWM(struct comedi_device *dev, struct comedi_subdevice
+ 			(unsigned char) data[2],	/*  b_TimingUnit */
+ 			(unsigned int) data[3],	/* ul_LowTiming */
+ 			(unsigned int) data[4],	/* ul_HighTiming */
+-			(unsigned int *) & data[0],	/* pul_RealLowTiming */
+-			(unsigned int *) & data[1]	/* pul_RealHighTiming */
++			(unsigned int *) &data[0],	/* pul_RealLowTiming */
++			(unsigned int *) &data[1]	/* pul_RealHighTiming */
+ 			);
+ 		break;
+ 
+ 	case APCI1710_PWM_GETINITDATA:
+ 		i_ReturnValue = i_APCI1710_GetPWMInitialisation(dev, (unsigned char) CR_AREF(insn->chanspec),	/*  b_ModulNbr */
+ 			(unsigned char) data[0],	/* b_PWM */
+-			(unsigned char *) & data[0],	/* pb_TimingUnit */
+-			(unsigned int *) & data[1],	/* pul_LowTiming */
+-			(unsigned int *) & data[2],	/* pul_HighTiming */
+-			(unsigned char *) & data[3],	/*  pb_StartLevel */
+-			(unsigned char *) & data[4],	/*  pb_StopMode */
+-			(unsigned char *) & data[5],	/*  pb_StopLevel */
+-			(unsigned char *) & data[6],	/*  pb_ExternGate */
+-			(unsigned char *) & data[7],	/*  pb_InterruptEnable */
+-			(unsigned char *) & data[8]	/*  pb_Enable */
++			(unsigned char *) &data[0],	/* pb_TimingUnit */
++			(unsigned int *) &data[1],	/* pul_LowTiming */
++			(unsigned int *) &data[2],	/* pul_HighTiming */
++			(unsigned char *) &data[3],	/*  pb_StartLevel */
++			(unsigned char *) &data[4],	/*  pb_StopMode */
++			(unsigned char *) &data[5],	/*  pb_StopLevel */
++			(unsigned char *) &data[6],	/*  pb_ExternGate */
++			(unsigned char *) &data[7],	/*  pb_InterruptEnable */
++			(unsigned char *) &data[8]	/*  pb_Enable */
+ 			);
+ 		break;
+ 
+@@ -3474,8 +3474,8 @@ int i_APCI1710_InsnReadGetPWMStatus(struct comedi_device *dev, struct comedi_sub
+ 	i_ReturnValue = insn->n;
+ 	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+ 	b_PWM = (unsigned char) CR_CHAN(insn->chanspec);
+-	pb_PWMOutputStatus = (unsigned char *) & data[0];
+-	pb_ExternGateStatus = (unsigned char *) & data[1];
++	pb_PWMOutputStatus = (unsigned char *) &data[0];
++	pb_ExternGateStatus = (unsigned char *) &data[1];
+ 
+ 	/**************************/
+ 	/* Test the module number */
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+index 7705b7b30579..a94b98093826 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+@@ -422,12 +422,12 @@ int i_APCI1710_InsnReadSSIValue(struct comedi_device *dev, struct comedi_subdevi
+ 	unsigned int *pul_TurnCpt1;
+ 
+ 	i_ReturnValue = insn->n;
+-	pul_Position1 = (unsigned int *) & data[0];
++	pul_Position1 = (unsigned int *) &data[0];
+ /* For Read1 */
+-	pul_TurnCpt1 = (unsigned int *) & data[1];
++	pul_TurnCpt1 = (unsigned int *) &data[1];
+ /* For Read all */
+-	pul_Position = (unsigned int *) & data[0];	/* 0-2 */
+-	pul_TurnCpt = (unsigned int *) & data[3];	/* 3-5 */
++	pul_Position = (unsigned int *) &data[0];	/* 0-2 */
++	pul_TurnCpt = (unsigned int *) &data[3];	/* 3-5 */
+ 	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+ 	b_SelectedSSI = (unsigned char) CR_CHAN(insn->chanspec);
+ 	b_ReadType = (unsigned char) CR_RANGE(insn->chanspec);
+@@ -786,7 +786,7 @@ int i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev, struct comedi_sub
+ 				   /******************************************/
+ 
+ 				b_InputChannel = (unsigned char) CR_CHAN(insn->chanspec);
+-				pb_ChannelStatus = (unsigned char *) & data[0];
++				pb_ChannelStatus = (unsigned char *) &data[0];
+ 
+ 				if (b_InputChannel <= 2) {
+ 					/**************************/
+@@ -814,7 +814,7 @@ int i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev, struct comedi_sub
+ 					/**************************/
+ 				/* Read all digital input */
+ 					/**************************/
+-				pb_InputStatus = (unsigned char *) & data[0];
++				pb_InputStatus = (unsigned char *) &data[0];
+ 
+ 				dw_StatusReg =
+ 					inl(devpriv->s_BoardInfos.ui_Address +
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+index a9b64e9f745c..43198aafb2dc 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+@@ -1479,13 +1479,13 @@ int i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device *dev,
+ 	b_ModulNbr = CR_AREF(insn->chanspec);
+ 	b_TorCounter = CR_CHAN(insn->chanspec);
+ 
+-	pb_TimingUnit = (unsigned char *) & data[0];
+-	pul_TimingInterval = (unsigned int *) & data[1];
+-	pb_InputMode = (unsigned char *) & data[2];
+-	pb_ExternGate = (unsigned char *) & data[3];
+-	pb_CycleMode = (unsigned char *) & data[4];
+-	pb_Enable = (unsigned char *) & data[5];
+-	pb_InterruptEnable = (unsigned char *) & data[6];
++	pb_TimingUnit = (unsigned char *) &data[0];
++	pul_TimingInterval = (unsigned int *) &data[1];
++	pb_InputMode = (unsigned char *) &data[2];
++	pb_ExternGate = (unsigned char *) &data[3];
++	pb_CycleMode = (unsigned char *) &data[4];
++	pb_Enable = (unsigned char *) &data[5];
++	pb_InterruptEnable = (unsigned char *) &data[6];
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -1719,8 +1719,8 @@ int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device
+ 	b_ReadType = (unsigned char) data[0];
+ 	b_TorCounter = (unsigned char) data[1];
+ 	ui_TimeOut = (unsigned int) data[2];
+-	pb_TorCounterStatus = (unsigned char *) & data[0];
+-	pul_TorCounterValue = (unsigned int *) & data[1];
++	pb_TorCounterStatus = (unsigned char *) &data[0];
++	pul_TorCounterValue = (unsigned int *) &data[1];
+ 
+ 	/**************************/
+ 	/* Test the module number */
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+index 9d32aba3cf3f..d3d78d37de5c 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+@@ -439,7 +439,7 @@ int i_APCI1710_InsnBitsReadTTLIO(struct comedi_device *dev, struct comedi_subdev
+ 			switch (b_ReadType) {
+ 
+ 			case APCI1710_TTL_READCHANNEL:
+-				pb_ChannelStatus = (unsigned char *) & data[0];
++				pb_ChannelStatus = (unsigned char *) &data[0];
+ 	      /********************************/
+ 				/* Test the TTL I/O port number */
+ 	      /********************************/
+@@ -533,7 +533,7 @@ int i_APCI1710_InsnBitsReadTTLIO(struct comedi_device *dev, struct comedi_subdev
+ 				break;
+ 
+ 			case APCI1710_TTL_READPORT:
+-				pb_PortValue = (unsigned char *) & data[0];
++				pb_PortValue = (unsigned char *) &data[0];
+ 			  /********************************/
+ 				/* Test the TTL I/O port number */
+ 			  /********************************/
+@@ -665,7 +665,7 @@ int i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
+ 
+ 	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+ 	i_ReturnValue = insn->n;
+-	pul_PortValue = (unsigned int *) & data[0];
++	pul_PortValue = (unsigned int *) &data[0];
+ 
+ 	/**************************/
+ 	/* Test the module number */
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
+index eab7ac1d0f0b..988e3fc2b857 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
+@@ -380,7 +380,7 @@ int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device *dev,
+ 	/**************************/
+ 
+ 	if (i_ReturnValue >= 0) {
+-		pb_Status = (unsigned char *) & data[0];
++		pb_Status = (unsigned char *) &data[0];
+ 
+ 	   /*******************************/
+ 		/* Get the digital inpu status */
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
+index d1f3bae15524..8f7a5661a116 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -873,7 +873,7 @@ static int jr3_pci_attach(struct comedi_device *dev, struct comedi_devconfig *it
+ 				p->range[j].range.max = 1000000;
+ 				for (k = 0; k < 7; k++) {
+ 					p->range_table_list[j + k * 8] =
+-						(struct comedi_lrange *) & p->range[j];
++						(struct comedi_lrange *) &p->range[j];
+ 					p->maxdata_list[j + k * 8] = 0x7fff;
+ 				}
+ 			}
+@@ -882,9 +882,9 @@ static int jr3_pci_attach(struct comedi_device *dev, struct comedi_devconfig *it
+ 			p->range[8].range.max = 65536;
+ 
+ 			p->range_table_list[56] =
+-				(struct comedi_lrange *) & p->range[8];
++				(struct comedi_lrange *) &p->range[8];
+ 			p->range_table_list[57] =
+-				(struct comedi_lrange *) & p->range[8];
++				(struct comedi_lrange *) &p->range[8];
+ 			p->maxdata_list[56] = 0xffff;
+ 			p->maxdata_list[57] = 0xffff;
+ 			/*  Channel specific range and maxdata */
+diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
+index b9e8a1757365..de444fff8d3e 100644
+--- a/drivers/staging/comedi/drivers/pcmmio.c
++++ b/drivers/staging/comedi/drivers/pcmmio.c
+@@ -859,10 +859,10 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d)
+ 									}
+ 								}
+ 								/* Write the scan to the buffer. */
+-								if (comedi_buf_put(s->async, ((short *) & val)[0])
++								if (comedi_buf_put(s->async, ((short *) &val)[0])
+ 									&&
+ 									comedi_buf_put
+-									(s->async, ((short *) & val)[1])) {
++									(s->async, ((short *) &val)[1])) {
+ 									s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS);
+ 								} else {
+ 									/* Overflow! Stop acquisition!! */
+diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
+index e02017369f72..bf419e0445b4 100644
+--- a/drivers/staging/comedi/drivers/pcmuio.c
++++ b/drivers/staging/comedi/drivers/pcmuio.c
+@@ -781,10 +781,10 @@ static irqreturn_t interrupt_pcmuio(int irq, void *d)
+ 									}
+ 								}
+ 								/* Write the scan to the buffer. */
+-								if (comedi_buf_put(s->async, ((short *) & val)[0])
++								if (comedi_buf_put(s->async, ((short *) &val)[0])
+ 									&&
+ 									comedi_buf_put
+-									(s->async, ((short *) & val)[1])) {
++									(s->async, ((short *) &val)[1])) {
+ 									s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS);
+ 								} else {
+ 									/* Overflow! Stop acquisition!! */

commit 56e9e16619a0c14dc948cf88b3a7aaa70ac92b45
+Author: Bill Pemberton 
+Date:   Thu Apr 23 15:54:52 2009 -0400
+
+    Staging: comedi: more remove C99 comments
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+index ccb35aee68b5..8bb0f9a1abbb 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+@@ -811,35 +811,35 @@ int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
+ 	struct str_MainHeader s_MainHeader;
+ 	struct str_DigitalInputHeader s_DigitalInputHeader;
+ 	struct str_DigitalOutputHeader s_DigitalOutputHeader;
+-	//struct str_TimerMainHeader     s_TimerMainHeader,s_WatchdogMainHeader;
++	/* struct str_TimerMainHeader     s_TimerMainHeader,s_WatchdogMainHeader; */
+ 	str_AnalogOutputHeader s_AnalogOutputHeader;
+ 	struct str_AnalogInputHeader s_AnalogInputHeader;
+ 
+-	// Read size
++	/* Read size */
+ 	s_MainHeader.w_HeaderSize =
+ 		w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
+ 		0x100 + 8);
+ 
+-	// Read nbr of functionality
++	/* Read nbr of functionality */
+ 	w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+ 		pc_PCIChipInformation, 0x100 + 10);
+ 	s_MainHeader.b_Nfunctions = (unsigned char) w_Temp & 0x00FF;
+ 
+-	// Read functionality details
++	/* Read functionality details */
+ 	for (i = 0; i < s_MainHeader.b_Nfunctions; i++) {
+-		// Read Type
++		/* Read Type */
+ 		w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+ 			pc_PCIChipInformation, 0x100 + 12 + w_Count);
+ 		s_MainHeader.s_Functions[i].b_Type = (unsigned char) w_Temp & 0x3F;
+ 		w_Count = w_Count + 2;
+-		//Read Address
++		/* Read Address */
+ 		s_MainHeader.s_Functions[i].w_Address =
+ 			w_EepromReadWord(w_PCIBoardEepromAddress,
+ 			pc_PCIChipInformation, 0x100 + 12 + w_Count);
+ 		w_Count = w_Count + 2;
+ 	}
+ 
+-	// Display main header info
++	/* Display main header info */
+ 	for (i = 0; i < s_MainHeader.b_Nfunctions; i++) {
+ 
+ 		switch (s_MainHeader.s_Functions[i].b_Type) {
+diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c
+index 9921702bf399..54724653a792 100644
+--- a/drivers/staging/comedi/drivers/adq12b.c
++++ b/drivers/staging/comedi/drivers/adq12b.c
+@@ -81,7 +81,7 @@ If you do not specify any options, they will default to
+ 
+ #include "../comedidev.h"
+ 
+-// address scheme (page 2.17 of the manual)
++/* address scheme (page 2.17 of the manual) */
+ #define ADQ12B_SIZE     16
+ 
+ #define ADQ12B_CTREG    0x00
+@@ -94,12 +94,12 @@ If you do not specify any options, they will default to
+ #define ADQ12B_CONT2    0x0e
+ #define ADQ12B_COWORD   0x0f
+ 
+-// mask of the bit at STINR to check end of conversion
++/* mask of the bit at STINR to check end of conversion */
+ #define ADQ12B_EOC     0x20
+ 
+ #define TIMEOUT        20
+ 
+-// available ranges through the PGA gains
++/* available ranges through the PGA gains */
+ static const struct comedi_lrange range_adq12b_ai_bipolar = { 4, {
+         BIP_RANGE(5),
+         BIP_RANGE(2),
+@@ -134,7 +134,7 @@ static const struct adq12b_board adq12b_boards[] = {
+ 	.di_chans = 5,
+ 	.do_chans = 8
+         }
+-// potentially, more adq-based deviced will be added
++/* potentially, more adq-based deviced will be added */
+ /*,
+ 	.name = "adq12b",
+ 	.ai_chans = 16,  // this is just for reference, hardcoded again later
+@@ -337,17 +337,17 @@ static int adq12b_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s
+           /* wait for end of convertion */
+ 	  i = 0;
+           do {
+-//            comedi_udelay(1);
++/* comedi_udelay(1); */
+ 	    status = inb(dev->iobase + ADQ12B_STINR);
+             status = status & ADQ12B_EOC;
+           } while (status == 0 && ++i < TIMEOUT);
+-//          } while (++i < 10);
++/* } while (++i < 10); */
+ 
+           /* read data */
+           hi = inb(dev->iobase + ADQ12B_ADHIG);
+           lo = inb(dev->iobase + ADQ12B_ADLOW);
+ 
+-          //rt_printk("debug: chan=%d range=%d status=%d hi=%d lo=%d\n", channel, range, status,  hi, lo);
++          /* rt_printk("debug: chan=%d range=%d status=%d hi=%d lo=%d\n", channel, range, status,  hi, lo); */
+           data[n] = (hi << 8) | lo;
+ 
+         }
+diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
+index 773ba0e07f86..1d262c132d05 100644
+--- a/drivers/staging/comedi/drivers/ni_pcidio.c
++++ b/drivers/staging/comedi/drivers/ni_pcidio.c
+@@ -66,8 +66,8 @@ comedi_nonfree_firmware tarball available from http://www.comedi.org
+  */
+ 
+ #define USE_DMA
+-//#define DEBUG 1
+-//#define DEBUG_FLAGS
++/* #define DEBUG 1 */
++/* #define DEBUG_FLAGS */
+ 
+ #include "../comedidev.h"
+ 
+@@ -117,9 +117,9 @@ comedi_nonfree_firmware tarball available from http://www.comedi.org
+ #define Waited				(1<<5)
+ #define PrimaryTC				(1<<6)
+ #define SecondaryTC				(1<<7)
+-  //#define SerialRose
+-  //#define ReqRose
+-  //#define Paused
++  /* #define SerialRose */
++  /* #define ReqRose */
++  /* #define Paused */
+ 
+ #define Group_1_First_Clear		6	/* W */
+ #define Group_2_First_Clear		7	/* W */
+@@ -206,7 +206,7 @@ comedi_nonfree_firmware tarball available from http://www.comedi.org
+ 
+ #define DMA_Line_Control_Group1		76
+ #define DMA_Line_Control_Group2		108
+-// channel zero is none
++/* channel zero is none */
+ static inline unsigned primary_DMAChannel_bits(unsigned channel)
+ {
+ 	return channel & 0x3;
+@@ -486,7 +486,7 @@ static irqreturn_t nidio_interrupt(int irq, void *d)
+ 	struct comedi_async *async = s->async;
+ 	struct mite_struct *mite = devpriv->mite;
+ 
+-	//int i, j;
++	/* int i, j; */
+ 	long int AuxData = 0;
+ 	short data1 = 0;
+ 	short data2 = 0;
+@@ -496,9 +496,9 @@ static irqreturn_t nidio_interrupt(int irq, void *d)
+ 	unsigned int m_status = 0;
+ 	unsigned long irq_flags;
+ 
+-	//interrupcions parasites
++	/* interrupcions parasites */
+ 	if (dev->attached == 0) {
+-		// assume it's from another card
++		/* assume it's from another card */
+ 		return IRQ_NONE;
+ 	}
+ 
+@@ -511,8 +511,8 @@ static irqreturn_t nidio_interrupt(int irq, void *d)
+ 	ni_pcidio_print_flags(flags);
+ 	ni_pcidio_print_status(status);
+ 
+-	//printk("buf[0]=%08x\n",*(unsigned int *)async->prealloc_buf);
+-	//printk("buf[4096]=%08x\n",*(unsigned int *)(async->prealloc_buf+4096));
++	/* printk("buf[0]=%08x\n",*(unsigned int *)async->prealloc_buf); */
++	/* printk("buf[4096]=%08x\n",*(unsigned int *)(async->prealloc_buf+4096)); */
+ 
+ 	comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, irq_flags);
+ 	if (devpriv->di_mite_chan)
+@@ -520,8 +520,8 @@ static irqreturn_t nidio_interrupt(int irq, void *d)
+ #ifdef MITE_DEBUG
+ 	mite_print_chsr(m_status);
+ #endif
+-	//printk("mite_bytes_transferred: %d\n",mite_bytes_transferred(mite,DI_DMA_CHAN));
+-	//mite_dump_regs(mite);
++	/* printk("mite_bytes_transferred: %d\n",mite_bytes_transferred(mite,DI_DMA_CHAN)); */
++	/* mite_dump_regs(mite); */
+ 	if (m_status & CHSR_INT) {
+ 		if (m_status & CHSR_LINKC) {
+ 			writel(CHOR_CLRLC,
+@@ -552,7 +552,7 @@ static irqreturn_t nidio_interrupt(int irq, void *d)
+ 		flags &= IntEn;
+ 
+ 		if (flags & TransferReady) {
+-			//DPRINTK("TransferReady\n");
++			/* DPRINTK("TransferReady\n"); */
+ 			while (flags & TransferReady) {
+ 				work++;
+ 				if (work > 100) {
+@@ -569,14 +569,14 @@ static irqreturn_t nidio_interrupt(int irq, void *d)
+ 				data2 = (AuxData & 0xffff0000) >> 16;
+ 				comedi_buf_put(async, data1);
+ 				comedi_buf_put(async, data2);
+-				//DPRINTK("read:%d, %d\n",data1,data2);
++				/* DPRINTK("read:%d, %d\n",data1,data2); */
+ 				flags = readb(devpriv->mite->daq_io_addr +
+ 					Group_1_Flags);
+ 			}
+-			//DPRINTK("buf_int_count: %d\n",async->buf_int_count);
+-			//DPRINTK("1) IntEn=%d,flags=%d,status=%d\n",IntEn,flags,status);
+-			//ni_pcidio_print_flags(flags);
+-			//ni_pcidio_print_status(status);
++			/* DPRINTK("buf_int_count: %d\n",async->buf_int_count); */
++			/* DPRINTK("1) IntEn=%d,flags=%d,status=%d\n",IntEn,flags,status); */
++			/* ni_pcidio_print_flags(flags); */
++			/* ni_pcidio_print_status(status); */
+ 			async->events |= COMEDI_CB_BLOCK;
+ 		}
+ 
+@@ -621,10 +621,10 @@ static irqreturn_t nidio_interrupt(int irq, void *d)
+ 		flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags);
+ 		status = readb(devpriv->mite->daq_io_addr +
+ 			Interrupt_And_Window_Status);
+-		//DPRINTK("loop end: IntEn=0x%02x,flags=0x%02x,status=0x%02x\n",
+-		//      IntEn,flags,status);
+-		//ni_pcidio_print_flags(flags);
+-		//ni_pcidio_print_status(status);
++		/* DPRINTK("loop end: IntEn=0x%02x,flags=0x%02x,status=0x%02x\n", */
++		/* IntEn,flags,status); */
++		/* ni_pcidio_print_flags(flags); */
++		/* ni_pcidio_print_status(status); */
+ 	}
+ 
+       out:
+@@ -963,7 +963,7 @@ static int ni_pcidio_cmd(struct comedi_device * dev, struct comedi_subdevice * s
+ 
+ 	/* clear and enable interrupts */
+ 	writeb(0xff, devpriv->mite->daq_io_addr + Group_1_First_Clear);
+-	//writeb(ClearExpired,devpriv->mite->daq_io_addr+Group_1_Second_Clear);
++	/* writeb(ClearExpired,devpriv->mite->daq_io_addr+Group_1_Second_Clear); */
+ 
+ 	writeb(IntEn, devpriv->mite->daq_io_addr + Interrupt_Control);
+ 	writeb(0x03,
+@@ -971,7 +971,7 @@ static int ni_pcidio_cmd(struct comedi_device * dev, struct comedi_subdevice * s
+ 
+ 	if (cmd->stop_src == TRIG_NONE) {
+ 		devpriv->OpModeBits = DataLatching(0) | RunMode(7);
+-	} else {		// TRIG_TIMER
++	} else {		/* TRIG_TIMER */
+ 		devpriv->OpModeBits = Numbered | RunMode(7);
+ 	}
+ 	if (cmd->start_src == TRIG_NOW) {

commit 68c3dbff9fc9f25872408d0e95980d41733d48d0
+Author: Bill Pemberton 
+Date:   Wed Apr 22 21:11:49 2009 -0400
+
+    Staging: comedi: fix the way structs are initialized.
+    
+    Change from the foo: bar format to the .foo = bar format.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c
+index e8206a18dee9..2e181f01d39d 100644
+--- a/drivers/staging/comedi/drivers/8255.c
++++ b/drivers/staging/comedi/drivers/8255.c
+@@ -108,10 +108,10 @@ struct subdev_8255_struct {
+ static int dev_8255_attach(struct comedi_device *dev, struct comedi_devconfig * it);
+ static int dev_8255_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_8255 = {
+-      driver_name:"8255",
+-      module:THIS_MODULE,
+-      attach:dev_8255_attach,
+-      detach:dev_8255_detach,
++	.driver_name = "8255",
++	.module = THIS_MODULE,
++	.attach = dev_8255_attach,
++	.detach = dev_8255_detach,
+ };
+ 
+ COMEDI_INITCLEANUP(driver_8255);
+diff --git a/drivers/staging/comedi/drivers/acl7225b.c b/drivers/staging/comedi/drivers/acl7225b.c
+index 067ad7523d9d..5b986aa7398b 100644
+--- a/drivers/staging/comedi/drivers/acl7225b.c
++++ b/drivers/staging/comedi/drivers/acl7225b.c
+@@ -39,13 +39,13 @@ static const struct boardtype boardtypes[] = {
+ #define this_board ((const struct boardtype *)dev->board_ptr)
+ 
+ static struct comedi_driver driver_acl7225b = {
+-      driver_name:"acl7225b",
+-      module:THIS_MODULE,
+-      attach:acl7225b_attach,
+-      detach:acl7225b_detach,
+-      board_name:&boardtypes[0].name,
+-      num_names:n_boardtypes,
+-      offset:sizeof(struct boardtype),
++	.driver_name = "acl7225b",
++	.module = THIS_MODULE,
++	.attach = acl7225b_attach,
++	.detach = acl7225b_detach,
++	.board_name = &boardtypes[0].name,
++	.num_names = n_boardtypes,
++	.offset = sizeof(struct boardtype),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_acl7225b);
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+index a6c3530674df..58d7bf1654c8 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+@@ -901,7 +901,7 @@ static const struct addi_board boardtypes[] = {
+ 		NULL},
+ #endif
+ #ifdef CONFIG_APCI_3300
+-	/* Begin JK 20.10.2004: APCI-3300 integration */
++	/* Begin JK	.20.10.2004 = APCI-3300 integration */
+ 	{"apci3300",
+ 			APCI3200_BOARD_VENDOR_ID,
+ 			0x3007,
+@@ -2528,13 +2528,13 @@ static const struct addi_board boardtypes[] = {
+ #define n_boardtypes (sizeof(boardtypes)/sizeof(struct addi_board))
+ 
+ struct comedi_driver driver_addi = {
+-      driver_name:"addi_common",
+-      module:THIS_MODULE,
+-      attach:i_ADDI_Attach,
+-      detach:i_ADDI_Detach,
+-      num_names:n_boardtypes,
+-      board_name:&boardtypes[0].pc_DriverName,
+-      offset:sizeof(struct addi_board),
++	.driver_name = "addi_common",
++	.module = THIS_MODULE,
++	.attach = i_ADDI_Attach,
++	.detach = i_ADDI_Detach,
++	.num_names = n_boardtypes,
++	.board_name = &boardtypes[0].pc_DriverName,
++	.offset = sizeof(struct addi_board),
+ };
+ 
+ COMEDI_PCI_INITCLEANUP(driver_addi, addi_apci_tbl);
+diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c
+index ad96114e359d..7cd6043ed49f 100644
+--- a/drivers/staging/comedi/drivers/adl_pci6208.c
++++ b/drivers/staging/comedi/drivers/adl_pci6208.c
+@@ -66,22 +66,22 @@ struct pci6208_board {
+ 
+ static const struct pci6208_board pci6208_boards[] = {
+ 	/*{
+-	   name :  "pci6208v",
+-	   dev_id       :  0x6208,      // not sure
+-	   ao_chans:  8
+-	   // ,  ao_bits :  16
++	.name = "pci6208v",
++	.dev_id = 0x6208,      // not sure
++	.ao_chans = 8
++	   // ,	.ao_bits = 16
+ 	   },
+ 	   {
+-	   name :  "pci6216v",
+-	   dev_id       :  0x6208,      // not sure
+-	   ao_chans:  16
+-	   // ,  ao_bits :  16
++	.name = "pci6216v",
++	.dev_id = 0x6208,      // not sure
++	.ao_chans = 16
++	   // ,	.ao_bits = 16
+ 	   }, */
+ 	{
+-	      name:	"pci6208a",
+-	      dev_id:	0x6208,
+-	      ao_chans:8
+-			/* ,     ao_bits :  16 */
++	.name = "pci6208a",
++	.dev_id = 0x6208,
++	.ao_chans = 8
++			/* ,	.ao_bits = 16 */
+ 		}
+ };
+ 
+@@ -114,10 +114,10 @@ static int pci6208_detach(struct comedi_device *dev);
+ 	(sizeof(pci6208_boards) / sizeof(struct pci6208_board))
+ 
+ static struct comedi_driver driver_pci6208 = {
+-      driver_name:PCI6208_DRIVER_NAME,
+-      module:THIS_MODULE,
+-      attach:pci6208_attach,
+-      detach:pci6208_detach,
++	.driver_name = PCI6208_DRIVER_NAME,
++	.module = THIS_MODULE,
++	.attach = pci6208_attach,
++	.detach = pci6208_detach,
+ };
+ 
+ COMEDI_PCI_INITCLEANUP(driver_pci6208, pci6208_pci_table);
+diff --git a/drivers/staging/comedi/drivers/adl_pci7296.c b/drivers/staging/comedi/drivers/adl_pci7296.c
+index 72b3f4614d06..d2f23a88608d 100644
+--- a/drivers/staging/comedi/drivers/adl_pci7296.c
++++ b/drivers/staging/comedi/drivers/adl_pci7296.c
+@@ -67,10 +67,10 @@ struct adl_pci7296_private {
+ static int adl_pci7296_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int adl_pci7296_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_adl_pci7296 = {
+-      driver_name:"adl_pci7296",
+-      module:THIS_MODULE,
+-      attach:adl_pci7296_attach,
+-      detach:adl_pci7296_detach,
++	.driver_name = "adl_pci7296",
++	.module = THIS_MODULE,
++	.attach = adl_pci7296_attach,
++	.detach = adl_pci7296_detach,
+ };
+ 
+ static int adl_pci7296_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+diff --git a/drivers/staging/comedi/drivers/adl_pci7432.c b/drivers/staging/comedi/drivers/adl_pci7432.c
+index e20ec2f9904e..78becbdd17a8 100644
+--- a/drivers/staging/comedi/drivers/adl_pci7432.c
++++ b/drivers/staging/comedi/drivers/adl_pci7432.c
+@@ -61,10 +61,10 @@ struct adl_pci7432_private {
+ static int adl_pci7432_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int adl_pci7432_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_adl_pci7432 = {
+-      driver_name:"adl_pci7432",
+-      module:THIS_MODULE,
+-      attach:adl_pci7432_attach,
+-      detach:adl_pci7432_detach,
++	.driver_name = "adl_pci7432",
++	.module = THIS_MODULE,
++	.attach = adl_pci7432_attach,
++	.detach = adl_pci7432_detach,
+ };
+ 
+ /* Digital IO */
+diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c
+index 61b8cba40d0c..2fe577a973af 100644
+--- a/drivers/staging/comedi/drivers/adl_pci8164.c
++++ b/drivers/staging/comedi/drivers/adl_pci8164.c
+@@ -73,10 +73,10 @@ struct adl_pci8164_private {
+ static int adl_pci8164_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int adl_pci8164_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_adl_pci8164 = {
+-      driver_name:"adl_pci8164",
+-      module:THIS_MODULE,
+-      attach:adl_pci8164_attach,
+-      detach:adl_pci8164_detach,
++	.driver_name = "adl_pci8164",
++	.module = THIS_MODULE,
++	.attach = adl_pci8164_attach,
++	.detach = adl_pci8164_detach,
+ };
+ 
+ static int adl_pci8164_insn_read_msts(struct comedi_device *dev, struct comedi_subdevice *s,
+diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
+index 6dc9435997ca..288ad8151dd1 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9111.c
++++ b/drivers/staging/comedi/drivers/adl_pci9111.c
+@@ -309,27 +309,27 @@ struct pci9111_board {
+ 
+ static const struct pci9111_board pci9111_boards[] = {
+ 	{
+-	      name:	"pci9111_hr",
+-	      device_id:PCI9111_HR_DEVICE_ID,
+-	      ai_channel_nbr:PCI9111_AI_CHANNEL_NBR,
+-	      ao_channel_nbr:PCI9111_AO_CHANNEL_NBR,
+-	      ai_resolution:PCI9111_HR_AI_RESOLUTION,
+-	      ai_resolution_mask:PCI9111_HR_AI_RESOLUTION_MASK,
+-	      ao_resolution:PCI9111_AO_RESOLUTION,
+-	      ao_resolution_mask:PCI9111_AO_RESOLUTION_MASK,
+-	      ai_range_list:&pci9111_hr_ai_range,
+-	      ao_range_list:&range_bipolar10,
+-      ai_acquisition_period_min_ns:PCI9111_AI_ACQUISITION_PERIOD_MIN_NS}
++	.name = "pci9111_hr",
++	.device_id = PCI9111_HR_DEVICE_ID,
++	.ai_channel_nbr = PCI9111_AI_CHANNEL_NBR,
++	.ao_channel_nbr = PCI9111_AO_CHANNEL_NBR,
++	.ai_resolution = PCI9111_HR_AI_RESOLUTION,
++	.ai_resolution_mask = PCI9111_HR_AI_RESOLUTION_MASK,
++	.ao_resolution = PCI9111_AO_RESOLUTION,
++	.ao_resolution_mask = PCI9111_AO_RESOLUTION_MASK,
++	.ai_range_list = &pci9111_hr_ai_range,
++	.ao_range_list = &range_bipolar10,
++	.ai_acquisition_period_min_ns = PCI9111_AI_ACQUISITION_PERIOD_MIN_NS}
+ };
+ 
+ #define pci9111_board_nbr \
+   (sizeof(pci9111_boards)/sizeof(struct pci9111_board))
+ 
+ static struct comedi_driver pci9111_driver = {
+-      driver_name:PCI9111_DRIVER_NAME,
+-      module:THIS_MODULE,
+-      attach:pci9111_attach,
+-      detach:pci9111_detach,
++	.driver_name = PCI9111_DRIVER_NAME,
++	.module = THIS_MODULE,
++	.attach = pci9111_attach,
++	.detach = pci9111_detach,
+ };
+ 
+ COMEDI_PCI_INITCLEANUP(pci9111_driver, pci9111_pci_table);
+diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
+index a1e669cf4cc6..59b6498ded60 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9118.c
++++ b/drivers/staging/comedi/drivers/adl_pci9118.c
+@@ -231,13 +231,13 @@ static const struct boardtype boardtypes[] = {
+ #define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype))
+ 
+ static struct comedi_driver driver_pci9118 = {
+-      driver_name:"adl_pci9118",
+-      module:THIS_MODULE,
+-      attach:pci9118_attach,
+-      detach:pci9118_detach,
+-      num_names:n_boardtypes,
+-      board_name:&boardtypes[0].name,
+-      offset:sizeof(struct boardtype),
++	.driver_name = "adl_pci9118",
++	.module = THIS_MODULE,
++	.attach = pci9118_attach,
++	.detach = pci9118_detach,
++	.num_names = n_boardtypes,
++	.board_name = &boardtypes[0].name,
++	.offset = sizeof(struct boardtype),
+ };
+ 
+ COMEDI_PCI_INITCLEANUP(driver_pci9118, pci9118_pci_table);
+diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c
+index 8fe4c0b0e8f4..9921702bf399 100644
+--- a/drivers/staging/comedi/drivers/adq12b.c
++++ b/drivers/staging/comedi/drivers/adq12b.c
+@@ -127,20 +127,20 @@ struct adq12b_board {
+ 
+ static const struct adq12b_board adq12b_boards[] = {
+         {
+-        name:           "adq12b",
+-        ai_se_chans:    16,
+-        ai_diff_chans:  8,
+-        ai_bits:        12,
+-        di_chans:       5,
+-        do_chans:       8
++	.name = "adq12b",
++	.ai_se_chans = 16,
++	.ai_diff_chans = 8,
++	.ai_bits = 12,
++	.di_chans = 5,
++	.do_chans = 8
+         }
+ // potentially, more adq-based deviced will be added
+ /*,
+-        name:           "adq12b",
+-        ai_chans:       16,  // this is just for reference, hardcoded again later
+-        ai_bits:        12,
+-        di_chans:       8,
+-        do_chans:       5
++	.name = "adq12b",
++	.ai_chans = 16,  // this is just for reference, hardcoded again later
++	.ai_bits = 12,
++	.di_chans = 8,
++	.do_chans = 5
+         }*/
+ };
+ 
+diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
+index 38be3f8be078..c617ec39dabe 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1723.c
++++ b/drivers/staging/comedi/drivers/adv_pci1723.c
+@@ -116,15 +116,15 @@ struct pci1723_board {
+ 
+ static const struct pci1723_board boardtypes[] = {
+ 	{
+-	      name:	"pci1723",
+-	      vendor_id:ADVANTECH_VENDOR,
+-	      device_id:0x1723,
+-	      iorange:	IORANGE_1723,
+-	      cardtype:TYPE_PCI1723,
+-	      n_aochan:8,
+-	      n_diochan:16,
+-	      ao_maxdata:0xffff,
+-	      rangelist_ao:&range_pci1723,
++	.name = "pci1723",
++	.vendor_id = ADVANTECH_VENDOR,
++	.device_id = 0x1723,
++	.iorange = IORANGE_1723,
++	.cardtype = TYPE_PCI1723,
++	.n_aochan = 8,
++	.n_diochan = 16,
++	.ao_maxdata = 0xffff,
++	.rangelist_ao = &range_pci1723,
+ 		},
+ };
+ 
+@@ -149,10 +149,10 @@ static int pci1723_detach(struct comedi_device *dev);
+ #define n_boardtypes (sizeof(boardtypes)/sizeof(struct pci1723_board))
+ 
+ static struct comedi_driver driver_pci1723 = {
+-      driver_name:"adv_pci1723",
+-      module:THIS_MODULE,
+-      attach:pci1723_attach,
+-      detach:pci1723_detach,
++	.driver_name = "adv_pci1723",
++	.module = THIS_MODULE,
++	.attach = pci1723_attach,
++	.detach = pci1723_detach,
+ };
+ 
+ /* this structure is for data unique to this hardware driver. */
+diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
+index afa2a4d3816d..7d66f2ba6b70 100644
+--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
++++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
+@@ -323,10 +323,10 @@ static const struct dio_boardtype boardtypes[] = {
+ #define n_boardtypes (sizeof(boardtypes)/sizeof(struct dio_boardtype))
+ 
+ static struct comedi_driver driver_pci_dio = {
+-      driver_name:"adv_pci_dio",
+-      module:THIS_MODULE,
+-      attach:pci_dio_attach,
+-      detach:pci_dio_detach
++	.driver_name = "adv_pci_dio",
++	.module = THIS_MODULE,
++	.attach = pci_dio_attach,
++	.detach = pci_dio_detach
+ };
+ 
+ struct pci_dio_private {
+diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c
+index ce4e8e49ae8e..e77d33797494 100644
+--- a/drivers/staging/comedi/drivers/aio_aio12_8.c
++++ b/drivers/staging/comedi/drivers/aio_aio12_8.c
+@@ -77,7 +77,7 @@ struct aio12_8_boardtype {
+ 
+ static const struct aio12_8_boardtype board_types[] = {
+ 	{
+-      name:	"aio_aio12_8"},
++	.name = "aio_aio12_8"},
+ };
+ 
+ #define	thisboard	((const struct aio12_8_boardtype  *) dev->board_ptr)
+@@ -214,13 +214,13 @@ static int aio_aio12_8_detach(struct comedi_device *dev)
+ }
+ 
+ static struct comedi_driver driver_aio_aio12_8 = {
+-      driver_name:"aio_aio12_8",
+-      module:THIS_MODULE,
+-      attach:aio_aio12_8_attach,
+-      detach:aio_aio12_8_detach,
+-      board_name:&board_types[0].name,
+-      num_names:1,
+-      offset:sizeof(struct aio12_8_boardtype),
++	.driver_name = "aio_aio12_8",
++	.module = THIS_MODULE,
++	.attach = aio_aio12_8_attach,
++	.detach = aio_aio12_8_detach,
++	.board_name = &board_types[0].name,
++	.num_names = 1,
++	.offset = sizeof(struct aio12_8_boardtype),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_aio_aio12_8);
+diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c
+index 8374f65a8bec..764cac2fd7d2 100644
+--- a/drivers/staging/comedi/drivers/aio_iiro_16.c
++++ b/drivers/staging/comedi/drivers/aio_iiro_16.c
+@@ -52,9 +52,9 @@ struct aio_iiro_16_board {
+ 
+ static const struct aio_iiro_16_board aio_iiro_16_boards[] = {
+ 	{
+-	      name:	"aio_iiro_16",
+-	      di:	16,
+-      do_:	16},
++	.name = "aio_iiro_16",
++	.di = 16,
++	.do_ = 16},
+ };
+ 
+ #define	thisboard	((const struct aio_iiro_16_board *) dev->board_ptr)
+@@ -72,13 +72,13 @@ static int aio_iiro_16_attach(struct comedi_device *dev, struct comedi_devconfig
+ static int aio_iiro_16_detach(struct comedi_device *dev);
+ 
+ static struct comedi_driver driver_aio_iiro_16 = {
+-      driver_name:"aio_iiro_16",
+-      module:THIS_MODULE,
+-      attach:aio_iiro_16_attach,
+-      detach:aio_iiro_16_detach,
+-      board_name:&aio_iiro_16_boards[0].name,
+-      offset:sizeof(struct aio_iiro_16_board),
+-      num_names:sizeof(aio_iiro_16_boards) / sizeof(struct aio_iiro_16_board),
++	.driver_name = "aio_iiro_16",
++	.module = THIS_MODULE,
++	.attach = aio_iiro_16_attach,
++	.detach = aio_iiro_16_detach,
++	.board_name = &aio_iiro_16_boards[0].name,
++	.offset = sizeof(struct aio_iiro_16_board),
++	.num_names = sizeof(aio_iiro_16_boards) / sizeof(struct aio_iiro_16_board),
+ };
+ 
+ static int aio_iiro_16_dio_insn_bits_read(struct comedi_device *dev,
+diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
+index 7c323e242835..582d6a2cfef6 100644
+--- a/drivers/staging/comedi/drivers/amplc_dio200.c
++++ b/drivers/staging/comedi/drivers/amplc_dio200.c
+@@ -290,59 +290,59 @@ struct dio200_board {
+ 
+ static const struct dio200_board dio200_boards[] = {
+ 	{
+-	      name:	"pc212e",
+-	      bustype:	isa_bustype,
+-	      model:	pc212e_model,
+-	      layout:	pc212_layout,
++	.name = "pc212e",
++	.bustype = isa_bustype,
++	.model = pc212e_model,
++	.layout = pc212_layout,
+ 		},
+ 	{
+-	      name:	"pc214e",
+-	      bustype:	isa_bustype,
+-	      model:	pc214e_model,
+-	      layout:	pc214_layout,
++	.name = "pc214e",
++	.bustype = isa_bustype,
++	.model = pc214e_model,
++	.layout = pc214_layout,
+ 		},
+ 	{
+-	      name:	"pc215e",
+-	      bustype:	isa_bustype,
+-	      model:	pc215e_model,
+-	      layout:	pc215_layout,
++	.name = "pc215e",
++	.bustype = isa_bustype,
++	.model = pc215e_model,
++	.layout = pc215_layout,
+ 		},
+ #ifdef CONFIG_COMEDI_PCI
+ 	{
+-	      name:	"pci215",
+-	      devid:	PCI_DEVICE_ID_AMPLICON_PCI215,
+-	      bustype:	pci_bustype,
+-	      model:	pci215_model,
+-	      layout:	pc215_layout,
++	.name = "pci215",
++	.devid = PCI_DEVICE_ID_AMPLICON_PCI215,
++	.bustype = pci_bustype,
++	.model = pci215_model,
++	.layout = pc215_layout,
+ 		},
+ #endif
+ 	{
+-	      name:	"pc218e",
+-	      bustype:	isa_bustype,
+-	      model:	pc218e_model,
+-	      layout:	pc218_layout,
++	.name = "pc218e",
++	.bustype = isa_bustype,
++	.model = pc218e_model,
++	.layout = pc218_layout,
+ 		},
+ 	{
+-	      name:	"pc272e",
+-	      bustype:	isa_bustype,
+-	      model:	pc272e_model,
+-	      layout:	pc272_layout,
++	.name = "pc272e",
++	.bustype = isa_bustype,
++	.model = pc272e_model,
++	.layout = pc272_layout,
+ 		},
+ #ifdef CONFIG_COMEDI_PCI
+ 	{
+-	      name:	"pci272",
+-	      devid:	PCI_DEVICE_ID_AMPLICON_PCI272,
+-	      bustype:	pci_bustype,
+-	      model:	pci272_model,
+-	      layout:	pc272_layout,
++	.name = "pci272",
++	.devid = PCI_DEVICE_ID_AMPLICON_PCI272,
++	.bustype = pci_bustype,
++	.model = pci272_model,
++	.layout = pc272_layout,
+ 		},
+ #endif
+ #ifdef CONFIG_COMEDI_PCI
+ 	{
+-	      name:	DIO200_DRIVER_NAME,
+-	      devid:	PCI_DEVICE_ID_INVALID,
+-	      bustype:	pci_bustype,
+-	      model:	anypci_model,	/* wildcard */
++	.name = DIO200_DRIVER_NAME,
++	.devid = PCI_DEVICE_ID_INVALID,
++	.bustype = pci_bustype,
++	.model = anypci_model,	/* wildcard */
+ 		},
+ #endif
+ };
+@@ -367,50 +367,50 @@ struct dio200_layout_struct {
+ 
+ static const struct dio200_layout_struct dio200_layouts[] = {
+ 	[pc212_layout] = {
+-	      n_subdevs:6,
+-	      sdtype:	{sd_8255, sd_8254, sd_8254, sd_8254,
++	.n_subdevs = 6,
++	.sdtype = {sd_8255, sd_8254, sd_8254, sd_8254,
+ 					sd_8254,
+ 				sd_intr},
+-	      sdinfo:	{0x00, 0x08, 0x0C, 0x10, 0x14,
++	.sdinfo = {0x00, 0x08, 0x0C, 0x10, 0x14,
+ 				0x3F},
+-	      has_int_sce:1,
+-	      has_clk_gat_sce:1,
++	.has_int_sce = 1,
++	.has_clk_gat_sce = 1,
+ 		},
+ 	[pc214_layout] = {
+-	      n_subdevs:4,
+-	      sdtype:	{sd_8255, sd_8255, sd_8254,
++	.n_subdevs = 4,
++	.sdtype = {sd_8255, sd_8255, sd_8254,
+ 				sd_intr},
+-	      sdinfo:	{0x00, 0x08, 0x10, 0x01},
+-	      has_int_sce:0,
+-	      has_clk_gat_sce:0,
++	.sdinfo = {0x00, 0x08, 0x10, 0x01},
++	.has_int_sce = 0,
++	.has_clk_gat_sce = 0,
+ 		},
+ 	[pc215_layout] = {
+-	      n_subdevs:5,
+-	      sdtype:	{sd_8255, sd_8255, sd_8254,
++	.n_subdevs = 5,
++	.sdtype = {sd_8255, sd_8255, sd_8254,
+ 					sd_8254,
+ 				sd_intr},
+-	      sdinfo:	{0x00, 0x08, 0x10, 0x14, 0x3F},
+-	      has_int_sce:1,
+-	      has_clk_gat_sce:1,
++	.sdinfo = {0x00, 0x08, 0x10, 0x14, 0x3F},
++	.has_int_sce = 1,
++	.has_clk_gat_sce = 1,
+ 		},
+ 	[pc218_layout] = {
+-	      n_subdevs:7,
+-	      sdtype:	{sd_8254, sd_8254, sd_8255, sd_8254,
++	.n_subdevs = 7,
++	.sdtype = {sd_8254, sd_8254, sd_8255, sd_8254,
+ 					sd_8254,
+ 				sd_intr},
+-	      sdinfo:	{0x00, 0x04, 0x08, 0x0C, 0x10,
++	.sdinfo = {0x00, 0x04, 0x08, 0x0C, 0x10,
+ 					0x14,
+ 				0x3F},
+-	      has_int_sce:1,
+-	      has_clk_gat_sce:1,
++	.has_int_sce = 1,
++	.has_clk_gat_sce = 1,
+ 		},
+ 	[pc272_layout] = {
+-	      n_subdevs:4,
+-	      sdtype:	{sd_8255, sd_8255, sd_8255,
++	.n_subdevs = 4,
++	.sdtype = {sd_8255, sd_8255, sd_8255,
+ 				sd_intr},
+-	      sdinfo:	{0x00, 0x08, 0x10, 0x3F},
+-	      has_int_sce:1,
+-	      has_clk_gat_sce:0,
++	.sdinfo = {0x00, 0x08, 0x10, 0x3F},
++	.has_int_sce = 1,
++	.has_clk_gat_sce = 0,
+ 		},
+ };
+ 
+@@ -478,13 +478,13 @@ struct dio200_subdev_intr {
+ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int dio200_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_amplc_dio200 = {
+-      driver_name:DIO200_DRIVER_NAME,
+-      module:THIS_MODULE,
+-      attach:dio200_attach,
+-      detach:dio200_detach,
+-      board_name:&dio200_boards[0].name,
+-      offset:sizeof(struct dio200_board),
+-      num_names:sizeof(dio200_boards) / sizeof(struct dio200_board),
++	.driver_name = DIO200_DRIVER_NAME,
++	.module = THIS_MODULE,
++	.attach = dio200_attach,
++	.detach = dio200_detach,
++	.board_name = &dio200_boards[0].name,
++	.offset = sizeof(struct dio200_board),
++	.num_names = sizeof(dio200_boards) / sizeof(struct dio200_board),
+ };
+ 
+ #ifdef CONFIG_COMEDI_PCI
+diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
+index 8454f6d6517e..57e57c670ec8 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc236.c
++++ b/drivers/staging/comedi/drivers/amplc_pc236.c
+@@ -107,27 +107,27 @@ struct pc236_board {
+ };
+ static const struct pc236_board pc236_boards[] = {
+ 	{
+-	      name:	"pc36at",
+-	      fancy_name:"PC36AT",
+-	      bustype:	isa_bustype,
+-	      model:	pc36at_model,
++	.name = "pc36at",
++	.fancy_name = "PC36AT",
++	.bustype = isa_bustype,
++	.model = pc36at_model,
+ 		},
+ #ifdef CONFIG_COMEDI_PCI
+ 	{
+-	      name:	"pci236",
+-	      fancy_name:"PCI236",
+-	      devid:	PCI_DEVICE_ID_AMPLICON_PCI236,
+-	      bustype:	pci_bustype,
+-	      model:	pci236_model,
++	.name = "pci236",
++	.fancy_name = "PCI236",
++	.devid = PCI_DEVICE_ID_AMPLICON_PCI236,
++	.bustype = pci_bustype,
++	.model = pci236_model,
+ 		},
+ #endif
+ #ifdef CONFIG_COMEDI_PCI
+ 	{
+-	      name:	PC236_DRIVER_NAME,
+-	      fancy_name:PC236_DRIVER_NAME,
+-	      devid:	PCI_DEVICE_ID_INVALID,
+-	      bustype:	pci_bustype,
+-	      model:	anypci_model,	/* wildcard */
++	.name = PC236_DRIVER_NAME,
++	.fancy_name = PC236_DRIVER_NAME,
++	.devid = PCI_DEVICE_ID_INVALID,
++	.bustype = pci_bustype,
++	.model = anypci_model,	/* wildcard */
+ 		},
+ #endif
+ };
+@@ -170,13 +170,13 @@ struct pc236_private {
+ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int pc236_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_amplc_pc236 = {
+-      driver_name:PC236_DRIVER_NAME,
+-      module:THIS_MODULE,
+-      attach:pc236_attach,
+-      detach:pc236_detach,
+-      board_name:&pc236_boards[0].name,
+-      offset:sizeof(struct pc236_board),
+-      num_names:sizeof(pc236_boards) / sizeof(struct pc236_board),
++	.driver_name = PC236_DRIVER_NAME,
++	.module = THIS_MODULE,
++	.attach = pc236_attach,
++	.detach = pc236_detach,
++	.board_name = &pc236_boards[0].name,
++	.offset = sizeof(struct pc236_board),
++	.num_names = sizeof(pc236_boards) / sizeof(struct pc236_board),
+ };
+ 
+ #ifdef CONFIG_COMEDI_PCI
+diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
+index 8a94360fe2db..1d516b1f1591 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc263.c
++++ b/drivers/staging/comedi/drivers/amplc_pc263.c
+@@ -74,27 +74,27 @@ struct pc263_board {
+ };
+ static const struct pc263_board pc263_boards[] = {
+ 	{
+-	      name:	"pc263",
+-	      fancy_name:"PC263",
+-	      bustype:	isa_bustype,
+-	      model:	pc263_model,
++	.name = "pc263",
++	.fancy_name = "PC263",
++	.bustype = isa_bustype,
++	.model = pc263_model,
+ 		},
+ #ifdef CONFIG_COMEDI_PCI
+ 	{
+-	      name:	"pci263",
+-	      fancy_name:"PCI263",
+-	      devid:	PCI_DEVICE_ID_AMPLICON_PCI263,
+-	      bustype:	pci_bustype,
+-	      model:	pci263_model,
++	.name = "pci263",
++	.fancy_name = "PCI263",
++	.devid = PCI_DEVICE_ID_AMPLICON_PCI263,
++	.bustype = pci_bustype,
++	.model = pci263_model,
+ 		},
+ #endif
+ #ifdef CONFIG_COMEDI_PCI
+ 	{
+-	      name:	PC263_DRIVER_NAME,
+-	      fancy_name:PC263_DRIVER_NAME,
+-	      devid:	PCI_DEVICE_ID_INVALID,
+-	      bustype:	pci_bustype,
+-	      model:	anypci_model,	/* wildcard */
++	.name = PC263_DRIVER_NAME,
++	.fancy_name = PC263_DRIVER_NAME,
++	.devid = PCI_DEVICE_ID_INVALID,
++	.bustype = pci_bustype,
++	.model = anypci_model,	/* wildcard */
+ 		},
+ #endif
+ };
+@@ -135,13 +135,13 @@ struct pc263_private {
+ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int pc263_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_amplc_pc263 = {
+-      driver_name:PC263_DRIVER_NAME,
+-      module:THIS_MODULE,
+-      attach:pc263_attach,
+-      detach:pc263_detach,
+-      board_name:&pc263_boards[0].name,
+-      offset:sizeof(struct pc263_board),
+-      num_names:sizeof(pc263_boards) / sizeof(struct pc263_board),
++	.driver_name = PC263_DRIVER_NAME,
++	.module = THIS_MODULE,
++	.attach = pc263_attach,
++	.detach = pc263_detach,
++	.board_name = &pc263_boards[0].name,
++	.offset = sizeof(struct pc263_board),
++	.num_names = sizeof(pc263_boards) / sizeof(struct pc263_board),
+ };
+ 
+ static int pc263_request_region(unsigned minor, unsigned long from,
+diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
+index 7cc594b38070..19e4428c3380 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci224.c
++++ b/drivers/staging/comedi/drivers/amplc_pci224.c
+@@ -358,23 +358,23 @@ struct pci224_board {
+ 
+ static const struct pci224_board pci224_boards[] = {
+ 	{
+-	      name:	"pci224",
+-	      devid: PCI_DEVICE_ID_AMPLICON_PCI224,
+-	      model:	pci224_model,
+-	      ao_chans:16,
+-	      ao_bits:	12,
++	.name = "pci224",
++	.devid = PCI_DEVICE_ID_AMPLICON_PCI224,
++	.model = pci224_model,
++	.ao_chans = 16,
++	.ao_bits = 12,
+ 		},
+ 	{
+-	      name:	"pci234",
+-	      devid: PCI_DEVICE_ID_AMPLICON_PCI234,
+-	      model:	pci234_model,
+-	      ao_chans:4,
+-	      ao_bits:	16,
++	.name = "pci234",
++	.devid = PCI_DEVICE_ID_AMPLICON_PCI234,
++	.model = pci234_model,
++	.ao_chans = 4,
++	.ao_bits = 16,
+ 		},
+ 	{
+-	      name:	DRIVER_NAME,
+-	      devid: PCI_DEVICE_ID_INVALID,
+-	      model:	any_model,	/* wildcard */
++	.name = DRIVER_NAME,
++	.devid = PCI_DEVICE_ID_INVALID,
++	.model = any_model,	/* wildcard */
+ 		},
+ };
+ 
+@@ -431,13 +431,13 @@ struct pci224_private {
+ static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int pci224_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_amplc_pci224 = {
+-      driver_name:DRIVER_NAME,
+-      module:THIS_MODULE,
+-      attach:pci224_attach,
+-      detach:pci224_detach,
+-      board_name:&pci224_boards[0].name,
+-      offset:sizeof(struct pci224_board),
+-      num_names:sizeof(pci224_boards) / sizeof(struct pci224_board),
++	.driver_name = DRIVER_NAME,
++	.module = THIS_MODULE,
++	.attach = pci224_attach,
++	.detach = pci224_detach,
++	.board_name = &pci224_boards[0].name,
++	.offset = sizeof(struct pci224_board),
++	.num_names = sizeof(pci224_boards) / sizeof(struct pci224_board),
+ };
+ 
+ COMEDI_PCI_INITCLEANUP(driver_amplc_pci224, pci224_pci_table);
+diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
+index 570ad457fe55..94f45029a9cf 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci230.c
++++ b/drivers/staging/comedi/drivers/amplc_pci230.c
+@@ -457,46 +457,46 @@ struct pci230_board {
+ };
+ static const struct pci230_board pci230_boards[] = {
+ 	{
+-	      name:	"pci230+",
+-	      id:	PCI_DEVICE_ID_PCI230,
+-	      ai_chans:16,
+-	      ai_bits:	16,
+-	      ao_chans:2,
+-	      ao_bits:	12,
+-	      have_dio:1,
+-	      min_hwver:1,
++	.name = "pci230+",
++	.id = PCI_DEVICE_ID_PCI230,
++	.ai_chans = 16,
++	.ai_bits = 16,
++	.ao_chans = 2,
++	.ao_bits = 12,
++	.have_dio = 1,
++	.min_hwver = 1,
+ 		},
+ 	{
+-	      name:	"pci260+",
+-	      id:	PCI_DEVICE_ID_PCI260,
+-	      ai_chans:16,
+-	      ai_bits:	16,
+-	      ao_chans:0,
+-	      ao_bits:	0,
+-	      have_dio:0,
+-	      min_hwver:1,
++	.name = "pci260+",
++	.id = PCI_DEVICE_ID_PCI260,
++	.ai_chans = 16,
++	.ai_bits = 16,
++	.ao_chans = 0,
++	.ao_bits = 0,
++	.have_dio = 0,
++	.min_hwver = 1,
+ 		},
+ 	{
+-	      name:	"pci230",
+-	      id:	PCI_DEVICE_ID_PCI230,
+-	      ai_chans:16,
+-	      ai_bits:	12,
+-	      ao_chans:2,
+-	      ao_bits:	12,
+-	      have_dio:1,
++	.name = "pci230",
++	.id = PCI_DEVICE_ID_PCI230,
++	.ai_chans = 16,
++	.ai_bits = 12,
++	.ao_chans = 2,
++	.ao_bits = 12,
++	.have_dio = 1,
+ 		},
+ 	{
+-	      name:	"pci260",
+-	      id:	PCI_DEVICE_ID_PCI260,
+-	      ai_chans:16,
+-	      ai_bits:	12,
+-	      ao_chans:0,
+-	      ao_bits:	0,
+-	      have_dio:0,
++	.name = "pci260",
++	.id = PCI_DEVICE_ID_PCI260,
++	.ai_chans = 16,
++	.ai_bits = 12,
++	.ao_chans = 0,
++	.ao_bits = 0,
++	.have_dio = 0,
+ 		},
+ 	{
+-	      name:	"amplc_pci230",	/* Wildcard matches any above */
+-	      id:	PCI_DEVICE_ID_INVALID,
++	.name = "amplc_pci230",	/* Wildcard matches any above */
++	.id = PCI_DEVICE_ID_INVALID,
+ 		},
+ };
+ 
+@@ -606,13 +606,13 @@ static const unsigned char pci230_ao_bipolar[2] = { 0, 1 };
+ static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int pci230_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_amplc_pci230 = {
+-      driver_name:"amplc_pci230",
+-      module:THIS_MODULE,
+-      attach:pci230_attach,
+-      detach:pci230_detach,
+-      board_name:&pci230_boards[0].name,
+-      offset:sizeof(pci230_boards[0]),
+-      num_names:sizeof(pci230_boards) / sizeof(pci230_boards[0]),
++	.driver_name = "amplc_pci230",
++	.module = THIS_MODULE,
++	.attach = pci230_attach,
++	.detach = pci230_detach,
++	.board_name = &pci230_boards[0].name,
++	.offset = sizeof(pci230_boards[0]),
++	.num_names = sizeof(pci230_boards) / sizeof(pci230_boards[0]),
+ };
+ 
+ COMEDI_PCI_INITCLEANUP(driver_amplc_pci230, pci230_pci_table);
+diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c
+index 0c212ecc76ca..b204793040e2 100644
+--- a/drivers/staging/comedi/drivers/c6xdigio.c
++++ b/drivers/staging/comedi/drivers/c6xdigio.c
+@@ -100,10 +100,10 @@ union encvaluetype {
+ static int c6xdigio_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int c6xdigio_detach(struct comedi_device *dev);
+ struct comedi_driver driver_c6xdigio = {
+-      driver_name:"c6xdigio",
+-      module:THIS_MODULE,
+-      attach:c6xdigio_attach,
+-      detach:c6xdigio_detach,
++	.driver_name = "c6xdigio",
++	.module = THIS_MODULE,
++	.attach = c6xdigio_attach,
++	.detach = c6xdigio_detach,
+ };
+ 
+ static void C6X_pwmInit(unsigned long baseAddr)
+diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
+index e476baf7c1d9..3199249a8fc4 100644
+--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
++++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
+@@ -61,19 +61,19 @@ struct das16cs_board {
+ };
+ static const struct das16cs_board das16cs_boards[] = {
+ 	{
+-	      device_id:0x0000,/* unknown */
+-	      name:	"PC-CARD DAS16/16",
+-	      n_ao_chans:0,
++	.device_id = 0x0000,/* unknown */
++	.name = "PC-CARD DAS16/16",
++	.n_ao_chans = 0,
+ 		},
+ 	{
+-	      device_id:0x0039,
+-	      name:	"PC-CARD DAS16/16-AO",
+-	      n_ao_chans:2,
++	.device_id = 0x0039,
++	.name = "PC-CARD DAS16/16-AO",
++	.n_ao_chans = 2,
+ 		},
+ 	{
+-	      device_id:0x4009,
+-	      name:	"PCM-DAS16s/16",
+-	      n_ao_chans:0,
++	.device_id = 0x4009,
++	.name = "PCM-DAS16s/16",
++	.n_ao_chans = 0,
+ 		},
+ };
+ 
+@@ -92,10 +92,10 @@ struct das16cs_private {
+ static int das16cs_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int das16cs_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_das16cs = {
+-      driver_name:"cb_das16_cs",
+-      module:THIS_MODULE,
+-      attach:das16cs_attach,
+-      detach:das16cs_detach,
++	.driver_name = "cb_das16_cs",
++	.module = THIS_MODULE,
++	.attach = das16cs_attach,
++	.detach = das16cs_detach,
+ };
+ 
+ static struct pcmcia_device *cur_dev = NULL;
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
+index a7b75808bda5..112480c969ab 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas.c
+@@ -260,118 +260,118 @@ struct cb_pcidas_board {
+ 
+ static const struct cb_pcidas_board cb_pcidas_boards[] = {
+ 	{
+-	      name:	"pci-das1602/16",
+-	      device_id:0x1,
+-	      ai_se_chans:16,
+-	      ai_diff_chans:8,
+-	      ai_bits:	16,
+-	      ai_speed:5000,
+-	      ao_nchan:2,
+-	      has_ao_fifo:1,
+-	      ao_scan_speed:10000,
+-	      fifo_size:512,
+-	      ranges:	&cb_pcidas_ranges,
+-	      trimpot:	AD8402,
+-	      has_dac08:1,
++	.name = "pci-das1602/16",
++	.device_id = 0x1,
++	.ai_se_chans = 16,
++	.ai_diff_chans = 8,
++	.ai_bits = 16,
++	.ai_speed = 5000,
++	.ao_nchan = 2,
++	.has_ao_fifo = 1,
++	.ao_scan_speed = 10000,
++	.fifo_size = 512,
++	.ranges = &cb_pcidas_ranges,
++	.trimpot = AD8402,
++	.has_dac08 = 1,
+ 		},
+ 	{
+-	      name:	"pci-das1200",
+-	      device_id:0xF,
+-	      ai_se_chans:16,
+-	      ai_diff_chans:8,
+-	      ai_bits:	12,
+-	      ai_speed:3200,
+-	      ao_nchan:2,
+-	      has_ao_fifo:0,
+-	      fifo_size:1024,
+-	      ranges:	&cb_pcidas_ranges,
+-	      trimpot:	AD7376,
+-	      has_dac08:0,
++	.name = "pci-das1200",
++	.device_id = 0xF,
++	.ai_se_chans = 16,
++	.ai_diff_chans = 8,
++	.ai_bits = 12,
++	.ai_speed = 3200,
++	.ao_nchan = 2,
++	.has_ao_fifo = 0,
++	.fifo_size = 1024,
++	.ranges = &cb_pcidas_ranges,
++	.trimpot = AD7376,
++	.has_dac08 = 0,
+ 		},
+ 	{
+-	      name:	"pci-das1602/12",
+-	      device_id:0x10,
+-	      ai_se_chans:16,
+-	      ai_diff_chans:8,
+-	      ai_bits:	12,
+-	      ai_speed:3200,
+-	      ao_nchan:2,
+-	      has_ao_fifo:1,
+-	      ao_scan_speed:4000,
+-	      fifo_size:1024,
+-	      ranges:	&cb_pcidas_ranges,
+-	      trimpot:	AD7376,
+-	      has_dac08:0,
++	.name = "pci-das1602/12",
++	.device_id = 0x10,
++	.ai_se_chans = 16,
++	.ai_diff_chans = 8,
++	.ai_bits = 12,
++	.ai_speed = 3200,
++	.ao_nchan = 2,
++	.has_ao_fifo = 1,
++	.ao_scan_speed = 4000,
++	.fifo_size = 1024,
++	.ranges = &cb_pcidas_ranges,
++	.trimpot = AD7376,
++	.has_dac08 = 0,
+ 		},
+ 	{
+-	      name:	"pci-das1200/jr",
+-	      device_id:0x19,
+-	      ai_se_chans:16,
+-	      ai_diff_chans:8,
+-	      ai_bits:	12,
+-	      ai_speed:3200,
+-	      ao_nchan:0,
+-	      has_ao_fifo:0,
+-	      fifo_size:1024,
+-	      ranges:	&cb_pcidas_ranges,
+-	      trimpot:	AD7376,
+-	      has_dac08:0,
++	.name = "pci-das1200/jr",
++	.device_id = 0x19,
++	.ai_se_chans = 16,
++	.ai_diff_chans = 8,
++	.ai_bits = 12,
++	.ai_speed = 3200,
++	.ao_nchan = 0,
++	.has_ao_fifo = 0,
++	.fifo_size = 1024,
++	.ranges = &cb_pcidas_ranges,
++	.trimpot = AD7376,
++	.has_dac08 = 0,
+ 		},
+ 	{
+-	      name:	"pci-das1602/16/jr",
+-	      device_id:0x1C,
+-	      ai_se_chans:16,
+-	      ai_diff_chans:8,
+-	      ai_bits:	16,
+-	      ai_speed:5000,
+-	      ao_nchan:0,
+-	      has_ao_fifo:0,
+-	      fifo_size:512,
+-	      ranges:	&cb_pcidas_ranges,
+-	      trimpot:	AD8402,
+-	      has_dac08:1,
++	.name = "pci-das1602/16/jr",
++	.device_id = 0x1C,
++	.ai_se_chans = 16,
++	.ai_diff_chans = 8,
++	.ai_bits = 16,
++	.ai_speed = 5000,
++	.ao_nchan = 0,
++	.has_ao_fifo = 0,
++	.fifo_size = 512,
++	.ranges = &cb_pcidas_ranges,
++	.trimpot = AD8402,
++	.has_dac08 = 1,
+ 		},
+ 	{
+-	      name:	"pci-das1000",
+-	      device_id:0x4C,
+-	      ai_se_chans:16,
+-	      ai_diff_chans:8,
+-	      ai_bits:	12,
+-	      ai_speed:4000,
+-	      ao_nchan:0,
+-	      has_ao_fifo:0,
+-	      fifo_size:1024,
+-	      ranges:	&cb_pcidas_ranges,
+-	      trimpot:	AD7376,
+-	      has_dac08:0,
++	.name = "pci-das1000",
++	.device_id = 0x4C,
++	.ai_se_chans = 16,
++	.ai_diff_chans = 8,
++	.ai_bits = 12,
++	.ai_speed = 4000,
++	.ao_nchan = 0,
++	.has_ao_fifo = 0,
++	.fifo_size = 1024,
++	.ranges = &cb_pcidas_ranges,
++	.trimpot = AD7376,
++	.has_dac08 = 0,
+ 		},
+ 	{
+-	      name:	"pci-das1001",
+-	      device_id:0x1a,
+-	      ai_se_chans:16,
+-	      ai_diff_chans:8,
+-	      ai_bits:	12,
+-	      ai_speed:6800,
+-	      ao_nchan:2,
+-	      has_ao_fifo:0,
+-	      fifo_size:1024,
+-	      ranges:	&cb_pcidas_alt_ranges,
+-	      trimpot:	AD7376,
+-	      has_dac08:0,
++	.name = "pci-das1001",
++	.device_id = 0x1a,
++	.ai_se_chans = 16,
++	.ai_diff_chans = 8,
++	.ai_bits = 12,
++	.ai_speed = 6800,
++	.ao_nchan = 2,
++	.has_ao_fifo = 0,
++	.fifo_size = 1024,
++	.ranges = &cb_pcidas_alt_ranges,
++	.trimpot = AD7376,
++	.has_dac08 = 0,
+ 		},
+ 	{
+-	      name:	"pci-das1002",
+-	      device_id:0x1b,
+-	      ai_se_chans:16,
+-	      ai_diff_chans:8,
+-	      ai_bits:	12,
+-	      ai_speed:6800,
+-	      ao_nchan:2,
+-	      has_ao_fifo:0,
+-	      fifo_size:1024,
+-	      ranges:	&cb_pcidas_ranges,
+-	      trimpot:	AD7376,
+-	      has_dac08:0,
++	.name = "pci-das1002",
++	.device_id = 0x1b,
++	.ai_se_chans = 16,
++	.ai_diff_chans = 8,
++	.ai_bits = 12,
++	.ai_speed = 6800,
++	.ao_nchan = 2,
++	.has_ao_fifo = 0,
++	.fifo_size = 1024,
++	.ranges = &cb_pcidas_ranges,
++	.trimpot = AD7376,
++	.has_dac08 = 0,
+ 		},
+ };
+ 
+@@ -444,10 +444,10 @@ struct cb_pcidas_private {
+ static int cb_pcidas_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int cb_pcidas_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_cb_pcidas = {
+-      driver_name:"cb_pcidas",
+-      module:THIS_MODULE,
+-      attach:cb_pcidas_attach,
+-      detach:cb_pcidas_detach,
++	.driver_name = "cb_pcidas",
++	.module = THIS_MODULE,
++	.attach = cb_pcidas_attach,
++	.detach = cb_pcidas_detach,
+ };
+ 
+ static int cb_pcidas_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice * s,
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
+index 425c0f296455..49dfd8f09e27 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
+@@ -560,24 +560,24 @@ struct pcidas64_board {
+ };
+ 
+ static const struct hw_fifo_info ai_fifo_4020 = {
+-      num_segments:2,
+-      max_segment_length:0x8000,
+-      sample_packing_ratio:2,
+-      fifo_size_reg_mask:0x7f,
++	.num_segments = 2,
++	.max_segment_length = 0x8000,
++	.sample_packing_ratio = 2,
++	.fifo_size_reg_mask = 0x7f,
+ };
+ 
+ static const struct hw_fifo_info ai_fifo_64xx = {
+-      num_segments:4,
+-      max_segment_length:0x800,
+-      sample_packing_ratio:1,
+-      fifo_size_reg_mask:0x3f,
++	.num_segments = 4,
++	.max_segment_length = 0x800,
++	.sample_packing_ratio = 1,
++	.fifo_size_reg_mask = 0x3f,
+ };
+ 
+ static const struct hw_fifo_info ai_fifo_60xx = {
+-      num_segments:4,
+-      max_segment_length:0x800,
+-      sample_packing_ratio:1,
+-      fifo_size_reg_mask:0x7f,
++	.num_segments = 4,
++	.max_segment_length = 0x800,
++	.sample_packing_ratio = 1,
++	.fifo_size_reg_mask = 0x7f,
+ };
+ 
+ /* maximum number of dma transfers we will chain together into a ring
+@@ -597,84 +597,84 @@ static const int bytes_in_sample = 2;
+ 
+ static const struct pcidas64_board pcidas64_boards[] = {
+ 	{
+-	      name:	"pci-das6402/16",
+-	      device_id:0x1d,
+-	      ai_se_chans:64,
+-	      ai_bits:	16,
+-	      ai_speed:5000,
+-	      ao_nchan:2,
+-	      ao_bits:	16,
+-	      ao_scan_speed:10000,
+-	      layout:	LAYOUT_64XX,
+-	      ai_range_table:&ai_ranges_64xx,
+-	      ao_range_table:&ao_ranges_64xx,
+-	      ao_range_code:ao_range_code_64xx,
+-	      ai_fifo:	&ai_fifo_64xx,
+-	      has_8255:1,
++	.name = "pci-das6402/16",
++	.device_id = 0x1d,
++	.ai_se_chans = 64,
++	.ai_bits = 16,
++	.ai_speed = 5000,
++	.ao_nchan = 2,
++	.ao_bits = 16,
++	.ao_scan_speed = 10000,
++	.layout = LAYOUT_64XX,
++	.ai_range_table = &ai_ranges_64xx,
++	.ao_range_table = &ao_ranges_64xx,
++	.ao_range_code = ao_range_code_64xx,
++	.ai_fifo = &ai_fifo_64xx,
++	.has_8255 = 1,
+ 		},
+ 	{
+-	      name:	"pci-das6402/12",	/*  XXX check */
+-	      device_id:0x1e,
+-	      ai_se_chans:64,
+-	      ai_bits:	12,
+-	      ai_speed:5000,
+-	      ao_nchan:2,
+-	      ao_bits:	12,
+-	      ao_scan_speed:10000,
+-	      layout:	LAYOUT_64XX,
+-	      ai_range_table:&ai_ranges_64xx,
+-	      ao_range_table:&ao_ranges_64xx,
+-	      ao_range_code:ao_range_code_64xx,
+-	      ai_fifo:	&ai_fifo_64xx,
+-	      has_8255:1,
++	.name = "pci-das6402/12",	/*  XXX check */
++	.device_id = 0x1e,
++	.ai_se_chans = 64,
++	.ai_bits = 12,
++	.ai_speed = 5000,
++	.ao_nchan = 2,
++	.ao_bits = 12,
++	.ao_scan_speed = 10000,
++	.layout = LAYOUT_64XX,
++	.ai_range_table = &ai_ranges_64xx,
++	.ao_range_table = &ao_ranges_64xx,
++	.ao_range_code = ao_range_code_64xx,
++	.ai_fifo = &ai_fifo_64xx,
++	.has_8255 = 1,
+ 		},
+ 	{
+-	      name:	"pci-das64/m1/16",
+-	      device_id:0x35,
+-	      ai_se_chans:64,
+-	      ai_bits:	16,
+-	      ai_speed:1000,
+-	      ao_nchan:2,
+-	      ao_bits:	16,
+-	      ao_scan_speed:10000,
+-	      layout:	LAYOUT_64XX,
+-	      ai_range_table:&ai_ranges_64xx,
+-	      ao_range_table:&ao_ranges_64xx,
+-	      ao_range_code:ao_range_code_64xx,
+-	      ai_fifo:	&ai_fifo_64xx,
+-	      has_8255:1,
++	.name = "pci-das64/m1/16",
++	.device_id = 0x35,
++	.ai_se_chans = 64,
++	.ai_bits = 16,
++	.ai_speed = 1000,
++	.ao_nchan = 2,
++	.ao_bits = 16,
++	.ao_scan_speed = 10000,
++	.layout = LAYOUT_64XX,
++	.ai_range_table = &ai_ranges_64xx,
++	.ao_range_table = &ao_ranges_64xx,
++	.ao_range_code = ao_range_code_64xx,
++	.ai_fifo = &ai_fifo_64xx,
++	.has_8255 = 1,
+ 		},
+ 	{
+-	      name:	"pci-das64/m2/16",
+-	      device_id:0x36,
+-	      ai_se_chans:64,
+-	      ai_bits:	16,
+-	      ai_speed:500,
+-	      ao_nchan:2,
+-	      ao_bits:	16,
+-	      ao_scan_speed:10000,
+-	      layout:	LAYOUT_64XX,
+-	      ai_range_table:&ai_ranges_64xx,
+-	      ao_range_table:&ao_ranges_64xx,
+-	      ao_range_code:ao_range_code_64xx,
+-	      ai_fifo:	&ai_fifo_64xx,
+-	      has_8255:1,
++	.name = "pci-das64/m2/16",
++	.device_id = 0x36,
++	.ai_se_chans = 64,
++	.ai_bits = 16,
++	.ai_speed = 500,
++	.ao_nchan = 2,
++	.ao_bits = 16,
++	.ao_scan_speed = 10000,
++	.layout = LAYOUT_64XX,
++	.ai_range_table = &ai_ranges_64xx,
++	.ao_range_table = &ao_ranges_64xx,
++	.ao_range_code = ao_range_code_64xx,
++	.ai_fifo = &ai_fifo_64xx,
++	.has_8255 = 1,
+ 		},
+ 	{
+-	      name:	"pci-das64/m3/16",
+-	      device_id:0x37,
+-	      ai_se_chans:64,
+-	      ai_bits:	16,
+-	      ai_speed:333,
+-	      ao_nchan:2,
+-	      ao_bits:	16,
+-	      ao_scan_speed:10000,
+-	      layout:	LAYOUT_64XX,
+-	      ai_range_table:&ai_ranges_64xx,
+-	      ao_range_table:&ao_ranges_64xx,
+-	      ao_range_code:ao_range_code_64xx,
+-	      ai_fifo:	&ai_fifo_64xx,
+-	      has_8255:1,
++	.name = "pci-das64/m3/16",
++	.device_id = 0x37,
++	.ai_se_chans = 64,
++	.ai_bits = 16,
++	.ai_speed = 333,
++	.ao_nchan = 2,
++	.ao_bits = 16,
++	.ao_scan_speed = 10000,
++	.layout = LAYOUT_64XX,
++	.ai_range_table = &ai_ranges_64xx,
++	.ao_range_table = &ao_ranges_64xx,
++	.ao_range_code = ao_range_code_64xx,
++	.ai_fifo = &ai_fifo_64xx,
++	.has_8255 = 1,
+ 		},
+ 	{
+ 		.name = "pci-das6013",
+@@ -692,324 +692,324 @@ static const struct pcidas64_board pcidas64_boards[] = {
+ 		.has_8255 = 0,
+ 		},
+ 	{
+-	      name:	"pci-das6014",
+-	      device_id:0x79,
+-	      ai_se_chans:16,
+-	      ai_bits:	16,
+-	      ai_speed:5000,
+-	      ao_nchan:2,
+-	      ao_bits:	16,
+-	      ao_scan_speed:100000,
+-	      layout:	LAYOUT_60XX,
+-	      ai_range_table:&ai_ranges_60xx,
+-	      ao_range_table:&ao_ranges_60xx,
+-	      ao_range_code:ao_range_code_60xx,
+-	      ai_fifo:	&ai_fifo_60xx,
+-	      has_8255:0,
++	.name = "pci-das6014",
++	.device_id = 0x79,
++	.ai_se_chans = 16,
++	.ai_bits = 16,
++	.ai_speed = 5000,
++	.ao_nchan = 2,
++	.ao_bits = 16,
++	.ao_scan_speed = 100000,
++	.layout = LAYOUT_60XX,
++	.ai_range_table = &ai_ranges_60xx,
++	.ao_range_table = &ao_ranges_60xx,
++	.ao_range_code = ao_range_code_60xx,
++	.ai_fifo = &ai_fifo_60xx,
++	.has_8255 = 0,
+ 		},
+ 	{
+-	      name:	"pci-das6023",
+-	      device_id:0x5d,
+-	      ai_se_chans:16,
+-	      ai_bits:	12,
+-	      ai_speed:5000,
+-	      ao_nchan:0,
+-	      ao_scan_speed:100000,
+-	      layout:	LAYOUT_60XX,
+-	      ai_range_table:&ai_ranges_60xx,
+-	      ao_range_table:&ao_ranges_60xx,
+-	      ao_range_code:ao_range_code_60xx,
+-	      ai_fifo:	&ai_fifo_60xx,
+-	      has_8255:1,
++	.name = "pci-das6023",
++	.device_id = 0x5d,
++	.ai_se_chans = 16,
++	.ai_bits = 12,
++	.ai_speed = 5000,
++	.ao_nchan = 0,
++	.ao_scan_speed = 100000,
++	.layout = LAYOUT_60XX,
++	.ai_range_table = &ai_ranges_60xx,
++	.ao_range_table = &ao_ranges_60xx,
++	.ao_range_code = ao_range_code_60xx,
++	.ai_fifo = &ai_fifo_60xx,
++	.has_8255 = 1,
+ 		},
+ 	{
+-	      name:	"pci-das6025",
+-	      device_id:0x5e,
+-	      ai_se_chans:16,
+-	      ai_bits:	12,
+-	      ai_speed:5000,
+-	      ao_nchan:2,
+-	      ao_bits:	12,
+-	      ao_scan_speed:100000,
+-	      layout:	LAYOUT_60XX,
+-	      ai_range_table:&ai_ranges_60xx,
+-	      ao_range_table:&ao_ranges_60xx,
+-	      ao_range_code:ao_range_code_60xx,
+-	      ai_fifo:	&ai_fifo_60xx,
+-	      has_8255:1,
++	.name = "pci-das6025",
++	.device_id = 0x5e,
++	.ai_se_chans = 16,
++	.ai_bits = 12,
++	.ai_speed = 5000,
++	.ao_nchan = 2,
++	.ao_bits = 12,
++	.ao_scan_speed = 100000,
++	.layout = LAYOUT_60XX,
++	.ai_range_table = &ai_ranges_60xx,
++	.ao_range_table = &ao_ranges_60xx,
++	.ao_range_code = ao_range_code_60xx,
++	.ai_fifo = &ai_fifo_60xx,
++	.has_8255 = 1,
+ 		},
+ 	{
+-	      name:	"pci-das6030",
+-	      device_id:0x5f,
+-	      ai_se_chans:16,
+-	      ai_bits:	16,
+-	      ai_speed:10000,
+-	      ao_nchan:2,
+-	      ao_bits:	16,
+-	      ao_scan_speed:10000,
+-	      layout:	LAYOUT_60XX,
+-	      ai_range_table:&ai_ranges_6030,
+-	      ao_range_table:&ao_ranges_6030,
+-	      ao_range_code:ao_range_code_6030,
+-	      ai_fifo:	&ai_fifo_60xx,
+-	      has_8255:0,
++	.name = "pci-das6030",
++	.device_id = 0x5f,
++	.ai_se_chans = 16,
++	.ai_bits = 16,
++	.ai_speed = 10000,
++	.ao_nchan = 2,
++	.ao_bits = 16,
++	.ao_scan_speed = 10000,
++	.layout = LAYOUT_60XX,
++	.ai_range_table = &ai_ranges_6030,
++	.ao_range_table = &ao_ranges_6030,
++	.ao_range_code = ao_range_code_6030,
++	.ai_fifo = &ai_fifo_60xx,
++	.has_8255 = 0,
+ 		},
+ 	{
+-	      name:	"pci-das6031",
+-	      device_id:0x60,
+-	      ai_se_chans:64,
+-	      ai_bits:	16,
+-	      ai_speed:10000,
+-	      ao_nchan:2,
+-	      ao_bits:	16,
+-	      ao_scan_speed:10000,
+-	      layout:	LAYOUT_60XX,
+-	      ai_range_table:&ai_ranges_6030,
+-	      ao_range_table:&ao_ranges_6030,
+-	      ao_range_code:ao_range_code_6030,
+-	      ai_fifo:	&ai_fifo_60xx,
+-	      has_8255:0,
++	.name = "pci-das6031",
++	.device_id = 0x60,
++	.ai_se_chans = 64,
++	.ai_bits = 16,
++	.ai_speed = 10000,
++	.ao_nchan = 2,
++	.ao_bits = 16,
++	.ao_scan_speed = 10000,
++	.layout = LAYOUT_60XX,
++	.ai_range_table = &ai_ranges_6030,
++	.ao_range_table = &ao_ranges_6030,
++	.ao_range_code = ao_range_code_6030,
++	.ai_fifo = &ai_fifo_60xx,
++	.has_8255 = 0,
+ 		},
+ 	{
+-	      name:	"pci-das6032",
+-	      device_id:0x61,
+-	      ai_se_chans:16,
+-	      ai_bits:	16,
+-	      ai_speed:10000,
+-	      ao_nchan:0,
+-	      layout:	LAYOUT_60XX,
+-	      ai_range_table:&ai_ranges_6030,
+-	      ai_fifo:	&ai_fifo_60xx,
+-	      has_8255:0,
++	.name = "pci-das6032",
++	.device_id = 0x61,
++	.ai_se_chans = 16,
++	.ai_bits = 16,
++	.ai_speed = 10000,
++	.ao_nchan = 0,
++	.layout = LAYOUT_60XX,
++	.ai_range_table = &ai_ranges_6030,
++	.ai_fifo = &ai_fifo_60xx,
++	.has_8255 = 0,
+ 		},
+ 	{
+-	      name:	"pci-das6033",
+-	      device_id:0x62,
+-	      ai_se_chans:64,
+-	      ai_bits:	16,
+-	      ai_speed:10000,
+-	      ao_nchan:0,
+-	      layout:	LAYOUT_60XX,
+-	      ai_range_table:&ai_ranges_6030,
+-	      ai_fifo:	&ai_fifo_60xx,
+-	      has_8255:0,
++	.name = "pci-das6033",
++	.device_id = 0x62,
++	.ai_se_chans = 64,
++	.ai_bits = 16,
++	.ai_speed = 10000,
++	.ao_nchan = 0,
++	.layout = LAYOUT_60XX,
++	.ai_range_table = &ai_ranges_6030,
++	.ai_fifo = &ai_fifo_60xx,
++	.has_8255 = 0,
+ 		},
+ 	{
+-	      name:	"pci-das6034",
+-	      device_id:0x63,
+-	      ai_se_chans:16,
+-	      ai_bits:	16,
+-	      ai_speed:5000,
+-	      ao_nchan:0,
+-	      ao_scan_speed:0,
+-	      layout:	LAYOUT_60XX,
+-	      ai_range_table:&ai_ranges_60xx,
+-	      ai_fifo:	&ai_fifo_60xx,
+-	      has_8255:0,
++	.name = "pci-das6034",
++	.device_id = 0x63,
++	.ai_se_chans = 16,
++	.ai_bits = 16,
++	.ai_speed = 5000,
++	.ao_nchan = 0,
++	.ao_scan_speed = 0,
++	.layout = LAYOUT_60XX,
++	.ai_range_table = &ai_ranges_60xx,
++	.ai_fifo = &ai_fifo_60xx,
++	.has_8255 = 0,
+ 		},
+ 	{
+-	      name:	"pci-das6035",
+-	      device_id:0x64,
+-	      ai_se_chans:16,
+-	      ai_bits:	16,
+-	      ai_speed:5000,
+-	      ao_nchan:2,
+-	      ao_bits:	12,
+-	      ao_scan_speed:100000,
+-	      layout:	LAYOUT_60XX,
+-	      ai_range_table:&ai_ranges_60xx,
+-	      ao_range_table:&ao_ranges_60xx,
+-	      ao_range_code:ao_range_code_60xx,
+-	      ai_fifo:	&ai_fifo_60xx,
+-	      has_8255:0,
++	.name = "pci-das6035",
++	.device_id = 0x64,
++	.ai_se_chans = 16,
++	.ai_bits = 16,
++	.ai_speed = 5000,
++	.ao_nchan = 2,
++	.ao_bits = 12,
++	.ao_scan_speed = 100000,
++	.layout = LAYOUT_60XX,
++	.ai_range_table = &ai_ranges_60xx,
++	.ao_range_table = &ao_ranges_60xx,
++	.ao_range_code = ao_range_code_60xx,
++	.ai_fifo = &ai_fifo_60xx,
++	.has_8255 = 0,
+ 		},
+ 	{
+-	      name:	"pci-das6036",
+-	      device_id:0x6f,
+-	      ai_se_chans:16,
+-	      ai_bits:	16,
+-	      ai_speed:5000,
+-	      ao_nchan:2,
+-	      ao_bits:	16,
+-	      ao_scan_speed:100000,
+-	      layout:	LAYOUT_60XX,
+-	      ai_range_table:&ai_ranges_60xx,
+-	      ao_range_table:&ao_ranges_60xx,
+-	      ao_range_code:ao_range_code_60xx,
+-	      ai_fifo:	&ai_fifo_60xx,
+-	      has_8255:0,
++	.name = "pci-das6036",
++	.device_id = 0x6f,
++	.ai_se_chans = 16,
++	.ai_bits = 16,
++	.ai_speed = 5000,
++	.ao_nchan = 2,
++	.ao_bits = 16,
++	.ao_scan_speed = 100000,
++	.layout = LAYOUT_60XX,
++	.ai_range_table = &ai_ranges_60xx,
++	.ao_range_table = &ao_ranges_60xx,
++	.ao_range_code = ao_range_code_60xx,
++	.ai_fifo = &ai_fifo_60xx,
++	.has_8255 = 0,
+ 		},
+ 	{
+-	      name:	"pci-das6040",
+-	      device_id:0x65,
+-	      ai_se_chans:16,
+-	      ai_bits:	12,
+-	      ai_speed:2000,
+-	      ao_nchan:2,
+-	      ao_bits:	12,
+-	      ao_scan_speed:1000,
+-	      layout:	LAYOUT_60XX,
+-	      ai_range_table:&ai_ranges_6052,
+-	      ao_range_table:&ao_ranges_6030,
+-	      ao_range_code:ao_range_code_6030,
+-	      ai_fifo:	&ai_fifo_60xx,
+-	      has_8255:0,
++	.name = "pci-das6040",
++	.device_id = 0x65,
++	.ai_se_chans = 16,
++	.ai_bits = 12,
++	.ai_speed = 2000,
++	.ao_nchan = 2,
++	.ao_bits = 12,
++	.ao_scan_speed = 1000,
++	.layout = LAYOUT_60XX,
++	.ai_range_table = &ai_ranges_6052,
++	.ao_range_table = &ao_ranges_6030,
++	.ao_range_code = ao_range_code_6030,
++	.ai_fifo = &ai_fifo_60xx,
++	.has_8255 = 0,
+ 		},
+ 	{
+-	      name:	"pci-das6052",
+-	      device_id:0x66,
+-	      ai_se_chans:16,
+-	      ai_bits:	16,
+-	      ai_speed:3333,
+-	      ao_nchan:2,
+-	      ao_bits:	16,
+-	      ao_scan_speed:3333,
+-	      layout:	LAYOUT_60XX,
+-	      ai_range_table:&ai_ranges_6052,
+-	      ao_range_table:&ao_ranges_6030,
+-	      ao_range_code:ao_range_code_6030,
+-	      ai_fifo:	&ai_fifo_60xx,
+-	      has_8255:0,
++	.name = "pci-das6052",
++	.device_id = 0x66,
++	.ai_se_chans = 16,
++	.ai_bits = 16,
++	.ai_speed = 3333,
++	.ao_nchan = 2,
++	.ao_bits = 16,
++	.ao_scan_speed = 3333,
++	.layout = LAYOUT_60XX,
++	.ai_range_table = &ai_ranges_6052,
++	.ao_range_table = &ao_ranges_6030,
++	.ao_range_code = ao_range_code_6030,
++	.ai_fifo = &ai_fifo_60xx,
++	.has_8255 = 0,
+ 		},
+ 	{
+-	      name:	"pci-das6070",
+-	      device_id:0x67,
+-	      ai_se_chans:16,
+-	      ai_bits:	12,
+-	      ai_speed:800,
+-	      ao_nchan:2,
+-	      ao_bits:	12,
+-	      ao_scan_speed:1000,
+-	      layout:	LAYOUT_60XX,
+-	      ai_range_table:&ai_ranges_6052,
+-	      ao_range_table:&ao_ranges_6030,
+-	      ao_range_code:ao_range_code_6030,
+-	      ai_fifo:	&ai_fifo_60xx,
+-	      has_8255:0,
++	.name = "pci-das6070",
++	.device_id = 0x67,
++	.ai_se_chans = 16,
++	.ai_bits = 12,
++	.ai_speed = 800,
++	.ao_nchan = 2,
++	.ao_bits = 12,
++	.ao_scan_speed = 1000,
++	.layout = LAYOUT_60XX,
++	.ai_range_table = &ai_ranges_6052,
++	.ao_range_table = &ao_ranges_6030,
++	.ao_range_code = ao_range_code_6030,
++	.ai_fifo = &ai_fifo_60xx,
++	.has_8255 = 0,
+ 		},
+ 	{
+-	      name:	"pci-das6071",
+-	      device_id:0x68,
+-	      ai_se_chans:64,
+-	      ai_bits:	12,
+-	      ai_speed:800,
+-	      ao_nchan:2,
+-	      ao_bits:	12,
+-	      ao_scan_speed:1000,
+-	      layout:	LAYOUT_60XX,
+-	      ai_range_table:&ai_ranges_6052,
+-	      ao_range_table:&ao_ranges_6030,
+-	      ao_range_code:ao_range_code_6030,
+-	      ai_fifo:	&ai_fifo_60xx,
+-	      has_8255:0,
++	.name = "pci-das6071",
++	.device_id = 0x68,
++	.ai_se_chans = 64,
++	.ai_bits = 12,
++	.ai_speed = 800,
++	.ao_nchan = 2,
++	.ao_bits = 12,
++	.ao_scan_speed = 1000,
++	.layout = LAYOUT_60XX,
++	.ai_range_table = &ai_ranges_6052,
++	.ao_range_table = &ao_ranges_6030,
++	.ao_range_code = ao_range_code_6030,
++	.ai_fifo = &ai_fifo_60xx,
++	.has_8255 = 0,
+ 		},
+ 	{
+-	      name:	"pci-das4020/12",
+-	      device_id:0x52,
+-	      ai_se_chans:4,
+-	      ai_bits:	12,
+-	      ai_speed:50,
+-	      ao_bits:	12,
+-	      ao_nchan:2,
+-	      ao_scan_speed:0,	/*  no hardware pacing on ao */
+-	      layout:	LAYOUT_4020,
+-	      ai_range_table:&ai_ranges_4020,
+-	      ao_range_table:&ao_ranges_4020,
+-	      ao_range_code:ao_range_code_4020,
+-	      ai_fifo:	&ai_fifo_4020,
+-	      has_8255:1,
++	.name = "pci-das4020/12",
++	.device_id = 0x52,
++	.ai_se_chans = 4,
++	.ai_bits = 12,
++	.ai_speed = 50,
++	.ao_bits = 12,
++	.ao_nchan = 2,
++	.ao_scan_speed = 0,	/*  no hardware pacing on ao */
++	.layout = LAYOUT_4020,
++	.ai_range_table = &ai_ranges_4020,
++	.ao_range_table = &ao_ranges_4020,
++	.ao_range_code = ao_range_code_4020,
++	.ai_fifo = &ai_fifo_4020,
++	.has_8255 = 1,
+ 		},
+ #if 0
+ 	{
+-	      name:	"pci-das6402/16/jr",
+-	      device_id:0	/*  XXX, */
+-	      ai_se_chans:64,
+-	      ai_bits:	16,
+-	      ai_speed:5000,
+-	      ao_nchan:0,
+-	      ao_scan_speed:10000,
+-	      layout:	LAYOUT_64XX,
+-	      ai_range_table:&ai_ranges_64xx,
+-	      ai_fifo:	ai_fifo_64xx,
+-	      has_8255:1,
++	.name = "pci-das6402/16/jr",
++	.device_id = 0	/*  XXX, */
++	.ai_se_chans = 64,
++	.ai_bits = 16,
++	.ai_speed = 5000,
++	.ao_nchan = 0,
++	.ao_scan_speed = 10000,
++	.layout = LAYOUT_64XX,
++	.ai_range_table = &ai_ranges_64xx,
++	.ai_fifo = ai_fifo_64xx,
++	.has_8255 = 1,
+ 		},
+ 	{
+-	      name:	"pci-das64/m1/16/jr",
+-	      device_id:0	/*  XXX, */
+-	      ai_se_chans:64,
+-	      ai_bits:	16,
+-	      ai_speed:1000,
+-	      ao_nchan:0,
+-	      ao_scan_speed:10000,
+-	      layout:	LAYOUT_64XX,
+-	      ai_range_table:&ai_ranges_64xx,
+-	      ai_fifo:	ai_fifo_64xx,
+-	      has_8255:1,
++	.name = "pci-das64/m1/16/jr",
++	.device_id = 0	/*  XXX, */
++	.ai_se_chans = 64,
++	.ai_bits = 16,
++	.ai_speed = 1000,
++	.ao_nchan = 0,
++	.ao_scan_speed = 10000,
++	.layout = LAYOUT_64XX,
++	.ai_range_table = &ai_ranges_64xx,
++	.ai_fifo = ai_fifo_64xx,
++	.has_8255 = 1,
+ 		},
+ 	{
+-	      name:	"pci-das64/m2/16/jr",
+-	      device_id:0	/*  XXX, */
+-	      ai_se_chans:64,
+-	      ai_bits:	16,
+-	      ai_speed:500,
+-	      ao_nchan:0,
+-	      ao_scan_speed:10000,
+-	      layout:	LAYOUT_64XX,
+-	      ai_range_table:&ai_ranges_64xx,
+-	      ai_fifo:	ai_fifo_64xx,
+-	      has_8255:1,
++	.name = "pci-das64/m2/16/jr",
++	.device_id = 0	/*  XXX, */
++	.ai_se_chans = 64,
++	.ai_bits = 16,
++	.ai_speed = 500,
++	.ao_nchan = 0,
++	.ao_scan_speed = 10000,
++	.layout = LAYOUT_64XX,
++	.ai_range_table = &ai_ranges_64xx,
++	.ai_fifo = ai_fifo_64xx,
++	.has_8255 = 1,
+ 		},
+ 	{
+-	      name:	"pci-das64/m3/16/jr",
+-	      device_id:0	/*  XXX, */
+-	      ai_se_chans:64,
+-	      ai_bits:	16,
+-	      ai_speed:333,
+-	      ao_nchan:0,
+-	      ao_scan_speed:10000,
+-	      layout:	LAYOUT_64XX,
+-	      ai_range_table:&ai_ranges_64xx,
+-	      ai_fifo:	ai_fifo_64xx,
+-	      has_8255:1,
++	.name = "pci-das64/m3/16/jr",
++	.device_id = 0	/*  XXX, */
++	.ai_se_chans = 64,
++	.ai_bits = 16,
++	.ai_speed = 333,
++	.ao_nchan = 0,
++	.ao_scan_speed = 10000,
++	.layout = LAYOUT_64XX,
++	.ai_range_table = &ai_ranges_64xx,
++	.ai_fifo = ai_fifo_64xx,
++	.has_8255 = 1,
+ 		},
+ 	{
+-	      name:	"pci-das64/m1/14",
+-	      device_id:0,	/*  XXX */
+-	      ai_se_chans:64,
+-	      ai_bits:	14,
+-	      ai_speed:1000,
+-	      ao_nchan:2,
+-	      ao_scan_speed:10000,
+-	      layout:	LAYOUT_64XX,
+-	      ai_range_table:&ai_ranges_64xx,
+-	      ai_fifo:	ai_fifo_64xx,
+-	      has_8255:1,
++	.name = "pci-das64/m1/14",
++	.device_id = 0,	/*  XXX */
++	.ai_se_chans = 64,
++	.ai_bits = 14,
++	.ai_speed = 1000,
++	.ao_nchan = 2,
++	.ao_scan_speed = 10000,
++	.layout = LAYOUT_64XX,
++	.ai_range_table = &ai_ranges_64xx,
++	.ai_fifo = ai_fifo_64xx,
++	.has_8255 = 1,
+ 		},
+ 	{
+-	      name:	"pci-das64/m2/14",
+-	      device_id:0,	/*  XXX */
+-	      ai_se_chans:64,
+-	      ai_bits:	14,
+-	      ai_speed:500,
+-	      ao_nchan:2,
+-	      ao_scan_speed:10000,
+-	      layout:	LAYOUT_64XX,
+-	      ai_range_table:&ai_ranges_64xx,
+-	      ai_fifo:	ai_fifo_64xx,
+-	      has_8255:1,
++	.name = "pci-das64/m2/14",
++	.device_id = 0,	/*  XXX */
++	.ai_se_chans = 64,
++	.ai_bits = 14,
++	.ai_speed = 500,
++	.ao_nchan = 2,
++	.ao_scan_speed = 10000,
++	.layout = LAYOUT_64XX,
++	.ai_range_table = &ai_ranges_64xx,
++	.ai_fifo = ai_fifo_64xx,
++	.has_8255 = 1,
+ 		},
+ 	{
+-	      name:	"pci-das64/m3/14",
+-	      device_id:0,	/*  XXX */
+-	      ai_se_chans:64,
+-	      ai_bits:	14,
+-	      ai_speed:333,
+-	      ao_nchan:2,
+-	      ao_scan_speed:10000,
+-	      layout:	LAYOUT_64XX,
+-	      ai_range_table:&ai_ranges_64xx,
+-	      ai_fifo:	ai_fifo_64xx,
+-	      has_8255:1,
++	.name = "pci-das64/m3/14",
++	.device_id = 0,	/*  XXX */
++	.ai_se_chans = 64,
++	.ai_bits = 14,
++	.ai_speed = 333,
++	.ao_nchan = 2,
++	.ao_scan_speed = 10000,
++	.layout = LAYOUT_64XX,
++	.ai_range_table = &ai_ranges_64xx,
++	.ai_fifo = ai_fifo_64xx,
++	.has_8255 = 1,
+ 		},
+ #endif
+ };
+@@ -1131,10 +1131,10 @@ static inline struct pcidas64_private *priv(struct comedi_device * dev)
+ static int attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int detach(struct comedi_device *dev);
+ static struct comedi_driver driver_cb_pcidas = {
+-      driver_name:"cb_pcidas64",
+-      module:THIS_MODULE,
+-      attach:attach,
+-      detach:detach,
++	.driver_name = "cb_pcidas64",
++	.module = THIS_MODULE,
++	.attach = attach,
++	.detach = detach,
+ };
+ 
+ static int ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
+index d87b04c9f931..8f3629416188 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidda.c
++++ b/drivers/staging/comedi/drivers/cb_pcidda.c
+@@ -147,52 +147,52 @@ struct cb_pcidda_board {
+ 
+ static const struct cb_pcidda_board cb_pcidda_boards[] = {
+ 	{
+-	      name:	"pci-dda02/12",
+-	      status:	1,
+-	      device_id:0x20,
+-	      ao_chans:2,
+-	      ao_bits:	12,
+-	      ranges:	&cb_pcidda_ranges,
++	.name = "pci-dda02/12",
++	.status = 1,
++	.device_id = 0x20,
++	.ao_chans = 2,
++	.ao_bits = 12,
++	.ranges = &cb_pcidda_ranges,
+ 		},
+ 	{
+-	      name:	"pci-dda04/12",
+-	      status:	1,
+-	      device_id:0x21,
+-	      ao_chans:4,
+-	      ao_bits:	12,
+-	      ranges:	&cb_pcidda_ranges,
++	.name = "pci-dda04/12",
++	.status = 1,
++	.device_id = 0x21,
++	.ao_chans = 4,
++	.ao_bits = 12,
++	.ranges = &cb_pcidda_ranges,
+ 		},
+ 	{
+-	      name:	"pci-dda08/12",
+-	      status:	0,
+-	      device_id:0x22,
+-	      ao_chans:8,
+-	      ao_bits:	12,
+-	      ranges:	&cb_pcidda_ranges,
++	.name = "pci-dda08/12",
++	.status = 0,
++	.device_id = 0x22,
++	.ao_chans = 8,
++	.ao_bits = 12,
++	.ranges = &cb_pcidda_ranges,
+ 		},
+ 	{
+-	      name:	"pci-dda02/16",
+-	      status:	2,
+-	      device_id:0x23,
+-	      ao_chans:2,
+-	      ao_bits:	16,
+-	      ranges:	&cb_pcidda_ranges,
++	.name = "pci-dda02/16",
++	.status = 2,
++	.device_id = 0x23,
++	.ao_chans = 2,
++	.ao_bits = 16,
++	.ranges = &cb_pcidda_ranges,
+ 		},
+ 	{
+-	      name:	"pci-dda04/16",
+-	      status:	2,
+-	      device_id:0x24,
+-	      ao_chans:4,
+-	      ao_bits:	16,
+-	      ranges:	&cb_pcidda_ranges,
++	.name = "pci-dda04/16",
++	.status = 2,
++	.device_id = 0x24,
++	.ao_chans = 4,
++	.ao_bits = 16,
++	.ranges = &cb_pcidda_ranges,
+ 		},
+ 	{
+-	      name:	"pci-dda08/16",
+-	      status:	0,
+-	      device_id:0x25,
+-	      ao_chans:8,
+-	      ao_bits:	16,
+-	      ranges:	&cb_pcidda_ranges,
++	.name = "pci-dda08/16",
++	.status = 0,
++	.device_id = 0x25,
++	.ao_chans = 8,
++	.ao_bits = 16,
++	.ranges = &cb_pcidda_ranges,
+ 		},
+ };
+ 
+@@ -264,10 +264,10 @@ static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel,
+  * the device code.
+  */
+ static struct comedi_driver driver_cb_pcidda = {
+-      driver_name:"cb_pcidda",
+-      module:THIS_MODULE,
+-      attach:cb_pcidda_attach,
+-      detach:cb_pcidda_detach,
++	.driver_name = "cb_pcidda",
++	.module = THIS_MODULE,
++	.attach = cb_pcidda_attach,
++	.detach = cb_pcidda_detach,
+ };
+ 
+ /*
+diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c
+index ec7b2e21c053..799b5aded13c 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidio.c
++++ b/drivers/staging/comedi/drivers/cb_pcidio.c
+@@ -63,22 +63,22 @@ struct pcidio_board {
+ 
+ static const struct pcidio_board pcidio_boards[] = {
+ 	{
+-	      name:	"pci-dio24",
+-	      n_8255:	1,
+-	      pcicontroler_badrindex:1,
+-	      dioregs_badrindex:2,
++	.name = "pci-dio24",
++	.n_8255 = 1,
++	.pcicontroler_badrindex = 1,
++	.dioregs_badrindex = 2,
+ 		},
+ 	{
+-	      name:	"pci-dio24h",
+-	      n_8255:	1,
+-	      pcicontroler_badrindex:1,
+-	      dioregs_badrindex:2,
++	.name = "pci-dio24h",
++	.n_8255 = 1,
++	.pcicontroler_badrindex = 1,
++	.dioregs_badrindex = 2,
+ 		},
+ 	{
+-	      name:	"pci-dio48h",
+-	      n_8255:	2,
+-	      pcicontroler_badrindex:0,
+-	      dioregs_badrindex:1,
++	.name = "pci-dio48h",
++	.n_8255 = 2,
++	.pcicontroler_badrindex = 0,
++	.dioregs_badrindex = 1,
+ 		},
+ };
+ 
+@@ -130,10 +130,10 @@ struct pcidio_private {
+ static int pcidio_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int pcidio_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_cb_pcidio = {
+-      driver_name:"cb_pcidio",
+-      module:THIS_MODULE,
+-      attach:pcidio_attach,
+-      detach:pcidio_detach,
++	.driver_name = "cb_pcidio",
++	.module = THIS_MODULE,
++	.attach = pcidio_attach,
++	.detach = pcidio_detach,
+ 
+ /* It is not necessary to implement the following members if you are
+  * writing a driver for a ISA PnP or PCI card */
+@@ -158,9 +158,9 @@ static struct comedi_driver driver_cb_pcidio = {
+ /* The following fields should NOT be initialized if you are dealing
+  * with PCI devices
+  *
+- *         board_name:	pcidio_boards,
+- *         offset:	sizeof(struct pcidio_board),
+- *         num_names: 	sizeof(pcidio_boards) / sizeof(structpcidio_board),
++ *	.board_name = pcidio_boards,
++ *	.offset = sizeof(struct pcidio_board),
++ *	.num_names = sizeof(pcidio_boards) / sizeof(structpcidio_board),
+  */
+ 
+ };
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
+index 0e20eadac2d3..13f793b76c61 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
+@@ -102,21 +102,21 @@ struct cb_pcimdas_board {
+ 
+ static const struct cb_pcimdas_board cb_pcimdas_boards[] = {
+ 	{
+-	      name:	"PCIM-DAS1602/16",
+-	      device_id:0x56,
+-	      ai_se_chans:16,
+-	      ai_diff_chans:8,
+-	      ai_bits:	16,
+-	      ai_speed:10000,	/* ?? */
+-	      ao_nchan:2,
+-	      ao_bits:	12,
+-	      has_ao_fifo:0,	/* ?? */
+-	      ao_scan_speed:10000,
++	.name = "PCIM-DAS1602/16",
++	.device_id = 0x56,
++	.ai_se_chans = 16,
++	.ai_diff_chans = 8,
++	.ai_bits = 16,
++	.ai_speed = 10000,	/* ?? */
++	.ao_nchan = 2,
++	.ao_bits = 12,
++	.has_ao_fifo = 0,	/* ?? */
++	.ao_scan_speed = 10000,
+ 			/* ?? */
+-	      fifo_size:1024,
+-	      dio_bits:24,
+-	      has_dio:	1,
+-/* ranges:         &cb_pcimdas_ranges, */
++	.fifo_size = 1024,
++	.dio_bits = 24,
++	.has_dio = 1,
++/*	.ranges = &cb_pcimdas_ranges, */
+ 		},
+ };
+ 
+@@ -178,10 +178,10 @@ struct cb_pcimdas_private {
+ static int cb_pcimdas_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int cb_pcimdas_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_cb_pcimdas = {
+-      driver_name:"cb_pcimdas",
+-      module:THIS_MODULE,
+-      attach:cb_pcimdas_attach,
+-      detach:cb_pcimdas_detach,
++	.driver_name = "cb_pcimdas",
++	.module = THIS_MODULE,
++	.attach = cb_pcimdas_attach,
++	.detach = cb_pcimdas_detach,
+ };
+ 
+ static int cb_pcimdas_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
+index 0a1b20142953..3ce133c69e27 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
+@@ -118,15 +118,15 @@ enum DIO_METHODS {
+ 
+ static const struct board_struct boards[] = {
+ 	{
+-	      name:	"cb_pcimdda06-16",
+-	      device_id:PCI_ID_PCIM_DDA06_16,
+-	      ao_chans:6,
+-	      ao_bits:	16,
+-	      dio_chans:24,
+-	      dio_method:DIO_8255,
+-	      dio_offset:12,
+-	      regs_badrindex:3,
+-	      reg_sz:	16,
++	.name = "cb_pcimdda06-16",
++	.device_id = PCI_ID_PCIM_DDA06_16,
++	.ao_chans = 6,
++	.ao_bits = 16,
++	.dio_chans = 24,
++	.dio_method = DIO_8255,
++	.dio_offset = 12,
++	.regs_badrindex = 3,
++	.reg_sz = 16,
+ 		}
+ };
+ 
+@@ -184,10 +184,10 @@ struct board_private_struct {
+ static int attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int detach(struct comedi_device *dev);
+ static struct comedi_driver cb_pcimdda_driver = {
+-      driver_name:"cb_pcimdda",
+-      module:THIS_MODULE,
+-      attach:attach,
+-      detach:detach,
++	.driver_name = "cb_pcimdda",
++	.module = THIS_MODULE,
++	.attach = attach,
++	.detach = detach,
+ };
+ 
+ MODULE_AUTHOR("Calin A. Culianu ");
+diff --git a/drivers/staging/comedi/drivers/comedi_rt_timer.c b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+index ef8accd528c6..3b21f4c85879 100644
+--- a/drivers/staging/comedi/drivers/comedi_rt_timer.c
++++ b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+@@ -152,11 +152,11 @@ static int timer_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
+ static int timer_start_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
+ 
+ static struct comedi_driver driver_timer = {
+-      module:THIS_MODULE,
+-      driver_name:"comedi_rt_timer",
+-      attach:timer_attach,
+-      detach:timer_detach,
+-/* open:           timer_open, */
++	.module = THIS_MODULE,
++	.driver_name = "comedi_rt_timer",
++	.attach = timer_attach,
++	.detach = timer_detach,
++/*	.open = timer_open, */
+ };
+ 
+ COMEDI_INITCLEANUP(driver_timer);
+diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
+index 6c0d26e86c16..f2ad24841296 100644
+--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
++++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
+@@ -78,10 +78,10 @@ struct contec_private {
+ static int contec_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int contec_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_contec = {
+-      driver_name:"contec_pci_dio",
+-      module:THIS_MODULE,
+-      attach:contec_attach,
+-      detach:contec_detach,
++	.driver_name = "contec_pci_dio",
++	.module = THIS_MODULE,
++	.attach = contec_attach,
++	.detach = contec_detach,
+ };
+ 
+ /* Classic digital IO */
+diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
+index 794fbb24aa32..bac642c55cd5 100644
+--- a/drivers/staging/comedi/drivers/daqboard2000.c
++++ b/drivers/staging/comedi/drivers/daqboard2000.c
+@@ -300,10 +300,10 @@ static int daqboard2000_attach(struct comedi_device *dev, struct comedi_devconfi
+ static int daqboard2000_detach(struct comedi_device *dev);
+ 
+ static struct comedi_driver driver_daqboard2000 = {
+-      driver_name:"daqboard2000",
+-      module:THIS_MODULE,
+-      attach:daqboard2000_attach,
+-      detach:daqboard2000_detach,
++	.driver_name = "daqboard2000",
++	.module = THIS_MODULE,
++	.attach = daqboard2000_attach,
++	.detach = daqboard2000_detach,
+ };
+ 
+ struct daq200_boardtype {
+diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
+index d7760e4aec13..2fa883edfef0 100644
+--- a/drivers/staging/comedi/drivers/das08.c
++++ b/drivers/staging/comedi/drivers/das08.c
+@@ -248,211 +248,211 @@ static const int *const das08_gainlists[] = {
+ 
+ static const struct das08_board_struct das08_boards[] = {
+ 	{
+-	      name:	"isa-das08",	/*  cio-das08.pdf */
+-	      bustype:	isa,
+-	      ai:	das08_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_pg:	das08_pg_none,
+-	      ai_encoding:das08_encode12,
+-	      ao:	NULL,
+-	      ao_nbits:12,
+-	      di:	das08_di_rbits,
+-	      do_:	das08_do_wbits,
+-	      do_nchan:4,
+-	      i8255_offset:8,
+-	      i8254_offset:4,
+-	      iosize:	16,	/*  unchecked */
++	.name = "isa-das08",	/*  cio-das08.pdf */
++	.bustype = isa,
++	.ai = das08_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_pg = das08_pg_none,
++	.ai_encoding = das08_encode12,
++	.ao = NULL,
++	.ao_nbits = 12,
++	.di = das08_di_rbits,
++	.do_ = das08_do_wbits,
++	.do_nchan = 4,
++	.i8255_offset = 8,
++	.i8254_offset = 4,
++	.iosize = 16,	/*  unchecked */
+ 		},
+ 	{
+-	      name:	"das08-pgm",	/*  cio-das08pgx.pdf */
+-	      bustype:	isa,
+-	      ai:	das08_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_pg:	das08_pgm,
+-	      ai_encoding:das08_encode12,
+-	      ao:	NULL,
+-	      di:	das08_di_rbits,
+-	      do_:	das08_do_wbits,
+-	      do_nchan:4,
+-	      i8255_offset:0,
+-	      i8254_offset:0x04,
+-	      iosize:	16,	/*  unchecked */
++	.name = "das08-pgm",	/*  cio-das08pgx.pdf */
++	.bustype = isa,
++	.ai = das08_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_pg = das08_pgm,
++	.ai_encoding = das08_encode12,
++	.ao = NULL,
++	.di = das08_di_rbits,
++	.do_ = das08_do_wbits,
++	.do_nchan = 4,
++	.i8255_offset = 0,
++	.i8254_offset = 0x04,
++	.iosize = 16,	/*  unchecked */
+ 		},
+ 	{
+-	      name:	"das08-pgh",	/*  cio-das08pgx.pdf */
+-	      bustype:	isa,
+-	      ai:	das08_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_pg:	das08_pgh,
+-	      ai_encoding:das08_encode12,
+-	      ao:	NULL,
+-	      di:	das08_di_rbits,
+-	      do_:	das08_do_wbits,
+-	      do_nchan:4,
+-	      i8255_offset:0,
+-	      i8254_offset:0x04,
+-	      iosize:	16,	/*  unchecked */
++	.name = "das08-pgh",	/*  cio-das08pgx.pdf */
++	.bustype = isa,
++	.ai = das08_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_pg = das08_pgh,
++	.ai_encoding = das08_encode12,
++	.ao = NULL,
++	.di = das08_di_rbits,
++	.do_ = das08_do_wbits,
++	.do_nchan = 4,
++	.i8255_offset = 0,
++	.i8254_offset = 0x04,
++	.iosize = 16,	/*  unchecked */
+ 		},
+ 	{
+-	      name:	"das08-pgl",	/*  cio-das08pgx.pdf */
+-	      bustype:	isa,
+-	      ai:	das08_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_pg:	das08_pgl,
+-	      ai_encoding:das08_encode12,
+-	      ao:	NULL,
+-	      di:	das08_di_rbits,
+-	      do_:	das08_do_wbits,
+-	      do_nchan:4,
+-	      i8255_offset:0,
+-	      i8254_offset:0x04,
+-	      iosize:	16,	/*  unchecked */
++	.name = "das08-pgl",	/*  cio-das08pgx.pdf */
++	.bustype = isa,
++	.ai = das08_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_pg = das08_pgl,
++	.ai_encoding = das08_encode12,
++	.ao = NULL,
++	.di = das08_di_rbits,
++	.do_ = das08_do_wbits,
++	.do_nchan = 4,
++	.i8255_offset = 0,
++	.i8254_offset = 0x04,
++	.iosize = 16,	/*  unchecked */
+ 		},
+ 	{
+-	      name:	"das08-aoh",	/*  cio-das08_aox.pdf */
+-	      bustype:	isa,
+-	      ai:	das08_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_pg:	das08_pgh,
+-	      ai_encoding:das08_encode12,
+-	      ao:	das08ao_ao_winsn,	/*  8 */
+-	      ao_nbits:12,
+-	      di:	das08_di_rbits,
+-	      do_:	das08_do_wbits,
+-	      do_nchan:4,
+-	      i8255_offset:0x0c,
+-	      i8254_offset:0x04,
+-	      iosize:	16,	/*  unchecked */
++	.name = "das08-aoh",	/*  cio-das08_aox.pdf */
++	.bustype = isa,
++	.ai = das08_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_pg = das08_pgh,
++	.ai_encoding = das08_encode12,
++	.ao = das08ao_ao_winsn,	/*  8 */
++	.ao_nbits = 12,
++	.di = das08_di_rbits,
++	.do_ = das08_do_wbits,
++	.do_nchan = 4,
++	.i8255_offset = 0x0c,
++	.i8254_offset = 0x04,
++	.iosize = 16,	/*  unchecked */
+ 		},
+ 	{
+-	      name:	"das08-aol",	/*  cio-das08_aox.pdf */
+-	      bustype:	isa,
+-	      ai:	das08_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_pg:	das08_pgl,
+-	      ai_encoding:das08_encode12,
+-	      ao:	das08ao_ao_winsn,	/*  8 */
+-	      ao_nbits:12,
+-	      di:	das08_di_rbits,
+-	      do_:	das08_do_wbits,
+-	      do_nchan:4,
+-	      i8255_offset:0x0c,
+-	      i8254_offset:0x04,
+-	      iosize:	16,	/*  unchecked */
++	.name = "das08-aol",	/*  cio-das08_aox.pdf */
++	.bustype = isa,
++	.ai = das08_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_pg = das08_pgl,
++	.ai_encoding = das08_encode12,
++	.ao = das08ao_ao_winsn,	/*  8 */
++	.ao_nbits = 12,
++	.di = das08_di_rbits,
++	.do_ = das08_do_wbits,
++	.do_nchan = 4,
++	.i8255_offset = 0x0c,
++	.i8254_offset = 0x04,
++	.iosize = 16,	/*  unchecked */
+ 		},
+ 	{
+-	      name:	"das08-aom",	/*  cio-das08_aox.pdf */
+-	      bustype:	isa,
+-	      ai:	das08_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_pg:	das08_pgm,
+-	      ai_encoding:das08_encode12,
+-	      ao:	das08ao_ao_winsn,	/*  8 */
+-	      ao_nbits:12,
+-	      di:	das08_di_rbits,
+-	      do_:	das08_do_wbits,
+-	      do_nchan:4,
+-	      i8255_offset:0x0c,
+-	      i8254_offset:0x04,
+-	      iosize:	16,	/*  unchecked */
++	.name = "das08-aom",	/*  cio-das08_aox.pdf */
++	.bustype = isa,
++	.ai = das08_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_pg = das08_pgm,
++	.ai_encoding = das08_encode12,
++	.ao = das08ao_ao_winsn,	/*  8 */
++	.ao_nbits = 12,
++	.di = das08_di_rbits,
++	.do_ = das08_do_wbits,
++	.do_nchan = 4,
++	.i8255_offset = 0x0c,
++	.i8254_offset = 0x04,
++	.iosize = 16,	/*  unchecked */
+ 		},
+ 	{
+-	      name:	"das08/jr-ao",	/*  cio-das08-jr-ao.pdf */
+-	      bustype:	isa,
+-	      ai:	das08_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_pg:	das08_pg_none,
+-	      ai_encoding:das08_encode12,
+-	      ao:	das08jr_ao_winsn,
+-	      ao_nbits:12,
+-	      di:	das08jr_di_rbits,
+-	      do_:	das08jr_do_wbits,
+-	      do_nchan:8,
+-	      i8255_offset:0,
+-	      i8254_offset:0,
+-	      iosize:	16,	/*  unchecked */
++	.name = "das08/jr-ao",	/*  cio-das08-jr-ao.pdf */
++	.bustype = isa,
++	.ai = das08_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_pg = das08_pg_none,
++	.ai_encoding = das08_encode12,
++	.ao = das08jr_ao_winsn,
++	.ao_nbits = 12,
++	.di = das08jr_di_rbits,
++	.do_ = das08jr_do_wbits,
++	.do_nchan = 8,
++	.i8255_offset = 0,
++	.i8254_offset = 0,
++	.iosize = 16,	/*  unchecked */
+ 		},
+ 	{
+-	      name:	"das08jr-16-ao",	/*  cio-das08jr-16-ao.pdf */
+-	      bustype:	isa,
+-	      ai:	das08_ai_rinsn,
+-	      ai_nbits:16,
+-	      ai_pg:	das08_pg_none,
+-	      ai_encoding:das08_encode12,
+-	      ao:	das08jr_ao_winsn,
+-	      ao_nbits:16,
+-	      di:	das08jr_di_rbits,
+-	      do_:	das08jr_do_wbits,
+-	      do_nchan:8,
+-	      i8255_offset:0,
+-	      i8254_offset:0x04,
+-	      iosize:	16,	/*  unchecked */
++	.name = "das08jr-16-ao",	/*  cio-das08jr-16-ao.pdf */
++	.bustype = isa,
++	.ai = das08_ai_rinsn,
++	.ai_nbits = 16,
++	.ai_pg = das08_pg_none,
++	.ai_encoding = das08_encode12,
++	.ao = das08jr_ao_winsn,
++	.ao_nbits = 16,
++	.di = das08jr_di_rbits,
++	.do_ = das08jr_do_wbits,
++	.do_nchan = 8,
++	.i8255_offset = 0,
++	.i8254_offset = 0x04,
++	.iosize = 16,	/*  unchecked */
+ 		},
+ #ifdef CONFIG_COMEDI_PCI
+ 	{
+-	      name:	"das08",	/*  pci-das08 */
+-	      id:	PCI_DEVICE_ID_PCIDAS08,
+-	      bustype:	pci,
+-	      ai:	das08_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_pg:	das08_bipolar5,
+-	      ai_encoding:das08_encode12,
+-	      ao:	NULL,
+-	      ao_nbits:0,
+-	      di:	das08_di_rbits,
+-	      do_:	das08_do_wbits,
+-	      do_nchan:4,
+-	      i8255_offset:0,
+-	      i8254_offset:4,
+-	      iosize:	8,
++	.name = "das08",	/*  pci-das08 */
++	.id = PCI_DEVICE_ID_PCIDAS08,
++	.bustype = pci,
++	.ai = das08_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_pg = das08_bipolar5,
++	.ai_encoding = das08_encode12,
++	.ao = NULL,
++	.ao_nbits = 0,
++	.di = das08_di_rbits,
++	.do_ = das08_do_wbits,
++	.do_nchan = 4,
++	.i8255_offset = 0,
++	.i8254_offset = 4,
++	.iosize = 8,
+ 		},
+ #endif
+ 	{
+-	      name:	"pc104-das08",
+-	      bustype:	pc104,
+-	      ai:	das08_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_pg:	das08_pg_none,
+-	      ai_encoding:das08_encode12,
+-	      ao:	NULL,
+-	      ao_nbits:0,
+-	      di:	das08_di_rbits,
+-	      do_:	das08_do_wbits,
+-	      do_nchan:4,
+-	      i8255_offset:0,
+-	      i8254_offset:4,
+-	      iosize:	16,	/*  unchecked */
++	.name = "pc104-das08",
++	.bustype = pc104,
++	.ai = das08_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_pg = das08_pg_none,
++	.ai_encoding = das08_encode12,
++	.ao = NULL,
++	.ao_nbits = 0,
++	.di = das08_di_rbits,
++	.do_ = das08_do_wbits,
++	.do_nchan = 4,
++	.i8255_offset = 0,
++	.i8254_offset = 4,
++	.iosize = 16,	/*  unchecked */
+ 		},
+ #if 0
+ 	{
+-	      name:	"das08/f",
++	.name = "das08/f",
+ 		},
+ 	{
+-	      name:	"das08jr",
++	.name = "das08jr",
+ 		},
+ #endif
+ 	{
+-	      name:	"das08jr/16",
+-	      bustype:	isa,
+-	      ai:	das08_ai_rinsn,
+-	      ai_nbits:16,
+-	      ai_pg:	das08_pg_none,
+-	      ai_encoding:das08_encode16,
+-	      ao:	NULL,
+-	      ao_nbits:0,
+-	      di:	das08jr_di_rbits,
+-	      do_:	das08jr_do_wbits,
+-	      do_nchan:8,
+-	      i8255_offset:0,
+-	      i8254_offset:0,
+-	      iosize:	16,	/*  unchecked */
++	.name = "das08jr/16",
++	.bustype = isa,
++	.ai = das08_ai_rinsn,
++	.ai_nbits = 16,
++	.ai_pg = das08_pg_none,
++	.ai_encoding = das08_encode16,
++	.ao = NULL,
++	.ao_nbits = 0,
++	.di = das08jr_di_rbits,
++	.do_ = das08jr_do_wbits,
++	.do_nchan = 8,
++	.i8255_offset = 0,
++	.i8254_offset = 0,
++	.iosize = 16,	/*  unchecked */
+ 		},
+ #if 0
+ 	{
+-	      name:	"das48-pga",	/*  cio-das48-pga.pdf */
++	.name = "das48-pga",	/*  cio-das48-pga.pdf */
+ 		},
+ 	{
+-	      name:	"das08-pga-g2",	/*  a KM board */
++	.name = "das08-pga-g2",	/*  a KM board */
+ 		},
+ #endif
+ };
+@@ -460,39 +460,39 @@ static const struct das08_board_struct das08_boards[] = {
+ #ifdef CONFIG_COMEDI_PCMCIA
+ struct das08_board_struct das08_cs_boards[NUM_DAS08_CS_BOARDS] = {
+ 	{
+-	      name:	"pcm-das08",
+-	      id:	0x0,	/*  XXX */
+-	      bustype:	pcmcia,
+-	      ai:	das08_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_pg:	das08_bipolar5,
+-	      ai_encoding:das08_pcm_encode12,
+-	      ao:	NULL,
+-	      ao_nbits:0,
+-	      di:	das08_di_rbits,
+-	      do_:	das08_do_wbits,
+-	      do_nchan:3,
+-	      i8255_offset:0,
+-	      i8254_offset:0,
+-	      iosize:	16,
++	.name = "pcm-das08",
++	.id = 0x0,	/*  XXX */
++	.bustype = pcmcia,
++	.ai = das08_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_pg = das08_bipolar5,
++	.ai_encoding = das08_pcm_encode12,
++	.ao = NULL,
++	.ao_nbits = 0,
++	.di = das08_di_rbits,
++	.do_ = das08_do_wbits,
++	.do_nchan = 3,
++	.i8255_offset = 0,
++	.i8254_offset = 0,
++	.iosize = 16,
+ 		},
+ 	/*  duplicate so driver name can be used also */
+ 	{
+-	      name:	"das08_cs",
+-	      id:	0x0,	/*  XXX */
+-	      bustype:	pcmcia,
+-	      ai:	das08_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_pg:	das08_bipolar5,
+-	      ai_encoding:das08_pcm_encode12,
+-	      ao:	NULL,
+-	      ao_nbits:0,
+-	      di:	das08_di_rbits,
+-	      do_:	das08_do_wbits,
+-	      do_nchan:3,
+-	      i8255_offset:0,
+-	      i8254_offset:0,
+-	      iosize:	16,
++	.name = "das08_cs",
++	.id = 0x0,	/*  XXX */
++	.bustype = pcmcia,
++	.ai = das08_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_pg = das08_bipolar5,
++	.ai_encoding = das08_pcm_encode12,
++	.ao = NULL,
++	.ao_nbits = 0,
++	.di = das08_di_rbits,
++	.do_ = das08_do_wbits,
++	.do_nchan = 3,
++	.i8255_offset = 0,
++	.i8254_offset = 0,
++	.iosize = 16,
+ 		},
+ };
+ #endif
+@@ -830,14 +830,14 @@ static int das08_counter_config(struct comedi_device *dev, struct comedi_subdevi
+ static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ 
+ static struct comedi_driver driver_das08 = {
+-      driver_name: DRV_NAME,
+-      module:THIS_MODULE,
+-      attach:das08_attach,
+-      detach:das08_common_detach,
+-      board_name:&das08_boards[0].name,
+-      num_names:sizeof(das08_boards) /
++	.driver_name = DRV_NAME,
++	.module = THIS_MODULE,
++	.attach = das08_attach,
++	.detach = das08_common_detach,
++	.board_name = &das08_boards[0].name,
++	.num_names = sizeof(das08_boards) /
+ 		sizeof(struct das08_board_struct),
+-      offset:sizeof(struct das08_board_struct),
++	.offset = sizeof(struct das08_board_struct),
+ };
+ 
+ int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
+diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
+index a97739612f84..8e4464100e1e 100644
+--- a/drivers/staging/comedi/drivers/das08_cs.c
++++ b/drivers/staging/comedi/drivers/das08_cs.c
+@@ -59,14 +59,14 @@ static struct pcmcia_device *cur_dev = NULL;
+ static int das08_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ 
+ static struct comedi_driver driver_das08_cs = {
+-      driver_name:"das08_cs",
+-      module:THIS_MODULE,
+-      attach:das08_cs_attach,
+-      detach:das08_common_detach,
+-      board_name:&das08_cs_boards[0].name,
+-      num_names:sizeof(das08_cs_boards) /
++	.driver_name = "das08_cs",
++	.module = THIS_MODULE,
++	.attach = das08_cs_attach,
++	.detach = das08_common_detach,
++	.board_name = &das08_cs_boards[0].name,
++	.num_names = sizeof(das08_cs_boards) /
+ 		sizeof(struct das08_board_struct),
+-      offset:sizeof(struct das08_board_struct),
++	.offset = sizeof(struct das08_board_struct),
+ };
+ 
+ static int das08_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
+index 090225128ce5..4433f6446b3f 100644
+--- a/drivers/staging/comedi/drivers/das16.c
++++ b/drivers/staging/comedi/drivers/das16.c
+@@ -375,323 +375,323 @@ struct das16_board {
+ 
+ static const struct das16_board das16_boards[] = {
+ 	{
+-	      name:	"das-16",
+-	      ai:	das16_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_speed:15000,
+-	      ai_pg:	das16_pg_none,
+-	      ao:	das16_ao_winsn,
+-	      ao_nbits:12,
+-	      di:	das16_di_rbits,
+-	      do_:	das16_do_wbits,
+-	      i8255_offset:0x10,
+-	      i8254_offset:0x0c,
+-	      size:	0x14,
+-	      id:	0x00,
++	.name = "das-16",
++	.ai = das16_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_speed = 15000,
++	.ai_pg = das16_pg_none,
++	.ao = das16_ao_winsn,
++	.ao_nbits = 12,
++	.di = das16_di_rbits,
++	.do_ = das16_do_wbits,
++	.i8255_offset = 0x10,
++	.i8254_offset = 0x0c,
++	.size = 0x14,
++	.id = 0x00,
+ 		},
+ 	{
+-	      name:	"das-16g",
+-	      ai:	das16_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_speed:15000,
+-	      ai_pg:	das16_pg_none,
+-	      ao:	das16_ao_winsn,
+-	      ao_nbits:12,
+-	      di:	das16_di_rbits,
+-	      do_:	das16_do_wbits,
+-	      i8255_offset:0x10,
+-	      i8254_offset:0x0c,
+-	      size:	0x14,
+-	      id:	0x00,
++	.name = "das-16g",
++	.ai = das16_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_speed = 15000,
++	.ai_pg = das16_pg_none,
++	.ao = das16_ao_winsn,
++	.ao_nbits = 12,
++	.di = das16_di_rbits,
++	.do_ = das16_do_wbits,
++	.i8255_offset = 0x10,
++	.i8254_offset = 0x0c,
++	.size = 0x14,
++	.id = 0x00,
+ 		},
+ 	{
+-	      name:	"das-16f",
+-	      ai:	das16_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_speed:8500,
+-	      ai_pg:	das16_pg_none,
+-	      ao:	das16_ao_winsn,
+-	      ao_nbits:12,
+-	      di:	das16_di_rbits,
+-	      do_:	das16_do_wbits,
+-	      i8255_offset:0x10,
+-	      i8254_offset:0x0c,
+-	      size:	0x14,
+-	      id:	0x00,
++	.name = "das-16f",
++	.ai = das16_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_speed = 8500,
++	.ai_pg = das16_pg_none,
++	.ao = das16_ao_winsn,
++	.ao_nbits = 12,
++	.di = das16_di_rbits,
++	.do_ = das16_do_wbits,
++	.i8255_offset = 0x10,
++	.i8254_offset = 0x0c,
++	.size = 0x14,
++	.id = 0x00,
+ 		},
+ 	{
+-	      name:	"cio-das16",	/*  cio-das16.pdf */
+-	      ai:	das16_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_speed:20000,
+-	      ai_pg:	das16_pg_none,
+-	      ao:	das16_ao_winsn,
+-	      ao_nbits:12,
+-	      di:	das16_di_rbits,
+-	      do_:	das16_do_wbits,
+-	      i8255_offset:0x10,
+-	      i8254_offset:0x0c,
+-	      size:	0x14,
+-	      id:	0x80,
++	.name = "cio-das16",	/*  cio-das16.pdf */
++	.ai = das16_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_speed = 20000,
++	.ai_pg = das16_pg_none,
++	.ao = das16_ao_winsn,
++	.ao_nbits = 12,
++	.di = das16_di_rbits,
++	.do_ = das16_do_wbits,
++	.i8255_offset = 0x10,
++	.i8254_offset = 0x0c,
++	.size = 0x14,
++	.id = 0x80,
+ 		},
+ 	{
+-	      name:	"cio-das16/f",	/*  das16.pdf */
+-	      ai:	das16_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_speed:10000,
+-	      ai_pg:	das16_pg_none,
+-	      ao:	das16_ao_winsn,
+-	      ao_nbits:12,
+-	      di:	das16_di_rbits,
+-	      do_:	das16_do_wbits,
+-	      i8255_offset:0x10,
+-	      i8254_offset:0x0c,
+-	      size:	0x14,
+-	      id:	0x80,
++	.name = "cio-das16/f",	/*  das16.pdf */
++	.ai = das16_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_speed = 10000,
++	.ai_pg = das16_pg_none,
++	.ao = das16_ao_winsn,
++	.ao_nbits = 12,
++	.di = das16_di_rbits,
++	.do_ = das16_do_wbits,
++	.i8255_offset = 0x10,
++	.i8254_offset = 0x0c,
++	.size = 0x14,
++	.id = 0x80,
+ 		},
+ 	{
+-	      name:	"cio-das16/jr",	/*  cio-das16jr.pdf */
+-	      ai:	das16_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_speed:7692,
+-	      ai_pg:	das16_pg_16jr,
+-	      ao:	NULL,
+-	      di:	das16_di_rbits,
+-	      do_:	das16_do_wbits,
+-	      i8255_offset:0,
+-	      i8254_offset:0x0c,
+-	      size:	0x10,
+-	      id:	0x00,
++	.name = "cio-das16/jr",	/*  cio-das16jr.pdf */
++	.ai = das16_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_speed = 7692,
++	.ai_pg = das16_pg_16jr,
++	.ao = NULL,
++	.di = das16_di_rbits,
++	.do_ = das16_do_wbits,
++	.i8255_offset = 0,
++	.i8254_offset = 0x0c,
++	.size = 0x10,
++	.id = 0x00,
+ 		},
+ 	{
+-	      name:	"pc104-das16jr",	/*  pc104-das16jr_xx.pdf */
+-	      ai:	das16_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_speed:3300,
+-	      ai_pg:	das16_pg_16jr,
+-	      ao:	NULL,
+-	      di:	das16_di_rbits,
+-	      do_:	das16_do_wbits,
+-	      i8255_offset:0,
+-	      i8254_offset:0x0c,
+-	      size:	0x10,
+-	      id:	0x00,
++	.name = "pc104-das16jr",	/*  pc104-das16jr_xx.pdf */
++	.ai = das16_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_speed = 3300,
++	.ai_pg = das16_pg_16jr,
++	.ao = NULL,
++	.di = das16_di_rbits,
++	.do_ = das16_do_wbits,
++	.i8255_offset = 0,
++	.i8254_offset = 0x0c,
++	.size = 0x10,
++	.id = 0x00,
+ 		},
+ 	{
+-	      name:	"cio-das16jr/16",	/*  cio-das16jr_16.pdf */
+-	      ai:	das16_ai_rinsn,
+-	      ai_nbits:16,
+-	      ai_speed:10000,
+-	      ai_pg:	das16_pg_16jr_16,
+-	      ao:	NULL,
+-	      di:	das16_di_rbits,
+-	      do_:	das16_do_wbits,
+-	      i8255_offset:0,
+-	      i8254_offset:0x0c,
+-	      size:	0x10,
+-	      id:	0x00,
++	.name = "cio-das16jr/16",	/*  cio-das16jr_16.pdf */
++	.ai = das16_ai_rinsn,
++	.ai_nbits = 16,
++	.ai_speed = 10000,
++	.ai_pg = das16_pg_16jr_16,
++	.ao = NULL,
++	.di = das16_di_rbits,
++	.do_ = das16_do_wbits,
++	.i8255_offset = 0,
++	.i8254_offset = 0x0c,
++	.size = 0x10,
++	.id = 0x00,
+ 		},
+ 	{
+-	      name:	"pc104-das16jr/16",	/*  pc104-das16jr_xx.pdf */
+-	      ai:	das16_ai_rinsn,
+-	      ai_nbits:16,
+-	      ai_speed:10000,
+-	      ai_pg:	das16_pg_16jr_16,
+-	      ao:	NULL,
+-	      di:	das16_di_rbits,
+-	      do_:	das16_do_wbits,
+-	      i8255_offset:0,
+-	      i8254_offset:0x0c,
+-	      size:	0x10,
+-	      id:	0x00,
++	.name = "pc104-das16jr/16",	/*  pc104-das16jr_xx.pdf */
++	.ai = das16_ai_rinsn,
++	.ai_nbits = 16,
++	.ai_speed = 10000,
++	.ai_pg = das16_pg_16jr_16,
++	.ao = NULL,
++	.di = das16_di_rbits,
++	.do_ = das16_do_wbits,
++	.i8255_offset = 0,
++	.i8254_offset = 0x0c,
++	.size = 0x10,
++	.id = 0x00,
+ 		},
+ 	{
+-	      name:	"das-1201",	/*  4924.pdf (keithley user's manual) */
+-	      ai:	das16_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_speed:20000,
+-	      ai_pg:	das16_pg_none,
+-	      ao:	NULL,
+-	      di:	das16_di_rbits,
+-	      do_:	das16_do_wbits,
+-	      i8255_offset:0x400,
+-	      i8254_offset:0x0c,
+-	      size:	0x408,
+-	      id:	0x20,
++	.name = "das-1201",	/*  4924.pdf (keithley user's manual) */
++	.ai = das16_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_speed = 20000,
++	.ai_pg = das16_pg_none,
++	.ao = NULL,
++	.di = das16_di_rbits,
++	.do_ = das16_do_wbits,
++	.i8255_offset = 0x400,
++	.i8254_offset = 0x0c,
++	.size = 0x408,
++	.id = 0x20,
+ 		},
+ 	{
+-	      name:	"das-1202",	/*  4924.pdf (keithley user's manual) */
+-	      ai:	das16_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_speed:10000,
+-	      ai_pg:	das16_pg_none,
+-	      ao:	NULL,
+-	      di:	das16_di_rbits,
+-	      do_:	das16_do_wbits,
+-	      i8255_offset:0x400,
+-	      i8254_offset:0x0c,
+-	      size:	0x408,
+-	      id:	0x20,
++	.name = "das-1202",	/*  4924.pdf (keithley user's manual) */
++	.ai = das16_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_speed = 10000,
++	.ai_pg = das16_pg_none,
++	.ao = NULL,
++	.di = das16_di_rbits,
++	.do_ = das16_do_wbits,
++	.i8255_offset = 0x400,
++	.i8254_offset = 0x0c,
++	.size = 0x408,
++	.id = 0x20,
+ 		},
+ 	{
+-	      name:	"das-1401",	/*  4919.pdf and 4922.pdf (keithley user's manual) */
+-	      ai:	das16_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_speed:10000,
+-	      ai_pg:	das16_pg_1601,
+-	      ao:	NULL,
+-	      di:	das16_di_rbits,
+-	      do_:	das16_do_wbits,
+-	      i8255_offset:0x0,
+-	      i8254_offset:0x0c,
+-	      size:	0x408,
+-	      id:	0xc0	/*  4919.pdf says id bits are 0xe0, 4922.pdf says 0xc0 */
++	.name = "das-1401",	/*  4919.pdf and 4922.pdf (keithley user's manual) */
++	.ai = das16_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_speed = 10000,
++	.ai_pg = das16_pg_1601,
++	.ao = NULL,
++	.di = das16_di_rbits,
++	.do_ = das16_do_wbits,
++	.i8255_offset = 0x0,
++	.i8254_offset = 0x0c,
++	.size = 0x408,
++	.id = 0xc0	/*  4919.pdf says id bits are 0xe0, 4922.pdf says 0xc0 */
+ 		},
+ 	{
+-	      name:	"das-1402",	/*  4919.pdf and 4922.pdf (keithley user's manual) */
+-	      ai:	das16_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_speed:10000,
+-	      ai_pg:	das16_pg_1602,
+-	      ao:	NULL,
+-	      di:	das16_di_rbits,
+-	      do_:	das16_do_wbits,
+-	      i8255_offset:0x0,
+-	      i8254_offset:0x0c,
+-	      size:	0x408,
+-	      id:	0xc0	/*  4919.pdf says id bits are 0xe0, 4922.pdf says 0xc0 */
++	.name = "das-1402",	/*  4919.pdf and 4922.pdf (keithley user's manual) */
++	.ai = das16_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_speed = 10000,
++	.ai_pg = das16_pg_1602,
++	.ao = NULL,
++	.di = das16_di_rbits,
++	.do_ = das16_do_wbits,
++	.i8255_offset = 0x0,
++	.i8254_offset = 0x0c,
++	.size = 0x408,
++	.id = 0xc0	/*  4919.pdf says id bits are 0xe0, 4922.pdf says 0xc0 */
+ 		},
+ 	{
+-	      name:	"das-1601",	/*  4919.pdf */
+-	      ai:	das16_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_speed:10000,
+-	      ai_pg:	das16_pg_1601,
+-	      ao:	das16_ao_winsn,
+-	      ao_nbits:12,
+-	      di:	das16_di_rbits,
+-	      do_:	das16_do_wbits,
+-	      i8255_offset:0x400,
+-	      i8254_offset:0x0c,
+-	      size:	0x408,
+-      id:	0xc0},
++	.name = "das-1601",	/*  4919.pdf */
++	.ai = das16_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_speed = 10000,
++	.ai_pg = das16_pg_1601,
++	.ao = das16_ao_winsn,
++	.ao_nbits = 12,
++	.di = das16_di_rbits,
++	.do_ = das16_do_wbits,
++	.i8255_offset = 0x400,
++	.i8254_offset = 0x0c,
++	.size = 0x408,
++	.id = 0xc0},
+ 	{
+-	      name:	"das-1602",	/*  4919.pdf */
+-	      ai:	das16_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_speed:10000,
+-	      ai_pg:	das16_pg_1602,
+-	      ao:	das16_ao_winsn,
+-	      ao_nbits:12,
+-	      di:	das16_di_rbits,
+-	      do_:	das16_do_wbits,
+-	      i8255_offset:0x400,
+-	      i8254_offset:0x0c,
+-	      size:	0x408,
+-      id:	0xc0},
++	.name = "das-1602",	/*  4919.pdf */
++	.ai = das16_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_speed = 10000,
++	.ai_pg = das16_pg_1602,
++	.ao = das16_ao_winsn,
++	.ao_nbits = 12,
++	.di = das16_di_rbits,
++	.do_ = das16_do_wbits,
++	.i8255_offset = 0x400,
++	.i8254_offset = 0x0c,
++	.size = 0x408,
++	.id = 0xc0},
+ 	{
+-	      name:	"cio-das1401/12",	/*  cio-das1400_series.pdf */
+-	      ai:	das16_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_speed:6250,
+-	      ai_pg:	das16_pg_1601,
+-	      ao:	NULL,
+-	      di:	das16_di_rbits,
+-	      do_:	das16_do_wbits,
+-	      i8255_offset:0,
+-	      i8254_offset:0x0c,
+-	      size:	0x408,
+-      id:	0xc0},
++	.name = "cio-das1401/12",	/*  cio-das1400_series.pdf */
++	.ai = das16_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_speed = 6250,
++	.ai_pg = das16_pg_1601,
++	.ao = NULL,
++	.di = das16_di_rbits,
++	.do_ = das16_do_wbits,
++	.i8255_offset = 0,
++	.i8254_offset = 0x0c,
++	.size = 0x408,
++	.id = 0xc0},
+ 	{
+-	      name:	"cio-das1402/12",	/*  cio-das1400_series.pdf */
+-	      ai:	das16_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_speed:6250,
+-	      ai_pg:	das16_pg_1602,
+-	      ao:	NULL,
+-	      di:	das16_di_rbits,
+-	      do_:	das16_do_wbits,
+-	      i8255_offset:0,
+-	      i8254_offset:0x0c,
+-	      size:	0x408,
+-      id:	0xc0},
++	.name = "cio-das1402/12",	/*  cio-das1400_series.pdf */
++	.ai = das16_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_speed = 6250,
++	.ai_pg = das16_pg_1602,
++	.ao = NULL,
++	.di = das16_di_rbits,
++	.do_ = das16_do_wbits,
++	.i8255_offset = 0,
++	.i8254_offset = 0x0c,
++	.size = 0x408,
++	.id = 0xc0},
+ 	{
+-	      name:	"cio-das1402/16",	/*  cio-das1400_series.pdf */
+-	      ai:	das16_ai_rinsn,
+-	      ai_nbits:16,
+-	      ai_speed:10000,
+-	      ai_pg:	das16_pg_1602,
+-	      ao:	NULL,
+-	      di:	das16_di_rbits,
+-	      do_:	das16_do_wbits,
+-	      i8255_offset:0,
+-	      i8254_offset:0x0c,
+-	      size:	0x408,
+-      id:	0xc0},
++	.name = "cio-das1402/16",	/*  cio-das1400_series.pdf */
++	.ai = das16_ai_rinsn,
++	.ai_nbits = 16,
++	.ai_speed = 10000,
++	.ai_pg = das16_pg_1602,
++	.ao = NULL,
++	.di = das16_di_rbits,
++	.do_ = das16_do_wbits,
++	.i8255_offset = 0,
++	.i8254_offset = 0x0c,
++	.size = 0x408,
++	.id = 0xc0},
+ 	{
+-	      name:	"cio-das1601/12",	/*  cio-das160x-1x.pdf */
+-	      ai:	das16_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_speed:6250,
+-	      ai_pg:	das16_pg_1601,
+-	      ao:	das16_ao_winsn,
+-	      ao_nbits:12,
+-	      di:	das16_di_rbits,
+-	      do_:	das16_do_wbits,
+-	      i8255_offset:0x400,
+-	      i8254_offset:0x0c,
+-	      size:	0x408,
+-      id:	0xc0},
++	.name = "cio-das1601/12",	/*  cio-das160x-1x.pdf */
++	.ai = das16_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_speed = 6250,
++	.ai_pg = das16_pg_1601,
++	.ao = das16_ao_winsn,
++	.ao_nbits = 12,
++	.di = das16_di_rbits,
++	.do_ = das16_do_wbits,
++	.i8255_offset = 0x400,
++	.i8254_offset = 0x0c,
++	.size = 0x408,
++	.id = 0xc0},
+ 	{
+-	      name:	"cio-das1602/12",	/*  cio-das160x-1x.pdf */
+-	      ai:	das16_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_speed:10000,
+-	      ai_pg:	das16_pg_1602,
+-	      ao:	das16_ao_winsn,
+-	      ao_nbits:12,
+-	      di:	das16_di_rbits,
+-	      do_:	das16_do_wbits,
+-	      i8255_offset:0x400,
+-	      i8254_offset:0x0c,
+-	      size:	0x408,
+-      id:	0xc0},
++	.name = "cio-das1602/12",	/*  cio-das160x-1x.pdf */
++	.ai = das16_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_speed = 10000,
++	.ai_pg = das16_pg_1602,
++	.ao = das16_ao_winsn,
++	.ao_nbits = 12,
++	.di = das16_di_rbits,
++	.do_ = das16_do_wbits,
++	.i8255_offset = 0x400,
++	.i8254_offset = 0x0c,
++	.size = 0x408,
++	.id = 0xc0},
+ 	{
+-	      name:	"cio-das1602/16",	/*  cio-das160x-1x.pdf */
+-	      ai:	das16_ai_rinsn,
+-	      ai_nbits:16,
+-	      ai_speed:10000,
+-	      ai_pg:	das16_pg_1602,
+-	      ao:	das16_ao_winsn,
+-	      ao_nbits:12,
+-	      di:	das16_di_rbits,
+-	      do_:	das16_do_wbits,
+-	      i8255_offset:0x400,
+-	      i8254_offset:0x0c,
+-	      size:	0x408,
+-      id:	0xc0},
++	.name = "cio-das1602/16",	/*  cio-das160x-1x.pdf */
++	.ai = das16_ai_rinsn,
++	.ai_nbits = 16,
++	.ai_speed = 10000,
++	.ai_pg = das16_pg_1602,
++	.ao = das16_ao_winsn,
++	.ao_nbits = 12,
++	.di = das16_di_rbits,
++	.do_ = das16_do_wbits,
++	.i8255_offset = 0x400,
++	.i8254_offset = 0x0c,
++	.size = 0x408,
++	.id = 0xc0},
+ 	{
+-	      name:	"cio-das16/330",	/*  ? */
+-	      ai:	das16_ai_rinsn,
+-	      ai_nbits:12,
+-	      ai_speed:3030,
+-	      ai_pg:	das16_pg_16jr,
+-	      ao:	NULL,
+-	      di:	das16_di_rbits,
+-	      do_:	das16_do_wbits,
+-	      i8255_offset:0,
+-	      i8254_offset:0x0c,
+-	      size:	0x14,
+-      id:	0xf0},
++	.name = "cio-das16/330",	/*  ? */
++	.ai = das16_ai_rinsn,
++	.ai_nbits = 12,
++	.ai_speed = 3030,
++	.ai_pg = das16_pg_16jr,
++	.ao = NULL,
++	.di = das16_di_rbits,
++	.do_ = das16_do_wbits,
++	.i8255_offset = 0,
++	.i8254_offset = 0x0c,
++	.size = 0x14,
++	.id = 0xf0},
+ #if 0
+ 	{
+-	      name:	"das16/330i",	/*  ? */
++	.name = "das16/330i",	/*  ? */
+ 		},
+ 	{
+-	      name:	"das16/jr/ctr5",	/*  ? */
++	.name = "das16/jr/ctr5",	/*  ? */
+ 		},
+ 	{
+-	      name:	"cio-das16/m1/16",	/*  cio-das16_m1_16.pdf, this board is a bit quirky, no dma */
++	.name = "cio-das16/m1/16",	/*  cio-das16_m1_16.pdf, this board is a bit quirky, no dma */
+ 		},
+ #endif
+ };
+@@ -701,13 +701,13 @@ static const struct das16_board das16_boards[] = {
+ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int das16_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_das16 = {
+-      driver_name:"das16",
+-      module:THIS_MODULE,
+-      attach:das16_attach,
+-      detach:das16_detach,
+-      board_name:&das16_boards[0].name,
+-      num_names:n_das16_boards,
+-      offset:sizeof(das16_boards[0]),
++	.driver_name = "das16",
++	.module = THIS_MODULE,
++	.attach = das16_attach,
++	.detach = das16_detach,
++	.board_name = &das16_boards[0].name,
++	.num_names = n_das16_boards,
++	.offset = sizeof(das16_boards[0]),
+ };
+ 
+ #define DAS16_TIMEOUT 1000
+diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
+index 00aa30471cf8..031d6307c09d 100644
+--- a/drivers/staging/comedi/drivers/das16m1.c
++++ b/drivers/staging/comedi/drivers/das16m1.c
+@@ -159,8 +159,8 @@ struct das16m1_board {
+ 
+ static const struct das16m1_board das16m1_boards[] = {
+ 	{
+-	      name:	"cio-das16/m1",	/*  CIO-DAS16_M1.pdf */
+-	      ai_speed:1000,	/*  1MHz max speed */
++	.name = "cio-das16/m1",	/*  CIO-DAS16_M1.pdf */
++	.ai_speed = 1000,	/*  1MHz max speed */
+ 		},
+ };
+ 
+@@ -169,13 +169,13 @@ static const struct das16m1_board das16m1_boards[] = {
+ static int das16m1_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int das16m1_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_das16m1 = {
+-      driver_name:"das16m1",
+-      module:THIS_MODULE,
+-      attach:das16m1_attach,
+-      detach:das16m1_detach,
+-      board_name:&das16m1_boards[0].name,
+-      num_names:das16m1_num_boards,
+-      offset:sizeof(das16m1_boards[0]),
++	.driver_name = "das16m1",
++	.module = THIS_MODULE,
++	.attach = das16m1_attach,
++	.detach = das16m1_detach,
++	.board_name = &das16m1_boards[0].name,
++	.num_names = das16m1_num_boards,
++	.offset = sizeof(das16m1_boards[0]),
+ };
+ 
+ struct das16m1_private_struct {
+diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
+index 2112783d37e2..b420e7649bc9 100644
+--- a/drivers/staging/comedi/drivers/das1800.c
++++ b/drivers/staging/comedi/drivers/das1800.c
+@@ -259,202 +259,202 @@ struct das1800_board {
+  */
+ static const struct das1800_board das1800_boards[] = {
+ 	{
+-	      name:	"das-1701st",
+-	      ai_speed:6250,
+-	      resolution:12,
+-	      qram_len:256,
+-	      common:	1,
+-	      do_n_chan:4,
+-	      ao_ability:0,
+-	      ao_n_chan:0,
+-	      range_ai:&range_ai_das1801,
++	.name = "das-1701st",
++	.ai_speed = 6250,
++	.resolution = 12,
++	.qram_len = 256,
++	.common = 1,
++	.do_n_chan = 4,
++	.ao_ability = 0,
++	.ao_n_chan = 0,
++	.range_ai = &range_ai_das1801,
+ 		},
+ 	{
+-	      name:	"das-1701st-da",
+-	      ai_speed:6250,
+-	      resolution:12,
+-	      qram_len:256,
+-	      common:	1,
+-	      do_n_chan:4,
+-	      ao_ability:1,
+-	      ao_n_chan:4,
+-	      range_ai:&range_ai_das1801,
++	.name = "das-1701st-da",
++	.ai_speed = 6250,
++	.resolution = 12,
++	.qram_len = 256,
++	.common = 1,
++	.do_n_chan = 4,
++	.ao_ability = 1,
++	.ao_n_chan = 4,
++	.range_ai = &range_ai_das1801,
+ 		},
+ 	{
+-	      name:	"das-1702st",
+-	      ai_speed:6250,
+-	      resolution:12,
+-	      qram_len:256,
+-	      common:	1,
+-	      do_n_chan:4,
+-	      ao_ability:0,
+-	      ao_n_chan:0,
+-	      range_ai:&range_ai_das1802,
++	.name = "das-1702st",
++	.ai_speed = 6250,
++	.resolution = 12,
++	.qram_len = 256,
++	.common = 1,
++	.do_n_chan = 4,
++	.ao_ability = 0,
++	.ao_n_chan = 0,
++	.range_ai = &range_ai_das1802,
+ 		},
+ 	{
+-	      name:	"das-1702st-da",
+-	      ai_speed:6250,
+-	      resolution:12,
+-	      qram_len:256,
+-	      common:	1,
+-	      do_n_chan:4,
+-	      ao_ability:1,
+-	      ao_n_chan:4,
+-	      range_ai:&range_ai_das1802,
++	.name = "das-1702st-da",
++	.ai_speed = 6250,
++	.resolution = 12,
++	.qram_len = 256,
++	.common = 1,
++	.do_n_chan = 4,
++	.ao_ability = 1,
++	.ao_n_chan = 4,
++	.range_ai = &range_ai_das1802,
+ 		},
+ 	{
+-	      name:	"das-1702hr",
+-	      ai_speed:20000,
+-	      resolution:16,
+-	      qram_len:256,
+-	      common:	1,
+-	      do_n_chan:4,
+-	      ao_ability:0,
+-	      ao_n_chan:0,
+-	      range_ai:&range_ai_das1802,
++	.name = "das-1702hr",
++	.ai_speed = 20000,
++	.resolution = 16,
++	.qram_len = 256,
++	.common = 1,
++	.do_n_chan = 4,
++	.ao_ability = 0,
++	.ao_n_chan = 0,
++	.range_ai = &range_ai_das1802,
+ 		},
+ 	{
+-	      name:	"das-1702hr-da",
+-	      ai_speed:20000,
+-	      resolution:16,
+-	      qram_len:256,
+-	      common:	1,
+-	      do_n_chan:4,
+-	      ao_ability:1,
+-	      ao_n_chan:2,
+-	      range_ai:&range_ai_das1802,
++	.name = "das-1702hr-da",
++	.ai_speed = 20000,
++	.resolution = 16,
++	.qram_len = 256,
++	.common = 1,
++	.do_n_chan = 4,
++	.ao_ability = 1,
++	.ao_n_chan = 2,
++	.range_ai = &range_ai_das1802,
+ 		},
+ 	{
+-	      name:	"das-1701ao",
+-	      ai_speed:6250,
+-	      resolution:12,
+-	      qram_len:256,
+-	      common:	1,
+-	      do_n_chan:4,
+-	      ao_ability:2,
+-	      ao_n_chan:2,
+-	      range_ai:&range_ai_das1801,
++	.name = "das-1701ao",
++	.ai_speed = 6250,
++	.resolution = 12,
++	.qram_len = 256,
++	.common = 1,
++	.do_n_chan = 4,
++	.ao_ability = 2,
++	.ao_n_chan = 2,
++	.range_ai = &range_ai_das1801,
+ 		},
+ 	{
+-	      name:	"das-1702ao",
+-	      ai_speed:6250,
+-	      resolution:12,
+-	      qram_len:256,
+-	      common:	1,
+-	      do_n_chan:4,
+-	      ao_ability:2,
+-	      ao_n_chan:2,
+-	      range_ai:&range_ai_das1802,
++	.name = "das-1702ao",
++	.ai_speed = 6250,
++	.resolution = 12,
++	.qram_len = 256,
++	.common = 1,
++	.do_n_chan = 4,
++	.ao_ability = 2,
++	.ao_n_chan = 2,
++	.range_ai = &range_ai_das1802,
+ 		},
+ 	{
+-	      name:	"das-1801st",
+-	      ai_speed:3000,
+-	      resolution:12,
+-	      qram_len:256,
+-	      common:	1,
+-	      do_n_chan:4,
+-	      ao_ability:0,
+-	      ao_n_chan:0,
+-	      range_ai:&range_ai_das1801,
++	.name = "das-1801st",
++	.ai_speed = 3000,
++	.resolution = 12,
++	.qram_len = 256,
++	.common = 1,
++	.do_n_chan = 4,
++	.ao_ability = 0,
++	.ao_n_chan = 0,
++	.range_ai = &range_ai_das1801,
+ 		},
+ 	{
+-	      name:	"das-1801st-da",
+-	      ai_speed:3000,
+-	      resolution:12,
+-	      qram_len:256,
+-	      common:	1,
+-	      do_n_chan:4,
+-	      ao_ability:0,
+-	      ao_n_chan:4,
+-	      range_ai:&range_ai_das1801,
++	.name = "das-1801st-da",
++	.ai_speed = 3000,
++	.resolution = 12,
++	.qram_len = 256,
++	.common = 1,
++	.do_n_chan = 4,
++	.ao_ability = 0,
++	.ao_n_chan = 4,
++	.range_ai = &range_ai_das1801,
+ 		},
+ 	{
+-	      name:	"das-1802st",
+-	      ai_speed:3000,
+-	      resolution:12,
+-	      qram_len:256,
+-	      common:	1,
+-	      do_n_chan:4,
+-	      ao_ability:0,
+-	      ao_n_chan:0,
+-	      range_ai:&range_ai_das1802,
++	.name = "das-1802st",
++	.ai_speed = 3000,
++	.resolution = 12,
++	.qram_len = 256,
++	.common = 1,
++	.do_n_chan = 4,
++	.ao_ability = 0,
++	.ao_n_chan = 0,
++	.range_ai = &range_ai_das1802,
+ 		},
+ 	{
+-	      name:	"das-1802st-da",
+-	      ai_speed:3000,
+-	      resolution:12,
+-	      qram_len:256,
+-	      common:	1,
+-	      do_n_chan:4,
+-	      ao_ability:1,
+-	      ao_n_chan:4,
+-	      range_ai:&range_ai_das1802,
++	.name = "das-1802st-da",
++	.ai_speed = 3000,
++	.resolution = 12,
++	.qram_len = 256,
++	.common = 1,
++	.do_n_chan = 4,
++	.ao_ability = 1,
++	.ao_n_chan = 4,
++	.range_ai = &range_ai_das1802,
+ 		},
+ 	{
+-	      name:	"das-1802hr",
+-	      ai_speed:10000,
+-	      resolution:16,
+-	      qram_len:256,
+-	      common:	1,
+-	      do_n_chan:4,
+-	      ao_ability:0,
+-	      ao_n_chan:0,
+-	      range_ai:&range_ai_das1802,
++	.name = "das-1802hr",
++	.ai_speed = 10000,
++	.resolution = 16,
++	.qram_len = 256,
++	.common = 1,
++	.do_n_chan = 4,
++	.ao_ability = 0,
++	.ao_n_chan = 0,
++	.range_ai = &range_ai_das1802,
+ 		},
+ 	{
+-	      name:	"das-1802hr-da",
+-	      ai_speed:10000,
+-	      resolution:16,
+-	      qram_len:256,
+-	      common:	1,
+-	      do_n_chan:4,
+-	      ao_ability:1,
+-	      ao_n_chan:2,
+-	      range_ai:&range_ai_das1802,
++	.name = "das-1802hr-da",
++	.ai_speed = 10000,
++	.resolution = 16,
++	.qram_len = 256,
++	.common = 1,
++	.do_n_chan = 4,
++	.ao_ability = 1,
++	.ao_n_chan = 2,
++	.range_ai = &range_ai_das1802,
+ 		},
+ 	{
+-	      name:	"das-1801hc",
+-	      ai_speed:3000,
+-	      resolution:12,
+-	      qram_len:64,
+-	      common:	0,
+-	      do_n_chan:8,
+-	      ao_ability:1,
+-	      ao_n_chan:2,
+-	      range_ai:&range_ai_das1801,
++	.name = "das-1801hc",
++	.ai_speed = 3000,
++	.resolution = 12,
++	.qram_len = 64,
++	.common = 0,
++	.do_n_chan = 8,
++	.ao_ability = 1,
++	.ao_n_chan = 2,
++	.range_ai = &range_ai_das1801,
+ 		},
+ 	{
+-	      name:	"das-1802hc",
+-	      ai_speed:3000,
+-	      resolution:12,
+-	      qram_len:64,
+-	      common:	0,
+-	      do_n_chan:8,
+-	      ao_ability:1,
+-	      ao_n_chan:2,
+-	      range_ai:&range_ai_das1802,
++	.name = "das-1802hc",
++	.ai_speed = 3000,
++	.resolution = 12,
++	.qram_len = 64,
++	.common = 0,
++	.do_n_chan = 8,
++	.ao_ability = 1,
++	.ao_n_chan = 2,
++	.range_ai = &range_ai_das1802,
+ 		},
+ 	{
+-	      name:	"das-1801ao",
+-	      ai_speed:3000,
+-	      resolution:12,
+-	      qram_len:256,
+-	      common:	1,
+-	      do_n_chan:4,
+-	      ao_ability:2,
+-	      ao_n_chan:2,
+-	      range_ai:&range_ai_das1801,
++	.name = "das-1801ao",
++	.ai_speed = 3000,
++	.resolution = 12,
++	.qram_len = 256,
++	.common = 1,
++	.do_n_chan = 4,
++	.ao_ability = 2,
++	.ao_n_chan = 2,
++	.range_ai = &range_ai_das1801,
+ 		},
+ 	{
+-	      name:	"das-1802ao",
+-	      ai_speed:3000,
+-	      resolution:12,
+-	      qram_len:256,
+-	      common:	1,
+-	      do_n_chan:4,
+-	      ao_ability:2,
+-	      ao_n_chan:2,
+-	      range_ai:&range_ai_das1802,
++	.name = "das-1802ao",
++	.ai_speed = 3000,
++	.resolution = 12,
++	.qram_len = 256,
++	.common = 1,
++	.do_n_chan = 4,
++	.ao_ability = 2,
++	.ao_n_chan = 2,
++	.range_ai = &range_ai_das1802,
+ 		},
+ };
+ 
+@@ -505,13 +505,13 @@ static const struct comedi_lrange range_ao_2 = {
+ */
+ 
+ static struct comedi_driver driver_das1800 = {
+-      driver_name:"das1800",
+-      module:THIS_MODULE,
+-      attach:das1800_attach,
+-      detach:das1800_detach,
+-      num_names:sizeof(das1800_boards) / sizeof(struct das1800_board),
+-      board_name:&das1800_boards[0].name,
+-      offset:sizeof(struct das1800_board),
++	.driver_name = "das1800",
++	.module = THIS_MODULE,
++	.attach = das1800_attach,
++	.detach = das1800_detach,
++	.num_names = sizeof(das1800_boards) / sizeof(struct das1800_board),
++	.board_name = &das1800_boards[0].name,
++	.offset = sizeof(struct das1800_board),
+ };
+ 
+ /*
+diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c
+index 9b43f8732844..950f07a56f4e 100644
+--- a/drivers/staging/comedi/drivers/das6402.c
++++ b/drivers/staging/comedi/drivers/das6402.c
+@@ -101,10 +101,10 @@ This driver has suffered bitrot.
+ static int das6402_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int das6402_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_das6402 = {
+-      driver_name:"das6402",
+-      module:THIS_MODULE,
+-      attach:das6402_attach,
+-      detach:das6402_detach,
++	.driver_name = "das6402",
++	.module = THIS_MODULE,
++	.attach = das6402_attach,
++	.detach = das6402_detach,
+ };
+ 
+ COMEDI_INITCLEANUP(driver_das6402);
+diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
+index aa1ae24da84c..71aeae3d57a8 100644
+--- a/drivers/staging/comedi/drivers/das800.c
++++ b/drivers/staging/comedi/drivers/das800.c
+@@ -184,46 +184,46 @@ enum { das800, ciodas800, das801, ciodas801, das802, ciodas802, ciodas80216 };
+ 
+ static const struct das800_board das800_boards[] = {
+ 	{
+-	      name:	"das-800",
+-	      ai_speed:25000,
+-	      ai_range:&range_das800_ai,
+-	      resolution:12,
++	.name = "das-800",
++	.ai_speed = 25000,
++	.ai_range = &range_das800_ai,
++	.resolution = 12,
+ 		},
+ 	{
+-	      name:	"cio-das800",
+-	      ai_speed:20000,
+-	      ai_range:&range_das800_ai,
+-	      resolution:12,
++	.name = "cio-das800",
++	.ai_speed = 20000,
++	.ai_range = &range_das800_ai,
++	.resolution = 12,
+ 		},
+ 	{
+-	      name:	"das-801",
+-	      ai_speed:25000,
+-	      ai_range:&range_das801_ai,
+-	      resolution:12,
++	.name = "das-801",
++	.ai_speed = 25000,
++	.ai_range = &range_das801_ai,
++	.resolution = 12,
+ 		},
+ 	{
+-	      name:	"cio-das801",
+-	      ai_speed:20000,
+-	      ai_range:&range_cio_das801_ai,
+-	      resolution:12,
++	.name = "cio-das801",
++	.ai_speed = 20000,
++	.ai_range = &range_cio_das801_ai,
++	.resolution = 12,
+ 		},
+ 	{
+-	      name:	"das-802",
+-	      ai_speed:25000,
+-	      ai_range:&range_das802_ai,
+-	      resolution:12,
++	.name = "das-802",
++	.ai_speed = 25000,
++	.ai_range = &range_das802_ai,
++	.resolution = 12,
+ 		},
+ 	{
+-	      name:	"cio-das802",
+-	      ai_speed:20000,
+-	      ai_range:&range_das802_ai,
+-	      resolution:12,
++	.name = "cio-das802",
++	.ai_speed = 20000,
++	.ai_range = &range_das802_ai,
++	.resolution = 12,
+ 		},
+ 	{
+-	      name:	"cio-das802/16",
+-	      ai_speed:10000,
+-	      ai_range:&range_das80216_ai,
+-	      resolution:16,
++	.name = "cio-das802/16",
++	.ai_speed = 10000,
++	.ai_range = &range_das80216_ai,
++	.resolution = 16,
+ 		},
+ };
+ 
+@@ -247,13 +247,13 @@ static int das800_detach(struct comedi_device *dev);
+ static int das800_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
+ 
+ static struct comedi_driver driver_das800 = {
+-      driver_name:"das800",
+-      module:THIS_MODULE,
+-      attach:das800_attach,
+-      detach:das800_detach,
+-      num_names:sizeof(das800_boards) / sizeof(struct das800_board),
+-      board_name:&das800_boards[0].name,
+-      offset:sizeof(struct das800_board),
++	.driver_name = "das800",
++	.module = THIS_MODULE,
++	.attach = das800_attach,
++	.detach = das800_detach,
++	.num_names = sizeof(das800_boards) / sizeof(struct das800_board),
++	.board_name = &das800_boards[0].name,
++	.offset = sizeof(struct das800_board),
+ };
+ 
+ static irqreturn_t das800_interrupt(int irq, void *d);
+diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
+index a8c0603d0d95..ce53d161a690 100644
+--- a/drivers/staging/comedi/drivers/dmm32at.c
++++ b/drivers/staging/comedi/drivers/dmm32at.c
+@@ -213,15 +213,15 @@ struct dmm32at_board {
+ };
+ static const struct dmm32at_board dmm32at_boards[] = {
+ 	{
+-	      name:	"dmm32at",
+-	      ai_chans:32,
+-	      ai_bits:	16,
+-	      ai_ranges:&dmm32at_airanges,
+-	      ao_chans:4,
+-	      ao_bits:	12,
+-	      ao_ranges:&dmm32at_aoranges,
+-	      have_dio:1,
+-	      dio_chans:24,
++	.name = "dmm32at",
++	.ai_chans = 32,
++	.ai_bits = 16,
++	.ai_ranges = &dmm32at_airanges,
++	.ao_chans = 4,
++	.ao_bits = 12,
++	.ao_ranges = &dmm32at_aoranges,
++	.have_dio = 1,
++	.dio_chans = 24,
+ 		},
+ };
+ 
+@@ -261,10 +261,10 @@ struct dmm32at_private {
+ static int dmm32at_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int dmm32at_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_dmm32at = {
+-      driver_name:"dmm32at",
+-      module:THIS_MODULE,
+-      attach:dmm32at_attach,
+-      detach:dmm32at_detach,
++	.driver_name = "dmm32at",
++	.module = THIS_MODULE,
++	.attach = dmm32at_attach,
++	.detach = dmm32at_detach,
+ /* It is not necessary to implement the following members if you are
+  * writing a driver for a ISA PnP or PCI card */
+ /* Most drivers will support multiple types of boards by
+@@ -283,9 +283,9 @@ static struct comedi_driver driver_dmm32at = {
+  * the type of board in software.  ISA PnP, PCI, and PCMCIA
+  * devices are such boards.
+  */
+-      board_name:&dmm32at_boards[0].name,
+-      offset:sizeof(struct dmm32at_board),
+-      num_names:sizeof(dmm32at_boards) / sizeof(struct dmm32at_board),
++	.board_name = &dmm32at_boards[0].name,
++	.offset = sizeof(struct dmm32at_board),
++	.num_names = sizeof(dmm32at_boards) / sizeof(struct dmm32at_board),
+ };
+ 
+ /* prototypes for driver functions below */
+diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c
+index 29fea1ac8ffa..335e3a0660cf 100644
+--- a/drivers/staging/comedi/drivers/dt2801.c
++++ b/drivers/staging/comedi/drivers/dt2801.c
+@@ -91,10 +91,10 @@ Configuration options:
+ static int dt2801_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int dt2801_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_dt2801 = {
+-      driver_name:"dt2801",
+-      module:THIS_MODULE,
+-      attach:dt2801_attach,
+-      detach:dt2801_detach,
++	.driver_name = "dt2801",
++	.module = THIS_MODULE,
++	.attach = dt2801_attach,
++	.detach = dt2801_detach,
+ };
+ 
+ COMEDI_INITCLEANUP(driver_dt2801);
+@@ -152,69 +152,69 @@ struct dt2801_board {
+    */
+ static const struct dt2801_board boardtypes[] = {
+ 	{
+-	      name:	"dt2801",
+-	      boardcode:0x09,
+-	      ad_diff:	2,
+-	      ad_chan:	16,
+-	      adbits:	12,
+-	      adrangetype:0,
+-      dabits:	12},
++	.name = "dt2801",
++	.boardcode = 0x09,
++	.ad_diff = 2,
++	.ad_chan = 16,
++	.adbits = 12,
++	.adrangetype = 0,
++	.dabits = 12},
+ 	{
+-	      name:	"dt2801-a",
+-	      boardcode:0x52,
+-	      ad_diff:	2,
+-	      ad_chan:	16,
+-	      adbits:	12,
+-	      adrangetype:0,
+-      dabits:	12},
++	.name = "dt2801-a",
++	.boardcode = 0x52,
++	.ad_diff = 2,
++	.ad_chan = 16,
++	.adbits = 12,
++	.adrangetype = 0,
++	.dabits = 12},
+ 	{
+-	      name:	"dt2801/5716a",
+-	      boardcode:0x82,
+-	      ad_diff:	1,
+-	      ad_chan:	16,
+-	      adbits:	16,
+-	      adrangetype:1,
+-      dabits:	12},
++	.name = "dt2801/5716a",
++	.boardcode = 0x82,
++	.ad_diff = 1,
++	.ad_chan = 16,
++	.adbits = 16,
++	.adrangetype = 1,
++	.dabits = 12},
+ 	{
+-	      name:	"dt2805",
+-	      boardcode:0x12,
+-	      ad_diff:	1,
+-	      ad_chan:	16,
+-	      adbits:	12,
+-	      adrangetype:0,
+-      dabits:	12},
++	.name = "dt2805",
++	.boardcode = 0x12,
++	.ad_diff = 1,
++	.ad_chan = 16,
++	.adbits = 12,
++	.adrangetype = 0,
++	.dabits = 12},
+ 	{
+-	      name:	"dt2805/5716a",
+-	      boardcode:0x92,
+-	      ad_diff:	1,
+-	      ad_chan:	16,
+-	      adbits:	16,
+-	      adrangetype:1,
+-      dabits:	12},
++	.name = "dt2805/5716a",
++	.boardcode = 0x92,
++	.ad_diff = 1,
++	.ad_chan = 16,
++	.adbits = 16,
++	.adrangetype = 1,
++	.dabits = 12},
+ 	{
+-	      name:	"dt2808",
+-	      boardcode:0x20,
+-	      ad_diff:	0,
+-	      ad_chan:	16,
+-	      adbits:	12,
+-	      adrangetype:2,
+-      dabits:	8},
++	.name = "dt2808",
++	.boardcode = 0x20,
++	.ad_diff = 0,
++	.ad_chan = 16,
++	.adbits = 12,
++	.adrangetype = 2,
++	.dabits = 8},
+ 	{
+-	      name:	"dt2818",
+-	      boardcode:0xa2,
+-	      ad_diff:	0,
+-	      ad_chan:	4,
+-	      adbits:	12,
+-	      adrangetype:0,
+-      dabits:	12},
++	.name = "dt2818",
++	.boardcode = 0xa2,
++	.ad_diff = 0,
++	.ad_chan = 4,
++	.adbits = 12,
++	.adrangetype = 0,
++	.dabits = 12},
+ 	{
+-	      name:	"dt2809",
+-	      boardcode:0xb0,
+-	      ad_diff:	0,
+-	      ad_chan:	8,
+-	      adbits:	12,
+-	      adrangetype:1,
+-      dabits:	12},
++	.name = "dt2809",
++	.boardcode = 0xb0,
++	.ad_diff = 0,
++	.ad_chan = 8,
++	.adbits = 12,
++	.adrangetype = 1,
++	.dabits = 12},
+ };
+ 
+ #define n_boardtypes ((sizeof(boardtypes))/(sizeof(boardtypes[0])))
+diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c
+index b782118ebff0..7e6995ed886d 100644
+--- a/drivers/staging/comedi/drivers/dt2811.c
++++ b/drivers/staging/comedi/drivers/dt2811.c
+@@ -217,13 +217,13 @@ static const struct dt2811_board boardtypes[] = {
+ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int dt2811_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_dt2811 = {
+-      driver_name:"dt2811",
+-      module:THIS_MODULE,
+-      attach:dt2811_attach,
+-      detach:dt2811_detach,
+-      board_name:&boardtypes[0].name,
+-      num_names:sizeof(boardtypes) / sizeof(struct dt2811_board),
+-      offset:sizeof(struct dt2811_board),
++	.driver_name = "dt2811",
++	.module = THIS_MODULE,
++	.attach = dt2811_attach,
++	.detach = dt2811_detach,
++	.board_name = &boardtypes[0].name,
++	.num_names = sizeof(boardtypes) / sizeof(struct dt2811_board),
++	.offset = sizeof(struct dt2811_board),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_dt2811);
+diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c
+index 4db82ae6bfb6..246d0d74ce9c 100644
+--- a/drivers/staging/comedi/drivers/dt2814.c
++++ b/drivers/staging/comedi/drivers/dt2814.c
+@@ -62,10 +62,10 @@ addition, the clock does not seem to be very accurate.
+ static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int dt2814_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_dt2814 = {
+-      driver_name:"dt2814",
+-      module:THIS_MODULE,
+-      attach:dt2814_attach,
+-      detach:dt2814_detach,
++	.driver_name = "dt2814",
++	.module = THIS_MODULE,
++	.attach = dt2814_attach,
++	.detach = dt2814_detach,
+ };
+ 
+ COMEDI_INITCLEANUP(driver_dt2814);
+diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c
+index 36a2f07792bc..d83ee4acbb19 100644
+--- a/drivers/staging/comedi/drivers/dt2815.c
++++ b/drivers/staging/comedi/drivers/dt2815.c
+@@ -78,10 +78,10 @@ static const struct comedi_lrange range_dt2815_ao_20_current = { 1, {
+ static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int dt2815_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_dt2815 = {
+-      driver_name:"dt2815",
+-      module:THIS_MODULE,
+-      attach:dt2815_attach,
+-      detach:dt2815_detach,
++	.driver_name = "dt2815",
++	.module = THIS_MODULE,
++	.attach = dt2815_attach,
++	.detach = dt2815_detach,
+ };
+ 
+ COMEDI_INITCLEANUP(driver_dt2815);
+diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c
+index 7e944c544fa1..b36f85632f87 100644
+--- a/drivers/staging/comedi/drivers/dt2817.c
++++ b/drivers/staging/comedi/drivers/dt2817.c
+@@ -50,10 +50,10 @@ Configuration options:
+ static int dt2817_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int dt2817_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_dt2817 = {
+-      driver_name:"dt2817",
+-      module:THIS_MODULE,
+-      attach:dt2817_attach,
+-      detach:dt2817_detach,
++	.driver_name = "dt2817",
++	.module = THIS_MODULE,
++	.attach = dt2817_attach,
++	.detach = dt2817_detach,
+ };
+ 
+ COMEDI_INITCLEANUP(driver_dt2817);
+diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
+index 64e9c4b32c0a..f852b9347027 100644
+--- a/drivers/staging/comedi/drivers/dt282x.c
++++ b/drivers/staging/comedi/drivers/dt282x.c
+@@ -209,132 +209,132 @@ struct dt282x_board {
+ };
+ 
+ static const struct dt282x_board boardtypes[] = {
+-      {name:"dt2821",
+-	      adbits:	12,
+-	      adchan_se:16,
+-	      adchan_di:8,
+-	      ai_speed:20000,
+-	      ispgl:	0,
+-	      dachan:	2,
+-	      dabits:	12,
+-		},
+-      {name:"dt2821-f",
+-	      adbits:	12,
+-	      adchan_se:16,
+-	      adchan_di:8,
+-	      ai_speed:6500,
+-	      ispgl:	0,
+-	      dachan:	2,
+-	      dabits:	12,
+-		},
+-      {name:"dt2821-g",
+-	      adbits:	12,
+-	      adchan_se:16,
+-	      adchan_di:8,
+-	      ai_speed:4000,
+-	      ispgl:	0,
+-	      dachan:	2,
+-	      dabits:	12,
+-		},
+-      {name:"dt2823",
+-	      adbits:	16,
+-	      adchan_se:0,
+-	      adchan_di:4,
+-	      ai_speed:10000,
+-	      ispgl:	0,
+-	      dachan:	2,
+-	      dabits:	16,
+-		},
+-      {name:"dt2824-pgh",
+-	      adbits:	12,
+-	      adchan_se:16,
+-	      adchan_di:8,
+-	      ai_speed:20000,
+-	      ispgl:	0,
+-	      dachan:	0,
+-	      dabits:	0,
+-		},
+-      {name:"dt2824-pgl",
+-	      adbits:	12,
+-	      adchan_se:16,
+-	      adchan_di:8,
+-	      ai_speed:20000,
+-	      ispgl:	1,
+-	      dachan:	0,
+-	      dabits:	0,
+-		},
+-      {name:"dt2825",
+-	      adbits:	12,
+-	      adchan_se:16,
+-	      adchan_di:8,
+-	      ai_speed:20000,
+-	      ispgl:	1,
+-	      dachan:	2,
+-	      dabits:	12,
+-		},
+-      {name:"dt2827",
+-	      adbits:	16,
+-	      adchan_se:0,
+-	      adchan_di:4,
+-	      ai_speed:10000,
+-	      ispgl:	0,
+-	      dachan:	2,
+-	      dabits:	12,
+-		},
+-      {name:"dt2828",
+-	      adbits:	12,
+-	      adchan_se:4,
+-	      adchan_di:0,
+-	      ai_speed:10000,
+-	      ispgl:	0,
+-	      dachan:	2,
+-	      dabits:	12,
+-		},
+-      {name:"dt2829",
+-	      adbits:	16,
+-	      adchan_se:8,
+-	      adchan_di:0,
+-	      ai_speed:33250,
+-	      ispgl:	0,
+-	      dachan:	2,
+-	      dabits:	16,
+-		},
+-      {name:"dt21-ez",
+-	      adbits:	12,
+-	      adchan_se:16,
+-	      adchan_di:8,
+-	      ai_speed:10000,
+-	      ispgl:	0,
+-	      dachan:	2,
+-	      dabits:	12,
+-		},
+-      {name:"dt23-ez",
+-	      adbits:	16,
+-	      adchan_se:16,
+-	      adchan_di:8,
+-	      ai_speed:10000,
+-	      ispgl:	0,
+-	      dachan:	0,
+-	      dabits:	0,
+-		},
+-      {name:"dt24-ez",
+-	      adbits:	12,
+-	      adchan_se:16,
+-	      adchan_di:8,
+-	      ai_speed:10000,
+-	      ispgl:	0,
+-	      dachan:	0,
+-	      dabits:	0,
+-		},
+-      {name:"dt24-ez-pgl",
+-	      adbits:	12,
+-	      adchan_se:16,
+-	      adchan_di:8,
+-	      ai_speed:10000,
+-	      ispgl:	1,
+-	      dachan:	0,
+-	      dabits:	0,
+-		},
++	{.name = "dt2821",
++	 .adbits = 12,
++	 .adchan_se = 16,
++	 .adchan_di = 8,
++	 .ai_speed = 20000,
++	 .ispgl = 0,
++	 .dachan = 2,
++	 .dabits = 12,
++	},
++	{.name = "dt2821-f",
++	 .adbits = 12,
++	 .adchan_se = 16,
++	 .adchan_di = 8,
++	 .ai_speed = 6500,
++	 .ispgl = 0,
++	 .dachan = 2,
++	 .dabits = 12,
++	},
++	{.name = "dt2821-g",
++	 .adbits = 12,
++	 .adchan_se = 16,
++	 .adchan_di = 8,
++	 .ai_speed = 4000,
++	 .ispgl = 0,
++	 .dachan = 2,
++	 .dabits = 12,
++	},
++	{.name = "dt2823",
++	 .adbits = 16,
++	 .adchan_se = 0,
++	 .adchan_di = 4,
++	 .ai_speed = 10000,
++	 .ispgl = 0,
++	 .dachan = 2,
++	 .dabits = 16,
++	},
++	{.name = "dt2824-pgh",
++	  .adbits = 12,
++	  .adchan_se = 16,
++	  .adchan_di = 8,
++	  .ai_speed = 20000,
++	  .ispgl = 0,
++	  .dachan = 0,
++	  .dabits = 0,
++	},
++	{.name = "dt2824-pgl",
++	 .adbits = 12,
++	 .adchan_se = 16,
++	 .adchan_di = 8,
++	 .ai_speed = 20000,
++	 .ispgl = 1,
++	 .dachan = 0,
++	 .dabits = 0,
++	},
++	{.name = "dt2825",
++	 .adbits = 12,
++	 .adchan_se = 16,
++	 .adchan_di = 8,
++	 .ai_speed = 20000,
++	 .ispgl = 1,
++	 .dachan = 2,
++	 .dabits = 12,
++	},
++	{.name = "dt2827",
++	 .adbits = 16,
++	 .adchan_se = 0,
++	 .adchan_di = 4,
++	 .ai_speed = 10000,
++	 .ispgl = 0,
++	 .dachan = 2,
++	 .dabits = 12,
++	},
++	{.name = "dt2828",
++	 .adbits = 12,
++	 .adchan_se = 4,
++	 .adchan_di = 0,
++	 .ai_speed = 10000,
++	 .ispgl = 0,
++	 .dachan = 2,
++	 .dabits = 12,
++	},
++	{.name = "dt2829",
++	 .adbits = 16,
++	 .adchan_se = 8,
++	 .adchan_di = 0,
++	 .ai_speed = 33250,
++	 .ispgl = 0,
++	 .dachan = 2,
++	 .dabits = 16,
++	},
++	{.name = "dt21-ez",
++	 .adbits = 12,
++	 .adchan_se = 16,
++	 .adchan_di = 8,
++	 .ai_speed = 10000,
++	 .ispgl = 0,
++	 .dachan = 2,
++	 .dabits = 12,
++	},
++	{.name = "dt23-ez",
++	 .adbits = 16,
++	 .adchan_se = 16,
++	 .adchan_di = 8,
++	 .ai_speed = 10000,
++	 .ispgl = 0,
++	 .dachan = 0,
++	 .dabits = 0,
++	},
++	{.name = "dt24-ez",
++	 .adbits = 12,
++	 .adchan_se = 16,
++	 .adchan_di = 8,
++	 .ai_speed = 10000,
++	 .ispgl = 0,
++	 .dachan = 0,
++	 .dabits = 0,
++	},
++	{.name = "dt24-ez-pgl",
++	 .adbits = 12,
++	 .adchan_se = 16,
++	 .adchan_di = 8,
++	 .ai_speed = 10000,
++	 .ispgl = 1,
++	 .dachan = 0,
++	 .dabits = 0,
++	},
+ };
+ 
+ #define n_boardtypes sizeof(boardtypes)/sizeof(struct dt282x_board)
+@@ -397,13 +397,13 @@ struct dt282x_private {
+ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int dt282x_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_dt282x = {
+-      driver_name:"dt282x",
+-      module:THIS_MODULE,
+-      attach:dt282x_attach,
+-      detach:dt282x_detach,
+-      board_name:&boardtypes[0].name,
+-      num_names:n_boardtypes,
+-      offset:sizeof(struct dt282x_board),
++	.driver_name = "dt282x",
++	.module = THIS_MODULE,
++	.attach = dt282x_attach,
++	.detach = dt282x_detach,
++	.board_name = &boardtypes[0].name,
++	.num_names = n_boardtypes,
++	.offset = sizeof(struct dt282x_board),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_dt282x);
+diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
+index c894e384c8ac..7440921c408f 100644
+--- a/drivers/staging/comedi/drivers/dt3000.c
++++ b/drivers/staging/comedi/drivers/dt3000.c
+@@ -95,69 +95,69 @@ struct dt3k_boardtype {
+ 
+ 
+ static const struct dt3k_boardtype dt3k_boardtypes[] = {
+-      {name:"dt3001",
+-	      device_id:0x22,
+-	      adchan:	16,
+-	      adbits:	12,
+-	      adrange:	&range_dt3000_ai,
+-	      ai_speed:3000,
+-	      dachan:	2,
+-	      dabits:	12,
+-		},
+-      {name:"dt3001-pgl",
+-	      device_id:0x27,
+-	      adchan:	16,
+-	      adbits:	12,
+-	      adrange:	&range_dt3000_ai_pgl,
+-	      ai_speed:3000,
+-	      dachan:	2,
+-	      dabits:	12,
+-		},
+-      {name:"dt3002",
+-	      device_id:0x23,
+-	      adchan:	32,
+-	      adbits:	12,
+-	      adrange:	&range_dt3000_ai,
+-	      ai_speed:3000,
+-	      dachan:	0,
+-	      dabits:	0,
+-		},
+-      {name:"dt3003",
+-	      device_id:0x24,
+-	      adchan:	64,
+-	      adbits:	12,
+-	      adrange:	&range_dt3000_ai,
+-	      ai_speed:3000,
+-	      dachan:	2,
+-	      dabits:	12,
+-		},
+-      {name:"dt3003-pgl",
+-	      device_id:0x28,
+-	      adchan:	64,
+-	      adbits:	12,
+-	      adrange:	&range_dt3000_ai_pgl,
+-	      ai_speed:3000,
+-	      dachan:	2,
+-	      dabits:	12,
+-		},
+-      {name:"dt3004",
+-	      device_id:0x25,
+-	      adchan:	16,
+-	      adbits:	16,
+-	      adrange:	&range_dt3000_ai,
+-	      ai_speed:10000,
+-	      dachan:	2,
+-	      dabits:	12,
+-		},
+-      {name:"dt3005",		/* a.k.a. 3004-200 */
+-	      device_id:0x26,
+-	      adchan:	16,
+-	      adbits:	16,
+-	      adrange:	&range_dt3000_ai,
+-	      ai_speed:5000,
+-	      dachan:	2,
+-	      dabits:	12,
+-		},
++	{.name = "dt3001",
++	 .device_id = 0x22,
++	 .adchan = 16,
++	 .adbits = 12,
++	 .adrange = &range_dt3000_ai,
++	 .ai_speed = 3000,
++	 .dachan = 2,
++	 .dabits = 12,
++	},
++	{.name = "dt3001-pgl",
++	 .device_id = 0x27,
++	 .adchan = 16,
++	 .adbits = 12,
++	 .adrange = &range_dt3000_ai_pgl,
++	 .ai_speed = 3000,
++	 .dachan = 2,
++	 .dabits = 12,
++	},
++	{.name = "dt3002",
++	 .device_id = 0x23,
++	 .adchan = 32,
++	 .adbits = 12,
++	 .adrange = &range_dt3000_ai,
++	 .ai_speed = 3000,
++	 .dachan = 0,
++	 .dabits = 0,
++	},
++	{.name = "dt3003",
++	 .device_id = 0x24,
++	 .adchan = 64,
++	 .adbits = 12,
++	 .adrange = &range_dt3000_ai,
++	 .ai_speed = 3000,
++	 .dachan = 2,
++	 .dabits = 12,
++	},
++	{.name = "dt3003-pgl",
++	 .device_id = 0x28,
++	 .adchan = 64,
++	 .adbits = 12,
++	 .adrange = &range_dt3000_ai_pgl,
++	 .ai_speed = 3000,
++	 .dachan = 2,
++	 .dabits = 12,
++	},
++	{.name = "dt3004",
++	 .device_id = 0x25,
++	 .adchan = 16,
++	 .adbits = 16,
++	 .adrange = &range_dt3000_ai,
++	 .ai_speed = 10000,
++	 .dachan = 2,
++	 .dabits = 12,
++	},
++        {.name = "dt3005",		/* a.k.a. 3004-200 */
++	 .device_id = 0x26,
++	 .adchan = 16,
++	 .adbits = 16,
++	 .adrange = &range_dt3000_ai,
++	 .ai_speed = 5000,
++	 .dachan = 2,
++	 .dabits = 12,
++	},
+ };
+ 
+ #define n_dt3k_boards sizeof(dt3k_boardtypes)/sizeof(struct dt3k_boardtype)
+@@ -278,10 +278,10 @@ struct dt3k_private {
+ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int dt3000_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_dt3000 = {
+-      driver_name:"dt3000",
+-      module:THIS_MODULE,
+-      attach:dt3000_attach,
+-      detach:dt3000_detach,
++	.driver_name = "dt3000",
++	.module = THIS_MODULE,
++	.attach = dt3000_attach,
++	.detach = dt3000_detach,
+ };
+ 
+ COMEDI_PCI_INITCLEANUP(driver_dt3000, dt3k_pci_table);
+diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c
+index 5a9a254997a6..f8ee5c5493b8 100644
+--- a/drivers/staging/comedi/drivers/fl512.c
++++ b/drivers/staging/comedi/drivers/fl512.c
+@@ -46,10 +46,10 @@ static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int fl512_detach(struct comedi_device *dev);
+ 
+ static struct comedi_driver driver_fl512 = {
+-      driver_name:"fl512",
+-      module:THIS_MODULE,
+-      attach:fl512_attach,
+-      detach:fl512_detach,
++	.driver_name = "fl512",
++	.module = THIS_MODULE,
++	.attach = fl512_attach,
++	.detach = fl512_detach,
+ };
+ 
+ COMEDI_INITCLEANUP(driver_fl512);
+diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
+index d25b4c8aeaed..567dd5290e8f 100644
+--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
++++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
+@@ -270,15 +270,15 @@ struct hpdi_board {
+ 
+ static const struct hpdi_board hpdi_boards[] = {
+ 	{
+-	      name:	"pci-hpdi32",
+-	      device_id:PCI_DEVICE_ID_PLX_9080,
+-	      subdevice_id:0x2400,
++	.name = "pci-hpdi32",
++	.device_id = PCI_DEVICE_ID_PLX_9080,
++	.subdevice_id = 0x2400,
+ 		},
+ #if 0
+ 	{
+-	      name:	"pxi-hpdi32",
+-	      device_id:0x9656,
+-	      subdevice_id:0x2705,
++	.name = "pxi-hpdi32",
++	.device_id = 0x9656,
++	.subdevice_id = 0x2705,
+ 		},
+ #endif
+ };
+@@ -332,10 +332,10 @@ static inline struct hpdi_private *priv(struct comedi_device * dev)
+ }
+ 
+ static struct comedi_driver driver_hpdi = {
+-      driver_name:"gsc_hpdi",
+-      module:THIS_MODULE,
+-      attach:hpdi_attach,
+-      detach:hpdi_detach,
++	.driver_name = "gsc_hpdi",
++	.module = THIS_MODULE,
++	.attach = hpdi_attach,
++	.detach = hpdi_detach,
+ };
+ 
+ COMEDI_PCI_INITCLEANUP(driver_hpdi, hpdi_pci_table);
+diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c
+index f4790bfa08ee..a90d65fde31e 100644
+--- a/drivers/staging/comedi/drivers/ii_pci20kc.c
++++ b/drivers/staging/comedi/drivers/ii_pci20kc.c
+@@ -162,10 +162,10 @@ static int pci20xxx_attach(struct comedi_device *dev, struct comedi_devconfig *i
+ static int pci20xxx_detach(struct comedi_device *dev);
+ 
+ static struct comedi_driver driver_pci20xxx = {
+-      driver_name:"ii_pci20kc",
+-      module:THIS_MODULE,
+-      attach:pci20xxx_attach,
+-      detach:pci20xxx_detach,
++	.driver_name = "ii_pci20kc",
++	.module = THIS_MODULE,
++	.attach = pci20xxx_attach,
++	.detach = pci20xxx_detach,
+ };
+ 
+ static int pci20006_init(struct comedi_device *dev, struct comedi_subdevice *s,
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
+index 3cb5e4753df6..d1f3bae15524 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -58,10 +58,10 @@ static int jr3_pci_attach(struct comedi_device *dev, struct comedi_devconfig *it
+ static int jr3_pci_detach(struct comedi_device *dev);
+ 
+ static struct comedi_driver driver_jr3_pci = {
+-      driver_name:"jr3_pci",
+-      module:THIS_MODULE,
+-      attach:jr3_pci_attach,
+-      detach:jr3_pci_detach,
++	.driver_name = "jr3_pci",
++	.module = THIS_MODULE,
++	.attach = jr3_pci_attach,
++	.detach = jr3_pci_detach,
+ };
+ 
+ static DEFINE_PCI_DEVICE_TABLE(jr3_pci_pci_table) = {
+diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c
+index e1f84a5c9670..b49aed5c4a02 100644
+--- a/drivers/staging/comedi/drivers/ke_counter.c
++++ b/drivers/staging/comedi/drivers/ke_counter.c
+@@ -72,10 +72,10 @@ struct cnt_board_struct {
+ 
+ static const struct cnt_board_struct cnt_boards[] = {
+ 	{
+-	      name:	CNT_DRIVER_NAME,
+-	      device_id:CNT_CARD_DEVICE_ID,
+-	      cnt_channel_nbr:3,
+-      cnt_bits:24}
++	.name = CNT_DRIVER_NAME,
++	.device_id = CNT_CARD_DEVICE_ID,
++	.cnt_channel_nbr = 3,
++	.cnt_bits = 24}
+ };
+ 
+ #define cnt_board_nbr (sizeof(cnt_boards)/sizeof(struct cnt_board_struct))
+@@ -91,10 +91,10 @@ struct cnt_device_private {
+ #define devpriv ((struct cnt_device_private *)dev->private)
+ 
+ static struct comedi_driver cnt_driver = {
+-      driver_name:CNT_DRIVER_NAME,
+-      module:THIS_MODULE,
+-      attach:cnt_attach,
+-      detach:cnt_detach,
++	.driver_name = CNT_DRIVER_NAME,
++	.module = THIS_MODULE,
++	.attach = cnt_attach,
++	.detach = cnt_detach,
+ };
+ 
+ COMEDI_PCI_INITCLEANUP(cnt_driver, cnt_pci_table);
+diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c
+index a00ad1b63ed5..15731a285442 100644
+--- a/drivers/staging/comedi/drivers/mpc624.c
++++ b/drivers/staging/comedi/drivers/mpc624.c
+@@ -150,10 +150,10 @@ static int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ static int mpc624_detach(struct comedi_device *dev);
+ /* ---------------------------------------------------------------------------- */
+ static struct comedi_driver driver_mpc624 = {
+-      driver_name:"mpc624",
+-      module:THIS_MODULE,
+-      attach:mpc624_attach,
+-      detach:mpc624_detach
++	.driver_name = "mpc624",
++	.module = THIS_MODULE,
++	.attach = mpc624_attach,
++	.detach = mpc624_detach
+ };
+ 
+ /* ---------------------------------------------------------------------------- */
+diff --git a/drivers/staging/comedi/drivers/mpc8260cpm.c b/drivers/staging/comedi/drivers/mpc8260cpm.c
+index 147108f72024..c7ee3ef10130 100644
+--- a/drivers/staging/comedi/drivers/mpc8260cpm.c
++++ b/drivers/staging/comedi/drivers/mpc8260cpm.c
+@@ -49,10 +49,10 @@ struct mpc8260cpm_private {
+ static int mpc8260cpm_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int mpc8260cpm_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_mpc8260cpm = {
+-      driver_name:"mpc8260cpm",
+-      module:THIS_MODULE,
+-      attach:mpc8260cpm_attach,
+-      detach:mpc8260cpm_detach,
++	.driver_name = "mpc8260cpm",
++	.module = THIS_MODULE,
++	.attach = mpc8260cpm_attach,
++	.detach = mpc8260cpm_detach,
+ };
+ 
+ COMEDI_INITCLEANUP(driver_mpc8260cpm);
+diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c
+index 5b155be0cf99..b3412241633a 100644
+--- a/drivers/staging/comedi/drivers/multiq3.c
++++ b/drivers/staging/comedi/drivers/multiq3.c
+@@ -85,10 +85,10 @@ Devices: [Quanser Consulting] MultiQ-3 (multiq3)
+ static int multiq3_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int multiq3_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_multiq3 = {
+-      driver_name:"multiq3",
+-      module:THIS_MODULE,
+-      attach:multiq3_attach,
+-      detach:multiq3_detach,
++	.driver_name = "multiq3",
++	.module = THIS_MODULE,
++	.attach = multiq3_attach,
++	.detach = multiq3_detach,
+ };
+ 
+ COMEDI_INITCLEANUP(driver_multiq3);
+diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
+index 78ba17aec0ad..2751ea7f9192 100644
+--- a/drivers/staging/comedi/drivers/ni_6527.c
++++ b/drivers/staging/comedi/drivers/ni_6527.c
+@@ -78,10 +78,10 @@ Updated: Sat, 25 Jan 2003 13:24:40 -0800
+ static int ni6527_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int ni6527_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_ni6527 = {
+-      driver_name:"ni6527",
+-      module:THIS_MODULE,
+-      attach:ni6527_attach,
+-      detach:ni6527_detach,
++	.driver_name = "ni6527",
++	.module = THIS_MODULE,
++	.attach = ni6527_attach,
++	.detach = ni6527_detach,
+ };
+ 
+ struct ni6527_board {
+@@ -92,12 +92,12 @@ struct ni6527_board {
+ 
+ static const struct ni6527_board ni6527_boards[] = {
+ 	{
+-	      dev_id:	0x2b20,
+-	      name:	"pci-6527",
++	.dev_id = 0x2b20,
++	.name = "pci-6527",
+ 		},
+ 	{
+-	      dev_id:	0x2b10,
+-	      name:	"pxi-6527",
++	.dev_id = 0x2b10,
++	.name = "pxi-6527",
+ 		},
+ };
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
+index 7cf22c0f566b..b4e63fba8aba 100644
+--- a/drivers/staging/comedi/drivers/ni_65xx.c
++++ b/drivers/staging/comedi/drivers/ni_65xx.c
+@@ -105,10 +105,10 @@ static inline unsigned Filter_Enable(unsigned port)
+ static int ni_65xx_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int ni_65xx_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_ni_65xx = {
+-      driver_name:"ni_65xx",
+-      module:THIS_MODULE,
+-      attach:ni_65xx_attach,
+-      detach:ni_65xx_detach,
++	.driver_name = "ni_65xx",
++	.module = THIS_MODULE,
++	.attach = ni_65xx_attach,
++	.detach = ni_65xx_detach,
+ };
+ 
+ struct ni_65xx_board {
+@@ -123,120 +123,120 @@ struct ni_65xx_board {
+ 
+ static const struct ni_65xx_board ni_65xx_boards[] = {
+ 	{
+-	      dev_id:	0x7085,
+-	      name:	"pci-6509",
+-	      num_dio_ports:12,
+-      invert_outputs:0},
++	.dev_id = 0x7085,
++	.name = "pci-6509",
++	.num_dio_ports = 12,
++	.invert_outputs = 0},
+ 	{
+-	      dev_id:	0x1710,
+-	      name:	"pxi-6509",
+-	      num_dio_ports:12,
+-      invert_outputs:0},
++	.dev_id = 0x1710,
++	.name = "pxi-6509",
++	.num_dio_ports = 12,
++	.invert_outputs = 0},
+ 	{
+-	      dev_id:	0x7124,
+-	      name:	"pci-6510",
+-      num_di_ports:4},
++	.dev_id = 0x7124,
++	.name = "pci-6510",
++	.num_di_ports = 4},
+ 	{
+-	      dev_id:	0x70c3,
+-	      name:	"pci-6511",
+-      num_di_ports:8},
++	.dev_id = 0x70c3,
++	.name = "pci-6511",
++	.num_di_ports = 8},
+ 	{
+-	      dev_id:	0x70d3,
+-	      name:	"pxi-6511",
+-      num_di_ports:8},
++	.dev_id = 0x70d3,
++	.name = "pxi-6511",
++	.num_di_ports = 8},
+ 	{
+-	      dev_id:	0x70cc,
+-	      name:	"pci-6512",
+-      num_do_ports:8},
++	.dev_id = 0x70cc,
++	.name = "pci-6512",
++	.num_do_ports = 8},
+ 	{
+-	      dev_id:	0x70d2,
+-	      name:	"pxi-6512",
+-      num_do_ports:8},
++	.dev_id = 0x70d2,
++	.name = "pxi-6512",
++	.num_do_ports = 8},
+ 	{
+-	      dev_id:	0x70c8,
+-	      name:	"pci-6513",
+-	      num_do_ports:8,
+-      invert_outputs:1},
++	.dev_id = 0x70c8,
++	.name = "pci-6513",
++	.num_do_ports = 8,
++	.invert_outputs = 1},
+ 	{
+-	      dev_id:	0x70d1,
+-	      name:	"pxi-6513",
+-	      num_do_ports:8,
+-      invert_outputs:1},
++	.dev_id = 0x70d1,
++	.name = "pxi-6513",
++	.num_do_ports = 8,
++	.invert_outputs = 1},
+ 	{
+-	      dev_id:	0x7088,
+-	      name:	"pci-6514",
+-	      num_di_ports:4,
+-	      num_do_ports:4,
+-      invert_outputs:1},
++	.dev_id = 0x7088,
++	.name = "pci-6514",
++	.num_di_ports = 4,
++	.num_do_ports = 4,
++	.invert_outputs = 1},
+ 	{
+-	      dev_id:	0x70CD,
+-	      name:	"pxi-6514",
+-	      num_di_ports:4,
+-	      num_do_ports:4,
+-      invert_outputs:1},
++	.dev_id = 0x70CD,
++	.name = "pxi-6514",
++	.num_di_ports = 4,
++	.num_do_ports = 4,
++	.invert_outputs = 1},
+ 	{
+-	      dev_id:	0x7087,
+-	      name:	"pci-6515",
+-	      num_di_ports:4,
+-	      num_do_ports:4,
+-      invert_outputs:1},
++	.dev_id = 0x7087,
++	.name = "pci-6515",
++	.num_di_ports = 4,
++	.num_do_ports = 4,
++	.invert_outputs = 1},
+ 	{
+-	      dev_id:	0x70c9,
+-	      name:	"pxi-6515",
+-	      num_di_ports:4,
+-	      num_do_ports:4,
+-      invert_outputs:1},
++	.dev_id = 0x70c9,
++	.name = "pxi-6515",
++	.num_di_ports = 4,
++	.num_do_ports = 4,
++	.invert_outputs = 1},
+ 	{
+-	      dev_id:	0x7125,
+-	      name:	"pci-6516",
+-	      num_do_ports:4,
+-      invert_outputs:1},
++	.dev_id = 0x7125,
++	.name = "pci-6516",
++	.num_do_ports = 4,
++	.invert_outputs = 1},
+ 	{
+-	      dev_id:	0x7126,
+-	      name:	"pci-6517",
+-	      num_do_ports:4,
+-      invert_outputs:1},
++	.dev_id = 0x7126,
++	.name = "pci-6517",
++	.num_do_ports = 4,
++	.invert_outputs = 1},
+ 	{
+-	      dev_id:	0x7127,
+-	      name:	"pci-6518",
+-	      num_di_ports:2,
+-	      num_do_ports:2,
+-      invert_outputs:1},
++	.dev_id = 0x7127,
++	.name = "pci-6518",
++	.num_di_ports = 2,
++	.num_do_ports = 2,
++	.invert_outputs = 1},
+ 	{
+-	      dev_id:	0x7128,
+-	      name:	"pci-6519",
+-	      num_di_ports:2,
+-	      num_do_ports:2,
+-      invert_outputs:1},
++	.dev_id = 0x7128,
++	.name = "pci-6519",
++	.num_di_ports = 2,
++	.num_do_ports = 2,
++	.invert_outputs = 1},
+ 	{
+-	      dev_id:	0x71c5,
+-	      name:	"pci-6520",
+-	      num_di_ports:1,
+-	      num_do_ports:1,
++	.dev_id = 0x71c5,
++	.name = "pci-6520",
++	.num_di_ports = 1,
++	.num_do_ports = 1,
+ 		},
+ 	{
+-	      dev_id:	0x718b,
+-	      name:	"pci-6521",
+-	      num_di_ports:1,
+-	      num_do_ports:1,
++	.dev_id = 0x718b,
++	.name = "pci-6521",
++	.num_di_ports = 1,
++	.num_do_ports = 1,
+ 		},
+ 	{
+-	      dev_id:	0x718c,
+-	      name:	"pxi-6521",
+-	      num_di_ports:1,
+-	      num_do_ports:1,
++	.dev_id = 0x718c,
++	.name = "pxi-6521",
++	.num_di_ports = 1,
++	.num_do_ports = 1,
+ 		},
+ 	{
+-	      dev_id:	0x70a9,
+-	      name:	"pci-6528",
+-	      num_di_ports:3,
+-	      num_do_ports:3,
++	.dev_id = 0x70a9,
++	.name = "pci-6528",
++	.num_di_ports = 3,
++	.num_do_ports = 3,
+ 		},
+ 	{
+-	      dev_id:	0x7086,
+-	      name:	"pxi-6528",
+-	      num_di_ports:3,
+-	      num_do_ports:3,
++	.dev_id = 0x7086,
++	.name = "pxi-6528",
++	.num_di_ports = 3,
++	.num_do_ports = 3,
+ 		},
+ };
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
+index 3c35dab02796..78c106ce5fa5 100644
+--- a/drivers/staging/comedi/drivers/ni_660x.c
++++ b/drivers/staging/comedi/drivers/ni_660x.c
+@@ -387,24 +387,24 @@ struct ni_660x_board {
+ 
+ static const struct ni_660x_board ni_660x_boards[] = {
+ 	{
+-	      dev_id:	0x2c60,
+-	      name:	"PCI-6601",
+-	      n_chips:	1,
++	.dev_id = 0x2c60,
++	.name = "PCI-6601",
++	.n_chips = 1,
+ 		},
+ 	{
+-	      dev_id:	0x1310,
+-	      name:	"PCI-6602",
+-	      n_chips:	2,
++	.dev_id = 0x1310,
++	.name = "PCI-6602",
++	.n_chips = 2,
+ 		},
+ 	{
+-	      dev_id:	0x1360,
+-	      name:	"PXI-6602",
+-	      n_chips:	2,
++	.dev_id = 0x1360,
++	.name = "PXI-6602",
++	.n_chips = 2,
+ 		},
+ 	{
+-	      dev_id:	0x2cc0,
+-	      name:	"PXI-6608",
+-	      n_chips:	2,
++	.dev_id = 0x2cc0,
++	.name = "PXI-6608",
++	.n_chips = 2,
+ 		},
+ };
+ 
+@@ -455,10 +455,10 @@ static void ni_660x_select_pfi_output(struct comedi_device *dev, unsigned pfi_ch
+ 	unsigned output_select);
+ 
+ static struct comedi_driver driver_ni_660x = {
+-      driver_name:"ni_660x",
+-      module:THIS_MODULE,
+-      attach:ni_660x_attach,
+-      detach:ni_660x_detach,
++	.driver_name = "ni_660x",
++	.module = THIS_MODULE,
++	.attach = ni_660x_attach,
++	.detach = ni_660x_detach,
+ };
+ 
+ COMEDI_PCI_INITCLEANUP(driver_ni_660x, ni_660x_pci_table);
+diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
+index 0caa4864190c..0a9678cdadc7 100644
+--- a/drivers/staging/comedi/drivers/ni_670x.c
++++ b/drivers/staging/comedi/drivers/ni_670x.c
+@@ -69,22 +69,22 @@ struct ni_670x_board {
+ 
+ static const struct ni_670x_board ni_670x_boards[] = {
+ 	{
+-	      dev_id:	0x2c90,
+-	      name:	"PCI-6703",
+-	      ao_chans:16,
+-	      ao_bits:	16,
++	.dev_id = 0x2c90,
++	.name = "PCI-6703",
++	.ao_chans = 16,
++	.ao_bits = 16,
+ 		},
+ 	{
+-	      dev_id:	0x1920,
+-	      name:	"PXI-6704",
+-	      ao_chans:32,
+-	      ao_bits:	16,
++	.dev_id = 0x1920,
++	.name = "PXI-6704",
++	.ao_chans = 32,
++	.ao_bits = 16,
+ 		},
+ 	{
+-	      dev_id:	0x1290,
+-	      name:	"PCI-6704",
+-	      ao_chans:32,
+-	      ao_bits:	16,
++	.dev_id = 0x1290,
++	.name = "PCI-6704",
++	.ao_chans = 32,
++	.ao_bits = 16,
+ 		},
+ };
+ 
+@@ -115,10 +115,10 @@ static int ni_670x_attach(struct comedi_device *dev, struct comedi_devconfig *it
+ static int ni_670x_detach(struct comedi_device *dev);
+ 
+ static struct comedi_driver driver_ni_670x = {
+-      driver_name:"ni_670x",
+-      module:THIS_MODULE,
+-      attach:ni_670x_attach,
+-      detach:ni_670x_detach,
++	.driver_name = "ni_670x",
++	.module = THIS_MODULE,
++	.attach = ni_670x_attach,
++	.detach = ni_670x_detach,
+ };
+ 
+ COMEDI_PCI_INITCLEANUP(driver_ni_670x, ni_670x_pci_table);
+diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
+index 62754d5372ae..0e42f18cdbfe 100644
+--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
++++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
+@@ -138,16 +138,16 @@ static const struct comedi_lrange range_a2150 = {
+ enum { a2150_c, a2150_s };
+ static const struct a2150_board a2150_boards[] = {
+ 	{
+-	      name:	"at-a2150c",
+-	      clock:	{31250, 22676, 20833, 19531},
+-	      num_clocks:4,
+-	      ai_speed:19531,
++	.name = "at-a2150c",
++	.clock = {31250, 22676, 20833, 19531},
++	.num_clocks = 4,
++	.ai_speed = 19531,
+ 		},
+ 	{
+-	      name:	"at-a2150s",
+-	      clock:	{62500, 50000, 41667, 0},
+-	      num_clocks:3,
+-	      ai_speed:41667,
++	.name = "at-a2150s",
++	.clock = {62500, 50000, 41667, 0},
++	.num_clocks = 3,
++	.ai_speed = 41667,
+ 		},
+ };
+ 
+@@ -174,10 +174,10 @@ static int a2150_detach(struct comedi_device *dev);
+ static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
+ 
+ static struct comedi_driver driver_a2150 = {
+-      driver_name:"ni_at_a2150",
+-      module:THIS_MODULE,
+-      attach:a2150_attach,
+-      detach:a2150_detach,
++	.driver_name = "ni_at_a2150",
++	.module = THIS_MODULE,
++	.attach = a2150_attach,
++	.detach = a2150_detach,
+ };
+ 
+ static irqreturn_t a2150_interrupt(int irq, void *d);
+diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c
+index 282457ccefb3..1b752f615002 100644
+--- a/drivers/staging/comedi/drivers/ni_at_ao.c
++++ b/drivers/staging/comedi/drivers/ni_at_ao.c
+@@ -158,12 +158,12 @@ struct atao_board {
+ 
+ static const struct atao_board atao_boards[] = {
+ 	{
+-	      name:	"ai-ao-6",
+-	      n_ao_chans:6,
++	.name = "ai-ao-6",
++	.n_ao_chans = 6,
+ 		},
+ 	{
+-	      name:	"ai-ao-10",
+-	      n_ao_chans:10,
++	.name = "ai-ao-10",
++	.n_ao_chans = 10,
+ 		},
+ };
+ 
+@@ -184,13 +184,13 @@ struct atao_private {
+ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int atao_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_atao = {
+-      driver_name:"ni_at_ao",
+-      module:THIS_MODULE,
+-      attach:atao_attach,
+-      detach:atao_detach,
+-      board_name:&atao_boards[0].name,
+-      offset:sizeof(struct atao_board),
+-      num_names:sizeof(atao_boards) / sizeof(struct atao_board),
++	.driver_name = "ni_at_ao",
++	.module = THIS_MODULE,
++	.attach = atao_attach,
++	.detach = atao_detach,
++	.board_name = &atao_boards[0].name,
++	.offset = sizeof(struct atao_board),
++	.num_names = sizeof(atao_boards) / sizeof(struct atao_board),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_atao);
+diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c
+index c4c47497373b..0116a4a0a06e 100644
+--- a/drivers/staging/comedi/drivers/ni_atmio.c
++++ b/drivers/staging/comedi/drivers/ni_atmio.c
+@@ -115,155 +115,155 @@ are not supported.
+ #define MAX_N_CALDACS 32
+ 
+ static const struct ni_board_struct ni_boards[] = {
+-      {device_id:44,
+-	      isapnp_id:0x0000,/* XXX unknown */
+-	      name:	"at-mio-16e-1",
+-	      n_adchan:16,
+-	      adbits:	12,
+-	      ai_fifo_depth:8192,
+-	      alwaysdither:0,
+-	      gainlkup:ai_gain_16,
+-	      ai_speed:800,
+-	      n_aochan:2,
+-	      aobits:	12,
+-	      ao_fifo_depth:2048,
++	{.device_id = 44,
++	.isapnp_id = 0x0000,/* XXX unknown */
++	.name = "at-mio-16e-1",
++	.n_adchan = 16,
++	.adbits = 12,
++	.ai_fifo_depth = 8192,
++	.alwaysdither = 0,
++	.gainlkup = ai_gain_16,
++	.ai_speed = 800,
++	.n_aochan = 2,
++	.aobits = 12,
++	.ao_fifo_depth = 2048,
+ 			.ao_range_table = &range_ni_E_ao_ext,
+-	      ao_unipolar:1,
+-	      ao_speed:1000,
+-	      has_8255:0,
++	.ao_unipolar = 1,
++	.ao_speed = 1000,
++	.has_8255 = 0,
+ 			.num_p0_dio_channels = 8,
+-	      caldac:	{mb88341},
++	.caldac = {mb88341},
+ 		},
+-      {device_id:25,
+-	      isapnp_id:0x1900,
+-	      name:	"at-mio-16e-2",
+-	      n_adchan:16,
+-	      adbits:	12,
+-	      ai_fifo_depth:2048,
+-	      alwaysdither:0,
+-	      gainlkup:ai_gain_16,
+-	      ai_speed:2000,
+-	      n_aochan:2,
+-	      aobits:	12,
+-	      ao_fifo_depth:2048,
++	{.device_id = 25,
++	.isapnp_id = 0x1900,
++	.name = "at-mio-16e-2",
++	.n_adchan = 16,
++	.adbits = 12,
++	.ai_fifo_depth = 2048,
++	.alwaysdither = 0,
++	.gainlkup = ai_gain_16,
++	.ai_speed = 2000,
++	.n_aochan = 2,
++	.aobits = 12,
++	.ao_fifo_depth = 2048,
+ 			.ao_range_table = &range_ni_E_ao_ext,
+-	      ao_unipolar:1,
+-	      ao_speed:1000,
+-	      has_8255:0,
++	.ao_unipolar = 1,
++	.ao_speed = 1000,
++	.has_8255 = 0,
+ 			.num_p0_dio_channels = 8,
+-	      caldac:	{mb88341},
++	.caldac = {mb88341},
+ 		},
+-      {device_id:36,
+-	      isapnp_id:0x2400,
+-	      name:	"at-mio-16e-10",
+-	      n_adchan:16,
+-	      adbits:	12,
+-	      ai_fifo_depth:512,
+-	      alwaysdither:0,
+-	      gainlkup:ai_gain_16,
+-	      ai_speed:10000,
+-	      n_aochan:2,
+-	      aobits:	12,
+-	      ao_fifo_depth:0,
++	{.device_id = 36,
++	.isapnp_id = 0x2400,
++	.name = "at-mio-16e-10",
++	.n_adchan = 16,
++	.adbits = 12,
++	.ai_fifo_depth = 512,
++	.alwaysdither = 0,
++	.gainlkup = ai_gain_16,
++	.ai_speed = 10000,
++	.n_aochan = 2,
++	.aobits = 12,
++	.ao_fifo_depth = 0,
+ 			.ao_range_table = &range_ni_E_ao_ext,
+-	      ao_unipolar:1,
+-	      ao_speed:10000,
++	.ao_unipolar = 1,
++	.ao_speed = 10000,
+ 			.num_p0_dio_channels = 8,
+-	      caldac:	{ad8804_debug},
+-	      has_8255:0,
++	.caldac = {ad8804_debug},
++	.has_8255 = 0,
+ 		},
+-      {device_id:37,
+-	      isapnp_id:0x2500,
+-	      name:	"at-mio-16de-10",
+-	      n_adchan:16,
+-	      adbits:	12,
+-	      ai_fifo_depth:512,
+-	      alwaysdither:0,
+-	      gainlkup:ai_gain_16,
+-	      ai_speed:10000,
+-	      n_aochan:2,
+-	      aobits:	12,
+-	      ao_fifo_depth:0,
++	{.device_id = 37,
++	.isapnp_id = 0x2500,
++	.name = "at-mio-16de-10",
++	.n_adchan = 16,
++	.adbits = 12,
++	.ai_fifo_depth = 512,
++	.alwaysdither = 0,
++	.gainlkup = ai_gain_16,
++	.ai_speed = 10000,
++	.n_aochan = 2,
++	.aobits = 12,
++	.ao_fifo_depth = 0,
+ 			.ao_range_table = &range_ni_E_ao_ext,
+-	      ao_unipolar:1,
+-	      ao_speed:10000,
++	.ao_unipolar = 1,
++	.ao_speed = 10000,
+ 			.num_p0_dio_channels = 8,
+-	      caldac:	{ad8804_debug},
+-	      has_8255:1,
++	.caldac = {ad8804_debug},
++	.has_8255 = 1,
+ 		},
+-      {device_id:38,
+-	      isapnp_id:0x2600,
+-	      name:	"at-mio-64e-3",
+-	      n_adchan:64,
+-	      adbits:	12,
+-	      ai_fifo_depth:2048,
+-	      alwaysdither:0,
+-	      gainlkup:ai_gain_16,
+-	      ai_speed:2000,
+-	      n_aochan:2,
+-	      aobits:	12,
+-	      ao_fifo_depth:2048,
++	{.device_id = 38,
++	.isapnp_id = 0x2600,
++	.name = "at-mio-64e-3",
++	.n_adchan = 64,
++	.adbits = 12,
++	.ai_fifo_depth = 2048,
++	.alwaysdither = 0,
++	.gainlkup = ai_gain_16,
++	.ai_speed = 2000,
++	.n_aochan = 2,
++	.aobits = 12,
++	.ao_fifo_depth = 2048,
+ 			.ao_range_table = &range_ni_E_ao_ext,
+-	      ao_unipolar:1,
+-	      ao_speed:1000,
+-	      has_8255:0,
++	.ao_unipolar = 1,
++	.ao_speed = 1000,
++	.has_8255 = 0,
+ 			.num_p0_dio_channels = 8,
+-	      caldac:	{ad8804_debug},
++	.caldac = {ad8804_debug},
+ 		},
+-      {device_id:39,
+-	      isapnp_id:0x2700,
+-	      name:	"at-mio-16xe-50",
+-	      n_adchan:16,
+-	      adbits:	16,
+-	      ai_fifo_depth:512,
+-	      alwaysdither:1,
+-	      gainlkup:ai_gain_8,
+-	      ai_speed:50000,
+-	      n_aochan:2,
+-	      aobits:	12,
+-	      ao_fifo_depth:0,
++	{.device_id = 39,
++	.isapnp_id = 0x2700,
++	.name = "at-mio-16xe-50",
++	.n_adchan = 16,
++	.adbits = 16,
++	.ai_fifo_depth = 512,
++	.alwaysdither = 1,
++	.gainlkup = ai_gain_8,
++	.ai_speed = 50000,
++	.n_aochan = 2,
++	.aobits = 12,
++	.ao_fifo_depth = 0,
+ 			.ao_range_table = &range_bipolar10,
+-	      ao_unipolar:0,
+-	      ao_speed:50000,
++	.ao_unipolar = 0,
++	.ao_speed = 50000,
+ 			.num_p0_dio_channels = 8,
+-	      caldac:	{dac8800, dac8043},
+-	      has_8255:0,
++	.caldac = {dac8800, dac8043},
++	.has_8255 = 0,
+ 		},
+-      {device_id:50,
+-	      isapnp_id:0x0000,/* XXX unknown */
+-	      name:	"at-mio-16xe-10",
+-	      n_adchan:16,
+-	      adbits:	16,
+-	      ai_fifo_depth:512,
+-	      alwaysdither:1,
+-	      gainlkup:ai_gain_14,
+-	      ai_speed:10000,
+-	      n_aochan:2,
+-	      aobits:	16,
+-	      ao_fifo_depth:2048,
++	{.device_id = 50,
++	.isapnp_id = 0x0000,/* XXX unknown */
++	.name = "at-mio-16xe-10",
++	.n_adchan = 16,
++	.adbits = 16,
++	.ai_fifo_depth = 512,
++	.alwaysdither = 1,
++	.gainlkup = ai_gain_14,
++	.ai_speed = 10000,
++	.n_aochan = 2,
++	.aobits = 16,
++	.ao_fifo_depth = 2048,
+ 			.ao_range_table = &range_ni_E_ao_ext,
+-	      ao_unipolar:1,
+-	      ao_speed:1000,
++	.ao_unipolar = 1,
++	.ao_speed = 1000,
+ 			.num_p0_dio_channels = 8,
+-	      caldac:	{dac8800, dac8043, ad8522},
+-	      has_8255:0,
++	.caldac = {dac8800, dac8043, ad8522},
++	.has_8255 = 0,
+ 		},
+-      {device_id:51,
+-	      isapnp_id:0x0000,/* XXX unknown */
+-	      name:	"at-ai-16xe-10",
+-	      n_adchan:16,
+-	      adbits:	16,
+-	      ai_fifo_depth:512,
+-	      alwaysdither:1,	/* unknown */
+-	      gainlkup:ai_gain_14,
+-	      ai_speed:10000,
+-	      n_aochan:0,
+-	      aobits:	0,
+-	      ao_fifo_depth:0,
+-	      ao_unipolar:0,
++	{.device_id = 51,
++	.isapnp_id = 0x0000,/* XXX unknown */
++	.name = "at-ai-16xe-10",
++	.n_adchan = 16,
++	.adbits = 16,
++	.ai_fifo_depth = 512,
++	.alwaysdither = 1,	/* unknown */
++	.gainlkup = ai_gain_14,
++	.ai_speed = 10000,
++	.n_aochan = 0,
++	.aobits = 0,
++	.ao_fifo_depth = 0,
++	.ao_unipolar = 0,
+ 			.num_p0_dio_channels = 8,
+-	      caldac:	{dac8800, dac8043, ad8522},
+-	      has_8255:0,
++	.caldac = {dac8800, dac8043, ad8522},
++	.has_8255 = 0,
+ 		}
+ };
+ 
+@@ -342,10 +342,10 @@ MODULE_DEVICE_TABLE(pnp, device_ids);
+ static int ni_atmio_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int ni_atmio_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_atmio = {
+-      driver_name:"ni_atmio",
+-      module:THIS_MODULE,
+-      attach:ni_atmio_attach,
+-      detach:ni_atmio_detach,
++	.driver_name = "ni_atmio",
++	.module = THIS_MODULE,
++	.attach = ni_atmio_attach,
++	.detach = ni_atmio_detach,
+ };
+ 
+ COMEDI_INITCLEANUP(driver_atmio);
+diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
+index b110ec651b42..b02d2f33d528 100644
+--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
++++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
+@@ -111,12 +111,12 @@ struct atmio16_board_t {
+ 
+ static const struct atmio16_board_t atmio16_boards[] = {
+ 	{
+-	      name:	"atmio16",
+-	      has_8255:0,
++	.name = "atmio16",
++	.has_8255 = 0,
+ 		},
+ 	{
+-	      name:	"atmio16d",
+-	      has_8255:1,
++	.name = "atmio16d",
++	.has_8255 = 1,
+ 		},
+ };
+ 
+@@ -137,13 +137,13 @@ static void reset_atmio16d(struct comedi_device * dev);
+ 
+ /* main driver struct */
+ static struct comedi_driver driver_atmio16d = {
+-      driver_name:"atmio16",
+-      module:THIS_MODULE,
+-      attach:atmio16d_attach,
+-      detach:atmio16d_detach,
+-      board_name:&atmio16_boards[0].name,
+-      num_names:n_atmio16_boards,
+-      offset:sizeof(struct atmio16_board_t),
++	.driver_name = "atmio16",
++	.module = THIS_MODULE,
++	.attach = atmio16d_attach,
++	.detach = atmio16d_detach,
++	.board_name = &atmio16_boards[0].name,
++	.num_names = n_atmio16_boards,
++	.offset = sizeof(struct atmio16_board_t),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_atmio16d);
+diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
+index 8f594a8778cf..3f0c1b3694dc 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_700.c
++++ b/drivers/staging/comedi/drivers/ni_daq_700.c
+@@ -73,16 +73,16 @@ struct dio700_board {
+ 
+ static const struct dio700_board dio700_boards[] = {
+ 	{
+-	      name:	"daqcard-700",
+-	      device_id:0x4743,/*  0x10b is manufacturer id, 0x4743 is device id */
+-	      bustype:	pcmcia_bustype,
+-	      have_dio:1,
++	.name = "daqcard-700",
++	.device_id = 0x4743,/*  0x10b is manufacturer id, 0x4743 is device id */
++	.bustype = pcmcia_bustype,
++	.have_dio = 1,
+ 		},
+ 	{
+-	      name:	"ni_daq_700",
+-	      device_id:0x4743,/*  0x10b is manufacturer id, 0x4743 is device id */
+-	      bustype:	pcmcia_bustype,
+-	      have_dio:1,
++	.name = "ni_daq_700",
++	.device_id = 0x4743,/*  0x10b is manufacturer id, 0x4743 is device id */
++	.bustype = pcmcia_bustype,
++	.have_dio = 1,
+ 		},
+ };
+ 
+@@ -100,13 +100,13 @@ struct dio700_private {
+ #define devpriv ((struct dio700_private *)dev->private)
+ 
+ static struct comedi_driver driver_dio700 = {
+-      driver_name:"ni_daq_700",
+-      module:THIS_MODULE,
+-      attach:dio700_attach,
+-      detach:dio700_detach,
+-      num_names:sizeof(dio700_boards) / sizeof(struct dio700_board),
+-      board_name:&dio700_boards[0].name,
+-      offset:sizeof(struct dio700_board),
++	.driver_name = "ni_daq_700",
++	.module = THIS_MODULE,
++	.attach = dio700_attach,
++	.detach = dio700_detach,
++	.num_names = sizeof(dio700_boards) / sizeof(struct dio700_board),
++	.board_name = &dio700_boards[0].name,
++	.offset = sizeof(struct dio700_board),
+ };
+ 
+ /*	the real driver routines	*/
+diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
+index f7814dbedb4b..a0b3dd254384 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
++++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
+@@ -73,16 +73,16 @@ struct dio24_board_struct {
+ 
+ static const struct dio24_board_struct dio24_boards[] = {
+ 	{
+-	      name:	"daqcard-dio24",
+-	      device_id:0x475c,/*  0x10b is manufacturer id, 0x475c is device id */
+-	      bustype:	pcmcia_bustype,
+-	      have_dio:1,
++	.name = "daqcard-dio24",
++	.device_id = 0x475c,/*  0x10b is manufacturer id, 0x475c is device id */
++	.bustype = pcmcia_bustype,
++	.have_dio = 1,
+ 		},
+ 	{
+-	      name:	"ni_daq_dio24",
+-	      device_id:0x475c,/*  0x10b is manufacturer id, 0x475c is device id */
+-	      bustype:	pcmcia_bustype,
+-	      have_dio:1,
++	.name = "ni_daq_dio24",
++	.device_id = 0x475c,/*  0x10b is manufacturer id, 0x475c is device id */
++	.bustype = pcmcia_bustype,
++	.have_dio = 1,
+ 		},
+ };
+ 
+@@ -100,13 +100,13 @@ struct dio24_private {
+ #define devpriv ((struct dio24_private *)dev->private)
+ 
+ static struct comedi_driver driver_dio24 = {
+-      driver_name:"ni_daq_dio24",
+-      module:THIS_MODULE,
+-      attach:dio24_attach,
+-      detach:dio24_detach,
+-      num_names:sizeof(dio24_boards) / sizeof(struct dio24_board_struct),
+-      board_name:&dio24_boards[0].name,
+-      offset:sizeof(struct dio24_board_struct),
++	.driver_name = "ni_daq_dio24",
++	.module = THIS_MODULE,
++	.attach = dio24_attach,
++	.detach = dio24_detach,
++	.num_names = sizeof(dio24_boards) / sizeof(struct dio24_board_struct),
++	.board_name = &dio24_boards[0].name,
++	.offset = sizeof(struct dio24_board_struct),
+ };
+ 
+ static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
+index caec783ca89a..e6ee7d94ca9a 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc.c
++++ b/drivers/staging/comedi/drivers/ni_labpc.c
+@@ -362,54 +362,54 @@ static inline void labpc_writeb(unsigned int byte, unsigned long address)
+ 
+ static const struct labpc_board_struct labpc_boards[] = {
+ 	{
+-	      name:	"lab-pc-1200",
+-	      ai_speed:10000,
+-	      bustype:	isa_bustype,
+-	      register_layout:labpc_1200_layout,
+-	      has_ao:	1,
+-	      ai_range_table:&range_labpc_1200_ai,
+-	      ai_range_code:labpc_1200_ai_gain_bits,
+-	      ai_range_is_unipolar:labpc_1200_is_unipolar,
+-	      ai_scan_up:1,
+-	      memory_mapped_io:0,
++	.name = "lab-pc-1200",
++	.ai_speed = 10000,
++	.bustype = isa_bustype,
++	.register_layout = labpc_1200_layout,
++	.has_ao = 1,
++	.ai_range_table = &range_labpc_1200_ai,
++	.ai_range_code = labpc_1200_ai_gain_bits,
++	.ai_range_is_unipolar = labpc_1200_is_unipolar,
++	.ai_scan_up = 1,
++	.memory_mapped_io = 0,
+ 		},
+ 	{
+-	      name:	"lab-pc-1200ai",
+-	      ai_speed:10000,
+-	      bustype:	isa_bustype,
+-	      register_layout:labpc_1200_layout,
+-	      has_ao:	0,
+-	      ai_range_table:&range_labpc_1200_ai,
+-	      ai_range_code:labpc_1200_ai_gain_bits,
+-	      ai_range_is_unipolar:labpc_1200_is_unipolar,
+-	      ai_scan_up:1,
+-	      memory_mapped_io:0,
++	.name = "lab-pc-1200ai",
++	.ai_speed = 10000,
++	.bustype = isa_bustype,
++	.register_layout = labpc_1200_layout,
++	.has_ao = 0,
++	.ai_range_table = &range_labpc_1200_ai,
++	.ai_range_code = labpc_1200_ai_gain_bits,
++	.ai_range_is_unipolar = labpc_1200_is_unipolar,
++	.ai_scan_up = 1,
++	.memory_mapped_io = 0,
+ 		},
+ 	{
+-	      name:	"lab-pc+",
+-	      ai_speed:12000,
+-	      bustype:	isa_bustype,
+-	      register_layout:labpc_plus_layout,
+-	      has_ao:	1,
+-	      ai_range_table:&range_labpc_plus_ai,
+-	      ai_range_code:labpc_plus_ai_gain_bits,
+-	      ai_range_is_unipolar:labpc_plus_is_unipolar,
+-	      ai_scan_up:0,
+-	      memory_mapped_io:0,
++	.name = "lab-pc+",
++	.ai_speed = 12000,
++	.bustype = isa_bustype,
++	.register_layout = labpc_plus_layout,
++	.has_ao = 1,
++	.ai_range_table = &range_labpc_plus_ai,
++	.ai_range_code = labpc_plus_ai_gain_bits,
++	.ai_range_is_unipolar = labpc_plus_is_unipolar,
++	.ai_scan_up = 0,
++	.memory_mapped_io = 0,
+ 		},
+ #ifdef CONFIG_COMEDI_PCI
+ 	{
+-		name:	"pci-1200",
+-		device_id:0x161,
+-		ai_speed:10000,
+-		bustype:	pci_bustype,
+-		register_layout:labpc_1200_layout,
+-		has_ao:	1,
+-		ai_range_table:&range_labpc_1200_ai,
+-		ai_range_code:labpc_1200_ai_gain_bits,
+-		ai_range_is_unipolar:labpc_1200_is_unipolar,
+-		ai_scan_up:1,
+-		memory_mapped_io:1,
++	.name = "pci-1200",
++	.device_id = 0x161,
++	.ai_speed = 10000,
++	.bustype = pci_bustype,
++	.register_layout = labpc_1200_layout,
++	.has_ao = 1,
++	.ai_range_table = &range_labpc_1200_ai,
++	.ai_range_code = labpc_1200_ai_gain_bits,
++	.ai_range_is_unipolar = labpc_1200_is_unipolar,
++	.ai_scan_up = 1,
++	.memory_mapped_io = 1,
+ 		},
+ 	/*  dummy entry so pci board works when comedi_config is passed driver name */
+ 	{
+diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
+index e504f4f594a6..41538c3c80ff 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
++++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
+@@ -83,31 +83,31 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ 
+ static const struct labpc_board_struct labpc_cs_boards[] = {
+ 	{
+-	      name:	"daqcard-1200",
+-	      device_id:0x103,	/*  0x10b is manufacturer id, 0x103 is device id */
+-	      ai_speed:10000,
+-	      bustype:	pcmcia_bustype,
+-	      register_layout:labpc_1200_layout,
+-	      has_ao:	1,
+-	      ai_range_table:&range_labpc_1200_ai,
+-	      ai_range_code:labpc_1200_ai_gain_bits,
+-	      ai_range_is_unipolar:labpc_1200_is_unipolar,
+-	      ai_scan_up:0,
+-	      memory_mapped_io:0,
++	.name = "daqcard-1200",
++	.device_id = 0x103,	/*  0x10b is manufacturer id, 0x103 is device id */
++	.ai_speed = 10000,
++	.bustype = pcmcia_bustype,
++	.register_layout = labpc_1200_layout,
++	.has_ao = 1,
++	.ai_range_table = &range_labpc_1200_ai,
++	.ai_range_code = labpc_1200_ai_gain_bits,
++	.ai_range_is_unipolar = labpc_1200_is_unipolar,
++	.ai_scan_up = 0,
++	.memory_mapped_io = 0,
+ 		},
+ 	/* duplicate entry, to support using alternate name */
+ 	{
+-	      name:	"ni_labpc_cs",
+-	      device_id:0x103,
+-	      ai_speed:10000,
+-	      bustype:	pcmcia_bustype,
+-	      register_layout:labpc_1200_layout,
+-	      has_ao:	1,
+-	      ai_range_table:&range_labpc_1200_ai,
+-	      ai_range_code:labpc_1200_ai_gain_bits,
+-	      ai_range_is_unipolar:labpc_1200_is_unipolar,
+-	      ai_scan_up:0,
+-	      memory_mapped_io:0,
++	.name = "ni_labpc_cs",
++	.device_id = 0x103,
++	.ai_speed = 10000,
++	.bustype = pcmcia_bustype,
++	.register_layout = labpc_1200_layout,
++	.has_ao = 1,
++	.ai_range_table = &range_labpc_1200_ai,
++	.ai_range_code = labpc_1200_ai_gain_bits,
++	.ai_range_is_unipolar = labpc_1200_is_unipolar,
++	.ai_scan_up = 0,
++	.memory_mapped_io = 0,
+ 		},
+ };
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c
+index a7ab3f72c7aa..fe6af0aa3dc7 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_cs.c
++++ b/drivers/staging/comedi/drivers/ni_mio_cs.c
+@@ -67,102 +67,102 @@ See the notes in the ni_atmio.o driver.
+ #define MAX_N_CALDACS 32
+ 
+ static const struct ni_board_struct ni_boards[] = {
+-      {device_id:0x010d,
+-	      name:	"DAQCard-ai-16xe-50",
+-	      n_adchan:16,
+-	      adbits:	16,
+-	      ai_fifo_depth:1024,
+-	      alwaysdither:0,
+-	      gainlkup:ai_gain_8,
+-	      ai_speed:5000,
+-	      n_aochan:0,
+-	      aobits:	0,
+-	      ao_fifo_depth:0,
+-	      ao_unipolar:0,
+-	      num_p0_dio_channels:8,
+-	      has_8255:0,
+-	      caldac:	{dac8800, dac8043},
+-		},
+-      {device_id:0x010c,
+-	      name:	"DAQCard-ai-16e-4",
+-	      n_adchan:16,
+-	      adbits:	12,
+-	      ai_fifo_depth:1024,
+-	      alwaysdither:0,
+-	      gainlkup:ai_gain_16,
+-	      ai_speed:4000,
+-	      n_aochan:0,
+-	      aobits:	0,
+-	      ao_fifo_depth:0,
+-	      ao_unipolar:0,
+-	      num_p0_dio_channels:8,
+-	      has_8255:0,
+-	      caldac:	{mb88341},	/* verified */
+-		},
+-      {device_id:0x02c4,
+-	      name:	"DAQCard-6062E",
+-	      n_adchan:16,
+-	      adbits:	12,
+-	      ai_fifo_depth:8192,
+-	      alwaysdither:0,
+-	      gainlkup:ai_gain_16,
+-	      ai_speed:2000,
+-	      n_aochan:2,
+-	      aobits:	12,
+-	      ao_fifo_depth:2048,
+-	      ao_range_table:&range_bipolar10,
+-	      ao_unipolar:0,
+-	      ao_speed:1176,
+-	      num_p0_dio_channels:8,
+-	      has_8255:0,
+-	      caldac:	{ad8804_debug},	/* verified */
+-		},
+-      {device_id:0x075e,
+-	      name:	"DAQCard-6024E",	/* specs incorrect! */
+-	      n_adchan:16,
+-	      adbits:	12,
+-	      ai_fifo_depth:1024,
+-	      alwaysdither:0,
+-	      gainlkup:ai_gain_16,
+-	      ai_speed:5000,
+-	      n_aochan:2,
+-	      aobits:	12,
+-	      ao_fifo_depth:0,
+-	      ao_range_table:&range_bipolar10,
+-	      ao_unipolar:0,
+-	      ao_speed:1000000,
+-	      num_p0_dio_channels:8,
+-	      has_8255:0,
+-	      caldac:	{ad8804_debug},
+-		},
+-      {device_id:0x0245,
+-	      name:	"DAQCard-6036E",	/* specs incorrect! */
+-	      n_adchan:16,
+-	      adbits:	16,
+-	      ai_fifo_depth:1024,
+-	      alwaysdither:1,
+-	      gainlkup:ai_gain_4,
+-	      ai_speed:5000,
+-	      n_aochan:2,
+-	      aobits:	16,
+-	      ao_fifo_depth:0,
+-	      ao_range_table:&range_bipolar10,
+-	      ao_unipolar:0,
+-	      ao_speed:1000000,
+-	      num_p0_dio_channels:8,
+-	      has_8255:0,
+-	      caldac:	{ad8804_debug},
+-		},
++	{.device_id = 0x010d,
++	 .name = "DAQCard-ai-16xe-50",
++	 .n_adchan = 16,
++	 .adbits = 16,
++	 .ai_fifo_depth = 1024,
++	 .alwaysdither = 0,
++	 .gainlkup = ai_gain_8,
++	 .ai_speed = 5000,
++	 .n_aochan = 0,
++	 .aobits = 0,
++	 .ao_fifo_depth = 0,
++	 .ao_unipolar = 0,
++	 .num_p0_dio_channels = 8,
++	 .has_8255 = 0,
++	 .caldac = {dac8800, dac8043},
++	},
++	{.device_id = 0x010c,
++	 .name = "DAQCard-ai-16e-4",
++	 .n_adchan = 16,
++	 .adbits = 12,
++	 .ai_fifo_depth = 1024,
++	 .alwaysdither = 0,
++	 .gainlkup = ai_gain_16,
++	 .ai_speed = 4000,
++	 .n_aochan = 0,
++	 .aobits = 0,
++	 .ao_fifo_depth = 0,
++	 .ao_unipolar = 0,
++	 .num_p0_dio_channels = 8,
++	 .has_8255 = 0,
++	 .caldac = {mb88341},	/* verified */
++	},
++	{.device_id = 0x02c4,
++	 .name = "DAQCard-6062E",
++	 .n_adchan = 16,
++	 .adbits = 12,
++	 .ai_fifo_depth = 8192,
++	 .alwaysdither = 0,
++	 .gainlkup = ai_gain_16,
++	 .ai_speed = 2000,
++	 .n_aochan = 2,
++	 .aobits = 12,
++	 .ao_fifo_depth = 2048,
++	 .ao_range_table = &range_bipolar10,
++	 .ao_unipolar = 0,
++	 .ao_speed = 1176,
++	 .num_p0_dio_channels = 8,
++	 .has_8255 = 0,
++	 .caldac = {ad8804_debug},	/* verified */
++	},
++	{.device_id = 0x075e,
++	 .name = "DAQCard-6024E",	/* specs incorrect! */
++	 .n_adchan = 16,
++	 .adbits = 12,
++	 .ai_fifo_depth = 1024,
++	 .alwaysdither = 0,
++	 .gainlkup = ai_gain_16,
++	 .ai_speed = 5000,
++	 .n_aochan = 2,
++	 .aobits = 12,
++	 .ao_fifo_depth = 0,
++	 .ao_range_table = &range_bipolar10,
++	 .ao_unipolar = 0,
++	 .ao_speed = 1000000,
++	 .num_p0_dio_channels = 8,
++	 .has_8255 = 0,
++	 .caldac = {ad8804_debug},
++	},
++	{.device_id = 0x0245,
++	 .name = "DAQCard-6036E",	/* specs incorrect! */
++	 .n_adchan = 16,
++	 .adbits = 16,
++	 .ai_fifo_depth = 1024,
++	 .alwaysdither = 1,
++	 .gainlkup = ai_gain_4,
++	 .ai_speed = 5000,
++	 .n_aochan = 2,
++	 .aobits = 16,
++	 .ao_fifo_depth = 0,
++	 .ao_range_table = &range_bipolar10,
++	 .ao_unipolar = 0,
++	 .ao_speed = 1000000,
++	 .num_p0_dio_channels = 8,
++	 .has_8255 = 0,
++	 .caldac = {ad8804_debug},
++	},
+ #if 0
+-      {device_id:0x0000,	/* unknown */
+-	      name:	"DAQCard-6715",
+-	      n_adchan:0,
+-	      n_aochan:8,
+-	      aobits:	12,
+-	      ao_671x:	8192,
+-	      num_p0_dio_channels:8,
+-	      caldac:	{mb88341, mb88341},
+-		},
++	{.device_id = 0x0000,	/* unknown */
++	 .name = "DAQCard-6715",
++	 .n_adchan = 0,
++	 .n_aochan = 8,
++	 .aobits = 12,
++	 .ao_671x = 8192,
++	 .num_p0_dio_channels = 8,
++	 .caldac = {mb88341, mb88341},
++	},
+ #endif
+ 	/* N.B. Update ni_mio_cs_ids[] when entries added above. */
+ };
+@@ -230,10 +230,10 @@ static uint16_t mio_cs_win_in(struct comedi_device *dev, int addr)
+ static int mio_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int mio_cs_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_ni_mio_cs = {
+-      driver_name:"ni_mio_cs",
+-      module:THIS_MODULE,
+-      attach:mio_cs_attach,
+-      detach:mio_cs_detach,
++	.driver_name = "ni_mio_cs",
++	.module = THIS_MODULE,
++	.attach = mio_cs_attach,
++	.detach = mio_cs_detach,
+ };
+ 
+ #include "ni_mio_common.c"
+diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
+index ffd619b0916c..773ba0e07f86 100644
+--- a/drivers/staging/comedi/drivers/ni_pcidio.c
++++ b/drivers/staging/comedi/drivers/ni_pcidio.c
+@@ -292,10 +292,10 @@ static int nidio_detach(struct comedi_device *dev);
+ static int ni_pcidio_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
+ 
+ static struct comedi_driver driver_pcidio = {
+-      driver_name:"ni_pcidio",
+-      module:THIS_MODULE,
+-      attach:nidio_attach,
+-      detach:nidio_detach,
++	.driver_name = "ni_pcidio",
++	.module = THIS_MODULE,
++	.attach = nidio_attach,
++	.detach = nidio_detach,
+ };
+ 
+ struct nidio_board {
+@@ -309,65 +309,65 @@ struct nidio_board {
+ 
+ static const struct nidio_board nidio_boards[] = {
+ 	{
+-	      dev_id:	0x1150,
+-	      name:	"pci-dio-32hs",
+-	      n_8255:	0,
+-	      is_diodaq:1,
++	.dev_id = 0x1150,
++	.name = "pci-dio-32hs",
++	.n_8255 = 0,
++	.is_diodaq = 1,
+ 		},
+ 	{
+-	      dev_id:	0x1320,
+-	      name:	"pxi-6533",
+-	      n_8255:	0,
+-	      is_diodaq:1,
++	.dev_id = 0x1320,
++	.name = "pxi-6533",
++	.n_8255 = 0,
++	.is_diodaq = 1,
+ 		},
+ 	{
+-	      dev_id:	0x12b0,
+-	      name:	"pci-6534",
+-	      n_8255:	0,
+-	      is_diodaq:1,
+-	      uses_firmware:1,
++	.dev_id = 0x12b0,
++	.name = "pci-6534",
++	.n_8255 = 0,
++	.is_diodaq = 1,
++	.uses_firmware = 1,
+ 		},
+ 	{
+-	      dev_id:	0x0160,
+-	      name:	"pci-dio-96",
+-	      n_8255:	4,
+-	      is_diodaq:0,
++	.dev_id = 0x0160,
++	.name = "pci-dio-96",
++	.n_8255 = 4,
++	.is_diodaq = 0,
+ 		},
+ 	{
+-	      dev_id:	0x1630,
+-	      name:	"pci-dio-96b",
+-	      n_8255:	4,
+-	      is_diodaq:0,
++	.dev_id = 0x1630,
++	.name = "pci-dio-96b",
++	.n_8255 = 4,
++	.is_diodaq = 0,
+ 		},
+ 	{
+-	      dev_id:	0x13c0,
+-	      name:	"pxi-6508",
+-	      n_8255:	4,
+-	      is_diodaq:0,
++	.dev_id = 0x13c0,
++	.name = "pxi-6508",
++	.n_8255 = 4,
++	.is_diodaq = 0,
+ 		},
+ 	{
+-	      dev_id:	0x0400,
+-	      name:	"pci-6503",
+-	      n_8255:	1,
+-	      is_diodaq:0,
++	.dev_id = 0x0400,
++	.name = "pci-6503",
++	.n_8255 = 1,
++	.is_diodaq = 0,
+ 		},
+ 	{
+-	      dev_id:	0x1250,
+-	      name:	"pci-6503b",
+-	      n_8255:	1,
+-	      is_diodaq:0,
++	.dev_id = 0x1250,
++	.name = "pci-6503b",
++	.n_8255 = 1,
++	.is_diodaq = 0,
+ 		},
+ 	{
+-	      dev_id:	0x17d0,
+-	      name:	"pci-6503x",
+-	      n_8255:	1,
+-	      is_diodaq:0,
++	.dev_id = 0x17d0,
++	.name = "pci-6503x",
++	.n_8255 = 1,
++	.is_diodaq = 0,
+ 		},
+ 	{
+-	      dev_id:	0x1800,
+-	      name:	"pxi-6503",
+-	      n_8255:	1,
+-	      is_diodaq:0,
++	.dev_id = 0x1800,
++	.name = "pxi-6503",
++	.n_8255 = 1,
++	.is_diodaq = 0,
+ 		},
+ };
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
+index bfccafe6080b..17fcdce6657d 100644
+--- a/drivers/staging/comedi/drivers/ni_pcimio.c
++++ b/drivers/staging/comedi/drivers/ni_pcimio.c
+@@ -320,7 +320,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 			.ai_fifo_depth = 512,
+ 			.alwaysdither = 0,
+ 			.gainlkup = ai_gain_16,
+-			/* Note: there have been reported problems with full speed
++			/*	.Note = there have been reported problems with full speed
+ 			 * on this board */
+ 			.ai_speed = 2000,
+ 			.n_aochan = 2,
+@@ -846,7 +846,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 			.n_adchan = 16,
+ 			.adbits = 16,
+ 			.ai_fifo_depth = 512,
+-			/* FIXME:  guess */
++			/*	.FIXME = guess */
+ 			.gainlkup = ai_gain_622x,
+ 			.ai_speed = 4000,
+ 			.n_aochan = 0,
+@@ -1210,10 +1210,10 @@ static const struct ni_board_struct ni_boards[] = {
+ static int pcimio_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int pcimio_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_pcimio = {
+-	driver_name: DRV_NAME,
+-	module:THIS_MODULE,
+-	attach:pcimio_attach,
+-	detach:pcimio_detach,
++	.driver_name = DRV_NAME,
++	.module = THIS_MODULE,
++	.attach = pcimio_attach,
++	.detach = pcimio_detach,
+ };
+ 
+ COMEDI_PCI_INITCLEANUP(driver_pcimio, ni_pci_table)
+diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c
+index e1a4917fc3ce..c5bcd641aa13 100644
+--- a/drivers/staging/comedi/drivers/pcl711.c
++++ b/drivers/staging/comedi/drivers/pcl711.c
+@@ -159,13 +159,13 @@ static const struct pcl711_board boardtypes[] = {
+ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int pcl711_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_pcl711 = {
+-      driver_name:"pcl711",
+-      module:THIS_MODULE,
+-      attach:pcl711_attach,
+-      detach:pcl711_detach,
+-      board_name:&boardtypes[0].name,
+-      num_names:n_boardtypes,
+-      offset:sizeof(struct pcl711_board),
++	.driver_name = "pcl711",
++	.module = THIS_MODULE,
++	.attach = pcl711_attach,
++	.detach = pcl711_detach,
++	.board_name = &boardtypes[0].name,
++	.num_names = n_boardtypes,
++	.offset = sizeof(struct pcl711_board),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_pcl711);
+diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c
+index 5d3ba759e862..b970d3d19144 100644
+--- a/drivers/staging/comedi/drivers/pcl724.c
++++ b/drivers/staging/comedi/drivers/pcl724.c
+@@ -84,13 +84,13 @@ static const struct pcl724_board boardtypes[] = {
+ #define this_board ((const struct pcl724_board *)dev->board_ptr)
+ 
+ static struct comedi_driver driver_pcl724 = {
+-      driver_name:"pcl724",
+-      module:THIS_MODULE,
+-      attach:pcl724_attach,
+-      detach:pcl724_detach,
+-      board_name:&boardtypes[0].name,
+-      num_names:n_boardtypes,
+-      offset:sizeof(struct pcl724_board),
++	.driver_name = "pcl724",
++	.module = THIS_MODULE,
++	.attach = pcl724_attach,
++	.detach = pcl724_detach,
++	.board_name = &boardtypes[0].name,
++	.num_names = n_boardtypes,
++	.offset = sizeof(struct pcl724_board),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_pcl724);
+diff --git a/drivers/staging/comedi/drivers/pcl725.c b/drivers/staging/comedi/drivers/pcl725.c
+index 0941dc157a8f..1347624d0519 100644
+--- a/drivers/staging/comedi/drivers/pcl725.c
++++ b/drivers/staging/comedi/drivers/pcl725.c
+@@ -23,10 +23,10 @@ Devices: [Advantech] PCL-725 (pcl725)
+ static int pcl725_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int pcl725_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_pcl725 = {
+-      driver_name:"pcl725",
+-      module:THIS_MODULE,
+-      attach:pcl725_attach,
+-      detach:pcl725_detach,
++	.driver_name = "pcl725",
++	.module = THIS_MODULE,
++	.attach = pcl725_attach,
++	.detach = pcl725_detach,
+ };
+ 
+ COMEDI_INITCLEANUP(driver_pcl725);
+diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c
+index 408f1ef664f9..c3ce26b8d793 100644
+--- a/drivers/staging/comedi/drivers/pcl726.c
++++ b/drivers/staging/comedi/drivers/pcl726.c
+@@ -152,13 +152,13 @@ static const struct pcl726_board boardtypes[] = {
+ #define this_board ((const struct pcl726_board *)dev->board_ptr)
+ 
+ static struct comedi_driver driver_pcl726 = {
+-      driver_name:"pcl726",
+-      module:THIS_MODULE,
+-      attach:pcl726_attach,
+-      detach:pcl726_detach,
+-      board_name:&boardtypes[0].name,
+-      num_names:n_boardtypes,
+-      offset:sizeof(struct pcl726_board),
++	.driver_name = "pcl726",
++	.module = THIS_MODULE,
++	.attach = pcl726_attach,
++	.detach = pcl726_detach,
++	.board_name = &boardtypes[0].name,
++	.num_names = n_boardtypes,
++	.offset = sizeof(struct pcl726_board),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_pcl726);
+diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c
+index ca18cf08358d..408cbffae418 100644
+--- a/drivers/staging/comedi/drivers/pcl730.c
++++ b/drivers/staging/comedi/drivers/pcl730.c
+@@ -46,13 +46,13 @@ static const struct pcl730_board boardtypes[] = {
+ #define this_board ((const struct pcl730_board *)dev->board_ptr)
+ 
+ static struct comedi_driver driver_pcl730 = {
+-      driver_name:"pcl730",
+-      module:THIS_MODULE,
+-      attach:pcl730_attach,
+-      detach:pcl730_detach,
+-      board_name:&boardtypes[0].name,
+-      num_names:n_boardtypes,
+-      offset:sizeof(struct pcl730_board),
++	.driver_name = "pcl730",
++	.module = THIS_MODULE,
++	.attach = pcl730_attach,
++	.detach = pcl730_detach,
++	.board_name = &boardtypes[0].name,
++	.num_names = n_boardtypes,
++	.offset = sizeof(struct pcl730_board),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_pcl730);
+diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
+index 6a6e84a52521..3812c2a9cb9d 100644
+--- a/drivers/staging/comedi/drivers/pcl812.c
++++ b/drivers/staging/comedi/drivers/pcl812.c
+@@ -377,13 +377,13 @@ static const struct pcl812_board boardtypes[] = {
+ #define this_board ((const struct pcl812_board *)dev->board_ptr)
+ 
+ static struct comedi_driver driver_pcl812 = {
+-      driver_name:"pcl812",
+-      module:THIS_MODULE,
+-      attach:pcl812_attach,
+-      detach:pcl812_detach,
+-      board_name:&boardtypes[0].name,
+-      num_names:n_boardtypes,
+-      offset:sizeof(struct pcl812_board),
++	.driver_name = "pcl812",
++	.module = THIS_MODULE,
++	.attach = pcl812_attach,
++	.detach = pcl812_detach,
++	.board_name = &boardtypes[0].name,
++	.num_names = n_boardtypes,
++	.offset = sizeof(struct pcl812_board),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_pcl812);
+diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
+index c52ba0319a46..d269ac1b5ddc 100644
+--- a/drivers/staging/comedi/drivers/pcl816.c
++++ b/drivers/staging/comedi/drivers/pcl816.c
+@@ -157,13 +157,13 @@ static int RTC_timer_lock = 0;	/* RTC int lock */
+ #endif
+ 
+ static struct comedi_driver driver_pcl816 = {
+-      driver_name:"pcl816",
+-      module:THIS_MODULE,
+-      attach:pcl816_attach,
+-      detach:pcl816_detach,
+-      board_name:&boardtypes[0].name,
+-      num_names:n_boardtypes,
+-      offset:sizeof(struct pcl816_board),
++	.driver_name = "pcl816",
++	.module = THIS_MODULE,
++	.attach = pcl816_attach,
++	.detach = pcl816_detach,
++	.board_name = &boardtypes[0].name,
++	.num_names = n_boardtypes,
++	.offset = sizeof(struct pcl816_board),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_pcl816);
+diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
+index 6fbc9abdbd7b..acca36212773 100644
+--- a/drivers/staging/comedi/drivers/pcl818.c
++++ b/drivers/staging/comedi/drivers/pcl818.c
+@@ -302,13 +302,13 @@ static const struct pcl818_board boardtypes[] = {
+ #define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl818_board))
+ 
+ static struct comedi_driver driver_pcl818 = {
+-      driver_name:"pcl818",
+-      module:THIS_MODULE,
+-      attach:pcl818_attach,
+-      detach:pcl818_detach,
+-      board_name:&boardtypes[0].name,
+-      num_names:n_boardtypes,
+-      offset:sizeof(struct pcl818_board),
++	.driver_name = "pcl818",
++	.module = THIS_MODULE,
++	.attach = pcl818_attach,
++	.detach = pcl818_detach,
++	.board_name = &boardtypes[0].name,
++	.num_names = n_boardtypes,
++	.offset = sizeof(struct pcl818_board),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_pcl818);
+diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c
+index 36310adf5fb7..a5d6b1d9a1aa 100644
+--- a/drivers/staging/comedi/drivers/pcm3724.c
++++ b/drivers/staging/comedi/drivers/pcm3724.c
+@@ -87,13 +87,13 @@ static const struct pcm3724_board boardtypes[] = {
+ #define this_board ((const struct pcm3724_board *)dev->board_ptr)
+ 
+ static struct comedi_driver driver_pcm3724 = {
+-      driver_name:"pcm3724",
+-      module:THIS_MODULE,
+-      attach:pcm3724_attach,
+-      detach:pcm3724_detach,
+-      board_name:&boardtypes[0].name,
+-      num_names:n_boardtypes,
+-      offset:sizeof(struct pcm3724_board),
++	.driver_name = "pcm3724",
++	.module = THIS_MODULE,
++	.attach = pcm3724_attach,
++	.detach = pcm3724_detach,
++	.board_name = &boardtypes[0].name,
++	.num_names = n_boardtypes,
++	.offset = sizeof(struct pcm3724_board),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_pcm3724);
+diff --git a/drivers/staging/comedi/drivers/pcm3730.c b/drivers/staging/comedi/drivers/pcm3730.c
+index 1a65af1c6e45..ae90ea4ae3c9 100644
+--- a/drivers/staging/comedi/drivers/pcm3730.c
++++ b/drivers/staging/comedi/drivers/pcm3730.c
+@@ -31,10 +31,10 @@ Configuration options:
+ static int pcm3730_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int pcm3730_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_pcm3730 = {
+-      driver_name:"pcm3730",
+-      module:THIS_MODULE,
+-      attach:pcm3730_attach,
+-      detach:pcm3730_detach,
++	.driver_name = "pcm3730",
++	.module = THIS_MODULE,
++	.attach = pcm3730_attach,
++	.detach = pcm3730_detach,
+ };
+ 
+ COMEDI_INITCLEANUP(driver_pcm3730);
+diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c
+index f1e19cc2ac20..14f40df298eb 100644
+--- a/drivers/staging/comedi/drivers/pcmad.c
++++ b/drivers/staging/comedi/drivers/pcmad.c
+@@ -58,12 +58,12 @@ struct pcmad_board_struct {
+ };
+ static const struct pcmad_board_struct pcmad_boards[] = {
+ 	{
+-	      name:	"pcmad12",
+-	      n_ai_bits:12,
++	.name = "pcmad12",
++	.n_ai_bits = 12,
+ 		},
+ 	{
+-	      name:	"pcmad16",
+-	      n_ai_bits:16,
++	.name = "pcmad16",
++	.n_ai_bits = 16,
+ 		},
+ };
+ 
+@@ -79,13 +79,13 @@ struct pcmad_priv_struct {
+ static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int pcmad_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_pcmad = {
+-      driver_name:"pcmad",
+-      module:THIS_MODULE,
+-      attach:pcmad_attach,
+-      detach:pcmad_detach,
+-      board_name:&pcmad_boards[0].name,
+-      num_names:n_pcmad_boards,
+-      offset:sizeof(pcmad_boards[0]),
++	.driver_name = "pcmad",
++	.module = THIS_MODULE,
++	.attach = pcmad_attach,
++	.detach = pcmad_detach,
++	.board_name = &pcmad_boards[0].name,
++	.num_names = n_pcmad_boards,
++	.offset = sizeof(pcmad_boards[0]),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_pcmad);
+diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c
+index f2a959654d6c..7bc4d7ef9505 100644
+--- a/drivers/staging/comedi/drivers/pcmda12.c
++++ b/drivers/staging/comedi/drivers/pcmda12.c
+@@ -83,7 +83,7 @@ static const struct comedi_lrange pcmda12_ranges = {
+ 
+ static const struct pcmda12_board pcmda12_boards[] = {
+ 	{
+-	      name:	"pcmda12",
++	.name = "pcmda12",
+ 		},
+ };
+ 
+@@ -113,10 +113,10 @@ static int pcmda12_detach(struct comedi_device *dev);
+ static void zero_chans(struct comedi_device *dev);
+ 
+ static struct comedi_driver driver = {
+-      driver_name:"pcmda12",
+-      module:THIS_MODULE,
+-      attach:pcmda12_attach,
+-      detach:pcmda12_detach,
++	.driver_name = "pcmda12",
++	.module = THIS_MODULE,
++	.attach = pcmda12_attach,
++	.detach = pcmda12_detach,
+ /* It is not necessary to implement the following members if you are
+  * writing a driver for a ISA PnP or PCI card */
+ 	/* Most drivers will support multiple types of boards by
+@@ -135,9 +135,9 @@ static struct comedi_driver driver = {
+ 	 * the type of board in software.  ISA PnP, PCI, and PCMCIA
+ 	 * devices are such boards.
+ 	 */
+-      board_name:&pcmda12_boards[0].name,
+-      offset:sizeof(struct pcmda12_board),
+-      num_names:sizeof(pcmda12_boards) / sizeof(struct pcmda12_board),
++	.board_name = &pcmda12_boards[0].name,
++	.offset = sizeof(struct pcmda12_board),
++	.num_names = sizeof(pcmda12_boards) / sizeof(struct pcmda12_board),
+ };
+ 
+ static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
+diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
+index 82da558fc8f7..b9e8a1757365 100644
+--- a/drivers/staging/comedi/drivers/pcmmio.c
++++ b/drivers/staging/comedi/drivers/pcmmio.c
+@@ -179,19 +179,19 @@ static const struct comedi_lrange ranges_ao =
+ 
+ static const struct pcmmio_board pcmmio_boards[] = {
+ 	{
+-	      name:	"pcmmio",
+-	      dio_num_asics:1,
+-	      dio_num_ports:6,
+-	      total_iosize:32,
+-	      ai_bits:	16,
+-	      ao_bits:	16,
+-	      n_ai_chans:16,
+-	      n_ao_chans:8,
+-	      ai_range_table:&ranges_ai,
+-	      ao_range_table:&ranges_ao,
+-	      ai_rinsn:ai_rinsn,
+-	      ao_rinsn:ao_rinsn,
+-      ao_winsn:ao_winsn},
++	.name = "pcmmio",
++	.dio_num_asics = 1,
++	.dio_num_ports = 6,
++	.total_iosize = 32,
++	.ai_bits = 16,
++	.ao_bits = 16,
++	.n_ai_chans = 16,
++	.n_ao_chans = 8,
++	.ai_range_table = &ranges_ai,
++	.ao_range_table = &ranges_ao,
++	.ai_rinsn = ai_rinsn,
++	.ao_rinsn = ao_rinsn,
++	.ao_winsn = ao_winsn},
+ };
+ 
+ /*
+@@ -268,10 +268,10 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ static int pcmmio_detach(struct comedi_device *dev);
+ 
+ static struct comedi_driver driver = {
+-      driver_name:"pcmmio",
+-      module:THIS_MODULE,
+-      attach:pcmmio_attach,
+-      detach:pcmmio_detach,
++	.driver_name = "pcmmio",
++	.module = THIS_MODULE,
++	.attach = pcmmio_attach,
++	.detach = pcmmio_detach,
+ /* It is not necessary to implement the following members if you are
+  * writing a driver for a ISA PnP or PCI card */
+ 	/* Most drivers will support multiple types of boards by
+@@ -290,9 +290,9 @@ static struct comedi_driver driver = {
+ 	 * the type of board in software.  ISA PnP, PCI, and PCMCIA
+ 	 * devices are such boards.
+ 	 */
+-      board_name:&pcmmio_boards[0].name,
+-      offset:sizeof(struct pcmmio_board),
+-      num_names:sizeof(pcmmio_boards) / sizeof(struct pcmmio_board),
++	.board_name = &pcmmio_boards[0].name,
++	.offset = sizeof(struct pcmmio_board),
++	.num_names = sizeof(pcmmio_boards) / sizeof(struct pcmmio_board),
+ };
+ 
+ static int pcmmio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
+index cc62f518128e..e02017369f72 100644
+--- a/drivers/staging/comedi/drivers/pcmuio.c
++++ b/drivers/staging/comedi/drivers/pcmuio.c
+@@ -155,14 +155,14 @@ struct pcmuio_board {
+ 
+ static const struct pcmuio_board pcmuio_boards[] = {
+ 	{
+-	      name:	"pcmuio48",
+-	      num_asics:1,
+-	      num_ports:6,
++	.name = "pcmuio48",
++	.num_asics = 1,
++	.num_ports = 6,
+ 		},
+ 	{
+-	      name:	"pcmuio96",
+-	      num_asics:2,
+-	      num_ports:12,
++	.name = "pcmuio96",
++	.num_asics = 2,
++	.num_ports = 12,
+ 		},
+ };
+ 
+@@ -226,10 +226,10 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ static int pcmuio_detach(struct comedi_device *dev);
+ 
+ static struct comedi_driver driver = {
+-      driver_name:"pcmuio",
+-      module:THIS_MODULE,
+-      attach:pcmuio_attach,
+-      detach:pcmuio_detach,
++	.driver_name = "pcmuio",
++	.module = THIS_MODULE,
++	.attach = pcmuio_attach,
++	.detach = pcmuio_detach,
+ /* It is not necessary to implement the following members if you are
+  * writing a driver for a ISA PnP or PCI card */
+ 	/* Most drivers will support multiple types of boards by
+@@ -248,9 +248,9 @@ static struct comedi_driver driver = {
+ 	 * the type of board in software.  ISA PnP, PCI, and PCMCIA
+ 	 * devices are such boards.
+ 	 */
+-      board_name:&pcmuio_boards[0].name,
+-      offset:sizeof(struct pcmuio_board),
+-      num_names:sizeof(pcmuio_boards) / sizeof(struct pcmuio_board),
++	.board_name = &pcmuio_boards[0].name,
++	.offset = sizeof(struct pcmuio_board),
++	.num_names = sizeof(pcmuio_boards) / sizeof(struct pcmuio_board),
+ };
+ 
+ static int pcmuio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c
+index f8f5a7366aae..47850bd15484 100644
+--- a/drivers/staging/comedi/drivers/poc.c
++++ b/drivers/staging/comedi/drivers/poc.c
+@@ -70,33 +70,33 @@ struct boarddef_struct {
+ };
+ static const struct boarddef_struct boards[] = {
+ 	{
+-	      name:	"dac02",
+-	      iosize:	8,
+-			/* setup:                dac02_setup, */
+-	      type:	COMEDI_SUBD_AO,
+-	      n_chan:	2,
+-	      n_bits:	12,
+-	      winsn:	dac02_ao_winsn,
+-	      rinsn:	readback_insn,
+-	      range:	&range_unknown,
++	.name = "dac02",
++	.iosize = 8,
++			/*	.setup = dac02_setup, */
++	.type = COMEDI_SUBD_AO,
++	.n_chan = 2,
++	.n_bits = 12,
++	.winsn = dac02_ao_winsn,
++	.rinsn = readback_insn,
++	.range = &range_unknown,
+ 		},
+ 	{
+-	      name:	"pcl733",
+-	      iosize:	4,
+-	      type:	COMEDI_SUBD_DI,
+-	      n_chan:	32,
+-	      n_bits:	1,
+-	      insnbits:pcl733_insn_bits,
+-	      range:	&range_digital,
++	.name = "pcl733",
++	.iosize = 4,
++	.type = COMEDI_SUBD_DI,
++	.n_chan = 32,
++	.n_bits = 1,
++	.insnbits = pcl733_insn_bits,
++	.range = &range_digital,
+ 		},
+ 	{
+-	      name:	"pcl734",
+-	      iosize:	4,
+-	      type:	COMEDI_SUBD_DO,
+-	      n_chan:	32,
+-	      n_bits:	1,
+-	      insnbits:pcl734_insn_bits,
+-	      range:	&range_digital,
++	.name = "pcl734",
++	.iosize = 4,
++	.type = COMEDI_SUBD_DO,
++	.n_chan = 32,
++	.n_bits = 1,
++	.insnbits = pcl734_insn_bits,
++	.range = &range_digital,
+ 		},
+ };
+ 
+@@ -104,13 +104,13 @@ static const struct boarddef_struct boards[] = {
+ #define this_board ((const struct boarddef_struct *)dev->board_ptr)
+ 
+ static struct comedi_driver driver_poc = {
+-      driver_name:"poc",
+-      module:THIS_MODULE,
+-      attach:poc_attach,
+-      detach:poc_detach,
+-      board_name:&boards[0].name,
+-      num_names:n_boards,
+-      offset:sizeof(boards[0]),
++	.driver_name = "poc",
++	.module = THIS_MODULE,
++	.attach = poc_attach,
++	.detach = poc_detach,
++	.board_name = &boards[0].name,
++	.num_names = n_boards,
++	.offset = sizeof(boards[0]),
+ };
+ 
+ static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+index d6427e2fc14c..85b53c93e135 100644
+--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
++++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+@@ -179,8 +179,8 @@ static struct local_info_t *dev_table[MAX_DEV] = { NULL, /* ... */  };
+ #define DAQP_AUX_FIFO_EMPTY		0x01
+ 
+ /* These range structures tell COMEDI how the sample values map to
+- * voltages.  The A/D converter has four ranges: +/- 10V through
+- * +/- 1.25V, and the D/A converter has only one: +/- 5V.
++ * voltages.  The A/D converter has four	.ranges = +/- 10V through
++ * +/- 1.25V, and the D/A converter has only	.one = +/- 5V.
+  */
+ 
+ static const struct comedi_lrange range_daqp_ai = { 4, {
+@@ -200,10 +200,10 @@ static const struct comedi_lrange range_daqp_ao = { 1, {BIP_RANGE(5)} };
+ static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int daqp_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_daqp = {
+-      driver_name:"quatech_daqp_cs",
+-      module:THIS_MODULE,
+-      attach:daqp_attach,
+-      detach:daqp_detach,
++	.driver_name = "quatech_daqp_cs",
++	.module = THIS_MODULE,
++	.attach = daqp_attach,
++	.detach = daqp_detach,
+ };
+ 
+ #ifdef DAQP_DEBUG
+diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c
+index b2579f42573c..57541d52a159 100644
+--- a/drivers/staging/comedi/drivers/rti800.c
++++ b/drivers/staging/comedi/drivers/rti800.c
+@@ -134,13 +134,13 @@ static const struct rti800_board boardtypes[] = {
+ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int rti800_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_rti800 = {
+-      driver_name:"rti800",
+-      module:THIS_MODULE,
+-      attach:rti800_attach,
+-      detach:rti800_detach,
+-      num_names:sizeof(boardtypes) / sizeof(struct rti800_board),
+-      board_name:&boardtypes[0].name,
+-      offset:sizeof(struct rti800_board),
++	.driver_name = "rti800",
++	.module = THIS_MODULE,
++	.attach = rti800_attach,
++	.detach = rti800_detach,
++	.num_names = sizeof(boardtypes) / sizeof(struct rti800_board),
++	.board_name = &boardtypes[0].name,
++	.offset = sizeof(struct rti800_board),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_rti800);
+diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c
+index ec64c9ee0a54..fffde45a352b 100644
+--- a/drivers/staging/comedi/drivers/rti802.c
++++ b/drivers/staging/comedi/drivers/rti802.c
+@@ -50,10 +50,10 @@ Configuration Options:
+ static int rti802_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int rti802_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_rti802 = {
+-      driver_name:"rti802",
+-      module:THIS_MODULE,
+-      attach:rti802_attach,
+-      detach:rti802_detach,
++	.driver_name = "rti802",
++	.module = THIS_MODULE,
++	.attach = rti802_attach,
++	.detach = rti802_detach,
+ };
+ 
+ COMEDI_INITCLEANUP(driver_rti802);
+diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
+index 54c24a266fbc..d9b8f837bfdb 100644
+--- a/drivers/staging/comedi/drivers/s526.c
++++ b/drivers/staging/comedi/drivers/s526.c
+@@ -169,14 +169,14 @@ struct s526_board {
+ 
+ static const struct s526_board s526_boards[] = {
+ 	{
+-	      name:	"s526",
+-	      gpct_chans:4,
+-	      gpct_bits:24,
+-	      ad_chans:8,
+-	      ad_bits:	16,
+-	      da_chans:4,
+-	      da_bits:	16,
+-	      have_dio:1,
++	.name = "s526",
++	.gpct_chans = 4,
++	.gpct_bits = 24,
++	.ad_chans = 8,
++	.ad_bits = 16,
++	.da_chans = 4,
++	.da_bits = 16,
++	.have_dio = 1,
+ 		}
+ };
+ 
+@@ -220,10 +220,10 @@ struct s526_private {
+ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int s526_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_s526 = {
+-      driver_name:"s526",
+-      module:THIS_MODULE,
+-      attach:s526_attach,
+-      detach:s526_detach,
++	.driver_name = "s526",
++	.module = THIS_MODULE,
++	.attach = s526_attach,
++	.detach = s526_detach,
+ /* It is not necessary to implement the following members if you are
+  * writing a driver for a ISA PnP or PCI card */
+ 	/* Most drivers will support multiple types of boards by
+@@ -242,9 +242,9 @@ static struct comedi_driver driver_s526 = {
+ 	 * the type of board in software.  ISA PnP, PCI, and PCMCIA
+ 	 * devices are such boards.
+ 	 */
+-      board_name:&s526_boards[0].name,
+-      offset:sizeof(struct s526_board),
+-      num_names:sizeof(s526_boards) / sizeof(struct s526_board),
++	.board_name = &s526_boards[0].name,
++	.offset = sizeof(struct s526_board),
++	.num_names = sizeof(s526_boards) / sizeof(struct s526_board),
+ };
+ 
+ static int s526_gpct_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
+diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
+index 278d754049a5..cf3e925261a0 100644
+--- a/drivers/staging/comedi/drivers/serial2002.c
++++ b/drivers/staging/comedi/drivers/serial2002.c
+@@ -52,7 +52,7 @@ struct serial2002_board {
+ 
+ static const struct serial2002_board serial2002_boards[] = {
+ 	{
+-      name:	"serial2002"}
++	.name = "serial2002"}
+ };
+ 
+ /*
+@@ -92,13 +92,13 @@ struct serial2002_private {
+ static int serial2002_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int serial2002_detach(struct comedi_device *dev);
+ struct comedi_driver driver_serial2002 = {
+-      driver_name:"serial2002",
+-      module:THIS_MODULE,
+-      attach:serial2002_attach,
+-      detach:serial2002_detach,
+-      board_name:&serial2002_boards[0].name,
+-      offset:sizeof(struct serial2002_board),
+-      num_names:sizeof(serial2002_boards) / sizeof(struct serial2002_board),
++	.driver_name = "serial2002",
++	.module = THIS_MODULE,
++	.attach = serial2002_attach,
++	.detach = serial2002_detach,
++	.board_name = &serial2002_boards[0].name,
++	.offset = sizeof(struct serial2002_board),
++	.num_names = sizeof(serial2002_boards) / sizeof(struct serial2002_board),
+ };
+ 
+ static int serial2002_di_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
+diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c
+index fe49310941d6..a0764f81917b 100644
+--- a/drivers/staging/comedi/drivers/skel.c
++++ b/drivers/staging/comedi/drivers/skel.c
+@@ -97,16 +97,16 @@ struct skel_board {
+ 
+ static const struct skel_board skel_boards[] = {
+ 	{
+-	      name:	"skel-100",
+-	      ai_chans:16,
+-	      ai_bits:	12,
+-	      have_dio:1,
++	.name = "skel-100",
++	.ai_chans = 16,
++	.ai_bits = 12,
++	.have_dio = 1,
+ 		},
+ 	{
+-	      name:	"skel-200",
+-	      ai_chans:8,
+-	      ai_bits:	16,
+-	      have_dio:0,
++	.name = "skel-200",
++	.ai_chans = 8,
++	.ai_bits = 16,
++	.have_dio = 0,
+ 		},
+ };
+ 
+@@ -157,10 +157,10 @@ struct skel_private {
+ static int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int skel_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_skel = {
+-      driver_name:"dummy",
+-      module:THIS_MODULE,
+-      attach:skel_attach,
+-      detach:skel_detach,
++	.driver_name = "dummy",
++	.module = THIS_MODULE,
++	.attach = skel_attach,
++	.detach = skel_detach,
+ /* It is not necessary to implement the following members if you are
+  * writing a driver for a ISA PnP or PCI card */
+ 	/* Most drivers will support multiple types of boards by
+@@ -179,9 +179,9 @@ static struct comedi_driver driver_skel = {
+ 	 * the type of board in software.  ISA PnP, PCI, and PCMCIA
+ 	 * devices are such boards.
+ 	 */
+-      board_name:&skel_boards[0].name,
+-      offset:sizeof(struct skel_board),
+-      num_names:sizeof(skel_boards) / sizeof(struct skel_board),
++	.board_name = &skel_boards[0].name,
++	.offset = sizeof(struct skel_board),
++	.num_names = sizeof(skel_boards) / sizeof(struct skel_board),
+ };
+ 
+ static int skel_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
+diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c
+index 847695a62819..b12c42991bba 100644
+--- a/drivers/staging/comedi/drivers/ssv_dnp.c
++++ b/drivers/staging/comedi/drivers/ssv_dnp.c
+@@ -61,10 +61,10 @@ struct dnp_board {
+ 
+ static const struct dnp_board dnp_boards[] = {	/* we only support one DNP 'board'   */
+ 	{			/* variant at the moment             */
+-	      name:	"dnp-1486",
+-	      ai_chans:16,
+-	      ai_bits:	12,
+-	      have_dio:1,
++	.name = "dnp-1486",
++	.ai_chans = 16,
++	.ai_bits = 12,
++	.have_dio = 1,
+ 		},
+ };
+ 
+@@ -92,14 +92,14 @@ static int dnp_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int dnp_detach(struct comedi_device *dev);
+ 
+ static struct comedi_driver driver_dnp = {
+-      driver_name:"ssv_dnp",
+-      module:THIS_MODULE,
+-      attach:dnp_attach,
+-      detach:dnp_detach,
+-      board_name:&dnp_boards[0].name,
++	.driver_name = "ssv_dnp",
++	.module = THIS_MODULE,
++	.attach = dnp_attach,
++	.detach = dnp_detach,
++	.board_name = &dnp_boards[0].name,
+ 	/* only necessary for non-PnP devs   */
+-      offset:sizeof(struct dnp_board),/* like ISA-PnP, PCI or PCMCIA.      */
+-      num_names:sizeof(dnp_boards) / sizeof(struct dnp_board),
++	.offset = sizeof(struct dnp_board),/* like ISA-PnP, PCI or PCMCIA.      */
++	.num_names = sizeof(dnp_boards) / sizeof(struct dnp_board),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_dnp);
+diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c
+index 18e5ddf6f968..e308f5f89305 100644
+--- a/drivers/staging/comedi/drivers/unioxx5.c
++++ b/drivers/staging/comedi/drivers/unioxx5.c
+@@ -103,10 +103,10 @@ static int __unioxx5_define_chan_offset(int chan_num);
+ static void __unioxx5_analog_config(struct unioxx5_subd_priv *usp, int channel);
+ 
+ static struct comedi_driver unioxx5_driver = {
+-      driver_name:DRIVER_NAME,
+-      module:THIS_MODULE,
+-      attach:unioxx5_attach,
+-      detach:unioxx5_detach
++	.driver_name = DRIVER_NAME,
++	.module = THIS_MODULE,
++	.attach = unioxx5_attach,
++	.detach = unioxx5_detach
+ };
+ 
+ COMEDI_INITCLEANUP(unioxx5_driver);

commit dae0dc30be7fa21b15a9d9534589286c6c3e68a3
+Author: Bill Pemberton 
+Date:   Wed Apr 22 21:11:48 2009 -0400
+
+    Staging: comedi: Remove parens around return values
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+index cd41e39bbced..a6115f480546 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+@@ -396,7 +396,7 @@ int i_APCI1710_InsnConfigInitTimer(struct comedi_device *dev, struct comedi_subd
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -552,7 +552,7 @@ int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -663,7 +663,7 @@ int i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, struct comedi_su
+ 		}
+ 
+ 	}			/*  End of Switch */
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -727,7 +727,7 @@ int i_APCI1710_InsnBitsTimer(struct comedi_device *dev, struct comedi_subdevice
+ 
+ 	if (i_ReturnValue >= 0)
+ 		i_ReturnValue = insn->n;
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -812,7 +812,7 @@ int i_APCI1710_ReadTimerValue(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ 	/*
+@@ -891,7 +891,7 @@ int i_APCI1710_GetTimerOutputLevel(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+index 24fd81333b83..6aab4290cea2 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+@@ -780,7 +780,7 @@ int i_APCI1710_InsnConfigInitChrono(struct comedi_device *dev, struct comedi_sub
+ 		i_ReturnValue = -2;
+ 	}
+ 	data[0] = ul_RealTimingInterval;
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -1072,7 +1072,7 @@ int i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -1152,7 +1152,7 @@ int i_APCI1710_InsnReadChrono(struct comedi_device *dev, struct comedi_subdevice
+ 
+ 	if (i_ReturnValue >= 0)
+ 		i_ReturnValue = insn->n;
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ 
+ }
+ 
+@@ -1289,7 +1289,7 @@ int i_APCI1710_GetChronoProgressStatus(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -1575,7 +1575,7 @@ int i_APCI1710_ReadChronoValue(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -1752,7 +1752,7 @@ int i_APCI1710_ConvertChronoValue(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -2028,5 +2028,5 @@ int i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+index 2fb05f392d5f..2047c46f1389 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+@@ -433,7 +433,7 @@ int i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -671,7 +671,7 @@ int i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -1021,5 +1021,5 @@ int i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device *dev,
+ 		i_ReturnValue = -9;
+ 		DPRINTK("NO INPUT/OUTPUT specified\n");
+ 	}			/* switch INPUT / OUTPUT */
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+index 5041f651091b..db03acf99f49 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+@@ -136,7 +136,7 @@ int i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev, struct comedi_subdevi
+ 
+ 	if (i_ReturnValue >= 0)
+ 		i_ReturnValue = insn->n;
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -502,7 +502,7 @@ int i_APCI1710_InitCounter(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -627,7 +627,7 @@ int i_APCI1710_CounterAutoTest(struct comedi_device *dev, unsigned char *pb_Test
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -1113,7 +1113,7 @@ int i_APCI1710_InitIndex(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -1239,7 +1239,7 @@ int i_APCI1710_InitReference(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -1362,7 +1362,7 @@ int i_APCI1710_InitExternalStrobe(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ 	/*
+@@ -1434,7 +1434,7 @@ int i_APCI1710_InitCompareLogic(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -1992,7 +1992,7 @@ int i_APCI1710_InitFrequencyMeasurement(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*########################################################################### */
+@@ -2065,7 +2065,7 @@ int i_APCI1710_InsnBitsINCCPT(struct comedi_device *dev, struct comedi_subdevice
+ 
+ 	if (i_ReturnValue >= 0)
+ 		i_ReturnValue = insn->n;
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -2131,7 +2131,7 @@ int i_APCI1710_ClearCounterValue(struct comedi_device *dev, unsigned char b_Modu
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -2198,7 +2198,7 @@ int i_APCI1710_ClearAllCounterValue(struct comedi_device *dev)
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -2530,7 +2530,7 @@ int i_APCI1710_SetInputFilter(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -2616,7 +2616,7 @@ int i_APCI1710_LatchCounter(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -2769,7 +2769,7 @@ int i_APCI1710_SetIndexAndReferenceSource(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -2849,7 +2849,7 @@ int i_APCI1710_SetDigitalChlOn(struct comedi_device *dev, unsigned char b_ModulN
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -2929,7 +2929,7 @@ int i_APCI1710_SetDigitalChlOff(struct comedi_device *dev, unsigned char b_Modul
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*########################################################################### */
+@@ -3018,7 +3018,7 @@ int i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev, struct comedi_subdevic
+ 
+ 	if (i_ReturnValue >= 0)
+ 		i_ReturnValue = insn->n;
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -3105,7 +3105,7 @@ int i_APCI1710_EnableLatchInterrupt(struct comedi_device *dev, unsigned char b_M
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -3198,7 +3198,7 @@ int i_APCI1710_DisableLatchInterrupt(struct comedi_device *dev, unsigned char b_
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -3288,7 +3288,7 @@ int i_APCI1710_Write16BitCounterValue(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -3357,7 +3357,7 @@ int i_APCI1710_Write32BitCounterValue(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -3455,7 +3455,7 @@ int i_APCI1710_EnableIndex(struct comedi_device *dev, unsigned char b_ModulNbr)
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -3549,7 +3549,7 @@ int i_APCI1710_DisableIndex(struct comedi_device *dev, unsigned char b_ModulNbr)
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -3653,7 +3653,7 @@ int i_APCI1710_EnableCompareLogic(struct comedi_device *dev, unsigned char b_Mod
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -3753,7 +3753,7 @@ int i_APCI1710_DisableCompareLogic(struct comedi_device *dev, unsigned char b_Mo
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ 	/*
+@@ -3909,7 +3909,7 @@ int i_APCI1710_EnableFrequencyMeasurement(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ 	/*
+@@ -4026,7 +4026,7 @@ int i_APCI1710_DisableFrequencyMeasurement(struct comedi_device *dev, unsigned c
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*########################################################################### */
+@@ -4155,7 +4155,7 @@ int i_APCI1710_InsnReadINCCPT(struct comedi_device *dev, struct comedi_subdevice
+ 
+ 	if (i_ReturnValue >= 0)
+ 		i_ReturnValue = insn->n;
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ 
+ }
+ 
+@@ -4248,7 +4248,7 @@ int i_APCI1710_ReadLatchRegisterStatus(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -4332,7 +4332,7 @@ int i_APCI1710_ReadLatchRegisterValue(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -4431,7 +4431,7 @@ int i_APCI1710_Read16BitCounterValue(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -4507,7 +4507,7 @@ int i_APCI1710_Read32BitCounterValue(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -4590,7 +4590,7 @@ int i_APCI1710_GetIndexStatus(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -4676,7 +4676,7 @@ int i_APCI1710_GetReferenceStatus(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -4744,7 +4744,7 @@ int i_APCI1710_GetUASStatus(struct comedi_device *dev,
+ 
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -4812,7 +4812,7 @@ int i_APCI1710_GetCBStatus(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -4937,7 +4937,7 @@ int i_APCI1710_Get16BitCBStatus(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}			/*  if (b_ModulNbr < 4) */
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -5007,7 +5007,7 @@ int i_APCI1710_GetUDStatus(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -5100,7 +5100,7 @@ int i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ 	/*
+@@ -5359,5 +5359,5 @@ int i_APCI1710_ReadFrequencyMeasurement(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+index b7b0a07d5573..b6e2e3fd49ff 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+@@ -346,7 +346,7 @@ int i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -656,7 +656,7 @@ int i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -831,7 +831,7 @@ int i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ int i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device *dev,
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+index 25b33d5b270e..f330093ee3bb 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+@@ -111,7 +111,7 @@ int i_APCI1710_InsnConfigPWM(struct comedi_device *dev, struct comedi_subdevice
+ 
+ 	if (i_ReturnValue >= 0)
+ 		i_ReturnValue = insn->n;
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -1436,7 +1436,7 @@ int i_APCI1710_InitPWM(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -1665,7 +1665,7 @@ int i_APCI1710_GetPWMInitialisation(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -1718,7 +1718,7 @@ int i_APCI1710_InsnWritePWM(struct comedi_device *dev, struct comedi_subdevice *
+ 
+ 	if (i_ReturnValue >= 0)
+ 		i_ReturnValue = insn->n;
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -2029,7 +2029,7 @@ int i_APCI1710_EnablePWM(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -2144,7 +2144,7 @@ int i_APCI1710_DisablePWM(struct comedi_device *dev, unsigned char b_ModulNbr, u
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -3411,7 +3411,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -3558,7 +3558,7 @@ int i_APCI1710_InsnReadGetPWMStatus(struct comedi_device *dev, struct comedi_sub
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ int i_APCI1710_InsnBitsReadPWMInterrupt(struct comedi_device *dev,
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+index c1f88cc668a4..7705b7b30579 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+@@ -351,7 +351,7 @@ int i_APCI1710_InsnConfigInitSSI(struct comedi_device *dev, struct comedi_subdev
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -695,7 +695,7 @@ int i_APCI1710_InsnReadSSIValue(struct comedi_device *dev, struct comedi_subdevi
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -844,5 +844,5 @@ int i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev, struct comedi_sub
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+index da094a413e03..a9b64e9f745c 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+@@ -858,7 +858,7 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 	data[0] = (unsigned int) ul_RealTimingInterval;
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -1375,7 +1375,7 @@ int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -1637,7 +1637,7 @@ int i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -2045,5 +2045,5 @@ int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+index 854f79ccca2a..9d32aba3cf3f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+@@ -340,7 +340,7 @@ int i_APCI1710_InsnConfigInitTTLIO(struct comedi_device *dev, struct comedi_subd
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -628,7 +628,7 @@ int i_APCI1710_InsnBitsReadTTLIO(struct comedi_device *dev, struct comedi_subdev
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -777,7 +777,7 @@ int i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -1034,5 +1034,5 @@ int i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,
+ 		i_ReturnValue = -2;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
+index 15d378a465f5..6ada45a46d67 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
+@@ -199,5 +199,5 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 		w_EepromStartAddress += 2;	/*  to read the next word */
+ 
+ 	}			/*  for (...) i_NbOfWordsToRead */
+-	return (0);
++	return 0;
+ }
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+index 162566d5006c..ccb35aee68b5 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+@@ -348,7 +348,7 @@ unsigned short w_EepromReadWord(unsigned short w_PCIBoardEepromAddress, char *pc
+ 
+ 	}
+ 
+-	return (w_ReadWord);
++	return w_ReadWord;
+ 
+ }
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+index bbe813b8119f..236b8a31c824 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+@@ -1209,7 +1209,7 @@ int i_APCI1500_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subde
+ 		}		/* if else data[3]==1) */
+ 	}			/* if else data[3]==0) */
+ 	ui_Temp = data[0];
+-	return (insn->n);;
++	return insn->n;
+ }
+ 
+ /*
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
+index 5b7e8e8f28ad..eab7ac1d0f0b 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
+@@ -239,7 +239,7 @@ int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device *dev,
+ 		}
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -405,7 +405,7 @@ int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device *dev,
+ 		}
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -524,7 +524,7 @@ int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
+ 		i_ReturnValue = -100;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -758,7 +758,7 @@ int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device *dev,
+ 			devpriv->iobase + 20 + ((b_SelectedPort / 4) * 4));
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
+index 6069894d7f33..ec817082d170 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
+@@ -290,7 +290,7 @@ int i_APCI2032_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subde
+ 			return -EINVAL;
+ 		}		/* if else data[3]==1) */
+ 	}			/* if else data[3]==0) */
+-	return (insn->n);;
++	return insn->n;
+ }
+ 
+ /*
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
+index 9846997e8d28..a853c62a4fd9 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
+@@ -330,7 +330,7 @@ int i_APCI2200_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subde
+ 			return -EINVAL;
+ 		}		/* if else data[3]==1) */
+ 	}			/* if else data[3]==0) */
+-	return (insn->n);;
++	return insn->n;
+ }
+ 
+ /*
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+index 2b9a38f8ab3c..26aaeaf25683 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+@@ -2576,7 +2576,7 @@ int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev,
+ 
+ /* ES05        ui_Temp=data[0] & 0xf0; */
+ 	devpriv->b_DigitalOutputRegister = data[0] & 0xf0;
+-	return (insn->n);
++	return insn->n;
+ 
+ }
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+index 1e591a42dd65..7dda06653402 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+@@ -243,7 +243,7 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 		w_EepromStartAddress += 2;	/*  to read the next word */
+ 
+ 	}			/*  for (...) i_NbOfWordsToRead */
+-	return (0);
++	return 0;
+ }
+ 
+ /*+----------------------------------------------------------------------------+*/
+@@ -522,7 +522,7 @@ int i_APCI3200_GetChannelCalibrationValue(struct comedi_device *dev,
+ #endif
+ 	/* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ 
+-	return (0);
++	return 0;
+ }
+ 
+ /* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+index fd74c409b846..30594c8acd35 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+@@ -70,11 +70,11 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ 
+ int i_APCI3XXX_TestConversionStarted(struct comedi_device *dev)
+ {
+-	if ((readl((void *)(devpriv->dw_AiBase + 8)) & 0x80000UL) == 0x80000UL) {
+-		return (1);
+-	} else {
+-		return (0);
+-	}
++	if ((readl((void *)(devpriv->dw_AiBase + 8)) & 0x80000UL) == 0x80000UL)
++		return 1;
++	else
++		return 0;
++
+ }
+ 
+ /*
+@@ -268,7 +268,7 @@ int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device *dev,
+ 		i_ReturnValue = -101;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -326,7 +326,7 @@ int i_APCI3XXX_InsnConfigAnalogInput(struct comedi_device *dev,
+ 		i_ReturnValue = -101;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -585,7 +585,7 @@ int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device *dev,
+ 		printk("Operating mode not configured\n");
+ 		i_ReturnValue = -1;
+ 	}
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -757,7 +757,7 @@ int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device *dev,
+ 		i_ReturnValue = -101;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -888,7 +888,7 @@ int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device *dev,
+ 		}
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -1051,7 +1051,7 @@ int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device *dev,
+ 		i_ReturnValue = -101;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -1157,7 +1157,7 @@ int i_APCI3XXX_InsnReadTTLIO(struct comedi_device *dev,
+ 		i_ReturnValue = -101;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -1269,7 +1269,7 @@ int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device *dev,
+ 		i_ReturnValue = -101;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -1334,7 +1334,7 @@ int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device *dev,
+ 		i_ReturnValue = -3;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -1378,7 +1378,7 @@ int i_APCI3XXX_InsnBitsDigitalInput(struct comedi_device *dev,
+ 		i_ReturnValue = -101;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -1481,7 +1481,7 @@ int i_APCI3XXX_InsnBitsDigitalOutput(struct comedi_device *dev,
+ 		i_ReturnValue = -101;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -1557,7 +1557,7 @@ int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device *dev,
+ 		i_ReturnValue = -101;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+@@ -1622,7 +1622,7 @@ int i_APCI3XXX_InsnReadDigitalOutput(struct comedi_device *dev,
+ 		i_ReturnValue = -101;
+ 	}
+ 
+-	return (i_ReturnValue);
++	return i_ReturnValue;
+ }
+ 
+ /*
+diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c
+index abd20dfec08c..0c212ecc76ca 100644
+--- a/drivers/staging/comedi/drivers/c6xdigio.c
++++ b/drivers/staging/comedi/drivers/c6xdigio.c
+@@ -304,7 +304,7 @@ static int C6X_encInput(unsigned long baseAddr, unsigned channel)
+ 		timeout++;
+ 	}
+ 
+-	return (enc.value ^ 0x800000);
++	return enc.value ^ 0x800000;
+ }
+ 
+ static void C6X_encResetAll(unsigned long baseAddr)
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
+index d59f4d04feb0..0a1b20142953 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
+@@ -209,7 +209,7 @@ static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
+ /* returns a maxdata value for a given n_bits */
+ static inline unsigned int figure_out_maxdata(int bits)
+ {
+-	return (((unsigned int) 1 << bits) - 1);
++	return ((unsigned int) 1 << bits) - 1;
+ }
+ 
+ /*
+diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
+index c29e4dcd51a0..00aa30471cf8 100644
+--- a/drivers/staging/comedi/drivers/das16m1.c
++++ b/drivers/staging/comedi/drivers/das16m1.c
+@@ -626,7 +626,7 @@ static int das16m1_irq_bits(unsigned int irq)
+ 		return -1;
+ 		break;
+ 	}
+-	return (ret << 4);
++	return ret << 4;
+ }
+ 
+ /*
+diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h
+index 55c8a1d66865..d4d352b6b465 100644
+--- a/drivers/staging/comedi/drivers/ni_stc.h
++++ b/drivers/staging/comedi/drivers/ni_stc.h
+@@ -318,7 +318,7 @@ enum Clock_and_FOUT_bits {
+ };
+ static inline unsigned FOUT_Divider(unsigned divider)
+ {
+-	return (divider & FOUT_Divider_mask);
++	return divider & FOUT_Divider_mask;
+ }
+ 
+ #define IO_Bidirection_Pin_Register	57
+@@ -759,7 +759,7 @@ enum Configuration_Memory_High_Bits {
+ };
+ static inline unsigned int AI_CONFIG_CHANNEL(unsigned int channel)
+ {
+-	return (channel & 0x3f);
++	return channel & 0x3f;
+ }
+ 
+ #define ADC_FIFO_Data_Register		0x1c
+diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c
+index bdb232635abd..2b0441e646dd 100644
+--- a/drivers/staging/comedi/drivers/ni_tio.c
++++ b/drivers/staging/comedi/drivers/ni_tio.c
+@@ -149,13 +149,13 @@ static const unsigned ni_660x_max_rtsi_channel = 6;
+ static inline unsigned NI_660x_RTSI_Clock(unsigned n)
+ {
+ 	BUG_ON(n > ni_660x_max_rtsi_channel);
+-	return (0xb + n);
++	return 0xb + n;
+ }
+ static const unsigned ni_660x_max_source_pin = 7;
+ static inline unsigned NI_660x_Source_Pin_Clock(unsigned n)
+ {
+ 	BUG_ON(n > ni_660x_max_source_pin);
+-	return (0x2 + n);
++	return 0x2 + n;
+ }
+ 
+ /* clock sources for ni e and m series boards, get bits with Gi_Source_Select_Bits() */

commit c3744138715045adb316284ee7a1e608f0278f6c
+Author: Bill Pemberton 
+Date:   Wed Apr 22 21:11:47 2009 -0400
+
+    Staging: comedi: remove assignment in conditionals
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c
+index 63fc08a3ad7b..e8206a18dee9 100644
+--- a/drivers/staging/comedi/drivers/8255.c
++++ b/drivers/staging/comedi/drivers/8255.c
+@@ -394,7 +394,8 @@ static int dev_8255_attach(struct comedi_device *dev, struct comedi_devconfig *
+ 		return -EINVAL;
+ 	}
+ 
+-	if ((ret = alloc_subdevices(dev, i)) < 0)
++	ret = alloc_subdevices(dev, i);
++	if (ret < 0)
+ 		return ret;
+ 
+ 	for (i = 0; i < dev->n_subdevices; i++) {
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+index 198ef1cd40e9..a6c3530674df 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+@@ -2575,9 +2575,9 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	sprintf(c_Identifier, "Addi-Data GmbH Comedi %s",
+ 		this_board->pc_DriverName);
+ 
+-	if ((ret = alloc_private(dev, sizeof(struct addi_private))) < 0) {
++	ret = alloc_private(dev, sizeof(struct addi_private));
++	if (ret < 0)
+ 		return -ENOMEM;
+-	}
+ 
+ 	if (!pci_list_builded) {
+ 		v_pci_card_list_init(this_board->i_VendorId, 1);	/* 1 for displaying the list.. */
+@@ -2589,12 +2589,14 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 		i_Dma = 1;
+ 	}
+ 
+-	if ((card = ptr_select_and_alloc_pci_card(this_board->i_VendorId,
+-				this_board->i_DeviceId,
+-				it->options[0],
+-				it->options[1], i_Dma)) == NULL) {
++	card = ptr_select_and_alloc_pci_card(this_board->i_VendorId,
++					     this_board->i_DeviceId,
++					     it->options[0],
++					     it->options[1], i_Dma);
++
++	if (card == NULL)
+ 		return -EIO;
+-	}
++
+ 	devpriv->allocated = 1;
+ 
+ 	if ((i_pci_card_data(card, &pci_bus, &pci_slot, &pci_func, &io_addr[0],
+@@ -2698,12 +2700,11 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 			devpriv->b_DmaDoubleBuffer = 0;
+ 			for (i = 0; i < 2; i++) {
+ 				for (pages = 4; pages >= 0; pages--) {
+-					if ((devpriv->ul_DmaBufferVirtual[i] =
+-							(void *)
+-							__get_free_pages
+-							(GFP_KERNEL, pages))) {
++					devpriv->ul_DmaBufferVirtual[i] =
++						(void *) __get_free_pages(GFP_KERNEL, pages);
++
++					if (devpriv->ul_DmaBufferVirtual[i])
+ 						break;
+-					}
+ 				}
+ 				if (devpriv->ul_DmaBufferVirtual[i]) {
+ 					devpriv->ui_DmaBufferPages[i] = pages;
+@@ -2745,7 +2746,8 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	} else {
+ 		/* Update-0.7.57->0.7.68dev->n_subdevices = 7; */
+ 		n_subdevices = 7;
+-		if ((ret = alloc_subdevices(dev, n_subdevices)) < 0)
++		ret = alloc_subdevices(dev, n_subdevices);
++		if (ret < 0)
+ 			return ret;
+ 
+ 		/*  Allocate and Initialise AI Subdevice Structures */
+diff --git a/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h b/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h
+index bee6101d2e87..ba89ff93a4e1 100644
+--- a/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h
++++ b/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h
+@@ -423,9 +423,8 @@ struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id,
+ 	struct pcilst_struct *card;
+ 
+ 	if ((pci_bus < 1) & (pci_slot < 1)) {	/*  use autodetection */
+-		if ((card = ptr_find_free_pci_card_by_device(vendor_id,
+-							     device_id)) ==
+-		    NULL) {
++		card = ptr_find_free_pci_card_by_device(vendor_id, device_id);
++		if (card == NULL) {
+ 			rt_printk(" - Unused card not found in system!\n");
+ 			return NULL;
+ 		}
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+index 355a0c8ab41e..508e19e9e0dc 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+@@ -1,4 +1,4 @@
+-/**
++//**
+ @verbatim
+ 
+ Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+@@ -63,7 +63,8 @@ void i_ADDI_AttachPCI1710(struct comedi_device *dev)
+ 	int n_subdevices = 9;
+ 
+ 	/* Update-0.7.57->0.7.68dev->n_subdevices = 9; */
+-	if ((ret = alloc_subdevices(dev, n_subdevices)) < 0)
++	ret = alloc_subdevices(dev, n_subdevices);
++	if (ret < 0)
+ 		return;
+ 
+ 	/*  Allocate and Initialise Timer Subdevice Structures */
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+index 871ed763fe2d..3a47c3034229 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+@@ -975,96 +975,117 @@ static void v_APCI1564_Interrupt(int irq, void *d)
+ 
+ 	}			/*  if  (ui_DO) */
+ 
+-	if ((ui_Timer == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_TIMER)) {
+-		/*  Disable Timer Interrupt */
+-		ul_Command2 =
+-			inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
+-			APCI1564_TCW_PROG);
+-		outl(0x0,
+-			devpriv->i_IobaseAmcc + APCI1564_TIMER +
+-			APCI1564_TCW_PROG);
++	if (ui_Timer == 1) {
++		devpriv->b_TimerSelectMode = ADDIDATA_TIMER;
++		if (devpriv->b_TimerSelectMode) {
+ 
+-		/* Send a signal to from kernel to user space */
+-		send_sig(SIGIO, devpriv->tsk_Current, 0);
++			/*  Disable Timer Interrupt */
++			ul_Command2 =
++				inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
++				    APCI1564_TCW_PROG);
++			outl(0x0,
++			     devpriv->i_IobaseAmcc + APCI1564_TIMER +
++			     APCI1564_TCW_PROG);
+ 
+-		/*  Enable Timer Interrupt */
++			/* Send a signal to from kernel to user space */
++			send_sig(SIGIO, devpriv->tsk_Current, 0);
+ 
+-		outl(ul_Command2,
+-			devpriv->i_IobaseAmcc + APCI1564_TIMER +
+-			APCI1564_TCW_PROG);
+-	}			/*  if  ((ui_Timer == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_TIMER)) */
++			/*  Enable Timer Interrupt */
+ 
+-	if ((ui_C1 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) {
+-		/*  Disable Counter Interrupt */
+-		ul_Command2 =
+-			inl(devpriv->iobase + APCI1564_COUNTER1 +
+-			APCI1564_TCW_PROG);
+-		outl(0x0,
+-			devpriv->iobase + APCI1564_COUNTER1 +
+-			APCI1564_TCW_PROG);
++			outl(ul_Command2,
++			     devpriv->i_IobaseAmcc + APCI1564_TIMER +
++			     APCI1564_TCW_PROG);
++		}
++	}/* if  (ui_Timer == 1) */
+ 
+-		/* Send a signal to from kernel to user space */
+-		send_sig(SIGIO, devpriv->tsk_Current, 0);
+ 
+-		/*  Enable Counter Interrupt */
+-		outl(ul_Command2,
+-			devpriv->iobase + APCI1564_COUNTER1 +
+-			APCI1564_TCW_PROG);
+-	}			/*  if  ((ui_C1 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) */
++	if (ui_C1 == 1) {
++		devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
++		if (devpriv->b_TimerSelectMode) {
+ 
+-	if ((ui_C2 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) {
+-		/*  Disable Counter Interrupt */
+-		ul_Command2 =
+-			inl(devpriv->iobase + APCI1564_COUNTER2 +
+-			APCI1564_TCW_PROG);
+-		outl(0x0,
+-			devpriv->iobase + APCI1564_COUNTER2 +
+-			APCI1564_TCW_PROG);
++			/*  Disable Counter Interrupt */
++			ul_Command2 =
++				inl(devpriv->iobase + APCI1564_COUNTER1 +
++				    APCI1564_TCW_PROG);
++			outl(0x0,
++			     devpriv->iobase + APCI1564_COUNTER1 +
++			     APCI1564_TCW_PROG);
+ 
+-		/* Send a signal to from kernel to user space */
+-		send_sig(SIGIO, devpriv->tsk_Current, 0);
++			/* Send a signal to from kernel to user space */
++			send_sig(SIGIO, devpriv->tsk_Current, 0);
+ 
+-		/*  Enable Counter Interrupt */
+-		outl(ul_Command2,
+-			devpriv->iobase + APCI1564_COUNTER2 +
+-			APCI1564_TCW_PROG);
+-	}			/*  if  ((ui_C2 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER)) */
++			/*  Enable Counter Interrupt */
++			outl(ul_Command2,
++			     devpriv->iobase + APCI1564_COUNTER1 +
++			     APCI1564_TCW_PROG);
++		}
++	} /* if  (ui_C1 == 1) */
+ 
+-	if ((ui_C3 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) {
+-		/*  Disable Counter Interrupt */
+-		ul_Command2 =
+-			inl(devpriv->iobase + APCI1564_COUNTER3 +
+-			APCI1564_TCW_PROG);
+-		outl(0x0,
+-			devpriv->iobase + APCI1564_COUNTER3 +
+-			APCI1564_TCW_PROG);
++	if (ui_C2 == 1) {
++		devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
++		if (devpriv->b_TimerSelectMode) {
+ 
+-		/* Send a signal to from kernel to user space */
+-		send_sig(SIGIO, devpriv->tsk_Current, 0);
++			/*  Disable Counter Interrupt */
++			ul_Command2 =
++				inl(devpriv->iobase + APCI1564_COUNTER2 +
++				    APCI1564_TCW_PROG);
++			outl(0x0,
++			     devpriv->iobase + APCI1564_COUNTER2 +
++			     APCI1564_TCW_PROG);
+ 
+-		/*  Enable Counter Interrupt */
+-		outl(ul_Command2,
+-			devpriv->iobase + APCI1564_COUNTER3 +
+-			APCI1564_TCW_PROG);
+-	}			/*  if ((ui_C3 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER)) */
++			/* Send a signal to from kernel to user space */
++			send_sig(SIGIO, devpriv->tsk_Current, 0);
+ 
+-	if ((ui_C4 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) {
+-		/*  Disable Counter Interrupt */
+-		ul_Command2 =
+-			inl(devpriv->iobase + APCI1564_COUNTER4 +
+-			APCI1564_TCW_PROG);
+-		outl(0x0,
+-			devpriv->iobase + APCI1564_COUNTER4 +
+-			APCI1564_TCW_PROG);
++			/*  Enable Counter Interrupt */
++			outl(ul_Command2,
++			     devpriv->iobase + APCI1564_COUNTER2 +
++			     APCI1564_TCW_PROG);
++		}
++	} /*  if  ((ui_C2 == 1) */
+ 
+-		/* Send a signal to from kernel to user space */
+-		send_sig(SIGIO, devpriv->tsk_Current, 0);
++	if (ui_C3 == 1) {
++		devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
++		if (devpriv->b_TimerSelectMode) {
+ 
+-		/*  Enable Counter Interrupt */
+-		outl(ul_Command2,
+-			devpriv->iobase + APCI1564_COUNTER4 +
+-			APCI1564_TCW_PROG);
+-	}			/*  if ((ui_C4 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER)) */
++			/*  Disable Counter Interrupt */
++			ul_Command2 =
++				inl(devpriv->iobase + APCI1564_COUNTER3 +
++				    APCI1564_TCW_PROG);
++			outl(0x0,
++			     devpriv->iobase + APCI1564_COUNTER3 +
++			     APCI1564_TCW_PROG);
++
++			/* Send a signal to from kernel to user space */
++			send_sig(SIGIO, devpriv->tsk_Current, 0);
++
++			/*  Enable Counter Interrupt */
++			outl(ul_Command2,
++			     devpriv->iobase + APCI1564_COUNTER3 +
++			     APCI1564_TCW_PROG);
++		}
++	}	/*  if ((ui_C3 == 1) */
++
++	if (ui_C4 == 1) {
++		devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
++		if (devpriv->b_TimerSelectMode) {
++
++			/*  Disable Counter Interrupt */
++			ul_Command2 =
++				inl(devpriv->iobase + APCI1564_COUNTER4 +
++				    APCI1564_TCW_PROG);
++			outl(0x0,
++			     devpriv->iobase + APCI1564_COUNTER4 +
++			     APCI1564_TCW_PROG);
++
++			/* Send a signal to from kernel to user space */
++			send_sig(SIGIO, devpriv->tsk_Current, 0);
++
++			/*  Enable Counter Interrupt */
++			outl(ul_Command2,
++			     devpriv->iobase + APCI1564_COUNTER4 +
++			     APCI1564_TCW_PROG);
++		}
++	}	/*  if (ui_C4 == 1) */
+ 	return;
+ }
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+index cac233e83a50..fd74c409b846 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+@@ -614,8 +614,8 @@ void v_APCI3XXX_Interrupt(int irq, void *d)
+ 	/* Test if interrupt occur */
+ 	/***************************/
+ 
+-	if (((dw_Status = readl((void *)(devpriv->dw_AiBase + 16))) & 0x2UL) ==
+-		0x2UL) {
++	dw_Status = readl((void *)(devpriv->dw_AiBase + 16));
++	if ( (dw_Status & 0x2UL) == 0x2UL) {
+ 	   /***********************/
+ 		/* Reset the interrupt */
+ 	   /***********************/
+diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
+index aed4a47a7988..6dc9435997ca 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9111.c
++++ b/drivers/staging/comedi/drivers/adl_pci9111.c
+@@ -1310,7 +1310,8 @@ static int pci9111_attach(struct comedi_device *dev, struct comedi_devconfig *it
+ 
+ 	/*  TODO: Add external multiplexer setup (according to option[2]). */
+ 
+-	if ((error = alloc_subdevices(dev, 4)) < 0)
++	error = alloc_subdevices(dev, 4);
++	if (error < 0)
+ 		return error;
+ 
+ 	subdevice = dev->subdevices + 0;
+diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
+index 20f7bf0c2b42..a1e669cf4cc6 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9118.c
++++ b/drivers/staging/comedi/drivers/adl_pci9118.c
+@@ -1474,11 +1474,10 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ 	s->async->cur_chan = 0;
+ 	devpriv->ai_buf_ptr = 0;
+ 
+-	if (devpriv->usedma) {
++	if (devpriv->usedma)
+ 		ret = pci9118_ai_docmd_dma(dev, s);
+-	} else {
++	else
+ 		ret = pci9118_ai_docmd_sampl(dev, s);
+-	}
+ 
+ 	DPRINTK("adl_pci9118 EDBG: END: pci9118_ai_cmd()\n");
+ 	return ret;
+@@ -1860,7 +1859,8 @@ static int pci9118_attach(struct comedi_device *dev, struct comedi_devconfig *it
+ 		master = 1;
+ 	}
+ 
+-	if ((ret = alloc_private(dev, sizeof(struct pci9118_private))) < 0) {
++	ret = alloc_private(dev, sizeof(struct pci9118_private));
++	if (ret < 0) {
+ 		rt_printk(" - Allocation failed!\n");
+ 		return -ENOMEM;
+ 	}
+@@ -1940,11 +1940,13 @@ static int pci9118_attach(struct comedi_device *dev, struct comedi_devconfig *it
+ 	if (master) {		/*  alloc DMA buffers */
+ 		devpriv->dma_doublebuf = 0;
+ 		for (i = 0; i < 2; i++) {
+-			for (pages = 4; pages >= 0; pages--)
+-				if ((devpriv->dmabuf_virt[i] = (short *)
+-						__get_free_pages(GFP_KERNEL,
+-							pages)))
++			for (pages = 4; pages >= 0; pages--) {
++				devpriv->dmabuf_virt[i] =
++					(short *) __get_free_pages(GFP_KERNEL,
++								   pages);
++				if (devpriv->dmabuf_virt[i])
+ 					break;
++			}
+ 			if (devpriv->dmabuf_virt[i]) {
+ 				devpriv->dmabuf_pages[i] = pages;
+ 				devpriv->dmabuf_size[i] = PAGE_SIZE * pages;
+@@ -1965,11 +1967,11 @@ static int pci9118_attach(struct comedi_device *dev, struct comedi_devconfig *it
+ 
+ 	}
+ 
+-	if ((devpriv->master = master)) {
++	devpriv->master = master;
++	if (devpriv->master)
+ 		rt_printk(", bus master");
+-	} else {
++	else
+ 		rt_printk(", no bus master");
+-	}
+ 
+ 	devpriv->usemux = 0;
+ 	if (it->options[2] > 0) {
+@@ -1998,7 +2000,8 @@ static int pci9118_attach(struct comedi_device *dev, struct comedi_devconfig *it
+ 	pci_read_config_word(devpriv->pcidev, PCI_COMMAND, &u16w);
+ 	pci_write_config_word(devpriv->pcidev, PCI_COMMAND, u16w | 64);	/*  Enable parity check for parity error */
+ 
+-	if ((ret = alloc_subdevices(dev, 4)) < 0)
++	ret = alloc_subdevices(dev, 4);
++	if (ret < 0)
+ 		return ret;
+ 
+ 	s = dev->subdevices + 0;
+diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
+index 37f1459d152c..f0aa576dc9e8 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1710.c
++++ b/drivers/staging/comedi/drivers/adv_pci1710.c
+@@ -1336,7 +1336,8 @@ static int pci1710_attach(struct comedi_device *dev, struct comedi_devconfig *it
+ 	opt_bus = it->options[0];
+ 	opt_slot = it->options[1];
+ 
+-	if ((ret = alloc_private(dev, sizeof(struct pci1710_private))) < 0) {
++	ret = alloc_private(dev, sizeof(struct pci1710_private));
++	if (ret < 0) {
+ 		rt_printk(" - Allocation failed!\n");
+ 		return -ENOMEM;
+ 	}
+@@ -1419,7 +1420,8 @@ static int pci1710_attach(struct comedi_device *dev, struct comedi_devconfig *it
+ 	if (this_board->n_counter)
+ 		n_subdevices++;
+ 
+-	if ((ret = alloc_subdevices(dev, n_subdevices)) < 0) {
++	ret = alloc_subdevices(dev, n_subdevices);
++	if (ret < 0) {
+ 		rt_printk(" - Allocation failed!\n");
+ 		return ret;
+ 	}
+diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
+index e45ce552dd02..38be3f8be078 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1723.c
++++ b/drivers/staging/comedi/drivers/adv_pci1723.c
+@@ -310,7 +310,8 @@ static int pci1723_attach(struct comedi_device *dev, struct comedi_devconfig *it
+ 	opt_bus = it->options[0];
+ 	opt_slot = it->options[1];
+ 
+-	if ((ret = alloc_private(dev, sizeof(struct pci1723_private))) < 0) {
++	ret = alloc_private(dev, sizeof(struct pci1723_private));
++	if (ret < 0) {
+ 		rt_printk(" - Allocation failed!\n");
+ 		return -ENOMEM;
+ 	}
+@@ -369,7 +370,8 @@ static int pci1723_attach(struct comedi_device *dev, struct comedi_devconfig *it
+ 	if (this_board->n_diochan)
+ 		n_subdevices++;
+ 
+-	if ((ret = alloc_subdevices(dev, n_subdevices)) < 0) {
++	ret = alloc_subdevices(dev, n_subdevices);
++	if (ret < 0) {
+ 		rt_printk(" - Allocation failed!\n");
+ 		return ret;
+ 	}
+diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
+index 21fd9aa8decc..afa2a4d3816d 100644
+--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
++++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
+@@ -443,7 +443,8 @@ static int pci1760_unchecked_mbxrequest(struct comedi_device *dev,
+ 		outb(omb[2], dev->iobase + OMB2);
+ 		outb(omb[3], dev->iobase + OMB3);
+ 		for (tout = 0; tout < 251; tout++) {
+-			if ((imb[2] = inb(dev->iobase + IMB2)) == omb[2]) {
++			imb[2] = inb(dev->iobase + IMB2);
++			if (imb[2] == omb[2]) {
+ 				imb[0] = inb(dev->iobase + IMB0);
+ 				imb[1] = inb(dev->iobase + IMB1);
+ 				imb[3] = inb(dev->iobase + IMB3);
+@@ -517,7 +518,8 @@ static int pci1760_insn_bits_do(struct comedi_device *dev, struct comedi_subdevi
+ 		s->state &= ~data[0];
+ 		s->state |= (data[0] & data[1]);
+ 		omb[0] = s->state;
+-		if (!(ret = pci1760_mbxrequest(dev, omb, imb)))
++		ret = pci1760_mbxrequest(dev, omb, imb);
++		if (!ret)
+ 			return ret;
+ 	}
+ 	data[1] = s->state;
+@@ -541,7 +543,8 @@ static int pci1760_insn_cnt_read(struct comedi_device *dev, struct comedi_subdev
+ 	unsigned char imb[4];
+ 
+ 	for (n = 0; n < insn->n; n++) {
+-		if (!(ret = pci1760_mbxrequest(dev, omb, imb)))
++		ret = pci1760_mbxrequest(dev, omb, imb);
++		if (!ret)
+ 			return ret;
+ 		data[n] = (imb[1] << 8) + imb[0];
+ 	}
+@@ -567,20 +570,23 @@ static int pci1760_insn_cnt_write(struct comedi_device *dev, struct comedi_subde
+ 	unsigned char imb[4];
+ 
+ 	if (devpriv->CntResValue[chan] != (data[0] & 0xffff)) {	/*  Set reset value if different */
+-		if (!(ret = pci1760_mbxrequest(dev, omb, imb)))
++		ret =  pci1760_mbxrequest(dev, omb, imb);
++		if (!ret)
+ 			return ret;
+ 		devpriv->CntResValue[chan] = data[0] & 0xffff;
+ 	}
+ 
+ 	omb[0] = bitmask;	/*  reset counter to it reset value */
+ 	omb[2] = CMD_ResetIDICounters;
+-	if (!(ret = pci1760_mbxrequest(dev, omb, imb)))
++	ret = pci1760_mbxrequest(dev, omb, imb);
++	if (!ret)
+ 		return ret;
+ 
+ 	if (!(bitmask & devpriv->IDICntEnable)) {	/*  start counter if it don't run */
+ 		omb[0] = bitmask;
+ 		omb[2] = CMD_EnableIDICounters;
+-		if (!(ret = pci1760_mbxrequest(dev, omb, imb)))
++		ret = pci1760_mbxrequest(dev, omb, imb);
++		if (!ret)
+ 			return ret;
+ 		devpriv->IDICntEnable |= bitmask;
+ 	}
+@@ -892,7 +898,8 @@ static int pci_dio_attach(struct comedi_device *dev, struct comedi_devconfig *it
+ 
+ 	rt_printk("comedi%d: adv_pci_dio: ", dev->minor);
+ 
+-	if ((ret = alloc_private(dev, sizeof(struct pci_dio_private))) < 0) {
++	ret = alloc_private(dev, sizeof(struct pci_dio_private));
++	if (ret < 0) {
+ 		rt_printk(", Error: Cann't allocate private memory!\n");
+ 		return -ENOMEM;
+ 	}
+@@ -959,7 +966,8 @@ static int pci_dio_attach(struct comedi_device *dev, struct comedi_devconfig *it
+ 			n_subdevices++;
+ 	}
+ 
+-	if ((ret = alloc_subdevices(dev, n_subdevices)) < 0) {
++	ret = alloc_subdevices(dev, n_subdevices);
++	if (ret < 0) {
+ 		rt_printk(", Error: Cann't allocate subdevice memory!\n");
+ 		return ret;
+ 	}
+diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
+index 563fb0ba06e8..7c323e242835 100644
+--- a/drivers/staging/comedi/drivers/amplc_dio200.c
++++ b/drivers/staging/comedi/drivers/amplc_dio200.c
+@@ -1282,7 +1282,8 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor,
+ 		DIO200_DRIVER_NAME);
+ 
+-	if ((ret = alloc_private(dev, sizeof(struct dio200_private))) < 0) {
++	ret = alloc_private(dev, sizeof(struct dio200_private));
++	if (ret < 0) {
+ 		printk(KERN_ERR "comedi%d: error! out of memory!\n",
+ 			dev->minor);
+ 		return ret;
+@@ -1301,7 +1302,8 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 		slot = it->options[1];
+ 		share_irq = 1;
+ 
+-		if ((ret = dio200_find_pci(dev, bus, slot, &pci_dev)) < 0)
++		ret = dio200_find_pci(dev, bus, slot, &pci_dev);
++		if (ret < 0)
+ 			return ret;
+ 		devpriv->pci_dev = pci_dev;
+ 		break;
+@@ -1339,7 +1341,9 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	dev->iobase = iobase;
+ 
+ 	layout = thislayout;
+-	if ((ret = alloc_subdevices(dev, layout->n_subdevs)) < 0) {
++
++	ret = alloc_subdevices(dev, layout->n_subdevs);
++	if (ret < 0) {
+ 		printk(KERN_ERR "comedi%d: error! out of memory!\n",
+ 			dev->minor);
+ 		return ret;
+diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
+index 4efdd1259636..8454f6d6517e 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc236.c
++++ b/drivers/staging/comedi/drivers/amplc_pc236.c
+@@ -284,7 +284,8 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+  * Allocate the private structure area.  alloc_private() is a
+  * convenient macro defined in comedidev.h.
+  */
+-	if ((ret = alloc_private(dev, sizeof(struct pc236_private))) < 0) {
++	ret = alloc_private(dev, sizeof(struct pc236_private));
++	if (ret < 0) {
+ 		printk(KERN_ERR "comedi%d: error! out of memory!\n",
+ 			dev->minor);
+ 		return ret;
+@@ -302,7 +303,8 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 		slot = it->options[1];
+ 		share_irq = 1;
+ 
+-		if ((ret = pc236_find_pci(dev, bus, slot, &pci_dev)) < 0)
++		ret = pc236_find_pci(dev, bus, slot, &pci_dev);
++		if (ret < 0)
+ 			return ret;
+ 		devpriv->pci_dev = pci_dev;
+ 		break;
+@@ -323,7 +325,9 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	/* Enable device and reserve I/O spaces. */
+ #ifdef CONFIG_COMEDI_PCI
+ 	if (pci_dev) {
+-		if ((ret = comedi_pci_enable(pci_dev, PC236_DRIVER_NAME)) < 0) {
++
++		ret = comedi_pci_enable(pci_dev, PC236_DRIVER_NAME);
++		if (ret < 0) {
+ 			printk(KERN_ERR
+ 				"comedi%d: error! cannot enable PCI device and request regions!\n",
+ 				dev->minor);
+@@ -346,7 +350,8 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+  * Allocate the subdevice structures.  alloc_subdevice() is a
+  * convenient macro defined in comedidev.h.
+  */
+-	if ((ret = alloc_subdevices(dev, 2)) < 0) {
++	ret = alloc_subdevices(dev, 2);
++	if (ret < 0) {
+ 		printk(KERN_ERR "comedi%d: error! out of memory!\n",
+ 			dev->minor);
+ 		return ret;
+@@ -354,7 +359,8 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 
+ 	s = dev->subdevices + 0;
+ 	/* digital i/o subdevice (8255) */
+-	if ((ret = subdev_8255_init(dev, s, NULL, iobase)) < 0) {
++	ret = subdev_8255_init(dev, s, NULL, iobase);
++	if (ret < 0) {
+ 		printk(KERN_ERR "comedi%d: error! out of memory!\n",
+ 			dev->minor);
+ 		return ret;
+diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
+index 1ca704760067..8a94360fe2db 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc263.c
++++ b/drivers/staging/comedi/drivers/amplc_pc263.c
+@@ -236,7 +236,8 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+  * convenient macro defined in comedidev.h.
+  */
+ #ifdef CONFIG_COMEDI_PCI
+-	if ((ret = alloc_private(dev, sizeof(struct pc263_private))) < 0) {
++	ret = alloc_private(dev, sizeof(struct pc263_private));
++	if (ret < 0) {
+ 		printk(KERN_ERR "comedi%d: error! out of memory!\n",
+ 			dev->minor);
+ 		return ret;
+@@ -252,7 +253,8 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 		bus = it->options[0];
+ 		slot = it->options[1];
+ 
+-		if ((ret = pc263_find_pci(dev, bus, slot, &pci_dev)) < 0)
++		ret = pc263_find_pci(dev, bus, slot, &pci_dev);
++		if (ret < 0)
+ 			return ret;
+ 		devpriv->pci_dev = pci_dev;
+ 		break;
+@@ -273,7 +275,8 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	/* Enable device and reserve I/O spaces. */
+ #ifdef CONFIG_COMEDI_PCI
+ 	if (pci_dev) {
+-		if ((ret = comedi_pci_enable(pci_dev, PC263_DRIVER_NAME)) < 0) {
++		ret = comedi_pci_enable(pci_dev, PC263_DRIVER_NAME);
++		if (ret < 0) {
+ 			printk(KERN_ERR
+ 				"comedi%d: error! cannot enable PCI device and request regions!\n",
+ 				dev->minor);
+@@ -294,7 +297,8 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+  * Allocate the subdevice structures.  alloc_subdevice() is a
+  * convenient macro defined in comedidev.h.
+  */
+-	if ((ret = alloc_subdevices(dev, 1)) < 0) {
++	ret = alloc_subdevices(dev, 1);
++	if (ret < 0) {
+ 		printk(KERN_ERR "comedi%d: error! out of memory!\n",
+ 			dev->minor);
+ 		return ret;
+diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
+index 9037ff4bf0e6..7cc594b38070 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci224.c
++++ b/drivers/staging/comedi/drivers/amplc_pci224.c
+@@ -1338,16 +1338,20 @@ static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 
+ 	bus = it->options[0];
+ 	slot = it->options[1];
+-	if ((ret = alloc_private(dev, sizeof(struct pci224_private))) < 0) {
++	ret = alloc_private(dev, sizeof(struct pci224_private));
++	if (ret < 0) {
+ 		printk(KERN_ERR "comedi%d: error! out of memory!\n",
+ 			dev->minor);
+ 		return ret;
+ 	}
+-	if ((ret = pci224_find_pci(dev, bus, slot, &pci_dev)) < 0)
++
++	ret = pci224_find_pci(dev, bus, slot, &pci_dev);
++	if (ret < 0)
+ 		return ret;
+-	devpriv->pci_dev = pci_dev;
+ 
+-	if ((ret = comedi_pci_enable(pci_dev, DRIVER_NAME)) < 0) {
++	devpriv->pci_dev = pci_dev;
++	ret = comedi_pci_enable(pci_dev, DRIVER_NAME);
++	if (ret < 0) {
+ 		printk(KERN_ERR
+ 			"comedi%d: error! cannot enable PCI device "
+ 			"and request regions!\n", dev->minor);
+@@ -1394,7 +1398,8 @@ static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 		dev->iobase + PCI224_DACCON);
+ 
+ 	/* Allocate subdevices.  There is only one!  */
+-	if ((ret = alloc_subdevices(dev, 1)) < 0) {
++	ret = alloc_subdevices(dev, 1);
++	if (ret < 0) {
+ 		printk(KERN_ERR "comedi%d: error! out of memory!\n",
+ 			dev->minor);
+ 		return ret;
+diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
+index 8e07a52e4d13..e476baf7c1d9 100644
+--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
++++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
+@@ -766,15 +766,22 @@ static void das16cs_pcmcia_config(struct pcmcia_device *link)
+ 	tuple.TupleData = buf;
+ 	tuple.TupleDataMax = sizeof(buf);
+ 	tuple.TupleOffset = 0;
++
+ 	last_fn = GetFirstTuple;
+-	if ((last_ret = pcmcia_get_first_tuple(link, &tuple)) != 0)
++	last_ret = pcmcia_get_first_tuple(link, &tuple);
++	if (last_ret != 0)
+ 		goto cs_failed;
++
+ 	last_fn = GetTupleData;
+-	if ((last_ret = pcmcia_get_tuple_data(link, &tuple)) != 0)
++	last_ret = pcmcia_get_tuple_data(link, &tuple);
++	if (last_ret != 0)
+ 		goto cs_failed;
++
+ 	last_fn = ParseTuple;
+-	if ((last_ret = pcmcia_parse_tuple(&tuple, &parse)) != 0)
++	last_ret = pcmcia_parse_tuple(&tuple, &parse);
++	if (last_ret != 0)
+ 		goto cs_failed;
++
+ 	link->conf.ConfigBase = parse.config.base;
+ 	link->conf.Present = parse.config.rmask[0];
+ 
+@@ -792,8 +799,11 @@ static void das16cs_pcmcia_config(struct pcmcia_device *link)
+ 	 */
+ 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+ 	last_fn = GetFirstTuple;
+-	if ((last_ret = pcmcia_get_first_tuple(link, &tuple)) != 0)
++
++	last_ret = pcmcia_get_first_tuple(link, &tuple);
++	if (last_ret)
+ 		goto cs_failed;
++
+ 	while (1) {
+ 		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
+ 		if (pcmcia_get_tuple_data(link, &tuple))
+@@ -844,7 +854,9 @@ static void das16cs_pcmcia_config(struct pcmcia_device *link)
+ 
+ 	      next_entry:
+ 		last_fn = GetNextTuple;
+-		if ((last_ret = pcmcia_get_next_tuple(link, &tuple)) != 0)
++
++		last_ret = pcmcia_get_next_tuple(link, &tuple);
++		if (last_ret)
+ 			goto cs_failed;
+ 	}
+ 
+@@ -855,7 +867,9 @@ static void das16cs_pcmcia_config(struct pcmcia_device *link)
+ 	 */
+ 	if (link->conf.Attributes & CONF_ENABLE_IRQ) {
+ 		last_fn = RequestIRQ;
+-		if ((last_ret = pcmcia_request_irq(link, &link->irq)) != 0)
++
++		last_ret = pcmcia_request_irq(link, &link->irq);
++		if (last_ret)
+ 			goto cs_failed;
+ 	}
+ 	/*
+@@ -864,7 +878,8 @@ static void das16cs_pcmcia_config(struct pcmcia_device *link)
+ 	   card and host interface into "Memory and IO" mode.
+ 	 */
+ 	last_fn = RequestConfiguration;
+-	if ((last_ret = pcmcia_request_configuration(link, &link->conf)) != 0)
++	last_ret = pcmcia_request_configuration(link, &link->conf);
++	if (last_ret)
+ 		goto cs_failed;
+ 
+ 	/*
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
+index 1afedd8e7cc0..d59f4d04feb0 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
+@@ -257,7 +257,8 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
+  * it is, this is the place to do it.  Otherwise, dev->board_ptr
+  * should already be initialized.
+  */
+-	if ((err = probe(dev, it)))
++	err = probe(dev, it);
++	if (err)
+ 		return err;
+ 
+ /* Output some info */
+diff --git a/drivers/staging/comedi/drivers/comedi_rt_timer.c b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+index 784b2e40f711..ef8accd528c6 100644
+--- a/drivers/staging/comedi/drivers/comedi_rt_timer.c
++++ b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+@@ -646,9 +646,12 @@ static int timer_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 
+ 	dev->board_name = "timer";
+ 
+-	if ((ret = alloc_subdevices(dev, 1)) < 0)
++	ret = alloc_subdevices(dev, 1);
++	if (ret < 0)
+ 		return ret;
+-	if ((ret = alloc_private(dev, sizeof(struct timer_private))) < 0)
++
++	ret = alloc_private(dev, sizeof(struct timer_private));
++	if (ret < 0)
+ 		return ret;
+ 
+ 	sprintf(path, "/dev/comedi%d", it->options[0]);
+diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
+index 90bed0b962ee..794fbb24aa32 100644
+--- a/drivers/staging/comedi/drivers/daqboard2000.c
++++ b/drivers/staging/comedi/drivers/daqboard2000.c
+@@ -772,7 +772,8 @@ static int daqboard2000_attach(struct comedi_device *dev, struct comedi_devconfi
+ 		}
+ 	}
+ 
+-	if ((result = comedi_pci_enable(card, "daqboard2000")) < 0) {
++	result = comedi_pci_enable(card, "daqboard2000");
++	if (result < 0) {
+ 		printk(" failed to enable PCI device and request regions\n");
+ 		return -EIO;
+ 	}
+diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
+index 51dddd464ef2..d7760e4aec13 100644
+--- a/drivers/staging/comedi/drivers/das08.c
++++ b/drivers/staging/comedi/drivers/das08.c
+@@ -857,7 +857,8 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
+ 
+ 	dev->board_name = thisboard->name;
+ 
+-	if ((ret = alloc_subdevices(dev, 6)) < 0)
++	ret = alloc_subdevices(dev, 6);
++	if (ret < 0)
+ 		return ret;
+ 
+ 	s = dev->subdevices + 0;
+@@ -961,7 +962,8 @@ static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	struct pci_dev *pdev;
+ #endif
+ 
+-	if ((ret = alloc_private(dev, sizeof(struct das08_private_struct))) < 0)
++	ret = alloc_private(dev, sizeof(struct das08_private_struct));
++	if (ret < 0)
+ 		return ret;
+ 
+ 	printk("comedi%d: das08: ", dev->minor);
+diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
+index ed25a63da29c..a97739612f84 100644
+--- a/drivers/staging/comedi/drivers/das08_cs.c
++++ b/drivers/staging/comedi/drivers/das08_cs.c
+@@ -75,7 +75,8 @@ static int das08_cs_attach(struct comedi_device *dev, struct comedi_devconfig *i
+ 	unsigned long iobase;
+ 	struct pcmcia_device *link = cur_dev;	/*  XXX hack */
+ 
+-	if ((ret = alloc_private(dev, sizeof(struct das08_private_struct))) < 0)
++	ret = alloc_private(dev, sizeof(struct das08_private_struct));
++	if (ret < 0)
+ 		return ret;
+ 
+ 	printk("comedi%d: das08_cs: ", dev->minor);
+@@ -264,14 +265,23 @@ static void das08_pcmcia_config(struct pcmcia_device *link)
+ 	tuple.TupleDataMax = sizeof(buf);
+ 	tuple.TupleOffset = 0;
+ 	last_fn = GetFirstTuple;
+-	if ((last_ret = pcmcia_get_first_tuple(link, &tuple)) != 0)
++
++	last_ret = pcmcia_get_first_tuple(link, &tuple);
++	if (last_ret)
+ 		goto cs_failed;
++
+ 	last_fn = GetTupleData;
+-	if ((last_ret = pcmcia_get_tuple_data(link, &tuple)) != 0)
++
++	last_ret = pcmcia_get_tuple_data(link, &tuple);
++	if (last_ret)
+ 		goto cs_failed;
++
+ 	last_fn = ParseTuple;
+-	if ((last_ret = pcmcia_parse_tuple(&tuple, &parse)) != 0)
++
++	last_ret = pcmcia_parse_tuple(&tuple, &parse);
++	if (last_ret)
+ 		goto cs_failed;
++
+ 	link->conf.ConfigBase = parse.config.base;
+ 	link->conf.Present = parse.config.rmask[0];
+ 
+@@ -289,13 +299,20 @@ static void das08_pcmcia_config(struct pcmcia_device *link)
+ 	 */
+ 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+ 	last_fn = GetFirstTuple;
+-	if ((last_ret = pcmcia_get_first_tuple(link, &tuple)) != 0)
++
++	last_ret = pcmcia_get_first_tuple(link, &tuple);
++	if (last_ret)
+ 		goto cs_failed;
++
+ 	while (1) {
+ 		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
+-		if ((last_ret = pcmcia_get_tuple_data(link, &tuple)) != 0)
++
++		last_ret = pcmcia_get_tuple_data(link, &tuple);
++		if (last_ret)
+ 			goto next_entry;
+-		if ((last_ret = pcmcia_parse_tuple(&tuple, &parse)) != 0)
++
++		last_ret = pcmcia_parse_tuple(&tuple, &parse);
++		if (last_ret)
+ 			goto next_entry;
+ 
+ 		if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
+@@ -341,13 +358,16 @@ static void das08_pcmcia_config(struct pcmcia_device *link)
+ 
+ 	      next_entry:
+ 		last_fn = GetNextTuple;
+-		if ((last_ret = pcmcia_get_next_tuple(link, &tuple)) != 0)
++
++		last_ret = pcmcia_get_next_tuple(link, &tuple);
++		if (last_ret)
+ 			goto cs_failed;
+ 	}
+ 
+ 	if (link->conf.Attributes & CONF_ENABLE_IRQ) {
+ 		last_fn = RequestIRQ;
+-		if ((last_ret = pcmcia_request_irq(link, &link->irq)) != 0)
++		last_ret = pcmcia_request_irq(link, &link->irq);
++		if (last_ret)
+ 			goto cs_failed;
+ 	}
+ 
+@@ -357,7 +377,8 @@ static void das08_pcmcia_config(struct pcmcia_device *link)
+ 	   card and host interface into "Memory and IO" mode.
+ 	 */
+ 	last_fn = RequestConfiguration;
+-	if ((last_ret = pcmcia_request_configuration(link, &link->conf)) != 0)
++	last_ret = pcmcia_request_configuration(link, &link->conf);
++	if (last_ret)
+ 		goto cs_failed;
+ 
+ 	/*
+diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
+index 2082030bd4ff..090225128ce5 100644
+--- a/drivers/staging/comedi/drivers/das16.c
++++ b/drivers/staging/comedi/drivers/das16.c
+@@ -1400,7 +1400,8 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 		}
+ 	}
+ 
+-	if ((ret = alloc_private(dev, sizeof(struct das16_private_struct))) < 0)
++	ret = alloc_private(dev, sizeof(struct das16_private_struct));
++	if (ret < 0)
+ 		return ret;
+ 
+ 	if (thisboard->size < 0x400) {
+@@ -1450,8 +1451,10 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 
+ 	/* now for the irq */
+ 	if (irq > 1 && irq < 8) {
+-		if ((ret = comedi_request_irq(irq, das16_dma_interrupt, 0,
+-					"das16", dev)) < 0)
++		ret = comedi_request_irq(irq, das16_dma_interrupt, 0,
++					 "das16", dev);
++
++		if (ret < 0)
+ 			return ret;
+ 		dev->irq = irq;
+ 		printk(" ( irq = %u )", irq);
+@@ -1526,7 +1529,8 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	}
+ 	devpriv->timer_mode = timer_mode ? 1 : 0;
+ 
+-	if ((ret = alloc_subdevices(dev, 5)) < 0)
++	ret = alloc_subdevices(dev, 5);
++	if (ret < 0)
+ 		return ret;
+ 
+ 	s = dev->subdevices + 0;
+diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
+index 7d35183b1d35..c29e4dcd51a0 100644
+--- a/drivers/staging/comedi/drivers/das16m1.c
++++ b/drivers/staging/comedi/drivers/das16m1.c
+@@ -646,8 +646,8 @@ static int das16m1_attach(struct comedi_device *dev, struct comedi_devconfig *it
+ 
+ 	printk("comedi%d: das16m1:", dev->minor);
+ 
+-	if ((ret = alloc_private(dev,
+-				sizeof(struct das16m1_private_struct))) < 0)
++	ret = alloc_private(dev, sizeof(struct das16m1_private_struct));
++	if (ret < 0)
+ 		return ret;
+ 
+ 	dev->board_name = thisboard->name;
+@@ -687,7 +687,8 @@ static int das16m1_attach(struct comedi_device *dev, struct comedi_devconfig *it
+ 		return -EINVAL;
+ 	}
+ 
+-	if ((ret = alloc_subdevices(dev, 4)) < 0)
++	ret = alloc_subdevices(dev, 4);
++	if (ret < 0)
+ 		return ret;
+ 
+ 	s = dev->subdevices + 0;
+diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c
+index b2326ec50833..9b43f8732844 100644
+--- a/drivers/staging/comedi/drivers/das6402.c
++++ b/drivers/staging/comedi/drivers/das6402.c
+@@ -331,10 +331,12 @@ static int das6402_attach(struct comedi_device *dev, struct comedi_devconfig *it
+ 	}
+ 	dev->irq = irq;
+ 
+-	if ((ret = alloc_private(dev, sizeof(struct das6402_private))) < 0)
++	ret = alloc_private(dev, sizeof(struct das6402_private));
++	if (ret < 0)
+ 		return ret;
+ 
+-	if ((ret = alloc_subdevices(dev, 1)) < 0)
++	ret = alloc_subdevices(dev, 1);
++	if (ret < 0)
+ 		return ret;
+ 
+ 	/* ai subdevice */
+diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c
+index 309abba276d4..29fea1ac8ffa 100644
+--- a/drivers/staging/comedi/drivers/dt2801.c
++++ b/drivers/staging/comedi/drivers/dt2801.c
+@@ -521,10 +521,12 @@ static int dt2801_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	n_ai_chans = probe_number_of_ai_chans(dev);
+ 	printk(" (ai channels = %d)", n_ai_chans);
+ 
+-	if ((ret = alloc_subdevices(dev, 4)) < 0)
++	ret = alloc_subdevices(dev, 4);
++	if (ret < 0)
+ 		goto out;
+ 
+-	if ((ret = alloc_private(dev, sizeof(struct dt2801_private))) < 0)
++	ret = alloc_private(dev, sizeof(struct dt2801_private));
++	if (ret < 0)
+ 		goto out;
+ 
+ 	dev->board_name = boardtype.name;
+diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c
+index 634f2adf7628..b782118ebff0 100644
+--- a/drivers/staging/comedi/drivers/dt2811.c
++++ b/drivers/staging/comedi/drivers/dt2811.c
+@@ -379,10 +379,14 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	}
+ #endif
+ 
+-	if ((ret = alloc_subdevices(dev, 4)) < 0)
++	ret = alloc_subdevices(dev, 4);
++	if (ret < 0)
+ 		return ret;
+-	if ((ret = alloc_private(dev, sizeof(struct dt2811_private))) < 0)
++
++	ret = alloc_private(dev, sizeof(struct dt2811_private));
++	if (ret < 0)
+ 		return ret;
++
+ 	switch (it->options[2]) {
+ 	case 0:
+ 		devpriv->adc_mux = adc_singleended;
+diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c
+index 6b82f6ef53f3..4db82ae6bfb6 100644
+--- a/drivers/staging/comedi/drivers/dt2814.c
++++ b/drivers/staging/comedi/drivers/dt2814.c
+@@ -309,9 +309,12 @@ static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ #endif
+ 	}
+ 
+-	if ((ret = alloc_subdevices(dev, 1)) < 0)
++	ret = alloc_subdevices(dev, 1);
++	if (ret < 0)
+ 		return ret;
+-	if ((ret = alloc_private(dev, sizeof(struct dt2814_private))) < 0)
++
++	ret = alloc_private(dev, sizeof(struct dt2814_private));
++	if (ret < 0)
+ 		return ret;
+ 
+ 	s = dev->subdevices + 0;
+diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c
+index 8d52b2699220..7e944c544fa1 100644
+--- a/drivers/staging/comedi/drivers/dt2817.c
++++ b/drivers/staging/comedi/drivers/dt2817.c
+@@ -146,7 +146,8 @@ static int dt2817_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	dev->iobase = iobase;
+ 	dev->board_name = "dt2817";
+ 
+-	if ((ret = alloc_subdevices(dev, 1)) < 0)
++	ret = alloc_subdevices(dev, 1);
++	if (ret < 0)
+ 		return ret;
+ 
+ 	s = dev->subdevices + 0;
+diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
+index 66328353fdaa..64e9c4b32c0a 100644
+--- a/drivers/staging/comedi/drivers/dt282x.c
++++ b/drivers/staging/comedi/drivers/dt282x.c
+@@ -1326,7 +1326,8 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ #endif
+ 	}
+ 
+-	if ((ret = alloc_private(dev, sizeof(struct dt282x_private))) < 0)
++	ret = alloc_private(dev, sizeof(struct dt282x_private));
++	if (ret < 0)
+ 		return ret;
+ 
+ 	ret = dt282x_grab_dma(dev, it->options[opt_dma1],
+@@ -1334,7 +1335,8 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	if (ret < 0)
+ 		return ret;
+ 
+-	if ((ret = alloc_subdevices(dev, 3)) < 0)
++	ret = alloc_subdevices(dev, 3);
++	if (ret < 0)
+ 		return ret;
+ 
+ 	s = dev->subdevices + 0;
+@@ -1358,7 +1360,9 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	devpriv->ad_2scomp = it->options[opt_ai_twos];
+ 
+ 	s++;
+-	if ((s->n_chan = boardtype.dachan)) {
++
++	s->n_chan = boardtype.dachan;
++	if (s->n_chan) {
+ 		/* ao subsystem */
+ 		s->type = COMEDI_SUBD_AO;
+ 		dev->write_subdev = s;
+diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
+index 2d301597c3ed..c894e384c8ac 100644
+--- a/drivers/staging/comedi/drivers/dt3000.c
++++ b/drivers/staging/comedi/drivers/dt3000.c
+@@ -811,7 +811,8 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	bus = it->options[0];
+ 	slot = it->options[1];
+ 
+-	if ((ret = alloc_private(dev, sizeof(struct dt3k_private))) < 0)
++	ret = alloc_private(dev, sizeof(struct dt3k_private));
++	if (ret < 0)
+ 		return ret;
+ 
+ 	ret = dt_pci_probe(dev, bus, slot);
+@@ -831,7 +832,8 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	}
+ 	dev->irq = devpriv->pci_dev->irq;
+ 
+-	if ((ret = alloc_subdevices(dev, 4)) < 0)
++	ret = alloc_subdevices(dev, 4);
++	if (ret < 0)
+ 		return ret;
+ 
+ 	s = dev->subdevices;
+@@ -935,7 +937,8 @@ static int dt_pci_probe(struct comedi_device *dev, int bus, int slot)
+ 	if (!devpriv->pci_dev)
+ 		return 0;
+ 
+-	if ((ret = setup_pci(dev)) < 0)
++	ret = setup_pci(dev);
++	if (ret < 0)
+ 		return ret;
+ 
+ 	return 1;
+diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c
+index fd8eb85ddbe9..f4790bfa08ee 100644
+--- a/drivers/staging/comedi/drivers/ii_pci20kc.c
++++ b/drivers/staging/comedi/drivers/ii_pci20kc.c
+@@ -209,9 +209,12 @@ static int pci20xxx_attach(struct comedi_device *dev, struct comedi_devconfig *i
+ 	struct comedi_subdevice *s;
+ 	union pci20xxx_subdev_private *sdp;
+ 
+-	if ((ret = alloc_subdevices(dev, 1 + PCI20000_MODULES)) < 0)
++	ret = alloc_subdevices(dev, 1 + PCI20000_MODULES);
++	if (ret < 0)
+ 		return ret;
+-	if ((ret = alloc_private(dev, sizeof(struct pci20xxx_private))) < 0)
++
++	ret = alloc_private(dev, sizeof(struct pci20xxx_private));
++	if (ret < 0)
+ 		return ret;
+ 
+ 	devpriv->ioaddr = (void *)(unsigned long)it->options[0];
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
+index 8a9433472310..3cb5e4753df6 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -834,9 +834,12 @@ static int jr3_pci_attach(struct comedi_device *dev, struct comedi_devconfig *it
+ 		devpriv->pci_dev = card;
+ 		dev->board_name = "jr3_pci";
+ 	}
+-	if ((result = comedi_pci_enable(card, "jr3_pci")) < 0) {
++
++	result = comedi_pci_enable(card, "jr3_pci");
++	if (result < 0) {
+ 		return -EIO;
+ 	}
++
+ 	devpriv->pci_enabled = 1;
+ 	devpriv->iobase = ioremap(pci_resource_start(card, 0), sizeof(struct jr3_t));
+ 	result = alloc_subdevices(dev, devpriv->n_channels);
+diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c
+index cff8ea71e28d..e1f84a5c9670 100644
+--- a/drivers/staging/comedi/drivers/ke_counter.c
++++ b/drivers/staging/comedi/drivers/ke_counter.c
+@@ -157,9 +157,9 @@ static int cnt_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	int error, i;
+ 
+ 	/* allocate device private structure */
+-	if ((error = alloc_private(dev, sizeof(struct cnt_device_private))) < 0) {
++	error = alloc_private(dev, sizeof(struct cnt_device_private));
++	if (error < 0)
+ 		return error;
+-	}
+ 
+ 	/* Probe the device to determine what device in the series it is. */
+ 	for (pci_device = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
+@@ -203,7 +203,8 @@ static int cnt_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	dev->board_name = board->name;
+ 
+ 	/* enable PCI device and request regions */
+-	if ((error = comedi_pci_enable(pci_device, CNT_DRIVER_NAME)) < 0) {
++	error = comedi_pci_enable(pci_device, CNT_DRIVER_NAME);
++	if (error < 0) {
+ 		printk("comedi%d: failed to enable PCI device and request regions!\n", dev->minor);
+ 		return error;
+ 	}
+@@ -213,9 +214,9 @@ static int cnt_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	dev->iobase = io_base;
+ 
+ 	/* allocate the subdevice structures */
+-	if ((error = alloc_subdevices(dev, 1)) < 0) {
++	error = alloc_subdevices(dev, 1);
++	if (error < 0)
+ 		return error;
+-	}
+ 
+ 	subdevice = dev->subdevices + 0;
+ 	dev->read_subdev = subdevice;
+diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
+index 4f476ec2d2f5..78ba17aec0ad 100644
+--- a/drivers/staging/comedi/drivers/ni_6527.c
++++ b/drivers/staging/comedi/drivers/ni_6527.c
+@@ -371,7 +371,8 @@ static int ni6527_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 
+ 	printk("comedi%d: ni6527:", dev->minor);
+ 
+-	if ((ret = alloc_private(dev, sizeof(struct ni6527_private))) < 0)
++	ret = alloc_private(dev, sizeof(struct ni6527_private));
++	if (ret < 0)
+ 		return ret;
+ 
+ 	ret = ni6527_find_device(dev, it->options[0], it->options[1]);
+@@ -389,7 +390,8 @@ static int ni6527_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 
+ 	printk(" ID=0x%02x", readb(devpriv->mite->daq_io_addr + ID_Register));
+ 
+-	if ((ret = alloc_subdevices(dev, 3)) < 0)
++	ret = alloc_subdevices(dev, 3);
++	if (ret < 0)
+ 		return ret;
+ 
+ 	s = dev->subdevices + 0;
+diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
+index 72005a40ad99..7cf22c0f566b 100644
+--- a/drivers/staging/comedi/drivers/ni_65xx.c
++++ b/drivers/staging/comedi/drivers/ni_65xx.c
+@@ -627,7 +627,8 @@ static int ni_65xx_attach(struct comedi_device *dev, struct comedi_devconfig *it
+ 
+ 	printk("comedi%d: ni_65xx:", dev->minor);
+ 
+-	if ((ret = alloc_private(dev, sizeof(struct ni_65xx_private))) < 0)
++	ret = alloc_private(dev, sizeof(struct ni_65xx_private));
++	if (ret < 0)
+ 		return ret;
+ 
+ 	ret = ni_65xx_find_device(dev, it->options[0], it->options[1]);
+@@ -647,7 +648,8 @@ static int ni_65xx_attach(struct comedi_device *dev, struct comedi_devconfig *it
+ 	printk(" ID=0x%02x",
+ 		readb(private(dev)->mite->daq_io_addr + ID_Register));
+ 
+-	if ((ret = alloc_subdevices(dev, 4)) < 0)
++	ret = alloc_subdevices(dev, 4);
++	if (ret < 0)
+ 		return ret;
+ 
+ 	s = dev->subdevices + 0;
+diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
+index b11f134e8c70..3c35dab02796 100644
+--- a/drivers/staging/comedi/drivers/ni_660x.c
++++ b/drivers/staging/comedi/drivers/ni_660x.c
+@@ -960,8 +960,10 @@ static int ni_660x_allocate_private(struct comedi_device *dev)
+ 	int retval;
+ 	unsigned i;
+ 
+-	if ((retval = alloc_private(dev, sizeof(struct ni_660x_private))) < 0)
++	retval = alloc_private(dev, sizeof(struct ni_660x_private));
++	if (retval < 0)
+ 		return retval;
++
+ 	spin_lock_init(&private(dev)->mite_channel_lock);
+ 	spin_lock_init(&private(dev)->interrupt_lock);
+ 	spin_lock_init(&private(dev)->soft_reg_copy_lock);
+@@ -1105,9 +1107,11 @@ static int ni_660x_attach(struct comedi_device *dev, struct comedi_devconfig *it
+ 	for (i = 0; i < board(dev)->n_chips; ++i) {
+ 		set_tio_counterswap(dev, i);
+ 	}
+-	if ((ret = comedi_request_irq(mite_irq(private(dev)->mite),
+-				&ni_660x_interrupt, IRQF_SHARED, "ni_660x",
+-				dev)) < 0) {
++	ret = comedi_request_irq(mite_irq(private(dev)->mite),
++				 ni_660x_interrupt, IRQF_SHARED, "ni_660x",
++				 dev);
++
++	if (ret < 0) {
+ 		printk(" irq not available\n");
+ 		return ret;
+ 	}
+diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
+index c00bd0d40458..0caa4864190c 100644
+--- a/drivers/staging/comedi/drivers/ni_670x.c
++++ b/drivers/staging/comedi/drivers/ni_670x.c
+@@ -144,7 +144,8 @@ static int ni_670x_attach(struct comedi_device *dev, struct comedi_devconfig *it
+ 
+ 	printk("comedi%d: ni_670x: ", dev->minor);
+ 
+-	if ((ret = alloc_private(dev, sizeof(struct ni_670x_private))) < 0)
++	ret = alloc_private(dev, sizeof(struct ni_670x_private));
++	if (ret < 0)
+ 		return ret;
+ 
+ 	ret = ni_670x_find_device(dev, it->options[0], it->options[1]);
+diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c
+index f8dda9a092e8..c4c47497373b 100644
+--- a/drivers/staging/comedi/drivers/ni_atmio.c
++++ b/drivers/staging/comedi/drivers/ni_atmio.c
+@@ -414,8 +414,10 @@ static int ni_atmio_attach(struct comedi_device *dev, struct comedi_devconfig *i
+ 	unsigned int irq;
+ 
+ 	/* allocate private area */
+-	if ((ret = ni_alloc_private(dev)) < 0)
++	ret = ni_alloc_private(dev);
++	if (ret < 0)
+ 		return ret;
++
+ 	devpriv->stc_writew = &ni_atmio_win_out;
+ 	devpriv->stc_readw = &ni_atmio_win_in;
+ 	devpriv->stc_writel = &win_out2;
+@@ -476,8 +478,10 @@ static int ni_atmio_attach(struct comedi_device *dev, struct comedi_devconfig *i
+ 			return -EINVAL;
+ 		}
+ 		printk(" ( irq = %u )", irq);
+-		if ((ret = comedi_request_irq(irq, ni_E_interrupt,
+-					NI_E_IRQ_FLAGS, "ni_atmio", dev)) < 0) {
++		ret = comedi_request_irq(irq, ni_E_interrupt,
++					  NI_E_IRQ_FLAGS, "ni_atmio", dev);
++
++		if (ret < 0) {
+ 			printk(" irq not available\n");
+ 			return -EINVAL;
+ 		}
+@@ -486,7 +490,8 @@ static int ni_atmio_attach(struct comedi_device *dev, struct comedi_devconfig *i
+ 
+ 	/* generic E series stuff in ni_mio_common.c */
+ 
+-	if ((ret = ni_E_init(dev, it)) < 0) {
++	ret = ni_E_init(dev, it);
++	if (ret < 0) {
+ 		return ret;
+ 	}
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
+index 9fafe0c234d9..b110ec651b42 100644
+--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
++++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
+@@ -449,11 +449,13 @@ static int atmio16d_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s
+ 		outw(devpriv->com_reg_1_state, dev->iobase + COM_REG_1);
+ 	} else {
+ 		/* Counter 4 and 5 are needed */
+-		if ((tmp = sample_count & 0xFFFF)) {
++
++		tmp = sample_count & 0xFFFF;
++		if (tmp)
+ 			outw(tmp - 1, dev->iobase + AM9513A_DATA_REG);
+-		} else {
++		else
+ 			outw(0xFFFF, dev->iobase + AM9513A_DATA_REG);
+-		}
++
+ 		outw(0xFF48, dev->iobase + AM9513A_COM_REG);
+ 		outw(0, dev->iobase + AM9513A_DATA_REG);
+ 		outw(0xFF28, dev->iobase + AM9513A_COM_REG);
+@@ -726,9 +728,12 @@ static int atmio16d_attach(struct comedi_device *dev, struct comedi_devconfig *i
+ 	/* board name */
+ 	dev->board_name = boardtype->name;
+ 
+-	if ((ret = alloc_subdevices(dev, 4)) < 0)
++	ret = alloc_subdevices(dev, 4);
++	if (ret < 0)
+ 		return ret;
+-	if ((ret = alloc_private(dev, sizeof(struct atmio16d_private))) < 0)
++
++	ret = alloc_private(dev, sizeof(struct atmio16d_private));
++	if (ret < 0)
+ 		return ret;
+ 
+ 	/* reset the atmio16d hardware */
+@@ -737,8 +742,10 @@ static int atmio16d_attach(struct comedi_device *dev, struct comedi_devconfig *i
+ 	/* check if our interrupt is available and get it */
+ 	irq = it->options[1];
+ 	if (irq) {
+-		if ((ret = comedi_request_irq(irq, atmio16d_interrupt,
+-					0, "atmio16d", dev)) < 0) {
++
++		ret = comedi_request_irq(irq, atmio16d_interrupt,
++					  0, "atmio16d", dev);
++		if (ret < 0) {
+ 			printk("failed to allocate irq %u\n", irq);
+ 			return ret;
+ 		}
+diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
+index 21c71c9b3007..8f594a8778cf 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_700.c
++++ b/drivers/staging/comedi/drivers/ni_daq_700.c
+@@ -594,15 +594,21 @@ static void dio700_config(struct pcmcia_device *link)
+ 	tuple.TupleData = buf;
+ 	tuple.TupleDataMax = sizeof(buf);
+ 	tuple.TupleOffset = 0;
+-	if ((last_ret = pcmcia_get_first_tuple(link, &tuple)) != 0) {
++
++	last_ret = pcmcia_get_first_tuple(link, &tuple);
++	if (last_ret) {
+ 		cs_error(link, GetFirstTuple, last_ret);
+ 		goto cs_failed;
+ 	}
+-	if ((last_ret = pcmcia_get_tuple_data(link, &tuple)) != 0) {
++
++	last_ret = pcmcia_get_tuple_data(link, &tuple);
++	if (last_ret) {
+ 		cs_error(link, GetTupleData, last_ret);
+ 		goto cs_failed;
+ 	}
+-	if ((last_ret = pcmcia_parse_tuple(&tuple, &parse)) != 0) {
++
++	last_ret = pcmcia_parse_tuple(&tuple, &parse);
++	 if (last_ret) {
+ 		cs_error(link, ParseTuple, last_ret);
+ 		goto cs_failed;
+ 	}
+@@ -622,7 +628,8 @@ static void dio700_config(struct pcmcia_device *link)
+ 	   will only use the CIS to fill in implementation-defined details.
+ 	 */
+ 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+-	if ((last_ret = pcmcia_get_first_tuple(link, &tuple)) != 0) {
++	last_ret = pcmcia_get_first_tuple(link, &tuple);
++	if (last_ret != 0) {
+ 		cs_error(link, GetFirstTuple, last_ret);
+ 		goto cs_failed;
+ 	}
+@@ -692,7 +699,9 @@ static void dio700_config(struct pcmcia_device *link)
+ 		break;
+ 
+ 	      next_entry:
+-		if ((last_ret = pcmcia_get_next_tuple(link, &tuple)) != 0) {
++
++		last_ret = pcmcia_get_next_tuple(link, &tuple);
++		if (last_ret) {
+ 			cs_error(link, GetNextTuple, last_ret);
+ 			goto cs_failed;
+ 		}
+@@ -703,18 +712,21 @@ static void dio700_config(struct pcmcia_device *link)
+ 	   handler to the interrupt, unless the 'Handler' member of the
+ 	   irq structure is initialized.
+ 	 */
+-	if (link->conf.Attributes & CONF_ENABLE_IRQ)
+-		if ((last_ret = pcmcia_request_irq(link, &link->irq)) != 0) {
++	if (link->conf.Attributes & CONF_ENABLE_IRQ) {
++		last_ret = pcmcia_request_irq(link, &link->irq);
++		if (last_ret) {
+ 			cs_error(link, RequestIRQ, last_ret);
+ 			goto cs_failed;
+ 		}
++	}
+ 
+ 	/*
+ 	   This actually configures the PCMCIA socket -- setting up
+ 	   the I/O windows and the interrupt mapping, and putting the
+ 	   card and host interface into "Memory and IO" mode.
+ 	 */
+-	if ((last_ret = pcmcia_request_configuration(link, &link->conf)) != 0) {
++	last_ret = pcmcia_request_configuration(link, &link->conf);
++	if (last_ret != 0) {
+ 		cs_error(link, RequestConfiguration, last_ret);
+ 		goto cs_failed;
+ 	}
+diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
+index 6474591eb0c2..f7814dbedb4b 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
++++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
+@@ -351,15 +351,21 @@ static void dio24_config(struct pcmcia_device *link)
+ 	tuple.TupleData = buf;
+ 	tuple.TupleDataMax = sizeof(buf);
+ 	tuple.TupleOffset = 0;
+-	if ((last_ret = pcmcia_get_first_tuple(link, &tuple)) != 0) {
++
++	last_ret = pcmcia_get_first_tuple(link, &tuple);
++	if (last_ret) {
+ 		cs_error(link, GetFirstTuple, last_ret);
+ 		goto cs_failed;
+ 	}
+-	if ((last_ret = pcmcia_get_tuple_data(link, &tuple)) != 0) {
++
++	last_ret = pcmcia_get_tuple_data(link, &tuple);
++	if (last_ret) {
+ 		cs_error(link, GetTupleData, last_ret);
+ 		goto cs_failed;
+ 	}
+-	if ((last_ret = pcmcia_parse_tuple(&tuple, &parse)) != 0) {
++
++	last_ret = pcmcia_parse_tuple(&tuple, &parse);
++	if (last_ret) {
+ 		cs_error(link, ParseTuple, last_ret);
+ 		goto cs_failed;
+ 	}
+@@ -379,7 +385,9 @@ static void dio24_config(struct pcmcia_device *link)
+ 	   will only use the CIS to fill in implementation-defined details.
+ 	 */
+ 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+-	if ((last_ret = pcmcia_get_first_tuple(link, &tuple)) != 0) {
++
++	last_ret = pcmcia_get_first_tuple(link, &tuple);
++	if (last_ret) {
+ 		cs_error(link, GetFirstTuple, last_ret);
+ 		goto cs_failed;
+ 	}
+@@ -449,7 +457,9 @@ static void dio24_config(struct pcmcia_device *link)
+ 		break;
+ 
+ 	      next_entry:
+-		if ((last_ret = pcmcia_get_next_tuple(link, &tuple)) != 0) {
++
++		last_ret = pcmcia_get_next_tuple(link, &tuple);
++		if (last_ret) {
+ 			cs_error(link, GetNextTuple, last_ret);
+ 			goto cs_failed;
+ 		}
+@@ -460,18 +470,21 @@ static void dio24_config(struct pcmcia_device *link)
+ 	   handler to the interrupt, unless the 'Handler' member of the
+ 	   irq structure is initialized.
+ 	 */
+-	if (link->conf.Attributes & CONF_ENABLE_IRQ)
+-		if ((last_ret = pcmcia_request_irq(link, &link->irq)) != 0) {
++	if (link->conf.Attributes & CONF_ENABLE_IRQ) {
++		last_ret = pcmcia_request_irq(link, &link->irq);
++		if (last_ret) {
+ 			cs_error(link, RequestIRQ, last_ret);
+ 			goto cs_failed;
+ 		}
++	}
+ 
+ 	/*
+ 	   This actually configures the PCMCIA socket -- setting up
+ 	   the I/O windows and the interrupt mapping, and putting the
+ 	   card and host interface into "Memory and IO" mode.
+ 	 */
+-	if ((last_ret = pcmcia_request_configuration(link, &link->conf)) != 0) {
++	last_ret = pcmcia_request_configuration(link, &link->conf);
++	if (last_ret) {
+ 		cs_error(link, RequestConfiguration, last_ret);
+ 		goto cs_failed;
+ 	}
+diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
+index b0c523e9f198..e504f4f594a6 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
++++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
+@@ -327,15 +327,21 @@ static void labpc_config(struct pcmcia_device *link)
+ 	tuple.TupleData = buf;
+ 	tuple.TupleDataMax = sizeof(buf);
+ 	tuple.TupleOffset = 0;
+-	if ((last_ret = pcmcia_get_first_tuple(link, &tuple))) {
++
++	last_ret = pcmcia_get_first_tuple(link, &tuple);
++	if (last_ret) {
+ 		cs_error(link, GetFirstTuple, last_ret);
+ 		goto cs_failed;
+ 	}
+-	if ((last_ret = pcmcia_get_tuple_data(link, &tuple))) {
++
++	last_ret = pcmcia_get_tuple_data(link, &tuple);
++	if (last_ret) {
+ 		cs_error(link, GetTupleData, last_ret);
+ 		goto cs_failed;
+ 	}
+-	if ((last_ret = pcmcia_parse_tuple(&tuple, &parse))) {
++
++	last_ret = pcmcia_parse_tuple(&tuple, &parse);
++	if (last_ret) {
+ 		cs_error(link, ParseTuple, last_ret);
+ 		goto cs_failed;
+ 	}
+@@ -355,7 +361,8 @@ static void labpc_config(struct pcmcia_device *link)
+ 	   will only use the CIS to fill in implementation-defined details.
+ 	 */
+ 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+-	if ((last_ret = pcmcia_get_first_tuple(link, &tuple))) {
++	last_ret = pcmcia_get_first_tuple(link, &tuple);
++	if (last_ret) {
+ 		cs_error(link, GetFirstTuple, last_ret);
+ 		goto cs_failed;
+ 	}
+@@ -422,7 +429,8 @@ static void labpc_config(struct pcmcia_device *link)
+ 		break;
+ 
+ 	      next_entry:
+-		if ((last_ret = pcmcia_get_next_tuple(link, &tuple))) {
++		last_ret = pcmcia_get_next_tuple(link, &tuple);
++		if (last_ret) {
+ 			cs_error(link, GetNextTuple, last_ret);
+ 			goto cs_failed;
+ 		}
+@@ -433,18 +441,21 @@ static void labpc_config(struct pcmcia_device *link)
+ 	   handler to the interrupt, unless the 'Handler' member of the
+ 	   irq structure is initialized.
+ 	 */
+-	if (link->conf.Attributes & CONF_ENABLE_IRQ)
+-		if ((last_ret = pcmcia_request_irq(link, &link->irq))) {
++	if (link->conf.Attributes & CONF_ENABLE_IRQ) {
++		last_ret = pcmcia_request_irq(link, &link->irq);
++		if (last_ret) {
+ 			cs_error(link, RequestIRQ, last_ret);
+ 			goto cs_failed;
+ 		}
++	}
+ 
+ 	/*
+ 	   This actually configures the PCMCIA socket -- setting up
+ 	   the I/O windows and the interrupt mapping, and putting the
+ 	   card and host interface into "Memory and IO" mode.
+ 	 */
+-	if ((last_ret = pcmcia_request_configuration(link, &link->conf))) {
++	last_ret = pcmcia_request_configuration(link, &link->conf);
++	if (last_ret) {
+ 		cs_error(link, RequestConfiguration, last_ret);
+ 		goto cs_failed;
+ 	}
+diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c
+index ff53ef781499..a7ab3f72c7aa 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_cs.c
++++ b/drivers/staging/comedi/drivers/ni_mio_cs.c
+@@ -446,24 +446,28 @@ static int mio_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	printk(" %s", boardtype.name);
+ 	dev->board_name = boardtype.name;
+ 
+-	if ((ret = comedi_request_irq(irq, ni_E_interrupt, NI_E_IRQ_FLAGS,
+-				"ni_mio_cs", dev)) < 0) {
++	ret = comedi_request_irq(irq, ni_E_interrupt, NI_E_IRQ_FLAGS,
++				 "ni_mio_cs", dev);
++	if (ret < 0) {
+ 		printk(" irq not available\n");
+ 		return -EINVAL;
+ 	}
+ 	dev->irq = irq;
+ 
+ 	/* allocate private area */
+-	if ((ret = ni_alloc_private(dev)) < 0)
++	ret = ni_alloc_private(dev);
++	if (ret < 0)
+ 		return ret;
++
+ 	devpriv->stc_writew = &mio_cs_win_out;
+ 	devpriv->stc_readw = &mio_cs_win_in;
+ 	devpriv->stc_writel = &win_out2;
+ 	devpriv->stc_readl = &win_in2;
+ 
+-	if ((ret = ni_E_init(dev, it)) < 0) {
++	ret = ni_E_init(dev, it);
++
++	if (ret < 0)
+ 		return ret;
+-	}
+ 
+ 	return 0;
+ }
+diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
+index 39566316dc80..bfccafe6080b 100644
+--- a/drivers/staging/comedi/drivers/ni_pcimio.c
++++ b/drivers/staging/comedi/drivers/ni_pcimio.c
+@@ -1679,9 +1679,10 @@ static int pcimio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 		printk(" unknown irq (bad)\n");
+ 	} else {
+ 		printk(" ( irq = %u )", dev->irq);
+-		if ((ret = comedi_request_irq(dev->irq, ni_E_interrupt,
+-					NI_E_IRQ_FLAGS, DRV_NAME,
+-					dev)) < 0) {
++		ret = comedi_request_irq(dev->irq, ni_E_interrupt,
++					 NI_E_IRQ_FLAGS, DRV_NAME,
++					 dev);
++		if (ret < 0) {
+ 			printk(" irq not available\n");
+ 			dev->irq = 0;
+ 		}
+diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c
+index 73b56b36d7c7..e1a4917fc3ce 100644
+--- a/drivers/staging/comedi/drivers/pcl711.c
++++ b/drivers/staging/comedi/drivers/pcl711.c
+@@ -550,9 +550,12 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	}
+ 	dev->irq = irq;
+ 
+-	if ((ret = alloc_subdevices(dev, 4)) < 0)
++	ret = alloc_subdevices(dev, 4);
++	if (ret < 0)
+ 		return ret;
+-	if ((ret = alloc_private(dev, sizeof(struct pcl711_private))) < 0)
++
++	ret = alloc_private(dev, sizeof(struct pcl711_private));
++	if (ret < 0)
+ 		return ret;
+ 
+ 	s = dev->subdevices + 0;
+diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c
+index 75ab137ce36f..5d3ba759e862 100644
+--- a/drivers/staging/comedi/drivers/pcl724.c
++++ b/drivers/staging/comedi/drivers/pcl724.c
+@@ -183,7 +183,8 @@ static int pcl724_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 			|| (it->options[1] == 96)))
+ 		n_subdevices = 4;	/*  PCL-724 in 96 DIO configuration */
+ 
+-	if ((ret = alloc_subdevices(dev, n_subdevices)) < 0)
++	ret = alloc_subdevices(dev, n_subdevices);
++	if (ret < 0)
+ 		return ret;
+ 
+ 	for (i = 0; i < dev->n_subdevices; i++) {
+diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c
+index 7c9112b0fdca..408f1ef664f9 100644
+--- a/drivers/staging/comedi/drivers/pcl726.c
++++ b/drivers/staging/comedi/drivers/pcl726.c
+@@ -264,7 +264,8 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 
+ 	dev->board_name = this_board->name;
+ 
+-	if ((ret = alloc_private(dev, sizeof(struct pcl726_private))) < 0)
++	ret = alloc_private(dev, sizeof(struct pcl726_private));
++	if (ret < 0)
+ 		return -ENOMEM;
+ 
+ 	for (i = 0; i < 12; i++) {
+@@ -302,7 +303,8 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 
+ 	printk("\n");
+ 
+-	if ((ret = alloc_subdevices(dev, 3)) < 0)
++	ret = alloc_subdevices(dev, 3);
++	if (ret < 0)
+ 		return ret;
+ 
+ 	s = dev->subdevices + 0;
+diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
+index 1f6f3e8b4185..6a6e84a52521 100644
+--- a/drivers/staging/comedi/drivers/pcl812.c
++++ b/drivers/staging/comedi/drivers/pcl812.c
+@@ -1286,7 +1286,8 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	}
+ 	dev->iobase = iobase;
+ 
+-	if ((ret = alloc_private(dev, sizeof(struct pcl812_private))) < 0) {
++	ret = alloc_private(dev, sizeof(struct pcl812_private));
++	if (ret < 0) {
+ 		free_resources(dev);
+ 		return ret;	/* Can't alloc mem */
+ 	}
+@@ -1364,7 +1365,8 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	if (this_board->n_dochan > 0)
+ 		n_subdevices++;
+ 
+-	if ((ret = alloc_subdevices(dev, n_subdevices)) < 0) {
++	ret = alloc_subdevices(dev, n_subdevices);
++	if (ret < 0) {
+ 		free_resources(dev);
+ 		return ret;
+ 	}
+diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
+index f44bd43f5d3f..c52ba0319a46 100644
+--- a/drivers/staging/comedi/drivers/pcl816.c
++++ b/drivers/staging/comedi/drivers/pcl816.c
+@@ -1041,7 +1041,8 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 		return -EIO;
+ 	}
+ 
+-	if ((ret = alloc_private(dev, sizeof(struct pcl816_private))) < 0)
++	ret = alloc_private(dev, sizeof(struct pcl816_private));
++	if (ret < 0)
+ 		return ret;	/* Can't alloc mem */
+ 
+ 	/* set up some name stuff */
+@@ -1177,7 +1178,9 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+   if (this_board->n_dochan > 0)
+     subdevs[3] = COMEDI_SUBD_DO;
+ */
+-	if ((ret = alloc_subdevices(dev, 1)) < 0)
++
++	ret = alloc_subdevices(dev, 1);
++	if (ret < 0)
+ 		return ret;
+ 
+ 	s = dev->subdevices + 0;
+diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
+index f1deeb247e19..6fbc9abdbd7b 100644
+--- a/drivers/staging/comedi/drivers/pcl818.c
++++ b/drivers/staging/comedi/drivers/pcl818.c
+@@ -1703,7 +1703,8 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	unsigned long pages;
+ 	struct comedi_subdevice *s;
+ 
+-	if ((ret = alloc_private(dev, sizeof(struct pcl818_private))) < 0)
++	ret = alloc_private(dev, sizeof(struct pcl818_private));
++	if (ret < 0)
+ 		return ret;	/* Can't alloc mem */
+ 
+ 	/* claim our I/O space */
+@@ -1842,7 +1843,8 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 
+       no_dma:
+ 
+-	if ((ret = alloc_subdevices(dev, 4)) < 0)
++	ret = alloc_subdevices(dev, 4);
++	if (ret < 0)
+ 		return ret;
+ 
+ 	s = dev->subdevices + 0;
+diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c
+index 5178b43b1072..36310adf5fb7 100644
+--- a/drivers/staging/comedi/drivers/pcm3724.c
++++ b/drivers/staging/comedi/drivers/pcm3724.c
+@@ -260,7 +260,9 @@ static int pcm3724_attach(struct comedi_device *dev, struct comedi_devconfig *it
+ 
+ 	iobase = it->options[0];
+ 	iorange = this_board->io_range;
+-	if ((ret = alloc_private(dev, sizeof(struct priv_pcm3724))) < 0)
++
++	ret = alloc_private(dev, sizeof(struct priv_pcm3724));
++	if (ret < 0)
+ 		return -ENOMEM;
+ 
+ 	((struct priv_pcm3724 *) (dev->private))->dio_1 = 0;
+@@ -279,7 +281,8 @@ static int pcm3724_attach(struct comedi_device *dev, struct comedi_devconfig *it
+ 
+ 	n_subdevices = this_board->numofports;
+ 
+-	if ((ret = alloc_subdevices(dev, n_subdevices)) < 0)
++	ret = alloc_subdevices(dev, n_subdevices);
++	if (ret < 0)
+ 		return ret;
+ 
+ 	for (i = 0; i < dev->n_subdevices; i++) {
+diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c
+index 15986691ff32..f1e19cc2ac20 100644
+--- a/drivers/staging/comedi/drivers/pcmad.c
++++ b/drivers/staging/comedi/drivers/pcmad.c
+@@ -140,9 +140,12 @@ static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	}
+ 	dev->iobase = iobase;
+ 
+-	if ((ret = alloc_subdevices(dev, 1)) < 0)
++	ret = alloc_subdevices(dev, 1);
++	if (ret < 0)
+ 		return ret;
+-	if ((ret = alloc_private(dev, sizeof(struct pcmad_priv_struct))) < 0)
++
++	ret = alloc_private(dev, sizeof(struct pcmad_priv_struct));
++	if (ret < 0)
+ 		return ret;
+ 
+ 	dev->board_name = this_board->name;
+diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
+index 849fa4fa4ced..82da558fc8f7 100644
+--- a/drivers/staging/comedi/drivers/pcmmio.c
++++ b/drivers/staging/comedi/drivers/pcmmio.c
+@@ -921,7 +921,8 @@ static void pcmmio_stop_intr(struct comedi_device *dev, struct comedi_subdevice
+ {
+ 	int nports, firstport, asic, port;
+ 
+-	if ((asic = subpriv->dio.intr.asic) < 0)
++	asic = subpriv->dio.intr.asic;
++	if (asic < 0)
+ 		return;		/* not an interrupt subdev */
+ 
+ 	subpriv->dio.intr.enabled_mask = 0;
+@@ -948,7 +949,8 @@ static int pcmmio_start_intr(struct comedi_device *dev, struct comedi_subdevice
+ 		int nports, firstport, asic, port;
+ 		struct comedi_cmd *cmd = &s->async->cmd;
+ 
+-		if ((asic = subpriv->dio.intr.asic) < 0)
++		asic = subpriv->dio.intr.asic;
++		if (asic  < 0)
+ 			return 1;	/* not an interrupt
+ 					   subdev */
+ 		subpriv->dio.intr.enabled_mask = 0;
+diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
+index 7e442dbd2c19..cc62f518128e 100644
+--- a/drivers/staging/comedi/drivers/pcmuio.c
++++ b/drivers/staging/comedi/drivers/pcmuio.c
+@@ -841,7 +841,8 @@ static void pcmuio_stop_intr(struct comedi_device *dev, struct comedi_subdevice
+ {
+ 	int nports, firstport, asic, port;
+ 
+-	if ((asic = subpriv->intr.asic) < 0)
++	asic = subpriv->intr.asic;
++	if (asic < 0)
+ 		return;		/* not an interrupt subdev */
+ 
+ 	subpriv->intr.enabled_mask = 0;
+@@ -868,7 +869,8 @@ static int pcmuio_start_intr(struct comedi_device *dev, struct comedi_subdevice
+ 		int nports, firstport, asic, port;
+ 		struct comedi_cmd *cmd = &s->async->cmd;
+ 
+-		if ((asic = subpriv->intr.asic) < 0)
++		asic = subpriv->intr.asic;
++		if (asic < 0)
+ 			return 1;	/* not an interrupt
+ 					   subdev */
+ 		subpriv->intr.enabled_mask = 0;
+diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+index 0066218dba48..d6427e2fc14c 100644
+--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
++++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+@@ -908,7 +908,8 @@ static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 
+ 	dev->iobase = local->link->io.BasePort1;
+ 
+-	if ((ret = alloc_subdevices(dev, 4)) < 0)
++	ret = alloc_subdevices(dev, 4);
++	if (ret < 0)
+ 		return ret;
+ 
+ 	printk("comedi%d: attaching daqp%d (io 0x%04lx)\n",
+@@ -1149,15 +1150,21 @@ static void daqp_cs_config(struct pcmcia_device *link)
+ 	tuple.TupleData = buf;
+ 	tuple.TupleDataMax = sizeof(buf);
+ 	tuple.TupleOffset = 0;
+-	if ((last_ret = pcmcia_get_first_tuple(link, &tuple))) {
++
++	last_ret = pcmcia_get_first_tuple(link, &tuple);
++	if (last_ret) {
+ 		cs_error(link, GetFirstTuple, last_ret);
+ 		goto cs_failed;
+ 	}
+-	if ((last_ret = pcmcia_get_tuple_data(link, &tuple))) {
++
++	last_ret = pcmcia_get_tuple_data(link, &tuple);
++	if (last_ret) {
+ 		cs_error(link, GetTupleData, last_ret);
+ 		goto cs_failed;
+ 	}
+-	if ((last_ret = pcmcia_parse_tuple(&tuple, &parse))) {
++
++	last_ret = pcmcia_parse_tuple(&tuple, &parse);
++	if (last_ret) {
+ 		cs_error(link, ParseTuple, last_ret);
+ 		goto cs_failed;
+ 	}
+@@ -1177,10 +1184,12 @@ static void daqp_cs_config(struct pcmcia_device *link)
+ 	   will only use the CIS to fill in implementation-defined details.
+ 	 */
+ 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+-	if ((last_ret = pcmcia_get_first_tuple(link, &tuple))) {
++	last_ret = pcmcia_get_first_tuple(link, &tuple);
++	if (last_ret) {
+ 		cs_error(link, GetFirstTuple, last_ret);
+ 		goto cs_failed;
+ 	}
++
+ 	while (1) {
+ 		cistpl_cftable_entry_t dflt = { 0 };
+ 		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
+@@ -1226,7 +1235,8 @@ static void daqp_cs_config(struct pcmcia_device *link)
+ 		break;
+ 
+ 	      next_entry:
+-		if ((last_ret = pcmcia_get_next_tuple(link, &tuple))) {
++		last_ret = pcmcia_get_next_tuple(link, &tuple);
++		if (last_ret) {
+ 			cs_error(link, GetNextTuple, last_ret);
+ 			goto cs_failed;
+ 		}
+@@ -1237,18 +1247,21 @@ static void daqp_cs_config(struct pcmcia_device *link)
+ 	   handler to the interrupt, unless the 'Handler' member of the
+ 	   irq structure is initialized.
+ 	 */
+-	if (link->conf.Attributes & CONF_ENABLE_IRQ)
+-		if ((last_ret = pcmcia_request_irq(link, &link->irq))) {
++	if (link->conf.Attributes & CONF_ENABLE_IRQ) {
++		last_ret = pcmcia_request_irq(link, &link->irq);
++		if (last_ret) {
+ 			cs_error(link, RequestIRQ, last_ret);
+ 			goto cs_failed;
+ 		}
++	}
+ 
+ 	/*
+ 	   This actually configures the PCMCIA socket -- setting up
+ 	   the I/O windows and the interrupt mapping, and putting the
+ 	   card and host interface into "Memory and IO" mode.
+ 	 */
+-	if ((last_ret = pcmcia_request_configuration(link, &link->conf))) {
++	last_ret = pcmcia_request_configuration(link, &link->conf);
++	if (last_ret) {
+ 		cs_error(link, RequestConfiguration, last_ret);
+ 		goto cs_failed;
+ 	}
+diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c
+index cac2abf6f03a..b2579f42573c 100644
+--- a/drivers/staging/comedi/drivers/rti800.c
++++ b/drivers/staging/comedi/drivers/rti800.c
+@@ -339,8 +339,9 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	irq = it->options[1];
+ 	if (irq) {
+ 		printk("( irq = %u )", irq);
+-		if ((ret = comedi_request_irq(irq, rti800_interrupt, 0,
+-					"rti800", dev)) < 0) {
++		ret = comedi_request_irq(irq, rti800_interrupt, 0,
++					 "rti800", dev);
++		if (ret < 0) {
+ 			printk(" Failed to allocate IRQ\n");
+ 			return ret;
+ 		}
+@@ -351,9 +352,12 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 
+ 	dev->board_name = this_board->name;
+ 
+-	if ((ret = alloc_subdevices(dev, 4)) < 0)
++	ret = alloc_subdevices(dev, 4);
++	if (ret < 0)
+ 		return ret;
+-	if ((ret = alloc_private(dev, sizeof(struct rti800_private))) < 0)
++
++	ret = alloc_private(dev, sizeof(struct rti800_private));
++	if (ret < 0)
+ 		return ret;
+ 
+ 	devpriv->adc_mux = it->options[2];
+diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c
+index 5b383e6354e0..18e5ddf6f968 100644
+--- a/drivers/staging/comedi/drivers/unioxx5.c
++++ b/drivers/staging/comedi/drivers/unioxx5.c
+@@ -213,7 +213,8 @@ static int unioxx5_insn_config(struct comedi_device *dev, struct comedi_subdevic
+ 		return -1;
+ 	}
+ 
+-	if ((channel_offset = __unioxx5_define_chan_offset(channel)) < 0) {
++	channel_offset = __unioxx5_define_chan_offset(channel);
++	if (channel_offset < 0) {
+ 		printk(KERN_ERR
+ 			"comedi%d: undefined channel %d. channel range is 0 .. 23\n",
+ 			dev->minor, channel);
+@@ -275,8 +276,9 @@ static int __unioxx5_subdev_init(struct comedi_subdevice *subdev, int subdev_iob
+ 		return -EIO;
+ 	}
+ 
+-	if ((usp = (struct unioxx5_subd_priv *) kzalloc(sizeof(*usp),
+-				GFP_KERNEL)) == NULL) {
++	usp = (struct unioxx5_subd_priv *) kzalloc(sizeof(*usp), GFP_KERNEL);
++
++	if (usp == NULL) {
+ 		printk(KERN_ERR "comedi%d: erorr! --> out of memory!\n", minor);
+ 		return -1;
+ 	}
+@@ -336,7 +338,8 @@ static int __unioxx5_digital_write(struct unioxx5_subd_priv *usp, unsigned int *
+ 	int channel_offset, val;
+ 	int mask = 1 << (channel & 0x07);
+ 
+-	if ((channel_offset = __unioxx5_define_chan_offset(channel)) < 0) {
++	channel_offset = __unioxx5_define_chan_offset(channel);
++	if (channel_offset < 0) {
+ 		printk(KERN_ERR
+ 			"comedi%d: undefined channel %d. channel range is 0 .. 23\n",
+ 			minor, channel);
+@@ -362,7 +365,8 @@ static int __unioxx5_digital_read(struct unioxx5_subd_priv *usp, unsigned int *d
+ {
+ 	int channel_offset, mask = 1 << (channel & 0x07);
+ 
+-	if ((channel_offset = __unioxx5_define_chan_offset(channel)) < 0) {
++	channel_offset = __unioxx5_define_chan_offset(channel);
++	if (channel_offset < 0) {
+ 		printk(KERN_ERR
+ 			"comedi%d: undefined channel %d. channel range is 0 .. 23\n",
+ 			minor, channel);

commit 356cdbcb838ebcc234a43ec81621a39231fdcb7a
+Author: Bill Pemberton 
+Date:   Thu Apr 9 16:07:27 2009 -0400
+
+    Staging: Comedi: change space indentation to tabs
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+index 3bbf7d7da63f..24fd81333b83 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+@@ -3,13 +3,13 @@
+ 
+ Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ 
+-        ADDI-DATA GmbH
+-        Dieselstrasse 3
+-        D-77833 Ottersweier
+-        Tel: +19(0)7223/9493-0
+-        Fax: +49(0)7223/9493-92
+-        http://www.addi-data-com
+-        info@addi-data.com
++	ADDI-DATA GmbH
++	Dieselstrasse 3
++	D-77833 Ottersweier
++	Tel: +19(0)7223/9493-0
++	Fax: +49(0)7223/9493-92
++	http://www.addi-data-com
++	info@addi-data.com
+ 
+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+index aad76fb8ea4b..2fb05f392d5f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+@@ -3,13 +3,13 @@
+ 
+ Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ 
+-        ADDI-DATA GmbH
+-        Dieselstrasse 3
+-        D-77833 Ottersweier
+-        Tel: +19(0)7223/9493-0
+-        Fax: +49(0)7223/9493-92
+-        http://www.addi-data-com
+-        info@addi-data.com
++	ADDI-DATA GmbH
++	Dieselstrasse 3
++	D-77833 Ottersweier
++	Tel: +19(0)7223/9493-0
++	Fax: +49(0)7223/9493-92
++	http://www.addi-data-com
++	info@addi-data.com
+ 
+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ 
+@@ -695,15 +695,15 @@ int i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device *dev,
+ |   unsigned char_ b_ModulNbr  CR_AREF(aref)    : Selected module number (0 to 3)|
+ |   unsigned char_ b_PortValue CR_CHAN(chanspec) : Output Value ( 0 To 7 )
+ |                       data[0]           read or write port
+-                        data[1]            if write then indicate ON or OFF
++|                       data[1]            if write then indicate ON or OFF
+ 
+-                        if read : data[1] will return port status.
++|                       if read : data[1] will return port status.
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+ +----------------------------------------------------------------------------+
+ | Return Value      :
+ 
+-                INPUT :
++|                INPUT :
+ 
+ 					  0: No error                                            |
+ |                    -1: The handle parameter of the board is wrong          |
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+index 29ba78f0939d..5041f651091b 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+@@ -3,13 +3,13 @@
+ 
+ Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ 
+-        ADDI-DATA GmbH
+-        Dieselstrasse 3
+-        D-77833 Ottersweier
+-        Tel: +19(0)7223/9493-0
+-        Fax: +49(0)7223/9493-92
+-        http://www.addi-data-com
+-        info@addi-data.com
++	ADDI-DATA GmbH
++	Dieselstrasse 3
++	D-77833 Ottersweier
++	Tel: +19(0)7223/9493-0
++	Fax: +49(0)7223/9493-92
++	http://www.addi-data-com
++	info@addi-data.com
+ 
+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+index b815d0a0e8a5..b7b0a07d5573 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+@@ -3,13 +3,13 @@
+ 
+ Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ 
+-        ADDI-DATA GmbH
+-        Dieselstrasse 3
+-        D-77833 Ottersweier
+-        Tel: +19(0)7223/9493-0
+-        Fax: +49(0)7223/9493-92
+-        http://www.addi-data-com
+-        info@addi-data.com
++	ADDI-DATA GmbH
++	Dieselstrasse 3
++	D-77833 Ottersweier
++	Tel: +19(0)7223/9493-0
++	Fax: +49(0)7223/9493-92
++	http://www.addi-data-com
++	info@addi-data.com
+ 
+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+index 9eb2b8349c22..25b33d5b270e 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+@@ -3,13 +3,13 @@
+ 
+ Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ 
+-        ADDI-DATA GmbH
+-        Dieselstrasse 3
+-        D-77833 Ottersweier
+-        Tel: +19(0)7223/9493-0
+-        Fax: +49(0)7223/9493-92
+-        http://www.addi-data-com
+-        info@addi-data.com
++	ADDI-DATA GmbH
++	Dieselstrasse 3
++	D-77833 Ottersweier
++	Tel: +19(0)7223/9493-0
++	Fax: +49(0)7223/9493-92
++	http://www.addi-data-com
++	info@addi-data.com
+ 
+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+index 5edae81763a0..c1f88cc668a4 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+@@ -3,13 +3,13 @@
+ 
+ Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ 
+-        ADDI-DATA GmbH
+-        Dieselstrasse 3
+-        D-77833 Ottersweier
+-        Tel: +19(0)7223/9493-0
+-        Fax: +49(0)7223/9493-92
+-        http://www.addi-data-com
+-        info@addi-data.com
++	ADDI-DATA GmbH
++	Dieselstrasse 3
++	D-77833 Ottersweier
++	Tel: +19(0)7223/9493-0
++	Fax: +49(0)7223/9493-92
++	http://www.addi-data-com
++	info@addi-data.com
+ 
+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+index 0170d36ac280..da094a413e03 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+@@ -3,13 +3,13 @@
+ 
+ Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ 
+-        ADDI-DATA GmbH
+-        Dieselstrasse 3
+-        D-77833 Ottersweier
+-        Tel: +19(0)7223/9493-0
+-        Fax: +49(0)7223/9493-92
+-        http://www.addi-data-com
+-        info@addi-data.com
++	ADDI-DATA GmbH
++	Dieselstrasse 3
++	D-77833 Ottersweier
++	Tel: +19(0)7223/9493-0
++	Fax: +49(0)7223/9493-92
++	http://www.addi-data-com
++	info@addi-data.com
+ 
+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+index c7680fe3f6c4..854f79ccca2a 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+@@ -3,13 +3,13 @@
+ 
+ Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ 
+-        ADDI-DATA GmbH
+-        Dieselstrasse 3
+-        D-77833 Ottersweier
+-        Tel: +19(0)7223/9493-0
+-        Fax: +49(0)7223/9493-92
+-        http://www.addi-data-com
+-        info@addi-data.com
++	ADDI-DATA GmbH
++	Dieselstrasse 3
++	D-77833 Ottersweier
++	Tel: +19(0)7223/9493-0
++	Fax: +49(0)7223/9493-92
++	http://www.addi-data-com
++	info@addi-data.com
+ 
+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
+index 090084556a95..15d378a465f5 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
+@@ -3,13 +3,13 @@
+ 
+ Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ 
+-        ADDI-DATA GmbH
+-        Dieselstrasse 3
+-        D-77833 Ottersweier
+-        Tel: +19(0)7223/9493-0
+-        Fax: +49(0)7223/9493-92
+-        http://www.addi-data-com
+-        info@addi-data.com
++	ADDI-DATA GmbH
++	Dieselstrasse 3
++	D-77833 Ottersweier
++	Tel: +19(0)7223/9493-0
++	Fax: +49(0)7223/9493-92
++	http://www.addi-data-com
++	info@addi-data.com
+ 
+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+index f9c27efe1dc3..198ef1cd40e9 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+@@ -3,13 +3,13 @@
+ 
+ Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ 
+-        ADDI-DATA GmbH
+-        Dieselstrasse 3
+-        D-77833 Ottersweier
+-        Tel: +19(0)7223/9493-0
+-        Fax: +49(0)7223/9493-92
+-        http://www.addi-data-com
+-        info@addi-data.com
++	ADDI-DATA GmbH
++	Dieselstrasse 3
++	D-77833 Ottersweier
++	Tel: +19(0)7223/9493-0
++	Fax: +49(0)7223/9493-92
++	http://www.addi-data-com
++	info@addi-data.com
+ 
+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ 
+@@ -2576,7 +2576,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 		this_board->pc_DriverName);
+ 
+ 	if ((ret = alloc_private(dev, sizeof(struct addi_private))) < 0) {
+-	  	return -ENOMEM;
++		return -ENOMEM;
+ 	}
+ 
+ 	if (!pci_list_builded) {
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+index 3c9bb3962c5d..162566d5006c 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+@@ -3,13 +3,13 @@
+ 
+ Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ 
+-        ADDI-DATA GmbH
+-        Dieselstrasse 3
+-        D-77833 Ottersweier
+-        Tel: +19(0)7223/9493-0
+-        Fax: +49(0)7223/9493-92
+-        http://www.addi-data-com
+-        info@addi-data.com
++	ADDI-DATA GmbH
++	Dieselstrasse 3
++	D-77833 Ottersweier
++	Tel: +19(0)7223/9493-0
++	Fax: +49(0)7223/9493-92
++	http://www.addi-data-com
++	info@addi-data.com
+ 
+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+index 176bd868a2b4..355a0c8ab41e 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+@@ -3,13 +3,13 @@
+ 
+ Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ 
+-        ADDI-DATA GmbH
+-        Dieselstrasse 3
+-        D-77833 Ottersweier
+-        Tel: +19(0)7223/9493-0
+-        Fax: +49(0)7223/9493-92
+-        http://www.addi-data-com
+-        info@addi-data.com
++	ADDI-DATA GmbH
++	Dieselstrasse 3
++	D-77833 Ottersweier
++	Tel: +19(0)7223/9493-0
++	Fax: +49(0)7223/9493-92
++	http://www.addi-data-com
++	info@addi-data.com
+ 
+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
+index ea4cac504b5d..016721efdbfb 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
+@@ -3,13 +3,13 @@
+ 
+ Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ 
+-        ADDI-DATA GmbH
+-        Dieselstrasse 3
+-        D-77833 Ottersweier
+-        Tel: +19(0)7223/9493-0
+-        Fax: +49(0)7223/9493-92
+-        http://www.addi-data-com
+-        info@addi-data.com
++	ADDI-DATA GmbH
++	Dieselstrasse 3
++	D-77833 Ottersweier
++	Tel: +19(0)7223/9493-0
++	Fax: +49(0)7223/9493-92
++	http://www.addi-data-com
++	info@addi-data.com
+ 
+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ 
+@@ -69,37 +69,37 @@ int i_Flag = 1;
+ |                                                                            |
+ |					  data[0]            : 0 Configure As Timer      |
+ |										   1 Configure As Watchdog   |
+-                              data[1]            : Watchdog number
++|                                         data[1]            : Watchdog number
+ |					  data[2]            : Time base Unit            |
+ |					  data[3]			 : Reload Value			     |
+-                              data[4]            : External Trigger          |
+-                                                   1:Enable
+-                                                   0:Disable
+-                              data[5]            :External Trigger Level
+-                                                  00 Trigger Disabled
+-                                                  01 Trigger Enabled (Low level)
+-                                                  10 Trigger Enabled (High Level)
+-                                                  11 Trigger Enabled (High/Low level)
+-                              data[6]            : External Gate            |
+-                                                   1:Enable
+-                                                   0:Disable
+-                              data[7]            : External Gate level
+-                                                  00 Gate Disabled
+-                                                  01 Gate Enabled (Low level)
+-                                                  10 Gate Enabled (High Level)
+-                              data[8]            :Warning Relay
+-                                                  1: ENABLE
+-                                                  0: DISABLE
+-                              data[9]            :Warning Delay available
+-                              data[10]           :Warning Relay Time unit
+-                              data[11]           :Warning Relay Time Reload value
+-                              data[12]           :Reset Relay
+-                                                  1 : ENABLE
+-                                                  0 : DISABLE
+-                              data[13]           :Interrupt
+-                                                  1 : ENABLE
+-                                                  0 : DISABLE
+-
++|                                         data[4]            : External Trigger          |
++|                                                              1:Enable
++|                                                           0:Disable
++|                              data[5]            :External Trigger Level
++|                                                  00 Trigger Disabled
++|                                                  01 Trigger Enabled (Low level)
++|                                                  10 Trigger Enabled (High Level)
++|                                                  11 Trigger Enabled (High/Low level)
++|                              data[6]            : External Gate            |
++|                                                   1:Enable
++|                                                   0:Disable
++|                              data[7]            : External Gate level
++|                                                  00 Gate Disabled
++|                                                  01 Gate Enabled (Low level)
++|                                                  10 Gate Enabled (High Level)
++|                              data[8]            :Warning Relay
++|                                                  1: ENABLE
++|                                                  0: DISABLE
++|                              data[9]            :Warning Delay available
++|                              data[10]           :Warning Relay Time unit
++|                              data[11]           :Warning Relay Time Reload value
++|                              data[12]           :Reset Relay
++|                                                  1 : ENABLE
++|                                                  0 : DISABLE
++|                              data[13]           :Interrupt
++|                                                  1 : ENABLE
++|                                                  0 : DISABLE
++|
+ |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -381,11 +381,11 @@ int i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device *dev,
+ |     																	 |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	data[0]            : software trigger status
+-              data[1]            : hardware trigger status
+-|     				data[2]            : Software clear status
+-                        data[3]            : Overflow status
+-                     data[4]            : Timer actual value
+-
++|                       data[1]            : hardware trigger status
++|     	  	        data[2]            : Software clear status
++|                       data[3]            : Overflow status
++|                       data[4]            : Timer actual value
++|
+ 
+ +----------------------------------------------------------------------------+
+ | Return Value      : TRUE  : No error occur                                 |
+@@ -398,25 +398,29 @@ int i_APCI035_ReadTimerWatchdog(struct comedi_device *dev, struct comedi_subdevi
+ {
+ 	unsigned int ui_Status = 0;	/*  Status register */
+ 	i_WatchdogNbr = insn->unused[0];
+-	      /******************/
++
++	/******************/
+ 	/* Get the status */
+-	      /******************/
++	/******************/
++
+ 	ui_Status = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 16);
+-      /***********************************/
++
++	/***********************************/
+ 	/* Get the software trigger status */
+-      /***********************************/
++	/***********************************/
++
+ 	data[0] = ((ui_Status >> 1) & 1);
+-      /***********************************/
++	/***********************************/
+ 	/* Get the hardware trigger status */
+-      /***********************************/
++	/***********************************/
+ 	data[1] = ((ui_Status >> 2) & 1);
+-      /*********************************/
++	/*********************************/
+ 	/* Get the software clear status */
+-      /*********************************/
++	/*********************************/
+ 	data[2] = ((ui_Status >> 3) & 1);
+-      /***************************/
++	/***************************/
+ 	/* Get the overflow status */
+-      /***************************/
++	/***************************/
+ 	data[3] = ((ui_Status >> 0) & 1);
+ 	if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
+ 		data[4] = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+index 4df4812e70b8..e9021cd4d341 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+@@ -3,13 +3,13 @@
+ 
+ Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ 
+-        ADDI-DATA GmbH
+-        Dieselstrasse 3
+-        D-77833 Ottersweier
+-        Tel: +19(0)7223/9493-0
+-        Fax: +49(0)7223/9493-92
+-        http://www.addi-data-com
+-        info@addi-data.com
++	ADDI-DATA GmbH
++	Dieselstrasse 3
++	D-77833 Ottersweier
++	Tel: +19(0)7223/9493-0
++	Fax: +49(0)7223/9493-92
++	http://www.addi-data-com
++	info@addi-data.com
+ 
+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+index da0e6dd8a171..bbe813b8119f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+@@ -3,13 +3,13 @@
+ 
+ Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ 
+-        ADDI-DATA GmbH
+-        Dieselstrasse 3
+-        D-77833 Ottersweier
+-        Tel: +19(0)7223/9493-0
+-        Fax: +49(0)7223/9493-92
+-        http://www.addi-data-com
+-        info@addi-data.com
++	ADDI-DATA GmbH
++	Dieselstrasse 3
++	D-77833 Ottersweier
++	Tel: +19(0)7223/9493-0
++	Fax: +49(0)7223/9493-92
++	http://www.addi-data-com
++	info@addi-data.com
+ 
+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ 
+@@ -77,7 +77,7 @@ int i_TimerCounter1Enabled = 0, i_TimerCounter2Enabled =
+ |			  data[0]            :Number of the input port on        |
+ |                                         which the event will take place    |
+ |                                         (1 or 2)
+-                      data[1]            : The event logic for port 1 has    |
++|                      data[1]            : The event logic for port 1 has    |
+ |                                            three possibilities             |
+ |                                        :0  APCI1500_AND       :This logic  |
+ |                                                                links       |
+@@ -508,9 +508,9 @@ int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |		              unsigned int ui_Channel : Channel number to read       |
+ |                     unsigned int *data          : Data Pointer to read status  |
+-                      data[0]                 :0 Start input event
+-                                               1 Stop input event
+-                      data[1]                 :No of port (1 or 2)
++|                      data[0]                 :0 Start input event
++|                                               1 Stop input event
++|                      data[1]                 :No of port (1 or 2)
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -945,9 +945,9 @@ int i_APCI1500_Initialisation(struct comedi_device *dev, struct comedi_subdevice
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     unsigned int ui_NoOfChannels    : No Of Channels To be Read    |
+ |                      unsigned int *data             : Data Pointer
+-                      data[0]                 : 0 Read a single channel
+-                                                1 read a port value
+-                      data[1]                 : port value
++|                      data[0]                 : 0 Read a single channel
++|                                                1 read a port value
++|                      data[1]                 : port value
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--	data[0]    :The read status value
+ +----------------------------------------------------------------------------+
+@@ -1015,21 +1015,21 @@ int i_APCI1500_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_sub
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_ConfigDigitalOutputErrorInterrupt
+-                      (struct comedi_device *dev,struct comedi_subdevice *s struct comedi_insn
+-                      *insn,unsigned int *data)                                  |
++|                      (struct comedi_device *dev,struct comedi_subdevice *s struct comedi_insn
++|                      *insn,unsigned int *data)                                  |
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures the digital output memory and the digital
+-                      output error interrupt                                 |
++|                      output error interrupt                                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev : Driver handle                     |
+ |                     unsigned int *data         : Data Pointer contains         |
+ |                                          configuration parameters as below |
+ |                      struct comedi_subdevice *s,   :pointer to subdevice structure
+-                       struct comedi_insn *insn      :pointer to insn structure                                                                                                                |
++|                       struct comedi_insn *insn      :pointer to insn structure                                                                                                                |
+ |					  data[0]  :1:Memory on                          |
+ |					            0:Memory off                         |
+-                              data[1]  :1 Enable the voltage error interrupt
++|                              data[1]  :1 Enable the voltage error interrupt
+ |							   :0 Disable the voltage error interrupt 		                                                                                                    |
+ |																	 |
+ +----------------------------------------------------------------------------+
+@@ -1215,23 +1215,23 @@ int i_APCI1500_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subde
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_ConfigCounterTimerWatchdog(comedi_device
+-                   *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)|
++|                   *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)|
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Watchdog                                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      struct comedi_insn *insn      :pointer to insn structure      |
++|                      struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data         : Data Pointer to read status                                                       data[0]                : 2     APCI1500_1_8_KHZ
+ |                                              1     APCI1500_3_6_KHZ        |
+ |                                              0     APCI1500_115_KHZ
+-                      data[1]                : 0     Counter1/Timer1
+-                                               1     Counter2/Timer2
+-                                               2     Counter3/Watchdog
+-                      data[2]                : 0     Counter
+-                                               1     Timer/Watchdog
+-                      data[3]                :         This parameter has    |
++|                      data[1]                : 0     Counter1/Timer1
++|                                               1     Counter2/Timer2
++|                                               2     Counter3/Watchdog
++|                      data[2]                : 0     Counter
++|                                               1     Timer/Watchdog
++|                      data[3]                :         This parameter has    |
+ |                                                      two meanings.         |
+ |                                                    - If the counter/timer  |
+ |                                                      is used as a counter  |
+@@ -1243,15 +1243,15 @@ int i_APCI1500_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subde
+ |                                                      the divider factor    |
+ |                                                      for the output is     |
+ |                                                      given.
+-                       data[4]                 : 0    APCI1500_CONTINUOUS
+-                                                 1    APCI1500_SINGLE
+-                       data[5]                 : 0    Software Trigger
+-                                                 1    Hardware Trigger
+-
+-                       data[6]                  :0    Software gate
+-                                                 1    Hardware gate
+-                       data[7]                  :0    Interrupt Disable
+-                                                 1    Interrupt Enable
++|                       data[4]                 : 0    APCI1500_CONTINUOUS
++|                                                 1    APCI1500_SINGLE
++|                       data[5]                 : 0    Software Trigger
++|                                                 1    Hardware Trigger
++|
++|                       data[6]                  :0    Software gate
++|                                                 1    Hardware gate
++|                       data[7]                  :0    Interrupt Disable
++|                                                 1    Interrupt Enable
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -1836,22 +1836,22 @@ int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_StartStopTriggerTimerCounterWatchdog      |
+ |				(struct comedi_device *dev,struct comedi_subdevice *s,
+-                         struct comedi_insn *insn,unsigned int *data);                  |
++|                         struct comedi_insn *insn,unsigned int *data);                  |
+ +----------------------------------------------------------------------------+
+ | Task              : Start / Stop or trigger the timer counter or Watchdog  |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev     : Driver handle                 |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      struct comedi_insn *insn      :pointer to insn structure      |
++|                      struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data         : Data Pointer to read status   |
+-                      data[0]                : 0     Counter1/Timer1
+-                                               1     Counter2/Timer2
+-                                               2     Counter3/Watchdog
+-                      data[1]                : 0     start
+-                                               1     stop
+-                                               2     Trigger
+-                      data[2]                : 0     Counter
+-                                               1     Timer/Watchdog
++|                      data[0]                : 0     Counter1/Timer1
++|                                               1     Counter2/Timer2
++|                                               2     Counter3/Watchdog
++|                      data[1]                : 0     start
++|                                               1     stop
++|                                               2     Trigger
++|                      data[2]                : 0     Counter
++|                                               1     Timer/Watchdog
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -2161,18 +2161,18 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device *dev,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_ReadCounterTimerWatchdog                |
+ |			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+-                    unsigned int *data); 	                                     |
++|                    unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Watchdog                                      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      struct comedi_insn *insn      :pointer to insn structure      |
++|                      struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+-                      data[0]                : 0     Counter1/Timer1
+-                                               1     Counter2/Timer2
+-                                               2     Counter3/Watchdog
+-
++|                      data[0]                : 0     Counter1/Timer1
++|                                               1     Counter2/Timer2
++|                                               2     Counter3/Watchdog
++|
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -2352,13 +2352,13 @@ int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device *dev,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int  i_APCI1500_ReadInterruptMask                      |
+ |			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+-                    unsigned int *data); 	                                     |
++|                    unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read the interrupt mask                                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      struct comedi_insn *insn      :pointer to insn structure      |
++|                      struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ 
+ 
+@@ -2383,15 +2383,15 @@ int i_APCI1500_ReadInterruptMask(struct comedi_device *dev, struct comedi_subdev
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int  i_APCI1500_ConfigureInterrupt                     |
+ |			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+-                    unsigned int *data); 	                                     |
++|                    unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures the interrupt registers                     |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      struct comedi_insn *insn      :pointer to insn structure      |
++|                      struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer                 |
+-
++|
+ 
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
+index dc2a1a9b41c0..38416356628d 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
+@@ -3,13 +3,13 @@
+ 
+ Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ 
+-        ADDI-DATA GmbH
+-        Dieselstrasse 3
+-        D-77833 Ottersweier
+-        Tel: +19(0)7223/9493-0
+-        Fax: +49(0)7223/9493-92
+-        http://www.addi-data-com
+-        info@addi-data.com
++	ADDI-DATA GmbH
++	Dieselstrasse 3
++	D-77833 Ottersweier
++	Tel: +19(0)7223/9493-0
++	Fax: +49(0)7223/9493-92
++	http://www.addi-data-com
++	info@addi-data.com
+ 
+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ 
+@@ -63,7 +63,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |		       struct comedi_subdevice *s,   :pointer to subdevice structure
+-                       struct comedi_insn *insn      :pointer to insn structure     |
++|                       struct comedi_insn *insn      :pointer to insn structure     |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -103,7 +103,7 @@ int i_APCI1516_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdev
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                      struct comedi_subdevice *s,   :pointer to subdevice structure
+-                       struct comedi_insn *insn      :pointer to insn structure     |
++|                       struct comedi_insn *insn      :pointer to insn structure     |
+ |                      unsigned int *data         : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -149,7 +149,7 @@ int i_APCI1516_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_sub
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_ConfigDigitalOutput (struct comedi_device *dev,
+-                    struct comedi_subdevice *s struct comedi_insn *insn,unsigned int *data)    |
++|                    struct comedi_subdevice *s struct comedi_insn *insn,unsigned int *data)    |
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Digital Output Subdevice.               |
+@@ -158,7 +158,7 @@ int i_APCI1516_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_sub
+ |                     unsigned int *data         : Data Pointer contains         |
+ |                                          configuration parameters as below |
+ |                      struct comedi_subdevice *s,   :pointer to subdevice structure
+-                       struct comedi_insn *insn      :pointer to insn structure                                                           |
++|                      struct comedi_insn *insn      :pointer to insn structure                                                           |
+ |					  data[0]  :1:Memory on                          |
+ |					            0:Memory off                         |
+ |										                             |
+@@ -182,13 +182,13 @@ int i_APCI1516_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subd
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_WriteDigitalOutput                      |
+ |			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+-                     unsigned int *data)                                         |
++|                     unsigned int *data)                                         |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes port value  To the selected port                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      struct comedi_insn *insn      :pointer to insn structure      |
++|                     struct comedi_insn *insn      :pointer to insn structure      |
+ |                    unsigned int *data           : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -342,13 +342,13 @@ int i_APCI1516_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_ReadDigitalOutput                       |
+ |			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+-                    unsigned int *data) 	                                     |
++|                    unsigned int *data) 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      struct comedi_insn *insn      :pointer to insn structure      |
++|                     struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -401,14 +401,14 @@ int i_APCI1516_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdev
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_ConfigWatchdog(struct comedi_device *dev,
+-                      struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)  |
++|                      struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)  |
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Watchdog                                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      struct comedi_insn *insn      :pointer to insn structure      |
++|                      struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status                                                     |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+index f90e9605c9bc..871ed763fe2d 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+@@ -3,13 +3,13 @@
+ 
+ Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ 
+-        ADDI-DATA GmbH
+-        Dieselstrasse 3
+-        D-77833 Ottersweier
+-        Tel: +19(0)7223/9493-0
+-        Fax: +49(0)7223/9493-92
+-        http://www.addi-data-com
+-        info@addi-data.com
++	ADDI-DATA GmbH
++	Dieselstrasse 3
++	D-77833 Ottersweier
++	Tel: +19(0)7223/9493-0
++	Fax: +49(0)7223/9493-92
++	http://www.addi-data-com
++	info@addi-data.com
+ 
+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
+index 1261801d0b83..5b7e8e8f28ad 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
+@@ -3,13 +3,13 @@
+ 
+ Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ 
+-        ADDI-DATA GmbH
+-        Dieselstrasse 3
+-        D-77833 Ottersweier
+-        Tel: +19(0)7223/9493-0
+-        Fax: +49(0)7223/9493-92
+-        http://www.addi-data-com
+-        info@addi-data.com
++	ADDI-DATA GmbH
++	Dieselstrasse 3
++	D-77833 Ottersweier
++	Tel: +19(0)7223/9493-0
++	Fax: +49(0)7223/9493-92
++	http://www.addi-data-com
++	info@addi-data.com
+ 
+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
+index 58ff5df037e0..457917f292b7 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
+@@ -3,13 +3,13 @@
+ 
+ Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ 
+-        ADDI-DATA GmbH
+-        Dieselstrasse 3
+-        D-77833 Ottersweier
+-        Tel: +19(0)7223/9493-0
+-        Fax: +49(0)7223/9493-92
+-        http://www.addi-data-com
+-        info@addi-data.com
++	ADDI-DATA GmbH
++	Dieselstrasse 3
++	D-77833 Ottersweier
++	Tel: +19(0)7223/9493-0
++	Fax: +49(0)7223/9493-92
++	http://www.addi-data-com
++	info@addi-data.com
+ 
+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
+index ad91b7b4a5c0..6069894d7f33 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
+@@ -3,13 +3,13 @@
+ 
+ Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ 
+-        ADDI-DATA GmbH
+-        Dieselstrasse 3
+-        D-77833 Ottersweier
+-        Tel: +19(0)7223/9493-0
+-        Fax: +49(0)7223/9493-92
+-        http://www.addi-data-com
+-        info@addi-data.com
++	ADDI-DATA GmbH
++	Dieselstrasse 3
++	D-77833 Ottersweier
++	Tel: +19(0)7223/9493-0
++	Fax: +49(0)7223/9493-92
++	http://www.addi-data-com
++	info@addi-data.com
+ 
+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ 
+@@ -363,14 +363,14 @@ int i_APCI2032_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdev
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2032_ConfigWatchdog(comedi_device
+-                   *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)|
++|                   *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)|
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Watchdog                                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      struct comedi_insn *insn      :pointer to insn structure      |
++|                      struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status                                                                                                             |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -449,13 +449,13 @@ int i_APCI2032_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_s
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2032_ReadWatchdog                            |
+ |			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+-                    unsigned int *data); 	                                     |
++|                    unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Watchdog                                      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      struct comedi_insn *insn      :pointer to insn structure      |
++|                      struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
+index c03192b5d9a0..9846997e8d28 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
+@@ -3,13 +3,13 @@
+ 
+ Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ 
+-        ADDI-DATA GmbH
+-        Dieselstrasse 3
+-        D-77833 Ottersweier
+-        Tel: +19(0)7223/9493-0
+-        Fax: +49(0)7223/9493-92
+-        http://www.addi-data-com
+-        info@addi-data.com
++	ADDI-DATA GmbH
++	Dieselstrasse 3
++	D-77833 Ottersweier
++	Tel: +19(0)7223/9493-0
++	Fax: +49(0)7223/9493-92
++	http://www.addi-data-com
++	info@addi-data.com
+ 
+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ 
+@@ -63,7 +63,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |		       struct comedi_subdevice *s,   :pointer to subdevice structure
+-                       struct comedi_insn *insn      :pointer to insn structure     |
++|                       struct comedi_insn *insn      :pointer to insn structure     |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -101,7 +101,7 @@ int i_APCI2200_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdev
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                      struct comedi_subdevice *s,   :pointer to subdevice structure
+-                       struct comedi_insn *insn      :pointer to insn structure     |
++|                       struct comedi_insn *insn      :pointer to insn structure     |
+ |                      unsigned int *data         : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -147,7 +147,7 @@ int i_APCI2200_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_sub
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_ConfigDigitalOutput (struct comedi_device *dev,
+-                    struct comedi_subdevice *s struct comedi_insn *insn,unsigned int *data)    |
++|                    struct comedi_subdevice *s struct comedi_insn *insn,unsigned int *data)    |
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Digital Output Subdevice.               |
+@@ -156,7 +156,7 @@ int i_APCI2200_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_sub
+ |                     unsigned int *data         : Data Pointer contains         |
+ |                                          configuration parameters as below |
+ |                      struct comedi_subdevice *s,   :pointer to subdevice structure
+-                       struct comedi_insn *insn      :pointer to insn structure                                                           |
++|                       struct comedi_insn *insn      :pointer to insn structure                                                           |
+ |					  data[0]  :1:Memory on                          |
+ |					            0:Memory off                         |
+ |										                             |
+@@ -180,13 +180,13 @@ int i_APCI2200_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subd
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_WriteDigitalOutput                      |
+ |			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+-                     unsigned int *data)                                         |
++|                     unsigned int *data)                                         |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes port value  To the selected port                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      struct comedi_insn *insn      :pointer to insn structure      |
++|                      struct comedi_insn *insn      :pointer to insn structure      |
+ |                    unsigned int *data           : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -337,13 +337,13 @@ int i_APCI2200_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_ReadDigitalOutput                       |
+ |			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+-                    unsigned int *data) 	                                     |
++|                    unsigned int *data) 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      struct comedi_insn *insn      :pointer to insn structure      |
++|                     struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -400,14 +400,14 @@ int i_APCI2200_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdev
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_ConfigWatchdog(struct comedi_device *dev,
+-                      struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)  |
++|                      struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)  |
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Watchdog                                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      struct comedi_insn *insn      :pointer to insn structure      |
++|                      struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status                                                                                                             |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -492,13 +492,13 @@ int i_APCI2200_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_s
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_ReadWatchdog                            |
+ |			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+-                    unsigned int *data); 	                                     |
++|                    unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Watchdog                                      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      struct comedi_insn *insn      :pointer to insn structure      |
++|                      struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+index e4b1c09f0e49..2b9a38f8ab3c 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+@@ -3,13 +3,13 @@
+ 
+ Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ 
+-        ADDI-DATA GmbH
+-        Dieselstrasse 3
+-        D-77833 Ottersweier
+-        Tel: +19(0)7223/9493-0
+-        Fax: +49(0)7223/9493-92
+-        http://www.addi-data-com
+-        info@addi-data.com
++	ADDI-DATA GmbH
++	Dieselstrasse 3
++	D-77833 Ottersweier
++	Tel: +19(0)7223/9493-0
++	Fax: +49(0)7223/9493-92
++	http://www.addi-data-com
++	info@addi-data.com
+ 
+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ 
+@@ -804,9 +804,9 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device *dev,
+ 
+ 	us_TmpValue = (unsigned short) inw(dev->iobase + APCI3120_RD_STATUS);
+ /*** EL241003 : add this section in comment because floats must not be used
+-	 if((us_TmpValue & 0x00B0)==0x00B0)
++	if((us_TmpValue & 0x00B0)==0x00B0)
+ 	 {
+-           f_ConvertValue=(((float)ui_ConvertTiming * 0.002) - 2);
++		f_ConvertValue=(((float)ui_ConvertTiming * 0.002) - 2);
+ 		ui_TimerValue0=(unsigned int)f_ConvertValue;
+ 		if (mode==2)
+ 		{
+@@ -814,7 +814,7 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device *dev,
+ 			ui_TimerValue1  =   (unsigned int) f_DelayValue;
+ 		}
+ 	 }
+-   	 else
++	else
+ 	 {
+ 		f_ConvertValue=(((float)ui_ConvertTiming * 0.0012926) - 1);
+ 		ui_TimerValue0=(unsigned int)f_ConvertValue;
+@@ -2463,9 +2463,9 @@ int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device *dev,
+ |                     struct comedi_subdevice *s									 |
+ |                     struct comedi_insn *insn                                      |
+ |                     unsigned int *data 										 |
+-                      data[0]     Value to be written
+-                      data[1]    :1 Set digital o/p ON
+-                      data[1]     2 Set digital o/p OFF with memory ON
++|                      data[0]     Value to be written
++|                      data[1]    :1 Set digital o/p ON
++|                      data[1]     2 Set digital o/p OFF with memory ON
+ +----------------------------------------------------------------------------+
+ | Return Value      :              					                         |
+ |                    													     |
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+index b6b075007787..1e591a42dd65 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+@@ -3,13 +3,13 @@
+ 
+ Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ 
+-        ADDI-DATA GmbH
+-        Dieselstrasse 3
+-        D-77833 Ottersweier
+-        Tel: +19(0)7223/9493-0
+-        Fax: +49(0)7223/9493-92
+-        http://www.addi-data-com
+-        info@addi-data.com
++	ADDI-DATA GmbH
++	Dieselstrasse 3
++	D-77833 Ottersweier
++	Tel: +19(0)7223/9493-0
++	Fax: +49(0)7223/9493-92
++	http://www.addi-data-com
++	info@addi-data.com
+ 
+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
+index 20460e2382a9..ef21f03fc961 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
+@@ -3,13 +3,13 @@
+ 
+ Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ 
+-        ADDI-DATA GmbH
+-        Dieselstrasse 3
+-        D-77833 Ottersweier
+-        Tel: +19(0)7223/9493-0
+-        Fax: +49(0)7223/9493-92
+-        http://www.addi-data-com
+-        info@addi-data.com
++	ADDI-DATA GmbH
++	Dieselstrasse 3
++	D-77833 Ottersweier
++	Tel: +19(0)7223/9493-0
++	Fax: +49(0)7223/9493-92
++	http://www.addi-data-com
++	info@addi-data.com
+ 
+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+index a908603e7e0e..cac233e83a50 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+@@ -3,13 +3,13 @@
+ 
+ Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ 
+-        ADDI-DATA GmbH
+-        Dieselstrasse 3
+-        D-77833 Ottersweier
+-        Tel: +19(0)7223/9493-0
+-        Fax: +49(0)7223/9493-92
+-        http://www.addi-data-com
+-        info@addi-data.com
++	ADDI-DATA GmbH
++	Dieselstrasse 3
++	D-77833 Ottersweier
++	Tel: +19(0)7223/9493-0
++	Fax: +49(0)7223/9493-92
++	http://www.addi-data-com
++	info@addi-data.com
+ 
+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ 
+diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
+index 23b83500fc78..278d754049a5 100644
+--- a/drivers/staging/comedi/drivers/serial2002.c
++++ b/drivers/staging/comedi/drivers/serial2002.c
+@@ -121,12 +121,12 @@ struct serial_data {
+ static long tty_ioctl(struct file *f, unsigned op, unsigned long param)
+ {
+ #ifdef HAVE_UNLOCKED_IOCTL
+-  	if (f->f_op->unlocked_ioctl) {
++	if (f->f_op->unlocked_ioctl) {
+ 		return f->f_op->unlocked_ioctl(f, op, param);
+ 	}
+ #endif
+ 	if (f->f_op->ioctl) {
+-	  	return f->f_op->ioctl(f->f_dentry->d_inode, f, op, param);
++		return f->f_op->ioctl(f->f_dentry->d_inode, f, op, param);
+ 	}
+ 	return -ENOSYS;
+ }
+@@ -211,7 +211,7 @@ static int tty_read(struct file *f, int timeout)
+ 			/* Device does not support poll, busy wait */
+ 			int retries = 0;
+ 			while (1) {
+-			  	unsigned char ch;
++				unsigned char ch;
+ 
+ 				retries++;
+ 				if (retries >= timeout) {
+@@ -220,7 +220,7 @@ static int tty_read(struct file *f, int timeout)
+ 
+ 				f->f_pos = 0;
+ 				if (f->f_op->read(f, &ch, 1, &f->f_pos) == 1) {
+-				  	result = ch;
++					result = ch;
+ 					break;
+ 				}
+ 				comedi_udelay(100);
+diff --git a/drivers/staging/comedi/range.c b/drivers/staging/comedi/range.c
+index ac200d929f35..d09f0bba0814 100644
+--- a/drivers/staging/comedi/range.c
++++ b/drivers/staging/comedi/range.c
+@@ -32,7 +32,7 @@ const struct comedi_lrange range_unipolar5 = { 1, {UNI_RANGE(5)} };
+ const struct comedi_lrange range_unknown = { 1, {{0, 1000000, UNIT_none}} };
+ 
+ /*
+-   	COMEDI_RANGEINFO
++	COMEDI_RANGEINFO
+ 	range information ioctl
+ 
+ 	arg:

commit 53106ae68acf6eda9593150a25fc44e30fd5ff68
+Author: Bill Pemberton 
+Date:   Thu Apr 9 16:07:21 2009 -0400
+
+    Staging Comedi: fix spacing around parens
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
+index 6e13e450dc73..cabbf090f60b 100644
+--- a/drivers/staging/comedi/drivers.c
++++ b/drivers/staging/comedi/drivers.c
+@@ -198,7 +198,7 @@ int comedi_driver_unregister(struct comedi_driver *driver)
+ 		struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(i);
+ 		struct comedi_device *dev;
+ 
+-		if(dev_file_info == NULL) continue;
++		if (dev_file_info == NULL) continue;
+ 		dev = dev_file_info->device;
+ 
+ 		mutex_lock(&dev->mutex);
+@@ -801,7 +801,7 @@ int comedi_auto_config(struct device *hardware_device, const char *board_name, c
+ 	}
+ 
+ 	minor = comedi_alloc_board_minor(hardware_device);
+-	if(minor < 0) return minor;
++	if (minor < 0) return minor;
+ 
+ 	private_data = kmalloc(sizeof(unsigned), GFP_KERNEL);
+ 	if (private_data == NULL) {
+@@ -824,7 +824,7 @@ int comedi_auto_config(struct device *hardware_device, const char *board_name, c
+ 	mutex_unlock(&dev_file_info->device->mutex);
+ 
+ cleanup:
+-	if(retval < 0)
++	if (retval < 0)
+ 	{
+ 		kfree(private_data);
+ 		comedi_free_board_minor(minor);
+@@ -835,7 +835,7 @@ int comedi_auto_config(struct device *hardware_device, const char *board_name, c
+ void comedi_auto_unconfig(struct device *hardware_device)
+ {
+ 	unsigned *minor = (unsigned *)dev_get_drvdata(hardware_device);
+-	if(minor == NULL) return;
++	if (minor == NULL) return;
+ 
+ 	BUG_ON(*minor >= COMEDI_NUM_BOARD_MINORS);
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+index a35f299f2a22..f9c27efe1dc3 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+@@ -2638,7 +2638,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 		devpriv->i_IobaseReserved = (int) io_addr[3];
+ 		printk("\nioremap begin");
+ 		devpriv->dw_AiBase =
+-			(unsigned long ) ioremap(io_addr[3],
++			(unsigned long) ioremap(io_addr[3],
+ 			this_board->i_IorangeBase3);
+ 		printk("\nioremap end");
+ 	}
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+index 3aa20928e670..3c9bb3962c5d 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+@@ -45,9 +45,9 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+   +----------+-----------+------------------------------------------------+
+ */
+ 
+-#define NVCMD_BEGIN_READ 	(0x7 << 5 )	/*  nvRam begin read command */
+-#define NVCMD_LOAD_LOW   	(0x4 << 5 )	/*  nvRam load low command */
+-#define NVCMD_LOAD_HIGH  	(0x5 << 5 )	/*  nvRam load high command */
++#define NVCMD_BEGIN_READ 	(0x7 << 5)	/*  nvRam begin read command */
++#define NVCMD_LOAD_LOW   	(0x4 << 5)	/*  nvRam load low command */
++#define NVCMD_LOAD_HIGH  	(0x5 << 5)	/*  nvRam load high command */
+ #define EE76_CMD_LEN    	13	/*  bits in instructions */
+ #define EE_READ         	0x0180	/*  01 1000 0000 read instruction */
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
+index ab3a46dc1332..fedfc9c58a88 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
+@@ -161,7 +161,7 @@ static const struct comedi_lrange range_apci3120_ao = { 2, {
+ 
+ #define APCI3120_TIMER2_SELECT_EOS                0xC0	/*  ADDED on 20-6 */
+ #define APCI3120_COUNTER                          3	/*  on 20-6 */
+-#define APCI3120_DISABLE_ALL_TIMER                ( APCI3120_DISABLE_TIMER0 & APCI3120_DISABLE_TIMER1 & APCI3120_DISABLE_TIMER2 )	/*  on 20-6 */
++#define APCI3120_DISABLE_ALL_TIMER                (APCI3120_DISABLE_TIMER0 & APCI3120_DISABLE_TIMER1 & APCI3120_DISABLE_TIMER2)	/*  on 20-6 */
+ 
+ #define MAX_ANALOGINPUT_CHANNELS    32
+ 
+diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
+index a792a5b33e61..aed4a47a7988 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9111.c
++++ b/drivers/staging/comedi/drivers/adl_pci9111.c
+@@ -252,15 +252,15 @@ Configuration options:
+ 
+ #define pci9111_8254_counter_0_set(data) \
+   outb(data & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_0); \
+-  outb( (data >> 8) & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_0)
++  outb((data >> 8) & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_0)
+ 
+ #define pci9111_8254_counter_1_set(data) \
+   outb(data & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_1); \
+-  outb( (data >> 8) & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_1)
++  outb((data >> 8) & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_1)
+ 
+ #define pci9111_8254_counter_2_set(data) \
+   outb(data & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_2); \
+-  outb( (data >> 8) & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_2)
++  outb((data >> 8) & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_2)
+ 
+ /*  Function prototypes */
+ 
+diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c
+index b9359c572485..8fe4c0b0e8f4 100644
+--- a/drivers/staging/comedi/drivers/adq12b.c
++++ b/drivers/staging/comedi/drivers/adq12b.c
+@@ -101,17 +101,17 @@ If you do not specify any options, they will default to
+ 
+ // available ranges through the PGA gains
+ static const struct comedi_lrange range_adq12b_ai_bipolar = { 4, {
+-        BIP_RANGE( 5 ),
+-        BIP_RANGE( 2 ),
+-        BIP_RANGE( 1 ),
+-        BIP_RANGE( 0.5 )
++        BIP_RANGE(5),
++        BIP_RANGE(2),
++        BIP_RANGE(1),
++        BIP_RANGE(0.5)
+ }};
+ 
+ static const struct comedi_lrange range_adq12b_ai_unipolar = { 4, {
+-        UNI_RANGE( 5 ),
+-        UNI_RANGE( 2 ),
+-        UNI_RANGE( 1 ),
+-        UNI_RANGE( 0.5 )
++        UNI_RANGE(5),
++        UNI_RANGE(2),
++        UNI_RANGE(1),
++        UNI_RANGE(0.5)
+ }};
+ 
+ 
+@@ -219,7 +219,7 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+  * Allocate the private structure area.  alloc_private() is a
+  * convenient macro defined in comedidev.h.
+  */
+-        if(alloc_private(dev, sizeof(struct adq12b_private)) < 0)
++        if (alloc_private (dev, sizeof (struct adq12b_private)) < 0)
+           return -ENOMEM;
+ 
+ /* fill in devpriv structure */
+@@ -236,7 +236,7 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+  * Allocate the subdevice structures.  alloc_subdevice() is a
+  * convenient macro defined in comedidev.h.
+  */
+-        if(alloc_subdevices(dev, 3)<0)
++        if (alloc_subdevices (dev, 3)<0)
+            return -ENOMEM;
+ 
+         s = dev->subdevices+0;
+@@ -332,7 +332,7 @@ static int adq12b_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s
+         status = inb(dev->iobase + ADQ12B_ADLOW);
+ 
+         /* convert n samples */
+-        for(n=0; n < insn->n; n++){
++        for (n=0; n < insn->n; n++){
+ 
+           /* wait for end of convertion */
+ 	  i = 0;
+diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
+index 2df5ab0eaeeb..37f1459d152c 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1710.c
++++ b/drivers/staging/comedi/drivers/adv_pci1710.c
+@@ -1347,20 +1347,20 @@ static int pci1710_attach(struct comedi_device *dev, struct comedi_devconfig *it
+ 	board_index = this_board - boardtypes;
+ 	while (NULL != (pcidev = pci_get_device(PCI_VENDOR_ID_ADVANTECH,
+ 		PCI_ANY_ID, pcidev))) {
+-		if(strcmp(this_board->name, DRV_NAME) == 0)
++		if (strcmp (this_board->name, DRV_NAME) == 0)
+ 		{
+-			for(i = 0; i < n_boardtypes; ++i)
++			for (i = 0; i < n_boardtypes; ++i)
+ 			{
+-				if(pcidev->device == boardtypes[i].device_id)
++				if (pcidev->device == boardtypes[i].device_id)
+ 				{
+ 					board_index = i;
+ 					break;
+ 				}
+ 			}
+-			if(i == n_boardtypes) continue;
++			if (i == n_boardtypes) continue;
+ 		}else
+ 		{
+-			if(pcidev->device != boardtypes[board_index].device_id) continue;
++			if (pcidev->device != boardtypes[board_index].device_id) continue;
+ 		}
+ 
+ 		/* Found matching vendor/device. */
+diff --git a/drivers/staging/comedi/drivers/am9513.h b/drivers/staging/comedi/drivers/am9513.h
+index 386226e5b17a..73367d6afffe 100644
+--- a/drivers/staging/comedi/drivers/am9513.h
++++ b/drivers/staging/comedi/drivers/am9513.h
+@@ -51,14 +51,14 @@
+ 		Am9513_output_control(reg);			\
+ 		Am9513_output_data(val>>8);			\
+ 		Am9513_output_data(val&0xff);			\
+-	}while(0)
++	}while (0)
+ 
+ #define Am9513_read_register(reg, val)				\
+ 	do{							\
+ 		Am9513_output_control(reg);			\
+ 		val=Am9513_input_data()<<8;			\
+ 		val|=Am9513_input_data();			\
+-	}while(0)
++	}while (0)
+ 
+ #else /* Am9513_16BITBUS */
+ 
+@@ -66,13 +66,13 @@
+ 	do{							\
+ 		Am9513_output_control(reg);			\
+ 		Am9513_output_data(val);			\
+-	}while(0)
++	}while (0)
+ 
+ #define Am9513_read_register(reg, val)				\
+ 	do{							\
+ 		Am9513_output_control(reg);			\
+ 		val=Am9513_input_data();			\
+-	}while(0)
++	}while (0)
+ 
+ #endif
+ 
+diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
+index c45cbf36f1eb..4efdd1259636 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc236.c
++++ b/drivers/staging/comedi/drivers/amplc_pc236.c
+@@ -77,19 +77,19 @@ unused.
+  * INTCSR values for PCI236.
+  */
+ /* Disable interrupt, also clear any interrupt there */
+-#define PCI236_INTR_DISABLE ( PLX9052_INTCSR_LI1ENAB_DISABLED \
++#define PCI236_INTR_DISABLE (PLX9052_INTCSR_LI1ENAB_DISABLED \
+         | PLX9052_INTCSR_LI1POL_HIGH \
+         | PLX9052_INTCSR_LI2POL_HIGH \
+         | PLX9052_INTCSR_PCIENAB_DISABLED \
+         | PLX9052_INTCSR_LI1SEL_EDGE \
+-        | PLX9052_INTCSR_LI1CLRINT_ASSERTED )
++        | PLX9052_INTCSR_LI1CLRINT_ASSERTED)
+ /* Enable interrupt, also clear any interrupt there. */
+-#define PCI236_INTR_ENABLE ( PLX9052_INTCSR_LI1ENAB_ENABLED \
++#define PCI236_INTR_ENABLE (PLX9052_INTCSR_LI1ENAB_ENABLED \
+         | PLX9052_INTCSR_LI1POL_HIGH \
+         | PLX9052_INTCSR_LI2POL_HIGH \
+         | PLX9052_INTCSR_PCIENAB_ENABLED \
+         | PLX9052_INTCSR_LI1SEL_EDGE \
+-        | PLX9052_INTCSR_LI1CLRINT_ASSERTED )
++        | PLX9052_INTCSR_LI1CLRINT_ASSERTED)
+ 
+ /*
+  * Board descriptions for Amplicon PC36AT and PCI236.
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
+index ba465c432402..425c0f296455 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
+@@ -98,7 +98,7 @@ known. If you have such a board, please file a bug report at
+ /* #define PCIDAS64_DEBUG         enable debugging code */
+ 
+ #ifdef PCIDAS64_DEBUG
+-#define DEBUG_PRINT(format, args...)  rt_printk(format , ## args )
++#define DEBUG_PRINT(format, args...)  rt_printk(format , ## args)
+ #else
+ #define DEBUG_PRINT(format, args...)
+ #endif
+diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
+index 643af376087b..66328353fdaa 100644
+--- a/drivers/staging/comedi/drivers/dt282x.c
++++ b/drivers/staging/comedi/drivers/dt282x.c
+@@ -387,12 +387,12 @@ struct dt282x_private {
+ #define wait_for(a, b)	 				\
+ 	do{						\
+ 		int _i;					\
+-		for(_i=0;_istart_arg = 0;
+ 		err++;
+ 	}
+-	if (cmd->scan_begin_arg < 5000 /* XXX unknown */ ) {
++	if (cmd->scan_begin_arg < 5000 /* XXX unknown */) {
+ 		cmd->scan_begin_arg = 5000;
+ 		err++;
+ 	}
+@@ -1302,7 +1302,7 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 
+ 		irq = probe_irq_off(irqs);
+ 		restore_flags(flags);
+-		if (0 /* error */ ) {
++		if (0 /* error */) {
+ 			printk(" error probing irq (bad)");
+ 		}
+ 	}
+diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
+index 48491c09e7f2..d25b4c8aeaed 100644
+--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
++++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
+@@ -66,7 +66,7 @@ static int dio_config_block_size(struct comedi_device * dev, unsigned int * data
+ /* #define HPDI_DEBUG      enable debugging code */
+ 
+ #ifdef HPDI_DEBUG
+-#define DEBUG_PRINT(format, args...)  rt_printk(format , ## args )
++#define DEBUG_PRINT(format, args...)  rt_printk(format , ## args)
+ #else
+ #define DEBUG_PRINT(format, args...)
+ #endif
+diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c
+index bd7cb4406e14..a00ad1b63ed5 100644
+--- a/drivers/staging/comedi/drivers/mpc624.c
++++ b/drivers/staging/comedi/drivers/mpc624.c
+@@ -110,13 +110,13 @@ Configuration Options:
+  */
+ 
+ #define MPC624_SPEED_3_52_kHz   (MPC624_OSR4                                           | MPC624_OSR0)
+-#define MPC624_SPEED_1_76_kHz   (MPC624_OSR4                             | MPC624_OSR1              )
++#define MPC624_SPEED_1_76_kHz   (MPC624_OSR4                             | MPC624_OSR1)
+ #define MPC624_SPEED_880_Hz     (MPC624_OSR4                             | MPC624_OSR1 | MPC624_OSR0)
+-#define MPC624_SPEED_440_Hz     (MPC624_OSR4               | MPC624_OSR2                            )
++#define MPC624_SPEED_440_Hz     (MPC624_OSR4               | MPC624_OSR2)
+ #define MPC624_SPEED_220_Hz     (MPC624_OSR4               | MPC624_OSR2               | MPC624_OSR0)
+-#define MPC624_SPEED_110_Hz     (MPC624_OSR4               | MPC624_OSR2 | MPC624_OSR1              )
++#define MPC624_SPEED_110_Hz     (MPC624_OSR4               | MPC624_OSR2 | MPC624_OSR1)
+ #define MPC624_SPEED_55_Hz      (MPC624_OSR4               | MPC624_OSR2 | MPC624_OSR1 | MPC624_OSR0)
+-#define MPC624_SPEED_27_5_Hz    (MPC624_OSR4 | MPC624_OSR3                                          )
++#define MPC624_SPEED_27_5_Hz    (MPC624_OSR4 | MPC624_OSR3)
+ #define MPC624_SPEED_13_75_Hz   (MPC624_OSR4 | MPC624_OSR3                             | MPC624_OSR0)
+ #define MPC624_SPEED_6_875_Hz   (MPC624_OSR4 | MPC624_OSR3 | MPC624_OSR2 | MPC624_OSR1 | MPC624_OSR0)
+ /* ---------------------------------------------------------------------------- */
+diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
+index d4a6cf3dde67..b11f134e8c70 100644
+--- a/drivers/staging/comedi/drivers/ni_660x.c
++++ b/drivers/staging/comedi/drivers/ni_660x.c
+@@ -1161,7 +1161,7 @@ static void init_tio_chip(struct comedi_device *dev, int chipset)
+ 	ni_660x_write_register(dev, chipset,
+ 		private(dev)->dma_configuration_soft_copies[chipset],
+ 		DMAConfigRegister);
+-	for(i = 0; i < NUM_PFI_CHANNELS; ++i)
++	for (i = 0; i < NUM_PFI_CHANNELS; ++i)
+ 	{
+ 		ni_660x_write_register(dev, chipset, 0, IOConfigReg(i));
+ 	}
+@@ -1237,8 +1237,8 @@ static void ni_660x_select_pfi_output(struct comedi_device *dev, unsigned pfi_ch
+ 	unsigned active_bits;
+ 	unsigned idle_bits;
+ 
+-	if(board(dev)->n_chips > 1) {
+-		if(output_select == pfi_output_select_counter &&
++	if (board (dev)->n_chips > 1) {
++		if (output_select == pfi_output_select_counter &&
+ 			pfi_channel >= counter_4_7_first_pfi &&
+ 			pfi_channel <= counter_4_7_last_pfi) {
+ 			active_chipset = 1;
+@@ -1249,7 +1249,7 @@ static void ni_660x_select_pfi_output(struct comedi_device *dev, unsigned pfi_ch
+ 		}
+ 	}
+ 
+-	if(idle_chipset != active_chipset) {
++	if (idle_chipset != active_chipset) {
+ 		idle_bits = ni_660x_read_register(dev, idle_chipset, IOConfigReg(pfi_channel));
+ 		idle_bits &= ~pfi_output_select_mask(pfi_channel);
+ 		idle_bits |= pfi_output_select_bits(pfi_channel, pfi_output_select_high_Z);
+diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
+index 442bfe717a13..9fafe0c234d9 100644
+--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
++++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
+@@ -417,10 +417,10 @@ static int atmio16d_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s
+ 	} else if (cmd->convert_arg < 655360000) {
+ 		base_clock = CLOCK_100_KHZ;
+ 		timer = cmd->convert_arg / 10000;
+-	} else if (cmd->convert_arg <= 0xffffffff /* 6553600000 */ ) {
++	} else if (cmd->convert_arg <= 0xffffffff /* 6553600000 */) {
+ 		base_clock = CLOCK_10_KHZ;
+ 		timer = cmd->convert_arg / 100000;
+-	} else if (cmd->convert_arg <= 0xffffffff /* 65536000000 */ ) {
++	} else if (cmd->convert_arg <= 0xffffffff /* 65536000000 */) {
+ 		base_clock = CLOCK_1_KHZ;
+ 		timer = cmd->convert_arg / 1000000;
+ 	}
+@@ -483,10 +483,10 @@ static int atmio16d_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s
+ 		} else if (cmd->scan_begin_arg < 655360000) {
+ 			base_clock = CLOCK_100_KHZ;
+ 			timer = cmd->scan_begin_arg / 10000;
+-		} else if (cmd->scan_begin_arg < 0xffffffff /* 6553600000 */ ) {
++		} else if (cmd->scan_begin_arg < 0xffffffff /* 6553600000 */) {
+ 			base_clock = CLOCK_10_KHZ;
+ 			timer = cmd->scan_begin_arg / 100000;
+-		} else if (cmd->scan_begin_arg < 0xffffffff /* 65536000000 */ ) {
++		} else if (cmd->scan_begin_arg < 0xffffffff /* 65536000000 */) {
+ 			base_clock = CLOCK_1_KHZ;
+ 			timer = cmd->scan_begin_arg / 1000000;
+ 		}
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index 5c165cac2348..7b0030e853c4 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -1554,7 +1554,7 @@ static int ni_ai_setup_MITE_dma(struct comedi_device *dev)
+ 	comedi_buf_write_alloc(s->async, s->async->prealloc_bufsz);
+ 
+ 	comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
+-	if(devpriv->ai_mite_chan == NULL)
++	if (devpriv->ai_mite_chan == NULL)
+ 	{
+ 		comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
+ 		return -EIO;
+@@ -2810,7 +2810,7 @@ static int ni_m_series_ao_config_chanlist(struct comedi_device *dev,
+ 	int i;
+ 	int invert = 0;
+ 
+-	if(timed) {
++	if (timed) {
+ 		for (i = 0; i < boardtype.n_aochan; ++i) {
+ 			devpriv->ao_conf[i] &= ~MSeries_AO_Update_Timed_Bit;
+ 			ni_writeb(devpriv->ao_conf[i], M_Offset_AO_Config_Bank(i));
+@@ -2970,11 +2970,11 @@ static int ni_ao_insn_config(struct comedi_device *dev, struct comedi_subdevice
+ {
+ 	switch (data[0]) {
+ 	case INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE:
+-		switch(data[1])
++		switch (data[1])
+ 		{
+ 		case COMEDI_OUTPUT:
+ 			data[2] = 1 + boardtype.ao_fifo_depth * sizeof(short);
+-			if(devpriv->mite) data[2] += devpriv->mite->fifo_size;
++			if (devpriv->mite) data[2] += devpriv->mite->fifo_size;
+ 			break;
+ 		case COMEDI_INPUT:
+ 			data[2] = 0;
+@@ -3139,7 +3139,7 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ 	devpriv->stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register);
+ 	switch (cmd->stop_src) {
+ 	case TRIG_COUNT:
+-		if(boardtype.reg_type & ni_reg_m_series_mask)
++		if (boardtype.reg_type & ni_reg_m_series_mask)
+ 		{
+ 			/*  this is how the NI example code does it for m-series boards, verified correct with 6259 */
+ 			devpriv->stc_writel(dev, cmd->stop_arg - 1, AO_UC_Load_A_Register);
+@@ -3422,7 +3422,7 @@ static int ni_ao_reset(struct comedi_device *dev, struct comedi_subdevice *s)
+ 	if (boardtype.reg_type & ni_reg_6xxx_mask) {
+ 		unsigned immediate_bits = 0;
+ 		unsigned i;
+-		for(i = 0; i < s->n_chan; ++i)
++		for (i = 0; i < s->n_chan; ++i)
+ 		{
+ 			immediate_bits |= 1 << i;
+ 		}
+diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h
+index a580cf351bd3..55c8a1d66865 100644
+--- a/drivers/staging/comedi/drivers/ni_stc.h
++++ b/drivers/staging/comedi/drivers/ni_stc.h
+@@ -262,7 +262,7 @@ enum Joint_Status_2_Bits {
+ #define AO_Trigger_Once				_bit0
+ 
+ #define AO_Mode_2_Register		39
+-#define AO_FIFO_Mode_Mask ( 0x3 << 14 )
++#define AO_FIFO_Mode_Mask (0x3 << 14)
+ enum AO_FIFO_Mode_Bits {
+ 	AO_FIFO_Mode_HF_to_F = (3 << 14),
+ 	AO_FIFO_Mode_F = (2 << 14),
+diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c
+index 328be7bd5014..f2a959654d6c 100644
+--- a/drivers/staging/comedi/drivers/pcmda12.c
++++ b/drivers/staging/comedi/drivers/pcmda12.c
+@@ -55,7 +55,7 @@ Configuration Options:
+ 
+ #include 		/* for PCI devices */
+ 
+-#define MIN(a, b) ( ((a) < (b)) ? (a) : (b) )
++#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+ #define SDEV_NO ((int)(s - dev->subdevices))
+ #define CHANS 8
+ #define IOSIZE 16
+diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
+index 0dc51f62bac5..849fa4fa4ced 100644
+--- a/drivers/staging/comedi/drivers/pcmmio.c
++++ b/drivers/staging/comedi/drivers/pcmmio.c
+@@ -76,7 +76,7 @@ Configuration Options:
+ #include "../comedidev.h"
+ #include 		/* for PCI devices */
+ 
+-#define MIN(a, b) ( ((a) < (b)) ? (a) : (b) )
++#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+ 
+ /* This stuff is all from pcmuio.c -- it refers to the DIO subdevices only */
+ #define CHANS_PER_PORT   8
+diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
+index 54971a1cb908..7e442dbd2c19 100644
+--- a/drivers/staging/comedi/drivers/pcmuio.c
++++ b/drivers/staging/comedi/drivers/pcmuio.c
+@@ -79,7 +79,7 @@ Configuration Options:
+ 
+ #include 		/* for PCI devices */
+ 
+-#define MIN(a, b) ( ((a) < (b)) ? (a) : (b) )
++#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+ #define CHANS_PER_PORT   8
+ #define PORTS_PER_ASIC   6
+ #define INTR_PORTS_PER_ASIC   3
+diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
+index 700090dc2a88..83af347934be 100644
+--- a/drivers/staging/comedi/drivers/rtd520.c
++++ b/drivers/staging/comedi/drivers/rtd520.c
+@@ -757,15 +757,15 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 				continue;
+ 			}
+ 		}
+-		for(i = 0; i < sizeof(rtd520Boards) / sizeof(rtd520Boards[0]); ++i)
++		for (i = 0; i < sizeof (rtd520Boards) / sizeof (rtd520Boards[0]); ++i)
+ 		{
+-			if(pcidev->device == rtd520Boards[i].device_id)
++			if (pcidev->device == rtd520Boards[i].device_id)
+ 			{
+ 				dev->board_ptr = &rtd520Boards[i];
+ 				break;
+ 			}
+ 		}
+-		if(dev->board_ptr) break;	/* found one */
++		if (dev->board_ptr) break;	/* found one */
+ 	}
+ 	if (!pcidev) {
+ 		if (it->options[0] && it->options[1]) {
+@@ -931,7 +931,7 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	printk("( irq=%u )", dev->irq);
+ 
+ 	ret = rtd520_probe_fifo_depth(dev);
+-	if(ret < 0) {
++	if (ret < 0) {
+ 		return ret;
+ 	}
+ 	devpriv->fifoLen = ret;
+@@ -1226,18 +1226,18 @@ static int rtd520_probe_fifo_depth(struct comedi_device *dev)
+ 		RtdAdcStart(dev);
+ 		comedi_udelay(1);
+ 		fifo_status = RtdFifoStatus(dev);
+-		if((fifo_status & FS_ADC_HEMPTY) == 0) {
++		if ((fifo_status & FS_ADC_HEMPTY) == 0) {
+ 			fifo_size = 2 * i;
+ 			break;
+ 		}
+ 	}
+-	if(i == limit)
++	if (i == limit)
+ 	{
+ 		rt_printk("\ncomedi: %s: failed to probe fifo size.\n", DRV_NAME);
+ 		return -EIO;
+ 	}
+ 	RtdAdcClearFifo(dev);
+-	if(fifo_size != 0x400 && fifo_size != 0x2000)
++	if (fifo_size != 0x400 && fifo_size != 0x2000)
+ 	{
+ 		rt_printk("\ncomedi: %s: unexpected fifo size of %i, expected 1024 or 8192.\n",
+ 			DRV_NAME, fifo_size);
+diff --git a/drivers/staging/comedi/rt_pend_tq.c b/drivers/staging/comedi/rt_pend_tq.c
+index 5d2eead99f26..f6e083d553d9 100644
+--- a/drivers/staging/comedi/rt_pend_tq.c
++++ b/drivers/staging/comedi/rt_pend_tq.c
+@@ -28,8 +28,8 @@ int rt_pend_tq_irq = 0;
+ DEFINE_SPINLOCK(rt_pend_tq_lock);
+ 
+ /* WARNING: following code not checked against race conditions yet. */
+-#define INC_CIRCULAR_PTR(ptr, begin, size) do {if(++(ptr)>=(begin)+(size)) (ptr)=(begin); } while(0)
+-#define DEC_CIRCULAR_PTR(ptr, begin, size) do {if(--(ptr)<(begin)) (ptr)=(begin)+(size)-1; } while(0)
++#define INC_CIRCULAR_PTR (ptr, begin, size) do {if (++ (ptr)>= (begin)+ (size)) (ptr)= (begin); } while (0)
++#define DEC_CIRCULAR_PTR (ptr, begin, size) do {if (-- (ptr)< (begin)) (ptr)= (begin)+ (size)-1; } while (0)
+ 
+ int rt_pend_call(void (*func) (int arg1, void *arg2), int arg1, void *arg2)
+ {

commit f7cbd7aad063b2a4b7aff6a743b2b00015ce3c3e
+Author: Bill Pemberton 
+Date:   Thu Apr 9 16:07:16 2009 -0400
+
+    Staging: comedi: Add spaces after commas
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
+index ae5c8552f117..a792a5b33e61 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9111.c
++++ b/drivers/staging/comedi/drivers/adl_pci9111.c
+@@ -187,24 +187,24 @@ Configuration options:
+   (inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK)&0x0F)
+ 
+ #define pci9111_trigger_and_autoscan_set(flags) \
+-  outb(flags,PCI9111_IO_BASE+PCI9111_REGISTER_TRIGGER_MODE_CONTROL)
++  outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_TRIGGER_MODE_CONTROL)
+ 
+ #define pci9111_interrupt_and_fifo_get() \
+   ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK) >> 4) &0x03)
+ 
+ #define pci9111_interrupt_and_fifo_set(flags) \
+-  outb(flags,PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL)
++  outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL)
+ 
+ #define pci9111_interrupt_clear() \
+-  outb(0,PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CLEAR)
++  outb(0, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CLEAR)
+ 
+ #define pci9111_software_trigger() \
+-  outb(0,PCI9111_IO_BASE+PCI9111_REGISTER_SOFTWARE_TRIGGER)
++  outb(0, PCI9111_IO_BASE+PCI9111_REGISTER_SOFTWARE_TRIGGER)
+ 
+ #define pci9111_fifo_reset() \
+-  outb(PCI9111_FFEN_SET_FIFO_ENABLE,PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \
+-  outb(PCI9111_FFEN_SET_FIFO_DISABLE,PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \
+-  outb(PCI9111_FFEN_SET_FIFO_ENABLE,PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL)
++  outb(PCI9111_FFEN_SET_FIFO_ENABLE, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \
++  outb(PCI9111_FFEN_SET_FIFO_DISABLE, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \
++  outb(PCI9111_FFEN_SET_FIFO_ENABLE, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL)
+ 
+ #define pci9111_is_fifo_full() \
+   ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
+@@ -219,13 +219,13 @@ Configuration options:
+     PCI9111_FIFO_EMPTY_MASK)==0)
+ 
+ #define pci9111_ai_channel_set(channel) \
+-  outb((channel)&PCI9111_CHANNEL_MASK,PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_CONTROL)
++  outb((channel)&PCI9111_CHANNEL_MASK, PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_CONTROL)
+ 
+ #define pci9111_ai_channel_get() \
+   inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_READBACK)&PCI9111_CHANNEL_MASK
+ 
+ #define pci9111_ai_range_set(range) \
+-  outb((range)&PCI9111_RANGE_MASK,PCI9111_IO_BASE+PCI9111_REGISTER_INPUT_SIGNAL_RANGE)
++  outb((range)&PCI9111_RANGE_MASK, PCI9111_IO_BASE+PCI9111_REGISTER_INPUT_SIGNAL_RANGE)
+ 
+ #define pci9111_ai_range_get() \
+   inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)&PCI9111_RANGE_MASK
+@@ -239,16 +239,16 @@ Configuration options:
+   ^ PCI9111_HR_AI_RESOLUTION_2_CMP_BIT
+ 
+ #define pci9111_ao_set_data(data) \
+-  outw(data&PCI9111_AO_RESOLUTION_MASK,PCI9111_IO_BASE+PCI9111_REGISTER_DA_OUTPUT)
++  outw(data&PCI9111_AO_RESOLUTION_MASK, PCI9111_IO_BASE+PCI9111_REGISTER_DA_OUTPUT)
+ 
+ #define pci9111_di_get_bits() \
+   inw(PCI9111_IO_BASE+PCI9111_REGISTER_DIGITAL_IO)
+ 
+ #define pci9111_do_set_bits(bits) \
+-  outw(bits,PCI9111_IO_BASE+PCI9111_REGISTER_DIGITAL_IO)
++  outw(bits, PCI9111_IO_BASE+PCI9111_REGISTER_DIGITAL_IO)
+ 
+ #define pci9111_8254_control_set(flags) \
+-  outb(flags,PCI9111_IO_BASE+PCI9111_REGISTER_8254_CONTROL)
++  outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_8254_CONTROL)
+ 
+ #define pci9111_8254_counter_0_set(data) \
+   outb(data & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_0); \
+@@ -536,7 +536,7 @@ static int pci9111_ai_cancel(struct comedi_device *dev, struct comedi_subdevice
+ 
+ /*  Test analog input command */
+ 
+-#define pci9111_check_trigger_src(src,flags) \
++#define pci9111_check_trigger_src(src, flags) \
+   tmp = src; \
+   src &= flags; \
+   if (!src || tmp != src) error++
+diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c
+index 92f62854d6dc..b9359c572485 100644
+--- a/drivers/staging/comedi/drivers/adq12b.c
++++ b/drivers/staging/comedi/drivers/adq12b.c
+@@ -162,7 +162,7 @@ struct adq12b_private {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int adq12b_attach(struct comedi_device *dev,struct comedi_devconfig *it);
++static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int adq12b_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_adq12b={
+         driver_name:    "adq12b",
+@@ -174,9 +174,9 @@ static struct comedi_driver driver_adq12b={
+         num_names:      sizeof(adq12b_boards) / sizeof(struct adq12b_board),
+ };
+ 
+-static int adq12b_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data);
+-static int adq12b_di_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data);
+-static int adq12b_do_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data);
++static int adq12b_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
++static int adq12b_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
++static int adq12b_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * Attach is called by the Comedi core to configure the driver
+@@ -184,7 +184,7 @@ static int adq12b_do_insn_bits(struct comedi_device *dev,struct comedi_subdevice
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int adq12b_attach(struct comedi_device *dev,struct comedi_devconfig *it)
++static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+         struct comedi_subdevice *s;
+         unsigned long iobase;
+@@ -194,7 +194,7 @@ static int adq12b_attach(struct comedi_device *dev,struct comedi_devconfig *it)
+         unipolar = it->options[1];
+         differential = it->options[2];
+ 
+-        printk("comedi%d: adq12b called with options base=0x%03lx, %s and %s\n",dev->minor, iobase, (unipolar==1)?"unipolar":"bipolar", (differential==1)?"differential":"single-ended");
++        printk("comedi%d: adq12b called with options base=0x%03lx, %s and %s\n", dev->minor, iobase, (unipolar==1)?"unipolar":"bipolar", (differential==1) ? "differential" : "single-ended");
+ 
+         /* if no address was specified, try the default 0x300 */
+         if (iobase == 0) {
+@@ -304,7 +304,7 @@ static int adq12b_detach(struct comedi_device *dev)
+ 
+         kfree(devpriv);
+ 
+-        printk("comedi%d: adq12b: removed\n",dev->minor);
++        printk("comedi%d: adq12b: removed\n", dev->minor);
+ 
+         return 0;
+ }
+@@ -314,7 +314,7 @@ static int adq12b_detach(struct comedi_device *dev)
+  * mode.
+  */
+ 
+-static int adq12b_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)
++static int adq12b_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+         int n, i;
+         int range, channel;
+@@ -357,7 +357,7 @@ static int adq12b_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,
+ }
+ 
+ 
+-static int adq12b_di_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, 	struct comedi_insn *insn,unsigned int *data)
++static int adq12b_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, 	struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+         /* only bits 0-4 have information about digital inputs */
+@@ -367,7 +367,7 @@ static int adq12b_di_insn_bits(struct comedi_device *dev,struct comedi_subdevice
+ }
+ 
+ 
+-static int adq12b_do_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, 	struct comedi_insn *insn,unsigned int *data)
++static int adq12b_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, 	struct comedi_insn *insn, unsigned int *data)
+ {
+         int channel;
+ 
+diff --git a/drivers/staging/comedi/drivers/am9513.h b/drivers/staging/comedi/drivers/am9513.h
+index f533cf1658cf..386226e5b17a 100644
+--- a/drivers/staging/comedi/drivers/am9513.h
++++ b/drivers/staging/comedi/drivers/am9513.h
+@@ -46,14 +46,14 @@
+ 
+ #ifdef Am9513_8BITBUS
+ 
+-#define Am9513_write_register(reg,val)				\
++#define Am9513_write_register(reg, val)				\
+ 	do{							\
+ 		Am9513_output_control(reg);			\
+ 		Am9513_output_data(val>>8);			\
+ 		Am9513_output_data(val&0xff);			\
+ 	}while(0)
+ 
+-#define Am9513_read_register(reg,val)				\
++#define Am9513_read_register(reg, val)				\
+ 	do{							\
+ 		Am9513_output_control(reg);			\
+ 		val=Am9513_input_data()<<8;			\
+@@ -62,13 +62,13 @@
+ 
+ #else /* Am9513_16BITBUS */
+ 
+-#define Am9513_write_register(reg,val)				\
++#define Am9513_write_register(reg, val)				\
+ 	do{							\
+ 		Am9513_output_control(reg);			\
+ 		Am9513_output_data(val);			\
+ 	}while(0)
+ 
+-#define Am9513_read_register(reg,val)				\
++#define Am9513_read_register(reg, val)				\
+ 	do{							\
+ 		Am9513_output_control(reg);			\
+ 		val=Am9513_input_data();			\
+diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c
+index 23263ed57532..abd20dfec08c 100644
+--- a/drivers/staging/comedi/drivers/c6xdigio.c
++++ b/drivers/staging/comedi/drivers/c6xdigio.c
+@@ -415,9 +415,9 @@ static void board_init(struct comedi_device *dev)
+ 
+ static const struct pnp_device_id c6xdigio_pnp_tbl[] = {
+ 	/* Standard LPT Printer Port */
+-	{.id = "PNP0400",.driver_data = 0},
++	{.id = "PNP0400", .driver_data = 0},
+ 	/* ECP Printer Port */
+-	{.id = "PNP0401",.driver_data = 0},
++	{.id = "PNP0401", .driver_data = 0},
+ 	{}
+ };
+ 
+diff --git a/drivers/staging/comedi/drivers/comedi_rt_timer.c b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+index ba1f485f3059..784b2e40f711 100644
+--- a/drivers/staging/comedi/drivers/comedi_rt_timer.c
++++ b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+@@ -70,11 +70,11 @@ Configuration options:
+ #define RTLINUX_VERSION_CODE 0
+ #endif
+ #ifndef RTLINUX_VERSION
+-#define RTLINUX_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
++#define RTLINUX_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
+ #endif
+ 
+ /* begin hack to workaround broken HRT_TO_8254() function on rtlinux */
+-#if RTLINUX_VERSION_CODE <= RTLINUX_VERSION(3,0,100)
++#if RTLINUX_VERSION_CODE <= RTLINUX_VERSION(3, 0, 100)
+ /* this function sole purpose is to divide a long long by 838 */
+ static inline RTIME nano2count(long long ns)
+ {
+@@ -97,8 +97,8 @@ static inline RTIME nano2count(long long ns)
+ #define rt_task_wait_period() rt_task_wait()
+ #define rt_pend_linux_srq(irq) rtl_global_pend_irq(irq)
+ #define rt_free_srq(irq) rtl_free_soft_irq(irq)
+-#define rt_request_srq(x,y,z) rtl_get_soft_irq(y,"timer")
+-#define rt_task_init(a,b,c,d,e,f,g) rt_task_init(a,b,c,d,(e)+1)
++#define rt_request_srq(x, y, z) rtl_get_soft_irq(y, "timer")
++#define rt_task_init(a, b, c, d, e, f, g) rt_task_init(a, b, c, d, (e)+1)
+ #define rt_task_resume(x) rt_task_wakeup(x)
+ #define rt_set_oneshot_mode()
+ #define start_rt_timer(x)
+@@ -126,7 +126,7 @@ static inline RTIME nano2count(long long ns)
+ #define test3	0
+ #endif
+ 
+-#if RTAI_VERSION_CODE < RTAI_MANGLE_VERSION(3,3,0)
++#if RTAI_VERSION_CODE < RTAI_MANGLE_VERSION(3, 3, 0)
+ #define comedi_rt_task_context_t	int
+ #else
+ #define comedi_rt_task_context_t	long
+diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
+index de6a96708140..a8c0603d0d95 100644
+--- a/drivers/staging/comedi/drivers/dmm32at.c
++++ b/drivers/staging/comedi/drivers/dmm32at.c
+@@ -114,8 +114,8 @@ Configuration Options:
+ #define DMM32AT_DIOC 0x0e
+ #define DMM32AT_DIOCONF 0x0f
+ 
+-#define dmm_inb(cdev,reg) inb((cdev->iobase)+reg)
+-#define dmm_outb(cdev,reg,valu) outb(valu,(cdev->iobase)+reg)
++#define dmm_inb(cdev, reg) inb((cdev->iobase)+reg)
++#define dmm_outb(cdev, reg, valu) outb(valu, (cdev->iobase)+reg)
+ 
+ /* Board register values. */
+ 
+diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
+index 3174c36573e2..643af376087b 100644
+--- a/drivers/staging/comedi/drivers/dt282x.c
++++ b/drivers/staging/comedi/drivers/dt282x.c
+@@ -374,17 +374,17 @@ struct dt282x_private {
+  *    Some useless abstractions
+  */
+ #define chan_to_DAC(a)	((a)&1)
+-#define update_dacsr(a)	outw(devpriv->dacsr|(a),dev->iobase+DT2821_DACSR)
+-#define update_adcsr(a)	outw(devpriv->adcsr|(a),dev->iobase+DT2821_ADCSR)
++#define update_dacsr(a)	outw(devpriv->dacsr|(a), dev->iobase+DT2821_DACSR)
++#define update_adcsr(a)	outw(devpriv->adcsr|(a), dev->iobase+DT2821_ADCSR)
+ #define mux_busy() (inw(dev->iobase+DT2821_ADCSR)&DT2821_MUXBUSY)
+ #define ad_done() (inw(dev->iobase+DT2821_ADCSR)&DT2821_ADDONE)
+-#define update_supcsr(a)	outw(devpriv->supcsr|(a),dev->iobase+DT2821_SUPCSR)
++#define update_supcsr(a)	outw(devpriv->supcsr|(a), dev->iobase+DT2821_SUPCSR)
+ 
+ /*
+  *    danger! macro abuse... a is the expression to wait on, and b is
+  *      the statement(s) to execute if it doesn't happen.
+  */
+-#define wait_for(a,b)	 				\
++#define wait_for(a, b)	 				\
+ 	do{						\
+ 		int _i;					\
+ 		for(_i=0;_iiobase))
++#define ni_writel(a, b)		(outl((a), (b)+dev->iobase))
+ #define ni_readl(a)		(inl((a)+dev->iobase))
+-#define ni_writew(a,b)		(outw((a),(b)+dev->iobase))
++#define ni_writew(a, b)		(outw((a), (b)+dev->iobase))
+ #define ni_readw(a)		(inw((a)+dev->iobase))
+-#define ni_writeb(a,b)		(outb((a),(b)+dev->iobase))
++#define ni_writeb(a, b)		(outb((a), (b)+dev->iobase))
+ #define ni_readb(a)		(inb((a)+dev->iobase))
+ 
+ /* How we access windowed registers */
+@@ -329,11 +329,11 @@ static uint16_t ni_atmio_win_in(struct comedi_device *dev, int addr)
+ }
+ 
+ static struct pnp_device_id device_ids[] = {
+-	{.id = "NIC1900",.driver_data = 0},
+-	{.id = "NIC2400",.driver_data = 0},
+-	{.id = "NIC2500",.driver_data = 0},
+-	{.id = "NIC2600",.driver_data = 0},
+-	{.id = "NIC2700",.driver_data = 0},
++	{.id = "NIC1900", .driver_data = 0},
++	{.id = "NIC2400", .driver_data = 0},
++	{.id = "NIC2500", .driver_data = 0},
++	{.id = "NIC2600", .driver_data = 0},
++	{.id = "NIC2700", .driver_data = 0},
+ 	{.id = ""}
+ };
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index f277ca6b73d4..5c165cac2348 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -66,7 +66,7 @@
+ #include "comedi_fc.h"
+ 
+ #ifndef MDPRINTK
+-#define MDPRINTK(format,args...)
++#define MDPRINTK(format, args...)
+ #endif
+ 
+ /* A timeout count */
+@@ -707,7 +707,7 @@ static uint32_t win_in2(struct comedi_device *dev, int reg)
+ 	return bits;
+ }
+ 
+-#define ao_win_out(data,addr) ni_ao_win_outw(dev,data,addr)
++#define ao_win_out(data, addr) ni_ao_win_outw(dev, data, addr)
+ static inline void ni_ao_win_outw(struct comedi_device *dev, uint16_t data, int addr)
+ {
+ 	unsigned long flags;
+diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c
+index a0301c5e2907..ff53ef781499 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_cs.c
++++ b/drivers/staging/comedi/drivers/ni_mio_cs.c
+@@ -183,11 +183,11 @@ struct ni_private {
+ 
+ /* How we access registers */
+ 
+-#define ni_writel(a,b)		(outl((a),(b)+dev->iobase))
++#define ni_writel(a, b)		(outl((a), (b)+dev->iobase))
+ #define ni_readl(a)		(inl((a)+dev->iobase))
+-#define ni_writew(a,b)		(outw((a),(b)+dev->iobase))
++#define ni_writew(a, b)		(outw((a), (b)+dev->iobase))
+ #define ni_readw(a)		(inw((a)+dev->iobase))
+-#define ni_writeb(a,b)		(outb((a),(b)+dev->iobase))
++#define ni_writeb(a, b)		(outb((a), (b)+dev->iobase))
+ #define ni_readb(a)		(inb((a)+dev->iobase))
+ 
+ /* How we access windowed registers */
+diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
+index 3447d5875533..39566316dc80 100644
+--- a/drivers/staging/comedi/drivers/ni_pcimio.c
++++ b/drivers/staging/comedi/drivers/ni_pcimio.c
+@@ -1225,11 +1225,11 @@ struct ni_private {
+ 
+ /* How we access registers */
+ 
+-#define ni_writel(a,b)	(writel((a), devpriv->mite->daq_io_addr + (b)))
++#define ni_writel(a, b)	(writel((a), devpriv->mite->daq_io_addr + (b)))
+ #define ni_readl(a)	(readl(devpriv->mite->daq_io_addr + (a)))
+-#define ni_writew(a,b)	(writew((a), devpriv->mite->daq_io_addr + (b)))
++#define ni_writew(a, b)	(writew((a), devpriv->mite->daq_io_addr + (b)))
+ #define ni_readw(a)	(readw(devpriv->mite->daq_io_addr + (a)))
+-#define ni_writeb(a,b)	(writeb((a), devpriv->mite->daq_io_addr + (b)))
++#define ni_writeb(a, b)	(writeb((a), devpriv->mite->daq_io_addr + (b)))
+ #define ni_readb(a)	(readb(devpriv->mite->daq_io_addr + (a)))
+ 
+ /* How we access STC registers */
+diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h
+index ea889175e84a..a580cf351bd3 100644
+--- a/drivers/staging/comedi/drivers/ni_stc.h
++++ b/drivers/staging/comedi/drivers/ni_stc.h
+@@ -1418,7 +1418,7 @@ struct ni_board_struct {
+ 	\
+ 	unsigned short dio_output;				\
+ 	unsigned short dio_control;				\
+-	int ao0p,ao1p;						\
++	int ao0p, ao1p;						\
+ 	int lastchan;						\
+ 	int last_do;						\
+ 	int rt_irq;						\
+diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c
+index 8e4feef27114..328be7bd5014 100644
+--- a/drivers/staging/comedi/drivers/pcmda12.c
++++ b/drivers/staging/comedi/drivers/pcmda12.c
+@@ -55,7 +55,7 @@ Configuration Options:
+ 
+ #include 		/* for PCI devices */
+ 
+-#define MIN(a,b) ( ((a) < (b)) ? (a) : (b) )
++#define MIN(a, b) ( ((a) < (b)) ? (a) : (b) )
+ #define SDEV_NO ((int)(s - dev->subdevices))
+ #define CHANS 8
+ #define IOSIZE 16
+diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
+index 9afd51ff9074..0dc51f62bac5 100644
+--- a/drivers/staging/comedi/drivers/pcmmio.c
++++ b/drivers/staging/comedi/drivers/pcmmio.c
+@@ -76,7 +76,7 @@ Configuration Options:
+ #include "../comedidev.h"
+ #include 		/* for PCI devices */
+ 
+-#define MIN(a,b) ( ((a) < (b)) ? (a) : (b) )
++#define MIN(a, b) ( ((a) < (b)) ? (a) : (b) )
+ 
+ /* This stuff is all from pcmuio.c -- it refers to the DIO subdevices only */
+ #define CHANS_PER_PORT   8
+diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
+index 04fff9dfe87d..54971a1cb908 100644
+--- a/drivers/staging/comedi/drivers/pcmuio.c
++++ b/drivers/staging/comedi/drivers/pcmuio.c
+@@ -79,7 +79,7 @@ Configuration Options:
+ 
+ #include 		/* for PCI devices */
+ 
+-#define MIN(a,b) ( ((a) < (b)) ? (a) : (b) )
++#define MIN(a, b) ( ((a) < (b)) ? (a) : (b) )
+ #define CHANS_PER_PORT   8
+ #define PORTS_PER_ASIC   6
+ #define INTR_PORTS_PER_ASIC   3
+diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c
+index 93ef401f409e..cac2abf6f03a 100644
+--- a/drivers/staging/comedi/drivers/rti800.c
++++ b/drivers/staging/comedi/drivers/rti800.c
+@@ -89,8 +89,8 @@ Configuration options:
+ 
+ #define Am9513_8BITBUS
+ 
+-#define Am9513_output_control(a)	outb(a,dev->iobase+RTI800_9513A_CNTRL)
+-#define Am9513_output_data(a)		outb(a,dev->iobase+RTI800_9513A_DATA)
++#define Am9513_output_control(a)	outb(a, dev->iobase+RTI800_9513A_CNTRL)
++#define Am9513_output_data(a)		outb(a, dev->iobase+RTI800_9513A_DATA)
+ #define Am9513_input_data()		inb(dev->iobase+RTI800_9513A_DATA)
+ #define Am9513_input_status()		inb(dev->iobase+RTI800_9513A_STATUS)
+ 
+diff --git a/drivers/staging/comedi/rt_pend_tq.c b/drivers/staging/comedi/rt_pend_tq.c
+index a374284b1864..5d2eead99f26 100644
+--- a/drivers/staging/comedi/rt_pend_tq.c
++++ b/drivers/staging/comedi/rt_pend_tq.c
+@@ -28,8 +28,8 @@ int rt_pend_tq_irq = 0;
+ DEFINE_SPINLOCK(rt_pend_tq_lock);
+ 
+ /* WARNING: following code not checked against race conditions yet. */
+-#define INC_CIRCULAR_PTR(ptr,begin,size) do {if(++(ptr)>=(begin)+(size)) (ptr)=(begin); } while(0)
+-#define DEC_CIRCULAR_PTR(ptr,begin,size) do {if(--(ptr)<(begin)) (ptr)=(begin)+(size)-1; } while(0)
++#define INC_CIRCULAR_PTR(ptr, begin, size) do {if(++(ptr)>=(begin)+(size)) (ptr)=(begin); } while(0)
++#define DEC_CIRCULAR_PTR(ptr, begin, size) do {if(--(ptr)<(begin)) (ptr)=(begin)+(size)-1; } while(0)
+ 
+ int rt_pend_call(void (*func) (int arg1, void *arg2), int arg1, void *arg2)
+ {

commit da91b2692e0939b307f9047192d2b9fe07793e7a
+Author: Bill Pemberton 
+Date:   Thu Apr 9 16:07:03 2009 -0400
+
+    Staging: comedi: fix "foo * bar" should be "foo *bar"
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c
+index 0369c7c84ac5..63fc08a3ad7b 100644
+--- a/drivers/staging/comedi/drivers/8255.c
++++ b/drivers/staging/comedi/drivers/8255.c
+@@ -144,7 +144,7 @@ static int subdev_8255_cb(int dir, int port, int data, unsigned long arg)
+ }
+ 
+ static int subdev_8255_insn(struct comedi_device *dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (data[0]) {
+ 		s->state &= ~data[0];
+@@ -169,7 +169,7 @@ static int subdev_8255_insn(struct comedi_device *dev, struct comedi_subdevice *
+ }
+ 
+ static int subdev_8255_insn_config(struct comedi_device *dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int mask;
+ 	unsigned int bits;
+@@ -223,7 +223,7 @@ static void do_config(struct comedi_device *dev, struct comedi_subdevice * s)
+ }
+ 
+ static int subdev_8255_cmdtest(struct comedi_device *dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	unsigned int tmp;
+diff --git a/drivers/staging/comedi/drivers/8255.h b/drivers/staging/comedi/drivers/8255.h
+index 979311b99275..5457c6b2d22e 100644
+--- a/drivers/staging/comedi/drivers/8255.h
++++ b/drivers/staging/comedi/drivers/8255.h
+@@ -28,16 +28,16 @@
+ 
+ #if defined(CONFIG_COMEDI_8255) || defined(CONFIG_COMEDI_8255_MODULE)
+ 
+-int subdev_8255_init(struct comedi_device * dev, struct comedi_subdevice * s,
++int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	int (*cb) (int, int, int, unsigned long), unsigned long arg);
+-int subdev_8255_init_irq(struct comedi_device * dev, struct comedi_subdevice * s,
++int subdev_8255_init_irq(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	int (*cb) (int, int, int, unsigned long), unsigned long arg);
+-void subdev_8255_cleanup(struct comedi_device * dev, struct comedi_subdevice * s);
+-void subdev_8255_interrupt(struct comedi_device * dev, struct comedi_subdevice * s);
++void subdev_8255_cleanup(struct comedi_device *dev, struct comedi_subdevice *s);
++void subdev_8255_interrupt(struct comedi_device *dev, struct comedi_subdevice *s);
+ 
+ #else
+ 
+-static inline int subdev_8255_init(struct comedi_device * dev, struct comedi_subdevice * s,
++static inline int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	void *x, unsigned long y)
+ {
+ 	printk("8255 support not configured -- disabling subdevice\n");
+@@ -47,8 +47,8 @@ static inline int subdev_8255_init(struct comedi_device * dev, struct comedi_sub
+ 	return 0;
+ }
+ 
+-static inline void subdev_8255_cleanup(struct comedi_device * dev,
+-	struct comedi_subdevice * s)
++static inline void subdev_8255_cleanup(struct comedi_device *dev,
++	struct comedi_subdevice *s)
+ {
+ }
+ 
+diff --git a/drivers/staging/comedi/drivers/acl7225b.c b/drivers/staging/comedi/drivers/acl7225b.c
+index 057753991323..067ad7523d9d 100644
+--- a/drivers/staging/comedi/drivers/acl7225b.c
++++ b/drivers/staging/comedi/drivers/acl7225b.c
+@@ -51,7 +51,7 @@ static struct comedi_driver driver_acl7225b = {
+ COMEDI_INITCLEANUP(driver_acl7225b);
+ 
+ static int acl7225b_do_insn(struct comedi_device *dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -72,7 +72,7 @@ static int acl7225b_do_insn(struct comedi_device *dev, struct comedi_subdevice *
+ }
+ 
+ static int acl7225b_di_insn(struct comedi_device *dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+index b3ee729c50ca..cd41e39bbced 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+@@ -219,8 +219,8 @@ int i_InsnConfig_InitTimer(struct comedi_device *dev,struct comedi_subdevice *s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, struct comedi_subdevice * s,
+-				   struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnConfigInitTimer(struct comedi_device *dev, struct comedi_subdevice *s,
++				   struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	int i_ReturnValue = 0;
+@@ -448,9 +448,9 @@ i_ReturnValue=insn->n;
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device * dev,
+-					   struct comedi_subdevice * s,
+-					   struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,
++					   struct comedi_subdevice *s,
++					   struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_DummyRead;
+@@ -595,7 +595,7 @@ int i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, struct comedi_su
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned char b_ModulNbr, b_ReadType;
+-	unsigned int * pul_TimerValueArray;
++	unsigned int *pul_TimerValueArray;
+ 
+ 	b_ModulNbr = CR_AREF(insn->chanspec);
+ 	b_ReadType = CR_CHAN(insn->chanspec);
+@@ -681,8 +681,8 @@ struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InsnBitsTimer(struct comedi_device * dev, struct comedi_subdevice * s,
+-			     struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnBitsTimer(struct comedi_device *dev, struct comedi_subdevice *s,
++			     struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned char b_BitsType;
+ 	int i_ReturnValue = 0;
+@@ -760,9 +760,9 @@ int i_APCI1710_InsnBitsTimer(struct comedi_device * dev, struct comedi_subdevice
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_ReadTimerValue(struct comedi_device * dev,
++int i_APCI1710_ReadTimerValue(struct comedi_device *dev,
+ 			      unsigned char b_ModulNbr, unsigned char b_TimerNbr,
+-			      unsigned int * pul_TimerValue)
++			      unsigned int *pul_TimerValue)
+ {
+ 	int i_ReturnValue = 0;
+ 
+@@ -848,9 +848,9 @@ int i_APCI1710_ReadTimerValue(struct comedi_device * dev,
+ 	   +----------------------------------------------------------------------------+
+ 	 */
+ 
+-int i_APCI1710_GetTimerOutputLevel(struct comedi_device * dev,
++int i_APCI1710_GetTimerOutputLevel(struct comedi_device *dev,
+ 				   unsigned char b_ModulNbr, unsigned char b_TimerNbr,
+-				   unsigned char * pb_OutputLevel)
++				   unsigned char *pb_OutputLevel)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_TimerStatus;
+@@ -929,7 +929,7 @@ int i_APCI1710_GetTimerOutputLevel(struct comedi_device * dev,
+ 
+ int i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
+ 				      unsigned char b_ModulNbr, unsigned char b_TimerNbr,
+-				      unsigned char * pb_TimerStatus)
++				      unsigned char *pb_TimerStatus)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_TimerStatus;
+@@ -1006,7 +1006,7 @@ int i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_WriteTimerValue(struct comedi_device * dev,
++int i_APCI1710_WriteTimerValue(struct comedi_device *dev,
+ 			       unsigned char b_ModulNbr, unsigned char b_TimerNbr,
+ 			       unsigned int ul_WriteValue)
+ {
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
+index cf6de0912a24..9698ae13509d 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
+@@ -55,15 +55,15 @@ int i_APCI1710_InsnBitsTimer(struct comedi_device *dev, struct comedi_subdevice
+  */
+ int i_APCI1710_ReadTimerValue(struct comedi_device *dev,
+ 			      unsigned char b_ModulNbr, unsigned char b_TimerNbr,
+-			      unsigned int * pul_TimerValue);
++			      unsigned int *pul_TimerValue);
+ 
+ int i_APCI1710_GetTimerOutputLevel(struct comedi_device *dev,
+ 				   unsigned char b_ModulNbr, unsigned char b_TimerNbr,
+-				   unsigned char * pb_OutputLevel);
++				   unsigned char *pb_OutputLevel);
+ 
+ int i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
+ 				      unsigned char b_ModulNbr, unsigned char b_TimerNbr,
+-				      unsigned char * pb_TimerStatus);
++				      unsigned char *pb_TimerStatus);
+ 
+ /*
+  * 82X54 WRITE FUNCTION
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+index 6c3be314303d..3bbf7d7da63f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+@@ -131,8 +131,8 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnConfigInitChrono(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int ul_TimerValue = 0;
+@@ -840,8 +840,8 @@ struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)						 |
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned char b_ModulNbr, b_CycleMode, b_InterruptEnable, b_Action;
+@@ -1090,8 +1090,8 @@ struct comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InsnReadChrono(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnReadChrono(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned char b_ReadType;
+ 	int i_ReturnValue = insn->n;
+@@ -1194,8 +1194,8 @@ int i_APCI1710_InsnReadChrono(struct comedi_device * dev, struct comedi_subdevic
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_GetChronoProgressStatus(struct comedi_device * dev,
+-	unsigned char b_ModulNbr, unsigned char * pb_ChronoStatus)
++int i_APCI1710_GetChronoProgressStatus(struct comedi_device *dev,
++	unsigned char b_ModulNbr, unsigned char *pb_ChronoStatus)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_Status;
+@@ -1355,9 +1355,9 @@ int i_APCI1710_GetChronoProgressStatus(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_ReadChronoValue(struct comedi_device * dev,
++int i_APCI1710_ReadChronoValue(struct comedi_device *dev,
+ 	unsigned char b_ModulNbr,
+-	unsigned int ui_TimeOut, unsigned char * pb_ChronoStatus, unsigned int * pul_ChronoValue)
++	unsigned int ui_TimeOut, unsigned char *pb_ChronoStatus, unsigned int *pul_ChronoValue)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_Status;
+@@ -1619,13 +1619,13 @@ int i_APCI1710_ReadChronoValue(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
++int i_APCI1710_ConvertChronoValue(struct comedi_device *dev,
+ 	unsigned char b_ModulNbr,
+ 	unsigned int ul_ChronoValue,
+-	unsigned int * pul_Hour,
+-	unsigned char * pb_Minute,
+-	unsigned char * pb_Second,
+-	unsigned int * pui_MilliSecond, unsigned int * pui_MicroSecond, unsigned int * pui_NanoSecond)
++	unsigned int *pul_Hour,
++	unsigned char *pb_Minute,
++	unsigned char *pb_Second,
++	unsigned int *pui_MilliSecond, unsigned int *pui_MicroSecond, unsigned int *pui_NanoSecond)
+ {
+ 	int i_ReturnValue = 0;
+ 	double d_Hour;
+@@ -1876,14 +1876,14 @@ int i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned char b_ModulNbr, b_OutputChannel, b_InputChannel, b_IOType;
+ 	unsigned int dw_Status;
+-	unsigned char * pb_ChannelStatus;
+-	unsigned char * pb_PortValue;
++	unsigned char *pb_ChannelStatus;
++	unsigned char *pb_PortValue;
+ 
+ 	b_ModulNbr = CR_AREF(insn->chanspec);
+ 	i_ReturnValue = insn->n;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
+index 16c6aff8859f..29bad1d144a1 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
+@@ -50,21 +50,21 @@ int i_APCI1710_InsnReadChrono(struct comedi_device *dev, struct comedi_subdevice
+ 			      struct comedi_insn *insn, unsigned int *data);
+ 
+ int i_APCI1710_GetChronoProgressStatus(struct comedi_device *dev,
+-				       unsigned char b_ModulNbr, unsigned char * pb_ChronoStatus);
++				       unsigned char b_ModulNbr, unsigned char *pb_ChronoStatus);
+ 
+ int i_APCI1710_ReadChronoValue(struct comedi_device *dev,
+ 			       unsigned char b_ModulNbr,
+-			       unsigned int ui_TimeOut, unsigned char * pb_ChronoStatus,
+-			       unsigned int * pul_ChronoValue);
++			       unsigned int ui_TimeOut, unsigned char *pb_ChronoStatus,
++			       unsigned int *pul_ChronoValue);
+ 
+ int i_APCI1710_ConvertChronoValue(struct comedi_device *dev,
+ 				  unsigned char b_ModulNbr,
+ 				  unsigned int ul_ChronoValue,
+-				  unsigned int * pul_Hour,
+-				  unsigned char * pb_Minute,
+-				  unsigned char * pb_Second,
+-				  unsigned int * pui_MilliSecond, unsigned int * pui_MicroSecond,
+-				  unsigned int * pui_NanoSecond);
++				  unsigned int *pul_Hour,
++				  unsigned char *pb_Minute,
++				  unsigned char *pb_Second,
++				  unsigned int *pui_MilliSecond, unsigned int *pui_MicroSecond,
++				  unsigned int *pui_NanoSecond);
+ 
+ /*
+  * CHRONOMETER DIGITAL INPUT OUTPUT FUNCTION
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+index a3266ba92846..aad76fb8ea4b 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+@@ -99,8 +99,8 @@ Activates and deactivates the digital output memory.
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InsnConfigDigitalIO(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnConfigDigitalIO(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned char b_ModulNbr, b_ChannelAMode, b_ChannelBMode;
+ 	unsigned char b_MemoryOnOff, b_ConfigType;
+@@ -293,13 +293,13 @@ int i_APCI1710_InsnConfigDigitalIO(struct comedi_device * dev, struct comedi_sub
+ * unsigned char_ b_ModulNbr, unsigned char_ b_InputChannel,
+ * unsigned char *_ pb_ChannelStatus)
+ */
+-int i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_StatusReg;
+ 	unsigned char b_ModulNbr, b_InputChannel;
+-	unsigned char * pb_ChannelStatus;
++	unsigned char *pb_ChannelStatus;
+ 	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+ 	b_InputChannel = (unsigned char) CR_CHAN(insn->chanspec);
+ 	data[0] = 0;
+@@ -481,8 +481,8 @@ int i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device * dev,
+ * _INT_ i_APCI1710_SetDigitalIOChlOn (unsigned char_ b_BoardHandle,
+ * unsigned char_ b_ModulNbr, unsigned char_ b_OutputChannel)
+ */
+-int i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_WriteValue = 0;
+@@ -731,8 +731,8 @@ int i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device * dev,
+  * b_BoardHandle, unsigned char_ b_ModulNbr, unsigned char_
+  * b_PortValue)
+ */
+-int i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_WriteValue = 0;
+@@ -740,7 +740,7 @@ int i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, b_PortValue;
+ 	unsigned char b_PortOperation, b_PortOnOFF;
+ 
+-	unsigned char * pb_PortValue;
++	unsigned char *pb_PortValue;
+ 
+ 	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+ 	b_PortOperation = (unsigned char) data[0];	/*  Input or output */
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+index 821edbae3f27..29ba78f0939d 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+@@ -75,8 +75,8 @@ struct comedi_insn *insn,unsigned int *data)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InsnConfigINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_ConfigType;
+ 	int i_ReturnValue = 0;
+@@ -299,7 +299,7 @@ int i_APCI1710_InsnConfigINCCPT(struct comedi_device * dev, struct comedi_subdev
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InitCounter(struct comedi_device * dev,
++int i_APCI1710_InitCounter(struct comedi_device *dev,
+ 	unsigned char b_ModulNbr,
+ 	unsigned char b_CounterRange,
+ 	unsigned char b_FirstCounterModus,
+@@ -545,7 +545,7 @@ int i_APCI1710_InitCounter(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_CounterAutoTest(struct comedi_device * dev, unsigned char * pb_TestStatus)
++int i_APCI1710_CounterAutoTest(struct comedi_device *dev, unsigned char *pb_TestStatus)
+ {
+ 	unsigned char b_ModulCpt = 0;
+ 	int i_ReturnValue = 0;
+@@ -708,7 +708,7 @@ int i_APCI1710_CounterAutoTest(struct comedi_device * dev, unsigned char * pb_Te
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InitIndex(struct comedi_device * dev,
++int i_APCI1710_InitIndex(struct comedi_device *dev,
+ 	unsigned char b_ModulNbr,
+ 	unsigned char b_ReferenceAction,
+ 	unsigned char b_IndexOperation, unsigned char b_AutoMode, unsigned char b_InterruptEnable)
+@@ -1152,7 +1152,7 @@ int i_APCI1710_InitIndex(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InitReference(struct comedi_device * dev,
++int i_APCI1710_InitReference(struct comedi_device *dev,
+ 	unsigned char b_ModulNbr, unsigned char b_ReferenceLevel)
+ {
+ 	int i_ReturnValue = 0;
+@@ -1277,7 +1277,7 @@ int i_APCI1710_InitReference(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InitExternalStrobe(struct comedi_device * dev,
++int i_APCI1710_InitExternalStrobe(struct comedi_device *dev,
+ 	unsigned char b_ModulNbr, unsigned char b_ExternalStrobe, unsigned char b_ExternalStrobeLevel)
+ {
+ 	int i_ReturnValue = 0;
+@@ -1391,7 +1391,7 @@ int i_APCI1710_InitExternalStrobe(struct comedi_device * dev,
+ 	   +----------------------------------------------------------------------------+
+ 	 */
+ 
+-int i_APCI1710_InitCompareLogic(struct comedi_device * dev,
++int i_APCI1710_InitCompareLogic(struct comedi_device *dev,
+ 	unsigned char b_ModulNbr, unsigned int ui_CompareValue)
+ {
+ 	int i_ReturnValue = 0;
+@@ -1487,11 +1487,11 @@ int i_APCI1710_InitCompareLogic(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InitFrequencyMeasurement(struct comedi_device * dev,
++int i_APCI1710_InitFrequencyMeasurement(struct comedi_device *dev,
+ 	unsigned char b_ModulNbr,
+ 	unsigned char b_PCIInputClock,
+ 	unsigned char b_TimingUnity,
+-	unsigned int ul_TimingInterval, unsigned int * pul_RealTimingInterval)
++	unsigned int ul_TimingInterval, unsigned int *pul_RealTimingInterval)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int ul_TimerValue = 0;
+@@ -2015,8 +2015,8 @@ struct comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InsnBitsINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnBitsINCCPT(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_BitsType;
+ 	int i_ReturnValue = 0;
+@@ -2091,7 +2091,7 @@ int i_APCI1710_InsnBitsINCCPT(struct comedi_device * dev, struct comedi_subdevic
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_ClearCounterValue(struct comedi_device * dev, unsigned char b_ModulNbr)
++int i_APCI1710_ClearCounterValue(struct comedi_device *dev, unsigned char b_ModulNbr)
+ {
+ 	int i_ReturnValue = 0;
+ 
+@@ -2151,7 +2151,7 @@ int i_APCI1710_ClearCounterValue(struct comedi_device * dev, unsigned char b_Mod
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_ClearAllCounterValue(struct comedi_device * dev)
++int i_APCI1710_ClearAllCounterValue(struct comedi_device *dev)
+ {
+ 	unsigned char b_ModulCpt = 0;
+ 	int i_ReturnValue = 0;
+@@ -2297,7 +2297,7 @@ int i_APCI1710_ClearAllCounterValue(struct comedi_device * dev)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_SetInputFilter(struct comedi_device * dev,
++int i_APCI1710_SetInputFilter(struct comedi_device *dev,
+ 	unsigned char b_ModulNbr, unsigned char b_PCIInputClock, unsigned char b_Filter)
+ {
+ 	int i_ReturnValue = 0;
+@@ -2561,7 +2561,7 @@ int i_APCI1710_SetInputFilter(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_LatchCounter(struct comedi_device * dev,
++int i_APCI1710_LatchCounter(struct comedi_device *dev,
+ 	unsigned char b_ModulNbr, unsigned char b_LatchReg)
+ {
+ 	int i_ReturnValue = 0;
+@@ -2658,7 +2658,7 @@ int i_APCI1710_LatchCounter(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_SetIndexAndReferenceSource(struct comedi_device * dev,
++int i_APCI1710_SetIndexAndReferenceSource(struct comedi_device *dev,
+ 	unsigned char b_ModulNbr, unsigned char b_SourceSelection)
+ {
+ 	int i_ReturnValue = 0;
+@@ -2795,7 +2795,7 @@ int i_APCI1710_SetIndexAndReferenceSource(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_SetDigitalChlOn(struct comedi_device * dev, unsigned char b_ModulNbr)
++int i_APCI1710_SetDigitalChlOn(struct comedi_device *dev, unsigned char b_ModulNbr)
+ {
+ 	int i_ReturnValue = 0;
+ 
+@@ -2875,7 +2875,7 @@ int i_APCI1710_SetDigitalChlOn(struct comedi_device * dev, unsigned char b_Modul
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_SetDigitalChlOff(struct comedi_device * dev, unsigned char b_ModulNbr)
++int i_APCI1710_SetDigitalChlOff(struct comedi_device *dev, unsigned char b_ModulNbr)
+ {
+ 	int i_ReturnValue = 0;
+ 
+@@ -2951,8 +2951,8 @@ struct comedi_insn *insn,unsigned int *data)                   |
+ | Return Value      :
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1710_InsnWriteINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_WriteType;
+ 	int i_ReturnValue = 0;
+@@ -3047,7 +3047,7 @@ int i_APCI1710_InsnWriteINCCPT(struct comedi_device * dev, struct comedi_subdevi
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_EnableLatchInterrupt(struct comedi_device * dev, unsigned char b_ModulNbr)
++int i_APCI1710_EnableLatchInterrupt(struct comedi_device *dev, unsigned char b_ModulNbr)
+ {
+ 	int i_ReturnValue = 0;
+ 
+@@ -3133,7 +3133,7 @@ int i_APCI1710_EnableLatchInterrupt(struct comedi_device * dev, unsigned char b_
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_DisableLatchInterrupt(struct comedi_device * dev, unsigned char b_ModulNbr)
++int i_APCI1710_DisableLatchInterrupt(struct comedi_device *dev, unsigned char b_ModulNbr)
+ {
+ 	int i_ReturnValue = 0;
+ 
+@@ -3231,7 +3231,7 @@ int i_APCI1710_DisableLatchInterrupt(struct comedi_device * dev, unsigned char b
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_Write16BitCounterValue(struct comedi_device * dev,
++int i_APCI1710_Write16BitCounterValue(struct comedi_device *dev,
+ 	unsigned char b_ModulNbr, unsigned char b_SelectedCounter, unsigned int ui_WriteValue)
+ {
+ 	int i_ReturnValue = 0;
+@@ -3316,7 +3316,7 @@ int i_APCI1710_Write16BitCounterValue(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_Write32BitCounterValue(struct comedi_device * dev,
++int i_APCI1710_Write32BitCounterValue(struct comedi_device *dev,
+ 	unsigned char b_ModulNbr, unsigned int ul_WriteValue)
+ {
+ 	int i_ReturnValue = 0;
+@@ -3383,7 +3383,7 @@ int i_APCI1710_Write32BitCounterValue(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_EnableIndex(struct comedi_device * dev, unsigned char b_ModulNbr)
++int i_APCI1710_EnableIndex(struct comedi_device *dev, unsigned char b_ModulNbr)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int ul_InterruptLatchReg;
+@@ -3481,7 +3481,7 @@ int i_APCI1710_EnableIndex(struct comedi_device * dev, unsigned char b_ModulNbr)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_DisableIndex(struct comedi_device * dev, unsigned char b_ModulNbr)
++int i_APCI1710_DisableIndex(struct comedi_device *dev, unsigned char b_ModulNbr)
+ {
+ 	int i_ReturnValue = 0;
+ 
+@@ -3580,7 +3580,7 @@ int i_APCI1710_DisableIndex(struct comedi_device * dev, unsigned char b_ModulNbr
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_EnableCompareLogic(struct comedi_device * dev, unsigned char b_ModulNbr)
++int i_APCI1710_EnableCompareLogic(struct comedi_device *dev, unsigned char b_ModulNbr)
+ {
+ 	int i_ReturnValue = 0;
+ 
+@@ -3680,7 +3680,7 @@ int i_APCI1710_EnableCompareLogic(struct comedi_device * dev, unsigned char b_Mo
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_DisableCompareLogic(struct comedi_device * dev, unsigned char b_ModulNbr)
++int i_APCI1710_DisableCompareLogic(struct comedi_device *dev, unsigned char b_ModulNbr)
+ {
+ 	int i_ReturnValue = 0;
+ 
+@@ -3789,7 +3789,7 @@ int i_APCI1710_DisableCompareLogic(struct comedi_device * dev, unsigned char b_M
+ 	   +----------------------------------------------------------------------------+
+ 	 */
+ 
+-int i_APCI1710_EnableFrequencyMeasurement(struct comedi_device * dev,
++int i_APCI1710_EnableFrequencyMeasurement(struct comedi_device *dev,
+ 	unsigned char b_ModulNbr, unsigned char b_InterruptEnable)
+ {
+ 	int i_ReturnValue = 0;
+@@ -3936,7 +3936,7 @@ int i_APCI1710_EnableFrequencyMeasurement(struct comedi_device * dev,
+ 	   +----------------------------------------------------------------------------+
+ 	 */
+ 
+-int i_APCI1710_DisableFrequencyMeasurement(struct comedi_device * dev, unsigned char b_ModulNbr)
++int i_APCI1710_DisableFrequencyMeasurement(struct comedi_device *dev, unsigned char b_ModulNbr)
+ {
+ 	int i_ReturnValue = 0;
+ 
+@@ -4049,8 +4049,8 @@ struct comedi_insn *insn,unsigned int *data)                   |
+ | Return Value      :
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1710_InsnReadINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnReadINCCPT(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_ReadType;
+ 	int i_ReturnValue = 0;
+@@ -4193,8 +4193,8 @@ int i_APCI1710_InsnReadINCCPT(struct comedi_device * dev, struct comedi_subdevic
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_ReadLatchRegisterStatus(struct comedi_device * dev,
+-	unsigned char b_ModulNbr, unsigned char b_LatchReg, unsigned char * pb_LatchStatus)
++int i_APCI1710_ReadLatchRegisterStatus(struct comedi_device *dev,
++	unsigned char b_ModulNbr, unsigned char b_LatchReg, unsigned char *pb_LatchStatus)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_LatchReg;
+@@ -4280,8 +4280,8 @@ int i_APCI1710_ReadLatchRegisterStatus(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_ReadLatchRegisterValue(struct comedi_device * dev,
+-	unsigned char b_ModulNbr, unsigned char b_LatchReg, unsigned int * pul_LatchValue)
++int i_APCI1710_ReadLatchRegisterValue(struct comedi_device *dev,
++	unsigned char b_ModulNbr, unsigned char b_LatchReg, unsigned int *pul_LatchValue)
+ {
+ 	int i_ReturnValue = 0;
+ 
+@@ -4364,8 +4364,8 @@ int i_APCI1710_ReadLatchRegisterValue(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_Read16BitCounterValue(struct comedi_device * dev,
+-	unsigned char b_ModulNbr, unsigned char b_SelectedCounter, unsigned int * pui_CounterValue)
++int i_APCI1710_Read16BitCounterValue(struct comedi_device *dev,
++	unsigned char b_ModulNbr, unsigned char b_SelectedCounter, unsigned int *pui_CounterValue)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_LathchValue = 0;
+@@ -4459,8 +4459,8 @@ int i_APCI1710_Read16BitCounterValue(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_Read32BitCounterValue(struct comedi_device * dev,
+-	unsigned char b_ModulNbr, unsigned int * pul_CounterValue)
++int i_APCI1710_Read32BitCounterValue(struct comedi_device *dev,
++	unsigned char b_ModulNbr, unsigned int *pul_CounterValue)
+ {
+ 	int i_ReturnValue = 0;
+ 
+@@ -4535,8 +4535,8 @@ int i_APCI1710_Read32BitCounterValue(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_GetIndexStatus(struct comedi_device * dev,
+-	unsigned char b_ModulNbr, unsigned char * pb_IndexStatus)
++int i_APCI1710_GetIndexStatus(struct comedi_device *dev,
++	unsigned char b_ModulNbr, unsigned char *pb_IndexStatus)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_StatusReg = 0;
+@@ -4619,8 +4619,8 @@ int i_APCI1710_GetIndexStatus(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_GetReferenceStatus(struct comedi_device * dev,
+-	unsigned char b_ModulNbr, unsigned char * pb_ReferenceStatus)
++int i_APCI1710_GetReferenceStatus(struct comedi_device *dev,
++	unsigned char b_ModulNbr, unsigned char *pb_ReferenceStatus)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_StatusReg = 0;
+@@ -4703,8 +4703,8 @@ int i_APCI1710_GetReferenceStatus(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_GetUASStatus(struct comedi_device * dev,
+-	unsigned char b_ModulNbr, unsigned char * pb_UASStatus)
++int i_APCI1710_GetUASStatus(struct comedi_device *dev,
++	unsigned char b_ModulNbr, unsigned char *pb_UASStatus)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_StatusReg = 0;
+@@ -4771,8 +4771,8 @@ int i_APCI1710_GetUASStatus(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_GetCBStatus(struct comedi_device * dev,
+-	unsigned char b_ModulNbr, unsigned char * pb_CBStatus)
++int i_APCI1710_GetCBStatus(struct comedi_device *dev,
++	unsigned char b_ModulNbr, unsigned char *pb_CBStatus)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_StatusReg = 0;
+@@ -4853,8 +4853,8 @@ int i_APCI1710_GetCBStatus(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_Get16BitCBStatus(struct comedi_device * dev,
+-	unsigned char b_ModulNbr, unsigned char * pb_CBStatusCounter0, unsigned char * pb_CBStatusCounter1)
++int i_APCI1710_Get16BitCBStatus(struct comedi_device *dev,
++	unsigned char b_ModulNbr, unsigned char *pb_CBStatusCounter0, unsigned char *pb_CBStatusCounter1)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_StatusReg = 0;
+@@ -4966,8 +4966,8 @@ int i_APCI1710_Get16BitCBStatus(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_GetUDStatus(struct comedi_device * dev,
+-	unsigned char b_ModulNbr, unsigned char * pb_UDStatus)
++int i_APCI1710_GetUDStatus(struct comedi_device *dev,
++	unsigned char b_ModulNbr, unsigned char *pb_UDStatus)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_StatusReg = 0;
+@@ -5040,8 +5040,8 @@ int i_APCI1710_GetUDStatus(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device * dev,
+-	unsigned char b_ModulNbr, unsigned char * pb_UDStatus)
++int i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device *dev,
++	unsigned char b_ModulNbr, unsigned char *pb_UDStatus)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_StatusReg = 0;
+@@ -5145,9 +5145,9 @@ int i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device * dev,
+ 	   +----------------------------------------------------------------------------+
+ 	 */
+ 
+-int i_APCI1710_ReadFrequencyMeasurement(struct comedi_device * dev,
++int i_APCI1710_ReadFrequencyMeasurement(struct comedi_device *dev,
+ 	unsigned char b_ModulNbr,
+-	unsigned char * pb_Status, unsigned char * pb_UDStatus, unsigned int * pul_ReadValue)
++	unsigned char *pb_Status, unsigned char *pb_UDStatus, unsigned int *pul_ReadValue)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int ui_16BitValue;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
+index 51c759bdc3b0..7b481107fe1d 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
+@@ -178,7 +178,7 @@ int i_APCI1710_InitFrequencyMeasurement(struct comedi_device *dev,
+ 					unsigned char b_PCIInputClock,
+ 					unsigned char b_TimingUnity,
+ 					unsigned int ul_TimingInterval,
+-					unsigned int * pul_RealTimingInterval);
++					unsigned int *pul_RealTimingInterval);
+ 
+ /* INSN BITS */
+ int i_APCI1710_ClearCounterValue(struct comedi_device *dev, unsigned char b_ModulNbr);
+@@ -230,42 +230,42 @@ int i_APCI1710_DisableFrequencyMeasurement(struct comedi_device *dev,
+ /* INSN READ */
+ int i_APCI1710_ReadLatchRegisterStatus(struct comedi_device *dev,
+ 				       unsigned char b_ModulNbr, unsigned char b_LatchReg,
+-				       unsigned char * pb_LatchStatus);
++				       unsigned char *pb_LatchStatus);
+ 
+ int i_APCI1710_ReadLatchRegisterValue(struct comedi_device *dev,
+ 				      unsigned char b_ModulNbr, unsigned char b_LatchReg,
+-				      unsigned int * pul_LatchValue);
++				      unsigned int *pul_LatchValue);
+ 
+ int i_APCI1710_Read16BitCounterValue(struct comedi_device *dev,
+ 				     unsigned char b_ModulNbr, unsigned char b_SelectedCounter,
+-				     unsigned int * pui_CounterValue);
++				     unsigned int *pui_CounterValue);
+ 
+ int i_APCI1710_Read32BitCounterValue(struct comedi_device *dev,
+-				     unsigned char b_ModulNbr, unsigned int * pul_CounterValue);
++				     unsigned char b_ModulNbr, unsigned int *pul_CounterValue);
+ 
+ int i_APCI1710_GetIndexStatus(struct comedi_device *dev,
+-			      unsigned char b_ModulNbr, unsigned char * pb_IndexStatus);
++			      unsigned char b_ModulNbr, unsigned char *pb_IndexStatus);
+ 
+ int i_APCI1710_GetReferenceStatus(struct comedi_device *dev,
+-				  unsigned char b_ModulNbr, unsigned char * pb_ReferenceStatus);
++				  unsigned char b_ModulNbr, unsigned char *pb_ReferenceStatus);
+ 
+ int i_APCI1710_GetUASStatus(struct comedi_device *dev,
+-			    unsigned char b_ModulNbr, unsigned char * pb_UASStatus);
++			    unsigned char b_ModulNbr, unsigned char *pb_UASStatus);
+ 
+ int i_APCI1710_GetCBStatus(struct comedi_device *dev,
+-			   unsigned char b_ModulNbr, unsigned char * pb_CBStatus);
++			   unsigned char b_ModulNbr, unsigned char *pb_CBStatus);
+ 
+ int i_APCI1710_Get16BitCBStatus(struct comedi_device *dev,
+-				unsigned char b_ModulNbr, unsigned char * pb_CBStatusCounter0,
+-				unsigned char * pb_CBStatusCounter1);
++				unsigned char b_ModulNbr, unsigned char *pb_CBStatusCounter0,
++				unsigned char *pb_CBStatusCounter1);
+ 
+ int i_APCI1710_GetUDStatus(struct comedi_device *dev,
+-			   unsigned char b_ModulNbr, unsigned char * pb_UDStatus);
++			   unsigned char b_ModulNbr, unsigned char *pb_UDStatus);
+ 
+ int i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device *dev,
+-					   unsigned char b_ModulNbr, unsigned char * pb_UDStatus);
++					   unsigned char b_ModulNbr, unsigned char *pb_UDStatus);
+ 
+ int i_APCI1710_ReadFrequencyMeasurement(struct comedi_device *dev,
+ 					unsigned char b_ModulNbr,
+-					unsigned char * pb_Status, unsigned char * pb_UDStatus,
+-					unsigned int * pul_ReadValue);
++					unsigned char *pb_Status, unsigned char *pb_UDStatus,
++					unsigned int *pul_ReadValue);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+index 966aba855d0c..b815d0a0e8a5 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+@@ -123,8 +123,8 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_IntRegister;
+@@ -414,8 +414,8 @@ int i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned char b_ModulNbr;
+@@ -708,16 +708,16 @@ int i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device * dev,
+ 
+ 						 unsigned char *_ pb_Status)
+ 						 */
+-int i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_StatusRegister;
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_PulseEncoderNbr;
+-	unsigned char * pb_Status;
++	unsigned char *pb_Status;
+ 	unsigned char b_Type;
+-	unsigned int * pul_ReadValue;
++	unsigned int *pul_ReadValue;
+ 	unsigned int ul_WriteValue;
+ 
+ 	i_ReturnValue = insn->n;
+@@ -834,8 +834,8 @@ int i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device * dev,
+ 	return (i_ReturnValue);
+ }
+ 
+-int i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	data[0] = devpriv->s_InterruptParameters.
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+index 976fe5863e49..9eb2b8349c22 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+@@ -70,8 +70,8 @@ struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InsnConfigPWM(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnConfigPWM(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned char b_ConfigType;
+ 	int i_ReturnValue = 0;
+@@ -179,14 +179,14 @@ int i_APCI1710_InsnConfigPWM(struct comedi_device * dev, struct comedi_subdevice
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InitPWM(struct comedi_device * dev,
++int i_APCI1710_InitPWM(struct comedi_device *dev,
+ 	unsigned char b_ModulNbr,
+ 	unsigned char b_PWM,
+ 	unsigned char b_ClockSelection,
+ 	unsigned char b_TimingUnit,
+ 	unsigned int ul_LowTiming,
+ 	unsigned int ul_HighTiming,
+-	unsigned int * pul_RealLowTiming, unsigned int * pul_RealHighTiming)
++	unsigned int *pul_RealLowTiming, unsigned int *pul_RealHighTiming)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int ul_LowTimerValue = 0;
+@@ -1534,16 +1534,16 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_GetPWMInitialisation(struct comedi_device * dev,
++int i_APCI1710_GetPWMInitialisation(struct comedi_device *dev,
+ 	unsigned char b_ModulNbr,
+ 	unsigned char b_PWM,
+-	unsigned char * pb_TimingUnit,
+-	unsigned int * pul_LowTiming,
+-	unsigned int * pul_HighTiming,
+-	unsigned char * pb_StartLevel,
+-	unsigned char * pb_StopMode,
+-	unsigned char * pb_StopLevel,
+-	unsigned char * pb_ExternGate, unsigned char * pb_InterruptEnable, unsigned char * pb_Enable)
++	unsigned char *pb_TimingUnit,
++	unsigned int *pul_LowTiming,
++	unsigned int *pul_HighTiming,
++	unsigned char *pb_StartLevel,
++	unsigned char *pb_StopMode,
++	unsigned char *pb_StopLevel,
++	unsigned char *pb_ExternGate, unsigned char *pb_InterruptEnable, unsigned char *pb_Enable)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_Status;
+@@ -1683,8 +1683,8 @@ struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InsnWritePWM(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnWritePWM(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned char b_WriteType;
+ 	int i_ReturnValue = 0;
+@@ -1806,7 +1806,7 @@ int i_APCI1710_InsnWritePWM(struct comedi_device * dev, struct comedi_subdevice
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_EnablePWM(struct comedi_device * dev,
++int i_APCI1710_EnablePWM(struct comedi_device *dev,
+ 	unsigned char b_ModulNbr,
+ 	unsigned char b_PWM,
+ 	unsigned char b_StartLevel,
+@@ -2062,7 +2062,7 @@ int i_APCI1710_EnablePWM(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_DisablePWM(struct comedi_device * dev, unsigned char b_ModulNbr, unsigned char b_PWM)
++int i_APCI1710_DisablePWM(struct comedi_device *dev, unsigned char b_ModulNbr, unsigned char b_PWM)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_Status;
+@@ -2189,7 +2189,7 @@ int i_APCI1710_DisablePWM(struct comedi_device * dev, unsigned char b_ModulNbr,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
++int i_APCI1710_SetNewPWMTiming(struct comedi_device *dev,
+ 	unsigned char b_ModulNbr,
+ 	unsigned char b_PWM, unsigned char b_TimingUnit, unsigned int ul_LowTiming, unsigned int ul_HighTiming)
+ {
+@@ -3460,16 +3460,16 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InsnReadGetPWMStatus(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnReadGetPWMStatus(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_Status;
+ 
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_PWM;
+-	unsigned char * pb_PWMOutputStatus;
+-	unsigned char * pb_ExternGateStatus;
++	unsigned char *pb_PWMOutputStatus;
++	unsigned char *pb_ExternGateStatus;
+ 
+ 	i_ReturnValue = insn->n;
+ 	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+@@ -3561,8 +3561,8 @@ int i_APCI1710_InsnReadGetPWMStatus(struct comedi_device * dev, struct comedi_su
+ 	return (i_ReturnValue);
+ }
+ 
+-int i_APCI1710_InsnBitsReadPWMInterrupt(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnBitsReadPWMInterrupt(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[0] = devpriv->s_InterruptParameters.
+ 		s_FIFOInterruptParameters[devpriv->
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
+index 07abf9126f78..bf1b4c39a1cd 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
+@@ -36,19 +36,19 @@ int i_APCI1710_InitPWM(struct comedi_device *dev,
+ 		       unsigned char b_TimingUnit,
+ 		       unsigned int ul_LowTiming,
+ 		       unsigned int ul_HighTiming,
+-		       unsigned int * pul_RealLowTiming, unsigned int * pul_RealHighTiming);
++		       unsigned int *pul_RealLowTiming, unsigned int *pul_RealHighTiming);
+ 
+ int i_APCI1710_GetPWMInitialisation(struct comedi_device *dev,
+ 				    unsigned char b_ModulNbr,
+ 				    unsigned char b_PWM,
+-				    unsigned char * pb_TimingUnit,
+-				    unsigned int * pul_LowTiming,
+-				    unsigned int * pul_HighTiming,
+-				    unsigned char * pb_StartLevel,
+-				    unsigned char * pb_StopMode,
+-				    unsigned char * pb_StopLevel,
+-				    unsigned char * pb_ExternGate,
+-				    unsigned char * pb_InterruptEnable, unsigned char * pb_Enable);
++				    unsigned char *pb_TimingUnit,
++				    unsigned int *pul_LowTiming,
++				    unsigned int *pul_HighTiming,
++				    unsigned char *pb_StartLevel,
++				    unsigned char *pb_StopMode,
++				    unsigned char *pb_StopLevel,
++				    unsigned char *pb_ExternGate,
++				    unsigned char *pb_InterruptEnable, unsigned char *pb_Enable);
+ 
+ int i_APCI1710_InsnWritePWM(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			    struct comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+index 238fcc88b15c..5edae81763a0 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+@@ -133,8 +133,8 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InsnConfigInitSSI(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnConfigInitSSI(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int ui_TimerValue;
+@@ -400,8 +400,8 @@ pul_Position	=	(unsigned int *) &data[0];
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InsnReadSSIValue(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnReadSSIValue(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned char b_Cpt;
+@@ -416,10 +416,10 @@ int i_APCI1710_InsnReadSSIValue(struct comedi_device * dev, struct comedi_subdev
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_SelectedSSI;
+ 	unsigned char b_ReadType;
+-	unsigned int * pul_Position;
+-	unsigned int * pul_TurnCpt;
+-	unsigned int * pul_Position1;
+-	unsigned int * pul_TurnCpt1;
++	unsigned int *pul_Position;
++	unsigned int *pul_TurnCpt;
++	unsigned int *pul_Position1;
++	unsigned int *pul_TurnCpt1;
+ 
+ 	i_ReturnValue = insn->n;
+ 	pul_Position1 = (unsigned int *) & data[0];
+@@ -735,15 +735,15 @@ int i_APCI1710_InsnReadSSIValue(struct comedi_device * dev, struct comedi_subdev
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_StatusReg;
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_InputChannel;
+-	unsigned char * pb_ChannelStatus;
+-	unsigned char * pb_InputStatus;
++	unsigned char *pb_ChannelStatus;
++	unsigned char *pb_InputStatus;
+ 	unsigned char b_IOType;
+ 	i_ReturnValue = insn->n;
+ 	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+index dc35124a7584..0170d36ac280 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+@@ -130,8 +130,8 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int ul_TimerValue = 0;
+@@ -987,8 +987,8 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_Status;
+@@ -1460,20 +1460,20 @@ int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_Status;
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_TorCounter;
+-	unsigned char * pb_TimingUnit;
+-	unsigned int * pul_TimingInterval;
+-	unsigned char * pb_InputMode;
+-	unsigned char * pb_ExternGate;
+-	unsigned char * pb_CycleMode;
+-	unsigned char * pb_Enable;
+-	unsigned char * pb_InterruptEnable;
++	unsigned char *pb_TimingUnit;
++	unsigned int *pul_TimingInterval;
++	unsigned char *pb_InputMode;
++	unsigned char *pb_ExternGate;
++	unsigned char *pb_CycleMode;
++	unsigned char *pb_Enable;
++	unsigned char *pb_InterruptEnable;
+ 
+ 	i_ReturnValue = insn->n;
+ 	b_ModulNbr = CR_AREF(insn->chanspec);
+@@ -1700,8 +1700,8 @@ int i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_Status;
+@@ -1711,8 +1711,8 @@ int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device
+ 	unsigned char b_TorCounter;
+ 	unsigned char b_ReadType;
+ 	unsigned int ui_TimeOut;
+-	unsigned char * pb_TorCounterStatus;
+-	unsigned int * pul_TorCounterValue;
++	unsigned char *pb_TorCounterStatus;
++	unsigned int *pul_TorCounterValue;
+ 
+ 	i_ReturnValue = insn->n;
+ 	b_ModulNbr = CR_AREF(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+index 1b8f5dfdd4c7..c7680fe3f6c4 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+@@ -100,8 +100,8 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InsnConfigInitTTLIO(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnConfigInitTTLIO(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned char b_ModulNbr;
+@@ -406,8 +406,8 @@ APCI1710_TTL_READCHANNEL
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InsnBitsReadTTLIO(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnBitsReadTTLIO(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_StatusReg;
+@@ -415,8 +415,8 @@ int i_APCI1710_InsnBitsReadTTLIO(struct comedi_device * dev, struct comedi_subde
+ 	unsigned char b_SelectedPort;
+ 	unsigned char b_InputChannel;
+ 	unsigned char b_ReadType;
+-	unsigned char * pb_ChannelStatus;
+-	unsigned char * pb_PortValue;
++	unsigned char *pb_ChannelStatus;
++	unsigned char *pb_PortValue;
+ 
+ 	i_ReturnValue = insn->n;
+ 	b_ReadType = (unsigned char) data[0];
+@@ -655,13 +655,13 @@ int i_APCI1710_InsnBitsReadTTLIO(struct comedi_device * dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_StatusReg;
+ 	unsigned char b_ModulNbr;
+-	unsigned int * pul_PortValue;
++	unsigned int *pul_PortValue;
+ 
+ 	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+ 	i_ReturnValue = insn->n;
+@@ -825,8 +825,8 @@ int i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,struct comedi
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int dw_StatusReg = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
+index fe7c8e1d0586..090084556a95 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
+@@ -68,7 +68,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ 
+ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 	unsigned int dw_PCIBoardEepromAddress,
+-	unsigned short w_EepromStartAddress, unsigned short * pw_DataRead)
++	unsigned short w_EepromStartAddress, unsigned short *pw_DataRead)
+ {
+ 	unsigned int dw_eeprom_busy = 0;
+ 	int i_Counter = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h
+index 1e5ddd4516aa..622a4ac2b799 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h
+@@ -24,4 +24,4 @@
+ 
+ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 			      unsigned int dw_PCIBoardEepromAddress,
+-			      unsigned short w_EepromStartAddress, unsigned short * pw_DataRead);
++			      unsigned short w_EepromStartAddress, unsigned short *pw_DataRead);
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+index 38cd7cf79b7f..a35f299f2a22 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+@@ -2559,7 +2559,7 @@ COMEDI_PCI_INITCLEANUP(driver_addi, addi_apci_tbl);
+ +----------------------------------------------------------------------------+
+ */
+ 
+-static int i_ADDI_Attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int ret, pages, i, n_subdevices;
+@@ -2926,7 +2926,7 @@ static int i_ADDI_Attach(struct comedi_device * dev, struct comedi_devconfig * i
+ +----------------------------------------------------------------------------+
+ */
+ 
+-static int i_ADDI_Detach(struct comedi_device * dev)
++static int i_ADDI_Detach(struct comedi_device *dev)
+ {
+ 
+ 	if (dev->private) {
+@@ -2992,7 +2992,7 @@ static int i_ADDI_Detach(struct comedi_device * dev)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-static int i_ADDI_Reset(struct comedi_device * dev)
++static int i_ADDI_Reset(struct comedi_device *dev)
+ {
+ 
+ 	this_board->i_hwdrv_Reset(dev);
+@@ -3046,8 +3046,8 @@ static irqreturn_t v_ADDI_Interrupt(int irq, void *d)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-static int i_ADDIDATA_InsnReadEeprom(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned short w_Data;
+ 	unsigned short w_Address;
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+index 0640a05339a3..edd657b902aa 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+@@ -362,7 +362,7 @@ struct addi_private {
+ 	unsigned int ui_AiNbrofChannels;	/*  how many channels is measured */
+ 	unsigned int ui_AiScanLength;	/*  Length of actual scanlist */
+ 	unsigned int ui_AiActualScanPosition;	/*  position in actual scan */
+-	unsigned int * pui_AiChannelList;	/*  actual chanlist */
++	unsigned int *pui_AiChannelList;	/*  actual chanlist */
+ 	unsigned int ui_AiChannelList[32];	/*  actual chanlist */
+ 	unsigned char b_AiChannelConfiguration[32];	/*  actual chanlist */
+ 	unsigned int ui_AiReadData[32];
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+index 1de291750736..3aa20928e670 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+@@ -152,7 +152,7 @@ void v_EepromClock76(unsigned int dw_Address, unsigned int dw_RegisterValue);
+ void v_EepromWaitBusy(unsigned short w_PCIBoardEepromAddress);
+ void v_EepromSendCommand76(unsigned int dw_Address, unsigned int dw_EepromCommand,
+ 	unsigned char b_DataLengthInBits);
+-void v_EepromCs76Read(unsigned int dw_Address, unsigned short w_offset, unsigned short * pw_Value);
++void v_EepromCs76Read(unsigned int dw_Address, unsigned short w_offset, unsigned short *pw_Value);
+ 
+ /*
+ +----------------------------------------------------------------------------+
+@@ -652,7 +652,7 @@ void v_EepromSendCommand76(unsigned int dw_Address, unsigned int dw_EepromComman
+ 
+ */
+ 
+-void v_EepromCs76Read(unsigned int dw_Address, unsigned short w_offset, unsigned short * pw_Value)
++void v_EepromCs76Read(unsigned int dw_Address, unsigned short w_offset, unsigned short *pw_Value)
+ {
+ 
+         char c_BitPos = 0;
+@@ -985,7 +985,7 @@ int i_EepromReadDigitalInputHeader(unsigned short w_PCIBoardEepromAddress,
+ */
+ int i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+-	struct str_DigitalOutputHeader * s_Header)
++	struct str_DigitalOutputHeader *s_Header)
+ {
+ /* Read Nbr channels */
+ 	s_Header->w_Nchannel =
+@@ -1016,7 +1016,7 @@ int i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ */
+ int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+-	struct str_TimerMainHeader * s_Header)
++	struct str_TimerMainHeader *s_Header)
+ {
+ 
+ 	unsigned short i, w_Size = 0, w_Temp;
+@@ -1120,7 +1120,7 @@ int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ /* Reads only for ONE  hardware component */
+ int i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+-	struct str_AnalogInputHeader * s_Header)
++	struct str_AnalogInputHeader *s_Header)
+ {
+ 	unsigned short w_Temp, w_Offset;
+ 	w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+index 502aaeaa8020..176bd868a2b4 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+@@ -56,7 +56,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ #include "APCI1710_Pwm.c"
+ #include "APCI1710_INCCPT.c"
+ 
+-void i_ADDI_AttachPCI1710(struct comedi_device * dev)
++void i_ADDI_AttachPCI1710(struct comedi_device *dev)
+ {
+ 	struct comedi_subdevice *s;
+ 	int ret = 0;
+@@ -195,11 +195,11 @@ void i_ADDI_AttachPCI1710(struct comedi_device * dev)
+ 	s->insn_bits = i_APCI1710_InsnBitsINCCPT;
+ }
+ 
+-int i_APCI1710_Reset(struct comedi_device * dev);
++int i_APCI1710_Reset(struct comedi_device *dev);
+ void v_APCI1710_Interrupt(int irq, void *d);
+ /* for 1710 */
+ 
+-int i_APCI1710_Reset(struct comedi_device * dev)
++int i_APCI1710_Reset(struct comedi_device *dev)
+ {
+ 	int ret;
+ 	unsigned int dw_Dummy;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
+index e9c7a3c1c39f..ea4cac504b5d 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
+@@ -109,8 +109,8 @@ int i_Flag = 1;
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI035_ConfigTimerWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI035_ConfigTimerWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_Status = 0;
+ 	unsigned int ui_Command = 0;
+@@ -278,8 +278,8 @@ int i_APCI035_ConfigTimerWatchdog(struct comedi_device * dev, struct comedi_subd
+ |					                                                 |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_Command = 0;
+ 	int i_Count = 0;
+@@ -393,8 +393,8 @@ int i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device * dev,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI035_ReadTimerWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI035_ReadTimerWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_Status = 0;	/*  Status register */
+ 	i_WatchdogNbr = insn->unused[0];
+@@ -449,8 +449,8 @@ int i_APCI035_ReadTimerWatchdog(struct comedi_device * dev, struct comedi_subdev
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI035_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI035_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	devpriv->tsk_Current = current;
+ 	outl(0x200 | 0, devpriv->iobase + 128 + 0x4);
+@@ -486,8 +486,8 @@ int i_APCI035_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subdev
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI035_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI035_ReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_CommandRegister = 0;
+ /******************/
+@@ -521,7 +521,7 @@ int i_APCI035_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevic
+ |			                                                                 |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI035_Reset(struct comedi_device * dev)
++int i_APCI035_Reset(struct comedi_device *dev)
+ {
+ 	int i_Count = 0;
+ 	for (i_Count = 1; i_Count <= 4; i_Count++) {
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+index 0966ad6214a5..4df4812e70b8 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+@@ -84,8 +84,8 @@ unsigned int ui_InterruptStatus = 0;
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1032_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1032_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_TmpValue;
+ 
+@@ -144,8 +144,8 @@ int i_APCI1032_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subd
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1032_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1032_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_TmpValue = 0;
+ 	unsigned int ui_Channel;
+@@ -185,8 +185,8 @@ int i_APCI1032_Read1DigitalInput(struct comedi_device * dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1032_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1032_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_PortValue = data[0];
+ 	unsigned int ui_Mask = 0;
+@@ -277,7 +277,7 @@ static void v_APCI1032_Interrupt(int irq, void *d)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1032_Reset(struct comedi_device * dev)
++int i_APCI1032_Reset(struct comedi_device *dev)
+ {
+ 	outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);	/* disable the interrupts */
+ 	inl(devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_STATUS);	/* Reset the interrupt status register */
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+index 8f2cae90be79..da0e6dd8a171 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+@@ -137,8 +137,8 @@ int i_TimerCounter1Enabled = 0, i_TimerCounter2Enabled =
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_PatternPolarity = 0, i_PatternTransition = 0, i_PatternMask = 0;
+ 	int i_MaxChannel = 0, i_Count = 0, i_EventMask = 0;
+@@ -519,8 +519,8 @@ int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device * dev,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1500_StartStopInputEvent(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1500_StartStopInputEvent(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_Event1InterruptStatus = 0, i_Event2InterruptStatus =
+ 		0, i_RegValue;
+@@ -784,8 +784,8 @@ int i_APCI1500_StartStopInputEvent(struct comedi_device * dev, struct comedi_sub
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1500_Initialisation(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1500_Initialisation(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_DummyRead = 0;
+     /******************/
+@@ -957,8 +957,8 @@ int i_APCI1500_Initialisation(struct comedi_device * dev, struct comedi_subdevic
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1500_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1500_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_PortValue = data[1];
+ 	unsigned int ui_Mask = 0;
+@@ -1040,8 +1040,8 @@ int i_APCI1500_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	devpriv->b_OutputMemoryStatus = data[0];
+ 	return insn->n;
+@@ -1067,8 +1067,8 @@ int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1500_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1500_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	static unsigned int ui_Temp = 0;
+ 	unsigned int ui_Temp1;
+@@ -1261,8 +1261,8 @@ int i_APCI1500_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_TimerCounterMode, i_MasterConfiguration;
+ 
+@@ -1860,8 +1860,8 @@ int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device * dev,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_CommandAndStatusValue;
+ 
+@@ -2182,8 +2182,8 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_CommandAndStatusValue;
+ 	switch (data[0]) {
+@@ -2370,8 +2370,8 @@ int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device * dev,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1500_ReadInterruptMask(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1500_ReadInterruptMask(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[0] = i_InterruptMask;
+ 	data[1] = i_InputChannel;
+@@ -2401,8 +2401,8 @@ int i_APCI1500_ReadInterruptMask(struct comedi_device * dev, struct comedi_subde
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1500_ConfigureInterrupt(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1500_ConfigureInterrupt(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_Status;
+ 	int i_RegValue;
+@@ -2822,7 +2822,7 @@ static void v_APCI1500_Interrupt(int irq, void *d)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1500_Reset(struct comedi_device * dev)
++int i_APCI1500_Reset(struct comedi_device *dev)
+ {
+ 	int i_DummyRead = 0;
+ 	i_TimerCounter1Init = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
+index bcc9b7a67f2e..dc2a1a9b41c0 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
+@@ -73,8 +73,8 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1516_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1516_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_TmpValue = 0;
+ 	unsigned int ui_Channel;
+@@ -114,8 +114,8 @@ int i_APCI1516_Read1DigitalInput(struct comedi_device * dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1516_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1516_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	unsigned int ui_PortValue = data[0];
+@@ -171,8 +171,8 @@ int i_APCI1516_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1516_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1516_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	devpriv->b_OutputMemoryStatus = data[0];
+ 	return insn->n;
+@@ -199,8 +199,8 @@ int i_APCI1516_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1516_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1516_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_Temp, ui_Temp1;
+ 	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	/*  get the channel */
+@@ -359,8 +359,8 @@ int i_APCI1516_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1516_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1516_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	unsigned int ui_Temp;
+@@ -419,8 +419,8 @@ int i_APCI1516_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1516_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1516_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (data[0] == 0) {
+ 		/* Disable the watchdog */
+@@ -465,8 +465,8 @@ int i_APCI1516_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevic
+     +----------------------------------------------------------------------------+
+   */
+ 
+-int i_APCI1516_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1516_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	switch (data[0]) {
+ 	case 0:		/* stop the watchdog */
+@@ -510,8 +510,8 @@ int i_APCI1516_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1516_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1516_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[0] = inw(devpriv->i_IobaseAddon + APCI1516_WATCHDOG_STATUS) & 0x1;
+ 	return insn->n;
+@@ -532,7 +532,7 @@ int i_APCI1516_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1516_Reset(struct comedi_device * dev)
++int i_APCI1516_Reset(struct comedi_device *dev)
+ {
+ 	outw(0x0, devpriv->iobase + APCI1516_DIGITAL_OP);	/* RESETS THE DIGITAL OUTPUTS */
+ 	outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_ENABLEDISABLE);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+index 304079bbb80a..f90e9605c9bc 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+@@ -86,8 +86,8 @@ unsigned int ui_InterruptData, ui_Type;
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1564_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1564_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	devpriv->tsk_Current = current;
+    /*******************************/
+@@ -147,8 +147,8 @@ int i_APCI1564_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subd
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1564_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1564_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_TmpValue = 0;
+ 	unsigned int ui_Channel;
+@@ -189,8 +189,8 @@ int i_APCI1564_Read1DigitalInput(struct comedi_device * dev, struct comedi_subde
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1564_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1564_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_PortValue = data[0];
+ 	unsigned int ui_Mask = 0;
+@@ -257,8 +257,8 @@ int i_APCI1564_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1564_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1564_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ul_Command = 0;
+ 
+@@ -314,8 +314,8 @@ int i_APCI1564_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1564_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1564_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_Temp, ui_Temp1;
+ 	unsigned int ui_NoOfChannel;
+@@ -488,8 +488,8 @@ int i_APCI1564_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1564_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1564_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_Temp;
+ 	unsigned int ui_NoOfChannel;
+@@ -566,8 +566,8 @@ int i_APCI1564_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ul_Command1 = 0;
+ 	devpriv->tsk_Current = current;
+@@ -720,8 +720,8 @@ int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ul_Command1 = 0;
+ 	if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+@@ -815,8 +815,8 @@ int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ul_Command1 = 0;
+ 
+@@ -894,8 +894,8 @@ int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1564_ReadInterruptStatus(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI1564_ReadInterruptStatus(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	*data = ui_Type;
+ 	return insn->n;
+@@ -1083,7 +1083,7 @@ static void v_APCI1564_Interrupt(int irq, void *d)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1564_Reset(struct comedi_device * dev)
++int i_APCI1564_Reset(struct comedi_device *dev)
+ {
+ 	outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_IRQ);	/* disable the interrupts */
+ 	inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_STATUS);	/* Reset the interrupt status register */
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
+index b22739a6c9a6..1261801d0b83 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
+@@ -90,8 +90,8 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = insn->n;
+ 	unsigned char b_Command = 0;
+@@ -283,8 +283,8 @@ int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = insn->n;
+ 	unsigned char b_Command = 0;
+@@ -430,8 +430,8 @@ int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned char b_Command = (unsigned char) CR_AREF(insn->chanspec);
+ 	int i_ReturnValue = insn->n;
+@@ -570,8 +570,8 @@ int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = insn->n;
+ 	unsigned char b_Command = 0;
+@@ -774,7 +774,7 @@ int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI16XX_Reset(struct comedi_device * dev)
++int i_APCI16XX_Reset(struct comedi_device *dev)
+ {
+ 	return 0;
+ }
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
+index 1969e8df7378..58ff5df037e0 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
+@@ -75,8 +75,8 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI2016_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI2016_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if ((data[0] != 0) && (data[0] != 1)) {
+ 		comedi_error(dev,
+@@ -111,8 +111,8 @@ int i_APCI2016_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI2016_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI2016_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_NoOfChannel;
+ 	unsigned int ui_Temp, ui_Temp1;
+@@ -266,8 +266,8 @@ int i_APCI2016_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI2016_BitsDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI2016_BitsDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_Temp;
+ 	unsigned int ui_NoOfChannel;
+@@ -337,8 +337,8 @@ int i_APCI2016_BitsDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI2016_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI2016_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	if (data[0] == 0) {
+@@ -380,8 +380,8 @@ int i_APCI2016_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevic
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI2016_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI2016_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	switch (data[0]) {
+@@ -427,8 +427,8 @@ int i_APCI2016_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI2016_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI2016_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	udelay(5);
+ 	data[0] = inw(devpriv->i_IobaseAddon + APCI2016_WATCHDOG_STATUS) & 0x1;
+@@ -450,7 +450,7 @@ int i_APCI2016_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI2016_Reset(struct comedi_device * dev)
++int i_APCI2016_Reset(struct comedi_device *dev)
+ {
+ 	outw(0x0, devpriv->iobase + APCI2016_DIGITAL_OP);	/*  Resets the digital output channels */
+ 	outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_ENABLEDISABLE);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
+index c2580c6e0d4d..ad91b7b4a5c0 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
+@@ -79,8 +79,8 @@ unsigned int ui_InterruptData, ui_Type;
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI2032_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI2032_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ul_Command = 0;
+ 	devpriv->tsk_Current = current;
+@@ -134,8 +134,8 @@ int i_APCI2032_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI2032_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI2032_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_Temp, ui_Temp1;
+ 	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	/*  get the channel */
+@@ -313,8 +313,8 @@ int i_APCI2032_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI2032_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI2032_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_Temp;
+ 	unsigned int ui_NoOfChannel;
+@@ -380,8 +380,8 @@ int i_APCI2032_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI2032_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI2032_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (data[0] == 0) {
+ 		/* Disable the watchdog */
+@@ -421,8 +421,8 @@ int i_APCI2032_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevic
+     +----------------------------------------------------------------------------+
+   */
+ 
+-int i_APCI2032_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI2032_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	switch (data[0]) {
+ 	case 0:		/* stop the watchdog */
+@@ -466,8 +466,8 @@ int i_APCI2032_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI2032_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI2032_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	data[0] =
+@@ -544,8 +544,8 @@ void v_APCI2032_Interrupt(int irq, void *d)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI2032_ReadInterruptStatus(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI2032_ReadInterruptStatus(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	*data = ui_Type;
+ 	return insn->n;
+@@ -567,7 +567,7 @@ int i_APCI2032_ReadInterruptStatus(struct comedi_device * dev, struct comedi_sub
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI2032_Reset(struct comedi_device * dev)
++int i_APCI2032_Reset(struct comedi_device *dev)
+ {
+ 	devpriv->b_DigitalOutputRegister = 0;
+ 	ui_Type = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
+index 530629bcdaca..c03192b5d9a0 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
+@@ -73,8 +73,8 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI2200_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI2200_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_TmpValue = 0;
+ 	unsigned int ui_Channel;
+@@ -112,8 +112,8 @@ int i_APCI2200_Read1DigitalInput(struct comedi_device * dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI2200_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI2200_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	unsigned int ui_PortValue = data[0];
+@@ -169,8 +169,8 @@ int i_APCI2200_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI2200_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI2200_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	devpriv->b_OutputMemoryStatus = data[0];
+ 	return insn->n;
+@@ -197,8 +197,8 @@ int i_APCI2200_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI2200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI2200_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_Temp, ui_Temp1;
+ 	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	/*  get the channel */
+@@ -354,8 +354,8 @@ int i_APCI2200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI2200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI2200_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	unsigned int ui_Temp;
+@@ -418,8 +418,8 @@ int i_APCI2200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI2200_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI2200_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (data[0] == 0) {
+ 		/* Disable the watchdog */
+@@ -464,8 +464,8 @@ int i_APCI2200_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevic
+     +----------------------------------------------------------------------------+
+   */
+ 
+-int i_APCI2200_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI2200_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	switch (data[0]) {
+ 	case 0:		/* stop the watchdog */
+@@ -509,8 +509,8 @@ int i_APCI2200_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI2200_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI2200_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[0] =
+ 		inw(devpriv->iobase + APCI2200_WATCHDOG +
+@@ -533,7 +533,7 @@ int i_APCI2200_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI2200_Reset(struct comedi_device * dev)
++int i_APCI2200_Reset(struct comedi_device *dev)
+ {
+ 	outw(0x0, devpriv->iobase + APCI2200_DIGITAL_OP);	/* RESETS THE DIGITAL OUTPUTS */
+ 	outw(0x0,
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+index 4808acbebd8c..e4b1c09f0e49 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+@@ -74,8 +74,8 @@ static unsigned int ui_Temp = 0;
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_InsnConfigAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI3120_InsnConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int i;
+ 
+@@ -145,8 +145,8 @@ int i_APCI3120_InsnConfigAnalogInput(struct comedi_device * dev, struct comedi_s
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned short us_ConvertTiming, us_TmpValue, i;
+ 	unsigned char b_Tmp;
+@@ -412,7 +412,7 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_sub
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_StopCyclicAcquisition(struct comedi_device * dev, struct comedi_subdevice * s)
++int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	/*  Disable A2P Fifo write and AMWEN signal */
+ 	outw(0, devpriv->i_IobaseAddon + 4);
+@@ -482,8 +482,8 @@ int i_APCI3120_StopCyclicAcquisition(struct comedi_device * dev, struct comedi_s
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;		/*  divisor1,divisor2; */
+@@ -639,7 +639,7 @@ int i_APCI3120_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_CommandAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s)
++int i_APCI3120_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+ 
+@@ -713,8 +713,8 @@ int i_APCI3120_CommandAnalogInput(struct comedi_device * dev, struct comedi_subd
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+-	struct comedi_subdevice * s)
++int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device *dev,
++	struct comedi_subdevice *s)
+ {
+ 	unsigned char b_Tmp;
+ 	unsigned int ui_Tmp, ui_DelayTiming = 0, ui_TimerValue1 = 0, dmalen0 =
+@@ -1250,7 +1250,7 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_Reset(struct comedi_device * dev)
++int i_APCI3120_Reset(struct comedi_device *dev)
+ {
+ 	unsigned int i;
+ 	unsigned short us_TmpValue;
+@@ -1330,7 +1330,7 @@ int i_APCI3120_Reset(struct comedi_device * dev)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_SetupChannelList(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI3120_SetupChannelList(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	int n_chan, unsigned int *chanlist, char check)
+ {
+ 	unsigned int i;		/* , differencial=0, bipolar=0; */
+@@ -1394,7 +1394,7 @@ int i_APCI3120_SetupChannelList(struct comedi_device * dev, struct comedi_subdev
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_ExttrigEnable(struct comedi_device * dev)
++int i_APCI3120_ExttrigEnable(struct comedi_device *dev)
+ {
+ 
+ 	devpriv->us_OutputRegister |= APCI3120_ENABLE_EXT_TRIGGER;
+@@ -1419,7 +1419,7 @@ int i_APCI3120_ExttrigEnable(struct comedi_device * dev)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_ExttrigDisable(struct comedi_device * dev)
++int i_APCI3120_ExttrigDisable(struct comedi_device *dev)
+ {
+ 	devpriv->us_OutputRegister &= ~APCI3120_ENABLE_EXT_TRIGGER;
+ 	outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
+@@ -1665,7 +1665,7 @@ void v_APCI3120_Interrupt(int irq, void *d)
+ */
+ 
+ 
+-int i_APCI3120_InterruptHandleEos(struct comedi_device * dev)
++int i_APCI3120_InterruptHandleEos(struct comedi_device *dev)
+ {
+ 	int n_chan, i;
+ 	struct comedi_subdevice *s = dev->subdevices + 0;
+@@ -1877,8 +1877,8 @@ void v_APCI3120_InterruptDma(int irq, void *d)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device * dev,
+-	struct comedi_subdevice * s, short * dma_buffer, unsigned int num_samples)
++void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,
++	struct comedi_subdevice *s, short *dma_buffer, unsigned int num_samples)
+ {
+ 	devpriv->ui_AiActualScan +=
+ 		(s->async->cur_chan + num_samples) / devpriv->ui_AiScanLength;
+@@ -1919,8 +1919,8 @@ void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_InsnConfigTimer(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI3120_InsnConfigTimer(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	unsigned int ui_Timervalue2;
+@@ -2079,8 +2079,8 @@ int i_APCI3120_InsnConfigTimer(struct comedi_device * dev, struct comedi_subdevi
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_InsnWriteTimer(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI3120_InsnWriteTimer(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	unsigned int ui_Timervalue2 = 0;
+@@ -2267,8 +2267,8 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device * dev, struct comedi_subdevic
+ |                    													     |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI3120_InsnReadTimer(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI3120_InsnReadTimer(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned char b_Tmp;
+ 	unsigned short us_TmpValue, us_TmpValue_2, us_StatusValue;
+@@ -2387,8 +2387,8 @@ int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev,
+ |                    													     |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI3120_InsnBitsDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI3120_InsnBitsDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_TmpValue;
+ 	ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI3120_RD_STATUS);
+@@ -2426,8 +2426,8 @@ int i_APCI3120_InsnBitsDigitalInput(struct comedi_device * dev, struct comedi_su
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	if ((data[0] != 0) && (data[0] != 1)) {
+@@ -2472,7 +2472,7 @@ int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device * dev,
++int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device *dev,
+ 				     struct comedi_subdevice *s,
+ 				     struct comedi_insn *insn,
+ 				     unsigned int *data)
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+index 8981b0feaba7..b6b075007787 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+@@ -112,7 +112,7 @@ struct str_BoardInfos s_BoardInfos[100];	/*  100 will be the max number of board
+ 
+ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 	unsigned int dw_PCIBoardEepromAddress,
+-	unsigned short w_EepromStartAddress, unsigned short * pw_DataRead)
++	unsigned short w_EepromStartAddress, unsigned short *pw_DataRead)
+ {
+ 	unsigned int dw_eeprom_busy = 0;
+ 	int i_Counter = 0;
+@@ -453,9 +453,9 @@ void v_GetAPCI3200EepromCalibrationValue(unsigned int dw_PCIBoardEepromAddress,
+ 	}
+ }
+ 
+-int i_APCI3200_GetChannelCalibrationValue(struct comedi_device * dev,
+-	unsigned int ui_Channel_num, unsigned int * CJCCurrentSource,
+-	unsigned int * ChannelCurrentSource, unsigned int * ChannelGainFactor)
++int i_APCI3200_GetChannelCalibrationValue(struct comedi_device *dev,
++	unsigned int ui_Channel_num, unsigned int *CJCCurrentSource,
++	unsigned int *ChannelCurrentSource, unsigned int *ChannelGainFactor)
+ {
+ 	int i_DiffChannel = 0;
+ 	int i_Module = 0;
+@@ -550,8 +550,8 @@ int i_APCI3200_GetChannelCalibrationValue(struct comedi_device * dev,
+   +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3200_ReadDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI3200_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_Temp = 0;
+ 	unsigned int ui_NoOfChannel = 0;
+@@ -608,8 +608,8 @@ int i_APCI3200_ReadDigitalInput(struct comedi_device * dev, struct comedi_subdev
+   |																	 |
+   +----------------------------------------------------------------------------+
+ */
+-int i_APCI3200_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI3200_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	if ((data[0] != 0) && (data[0] != 1)) {
+@@ -653,8 +653,8 @@ int i_APCI3200_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-int i_APCI3200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI3200_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_Temp = 0, ui_Temp1 = 0;
+ 	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	/*  get the channel */
+@@ -766,8 +766,8 @@ int i_APCI3200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-int i_APCI3200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI3200_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_Temp;
+ 	unsigned int ui_NoOfChannel;
+@@ -874,8 +874,8 @@ int i_APCI3200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-int i_APCI3200_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI3200_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	unsigned int ul_Config = 0, ul_Temp = 0;
+@@ -1361,8 +1361,8 @@ int i_APCI3200_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subde
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-int i_APCI3200_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI3200_ReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_DummyValue = 0;
+ 	int i_ConvertCJCCalibration;
+@@ -1651,8 +1651,8 @@ int i_APCI3200_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevi
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-int i_APCI3200_Read1AnalogInputChannel(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI3200_Read1AnalogInputChannel(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_EOC = 0;
+ 	unsigned int ui_ChannelNo = 0;
+@@ -1776,7 +1776,7 @@ int i_APCI3200_Read1AnalogInputChannel(struct comedi_device * dev,
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device * dev, unsigned int * data)
++int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device *dev, unsigned int *data)
+ {
+ 	unsigned int ui_Temp = 0, ui_EOC = 0;
+ 	unsigned int ui_CommandRegister = 0;
+@@ -1912,7 +1912,7 @@ int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device * dev, unsigned i
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-int i_APCI3200_ReadCalibrationGainValue(struct comedi_device * dev, unsigned int * data)
++int i_APCI3200_ReadCalibrationGainValue(struct comedi_device *dev, unsigned int *data)
+ {
+ 	unsigned int ui_EOC = 0;
+ 	int ui_CommandRegister = 0;
+@@ -2048,7 +2048,7 @@ int i_APCI3200_ReadCalibrationGainValue(struct comedi_device * dev, unsigned int
+   +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3200_ReadCJCValue(struct comedi_device * dev, unsigned int * data)
++int i_APCI3200_ReadCJCValue(struct comedi_device *dev, unsigned int *data)
+ {
+ 	unsigned int ui_EOC = 0;
+ 	int ui_CommandRegister = 0;
+@@ -2167,7 +2167,7 @@ int i_APCI3200_ReadCJCValue(struct comedi_device * dev, unsigned int * data)
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-int i_APCI3200_ReadCJCCalOffset(struct comedi_device * dev, unsigned int * data)
++int i_APCI3200_ReadCJCCalOffset(struct comedi_device *dev, unsigned int *data)
+ {
+ 	unsigned int ui_EOC = 0;
+ 	int ui_CommandRegister = 0;
+@@ -2283,7 +2283,7 @@ int i_APCI3200_ReadCJCCalOffset(struct comedi_device * dev, unsigned int * data)
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-int i_APCI3200_ReadCJCCalGain(struct comedi_device * dev, unsigned int * data)
++int i_APCI3200_ReadCJCCalGain(struct comedi_device *dev, unsigned int *data)
+ {
+ 	unsigned int ui_EOC = 0;
+ 	int ui_CommandRegister = 0;
+@@ -2404,8 +2404,8 @@ int i_APCI3200_ReadCJCCalGain(struct comedi_device * dev, unsigned int * data)
+   +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_Configuration = 0;
+ 	int i_Temp;		/* ,i_TimeUnit; */
+@@ -2529,8 +2529,8 @@ int i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device * dev,
+   +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	i_APCI3200_Reset(dev);
+ 	return insn->n;
+@@ -2560,8 +2560,8 @@ int i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device * dev,
+   +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3200_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++int i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 
+ 	int err = 0;
+@@ -2764,7 +2764,7 @@ int i_APCI3200_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_
+   +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3200_StopCyclicAcquisition(struct comedi_device * dev, struct comedi_subdevice * s)
++int i_APCI3200_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	unsigned int ui_Configuration = 0;
+ 	/* i_InterruptFlag=0; */
+@@ -2814,7 +2814,7 @@ int i_APCI3200_StopCyclicAcquisition(struct comedi_device * dev, struct comedi_s
+   +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3200_CommandAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s)
++int i_APCI3200_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned int ui_Configuration = 0;
+@@ -3001,7 +3001,7 @@ int i_APCI3200_CommandAnalogInput(struct comedi_device * dev, struct comedi_subd
+   +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3200_Reset(struct comedi_device * dev)
++int i_APCI3200_Reset(struct comedi_device *dev)
+ {
+ 	int i_Temp;
+ 	unsigned int dw_Dummy;
+@@ -3499,7 +3499,7 @@ void v_APCI3200_Interrupt(int irq, void *d)
+   |                    													     |
+   +----------------------------------------------------------------------------+
+ */
+-int i_APCI3200_InterruptHandleEos(struct comedi_device * dev)
++int i_APCI3200_InterruptHandleEos(struct comedi_device *dev)
+ {
+ 	unsigned int ui_StatusRegister = 0;
+ 	struct comedi_subdevice *s = dev->subdevices + 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
+index dfca2e6d4d8c..20460e2382a9 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
+@@ -73,8 +73,8 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3501_ReadDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI3501_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_Temp;
+ 	unsigned int ui_NoOfChannel;
+@@ -121,8 +121,8 @@ int i_APCI3501_ReadDigitalInput(struct comedi_device * dev, struct comedi_subdev
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI3501_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI3501_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	if ((data[0] != 0) && (data[0] != 1)) {
+@@ -161,8 +161,8 @@ int i_APCI3501_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI3501_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI3501_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_Temp, ui_Temp1;
+ 	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	/*  get the channel */
+@@ -248,8 +248,8 @@ int i_APCI3501_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI3501_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI3501_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ui_Temp;
+ 	unsigned int ui_NoOfChannel;
+@@ -298,8 +298,8 @@ int i_APCI3501_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI3501_ConfigAnalogOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI3501_ConfigAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	outl(data[0],
+ 		devpriv->iobase + APCI3501_ANALOG_OUTPUT +
+@@ -336,8 +336,8 @@ int i_APCI3501_ConfigAnalogOutput(struct comedi_device * dev, struct comedi_subd
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI3501_WriteAnalogOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++int i_APCI3501_WriteAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ul_Command1 = 0, ul_Channel_no, ul_Polarity, ul_DAC_Ready = 0;;
+ 
+@@ -410,8 +410,8 @@ int i_APCI3501_WriteAnalogOutput(struct comedi_device * dev, struct comedi_subde
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ul_Command1 = 0;
+ 	devpriv->tsk_Current = current;
+@@ -511,8 +511,8 @@ int i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int ul_Command1 = 0;
+ 	int i_Temp;
+@@ -613,8 +613,8 @@ int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+@@ -654,7 +654,7 @@ int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3501_Reset(struct comedi_device * dev)
++int i_APCI3501_Reset(struct comedi_device *dev)
+ {
+ 	int i_Count = 0, i_temp = 0;
+ 	unsigned int ul_Command1 = 0, ul_Polarity, ul_DAC_Ready = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+index 8c630d72ad41..a908603e7e0e 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+@@ -68,7 +68,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3XXX_TestConversionStarted(struct comedi_device * dev)
++int i_APCI3XXX_TestConversionStarted(struct comedi_device *dev)
+ {
+ 	if ((readl((void *)(devpriv->dw_AiBase + 8)) & 0x80000UL) == 0x80000UL) {
+ 		return (1);
+@@ -105,8 +105,8 @@ int i_APCI3XXX_TestConversionStarted(struct comedi_device * dev)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = insn->n;
+ 	unsigned char b_TimeBase = 0;
+@@ -295,8 +295,8 @@ int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3XXX_InsnConfigAnalogInput(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI3XXX_InsnConfigAnalogInput(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = insn->n;
+ 
+@@ -355,8 +355,8 @@ int i_APCI3XXX_InsnConfigAnalogInput(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = insn->n;
+ 	unsigned char b_Configuration = (unsigned char) CR_RANGE(insn->chanspec);
+@@ -684,8 +684,8 @@ void v_APCI3XXX_Interrupt(int irq, void *d)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned char b_Range = (unsigned char) CR_RANGE(insn->chanspec);
+ 	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
+@@ -791,8 +791,8 @@ int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = insn->n;
+ 	unsigned char b_Command = 0;
+@@ -919,8 +919,8 @@ int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = insn->n;
+ 	unsigned char b_ChannelCpt = 0;
+@@ -1074,8 +1074,8 @@ int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3XXX_InsnReadTTLIO(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI3XXX_InsnReadTTLIO(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
+ 	int i_ReturnValue = insn->n;
+@@ -1187,8 +1187,8 @@ int i_APCI3XXX_InsnReadTTLIO(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = insn->n;
+ 	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
+@@ -1298,8 +1298,8 @@ int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = insn->n;
+ 	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
+@@ -1356,8 +1356,8 @@ int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device * dev,
+ |                    -101 : Data size error                                  |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI3XXX_InsnBitsDigitalInput(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI3XXX_InsnBitsDigitalInput(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = insn->n;
+ 	unsigned int dw_Temp = 0;
+@@ -1409,8 +1409,8 @@ int i_APCI3XXX_InsnBitsDigitalInput(struct comedi_device * dev,
+ |                    -101 : Data size error                                  |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI3XXX_InsnBitsDigitalOutput(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI3XXX_InsnBitsDigitalOutput(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = insn->n;
+ 	unsigned char b_ChannelCpt = 0;
+@@ -1505,8 +1505,8 @@ int i_APCI3XXX_InsnBitsDigitalOutput(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = insn->n;
+ 	unsigned char b_Channel = CR_CHAN(insn->chanspec);
+@@ -1580,8 +1580,8 @@ int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3XXX_InsnReadDigitalOutput(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++int i_APCI3XXX_InsnReadDigitalOutput(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i_ReturnValue = insn->n;
+ 	unsigned char b_Channel = CR_CHAN(insn->chanspec);
+@@ -1638,7 +1638,7 @@ int i_APCI3XXX_InsnReadDigitalOutput(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3XXX_Reset(struct comedi_device * dev)
++int i_APCI3XXX_Reset(struct comedi_device *dev)
+ {
+ 	unsigned char b_Cpt = 0;
+ 
+diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c
+index 7e27f92a9e6d..ad96114e359d 100644
+--- a/drivers/staging/comedi/drivers/adl_pci6208.c
++++ b/drivers/staging/comedi/drivers/adl_pci6208.c
+@@ -107,8 +107,8 @@ struct pci6208_private {
+ 
+ #define devpriv ((struct pci6208_private *)dev->private)
+ 
+-static int pci6208_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pci6208_detach(struct comedi_device * dev);
++static int pci6208_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pci6208_detach(struct comedi_device *dev);
+ 
+ #define pci6208_board_nbr \
+ 	(sizeof(pci6208_boards) / sizeof(struct pci6208_board))
+@@ -122,16 +122,16 @@ static struct comedi_driver driver_pci6208 = {
+ 
+ COMEDI_PCI_INITCLEANUP(driver_pci6208, pci6208_pci_table);
+ 
+-static int pci6208_find_device(struct comedi_device * dev, int bus, int slot);
++static int pci6208_find_device(struct comedi_device *dev, int bus, int slot);
+ static int
+ pci6208_pci_setup(struct pci_dev *pci_dev, unsigned long *io_base_ptr,
+ 	int dev_minor);
+ 
+ /*read/write functions*/
+-static int pci6208_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int pci6208_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int pci6208_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int pci6208_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ /* static int pci6208_dio_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, */
+ /* struct comedi_insn *insn,unsigned int *data); */
+ /* static int pci6208_dio_insn_config(struct comedi_device *dev,struct comedi_subdevice *s, */
+@@ -143,7 +143,7 @@ static int pci6208_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pci6208_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pci6208_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int retval;
+@@ -206,7 +206,7 @@ static int pci6208_attach(struct comedi_device * dev, struct comedi_devconfig *
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int pci6208_detach(struct comedi_device * dev)
++static int pci6208_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: pci6208: remove\n", dev->minor);
+ 
+@@ -220,8 +220,8 @@ static int pci6208_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int pci6208_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci6208_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i = 0, Data_Read;
+ 	unsigned short chan = CR_CHAN(insn->chanspec);
+@@ -245,8 +245,8 @@ static int pci6208_ao_winsn(struct comedi_device * dev, struct comedi_subdevice
+ 
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+-static int pci6208_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci6208_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -306,7 +306,7 @@ static int pci6208_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice
+ /* return 1; */
+ /* } */
+ 
+-static int pci6208_find_device(struct comedi_device * dev, int bus, int slot)
++static int pci6208_find_device(struct comedi_device *dev, int bus, int slot)
+ {
+ 	struct pci_dev *pci_dev;
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/adl_pci7296.c b/drivers/staging/comedi/drivers/adl_pci7296.c
+index 1d9f5ad69722..72b3f4614d06 100644
+--- a/drivers/staging/comedi/drivers/adl_pci7296.c
++++ b/drivers/staging/comedi/drivers/adl_pci7296.c
+@@ -64,8 +64,8 @@ struct adl_pci7296_private {
+ 
+ #define devpriv ((struct adl_pci7296_private *)dev->private)
+ 
+-static int adl_pci7296_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int adl_pci7296_detach(struct comedi_device * dev);
++static int adl_pci7296_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int adl_pci7296_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_adl_pci7296 = {
+       driver_name:"adl_pci7296",
+       module:THIS_MODULE,
+@@ -73,7 +73,7 @@ static struct comedi_driver driver_adl_pci7296 = {
+       detach:adl_pci7296_detach,
+ };
+ 
+-static int adl_pci7296_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int adl_pci7296_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct pci_dev *pcidev;
+ 	struct comedi_subdevice *s;
+@@ -149,7 +149,7 @@ static int adl_pci7296_attach(struct comedi_device * dev, struct comedi_devconfi
+ 	return -EIO;
+ }
+ 
+-static int adl_pci7296_detach(struct comedi_device * dev)
++static int adl_pci7296_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: pci7432: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/adl_pci7432.c b/drivers/staging/comedi/drivers/adl_pci7432.c
+index a8f1715608d1..e20ec2f9904e 100644
+--- a/drivers/staging/comedi/drivers/adl_pci7432.c
++++ b/drivers/staging/comedi/drivers/adl_pci7432.c
+@@ -58,8 +58,8 @@ struct adl_pci7432_private {
+ 
+ #define devpriv ((struct adl_pci7432_private *)dev->private)
+ 
+-static int adl_pci7432_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int adl_pci7432_detach(struct comedi_device * dev);
++static int adl_pci7432_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int adl_pci7432_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_adl_pci7432 = {
+       driver_name:"adl_pci7432",
+       module:THIS_MODULE,
+@@ -69,15 +69,15 @@ static struct comedi_driver driver_adl_pci7432 = {
+ 
+ /* Digital IO */
+ 
+-static int adl_pci7432_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int adl_pci7432_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+-static int adl_pci7432_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int adl_pci7432_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+ /*            */
+ 
+-static int adl_pci7432_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int adl_pci7432_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct pci_dev *pcidev;
+ 	struct comedi_subdevice *s;
+@@ -150,7 +150,7 @@ static int adl_pci7432_attach(struct comedi_device * dev, struct comedi_devconfi
+ 	return -EIO;
+ }
+ 
+-static int adl_pci7432_detach(struct comedi_device * dev)
++static int adl_pci7432_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: pci7432: remove\n", dev->minor);
+ 
+@@ -164,8 +164,8 @@ static int adl_pci7432_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int adl_pci7432_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int adl_pci7432_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	printk("comedi: pci7432_do_insn_bits called\n");
+ 	printk("comedi: data0: %8x data1: %8x\n", data[0], data[1]);
+@@ -184,8 +184,8 @@ static int adl_pci7432_do_insn_bits(struct comedi_device * dev, struct comedi_su
+ 	return 2;
+ }
+ 
+-static int adl_pci7432_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int adl_pci7432_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	printk("comedi: pci7432_di_insn_bits called\n");
+ 	printk("comedi: data0: %8x data1: %8x\n", data[0], data[1]);
+diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c
+index dd376b69bde3..61b8cba40d0c 100644
+--- a/drivers/staging/comedi/drivers/adl_pci8164.c
++++ b/drivers/staging/comedi/drivers/adl_pci8164.c
+@@ -70,8 +70,8 @@ struct adl_pci8164_private {
+ 
+ #define devpriv ((struct adl_pci8164_private *)dev->private)
+ 
+-static int adl_pci8164_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int adl_pci8164_detach(struct comedi_device * dev);
++static int adl_pci8164_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int adl_pci8164_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_adl_pci8164 = {
+       driver_name:"adl_pci8164",
+       module:THIS_MODULE,
+@@ -79,31 +79,31 @@ static struct comedi_driver driver_adl_pci8164 = {
+       detach:adl_pci8164_detach,
+ };
+ 
+-static int adl_pci8164_insn_read_msts(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int adl_pci8164_insn_read_msts(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+-static int adl_pci8164_insn_read_ssts(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int adl_pci8164_insn_read_ssts(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+-static int adl_pci8164_insn_read_buf0(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int adl_pci8164_insn_read_buf0(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+-static int adl_pci8164_insn_read_buf1(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int adl_pci8164_insn_read_buf1(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+-static int adl_pci8164_insn_write_cmd(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int adl_pci8164_insn_write_cmd(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+-static int adl_pci8164_insn_write_otp(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int adl_pci8164_insn_write_otp(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+-static int adl_pci8164_insn_write_buf0(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
++static int adl_pci8164_insn_write_buf0(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
+ 
+-static int adl_pci8164_insn_write_buf1(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
++static int adl_pci8164_insn_write_buf1(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
+ 
+-static int adl_pci8164_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int adl_pci8164_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct pci_dev *pcidev;
+ 	struct comedi_subdevice *s;
+@@ -194,7 +194,7 @@ static int adl_pci8164_attach(struct comedi_device * dev, struct comedi_devconfi
+ 	return -EIO;
+ }
+ 
+-static int adl_pci8164_detach(struct comedi_device * dev)
++static int adl_pci8164_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: pci8164: remove\n", dev->minor);
+ 
+@@ -208,8 +208,8 @@ static int adl_pci8164_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int adl_pci8164_insn_read_msts(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int adl_pci8164_insn_read_msts(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int axis, axis_reg;
+ 	char *axisname;
+@@ -245,8 +245,8 @@ static int adl_pci8164_insn_read_msts(struct comedi_device * dev, struct comedi_
+ 	return 2;
+ }
+ 
+-static int adl_pci8164_insn_read_ssts(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int adl_pci8164_insn_read_ssts(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int axis, axis_reg;
+ 	char *axisname;
+@@ -282,8 +282,8 @@ static int adl_pci8164_insn_read_ssts(struct comedi_device * dev, struct comedi_
+ 	return 2;
+ }
+ 
+-static int adl_pci8164_insn_read_buf0(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int adl_pci8164_insn_read_buf0(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int axis, axis_reg;
+ 	char *axisname;
+@@ -319,8 +319,8 @@ static int adl_pci8164_insn_read_buf0(struct comedi_device * dev, struct comedi_
+ 	return 2;
+ }
+ 
+-static int adl_pci8164_insn_read_buf1(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int adl_pci8164_insn_read_buf1(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int axis, axis_reg;
+ 
+@@ -357,8 +357,8 @@ static int adl_pci8164_insn_read_buf1(struct comedi_device * dev, struct comedi_
+ 	return 2;
+ }
+ 
+-static int adl_pci8164_insn_write_cmd(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int adl_pci8164_insn_write_cmd(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int axis, axis_reg;
+ 
+@@ -395,8 +395,8 @@ static int adl_pci8164_insn_write_cmd(struct comedi_device * dev, struct comedi_
+ 	return 2;
+ }
+ 
+-static int adl_pci8164_insn_write_otp(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int adl_pci8164_insn_write_otp(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int axis, axis_reg;
+ 
+@@ -433,8 +433,8 @@ static int adl_pci8164_insn_write_otp(struct comedi_device * dev, struct comedi_
+ 	return 2;
+ }
+ 
+-static int adl_pci8164_insn_write_buf0(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++static int adl_pci8164_insn_write_buf0(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int axis, axis_reg;
+ 
+@@ -471,8 +471,8 @@ static int adl_pci8164_insn_write_buf0(struct comedi_device * dev,
+ 	return 2;
+ }
+ 
+-static int adl_pci8164_insn_write_buf1(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++static int adl_pci8164_insn_write_buf1(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int axis, axis_reg;
+ 
+diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
+index 28b6b8d3c664..ae5c8552f117 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9111.c
++++ b/drivers/staging/comedi/drivers/adl_pci9111.c
+@@ -264,9 +264,9 @@ Configuration options:
+ 
+ /*  Function prototypes */
+ 
+-static int pci9111_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pci9111_detach(struct comedi_device * dev);
+-static void pci9111_ai_munge(struct comedi_device * dev, struct comedi_subdevice * s,
++static int pci9111_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pci9111_detach(struct comedi_device *dev);
++static void pci9111_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	void *data, unsigned int num_bytes, unsigned int start_chan_index);
+ 
+ static const struct comedi_lrange pci9111_hr_ai_range = {
+@@ -406,7 +406,7 @@ static void plx9050_interrupt_control(unsigned long io_base,
+ 
+ /*  8254 timer */
+ 
+-static void pci9111_timer_set(struct comedi_device * dev)
++static void pci9111_timer_set(struct comedi_device *dev)
+ {
+ 	pci9111_8254_control_set(PCI9111_8254_COUNTER_0 |
+ 		PCI9111_8254_READ_LOAD_LSB_MSB |
+@@ -432,7 +432,7 @@ enum pci9111_trigger_sources {
+ 	external
+ };
+ 
+-static void pci9111_trigger_source_set(struct comedi_device * dev,
++static void pci9111_trigger_source_set(struct comedi_device *dev,
+ 	enum pci9111_trigger_sources source)
+ {
+ 	int flags;
+@@ -456,7 +456,7 @@ static void pci9111_trigger_source_set(struct comedi_device * dev,
+ 	pci9111_trigger_and_autoscan_set(flags);
+ }
+ 
+-static void pci9111_pretrigger_set(struct comedi_device * dev, bool pretrigger)
++static void pci9111_pretrigger_set(struct comedi_device *dev, bool pretrigger)
+ {
+ 	int flags;
+ 
+@@ -468,7 +468,7 @@ static void pci9111_pretrigger_set(struct comedi_device * dev, bool pretrigger)
+ 	pci9111_trigger_and_autoscan_set(flags);
+ }
+ 
+-static void pci9111_autoscan_set(struct comedi_device * dev, bool autoscan)
++static void pci9111_autoscan_set(struct comedi_device *dev, bool autoscan)
+ {
+ 	int flags;
+ 
+@@ -490,7 +490,7 @@ enum pci9111_ISC1_sources {
+ 	irq_on_external_trigger
+ };
+ 
+-static void pci9111_interrupt_source_set(struct comedi_device * dev,
++static void pci9111_interrupt_source_set(struct comedi_device *dev,
+ 	enum pci9111_ISC0_sources irq_0_source, enum pci9111_ISC1_sources irq_1_source)
+ {
+ 	int flags;
+@@ -514,7 +514,7 @@ static void pci9111_interrupt_source_set(struct comedi_device * dev,
+ 
+ #undef AI_DO_CMD_DEBUG
+ 
+-static int pci9111_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pci9111_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	/*  Disable interrupts */
+ 
+@@ -542,8 +542,8 @@ static int pci9111_ai_cancel(struct comedi_device * dev, struct comedi_subdevice
+   if (!src || tmp != src) error++
+ 
+ static int
+-pci9111_ai_do_cmd_test(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_cmd * cmd)
++pci9111_ai_do_cmd_test(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_cmd *cmd)
+ {
+ 	int tmp;
+ 	int error = 0;
+@@ -741,7 +741,7 @@ pci9111_ai_do_cmd_test(struct comedi_device * dev,
+ 
+ /*  Analog input command */
+ 
+-static int pci9111_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * subdevice)
++static int pci9111_ai_do_cmd(struct comedi_device *dev, struct comedi_subdevice *subdevice)
+ {
+ 	struct comedi_cmd *async_cmd = &subdevice->async->cmd;
+ 
+@@ -859,7 +859,7 @@ static int pci9111_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice
+ 	return 0;
+ }
+ 
+-static void pci9111_ai_munge(struct comedi_device * dev, struct comedi_subdevice * s,
++static void pci9111_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	void *data, unsigned int num_bytes, unsigned int start_chan_index)
+ {
+ 	unsigned int i, num_samples = num_bytes / sizeof(short);
+@@ -1043,8 +1043,8 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device)
+ 
+ #undef AI_INSN_DEBUG
+ 
+-static int pci9111_ai_insn_read(struct comedi_device * dev,
+-	struct comedi_subdevice * subdevice, struct comedi_insn * insn, unsigned int * data)
++static int pci9111_ai_insn_read(struct comedi_device *dev,
++	struct comedi_subdevice *subdevice, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int resolution =
+ 		((struct pci9111_board *) dev->board_ptr)->ai_resolution;
+@@ -1101,8 +1101,8 @@ static int pci9111_ai_insn_read(struct comedi_device * dev,
+ /*  Analog instant output */
+ 
+ static int
+-pci9111_ao_insn_write(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++pci9111_ao_insn_write(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 
+@@ -1116,8 +1116,8 @@ pci9111_ao_insn_write(struct comedi_device * dev,
+ 
+ /*  Analog output readback */
+ 
+-static int pci9111_ao_insn_read(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++static int pci9111_ao_insn_read(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 
+@@ -1134,8 +1134,8 @@ static int pci9111_ao_insn_read(struct comedi_device * dev,
+ 
+ /*  Digital inputs */
+ 
+-static int pci9111_di_insn_bits(struct comedi_device * dev,
+-	struct comedi_subdevice * subdevice, struct comedi_insn * insn, unsigned int * data)
++static int pci9111_di_insn_bits(struct comedi_device *dev,
++	struct comedi_subdevice *subdevice, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int bits;
+ 
+@@ -1147,8 +1147,8 @@ static int pci9111_di_insn_bits(struct comedi_device * dev,
+ 
+ /*  Digital outputs */
+ 
+-static int pci9111_do_insn_bits(struct comedi_device * dev,
+-	struct comedi_subdevice * subdevice, struct comedi_insn * insn, unsigned int * data)
++static int pci9111_do_insn_bits(struct comedi_device *dev,
++	struct comedi_subdevice *subdevice, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int bits;
+ 
+@@ -1176,7 +1176,7 @@ static int pci9111_do_insn_bits(struct comedi_device * dev,
+ 
+ /*  Reset device */
+ 
+-static int pci9111_reset(struct comedi_device * dev)
++static int pci9111_reset(struct comedi_device *dev)
+ {
+ 	/*  Set trigger source to software */
+ 
+@@ -1201,7 +1201,7 @@ static int pci9111_reset(struct comedi_device * dev)
+ /*       - Register PCI device */
+ /*       - Declare device driver capability */
+ 
+-static int pci9111_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pci9111_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *subdevice;
+ 	unsigned long io_base, io_range, lcr_io_base, lcr_io_range;
+@@ -1366,7 +1366,7 @@ static int pci9111_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 
+ /*  Detach */
+ 
+-static int pci9111_detach(struct comedi_device * dev)
++static int pci9111_detach(struct comedi_device *dev)
+ {
+ 	/*  Reset device */
+ 
+diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
+index 6a8a4e2d45aa..20f7bf0c2b42 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9118.c
++++ b/drivers/staging/comedi/drivers/adl_pci9118.c
+@@ -179,8 +179,8 @@ static const struct comedi_lrange range_pci9118hg = { 8, {
+ 
+ #define PCI9118_BIPOLAR_RANGES	4	/* used for test on mixture of BIP/UNI ranges */
+ 
+-static int pci9118_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pci9118_detach(struct comedi_device * dev);
++static int pci9118_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pci9118_detach(struct comedi_device *dev);
+ 
+ struct boardtype {
+ 	const char *name;	/*  board name */
+@@ -309,27 +309,27 @@ struct pci9118_private {
+ ==============================================================================
+ */
+ 
+-static int check_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
++static int check_channel_list(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	int n_chan, unsigned int *chanlist, int frontadd, int backadd);
+-static int setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
++static int setup_channel_list(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	int n_chan, unsigned int *chanlist, int rot, int frontadd, int backadd,
+ 	int usedma, char eoshandle);
+-static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
++static void start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1,
+ 	unsigned int divisor2);
+-static int pci9118_reset(struct comedi_device * dev);
+-static int pci9118_exttrg_add(struct comedi_device * dev, unsigned char source);
+-static int pci9118_exttrg_del(struct comedi_device * dev, unsigned char source);
+-static int pci9118_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+-static void pci9118_calc_divisors(char mode, struct comedi_device * dev,
+-	struct comedi_subdevice * s, unsigned int *tim1, unsigned int *tim2,
++static int pci9118_reset(struct comedi_device *dev);
++static int pci9118_exttrg_add(struct comedi_device *dev, unsigned char source);
++static int pci9118_exttrg_del(struct comedi_device *dev, unsigned char source);
++static int pci9118_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
++static void pci9118_calc_divisors(char mode, struct comedi_device *dev,
++	struct comedi_subdevice *s, unsigned int *tim1, unsigned int *tim2,
+ 	unsigned int flags, int chans, unsigned int *div1, unsigned int *div2,
+ 	char usessh, unsigned int chnsshfront);
+ 
+ /*
+ ==============================================================================
+ */
+-static int pci9118_insn_read_ai(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci9118_insn_read_ai(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	int n, timeout;
+@@ -378,8 +378,8 @@ static int pci9118_insn_read_ai(struct comedi_device * dev, struct comedi_subdev
+ /*
+ ==============================================================================
+ */
+-static int pci9118_insn_write_ao(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci9118_insn_write_ao(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, chanreg, ch;
+ 
+@@ -401,8 +401,8 @@ static int pci9118_insn_write_ao(struct comedi_device * dev, struct comedi_subde
+ /*
+ ==============================================================================
+ */
+-static int pci9118_insn_read_ao(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci9118_insn_read_ao(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, chan;
+ 
+@@ -416,8 +416,8 @@ static int pci9118_insn_read_ao(struct comedi_device * dev, struct comedi_subdev
+ /*
+ ==============================================================================
+ */
+-static int pci9118_insn_bits_di(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci9118_insn_bits_di(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[1] = inl(dev->iobase + PCI9118_DI) & 0xf;
+ 
+@@ -427,8 +427,8 @@ static int pci9118_insn_bits_di(struct comedi_device * dev, struct comedi_subdev
+ /*
+ ==============================================================================
+ */
+-static int pci9118_insn_bits_do(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci9118_insn_bits_do(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (data[0]) {
+ 		s->state &= ~data[0];
+@@ -443,7 +443,7 @@ static int pci9118_insn_bits_do(struct comedi_device * dev, struct comedi_subdev
+ /*
+ ==============================================================================
+ */
+-static void interrupt_pci9118_ai_mode4_switch(struct comedi_device * dev)
++static void interrupt_pci9118_ai_mode4_switch(struct comedi_device *dev)
+ {
+ 	devpriv->AdFunctionReg =
+ 		AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM;
+@@ -457,8 +457,8 @@ static void interrupt_pci9118_ai_mode4_switch(struct comedi_device * dev)
+ 	outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
+ }
+ 
+-static unsigned int defragment_dma_buffer(struct comedi_device * dev,
+-	struct comedi_subdevice * s, short * dma_buffer, unsigned int num_samples)
++static unsigned int defragment_dma_buffer(struct comedi_device *dev,
++	struct comedi_subdevice *s, short *dma_buffer, unsigned int num_samples)
+ {
+ 	unsigned int i = 0, j = 0;
+ 	unsigned int start_pos = devpriv->ai_add_front,
+@@ -481,8 +481,8 @@ static unsigned int defragment_dma_buffer(struct comedi_device * dev,
+ /*
+ ==============================================================================
+ */
+-static unsigned int move_block_from_dma(struct comedi_device * dev,
+-	struct comedi_subdevice * s, short * dma_buffer, unsigned int num_samples)
++static unsigned int move_block_from_dma(struct comedi_device *dev,
++	struct comedi_subdevice *s, short *dma_buffer, unsigned int num_samples)
+ {
+ 	unsigned int num_bytes;
+ 
+@@ -502,8 +502,8 @@ static unsigned int move_block_from_dma(struct comedi_device * dev,
+ /*
+ ==============================================================================
+ */
+-static char pci9118_decode_error_status(struct comedi_device * dev,
+-	struct comedi_subdevice * s, unsigned char m)
++static char pci9118_decode_error_status(struct comedi_device *dev,
++	struct comedi_subdevice *s, unsigned char m)
+ {
+ 	if (m & 0x100) {
+ 		comedi_error(dev, "A/D FIFO Full status (Fatal Error!)");
+@@ -532,7 +532,7 @@ static char pci9118_decode_error_status(struct comedi_device * dev,
+ 	return 0;
+ }
+ 
+-static void pci9118_ai_munge(struct comedi_device * dev, struct comedi_subdevice * s,
++static void pci9118_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	void *data, unsigned int num_bytes, unsigned int start_chan_index)
+ {
+ 	unsigned int i, num_samples = num_bytes / sizeof(short);
+@@ -552,8 +552,8 @@ static void pci9118_ai_munge(struct comedi_device * dev, struct comedi_subdevice
+ /*
+ ==============================================================================
+ */
+-static void interrupt_pci9118_ai_onesample(struct comedi_device * dev,
+-	struct comedi_subdevice * s, unsigned short int_adstat, unsigned int int_amcc,
++static void interrupt_pci9118_ai_onesample(struct comedi_device *dev,
++	struct comedi_subdevice *s, unsigned short int_adstat, unsigned int int_amcc,
+ 	unsigned short int_daq)
+ {
+ 	register short sampl;
+@@ -599,7 +599,7 @@ static void interrupt_pci9118_ai_onesample(struct comedi_device * dev,
+ /*
+ ==============================================================================
+ */
+-static void interrupt_pci9118_ai_dma(struct comedi_device * dev, struct comedi_subdevice * s,
++static void interrupt_pci9118_ai_dma(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned short int_adstat, unsigned int int_amcc,
+ 	unsigned short int_daq)
+ {
+@@ -728,7 +728,7 @@ static irqreturn_t interrupt_pci9118(int irq, void *d)
+ /*
+ ==============================================================================
+ */
+-static int pci9118_ai_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
++static int pci9118_ai_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int trignum)
+ {
+ 	if (trignum != devpriv->ai_inttrig_start)
+@@ -752,8 +752,8 @@ static int pci9118_ai_inttrig(struct comedi_device * dev, struct comedi_subdevic
+ /*
+ ==============================================================================
+ */
+-static int pci9118_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int pci9118_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp, divisor1, divisor2;
+@@ -1010,7 +1010,7 @@ static int pci9118_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevic
+ /*
+ ==============================================================================
+ */
+-static int Compute_and_setup_dma(struct comedi_device * dev)
++static int Compute_and_setup_dma(struct comedi_device *dev)
+ {
+ 	unsigned int dmalen0, dmalen1, i;
+ 
+@@ -1164,7 +1164,7 @@ static int Compute_and_setup_dma(struct comedi_device * dev)
+ /*
+ ==============================================================================
+ */
+-static int pci9118_ai_docmd_sampl(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pci9118_ai_docmd_sampl(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_sampl(%d,) [%d]\n",
+ 		dev->minor, devpriv->ai_do);
+@@ -1217,7 +1217,7 @@ static int pci9118_ai_docmd_sampl(struct comedi_device * dev, struct comedi_subd
+ /*
+ ==============================================================================
+ */
+-static int pci9118_ai_docmd_dma(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pci9118_ai_docmd_dma(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_dma(%d,) [%d,%d]\n",
+ 		dev->minor, devpriv->ai_do, devpriv->usedma);
+@@ -1288,7 +1288,7 @@ static int pci9118_ai_docmd_dma(struct comedi_device * dev, struct comedi_subdev
+ /*
+ ==============================================================================
+ */
+-static int pci9118_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned int addchans = 0;
+@@ -1487,7 +1487,7 @@ static int pci9118_ai_cmd(struct comedi_device * dev, struct comedi_subdevice *
+ /*
+ ==============================================================================
+ */
+-static int check_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
++static int check_channel_list(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	int n_chan, unsigned int *chanlist, int frontadd, int backadd)
+ {
+ 	unsigned int i, differencial = 0, bipolar = 0;
+@@ -1538,7 +1538,7 @@ static int check_channel_list(struct comedi_device * dev, struct comedi_subdevic
+ /*
+ ==============================================================================
+ */
+-static int setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
++static int setup_channel_list(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	int n_chan, unsigned int *chanlist, int rot, int frontadd, int backadd,
+ 	int usedma, char useeos)
+ {
+@@ -1652,8 +1652,8 @@ static int setup_channel_list(struct comedi_device * dev, struct comedi_subdevic
+ ==============================================================================
+   calculate 8254 divisors if they are used for dual timing
+ */
+-static void pci9118_calc_divisors(char mode, struct comedi_device * dev,
+-	struct comedi_subdevice * s, unsigned int *tim1, unsigned int *tim2,
++static void pci9118_calc_divisors(char mode, struct comedi_device *dev,
++	struct comedi_subdevice *s, unsigned int *tim1, unsigned int *tim2,
+ 	unsigned int flags, int chans, unsigned int *div1, unsigned int *div2,
+ 	char usessh, unsigned int chnsshfront)
+ {
+@@ -1711,7 +1711,7 @@ static void pci9118_calc_divisors(char mode, struct comedi_device * dev,
+ /*
+ ==============================================================================
+ */
+-static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
++static void start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1,
+ 	unsigned int divisor2)
+ {
+ 	outl(0x74, dev->iobase + PCI9118_CNTCTRL);
+@@ -1730,7 +1730,7 @@ static void start_pacer(struct comedi_device * dev, int mode, unsigned int divis
+ /*
+ ==============================================================================
+ */
+-static int pci9118_exttrg_add(struct comedi_device * dev, unsigned char source)
++static int pci9118_exttrg_add(struct comedi_device *dev, unsigned char source)
+ {
+ 	if (source > 3)
+ 		return -1;	/*  incorrect source */
+@@ -1744,7 +1744,7 @@ static int pci9118_exttrg_add(struct comedi_device * dev, unsigned char source)
+ /*
+ ==============================================================================
+ */
+-static int pci9118_exttrg_del(struct comedi_device * dev, unsigned char source)
++static int pci9118_exttrg_del(struct comedi_device *dev, unsigned char source)
+ {
+ 	if (source > 3)
+ 		return -1;	/*  incorrect source */
+@@ -1761,7 +1761,7 @@ static int pci9118_exttrg_del(struct comedi_device * dev, unsigned char source)
+ /*
+ ==============================================================================
+ */
+-static int pci9118_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pci9118_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	if (devpriv->usedma)
+ 		outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS), devpriv->iobase_a + AMCC_OP_REG_MCSR);	/*  stop DMA */
+@@ -1796,7 +1796,7 @@ static int pci9118_ai_cancel(struct comedi_device * dev, struct comedi_subdevice
+ /*
+ ==============================================================================
+ */
+-static int pci9118_reset(struct comedi_device * dev)
++static int pci9118_reset(struct comedi_device *dev)
+ {
+ 	devpriv->IntControlReg = 0;
+ 	devpriv->exttrg_users = 0;
+@@ -1836,7 +1836,7 @@ static int pci9118_reset(struct comedi_device * dev)
+ /*
+ ==============================================================================
+ */
+-static int pci9118_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pci9118_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int ret, pages, i;
+@@ -2072,7 +2072,7 @@ static int pci9118_attach(struct comedi_device * dev, struct comedi_devconfig *
+ /*
+ ==============================================================================
+ */
+-static int pci9118_detach(struct comedi_device * dev)
++static int pci9118_detach(struct comedi_device *dev)
+ {
+ 	if (dev->private) {
+ 		if (devpriv->valid)
+diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
+index b8b5001c5d24..2df5ab0eaeeb 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1710.c
++++ b/drivers/staging/comedi/drivers/adv_pci1710.c
+@@ -184,8 +184,8 @@ static const struct comedi_lrange range_pci171x_da = { 2, {
+ 	}
+ };
+ 
+-static int pci1710_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pci1710_detach(struct comedi_device * dev);
++static int pci1710_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pci1710_detach(struct comedi_device *dev);
+ 
+ struct boardtype {
+ 	const char *name;	/*  board name */
+@@ -306,14 +306,14 @@ struct pci1710_private {
+ ==============================================================================
+ */
+ 
+-static int check_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
++static int check_channel_list(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int *chanlist, unsigned int n_chan);
+-static void setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
++static void setup_channel_list(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int *chanlist, unsigned int n_chan, unsigned int seglen);
+-static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
++static void start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1,
+ 	unsigned int divisor2);
+-static int pci1710_reset(struct comedi_device * dev);
+-static int pci171x_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
++static int pci1710_reset(struct comedi_device *dev);
++static int pci171x_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
+ 
+ static const unsigned int muxonechan[] = { 0x0000, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, 0x0707,	/*  used for gain list programming */
+ 	0x0808, 0x0909, 0x0a0a, 0x0b0b, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f,
+@@ -324,8 +324,8 @@ static const unsigned int muxonechan[] = { 0x0000, 0x0101, 0x0202, 0x0303, 0x040
+ /*
+ ==============================================================================
+ */
+-static int pci171x_insn_read_ai(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci171x_insn_read_ai(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, timeout;
+ #ifdef PCI171x_PARANOIDCHECK
+@@ -392,8 +392,8 @@ static int pci171x_insn_read_ai(struct comedi_device * dev, struct comedi_subdev
+ /*
+ ==============================================================================
+ */
+-static int pci171x_insn_write_ao(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci171x_insn_write_ao(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, chan, range, ofs;
+ 
+@@ -423,8 +423,8 @@ static int pci171x_insn_write_ao(struct comedi_device * dev, struct comedi_subde
+ /*
+ ==============================================================================
+ */
+-static int pci171x_insn_read_ao(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci171x_insn_read_ao(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, chan;
+ 
+@@ -438,8 +438,8 @@ static int pci171x_insn_read_ao(struct comedi_device * dev, struct comedi_subdev
+ /*
+ ==============================================================================
+ */
+-static int pci171x_insn_bits_di(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci171x_insn_bits_di(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[1] = inw(dev->iobase + PCI171x_DI);
+ 
+@@ -449,8 +449,8 @@ static int pci171x_insn_bits_di(struct comedi_device * dev, struct comedi_subdev
+ /*
+ ==============================================================================
+ */
+-static int pci171x_insn_bits_do(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci171x_insn_bits_do(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (data[0]) {
+ 		s->state &= ~data[0];
+@@ -465,8 +465,8 @@ static int pci171x_insn_bits_do(struct comedi_device * dev, struct comedi_subdev
+ /*
+ ==============================================================================
+ */
+-static int pci171x_insn_counter_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci171x_insn_counter_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int msb, lsb, ccntrl;
+ 	int i;
+@@ -487,8 +487,8 @@ static int pci171x_insn_counter_read(struct comedi_device * dev, struct comedi_s
+ /*
+ ==============================================================================
+ */
+-static int pci171x_insn_counter_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci171x_insn_counter_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	uint msb, lsb, ccntrl, status;
+ 
+@@ -514,8 +514,8 @@ static int pci171x_insn_counter_write(struct comedi_device * dev, struct comedi_
+ /*
+ ==============================================================================
+ */
+-static int pci171x_insn_counter_config(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++static int pci171x_insn_counter_config(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ #ifdef unused
+ 	/* This doesn't work like a normal Comedi counter config */
+@@ -550,8 +550,8 @@ static int pci171x_insn_counter_config(struct comedi_device * dev,
+ /*
+ ==============================================================================
+ */
+-static int pci1720_insn_write_ao(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci1720_insn_write_ao(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, rangereg, chan;
+ 
+@@ -661,7 +661,7 @@ static void interrupt_pci1710_every_sample(void *d)
+ /*
+ ==============================================================================
+ */
+-static int move_block_from_fifo(struct comedi_device * dev, struct comedi_subdevice * s,
++static int move_block_from_fifo(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	int n, int turn)
+ {
+ 	int i, j;
+@@ -803,8 +803,8 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d)
+ /*
+ ==============================================================================
+ */
+-static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device * dev,
+-	struct comedi_subdevice * s)
++static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device *dev,
++	struct comedi_subdevice *s)
+ {
+ 	unsigned int divisor1, divisor2;
+ 	unsigned int seglen;
+@@ -886,7 +886,7 @@ static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device * dev,
+ /*
+ ==============================================================================
+ */
+-static void pci171x_cmdtest_out(int e, struct comedi_cmd * cmd)
++static void pci171x_cmdtest_out(int e, struct comedi_cmd *cmd)
+ {
+ 	rt_printk("adv_pci1710 e=%d startsrc=%x scansrc=%x convsrc=%x\n", e,
+ 		cmd->start_src, cmd->scan_begin_src, cmd->convert_src);
+@@ -902,8 +902,8 @@ static void pci171x_cmdtest_out(int e, struct comedi_cmd * cmd)
+ /*
+ ==============================================================================
+ */
+-static int pci171x_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int pci171x_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp, divisor1, divisor2;
+@@ -1067,7 +1067,7 @@ static int pci171x_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevic
+ /*
+ ==============================================================================
+ */
+-static int pci171x_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+ 
+@@ -1106,7 +1106,7 @@ static int pci171x_ai_cmd(struct comedi_device * dev, struct comedi_subdevice *
+  If it's ok, then program scan/gain logic.
+  This works for all cards.
+ */
+-static int check_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
++static int check_channel_list(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int *chanlist, unsigned int n_chan)
+ {
+ 	unsigned int chansegment[32];
+@@ -1165,7 +1165,7 @@ static int check_channel_list(struct comedi_device * dev, struct comedi_subdevic
+ 	return seglen;
+ }
+ 
+-static void setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
++static void setup_channel_list(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int *chanlist, unsigned int n_chan, unsigned int seglen)
+ {
+ 	unsigned int i, range, chanprog;
+@@ -1202,7 +1202,7 @@ static void setup_channel_list(struct comedi_device * dev, struct comedi_subdevi
+ /*
+ ==============================================================================
+ */
+-static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
++static void start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1,
+ 	unsigned int divisor2)
+ {
+ 	DPRINTK("adv_pci1710 EDBG: BGN: start_pacer(%d,%u,%u)\n", mode,
+@@ -1222,7 +1222,7 @@ static void start_pacer(struct comedi_device * dev, int mode, unsigned int divis
+ /*
+ ==============================================================================
+ */
+-static int pci171x_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pci171x_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cancel(...)\n");
+ 
+@@ -1251,7 +1251,7 @@ static int pci171x_ai_cancel(struct comedi_device * dev, struct comedi_subdevice
+ /*
+ ==============================================================================
+ */
+-static int pci171x_reset(struct comedi_device * dev)
++static int pci171x_reset(struct comedi_device *dev)
+ {
+ 	DPRINTK("adv_pci1710 EDBG: BGN: pci171x_reset(...)\n");
+ 	outw(0x30, dev->iobase + PCI171x_CNTCTRL);
+@@ -1281,7 +1281,7 @@ static int pci171x_reset(struct comedi_device * dev)
+ /*
+ ==============================================================================
+ */
+-static int pci1720_reset(struct comedi_device * dev)
++static int pci1720_reset(struct comedi_device *dev)
+ {
+ 	DPRINTK("adv_pci1710 EDBG: BGN: pci1720_reset(...)\n");
+ 	outb(Syncont_SC0, dev->iobase + PCI1720_SYNCONT);	/*  set synchronous output mode */
+@@ -1303,7 +1303,7 @@ static int pci1720_reset(struct comedi_device * dev)
+ /*
+ ==============================================================================
+ */
+-static int pci1710_reset(struct comedi_device * dev)
++static int pci1710_reset(struct comedi_device *dev)
+ {
+ 	DPRINTK("adv_pci1710 EDBG: BGN: pci1710_reset(...)\n");
+ 	switch (this_board->cardtype) {
+@@ -1318,7 +1318,7 @@ static int pci1710_reset(struct comedi_device * dev)
+ /*
+ ==============================================================================
+ */
+-static int pci1710_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pci1710_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int ret, subdev, n_subdevices;
+@@ -1542,7 +1542,7 @@ static int pci1710_attach(struct comedi_device * dev, struct comedi_devconfig *
+ /*
+ ==============================================================================
+ */
+-static int pci1710_detach(struct comedi_device * dev)
++static int pci1710_detach(struct comedi_device *dev)
+ {
+ 
+ 	if (dev->private) {
+diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
+index eb4bf1f47b30..e45ce552dd02 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1723.c
++++ b/drivers/staging/comedi/drivers/adv_pci1723.c
+@@ -143,8 +143,8 @@ MODULE_DEVICE_TABLE(pci, pci1723_pci_table);
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pci1723_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pci1723_detach(struct comedi_device * dev);
++static int pci1723_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pci1723_detach(struct comedi_device *dev);
+ 
+ #define n_boardtypes (sizeof(boardtypes)/sizeof(struct pci1723_board))
+ 
+@@ -175,7 +175,7 @@ struct pci1723_private {
+ /*
+  *   the pci1723 card reset;
+  */
+-static int pci1723_reset(struct comedi_device * dev)
++static int pci1723_reset(struct comedi_device *dev)
+ {
+ 	int i;
+ 	DPRINTK("adv_pci1723 EDBG: BGN: pci1723_reset(...)\n");
+@@ -202,8 +202,8 @@ static int pci1723_reset(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int pci1723_insn_read_ao(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci1723_insn_read_ao(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, chan;
+ 
+@@ -218,8 +218,8 @@ static int pci1723_insn_read_ao(struct comedi_device * dev, struct comedi_subdev
+ /*
+   analog data output;
+ */
+-static int pci1723_ao_write_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci1723_ao_write_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, chan;
+ 	chan = CR_CHAN(insn->chanspec);
+@@ -238,8 +238,8 @@ static int pci1723_ao_write_winsn(struct comedi_device * dev, struct comedi_subd
+ /*
+   digital i/o config/query
+ */
+-static int pci1723_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci1723_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int mask;
+ 	unsigned int bits;
+@@ -278,8 +278,8 @@ static int pci1723_dio_insn_config(struct comedi_device * dev, struct comedi_sub
+ /*
+   digital i/o bits read/write
+ */
+-static int pci1723_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci1723_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (data[0]) {
+ 		s->state &= ~data[0];
+@@ -294,7 +294,7 @@ static int pci1723_dio_insn_bits(struct comedi_device * dev, struct comedi_subde
+  * Attach is called by the Comedi core to configure the driver
+  * for a pci1723 board.
+  */
+-static int pci1723_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pci1723_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int ret, subdev, n_subdevices;
+@@ -439,7 +439,7 @@ static int pci1723_attach(struct comedi_device * dev, struct comedi_devconfig *
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int pci1723_detach(struct comedi_device * dev)
++static int pci1723_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: pci1723: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
+index 2604425c3a0f..21fd9aa8decc 100644
+--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
++++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
+@@ -183,8 +183,8 @@ enum hw_io_access {
+ 
+ #define OMBCMD_RETRY	0x03	/* 3 times try request before error */
+ 
+-static int pci_dio_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pci_dio_detach(struct comedi_device * dev);
++static int pci_dio_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pci_dio_detach(struct comedi_device *dev);
+ 
+ struct diosubd_data {
+ 	int chans;		/*  num of chans */
+@@ -357,8 +357,8 @@ static struct pci_dio_private *pci_priv = NULL;	/* list of allocated cards */
+ /*
+ ==============================================================================
+ */
+-static int pci_dio_insn_bits_di_b(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci_dio_insn_bits_di_b(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	const struct diosubd_data *d = (const struct diosubd_data *)s->private;
+ 	int i;
+@@ -374,8 +374,8 @@ static int pci_dio_insn_bits_di_b(struct comedi_device * dev, struct comedi_subd
+ /*
+ ==============================================================================
+ */
+-static int pci_dio_insn_bits_di_w(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci_dio_insn_bits_di_w(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	const struct diosubd_data *d = (const struct diosubd_data *)s->private;
+ 	int i;
+@@ -390,8 +390,8 @@ static int pci_dio_insn_bits_di_w(struct comedi_device * dev, struct comedi_subd
+ /*
+ ==============================================================================
+ */
+-static int pci_dio_insn_bits_do_b(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci_dio_insn_bits_do_b(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	const struct diosubd_data *d = (const struct diosubd_data *)s->private;
+ 	int i;
+@@ -411,8 +411,8 @@ static int pci_dio_insn_bits_do_b(struct comedi_device * dev, struct comedi_subd
+ /*
+ ==============================================================================
+ */
+-static int pci_dio_insn_bits_do_w(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci_dio_insn_bits_do_w(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	const struct diosubd_data *d = (const struct diosubd_data *)s->private;
+ 	int i;
+@@ -432,7 +432,7 @@ static int pci_dio_insn_bits_do_w(struct comedi_device * dev, struct comedi_subd
+ /*
+ ==============================================================================
+ */
+-static int pci1760_unchecked_mbxrequest(struct comedi_device * dev,
++static int pci1760_unchecked_mbxrequest(struct comedi_device *dev,
+ 	unsigned char *omb, unsigned char *imb, int repeats)
+ {
+ 	int cnt, tout, ok = 0;
+@@ -460,7 +460,7 @@ static int pci1760_unchecked_mbxrequest(struct comedi_device * dev,
+ 	return -ETIME;
+ }
+ 
+-static int pci1760_clear_imb2(struct comedi_device * dev)
++static int pci1760_clear_imb2(struct comedi_device *dev)
+ {
+ 	unsigned char omb[4] = { 0x0, 0x0, CMD_ClearIMB2, 0x0 };
+ 	unsigned char imb[4];
+@@ -470,7 +470,7 @@ static int pci1760_clear_imb2(struct comedi_device * dev)
+ 	return pci1760_unchecked_mbxrequest(dev, omb, imb, OMBCMD_RETRY);
+ }
+ 
+-static int pci1760_mbxrequest(struct comedi_device * dev,
++static int pci1760_mbxrequest(struct comedi_device *dev,
+ 	unsigned char *omb, unsigned char *imb)
+ {
+ 	if (omb[2] == CMD_ClearIMB2) {
+@@ -490,8 +490,8 @@ static int pci1760_mbxrequest(struct comedi_device * dev,
+ /*
+ ==============================================================================
+ */
+-static int pci1760_insn_bits_di(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci1760_insn_bits_di(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[1] = inb(dev->iobase + IMB3);
+ 
+@@ -501,8 +501,8 @@ static int pci1760_insn_bits_di(struct comedi_device * dev, struct comedi_subdev
+ /*
+ ==============================================================================
+ */
+-static int pci1760_insn_bits_do(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci1760_insn_bits_do(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int ret;
+ 	unsigned char omb[4] = {
+@@ -528,8 +528,8 @@ static int pci1760_insn_bits_do(struct comedi_device * dev, struct comedi_subdev
+ /*
+ ==============================================================================
+ */
+-static int pci1760_insn_cnt_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci1760_insn_cnt_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int ret, n;
+ 	unsigned char omb[4] = {
+@@ -552,8 +552,8 @@ static int pci1760_insn_cnt_read(struct comedi_device * dev, struct comedi_subde
+ /*
+ ==============================================================================
+ */
+-static int pci1760_insn_cnt_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci1760_insn_cnt_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int ret;
+ 	unsigned char chan = CR_CHAN(insn->chanspec) & 0x07;
+@@ -590,7 +590,7 @@ static int pci1760_insn_cnt_write(struct comedi_device * dev, struct comedi_subd
+ /*
+ ==============================================================================
+ */
+-static int pci1760_reset(struct comedi_device * dev)
++static int pci1760_reset(struct comedi_device *dev)
+ {
+ 	int i;
+ 	unsigned char omb[4] = { 0x00, 0x00, 0x00, 0x00 };
+@@ -667,7 +667,7 @@ static int pci1760_reset(struct comedi_device * dev)
+ /*
+ ==============================================================================
+ */
+-static int pci_dio_reset(struct comedi_device * dev)
++static int pci_dio_reset(struct comedi_device *dev)
+ {
+ 	DPRINTK("adv_pci_dio EDBG: BGN: pci171x_reset(...)\n");
+ 
+@@ -750,7 +750,7 @@ static int pci_dio_reset(struct comedi_device * dev)
+ /*
+ ==============================================================================
+ */
+-static int pci1760_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pci1760_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int subdev = 0;
+@@ -802,8 +802,8 @@ static int pci1760_attach(struct comedi_device * dev, struct comedi_devconfig *
+ /*
+ ==============================================================================
+ */
+-static int pci_dio_add_di(struct comedi_device * dev, struct comedi_subdevice * s,
+-	const struct diosubd_data * d, int subdev)
++static int pci_dio_add_di(struct comedi_device *dev, struct comedi_subdevice *s,
++	const struct diosubd_data *d, int subdev)
+ {
+ 	s->type = COMEDI_SUBD_DI;
+ 	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON | d->specflags;
+@@ -829,8 +829,8 @@ static int pci_dio_add_di(struct comedi_device * dev, struct comedi_subdevice *
+ /*
+ ==============================================================================
+ */
+-static int pci_dio_add_do(struct comedi_device * dev, struct comedi_subdevice * s,
+-	const struct diosubd_data * d, int subdev)
++static int pci_dio_add_do(struct comedi_device *dev, struct comedi_subdevice *s,
++	const struct diosubd_data *d, int subdev)
+ {
+ 	s->type = COMEDI_SUBD_DO;
+ 	s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
+@@ -857,7 +857,7 @@ static int pci_dio_add_do(struct comedi_device * dev, struct comedi_subdevice *
+ /*
+ ==============================================================================
+ */
+-static int CheckAndAllocCard(struct comedi_device * dev, struct comedi_devconfig * it,
++static int CheckAndAllocCard(struct comedi_device *dev, struct comedi_devconfig *it,
+ 	struct pci_dev *pcidev)
+ {
+ 	struct pci_dio_private *pr, *prev;
+@@ -883,7 +883,7 @@ static int CheckAndAllocCard(struct comedi_device * dev, struct comedi_devconfig
+ /*
+ ==============================================================================
+ */
+-static int pci_dio_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pci_dio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int ret, subdev, n_subdevices, i, j;
+@@ -1011,7 +1011,7 @@ static int pci_dio_attach(struct comedi_device * dev, struct comedi_devconfig *
+ /*
+ ==============================================================================
+ */
+-static int pci_dio_detach(struct comedi_device * dev)
++static int pci_dio_detach(struct comedi_device *dev)
+ {
+ 	int i, j;
+ 	struct comedi_subdevice *s;
+diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c
+index b21c23b8ba52..ce4e8e49ae8e 100644
+--- a/drivers/staging/comedi/drivers/aio_aio12_8.c
++++ b/drivers/staging/comedi/drivers/aio_aio12_8.c
+@@ -88,8 +88,8 @@ struct aio12_8_private {
+ 
+ #define devpriv	((struct aio12_8_private *) dev->private)
+ 
+-static int aio_aio12_8_ai_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int aio_aio12_8_ai_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	unsigned char control =
+@@ -122,8 +122,8 @@ static int aio_aio12_8_ai_read(struct comedi_device * dev, struct comedi_subdevi
+ 	return n;
+ }
+ 
+-static int aio_aio12_8_ao_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int aio_aio12_8_ao_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int val = devpriv->ao_readback[CR_CHAN(insn->chanspec)];
+@@ -133,8 +133,8 @@ static int aio_aio12_8_ao_read(struct comedi_device * dev, struct comedi_subdevi
+ 	return insn->n;
+ }
+ 
+-static int aio_aio12_8_ao_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int aio_aio12_8_ao_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -161,7 +161,7 @@ static const struct comedi_lrange range_aio_aio12_8 = {
+ 		}
+ };
+ 
+-static int aio_aio12_8_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int aio_aio12_8_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int iobase;
+ 	struct comedi_subdevice *s;
+@@ -205,7 +205,7 @@ static int aio_aio12_8_attach(struct comedi_device * dev, struct comedi_devconfi
+ 	return 0;
+ }
+ 
+-static int aio_aio12_8_detach(struct comedi_device * dev)
++static int aio_aio12_8_detach(struct comedi_device *dev)
+ {
+ 	subdev_8255_cleanup(dev, &dev->subdevices[2]);
+ 	if (dev->iobase)
+diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c
+index 9160fdf0ca37..8374f65a8bec 100644
+--- a/drivers/staging/comedi/drivers/aio_iiro_16.c
++++ b/drivers/staging/comedi/drivers/aio_iiro_16.c
+@@ -67,9 +67,9 @@ struct aio_iiro_16_private {
+ 
+ #define	devpriv	((struct aio_iiro_16_private *) dev->private)
+ 
+-static int aio_iiro_16_attach(struct comedi_device * dev, struct comedi_devconfig * it);
++static int aio_iiro_16_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ 
+-static int aio_iiro_16_detach(struct comedi_device * dev);
++static int aio_iiro_16_detach(struct comedi_device *dev);
+ 
+ static struct comedi_driver driver_aio_iiro_16 = {
+       driver_name:"aio_iiro_16",
+@@ -81,13 +81,13 @@ static struct comedi_driver driver_aio_iiro_16 = {
+       num_names:sizeof(aio_iiro_16_boards) / sizeof(struct aio_iiro_16_board),
+ };
+ 
+-static int aio_iiro_16_dio_insn_bits_read(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
++static int aio_iiro_16_dio_insn_bits_read(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
+ 
+-static int aio_iiro_16_dio_insn_bits_write(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
++static int aio_iiro_16_dio_insn_bits_write(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
+ 
+-static int aio_iiro_16_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int aio_iiro_16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int iobase;
+ 	struct comedi_subdevice *s;
+@@ -132,7 +132,7 @@ static int aio_iiro_16_attach(struct comedi_device * dev, struct comedi_devconfi
+ 	return 1;
+ }
+ 
+-static int aio_iiro_16_detach(struct comedi_device * dev)
++static int aio_iiro_16_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: aio_iiro_16: remove\n", dev->minor);
+ 
+@@ -142,8 +142,8 @@ static int aio_iiro_16_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int aio_iiro_16_dio_insn_bits_write(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++static int aio_iiro_16_dio_insn_bits_write(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -161,8 +161,8 @@ static int aio_iiro_16_dio_insn_bits_write(struct comedi_device * dev,
+ 	return 2;
+ }
+ 
+-static int aio_iiro_16_dio_insn_bits_read(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++static int aio_iiro_16_dio_insn_bits_read(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
+index 771e88ca873d..563fb0ba06e8 100644
+--- a/drivers/staging/comedi/drivers/amplc_dio200.c
++++ b/drivers/staging/comedi/drivers/amplc_dio200.c
+@@ -475,8 +475,8 @@ struct dio200_subdev_intr {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int dio200_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int dio200_detach(struct comedi_device * dev);
++static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int dio200_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_amplc_dio200 = {
+       driver_name:DIO200_DRIVER_NAME,
+       module:THIS_MODULE,
+@@ -499,7 +499,7 @@ COMEDI_INITCLEANUP(driver_amplc_dio200);
+  */
+ #ifdef CONFIG_COMEDI_PCI
+ static int
+-dio200_find_pci(struct comedi_device * dev, int bus, int slot,
++dio200_find_pci(struct comedi_device *dev, int bus, int slot,
+ 	struct pci_dev **pci_dev_p)
+ {
+ 	struct pci_dev *pci_dev = NULL;
+@@ -574,8 +574,8 @@ dio200_request_region(unsigned minor, unsigned long from, unsigned long extent)
+  * 'insn_bits' function for an 'INTERRUPT' subdevice.
+  */
+ static int
+-dio200_subdev_intr_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++dio200_subdev_intr_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	struct dio200_subdev_intr *subpriv = s->private;
+ 
+@@ -593,7 +593,7 @@ dio200_subdev_intr_insn_bits(struct comedi_device * dev, struct comedi_subdevice
+ /*
+  * Called to stop acquisition for an 'INTERRUPT' subdevice.
+  */
+-static void dio200_stop_intr(struct comedi_device * dev, struct comedi_subdevice * s)
++static void dio200_stop_intr(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct dio200_subdev_intr *subpriv = s->private;
+ 
+@@ -607,7 +607,7 @@ static void dio200_stop_intr(struct comedi_device * dev, struct comedi_subdevice
+ /*
+  * Called to start acquisition for an 'INTERRUPT' subdevice.
+  */
+-static int dio200_start_intr(struct comedi_device * dev, struct comedi_subdevice * s)
++static int dio200_start_intr(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	unsigned int n;
+ 	unsigned isn_bits;
+@@ -643,7 +643,7 @@ static int dio200_start_intr(struct comedi_device * dev, struct comedi_subdevice
+  * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
+  */
+ static int
+-dio200_inttrig_start_intr(struct comedi_device * dev, struct comedi_subdevice * s,
++dio200_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int trignum)
+ {
+ 	struct dio200_subdev_intr *subpriv;
+@@ -673,7 +673,7 @@ dio200_inttrig_start_intr(struct comedi_device * dev, struct comedi_subdevice *
+  * This is called from the interrupt service routine to handle a read
+  * scan on an 'INTERRUPT' subdevice.
+  */
+-static int dio200_handle_read_intr(struct comedi_device * dev, struct comedi_subdevice * s)
++static int dio200_handle_read_intr(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct dio200_subdev_intr *subpriv = s->private;
+ 	unsigned triggered;
+@@ -785,7 +785,7 @@ static int dio200_handle_read_intr(struct comedi_device * dev, struct comedi_sub
+ /*
+  * 'cancel' function for an 'INTERRUPT' subdevice.
+  */
+-static int dio200_subdev_intr_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int dio200_subdev_intr_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct dio200_subdev_intr *subpriv = s->private;
+ 	unsigned long flags;
+@@ -803,8 +803,8 @@ static int dio200_subdev_intr_cancel(struct comedi_device * dev, struct comedi_s
+  * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
+  */
+ static int
+-dio200_subdev_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++dio200_subdev_intr_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	unsigned int tmp;
+@@ -909,7 +909,7 @@ dio200_subdev_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevice *
+ /*
+  * 'do_cmd' function for an 'INTERRUPT' subdevice.
+  */
+-static int dio200_subdev_intr_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int dio200_subdev_intr_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+ 	struct dio200_subdev_intr *subpriv = s->private;
+@@ -955,7 +955,7 @@ static int dio200_subdev_intr_cmd(struct comedi_device * dev, struct comedi_subd
+  * This function initializes an 'INTERRUPT' subdevice.
+  */
+ static int
+-dio200_subdev_intr_init(struct comedi_device * dev, struct comedi_subdevice * s,
++dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned long iobase, unsigned valid_isns, int has_int_sce)
+ {
+ 	struct dio200_subdev_intr *subpriv;
+@@ -1000,7 +1000,7 @@ dio200_subdev_intr_init(struct comedi_device * dev, struct comedi_subdevice * s,
+  * This function cleans up an 'INTERRUPT' subdevice.
+  */
+ static void
+-dio200_subdev_intr_cleanup(struct comedi_device * dev, struct comedi_subdevice * s)
++dio200_subdev_intr_cleanup(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct dio200_subdev_intr *subpriv = s->private;
+ 
+@@ -1035,8 +1035,8 @@ static irqreturn_t dio200_interrupt(int irq, void *d)
+  * Handle 'insn_read' for an '8254' counter subdevice.
+  */
+ static int
+-dio200_subdev_8254_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++dio200_subdev_8254_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	struct dio200_subdev_8254 *subpriv = s->private;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -1050,8 +1050,8 @@ dio200_subdev_8254_read(struct comedi_device * dev, struct comedi_subdevice * s,
+  * Handle 'insn_write' for an '8254' counter subdevice.
+  */
+ static int
+-dio200_subdev_8254_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++dio200_subdev_8254_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	struct dio200_subdev_8254 *subpriv = s->private;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -1065,7 +1065,7 @@ dio200_subdev_8254_write(struct comedi_device * dev, struct comedi_subdevice * s
+  * Set gate source for an '8254' counter subdevice channel.
+  */
+ static int
+-dio200_set_gate_src(struct dio200_subdev_8254 * subpriv, unsigned int counter_number,
++dio200_set_gate_src(struct dio200_subdev_8254 *subpriv, unsigned int counter_number,
+ 	unsigned int gate_src)
+ {
+ 	unsigned char byte;
+@@ -1088,7 +1088,7 @@ dio200_set_gate_src(struct dio200_subdev_8254 * subpriv, unsigned int counter_nu
+  * Get gate source for an '8254' counter subdevice channel.
+  */
+ static int
+-dio200_get_gate_src(struct dio200_subdev_8254 * subpriv, unsigned int counter_number)
++dio200_get_gate_src(struct dio200_subdev_8254 *subpriv, unsigned int counter_number)
+ {
+ 	if (!subpriv->has_clk_gat_sce)
+ 		return -1;
+@@ -1102,7 +1102,7 @@ dio200_get_gate_src(struct dio200_subdev_8254 * subpriv, unsigned int counter_nu
+  * Set clock source for an '8254' counter subdevice channel.
+  */
+ static int
+-dio200_set_clock_src(struct dio200_subdev_8254 * subpriv, unsigned int counter_number,
++dio200_set_clock_src(struct dio200_subdev_8254 *subpriv, unsigned int counter_number,
+ 	unsigned int clock_src)
+ {
+ 	unsigned char byte;
+@@ -1125,8 +1125,8 @@ dio200_set_clock_src(struct dio200_subdev_8254 * subpriv, unsigned int counter_n
+  * Get clock source for an '8254' counter subdevice channel.
+  */
+ static int
+-dio200_get_clock_src(struct dio200_subdev_8254 * subpriv, unsigned int counter_number,
+-	unsigned int * period_ns)
++dio200_get_clock_src(struct dio200_subdev_8254 *subpriv, unsigned int counter_number,
++	unsigned int *period_ns)
+ {
+ 	unsigned clock_src;
+ 
+@@ -1144,8 +1144,8 @@ dio200_get_clock_src(struct dio200_subdev_8254 * subpriv, unsigned int counter_n
+  * Handle 'insn_config' for an '8254' counter subdevice.
+  */
+ static int
+-dio200_subdev_8254_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	struct dio200_subdev_8254 *subpriv = s->private;
+ 	int ret;
+@@ -1196,7 +1196,7 @@ dio200_subdev_8254_config(struct comedi_device * dev, struct comedi_subdevice *
+  * offset is the offset to the 8254 chip.
+  */
+ static int
+-dio200_subdev_8254_init(struct comedi_device * dev, struct comedi_subdevice * s,
++dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned long iobase, unsigned offset, int has_clk_gat_sce)
+ {
+ 	struct dio200_subdev_8254 *subpriv;
+@@ -1249,7 +1249,7 @@ dio200_subdev_8254_init(struct comedi_device * dev, struct comedi_subdevice * s,
+  * This function cleans up an '8254' counter subdevice.
+  */
+ static void
+-dio200_subdev_8254_cleanup(struct comedi_device * dev, struct comedi_subdevice * s)
++dio200_subdev_8254_cleanup(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct dio200_subdev_intr *subpriv = s->private;
+ 
+@@ -1264,7 +1264,7 @@ dio200_subdev_8254_cleanup(struct comedi_device * dev, struct comedi_subdevice *
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int dio200_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase = 0;
+@@ -1431,7 +1431,7 @@ static int dio200_attach(struct comedi_device * dev, struct comedi_devconfig * i
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int dio200_detach(struct comedi_device * dev)
++static int dio200_detach(struct comedi_device *dev)
+ {
+ 	const struct dio200_layout_struct *layout;
+ 	unsigned n;
+diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
+index fc1a8f1b611a..c45cbf36f1eb 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc236.c
++++ b/drivers/staging/comedi/drivers/amplc_pc236.c
+@@ -167,8 +167,8 @@ struct pc236_private {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pc236_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pc236_detach(struct comedi_device * dev);
++static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pc236_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_amplc_pc236 = {
+       driver_name:PC236_DRIVER_NAME,
+       module:THIS_MODULE,
+@@ -204,7 +204,7 @@ static irqreturn_t pc236_interrupt(int irq, void *d);
+  */
+ #ifdef CONFIG_COMEDI_PCI
+ static int
+-pc236_find_pci(struct comedi_device * dev, int bus, int slot,
++pc236_find_pci(struct comedi_device *dev, int bus, int slot,
+ 	struct pci_dev **pci_dev_p)
+ {
+ 	struct pci_dev *pci_dev = NULL;
+@@ -266,7 +266,7 @@ pc236_find_pci(struct comedi_device * dev, int bus, int slot,
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pc236_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase = 0;
+@@ -407,7 +407,7 @@ static int pc236_attach(struct comedi_device * dev, struct comedi_devconfig * it
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int pc236_detach(struct comedi_device * dev)
++static int pc236_detach(struct comedi_device *dev)
+ {
+ 	printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
+ 		PC236_DRIVER_NAME);
+@@ -461,7 +461,7 @@ static int pc236_request_region(unsigned minor, unsigned long from,
+  * configured on subdevice 1) and to physically disable the interrupt
+  * (not possible on the PC36AT, except by removing the IRQ jumper!).
+  */
+-static void pc236_intr_disable(struct comedi_device * dev)
++static void pc236_intr_disable(struct comedi_device *dev)
+ {
+ 	unsigned long flags;
+ 
+@@ -479,7 +479,7 @@ static void pc236_intr_disable(struct comedi_device * dev)
+  * configured on subdevice 1) and to physically enable the interrupt
+  * (not possible on the PC36AT, except by (re)connecting the IRQ jumper!).
+  */
+-static void pc236_intr_enable(struct comedi_device * dev)
++static void pc236_intr_enable(struct comedi_device *dev)
+ {
+ 	unsigned long flags;
+ 
+@@ -499,7 +499,7 @@ static void pc236_intr_enable(struct comedi_device * dev)
+  * interrupt.
+  * Returns 0 if the interrupt should be ignored.
+  */
+-static int pc236_intr_check(struct comedi_device * dev)
++static int pc236_intr_check(struct comedi_device *dev)
+ {
+ 	int retval = 0;
+ 	unsigned long flags;
+@@ -530,8 +530,8 @@ static int pc236_intr_check(struct comedi_device * dev)
+  * Input from subdevice 1.
+  * Copied from the comedi_parport driver.
+  */
+-static int pc236_intr_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pc236_intr_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[1] = 0;
+ 	return 2;
+@@ -541,8 +541,8 @@ static int pc236_intr_insn(struct comedi_device * dev, struct comedi_subdevice *
+  * Subdevice 1 command test.
+  * Copied from the comedi_parport driver.
+  */
+-static int pc236_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int pc236_intr_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -619,7 +619,7 @@ static int pc236_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevic
+ /*
+  * Subdevice 1 command.
+  */
+-static int pc236_intr_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pc236_intr_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	pc236_intr_enable(dev);
+ 
+@@ -629,7 +629,7 @@ static int pc236_intr_cmd(struct comedi_device * dev, struct comedi_subdevice *
+ /*
+  * Subdevice 1 cancel command.
+  */
+-static int pc236_intr_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pc236_intr_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	pc236_intr_disable(dev);
+ 
+diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
+index 97ac4157adaf..1ca704760067 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc263.c
++++ b/drivers/staging/comedi/drivers/amplc_pc263.c
+@@ -132,8 +132,8 @@ struct pc263_private {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pc263_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pc263_detach(struct comedi_device * dev);
++static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pc263_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_amplc_pc263 = {
+       driver_name:PC263_DRIVER_NAME,
+       module:THIS_MODULE,
+@@ -146,10 +146,10 @@ static struct comedi_driver driver_amplc_pc263 = {
+ 
+ static int pc263_request_region(unsigned minor, unsigned long from,
+ 	unsigned long extent);
+-static int pc263_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int pc263_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int pc263_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int pc263_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * This function looks for a PCI device matching the requested board name,
+@@ -157,7 +157,7 @@ static int pc263_dio_insn_config(struct comedi_device * dev, struct comedi_subde
+  */
+ #ifdef CONFIG_COMEDI_PCI
+ static int
+-pc263_find_pci(struct comedi_device * dev, int bus, int slot,
++pc263_find_pci(struct comedi_device *dev, int bus, int slot,
+ 	struct pci_dev **pci_dev_p)
+ {
+ 	struct pci_dev *pci_dev = NULL;
+@@ -219,7 +219,7 @@ pc263_find_pci(struct comedi_device * dev, int bus, int slot,
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pc263_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase = 0;
+@@ -337,7 +337,7 @@ static int pc263_attach(struct comedi_device * dev, struct comedi_devconfig * it
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int pc263_detach(struct comedi_device * dev)
++static int pc263_detach(struct comedi_device *dev)
+ {
+ 	printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
+ 		PC263_DRIVER_NAME);
+@@ -387,8 +387,8 @@ static int pc263_request_region(unsigned minor, unsigned long from,
+  * useful to applications if you implement the insn_bits interface.
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+-static int pc263_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pc263_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -412,8 +412,8 @@ static int pc263_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+ 	return 2;
+ }
+ 
+-static int pc263_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pc263_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 1)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
+index 70381b5c015b..9037ff4bf0e6 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci224.c
++++ b/drivers/staging/comedi/drivers/amplc_pci224.c
+@@ -428,8 +428,8 @@ struct pci224_private {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pci224_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pci224_detach(struct comedi_device * dev);
++static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pci224_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_amplc_pci224 = {
+       driver_name:DRIVER_NAME,
+       module:THIS_MODULE,
+@@ -446,7 +446,7 @@ COMEDI_PCI_INITCLEANUP(driver_amplc_pci224, pci224_pci_table);
+  * Called from the 'insn_write' function to perform a single write.
+  */
+ static void
+-pci224_ao_set_data(struct comedi_device * dev, int chan, int range, unsigned int data)
++pci224_ao_set_data(struct comedi_device *dev, int chan, int range, unsigned int data)
+ {
+ 	unsigned short mangled;
+ 
+@@ -479,8 +479,8 @@ pci224_ao_set_data(struct comedi_device * dev, int chan, int range, unsigned int
+  * 'insn_write' function for AO subdevice.
+  */
+ static int
+-pci224_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++pci224_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan, range;
+@@ -506,8 +506,8 @@ pci224_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+  * command.
+  */
+ static int
+-pci224_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++pci224_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan;
+@@ -534,7 +534,7 @@ pci224_cascade_ns_to_timer(int osc_base, unsigned int *d1, unsigned int *d2,
+ /*
+  * Kills a command running on the AO subdevice.
+  */
+-static void pci224_ao_stop(struct comedi_device * dev, struct comedi_subdevice * s)
++static void pci224_ao_stop(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	unsigned long flags;
+ 
+@@ -574,7 +574,7 @@ static void pci224_ao_stop(struct comedi_device * dev, struct comedi_subdevice *
+ /*
+  * Handles start of acquisition for the AO subdevice.
+  */
+-static void pci224_ao_start(struct comedi_device * dev, struct comedi_subdevice * s)
++static void pci224_ao_start(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned long flags;
+@@ -601,7 +601,7 @@ static void pci224_ao_start(struct comedi_device * dev, struct comedi_subdevice
+ /*
+  * Handles interrupts from the DAC FIFO.
+  */
+-static void pci224_ao_handle_fifo(struct comedi_device * dev, struct comedi_subdevice * s)
++static void pci224_ao_handle_fifo(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned int num_scans;
+@@ -730,7 +730,7 @@ static void pci224_ao_handle_fifo(struct comedi_device * dev, struct comedi_subd
+  * Internal trigger function to start acquisition on AO subdevice.
+  */
+ static int
+-pci224_ao_inttrig_start(struct comedi_device * dev, struct comedi_subdevice * s,
++pci224_ao_inttrig_start(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int trignum)
+ {
+ 	if (trignum != 0)
+@@ -750,7 +750,7 @@ pci224_ao_inttrig_start(struct comedi_device * dev, struct comedi_subdevice * s,
+  * 'do_cmdtest' function for AO subdevice.
+  */
+ static int
+-pci224_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_cmd * cmd)
++pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	unsigned int tmp;
+@@ -1017,7 +1017,7 @@ pci224_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, struc
+ /*
+  * 'do_cmd' function for AO subdevice.
+  */
+-static int pci224_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+ 	int range;
+@@ -1174,7 +1174,7 @@ static int pci224_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s
+ /*
+  * 'cancel' function for AO subdevice.
+  */
+-static int pci224_ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pci224_ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	pci224_ao_stop(dev, s);
+ 	return 0;
+@@ -1184,7 +1184,7 @@ static int pci224_ao_cancel(struct comedi_device * dev, struct comedi_subdevice
+  * 'munge' data for AO command.
+  */
+ static void
+-pci224_ao_munge(struct comedi_device * dev, struct comedi_subdevice * s, void *data,
++pci224_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s, void *data,
+ 	unsigned int num_bytes, unsigned int chan_index)
+ {
+ 	struct comedi_async *async = s->async;
+@@ -1266,7 +1266,7 @@ static irqreturn_t pci224_interrupt(int irq, void *d)
+  * bus and slot.
+  */
+ static int
+-pci224_find_pci(struct comedi_device * dev, int bus, int slot,
++pci224_find_pci(struct comedi_device *dev, int bus, int slot,
+ 	struct pci_dev **pci_dev_p)
+ {
+ 	struct pci_dev *pci_dev = NULL;
+@@ -1325,7 +1325,7 @@ pci224_find_pci(struct comedi_device * dev, int bus, int slot,
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pci224_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	struct pci_dev *pci_dev;
+@@ -1505,7 +1505,7 @@ static int pci224_attach(struct comedi_device * dev, struct comedi_devconfig * i
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int pci224_detach(struct comedi_device * dev)
++static int pci224_detach(struct comedi_device *dev)
+ {
+ 	printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor, DRIVER_NAME);
+ 
+diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
+index 0fa228f6edc4..570ad457fe55 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci230.c
++++ b/drivers/staging/comedi/drivers/amplc_pci230.c
+@@ -603,8 +603,8 @@ static const unsigned char pci230_ao_bipolar[2] = { 0, 1 };
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pci230_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pci230_detach(struct comedi_device * dev);
++static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pci230_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_amplc_pci230 = {
+       driver_name:"amplc_pci230",
+       module:THIS_MODULE,
+@@ -660,7 +660,7 @@ static short pci230_ai_read(struct comedi_device * dev)
+ 	return data;
+ }
+ 
+-static inline unsigned short pci230_ao_mangle_datum(struct comedi_device * dev,
++static inline unsigned short pci230_ao_mangle_datum(struct comedi_device *dev,
+ 	short datum)
+ {
+ 	/* If a bipolar range was specified, mangle it (straight binary->twos
+@@ -676,7 +676,7 @@ static inline unsigned short pci230_ao_mangle_datum(struct comedi_device * dev,
+ 	return (unsigned short)datum;
+ }
+ 
+-static inline void pci230_ao_write_nofifo(struct comedi_device * dev, short datum,
++static inline void pci230_ao_write_nofifo(struct comedi_device *dev, short datum,
+ 	unsigned int chan)
+ {
+ 	/* Store unmangled datum to be read back later. */
+@@ -687,7 +687,7 @@ static inline void pci230_ao_write_nofifo(struct comedi_device * dev, short datu
+ 			? PCI230_DACOUT1 : PCI230_DACOUT2));
+ }
+ 
+-static inline void pci230_ao_write_fifo(struct comedi_device * dev, short datum,
++static inline void pci230_ao_write_fifo(struct comedi_device *dev, short datum,
+ 	unsigned int chan)
+ {
+ 	/* Store unmangled datum to be read back later. */
+@@ -704,7 +704,7 @@ static inline void pci230_ao_write_fifo(struct comedi_device * dev, short datum,
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pci230_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase1, iobase2;
+@@ -961,7 +961,7 @@ static int pci230_attach(struct comedi_device * dev, struct comedi_devconfig * i
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int pci230_detach(struct comedi_device * dev)
++static int pci230_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: amplc_pci230: remove\n", dev->minor);
+ 
+@@ -984,7 +984,7 @@ static int pci230_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int get_resources(struct comedi_device * dev, unsigned int res_mask,
++static int get_resources(struct comedi_device *dev, unsigned int res_mask,
+ 	unsigned char owner)
+ {
+ 	int ok;
+@@ -1020,13 +1020,13 @@ static int get_resources(struct comedi_device * dev, unsigned int res_mask,
+ 	return ok;
+ }
+ 
+-static inline int get_one_resource(struct comedi_device * dev, unsigned int resource,
++static inline int get_one_resource(struct comedi_device *dev, unsigned int resource,
+ 	unsigned char owner)
+ {
+ 	return get_resources(dev, (1U << resource), owner);
+ }
+ 
+-static void put_resources(struct comedi_device * dev, unsigned int res_mask,
++static void put_resources(struct comedi_device *dev, unsigned int res_mask,
+ 	unsigned char owner)
+ {
+ 	unsigned int i;
+@@ -1046,13 +1046,13 @@ static void put_resources(struct comedi_device * dev, unsigned int res_mask,
+ 	comedi_spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags);
+ }
+ 
+-static inline void put_one_resource(struct comedi_device * dev, unsigned int resource,
++static inline void put_one_resource(struct comedi_device *dev, unsigned int resource,
+ 	unsigned char owner)
+ {
+ 	put_resources(dev, (1U << resource), owner);
+ }
+ 
+-static inline void put_all_resources(struct comedi_device * dev, unsigned char owner)
++static inline void put_all_resources(struct comedi_device *dev, unsigned char owner)
+ {
+ 	put_resources(dev, (1U << NUM_RESOURCES) - 1, owner);
+ }
+@@ -1060,8 +1060,8 @@ static inline void put_all_resources(struct comedi_device * dev, unsigned char o
+ /*
+  *  COMEDI_SUBD_AI instruction;
+  */
+-static int pci230_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci230_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int n, i;
+ 	unsigned int chan, range, aref;
+@@ -1165,8 +1165,8 @@ static int pci230_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ /*
+  *  COMEDI_SUBD_AO instructions;
+  */
+-static int pci230_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci230_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan, range;
+@@ -1193,8 +1193,8 @@ static int pci230_ao_winsn(struct comedi_device * dev, struct comedi_subdevice *
+ 
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+-static int pci230_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci230_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -1205,8 +1205,8 @@ static int pci230_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ 	return i;
+ }
+ 
+-static int pci230_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int pci230_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	unsigned int tmp;
+@@ -1418,8 +1418,8 @@ static int pci230_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice
+ 	return 0;
+ }
+ 
+-static int pci230_ao_inttrig_scan_begin(struct comedi_device * dev,
+-	struct comedi_subdevice * s, unsigned int trig_num)
++static int pci230_ao_inttrig_scan_begin(struct comedi_device *dev,
++	struct comedi_subdevice *s, unsigned int trig_num)
+ {
+ 	unsigned long irqflags;
+ 
+@@ -1450,7 +1450,7 @@ static int pci230_ao_inttrig_scan_begin(struct comedi_device * dev,
+ 	return 1;
+ }
+ 
+-static void pci230_ao_start(struct comedi_device * dev, struct comedi_subdevice * s)
++static void pci230_ao_start(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct comedi_async *async = s->async;
+ 	struct comedi_cmd *cmd = &async->cmd;
+@@ -1538,7 +1538,7 @@ static void pci230_ao_start(struct comedi_device * dev, struct comedi_subdevice
+ 	}
+ }
+ 
+-static int pci230_ao_inttrig_start(struct comedi_device * dev, struct comedi_subdevice * s,
++static int pci230_ao_inttrig_start(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int trig_num)
+ {
+ 	if (trig_num != 0)
+@@ -1550,7 +1550,7 @@ static int pci230_ao_inttrig_start(struct comedi_device * dev, struct comedi_sub
+ 	return 1;
+ }
+ 
+-static int pci230_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	unsigned short daccon;
+ 	unsigned int range;
+@@ -1626,7 +1626,7 @@ static int pci230_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s
+ 	return 0;
+ }
+ 
+-static int pci230_ai_check_scan_period(struct comedi_cmd * cmd)
++static int pci230_ai_check_scan_period(struct comedi_cmd *cmd)
+ {
+ 	unsigned int min_scan_period, chanlist_len;
+ 	int err = 0;
+@@ -1650,8 +1650,8 @@ static int pci230_ai_check_scan_period(struct comedi_cmd * cmd)
+ 	return !err;
+ }
+ 
+-static int pci230_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int pci230_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	unsigned int tmp;
+@@ -2036,8 +2036,8 @@ static int pci230_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice
+ 	return 0;
+ }
+ 
+-static void pci230_ai_update_fifo_trigger_level(struct comedi_device * dev,
+-	struct comedi_subdevice * s)
++static void pci230_ai_update_fifo_trigger_level(struct comedi_device *dev,
++	struct comedi_subdevice *s)
+ {
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned int scanlen = cmd->scan_end_arg;
+@@ -2080,7 +2080,7 @@ static void pci230_ai_update_fifo_trigger_level(struct comedi_device * dev,
+ 	}
+ }
+ 
+-static int pci230_ai_inttrig_convert(struct comedi_device * dev, struct comedi_subdevice * s,
++static int pci230_ai_inttrig_convert(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int trig_num)
+ {
+ 	unsigned long irqflags;
+@@ -2123,8 +2123,8 @@ static int pci230_ai_inttrig_convert(struct comedi_device * dev, struct comedi_s
+ 	return 1;
+ }
+ 
+-static int pci230_ai_inttrig_scan_begin(struct comedi_device * dev,
+-	struct comedi_subdevice * s, unsigned int trig_num)
++static int pci230_ai_inttrig_scan_begin(struct comedi_device *dev,
++	struct comedi_subdevice *s, unsigned int trig_num)
+ {
+ 	unsigned long irqflags;
+ 	unsigned char zgat;
+@@ -2145,7 +2145,7 @@ static int pci230_ai_inttrig_scan_begin(struct comedi_device * dev,
+ 	return 1;
+ }
+ 
+-static void pci230_ai_start(struct comedi_device * dev, struct comedi_subdevice * s)
++static void pci230_ai_start(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	unsigned long irqflags;
+ 	unsigned short conv;
+@@ -2282,7 +2282,7 @@ static void pci230_ai_start(struct comedi_device * dev, struct comedi_subdevice
+ 	}
+ }
+ 
+-static int pci230_ai_inttrig_start(struct comedi_device * dev, struct comedi_subdevice * s,
++static int pci230_ai_inttrig_start(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int trig_num)
+ {
+ 	if (trig_num != 0)
+@@ -2294,7 +2294,7 @@ static int pci230_ai_inttrig_start(struct comedi_device * dev, struct comedi_sub
+ 	return 1;
+ }
+ 
+-static int pci230_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	unsigned int i, chan, range, diff;
+ 	unsigned int res_mask;
+@@ -2534,7 +2534,7 @@ static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round)
+ 	return;
+ }
+ 
+-static void pci230_ct_setup_ns_mode(struct comedi_device * dev, unsigned int ct,
++static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct,
+ 	unsigned int mode, uint64_t ns, unsigned int round)
+ {
+ 	unsigned int clk_src;
+@@ -2553,7 +2553,7 @@ static void pci230_ct_setup_ns_mode(struct comedi_device * dev, unsigned int ct,
+ 	i8254_write(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, count);
+ }
+ 
+-static void pci230_cancel_ct(struct comedi_device * dev, unsigned int ct)
++static void pci230_cancel_ct(struct comedi_device *dev, unsigned int ct)
+ {
+ 	i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct,
+ 		I8254_MODE1);
+@@ -2624,7 +2624,7 @@ static irqreturn_t pci230_interrupt(int irq, void *d)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static void pci230_handle_ao_nofifo(struct comedi_device * dev, struct comedi_subdevice * s)
++static void pci230_handle_ao_nofifo(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	short data;
+ 	int i, ret;
+@@ -2661,7 +2661,7 @@ static void pci230_handle_ao_nofifo(struct comedi_device * dev, struct comedi_su
+ 
+ /* Loads DAC FIFO (if using it) from buffer. */
+ /* Returns 0 if AO finished due to completion or error, 1 if still going. */
+-static int pci230_handle_ao_fifo(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pci230_handle_ao_fifo(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct comedi_async *async = s->async;
+ 	struct comedi_cmd *cmd = &async->cmd;
+@@ -2764,7 +2764,7 @@ static int pci230_handle_ao_fifo(struct comedi_device * dev, struct comedi_subde
+ 	return running;
+ }
+ 
+-static void pci230_handle_ai(struct comedi_device * dev, struct comedi_subdevice * s)
++static void pci230_handle_ai(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	unsigned int events = 0;
+ 	unsigned int status_fifo;
+@@ -2863,7 +2863,7 @@ static void pci230_handle_ai(struct comedi_device * dev, struct comedi_subdevice
+ 	}
+ }
+ 
+-static void pci230_ao_stop(struct comedi_device * dev, struct comedi_subdevice * s)
++static void pci230_ao_stop(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	unsigned long irqflags;
+ 	unsigned char intsrc;
+@@ -2918,13 +2918,13 @@ static void pci230_ao_stop(struct comedi_device * dev, struct comedi_subdevice *
+ 	put_all_resources(dev, OWNER_AOCMD);
+ }
+ 
+-static int pci230_ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pci230_ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	pci230_ao_stop(dev, s);
+ 	return 0;
+ }
+ 
+-static void pci230_ai_stop(struct comedi_device * dev, struct comedi_subdevice * s)
++static void pci230_ai_stop(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	unsigned long irqflags;
+ 	struct comedi_cmd *cmd;
+@@ -2972,7 +2972,7 @@ static void pci230_ai_stop(struct comedi_device * dev, struct comedi_subdevice *
+ 	put_all_resources(dev, OWNER_AICMD);
+ }
+ 
+-static int pci230_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pci230_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	pci230_ai_stop(dev, s);
+ 	return 0;
+diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c
+index c8ffddf4add4..23263ed57532 100644
+--- a/drivers/staging/comedi/drivers/c6xdigio.c
++++ b/drivers/staging/comedi/drivers/c6xdigio.c
+@@ -97,8 +97,8 @@ union encvaluetype {
+ 
+ #define C6XDIGIO_TIME_OUT 20
+ 
+-static int c6xdigio_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int c6xdigio_detach(struct comedi_device * dev);
++static int c6xdigio_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int c6xdigio_detach(struct comedi_device *dev);
+ struct comedi_driver driver_c6xdigio = {
+       driver_name:"c6xdigio",
+       module:THIS_MODULE,
+@@ -338,15 +338,15 @@ static void C6X_encResetAll(unsigned long baseAddr)
+ 	}
+ }
+ 
+-static int c6xdigio_pwmo_insn_read(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++static int c6xdigio_pwmo_insn_read(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	printk("c6xdigio_pwmo_insn_read %x\n", insn->n);
+ 	return insn->n;
+ }
+ 
+-static int c6xdigio_pwmo_insn_write(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++static int c6xdigio_pwmo_insn_write(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -379,8 +379,8 @@ static int c6xdigio_pwmo_insn_write(struct comedi_device * dev,
+ /*  *//* return insn->n; */
+ /* } */
+ 
+-static int c6xdigio_ei_insn_read(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++static int c6xdigio_ei_insn_read(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	/*   printk("c6xdigio_ei__insn_read %x\n", insn->n); */
+ 	int n;
+@@ -393,7 +393,7 @@ static int c6xdigio_ei_insn_read(struct comedi_device * dev,
+ 	return n;
+ }
+ 
+-static void board_init(struct comedi_device * dev)
++static void board_init(struct comedi_device *dev)
+ {
+ 
+ 	/* printk("Inside board_init\n"); */
+@@ -426,7 +426,7 @@ static struct pnp_driver c6xdigio_pnp_driver = {
+ 	.id_table = c6xdigio_pnp_tbl,
+ };
+ 
+-static int c6xdigio_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int c6xdigio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int result = 0;
+ 	unsigned long iobase;
+@@ -495,7 +495,7 @@ static int c6xdigio_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	return 0;
+ }
+ 
+-static int c6xdigio_detach(struct comedi_device * dev)
++static int c6xdigio_detach(struct comedi_device *dev)
+ {
+ /* board_halt(dev);  may not need this */
+ 
+diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
+index e7ba3e4288a1..8e07a52e4d13 100644
+--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
++++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
+@@ -89,8 +89,8 @@ struct das16cs_private {
+ };
+ #define devpriv ((struct das16cs_private *)dev->private)
+ 
+-static int das16cs_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int das16cs_detach(struct comedi_device * dev);
++static int das16cs_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int das16cs_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_das16cs = {
+       driver_name:"cb_das16_cs",
+       module:THIS_MODULE,
+@@ -165,7 +165,7 @@ static const struct das16cs_board *das16cs_probe(struct comedi_device * dev,
+ 	return NULL;
+ }
+ 
+-static int das16cs_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int das16cs_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct pcmcia_device *link;
+ 	struct comedi_subdevice *s;
+@@ -265,7 +265,7 @@ static int das16cs_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	return 1;
+ }
+ 
+-static int das16cs_detach(struct comedi_device * dev)
++static int das16cs_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: das16cs: remove\n", dev->minor);
+ 
+@@ -286,8 +286,8 @@ static irqreturn_t das16cs_interrupt(int irq, void *d)
+  * "instructions" read/write data in "one-shot" or "software-triggered"
+  * mode.
+  */
+-static int das16cs_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das16cs_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int to;
+@@ -328,13 +328,13 @@ static int das16cs_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice
+ 	return i;
+ }
+ 
+-static int das16cs_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int das16cs_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	return -EINVAL;
+ }
+ 
+-static int das16cs_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int das16cs_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -489,8 +489,8 @@ static int das16cs_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevic
+ 	return 0;
+ }
+ 
+-static int das16cs_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das16cs_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -535,8 +535,8 @@ static int das16cs_ao_winsn(struct comedi_device * dev, struct comedi_subdevice
+ 
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+-static int das16cs_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das16cs_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -552,8 +552,8 @@ static int das16cs_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice
+  * useful to applications if you implement the insn_bits interface.
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+-static int das16cs_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das16cs_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -572,8 +572,8 @@ static int das16cs_dio_insn_bits(struct comedi_device * dev, struct comedi_subde
+ 	return 2;
+ }
+ 
+-static int das16cs_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das16cs_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	int bits;
+@@ -610,14 +610,14 @@ static int das16cs_dio_insn_config(struct comedi_device * dev, struct comedi_sub
+ 	return insn->n;
+ }
+ 
+-static int das16cs_timer_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das16cs_timer_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	return -EINVAL;
+ }
+ 
+-static int das16cs_timer_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das16cs_timer_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	return -EINVAL;
+ }
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
+index 0b09fc9bd4fb..a7b75808bda5 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas.c
+@@ -441,8 +441,8 @@ struct cb_pcidas_private {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int cb_pcidas_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int cb_pcidas_detach(struct comedi_device * dev);
++static int cb_pcidas_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int cb_pcidas_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_cb_pcidas = {
+       driver_name:"cb_pcidas",
+       module:THIS_MODULE,
+@@ -509,7 +509,7 @@ static inline unsigned int cal_enable_bits(struct comedi_device * dev)
+  * Attach is called by the Comedi core to configure the driver
+  * for a particular board.
+  */
+-static int cb_pcidas_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int cb_pcidas_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	struct pci_dev *pcidev;
+@@ -720,7 +720,7 @@ static int cb_pcidas_attach(struct comedi_device * dev, struct comedi_devconfig
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int cb_pcidas_detach(struct comedi_device * dev)
++static int cb_pcidas_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: cb_pcidas: remove\n", dev->minor);
+ 
+@@ -754,8 +754,8 @@ static int cb_pcidas_detach(struct comedi_device * dev)
+  * "instructions" read/write data in "one-shot" or "software-triggered"
+  * mode.
+  */
+-static int cb_pcidas_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int cb_pcidas_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, i;
+ 	unsigned int bits;
+@@ -806,7 +806,7 @@ static int cb_pcidas_ai_rinsn(struct comedi_device * dev, struct comedi_subdevic
+ 	return n;
+ }
+ 
+-static int ai_config_calibration_source(struct comedi_device * dev, unsigned int * data)
++static int ai_config_calibration_source(struct comedi_device *dev, unsigned int *data)
+ {
+ 	static const int num_calibration_sources = 8;
+ 	unsigned int source = data[1];
+@@ -821,8 +821,8 @@ static int ai_config_calibration_source(struct comedi_device * dev, unsigned int
+ 	return 2;
+ }
+ 
+-static int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int id = data[0];
+ 
+@@ -838,8 +838,8 @@ static int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ /* analog output insn for pcidas-1000 and 1200 series */
+-static int cb_pcidas_ao_nofifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int cb_pcidas_ao_nofifo_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int channel;
+ 	unsigned long flags;
+@@ -863,8 +863,8 @@ static int cb_pcidas_ao_nofifo_winsn(struct comedi_device * dev, struct comedi_s
+ }
+ 
+ /* analog output insn for pcidas-1602 series */
+-static int cb_pcidas_ao_fifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int cb_pcidas_ao_fifo_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int channel;
+ 	unsigned long flags;
+@@ -894,16 +894,16 @@ static int cb_pcidas_ao_fifo_winsn(struct comedi_device * dev, struct comedi_sub
+ 
+ /* analog output readback insn */
+ /* XXX loses track of analog output value back after an analog ouput command is executed */
+-static int cb_pcidas_ao_readback_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int cb_pcidas_ao_readback_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)];
+ 
+ 	return 1;
+ }
+ 
+-static int eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int eeprom_read_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	uint8_t nvram_data;
+ 	int retval;
+@@ -917,16 +917,16 @@ static int eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice
+ 	return 1;
+ }
+ 
+-static int caldac_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int caldac_write_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	const unsigned int channel = CR_CHAN(insn->chanspec);
+ 
+ 	return caldac_8800_write(dev, channel, data[0]);
+ }
+ 
+-static int caldac_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int caldac_read_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[0] = devpriv->caldac_value[CR_CHAN(insn->chanspec)];
+ 
+@@ -934,7 +934,7 @@ static int caldac_read_insn(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ /* 1602/16 pregain offset */
+-static int dac08_write(struct comedi_device * dev, unsigned int value)
++static int dac08_write(struct comedi_device *dev, unsigned int value)
+ {
+ 	if (devpriv->dac08_value == value)
+ 		return 1;
+@@ -954,21 +954,21 @@ static int dac08_write(struct comedi_device * dev, unsigned int value)
+ 	return 1;
+ }
+ 
+-static int dac08_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dac08_write_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	return dac08_write(dev, data[0]);
+ }
+ 
+-static int dac08_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dac08_read_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[0] = devpriv->dac08_value;
+ 
+ 	return 1;
+ }
+ 
+-static int cb_pcidas_trimpot_write(struct comedi_device * dev,
++static int cb_pcidas_trimpot_write(struct comedi_device *dev,
+ 	unsigned int channel, unsigned int value)
+ {
+ 	if (devpriv->trimpot_value[channel] == value)
+@@ -991,16 +991,16 @@ static int cb_pcidas_trimpot_write(struct comedi_device * dev,
+ 	return 1;
+ }
+ 
+-static int trimpot_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int trimpot_write_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int channel = CR_CHAN(insn->chanspec);
+ 
+ 	return cb_pcidas_trimpot_write(dev, channel, data[0]);
+ }
+ 
+-static int trimpot_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int trimpot_read_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int channel = CR_CHAN(insn->chanspec);
+ 
+@@ -1009,8 +1009,8 @@ static int trimpot_read_insn(struct comedi_device * dev, struct comedi_subdevice
+ 	return 1;
+ }
+ 
+-static int cb_pcidas_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -1164,7 +1164,7 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device * dev, struct comedi_subdev
+ 	return 0;
+ }
+ 
+-static int cb_pcidas_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int cb_pcidas_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct comedi_async *async = s->async;
+ 	struct comedi_cmd *cmd = &async->cmd;
+@@ -1251,8 +1251,8 @@ static int cb_pcidas_ai_cmd(struct comedi_device * dev, struct comedi_subdevice
+ 	return 0;
+ }
+ 
+-static int cb_pcidas_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int cb_pcidas_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -1364,7 +1364,7 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device * dev, struct comedi_subdev
+ 	return 0;
+ }
+ 
+-static int cb_pcidas_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int cb_pcidas_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct comedi_async *async = s->async;
+ 	struct comedi_cmd *cmd = &async->cmd;
+@@ -1589,7 +1589,7 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static void handle_ao_interrupt(struct comedi_device * dev, unsigned int status)
++static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status)
+ {
+ 	struct comedi_subdevice *s = dev->write_subdev;
+ 	struct comedi_async *async = s->async;
+@@ -1646,7 +1646,7 @@ static void handle_ao_interrupt(struct comedi_device * dev, unsigned int status)
+ }
+ 
+ /* cancel analog input command */
+-static int cb_pcidas_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int cb_pcidas_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	unsigned long flags;
+ 
+@@ -1683,7 +1683,7 @@ static int cb_pcidas_ao_cancel(struct comedi_device *dev,
+ 	return 0;
+ }
+ 
+-static void cb_pcidas_load_counters(struct comedi_device * dev, unsigned int *ns,
++static void cb_pcidas_load_counters(struct comedi_device *dev, unsigned int *ns,
+ 	int rounding_flags)
+ {
+ 	i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1),
+@@ -1696,7 +1696,7 @@ static void cb_pcidas_load_counters(struct comedi_device * dev, unsigned int *ns
+ 		devpriv->divisor2, 2);
+ }
+ 
+-static void write_calibration_bitstream(struct comedi_device * dev,
++static void write_calibration_bitstream(struct comedi_device *dev,
+ 	unsigned int register_bits, unsigned int bitstream,
+ 	unsigned int bitstream_length)
+ {
+@@ -1713,7 +1713,7 @@ static void write_calibration_bitstream(struct comedi_device * dev,
+ 	}
+ }
+ 
+-static int caldac_8800_write(struct comedi_device * dev, unsigned int address,
++static int caldac_8800_write(struct comedi_device *dev, unsigned int address,
+ 	uint8_t value)
+ {
+ 	static const int num_caldac_channels = 8;
+@@ -1743,7 +1743,7 @@ static int caldac_8800_write(struct comedi_device * dev, unsigned int address,
+ 	return 1;
+ }
+ 
+-static int trimpot_7376_write(struct comedi_device * dev, uint8_t value)
++static int trimpot_7376_write(struct comedi_device *dev, uint8_t value)
+ {
+ 	static const int bitstream_length = 7;
+ 	unsigned int bitstream = value & 0x7f;
+@@ -1766,7 +1766,7 @@ static int trimpot_7376_write(struct comedi_device * dev, uint8_t value)
+ /* For 1602/16 only
+  * ch 0 : adc gain
+  * ch 1 : adc postgain offset */
+-static int trimpot_8402_write(struct comedi_device * dev, unsigned int channel,
++static int trimpot_8402_write(struct comedi_device *dev, unsigned int channel,
+ 	uint8_t value)
+ {
+ 	static const int bitstream_length = 10;
+@@ -1802,7 +1802,7 @@ static int wait_for_nvram_ready(unsigned long s5933_base_addr)
+ 	return -1;
+ }
+ 
+-static int nvram_read(struct comedi_device * dev, unsigned int address, uint8_t * data)
++static int nvram_read(struct comedi_device *dev, unsigned int address, uint8_t *data)
+ {
+ 	unsigned long iobase = devpriv->s5933_config;
+ 
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
+index 10401d91113e..ba465c432402 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
+@@ -585,7 +585,7 @@ static const struct hw_fifo_info ai_fifo_60xx = {
+ #define MAX_AI_DMA_RING_COUNT (0x80000 / DMA_BUFFER_SIZE)
+ #define MIN_AI_DMA_RING_COUNT (0x10000 / DMA_BUFFER_SIZE)
+ #define AO_DMA_RING_COUNT (0x10000 / DMA_BUFFER_SIZE)
+-static inline unsigned int ai_dma_ring_count(struct pcidas64_board * board)
++static inline unsigned int ai_dma_ring_count(struct pcidas64_board *board)
+ {
+ 	if (board->layout == LAYOUT_4020)
+ 		return MAX_AI_DMA_RING_COUNT;
+@@ -1050,7 +1050,7 @@ static inline struct pcidas64_board *board(const struct comedi_device * dev)
+ 	return (struct pcidas64_board *) dev->board_ptr;
+ }
+ 
+-static inline unsigned short se_diff_bit_6xxx(struct comedi_device * dev,
++static inline unsigned short se_diff_bit_6xxx(struct comedi_device *dev,
+ 	int use_differential)
+ {
+ 	if ((board(dev)->layout == LAYOUT_64XX && !use_differential) ||
+@@ -1128,8 +1128,8 @@ static inline struct pcidas64_private *priv(struct comedi_device * dev)
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int detach(struct comedi_device * dev);
++static int attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int detach(struct comedi_device *dev);
+ static struct comedi_driver driver_cb_pcidas = {
+       driver_name:"cb_pcidas64",
+       module:THIS_MODULE,
+@@ -1247,7 +1247,7 @@ static unsigned int ai_range_bits_6xxx(const struct comedi_device * dev,
+ 	return bits;
+ }
+ 
+-static unsigned int hw_revision(const struct comedi_device * dev,
++static unsigned int hw_revision(const struct comedi_device *dev,
+ 	uint16_t hw_status_bits)
+ {
+ 	if (board(dev)->layout == LAYOUT_4020)
+@@ -1256,7 +1256,7 @@ static unsigned int hw_revision(const struct comedi_device * dev,
+ 	return (hw_status_bits >> 12) & 0xf;
+ }
+ 
+-static void set_dac_range_bits(struct comedi_device * dev, volatile uint16_t * bits,
++static void set_dac_range_bits(struct comedi_device *dev, volatile uint16_t *bits,
+ 	unsigned int channel, unsigned int range)
+ {
+ 	unsigned int code = board(dev)->ao_range_code[range];
+@@ -1270,13 +1270,13 @@ static void set_dac_range_bits(struct comedi_device * dev, volatile uint16_t * b
+ 	*bits |= code << (2 * channel);
+ };
+ 
+-static inline int ao_cmd_is_supported(const struct pcidas64_board * board)
++static inline int ao_cmd_is_supported(const struct pcidas64_board *board)
+ {
+ 	return board->ao_nchan && board->layout != LAYOUT_4020;
+ }
+ 
+ /* initialize plx9080 chip */
+-static void init_plx9080(struct comedi_device * dev)
++static void init_plx9080(struct comedi_device *dev)
+ {
+ 	uint32_t bits;
+ 	void *plx_iobase = priv(dev)->plx9080_iobase;
+@@ -1366,7 +1366,7 @@ static void init_plx9080(struct comedi_device * dev)
+ 
+ /* Allocate and initialize the subdevice structures.
+  */
+-static int setup_subdevices(struct comedi_device * dev)
++static int setup_subdevices(struct comedi_device *dev)
+ {
+ 	struct comedi_subdevice *s;
+ 	void *dio_8255_iobase;
+@@ -1529,14 +1529,14 @@ static int setup_subdevices(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static void disable_plx_interrupts(struct comedi_device * dev)
++static void disable_plx_interrupts(struct comedi_device *dev)
+ {
+ 	priv(dev)->plx_intcsr_bits = 0;
+ 	writel(priv(dev)->plx_intcsr_bits,
+ 		priv(dev)->plx9080_iobase + PLX_INTRCS_REG);
+ }
+ 
+-static void init_stc_registers(struct comedi_device * dev)
++static void init_stc_registers(struct comedi_device *dev)
+ {
+ 	uint16_t bits;
+ 	unsigned long flags;
+@@ -1578,7 +1578,7 @@ static void init_stc_registers(struct comedi_device * dev)
+ 	disable_ai_pacing(dev);
+ };
+ 
+-int alloc_and_init_dma_members(struct comedi_device * dev)
++int alloc_and_init_dma_members(struct comedi_device *dev)
+ {
+ 	int i;
+ 
+@@ -1664,7 +1664,7 @@ int alloc_and_init_dma_members(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static inline void warn_external_queue(struct comedi_device * dev)
++static inline void warn_external_queue(struct comedi_device *dev)
+ {
+ 	comedi_error(dev,
+ 		"AO command and AI external channel queue cannot be used simultaneously.");
+@@ -1824,7 +1824,7 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int detach(struct comedi_device * dev)
++static int detach(struct comedi_device *dev)
+ {
+ 	unsigned int i;
+ 
+@@ -1884,8 +1884,8 @@ static int detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int bits = 0, n, i;
+ 	unsigned int channel, range, aref;
+@@ -2021,7 +2021,7 @@ static int ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int ai_config_calibration_source(struct comedi_device * dev, unsigned int * data)
++static int ai_config_calibration_source(struct comedi_device *dev, unsigned int *data)
+ {
+ 	unsigned int source = data[1];
+ 	int num_calibration_sources;
+@@ -2041,7 +2041,7 @@ static int ai_config_calibration_source(struct comedi_device * dev, unsigned int
+ 	return 2;
+ }
+ 
+-static int ai_config_block_size(struct comedi_device * dev, unsigned int * data)
++static int ai_config_block_size(struct comedi_device *dev, unsigned int *data)
+ {
+ 	int fifo_size;
+ 	const struct hw_fifo_info *const fifo = board(dev)->ai_fifo;
+@@ -2068,7 +2068,7 @@ static int ai_config_block_size(struct comedi_device * dev, unsigned int * data)
+ 	return 2;
+ }
+ 
+-static int ai_config_master_clock_4020(struct comedi_device * dev, unsigned int * data)
++static int ai_config_master_clock_4020(struct comedi_device *dev, unsigned int *data)
+ {
+ 	unsigned int divisor = data[4];
+ 	int retval = 0;
+@@ -2094,7 +2094,7 @@ static int ai_config_master_clock_4020(struct comedi_device * dev, unsigned int
+ }
+ 
+ /* XXX could add support for 60xx series */
+-static int ai_config_master_clock(struct comedi_device * dev, unsigned int * data)
++static int ai_config_master_clock(struct comedi_device *dev, unsigned int *data)
+ {
+ 
+ 	switch (board(dev)->layout) {
+@@ -2109,8 +2109,8 @@ static int ai_config_master_clock(struct comedi_device * dev, unsigned int * dat
+ 	return -EINVAL;
+ }
+ 
+-static int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int id = data[0];
+ 
+@@ -2131,8 +2131,8 @@ static int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice *
+ 	return -EINVAL;
+ }
+ 
+-static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -2316,7 +2316,7 @@ static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int use_hw_sample_counter(struct comedi_cmd * cmd)
++static int use_hw_sample_counter(struct comedi_cmd *cmd)
+ {
+ /* disable for now until I work out a race */
+ 	return 0;
+@@ -2327,7 +2327,7 @@ static int use_hw_sample_counter(struct comedi_cmd * cmd)
+ 		return 0;
+ }
+ 
+-static void setup_sample_counters(struct comedi_device * dev, struct comedi_cmd * cmd)
++static void setup_sample_counters(struct comedi_device *dev, struct comedi_cmd *cmd)
+ {
+ 	if (cmd->stop_src == TRIG_COUNT) {
+ 		/*  set software count */
+@@ -2344,7 +2344,7 @@ static void setup_sample_counters(struct comedi_device * dev, struct comedi_cmd
+ 	}
+ }
+ 
+-static inline unsigned int dma_transfer_size(struct comedi_device * dev)
++static inline unsigned int dma_transfer_size(struct comedi_device *dev)
+ {
+ 	unsigned int num_samples;
+ 
+@@ -2357,7 +2357,7 @@ static inline unsigned int dma_transfer_size(struct comedi_device * dev)
+ 	return num_samples;
+ }
+ 
+-static void disable_ai_pacing(struct comedi_device * dev)
++static void disable_ai_pacing(struct comedi_device *dev)
+ {
+ 	unsigned long flags;
+ 
+@@ -2374,7 +2374,7 @@ static void disable_ai_pacing(struct comedi_device * dev)
+ 		priv(dev)->main_iobase + ADC_CONTROL0_REG);
+ }
+ 
+-static void disable_ai_interrupts(struct comedi_device * dev)
++static void disable_ai_interrupts(struct comedi_device *dev)
+ {
+ 	unsigned long flags;
+ 
+@@ -2390,7 +2390,7 @@ static void disable_ai_interrupts(struct comedi_device * dev)
+ 	DEBUG_PRINT("intr enable bits 0x%x\n", priv(dev)->intr_enable_bits);
+ }
+ 
+-static void enable_ai_interrupts(struct comedi_device * dev, const struct comedi_cmd * cmd)
++static void enable_ai_interrupts(struct comedi_device *dev, const struct comedi_cmd *cmd)
+ {
+ 	uint32_t bits;
+ 	unsigned long flags;
+@@ -2411,14 +2411,14 @@ static void enable_ai_interrupts(struct comedi_device * dev, const struct comedi
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ }
+ 
+-static uint32_t ai_convert_counter_6xxx(const struct comedi_device * dev,
+-	const struct comedi_cmd * cmd)
++static uint32_t ai_convert_counter_6xxx(const struct comedi_device *dev,
++	const struct comedi_cmd *cmd)
+ {
+ 	/*  supposed to load counter with desired divisor minus 3 */
+ 	return cmd->convert_arg / TIMER_BASE - 3;
+ }
+ 
+-static uint32_t ai_scan_counter_6xxx(struct comedi_device * dev, struct comedi_cmd * cmd)
++static uint32_t ai_scan_counter_6xxx(struct comedi_device *dev, struct comedi_cmd *cmd)
+ {
+ 	uint32_t count;
+ 	/*  figure out how long we need to delay at end of scan */
+@@ -2438,7 +2438,7 @@ static uint32_t ai_scan_counter_6xxx(struct comedi_device * dev, struct comedi_c
+ 	return count - 3;
+ }
+ 
+-static uint32_t ai_convert_counter_4020(struct comedi_device * dev, struct comedi_cmd * cmd)
++static uint32_t ai_convert_counter_4020(struct comedi_device *dev, struct comedi_cmd *cmd)
+ {
+ 	unsigned int divisor;
+ 
+@@ -2459,8 +2459,8 @@ static uint32_t ai_convert_counter_4020(struct comedi_device * dev, struct comed
+ 	return divisor - 2;
+ }
+ 
+-static void select_master_clock_4020(struct comedi_device * dev,
+-	const struct comedi_cmd * cmd)
++static void select_master_clock_4020(struct comedi_device *dev,
++	const struct comedi_cmd *cmd)
+ {
+ 	/*  select internal/external master clock */
+ 	priv(dev)->hw_config_bits &= ~MASTER_CLOCK_4020_MASK;
+@@ -2478,7 +2478,7 @@ static void select_master_clock_4020(struct comedi_device * dev,
+ 		priv(dev)->main_iobase + HW_CONFIG_REG);
+ }
+ 
+-static void select_master_clock(struct comedi_device * dev, const struct comedi_cmd * cmd)
++static void select_master_clock(struct comedi_device *dev, const struct comedi_cmd *cmd)
+ {
+ 	switch (board(dev)->layout) {
+ 	case LAYOUT_4020:
+@@ -2489,7 +2489,7 @@ static void select_master_clock(struct comedi_device * dev, const struct comedi_
+ 	}
+ }
+ 
+-static inline void dma_start_sync(struct comedi_device * dev, unsigned int channel)
++static inline void dma_start_sync(struct comedi_device *dev, unsigned int channel)
+ {
+ 	unsigned long flags;
+ 
+@@ -2506,7 +2506,7 @@ static inline void dma_start_sync(struct comedi_device * dev, unsigned int chann
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ }
+ 
+-static void set_ai_pacing(struct comedi_device * dev, struct comedi_cmd * cmd)
++static void set_ai_pacing(struct comedi_device *dev, struct comedi_cmd *cmd)
+ {
+ 	uint32_t convert_counter = 0, scan_counter = 0;
+ 
+@@ -2537,7 +2537,7 @@ static void set_ai_pacing(struct comedi_device * dev, struct comedi_cmd * cmd)
+ 	DEBUG_PRINT("scan counter 0x%x\n", scan_counter);
+ }
+ 
+-static int use_internal_queue_6xxx(const struct comedi_cmd * cmd)
++static int use_internal_queue_6xxx(const struct comedi_cmd *cmd)
+ {
+ 	int i;
+ 	for (i = 0; i + 1 < cmd->chanlist_len; i++) {
+@@ -2553,7 +2553,7 @@ static int use_internal_queue_6xxx(const struct comedi_cmd * cmd)
+ 	return 1;
+ }
+ 
+-static int setup_channel_queue(struct comedi_device * dev, const struct comedi_cmd * cmd)
++static int setup_channel_queue(struct comedi_device *dev, const struct comedi_cmd *cmd)
+ {
+ 	unsigned short bits;
+ 	int i;
+@@ -2655,7 +2655,7 @@ static int setup_channel_queue(struct comedi_device * dev, const struct comedi_c
+ 	return 0;
+ }
+ 
+-static inline void load_first_dma_descriptor(struct comedi_device * dev,
++static inline void load_first_dma_descriptor(struct comedi_device *dev,
+ 	unsigned int dma_channel, unsigned int descriptor_bits)
+ {
+ 	/* The transfer size, pci address, and local address registers
+@@ -2682,7 +2682,7 @@ static inline void load_first_dma_descriptor(struct comedi_device * dev,
+ 	}
+ }
+ 
+-static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct comedi_async *async = s->async;
+ 	struct comedi_cmd *cmd = &async->cmd;
+@@ -2800,7 +2800,7 @@ static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ }
+ 
+ /* read num_samples from 16 bit wide ai fifo */
+-static void pio_drain_ai_fifo_16(struct comedi_device * dev)
++static void pio_drain_ai_fifo_16(struct comedi_device *dev)
+ {
+ 	struct comedi_subdevice *s = dev->read_subdev;
+ 	struct comedi_async *async = s->async;
+@@ -2867,7 +2867,7 @@ static void pio_drain_ai_fifo_16(struct comedi_device * dev)
+  * dma transfers (it only supports the use of pio for draining the last remaining
+  * points from the fifo when a data aquisition operation has completed).
+  */
+-static void pio_drain_ai_fifo_32(struct comedi_device * dev)
++static void pio_drain_ai_fifo_32(struct comedi_device *dev)
+ {
+ 	struct comedi_subdevice *s = dev->read_subdev;
+ 	struct comedi_async *async = s->async;
+@@ -2901,7 +2901,7 @@ static void pio_drain_ai_fifo_32(struct comedi_device * dev)
+ }
+ 
+ /* empty fifo */
+-static void pio_drain_ai_fifo(struct comedi_device * dev)
++static void pio_drain_ai_fifo(struct comedi_device *dev)
+ {
+ 	if (board(dev)->layout == LAYOUT_4020) {
+ 		pio_drain_ai_fifo_32(dev);
+@@ -2909,7 +2909,7 @@ static void pio_drain_ai_fifo(struct comedi_device * dev)
+ 		pio_drain_ai_fifo_16(dev);
+ }
+ 
+-static void drain_dma_buffers(struct comedi_device * dev, unsigned int channel)
++static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel)
+ {
+ 	struct comedi_async *async = dev->read_subdev->async;
+ 	uint32_t next_transfer_addr;
+@@ -2955,7 +2955,7 @@ static void drain_dma_buffers(struct comedi_device * dev, unsigned int channel)
+ 	 * unused buffer) */
+ }
+ 
+-void handle_ai_interrupt(struct comedi_device * dev, unsigned short status,
++void handle_ai_interrupt(struct comedi_device *dev, unsigned short status,
+ 	unsigned int plx_status)
+ {
+ 	struct comedi_subdevice *s = dev->read_subdev;
+@@ -3009,7 +3009,7 @@ void handle_ai_interrupt(struct comedi_device * dev, unsigned short status,
+ 	cfc_handle_events(dev, s);
+ }
+ 
+-static inline unsigned int prev_ao_dma_index(struct comedi_device * dev)
++static inline unsigned int prev_ao_dma_index(struct comedi_device *dev)
+ {
+ 	unsigned int buffer_index;
+ 
+@@ -3020,7 +3020,7 @@ static inline unsigned int prev_ao_dma_index(struct comedi_device * dev)
+ 	return buffer_index;
+ }
+ 
+-static int last_ao_dma_load_completed(struct comedi_device * dev)
++static int last_ao_dma_load_completed(struct comedi_device *dev)
+ {
+ 	unsigned int buffer_index;
+ 	unsigned int transfer_address;
+@@ -3039,7 +3039,7 @@ static int last_ao_dma_load_completed(struct comedi_device * dev)
+ 	return 1;
+ }
+ 
+-static int ao_stopped_by_error(struct comedi_device * dev, const struct comedi_cmd * cmd)
++static int ao_stopped_by_error(struct comedi_device *dev, const struct comedi_cmd *cmd)
+ {
+ 	if (cmd->stop_src == TRIG_NONE)
+ 		return 1;
+@@ -3052,7 +3052,7 @@ static int ao_stopped_by_error(struct comedi_device * dev, const struct comedi_c
+ 	return 0;
+ }
+ 
+-static inline int ao_dma_needs_restart(struct comedi_device * dev,
++static inline int ao_dma_needs_restart(struct comedi_device *dev,
+ 	unsigned short dma_status)
+ {
+ 	if ((dma_status & PLX_DMA_DONE_BIT) == 0 ||
+@@ -3064,7 +3064,7 @@ static inline int ao_dma_needs_restart(struct comedi_device * dev,
+ 	return 1;
+ }
+ 
+-static void restart_ao_dma(struct comedi_device * dev)
++static void restart_ao_dma(struct comedi_device *dev)
+ {
+ 	unsigned int dma_desc_bits;
+ 
+@@ -3077,7 +3077,7 @@ static void restart_ao_dma(struct comedi_device * dev)
+ 	dma_start_sync(dev, 0);
+ }
+ 
+-static void handle_ao_interrupt(struct comedi_device * dev, unsigned short status,
++static void handle_ao_interrupt(struct comedi_device *dev, unsigned short status,
+ 	unsigned int plx_status)
+ {
+ 	struct comedi_subdevice *s = dev->write_subdev;
+@@ -3165,7 +3165,7 @@ static irqreturn_t handle_interrupt(int irq, void *d)
+ 	return IRQ_HANDLED;
+ }
+ 
+-void abort_dma(struct comedi_device * dev, unsigned int channel)
++void abort_dma(struct comedi_device *dev, unsigned int channel)
+ {
+ 	unsigned long flags;
+ 
+@@ -3177,7 +3177,7 @@ void abort_dma(struct comedi_device * dev, unsigned int channel)
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ }
+ 
+-static int ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	unsigned long flags;
+ 
+@@ -3197,8 +3197,8 @@ static int ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	int range = CR_RANGE(insn->chanspec);
+@@ -3227,15 +3227,15 @@ static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int ao_readback_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ao_readback_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[0] = priv(dev)->ao_value[CR_CHAN(insn->chanspec)];
+ 
+ 	return 1;
+ }
+ 
+-static void set_dac_control0_reg(struct comedi_device * dev, const struct comedi_cmd * cmd)
++static void set_dac_control0_reg(struct comedi_device *dev, const struct comedi_cmd *cmd)
+ {
+ 	unsigned int bits = DAC_ENABLE_BIT | WAVEFORM_GATE_LEVEL_BIT |
+ 		WAVEFORM_GATE_ENABLE_BIT | WAVEFORM_GATE_SELECT_BIT;
+@@ -3255,7 +3255,7 @@ static void set_dac_control0_reg(struct comedi_device * dev, const struct comedi
+ 	writew(bits, priv(dev)->main_iobase + DAC_CONTROL0_REG);
+ }
+ 
+-static void set_dac_control1_reg(struct comedi_device * dev, const struct comedi_cmd * cmd)
++static void set_dac_control1_reg(struct comedi_device *dev, const struct comedi_cmd *cmd)
+ {
+ 	int i;
+ 
+@@ -3272,7 +3272,7 @@ static void set_dac_control1_reg(struct comedi_device * dev, const struct comedi
+ 		priv(dev)->main_iobase + DAC_CONTROL1_REG);
+ }
+ 
+-static void set_dac_select_reg(struct comedi_device * dev, const struct comedi_cmd * cmd)
++static void set_dac_select_reg(struct comedi_device *dev, const struct comedi_cmd *cmd)
+ {
+ 	uint16_t bits;
+ 	unsigned int first_channel, last_channel;
+@@ -3287,7 +3287,7 @@ static void set_dac_select_reg(struct comedi_device * dev, const struct comedi_c
+ 	writew(bits, priv(dev)->main_iobase + DAC_SELECT_REG);
+ }
+ 
+-static void set_dac_interval_regs(struct comedi_device * dev, const struct comedi_cmd * cmd)
++static void set_dac_interval_regs(struct comedi_device *dev, const struct comedi_cmd *cmd)
+ {
+ 	unsigned int divisor;
+ 
+@@ -3305,8 +3305,8 @@ static void set_dac_interval_regs(struct comedi_device * dev, const struct comed
+ 		priv(dev)->main_iobase + DAC_SAMPLE_INTERVAL_UPPER_REG);
+ }
+ 
+-static unsigned int load_ao_dma_buffer(struct comedi_device * dev,
+-	const struct comedi_cmd * cmd)
++static unsigned int load_ao_dma_buffer(struct comedi_device *dev,
++	const struct comedi_cmd *cmd)
+ {
+ 	unsigned int num_bytes, buffer_index, prev_buffer_index;
+ 	unsigned int next_bits;
+@@ -3349,7 +3349,7 @@ static unsigned int load_ao_dma_buffer(struct comedi_device * dev,
+ 	return num_bytes;
+ }
+ 
+-static void load_ao_dma(struct comedi_device * dev, const struct comedi_cmd * cmd)
++static void load_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
+ {
+ 	unsigned int num_bytes;
+ 	unsigned int next_transfer_addr;
+@@ -3371,7 +3371,7 @@ static void load_ao_dma(struct comedi_device * dev, const struct comedi_cmd * cm
+ 	} while (num_bytes >= DMA_BUFFER_SIZE);
+ }
+ 
+-static int prep_ao_dma(struct comedi_device * dev, const struct comedi_cmd * cmd)
++static int prep_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
+ {
+ 	unsigned int num_bytes;
+ 	int i;
+@@ -3405,7 +3405,7 @@ static int prep_ao_dma(struct comedi_device * dev, const struct comedi_cmd * cmd
+ 	return 0;
+ }
+ 
+-static inline int external_ai_queue_in_use(struct comedi_device * dev)
++static inline int external_ai_queue_in_use(struct comedi_device *dev)
+ {
+ 	if (dev->read_subdev->busy)
+ 		return 0;
+@@ -3416,7 +3416,7 @@ static inline int external_ai_queue_in_use(struct comedi_device * dev)
+ 	return 1;
+ }
+ 
+-static int ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+ 
+@@ -3441,7 +3441,7 @@ static int ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ao_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
++static int ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int trig_num)
+ {
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+@@ -3464,8 +3464,8 @@ static int ao_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -3580,7 +3580,7 @@ static int ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	writew(0x0, priv(dev)->main_iobase + DAC_CONTROL0_REG);
+ 	abort_dma(dev, 0);
+@@ -3608,8 +3608,8 @@ static int dio_callback_4020(int dir, int port, int data, unsigned long iobase)
+ 	}
+ }
+ 
+-static int di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int bits;
+ 
+@@ -3621,8 +3621,8 @@ static int di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[0] &= 0xf;
+ 	/*  zero bits we are going to change */
+@@ -3637,8 +3637,8 @@ static int do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int dio_60xx_config_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dio_60xx_config_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int mask;
+ 
+@@ -3664,8 +3664,8 @@ static int dio_60xx_config_insn(struct comedi_device * dev, struct comedi_subdev
+ 	return 1;
+ }
+ 
+-static int dio_60xx_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dio_60xx_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (data[0]) {
+ 		s->state &= ~data[0];
+@@ -3679,7 +3679,7 @@ static int dio_60xx_wbits(struct comedi_device * dev, struct comedi_subdevice *
+ 	return 2;
+ }
+ 
+-static void caldac_write(struct comedi_device * dev, unsigned int channel,
++static void caldac_write(struct comedi_device *dev, unsigned int channel,
+ 	unsigned int value)
+ {
+ 	priv(dev)->caldac_state[channel] = value;
+@@ -3697,8 +3697,8 @@ static void caldac_write(struct comedi_device * dev, unsigned int channel,
+ 	}
+ }
+ 
+-static int calib_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int calib_write_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int channel = CR_CHAN(insn->chanspec);
+ 
+@@ -3712,8 +3712,8 @@ static int calib_write_insn(struct comedi_device * dev, struct comedi_subdevice
+ 	return 1;
+ }
+ 
+-static int calib_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int calib_read_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int channel = CR_CHAN(insn->chanspec);
+ 
+@@ -3722,7 +3722,7 @@ static int calib_read_insn(struct comedi_device * dev, struct comedi_subdevice *
+ 	return 1;
+ }
+ 
+-static void ad8402_write(struct comedi_device * dev, unsigned int channel,
++static void ad8402_write(struct comedi_device *dev, unsigned int channel,
+ 	unsigned int value)
+ {
+ 	static const int bitstream_length = 10;
+@@ -3753,8 +3753,8 @@ static void ad8402_write(struct comedi_device * dev, unsigned int channel,
+ }
+ 
+ /* for pci-das6402/16, channel 0 is analog input gain and channel 1 is offset */
+-static int ad8402_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ad8402_write_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int channel = CR_CHAN(insn->chanspec);
+ 
+@@ -3770,8 +3770,8 @@ static int ad8402_write_insn(struct comedi_device * dev, struct comedi_subdevice
+ 	return 1;
+ }
+ 
+-static int ad8402_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ad8402_read_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int channel = CR_CHAN(insn->chanspec);
+ 
+@@ -3780,7 +3780,7 @@ static int ad8402_read_insn(struct comedi_device * dev, struct comedi_subdevice
+ 	return 1;
+ }
+ 
+-static uint16_t read_eeprom(struct comedi_device * dev, uint8_t address)
++static uint16_t read_eeprom(struct comedi_device *dev, uint8_t address)
+ {
+ 	static const int bitstream_length = 11;
+ 	static const int read_command = 0x6;
+@@ -3842,8 +3842,8 @@ static uint16_t read_eeprom(struct comedi_device * dev, uint8_t address)
+ 	return value;
+ }
+ 
+-static int eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int eeprom_read_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[0] = read_eeprom(dev, CR_CHAN(insn->chanspec));
+ 
+@@ -3928,7 +3928,7 @@ static unsigned int get_ao_divisor(unsigned int ns, unsigned int flags)
+ }
+ 
+ /* adjusts the size of hardware fifo (which determines block size for dma xfers) */
+-static int set_ai_fifo_size(struct comedi_device * dev, unsigned int num_samples)
++static int set_ai_fifo_size(struct comedi_device *dev, unsigned int num_samples)
+ {
+ 	unsigned int num_fifo_entries;
+ 	int retval;
+@@ -3949,14 +3949,14 @@ static int set_ai_fifo_size(struct comedi_device * dev, unsigned int num_samples
+ }
+ 
+ /* query length of fifo */
+-static unsigned int ai_fifo_size(struct comedi_device * dev)
++static unsigned int ai_fifo_size(struct comedi_device *dev)
+ {
+ 	return priv(dev)->ai_fifo_segment_length *
+ 		board(dev)->ai_fifo->num_segments *
+ 		board(dev)->ai_fifo->sample_packing_ratio;
+ }
+ 
+-static int set_ai_fifo_segment_length(struct comedi_device * dev,
++static int set_ai_fifo_segment_length(struct comedi_device *dev,
+ 	unsigned int num_entries)
+ {
+ 	static const int increment_size = 0x100;
+@@ -4007,7 +4007,7 @@ static int set_ai_fifo_segment_length(struct comedi_device * dev,
+  * address 7 == dac channel 1 fine offset
+ */
+ 
+-static int caldac_8800_write(struct comedi_device * dev, unsigned int address,
++static int caldac_8800_write(struct comedi_device *dev, unsigned int address,
+ 	uint8_t value)
+ {
+ 	static const int num_caldac_channels = 8;
+@@ -4039,7 +4039,7 @@ static int caldac_8800_write(struct comedi_device * dev, unsigned int address,
+ }
+ 
+ /* 4020 caldacs */
+-static int caldac_i2c_write(struct comedi_device * dev, unsigned int caldac_channel,
++static int caldac_i2c_write(struct comedi_device *dev, unsigned int caldac_channel,
+ 	unsigned int value)
+ {
+ 	uint8_t serial_bytes[3];
+@@ -4104,7 +4104,7 @@ static const int i2c_high_comedi_udelay = 1000;
+ static const int i2c_low_comedi_udelay = 10;
+ 
+ /* set i2c data line high or low */
+-static void i2c_set_sda(struct comedi_device * dev, int state)
++static void i2c_set_sda(struct comedi_device *dev, int state)
+ {
+ 	static const int data_bit = CTL_EE_W;
+ 	void *plx_control_addr = priv(dev)->plx9080_iobase + PLX_CONTROL_REG;
+@@ -4123,7 +4123,7 @@ static void i2c_set_sda(struct comedi_device * dev, int state)
+ }
+ 
+ /* set i2c clock line high or low */
+-static void i2c_set_scl(struct comedi_device * dev, int state)
++static void i2c_set_scl(struct comedi_device *dev, int state)
+ {
+ 	static const int clock_bit = CTL_USERO;
+ 	void *plx_control_addr = priv(dev)->plx9080_iobase + PLX_CONTROL_REG;
+@@ -4141,7 +4141,7 @@ static void i2c_set_scl(struct comedi_device * dev, int state)
+ 	}
+ }
+ 
+-static void i2c_write_byte(struct comedi_device * dev, uint8_t byte)
++static void i2c_write_byte(struct comedi_device *dev, uint8_t byte)
+ {
+ 	uint8_t bit;
+ 	unsigned int num_bits = 8;
+@@ -4159,7 +4159,7 @@ static void i2c_write_byte(struct comedi_device * dev, uint8_t byte)
+ }
+ 
+ /* we can't really read the lines, so fake it */
+-static int i2c_read_ack(struct comedi_device * dev)
++static int i2c_read_ack(struct comedi_device *dev)
+ {
+ 	i2c_set_scl(dev, 0);
+ 	i2c_set_sda(dev, 1);
+@@ -4169,7 +4169,7 @@ static int i2c_read_ack(struct comedi_device * dev)
+ }
+ 
+ /* send start bit */
+-static void i2c_start(struct comedi_device * dev)
++static void i2c_start(struct comedi_device *dev)
+ {
+ 	i2c_set_scl(dev, 1);
+ 	i2c_set_sda(dev, 1);
+@@ -4177,7 +4177,7 @@ static void i2c_start(struct comedi_device * dev)
+ }
+ 
+ /* send stop bit */
+-static void i2c_stop(struct comedi_device * dev)
++static void i2c_stop(struct comedi_device *dev)
+ {
+ 	i2c_set_scl(dev, 0);
+ 	i2c_set_sda(dev, 0);
+@@ -4185,8 +4185,8 @@ static void i2c_stop(struct comedi_device * dev)
+ 	i2c_set_sda(dev, 1);
+ }
+ 
+-static void i2c_write(struct comedi_device * dev, unsigned int address,
+-	const uint8_t * data, unsigned int length)
++static void i2c_write(struct comedi_device *dev, unsigned int address,
++	const uint8_t *data, unsigned int length)
+ {
+ 	unsigned int i;
+ 	uint8_t bitstream;
+diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
+index 581ff7a81cea..d87b04c9f931 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidda.c
++++ b/drivers/staging/comedi/drivers/cb_pcidda.c
+@@ -239,22 +239,22 @@ struct cb_pcidda_private {
+  */
+ #define devpriv ((struct cb_pcidda_private *)dev->private)
+ 
+-static int cb_pcidda_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int cb_pcidda_detach(struct comedi_device * dev);
++static int cb_pcidda_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int cb_pcidda_detach(struct comedi_device *dev);
+ /* static int cb_pcidda_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data); */
+-static int cb_pcidda_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int cb_pcidda_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+ /* static int cb_pcidda_ai_cmd(struct comedi_device *dev, struct *comedi_subdevice *s);*/
+ /* static int cb_pcidda_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd); */
+ /* static int cb_pcidda_ns_to_timer(unsigned int *ns,int *round); */
+ 
+-static unsigned int cb_pcidda_serial_in(struct comedi_device * dev);
+-static void cb_pcidda_serial_out(struct comedi_device * dev, unsigned int value,
++static unsigned int cb_pcidda_serial_in(struct comedi_device *dev);
++static void cb_pcidda_serial_out(struct comedi_device *dev, unsigned int value,
+ 	unsigned int num_bits);
+-static unsigned int cb_pcidda_read_eeprom(struct comedi_device * dev,
++static unsigned int cb_pcidda_read_eeprom(struct comedi_device *dev,
+ 	unsigned int address);
+-static void cb_pcidda_calibrate(struct comedi_device * dev, unsigned int channel,
++static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel,
+ 	unsigned int range);
+ 
+ /*
+@@ -274,7 +274,7 @@ static struct comedi_driver driver_cb_pcidda = {
+  * Attach is called by the Comedi core to configure the driver
+  * for a particular board.
+  */
+-static int cb_pcidda_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int cb_pcidda_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	struct pci_dev *pcidev;
+@@ -395,7 +395,7 @@ static int cb_pcidda_attach(struct comedi_device * dev, struct comedi_devconfig
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int cb_pcidda_detach(struct comedi_device * dev)
++static int cb_pcidda_detach(struct comedi_device *dev)
+ {
+ /*
+  * Deallocate the I/O ports.
+@@ -423,7 +423,7 @@ static int cb_pcidda_detach(struct comedi_device * dev)
+  * I will program this later... ;-)
+  */
+ #if 0
+-static int cb_pcidda_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int cb_pcidda_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	printk("cb_pcidda_ai_cmd\n");
+ 	printk("subdev: %d\n", cmd->subdev);
+@@ -442,8 +442,8 @@ static int cb_pcidda_ai_cmd(struct comedi_device * dev, struct comedi_subdevice
+ #endif
+ 
+ #if 0
+-static int cb_pcidda_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int cb_pcidda_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -608,8 +608,8 @@ static int cb_pcidda_ns_to_timer(unsigned int *ns, int round)
+ }
+ #endif
+ 
+-static int cb_pcidda_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int cb_pcidda_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int command;
+ 	unsigned int channel, range;
+@@ -658,7 +658,7 @@ static int cb_pcidda_ao_winsn(struct comedi_device * dev, struct comedi_subdevic
+ }
+ 
+ /* lowlevel read from eeprom */
+-static unsigned int cb_pcidda_serial_in(struct comedi_device * dev)
++static unsigned int cb_pcidda_serial_in(struct comedi_device *dev)
+ {
+ 	unsigned int value = 0;
+ 	int i;
+@@ -675,7 +675,7 @@ static unsigned int cb_pcidda_serial_in(struct comedi_device * dev)
+ }
+ 
+ /* lowlevel write to eeprom/dac */
+-static void cb_pcidda_serial_out(struct comedi_device * dev, unsigned int value,
++static void cb_pcidda_serial_out(struct comedi_device *dev, unsigned int value,
+ 	unsigned int num_bits)
+ {
+ 	int i;
+@@ -691,7 +691,7 @@ static void cb_pcidda_serial_out(struct comedi_device * dev, unsigned int value,
+ }
+ 
+ /* reads a 16 bit value from board's eeprom */
+-static unsigned int cb_pcidda_read_eeprom(struct comedi_device * dev,
++static unsigned int cb_pcidda_read_eeprom(struct comedi_device *dev,
+ 	unsigned int address)
+ {
+ 	unsigned int i;
+@@ -725,7 +725,7 @@ static unsigned int cb_pcidda_read_eeprom(struct comedi_device * dev,
+ }
+ 
+ /* writes to 8 bit calibration dacs */
+-static void cb_pcidda_write_caldac(struct comedi_device * dev, unsigned int caldac,
++static void cb_pcidda_write_caldac(struct comedi_device *dev, unsigned int caldac,
+ 	unsigned int channel, unsigned int value)
+ {
+ 	unsigned int cal2_bits;
+@@ -812,7 +812,7 @@ static unsigned int eeprom_fine_byte(unsigned int word)
+ }
+ 
+ /* set caldacs to eeprom values for given channel and range */
+-static void cb_pcidda_calibrate(struct comedi_device * dev, unsigned int channel,
++static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel,
+ 	unsigned int range)
+ {
+ 	unsigned int coarse_offset, fine_offset, coarse_gain, fine_gain;
+diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c
+index eeda0b3dc5b1..ec7b2e21c053 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidio.c
++++ b/drivers/staging/comedi/drivers/cb_pcidio.c
+@@ -127,8 +127,8 @@ struct pcidio_private {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pcidio_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pcidio_detach(struct comedi_device * dev);
++static int pcidio_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pcidio_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_cb_pcidio = {
+       driver_name:"cb_pcidio",
+       module:THIS_MODULE,
+@@ -173,7 +173,7 @@ static struct comedi_driver driver_cb_pcidio = {
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pcidio_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pcidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct pci_dev *pcidev = NULL;
+ 	int index;
+@@ -274,7 +274,7 @@ static int pcidio_attach(struct comedi_device * dev, struct comedi_devconfig * i
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int pcidio_detach(struct comedi_device * dev)
++static int pcidio_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: cb_pcidio: remove\n", dev->minor);
+ 	if (devpriv) {
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
+index 49d32fb4a4b4..0e20eadac2d3 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
+@@ -175,8 +175,8 @@ struct cb_pcimdas_private {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int cb_pcimdas_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int cb_pcimdas_detach(struct comedi_device * dev);
++static int cb_pcimdas_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int cb_pcimdas_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_cb_pcimdas = {
+       driver_name:"cb_pcimdas",
+       module:THIS_MODULE,
+@@ -184,12 +184,12 @@ static struct comedi_driver driver_cb_pcimdas = {
+       detach:cb_pcimdas_detach,
+ };
+ 
+-static int cb_pcimdas_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int cb_pcimdas_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int cb_pcimdas_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int cb_pcimdas_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int cb_pcimdas_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int cb_pcimdas_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * Attach is called by the Comedi core to configure the driver
+@@ -197,7 +197,7 @@ static int cb_pcimdas_ao_rinsn(struct comedi_device * dev, struct comedi_subdevi
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int cb_pcimdas_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int cb_pcimdas_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	struct pci_dev *pcidev;
+@@ -342,7 +342,7 @@ static int cb_pcimdas_attach(struct comedi_device * dev, struct comedi_devconfig
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int cb_pcimdas_detach(struct comedi_device * dev)
++static int cb_pcimdas_detach(struct comedi_device *dev)
+ {
+ #ifdef CBPCIMDAS_DEBUG
+ 	if (devpriv) {
+@@ -372,8 +372,8 @@ static int cb_pcimdas_detach(struct comedi_device * dev)
+  * "instructions" read/write data in "one-shot" or "software-triggered"
+  * mode.
+  */
+-static int cb_pcimdas_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int cb_pcimdas_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, i;
+ 	unsigned int d;
+@@ -437,8 +437,8 @@ static int cb_pcimdas_ai_rinsn(struct comedi_device * dev, struct comedi_subdevi
+ 	return n;
+ }
+ 
+-static int cb_pcimdas_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int cb_pcimdas_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -465,8 +465,8 @@ static int cb_pcimdas_ao_winsn(struct comedi_device * dev, struct comedi_subdevi
+ 
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+-static int cb_pcimdas_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int cb_pcimdas_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
+index 4e6002c8dfb6..1afedd8e7cc0 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
+@@ -181,8 +181,8 @@ struct board_private_struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int detach(struct comedi_device * dev);
++static int attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int detach(struct comedi_device *dev);
+ static struct comedi_driver cb_pcimdda_driver = {
+       driver_name:"cb_pcimdda",
+       module:THIS_MODULE,
+@@ -197,10 +197,10 @@ MODULE_DESCRIPTION("Comedi low-level driver for the Computerboards PCIM-DDA "
+ MODULE_LICENSE("GPL");
+ COMEDI_PCI_INITCLEANUP_NOMODULE(cb_pcimdda_driver, pci_table);
+ 
+-static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+ /*---------------------------------------------------------------------------
+   HELPER FUNCTION DECLARATIONS
+@@ -226,7 +226,7 @@ static inline unsigned int figure_out_maxdata(int bits)
+  *
+  *  Otherwise, returns a -errno on error
+  */
+-static int probe(struct comedi_device * dev, const struct comedi_devconfig * it);
++static int probe(struct comedi_device *dev, const struct comedi_devconfig *it);
+ 
+ /*---------------------------------------------------------------------------
+   FUNCTION DEFINITIONS
+@@ -238,7 +238,7 @@ static int probe(struct comedi_device * dev, const struct comedi_devconfig * it)
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int err;
+@@ -326,7 +326,7 @@ static int attach(struct comedi_device * dev, struct comedi_devconfig * it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int detach(struct comedi_device * dev)
++static int detach(struct comedi_device *dev)
+ {
+ 	if (devpriv) {
+ 
+@@ -352,8 +352,8 @@ static int detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -391,8 +391,8 @@ static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+    all AO channels update simultaneously.  This is useful for some control
+    applications, I would imagine.
+ */
+-static int ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -425,7 +425,7 @@ static int ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+  *
+  *  Otherwise, returns a -errno on error
+  */
+-static int probe(struct comedi_device * dev, const struct comedi_devconfig * it)
++static int probe(struct comedi_device *dev, const struct comedi_devconfig *it)
+ {
+ 	struct pci_dev *pcidev;
+ 	int index;
+diff --git a/drivers/staging/comedi/drivers/comedi_rt_timer.c b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+index c19ca8d3fb9e..ba1f485f3059 100644
+--- a/drivers/staging/comedi/drivers/comedi_rt_timer.c
++++ b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+@@ -145,11 +145,11 @@ static inline RTIME nano2count(long long ns)
+  * task period because analog input tends to be slow. */
+ #define SPEED_LIMIT 100000	/* in nanoseconds */
+ 
+-static int timer_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int timer_detach(struct comedi_device * dev);
+-static int timer_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
++static int timer_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int timer_detach(struct comedi_device *dev);
++static int timer_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int trig_num);
+-static int timer_start_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
++static int timer_start_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
+ 
+ static struct comedi_driver driver_timer = {
+       module:THIS_MODULE,
+@@ -168,7 +168,7 @@ struct timer_private {
+ 	RT_TASK *scan_task;	/*  rt task that controls conversion timing in a scan */
+ 	/* io_function can point to either an input or output function
+ 	 * depending on what kind of subdevice we are emulating for */
+-	int (*io_function) (struct comedi_device * dev, struct comedi_cmd * cmd,
++	int (*io_function) (struct comedi_device *dev, struct comedi_cmd *cmd,
+ 		unsigned int index);
+ /*
+ * RTIME has units of 1 = 838 nanoseconds time at which first scan
+@@ -187,7 +187,7 @@ struct timer_private {
+ };
+ #define devpriv ((struct timer_private *)dev->private)
+ 
+-static int timer_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int timer_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	devpriv->stop = 1;
+ 
+@@ -195,7 +195,7 @@ static int timer_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ }
+ 
+ /* checks for scan timing error */
+-inline static int check_scan_timing(struct comedi_device * dev,
++inline static int check_scan_timing(struct comedi_device *dev,
+ 	unsigned long long scan)
+ {
+ 	RTIME now, timing_error;
+@@ -212,7 +212,7 @@ inline static int check_scan_timing(struct comedi_device * dev,
+ }
+ 
+ /* checks for conversion timing error */
+-inline static int check_conversion_timing(struct comedi_device * dev,
++inline static int check_conversion_timing(struct comedi_device *dev,
+ 	RTIME scan_start, unsigned int conversion)
+ {
+ 	RTIME now, timing_error;
+@@ -231,7 +231,7 @@ inline static int check_conversion_timing(struct comedi_device * dev,
+ }
+ 
+ /* devpriv->io_function for an input subdevice */
+-static int timer_data_read(struct comedi_device * dev, struct comedi_cmd * cmd,
++static int timer_data_read(struct comedi_device *dev, struct comedi_cmd *cmd,
+ 	unsigned int index)
+ {
+ 	struct comedi_subdevice *s = dev->read_subdev;
+@@ -256,7 +256,7 @@ static int timer_data_read(struct comedi_device * dev, struct comedi_cmd * cmd,
+ }
+ 
+ /* devpriv->io_function for an output subdevice */
+-static int timer_data_write(struct comedi_device * dev, struct comedi_cmd * cmd,
++static int timer_data_write(struct comedi_device *dev, struct comedi_cmd *cmd,
+ 	unsigned int index)
+ {
+ 	struct comedi_subdevice *s = dev->write_subdev;
+@@ -291,7 +291,7 @@ static int timer_data_write(struct comedi_device * dev, struct comedi_cmd * cmd,
+ }
+ 
+ /* devpriv->io_function for DIO subdevices */
+-static int timer_dio_read(struct comedi_device * dev, struct comedi_cmd * cmd,
++static int timer_dio_read(struct comedi_device *dev, struct comedi_cmd *cmd,
+ 	unsigned int index)
+ {
+ 	struct comedi_subdevice *s = dev->read_subdev;
+@@ -421,8 +421,8 @@ static void timer_task_func(comedi_rt_task_context_t d)
+ 	}
+ }
+ 
+-static int timer_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int timer_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	struct comedi_insn xinsn = *insn;
+ 
+@@ -432,7 +432,7 @@ static int timer_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	return comedi_do_insn(devpriv->device, &xinsn);
+ }
+ 
+-static int cmdtest_helper(struct comedi_cmd * cmd,
++static int cmdtest_helper(struct comedi_cmd *cmd,
+ 	unsigned int start_src,
+ 	unsigned int scan_begin_src,
+ 	unsigned int convert_src,
+@@ -469,8 +469,8 @@ static int cmdtest_helper(struct comedi_cmd * cmd,
+ 	return err;
+ }
+ 
+-static int timer_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int timer_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	unsigned int start_src = 0;
+@@ -541,7 +541,7 @@ static int timer_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s
+ 	return 0;
+ }
+ 
+-static int timer_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int timer_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	int ret;
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+@@ -592,7 +592,7 @@ static int timer_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int timer_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
++static int timer_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int trig_num)
+ {
+ 	if (trig_num != 0)
+@@ -603,7 +603,7 @@ static int timer_inttrig(struct comedi_device * dev, struct comedi_subdevice * s
+ 	return timer_start_cmd(dev, s);
+ }
+ 
+-static int timer_start_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int timer_start_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct comedi_async *async = s->async;
+ 	struct comedi_cmd *cmd = &async->cmd;
+@@ -632,7 +632,7 @@ static int timer_start_cmd(struct comedi_device * dev, struct comedi_subdevice *
+ 	return 0;
+ }
+ 
+-static int timer_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int timer_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int ret;
+ 	struct comedi_subdevice *s, *emul_s;
+@@ -731,7 +731,7 @@ static int timer_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ }
+ 
+ /* free allocated resources */
+-static int timer_detach(struct comedi_device * dev)
++static int timer_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: timer: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
+index 1f194a0a45d6..6c0d26e86c16 100644
+--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
++++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
+@@ -75,8 +75,8 @@ struct contec_private {
+ 
+ #define devpriv ((struct contec_private *)dev->private)
+ 
+-static int contec_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int contec_detach(struct comedi_device * dev);
++static int contec_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int contec_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_contec = {
+       driver_name:"contec_pci_dio",
+       module:THIS_MODULE,
+@@ -85,19 +85,19 @@ static struct comedi_driver driver_contec = {
+ };
+ 
+ /* Classic digital IO */
+-static int contec_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int contec_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int contec_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int contec_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+ #if 0
+-static int contec_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd);
++static int contec_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd);
+ 
+ static int contec_ns_to_timer(unsigned int *ns, int round);
+ #endif
+ 
+-static int contec_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int contec_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct pci_dev *pcidev;
+ 	struct comedi_subdevice *s;
+@@ -164,7 +164,7 @@ static int contec_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	return -EIO;
+ }
+ 
+-static int contec_detach(struct comedi_device * dev)
++static int contec_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: contec: remove\n", dev->minor);
+ 
+@@ -179,8 +179,8 @@ static int contec_detach(struct comedi_device * dev)
+ }
+ 
+ #if 0
+-static int contec_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int contec_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	printk("contec_cmdtest called\n");
+ 	return 0;
+@@ -192,8 +192,8 @@ static int contec_ns_to_timer(unsigned int *ns, int round)
+ }
+ #endif
+ 
+-static int contec_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int contec_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	printk("contec_do_insn_bits called\n");
+@@ -212,8 +212,8 @@ static int contec_do_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+ 	return 2;
+ }
+ 
+-static int contec_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int contec_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	rt_printk("contec_di_insn_bits called\n");
+diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
+index 4afc88cb7173..90bed0b962ee 100644
+--- a/drivers/staging/comedi/drivers/daqboard2000.c
++++ b/drivers/staging/comedi/drivers/daqboard2000.c
+@@ -296,8 +296,8 @@ struct daqboard2000_hw {
+ #define DAQBOARD2000_PosRefDacSelect             0x0100
+ #define DAQBOARD2000_NegRefDacSelect             0x0000
+ 
+-static int daqboard2000_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int daqboard2000_detach(struct comedi_device * dev);
++static int daqboard2000_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int daqboard2000_detach(struct comedi_device *dev);
+ 
+ static struct comedi_driver driver_daqboard2000 = {
+       driver_name:"daqboard2000",
+@@ -338,7 +338,7 @@ struct daqboard2000_private {
+ 
+ #define devpriv ((struct daqboard2000_private *)dev->private)
+ 
+-static void writeAcqScanListEntry(struct comedi_device * dev, u16 entry)
++static void writeAcqScanListEntry(struct comedi_device *dev, u16 entry)
+ {
+ 	struct daqboard2000_hw *fpga = devpriv->daq;
+ 
+@@ -348,7 +348,7 @@ static void writeAcqScanListEntry(struct comedi_device * dev, u16 entry)
+ 	fpga->acqScanListFIFO = (entry >> 8) & 0x00ff;
+ }
+ 
+-static void setup_sampling(struct comedi_device * dev, int chan, int gain)
++static void setup_sampling(struct comedi_device *dev, int chan, int gain)
+ {
+ 	u16 word0, word1, word2, word3;
+ 
+@@ -393,8 +393,8 @@ static void setup_sampling(struct comedi_device * dev, int chan, int gain)
+ 	writeAcqScanListEntry(dev, word3);
+ }
+ 
+-static int daqboard2000_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int daqboard2000_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	struct daqboard2000_hw *fpga = devpriv->daq;
+@@ -450,8 +450,8 @@ static int daqboard2000_ai_insn_read(struct comedi_device * dev, struct comedi_s
+ 	return i;
+ }
+ 
+-static int daqboard2000_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int daqboard2000_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -463,8 +463,8 @@ static int daqboard2000_ao_insn_read(struct comedi_device * dev, struct comedi_s
+ 	return i;
+ }
+ 
+-static int daqboard2000_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int daqboard2000_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -494,7 +494,7 @@ static int daqboard2000_ao_insn_write(struct comedi_device * dev, struct comedi_
+ 	return i;
+ }
+ 
+-static void daqboard2000_resetLocalBus(struct comedi_device * dev)
++static void daqboard2000_resetLocalBus(struct comedi_device *dev)
+ {
+ 	printk("daqboard2000_resetLocalBus\n");
+ 	writel(DAQBOARD2000_SECRLocalBusHi, devpriv->plx + 0x6c);
+@@ -503,7 +503,7 @@ static void daqboard2000_resetLocalBus(struct comedi_device * dev)
+ 	comedi_udelay(10000);
+ }
+ 
+-static void daqboard2000_reloadPLX(struct comedi_device * dev)
++static void daqboard2000_reloadPLX(struct comedi_device *dev)
+ {
+ 	printk("daqboard2000_reloadPLX\n");
+ 	writel(DAQBOARD2000_SECRReloadLo, devpriv->plx + 0x6c);
+@@ -514,7 +514,7 @@ static void daqboard2000_reloadPLX(struct comedi_device * dev)
+ 	comedi_udelay(10000);
+ }
+ 
+-static void daqboard2000_pulseProgPin(struct comedi_device * dev)
++static void daqboard2000_pulseProgPin(struct comedi_device *dev)
+ {
+ 	printk("daqboard2000_pulseProgPin 1\n");
+ 	writel(DAQBOARD2000_SECRProgPinHi, devpriv->plx + 0x6c);
+@@ -523,7 +523,7 @@ static void daqboard2000_pulseProgPin(struct comedi_device * dev)
+ 	comedi_udelay(10000);	/* Not in the original code, but I like symmetry... */
+ }
+ 
+-static int daqboard2000_pollCPLD(struct comedi_device * dev, int mask)
++static int daqboard2000_pollCPLD(struct comedi_device *dev, int mask)
+ {
+ 	int result = 0;
+ 	int i;
+@@ -542,7 +542,7 @@ static int daqboard2000_pollCPLD(struct comedi_device * dev, int mask)
+ 	return result;
+ }
+ 
+-static int daqboard2000_writeCPLD(struct comedi_device * dev, int data)
++static int daqboard2000_writeCPLD(struct comedi_device *dev, int data)
+ {
+ 	int result = 0;
+ 
+@@ -555,7 +555,7 @@ static int daqboard2000_writeCPLD(struct comedi_device * dev, int data)
+ 	return result;
+ }
+ 
+-static int initialize_daqboard2000(struct comedi_device * dev,
++static int initialize_daqboard2000(struct comedi_device *dev,
+ 	unsigned char *cpld_array, int len)
+ {
+ 	int result = -EIO;
+@@ -613,12 +613,12 @@ static int initialize_daqboard2000(struct comedi_device * dev,
+ 	return result;
+ }
+ 
+-static void daqboard2000_adcStopDmaTransfer(struct comedi_device * dev)
++static void daqboard2000_adcStopDmaTransfer(struct comedi_device *dev)
+ {
+ /*  printk("Implement: daqboard2000_adcStopDmaTransfer\n");*/
+ }
+ 
+-static void daqboard2000_adcDisarm(struct comedi_device * dev)
++static void daqboard2000_adcDisarm(struct comedi_device *dev)
+ {
+ 	struct daqboard2000_hw *fpga = devpriv->daq;
+ 
+@@ -640,7 +640,7 @@ static void daqboard2000_adcDisarm(struct comedi_device * dev)
+ 	daqboard2000_adcStopDmaTransfer(dev);
+ }
+ 
+-static void daqboard2000_activateReferenceDacs(struct comedi_device * dev)
++static void daqboard2000_activateReferenceDacs(struct comedi_device *dev)
+ {
+ 	struct daqboard2000_hw *fpga = devpriv->daq;
+ 	int timeout;
+@@ -666,22 +666,22 @@ static void daqboard2000_activateReferenceDacs(struct comedi_device * dev)
+ /*  printk("DAQBOARD2000_NegRefDacSelect %d\n", timeout);*/
+ }
+ 
+-static void daqboard2000_initializeCtrs(struct comedi_device * dev)
++static void daqboard2000_initializeCtrs(struct comedi_device *dev)
+ {
+ /*  printk("Implement: daqboard2000_initializeCtrs\n");*/
+ }
+ 
+-static void daqboard2000_initializeTmrs(struct comedi_device * dev)
++static void daqboard2000_initializeTmrs(struct comedi_device *dev)
+ {
+ /*  printk("Implement: daqboard2000_initializeTmrs\n");*/
+ }
+ 
+-static void daqboard2000_dacDisarm(struct comedi_device * dev)
++static void daqboard2000_dacDisarm(struct comedi_device *dev)
+ {
+ /*  printk("Implement: daqboard2000_dacDisarm\n");*/
+ }
+ 
+-static void daqboard2000_initializeAdc(struct comedi_device * dev)
++static void daqboard2000_initializeAdc(struct comedi_device *dev)
+ {
+ 	daqboard2000_adcDisarm(dev);
+ 	daqboard2000_activateReferenceDacs(dev);
+@@ -689,7 +689,7 @@ static void daqboard2000_initializeAdc(struct comedi_device * dev)
+ 	daqboard2000_initializeTmrs(dev);
+ }
+ 
+-static void daqboard2000_initializeDac(struct comedi_device * dev)
++static void daqboard2000_initializeDac(struct comedi_device *dev)
+ {
+ 	daqboard2000_dacDisarm(dev);
+ }
+@@ -717,7 +717,7 @@ static int daqboard2000_8255_cb(int dir, int port, int data,
+ 	return result;
+ }
+ 
+-static int daqboard2000_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int daqboard2000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int result = 0;
+ 	struct comedi_subdevice *s;
+@@ -849,7 +849,7 @@ static int daqboard2000_attach(struct comedi_device * dev, struct comedi_devconf
+ 	return result;
+ }
+ 
+-static int daqboard2000_detach(struct comedi_device * dev)
++static int daqboard2000_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: daqboard2000: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
+index a2e261c96ba5..51dddd464ef2 100644
+--- a/drivers/staging/comedi/drivers/das08.c
++++ b/drivers/staging/comedi/drivers/das08.c
+@@ -154,20 +154,20 @@ driver.
+ 
+ /* gainlist same as _pgx_ below */
+ 
+-static int das08_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int das08_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int das08_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int das08jr_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int das08jr_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int das08jr_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int das08ao_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int das08_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int das08_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int das08_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int das08jr_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int das08jr_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int das08jr_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int das08ao_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ static void i8254_set_mode_low(unsigned int base, int channel,
+ 	unsigned int mode);
+ 
+@@ -512,8 +512,8 @@ MODULE_DEVICE_TABLE(pci, das08_pci_table);
+ 
+ #define TIMEOUT 100000
+ 
+-static int das08_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das08_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, n;
+ 	int chan;
+@@ -579,8 +579,8 @@ static int das08_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ 	return n;
+ }
+ 
+-static int das08_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das08_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[0] = 0;
+ 	data[1] = DAS08_IP(inb(dev->iobase + DAS08_STATUS));
+@@ -588,8 +588,8 @@ static int das08_di_rbits(struct comedi_device * dev, struct comedi_subdevice *
+ 	return 2;
+ }
+ 
+-static int das08_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das08_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int wbits;
+ 
+@@ -611,8 +611,8 @@ static int das08_do_wbits(struct comedi_device * dev, struct comedi_subdevice *
+ 	return 2;
+ }
+ 
+-static int das08jr_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das08jr_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[0] = 0;
+ 	data[1] = inb(dev->iobase + DAS08JR_DIO);
+@@ -620,8 +620,8 @@ static int das08jr_di_rbits(struct comedi_device * dev, struct comedi_subdevice
+ 	return 2;
+ }
+ 
+-static int das08jr_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das08jr_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	/*  null bits we are going to set */
+ 	devpriv->do_bits &= ~data[0];
+@@ -634,8 +634,8 @@ static int das08jr_do_wbits(struct comedi_device * dev, struct comedi_subdevice
+ 	return 2;
+ }
+ 
+-static int das08jr_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das08jr_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	int lsb, msb;
+@@ -668,8 +668,8 @@ static int das08jr_ao_winsn(struct comedi_device * dev, struct comedi_subdevice
+  * a different method to force an update.
+  *
+  */
+-static int das08ao_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das08ao_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	int lsb, msb;
+@@ -782,8 +782,8 @@ static unsigned int i8254_read_status(struct i8254_struct *st, int channel)
+ 	return i8254_read_status_low(st->iobase, chan);
+ }
+ 
+-static int das08_counter_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das08_counter_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = insn->chanspec;
+ 
+@@ -794,8 +794,8 @@ static int das08_counter_read(struct comedi_device * dev, struct comedi_subdevic
+ 	return 1;
+ }
+ 
+-static int das08_counter_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das08_counter_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = insn->chanspec;
+ 
+@@ -805,8 +805,8 @@ static int das08_counter_write(struct comedi_device * dev, struct comedi_subdevi
+ 	return 1;
+ }
+ 
+-static int das08_counter_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das08_counter_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = insn->chanspec;
+ 
+@@ -827,7 +827,7 @@ static int das08_counter_config(struct comedi_device * dev, struct comedi_subdev
+ 	return 2;
+ }
+ 
+-static int das08_attach(struct comedi_device * dev, struct comedi_devconfig * it);
++static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ 
+ static struct comedi_driver driver_das08 = {
+       driver_name: DRV_NAME,
+@@ -840,7 +840,7 @@ static struct comedi_driver driver_das08 = {
+       offset:sizeof(struct das08_board_struct),
+ };
+ 
+-int das08_common_attach(struct comedi_device * dev, unsigned long iobase)
++int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
+ {
+ 	struct comedi_subdevice *s;
+ 	int ret;
+@@ -952,7 +952,7 @@ int das08_common_attach(struct comedi_device * dev, unsigned long iobase)
+ 	return 0;
+ }
+ 
+-static int das08_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int ret;
+ 	unsigned long iobase;
+@@ -1028,7 +1028,7 @@ static int das08_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 	return das08_common_attach(dev, iobase);
+ }
+ 
+-int das08_common_detach(struct comedi_device * dev)
++int das08_common_detach(struct comedi_device *dev)
+ {
+ 	printk(KERN_INFO "comedi%d: das08: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/das08.h b/drivers/staging/comedi/drivers/das08.h
+index b870e88ab834..7cdb3fc4daee 100644
+--- a/drivers/staging/comedi/drivers/das08.h
++++ b/drivers/staging/comedi/drivers/das08.h
+@@ -72,7 +72,7 @@ struct das08_private_struct {
+ #define NUM_DAS08_CS_BOARDS 2
+ extern struct das08_board_struct das08_cs_boards[NUM_DAS08_CS_BOARDS];
+ 
+-int das08_common_attach(struct comedi_device * dev, unsigned long iobase);
+-int das08_common_detach(struct comedi_device * dev);
++int das08_common_attach(struct comedi_device *dev, unsigned long iobase);
++int das08_common_detach(struct comedi_device *dev);
+ 
+ #endif /* _DAS08_H */
+diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
+index 9fbcbf966386..ed25a63da29c 100644
+--- a/drivers/staging/comedi/drivers/das08_cs.c
++++ b/drivers/staging/comedi/drivers/das08_cs.c
+@@ -56,7 +56,7 @@ static struct pcmcia_device *cur_dev = NULL;
+ 
+ #define thisboard ((const struct das08_board_struct *)dev->board_ptr)
+ 
+-static int das08_cs_attach(struct comedi_device * dev, struct comedi_devconfig * it);
++static int das08_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ 
+ static struct comedi_driver driver_das08_cs = {
+       driver_name:"das08_cs",
+@@ -69,7 +69,7 @@ static struct comedi_driver driver_das08_cs = {
+       offset:sizeof(struct das08_board_struct),
+ };
+ 
+-static int das08_cs_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int das08_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int ret;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
+index 991e3330d11f..2082030bd4ff 100644
+--- a/drivers/staging/comedi/drivers/das16.c
++++ b/drivers/staging/comedi/drivers/das16.c
+@@ -698,8 +698,8 @@ static const struct das16_board das16_boards[] = {
+ 
+ #define n_das16_boards ((sizeof(das16_boards))/(sizeof(struct das16_board)))
+ 
+-static int das16_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int das16_detach(struct comedi_device * dev);
++static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int das16_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_das16 = {
+       driver_name:"das16",
+       module:THIS_MODULE,
+@@ -742,8 +742,8 @@ struct das16_private_struct {
+ #define devpriv ((struct das16_private_struct *)(dev->private))
+ #define thisboard ((struct das16_board *)(dev->board_ptr))
+ 
+-static int das16_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0, tmp;
+ 	int gain, start_chan, i;
+@@ -893,7 +893,7 @@ static int das16_cmd_test(struct comedi_device * dev, struct comedi_subdevice *
+ 	return 0;
+ }
+ 
+-static int das16_cmd_exec(struct comedi_device * dev, struct comedi_subdevice * s)
++static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct comedi_async *async = s->async;
+ 	struct comedi_cmd *cmd = &async->cmd;
+@@ -996,7 +996,7 @@ static int das16_cmd_exec(struct comedi_device * dev, struct comedi_subdevice *
+ 	return 0;
+ }
+ 
+-static int das16_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	unsigned long flags;
+ 
+@@ -1023,7 +1023,7 @@ static int das16_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static void das16_reset(struct comedi_device * dev)
++static void das16_reset(struct comedi_device *dev)
+ {
+ 	outb(0, dev->iobase + DAS16_STATUS);
+ 	outb(0, dev->iobase + DAS16_CONTROL);
+@@ -1031,8 +1031,8 @@ static void das16_reset(struct comedi_device * dev)
+ 	outb(0, dev->iobase + DAS16_CNTR_CONTROL);
+ }
+ 
+-static int das16_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das16_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, n;
+ 	int range;
+@@ -1079,8 +1079,8 @@ static int das16_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ 	return n;
+ }
+ 
+-static int das16_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das16_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int bits;
+ 
+@@ -1091,8 +1091,8 @@ static int das16_di_rbits(struct comedi_device * dev, struct comedi_subdevice *
+ 	return 2;
+ }
+ 
+-static int das16_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das16_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int wbits;
+ 
+@@ -1111,8 +1111,8 @@ static int das16_do_wbits(struct comedi_device * dev, struct comedi_subdevice *
+ 	return 2;
+ }
+ 
+-static int das16_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das16_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int lsb, msb;
+@@ -1169,7 +1169,7 @@ static void das16_timer_interrupt(unsigned long arg)
+ 	an even transfer count after disabling dma
+ 	channel.
+ */
+-static int disable_dma_on_even(struct comedi_device * dev)
++static int disable_dma_on_even(struct comedi_device *dev)
+ {
+ 	int residue;
+ 	int i;
+@@ -1197,7 +1197,7 @@ static int disable_dma_on_even(struct comedi_device * dev)
+ 	return residue;
+ }
+ 
+-static void das16_interrupt(struct comedi_device * dev)
++static void das16_interrupt(struct comedi_device *dev)
+ {
+ 	unsigned long dma_flags, spin_flags;
+ 	struct comedi_subdevice *s = dev->read_subdev;
+@@ -1273,7 +1273,7 @@ static void das16_interrupt(struct comedi_device * dev)
+ 	cfc_handle_events(dev, s);
+ }
+ 
+-static unsigned int das16_set_pacer(struct comedi_device * dev, unsigned int ns,
++static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
+ 	int rounding_flags)
+ {
+ 	i8253_cascade_ns_to_timer_2div(devpriv->clockbase, &(devpriv->divisor1),
+@@ -1286,7 +1286,7 @@ static unsigned int das16_set_pacer(struct comedi_device * dev, unsigned int ns,
+ 	return ns;
+ }
+ 
+-static void reg_dump(struct comedi_device * dev)
++static void reg_dump(struct comedi_device *dev)
+ {
+ 	DEBUG_PRINT("********DAS1600 REGISTER DUMP********\n");
+ 	DEBUG_PRINT("DAS16_MUX: %x\n", inb(dev->iobase + DAS16_MUX));
+@@ -1304,7 +1304,7 @@ static void reg_dump(struct comedi_device * dev)
+ 		inb(dev->iobase + DAS1600_STATUS_B));
+ }
+ 
+-static int das16_probe(struct comedi_device * dev, struct comedi_devconfig * it)
++static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int status;
+ 	int diobits;
+@@ -1338,7 +1338,7 @@ static int das16_probe(struct comedi_device * dev, struct comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int das1600_mode_detect(struct comedi_device * dev)
++static int das1600_mode_detect(struct comedi_device *dev)
+ {
+ 	int status = 0;
+ 
+@@ -1366,7 +1366,7 @@ static int das1600_mode_detect(struct comedi_device * dev)
+  *   3  Clock speed (in MHz)
+  */
+ 
+-static int das16_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int ret;
+@@ -1630,7 +1630,7 @@ static int das16_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 	return 0;
+ }
+ 
+-static int das16_detach(struct comedi_device * dev)
++static int das16_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: das16: remove\n", dev->minor);
+ 
+@@ -1674,7 +1674,7 @@ static int das16_detach(struct comedi_device * dev)
+ COMEDI_INITCLEANUP(driver_das16);
+ 
+ /* utility function that suggests a dma transfer size in bytes */
+-static unsigned int das16_suggest_transfer_size(struct comedi_device * dev,
++static unsigned int das16_suggest_transfer_size(struct comedi_device *dev,
+ 	struct comedi_cmd cmd)
+ {
+ 	unsigned int size;
+@@ -1715,7 +1715,7 @@ static unsigned int das16_suggest_transfer_size(struct comedi_device * dev,
+ 	return size;
+ }
+ 
+-static void das16_ai_munge(struct comedi_device * dev, struct comedi_subdevice * s,
++static void das16_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	void *array, unsigned int num_bytes, unsigned int start_chan_index)
+ {
+ 	unsigned int i, num_samples = num_bytes / sizeof(short);
+diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
+index 5b1d96cea046..7d35183b1d35 100644
+--- a/drivers/staging/comedi/drivers/das16m1.c
++++ b/drivers/staging/comedi/drivers/das16m1.c
+@@ -166,8 +166,8 @@ static const struct das16m1_board das16m1_boards[] = {
+ 
+ #define das16m1_num_boards ((sizeof(das16m1_boards)) / (sizeof(das16m1_boards[0])))
+ 
+-static int das16m1_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int das16m1_detach(struct comedi_device * dev);
++static int das16m1_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int das16m1_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_das16m1 = {
+       driver_name:"das16m1",
+       module:THIS_MODULE,
+@@ -200,8 +200,8 @@ static inline short munge_sample(short data)
+ 	return (data >> 4) & 0xfff;
+ }
+ 
+-static int das16m1_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int das16m1_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	unsigned int err = 0, tmp, i;
+ 
+@@ -322,7 +322,7 @@ static int das16m1_cmd_test(struct comedi_device * dev, struct comedi_subdevice
+ 	return 0;
+ }
+ 
+-static int das16m1_cmd_exec(struct comedi_device * dev, struct comedi_subdevice * s)
++static int das16m1_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct comedi_async *async = s->async;
+ 	struct comedi_cmd *cmd = &async->cmd;
+@@ -385,7 +385,7 @@ static int das16m1_cmd_exec(struct comedi_device * dev, struct comedi_subdevice
+ 	return 0;
+ }
+ 
+-static int das16m1_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int das16m1_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	devpriv->control_state &= ~INTE & ~PACER_MASK;
+ 	outb(devpriv->control_state, dev->iobase + DAS16M1_INTR_CONTROL);
+@@ -393,8 +393,8 @@ static int das16m1_cancel(struct comedi_device * dev, struct comedi_subdevice *
+ 	return 0;
+ }
+ 
+-static int das16m1_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das16m1_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, n;
+ 	int byte;
+@@ -430,8 +430,8 @@ static int das16m1_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice
+ 	return n;
+ }
+ 
+-static int das16m1_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das16m1_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int bits;
+ 
+@@ -442,8 +442,8 @@ static int das16m1_di_rbits(struct comedi_device * dev, struct comedi_subdevice
+ 	return 2;
+ }
+ 
+-static int das16m1_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das16m1_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int wbits;
+ 
+@@ -462,7 +462,7 @@ static int das16m1_do_wbits(struct comedi_device * dev, struct comedi_subdevice
+ 	return 2;
+ }
+ 
+-static int das16m1_poll(struct comedi_device * dev, struct comedi_subdevice * s)
++static int das16m1_poll(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	unsigned long flags;
+ 	unsigned int status;
+@@ -505,7 +505,7 @@ static irqreturn_t das16m1_interrupt(int irq, void *d)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static void munge_sample_array(short * array, unsigned int num_elements)
++static void munge_sample_array(short *array, unsigned int num_elements)
+ {
+ 	unsigned int i;
+ 
+@@ -514,7 +514,7 @@ static void munge_sample_array(short * array, unsigned int num_elements)
+ 	}
+ }
+ 
+-static void das16m1_handler(struct comedi_device * dev, unsigned int status)
++static void das16m1_handler(struct comedi_device *dev, unsigned int status)
+ {
+ 	struct comedi_subdevice *s;
+ 	struct comedi_async *async;
+@@ -578,7 +578,7 @@ static void das16m1_handler(struct comedi_device * dev, unsigned int status)
+ /* This function takes a time in nanoseconds and sets the     *
+  * 2 pacer clocks to the closest frequency possible. It also  *
+  * returns the actual sampling period.                        */
+-static unsigned int das16m1_set_pacer(struct comedi_device * dev, unsigned int ns,
++static unsigned int das16m1_set_pacer(struct comedi_device *dev, unsigned int ns,
+ 	int rounding_flags)
+ {
+ 	i8253_cascade_ns_to_timer_2div(DAS16M1_XTAL, &(devpriv->divisor1),
+@@ -635,7 +635,7 @@ static int das16m1_irq_bits(unsigned int irq)
+  *   1  IRQ
+  */
+ 
+-static int das16m1_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int das16m1_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int ret;
+@@ -744,7 +744,7 @@ static int das16m1_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	return 0;
+ }
+ 
+-static int das16m1_detach(struct comedi_device * dev)
++static int das16m1_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: das16m1: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
+index 7e1b8f8fec57..2112783d37e2 100644
+--- a/drivers/staging/comedi/drivers/das1800.c
++++ b/drivers/staging/comedi/drivers/das1800.c
+@@ -520,7 +520,7 @@ static struct comedi_driver driver_das1800 = {
+  */
+ COMEDI_INITCLEANUP(driver_das1800);
+ 
+-static int das1800_init_dma(struct comedi_device * dev, unsigned int dma0,
++static int das1800_init_dma(struct comedi_device *dev, unsigned int dma0,
+ 	unsigned int dma1)
+ {
+ 	unsigned long flags;
+@@ -590,7 +590,7 @@ static int das1800_init_dma(struct comedi_device * dev, unsigned int dma0,
+ 	return 0;
+ }
+ 
+-static int das1800_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int das1800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase = it->options[0];
+@@ -765,7 +765,7 @@ static int das1800_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	return 0;
+ };
+ 
+-static int das1800_detach(struct comedi_device * dev)
++static int das1800_detach(struct comedi_device *dev)
+ {
+ 	/* only free stuff if it has been allocated by _attach */
+ 	if (dev->iobase)
+@@ -793,7 +793,7 @@ static int das1800_detach(struct comedi_device * dev)
+ 
+ /* probes and checks das-1800 series board type
+  */
+-static int das1800_probe(struct comedi_device * dev)
++static int das1800_probe(struct comedi_device *dev)
+ {
+ 	int id;
+ 	int board;
+@@ -867,7 +867,7 @@ static int das1800_probe(struct comedi_device * dev)
+ 	return -1;
+ }
+ 
+-static int das1800_ai_poll(struct comedi_device * dev, struct comedi_subdevice * s)
++static int das1800_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	unsigned long flags;
+ 
+@@ -909,7 +909,7 @@ static irqreturn_t das1800_interrupt(int irq, void *d)
+ }
+ 
+ /* the guts of the interrupt handler, that is shared with das1800_ai_poll */
+-static void das1800_ai_handler(struct comedi_device * dev)
++static void das1800_ai_handler(struct comedi_device *dev)
+ {
+ 	struct comedi_subdevice *s = dev->subdevices + 0;	/* analog input subdevice */
+ 	struct comedi_async *async = s->async;
+@@ -962,7 +962,7 @@ static void das1800_ai_handler(struct comedi_device * dev)
+ 	return;
+ }
+ 
+-static void das1800_handle_dma(struct comedi_device * dev, struct comedi_subdevice * s,
++static void das1800_handle_dma(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int status)
+ {
+ 	unsigned long flags;
+@@ -997,14 +997,14 @@ static void das1800_handle_dma(struct comedi_device * dev, struct comedi_subdevi
+ 	return;
+ }
+ 
+-static inline uint16_t munge_bipolar_sample(const struct comedi_device * dev,
++static inline uint16_t munge_bipolar_sample(const struct comedi_device *dev,
+ 	uint16_t sample)
+ {
+ 	sample += 1 << (thisboard->resolution - 1);
+ 	return sample;
+ }
+ 
+-static void munge_data(struct comedi_device * dev, uint16_t * array,
++static void munge_data(struct comedi_device *dev, uint16_t *array,
+ 	unsigned int num_elements)
+ {
+ 	unsigned int i;
+@@ -1023,8 +1023,8 @@ static void munge_data(struct comedi_device * dev, uint16_t * array,
+ 
+ /* Utility function used by das1800_flush_dma() and das1800_handle_dma().
+  * Assumes dma lock is held */
+-static void das1800_flush_dma_channel(struct comedi_device * dev, struct comedi_subdevice * s,
+-	unsigned int channel, uint16_t * buffer)
++static void das1800_flush_dma_channel(struct comedi_device *dev, struct comedi_subdevice *s,
++	unsigned int channel, uint16_t *buffer)
+ {
+ 	unsigned int num_bytes, num_samples;
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+@@ -1053,7 +1053,7 @@ static void das1800_flush_dma_channel(struct comedi_device * dev, struct comedi_
+ 
+ /* flushes remaining data from board when external trigger has stopped aquisition
+  * and we are using dma transfers */
+-static void das1800_flush_dma(struct comedi_device * dev, struct comedi_subdevice * s)
++static void das1800_flush_dma(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	unsigned long flags;
+ 	const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
+@@ -1083,8 +1083,8 @@ static void das1800_flush_dma(struct comedi_device * dev, struct comedi_subdevic
+ 	return;
+ }
+ 
+-static void das1800_handle_fifo_half_full(struct comedi_device * dev,
+-	struct comedi_subdevice * s)
++static void das1800_handle_fifo_half_full(struct comedi_device *dev,
++	struct comedi_subdevice *s)
+ {
+ 	int numPoints = 0;	/* number of points to read */
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+@@ -1102,8 +1102,8 @@ static void das1800_handle_fifo_half_full(struct comedi_device * dev,
+ 	return;
+ }
+ 
+-static void das1800_handle_fifo_not_empty(struct comedi_device * dev,
+-	struct comedi_subdevice * s)
++static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
++	struct comedi_subdevice *s)
+ {
+ 	short dpnt;
+ 	int unipolar;
+@@ -1126,7 +1126,7 @@ static void das1800_handle_fifo_not_empty(struct comedi_device * dev,
+ 	return;
+ }
+ 
+-static int das1800_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	outb(0x0, dev->iobase + DAS1800_STATUS);	/* disable conversions */
+ 	outb(0x0, dev->iobase + DAS1800_CONTROL_B);	/* disable interrupts and dma */
+@@ -1139,8 +1139,8 @@ static int das1800_cancel(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ /* test analog input cmd */
+-static int das1800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int das1800_ai_do_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -1385,7 +1385,7 @@ static int control_c_bits(struct comedi_cmd cmd)
+ }
+ 
+ /* sets up counters */
+-static int setup_counters(struct comedi_device * dev, struct comedi_cmd cmd)
++static int setup_counters(struct comedi_device *dev, struct comedi_cmd cmd)
+ {
+ 	/*  setup cascaded counters for conversion/scan frequency */
+ 	switch (cmd.scan_begin_src) {
+@@ -1424,7 +1424,7 @@ static int setup_counters(struct comedi_device * dev, struct comedi_cmd cmd)
+ }
+ 
+ /* sets up dma */
+-static void setup_dma(struct comedi_device * dev, struct comedi_cmd cmd)
++static void setup_dma(struct comedi_device *dev, struct comedi_cmd cmd)
+ {
+ 	unsigned long lock_flags;
+ 	const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
+@@ -1462,7 +1462,7 @@ static void setup_dma(struct comedi_device * dev, struct comedi_cmd cmd)
+ }
+ 
+ /* programs channel/gain list into card */
+-static void program_chanlist(struct comedi_device * dev, struct comedi_cmd cmd)
++static void program_chanlist(struct comedi_device *dev, struct comedi_cmd cmd)
+ {
+ 	int i, n, chan_range;
+ 	unsigned long irq_flags;
+@@ -1489,7 +1489,7 @@ static void program_chanlist(struct comedi_device * dev, struct comedi_cmd cmd)
+ }
+ 
+ /* analog input do_cmd */
+-static int das1800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int das1800_ai_do_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	int ret;
+ 	int control_a, control_c;
+@@ -1552,8 +1552,8 @@ static int das1800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ /* read analog input */
+-static int das1800_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das1800_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, n;
+ 	int chan, range, aref, chan_range;
+@@ -1612,8 +1612,8 @@ static int das1800_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ /* writes to an analog output channel */
+-static int das1800_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das1800_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ /* int range = CR_RANGE(insn->chanspec); */
+@@ -1641,8 +1641,8 @@ static int das1800_ao_winsn(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ /* reads from digital input channels */
+-static int das1800_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das1800_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	data[1] = inb(dev->iobase + DAS1800_DIGITAL) & 0xf;
+@@ -1652,8 +1652,8 @@ static int das1800_di_rbits(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ /* writes to digital output channels */
+-static int das1800_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das1800_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int wbits;
+ 
+@@ -1672,7 +1672,7 @@ static int das1800_do_wbits(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ /* loads counters with divisor1, divisor2 from private structure */
+-static int das1800_set_frequency(struct comedi_device * dev)
++static int das1800_set_frequency(struct comedi_device *dev)
+ {
+ 	int err = 0;
+ 
+@@ -1720,7 +1720,7 @@ static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode)
+ }
+ 
+ /* utility function that suggests a dma transfer size based on the conversion period 'ns' */
+-static unsigned int suggest_transfer_size(struct comedi_cmd * cmd)
++static unsigned int suggest_transfer_size(struct comedi_cmd *cmd)
+ {
+ 	unsigned int size = DMA_BUF_SIZE;
+ 	static const int sample_size = 2;	/*  size in bytes of one sample from board */
+diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c
+index ed9409d41a32..b2326ec50833 100644
+--- a/drivers/staging/comedi/drivers/das6402.c
++++ b/drivers/staging/comedi/drivers/das6402.c
+@@ -98,8 +98,8 @@ This driver has suffered bitrot.
+ #define	C2 0x80
+ #define	RWLH 0x30
+ 
+-static int das6402_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int das6402_detach(struct comedi_device * dev);
++static int das6402_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int das6402_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_das6402 = {
+       driver_name:"das6402",
+       module:THIS_MODULE,
+@@ -116,9 +116,9 @@ struct das6402_private {
+ };
+ #define devpriv ((struct das6402_private *)dev->private)
+ 
+-static void das6402_ai_fifo_dregs(struct comedi_device * dev, struct comedi_subdevice * s);
++static void das6402_ai_fifo_dregs(struct comedi_device *dev, struct comedi_subdevice *s);
+ 
+-static void das6402_setcounter(struct comedi_device * dev)
++static void das6402_setcounter(struct comedi_device *dev)
+ {
+ 	BYTE p;
+ 	unsigned short ctrlwrd;
+@@ -186,7 +186,7 @@ static irqreturn_t intr_handler(int irq, void *d)
+ }
+ 
+ #if 0
+-static void das6402_ai_fifo_read(struct comedi_device * dev, short * data, int n)
++static void das6402_ai_fifo_read(struct comedi_device *dev, short *data, int n)
+ {
+ 	int i;
+ 
+@@ -195,7 +195,7 @@ static void das6402_ai_fifo_read(struct comedi_device * dev, short * data, int n
+ }
+ #endif
+ 
+-static void das6402_ai_fifo_dregs(struct comedi_device * dev, struct comedi_subdevice * s)
++static void das6402_ai_fifo_dregs(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	while (1) {
+ 		if (!(inb(dev->iobase + 8) & 0x01))
+@@ -204,7 +204,7 @@ static void das6402_ai_fifo_dregs(struct comedi_device * dev, struct comedi_subd
+ 	}
+ }
+ 
+-static int das6402_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int das6402_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	/*
+ 	 *  This function should reset the board from whatever condition it
+@@ -226,8 +226,8 @@ static int das6402_ai_cancel(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ #ifdef unused
+-static int das6402_ai_mode2(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_trig * it)
++static int das6402_ai_mode2(struct comedi_device *dev, struct comedi_subdevice *s,
++	comedi_trig *it)
+ {
+ 	devpriv->das6402_ignoreirq = 1;
+ 
+@@ -249,7 +249,7 @@ static int das6402_ai_mode2(struct comedi_device * dev, struct comedi_subdevice
+ }
+ #endif
+ 
+-static int board_init(struct comedi_device * dev)
++static int board_init(struct comedi_device *dev)
+ {
+ 	BYTE b;
+ 
+@@ -289,7 +289,7 @@ static int board_init(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int das6402_detach(struct comedi_device * dev)
++static int das6402_detach(struct comedi_device *dev)
+ {
+ 	if (dev->irq)
+ 		comedi_free_irq(dev->irq, dev);
+@@ -299,7 +299,7 @@ static int das6402_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int das6402_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int das6402_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	unsigned int irq;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
+index eafee0c655aa..aa1ae24da84c 100644
+--- a/drivers/staging/comedi/drivers/das800.c
++++ b/drivers/staging/comedi/drivers/das800.c
+@@ -242,9 +242,9 @@ struct das800_private {
+ 
+ #define devpriv ((struct das800_private *)dev->private)
+ 
+-static int das800_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int das800_detach(struct comedi_device * dev);
+-static int das800_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
++static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int das800_detach(struct comedi_device *dev);
++static int das800_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
+ 
+ static struct comedi_driver driver_das800 = {
+       driver_name:"das800",
+@@ -441,7 +441,7 @@ static irqreturn_t das800_interrupt(int irq, void *d)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int das800_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase = it->options[0];
+@@ -539,7 +539,7 @@ static int das800_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	return 0;
+ };
+ 
+-static int das800_detach(struct comedi_device * dev)
++static int das800_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: das800: remove\n", dev->minor);
+ 
+@@ -551,7 +551,7 @@ static int das800_detach(struct comedi_device * dev)
+ 	return 0;
+ };
+ 
+-static int das800_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int das800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	devpriv->forever = 0;
+ 	devpriv->count = 0;
+@@ -560,7 +560,7 @@ static int das800_cancel(struct comedi_device * dev, struct comedi_subdevice * s
+ }
+ 
+ /* enable_das800 makes the card start taking hardware triggered conversions */
+-static void enable_das800(struct comedi_device * dev)
++static void enable_das800(struct comedi_device *dev)
+ {
+ 	unsigned long irq_flags;
+ 	comedi_spin_lock_irqsave(&dev->spinlock, irq_flags);
+@@ -575,7 +575,7 @@ static void enable_das800(struct comedi_device * dev)
+ }
+ 
+ /* disable_das800 stops hardware triggered conversions */
+-static void disable_das800(struct comedi_device * dev)
++static void disable_das800(struct comedi_device *dev)
+ {
+ 	unsigned long irq_flags;
+ 	comedi_spin_lock_irqsave(&dev->spinlock, irq_flags);
+@@ -584,8 +584,8 @@ static void disable_das800(struct comedi_device * dev)
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags);
+ }
+ 
+-static int das800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int das800_ai_do_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -709,7 +709,7 @@ static int das800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subdev
+ 	return 0;
+ }
+ 
+-static int das800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int das800_ai_do_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	int startChan, endChan, scan, gain;
+ 	int conv_bits;
+@@ -788,8 +788,8 @@ static int das800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice
+ 	return 0;
+ }
+ 
+-static int das800_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das800_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, n;
+ 	int chan;
+@@ -842,8 +842,8 @@ static int das800_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ 	return n;
+ }
+ 
+-static int das800_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das800_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int bits;
+ 
+@@ -855,8 +855,8 @@ static int das800_di_rbits(struct comedi_device * dev, struct comedi_subdevice *
+ 	return 2;
+ }
+ 
+-static int das800_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int das800_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int wbits;
+ 	unsigned long irq_flags;
+@@ -879,7 +879,7 @@ static int das800_do_wbits(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ /* loads counters with divisor1, divisor2 from private structure */
+-static int das800_set_frequency(struct comedi_device * dev)
++static int das800_set_frequency(struct comedi_device *dev)
+ {
+ 	int err = 0;
+ 
+diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
+index d627479ff71a..de6a96708140 100644
+--- a/drivers/staging/comedi/drivers/dmm32at.c
++++ b/drivers/staging/comedi/drivers/dmm32at.c
+@@ -258,8 +258,8 @@ struct dmm32at_private {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int dmm32at_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int dmm32at_detach(struct comedi_device * dev);
++static int dmm32at_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int dmm32at_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_dmm32at = {
+       driver_name:"dmm32at",
+       module:THIS_MODULE,
+@@ -313,7 +313,7 @@ void dmm32at_setaitimer(struct comedi_device * dev, unsigned int nansec);
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int dmm32at_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int dmm32at_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int ret;
+ 	struct comedi_subdevice *s;
+@@ -481,7 +481,7 @@ static int dmm32at_attach(struct comedi_device * dev, struct comedi_devconfig *
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int dmm32at_detach(struct comedi_device * dev)
++static int dmm32at_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: dmm32at: remove\n", dev->minor);
+ 	if (dev->irq)
+@@ -497,8 +497,8 @@ static int dmm32at_detach(struct comedi_device * dev)
+  * mode.
+  */
+ 
+-static int dmm32at_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dmm32at_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, i;
+ 	unsigned int d;
+@@ -568,8 +568,8 @@ static int dmm32at_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice
+ 	return n;
+ }
+ 
+-static int dmm32at_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int dmm32at_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -752,7 +752,7 @@ static int dmm32at_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevic
+ 	return 0;
+ }
+ 
+-static int dmm32at_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int dmm32at_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+ 	int i, range;
+@@ -822,7 +822,7 @@ static int dmm32at_ai_cmd(struct comedi_device * dev, struct comedi_subdevice *
+ 
+ }
+ 
+-static int dmm32at_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int dmm32at_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	devpriv->ai_scans_left = 1;
+ 	return 0;
+@@ -893,8 +893,8 @@ static int dmm32at_ns_to_timer(unsigned int *ns, int round)
+ 	return *ns;
+ }
+ 
+-static int dmm32at_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dmm32at_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -936,8 +936,8 @@ static int dmm32at_ao_winsn(struct comedi_device * dev, struct comedi_subdevice
+ 
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+-static int dmm32at_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dmm32at_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -953,8 +953,8 @@ static int dmm32at_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice
+  * useful to applications if you implement the insn_bits interface.
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+-static int dmm32at_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dmm32at_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned char diobits;
+ 
+@@ -1006,8 +1006,8 @@ static int dmm32at_dio_insn_bits(struct comedi_device * dev, struct comedi_subde
+ 	return 2;
+ }
+ 
+-static int dmm32at_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dmm32at_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned char chanbit;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -1043,7 +1043,7 @@ static int dmm32at_dio_insn_config(struct comedi_device * dev, struct comedi_sub
+ 	return 1;
+ }
+ 
+-void dmm32at_setaitimer(struct comedi_device * dev, unsigned int nansec)
++void dmm32at_setaitimer(struct comedi_device *dev, unsigned int nansec)
+ {
+ 	unsigned char lo1, lo2, hi2;
+ 	unsigned short both2;
+diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c
+index c3b927dc8886..309abba276d4 100644
+--- a/drivers/staging/comedi/drivers/dt2801.c
++++ b/drivers/staging/comedi/drivers/dt2801.c
+@@ -88,8 +88,8 @@ Configuration options:
+ #define DT2801_STATUS		1
+ #define DT2801_CMD		1
+ 
+-static int dt2801_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int dt2801_detach(struct comedi_device * dev);
++static int dt2801_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int dt2801_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_dt2801 = {
+       driver_name:"dt2801",
+       module:THIS_MODULE,
+@@ -228,16 +228,16 @@ struct dt2801_private {
+ 
+ #define devpriv ((struct dt2801_private *)dev->private)
+ 
+-static int dt2801_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int dt2801_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int dt2801_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int dt2801_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int dt2801_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int dt2801_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int dt2801_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int dt2801_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int dt2801_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int dt2801_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+ /* These are the low-level routines:
+    writecommand: write a command to the board
+@@ -248,7 +248,7 @@ static int dt2801_dio_insn_config(struct comedi_device * dev, struct comedi_subd
+ /* Only checks DataOutReady-flag, not the Ready-flag as it is done
+    in the examples of the manual. I don't see why this should be
+    necessary. */
+-static int dt2801_readdata(struct comedi_device * dev, int *data)
++static int dt2801_readdata(struct comedi_device *dev, int *data)
+ {
+ 	int stat = 0;
+ 	int timeout = DT2801_TIMEOUT;
+@@ -267,7 +267,7 @@ static int dt2801_readdata(struct comedi_device * dev, int *data)
+ 	return -ETIME;
+ }
+ 
+-static int dt2801_readdata2(struct comedi_device * dev, int *data)
++static int dt2801_readdata2(struct comedi_device *dev, int *data)
+ {
+ 	int lb, hb;
+ 	int ret;
+@@ -283,7 +283,7 @@ static int dt2801_readdata2(struct comedi_device * dev, int *data)
+ 	return 0;
+ }
+ 
+-static int dt2801_writedata(struct comedi_device * dev, unsigned int data)
++static int dt2801_writedata(struct comedi_device *dev, unsigned int data)
+ {
+ 	int stat = 0;
+ 	int timeout = DT2801_TIMEOUT;
+@@ -309,7 +309,7 @@ static int dt2801_writedata(struct comedi_device * dev, unsigned int data)
+ 	return -ETIME;
+ }
+ 
+-static int dt2801_writedata2(struct comedi_device * dev, unsigned int data)
++static int dt2801_writedata2(struct comedi_device *dev, unsigned int data)
+ {
+ 	int ret;
+ 
+@@ -323,7 +323,7 @@ static int dt2801_writedata2(struct comedi_device * dev, unsigned int data)
+ 	return 0;
+ }
+ 
+-static int dt2801_wait_for_ready(struct comedi_device * dev)
++static int dt2801_wait_for_ready(struct comedi_device *dev)
+ {
+ 	int timeout = DT2801_TIMEOUT;
+ 	int stat;
+@@ -346,7 +346,7 @@ static int dt2801_wait_for_ready(struct comedi_device * dev)
+ 	return -ETIME;
+ }
+ 
+-static int dt2801_writecmd(struct comedi_device * dev, int command)
++static int dt2801_writecmd(struct comedi_device *dev, int command)
+ {
+ 	int stat;
+ 
+@@ -364,7 +364,7 @@ static int dt2801_writecmd(struct comedi_device * dev, int command)
+ 	return 0;
+ }
+ 
+-static int dt2801_reset(struct comedi_device * dev)
++static int dt2801_reset(struct comedi_device *dev)
+ {
+ 	int board_code = 0;
+ 	unsigned int stat;
+@@ -422,7 +422,7 @@ static int dt2801_reset(struct comedi_device * dev)
+ 	return board_code;
+ }
+ 
+-static int probe_number_of_ai_chans(struct comedi_device * dev)
++static int probe_number_of_ai_chans(struct comedi_device *dev)
+ {
+ 	int n_chans;
+ 	int stat;
+@@ -483,7 +483,7 @@ static const struct comedi_lrange *ai_range_lkup(int type, int opt)
+ 	[4] - dac0 range 0=[-10,10], 1=[-5,5], 2=[-2.5,2.5] 3=[0,10], 4=[0,5]
+ 	[5] - dac1 range 0=[-10,10], 1=[-5,5], 2=[-2.5,2.5] 3=[0,10], 4=[0,5]
+ */
+-static int dt2801_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int dt2801_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+@@ -584,7 +584,7 @@ static int dt2801_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	return ret;
+ }
+ 
+-static int dt2801_detach(struct comedi_device * dev)
++static int dt2801_detach(struct comedi_device *dev)
+ {
+ 	if (dev->iobase)
+ 		release_region(dev->iobase, DT2801_IOSIZE);
+@@ -592,7 +592,7 @@ static int dt2801_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int dt2801_error(struct comedi_device * dev, int stat)
++static int dt2801_error(struct comedi_device *dev, int stat)
+ {
+ 	if (stat < 0) {
+ 		if (stat == -ETIME) {
+@@ -610,8 +610,8 @@ static int dt2801_error(struct comedi_device * dev, int stat)
+ 	return -EIO;
+ }
+ 
+-static int dt2801_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dt2801_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int d;
+ 	int stat;
+@@ -632,16 +632,16 @@ static int dt2801_ai_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ 	return i;
+ }
+ 
+-static int dt2801_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dt2801_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[0] = devpriv->ao_readback[CR_CHAN(insn->chanspec)];
+ 
+ 	return 1;
+ }
+ 
+-static int dt2801_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dt2801_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	dt2801_writecmd(dev, DT_C_WRITE_DAIM);
+ 	dt2801_writedata(dev, CR_CHAN(insn->chanspec));
+@@ -652,8 +652,8 @@ static int dt2801_ao_insn_write(struct comedi_device * dev, struct comedi_subdev
+ 	return 1;
+ }
+ 
+-static int dt2801_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dt2801_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int which = 0;
+ 
+@@ -676,8 +676,8 @@ static int dt2801_dio_insn_bits(struct comedi_device * dev, struct comedi_subdev
+ 	return 2;
+ }
+ 
+-static int dt2801_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dt2801_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int which = 0;
+ 
+diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c
+index c6908075ab04..634f2adf7628 100644
+--- a/drivers/staging/comedi/drivers/dt2811.c
++++ b/drivers/staging/comedi/drivers/dt2811.c
+@@ -214,8 +214,8 @@ static const struct dt2811_board boardtypes[] = {
+ 
+ #define this_board ((const struct dt2811_board *)dev->board_ptr)
+ 
+-static int dt2811_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int dt2811_detach(struct comedi_device * dev);
++static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int dt2811_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_dt2811 = {
+       driver_name:"dt2811",
+       module:THIS_MODULE,
+@@ -228,16 +228,16 @@ static struct comedi_driver driver_dt2811 = {
+ 
+ COMEDI_INITCLEANUP(driver_dt2811);
+ 
+-static int dt2811_ai_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int dt2811_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int dt2811_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int dt2811_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int dt2811_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int dt2811_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int dt2811_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int dt2811_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int dt2811_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int dt2811_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+ enum { card_2811_pgh, card_2811_pgl };
+ 
+@@ -311,7 +311,7 @@ static irqreturn_t dt2811_interrupt(int irq, void *d)
+                  2 == unipolar 5V  (0V -- +5V)
+ */
+ 
+-static int dt2811_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	/* int i, irq; */
+ 	/* unsigned long irqs; */
+@@ -480,7 +480,7 @@ static int dt2811_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	return 0;
+ }
+ 
+-static int dt2811_detach(struct comedi_device * dev)
++static int dt2811_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: dt2811: remove\n", dev->minor);
+ 
+@@ -494,8 +494,8 @@ static int dt2811_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int dt2811_ai_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dt2811_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	int timeout = DT2811_TIMEOUT;
+@@ -521,7 +521,7 @@ static int dt2811_ai_insn(struct comedi_device * dev, struct comedi_subdevice *
+ #if 0
+ /* Wow.  This is code from the Comedi stone age.  But it hasn't been
+  * replaced, so I'll let it stay. */
+-int dt2811_adtrig(kdev_t minor, comedi_adtrig * adtrig)
++int dt2811_adtrig(kdev_t minor, comedi_adtrig *adtrig)
+ {
+ 	struct comedi_device *dev = comedi_devices + minor;
+ 
+@@ -545,8 +545,8 @@ int dt2811_adtrig(kdev_t minor, comedi_adtrig * adtrig)
+ }
+ #endif
+ 
+-static int dt2811_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dt2811_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan;
+@@ -563,8 +563,8 @@ static int dt2811_ao_insn(struct comedi_device * dev, struct comedi_subdevice *
+ 	return i;
+ }
+ 
+-static int dt2811_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dt2811_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan;
+@@ -578,8 +578,8 @@ static int dt2811_ao_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ 	return i;
+ }
+ 
+-static int dt2811_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dt2811_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -589,8 +589,8 @@ static int dt2811_di_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+ 	return 2;
+ }
+ 
+-static int dt2811_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dt2811_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c
+index e806520b5879..6b82f6ef53f3 100644
+--- a/drivers/staging/comedi/drivers/dt2814.c
++++ b/drivers/staging/comedi/drivers/dt2814.c
+@@ -59,8 +59,8 @@ addition, the clock does not seem to be very accurate.
+ #define DT2814_ENB 0x10
+ #define DT2814_CHANMASK 0x0f
+ 
+-static int dt2814_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int dt2814_detach(struct comedi_device * dev);
++static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int dt2814_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_dt2814 = {
+       driver_name:"dt2814",
+       module:THIS_MODULE,
+@@ -83,8 +83,8 @@ struct dt2814_private {
+ #define DT2814_TIMEOUT 10
+ #define DT2814_MAX_SPEED 100000	/* Arbitrary 10 khz limit */
+ 
+-static int dt2814_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dt2814_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, i, hi, lo;
+ 	int chan;
+@@ -134,8 +134,8 @@ static int dt2814_ns_to_timer(unsigned int *ns, unsigned int flags)
+ 	return i;
+ }
+ 
+-static int dt2814_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int dt2814_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -226,7 +226,7 @@ static int dt2814_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice
+ 	return 0;
+ }
+ 
+-static int dt2814_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int dt2814_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+ 	int chan;
+@@ -245,7 +245,7 @@ static int dt2814_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s
+ 
+ }
+ 
+-static int dt2814_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int i, irq;
+ 	int ret;
+@@ -329,7 +329,7 @@ static int dt2814_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	return 0;
+ }
+ 
+-static int dt2814_detach(struct comedi_device * dev)
++static int dt2814_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: dt2814: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c
+index fccec8a77d50..36a2f07792bc 100644
+--- a/drivers/staging/comedi/drivers/dt2815.c
++++ b/drivers/staging/comedi/drivers/dt2815.c
+@@ -75,8 +75,8 @@ static const struct comedi_lrange range_dt2815_ao_20_current = { 1, {
+ #define DT2815_DATA 0
+ #define DT2815_STATUS 1
+ 
+-static int dt2815_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int dt2815_detach(struct comedi_device * dev);
++static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int dt2815_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_dt2815 = {
+       driver_name:"dt2815",
+       module:THIS_MODULE,
+@@ -86,7 +86,7 @@ static struct comedi_driver driver_dt2815 = {
+ 
+ COMEDI_INITCLEANUP(driver_dt2815);
+ 
+-static void dt2815_free_resources(struct comedi_device * dev);
++static void dt2815_free_resources(struct comedi_device *dev);
+ 
+ struct dt2815_private {
+ 
+@@ -97,7 +97,7 @@ struct dt2815_private {
+ 
+ #define devpriv ((struct dt2815_private *)dev->private)
+ 
+-static int dt2815_wait_for_status(struct comedi_device * dev, int status)
++static int dt2815_wait_for_status(struct comedi_device *dev, int status)
+ {
+ 	int i;
+ 
+@@ -108,8 +108,8 @@ static int dt2815_wait_for_status(struct comedi_device * dev, int status)
+ 	return status;
+ }
+ 
+-static int dt2815_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dt2815_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -121,8 +121,8 @@ static int dt2815_ao_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ 	return i;
+ }
+ 
+-static int dt2815_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dt2815_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -179,7 +179,7 @@ static int dt2815_ao_insn(struct comedi_device * dev, struct comedi_subdevice *
+                  1 == current
+  */
+ 
+-static int dt2815_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int i;
+@@ -248,13 +248,13 @@ static int dt2815_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	return 0;
+ }
+ 
+-static void dt2815_free_resources(struct comedi_device * dev)
++static void dt2815_free_resources(struct comedi_device *dev)
+ {
+ 	if (dev->iobase)
+ 		release_region(dev->iobase, DT2815_SIZE);
+ }
+ 
+-static int dt2815_detach(struct comedi_device * dev)
++static int dt2815_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: dt2815: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c
+index 2dc396a44e6f..8d52b2699220 100644
+--- a/drivers/staging/comedi/drivers/dt2817.c
++++ b/drivers/staging/comedi/drivers/dt2817.c
+@@ -47,8 +47,8 @@ Configuration options:
+ #define DT2817_CR 0
+ #define DT2817_DATA 1
+ 
+-static int dt2817_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int dt2817_detach(struct comedi_device * dev);
++static int dt2817_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int dt2817_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_dt2817 = {
+       driver_name:"dt2817",
+       module:THIS_MODULE,
+@@ -58,8 +58,8 @@ static struct comedi_driver driver_dt2817 = {
+ 
+ COMEDI_INITCLEANUP(driver_dt2817);
+ 
+-static int dt2817_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dt2817_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int mask;
+ 	int chan;
+@@ -96,8 +96,8 @@ static int dt2817_dio_insn_config(struct comedi_device * dev, struct comedi_subd
+ 	return 1;
+ }
+ 
+-static int dt2817_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dt2817_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int changed;
+ 
+@@ -131,7 +131,7 @@ static int dt2817_dio_insn_bits(struct comedi_device * dev, struct comedi_subdev
+ 	return 2;
+ }
+ 
+-static int dt2817_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int dt2817_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int ret;
+ 	struct comedi_subdevice *s;
+@@ -167,7 +167,7 @@ static int dt2817_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	return 0;
+ }
+ 
+-static int dt2817_detach(struct comedi_device * dev)
++static int dt2817_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: dt2817: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
+index 275644ac4b94..3174c36573e2 100644
+--- a/drivers/staging/comedi/drivers/dt282x.c
++++ b/drivers/staging/comedi/drivers/dt282x.c
+@@ -394,8 +394,8 @@ struct dt282x_private {
+ 		if(_i){b}				\
+ 	}while(0)
+ 
+-static int dt282x_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int dt282x_detach(struct comedi_device * dev);
++static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int dt282x_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_dt282x = {
+       driver_name:"dt282x",
+       module:THIS_MODULE,
+@@ -408,17 +408,17 @@ static struct comedi_driver driver_dt282x = {
+ 
+ COMEDI_INITCLEANUP(driver_dt282x);
+ 
+-static void free_resources(struct comedi_device * dev);
+-static int prep_ai_dma(struct comedi_device * dev, int chan, int size);
+-static int prep_ao_dma(struct comedi_device * dev, int chan, int size);
+-static int dt282x_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int dt282x_ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
++static void free_resources(struct comedi_device *dev);
++static int prep_ai_dma(struct comedi_device *dev, int chan, int size);
++static int prep_ao_dma(struct comedi_device *dev, int chan, int size);
++static int dt282x_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
++static int dt282x_ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
+ static int dt282x_ns_to_timer(int *nanosec, int round_mode);
+-static void dt282x_disable_dma(struct comedi_device * dev);
++static void dt282x_disable_dma(struct comedi_device *dev);
+ 
+-static int dt282x_grab_dma(struct comedi_device * dev, int dma1, int dma2);
++static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2);
+ 
+-static void dt282x_munge(struct comedi_device * dev, short * buf,
++static void dt282x_munge(struct comedi_device *dev, short *buf,
+ 	unsigned int nbytes)
+ {
+ 	unsigned int i;
+@@ -440,7 +440,7 @@ static void dt282x_munge(struct comedi_device * dev, short * buf,
+ 	}
+ }
+ 
+-static void dt282x_ao_dma_interrupt(struct comedi_device * dev)
++static void dt282x_ao_dma_interrupt(struct comedi_device *dev)
+ {
+ 	void *ptr;
+ 	int size;
+@@ -472,7 +472,7 @@ static void dt282x_ao_dma_interrupt(struct comedi_device * dev)
+ 	return;
+ }
+ 
+-static void dt282x_ai_dma_interrupt(struct comedi_device * dev)
++static void dt282x_ai_dma_interrupt(struct comedi_device *dev)
+ {
+ 	void *ptr;
+ 	int size;
+@@ -524,7 +524,7 @@ static void dt282x_ai_dma_interrupt(struct comedi_device * dev)
+ 	prep_ai_dma(dev, i, 0);
+ }
+ 
+-static int prep_ai_dma(struct comedi_device * dev, int dma_index, int n)
++static int prep_ai_dma(struct comedi_device *dev, int dma_index, int n)
+ {
+ 	int dma_chan;
+ 	unsigned long dma_ptr;
+@@ -555,7 +555,7 @@ static int prep_ai_dma(struct comedi_device * dev, int dma_index, int n)
+ 	return n;
+ }
+ 
+-static int prep_ao_dma(struct comedi_device * dev, int dma_index, int n)
++static int prep_ao_dma(struct comedi_device *dev, int dma_index, int n)
+ {
+ 	int dma_chan;
+ 	unsigned long dma_ptr;
+@@ -653,7 +653,7 @@ static irqreturn_t dt282x_interrupt(int irq, void *d)
+ 	return IRQ_RETVAL(handled);
+ }
+ 
+-static void dt282x_load_changain(struct comedi_device * dev, int n,
++static void dt282x_load_changain(struct comedi_device *dev, int n,
+ 	unsigned int *chanlist)
+ {
+ 	unsigned int i;
+@@ -674,8 +674,8 @@ static void dt282x_load_changain(struct comedi_device * dev, int n,
+  *      - preload multiplexer
+  *      - trigger conversion and wait for it to finish
+  */
+-static int dt282x_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dt282x_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 
+@@ -706,8 +706,8 @@ static int dt282x_ai_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ 	return i;
+ }
+ 
+-static int dt282x_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int dt282x_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -818,7 +818,7 @@ static int dt282x_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice
+ 	return 0;
+ }
+ 
+-static int dt282x_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+ 	int timer;
+@@ -879,7 +879,7 @@ static int dt282x_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s
+ 	return 0;
+ }
+ 
+-static void dt282x_disable_dma(struct comedi_device * dev)
++static void dt282x_disable_dma(struct comedi_device *dev)
+ {
+ 	if (devpriv->usedma) {
+ 		disable_dma(devpriv->dma[0].chan);
+@@ -887,7 +887,7 @@ static void dt282x_disable_dma(struct comedi_device * dev)
+ 	}
+ }
+ 
+-static int dt282x_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int dt282x_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	dt282x_disable_dma(dev);
+ 
+@@ -937,16 +937,16 @@ static int dt282x_ns_to_timer(int *nanosec, int round_mode)
+  *      offset binary if necessary, loads the data into the DAC
+  *      data register, and performs the conversion.
+  */
+-static int dt282x_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dt282x_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[0] = devpriv->ao[CR_CHAN(insn->chanspec)];
+ 
+ 	return 1;
+ }
+ 
+-static int dt282x_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dt282x_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	short d;
+ 	unsigned int chan;
+@@ -978,8 +978,8 @@ static int dt282x_ao_insn_write(struct comedi_device * dev, struct comedi_subdev
+ 	return 1;
+ }
+ 
+-static int dt282x_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int dt282x_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -1069,7 +1069,7 @@ static int dt282x_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice
+ 
+ }
+ 
+-static int dt282x_ao_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
++static int dt282x_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int x)
+ {
+ 	int size;
+@@ -1099,7 +1099,7 @@ static int dt282x_ao_inttrig(struct comedi_device * dev, struct comedi_subdevice
+ 	return 1;
+ }
+ 
+-static int dt282x_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	int timer;
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+@@ -1132,7 +1132,7 @@ static int dt282x_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s
+ 	return 0;
+ }
+ 
+-static int dt282x_ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int dt282x_ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	dt282x_disable_dma(dev);
+ 
+@@ -1145,8 +1145,8 @@ static int dt282x_ao_cancel(struct comedi_device * dev, struct comedi_subdevice
+ 	return 0;
+ }
+ 
+-static int dt282x_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dt282x_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (data[0]) {
+ 		s->state &= ~data[0];
+@@ -1159,8 +1159,8 @@ static int dt282x_dio_insn_bits(struct comedi_device * dev, struct comedi_subdev
+ 	return 2;
+ }
+ 
+-static int dt282x_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dt282x_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int mask;
+ 
+@@ -1240,7 +1240,7 @@ enum { opt_iobase = 0, opt_irq, opt_dma1, opt_dma2,	/* i/o base, irq, dma channe
+    9	ao0 0=±10 V, 1=0-10 V, 2=±5 V, 3=0-5 V, 4=±2.5 V
+    10	ao1 0=±10 V, 1=0-10 V, 2=±5 V, 3=0-5 V, 4=±2.5 V
+  */
+-static int dt282x_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int i, irq;
+ 	int ret;
+@@ -1396,7 +1396,7 @@ static int dt282x_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	return 0;
+ }
+ 
+-static void free_resources(struct comedi_device * dev)
++static void free_resources(struct comedi_device *dev)
+ {
+ 	if (dev->irq) {
+ 		comedi_free_irq(dev->irq, dev);
+@@ -1415,7 +1415,7 @@ static void free_resources(struct comedi_device * dev)
+ 	}
+ }
+ 
+-static int dt282x_detach(struct comedi_device * dev)
++static int dt282x_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: dt282x: remove\n", dev->minor);
+ 
+@@ -1424,7 +1424,7 @@ static int dt282x_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int dt282x_grab_dma(struct comedi_device * dev, int dma1, int dma2)
++static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2)
+ {
+ 	int ret;
+ 
+diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
+index dabc09705048..2d301597c3ed 100644
+--- a/drivers/staging/comedi/drivers/dt3000.c
++++ b/drivers/staging/comedi/drivers/dt3000.c
+@@ -275,8 +275,8 @@ struct dt3k_private {
+ 
+ #define devpriv ((struct dt3k_private *)dev->private)
+ 
+-static int dt3000_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int dt3000_detach(struct comedi_device * dev);
++static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int dt3000_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_dt3000 = {
+       driver_name:"dt3000",
+       module:THIS_MODULE,
+@@ -286,17 +286,17 @@ static struct comedi_driver driver_dt3000 = {
+ 
+ COMEDI_PCI_INITCLEANUP(driver_dt3000, dt3k_pci_table);
+ 
+-static void dt3k_ai_empty_fifo(struct comedi_device * dev, struct comedi_subdevice * s);
++static void dt3k_ai_empty_fifo(struct comedi_device *dev, struct comedi_subdevice *s);
+ static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *arg,
+ 	unsigned int round_mode);
+-static int dt3k_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
++static int dt3k_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
+ #ifdef DEBUG
+ static void debug_intr_flags(unsigned int flags);
+ #endif
+ 
+ #define TIMEOUT 100
+ 
+-static int dt3k_send_cmd(struct comedi_device * dev, unsigned int cmd)
++static int dt3k_send_cmd(struct comedi_device *dev, unsigned int cmd)
+ {
+ 	int i;
+ 	unsigned int status = 0;
+@@ -318,7 +318,7 @@ static int dt3k_send_cmd(struct comedi_device * dev, unsigned int cmd)
+ 	return -ETIME;
+ }
+ 
+-static unsigned int dt3k_readsingle(struct comedi_device * dev, unsigned int subsys,
++static unsigned int dt3k_readsingle(struct comedi_device *dev, unsigned int subsys,
+ 	unsigned int chan, unsigned int gain)
+ {
+ 	writew(subsys, devpriv->io_addr + DPR_SubSys);
+@@ -331,7 +331,7 @@ static unsigned int dt3k_readsingle(struct comedi_device * dev, unsigned int sub
+ 	return readw(devpriv->io_addr + DPR_Params(2));
+ }
+ 
+-static void dt3k_writesingle(struct comedi_device * dev, unsigned int subsys,
++static void dt3k_writesingle(struct comedi_device *dev, unsigned int subsys,
+ 	unsigned int chan, unsigned int data)
+ {
+ 	writew(subsys, devpriv->io_addr + DPR_SubSys);
+@@ -400,7 +400,7 @@ static void debug_intr_flags(unsigned int flags)
+ }
+ #endif
+ 
+-static void dt3k_ai_empty_fifo(struct comedi_device * dev, struct comedi_subdevice * s)
++static void dt3k_ai_empty_fifo(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	int front;
+ 	int rear;
+@@ -429,8 +429,8 @@ static void dt3k_ai_empty_fifo(struct comedi_device * dev, struct comedi_subdevi
+ 	writew(rear, devpriv->io_addr + DPR_AD_Buf_Rear);
+ }
+ 
+-static int dt3k_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int dt3k_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -591,7 +591,7 @@ static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
+ 	return (prescale << 16) | (divider);
+ }
+ 
+-static int dt3k_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+ 	int i;
+@@ -659,7 +659,7 @@ static int dt3k_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int dt3k_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int dt3k_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	int ret;
+ 
+@@ -671,8 +671,8 @@ static int dt3k_ai_cancel(struct comedi_device * dev, struct comedi_subdevice *
+ 	return 0;
+ }
+ 
+-static int dt3k_ai_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dt3k_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	unsigned int chan, gain, aref;
+@@ -689,8 +689,8 @@ static int dt3k_ai_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int dt3k_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dt3k_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	unsigned int chan;
+@@ -704,8 +704,8 @@ static int dt3k_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int dt3k_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dt3k_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	unsigned int chan;
+@@ -718,7 +718,7 @@ static int dt3k_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice
+ 	return i;
+ }
+ 
+-static void dt3k_dio_config(struct comedi_device * dev, int bits)
++static void dt3k_dio_config(struct comedi_device *dev, int bits)
+ {
+ 	/* XXX */
+ 	writew(SUBS_DOUT, devpriv->io_addr + DPR_SubSys);
+@@ -733,8 +733,8 @@ static void dt3k_dio_config(struct comedi_device * dev, int bits)
+ 	dt3k_send_cmd(dev, CMD_CONFIG);
+ }
+ 
+-static int dt3k_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dt3k_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int mask;
+ 
+@@ -764,8 +764,8 @@ static int dt3k_dio_insn_config(struct comedi_device * dev, struct comedi_subdev
+ 	return insn->n;
+ }
+ 
+-static int dt3k_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dt3k_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -780,8 +780,8 @@ static int dt3k_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevic
+ 	return 2;
+ }
+ 
+-static int dt3k_mem_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dt3k_mem_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int addr = CR_CHAN(insn->chanspec);
+ 	int i;
+@@ -799,9 +799,9 @@ static int dt3k_mem_insn_read(struct comedi_device * dev, struct comedi_subdevic
+ 	return i;
+ }
+ 
+-static int dt_pci_probe(struct comedi_device * dev, int bus, int slot);
++static int dt_pci_probe(struct comedi_device *dev, int bus, int slot);
+ 
+-static int dt3000_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int bus, slot;
+@@ -890,7 +890,7 @@ static int dt3000_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	return 0;
+ }
+ 
+-static int dt3000_detach(struct comedi_device * dev)
++static int dt3000_detach(struct comedi_device *dev)
+ {
+ 	if (dev->irq)
+ 		comedi_free_irq(dev->irq, dev);
+@@ -911,9 +911,9 @@ static int dt3000_detach(struct comedi_device * dev)
+ }
+ 
+ static struct pci_dev *dt_pci_find_device(struct pci_dev *from, int *board);
+-static int setup_pci(struct comedi_device * dev);
++static int setup_pci(struct comedi_device *dev);
+ 
+-static int dt_pci_probe(struct comedi_device * dev, int bus, int slot)
++static int dt_pci_probe(struct comedi_device *dev, int bus, int slot)
+ {
+ 	int board;
+ 	int ret;
+@@ -941,7 +941,7 @@ static int dt_pci_probe(struct comedi_device * dev, int bus, int slot)
+ 	return 1;
+ }
+ 
+-static int setup_pci(struct comedi_device * dev)
++static int setup_pci(struct comedi_device *dev)
+ {
+ 	resource_size_t addr;
+ 	int ret;
+diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c
+index 6d7bb37d2b1c..5a9a254997a6 100644
+--- a/drivers/staging/comedi/drivers/fl512.c
++++ b/drivers/staging/comedi/drivers/fl512.c
+@@ -42,8 +42,8 @@ static const struct comedi_lrange range_fl512 = { 4, {
+ 	}
+ };
+ 
+-static int fl512_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int fl512_detach(struct comedi_device * dev);
++static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int fl512_detach(struct comedi_device *dev);
+ 
+ static struct comedi_driver driver_fl512 = {
+       driver_name:"fl512",
+@@ -54,18 +54,18 @@ static struct comedi_driver driver_fl512 = {
+ 
+ COMEDI_INITCLEANUP(driver_fl512);
+ 
+-static int fl512_ai_insn(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
+-static int fl512_ao_insn(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
+-static int fl512_ao_insn_readback(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
++static int fl512_ai_insn(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
++static int fl512_ao_insn(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
++static int fl512_ao_insn_readback(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * fl512_ai_insn : this is the analog input function
+  */
+-static int fl512_ai_insn(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++static int fl512_ai_insn(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	unsigned int lo_byte, hi_byte;
+@@ -89,8 +89,8 @@ static int fl512_ai_insn(struct comedi_device * dev,
+ /*
+  * fl512_ao_insn : used to write to a DA port n times
+  */
+-static int fl512_ao_insn(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++static int fl512_ao_insn(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);	/* get chan to write */
+@@ -110,8 +110,8 @@ static int fl512_ao_insn(struct comedi_device * dev,
+  * fl512_ao_insn_readback : used to read previous values written to
+  * DA port
+  */
+-static int fl512_ao_insn_readback(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++static int fl512_ao_insn_readback(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -126,7 +126,7 @@ static int fl512_ao_insn_readback(struct comedi_device * dev,
+ /*
+  * start attach
+  */
+-static int fl512_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	unsigned long iobase;
+ 	struct comedi_subdevice *s;	/* pointer to the subdevice:
+@@ -177,7 +177,7 @@ static int fl512_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 	return 1;
+ }
+ 
+-static int fl512_detach(struct comedi_device * dev)
++static int fl512_detach(struct comedi_device *dev)
+ {
+ 	if (dev->iobase)
+ 		release_region(dev->iobase, FL512_SIZE);
+diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
+index cd5772f90aa1..48491c09e7f2 100644
+--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
++++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
+@@ -340,8 +340,8 @@ static struct comedi_driver driver_hpdi = {
+ 
+ COMEDI_PCI_INITCLEANUP(driver_hpdi, hpdi_pci_table);
+ 
+-static int dio_config_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dio_config_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	switch (data[0]) {
+ 	case INSN_CONFIG_DIO_OUTPUT:
+@@ -368,13 +368,13 @@ static int dio_config_insn(struct comedi_device * dev, struct comedi_subdevice *
+ 	return -EINVAL;
+ }
+ 
+-static void disable_plx_interrupts(struct comedi_device * dev)
++static void disable_plx_interrupts(struct comedi_device *dev)
+ {
+ 	writel(0, priv(dev)->plx9080_iobase + PLX_INTRCS_REG);
+ }
+ 
+ /* initialize plx9080 chip */
+-static void init_plx9080(struct comedi_device * dev)
++static void init_plx9080(struct comedi_device *dev)
+ {
+ 	uint32_t bits;
+ 	void *plx_iobase = priv(dev)->plx9080_iobase;
+@@ -439,7 +439,7 @@ static void init_plx9080(struct comedi_device * dev)
+ 
+ /* Allocate and initialize the subdevice structures.
+  */
+-static int setup_subdevices(struct comedi_device * dev)
++static int setup_subdevices(struct comedi_device *dev)
+ {
+ 	struct comedi_subdevice *s;
+ 
+@@ -465,7 +465,7 @@ static int setup_subdevices(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int init_hpdi(struct comedi_device * dev)
++static int init_hpdi(struct comedi_device *dev)
+ {
+ 	uint32_t plx_intcsr_bits;
+ 
+@@ -494,7 +494,7 @@ static int init_hpdi(struct comedi_device * dev)
+ }
+ 
+ /* setup dma descriptors so a link completes every 'transfer_size' bytes */
+-static int setup_dma_descriptors(struct comedi_device * dev,
++static int setup_dma_descriptors(struct comedi_device *dev,
+ 	unsigned int transfer_size)
+ {
+ 	unsigned int buffer_index, buffer_offset;
+@@ -556,7 +556,7 @@ static int setup_dma_descriptors(struct comedi_device * dev,
+ 	return transfer_size;
+ }
+ 
+-static int hpdi_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct pci_dev *pcidev;
+ 	int i;
+@@ -665,7 +665,7 @@ static int hpdi_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ 	return init_hpdi(dev);
+ }
+ 
+-static int hpdi_detach(struct comedi_device * dev)
++static int hpdi_detach(struct comedi_device *dev)
+ {
+ 	unsigned int i;
+ 
+@@ -706,7 +706,7 @@ static int hpdi_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int dio_config_block_size(struct comedi_device * dev, unsigned int * data)
++static int dio_config_block_size(struct comedi_device *dev, unsigned int *data)
+ {
+ 	unsigned int requested_block_size;
+ 	int retval;
+@@ -722,8 +722,8 @@ static int dio_config_block_size(struct comedi_device * dev, unsigned int * data
+ 	return 2;
+ }
+ 
+-static int di_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int di_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -822,8 +822,8 @@ static int di_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int hpdi_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int hpdi_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	if (priv(dev)->dio_config_output) {
+ 		return -EINVAL;
+@@ -831,14 +831,14 @@ static int hpdi_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s
+ 		return di_cmd_test(dev, s, cmd);
+ }
+ 
+-static inline void hpdi_writel(struct comedi_device * dev, uint32_t bits,
++static inline void hpdi_writel(struct comedi_device *dev, uint32_t bits,
+ 	unsigned int offset)
+ {
+ 	writel(bits | priv(dev)->bits[offset / sizeof(uint32_t)],
+ 		priv(dev)->hpdi_iobase + offset);
+ }
+ 
+-static int di_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int di_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	uint32_t bits;
+ 	unsigned long flags;
+@@ -891,7 +891,7 @@ static int di_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int hpdi_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int hpdi_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	if (priv(dev)->dio_config_output) {
+ 		return -EINVAL;
+@@ -899,7 +899,7 @@ static int hpdi_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 		return di_cmd(dev, s);
+ }
+ 
+-static void drain_dma_buffers(struct comedi_device * dev, unsigned int channel)
++static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel)
+ {
+ 	struct comedi_async *async = dev->read_subdev->async;
+ 	uint32_t next_transfer_addr;
+@@ -1036,7 +1036,7 @@ static irqreturn_t handle_interrupt(int irq, void *d)
+ 	return IRQ_HANDLED;
+ }
+ 
+-void abort_dma(struct comedi_device * dev, unsigned int channel)
++void abort_dma(struct comedi_device *dev, unsigned int channel)
+ {
+ 	unsigned long flags;
+ 
+@@ -1048,7 +1048,7 @@ void abort_dma(struct comedi_device * dev, unsigned int channel)
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ }
+ 
+-static int hpdi_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int hpdi_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	hpdi_writel(dev, 0, BOARD_CONTROL_REG);
+ 
+diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c
+index 80825ba25418..fd8eb85ddbe9 100644
+--- a/drivers/staging/comedi/drivers/ii_pci20kc.c
++++ b/drivers/staging/comedi/drivers/ii_pci20kc.c
+@@ -158,8 +158,8 @@ struct pci20xxx_private {
+ #define devpriv ((struct pci20xxx_private *)dev->private)
+ #define CHAN (CR_CHAN(it->chanlist[0]))
+ 
+-static int pci20xxx_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pci20xxx_detach(struct comedi_device * dev);
++static int pci20xxx_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pci20xxx_detach(struct comedi_device *dev);
+ 
+ static struct comedi_driver driver_pci20xxx = {
+       driver_name:"ii_pci20kc",
+@@ -168,11 +168,11 @@ static struct comedi_driver driver_pci20xxx = {
+       detach:pci20xxx_detach,
+ };
+ 
+-static int pci20006_init(struct comedi_device * dev, struct comedi_subdevice * s,
++static int pci20006_init(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	int opt0, int opt1);
+-static int pci20341_init(struct comedi_device * dev, struct comedi_subdevice * s,
++static int pci20341_init(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	int opt0, int opt1);
+-static int pci20xxx_dio_init(struct comedi_device * dev, struct comedi_subdevice * s);
++static int pci20xxx_dio_init(struct comedi_device *dev, struct comedi_subdevice *s);
+ 
+ /*
+   options[0]	Board base address
+@@ -201,7 +201,7 @@ static int pci20xxx_dio_init(struct comedi_device * dev, struct comedi_subdevice
+ 		1 == unipolar 10V  (0V -- +10V)
+ 		2 == bipolar 5V  (-5V -- +5V)
+ */
+-static int pci20xxx_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pci20xxx_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	unsigned char i;
+ 	int ret;
+@@ -263,7 +263,7 @@ static int pci20xxx_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	return 1;
+ }
+ 
+-static int pci20xxx_detach(struct comedi_device * dev)
++static int pci20xxx_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: pci20xxx: remove\n", dev->minor);
+ 
+@@ -272,10 +272,10 @@ static int pci20xxx_detach(struct comedi_device * dev)
+ 
+ /* pci20006m */
+ 
+-static int pci20006_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int pci20006_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int pci20006_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int pci20006_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+ static const struct comedi_lrange *pci20006_range_list[] = {
+ 	&range_bipolar10,
+@@ -283,7 +283,7 @@ static const struct comedi_lrange *pci20006_range_list[] = {
+ 	&range_bipolar5,
+ };
+ 
+-static int pci20006_init(struct comedi_device * dev, struct comedi_subdevice * s,
++static int pci20006_init(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	int opt0, int opt1)
+ {
+ 	union pci20xxx_subdev_private *sdp = s->private;
+@@ -308,8 +308,8 @@ static int pci20006_init(struct comedi_device * dev, struct comedi_subdevice * s
+ 	return 0;
+ }
+ 
+-static int pci20006_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci20006_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	union pci20xxx_subdev_private *sdp = s->private;
+ 
+@@ -318,8 +318,8 @@ static int pci20006_insn_read(struct comedi_device * dev, struct comedi_subdevic
+ 	return 1;
+ }
+ 
+-static int pci20006_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci20006_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	union pci20xxx_subdev_private *sdp = s->private;
+ 	int hi, lo;
+@@ -351,8 +351,8 @@ static int pci20006_insn_write(struct comedi_device * dev, struct comedi_subdevi
+ 
+ /* PCI20341M */
+ 
+-static int pci20341_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int pci20341_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+ static const int pci20341_timebase[] = { 0x00, 0x00, 0x00, 0x04 };
+ static const int pci20341_settling_time[] = { 0x58, 0x58, 0x93, 0x99 };
+@@ -368,7 +368,7 @@ static const struct comedi_lrange *const pci20341_ranges[] = {
+ 	&range_bipolar0_025,
+ };
+ 
+-static int pci20341_init(struct comedi_device * dev, struct comedi_subdevice * s,
++static int pci20341_init(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	int opt0, int opt1)
+ {
+ 	union pci20xxx_subdev_private *sdp = s->private;
+@@ -399,8 +399,8 @@ static int pci20341_init(struct comedi_device * dev, struct comedi_subdevice * s
+ 	return 0;
+ }
+ 
+-static int pci20341_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci20341_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+         union pci20xxx_subdev_private *sdp = s->private;
+ 	unsigned int i = 0, j = 0;
+@@ -445,14 +445,14 @@ static int pci20341_insn_read(struct comedi_device * dev, struct comedi_subdevic
+ 
+ /* native DIO */
+ 
+-static void pci20xxx_dio_config(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int pci20xxx_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int pci20xxx_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static void pci20xxx_dio_config(struct comedi_device *dev, struct comedi_subdevice *s);
++static int pci20xxx_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int pci20xxx_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+ /* initialize struct pci20xxx_private */
+-static int pci20xxx_dio_init(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pci20xxx_dio_init(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 
+ 	s->type = COMEDI_SUBD_DIO;
+@@ -471,8 +471,8 @@ static int pci20xxx_dio_init(struct comedi_device * dev, struct comedi_subdevice
+ 	return 0;
+ }
+ 
+-static int pci20xxx_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci20xxx_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int mask, bits;
+ 
+@@ -496,8 +496,8 @@ static int pci20xxx_dio_insn_config(struct comedi_device * dev, struct comedi_su
+ 	return 1;
+ }
+ 
+-static int pci20xxx_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pci20xxx_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int mask = data[0];
+ 
+@@ -526,7 +526,7 @@ static int pci20xxx_dio_insn_bits(struct comedi_device * dev, struct comedi_subd
+ 	return 2;
+ }
+ 
+-static void pci20xxx_dio_config(struct comedi_device * dev, struct comedi_subdevice * s)
++static void pci20xxx_dio_config(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	unsigned char control_01;
+ 	unsigned char control_23;
+@@ -582,7 +582,7 @@ static void pci20xxx_dio_config(struct comedi_device * dev, struct comedi_subdev
+ }
+ 
+ #if 0
+-static void pci20xxx_do(struct comedi_device * dev, struct comedi_subdevice * s)
++static void pci20xxx_do(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	/* XXX if the channel is configured for input, does this
+ 	   do bad things? */
+@@ -595,7 +595,7 @@ static void pci20xxx_do(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	writeb((s->state >> 24) & 0xff, devpriv->ioaddr + PCI20000_DIO_3);
+ }
+ 
+-static unsigned int pci20xxx_di(struct comedi_device * dev, struct comedi_subdevice * s)
++static unsigned int pci20xxx_di(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	/* XXX same note as above */
+ 	unsigned int bits;
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
+index c360492159b2..8a9433472310 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -54,8 +54,8 @@ Devices: [JR3] PCI force sensor board (jr3_pci)
+ #define PCI_DEVICE_ID_JR3_3_CHANNEL 0x3113
+ #define PCI_DEVICE_ID_JR3_4_CHANNEL 0x3114
+ 
+-static int jr3_pci_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int jr3_pci_detach(struct comedi_device * dev);
++static int jr3_pci_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int jr3_pci_detach(struct comedi_device *dev);
+ 
+ static struct comedi_driver driver_jr3_pci = {
+       driver_name:"jr3_pci",
+@@ -259,8 +259,8 @@ static struct six_axis_t get_max_full_scales(volatile struct jr3_channel *channe
+ 	return result;
+ }
+ 
+-static int jr3_pci_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int jr3_pci_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int result;
+ 	struct jr3_pci_subdev_private *p;
+@@ -375,7 +375,7 @@ static int jr3_pci_ai_insn_read(struct comedi_device * dev, struct comedi_subdev
+ 	return result;
+ }
+ 
+-static void jr3_pci_open(struct comedi_device * dev)
++static void jr3_pci_open(struct comedi_device *dev)
+ {
+ 	int i;
+ 	struct jr3_pci_dev_private *devpriv = dev->private;
+@@ -392,7 +392,7 @@ static void jr3_pci_open(struct comedi_device * dev)
+ 	}
+ }
+ 
+-int read_idm_word(const u8 * data, size_t size, int *pos, unsigned int *val)
++int read_idm_word(const u8 *data, size_t size, int *pos, unsigned int *val)
+ {
+ 	int result = 0;
+ 	if (pos != 0 && val != 0) {
+@@ -414,7 +414,7 @@ int read_idm_word(const u8 * data, size_t size, int *pos, unsigned int *val)
+ 	return result;
+ }
+ 
+-static int jr3_download_firmware(struct comedi_device * dev, const u8 * data,
++static int jr3_download_firmware(struct comedi_device *dev, const u8 *data,
+ 	size_t size)
+ {
+ 	/*
+@@ -513,7 +513,7 @@ static int jr3_download_firmware(struct comedi_device * dev, const u8 * data,
+ 	return result;
+ }
+ 
+-static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice * s)
++static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice *s)
+ {
+ 	struct poll_delay_t result = poll_delay_min_max(1000, 2000);
+ 	struct jr3_pci_subdev_private *p = s->private;
+@@ -763,7 +763,7 @@ static void jr3_pci_poll_dev(unsigned long data)
+ 	add_timer(&devpriv->timer);
+ }
+ 
+-static int jr3_pci_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int jr3_pci_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int result = 0;
+ 	struct pci_dev *card = NULL;
+@@ -938,7 +938,7 @@ static int jr3_pci_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	return result;
+ }
+ 
+-static int jr3_pci_detach(struct comedi_device * dev)
++static int jr3_pci_detach(struct comedi_device *dev)
+ {
+ 	int i;
+ 	struct jr3_pci_dev_private *devpriv = dev->private;
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.h b/drivers/staging/comedi/drivers/jr3_pci.h
+index 3585f2941bca..4f4bfb24c6d6 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.h
++++ b/drivers/staging/comedi/drivers/jr3_pci.h
+@@ -2,22 +2,22 @@
+  * is 16 bits, but aligned on a 32 bit PCI boundary
+  */
+ 
+-static inline u16 get_u16(volatile const u32 * p)
++static inline u16 get_u16(volatile const u32 *p)
+ {
+ 	return (u16) readl(p);
+ }
+ 
+-static inline void set_u16(volatile u32 * p, u16 val)
++static inline void set_u16(volatile u32 *p, u16 val)
+ {
+ 	writel(val, p);
+ }
+ 
+-static inline s16 get_s16(volatile const s32 * p)
++static inline s16 get_s16(volatile const s32 *p)
+ {
+ 	return (s16) readl(p);
+ }
+ 
+-static inline void set_s16(volatile s32 * p, s16 val)
++static inline void set_s16(volatile s32 *p, s16 val)
+ {
+ 	writel(val, p);
+ }
+diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c
+index e72845767068..cff8ea71e28d 100644
+--- a/drivers/staging/comedi/drivers/ke_counter.c
++++ b/drivers/staging/comedi/drivers/ke_counter.c
+@@ -48,8 +48,8 @@ Kolter Electronic PCI Counter Card.
+ 
+ /*-- function prototypes ----------------------------------------------------*/
+ 
+-static int cnt_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int cnt_detach(struct comedi_device * dev);
++static int cnt_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int cnt_detach(struct comedi_device *dev);
+ 
+ static DEFINE_PCI_DEVICE_TABLE(cnt_pci_table) = {
+ 	{PCI_VENDOR_ID_KOLTER, CNT_CARD_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+@@ -103,8 +103,8 @@ COMEDI_PCI_INITCLEANUP(cnt_driver, cnt_pci_table);
+ 
+ /* This should be used only for resetting the counters; maybe it is better
+    to make a special command 'reset'. */
+-static int cnt_winsn(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++static int cnt_winsn(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+@@ -123,8 +123,8 @@ static int cnt_winsn(struct comedi_device * dev,
+ 
+ /*-- counter read -----------------------------------------------------------*/
+ 
+-static int cnt_rinsn(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++static int cnt_rinsn(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned char a0, a1, a2, a3, a4;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -148,7 +148,7 @@ static int cnt_rinsn(struct comedi_device * dev,
+ 
+ /*-- attach -----------------------------------------------------------------*/
+ 
+-static int cnt_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int cnt_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *subdevice;
+ 	struct pci_dev *pci_device;
+@@ -241,7 +241,7 @@ static int cnt_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ 
+ /*-- detach -----------------------------------------------------------------*/
+ 
+-static int cnt_detach(struct comedi_device * dev)
++static int cnt_detach(struct comedi_device *dev)
+ {
+ 	if (devpriv && devpriv->pcidev) {
+ 		if (dev->iobase) {
+diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c
+index c3fb504feb1e..bd7cb4406e14 100644
+--- a/drivers/staging/comedi/drivers/mpc624.c
++++ b/drivers/staging/comedi/drivers/mpc624.c
+@@ -146,8 +146,8 @@ static const struct comedi_lrange range_mpc624_bipolar10 = {
+ };
+ 
+ /* ---------------------------------------------------------------------------- */
+-static int mpc624_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int mpc624_detach(struct comedi_device * dev);
++static int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int mpc624_detach(struct comedi_device *dev);
+ /* ---------------------------------------------------------------------------- */
+ static struct comedi_driver driver_mpc624 = {
+       driver_name:"mpc624",
+@@ -157,10 +157,10 @@ static struct comedi_driver driver_mpc624 = {
+ };
+ 
+ /* ---------------------------------------------------------------------------- */
+-static int mpc624_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int mpc624_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ /* ---------------------------------------------------------------------------- */
+-static int mpc624_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+@@ -257,7 +257,7 @@ static int mpc624_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	return 1;
+ }
+ 
+-static int mpc624_detach(struct comedi_device * dev)
++static int mpc624_detach(struct comedi_device *dev)
+ {
+ 	rt_printk("comedi%d: mpc624: remove\n", dev->minor);
+ 
+@@ -270,8 +270,8 @@ static int mpc624_detach(struct comedi_device * dev)
+ /* Timeout 200ms */
+ #define TIMEOUT 200
+ 
+-static int mpc624_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int mpc624_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, i;
+ 	unsigned long int data_in, data_out;
+diff --git a/drivers/staging/comedi/drivers/mpc8260cpm.c b/drivers/staging/comedi/drivers/mpc8260cpm.c
+index bac0a7bb9cbd..147108f72024 100644
+--- a/drivers/staging/comedi/drivers/mpc8260cpm.c
++++ b/drivers/staging/comedi/drivers/mpc8260cpm.c
+@@ -46,8 +46,8 @@ struct mpc8260cpm_private {
+ 
+ #define devpriv ((struct mpc8260cpm_private *)dev->private)
+ 
+-static int mpc8260cpm_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int mpc8260cpm_detach(struct comedi_device * dev);
++static int mpc8260cpm_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int mpc8260cpm_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_mpc8260cpm = {
+       driver_name:"mpc8260cpm",
+       module:THIS_MODULE,
+@@ -57,12 +57,12 @@ static struct comedi_driver driver_mpc8260cpm = {
+ 
+ COMEDI_INITCLEANUP(driver_mpc8260cpm);
+ 
+-static int mpc8260cpm_dio_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int mpc8260cpm_dio_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int mpc8260cpm_dio_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int mpc8260cpm_dio_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+-static int mpc8260cpm_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int mpc8260cpm_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int i;
+@@ -93,7 +93,7 @@ static int mpc8260cpm_attach(struct comedi_device * dev, struct comedi_devconfig
+ 	return 1;
+ }
+ 
+-static int mpc8260cpm_detach(struct comedi_device * dev)
++static int mpc8260cpm_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: mpc8260cpm: remove\n", dev->minor);
+ 
+@@ -114,8 +114,8 @@ static unsigned long *cpm_pdat(int port)
+ 	}
+ }
+ 
+-static int mpc8260cpm_dio_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int mpc8260cpm_dio_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	unsigned int d;
+@@ -157,8 +157,8 @@ static int mpc8260cpm_dio_config(struct comedi_device * dev, struct comedi_subde
+ 	return 1;
+ }
+ 
+-static int mpc8260cpm_dio_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int mpc8260cpm_dio_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int port;
+ 	unsigned long *p;
+diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c
+index 9e47574171de..5b155be0cf99 100644
+--- a/drivers/staging/comedi/drivers/multiq3.c
++++ b/drivers/staging/comedi/drivers/multiq3.c
+@@ -82,8 +82,8 @@ Devices: [Quanser Consulting] MultiQ-3 (multiq3)
+ 
+ #define MULTIQ3_TIMEOUT 30
+ 
+-static int multiq3_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int multiq3_detach(struct comedi_device * dev);
++static int multiq3_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int multiq3_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_multiq3 = {
+       driver_name:"multiq3",
+       module:THIS_MODULE,
+@@ -98,8 +98,8 @@ struct multiq3_private {
+ };
+ #define devpriv ((struct multiq3_private *)dev->private)
+ 
+-static int multiq3_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int multiq3_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, n;
+ 	int chan;
+@@ -134,8 +134,8 @@ static int multiq3_ai_insn_read(struct comedi_device * dev, struct comedi_subdev
+ 	return n;
+ }
+ 
+-static int multiq3_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int multiq3_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -147,8 +147,8 @@ static int multiq3_ao_insn_read(struct comedi_device * dev, struct comedi_subdev
+ 	return i;
+ }
+ 
+-static int multiq3_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int multiq3_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -165,8 +165,8 @@ static int multiq3_ao_insn_write(struct comedi_device * dev, struct comedi_subde
+ 	return i;
+ }
+ 
+-static int multiq3_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int multiq3_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -176,8 +176,8 @@ static int multiq3_di_insn_bits(struct comedi_device * dev, struct comedi_subdev
+ 	return 2;
+ }
+ 
+-static int multiq3_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int multiq3_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -191,8 +191,8 @@ static int multiq3_do_insn_bits(struct comedi_device * dev, struct comedi_subdev
+ 	return 2;
+ }
+ 
+-static int multiq3_encoder_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int multiq3_encoder_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -212,7 +212,7 @@ static int multiq3_encoder_insn_read(struct comedi_device * dev, struct comedi_s
+ 	return n;
+ }
+ 
+-static void encoder_reset(struct comedi_device * dev)
++static void encoder_reset(struct comedi_device *dev)
+ {
+ 	int chan;
+ 	for (chan = 0; chan < dev->subdevices[4].n_chan; chan++) {
+@@ -235,7 +235,7 @@ static void encoder_reset(struct comedi_device * dev)
+    options[2] - number of encoder chips installed
+  */
+ 
+-static int multiq3_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int multiq3_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int result = 0;
+ 	unsigned long iobase;
+@@ -318,7 +318,7 @@ static int multiq3_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	return 0;
+ }
+ 
+-static int multiq3_detach(struct comedi_device * dev)
++static int multiq3_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: multiq3: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
+index d7c7c0f6be8b..4f476ec2d2f5 100644
+--- a/drivers/staging/comedi/drivers/ni_6527.c
++++ b/drivers/staging/comedi/drivers/ni_6527.c
+@@ -75,8 +75,8 @@ Updated: Sat, 25 Jan 2003 13:24:40 -0800
+ #define Rising_Edge_Detection_Enable(x)		(0x018+(x))
+ #define Falling_Edge_Detection_Enable(x)	(0x020+(x))
+ 
+-static int ni6527_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int ni6527_detach(struct comedi_device * dev);
++static int ni6527_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int ni6527_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_ni6527 = {
+       driver_name:"ni6527",
+       module:THIS_MODULE,
+@@ -120,10 +120,10 @@ struct ni6527_private {
+ 
+ #define devpriv ((struct ni6527_private *)dev->private)
+ 
+-static int ni6527_find_device(struct comedi_device * dev, int bus, int slot);
++static int ni6527_find_device(struct comedi_device *dev, int bus, int slot);
+ 
+-static int ni6527_di_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni6527_di_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	unsigned int interval;
+@@ -170,8 +170,8 @@ static int ni6527_di_insn_config(struct comedi_device * dev, struct comedi_subde
+ 	return 2;
+ }
+ 
+-static int ni6527_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni6527_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -183,8 +183,8 @@ static int ni6527_di_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+ 	return 2;
+ }
+ 
+-static int ni6527_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni6527_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -233,8 +233,8 @@ static irqreturn_t ni6527_interrupt(int irq, void *d)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int ni6527_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int ni6527_intr_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -309,7 +309,7 @@ static int ni6527_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevi
+ 	return 0;
+ }
+ 
+-static int ni6527_intr_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int ni6527_intr_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	/* struct comedi_cmd *cmd = &s->async->cmd; */
+ 
+@@ -322,15 +322,15 @@ static int ni6527_intr_cmd(struct comedi_device * dev, struct comedi_subdevice *
+ 	return 0;
+ }
+ 
+-static int ni6527_intr_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int ni6527_intr_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	writeb(0x00, devpriv->mite->daq_io_addr + Master_Interrupt_Control);
+ 
+ 	return 0;
+ }
+ 
+-static int ni6527_intr_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni6527_intr_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n < 1)
+ 		return -EINVAL;
+@@ -339,8 +339,8 @@ static int ni6527_intr_insn_bits(struct comedi_device * dev, struct comedi_subde
+ 	return 2;
+ }
+ 
+-static int ni6527_intr_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni6527_intr_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n < 1)
+ 		return -EINVAL;
+@@ -364,7 +364,7 @@ static int ni6527_intr_insn_config(struct comedi_device * dev, struct comedi_sub
+ 	return 2;
+ }
+ 
+-static int ni6527_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int ni6527_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int ret;
+@@ -442,7 +442,7 @@ static int ni6527_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	return 0;
+ }
+ 
+-static int ni6527_detach(struct comedi_device * dev)
++static int ni6527_detach(struct comedi_device *dev)
+ {
+ 	if (devpriv && devpriv->mite && devpriv->mite->daq_io_addr) {
+ 		writeb(0x00,
+@@ -460,7 +460,7 @@ static int ni6527_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int ni6527_find_device(struct comedi_device * dev, int bus, int slot)
++static int ni6527_find_device(struct comedi_device *dev, int bus, int slot)
+ {
+ 	struct mite_struct *mite;
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
+index 60dfec593330..72005a40ad99 100644
+--- a/drivers/staging/comedi/drivers/ni_65xx.c
++++ b/drivers/staging/comedi/drivers/ni_65xx.c
+@@ -102,8 +102,8 @@ static inline unsigned Filter_Enable(unsigned port)
+ #define OverflowIntEnable		0x02
+ #define EdgeIntEnable			0x01
+ 
+-static int ni_65xx_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int ni_65xx_detach(struct comedi_device * dev);
++static int ni_65xx_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int ni_65xx_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_ni_65xx = {
+       driver_name:"ni_65xx",
+       module:THIS_MODULE,
+@@ -249,7 +249,7 @@ static inline unsigned ni_65xx_port_by_channel(unsigned channel)
+ {
+ 	return channel / ni_65xx_channels_per_port;
+ }
+-static inline unsigned ni_65xx_total_num_ports(const struct ni_65xx_board * board)
++static inline unsigned ni_65xx_total_num_ports(const struct ni_65xx_board *board)
+ {
+ 	return board->num_dio_ports + board->num_di_ports + board->num_do_ports;
+ }
+@@ -312,10 +312,10 @@ static struct ni_65xx_subdevice_private *ni_65xx_alloc_subdevice_private(void)
+ 	return subdev_private;
+ }
+ 
+-static int ni_65xx_find_device(struct comedi_device * dev, int bus, int slot);
++static int ni_65xx_find_device(struct comedi_device *dev, int bus, int slot);
+ 
+-static int ni_65xx_config_filter(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_65xx_config_filter(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	const unsigned chan = CR_CHAN(insn->chanspec);
+ 	const unsigned port =
+@@ -353,8 +353,8 @@ static int ni_65xx_config_filter(struct comedi_device * dev, struct comedi_subde
+ 	return 2;
+ }
+ 
+-static int ni_65xx_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_65xx_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned port;
+ 
+@@ -392,8 +392,8 @@ static int ni_65xx_dio_insn_config(struct comedi_device * dev, struct comedi_sub
+ 	return -EINVAL;
+ }
+ 
+-static int ni_65xx_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_65xx_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned base_bitfield_channel;
+ 	const unsigned max_ports_per_bitfield = 5;
+@@ -475,8 +475,8 @@ static irqreturn_t ni_65xx_interrupt(int irq, void *d)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int ni_65xx_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int ni_65xx_intr_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -551,7 +551,7 @@ static int ni_65xx_intr_cmdtest(struct comedi_device * dev, struct comedi_subdev
+ 	return 0;
+ }
+ 
+-static int ni_65xx_intr_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int ni_65xx_intr_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	/* struct comedi_cmd *cmd = &s->async->cmd; */
+ 
+@@ -564,7 +564,7 @@ static int ni_65xx_intr_cmd(struct comedi_device * dev, struct comedi_subdevice
+ 	return 0;
+ }
+ 
+-static int ni_65xx_intr_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int ni_65xx_intr_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	writeb(0x00,
+ 		private(dev)->mite->daq_io_addr + Master_Interrupt_Control);
+@@ -572,8 +572,8 @@ static int ni_65xx_intr_cancel(struct comedi_device * dev, struct comedi_subdevi
+ 	return 0;
+ }
+ 
+-static int ni_65xx_intr_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_65xx_intr_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n < 1)
+ 		return -EINVAL;
+@@ -582,8 +582,8 @@ static int ni_65xx_intr_insn_bits(struct comedi_device * dev, struct comedi_subd
+ 	return 2;
+ }
+ 
+-static int ni_65xx_intr_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_65xx_intr_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n < 1)
+ 		return -EINVAL;
+@@ -619,7 +619,7 @@ static int ni_65xx_intr_insn_config(struct comedi_device * dev, struct comedi_su
+ 	return 2;
+ }
+ 
+-static int ni_65xx_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int ni_65xx_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned i;
+@@ -752,7 +752,7 @@ static int ni_65xx_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	return 0;
+ }
+ 
+-static int ni_65xx_detach(struct comedi_device * dev)
++static int ni_65xx_detach(struct comedi_device *dev)
+ {
+ 	if (private(dev) && private(dev)->mite
+ 		&& private(dev)->mite->daq_io_addr) {
+@@ -780,7 +780,7 @@ static int ni_65xx_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int ni_65xx_find_device(struct comedi_device * dev, int bus, int slot)
++static int ni_65xx_find_device(struct comedi_device *dev, int bus, int slot)
+ {
+ 	struct mite_struct *mite;
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
+index 6b0fe5c4022e..d4a6cf3dde67 100644
+--- a/drivers/staging/comedi/drivers/ni_660x.c
++++ b/drivers/staging/comedi/drivers/ni_660x.c
+@@ -448,10 +448,10 @@ static inline const struct ni_660x_board *board(struct comedi_device * dev)
+ 
+ #define n_ni_660x_boards (sizeof(ni_660x_boards)/sizeof(ni_660x_boards[0]))
+ 
+-static int ni_660x_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int ni_660x_detach(struct comedi_device * dev);
+-static void init_tio_chip(struct comedi_device * dev, int chipset);
+-static void ni_660x_select_pfi_output(struct comedi_device * dev, unsigned pfi_channel,
++static int ni_660x_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int ni_660x_detach(struct comedi_device *dev);
++static void init_tio_chip(struct comedi_device *dev, int chipset);
++static void ni_660x_select_pfi_output(struct comedi_device *dev, unsigned pfi_channel,
+ 	unsigned output_select);
+ 
+ static struct comedi_driver driver_ni_660x = {
+@@ -463,25 +463,25 @@ static struct comedi_driver driver_ni_660x = {
+ 
+ COMEDI_PCI_INITCLEANUP(driver_ni_660x, ni_660x_pci_table);
+ 
+-static int ni_660x_find_device(struct comedi_device * dev, int bus, int slot);
+-static int ni_660x_set_pfi_routing(struct comedi_device * dev, unsigned chan,
++static int ni_660x_find_device(struct comedi_device *dev, int bus, int slot);
++static int ni_660x_set_pfi_routing(struct comedi_device *dev, unsigned chan,
+ 	unsigned source);
+ 
+ /* Possible instructions for a GPCT */
+-static int ni_660x_GPCT_rinsn(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
+-static int ni_660x_GPCT_insn_config(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
+-static int ni_660x_GPCT_winsn(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
++static int ni_660x_GPCT_rinsn(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
++static int ni_660x_GPCT_insn_config(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
++static int ni_660x_GPCT_winsn(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
+ 
+ /* Possible instructions for Digital IO */
+-static int ni_660x_dio_insn_config(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
+-static int ni_660x_dio_insn_bits(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
++static int ni_660x_dio_insn_config(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
++static int ni_660x_dio_insn_bits(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
+ 
+-static inline unsigned ni_660x_num_counters(struct comedi_device * dev)
++static inline unsigned ni_660x_num_counters(struct comedi_device *dev)
+ {
+ 	return board(dev)->n_chips * counters_per_chip;
+ }
+@@ -704,7 +704,7 @@ static enum NI_660x_Register ni_gpct_to_660x_register(enum ni_gpct_register reg)
+ 	return ni_660x_register;
+ }
+ 
+-static inline void ni_660x_write_register(struct comedi_device * dev,
++static inline void ni_660x_write_register(struct comedi_device *dev,
+ 	unsigned chip_index, unsigned bits, enum NI_660x_Register reg)
+ {
+ 	void *const write_address =
+@@ -726,7 +726,7 @@ static inline void ni_660x_write_register(struct comedi_device * dev,
+ 	}
+ }
+ 
+-static inline unsigned ni_660x_read_register(struct comedi_device * dev,
++static inline unsigned ni_660x_read_register(struct comedi_device *dev,
+ 	unsigned chip_index, enum NI_660x_Register reg)
+ {
+ 	void *const read_address =
+@@ -773,7 +773,7 @@ static inline struct mite_dma_descriptor_ring *mite_ring(struct ni_660x_private
+ 	return priv->mite_rings[counter->chip_index][counter->counter_index];
+ }
+ 
+-static inline void ni_660x_set_dma_channel(struct comedi_device * dev,
++static inline void ni_660x_set_dma_channel(struct comedi_device *dev,
+ 	unsigned mite_channel, struct ni_gpct *counter)
+ {
+ 	unsigned long flags;
+@@ -791,7 +791,7 @@ static inline void ni_660x_set_dma_channel(struct comedi_device * dev,
+ 	comedi_spin_unlock_irqrestore(&private(dev)->soft_reg_copy_lock, flags);
+ }
+ 
+-static inline void ni_660x_unset_dma_channel(struct comedi_device * dev,
++static inline void ni_660x_unset_dma_channel(struct comedi_device *dev,
+ 	unsigned mite_channel, struct ni_gpct *counter)
+ {
+ 	unsigned long flags;
+@@ -807,7 +807,7 @@ static inline void ni_660x_unset_dma_channel(struct comedi_device * dev,
+ 	comedi_spin_unlock_irqrestore(&private(dev)->soft_reg_copy_lock, flags);
+ }
+ 
+-static int ni_660x_request_mite_channel(struct comedi_device * dev,
++static int ni_660x_request_mite_channel(struct comedi_device *dev,
+ 	struct ni_gpct *counter, enum comedi_io_direction direction)
+ {
+ 	unsigned long flags;
+@@ -832,7 +832,7 @@ static int ni_660x_request_mite_channel(struct comedi_device * dev,
+ 	return 0;
+ }
+ 
+-void ni_660x_release_mite_channel(struct comedi_device * dev, struct ni_gpct *counter)
++void ni_660x_release_mite_channel(struct comedi_device *dev, struct ni_gpct *counter)
+ {
+ 	unsigned long flags;
+ 
+@@ -847,7 +847,7 @@ void ni_660x_release_mite_channel(struct comedi_device * dev, struct ni_gpct *co
+ 	comedi_spin_unlock_irqrestore(&private(dev)->mite_channel_lock, flags);
+ }
+ 
+-static int ni_660x_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int ni_660x_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	int retval;
+ 
+@@ -866,15 +866,15 @@ static int ni_660x_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	return retval;
+ }
+ 
+-static int ni_660x_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int ni_660x_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	struct ni_gpct *counter = subdev_to_counter(s);
+ 
+ 	return ni_tio_cmdtest(counter, cmd);
+ }
+ 
+-static int ni_660x_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int ni_660x_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct ni_gpct *counter = subdev_to_counter(s);
+ 	int retval;
+@@ -884,7 +884,7 @@ static int ni_660x_cancel(struct comedi_device * dev, struct comedi_subdevice *
+ 	return retval;
+ }
+ 
+-static void set_tio_counterswap(struct comedi_device * dev, int chipset)
++static void set_tio_counterswap(struct comedi_device *dev, int chipset)
+ {
+ 	/* See P. 3.5 of the Register-Level Programming manual.  The
+ 	   CounterSwap bit has to be set on the second chip, otherwise
+@@ -897,8 +897,8 @@ static void set_tio_counterswap(struct comedi_device * dev, int chipset)
+ 		ni_660x_write_register(dev, chipset, 0, ClockConfigRegister);
+ }
+ 
+-static void ni_660x_handle_gpct_interrupt(struct comedi_device * dev,
+-	struct comedi_subdevice * s)
++static void ni_660x_handle_gpct_interrupt(struct comedi_device *dev,
++	struct comedi_subdevice *s)
+ {
+ 	ni_tio_handle_interrupt(subdev_to_counter(s), s);
+ 	if (s->async->events) {
+@@ -942,7 +942,7 @@ static int ni_660x_input_poll(struct comedi_device *dev,
+ 	return comedi_buf_read_n_available(s->async);
+ }
+ 
+-static int ni_660x_buf_change(struct comedi_device * dev, struct comedi_subdevice * s,
++static int ni_660x_buf_change(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned long new_size)
+ {
+ 	int ret;
+@@ -955,7 +955,7 @@ static int ni_660x_buf_change(struct comedi_device * dev, struct comedi_subdevic
+ 	return 0;
+ }
+ 
+-static int ni_660x_allocate_private(struct comedi_device * dev)
++static int ni_660x_allocate_private(struct comedi_device *dev)
+ {
+ 	int retval;
+ 	unsigned i;
+@@ -971,7 +971,7 @@ static int ni_660x_allocate_private(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int ni_660x_alloc_mite_rings(struct comedi_device * dev)
++static int ni_660x_alloc_mite_rings(struct comedi_device *dev)
+ {
+ 	unsigned i;
+ 	unsigned j;
+@@ -988,7 +988,7 @@ static int ni_660x_alloc_mite_rings(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static void ni_660x_free_mite_rings(struct comedi_device * dev)
++static void ni_660x_free_mite_rings(struct comedi_device *dev)
+ {
+ 	unsigned i;
+ 	unsigned j;
+@@ -1000,7 +1000,7 @@ static void ni_660x_free_mite_rings(struct comedi_device * dev)
+ 	}
+ }
+ 
+-static int ni_660x_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int ni_660x_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int ret;
+@@ -1121,7 +1121,7 @@ static int ni_660x_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	return 0;
+ }
+ 
+-static int ni_660x_detach(struct comedi_device * dev)
++static int ni_660x_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: ni_660x: remove\n", dev->minor);
+ 
+@@ -1141,13 +1141,13 @@ static int ni_660x_detach(struct comedi_device * dev)
+ }
+ 
+ static int
+-ni_660x_GPCT_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++ni_660x_GPCT_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	return ni_tio_rinsn(subdev_to_counter(s), insn, data);
+ }
+ 
+-static void init_tio_chip(struct comedi_device * dev, int chipset)
++static void init_tio_chip(struct comedi_device *dev, int chipset)
+ {
+ 	unsigned i;
+ 
+@@ -1168,19 +1168,19 @@ static void init_tio_chip(struct comedi_device * dev, int chipset)
+ }
+ 
+ static int
+-ni_660x_GPCT_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++ni_660x_GPCT_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	return ni_tio_insn_config(subdev_to_counter(s), insn, data);
+ }
+ 
+-static int ni_660x_GPCT_winsn(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++static int ni_660x_GPCT_winsn(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	return ni_tio_winsn(subdev_to_counter(s), insn, data);
+ }
+ 
+-static int ni_660x_find_device(struct comedi_device * dev, int bus, int slot)
++static int ni_660x_find_device(struct comedi_device *dev, int bus, int slot)
+ {
+ 	struct mite_struct *mite;
+ 	int i;
+@@ -1207,8 +1207,8 @@ static int ni_660x_find_device(struct comedi_device * dev, int bus, int slot)
+ 	return -EIO;
+ }
+ 
+-static int ni_660x_dio_insn_bits(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++static int ni_660x_dio_insn_bits(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned base_bitfield_channel = CR_CHAN(insn->chanspec);
+ 
+@@ -1227,7 +1227,7 @@ static int ni_660x_dio_insn_bits(struct comedi_device * dev,
+ 	return 2;
+ }
+ 
+-static void ni_660x_select_pfi_output(struct comedi_device * dev, unsigned pfi_channel,
++static void ni_660x_select_pfi_output(struct comedi_device *dev, unsigned pfi_channel,
+ 	unsigned output_select)
+ {
+ 	static const unsigned counter_4_7_first_pfi = 8;
+@@ -1262,7 +1262,7 @@ static void ni_660x_select_pfi_output(struct comedi_device * dev, unsigned pfi_c
+ 	ni_660x_write_register(dev, active_chipset, active_bits, IOConfigReg(pfi_channel));
+ }
+ 
+-static int ni_660x_set_pfi_routing(struct comedi_device * dev, unsigned chan,
++static int ni_660x_set_pfi_routing(struct comedi_device *dev, unsigned chan,
+ 	unsigned source)
+ {
+ 	if (source > num_pfi_output_selects)
+@@ -1285,13 +1285,13 @@ static int ni_660x_set_pfi_routing(struct comedi_device * dev, unsigned chan,
+ 	return 0;
+ }
+ 
+-static unsigned ni_660x_get_pfi_routing(struct comedi_device * dev, unsigned chan)
++static unsigned ni_660x_get_pfi_routing(struct comedi_device *dev, unsigned chan)
+ {
+ 	BUG_ON(chan >= NUM_PFI_CHANNELS);
+ 	return private(dev)->pfi_output_selects[chan];
+ }
+ 
+-static void ni660x_config_filter(struct comedi_device * dev, unsigned pfi_channel,
++static void ni660x_config_filter(struct comedi_device *dev, unsigned pfi_channel,
+ 	enum ni_gpct_filter_select filter)
+ {
+ 	unsigned bits = ni_660x_read_register(dev, 0, IOConfigReg(pfi_channel));
+@@ -1300,8 +1300,8 @@ static void ni660x_config_filter(struct comedi_device * dev, unsigned pfi_channe
+ 	ni_660x_write_register(dev, 0, bits, IOConfigReg(pfi_channel));
+ }
+ 
+-static int ni_660x_dio_insn_config(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++static int ni_660x_dio_insn_config(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
+index 05dcc5ba255c..c00bd0d40458 100644
+--- a/drivers/staging/comedi/drivers/ni_670x.c
++++ b/drivers/staging/comedi/drivers/ni_670x.c
+@@ -111,8 +111,8 @@ struct ni_670x_private {
+ #define devpriv ((struct ni_670x_private *)dev->private)
+ #define n_ni_670x_boards (sizeof(ni_670x_boards)/sizeof(ni_670x_boards[0]))
+ 
+-static int ni_670x_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int ni_670x_detach(struct comedi_device * dev);
++static int ni_670x_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int ni_670x_detach(struct comedi_device *dev);
+ 
+ static struct comedi_driver driver_ni_670x = {
+       driver_name:"ni_670x",
+@@ -125,18 +125,18 @@ COMEDI_PCI_INITCLEANUP(driver_ni_670x, ni_670x_pci_table);
+ 
+ static struct comedi_lrange range_0_20mA = { 1, {RANGE_mA(0, 20)} };
+ 
+-static int ni_670x_find_device(struct comedi_device * dev, int bus, int slot);
++static int ni_670x_find_device(struct comedi_device *dev, int bus, int slot);
+ 
+-static int ni_670x_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int ni_670x_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int ni_670x_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int ni_670x_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int ni_670x_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int ni_670x_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int ni_670x_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int ni_670x_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+-static int ni_670x_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int ni_670x_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int ret;
+@@ -205,7 +205,7 @@ static int ni_670x_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	return 1;
+ }
+ 
+-static int ni_670x_detach(struct comedi_device * dev)
++static int ni_670x_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: ni_670x: remove\n", dev->minor);
+ 
+@@ -221,8 +221,8 @@ static int ni_670x_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int ni_670x_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_670x_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -247,8 +247,8 @@ static int ni_670x_ao_winsn(struct comedi_device * dev, struct comedi_subdevice
+ 	return i;
+ }
+ 
+-static int ni_670x_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_670x_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -259,8 +259,8 @@ static int ni_670x_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice
+ 	return i;
+ }
+ 
+-static int ni_670x_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_670x_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -281,8 +281,8 @@ static int ni_670x_dio_insn_bits(struct comedi_device * dev, struct comedi_subde
+ 	return 2;
+ }
+ 
+-static int ni_670x_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_670x_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+@@ -308,7 +308,7 @@ static int ni_670x_dio_insn_config(struct comedi_device * dev, struct comedi_sub
+ 	return insn->n;
+ }
+ 
+-static int ni_670x_find_device(struct comedi_device * dev, int bus, int slot)
++static int ni_670x_find_device(struct comedi_device *dev, int bus, int slot)
+ {
+ 	struct mite_struct *mite;
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
+index 8b73a793ad0f..62754d5372ae 100644
+--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
++++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
+@@ -169,9 +169,9 @@ struct a2150_private {
+ 
+ #define devpriv ((struct a2150_private *)dev->private)
+ 
+-static int a2150_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int a2150_detach(struct comedi_device * dev);
+-static int a2150_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
++static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int a2150_detach(struct comedi_device *dev);
++static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
+ 
+ static struct comedi_driver driver_a2150 = {
+       driver_name:"ni_at_a2150",
+@@ -199,7 +199,7 @@ COMEDI_INITCLEANUP(driver_a2150);
+ 
+ #ifdef A2150_DEBUG
+ 
+-static void ni_dump_regs(struct comedi_device * dev)
++static void ni_dump_regs(struct comedi_device *dev)
+ {
+ 	rt_printk("config bits 0x%x\n", devpriv->config_bits);
+ 	rt_printk("irq dma bits 0x%x\n", devpriv->irq_dma_bits);
+@@ -318,13 +318,13 @@ static irqreturn_t a2150_interrupt(int irq, void *d)
+ }
+ 
+ /* probes board type, returns offset */
+-static int a2150_probe(struct comedi_device * dev)
++static int a2150_probe(struct comedi_device *dev)
+ {
+ 	int status = inw(dev->iobase + STATUS_REG);
+ 	return ID_BITS(status);
+ }
+ 
+-static int a2150_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase = it->options[0];
+@@ -449,7 +449,7 @@ static int a2150_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 	return 0;
+ };
+ 
+-static int a2150_detach(struct comedi_device * dev)
++static int a2150_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: %s: remove\n", dev->minor, driver_a2150.driver_name);
+ 
+@@ -472,7 +472,7 @@ static int a2150_detach(struct comedi_device * dev)
+ 	return 0;
+ };
+ 
+-static int a2150_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	/*  disable dma on card */
+ 	devpriv->irq_dma_bits &= ~DMA_INTR_EN_BIT & ~DMA_EN_BIT;
+@@ -487,8 +487,8 @@ static int a2150_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int a2150_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int a2150_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -617,7 +617,7 @@ static int a2150_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice
+ 	return 0;
+ }
+ 
+-static int a2150_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct comedi_async *async = s->async;
+ 	struct comedi_cmd *cmd = &async->cmd;
+@@ -728,8 +728,8 @@ static int a2150_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int a2150_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int i, n;
+ 	static const int timeout = 100000;
+@@ -802,7 +802,7 @@ static int a2150_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ 
+ /* sets bits in devpriv->clock_bits to nearest approximation of requested period,
+  * adjusts requested period to actual timing. */
+-static int a2150_get_timing(struct comedi_device * dev, unsigned int *period,
++static int a2150_get_timing(struct comedi_device *dev, unsigned int *period,
+ 	int flags)
+ {
+ 	int lub, glb, temp;
+@@ -876,7 +876,7 @@ static int a2150_get_timing(struct comedi_device * dev, unsigned int *period,
+ 	return 0;
+ }
+ 
+-static int a2150_set_chanlist(struct comedi_device * dev, unsigned int start_channel,
++static int a2150_set_chanlist(struct comedi_device *dev, unsigned int start_channel,
+ 	unsigned int num_channels)
+ {
+ 	if (start_channel + num_channels > 4)
+diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c
+index 089fb428b411..282457ccefb3 100644
+--- a/drivers/staging/comedi/drivers/ni_at_ao.c
++++ b/drivers/staging/comedi/drivers/ni_at_ao.c
+@@ -181,8 +181,8 @@ struct atao_private {
+ 
+ #define devpriv ((struct atao_private *)dev->private)
+ 
+-static int atao_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int atao_detach(struct comedi_device * dev);
++static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int atao_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_atao = {
+       driver_name:"ni_at_ao",
+       module:THIS_MODULE,
+@@ -195,22 +195,22 @@ static struct comedi_driver driver_atao = {
+ 
+ COMEDI_INITCLEANUP(driver_atao);
+ 
+-static void atao_reset(struct comedi_device * dev);
+-
+-static int atao_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int atao_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int atao_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int atao_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int atao_calib_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int atao_calib_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-
+-static int atao_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static void atao_reset(struct comedi_device *dev);
++
++static int atao_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int atao_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int atao_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int atao_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int atao_calib_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int atao_calib_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++
++static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+@@ -283,7 +283,7 @@ static int atao_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int atao_detach(struct comedi_device * dev)
++static int atao_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: atao: remove\n", dev->minor);
+ 
+@@ -293,7 +293,7 @@ static int atao_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static void atao_reset(struct comedi_device * dev)
++static void atao_reset(struct comedi_device *dev)
+ {
+ 	/* This is the reset sequence described in the manual */
+ 
+@@ -323,8 +323,8 @@ static void atao_reset(struct comedi_device * dev)
+ 	outw(devpriv->cfg1, dev->iobase + ATAO_CFG1);
+ }
+ 
+-static int atao_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int atao_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -347,8 +347,8 @@ static int atao_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s
+ 	return i;
+ }
+ 
+-static int atao_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int atao_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -359,8 +359,8 @@ static int atao_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s
+ 	return i;
+ }
+ 
+-static int atao_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int atao_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -376,8 +376,8 @@ static int atao_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevic
+ 	return 2;
+ }
+ 
+-static int atao_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int atao_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	unsigned int mask, bit;
+@@ -421,8 +421,8 @@ static int atao_dio_insn_config(struct comedi_device * dev, struct comedi_subdev
+  * DACs.  It is not explicitly stated in the manual how to access
+  * the caldacs, but we can guess.
+  */
+-static int atao_calib_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int atao_calib_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	for (i = 0; i < insn->n; i++) {
+@@ -431,8 +431,8 @@ static int atao_calib_insn_read(struct comedi_device * dev, struct comedi_subdev
+ 	return insn->n;
+ }
+ 
+-static int atao_calib_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int atao_calib_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int bitstring, bit;
+ 	unsigned int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c
+index dcd44874aaf3..8de904832dc5 100644
+--- a/drivers/staging/comedi/drivers/ni_atmio.c
++++ b/drivers/staging/comedi/drivers/ni_atmio.c
+@@ -297,7 +297,7 @@ struct ni_private {
+  * read/written directly in the I/O space of the board.  The
+  * AT-MIO devices map the low 8 STC registers to iobase+addr*2. */
+ 
+-static void ni_atmio_win_out(struct comedi_device * dev, uint16_t data, int addr)
++static void ni_atmio_win_out(struct comedi_device *dev, uint16_t data, int addr)
+ {
+ 	unsigned long flags;
+ 
+@@ -311,7 +311,7 @@ static void ni_atmio_win_out(struct comedi_device * dev, uint16_t data, int addr
+ 	comedi_spin_unlock_irqrestore(&devpriv->window_lock, flags);
+ }
+ 
+-static uint16_t ni_atmio_win_in(struct comedi_device * dev, int addr)
++static uint16_t ni_atmio_win_in(struct comedi_device *dev, int addr)
+ {
+ 	unsigned long flags;
+ 	uint16_t ret;
+@@ -339,8 +339,8 @@ static struct pnp_device_id device_ids[] = {
+ 
+ MODULE_DEVICE_TABLE(pnp, device_ids);
+ 
+-static int ni_atmio_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int ni_atmio_detach(struct comedi_device * dev);
++static int ni_atmio_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int ni_atmio_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_atmio = {
+       driver_name:"ni_atmio",
+       module:THIS_MODULE,
+@@ -352,10 +352,10 @@ COMEDI_INITCLEANUP(driver_atmio);
+ 
+ #include "ni_mio_common.c"
+ 
+-static int ni_getboardtype(struct comedi_device * dev);
++static int ni_getboardtype(struct comedi_device *dev);
+ 
+ /* clean up allocated resources */
+-static int ni_atmio_detach(struct comedi_device * dev)
++static int ni_atmio_detach(struct comedi_device *dev)
+ {
+ 	mio_common_detach(dev);
+ 
+@@ -405,7 +405,7 @@ static int ni_isapnp_find_board(struct pnp_dev **dev)
+ 	return 0;
+ }
+ 
+-static int ni_atmio_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int ni_atmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct pnp_dev *isapnp_dev;
+ 	int ret;
+@@ -493,7 +493,7 @@ static int ni_atmio_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	return 0;
+ }
+ 
+-static int ni_getboardtype(struct comedi_device * dev)
++static int ni_getboardtype(struct comedi_device *dev)
+ {
+ 	int device_id = ni_read_eeprom(dev, 511);
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
+index 44b67ec86c3a..442bfe717a13 100644
+--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
++++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
+@@ -187,7 +187,7 @@ struct atmio16d_private {
+ 	unsigned int com_reg_2_state;	/* current state of command register 2 */
+ };
+ 
+-static void reset_counters(struct comedi_device * dev)
++static void reset_counters(struct comedi_device *dev)
+ {
+ 	/* Counter 2 */
+ 	outw(0xFFC2, dev->iobase + AM9513A_COM_REG);
+@@ -225,7 +225,7 @@ static void reset_counters(struct comedi_device * dev)
+ 	outw(0, dev->iobase + AD_CLEAR_REG);
+ }
+ 
+-static void reset_atmio16d(struct comedi_device * dev)
++static void reset_atmio16d(struct comedi_device *dev)
+ {
+ 	int i;
+ 
+@@ -270,8 +270,8 @@ static irqreturn_t atmio16d_interrupt(int irq, void *d)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int atmio16d_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int atmio16d_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0, tmp;
+ #ifdef DEBUG1
+@@ -371,7 +371,7 @@ static int atmio16d_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevi
+ 	return 0;
+ }
+ 
+-static int atmio16d_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int atmio16d_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned int timer, base_clock;
+@@ -519,7 +519,7 @@ static int atmio16d_ai_cmd(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ /* This will cancel a running acquisition operation */
+-static int atmio16d_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int atmio16d_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	reset_atmio16d(dev);
+ 
+@@ -527,8 +527,8 @@ static int atmio16d_ai_cancel(struct comedi_device * dev, struct comedi_subdevic
+ }
+ 
+ /* Mode 0 is used to get a single conversion on demand */
+-static int atmio16d_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int atmio16d_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, t;
+ 	int chan;
+@@ -586,8 +586,8 @@ static int atmio16d_ai_insn_read(struct comedi_device * dev, struct comedi_subde
+ 	return i;
+ }
+ 
+-static int atmio16d_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int atmio16d_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ #ifdef DEBUG1
+@@ -601,8 +601,8 @@ static int atmio16d_ao_insn_read(struct comedi_device * dev, struct comedi_subde
+ 	return i;
+ }
+ 
+-static int atmio16d_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int atmio16d_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan;
+@@ -636,8 +636,8 @@ static int atmio16d_ao_insn_write(struct comedi_device * dev, struct comedi_subd
+ 	return i;
+ }
+ 
+-static int atmio16d_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int atmio16d_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -652,8 +652,8 @@ static int atmio16d_dio_insn_bits(struct comedi_device * dev, struct comedi_subd
+ 	return 2;
+ }
+ 
+-static int atmio16d_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int atmio16d_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int mask;
+@@ -706,7 +706,7 @@ static int atmio16d_dio_insn_config(struct comedi_device * dev, struct comedi_su
+    options[12] - dac1 coding
+  */
+ 
+-static int atmio16d_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int atmio16d_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	unsigned int irq;
+ 	unsigned long iobase;
+@@ -841,7 +841,7 @@ static int atmio16d_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	return 0;
+ }
+ 
+-static int atmio16d_detach(struct comedi_device * dev)
++static int atmio16d_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: atmio16d: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
+index cbefda8e9de4..21c71c9b3007 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_700.c
++++ b/drivers/staging/comedi/drivers/ni_daq_700.c
+@@ -55,8 +55,8 @@ static struct pcmcia_device *pcmcia_cur_dev = NULL;
+ 
+ #define DIO700_SIZE 8		/*  size of io region used by board */
+ 
+-static int dio700_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int dio700_detach(struct comedi_device * dev);
++static int dio700_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int dio700_detach(struct comedi_device *dev);
+ 
+ enum dio700_bustype { pcmcia_bustype };
+ 
+@@ -128,9 +128,9 @@ struct subdev_700_struct {
+ #define CALLBACK_FUNC	(((struct subdev_700_struct *)s->private)->cb_func)
+ #define subdevpriv	((struct subdev_700_struct *)s->private)
+ 
+-static void do_config(struct comedi_device * dev, struct comedi_subdevice * s);
++static void do_config(struct comedi_device *dev, struct comedi_subdevice *s);
+ 
+-void subdev_700_interrupt(struct comedi_device * dev, struct comedi_subdevice * s)
++void subdev_700_interrupt(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	short d;
+ 
+@@ -155,8 +155,8 @@ static int subdev_700_cb(int dir, int port, int data, unsigned long arg)
+ 	}
+ }
+ 
+-static int subdev_700_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int subdev_700_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (data[0]) {
+ 		s->state &= ~data[0];
+@@ -173,8 +173,8 @@ static int subdev_700_insn(struct comedi_device * dev, struct comedi_subdevice *
+ 	return 2;
+ }
+ 
+-static int subdev_700_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int subdev_700_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	switch (data[0]) {
+@@ -196,13 +196,13 @@ static int subdev_700_insn_config(struct comedi_device * dev, struct comedi_subd
+ 	return 1;
+ }
+ 
+-static void do_config(struct comedi_device * dev, struct comedi_subdevice * s)
++static void do_config(struct comedi_device *dev, struct comedi_subdevice *s)
+ {				/* use powerup defaults */
+ 	return;
+ }
+ 
+-static int subdev_700_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int subdev_700_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	unsigned int tmp;
+@@ -276,21 +276,21 @@ static int subdev_700_cmdtest(struct comedi_device * dev, struct comedi_subdevic
+ 	return 0;
+ }
+ 
+-static int subdev_700_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int subdev_700_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	/* FIXME */
+ 
+ 	return 0;
+ }
+ 
+-static int subdev_700_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int subdev_700_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	/* FIXME */
+ 
+ 	return 0;
+ }
+ 
+-int subdev_700_init(struct comedi_device * dev, struct comedi_subdevice * s, int (*cb) (int,
++int subdev_700_init(struct comedi_device *dev, struct comedi_subdevice *s, int (*cb) (int,
+ 		int, int, unsigned long), unsigned long arg)
+ {
+ 	s->type = COMEDI_SUBD_DIO;
+@@ -319,7 +319,7 @@ int subdev_700_init(struct comedi_device * dev, struct comedi_subdevice * s, int
+ 	return 0;
+ }
+ 
+-int subdev_700_init_irq(struct comedi_device * dev, struct comedi_subdevice * s,
++int subdev_700_init_irq(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	int (*cb) (int, int, int, unsigned long), unsigned long arg)
+ {
+ 	int ret;
+@@ -337,7 +337,7 @@ int subdev_700_init_irq(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-void subdev_700_cleanup(struct comedi_device * dev, struct comedi_subdevice * s)
++void subdev_700_cleanup(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	if (s->private) {
+ 		if (subdevpriv->have_irq) {
+@@ -352,7 +352,7 @@ EXPORT_SYMBOL(subdev_700_init_irq);
+ EXPORT_SYMBOL(subdev_700_cleanup);
+ EXPORT_SYMBOL(subdev_700_interrupt);
+ 
+-static int dio700_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int dio700_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase = 0;
+@@ -415,7 +415,7 @@ static int dio700_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	return 0;
+ };
+ 
+-static int dio700_detach(struct comedi_device * dev)
++static int dio700_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: ni_daq_700: cs-remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
+index 7f9e502403c8..6474591eb0c2 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
++++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
+@@ -56,8 +56,8 @@ static struct pcmcia_device *pcmcia_cur_dev = NULL;
+ 
+ #define DIO24_SIZE 4		/*  size of io region used by board */
+ 
+-static int dio24_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int dio24_detach(struct comedi_device * dev);
++static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int dio24_detach(struct comedi_device *dev);
+ 
+ enum dio24_bustype { pcmcia_bustype };
+ 
+@@ -109,7 +109,7 @@ static struct comedi_driver driver_dio24 = {
+       offset:sizeof(struct dio24_board_struct),
+ };
+ 
+-static int dio24_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase = 0;
+@@ -172,7 +172,7 @@ static int dio24_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 	return 0;
+ };
+ 
+-static int dio24_detach(struct comedi_device * dev)
++static int dio24_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: ni_daq_dio24: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
+index 15172c20251d..caec783ca89a 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc.c
++++ b/drivers/staging/comedi/drivers/ni_labpc.c
+@@ -448,7 +448,7 @@ static DEFINE_PCI_DEVICE_TABLE(labpc_pci_table) = {
+ MODULE_DEVICE_TABLE(pci, labpc_pci_table);
+ #endif /* CONFIG_COMEDI_PCI */
+ 
+-static inline int labpc_counter_load(struct comedi_device * dev,
++static inline int labpc_counter_load(struct comedi_device *dev,
+ 	unsigned long base_address, unsigned int counter_number,
+ 	unsigned int count, unsigned int mode)
+ {
+@@ -459,7 +459,7 @@ static inline int labpc_counter_load(struct comedi_device * dev,
+ 		return i8254_load(base_address, 0, counter_number, count, mode);
+ }
+ 
+-int labpc_common_attach(struct comedi_device * dev, unsigned long iobase,
++int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
+ 	unsigned int irq, unsigned int dma_chan)
+ {
+ 	struct comedi_subdevice *s;
+@@ -643,7 +643,7 @@ int labpc_common_attach(struct comedi_device * dev, unsigned long iobase,
+ 	return 0;
+ }
+ 
+-static int labpc_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	unsigned long iobase = 0;
+ 	unsigned int irq = 0;
+@@ -724,7 +724,7 @@ static int labpc_find_device(struct comedi_device *dev, int bus, int slot)
+ }
+ #endif
+ 
+-int labpc_common_detach(struct comedi_device * dev)
++int labpc_common_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: ni_labpc: detach\n", dev->minor);
+ 
+@@ -748,14 +748,14 @@ int labpc_common_detach(struct comedi_device * dev)
+ 	return 0;
+ };
+ 
+-static void labpc_clear_adc_fifo(const struct comedi_device * dev)
++static void labpc_clear_adc_fifo(const struct comedi_device *dev)
+ {
+ 	devpriv->write_byte(0x1, dev->iobase + ADC_CLEAR_REG);
+ 	devpriv->read_byte(dev->iobase + ADC_FIFO_REG);
+ 	devpriv->read_byte(dev->iobase + ADC_FIFO_REG);
+ }
+ 
+-static int labpc_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	unsigned long flags;
+ 
+@@ -770,7 +770,7 @@ static int labpc_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static enum scan_mode labpc_ai_scan_mode(const struct comedi_cmd * cmd)
++static enum scan_mode labpc_ai_scan_mode(const struct comedi_cmd *cmd)
+ {
+ 	if (cmd->chanlist_len == 1)
+ 		return MODE_SINGLE_CHAN;
+@@ -793,8 +793,8 @@ static enum scan_mode labpc_ai_scan_mode(const struct comedi_cmd * cmd)
+ 	return 0;
+ }
+ 
+-static int labpc_ai_chanlist_invalid(const struct comedi_device * dev,
+-	const struct comedi_cmd * cmd)
++static int labpc_ai_chanlist_invalid(const struct comedi_device *dev,
++	const struct comedi_cmd *cmd)
+ {
+ 	int mode, channel, range, aref, i;
+ 
+@@ -865,7 +865,7 @@ static int labpc_ai_chanlist_invalid(const struct comedi_device * dev,
+ 	return 0;
+ }
+ 
+-static int labpc_use_continuous_mode(const struct comedi_cmd * cmd)
++static int labpc_use_continuous_mode(const struct comedi_cmd *cmd)
+ {
+ 	if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN)
+ 		return 1;
+@@ -876,7 +876,7 @@ static int labpc_use_continuous_mode(const struct comedi_cmd * cmd)
+ 	return 0;
+ }
+ 
+-static unsigned int labpc_ai_convert_period(const struct comedi_cmd * cmd)
++static unsigned int labpc_ai_convert_period(const struct comedi_cmd *cmd)
+ {
+ 	if (cmd->convert_src != TRIG_TIMER)
+ 		return 0;
+@@ -888,7 +888,7 @@ static unsigned int labpc_ai_convert_period(const struct comedi_cmd * cmd)
+ 	return cmd->convert_arg;
+ }
+ 
+-static void labpc_set_ai_convert_period(struct comedi_cmd * cmd, unsigned int ns)
++static void labpc_set_ai_convert_period(struct comedi_cmd *cmd, unsigned int ns)
+ {
+ 	if (cmd->convert_src != TRIG_TIMER)
+ 		return;
+@@ -902,7 +902,7 @@ static void labpc_set_ai_convert_period(struct comedi_cmd * cmd, unsigned int ns
+ 		cmd->convert_arg = ns;
+ }
+ 
+-static unsigned int labpc_ai_scan_period(const struct comedi_cmd * cmd)
++static unsigned int labpc_ai_scan_period(const struct comedi_cmd *cmd)
+ {
+ 	if (cmd->scan_begin_src != TRIG_TIMER)
+ 		return 0;
+@@ -914,7 +914,7 @@ static unsigned int labpc_ai_scan_period(const struct comedi_cmd * cmd)
+ 	return cmd->scan_begin_arg;
+ }
+ 
+-static void labpc_set_ai_scan_period(struct comedi_cmd * cmd, unsigned int ns)
++static void labpc_set_ai_scan_period(struct comedi_cmd *cmd, unsigned int ns)
+ {
+ 	if (cmd->scan_begin_src != TRIG_TIMER)
+ 		return;
+@@ -926,8 +926,8 @@ static void labpc_set_ai_scan_period(struct comedi_cmd * cmd, unsigned int ns)
+ 	cmd->scan_begin_arg = ns;
+ }
+ 
+-static int labpc_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int labpc_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp, tmp2;
+@@ -1063,7 +1063,7 @@ static int labpc_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice
+ 	return 0;
+ }
+ 
+-static int labpc_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	int channel, range, aref;
+ 	unsigned long irq_flags;
+@@ -1393,7 +1393,7 @@ static irqreturn_t labpc_interrupt(int irq, void *d)
+ }
+ 
+ /* read all available samples from ai fifo */
+-static int labpc_drain_fifo(struct comedi_device * dev)
++static int labpc_drain_fifo(struct comedi_device *dev)
+ {
+ 	unsigned int lsb, msb;
+ 	short data;
+@@ -1427,7 +1427,7 @@ static int labpc_drain_fifo(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static void labpc_drain_dma(struct comedi_device * dev)
++static void labpc_drain_dma(struct comedi_device *dev)
+ {
+ 	struct comedi_subdevice *s = dev->read_subdev;
+ 	struct comedi_async *async = s->async;
+@@ -1480,7 +1480,7 @@ static void labpc_drain_dma(struct comedi_device * dev)
+ 	async->events |= COMEDI_CB_BLOCK;
+ }
+ 
+-static void handle_isa_dma(struct comedi_device * dev)
++static void handle_isa_dma(struct comedi_device *dev)
+ {
+ 	labpc_drain_dma(dev);
+ 
+@@ -1492,7 +1492,7 @@ static void handle_isa_dma(struct comedi_device * dev)
+ 
+ /* makes sure all data aquired by board is transfered to comedi (used
+  * when aquisition is terminated by stop_src == TRIG_EXT). */
+-static void labpc_drain_dregs(struct comedi_device * dev)
++static void labpc_drain_dregs(struct comedi_device *dev)
+ {
+ 	if (devpriv->current_transfer == isa_dma_transfer)
+ 		labpc_drain_dma(dev);
+@@ -1500,8 +1500,8 @@ static void labpc_drain_dregs(struct comedi_device * dev)
+ 	labpc_drain_fifo(dev);
+ }
+ 
+-static int labpc_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int labpc_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, n;
+ 	int chan, range;
+@@ -1586,8 +1586,8 @@ static int labpc_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ /* analog output insn */
+-static int labpc_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int labpc_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int channel, range;
+ 	unsigned long flags;
+@@ -1627,24 +1627,24 @@ static int labpc_ao_winsn(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ /* analog output readback insn */
+-static int labpc_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int labpc_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)];
+ 
+ 	return 1;
+ }
+ 
+-static int labpc_calib_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int labpc_calib_read_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[0] = devpriv->caldac[CR_CHAN(insn->chanspec)];
+ 
+ 	return 1;
+ }
+ 
+-static int labpc_calib_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int labpc_calib_write_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int channel = CR_CHAN(insn->chanspec);
+ 
+@@ -1652,16 +1652,16 @@ static int labpc_calib_write_insn(struct comedi_device * dev, struct comedi_subd
+ 	return 1;
+ }
+ 
+-static int labpc_eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int labpc_eeprom_read_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[0] = devpriv->eeprom_data[CR_CHAN(insn->chanspec)];
+ 
+ 	return 1;
+ }
+ 
+-static int labpc_eeprom_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int labpc_eeprom_write_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int channel = CR_CHAN(insn->chanspec);
+ 	int ret;
+@@ -1704,7 +1704,7 @@ static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd)
+ }
+ 
+ /* figures out what counter values to use based on command */
+-static void labpc_adc_timing(struct comedi_device * dev, struct comedi_cmd * cmd)
++static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd)
+ {
+ 	const int max_counter_value = 0x10000;	/*  max value for 16 bit counter in mode 2 */
+ 	const int min_counter_value = 2;	/*  min value for 16 bit counter in mode 2 */
+@@ -1796,7 +1796,7 @@ static int labpc_dio_mem_callback(int dir, int port, int data,
+ }
+ 
+ /* lowlevel write to eeprom/dac */
+-static void labpc_serial_out(struct comedi_device * dev, unsigned int value,
++static void labpc_serial_out(struct comedi_device *dev, unsigned int value,
+ 	unsigned int value_width)
+ {
+ 	int i;
+@@ -1821,7 +1821,7 @@ static void labpc_serial_out(struct comedi_device * dev, unsigned int value,
+ }
+ 
+ /* lowlevel read from eeprom */
+-static unsigned int labpc_serial_in(struct comedi_device * dev)
++static unsigned int labpc_serial_in(struct comedi_device *dev)
+ {
+ 	unsigned int value = 0;
+ 	int i;
+@@ -1850,7 +1850,7 @@ static unsigned int labpc_serial_in(struct comedi_device * dev)
+ 	return value;
+ }
+ 
+-static unsigned int labpc_eeprom_read(struct comedi_device * dev, unsigned int address)
++static unsigned int labpc_eeprom_read(struct comedi_device *dev, unsigned int address)
+ {
+ 	unsigned int value;
+ 	const int read_instruction = 0x3;	/*  bits to tell eeprom to expect a read */
+@@ -1879,7 +1879,7 @@ static unsigned int labpc_eeprom_read(struct comedi_device * dev, unsigned int a
+ 	return value;
+ }
+ 
+-static unsigned int labpc_eeprom_write(struct comedi_device * dev,
++static unsigned int labpc_eeprom_write(struct comedi_device *dev,
+ 	unsigned int address, unsigned int value)
+ {
+ 	const int write_enable_instruction = 0x6;
+@@ -1937,7 +1937,7 @@ static unsigned int labpc_eeprom_write(struct comedi_device * dev,
+ 	return 0;
+ }
+ 
+-static unsigned int labpc_eeprom_read_status(struct comedi_device * dev)
++static unsigned int labpc_eeprom_read_status(struct comedi_device *dev)
+ {
+ 	unsigned int value;
+ 	const int read_status_instruction = 0x5;
+@@ -1965,7 +1965,7 @@ static unsigned int labpc_eeprom_read_status(struct comedi_device * dev)
+ }
+ 
+ /* writes to 8 bit calibration dacs */
+-static void write_caldac(struct comedi_device * dev, unsigned int channel,
++static void write_caldac(struct comedi_device *dev, unsigned int channel,
+ 	unsigned int value)
+ {
+ 	if (value == devpriv->caldac[channel])
+diff --git a/drivers/staging/comedi/drivers/ni_labpc.h b/drivers/staging/comedi/drivers/ni_labpc.h
+index 1171ec816b61..c5d2d212612c 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc.h
++++ b/drivers/staging/comedi/drivers/ni_labpc.h
+@@ -74,9 +74,9 @@ struct labpc_private {
+ 	void (*write_byte) (unsigned int byte, unsigned long address);
+ };
+ 
+-int labpc_common_attach(struct comedi_device * dev, unsigned long iobase,
++int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
+ 	unsigned int irq, unsigned int dma);
+-int labpc_common_detach(struct comedi_device * dev);
++int labpc_common_detach(struct comedi_device *dev);
+ 
+ extern const int labpc_1200_is_unipolar[];
+ extern const int labpc_1200_ai_gain_bits[];
+diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
+index ac3352fed6d6..b0c523e9f198 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
++++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
+@@ -79,7 +79,7 @@ NI manuals:
+ 
+ static struct pcmcia_device *pcmcia_cur_dev = NULL;
+ 
+-static int labpc_attach(struct comedi_device * dev, struct comedi_devconfig * it);
++static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ 
+ static const struct labpc_board_struct labpc_cs_boards[] = {
+ 	{
+@@ -126,7 +126,7 @@ static struct comedi_driver driver_labpc_cs = {
+ 	.offset = sizeof(struct labpc_board_struct),
+ };
+ 
+-static int labpc_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	unsigned long iobase = 0;
+ 	unsigned int irq = 0;
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index 838487868c62..f277ca6b73d4 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -193,49 +193,49 @@ static const struct comedi_lrange *const ni_range_lkup[] = {
+ 	[ai_gain_6143] = &range_ni_S_ai_6143
+ };
+ 
+-static int ni_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int ni_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int ni_cdio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd);
+-static int ni_cdio_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int ni_cdio_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+-static void handle_cdio_interrupt(struct comedi_device * dev);
+-static int ni_cdo_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
++static int ni_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int ni_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int ni_cdio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd);
++static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
++static int ni_cdio_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
++static void handle_cdio_interrupt(struct comedi_device *dev);
++static int ni_cdo_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int trignum);
+ 
+-static int ni_serial_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int ni_serial_hw_readwrite8(struct comedi_device * dev, struct comedi_subdevice * s,
++static int ni_serial_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int ni_serial_hw_readwrite8(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned char data_out, unsigned char *data_in);
+-static int ni_serial_sw_readwrite8(struct comedi_device * dev, struct comedi_subdevice * s,
++static int ni_serial_sw_readwrite8(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned char data_out, unsigned char *data_in);
+ 
+-static int ni_calib_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int ni_calib_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int ni_calib_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int ni_calib_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+-static int ni_eeprom_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int ni_m_series_eeprom_insn_read(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
++static int ni_eeprom_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int ni_m_series_eeprom_insn_read(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
+ 
+-static int ni_pfi_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int ni_pfi_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static unsigned ni_old_get_pfi_routing(struct comedi_device * dev, unsigned chan);
++static int ni_pfi_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int ni_pfi_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static unsigned ni_old_get_pfi_routing(struct comedi_device *dev, unsigned chan);
+ 
+-static void ni_rtsi_init(struct comedi_device * dev);
+-static int ni_rtsi_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int ni_rtsi_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static void ni_rtsi_init(struct comedi_device *dev);
++static int ni_rtsi_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int ni_rtsi_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+-static void caldac_setup(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int ni_read_eeprom(struct comedi_device * dev, int addr);
++static void caldac_setup(struct comedi_device *dev, struct comedi_subdevice *s);
++static int ni_read_eeprom(struct comedi_device *dev, int addr);
+ 
+ #ifdef DEBUG_STATUS_A
+ static void ni_mio_print_status_a(int status);
+@@ -248,58 +248,58 @@ static void ni_mio_print_status_b(int status);
+ #define ni_mio_print_status_b(a)
+ #endif
+ 
+-static int ni_ai_reset(struct comedi_device * dev, struct comedi_subdevice * s);
++static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s);
+ #ifndef PCIDMA
+-static void ni_handle_fifo_half_full(struct comedi_device * dev);
+-static int ni_ao_fifo_half_empty(struct comedi_device * dev, struct comedi_subdevice * s);
++static void ni_handle_fifo_half_full(struct comedi_device *dev);
++static int ni_ao_fifo_half_empty(struct comedi_device *dev, struct comedi_subdevice *s);
+ #endif
+-static void ni_handle_fifo_dregs(struct comedi_device * dev);
+-static int ni_ai_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
++static void ni_handle_fifo_dregs(struct comedi_device *dev);
++static int ni_ai_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int trignum);
+-static void ni_load_channelgain_list(struct comedi_device * dev, unsigned int n_chan,
++static void ni_load_channelgain_list(struct comedi_device *dev, unsigned int n_chan,
+ 	unsigned int *list);
+-static void shutdown_ai_command(struct comedi_device * dev);
++static void shutdown_ai_command(struct comedi_device *dev);
+ 
+-static int ni_ao_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
++static int ni_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int trignum);
+ 
+-static int ni_ao_reset(struct comedi_device * dev, struct comedi_subdevice * s);
++static int ni_ao_reset(struct comedi_device *dev, struct comedi_subdevice *s);
+ 
+ static int ni_8255_callback(int dir, int port, int data, unsigned long arg);
+ 
+-static int ni_gpct_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int ni_gpct_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int ni_gpct_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int ni_gpct_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int ni_gpct_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd);
+-static int ni_gpct_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+-static void handle_gpct_interrupt(struct comedi_device * dev,
++static int ni_gpct_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int ni_gpct_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int ni_gpct_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int ni_gpct_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
++static int ni_gpct_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd);
++static int ni_gpct_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
++static void handle_gpct_interrupt(struct comedi_device *dev,
+ 	unsigned short counter_index);
+ 
+-static int init_cs5529(struct comedi_device * dev);
+-static int cs5529_do_conversion(struct comedi_device * dev, unsigned short *data);
+-static int cs5529_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int init_cs5529(struct comedi_device *dev);
++static int cs5529_do_conversion(struct comedi_device *dev, unsigned short *data);
++static int cs5529_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ #ifdef NI_CS5529_DEBUG
+-static unsigned int cs5529_config_read(struct comedi_device * dev,
++static unsigned int cs5529_config_read(struct comedi_device *dev,
+ 	unsigned int reg_select_bits);
+ #endif
+-static void cs5529_config_write(struct comedi_device * dev, unsigned int value,
++static void cs5529_config_write(struct comedi_device *dev, unsigned int value,
+ 	unsigned int reg_select_bits);
+ 
+-static int ni_m_series_pwm_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int ni_6143_pwm_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int ni_m_series_pwm_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int ni_6143_pwm_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+-static int ni_set_master_clock(struct comedi_device * dev, unsigned source,
++static int ni_set_master_clock(struct comedi_device *dev, unsigned source,
+ 	unsigned period_ns);
+-static void ack_a_interrupt(struct comedi_device * dev, unsigned short a_status);
+-static void ack_b_interrupt(struct comedi_device * dev, unsigned short b_status);
++static void ack_a_interrupt(struct comedi_device *dev, unsigned short a_status);
++static void ack_b_interrupt(struct comedi_device *dev, unsigned short b_status);
+ 
+ enum aimodes {
+ 	AIMODE_NONE = 0,
+@@ -353,14 +353,14 @@ enum timebase_nanoseconds {
+ 
+ static const int num_adc_stages_611x = 3;
+ 
+-static void handle_a_interrupt(struct comedi_device * dev, unsigned short status,
++static void handle_a_interrupt(struct comedi_device *dev, unsigned short status,
+ 	unsigned ai_mite_status);
+-static void handle_b_interrupt(struct comedi_device * dev, unsigned short status,
++static void handle_b_interrupt(struct comedi_device *dev, unsigned short status,
+ 	unsigned ao_mite_status);
+-static void get_last_sample_611x(struct comedi_device * dev);
+-static void get_last_sample_6143(struct comedi_device * dev);
++static void get_last_sample_611x(struct comedi_device *dev);
++static void get_last_sample_6143(struct comedi_device *dev);
+ 
+-static inline void ni_set_bitfield(struct comedi_device * dev, int reg,
++static inline void ni_set_bitfield(struct comedi_device *dev, int reg,
+ 	unsigned bit_mask, unsigned bit_values)
+ {
+ 	unsigned long flags;
+@@ -406,12 +406,12 @@ static inline void ni_set_bitfield(struct comedi_device * dev, int reg,
+ }
+ 
+ #ifdef PCIDMA
+-static int ni_ai_drain_dma(struct comedi_device * dev);
++static int ni_ai_drain_dma(struct comedi_device *dev);
+ 
+ /* DMA channel setup */
+ 
+ /* negative channel means no channel */
+-static inline void ni_set_ai_dma_channel(struct comedi_device * dev, int channel)
++static inline void ni_set_ai_dma_channel(struct comedi_device *dev, int channel)
+ {
+ 	unsigned bitfield;
+ 
+@@ -426,7 +426,7 @@ static inline void ni_set_ai_dma_channel(struct comedi_device * dev, int channel
+ }
+ 
+ /* negative channel means no channel */
+-static inline void ni_set_ao_dma_channel(struct comedi_device * dev, int channel)
++static inline void ni_set_ao_dma_channel(struct comedi_device *dev, int channel)
+ {
+ 	unsigned bitfield;
+ 
+@@ -441,7 +441,7 @@ static inline void ni_set_ao_dma_channel(struct comedi_device * dev, int channel
+ }
+ 
+ /* negative mite_channel means no channel */
+-static inline void ni_set_gpct_dma_channel(struct comedi_device * dev,
++static inline void ni_set_gpct_dma_channel(struct comedi_device *dev,
+ 	unsigned gpct_index, int mite_channel)
+ {
+ 	unsigned bitfield;
+@@ -456,7 +456,7 @@ static inline void ni_set_gpct_dma_channel(struct comedi_device * dev,
+ }
+ 
+ /* negative mite_channel means no channel */
+-static inline void ni_set_cdo_dma_channel(struct comedi_device * dev, int mite_channel)
++static inline void ni_set_cdo_dma_channel(struct comedi_device *dev, int mite_channel)
+ {
+ 	unsigned long flags;
+ 
+@@ -475,7 +475,7 @@ static inline void ni_set_cdo_dma_channel(struct comedi_device * dev, int mite_c
+ 	comedi_spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags);
+ }
+ 
+-static int ni_request_ai_mite_channel(struct comedi_device * dev)
++static int ni_request_ai_mite_channel(struct comedi_device *dev)
+ {
+ 	unsigned long flags;
+ 
+@@ -496,7 +496,7 @@ static int ni_request_ai_mite_channel(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int ni_request_ao_mite_channel(struct comedi_device * dev)
++static int ni_request_ao_mite_channel(struct comedi_device *dev)
+ {
+ 	unsigned long flags;
+ 
+@@ -517,7 +517,7 @@ static int ni_request_ao_mite_channel(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int ni_request_gpct_mite_channel(struct comedi_device * dev,
++static int ni_request_gpct_mite_channel(struct comedi_device *dev,
+ 	unsigned gpct_index, enum comedi_io_direction direction)
+ {
+ 	unsigned long flags;
+@@ -546,7 +546,7 @@ static int ni_request_gpct_mite_channel(struct comedi_device * dev,
+ 
+ #endif /*  PCIDMA */
+ 
+-static int ni_request_cdo_mite_channel(struct comedi_device * dev)
++static int ni_request_cdo_mite_channel(struct comedi_device *dev)
+ {
+ #ifdef PCIDMA
+ 	unsigned long flags;
+@@ -569,7 +569,7 @@ static int ni_request_cdo_mite_channel(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static void ni_release_ai_mite_channel(struct comedi_device * dev)
++static void ni_release_ai_mite_channel(struct comedi_device *dev)
+ {
+ #ifdef PCIDMA
+ 	unsigned long flags;
+@@ -584,7 +584,7 @@ static void ni_release_ai_mite_channel(struct comedi_device * dev)
+ #endif /*  PCIDMA */
+ }
+ 
+-static void ni_release_ao_mite_channel(struct comedi_device * dev)
++static void ni_release_ao_mite_channel(struct comedi_device *dev)
+ {
+ #ifdef PCIDMA
+ 	unsigned long flags;
+@@ -599,7 +599,7 @@ static void ni_release_ao_mite_channel(struct comedi_device * dev)
+ #endif /*  PCIDMA */
+ }
+ 
+-void ni_release_gpct_mite_channel(struct comedi_device * dev, unsigned gpct_index)
++void ni_release_gpct_mite_channel(struct comedi_device *dev, unsigned gpct_index)
+ {
+ #ifdef PCIDMA
+ 	unsigned long flags;
+@@ -619,7 +619,7 @@ void ni_release_gpct_mite_channel(struct comedi_device * dev, unsigned gpct_inde
+ #endif /*  PCIDMA */
+ }
+ 
+-static void ni_release_cdo_mite_channel(struct comedi_device * dev)
++static void ni_release_cdo_mite_channel(struct comedi_device *dev)
+ {
+ #ifdef PCIDMA
+ 	unsigned long flags;
+@@ -636,7 +636,7 @@ static void ni_release_cdo_mite_channel(struct comedi_device * dev)
+ 
+ /* e-series boards use the second irq signals to generate dma requests for their counters */
+ #ifdef PCIDMA
+-static void ni_e_series_enable_second_irq(struct comedi_device * dev,
++static void ni_e_series_enable_second_irq(struct comedi_device *dev,
+ 	unsigned gpct_index, short enable)
+ {
+ 	if (boardtype.reg_type & ni_reg_m_series_mask)
+@@ -667,7 +667,7 @@ static void ni_e_series_enable_second_irq(struct comedi_device * dev,
+ }
+ #endif /*  PCIDMA */
+ 
+-static void ni_clear_ai_fifo(struct comedi_device * dev)
++static void ni_clear_ai_fifo(struct comedi_device *dev)
+ {
+ 	if (boardtype.reg_type == ni_reg_6143) {
+ 		/*  Flush the 6143 data FIFO */
+@@ -693,13 +693,13 @@ static void ni_clear_ai_fifo(struct comedi_device * dev)
+ 	}
+ }
+ 
+-static void win_out2(struct comedi_device * dev, uint32_t data, int reg)
++static void win_out2(struct comedi_device *dev, uint32_t data, int reg)
+ {
+ 	devpriv->stc_writew(dev, data >> 16, reg);
+ 	devpriv->stc_writew(dev, data & 0xffff, reg + 1);
+ }
+ 
+-static uint32_t win_in2(struct comedi_device * dev, int reg)
++static uint32_t win_in2(struct comedi_device *dev, int reg)
+ {
+ 	uint32_t bits;
+ 	bits = devpriv->stc_readw(dev, reg) << 16;
+@@ -708,7 +708,7 @@ static uint32_t win_in2(struct comedi_device * dev, int reg)
+ }
+ 
+ #define ao_win_out(data,addr) ni_ao_win_outw(dev,data,addr)
+-static inline void ni_ao_win_outw(struct comedi_device * dev, uint16_t data, int addr)
++static inline void ni_ao_win_outw(struct comedi_device *dev, uint16_t data, int addr)
+ {
+ 	unsigned long flags;
+ 
+@@ -718,7 +718,7 @@ static inline void ni_ao_win_outw(struct comedi_device * dev, uint16_t data, int
+ 	comedi_spin_unlock_irqrestore(&devpriv->window_lock, flags);
+ }
+ 
+-static inline void ni_ao_win_outl(struct comedi_device * dev, uint32_t data, int addr)
++static inline void ni_ao_win_outl(struct comedi_device *dev, uint32_t data, int addr)
+ {
+ 	unsigned long flags;
+ 
+@@ -728,7 +728,7 @@ static inline void ni_ao_win_outl(struct comedi_device * dev, uint32_t data, int
+ 	comedi_spin_unlock_irqrestore(&devpriv->window_lock, flags);
+ }
+ 
+-static inline unsigned short ni_ao_win_inw(struct comedi_device * dev, int addr)
++static inline unsigned short ni_ao_win_inw(struct comedi_device *dev, int addr)
+ {
+ 	unsigned long flags;
+ 	unsigned short data;
+@@ -750,7 +750,7 @@ static inline unsigned short ni_ao_win_inw(struct comedi_device * dev, int addr)
+ *
+ * value should only be 1 or 0.
+ */
+-static inline void ni_set_bits(struct comedi_device * dev, int reg, unsigned bits,
++static inline void ni_set_bits(struct comedi_device *dev, int reg, unsigned bits,
+ 	unsigned value)
+ {
+ 	unsigned bit_values;
+@@ -823,7 +823,7 @@ static irqreturn_t ni_E_interrupt(int irq, void *d)
+ }
+ 
+ #ifdef PCIDMA
+-static void ni_sync_ai_dma(struct comedi_device * dev)
++static void ni_sync_ai_dma(struct comedi_device *dev)
+ {
+ 	struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ 	unsigned long flags;
+@@ -846,7 +846,7 @@ static void mite_handle_b_linkc(struct mite_struct *mite, struct comedi_device *
+ 	comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
+ }
+ 
+-static int ni_ao_wait_for_dma_load(struct comedi_device * dev)
++static int ni_ao_wait_for_dma_load(struct comedi_device *dev)
+ {
+ 	static const int timeout = 10000;
+ 	int i;
+@@ -868,7 +868,7 @@ static int ni_ao_wait_for_dma_load(struct comedi_device * dev)
+ }
+ 
+ #endif /* PCIDMA */
+-static void ni_handle_eos(struct comedi_device * dev, struct comedi_subdevice * s)
++static void ni_handle_eos(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	if (devpriv->aimode == AIMODE_SCAN) {
+ #ifdef PCIDMA
+@@ -892,7 +892,7 @@ static void ni_handle_eos(struct comedi_device * dev, struct comedi_subdevice *
+ 	}
+ }
+ 
+-static void shutdown_ai_command(struct comedi_device * dev)
++static void shutdown_ai_command(struct comedi_device *dev)
+ {
+ 	struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ 
+@@ -906,7 +906,7 @@ static void shutdown_ai_command(struct comedi_device * dev)
+ 	s->async->events |= COMEDI_CB_EOA;
+ }
+ 
+-static void ni_event(struct comedi_device * dev, struct comedi_subdevice * s)
++static void ni_event(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	if (s->async->
+ 		events & (COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW | COMEDI_CB_EOA))
+@@ -932,7 +932,7 @@ static void ni_event(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	comedi_event(dev, s);
+ }
+ 
+-static void handle_gpct_interrupt(struct comedi_device * dev,
++static void handle_gpct_interrupt(struct comedi_device *dev,
+ 	unsigned short counter_index)
+ {
+ #ifdef PCIDMA
+@@ -945,7 +945,7 @@ static void handle_gpct_interrupt(struct comedi_device * dev,
+ #endif
+ }
+ 
+-static void ack_a_interrupt(struct comedi_device * dev, unsigned short a_status)
++static void ack_a_interrupt(struct comedi_device *dev, unsigned short a_status)
+ {
+ 	unsigned short ack = 0;
+ 
+@@ -966,7 +966,7 @@ static void ack_a_interrupt(struct comedi_device * dev, unsigned short a_status)
+ 		devpriv->stc_writew(dev, ack, Interrupt_A_Ack_Register);
+ }
+ 
+-static void handle_a_interrupt(struct comedi_device * dev, unsigned short status,
++static void handle_a_interrupt(struct comedi_device *dev, unsigned short status,
+ 	unsigned ai_mite_status)
+ {
+ 	struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+@@ -1070,7 +1070,7 @@ static void handle_a_interrupt(struct comedi_device * dev, unsigned short status
+ #endif
+ }
+ 
+-static void ack_b_interrupt(struct comedi_device * dev, unsigned short b_status)
++static void ack_b_interrupt(struct comedi_device *dev, unsigned short b_status)
+ {
+ 	unsigned short ack = 0;
+ 	if (b_status & AO_BC_TC_St) {
+@@ -1098,7 +1098,7 @@ static void ack_b_interrupt(struct comedi_device * dev, unsigned short b_status)
+ 		devpriv->stc_writew(dev, ack, Interrupt_B_Ack_Register);
+ }
+ 
+-static void handle_b_interrupt(struct comedi_device * dev, unsigned short b_status,
++static void handle_b_interrupt(struct comedi_device *dev, unsigned short b_status,
+ 	unsigned ao_mite_status)
+ {
+ 	struct comedi_subdevice *s = dev->subdevices + NI_AO_SUBDEV;
+@@ -1204,7 +1204,7 @@ static void ni_mio_print_status_b(int status)
+ 
+ #ifndef PCIDMA
+ 
+-static void ni_ao_fifo_load(struct comedi_device * dev, struct comedi_subdevice * s, int n)
++static void ni_ao_fifo_load(struct comedi_device *dev, struct comedi_subdevice *s, int n)
+ {
+ 	struct comedi_async *async = s->async;
+ 	struct comedi_cmd *cmd = &async->cmd;
+@@ -1263,7 +1263,7 @@ static void ni_ao_fifo_load(struct comedi_device * dev, struct comedi_subdevice
+  *  RT code, as RT code might purposely be running close to the
+  *  metal.  Needs to be fixed eventually.
+  */
+-static int ni_ao_fifo_half_empty(struct comedi_device * dev, struct comedi_subdevice * s)
++static int ni_ao_fifo_half_empty(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	int n;
+ 
+@@ -1284,7 +1284,7 @@ static int ni_ao_fifo_half_empty(struct comedi_device * dev, struct comedi_subde
+ 	return 1;
+ }
+ 
+-static int ni_ao_prep_fifo(struct comedi_device * dev, struct comedi_subdevice * s)
++static int ni_ao_prep_fifo(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	int n;
+ 
+@@ -1307,7 +1307,7 @@ static int ni_ao_prep_fifo(struct comedi_device * dev, struct comedi_subdevice *
+ 	return n;
+ }
+ 
+-static void ni_ai_fifo_read(struct comedi_device * dev, struct comedi_subdevice * s, int n)
++static void ni_ai_fifo_read(struct comedi_device *dev, struct comedi_subdevice *s, int n)
+ {
+ 	struct comedi_async *async = s->async;
+ 	int i;
+@@ -1364,7 +1364,7 @@ static void ni_ai_fifo_read(struct comedi_device * dev, struct comedi_subdevice
+ 	}
+ }
+ 
+-static void ni_handle_fifo_half_full(struct comedi_device * dev)
++static void ni_handle_fifo_half_full(struct comedi_device *dev)
+ {
+ 	int n;
+ 	struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+@@ -1376,7 +1376,7 @@ static void ni_handle_fifo_half_full(struct comedi_device * dev)
+ #endif
+ 
+ #ifdef PCIDMA
+-static int ni_ai_drain_dma(struct comedi_device * dev)
++static int ni_ai_drain_dma(struct comedi_device *dev)
+ {
+ 	int i;
+ 	static const int timeout = 10000;
+@@ -1414,7 +1414,7 @@ static int ni_ai_drain_dma(struct comedi_device * dev)
+ /*
+    Empties the AI fifo
+ */
+-static void ni_handle_fifo_dregs(struct comedi_device * dev)
++static void ni_handle_fifo_dregs(struct comedi_device *dev)
+ {
+ 	struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ 	short data[2];
+@@ -1476,7 +1476,7 @@ static void ni_handle_fifo_dregs(struct comedi_device * dev)
+ 	}
+ }
+ 
+-static void get_last_sample_611x(struct comedi_device * dev)
++static void get_last_sample_611x(struct comedi_device *dev)
+ {
+ 	struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ 	short data;
+@@ -1493,7 +1493,7 @@ static void get_last_sample_611x(struct comedi_device * dev)
+ 	}
+ }
+ 
+-static void get_last_sample_6143(struct comedi_device * dev)
++static void get_last_sample_6143(struct comedi_device *dev)
+ {
+ 	struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ 	short data;
+@@ -1513,7 +1513,7 @@ static void get_last_sample_6143(struct comedi_device * dev)
+ 	}
+ }
+ 
+-static void ni_ai_munge(struct comedi_device * dev, struct comedi_subdevice * s,
++static void ni_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	void *data, unsigned int num_bytes, unsigned int chan_index)
+ {
+ 	struct comedi_async *async = s->async;
+@@ -1539,7 +1539,7 @@ static void ni_ai_munge(struct comedi_device * dev, struct comedi_subdevice * s,
+ 
+ #ifdef PCIDMA
+ 
+-static int ni_ai_setup_MITE_dma(struct comedi_device * dev)
++static int ni_ai_setup_MITE_dma(struct comedi_device *dev)
+ {
+ 	struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ 	int retval;
+@@ -1579,7 +1579,7 @@ static int ni_ai_setup_MITE_dma(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int ni_ao_setup_MITE_dma(struct comedi_device * dev)
++static int ni_ao_setup_MITE_dma(struct comedi_device *dev)
+ {
+ 	struct comedi_subdevice *s = dev->subdevices + NI_AO_SUBDEV;
+ 	int retval;
+@@ -1617,7 +1617,7 @@ static int ni_ao_setup_MITE_dma(struct comedi_device * dev)
+    this is pretty harsh for a cancel, but it works...
+  */
+ 
+-static int ni_ai_reset(struct comedi_device * dev, struct comedi_subdevice * s)
++static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	ni_release_ai_mite_channel(dev);
+ 	/* ai configuration */
+@@ -1698,7 +1698,7 @@ static int ni_ai_reset(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ni_ai_poll(struct comedi_device * dev, struct comedi_subdevice * s)
++static int ni_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	unsigned long flags = 0;
+ 	int count;
+@@ -1718,8 +1718,8 @@ static int ni_ai_poll(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	return count;
+ }
+ 
+-static int ni_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, n;
+ 	const unsigned int mask = (1 << boardtype.adbits) - 1;
+@@ -1814,7 +1814,7 @@ static int ni_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice *
+ 	return insn->n;
+ }
+ 
+-void ni_prime_channelgain_list(struct comedi_device * dev)
++void ni_prime_channelgain_list(struct comedi_device *dev)
+ {
+ 	int i;
+ 	devpriv->stc_writew(dev, AI_CONVERT_Pulse, AI_Command_1_Register);
+@@ -1830,7 +1830,7 @@ void ni_prime_channelgain_list(struct comedi_device * dev)
+ 	rt_printk("ni_mio_common: timeout loading channel/gain list\n");
+ }
+ 
+-static void ni_m_series_load_channelgain_list(struct comedi_device * dev,
++static void ni_m_series_load_channelgain_list(struct comedi_device *dev,
+ 	unsigned int n_chan, unsigned int *list)
+ {
+ 	unsigned int chan, range, aref;
+@@ -1935,7 +1935,7 @@ static void ni_m_series_load_channelgain_list(struct comedi_device * dev,
+  *   bits 0-2: channel
+  *       valid channels are 0-3
+  */
+-static void ni_load_channelgain_list(struct comedi_device * dev, unsigned int n_chan,
++static void ni_load_channelgain_list(struct comedi_device *dev, unsigned int n_chan,
+ 	unsigned int *list)
+ {
+ 	unsigned int chan, range, aref;
+@@ -2055,7 +2055,7 @@ static void ni_load_channelgain_list(struct comedi_device * dev, unsigned int n_
+ 	}
+ }
+ 
+-static int ni_ns_to_timer(const struct comedi_device * dev, unsigned nanosec,
++static int ni_ns_to_timer(const struct comedi_device *dev, unsigned nanosec,
+ 	int round_mode)
+ {
+ 	int divider;
+@@ -2074,12 +2074,12 @@ static int ni_ns_to_timer(const struct comedi_device * dev, unsigned nanosec,
+ 	return divider - 1;
+ }
+ 
+-static unsigned ni_timer_to_ns(const struct comedi_device * dev, int timer)
++static unsigned ni_timer_to_ns(const struct comedi_device *dev, int timer)
+ {
+ 	return devpriv->clock_ns * (timer + 1);
+ }
+ 
+-static unsigned ni_min_ai_scan_period_ns(struct comedi_device * dev,
++static unsigned ni_min_ai_scan_period_ns(struct comedi_device *dev,
+ 	unsigned num_channels)
+ {
+ 	switch (boardtype.reg_type) {
+@@ -2095,8 +2095,8 @@ static unsigned ni_min_ai_scan_period_ns(struct comedi_device * dev,
+ 	return boardtype.ai_speed * num_channels;
+ }
+ 
+-static int ni_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -2308,7 +2308,7 @@ static int ni_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s
+ 	return 0;
+ }
+ 
+-static int ni_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	const struct comedi_cmd *cmd = &s->async->cmd;
+ 	int timer;
+@@ -2612,7 +2612,7 @@ static int ni_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ni_ai_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
++static int ni_ai_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int trignum)
+ {
+ 	if (trignum != 0)
+@@ -2625,11 +2625,11 @@ static int ni_ai_inttrig(struct comedi_device * dev, struct comedi_subdevice * s
+ 	return 1;
+ }
+ 
+-static int ni_ai_config_analog_trig(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int ni_ai_config_analog_trig(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+-static int ni_ai_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_ai_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n < 1)
+ 		return -EINVAL;
+@@ -2679,8 +2679,8 @@ static int ni_ai_insn_config(struct comedi_device * dev, struct comedi_subdevice
+ 	return -EINVAL;
+ }
+ 
+-static int ni_ai_config_analog_trig(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_ai_config_analog_trig(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int a, b, modebits;
+ 	int err = 0;
+@@ -2777,7 +2777,7 @@ static int ni_ai_config_analog_trig(struct comedi_device * dev, struct comedi_su
+ }
+ 
+ /* munge data from unsigned to 2's complement for analog output bipolar modes */
+-static void ni_ao_munge(struct comedi_device * dev, struct comedi_subdevice * s,
++static void ni_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	void *data, unsigned int num_bytes, unsigned int chan_index)
+ {
+ 	struct comedi_async *async = s->async;
+@@ -2800,8 +2800,8 @@ static void ni_ao_munge(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	}
+ }
+ 
+-static int ni_m_series_ao_config_chanlist(struct comedi_device * dev,
+-	struct comedi_subdevice * s, unsigned int chanspec[], unsigned int n_chans,
++static int ni_m_series_ao_config_chanlist(struct comedi_device *dev,
++	struct comedi_subdevice *s, unsigned int chanspec[], unsigned int n_chans,
+ 	int timed)
+ {
+ 	unsigned int range;
+@@ -2869,7 +2869,7 @@ static int ni_m_series_ao_config_chanlist(struct comedi_device * dev,
+ 	return invert;
+ }
+ 
+-static int ni_old_ao_config_chanlist(struct comedi_device * dev, struct comedi_subdevice * s,
++static int ni_old_ao_config_chanlist(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int chanspec[], unsigned int n_chans)
+ {
+ 	unsigned int range;
+@@ -2912,7 +2912,7 @@ static int ni_old_ao_config_chanlist(struct comedi_device * dev, struct comedi_s
+ 	return invert;
+ }
+ 
+-static int ni_ao_config_chanlist(struct comedi_device * dev, struct comedi_subdevice * s,
++static int ni_ao_config_chanlist(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int chanspec[], unsigned int n_chans, int timed)
+ {
+ 	if (boardtype.reg_type & ni_reg_m_series_mask)
+@@ -2921,16 +2921,16 @@ static int ni_ao_config_chanlist(struct comedi_device * dev, struct comedi_subde
+ 	else
+ 		return ni_old_ao_config_chanlist(dev, s, chanspec, n_chans);
+ }
+-static int ni_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[0] = devpriv->ao[CR_CHAN(insn->chanspec)];
+ 
+ 	return 1;
+ }
+ 
+-static int ni_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int chan = CR_CHAN(insn->chanspec);
+ 	unsigned int invert;
+@@ -2948,8 +2948,8 @@ static int ni_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice
+ 	return 1;
+ }
+ 
+-static int ni_ao_insn_write_671x(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_ao_insn_write_671x(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int chan = CR_CHAN(insn->chanspec);
+ 	unsigned int invert;
+@@ -2965,8 +2965,8 @@ static int ni_ao_insn_write_671x(struct comedi_device * dev, struct comedi_subde
+ 	return 1;
+ }
+ 
+-static int ni_ao_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_ao_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	switch (data[0]) {
+ 	case INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE:
+@@ -2991,7 +2991,7 @@ static int ni_ao_insn_config(struct comedi_device * dev, struct comedi_subdevice
+ 	return -EINVAL;
+ }
+ 
+-static int ni_ao_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
++static int ni_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int trignum)
+ {
+ 	int ret;
+@@ -3062,7 +3062,7 @@ static int ni_ao_inttrig(struct comedi_device * dev, struct comedi_subdevice * s
+ 	return 0;
+ }
+ 
+-static int ni_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	const struct comedi_cmd *cmd = &s->async->cmd;
+ 	int bits;
+@@ -3261,8 +3261,8 @@ static int ni_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ni_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -3384,7 +3384,7 @@ static int ni_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s
+ 	return 0;
+ }
+ 
+-static int ni_ao_reset(struct comedi_device * dev, struct comedi_subdevice * s)
++static int ni_ao_reset(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	/* devpriv->ao0p=0x0000; */
+ 	/* ni_writew(devpriv->ao0p,AO_Configuration); */
+@@ -3436,8 +3436,8 @@ static int ni_ao_reset(struct comedi_device * dev, struct comedi_subdevice * s)
+ 
+ /* digital io */
+ 
+-static int ni_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ #ifdef DEBUG_DIO
+ 	rt_printk("ni_dio_insn_config() chan=%d io=%d\n",
+@@ -3468,8 +3468,8 @@ static int ni_dio_insn_config(struct comedi_device * dev, struct comedi_subdevic
+ 	return 1;
+ }
+ 
+-static int ni_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ #ifdef DEBUG_DIO
+ 	rt_printk("ni_dio_insn_bits() mask=0x%x bits=0x%x\n", data[0], data[1]);
+@@ -3495,8 +3495,8 @@ static int ni_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice
+ 	return 2;
+ }
+ 
+-static int ni_m_series_dio_insn_config(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++static int ni_m_series_dio_insn_config(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ #ifdef DEBUG_DIO
+ 	rt_printk("ni_m_series_dio_insn_config() chan=%d io=%d\n",
+@@ -3525,8 +3525,8 @@ static int ni_m_series_dio_insn_config(struct comedi_device * dev,
+ 	return 1;
+ }
+ 
+-static int ni_m_series_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_m_series_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ #ifdef DEBUG_DIO
+ 	rt_printk("ni_m_series_dio_insn_bits() mask=0x%x bits=0x%x\n", data[0],
+@@ -3544,8 +3544,8 @@ static int ni_m_series_dio_insn_bits(struct comedi_device * dev, struct comedi_s
+ 	return 2;
+ }
+ 
+-static int ni_cdio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int ni_cdio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -3653,7 +3653,7 @@ static int ni_cdio_cmdtest(struct comedi_device * dev, struct comedi_subdevice *
+ 	return 0;
+ }
+ 
+-static int ni_cdio_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	const struct comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned cdo_mode_bits = CDO_FIFO_Mode_Bit | CDO_Halt_On_Error_Bit;
+@@ -3690,7 +3690,7 @@ static int ni_cdio_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ni_cdo_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
++static int ni_cdo_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int trignum)
+ {
+ #ifdef PCIDMA
+@@ -3738,7 +3738,7 @@ static int ni_cdo_inttrig(struct comedi_device * dev, struct comedi_subdevice *
+ 	return retval;
+ }
+ 
+-static int ni_cdio_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int ni_cdio_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	ni_writel(CDO_Disarm_Bit | CDO_Error_Interrupt_Enable_Clear_Bit |
+ 		CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit |
+@@ -3753,7 +3753,7 @@ static int ni_cdio_cancel(struct comedi_device * dev, struct comedi_subdevice *
+ 	return 0;
+ }
+ 
+-static void handle_cdio_interrupt(struct comedi_device * dev)
++static void handle_cdio_interrupt(struct comedi_device *dev)
+ {
+ 	unsigned cdio_status;
+ 	struct comedi_subdevice *s = dev->subdevices + NI_DIO_SUBDEV;
+@@ -3794,8 +3794,8 @@ static void handle_cdio_interrupt(struct comedi_device * dev)
+ 	ni_event(dev, s);
+ }
+ 
+-static int ni_serial_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_serial_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int err = insn->n;
+ 	unsigned char byte_out, byte_in = 0;
+@@ -3888,7 +3888,7 @@ static int ni_serial_insn_config(struct comedi_device * dev, struct comedi_subde
+ 
+ }
+ 
+-static int ni_serial_hw_readwrite8(struct comedi_device * dev, struct comedi_subdevice * s,
++static int ni_serial_hw_readwrite8(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned char data_out, unsigned char *data_in)
+ {
+ 	unsigned int status1;
+@@ -3944,7 +3944,7 @@ static int ni_serial_hw_readwrite8(struct comedi_device * dev, struct comedi_sub
+ 	return err;
+ }
+ 
+-static int ni_serial_sw_readwrite8(struct comedi_device * dev, struct comedi_subdevice * s,
++static int ni_serial_sw_readwrite8(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned char data_out, unsigned char *data_in)
+ {
+ 	unsigned char mask, input = 0;
+@@ -3997,7 +3997,7 @@ static int ni_serial_sw_readwrite8(struct comedi_device * dev, struct comedi_sub
+ 	return 0;
+ }
+ 
+-static void mio_common_detach(struct comedi_device * dev)
++static void mio_common_detach(struct comedi_device *dev)
+ {
+ 	if (dev->private) {
+ 		if (devpriv->counter_dev) {
+@@ -4008,7 +4008,7 @@ static void mio_common_detach(struct comedi_device * dev)
+ 		subdev_8255_cleanup(dev, dev->subdevices + NI_8255_DIO_SUBDEV);
+ }
+ 
+-static void init_ao_67xx(struct comedi_device * dev, struct comedi_subdevice * s)
++static void init_ao_67xx(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	int i;
+ 
+@@ -4212,15 +4212,15 @@ static unsigned ni_gpct_read_register(struct ni_gpct *counter,
+ 	return 0;
+ }
+ 
+-static int ni_freq_out_insn_read(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++static int ni_freq_out_insn_read(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[0] = devpriv->clock_and_fout & FOUT_Divider_mask;
+ 	return 1;
+ }
+ 
+-static int ni_freq_out_insn_write(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++static int ni_freq_out_insn_write(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	devpriv->clock_and_fout &= ~FOUT_Enable;
+ 	devpriv->stc_writew(dev, devpriv->clock_and_fout,
+@@ -4233,7 +4233,7 @@ static int ni_freq_out_insn_write(struct comedi_device * dev,
+ 	return insn->n;
+ }
+ 
+-static int ni_set_freq_out_clock(struct comedi_device * dev, unsigned int clock_source)
++static int ni_set_freq_out_clock(struct comedi_device *dev, unsigned int clock_source)
+ {
+ 	switch (clock_source) {
+ 	case NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC:
+@@ -4250,8 +4250,8 @@ static int ni_set_freq_out_clock(struct comedi_device * dev, unsigned int clock_
+ 	return 3;
+ }
+ 
+-static void ni_get_freq_out_clock(struct comedi_device * dev, unsigned int * clock_source,
+-	unsigned int * clock_period_ns)
++static void ni_get_freq_out_clock(struct comedi_device *dev, unsigned int *clock_source,
++	unsigned int *clock_period_ns)
+ {
+ 	if (devpriv->clock_and_fout & FOUT_Timebase_Select) {
+ 		*clock_source = NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC;
+@@ -4262,8 +4262,8 @@ static void ni_get_freq_out_clock(struct comedi_device * dev, unsigned int * clo
+ 	}
+ }
+ 
+-static int ni_freq_out_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_freq_out_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	switch (data[0]) {
+ 	case INSN_CONFIG_SET_CLOCK_SRC:
+@@ -4278,7 +4278,7 @@ static int ni_freq_out_insn_config(struct comedi_device * dev, struct comedi_sub
+ 	return -EINVAL;
+ }
+ 
+-static int ni_alloc_private(struct comedi_device * dev)
++static int ni_alloc_private(struct comedi_device *dev)
+ {
+ 	int ret;
+ 
+@@ -4293,7 +4293,7 @@ static int ni_alloc_private(struct comedi_device * dev)
+ 	return 0;
+ };
+ 
+-static int ni_E_init(struct comedi_device * dev, struct comedi_devconfig * it)
++static int ni_E_init(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned j;
+@@ -4627,8 +4627,8 @@ static int ni_8255_callback(int dir, int port, int data, unsigned long arg)
+ 	presents the EEPROM as a subdevice
+ */
+ 
+-static int ni_eeprom_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_eeprom_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[0] = ni_read_eeprom(dev, CR_CHAN(insn->chanspec));
+ 
+@@ -4639,7 +4639,7 @@ static int ni_eeprom_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ 	reads bytes out of eeprom
+ */
+ 
+-static int ni_read_eeprom(struct comedi_device * dev, int addr)
++static int ni_read_eeprom(struct comedi_device *dev, int addr)
+ {
+ 	int bit;
+ 	int bitstring;
+@@ -4663,23 +4663,23 @@ static int ni_read_eeprom(struct comedi_device * dev, int addr)
+ 	return bitstring;
+ }
+ 
+-static int ni_m_series_eeprom_insn_read(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++static int ni_m_series_eeprom_insn_read(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[0] = devpriv->eeprom_buffer[CR_CHAN(insn->chanspec)];
+ 
+ 	return 1;
+ }
+ 
+-static int ni_get_pwm_config(struct comedi_device * dev, unsigned int * data)
++static int ni_get_pwm_config(struct comedi_device *dev, unsigned int *data)
+ {
+ 	data[1] = devpriv->pwm_up_count * devpriv->clock_ns;
+ 	data[2] = devpriv->pwm_down_count * devpriv->clock_ns;
+ 	return 3;
+ }
+ 
+-static int ni_m_series_pwm_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_m_series_pwm_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned up_count, down_count;
+ 	switch (data[0]) {
+@@ -4743,8 +4743,8 @@ static int ni_m_series_pwm_config(struct comedi_device * dev, struct comedi_subd
+ 	return 0;
+ }
+ 
+-static int ni_6143_pwm_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_6143_pwm_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned up_count, down_count;
+ 	switch (data[0]) {
+@@ -4806,20 +4806,20 @@ static int ni_6143_pwm_config(struct comedi_device * dev, struct comedi_subdevic
+ 	return 0;
+ }
+ 
+-static void ni_write_caldac(struct comedi_device * dev, int addr, int val);
++static void ni_write_caldac(struct comedi_device *dev, int addr, int val);
+ /*
+ 	calibration subdevice
+ */
+-static int ni_calib_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_calib_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	ni_write_caldac(dev, CR_CHAN(insn->chanspec), data[0]);
+ 
+ 	return 1;
+ }
+ 
+-static int ni_calib_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_calib_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[0] = devpriv->caldacs[CR_CHAN(insn->chanspec)];
+ 
+@@ -4849,7 +4849,7 @@ static struct caldac_struct caldacs[] = {
+ 	[ad8804_debug] = {16, 8, pack_ad8804},
+ };
+ 
+-static void caldac_setup(struct comedi_device * dev, struct comedi_subdevice * s)
++static void caldac_setup(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	int i, j;
+ 	int n_dacs;
+@@ -4902,7 +4902,7 @@ static void caldac_setup(struct comedi_device * dev, struct comedi_subdevice * s
+ 	}
+ }
+ 
+-static void ni_write_caldac(struct comedi_device * dev, int addr, int val)
++static void ni_write_caldac(struct comedi_device *dev, int addr, int val)
+ {
+ 	unsigned int loadbit = 0, bits = 0, bit, bitstring = 0;
+ 	int i;
+@@ -4989,7 +4989,7 @@ static int pack_ad8842(int addr, int val, int *bitstring)
+ /*
+  *	Read the GPCTs current value.
+  */
+-static int GPCT_G_Watch(struct comedi_device * dev, int chan)
++static int GPCT_G_Watch(struct comedi_device *dev, int chan)
+ {
+ 	unsigned int hi1, hi2, lo;
+ 
+@@ -5012,7 +5012,7 @@ static int GPCT_G_Watch(struct comedi_device * dev, int chan)
+ 	return (hi1 << 16) | lo;
+ }
+ 
+-static void GPCT_Reset(struct comedi_device * dev, int chan)
++static void GPCT_Reset(struct comedi_device *dev, int chan)
+ {
+ 	int temp_ack_reg = 0;
+ 
+@@ -5074,28 +5074,28 @@ static void GPCT_Reset(struct comedi_device * dev, int chan)
+ 
+ #endif
+ 
+-static int ni_gpct_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_gpct_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	struct ni_gpct *counter = s->private;
+ 	return ni_tio_insn_config(counter, insn, data);
+ }
+ 
+-static int ni_gpct_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_gpct_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	struct ni_gpct *counter = s->private;
+ 	return ni_tio_rinsn(counter, insn, data);
+ }
+ 
+-static int ni_gpct_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_gpct_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	struct ni_gpct *counter = s->private;
+ 	return ni_tio_winsn(counter, insn, data);
+ }
+ 
+-static int ni_gpct_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int ni_gpct_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	int retval;
+ #ifdef PCIDMA
+@@ -5118,8 +5118,8 @@ static int ni_gpct_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	return retval;
+ }
+ 
+-static int ni_gpct_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int ni_gpct_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ #ifdef PCIDMA
+ 	struct ni_gpct *counter = s->private;
+@@ -5130,7 +5130,7 @@ static int ni_gpct_cmdtest(struct comedi_device * dev, struct comedi_subdevice *
+ #endif
+ }
+ 
+-static int ni_gpct_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int ni_gpct_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ #ifdef PCIDMA
+ 	struct ni_gpct *counter = s->private;
+@@ -5151,7 +5151,7 @@ static int ni_gpct_cancel(struct comedi_device * dev, struct comedi_subdevice *
+  *
+  */
+ 
+-static int ni_m_series_set_pfi_routing(struct comedi_device * dev, unsigned chan,
++static int ni_m_series_set_pfi_routing(struct comedi_device *dev, unsigned chan,
+ 	unsigned source)
+ {
+ 	unsigned pfi_reg_index;
+@@ -5169,7 +5169,7 @@ static int ni_m_series_set_pfi_routing(struct comedi_device * dev, unsigned chan
+ 	return 2;
+ }
+ 
+-static int ni_old_set_pfi_routing(struct comedi_device * dev, unsigned chan,
++static int ni_old_set_pfi_routing(struct comedi_device *dev, unsigned chan,
+ 	unsigned source)
+ {
+ 	/*  pre-m-series boards have fixed signals on pfi pins */
+@@ -5178,7 +5178,7 @@ static int ni_old_set_pfi_routing(struct comedi_device * dev, unsigned chan,
+ 	return 2;
+ }
+ 
+-static int ni_set_pfi_routing(struct comedi_device * dev, unsigned chan,
++static int ni_set_pfi_routing(struct comedi_device *dev, unsigned chan,
+ 	unsigned source)
+ {
+ 	if (boardtype.reg_type & ni_reg_m_series_mask)
+@@ -5187,14 +5187,14 @@ static int ni_set_pfi_routing(struct comedi_device * dev, unsigned chan,
+ 		return ni_old_set_pfi_routing(dev, chan, source);
+ }
+ 
+-static unsigned ni_m_series_get_pfi_routing(struct comedi_device * dev, unsigned chan)
++static unsigned ni_m_series_get_pfi_routing(struct comedi_device *dev, unsigned chan)
+ {
+ 	const unsigned array_offset = chan / 3;
+ 	return MSeries_PFI_Output_Select_Source(chan,
+ 		devpriv->pfi_output_select_reg[array_offset]);
+ }
+ 
+-static unsigned ni_old_get_pfi_routing(struct comedi_device * dev, unsigned chan)
++static unsigned ni_old_get_pfi_routing(struct comedi_device *dev, unsigned chan)
+ {
+ 	/*  pre-m-series boards have fixed signals on pfi pins */
+ 	switch (chan) {
+@@ -5235,7 +5235,7 @@ static unsigned ni_old_get_pfi_routing(struct comedi_device * dev, unsigned chan
+ 	return 0;
+ }
+ 
+-static unsigned ni_get_pfi_routing(struct comedi_device * dev, unsigned chan)
++static unsigned ni_get_pfi_routing(struct comedi_device *dev, unsigned chan)
+ {
+ 	if (boardtype.reg_type & ni_reg_m_series_mask)
+ 		return ni_m_series_get_pfi_routing(dev, chan);
+@@ -5243,7 +5243,7 @@ static unsigned ni_get_pfi_routing(struct comedi_device * dev, unsigned chan)
+ 		return ni_old_get_pfi_routing(dev, chan);
+ }
+ 
+-static int ni_config_filter(struct comedi_device * dev, unsigned pfi_channel,
++static int ni_config_filter(struct comedi_device *dev, unsigned pfi_channel,
+ 	enum ni_pfi_filter_select filter)
+ {
+ 	unsigned bits;
+@@ -5257,8 +5257,8 @@ static int ni_config_filter(struct comedi_device * dev, unsigned pfi_channel,
+ 	return 0;
+ }
+ 
+-static int ni_pfi_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_pfi_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if ((boardtype.reg_type & ni_reg_m_series_mask) == 0) {
+ 		return -ENOTSUPP;
+@@ -5272,8 +5272,8 @@ static int ni_pfi_insn_bits(struct comedi_device * dev, struct comedi_subdevice
+ 	return 2;
+ }
+ 
+-static int ni_pfi_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_pfi_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int chan;
+ 
+@@ -5316,7 +5316,7 @@ static int ni_pfi_insn_config(struct comedi_device * dev, struct comedi_subdevic
+  *  NI RTSI Bus Functions
+  *
+  */
+-static void ni_rtsi_init(struct comedi_device * dev)
++static void ni_rtsi_init(struct comedi_device *dev)
+ {
+ 	/*  Initialises the RTSI bus signal switch to a default state */
+ 
+@@ -5351,8 +5351,8 @@ static void ni_rtsi_init(struct comedi_device * dev)
+ */
+ }
+ 
+-static int ni_rtsi_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_rtsi_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -5407,7 +5407,7 @@ static int ni_mseries_get_pll_parameters(unsigned reference_period_ns,
+ 	return 0;
+ }
+ 
+-static inline unsigned num_configurable_rtsi_channels(struct comedi_device * dev)
++static inline unsigned num_configurable_rtsi_channels(struct comedi_device *dev)
+ {
+ 	if (boardtype.reg_type & ni_reg_m_series_mask)
+ 		return 8;
+@@ -5415,7 +5415,7 @@ static inline unsigned num_configurable_rtsi_channels(struct comedi_device * dev
+ 		return 7;
+ }
+ 
+-static int ni_mseries_set_pll_master_clock(struct comedi_device * dev, unsigned source,
++static int ni_mseries_set_pll_master_clock(struct comedi_device *dev, unsigned source,
+ 	unsigned period_ns)
+ {
+ 	static const unsigned min_period_ns = 50;
+@@ -5512,7 +5512,7 @@ static int ni_mseries_set_pll_master_clock(struct comedi_device * dev, unsigned
+ 	return 3;
+ }
+ 
+-static int ni_set_master_clock(struct comedi_device * dev, unsigned source,
++static int ni_set_master_clock(struct comedi_device *dev, unsigned source,
+ 	unsigned period_ns)
+ {
+ 	if (source == NI_MIO_INTERNAL_CLOCK) {
+@@ -5556,7 +5556,7 @@ static int ni_set_master_clock(struct comedi_device * dev, unsigned source,
+ 	return 3;
+ }
+ 
+-static int ni_valid_rtsi_output_source(struct comedi_device * dev, unsigned chan,
++static int ni_valid_rtsi_output_source(struct comedi_device *dev, unsigned chan,
+ 	unsigned source)
+ {
+ 	if (chan >= num_configurable_rtsi_channels(dev)) {
+@@ -5597,7 +5597,7 @@ static int ni_valid_rtsi_output_source(struct comedi_device * dev, unsigned chan
+ 	}
+ }
+ 
+-static int ni_set_rtsi_routing(struct comedi_device * dev, unsigned chan,
++static int ni_set_rtsi_routing(struct comedi_device *dev, unsigned chan,
+ 	unsigned source)
+ {
+ 	if (ni_valid_rtsi_output_source(dev, chan, source) == 0)
+@@ -5618,7 +5618,7 @@ static int ni_set_rtsi_routing(struct comedi_device * dev, unsigned chan,
+ 	return 2;
+ }
+ 
+-static unsigned ni_get_rtsi_routing(struct comedi_device * dev, unsigned chan)
++static unsigned ni_get_rtsi_routing(struct comedi_device *dev, unsigned chan)
+ {
+ 	if (chan < 4) {
+ 		return RTSI_Trig_Output_Source(chan,
+@@ -5634,8 +5634,8 @@ static unsigned ni_get_rtsi_routing(struct comedi_device * dev, unsigned chan)
+ 	}
+ }
+ 
+-static int ni_rtsi_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ni_rtsi_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int chan = CR_CHAN(insn->chanspec);
+ 	switch (data[0]) {
+@@ -5706,7 +5706,7 @@ static int ni_rtsi_insn_config(struct comedi_device * dev, struct comedi_subdevi
+ 	return 1;
+ }
+ 
+-static int cs5529_wait_for_idle(struct comedi_device * dev)
++static int cs5529_wait_for_idle(struct comedi_device *dev)
+ {
+ 	unsigned short status;
+ 	const int timeout = HZ;
+@@ -5730,7 +5730,7 @@ static int cs5529_wait_for_idle(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static void cs5529_command(struct comedi_device * dev, unsigned short value)
++static void cs5529_command(struct comedi_device *dev, unsigned short value)
+ {
+ 	static const int timeout = 100;
+ 	int i;
+@@ -5752,7 +5752,7 @@ static void cs5529_command(struct comedi_device * dev, unsigned short value)
+ }
+ 
+ /* write to cs5529 register */
+-static void cs5529_config_write(struct comedi_device * dev, unsigned int value,
++static void cs5529_config_write(struct comedi_device *dev, unsigned int value,
+ 	unsigned int reg_select_bits)
+ {
+ 	ni_ao_win_outw(dev, ((value >> 16) & 0xff),
+@@ -5767,7 +5767,7 @@ static void cs5529_config_write(struct comedi_device * dev, unsigned int value,
+ 
+ #ifdef NI_CS5529_DEBUG
+ /* read from cs5529 register */
+-static unsigned int cs5529_config_read(struct comedi_device * dev,
++static unsigned int cs5529_config_read(struct comedi_device *dev,
+ 	unsigned int reg_select_bits)
+ {
+ 	unsigned int value;
+@@ -5783,7 +5783,7 @@ static unsigned int cs5529_config_read(struct comedi_device * dev,
+ }
+ #endif
+ 
+-static int cs5529_do_conversion(struct comedi_device * dev, unsigned short *data)
++static int cs5529_do_conversion(struct comedi_device *dev, unsigned short *data)
+ {
+ 	int retval;
+ 	unsigned short status;
+@@ -5813,8 +5813,8 @@ static int cs5529_do_conversion(struct comedi_device * dev, unsigned short *data
+ 	return 0;
+ }
+ 
+-static int cs5529_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int cs5529_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, retval;
+ 	unsigned short sample;
+@@ -5839,7 +5839,7 @@ static int cs5529_ai_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ 	return insn->n;
+ }
+ 
+-static int init_cs5529(struct comedi_device * dev)
++static int init_cs5529(struct comedi_device *dev)
+ {
+ 	unsigned int config_bits =
+ 		CSCFG_PORT_MODE | CSCFG_WORD_RATE_2180_CYCLES;
+diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c
+index eef01984ab2a..a0301c5e2907 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_cs.c
++++ b/drivers/staging/comedi/drivers/ni_mio_cs.c
+@@ -196,7 +196,7 @@ struct ni_private {
+  * read/written directly in the I/O space of the board.  The
+  * DAQCard devices map the low 8 STC registers to iobase+addr*2. */
+ 
+-static void mio_cs_win_out(struct comedi_device * dev, uint16_t data, int addr)
++static void mio_cs_win_out(struct comedi_device *dev, uint16_t data, int addr)
+ {
+ 	unsigned long flags;
+ 
+@@ -210,7 +210,7 @@ static void mio_cs_win_out(struct comedi_device * dev, uint16_t data, int addr)
+ 	comedi_spin_unlock_irqrestore(&devpriv->window_lock, flags);
+ }
+ 
+-static uint16_t mio_cs_win_in(struct comedi_device * dev, int addr)
++static uint16_t mio_cs_win_in(struct comedi_device *dev, int addr)
+ {
+ 	unsigned long flags;
+ 	uint16_t ret;
+@@ -227,8 +227,8 @@ static uint16_t mio_cs_win_in(struct comedi_device * dev, int addr)
+ 	return ret;
+ }
+ 
+-static int mio_cs_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int mio_cs_detach(struct comedi_device * dev);
++static int mio_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int mio_cs_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_ni_mio_cs = {
+       driver_name:"ni_mio_cs",
+       module:THIS_MODULE,
+@@ -238,11 +238,11 @@ static struct comedi_driver driver_ni_mio_cs = {
+ 
+ #include "ni_mio_common.c"
+ 
+-static int ni_getboardtype(struct comedi_device * dev, struct pcmcia_device *link);
++static int ni_getboardtype(struct comedi_device *dev, struct pcmcia_device *link);
+ 
+ /* clean up allocated resources */
+ /* called when driver is removed */
+-static int mio_cs_detach(struct comedi_device * dev)
++static int mio_cs_detach(struct comedi_device *dev)
+ {
+ 	mio_common_detach(dev);
+ 
+@@ -403,7 +403,7 @@ static void mio_cs_config(struct pcmcia_device *link)
+ 	link->dev_node = &dev_node;
+ }
+ 
+-static int mio_cs_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int mio_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct pcmcia_device *link;
+ 	unsigned int irq;
+@@ -468,7 +468,7 @@ static int mio_cs_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	return 0;
+ }
+ 
+-static int get_prodid(struct comedi_device * dev, struct pcmcia_device *link)
++static int get_prodid(struct comedi_device *dev, struct pcmcia_device *link)
+ {
+ 	tuple_t tuple;
+ 	u_short buf[128];
+@@ -487,7 +487,7 @@ static int get_prodid(struct comedi_device * dev, struct pcmcia_device *link)
+ 	return prodid;
+ }
+ 
+-static int ni_getboardtype(struct comedi_device * dev, struct pcmcia_device *link)
++static int ni_getboardtype(struct comedi_device *dev, struct pcmcia_device *link)
+ {
+ 	int id;
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
+index 55c7ad439180..ffd619b0916c 100644
+--- a/drivers/staging/comedi/drivers/ni_pcidio.c
++++ b/drivers/staging/comedi/drivers/ni_pcidio.c
+@@ -287,9 +287,9 @@ enum FPGA_Control_Bits {
+ #define IntEn (TransferReady|CountExpired|Waited|PrimaryTC|SecondaryTC)
+ #endif
+ 
+-static int nidio_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int nidio_detach(struct comedi_device * dev);
+-static int ni_pcidio_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
++static int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int nidio_detach(struct comedi_device *dev);
++static int ni_pcidio_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
+ 
+ static struct comedi_driver driver_pcidio = {
+       driver_name:"ni_pcidio",
+@@ -401,14 +401,14 @@ struct nidio96_private {
+ };
+ #define devpriv ((struct nidio96_private *)dev->private)
+ 
+-static int ni_pcidio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd);
+-static int ni_pcidio_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int ni_pcidio_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
++static int ni_pcidio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd);
++static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
++static int ni_pcidio_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int trignum);
+-static int nidio_find_device(struct comedi_device * dev, int bus, int slot);
++static int nidio_find_device(struct comedi_device *dev, int bus, int slot);
+ static int ni_pcidio_ns_to_timer(int *nanosec, int round_mode);
+-static int setup_mite_dma(struct comedi_device * dev, struct comedi_subdevice * s);
++static int setup_mite_dma(struct comedi_device *dev, struct comedi_subdevice *s);
+ 
+ #ifdef DEBUG_FLAGS
+ static void ni_pcidio_print_flags(unsigned int flags);
+@@ -418,7 +418,7 @@ static void ni_pcidio_print_status(unsigned int status);
+ #define ni_pcidio_print_status(x)
+ #endif
+ 
+-static int ni_pcidio_request_di_mite_channel(struct comedi_device * dev)
++static int ni_pcidio_request_di_mite_channel(struct comedi_device *dev)
+ {
+ 	unsigned long flags;
+ 
+@@ -441,7 +441,7 @@ static int ni_pcidio_request_di_mite_channel(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static void ni_pcidio_release_di_mite_channel(struct comedi_device * dev)
++static void ni_pcidio_release_di_mite_channel(struct comedi_device *dev)
+ {
+ 	unsigned long flags;
+ 
+@@ -469,7 +469,7 @@ static int nidio96_8255_cb(int dir, int port, int data, unsigned long iobase)
+ 	}
+ }
+ 
+-void ni_pcidio_event(struct comedi_device * dev, struct comedi_subdevice * s)
++void ni_pcidio_event(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	if (s->async->
+ 		events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW))
+diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
+index 752092b069d7..3447d5875533 100644
+--- a/drivers/staging/comedi/drivers/ni_pcimio.c
++++ b/drivers/staging/comedi/drivers/ni_pcimio.c
+@@ -1207,8 +1207,8 @@ static const struct ni_board_struct ni_boards[] = {
+ 
+ #define n_pcimio_boards ((sizeof(ni_boards)/sizeof(ni_boards[0])))
+ 
+-static int pcimio_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pcimio_detach(struct comedi_device * dev);
++static int pcimio_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pcimio_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_pcimio = {
+ 	driver_name: DRV_NAME,
+ 	module:THIS_MODULE,
+@@ -1242,7 +1242,7 @@ struct ni_private {
+ /* However, the 611x boards still aren't working, so I'm disabling
+  * non-windowed STC access temporarily */
+ 
+-static void e_series_win_out(struct comedi_device * dev, uint16_t data, int reg)
++static void e_series_win_out(struct comedi_device *dev, uint16_t data, int reg)
+ {
+ 	unsigned long flags;
+ 
+@@ -1252,7 +1252,7 @@ static void e_series_win_out(struct comedi_device * dev, uint16_t data, int reg)
+ 	comedi_spin_unlock_irqrestore(&devpriv->window_lock, flags);
+ }
+ 
+-static uint16_t e_series_win_in(struct comedi_device * dev, int reg)
++static uint16_t e_series_win_in(struct comedi_device *dev, int reg)
+ {
+ 	unsigned long flags;
+ 	uint16_t ret;
+@@ -1265,7 +1265,7 @@ static uint16_t e_series_win_in(struct comedi_device * dev, int reg)
+ 	return ret;
+ }
+ 
+-static void m_series_stc_writew(struct comedi_device * dev, uint16_t data, int reg)
++static void m_series_stc_writew(struct comedi_device *dev, uint16_t data, int reg)
+ {
+ 	unsigned offset;
+ 	switch (reg) {
+@@ -1420,7 +1420,7 @@ static void m_series_stc_writew(struct comedi_device * dev, uint16_t data, int r
+ 	ni_writew(data, offset);
+ }
+ 
+-static uint16_t m_series_stc_readw(struct comedi_device * dev, int reg)
++static uint16_t m_series_stc_readw(struct comedi_device *dev, int reg)
+ {
+ 	unsigned offset;
+ 	switch (reg) {
+@@ -1455,7 +1455,7 @@ static uint16_t m_series_stc_readw(struct comedi_device * dev, int reg)
+ 	return ni_readw(offset);
+ }
+ 
+-static void m_series_stc_writel(struct comedi_device * dev, uint32_t data, int reg)
++static void m_series_stc_writel(struct comedi_device *dev, uint32_t data, int reg)
+ {
+ 	unsigned offset;
+ 	switch (reg) {
+@@ -1496,7 +1496,7 @@ static void m_series_stc_writel(struct comedi_device * dev, uint32_t data, int r
+ 	ni_writel(data, offset);
+ }
+ 
+-static uint32_t m_series_stc_readl(struct comedi_device * dev, int reg)
++static uint32_t m_series_stc_readl(struct comedi_device *dev, int reg)
+ {
+ 	unsigned offset;
+ 	switch (reg) {
+@@ -1529,19 +1529,19 @@ static uint32_t m_series_stc_readl(struct comedi_device * dev, int reg)
+ 
+ #include "ni_mio_common.c"
+ 
+-static int pcimio_find_device(struct comedi_device * dev, int bus, int slot);
+-static int pcimio_ai_change(struct comedi_device * dev, struct comedi_subdevice * s,
++static int pcimio_find_device(struct comedi_device *dev, int bus, int slot);
++static int pcimio_ai_change(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned long new_size);
+-static int pcimio_ao_change(struct comedi_device * dev, struct comedi_subdevice * s,
++static int pcimio_ao_change(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned long new_size);
+-static int pcimio_gpct0_change(struct comedi_device * dev, struct comedi_subdevice * s,
++static int pcimio_gpct0_change(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned long new_size);
+-static int pcimio_gpct1_change(struct comedi_device * dev, struct comedi_subdevice * s,
++static int pcimio_gpct1_change(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned long new_size);
+-static int pcimio_dio_change(struct comedi_device * dev, struct comedi_subdevice * s,
++static int pcimio_dio_change(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned long new_size);
+ 
+-static void m_series_init_eeprom_buffer(struct comedi_device * dev)
++static void m_series_init_eeprom_buffer(struct comedi_device *dev)
+ {
+ 	static const int Start_Cal_EEPROM = 0x400;
+ 	static const unsigned window_size = 10;
+@@ -1578,7 +1578,7 @@ static void m_series_init_eeprom_buffer(struct comedi_device * dev)
+ 	writel(0x0, devpriv->mite->mite_io_addr + 0x30);
+ }
+ 
+-static void init_6143(struct comedi_device * dev)
++static void init_6143(struct comedi_device *dev)
+ {
+ 	/*  Disable interrupts */
+ 	devpriv->stc_writew(dev, 0, Interrupt_Control_Register);
+@@ -1598,7 +1598,7 @@ static void init_6143(struct comedi_device * dev)
+ }
+ 
+ /* cleans up allocated resources */
+-static int pcimio_detach(struct comedi_device * dev)
++static int pcimio_detach(struct comedi_device *dev)
+ {
+ 	mio_common_detach(dev);
+ 	if (dev->irq) {
+@@ -1617,7 +1617,7 @@ static int pcimio_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int pcimio_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pcimio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int ret;
+ 
+@@ -1700,7 +1700,7 @@ static int pcimio_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	return ret;
+ }
+ 
+-static int pcimio_find_device(struct comedi_device * dev, int bus, int slot)
++static int pcimio_find_device(struct comedi_device *dev, int bus, int slot)
+ {
+ 	struct mite_struct *mite;
+ 	int i;
+@@ -1728,7 +1728,7 @@ static int pcimio_find_device(struct comedi_device * dev, int bus, int slot)
+ 	return -EIO;
+ }
+ 
+-static int pcimio_ai_change(struct comedi_device * dev, struct comedi_subdevice * s,
++static int pcimio_ai_change(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned long new_size)
+ {
+ 	int ret;
+@@ -1740,7 +1740,7 @@ static int pcimio_ai_change(struct comedi_device * dev, struct comedi_subdevice
+ 	return 0;
+ }
+ 
+-static int pcimio_ao_change(struct comedi_device * dev, struct comedi_subdevice * s,
++static int pcimio_ao_change(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned long new_size)
+ {
+ 	int ret;
+@@ -1752,7 +1752,7 @@ static int pcimio_ao_change(struct comedi_device * dev, struct comedi_subdevice
+ 	return 0;
+ }
+ 
+-static int pcimio_gpct0_change(struct comedi_device * dev, struct comedi_subdevice * s,
++static int pcimio_gpct0_change(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned long new_size)
+ {
+ 	int ret;
+@@ -1764,7 +1764,7 @@ static int pcimio_gpct0_change(struct comedi_device * dev, struct comedi_subdevi
+ 	return 0;
+ }
+ 
+-static int pcimio_gpct1_change(struct comedi_device * dev, struct comedi_subdevice * s,
++static int pcimio_gpct1_change(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned long new_size)
+ {
+ 	int ret;
+@@ -1776,7 +1776,7 @@ static int pcimio_gpct1_change(struct comedi_device * dev, struct comedi_subdevi
+ 	return 0;
+ }
+ 
+-static int pcimio_dio_change(struct comedi_device * dev, struct comedi_subdevice * s,
++static int pcimio_dio_change(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned long new_size)
+ {
+ 	int ret;
+diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c
+index 7457b4ffbe8c..bdb232635abd 100644
+--- a/drivers/staging/comedi/drivers/ni_tio.c
++++ b/drivers/staging/comedi/drivers/ni_tio.c
+@@ -279,9 +279,9 @@ static void __exit ni_tio_cleanup_module(void)
+ module_exit(ni_tio_cleanup_module);
+ 
+ struct ni_gpct_device *ni_gpct_device_construct(struct comedi_device * dev,
+-	void (*write_register) (struct ni_gpct * counter, unsigned bits,
++	void (*write_register) (struct ni_gpct *counter, unsigned bits,
+ 		enum ni_gpct_register reg),
+-	unsigned (*read_register) (struct ni_gpct * counter,
++	unsigned (*read_register) (struct ni_gpct *counter,
+ 		enum ni_gpct_register reg), enum ni_gpct_variant variant,
+ 	unsigned num_counters)
+ {
+@@ -965,7 +965,7 @@ static uint64_t ni_tio_clock_period_ps(const struct ni_gpct *counter,
+ }
+ 
+ static void ni_tio_get_clock_src(struct ni_gpct *counter,
+-	unsigned int * clock_source, unsigned int * period_ns)
++	unsigned int *clock_source, unsigned int *period_ns)
+ {
+ 	static const unsigned pico_per_nano = 1000;
+ 	uint64_t temp64;
+@@ -1442,7 +1442,7 @@ static unsigned ni_m_series_second_gate_to_generic_gate_source(unsigned
+ };
+ 
+ static int ni_tio_get_gate_src(struct ni_gpct *counter, unsigned gate_index,
+-	unsigned int * gate_source)
++	unsigned int *gate_source)
+ {
+ 	struct ni_gpct_device *counter_dev = counter->counter_dev;
+ 	const unsigned mode_bits = ni_tio_get_soft_copy(counter,
+@@ -1534,7 +1534,7 @@ static int ni_tio_get_gate_src(struct ni_gpct *counter, unsigned gate_index,
+ }
+ 
+ int ni_tio_insn_config(struct ni_gpct *counter,
+-	struct comedi_insn * insn, unsigned int * data)
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	switch (data[0]) {
+ 	case INSN_CONFIG_SET_COUNTER_MODE:
+diff --git a/drivers/staging/comedi/drivers/ni_tio.h b/drivers/staging/comedi/drivers/ni_tio.h
+index f9e7b8343aef..3aacfe2f2420 100644
+--- a/drivers/staging/comedi/drivers/ni_tio.h
++++ b/drivers/staging/comedi/drivers/ni_tio.h
+@@ -120,9 +120,9 @@ struct ni_gpct {
+ 
+ struct ni_gpct_device {
+ 	struct comedi_device *dev;
+-	void (*write_register) (struct ni_gpct * counter, unsigned bits,
++	void (*write_register) (struct ni_gpct *counter, unsigned bits,
+ 		enum ni_gpct_register reg);
+-	unsigned (*read_register) (struct ni_gpct * counter,
++	unsigned (*read_register) (struct ni_gpct *counter,
+ 		enum ni_gpct_register reg);
+ 	enum ni_gpct_variant variant;
+ 	struct ni_gpct *counters;
+@@ -132,24 +132,24 @@ struct ni_gpct_device {
+ };
+ 
+ extern struct ni_gpct_device *ni_gpct_device_construct(struct comedi_device * dev,
+-	void (*write_register) (struct ni_gpct * counter, unsigned bits,
++	void (*write_register) (struct ni_gpct *counter, unsigned bits,
+ 		enum ni_gpct_register reg),
+-	unsigned (*read_register) (struct ni_gpct * counter,
++	unsigned (*read_register) (struct ni_gpct *counter,
+ 		enum ni_gpct_register reg), enum ni_gpct_variant variant,
+ 	unsigned num_counters);
+ extern void ni_gpct_device_destroy(struct ni_gpct_device *counter_dev);
+ extern void ni_tio_init_counter(struct ni_gpct *counter);
+ extern int ni_tio_rinsn(struct ni_gpct *counter,
+-	struct comedi_insn * insn, unsigned int * data);
++	struct comedi_insn *insn, unsigned int *data);
+ extern int ni_tio_insn_config(struct ni_gpct *counter,
+-	struct comedi_insn * insn, unsigned int * data);
++	struct comedi_insn *insn, unsigned int *data);
+ extern int ni_tio_winsn(struct ni_gpct *counter,
+-	struct comedi_insn * insn, unsigned int * data);
++	struct comedi_insn *insn, unsigned int *data);
+ extern int ni_tio_cmd(struct ni_gpct *counter, struct comedi_async *async);
+ extern int ni_tio_cmdtest(struct ni_gpct *counter, struct comedi_cmd * cmd);
+ extern int ni_tio_cancel(struct ni_gpct *counter);
+ extern void ni_tio_handle_interrupt(struct ni_gpct *counter,
+-	struct comedi_subdevice * s);
++	struct comedi_subdevice *s);
+ extern void ni_tio_set_mite_channel(struct ni_gpct *counter,
+ 	struct mite_channel *mite_chan);
+ extern void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter,
+diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c
+index a3c55979cf4c..fcf4eb6cdf60 100644
+--- a/drivers/staging/comedi/drivers/ni_tiocmd.c
++++ b/drivers/staging/comedi/drivers/ni_tiocmd.c
+@@ -96,7 +96,7 @@ static void ni_tio_configure_dma(struct ni_gpct *counter, short enable,
+ 	}
+ }
+ 
+-static int ni_tio_input_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
++static int ni_tio_input_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int trignum)
+ {
+ 	unsigned long flags;
+diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c
+index 7b99471a4369..73b56b36d7c7 100644
+--- a/drivers/staging/comedi/drivers/pcl711.c
++++ b/drivers/staging/comedi/drivers/pcl711.c
+@@ -156,8 +156,8 @@ static const struct pcl711_board boardtypes[] = {
+ #define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl711_board))
+ #define this_board ((const struct pcl711_board *)dev->board_ptr)
+ 
+-static int pcl711_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pcl711_detach(struct comedi_device * dev);
++static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pcl711_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_pcl711 = {
+       driver_name:"pcl711",
+       module:THIS_MODULE,
+@@ -217,7 +217,7 @@ static irqreturn_t pcl711_interrupt(int irq, void *d)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static void pcl711_set_changain(struct comedi_device * dev, int chan)
++static void pcl711_set_changain(struct comedi_device *dev, int chan)
+ {
+ 	int chan_register;
+ 
+@@ -244,8 +244,8 @@ static void pcl711_set_changain(struct comedi_device * dev, int chan)
+ 	}
+ }
+ 
+-static int pcl711_ai_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcl711_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, n;
+ 	int hi, lo;
+@@ -283,8 +283,8 @@ static int pcl711_ai_insn(struct comedi_device * dev, struct comedi_subdevice *
+ 	return n;
+ }
+ 
+-static int pcl711_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int pcl711_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int tmp;
+ 	int err = 0;
+@@ -385,7 +385,7 @@ static int pcl711_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice
+ 	return 0;
+ }
+ 
+-static int pcl711_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pcl711_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	int timer1, timer2;
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+@@ -431,8 +431,8 @@ static int pcl711_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s
+ /*
+    analog output
+ */
+-static int pcl711_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcl711_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -449,8 +449,8 @@ static int pcl711_ao_insn(struct comedi_device * dev, struct comedi_subdevice *
+ 	return n;
+ }
+ 
+-static int pcl711_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcl711_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -464,8 +464,8 @@ static int pcl711_ao_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ /* Digital port read - Untested on 8112 */
+-static int pcl711_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcl711_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -477,8 +477,8 @@ static int pcl711_di_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ /* Digital port write - Untested on 8112 */
+-static int pcl711_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcl711_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -498,7 +498,7 @@ static int pcl711_do_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ /*  Free any resources that we have claimed  */
+-static int pcl711_detach(struct comedi_device * dev)
++static int pcl711_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: pcl711: remove\n", dev->minor);
+ 
+@@ -512,7 +512,7 @@ static int pcl711_detach(struct comedi_device * dev)
+ }
+ 
+ /*  Initialization */
+-static int pcl711_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int ret;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c
+index 1f7763b2b653..75ab137ce36f 100644
+--- a/drivers/staging/comedi/drivers/pcl724.c
++++ b/drivers/staging/comedi/drivers/pcl724.c
+@@ -56,8 +56,8 @@ See the source for configuration details.
+ 
+ /* #define PCL724_IRQ   1  no IRQ support now */
+ 
+-static int pcl724_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pcl724_detach(struct comedi_device * dev);
++static int pcl724_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pcl724_detach(struct comedi_device *dev);
+ 
+ struct pcl724_board {
+ 
+@@ -124,7 +124,7 @@ static int subdev_8255mapped_cb(int dir, int port, int data,
+ 	}
+ }
+ 
+-static int pcl724_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pcl724_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	unsigned long iobase;
+ 	unsigned int iorange;
+@@ -200,7 +200,7 @@ static int pcl724_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	return 0;
+ }
+ 
+-static int pcl724_detach(struct comedi_device * dev)
++static int pcl724_detach(struct comedi_device *dev)
+ {
+ 	int i;
+ 
+diff --git a/drivers/staging/comedi/drivers/pcl725.c b/drivers/staging/comedi/drivers/pcl725.c
+index 0766ba02bd03..0941dc157a8f 100644
+--- a/drivers/staging/comedi/drivers/pcl725.c
++++ b/drivers/staging/comedi/drivers/pcl725.c
+@@ -20,8 +20,8 @@ Devices: [Advantech] PCL-725 (pcl725)
+ #define PCL725_DO 0
+ #define PCL725_DI 1
+ 
+-static int pcl725_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pcl725_detach(struct comedi_device * dev);
++static int pcl725_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pcl725_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_pcl725 = {
+       driver_name:"pcl725",
+       module:THIS_MODULE,
+@@ -31,8 +31,8 @@ static struct comedi_driver driver_pcl725 = {
+ 
+ COMEDI_INITCLEANUP(driver_pcl725);
+ 
+-static int pcl725_do_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcl725_do_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -48,8 +48,8 @@ static int pcl725_do_insn(struct comedi_device * dev, struct comedi_subdevice *
+ 	return 2;
+ }
+ 
+-static int pcl725_di_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcl725_di_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -59,7 +59,7 @@ static int pcl725_di_insn(struct comedi_device * dev, struct comedi_subdevice *
+ 	return 2;
+ }
+ 
+-static int pcl725_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pcl725_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+@@ -100,7 +100,7 @@ static int pcl725_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	return 0;
+ }
+ 
+-static int pcl725_detach(struct comedi_device * dev)
++static int pcl725_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: pcl725: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c
+index c92ffca0b9ab..7c9112b0fdca 100644
+--- a/drivers/staging/comedi/drivers/pcl726.c
++++ b/drivers/staging/comedi/drivers/pcl726.c
+@@ -111,8 +111,8 @@ static const struct comedi_lrange *const rangelist_728[] = {
+ 	&range_4_20mA, &range_0_20mA
+ };
+ 
+-static int pcl726_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pcl726_detach(struct comedi_device * dev);
++static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pcl726_detach(struct comedi_device *dev);
+ 
+ struct pcl726_board {
+ 
+@@ -172,8 +172,8 @@ struct pcl726_private {
+ 
+ #define devpriv ((struct pcl726_private *)dev->private)
+ 
+-static int pcl726_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcl726_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int hi, lo;
+ 	int n;
+@@ -197,8 +197,8 @@ static int pcl726_ao_insn(struct comedi_device * dev, struct comedi_subdevice *
+ 	return n;
+ }
+ 
+-static int pcl726_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcl726_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	int n;
+@@ -209,8 +209,8 @@ static int pcl726_ao_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ 	return n;
+ }
+ 
+-static int pcl726_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcl726_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -221,8 +221,8 @@ static int pcl726_di_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+ 	return 2;
+ }
+ 
+-static int pcl726_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcl726_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -241,7 +241,7 @@ static int pcl726_do_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+ 	return 2;
+ }
+ 
+-static int pcl726_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+@@ -360,7 +360,7 @@ static int pcl726_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	return 0;
+ }
+ 
+-static int pcl726_detach(struct comedi_device * dev)
++static int pcl726_detach(struct comedi_device *dev)
+ {
+ /* printk("comedi%d: pcl726: remove\n",dev->minor); */
+ 
+diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c
+index c411a16f71d2..ca18cf08358d 100644
+--- a/drivers/staging/comedi/drivers/pcl730.c
++++ b/drivers/staging/comedi/drivers/pcl730.c
+@@ -26,8 +26,8 @@ The ACL-7130 card have an 8254 timer/counter not supported by this driver.
+ #define PCL730_DIO_LO	2	/* TTL Digital I/O low byte (D0-D7) */
+ #define PCL730_DIO_HI	3	/* TTL Digital I/O high byte (D8-D15) */
+ 
+-static int pcl730_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pcl730_detach(struct comedi_device * dev);
++static int pcl730_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pcl730_detach(struct comedi_device *dev);
+ 
+ struct pcl730_board {
+ 
+@@ -57,8 +57,8 @@ static struct comedi_driver driver_pcl730 = {
+ 
+ COMEDI_INITCLEANUP(driver_pcl730);
+ 
+-static int pcl730_do_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcl730_do_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -79,8 +79,8 @@ static int pcl730_do_insn(struct comedi_device * dev, struct comedi_subdevice *
+ 	return 2;
+ }
+ 
+-static int pcl730_di_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcl730_di_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -91,7 +91,7 @@ static int pcl730_di_insn(struct comedi_device * dev, struct comedi_subdevice *
+ 	return 2;
+ }
+ 
+-static int pcl730_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pcl730_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+@@ -157,7 +157,7 @@ static int pcl730_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	return 0;
+ }
+ 
+-static int pcl730_detach(struct comedi_device * dev)
++static int pcl730_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: pcl730: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
+index dc1a1e4a303f..1f6f3e8b4185 100644
+--- a/drivers/staging/comedi/drivers/pcl812.c
++++ b/drivers/staging/comedi/drivers/pcl812.c
+@@ -292,8 +292,8 @@ static const struct comedi_lrange range_a821pgh_ai = { 4, {
+ 	}
+ };
+ 
+-static int pcl812_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pcl812_detach(struct comedi_device * dev);
++static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pcl812_detach(struct comedi_device *dev);
+ 
+ struct pcl812_board {
+ 
+@@ -429,16 +429,16 @@ struct pcl812_private {
+ /*
+ ==============================================================================
+ */
+-static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
++static void start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1,
+ 	unsigned int divisor2);
+-static void setup_range_channel(struct comedi_device * dev, struct comedi_subdevice * s,
++static void setup_range_channel(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int rangechan, char wait);
+-static int pcl812_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
++static int pcl812_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
+ /*
+ ==============================================================================
+ */
+-static int pcl812_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcl812_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	int timeout, hi;
+@@ -471,8 +471,8 @@ static int pcl812_ai_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ /*
+ ==============================================================================
+ */
+-static int acl8216_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int acl8216_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	int timeout;
+@@ -507,8 +507,8 @@ static int acl8216_ai_insn_read(struct comedi_device * dev, struct comedi_subdev
+ /*
+ ==============================================================================
+ */
+-static int pcl812_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcl812_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	int i;
+@@ -527,8 +527,8 @@ static int pcl812_ao_insn_write(struct comedi_device * dev, struct comedi_subdev
+ /*
+ ==============================================================================
+ */
+-static int pcl812_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcl812_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	int i;
+@@ -543,8 +543,8 @@ static int pcl812_ao_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ /*
+ ==============================================================================
+ */
+-static int pcl812_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcl812_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -558,8 +558,8 @@ static int pcl812_di_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+ /*
+ ==============================================================================
+ */
+-static int pcl812_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcl812_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -579,7 +579,7 @@ static int pcl812_do_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+ /*
+ ==============================================================================
+ */
+-static void pcl812_cmdtest_out(int e, struct comedi_cmd * cmd)
++static void pcl812_cmdtest_out(int e, struct comedi_cmd *cmd)
+ {
+ 	rt_printk("pcl812 e=%d startsrc=%x scansrc=%x convsrc=%x\n", e,
+ 		cmd->start_src, cmd->scan_begin_src, cmd->convert_src);
+@@ -595,8 +595,8 @@ static void pcl812_cmdtest_out(int e, struct comedi_cmd * cmd)
+ /*
+ ==============================================================================
+ */
+-static int pcl812_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int pcl812_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp, divisor1, divisor2;
+@@ -774,7 +774,7 @@ static int pcl812_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice
+ /*
+ ==============================================================================
+ */
+-static int pcl812_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	unsigned int divisor1 = 0, divisor2 = 0, i, dma_flags, bytes;
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+@@ -984,8 +984,8 @@ static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d)
+ /*
+ ==============================================================================
+ */
+-static void transfer_from_dma_buf(struct comedi_device * dev, struct comedi_subdevice * s,
+-	short * ptr, unsigned int bufptr, unsigned int len)
++static void transfer_from_dma_buf(struct comedi_device *dev, struct comedi_subdevice *s,
++	short *ptr, unsigned int bufptr, unsigned int len)
+ {
+ 	unsigned int i;
+ 
+@@ -1079,7 +1079,7 @@ static irqreturn_t interrupt_pcl812(int irq, void *d)
+ /*
+ ==============================================================================
+ */
+-static int pcl812_ai_poll(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pcl812_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	unsigned long flags;
+ 	unsigned int top1, top2, i;
+@@ -1123,7 +1123,7 @@ static int pcl812_ai_poll(struct comedi_device * dev, struct comedi_subdevice *
+ /*
+ ==============================================================================
+ */
+-static void setup_range_channel(struct comedi_device * dev, struct comedi_subdevice * s,
++static void setup_range_channel(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int rangechan, char wait)
+ {
+ 	unsigned char chan_reg = CR_CHAN(rangechan);	/*  normal board */
+@@ -1159,7 +1159,7 @@ static void setup_range_channel(struct comedi_device * dev, struct comedi_subdev
+ /*
+ ==============================================================================
+ */
+-static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
++static void start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1,
+ 	unsigned int divisor2)
+ {
+ #ifdef PCL812_EXTDEBUG
+@@ -1184,7 +1184,7 @@ static void start_pacer(struct comedi_device * dev, int mode, unsigned int divis
+ /*
+ ==============================================================================
+ */
+-static void free_resources(struct comedi_device * dev)
++static void free_resources(struct comedi_device *dev)
+ {
+ 
+ 	if (dev->private) {
+@@ -1204,7 +1204,7 @@ static void free_resources(struct comedi_device * dev)
+ /*
+ ==============================================================================
+ */
+-static int pcl812_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pcl812_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ #ifdef PCL812_EXTDEBUG
+ 	rt_printk("pcl812 EDBG: BGN: pcl812_ai_cancel(...)\n");
+@@ -1224,7 +1224,7 @@ static int pcl812_ai_cancel(struct comedi_device * dev, struct comedi_subdevice
+ /*
+ ==============================================================================
+ */
+-static void pcl812_reset(struct comedi_device * dev)
++static void pcl812_reset(struct comedi_device *dev)
+ {
+ #ifdef PCL812_EXTDEBUG
+ 	rt_printk("pcl812 EDBG: BGN: pcl812_reset(...)\n");
+@@ -1266,7 +1266,7 @@ static void pcl812_reset(struct comedi_device * dev)
+ /*
+ ==============================================================================
+ */
+-static int pcl812_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int ret, subdev;
+ 	unsigned long iobase;
+@@ -1594,7 +1594,7 @@ static int pcl812_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ /*
+ ==============================================================================
+  */
+-static int pcl812_detach(struct comedi_device * dev)
++static int pcl812_detach(struct comedi_device *dev)
+ {
+ 
+ #ifdef PCL812_EXTDEBUG
+diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
+index 2241fa9f5b63..f44bd43f5d3f 100644
+--- a/drivers/staging/comedi/drivers/pcl816.c
++++ b/drivers/staging/comedi/drivers/pcl816.c
+@@ -148,8 +148,8 @@ static const struct pcl816_board boardtypes[] = {
+ #define devpriv ((struct pcl816_private *)dev->private)
+ #define this_board ((const struct pcl816_board *)dev->board_ptr)
+ 
+-static int pcl816_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pcl816_detach(struct comedi_device * dev);
++static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pcl816_detach(struct comedi_device *dev);
+ 
+ #ifdef unused
+ static int RTC_lock = 0;	/* RTC lock */
+@@ -213,25 +213,25 @@ struct pcl816_private {
+ /*
+ ==============================================================================
+ */
+-static int check_and_setup_channel_list(struct comedi_device * dev,
+-	struct comedi_subdevice * s, unsigned int *chanlist, int chanlen);
+-static int pcl816_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+-static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
++static int check_and_setup_channel_list(struct comedi_device *dev,
++	struct comedi_subdevice *s, unsigned int *chanlist, int chanlen);
++static int pcl816_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
++static void start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1,
+ 	unsigned int divisor2);
+ #ifdef unused
+ static int set_rtc_irq_bit(unsigned char bit);
+ #endif
+ 
+-static int pcl816_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd);
+-static int pcl816_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
++static int pcl816_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd);
++static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
+ 
+ /*
+ ==============================================================================
+    ANALOG INPUT MODE0, 816 cards, slow version
+ */
+-static int pcl816_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcl816_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	int timeout;
+@@ -334,8 +334,8 @@ static irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d)
+ ==============================================================================
+    analog input dma mode 1 & 3, 816 cards
+ */
+-static void transfer_from_dma_buf(struct comedi_device * dev, struct comedi_subdevice * s,
+-	short * ptr, unsigned int bufptr, unsigned int len)
++static void transfer_from_dma_buf(struct comedi_device *dev, struct comedi_subdevice *s,
++	short *ptr, unsigned int bufptr, unsigned int len)
+ {
+ 	int i;
+ 
+@@ -447,7 +447,7 @@ static irqreturn_t interrupt_pcl816(int irq, void *d)
+ ==============================================================================
+    COMMAND MODE
+ */
+-static void pcl816_cmdtest_out(int e, struct comedi_cmd * cmd)
++static void pcl816_cmdtest_out(int e, struct comedi_cmd *cmd)
+ {
+ 	rt_printk("pcl816 e=%d startsrc=%x scansrc=%x convsrc=%x\n", e,
+ 		cmd->start_src, cmd->scan_begin_src, cmd->convert_src);
+@@ -462,8 +462,8 @@ static void pcl816_cmdtest_out(int e, struct comedi_cmd * cmd)
+ /*
+ ==============================================================================
+ */
+-static int pcl816_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int pcl816_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp, divisor1, divisor2;
+@@ -597,7 +597,7 @@ static int pcl816_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice
+ 	return 0;
+ }
+ 
+-static int pcl816_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	unsigned int divisor1 = 0, divisor2 = 0, dma_flags, bytes, dmairq;
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+@@ -702,7 +702,7 @@ static int pcl816_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s
+ 	return 0;
+ }
+ 
+-static int pcl816_ai_poll(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pcl816_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	unsigned long flags;
+ 	unsigned int top1, top2, i;
+@@ -745,7 +745,7 @@ static int pcl816_ai_poll(struct comedi_device * dev, struct comedi_subdevice *
+ ==============================================================================
+  cancel any mode 1-4 AI
+ */
+-static int pcl816_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pcl816_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ /* DEBUG(rt_printk("pcl816_ai_cancel()\n");) */
+ 
+@@ -813,7 +813,7 @@ static int pcl816_check(unsigned long iobase)
+ ==============================================================================
+  reset whole PCL-816 cards
+ */
+-static void pcl816_reset(struct comedi_device * dev)
++static void pcl816_reset(struct comedi_device *dev)
+ {
+ /* outb (0, dev->iobase + PCL818_DA_LO);         DAC=0V */
+ /* outb (0, dev->iobase + PCL818_DA_HI); */
+@@ -835,7 +835,7 @@ static void pcl816_reset(struct comedi_device * dev)
+  Start/stop pacer onboard pacer
+ */
+ static void
+-start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
++start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1,
+ 	unsigned int divisor2)
+ {
+ 	outb(0x32, dev->iobase + PCL816_CTRCTL);
+@@ -865,7 +865,7 @@ start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
+  If it's ok, then program scan/gain logic
+ */
+ static int
+-check_and_setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
++check_and_setup_channel_list(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int *chanlist, int chanlen)
+ {
+ 	unsigned int chansegment[16];
+@@ -979,7 +979,7 @@ static int set_rtc_irq_bit(unsigned char bit)
+ ==============================================================================
+   Free any resources that we have claimed
+ */
+-static void free_resources(struct comedi_device * dev)
++static void free_resources(struct comedi_device *dev)
+ {
+ 	/* rt_printk("free_resource()\n"); */
+ 	if (dev->private) {
+@@ -1015,7 +1015,7 @@ static void free_resources(struct comedi_device * dev)
+    Initialization
+ 
+ */
+-static int pcl816_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int ret;
+ 	unsigned long iobase;
+@@ -1238,7 +1238,7 @@ case COMEDI_SUBD_DO:
+ ==============================================================================
+   Removes device
+  */
+-static int pcl816_detach(struct comedi_device * dev)
++static int pcl816_detach(struct comedi_device *dev)
+ {
+ 	DEBUG(rt_printk("comedi%d: pcl816: remove\n", dev->minor);
+ 		)
+diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
+index 495f802c39ac..f1deeb247e19 100644
+--- a/drivers/staging/comedi/drivers/pcl818.c
++++ b/drivers/staging/comedi/drivers/pcl818.c
+@@ -244,8 +244,8 @@ static const struct comedi_lrange range718_bipolar0_5 = { 1, {BIP_RANGE(0.5),} }
+ static const struct comedi_lrange range718_unipolar2 = { 1, {UNI_RANGE(2),} };
+ static const struct comedi_lrange range718_unipolar1 = { 1, {BIP_RANGE(1),} };
+ 
+-static int pcl818_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pcl818_detach(struct comedi_device * dev);
++static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pcl818_detach(struct comedi_device *dev);
+ 
+ #ifdef unused
+ static int RTC_lock = 0;	/* RTC lock */
+@@ -372,13 +372,13 @@ static const unsigned int muxonechan[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0
+ /*
+ ==============================================================================
+ */
+-static void setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
++static void setup_channel_list(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int *chanlist, unsigned int n_chan, unsigned int seglen);
+-static int check_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
++static int check_channel_list(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int *chanlist, unsigned int n_chan);
+ 
+-static int pcl818_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+-static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
++static int pcl818_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
++static void start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1,
+ 	unsigned int divisor2);
+ 
+ #ifdef unused
+@@ -391,8 +391,8 @@ static int rtc_setfreq_irq(int freq);
+ ==============================================================================
+    ANALOG INPUT MODE0, 818 cards, slow version
+ */
+-static int pcl818_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcl818_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	int timeout;
+@@ -438,8 +438,8 @@ static int pcl818_ai_insn_read(struct comedi_device * dev, struct comedi_subdevi
+    ANALOG OUTPUT MODE0, 818 cards
+    only one sample per call is supported
+ */
+-static int pcl818_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcl818_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -451,8 +451,8 @@ static int pcl818_ao_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ 	return n;
+ }
+ 
+-static int pcl818_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcl818_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -474,8 +474,8 @@ static int pcl818_ao_insn_write(struct comedi_device * dev, struct comedi_subdev
+ 
+    only one sample per call is supported
+ */
+-static int pcl818_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcl818_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -492,8 +492,8 @@ static int pcl818_di_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+ 
+    only one sample per call is supported
+ */
+-static int pcl818_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcl818_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -876,8 +876,8 @@ static irqreturn_t interrupt_pcl818(int irq, void *d)
+ ==============================================================================
+    ANALOG INPUT MODE 1 or 3 DMA , 818 cards
+ */
+-static void pcl818_ai_mode13dma_int(int mode, struct comedi_device * dev,
+-	struct comedi_subdevice * s)
++static void pcl818_ai_mode13dma_int(int mode, struct comedi_device *dev,
++	struct comedi_subdevice *s)
+ {
+ 	unsigned int flags;
+ 	unsigned int bytes;
+@@ -917,8 +917,8 @@ static void pcl818_ai_mode13dma_int(int mode, struct comedi_device * dev,
+ ==============================================================================
+    ANALOG INPUT MODE 1 or 3 DMA rtc, 818 cards
+ */
+-static void pcl818_ai_mode13dma_rtc(int mode, struct comedi_device * dev,
+-	struct comedi_subdevice * s)
++static void pcl818_ai_mode13dma_rtc(int mode, struct comedi_device *dev,
++	struct comedi_subdevice *s)
+ {
+ 	unsigned int flags;
+ 	short *pole;
+@@ -958,8 +958,8 @@ static void pcl818_ai_mode13dma_rtc(int mode, struct comedi_device * dev,
+ ==============================================================================
+    ANALOG INPUT MODE 1 or 3, 818 cards
+ */
+-static int pcl818_ai_cmd_mode(int mode, struct comedi_device * dev,
+-	struct comedi_subdevice * s)
++static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev,
++	struct comedi_subdevice *s)
+ {
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+ 	int divisor1, divisor2;
+@@ -1075,8 +1075,8 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device * dev,
+    ANALOG OUTPUT MODE 1 or 3, 818 cards
+ */
+ #ifdef PCL818_MODE13_AO
+-static int pcl818_ao_mode13(int mode, struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_trig * it)
++static int pcl818_ao_mode13(int mode, struct comedi_device *dev, struct comedi_subdevice *s,
++	comedi_trig *it)
+ {
+ 	int divisor1, divisor2;
+ 
+@@ -1128,8 +1128,8 @@ static int pcl818_ao_mode13(int mode, struct comedi_device * dev, struct comedi_
+ ==============================================================================
+    ANALOG OUTPUT MODE 1, 818 cards
+ */
+-static int pcl818_ao_mode1(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_trig * it)
++static int pcl818_ao_mode1(struct comedi_device *dev, struct comedi_subdevice *s,
++	comedi_trig *it)
+ {
+ 	return pcl818_ao_mode13(1, dev, s, it);
+ }
+@@ -1138,8 +1138,8 @@ static int pcl818_ao_mode1(struct comedi_device * dev, struct comedi_subdevice *
+ ==============================================================================
+    ANALOG OUTPUT MODE 3, 818 cards
+ */
+-static int pcl818_ao_mode3(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_trig * it)
++static int pcl818_ao_mode3(struct comedi_device *dev, struct comedi_subdevice *s,
++	comedi_trig *it)
+ {
+ 	return pcl818_ao_mode13(3, dev, s, it);
+ }
+@@ -1150,7 +1150,7 @@ static int pcl818_ao_mode3(struct comedi_device * dev, struct comedi_subdevice *
+ ==============================================================================
+  Start/stop pacer onboard pacer
+ */
+-static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
++static void start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1,
+ 	unsigned int divisor2)
+ {
+ 	outb(0xb4, dev->iobase + PCL818_CTRCTL);
+@@ -1170,7 +1170,7 @@ static void start_pacer(struct comedi_device * dev, int mode, unsigned int divis
+  Check if channel list from user is builded correctly
+  If it's ok, then program scan/gain logic
+ */
+-static int check_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
++static int check_channel_list(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int *chanlist, unsigned int n_chan)
+ {
+ 	unsigned int chansegment[16];
+@@ -1230,7 +1230,7 @@ static int check_channel_list(struct comedi_device * dev, struct comedi_subdevic
+ 	return seglen;
+ }
+ 
+-static void setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
++static void setup_channel_list(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int *chanlist, unsigned int n_chan, unsigned int seglen)
+ {
+ 	int i;
+@@ -1267,8 +1267,8 @@ static int check_single_ended(unsigned int port)
+ /*
+ ==============================================================================
+ */
+-static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp, divisor1, divisor2;
+@@ -1412,7 +1412,7 @@ static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+ 	int retval;
+@@ -1451,7 +1451,7 @@ static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ ==============================================================================
+  cancel any mode 1-4 AI
+ */
+-static int pcl818_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pcl818_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	if (devpriv->irq_blocked > 0) {
+ 		rt_printk("pcl818_ai_cancel()\n");
+@@ -1535,7 +1535,7 @@ static int pcl818_check(unsigned long iobase)
+ ==============================================================================
+  reset whole PCL-818 cards
+ */
+-static void pcl818_reset(struct comedi_device * dev)
++static void pcl818_reset(struct comedi_device *dev)
+ {
+ 	if (devpriv->usefifo) {	/*  FIFO shutdown */
+ 		outb(0, dev->iobase + PCL818_FI_INTCLR);
+@@ -1656,7 +1656,7 @@ static int rtc_setfreq_irq(int freq)
+ ==============================================================================
+   Free any resources that we have claimed
+ */
+-static void free_resources(struct comedi_device * dev)
++static void free_resources(struct comedi_device *dev)
+ {
+ 	/* rt_printk("free_resource()\n"); */
+ 	if (dev->private) {
+@@ -1694,7 +1694,7 @@ static void free_resources(struct comedi_device * dev)
+    Initialization
+ 
+ */
+-static int pcl818_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int ret;
+ 	unsigned long iobase;
+@@ -1996,7 +1996,7 @@ static int pcl818_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ ==============================================================================
+   Removes device
+  */
+-static int pcl818_detach(struct comedi_device * dev)
++static int pcl818_detach(struct comedi_device *dev)
+ {
+ 	/*   rt_printk("comedi%d: pcl818: remove\n", dev->minor); */
+ 	free_resources(dev);
+diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c
+index 747882d7846f..5178b43b1072 100644
+--- a/drivers/staging/comedi/drivers/pcm3724.c
++++ b/drivers/staging/comedi/drivers/pcm3724.c
+@@ -62,8 +62,8 @@ Copy/pasted/hacked from pcm724.c
+ #define CR_A_MODE(a)	((a)<<5)
+ #define CR_CW		0x80
+ 
+-static int pcm3724_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pcm3724_detach(struct comedi_device * dev);
++static int pcm3724_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pcm3724_detach(struct comedi_device *dev);
+ 
+ struct pcm3724_board {
+ 	const char *name;	/*  driver name */
+@@ -116,7 +116,7 @@ static int subdev_8255_cb(int dir, int port, int data, unsigned long arg)
+ 	}
+ }
+ 
+-static int compute_buffer(int config, int devno, struct comedi_subdevice * s)
++static int compute_buffer(int config, int devno, struct comedi_subdevice *s)
+ {
+ 	/* 1 in io_bits indicates output */
+ 	if (s->io_bits & 0x0000ff) {
+@@ -143,7 +143,7 @@ static int compute_buffer(int config, int devno, struct comedi_subdevice * s)
+ 	return config;
+ }
+ 
+-static void do_3724_config(struct comedi_device * dev, struct comedi_subdevice * s,
++static void do_3724_config(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	int chanspec)
+ {
+ 	int config;
+@@ -177,7 +177,7 @@ static void do_3724_config(struct comedi_device * dev, struct comedi_subdevice *
+ 	outb(config, port_8255_cfg);
+ }
+ 
+-static void enable_chan(struct comedi_device * dev, struct comedi_subdevice * s, int chanspec)
++static void enable_chan(struct comedi_device *dev, struct comedi_subdevice *s, int chanspec)
+ {
+ 	unsigned int mask;
+ 	int gatecfg;
+@@ -215,8 +215,8 @@ static void enable_chan(struct comedi_device * dev, struct comedi_subdevice * s,
+ }
+ 
+ /* overriding the 8255 insn config */
+-static int subdev_3724_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int subdev_3724_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int mask;
+ 	unsigned int bits;
+@@ -252,7 +252,7 @@ static int subdev_3724_insn_config(struct comedi_device * dev, struct comedi_sub
+ 	return 1;
+ }
+ 
+-static int pcm3724_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pcm3724_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	unsigned long iobase;
+ 	unsigned int iorange;
+@@ -290,7 +290,7 @@ static int pcm3724_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	return 0;
+ }
+ 
+-static int pcm3724_detach(struct comedi_device * dev)
++static int pcm3724_detach(struct comedi_device *dev)
+ {
+ 	int i;
+ 
+diff --git a/drivers/staging/comedi/drivers/pcm3730.c b/drivers/staging/comedi/drivers/pcm3730.c
+index 41983d03dabf..1a65af1c6e45 100644
+--- a/drivers/staging/comedi/drivers/pcm3730.c
++++ b/drivers/staging/comedi/drivers/pcm3730.c
+@@ -28,8 +28,8 @@ Configuration options:
+ #define PCM3730_DIB 2
+ #define PCM3730_DIC 3
+ 
+-static int pcm3730_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pcm3730_detach(struct comedi_device * dev);
++static int pcm3730_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pcm3730_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_pcm3730 = {
+       driver_name:"pcm3730",
+       module:THIS_MODULE,
+@@ -39,8 +39,8 @@ static struct comedi_driver driver_pcm3730 = {
+ 
+ COMEDI_INITCLEANUP(driver_pcm3730);
+ 
+-static int pcm3730_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcm3730_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -54,8 +54,8 @@ static int pcm3730_do_insn_bits(struct comedi_device * dev, struct comedi_subdev
+ 	return 2;
+ }
+ 
+-static int pcm3730_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcm3730_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -63,7 +63,7 @@ static int pcm3730_di_insn_bits(struct comedi_device * dev, struct comedi_subdev
+ 	return 2;
+ }
+ 
+-static int pcm3730_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pcm3730_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+@@ -141,7 +141,7 @@ static int pcm3730_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	return 0;
+ }
+ 
+-static int pcm3730_detach(struct comedi_device * dev)
++static int pcm3730_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: pcm3730: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c
+index fc2a73d97c24..15986691ff32 100644
+--- a/drivers/staging/comedi/drivers/pcmad.c
++++ b/drivers/staging/comedi/drivers/pcmad.c
+@@ -76,8 +76,8 @@ struct pcmad_priv_struct {
+ };
+ #define devpriv ((struct pcmad_priv_struct *)dev->private)
+ 
+-static int pcmad_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pcmad_detach(struct comedi_device * dev);
++static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pcmad_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_pcmad = {
+       driver_name:"pcmad",
+       module:THIS_MODULE,
+@@ -92,8 +92,8 @@ COMEDI_INITCLEANUP(driver_pcmad);
+ 
+ #define TIMEOUT	100
+ 
+-static int pcmad_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcmad_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan;
+@@ -126,7 +126,7 @@ static int pcmad_ai_insn_read(struct comedi_device * dev, struct comedi_subdevic
+  * 2	0=single ended 1=differential
+  * 3	0=straight binary 1=two's comp
+  */
+-static int pcmad_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int ret;
+ 	struct comedi_subdevice *s;
+@@ -159,7 +159,7 @@ static int pcmad_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 	return 0;
+ }
+ 
+-static int pcmad_detach(struct comedi_device * dev)
++static int pcmad_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: pcmad: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c
+index 2a1ff465602a..8e4feef27114 100644
+--- a/drivers/staging/comedi/drivers/pcmda12.c
++++ b/drivers/staging/comedi/drivers/pcmda12.c
+@@ -107,10 +107,10 @@ struct pcmda12_private {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pcmda12_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pcmda12_detach(struct comedi_device * dev);
++static int pcmda12_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pcmda12_detach(struct comedi_device *dev);
+ 
+-static void zero_chans(struct comedi_device * dev);
++static void zero_chans(struct comedi_device *dev);
+ 
+ static struct comedi_driver driver = {
+       driver_name:"pcmda12",
+@@ -140,10 +140,10 @@ static struct comedi_driver driver = {
+       num_names:sizeof(pcmda12_boards) / sizeof(struct pcmda12_board),
+ };
+ 
+-static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * Attach is called by the Comedi core to configure the driver
+@@ -151,7 +151,7 @@ static int ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pcmda12_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pcmda12_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+@@ -220,7 +220,7 @@ static int pcmda12_attach(struct comedi_device * dev, struct comedi_devconfig *
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int pcmda12_detach(struct comedi_device * dev)
++static int pcmda12_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: %s: remove\n", dev->minor, driver.driver_name);
+ 	if (dev->iobase)
+@@ -228,7 +228,7 @@ static int pcmda12_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static void zero_chans(struct comedi_device * dev)
++static void zero_chans(struct comedi_device *dev)
+ {				/* sets up an
+ 				   ASIC chip to defaults */
+ 	int i;
+@@ -241,8 +241,8 @@ static void zero_chans(struct comedi_device * dev)
+ 	inb(LSB_PORT(0));	/* update chans. */
+ }
+ 
+-static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -283,8 +283,8 @@ static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+    DAC outputs, which makes all AO channels update simultaneously.
+    This is useful for some control applications, I would imagine.
+ */
+-static int ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
+index 8c332c2f421a..9afd51ff9074 100644
+--- a/drivers/staging/comedi/drivers/pcmmio.c
++++ b/drivers/staging/comedi/drivers/pcmmio.c
+@@ -264,8 +264,8 @@ struct pcmmio_private {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pcmmio_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pcmmio_detach(struct comedi_device * dev);
++static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pcmmio_detach(struct comedi_device *dev);
+ 
+ static struct comedi_driver driver = {
+       driver_name:"pcmmio",
+@@ -321,7 +321,7 @@ static void unlock_port(struct comedi_device * dev, int asic, int port);
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pcmmio_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int sdev_no, chans_left, n_dio_subdevs, n_subdevs, port, asic,
+@@ -526,7 +526,7 @@ static int pcmmio_attach(struct comedi_device * dev, struct comedi_devconfig * i
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int pcmmio_detach(struct comedi_device * dev)
++static int pcmmio_detach(struct comedi_device *dev)
+ {
+ 	int i;
+ 
+@@ -550,8 +550,8 @@ static int pcmmio_detach(struct comedi_device * dev)
+  * useful to applications if you implement the insn_bits interface.
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+-static int pcmmio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcmmio_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int byte_no;
+ 	if (insn->n != 2)
+@@ -624,8 +624,8 @@ static int pcmmio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdev
+  * configured by a special insn_config instruction.  chanspec
+  * contains the channel to be changed, and data[0] contains the
+  * value COMEDI_INPUT or COMEDI_OUTPUT. */
+-static int pcmmio_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcmmio_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec), byte_no = chan / 8, bit_no =
+ 		chan % 8;
+@@ -685,7 +685,7 @@ static int pcmmio_dio_insn_config(struct comedi_device * dev, struct comedi_subd
+ 	return insn->n;
+ }
+ 
+-static void init_asics(struct comedi_device * dev)
++static void init_asics(struct comedi_device *dev)
+ {				/* sets up an
+ 				   ASIC chip to defaults */
+ 	int asic;
+@@ -722,7 +722,7 @@ static void init_asics(struct comedi_device * dev)
+ 	}
+ }
+ 
+-static void switch_page(struct comedi_device * dev, int asic, int page)
++static void switch_page(struct comedi_device *dev, int asic, int page)
+ {
+ 	if (asic < 0 || asic >= thisboard->dio_num_asics)
+ 		return;		/* paranoia */
+@@ -738,7 +738,7 @@ static void switch_page(struct comedi_device * dev, int asic, int page)
+ }
+ 
+ #ifdef notused
+-static void lock_port(struct comedi_device * dev, int asic, int port)
++static void lock_port(struct comedi_device *dev, int asic, int port)
+ {
+ 	if (asic < 0 || asic >= thisboard->dio_num_asics)
+ 		return;		/* paranoia */
+@@ -752,7 +752,7 @@ static void lock_port(struct comedi_device * dev, int asic, int port)
+ 	return;
+ }
+ 
+-static void unlock_port(struct comedi_device * dev, int asic, int port)
++static void unlock_port(struct comedi_device *dev, int asic, int port)
+ {
+ 	if (asic < 0 || asic >= thisboard->dio_num_asics)
+ 		return;		/* paranoia */
+@@ -917,7 +917,7 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static void pcmmio_stop_intr(struct comedi_device * dev, struct comedi_subdevice * s)
++static void pcmmio_stop_intr(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	int nports, firstport, asic, port;
+ 
+@@ -936,7 +936,7 @@ static void pcmmio_stop_intr(struct comedi_device * dev, struct comedi_subdevice
+ 	}
+ }
+ 
+-static int pcmmio_start_intr(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pcmmio_start_intr(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	if (!subpriv->dio.intr.continuous && subpriv->dio.intr.stop_count == 0) {
+ 		/* An empty acquisition! */
+@@ -995,7 +995,7 @@ static int pcmmio_start_intr(struct comedi_device * dev, struct comedi_subdevice
+ 	return 0;
+ }
+ 
+-static int pcmmio_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pcmmio_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	unsigned long flags;
+ 
+@@ -1011,7 +1011,7 @@ static int pcmmio_cancel(struct comedi_device * dev, struct comedi_subdevice * s
+  * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
+  */
+ static int
+-pcmmio_inttrig_start_intr(struct comedi_device * dev, struct comedi_subdevice * s,
++pcmmio_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int trignum)
+ {
+ 	unsigned long flags;
+@@ -1037,7 +1037,7 @@ pcmmio_inttrig_start_intr(struct comedi_device * dev, struct comedi_subdevice *
+ /*
+  * 'do_cmd' function for an 'INTERRUPT' subdevice.
+  */
+-static int pcmmio_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pcmmio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned long flags;
+@@ -1082,7 +1082,7 @@ static int pcmmio_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+  * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
+  */
+ static int
+-pcmmio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_cmd * cmd)
++pcmmio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	unsigned int tmp;
+@@ -1194,8 +1194,8 @@ static int adc_wait_ready(unsigned long iobase)
+ }
+ 
+ /* All this is for AI and AO */
+-static int ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	unsigned long iobase = subpriv->iobase;
+@@ -1258,8 +1258,8 @@ static int ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	for (n = 0; n < insn->n; n++) {
+@@ -1288,8 +1288,8 @@ static int wait_dac_ready(unsigned long iobase)
+ 	return 1;
+ }
+ 
+-static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	unsigned iobase = subpriv->iobase, iooffset = 0;
+diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
+index de9c13554ca1..04fff9dfe87d 100644
+--- a/drivers/staging/comedi/drivers/pcmuio.c
++++ b/drivers/staging/comedi/drivers/pcmuio.c
+@@ -222,8 +222,8 @@ struct pcmuio_private {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pcmuio_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int pcmuio_detach(struct comedi_device * dev);
++static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int pcmuio_detach(struct comedi_device *dev);
+ 
+ static struct comedi_driver driver = {
+       driver_name:"pcmuio",
+@@ -279,7 +279,7 @@ static void unlock_port(struct comedi_device * dev, int asic, int port);
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pcmuio_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int sdev_no, chans_left, n_subdevs, port, asic, thisasic_chanct = 0;
+@@ -450,7 +450,7 @@ static int pcmuio_attach(struct comedi_device * dev, struct comedi_devconfig * i
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int pcmuio_detach(struct comedi_device * dev)
++static int pcmuio_detach(struct comedi_device *dev)
+ {
+ 	int i;
+ 
+@@ -474,8 +474,8 @@ static int pcmuio_detach(struct comedi_device * dev)
+  * useful to applications if you implement the insn_bits interface.
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+-static int pcmuio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcmuio_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int byte_no;
+ 	if (insn->n != 2)
+@@ -548,8 +548,8 @@ static int pcmuio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdev
+  * configured by a special insn_config instruction.  chanspec
+  * contains the channel to be changed, and data[0] contains the
+  * value COMEDI_INPUT or COMEDI_OUTPUT. */
+-static int pcmuio_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcmuio_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec), byte_no = chan / 8, bit_no =
+ 		chan % 8;
+@@ -609,7 +609,7 @@ static int pcmuio_dio_insn_config(struct comedi_device * dev, struct comedi_subd
+ 	return insn->n;
+ }
+ 
+-static void init_asics(struct comedi_device * dev)
++static void init_asics(struct comedi_device *dev)
+ {				/* sets up an
+ 				   ASIC chip to defaults */
+ 	int asic;
+@@ -646,7 +646,7 @@ static void init_asics(struct comedi_device * dev)
+ 	}
+ }
+ 
+-static void switch_page(struct comedi_device * dev, int asic, int page)
++static void switch_page(struct comedi_device *dev, int asic, int page)
+ {
+ 	if (asic < 0 || asic >= thisboard->num_asics)
+ 		return;		/* paranoia */
+@@ -662,7 +662,7 @@ static void switch_page(struct comedi_device * dev, int asic, int page)
+ }
+ 
+ #ifdef notused
+-static void lock_port(struct comedi_device * dev, int asic, int port)
++static void lock_port(struct comedi_device *dev, int asic, int port)
+ {
+ 	if (asic < 0 || asic >= thisboard->num_asics)
+ 		return;		/* paranoia */
+@@ -675,7 +675,7 @@ static void lock_port(struct comedi_device * dev, int asic, int port)
+ 		dev->iobase + ASIC_IOSIZE * asic + REG_PAGELOCK);
+ }
+ 
+-static void unlock_port(struct comedi_device * dev, int asic, int port)
++static void unlock_port(struct comedi_device *dev, int asic, int port)
+ {
+ 	if (asic < 0 || asic >= thisboard->num_asics)
+ 		return;		/* paranoia */
+@@ -837,7 +837,7 @@ static irqreturn_t interrupt_pcmuio(int irq, void *d)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static void pcmuio_stop_intr(struct comedi_device * dev, struct comedi_subdevice * s)
++static void pcmuio_stop_intr(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	int nports, firstport, asic, port;
+ 
+@@ -856,7 +856,7 @@ static void pcmuio_stop_intr(struct comedi_device * dev, struct comedi_subdevice
+ 	}
+ }
+ 
+-static int pcmuio_start_intr(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pcmuio_start_intr(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	if (!subpriv->intr.continuous && subpriv->intr.stop_count == 0) {
+ 		/* An empty acquisition! */
+@@ -905,7 +905,7 @@ static int pcmuio_start_intr(struct comedi_device * dev, struct comedi_subdevice
+ 	return 0;
+ }
+ 
+-static int pcmuio_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pcmuio_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	unsigned long flags;
+ 
+@@ -921,7 +921,7 @@ static int pcmuio_cancel(struct comedi_device * dev, struct comedi_subdevice * s
+  * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
+  */
+ static int
+-pcmuio_inttrig_start_intr(struct comedi_device * dev, struct comedi_subdevice * s,
++pcmuio_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int trignum)
+ {
+ 	unsigned long flags;
+@@ -947,7 +947,7 @@ pcmuio_inttrig_start_intr(struct comedi_device * dev, struct comedi_subdevice *
+ /*
+  * 'do_cmd' function for an 'INTERRUPT' subdevice.
+  */
+-static int pcmuio_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int pcmuio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned long flags;
+@@ -992,7 +992,7 @@ static int pcmuio_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+  * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
+  */
+ static int
+-pcmuio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_cmd * cmd)
++pcmuio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	unsigned int tmp;
+diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c
+index ca439ba5c01d..f8f5a7366aae 100644
+--- a/drivers/staging/comedi/drivers/poc.c
++++ b/drivers/staging/comedi/drivers/poc.c
+@@ -41,17 +41,17 @@ Configuration options:
+ 
+ #include 
+ 
+-static int poc_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int poc_detach(struct comedi_device * dev);
+-static int readback_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-
+-static int dac02_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int pcl733_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int pcl734_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int poc_detach(struct comedi_device *dev);
++static int readback_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++
++static int dac02_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int pcl733_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int pcl734_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+ struct boarddef_struct {
+ 	const char *name;
+@@ -113,7 +113,7 @@ static struct comedi_driver driver_poc = {
+       offset:sizeof(boards[0]),
+ };
+ 
+-static int poc_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+@@ -159,7 +159,7 @@ static int poc_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int poc_detach(struct comedi_device * dev)
++static int poc_detach(struct comedi_device *dev)
+ {
+ 	/* only free stuff if it has been allocated by _attach */
+ 	if (dev->iobase)
+@@ -170,8 +170,8 @@ static int poc_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int readback_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int readback_insn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan;
+ 
+@@ -185,8 +185,8 @@ static int readback_insn(struct comedi_device * dev, struct comedi_subdevice * s
+ #define DAC02_LSB(a)	(2 * a)
+ #define DAC02_MSB(a)	(2 * a + 1)
+ 
+-static int dac02_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int dac02_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int temp;
+ 	int chan;
+@@ -208,8 +208,8 @@ static int dac02_ao_winsn(struct comedi_device * dev, struct comedi_subdevice *
+ 	return 1;
+ }
+ 
+-static int pcl733_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcl733_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -222,8 +222,8 @@ static int pcl733_insn_bits(struct comedi_device * dev, struct comedi_subdevice
+ 	return 2;
+ }
+ 
+-static int pcl734_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int pcl734_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+index d05f33bac4a1..0066218dba48 100644
+--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
++++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+@@ -197,8 +197,8 @@ static const struct comedi_lrange range_daqp_ao = { 1, {BIP_RANGE(5)} };
+ 
+ /* comedi interface code */
+ 
+-static int daqp_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int daqp_detach(struct comedi_device * dev);
++static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int daqp_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_daqp = {
+       driver_name:"quatech_daqp_cs",
+       module:THIS_MODULE,
+@@ -208,7 +208,7 @@ static struct comedi_driver driver_daqp = {
+ 
+ #ifdef DAQP_DEBUG
+ 
+-static void daqp_dump(struct comedi_device * dev)
++static void daqp_dump(struct comedi_device *dev)
+ {
+ 	printk("DAQP: status %02x; aux status %02x\n",
+ 		inb(dev->iobase + DAQP_STATUS), inb(dev->iobase + DAQP_AUX));
+@@ -234,7 +234,7 @@ static void hex_dump(char *str, void *ptr, int len)
+ 
+ /* Cancel a running acquisition */
+ 
+-static int daqp_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++static int daqp_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct local_info_t *local = (struct local_info_t *) s->private;
+ 
+@@ -361,8 +361,8 @@ static void daqp_interrupt(int irq, void *dev_id)
+ 
+ /* One-shot analog data acquisition routine */
+ 
+-static int daqp_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int daqp_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	struct local_info_t *local = (struct local_info_t *) s->private;
+ 	int i;
+@@ -467,8 +467,8 @@ static int daqp_ns_to_timer(unsigned int *ns, int round)
+  * the command passes.
+  */
+ 
+-static int daqp_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int daqp_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -593,7 +593,7 @@ static int daqp_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice *
+ 	return 0;
+ }
+ 
+-static int daqp_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
++static int daqp_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct local_info_t *local = (struct local_info_t *) s->private;
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+@@ -793,8 +793,8 @@ static int daqp_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 
+ /* Single-shot analog output routine */
+ 
+-static int daqp_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int daqp_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	struct local_info_t *local = (struct local_info_t *) s->private;
+ 	int d;
+@@ -820,8 +820,8 @@ static int daqp_ao_insn_write(struct comedi_device * dev, struct comedi_subdevic
+ 
+ /* Digital input routine */
+ 
+-static int daqp_di_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int daqp_di_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	struct local_info_t *local = (struct local_info_t *) s->private;
+ 
+@@ -836,8 +836,8 @@ static int daqp_di_insn_read(struct comedi_device * dev, struct comedi_subdevice
+ 
+ /* Digital output routine */
+ 
+-static int daqp_do_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int daqp_do_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	struct local_info_t *local = (struct local_info_t *) s->private;
+ 
+@@ -856,7 +856,7 @@ static int daqp_do_insn_write(struct comedi_device * dev, struct comedi_subdevic
+  * when it is inserted.
+  */
+ 
+-static int daqp_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int ret;
+ 	struct local_info_t *local = dev_table[it->options[0]];
+@@ -962,7 +962,7 @@ static int daqp_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+  * card is removed, daqp_cs_detach() is called by the pcmcia subsystem.
+  */
+ 
+-static int daqp_detach(struct comedi_device * dev)
++static int daqp_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: detaching daqp\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c
+index 14bb8d19353e..93ef401f409e 100644
+--- a/drivers/staging/comedi/drivers/rti800.c
++++ b/drivers/staging/comedi/drivers/rti800.c
+@@ -131,8 +131,8 @@ static const struct rti800_board boardtypes[] = {
+ 
+ #define this_board ((const struct rti800_board *)dev->board_ptr)
+ 
+-static int rti800_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int rti800_detach(struct comedi_device * dev);
++static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int rti800_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_rti800 = {
+       driver_name:"rti800",
+       module:THIS_MODULE,
+@@ -180,8 +180,8 @@ static irqreturn_t rti800_interrupt(int irq, void *dev)
+ /* settling delay times in usec for different gains */
+ static const int gaindelay[] = { 10, 20, 40, 80 };
+ 
+-static int rti800_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int rti800_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, t;
+ 	int status;
+@@ -233,8 +233,8 @@ static int rti800_ai_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ 	return i;
+ }
+ 
+-static int rti800_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int rti800_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -245,8 +245,8 @@ static int rti800_ao_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ 	return i;
+ }
+ 
+-static int rti800_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int rti800_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	int d;
+@@ -265,8 +265,8 @@ static int rti800_ao_insn_write(struct comedi_device * dev, struct comedi_subdev
+ 	return i;
+ }
+ 
+-static int rti800_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int rti800_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -274,8 +274,8 @@ static int rti800_di_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+ 	return 2;
+ }
+ 
+-static int rti800_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int rti800_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -309,7 +309,7 @@ static int rti800_do_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+    options[8] - dac1 coding
+  */
+ 
+-static int rti800_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	unsigned int irq;
+ 	unsigned long iobase;
+@@ -444,7 +444,7 @@ static int rti800_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	return 0;
+ }
+ 
+-static int rti800_detach(struct comedi_device * dev)
++static int rti800_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: rti800: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c
+index cc2c385db0b0..ec64c9ee0a54 100644
+--- a/drivers/staging/comedi/drivers/rti802.c
++++ b/drivers/staging/comedi/drivers/rti802.c
+@@ -47,8 +47,8 @@ Configuration Options:
+ #define RTI802_DATALOW 1
+ #define RTI802_DATAHIGH 2
+ 
+-static int rti802_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int rti802_detach(struct comedi_device * dev);
++static int rti802_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int rti802_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_rti802 = {
+       driver_name:"rti802",
+       module:THIS_MODULE,
+@@ -68,8 +68,8 @@ struct rti802_private {
+ 
+ #define devpriv ((struct rti802_private *)dev->private)
+ 
+-static int rti802_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int rti802_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 
+@@ -79,8 +79,8 @@ static int rti802_ao_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ 	return i;
+ }
+ 
+-static int rti802_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int rti802_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, d;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -96,7 +96,7 @@ static int rti802_ao_insn_write(struct comedi_device * dev, struct comedi_subdev
+ 	return i;
+ }
+ 
+-static int rti802_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int rti802_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int i;
+@@ -140,7 +140,7 @@ static int rti802_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	return 0;
+ }
+ 
+-static int rti802_detach(struct comedi_device * dev)
++static int rti802_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: rti802: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
+index e419a7c6943d..54c24a266fbc 100644
+--- a/drivers/staging/comedi/drivers/s526.c
++++ b/drivers/staging/comedi/drivers/s526.c
+@@ -217,8 +217,8 @@ struct s526_private {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int s526_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int s526_detach(struct comedi_device * dev);
++static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int s526_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_s526 = {
+       driver_name:"s526",
+       module:THIS_MODULE,
+@@ -247,24 +247,24 @@ static struct comedi_driver driver_s526 = {
+       num_names:sizeof(s526_boards) / sizeof(struct s526_board),
+ };
+ 
+-static int s526_gpct_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int s526_gpct_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int s526_gpct_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int s526_ai_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int s526_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int s526_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int s526_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int s526_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int s526_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int s526_gpct_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int s526_gpct_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int s526_gpct_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int s526_ai_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int s526_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int s526_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int s526_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int s526_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int s526_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * Attach is called by the Comedi core to configure the driver
+@@ -272,7 +272,7 @@ static int s526_dio_insn_config(struct comedi_device * dev, struct comedi_subdev
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int s526_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int iobase;
+@@ -468,7 +468,7 @@ static int s526_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int s526_detach(struct comedi_device * dev)
++static int s526_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: s526: remove\n", dev->minor);
+ 
+@@ -478,8 +478,8 @@ static int s526_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int s526_gpct_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int s526_gpct_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;			/*  counts the Data */
+ 	int counter_channel = CR_CHAN(insn->chanspec);
+@@ -502,8 +502,8 @@ static int s526_gpct_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ 	return i;
+ }
+ 
+-static int s526_gpct_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int s526_gpct_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int subdev_channel = CR_CHAN(insn->chanspec);	/*  Unpack chanspec */
+ 	int i;
+@@ -727,8 +727,8 @@ static int s526_gpct_insn_config(struct comedi_device * dev, struct comedi_subde
+ 	return insn->n;
+ }
+ 
+-static int s526_gpct_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int s526_gpct_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int subdev_channel = CR_CHAN(insn->chanspec);	/*  Unpack chanspec */
+ 	short value;
+@@ -786,8 +786,8 @@ static int s526_gpct_winsn(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ #define ISR_ADC_DONE 0x4
+-static int s526_ai_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int s526_ai_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int result = -EINVAL;
+ 
+@@ -819,8 +819,8 @@ static int s526_ai_insn_config(struct comedi_device * dev, struct comedi_subdevi
+  * "instructions" read/write data in "one-shot" or "software-triggered"
+  * mode.
+  */
+-static int s526_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int s526_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -869,8 +869,8 @@ static int s526_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s
+ 	return n;
+ }
+ 
+-static int s526_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int s526_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -898,8 +898,8 @@ static int s526_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s
+ 
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+-static int s526_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int s526_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -915,8 +915,8 @@ static int s526_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s
+  * useful to applications if you implement the insn_bits interface.
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+-static int s526_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int s526_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -940,8 +940,8 @@ static int s526_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevic
+ 	return 2;
+ }
+ 
+-static int s526_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int s526_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	short value;
+diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
+index 602fa85dc70f..23b83500fc78 100644
+--- a/drivers/staging/comedi/drivers/serial2002.c
++++ b/drivers/staging/comedi/drivers/serial2002.c
+@@ -89,8 +89,8 @@ struct serial2002_private {
+  */
+ #define devpriv ((struct serial2002_private *)dev->private)
+ 
+-static int serial2002_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int serial2002_detach(struct comedi_device * dev);
++static int serial2002_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int serial2002_detach(struct comedi_device *dev);
+ struct comedi_driver driver_serial2002 = {
+       driver_name:"serial2002",
+       module:THIS_MODULE,
+@@ -101,16 +101,16 @@ struct comedi_driver driver_serial2002 = {
+       num_names:sizeof(serial2002_boards) / sizeof(struct serial2002_board),
+ };
+ 
+-static int serial2002_di_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int serial2002_do_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int serial2002_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int serial2002_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int serial2002_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
++static int serial2002_di_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int serial2002_do_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int serial2002_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int serial2002_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int serial2002_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
+ 
+ struct serial_data {
+ 	enum { is_invalid, is_digital, is_channel } kind;
+@@ -393,7 +393,7 @@ static void serial_write(struct file *f, struct serial_data data)
+ 	}
+ }
+ 
+-static void serial_2002_open(struct comedi_device * dev)
++static void serial_2002_open(struct comedi_device *dev)
+ {
+ 	char port[20];
+ 
+@@ -659,15 +659,15 @@ static void serial_2002_open(struct comedi_device * dev)
+ 	}
+ }
+ 
+-static void serial_2002_close(struct comedi_device * dev)
++static void serial_2002_close(struct comedi_device *dev)
+ {
+ 	if (!IS_ERR(devpriv->tty) && (devpriv->tty != 0)) {
+ 		filp_close(devpriv->tty, 0);
+ 	}
+ }
+ 
+-static int serial2002_di_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int serial2002_di_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	int chan;
+@@ -688,8 +688,8 @@ static int serial2002_di_rinsn(struct comedi_device * dev, struct comedi_subdevi
+ 	return n;
+ }
+ 
+-static int serial2002_do_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int serial2002_do_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	int chan;
+@@ -706,8 +706,8 @@ static int serial2002_do_winsn(struct comedi_device * dev, struct comedi_subdevi
+ 	return n;
+ }
+ 
+-static int serial2002_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int serial2002_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	int chan;
+@@ -728,8 +728,8 @@ static int serial2002_ai_rinsn(struct comedi_device * dev, struct comedi_subdevi
+ 	return n;
+ }
+ 
+-static int serial2002_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int serial2002_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	int chan;
+@@ -747,8 +747,8 @@ static int serial2002_ao_winsn(struct comedi_device * dev, struct comedi_subdevi
+ 	return n;
+ }
+ 
+-static int serial2002_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int serial2002_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -760,8 +760,8 @@ static int serial2002_ao_rinsn(struct comedi_device * dev, struct comedi_subdevi
+ 	return n;
+ }
+ 
+-static int serial2002_ei_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int serial2002_ei_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	int chan;
+@@ -782,7 +782,7 @@ static int serial2002_ei_rinsn(struct comedi_device * dev, struct comedi_subdevi
+ 	return n;
+ }
+ 
+-static int serial2002_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int serial2002_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 
+@@ -849,7 +849,7 @@ static int serial2002_attach(struct comedi_device * dev, struct comedi_devconfig
+ 	return 1;
+ }
+ 
+-static int serial2002_detach(struct comedi_device * dev)
++static int serial2002_detach(struct comedi_device *dev)
+ {
+ 	struct comedi_subdevice *s;
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c
+index c7700d134cc1..fe49310941d6 100644
+--- a/drivers/staging/comedi/drivers/skel.c
++++ b/drivers/staging/comedi/drivers/skel.c
+@@ -154,8 +154,8 @@ struct skel_private {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int skel_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int skel_detach(struct comedi_device * dev);
++static int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int skel_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_skel = {
+       driver_name:"dummy",
+       module:THIS_MODULE,
+@@ -184,18 +184,18 @@ static struct comedi_driver driver_skel = {
+       num_names:sizeof(skel_boards) / sizeof(struct skel_board),
+ };
+ 
+-static int skel_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int skel_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int skel_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int skel_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int skel_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int skel_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd);
++static int skel_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int skel_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int skel_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int skel_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int skel_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data);
++static int skel_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd);
+ static int skel_ns_to_timer(unsigned int *ns, int round);
+ 
+ /*
+@@ -204,7 +204,7 @@ static int skel_ns_to_timer(unsigned int *ns, int round);
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int skel_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 
+@@ -292,7 +292,7 @@ static int skel_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int skel_detach(struct comedi_device * dev)
++static int skel_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: skel: remove\n", dev->minor);
+ 
+@@ -303,8 +303,8 @@ static int skel_detach(struct comedi_device * dev)
+  * "instructions" read/write data in "one-shot" or "software-triggered"
+  * mode.
+  */
+-static int skel_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int skel_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, i;
+ 	unsigned int d;
+@@ -351,8 +351,8 @@ static int skel_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s
+ 	return n;
+ }
+ 
+-static int skel_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_cmd * cmd)
++static int skel_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -520,8 +520,8 @@ static int skel_ns_to_timer(unsigned int *ns, int round)
+ 	return *ns;
+ }
+ 
+-static int skel_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int skel_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -541,8 +541,8 @@ static int skel_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s
+ 
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+-static int skel_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int skel_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -558,8 +558,8 @@ static int skel_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s
+  * useful to applications if you implement the insn_bits interface.
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+-static int skel_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int skel_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -583,8 +583,8 @@ static int skel_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevic
+ 	return 2;
+ }
+ 
+-static int skel_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	struct comedi_insn * insn, unsigned int * data)
++static int skel_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c
+index c9a8fb5e8524..847695a62819 100644
+--- a/drivers/staging/comedi/drivers/ssv_dnp.c
++++ b/drivers/staging/comedi/drivers/ssv_dnp.c
+@@ -88,8 +88,8 @@ struct dnp_private_data {
+ /* In the following section we define the API of this driver.                */
+ /* ------------------------------------------------------------------------- */
+ 
+-static int dnp_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int dnp_detach(struct comedi_device * dev);
++static int dnp_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int dnp_detach(struct comedi_device *dev);
+ 
+ static struct comedi_driver driver_dnp = {
+       driver_name:"ssv_dnp",
+@@ -104,11 +104,11 @@ static struct comedi_driver driver_dnp = {
+ 
+ COMEDI_INITCLEANUP(driver_dnp);
+ 
+-static int dnp_dio_insn_bits(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
++static int dnp_dio_insn_bits(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
+ 
+-static int dnp_dio_insn_config(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
++static int dnp_dio_insn_config(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
+ 
+ /* ------------------------------------------------------------------------- */
+ /* Attach is called by comedi core to configure the driver for a particular  */
+@@ -116,7 +116,7 @@ static int dnp_dio_insn_config(struct comedi_device * dev,
+ /* dev->board_ptr contains that address.                                     */
+ /* ------------------------------------------------------------------------- */
+ 
+-static int dnp_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int dnp_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 
+ 	struct comedi_subdevice *s;
+@@ -177,7 +177,7 @@ static int dnp_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ /* deallocated automatically by the core.                                    */
+ /* ------------------------------------------------------------------------- */
+ 
+-static int dnp_detach(struct comedi_device * dev)
++static int dnp_detach(struct comedi_device *dev)
+ {
+ 
+ 	/* configure all ports as input (default)                                  */
+@@ -201,8 +201,8 @@ static int dnp_detach(struct comedi_device * dev)
+ /* are able to use these instructions as well.                               */
+ /* ------------------------------------------------------------------------- */
+ 
+-static int dnp_dio_insn_bits(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++static int dnp_dio_insn_bits(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	if (insn->n != 2)
+@@ -251,8 +251,8 @@ static int dnp_dio_insn_bits(struct comedi_device * dev,
+ /* COMEDI_INPUT or COMEDI_OUTPUT.                                            */
+ /* ------------------------------------------------------------------------- */
+ 
+-static int dnp_dio_insn_config(struct comedi_device * dev,
+-	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
++static int dnp_dio_insn_config(struct comedi_device *dev,
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	u8 register_buffer;
+diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c
+index 96284f020be1..5b383e6354e0 100644
+--- a/drivers/staging/comedi/drivers/unioxx5.c
++++ b/drivers/staging/comedi/drivers/unioxx5.c
+@@ -80,27 +80,27 @@ struct unioxx5_subd_priv {
+ 	unsigned char usp_prev_cn_val[3];	/* previous channel value */
+ };
+ 
+-static int unioxx5_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+-static int unioxx5_subdev_write(struct comedi_device * dev, struct comedi_subdevice * subdev,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int unioxx5_subdev_read(struct comedi_device * dev, struct comedi_subdevice * subdev,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int unioxx5_insn_config(struct comedi_device * dev, struct comedi_subdevice * subdev,
+-	struct comedi_insn * insn, unsigned int * data);
+-static int unioxx5_detach(struct comedi_device * dev);
+-static int __unioxx5_subdev_init(struct comedi_subdevice * subdev, int subdev_iobase,
++static int unioxx5_attach(struct comedi_device *dev, struct comedi_devconfig *it);
++static int unioxx5_subdev_write(struct comedi_device *dev, struct comedi_subdevice *subdev,
++	struct comedi_insn *insn, unsigned int *data);
++static int unioxx5_subdev_read(struct comedi_device *dev, struct comedi_subdevice *subdev,
++	struct comedi_insn *insn, unsigned int *data);
++static int unioxx5_insn_config(struct comedi_device *dev, struct comedi_subdevice *subdev,
++	struct comedi_insn *insn, unsigned int *data);
++static int unioxx5_detach(struct comedi_device *dev);
++static int __unioxx5_subdev_init(struct comedi_subdevice *subdev, int subdev_iobase,
+ 	int minor);
+-static int __unioxx5_digital_write(struct unioxx5_subd_priv * usp, unsigned int * data,
++static int __unioxx5_digital_write(struct unioxx5_subd_priv *usp, unsigned int *data,
+ 	int channel, int minor);
+-static int __unioxx5_digital_read(struct unioxx5_subd_priv * usp, unsigned int * data,
++static int __unioxx5_digital_read(struct unioxx5_subd_priv *usp, unsigned int *data,
+ 	int channel, int minor);
+ /* static void __unioxx5_digital_config(struct unioxx5_subd_priv* usp, int mode); */
+-static int __unioxx5_analog_write(struct unioxx5_subd_priv * usp, unsigned int * data,
++static int __unioxx5_analog_write(struct unioxx5_subd_priv *usp, unsigned int *data,
+ 	int channel, int minor);
+-static int __unioxx5_analog_read(struct unioxx5_subd_priv * usp, unsigned int * data,
++static int __unioxx5_analog_read(struct unioxx5_subd_priv *usp, unsigned int *data,
+ 	int channel, int minor);
+ static int __unioxx5_define_chan_offset(int chan_num);
+-static void __unioxx5_analog_config(struct unioxx5_subd_priv * usp, int channel);
++static void __unioxx5_analog_config(struct unioxx5_subd_priv *usp, int channel);
+ 
+ static struct comedi_driver unioxx5_driver = {
+       driver_name:DRIVER_NAME,
+@@ -111,7 +111,7 @@ static struct comedi_driver unioxx5_driver = {
+ 
+ COMEDI_INITCLEANUP(unioxx5_driver);
+ 
+-static int unioxx5_attach(struct comedi_device * dev, struct comedi_devconfig * it)
++static int unioxx5_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int iobase, i, n_subd;
+ 	int id, num, ba;
+@@ -156,8 +156,8 @@ static int unioxx5_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	return 0;
+ }
+ 
+-static int unioxx5_subdev_read(struct comedi_device * dev, struct comedi_subdevice * subdev,
+-	struct comedi_insn * insn, unsigned int * data)
++static int unioxx5_subdev_read(struct comedi_device *dev, struct comedi_subdevice *subdev,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	struct unioxx5_subd_priv *usp = subdev->private;
+ 	int channel, type;
+@@ -176,8 +176,8 @@ static int unioxx5_subdev_read(struct comedi_device * dev, struct comedi_subdevi
+ 	return 1;
+ }
+ 
+-static int unioxx5_subdev_write(struct comedi_device * dev, struct comedi_subdevice * subdev,
+-	struct comedi_insn * insn, unsigned int * data)
++static int unioxx5_subdev_write(struct comedi_device *dev, struct comedi_subdevice *subdev,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	struct unioxx5_subd_priv *usp = subdev->private;
+ 	int channel, type;
+@@ -197,8 +197,8 @@ static int unioxx5_subdev_write(struct comedi_device * dev, struct comedi_subdev
+ }
+ 
+ /* for digital modules only */
+-static int unioxx5_insn_config(struct comedi_device * dev, struct comedi_subdevice * subdev,
+-	struct comedi_insn * insn, unsigned int * data)
++static int unioxx5_insn_config(struct comedi_device *dev, struct comedi_subdevice *subdev,
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int channel_offset, flags, channel = CR_CHAN(insn->chanspec), type;
+ 	struct unioxx5_subd_priv *usp = subdev->private;
+@@ -247,7 +247,7 @@ static int unioxx5_insn_config(struct comedi_device * dev, struct comedi_subdevi
+ 	return 0;
+ }
+ 
+-static int unioxx5_detach(struct comedi_device * dev)
++static int unioxx5_detach(struct comedi_device *dev)
+ {
+ 	int i;
+ 	struct comedi_subdevice *subdev;
+@@ -264,7 +264,7 @@ static int unioxx5_detach(struct comedi_device * dev)
+ }
+ 
+ /* initializing subdevice with given address */
+-static int __unioxx5_subdev_init(struct comedi_subdevice * subdev, int subdev_iobase,
++static int __unioxx5_subdev_init(struct comedi_subdevice *subdev, int subdev_iobase,
+ 	int minor)
+ {
+ 	struct unioxx5_subd_priv *usp;
+@@ -330,7 +330,7 @@ static int __unioxx5_subdev_init(struct comedi_subdevice * subdev, int subdev_io
+ 	return 0;
+ }
+ 
+-static int __unioxx5_digital_write(struct unioxx5_subd_priv * usp, unsigned int * data,
++static int __unioxx5_digital_write(struct unioxx5_subd_priv *usp, unsigned int *data,
+ 	int channel, int minor)
+ {
+ 	int channel_offset, val;
+@@ -357,7 +357,7 @@ static int __unioxx5_digital_write(struct unioxx5_subd_priv * usp, unsigned int
+ }
+ 
+ /* function for digital reading */
+-static int __unioxx5_digital_read(struct unioxx5_subd_priv * usp, unsigned int * data,
++static int __unioxx5_digital_read(struct unioxx5_subd_priv *usp, unsigned int *data,
+ 	int channel, int minor)
+ {
+ 	int channel_offset, mask = 1 << (channel & 0x07);
+@@ -380,7 +380,7 @@ static int __unioxx5_digital_read(struct unioxx5_subd_priv * usp, unsigned int *
+ }
+ 
+ #if 0				/* not used? */
+-static void __unioxx5_digital_config(struct unioxx5_subd_priv * usp, int mode)
++static void __unioxx5_digital_config(struct unioxx5_subd_priv *usp, int mode)
+ {
+ 	int i, mask;
+ 
+@@ -396,7 +396,7 @@ static void __unioxx5_digital_config(struct unioxx5_subd_priv * usp, int mode)
+ }
+ #endif
+ 
+-static int __unioxx5_analog_write(struct unioxx5_subd_priv * usp, unsigned int * data,
++static int __unioxx5_analog_write(struct unioxx5_subd_priv *usp, unsigned int *data,
+ 	int channel, int minor)
+ {
+ 	int module, i;
+@@ -431,7 +431,7 @@ static int __unioxx5_analog_write(struct unioxx5_subd_priv * usp, unsigned int *
+ 	return 1;
+ }
+ 
+-static int __unioxx5_analog_read(struct unioxx5_subd_priv * usp, unsigned int * data,
++static int __unioxx5_analog_read(struct unioxx5_subd_priv *usp, unsigned int *data,
+ 	int channel, int minor)
+ {
+ 	int module_no, read_ch;
+@@ -471,7 +471,7 @@ static int __unioxx5_analog_read(struct unioxx5_subd_priv * usp, unsigned int *
+ }
+ 
+ /* configure channels for analog i/o (even to output, odd to input) */
+-static void __unioxx5_analog_config(struct unioxx5_subd_priv * usp, int channel)
++static void __unioxx5_analog_config(struct unioxx5_subd_priv *usp, int channel)
+ {
+ 	int chan_a, chan_b, conf, channel_offset;
+ 

commit 2696fb57e6af653dd8b4df41b16754579f42fc78
+Author: Bill Pemberton 
+Date:   Fri Mar 27 11:29:34 2009 -0400
+
+    Staging: comedi: Remove C99 comments
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+index 26f9d91e8130..6c3be314303d 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+@@ -736,7 +736,7 @@ int i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_su
+ 							DPRINTK("Base timing selection is wrong\n");
+ 							i_ReturnValue = -7;
+ 						}
+-					}	// if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))
++					}	/*  if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) */
+ 					else {
+ 		       /***********************************/
+ 						/* Timing unity selection is wrong */
+@@ -744,8 +744,8 @@ int i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_su
+ 
+ 						DPRINTK("Timing unity selection is wrong\n");
+ 						i_ReturnValue = -6;
+-					}	// if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))
+-				}	// if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ))
++					}	/*  if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) */
++				}	/*  if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ)) */
+ 				else {
+ 		    /*****************************************/
+ 					/* The selected PCI input clock is wrong */
+@@ -753,8 +753,8 @@ int i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_su
+ 
+ 					DPRINTK("The selected PCI input clock is wrong\n");
+ 					i_ReturnValue = -5;
+-				}	// if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ))
+-			}	// if (b_ChronoMode >= 0 && b_ChronoMode <= 7)
++				}	/*  if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ)) */
++			}	/*  if (b_ChronoMode >= 0 && b_ChronoMode <= 7) */
+ 			else {
+ 		 /***************************************/
+ 				/* Chronometer mode selection is wrong */
+@@ -762,7 +762,7 @@ int i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_su
+ 
+ 				DPRINTK("Chronometer mode selection is wrong\n");
+ 				i_ReturnValue = -4;
+-			}	// if (b_ChronoMode >= 0 && b_ChronoMode <= 7)
++			}	/*  if (b_ChronoMode >= 0 && b_ChronoMode <= 7) */
+ 		} else {
+ 	      /******************************************/
+ 			/* The module is not a Chronometer module */
+@@ -951,7 +951,7 @@ int i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device * dev,
+ 									ui_Address
+ 									+ 32 +
+ 									(64 * b_ModulNbr));
+-								devpriv->tsk_Current = current;	// Save the current process task structure
++								devpriv->tsk_Current = current;	/*  Save the current process task structure */
+ 							}
+ 
+ 			  /***********************************/
+@@ -980,7 +980,7 @@ int i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device * dev,
+ 								36 +
+ 								(64 * b_ModulNbr));
+ 
+-						}	// if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE))
++						}	/*  if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE)) */
+ 						else {
+ 		       /********************************/
+ 							/* Interrupt parameter is wrong */
+@@ -988,8 +988,8 @@ int i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device * dev,
+ 
+ 							DPRINTK("Interrupt parameter is wrong\n");
+ 							i_ReturnValue = -6;
+-						}	// if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE))
+-					}	// if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS))
++						}	/*  if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE)) */
++					}	/*  if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS)) */
+ 					else {
+ 		    /***********************************************/
+ 						/* Chronometer acquisition mode cycle is wrong */
+@@ -997,7 +997,7 @@ int i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device * dev,
+ 
+ 						DPRINTK("Chronometer acquisition mode cycle is wrong\n");
+ 						i_ReturnValue = -5;
+-					}	// if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS))
++					}	/*  if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS)) */
+ 					break;
+ 
+ 				case APCI1710_DISABLE:
+@@ -1046,7 +1046,7 @@ int i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device * dev,
+ 				default:
+ 					DPRINTK("Inputs wrong! Enable or Disable chrono\n");
+ 					i_ReturnValue = -8;
+-				}	// switch ENABLE/DISABLE
++				}	/*  switch ENABLE/DISABLE */
+ 			} else {
+ 		 /*******************************/
+ 				/* Chronometer not initialised */
+@@ -1233,7 +1233,7 @@ int i_APCI1710_GetChronoProgressStatus(struct comedi_device * dev,
+ 		    /******************/
+ 
+ 					*pb_ChronoStatus = 3;
+-				}	// if ((dw_Status & 8) == 8)
++				}	/*  if ((dw_Status & 8) == 8) */
+ 				else {
+ 		    /*******************************/
+ 					/* Test if measurement stopped */
+@@ -1245,7 +1245,7 @@ int i_APCI1710_GetChronoProgressStatus(struct comedi_device * dev,
+ 		       /***********************/
+ 
+ 						*pb_ChronoStatus = 2;
+-					}	// if ((dw_Status & 2) == 2)
++					}	/*  if ((dw_Status & 2) == 2) */
+ 					else {
+ 		       /*******************************/
+ 						/* Test if measurement started */
+@@ -1257,16 +1257,16 @@ int i_APCI1710_GetChronoProgressStatus(struct comedi_device * dev,
+ 			  /************************/
+ 
+ 							*pb_ChronoStatus = 1;
+-						}	// if ((dw_Status & 1) == 1)
++						}	/*  if ((dw_Status & 1) == 1) */
+ 						else {
+ 			  /***************************/
+ 							/* Measurement not started */
+ 			  /***************************/
+ 
+ 							*pb_ChronoStatus = 0;
+-						}	// if ((dw_Status & 1) == 1)
+-					}	// if ((dw_Status & 2) == 2)
+-				}	// if ((dw_Status & 8) == 8)
++						}	/*  if ((dw_Status & 1) == 1) */
++					}	/*  if ((dw_Status & 2) == 2) */
++				}	/*  if ((dw_Status & 8) == 8) */
+ 			} else {
+ 		 /*******************************/
+ 				/* Chronometer not initialised */
+@@ -1430,7 +1430,7 @@ int i_APCI1710_ReadChronoValue(struct comedi_device * dev,
+ 							}
+ 
+ 							break;
+-						}	// if ((dw_Status & 8) == 8)
++						}	/*  if ((dw_Status & 8) == 8) */
+ 						else {
+ 			     /*******************************/
+ 							/* Test if measurement stopped */
+@@ -1464,7 +1464,7 @@ int i_APCI1710_ReadChronoValue(struct comedi_device * dev,
+ 									outl(0, devpriv->s_BoardInfos.ui_Address + 36 + (64 * b_ModulNbr));
+ 								}
+ 								break;
+-							}	// if ((dw_Status & 2) == 2)
++							}	/*  if ((dw_Status & 2) == 2) */
+ 							else {
+ 				/*******************************/
+ 								/* Test if measurement started */
+@@ -1478,7 +1478,7 @@ int i_APCI1710_ReadChronoValue(struct comedi_device * dev,
+ 									*pb_ChronoStatus
+ 										=
+ 										1;
+-								}	// if ((dw_Status & 1) == 1)
++								}	/*  if ((dw_Status & 1) == 1) */
+ 								else {
+ 				   /***************************/
+ 									/* Measurement not started */
+@@ -1487,9 +1487,9 @@ int i_APCI1710_ReadChronoValue(struct comedi_device * dev,
+ 									*pb_ChronoStatus
+ 										=
+ 										0;
+-								}	// if ((dw_Status & 1) == 1)
+-							}	// if ((dw_Status & 2) == 2)
+-						}	// if ((dw_Status & 8) == 8)
++								}	/*  if ((dw_Status & 1) == 1) */
++							}	/*  if ((dw_Status & 2) == 2) */
++						}	/*  if ((dw_Status & 8) == 8) */
+ 
+ 						if (dw_TimeOut == ui_TimeOut) {
+ 			     /*****************/
+@@ -1507,7 +1507,7 @@ int i_APCI1710_ReadChronoValue(struct comedi_device * dev,
+ 							mdelay(1000);
+ 
+ 						}
+-					}	// for (;;)
++					}	/*  for (;;) */
+ 
+ 		       /*****************************/
+ 					/* Test if stop signal occur */
+@@ -1922,7 +1922,7 @@ int i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device * dev,
+ 							ui_Address + 20 +
+ 							(b_OutputChannel * 4) +
+ 							(64 * b_ModulNbr));
+-					}	// if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2))
++					}	/*  if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2)) */
+ 					else {
+ 		    /****************************************/
+ 						/* The selected digital output is wrong */
+@@ -1931,7 +1931,7 @@ int i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device * dev,
+ 						DPRINTK("The selected digital output is wrong\n");
+ 						i_ReturnValue = -4;
+ 
+-					}	// if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2))
++					}	/*  if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2)) */
+ 
+ 					break;
+ 
+@@ -1945,7 +1945,7 @@ int i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device * dev,
+ 							ui_Address + 20 +
+ 							(b_OutputChannel * 4) +
+ 							(64 * b_ModulNbr));
+-					}	// if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2))
++					}	/*  if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2)) */
+ 					else {
+ 		    /****************************************/
+ 						/* The selected digital output is wrong */
+@@ -1954,7 +1954,7 @@ int i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device * dev,
+ 						DPRINTK("The selected digital output is wrong\n");
+ 						i_ReturnValue = -4;
+ 
+-					}	// if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2))
++					}	/*  if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2)) */
+ 
+ 					break;
+ 
+@@ -1978,7 +1978,7 @@ int i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device * dev,
+ 							(unsigned char) (((dw_Status >>
+ 									b_InputChannel)
+ 								& 1) ^ 1);
+-					}	// if ((b_InputChannel >= 0) && (b_InputChannel <= 2))
++					}	/*  if ((b_InputChannel >= 0) && (b_InputChannel <= 2)) */
+ 					else {
+ 		    /***************************************/
+ 						/* The selected digital input is wrong */
+@@ -1986,7 +1986,7 @@ int i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device * dev,
+ 
+ 						DPRINTK("The selected digital input is wrong\n");
+ 						i_ReturnValue = -4;
+-					}	// if ((b_InputChannel >= 0) && (b_InputChannel <= 2))
++					}	/*  if ((b_InputChannel >= 0) && (b_InputChannel <= 2)) */
+ 
+ 					break;
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+index 819d46f24c21..a3266ba92846 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+@@ -108,10 +108,10 @@ int i_APCI1710_InsnConfigDigitalIO(struct comedi_device * dev, struct comedi_sub
+ 	unsigned int dw_WriteConfig = 0;
+ 
+ 	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+-	b_ConfigType = (unsigned char) data[0];	// Memory or  Init
++	b_ConfigType = (unsigned char) data[0];	/*  Memory or  Init */
+ 	b_ChannelAMode = (unsigned char) data[1];
+ 	b_ChannelBMode = (unsigned char) data[2];
+-	b_MemoryOnOff = (unsigned char) data[1];	// if memory operation
++	b_MemoryOnOff = (unsigned char) data[1];	/*  if memory operation */
+ 	i_ReturnValue = insn->n;
+ 
+ 		/**************************/
+@@ -126,7 +126,7 @@ int i_APCI1710_InsnConfigDigitalIO(struct comedi_device * dev, struct comedi_sub
+ 	switch (b_ConfigType) {
+ 	case APCI1710_DIGIO_MEMORYONOFF:
+ 
+-		if (b_MemoryOnOff)	// If Memory ON
++		if (b_MemoryOnOff)	/*  If Memory ON */
+ 		{
+ 		 /****************************/
+ 			/* Set the output memory on */
+@@ -140,7 +140,7 @@ int i_APCI1710_InsnConfigDigitalIO(struct comedi_device * dev, struct comedi_sub
+ 		 /***************************/
+ 			devpriv->s_ModuleInfo[b_ModulNbr].
+ 				s_DigitalIOInfo.dw_OutputMemory = 0;
+-		} else		// If memory off
++		} else		/*  If memory off */
+ 		{
+ 		 /*****************************/
+ 			/* Set the output memory off */
+@@ -233,7 +233,7 @@ int i_APCI1710_InsnConfigDigitalIO(struct comedi_device * dev, struct comedi_sub
+ 			DPRINTK("The module is not a digital I/O module\n");
+ 			i_ReturnValue = -3;
+ 		}
+-	}			// end of Switch
++	}			/*  end of Switch */
+ 	printk("Return Value %d\n", i_ReturnValue);
+ 	return i_ReturnValue;
+ }
+@@ -288,11 +288,11 @@ int i_APCI1710_InsnConfigDigitalIO(struct comedi_device * dev, struct comedi_sub
+ +----------------------------------------------------------------------------+
+ */
+ 
+-//_INT_   i_APCI1710_ReadDigitalIOChlValue      (unsigned char_    b_BoardHandle,
+-//                                             unsigned char_    b_ModulNbr,
+-//                                             unsigned char_    b_InputChannel,
+-//
+-//                                             unsigned char *_  pb_ChannelStatus)
++/* _INT_   i_APCI1710_ReadDigitalIOChlValue      (unsigned char_    b_BoardHandle, */
++/*
++* unsigned char_ b_ModulNbr, unsigned char_ b_InputChannel,
++* unsigned char *_ pb_ChannelStatus)
++*/
+ int i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+@@ -356,7 +356,7 @@ int i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device * dev,
+ 								i_ReturnValue =
+ 									-6;
+ 							}
+-						}	// if (b_InputChannel == 5)
++						}	/*  if (b_InputChannel == 5) */
+ 						else {
+ 			  /***************************/
+ 							/* Test the channel B mode */
+@@ -375,8 +375,8 @@ int i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device * dev,
+ 								i_ReturnValue =
+ 									-7;
+ 							}
+-						}	// if (b_InputChannel == 5)
+-					}	// if (b_InputChannel > 4)
++						}	/*  if (b_InputChannel == 5) */
++					}	/*  if (b_InputChannel > 4) */
+ 
+ 		    /***********************/
+ 					/* Test if error occur */
+@@ -387,11 +387,10 @@ int i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device * dev,
+ 						/* Read all digital input */
+ 		       /**************************/
+ 
+-						//INPDW (ps_APCI1710Variable->
+-						//   s_Board [b_BoardHandle].
+-						//   s_BoardInfos.
+-						//  ui_Address + (64 * b_ModulNbr),
+-						// &dw_StatusReg);
++/*
++* INPDW (ps_APCI1710Variable-> s_Board [b_BoardHandle].
++* s_BoardInfos. ui_Address + (64 * b_ModulNbr), &dw_StatusReg);
++*/
+ 
+ 						dw_StatusReg =
+ 							inl(devpriv->
+@@ -404,7 +403,7 @@ int i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device * dev,
+ 								0x1C) >>
+ 							b_InputChannel) & 1;
+ 
+-					}	// if (i_ReturnValue == 0)
++					}	/*  if (i_ReturnValue == 0) */
+ 				} else {
+ 		    /*******************************/
+ 					/* Digital I/O not initialised */
+@@ -478,9 +477,10 @@ int i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-//_INT_   i_APCI1710_SetDigitalIOChlOn    (unsigned char_ b_BoardHandle,
+-//                                       unsigned char_ b_ModulNbr,
+-//                                       unsigned char_ b_OutputChannel)
++/*
++* _INT_ i_APCI1710_SetDigitalIOChlOn (unsigned char_ b_BoardHandle,
++* unsigned char_ b_ModulNbr, unsigned char_ b_OutputChannel)
++*/
+ int i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+@@ -602,7 +602,7 @@ int i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device * dev,
+ 								1 <<
+ 								b_OutputChannel;
+ 						}
+-					}	// set channel off
++					}	/*  set channel off */
+ 					else {
+ 						if (devpriv->
+ 							s_ModuleInfo
+@@ -627,23 +627,24 @@ int i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device * dev,
+ 								dw_OutputMemory
+ 								= dw_WriteValue;
+ 						} else {
+-		       /*****************************/
++							/*****************************/
+ 							/* Digital Output Memory OFF */
+-		       /*****************************/
+-							// +Use previously the function "i_APCI1710_SetDigitalIOMemoryOn"
++							/*****************************/
++							/*  +Use previously the function "i_APCI1710_SetDigitalIOMemoryOn" */
+ 							i_ReturnValue = -8;
+ 						}
+ 
+ 					}
+-		    /*******************/
++					/*******************/
+ 					/* Write the value */
+-		    /*******************/
++					/*******************/
+ 
+-					//OUTPDW (ps_APCI1710Variable->
+-					//    s_Board [b_BoardHandle].
+-					//   s_BoardInfos.
+-					//   ui_Address + (64 * b_ModulNbr),
+-					//   dw_WriteValue);
++					/* OUTPDW (ps_APCI1710Variable->
++					 * s_Board [b_BoardHandle].
++					 * s_BoardInfos. ui_Address + (64 * b_ModulNbr),
++					 * dw_WriteValue);
++					 */
++*/
+ 					outl(dw_WriteValue,
+ 						devpriv->s_BoardInfos.
+ 						ui_Address + (64 * b_ModulNbr));
+@@ -725,9 +726,11 @@ int i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-//_INT_   i_APCI1710_SetDigitalIOPortOn   (unsigned char_ b_BoardHandle,
+-//                                       unsigned char_ b_ModulNbr,
+-//                                       unsigned char_ b_PortValue)
++/*
++ * _INT_ i_APCI1710_SetDigitalIOPortOn (unsigned char_
++ * b_BoardHandle, unsigned char_ b_ModulNbr, unsigned char_
++ * b_PortValue)
++*/
+ int i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+@@ -740,42 +743,43 @@ int i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device * dev,
+ 	unsigned char * pb_PortValue;
+ 
+ 	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+-	b_PortOperation = (unsigned char) data[0];	// Input or output
+-	b_PortOnOFF = (unsigned char) data[1];	// if output then On or Off
+-	b_PortValue = (unsigned char) data[2];	// if out put then Value
++	b_PortOperation = (unsigned char) data[0];	/*  Input or output */
++	b_PortOnOFF = (unsigned char) data[1];	/*  if output then On or Off */
++	b_PortValue = (unsigned char) data[2];	/*  if out put then Value */
+ 	i_ReturnValue = insn->n;
+ 	pb_PortValue = (unsigned char *) & data[0];
+-// if input then read value
++/* if input then read value */
+ 
+ 	switch (b_PortOperation) {
+ 	case APCI1710_INPUT:
+-	/**************************/
++		/**************************/
+ 		/* Test the module number */
+-	/**************************/
++		/**************************/
+ 
+ 		if (b_ModulNbr < 4) {
+-	   /*******************************/
++			/*******************************/
+ 			/* Test if digital I/O counter */
+-	   /*******************************/
++			/*******************************/
+ 
+ 			if ((devpriv->s_BoardInfos.
+ 					dw_MolduleConfiguration[b_ModulNbr] &
+ 					0xFFFF0000UL) == APCI1710_DIGITAL_IO) {
+-	      /**********************************************/
++				/**********************************************/
+ 				/* Test if the digital I/O module initialised */
+-	      /**********************************************/
++				/**********************************************/
+ 
+ 				if (devpriv->s_ModuleInfo[b_ModulNbr].
+ 					s_DigitalIOInfo.b_DigitalInit == 1) {
+-		 /**************************/
++					/**************************/
+ 					/* Read all digital input */
+-		 /**************************/
++					/**************************/
+ 
+-					//INPDW (ps_APCI1710Variable->
+-					//      s_Board [b_BoardHandle].
+-					//      s_BoardInfos.
+-					//      ui_Address + (64 * b_ModulNbr),
+-					//      &dw_StatusReg);
++					/* INPDW (ps_APCI1710Variable->
++					 * s_Board [b_BoardHandle].
++					 * s_BoardInfos.
++					 * ui_Address + (64 * b_ModulNbr),
++					 * &dw_StatusReg);
++					 */
+ 
+ 					dw_StatusReg =
+ 						inl(devpriv->s_BoardInfos.
+@@ -784,16 +788,16 @@ int i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device * dev,
+ 						(unsigned char) (dw_StatusReg ^ 0x1C);
+ 
+ 				} else {
+-		 /*******************************/
++					/*******************************/
+ 					/* Digital I/O not initialised */
+-		 /*******************************/
++					/*******************************/
+ 
+ 					i_ReturnValue = -4;
+ 				}
+ 			} else {
+-	      /******************************************/
++				/******************************************/
+ 				/* The module is not a digital I/O module */
+-	      /******************************************/
++				/******************************************/
+ 
+ 				i_ReturnValue = -3;
+ 			}
+@@ -853,11 +857,11 @@ int i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device * dev,
+ 								i_ReturnValue =
+ 									-6;
+ 							}
+-						}	// if ((b_PortValue & 2) == 2)
++						}	/*  if ((b_PortValue & 2) == 2) */
+ 
+-		    /**************************/
++						/**************************/
+ 						/* Test if channel B used */
+-		    /**************************/
++						/**************************/
+ 
+ 						if ((b_PortValue & 4) == 4) {
+ 							if (devpriv->
+@@ -866,33 +870,33 @@ int i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device * dev,
+ 								s_DigitalIOInfo.
+ 								b_ChannelBMode
+ 								!= 1) {
+-			  /*******************************************/
++								/*******************************************/
+ 								/* The digital channel B is used for input */
+-			  /*******************************************/
++								/*******************************************/
+ 
+ 								i_ReturnValue =
+ 									-7;
+ 							}
+-						}	// if ((b_PortValue & 4) == 4)
++						}	/*  if ((b_PortValue & 4) == 4) */
+ 
+-		    /***********************/
++						/***********************/
+ 						/* Test if error occur */
+-		    /***********************/
++						/***********************/
+ 
+ 						if (i_ReturnValue >= 0) {
+ 
+-							//if(data[1])
+-							//{
++							/* if(data[1]) { */
++
+ 							switch (b_PortOnOFF) {
+-			   /*********************************/
++								/*********************************/
+ 								/* Test if set Port ON                   */
+-		       /*********************************/
++								/*********************************/
+ 
+ 							case APCI1710_ON:
+ 
+-		       /*********************************/
++								/*********************************/
+ 								/* Test if output memory enabled */
+-		       /*********************************/
++								/*********************************/
+ 
+ 								if (devpriv->
+ 									s_ModuleInfo
+@@ -924,7 +928,7 @@ int i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device * dev,
+ 								}
+ 								break;
+ 
+-								// If Set PORT  OFF
++								/*  If Set PORT  OFF */
+ 							case APCI1710_OFF:
+ 
+ 			   /*********************************/
+@@ -957,25 +961,26 @@ int i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device * dev,
+ 										=
+ 										dw_WriteValue;
+ 								} else {
+-			  /*****************************/
++									/*****************************/
+ 									/* Digital Output Memory OFF */
+-			  /*****************************/
++									/*****************************/
+ 
+ 									i_ReturnValue
+ 										=
+ 										-8;
+ 								}
+-							}	// switch
++							}	/*  switch */
+ 
+-		       /*******************/
++							/*******************/
+ 							/* Write the value */
+-		       /*******************/
++							/*******************/
++
++							/* OUTPDW (ps_APCI1710Variable->
++							 * s_Board [b_BoardHandle].
++							 * s_BoardInfos.
++							 * ui_Address + (64 * b_ModulNbr),
++							 * dw_WriteValue); */
+ 
+-							//  OUTPDW (ps_APCI1710Variable->
+-							//      s_Board [b_BoardHandle].
+-							//      s_BoardInfos.
+-							//      ui_Address + (64 * b_ModulNbr),
+-							//      dw_WriteValue);
+ 							outl(dw_WriteValue,
+ 								devpriv->
+ 								s_BoardInfos.
+@@ -983,16 +988,16 @@ int i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device * dev,
+ 								(64 * b_ModulNbr));
+ 						}
+ 					} else {
+-		    /**********************/
++						/**********************/
+ 						/* Output value wrong */
+-		    /**********************/
++						/**********************/
+ 
+ 						i_ReturnValue = -4;
+ 					}
+ 				} else {
+-		 /*******************************/
++					/*******************************/
+ 					/* Digital I/O not initialised */
+-		 /*******************************/
++					/*******************************/
+ 
+ 					i_ReturnValue = -5;
+ 				}
+@@ -1015,6 +1020,6 @@ int i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device * dev,
+ 	default:
+ 		i_ReturnValue = -9;
+ 		DPRINTK("NO INPUT/OUTPUT specified\n");
+-	}			//switch INPUT / OUTPUT
++	}			/* switch INPUT / OUTPUT */
+ 	return (i_ReturnValue);
+ }
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+index 3292abd6088e..821edbae3f27 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+@@ -84,7 +84,7 @@ int i_APCI1710_InsnConfigINCCPT(struct comedi_device * dev, struct comedi_subdev
+ 
+ 	printk("\nINC_CPT");
+ 
+-	devpriv->tsk_Current = current;	// Save the current process task structure
++	devpriv->tsk_Current = current;	/*  Save the current process task structure */
+ 	switch (ui_ConfigType) {
+ 	case APCI1710_INCCPT_INITCOUNTER:
+ 		i_ReturnValue = i_APCI1710_InitCounter(dev,
+@@ -902,7 +902,7 @@ int i_APCI1710_InitIndex(struct comedi_device * dev,
+ 									b_ModeRegister4
+ 									|
+ 									APCI1710_ENABLE_LATCH_AND_CLEAR;
+-							}	// if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER || b_IndexOperation == APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER)
++							}	/*  if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER || b_IndexOperation == APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER) */
+ 							else {
+ 				/*****************************************/
+ 								/* Clear the latch and clear flag (DQ27) */
+@@ -975,7 +975,7 @@ int i_APCI1710_InitIndex(struct comedi_device * dev,
+ 										&
+ 										(~APCI1710_INDEX_LATCH_COUNTER);
+ 								}
+-							}	// // if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER || b_IndexOperation == APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER)
++							}	/*  // if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER || b_IndexOperation == APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER) */
+ 
+ 							if (b_AutoMode ==
+ 								APCI1710_DISABLE)
+@@ -1335,7 +1335,7 @@ int i_APCI1710_InitExternalStrobe(struct comedi_device * dev,
+ 					DPRINTK("External strobe level parameter is wrong\n");
+ 					i_ReturnValue = -5;
+ 				}
+-			}	// if (b_ExternalStrobe == 0 || b_ExternalStrobe == 1)
++			}	/*  if (b_ExternalStrobe == 0 || b_ExternalStrobe == 1) */
+ 			else {
+ 		 /**************************************/
+ 				/* External strobe selection is wrong */
+@@ -1343,7 +1343,7 @@ int i_APCI1710_InitExternalStrobe(struct comedi_device * dev,
+ 
+ 				DPRINTK("External strobe selection is wrong\n");
+ 				i_ReturnValue = -4;
+-			}	// if (b_ExternalStrobe == 0 || b_ExternalStrobe == 1)
++			}	/*  if (b_ExternalStrobe == 0 || b_ExternalStrobe == 1) */
+ 		} else {
+ 	      /****************************************/
+ 			/* Counter not initialised see function */
+@@ -1637,7 +1637,7 @@ int i_APCI1710_InitFrequencyMeasurement(struct comedi_device * dev,
+ 								i_ReturnValue =
+ 									-7;
+ 							}
+-						}	// if (b_PCIInputClock == APCI1710_40MHZ)
++						}	/*  if (b_PCIInputClock == APCI1710_40MHZ) */
+ 
+ 		       /***************************/
+ 						/* Test if not error occur */
+@@ -1676,7 +1676,7 @@ int i_APCI1710_InitFrequencyMeasurement(struct comedi_device * dev,
+ 										b_ModeRegister4
+ 										|
+ 										APCI1710_ENABLE_40MHZ_FREQUENCY;
+-								}	// if (b_PCIInputClock == APCI1710_40MHZ)
++								}	/*  if (b_PCIInputClock == APCI1710_40MHZ) */
+ 								else {
+ 				   /**********************************/
+ 									/* Disable the 40MHz quarz (DQ30) */
+@@ -1700,7 +1700,7 @@ int i_APCI1710_InitFrequencyMeasurement(struct comedi_device * dev,
+ 										&
+ 										APCI1710_DISABLE_40MHZ_FREQUENCY;
+ 
+-								}	// if (b_PCIInputClock == APCI1710_40MHZ)
++								}	/*  if (b_PCIInputClock == APCI1710_40MHZ) */
+ 
+ 			     /********************************/
+ 								/* Calculate the division fator */
+@@ -1949,7 +1949,7 @@ int i_APCI1710_InitFrequencyMeasurement(struct comedi_device * dev,
+ 								i_ReturnValue =
+ 									-3;
+ 							}
+-						}	// if (i_ReturnValue == 0)
++						}	/*  if (i_ReturnValue == 0) */
+ 					} else {
+ 		       /**********************************/
+ 						/* Base timing selection is wrong */
+@@ -1997,7 +1997,7 @@ int i_APCI1710_InitFrequencyMeasurement(struct comedi_device * dev,
+ 
+ /*########################################################################### */
+ 
+-							//INSN BITS
++							/* INSN BITS */
+ /*########################################################################### */
+ 
+ /*
+@@ -2021,7 +2021,7 @@ int i_APCI1710_InsnBitsINCCPT(struct comedi_device * dev, struct comedi_subdevic
+ 	unsigned int ui_BitsType;
+ 	int i_ReturnValue = 0;
+ 	ui_BitsType = CR_CHAN(insn->chanspec);
+-	devpriv->tsk_Current = current;	// Save the current process task structure
++	devpriv->tsk_Current = current;	/*  Save the current process task structure */
+ 
+ 	switch (ui_BitsType) {
+ 	case APCI1710_INCCPT_CLEARCOUNTERVALUE:
+@@ -2365,7 +2365,7 @@ int i_APCI1710_SetInputFilter(struct comedi_device * dev,
+ 								i_ReturnValue =
+ 									-6;
+ 							}
+-						}	// if (b_PCIInputClock == APCI1710_40MHZ)
++						}	/*  if (b_PCIInputClock == APCI1710_40MHZ) */
+ 
+ 		       /***************************/
+ 						/* Test if error not occur */
+@@ -2401,7 +2401,7 @@ int i_APCI1710_SetInputFilter(struct comedi_device * dev,
+ 									|
+ 									APCI1710_ENABLE_40MHZ_FILTER;
+ 
+-							}	// if (b_PCIInputClock == APCI1710_40MHZ)
++							}	/*  if (b_PCIInputClock == APCI1710_40MHZ) */
+ 							else {
+ 			     /**********************************/
+ 								/* Disable the 40MHz quarz (DQ31) */
+@@ -2425,7 +2425,7 @@ int i_APCI1710_SetInputFilter(struct comedi_device * dev,
+ 									&
+ 									APCI1710_DISABLE_40MHZ_FILTER;
+ 
+-							}	// if (b_PCIInputClock == APCI1710_40MHZ)
++							}	/*  if (b_PCIInputClock == APCI1710_40MHZ) */
+ 
+ 			  /************************/
+ 							/* Set the filter value */
+@@ -2486,8 +2486,8 @@ int i_APCI1710_SetInputFilter(struct comedi_device * dev,
+ 								ui_Address +
+ 								20 +
+ 								(64 * b_ModulNbr));
+-						}	// if (i_ReturnValue == 0)
+-					}	// if (b_Filter < 16)
++						}	/*  if (i_ReturnValue == 0) */
++					}	/*  if (b_Filter < 16) */
+ 					else {
+ 		       /**************************************/
+ 						/* The selected filter value is wrong */
+@@ -2495,8 +2495,8 @@ int i_APCI1710_SetInputFilter(struct comedi_device * dev,
+ 
+ 						DPRINTK("The selected filter value is wrong\n");
+ 						i_ReturnValue = -5;
+-					}	// if (b_Filter < 16)
+-				}	// if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ) || (b_PCIInputClock == APCI1710_40MHZ))
++					}	/*  if (b_Filter < 16) */
++				}	/*  if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ) || (b_PCIInputClock == APCI1710_40MHZ)) */
+ 				else {
+ 		    /*****************************************/
+ 					/* The selected PCI input clock is wrong */
+@@ -2504,7 +2504,7 @@ int i_APCI1710_SetInputFilter(struct comedi_device * dev,
+ 
+ 					DPRINTK("The selected PCI input clock is wrong\n");
+ 					i_ReturnValue = 4;
+-				}	// if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ) || (b_PCIInputClock == APCI1710_40MHZ))
++				}	/*  if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ) || (b_PCIInputClock == APCI1710_40MHZ)) */
+ 			} else {
+ 		 /**************************************/
+ 				/* The module is not a counter module */
+@@ -2735,7 +2735,7 @@ int i_APCI1710_SetIndexAndReferenceSource(struct comedi_device * dev,
+ 							b_ModeRegister4 &
+ 							APCI1710_DEFAULT_INDEX_RFERENCE;
+ 					}
+-				}	// if (b_SourceSelection == APCI1710_SOURCE_0 ||b_SourceSelection == APCI1710_SOURCE_1)
++				}	/*  if (b_SourceSelection == APCI1710_SOURCE_0 ||b_SourceSelection == APCI1710_SOURCE_1) */
+ 				else {
+ 		    /*********************************/
+ 					/* The source selection is wrong */
+@@ -2743,7 +2743,7 @@ int i_APCI1710_SetIndexAndReferenceSource(struct comedi_device * dev,
+ 
+ 					DPRINTK("The source selection is wrong\n");
+ 					i_ReturnValue = -4;
+-				}	// if (b_SourceSelection == APCI1710_SOURCE_0 ||b_SourceSelection == APCI1710_SOURCE_1)
++				}	/*  if (b_SourceSelection == APCI1710_SOURCE_0 ||b_SourceSelection == APCI1710_SOURCE_1) */
+ 			} else {
+ 		 /**************************************/
+ 				/* The module is not a counter module */
+@@ -2934,7 +2934,7 @@ int i_APCI1710_SetDigitalChlOff(struct comedi_device * dev, unsigned char b_Modu
+ 
+ /*########################################################################### */
+ 
+-							// INSN WRITE
++							/*  INSN WRITE */
+ /*########################################################################### */
+ 
+ /*
+@@ -2958,7 +2958,7 @@ int i_APCI1710_InsnWriteINCCPT(struct comedi_device * dev, struct comedi_subdevi
+ 	int i_ReturnValue = 0;
+ 
+ 	ui_WriteType = CR_CHAN(insn->chanspec);
+-	devpriv->tsk_Current = current;	// Save the current process task structure
++	devpriv->tsk_Current = current;	/*  Save the current process task structure */
+ 
+ 	switch (ui_WriteType) {
+ 	case APCI1710_INCCPT_ENABLELATCHINTERRUPT:
+@@ -3976,9 +3976,9 @@ int i_APCI1710_DisableFrequencyMeasurement(struct comedi_device * dev, unsigned
+ 					s_ByteModeRegister.
+ 					b_ModeRegister3 &
+ 					APCI1710_DISABLE_FREQUENCY
+-					// Begin CG 29/06/01 CG 1100/0231 -> 0701/0232 Frequence measure IRQ must be cleared
++					/*  Begin CG 29/06/01 CG 1100/0231 -> 0701/0232 Frequence measure IRQ must be cleared */
+ 					& APCI1710_DISABLE_FREQUENCY_INT;
+-				// End CG 29/06/01 CG 1100/0231 -> 0701/0232 Frequence measure IRQ must be cleared
++				/*  End CG 29/06/01 CG 1100/0231 -> 0701/0232 Frequence measure IRQ must be cleared */
+ 
+ 		 /***************************/
+ 				/* Write the configuration */
+@@ -4031,7 +4031,7 @@ int i_APCI1710_DisableFrequencyMeasurement(struct comedi_device * dev, unsigned
+ 
+ /*########################################################################### */
+ 
+-							// INSN READ
++							/*  INSN READ */
+ 
+ /*########################################################################### */
+ 
+@@ -4057,7 +4057,7 @@ int i_APCI1710_InsnReadINCCPT(struct comedi_device * dev, struct comedi_subdevic
+ 
+ 	ui_ReadType = CR_CHAN(insn->chanspec);
+ 
+-	devpriv->tsk_Current = current;	// Save the current process task structure
++	devpriv->tsk_Current = current;	/*  Save the current process task structure */
+ 	switch (ui_ReadType) {
+ 	case APCI1710_INCCPT_READLATCHREGISTERSTATUS:
+ 		i_ReturnValue = i_APCI1710_ReadLatchRegisterStatus(dev,
+@@ -4899,15 +4899,15 @@ int i_APCI1710_Get16BitCBStatus(struct comedi_device * dev,
+ 					*pb_CBStatusCounter0 =
+ 						(unsigned char) ((dw_StatusReg >> 1) &
+ 						1);
+-				}	// if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_BoardInfos.dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3136)
++				}	/*  if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_BoardInfos.dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3136) */
+ 				else {
+ 		    /****************************/
+ 					/* Firmware revision error  */
+ 		    /****************************/
+ 
+ 					i_ReturnValue = -5;
+-				}	// if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_BoardInfos.dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3136)
+-			}	// if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_ModeRegister.s_ByteModeRegister.b_ModeRegister1 & 0x10) == 0x10)
++				}	/*  if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_BoardInfos.dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3136) */
++			}	/*  if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_ModeRegister.s_ByteModeRegister.b_ModeRegister1 & 0x10) == 0x10) */
+ 			else {
+ 		 /********************************************/
+ 				/* Counter not initialised to 2*16-bit mode */
+@@ -4916,8 +4916,8 @@ int i_APCI1710_Get16BitCBStatus(struct comedi_device * dev,
+ 
+ 				DPRINTK("Counter not initialised\n");
+ 				i_ReturnValue = -4;
+-			}	// if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_ModeRegister.s_ByteModeRegister.b_ModeRegister1 & 0x10) == 0x10)
+-		}		// if (ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1)
++			}	/*  if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_ModeRegister.s_ByteModeRegister.b_ModeRegister1 & 0x10) == 0x10) */
++		}		/*  if (ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) */
+ 		else {
+ 	      /****************************************/
+ 			/* Counter not initialised see function */
+@@ -4926,8 +4926,8 @@ int i_APCI1710_Get16BitCBStatus(struct comedi_device * dev,
+ 
+ 			DPRINTK("Counter not initialised\n");
+ 			i_ReturnValue = -3;
+-		}		// if (ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1)
+-	}			// if (b_ModulNbr < 4)
++		}		/*  if (ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) */
++	}			/*  if (b_ModulNbr < 4) */
+ 	else {
+ 	   /*************************************************/
+ 		/* The selected module number parameter is wrong */
+@@ -4935,7 +4935,7 @@ int i_APCI1710_Get16BitCBStatus(struct comedi_device * dev,
+ 
+ 		DPRINTK("The selected module number parameter is wrong\n");
+ 		i_ReturnValue = -2;
+-	}			// if (b_ModulNbr < 4)
++	}			/*  if (b_ModulNbr < 4) */
+ 
+ 	return (i_ReturnValue);
+ }
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+index 637898cef12d..966aba855d0c 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+@@ -515,7 +515,7 @@ int i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device * dev,
+ 									| (1UL
+ 									<<
+ 									b_PulseEncoderNbr);
+-								devpriv->tsk_Current = current;	// Save the current process task structure
++								devpriv->tsk_Current = current;	/*  Save the current process task structure */
+ 
+ 							}
+ 
+@@ -629,7 +629,7 @@ int i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device * dev,
+ 						(64 * b_ModulNbr));
+ 
+ 					break;
+-				}	// switch End
++				}	/*  switch End */
+ 
+ 			} else {
+ 		 /*********************************/
+@@ -805,7 +805,7 @@ int i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device * dev,
+ 						(4 * b_PulseEncoderNbr) +
+ 						(64 * b_ModulNbr));
+ 
+-				}	//end of switch
++				}	/* end of switch */
+ 			} else {
+ 		 /*********************************/
+ 				/* Pulse encoder not initialised */
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+index acf421b7a821..238fcc88b15c 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+@@ -167,7 +167,7 @@ int i_APCI1710_InsnConfigInitSSI(struct comedi_device * dev, struct comedi_subde
+ 			/* Test the SSI profile length */
+ 	      /*******************************/
+ 
+-			// CG 22/03/00 b_SSIProfile >= 2 anstatt b_SSIProfile > 2
++			/*  CG 22/03/00 b_SSIProfile >= 2 anstatt b_SSIProfile > 2 */
+ 			if (b_SSIProfile >= 2 && b_SSIProfile < 33) {
+ 		 /*************************************/
+ 				/* Test the SSI position data length */
+@@ -423,11 +423,11 @@ int i_APCI1710_InsnReadSSIValue(struct comedi_device * dev, struct comedi_subdev
+ 
+ 	i_ReturnValue = insn->n;
+ 	pul_Position1 = (unsigned int *) & data[0];
+-// For Read1
++/* For Read1 */
+ 	pul_TurnCpt1 = (unsigned int *) & data[1];
+-// For Read all
+-	pul_Position = (unsigned int *) & data[0];	//0-2
+-	pul_TurnCpt = (unsigned int *) & data[3];	//3-5
++/* For Read all */
++	pul_Position = (unsigned int *) & data[0];	/* 0-2 */
++	pul_TurnCpt = (unsigned int *) & data[3];	/* 3-5 */
+ 	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+ 	b_SelectedSSI = (unsigned char) CR_CHAN(insn->chanspec);
+ 	b_ReadType = (unsigned char) CR_RANGE(insn->chanspec);
+@@ -667,7 +667,7 @@ int i_APCI1710_InsnReadSSIValue(struct comedi_device * dev, struct comedi_subdev
+ 				default:
+ 					printk("Read Type Inputs Wrong\n");
+ 
+-				}	// switch  ending
++				}	/*  switch  ending */
+ 
+ 			} else {
+ 		 /***********************/
+@@ -826,7 +826,7 @@ int i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device * dev, struct comedi_su
+ 			default:
+ 				printk("IO type wrong\n");
+ 
+-			}	//switch end
++			}	/* switch end */
+ 		} else {
+ 	      /**********************************/
+ 			/* The module is not a SSI module */
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+index 03da9db2b31d..dc35124a7584 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+@@ -641,7 +641,7 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ 										}
+ 
+ 										fpu_end();
+-									}	// if (b_PCIInputClock != APCI1710_GATE_INPUT)
++									}	/*  if (b_PCIInputClock != APCI1710_GATE_INPUT) */
+ 									else {
+ 				   /*************************************************************/
+ 										/* 2 Clock used for the overflow and the reload from counter */
+@@ -652,7 +652,7 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ 											ul_TimingInterval
+ 											-
+ 											2;
+-									}	// if (b_PCIInputClock != APCI1710_GATE_INPUT)
++									}	/*  if (b_PCIInputClock != APCI1710_GATE_INPUT) */
+ 
+ 				/****************************/
+ 									/* Save the PCI input clock */
+@@ -814,7 +814,7 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ 							DPRINTK("Base timing selection is wrong\n");
+ 							i_ReturnValue = -7;
+ 						}
+-					}	// if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))
++					}	/*  if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) */
+ 					else {
+ 		       /**********************************/
+ 						/* Timing unit selection is wrong */
+@@ -822,8 +822,8 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ 
+ 						DPRINTK("Timing unit selection is wrong\n");
+ 						i_ReturnValue = -6;
+-					}	// if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))
+-				}	// if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ))
++					}	/*  if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) */
++				}	/*  if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ)) */
+ 				else {
+ 		    /*****************************************/
+ 					/* The selected PCI input clock is wrong */
+@@ -831,8 +831,8 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ 
+ 					DPRINTK("The selected PCI input clock is wrong\n");
+ 					i_ReturnValue = -5;
+-				}	// if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ))
+-			}	// if (b_TorCounterMode >= 0 && b_TorCounterMode <= 7)
++				}	/*  if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ)) */
++			}	/*  if (b_TorCounterMode >= 0 && b_TorCounterMode <= 7) */
+ 			else {
+ 		 /**********************************/
+ 				/* Tor Counter selection is wrong */
+@@ -840,7 +840,7 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ 
+ 				DPRINTK("Tor Counter selection is wrong\n");
+ 				i_ReturnValue = -4;
+-			}	// if (b_TorCounterMode >= 0 && b_TorCounterMode <= 7)
++			}	/*  if (b_TorCounterMode >= 0 && b_TorCounterMode <= 7) */
+ 		} else {
+ 	      /******************************************/
+ 			/* The module is not a tor counter module */
+@@ -1002,14 +1002,14 @@ int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+ 	unsigned char b_InterruptEnable;
+ 
+ 	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+-	b_Action = (unsigned char) data[0];	// enable or disable
++	b_Action = (unsigned char) data[0];	/*  enable or disable */
+ 	b_TorCounter = (unsigned char) data[1];
+ 	b_InputMode = (unsigned char) data[2];
+ 	b_ExternGate = (unsigned char) data[3];
+ 	b_CycleMode = (unsigned char) data[4];
+ 	b_InterruptEnable = (unsigned char) data[5];
+ 	i_ReturnValue = insn->n;;
+-	devpriv->tsk_Current = current;	// Save the current process task structure
++	devpriv->tsk_Current = current;	/*  Save the current process task structure */
+ 	/**************************/
+ 	/* Test the module number */
+ 	/**************************/
+@@ -1027,7 +1027,7 @@ int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+ 	      /**********************************/
+ 
+ 			if (b_TorCounter <= 1) {
+-				switch (b_Action)	// Enable or Disable
++				switch (b_Action)	/*  Enable or Disable */
+ 				{
+ 				case APCI1710_ENABLE:
+ 		 /***********************************/
+@@ -1149,7 +1149,7 @@ int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+ 													|
+ 													0x780;
+ 
+-											}	// if (b_InputMode == APCI1710_TOR_SIMPLE_MODE)
++											}	/*  if (b_InputMode == APCI1710_TOR_SIMPLE_MODE) */
+ 
+ 				      /***********************/
+ 											/* Test if double mode */
+@@ -1166,12 +1166,12 @@ int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+ 													|
+ 													0x180;
+ 
+-											}	// if (b_InputMode == APCI1710_TOR_DOUBLE_MODE)
++											}	/*  if (b_InputMode == APCI1710_TOR_DOUBLE_MODE) */
+ 
+ 											b_InputMode
+ 												=
+ 												0;
+-										}	// if (b_InputMode > 1)
++										}	/*  if (b_InputMode > 1) */
+ 
+ 				   /*******************/
+ 										/* Set the command */
+@@ -1237,7 +1237,7 @@ int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+ 
+ 										outl(1, devpriv->s_BoardInfos.ui_Address + 8 + (16 * b_TorCounter) + (64 * b_ModulNbr));
+ 
+-									}	// if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE))
++									}	/*  if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE)) */
+ 									else {
+ 				/********************************/
+ 										/* Interrupt parameter is wrong */
+@@ -1247,8 +1247,8 @@ int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+ 										i_ReturnValue
+ 											=
+ 											-9;
+-									}	// if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE))
+-								}	// if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS))
++									}	/*  if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE)) */
++								}	/*  if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS)) */
+ 								else {
+ 			     /***********************************************/
+ 									/* Tor counter acquisition mode cycle is wrong */
+@@ -1258,8 +1258,8 @@ int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+ 									i_ReturnValue
+ 										=
+ 										-8;
+-								}	// if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS))
+-							}	// if (b_ExternGate >= 0 && b_ExternGate <= 1)
++								}	/*  if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS)) */
++							}	/*  if (b_ExternGate >= 0 && b_ExternGate <= 1) */
+ 							else {
+ 			  /***********************************/
+ 								/* Extern gate input mode is wrong */
+@@ -1268,8 +1268,8 @@ int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+ 								DPRINTK("Extern gate input mode is wrong\n");
+ 								i_ReturnValue =
+ 									-7;
+-							}	// if (b_ExternGate >= 0 && b_ExternGate <= 1)
+-						}	// if (b_InputMode >= 0 && b_InputMode <= 1)
++							}	/*  if (b_ExternGate >= 0 && b_ExternGate <= 1) */
++						}	/*  if (b_InputMode >= 0 && b_InputMode <= 1) */
+ 						else {
+ 		       /***************************************/
+ 							/* Tor input signal selection is wrong */
+@@ -1329,7 +1329,7 @@ int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+ 								s_BoardInfos.
+ 								ui_Address + 8 +
+ 								(16 * b_TorCounter) + (64 * b_ModulNbr));
+-						}	// if (dw_Status & 0x1)
++						}	/*  if (dw_Status & 0x1) */
+ 						else {
+ 		       /***************************/
+ 							/* Tor counter not enabled */
+@@ -1337,8 +1337,8 @@ int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+ 
+ 							DPRINTK("Tor counter not enabled \n");
+ 							i_ReturnValue = -6;
+-						}	// if (dw_Status & 0x1)
+-					}	// if (dw_Status & 0x10)
++						}	/*  if (dw_Status & 0x1) */
++					}	/*  if (dw_Status & 0x10) */
+ 					else {
+ 		    /*******************************/
+ 						/* Tor counter not initialised */
+@@ -1346,10 +1346,10 @@ int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+ 
+ 						DPRINTK("Tor counter not initialised\n");
+ 						i_ReturnValue = -5;
+-					}	// // if (dw_Status & 0x10)
++					}	/*  // if (dw_Status & 0x10) */
+ 
+-				}	// switch
+-			}	// if (b_TorCounter <= 1)
++				}	/*  switch */
++			}	/*  if (b_TorCounter <= 1) */
+ 			else {
+ 		 /**********************************/
+ 				/* Tor counter selection is wrong */
+@@ -1357,7 +1357,7 @@ int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+ 
+ 				DPRINTK("Tor counter selection is wrong\n");
+ 				i_ReturnValue = -4;
+-			}	// if (b_TorCounter <= 1)
++			}	/*  if (b_TorCounter <= 1) */
+ 		} else {
+ 	      /******************************************/
+ 			/* The module is not a tor counter module */
+@@ -1569,17 +1569,17 @@ int i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
+ 								*pb_InputMode =
+ 									APCI1710_TOR_QUADRUPLE_MODE;
+ 							}
+-						}	// if (dw_Status & 0x400)
++						}	/*  if (dw_Status & 0x400) */
+ 						else {
+ 							*pb_InputMode = 1;
+-						}	// // if (dw_Status & 0x400)
++						}	/*  // if (dw_Status & 0x400) */
+ 
+ 		       /************************/
+ 						/* Extern gate not used */
+ 		       /************************/
+ 
+ 						*pb_ExternGate = 0;
+-					}	// if (dw_Status & 0x600)
++					}	/*  if (dw_Status & 0x600) */
+ 					else {
+ 						*pb_InputMode =
+ 							(unsigned char) ((dw_Status >> 6)
+@@ -1587,7 +1587,7 @@ int i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
+ 						*pb_ExternGate =
+ 							(unsigned char) ((dw_Status >> 7)
+ 							& 1);
+-					}	// if (dw_Status & 0x600)
++					}	/*  if (dw_Status & 0x600) */
+ 
+ 					*pb_TimingUnit =
+ 						devpriv->
+@@ -1611,7 +1611,7 @@ int i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
+ 					i_ReturnValue = -5;
+ 				}
+ 
+-			}	// if (b_TorCounter <= 1)
++			}	/*  if (b_TorCounter <= 1) */
+ 			else {
+ 		 /**********************************/
+ 				/* Tor counter selection is wrong */
+@@ -1619,7 +1619,7 @@ int i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
+ 
+ 				DPRINTK("Tor counter selection is wrong \n");
+ 				i_ReturnValue = -4;
+-			}	// if (b_TorCounter <= 1)
++			}	/*  if (b_TorCounter <= 1) */
+ 		} else {
+ 	      /******************************************/
+ 			/* The module is not a tor counter module */
+@@ -1896,7 +1896,7 @@ int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device
+ 											+
+ 											(16 * b_TorCounter) + (64 * b_ModulNbr));
+ 										break;
+-									}	// if ((dw_Status & 4) == 4)
++									}	/*  if ((dw_Status & 4) == 4) */
+ 									else {
+ 				/*******************************/
+ 										/* Test if measurement stopped */
+@@ -1927,7 +1927,7 @@ int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device
+ 												(16 * b_TorCounter) + (64 * b_ModulNbr));
+ 
+ 											break;
+-										}	// if ((dw_Status & 2) == 2)
++										}	/*  if ((dw_Status & 2) == 2) */
+ 										else {
+ 				   /*******************************/
+ 											/* Test if measurement started */
+@@ -1941,7 +1941,7 @@ int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device
+ 												*pb_TorCounterStatus
+ 													=
+ 													1;
+-											}	// if ((dw_Status & 1) == 1)
++											}	/*  if ((dw_Status & 1) == 1) */
+ 											else {
+ 				      /***************************/
+ 												/* Measurement not started */
+@@ -1950,9 +1950,9 @@ int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device
+ 												*pb_TorCounterStatus
+ 													=
+ 													0;
+-											}	// if ((dw_Status & 1) == 1)
+-										}	// if ((dw_Status & 2) == 2)
+-									}	// if ((dw_Status & 8) == 8)
++											}	/*  if ((dw_Status & 1) == 1) */
++										}	/*  if ((dw_Status & 2) == 2) */
++									}	/*  if ((dw_Status & 8) == 8) */
+ 
+ 									if (dw_TimeOut == ui_TimeOut) {
+ 				/*****************/
+@@ -1973,7 +1973,7 @@ int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device
+ 
+ 										mdelay(1000);
+ 									}
+-								}	// for (;;)
++								}	/*  for (;;) */
+ 
+ 			  /*************************/
+ 								/* Test if timeout occur */
+@@ -2001,8 +2001,8 @@ int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device
+ 
+ 						default:
+ 							printk("Inputs wrong\n");
+-						}	// switch end
+-					}	// if (dw_Status & 0x1)
++						}	/*  switch end */
++					}	/*  if (dw_Status & 0x1) */
+ 					else {
+ 		       /***************************/
+ 						/* Tor counter not enabled */
+@@ -2010,7 +2010,7 @@ int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device
+ 
+ 						DPRINTK("Tor counter not enabled\n");
+ 						i_ReturnValue = -6;
+-					}	// if (dw_Status & 0x1)
++					}	/*  if (dw_Status & 0x1) */
+ 				} else {
+ 		    /*******************************/
+ 					/* Tor counter not initialised */
+@@ -2019,7 +2019,7 @@ int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device
+ 					DPRINTK("Tor counter not initialised\n");
+ 					i_ReturnValue = -5;
+ 				}
+-			}	// if (b_TorCounter <= 1)
++			}	/*  if (b_TorCounter <= 1) */
+ 			else {
+ 		 /**********************************/
+ 				/* Tor counter selection is wrong */
+@@ -2027,7 +2027,7 @@ int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device
+ 
+ 				DPRINTK("Tor counter selection is wrong\n");
+ 				i_ReturnValue = -4;
+-			}	// if (b_TorCounter <= 1)
++			}	/*  if (b_TorCounter <= 1) */
+ 		} else {
+ 	      /******************************************/
+ 			/* The module is not a tor counter module */
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+index 2cd0209e143d..1b8f5dfdd4c7 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+@@ -322,7 +322,7 @@ int i_APCI1710_InsnConfigInitTTLIO(struct comedi_device * dev, struct comedi_sub
+ 				DPRINTK("\n");
+ 			default:
+ 				printk("Bad Config Type\n");
+-			}	// switch end
++			}	/*  switch end */
+ 		} else {
+ 	      /**********************************/
+ 			/* The module is not a TTL module */
+@@ -610,7 +610,7 @@ int i_APCI1710_InsnBitsReadTTLIO(struct comedi_device * dev, struct comedi_subde
+ 			default:
+ 				printk("Bad ReadType\n");
+ 
+-			}	//End Switch
++			}	/* End Switch */
+ 		} else {
+ 	      /**********************************/
+ 			/* The module is not a TTL module */
+@@ -811,7 +811,7 @@ int i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,struct comedi
+ 
+   b_ModulNbr	   = CR_AREF(insn->chanspec);
+ 	b_OutputChannel= CR_CHAN(insn->chanspec);
+-	ui_State	   = data[0]; // ON or OFF
++	ui_State	   = data[0]; /*  ON or OFF */
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+ +----------------------------------------------------------------------------+
+@@ -837,7 +837,7 @@ int i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device * dev,
+ 	i_ReturnValue = insn->n;
+ 	b_ModulNbr = CR_AREF(insn->chanspec);
+ 	b_OutputChannel = CR_CHAN(insn->chanspec);
+-	ui_State = data[0];	// ON or OFF
++	ui_State = data[0];	/*  ON or OFF */
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -953,7 +953,7 @@ int i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device * dev,
+ 									ui_Address
+ 									+
+ 									(64 * b_ModulNbr));
+-								if (ui_State)	// ON
++								if (ui_State)	/*  ON */
+ 								{
+ 									dw_StatusReg
+ 										=
+@@ -969,7 +969,7 @@ int i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device * dev,
+ 										(b_OutputChannel
+ 											%
+ 											8));
+-								} else	// Off
++								} else	/*  Off */
+ 								{
+ 									dw_StatusReg
+ 										=
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
+index 0328ecac4550..fe7c8e1d0586 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
+@@ -92,15 +92,15 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 		while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+ 		for (i_Counter = 0; i_Counter < 2; i_Counter++) {
+-			b_SelectedAddressLow = (w_EepromStartAddress + i_Counter) % 256;	//Read the low 8 bit part
+-			b_SelectedAddressHigh = (w_EepromStartAddress + i_Counter) / 256;	//Read the high 8 bit part
++			b_SelectedAddressLow = (w_EepromStartAddress + i_Counter) % 256;	/* Read the low 8 bit part */
++			b_SelectedAddressHigh = (w_EepromStartAddress + i_Counter) / 256;	/* Read the high 8 bit part */
+ 
+-			//Select the load low address mode
++			/* Select the load low address mode */
+ 			outb(NVCMD_LOAD_LOW,
+ 				dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+ 				3);
+ 
+-			//Wait on busy
++			/* Wait on busy */
+ 			do {
+ 				dw_eeprom_busy =
+ 					inl(dw_PCIBoardEepromAddress +
+@@ -109,12 +109,12 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 			}
+ 			while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+-			//Load the low address
++			/* Load the low address */
+ 			outb(b_SelectedAddressLow,
+ 				dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+ 				2);
+ 
+-			//Wait on busy
++			/* Wait on busy */
+ 			do {
+ 				dw_eeprom_busy =
+ 					inl(dw_PCIBoardEepromAddress +
+@@ -123,12 +123,12 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 			}
+ 			while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+-			//Select the load high address mode
++			/* Select the load high address mode */
+ 			outb(NVCMD_LOAD_HIGH,
+ 				dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+ 				3);
+ 
+-			//Wait on busy
++			/* Wait on busy */
+ 			do {
+ 				dw_eeprom_busy =
+ 					inl(dw_PCIBoardEepromAddress +
+@@ -137,12 +137,12 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 			}
+ 			while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+-			//Load the high address
++			/* Load the high address */
+ 			outb(b_SelectedAddressHigh,
+ 				dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+ 				2);
+ 
+-			//Wait on busy
++			/* Wait on busy */
+ 			do {
+ 				dw_eeprom_busy =
+ 					inl(dw_PCIBoardEepromAddress +
+@@ -151,12 +151,12 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 			}
+ 			while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+-			//Select the READ mode
++			/* Select the READ mode */
+ 			outb(NVCMD_BEGIN_READ,
+ 				dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+ 				3);
+ 
+-			//Wait on busy
++			/* Wait on busy */
+ 			do {
+ 				dw_eeprom_busy =
+ 					inl(dw_PCIBoardEepromAddress +
+@@ -165,12 +165,12 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 			}
+ 			while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+-			//Read data into the EEPROM
++			/* Read data into the EEPROM */
+ 			*pb_ReadByte =
+ 				inb(dw_PCIBoardEepromAddress +
+ 				AMCC_OP_REG_MCSR + 2);
+ 
+-			//Wait on busy
++			/* Wait on busy */
+ 			do {
+ 				dw_eeprom_busy =
+ 					inl(dw_PCIBoardEepromAddress +
+@@ -179,14 +179,14 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 			}
+ 			while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+-			//Select the upper address part
++			/* Select the upper address part */
+ 			if (i_Counter == 0) {
+ 				b_ReadLowByte = pb_ReadByte[0];
+ 			} else {
+ 				b_ReadHighByte = pb_ReadByte[0];
+ 			}
+ 
+-			//Sleep
++			/* Sleep */
+ 			for (i = 0; i < 10000; i++) ;
+ 
+ 		}
+@@ -196,8 +196,8 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 
+ 		pw_DataRead[i_WordCounter] = w_ReadWord;
+ 
+-		w_EepromStartAddress += 2;	// to read the next word
++		w_EepromStartAddress += 2;	/*  to read the next word */
+ 
+-	}			// for (...) i_NbOfWordsToRead
++	}			/*  for (...) i_NbOfWordsToRead */
+ 	return (0);
+ }
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+index fcdfefbd4d6f..38cd7cf79b7f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+@@ -68,25 +68,25 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ #include "addi_common.h"
+ #include "addi_amcc_s5933.h"
+ 
+-//Update-0.7.57->0.7.68MODULE_AUTHOR("ADDI-DATA GmbH ");
+-//Update-0.7.57->0.7.68MODULE_DESCRIPTION("Comedi ADDI-DATA module");
+-//Update-0.7.57->0.7.68MODULE_LICENSE("GPL");
++/* Update-0.7.57->0.7.68MODULE_AUTHOR("ADDI-DATA GmbH "); */
++/* Update-0.7.57->0.7.68MODULE_DESCRIPTION("Comedi ADDI-DATA module"); */
++/* Update-0.7.57->0.7.68MODULE_LICENSE("GPL"); */
+ 
+ #define devpriv ((struct addi_private *)dev->private)
+ #define this_board ((struct addi_board *)dev->board_ptr)
+ 
+ #if defined(CONFIG_APCI_1710) || defined(CONFIG_APCI_3200) || defined(CONFIG_APCI_3300)
+-//BYTE b_SaveFPUReg [94];
++/* BYTE b_SaveFPUReg [94]; */
+ 
+ void fpu_begin(void)
+ {
+-	//asm ("fstenv b_SaveFPUReg");
++	/* asm ("fstenv b_SaveFPUReg"); */
+ 	kernel_fpu_begin();
+ }
+ 
+ void fpu_end(void)
+ {
+-	// asm ("frstor b_SaveFPUReg");
++	/*  asm ("frstor b_SaveFPUReg"); */
+ 	kernel_fpu_end();
+ }
+ #endif
+@@ -901,7 +901,7 @@ static const struct addi_board boardtypes[] = {
+ 		NULL},
+ #endif
+ #ifdef CONFIG_APCI_3300
+-	//Begin JK 20.10.2004: APCI-3300 integration
++	/* Begin JK 20.10.2004: APCI-3300 integration */
+ 	{"apci3300",
+ 			APCI3200_BOARD_VENDOR_ID,
+ 			0x3007,
+@@ -2580,10 +2580,10 @@ static int i_ADDI_Attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	}
+ 
+ 	if (!pci_list_builded) {
+-		v_pci_card_list_init(this_board->i_VendorId, 1);	//1 for displaying the list..
++		v_pci_card_list_init(this_board->i_VendorId, 1);	/* 1 for displaying the list.. */
+ 		pci_list_builded = 1;
+ 	}
+-	//rt_printk("comedi%d: addi_common: board=%s",dev->minor,this_board->pc_DriverName);
++	/* rt_printk("comedi%d: addi_common: board=%s",dev->minor,this_board->pc_DriverName); */
+ 
+ 	if ((this_board->i_Dma) && (it->options[2] == 0)) {
+ 		i_Dma = 1;
+@@ -2617,16 +2617,16 @@ static int i_ADDI_Attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	   /************************************/
+ 
+ 		if (this_board->i_IorangeBase1 != 0) {
+-			dev->iobase = (unsigned long)iobase_main;	// DAQ base address...
++			dev->iobase = (unsigned long)iobase_main;	/*  DAQ base address... */
+ 		} else {
+-			dev->iobase = (unsigned long)iobase_a;	// DAQ base address...
++			dev->iobase = (unsigned long)iobase_a;	/*  DAQ base address... */
+ 		}
+ 
+ 		dev->board_name = this_board->pc_DriverName;
+ 		devpriv->amcc = card;
+ 		devpriv->iobase = (int) dev->iobase;
+-		devpriv->i_IobaseAmcc = (int) iobase_a;	//AMCC base address...
+-		devpriv->i_IobaseAddon = (int) iobase_addon;	//ADD ON base address....
++		devpriv->i_IobaseAmcc = (int) iobase_a;	/* AMCC base address... */
++		devpriv->i_IobaseAddon = (int) iobase_addon;	/* ADD ON base address.... */
+ 		devpriv->i_IobaseReserved = (int) iobase_reserved;
+ 		devpriv->ps_BoardInfo = this_board;
+ 	} else {
+@@ -2643,7 +2643,7 @@ static int i_ADDI_Attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 		printk("\nioremap end");
+ 	}
+ 
+-	//##
++	/* ## */
+ 
+ 	if (irq > 0) {
+ 		if (comedi_request_irq(irq, v_ADDI_Interrupt, IRQF_SHARED,
+@@ -2662,18 +2662,18 @@ static int i_ADDI_Attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 		it->options[2]);
+ 	dev->irq = irq;
+ 
+-	// Read eepeom and fill addi_board Structure
++	/*  Read eepeom and fill addi_board Structure */
+ 
+ 	if (this_board->i_PCIEeprom) {
+ 		printk("\nPCI Eeprom used");
+ 		if (!(strcmp(this_board->pc_EepromChip, "S5920"))) {
+-			// Set 3 wait stait
++			/*  Set 3 wait stait */
+ 			if (!(strcmp(this_board->pc_DriverName, "apci035"))) {
+ 				outl(0x80808082, devpriv->i_IobaseAmcc + 0x60);
+ 			} else {
+ 				outl(0x83838383, devpriv->i_IobaseAmcc + 0x60);
+ 			}
+-			// Enable the interrupt for the controler
++			/*  Enable the interrupt for the controler */
+ 			dw_Dummy = inl(devpriv->i_IobaseAmcc + 0x38);
+ 			outl(dw_Dummy | 0x2000, devpriv->i_IobaseAmcc + 0x38);
+ 			printk("\nEnable the interrupt for the controler");
+@@ -2694,7 +2694,7 @@ static int i_ADDI_Attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	if (this_board->i_Dma) {
+ 		printk("\nDMA used");
+ 		if (devpriv->us_UseDma == ADDI_ENABLE) {
+-			// alloc DMA buffers
++			/*  alloc DMA buffers */
+ 			devpriv->b_DmaDoubleBuffer = 0;
+ 			for (i = 0; i < 2; i++) {
+ 				for (pages = 4; pages >= 0; pages--) {
+@@ -2739,16 +2739,16 @@ static int i_ADDI_Attach(struct comedi_device * dev, struct comedi_devconfig * i
+ #ifdef CONFIG_APCI_1710
+ 		i_ADDI_AttachPCI1710(dev);
+ 
+-		// save base address
++		/*  save base address */
+ 		devpriv->s_BoardInfos.ui_Address = io_addr[2];
+ #endif
+ 	} else {
+-		//Update-0.7.57->0.7.68dev->n_subdevices = 7;
++		/* Update-0.7.57->0.7.68dev->n_subdevices = 7; */
+ 		n_subdevices = 7;
+ 		if ((ret = alloc_subdevices(dev, n_subdevices)) < 0)
+ 			return ret;
+ 
+-		// Allocate and Initialise AI Subdevice Structures
++		/*  Allocate and Initialise AI Subdevice Structures */
+ 		s = dev->subdevices + 0;
+ 		if ((this_board->i_NbrAiChannel)
+ 			|| (this_board->i_NbrAiChannelDiff)) {
+@@ -2786,7 +2786,7 @@ static int i_ADDI_Attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 			s->type = COMEDI_SUBD_UNUSED;
+ 		}
+ 
+-		// Allocate and Initialise AO Subdevice Structures
++		/*  Allocate and Initialise AO Subdevice Structures */
+ 		s = dev->subdevices + 1;
+ 		if (this_board->i_NbrAoChannel) {
+ 			s->type = COMEDI_SUBD_AO;
+@@ -2804,7 +2804,7 @@ static int i_ADDI_Attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 		} else {
+ 			s->type = COMEDI_SUBD_UNUSED;
+ 		}
+-		// Allocate and Initialise DI Subdevice Structures
++		/*  Allocate and Initialise DI Subdevice Structures */
+ 		s = dev->subdevices + 2;
+ 		if (this_board->i_NbrDiChannel) {
+ 			s->type = COMEDI_SUBD_DI;
+@@ -2824,7 +2824,7 @@ static int i_ADDI_Attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 		} else {
+ 			s->type = COMEDI_SUBD_UNUSED;
+ 		}
+-		// Allocate and Initialise DO Subdevice Structures
++		/*  Allocate and Initialise DO Subdevice Structures */
+ 		s = dev->subdevices + 3;
+ 		if (this_board->i_NbrDoChannel) {
+ 			s->type = COMEDI_SUBD_DO;
+@@ -2837,7 +2837,7 @@ static int i_ADDI_Attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 			s->range_table = &range_digital;
+ 			s->io_bits = 0xf;	/* all bits output */
+ 
+-			s->insn_config = this_board->i_hwdrv_InsnConfigDigitalOutput;	//for digital output memory..
++			s->insn_config = this_board->i_hwdrv_InsnConfigDigitalOutput;	/* for digital output memory.. */
+ 			s->insn_write =
+ 				this_board->i_hwdrv_InsnWriteDigitalOutput;
+ 			s->insn_bits =
+@@ -2848,7 +2848,7 @@ static int i_ADDI_Attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 			s->type = COMEDI_SUBD_UNUSED;
+ 		}
+ 
+-		// Allocate and Initialise Timer Subdevice Structures
++		/*  Allocate and Initialise Timer Subdevice Structures */
+ 		s = dev->subdevices + 4;
+ 		if (this_board->i_Timer) {
+ 			s->type = COMEDI_SUBD_TIMER;
+@@ -2868,7 +2868,7 @@ static int i_ADDI_Attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 			s->type = COMEDI_SUBD_UNUSED;
+ 		}
+ 
+-		// Allocate and Initialise TTL
++		/*  Allocate and Initialise TTL */
+ 		s = dev->subdevices + 5;
+ 		if (this_board->i_NbrTTLChannel) {
+ 			s->type = COMEDI_SUBD_TTLIO;
+@@ -2965,7 +2965,7 @@ static int i_ADDI_Detach(struct comedi_device * dev)
+ 		}
+ 
+ 		if (pci_list_builded) {
+-			//v_pci_card_list_cleanup(PCI_VENDOR_ID_AMCC);
++			/* v_pci_card_list_cleanup(PCI_VENDOR_ID_AMCC); */
+ 			v_pci_card_list_cleanup(this_board->i_VendorId);
+ 			pci_list_builded = 0;
+ 		}
+@@ -2999,7 +2999,7 @@ static int i_ADDI_Reset(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-// Interrupt function
++/* Interrupt function */
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :                                                        |
+@@ -3025,7 +3025,7 @@ static irqreturn_t v_ADDI_Interrupt(int irq, void *d)
+ 	return IRQ_RETVAL(1);
+ }
+ 
+-// EEPROM Read Function
++/* EEPROM Read Function */
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :                                                        |
+@@ -3051,12 +3051,12 @@ static int i_ADDIDATA_InsnReadEeprom(struct comedi_device * dev, struct comedi_s
+ {
+ 	unsigned short w_Data;
+ 	unsigned short w_Address;
+-	w_Address = CR_CHAN(insn->chanspec);	// address to be read as 0,1,2,3...255
++	w_Address = CR_CHAN(insn->chanspec);	/*  address to be read as 0,1,2,3...255 */
+ 
+ 	w_Data = w_EepromReadWord(devpriv->i_IobaseAmcc,
+ 		this_board->pc_EepromChip, 0x100 + (2 * w_Address));
+ 	data[0] = w_Data;
+-	//multiplied by 2 bcozinput will be like 0,1,2...255
++	/* multiplied by 2 bcozinput will be like 0,1,2...255 */
+ 	return insn->n;
+ 
+ }
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+index fbe7b27ae64f..0640a05339a3 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+@@ -62,36 +62,36 @@
+ 
+ /* structure for the boardtype */
+ struct addi_board {
+-	const char *pc_DriverName;	// driver name
+-	int i_VendorId;		//PCI vendor a device ID of card
++	const char *pc_DriverName;	/*  driver name */
++	int i_VendorId;		/* PCI vendor a device ID of card */
+ 	int i_DeviceId;
+ 	int i_IorangeBase0;
+ 	int i_IorangeBase1;
+-	int i_IorangeBase2;	//  base 2 range
+-	int i_IorangeBase3;	//  base 3 range
+-	int i_PCIEeprom;	// eeprom present or not
+-	char *pc_EepromChip;	// type of chip
+-	int i_NbrAiChannel;	// num of A/D chans
+-	int i_NbrAiChannelDiff;	// num of A/D chans in diff mode
+-	int i_AiChannelList;	// len of chanlist
+-	int i_NbrAoChannel;	// num of D/A chans
+-	int i_AiMaxdata;	// resolution of A/D
+-	int i_AoMaxdata;	// resolution of D/A
++	int i_IorangeBase2;	/*   base 2 range */
++	int i_IorangeBase3;	/*   base 3 range */
++	int i_PCIEeprom;	/*  eeprom present or not */
++	char *pc_EepromChip;	/*  type of chip */
++	int i_NbrAiChannel;	/*  num of A/D chans */
++	int i_NbrAiChannelDiff;	/*  num of A/D chans in diff mode */
++	int i_AiChannelList;	/*  len of chanlist */
++	int i_NbrAoChannel;	/*  num of D/A chans */
++	int i_AiMaxdata;	/*  resolution of A/D */
++	int i_AoMaxdata;	/*  resolution of D/A */
+         const struct comedi_lrange *pr_AiRangelist;	/* rangelist for A/D */
+         const struct comedi_lrange *pr_AoRangelist;	/* rangelist for D/A */
+ 
+-	int i_NbrDiChannel;	// Number of DI channels
+-	int i_NbrDoChannel;	// Number of DO channels
+-	int i_DoMaxdata;	// data to set all chanels high
++	int i_NbrDiChannel;	/*  Number of DI channels */
++	int i_NbrDoChannel;	/*  Number of DO channels */
++	int i_DoMaxdata;	/*  data to set all chanels high */
+ 
+-	int i_NbrTTLChannel;	// Number of TTL channels
++	int i_NbrTTLChannel;	/*  Number of TTL channels */
+ 	const struct comedi_lrange *pr_TTLRangelist;	/* rangelist for TTL */
+ 
+-	int i_Dma;		// dma present or not
+-	int i_Timer;		//   timer subdevice present or not
++	int i_Dma;		/*  dma present or not */
++	int i_Timer;		/*    timer subdevice present or not */
+ 	unsigned char b_AvailableConvertUnit;
+-	unsigned int ui_MinAcquisitiontimeNs;	// Minimum Acquisition in Nano secs
+-	unsigned int ui_MinDelaytimeNs;	// Minimum Delay in Nano secs
++	unsigned int ui_MinAcquisitiontimeNs;	/*  Minimum Acquisition in Nano secs */
++	unsigned int ui_MinDelaytimeNs;	/*  Minimum Delay in Nano secs */
+ 
+ 	/* interrupt and reset */
+ 	void (*v_hwdrv_Interrupt)(int irq, void *d);
+@@ -348,57 +348,57 @@ union str_ModuleInfo {
+ struct addi_private {
+ 
+ 	int iobase;
+-	int i_IobaseAmcc;	// base+size for AMCC chip
+-	int i_IobaseAddon;	//addon base address
++	int i_IobaseAmcc;	/*  base+size for AMCC chip */
++	int i_IobaseAddon;	/* addon base address */
+ 	int i_IobaseReserved;
+ 	unsigned long dw_AiBase;
+-	struct pcilst_struct *amcc;	// ptr too AMCC data
+-	unsigned char allocated;		// we have blocked card
+-	unsigned char b_ValidDriver;	// driver is ok
+-	unsigned char b_AiContinuous;	// we do unlimited AI
++	struct pcilst_struct *amcc;	/*  ptr too AMCC data */
++	unsigned char allocated;		/*  we have blocked card */
++	unsigned char b_ValidDriver;	/*  driver is ok */
++	unsigned char b_AiContinuous;	/*  we do unlimited AI */
+ 	unsigned char b_AiInitialisation;
+-	unsigned int ui_AiActualScan;	//how many scans we finished
+-	unsigned int ui_AiBufferPtr;	// data buffer ptr in samples
+-	unsigned int ui_AiNbrofChannels;	// how many channels is measured
+-	unsigned int ui_AiScanLength;	// Length of actual scanlist
+-	unsigned int ui_AiActualScanPosition;	// position in actual scan
+-	unsigned int * pui_AiChannelList;	// actual chanlist
+-	unsigned int ui_AiChannelList[32];	// actual chanlist
+-	unsigned char b_AiChannelConfiguration[32];	// actual chanlist
++	unsigned int ui_AiActualScan;	/* how many scans we finished */
++	unsigned int ui_AiBufferPtr;	/*  data buffer ptr in samples */
++	unsigned int ui_AiNbrofChannels;	/*  how many channels is measured */
++	unsigned int ui_AiScanLength;	/*  Length of actual scanlist */
++	unsigned int ui_AiActualScanPosition;	/*  position in actual scan */
++	unsigned int * pui_AiChannelList;	/*  actual chanlist */
++	unsigned int ui_AiChannelList[32];	/*  actual chanlist */
++	unsigned char b_AiChannelConfiguration[32];	/*  actual chanlist */
+ 	unsigned int ui_AiReadData[32];
+ 	unsigned int dw_AiInitialised;
+-	unsigned int ui_AiTimer0;	//Timer Constant for Timer0
+-	unsigned int ui_AiTimer1;	//Timer constant for Timer1
++	unsigned int ui_AiTimer0;	/* Timer Constant for Timer0 */
++	unsigned int ui_AiTimer1;	/* Timer constant for Timer1 */
+ 	unsigned int ui_AiFlags;
+ 	unsigned int ui_AiDataLength;
+-	short *AiData;	// Pointer to sample data
+-	unsigned int ui_AiNbrofScans;	// number of scans to do
+-	unsigned short us_UseDma;	// To use Dma or not
+-	unsigned char b_DmaDoubleBuffer;	// we can use double buffering
+-	unsigned int ui_DmaActualBuffer;	// which buffer is used now
++	short *AiData;	/*  Pointer to sample data */
++	unsigned int ui_AiNbrofScans;	/*  number of scans to do */
++	unsigned short us_UseDma;	/*  To use Dma or not */
++	unsigned char b_DmaDoubleBuffer;	/*  we can use double buffering */
++	unsigned int ui_DmaActualBuffer;	/*  which buffer is used now */
+ 	/* UPDATE-0.7.57->0.7.68 */
+ 	/* unsigned int               ul_DmaBufferVirtual[2]; pointers to begin of DMA buffer */
+-	short *ul_DmaBufferVirtual[2];	// pointers to begin of DMA buffer
+-	unsigned int ul_DmaBufferHw[2];	// hw address of DMA buff
+-	unsigned int ui_DmaBufferSize[2];	// size of dma buffer in bytes
+-	unsigned int ui_DmaBufferUsesize[2];	// which size we may now used for transfer
+-	unsigned int ui_DmaBufferSamples[2];	// size in samples
+-	unsigned int ui_DmaBufferPages[2];	// number of pages in buffer
+-	unsigned char b_DigitalOutputRegister;	// Digital Output Register
++	short *ul_DmaBufferVirtual[2];	/*  pointers to begin of DMA buffer */
++	unsigned int ul_DmaBufferHw[2];	/*  hw address of DMA buff */
++	unsigned int ui_DmaBufferSize[2];	/*  size of dma buffer in bytes */
++	unsigned int ui_DmaBufferUsesize[2];	/*  which size we may now used for transfer */
++	unsigned int ui_DmaBufferSamples[2];	/*  size in samples */
++	unsigned int ui_DmaBufferPages[2];	/*  number of pages in buffer */
++	unsigned char b_DigitalOutputRegister;	/*  Digital Output Register */
+ 	unsigned char b_OutputMemoryStatus;
+-	unsigned char b_AnalogInputChannelNbr;	// Analog input channel Nbr
+-	unsigned char b_AnalogOutputChannelNbr;	// Analog input Output  Nbr
+-	unsigned char b_TimerSelectMode;	// Contain data written at iobase + 0C
+-	unsigned char b_ModeSelectRegister;	// Contain data written at iobase + 0E
+-	unsigned short us_OutputRegister;	// Contain data written at iobase + 0
++	unsigned char b_AnalogInputChannelNbr;	/*  Analog input channel Nbr */
++	unsigned char b_AnalogOutputChannelNbr;	/*  Analog input Output  Nbr */
++	unsigned char b_TimerSelectMode;	/*  Contain data written at iobase + 0C */
++	unsigned char b_ModeSelectRegister;	/*  Contain data written at iobase + 0E */
++	unsigned short us_OutputRegister;	/*  Contain data written at iobase + 0 */
+ 	unsigned char b_InterruptState;
+-	unsigned char b_TimerInit;	// Specify if InitTimerWatchdog was load
+-	unsigned char b_TimerStarted;	// Specify if timer 2 is running or not
+-	unsigned char b_Timer2Mode;	// Specify the timer 2 mode
+-	unsigned char b_Timer2Interrupt;	//Timer2  interrupt enable or disable
+-	unsigned char b_AiCyclicAcquisition;	// indicate cyclic acquisition
+-	unsigned char b_InterruptMode;	// eoc eos or dma
+-	unsigned char b_EocEosInterrupt;	// Enable disable eoc eos interrupt
++	unsigned char b_TimerInit;	/*  Specify if InitTimerWatchdog was load */
++	unsigned char b_TimerStarted;	/*  Specify if timer 2 is running or not */
++	unsigned char b_Timer2Mode;	/*  Specify the timer 2 mode */
++	unsigned char b_Timer2Interrupt;	/* Timer2  interrupt enable or disable */
++	unsigned char b_AiCyclicAcquisition;	/*  indicate cyclic acquisition */
++	unsigned char b_InterruptMode;	/*  eoc eos or dma */
++	unsigned char b_EocEosInterrupt;	/*  Enable disable eoc eos interrupt */
+ 	unsigned int ui_EocEosConversionTime;
+ 	unsigned char b_EocEosConversionTimeBase;
+ 	unsigned char b_SingelDiff;
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+index e57692dc9e83..1de291750736 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+@@ -45,11 +45,11 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+   +----------+-----------+------------------------------------------------+
+ */
+ 
+-#define NVCMD_BEGIN_READ 	(0x7 << 5 )	// nvRam begin read command
+-#define NVCMD_LOAD_LOW   	(0x4 << 5 )	// nvRam load low command
+-#define NVCMD_LOAD_HIGH  	(0x5 << 5 )	// nvRam load high command
+-#define EE76_CMD_LEN    	13	// bits in instructions
+-#define EE_READ         	0x0180	// 01 1000 0000 read instruction
++#define NVCMD_BEGIN_READ 	(0x7 << 5 )	/*  nvRam begin read command */
++#define NVCMD_LOAD_LOW   	(0x4 << 5 )	/*  nvRam load low command */
++#define NVCMD_LOAD_HIGH  	(0x5 << 5 )	/*  nvRam load high command */
++#define EE76_CMD_LEN    	13	/*  bits in instructions */
++#define EE_READ         	0x0180	/*  01 1000 0000 read instruction */
+ 
+ #define EEPROM_DIGITALINPUT 			0
+ #define EEPROM_DIGITALOUTPUT			1
+@@ -82,13 +82,13 @@ struct str_DigitalOutputHeader {
+ };
+ 
+ 
+-// used for timer as well as watchdog
++/* used for timer as well as watchdog */
+ 
+ struct str_TimerDetails {
+ 
+ 	unsigned short w_HeaderSize;
+ 	unsigned char b_Resolution;
+-	unsigned char b_Mode;		// in case of Watchdog it is functionality
++	unsigned char b_Mode;		/*  in case of Watchdog it is functionality */
+ 	unsigned short w_MinTiming;
+ 	unsigned char b_TimeBase;
+ };
+@@ -97,7 +97,7 @@ struct str_TimerMainHeader {
+ 
+ 
+ 	unsigned short w_Ntimer;
+-	struct str_TimerDetails s_TimerDetails[4];	//  supports 4 timers
++	struct str_TimerDetails s_TimerDetails[4];	/*   supports 4 timers */
+ };
+ 
+ 
+@@ -206,9 +206,9 @@ unsigned short w_EepromReadWord(unsigned short w_PCIBoardEepromAddress, char *pc
+ 		for (b_Counter = 0; b_Counter < 2; b_Counter++)
+ 		{
+ 
+-			b_SelectedAddressLow = (w_EepromStartAddress + b_Counter) % 256;	//Read the low 8 bit part
++			b_SelectedAddressLow = (w_EepromStartAddress + b_Counter) % 256;	/* Read the low 8 bit part */
+ 
+-			b_SelectedAddressHigh = (w_EepromStartAddress + b_Counter) / 256;	//Read the high 8 bit part
++			b_SelectedAddressHigh = (w_EepromStartAddress + b_Counter) / 256;	/* Read the high 8 bit part */
+ 
+ 	      /************************************/
+ 
+@@ -319,20 +319,20 @@ unsigned short w_EepromReadWord(unsigned short w_PCIBoardEepromAddress, char *pc
+ 
+ 				b_ReadLowByte = b_ReadByte;
+ 
+-			}	// if(b_Counter==0)
++			}	/*  if(b_Counter==0) */
+ 
+ 			else
+ 			{
+ 
+ 				b_ReadHighByte = b_ReadByte;
+ 
+-			}	// if(b_Counter==0)
++			}	/*  if(b_Counter==0) */
+ 
+-		}		// for (b_Counter=0; b_Counter<2; b_Counter++)
++		}		/*  for (b_Counter=0; b_Counter<2; b_Counter++) */
+ 
+ 		w_ReadWord = (b_ReadLowByte | (((unsigned short) b_ReadHighByte) * 256));
+ 
+-	}			// end of if ((!strcmp(pc_PCIChipInformation, "S5920")) || (!strcmp(pc_PCIChipInformation, "S5933")))
++	}			/*  end of if ((!strcmp(pc_PCIChipInformation, "S5920")) || (!strcmp(pc_PCIChipInformation, "S5933"))) */
+ 
+ 	if (!strcmp(pc_PCIChipInformation, "93C76"))
+ 	{
+@@ -902,15 +902,15 @@ int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
+ 			break;
+ 
+ 		case EEPROM_TIMER:
+-			this_board->i_Timer = 1;	//Timer subdevice present
++			this_board->i_Timer = 1;	/* Timer subdevice present */
+ 			break;
+ 
+ 		case EEPROM_WATCHDOG:
+-			this_board->i_Timer = 1;	//Timer subdevice present
++			this_board->i_Timer = 1;	/* Timer subdevice present */
+ 			break;
+ 
+ 		case EEPROM_TIMER_WATCHDOG_COUNTER:
+-			this_board->i_Timer = 1;	//Timer subdevice present
++			this_board->i_Timer = 1;	/* Timer subdevice present */
+ 		}
+ 	}
+ 
+@@ -944,17 +944,17 @@ int i_EepromReadDigitalInputHeader(unsigned short w_PCIBoardEepromAddress,
+ {
+ 	unsigned short w_Temp;
+ 
+-	// read nbr of channels
++	/*  read nbr of channels */
+ 	s_Header->w_Nchannel =
+ 		w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
+ 		0x100 + w_Address + 6);
+ 
+-	// interruptible or not
++	/*  interruptible or not */
+ 	w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+ 		pc_PCIChipInformation, 0x100 + w_Address + 8);
+ 	s_Header->b_Interruptible = (unsigned char) (w_Temp >> 7) & 0x01;
+ 
+-// How many interruptible logic
++/* How many interruptible logic */
+ 	s_Header->w_NinterruptLogic =
+ 		w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
+ 		0x100 + w_Address + 10);
+@@ -987,7 +987,7 @@ int i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+ 	struct str_DigitalOutputHeader * s_Header)
+ {
+-// Read Nbr channels
++/* Read Nbr channels */
+ 	s_Header->w_Nchannel =
+ 		w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
+ 		0x100 + w_Address + 6);
+@@ -1021,11 +1021,11 @@ int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
+ 
+ 	unsigned short i, w_Size = 0, w_Temp;
+ 
+-//Read No of Timer
++/* Read No of Timer */
+ 	s_Header->w_Ntimer =
+ 		w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
+ 		0x100 + w_Address + 6);
+-//Read header size
++/* Read header size */
+ 
+ 	for (i = 0; i < s_Header->w_Ntimer; i++) {
+ 		s_Header->s_TimerDetails[i].w_HeaderSize =
+@@ -1036,11 +1036,11 @@ int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
+ 			pc_PCIChipInformation,
+ 			0x100 + w_Address + 8 + w_Size + 2);
+ 
+-		//Read Resolution
++		/* Read Resolution */
+ 		s_Header->s_TimerDetails[i].b_Resolution =
+ 			(unsigned char) (w_Temp >> 10) & 0x3F;
+ 
+-		//Read Mode
++		/* Read Mode */
+ 		s_Header->s_TimerDetails[i].b_Mode =
+ 			(unsigned char) (w_Temp >> 4) & 0x3F;
+ 
+@@ -1048,10 +1048,10 @@ int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
+ 			pc_PCIChipInformation,
+ 			0x100 + w_Address + 8 + w_Size + 4);
+ 
+-		//Read MinTiming
++		/* Read MinTiming */
+ 		s_Header->s_TimerDetails[i].w_MinTiming = (w_Temp >> 6) & 0x3FF;
+ 
+-		//Read Timebase
++		/* Read Timebase */
+ 		s_Header->s_TimerDetails[i].b_TimeBase = (unsigned char) (w_Temp) & 0x3F;
+ 		w_Size += s_Header->s_TimerDetails[i].w_HeaderSize;
+ 	}
+@@ -1085,11 +1085,11 @@ int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ 	str_AnalogOutputHeader * s_Header)
+ {
+ 	unsigned short w_Temp;
+-	// No of channels for 1st hard component
++	/*  No of channels for 1st hard component */
+ 	w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+ 		pc_PCIChipInformation, 0x100 + w_Address + 10);
+ 	s_Header->w_Nchannel = (w_Temp >> 4) & 0x03FF;
+-	// Resolution for 1st hard component
++	/*  Resolution for 1st hard component */
+ 	w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+ 		pc_PCIChipInformation, 0x100 + w_Address + 16);
+ 	s_Header->b_Resolution = (unsigned char) (w_Temp >> 8) & 0xFF;
+@@ -1117,7 +1117,7 @@ int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-// Reads only for ONE  hardware component
++/* Reads only for ONE  hardware component */
+ int i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+ 	struct str_AnalogInputHeader * s_Header)
+@@ -1134,24 +1134,24 @@ int i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress,
+ 		0x100 + w_Address + 30);
+ 	w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+ 		pc_PCIChipInformation, 0x100 + w_Address + 20);
+-	s_Header->b_HasDma = (w_Temp >> 13) & 0x01;	// whether dma present or not
++	s_Header->b_HasDma = (w_Temp >> 13) & 0x01;	/*  whether dma present or not */
+ 
+-	w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation, 0x100 + w_Address + 72);	// reading Y
++	w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation, 0x100 + w_Address + 72);	/*  reading Y */
+ 	w_Temp = w_Temp & 0x00FF;
+-	if (w_Temp)		//Y>0
++	if (w_Temp)		/* Y>0 */
+ 	{
+-		w_Offset = 74 + (2 * w_Temp) + (10 * (1 + (w_Temp / 16)));	// offset of first analog input single header
+-		w_Offset = w_Offset + 2;	// resolution
+-	} else			//Y=0
++		w_Offset = 74 + (2 * w_Temp) + (10 * (1 + (w_Temp / 16)));	/*  offset of first analog input single header */
++		w_Offset = w_Offset + 2;	/*  resolution */
++	} else			/* Y=0 */
+ 	{
+ 		w_Offset = 74;
+-		w_Offset = w_Offset + 2;	// resolution
++		w_Offset = w_Offset + 2;	/*  resolution */
+ 	}
+ 
+-// read Resolution
++/* read Resolution */
+ 	w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+ 		pc_PCIChipInformation, 0x100 + w_Address + w_Offset);
+-	s_Header->b_Resolution = w_Temp & 0x001F;	// last 5 bits
++	s_Header->b_Resolution = w_Temp & 0x001F;	/*  last 5 bits */
+ 
+ 	return 0;
+ }
+diff --git a/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h b/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h
+index 86e6578a20fe..bee6101d2e87 100644
+--- a/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h
++++ b/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h
+@@ -31,15 +31,15 @@
+ 
+ *************************/
+ 
+-#define FIFO_ADVANCE_ON_BYTE_2     0x20000000	// written on base0
++#define FIFO_ADVANCE_ON_BYTE_2     0x20000000	/*  written on base0 */
+ 
+-#define AMWEN_ENABLE                     0x02	// added for step 6 dma written on base2
++#define AMWEN_ENABLE                     0x02	/*  added for step 6 dma written on base2 */
+ #define A2P_FIFO_WRITE_ENABLE            0x01
+ 
+-#define AGCSTS_TC_ENABLE		   0x10000000	// Added for transfer count enable bit
++#define AGCSTS_TC_ENABLE		   0x10000000	/*  Added for transfer count enable bit */
+ 
+-//  ADDON RELATED ADDITIONS
+-// Constant
++/* ADDON RELATED ADDITIONS */
++/* Constant */
+ #define     APCI3120_ENABLE_TRANSFER_ADD_ON_LOW       0x00
+ #define     APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH      0x1200
+ #define     APCI3120_A2P_FIFO_MANAGEMENT              0x04000400L
+@@ -52,7 +52,7 @@
+ #define     APCI3120_DISABLE_BUS_MASTER_ADD_ON        0x0
+ #define     APCI3120_DISABLE_BUS_MASTER_PCI           0x0
+ 
+- // ADD_ON ::: this needed since apci supports 16 bit interface to add on
++ /*  ADD_ON ::: this needed since apci supports 16 bit interface to add on */
+ #define     APCI3120_ADD_ON_AGCSTS_LOW       0x3C
+ #define     APCI3120_ADD_ON_AGCSTS_HIGH      APCI3120_ADD_ON_AGCSTS_LOW + 2
+ #define     APCI3120_ADD_ON_MWAR_LOW         0x24
+@@ -60,7 +60,7 @@
+ #define     APCI3120_ADD_ON_MWTC_LOW         0x058
+ #define     APCI3120_ADD_ON_MWTC_HIGH        APCI3120_ADD_ON_MWTC_LOW + 2
+ 
+-// AMCC
++/* AMCC */
+ #define     APCI3120_AMCC_OP_MCSR            0x3C
+ #define     APCI3120_AMCC_OP_REG_INTCSR      0x38
+ 
+@@ -212,7 +212,7 @@ struct pcilst_struct {
+ 	unsigned int irq;
+ };
+ 
+-struct pcilst_struct *amcc_devices;	// ptr to root list of all amcc devices
++struct pcilst_struct *amcc_devices;	/*  ptr to root list of all amcc devices */
+ 
+ /****************************************************************************/
+ 
+@@ -267,7 +267,7 @@ void v_pci_card_list_init(unsigned short pci_vendor, char display)
+ 			amcc->vendor = pcidev->vendor;
+ 			amcc->device = pcidev->device;
+ #if 0
+-			amcc->master = pcidev->master;	// how get this information under 2.4 kernels?
++			amcc->master = pcidev->master;	/*  how get this information under 2.4 kernels? */
+ #endif
+ 			amcc->pci_bus = pcidev->bus->number;
+ 			amcc->pci_slot = PCI_SLOT(pcidev->devfn);
+@@ -333,17 +333,17 @@ int i_find_free_pci_card_by_position(unsigned short vendor_id,
+ 		    && (amcc->pci_slot == pci_slot)) {
+ 			if (!(amcc->used)) {
+ 				*card = amcc;
+-				return 0;	// ok, card is found
++				return 0;	/*  ok, card is found */
+ 			} else {
+ 				rt_printk
+ 				    (" - \nCard on requested position is used b:s %d:%d!\n",
+ 				     pci_bus, pci_slot);
+-				return 2;	// card exist but is used
++				return 2;	/*  card exist but is used */
+ 			}
+ 		}
+ 	}
+ 
+-	return 1;		// no card found
++	return 1;		/*  no card found */
+ }
+ 
+ /****************************************************************************/
+@@ -422,7 +422,7 @@ struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id,
+ {
+ 	struct pcilst_struct *card;
+ 
+-	if ((pci_bus < 1) & (pci_slot < 1)) {	// use autodetection
++	if ((pci_bus < 1) & (pci_slot < 1)) {	/*  use autodetection */
+ 		if ((card = ptr_find_free_pci_card_by_device(vendor_id,
+ 							     device_id)) ==
+ 		    NULL) {
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+index 098cd792e035..502aaeaa8020 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+@@ -62,11 +62,11 @@ void i_ADDI_AttachPCI1710(struct comedi_device * dev)
+ 	int ret = 0;
+ 	int n_subdevices = 9;
+ 
+-	//Update-0.7.57->0.7.68dev->n_subdevices = 9;
++	/* Update-0.7.57->0.7.68dev->n_subdevices = 9; */
+ 	if ((ret = alloc_subdevices(dev, n_subdevices)) < 0)
+ 		return;
+ 
+-	// Allocate and Initialise Timer Subdevice Structures
++	/*  Allocate and Initialise Timer Subdevice Structures */
+ 	s = dev->subdevices + 0;
+ 
+ 	s->type = COMEDI_SUBD_TIMER;
+@@ -80,7 +80,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device * dev)
+ 	s->insn_config = i_APCI1710_InsnConfigInitTimer;
+ 	s->insn_bits = i_APCI1710_InsnBitsTimer;
+ 
+-	// Allocate and Initialise DIO Subdevice Structures
++	/*  Allocate and Initialise DIO Subdevice Structures */
+ 	s = dev->subdevices + 1;
+ 
+ 	s->type = COMEDI_SUBD_DIO;
+@@ -95,7 +95,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device * dev)
+ 	s->insn_bits = i_APCI1710_InsnBitsDigitalIOPortOnOff;
+ 	s->insn_write = i_APCI1710_InsnWriteDigitalIOChlOnOff;
+ 
+-	// Allocate and Initialise Chrono Subdevice Structures
++	/*  Allocate and Initialise Chrono Subdevice Structures */
+ 	s = dev->subdevices + 2;
+ 
+ 	s->type = COMEDI_SUBD_CHRONO;
+@@ -109,7 +109,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device * dev)
+ 	s->insn_config = i_APCI1710_InsnConfigInitChrono;
+ 	s->insn_bits = i_APCI1710_InsnBitsChronoDigitalIO;
+ 
+-	// Allocate and Initialise PWM Subdevice Structures
++	/*  Allocate and Initialise PWM Subdevice Structures */
+ 	s = dev->subdevices + 3;
+ 	s->type = COMEDI_SUBD_PWM;
+ 	s->subdev_flags =
+@@ -118,13 +118,13 @@ void i_ADDI_AttachPCI1710(struct comedi_device * dev)
+ 	s->maxdata = 1;
+ 	s->len_chanlist = 3;
+ 	s->range_table = &range_digital;
+-	s->io_bits = 0;		//all bits input
++	s->io_bits = 0;		/* all bits input */
+ 	s->insn_config = i_APCI1710_InsnConfigPWM;
+ 	s->insn_read = i_APCI1710_InsnReadGetPWMStatus;
+ 	s->insn_write = i_APCI1710_InsnWritePWM;
+ 	s->insn_bits = i_APCI1710_InsnBitsReadPWMInterrupt;
+ 
+-	// Allocate and Initialise TTLIO Subdevice Structures
++	/*  Allocate and Initialise TTLIO Subdevice Structures */
+ 	s = dev->subdevices + 4;
+ 	s->type = COMEDI_SUBD_TTLIO;
+ 	s->subdev_flags =
+@@ -132,13 +132,13 @@ void i_ADDI_AttachPCI1710(struct comedi_device * dev)
+ 	s->n_chan = 8;
+ 	s->maxdata = 1;
+ 	s->len_chanlist = 8;
+-	s->range_table = &range_apci1710_ttl;	// to pass arguments in range
++	s->range_table = &range_apci1710_ttl;	/*  to pass arguments in range */
+ 	s->insn_config = i_APCI1710_InsnConfigInitTTLIO;
+ 	s->insn_bits = i_APCI1710_InsnBitsReadTTLIO;
+ 	s->insn_write = i_APCI1710_InsnWriteSetTTLIOChlOnOff;
+ 	s->insn_read = i_APCI1710_InsnReadTTLIOAllPortValue;
+ 
+-	// Allocate and Initialise TOR Subdevice Structures
++	/*  Allocate and Initialise TOR Subdevice Structures */
+ 	s = dev->subdevices + 5;
+ 	s->type = COMEDI_SUBD_TOR;
+ 	s->subdev_flags =
+@@ -147,13 +147,13 @@ void i_ADDI_AttachPCI1710(struct comedi_device * dev)
+ 	s->maxdata = 1;
+ 	s->len_chanlist = 8;
+ 	s->range_table = &range_digital;
+-	s->io_bits = 0;		//all bits input
++	s->io_bits = 0;		/* all bits input */
+ 	s->insn_config = i_APCI1710_InsnConfigInitTorCounter;
+ 	s->insn_read = i_APCI1710_InsnReadGetTorCounterInitialisation;
+ 	s->insn_write = i_APCI1710_InsnWriteEnableDisableTorCounter;
+ 	s->insn_bits = i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue;
+ 
+-	// Allocate and Initialise SSI Subdevice Structures
++	/*  Allocate and Initialise SSI Subdevice Structures */
+ 	s = dev->subdevices + 6;
+ 	s->type = COMEDI_SUBD_SSI;
+ 	s->subdev_flags =
+@@ -166,7 +166,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device * dev)
+ 	s->insn_read = i_APCI1710_InsnReadSSIValue;
+ 	s->insn_bits = i_APCI1710_InsnBitsSSIDigitalIO;
+ 
+-	// Allocate and Initialise PULSEENCODER Subdevice Structures
++	/*  Allocate and Initialise PULSEENCODER Subdevice Structures */
+ 	s = dev->subdevices + 7;
+ 	s->type = COMEDI_SUBD_PULSEENCODER;
+ 	s->subdev_flags =
+@@ -180,7 +180,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device * dev)
+ 	s->insn_bits = i_APCI1710_InsnBitsReadWritePulseEncoder;
+ 	s->insn_read = i_APCI1710_InsnReadInterruptPulseEncoder;
+ 
+-	// Allocate and Initialise INCREMENTALCOUNTER Subdevice Structures
++	/*  Allocate and Initialise INCREMENTALCOUNTER Subdevice Structures */
+ 	s = dev->subdevices + 8;
+ 	s->type = COMEDI_SUBD_INCREMENTALCOUNTER;
+ 	s->subdev_flags =
+@@ -197,7 +197,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device * dev)
+ 
+ int i_APCI1710_Reset(struct comedi_device * dev);
+ void v_APCI1710_Interrupt(int irq, void *d);
+-//for 1710
++/* for 1710 */
+ 
+ int i_APCI1710_Reset(struct comedi_device * dev)
+ {
+@@ -219,12 +219,12 @@ int i_APCI1710_Reset(struct comedi_device * dev)
+ 	ret = inl(devpriv->s_BoardInfos.ui_Address + 252);
+ 	devpriv->s_BoardInfos.dw_MolduleConfiguration[3] = ret;
+ 
+-	// outl(0x80808082,devpriv->s_BoardInfos.ui_Address+0x60);
++	/*  outl(0x80808082,devpriv->s_BoardInfos.ui_Address+0x60); */
+ 	outl(0x83838383, devpriv->s_BoardInfos.ui_Address + 0x60);
+ 
+ 	devpriv->s_BoardInfos.b_BoardVersion = 1;
+ 
+-	// Enable the interrupt for the controler
++	/*  Enable the interrupt for the controler */
+ 	dw_Dummy = inl(devpriv->s_BoardInfos.ui_Address + 0x38);
+ 	outl(dw_Dummy | 0x2000, devpriv->s_BoardInfos.ui_Address + 0x38);
+ 
+@@ -279,7 +279,7 @@ void v_APCI1710_Interrupt(int irq, void *d)
+ 				dw_MolduleConfiguration[b_ModuleCpt] &
+ 				0xFFFF0000UL) == APCI1710_82X54_TIMER) {
+ 
+-			//printk("TIMER Interrupt Occurred\n");
++			/* printk("TIMER Interrupt Occurred\n"); */
+ 			ul_82X54InterruptStatus = inl(devpriv->s_BoardInfos.
+ 				ui_Address + 12 + (64 * b_ModuleCpt));
+ 
+@@ -332,11 +332,11 @@ void v_APCI1710_Interrupt(int irq, void *d)
+ 			     /**********************/
+ 				/* Call user function */
+ 			     /**********************/
+-				//Send a signal to from kernel to user space
++				/* Send a signal to from kernel to user space */
+ 				send_sig(SIGIO, devpriv->tsk_Current, 0);
+ 
+-			}	// if ((ul_82X54InterruptStatus & 0x7) != 0)
+-		}		// 82X54 timer
++			}	/*  if ((ul_82X54InterruptStatus & 0x7) != 0) */
++		}		/*  82X54 timer */
+ 
+ 		 /***************************/
+ 		/* Test if increm. counter */
+@@ -412,7 +412,7 @@ void v_APCI1710_Interrupt(int irq, void *d)
+ 				/**********************/
+ 					/* Call user function */
+ 				/**********************/
+-					//Send a signal to from kernel to user space
++					/* Send a signal to from kernel to user space */
+ 					send_sig(SIGIO, devpriv->tsk_Current,
+ 						0);
+ 
+@@ -473,7 +473,7 @@ void v_APCI1710_Interrupt(int irq, void *d)
+ 			    /**********************/
+ 					/* Call user function */
+ 				/**********************/
+-					//Send a signal to from kernel to user space
++					/* Send a signal to from kernel to user space */
+ 					send_sig(SIGIO, devpriv->tsk_Current,
+ 						0);
+ 
+@@ -562,7 +562,7 @@ void v_APCI1710_Interrupt(int irq, void *d)
+ 				/**********************/
+ 					/* Call user function */
+ 				/**********************/
+-					//Send a signal to from kernel to user space
++					/* Send a signal to from kernel to user space */
+ 					send_sig(SIGIO, devpriv->tsk_Current,
+ 						0);
+ 
+@@ -628,7 +628,7 @@ void v_APCI1710_Interrupt(int irq, void *d)
+ 				/**********************/
+ 					/* Call user function */
+ 				/**********************/
+-					//Send a signal to from kernel to user space
++					/* Send a signal to from kernel to user space */
+ 					send_sig(SIGIO, devpriv->tsk_Current,
+ 						0);
+ 
+@@ -795,11 +795,11 @@ void v_APCI1710_Interrupt(int irq, void *d)
+ 			     /**********************/
+ 				/* Call user function */
+ 			     /**********************/
+-				//Send a signal to from kernel to user space
++				/* Send a signal to from kernel to user space */
+ 				send_sig(SIGIO, devpriv->tsk_Current, 0);
+ 
+ 			}
+-		}		// Incremental counter
++		}		/*  Incremental counter */
+ 
+ 		 /***************/
+ 		/* Test if CDA */
+@@ -870,14 +870,14 @@ void v_APCI1710_Interrupt(int irq, void *d)
+ 					/* Call user function */
+ 				/**********************/
+ 
+-					//Send a signal to from kernel to user space
++					/* Send a signal to from kernel to user space */
+ 					send_sig(SIGIO, devpriv->tsk_Current,
+ 						0);
+ 
+-				}	// if (ul_StatusRegister & 1)
++				}	/*  if (ul_StatusRegister & 1) */
+ 
+ 			}
+-		}		// CDA
++		}		/*  CDA */
+ 
+ 		 /***********************/
+ 		/* Test if PWM counter */
+@@ -950,15 +950,15 @@ void v_APCI1710_Interrupt(int irq, void *d)
+ 				   /**********************/
+ 						/* Call user function */
+ 				   /**********************/
+-						//Send a signal to from kernel to user space
++						/* Send a signal to from kernel to user space */
+ 						send_sig(SIGIO,
+ 							devpriv->tsk_Current,
+ 							0);
+ 
+-					}	// if (ul_StatusRegister & 0x1)
+-				}	// if (APCI1710_ENABLE)
+-			}	// for (b_PWMCpt == 0; b_PWMCpt < 0; b_PWMCpt ++)
+-		}		// PWM counter
++					}	/*  if (ul_StatusRegister & 0x1) */
++				}	/*  if (APCI1710_ENABLE) */
++			}	/*  for (b_PWMCpt == 0; b_PWMCpt < 0; b_PWMCpt ++) */
++		}		/*  PWM counter */
+ 
+ 		 /***********************/
+ 		/* Test if tor counter */
+@@ -1054,14 +1054,14 @@ void v_APCI1710_Interrupt(int irq, void *d)
+ 						/* Call user function */
+ 				   /**********************/
+ 
+-						//Send a signal to from kernel to user space
++						/* Send a signal to from kernel to user space */
+ 						send_sig(SIGIO,
+ 							devpriv->tsk_Current,
+ 							0);
+-					}	// if (ul_StatusRegister & 0x1)
+-				}	// if (APCI1710_ENABLE)
+-			}	// for (b_TorCounterCpt == 0; b_TorCounterCpt < 0; b_TorCounterCpt ++)
+-		}		// Tor counter
++					}	/*  if (ul_StatusRegister & 0x1) */
++				}	/*  if (APCI1710_ENABLE) */
++			}	/*  for (b_TorCounterCpt == 0; b_TorCounterCpt < 0; b_TorCounterCpt ++) */
++		}		/*  Tor counter */
+ 
+ 		 /***********************/
+ 		/* Test if chronometer */
+@@ -1071,7 +1071,7 @@ void v_APCI1710_Interrupt(int irq, void *d)
+ 				dw_MolduleConfiguration[b_ModuleCpt] &
+ 				0xFFFF0000UL) == APCI1710_CHRONOMETER) {
+ 
+-			//printk("APCI1710 Chrono Interrupt\n");
++			/* printk("APCI1710 Chrono Interrupt\n"); */
+ 		    /*****************************/
+ 			/* Read the interrupt status */
+ 		    /*****************************/
+@@ -1163,13 +1163,13 @@ void v_APCI1710_Interrupt(int irq, void *d)
+ 				/**********************/
+ 					/* Call user function */
+ 				/**********************/
+-					//Send a signal to from kernel to user space
++					/* Send a signal to from kernel to user space */
+ 					send_sig(SIGIO, devpriv->tsk_Current,
+ 						0);
+ 
+ 				}
+ 			}
+-		}		// Chronometer
++		}		/*  Chronometer */
+ 
+ 		 /*************************/
+ 		/* Test if pulse encoder */
+@@ -1249,7 +1249,7 @@ void v_APCI1710_Interrupt(int irq, void *d)
+ 				   /**********************/
+ 						/* Call user function */
+ 				   /**********************/
+-						//Send a signal to from kernel to user space
++						/* Send a signal to from kernel to user space */
+ 						send_sig(SIGIO,
+ 							devpriv->tsk_Current,
+ 							0);
+@@ -1257,7 +1257,7 @@ void v_APCI1710_Interrupt(int irq, void *d)
+ 					}
+ 				}
+ 			}
+-		}		//pulse encoder
++		}		/* pulse encoder */
+ 
+ 	}
+ 	return;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.h
+index 998cbba8afeb..22b3e569ecd5 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.h
+@@ -44,7 +44,7 @@
+ #define APCI1710_SYNCHRONOUS_MODE	1
+ #define APCI1710_ASYNCHRONOUS_MODE	0
+ 
+-//MODULE INFO STRUCTURE
++/* MODULE INFO STRUCTURE */
+ 
+ static const struct comedi_lrange range_apci1710_ttl = { 4, {
+ 						      BIP_RANGE(10),
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
+index 42160d82e0be..e9c7a3c1c39f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
+@@ -124,9 +124,9 @@ int i_APCI035_ConfigTimerWatchdog(struct comedi_device * dev, struct comedi_subd
+ 	} else {
+ 		ui_Mode = 0;
+ 	}
+-//ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12);
++/* ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12); */
+ 	ui_Command = 0;
+-//ui_Command = ui_Command & 0xFFFFF9FEUL;
++/* ui_Command = ui_Command & 0xFFFFF9FEUL; */
+ 	outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+ 	ui_Command = 0;
+ 	ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+@@ -153,7 +153,7 @@ int i_APCI035_ConfigTimerWatchdog(struct comedi_device * dev, struct comedi_subd
+ 		ui_Command =
+ 			(ui_Command & 0xFFF719E2UL) | ui_Mode << 13UL | 0x10UL;
+ 
+-	}			//if (data[0] == ADDIDATA_TIMER)
++	}			/* if (data[0] == ADDIDATA_TIMER) */
+ 	else {
+ 		if (data[0] == ADDIDATA_WATCHDOG) {
+ 
+@@ -292,7 +292,7 @@ int i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device * dev,
+ 		ui_Command = (ui_Command & 0xFFFFF9FFUL) | 0x1UL;
+ 		outl(ui_Command,
+ 			devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+-	}			// if  (data[0]==1)
++	}			/*  if  (data[0]==1) */
+ 	if (data[0] == 2) {
+ 		ui_Command =
+ 			inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+@@ -304,16 +304,18 @@ int i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device * dev,
+ 			devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+ 	}
+ 
+-	if (data[0] == 0)	//Stop The Watchdog
++	if (data[0] == 0)	/* Stop The Watchdog */
+ 	{
+-		//Stop The Watchdog
++		/* Stop The Watchdog */
+ 		ui_Command = 0;
+-		//ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12);
+-		//ui_Command = ui_Command & 0xFFFFF9FEUL;
++/*
++* ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12);
++* ui_Command = ui_Command & 0xFFFFF9FEUL;
++*/
+ 		outl(ui_Command,
+ 			devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+-	}			//  if (data[1]==0)
+-	if (data[0] == 3)	//stop all Watchdogs
++	}			/*   if (data[1]==0) */
++	if (data[0] == 3)	/* stop all Watchdogs */
+ 	{
+ 		ui_Command = 0;
+ 		for (i_Count = 1; i_Count <= 4; i_Count++) {
+@@ -329,7 +331,7 @@ int i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device * dev,
+ 		}
+ 
+ 	}
+-	if (data[0] == 4)	//start all Watchdogs
++	if (data[0] == 4)	/* start all Watchdogs */
+ 	{
+ 		ui_Command = 0;
+ 		for (i_Count = 1; i_Count <= 4; i_Count++) {
+@@ -344,7 +346,7 @@ int i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device * dev,
+ 				0);
+ 		}
+ 	}
+-	if (data[0] == 5)	//trigger all Watchdogs
++	if (data[0] == 5)	/* trigger all Watchdogs */
+ 	{
+ 		ui_Command = 0;
+ 		for (i_Count = 1; i_Count <= 4; i_Count++) {
+@@ -394,7 +396,7 @@ int i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device * dev,
+ int i_APCI035_ReadTimerWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	unsigned int ui_Status = 0;	// Status register
++	unsigned int ui_Status = 0;	/*  Status register */
+ 	i_WatchdogNbr = insn->unused[0];
+ 	      /******************/
+ 	/* Get the status */
+@@ -419,7 +421,7 @@ int i_APCI035_ReadTimerWatchdog(struct comedi_device * dev, struct comedi_subdev
+ 	if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
+ 		data[4] = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0);
+ 
+-	}			//  if  (devpriv->b_TimerSelectMode==ADDIDATA_TIMER)
++	}			/*   if  (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */
+ 
+ 	return insn->n;
+ }
+@@ -524,9 +526,9 @@ int i_APCI035_Reset(struct comedi_device * dev)
+ 	int i_Count = 0;
+ 	for (i_Count = 1; i_Count <= 4; i_Count++) {
+ 		i_WatchdogNbr = i_Count;
+-		outl(0x0, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0);	//stop all timers
++		outl(0x0, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0);	/* stop all timers */
+ 	}
+-	outl(0x0, devpriv->iobase + 128 + 12);	//Disable the warning delay
++	outl(0x0, devpriv->iobase + 128 + 12);	/* Disable the warning delay */
+ 
+ 	return 0;
+ }
+@@ -571,7 +573,7 @@ static void v_APCI035_Interrupt(int irq, void *d)
+ 	ui_StatusRegister2 =
+ 		inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 20);
+ 
+-	if ((((ui_StatusRegister1) & 0x8) == 0x8))	//Test if warning relay interrupt
++	if ((((ui_StatusRegister1) & 0x8) == 0x8))	/* Test if warning relay interrupt */
+ 	{
+ 	/**********************************/
+ 		/* Disable the temperature warning */
+@@ -587,14 +589,14 @@ static void v_APCI035_Interrupt(int irq, void *d)
+ 		/* Read the digital temperature value */
+ 	/**************************************/
+ 		ui_DigitalTemperature = inl(devpriv->iobase + 128 + 60);
+-		send_sig(SIGIO, devpriv->tsk_Current, 0);	// send signal to the sample
+-	}			//if (((ui_StatusRegister1 & 0x8) == 0x8))
++		send_sig(SIGIO, devpriv->tsk_Current, 0);	/*  send signal to the sample */
++	}			/* if (((ui_StatusRegister1 & 0x8) == 0x8)) */
+ 
+ 	else {
+ 		if ((ui_StatusRegister2 & 0x1) == 0x1) {
+-			send_sig(SIGIO, devpriv->tsk_Current, 0);	// send signal to the sample
++			send_sig(SIGIO, devpriv->tsk_Current, 0);	/*  send signal to the sample */
+ 		}
+-	}			//else if (((ui_StatusRegister1 & 0x8) == 0x8))
++	}			/* else if (((ui_StatusRegister1 & 0x8) == 0x8)) */
+ 
+ 	return;
+ }
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+index 3c4086521412..0966ad6214a5 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+@@ -53,7 +53,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ */
+ #include "hwdrv_apci1032.h"
+ #include 
+-//Global variables
++/* Global variables */
+ unsigned int ui_InterruptStatus = 0;
+ 
+ /*
+@@ -107,11 +107,11 @@ int i_APCI1032_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subd
+ 			outl(0x4, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
+ 			ui_TmpValue =
+ 				inl(devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
+-		}		//if (data[1] == ADDIDATA_OR)
++		}		/* if (data[1] == ADDIDATA_OR) */
+ 		else {
+ 			outl(0x6, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
+-		}		//else if(data[1] == ADDIDATA_OR)
+-	}			// if( data[0] == ADDIDATA_ENABLE)
++		}		/* else if(data[1] == ADDIDATA_OR) */
++	}			/*  if( data[0] == ADDIDATA_ENABLE) */
+ 	else {
+ 		ul_Command1 = ul_Command1 & 0xFFFF0000;
+ 		ul_Command2 = ul_Command2 & 0xFFFF0000;
+@@ -120,7 +120,7 @@ int i_APCI1032_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subd
+ 		outl(ul_Command2,
+ 			devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE2);
+ 		outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
+-	}			//else if  ( data[0] == ADDIDATA_ENABLE)
++	}			/* else if  ( data[0] == ADDIDATA_ENABLE) */
+ 
+ 	return insn->n;
+ }
+@@ -152,14 +152,16 @@ int i_APCI1032_Read1DigitalInput(struct comedi_device * dev, struct comedi_subde
+ 	ui_Channel = CR_CHAN(insn->chanspec);
+ 	if (ui_Channel >= 0 && ui_Channel <= 31) {
+ 		ui_TmpValue = (unsigned int) inl(devpriv->iobase + APCI1032_DIGITAL_IP);
+-		//  since only 1 channel reqd  to bring it to last bit it is rotated
+-		//  8 +(chan - 1) times then ANDed with 1 for last bit.
++/*
++* since only 1 channel reqd to bring it to last bit it is rotated 8
++* +(chan - 1) times then ANDed with 1 for last bit.
++*/
+ 		*data = (ui_TmpValue >> ui_Channel) & 0x1;
+-	}			//if(ui_Channel >= 0 && ui_Channel <=31)
++	}			/* if(ui_Channel >= 0 && ui_Channel <=31) */
+ 	else {
+-		//comedi_error(dev," \n chan spec wrong\n");
+-		return -EINVAL;	// "sorry channel spec wrong "
+-	}			//else if(ui_Channel >= 0 && ui_Channel <=31)
++		/* comedi_error(dev," \n chan spec wrong\n"); */
++		return -EINVAL;	/*  "sorry channel spec wrong " */
++	}			/* else if(ui_Channel >= 0 && ui_Channel <=31) */
+ 	return insn->n;
+ }
+ 
+@@ -213,16 +215,16 @@ int i_APCI1032_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ 		case 31:
+ 			break;
+ 		default:
+-			//comedi_error(dev," \nchan spec wrong\n");
+-			return -EINVAL;	// "sorry channel spec wrong "
++			/* comedi_error(dev," \nchan spec wrong\n"); */
++			return -EINVAL;	/*  "sorry channel spec wrong " */
+ 			break;
+-		}		//switch(ui_NoOfChannels)
+-	}			//if(data[1]==0)
++		}		/* switch(ui_NoOfChannels) */
++	}			/* if(data[1]==0) */
+ 	else {
+ 		if (data[1] == 1) {
+ 			*data = ui_InterruptStatus;
+-		}		//if(data[1]==1)
+-	}			//else if(data[1]==0)
++		}		/* if(data[1]==1) */
++	}			/* else if(data[1]==0) */
+ 	return insn->n;
+ }
+ 
+@@ -248,15 +250,15 @@ static void v_APCI1032_Interrupt(int irq, void *d)
+ 	struct comedi_device *dev = d;
+ 
+ 	unsigned int ui_Temp;
+-	//disable the interrupt
++	/* disable the interrupt */
+ 	ui_Temp = inl(devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
+ 	outl(ui_Temp & APCI1032_DIGITAL_IP_INTERRUPT_DISABLE,
+ 		devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
+ 	ui_InterruptStatus =
+ 		inl(devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_STATUS);
+ 	ui_InterruptStatus = ui_InterruptStatus & 0X0000FFFF;
+-	send_sig(SIGIO, devpriv->tsk_Current, 0);	// send signal to the sample
+-	outl(ui_Temp, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);	//enable the interrupt
++	send_sig(SIGIO, devpriv->tsk_Current, 0);	/*  send signal to the sample */
++	outl(ui_Temp, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);	/* enable the interrupt */
+ 	return;
+ }
+ 
+@@ -277,9 +279,9 @@ static void v_APCI1032_Interrupt(int irq, void *d)
+ 
+ int i_APCI1032_Reset(struct comedi_device * dev)
+ {
+-	outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);	//disable the interrupts
+-	inl(devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_STATUS);	//Reset the interrupt status register
+-	outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE1);	//Disable the and/or interrupt
++	outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);	/* disable the interrupts */
++	inl(devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_STATUS);	/* Reset the interrupt status register */
++	outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE1);	/* Disable the and/or interrupt */
+ 	outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE2);
+ 	return 0;
+ }
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
+index cb1fb9dbe1f4..e29a72a568f3 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
+@@ -19,33 +19,34 @@
+ 
+ #define APCI1032_BOARD_VENDOR_ID 0x15B8
+ #define APCI1032_ADDRESS_RANGE  20
+-//DIGITAL INPUT DEFINE
++/* DIGITAL INPUT DEFINE */
+ 
+ #define APCI1032_DIGITAL_IP                     0
+ #define APCI1032_DIGITAL_IP_INTERRUPT_MODE1     4
+ #define APCI1032_DIGITAL_IP_INTERRUPT_MODE2     8
+ #define APCI1032_DIGITAL_IP_IRQ                 16
+ 
+-//Digital Input IRQ Function Selection
++/* Digital Input IRQ Function Selection */
+ #define ADDIDATA_OR                  0
+ #define ADDIDATA_AND                 1
+ 
+-//Digital Input Interrupt Status
++/* Digital Input Interrupt Status */
+ #define APCI1032_DIGITAL_IP_INTERRUPT_STATUS    12
+ 
+-//Digital Input Interrupt Enable Disable.
++/* Digital Input Interrupt Enable Disable. */
+ #define APCI1032_DIGITAL_IP_INTERRUPT_ENABLE    0x4
+ #define APCI1032_DIGITAL_IP_INTERRUPT_DISABLE   0xFFFFFFFB
+ 
+-//ADDIDATA Enable Disable
++/* ADDIDATA Enable Disable */
+ 
+ #define ADDIDATA_ENABLE                            1
+ #define ADDIDATA_DISABLE                           0
+ 
+-// Hardware Layer  functions for Apci1032
++/* Hardware Layer  functions for Apci1032 */
+ 
+-//DI
+-// for di read
++/*
++* DI for di read
++*/
+ 
+ int i_APCI1032_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				  struct comedi_insn *insn, unsigned int *data);
+@@ -56,8 +57,8 @@ int i_APCI1032_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdev
+ int i_APCI1032_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				    struct comedi_insn *insn, unsigned int *data);
+ 
+-// Interrupt functions.....
++/* Interrupt functions..... */
+ 
+ static void v_APCI1032_Interrupt(int irq, void *d);
+-//Reset
++/* Reset */
+ int i_APCI1032_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h
+index 5d960b40a6a8..057903366a80 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h
+@@ -17,11 +17,11 @@
+ 
+ /*********      Definitions for APCI-1500 card  *****/
+ 
+-// Card Specific information
++/* Card Specific information */
+ #define APCI1500_BOARD_VENDOR_ID           0x10e8
+ #define APCI1500_ADDRESS_RANGE              4
+ 
+-//DIGITAL INPUT-OUTPUT DEFINE
++/* DIGITAL INPUT-OUTPUT DEFINE */
+ 
+ #define  APCI1500_DIGITAL_OP                 	2
+ #define  APCI1500_DIGITAL_IP                    0
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
+index 3d09025c548a..bcc9b7a67f2e 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
+@@ -81,14 +81,14 @@ int i_APCI1516_Read1DigitalInput(struct comedi_device * dev, struct comedi_subde
+ 	ui_Channel = CR_CHAN(insn->chanspec);
+ 	if (ui_Channel >= 0 && ui_Channel <= 7) {
+ 		ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI1516_DIGITAL_IP);
+-		//  since only 1 channel reqd  to bring it to last bit it is rotated
+-		//  8 +(chan - 1) times then ANDed with 1 for last bit.
++		/*   since only 1 channel reqd  to bring it to last bit it is rotated */
++		/*   8 +(chan - 1) times then ANDed with 1 for last bit. */
+ 		*data = (ui_TmpValue >> ui_Channel) & 0x1;
+-	}			//if(ui_Channel >= 0 && ui_Channel <=7)
++	}			/* if(ui_Channel >= 0 && ui_Channel <=7) */
+ 	else {
+-		//comedi_error(dev," \n chan spec wrong\n");
+-		return -EINVAL;	// "sorry channel spec wrong "
+-	}			//else if(ui_Channel >= 0 && ui_Channel <=7)
++		/* comedi_error(dev," \n chan spec wrong\n"); */
++		return -EINVAL;	/*  "sorry channel spec wrong " */
++	}			/* else if(ui_Channel >= 0 && ui_Channel <=7) */
+ 
+ 	return insn->n;
+ }
+@@ -139,9 +139,9 @@ int i_APCI1516_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ 
+ 	default:
+ 		printk("\nWrong parameters\n");
+-		return -EINVAL;	// "sorry channel spec wrong "
++		return -EINVAL;	/*  "sorry channel spec wrong " */
+ 		break;
+-	}			//switch(ui_NoOfChannels)
++	}			/* switch(ui_NoOfChannels) */
+ 
+ 	return insn->n;
+ }
+@@ -203,17 +203,17 @@ int i_APCI1516_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int ui_Temp, ui_Temp1;
+-	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
++	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	/*  get the channel */
+ 
+ 	printk("EL311003 : @=%x\n", devpriv->iobase + APCI1516_DIGITAL_OP);
+ 
+ 	if (devpriv->b_OutputMemoryStatus) {
+ 		ui_Temp = inw(devpriv->iobase + APCI1516_DIGITAL_OP);
+ 
+-	}			//if(devpriv->b_OutputMemoryStatus )
++	}			/* if(devpriv->b_OutputMemoryStatus ) */
+ 	else {
+ 		ui_Temp = 0;
+-	}			//if(devpriv->b_OutputMemoryStatus )
++	}			/* if(devpriv->b_OutputMemoryStatus ) */
+ 	if (data[3] == 0) {
+ 		if (data[1] == 0) {
+ 			data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
+@@ -222,7 +222,7 @@ int i_APCI1516_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 			printk("EL311003 : d=%d @=%x\n", data[0],
+ 				devpriv->iobase + APCI1516_DIGITAL_OP);
+ 
+-		}		//if(data[1]==0)
++		}		/* if(data[1]==0) */
+ 		else {
+ 			if (data[1] == 1) {
+ 				switch (ui_NoOfChannel) {
+@@ -245,21 +245,21 @@ int i_APCI1516_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 
+ 				default:
+ 					comedi_error(dev, " chan spec wrong");
+-					return -EINVAL;	// "sorry channel spec wrong "
++					return -EINVAL;	/*  "sorry channel spec wrong " */
+ 
+-				}	//switch(ui_NoOfChannels)
++				}	/* switch(ui_NoOfChannels) */
+ 
+ 				outw(data[0],
+ 					devpriv->iobase + APCI1516_DIGITAL_OP);
+ 
+ 				printk("EL311003 : d=%d @=%x\n", data[0],
+ 					devpriv->iobase + APCI1516_DIGITAL_OP);
+-			}	// if(data[1]==1)
++			}	/*  if(data[1]==1) */
+ 			else {
+ 				printk("\nSpecified channel not supported\n");
+-			}	//else if(data[1]==1)
+-		}		//elseif(data[1]==0)
+-	}			//if(data[3]==0)
++			}	/* else if(data[1]==1) */
++		}		/* elseif(data[1]==0) */
++	}			/* if(data[3]==0) */
+ 	else {
+ 		if (data[3] == 1) {
+ 			if (data[1] == 0) {
+@@ -275,7 +275,7 @@ int i_APCI1516_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 				printk("EL311003 : d=%d @=%x\n", data[0],
+ 					devpriv->iobase + APCI1516_DIGITAL_OP);
+ 
+-			}	//if(data[1]==0)
++			}	/* if(data[1]==0) */
+ 			else {
+ 				if (data[1] == 1) {
+ 					switch (ui_NoOfChannel) {
+@@ -312,9 +312,9 @@ int i_APCI1516_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 					default:
+ 						comedi_error(dev,
+ 							" chan spec wrong");
+-						return -EINVAL;	// "sorry channel spec wrong "
++						return -EINVAL;	/*  "sorry channel spec wrong " */
+ 
+-					}	//switch(ui_NoOfChannels)
++					}	/* switch(ui_NoOfChannels) */
+ 
+ 					outw(data[0],
+ 						devpriv->iobase +
+@@ -324,17 +324,17 @@ int i_APCI1516_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 						data[0],
+ 						devpriv->iobase +
+ 						APCI1516_DIGITAL_OP);
+-				}	// if(data[1]==1)
++				}	/*  if(data[1]==1) */
+ 				else {
+ 					printk("\nSpecified channel not supported\n");
+-				}	//else if(data[1]==1)
+-			}	//elseif(data[1]==0)
+-		}		//if(data[3]==1);
++				}	/* else if(data[1]==1) */
++			}	/* elseif(data[1]==0) */
++		}		/* if(data[3]==1); */
+ 		else {
+ 			printk("\nSpecified functionality does not exist\n");
+ 			return -EINVAL;
+-		}		//if else data[3]==1)
+-	}			//if else data[3]==0)
++		}		/* if else data[3]==1) */
++	}			/* if else data[3]==0) */
+ 	return (insn->n);;
+ }
+ 
+@@ -364,12 +364,12 @@ int i_APCI1516_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ {
+ 
+ 	unsigned int ui_Temp;
+-	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
++	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	/*  get the channel */
+ 	ui_Temp = data[0];
+ 	*data = inw(devpriv->iobase + APCI1516_DIGITAL_OP_RW);
+ 	if (ui_Temp == 0) {
+ 		*data = (*data >> ui_NoOfChannel) & 0x1;
+-	}			//if(ui_Temp==0)
++	}			/* if(ui_Temp==0) */
+ 	else {
+ 		if (ui_Temp == 1) {
+ 			switch (ui_NoOfChannel) {
+@@ -387,14 +387,14 @@ int i_APCI1516_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ 
+ 			default:
+ 				comedi_error(dev, " chan spec wrong");
+-				return -EINVAL;	// "sorry channel spec wrong "
++				return -EINVAL;	/*  "sorry channel spec wrong " */
+ 
+-			}	//switch(ui_NoOfChannels)
+-		}		//if(ui_Temp==1)
++			}	/* switch(ui_NoOfChannels) */
++		}		/* if(ui_Temp==1) */
+ 		else {
+ 			printk("\nSpecified channel not supported \n");
+-		}		//elseif(ui_Temp==1)
+-	}			//elseif(ui_Temp==0)
++		}		/* elseif(ui_Temp==1) */
++	}			/* elseif(ui_Temp==0) */
+ 	return insn->n;
+ }
+ 
+@@ -423,11 +423,11 @@ int i_APCI1516_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevic
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0] == 0) {
+-		//Disable the watchdog
++		/* Disable the watchdog */
+ 		outw(0x0,
+ 			devpriv->i_IobaseAddon +
+ 			APCI1516_WATCHDOG_ENABLEDISABLE);
+-		//Loading the Reload value
++		/* Loading the Reload value */
+ 		outw(data[1],
+ 			devpriv->i_IobaseAddon +
+ 			APCI1516_WATCHDOG_RELOAD_VALUE);
+@@ -435,11 +435,11 @@ int i_APCI1516_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevic
+ 		outw(data[1],
+ 			devpriv->i_IobaseAddon +
+ 			APCI1516_WATCHDOG_RELOAD_VALUE + 2);
+-	}			//if(data[0]==0)
++	}			/* if(data[0]==0) */
+ 	else {
+ 		printk("\nThe input parameters are wrong\n");
+ 		return -EINVAL;
+-	}			//elseif(data[0]==0)
++	}			/* elseif(data[0]==0) */
+ 
+ 	return insn->n;
+ }
+@@ -469,15 +469,15 @@ int i_APCI1516_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+-	case 0:		//stop the watchdog
+-		outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_ENABLEDISABLE);	//disable the watchdog
++	case 0:		/* stop the watchdog */
++		outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_ENABLEDISABLE);	/* disable the watchdog */
+ 		break;
+-	case 1:		//start the watchdog
++	case 1:		/* start the watchdog */
+ 		outw(0x0001,
+ 			devpriv->i_IobaseAddon +
+ 			APCI1516_WATCHDOG_ENABLEDISABLE);
+ 		break;
+-	case 2:		//Software trigger
++	case 2:		/* Software trigger */
+ 		outw(0x0201,
+ 			devpriv->i_IobaseAddon +
+ 			APCI1516_WATCHDOG_ENABLEDISABLE);
+@@ -485,7 +485,7 @@ int i_APCI1516_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_
+ 	default:
+ 		printk("\nSpecified functionality does not exist\n");
+ 		return -EINVAL;
+-	}			// switch(data[0])
++	}			/*  switch(data[0]) */
+ 	return insn->n;
+ }
+ 
+@@ -534,7 +534,7 @@ int i_APCI1516_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice
+ 
+ int i_APCI1516_Reset(struct comedi_device * dev)
+ {
+-	outw(0x0, devpriv->iobase + APCI1516_DIGITAL_OP);	//RESETS THE DIGITAL OUTPUTS
++	outw(0x0, devpriv->iobase + APCI1516_DIGITAL_OP);	/* RESETS THE DIGITAL OUTPUTS */
+ 	outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_ENABLEDISABLE);
+ 	outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_RELOAD_VALUE);
+ 	outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_RELOAD_VALUE + 2);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h
+index b1367efa243e..21c09ed01b1d 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h
+@@ -17,17 +17,17 @@
+ 
+ /*********      Definitions for APCI-1516 card  *****/
+ 
+-// Card Specific information
++/* Card Specific information */
+ #define APCI1516_BOARD_VENDOR_ID                 0x15B8
+ #define APCI1516_ADDRESS_RANGE                   8
+ 
+-//DIGITAL INPUT-OUTPUT DEFINE
++/* DIGITAL INPUT-OUTPUT DEFINE */
+ 
+ #define APCI1516_DIGITAL_OP                 	4
+ #define APCI1516_DIGITAL_OP_RW                 	4
+ #define APCI1516_DIGITAL_IP                     0
+ 
+-// TIMER COUNTER WATCHDOG DEFINES
++/* TIMER COUNTER WATCHDOG DEFINES */
+ 
+ #define ADDIDATA_WATCHDOG                          2
+ #define APCI1516_DIGITAL_OP_WATCHDOG               0
+@@ -35,15 +35,15 @@
+ #define APCI1516_WATCHDOG_RELOAD_VALUE             4
+ #define APCI1516_WATCHDOG_STATUS                   16
+ 
+-// Hardware Layer  functions for Apci1516
++/* Hardware Layer  functions for Apci1516 */
+ 
+-//Digital Input
++/* Digital Input */
+ int i_APCI1516_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				    struct comedi_insn *insn, unsigned int *data);
+ int i_APCI1516_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 struct comedi_insn *insn, unsigned int *data);
+ 
+-//Digital Output
++/* Digital Output */
+ int i_APCI1516_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   struct comedi_insn *insn, unsigned int *data);
+ int i_APCI1516_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+@@ -51,8 +51,9 @@ int i_APCI1516_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subde
+ int i_APCI1516_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 struct comedi_insn *insn, unsigned int *data);
+ 
+-// TIMER
+-// timer value is passed as u seconds
++/*
++* TIMER timer value is passed as u seconds
++*/
+ int i_APCI1516_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			      struct comedi_insn *insn, unsigned int *data);
+ int i_APCI1516_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+@@ -60,5 +61,5 @@ int i_APCI1516_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_s
+ int i_APCI1516_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			    struct comedi_insn *insn, unsigned int *data);
+ 
+-//reset
++/* reset */
+ int i_APCI1516_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
+index 19ded14c88d7..0780c440c44a 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
+@@ -20,45 +20,45 @@
+ #define APCI1564_BOARD_VENDOR_ID                0x15B8
+ #define APCI1564_ADDRESS_RANGE                  128
+ 
+-//DIGITAL INPUT-OUTPUT DEFINE
+-// Input defines
++/* DIGITAL INPUT-OUTPUT DEFINE */
++/* Input defines */
+ #define APCI1564_DIGITAL_IP                     0x04
+ #define APCI1564_DIGITAL_IP_INTERRUPT_MODE1     4
+ #define APCI1564_DIGITAL_IP_INTERRUPT_MODE2     8
+ #define APCI1564_DIGITAL_IP_IRQ                 16
+ 
+-// Output defines
++/* Output defines */
+ #define APCI1564_DIGITAL_OP                 	0x18
+ #define APCI1564_DIGITAL_OP_RW               	0
+ #define APCI1564_DIGITAL_OP_INTERRUPT           4
+ #define APCI1564_DIGITAL_OP_IRQ                 12
+ 
+-//Digital Input IRQ Function Selection
++/* Digital Input IRQ Function Selection */
+ #define ADDIDATA_OR                             0
+ #define ADDIDATA_AND                            1
+ 
+-//Digital Input Interrupt Status
++/* Digital Input Interrupt Status */
+ #define APCI1564_DIGITAL_IP_INTERRUPT_STATUS    12
+ 
+-//Digital Output Interrupt Status
++/* Digital Output Interrupt Status */
+ #define APCI1564_DIGITAL_OP_INTERRUPT_STATUS    8
+ 
+-//Digital Input Interrupt Enable Disable.
++/* Digital Input Interrupt Enable Disable. */
+ #define APCI1564_DIGITAL_IP_INTERRUPT_ENABLE    0x4
+ #define APCI1564_DIGITAL_IP_INTERRUPT_DISABLE   0xFFFFFFFB
+ 
+-//Digital Output Interrupt Enable Disable.
++/* Digital Output Interrupt Enable Disable. */
+ #define APCI1564_DIGITAL_OP_VCC_INTERRUPT_ENABLE   0x1
+ #define APCI1564_DIGITAL_OP_VCC_INTERRUPT_DISABLE  0xFFFFFFFE
+ #define APCI1564_DIGITAL_OP_CC_INTERRUPT_ENABLE    0x2
+ #define APCI1564_DIGITAL_OP_CC_INTERRUPT_DISABLE   0xFFFFFFFD
+ 
+-//ADDIDATA Enable Disable
++/* ADDIDATA Enable Disable */
+ 
+ #define ADDIDATA_ENABLE                            1
+ #define ADDIDATA_DISABLE                           0
+ 
+-// TIMER COUNTER WATCHDOG DEFINES
++/* TIMER COUNTER WATCHDOG DEFINES */
+ 
+ #define ADDIDATA_TIMER                             0
+ #define ADDIDATA_COUNTER                           1
+@@ -78,10 +78,11 @@
+ #define APCI1564_TCW_WARN_TIMEVAL                  24
+ #define APCI1564_TCW_WARN_TIMEBASE                 28
+ 
+-// Hardware Layer  functions for Apci1564
++/* Hardware Layer  functions for Apci1564 */
+ 
+-//DI
+-// for di read
++/*
++* DI for di read
++*/
+ int i_APCI1564_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				  struct comedi_insn *insn, unsigned int *data);
+ int i_APCI1564_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+@@ -89,7 +90,7 @@ int i_APCI1564_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdev
+ int i_APCI1564_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				    struct comedi_insn *insn, unsigned int *data);
+ 
+-//DO
++/* DO */
+ int i_APCI1564_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   struct comedi_insn *insn, unsigned int *data);
+ int i_APCI1564_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+@@ -99,8 +100,9 @@ int i_APCI1564_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdev
+ int i_APCI1564_ReadInterruptStatus(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   struct comedi_insn *insn, unsigned int *data);
+ 
+-// TIMER
+-// timer value is passed as u seconds
++/*
++* TIMER timer value is passed as u seconds
++*/
+ int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev,
+ 					  struct comedi_subdevice *s,
+ 					  struct comedi_insn *insn, unsigned int *data);
+@@ -112,8 +114,8 @@ int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device *dev,
+ 					struct comedi_subdevice *s,
+ 					struct comedi_insn *insn, unsigned int *data);
+ 
+-// intERRUPT
++/* intERRUPT */
+ static void v_APCI1564_Interrupt(int irq, void *d);
+ 
+-// RESET
++/* RESET */
+ int i_APCI1564_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
+index 5bcea0f58eed..1969e8df7378 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
+@@ -82,13 +82,13 @@ int i_APCI2016_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ 		comedi_error(dev,
+ 			"Not a valid Data !!! ,Data should be 1 or 0\n");
+ 		return -EINVAL;
+-	}			// if  ((data[0]!=0) && (data[0]!=1))
++	}			/*  if  ((data[0]!=0) && (data[0]!=1)) */
+ 	if (data[0]) {
+ 		devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
+-	}			// if  (data[0]
++	}			/*  if  (data[0] */
+ 	else {
+ 		devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
+-	}			// else if  (data[0]
++	}			/*  else if  (data[0] */
+ 	return insn->n;
+ }
+ 
+@@ -121,24 +121,24 @@ int i_APCI2016_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 		comedi_error(dev,
+ 			"Invalid Channel Numbers !!!, Channel Numbers must be between 0 and 15\n");
+ 		return -EINVAL;
+-	}			// if  ((ui_NoOfChannel<0) || (ui_NoOfChannel>15))
++	}			/*  if  ((ui_NoOfChannel<0) || (ui_NoOfChannel>15)) */
+ 	if (devpriv->b_OutputMemoryStatus) {
+ 		ui_Temp = inw(devpriv->iobase + APCI2016_DIGITAL_OP);
+-	}			// if  (devpriv->b_OutputMemoryStatus )
++	}			/*  if  (devpriv->b_OutputMemoryStatus ) */
+ 	else {
+ 		ui_Temp = 0;
+-	}			// else if  (devpriv->b_OutputMemoryStatus )
++	}			/*  else if  (devpriv->b_OutputMemoryStatus ) */
+ 	if ((data[1] != 0) && (data[1] != 1)) {
+ 		comedi_error(dev,
+ 			"Invalid Data[1] value !!!, Data[1] should be 0 or 1\n");
+ 		return -EINVAL;
+-	}			// if  ((data[1]!=0) && (data[1]!=1))
++	}			/*  if  ((data[1]!=0) && (data[1]!=1)) */
+ 
+ 	if (data[3] == 0) {
+ 		if (data[1] == 0) {
+ 			data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
+ 			outw(data[0], devpriv->iobase + APCI2016_DIGITAL_OP);
+-		}		// if (data[1]==0)
++		}		/*  if (data[1]==0) */
+ 		else {
+ 			if (data[1] == 1) {
+ 				switch (ui_NoOfChannel) {
+@@ -162,16 +162,16 @@ int i_APCI2016_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 					break;
+ 				default:
+ 					comedi_error(dev, " chan spec wrong");
+-					return -EINVAL;	// "sorry channel spec wrong "
+-				}	//switch(ui_NoOfChannels)
++					return -EINVAL;	/*  "sorry channel spec wrong " */
++				}	/* switch(ui_NoOfChannels) */
+ 				outw(data[0],
+ 					devpriv->iobase + APCI2016_DIGITAL_OP);
+-			}	// if  (data[1]==1)
++			}	/*  if  (data[1]==1) */
+ 			else {
+ 				printk("\nSpecified channel not supported\n");
+-			}	// else if  (data[1]==1)
+-		}		// else if (data[1]==0)
+-	}			// if (data[3]==0)
++			}	/*  else if  (data[1]==1) */
++		}		/*  else if (data[1]==0) */
++	}			/*  if (data[3]==0) */
+ 	else {
+ 		if (data[3] == 1) {
+ 			if (data[1] == 0) {
+@@ -183,7 +183,7 @@ int i_APCI2016_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 				data[0] = data[0] & ui_Temp;
+ 				outw(data[0],
+ 					devpriv->iobase + APCI2016_DIGITAL_OP);
+-			}	// if  (data[1]==0)
++			}	/*  if  (data[1]==0) */
+ 			else {
+ 				if (data[1] == 1) {
+ 					switch (ui_NoOfChannel) {
+@@ -228,22 +228,22 @@ int i_APCI2016_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 					default:
+ 						comedi_error(dev,
+ 							" chan spec wrong");
+-						return -EINVAL;	// "sorry channel spec wrong "
+-					}	//switch(ui_NoOfChannels)
++						return -EINVAL;	/*  "sorry channel spec wrong " */
++					}	/* switch(ui_NoOfChannels) */
+ 					outw(data[0],
+ 						devpriv->iobase +
+ 						APCI2016_DIGITAL_OP);
+-				}	// if(data[1]==1)
++				}	/*  if(data[1]==1) */
+ 				else {
+ 					printk("\nSpecified channel not supported\n");
+-				}	//else if(data[1]==1)
+-			}	//elseif(data[1]==0)
+-		}		//if(data[3]==1);
++				}	/* else if(data[1]==1) */
++			}	/* elseif(data[1]==0) */
++		}		/* if(data[3]==1); */
+ 		else {
+ 			printk("\nSpecified functionality does not exist\n");
+ 			return -EINVAL;
+-		}		//if else data[3]==1)
+-	}			//if else data[3]==0)
++		}		/* if else data[3]==1) */
++	}			/* if else data[3]==0) */
+ 	return insn->n;
+ }
+ 
+@@ -276,17 +276,17 @@ int i_APCI2016_BitsDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ 		comedi_error(dev,
+ 			"Invalid Channel Numbers !!!, Channel Numbers must be between 0 and 15\n");
+ 		return -EINVAL;
+-	}			// if  ((ui_NoOfChannel<0) || (ui_NoOfChannel>15))
++	}			/*  if  ((ui_NoOfChannel<0) || (ui_NoOfChannel>15)) */
+ 	if ((data[0] != 0) && (data[0] != 1)) {
+ 		comedi_error(dev,
+ 			"Invalid Data[0] value !!!, Data[0] should be 0 or 1\n");
+ 		return -EINVAL;
+-	}			// if  ((data[0]!=0) && (data[0]!=1))
++	}			/*  if  ((data[0]!=0) && (data[0]!=1)) */
+ 	ui_Temp = data[0];
+ 	*data = inw(devpriv->iobase + APCI2016_DIGITAL_OP_RW);
+ 	if (ui_Temp == 0) {
+ 		*data = (*data >> ui_NoOfChannel) & 0x1;
+-	}			// if  (ui_Temp==0)
++	}			/*  if  (ui_Temp==0) */
+ 	else {
+ 		if (ui_Temp == 1) {
+ 			switch (ui_NoOfChannel) {
+@@ -307,13 +307,13 @@ int i_APCI2016_BitsDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ 
+ 			default:
+ 				comedi_error(dev, " chan spec wrong");
+-				return -EINVAL;	// "sorry channel spec wrong "
+-			}	//switch(ui_NoOfChannel)
+-		}		// if  (ui_Temp==1)
++				return -EINVAL;	/*  "sorry channel spec wrong " */
++			}	/* switch(ui_NoOfChannel) */
++		}		/*  if  (ui_Temp==1) */
+ 		else {
+ 			printk("\nSpecified channel not supported \n");
+-		}		// else if  (ui_Temp==1)
+-	}			// if  (ui_Temp==0)
++		}		/*  else if  (ui_Temp==1) */
++	}			/*  if  (ui_Temp==0) */
+ 	return insn->n;
+ }
+ 
+@@ -342,11 +342,11 @@ int i_APCI2016_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevic
+ {
+ 
+ 	if (data[0] == 0) {
+-		//Disable the watchdog
++		/* Disable the watchdog */
+ 		outw(0x0,
+ 			devpriv->i_IobaseAddon +
+ 			APCI2016_WATCHDOG_ENABLEDISABLE);
+-		//Loading the Reload value
++		/* Loading the Reload value */
+ 		outw(data[1],
+ 			devpriv->i_IobaseAddon +
+ 			APCI2016_WATCHDOG_RELOAD_VALUE);
+@@ -385,15 +385,15 @@ int i_APCI2016_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_
+ {
+ 
+ 	switch (data[0]) {
+-	case 0:		//stop the watchdog
+-		outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_ENABLEDISABLE);	//disable the watchdog
++	case 0:		/* stop the watchdog */
++		outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_ENABLEDISABLE);	/* disable the watchdog */
+ 		break;
+-	case 1:		//start the watchdog
++	case 1:		/* start the watchdog */
+ 		outw(0x0001,
+ 			devpriv->i_IobaseAddon +
+ 			APCI2016_WATCHDOG_ENABLEDISABLE);
+ 		break;
+-	case 2:		//Software trigger
++	case 2:		/* Software trigger */
+ 		outw(0x0201,
+ 			devpriv->i_IobaseAddon +
+ 			APCI2016_WATCHDOG_ENABLEDISABLE);
+@@ -401,7 +401,7 @@ int i_APCI2016_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_
+ 	default:
+ 		printk("\nSpecified functionality does not exist\n");
+ 		return -EINVAL;
+-	}			// switch(data[0])
++	}			/*  switch(data[0]) */
+ 
+ 	return insn->n;
+ }
+@@ -452,7 +452,7 @@ int i_APCI2016_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice
+ 
+ int i_APCI2016_Reset(struct comedi_device * dev)
+ {
+-	outw(0x0, devpriv->iobase + APCI2016_DIGITAL_OP);	// Resets the digital output channels
++	outw(0x0, devpriv->iobase + APCI2016_DIGITAL_OP);	/*  Resets the digital output channels */
+ 	outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_ENABLEDISABLE);
+ 	outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_RELOAD_VALUE);
+ 	outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_RELOAD_VALUE + 2);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
+index 80e907e87f08..639944c44469 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
+@@ -19,17 +19,17 @@
+ #define APCI2016_BOARD_VENDOR_ID 0x15B8
+ #define APCI2016_ADDRESS_RANGE   8
+ 
+-//DIGITAL INPUT-OUTPUT DEFINE
++/* DIGITAL INPUT-OUTPUT DEFINE */
+ 
+ #define APCI2016_DIGITAL_OP                 	0x04
+ #define APCI2016_DIGITAL_OP_RW                 	4
+ 
+-//ADDIDATA Enable Disable
++/* ADDIDATA Enable Disable */
+ 
+ #define ADDIDATA_ENABLE                            1
+ #define ADDIDATA_DISABLE                           0
+ 
+-// TIMER COUNTER WATCHDOG DEFINES
++/* TIMER COUNTER WATCHDOG DEFINES */
+ 
+ #define ADDIDATA_WATCHDOG                          2
+ #define APCI2016_DIGITAL_OP_WATCHDOG               0
+@@ -37,9 +37,9 @@
+ #define APCI2016_WATCHDOG_RELOAD_VALUE             4
+ #define APCI2016_WATCHDOG_STATUS                   16
+ 
+-// Hardware Layer  functions for Apci2016
++/* Hardware Layer  functions for Apci2016 */
+ 
+-//DO
++/* DO */
+ int i_APCI2016_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   struct comedi_insn *insn, unsigned int *data);
+ 
+@@ -49,8 +49,10 @@ int i_APCI2016_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subde
+ int i_APCI2016_BitsDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 struct comedi_insn *insn, unsigned int *data);
+ 
+-// TIMER
+-// timer value is passed as u seconds
++/*
++* TIMER
++* timer value is passed as u seconds
++*/
+ 
+ int i_APCI2016_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			      struct comedi_insn *insn, unsigned int *data);
+@@ -61,10 +63,10 @@ int i_APCI2016_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_s
+ int i_APCI2016_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			    struct comedi_insn *insn, unsigned int *data);
+ 
+-// Interrupt functions.....
++/* Interrupt functions..... */
+ 
+-// void v_APCI2016_Interrupt(int irq, void *d) ;
++/* void v_APCI2016_Interrupt(int irq, void *d); */
+ 
+- //void v_APCI2016_Interrupt(int irq, void *d);
+-// RESET
++/* void v_APCI2016_Interrupt(int irq, void *d); */
++/* RESET */
+ int i_APCI2016_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
+index 84d84a1ce3e0..c2580c6e0d4d 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
+@@ -89,26 +89,26 @@ int i_APCI2032_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ 		comedi_error(dev,
+ 			"Not a valid Data !!! ,Data should be 1 or 0\n");
+ 		return -EINVAL;
+-	}			//if  ( (data[0]!=0) && (data[0]!=1) )
++	}			/* if  ( (data[0]!=0) && (data[0]!=1) ) */
+ 	if (data[0]) {
+ 		devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
+-	}			// if  (data[0])
++	}			/*  if  (data[0]) */
+ 	else {
+ 		devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
+-	}			//else if  (data[0])
++	}			/* else if  (data[0]) */
+ 
+ 	if (data[1] == ADDIDATA_ENABLE) {
+ 		ul_Command = ul_Command | 0x1;
+-	}			//if  (data[1] == ADDIDATA_ENABLE)
++	}			/* if  (data[1] == ADDIDATA_ENABLE) */
+ 	else {
+ 		ul_Command = ul_Command & 0xFFFFFFFE;
+-	}			//elseif  (data[1] == ADDIDATA_ENABLE)
++	}			/* elseif  (data[1] == ADDIDATA_ENABLE) */
+ 	if (data[2] == ADDIDATA_ENABLE) {
+ 		ul_Command = ul_Command | 0x2;
+-	}			//if  (data[2] == ADDIDATA_ENABLE)
++	}			/* if  (data[2] == ADDIDATA_ENABLE) */
+ 	else {
+ 		ul_Command = ul_Command & 0xFFFFFFFD;
+-	}			//elseif  (data[2] == ADDIDATA_ENABLE)
++	}			/* elseif  (data[2] == ADDIDATA_ENABLE) */
+ 	outl(ul_Command, devpriv->iobase + APCI2032_DIGITAL_OP_INTERRUPT);
+ 	ui_InterruptData = inl(devpriv->iobase + APCI2032_DIGITAL_OP_INTERRUPT);
+ 	return insn->n;
+@@ -138,19 +138,19 @@ int i_APCI2032_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int ui_Temp, ui_Temp1;
+-	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
++	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	/*  get the channel */
+ 	if (devpriv->b_OutputMemoryStatus) {
+ 		ui_Temp = inl(devpriv->iobase + APCI2032_DIGITAL_OP);
+ 
+-	}			//if(devpriv->b_OutputMemoryStatus )
++	}			/* if(devpriv->b_OutputMemoryStatus ) */
+ 	else {
+ 		ui_Temp = 0;
+-	}			//if(devpriv->b_OutputMemoryStatus )
++	}			/* if(devpriv->b_OutputMemoryStatus ) */
+ 	if (data[3] == 0) {
+ 		if (data[1] == 0) {
+ 			data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
+ 			outl(data[0], devpriv->iobase + APCI2032_DIGITAL_OP);
+-		}		//if(data[1]==0)
++		}		/* if(data[1]==0) */
+ 		else {
+ 			if (data[1] == 1) {
+ 				switch (ui_NoOfChannel) {
+@@ -184,18 +184,18 @@ int i_APCI2032_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 
+ 				default:
+ 					comedi_error(dev, " chan spec wrong");
+-					return -EINVAL;	// "sorry channel spec wrong "
++					return -EINVAL;	/*  "sorry channel spec wrong " */
+ 
+-				}	//switch(ui_NoOfChannels)
++				}	/* switch(ui_NoOfChannels) */
+ 
+ 				outl(data[0],
+ 					devpriv->iobase + APCI2032_DIGITAL_OP);
+-			}	// if(data[1]==1)
++			}	/*  if(data[1]==1) */
+ 			else {
+ 				printk("\nSpecified channel not supported\n");
+-			}	//else if(data[1]==1)
+-		}		//elseif(data[1]==0)
+-	}			//if(data[3]==0)
++			}	/* else if(data[1]==1) */
++		}		/* elseif(data[1]==0) */
++	}			/* if(data[3]==0) */
+ 	else {
+ 		if (data[3] == 1) {
+ 			if (data[1] == 0) {
+@@ -209,7 +209,7 @@ int i_APCI2032_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 				data[0] = data[0] & ui_Temp;
+ 				outl(data[0],
+ 					devpriv->iobase + APCI2032_DIGITAL_OP);
+-			}	//if(data[1]==0)
++			}	/* if(data[1]==0) */
+ 			else {
+ 				if (data[1] == 1) {
+ 					switch (ui_NoOfChannel) {
+@@ -272,24 +272,24 @@ int i_APCI2032_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 					default:
+ 						comedi_error(dev,
+ 							" chan spec wrong");
+-						return -EINVAL;	// "sorry channel spec wrong "
++						return -EINVAL;	/*  "sorry channel spec wrong " */
+ 
+-					}	//switch(ui_NoOfChannels)
++					}	/* switch(ui_NoOfChannels) */
+ 
+ 					outl(data[0],
+ 						devpriv->iobase +
+ 						APCI2032_DIGITAL_OP);
+-				}	// if(data[1]==1)
++				}	/*  if(data[1]==1) */
+ 				else {
+ 					printk("\nSpecified channel not supported\n");
+-				}	//else if(data[1]==1)
+-			}	//elseif(data[1]==0)
+-		}		//if(data[3]==1);
++				}	/* else if(data[1]==1) */
++			}	/* elseif(data[1]==0) */
++		}		/* if(data[3]==1); */
+ 		else {
+ 			printk("\nSpecified functionality does not exist\n");
+ 			return -EINVAL;
+-		}		//if else data[3]==1)
+-	}			//if else data[3]==0)
++		}		/* if else data[3]==1) */
++	}			/* if else data[3]==0) */
+ 	return (insn->n);;
+ }
+ 
+@@ -323,7 +323,7 @@ int i_APCI2032_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ 	*data = inl(devpriv->iobase + APCI2032_DIGITAL_OP_RW);
+ 	if (ui_Temp == 0) {
+ 		*data = (*data >> ui_NoOfChannel) & 0x1;
+-	}			//if  (ui_Temp==0)
++	}			/* if  (ui_Temp==0) */
+ 	else {
+ 		if (ui_Temp == 1) {
+ 			switch (ui_NoOfChannel) {
+@@ -349,13 +349,13 @@ int i_APCI2032_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ 
+ 			default:
+ 				comedi_error(dev, " chan spec wrong");
+-				return -EINVAL;	// "sorry channel spec wrong "
++				return -EINVAL;	/*  "sorry channel spec wrong " */
+ 
+-			}	//switch(ui_NoOfChannels)
+-		}		//if  (ui_Temp==1)
++			}	/* switch(ui_NoOfChannels) */
++		}		/* if  (ui_Temp==1) */
+ 		else {
+ 			printk("\nSpecified channel not supported \n");
+-		}		//elseif  (ui_Temp==1)
++		}		/* elseif  (ui_Temp==1) */
+ 	}
+ 	return insn->n;
+ }
+@@ -384,11 +384,11 @@ int i_APCI2032_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevic
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0] == 0) {
+-		//Disable the watchdog
++		/* Disable the watchdog */
+ 		outl(0x0,
+ 			devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG +
+ 			APCI2032_TCW_PROG);
+-		//Loading the Reload value
++		/* Loading the Reload value */
+ 		outl(data[1],
+ 			devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG +
+ 			APCI2032_TCW_RELOAD_VALUE);
+@@ -425,15 +425,15 @@ int i_APCI2032_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+-	case 0:		//stop the watchdog
+-		outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + APCI2032_TCW_PROG);	//disable the watchdog
++	case 0:		/* stop the watchdog */
++		outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + APCI2032_TCW_PROG);	/* disable the watchdog */
+ 		break;
+-	case 1:		//start the watchdog
++	case 1:		/* start the watchdog */
+ 		outl(0x0001,
+ 			devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG +
+ 			APCI2032_TCW_PROG);
+ 		break;
+-	case 2:		//Software trigger
++	case 2:		/* Software trigger */
+ 		outl(0x0201,
+ 			devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG +
+ 			APCI2032_TCW_PROG);
+@@ -498,13 +498,13 @@ void v_APCI2032_Interrupt(int irq, void *d)
+ 	struct comedi_device *dev = d;
+ 	unsigned int ui_DO;
+ 
+-	ui_DO = inl(devpriv->iobase + APCI2032_DIGITAL_OP_IRQ) & 0x1;	//Check if VCC OR CC interrupt has occured.
++	ui_DO = inl(devpriv->iobase + APCI2032_DIGITAL_OP_IRQ) & 0x1;	/* Check if VCC OR CC interrupt has occured. */
+ 
+ 	if (ui_DO == 0) {
+ 		printk("\nInterrupt from unKnown source\n");
+-	}			// if(ui_DO==0)
++	}			/*  if(ui_DO==0) */
+ 	if (ui_DO) {
+-		// Check for Digital Output interrupt Type - 1: Vcc interrupt 2: CC interrupt.
++		/*  Check for Digital Output interrupt Type - 1: Vcc interrupt 2: CC interrupt. */
+ 		ui_Type =
+ 			inl(devpriv->iobase +
+ 			APCI2032_DIGITAL_OP_INTERRUPT_STATUS) & 0x3;
+@@ -512,16 +512,16 @@ void v_APCI2032_Interrupt(int irq, void *d)
+ 			devpriv->iobase + APCI2032_DIGITAL_OP +
+ 			APCI2032_DIGITAL_OP_INTERRUPT);
+ 		if (ui_Type == 1) {
+-			//Sends signal to user space
++			/* Sends signal to user space */
+ 			send_sig(SIGIO, devpriv->tsk_Current, 0);
+-		}		// if (ui_Type==1)
++		}		/*  if (ui_Type==1) */
+ 		else {
+ 			if (ui_Type == 2) {
+-				// Sends signal to user space
++				/*  Sends signal to user space */
+ 				send_sig(SIGIO, devpriv->tsk_Current, 0);
+-			}	//if (ui_Type==2)
+-		}		//else if (ui_Type==1)
+-	}			//if(ui_DO)
++			}	/* if (ui_Type==2) */
++		}		/* else if (ui_Type==1) */
++	}			/* if(ui_DO) */
+ 
+ 	return;
+ 
+@@ -571,9 +571,9 @@ int i_APCI2032_Reset(struct comedi_device * dev)
+ {
+ 	devpriv->b_DigitalOutputRegister = 0;
+ 	ui_Type = 0;
+-	outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP);	//Resets the output channels
+-	outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_INTERRUPT);	//Disables the interrupt.
+-	outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + APCI2032_TCW_PROG);	//disable the watchdog
+-	outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + APCI2032_TCW_RELOAD_VALUE);	//reload=0
++	outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP);	/* Resets the output channels */
++	outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_INTERRUPT);	/* Disables the interrupt. */
++	outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + APCI2032_TCW_PROG);	/* disable the watchdog */
++	outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + APCI2032_TCW_RELOAD_VALUE);	/* reload=0 */
+ 	return 0;
+ }
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h
+index 15f09e3ab2eb..c971d143c249 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h
+@@ -17,32 +17,32 @@
+ 
+ /*********      Definitions for APCI-2032 card  *****/
+ 
+-// Card Specific information
++/* Card Specific information */
+ #define APCI2032_BOARD_VENDOR_ID                 0x15B8
+ #define APCI2032_ADDRESS_RANGE                   63
+ 
+-//DIGITAL INPUT-OUTPUT DEFINE
++/* DIGITAL INPUT-OUTPUT DEFINE */
+ 
+ #define APCI2032_DIGITAL_OP                 	0
+ #define APCI2032_DIGITAL_OP_RW                 	0
+ #define APCI2032_DIGITAL_OP_INTERRUPT           4
+ #define APCI2032_DIGITAL_OP_IRQ                 12
+ 
+-//Digital Output Interrupt Status
++/* Digital Output Interrupt Status */
+ #define APCI2032_DIGITAL_OP_INTERRUPT_STATUS    8
+ 
+-//Digital Output Interrupt Enable Disable.
++/* Digital Output Interrupt Enable Disable. */
+ #define APCI2032_DIGITAL_OP_VCC_INTERRUPT_ENABLE   0x1
+ #define APCI2032_DIGITAL_OP_VCC_INTERRUPT_DISABLE  0xFFFFFFFE
+ #define APCI2032_DIGITAL_OP_CC_INTERRUPT_ENABLE    0x2
+ #define APCI2032_DIGITAL_OP_CC_INTERRUPT_DISABLE   0xFFFFFFFD
+ 
+-//ADDIDATA Enable Disable
++/* ADDIDATA Enable Disable */
+ 
+ #define ADDIDATA_ENABLE                            1
+ #define ADDIDATA_DISABLE                           0
+ 
+-// TIMER COUNTER WATCHDOG DEFINES
++/* TIMER COUNTER WATCHDOG DEFINES */
+ 
+ #define ADDIDATA_WATCHDOG                          2
+ #define APCI2032_DIGITAL_OP_WATCHDOG               16
+@@ -52,9 +52,9 @@
+ #define APCI2032_TCW_TRIG_STATUS                   16
+ #define APCI2032_TCW_IRQ                           20
+ 
+-// Hardware Layer  functions for Apci2032
++/* Hardware Layer  functions for Apci2032 */
+ 
+-//DO
++/* DO */
+ int i_APCI2032_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   struct comedi_insn *insn, unsigned int *data);
+ int i_APCI2032_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+@@ -64,8 +64,10 @@ int i_APCI2032_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdev
+ int i_APCI2032_ReadInterruptStatus(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   struct comedi_insn *insn, unsigned int *data);
+ 
+-// TIMER
+-// timer value is passed as u seconds
++/* TIMER
++ * timer value is passed as u seconds
++*/
++
+ int i_APCI2032_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			      struct comedi_insn *insn, unsigned int *data);
+ int i_APCI2032_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+@@ -73,9 +75,9 @@ int i_APCI2032_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_s
+ int i_APCI2032_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			    struct comedi_insn *insn, unsigned int *data);
+ 
+-// Interrupt functions.....
++/* Interrupt functions..... */
+ 
+ void v_APCI2032_Interrupt(int irq, void *d);
+ 
+-//Reset functions
++/* Reset functions */
+ int i_APCI2032_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
+index e56647f28c2e..530629bcdaca 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
+@@ -82,11 +82,11 @@ int i_APCI2200_Read1DigitalInput(struct comedi_device * dev, struct comedi_subde
+ 	if (ui_Channel >= 0 && ui_Channel <= 7) {
+ 		ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI2200_DIGITAL_IP);
+ 		*data = (ui_TmpValue >> ui_Channel) & 0x1;
+-	}			//if(ui_Channel >= 0 && ui_Channel <=7)
++	}			/* if(ui_Channel >= 0 && ui_Channel <=7) */
+ 	else {
+ 		printk("\nThe specified channel does not exist\n");
+-		return -EINVAL;	// "sorry channel spec wrong "
+-	}			//else if(ui_Channel >= 0 && ui_Channel <=7)
++		return -EINVAL;	/*  "sorry channel spec wrong " */
++	}			/* else if(ui_Channel >= 0 && ui_Channel <=7) */
+ 
+ 	return insn->n;
+ }
+@@ -137,9 +137,9 @@ int i_APCI2200_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ 
+ 	default:
+ 		printk("\nWrong parameters\n");
+-		return -EINVAL;	// "sorry channel spec wrong "
++		return -EINVAL;	/*  "sorry channel spec wrong " */
+ 		break;
+-	}			//switch(ui_NoOfChannels)
++	}			/* switch(ui_NoOfChannels) */
+ 
+ 	return insn->n;
+ }
+@@ -201,19 +201,19 @@ int i_APCI2200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int ui_Temp, ui_Temp1;
+-	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
++	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	/*  get the channel */
+ 	if (devpriv->b_OutputMemoryStatus) {
+ 		ui_Temp = inw(devpriv->iobase + APCI2200_DIGITAL_OP);
+ 
+-	}			//if(devpriv->b_OutputMemoryStatus )
++	}			/* if(devpriv->b_OutputMemoryStatus ) */
+ 	else {
+ 		ui_Temp = 0;
+-	}			//if(devpriv->b_OutputMemoryStatus )
++	}			/* if(devpriv->b_OutputMemoryStatus ) */
+ 	if (data[3] == 0) {
+ 		if (data[1] == 0) {
+ 			data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
+ 			outw(data[0], devpriv->iobase + APCI2200_DIGITAL_OP);
+-		}		//if(data[1]==0)
++		}		/* if(data[1]==0) */
+ 		else {
+ 			if (data[1] == 1) {
+ 				switch (ui_NoOfChannel) {
+@@ -240,18 +240,18 @@ int i_APCI2200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 					break;
+ 				default:
+ 					comedi_error(dev, " chan spec wrong");
+-					return -EINVAL;	// "sorry channel spec wrong "
++					return -EINVAL;	/*  "sorry channel spec wrong " */
+ 
+-				}	//switch(ui_NoOfChannels)
++				}	/* switch(ui_NoOfChannels) */
+ 
+ 				outw(data[0],
+ 					devpriv->iobase + APCI2200_DIGITAL_OP);
+-			}	// if(data[1]==1)
++			}	/*  if(data[1]==1) */
+ 			else {
+ 				printk("\nSpecified channel not supported\n");
+-			}	//else if(data[1]==1)
+-		}		//elseif(data[1]==0)
+-	}			//if(data[3]==0)
++			}	/* else if(data[1]==1) */
++		}		/* elseif(data[1]==0) */
++	}			/* if(data[3]==0) */
+ 	else {
+ 		if (data[3] == 1) {
+ 			if (data[1] == 0) {
+@@ -263,7 +263,7 @@ int i_APCI2200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 				data[0] = data[0] & ui_Temp;
+ 				outw(data[0],
+ 					devpriv->iobase + APCI2200_DIGITAL_OP);
+-			}	//if(data[1]==0)
++			}	/* if(data[1]==0) */
+ 			else {
+ 				if (data[1] == 1) {
+ 					switch (ui_NoOfChannel) {
+@@ -312,24 +312,24 @@ int i_APCI2200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 					default:
+ 						comedi_error(dev,
+ 							" chan spec wrong");
+-						return -EINVAL;	// "sorry channel spec wrong "
++						return -EINVAL;	/*  "sorry channel spec wrong " */
+ 
+-					}	//switch(ui_NoOfChannels)
++					}	/* switch(ui_NoOfChannels) */
+ 
+ 					outw(data[0],
+ 						devpriv->iobase +
+ 						APCI2200_DIGITAL_OP);
+-				}	// if(data[1]==1)
++				}	/*  if(data[1]==1) */
+ 				else {
+ 					printk("\nSpecified channel not supported\n");
+-				}	//else if(data[1]==1)
+-			}	//elseif(data[1]==0)
+-		}		//if(data[3]==1);
++				}	/* else if(data[1]==1) */
++			}	/* elseif(data[1]==0) */
++		}		/* if(data[3]==1); */
+ 		else {
+ 			printk("\nSpecified functionality does not exist\n");
+ 			return -EINVAL;
+-		}		//if else data[3]==1)
+-	}			//if else data[3]==0)
++		}		/* if else data[3]==1) */
++	}			/* if else data[3]==0) */
+ 	return (insn->n);;
+ }
+ 
+@@ -359,12 +359,12 @@ int i_APCI2200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ {
+ 
+ 	unsigned int ui_Temp;
+-	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
++	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	/*  get the channel */
+ 	ui_Temp = data[0];
+ 	*data = inw(devpriv->iobase + APCI2200_DIGITAL_OP);
+ 	if (ui_Temp == 0) {
+ 		*data = (*data >> ui_NoOfChannel) & 0x1;
+-	}			//if(ui_Temp==0)
++	}			/* if(ui_Temp==0) */
+ 	else {
+ 		if (ui_Temp == 1) {
+ 			switch (ui_NoOfChannel) {
+@@ -386,14 +386,14 @@ int i_APCI2200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ 
+ 			default:
+ 				comedi_error(dev, " chan spec wrong");
+-				return -EINVAL;	// "sorry channel spec wrong "
++				return -EINVAL;	/*  "sorry channel spec wrong " */
+ 
+-			}	//switch(ui_NoOfChannels)
+-		}		//if(ui_Temp==1)
++			}	/* switch(ui_NoOfChannels) */
++		}		/* if(ui_Temp==1) */
+ 		else {
+ 			printk("\nSpecified channel not supported \n");
+-		}		//elseif(ui_Temp==1)
+-	}			//elseif(ui_Temp==0)
++		}		/* elseif(ui_Temp==1) */
++	}			/* elseif(ui_Temp==0) */
+ 	return insn->n;
+ }
+ 
+@@ -422,11 +422,11 @@ int i_APCI2200_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevic
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0] == 0) {
+-		//Disable the watchdog
++		/* Disable the watchdog */
+ 		outw(0x0,
+ 			devpriv->iobase + APCI2200_WATCHDOG +
+ 			APCI2200_WATCHDOG_ENABLEDISABLE);
+-		//Loading the Reload value
++		/* Loading the Reload value */
+ 		outw(data[1],
+ 			devpriv->iobase + APCI2200_WATCHDOG +
+ 			APCI2200_WATCHDOG_RELOAD_VALUE);
+@@ -434,11 +434,11 @@ int i_APCI2200_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevic
+ 		outw(data[1],
+ 			devpriv->iobase + APCI2200_WATCHDOG +
+ 			APCI2200_WATCHDOG_RELOAD_VALUE + 2);
+-	}			//if(data[0]==0)
++	}			/* if(data[0]==0) */
+ 	else {
+ 		printk("\nThe input parameters are wrong\n");
+ 		return -EINVAL;
+-	}			//elseif(data[0]==0)
++	}			/* elseif(data[0]==0) */
+ 
+ 	return insn->n;
+ }
+@@ -468,15 +468,15 @@ int i_APCI2200_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+-	case 0:		//stop the watchdog
+-		outw(0x0, devpriv->iobase + APCI2200_WATCHDOG + APCI2200_WATCHDOG_ENABLEDISABLE);	//disable the watchdog
++	case 0:		/* stop the watchdog */
++		outw(0x0, devpriv->iobase + APCI2200_WATCHDOG + APCI2200_WATCHDOG_ENABLEDISABLE);	/* disable the watchdog */
+ 		break;
+-	case 1:		//start the watchdog
++	case 1:		/* start the watchdog */
+ 		outw(0x0001,
+ 			devpriv->iobase + APCI2200_WATCHDOG +
+ 			APCI2200_WATCHDOG_ENABLEDISABLE);
+ 		break;
+-	case 2:		//Software trigger
++	case 2:		/* Software trigger */
+ 		outw(0x0201,
+ 			devpriv->iobase + APCI2200_WATCHDOG +
+ 			APCI2200_WATCHDOG_ENABLEDISABLE);
+@@ -484,7 +484,7 @@ int i_APCI2200_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_
+ 	default:
+ 		printk("\nSpecified functionality does not exist\n");
+ 		return -EINVAL;
+-	}			// switch(data[0])
++	}			/*  switch(data[0]) */
+ 	return insn->n;
+ }
+ 
+@@ -535,7 +535,7 @@ int i_APCI2200_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice
+ 
+ int i_APCI2200_Reset(struct comedi_device * dev)
+ {
+-	outw(0x0, devpriv->iobase + APCI2200_DIGITAL_OP);	//RESETS THE DIGITAL OUTPUTS
++	outw(0x0, devpriv->iobase + APCI2200_DIGITAL_OP);	/* RESETS THE DIGITAL OUTPUTS */
+ 	outw(0x0,
+ 		devpriv->iobase + APCI2200_WATCHDOG +
+ 		APCI2200_WATCHDOG_ENABLEDISABLE);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h
+index 37b795106093..63e5f1fcecc7 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h
+@@ -17,31 +17,31 @@
+ 
+ /*********      Definitions for APCI-2200 card  *****/
+ 
+-// Card Specific information
++/* Card Specific information */
+ #define APCI2200_BOARD_VENDOR_ID                 0x15b8
+ #define APCI2200_ADDRESS_RANGE                   64
+ 
+-//DIGITAL INPUT-OUTPUT DEFINE
++/* DIGITAL INPUT-OUTPUT DEFINE */
+ 
+ #define APCI2200_DIGITAL_OP                 	4
+ #define APCI2200_DIGITAL_IP                     0
+ 
+-// TIMER COUNTER WATCHDOG DEFINES
++/* TIMER COUNTER WATCHDOG DEFINES */
+ 
+ #define APCI2200_WATCHDOG                          0x08
+ #define APCI2200_WATCHDOG_ENABLEDISABLE            12
+ #define APCI2200_WATCHDOG_RELOAD_VALUE             4
+ #define APCI2200_WATCHDOG_STATUS                   16
+ 
+-// Hardware Layer  functions for Apci2200
++/* Hardware Layer  functions for Apci2200 */
+ 
+-//Digital Input
++/* Digital Input */
+ int i_APCI2200_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				    struct comedi_insn *insn, unsigned int *data);
+ int i_APCI2200_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 struct comedi_insn *insn, unsigned int *data);
+ 
+-//Digital Output
++/* Digital Output */
+ int i_APCI2200_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   struct comedi_insn *insn, unsigned int *data);
+ int i_APCI2200_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+@@ -49,7 +49,7 @@ int i_APCI2200_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subde
+ int i_APCI2200_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 struct comedi_insn *insn, unsigned int *data);
+ 
+-// TIMER
++/* TIMER */
+ int i_APCI2200_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			      struct comedi_insn *insn, unsigned int *data);
+ int i_APCI2200_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+@@ -57,5 +57,5 @@ int i_APCI2200_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_s
+ int i_APCI2200_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			    struct comedi_insn *insn, unsigned int *data);
+ 
+-//reset
++/* reset */
+ int i_APCI2200_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
+index f6755cdfcba2..ab3a46dc1332 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
+@@ -1,5 +1,5 @@
+ 
+-// hwdrv_apci3120.h
++/* hwdrv_apci3120.h */
+ 
+ /*
+  * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+@@ -18,9 +18,9 @@
+  * any later version.
+  */
+ 
+-// comedi related defines
++/* comedi related defines */
+ 
+-//ANALOG INPUT RANGE
++/* ANALOG INPUT RANGE */
+ static const struct comedi_lrange range_apci3120_ai = { 8, {
+ 						     BIP_RANGE(10),
+ 						     BIP_RANGE(5),
+@@ -33,14 +33,14 @@ static const struct comedi_lrange range_apci3120_ai = { 8, {
+ 						     }
+ };
+ 
+-// ANALOG OUTPUT RANGE
++/* ANALOG OUTPUT RANGE */
+ static const struct comedi_lrange range_apci3120_ao = { 2, {
+ 						     BIP_RANGE(10),
+ 						     UNI_RANGE(10)
+ 						     }
+ };
+ 
+-#define APCI3120_BIPOLAR_RANGES	4	// used for test on mixture of BIP/UNI ranges
++#define APCI3120_BIPOLAR_RANGES	4	/*  used for test on mixture of BIP/UNI ranges */
+ 
+ #define APCI3120_BOARD_VENDOR_ID                 0x10E8
+ #define APCI3120_ADDRESS_RANGE            			16
+@@ -55,17 +55,17 @@ static const struct comedi_lrange range_apci3120_ao = { 2, {
+ #define     APCI3120_EOS_MODE         2
+ #define     APCI3120_DMA_MODE         3
+ 
+-//DIGITAL INPUT-OUTPUT DEFINE
++/* DIGITAL INPUT-OUTPUT DEFINE */
+ 
+ #define APCI3120_DIGITAL_OUTPUT                  	0x0D
+ #define APCI3120_RD_STATUS                       	0x02
+ #define APCI3120_RD_FIFO                     		0x00
+ 
+-// digital output insn_write ON /OFF selection
++/* digital output insn_write ON /OFF selection */
+ #define	APCI3120_SET4DIGITALOUTPUTON				1
+ #define APCI3120_SET4DIGITALOUTPUTOFF				0
+ 
+-// analog output SELECT BIT
++/* analog output SELECT BIT */
+ #define APCI3120_ANALOG_OP_CHANNEL_1   0x0000
+ #define APCI3120_ANALOG_OP_CHANNEL_2   0x4000
+ #define APCI3120_ANALOG_OP_CHANNEL_3   0x8000
+@@ -75,32 +75,32 @@ static const struct comedi_lrange range_apci3120_ao = { 2, {
+ #define APCI3120_ANALOG_OP_CHANNEL_7   0x8000
+ #define APCI3120_ANALOG_OP_CHANNEL_8   0xC000
+ 
+-// Enable external trigger bit in nWrAddress
++/* Enable external trigger bit in nWrAddress */
+ #define APCI3120_ENABLE_EXT_TRIGGER    0x8000
+ 
+-//ANALOG OUTPUT AND INPUT DEFINE
+-#define APCI3120_UNIPOLAR 0x80	//$$ RAM sequence polarity BIT
+-#define APCI3120_BIPOLAR  0x00	//$$ RAM sequence polarity BIT
+-#define APCI3120_ANALOG_OUTPUT_1 0x08	// (ADDRESS )
+-#define APCI3120_ANALOG_OUTPUT_2 0x0A	// (ADDRESS )
+-#define APCI3120_1_GAIN              0x00	//$$ RAM sequence Gain Bits for gain 1
+-#define APCI3120_2_GAIN              0x10	//$$ RAM sequence Gain Bits for gain 2
+-#define APCI3120_5_GAIN              0x20	//$$ RAM sequence Gain Bits for gain 5
+-#define APCI3120_10_GAIN             0x30	//$$ RAM sequence Gain Bits for gain 10
+-#define APCI3120_SEQ_RAM_ADDRESS        0x06	//$$ EARLIER NAMED APCI3120_FIFO_ADDRESS
+-#define APCI3120_RESET_FIFO          0x0C	//(ADDRESS)
+-#define APCI3120_TIMER_0_MODE_2      0x01	//$$ Bits for timer mode
++/* ANALOG OUTPUT AND INPUT DEFINE */
++#define APCI3120_UNIPOLAR 0x80	/* $$ RAM sequence polarity BIT */
++#define APCI3120_BIPOLAR  0x00	/* $$ RAM sequence polarity BIT */
++#define APCI3120_ANALOG_OUTPUT_1 0x08	/*  (ADDRESS ) */
++#define APCI3120_ANALOG_OUTPUT_2 0x0A	/*  (ADDRESS ) */
++#define APCI3120_1_GAIN              0x00	/* $$ RAM sequence Gain Bits for gain 1 */
++#define APCI3120_2_GAIN              0x10	/* $$ RAM sequence Gain Bits for gain 2 */
++#define APCI3120_5_GAIN              0x20	/* $$ RAM sequence Gain Bits for gain 5 */
++#define APCI3120_10_GAIN             0x30	/* $$ RAM sequence Gain Bits for gain 10 */
++#define APCI3120_SEQ_RAM_ADDRESS        0x06	/* $$ EARLIER NAMED APCI3120_FIFO_ADDRESS */
++#define APCI3120_RESET_FIFO          0x0C	/* (ADDRESS) */
++#define APCI3120_TIMER_0_MODE_2      0x01	/* $$ Bits for timer mode */
+ #define APCI3120_TIMER_0_MODE_4       0x2
+ #define APCI3120_SELECT_TIMER_0_WORD 0x00
+-#define APCI3120_ENABLE_TIMER0     0x1000	//$$Gatebit 0 in nWrAddress
++#define APCI3120_ENABLE_TIMER0     0x1000	/* $$Gatebit 0 in nWrAddress */
+ #define APCI3120_CLEAR_PR          0xF0FF
+ #define APCI3120_CLEAR_PA          0xFFF0
+ #define APCI3120_CLEAR_PA_PR       (APCI3120_CLEAR_PR & APCI3120_CLEAR_PA)
+ 
+-// nWrMode_Select
+-#define APCI3120_ENABLE_SCAN          0x8	//$$ bit in nWrMode_Select
++/* nWrMode_Select */
++#define APCI3120_ENABLE_SCAN          0x8	/* $$ bit in nWrMode_Select */
+ #define APCI3120_DISABLE_SCAN      (~APCI3120_ENABLE_SCAN)
+-#define APCI3120_ENABLE_EOS_INT       0x2	//$$ bit in nWrMode_Select
++#define APCI3120_ENABLE_EOS_INT       0x2	/* $$ bit in nWrMode_Select */
+ 
+ #define APCI3120_DISABLE_EOS_INT   (~APCI3120_ENABLE_EOS_INT)
+ #define APCI3120_ENABLE_EOC_INT       0x1
+@@ -108,50 +108,50 @@ static const struct comedi_lrange range_apci3120_ao = { 2, {
+ #define APCI3120_DISABLE_ALL_INTERRUPT_WITHOUT_TIMER   (APCI3120_DISABLE_EOS_INT & APCI3120_DISABLE_EOC_INT)
+ #define APCI3120_DISABLE_ALL_INTERRUPT   (APCI3120_DISABLE_TIMER_INT & APCI3120_DISABLE_EOS_INT & APCI3120_DISABLE_EOC_INT)
+ 
+-//status register bits
++/* status register bits */
+ #define APCI3120_EOC                     0x8000
+ #define APCI3120_EOS                     0x2000
+ 
+-// software trigger dummy register
+-#define APCI3120_START_CONVERSION        0x02	//(ADDRESS)
++/* software trigger dummy register */
++#define APCI3120_START_CONVERSION        0x02	/* (ADDRESS) */
+ 
+-//TIMER DEFINE
++/* TIMER DEFINE */
+ #define APCI3120_QUARTZ_A				  70
+ #define APCI3120_QUARTZ_B				  50
+ #define APCI3120_TIMER                            1
+ #define APCI3120_WATCHDOG                         2
+ #define APCI3120_TIMER_DISABLE                    0
+ #define APCI3120_TIMER_ENABLE                     1
+-#define APCI3120_ENABLE_TIMER2                    0x4000	//$$ gatebit 2 in nWrAddress
++#define APCI3120_ENABLE_TIMER2                    0x4000	/* $$ gatebit 2 in nWrAddress */
+ #define APCI3120_DISABLE_TIMER2                   (~APCI3120_ENABLE_TIMER2)
+-#define APCI3120_ENABLE_TIMER_INT                 0x04	//$$ ENAIRQ_FC_Bit in nWrModeSelect
++#define APCI3120_ENABLE_TIMER_INT                 0x04	/* $$ ENAIRQ_FC_Bit in nWrModeSelect */
+ #define APCI3120_DISABLE_TIMER_INT                (~APCI3120_ENABLE_TIMER_INT)
+-#define APCI3120_WRITE_MODE_SELECT                0x0E	// (ADDRESS)
++#define APCI3120_WRITE_MODE_SELECT                0x0E	/*  (ADDRESS) */
+ #define APCI3120_SELECT_TIMER_0_WORD  0x00
+ #define APCI3120_SELECT_TIMER_1_WORD  0x01
+ #define APCI3120_TIMER_1_MODE_2       0x4
+ 
+-//$$ BIT FOR MODE IN nCsTimerCtr1
++/* $$ BIT FOR MODE IN nCsTimerCtr1 */
+ #define APCI3120_TIMER_2_MODE_0                   0x0
+ #define APCI3120_TIMER_2_MODE_2                   0x10
+ #define APCI3120_TIMER_2_MODE_5                   0x30
+ 
+-//$$ BIT FOR MODE IN nCsTimerCtr0
++/* $$ BIT FOR MODE IN nCsTimerCtr0 */
+ #define APCI3120_SELECT_TIMER_2_LOW_WORD          0x02
+ #define APCI3120_SELECT_TIMER_2_HIGH_WORD         0x03
+ 
+-#define APCI3120_TIMER_CRT0                       0x0D	//(ADDRESS for cCsTimerCtr0)
+-#define APCI3120_TIMER_CRT1                       0x0C	//(ADDRESS for cCsTimerCtr1)
++#define APCI3120_TIMER_CRT0                       0x0D	/* (ADDRESS for cCsTimerCtr0) */
++#define APCI3120_TIMER_CRT1                       0x0C	/* (ADDRESS for cCsTimerCtr1) */
+ 
+-#define APCI3120_TIMER_VALUE                      0x04	//ADDRESS for nCsTimerWert
+-#define APCI3120_TIMER_STATUS_REGISTER            0x0D	//ADDRESS for delete timer 2 interrupt
+-#define APCI3120_RD_STATUS                        0x02	//ADDRESS
+-#define APCI3120_WR_ADDRESS                       0x00	//ADDRESS
+-#define APCI3120_ENABLE_WATCHDOG                  0x20	//$$BIT in nWrMode_Select
++#define APCI3120_TIMER_VALUE                      0x04	/* ADDRESS for nCsTimerWert */
++#define APCI3120_TIMER_STATUS_REGISTER            0x0D	/* ADDRESS for delete timer 2 interrupt */
++#define APCI3120_RD_STATUS                        0x02	/* ADDRESS */
++#define APCI3120_WR_ADDRESS                       0x00	/* ADDRESS */
++#define APCI3120_ENABLE_WATCHDOG                  0x20	/* $$BIT in nWrMode_Select */
+ #define APCI3120_DISABLE_WATCHDOG                 (~APCI3120_ENABLE_WATCHDOG)
+-#define APCI3120_ENABLE_TIMER_COUNTER    		  0x10	//$$BIT in nWrMode_Select
++#define APCI3120_ENABLE_TIMER_COUNTER    		  0x10	/* $$BIT in nWrMode_Select */
+ #define APCI3120_DISABLE_TIMER_COUNTER            (~APCI3120_ENABLE_TIMER_COUNTER)
+-#define APCI3120_FC_TIMER                         0x1000	//bit in  status register
++#define APCI3120_FC_TIMER                         0x1000	/* bit in  status register */
+ #define APCI3120_ENABLE_TIMER0                    0x1000
+ #define APCI3120_ENABLE_TIMER1                    0x2000
+ #define APCI3120_ENABLE_TIMER2                    0x4000
+@@ -159,9 +159,9 @@ static const struct comedi_lrange range_apci3120_ao = { 2, {
+ #define APCI3120_DISABLE_TIMER1		              (~APCI3120_ENABLE_TIMER1)
+ #define APCI3120_DISABLE_TIMER2	                  (~APCI3120_ENABLE_TIMER2)
+ 
+-#define APCI3120_TIMER2_SELECT_EOS                0xC0	// ADDED on 20-6
+-#define APCI3120_COUNTER                          3	// on 20-6
+-#define APCI3120_DISABLE_ALL_TIMER                ( APCI3120_DISABLE_TIMER0 & APCI3120_DISABLE_TIMER1 & APCI3120_DISABLE_TIMER2 )	// on 20-6
++#define APCI3120_TIMER2_SELECT_EOS                0xC0	/*  ADDED on 20-6 */
++#define APCI3120_COUNTER                          3	/*  on 20-6 */
++#define APCI3120_DISABLE_ALL_TIMER                ( APCI3120_DISABLE_TIMER0 & APCI3120_DISABLE_TIMER1 & APCI3120_DISABLE_TIMER2 )	/*  on 20-6 */
+ 
+ #define MAX_ANALOGINPUT_CHANNELS    32
+ 
+@@ -177,9 +177,9 @@ struct str_AnalogReadInformation {
+ };
+ 
+ 
+-// Function Declaration For APCI-3120
++/* Function Declaration For APCI-3120 */
+ 
+-// Internal functions
++/* Internal functions */
+ int i_APCI3120_SetupChannelList(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				int n_chan, unsigned int *chanlist, char check);
+ int i_APCI3120_ExttrigEnable(struct comedi_device *dev);
+@@ -188,9 +188,9 @@ int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_su
+ int i_APCI3120_Reset(struct comedi_device *dev);
+ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device *dev,
+ 				 struct comedi_subdevice *s);
+-// Interrupt functions
++/* Interrupt functions */
+ void v_APCI3120_Interrupt(int irq, void *d);
+-//UPDATE-0.7.57->0.7.68 void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,struct comedi_subdevice *s,short *dma,short *data,int n);
++/* UPDATE-0.7.57->0.7.68 void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,struct comedi_subdevice *s,short *dma,short *data,int n); */
+ void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,
+ 					   struct comedi_subdevice *s,
+ 					   short *dma_buffer,
+@@ -198,7 +198,7 @@ void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,
+ int i_APCI3120_InterruptHandleEos(struct comedi_device *dev);
+ void v_APCI3120_InterruptDma(int irq, void *d);
+ 
+-// TIMER
++/* TIMER */
+ 
+ int i_APCI3120_InsnConfigTimer(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			       struct comedi_insn *insn, unsigned int *data);
+@@ -207,16 +207,19 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device *dev, struct comedi_subdevice
+ int i_APCI3120_InsnReadTimer(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			     struct comedi_insn *insn, unsigned int *data);
+ 
+-//DI
+-// for di read
++/*
++* DI for di read
++*/
+ 
+ int i_APCI3120_InsnBitsDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				    struct comedi_insn *insn, unsigned int *data);
+ int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				    struct comedi_insn *insn, unsigned int *data);
+ 
+-//DO
+-//int i_APCI3120_WriteDigitalOutput(struct comedi_device *dev, unsigned char data);
++/* DO */
++/* int i_APCI3120_WriteDigitalOutput(struct comedi_device *dev,
++ * unsigned char data);
++ */
+ int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device *dev,
+ 				       struct comedi_subdevice *s, struct comedi_insn *insn,
+ 				       unsigned int *data);
+@@ -225,12 +228,15 @@ int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device *dev, struct comedi_su
+ int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				      struct comedi_insn *insn, unsigned int *data);
+ 
+-//AO
+-//int i_APCI3120_Write1AnalogValue(struct comedi_device *dev,UINT ui_Range,UINT ui_Channel,UINT data );
++/* AO */
++/* int i_APCI3120_Write1AnalogValue(struct comedi_device *dev,UINT ui_Range,
++ * UINT ui_Channel,UINT data );
++ */
++
+ int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				     struct comedi_insn *insn, unsigned int *data);
+ 
+-//AI HArdware layer
++/* AI HArdware layer */
+ 
+ int i_APCI3120_InsnConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				     struct comedi_insn *insn, unsigned int *data);
+@@ -239,5 +245,5 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev, struct comedi_subd
+ int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				      struct comedi_cmd *cmd);
+ int i_APCI3120_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s);
+-//int i_APCI3120_CancelAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s);
++/* int i_APCI3120_CancelAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s); */
+ int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+index d25fdf690d1b..f3e7ebf8c1f3 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+@@ -15,9 +15,9 @@
+  * any later version.
+  */
+ 
+-// Card Specific information
++/* Card Specific information */
+ #define APCI3200_BOARD_VENDOR_ID                 0x15B8
+-//#define APCI3200_ADDRESS_RANGE                   264
++/* #define APCI3200_ADDRESS_RANGE                   264 */
+ 
+ int MODULE_NO;
+ struct {
+@@ -34,7 +34,7 @@ struct {
+ } Config_Parameters_Module1, Config_Parameters_Module2,
+     Config_Parameters_Module3, Config_Parameters_Module4;
+ 
+-//ANALOG INPUT RANGE
++/* ANALOG INPUT RANGE */
+ static const struct comedi_lrange range_apci3200_ai = { 8, {
+ 						     BIP_RANGE(10),
+ 						     BIP_RANGE(5),
+@@ -55,7 +55,7 @@ static const struct comedi_lrange range_apci3300_ai = { 4, {
+ 						     }
+ };
+ 
+-//Analog Input related Defines
++/* Analog Input related Defines */
+ #define APCI3200_AI_OFFSET_GAIN                  0
+ #define APCI3200_AI_SC_TEST                      4
+ #define APCI3200_AI_IRQ                          8
+@@ -89,9 +89,9 @@ static const struct comedi_lrange range_apci3300_ai = { 4, {
+ #define ADDIDATA_UNIPOLAR                        1
+ #define ADDIDATA_BIPOLAR                         2
+ 
+-//BEGIN JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++/* BEGIN JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ #define MAX_MODULE				4
+-//END JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++/* END JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ 
+ struct str_ADDIDATA_RTDStruct {
+ 	unsigned int ul_NumberOfValue;
+@@ -99,23 +99,23 @@ struct str_ADDIDATA_RTDStruct {
+ 	unsigned int *pul_TemperatureValue;
+ };
+ 
+-//BEGIN JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++/* BEGIN JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ struct str_Module {
+ 
+-	// Begin JK 05/08/2003 change for Linux
++	/*  Begin JK 05/08/2003 change for Linux */
+ 	unsigned long ul_CurrentSourceCJC;
+ 	unsigned long ul_CurrentSource[5];
+-	// End JK 05/08/2003 change for Linux
++	/*  End JK 05/08/2003 change for Linux */
+ 
+-	// Begin CG 15/02/02 Rev 1.0 -> Rev 1.1 : Add Header Type 1
+-	unsigned long ul_GainFactor[8];	// Gain Factor
++	/*  Begin CG 15/02/02 Rev 1.0 -> Rev 1.1 : Add Header Type 1 */
++	unsigned long ul_GainFactor[8];	/*  Gain Factor */
+ 	unsigned int w_GainValue[10];
+-	// End CG 15/02/02 Rev 1.0 -> Rev 1.1 : Add Header Type 1
++	/*  End CG 15/02/02 Rev 1.0 -> Rev 1.1 : Add Header Type 1 */
+ };
+ 
+-//END JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++/* END JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ 
+-//BEGIN JK 06.07.04: Management of sevrals boards
++/* BEGIN JK 06.07.04: Management of sevrals boards */
+ struct str_BoardInfos {
+ 
+ 	int i_CJCAvailable;
+@@ -138,25 +138,25 @@ struct str_BoardInfos {
+ 	unsigned int ui_Channel_num;
+ 	int i_Count;
+ 	int i_Initialised;
+-	//UINT ui_InterruptChannelValue[96]; //Buffer
+-	unsigned int ui_InterruptChannelValue[144];	//Buffer
++	/* UINT ui_InterruptChannelValue[96]; //Buffer */
++	unsigned int ui_InterruptChannelValue[144];	/* Buffer */
+ 	unsigned char b_StructInitialized;
+-	//Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+-	unsigned int ui_ScanValueArray[7 + 12];	// 7 is the maximal number of channels
+-	//End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
++	/* Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
++	unsigned int ui_ScanValueArray[7 + 12];	/*  7 is the maximal number of channels */
++	/* End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
+ 
+-	//Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++	/* Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ 	int i_ConnectionType;
+ 	int i_NbrOfModule;
+ 	struct str_Module s_Module[MAX_MODULE];
+-	//End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++	/* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ };
+ 
+-//END JK 06.07.04: Management of sevrals boards
++/* END JK 06.07.04: Management of sevrals boards */
+ 
+-// Hardware Layer  functions for Apci3200
++/* Hardware Layer  functions for Apci3200 */
+ 
+-//AI
++/* AI */
+ 
+ int i_APCI3200_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 struct comedi_insn *insn, unsigned int *data);
+@@ -175,10 +175,10 @@ int i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_s
+ int i_APCI3200_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s);
+ int i_APCI3200_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				struct comedi_insn *insn, unsigned int *data);
+-//Interrupt
++/* Interrupt */
+ void v_APCI3200_Interrupt(int irq, void *d);
+ int i_APCI3200_InterruptHandleEos(struct comedi_device *dev);
+-//Reset functions
++/* Reset functions */
+ int i_APCI3200_Reset(struct comedi_device *dev);
+ 
+ int i_APCI3200_ReadCJCCalOffset(struct comedi_device *dev, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
+index da2221d51d61..dfca2e6d4d8c 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
+@@ -83,16 +83,16 @@ int i_APCI3501_ReadDigitalInput(struct comedi_device * dev, struct comedi_subdev
+ 	*data = inl(devpriv->iobase + APCI3501_DIGITAL_IP);
+ 	if (ui_Temp == 0) {
+ 		*data = (*data >> ui_NoOfChannel) & 0x1;
+-	}			//if  (ui_Temp==0)
++	}			/* if  (ui_Temp==0) */
+ 	else {
+ 		if (ui_Temp == 1) {
+ 
+ 			*data = *data & 0x3;
+-		}		//if  (ui_Temp==1)
++		}		/* if  (ui_Temp==1) */
+ 		else {
+ 			printk("\nSpecified channel not supported \n");
+-		}		//elseif  (ui_Temp==1)
+-	}			//elseif  (ui_Temp==0)
++		}		/* elseif  (ui_Temp==1) */
++	}			/* elseif  (ui_Temp==0) */
+ 	return insn->n;
+ }
+ 
+@@ -129,13 +129,13 @@ int i_APCI3501_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ 		comedi_error(dev,
+ 			"Not a valid Data !!! ,Data should be 1 or 0\n");
+ 		return -EINVAL;
+-	}			//if  ( (data[0]!=0) && (data[0]!=1) )
++	}			/* if  ( (data[0]!=0) && (data[0]!=1) ) */
+ 	if (data[0]) {
+ 		devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
+-	}			// if  (data[0])
++	}			/*  if  (data[0]) */
+ 	else {
+ 		devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
+-	}			//else if  (data[0])
++	}			/* else if  (data[0]) */
+ 	return insn->n;
+ }
+ 
+@@ -165,29 +165,29 @@ int i_APCI3501_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int ui_Temp, ui_Temp1;
+-	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
++	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	/*  get the channel */
+ 	if (devpriv->b_OutputMemoryStatus) {
+ 		ui_Temp = inl(devpriv->iobase + APCI3501_DIGITAL_OP);
+-	}			//if(devpriv->b_OutputMemoryStatus )
++	}			/* if(devpriv->b_OutputMemoryStatus ) */
+ 	else {
+ 		ui_Temp = 0;
+-	}			//if(devpriv->b_OutputMemoryStatus )
++	}			/* if(devpriv->b_OutputMemoryStatus ) */
+ 	if (data[3] == 0) {
+ 		if (data[1] == 0) {
+ 			data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
+ 			outl(data[0], devpriv->iobase + APCI3501_DIGITAL_OP);
+-		}		//if(data[1]==0)
++		}		/* if(data[1]==0) */
+ 		else {
+ 			if (data[1] == 1) {
+ 				data[0] = (data[0] << (2 * data[2])) | ui_Temp;
+ 				outl(data[0],
+ 					devpriv->iobase + APCI3501_DIGITAL_OP);
+-			}	// if(data[1]==1)
++			}	/*  if(data[1]==1) */
+ 			else {
+ 				printk("\nSpecified channel not supported\n");
+-			}	//else if(data[1]==1)
+-		}		//elseif(data[1]==0)
+-	}			//if(data[3]==0)
++			}	/* else if(data[1]==1) */
++		}		/* elseif(data[1]==0) */
++	}			/* if(data[3]==0) */
+ 	else {
+ 		if (data[3] == 1) {
+ 			if (data[1] == 0) {
+@@ -201,7 +201,7 @@ int i_APCI3501_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 				data[0] = data[0] & ui_Temp;
+ 				outl(data[0],
+ 					devpriv->iobase + APCI3501_DIGITAL_OP);
+-			}	//if(data[1]==0)
++			}	/* if(data[1]==0) */
+ 			else {
+ 				if (data[1] == 1) {
+ 					data[0] = ~data[0] & 0x3;
+@@ -215,17 +215,17 @@ int i_APCI3501_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 					outl(data[0],
+ 						devpriv->iobase +
+ 						APCI3501_DIGITAL_OP);
+-				}	// if(data[1]==1)
++				}	/*  if(data[1]==1) */
+ 				else {
+ 					printk("\nSpecified channel not supported\n");
+-				}	//else if(data[1]==1)
+-			}	//elseif(data[1]==0)
+-		}		//if(data[3]==1);
++				}	/* else if(data[1]==1) */
++			}	/* elseif(data[1]==0) */
++		}		/* if(data[3]==1); */
+ 		else {
+ 			printk("\nSpecified functionality does not exist\n");
+ 			return -EINVAL;
+-		}		//if else data[3]==1)
+-	}			//if else data[3]==0)
++		}		/* if else data[3]==1) */
++	}			/* if else data[3]==0) */
+ 	return insn->n;
+ }
+ 
+@@ -259,16 +259,16 @@ int i_APCI3501_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ 	*data = inl(devpriv->iobase + APCI3501_DIGITAL_OP);
+ 	if (ui_Temp == 0) {
+ 		*data = (*data >> ui_NoOfChannel) & 0x1;
+-	}			// if  (ui_Temp==0)
++	}			/*  if  (ui_Temp==0) */
+ 	else {
+ 		if (ui_Temp == 1) {
+ 			*data = *data & 0x3;
+ 
+-		}		// if  (ui_Temp==1)
++		}		/*  if  (ui_Temp==1) */
+ 		else {
+ 			printk("\nSpecified channel not supported \n");
+-		}		// else if (ui_Temp==1)
+-	}			// else if  (ui_Temp==0)
++		}		/*  else if (ui_Temp==1) */
++	}			/*  else if  (ui_Temp==0) */
+ 	return insn->n;
+ }
+ 
+@@ -349,18 +349,18 @@ int i_APCI3501_WriteAnalogOutput(struct comedi_device * dev, struct comedi_subde
+ 			printk("\nIn WriteAnalogOutput :: Not Valid Data\n");
+ 		}
+ 
+-	}			// end if(devpriv->b_InterruptMode==MODE1)
++	}			/*  end if(devpriv->b_InterruptMode==MODE1) */
+ 	else {
+ 		ul_Polarity = 0;
+ 		if ((*data < 0) || (*data > 8192)) {
+ 			printk("\nIn WriteAnalogOutput :: Not Valid Data\n");
+ 		}
+ 
+-	}			// end else
++	}			/*  end else */
+ 
+ 	if ((ul_Channel_no < 0) || (ul_Channel_no > 7)) {
+ 		printk("\nIn WriteAnalogOutput :: Not Valid Channel\n");
+-	}			// end if((ul_Channel_no<0)||(ul_Channel_no>7))
++	}			/*  end if((ul_Channel_no<0)||(ul_Channel_no>7)) */
+ 
+ 	ul_DAC_Ready = inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT);
+ 
+@@ -370,7 +370,7 @@ int i_APCI3501_WriteAnalogOutput(struct comedi_device * dev, struct comedi_subde
+ 	}
+ 
+ 	if (ul_DAC_Ready) {
+-// Output the Value on the output channels.
++/* Output the Value on the output channels. */
+ 		ul_Command1 =
+ 			(unsigned int) ((unsigned int) (ul_Channel_no & 0xFF) |
+ 			(unsigned int) ((*data << 0x8) & 0x7FFFFF00L) |
+@@ -418,70 +418,70 @@ int i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ 	if (data[0] == ADDIDATA_WATCHDOG) {
+ 
+ 		devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG;
+-		//Disable the watchdog
+-		outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);	//disable Wa
++		/* Disable the watchdog */
++		outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);	/* disable Wa */
+ 
+ 		if (data[1] == 1) {
+-			//Enable TIMER int & DISABLE ALL THE OTHER int SOURCES
++			/* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */
+ 			outl(0x02,
+ 				devpriv->iobase + APCI3501_WATCHDOG +
+ 				APCI3501_TCW_PROG);
+ 		} else {
+-			outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);	//disable Timer interrupt
++			outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);	/* disable Timer interrupt */
+ 		}
+ 
+-		//Loading the Timebase value
++		/* Loading the Timebase value */
+ 		outl(data[2],
+ 			devpriv->iobase + APCI3501_WATCHDOG +
+ 			APCI3501_TCW_TIMEBASE);
+ 
+-		//Loading the Reload value
++		/* Loading the Reload value */
+ 		outl(data[3],
+ 			devpriv->iobase + APCI3501_WATCHDOG +
+ 			APCI3501_TCW_RELOAD_VALUE);
+-		//Set the mode
+-		ul_Command1 = inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG) | 0xFFF819E0UL;	//e2->e0
++		/* Set the mode */
++		ul_Command1 = inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG) | 0xFFF819E0UL;	/* e2->e0 */
+ 		outl(ul_Command1,
+ 			devpriv->iobase + APCI3501_WATCHDOG +
+ 			APCI3501_TCW_PROG);
+-	}			//end if(data[0]==ADDIDATA_WATCHDOG)
++	}			/* end if(data[0]==ADDIDATA_WATCHDOG) */
+ 
+ 	else if (data[0] == ADDIDATA_TIMER) {
+-		//First Stop The Timer
++		/* First Stop The Timer */
+ 		ul_Command1 =
+ 			inl(devpriv->iobase + APCI3501_WATCHDOG +
+ 			APCI3501_TCW_PROG);
+ 		ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
+-		outl(ul_Command1, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);	//Stop The Timer
++		outl(ul_Command1, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);	/* Stop The Timer */
+ 		devpriv->b_TimerSelectMode = ADDIDATA_TIMER;
+ 		if (data[1] == 1) {
+-			//Enable TIMER int & DISABLE ALL THE OTHER int SOURCES
++			/* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */
+ 			outl(0x02,
+ 				devpriv->iobase + APCI3501_WATCHDOG +
+ 				APCI3501_TCW_PROG);
+ 		} else {
+-			outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);	//disable Timer interrupt
++			outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);	/* disable Timer interrupt */
+ 		}
+ 
+-		// Loading Timebase
++		/*  Loading Timebase */
+ 		outl(data[2],
+ 			devpriv->iobase + APCI3501_WATCHDOG +
+ 			APCI3501_TCW_TIMEBASE);
+ 
+-		//Loading the Reload value
++		/* Loading the Reload value */
+ 		outl(data[3],
+ 			devpriv->iobase + APCI3501_WATCHDOG +
+ 			APCI3501_TCW_RELOAD_VALUE);
+ 
+-		// printk ("\nTimer Address :: %x\n", (devpriv->iobase+APCI3501_WATCHDOG));
++		/*  printk ("\nTimer Address :: %x\n", (devpriv->iobase+APCI3501_WATCHDOG)); */
+ 		ul_Command1 =
+ 			inl(devpriv->iobase + APCI3501_WATCHDOG +
+ 			APCI3501_TCW_PROG);
+ 		ul_Command1 =
+ 			(ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL;
+-		outl(ul_Command1, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);	//mode 2
++		outl(ul_Command1, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);	/* mode 2 */
+ 
+-	}			//end if(data[0]==ADDIDATA_TIMER)
++	}			/* end if(data[0]==ADDIDATA_TIMER) */
+ 
+ 	return insn->n;
+ }
+@@ -523,15 +523,15 @@ int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ 				inl(devpriv->iobase + APCI3501_WATCHDOG +
+ 				APCI3501_TCW_PROG);
+ 			ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
+-			//Enable the Watchdog
++			/* Enable the Watchdog */
+ 			outl(ul_Command1,
+ 				devpriv->iobase + APCI3501_WATCHDOG +
+ 				APCI3501_TCW_PROG);
+ 		}
+ 
+-		else if (data[1] == 0)	//Stop The Watchdog
++		else if (data[1] == 0)	/* Stop The Watchdog */
+ 		{
+-			//Stop The Watchdog
++			/* Stop The Watchdog */
+ 			ul_Command1 =
+ 				inl(devpriv->iobase + APCI3501_WATCHDOG +
+ 				APCI3501_TCW_PROG);
+@@ -547,8 +547,8 @@ int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ 			outl(ul_Command1,
+ 				devpriv->iobase + APCI3501_WATCHDOG +
+ 				APCI3501_TCW_PROG);
+-		}		//if(data[1]==2)
+-	}			// end if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG)
++		}		/* if(data[1]==2) */
++	}			/*  end if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) */
+ 
+ 	if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
+ 		if (data[1] == 1) {
+@@ -557,12 +557,12 @@ int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ 				inl(devpriv->iobase + APCI3501_WATCHDOG +
+ 				APCI3501_TCW_PROG);
+ 			ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
+-			//Enable the Timer
++			/* Enable the Timer */
+ 			outl(ul_Command1,
+ 				devpriv->iobase + APCI3501_WATCHDOG +
+ 				APCI3501_TCW_PROG);
+ 		} else if (data[1] == 0) {
+-			//Stop The Timer
++			/* Stop The Timer */
+ 			ul_Command1 =
+ 				inl(devpriv->iobase + APCI3501_WATCHDOG +
+ 				APCI3501_TCW_PROG);
+@@ -573,7 +573,7 @@ int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ 		}
+ 
+ 		else if (data[1] == 2) {
+-			//Trigger the Timer
++			/* Trigger the Timer */
+ 			ul_Command1 =
+ 				inl(devpriv->iobase + APCI3501_WATCHDOG +
+ 				APCI3501_TCW_PROG);
+@@ -583,7 +583,7 @@ int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ 				APCI3501_TCW_PROG);
+ 		}
+ 
+-	}			// end if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER)
++	}			/*  end if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */
+ 	i_Temp = inl(devpriv->iobase + APCI3501_WATCHDOG +
+ 		APCI3501_TCW_TRIG_STATUS) & 0x1;
+ 	return insn->n;
+@@ -622,14 +622,14 @@ int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device * dev,
+ 			inl(devpriv->iobase + APCI3501_WATCHDOG +
+ 			APCI3501_TCW_TRIG_STATUS) & 0x1;
+ 		data[1] = inl(devpriv->iobase + APCI3501_WATCHDOG);
+-	}			// end if  (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG)
++	}			/*  end if  (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) */
+ 
+ 	else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
+ 		data[0] =
+ 			inl(devpriv->iobase + APCI3501_WATCHDOG +
+ 			APCI3501_TCW_TRIG_STATUS) & 0x1;
+ 		data[1] = inl(devpriv->iobase + APCI3501_WATCHDOG);
+-	}			// end if  (devpriv->b_TimerSelectMode==ADDIDATA_TIMER)
++	}			/*  end if  (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */
+ 
+ 	else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER)
+ 		&& (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG)) {
+@@ -674,7 +674,7 @@ int i_APCI3501_Reset(struct comedi_device * dev)
+ 		}
+ 
+ 		if (ul_DAC_Ready) {
+-			// Output the Value on the output channels.
++			/*  Output the Value on the output channels. */
+ 			ul_Command1 =
+ 				(unsigned int) ((unsigned int) (i_Count & 0xFF) |
+ 				(unsigned int) ((i_temp << 0x8) & 0x7FFFFF00L) |
+@@ -711,7 +711,7 @@ void v_APCI3501_Interrupt(int irq, void *d)
+ 	struct comedi_device *dev = d;
+ 	unsigned int ui_Timer_AOWatchdog;
+ 	unsigned long ul_Command1;
+-	// Disable Interrupt
++	/*  Disable Interrupt */
+ 	ul_Command1 =
+ 		inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);
+ 
+@@ -728,8 +728,9 @@ void v_APCI3501_Interrupt(int irq, void *d)
+ 		return;
+ 	}
+ 
+-	// Enable Interrupt
+-	//Send a signal to from kernel to user space
++/*
++* Enable Interrupt Send a signal to from kernel to user space
++*/
+ 	send_sig(SIGIO, devpriv->tsk_Current, 0);
+ 	ul_Command1 =
+ 		inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
+index ba71f2dc760a..c456d75674b8 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
+@@ -15,7 +15,7 @@
+  * any later version.
+  */
+ 
+-// Card Specific information
++/* Card Specific information */
+ #define APCI3501_BOARD_VENDOR_ID                 0x15B8
+ #define APCI3501_ADDRESS_RANGE                   255
+ 
+@@ -23,7 +23,7 @@
+ #define APCI3501_DIGITAL_OP                       0x40
+ #define APCI3501_ANALOG_OUTPUT                    0x00
+ 
+-//Analog Output related Defines
++/* Analog Output related Defines */
+ #define APCI3501_AO_VOLT_MODE                     0
+ #define APCI3501_AO_PROG                          4
+ #define APCI3501_AO_TRIG_SCS                      8
+@@ -31,14 +31,14 @@
+ #define BIPOLAR                                   1
+ #define MODE0                                     0
+ #define MODE1                                     1
+-// ANALOG OUTPUT RANGE
++/* ANALOG OUTPUT RANGE */
+ struct comedi_lrange range_apci3501_ao = { 2, {
+ 					BIP_RANGE(10),
+ 					UNI_RANGE(10)
+ 					}
+ };
+ 
+-//Watchdog Related Defines
++/* Watchdog Related Defines */
+ 
+ #define APCI3501_WATCHDOG                         0x20
+ #define APCI3501_TCW_SYNC_ENABLEDISABLE           0
+@@ -52,22 +52,24 @@ struct comedi_lrange range_apci3501_ao = { 2, {
+ #define ADDIDATA_TIMER                            0
+ #define ADDIDATA_WATCHDOG                         2
+ 
+-// Hardware Layer  functions for Apci3501
++/* Hardware Layer  functions for Apci3501 */
+ 
+-//AO
++/* AO */
+ int i_APCI3501_ConfigAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				  struct comedi_insn *insn, unsigned int *data);
+ int i_APCI3501_WriteAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 struct comedi_insn *insn, unsigned int *data);
+ 
+-//DI
+-// for di read
+-//INT i_APCI3501_ReadDigitalInput(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data);
++/*
++* DI for di read INT i_APCI3501_ReadDigitalInput(struct
++* comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn
++* *insn,unsigned int *data);
++*/
+ 
+ int i_APCI3501_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				struct comedi_insn *insn, unsigned int *data);
+ 
+-//DO
++/* DO */
+ int i_APCI3501_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   struct comedi_insn *insn, unsigned int *data);
+ int i_APCI3501_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+@@ -75,8 +77,10 @@ int i_APCI3501_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subde
+ int i_APCI3501_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 struct comedi_insn *insn, unsigned int *data);
+ 
+-// TIMER
+-// timer value is passed as u seconds
++/* TIMER
++ * timer value is passed as u seconds
++ */
++
+ int i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device *dev,
+ 					  struct comedi_subdevice *s,
+ 					  struct comedi_insn *insn, unsigned int *data);
+@@ -87,8 +91,8 @@ int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
+ int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device *dev,
+ 					struct comedi_subdevice *s,
+ 					struct comedi_insn *insn, unsigned int *data);
+-//Interrupt
++/* Interrupt */
+ void v_APCI3501_Interrupt(int irq, void *d);
+ 
+-//Reset functions
++/* Reset functions */
+ int i_APCI3501_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi_apci_035.c b/drivers/staging/comedi/drivers/addi_apci_035.c
+index bac018202fe8..da454e854c4c 100644
+--- a/drivers/staging/comedi/drivers/addi_apci_035.c
++++ b/drivers/staging/comedi/drivers/addi_apci_035.c
+@@ -1,5 +1,5 @@
+ #define CONFIG_APCI_035 1
+ 
+-#define ADDIDATA_WATCHDOG 2	// Or shold it be something else
++#define ADDIDATA_WATCHDOG 2	/*  Or shold it be something else */
+ 
+ #include "addi-data/addi_common.c"
+diff --git a/drivers/staging/comedi/drivers/adl_pci7296.c b/drivers/staging/comedi/drivers/adl_pci7296.c
+index bd0f9ab226ef..1d9f5ad69722 100644
+--- a/drivers/staging/comedi/drivers/adl_pci7296.c
++++ b/drivers/staging/comedi/drivers/adl_pci7296.c
+@@ -39,7 +39,7 @@ Configuration Options:
+ 
+ #include "comedi_pci.h"
+ #include "8255.h"
+-// #include "8253.h"
++/* #include "8253.h" */
+ 
+ #define PORT1A 0
+ #define PORT2A 4
+@@ -115,7 +115,7 @@ static int adl_pci7296_attach(struct comedi_device * dev, struct comedi_devconfi
+ 			dev->iobase = pci_resource_start(pcidev, 2);
+ 			printk("comedi: base addr %4lx\n", dev->iobase);
+ 
+-			// four 8255 digital io subdevices
++			/*  four 8255 digital io subdevices */
+ 			s = dev->subdevices + 0;
+ 			subdev_8255_init(dev, s, NULL,
+ 				(unsigned long)(dev->iobase));
+@@ -159,7 +159,7 @@ static int adl_pci7296_detach(struct comedi_device * dev)
+ 		}
+ 		pci_dev_put(devpriv->pci_dev);
+ 	}
+-	// detach four 8255 digital io subdevices
++	/*  detach four 8255 digital io subdevices */
+ 	if (dev->subdevices) {
+ 		subdev_8255_cleanup(dev, dev->subdevices + 0);
+ 		subdev_8255_cleanup(dev, dev->subdevices + 1);
+diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c
+index adf90be79983..dd376b69bde3 100644
+--- a/drivers/staging/comedi/drivers/adl_pci8164.c
++++ b/drivers/staging/comedi/drivers/adl_pci8164.c
+@@ -149,7 +149,7 @@ static int adl_pci8164_attach(struct comedi_device * dev, struct comedi_devconfi
+ 			s->n_chan = 4;
+ 			s->maxdata = 0xffff;
+ 			s->len_chanlist = 4;
+-			//s->range_table = &range_axis;
++			/* s->range_table = &range_axis; */
+ 			s->insn_read = adl_pci8164_insn_read_msts;
+ 			s->insn_write = adl_pci8164_insn_write_cmd;
+ 
+@@ -159,7 +159,7 @@ static int adl_pci8164_attach(struct comedi_device * dev, struct comedi_devconfi
+ 			s->n_chan = 4;
+ 			s->maxdata = 0xffff;
+ 			s->len_chanlist = 4;
+-			//s->range_table = &range_axis;
++			/* s->range_table = &range_axis; */
+ 			s->insn_read = adl_pci8164_insn_read_ssts;
+ 			s->insn_write = adl_pci8164_insn_write_otp;
+ 
+@@ -169,7 +169,7 @@ static int adl_pci8164_attach(struct comedi_device * dev, struct comedi_devconfi
+ 			s->n_chan = 4;
+ 			s->maxdata = 0xffff;
+ 			s->len_chanlist = 4;
+-			//s->range_table = &range_axis;
++			/* s->range_table = &range_axis; */
+ 			s->insn_read = adl_pci8164_insn_read_buf0;
+ 			s->insn_write = adl_pci8164_insn_write_buf0;
+ 
+@@ -179,7 +179,7 @@ static int adl_pci8164_attach(struct comedi_device * dev, struct comedi_devconfi
+ 			s->n_chan = 4;
+ 			s->maxdata = 0xffff;
+ 			s->len_chanlist = 4;
+-			//s->range_table = &range_axis;
++			/* s->range_table = &range_axis; */
+ 			s->insn_read = adl_pci8164_insn_read_buf1;
+ 			s->insn_write = adl_pci8164_insn_write_buf1;
+ 
+diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
+index 1e4a556935ca..b8b5001c5d24 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1710.c
++++ b/drivers/staging/comedi/drivers/adv_pci1710.c
+@@ -63,7 +63,7 @@ Configuration options:
+ #define DPRINTK(fmt, args...)
+ #endif
+ 
+-// hardware types of the cards
++/* hardware types of the cards */
+ #define TYPE_PCI171X	0
+ #define TYPE_PCI1713	2
+ #define TYPE_PCI1720	3
+@@ -89,12 +89,12 @@ Configuration options:
+ #define PCI171x_CNT2	28	/* R/W: 8254 couter 2 */
+ #define PCI171x_CNTCTRL	30	/* W:   8254 counter control */
+ 
+-// upper bits from status register (PCI171x_STATUS) (lower is same woth control reg)
++/* upper bits from status register (PCI171x_STATUS) (lower is same woth control reg) */
+ #define	Status_FE	0x0100	/* 1=FIFO is empty */
+ #define Status_FH	0x0200	/* 1=FIFO is half full */
+ #define Status_FF	0x0400	/* 1=FIFO is full, fatal error */
+ #define Status_IRQ	0x0800	/* 1=IRQ occured */
+-// bits from control register (PCI171x_CONTROL)
++/* bits from control register (PCI171x_CONTROL) */
+ #define Control_CNT0	0x0040	/* 1=CNT0 have external source, 0=have internal 100kHz source */
+ #define Control_ONEFH	0x0020	/* 1=IRQ on FIFO is half full, 0=every sample */
+ #define Control_IRQEN	0x0010	/* 1=enable IRQ */
+@@ -102,7 +102,7 @@ Configuration options:
+ #define Control_EXT	0x0004	/* 1=external trigger source */
+ #define Control_PACER	0x0002	/* 1=enable internal 8254 trigger source */
+ #define Control_SW	0x0001	/* 1=enable software trigger source */
+-// bits from counter control register (PCI171x_CNTCTRL)
++/* bits from counter control register (PCI171x_CNTCTRL) */
+ #define Counter_BCD     0x0001	/* 0 = binary counter, 1 = BCD counter */
+ #define Counter_M0      0x0002	/* M0-M2 select modes 0-5 */
+ #define Counter_M1      0x0004	/* 000 = mode 0, 010 = mode 2 ... */
+@@ -120,7 +120,7 @@ Configuration options:
+ #define PCI1720_SYNCOUT	 9	/* W:   D/A synchronized output register */
+ #define PCI1720_SYNCONT	15	/* R/W: D/A synchronized control */
+ 
+-// D/A synchronized control (PCI1720_SYNCONT)
++/* D/A synchronized control (PCI1720_SYNCONT) */
+ #define Syncont_SC0	 1	/* set synchronous output mode */
+ 
+ static const struct comedi_lrange range_pci1710_3 = { 9, {
+@@ -188,24 +188,24 @@ static int pci1710_attach(struct comedi_device * dev, struct comedi_devconfig *
+ static int pci1710_detach(struct comedi_device * dev);
+ 
+ struct boardtype {
+-	const char *name;	// board name
++	const char *name;	/*  board name */
+ 	int device_id;
+-	int iorange;		// I/O range len
+-	char have_irq;		// 1=card support IRQ
+-	char cardtype;		// 0=1710& co. 2=1713, ...
+-	int n_aichan;		// num of A/D chans
+-	int n_aichand;		// num of A/D chans in diff mode
+-	int n_aochan;		// num of D/A chans
+-	int n_dichan;		// num of DI chans
+-	int n_dochan;		// num of DO chans
+-	int n_counter;		// num of counters
+-	int ai_maxdata;		// resolution of A/D
+-	int ao_maxdata;		// resolution of D/A
+-	const struct comedi_lrange *rangelist_ai;	// rangelist for A/D
+-	const char *rangecode_ai;	// range codes for programming
+-	const struct comedi_lrange *rangelist_ao;	// rangelist for D/A
+-	unsigned int ai_ns_min;	// max sample speed of card v ns
+-	unsigned int fifo_half_size;	// size of FIFO/2
++	int iorange;		/*  I/O range len */
++	char have_irq;		/*  1=card support IRQ */
++	char cardtype;		/*  0=1710& co. 2=1713, ... */
++	int n_aichan;		/*  num of A/D chans */
++	int n_aichand;		/*  num of A/D chans in diff mode */
++	int n_aochan;		/*  num of D/A chans */
++	int n_dichan;		/*  num of DI chans */
++	int n_dochan;		/*  num of DO chans */
++	int n_counter;		/*  num of counters */
++	int ai_maxdata;		/*  resolution of A/D */
++	int ao_maxdata;		/*  resolution of D/A */
++	const struct comedi_lrange *rangelist_ai;	/*  rangelist for A/D */
++	const char *rangecode_ai;	/*  range codes for programming */
++	const struct comedi_lrange *rangelist_ao;	/*  rangelist for D/A */
++	unsigned int ai_ns_min;	/*  max sample speed of card v ns */
++	unsigned int fifo_half_size;	/*  size of FIFO/2 */
+ };
+ 
+ static DEFINE_PCI_DEVICE_TABLE(pci1710_pci_table) = {
+@@ -252,7 +252,7 @@ static const struct boardtype boardtypes[] = {
+ 		16, 0, 0, 16, 16, 0, 0x0fff, 0x0000,
+ 		&range_pci17x1, range_codes_pci17x1, NULL,
+ 		10000, 512},
+-	// dummy entry corresponding to driver name
++	/*  dummy entry corresponding to driver name */
+ 	{.name = DRV_NAME},
+ };
+ 
+@@ -269,34 +269,34 @@ static struct comedi_driver driver_pci1710 = {
+ };
+ 
+ struct pci1710_private {
+-	struct pci_dev *pcidev;	// ptr to PCI device
+-	char valid;		// card is usable
+-	char neverending_ai;	// we do unlimited AI
+-	unsigned int CntrlReg;	// Control register
+-	unsigned int i8254_osc_base;	// frequence of onboard oscilator
+-	unsigned int ai_do;	// what do AI? 0=nothing, 1 to 4 mode
+-	unsigned int ai_act_scan;	// how many scans we finished
+-	unsigned int ai_act_chan;	// actual position in actual scan
+-	unsigned int ai_buf_ptr;	// data buffer ptr in samples
+-	unsigned char ai_eos;	// 1=EOS wake up
++	struct pci_dev *pcidev;	/*  ptr to PCI device */
++	char valid;		/*  card is usable */
++	char neverending_ai;	/*  we do unlimited AI */
++	unsigned int CntrlReg;	/*  Control register */
++	unsigned int i8254_osc_base;	/*  frequence of onboard oscilator */
++	unsigned int ai_do;	/*  what do AI? 0=nothing, 1 to 4 mode */
++	unsigned int ai_act_scan;	/*  how many scans we finished */
++	unsigned int ai_act_chan;	/*  actual position in actual scan */
++	unsigned int ai_buf_ptr;	/*  data buffer ptr in samples */
++	unsigned char ai_eos;	/*  1=EOS wake up */
+ 	unsigned char ai_et;
+ 	unsigned int ai_et_CntrlReg;
+ 	unsigned int ai_et_MuxVal;
+ 	unsigned int ai_et_div1, ai_et_div2;
+-	unsigned int act_chanlist[32];	// list of scaned channel
+-	unsigned char act_chanlist_len;	// len of scanlist
+-	unsigned char act_chanlist_pos;	// actual position in MUX list
+-	unsigned char da_ranges;	// copy of D/A outpit range register
+-	unsigned int ai_scans;	// len of scanlist
+-	unsigned int ai_n_chan;	// how many channels is measured
+-	unsigned int *ai_chanlist;	// actaul chanlist
+-	unsigned int ai_flags;	// flaglist
+-	unsigned int ai_data_len;	// len of data buffer
+-	short *ai_data;	// data buffer
+-	unsigned int ai_timer1;	// timers
++	unsigned int act_chanlist[32];	/*  list of scaned channel */
++	unsigned char act_chanlist_len;	/*  len of scanlist */
++	unsigned char act_chanlist_pos;	/*  actual position in MUX list */
++	unsigned char da_ranges;	/*  copy of D/A outpit range register */
++	unsigned int ai_scans;	/*  len of scanlist */
++	unsigned int ai_n_chan;	/*  how many channels is measured */
++	unsigned int *ai_chanlist;	/*  actaul chanlist */
++	unsigned int ai_flags;	/*  flaglist */
++	unsigned int ai_data_len;	/*  len of data buffer */
++	short *ai_data;	/*  data buffer */
++	unsigned int ai_timer1;	/*  timers */
+ 	unsigned int ai_timer2;
+-	short ao_data[4];	// data output buffer
+-	unsigned int cnt0_write_wait;	// after a write, wait for update of the internal state
++	short ao_data[4];	/*  data output buffer */
++	unsigned int cnt0_write_wait;	/*  after a write, wait for update of the internal state */
+ };
+ 
+ #define devpriv ((struct pci1710_private *)dev->private)
+@@ -315,7 +315,7 @@ static void start_pacer(struct comedi_device * dev, int mode, unsigned int divis
+ static int pci1710_reset(struct comedi_device * dev);
+ static int pci171x_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ 
+-static const unsigned int muxonechan[] = { 0x0000, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, 0x0707,	// used for gain list programming
++static const unsigned int muxonechan[] = { 0x0000, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, 0x0707,	/*  used for gain list programming */
+ 	0x0808, 0x0909, 0x0a0a, 0x0b0b, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f,
+ 	0x1010, 0x1111, 0x1212, 0x1313, 0x1414, 0x1515, 0x1616, 0x1717,
+ 	0x1818, 0x1919, 0x1a1a, 0x1b1b, 0x1c1c, 0x1d1d, 0x1e1e, 0x1f1f
+@@ -334,7 +334,7 @@ static int pci171x_insn_read_ai(struct comedi_device * dev, struct comedi_subdev
+ 
+ 	DPRINTK("adv_pci1710 EDBG: BGN: pci171x_insn_read_ai(...)\n");
+ 	devpriv->CntrlReg &= Control_CNT0;
+-	devpriv->CntrlReg |= Control_SW;	// set software trigger
++	devpriv->CntrlReg |= Control_SW;	/*  set software trigger */
+ 	outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
+ 	outb(0, dev->iobase + PCI171x_CLRFIFO);
+ 	outb(0, dev->iobase + PCI171x_CLRINT);
+@@ -348,7 +348,7 @@ static int pci171x_insn_read_ai(struct comedi_device * dev, struct comedi_subdev
+ 		outw(0, dev->iobase + PCI171x_SOFTTRG);	/* start conversion */
+ 		DPRINTK("adv_pci1710 B n=%d ST=%4x\n", n,
+ 			inw(dev->iobase + PCI171x_STATUS));
+-		//comedi_udelay(1);
++		/* comedi_udelay(1); */
+ 		DPRINTK("adv_pci1710 C n=%d ST=%4x\n", n,
+ 			inw(dev->iobase + PCI171x_STATUS));
+ 		timeout = 100;
+@@ -565,7 +565,7 @@ static int pci1720_insn_write_ao(struct comedi_device * dev, struct comedi_subde
+ 
+ 	for (n = 0; n < insn->n; n++) {
+ 		outw(data[n], dev->iobase + PCI1720_DA0 + (chan << 1));
+-		outb(0, dev->iobase + PCI1720_SYNCOUT);	// update outputs
++		outb(0, dev->iobase + PCI1720_SYNCOUT);	/*  update outputs */
+ 	}
+ 
+ 	devpriv->ao_data[chan] = data[n];
+@@ -604,7 +604,7 @@ static void interrupt_pci1710_every_sample(void *d)
+ 		return;
+ 	}
+ 
+-	outb(0, dev->iobase + PCI171x_CLRINT);	// clear our INT request
++	outb(0, dev->iobase + PCI171x_CLRINT);	/*  clear our INT request */
+ 
+ 	DPRINTK("FOR ");
+ 	for (; !(inw(dev->iobase + PCI171x_STATUS) & Status_FE);) {
+@@ -639,11 +639,11 @@ static void interrupt_pci1710_every_sample(void *d)
+ 			s->async->cur_chan = 0;
+ 		}
+ 
+-		if (s->async->cur_chan == 0) {	// one scan done
++		if (s->async->cur_chan == 0) {	/*  one scan done */
+ 			devpriv->ai_act_scan++;
+ 			DPRINTK("adv_pci1710 EDBG: EOS1 bic %d bip %d buc %d bup %d\n", s->async->buf_int_count, s->async->buf_int_ptr, s->async->buf_user_count, s->async->buf_user_ptr);
+ 			DPRINTK("adv_pci1710 EDBG: EOS2\n");
+-			if ((!devpriv->neverending_ai) && (devpriv->ai_act_scan >= devpriv->ai_scans)) {	// all data sampled
++			if ((!devpriv->neverending_ai) && (devpriv->ai_act_scan >= devpriv->ai_scans)) {	/*  all data sampled */
+ 				pci171x_ai_cancel(dev, s);
+ 				s->async->events |= COMEDI_CB_EOA;
+ 				comedi_event(dev, s);
+@@ -652,7 +652,7 @@ static void interrupt_pci1710_every_sample(void *d)
+ 		}
+ 	}
+ 
+-	outb(0, dev->iobase + PCI171x_CLRINT);	// clear our INT request
++	outb(0, dev->iobase + PCI171x_CLRINT);	/*  clear our INT request */
+ 	DPRINTK("adv_pci1710 EDBG: END: interrupt_pci1710_every_sample(...)\n");
+ 
+ 	comedi_event(dev, s);
+@@ -753,7 +753,7 @@ static void interrupt_pci1710_half_fifo(void *d)
+ 			comedi_event(dev, s);
+ 			return;
+ 		}
+-	outb(0, dev->iobase + PCI171x_CLRINT);	// clear our INT request
++	outb(0, dev->iobase + PCI171x_CLRINT);	/*  clear our INT request */
+ 	DPRINTK("adv_pci1710 EDBG: END: interrupt_pci1710_half_fifo(...)\n");
+ 
+ 	comedi_event(dev, s);
+@@ -768,30 +768,30 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d)
+ 
+ 	DPRINTK("adv_pci1710 EDBG: BGN: interrupt_service_pci1710(%d,...)\n",
+ 		irq);
+-	if (!dev->attached)	// is device attached?
+-		return IRQ_NONE;	// no, exit
++	if (!dev->attached)	/*  is device attached? */
++		return IRQ_NONE;	/*  no, exit */
+ 
+-	if (!(inw(dev->iobase + PCI171x_STATUS) & Status_IRQ))	// is this interrupt from our board?
+-		return IRQ_NONE;	// no, exit
++	if (!(inw(dev->iobase + PCI171x_STATUS) & Status_IRQ))	/*  is this interrupt from our board? */
++		return IRQ_NONE;	/*  no, exit */
+ 
+ 	DPRINTK("adv_pci1710 EDBG: interrupt_service_pci1710() ST: %4x\n",
+ 		inw(dev->iobase + PCI171x_STATUS));
+ 
+-	if (devpriv->ai_et) {	// Switch from initial TRIG_EXT to TRIG_xxx.
++	if (devpriv->ai_et) {	/*  Switch from initial TRIG_EXT to TRIG_xxx. */
+ 		devpriv->ai_et = 0;
+ 		devpriv->CntrlReg &= Control_CNT0;
+-		devpriv->CntrlReg |= Control_SW;	// set software trigger
++		devpriv->CntrlReg |= Control_SW;	/*  set software trigger */
+ 		outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
+ 		devpriv->CntrlReg = devpriv->ai_et_CntrlReg;
+ 		outb(0, dev->iobase + PCI171x_CLRFIFO);
+ 		outb(0, dev->iobase + PCI171x_CLRINT);
+ 		outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX);
+ 		outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
+-		// start pacer
++		/*  start pacer */
+ 		start_pacer(dev, 1, devpriv->ai_et_div1, devpriv->ai_et_div2);
+ 		return IRQ_HANDLED;
+ 	}
+-	if (devpriv->ai_eos) {	// We use FIFO half full INT or not?
++	if (devpriv->ai_eos) {	/*  We use FIFO half full INT or not? */
+ 		interrupt_pci1710_every_sample(d);
+ 	} else {
+ 		interrupt_pci1710_half_fifo(d);
+@@ -811,7 +811,7 @@ static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device * dev,
+ 
+ 	DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_docmd_and_mode(%d,...)\n",
+ 		mode);
+-	start_pacer(dev, -1, 0, 0);	// stop pacer
++	start_pacer(dev, -1, 0, 0);	/*  stop pacer */
+ 
+ 	seglen = check_channel_list(dev, s, devpriv->ai_chanlist,
+ 		devpriv->ai_n_chan);
+@@ -831,7 +831,7 @@ static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device * dev,
+ 	devpriv->neverending_ai = 0;
+ 
+ 	devpriv->CntrlReg &= Control_CNT0;
+-	if ((devpriv->ai_flags & TRIG_WAKE_EOS)) {	// don't we want wake up every scan?            devpriv->ai_eos=1;
++	if ((devpriv->ai_flags & TRIG_WAKE_EOS)) {	/*  don't we want wake up every scan?            devpriv->ai_eos=1; */
+ 		devpriv->ai_eos = 1;
+ 	} else {
+ 		devpriv->CntrlReg |= Control_ONEFH;
+@@ -840,7 +840,7 @@ static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device * dev,
+ 
+ 	if ((devpriv->ai_scans == 0) || (devpriv->ai_scans == -1)) {
+ 		devpriv->neverending_ai = 1;
+-	}			//well, user want neverending
++	}			/* well, user want neverending */
+ 	else {
+ 		devpriv->neverending_ai = 0;
+ 	}
+@@ -865,7 +865,7 @@ static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device * dev,
+ 		DPRINTK("adv_pci1710 EDBG: OSC base=%u div1=%u div2=%u timer=%u\n", devpriv->i8254_osc_base, divisor1, divisor2, devpriv->ai_timer1);
+ 		outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
+ 		if (mode != 2) {
+-			// start pacer
++			/*  start pacer */
+ 			start_pacer(dev, mode, divisor1, divisor2);
+ 		} else {
+ 			devpriv->ai_et_div1 = divisor1;
+@@ -1057,7 +1057,7 @@ static int pci171x_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevic
+ 	if (cmd->chanlist) {
+ 		if (!check_channel_list(dev, s, cmd->chanlist,
+ 				cmd->chanlist_len))
+-			return 5;	// incorrect channels list
++			return 5;	/*  incorrect channels list */
+ 	}
+ 
+ 	DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) ret=0\n");
+@@ -1086,13 +1086,13 @@ static int pci171x_ai_cmd(struct comedi_device * dev, struct comedi_subdevice *
+ 		devpriv->ai_scans = 0;
+ 	}
+ 
+-	if (cmd->scan_begin_src == TRIG_FOLLOW) {	// mode 1, 2, 3
+-		if (cmd->convert_src == TRIG_TIMER) {	// mode 1 and 2
++	if (cmd->scan_begin_src == TRIG_FOLLOW) {	/*  mode 1, 2, 3 */
++		if (cmd->convert_src == TRIG_TIMER) {	/*  mode 1 and 2 */
+ 			devpriv->ai_timer1 = cmd->convert_arg;
+ 			return pci171x_ai_docmd_and_mode(cmd->start_src ==
+ 				TRIG_EXT ? 2 : 1, dev, s);
+ 		}
+-		if (cmd->convert_src == TRIG_EXT) {	// mode 3
++		if (cmd->convert_src == TRIG_EXT) {	/*  mode 3 */
+ 			return pci171x_ai_docmd_and_mode(3, dev, s);
+ 		}
+ 	}
+@@ -1120,12 +1120,12 @@ static int check_channel_list(struct comedi_device * dev, struct comedi_subdevic
+ 	}
+ 
+ 	if (n_chan > 1) {
+-		chansegment[0] = chanlist[0];	// first channel is everytime ok
+-		for (i = 1, seglen = 1; i < n_chan; i++, seglen++) {	// build part of chanlist
+-			// rt_printk("%d. %d %d\n",i,CR_CHAN(chanlist[i]),CR_RANGE(chanlist[i]));
++		chansegment[0] = chanlist[0];	/*  first channel is everytime ok */
++		for (i = 1, seglen = 1; i < n_chan; i++, seglen++) {	/*  build part of chanlist */
++			/*  rt_printk("%d. %d %d\n",i,CR_CHAN(chanlist[i]),CR_RANGE(chanlist[i])); */
+ 			if (chanlist[0] == chanlist[i])
+-				break;	// we detect loop, this must by finish
+-			if (CR_CHAN(chanlist[i]) & 1)	// odd channel cann't by differencial
++				break;	/*  we detect loop, this must by finish */
++			if (CR_CHAN(chanlist[i]) & 1)	/*  odd channel cann't by differencial */
+ 				if (CR_AREF(chanlist[i]) == AREF_DIFF) {
+ 					comedi_error(dev,
+ 						"Odd channel can't be differential input!\n");
+@@ -1135,18 +1135,18 @@ static int check_channel_list(struct comedi_device * dev, struct comedi_subdevic
+ 				(CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan;
+ 			if (CR_AREF(chansegment[i - 1]) == AREF_DIFF)
+ 				nowmustbechan = (nowmustbechan + 1) % s->n_chan;
+-			if (nowmustbechan != CR_CHAN(chanlist[i])) {	// channel list isn't continous :-(
++			if (nowmustbechan != CR_CHAN(chanlist[i])) {	/*  channel list isn't continous :-( */
+ 				rt_printk
+ 					("channel list must be continous! chanlist[%i]=%d but must be %d or %d!\n",
+ 					i, CR_CHAN(chanlist[i]), nowmustbechan,
+ 					CR_CHAN(chanlist[0]));
+ 				return 0;
+ 			}
+-			chansegment[i] = chanlist[i];	// well, this is next correct channel in list
++			chansegment[i] = chanlist[i];	/*  well, this is next correct channel in list */
+ 		}
+ 
+-		for (i = 0, segpos = 0; i < n_chan; i++) {	// check whole chanlist
+-			//rt_printk("%d %d=%d %d\n",CR_CHAN(chansegment[i%seglen]),CR_RANGE(chansegment[i%seglen]),CR_CHAN(chanlist[i]),CR_RANGE(chanlist[i]));
++		for (i = 0, segpos = 0; i < n_chan; i++) {	/*  check whole chanlist */
++			/* rt_printk("%d %d=%d %d\n",CR_CHAN(chansegment[i%seglen]),CR_RANGE(chansegment[i%seglen]),CR_CHAN(chanlist[i]),CR_RANGE(chanlist[i])); */
+ 			if (chanlist[i] != chansegment[i % seglen]) {
+ 				rt_printk
+ 					("bad channel, reference or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
+@@ -1156,7 +1156,7 @@ static int check_channel_list(struct comedi_device * dev, struct comedi_subdevic
+ 					CR_CHAN(chanlist[i % seglen]),
+ 					CR_RANGE(chanlist[i % seglen]),
+ 					CR_AREF(chansegment[i % seglen]));
+-				return 0;	// chan/gain list is strange
++				return 0;	/*  chan/gain list is strange */
+ 			}
+ 		}
+ 	} else {
+@@ -1176,7 +1176,7 @@ static void setup_channel_list(struct comedi_device * dev, struct comedi_subdevi
+ 	devpriv->act_chanlist_pos = 0;
+ 
+ 	DPRINTK("SegLen: %d\n", seglen);
+-	for (i = 0; i < seglen; i++) {	// store range list to card
++	for (i = 0; i < seglen; i++) {	/*  store range list to card */
+ 		chanprog = muxonechan[CR_CHAN(chanlist[i])];
+ 		outw(chanprog, dev->iobase + PCI171x_MUX);	/* select channel */
+ 		range = this_board->rangecode_ai[CR_RANGE(chanlist[i])];
+@@ -1231,7 +1231,7 @@ static int pci171x_ai_cancel(struct comedi_device * dev, struct comedi_subdevice
+ 		devpriv->CntrlReg &= Control_CNT0;
+ 		devpriv->CntrlReg |= Control_SW;
+ 
+-		outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);	// reset any operations
++		outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);	/*  reset any operations */
+ 		start_pacer(dev, -1, 0, 0);
+ 		outb(0, dev->iobase + PCI171x_CLRFIFO);
+ 		outb(0, dev->iobase + PCI171x_CLRINT);
+@@ -1255,24 +1255,24 @@ static int pci171x_reset(struct comedi_device * dev)
+ {
+ 	DPRINTK("adv_pci1710 EDBG: BGN: pci171x_reset(...)\n");
+ 	outw(0x30, dev->iobase + PCI171x_CNTCTRL);
+-	devpriv->CntrlReg = Control_SW | Control_CNT0;	// Software trigger, CNT0=external
+-	outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);	// reset any operations
+-	outb(0, dev->iobase + PCI171x_CLRFIFO);	// clear FIFO
+-	outb(0, dev->iobase + PCI171x_CLRINT);	// clear INT request
+-	start_pacer(dev, -1, 0, 0);	// stop 8254
++	devpriv->CntrlReg = Control_SW | Control_CNT0;	/*  Software trigger, CNT0=external */
++	outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);	/*  reset any operations */
++	outb(0, dev->iobase + PCI171x_CLRFIFO);	/*  clear FIFO */
++	outb(0, dev->iobase + PCI171x_CLRINT);	/*  clear INT request */
++	start_pacer(dev, -1, 0, 0);	/*  stop 8254 */
+ 	devpriv->da_ranges = 0;
+ 	if (this_board->n_aochan) {
+-		outb(devpriv->da_ranges, dev->iobase + PCI171x_DAREF);	// set DACs to 0..5V
+-		outw(0, dev->iobase + PCI171x_DA1);	// set DA outputs to 0V
++		outb(devpriv->da_ranges, dev->iobase + PCI171x_DAREF);	/*  set DACs to 0..5V */
++		outw(0, dev->iobase + PCI171x_DA1);	/*  set DA outputs to 0V */
+ 		devpriv->ao_data[0] = 0x0000;
+ 		if (this_board->n_aochan > 1) {
+ 			outw(0, dev->iobase + PCI171x_DA2);
+ 			devpriv->ao_data[1] = 0x0000;
+ 		}
+ 	}
+-	outw(0, dev->iobase + PCI171x_DO);	// digital outputs to 0
+-	outb(0, dev->iobase + PCI171x_CLRFIFO);	// clear FIFO
+-	outb(0, dev->iobase + PCI171x_CLRINT);	// clear INT request
++	outw(0, dev->iobase + PCI171x_DO);	/*  digital outputs to 0 */
++	outb(0, dev->iobase + PCI171x_CLRFIFO);	/*  clear FIFO */
++	outb(0, dev->iobase + PCI171x_CLRINT);	/*  clear INT request */
+ 
+ 	DPRINTK("adv_pci1710 EDBG: END: pci171x_reset(...)\n");
+ 	return 0;
+@@ -1284,14 +1284,14 @@ static int pci171x_reset(struct comedi_device * dev)
+ static int pci1720_reset(struct comedi_device * dev)
+ {
+ 	DPRINTK("adv_pci1710 EDBG: BGN: pci1720_reset(...)\n");
+-	outb(Syncont_SC0, dev->iobase + PCI1720_SYNCONT);	// set synchronous output mode
++	outb(Syncont_SC0, dev->iobase + PCI1720_SYNCONT);	/*  set synchronous output mode */
+ 	devpriv->da_ranges = 0xAA;
+-	outb(devpriv->da_ranges, dev->iobase + PCI1720_RANGE);	// set all ranges to +/-5V
+-	outw(0x0800, dev->iobase + PCI1720_DA0);	// set outputs to 0V
++	outb(devpriv->da_ranges, dev->iobase + PCI1720_RANGE);	/*  set all ranges to +/-5V */
++	outw(0x0800, dev->iobase + PCI1720_DA0);	/*  set outputs to 0V */
+ 	outw(0x0800, dev->iobase + PCI1720_DA1);
+ 	outw(0x0800, dev->iobase + PCI1720_DA2);
+ 	outw(0x0800, dev->iobase + PCI1720_DA3);
+-	outb(0, dev->iobase + PCI1720_SYNCOUT);	// update outputs
++	outb(0, dev->iobase + PCI1720_SYNCOUT);	/*  update outputs */
+ 	devpriv->ao_data[0] = 0x0800;
+ 	devpriv->ao_data[1] = 0x0800;
+ 	devpriv->ao_data[2] = 0x0800;
+@@ -1378,7 +1378,7 @@ static int pci1710_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 			errstr = "failed to enable PCI device and request regions!";
+ 			continue;
+ 		}
+-		// fixup board_ptr in case we were using the dummy entry with the driver name
++		/*  fixup board_ptr in case we were using the dummy entry with the driver name */
+ 		dev->board_ptr = &boardtypes[board_index];
+ 		break;
+ 	}
+@@ -1469,7 +1469,7 @@ static int pci1710_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 			s->do_cmdtest = pci171x_ai_cmdtest;
+ 			s->do_cmd = pci171x_ai_cmd;
+ 		}
+-		devpriv->i8254_osc_base = 100;	// 100ns=10MHz
++		devpriv->i8254_osc_base = 100;	/*  100ns=10MHz */
+ 		subdev++;
+ 	}
+ 
+diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c
+index b97b4d82611b..b21c23b8ba52 100644
+--- a/drivers/staging/comedi/drivers/aio_aio12_8.c
++++ b/drivers/staging/comedi/drivers/aio_aio12_8.c
+@@ -96,16 +96,16 @@ static int aio_aio12_8_ai_read(struct comedi_device * dev, struct comedi_subdevi
+ 		ADC_MODE_NORMAL |
+ 		(CR_RANGE(insn->chanspec) << 3) | CR_CHAN(insn->chanspec);
+ 
+-	//read status to clear EOC latch
++	/* read status to clear EOC latch */
+ 	inb(dev->iobase + AIO12_8_STATUS);
+ 
+ 	for (n = 0; n < insn->n; n++) {
+ 		int timeout = 5;
+ 
+-		// Setup and start conversion
++		/*  Setup and start conversion */
+ 		outb(control, dev->iobase + AIO12_8_ADC);
+ 
+-		// Wait for conversion to complete
++		/*  Wait for conversion to complete */
+ 		while (timeout &&
+ 			!(inb(dev->iobase + AIO12_8_STATUS) & STATUS_ADC_EOC)) {
+ 			timeout--;
+@@ -140,12 +140,12 @@ static int aio_aio12_8_ao_write(struct comedi_device * dev, struct comedi_subdev
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	unsigned long port = dev->iobase + AIO12_8_DAC_0 + (2 * chan);
+ 
+-	//enable DACs
++	/* enable DACs */
+ 	outb(0x01, dev->iobase + DAC_ENABLE);
+ 
+ 	for (i = 0; i < insn->n; i++) {
+-		outb(data[i] & 0xFF, port);	// LSB
+-		outb((data[i] >> 8) & 0x0F, port + 1);	// MSB
++		outb(data[i] & 0xFF, port);	/*  LSB */
++		outb((data[i] >> 8) & 0x0F, port + 1);	/*  MSB */
+ 		devpriv->ao_readback[chan] = data[i];
+ 	}
+ 	return insn->n;
+diff --git a/drivers/staging/comedi/drivers/amcc_s5933.h b/drivers/staging/comedi/drivers/amcc_s5933.h
+index aceffce7ef3f..b810d5f3d971 100644
+--- a/drivers/staging/comedi/drivers/amcc_s5933.h
++++ b/drivers/staging/comedi/drivers/amcc_s5933.h
+@@ -48,12 +48,12 @@
+ /****************************************************************************/
+ #define INTCSR_OUTBOX_BYTE(x)	((x) & 0x3)
+ #define INTCSR_OUTBOX_SELECT(x)	(((x) & 0x3) << 2)
+-#define INTCSR_OUTBOX_EMPTY_INT	0x10	// enable outbox empty interrupt
++#define INTCSR_OUTBOX_EMPTY_INT	0x10	/*  enable outbox empty interrupt */
+ #define INTCSR_INBOX_BYTE(x)	(((x) & 0x3) << 8)
+ #define INTCSR_INBOX_SELECT(x)	(((x) & 0x3) << 10)
+-#define INTCSR_INBOX_FULL_INT	0x1000	// enable inbox full interrupt
+-#define INTCSR_INBOX_INTR_STATUS	0x20000	// read, or write clear inbox full interrupt
+-#define INTCSR_INTR_ASSERTED	0x800000	// read only, interrupt asserted
++#define INTCSR_INBOX_FULL_INT	0x1000	/*  enable inbox full interrupt */
++#define INTCSR_INBOX_INTR_STATUS	0x20000	/*  read, or write clear inbox full interrupt */
++#define INTCSR_INTR_ASSERTED	0x800000	/*  read only, interrupt asserted */
+ 
+ /****************************************************************************/
+ /* AMCC - PCI non-volatile ram command register (byte 3 of master control/status register) */
+@@ -153,7 +153,7 @@
+ #define AINT_IMB_SELECT 	0x0000000c
+ #define AINT_IMB_BYTE		0x00000003
+ 
+-// these are bits from various different registers, needs cleanup XXX
++/* these are bits from various different registers, needs cleanup XXX */
+ /* Enable Bus Mastering */
+ #define EN_A2P_TRANSFERS	0x00000400
+ /* FIFO Flag Reset */
+diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
+index aebb9fe1eaa7..0dd9630cfdfd 100644
+--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
++++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
+@@ -278,7 +278,7 @@ static int das16cs_detach(struct comedi_device * dev)
+ 
+ static irqreturn_t das16cs_interrupt(int irq, void *d)
+ {
+-	//struct comedi_device *dev = d;
++	/* struct comedi_device *dev = d; */
+ 	return IRQ_HANDLED;
+ }
+ 
+@@ -973,4 +973,4 @@ void __exit cleanup_module(void)
+ 
+ #else
+ COMEDI_INITCLEANUP(driver_das16cs);
+-#endif //CONFIG_PCMCIA
++#endif /* CONFIG_PCMCIA */
+diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
+index ed0a5eb3dd91..581ff7a81cea 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidda.c
++++ b/drivers/staging/comedi/drivers/cb_pcidda.c
+@@ -51,66 +51,66 @@ Please report success/failure with other different cards to
+ #include "comedi_pci.h"
+ #include "8255.h"
+ 
+-#define PCI_VENDOR_ID_CB	0x1307	// PCI vendor number of ComputerBoards
+-#define N_BOARDS	10	// Number of boards in cb_pcidda_boards
+-#define EEPROM_SIZE	128	// number of entries in eeprom
+-#define MAX_AO_CHANNELS 8	// maximum number of ao channels for supported boards
++#define PCI_VENDOR_ID_CB	0x1307	/*  PCI vendor number of ComputerBoards */
++#define N_BOARDS	10	/*  Number of boards in cb_pcidda_boards */
++#define EEPROM_SIZE	128	/*  number of entries in eeprom */
++#define MAX_AO_CHANNELS 8	/*  maximum number of ao channels for supported boards */
+ 
+ /* PCI-DDA base addresses */
+ #define DIGITALIO_BADRINDEX	2
+-	// DIGITAL I/O is pci_dev->resource[2]
++	/*  DIGITAL I/O is pci_dev->resource[2] */
+ #define DIGITALIO_SIZE 8
+-	// DIGITAL I/O uses 8 I/O port addresses
++	/*  DIGITAL I/O uses 8 I/O port addresses */
+ #define DAC_BADRINDEX	3
+-	// DAC is pci_dev->resource[3]
++	/*  DAC is pci_dev->resource[3] */
+ 
+ /* Digital I/O registers */
+-#define PORT1A 0		// PORT 1A DATA
++#define PORT1A 0		/*  PORT 1A DATA */
+ 
+-#define PORT1B 1		// PORT 1B DATA
++#define PORT1B 1		/*  PORT 1B DATA */
+ 
+-#define PORT1C 2		// PORT 1C DATA
++#define PORT1C 2		/*  PORT 1C DATA */
+ 
+-#define CONTROL1 3		// CONTROL REGISTER 1
++#define CONTROL1 3		/*  CONTROL REGISTER 1 */
+ 
+-#define PORT2A 4		// PORT 2A DATA
++#define PORT2A 4		/*  PORT 2A DATA */
+ 
+-#define PORT2B 5		// PORT 2B DATA
++#define PORT2B 5		/*  PORT 2B DATA */
+ 
+-#define PORT2C 6		// PORT 2C DATA
++#define PORT2C 6		/*  PORT 2C DATA */
+ 
+-#define CONTROL2 7		// CONTROL REGISTER 2
++#define CONTROL2 7		/*  CONTROL REGISTER 2 */
+ 
+ /* DAC registers */
+-#define DACONTROL	0	// D/A CONTROL REGISTER
+-#define	SU	0000001		// Simultaneous update enabled
+-#define NOSU	0000000		// Simultaneous update disabled
+-#define	ENABLEDAC	0000002	// Enable specified DAC
+-#define	DISABLEDAC	0000000	// Disable specified DAC
+-#define RANGE2V5	0000000	// 2.5V
+-#define RANGE5V	0000200		// 5V
+-#define RANGE10V	0000300	// 10V
+-#define UNIP	0000400		// Unipolar outputs
+-#define BIP	0000000		// Bipolar outputs
+-
+-#define DACALIBRATION1	4	// D/A CALIBRATION REGISTER 1
+-//write bits
+-#define	SERIAL_IN_BIT	0x1	// serial data input for eeprom, caldacs, reference dac
++#define DACONTROL	0	/*  D/A CONTROL REGISTER */
++#define	SU	0000001		/*  Simultaneous update enabled */
++#define NOSU	0000000		/*  Simultaneous update disabled */
++#define	ENABLEDAC	0000002	/*  Enable specified DAC */
++#define	DISABLEDAC	0000000	/*  Disable specified DAC */
++#define RANGE2V5	0000000	/*  2.5V */
++#define RANGE5V	0000200		/*  5V */
++#define RANGE10V	0000300	/*  10V */
++#define UNIP	0000400		/*  Unipolar outputs */
++#define BIP	0000000		/*  Bipolar outputs */
++
++#define DACALIBRATION1	4	/*  D/A CALIBRATION REGISTER 1 */
++/* write bits */
++#define	SERIAL_IN_BIT	0x1	/*  serial data input for eeprom, caldacs, reference dac */
+ #define	CAL_CHANNEL_MASK	(0x7 << 1)
+ #define	CAL_CHANNEL_BITS(channel)	(((channel) << 1) & CAL_CHANNEL_MASK)
+-//read bits
++/* read bits */
+ #define	CAL_COUNTER_MASK	0x1f
+-#define	CAL_COUNTER_OVERFLOW_BIT	0x20	// calibration counter overflow status bit
+-#define	AO_BELOW_REF_BIT	0x40	// analog output is less than reference dac voltage
+-#define	SERIAL_OUT_BIT	0x80	// serial data out, for reading from eeprom
++#define	CAL_COUNTER_OVERFLOW_BIT	0x20	/*  calibration counter overflow status bit */
++#define	AO_BELOW_REF_BIT	0x40	/*  analog output is less than reference dac voltage */
++#define	SERIAL_OUT_BIT	0x80	/*  serial data out, for reading from eeprom */
+ 
+-#define DACALIBRATION2	6	// D/A CALIBRATION REGISTER 2
+-#define	SELECT_EEPROM_BIT	0x1	// send serial data in to eeprom
+-#define	DESELECT_REF_DAC_BIT	0x2	// don't send serial data to MAX542 reference dac
+-#define	DESELECT_CALDAC_BIT(n)	(0x4 << (n))	// don't send serial data to caldac n
+-#define	DUMMY_BIT	0x40	// manual says to set this bit with no explanation
++#define DACALIBRATION2	6	/*  D/A CALIBRATION REGISTER 2 */
++#define	SELECT_EEPROM_BIT	0x1	/*  send serial data in to eeprom */
++#define	DESELECT_REF_DAC_BIT	0x2	/*  don't send serial data to MAX542 reference dac */
++#define	DESELECT_CALDAC_BIT(n)	(0x4 << (n))	/*  don't send serial data to caldac n */
++#define	DUMMY_BIT	0x40	/*  manual says to set this bit with no explanation */
+ 
+-#define DADATA	8		// FIRST D/A DATA REGISTER (0)
++#define DADATA	8		/*  FIRST D/A DATA REGISTER (0) */
+ 
+ static const struct comedi_lrange cb_pcidda_ranges = {
+ 	6,
+@@ -131,15 +131,20 @@ static const struct comedi_lrange cb_pcidda_ranges = {
+  */
+ struct cb_pcidda_board {
+ 	const char *name;
+-	char status;		// Driver status:
+-	// 0 - tested
+-	// 1 - manual read, not tested
+-	// 2 - manual not read
++	char status;		/*  Driver status: */
++
++	/*
++	 * 0 - tested
++	 * 1 - manual read, not tested
++	 * 2 - manual not read
++	 */
++
+ 	unsigned short device_id;
+ 	int ao_chans;
+ 	int ao_bits;
+ 	const struct comedi_lrange *ranges;
+ };
++
+ static const struct cb_pcidda_board cb_pcidda_boards[] = {
+ 	{
+ 	      name:	"pci-dda02/12",
+@@ -219,11 +224,13 @@ struct cb_pcidda_private {
+ 
+ 	unsigned long digitalio;
+ 	unsigned long dac;
+-	//unsigned long control_status;
+-	//unsigned long adc_fifo;
+-	unsigned int dac_cal1_bits;	// bits last written to da calibration register 1
+-	unsigned int ao_range[MAX_AO_CHANNELS];	// current range settings for output channels
+-	u16 eeprom_data[EEPROM_SIZE];	// software copy of board's eeprom
++
++	/* unsigned long control_status; */
++	/* unsigned long adc_fifo; */
++
++	unsigned int dac_cal1_bits;	/*  bits last written to da calibration register 1 */
++	unsigned int ao_range[MAX_AO_CHANNELS];	/*  current range settings for output channels */
++	u16 eeprom_data[EEPROM_SIZE];	/*  software copy of board's eeprom */
+ };
+ 
+ /*
+@@ -234,12 +241,14 @@ struct cb_pcidda_private {
+ 
+ static int cb_pcidda_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int cb_pcidda_detach(struct comedi_device * dev);
+-//static int cb_pcidda_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data);
++/* static int cb_pcidda_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data); */
+ static int cb_pcidda_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data);
+-//static int cb_pcidda_ai_cmd(struct comedi_device *dev,struct comedi_subdevice *s);
+-//static int cb_pcidda_ai_cmdtest(struct comedi_device *dev,struct comedi_subdevice *s, struct comedi_cmd *cmd);
+-//static int cb_pcidda_ns_to_timer(unsigned int *ns,int round);
++
++/* static int cb_pcidda_ai_cmd(struct comedi_device *dev, struct *comedi_subdevice *s);*/
++/* static int cb_pcidda_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd); */
++/* static int cb_pcidda_ns_to_timer(unsigned int *ns,int *round); */
++
+ static unsigned int cb_pcidda_serial_in(struct comedi_device * dev);
+ static void cb_pcidda_serial_out(struct comedi_device * dev, unsigned int value,
+ 	unsigned int num_bits);
+@@ -310,7 +319,7 @@ static int cb_pcidda_attach(struct comedi_device * dev, struct comedi_devconfig
+       found:
+ 	devpriv->pci_dev = pcidev;
+ 	dev->board_ptr = cb_pcidda_boards + index;
+-	// "thisboard" macro can be used from here.
++	/*  "thisboard" macro can be used from here. */
+ 	printk("Found %s at requested position\n", thisboard->name);
+ 
+ 	/*
+@@ -353,11 +362,12 @@ static int cb_pcidda_attach(struct comedi_device * dev, struct comedi_devconfig
+ 	s->maxdata = (1 << thisboard->ao_bits) - 1;
+ 	s->range_table = thisboard->ranges;
+ 	s->insn_write = cb_pcidda_ao_winsn;
+-//      s->subdev_flags |= SDF_CMD_READ;
+-//      s->do_cmd = cb_pcidda_ai_cmd;
+-//      s->do_cmdtest = cb_pcidda_ai_cmdtest;
+ 
+-	// two 8255 digital io subdevices
++	/* s->subdev_flags |= SDF_CMD_READ; */
++	/* s->do_cmd = cb_pcidda_ai_cmd; */
++	/* s->do_cmdtest = cb_pcidda_ai_cmdtest; */
++
++	/*  two 8255 digital io subdevices */
+ 	s = dev->subdevices + 1;
+ 	subdev_8255_init(dev, s, NULL, devpriv->digitalio);
+ 	s = dev->subdevices + 2;
+@@ -370,7 +380,7 @@ static int cb_pcidda_attach(struct comedi_device * dev, struct comedi_devconfig
+ 	}
+ 	printk("\n");
+ 
+-	// set calibrations dacs
++	/*  set calibrations dacs */
+ 	for (index = 0; index < thisboard->ao_chans; index++)
+ 		cb_pcidda_calibrate(dev, index, devpriv->ao_range[index]);
+ 
+@@ -398,7 +408,7 @@ static int cb_pcidda_detach(struct comedi_device * dev)
+ 			pci_dev_put(devpriv->pci_dev);
+ 		}
+ 	}
+-	// cleanup 8255
++	/*  cleanup 8255 */
+ 	if (dev->subdevices) {
+ 		subdev_8255_cleanup(dev, dev->subdevices + 1);
+ 		subdev_8255_cleanup(dev, dev->subdevices + 2);
+@@ -607,7 +617,7 @@ static int cb_pcidda_ao_winsn(struct comedi_device * dev, struct comedi_subdevic
+ 	channel = CR_CHAN(insn->chanspec);
+ 	range = CR_RANGE(insn->chanspec);
+ 
+-	// adjust calibration dacs if range has changed
++	/*  adjust calibration dacs if range has changed */
+ 	if (range != devpriv->ao_range[channel])
+ 		cb_pcidda_calibrate(dev, channel, range);
+ 
+@@ -647,15 +657,15 @@ static int cb_pcidda_ao_winsn(struct comedi_device * dev, struct comedi_subdevic
+ 	return 1;
+ }
+ 
+-// lowlevel read from eeprom
++/* lowlevel read from eeprom */
+ static unsigned int cb_pcidda_serial_in(struct comedi_device * dev)
+ {
+ 	unsigned int value = 0;
+ 	int i;
+-	const int value_width = 16;	// number of bits wide values are
++	const int value_width = 16;	/*  number of bits wide values are */
+ 
+ 	for (i = 1; i <= value_width; i++) {
+-		// read bits most significant bit first
++		/*  read bits most significant bit first */
+ 		if (inw_p(devpriv->dac + DACALIBRATION1) & SERIAL_OUT_BIT) {
+ 			value |= 1 << (value_width - i);
+ 		}
+@@ -664,14 +674,14 @@ static unsigned int cb_pcidda_serial_in(struct comedi_device * dev)
+ 	return value;
+ }
+ 
+-// lowlevel write to eeprom/dac
++/* lowlevel write to eeprom/dac */
+ static void cb_pcidda_serial_out(struct comedi_device * dev, unsigned int value,
+ 	unsigned int num_bits)
+ {
+ 	int i;
+ 
+ 	for (i = 1; i <= num_bits; i++) {
+-		// send bits most significant bit first
++		/*  send bits most significant bit first */
+ 		if (value & (1 << (num_bits - i)))
+ 			devpriv->dac_cal1_bits |= SERIAL_IN_BIT;
+ 		else
+@@ -680,136 +690,137 @@ static void cb_pcidda_serial_out(struct comedi_device * dev, unsigned int value,
+ 	}
+ }
+ 
+-// reads a 16 bit value from board's eeprom
++/* reads a 16 bit value from board's eeprom */
+ static unsigned int cb_pcidda_read_eeprom(struct comedi_device * dev,
+ 	unsigned int address)
+ {
+ 	unsigned int i;
+ 	unsigned int cal2_bits;
+ 	unsigned int value;
+-	const int max_num_caldacs = 4;	// one caldac for every two dac channels
+-	const int read_instruction = 0x6;	// bits to send to tell eeprom we want to read
++	const int max_num_caldacs = 4;	/*  one caldac for every two dac channels */
++	const int read_instruction = 0x6;	/*  bits to send to tell eeprom we want to read */
+ 	const int instruction_length = 3;
+ 	const int address_length = 8;
+ 
+-	// send serial output stream to eeprom
++	/*  send serial output stream to eeprom */
+ 	cal2_bits = SELECT_EEPROM_BIT | DESELECT_REF_DAC_BIT | DUMMY_BIT;
+-	// deactivate caldacs (one caldac for every two channels)
++	/*  deactivate caldacs (one caldac for every two channels) */
+ 	for (i = 0; i < max_num_caldacs; i++) {
+ 		cal2_bits |= DESELECT_CALDAC_BIT(i);
+ 	}
+ 	outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
+ 
+-	// tell eeprom we want to read
++	/*  tell eeprom we want to read */
+ 	cb_pcidda_serial_out(dev, read_instruction, instruction_length);
+-	// send address we want to read from
++	/*  send address we want to read from */
+ 	cb_pcidda_serial_out(dev, address, address_length);
+ 
+ 	value = cb_pcidda_serial_in(dev);
+ 
+-	// deactivate eeprom
++	/*  deactivate eeprom */
+ 	cal2_bits &= ~SELECT_EEPROM_BIT;
+ 	outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
+ 
+ 	return value;
+ }
+ 
+-// writes to 8 bit calibration dacs
++/* writes to 8 bit calibration dacs */
+ static void cb_pcidda_write_caldac(struct comedi_device * dev, unsigned int caldac,
+ 	unsigned int channel, unsigned int value)
+ {
+ 	unsigned int cal2_bits;
+ 	unsigned int i;
+-	const int num_channel_bits = 3;	// caldacs use 3 bit channel specification
+-	const int num_caldac_bits = 8;	// 8 bit calibration dacs
+-	const int max_num_caldacs = 4;	// one caldac for every two dac channels
++	const int num_channel_bits = 3;	/*  caldacs use 3 bit channel specification */
++	const int num_caldac_bits = 8;	/*  8 bit calibration dacs */
++	const int max_num_caldacs = 4;	/*  one caldac for every two dac channels */
+ 
+ 	/* write 3 bit channel */
+ 	cb_pcidda_serial_out(dev, channel, num_channel_bits);
+-	// write 8 bit caldac value
++	/*  write 8 bit caldac value */
+ 	cb_pcidda_serial_out(dev, value, num_caldac_bits);
+ 
+-	// latch stream into appropriate caldac
+-	// deselect reference dac
++/*
++* latch stream into appropriate caldac deselect reference dac
++*/
+ 	cal2_bits = DESELECT_REF_DAC_BIT | DUMMY_BIT;
+-	// deactivate caldacs (one caldac for every two channels)
++	/*  deactivate caldacs (one caldac for every two channels) */
+ 	for (i = 0; i < max_num_caldacs; i++) {
+ 		cal2_bits |= DESELECT_CALDAC_BIT(i);
+ 	}
+-	// activate the caldac we want
++	/*  activate the caldac we want */
+ 	cal2_bits &= ~DESELECT_CALDAC_BIT(caldac);
+ 	outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
+-	// deactivate caldac
++	/*  deactivate caldac */
+ 	cal2_bits |= DESELECT_CALDAC_BIT(caldac);
+ 	outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
+ }
+ 
+-// returns caldac that calibrates given analog out channel
++/* returns caldac that calibrates given analog out channel */
+ static unsigned int caldac_number(unsigned int channel)
+ {
+ 	return channel / 2;
+ }
+ 
+-// returns caldac channel that provides fine gain for given ao channel
++/* returns caldac channel that provides fine gain for given ao channel */
+ static unsigned int fine_gain_channel(unsigned int ao_channel)
+ {
+ 	return 4 * (ao_channel % 2);
+ }
+ 
+-// returns caldac channel that provides coarse gain for given ao channel
++/* returns caldac channel that provides coarse gain for given ao channel */
+ static unsigned int coarse_gain_channel(unsigned int ao_channel)
+ {
+ 	return 1 + 4 * (ao_channel % 2);
+ }
+ 
+-// returns caldac channel that provides coarse offset for given ao channel
++/* returns caldac channel that provides coarse offset for given ao channel */
+ static unsigned int coarse_offset_channel(unsigned int ao_channel)
+ {
+ 	return 2 + 4 * (ao_channel % 2);
+ }
+ 
+-// returns caldac channel that provides fine offset for given ao channel
++/* returns caldac channel that provides fine offset for given ao channel */
+ static unsigned int fine_offset_channel(unsigned int ao_channel)
+ {
+ 	return 3 + 4 * (ao_channel % 2);
+ }
+ 
+-// returns eeprom address that provides offset for given ao channel and range
++/* returns eeprom address that provides offset for given ao channel and range */
+ static unsigned int offset_eeprom_address(unsigned int ao_channel,
+ 	unsigned int range)
+ {
+ 	return 0x7 + 2 * range + 12 * ao_channel;
+ }
+ 
+-// returns eeprom address that provides gain calibration for given ao channel and range
++/* returns eeprom address that provides gain calibration for given ao channel and range */
+ static unsigned int gain_eeprom_address(unsigned int ao_channel,
+ 	unsigned int range)
+ {
+ 	return 0x8 + 2 * range + 12 * ao_channel;
+ }
+ 
+-// returns upper byte of eeprom entry, which gives the coarse adjustment values
++/* returns upper byte of eeprom entry, which gives the coarse adjustment values */
+ static unsigned int eeprom_coarse_byte(unsigned int word)
+ {
+ 	return (word >> 8) & 0xff;
+ }
+ 
+-// returns lower byte of eeprom entry, which gives the fine adjustment values
++/* returns lower byte of eeprom entry, which gives the fine adjustment values */
+ static unsigned int eeprom_fine_byte(unsigned int word)
+ {
+ 	return word & 0xff;
+ }
+ 
+-// set caldacs to eeprom values for given channel and range
++/* set caldacs to eeprom values for given channel and range */
+ static void cb_pcidda_calibrate(struct comedi_device * dev, unsigned int channel,
+ 	unsigned int range)
+ {
+ 	unsigned int coarse_offset, fine_offset, coarse_gain, fine_gain;
+ 
+-	// remember range so we can tell when we need to readjust calibration
++	/*  remember range so we can tell when we need to readjust calibration */
+ 	devpriv->ao_range[channel] = range;
+ 
+-	// get values from eeprom data
++	/*  get values from eeprom data */
+ 	coarse_offset =
+ 		eeprom_coarse_byte(devpriv->
+ 		eeprom_data[offset_eeprom_address(channel, range)]);
+@@ -823,7 +834,7 @@ static void cb_pcidda_calibrate(struct comedi_device * dev, unsigned int channel
+ 		eeprom_fine_byte(devpriv->
+ 		eeprom_data[gain_eeprom_address(channel, range)]);
+ 
+-	// set caldacs
++	/*  set caldacs */
+ 	cb_pcidda_write_caldac(dev, caldac_number(channel),
+ 		coarse_offset_channel(channel), coarse_offset);
+ 	cb_pcidda_write_caldac(dev, caldac_number(channel),
+diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c
+index 71a4b1482e36..eeda0b3dc5b1 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidio.c
++++ b/drivers/staging/comedi/drivers/cb_pcidio.c
+@@ -53,10 +53,10 @@ Passing a zero for an option is the same as leaving it unspecified.
+  * Some drivers use arrays such as this, other do not.
+  */
+ struct pcidio_board {
+-	const char *name;	// anme of the board
+-	int n_8255;		// number of 8255 chips on board
++	const char *name;	/*  anme of the board */
++	int n_8255;		/*  number of 8255 chips on board */
+ 
+-	// indices of base address regions
++	/*  indices of base address regions */
+ 	int pcicontroler_badrindex;
+ 	int dioregs_badrindex;
+ };
+@@ -104,7 +104,7 @@ MODULE_DEVICE_TABLE(pci, pcidio_pci_table);
+    several hardware drivers keep similar information in this structure,
+    feel free to suggest moving the variable to the struct comedi_device struct.  */
+ struct pcidio_private {
+-	int data;		// curently unused
++	int data;		/*  curently unused */
+ 
+ 	/* would be useful for a PCI device */
+ 	struct pci_dev *pci_dev;
+@@ -112,7 +112,7 @@ struct pcidio_private {
+ 	/* used for DO readback, curently unused */
+ 	unsigned int do_readback[4];	/* up to 4 unsigned int suffice to hold 96 bits for PCI-DIO96 */
+ 
+-	unsigned long dio_reg_base;	// address of port A of the first 8255 chip on board
++	unsigned long dio_reg_base;	/*  address of port A of the first 8255 chip on board */
+ };
+ 
+ /*
+@@ -134,8 +134,10 @@ static struct comedi_driver driver_cb_pcidio = {
+       module:THIS_MODULE,
+       attach:pcidio_attach,
+       detach:pcidio_detach,
++
+ /* It is not necessary to implement the following members if you are
+  * writing a driver for a ISA PnP or PCI card */
++
+ 	/* Most drivers will support multiple types of boards by
+ 	 * having an array of board structures.  These were defined
+ 	 * in pcidio_boards[] above.  Note that the element 'name'
+@@ -152,10 +154,15 @@ static struct comedi_driver driver_cb_pcidio = {
+ 	 * the type of board in software.  ISA PnP, PCI, and PCMCIA
+ 	 * devices are such boards.
+ 	 */
+-// The following fields should NOT be initialized if you are dealing with PCI devices
+-//      board_name:     pcidio_boards,
+-//      offset:         sizeof(struct pcidio_board),
+-//      num_names:      sizeof(pcidio_boards) / sizeof(struct pcidio_board),
++
++/* The following fields should NOT be initialized if you are dealing
++ * with PCI devices
++ *
++ *         board_name:	pcidio_boards,
++ *         offset:	sizeof(struct pcidio_board),
++ *         num_names: 	sizeof(pcidio_boards) / sizeof(structpcidio_board),
++ */
++
+ };
+ 
+ /*------------------------------- FUNCTIONS -----------------------------------*/
+@@ -192,19 +199,19 @@ static int pcidio_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
+ 		pcidev != NULL;
+ 		pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
+-		// is it not a computer boards card?
++		/*  is it not a computer boards card? */
+ 		if (pcidev->vendor != PCI_VENDOR_ID_CB)
+ 			continue;
+-		// loop through cards supported by this driver
++		/*  loop through cards supported by this driver */
+ 		for (index = 0;
+ 			index < sizeof pcidio_boards / sizeof(struct pcidio_board);
+ 			index++) {
+ 			if (pcidio_pci_table[index].device != pcidev->device)
+ 				continue;
+ 
+-			// was a particular bus/slot requested?
++			/*  was a particular bus/slot requested? */
+ 			if (it->options[0] || it->options[1]) {
+-				// are we on the wrong bus/slot?
++				/*  are we on the wrong bus/slot? */
+ 				if (pcidev->bus->number != it->options[0] ||
+ 					PCI_SLOT(pcidev->devfn) !=
+ 					it->options[1]) {
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
+index e4c5b460fbd5..4e6002c8dfb6 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
+@@ -434,16 +434,16 @@ static int probe(struct comedi_device * dev, const struct comedi_devconfig * it)
+ 	for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
+ 		pcidev != NULL;
+ 		pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
+-		// is it not a computer boards card?
++		/*  is it not a computer boards card? */
+ 		if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS)
+ 			continue;
+-		// loop through cards supported by this driver
++		/*  loop through cards supported by this driver */
+ 		for (index = 0; index < N_BOARDS; index++) {
+ 			if (boards[index].device_id != pcidev->device)
+ 				continue;
+-			// was a particular bus/slot requested?
++			/*  was a particular bus/slot requested? */
+ 			if (it->options[0] || it->options[1]) {
+-				// are we on the wrong bus/slot?
++				/*  are we on the wrong bus/slot? */
+ 				if (pcidev->bus->number != it->options[0] ||
+ 					PCI_SLOT(pcidev->devfn) !=
+ 					it->options[1]) {
+diff --git a/drivers/staging/comedi/drivers/comedi_rt_timer.c b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+index f40c8cffd4bb..8dbd0fde1f86 100644
+--- a/drivers/staging/comedi/drivers/comedi_rt_timer.c
++++ b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+@@ -73,9 +73,9 @@ Configuration options:
+ #define RTLINUX_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+ #endif
+ 
+-// begin hack to workaround broken HRT_TO_8254() function on rtlinux
++/* begin hack to workaround broken HRT_TO_8254() function on rtlinux */
+ #if RTLINUX_VERSION_CODE <= RTLINUX_VERSION(3,0,100)
+-// this function sole purpose is to divide a long long by 838
++/* this function sole purpose is to divide a long long by 838 */
+ static inline RTIME nano2count(long long ns)
+ {
+ 	do_div(ns, 838);
+@@ -91,9 +91,9 @@ static inline RTIME nano2count(long long ns)
+ 
+ #define nano2count(x) HRT_TO_8254(x)
+ #endif
+-// end hack
++/* end hack */
+ 
+-// rtl-rtai compatibility
++/* rtl-rtai compatibility */
+ #define rt_task_wait_period() rt_task_wait()
+ #define rt_pend_linux_srq(irq) rtl_global_pend_irq(irq)
+ #define rt_free_srq(irq) rtl_free_soft_irq(irq)
+@@ -133,31 +133,33 @@ static struct comedi_driver driver_timer = {
+       driver_name:"comedi_rt_timer",
+       attach:timer_attach,
+       detach:timer_detach,
+-//      open:           timer_open,
++/* open:           timer_open, */
+ };
+ 
+ COMEDI_INITCLEANUP(driver_timer);
+ 
+ struct timer_private {
+-	comedi_t *device;	// device we are emulating commands for
+-	int subd;		// subdevice we are emulating commands for
+-	RT_TASK *rt_task;	// rt task that starts scans
+-	RT_TASK *scan_task;	// rt task that controls conversion timing in a scan
++	comedi_t *device;	/*  device we are emulating commands for */
++	int subd;		/*  subdevice we are emulating commands for */
++	RT_TASK *rt_task;	/*  rt task that starts scans */
++	RT_TASK *scan_task;	/*  rt task that controls conversion timing in a scan */
+ 	/* io_function can point to either an input or output function
+ 	 * depending on what kind of subdevice we are emulating for */
+ 	int (*io_function) (struct comedi_device * dev, struct comedi_cmd * cmd,
+ 		unsigned int index);
+-	// RTIME has units of 1 = 838 nanoseconds
+-	// time at which first scan started, used to check scan timing
++/*
++* RTIME has units of 1 = 838 nanoseconds time at which first scan
++* started, used to check scan timing
++*/
+ 	RTIME start;
+-	// time between scans
++	/*  time between scans */
+ 	RTIME scan_period;
+-	// time between conversions in a scan
++	/*  time between conversions in a scan */
+ 	RTIME convert_period;
+-	// flags
+-	volatile int stop;	// indicates we should stop
+-	volatile int rt_task_active;	// indicates rt_task is servicing a struct comedi_cmd
+-	volatile int scan_task_active;	// indicates scan_task is servicing a struct comedi_cmd
++	/*  flags */
++	volatile int stop;	/*  indicates we should stop */
++	volatile int rt_task_active;	/*  indicates rt_task is servicing a struct comedi_cmd */
++	volatile int scan_task_active;	/*  indicates scan_task is servicing a struct comedi_cmd */
+ 	unsigned timer_running:1;
+ };
+ #define devpriv ((struct timer_private *)dev->private)
+@@ -169,7 +171,7 @@ static int timer_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-// checks for scan timing error
++/* checks for scan timing error */
+ inline static int check_scan_timing(struct comedi_device * dev,
+ 	unsigned long long scan)
+ {
+@@ -186,7 +188,7 @@ inline static int check_scan_timing(struct comedi_device * dev,
+ 	return 0;
+ }
+ 
+-// checks for conversion timing error
++/* checks for conversion timing error */
+ inline static int check_conversion_timing(struct comedi_device * dev,
+ 	RTIME scan_start, unsigned int conversion)
+ {
+@@ -205,7 +207,7 @@ inline static int check_conversion_timing(struct comedi_device * dev,
+ 	return 0;
+ }
+ 
+-// devpriv->io_function for an input subdevice
++/* devpriv->io_function for an input subdevice */
+ static int timer_data_read(struct comedi_device * dev, struct comedi_cmd * cmd,
+ 	unsigned int index)
+ {
+@@ -230,7 +232,7 @@ static int timer_data_read(struct comedi_device * dev, struct comedi_cmd * cmd,
+ 	return 0;
+ }
+ 
+-// devpriv->io_function for an output subdevice
++/* devpriv->io_function for an output subdevice */
+ static int timer_data_write(struct comedi_device * dev, struct comedi_cmd * cmd,
+ 	unsigned int index)
+ {
+@@ -265,7 +267,7 @@ static int timer_data_write(struct comedi_device * dev, struct comedi_cmd * cmd,
+ 	return 0;
+ }
+ 
+-// devpriv->io_function for DIO subdevices
++/* devpriv->io_function for DIO subdevices */
+ static int timer_dio_read(struct comedi_device * dev, struct comedi_cmd * cmd,
+ 	unsigned int index)
+ {
+@@ -287,7 +289,7 @@ static int timer_dio_read(struct comedi_device * dev, struct comedi_cmd * cmd,
+ 	return 0;
+ }
+ 
+-// performs scans
++/* performs scans */
+ static void scan_task_func(comedi_rt_task_context_t d)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+@@ -298,14 +300,14 @@ static void scan_task_func(comedi_rt_task_context_t d)
+ 	unsigned long long n;
+ 	RTIME scan_start;
+ 
+-	// every struct comedi_cmd causes one execution of while loop
++	/*  every struct comedi_cmd causes one execution of while loop */
+ 	while (1) {
+ 		devpriv->scan_task_active = 1;
+-		// each for loop completes one scan
++		/*  each for loop completes one scan */
+ 		for (n = 0; n < cmd->stop_arg || cmd->stop_src == TRIG_NONE;
+ 			n++) {
+ 			if (n) {
+-				// suspend task until next scan
++				/*  suspend task until next scan */
+ 				ret = rt_task_suspend(devpriv->scan_task);
+ 				if (ret < 0) {
+ 					comedi_error(dev,
+@@ -314,7 +316,7 @@ static void scan_task_func(comedi_rt_task_context_t d)
+ 					goto cleanup;
+ 				}
+ 			}
+-			// check if stop flag was set (by timer_cancel())
++			/*  check if stop flag was set (by timer_cancel()) */
+ 			if (devpriv->stop)
+ 				goto cleanup;
+ 			ret = check_scan_timing(dev, n);
+@@ -324,7 +326,7 @@ static void scan_task_func(comedi_rt_task_context_t d)
+ 			}
+ 			scan_start = rt_get_time();
+ 			for (i = 0; i < cmd->scan_end_arg; i++) {
+-				// conversion timing
++				/*  conversion timing */
+ 				if (cmd->convert_src == TRIG_TIMER && i) {
+ 					rt_task_wait_period();
+ 					ret = check_conversion_timing(dev,
+@@ -353,7 +355,7 @@ static void scan_task_func(comedi_rt_task_context_t d)
+ 		comedi_event(dev, s);
+ 		async->events = 0;
+ 		devpriv->scan_task_active = 0;
+-		// suspend task until next struct comedi_cmd
++		/*  suspend task until next struct comedi_cmd */
+ 		rt_task_suspend(devpriv->scan_task);
+ 	}
+ }
+@@ -366,7 +368,7 @@ static void timer_task_func(comedi_rt_task_context_t d)
+ 	int ret;
+ 	unsigned long long n;
+ 
+-	// every struct comedi_cmd causes one execution of while loop
++	/*  every struct comedi_cmd causes one execution of while loop */
+ 	while (1) {
+ 		devpriv->rt_task_active = 1;
+ 		devpriv->scan_task_active = 1;
+@@ -374,7 +376,7 @@ static void timer_task_func(comedi_rt_task_context_t d)
+ 
+ 		for (n = 0; n < cmd->stop_arg || cmd->stop_src == TRIG_NONE;
+ 			n++) {
+-			// scan timing
++			/*  scan timing */
+ 			if (n)
+ 				rt_task_wait_period();
+ 			if (devpriv->scan_task_active == 0) {
+@@ -391,7 +393,7 @@ static void timer_task_func(comedi_rt_task_context_t d)
+ 	      cleanup:
+ 
+ 		devpriv->rt_task_active = 0;
+-		// suspend until next struct comedi_cmd
++		/*  suspend until next struct comedi_cmd */
+ 		rt_task_suspend(devpriv->rt_task);
+ 	}
+ }
+@@ -485,7 +487,7 @@ static int timer_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s
+ 		return 2;
+ 
+ 	/* step 3: make sure arguments are trivially compatible */
+-	// limit frequency, this is fairly arbitrary
++	/*  limit frequency, this is fairly arbitrary */
+ 	if (cmd->scan_begin_src == TRIG_TIMER) {
+ 		if (cmd->scan_begin_arg < SPEED_LIMIT) {
+ 			cmd->scan_begin_arg = SPEED_LIMIT;
+@@ -498,7 +500,7 @@ static int timer_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s
+ 			err++;
+ 		}
+ 	}
+-	// make sure conversion and scan frequencies are compatible
++	/*  make sure conversion and scan frequencies are compatible */
+ 	if (cmd->convert_src == TRIG_TIMER && cmd->scan_begin_src == TRIG_TIMER) {
+ 		if (cmd->convert_arg * cmd->scan_end_arg > cmd->scan_begin_arg) {
+ 			cmd->scan_begin_arg =
+@@ -524,7 +526,7 @@ static int timer_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	/* hack attack: drivers are not supposed to do this: */
+ 	dev->rt = 1;
+ 
+-	// make sure tasks have finished cleanup of last struct comedi_cmd
++	/*  make sure tasks have finished cleanup of last struct comedi_cmd */
+ 	if (devpriv->rt_task_active || devpriv->scan_task_active)
+ 		return -EBUSY;
+ 
+@@ -636,7 +638,7 @@ static int timer_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 	emul_dev = devpriv->device;
+ 	emul_s = emul_dev->subdevices + devpriv->subd;
+ 
+-	// input or output subdevice
++	/*  input or output subdevice */
+ 	s = dev->subdevices + 0;
+ 	s->type = emul_s->type;
+ 	s->subdev_flags = emul_s->subdev_flags;	/* SDF_GROUND (to fool check_driver) */
+@@ -681,7 +683,7 @@ static int timer_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 
+ 	devpriv->rt_task = kzalloc(sizeof(RT_TASK), GFP_KERNEL);
+ 
+-	// initialize real-time tasks
++	/*  initialize real-time tasks */
+ 	ret = rt_task_init(devpriv->rt_task, timer_task_func,
+ 		(comedi_rt_task_context_t) dev, 3000, timer_priority, 0, 0);
+ 	if (ret < 0) {
+@@ -705,7 +707,7 @@ static int timer_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 	return 1;
+ }
+ 
+-// free allocated resources
++/* free allocated resources */
+ static int timer_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: timer: remove\n", dev->minor);
+diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
+index 3b8444f09f28..4afc88cb7173 100644
+--- a/drivers/staging/comedi/drivers/daqboard2000.c
++++ b/drivers/staging/comedi/drivers/daqboard2000.c
+@@ -129,7 +129,7 @@ Configuration options:
+ #define DAQBOARD2000_DAQ_SIZE 		0x1002
+ #define DAQBOARD2000_PLX_SIZE 		0x100
+ 
+-// Initialization bits for the Serial EEPROM Control Register
++/* Initialization bits for the Serial EEPROM Control Register */
+ #define DAQBOARD2000_SECRProgPinHi      0x8001767e
+ #define DAQBOARD2000_SECRProgPinLo      0x8000767e
+ #define DAQBOARD2000_SECRLocalBusHi     0xc000767e
+@@ -137,14 +137,14 @@ Configuration options:
+ #define DAQBOARD2000_SECRReloadHi       0xa000767e
+ #define DAQBOARD2000_SECRReloadLo       0x8000767e
+ 
+-// SECR status bits
++/* SECR status bits */
+ #define DAQBOARD2000_EEPROM_PRESENT     0x10000000
+ 
+-// CPLD status bits
++/* CPLD status bits */
+ #define DAQBOARD2000_CPLD_INIT 		0x0002
+ #define DAQBOARD2000_CPLD_DONE 		0x0004
+ 
+-// Available ranges
++/* Available ranges */
+ static const struct comedi_lrange range_daqboard2000_ai = { 13, {
+ 			RANGE(-10, 10),
+ 			RANGE(-5, 5),
+@@ -168,65 +168,65 @@ static const struct comedi_lrange range_daqboard2000_ao = { 1, {
+ };
+ 
+ struct daqboard2000_hw {
+-	volatile u16 acqControl;	// 0x00
+-	volatile u16 acqScanListFIFO;	// 0x02
+-	volatile u32 acqPacerClockDivLow;	// 0x04
+-
+-	volatile u16 acqScanCounter;	// 0x08
+-	volatile u16 acqPacerClockDivHigh;	// 0x0a
+-	volatile u16 acqTriggerCount;	// 0x0c
+-	volatile u16 fill2;	// 0x0e
+-	volatile u16 acqResultsFIFO;	// 0x10
+-	volatile u16 fill3;	// 0x12
+-	volatile u16 acqResultsShadow;	// 0x14
+-	volatile u16 fill4;	// 0x16
+-	volatile u16 acqAdcResult;	// 0x18
+-	volatile u16 fill5;	// 0x1a
+-	volatile u16 dacScanCounter;	// 0x1c
+-	volatile u16 fill6;	// 0x1e
+-
+-	volatile u16 dacControl;	// 0x20
+-	volatile u16 fill7;	// 0x22
+-	volatile s16 dacFIFO;	// 0x24
+-	volatile u16 fill8[2];	// 0x26
+-	volatile u16 dacPacerClockDiv;	// 0x2a
+-	volatile u16 refDacs;	// 0x2c
+-	volatile u16 fill9;	// 0x2e
+-
+-	volatile u16 dioControl;	// 0x30
+-	volatile s16 dioP3hsioData;	// 0x32
+-	volatile u16 dioP3Control;	// 0x34
+-	volatile u16 calEepromControl;	// 0x36
+-	volatile s16 dacSetting[4];	// 0x38
+-	volatile s16 dioP2ExpansionIO8Bit[32];	// 0x40
+-
+-	volatile u16 ctrTmrControl;	// 0x80
+-	volatile u16 fill10[3];	// 0x82
+-	volatile s16 ctrInput[4];	// 0x88
+-	volatile u16 fill11[8];	// 0x90
+-	volatile u16 timerDivisor[2];	// 0xa0
+-	volatile u16 fill12[6];	// 0xa4
+-
+-	volatile u16 dmaControl;	// 0xb0
+-	volatile u16 trigControl;	// 0xb2
+-	volatile u16 fill13[2];	// 0xb4
+-	volatile u16 calEeprom;	// 0xb8
+-	volatile u16 acqDigitalMark;	// 0xba
+-	volatile u16 trigDacs;	// 0xbc
+-	volatile u16 fill14;	// 0xbe
+-	volatile s16 dioP2ExpansionIO16Bit[32];	// 0xc0
++	volatile u16 acqControl;	/*  0x00 */
++	volatile u16 acqScanListFIFO;	/*  0x02 */
++	volatile u32 acqPacerClockDivLow;	/*  0x04 */
++
++	volatile u16 acqScanCounter;	/*  0x08 */
++	volatile u16 acqPacerClockDivHigh;	/*  0x0a */
++	volatile u16 acqTriggerCount;	/*  0x0c */
++	volatile u16 fill2;	/*  0x0e */
++	volatile u16 acqResultsFIFO;	/*  0x10 */
++	volatile u16 fill3;	/*  0x12 */
++	volatile u16 acqResultsShadow;	/*  0x14 */
++	volatile u16 fill4;	/*  0x16 */
++	volatile u16 acqAdcResult;	/*  0x18 */
++	volatile u16 fill5;	/*  0x1a */
++	volatile u16 dacScanCounter;	/*  0x1c */
++	volatile u16 fill6;	/*  0x1e */
++
++	volatile u16 dacControl;	/*  0x20 */
++	volatile u16 fill7;	/*  0x22 */
++	volatile s16 dacFIFO;	/*  0x24 */
++	volatile u16 fill8[2];	/*  0x26 */
++	volatile u16 dacPacerClockDiv;	/*  0x2a */
++	volatile u16 refDacs;	/*  0x2c */
++	volatile u16 fill9;	/*  0x2e */
++
++	volatile u16 dioControl;	/*  0x30 */
++	volatile s16 dioP3hsioData;	/*  0x32 */
++	volatile u16 dioP3Control;	/*  0x34 */
++	volatile u16 calEepromControl;	/*  0x36 */
++	volatile s16 dacSetting[4];	/*  0x38 */
++	volatile s16 dioP2ExpansionIO8Bit[32];	/*  0x40 */
++
++	volatile u16 ctrTmrControl;	/*  0x80 */
++	volatile u16 fill10[3];	/*  0x82 */
++	volatile s16 ctrInput[4];	/*  0x88 */
++	volatile u16 fill11[8];	/*  0x90 */
++	volatile u16 timerDivisor[2];	/*  0xa0 */
++	volatile u16 fill12[6];	/*  0xa4 */
++
++	volatile u16 dmaControl;	/*  0xb0 */
++	volatile u16 trigControl;	/*  0xb2 */
++	volatile u16 fill13[2];	/*  0xb4 */
++	volatile u16 calEeprom;	/*  0xb8 */
++	volatile u16 acqDigitalMark;	/*  0xba */
++	volatile u16 trigDacs;	/*  0xbc */
++	volatile u16 fill14;	/*  0xbe */
++	volatile s16 dioP2ExpansionIO16Bit[32];	/*  0xc0 */
+ };
+ 
+ /* Scan Sequencer programming */
+ #define DAQBOARD2000_SeqStartScanList            0x0011
+ #define DAQBOARD2000_SeqStopScanList             0x0010
+ 
+-// Prepare for acquisition
++/* Prepare for acquisition */
+ #define DAQBOARD2000_AcqResetScanListFifo        0x0004
+ #define DAQBOARD2000_AcqResetResultsFifo         0x0002
+ #define DAQBOARD2000_AcqResetConfigPipe          0x0001
+ 
+-// Acqusition status bits
++/* Acqusition status bits */
+ #define DAQBOARD2000_AcqResultsFIFOMore1Sample   0x0001
+ #define DAQBOARD2000_AcqResultsFIFOHasValidData  0x0002
+ #define DAQBOARD2000_AcqResultsFIFOOverrun       0x0004
+@@ -239,7 +239,7 @@ struct daqboard2000_hw {
+ #define DAQBOARD2000_DacPacerOverrun             0x0200
+ #define DAQBOARD2000_AcqHardwareError            0x01c0
+ 
+-// Scan Sequencer programming
++/* Scan Sequencer programming */
+ #define DAQBOARD2000_SeqStartScanList            0x0011
+ #define DAQBOARD2000_SeqStopScanList             0x0010
+ 
+@@ -254,7 +254,7 @@ struct daqboard2000_hw {
+ #define DAQBOARD2000_AdcPacerInternalOutEnable   0x0008
+ #define DAQBOARD2000_AdcPacerExternalRising      0x0100
+ 
+-// DAC status
++/* DAC status */
+ #define DAQBOARD2000_DacFull                     0x0001
+ #define DAQBOARD2000_RefBusy                     0x0002
+ #define DAQBOARD2000_TrgBusy                     0x0004
+@@ -264,7 +264,7 @@ struct daqboard2000_hw {
+ #define DAQBOARD2000_Dac2Busy                    0x0040
+ #define DAQBOARD2000_Dac3Busy                    0x0080
+ 
+-// DAC control
++/* DAC control */
+ #define DAQBOARD2000_Dac0Enable                  0x0021
+ #define DAQBOARD2000_Dac1Enable                  0x0031
+ #define DAQBOARD2000_Dac2Enable                  0x0041
+@@ -292,7 +292,7 @@ struct daqboard2000_hw {
+ #define DAQBOARD2000_TrigEnable                  0x0001
+ #define DAQBOARD2000_TrigDisable                 0x0000
+ 
+-// Reference Dac Selection
++/* Reference Dac Selection */
+ #define DAQBOARD2000_PosRefDacSelect             0x0100
+ #define DAQBOARD2000_NegRefDacSelect             0x0000
+ 
+@@ -342,9 +342,9 @@ static void writeAcqScanListEntry(struct comedi_device * dev, u16 entry)
+ {
+ 	struct daqboard2000_hw *fpga = devpriv->daq;
+ 
+-//  comedi_udelay(4);
++/* comedi_udelay(4); */
+ 	fpga->acqScanListFIFO = entry & 0x00ff;
+-//  comedi_udelay(4);
++/* comedi_udelay(4); */
+ 	fpga->acqScanListFIFO = (entry >> 8) & 0x00ff;
+ }
+ 
+@@ -425,14 +425,14 @@ static int daqboard2000_ai_insn_read(struct comedi_device * dev, struct comedi_s
+ 			if (fpga->acqControl & DAQBOARD2000_AcqConfigPipeFull) {
+ 				break;
+ 			}
+-			//comedi_udelay(2);
++			/* comedi_udelay(2); */
+ 		}
+ 		fpga->acqControl = DAQBOARD2000_AdcPacerEnable;
+ 		for (timeout = 0; timeout < 20; timeout++) {
+ 			if (fpga->acqControl & DAQBOARD2000_AcqLogicScanning) {
+ 				break;
+ 			}
+-			//comedi_udelay(2);
++			/* comedi_udelay(2); */
+ 		}
+ 		for (timeout = 0; timeout < 20; timeout++) {
+ 			if (fpga->
+@@ -440,7 +440,7 @@ static int daqboard2000_ai_insn_read(struct comedi_device * dev, struct comedi_s
+ 				DAQBOARD2000_AcqResultsFIFOHasValidData) {
+ 				break;
+ 			}
+-			//comedi_udelay(2);
++			/* comedi_udelay(2); */
+ 		}
+ 		data[i] = fpga->acqResultsFIFO;
+ 		fpga->acqControl = DAQBOARD2000_AdcPacerDisable;
+@@ -476,13 +476,13 @@ static int daqboard2000_ao_insn_write(struct comedi_device * dev, struct comedi_
+ 		 * OK, since it works OK without enabling the DAC's, let's keep
+ 		 * it as simple as possible...
+ 		 */
+-		//fpga->dacControl = (chan + 2) * 0x0010 | 0x0001; comedi_udelay(1000);
++		/* fpga->dacControl = (chan + 2) * 0x0010 | 0x0001; comedi_udelay(1000); */
+ 		fpga->dacSetting[chan] = data[i];
+ 		for (timeout = 0; timeout < 20; timeout++) {
+ 			if ((fpga->dacControl & ((chan + 1) * 0x0010)) == 0) {
+ 				break;
+ 			}
+-			//comedi_udelay(2);
++			/* comedi_udelay(2); */
+ 		}
+ 		devpriv->ao_readback[chan] = data[i];
+ 		/*
+@@ -645,7 +645,7 @@ static void daqboard2000_activateReferenceDacs(struct comedi_device * dev)
+ 	struct daqboard2000_hw *fpga = devpriv->daq;
+ 	int timeout;
+ 
+-	// Set the + reference dac value in the FPGA
++	/*  Set the + reference dac value in the FPGA */
+ 	fpga->refDacs = 0x80 | DAQBOARD2000_PosRefDacSelect;
+ 	for (timeout = 0; timeout < 20; timeout++) {
+ 		if ((fpga->dacControl & DAQBOARD2000_RefBusy) == 0) {
+@@ -655,7 +655,7 @@ static void daqboard2000_activateReferenceDacs(struct comedi_device * dev)
+ 	}
+ /*  printk("DAQBOARD2000_PosRefDacSelect %d\n", timeout);*/
+ 
+-	// Set the - reference dac value in the FPGA
++	/*  Set the - reference dac value in the FPGA */
+ 	fpga->refDacs = 0x80 | DAQBOARD2000_NegRefDacSelect;
+ 	for (timeout = 0; timeout < 20; timeout++) {
+ 		if ((fpga->dacControl & DAQBOARD2000_RefBusy) == 0) {
+diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
+index e4563331e963..a2e261c96ba5 100644
+--- a/drivers/staging/comedi/drivers/das08.c
++++ b/drivers/staging/comedi/drivers/das08.c
+@@ -65,12 +65,12 @@ driver.
+ #define PCI_DEVICE_ID_PCIDAS08 0x29
+ #define PCIDAS08_SIZE 0x54
+ 
+-// pci configuration registers
++/* pci configuration registers */
+ #define INTCSR               0x4c
+ #define   INTR1_ENABLE         0x1
+ #define   INTR1_HIGH_POLARITY  0x2
+ #define   PCI_INTR_ENABLE      0x40
+-#define   INTR1_EDGE_TRIG      0x100	// requires high polarity
++#define   INTR1_EDGE_TRIG      0x100	/*  requires high polarity */
+ #define CNTRL                0x50
+ #define   CNTRL_DIR            0x2
+ #define   CNTRL_INTR           0x4
+@@ -248,7 +248,7 @@ static const int *const das08_gainlists[] = {
+ 
+ static const struct das08_board_struct das08_boards[] = {
+ 	{
+-	      name:	"isa-das08",	// cio-das08.pdf
++	      name:	"isa-das08",	/*  cio-das08.pdf */
+ 	      bustype:	isa,
+ 	      ai:	das08_ai_rinsn,
+ 	      ai_nbits:12,
+@@ -261,10 +261,10 @@ static const struct das08_board_struct das08_boards[] = {
+ 	      do_nchan:4,
+ 	      i8255_offset:8,
+ 	      i8254_offset:4,
+-	      iosize:	16,	// unchecked
++	      iosize:	16,	/*  unchecked */
+ 		},
+ 	{
+-	      name:	"das08-pgm",	// cio-das08pgx.pdf
++	      name:	"das08-pgm",	/*  cio-das08pgx.pdf */
+ 	      bustype:	isa,
+ 	      ai:	das08_ai_rinsn,
+ 	      ai_nbits:12,
+@@ -276,10 +276,10 @@ static const struct das08_board_struct das08_boards[] = {
+ 	      do_nchan:4,
+ 	      i8255_offset:0,
+ 	      i8254_offset:0x04,
+-	      iosize:	16,	// unchecked
++	      iosize:	16,	/*  unchecked */
+ 		},
+ 	{
+-	      name:	"das08-pgh",	// cio-das08pgx.pdf
++	      name:	"das08-pgh",	/*  cio-das08pgx.pdf */
+ 	      bustype:	isa,
+ 	      ai:	das08_ai_rinsn,
+ 	      ai_nbits:12,
+@@ -291,10 +291,10 @@ static const struct das08_board_struct das08_boards[] = {
+ 	      do_nchan:4,
+ 	      i8255_offset:0,
+ 	      i8254_offset:0x04,
+-	      iosize:	16,	// unchecked
++	      iosize:	16,	/*  unchecked */
+ 		},
+ 	{
+-	      name:	"das08-pgl",	// cio-das08pgx.pdf
++	      name:	"das08-pgl",	/*  cio-das08pgx.pdf */
+ 	      bustype:	isa,
+ 	      ai:	das08_ai_rinsn,
+ 	      ai_nbits:12,
+@@ -306,58 +306,58 @@ static const struct das08_board_struct das08_boards[] = {
+ 	      do_nchan:4,
+ 	      i8255_offset:0,
+ 	      i8254_offset:0x04,
+-	      iosize:	16,	// unchecked
++	      iosize:	16,	/*  unchecked */
+ 		},
+ 	{
+-	      name:	"das08-aoh",	// cio-das08_aox.pdf
++	      name:	"das08-aoh",	/*  cio-das08_aox.pdf */
+ 	      bustype:	isa,
+ 	      ai:	das08_ai_rinsn,
+ 	      ai_nbits:12,
+ 	      ai_pg:	das08_pgh,
+ 	      ai_encoding:das08_encode12,
+-	      ao:	das08ao_ao_winsn,	// 8
++	      ao:	das08ao_ao_winsn,	/*  8 */
+ 	      ao_nbits:12,
+ 	      di:	das08_di_rbits,
+ 	      do_:	das08_do_wbits,
+ 	      do_nchan:4,
+ 	      i8255_offset:0x0c,
+ 	      i8254_offset:0x04,
+-	      iosize:	16,	// unchecked
++	      iosize:	16,	/*  unchecked */
+ 		},
+ 	{
+-	      name:	"das08-aol",	// cio-das08_aox.pdf
++	      name:	"das08-aol",	/*  cio-das08_aox.pdf */
+ 	      bustype:	isa,
+ 	      ai:	das08_ai_rinsn,
+ 	      ai_nbits:12,
+ 	      ai_pg:	das08_pgl,
+ 	      ai_encoding:das08_encode12,
+-	      ao:	das08ao_ao_winsn,	// 8
++	      ao:	das08ao_ao_winsn,	/*  8 */
+ 	      ao_nbits:12,
+ 	      di:	das08_di_rbits,
+ 	      do_:	das08_do_wbits,
+ 	      do_nchan:4,
+ 	      i8255_offset:0x0c,
+ 	      i8254_offset:0x04,
+-	      iosize:	16,	// unchecked
++	      iosize:	16,	/*  unchecked */
+ 		},
+ 	{
+-	      name:	"das08-aom",	// cio-das08_aox.pdf
++	      name:	"das08-aom",	/*  cio-das08_aox.pdf */
+ 	      bustype:	isa,
+ 	      ai:	das08_ai_rinsn,
+ 	      ai_nbits:12,
+ 	      ai_pg:	das08_pgm,
+ 	      ai_encoding:das08_encode12,
+-	      ao:	das08ao_ao_winsn,	// 8
++	      ao:	das08ao_ao_winsn,	/*  8 */
+ 	      ao_nbits:12,
+ 	      di:	das08_di_rbits,
+ 	      do_:	das08_do_wbits,
+ 	      do_nchan:4,
+ 	      i8255_offset:0x0c,
+ 	      i8254_offset:0x04,
+-	      iosize:	16,	// unchecked
++	      iosize:	16,	/*  unchecked */
+ 		},
+ 	{
+-	      name:	"das08/jr-ao",	// cio-das08-jr-ao.pdf
++	      name:	"das08/jr-ao",	/*  cio-das08-jr-ao.pdf */
+ 	      bustype:	isa,
+ 	      ai:	das08_ai_rinsn,
+ 	      ai_nbits:12,
+@@ -370,10 +370,10 @@ static const struct das08_board_struct das08_boards[] = {
+ 	      do_nchan:8,
+ 	      i8255_offset:0,
+ 	      i8254_offset:0,
+-	      iosize:	16,	// unchecked
++	      iosize:	16,	/*  unchecked */
+ 		},
+ 	{
+-	      name:	"das08jr-16-ao",	// cio-das08jr-16-ao.pdf
++	      name:	"das08jr-16-ao",	/*  cio-das08jr-16-ao.pdf */
+ 	      bustype:	isa,
+ 	      ai:	das08_ai_rinsn,
+ 	      ai_nbits:16,
+@@ -386,11 +386,11 @@ static const struct das08_board_struct das08_boards[] = {
+ 	      do_nchan:8,
+ 	      i8255_offset:0,
+ 	      i8254_offset:0x04,
+-	      iosize:	16,	// unchecked
++	      iosize:	16,	/*  unchecked */
+ 		},
+ #ifdef CONFIG_COMEDI_PCI
+ 	{
+-	      name:	"das08",	// pci-das08
++	      name:	"das08",	/*  pci-das08 */
+ 	      id:	PCI_DEVICE_ID_PCIDAS08,
+ 	      bustype:	pci,
+ 	      ai:	das08_ai_rinsn,
+@@ -421,7 +421,7 @@ static const struct das08_board_struct das08_boards[] = {
+ 	      do_nchan:4,
+ 	      i8255_offset:0,
+ 	      i8254_offset:4,
+-	      iosize:	16,	// unchecked
++	      iosize:	16,	/*  unchecked */
+ 		},
+ #if 0
+ 	{
+@@ -445,14 +445,14 @@ static const struct das08_board_struct das08_boards[] = {
+ 	      do_nchan:8,
+ 	      i8255_offset:0,
+ 	      i8254_offset:0,
+-	      iosize:	16,	// unchecked
++	      iosize:	16,	/*  unchecked */
+ 		},
+ #if 0
+ 	{
+-	      name:	"das48-pga",	// cio-das48-pga.pdf
++	      name:	"das48-pga",	/*  cio-das48-pga.pdf */
+ 		},
+ 	{
+-	      name:	"das08-pga-g2",	// a KM board
++	      name:	"das08-pga-g2",	/*  a KM board */
+ 		},
+ #endif
+ };
+@@ -461,7 +461,7 @@ static const struct das08_board_struct das08_boards[] = {
+ struct das08_board_struct das08_cs_boards[NUM_DAS08_CS_BOARDS] = {
+ 	{
+ 	      name:	"pcm-das08",
+-	      id:	0x0,	// XXX
++	      id:	0x0,	/*  XXX */
+ 	      bustype:	pcmcia,
+ 	      ai:	das08_ai_rinsn,
+ 	      ai_nbits:12,
+@@ -476,10 +476,10 @@ struct das08_board_struct das08_cs_boards[NUM_DAS08_CS_BOARDS] = {
+ 	      i8254_offset:0,
+ 	      iosize:	16,
+ 		},
+-	// duplicate so driver name can be used also
++	/*  duplicate so driver name can be used also */
+ 	{
+ 	      name:	"das08_cs",
+-	      id:	0x0,	// XXX
++	      id:	0x0,	/*  XXX */
+ 	      bustype:	pcmcia,
+ 	      ai:	das08_ai_rinsn,
+ 	      ai_nbits:12,
+@@ -528,7 +528,7 @@ static int das08_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ 	inb(dev->iobase + DAS08_MSB);
+ 
+ 	/* set multiplexer */
+-	spin_lock(&dev->spinlock);	// lock to prevent race with digital output
++	spin_lock(&dev->spinlock);	/*  lock to prevent race with digital output */
+ 	devpriv->do_mux_bits &= ~DAS08_MUX_MASK;
+ 	devpriv->do_mux_bits |= DAS08_MUX(chan);
+ 	outb(devpriv->do_mux_bits, dev->iobase + DAS08_CONTROL);
+@@ -593,14 +593,14 @@ static int das08_do_wbits(struct comedi_device * dev, struct comedi_subdevice *
+ {
+ 	int wbits;
+ 
+-	// get current settings of digital output lines
++	/*  get current settings of digital output lines */
+ 	wbits = (devpriv->do_mux_bits >> 4) & 0xf;
+-	// null bits we are going to set
++	/*  null bits we are going to set */
+ 	wbits &= ~data[0];
+-	// set new bit values
++	/*  set new bit values */
+ 	wbits |= data[0] & data[1];
+-	// remember digital output bits
+-	spin_lock(&dev->spinlock);	// prevent race with setting of analog input mux
++	/*  remember digital output bits */
++	spin_lock(&dev->spinlock);	/*  prevent race with setting of analog input mux */
+ 	devpriv->do_mux_bits &= ~DAS08_DO_MASK;
+ 	devpriv->do_mux_bits |= DAS08_OP(wbits);
+ 	outb(devpriv->do_mux_bits, dev->iobase + DAS08_CONTROL);
+@@ -623,9 +623,9 @@ static int das08jr_di_rbits(struct comedi_device * dev, struct comedi_subdevice
+ static int das08jr_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	// null bits we are going to set
++	/*  null bits we are going to set */
+ 	devpriv->do_bits &= ~data[0];
+-	// set new bit values
++	/*  set new bit values */
+ 	devpriv->do_bits |= data[0] & data[1];
+ 	outb(devpriv->do_bits, dev->iobase + DAS08JR_DIO);
+ 
+@@ -787,9 +787,9 @@ static int das08_counter_read(struct comedi_device * dev, struct comedi_subdevic
+ {
+ 	int chan = insn->chanspec;
+ 
+-	//printk("Reading counter channel %d ",chan);
++	/* printk("Reading counter channel %d ",chan); */
+ 	data[0] = i8254_read_channel(&devpriv->i8254, chan);
+-	//printk("=> 0x%08X\n",data[0]);
++	/* printk("=> 0x%08X\n",data[0]); */
+ 
+ 	return 1;
+ }
+@@ -799,7 +799,7 @@ static int das08_counter_write(struct comedi_device * dev, struct comedi_subdevi
+ {
+ 	int chan = insn->chanspec;
+ 
+-	//printk("Writing counter channel %d with 0x%04X\n",chan,data[0]);
++	/* printk("Writing counter channel %d with 0x%04X\n",chan,data[0]); */
+ 	i8254_write_channel(&devpriv->i8254, chan, data[0]);
+ 
+ 	return 1;
+@@ -845,7 +845,7 @@ int das08_common_attach(struct comedi_device * dev, unsigned long iobase)
+ 	struct comedi_subdevice *s;
+ 	int ret;
+ 
+-	// allocate ioports for non-pcmcia, non-pci boards
++	/*  allocate ioports for non-pcmcia, non-pci boards */
+ 	if ((thisboard->bustype != pcmcia) && (thisboard->bustype != pci)) {
+ 		printk(" iobase 0x%lx\n", iobase);
+ 		if (!request_region(iobase, thisboard->iosize, DRV_NAME)) {
+@@ -880,7 +880,7 @@ int das08_common_attach(struct comedi_device * dev, unsigned long iobase)
+ 	/* ao */
+ 	if (thisboard->ao) {
+ 		s->type = COMEDI_SUBD_AO;
+-// XXX lacks read-back insn
++/* XXX lacks read-back insn */
+ 		s->subdev_flags = SDF_WRITABLE;
+ 		s->n_chan = 2;
+ 		s->maxdata = (1 << thisboard->ao_nbits) - 1;
+@@ -965,7 +965,7 @@ static int das08_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 		return ret;
+ 
+ 	printk("comedi%d: das08: ", dev->minor);
+-	// deal with a pci board
++	/*  deal with a pci board */
+ 	if (thisboard->bustype == pci) {
+ #ifdef CONFIG_COMEDI_PCI
+ 		if (it->options[0] || it->options[1]) {
+@@ -973,7 +973,7 @@ static int das08_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 				it->options[0], it->options[1]);
+ 		}
+ 		printk("\n");
+-		// find card
++		/*  find card */
+ 		for (pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
+ 			pdev != NULL;
+ 			pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) {
+@@ -995,12 +995,12 @@ static int das08_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 			return -EIO;
+ 		}
+ 		devpriv->pdev = pdev;
+-		// enable PCI device and reserve I/O spaces
++		/*  enable PCI device and reserve I/O spaces */
+ 		if (comedi_pci_enable(pdev, DRV_NAME)) {
+ 			printk(" Error enabling PCI device and requesting regions\n");
+ 			return -EIO;
+ 		}
+-		// read base addresses
++		/*  read base addresses */
+ 		pci_iobase = pci_resource_start(pdev, 1);
+ 		iobase = pci_resource_start(pdev, 2);
+ 		printk("pcibase 0x%lx  iobase 0x%lx\n", pci_iobase, iobase);
+@@ -1035,7 +1035,7 @@ int das08_common_detach(struct comedi_device * dev)
+ 	if (dev->subdevices)
+ 		subdev_8255_cleanup(dev, dev->subdevices + 4);
+ 
+-	// deallocate ioports for non-pcmcia, non-pci boards
++	/*  deallocate ioports for non-pcmcia, non-pci boards */
+ 	if ((thisboard->bustype != pcmcia) && (thisboard->bustype != pci)) {
+ 		if (dev->iobase)
+ 			release_region(dev->iobase, thisboard->iosize);
+diff --git a/drivers/staging/comedi/drivers/das08.h b/drivers/staging/comedi/drivers/das08.h
+index 69089ce690f2..b870e88ab834 100644
+--- a/drivers/staging/comedi/drivers/das08.h
++++ b/drivers/staging/comedi/drivers/das08.h
+@@ -25,14 +25,14 @@
+ #define _DAS08_H
+ 
+ enum das08_bustype { isa, pci, pcmcia, pc104 };
+-// different ways ai data is encoded in first two registers
++/* different ways ai data is encoded in first two registers */
+ enum das08_ai_encoding { das08_encode12, das08_encode16, das08_pcm_encode12 };
+ enum das08_lrange { das08_pg_none, das08_bipolar5, das08_pgh, das08_pgl,
+ 		das08_pgm };
+ 
+ struct das08_board_struct {
+ 	const char *name;
+-	unsigned int id;	// id for pci/pcmcia boards
++	unsigned int id;	/*  id for pci/pcmcia boards */
+ 	enum das08_bustype bustype;
+ 	void *ai;
+ 	unsigned int ai_nbits;
+@@ -45,13 +45,13 @@ struct das08_board_struct {
+ 	unsigned int do_nchan;
+ 	unsigned int i8255_offset;
+ 	unsigned int i8254_offset;
+-	unsigned int iosize;	// number of ioports used
++	unsigned int iosize;	/*  number of ioports used */
+ };
+ 
+ struct i8254_struct {
+-	int channels;		// available channels. Some could be used internally.
+-	int logic2phys[3];	// to know which physical channel is.
+-	int mode[3];		// the index is the real counter.
++	int channels;		/*  available channels. Some could be used internally. */
++	int logic2phys[3];	/*  to know which physical channel is. */
++	int mode[3];		/*  the index is the real counter. */
+ 	unsigned int iobase;
+ };
+ 
+@@ -61,11 +61,11 @@ struct i8254_struct {
+ #define I8254_CTRL 3
+ 
+ struct das08_private_struct {
+-	unsigned int do_mux_bits;	// bits for do/mux register on boards without seperate do register
+-	unsigned int do_bits;	// bits for do register on boards with register dedicated to digital out only
++	unsigned int do_mux_bits;	/*  bits for do/mux register on boards without seperate do register */
++	unsigned int do_bits;	/*  bits for do register on boards with register dedicated to digital out only */
+ 	const unsigned int *pg_gainlist;
+-	struct pci_dev *pdev;	// struct for pci-das08
+-	unsigned int pci_iobase;	// additional base address for pci-das08
++	struct pci_dev *pdev;	/*  struct for pci-das08 */
++	unsigned int pci_iobase;	/*  additional base address for pci-das08 */
+ 	struct i8254_struct i8254;
+ };
+ 
+diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
+index be6c88788c4b..9fbcbf966386 100644
+--- a/drivers/staging/comedi/drivers/das08_cs.c
++++ b/drivers/staging/comedi/drivers/das08_cs.c
+@@ -46,7 +46,7 @@ Command support does not exist, but could be added for this board.
+ 
+ #include "das08.h"
+ 
+-// pcmcia includes
++/* pcmcia includes */
+ #include 
+ #include 
+ #include 
+@@ -73,13 +73,13 @@ static int das08_cs_attach(struct comedi_device * dev, struct comedi_devconfig *
+ {
+ 	int ret;
+ 	unsigned long iobase;
+-	struct pcmcia_device *link = cur_dev;	// XXX hack
++	struct pcmcia_device *link = cur_dev;	/*  XXX hack */
+ 
+ 	if ((ret = alloc_private(dev, sizeof(struct das08_private_struct))) < 0)
+ 		return ret;
+ 
+ 	printk("comedi%d: das08_cs: ", dev->minor);
+-	// deal with a pci board
++	/*  deal with a pci board */
+ 
+ 	if (thisboard->bustype == pcmcia) {
+ 		if (link == NULL) {
+diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
+index b89316d5b53a..991e3330d11f 100644
+--- a/drivers/staging/comedi/drivers/das16.c
++++ b/drivers/staging/comedi/drivers/das16.c
+@@ -87,7 +87,7 @@ Computer boards manuals also available from their website www.measurementcomputi
+ #include "comedi_fc.h"
+ 
+ #undef DEBUG
+-//#define DEBUG
++/* #define DEBUG */
+ 
+ #ifdef DEBUG
+ #define DEBUG_PRINT(format, args...) rt_printk("das16: " format, ## args)
+@@ -95,8 +95,8 @@ Computer boards manuals also available from their website www.measurementcomputi
+ #define DEBUG_PRINT(format, args...)
+ #endif
+ 
+-#define DAS16_SIZE 20		// number of ioports
+-#define DAS16_DMA_SIZE 0xff00	// size in bytes of allocated dma buffer
++#define DAS16_SIZE 20		/*  number of ioports */
++#define DAS16_DMA_SIZE 0xff00	/*  size in bytes of allocated dma buffer */
+ 
+ /*
+     cio-das16.pdf
+@@ -184,7 +184,7 @@ Computer boards manuals also available from their website www.measurementcomputi
+ 
+ */
+ 
+-static const int sample_size = 2;	// size in bytes of a sample from board
++static const int sample_size = 2;	/*  size in bytes of a sample from board */
+ 
+ #define DAS16_TRIG		0
+ #define DAS16_AI_LSB		0
+@@ -265,7 +265,7 @@ static const struct comedi_lrange range_das1x02_unip = { 4, {
+ 	}
+ };
+ static const struct comedi_lrange range_das16jr = { 9, {
+-			// also used by 16/330
++			/*  also used by 16/330 */
+ 			BIP_RANGE(10),
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(2.5),
+@@ -359,7 +359,7 @@ struct das16_board {
+ 	const char *name;
+ 	void *ai;
+ 	unsigned int ai_nbits;
+-	unsigned int ai_speed;	// max conversion speed in nanosec
++	unsigned int ai_speed;	/*  max conversion speed in nanosec */
+ 	unsigned int ai_pg;
+ 	void *ao;
+ 	unsigned int ao_nbits;
+@@ -420,7 +420,7 @@ static const struct das16_board das16_boards[] = {
+ 	      id:	0x00,
+ 		},
+ 	{
+-	      name:	"cio-das16",	// cio-das16.pdf
++	      name:	"cio-das16",	/*  cio-das16.pdf */
+ 	      ai:	das16_ai_rinsn,
+ 	      ai_nbits:12,
+ 	      ai_speed:20000,
+@@ -435,7 +435,7 @@ static const struct das16_board das16_boards[] = {
+ 	      id:	0x80,
+ 		},
+ 	{
+-	      name:	"cio-das16/f",	// das16.pdf
++	      name:	"cio-das16/f",	/*  das16.pdf */
+ 	      ai:	das16_ai_rinsn,
+ 	      ai_nbits:12,
+ 	      ai_speed:10000,
+@@ -450,7 +450,7 @@ static const struct das16_board das16_boards[] = {
+ 	      id:	0x80,
+ 		},
+ 	{
+-	      name:	"cio-das16/jr",	// cio-das16jr.pdf
++	      name:	"cio-das16/jr",	/*  cio-das16jr.pdf */
+ 	      ai:	das16_ai_rinsn,
+ 	      ai_nbits:12,
+ 	      ai_speed:7692,
+@@ -464,7 +464,7 @@ static const struct das16_board das16_boards[] = {
+ 	      id:	0x00,
+ 		},
+ 	{
+-	      name:	"pc104-das16jr",	// pc104-das16jr_xx.pdf
++	      name:	"pc104-das16jr",	/*  pc104-das16jr_xx.pdf */
+ 	      ai:	das16_ai_rinsn,
+ 	      ai_nbits:12,
+ 	      ai_speed:3300,
+@@ -478,7 +478,7 @@ static const struct das16_board das16_boards[] = {
+ 	      id:	0x00,
+ 		},
+ 	{
+-	      name:	"cio-das16jr/16",	// cio-das16jr_16.pdf
++	      name:	"cio-das16jr/16",	/*  cio-das16jr_16.pdf */
+ 	      ai:	das16_ai_rinsn,
+ 	      ai_nbits:16,
+ 	      ai_speed:10000,
+@@ -492,7 +492,7 @@ static const struct das16_board das16_boards[] = {
+ 	      id:	0x00,
+ 		},
+ 	{
+-	      name:	"pc104-das16jr/16",	// pc104-das16jr_xx.pdf
++	      name:	"pc104-das16jr/16",	/*  pc104-das16jr_xx.pdf */
+ 	      ai:	das16_ai_rinsn,
+ 	      ai_nbits:16,
+ 	      ai_speed:10000,
+@@ -506,7 +506,7 @@ static const struct das16_board das16_boards[] = {
+ 	      id:	0x00,
+ 		},
+ 	{
+-	      name:	"das-1201",	// 4924.pdf (keithley user's manual)
++	      name:	"das-1201",	/*  4924.pdf (keithley user's manual) */
+ 	      ai:	das16_ai_rinsn,
+ 	      ai_nbits:12,
+ 	      ai_speed:20000,
+@@ -520,7 +520,7 @@ static const struct das16_board das16_boards[] = {
+ 	      id:	0x20,
+ 		},
+ 	{
+-	      name:	"das-1202",	// 4924.pdf (keithley user's manual)
++	      name:	"das-1202",	/*  4924.pdf (keithley user's manual) */
+ 	      ai:	das16_ai_rinsn,
+ 	      ai_nbits:12,
+ 	      ai_speed:10000,
+@@ -534,7 +534,7 @@ static const struct das16_board das16_boards[] = {
+ 	      id:	0x20,
+ 		},
+ 	{
+-	      name:	"das-1401",	// 4919.pdf and 4922.pdf (keithley user's manual)
++	      name:	"das-1401",	/*  4919.pdf and 4922.pdf (keithley user's manual) */
+ 	      ai:	das16_ai_rinsn,
+ 	      ai_nbits:12,
+ 	      ai_speed:10000,
+@@ -545,10 +545,10 @@ static const struct das16_board das16_boards[] = {
+ 	      i8255_offset:0x0,
+ 	      i8254_offset:0x0c,
+ 	      size:	0x408,
+-	      id:	0xc0	// 4919.pdf says id bits are 0xe0, 4922.pdf says 0xc0
++	      id:	0xc0	/*  4919.pdf says id bits are 0xe0, 4922.pdf says 0xc0 */
+ 		},
+ 	{
+-	      name:	"das-1402",	// 4919.pdf and 4922.pdf (keithley user's manual)
++	      name:	"das-1402",	/*  4919.pdf and 4922.pdf (keithley user's manual) */
+ 	      ai:	das16_ai_rinsn,
+ 	      ai_nbits:12,
+ 	      ai_speed:10000,
+@@ -559,10 +559,10 @@ static const struct das16_board das16_boards[] = {
+ 	      i8255_offset:0x0,
+ 	      i8254_offset:0x0c,
+ 	      size:	0x408,
+-	      id:	0xc0	// 4919.pdf says id bits are 0xe0, 4922.pdf says 0xc0
++	      id:	0xc0	/*  4919.pdf says id bits are 0xe0, 4922.pdf says 0xc0 */
+ 		},
+ 	{
+-	      name:	"das-1601",	// 4919.pdf
++	      name:	"das-1601",	/*  4919.pdf */
+ 	      ai:	das16_ai_rinsn,
+ 	      ai_nbits:12,
+ 	      ai_speed:10000,
+@@ -576,7 +576,7 @@ static const struct das16_board das16_boards[] = {
+ 	      size:	0x408,
+       id:	0xc0},
+ 	{
+-	      name:	"das-1602",	// 4919.pdf
++	      name:	"das-1602",	/*  4919.pdf */
+ 	      ai:	das16_ai_rinsn,
+ 	      ai_nbits:12,
+ 	      ai_speed:10000,
+@@ -590,7 +590,7 @@ static const struct das16_board das16_boards[] = {
+ 	      size:	0x408,
+       id:	0xc0},
+ 	{
+-	      name:	"cio-das1401/12",	// cio-das1400_series.pdf
++	      name:	"cio-das1401/12",	/*  cio-das1400_series.pdf */
+ 	      ai:	das16_ai_rinsn,
+ 	      ai_nbits:12,
+ 	      ai_speed:6250,
+@@ -603,7 +603,7 @@ static const struct das16_board das16_boards[] = {
+ 	      size:	0x408,
+       id:	0xc0},
+ 	{
+-	      name:	"cio-das1402/12",	// cio-das1400_series.pdf
++	      name:	"cio-das1402/12",	/*  cio-das1400_series.pdf */
+ 	      ai:	das16_ai_rinsn,
+ 	      ai_nbits:12,
+ 	      ai_speed:6250,
+@@ -616,7 +616,7 @@ static const struct das16_board das16_boards[] = {
+ 	      size:	0x408,
+       id:	0xc0},
+ 	{
+-	      name:	"cio-das1402/16",	// cio-das1400_series.pdf
++	      name:	"cio-das1402/16",	/*  cio-das1400_series.pdf */
+ 	      ai:	das16_ai_rinsn,
+ 	      ai_nbits:16,
+ 	      ai_speed:10000,
+@@ -629,7 +629,7 @@ static const struct das16_board das16_boards[] = {
+ 	      size:	0x408,
+       id:	0xc0},
+ 	{
+-	      name:	"cio-das1601/12",	// cio-das160x-1x.pdf
++	      name:	"cio-das1601/12",	/*  cio-das160x-1x.pdf */
+ 	      ai:	das16_ai_rinsn,
+ 	      ai_nbits:12,
+ 	      ai_speed:6250,
+@@ -643,7 +643,7 @@ static const struct das16_board das16_boards[] = {
+ 	      size:	0x408,
+       id:	0xc0},
+ 	{
+-	      name:	"cio-das1602/12",	// cio-das160x-1x.pdf
++	      name:	"cio-das1602/12",	/*  cio-das160x-1x.pdf */
+ 	      ai:	das16_ai_rinsn,
+ 	      ai_nbits:12,
+ 	      ai_speed:10000,
+@@ -657,7 +657,7 @@ static const struct das16_board das16_boards[] = {
+ 	      size:	0x408,
+       id:	0xc0},
+ 	{
+-	      name:	"cio-das1602/16",	// cio-das160x-1x.pdf
++	      name:	"cio-das1602/16",	/*  cio-das160x-1x.pdf */
+ 	      ai:	das16_ai_rinsn,
+ 	      ai_nbits:16,
+ 	      ai_speed:10000,
+@@ -671,7 +671,7 @@ static const struct das16_board das16_boards[] = {
+ 	      size:	0x408,
+       id:	0xc0},
+ 	{
+-	      name:	"cio-das16/330",	// ?
++	      name:	"cio-das16/330",	/*  ? */
+ 	      ai:	das16_ai_rinsn,
+ 	      ai_nbits:12,
+ 	      ai_speed:3030,
+@@ -685,13 +685,13 @@ static const struct das16_board das16_boards[] = {
+       id:	0xf0},
+ #if 0
+ 	{
+-	      name:	"das16/330i",	// ?
++	      name:	"das16/330i",	/*  ? */
+ 		},
+ 	{
+-	      name:	"das16/jr/ctr5",	// ?
++	      name:	"das16/jr/ctr5",	/*  ? */
+ 		},
+ 	{
+-	      name:	"cio-das16/m1/16",	// cio-das16_m1_16.pdf, this board is a bit quirky, no dma
++	      name:	"cio-das16/m1/16",	/*  cio-das16_m1_16.pdf, this board is a bit quirky, no dma */
+ 		},
+ #endif
+ };
+@@ -719,25 +719,25 @@ static inline int timer_period(void)
+ 	return HZ / 20;
+ }
+ struct das16_private_struct {
+-	unsigned int ai_unipolar;	// unipolar flag
+-	unsigned int ai_singleended;	// single ended flag
+-	unsigned int clockbase;	// master clock speed in ns
+-	volatile unsigned int control_state;	// dma, interrupt and trigger control bits
+-	volatile unsigned long adc_byte_count;	// number of bytes remaining
+-	unsigned int divisor1;	// divisor dividing master clock to get conversion frequency
+-	unsigned int divisor2;	// divisor dividing master clock to get conversion frequency
+-	unsigned int dma_chan;	// dma channel
++	unsigned int ai_unipolar;	/*  unipolar flag */
++	unsigned int ai_singleended;	/*  single ended flag */
++	unsigned int clockbase;	/*  master clock speed in ns */
++	volatile unsigned int control_state;	/*  dma, interrupt and trigger control bits */
++	volatile unsigned long adc_byte_count;	/*  number of bytes remaining */
++	unsigned int divisor1;	/*  divisor dividing master clock to get conversion frequency */
++	unsigned int divisor2;	/*  divisor dividing master clock to get conversion frequency */
++	unsigned int dma_chan;	/*  dma channel */
+ 	uint16_t *dma_buffer[2];
+ 	dma_addr_t dma_buffer_addr[2];
+ 	unsigned int current_buffer;
+-	volatile unsigned int dma_transfer_size;	// target number of bytes to transfer per dma shot
+-	// user-defined analog input and output ranges defined from config options
++	volatile unsigned int dma_transfer_size;	/*  target number of bytes to transfer per dma shot */
++	/*  user-defined analog input and output ranges defined from config options */
+ 	struct comedi_lrange *user_ai_range_table;
+ 	struct comedi_lrange *user_ao_range_table;
+ 
+-	struct timer_list timer;	// for timed interrupt
++	struct timer_list timer;	/*  for timed interrupt */
+ 	volatile short timer_running;
+-	volatile short timer_mode;	// true if using timer mode
++	volatile short timer_mode;	/*  true if using timer mode */
+ };
+ #define devpriv ((struct das16_private_struct *)(dev->private))
+ #define thisboard ((struct das16_board *)(dev->board_ptr))
+@@ -757,7 +757,7 @@ static int das16_cmd_test(struct comedi_device * dev, struct comedi_subdevice *
+ 
+ 	tmp = cmd->scan_begin_src;
+ 	mask = TRIG_FOLLOW;
+-	// if board supports burst mode
++	/*  if board supports burst mode */
+ 	if (thisboard->size > 0x400)
+ 		mask |= TRIG_TIMER | TRIG_EXT;
+ 	cmd->scan_begin_src &= mask;
+@@ -766,7 +766,7 @@ static int das16_cmd_test(struct comedi_device * dev, struct comedi_subdevice *
+ 
+ 	tmp = cmd->convert_src;
+ 	mask = TRIG_TIMER | TRIG_EXT;
+-	// if board supports burst mode
++	/*  if board supports burst mode */
+ 	if (thisboard->size > 0x400)
+ 		mask |= TRIG_NOW;
+ 	cmd->convert_src &= mask;
+@@ -797,7 +797,7 @@ static int das16_cmd_test(struct comedi_device * dev, struct comedi_subdevice *
+ 	if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
+ 		err++;
+ 
+-	// make sure scan_begin_src and convert_src dont conflict
++	/*  make sure scan_begin_src and convert_src dont conflict */
+ 	if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
+ 		err++;
+ 	if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
+@@ -824,7 +824,7 @@ static int das16_cmd_test(struct comedi_device * dev, struct comedi_subdevice *
+ 		cmd->scan_end_arg = cmd->chanlist_len;
+ 		err++;
+ 	}
+-	// check against maximum frequency
++	/*  check against maximum frequency */
+ 	if (cmd->scan_begin_src == TRIG_TIMER) {
+ 		if (cmd->scan_begin_arg <
+ 			thisboard->ai_speed * cmd->chanlist_len) {
+@@ -849,10 +849,10 @@ static int das16_cmd_test(struct comedi_device * dev, struct comedi_subdevice *
+ 	if (err)
+ 		return 3;
+ 
+-	// step 4: fix up arguments
++	/*  step 4: fix up arguments */
+ 	if (cmd->scan_begin_src == TRIG_TIMER) {
+ 		unsigned int tmp = cmd->scan_begin_arg;
+-		// set divisors, correct timing arguments
++		/*  set divisors, correct timing arguments */
+ 		i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
+ 			&(devpriv->divisor1), &(devpriv->divisor2),
+ 			&(cmd->scan_begin_arg), cmd->flags & TRIG_ROUND_MASK);
+@@ -860,7 +860,7 @@ static int das16_cmd_test(struct comedi_device * dev, struct comedi_subdevice *
+ 	}
+ 	if (cmd->convert_src == TRIG_TIMER) {
+ 		unsigned int tmp = cmd->convert_arg;
+-		// set divisors, correct timing arguments
++		/*  set divisors, correct timing arguments */
+ 		i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
+ 			&(devpriv->divisor1), &(devpriv->divisor2),
+ 			&(cmd->convert_arg), cmd->flags & TRIG_ROUND_MASK);
+@@ -869,7 +869,7 @@ static int das16_cmd_test(struct comedi_device * dev, struct comedi_subdevice *
+ 	if (err)
+ 		return 4;
+ 
+-	// check channel/gain list against card's limitations
++	/*  check channel/gain list against card's limitations */
+ 	if (cmd->chanlist) {
+ 		gain = CR_RANGE(cmd->chanlist[0]);
+ 		start_chan = CR_CHAN(cmd->chanlist[0]);
+@@ -916,11 +916,11 @@ static int das16_cmd_exec(struct comedi_device * dev, struct comedi_subdevice *
+ 	devpriv->adc_byte_count =
+ 		cmd->stop_arg * cmd->chanlist_len * sizeof(uint16_t);
+ 
+-	// disable conversions for das1600 mode
++	/*  disable conversions for das1600 mode */
+ 	if (thisboard->size > 0x400) {
+ 		outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV);
+ 	}
+-	// set scan limits
++	/*  set scan limits */
+ 	byte = CR_CHAN(cmd->chanlist[0]);
+ 	byte |= CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]) << 4;
+ 	outb(byte, dev->iobase + DAS16_MUX);
+@@ -945,7 +945,7 @@ static int das16_cmd_exec(struct comedi_device * dev, struct comedi_subdevice *
+ 	if (thisboard->size > 0x400) {
+ 		if (cmd->convert_src == TRIG_NOW) {
+ 			outb(DAS1600_BURST_VAL, dev->iobase + DAS1600_BURST);
+-			// set burst length
++			/*  set burst length */
+ 			byte |= BURST_LEN_BITS(cmd->chanlist_len - 1);
+ 		} else {
+ 			outb(0, dev->iobase + DAS1600_BURST);
+@@ -953,7 +953,7 @@ static int das16_cmd_exec(struct comedi_device * dev, struct comedi_subdevice *
+ 	}
+ 	outb(byte, dev->iobase + DAS16_PACER);
+ 
+-	// set up dma transfer
++	/*  set up dma transfer */
+ 	flags = claim_dma_lock();
+ 	disable_dma(devpriv->dma_chan);
+ 	/* clear flip-flop to make sure 2-byte registers for
+@@ -962,13 +962,13 @@ static int das16_cmd_exec(struct comedi_device * dev, struct comedi_subdevice *
+ 	devpriv->current_buffer = 0;
+ 	set_dma_addr(devpriv->dma_chan,
+ 		devpriv->dma_buffer_addr[devpriv->current_buffer]);
+-	// set appropriate size of transfer
++	/*  set appropriate size of transfer */
+ 	devpriv->dma_transfer_size = das16_suggest_transfer_size(dev, *cmd);
+ 	set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
+ 	enable_dma(devpriv->dma_chan);
+ 	release_dma_lock(flags);
+ 
+-	// set up interrupt
++	/*  set up interrupt */
+ 	if (devpriv->timer_mode) {
+ 		devpriv->timer_running = 1;
+ 		devpriv->timer.expires = jiffies + timer_period();
+@@ -1007,7 +1007,7 @@ static int das16_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	if (devpriv->dma_chan)
+ 		disable_dma(devpriv->dma_chan);
+ 
+-	// disable SW timer
++	/*  disable SW timer */
+ 	if (devpriv->timer_mode && devpriv->timer_running) {
+ 		devpriv->timer_running = 0;
+ 		del_timer(&devpriv->timer);
+@@ -1039,7 +1039,7 @@ static int das16_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ 	int chan;
+ 	int msb, lsb;
+ 
+-	// disable interrupts and pacing
++	/*  disable interrupts and pacing */
+ 	devpriv->control_state &= ~DAS16_INTE & ~DMA_ENABLE & ~PACING_MASK;
+ 	outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
+ 
+@@ -1096,12 +1096,12 @@ static int das16_do_wbits(struct comedi_device * dev, struct comedi_subdevice *
+ {
+ 	unsigned int wbits;
+ 
+-	// only set bits that have been masked
++	/*  only set bits that have been masked */
+ 	data[0] &= 0xf;
+ 	wbits = s->state;
+-	// zero bits that have been masked
++	/*  zero bits that have been masked */
+ 	wbits &= ~data[0];
+-	// set masked bits
++	/*  set masked bits */
+ 	wbits |= data[0] & data[1];
+ 	s->state = wbits;
+ 	data[1] = wbits;
+@@ -1210,7 +1210,7 @@ static void das16_interrupt(struct comedi_device * dev)
+ 		comedi_error(dev, "premature interrupt");
+ 		return;
+ 	}
+-	// initialize async here to make sure it is not NULL
++	/*  initialize async here to make sure it is not NULL */
+ 	async = s->async;
+ 	cmd = &async->cmd;
+ 
+@@ -1230,7 +1230,7 @@ static void das16_interrupt(struct comedi_device * dev)
+ 	clear_dma_ff(devpriv->dma_chan);
+ 	residue = disable_dma_on_even(dev);
+ 
+-	// figure out how many points to read
++	/*  figure out how many points to read */
+ 	if (residue > devpriv->dma_transfer_size) {
+ 		comedi_error(dev, "residue > transfer size!\n");
+ 		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
+@@ -1247,12 +1247,12 @@ static void das16_interrupt(struct comedi_device * dev)
+ 	devpriv->current_buffer = (devpriv->current_buffer + 1) % 2;
+ 	devpriv->adc_byte_count -= num_bytes;
+ 
+-	// figure out how many bytes for next transfer
++	/*  figure out how many bytes for next transfer */
+ 	if (cmd->stop_src == TRIG_COUNT && devpriv->timer_mode == 0 &&
+ 		devpriv->dma_transfer_size > devpriv->adc_byte_count)
+ 		devpriv->dma_transfer_size = devpriv->adc_byte_count;
+ 
+-	// re-enable  dma
++	/*  re-enable  dma */
+ 	if ((async->events & COMEDI_CB_EOA) == 0) {
+ 		set_dma_addr(devpriv->dma_chan,
+ 			devpriv->dma_buffer_addr[devpriv->current_buffer]);
+@@ -1391,7 +1391,7 @@ static int das16_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 
+ 	printk("comedi%d: das16:", dev->minor);
+ 
+-	// check that clock setting is valid
++	/*  check that clock setting is valid */
+ 	if (it->options[3]) {
+ 		if (it->options[3] != 0 &&
+ 			it->options[3] != 1 && it->options[3] != 10) {
+@@ -1431,19 +1431,19 @@ static int das16_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 
+ 	dev->iobase = iobase;
+ 
+-	// probe id bits to make sure they are consistent
++	/*  probe id bits to make sure they are consistent */
+ 	if (das16_probe(dev, it)) {
+ 		printk(" id bits do not match selected board, aborting\n");
+ 		return -EINVAL;
+ 	}
+ 	dev->board_name = thisboard->name;
+ 
+-	// get master clock speed
++	/*  get master clock speed */
+ 	if (thisboard->size < 0x400) {
+ 		if (it->options[3])
+ 			devpriv->clockbase = 1000 / it->options[3];
+ 		else
+-			devpriv->clockbase = 1000;	// 1 MHz default
++			devpriv->clockbase = 1000;	/*  1 MHz default */
+ 	} else {
+ 		das1600_mode_detect(dev);
+ 	}
+@@ -1462,10 +1462,10 @@ static int das16_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 		return -EINVAL;
+ 	}
+ 
+-	// initialize dma
++	/*  initialize dma */
+ 	dma_chan = it->options[2];
+ 	if (dma_chan == 1 || dma_chan == 3) {
+-		// allocate dma buffers
++		/*  allocate dma buffers */
+ 		int i;
+ 		for (i = 0; i < 2; i++) {
+ 			devpriv->dma_buffer[i] = pci_alloc_consistent(NULL,
+@@ -1491,27 +1491,27 @@ static int das16_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 		return -EINVAL;
+ 	}
+ 
+-	// get any user-defined input range
++	/*  get any user-defined input range */
+ 	if (thisboard->ai_pg == das16_pg_none &&
+ 		(it->options[4] || it->options[5])) {
+-		// allocate single-range range table
++		/*  allocate single-range range table */
+ 		devpriv->user_ai_range_table =
+ 			kmalloc(sizeof(struct comedi_lrange) + sizeof(struct comedi_krange),
+ 			GFP_KERNEL);
+-		// initialize ai range
++		/*  initialize ai range */
+ 		devpriv->user_ai_range_table->length = 1;
+ 		user_ai_range = devpriv->user_ai_range_table->range;
+ 		user_ai_range->min = it->options[4];
+ 		user_ai_range->max = it->options[5];
+ 		user_ai_range->flags = UNIT_volt;
+ 	}
+-	// get any user-defined output range
++	/*  get any user-defined output range */
+ 	if (it->options[6] || it->options[7]) {
+-		// allocate single-range range table
++		/*  allocate single-range range table */
+ 		devpriv->user_ao_range_table =
+ 			kmalloc(sizeof(struct comedi_lrange) + sizeof(struct comedi_krange),
+ 			GFP_KERNEL);
+-		// initialize ao range
++		/*  initialize ao range */
+ 		devpriv->user_ao_range_table->length = 1;
+ 		user_ao_range = devpriv->user_ao_range_table->range;
+ 		user_ao_range->min = it->options[6];
+@@ -1545,7 +1545,7 @@ static int das16_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 			s->subdev_flags |= SDF_DIFF;
+ 		}
+ 		s->maxdata = (1 << thisboard->ai_nbits) - 1;
+-		if (devpriv->user_ai_range_table) {	// user defined ai range
++		if (devpriv->user_ai_range_table) {	/*  user defined ai range */
+ 			s->range_table = devpriv->user_ai_range_table;
+ 		} else if (devpriv->ai_unipolar) {
+ 			s->range_table = das16_ai_uni_lranges[thisboard->ai_pg];
+@@ -1568,7 +1568,7 @@ static int das16_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 		s->subdev_flags = SDF_WRITABLE;
+ 		s->n_chan = 2;
+ 		s->maxdata = (1 << thisboard->ao_nbits) - 1;
+-		if (devpriv->user_ao_range_table) {	// user defined ao range
++		if (devpriv->user_ao_range_table) {	/*  user defined ao range */
+ 			s->range_table = devpriv->user_ao_range_table;
+ 		} else {
+ 			s->range_table = &range_unknown;
+@@ -1600,7 +1600,7 @@ static int das16_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 		s->maxdata = 1;
+ 		s->range_table = &range_digital;
+ 		s->insn_bits = thisboard->do_;
+-		// initialize digital output lines
++		/*  initialize digital output lines */
+ 		outb(s->state, dev->iobase + DAS16_DIO);
+ 	} else {
+ 		s->type = COMEDI_SUBD_UNUSED;
+@@ -1620,7 +1620,7 @@ static int das16_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 	devpriv->control_state = DAS16_IRQ(dev->irq);
+ 	outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
+ 
+-	// turn on das1600 mode if available
++	/*  turn on das1600 mode if available */
+ 	if (thisboard->size > 0x400) {
+ 		outb(DAS1600_ENABLE_VAL, dev->iobase + DAS1600_ENABLE);
+ 		outb(0, dev->iobase + DAS1600_CONV);
+@@ -1673,7 +1673,7 @@ static int das16_detach(struct comedi_device * dev)
+ 
+ COMEDI_INITCLEANUP(driver_das16);
+ 
+-// utility function that suggests a dma transfer size in bytes
++/* utility function that suggests a dma transfer size in bytes */
+ static unsigned int das16_suggest_transfer_size(struct comedi_device * dev,
+ 	struct comedi_cmd cmd)
+ {
+@@ -1692,18 +1692,18 @@ static unsigned int das16_suggest_transfer_size(struct comedi_device * dev,
+ 		freq = 1000000000 / cmd.convert_arg;
+ 	else if (cmd.scan_begin_src == TRIG_TIMER)
+ 		freq = (1000000000 / cmd.scan_begin_arg) * cmd.chanlist_len;
+-	// return some default value
++	/*  return some default value */
+ 	else
+ 		freq = 0xffffffff;
+ 
+ 	if (cmd.flags & TRIG_WAKE_EOS) {
+ 		size = sample_size * cmd.chanlist_len;
+ 	} else {
+-		// make buffer fill in no more than 1/3 second
++		/*  make buffer fill in no more than 1/3 second */
+ 		size = (freq / 3) * sample_size;
+ 	}
+ 
+-	// set a minimum and maximum size allowed
++	/*  set a minimum and maximum size allowed */
+ 	if (size > DAS16_DMA_SIZE)
+ 		size = DAS16_DMA_SIZE - DAS16_DMA_SIZE % sample_size;
+ 	else if (size < sample_size)
+diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
+index 1a5cb1217938..5b1d96cea046 100644
+--- a/drivers/staging/comedi/drivers/das16m1.c
++++ b/drivers/staging/comedi/drivers/das16m1.c
+@@ -68,9 +68,9 @@ irq can be omitted, although the cmd interface will not work without it.
+ #define DAS16M1_SIZE 16
+ #define DAS16M1_SIZE2 8
+ 
+-#define DAS16M1_XTAL 100	//10 MHz master clock
++#define DAS16M1_XTAL 100	/* 10 MHz master clock */
+ 
+-#define FIFO_SIZE 1024		// 1024 sample fifo
++#define FIFO_SIZE 1024		/*  1024 sample fifo */
+ 
+ /*
+     CIO-DAS16_M1.pdf
+@@ -92,7 +92,7 @@ irq can be omitted, although the cmd interface will not work without it.
+ 
+ */
+ 
+-#define DAS16M1_AI             0	// 16-bit wide register
++#define DAS16M1_AI             0	/*  16-bit wide register */
+ #define   AI_CHAN(x)             ((x) & 0xf)
+ #define DAS16M1_CS             2
+ #define   EXT_TRIG_BIT           0x1
+@@ -159,8 +159,8 @@ struct das16m1_board {
+ 
+ static const struct das16m1_board das16m1_boards[] = {
+ 	{
+-	      name:	"cio-das16/m1",	// CIO-DAS16_M1.pdf
+-	      ai_speed:1000,	// 1MHz max speed
++	      name:	"cio-das16/m1",	/*  CIO-DAS16_M1.pdf */
++	      ai_speed:1000,	/*  1MHz max speed */
+ 		},
+ };
+ 
+@@ -180,15 +180,15 @@ static struct comedi_driver driver_das16m1 = {
+ 
+ struct das16m1_private_struct {
+ 	unsigned int control_state;
+-	volatile unsigned int adc_count;	// number of samples completed
++	volatile unsigned int adc_count;	/*  number of samples completed */
+ 	/* initial value in lower half of hardware conversion counter,
+ 	 * needed to keep track of whether new count has been loaded into
+ 	 * counter yet (loaded by first sample conversion) */
+ 	u16 initial_hw_count;
+ 	short ai_buffer[FIFO_SIZE];
+-	unsigned int do_bits;	// saves status of digital output bits
+-	unsigned int divisor1;	// divides master clock to obtain conversion speed
+-	unsigned int divisor2;	// divides master clock to obtain conversion speed
++	unsigned int do_bits;	/*  saves status of digital output bits */
++	unsigned int divisor1;	/*  divides master clock to obtain conversion speed */
++	unsigned int divisor2;	/*  divides master clock to obtain conversion speed */
+ };
+ #define devpriv ((struct das16m1_private_struct *)(dev->private))
+ #define thisboard ((const struct das16m1_board *)(dev->board_ptr))
+@@ -299,10 +299,10 @@ static int das16m1_cmd_test(struct comedi_device * dev, struct comedi_subdevice
+ 	if (err)
+ 		return 4;
+ 
+-	// check chanlist against board's peculiarities
++	/*  check chanlist against board's peculiarities */
+ 	if (cmd->chanlist && cmd->chanlist_len > 1) {
+ 		for (i = 0; i < cmd->chanlist_len; i++) {
+-			// even/odd channels must go into even/odd queue addresses
++			/*  even/odd channels must go into even/odd queue addresses */
+ 			if ((i % 2) != (CR_CHAN(cmd->chanlist[i]) % 2)) {
+ 				comedi_error(dev, "bad chanlist:\n"
+ 					" even/odd channels must go have even/odd chanlist indices");
+@@ -337,7 +337,7 @@ static int das16m1_cmd_exec(struct comedi_device * dev, struct comedi_subdevice
+ 	devpriv->control_state &= ~INTE & ~PACER_MASK;
+ 	outb(devpriv->control_state, dev->iobase + DAS16M1_INTR_CONTROL);
+ 
+-	// set software count
++	/*  set software count */
+ 	devpriv->adc_count = 0;
+ 	/* Initialize lower half of hardware counter, used to determine how
+ 	 * many samples are in fifo.  Value doesn't actually load into counter
+@@ -361,7 +361,7 @@ static int das16m1_cmd_exec(struct comedi_device * dev, struct comedi_subdevice
+ 		das16m1_set_pacer(dev, cmd->convert_arg,
+ 		cmd->flags & TRIG_ROUND_MASK);
+ 
+-	// set control & status register
++	/*  set control & status register */
+ 	byte = 0;
+ 	/* if we are using external start trigger (also board dislikes having
+ 	 * both start and conversion triggers external simultaneously) */
+@@ -447,12 +447,12 @@ static int das16m1_do_wbits(struct comedi_device * dev, struct comedi_subdevice
+ {
+ 	unsigned int wbits;
+ 
+-	// only set bits that have been masked
++	/*  only set bits that have been masked */
+ 	data[0] &= 0xf;
+ 	wbits = devpriv->do_bits;
+-	// zero bits that have been masked
++	/*  zero bits that have been masked */
+ 	wbits &= ~data[0];
+-	// set masked bits
++	/*  set masked bits */
+ 	wbits |= data[0] & data[1];
+ 	devpriv->do_bits = wbits;
+ 	data[1] = wbits;
+@@ -467,7 +467,7 @@ static int das16m1_poll(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	unsigned long flags;
+ 	unsigned int status;
+ 
+-	// prevent race with interrupt handler
++	/*  prevent race with interrupt handler */
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 	status = inb(dev->iobase + DAS16M1_CS);
+ 	das16m1_handler(dev, status);
+@@ -485,7 +485,7 @@ static irqreturn_t das16m1_interrupt(int irq, void *d)
+ 		comedi_error(dev, "premature interrupt");
+ 		return IRQ_HANDLED;
+ 	}
+-	// prevent race with comedi_poll()
++	/*  prevent race with comedi_poll() */
+ 	spin_lock(&dev->spinlock);
+ 
+ 	status = inb(dev->iobase + DAS16M1_CS);
+@@ -527,7 +527,7 @@ static void das16m1_handler(struct comedi_device * dev, unsigned int status)
+ 	async->events = 0;
+ 	cmd = &async->cmd;
+ 
+-	// figure out how many samples are in fifo
++	/*  figure out how many samples are in fifo */
+ 	hw_counter = i8254_read(dev->iobase + DAS16M1_8254_FIRST, 0, 1);
+ 	/* make sure hardware counter reading is not bogus due to initial value
+ 	 * not having been loaded yet */
+@@ -542,12 +542,12 @@ static void das16m1_handler(struct comedi_device * dev, unsigned int status)
+ 		 * hardware counter.  Work it out, and this is what you get. */
+ 		num_samples = -hw_counter - devpriv->adc_count;
+ 	}
+-	// check if we only need some of the points
++	/*  check if we only need some of the points */
+ 	if (cmd->stop_src == TRIG_COUNT) {
+ 		if (num_samples > cmd->stop_arg * cmd->chanlist_len)
+ 			num_samples = cmd->stop_arg * cmd->chanlist_len;
+ 	}
+-	// make sure we dont try to get too many points if fifo has overrun
++	/*  make sure we dont try to get too many points if fifo has overrun */
+ 	if (num_samples > FIFO_SIZE)
+ 		num_samples = FIFO_SIZE;
+ 	insw(dev->iobase, devpriv->ai_buffer, num_samples);
+@@ -669,7 +669,7 @@ static int das16m1_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 
+ 	/* now for the irq */
+ 	irq = it->options[1];
+-	// make sure it is valid
++	/*  make sure it is valid */
+ 	if (das16m1_irq_bits(irq) >= 0) {
+ 		ret = comedi_request_irq(irq, das16m1_interrupt, 0,
+ 			driver_das16m1.driver_name, dev);
+@@ -728,10 +728,10 @@ static int das16m1_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	/* 8255 */
+ 	subdev_8255_init(dev, s, NULL, dev->iobase + DAS16M1_82C55);
+ 
+-	// disable upper half of hardware conversion counter so it doesn't mess with us
++	/*  disable upper half of hardware conversion counter so it doesn't mess with us */
+ 	outb(TOTAL_CLEAR, dev->iobase + DAS16M1_8254_FIRST_CNTRL);
+ 
+-	// initialize digital output lines
++	/*  initialize digital output lines */
+ 	outb(devpriv->do_bits, dev->iobase + DAS16M1_DIO);
+ 
+ 	/* set the interrupt level */
+@@ -748,7 +748,7 @@ static int das16m1_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: das16m1: remove\n", dev->minor);
+ 
+-//      das16m1_reset(dev);
++/* das16m1_reset(dev); */
+ 
+ 	if (dev->subdevices)
+ 		subdev_8255_cleanup(dev, dev->subdevices + 3);
+diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c
+index 9dccd82d2663..ed9409d41a32 100644
+--- a/drivers/staging/comedi/drivers/das6402.c
++++ b/drivers/staging/comedi/drivers/das6402.c
+@@ -342,7 +342,7 @@ static int das6402_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	s->type = COMEDI_SUBD_AI;
+ 	s->subdev_flags = SDF_READABLE | SDF_GROUND;
+ 	s->n_chan = 8;
+-	//s->trig[2]=das6402_ai_mode2;
++	/* s->trig[2]=das6402_ai_mode2; */
+ 	s->cancel = das6402_ai_cancel;
+ 	s->maxdata = (1 << 12) - 1;
+ 	s->len_chanlist = 16;	/* ? */
+diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
+index ee659fdd1b59..eafee0c655aa 100644
+--- a/drivers/staging/comedi/drivers/das800.c
++++ b/drivers/staging/comedi/drivers/das800.c
+@@ -72,7 +72,7 @@ cmd triggers supported:
+ 
+ #define DAS800_SIZE           8
+ #define TIMER_BASE            1000
+-#define N_CHAN_AI             8	// number of analog input channels
++#define N_CHAN_AI             8	/*  number of analog input channels */
+ 
+ /* Registers for the das800 */
+ 
+@@ -94,8 +94,8 @@ cmd triggers supported:
+ #define   IRQ                   0x8
+ #define   BUSY                  0x80
+ #define DAS800_GAIN           3
+-#define   CIO_FFOV              0x8	// fifo overflow for cio-das802/16
+-#define   CIO_ENHF              0x90	// interrupt fifo half full for cio-das802/16
++#define   CIO_FFOV              0x8	/*  fifo overflow for cio-das802/16 */
++#define   CIO_ENHF              0x90	/*  interrupt fifo half full for cio-das802/16 */
+ #define   CONTROL1              0x80
+ #define   CONV_CONTROL          0xa0
+ #define   SCAN_LIMITS           0xc0
+@@ -113,7 +113,7 @@ struct das800_board {
+ 	int resolution;
+ };
+ 
+-//analog input ranges
++/* analog input ranges */
+ static const struct comedi_lrange range_das800_ai = {
+ 	1,
+ 	{
+@@ -278,7 +278,7 @@ static int das800_probe(struct comedi_device * dev)
+ 	unsigned long irq_flags;
+ 	int board;
+ 
+-	// 'comedi spin lock irqsave' disables even rt interrupts, we use them to protect indirect addressing
++	/*  'comedi spin lock irqsave' disables even rt interrupts, we use them to protect indirect addressing */
+ 	comedi_spin_lock_irqsave(&dev->spinlock, irq_flags);
+ 	outb(ID, dev->iobase + DAS800_GAIN);	/* select base address + 7 to be ID register */
+ 	id_bits = inb(dev->iobase + DAS800_ID) & 0x3;	/* get id bits */
+@@ -352,8 +352,8 @@ static irqreturn_t das800_interrupt(int irq, void *d)
+ 	struct comedi_async *async;
+ 	int status;
+ 	unsigned long irq_flags;
+-	static const int max_loops = 128;	// half-fifo size for cio-das802/16
+-	// flags
++	static const int max_loops = 128;	/*  half-fifo size for cio-das802/16 */
++	/*  flags */
+ 	int fifo_empty = 0;
+ 	int fifo_overflow = 0;
+ 
+@@ -369,7 +369,7 @@ static irqreturn_t das800_interrupt(int irq, void *d)
+ 	 */
+ 	async = s->async;
+ 
+-	// if hardware conversions are not enabled, then quit
++	/*  if hardware conversions are not enabled, then quit */
+ 	comedi_spin_lock_irqsave(&dev->spinlock, irq_flags);
+ 	outb(CONTROL1, dev->iobase + DAS800_GAIN);	/* select base address + 7 to be STATUS2 register */
+ 	status = inb(dev->iobase + DAS800_STATUS2) & STATUS2_HCEN;
+@@ -390,7 +390,7 @@ static irqreturn_t das800_interrupt(int irq, void *d)
+ 			if (fifo_overflow)
+ 				break;
+ 		} else {
+-			fifo_empty = 0;	// cio-das802/16 has no fifo empty status bit
++			fifo_empty = 0;	/*  cio-das802/16 has no fifo empty status bit */
+ 		}
+ 		if (fifo_empty) {
+ 			break;
+@@ -410,7 +410,7 @@ static irqreturn_t das800_interrupt(int irq, void *d)
+ 	/* check for fifo overflow */
+ 	if (thisboard->resolution == 12) {
+ 		fifo_overflow = dataPoint & FIFO_OVF;
+-		// else cio-das802/16
++		/*  else cio-das802/16 */
+ 	} else {
+ 		fifo_overflow = inb(dev->iobase + DAS800_GAIN) & CIO_FFOV;
+ 	}
+@@ -564,7 +564,7 @@ static void enable_das800(struct comedi_device * dev)
+ {
+ 	unsigned long irq_flags;
+ 	comedi_spin_lock_irqsave(&dev->spinlock, irq_flags);
+-	// enable fifo-half full interrupts for cio-das802/16
++	/*  enable fifo-half full interrupts for cio-das802/16 */
+ 	if (thisboard->resolution == 16)
+ 		outb(CIO_ENHF, dev->iobase + DAS800_GAIN);
+ 	outb(CONV_CONTROL, dev->iobase + DAS800_GAIN);	/* select dev->iobase + 2 to be conversion control register */
+@@ -684,7 +684,7 @@ static int das800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subdev
+ 	if (err)
+ 		return 4;
+ 
+-	// check channel/gain list against card's limitations
++	/*  check channel/gain list against card's limitations */
+ 	if (cmd->chanlist) {
+ 		gain = CR_RANGE(cmd->chanlist[0]);
+ 		startChan = CR_CHAN(cmd->chanlist[0]);
+@@ -861,7 +861,7 @@ static int das800_do_wbits(struct comedi_device * dev, struct comedi_subdevice *
+ 	int wbits;
+ 	unsigned long irq_flags;
+ 
+-	// only set bits that have been masked
++	/*  only set bits that have been masked */
+ 	data[0] &= 0xf;
+ 	wbits = devpriv->do_bits >> 4;
+ 	wbits &= ~data[0];
+diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
+index 101c22f1d247..d627479ff71a 100644
+--- a/drivers/staging/comedi/drivers/dmm32at.c
++++ b/drivers/staging/comedi/drivers/dmm32at.c
+@@ -394,7 +394,7 @@ static int dmm32at_attach(struct comedi_device * dev, struct comedi_devconfig *
+  * it is, this is the place to do it.  Otherwise, dev->board_ptr
+  * should already be initialized.
+  */
+-	//dev->board_ptr = dmm32at_probe(dev);
++	/* dev->board_ptr = dmm32at_probe(dev); */
+ 
+ /*
+  * Initialize dev->board_name.  Note that we can use the "thisboard"
+@@ -512,7 +512,7 @@ static int dmm32at_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice
+ 	chan = CR_CHAN(insn->chanspec) & (s->n_chan - 1);
+ 	range = CR_RANGE(insn->chanspec);
+ 
+-	//printk("channel=0x%02x, range=%d\n",chan,range);
++	/* printk("channel=0x%02x, range=%d\n",chan,range); */
+ 
+ 	/* zero scan and fifo control and reset fifo */
+ 	dmm_outb(dev, DMM32AT_FIFOCNTRL, DMM32AT_FIFORESET);
+@@ -575,7 +575,7 @@ static int dmm32at_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevic
+ 	int tmp;
+ 	int start_chan, gain, i;
+ 
+-	//printk("dmmat32 in command test\n");
++	/* printk("dmmat32 in command test\n"); */
+ 
+ 	/* cmdtest tests a particular command to see if it is valid.
+ 	 * Using the cmdtest ioctl, a user can create a valid cmd
+@@ -910,7 +910,7 @@ static int dmm32at_ao_winsn(struct comedi_device * dev, struct comedi_subdevice
+ 		lo = data[i] & 0x00ff;
+ 		/* high byte also contains channel number */
+ 		hi = (data[i] >> 8) + chan * (1 << 6);
+-		//printk("writing 0x%02x  0x%02x\n",hi,lo);
++		/* printk("writing 0x%02x  0x%02x\n",hi,lo); */
+ 		/* write the low and high values to the board */
+ 		dmm_outb(dev, DMM32AT_DACLSB, lo);
+ 		dmm_outb(dev, DMM32AT_DACMSB, hi);
+@@ -967,7 +967,7 @@ static int dmm32at_dio_insn_bits(struct comedi_device * dev, struct comedi_subde
+ 		s->state &= ~data[0];
+ 		s->state |= data[0] & data[1];
+ 		/* Write out the new digital output lines */
+-		//outw(s->state,dev->iobase + DMM32AT_DIO);
++		/* outw(s->state,dev->iobase + DMM32AT_DIO); */
+ 	}
+ 
+ 	/* get access to the DIO regs */
+@@ -998,10 +998,10 @@ static int dmm32at_dio_insn_bits(struct comedi_device * dev, struct comedi_subde
+ 
+ 	/* on return, data[1] contains the value of the digital
+ 	 * input and output lines. */
+-	//data[1]=inw(dev->iobase + DMM32AT_DIO);
++	/* data[1]=inw(dev->iobase + DMM32AT_DIO); */
+ 	/* or we could just return the software copy of the output values if
+ 	 * it was a purely digital output subdevice */
+-	//data[1]=s->state;
++	/* data[1]=s->state; */
+ 
+ 	return 2;
+ }
+diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c
+index 5e0eed835d1a..c3b927dc8886 100644
+--- a/drivers/staging/comedi/drivers/dt2801.c
++++ b/drivers/staging/comedi/drivers/dt2801.c
+@@ -100,7 +100,7 @@ static struct comedi_driver driver_dt2801 = {
+ COMEDI_INITCLEANUP(driver_dt2801);
+ 
+ #if 0
+-// ignore 'defined but not used' warning
++/* ignore 'defined but not used' warning */
+ static const struct comedi_lrange range_dt2801_ai_pgh_bipolar = { 4, {
+ 			RANGE(-10, 10),
+ 			RANGE(-5, 5),
+@@ -118,7 +118,7 @@ static const struct comedi_lrange range_dt2801_ai_pgl_bipolar = { 4, {
+ };
+ 
+ #if 0
+-// ignore 'defined but not used' warning
++/* ignore 'defined but not used' warning */
+ static const struct comedi_lrange range_dt2801_ai_pgh_unipolar = { 4, {
+ 			RANGE(0, 10),
+ 			RANGE(0, 5),
+@@ -381,10 +381,10 @@ static int dt2801_reset(struct comedi_device * dev)
+ 	inb_p(dev->iobase + DT2801_DATA);
+ 
+ 	DPRINTK("dt2801: stop\n");
+-	//dt2801_writecmd(dev,DT_C_STOP);
++	/* dt2801_writecmd(dev,DT_C_STOP); */
+ 	outb_p(DT_C_STOP, dev->iobase + DT2801_CMD);
+ 
+-	//dt2801_wait_for_ready(dev);
++	/* dt2801_wait_for_ready(dev); */
+ 	comedi_udelay(100);
+ 	timeout = 10000;
+ 	do {
+@@ -395,12 +395,13 @@ static int dt2801_reset(struct comedi_device * dev)
+ 	if (!timeout) {
+ 		printk("dt2801: timeout 1 status=0x%02x\n", stat);
+ 	}
+-	//printk("dt2801: reading dummy\n");
+-	//dt2801_readdata(dev,&board_code);
++
++	/* printk("dt2801: reading dummy\n"); */
++	/* dt2801_readdata(dev,&board_code); */
+ 
+ 	DPRINTK("dt2801: reset\n");
+ 	outb_p(DT_C_RESET, dev->iobase + DT2801_CMD);
+-	//dt2801_writecmd(dev,DT_C_RESET);
++	/* dt2801_writecmd(dev,DT_C_RESET); */
+ 
+ 	comedi_udelay(100);
+ 	timeout = 10000;
+diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c
+index 957cde606853..c6908075ab04 100644
+--- a/drivers/staging/comedi/drivers/dt2811.c
++++ b/drivers/staging/comedi/drivers/dt2811.c
+@@ -313,9 +313,10 @@ static irqreturn_t dt2811_interrupt(int irq, void *d)
+ 
+ static int dt2811_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+-	//int i, irq;
+-	//unsigned long irqs;
+-	//long flags;
++	/* int i, irq; */
++	/* unsigned long irqs; */
++	/* long flags; */
++
+ 	int ret;
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+@@ -531,7 +532,7 @@ int dt2811_adtrig(kdev_t minor, comedi_adtrig * adtrig)
+ 	case COMEDI_MDEMAND:
+ 		dev->ntrig = adtrig->n - 1;
+ 		/*printk("dt2811: AD soft trigger\n"); */
+-		/*outb(DT2811_CLRERROR|DT2811_INTENB,dev->iobase+DT2811_ADCSR); *//* not neccessary */
++		/*outb(DT2811_CLRERROR|DT2811_INTENB,dev->iobase+DT2811_ADCSR); */ /* not neccessary */
+ 		outb(dev->curadchan, dev->iobase + DT2811_ADGCR);
+ 		do_gettimeofday(&trigtime);
+ 		break;
+diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
+index 26ab3ba44198..dabc09705048 100644
+--- a/drivers/staging/comedi/drivers/dt3000.c
++++ b/drivers/staging/comedi/drivers/dt3000.c
+@@ -345,8 +345,8 @@ static void dt3k_writesingle(struct comedi_device * dev, unsigned int subsys,
+ 
+ static int debug_n_ints = 0;
+ 
+-// FIXME! Assumes shared interrupt is for this card.
+-// What's this debug_n_ints stuff? Obviously needs some work...
++/* FIXME! Assumes shared interrupt is for this card. */
++/* What's this debug_n_ints stuff? Obviously needs some work... */
+ static irqreturn_t dt3k_interrupt(int irq, void *d)
+ {
+ 	struct comedi_device *dev = d;
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
+index a3c887f3b2c6..ec5d9184f6a1 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -194,7 +194,7 @@ static void set_transforms(volatile struct jr3_channel *channel,
+ {
+ 	int i;
+ 
+-	num &= 0x000f;		// Make sure that 0 <= num <= 15
++	num &= 0x000f;		/*  Make sure that 0 <= num <= 15 */
+ 	for (i = 0; i < 8; i++) {
+ 
+ 		set_u16(&channel->transforms[num].link[i].link_type,
+@@ -410,10 +410,10 @@ int read_idm_word(const u8 * data, size_t size, int *pos, unsigned int *val)
+ {
+ 	int result = 0;
+ 	if (pos != 0 && val != 0) {
+-		// Skip over non hex
++		/*  Skip over non hex */
+ 		for (; *pos < size && !isxdigit(data[*pos]); (*pos)++) {
+ 		}
+-		// Collect value
++		/*  Collect value */
+ 		*val = 0;
+ 		for (; *pos < size && isxdigit(data[*pos]); (*pos)++) {
+ 			char ch = tolower(data[*pos]);
+@@ -485,17 +485,17 @@ static int jr3_download_firmware(struct comedi_device * dev, const u8 * data,
+ 					count, addr);
+ 				while (more && count > 0) {
+ 					if (addr & 0x4000) {
+-						// 16 bit data, never seen in real life!!
++						/*  16 bit data, never seen in real life!! */
+ 						unsigned int data1;
+ 
+ 						more = more
+ 							&& read_idm_word(data,
+ 							size, &pos, &data1);
+ 						count--;
+-						// printk("jr3_data, not tested\n");
+-						//        jr3[addr + 0x20000 * pnum] = data1;
++						/* printk("jr3_data, not tested\n"); */
++						/* jr3[addr + 0x20000 * pnum] = data1; */
+ 					} else {
+-						//  Download 24 bit program
++						/*   Download 24 bit program */
+ 						unsigned int data1, data2;
+ 
+ 						more = more
+@@ -541,7 +541,7 @@ static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice * s)
+ 			p->errors = errors;
+ 		}
+ 		if (errors & (watch_dog | watch_dog2 | sensor_change)) {
+-			// Sensor communication lost, force poll mode
++			/*  Sensor communication lost, force poll mode */
+ 			p->state = state_jr3_poll;
+ 
+ 		}
+@@ -551,9 +551,10 @@ static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice * s)
+ 				u16 serial_no = get_u16(&channel->serial_no);
+ 				if ((errors & (watch_dog | watch_dog2)) ||
+ 					model_no == 0 || serial_no == 0) {
+-					// Still no sensor, keep on polling. Since it takes up to
+-					// 10 seconds for offsets to stabilize, polling each
+-					// second should suffice.
++/*
++ * Still no sensor, keep on polling. Since it takes up to 10 seconds
++ * for offsets to stabilize, polling each second should suffice.
++ */
+ 					result = poll_delay_min_max(1000, 2000);
+ 				} else {
+ 					p->retries = 0;
+@@ -566,7 +567,7 @@ static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice * s)
+ 		case state_jr3_init_wait_for_offset:{
+ 				p->retries++;
+ 				if (p->retries < 10) {
+-					// Wait for offeset to stabilize (< 10 s according to manual)
++					/*  Wait for offeset to stabilize (< 10 s according to manual) */
+ 					result = poll_delay_min_max(1000, 2000);
+ 				} else {
+ 					struct transform_t transf;
+@@ -582,7 +583,7 @@ static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice * s)
+ 					printk("Sensor Serial    = %i\n",
+ 						p->serial_no);
+ 
+-					// Transformation all zeros
++					/*  Transformation all zeros */
+ 					transf.link[0].link_type =
+ 						(enum link_types)0;
+ 					transf.link[0].link_amount = 0;
+@@ -600,7 +601,7 @@ static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice * s)
+ 					use_transform(channel, 0);
+ 					p->state =
+ 						state_jr3_init_transform_complete;
+-					result = poll_delay_min_max(20, 100);	// Allow 20 ms for completion
++					result = poll_delay_min_max(20, 100);	/*  Allow 20 ms for completion */
+ 				}
+ 			} break;
+ 		case state_jr3_init_transform_complete:{
+@@ -608,7 +609,7 @@ static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice * s)
+ 					printk("state_jr3_init_transform_complete complete = %d\n", is_complete(channel));
+ 					result = poll_delay_min_max(20, 100);
+ 				} else {
+-					// Set full scale
++					/*  Set full scale */
+ 					struct six_axis_t min_full_scale;
+ 					struct six_axis_t max_full_scale;
+ 
+@@ -639,7 +640,7 @@ static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice * s)
+ 
+ 					p->state =
+ 						state_jr3_init_set_full_scale_complete;
+-					result = poll_delay_min_max(20, 100);	// Allow 20 ms for completion
++					result = poll_delay_min_max(20, 100);	/*  Allow 20 ms for completion */
+ 				}
+ 			}
+ 			break;
+@@ -650,7 +651,7 @@ static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice * s)
+ 				} else {
+ 					volatile struct force_array *full_scale;
+ 
+-					// Use ranges in kN or we will overflow arount 2000N!
++					/*  Use ranges in kN or we will overflow arount 2000N! */
+ 					full_scale = &channel->full_scale;
+ 					p->range[0].range.min =
+ 						-get_s16(&full_scale->fx) *
+@@ -679,10 +680,10 @@ static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice * s)
+ 						-get_s16(&full_scale->mz) * 100;
+ 					p->range[5].range.max =
+ 						get_s16(&full_scale->mz) * 100;
+-					p->range[6].range.min = -get_s16(&full_scale->v1) * 100;	// ??
+-					p->range[6].range.max = get_s16(&full_scale->v1) * 100;	// ??
+-					p->range[7].range.min = -get_s16(&full_scale->v2) * 100;	// ??
+-					p->range[7].range.max = get_s16(&full_scale->v2) * 100;	// ??
++					p->range[6].range.min = -get_s16(&full_scale->v1) * 100;	/*  ?? */
++					p->range[6].range.max = get_s16(&full_scale->v1) * 100;	/*  ?? */
++					p->range[7].range.min = -get_s16(&full_scale->v2) * 100;	/*  ?? */
++					p->range[7].range.max = get_s16(&full_scale->v2) * 100;	/*  ?? */
+ 					p->range[8].range.min = 0;
+ 					p->range[8].range.max = 65535;
+ 
+@@ -701,7 +702,7 @@ static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice * s)
+ 					use_offset(channel, 0);
+ 					p->state =
+ 						state_jr3_init_use_offset_complete;
+-					result = poll_delay_min_max(40, 100);	// Allow 40 ms for completion
++					result = poll_delay_min_max(40, 100);	/*  Allow 40 ms for completion */
+ 				}
+ 			}
+ 			break;
+@@ -750,7 +751,7 @@ static void jr3_pci_poll_dev(unsigned long data)
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 	delay = 1000;
+ 	now = jiffies;
+-	// Poll all channels that are ready to be polled
++	/*  Poll all channels that are ready to be polled */
+ 	for (i = 0; i < devpriv->n_channels; i++) {
+ 		struct jr3_pci_subdev_private *subdevpriv = dev->subdevices[i].private;
+ 		if (now > subdevpriv->next_time_min) {
+@@ -762,8 +763,10 @@ static void jr3_pci_poll_dev(unsigned long data)
+ 			subdevpriv->next_time_max =
+ 				jiffies + msecs_to_jiffies(sub_delay.max);
+ 			if (sub_delay.max && sub_delay.max < delay) {
+-				// Wake up as late as possible -> poll as many channels as
+-				// possible at once
++/*
++* Wake up as late as possible -> poll as many channels as possible
++* at once
++*/
+ 				delay = sub_delay.max;
+ 			}
+ 		}
+@@ -895,7 +898,7 @@ static int jr3_pci_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 				(struct comedi_lrange *) & p->range[8];
+ 			p->maxdata_list[56] = 0xffff;
+ 			p->maxdata_list[57] = 0xffff;
+-			// Channel specific range and maxdata
++			/*  Channel specific range and maxdata */
+ 			dev->subdevices[i].range_table = 0;
+ 			dev->subdevices[i].range_table_list =
+ 				p->range_table_list;
+@@ -904,7 +907,7 @@ static int jr3_pci_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 		}
+ 	}
+ 
+-	// Reset DSP card
++	/*  Reset DSP card */
+ 	devpriv->iobase->channel[0].reset = 0;
+ 
+ 	result = comedi_load_firmware(dev, "jr3pci.idm", jr3_download_firmware);
+@@ -913,13 +916,18 @@ static int jr3_pci_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	if (result < 0) {
+ 		goto out;
+ 	}
+-	// TODO: use firmware to load preferred offset tables. Suggested format:
+-	// model serial Fx Fy Fz Mx My Mz\n
+-	//
+-	// comedi_load_firmware(dev, "jr3_offsets_table", jr3_download_firmware);
++/*
++ * TODO: use firmware to load preferred offset tables. Suggested
++ * format:
++ *     model serial Fx Fy Fz Mx My Mz\n
++ *
++ *     comedi_load_firmware(dev, "jr3_offsets_table", jr3_download_firmware);
++ */
+ 
+-	// It takes a few milliseconds for software to settle
+-	// as much as we can read firmware version
++/*
++ * It takes a few milliseconds for software to settle as much as we
++ * can read firmware version
++ */
+ 	msleep_interruptible(25);
+ 	for (i = 0; i < 0x18; i++) {
+ 		printk("%c",
+@@ -927,7 +935,7 @@ static int jr3_pci_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 				copyright[i]) >> 8);
+ 	}
+ 
+-	// Start card timer
++	/*  Start card timer */
+ 	for (i = 0; i < devpriv->n_channels; i++) {
+ 		struct jr3_pci_subdev_private *p = dev->subdevices[i].private;
+ 
+diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c
+index 79f6fe5646c5..e72845767068 100644
+--- a/drivers/staging/comedi/drivers/ke_counter.c
++++ b/drivers/staging/comedi/drivers/ke_counter.c
+@@ -227,10 +227,10 @@ static int cnt_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ 	subdevice->insn_read = cnt_rinsn;
+ 	subdevice->insn_write = cnt_winsn;
+ 
+-	// select 20MHz clock
++	/*  select 20MHz clock */
+ 	outb(3, dev->iobase + 248);
+ 
+-	// reset all counters
++	/*  reset all counters */
+ 	outb(0, dev->iobase);
+ 	outb(0, dev->iobase + 0x20);
+ 	outb(0, dev->iobase + 0x40);
+diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
+index b32833eaae1e..d7c7c0f6be8b 100644
+--- a/drivers/staging/comedi/drivers/ni_6527.c
++++ b/drivers/staging/comedi/drivers/ni_6527.c
+@@ -311,7 +311,7 @@ static int ni6527_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevi
+ 
+ static int ni6527_intr_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	//struct comedi_cmd *cmd = &s->async->cmd;
++	/* struct comedi_cmd *cmd = &s->async->cmd; */
+ 
+ 	writeb(ClrEdge | ClrOverflow,
+ 		devpriv->mite->daq_io_addr + Clear_Register);
+diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
+index 97b9be331285..60dfec593330 100644
+--- a/drivers/staging/comedi/drivers/ni_65xx.c
++++ b/drivers/staging/comedi/drivers/ni_65xx.c
+@@ -437,12 +437,12 @@ static int ni_65xx_dio_insn_bits(struct comedi_device * dev, struct comedi_subde
+ 			writeb(bits,
+ 				private(dev)->mite->daq_io_addr +
+ 				Port_Data(port));
+-//                      rt_printk("wrote 0x%x to port %i\n", bits, port);
++/* rt_printk("wrote 0x%x to port %i\n", bits, port); */
+ 		}
+ 		port_read_bits =
+ 			readb(private(dev)->mite->daq_io_addr +
+ 			Port_Data(port));
+-//              rt_printk("read 0x%x from port %i\n", port_read_bits, port);
++/* rt_printk("read 0x%x from port %i\n", port_read_bits, port); */
+ 		if (bitshift > 0) {
+ 			port_read_bits <<= bitshift;
+ 		} else {
+@@ -553,7 +553,7 @@ static int ni_65xx_intr_cmdtest(struct comedi_device * dev, struct comedi_subdev
+ 
+ static int ni_65xx_intr_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	//struct comedi_cmd *cmd = &s->async->cmd;
++	/* struct comedi_cmd *cmd = &s->async->cmd; */
+ 
+ 	writeb(ClrEdge | ClrOverflow,
+ 		private(dev)->mite->daq_io_addr + Clear_Register);
+@@ -700,7 +700,7 @@ static int ni_65xx_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 			return -ENOMEM;
+ 		sprivate(s)->base_port = 0;
+ 		for (i = 0; i < board(dev)->num_dio_ports; ++i) {
+-			// configure all ports for input
++			/*  configure all ports for input */
+ 			writeb(0x1,
+ 				private(dev)->mite->daq_io_addr +
+ 				Port_Select(i));
+diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
+index b75ea44c3307..377a78afc1eb 100644
+--- a/drivers/staging/comedi/drivers/ni_660x.c
++++ b/drivers/staging/comedi/drivers/ni_660x.c
+@@ -51,7 +51,7 @@ enum ni_660x_constants {
+ };
+ 
+ #define NUM_PFI_CHANNELS 40
+-// really there are only up to 3 dma channels, but the register layout allows for 4
++/* really there are only up to 3 dma channels, but the register layout allows for 4 */
+ #define MAX_DMA_CHANNEL 4
+ 
+ /* See Register-Level Programmer Manual page 3.1 */
+@@ -194,10 +194,10 @@ static inline unsigned NI_660X_GPCT_SUBDEV(unsigned index)
+ 
+ struct NI_660xRegisterData {
+ 
+-	const char *name;	// Register Name
+-	int offset;		// Offset from base address from GPCT chip
++	const char *name;	/*  Register Name */
++	int offset;		/*  Offset from base address from GPCT chip */
+ 	enum ni_660x_register_direction direction;
+-	enum ni_660x_register_width size;	// 1 byte, 2 bytes, or 4 bytes
++	enum ni_660x_register_width size;	/*  1 byte, 2 bytes, or 4 bytes */
+ };
+ 
+ 
+@@ -302,12 +302,12 @@ static const struct NI_660xRegisterData registerData[NumRegisters] = {
+ 	{"IO Config Register 38-39", 0x7A2, NI_660x_READ_WRITE, DATA_2B}
+ };
+ 
+-// kind of ENABLE for the second counter
++/* kind of ENABLE for the second counter */
+ enum clock_config_register_bits {
+ 	CounterSwap = 0x1 << 21
+ };
+ 
+-// ioconfigreg
++/* ioconfigreg */
+ static inline unsigned ioconfig_bitshift(unsigned pfi_channel)
+ {
+ 	if (pfi_channel % 2)
+@@ -334,7 +334,7 @@ static inline unsigned pfi_input_select_bits(unsigned pfi_channel,
+ 	return (input_select & 0x7) << (4 + ioconfig_bitshift(pfi_channel));
+ }
+ 
+-// dma configuration register bits
++/* dma configuration register bits */
+ static inline unsigned dma_select_mask(unsigned dma_channel)
+ {
+ 	BUG_ON(dma_channel >= MAX_DMA_CHANNEL);
+@@ -374,7 +374,7 @@ enum global_interrupt_config_register_bits {
+ 	Global_Int_Enable_Bit = 0x80000000
+ };
+ 
+-// Offset of the GPCT chips from the base-adress of the card
++/* Offset of the GPCT chips from the base-adress of the card */
+ static const unsigned GPCT_OFFSET[2] = { 0x0, 0x800 };	/* First chip is at base-address +
+ 							   0x00, etc. */
+ 
+@@ -850,7 +850,7 @@ static int ni_660x_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	int retval;
+ 
+ 	struct ni_gpct *counter = subdev_to_counter(s);
+-//      const struct comedi_cmd *cmd = &s->async->cmd;
++/* const struct comedi_cmd *cmd = &s->async->cmd; */
+ 
+ 	retval = ni_660x_request_mite_channel(dev, counter, COMEDI_INPUT);
+ 	if (retval) {
+@@ -1031,7 +1031,7 @@ static int ni_660x_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	s->insn_bits = ni_660x_dio_insn_bits;
+ 	s->insn_config = ni_660x_dio_insn_config;
+ 	s->io_bits = 0;		/* all bits default to input */
+-	// we use the ioconfig registers to control dio direction, so zero output enables in stc dio control reg
++	/*  we use the ioconfig registers to control dio direction, so zero output enables in stc dio control reg */
+ 	ni_660x_write_register(dev, 0, 0, STCDIOControl);
+ 
+ 	private(dev)->counter_dev = ni_gpct_device_construct(dev,
+@@ -1132,7 +1132,7 @@ static void init_tio_chip(struct comedi_device * dev, int chipset)
+ {
+ 	unsigned i;
+ 
+-	// init dma configuration register
++	/*  init dma configuration register */
+ 	private(dev)->dma_configuration_soft_copies[chipset] = 0;
+ 	for (i = 0; i < MAX_DMA_CHANNEL; ++i) {
+ 		private(dev)->dma_configuration_soft_copies[chipset] |=
+@@ -1193,7 +1193,7 @@ static int ni_660x_dio_insn_bits(struct comedi_device * dev,
+ {
+ 	unsigned base_bitfield_channel = CR_CHAN(insn->chanspec);
+ 
+-	// Check if we have to write some bits
++	/*  Check if we have to write some bits */
+ 	if (data[0]) {
+ 		s->state &= ~(data[0] << base_bitfield_channel);
+ 		s->state |= (data[0] & data[1]) << base_bitfield_channel;
+diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
+index d1312e073a65..05dcc5ba255c 100644
+--- a/drivers/staging/comedi/drivers/ni_670x.c
++++ b/drivers/staging/comedi/drivers/ni_670x.c
+@@ -91,7 +91,7 @@ static const struct ni_670x_board ni_670x_boards[] = {
+ static DEFINE_PCI_DEVICE_TABLE(ni_670x_pci_table) = {
+ 	{PCI_VENDOR_ID_NATINST, 0x2c90, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ 	{PCI_VENDOR_ID_NATINST, 0x1920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+-	//{ PCI_VENDOR_ID_NATINST, 0x0000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
++	/* { PCI_VENDOR_ID_NATINST, 0x0000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, */
+ 	{0}
+ };
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c
+index 2cc46b672588..089fb428b411 100644
+--- a/drivers/staging/comedi/drivers/ni_at_ao.c
++++ b/drivers/staging/comedi/drivers/ni_at_ao.c
+@@ -229,7 +229,7 @@ static int atao_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ 	}
+ 	dev->iobase = iobase;
+ 
+-	//dev->board_ptr = atao_probe(dev);
++	/* dev->board_ptr = atao_probe(dev); */
+ 
+ 	dev->board_name = thisboard->name;
+ 
+@@ -273,7 +273,7 @@ static int atao_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ 
+ 	s = dev->subdevices + 3;
+ 	/* eeprom subdevice */
+-	//s->type=COMEDI_SUBD_EEPROM;
++	/* s->type=COMEDI_SUBD_EEPROM; */
+ 	s->type = COMEDI_SUBD_UNUSED;
+ 
+ 	atao_reset(dev);
+diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
+index e83784496aef..44b67ec86c3a 100644
+--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
++++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
+@@ -262,7 +262,7 @@ static irqreturn_t atmio16d_interrupt(int irq, void *d)
+ 	struct comedi_device *dev = d;
+ 	struct comedi_subdevice *s = dev->subdevices + 0;
+ 
+-//      printk("atmio16d_interrupt!\n");
++/* printk("atmio16d_interrupt!\n"); */
+ 
+ 	comedi_buf_put(s->async, inw(dev->iobase + AD_FIFO_REG));
+ 
+@@ -542,9 +542,9 @@ static int atmio16d_ai_insn_read(struct comedi_device * dev, struct comedi_subde
+ 	gain = CR_RANGE(insn->chanspec);
+ 
+ 	/* reset the Analog input circuitry */
+-	//outw( 0, dev->iobase+AD_CLEAR_REG );
++	/* outw( 0, dev->iobase+AD_CLEAR_REG ); */
+ 	/* reset the Analog Input MUX Counter to 0 */
+-	//outw( 0, dev->iobase+MUX_CNTR_REG );
++	/* outw( 0, dev->iobase+MUX_CNTR_REG ); */
+ 
+ 	/* set the Input MUX gain */
+ 	outw(chan | (gain << 6), dev->iobase + MUX_GAIN_REG);
+diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
+index 61a31ad2d030..cbefda8e9de4 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_700.c
++++ b/drivers/staging/comedi/drivers/ni_daq_700.c
+@@ -53,7 +53,7 @@ IRQ is assigned but not used.
+ 
+ static struct pcmcia_device *pcmcia_cur_dev = NULL;
+ 
+-#define DIO700_SIZE 8		// size of io region used by board
++#define DIO700_SIZE 8		/*  size of io region used by board */
+ 
+ static int dio700_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int dio700_detach(struct comedi_device * dev);
+@@ -62,11 +62,11 @@ enum dio700_bustype { pcmcia_bustype };
+ 
+ struct dio700_board {
+ 	const char *name;
+-	int device_id;		// device id for pcmcia board
+-	enum dio700_bustype bustype;	// PCMCIA
+-	int have_dio;		// have daqcard-700 dio
+-	// function pointers so we can use inb/outb or readb/writeb
+-	// as appropriate
++	int device_id;		/*  device id for pcmcia board */
++	enum dio700_bustype bustype;	/*  PCMCIA */
++	int have_dio;		/*  have daqcard-700 dio */
++	/*  function pointers so we can use inb/outb or readb/writeb */
++	/*  as appropriate */
+ 	unsigned int (*read_byte) (unsigned int address);
+ 	void (*write_byte) (unsigned int byte, unsigned int address);
+ };
+@@ -74,13 +74,13 @@ struct dio700_board {
+ static const struct dio700_board dio700_boards[] = {
+ 	{
+ 	      name:	"daqcard-700",
+-	      device_id:0x4743,// 0x10b is manufacturer id, 0x4743 is device id
++	      device_id:0x4743,/*  0x10b is manufacturer id, 0x4743 is device id */
+ 	      bustype:	pcmcia_bustype,
+ 	      have_dio:1,
+ 		},
+ 	{
+ 	      name:	"ni_daq_700",
+-	      device_id:0x4743,// 0x10b is manufacturer id, 0x4743 is device id
++	      device_id:0x4743,/*  0x10b is manufacturer id, 0x4743 is device id */
+ 	      bustype:	pcmcia_bustype,
+ 	      have_dio:1,
+ 		},
+@@ -365,7 +365,7 @@ static int dio700_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	if (alloc_private(dev, sizeof(struct dio700_private)) < 0)
+ 		return -ENOMEM;
+ 
+-	// get base address, irq etc. based on bustype
++	/*  get base address, irq etc. based on bustype */
+ 	switch (thisboard->bustype) {
+ 	case pcmcia_bustype:
+ 		link = pcmcia_cur_dev;	/* XXX hack */
+@@ -430,7 +430,7 @@ static int dio700_detach(struct comedi_device * dev)
+ 	return 0;
+ };
+ 
+-// PCMCIA crap
++/* PCMCIA crap */
+ 
+ /*
+    All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If
+diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
+index 38ba49ec1def..4be9deffbcfd 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
++++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
+@@ -37,7 +37,7 @@ This is just a wrapper around the 8255.o driver to properly handle
+ the PCMCIA interface.
+ */
+ 
+-//#define LABPC_DEBUG   // enable debugging messages
++/* #define LABPC_DEBUG   /*  enable debugging messages */ */
+ #undef LABPC_DEBUG
+ 
+ #include "../comedidev.h"
+@@ -54,7 +54,7 @@ the PCMCIA interface.
+ 
+ static struct pcmcia_device *pcmcia_cur_dev = NULL;
+ 
+-#define DIO24_SIZE 4		// size of io region used by board
++#define DIO24_SIZE 4		/*  size of io region used by board */
+ 
+ static int dio24_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int dio24_detach(struct comedi_device * dev);
+@@ -63,10 +63,10 @@ enum dio24_bustype { pcmcia_bustype };
+ 
+ struct dio24_board_struct {
+ 	const char *name;
+-	int device_id;		// device id for pcmcia board
+-	enum dio24_bustype bustype;	// PCMCIA
+-	int have_dio;		// have 8255 chip
+-	// function pointers so we can use inb/outb or readb/writeb as appropriate
++	int device_id;		/*  device id for pcmcia board */
++	enum dio24_bustype bustype;	/*  PCMCIA */
++	int have_dio;		/*  have 8255 chip */
++	/*  function pointers so we can use inb/outb or readb/writeb as appropriate */
+ 	unsigned int (*read_byte) (unsigned int address);
+ 	void (*write_byte) (unsigned int byte, unsigned int address);
+ };
+@@ -74,13 +74,13 @@ struct dio24_board_struct {
+ static const struct dio24_board_struct dio24_boards[] = {
+ 	{
+ 	      name:	"daqcard-dio24",
+-	      device_id:0x475c,// 0x10b is manufacturer id, 0x475c is device id
++	      device_id:0x475c,/*  0x10b is manufacturer id, 0x475c is device id */
+ 	      bustype:	pcmcia_bustype,
+ 	      have_dio:1,
+ 		},
+ 	{
+ 	      name:	"ni_daq_dio24",
+-	      device_id:0x475c,// 0x10b is manufacturer id, 0x475c is device id
++	      device_id:0x475c,/*  0x10b is manufacturer id, 0x475c is device id */
+ 	      bustype:	pcmcia_bustype,
+ 	      have_dio:1,
+ 		},
+@@ -122,7 +122,7 @@ static int dio24_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 	if (alloc_private(dev, sizeof(struct dio24_private)) < 0)
+ 		return -ENOMEM;
+ 
+-	// get base address, irq etc. based on bustype
++	/*  get base address, irq etc. based on bustype */
+ 	switch (thisboard->bustype) {
+ 	case pcmcia_bustype:
+ 		link = pcmcia_cur_dev;	/* XXX hack */
+@@ -187,7 +187,7 @@ static int dio24_detach(struct comedi_device * dev)
+ 	return 0;
+ };
+ 
+-// PCMCIA crap
++/* PCMCIA crap */
+ 
+ /*
+    All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If
+diff --git a/drivers/staging/comedi/drivers/ni_labpc.h b/drivers/staging/comedi/drivers/ni_labpc.h
+index 6f76db026b9b..1171ec816b61 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc.h
++++ b/drivers/staging/comedi/drivers/ni_labpc.h
+@@ -24,8 +24,8 @@
+ #ifndef _NI_LABPC_H
+ #define _NI_LABPC_H
+ 
+-#define EEPROM_SIZE	256	// 256 byte eeprom
+-#define NUM_AO_CHAN	2	// boards have two analog output channels
++#define EEPROM_SIZE	256	/*  256 byte eeprom */
++#define NUM_AO_CHAN	2	/*  boards have two analog output channels */
+ 
+ enum labpc_bustype { isa_bustype, pci_bustype, pcmcia_bustype };
+ enum labpc_register_layout { labpc_plus_layout, labpc_1200_layout };
+@@ -34,42 +34,42 @@ enum transfer_type { fifo_not_empty_transfer, fifo_half_full_transfer,
+ 
+ struct labpc_board_struct {
+ 	const char *name;
+-	int device_id;		// device id for pci and pcmcia boards
+-	int ai_speed;		// maximum input speed in nanoseconds
+-	enum labpc_bustype bustype;	// ISA/PCI/etc.
+-	enum labpc_register_layout register_layout;	// 1200 has extra registers compared to pc+
+-	int has_ao;		// has analog output true/false
++	int device_id;		/*  device id for pci and pcmcia boards */
++	int ai_speed;		/*  maximum input speed in nanoseconds */
++	enum labpc_bustype bustype;	/*  ISA/PCI/etc. */
++	enum labpc_register_layout register_layout;	/*  1200 has extra registers compared to pc+ */
++	int has_ao;		/*  has analog output true/false */
+ 	const struct comedi_lrange *ai_range_table;
+ 	const int *ai_range_code;
+ 	const int *ai_range_is_unipolar;
+-	unsigned ai_scan_up:1;	// board can auto scan up in ai channels, not just down
++	unsigned ai_scan_up:1;	/*  board can auto scan up in ai channels, not just down */
+ 	unsigned memory_mapped_io:1;	/* uses memory mapped io instead of ioports */
+ };
+ 
+ struct labpc_private {
+-	struct mite_struct *mite;	// for mite chip on pci-1200
++	struct mite_struct *mite;	/*  for mite chip on pci-1200 */
+ 	volatile unsigned long long count;	/* number of data points left to be taken */
+-	unsigned int ao_value[NUM_AO_CHAN];	// software copy of analog output values
+-	// software copys of bits written to command registers
++	unsigned int ao_value[NUM_AO_CHAN];	/*  software copy of analog output values */
++	/*  software copys of bits written to command registers */
+ 	volatile unsigned int command1_bits;
+ 	volatile unsigned int command2_bits;
+ 	volatile unsigned int command3_bits;
+ 	volatile unsigned int command4_bits;
+ 	volatile unsigned int command5_bits;
+ 	volatile unsigned int command6_bits;
+-	// store last read of board status registers
++	/*  store last read of board status registers */
+ 	volatile unsigned int status1_bits;
+ 	volatile unsigned int status2_bits;
+ 	unsigned int divisor_a0;	/* value to load into board's counter a0 (conversion pacing) for timed conversions */
+ 	unsigned int divisor_b0;	/* value to load into board's counter b0 (master) for timed conversions */
+ 	unsigned int divisor_b1;	/* value to load into board's counter b1 (scan pacing) for timed conversions */
+-	unsigned int dma_chan;	// dma channel to use
+-	u16 *dma_buffer;	// buffer ai will dma into
+-	unsigned int dma_transfer_size;	// transfer size in bytes for current transfer
+-	enum transfer_type current_transfer;	// we are using dma/fifo-half-full/etc.
+-	unsigned int eeprom_data[EEPROM_SIZE];	// stores contents of board's eeprom
+-	unsigned int caldac[16];	// stores settings of calibration dacs
+-	// function pointers so we can use inb/outb or readb/writeb as appropriate
++	unsigned int dma_chan;	/*  dma channel to use */
++	u16 *dma_buffer;	/*  buffer ai will dma into */
++	unsigned int dma_transfer_size;	/*  transfer size in bytes for current transfer */
++	enum transfer_type current_transfer;	/*  we are using dma/fifo-half-full/etc. */
++	unsigned int eeprom_data[EEPROM_SIZE];	/*  stores contents of board's eeprom */
++	unsigned int caldac[16];	/*  stores settings of calibration dacs */
++	/*  function pointers so we can use inb/outb or readb/writeb as appropriate */
+ 	unsigned int (*read_byte) (unsigned long address);
+ 	void (*write_byte) (unsigned int byte, unsigned long address);
+ };
+diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
+index 884074ddaac8..a78a2095dd96 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
++++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
+@@ -60,7 +60,7 @@ NI manuals:
+ */
+ 
+ #undef LABPC_DEBUG
+-//#define LABPC_DEBUG   // enable debugging messages
++/* #define LABPC_DEBUG   /*  enable debugging messages */ */
+ 
+ #include "../comedidev.h"
+ 
+@@ -84,7 +84,7 @@ static int labpc_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ static const struct labpc_board_struct labpc_cs_boards[] = {
+ 	{
+ 	      name:	"daqcard-1200",
+-	      device_id:0x103,	// 0x10b is manufacturer id, 0x103 is device id
++	      device_id:0x103,	/*  0x10b is manufacturer id, 0x103 is device id */
+ 	      ai_speed:10000,
+ 	      bustype:	pcmcia_bustype,
+ 	      register_layout:labpc_1200_layout,
+@@ -136,7 +136,7 @@ static int labpc_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 	if (alloc_private(dev, sizeof(struct labpc_private)) < 0)
+ 		return -ENOMEM;
+ 
+-	// get base address, irq etc. based on bustype
++	/*  get base address, irq etc. based on bustype */
+ 	switch (thisboard->bustype) {
+ 	case pcmcia_bustype:
+ 		link = pcmcia_cur_dev;	/* XXX hack */
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index 8e9cf12f9251..dfc2f86c5a25 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -57,9 +57,9 @@
+ 		fully tested as yet. Terry Barnaby, BEAM Ltd.
+ */
+ 
+-//#define DEBUG_INTERRUPT
+-//#define DEBUG_STATUS_A
+-//#define DEBUG_STATUS_B
++/* #define DEBUG_INTERRUPT */
++/* #define DEBUG_STATUS_A */
++/* #define DEBUG_STATUS_B */
+ 
+ #include "8255.h"
+ #include "mite.h"
+@@ -410,7 +410,7 @@ static int ni_ai_drain_dma(struct comedi_device * dev);
+ 
+ /* DMA channel setup */
+ 
+-// negative channel means no channel
++/* negative channel means no channel */
+ static inline void ni_set_ai_dma_channel(struct comedi_device * dev, int channel)
+ {
+ 	unsigned bitfield;
+@@ -425,7 +425,7 @@ static inline void ni_set_ai_dma_channel(struct comedi_device * dev, int channel
+ 	ni_set_bitfield(dev, AI_AO_Select, AI_DMA_Select_Mask, bitfield);
+ }
+ 
+-// negative channel means no channel
++/* negative channel means no channel */
+ static inline void ni_set_ao_dma_channel(struct comedi_device * dev, int channel)
+ {
+ 	unsigned bitfield;
+@@ -440,7 +440,7 @@ static inline void ni_set_ao_dma_channel(struct comedi_device * dev, int channel
+ 	ni_set_bitfield(dev, AI_AO_Select, AO_DMA_Select_Mask, bitfield);
+ }
+ 
+-// negative mite_channel means no channel
++/* negative mite_channel means no channel */
+ static inline void ni_set_gpct_dma_channel(struct comedi_device * dev,
+ 	unsigned gpct_index, int mite_channel)
+ {
+@@ -455,7 +455,7 @@ static inline void ni_set_gpct_dma_channel(struct comedi_device * dev,
+ 		bitfield);
+ }
+ 
+-// negative mite_channel means no channel
++/* negative mite_channel means no channel */
+ static inline void ni_set_cdo_dma_channel(struct comedi_device * dev, int mite_channel)
+ {
+ 	unsigned long flags;
+@@ -544,7 +544,7 @@ static int ni_request_gpct_mite_channel(struct comedi_device * dev,
+ 	return 0;
+ }
+ 
+-#endif // PCIDMA
++#endif /*  PCIDMA */
+ 
+ static int ni_request_cdo_mite_channel(struct comedi_device * dev)
+ {
+@@ -565,7 +565,7 @@ static int ni_request_cdo_mite_channel(struct comedi_device * dev)
+ 	devpriv->cdo_mite_chan->dir = COMEDI_OUTPUT;
+ 	ni_set_cdo_dma_channel(dev, devpriv->cdo_mite_chan->channel);
+ 	comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
+-#endif // PCIDMA
++#endif /*  PCIDMA */
+ 	return 0;
+ }
+ 
+@@ -581,7 +581,7 @@ static void ni_release_ai_mite_channel(struct comedi_device * dev)
+ 		devpriv->ai_mite_chan = NULL;
+ 	}
+ 	comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
+-#endif // PCIDMA
++#endif /*  PCIDMA */
+ }
+ 
+ static void ni_release_ao_mite_channel(struct comedi_device * dev)
+@@ -596,7 +596,7 @@ static void ni_release_ao_mite_channel(struct comedi_device * dev)
+ 		devpriv->ao_mite_chan = NULL;
+ 	}
+ 	comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
+-#endif // PCIDMA
++#endif /*  PCIDMA */
+ }
+ 
+ void ni_release_gpct_mite_channel(struct comedi_device * dev, unsigned gpct_index)
+@@ -616,7 +616,7 @@ void ni_release_gpct_mite_channel(struct comedi_device * dev, unsigned gpct_inde
+ 		mite_release_channel(mite_chan);
+ 	}
+ 	comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
+-#endif // PCIDMA
++#endif /*  PCIDMA */
+ }
+ 
+ static void ni_release_cdo_mite_channel(struct comedi_device * dev)
+@@ -631,10 +631,10 @@ static void ni_release_cdo_mite_channel(struct comedi_device * dev)
+ 		devpriv->cdo_mite_chan = NULL;
+ 	}
+ 	comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
+-#endif // PCIDMA
++#endif /*  PCIDMA */
+ }
+ 
+-// e-series boards use the second irq signals to generate dma requests for their counters
++/* e-series boards use the second irq signals to generate dma requests for their counters */
+ #ifdef PCIDMA
+ static void ni_e_series_enable_second_irq(struct comedi_device * dev,
+ 	unsigned gpct_index, short enable)
+@@ -665,15 +665,15 @@ static void ni_e_series_enable_second_irq(struct comedi_device * dev,
+ 		break;
+ 	}
+ }
+-#endif // PCIDMA
++#endif /*  PCIDMA */
+ 
+ static void ni_clear_ai_fifo(struct comedi_device * dev)
+ {
+ 	if (boardtype.reg_type == ni_reg_6143) {
+-		// Flush the 6143 data FIFO
+-		ni_writel(0x10, AIFIFO_Control_6143);	// Flush fifo
+-		ni_writel(0x00, AIFIFO_Control_6143);	// Flush fifo
+-		while (ni_readl(AIFIFO_Status_6143) & 0x10) ;	// Wait for complete
++		/*  Flush the 6143 data FIFO */
++		ni_writel(0x10, AIFIFO_Control_6143);	/*  Flush fifo */
++		ni_writel(0x00, AIFIFO_Control_6143);	/*  Flush fifo */
++		while (ni_readl(AIFIFO_Status_6143) & 0x10) ;	/*  Wait for complete */
+ 	} else {
+ 		devpriv->stc_writew(dev, 1, ADC_FIFO_Clear);
+ 		if (boardtype.reg_type == ni_reg_625x) {
+@@ -776,9 +776,9 @@ static irqreturn_t ni_E_interrupt(int irq, void *d)
+ 
+ 	if (dev->attached == 0)
+ 		return IRQ_NONE;
+-	smp_mb();		// make sure dev->attached is checked before handler does anything else.
++	smp_mb();		/*  make sure dev->attached is checked before handler does anything else. */
+ 
+-	// lock to avoid race with comedi_poll
++	/*  lock to avoid race with comedi_poll */
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 	a_status = devpriv->stc_readw(dev, AI_Status_1_Register);
+ 	b_status = devpriv->stc_readw(dev, AO_Status_1_Register);
+@@ -867,7 +867,7 @@ static int ni_ao_wait_for_dma_load(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-#endif //PCIDMA
++#endif /* PCIDMA */
+ static void ni_handle_eos(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	if (devpriv->aimode == AIMODE_SCAN) {
+@@ -971,7 +971,7 @@ static void handle_a_interrupt(struct comedi_device * dev, unsigned short status
+ {
+ 	struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ 
+-	//67xx boards don't have ai subdevice, but their gpct0 might generate an a interrupt
++	/* 67xx boards don't have ai subdevice, but their gpct0 might generate an a interrupt */
+ 	if (s->type == COMEDI_SUBD_UNUSED)
+ 		return;
+ 
+@@ -992,9 +992,9 @@ static void handle_a_interrupt(struct comedi_device * dev, unsigned short status
+ 		rt_printk
+ 			("unknown mite interrupt, ack! (ai_mite_status=%08x)\n",
+ 			ai_mite_status);
+-		//mite_print_chsr(ai_mite_status);
++		/* mite_print_chsr(ai_mite_status); */
+ 		s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
+-		//disable_irq(dev->irq);
++		/* disable_irq(dev->irq); */
+ 	}
+ #endif
+ 
+@@ -1052,7 +1052,7 @@ static void handle_a_interrupt(struct comedi_device * dev, unsigned short status
+ 				break;
+ 		}
+ 	}
+-#endif // !PCIDMA
++#endif /*  !PCIDMA */
+ 
+ 	if ((status & AI_STOP_St)) {
+ 		ni_handle_eos(dev, s);
+@@ -1102,7 +1102,7 @@ static void handle_b_interrupt(struct comedi_device * dev, unsigned short b_stat
+ 	unsigned ao_mite_status)
+ {
+ 	struct comedi_subdevice *s = dev->subdevices + NI_AO_SUBDEV;
+-	//unsigned short ack=0;
++	/* unsigned short ack=0; */
+ #ifdef DEBUG_INTERRUPT
+ 	rt_printk("ni_mio_common: interrupt: b_status=%04x m1_status=%08x\n",
+ 		b_status, ao_mite_status);
+@@ -1121,7 +1121,7 @@ static void handle_b_interrupt(struct comedi_device * dev, unsigned short b_stat
+ 		rt_printk
+ 			("unknown mite interrupt, ack! (ao_mite_status=%08x)\n",
+ 			ao_mite_status);
+-		//mite_print_chsr(ao_mite_status);
++		/* mite_print_chsr(ao_mite_status); */
+ 		s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
+ 	}
+ #endif
+@@ -1333,7 +1333,7 @@ static void ni_ai_fifo_read(struct comedi_device * dev, struct comedi_subdevice
+ 		short data[2];
+ 		u32 dl;
+ 
+-		// This just reads the FIFO assuming the data is present, no checks on the FIFO status are performed
++		/*  This just reads the FIFO assuming the data is present, no checks on the FIFO status are performed */
+ 		for (i = 0; i < n / 2; i++) {
+ 			dl = ni_readl(AIFIFO_Data_6143);
+ 
+@@ -1343,7 +1343,7 @@ static void ni_ai_fifo_read(struct comedi_device * dev, struct comedi_subdevice
+ 		}
+ 		if (n % 2) {
+ 			/* Assume there is a single sample stuck in the FIFO */
+-			ni_writel(0x01, AIFIFO_Control_6143);	// Get stranded sample into FIFO
++			ni_writel(0x01, AIFIFO_Control_6143);	/*  Get stranded sample into FIFO */
+ 			dl = ni_readl(AIFIFO_Data_6143);
+ 			data[0] = (dl >> 16) & 0xffff;
+ 			cfc_write_to_buffer(s, data[0]);
+@@ -1444,9 +1444,9 @@ static void ni_handle_fifo_dregs(struct comedi_device * dev)
+ 			cfc_write_array_to_buffer(s, data, sizeof(data));
+ 			i += 2;
+ 		}
+-		// Check if stranded sample is present
++		/*  Check if stranded sample is present */
+ 		if (ni_readl(AIFIFO_Status_6143) & 0x01) {
+-			ni_writel(0x01, AIFIFO_Control_6143);	// Get stranded sample into FIFO
++			ni_writel(0x01, AIFIFO_Control_6143);	/*  Get stranded sample into FIFO */
+ 			dl = ni_readl(AIFIFO_Data_6143);
+ 			data[0] = (dl >> 16) & 0xffff;
+ 			cfc_write_to_buffer(s, data[0]);
+@@ -1504,7 +1504,7 @@ static void get_last_sample_6143(struct comedi_device * dev)
+ 
+ 	/* Check if there's a single sample stuck in the FIFO */
+ 	if (ni_readl(AIFIFO_Status_6143) & 0x01) {
+-		ni_writel(0x01, AIFIFO_Control_6143);	// Get stranded sample into FIFO
++		ni_writel(0x01, AIFIFO_Control_6143);	/*  Get stranded sample into FIFO */
+ 		dl = ni_readl(AIFIFO_Data_6143);
+ 
+ 		/* This may get the hi/lo data in the wrong order */
+@@ -1548,7 +1548,7 @@ static int ni_ai_setup_MITE_dma(struct comedi_device * dev)
+ 	retval = ni_request_ai_mite_channel(dev);
+ 	if (retval)
+ 		return retval;
+-//      rt_printk("comedi_debug: using mite channel %i for ai.\n", devpriv->ai_mite_chan->channel);
++/* rt_printk("comedi_debug: using mite channel %i for ai.\n", devpriv->ai_mite_chan->channel); */
+ 
+ 	/* write alloc the entire buffer */
+ 	comedi_buf_write_alloc(s->async, s->async->prealloc_bufsz);
+@@ -1609,7 +1609,7 @@ static int ni_ao_setup_MITE_dma(struct comedi_device * dev)
+ 	return retval;
+ }
+ 
+-#endif // PCIDMA
++#endif /*  PCIDMA */
+ 
+ /*
+    used for both cancel ioctl and board initialization
+@@ -1703,7 +1703,7 @@ static int ni_ai_poll(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	unsigned long flags = 0;
+ 	int count;
+ 
+-	// lock to avoid race with interrupt handler
++	/*  lock to avoid race with interrupt handler */
+ 	if (in_interrupt() == 0)
+ 		comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ #ifndef PCIDMA
+@@ -1774,7 +1774,7 @@ static int ni_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice *
+ 			dl = 0;
+ 			for (i = 0; i < NI_TIMEOUT; i++) {
+ 				if (ni_readl(AIFIFO_Status_6143) & 0x01) {
+-					ni_writel(0x01, AIFIFO_Control_6143);	// Get stranded sample into FIFO
++					ni_writel(0x01, AIFIFO_Control_6143);	/*  Get stranded sample into FIFO */
+ 					dl = ni_readl(AIFIFO_Data_6143);
+ 					break;
+ 				}
+@@ -1841,7 +1841,7 @@ static void ni_m_series_load_channelgain_list(struct comedi_device * dev,
+ 
+ 	devpriv->stc_writew(dev, 1, Configuration_Memory_Clear);
+ 
+-//      offset = 1 << (boardtype.adbits - 1);
++/* offset = 1 << (boardtype.adbits - 1); */
+ 	if ((list[0] & CR_ALT_SOURCE)) {
+ 		unsigned bypass_bits;
+ 		chan = CR_CHAN(list[0]);
+@@ -1859,7 +1859,7 @@ static void ni_m_series_load_channelgain_list(struct comedi_device * dev,
+ 		bypass_bits |= MSeries_AI_Bypass_Gain_Bits(range_code);
+ 		if (dither)
+ 			bypass_bits |= MSeries_AI_Bypass_Dither_Bit;
+-		// don't use 2's complement encoding
++		/*  don't use 2's complement encoding */
+ 		bypass_bits |= MSeries_AI_Bypass_Polarity_Bit;
+ 		ni_writel(bypass_bits, M_Offset_AI_Config_FIFO_Bypass);
+ 	} else {
+@@ -1899,7 +1899,7 @@ static void ni_m_series_load_channelgain_list(struct comedi_device * dev,
+ 			config_bits |= MSeries_AI_Config_Last_Channel_Bit;
+ 		if (dither)
+ 			config_bits |= MSeries_AI_Config_Dither_Bit;
+-		// don't use 2's complement encoding
++		/*  don't use 2's complement encoding */
+ 		config_bits |= MSeries_AI_Config_Polarity_Bit;
+ 		ni_writew(config_bits, M_Offset_AI_Config_FIFO_Data);
+ 	}
+@@ -1952,7 +1952,7 @@ static void ni_load_channelgain_list(struct comedi_device * dev, unsigned int n_
+ 		&& (boardtype.reg_type != ni_reg_6143)) {
+ 		if (devpriv->changain_state
+ 			&& devpriv->changain_spec == list[0]) {
+-			// ready to go.
++			/*  ready to go. */
+ 			return;
+ 		}
+ 		devpriv->changain_state = 1;
+@@ -1963,11 +1963,11 @@ static void ni_load_channelgain_list(struct comedi_device * dev, unsigned int n_
+ 
+ 	devpriv->stc_writew(dev, 1, Configuration_Memory_Clear);
+ 
+-	// Set up Calibration mode if required
++	/*  Set up Calibration mode if required */
+ 	if (boardtype.reg_type == ni_reg_6143) {
+ 		if ((list[0] & CR_ALT_SOURCE)
+ 			&& !devpriv->ai_calib_source_enabled) {
+-			// Strobe Relay enable bit
++			/*  Strobe Relay enable bit */
+ 			ni_writew(devpriv->
+ 				ai_calib_source |
+ 				Calibration_Channel_6143_RelayOn,
+@@ -1975,10 +1975,10 @@ static void ni_load_channelgain_list(struct comedi_device * dev, unsigned int n_
+ 			ni_writew(devpriv->ai_calib_source,
+ 				Calibration_Channel_6143);
+ 			devpriv->ai_calib_source_enabled = 1;
+-			msleep_interruptible(100);	// Allow relays to change
++			msleep_interruptible(100);	/*  Allow relays to change */
+ 		} else if (!(list[0] & CR_ALT_SOURCE)
+ 			&& devpriv->ai_calib_source_enabled) {
+-			// Strobe Relay disable bit
++			/*  Strobe Relay disable bit */
+ 			ni_writew(devpriv->
+ 				ai_calib_source |
+ 				Calibration_Channel_6143_RelayOff,
+@@ -1986,7 +1986,7 @@ static void ni_load_channelgain_list(struct comedi_device * dev, unsigned int n_
+ 			ni_writew(devpriv->ai_calib_source,
+ 				Calibration_Channel_6143);
+ 			devpriv->ai_calib_source_enabled = 0;
+-			msleep_interruptible(100);	// Allow relays to change
++			msleep_interruptible(100);	/*  Allow relays to change */
+ 		}
+ 	}
+ 
+@@ -2085,11 +2085,11 @@ static unsigned ni_min_ai_scan_period_ns(struct comedi_device * dev,
+ 	switch (boardtype.reg_type) {
+ 	case ni_reg_611x:
+ 	case ni_reg_6143:
+-		// simultaneously-sampled inputs
++		/*  simultaneously-sampled inputs */
+ 		return boardtype.ai_speed;
+ 		break;
+ 	default:
+-		// multiplexed inputs
++		/*  multiplexed inputs */
+ 		break;
+ 	};
+ 	return boardtype.ai_speed * num_channels;
+@@ -2367,10 +2367,10 @@ static int ni_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	if (cmd->chanlist_len == 1 || (boardtype.reg_type == ni_reg_611x)
+ 		|| (boardtype.reg_type == ni_reg_6143)) {
+ 		start_stop_select |= AI_STOP_Polarity;
+-		start_stop_select |= AI_STOP_Select(31);	// logic low
++		start_stop_select |= AI_STOP_Select(31);	/*  logic low */
+ 		start_stop_select |= AI_STOP_Sync;
+ 	} else {
+-		start_stop_select |= AI_STOP_Select(19);	// ai configuration memory
++		start_stop_select |= AI_STOP_Select(19);	/*  ai configuration memory */
+ 	}
+ 	devpriv->stc_writew(dev, start_stop_select,
+ 		AI_START_STOP_Select_Register);
+@@ -2381,7 +2381,7 @@ static int ni_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 		stop_count = cmd->stop_arg - 1;
+ 
+ 		if (boardtype.reg_type == ni_reg_611x) {
+-			// have to take 3 stage adc pipeline into account
++			/*  have to take 3 stage adc pipeline into account */
+ 			stop_count += num_adc_stages_611x;
+ 		}
+ 		/* stage number of scans */
+@@ -2396,7 +2396,7 @@ static int ni_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 		if (stop_count == 0) {
+ 			devpriv->ai_cmd2 |= AI_End_On_End_Of_Scan;
+ 			interrupt_a_enable |= AI_STOP_Interrupt_Enable;
+-			// this is required to get the last sample for chanlist_len > 1, not sure why
++			/*  this is required to get the last sample for chanlist_len > 1, not sure why */
+ 			if (cmd->chanlist_len > 1)
+ 				start_stop_select |=
+ 					AI_STOP_Polarity | AI_STOP_Edge;
+@@ -2440,7 +2440,7 @@ static int ni_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 		mode2 |= AI_SI_Reload_Mode(0);
+ 		/* AI_SI_Initial_Load_Source=A */
+ 		mode2 &= ~AI_SI_Initial_Load_Source;
+-		//mode2 |= AI_SC_Reload_Mode;
++		/* mode2 |= AI_SC_Reload_Mode; */
+ 		devpriv->stc_writew(dev, mode2, AI_Mode_2_Register);
+ 
+ 		/* load SI */
+@@ -2486,8 +2486,8 @@ static int ni_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 		/* AI_SI2_Load */
+ 		devpriv->stc_writew(dev, AI_SI2_Load, AI_Command_1_Register);
+ 
+-		mode2 |= AI_SI2_Reload_Mode;	// alternate
+-		mode2 |= AI_SI2_Initial_Load_Source;	// B
++		mode2 |= AI_SI2_Reload_Mode;	/*  alternate */
++		mode2 |= AI_SI2_Initial_Load_Source;	/*  B */
+ 
+ 		devpriv->stc_writew(dev, mode2, AI_Mode_2_Register);
+ 		break;
+@@ -2589,7 +2589,7 @@ static int ni_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 		if (retval)
+ 			return retval;
+ 	}
+-	//mite_dump_regs(devpriv->mite);
++	/* mite_dump_regs(devpriv->mite); */
+ #endif
+ 
+ 	switch (cmd->start_src) {
+@@ -3044,7 +3044,7 @@ static int ni_ao_inttrig(struct comedi_device * dev, struct comedi_subdevice * s
+ 			"timed out waiting for AO_TMRDACWRs_In_Progress_St to clear");
+ 		return -EIO;
+ 	}
+-	// stc manual says we are need to clear error interrupt after AO_TMRDACWRs_In_Progress_St clears
++	/*  stc manual says we are need to clear error interrupt after AO_TMRDACWRs_In_Progress_St clears */
+ 	devpriv->stc_writew(dev, AO_Error_Interrupt_Ack,
+ 		Interrupt_B_Ack_Register);
+ 
+@@ -3114,9 +3114,9 @@ static int ni_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	case TRIG_EXT:
+                 devpriv->ao_trigger_select = AO_START1_Select(CR_CHAN(cmd->start_arg)+1);
+ 		if (cmd->start_arg & CR_INVERT)
+-			devpriv->ao_trigger_select |= AO_START1_Polarity;  // 0=active high, 1=active low. see daq-stc 3-24 (p186)
++			devpriv->ao_trigger_select |= AO_START1_Polarity;  /*  0=active high, 1=active low. see daq-stc 3-24 (p186) */
+ 		if (cmd->start_arg & CR_EDGE)
+-			devpriv->ao_trigger_select |= AO_START1_Edge;      // 0=edge detection disabled, 1=enabled
++			devpriv->ao_trigger_select |= AO_START1_Edge;      /*  0=edge detection disabled, 1=enabled */
+ 		devpriv->stc_writew(dev, devpriv->ao_trigger_select, AO_Trigger_Select_Register);
+ 		break;
+ 	default:
+@@ -3141,7 +3141,7 @@ static int ni_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	case TRIG_COUNT:
+ 		if(boardtype.reg_type & ni_reg_m_series_mask)
+ 		{
+-			// this is how the NI example code does it for m-series boards, verified correct with 6259
++			/*  this is how the NI example code does it for m-series boards, verified correct with 6259 */
+ 			devpriv->stc_writel(dev, cmd->stop_arg - 1, AO_UC_Load_A_Register);
+ 			devpriv->stc_writew(dev, AO_UC_Load, AO_Command_1_Register);
+ 		}else
+@@ -3244,7 +3244,7 @@ static int ni_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 		bits |= AO_Number_Of_DAC_Packages;
+ #endif
+ 	devpriv->stc_writew(dev, bits, AO_Personal_Register);
+-	// enable sending of ao dma requests
++	/*  enable sending of ao dma requests */
+ 	devpriv->stc_writew(dev, AO_AOFREQ_Enable, AO_Start_Select_Register);
+ 
+ 	devpriv->stc_writew(dev, AO_Configuration_End, Joint_Reset_Register);
+@@ -3386,11 +3386,11 @@ static int ni_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s
+ 
+ static int ni_ao_reset(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	//devpriv->ao0p=0x0000;
+-	//ni_writew(devpriv->ao0p,AO_Configuration);
++	/* devpriv->ao0p=0x0000; */
++	/* ni_writew(devpriv->ao0p,AO_Configuration); */
+ 
+-	//devpriv->ao1p=AO_Channel(1);
+-	//ni_writew(devpriv->ao1p,AO_Configuration);
++	/* devpriv->ao1p=AO_Channel(1); */
++	/* ni_writew(devpriv->ao1p,AO_Configuration); */
+ 
+ 	ni_release_ao_mite_channel(dev);
+ 
+@@ -3434,7 +3434,7 @@ static int ni_ao_reset(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-// digital io
++/* digital io */
+ 
+ static int ni_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+@@ -3718,9 +3718,11 @@ static int ni_cdo_inttrig(struct comedi_device * dev, struct comedi_subdevice *
+ 	if (retval < 0)
+ 		return retval;
+ #endif
+-// XXX not sure what interrupt C group does
+-//      ni_writeb(Interrupt_Group_C_Enable_Bit, M_Offset_Interrupt_C_Enable);
+-	//wait for dma to fill output fifo
++/*
++* XXX not sure what interrupt C group does
++* ni_writeb(Interrupt_Group_C_Enable_Bit,
++* M_Offset_Interrupt_C_Enable); wait for dma to fill output fifo
++*/
+ 	for (i = 0; i < timeout; ++i) {
+ 		if (ni_readl(M_Offset_CDIO_Status) & CDO_FIFO_Full_Bit)
+ 			break;
+@@ -3742,8 +3744,10 @@ static int ni_cdio_cancel(struct comedi_device * dev, struct comedi_subdevice *
+ 		CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit |
+ 		CDO_FIFO_Request_Interrupt_Enable_Clear_Bit,
+ 		M_Offset_CDIO_Command);
+-// XXX not sure what interrupt C group does
+-//      ni_writeb(0, M_Offset_Interrupt_C_Enable);
++/*
++* XXX not sure what interrupt C group does ni_writeb(0,
++* M_Offset_Interrupt_C_Enable);
++*/
+ 	ni_writel(0, M_Offset_CDO_Mask_Enable);
+ 	ni_release_cdo_mite_channel(dev);
+ 	return 0;
+@@ -3777,15 +3781,15 @@ static void handle_cdio_interrupt(struct comedi_device * dev)
+ 
+ 	cdio_status = ni_readl(M_Offset_CDIO_Status);
+ 	if (cdio_status & (CDO_Overrun_Bit | CDO_Underflow_Bit)) {
+-//              rt_printk("cdio error: statux=0x%x\n", cdio_status);
+-		ni_writel(CDO_Error_Interrupt_Confirm_Bit, M_Offset_CDIO_Command);	// XXX just guessing this is needed and does something useful
++/* rt_printk("cdio error: statux=0x%x\n", cdio_status); */
++		ni_writel(CDO_Error_Interrupt_Confirm_Bit, M_Offset_CDIO_Command);	/*  XXX just guessing this is needed and does something useful */
+ 		s->async->events |= COMEDI_CB_OVERFLOW;
+ 	}
+ 	if (cdio_status & CDO_FIFO_Empty_Bit) {
+-//              rt_printk("cdio fifo empty\n");
++/* rt_printk("cdio fifo empty\n"); */
+ 		ni_writel(CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit,
+ 			M_Offset_CDIO_Command);
+-//              s->async->events |= COMEDI_CB_EOA;
++/* s->async->events |= COMEDI_CB_EOA; */
+ 	}
+ 	ni_event(dev, s);
+ }
+@@ -4419,14 +4423,14 @@ static int ni_E_init(struct comedi_device * dev, struct comedi_devconfig * it)
+ 	s = dev->subdevices + NI_CALIBRATION_SUBDEV;
+ 	s->type = COMEDI_SUBD_CALIB;
+ 	if (boardtype.reg_type & ni_reg_m_series_mask) {
+-		// internal PWM analog output used for AI nonlinearity calibration
++		/*  internal PWM analog output used for AI nonlinearity calibration */
+ 		s->subdev_flags = SDF_INTERNAL;
+ 		s->insn_config = &ni_m_series_pwm_config;
+ 		s->n_chan = 1;
+ 		s->maxdata = 0;
+ 		ni_writel(0x0, M_Offset_Cal_PWM);
+ 	} else if (boardtype.reg_type == ni_reg_6143) {
+-		// internal PWM analog output used for AI nonlinearity calibration
++		/*  internal PWM analog output used for AI nonlinearity calibration */
+ 		s->subdev_flags = SDF_INTERNAL;
+ 		s->insn_config = &ni_6143_pwm_config;
+ 		s->n_chan = 1;
+@@ -4478,7 +4482,7 @@ static int ni_E_init(struct comedi_device * dev, struct comedi_devconfig * it)
+ 	if (boardtype.reg_type & ni_reg_67xx_mask) {
+ 		s->type = COMEDI_SUBD_AI;
+ 		s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_INTERNAL;
+-		// one channel for each analog output channel
++		/*  one channel for each analog output channel */
+ 		s->n_chan = boardtype.n_aochan;
+ 		s->maxdata = (1 << 16) - 1;
+ 		s->range_table = &range_unknown;	/* XXX */
+@@ -4557,7 +4561,7 @@ static int ni_E_init(struct comedi_device * dev, struct comedi_devconfig * it)
+ 	/* ai configuration */
+ 	ni_ai_reset(dev, dev->subdevices + NI_AI_SUBDEV);
+ 	if ((boardtype.reg_type & ni_reg_6xxx_mask) == 0) {
+-		// BEAM is this needed for PCI-6143 ??
++		/*  BEAM is this needed for PCI-6143 ?? */
+ 		devpriv->clock_and_fout =
+ 			Slow_Internal_Time_Divide_By_2 |
+ 			Slow_Internal_Timebase |
+@@ -4904,7 +4908,7 @@ static void ni_write_caldac(struct comedi_device * dev, int addr, int val)
+ 	int i;
+ 	int type;
+ 
+-	//printk("ni_write_caldac: chan=%d val=%d\n",addr,val);
++	/* printk("ni_write_caldac: chan=%d val=%d\n",addr,val); */
+ 	if (devpriv->caldacs[addr] == val)
+ 		return;
+ 	devpriv->caldacs[addr] = val;
+@@ -4916,7 +4920,7 @@ static void ni_write_caldac(struct comedi_device * dev, int addr, int val)
+ 		if (addr < caldacs[type].n_chans) {
+ 			bits = caldacs[type].packbits(addr, val, &bitstring);
+ 			loadbit = SerDacLd(i);
+-			//printk("caldac: using i=%d addr=%d %x\n",i,addr,bitstring);
++			/* printk("caldac: using i=%d addr=%d %x\n",i,addr,bitstring); */
+ 			break;
+ 		}
+ 		addr -= caldacs[type].n_chans;
+@@ -5012,7 +5016,7 @@ static void GPCT_Reset(struct comedi_device * dev, int chan)
+ {
+ 	int temp_ack_reg = 0;
+ 
+-	//printk("GPCT_Reset...");
++	/* printk("GPCT_Reset..."); */
+ 	devpriv->gpct_cur_operation[chan] = GPCT_RESET;
+ 
+ 	switch (chan) {
+@@ -5029,7 +5033,7 @@ static void GPCT_Reset(struct comedi_device * dev, int chan)
+ 		devpriv->stc_writew(dev, temp_ack_reg,
+ 			Interrupt_A_Ack_Register);
+ 
+-		//problem...this interferes with the other ctr...
++		/* problem...this interferes with the other ctr... */
+ 		devpriv->an_trig_etc_reg |= GPFO_0_Output_Enable;
+ 		devpriv->stc_writew(dev, devpriv->an_trig_etc_reg,
+ 			Analog_Trigger_Etc_Register);
+@@ -5065,7 +5069,7 @@ static void GPCT_Reset(struct comedi_device * dev, int chan)
+ 		G_Input_Select_Register(chan));
+ 	devpriv->stc_writew(dev, 0, G_Autoincrement_Register(chan));
+ 
+-	//printk("exit GPCT_Reset\n");
++	/* printk("exit GPCT_Reset\n"); */
+ }
+ 
+ #endif
+@@ -5096,7 +5100,7 @@ static int ni_gpct_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	int retval;
+ #ifdef PCIDMA
+ 	struct ni_gpct *counter = s->private;
+-//      const struct comedi_cmd *cmd = &s->async->cmd;
++/* const struct comedi_cmd *cmd = &s->async->cmd; */
+ 
+ 	retval = ni_request_gpct_mite_channel(dev, counter->counter_index,
+ 		COMEDI_INPUT);
+@@ -5168,7 +5172,7 @@ static int ni_m_series_set_pfi_routing(struct comedi_device * dev, unsigned chan
+ static int ni_old_set_pfi_routing(struct comedi_device * dev, unsigned chan,
+ 	unsigned source)
+ {
+-	// pre-m-series boards have fixed signals on pfi pins
++	/*  pre-m-series boards have fixed signals on pfi pins */
+ 	if (source != ni_old_get_pfi_routing(dev, chan))
+ 		return -EINVAL;
+ 	return 2;
+@@ -5192,7 +5196,7 @@ static unsigned ni_m_series_get_pfi_routing(struct comedi_device * dev, unsigned
+ 
+ static unsigned ni_old_get_pfi_routing(struct comedi_device * dev, unsigned chan)
+ {
+-	// pre-m-series boards have fixed signals on pfi pins
++	/*  pre-m-series boards have fixed signals on pfi pins */
+ 	switch (chan) {
+ 	case 0:
+ 		return NI_PFI_OUTPUT_AI_START1;
+@@ -5314,14 +5318,14 @@ static int ni_pfi_insn_config(struct comedi_device * dev, struct comedi_subdevic
+  */
+ static void ni_rtsi_init(struct comedi_device * dev)
+ {
+-	// Initialises the RTSI bus signal switch to a default state
++	/*  Initialises the RTSI bus signal switch to a default state */
+ 
+-	// Set clock mode to internal
++	/*  Set clock mode to internal */
+ 	devpriv->clock_and_fout2 = MSeries_RTSI_10MHz_Bit;
+ 	if (ni_set_master_clock(dev, NI_MIO_INTERNAL_CLOCK, 0) < 0) {
+ 		rt_printk("ni_set_master_clock failed, bug?");
+ 	}
+-	// default internal lines routing to RTSI bus lines
++	/*  default internal lines routing to RTSI bus lines */
+ 	devpriv->rtsi_trig_a_output_reg =
+ 		RTSI_Trig_Output_Bits(0,
+ 		NI_RTSI_OUTPUT_ADR_START1) | RTSI_Trig_Output_Bits(1,
+@@ -5341,8 +5345,10 @@ static void ni_rtsi_init(struct comedi_device * dev)
+ 	devpriv->stc_writew(dev, devpriv->rtsi_trig_b_output_reg,
+ 		RTSI_Trig_B_Output_Register);
+ 
+-	// Sets the source and direction of the 4 on board lines
+-//      devpriv->stc_writew(dev, 0x0000, RTSI_Board_Register);
++/*
++* Sets the source and direction of the 4 on board lines
++* devpriv->stc_writew(dev, 0x0000, RTSI_Board_Register);
++*/
+ }
+ 
+ static int ni_rtsi_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+@@ -5422,7 +5428,7 @@ static int ni_mseries_set_pll_master_clock(struct comedi_device * dev, unsigned
+ 	int retval;
+ 	if (source == NI_MIO_PLL_PXI10_CLOCK)
+ 		period_ns = 100;
+-	// these limits are somewhat arbitrary, but NI advertises 1 to 20MHz range so we'll use that
++	/*  these limits are somewhat arbitrary, but NI advertises 1 to 20MHz range so we'll use that */
+ 	if (period_ns < min_period_ns || period_ns > max_period_ns) {
+ 		rt_printk
+ 			("%s: you must specify an input clock frequency between %i and %i nanosec "
+@@ -5484,8 +5490,10 @@ static int ni_mseries_set_pll_master_clock(struct comedi_device * dev, unsigned
+ 	pll_control_bits |=
+ 		MSeries_PLL_Divisor_Bits(freq_divider) |
+ 		MSeries_PLL_Multiplier_Bits(freq_multiplier);
+-//      rt_printk("using divider=%i, multiplier=%i for PLL.  pll_control_bits = 0x%x\n", freq_divider, freq_multiplier, pll_control_bits);
+-//      rt_printk("clock_ns=%d\n", devpriv->clock_ns);
++
++	/* rt_printk("using divider=%i, multiplier=%i for PLL. pll_control_bits = 0x%x\n",
++	 * freq_divider, freq_multiplier, pll_control_bits); */
++	/* rt_printk("clock_ns=%d\n", devpriv->clock_ns); */
+ 	ni_writew(pll_control_bits, M_Offset_PLL_Control);
+ 	devpriv->clock_source = source;
+ 	/* it seems to typically take a few hundred microseconds for PLL to lock */
+@@ -5714,7 +5722,7 @@ static int cs5529_wait_for_idle(struct comedi_device * dev)
+ 			return -EIO;
+ 		}
+ 	}
+-//printk("looped %i times waiting for idle\n", i);
++/* printk("looped %i times waiting for idle\n", i); */
+ 	if (i == timeout) {
+ 		rt_printk("%s: %s: timeout\n", __FILE__, __FUNCTION__);
+ 		return -ETIME;
+@@ -5737,7 +5745,7 @@ static void cs5529_command(struct comedi_device * dev, unsigned short value)
+ 			break;
+ 		comedi_udelay(1);
+ 	}
+-//printk("looped %i times writing command to cs5529\n", i);
++/* printk("looped %i times writing command to cs5529\n", i); */
+ 	if (i == timeout) {
+ 		comedi_error(dev, "possible problem - never saw adc go busy?");
+ 	}
+diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c
+index d6357c25aca5..228b1ca220e7 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_cs.c
++++ b/drivers/staging/comedi/drivers/ni_mio_cs.c
+@@ -344,7 +344,7 @@ static void mio_cs_config(struct pcmcia_device *link)
+ 		manfid = le16_to_cpu(buf[0]);
+ 		prodid = le16_to_cpu(buf[1]);
+ 	}
+-	//printk("manfid = 0x%04x, 0x%04x\n",manfid,prodid);
++	/* printk("manfid = 0x%04x, 0x%04x\n",manfid,prodid); */
+ 
+ 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+ 	tuple.Attributes = 0;
+@@ -381,7 +381,7 @@ static void mio_cs_config(struct pcmcia_device *link)
+ 		for (base = 0x000; base < 0x400; base += 0x20) {
+ 			link->io.BasePort1 = base;
+ 			ret = pcmcia_request_io(link, &link->io);
+-			//printk("RequestIO 0x%02x\n",ret);
++			/* printk("RequestIO 0x%02x\n",ret); */
+ 			if (!ret)
+ 				break;
+ 		}
+@@ -393,12 +393,12 @@ static void mio_cs_config(struct pcmcia_device *link)
+ 	if (ret) {
+ 		printk("pcmcia_request_irq() returned error: %i\n", ret);
+ 	}
+-	//printk("RequestIRQ 0x%02x\n",ret);
++	/* printk("RequestIRQ 0x%02x\n",ret); */
+ 
+ 	link->conf.ConfigIndex = 1;
+ 
+ 	ret = pcmcia_request_configuration(link, &link->conf);
+-	//printk("RequestConfiguration %d\n",ret);
++	/* printk("RequestConfiguration %d\n",ret); */
+ 
+ 	link->dev_node = &dev_node;
+ }
+diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
+index 90e228b0ae0f..eaa2bd2620b8 100644
+--- a/drivers/staging/comedi/drivers/ni_pcimio.c
++++ b/drivers/staging/comedi/drivers/ni_pcimio.c
+@@ -117,7 +117,7 @@ SCXI is probably broken for m-series boards.
+ #include "ni_stc.h"
+ #include "mite.h"
+ 
+-//#define PCI_DEBUG
++/* #define PCI_DEBUG */
+ 
+ #define PCIDMA
+ 
+@@ -218,7 +218,7 @@ static const struct comedi_lrange range_ni_M_622x_ao = { 1, {
+ 
+ static const struct ni_board_struct ni_boards[] = {
+ 	{
+-			.device_id = 0x0162,	// NI also says 0x1620.  typo?
++			.device_id = 0x0162,	/*  NI also says 0x1620.  typo? */
+ 			.name = "pci-mio-16xe-50",
+ 			.n_adchan = 16,
+ 			.adbits = 16,
+@@ -238,7 +238,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 		},
+ 	{
+ 			.device_id = 0x1170,
+-			.name = "pci-mio-16xe-10",	// aka pci-6030E
++			.name = "pci-mio-16xe-10",	/*  aka pci-6030E */
+ 			.n_adchan = 16,
+ 			.adbits = 16,
+ 			.ai_fifo_depth = 512,
+@@ -330,7 +330,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 			.ao_unipolar = 1,
+ 			.ao_speed = 1000,
+ 			.num_p0_dio_channels = 8,
+-			.caldac = {ad8804_debug},	// doc says mb88341
++			.caldac = {ad8804_debug},	/*  doc says mb88341 */
+ 			.has_8255 = 0,
+ 		},
+ 	{
+@@ -846,7 +846,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 			.n_adchan = 16,
+ 			.adbits = 16,
+ 			.ai_fifo_depth = 512,
+-			//FIXME:  guess
++			/* FIXME:  guess */
+ 			.gainlkup = ai_gain_622x,
+ 			.ai_speed = 4000,
+ 			.n_aochan = 0,
+@@ -1295,12 +1295,12 @@ static void m_series_stc_writew(struct comedi_device * dev, uint16_t data, int r
+ 		offset = M_Offset_AI_Personal;
+ 		break;
+ 	case AI_SI2_Load_A_Register:
+-		// this is actually a 32 bit register on m series boards
++		/*  this is actually a 32 bit register on m series boards */
+ 		ni_writel(data, M_Offset_AI_SI2_Load_A);
+ 		return;
+ 		break;
+ 	case AI_SI2_Load_B_Register:
+-		// this is actually a 32 bit register on m series boards
++		/*  this is actually a 32 bit register on m series boards */
+ 		ni_writel(data, M_Offset_AI_SI2_Load_B);
+ 		return;
+ 		break;
+@@ -1581,17 +1581,17 @@ static void m_series_init_eeprom_buffer(struct comedi_device * dev)
+ 
+ static void init_6143(struct comedi_device * dev)
+ {
+-	// Disable interrupts
++	/*  Disable interrupts */
+ 	devpriv->stc_writew(dev, 0, Interrupt_Control_Register);
+ 
+-	// Initialise 6143 AI specific bits
+-	ni_writeb(0x00, Magic_6143);	// Set G0,G1 DMA mode to E series version
+-	ni_writeb(0x80, PipelineDelay_6143);	// Set EOCMode, ADCMode and pipelinedelay
+-	ni_writeb(0x00, EOC_Set_6143);	// Set EOC Delay
++	/*  Initialise 6143 AI specific bits */
++	ni_writeb(0x00, Magic_6143);	/*  Set G0,G1 DMA mode to E series version */
++	ni_writeb(0x80, PipelineDelay_6143);	/*  Set EOCMode, ADCMode and pipelinedelay */
++	ni_writeb(0x00, EOC_Set_6143);	/*  Set EOC Delay */
+ 
+-	ni_writel(boardtype.ai_fifo_depth / 2, AIFIFO_Flag_6143);	// Set the FIFO half full level
++	ni_writel(boardtype.ai_fifo_depth / 2, AIFIFO_Flag_6143);	/*  Set the FIFO half full level */
+ 
+-	// Strobe Relay disable bit
++	/*  Strobe Relay disable bit */
+ 	devpriv->ai_calib_source_enabled = 0;
+ 	ni_writew(devpriv->ai_calib_source | Calibration_Channel_6143_RelayOff,
+ 		Calibration_Channel_6143);
+diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h
+index 8c03e7d85e84..ceee30c7972c 100644
+--- a/drivers/staging/comedi/drivers/ni_stc.h
++++ b/drivers/staging/comedi/drivers/ni_stc.h
+@@ -521,13 +521,13 @@ enum AO_Personal_Bits {
+ 	AO_FIFO_Flags_Polarity = 1 << 11,	/* M Series: reserved */
+ 	AO_TMRDACWR_Pulse_Width = 1 << 12,
+ 	AO_Fast_CPU = 1 << 13,	/* M Series: reserved */
+-	AO_Number_Of_DAC_Packages = 1 << 14,	// 1 for "single" mode, 0 for "dual"
+-	AO_Multiple_DACS_Per_Package = 1 << 15	// m-series only
++	AO_Number_Of_DAC_Packages = 1 << 14,	/*  1 for "single" mode, 0 for "dual" */
++	AO_Multiple_DACS_Per_Package = 1 << 15	/*  m-series only */
+ };
+ #define	RTSI_Trig_A_Output_Register	79
+ #define	RTSI_Trig_B_Output_Register	80
+ enum RTSI_Trig_B_Output_Bits {
+-	RTSI_Sub_Selection_1_Bit = 0x8000	// not for m-series
++	RTSI_Sub_Selection_1_Bit = 0x8000	/*  not for m-series */
+ };
+ static inline unsigned RTSI_Trig_Output_Bits(unsigned rtsi_channel,
+ 	unsigned source)
+@@ -539,7 +539,7 @@ static inline unsigned RTSI_Trig_Output_Mask(unsigned rtsi_channel)
+ 	return 0xf << ((rtsi_channel % 4) * 4);
+ };
+ 
+-// inverse to RTSI_Trig_Output_Bits()
++/* inverse to RTSI_Trig_Output_Bits() */
+ static inline unsigned RTSI_Trig_Output_Source(unsigned rtsi_channel,
+ 	unsigned bits)
+ {
+@@ -920,42 +920,42 @@ enum ni_reg_type {
+ static const struct comedi_lrange range_ni_E_ao_ext;
+ 
+ enum m_series_register_offsets {
+-	M_Offset_CDIO_DMA_Select = 0x7,	// write
+-	M_Offset_SCXI_Status = 0x7,	// read
+-	M_Offset_AI_AO_Select = 0x9,	// write, same offset as e-series
+-	M_Offset_SCXI_Serial_Data_In = 0x9,	// read
+-	M_Offset_G0_G1_Select = 0xb,	// write, same offset as e-series
++	M_Offset_CDIO_DMA_Select = 0x7,	/*  write */
++	M_Offset_SCXI_Status = 0x7,	/*  read */
++	M_Offset_AI_AO_Select = 0x9,	/*  write, same offset as e-series */
++	M_Offset_SCXI_Serial_Data_In = 0x9,	/*  read */
++	M_Offset_G0_G1_Select = 0xb,	/*  write, same offset as e-series */
+ 	M_Offset_Misc_Command = 0xf,
+ 	M_Offset_SCXI_Serial_Data_Out = 0x11,
+ 	M_Offset_SCXI_Control = 0x13,
+ 	M_Offset_SCXI_Output_Enable = 0x15,
+ 	M_Offset_AI_FIFO_Data = 0x1c,
+-	M_Offset_Static_Digital_Output = 0x24,	// write
+-	M_Offset_Static_Digital_Input = 0x24,	// read
++	M_Offset_Static_Digital_Output = 0x24,	/*  write */
++	M_Offset_Static_Digital_Input = 0x24,	/*  read */
+ 	M_Offset_DIO_Direction = 0x28,
+ 	M_Offset_Cal_PWM = 0x40,
+ 	M_Offset_AI_Config_FIFO_Data = 0x5e,
+-	M_Offset_Interrupt_C_Enable = 0x88,	// write
+-	M_Offset_Interrupt_C_Status = 0x88,	// read
++	M_Offset_Interrupt_C_Enable = 0x88,	/*  write */
++	M_Offset_Interrupt_C_Status = 0x88,	/*  read */
+ 	M_Offset_Analog_Trigger_Control = 0x8c,
+ 	M_Offset_AO_Serial_Interrupt_Enable = 0xa0,
+-	M_Offset_AO_Serial_Interrupt_Ack = 0xa1,	// write
+-	M_Offset_AO_Serial_Interrupt_Status = 0xa1,	// read
++	M_Offset_AO_Serial_Interrupt_Ack = 0xa1,	/*  write */
++	M_Offset_AO_Serial_Interrupt_Status = 0xa1,	/*  read */
+ 	M_Offset_AO_Calibration = 0xa3,
+ 	M_Offset_AO_FIFO_Data = 0xa4,
+ 	M_Offset_PFI_Filter = 0xb0,
+ 	M_Offset_RTSI_Filter = 0xb4,
+ 	M_Offset_SCXI_Legacy_Compatibility = 0xbc,
+-	M_Offset_Interrupt_A_Ack = 0x104,	// write
+-	M_Offset_AI_Status_1 = 0x104,	// read
+-	M_Offset_Interrupt_B_Ack = 0x106,	// write
+-	M_Offset_AO_Status_1 = 0x106,	// read
+-	M_Offset_AI_Command_2 = 0x108,	// write
+-	M_Offset_G01_Status = 0x108,	// read
++	M_Offset_Interrupt_A_Ack = 0x104,	/*  write */
++	M_Offset_AI_Status_1 = 0x104,	/*  read */
++	M_Offset_Interrupt_B_Ack = 0x106,	/*  write */
++	M_Offset_AO_Status_1 = 0x106,	/*  read */
++	M_Offset_AI_Command_2 = 0x108,	/*  write */
++	M_Offset_G01_Status = 0x108,	/*  read */
+ 	M_Offset_AO_Command_2 = 0x10a,
+-	M_Offset_AO_Status_2 = 0x10c,	// read
+-	M_Offset_G0_Command = 0x10c,	// write
+-	M_Offset_G1_Command = 0x10e,	// write
++	M_Offset_AO_Status_2 = 0x10c,	/*  read */
++	M_Offset_G0_Command = 0x10c,	/*  write */
++	M_Offset_G1_Command = 0x10e,	/*  write */
+ 	M_Offset_G0_HW_Save = 0x110,
+ 	M_Offset_G0_HW_Save_High = 0x110,
+ 	M_Offset_AI_Command_1 = 0x110,
+@@ -973,17 +973,17 @@ enum m_series_register_offsets {
+ 	M_Offset_G1_Save = 0x11c,
+ 	M_Offset_G1_Save_High = 0x11c,
+ 	M_Offset_G1_Save_Low = 0x11e,
+-	M_Offset_AI_SI_Load_B = 0x120,	// write
+-	M_Offset_AO_UI_Save = 0x120,	// read
+-	M_Offset_AI_SC_Load_A = 0x124,	// write
+-	M_Offset_AO_BC_Save = 0x124,	// read
+-	M_Offset_AI_SC_Load_B = 0x128,	// write
+-	M_Offset_AO_UC_Save = 0x128,	//read
++	M_Offset_AI_SI_Load_B = 0x120,	/*  write */
++	M_Offset_AO_UI_Save = 0x120,	/*  read */
++	M_Offset_AI_SC_Load_A = 0x124,	/*  write */
++	M_Offset_AO_BC_Save = 0x124,	/*  read */
++	M_Offset_AI_SC_Load_B = 0x128,	/*  write */
++	M_Offset_AO_UC_Save = 0x128,	/* read */
+ 	M_Offset_AI_SI2_Load_A = 0x12c,
+ 	M_Offset_AI_SI2_Load_B = 0x130,
+ 	M_Offset_G0_Mode = 0x134,
+-	M_Offset_G1_Mode = 0x136,	// write
+-	M_Offset_Joint_Status_1 = 0x136,	// read
++	M_Offset_G1_Mode = 0x136,	/*  write */
++	M_Offset_Joint_Status_1 = 0x136,	/*  read */
+ 	M_Offset_G0_Load_A = 0x138,
+ 	M_Offset_Joint_Status_2 = 0x13a,
+ 	M_Offset_G0_Load_B = 0x13c,
+@@ -1007,10 +1007,10 @@ enum m_series_register_offsets {
+ 	M_Offset_Analog_Trigger_Etc = 0x17a,
+ 	M_Offset_AI_START_STOP_Select = 0x17c,
+ 	M_Offset_AI_Trigger_Select = 0x17e,
+-	M_Offset_AI_SI_Save = 0x180,	// read
+-	M_Offset_AI_DIV_Load_A = 0x180,	// write
+-	M_Offset_AI_SC_Save = 0x184,	// read
+-	M_Offset_AO_Start_Select = 0x184,	// write
++	M_Offset_AI_SI_Save = 0x180,	/*  read */
++	M_Offset_AI_DIV_Load_A = 0x180,	/*  write */
++	M_Offset_AI_SC_Save = 0x184,	/*  read */
++	M_Offset_AO_Start_Select = 0x184,	/*  write */
+ 	M_Offset_AO_Trigger_Select = 0x186,
+ 	M_Offset_AO_Mode_3 = 0x18c,
+ 	M_Offset_G0_Autoincrement = 0x188,
+@@ -1032,10 +1032,10 @@ enum m_series_register_offsets {
+ 	M_Offset_G1_Counting_Mode = 0x1b2,
+ 	M_Offset_G0_Second_Gate = 0x1b4,
+ 	M_Offset_G1_Second_Gate = 0x1b6,
+-	M_Offset_G0_DMA_Config = 0x1b8,	// write
+-	M_Offset_G0_DMA_Status = 0x1b8,	// read
+-	M_Offset_G1_DMA_Config = 0x1ba,	// write
+-	M_Offset_G1_DMA_Status = 0x1ba,	// read
++	M_Offset_G0_DMA_Config = 0x1b8,	/*  write */
++	M_Offset_G0_DMA_Status = 0x1b8,	/*  read */
++	M_Offset_G1_DMA_Config = 0x1ba,	/*  write */
++	M_Offset_G1_DMA_Status = 0x1ba,	/*  read */
+ 	M_Offset_G0_MSeries_ABZ = 0x1c0,
+ 	M_Offset_G1_MSeries_ABZ = 0x1c2,
+ 	M_Offset_Clock_and_Fout2 = 0x1c4,
+@@ -1051,10 +1051,10 @@ enum m_series_register_offsets {
+ 	M_Offset_PFI_DO = 0x1de,
+ 	M_Offset_AI_Config_FIFO_Bypass = 0x218,
+ 	M_Offset_SCXI_DIO_Enable = 0x21c,
+-	M_Offset_CDI_FIFO_Data = 0x220,	// read
+-	M_Offset_CDO_FIFO_Data = 0x220,	// write
+-	M_Offset_CDIO_Status = 0x224,	// read
+-	M_Offset_CDIO_Command = 0x224,	// write
++	M_Offset_CDI_FIFO_Data = 0x220,	/*  read */
++	M_Offset_CDO_FIFO_Data = 0x220,	/*  write */
++	M_Offset_CDIO_Status = 0x224,	/*  read */
++	M_Offset_CDIO_Command = 0x224,	/*  write */
+ 	M_Offset_CDI_Mode = 0x228,
+ 	M_Offset_CDO_Mode = 0x22c,
+ 	M_Offset_CDI_Mask_Enable = 0x230,
+@@ -1122,7 +1122,7 @@ enum MSeries_AI_Config_FIFO_Data_Bits {
+ 	MSeries_AI_Config_Channel_Type_Ground_Ref_Bits = 0x3 << 6,
+ 	MSeries_AI_Config_Channel_Type_Aux_Bits = 0x5 << 6,
+ 	MSeries_AI_Config_Channel_Type_Ghost_Bits = 0x7 << 6,
+-	MSeries_AI_Config_Polarity_Bit = 0x1000,	// 0 for 2's complement encoding
++	MSeries_AI_Config_Polarity_Bit = 0x1000,	/*  0 for 2's complement encoding */
+ 	MSeries_AI_Config_Dither_Bit = 0x2000,
+ 	MSeries_AI_Config_Last_Channel_Bit = 0x4000,
+ };
+@@ -1151,8 +1151,8 @@ enum MSeries_Clock_and_Fout2_Bits {
+ 	MSeries_PLL_In_Source_Select_RTSI7_Bits = 0x1b,
+ 	MSeries_PLL_In_Source_Select_PXI_Clock10 = 0x1d,
+ 	MSeries_PLL_In_Source_Select_Mask = 0x1f,
+-	MSeries_Timebase1_Select_Bit = 0x20,	// use PLL for timebase 1
+-	MSeries_Timebase3_Select_Bit = 0x40,	// use PLL for timebase 3
++	MSeries_Timebase1_Select_Bit = 0x20,	/*  use PLL for timebase 1 */
++	MSeries_Timebase3_Select_Bit = 0x40,	/*  use PLL for timebase 3 */
+ 	/* use 10MHz instead of 20MHz for RTSI clock frequency.  Appears
+ 	   to have no effect, at least on pxi-6281, which always uses
+ 	   20MHz rtsi clock frequency */
+@@ -1213,7 +1213,7 @@ enum MSeries_AI_Config_FIFO_Bypass_Bits {
+ 	MSeries_AO_Bypass_AO_Cal_Sel_Mask = 0x38000,
+ 	MSeries_AI_Bypass_Gain_Mask = 0x1c0000,
+ 	MSeries_AI_Bypass_Dither_Bit = 0x200000,
+-	MSeries_AI_Bypass_Polarity_Bit = 0x400000,	// 0 for 2's complement encoding
++	MSeries_AI_Bypass_Polarity_Bit = 0x400000,	/*  0 for 2's complement encoding */
+ 	MSeries_AI_Bypass_Config_FIFO_Bit = 0x80000000
+ };
+ static inline unsigned MSeries_AI_Bypass_Cal_Sel_Pos_Bits(int
+@@ -1239,7 +1239,7 @@ enum MSeries_AO_Config_Bank_Bits {
+ 	MSeries_AO_DAC_Reference_10V_Internal_Bits = 0x0,
+ 	MSeries_AO_DAC_Reference_5V_Internal_Bits = 0x8,
+ 	MSeries_AO_Update_Timed_Bit = 0x40,
+-	MSeries_AO_Bipolar_Bit = 0x80	// turns on 2's complement encoding
++	MSeries_AO_Bipolar_Bit = 0x80	/*  turns on 2's complement encoding */
+ };
+ 
+ enum MSeries_AO_Reference_Attenuation_Bits {
+@@ -1266,7 +1266,7 @@ static inline unsigned MSeries_PFI_Output_Select_Bits(unsigned channel,
+ 	return (source & 0x1f) << ((channel % 3) * 5);
+ };
+ 
+-// inverse to MSeries_PFI_Output_Select_Bits
++/* inverse to MSeries_PFI_Output_Select_Bits */
+ static inline unsigned MSeries_PFI_Output_Select_Source(unsigned channel,
+ 	unsigned bits)
+ {
+@@ -1338,9 +1338,9 @@ enum CDIO_Command_Bits {
+ enum CDI_Mode_Bits {
+ 	CDI_Sample_Source_Select_Mask = 0x3f,
+ 	CDI_Halt_On_Error_Bit = 0x200,
+-	CDI_Polarity_Bit = 0x400,	// sample clock on falling edge
+-	CDI_FIFO_Mode_Bit = 0x800,	// set for half full mode, clear for not empty mode
+-	CDI_Data_Lane_Mask = 0x3000,	// data lanes specify which dio channels map to byte or word accesses to the dio fifos
++	CDI_Polarity_Bit = 0x400,	/*  sample clock on falling edge */
++	CDI_FIFO_Mode_Bit = 0x800,	/*  set for half full mode, clear for not empty mode */
++	CDI_Data_Lane_Mask = 0x3000,	/*  data lanes specify which dio channels map to byte or word accesses to the dio fifos */
+ 	CDI_Data_Lane_0_15_Bits = 0x0,
+ 	CDI_Data_Lane_16_31_Bits = 0x1000,
+ 	CDI_Data_Lane_0_7_Bits = 0x0,
+@@ -1353,9 +1353,9 @@ enum CDO_Mode_Bits {
+ 	CDO_Sample_Source_Select_Mask = 0x3f,
+ 	CDO_Retransmit_Bit = 0x100,
+ 	CDO_Halt_On_Error_Bit = 0x200,
+-	CDO_Polarity_Bit = 0x400,	// sample clock on falling edge
+-	CDO_FIFO_Mode_Bit = 0x800,	// set for half full mode, clear for not full mode
+-	CDO_Data_Lane_Mask = 0x3000,	// data lanes specify which dio channels map to byte or word accesses to the dio fifos
++	CDO_Polarity_Bit = 0x400,	/*  sample clock on falling edge */
++	CDO_FIFO_Mode_Bit = 0x800,	/*  set for half full mode, clear for not full mode */
++	CDO_Data_Lane_Mask = 0x3000,	/*  data lanes specify which dio channels map to byte or word accesses to the dio fifos */
+ 	CDO_Data_Lane_0_15_Bits = 0x0,
+ 	CDO_Data_Lane_16_31_Bits = 0x1000,
+ 	CDO_Data_Lane_0_7_Bits = 0x0,
+diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c
+index 05a957540398..53966e9816c1 100644
+--- a/drivers/staging/comedi/drivers/ni_tio.c
++++ b/drivers/staging/comedi/drivers/ni_tio.c
+@@ -1273,7 +1273,7 @@ static int ni_tio_set_other_src(struct ni_gpct *counter, unsigned index,
+ 		counter_dev->regs[abz_reg] &= ~mask;
+ 		counter_dev->regs[abz_reg] |= (source << shift) & mask;
+ 		write_register(counter, counter_dev->regs[abz_reg], abz_reg);
+-//              rt_printk("%s %x %d %d\n", __FUNCTION__, counter_dev->regs[abz_reg], index, source);
++/* rt_printk("%s %x %d %d\n", __FUNCTION__, counter_dev->regs[abz_reg], index, source); */
+ 		return 0;
+ 	}
+ 	return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/ni_tio.h b/drivers/staging/comedi/drivers/ni_tio.h
+index 0729d60b01cc..f9e7b8343aef 100644
+--- a/drivers/staging/comedi/drivers/ni_tio.h
++++ b/drivers/staging/comedi/drivers/ni_tio.h
+@@ -25,7 +25,7 @@
+ 
+ #include "../comedidev.h"
+ 
+-// forward declarations
++/* forward declarations */
+ struct mite_struct;
+ struct ni_gpct_device;
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_tio_internal.h b/drivers/staging/comedi/drivers/ni_tio_internal.h
+index ac5b171cbe18..850e1ea3ad9f 100644
+--- a/drivers/staging/comedi/drivers/ni_tio_internal.h
++++ b/drivers/staging/comedi/drivers/ni_tio_internal.h
+@@ -487,8 +487,8 @@ enum Gi_Counting_Mode_Reg_Bits {
+ #define Gi_Source_Select_Shift 2
+ #define Gi_Gate_Select_Shift 7
+ enum Gi_Input_Select_Bits {
+-	Gi_Read_Acknowledges_Irq = 0x1,	// not present on 660x
+-	Gi_Write_Acknowledges_Irq = 0x2,	// not present on 660x
++	Gi_Read_Acknowledges_Irq = 0x1,	/*  not present on 660x */
++	Gi_Write_Acknowledges_Irq = 0x2,	/*  not present on 660x */
+ 	Gi_Source_Select_Mask = 0x7c,
+ 	Gi_Gate_Select_Mask = 0x1f << Gi_Gate_Select_Shift,
+ 	Gi_Gate_Select_Load_Source_Bit = 0x1000,
+@@ -656,7 +656,7 @@ static inline unsigned Gi_TC_Error_Confirm_Bit(unsigned counter_index)
+ 	return G0_TC_Error_Confirm_Bit;
+ }
+ 
+-// bits that are the same in G0/G2 and G1/G3 interrupt acknowledge registers
++/* bits that are the same in G0/G2 and G1/G3 interrupt acknowledge registers */
+ enum Gxx_Interrupt_Acknowledge_Bits {
+ 	Gi_TC_Interrupt_Ack_Bit = 0x4000,
+ 	Gi_Gate_Interrupt_Ack_Bit = 0x8000
+diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c
+index 16a26e73c994..a3c55979cf4c 100644
+--- a/drivers/staging/comedi/drivers/ni_tiocmd.c
++++ b/drivers/staging/comedi/drivers/ni_tiocmd.c
+@@ -365,7 +365,7 @@ static int should_ack_gate(struct ni_gpct *counter)
+ 
+ 	switch (counter->counter_dev->variant) {
+ 	case ni_gpct_variant_m_series:
+-	case ni_gpct_variant_660x:	// not sure if 660x really supports gate interrupts (the bits are not listed in register-level manual)
++	case ni_gpct_variant_660x:	/*  not sure if 660x really supports gate interrupts (the bits are not listed in register-level manual) */
+ 		return 1;
+ 		break;
+ 	case ni_gpct_variant_e_series:
+diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c
+index 6dbd33d7907b..c92ffca0b9ab 100644
+--- a/drivers/staging/comedi/drivers/pcl726.c
++++ b/drivers/staging/comedi/drivers/pcl726.c
+@@ -116,17 +116,17 @@ static int pcl726_detach(struct comedi_device * dev);
+ 
+ struct pcl726_board {
+ 
+-	const char *name;	// driver name
+-	int n_aochan;		// num of D/A chans
+-	int num_of_ranges;	// num of ranges
+-	unsigned int IRQbits;	// allowed interrupts
+-	unsigned int io_range;	// len of IO space
+-	char have_dio;		// 1=card have DI/DO ports
+-	int di_hi;		// ports for DI/DO operations
++	const char *name;	/*  driver name */
++	int n_aochan;		/*  num of D/A chans */
++	int num_of_ranges;	/*  num of ranges */
++	unsigned int IRQbits;	/*  allowed interrupts */
++	unsigned int io_range;	/*  len of IO space */
++	char have_dio;		/*  1=card have DI/DO ports */
++	int di_hi;		/*  ports for DI/DO operations */
+ 	int di_lo;
+ 	int do_hi;
+ 	int do_lo;
+-	const struct comedi_lrange *const *range_type_list;	// list of supported ranges
++	const struct comedi_lrange *const *range_type_list;	/*  list of supported ranges */
+ };
+ 
+ 
+@@ -362,7 +362,7 @@ static int pcl726_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 
+ static int pcl726_detach(struct comedi_device * dev)
+ {
+-//      printk("comedi%d: pcl726: remove\n",dev->minor);
++/* printk("comedi%d: pcl726: remove\n",dev->minor); */
+ 
+ #ifdef ACL6126_IRQ
+ 	if (dev->irq) {
+diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c
+index f2c6d7c5693c..c411a16f71d2 100644
+--- a/drivers/staging/comedi/drivers/pcl730.c
++++ b/drivers/staging/comedi/drivers/pcl730.c
+@@ -31,8 +31,8 @@ static int pcl730_detach(struct comedi_device * dev);
+ 
+ struct pcl730_board {
+ 
+-	const char *name;	// board name
+-	unsigned int io_range;	// len of I/O space
++	const char *name;	/*  board name */
++	unsigned int io_range;	/*  len of I/O space */
+ };
+ 
+ 
+diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
+index c5bae2989ef2..dc1a1e4a303f 100644
+--- a/drivers/staging/comedi/drivers/pcl812.c
++++ b/drivers/staging/comedi/drivers/pcl812.c
+@@ -117,7 +117,7 @@ Options for ACL-8113, ISO-813:
+ 
+ #undef PCL812_EXTDEBUG		/* if this is defined then a lot of messages is printed */
+ 
+-// hardware types of the cards
++/* hardware types of the cards */
+ #define boardPCL812PG 		 0	/* and ACL-8112PG */
+ #define boardPCL813B 		 1
+ #define boardPCL812		 2
+@@ -297,22 +297,22 @@ static int pcl812_detach(struct comedi_device * dev);
+ 
+ struct pcl812_board {
+ 
+-	const char *name;	// board name
+-	int board_type;		// type of this board
+-	int n_aichan;		// num of AI chans in S.E.
+-	int n_aichan_diff;	// DIFF num of chans
+-	int n_aochan;		// num of DA chans
+-	int n_dichan;		// DI and DO chans
++	const char *name;	/*  board name */
++	int board_type;		/*  type of this board */
++	int n_aichan;		/*  num of AI chans in S.E. */
++	int n_aichan_diff;	/*  DIFF num of chans */
++	int n_aochan;		/*  num of DA chans */
++	int n_dichan;		/*  DI and DO chans */
+ 	int n_dochan;
+-	int ai_maxdata;		// AI resolution
+-	unsigned int ai_ns_min;	// max sample speed of card v ns
+-	unsigned int i8254_osc_base;	// clock base
+-	const struct comedi_lrange *rangelist_ai;	// rangelist for A/D
+-	const struct comedi_lrange *rangelist_ao;	// rangelist for D/A
+-	unsigned int IRQbits;	// allowed IRQ
+-	unsigned char DMAbits;	// allowed DMA chans
+-	unsigned char io_range;	// iorange for this board
+-	unsigned char haveMPC508;	// 1=board use MPC508A multiplexor
++	int ai_maxdata;		/*  AI resolution */
++	unsigned int ai_ns_min;	/*  max sample speed of card v ns */
++	unsigned int i8254_osc_base;	/*  clock base */
++	const struct comedi_lrange *rangelist_ai;	/*  rangelist for A/D */
++	const struct comedi_lrange *rangelist_ao;	/*  rangelist for D/A */
++	unsigned int IRQbits;	/*  allowed IRQ */
++	unsigned char DMAbits;	/*  allowed DMA chans */
++	unsigned char io_range;	/*  iorange for this board */
++	unsigned char haveMPC508;	/*  1=board use MPC508A multiplexor */
+ };
+ 
+ 
+@@ -390,37 +390,37 @@ COMEDI_INITCLEANUP(driver_pcl812);
+ 
+ struct pcl812_private {
+ 
+-	unsigned char valid;	// =1 device is OK
+-	unsigned char dma;	// >0 use dma ( usedDMA channel)
+-	unsigned char use_diff;	// =1 diff inputs
+-	unsigned char use_MPC;	// 1=board uses MPC508A multiplexor
+-	unsigned char use_ext_trg;	// 1=board uses external trigger
+-	unsigned char range_correction;	// =1 we must add 1 to range number
+-	unsigned char old_chan_reg;	// lastly used chan/gain pair
++	unsigned char valid;	/*  =1 device is OK */
++	unsigned char dma;	/*  >0 use dma ( usedDMA channel) */
++	unsigned char use_diff;	/*  =1 diff inputs */
++	unsigned char use_MPC;	/*  1=board uses MPC508A multiplexor */
++	unsigned char use_ext_trg;	/*  1=board uses external trigger */
++	unsigned char range_correction;	/*  =1 we must add 1 to range number */
++	unsigned char old_chan_reg;	/*  lastly used chan/gain pair */
+ 	unsigned char old_gain_reg;
+-	unsigned char mode_reg_int;	// there is stored INT number for some card
+-	unsigned char ai_neverending;	// =1 we do unlimited AI
+-	unsigned char ai_eos;	// 1=EOS wake up
+-	unsigned char ai_dma;	// =1 we use DMA
+-	unsigned int ai_poll_ptr;	// how many sampes transfer poll
+-	unsigned int ai_scans;	// len of scanlist
+-	unsigned int ai_act_scan;	// how many scans we finished
+-	unsigned int ai_chanlist[MAX_CHANLIST_LEN];	// our copy of channel/range list
+-	unsigned int ai_n_chan;	// how many channels is measured
+-	unsigned int ai_flags;	// flaglist
+-	unsigned int ai_data_len;	// len of data buffer
+-	short *ai_data;	// data buffer
+-	unsigned int ai_is16b;	// =1 we have 16 bit card
+-	unsigned long dmabuf[2];	// PTR to DMA buf
+-	unsigned int dmapages[2];	// how many pages we have allocated
+-	unsigned int hwdmaptr[2];	// HW PTR to DMA buf
+-	unsigned int hwdmasize[2];	// DMA buf size in bytes
+-	unsigned int dmabytestomove[2];	// how many bytes DMA transfer
+-	int next_dma_buf;	// which buffer is next to use
+-	unsigned int dma_runs_to_end;	// how many times we must switch DMA buffers
+-	unsigned int last_dma_run;	// how many bytes to transfer on last DMA buffer
+-	unsigned int max_812_ai_mode0_rangewait;	// setling time for gain
+-	unsigned int ao_readback[2];	// data for AO readback
++	unsigned char mode_reg_int;	/*  there is stored INT number for some card */
++	unsigned char ai_neverending;	/*  =1 we do unlimited AI */
++	unsigned char ai_eos;	/*  1=EOS wake up */
++	unsigned char ai_dma;	/*  =1 we use DMA */
++	unsigned int ai_poll_ptr;	/*  how many sampes transfer poll */
++	unsigned int ai_scans;	/*  len of scanlist */
++	unsigned int ai_act_scan;	/*  how many scans we finished */
++	unsigned int ai_chanlist[MAX_CHANLIST_LEN];	/*  our copy of channel/range list */
++	unsigned int ai_n_chan;	/*  how many channels is measured */
++	unsigned int ai_flags;	/*  flaglist */
++	unsigned int ai_data_len;	/*  len of data buffer */
++	short *ai_data;	/*  data buffer */
++	unsigned int ai_is16b;	/*  =1 we have 16 bit card */
++	unsigned long dmabuf[2];	/*  PTR to DMA buf */
++	unsigned int dmapages[2];	/*  how many pages we have allocated */
++	unsigned int hwdmaptr[2];	/*  HW PTR to DMA buf */
++	unsigned int hwdmasize[2];	/*  DMA buf size in bytes */
++	unsigned int dmabytestomove[2];	/*  how many bytes DMA transfer */
++	int next_dma_buf;	/*  which buffer is next to use */
++	unsigned int dma_runs_to_end;	/*  how many times we must switch DMA buffers */
++	unsigned int last_dma_run;	/*  how many bytes to transfer on last DMA buffer */
++	unsigned int max_812_ai_mode0_rangewait;	/*  setling time for gain */
++	unsigned int ao_readback[2];	/*  data for AO readback */
+ };
+ 
+ 
+@@ -444,7 +444,7 @@ static int pcl812_ai_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ 	int timeout, hi;
+ 
+ 	outb(devpriv->mode_reg_int | 1, dev->iobase + PCL812_MODE);	/* select software trigger */
+-	setup_range_channel(dev, s, insn->chanspec, 1);	// select channel and renge
++	setup_range_channel(dev, s, insn->chanspec, 1);	/*  select channel and renge */
+ 	for (n = 0; n < insn->n; n++) {
+ 		outb(255, dev->iobase + PCL812_SOFTTRIG);	/* start conversion */
+ 		comedi_udelay(5);
+@@ -478,7 +478,7 @@ static int acl8216_ai_insn_read(struct comedi_device * dev, struct comedi_subdev
+ 	int timeout;
+ 
+ 	outb(1, dev->iobase + PCL812_MODE);	/* select software trigger */
+-	setup_range_channel(dev, s, insn->chanspec, 1);	// select channel and renge
++	setup_range_channel(dev, s, insn->chanspec, 1);	/*  select channel and renge */
+ 	for (n = 0; n < insn->n; n++) {
+ 		outb(255, dev->iobase + PCL812_SOFTTRIG);	/* start conversion */
+ 		comedi_udelay(5);
+@@ -809,18 +809,18 @@ static int pcl812_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s
+ 			cmd->flags & TRIG_ROUND_MASK);
+ 	}
+ 
+-	start_pacer(dev, -1, 0, 0);	// stop pacer
++	start_pacer(dev, -1, 0, 0);	/*  stop pacer */
+ 
+ 	devpriv->ai_n_chan = cmd->chanlist_len;
+ 	memcpy(devpriv->ai_chanlist, cmd->chanlist,
+ 		sizeof(unsigned int) * cmd->scan_end_arg);
+-	setup_range_channel(dev, s, devpriv->ai_chanlist[0], 1);	// select first channel and range
++	setup_range_channel(dev, s, devpriv->ai_chanlist[0], 1);	/*  select first channel and range */
+ 
+-	if (devpriv->dma) {	// check if we can use DMA transfer
++	if (devpriv->dma) {	/*  check if we can use DMA transfer */
+ 		devpriv->ai_dma = 1;
+ 		for (i = 1; i < devpriv->ai_n_chan; i++)
+ 			if (devpriv->ai_chanlist[0] != devpriv->ai_chanlist[i]) {
+-				devpriv->ai_dma = 0;	// we cann't use DMA :-(
++				devpriv->ai_dma = 0;	/*  we cann't use DMA :-( */
+ 				break;
+ 			}
+ 	} else
+@@ -841,14 +841,14 @@ static int pcl812_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s
+ 	devpriv->ai_poll_ptr = 0;
+ 	s->async->cur_chan = 0;
+ 
+-	if ((devpriv->ai_flags & TRIG_WAKE_EOS)) {	// don't we want wake up every scan?
++	if ((devpriv->ai_flags & TRIG_WAKE_EOS)) {	/*  don't we want wake up every scan? */
+ 		devpriv->ai_eos = 1;
+ 		if (devpriv->ai_n_chan == 1)
+-			devpriv->ai_dma = 0;	// DMA is useless for this situation
++			devpriv->ai_dma = 0;	/*  DMA is useless for this situation */
+ 	}
+ 
+ 	if (devpriv->ai_dma) {
+-		if (devpriv->ai_eos) {	// we use EOS, so adapt DMA buffer to one scan
++		if (devpriv->ai_eos) {	/*  we use EOS, so adapt DMA buffer to one scan */
+ 			devpriv->dmabytestomove[0] =
+ 				devpriv->ai_n_chan * sizeof(short);
+ 			devpriv->dmabytestomove[1] =
+@@ -866,9 +866,9 @@ static int pcl812_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s
+ 			if (devpriv->ai_neverending) {
+ 				devpriv->dma_runs_to_end = 1;
+ 			} else {
+-				bytes = devpriv->ai_n_chan * devpriv->ai_scans * sizeof(short);	// how many samples we must transfer?
+-				devpriv->dma_runs_to_end = bytes / devpriv->dmabytestomove[0];	// how many DMA pages we must fill
+-				devpriv->last_dma_run = bytes % devpriv->dmabytestomove[0];	//on last dma transfer must be moved
++				bytes = devpriv->ai_n_chan * devpriv->ai_scans * sizeof(short);	/*  how many samples we must transfer? */
++				devpriv->dma_runs_to_end = bytes / devpriv->dmabytestomove[0];	/*  how many DMA pages we must fill */
++				devpriv->last_dma_run = bytes % devpriv->dmabytestomove[0];	/* on last dma transfer must be moved */
+ 				if (devpriv->dma_runs_to_end == 0)
+ 					devpriv->dmabytestomove[0] =
+ 						devpriv->last_dma_run;
+@@ -907,9 +907,9 @@ static int pcl812_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s
+ 	}
+ 
+ 	if (devpriv->ai_dma) {
+-		outb(devpriv->mode_reg_int | 2, dev->iobase + PCL812_MODE);	// let's go!
++		outb(devpriv->mode_reg_int | 2, dev->iobase + PCL812_MODE);	/*  let's go! */
+ 	} else {
+-		outb(devpriv->mode_reg_int | 6, dev->iobase + PCL812_MODE);	// let's go!
++		outb(devpriv->mode_reg_int | 6, dev->iobase + PCL812_MODE);	/*  let's go! */
+ 	}
+ 
+ #ifdef PCL812_EXTDEBUG
+@@ -991,7 +991,7 @@ static void transfer_from_dma_buf(struct comedi_device * dev, struct comedi_subd
+ 
+ 	s->async->events = 0;
+ 	for (i = len; i; i--) {
+-		comedi_buf_put(s->async, ptr[bufptr++]);	// get one sample
++		comedi_buf_put(s->async, ptr[bufptr++]);	/*  get one sample */
+ 
+ 		if (s->async->cur_chan == 0) {
+ 			devpriv->ai_act_scan++;
+@@ -1085,12 +1085,12 @@ static int pcl812_ai_poll(struct comedi_device * dev, struct comedi_subdevice *
+ 	unsigned int top1, top2, i;
+ 
+ 	if (!devpriv->ai_dma)
+-		return 0;	// poll is valid only for DMA transfer
++		return 0;	/*  poll is valid only for DMA transfer */
+ 
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 
+ 	for (i = 0; i < 10; i++) {
+-		top1 = get_dma_residue(devpriv->ai_dma);	// where is now DMA
++		top1 = get_dma_residue(devpriv->ai_dma);	/*  where is now DMA */
+ 		top2 = get_dma_residue(devpriv->ai_dma);
+ 		if (top1 == top2)
+ 			break;
+@@ -1101,10 +1101,10 @@ static int pcl812_ai_poll(struct comedi_device * dev, struct comedi_subdevice *
+ 		return 0;
+ 	}
+ 
+-	top1 = devpriv->dmabytestomove[1 - devpriv->next_dma_buf] - top1;	// where is now DMA in buffer
+-	top1 >>= 1;		// sample position
++	top1 = devpriv->dmabytestomove[1 - devpriv->next_dma_buf] - top1;	/*  where is now DMA in buffer */
++	top1 >>= 1;		/*  sample position */
+ 	top2 = top1 - devpriv->ai_poll_ptr;
+-	if (top2 < 1) {		// no new samples
++	if (top2 < 1) {		/*  no new samples */
+ 		comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ 		return 0;
+ 	}
+@@ -1113,7 +1113,7 @@ static int pcl812_ai_poll(struct comedi_device * dev, struct comedi_subdevice *
+ 		(void *)devpriv->dmabuf[1 - devpriv->next_dma_buf],
+ 		devpriv->ai_poll_ptr, top2);
+ 
+-	devpriv->ai_poll_ptr = top1;	// new buffer position
++	devpriv->ai_poll_ptr = top1;	/*  new buffer position */
+ 
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ 
+@@ -1126,24 +1126,24 @@ static int pcl812_ai_poll(struct comedi_device * dev, struct comedi_subdevice *
+ static void setup_range_channel(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int rangechan, char wait)
+ {
+-	unsigned char chan_reg = CR_CHAN(rangechan);	// normal board
+-	unsigned char gain_reg = CR_RANGE(rangechan) + devpriv->range_correction;	// gain index
++	unsigned char chan_reg = CR_CHAN(rangechan);	/*  normal board */
++	unsigned char gain_reg = CR_RANGE(rangechan) + devpriv->range_correction;	/*  gain index */
+ 
+ 	if ((chan_reg == devpriv->old_chan_reg)
+ 		&& (gain_reg == devpriv->old_gain_reg))
+-		return;		// we can return, no change
++		return;		/*  we can return, no change */
+ 
+ 	devpriv->old_chan_reg = chan_reg;
+ 	devpriv->old_gain_reg = gain_reg;
+ 
+ 	if (devpriv->use_MPC) {
+ 		if (devpriv->use_diff) {
+-			chan_reg = chan_reg | 0x30;	// DIFF inputs
++			chan_reg = chan_reg | 0x30;	/*  DIFF inputs */
+ 		} else {
+ 			if (chan_reg & 0x80) {
+-				chan_reg = chan_reg | 0x20;	// SE inputs 8-15
++				chan_reg = chan_reg | 0x20;	/*  SE inputs 8-15 */
+ 			} else {
+-				chan_reg = chan_reg | 0x10;	// SE inputs 0-7
++				chan_reg = chan_reg | 0x10;	/*  SE inputs 0-7 */
+ 			}
+ 		}
+ 	}
+@@ -1152,7 +1152,7 @@ static void setup_range_channel(struct comedi_device * dev, struct comedi_subdev
+ 	outb(gain_reg, dev->iobase + PCL812_GAIN);	/* select gain */
+ 
+ 	if (wait) {
+-		comedi_udelay(devpriv->max_812_ai_mode0_rangewait);	// XXX this depends on selected range and can be very long for some high gain ranges!
++		comedi_udelay(devpriv->max_812_ai_mode0_rangewait);	/*  XXX this depends on selected range and can be very long for some high gain ranges! */
+ 	}
+ }
+ 
+@@ -1213,7 +1213,7 @@ static int pcl812_ai_cancel(struct comedi_device * dev, struct comedi_subdevice
+ 		disable_dma(devpriv->dma);
+ 	outb(0, dev->iobase + PCL812_CLRINT);	/* clear INT request */
+ 	outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE);	/* Stop A/D */
+-	start_pacer(dev, -1, 0, 0);	// stop 8254
++	start_pacer(dev, -1, 0, 0);	/*  stop 8254 */
+ 	outb(0, dev->iobase + PCL812_CLRINT);	/* clear INT request */
+ #ifdef PCL812_EXTDEBUG
+ 	rt_printk("pcl812 EDBG: END: pcl812_ai_cancel(...)\n");
+@@ -1231,7 +1231,7 @@ static void pcl812_reset(struct comedi_device * dev)
+ #endif
+ 	outb(0, dev->iobase + PCL812_MUX);
+ 	outb(0 + devpriv->range_correction, dev->iobase + PCL812_GAIN);
+-	devpriv->old_chan_reg = -1;	// invalidate chain/gain memory
++	devpriv->old_chan_reg = -1;	/*  invalidate chain/gain memory */
+ 	devpriv->old_gain_reg = -1;
+ 
+ 	switch (this_board->board_type) {
+@@ -1244,7 +1244,7 @@ static void pcl812_reset(struct comedi_device * dev)
+ 	case boardA821:
+ 		outb(0, dev->iobase + PCL812_DA1_LO);
+ 		outb(0, dev->iobase + PCL812_DA1_HI);
+-		start_pacer(dev, -1, 0, 0);	// stop 8254
++		start_pacer(dev, -1, 0, 0);	/*  stop 8254 */
+ 		outb(0, dev->iobase + PCL812_DO_HI);
+ 		outb(0, dev->iobase + PCL812_DO_LO);
+ 		outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE);
+@@ -1570,7 +1570,7 @@ static int pcl812_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	case boardACL8112:
+ 		devpriv->max_812_ai_mode0_rangewait = 1;
+ 		if (it->options[3] > 0)
+-			devpriv->use_ext_trg = 1;	// we use external trigger
++			devpriv->use_ext_trg = 1;	/*  we use external trigger */
+ 	case boardA821:
+ 		devpriv->max_812_ai_mode0_rangewait = 1;
+ 		devpriv->mode_reg_int = (irq << 4) & 0xf0;
+diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c
+index a3ed3a0e855a..747882d7846f 100644
+--- a/drivers/staging/comedi/drivers/pcm3724.c
++++ b/drivers/staging/comedi/drivers/pcm3724.c
+@@ -66,14 +66,14 @@ static int pcm3724_attach(struct comedi_device * dev, struct comedi_devconfig *
+ static int pcm3724_detach(struct comedi_device * dev);
+ 
+ struct pcm3724_board {
+-	const char *name;	// driver name
+-	int dio;		// num of DIO
+-	int numofports;		// num of 8255 subdevices
+-	unsigned int IRQbits;	// allowed interrupts
+-	unsigned int io_range;	// len of IO space
++	const char *name;	/*  driver name */
++	int dio;		/*  num of DIO */
++	int numofports;		/*  num of 8255 subdevices */
++	unsigned int IRQbits;	/*  allowed interrupts */
++	unsigned int io_range;	/*  len of IO space */
+ };
+ 
+-//used to track configured dios
++/* used to track configured dios */
+ struct priv_pcm3724 {
+ 	int dio_1;
+ 	int dio_2;
+@@ -98,20 +98,20 @@ static struct comedi_driver driver_pcm3724 = {
+ 
+ COMEDI_INITCLEANUP(driver_pcm3724);
+ 
+-//          (setq c-basic-offset 8)
++/* (setq c-basic-offset 8) */
+ 
+ static int subdev_8255_cb(int dir, int port, int data, unsigned long arg)
+ {
+ 	unsigned long iobase = arg;
+ 	unsigned char inbres;
+-	//printk("8255cb %d %d %d %lx\n", dir,port,data,arg);
++	/* printk("8255cb %d %d %d %lx\n", dir,port,data,arg); */
+ 	if (dir) {
+-		//printk("8255 cb   outb(%x, %lx)\n", data, iobase+port);
++		/* printk("8255 cb   outb(%x, %lx)\n", data, iobase+port); */
+ 		outb(data, iobase + port);
+ 		return 0;
+ 	} else {
+ 		inbres = inb(iobase + port);
+-		//printk("8255 cb   inb(%lx) = %x\n", iobase+port, inbres);
++		/* printk("8255 cb   inb(%lx) = %x\n", iobase+port, inbres); */
+ 		return inbres;
+ 	}
+ }
+@@ -173,7 +173,7 @@ static void do_3724_config(struct comedi_device * dev, struct comedi_subdevice *
+ 		port_8255_cfg = dev->iobase + SIZE_8255 + _8255_CR;
+ 	}
+ 	outb(buffer_config, dev->iobase + 8);	/* update buffer register */
+-	//printk("pcm3724 buffer_config (%lx) %d, %x\n", dev->iobase + _8255_CR, chanspec, buffer_config);
++	/* printk("pcm3724 buffer_config (%lx) %d, %x\n", dev->iobase + _8255_CR, chanspec, buffer_config); */
+ 	outb(config, port_8255_cfg);
+ }
+ 
+@@ -187,9 +187,9 @@ static void enable_chan(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	priv = (struct priv_pcm3724 *) (dev->private);
+ 
+ 	mask = 1 << CR_CHAN(chanspec);
+-	if (s == dev->subdevices) {	// subdev 0
++	if (s == dev->subdevices) {	/*  subdev 0 */
+ 		priv->dio_1 |= mask;
+-	} else {		//subdev 1
++	} else {		/* subdev 1 */
+ 		priv->dio_2 |= mask;
+ 	}
+ 	if (priv->dio_1 & 0xff0000) {
+@@ -210,7 +210,7 @@ static void enable_chan(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	if (priv->dio_2 & 0xff) {
+ 		gatecfg |= GATE_A1;
+ 	}
+-	//      printk("gate control %x\n", gatecfg);
++	/*       printk("gate control %x\n", gatecfg); */
+ 	outb(gatecfg, dev->iobase + 9);
+ }
+ 
+diff --git a/drivers/staging/comedi/drivers/pcm3730.c b/drivers/staging/comedi/drivers/pcm3730.c
+index 1de555fe645c..41983d03dabf 100644
+--- a/drivers/staging/comedi/drivers/pcm3730.c
++++ b/drivers/staging/comedi/drivers/pcm3730.c
+@@ -19,9 +19,9 @@ Configuration options:
+ 
+ #include 
+ 
+-#define PCM3730_SIZE 4		// consecutive io port addresses
++#define PCM3730_SIZE 4		/*  consecutive io port addresses */
+ 
+-#define PCM3730_DOA 0		// offsets for each port
++#define PCM3730_DOA 0		/*  offsets for each port */
+ #define PCM3730_DOB 2
+ #define PCM3730_DOC 3
+ #define PCM3730_DIA 0
+diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c
+index 8a0bf6854939..ca439ba5c01d 100644
+--- a/drivers/staging/comedi/drivers/poc.c
++++ b/drivers/staging/comedi/drivers/poc.c
+@@ -72,7 +72,7 @@ static const struct boarddef_struct boards[] = {
+ 	{
+ 	      name:	"dac02",
+ 	      iosize:	8,
+-			//setup:                dac02_setup,
++			/* setup:                dac02_setup, */
+ 	      type:	COMEDI_SUBD_AO,
+ 	      n_chan:	2,
+ 	      n_bits:	12,
+@@ -196,7 +196,7 @@ static int dac02_ao_winsn(struct comedi_device * dev, struct comedi_subdevice *
+ 	((unsigned int *) dev->private)[chan] = data[0];
+ 	output = data[0];
+ #ifdef wrong
+-	// convert to complementary binary if range is bipolar
++	/*  convert to complementary binary if range is bipolar */
+ 	if ((CR_RANGE(insn->chanspec) & 0x2) == 0)
+ 		output = ~output;
+ #endif
+diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c
+index 5c7ef8edefcd..14bb8d19353e 100644
+--- a/drivers/staging/comedi/drivers/rti800.c
++++ b/drivers/staging/comedi/drivers/rti800.c
+@@ -177,7 +177,7 @@ static irqreturn_t rti800_interrupt(int irq, void *dev)
+ 	return IRQ_HANDLED;
+ }
+ 
+-// settling delay times in usec for different gains
++/* settling delay times in usec for different gains */
+ static const int gaindelay[] = { 10, 20, 40, 80 };
+ 
+ static int rti800_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
+index 844fd5e2e3a9..602fa85dc70f 100644
+--- a/drivers/staging/comedi/drivers/serial2002.c
++++ b/drivers/staging/comedi/drivers/serial2002.c
+@@ -62,7 +62,7 @@ static const struct serial2002_board serial2002_boards[] = {
+ 
+ struct serial2002_range_table_t {
+ 
+-	// HACK...
++	/*  HACK... */
+ 	int length;
+ 	struct comedi_krange range;
+ };
+@@ -70,8 +70,8 @@ struct serial2002_range_table_t {
+ 
+ struct serial2002_private {
+ 
+-	int port;		// /dev/ttyS
+-	int speed;		// baudrate
++	int port;		/*  /dev/ttyS */
++	int speed;		/*  baudrate */
+ 	struct file *tty;
+ 	unsigned int ao_readback[32];
+ 	unsigned char digital_in_mapping[32];
+@@ -238,11 +238,11 @@ static void tty_setspeed(struct file *f, int speed)
+ 	oldfs = get_fs();
+ 	set_fs(KERNEL_DS);
+ 	{
+-		// Set speed
++		/*  Set speed */
+ 		struct termios settings;
+ 
+ 		tty_ioctl(f, TCGETS, (unsigned long)&settings);
+-//    printk("Speed: %d\n", settings.c_cflag & (CBAUD | CBAUDEX));
++/* printk("Speed: %d\n", settings.c_cflag & (CBAUD | CBAUDEX)); */
+ 		settings.c_iflag = 0;
+ 		settings.c_oflag = 0;
+ 		settings.c_lflag = 0;
+@@ -284,10 +284,10 @@ static void tty_setspeed(struct file *f, int speed)
+ 			break;
+ 		}
+ 		tty_ioctl(f, TCSETS, (unsigned long)&settings);
+-//    printk("Speed: %d\n", settings.c_cflag & (CBAUD | CBAUDEX));
++/* printk("Speed: %d\n", settings.c_cflag & (CBAUD | CBAUDEX)); */
+ 	}
+ 	{
+-		// Set low latency
++		/*  Set low latency */
+ 		struct serial_struct settings;
+ 
+ 		tty_ioctl(f, TIOCGSERIAL, (unsigned long)&settings);
+@@ -437,7 +437,7 @@ static void serial_2002_open(struct comedi_device * dev)
+ 		}
+ 
+ 		tty_setspeed(devpriv->tty, devpriv->speed);
+-		poll_channel(devpriv->tty, 31);	// Start reading configuration
++		poll_channel(devpriv->tty, 31);	/*  Start reading configuration */
+ 		while (1) {
+ 			struct serial_data data;
+ 
+@@ -557,7 +557,7 @@ static void serial_2002_open(struct comedi_device * dev)
+ 			}
+ 		}
+ 		for (i = 0; i <= 4; i++) {
+-			// Fill in subdev data
++			/*  Fill in subdev data */
+ 			struct config_t *c;
+ 			unsigned char *mapping = 0;
+ 			struct serial2002_range_table_t *range = 0;
+diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c
+index 1628d216cdd4..c9a8fb5e8524 100644
+--- a/drivers/staging/comedi/drivers/ssv_dnp.c
++++ b/drivers/staging/comedi/drivers/ssv_dnp.c
+@@ -74,7 +74,6 @@ static const struct dnp_board dnp_boards[] = {	/* we only support one DNP 'board
+ /* This structure is for data unique to the DNP driver --------------------- */
+ struct dnp_private_data {
+ 
+-	//
+ };
+ 
+ 
+@@ -126,7 +125,7 @@ static int dnp_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ 
+ 	/* Autoprobing: this should find out which board we have. Currently only   */
+ 	/* the 1486 board is supported and autoprobing is not implemented :-)      */
+-	//dev->board_ptr = dnp_probe(dev);
++	/* dev->board_ptr = dnp_probe(dev); */
+ 
+ 	/* Initialize the name of the board. We can use the "thisboard" macro now. */
+ 	dev->board_name = thisboard->name;
+diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c
+index dd3b1119319b..96284f020be1 100644
+--- a/drivers/staging/comedi/drivers/unioxx5.c
++++ b/drivers/staging/comedi/drivers/unioxx5.c
+@@ -94,7 +94,7 @@ static int __unioxx5_digital_write(struct unioxx5_subd_priv * usp, unsigned int
+ 	int channel, int minor);
+ static int __unioxx5_digital_read(struct unioxx5_subd_priv * usp, unsigned int * data,
+ 	int channel, int minor);
+-//static void __unioxx5_digital_config(struct unioxx5_subd_priv* usp, int mode);
++/* static void __unioxx5_digital_config(struct unioxx5_subd_priv* usp, int mode); */
+ static int __unioxx5_analog_write(struct unioxx5_subd_priv * usp, unsigned int * data,
+ 	int channel, int minor);
+ static int __unioxx5_analog_read(struct unioxx5_subd_priv * usp, unsigned int * data,
+@@ -418,7 +418,7 @@ static int __unioxx5_analog_write(struct unioxx5_subd_priv * usp, unsigned int *
+ 	/* saving major byte */
+ 	usp->usp_extra_data[module][i] = (unsigned char)((*data & 0xFF00) >> 8);
+ 
+-	//while(!((inb(usp->usp_iobase + 0)) & TxBE));
++	/* while(!((inb(usp->usp_iobase + 0)) & TxBE)); */
+ 	outb(module + 1, usp->usp_iobase + 5);	/* sending module number to card(1 .. 12) */
+ 	outb('W', usp->usp_iobase + 6);	/* sends (W)rite command to module */
+ 
+diff --git a/drivers/staging/comedi/kcomedilib/ksyms.c b/drivers/staging/comedi/kcomedilib/ksyms.c
+index 3db86dabf878..314765db51fe 100644
+--- a/drivers/staging/comedi/kcomedilib/ksyms.c
++++ b/drivers/staging/comedi/kcomedilib/ksyms.c
+@@ -59,7 +59,7 @@ EXPORT_SYMBOL(comedi_close);
+ EXPORT_SYMBOL(comedi_loglevel);
+ EXPORT_SYMBOL(comedi_perror);
+ EXPORT_SYMBOL(comedi_strerror);
+-//EXPORT_SYMBOL(comedi_errno);
++/* EXPORT_SYMBOL(comedi_errno); */
+ EXPORT_SYMBOL(comedi_fileno);
+ 
+ /* device queries */
+@@ -73,8 +73,10 @@ EXPORT_SYMBOL(comedi_get_subdevice_type);
+ EXPORT_SYMBOL(comedi_find_subdevice_by_type);
+ EXPORT_SYMBOL(comedi_get_subdevice_flags);
+ EXPORT_SYMBOL(comedi_get_n_channels);
+-//EXPORT_SYMBOL(comedi_range_is_chan_specific);
+-//EXPORT_SYMBOL(comedi_maxdata_is_chan_specific);
++/*
++* EXPORT_SYMBOL(comedi_range_is_chan_specific);
++* EXPORT_SYMBOL(comedi_maxdata_is_chan_specific);
++*/
+ 
+ /* channel queries */
+ EXPORT_SYMBOL(comedi_get_maxdata);
+@@ -82,25 +84,29 @@ EXPORT_SYMBOL(comedi_get_maxdata);
+ EXPORT_SYMBOL(comedi_get_rangetype);
+ #endif
+ EXPORT_SYMBOL(comedi_get_n_ranges);
+-//EXPORT_SYMBOL(comedi_find_range);
++/* EXPORT_SYMBOL(comedi_find_range); */
+ 
+ /* buffer queries */
+ EXPORT_SYMBOL(comedi_get_buffer_size);
+-//EXPORT_SYMBOL(comedi_get_max_buffer_size);
+-//EXPORT_SYMBOL(comedi_set_buffer_size);
++/*
++* EXPORT_SYMBOL(comedi_get_max_buffer_size);
++* EXPORT_SYMBOL(comedi_set_buffer_size);
++*/
+ EXPORT_SYMBOL(comedi_get_buffer_contents);
+ EXPORT_SYMBOL(comedi_get_buffer_offset);
+ 
+ /* low-level stuff */
+-//EXPORT_SYMBOL(comedi_trigger);
+-//EXPORT_SYMBOL(comedi_do_insnlist);
++/*
++* EXPORT_SYMBOL(comedi_trigger); EXPORT_SYMBOL(comedi_do_insnlist);
++*/
+ EXPORT_SYMBOL(comedi_do_insn);
+ EXPORT_SYMBOL(comedi_lock);
+ EXPORT_SYMBOL(comedi_unlock);
+ 
+ /* physical units */
+-//EXPORT_SYMBOL(comedi_to_phys);
+-//EXPORT_SYMBOL(comedi_from_phys);
++/*
++* EXPORT_SYMBOL(comedi_to_phys); EXPORT_SYMBOL(comedi_from_phys);
++*/
+ 
+ /* synchronous stuff */
+ EXPORT_SYMBOL(comedi_data_read);
+@@ -113,13 +119,16 @@ EXPORT_SYMBOL(comedi_dio_write);
+ EXPORT_SYMBOL(comedi_dio_bitfield);
+ 
+ /* slowly varying stuff */
+-//EXPORT_SYMBOL(comedi_sv_init);
+-//EXPORT_SYMBOL(comedi_sv_update);
+-//EXPORT_SYMBOL(comedi_sv_measure);
++/*
++* EXPORT_SYMBOL(comedi_sv_init); EXPORT_SYMBOL(comedi_sv_update);
++* EXPORT_SYMBOL(comedi_sv_measure);
++*/
+ 
+ /* commands */
+-//EXPORT_SYMBOL(comedi_get_cmd_src_mask);
+-//EXPORT_SYMBOL(comedi_get_cmd_generic_timed);
++/*
++* EXPORT_SYMBOL(comedi_get_cmd_src_mask);
++* EXPORT_SYMBOL(comedi_get_cmd_generic_timed);
++*/
+ EXPORT_SYMBOL(comedi_cancel);
+ EXPORT_SYMBOL(comedi_command);
+ EXPORT_SYMBOL(comedi_command_test);
+@@ -129,12 +138,14 @@ EXPORT_SYMBOL(comedi_poll);
+ EXPORT_SYMBOL(comedi_mark_buffer_read);
+ EXPORT_SYMBOL(comedi_mark_buffer_written);
+ 
+-//EXPORT_SYMBOL(comedi_get_range);
++/* EXPORT_SYMBOL(comedi_get_range); */
+ EXPORT_SYMBOL(comedi_get_len_chanlist);
+ 
+ /* deprecated */
+-//EXPORT_SYMBOL(comedi_get_timer);
+-//EXPORT_SYMBOL(comedi_timed_1chan);
++/*
++* EXPORT_SYMBOL(comedi_get_timer);
++* EXPORT_SYMBOL(comedi_timed_1chan);
++*/
+ 
+ /* alpha */
+-//EXPORT_SYMBOL(comedi_set_global_oor_behavior);
++/* EXPORT_SYMBOL(comedi_set_global_oor_behavior); */

commit 232f650253a04b52def9974f47c15f086f7772a5
+Author: Bill Pemberton 
+Date:   Fri Mar 27 11:31:27 2009 -0400
+
+    Staging: comedi: remove C99 comments in s526.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
+index a7b6f711afca..e419a7c6943d 100644
+--- a/drivers/staging/comedi/drivers/s526.c
++++ b/drivers/staging/comedi/drivers/s526.c
+@@ -277,8 +277,8 @@ static int s526_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ 	struct comedi_subdevice *s;
+ 	int iobase;
+ 	int i, n;
+-//      short value;
+-//      int subdev_channel = 0;
++/* short value; */
++/* int subdev_channel = 0; */
+ 
+ 	printk("comedi%d: s526: ", dev->minor);
+ 
+@@ -334,12 +334,12 @@ static int s526_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ 	/* Command are not implemented yet, however they are necessary to
+ 	   allocate the necessary memory for the comedi_async struct (used
+ 	   to trigger the GPCT in case of pulsegenerator function */
+-	//s->do_cmd = s526_gpct_cmd;
+-	//s->do_cmdtest = s526_gpct_cmdtest;
+-	//s->cancel = s526_gpct_cancel;
++	/* s->do_cmd = s526_gpct_cmd; */
++	/* s->do_cmdtest = s526_gpct_cmdtest; */
++	/* s->cancel = s526_gpct_cancel; */
+ 
+ 	s = dev->subdevices + 1;
+-	//dev->read_subdev=s;
++	/* dev->read_subdev=s; */
+ 	/* analog input subdevice */
+ 	s->type = COMEDI_SUBD_AI;
+ 	/* we support differential */
+@@ -383,18 +383,18 @@ static int s526_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ 	return 1;
+ 
+ #if 0
+-	// Example of Counter Application
+-	//One-shot (software trigger)
+-	cmReg.reg.coutSource = 0;	// out RCAP
+-	cmReg.reg.coutPolarity = 1;	// Polarity inverted
+-	cmReg.reg.autoLoadResetRcap = 1;	// Auto load 0:disabled, 1:enabled
+-	cmReg.reg.hwCtEnableSource = 3;	// NOT RCAP
+-	cmReg.reg.ctEnableCtrl = 2;	// Hardware
+-	cmReg.reg.clockSource = 2;	// Internal
+-	cmReg.reg.countDir = 1;	// Down
+-	cmReg.reg.countDirCtrl = 1;	// Software
+-	cmReg.reg.outputRegLatchCtrl = 0;	// latch on read
+-	cmReg.reg.preloadRegSel = 0;	// PR0
++	/*  Example of Counter Application */
++	/* One-shot (software trigger) */
++	cmReg.reg.coutSource = 0;	/*  out RCAP */
++	cmReg.reg.coutPolarity = 1;	/*  Polarity inverted */
++	cmReg.reg.autoLoadResetRcap = 1;	/*  Auto load 0:disabled, 1:enabled */
++	cmReg.reg.hwCtEnableSource = 3;	/*  NOT RCAP */
++	cmReg.reg.ctEnableCtrl = 2;	/*  Hardware */
++	cmReg.reg.clockSource = 2;	/*  Internal */
++	cmReg.reg.countDir = 1;	/*  Down */
++	cmReg.reg.countDirCtrl = 1;	/*  Software */
++	cmReg.reg.outputRegLatchCtrl = 0;	/*  latch on read */
++	cmReg.reg.preloadRegSel = 0;	/*  PR0 */
+ 	cmReg.reg.reserved = 0;
+ 
+ 	outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
+@@ -402,24 +402,24 @@ static int s526_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ 	outw(0x0001, ADDR_CHAN_REG(REG_C0H, subdev_channel));
+ 	outw(0x3C68, ADDR_CHAN_REG(REG_C0L, subdev_channel));
+ 
+-	outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel));	// Reset the counter
+-	outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel));	// Load the counter from PR0
++	outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel));	/*  Reset the counter */
++	outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel));	/*  Load the counter from PR0 */
+ 
+-	outw(0x0008, ADDR_CHAN_REG(REG_C0C, subdev_channel));	// Reset RCAP (fires one-shot)
++	outw(0x0008, ADDR_CHAN_REG(REG_C0C, subdev_channel));	/*  Reset RCAP (fires one-shot) */
+ 
+ #else
+ 
+-	// Set Counter Mode Register
+-	cmReg.reg.coutSource = 0;	// out RCAP
+-	cmReg.reg.coutPolarity = 0;	// Polarity inverted
+-	cmReg.reg.autoLoadResetRcap = 0;	// Auto load disabled
+-	cmReg.reg.hwCtEnableSource = 2;	// NOT RCAP
+-	cmReg.reg.ctEnableCtrl = 1;	// 1: Software,  >1 : Hardware
+-	cmReg.reg.clockSource = 3;	// x4
+-	cmReg.reg.countDir = 0;	// up
+-	cmReg.reg.countDirCtrl = 0;	// quadrature
+-	cmReg.reg.outputRegLatchCtrl = 0;	// latch on read
+-	cmReg.reg.preloadRegSel = 0;	// PR0
++	/*  Set Counter Mode Register */
++	cmReg.reg.coutSource = 0;	/*  out RCAP */
++	cmReg.reg.coutPolarity = 0;	/*  Polarity inverted */
++	cmReg.reg.autoLoadResetRcap = 0;	/*  Auto load disabled */
++	cmReg.reg.hwCtEnableSource = 2;	/*  NOT RCAP */
++	cmReg.reg.ctEnableCtrl = 1;	/*  1: Software,  >1 : Hardware */
++	cmReg.reg.clockSource = 3;	/*  x4 */
++	cmReg.reg.countDir = 0;	/*  up */
++	cmReg.reg.countDirCtrl = 0;	/*  quadrature */
++	cmReg.reg.outputRegLatchCtrl = 0;	/*  latch on read */
++	cmReg.reg.preloadRegSel = 0;	/*  PR0 */
+ 	cmReg.reg.reserved = 0;
+ 
+ 	n = 0;
+@@ -429,21 +429,21 @@ static int s526_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ 	udelay(1000);
+ 	printk("Read back mode reg=0x%04x\n", inw(ADDR_CHAN_REG(REG_C0M, n)));
+ 
+-	// Load the pre-laod register high word
+-//                      value = (short) (0x55);
+-//                      outw(value, ADDR_CHAN_REG(REG_C0H, n));
++	/*  Load the pre-laod register high word */
++/* value = (short) (0x55); */
++/* outw(value, ADDR_CHAN_REG(REG_C0H, n)); */
+ 
+-	// Load the pre-laod register low word
+-//                      value = (short)(0xaa55);
+-//                      outw(value, ADDR_CHAN_REG(REG_C0L, n));
++	/*  Load the pre-laod register low word */
++/* value = (short)(0xaa55); */
++/* outw(value, ADDR_CHAN_REG(REG_C0L, n)); */
+ 
+-	// Write the Counter Control Register
+-//                      outw(value, ADDR_CHAN_REG(REG_C0C, 0));
++	/*  Write the Counter Control Register */
++/* outw(value, ADDR_CHAN_REG(REG_C0C, 0)); */
+ 
+-	// Reset the counter if it is software preload
++	/*  Reset the counter if it is software preload */
+ 	if (cmReg.reg.autoLoadResetRcap == 0) {
+-		outw(0x8000, ADDR_CHAN_REG(REG_C0C, n));	// Reset the counter
+-		outw(0x4000, ADDR_CHAN_REG(REG_C0C, n));	// Load the counter from PR0
++		outw(0x8000, ADDR_CHAN_REG(REG_C0C, n));	/*  Reset the counter */
++		outw(0x4000, ADDR_CHAN_REG(REG_C0C, n));	/*  Load the counter from PR0 */
+ 	}
+ 
+ 	outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, n));
+@@ -481,23 +481,23 @@ static int s526_detach(struct comedi_device * dev)
+ static int s526_gpct_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	int i;			// counts the Data
++	int i;			/*  counts the Data */
+ 	int counter_channel = CR_CHAN(insn->chanspec);
+ 	unsigned short datalow;
+ 	unsigned short datahigh;
+ 
+-	// Check if (n > 0)
++	/*  Check if (n > 0) */
+ 	if (insn->n <= 0) {
+ 		printk("s526: INSN_READ: n should be > 0\n");
+ 		return -EINVAL;
+ 	}
+-	// Read the low word first
++	/*  Read the low word first */
+ 	for (i = 0; i < insn->n; i++) {
+ 		datalow = inw(ADDR_CHAN_REG(REG_C0L, counter_channel));
+ 		datahigh = inw(ADDR_CHAN_REG(REG_C0H, counter_channel));
+ 		data[i] = (int)(datahigh & 0x00FF);
+ 		data[i] = (data[i] << 16) | (datalow & 0xFFFF);
+-//              printk("s526 GPCT[%d]: %x(0x%04x, 0x%04x)\n", counter_channel, data[i], datahigh, datalow);
++/* printk("s526 GPCT[%d]: %x(0x%04x, 0x%04x)\n", counter_channel, data[i], datahigh, datalow); */
+ 	}
+ 	return i;
+ }
+@@ -505,20 +505,20 @@ static int s526_gpct_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ static int s526_gpct_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	int subdev_channel = CR_CHAN(insn->chanspec);	// Unpack chanspec
++	int subdev_channel = CR_CHAN(insn->chanspec);	/*  Unpack chanspec */
+ 	int i;
+ 	short value;
+ 
+-//        printk("s526: GPCT_INSN_CONFIG: Configuring Channel %d\n", subdev_channel);
++/* printk("s526: GPCT_INSN_CONFIG: Configuring Channel %d\n", subdev_channel); */
+ 
+ 	for (i = 0; i < MAX_GPCT_CONFIG_DATA; i++) {
+ 		devpriv->s526_gpct_config[subdev_channel].data[i] =
+ 			insn->data[i];
+-//              printk("data[%d]=%x\n", i, insn->data[i]);
++/* printk("data[%d]=%x\n", i, insn->data[i]); */
+ 	}
+ 
+-	// Check what type of Counter the user requested, data[0] contains
+-	// the Application type
++	/*  Check what type of Counter the user requested, data[0] contains */
++	/*  the Application type */
+ 	switch (insn->data[0]) {
+ 	case INSN_CONFIG_GPCT_QUADRATURE_ENCODER:
+ 		/*
+@@ -531,19 +531,19 @@ static int s526_gpct_insn_config(struct comedi_device * dev, struct comedi_subde
+ 		devpriv->s526_gpct_config[subdev_channel].app =
+ 			PositionMeasurement;
+ 
+-/*
+-			// Example of Counter Application
+-			//One-shot (software trigger)
+-			cmReg.reg.coutSource		= 0; // out RCAP
+-			cmReg.reg.coutPolarity		= 1; // Polarity inverted
+-			cmReg.reg.autoLoadResetRcap	= 0; // Auto load disabled
+-			cmReg.reg.hwCtEnableSource	= 3; // NOT RCAP
+-			cmReg.reg.ctEnableCtrl		= 2; // Hardware
+-			cmReg.reg.clockSource		= 2; // Internal
+-			cmReg.reg.countDir		= 1; // Down
+-			cmReg.reg.countDirCtrl		= 1; // Software
+-			cmReg.reg.outputRegLatchCtrl	= 0; // latch on read
+-			cmReg.reg.preloadRegSel		= 0; // PR0
++#if 0
++			/*  Example of Counter Application */
++			/* One-shot (software trigger) */
++			cmReg.reg.coutSource		= 0; /*  out RCAP */
++			cmReg.reg.coutPolarity		= 1; /*  Polarity inverted */
++			cmReg.reg.autoLoadResetRcap	= 0; /*  Auto load disabled */
++			cmReg.reg.hwCtEnableSource	= 3; /*  NOT RCAP */
++			cmReg.reg.ctEnableCtrl		= 2; /*  Hardware */
++			cmReg.reg.clockSource		= 2; /*  Internal */
++			cmReg.reg.countDir		= 1; /*  Down */
++			cmReg.reg.countDirCtrl		= 1; /*  Software */
++			cmReg.reg.outputRegLatchCtrl	= 0; /*  latch on read */
++			cmReg.reg.preloadRegSel		= 0; /*  PR0 */
+ 			cmReg.reg.reserved		= 0;
+ 
+ 			outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
+@@ -551,40 +551,40 @@ static int s526_gpct_insn_config(struct comedi_device * dev, struct comedi_subde
+ 			outw(0x0001, ADDR_CHAN_REG(REG_C0H, subdev_channel));
+ 			outw(0x3C68, ADDR_CHAN_REG(REG_C0L, subdev_channel));
+ 
+-			outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel));	// Reset the counter
+-			outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel));	// Load the counter from PR0
++			outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel));	/*  Reset the counter */
++			outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel));	/*  Load the counter from PR0 */
+ 
+-			outw(0x0008, ADDR_CHAN_REG(REG_C0C, subdev_channel));  // Reset RCAP (fires one-shot)
++			outw(0x0008, ADDR_CHAN_REG(REG_C0C, subdev_channel));  /*  Reset RCAP (fires one-shot) */
+ 
+-*/
++#endif
+ 
+ #if 1
+-		// Set Counter Mode Register
+-		cmReg.reg.coutSource = 0;	// out RCAP
+-		cmReg.reg.coutPolarity = 0;	// Polarity inverted
+-		cmReg.reg.autoLoadResetRcap = 0;	// Auto load disabled
+-		cmReg.reg.hwCtEnableSource = 2;	// NOT RCAP
+-		cmReg.reg.ctEnableCtrl = 1;	// 1: Software,  >1 : Hardware
+-		cmReg.reg.clockSource = 3;	// x4
+-		cmReg.reg.countDir = 0;	// up
+-		cmReg.reg.countDirCtrl = 0;	// quadrature
+-		cmReg.reg.outputRegLatchCtrl = 0;	// latch on read
+-		cmReg.reg.preloadRegSel = 0;	// PR0
++		/*  Set Counter Mode Register */
++		cmReg.reg.coutSource = 0;	/*  out RCAP */
++		cmReg.reg.coutPolarity = 0;	/*  Polarity inverted */
++		cmReg.reg.autoLoadResetRcap = 0;	/*  Auto load disabled */
++		cmReg.reg.hwCtEnableSource = 2;	/*  NOT RCAP */
++		cmReg.reg.ctEnableCtrl = 1;	/*  1: Software,  >1 : Hardware */
++		cmReg.reg.clockSource = 3;	/*  x4 */
++		cmReg.reg.countDir = 0;	/*  up */
++		cmReg.reg.countDirCtrl = 0;	/*  quadrature */
++		cmReg.reg.outputRegLatchCtrl = 0;	/*  latch on read */
++		cmReg.reg.preloadRegSel = 0;	/*  PR0 */
+ 		cmReg.reg.reserved = 0;
+ 
+-		// Set Counter Mode Register
+-//                      printk("s526: Counter Mode register=%x\n", cmReg.value);
++		/*  Set Counter Mode Register */
++/* printk("s526: Counter Mode register=%x\n", cmReg.value); */
+ 		outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
+ 
+-		// Reset the counter if it is software preload
++		/*  Reset the counter if it is software preload */
+ 		if (cmReg.reg.autoLoadResetRcap == 0) {
+-			outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel));	// Reset the counter
+-//                              outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel));   // Load the counter from PR0
++			outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel));	/*  Reset the counter */
++/* outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel));    Load the counter from PR0 */
+ 		}
+ #else
+-		cmReg.reg.countDirCtrl = 0;	// 0 quadrature, 1 software control
++		cmReg.reg.countDirCtrl = 0;	/*  0 quadrature, 1 software control */
+ 
+-		// data[1] contains GPCT_X1, GPCT_X2 or GPCT_X4
++		/*  data[1] contains GPCT_X1, GPCT_X2 or GPCT_X4 */
+ 		if (insn->data[1] == GPCT_X2) {
+ 			cmReg.reg.clockSource = 1;
+ 		} else if (insn->data[1] == GPCT_X4) {
+@@ -593,37 +593,37 @@ static int s526_gpct_insn_config(struct comedi_device * dev, struct comedi_subde
+ 			cmReg.reg.clockSource = 0;
+ 		}
+ 
+-		// When to take into account the indexpulse:
++		/*  When to take into account the indexpulse: */
+ 		if (insn->data[2] == GPCT_IndexPhaseLowLow) {
+ 		} else if (insn->data[2] == GPCT_IndexPhaseLowHigh) {
+ 		} else if (insn->data[2] == GPCT_IndexPhaseHighLow) {
+ 		} else if (insn->data[2] == GPCT_IndexPhaseHighHigh) {
+ 		}
+-		// Take into account the index pulse?
++		/*  Take into account the index pulse? */
+ 		if (insn->data[3] == GPCT_RESET_COUNTER_ON_INDEX)
+-			cmReg.reg.autoLoadResetRcap = 4;	// Auto load with INDEX^
++			cmReg.reg.autoLoadResetRcap = 4;	/*  Auto load with INDEX^ */
+ 
+-		// Set Counter Mode Register
++		/*  Set Counter Mode Register */
+ 		cmReg.value = (short) (insn->data[1] & 0xFFFF);
+ 		outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
+ 
+-		// Load the pre-laod register high word
++		/*  Load the pre-laod register high word */
+ 		value = (short) ((insn->data[2] >> 16) & 0xFFFF);
+ 		outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
+ 
+-		// Load the pre-laod register low word
++		/*  Load the pre-laod register low word */
+ 		value = (short) (insn->data[2] & 0xFFFF);
+ 		outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
+ 
+-		// Write the Counter Control Register
++		/*  Write the Counter Control Register */
+ 		if (insn->data[3] != 0) {
+ 			value = (short) (insn->data[3] & 0xFFFF);
+ 			outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel));
+ 		}
+-		// Reset the counter if it is software preload
++		/*  Reset the counter if it is software preload */
+ 		if (cmReg.reg.autoLoadResetRcap == 0) {
+-			outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel));	// Reset the counter
+-			outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel));	// Load the counter from PR0
++			outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel));	/*  Reset the counter */
++			outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel));	/*  Load the counter from PR0 */
+ 		}
+ #endif
+ 		break;
+@@ -640,33 +640,33 @@ static int s526_gpct_insn_config(struct comedi_device * dev, struct comedi_subde
+ 		devpriv->s526_gpct_config[subdev_channel].app =
+ 			SinglePulseGeneration;
+ 
+-		// Set Counter Mode Register
++		/*  Set Counter Mode Register */
+ 		cmReg.value = (short) (insn->data[1] & 0xFFFF);
+-		cmReg.reg.preloadRegSel = 0;	// PR0
++		cmReg.reg.preloadRegSel = 0;	/*  PR0 */
+ 		outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
+ 
+-		// Load the pre-laod register 0 high word
++		/*  Load the pre-laod register 0 high word */
+ 		value = (short) ((insn->data[2] >> 16) & 0xFFFF);
+ 		outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
+ 
+-		// Load the pre-laod register 0 low word
++		/*  Load the pre-laod register 0 low word */
+ 		value = (short) (insn->data[2] & 0xFFFF);
+ 		outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
+ 
+-		// Set Counter Mode Register
++		/*  Set Counter Mode Register */
+ 		cmReg.value = (short) (insn->data[1] & 0xFFFF);
+-		cmReg.reg.preloadRegSel = 1;	// PR1
++		cmReg.reg.preloadRegSel = 1;	/*  PR1 */
+ 		outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
+ 
+-		// Load the pre-laod register 1 high word
++		/*  Load the pre-laod register 1 high word */
+ 		value = (short) ((insn->data[3] >> 16) & 0xFFFF);
+ 		outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
+ 
+-		// Load the pre-laod register 1 low word
++		/*  Load the pre-laod register 1 low word */
+ 		value = (short) (insn->data[3] & 0xFFFF);
+ 		outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
+ 
+-		// Write the Counter Control Register
++		/*  Write the Counter Control Register */
+ 		if (insn->data[3] != 0) {
+ 			value = (short) (insn->data[3] & 0xFFFF);
+ 			outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel));
+@@ -685,33 +685,33 @@ static int s526_gpct_insn_config(struct comedi_device * dev, struct comedi_subde
+ 		devpriv->s526_gpct_config[subdev_channel].app =
+ 			PulseTrainGeneration;
+ 
+-		// Set Counter Mode Register
++		/*  Set Counter Mode Register */
+ 		cmReg.value = (short) (insn->data[1] & 0xFFFF);
+-		cmReg.reg.preloadRegSel = 0;	// PR0
++		cmReg.reg.preloadRegSel = 0;	/*  PR0 */
+ 		outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
+ 
+-		// Load the pre-laod register 0 high word
++		/*  Load the pre-laod register 0 high word */
+ 		value = (short) ((insn->data[2] >> 16) & 0xFFFF);
+ 		outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
+ 
+-		// Load the pre-laod register 0 low word
++		/*  Load the pre-laod register 0 low word */
+ 		value = (short) (insn->data[2] & 0xFFFF);
+ 		outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
+ 
+-		// Set Counter Mode Register
++		/*  Set Counter Mode Register */
+ 		cmReg.value = (short) (insn->data[1] & 0xFFFF);
+-		cmReg.reg.preloadRegSel = 1;	// PR1
++		cmReg.reg.preloadRegSel = 1;	/*  PR1 */
+ 		outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
+ 
+-		// Load the pre-laod register 1 high word
++		/*  Load the pre-laod register 1 high word */
+ 		value = (short) ((insn->data[3] >> 16) & 0xFFFF);
+ 		outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
+ 
+-		// Load the pre-laod register 1 low word
++		/*  Load the pre-laod register 1 low word */
+ 		value = (short) (insn->data[3] & 0xFFFF);
+ 		outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
+ 
+-		// Write the Counter Control Register
++		/*  Write the Counter Control Register */
+ 		if (insn->data[3] != 0) {
+ 			value = (short) (insn->data[3] & 0xFFFF);
+ 			outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel));
+@@ -730,13 +730,13 @@ static int s526_gpct_insn_config(struct comedi_device * dev, struct comedi_subde
+ static int s526_gpct_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	int subdev_channel = CR_CHAN(insn->chanspec);	// Unpack chanspec
++	int subdev_channel = CR_CHAN(insn->chanspec);	/*  Unpack chanspec */
+ 	short value;
+ 
+ 	printk("s526: GPCT_INSN_WRITE on channel %d\n", subdev_channel);
+ 	cmReg.value = inw(ADDR_CHAN_REG(REG_C0M, subdev_channel));
+ 	printk("s526: Counter Mode Register: %x\n", cmReg.value);
+-	// Check what Application of Counter this channel is configured for
++	/*  Check what Application of Counter this channel is configured for */
+ 	switch (devpriv->s526_gpct_config[subdev_channel].app) {
+ 	case PositionMeasurement:
+ 		printk("S526: INSN_WRITE: PM\n");
+@@ -776,12 +776,12 @@ static int s526_gpct_winsn(struct comedi_device * dev, struct comedi_subdevice *
+ 		value = (short) (*data & 0xFFFF);
+ 		outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
+ 		break;
+-	default:		// Impossible
++	default:		/*  Impossible */
+ 		printk("s526: INSN_WRITE: Functionality %d not implemented yet\n", devpriv->s526_gpct_config[subdev_channel].app);
+ 		return -EINVAL;
+ 		break;
+ 	}
+-	// return the number of samples written
++	/*  return the number of samples written */
+ 	return insn->n;
+ }
+ 
+@@ -803,14 +803,14 @@ static int s526_ai_insn_config(struct comedi_device * dev, struct comedi_subdevi
+ 	 * enable channels here.  The channel should be enabled in the
+ 	 * INSN_READ handler. */
+ 
+-	// Enable ADC interrupt
++	/*  Enable ADC interrupt */
+ 	outw(ISR_ADC_DONE, ADDR_REG(REG_IER));
+-//      printk("s526: ADC current value: 0x%04x\n", inw(ADDR_REG(REG_ADC)));
++/* printk("s526: ADC current value: 0x%04x\n", inw(ADDR_REG(REG_ADC))); */
+ 	devpriv->s526_ai_config = (data[0] & 0x3FF) << 5;
+ 	if (data[1] > 0)
+-		devpriv->s526_ai_config |= 0x8000;	//set the delay
++		devpriv->s526_ai_config |= 0x8000;	/* set the delay */
+ 
+-	devpriv->s526_ai_config |= 0x0001;	// ADC start bit.
++	devpriv->s526_ai_config |= 0x0001;	/*  ADC start bit. */
+ 
+ 	return result;
+ }
+@@ -837,8 +837,8 @@ static int s526_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s
+ 	for (n = 0; n < insn->n; n++) {
+ 		/* trigger conversion */
+ 		outw(value, ADDR_REG(REG_ADC));
+-//              printk("s526: Wrote 0x%04x to ADC\n", value);
+-//              printk("s526: ADC reg=0x%04x\n", inw(ADDR_REG(REG_ADC)));
++/* printk("s526: Wrote 0x%04x to ADC\n", value); */
++/* printk("s526: ADC reg=0x%04x\n", inw(ADDR_REG(REG_ADC))); */
+ 
+ #define TIMEOUT 100
+ 		/* wait for conversion to end */
+@@ -859,7 +859,7 @@ static int s526_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s
+ 
+ 		/* read data */
+ 		d = inw(ADDR_REG(REG_ADD));
+-//              printk("AI[%d]=0x%04x\n", n, (unsigned short)(d & 0xFFFF));
++/* printk("AI[%d]=0x%04x\n", n, (unsigned short)(d & 0xFFFF)); */
+ 
+ 		/* munge data */
+ 		data[n] = d ^ 0x8000;
+@@ -876,20 +876,20 @@ static int s526_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	unsigned short val;
+ 
+-//      printk("s526_ao_winsn\n");
++/* printk("s526_ao_winsn\n"); */
+ 	val = chan << 1;
+-//      outw(val, dev->iobase + REG_DAC);
++/* outw(val, dev->iobase + REG_DAC); */
+ 	outw(val, ADDR_REG(REG_DAC));
+ 
+ 	/* Writing a list of values to an AO channel is probably not
+ 	 * very useful, but that's how the interface is defined. */
+ 	for (i = 0; i < insn->n; i++) {
+ 		/* a typical programming sequence */
+-//              outw(data[i], dev->iobase + REG_ADD);  // write the data to preload register
+-		outw(data[i], ADDR_REG(REG_ADD));	// write the data to preload register
++/* outw(data[i], dev->iobase + REG_ADD);    write the data to preload register */
++		outw(data[i], ADDR_REG(REG_ADD));	/*  write the data to preload register */
+ 		devpriv->ao_readback[chan] = data[i];
+-//              outw(val + 1, dev->iobase + REG_DAC); // starts the D/A conversion.
+-		outw(val + 1, ADDR_REG(REG_DAC));	// starts the D/A conversion.
++/* outw(val + 1, dev->iobase + REG_DAC);  starts the D/A conversion. */
++		outw(val + 1, ADDR_REG(REG_DAC));	/*  starts the D/A conversion. */
+ 	}
+ 
+ 	/* return the number of samples read/written */
+@@ -932,10 +932,10 @@ static int s526_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevic
+ 
+ 	/* on return, data[1] contains the value of the digital
+ 	 * input and output lines. */
+-	data[1] = inw(ADDR_REG(REG_DIO)) & 0xFF;	// low 8 bits are the data
++	data[1] = inw(ADDR_REG(REG_DIO)) & 0xFF;	/*  low 8 bits are the data */
+ 	/* or we could just return the software copy of the output values if
+ 	 * it was a purely digital output subdevice */
+-	//data[1]=s->state;
++	/* data[1]=s->state; */
+ 
+ 	return 2;
+ }
+@@ -959,10 +959,10 @@ static int s526_dio_insn_config(struct comedi_device * dev, struct comedi_subdev
+ 	 * value COMEDI_INPUT or COMEDI_OUTPUT. */
+ 
+ 	if (data[0] == COMEDI_OUTPUT) {
+-		value |= 1 << (chan + 10);	// bit 10/11 set the group 1/2's mode
++		value |= 1 << (chan + 10);	/*  bit 10/11 set the group 1/2's mode */
+ 		s->io_bits |= (0xF << chan);
+ 	} else {
+-		value &= ~(1 << (chan + 10));	// 1 is output, 0 is input.
++		value &= ~(1 << (chan + 10));	/*  1 is output, 0 is input. */
+ 		s->io_bits &= ~(0xF << chan);
+ 	}
+ 	outw(value, ADDR_REG(REG_DIO));

commit 58c0576eea94298e698e03114c4d3d0179c5ef66
+Author: Bill Pemberton 
+Date:   Fri Mar 27 11:31:22 2009 -0400
+
+    Staging: comedi: remove C99 comments in pcl816.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
+index 515ba74cc7fe..5382adf1dd6a 100644
+--- a/drivers/staging/comedi/drivers/pcl816.c
++++ b/drivers/staging/comedi/drivers/pcl816.c
+@@ -43,38 +43,38 @@ Configuration Options:
+ 
+ #define DEBUG(x) x
+ 
+-// boards constants
+-// IO space len
++/* boards constants */
++/* IO space len */
+ #define PCLx1x_RANGE 16
+ 
+-//#define outb(x,y)  printk("OUTB(%x, 200+%d)\n", x,y-0x200); outb(x,y)
++/* #define outb(x,y)  printk("OUTB(%x, 200+%d)\n", x,y-0x200); outb(x,y) */
+ 
+-// INTEL 8254 counters
++/* INTEL 8254 counters */
+ #define PCL816_CTR0 4
+ #define PCL816_CTR1 5
+ #define PCL816_CTR2 6
+-// R: counter read-back register W: counter control
++/* R: counter read-back register W: counter control */
+ #define PCL816_CTRCTL 7
+ 
+-// R: A/D high byte W: A/D range control
++/* R: A/D high byte W: A/D range control */
+ #define PCL816_RANGE 9
+-// W: clear INT request
++/* W: clear INT request */
+ #define PCL816_CLRINT 10
+-// R: next mux scan channel W: mux scan channel & range control pointer
++/* R: next mux scan channel W: mux scan channel & range control pointer */
+ #define PCL816_MUX 11
+-// R/W: operation control register
++/* R/W: operation control register */
+ #define PCL816_CONTROL 12
+ 
+-// R: return status byte  W: set DMA/IRQ
++/* R: return status byte  W: set DMA/IRQ */
+ #define PCL816_STATUS 13
+ #define PCL816_STATUS_DRDY_MASK 0x80
+ 
+-// R: low byte of A/D W: soft A/D trigger
++/* R: low byte of A/D W: soft A/D trigger */
+ #define PCL816_AD_LO 8
+-// R: high byte of A/D W: A/D range control
++/* R: high byte of A/D W: A/D range control */
+ #define PCL816_AD_HI 9
+ 
+-// type of interrupt handler
++/* type of interrupt handler */
+ #define INT_TYPE_AI1_INT 1
+ #define INT_TYPE_AI1_DMA 2
+ #define INT_TYPE_AI3_INT 4
+@@ -83,7 +83,7 @@ Configuration Options:
+ #define INT_TYPE_AI1_DMA_RTC 9
+ #define INT_TYPE_AI3_DMA_RTC 10
+ 
+-// RTC stuff...
++/* RTC stuff... */
+ #define RTC_IRQ 	8
+ #define RTC_IO_EXTENT	0x10
+ #endif
+@@ -103,35 +103,35 @@ static const struct comedi_lrange range_pcl816 = { 8, {
+ };
+ struct pcl816_board {
+ 
+-	const char *name;	// board name
+-	int n_ranges;		// len of range list
+-	int n_aichan;		// num of A/D chans in diferencial mode
+-	unsigned int ai_ns_min;	// minimal alllowed delay between samples (in ns)
+-	int n_aochan;		// num of D/A chans
+-	int n_dichan;		// num of DI chans
+-	int n_dochan;		// num of DO chans
+-	const struct comedi_lrange *ai_range_type;	// default A/D rangelist
+-	const struct comedi_lrange *ao_range_type;	// dafault D/A rangelist
+-	unsigned int io_range;	// len of IO space
+-	unsigned int IRQbits;	// allowed interrupts
+-	unsigned int DMAbits;	// allowed DMA chans
+-	int ai_maxdata;		// maxdata for A/D
+-	int ao_maxdata;		// maxdata for D/A
+-	int ai_chanlist;	// allowed len of channel list A/D
+-	int ao_chanlist;	// allowed len of channel list D/A
+-	int i8254_osc_base;	// 1/frequency of on board oscilator in ns
++	const char *name;	/*  board name */
++	int n_ranges;		/*  len of range list */
++	int n_aichan;		/*  num of A/D chans in diferencial mode */
++	unsigned int ai_ns_min;	/*  minimal alllowed delay between samples (in ns) */
++	int n_aochan;		/*  num of D/A chans */
++	int n_dichan;		/*  num of DI chans */
++	int n_dochan;		/*  num of DO chans */
++	const struct comedi_lrange *ai_range_type;	/*  default A/D rangelist */
++	const struct comedi_lrange *ao_range_type;	/*  dafault D/A rangelist */
++	unsigned int io_range;	/*  len of IO space */
++	unsigned int IRQbits;	/*  allowed interrupts */
++	unsigned int DMAbits;	/*  allowed DMA chans */
++	int ai_maxdata;		/*  maxdata for A/D */
++	int ao_maxdata;		/*  maxdata for D/A */
++	int ai_chanlist;	/*  allowed len of channel list A/D */
++	int ao_chanlist;	/*  allowed len of channel list D/A */
++	int i8254_osc_base;	/*  1/frequency of on board oscilator in ns */
+ };
+ 
+ 
+ static const struct pcl816_board boardtypes[] = {
+ 	{"pcl816", 8, 16, 10000, 1, 16, 16, &range_pcl816,
+ 			&range_pcl816, PCLx1x_RANGE,
+-			0x00fc,	// IRQ mask
+-			0x0a,	// DMA mask
+-			0xffff,	// 16-bit card
+-			0xffff,	// D/A maxdata
++			0x00fc,	/*  IRQ mask */
++			0x0a,	/*  DMA mask */
++			0xffff,	/*  16-bit card */
++			0xffff,	/*  D/A maxdata */
+ 			1024,
+-			1,	// ao chan list
++			1,	/*  ao chan list */
+ 		100},
+ 	{"pcl814b", 8, 16, 10000, 1, 16, 16, &range_pcl816,
+ 			&range_pcl816, PCLx1x_RANGE,
+@@ -170,42 +170,42 @@ COMEDI_INITCLEANUP(driver_pcl816);
+ 
+ struct pcl816_private {
+ 
+-	unsigned int dma;	// used DMA, 0=don't use DMA
+-	int dma_rtc;		// 1=RTC used with DMA, 0=no RTC alloc
++	unsigned int dma;	/*  used DMA, 0=don't use DMA */
++	int dma_rtc;		/*  1=RTC used with DMA, 0=no RTC alloc */
+ #ifdef unused
+-	unsigned long rtc_iobase;	// RTC port region
++	unsigned long rtc_iobase;	/*  RTC port region */
+ 	unsigned int rtc_iosize;
+ 	unsigned int rtc_irq;
+ #endif
+-	unsigned long dmabuf[2];	// pointers to begin of DMA buffers
+-	unsigned int dmapages[2];	// len of DMA buffers in PAGE_SIZEs
+-	unsigned int hwdmaptr[2];	// hardware address of DMA buffers
+-	unsigned int hwdmasize[2];	// len of DMA buffers in Bytes
+-	unsigned int dmasamplsize;	// size in samples hwdmasize[0]/2
+-	unsigned int last_top_dma;	// DMA pointer in last RTC int
+-	int next_dma_buf;	// which DMA buffer will be used next round
+-	long dma_runs_to_end;	// how many we must permorm DMA transfer to end of record
+-	unsigned long last_dma_run;	// how many bytes we must transfer on last DMA page
+-
+-	unsigned int ai_scans;	// len of scanlist
+-	unsigned char ai_neverending;	// if=1, then we do neverending record (you must use cancel())
+-	int irq_free;		// 1=have allocated IRQ
+-	int irq_blocked;	// 1=IRQ now uses any subdev
++	unsigned long dmabuf[2];	/*  pointers to begin of DMA buffers */
++	unsigned int dmapages[2];	/*  len of DMA buffers in PAGE_SIZEs */
++	unsigned int hwdmaptr[2];	/*  hardware address of DMA buffers */
++	unsigned int hwdmasize[2];	/*  len of DMA buffers in Bytes */
++	unsigned int dmasamplsize;	/*  size in samples hwdmasize[0]/2 */
++	unsigned int last_top_dma;	/*  DMA pointer in last RTC int */
++	int next_dma_buf;	/*  which DMA buffer will be used next round */
++	long dma_runs_to_end;	/*  how many we must permorm DMA transfer to end of record */
++	unsigned long last_dma_run;	/*  how many bytes we must transfer on last DMA page */
++
++	unsigned int ai_scans;	/*  len of scanlist */
++	unsigned char ai_neverending;	/*  if=1, then we do neverending record (you must use cancel()) */
++	int irq_free;		/*  1=have allocated IRQ */
++	int irq_blocked;	/*  1=IRQ now uses any subdev */
+ #ifdef unused
+-	int rtc_irq_blocked;	// 1=we now do AI with DMA&RTC
++	int rtc_irq_blocked;	/*  1=we now do AI with DMA&RTC */
+ #endif
+-	int irq_was_now_closed;	// when IRQ finish, there's stored int816_mode for last interrupt
+-	int int816_mode;	// who now uses IRQ - 1=AI1 int, 2=AI1 dma, 3=AI3 int, 4AI3 dma
+-	struct comedi_subdevice *last_int_sub;	// ptr to subdevice which now finish
+-	int ai_act_scan;	// how many scans we finished
+-	unsigned int ai_act_chanlist[16];	// MUX setting for actual AI operations
+-	unsigned int ai_act_chanlist_len;	// how long is actual MUX list
+-	unsigned int ai_act_chanlist_pos;	// actual position in MUX list
+-	unsigned int ai_poll_ptr;	// how many sampes transfer poll
+-	struct comedi_subdevice *sub_ai;	// ptr to AI subdevice
++	int irq_was_now_closed;	/*  when IRQ finish, there's stored int816_mode for last interrupt */
++	int int816_mode;	/*  who now uses IRQ - 1=AI1 int, 2=AI1 dma, 3=AI3 int, 4AI3 dma */
++	struct comedi_subdevice *last_int_sub;	/*  ptr to subdevice which now finish */
++	int ai_act_scan;	/*  how many scans we finished */
++	unsigned int ai_act_chanlist[16];	/*  MUX setting for actual AI operations */
++	unsigned int ai_act_chanlist_len;	/*  how long is actual MUX list */
++	unsigned int ai_act_chanlist_pos;	/*  actual position in MUX list */
++	unsigned int ai_poll_ptr;	/*  how many sampes transfer poll */
++	struct comedi_subdevice *sub_ai;	/*  ptr to AI subdevice */
+ #ifdef unused
+-	struct timer_list rtc_irq_timer;	// timer for RTC sanity check
+-	unsigned long rtc_freq;	// RTC int freq
++	struct timer_list rtc_irq_timer;	/*  timer for RTC sanity check */
++	unsigned long rtc_freq;	/*  RTC int freq */
+ #endif
+ };
+ 
+@@ -237,12 +237,12 @@ static int pcl816_ai_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ 	int timeout;
+ 
+ 	DPRINTK("mode 0 analog input\n");
+-	// software trigger, DMA and INT off
++	/*  software trigger, DMA and INT off */
+ 	outb(0, dev->iobase + PCL816_CONTROL);
+-	// clear INT (conversion end) flag
++	/*  clear INT (conversion end) flag */
+ 	outb(0, dev->iobase + PCL816_CLRINT);
+ 
+-	// Set the input channel
++	/*  Set the input channel */
+ 	outb(CR_CHAN(insn->chanspec) & 0xf, dev->iobase + PCL816_MUX);
+ 	outb(CR_RANGE(insn->chanspec), dev->iobase + PCL816_RANGE);	/* select gain */
+ 
+@@ -254,7 +254,7 @@ static int pcl816_ai_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ 		while (timeout--) {
+ 			if (!(inb(dev->iobase + PCL816_STATUS) &
+ 					PCL816_STATUS_DRDY_MASK)) {
+-				// return read value
++				/*  return read value */
+ 				data[n] =
+ 					((inb(dev->iobase +
+ 							PCL816_AD_HI) << 8) |
+@@ -265,7 +265,7 @@ static int pcl816_ai_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ 			}
+ 			comedi_udelay(1);
+ 		}
+-		// Return timeout error
++		/*  Return timeout error */
+ 		if (!timeout) {
+ 			comedi_error(dev, "A/D insn timeout\n");
+ 			data[0] = 0;
+@@ -295,7 +295,7 @@ static irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d)
+ 			break;
+ 		comedi_udelay(1);
+ 	}
+-	if (!timeout) {		// timeout, bail error
++	if (!timeout) {		/*  timeout, bail error */
+ 		outb(0, dev->iobase + PCL816_CLRINT);	/* clear INT request */
+ 		comedi_error(dev, "A/D mode1/3 IRQ without DRDY!");
+ 		pcl816_ai_cancel(dev, s);
+@@ -305,7 +305,7 @@ static irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d)
+ 
+ 	}
+ 
+-	// get the sample
++	/*  get the sample */
+ 	low = inb(dev->iobase + PCL816_AD_LO);
+ 	hi = inb(dev->iobase + PCL816_AD_HI);
+ 
+@@ -352,7 +352,7 @@ static void transfer_from_dma_buf(struct comedi_device * dev, struct comedi_subd
+ 		}
+ 
+ 		if (!devpriv->ai_neverending)
+-			if (devpriv->ai_act_scan >= devpriv->ai_scans) {	// all data sampled
++			if (devpriv->ai_act_scan >= devpriv->ai_scans) {	/*  all data sampled */
+ 				pcl816_ai_cancel(dev, s);
+ 				s->async->events |= COMEDI_CB_EOA;
+ 				s->async->events |= COMEDI_CB_BLOCK;
+@@ -374,12 +374,12 @@ static irqreturn_t interrupt_pcl816_ai_mode13_dma(int irq, void *d)
+ 	disable_dma(devpriv->dma);
+ 	this_dma_buf = devpriv->next_dma_buf;
+ 
+-	if ((devpriv->dma_runs_to_end > -1) || devpriv->ai_neverending) {	// switch dma bufs
++	if ((devpriv->dma_runs_to_end > -1) || devpriv->ai_neverending) {	/*  switch dma bufs */
+ 
+ 		devpriv->next_dma_buf = 1 - devpriv->next_dma_buf;
+ 		set_dma_mode(devpriv->dma, DMA_MODE_READ);
+ 		dma_flags = claim_dma_lock();
+-//  clear_dma_ff (devpriv->dma);
++/* clear_dma_ff (devpriv->dma); */
+ 		set_dma_addr(devpriv->dma,
+ 			devpriv->hwdmaptr[devpriv->next_dma_buf]);
+ 		if (devpriv->dma_runs_to_end) {
+@@ -433,7 +433,7 @@ static irqreturn_t interrupt_pcl816(int irq, void *d PT_REGS_ARG)
+ 		(!devpriv->int816_mode)) {
+ 		if (devpriv->irq_was_now_closed) {
+ 			devpriv->irq_was_now_closed = 0;
+-			// comedi_error(dev,"last IRQ..");
++			/*  comedi_error(dev,"last IRQ.."); */
+ 			return IRQ_HANDLED;
+ 		}
+ 		comedi_error(dev, "bad IRQ!");
+@@ -610,7 +610,7 @@ static int pcl816_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s
+ 		return -EINVAL;
+ 	if (cmd->scan_end_arg != cmd->chanlist_len)
+ 		return -EINVAL;
+-//      if(cmd->chanlist_len>MAX_CHANLIST_LEN) return -EINVAL;
++/* if(cmd->chanlist_len>MAX_CHANLIST_LEN) return -EINVAL; */
+ 	if (devpriv->irq_blocked)
+ 		return -EBUSY;
+ 
+@@ -621,7 +621,7 @@ static int pcl816_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s
+ 		i8253_cascade_ns_to_timer(this_board->i8254_osc_base, &divisor1,
+ 			&divisor2, &cmd->convert_arg,
+ 			cmd->flags & TRIG_ROUND_MASK);
+-		if (divisor1 == 1) {	// PCL816 crash if any divisor is set to 1
++		if (divisor1 == 1) {	/*  PCL816 crash if any divisor is set to 1 */
+ 			divisor1 = 2;
+ 			divisor2 /= 2;
+ 		}
+@@ -631,7 +631,7 @@ static int pcl816_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s
+ 		}
+ 	}
+ 
+-	start_pacer(dev, -1, 0, 0);	// stop pacer
++	start_pacer(dev, -1, 0, 0);	/*  stop pacer */
+ 
+ 	if (!check_and_setup_channel_list(dev, s, cmd->chanlist,
+ 			cmd->chanlist_len))
+@@ -652,19 +652,19 @@ static int pcl816_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s
+ 		devpriv->ai_neverending = 1;
+ 	}
+ 
+-	if ((cmd->flags & TRIG_WAKE_EOS)) {	// don't we want wake up every scan?
++	if ((cmd->flags & TRIG_WAKE_EOS)) {	/*  don't we want wake up every scan? */
+ 		printk("pl816: You wankt WAKE_EOS but I dont want handle it");
+-		//              devpriv->ai_eos=1;
+-		//if (devpriv->ai_n_chan==1)
+-		//      devpriv->dma=0; // DMA is useless for this situation
++		/*               devpriv->ai_eos=1; */
++		/* if (devpriv->ai_n_chan==1) */
++		/*       devpriv->dma=0; // DMA is useless for this situation */
+ 	}
+ 
+ 	if (devpriv->dma) {
+ 		bytes = devpriv->hwdmasize[0];
+ 		if (!devpriv->ai_neverending) {
+-			bytes = s->async->cmd.chanlist_len * s->async->cmd.chanlist_len * sizeof(short);	// how many
+-			devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize[0];	// how many DMA pages we must fill
+-			devpriv->last_dma_run = bytes % devpriv->hwdmasize[0];	//on last dma transfer must be moved
++			bytes = s->async->cmd.chanlist_len * s->async->cmd.chanlist_len * sizeof(short);	/*  how many */
++			devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize[0];	/*  how many DMA pages we must fill */
++			devpriv->last_dma_run = bytes % devpriv->hwdmasize[0];	/* on last dma transfer must be moved */
+ 			devpriv->dma_runs_to_end--;
+ 			if (devpriv->dma_runs_to_end >= 0)
+ 				bytes = devpriv->hwdmasize[0];
+@@ -687,14 +687,14 @@ static int pcl816_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s
+ 	switch (cmd->convert_src) {
+ 	case TRIG_TIMER:
+ 		devpriv->int816_mode = INT_TYPE_AI1_DMA;
+-		outb(0x32, dev->iobase + PCL816_CONTROL);	// Pacer+IRQ+DMA
+-		outb(dmairq, dev->iobase + PCL816_STATUS);	// write irq and DMA to card
++		outb(0x32, dev->iobase + PCL816_CONTROL);	/*  Pacer+IRQ+DMA */
++		outb(dmairq, dev->iobase + PCL816_STATUS);	/*  write irq and DMA to card */
+ 		break;
+ 
+ 	default:
+ 		devpriv->int816_mode = INT_TYPE_AI3_DMA;
+-		outb(0x34, dev->iobase + PCL816_CONTROL);	// Ext trig+IRQ+DMA
+-		outb(dmairq, dev->iobase + PCL816_STATUS);	// write irq to card
++		outb(0x34, dev->iobase + PCL816_CONTROL);	/*  Ext trig+IRQ+DMA */
++		outb(dmairq, dev->iobase + PCL816_STATUS);	/*  write irq to card */
+ 		break;
+ 	}
+ 
+@@ -708,12 +708,12 @@ static int pcl816_ai_poll(struct comedi_device * dev, struct comedi_subdevice *
+ 	unsigned int top1, top2, i;
+ 
+ 	if (!devpriv->dma)
+-		return 0;	// poll is valid only for DMA transfer
++		return 0;	/*  poll is valid only for DMA transfer */
+ 
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 
+ 	for (i = 0; i < 20; i++) {
+-		top1 = get_dma_residue(devpriv->dma);	// where is now DMA
++		top1 = get_dma_residue(devpriv->dma);	/*  where is now DMA */
+ 		top2 = get_dma_residue(devpriv->dma);
+ 		if (top1 == top2)
+ 			break;
+@@ -723,10 +723,10 @@ static int pcl816_ai_poll(struct comedi_device * dev, struct comedi_subdevice *
+ 		return 0;
+ 	}
+ 
+-	top1 = devpriv->hwdmasize[0] - top1;	// where is now DMA in buffer
+-	top1 >>= 1;		// sample position
++	top1 = devpriv->hwdmasize[0] - top1;	/*  where is now DMA in buffer */
++	top1 >>= 1;		/*  sample position */
+ 	top2 = top1 - devpriv->ai_poll_ptr;
+-	if (top2 < 1) {		// no new samples
++	if (top2 < 1) {		/*  no new samples */
+ 		comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ 		return 0;
+ 	}
+@@ -735,7 +735,7 @@ static int pcl816_ai_poll(struct comedi_device * dev, struct comedi_subdevice *
+ 		(short *) devpriv->dmabuf[devpriv->next_dma_buf],
+ 		devpriv->ai_poll_ptr, top2);
+ 
+-	devpriv->ai_poll_ptr = top1;	// new buffer position
++	devpriv->ai_poll_ptr = top1;	/*  new buffer position */
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ 
+ 	return s->async->buf_write_count - s->async->buf_read_count;
+@@ -747,14 +747,14 @@ static int pcl816_ai_poll(struct comedi_device * dev, struct comedi_subdevice *
+ */
+ static int pcl816_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-//  DEBUG(rt_printk("pcl816_ai_cancel()\n");)
++/* DEBUG(rt_printk("pcl816_ai_cancel()\n");) */
+ 
+ 	if (devpriv->irq_blocked > 0) {
+ 		switch (devpriv->int816_mode) {
+ #ifdef unused
+ 		case INT_TYPE_AI1_DMA_RTC:
+ 		case INT_TYPE_AI3_DMA_RTC:
+-			set_rtc_irq_bit(0);	// stop RTC
++			set_rtc_irq_bit(0);	/*  stop RTC */
+ 			del_timer(&devpriv->rtc_irq_timer);
+ #endif
+ 		case INT_TYPE_AI1_DMA:
+@@ -776,7 +776,7 @@ static int pcl816_ai_cancel(struct comedi_device * dev, struct comedi_subdevice
+ 			devpriv->irq_was_now_closed = devpriv->int816_mode;
+ 			devpriv->int816_mode = 0;
+ 			devpriv->last_int_sub = s;
+-//        s->busy = 0;
++/* s->busy = 0; */
+ 			break;
+ 		}
+ 	}
+@@ -795,18 +795,18 @@ static int pcl816_check(unsigned long iobase)
+ 	outb(0x00, iobase + PCL816_MUX);
+ 	comedi_udelay(1);
+ 	if (inb(iobase + PCL816_MUX) != 0x00)
+-		return 1;	//there isn't card
++		return 1;	/* there isn't card */
+ 	outb(0x55, iobase + PCL816_MUX);
+ 	comedi_udelay(1);
+ 	if (inb(iobase + PCL816_MUX) != 0x55)
+-		return 1;	//there isn't card
++		return 1;	/* there isn't card */
+ 	outb(0x00, iobase + PCL816_MUX);
+ 	comedi_udelay(1);
+ 	outb(0x18, iobase + PCL816_CONTROL);
+ 	comedi_udelay(1);
+ 	if (inb(iobase + PCL816_CONTROL) != 0x18)
+-		return 1;	//there isn't card
+-	return 0;		// ok, card exist
++		return 1;	/* there isn't card */
++	return 0;		/*  ok, card exist */
+ }
+ 
+ /*
+@@ -815,12 +815,12 @@ static int pcl816_check(unsigned long iobase)
+ */
+ static void pcl816_reset(struct comedi_device * dev)
+ {
+-//  outb (0, dev->iobase + PCL818_DA_LO);       // DAC=0V
+-//  outb (0, dev->iobase + PCL818_DA_HI);
+-//  comedi_udelay (1);
+-//  outb (0, dev->iobase + PCL818_DO_HI);       // DO=$0000
+-//  outb (0, dev->iobase + PCL818_DO_LO);
+-//  comedi_udelay (1);
++/* outb (0, dev->iobase + PCL818_DA_LO);         DAC=0V */
++/* outb (0, dev->iobase + PCL818_DA_HI); */
++/* comedi_udelay (1); */
++/* outb (0, dev->iobase + PCL818_DO_HI);        DO=$0000 */
++/* outb (0, dev->iobase + PCL818_DO_LO); */
++/* comedi_udelay (1); */
+ 	outb(0, dev->iobase + PCL816_CONTROL);
+ 	outb(0, dev->iobase + PCL816_MUX);
+ 	outb(0, dev->iobase + PCL816_CLRINT);
+@@ -842,8 +842,8 @@ start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
+ 	outb(0xff, dev->iobase + PCL816_CTR0);
+ 	outb(0x00, dev->iobase + PCL816_CTR0);
+ 	comedi_udelay(1);
+-	outb(0xb4, dev->iobase + PCL816_CTRCTL);	// set counter 2 as mode 3
+-	outb(0x74, dev->iobase + PCL816_CTRCTL);	// set counter 1 as mode 3
++	outb(0xb4, dev->iobase + PCL816_CTRCTL);	/*  set counter 2 as mode 3 */
++	outb(0x74, dev->iobase + PCL816_CTRCTL);	/*  set counter 1 as mode 3 */
+ 	comedi_udelay(1);
+ 
+ 	if (mode == 1) {
+@@ -856,7 +856,7 @@ start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
+ 	}
+ 
+ 	/* clear pending interrupts (just in case) */
+-//      outb(0, dev->iobase + PCL816_CLRINT);
++/* outb(0, dev->iobase + PCL816_CLRINT); */
+ }
+ 
+ /*
+@@ -871,35 +871,35 @@ check_and_setup_channel_list(struct comedi_device * dev, struct comedi_subdevice
+ 	unsigned int chansegment[16];
+ 	unsigned int i, nowmustbechan, seglen, segpos;
+ 
+-	// correct channel and range number check itself comedi/range.c
++	/*  correct channel and range number check itself comedi/range.c */
+ 	if (chanlen < 1) {
+ 		comedi_error(dev, "range/channel list is empty!");
+ 		return 0;
+ 	}
+ 
+ 	if (chanlen > 1) {
+-		chansegment[0] = chanlist[0];	// first channel is everytime ok
++		chansegment[0] = chanlist[0];	/*  first channel is everytime ok */
+ 		for (i = 1, seglen = 1; i < chanlen; i++, seglen++) {
+-			// build part of chanlist
++			/*  build part of chanlist */
+ 			DEBUG(rt_printk("%d. %d %d\n", i, CR_CHAN(chanlist[i]),
+ 					CR_RANGE(chanlist[i]));
+ 				)
+ 				if (chanlist[0] == chanlist[i])
+-				break;	// we detect loop, this must by finish
++				break;	/*  we detect loop, this must by finish */
+ 			nowmustbechan =
+ 				(CR_CHAN(chansegment[i - 1]) + 1) % chanlen;
+ 			if (nowmustbechan != CR_CHAN(chanlist[i])) {
+-				// channel list isn't continous :-(
++				/*  channel list isn't continous :-( */
+ 				rt_printk
+ 					("comedi%d: pcl816: channel list must be continous! chanlist[%i]=%d but must be %d or %d!\n",
+ 					dev->minor, i, CR_CHAN(chanlist[i]),
+ 					nowmustbechan, CR_CHAN(chanlist[0]));
+ 				return 0;
+ 			}
+-			chansegment[i] = chanlist[i];	// well, this is next correct channel in list
++			chansegment[i] = chanlist[i];	/*  well, this is next correct channel in list */
+ 		}
+ 
+-		for (i = 0, segpos = 0; i < chanlen; i++) {	// check whole chanlist
++		for (i = 0, segpos = 0; i < chanlen; i++) {	/*  check whole chanlist */
+ 			DEBUG(rt_printk("%d %d=%d %d\n",
+ 					CR_CHAN(chansegment[i % seglen]),
+ 					CR_RANGE(chansegment[i % seglen]),
+@@ -915,7 +915,7 @@ check_and_setup_channel_list(struct comedi_device * dev, struct comedi_subdevice
+ 					CR_CHAN(chanlist[i % seglen]),
+ 					CR_RANGE(chanlist[i % seglen]),
+ 					CR_AREF(chansegment[i % seglen]));
+-				return 0;	// chan/gain list is strange
++				return 0;	/*  chan/gain list is strange */
+ 			}
+ 		}
+ 	} else {
+@@ -925,7 +925,7 @@ check_and_setup_channel_list(struct comedi_device * dev, struct comedi_subdevice
+ 	devpriv->ai_act_chanlist_len = seglen;
+ 	devpriv->ai_act_chanlist_pos = 0;
+ 
+-	for (i = 0; i < seglen; i++) {	// store range list to card
++	for (i = 0; i < seglen; i++) {	/*  store range list to card */
+ 		devpriv->ai_act_chanlist[i] = CR_CHAN(chanlist[i]);
+ 		outb(CR_CHAN(chanlist[0]) & 0xf, dev->iobase + PCL816_MUX);
+ 		outb(CR_RANGE(chanlist[0]), dev->iobase + PCL816_RANGE);	/* select gain */
+@@ -935,7 +935,7 @@ check_and_setup_channel_list(struct comedi_device * dev, struct comedi_subdevice
+ 
+ 	outb(devpriv->ai_act_chanlist[0] | (devpriv->ai_act_chanlist[seglen - 1] << 4), dev->iobase + PCL816_MUX);	/* select channel interval to scan */
+ 
+-	return 1;		// we can serve this with MUX logic
++	return 1;		/*  we can serve this with MUX logic */
+ }
+ 
+ #ifdef unused
+@@ -981,7 +981,7 @@ static int set_rtc_irq_bit(unsigned char bit)
+ */
+ static void free_resources(struct comedi_device * dev)
+ {
+-	//rt_printk("free_resource()\n");
++	/* rt_printk("free_resource()\n"); */
+ 	if (dev->private) {
+ 		pcl816_ai_cancel(dev, devpriv->sub_ai);
+ 		pcl816_reset(dev);
+@@ -1006,7 +1006,7 @@ static void free_resources(struct comedi_device * dev)
+ 		free_irq(dev->irq, dev);
+ 	if (dev->iobase)
+ 		release_region(dev->iobase, this_board->io_range);
+-	//rt_printk("free_resource() end\n");
++	/* rt_printk("free_resource() end\n"); */
+ }
+ 
+ /*
+@@ -1021,7 +1021,7 @@ static int pcl816_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	unsigned long iobase;
+ 	unsigned int irq, dma;
+ 	unsigned long pages;
+-	//int i;
++	/* int i; */
+ 	struct comedi_subdevice *s;
+ 
+ 	/* claim our I/O space */
+@@ -1084,7 +1084,7 @@ static int pcl816_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ #ifdef unused
+ 	/* grab RTC for DMA operations */
+ 	devpriv->dma_rtc = 0;
+-	if (it->options[2] > 0) {	// we want to use DMA
++	if (it->options[2] > 0) {	/*  we want to use DMA */
+ 		if (RTC_lock == 0) {
+ 			if (!request_region(RTC_PORT(0), RTC_IO_EXTENT,
+ 					"pcl816 (RTC)"))
+@@ -1152,9 +1152,9 @@ static int pcl816_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 		devpriv->dmapages[0] = pages;
+ 		devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]);
+ 		devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE;
+-		//rt_printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE);
++		/* rt_printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE); */
+ 
+-		if (devpriv->dma_rtc == 0) {	// we must do duble buff :-(
++		if (devpriv->dma_rtc == 0) {	/*  we must do duble buff :-( */
+ 			devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages);
+ 			if (!devpriv->dmabuf[1]) {
+ 				rt_printk
+@@ -1188,7 +1188,7 @@ static int pcl816_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 		s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
+ 		s->n_chan = this_board->n_aichan;
+ 		s->subdev_flags |= SDF_DIFF;
+-		//printk (", %dchans DIFF DAC - %d", s->n_chan, i);
++		/* printk (", %dchans DIFF DAC - %d", s->n_chan, i); */
+ 		s->maxdata = this_board->ai_maxdata;
+ 		s->len_chanlist = this_board->ai_chanlist;
+ 		s->range_table = this_board->ai_range_type;

commit 701a91f1e57b7e349af35cc0993e4145ca041c0c
+Author: Bill Pemberton 
+Date:   Fri Mar 27 11:31:16 2009 -0400
+
+    Staging: comedi: remove C99 comments in pcl724.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c
+index cd1e784f25f9..1f7763b2b653 100644
+--- a/drivers/staging/comedi/drivers/pcl724.c
++++ b/drivers/staging/comedi/drivers/pcl724.c
+@@ -54,18 +54,18 @@ See the source for configuration details.
+ 
+ #define SIZE_8255	4
+ 
+-// #define PCL724_IRQ   1  /* no IRQ support now */
++/* #define PCL724_IRQ   1  no IRQ support now */
+ 
+ static int pcl724_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pcl724_detach(struct comedi_device * dev);
+ 
+ struct pcl724_board {
+ 
+-	const char *name;	// board name
+-	int dio;		// num of DIO
+-	int numofports;		// num of 8255 subdevices
+-	unsigned int IRQbits;	// allowed interrupts
+-	unsigned int io_range;	// len of IO space
++	const char *name;	/*  board name */
++	int dio;		/*  num of DIO */
++	int numofports;		/*  num of 8255 subdevices */
++	unsigned int IRQbits;	/*  allowed interrupts */
++	unsigned int io_range;	/*  len of IO space */
+ 	char can_have96;
+ 	char is_pet48;
+ };
+@@ -137,7 +137,7 @@ static int pcl724_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	iorange = this_board->io_range;
+ 	if ((this_board->can_have96) && ((it->options[1] == 1)
+ 			|| (it->options[1] == 96)))
+-		iorange = PCL722_96_SIZE;	// PCL-724 in 96 DIO configuration
++		iorange = PCL722_96_SIZE;	/*  PCL-724 in 96 DIO configuration */
+ 	printk("comedi%d: pcl724: board=%s, 0x%03lx ", dev->minor,
+ 		this_board->name, iobase);
+ 	if (!request_region(iobase, iorange, "pcl724")) {
+@@ -181,7 +181,7 @@ static int pcl724_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	n_subdevices = this_board->numofports;
+ 	if ((this_board->can_have96) && ((it->options[1] == 1)
+ 			|| (it->options[1] == 96)))
+-		n_subdevices = 4;	// PCL-724 in 96 DIO configuration
++		n_subdevices = 4;	/*  PCL-724 in 96 DIO configuration */
+ 
+ 	if ((ret = alloc_subdevices(dev, n_subdevices)) < 0)
+ 		return ret;
+@@ -204,7 +204,7 @@ static int pcl724_detach(struct comedi_device * dev)
+ {
+ 	int i;
+ 
+-//      printk("comedi%d: pcl724: remove\n",dev->minor);
++/* printk("comedi%d: pcl724: remove\n",dev->minor); */
+ 
+ 	for (i = 0; i < dev->n_subdevices; i++) {
+ 		subdev_8255_cleanup(dev, dev->subdevices + i);

commit f6b49620a43ca661246d209009b849d7d3030cae
+Author: Bill Pemberton 
+Date:   Fri Mar 27 11:31:11 2009 -0400
+
+    Staging: comedi: remove C99 comments in ni_labpc.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
+index c0da5c75b4bb..028eada2ad74 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc.c
++++ b/drivers/staging/comedi/drivers/ni_labpc.c
+@@ -74,7 +74,7 @@ NI manuals:
+ */
+ 
+ #undef LABPC_DEBUG
+-//#define LABPC_DEBUG   // enable debugging messages
++/* #define LABPC_DEBUG    enable debugging messages */
+ 
+ #include "../comedidev.h"
+ 
+@@ -89,78 +89,78 @@ NI manuals:
+ 
+ #define DRV_NAME "ni_labpc"
+ 
+-#define LABPC_SIZE           32	// size of io region used by board
+-#define LABPC_TIMER_BASE            500	// 2 MHz master clock
++#define LABPC_SIZE           32	/*  size of io region used by board */
++#define LABPC_TIMER_BASE            500	/*  2 MHz master clock */
+ 
+ /* Registers for the lab-pc+ */
+ 
+-//write-only registers
++/* write-only registers */
+ #define COMMAND1_REG	0x0
+ #define   ADC_GAIN_MASK	(0x7 << 4)
+ #define   ADC_CHAN_BITS(x)	((x) & 0x7)
+-#define   ADC_SCAN_EN_BIT	0x80	// enables multi channel scans
++#define   ADC_SCAN_EN_BIT	0x80	/*  enables multi channel scans */
+ #define COMMAND2_REG	0x1
+-#define   PRETRIG_BIT	0x1	// enable pretriggering (used in conjunction with SWTRIG)
+-#define   HWTRIG_BIT	0x2	// enable paced conversions on external trigger
+-#define   SWTRIG_BIT	0x4	// enable paced conversions
+-#define   CASCADE_BIT	0x8	// use two cascaded counters for pacing
++#define   PRETRIG_BIT	0x1	/*  enable pretriggering (used in conjunction with SWTRIG) */
++#define   HWTRIG_BIT	0x2	/*  enable paced conversions on external trigger */
++#define   SWTRIG_BIT	0x4	/*  enable paced conversions */
++#define   CASCADE_BIT	0x8	/*  use two cascaded counters for pacing */
+ #define   DAC_PACED_BIT(channel)	(0x40 << ((channel) & 0x1))
+ #define COMMAND3_REG	0x2
+-#define   DMA_EN_BIT	0x1	// enable dma transfers
+-#define   DIO_INTR_EN_BIT	0x2	// enable interrupts for 8255
+-#define   DMATC_INTR_EN_BIT	0x4	// enable dma terminal count interrupt
+-#define   TIMER_INTR_EN_BIT	0x8	// enable timer interrupt
+-#define   ERR_INTR_EN_BIT	0x10	// enable error interrupt
+-#define   ADC_FNE_INTR_EN_BIT	0x20	// enable fifo not empty interrupt
++#define   DMA_EN_BIT	0x1	/*  enable dma transfers */
++#define   DIO_INTR_EN_BIT	0x2	/*  enable interrupts for 8255 */
++#define   DMATC_INTR_EN_BIT	0x4	/*  enable dma terminal count interrupt */
++#define   TIMER_INTR_EN_BIT	0x8	/*  enable timer interrupt */
++#define   ERR_INTR_EN_BIT	0x10	/*  enable error interrupt */
++#define   ADC_FNE_INTR_EN_BIT	0x20	/*  enable fifo not empty interrupt */
+ #define ADC_CONVERT_REG	0x3
+ #define DAC_LSB_REG(channel)	(0x4 + 2 * ((channel) & 0x1))
+ #define DAC_MSB_REG(channel)	(0x5 + 2 * ((channel) & 0x1))
+ #define ADC_CLEAR_REG	0x8
+ #define DMATC_CLEAR_REG	0xa
+ #define TIMER_CLEAR_REG	0xc
+-#define COMMAND6_REG	0xe	// 1200 boards only
+-#define   ADC_COMMON_BIT	0x1	// select ground or common-mode reference
+-#define   ADC_UNIP_BIT	0x2	// adc unipolar
+-#define   DAC_UNIP_BIT(channel)	(0x4 << ((channel) & 0x1))	// dac unipolar
+-#define   ADC_FHF_INTR_EN_BIT	0x20	// enable fifo half full interrupt
+-#define   A1_INTR_EN_BIT	0x40	// enable interrupt on end of hardware count
+-#define   ADC_SCAN_UP_BIT 0x80	// scan up from channel zero instead of down to zero
++#define COMMAND6_REG	0xe	/*  1200 boards only */
++#define   ADC_COMMON_BIT	0x1	/*  select ground or common-mode reference */
++#define   ADC_UNIP_BIT	0x2	/*  adc unipolar */
++#define   DAC_UNIP_BIT(channel)	(0x4 << ((channel) & 0x1))	/*  dac unipolar */
++#define   ADC_FHF_INTR_EN_BIT	0x20	/*  enable fifo half full interrupt */
++#define   A1_INTR_EN_BIT	0x40	/*  enable interrupt on end of hardware count */
++#define   ADC_SCAN_UP_BIT 0x80	/*  scan up from channel zero instead of down to zero */
+ #define COMMAND4_REG	0xf
+-#define   INTERVAL_SCAN_EN_BIT	0x1	// enables 'interval' scanning
+-#define   EXT_SCAN_EN_BIT	0x2	// enables external signal on counter b1 output to trigger scan
+-#define   EXT_CONVERT_OUT_BIT	0x4	// chooses direction (output or input) for EXTCONV* line
+-#define   ADC_DIFF_BIT	0x8	// chooses differential inputs for adc (in conjunction with board jumper)
++#define   INTERVAL_SCAN_EN_BIT	0x1	/*  enables 'interval' scanning */
++#define   EXT_SCAN_EN_BIT	0x2	/*  enables external signal on counter b1 output to trigger scan */
++#define   EXT_CONVERT_OUT_BIT	0x4	/*  chooses direction (output or input) for EXTCONV* line */
++#define   ADC_DIFF_BIT	0x8	/*  chooses differential inputs for adc (in conjunction with board jumper) */
+ #define   EXT_CONVERT_DISABLE_BIT	0x10
+-#define COMMAND5_REG	0x1c	// 1200 boards only, calibration stuff
+-#define   EEPROM_WRITE_UNPROTECT_BIT	0x4	// enable eeprom for write
+-#define   DITHER_EN_BIT	0x8	// enable dithering
+-#define   CALDAC_LOAD_BIT	0x10	// load calibration dac
+-#define   SCLOCK_BIT	0x20	// serial clock - rising edge writes, falling edge reads
+-#define   SDATA_BIT	0x40	// serial data bit for writing to eeprom or calibration dacs
+-#define   EEPROM_EN_BIT	0x80	// enable eeprom for read/write
++#define COMMAND5_REG	0x1c	/*  1200 boards only, calibration stuff */
++#define   EEPROM_WRITE_UNPROTECT_BIT	0x4	/*  enable eeprom for write */
++#define   DITHER_EN_BIT	0x8	/*  enable dithering */
++#define   CALDAC_LOAD_BIT	0x10	/*  load calibration dac */
++#define   SCLOCK_BIT	0x20	/*  serial clock - rising edge writes, falling edge reads */
++#define   SDATA_BIT	0x40	/*  serial data bit for writing to eeprom or calibration dacs */
++#define   EEPROM_EN_BIT	0x80	/*  enable eeprom for read/write */
+ #define INTERVAL_COUNT_REG	0x1e
+ #define INTERVAL_LOAD_REG	0x1f
+ #define   INTERVAL_LOAD_BITS	0x1
+ 
+-// read-only registers
++/* read-only registers */
+ #define STATUS1_REG	0x0
+-#define   DATA_AVAIL_BIT	0x1	// data is available in fifo
+-#define   OVERRUN_BIT	0x2	// overrun has occurred
+-#define   OVERFLOW_BIT	0x4	// fifo overflow
+-#define   TIMER_BIT	0x8	// timer interrupt has occured
+-#define   DMATC_BIT	0x10	// dma terminal count has occured
+-#define   EXT_TRIG_BIT	0x40	// external trigger has occured
+-#define STATUS2_REG	0x1d	// 1200 boards only
+-#define   EEPROM_OUT_BIT	0x1	// programmable eeprom serial output
+-#define   A1_TC_BIT	0x2	// counter A1 terminal count
+-#define   FNHF_BIT	0x4	// fifo not half full
++#define   DATA_AVAIL_BIT	0x1	/*  data is available in fifo */
++#define   OVERRUN_BIT	0x2	/*  overrun has occurred */
++#define   OVERFLOW_BIT	0x4	/*  fifo overflow */
++#define   TIMER_BIT	0x8	/*  timer interrupt has occured */
++#define   DMATC_BIT	0x10	/*  dma terminal count has occured */
++#define   EXT_TRIG_BIT	0x40	/*  external trigger has occured */
++#define STATUS2_REG	0x1d	/*  1200 boards only */
++#define   EEPROM_OUT_BIT	0x1	/*  programmable eeprom serial output */
++#define   A1_TC_BIT	0x2	/*  counter A1 terminal count */
++#define   FNHF_BIT	0x4	/*  fifo not half full */
+ #define ADC_FIFO_REG	0xa
+ 
+ #define DIO_BASE_REG	0x10
+ #define COUNTER_A_BASE_REG	0x14
+ #define COUNTER_A_CONTROL_REG	(COUNTER_A_BASE_REG + 0x3)
+-#define   INIT_A0_BITS	0x14	// check modes put conversion pacer output in harmless state (a0 mode 2)
+-#define   INIT_A1_BITS	0x70	// put hardware conversion counter output in harmless state (a1 mode 0)
++#define   INIT_A0_BITS	0x14	/*  check modes put conversion pacer output in harmless state (a0 mode 2) */
++#define   INIT_A1_BITS	0x70	/*  put hardware conversion counter output in harmless state (a1 mode 0) */
+ #define COUNTER_B_BASE_REG	0x18
+ 
+ static int labpc_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+@@ -212,9 +212,9 @@ enum scan_mode {
+ 	MODE_MULT_CHAN_DOWN,
+ };
+ 
+-//analog input ranges
++/* analog input ranges */
+ #define NUM_LABPC_PLUS_AI_RANGES 16
+-// indicates unipolar ranges
++/* indicates unipolar ranges */
+ static const int labpc_plus_is_unipolar[NUM_LABPC_PLUS_AI_RANGES] = {
+ 	0,
+ 	0,
+@@ -234,7 +234,7 @@ static const int labpc_plus_is_unipolar[NUM_LABPC_PLUS_AI_RANGES] = {
+ 	1,
+ };
+ 
+-// map range index to gain bits
++/* map range index to gain bits */
+ static const int labpc_plus_ai_gain_bits[NUM_LABPC_PLUS_AI_RANGES] = {
+ 	0x00,
+ 	0x10,
+@@ -276,7 +276,7 @@ static const struct comedi_lrange range_labpc_plus_ai = {
+ };
+ 
+ #define NUM_LABPC_1200_AI_RANGES 14
+-// indicates unipolar ranges
++/* indicates unipolar ranges */
+ const int labpc_1200_is_unipolar[NUM_LABPC_1200_AI_RANGES] = {
+ 	0,
+ 	0,
+@@ -294,7 +294,7 @@ const int labpc_1200_is_unipolar[NUM_LABPC_1200_AI_RANGES] = {
+ 	1,
+ };
+ 
+-// map range index to gain bits
++/* map range index to gain bits */
+ const int labpc_1200_ai_gain_bits[NUM_LABPC_1200_AI_RANGES] = {
+ 	0x00,
+ 	0x20,
+@@ -331,7 +331,7 @@ const struct comedi_lrange range_labpc_1200_ai = {
+ 		}
+ };
+ 
+-//analog output ranges
++/* analog output ranges */
+ #define AO_RANGE_IS_UNIPOLAR 0x1
+ static const struct comedi_lrange range_labpc_ao = {
+ 	2,
+@@ -411,7 +411,7 @@ static const struct labpc_board_struct labpc_boards[] = {
+ 		ai_scan_up:1,
+ 		memory_mapped_io:1,
+ 		},
+-	// dummy entry so pci board works when comedi_config is passed driver name
++	/*  dummy entry so pci board works when comedi_config is passed driver name */
+ 	{
+ 		.name = DRV_NAME,
+ 		.bustype = pci_bustype,
+@@ -424,8 +424,8 @@ static const struct labpc_board_struct labpc_boards[] = {
+  */
+ #define thisboard ((struct labpc_board_struct *)dev->board_ptr)
+ 
+-static const int dma_buffer_size = 0xff00;	// size in bytes of dma buffer
+-static const int sample_size = 2;	// 2 bytes per sample
++static const int dma_buffer_size = 0xff00;	/*  size in bytes of dma buffer */
++static const int sample_size = 2;	/*  2 bytes per sample */
+ 
+ #define devpriv ((struct labpc_private *)dev->private)
+ 
+@@ -481,7 +481,7 @@ int labpc_common_attach(struct comedi_device * dev, unsigned long iobase,
+ 		printk("io base address is zero!\n");
+ 		return -EINVAL;
+ 	}
+-	// request io regions for isa boards
++	/*  request io regions for isa boards */
+ 	if (thisboard->bustype == isa_bustype) {
+ 		/* check if io addresses are available */
+ 		if (!request_region(iobase, LABPC_SIZE,
+@@ -499,7 +499,7 @@ int labpc_common_attach(struct comedi_device * dev, unsigned long iobase,
+ 		devpriv->read_byte = labpc_inb;
+ 		devpriv->write_byte = labpc_outb;
+ 	}
+-	// initialize board's command registers
++	/*  initialize board's command registers */
+ 	devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG);
+ 	devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG);
+ 	devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG);
+@@ -524,12 +524,12 @@ int labpc_common_attach(struct comedi_device * dev, unsigned long iobase,
+ 	}
+ 	dev->irq = irq;
+ 
+-	// grab dma channel
++	/*  grab dma channel */
+ 	if (dma_chan > 3) {
+ 		printk(" invalid dma channel %u\n", dma_chan);
+ 		return -EINVAL;
+ 	} else if (dma_chan) {
+-		// allocate dma buffer
++		/*  allocate dma buffer */
+ 		devpriv->dma_buffer =
+ 			kmalloc(dma_buffer_size, GFP_KERNEL | GFP_DMA);
+ 		if (devpriv->dma_buffer == NULL) {
+@@ -562,7 +562,7 @@ int labpc_common_attach(struct comedi_device * dev, unsigned long iobase,
+ 		SDF_CMD_READ;
+ 	s->n_chan = 8;
+ 	s->len_chanlist = 8;
+-	s->maxdata = (1 << 12) - 1;	// 12 bit resolution
++	s->maxdata = (1 << 12) - 1;	/*  12 bit resolution */
+ 	s->range_table = thisboard->ai_range_table;
+ 	s->do_cmd = labpc_ai_cmd;
+ 	s->do_cmdtest = labpc_ai_cmdtest;
+@@ -577,7 +577,7 @@ int labpc_common_attach(struct comedi_device * dev, unsigned long iobase,
+ 		s->type = COMEDI_SUBD_AO;
+ 		s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND;
+ 		s->n_chan = NUM_AO_CHAN;
+-		s->maxdata = (1 << 12) - 1;	// 12 bit resolution
++		s->maxdata = (1 << 12) - 1;	/*  12 bit resolution */
+ 		s->range_table = &range_labpc_ao;
+ 		s->insn_read = labpc_ao_rinsn;
+ 		s->insn_write = labpc_ao_winsn;
+@@ -595,14 +595,14 @@ int labpc_common_attach(struct comedi_device * dev, unsigned long iobase,
+ 
+ 	/* 8255 dio */
+ 	s = dev->subdevices + 2;
+-	// if board uses io memory we have to give a custom callback function to the 8255 driver
++	/*  if board uses io memory we have to give a custom callback function to the 8255 driver */
+ 	if (thisboard->memory_mapped_io)
+ 		subdev_8255_init(dev, s, labpc_dio_mem_callback,
+ 			(unsigned long)(dev->iobase + DIO_BASE_REG));
+ 	else
+ 		subdev_8255_init(dev, s, NULL, dev->iobase + DIO_BASE_REG);
+ 
+-	// calibration subdevices for boards that have one
++	/*  calibration subdevices for boards that have one */
+ 	s = dev->subdevices + 3;
+ 	if (thisboard->register_layout == labpc_1200_layout) {
+ 		s->type = COMEDI_SUBD_CALIB;
+@@ -656,7 +656,7 @@ static int labpc_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 	if (alloc_private(dev, sizeof(struct labpc_private)) < 0)
+ 		return -ENOMEM;
+ 
+-	// get base address, irq etc. based on bustype
++	/*  get base address, irq etc. based on bustype */
+ 	switch (thisboard->bustype) {
+ 	case isa_bustype:
+ 		iobase = it->options[0];
+@@ -692,7 +692,7 @@ static int labpc_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 	return labpc_common_attach(dev, iobase, irq, dma_chan);
+ }
+ 
+-// adapted from ni_pcimio for finding mite based boards (pc-1200)
++/* adapted from ni_pcimio for finding mite based boards (pc-1200) */
+ #ifdef CONFIG_COMEDI_PCI
+ static int labpc_find_device(struct comedi_device *dev, int bus, int slot)
+ {
+@@ -701,7 +701,7 @@ static int labpc_find_device(struct comedi_device *dev, int bus, int slot)
+ 	for (mite = mite_devices; mite; mite = mite->next) {
+ 		if (mite->used)
+ 			continue;
+-		// if bus/slot are specified then make sure we have the right bus/slot
++		/*  if bus/slot are specified then make sure we have the right bus/slot */
+ 		if (bus || slot) {
+ 			if (bus != mite->pcidev->bus->number
+ 				|| slot != PCI_SLOT(mite->pcidev->devfn))
+@@ -712,7 +712,7 @@ static int labpc_find_device(struct comedi_device *dev, int bus, int slot)
+ 				continue;
+ 			if (mite_device_id(mite) == labpc_boards[i].device_id) {
+ 				devpriv->mite = mite;
+-				// fixup board pointer, in case we were using the dummy "ni_labpc" entry
++				/*  fixup board pointer, in case we were using the dummy "ni_labpc" entry */
+ 				dev->board_ptr = &labpc_boards[i];
+ 				return 0;
+ 			}
+@@ -980,7 +980,7 @@ static int labpc_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice
+ 		cmd->stop_src != TRIG_EXT && cmd->stop_src != TRIG_NONE)
+ 		err++;
+ 
+-	// can't have external stop and start triggers at once
++	/*  can't have external stop and start triggers at once */
+ 	if (cmd->start_src == TRIG_EXT && cmd->stop_src == TRIG_EXT)
+ 		err++;
+ 
+@@ -1008,7 +1008,7 @@ static int labpc_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice
+ 			err++;
+ 		}
+ 	}
+-	// make sure scan timing is not too fast
++	/*  make sure scan timing is not too fast */
+ 	if (cmd->scan_begin_src == TRIG_TIMER) {
+ 		if (cmd->convert_src == TRIG_TIMER &&
+ 			cmd->scan_begin_arg <
+@@ -1024,7 +1024,7 @@ static int labpc_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice
+ 			err++;
+ 		}
+ 	}
+-	// stop source
++	/*  stop source */
+ 	switch (cmd->stop_src) {
+ 	case TRIG_COUNT:
+ 		if (!cmd->stop_arg) {
+@@ -1038,7 +1038,7 @@ static int labpc_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice
+ 			err++;
+ 		}
+ 		break;
+-		// TRIG_EXT doesn't care since it doesn't trigger off a numbered channel
++		/*  TRIG_EXT doesn't care since it doesn't trigger off a numbered channel */
+ 	default:
+ 		break;
+ 	}
+@@ -1081,7 +1081,7 @@ static int labpc_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	range = CR_RANGE(cmd->chanlist[0]);
+ 	aref = CR_AREF(cmd->chanlist[0]);
+ 
+-	// make sure board is disabled before setting up aquisition
++	/*  make sure board is disabled before setting up aquisition */
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 	devpriv->command2_bits &= ~SWTRIG_BIT & ~HWTRIG_BIT & ~PRETRIG_BIT;
+ 	devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG);
+@@ -1090,68 +1090,68 @@ static int labpc_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	devpriv->command3_bits = 0;
+ 	devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG);
+ 
+-	// initialize software conversion count
++	/*  initialize software conversion count */
+ 	if (cmd->stop_src == TRIG_COUNT) {
+ 		devpriv->count = cmd->stop_arg * cmd->chanlist_len;
+ 	}
+-	// setup hardware conversion counter
++	/*  setup hardware conversion counter */
+ 	if (cmd->stop_src == TRIG_EXT) {
+-		// load counter a1 with count of 3 (pc+ manual says this is minimum allowed) using mode 0
++		/*  load counter a1 with count of 3 (pc+ manual says this is minimum allowed) using mode 0 */
+ 		ret = labpc_counter_load(dev, dev->iobase + COUNTER_A_BASE_REG,
+ 			1, 3, 0);
+ 		if (ret < 0) {
+ 			comedi_error(dev, "error loading counter a1");
+ 			return -1;
+ 		}
+-	} else			// otherwise, just put a1 in mode 0 with no count to set its output low
++	} else			/*  otherwise, just put a1 in mode 0 with no count to set its output low */
+ 		devpriv->write_byte(INIT_A1_BITS,
+ 			dev->iobase + COUNTER_A_CONTROL_REG);
+ 
+-	// figure out what method we will use to transfer data
+-	if (devpriv->dma_chan &&	// need a dma channel allocated
+-		// dma unsafe at RT priority, and too much setup time for TRIG_WAKE_EOS for
++	/*  figure out what method we will use to transfer data */
++	if (devpriv->dma_chan &&	/*  need a dma channel allocated */
++		/*  dma unsafe at RT priority, and too much setup time for TRIG_WAKE_EOS for */
+ 		(cmd->flags & (TRIG_WAKE_EOS | TRIG_RT)) == 0 &&
+-		// only available on the isa boards
++		/*  only available on the isa boards */
+ 		thisboard->bustype == isa_bustype) {
+ 		xfer = isa_dma_transfer;
+-	} else if (thisboard->register_layout == labpc_1200_layout &&	// pc-plus has no fifo-half full interrupt
+-		// wake-end-of-scan should interrupt on fifo not empty
++	} else if (thisboard->register_layout == labpc_1200_layout &&	/*  pc-plus has no fifo-half full interrupt */
++		/*  wake-end-of-scan should interrupt on fifo not empty */
+ 		(cmd->flags & TRIG_WAKE_EOS) == 0 &&
+-		// make sure we are taking more than just a few points
++		/*  make sure we are taking more than just a few points */
+ 		(cmd->stop_src != TRIG_COUNT || devpriv->count > 256)) {
+ 		xfer = fifo_half_full_transfer;
+ 	} else
+ 		xfer = fifo_not_empty_transfer;
+ 	devpriv->current_transfer = xfer;
+ 
+-	// setup command6 register for 1200 boards
++	/*  setup command6 register for 1200 boards */
+ 	if (thisboard->register_layout == labpc_1200_layout) {
+-		// reference inputs to ground or common?
++		/*  reference inputs to ground or common? */
+ 		if (aref != AREF_GROUND)
+ 			devpriv->command6_bits |= ADC_COMMON_BIT;
+ 		else
+ 			devpriv->command6_bits &= ~ADC_COMMON_BIT;
+-		// bipolar or unipolar range?
++		/*  bipolar or unipolar range? */
+ 		if (thisboard->ai_range_is_unipolar[range])
+ 			devpriv->command6_bits |= ADC_UNIP_BIT;
+ 		else
+ 			devpriv->command6_bits &= ~ADC_UNIP_BIT;
+-		// interrupt on fifo half full?
++		/*  interrupt on fifo half full? */
+ 		if (xfer == fifo_half_full_transfer)
+ 			devpriv->command6_bits |= ADC_FHF_INTR_EN_BIT;
+ 		else
+ 			devpriv->command6_bits &= ~ADC_FHF_INTR_EN_BIT;
+-		// enable interrupt on counter a1 terminal count?
++		/*  enable interrupt on counter a1 terminal count? */
+ 		if (cmd->stop_src == TRIG_EXT)
+ 			devpriv->command6_bits |= A1_INTR_EN_BIT;
+ 		else
+ 			devpriv->command6_bits &= ~A1_INTR_EN_BIT;
+-		// are we scanning up or down through channels?
++		/*  are we scanning up or down through channels? */
+ 		if (labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_UP)
+ 			devpriv->command6_bits |= ADC_SCAN_UP_BIT;
+ 		else
+ 			devpriv->command6_bits &= ~ADC_SCAN_UP_BIT;
+-		// write to register
++		/*  write to register */
+ 		devpriv->write_byte(devpriv->command6_bits,
+ 			dev->iobase + COMMAND6_REG);
+ 	}
+@@ -1162,13 +1162,13 @@ static int labpc_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 		channel = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]);
+ 	else
+ 		channel = CR_CHAN(cmd->chanlist[0]);
+-	// munge channel bits for differential / scan disabled mode
++	/*  munge channel bits for differential / scan disabled mode */
+ 	if (labpc_ai_scan_mode(cmd) != MODE_SINGLE_CHAN && aref == AREF_DIFF)
+ 		channel *= 2;
+ 	devpriv->command1_bits |= ADC_CHAN_BITS(channel);
+ 	devpriv->command1_bits |= thisboard->ai_range_code[range];
+ 	devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG);
+-	// manual says to set scan enable bit on second pass
++	/*  manual says to set scan enable bit on second pass */
+ 	if (labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_UP ||
+ 		labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_DOWN) {
+ 		devpriv->command1_bits |= ADC_SCAN_EN_BIT;
+@@ -1178,7 +1178,7 @@ static int labpc_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 		devpriv->write_byte(devpriv->command1_bits,
+ 			dev->iobase + COMMAND1_REG);
+ 	}
+-	// setup any external triggering/pacing (command4 register)
++	/*  setup any external triggering/pacing (command4 register) */
+ 	devpriv->command4_bits = 0;
+ 	if (cmd->convert_src != TRIG_EXT)
+ 		devpriv->command4_bits |= EXT_CONVERT_DISABLE_BIT;
+@@ -1189,21 +1189,21 @@ static int labpc_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 		if (cmd->scan_begin_src == TRIG_EXT)
+ 			devpriv->command4_bits |= EXT_SCAN_EN_BIT;
+ 	}
+-	// single-ended/differential
++	/*  single-ended/differential */
+ 	if (aref == AREF_DIFF)
+ 		devpriv->command4_bits |= ADC_DIFF_BIT;
+ 	devpriv->write_byte(devpriv->command4_bits, dev->iobase + COMMAND4_REG);
+ 
+ 	devpriv->write_byte(cmd->chanlist_len,
+ 		dev->iobase + INTERVAL_COUNT_REG);
+-	// load count
++	/*  load count */
+ 	devpriv->write_byte(INTERVAL_LOAD_BITS,
+ 		dev->iobase + INTERVAL_LOAD_REG);
+ 
+ 	if (cmd->convert_src == TRIG_TIMER || cmd->scan_begin_src == TRIG_TIMER) {
+-		// set up pacing
++		/*  set up pacing */
+ 		labpc_adc_timing(dev, cmd);
+-		// load counter b0 in mode 3
++		/*  load counter b0 in mode 3 */
+ 		ret = labpc_counter_load(dev, dev->iobase + COUNTER_B_BASE_REG,
+ 			0, devpriv->divisor_b0, 3);
+ 		if (ret < 0) {
+@@ -1211,9 +1211,9 @@ static int labpc_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 			return -1;
+ 		}
+ 	}
+-	// set up conversion pacing
++	/*  set up conversion pacing */
+ 	if (labpc_ai_convert_period(cmd)) {
+-		// load counter a0 in mode 2
++		/*  load counter a0 in mode 2 */
+ 		ret = labpc_counter_load(dev, dev->iobase + COUNTER_A_BASE_REG,
+ 			0, devpriv->divisor_a0, 2);
+ 		if (ret < 0) {
+@@ -1224,9 +1224,9 @@ static int labpc_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 		devpriv->write_byte(INIT_A0_BITS,
+ 			dev->iobase + COUNTER_A_CONTROL_REG);
+ 
+-	// set up scan pacing
++	/*  set up scan pacing */
+ 	if (labpc_ai_scan_period(cmd)) {
+-		// load counter b1 in mode 2
++		/*  load counter b1 in mode 2 */
+ 		ret = labpc_counter_load(dev, dev->iobase + COUNTER_B_BASE_REG,
+ 			1, devpriv->divisor_b1, 2);
+ 		if (ret < 0) {
+@@ -1237,7 +1237,7 @@ static int labpc_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 
+ 	labpc_clear_adc_fifo(dev);
+ 
+-	// set up dma transfer
++	/*  set up dma transfer */
+ 	if (xfer == isa_dma_transfer) {
+ 		irq_flags = claim_dma_lock();
+ 		disable_dma(devpriv->dma_chan);
+@@ -1246,7 +1246,7 @@ static int labpc_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 		clear_dma_ff(devpriv->dma_chan);
+ 		set_dma_addr(devpriv->dma_chan,
+ 			virt_to_bus(devpriv->dma_buffer));
+-		// set appropriate size of transfer
++		/*  set appropriate size of transfer */
+ 		devpriv->dma_transfer_size = labpc_suggest_transfer_size(*cmd);
+ 		if (cmd->stop_src == TRIG_COUNT &&
+ 			devpriv->count * sample_size <
+@@ -1257,24 +1257,24 @@ static int labpc_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 		set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
+ 		enable_dma(devpriv->dma_chan);
+ 		release_dma_lock(irq_flags);
+-		// enable board's dma
++		/*  enable board's dma */
+ 		devpriv->command3_bits |= DMA_EN_BIT | DMATC_INTR_EN_BIT;
+ 	} else
+ 		devpriv->command3_bits &= ~DMA_EN_BIT & ~DMATC_INTR_EN_BIT;
+ 
+-	// enable error interrupts
++	/*  enable error interrupts */
+ 	devpriv->command3_bits |= ERR_INTR_EN_BIT;
+-	// enable fifo not empty interrupt?
++	/*  enable fifo not empty interrupt? */
+ 	if (xfer == fifo_not_empty_transfer)
+ 		devpriv->command3_bits |= ADC_FNE_INTR_EN_BIT;
+ 	else
+ 		devpriv->command3_bits &= ~ADC_FNE_INTR_EN_BIT;
+ 	devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG);
+ 
+-	// startup aquisition
++	/*  startup aquisition */
+ 
+-	// command2 reg
+-	// use 2 cascaded counters for pacing
++	/*  command2 reg */
++	/*  use 2 cascaded counters for pacing */
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 	devpriv->command2_bits |= CASCADE_BIT;
+ 	switch (cmd->start_src) {
+@@ -1325,7 +1325,7 @@ static irqreturn_t labpc_interrupt(int irq, void *d PT_REGS_ARG)
+ 	cmd = &async->cmd;
+ 	async->events = 0;
+ 
+-	// read board status
++	/*  read board status */
+ 	devpriv->status1_bits = devpriv->read_byte(dev->iobase + STATUS1_REG);
+ 	if (thisboard->register_layout == labpc_1200_layout)
+ 		devpriv->status2_bits =
+@@ -1339,7 +1339,7 @@ static irqreturn_t labpc_interrupt(int irq, void *d PT_REGS_ARG)
+ 	}
+ 
+ 	if (devpriv->status1_bits & OVERRUN_BIT) {
+-		// clear error interrupt
++		/*  clear error interrupt */
+ 		devpriv->write_byte(0x1, dev->iobase + ADC_CLEAR_REG);
+ 		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
+ 		comedi_event(dev, s);
+@@ -1348,7 +1348,7 @@ static irqreturn_t labpc_interrupt(int irq, void *d PT_REGS_ARG)
+ 	}
+ 
+ 	if (devpriv->current_transfer == isa_dma_transfer) {
+-		// if a dma terminal count of external stop trigger has occurred
++		/*  if a dma terminal count of external stop trigger has occurred */
+ 		if (devpriv->status1_bits & DMATC_BIT ||
+ 			(thisboard->register_layout == labpc_1200_layout
+ 				&& devpriv->status2_bits & A1_TC_BIT)) {
+@@ -1359,19 +1359,19 @@ static irqreturn_t labpc_interrupt(int irq, void *d PT_REGS_ARG)
+ 
+ 	if (devpriv->status1_bits & TIMER_BIT) {
+ 		comedi_error(dev, "handled timer interrupt?");
+-		// clear it
++		/*  clear it */
+ 		devpriv->write_byte(0x1, dev->iobase + TIMER_CLEAR_REG);
+ 	}
+ 
+ 	if (devpriv->status1_bits & OVERFLOW_BIT) {
+-		// clear error interrupt
++		/*  clear error interrupt */
+ 		devpriv->write_byte(0x1, dev->iobase + ADC_CLEAR_REG);
+ 		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
+ 		comedi_event(dev, s);
+ 		comedi_error(dev, "overflow");
+ 		return IRQ_HANDLED;
+ 	}
+-	// handle external stop trigger
++	/*  handle external stop trigger */
+ 	if (cmd->stop_src == TRIG_EXT) {
+ 		if (devpriv->status2_bits & A1_TC_BIT) {
+ 			labpc_drain_dregs(dev);
+@@ -1392,7 +1392,7 @@ static irqreturn_t labpc_interrupt(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-// read all available samples from ai fifo
++/* read all available samples from ai fifo */
+ static int labpc_drain_fifo(struct comedi_device * dev)
+ {
+ 	unsigned int lsb, msb;
+@@ -1405,7 +1405,7 @@ static int labpc_drain_fifo(struct comedi_device * dev)
+ 
+ 	for (i = 0; (devpriv->status1_bits & DATA_AVAIL_BIT) && i < timeout;
+ 		i++) {
+-		// quit if we have all the data we want
++		/*  quit if we have all the data we want */
+ 		if (async->cmd.stop_src == TRIG_COUNT) {
+ 			if (devpriv->count == 0)
+ 				break;
+@@ -1444,7 +1444,7 @@ static void labpc_drain_dma(struct comedi_device * dev)
+ 	 * count and address get set correctly */
+ 	clear_dma_ff(devpriv->dma_chan);
+ 
+-	// figure out how many points to read
++	/*  figure out how many points to read */
+ 	max_points = devpriv->dma_transfer_size / sample_size;
+ 	/* residue is the number of points left to be done on the dma
+ 	 * transfer.  It should always be zero at this point unless
+@@ -1455,7 +1455,7 @@ static void labpc_drain_dma(struct comedi_device * dev)
+ 	if (devpriv->count < num_points && async->cmd.stop_src == TRIG_COUNT)
+ 		num_points = devpriv->count;
+ 
+-	// figure out how many points will be stored next time
++	/*  figure out how many points will be stored next time */
+ 	leftover = 0;
+ 	if (async->cmd.stop_src != TRIG_COUNT) {
+ 		leftover = devpriv->dma_transfer_size / sample_size;
+@@ -1472,7 +1472,7 @@ static void labpc_drain_dma(struct comedi_device * dev)
+ 	if (async->cmd.stop_src == TRIG_COUNT)
+ 		devpriv->count -= num_points;
+ 
+-	// set address and count for next transfer
++	/*  set address and count for next transfer */
+ 	set_dma_addr(devpriv->dma_chan, virt_to_bus(devpriv->dma_buffer));
+ 	set_dma_count(devpriv->dma_chan, leftover * sample_size);
+ 	release_dma_lock(flags);
+@@ -1486,7 +1486,7 @@ static void handle_isa_dma(struct comedi_device * dev)
+ 
+ 	enable_dma(devpriv->dma_chan);
+ 
+-	// clear dma tc interrupt
++	/*  clear dma tc interrupt */
+ 	devpriv->write_byte(0x1, dev->iobase + DMATC_CLEAR_REG);
+ }
+ 
+@@ -1509,13 +1509,13 @@ static int labpc_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ 	int timeout = 1000;
+ 	unsigned long flags;
+ 
+-	// disable timed conversions
++	/*  disable timed conversions */
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 	devpriv->command2_bits &= ~SWTRIG_BIT & ~HWTRIG_BIT & ~PRETRIG_BIT;
+ 	devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG);
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ 
+-	// disable interrupt generation and dma
++	/*  disable interrupt generation and dma */
+ 	devpriv->command3_bits = 0;
+ 	devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG);
+ 
+@@ -1524,41 +1524,41 @@ static int labpc_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ 	chan = CR_CHAN(insn->chanspec);
+ 	range = CR_RANGE(insn->chanspec);
+ 	devpriv->command1_bits |= thisboard->ai_range_code[range];
+-	// munge channel bits for differential/scan disabled mode
++	/*  munge channel bits for differential/scan disabled mode */
+ 	if (CR_AREF(insn->chanspec) == AREF_DIFF)
+ 		chan *= 2;
+ 	devpriv->command1_bits |= ADC_CHAN_BITS(chan);
+ 	devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG);
+ 
+-	// setup command6 register for 1200 boards
++	/*  setup command6 register for 1200 boards */
+ 	if (thisboard->register_layout == labpc_1200_layout) {
+-		// reference inputs to ground or common?
++		/*  reference inputs to ground or common? */
+ 		if (CR_AREF(insn->chanspec) != AREF_GROUND)
+ 			devpriv->command6_bits |= ADC_COMMON_BIT;
+ 		else
+ 			devpriv->command6_bits &= ~ADC_COMMON_BIT;
+-		// bipolar or unipolar range?
++		/*  bipolar or unipolar range? */
+ 		if (thisboard->ai_range_is_unipolar[range])
+ 			devpriv->command6_bits |= ADC_UNIP_BIT;
+ 		else
+ 			devpriv->command6_bits &= ~ADC_UNIP_BIT;
+-		// don't interrupt on fifo half full
++		/*  don't interrupt on fifo half full */
+ 		devpriv->command6_bits &= ~ADC_FHF_INTR_EN_BIT;
+-		// don't enable interrupt on counter a1 terminal count?
++		/*  don't enable interrupt on counter a1 terminal count? */
+ 		devpriv->command6_bits &= ~A1_INTR_EN_BIT;
+-		// write to register
++		/*  write to register */
+ 		devpriv->write_byte(devpriv->command6_bits,
+ 			dev->iobase + COMMAND6_REG);
+ 	}
+-	// setup command4 register
++	/*  setup command4 register */
+ 	devpriv->command4_bits = 0;
+ 	devpriv->command4_bits |= EXT_CONVERT_DISABLE_BIT;
+-	// single-ended/differential
++	/*  single-ended/differential */
+ 	if (CR_AREF(insn->chanspec) == AREF_DIFF)
+ 		devpriv->command4_bits |= ADC_DIFF_BIT;
+ 	devpriv->write_byte(devpriv->command4_bits, dev->iobase + COMMAND4_REG);
+ 
+-	// initialize pacer counter output to make sure it doesn't cause any problems
++	/*  initialize pacer counter output to make sure it doesn't cause any problems */
+ 	devpriv->write_byte(INIT_A0_BITS, dev->iobase + COUNTER_A_CONTROL_REG);
+ 
+ 	labpc_clear_adc_fifo(dev);
+@@ -1585,7 +1585,7 @@ static int labpc_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ 	return n;
+ }
+ 
+-// analog output insn
++/* analog output insn */
+ static int labpc_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+@@ -1595,7 +1595,7 @@ static int labpc_ao_winsn(struct comedi_device * dev, struct comedi_subdevice *
+ 
+ 	channel = CR_CHAN(insn->chanspec);
+ 
+-	// turn off pacing of analog output channel
++	/*  turn off pacing of analog output channel */
+ 	/* note: hardware bug in daqcard-1200 means pacing cannot
+ 	 * be independently enabled/disabled for its the two channels */
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+@@ -1603,30 +1603,30 @@ static int labpc_ao_winsn(struct comedi_device * dev, struct comedi_subdevice *
+ 	devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG);
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ 
+-	// set range
++	/*  set range */
+ 	if (thisboard->register_layout == labpc_1200_layout) {
+ 		range = CR_RANGE(insn->chanspec);
+ 		if (range & AO_RANGE_IS_UNIPOLAR)
+ 			devpriv->command6_bits |= DAC_UNIP_BIT(channel);
+ 		else
+ 			devpriv->command6_bits &= ~DAC_UNIP_BIT(channel);
+-		// write to register
++		/*  write to register */
+ 		devpriv->write_byte(devpriv->command6_bits,
+ 			dev->iobase + COMMAND6_REG);
+ 	}
+-	// send data
++	/*  send data */
+ 	lsb = data[0] & 0xff;
+ 	msb = (data[0] >> 8) & 0xff;
+ 	devpriv->write_byte(lsb, dev->iobase + DAC_LSB_REG(channel));
+ 	devpriv->write_byte(msb, dev->iobase + DAC_MSB_REG(channel));
+ 
+-	// remember value for readback
++	/*  remember value for readback */
+ 	devpriv->ao_value[channel] = data[0];
+ 
+ 	return 1;
+ }
+ 
+-// analog output readback insn
++/* analog output readback insn */
+ static int labpc_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+@@ -1666,7 +1666,7 @@ static int labpc_eeprom_write_insn(struct comedi_device * dev, struct comedi_sub
+ 	int channel = CR_CHAN(insn->chanspec);
+ 	int ret;
+ 
+-	// only allow writes to user area of eeprom
++	/*  only allow writes to user area of eeprom */
+ 	if (channel < 16 || channel > 127) {
+ 		printk("eeprom writes are only allowed to channels 16 through 127 (the pointer and user areas)");
+ 		return -EINVAL;
+@@ -1679,7 +1679,7 @@ static int labpc_eeprom_write_insn(struct comedi_device * dev, struct comedi_sub
+ 	return 1;
+ }
+ 
+-// utility function that suggests a dma transfer size in bytes
++/* utility function that suggests a dma transfer size in bytes */
+ static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd)
+ {
+ 	unsigned int size;
+@@ -1687,14 +1687,14 @@ static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd)
+ 
+ 	if (cmd.convert_src == TRIG_TIMER)
+ 		freq = 1000000000 / cmd.convert_arg;
+-	// return some default value
++	/*  return some default value */
+ 	else
+ 		freq = 0xffffffff;
+ 
+-	// make buffer fill in no more than 1/3 second
++	/*  make buffer fill in no more than 1/3 second */
+ 	size = (freq / 3) * sample_size;
+ 
+-	// set a minimum and maximum size allowed
++	/*  set a minimum and maximum size allowed */
+ 	if (size > dma_buffer_size)
+ 		size = dma_buffer_size - dma_buffer_size % sample_size;
+ 	else if (size < sample_size)
+@@ -1703,16 +1703,16 @@ static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd)
+ 	return size;
+ }
+ 
+-// figures out what counter values to use based on command
++/* figures out what counter values to use based on command */
+ static void labpc_adc_timing(struct comedi_device * dev, struct comedi_cmd * cmd)
+ {
+-	const int max_counter_value = 0x10000;	// max value for 16 bit counter in mode 2
+-	const int min_counter_value = 2;	// min value for 16 bit counter in mode 2
++	const int max_counter_value = 0x10000;	/*  max value for 16 bit counter in mode 2 */
++	const int min_counter_value = 2;	/*  min value for 16 bit counter in mode 2 */
+ 	unsigned int base_period;
+ 
+-	// if both convert and scan triggers are TRIG_TIMER, then they both rely on counter b0
++	/*  if both convert and scan triggers are TRIG_TIMER, then they both rely on counter b0 */
+ 	if (labpc_ai_convert_period(cmd) && labpc_ai_scan_period(cmd)) {
+-		// pick the lowest b0 divisor value we can (for maximum input clock speed on convert and scan counters)
++		/*  pick the lowest b0 divisor value we can (for maximum input clock speed on convert and scan counters) */
+ 		devpriv->divisor_b0 = (labpc_ai_scan_period(cmd) - 1) /
+ 			(LABPC_TIMER_BASE * max_counter_value) + 1;
+ 		if (devpriv->divisor_b0 < min_counter_value)
+@@ -1722,7 +1722,7 @@ static void labpc_adc_timing(struct comedi_device * dev, struct comedi_cmd * cmd
+ 
+ 		base_period = LABPC_TIMER_BASE * devpriv->divisor_b0;
+ 
+-		// set a0 for conversion frequency and b1 for scan frequency
++		/*  set a0 for conversion frequency and b1 for scan frequency */
+ 		switch (cmd->flags & TRIG_ROUND_MASK) {
+ 		default:
+ 		case TRIG_ROUND_NEAREST:
+@@ -1748,7 +1748,7 @@ static void labpc_adc_timing(struct comedi_device * dev, struct comedi_cmd * cmd
+ 				labpc_ai_scan_period(cmd) / base_period;
+ 			break;
+ 		}
+-		// make sure a0 and b1 values are acceptable
++		/*  make sure a0 and b1 values are acceptable */
+ 		if (devpriv->divisor_a0 < min_counter_value)
+ 			devpriv->divisor_a0 = min_counter_value;
+ 		if (devpriv->divisor_a0 > max_counter_value)
+@@ -1757,12 +1757,12 @@ static void labpc_adc_timing(struct comedi_device * dev, struct comedi_cmd * cmd
+ 			devpriv->divisor_b1 = min_counter_value;
+ 		if (devpriv->divisor_b1 > max_counter_value)
+ 			devpriv->divisor_b1 = max_counter_value;
+-		// write corrected timings to command
++		/*  write corrected timings to command */
+ 		labpc_set_ai_convert_period(cmd,
+ 			base_period * devpriv->divisor_a0);
+ 		labpc_set_ai_scan_period(cmd,
+ 			base_period * devpriv->divisor_b1);
+-		// if only one TRIG_TIMER is used, we can employ the generic cascaded timing functions
++		/*  if only one TRIG_TIMER is used, we can employ the generic cascaded timing functions */
+ 	} else if (labpc_ai_scan_period(cmd)) {
+ 		unsigned int scan_period;
+ 
+@@ -1795,16 +1795,16 @@ static int labpc_dio_mem_callback(int dir, int port, int data,
+ 	}
+ }
+ 
+-// lowlevel write to eeprom/dac
++/* lowlevel write to eeprom/dac */
+ static void labpc_serial_out(struct comedi_device * dev, unsigned int value,
+ 	unsigned int value_width)
+ {
+ 	int i;
+ 
+ 	for (i = 1; i <= value_width; i++) {
+-		// clear serial clock
++		/*  clear serial clock */
+ 		devpriv->command5_bits &= ~SCLOCK_BIT;
+-		// send bits most significant bit first
++		/*  send bits most significant bit first */
+ 		if (value & (1 << (value_width - i)))
+ 			devpriv->command5_bits |= SDATA_BIT;
+ 		else
+@@ -1812,7 +1812,7 @@ static void labpc_serial_out(struct comedi_device * dev, unsigned int value,
+ 		comedi_udelay(1);
+ 		devpriv->write_byte(devpriv->command5_bits,
+ 			dev->iobase + COMMAND5_REG);
+-		// set clock to load bit
++		/*  set clock to load bit */
+ 		devpriv->command5_bits |= SCLOCK_BIT;
+ 		comedi_udelay(1);
+ 		devpriv->write_byte(devpriv->command5_bits,
+@@ -1820,25 +1820,25 @@ static void labpc_serial_out(struct comedi_device * dev, unsigned int value,
+ 	}
+ }
+ 
+-// lowlevel read from eeprom
++/* lowlevel read from eeprom */
+ static unsigned int labpc_serial_in(struct comedi_device * dev)
+ {
+ 	unsigned int value = 0;
+ 	int i;
+-	const int value_width = 8;	// number of bits wide values are
++	const int value_width = 8;	/*  number of bits wide values are */
+ 
+ 	for (i = 1; i <= value_width; i++) {
+-		// set serial clock
++		/*  set serial clock */
+ 		devpriv->command5_bits |= SCLOCK_BIT;
+ 		comedi_udelay(1);
+ 		devpriv->write_byte(devpriv->command5_bits,
+ 			dev->iobase + COMMAND5_REG);
+-		// clear clock bit
++		/*  clear clock bit */
+ 		devpriv->command5_bits &= ~SCLOCK_BIT;
+ 		comedi_udelay(1);
+ 		devpriv->write_byte(devpriv->command5_bits,
+ 			dev->iobase + COMMAND5_REG);
+-		// read bits most significant bit first
++		/*  read bits most significant bit first */
+ 		comedi_udelay(1);
+ 		devpriv->status2_bits =
+ 			devpriv->read_byte(dev->iobase + STATUS2_REG);
+@@ -1853,10 +1853,10 @@ static unsigned int labpc_serial_in(struct comedi_device * dev)
+ static unsigned int labpc_eeprom_read(struct comedi_device * dev, unsigned int address)
+ {
+ 	unsigned int value;
+-	const int read_instruction = 0x3;	// bits to tell eeprom to expect a read
+-	const int write_length = 8;	// 8 bit write lengths to eeprom
++	const int read_instruction = 0x3;	/*  bits to tell eeprom to expect a read */
++	const int write_length = 8;	/*  8 bit write lengths to eeprom */
+ 
+-	// enable read/write to eeprom
++	/*  enable read/write to eeprom */
+ 	devpriv->command5_bits &= ~EEPROM_EN_BIT;
+ 	comedi_udelay(1);
+ 	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
+@@ -1864,14 +1864,14 @@ static unsigned int labpc_eeprom_read(struct comedi_device * dev, unsigned int a
+ 	comedi_udelay(1);
+ 	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
+ 
+-	// send read instruction
++	/*  send read instruction */
+ 	labpc_serial_out(dev, read_instruction, write_length);
+-	// send 8 bit address to read from
++	/*  send 8 bit address to read from */
+ 	labpc_serial_out(dev, address, write_length);
+-	// read result
++	/*  read result */
+ 	value = labpc_serial_in(dev);
+ 
+-	// disable read/write to eeprom
++	/*  disable read/write to eeprom */
+ 	devpriv->command5_bits &= ~EEPROM_EN_BIT & ~EEPROM_WRITE_UNPROTECT_BIT;
+ 	comedi_udelay(1);
+ 	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
+@@ -1884,12 +1884,12 @@ static unsigned int labpc_eeprom_write(struct comedi_device * dev,
+ {
+ 	const int write_enable_instruction = 0x6;
+ 	const int write_instruction = 0x2;
+-	const int write_length = 8;	// 8 bit write lengths to eeprom
++	const int write_length = 8;	/*  8 bit write lengths to eeprom */
+ 	const int write_in_progress_bit = 0x1;
+ 	const int timeout = 10000;
+ 	int i;
+ 
+-	// make sure there isn't already a write in progress
++	/*  make sure there isn't already a write in progress */
+ 	for (i = 0; i < timeout; i++) {
+ 		if ((labpc_eeprom_read_status(dev) & write_in_progress_bit) ==
+ 			0)
+@@ -1899,10 +1899,10 @@ static unsigned int labpc_eeprom_write(struct comedi_device * dev,
+ 		comedi_error(dev, "eeprom write timed out");
+ 		return -ETIME;
+ 	}
+-	// update software copy of eeprom
++	/*  update software copy of eeprom */
+ 	devpriv->eeprom_data[address] = value;
+ 
+-	// enable read/write to eeprom
++	/*  enable read/write to eeprom */
+ 	devpriv->command5_bits &= ~EEPROM_EN_BIT;
+ 	comedi_udelay(1);
+ 	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
+@@ -1910,26 +1910,26 @@ static unsigned int labpc_eeprom_write(struct comedi_device * dev,
+ 	comedi_udelay(1);
+ 	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
+ 
+-	// send write_enable instruction
++	/*  send write_enable instruction */
+ 	labpc_serial_out(dev, write_enable_instruction, write_length);
+ 	devpriv->command5_bits &= ~EEPROM_EN_BIT;
+ 	comedi_udelay(1);
+ 	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
+ 
+-	// send write instruction
++	/*  send write instruction */
+ 	devpriv->command5_bits |= EEPROM_EN_BIT;
+ 	comedi_udelay(1);
+ 	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
+ 	labpc_serial_out(dev, write_instruction, write_length);
+-	// send 8 bit address to write to
++	/*  send 8 bit address to write to */
+ 	labpc_serial_out(dev, address, write_length);
+-	// write value
++	/*  write value */
+ 	labpc_serial_out(dev, value, write_length);
+ 	devpriv->command5_bits &= ~EEPROM_EN_BIT;
+ 	comedi_udelay(1);
+ 	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
+ 
+-	// disable read/write to eeprom
++	/*  disable read/write to eeprom */
+ 	devpriv->command5_bits &= ~EEPROM_EN_BIT & ~EEPROM_WRITE_UNPROTECT_BIT;
+ 	comedi_udelay(1);
+ 	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
+@@ -1941,9 +1941,9 @@ static unsigned int labpc_eeprom_read_status(struct comedi_device * dev)
+ {
+ 	unsigned int value;
+ 	const int read_status_instruction = 0x5;
+-	const int write_length = 8;	// 8 bit write lengths to eeprom
++	const int write_length = 8;	/*  8 bit write lengths to eeprom */
+ 
+-	// enable read/write to eeprom
++	/*  enable read/write to eeprom */
+ 	devpriv->command5_bits &= ~EEPROM_EN_BIT;
+ 	comedi_udelay(1);
+ 	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
+@@ -1951,12 +1951,12 @@ static unsigned int labpc_eeprom_read_status(struct comedi_device * dev)
+ 	comedi_udelay(1);
+ 	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
+ 
+-	// send read status instruction
++	/*  send read status instruction */
+ 	labpc_serial_out(dev, read_status_instruction, write_length);
+-	// read result
++	/*  read result */
+ 	value = labpc_serial_in(dev);
+ 
+-	// disable read/write to eeprom
++	/*  disable read/write to eeprom */
+ 	devpriv->command5_bits &= ~EEPROM_EN_BIT & ~EEPROM_WRITE_UNPROTECT_BIT;
+ 	comedi_udelay(1);
+ 	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
+@@ -1964,7 +1964,7 @@ static unsigned int labpc_eeprom_read_status(struct comedi_device * dev)
+ 	return value;
+ }
+ 
+-// writes to 8 bit calibration dacs
++/* writes to 8 bit calibration dacs */
+ static void write_caldac(struct comedi_device * dev, unsigned int channel,
+ 	unsigned int value)
+ {
+@@ -1972,18 +1972,18 @@ static void write_caldac(struct comedi_device * dev, unsigned int channel,
+ 		return;
+ 	devpriv->caldac[channel] = value;
+ 
+-	// clear caldac load bit and make sure we don't write to eeprom
++	/*  clear caldac load bit and make sure we don't write to eeprom */
+ 	devpriv->command5_bits &=
+ 		~CALDAC_LOAD_BIT & ~EEPROM_EN_BIT & ~EEPROM_WRITE_UNPROTECT_BIT;
+ 	comedi_udelay(1);
+ 	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);
+ 
+-	// write 4 bit channel
++	/*  write 4 bit channel */
+ 	labpc_serial_out(dev, channel, 4);
+-	// write 8 bit caldac value
++	/*  write 8 bit caldac value */
+ 	labpc_serial_out(dev, value, 8);
+ 
+-	// set and clear caldac bit to load caldac value
++	/*  set and clear caldac bit to load caldac value */
+ 	devpriv->command5_bits |= CALDAC_LOAD_BIT;
+ 	comedi_udelay(1);
+ 	devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG);

commit 30c687c1b8f4977ad72c544dfcccb27586d0a72c
+Author: Bill Pemberton 
+Date:   Fri Mar 27 11:31:06 2009 -0400
+
+    Staging: comedi: remove C99 comments in ni_at_a2150.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
+index 5d45bf24a5ef..f956ee1ff72d 100644
+--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
++++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
+@@ -73,10 +73,10 @@ TRIG_WAKE_EOS
+ #include "comedi_fc.h"
+ 
+ #define A2150_SIZE           28
+-#define A2150_DMA_BUFFER_SIZE	0xff00	// size in bytes of dma buffer
++#define A2150_DMA_BUFFER_SIZE	0xff00	/*  size in bytes of dma buffer */
+ 
+-//#define A2150_DEBUG   // enable debugging code
+-#undef A2150_DEBUG		// disable debugging code
++/* #define A2150_DEBUG     enable debugging code */
++#undef A2150_DEBUG		/*  disable debugging code */
+ 
+ /* Registers and bits */
+ #define CONFIG_REG		0x0
+@@ -85,48 +85,48 @@ TRIG_WAKE_EOS
+ #define   CLOCK_SELECT_BITS(x)		(((x) & 0x3) << 3)
+ #define   CLOCK_DIVISOR_BITS(x)		(((x) & 0x3) << 5)
+ #define   CLOCK_MASK		(0xf << 3)
+-#define   ENABLE0_BIT		0x80	// enable (don't internally ground) channels 0 and 1
+-#define   ENABLE1_BIT		0x100	// enable (don't internally ground) channels 2 and 3
+-#define   AC0_BIT		0x200	// ac couple channels 0,1
+-#define   AC1_BIT		0x400	// ac couple channels 2,3
+-#define   APD_BIT		0x800	// analog power down
+-#define   DPD_BIT		0x1000	// digital power down
+-#define TRIGGER_REG		0x2	// trigger config register
++#define   ENABLE0_BIT		0x80	/*  enable (don't internally ground) channels 0 and 1 */
++#define   ENABLE1_BIT		0x100	/*  enable (don't internally ground) channels 2 and 3 */
++#define   AC0_BIT		0x200	/*  ac couple channels 0,1 */
++#define   AC1_BIT		0x400	/*  ac couple channels 2,3 */
++#define   APD_BIT		0x800	/*  analog power down */
++#define   DPD_BIT		0x1000	/*  digital power down */
++#define TRIGGER_REG		0x2	/*  trigger config register */
+ #define   POST_TRIGGER_BITS		0x2
+ #define   DELAY_TRIGGER_BITS		0x3
+-#define   HW_TRIG_EN		0x10	// enable hardware trigger
+-#define FIFO_START_REG		0x6	// software start aquistion trigger
+-#define FIFO_RESET_REG		0x8	// clears fifo + fifo flags
+-#define FIFO_DATA_REG		0xa	// read data
+-#define DMA_TC_CLEAR_REG		0xe	// clear dma terminal count interrupt
+-#define STATUS_REG		0x12	// read only
+-#define   FNE_BIT		0x1	// fifo not empty
+-#define   OVFL_BIT		0x8	// fifo overflow
+-#define   EDAQ_BIT		0x10	// end of aquisition interrupt
+-#define   DCAL_BIT		0x20	// offset calibration in progress
+-#define   INTR_BIT		0x40	// interrupt has occured
+-#define   DMA_TC_BIT		0x80	// dma terminal count interrupt has occured
++#define   HW_TRIG_EN		0x10	/*  enable hardware trigger */
++#define FIFO_START_REG		0x6	/*  software start aquistion trigger */
++#define FIFO_RESET_REG		0x8	/*  clears fifo + fifo flags */
++#define FIFO_DATA_REG		0xa	/*  read data */
++#define DMA_TC_CLEAR_REG		0xe	/*  clear dma terminal count interrupt */
++#define STATUS_REG		0x12	/*  read only */
++#define   FNE_BIT		0x1	/*  fifo not empty */
++#define   OVFL_BIT		0x8	/*  fifo overflow */
++#define   EDAQ_BIT		0x10	/*  end of aquisition interrupt */
++#define   DCAL_BIT		0x20	/*  offset calibration in progress */
++#define   INTR_BIT		0x40	/*  interrupt has occured */
++#define   DMA_TC_BIT		0x80	/*  dma terminal count interrupt has occured */
+ #define   ID_BITS(x)	(((x) >> 8) & 0x3)
+-#define IRQ_DMA_CNTRL_REG		0x12	// write only
+-#define   DMA_CHAN_BITS(x)		((x) & 0x7)	// sets dma channel
+-#define   DMA_EN_BIT		0x8	// enables dma
+-#define   IRQ_LVL_BITS(x)		(((x) & 0xf) << 4)	// sets irq level
+-#define   FIFO_INTR_EN_BIT		0x100	// enable fifo interrupts
+-#define   FIFO_INTR_FHF_BIT		0x200	// interrupt fifo half full
+-#define   DMA_INTR_EN_BIT 		0x800	// enable interrupt on dma terminal count
+-#define   DMA_DEM_EN_BIT	0x1000	// enables demand mode dma
++#define IRQ_DMA_CNTRL_REG		0x12	/*  write only */
++#define   DMA_CHAN_BITS(x)		((x) & 0x7)	/*  sets dma channel */
++#define   DMA_EN_BIT		0x8	/*  enables dma */
++#define   IRQ_LVL_BITS(x)		(((x) & 0xf) << 4)	/*  sets irq level */
++#define   FIFO_INTR_EN_BIT		0x100	/*  enable fifo interrupts */
++#define   FIFO_INTR_FHF_BIT		0x200	/*  interrupt fifo half full */
++#define   DMA_INTR_EN_BIT 		0x800	/*  enable interrupt on dma terminal count */
++#define   DMA_DEM_EN_BIT	0x1000	/*  enables demand mode dma */
+ #define I8253_BASE_REG		0x14
+ #define I8253_MODE_REG		0x17
+-#define   HW_COUNT_DISABLE		0x30	// disable hardware counting of conversions
++#define   HW_COUNT_DISABLE		0x30	/*  disable hardware counting of conversions */
+ 
+ struct a2150_board {
+ 	const char *name;
+-	int clock[4];		// master clock periods, in nanoseconds
+-	int num_clocks;		// number of available master clock speeds
+-	int ai_speed;		// maximum conversion rate in nanoseconds
++	int clock[4];		/*  master clock periods, in nanoseconds */
++	int num_clocks;		/*  number of available master clock speeds */
++	int ai_speed;		/*  maximum conversion rate in nanoseconds */
+ };
+ 
+-//analog input range
++/* analog input range */
+ static const struct comedi_lrange range_a2150 = {
+ 	1,
+ 	{
+@@ -134,7 +134,7 @@ static const struct comedi_lrange range_a2150 = {
+ 		}
+ };
+ 
+-// enum must match board indices
++/* enum must match board indices */
+ enum { a2150_c, a2150_s };
+ static const struct a2150_board a2150_boards[] = {
+ 	{
+@@ -159,11 +159,11 @@ static const struct a2150_board a2150_boards[] = {
+ struct a2150_private {
+ 
+ 	volatile unsigned int count;	/* number of data points left to be taken */
+-	unsigned int dma;	// dma channel
+-	s16 *dma_buffer;	// dma buffer
+-	unsigned int dma_transfer_size;	// size in bytes of dma transfers
+-	int irq_dma_bits;	// irq/dma register bits
+-	int config_bits;	// config register bits
++	unsigned int dma;	/*  dma channel */
++	s16 *dma_buffer;	/*  dma buffer */
++	unsigned int dma_transfer_size;	/*  size in bytes of dma transfers */
++	int irq_dma_bits;	/*  irq/dma register bits */
++	int config_bits;	/*  config register bits */
+ };
+ 
+ 
+@@ -226,7 +226,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d PT_REGS_ARG)
+ 		comedi_error(dev, "premature interrupt");
+ 		return IRQ_HANDLED;
+ 	}
+-	// initialize async here to make sure s is not NULL
++	/*  initialize async here to make sure s is not NULL */
+ 	async = s->async;
+ 	async->events = 0;
+ 	cmd = &async->cmd;
+@@ -258,7 +258,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d PT_REGS_ARG)
+ 	 * count and address get set correctly */
+ 	clear_dma_ff(devpriv->dma);
+ 
+-	// figure out how many points to read
++	/*  figure out how many points to read */
+ 	max_points = devpriv->dma_transfer_size / sample_size;
+ 	/* residue is the number of points left to be done on the dma
+ 	 * transfer.  It should always be zero at this point unless
+@@ -269,7 +269,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d PT_REGS_ARG)
+ 	if (devpriv->count < num_points && cmd->stop_src == TRIG_COUNT)
+ 		num_points = devpriv->count;
+ 
+-	// figure out how many points will be stored next time
++	/*  figure out how many points will be stored next time */
+ 	leftover = 0;
+ 	if (cmd->stop_src == TRIG_NONE) {
+ 		leftover = devpriv->dma_transfer_size / sample_size;
+@@ -288,7 +288,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d PT_REGS_ARG)
+ 	for (i = 0; i < num_points; i++) {
+ 		/* write data point to comedi buffer */
+ 		dpnt = devpriv->dma_buffer[i];
+-		// convert from 2's complement to unsigned coding
++		/*  convert from 2's complement to unsigned coding */
+ 		dpnt ^= 0x8000;
+ 		cfc_write_to_buffer(s, dpnt);
+ 		if (cmd->stop_src == TRIG_COUNT) {
+@@ -299,7 +299,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d PT_REGS_ARG)
+ 			}
+ 		}
+ 	}
+-	// re-enable  dma
++	/*  re-enable  dma */
+ 	if (leftover) {
+ 		set_dma_addr(devpriv->dma, virt_to_bus(devpriv->dma_buffer));
+ 		set_dma_count(devpriv->dma, leftover * sample_size);
+@@ -317,7 +317,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-// probes board type, returns offset
++/* probes board type, returns offset */
+ static int a2150_probe(struct comedi_device * dev)
+ {
+ 	int status = inw(dev->iobase + STATUS_REG);
+@@ -365,7 +365,7 @@ static int a2150_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 
+ 	/* grab our IRQ */
+ 	if (irq) {
+-		// check that irq is supported
++		/*  check that irq is supported */
+ 		if (irq < 3 || irq == 8 || irq == 13 || irq > 15) {
+ 			printk(" invalid irq line %u\n", irq);
+ 			return -EINVAL;
+@@ -378,7 +378,7 @@ static int a2150_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 		devpriv->irq_dma_bits |= IRQ_LVL_BITS(irq);
+ 		dev->irq = irq;
+ 	}
+-	// initialize dma
++	/*  initialize dma */
+ 	if (dma) {
+ 		if (dma == 4 || dma > 7) {
+ 			printk(" invalid dma channel %u\n", dma);
+@@ -424,16 +424,16 @@ static int a2150_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 	 * prevent hardware count from stopping aquisition */
+ 	outw(HW_COUNT_DISABLE, dev->iobase + I8253_MODE_REG);
+ 
+-	// set card's irq and dma levels
++	/*  set card's irq and dma levels */
+ 	outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
+ 
+-	// reset and sync adc clock circuitry
++	/*  reset and sync adc clock circuitry */
+ 	outw_p(DPD_BIT | APD_BIT, dev->iobase + CONFIG_REG);
+ 	outw_p(DPD_BIT, dev->iobase + CONFIG_REG);
+-	// initialize configuration register
++	/*  initialize configuration register */
+ 	devpriv->config_bits = 0;
+ 	outw(devpriv->config_bits, dev->iobase + CONFIG_REG);
+-	// wait until offset calibration is done, then enable analog inputs
++	/*  wait until offset calibration is done, then enable analog inputs */
+ 	for (i = 0; i < timeout; i++) {
+ 		if ((DCAL_BIT & inw(dev->iobase + STATUS_REG)) == 0)
+ 			break;
+@@ -455,7 +455,7 @@ static int a2150_detach(struct comedi_device * dev)
+ 
+ 	/* only free stuff if it has been allocated by _attach */
+ 	if (dev->iobase) {
+-		// put board in power-down mode
++		/*  put board in power-down mode */
+ 		outw(APD_BIT | DPD_BIT, dev->iobase + CONFIG_REG);
+ 		release_region(dev->iobase, A2150_SIZE);
+ 	}
+@@ -474,14 +474,14 @@ static int a2150_detach(struct comedi_device * dev)
+ 
+ static int a2150_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	// disable dma on card
++	/*  disable dma on card */
+ 	devpriv->irq_dma_bits &= ~DMA_INTR_EN_BIT & ~DMA_EN_BIT;
+ 	outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
+ 
+-	// disable computer's dma
++	/*  disable computer's dma */
+ 	disable_dma(devpriv->dma);
+ 
+-	// clear fifo and reset triggering circuitry
++	/*  clear fifo and reset triggering circuitry */
+ 	outw(0, dev->iobase + FIFO_RESET_REG);
+ 
+ 	return 0;
+@@ -582,7 +582,7 @@ static int a2150_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice
+ 	if (err)
+ 		return 4;
+ 
+-	// check channel/gain list against card's limitations
++	/*  check channel/gain list against card's limitations */
+ 	if (cmd->chanlist) {
+ 		startChan = CR_CHAN(cmd->chanlist[0]);
+ 		for (i = 1; i < cmd->chanlist_len; i++) {
+@@ -635,7 +635,7 @@ static int a2150_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 			" dma incompatible with hard real-time interrupt (TRIG_RT), aborting");
+ 		return -1;
+ 	}
+-	// clear fifo and reset triggering circuitry
++	/*  clear fifo and reset triggering circuitry */
+ 	outw(0, dev->iobase + FIFO_RESET_REG);
+ 
+ 	/* setup chanlist */
+@@ -643,7 +643,7 @@ static int a2150_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 			cmd->chanlist_len) < 0)
+ 		return -1;
+ 
+-	// setup ac/dc coupling
++	/*  setup ac/dc coupling */
+ 	if (CR_AREF(cmd->chanlist[0]) == AREF_OTHER)
+ 		devpriv->config_bits |= AC0_BIT;
+ 	else
+@@ -653,23 +653,23 @@ static int a2150_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	else
+ 		devpriv->config_bits &= ~AC1_BIT;
+ 
+-	// setup timing
++	/*  setup timing */
+ 	a2150_get_timing(dev, &cmd->scan_begin_arg, cmd->flags);
+ 
+-	// send timing, channel, config bits
++	/*  send timing, channel, config bits */
+ 	outw(devpriv->config_bits, dev->iobase + CONFIG_REG);
+ 
+-	// initialize number of samples remaining
++	/*  initialize number of samples remaining */
+ 	devpriv->count = cmd->stop_arg * cmd->chanlist_len;
+ 
+-	// enable computer's dma
++	/*  enable computer's dma */
+ 	lock_flags = claim_dma_lock();
+ 	disable_dma(devpriv->dma);
+ 	/* clear flip-flop to make sure 2-byte registers for
+ 	 * count and address get set correctly */
+ 	clear_dma_ff(devpriv->dma);
+ 	set_dma_addr(devpriv->dma, virt_to_bus(devpriv->dma_buffer));
+-	// set size of transfer to fill in 1/3 second
++	/*  set size of transfer to fill in 1/3 second */
+ #define ONE_THIRD_SECOND 333333333
+ 	devpriv->dma_transfer_size =
+ 		sizeof(devpriv->dma_buffer[0]) * cmd->chanlist_len *
+@@ -688,36 +688,36 @@ static int a2150_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	 * one spurious interrupt that has been happening */
+ 	outw(0x00, dev->iobase + DMA_TC_CLEAR_REG);
+ 
+-	// enable dma on card
++	/*  enable dma on card */
+ 	devpriv->irq_dma_bits |= DMA_INTR_EN_BIT | DMA_EN_BIT;
+ 	outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
+ 
+-	// may need to wait 72 sampling periods if timing was changed
++	/*  may need to wait 72 sampling periods if timing was changed */
+ 	i8254_load(dev->iobase + I8253_BASE_REG, 0, 2, 72, 0);
+ 
+-	// setup start triggering
++	/*  setup start triggering */
+ 	trigger_bits = 0;
+-	// decide if we need to wait 72 periods for valid data
++	/*  decide if we need to wait 72 periods for valid data */
+ 	if (cmd->start_src == TRIG_NOW &&
+ 		(old_config_bits & CLOCK_MASK) !=
+ 		(devpriv->config_bits & CLOCK_MASK)) {
+-		// set trigger source to delay trigger
++		/*  set trigger source to delay trigger */
+ 		trigger_bits |= DELAY_TRIGGER_BITS;
+ 	} else {
+-		// otherwise no delay
++		/*  otherwise no delay */
+ 		trigger_bits |= POST_TRIGGER_BITS;
+ 	}
+-	// enable external hardware trigger
++	/*  enable external hardware trigger */
+ 	if (cmd->start_src == TRIG_EXT) {
+ 		trigger_bits |= HW_TRIG_EN;
+ 	} else if (cmd->start_src == TRIG_OTHER) {
+-		// XXX add support for level/slope start trigger using TRIG_OTHER
++		/*  XXX add support for level/slope start trigger using TRIG_OTHER */
+ 		comedi_error(dev, "you shouldn't see this?");
+ 	}
+-	// send trigger config bits
++	/*  send trigger config bits */
+ 	outw(trigger_bits, dev->iobase + TRIGGER_REG);
+ 
+-	// start aquisition for soft trigger
++	/*  start aquisition for soft trigger */
+ 	if (cmd->start_src == TRIG_NOW) {
+ 		outw(0, dev->iobase + FIFO_START_REG);
+ 	}
+@@ -735,28 +735,28 @@ static int a2150_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ 	static const int timeout = 100000;
+ 	static const int filter_delay = 36;
+ 
+-	// clear fifo and reset triggering circuitry
++	/*  clear fifo and reset triggering circuitry */
+ 	outw(0, dev->iobase + FIFO_RESET_REG);
+ 
+ 	/* setup chanlist */
+ 	if (a2150_set_chanlist(dev, CR_CHAN(insn->chanspec), 1) < 0)
+ 		return -1;
+ 
+-	// set dc coupling
++	/*  set dc coupling */
+ 	devpriv->config_bits &= ~AC0_BIT;
+ 	devpriv->config_bits &= ~AC1_BIT;
+ 
+-	// send timing, channel, config bits
++	/*  send timing, channel, config bits */
+ 	outw(devpriv->config_bits, dev->iobase + CONFIG_REG);
+ 
+-	// disable dma on card
++	/*  disable dma on card */
+ 	devpriv->irq_dma_bits &= ~DMA_INTR_EN_BIT & ~DMA_EN_BIT;
+ 	outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
+ 
+-	// setup start triggering
++	/*  setup start triggering */
+ 	outw(0, dev->iobase + TRIGGER_REG);
+ 
+-	// start aquisition for soft trigger
++	/*  start aquisition for soft trigger */
+ 	outw(0, dev->iobase + FIFO_START_REG);
+ 
+ 	/* there is a 35.6 sample delay for data to get through the antialias filter */
+@@ -773,7 +773,7 @@ static int a2150_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ 		inw(dev->iobase + FIFO_DATA_REG);
+ 	}
+ 
+-	// read data
++	/*  read data */
+ 	for (n = 0; n < insn->n; n++) {
+ 		for (i = 0; i < timeout; i++) {
+ 			if (inw(dev->iobase + STATUS_REG) & FNE_BIT)
+@@ -794,7 +794,7 @@ static int a2150_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ 		data[n] ^= 0x8000;
+ 	}
+ 
+-	// clear fifo and reset triggering circuitry
++	/*  clear fifo and reset triggering circuitry */
+ 	outw(0, dev->iobase + FIFO_RESET_REG);
+ 
+ 	return n;
+@@ -809,7 +809,7 @@ static int a2150_get_timing(struct comedi_device * dev, unsigned int *period,
+ 	int lub_divisor_shift, lub_index, glb_divisor_shift, glb_index;
+ 	int i, j;
+ 
+-	// initialize greatest lower and least upper bounds
++	/*  initialize greatest lower and least upper bounds */
+ 	lub_divisor_shift = 3;
+ 	lub_index = 0;
+ 	lub = thisboard->clock[lub_index] * (1 << lub_divisor_shift);
+@@ -817,19 +817,19 @@ static int a2150_get_timing(struct comedi_device * dev, unsigned int *period,
+ 	glb_index = thisboard->num_clocks - 1;
+ 	glb = thisboard->clock[glb_index] * (1 << glb_divisor_shift);
+ 
+-	// make sure period is in available range
++	/*  make sure period is in available range */
+ 	if (*period < glb)
+ 		*period = glb;
+ 	if (*period > lub)
+ 		*period = lub;
+ 
+-	// we can multiply period by 1, 2, 4, or 8, using (1 << i)
++	/*  we can multiply period by 1, 2, 4, or 8, using (1 << i) */
+ 	for (i = 0; i < 4; i++) {
+-		// there are a maximum of 4 master clocks
++		/*  there are a maximum of 4 master clocks */
+ 		for (j = 0; j < thisboard->num_clocks; j++) {
+-			// temp is the period in nanosec we are evaluating
++			/*  temp is the period in nanosec we are evaluating */
+ 			temp = thisboard->clock[j] * (1 << i);
+-			// if it is the best match yet
++			/*  if it is the best match yet */
+ 			if (temp < lub && temp >= *period) {
+ 				lub_divisor_shift = i;
+ 				lub_index = j;
+@@ -846,7 +846,7 @@ static int a2150_get_timing(struct comedi_device * dev, unsigned int *period,
+ 	switch (flags) {
+ 	case TRIG_ROUND_NEAREST:
+ 	default:
+-		// if least upper bound is better approximation
++		/*  if least upper bound is better approximation */
+ 		if (lub - *period < *period - glb) {
+ 			*period = lub;
+ 		} else {
+@@ -861,7 +861,7 @@ static int a2150_get_timing(struct comedi_device * dev, unsigned int *period,
+ 		break;
+ 	}
+ 
+-	// set clock bits for config register appropriately
++	/*  set clock bits for config register appropriately */
+ 	devpriv->config_bits &= ~CLOCK_MASK;
+ 	if (*period == lub) {
+ 		devpriv->config_bits |=

commit 79a31bae80df12e3cd19a831e7eacfbc4dc555a0
+Author: Bill Pemberton 
+Date:   Fri Mar 27 11:31:00 2009 -0400
+
+    Staging: comedi: remove C99 comments in mpc624.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c
+index a151602929d9..c3fb504feb1e 100644
+--- a/drivers/staging/comedi/drivers/mpc624.c
++++ b/drivers/staging/comedi/drivers/mpc624.c
+@@ -61,19 +61,19 @@ Configuration Options:
+ #include 
+ #include 
+ 
+-// Consecutive I/O port addresses
++/* Consecutive I/O port addresses */
+ #define MPC624_SIZE             16
+ 
+-// Offsets of different ports
+-#define MPC624_MASTER_CONTROL	0	// not used
+-#define MPC624_GNMUXCH          1	// Gain, Mux, Channel of ADC
+-#define MPC624_ADC              2	// read/write to/from ADC
+-#define MPC624_EE               3	// read/write to/from serial EEPROM via I2C
+-#define MPC624_LEDS             4	// write to LEDs
+-#define MPC624_DIO              5	// read/write to/from digital I/O ports
+-#define MPC624_IRQ_MASK         6	// IRQ masking enable/disable
++/* Offsets of different ports */
++#define MPC624_MASTER_CONTROL	0	/*  not used */
++#define MPC624_GNMUXCH          1	/*  Gain, Mux, Channel of ADC */
++#define MPC624_ADC              2	/*  read/write to/from ADC */
++#define MPC624_EE               3	/*  read/write to/from serial EEPROM via I2C */
++#define MPC624_LEDS             4	/*  write to LEDs */
++#define MPC624_DIO              5	/*  read/write to/from digital I/O ports */
++#define MPC624_IRQ_MASK         6	/*  IRQ masking enable/disable */
+ 
+-// Register bits' names
++/* Register bits' names */
+ #define MPC624_ADBUSY           (1<<5)
+ #define MPC624_ADSDO            (1<<4)
+ #define MPC624_ADFO             (1<<3)
+@@ -81,19 +81,19 @@ Configuration Options:
+ #define MPC624_ADSCK            (1<<1)
+ #define MPC624_ADSDI            (1<<0)
+ 
+-// SDI Speed/Resolution Programming bits
++/* SDI Speed/Resolution Programming bits */
+ #define MPC624_OSR4             (1<<31)
+ #define MPC624_OSR3             (1<<30)
+ #define MPC624_OSR2             (1<<29)
+ #define MPC624_OSR1             (1<<28)
+ #define MPC624_OSR0             (1<<27)
+ 
+-// 32-bit output value bits' names
++/* 32-bit output value bits' names */
+ #define MPC624_EOC_BIT          (1<<31)
+ #define MPC624_DMY_BIT          (1<<30)
+ #define MPC624_SGN_BIT          (1<<29)
+ 
+-// Convertion speeds
++/* Convertion speeds */
+ /* OSR4 OSR3 OSR2 OSR1 OSR0  Convertion rate  RMS noise  ENOB^
+  *  X    0    0    0    1        3.52kHz        23uV      17
+  *  X    0    0    1    0        1.76kHz       3.5uV      20
+@@ -119,36 +119,36 @@ Configuration Options:
+ #define MPC624_SPEED_27_5_Hz    (MPC624_OSR4 | MPC624_OSR3                                          )
+ #define MPC624_SPEED_13_75_Hz   (MPC624_OSR4 | MPC624_OSR3                             | MPC624_OSR0)
+ #define MPC624_SPEED_6_875_Hz   (MPC624_OSR4 | MPC624_OSR3 | MPC624_OSR2 | MPC624_OSR1 | MPC624_OSR0)
+-//----------------------------------------------------------------------------
++/* ---------------------------------------------------------------------------- */
+ struct skel_private {
+ 
+-	unsigned long int ulConvertionRate;	// set by mpc624_attach() from driver's parameters
++	unsigned long int ulConvertionRate;	/*  set by mpc624_attach() from driver's parameters */
+ };
+ 
+ 
+ #define devpriv ((struct skel_private *)dev->private)
+-//----------------------------------------------------------------------------
++/* ---------------------------------------------------------------------------- */
+ static const struct comedi_lrange range_mpc624_bipolar1 = {
+ 	1,
+ 	{
+-//    BIP_RANGE(1.01) // this is correct,
+-			// but my MPC-624 actually seems to have a range of 2.02
++/* BIP_RANGE(1.01)  this is correct, */
++			/*  but my MPC-624 actually seems to have a range of 2.02 */
+ 			BIP_RANGE(2.02)
+ 		}
+ };
+ static const struct comedi_lrange range_mpc624_bipolar10 = {
+ 	1,
+ 	{
+-//    BIP_RANGE(10.1) // this is correct,
+-			// but my MPC-624 actually seems to have a range of 20.2
++/* BIP_RANGE(10.1)   this is correct, */
++			/*  but my MPC-624 actually seems to have a range of 20.2 */
+ 			BIP_RANGE(20.2)
+ 		}
+ };
+ 
+-//----------------------------------------------------------------------------
++/* ---------------------------------------------------------------------------- */
+ static int mpc624_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int mpc624_detach(struct comedi_device * dev);
+-//----------------------------------------------------------------------------
++/* ---------------------------------------------------------------------------- */
+ static struct comedi_driver driver_mpc624 = {
+       driver_name:"mpc624",
+       module:THIS_MODULE,
+@@ -156,10 +156,10 @@ static struct comedi_driver driver_mpc624 = {
+       detach:mpc624_detach
+ };
+ 
+-//----------------------------------------------------------------------------
++/* ---------------------------------------------------------------------------- */
+ static int mpc624_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data);
+-//----------------------------------------------------------------------------
++/* ---------------------------------------------------------------------------- */
+ static int mpc624_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+@@ -175,7 +175,7 @@ static int mpc624_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	dev->iobase = iobase;
+ 	dev->board_name = "mpc624";
+ 
+-	// Private structure initialization
++	/*  Private structure initialization */
+ 	if (alloc_private(dev, sizeof(struct skel_private)) < 0)
+ 		return -ENOMEM;
+ 
+@@ -226,7 +226,7 @@ static int mpc624_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 		devpriv->ulConvertionRate = MPC624_SPEED_3_52_kHz;
+ 	}
+ 
+-	// Subdevices structures
++	/*  Subdevices structures */
+ 	if (alloc_subdevices(dev, 1) < 0)
+ 		return -ENOMEM;
+ 
+@@ -267,7 +267,7 @@ static int mpc624_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-// Timeout 200ms
++/* Timeout 200ms */
+ #define TIMEOUT 200
+ 
+ static int mpc624_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+@@ -277,16 +277,16 @@ static int mpc624_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ 	unsigned long int data_in, data_out;
+ 	unsigned char ucPort;
+ 
+-	// WARNING: We always write 0 to GNSWA bit, so the channel range is +-/10.1Vdc
++	/*  WARNING: We always write 0 to GNSWA bit, so the channel range is +-/10.1Vdc */
+ 	outb(insn->chanspec, dev->iobase + MPC624_GNMUXCH);
+-//    rt_printk("Channel %d: \n", insn->chanspec);
++/* rt_printk("Channel %d: \n", insn->chanspec); */
+ 	if (!insn->n) {
+ 		rt_printk("MPC624: Warning, no data to aquire\n");
+ 		return 0;
+ 	}
+ 
+ 	for (n = 0; n < insn->n; n++) {
+-		// Trigger the convertion
++		/*  Trigger the convertion */
+ 		outb(MPC624_ADSCK, dev->iobase + MPC624_ADC);
+ 		comedi_udelay(1);
+ 		outb(MPC624_ADCS | MPC624_ADSCK, dev->iobase + MPC624_ADC);
+@@ -294,7 +294,7 @@ static int mpc624_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ 		outb(0, dev->iobase + MPC624_ADC);
+ 		comedi_udelay(1);
+ 
+-		// Wait for the convertion to end
++		/*  Wait for the convertion to end */
+ 		for (i = 0; i < TIMEOUT; i++) {
+ 			ucPort = inb(dev->iobase + MPC624_ADC);
+ 			if (ucPort & MPC624_ADBUSY)
+@@ -307,32 +307,32 @@ static int mpc624_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ 			data[n] = 0;
+ 			return -ETIMEDOUT;
+ 		}
+-		// Start reading data
++		/*  Start reading data */
+ 		data_in = 0;
+ 		data_out = devpriv->ulConvertionRate;
+ 		comedi_udelay(1);
+ 		for (i = 0; i < 32; i++) {
+-			// Set the clock low
++			/*  Set the clock low */
+ 			outb(0, dev->iobase + MPC624_ADC);
+ 			comedi_udelay(1);
+ 
+-			if (data_out & (1 << 31))	// the next bit is a 1
++			if (data_out & (1 << 31))	/*  the next bit is a 1 */
+ 			{
+-				// Set the ADSDI line (send to MPC624)
++				/*  Set the ADSDI line (send to MPC624) */
+ 				outb(MPC624_ADSDI, dev->iobase + MPC624_ADC);
+ 				comedi_udelay(1);
+-				// Set the clock high
++				/*  Set the clock high */
+ 				outb(MPC624_ADSCK | MPC624_ADSDI,
+ 					dev->iobase + MPC624_ADC);
+-			} else	// the next bit is a 0
++			} else	/*  the next bit is a 0 */
+ 			{
+-				// Set the ADSDI line (send to MPC624)
++				/*  Set the ADSDI line (send to MPC624) */
+ 				outb(0, dev->iobase + MPC624_ADC);
+ 				comedi_udelay(1);
+-				// Set the clock high
++				/*  Set the clock high */
+ 				outb(MPC624_ADSCK, dev->iobase + MPC624_ADC);
+ 			}
+-			// Read ADSDO on high clock (receive from MPC624)
++			/*  Read ADSDO on high clock (receive from MPC624) */
+ 			comedi_udelay(1);
+ 			data_in <<= 1;
+ 			data_in |=
+@@ -343,18 +343,18 @@ static int mpc624_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ 			data_out <<= 1;
+ 		}
+ 
+-		// Received 32-bit long value consist of:
+-		//   31: EOC (End Of Transmission) bit - should be 0
+-		//   30: DMY (Dummy) bit               - should be 0
+-		//   29: SIG (Sign) bit                - 1 if the voltage is positive, 0 if negative
+-		//   28: MSB (Most Significant Bit)    - the first bit of convertion result
+-		//   ....
+-		//   05: LSB (Least Significant Bit)   - the last bit of convertion result
+-		//   04: sub-LSB                       - sub-LSBs are basically noise, but when
+-		//   03: sub-LSB                         averaged properly, they can increase convertion
+-		//   02: sub-LSB                         precision up to 29 bits; they can be discarded
+-		//   01: sub-LSB                         without loss of resolution.
+-		//   00: sub-LSB
++		/*  Received 32-bit long value consist of: */
++		/*    31: EOC (End Of Transmission) bit - should be 0 */
++		/*    30: DMY (Dummy) bit               - should be 0 */
++		/*    29: SIG (Sign) bit                - 1 if the voltage is positive, 0 if negative */
++		/*    28: MSB (Most Significant Bit)    - the first bit of convertion result */
++		/*    .... */
++		/*    05: LSB (Least Significant Bit)   - the last bit of convertion result */
++		/*    04: sub-LSB                       - sub-LSBs are basically noise, but when */
++		/*    03: sub-LSB                         averaged properly, they can increase convertion */
++		/*    02: sub-LSB                         precision up to 29 bits; they can be discarded */
++		/*    01: sub-LSB                         without loss of resolution. */
++		/*    00: sub-LSB */
+ 
+ 		if (data_in & MPC624_EOC_BIT)
+ 			rt_printk("MPC624: EOC bit is set (data_in=%lu)!",
+@@ -362,24 +362,24 @@ static int mpc624_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ 		if (data_in & MPC624_DMY_BIT)
+ 			rt_printk("MPC624: DMY bit is set (data_in=%lu)!",
+ 				data_in);
+-		if (data_in & MPC624_SGN_BIT)	// check the sign bit
+-		{		// The voltage is positive
+-			data_in &= 0x3FFFFFFF;	// EOC and DMY should be 0, but we will mask them out just to be sure
+-			data[n] = data_in;	// comedi operates on unsigned numbers, so we don't clear the SGN bit
+-			// SGN bit is still set! It's correct, since we're converting to unsigned.
+-		} else {	// The voltage is negative
+-			// data_in contains a number in 30-bit two's complement code and we must deal with it
++		if (data_in & MPC624_SGN_BIT)	/*  check the sign bit */
++		{		/*  The voltage is positive */
++			data_in &= 0x3FFFFFFF;	/*  EOC and DMY should be 0, but we will mask them out just to be sure */
++			data[n] = data_in;	/*  comedi operates on unsigned numbers, so we don't clear the SGN bit */
++			/*  SGN bit is still set! It's correct, since we're converting to unsigned. */
++		} else {	/*  The voltage is negative */
++			/*  data_in contains a number in 30-bit two's complement code and we must deal with it */
+ 			data_in |= MPC624_SGN_BIT;
+ 			data_in = ~data_in;
+ 			data_in += 1;
+ 			data_in &= ~(MPC624_EOC_BIT | MPC624_DMY_BIT);
+-			// clear EOC and DMY bits
++			/*  clear EOC and DMY bits */
+ 			data_in = 0x20000000 - data_in;
+ 			data[n] = data_in;
+ 		}
+ 	}
+ 
+-	// Return the number of samples read/written
++	/*  Return the number of samples read/written */
+ 	return n;
+ }
+ 

commit c52c19c33617cb76e2cec7d9555c30f2505e69e4
+Author: Bill Pemberton 
+Date:   Fri Mar 27 11:30:55 2009 -0400
+
+    Staging: comedi: remove C99 comments in gsc_hpdi.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
+index 49e5c86c2dd8..69359c00d2ab 100644
+--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
++++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
+@@ -62,8 +62,8 @@ static int hpdi_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static irqreturn_t handle_interrupt(int irq, void *d PT_REGS_ARG);
+ static int dio_config_block_size(struct comedi_device * dev, unsigned int * data);
+ 
+-#undef HPDI_DEBUG		// disable debugging messages
+-//#define HPDI_DEBUG    // enable debugging code
++#undef HPDI_DEBUG		/*  disable debugging messages */
++/* #define HPDI_DEBUG      enable debugging code */
+ 
+ #ifdef HPDI_DEBUG
+ #define DEBUG_PRINT(format, args...)  rt_printk(format , ## args )
+@@ -71,12 +71,12 @@ static int dio_config_block_size(struct comedi_device * dev, unsigned int * data
+ #define DEBUG_PRINT(format, args...)
+ #endif
+ 
+-#define TIMER_BASE 50		// 20MHz master clock
++#define TIMER_BASE 50		/*  20MHz master clock */
+ #define DMA_BUFFER_SIZE 0x10000
+ #define NUM_DMA_BUFFERS 4
+ #define NUM_DMA_DESCRIPTORS 256
+ 
+-// indices of base address regions
++/* indices of base address regions */
+ enum base_address_regions {
+ 	PLX9080_BADDRINDEX = 0,
+ 	HPDI_BADDRINDEX = 2,
+@@ -115,7 +115,7 @@ int command_channel_valid(unsigned int channel)
+ 	return 1;
+ }
+ 
+-// bit definitions
++/* bit definitions */
+ 
+ enum firmware_revision_bits {
+ 	FEATURES_REG_PRESENT_BIT = 0x8000,
+@@ -184,7 +184,7 @@ enum board_status_bits {
+ 
+ uint32_t almost_full_bits(unsigned int num_words)
+ {
+-// XXX need to add or subtract one?
++/* XXX need to add or subtract one? */
+ 	return (num_words << 16) & 0xff0000;
+ }
+ 
+@@ -194,7 +194,7 @@ uint32_t almost_empty_bits(unsigned int num_words)
+ }
+ unsigned int almost_full_num_words(uint32_t bits)
+ {
+-// XXX need to add or subtract one?
++/* XXX need to add or subtract one? */
+ 	return (bits >> 16) & 0xffff;
+ }
+ unsigned int almost_empty_num_words(uint32_t bits)
+@@ -263,8 +263,8 @@ uint32_t intr_active_high_bit(int interrupt_source)
+ struct hpdi_board {
+ 
+ 	char *name;
+-	int device_id;		// pci device id
+-	int subdevice_id;	// pci subdevice id
++	int device_id;		/*  pci device id */
++	int subdevice_id;	/*  pci subdevice id */
+ };
+ 
+ 
+@@ -303,25 +303,25 @@ static inline struct hpdi_board *board(const struct comedi_device * dev)
+ 
+ struct hpdi_private {
+ 
+-	struct pci_dev *hw_dev;	// pointer to board's pci_dev struct
+-	// base addresses (physical)
++	struct pci_dev *hw_dev;	/*  pointer to board's pci_dev struct */
++	/*  base addresses (physical) */
+ 	resource_size_t plx9080_phys_iobase;
+ 	resource_size_t hpdi_phys_iobase;
+-	// base addresses (ioremapped)
++	/*  base addresses (ioremapped) */
+ 	void *plx9080_iobase;
+ 	void *hpdi_iobase;
+-	uint32_t *dio_buffer[NUM_DMA_BUFFERS];	// dma buffers
+-	dma_addr_t dio_buffer_phys_addr[NUM_DMA_BUFFERS];	// physical addresses of dma buffers
+-	struct plx_dma_desc *dma_desc;	// array of dma descriptors read by plx9080, allocated to get proper alignment
+-	dma_addr_t dma_desc_phys_addr;	// physical address of dma descriptor array
++	uint32_t *dio_buffer[NUM_DMA_BUFFERS];	/*  dma buffers */
++	dma_addr_t dio_buffer_phys_addr[NUM_DMA_BUFFERS];	/*  physical addresses of dma buffers */
++	struct plx_dma_desc *dma_desc;	/*  array of dma descriptors read by plx9080, allocated to get proper alignment */
++	dma_addr_t dma_desc_phys_addr;	/*  physical address of dma descriptor array */
+ 	unsigned int num_dma_descriptors;
+-	uint32_t *desc_dio_buffer[NUM_DMA_DESCRIPTORS];	// pointer to start of buffers indexed by descriptor
+-	volatile unsigned int dma_desc_index;	// index of the dma descriptor that is currently being used
++	uint32_t *desc_dio_buffer[NUM_DMA_DESCRIPTORS];	/*  pointer to start of buffers indexed by descriptor */
++	volatile unsigned int dma_desc_index;	/*  index of the dma descriptor that is currently being used */
+ 	unsigned int tx_fifo_size;
+ 	unsigned int rx_fifo_size;
+ 	volatile unsigned long dio_count;
+-	volatile uint32_t bits[24];	// software copies of values written to hpdi registers
+-	volatile unsigned int block_size;	// number of bytes at which to generate COMEDI_CB_BLOCK events
++	volatile uint32_t bits[24];	/*  software copies of values written to hpdi registers */
++	volatile unsigned int block_size;	/*  number of bytes at which to generate COMEDI_CB_BLOCK events */
+ 	unsigned dio_config_output:1;
+ };
+ 
+@@ -373,13 +373,13 @@ static void disable_plx_interrupts(struct comedi_device * dev)
+ 	writel(0, priv(dev)->plx9080_iobase + PLX_INTRCS_REG);
+ }
+ 
+-// initialize plx9080 chip
++/* initialize plx9080 chip */
+ static void init_plx9080(struct comedi_device * dev)
+ {
+ 	uint32_t bits;
+ 	void *plx_iobase = priv(dev)->plx9080_iobase;
+ 
+-	// plx9080 dump
++	/*  plx9080 dump */
+ 	DEBUG_PRINT(" plx interrupt status 0x%x\n",
+ 		readl(plx_iobase + PLX_INTRCS_REG));
+ 	DEBUG_PRINT(" plx id bits 0x%x\n", readl(plx_iobase + PLX_ID_REG));
+@@ -417,21 +417,21 @@ static void init_plx9080(struct comedi_device * dev)
+ 	abort_dma(dev, 0);
+ 	abort_dma(dev, 1);
+ 
+-	// configure dma0 mode
++	/*  configure dma0 mode */
+ 	bits = 0;
+-	// enable ready input
++	/*  enable ready input */
+ 	bits |= PLX_DMA_EN_READYIN_BIT;
+-	// enable dma chaining
++	/*  enable dma chaining */
+ 	bits |= PLX_EN_CHAIN_BIT;
+-	// enable interrupt on dma done (probably don't need this, since chain never finishes)
++	/*  enable interrupt on dma done (probably don't need this, since chain never finishes) */
+ 	bits |= PLX_EN_DMA_DONE_INTR_BIT;
+-	// don't increment local address during transfers (we are transferring from a fixed fifo register)
++	/*  don't increment local address during transfers (we are transferring from a fixed fifo register) */
+ 	bits |= PLX_LOCAL_ADDR_CONST_BIT;
+-	// route dma interrupt to pci bus
++	/*  route dma interrupt to pci bus */
+ 	bits |= PLX_DMA_INTR_PCI_BIT;
+-	// enable demand mode
++	/*  enable demand mode */
+ 	bits |= PLX_DEMAND_MODE_BIT;
+-	// enable local burst mode
++	/*  enable local burst mode */
+ 	bits |= PLX_DMA_LOCAL_BURST_EN_BIT;
+ 	bits |= PLX_LOCAL_BUS_32_WIDE_BITS;
+ 	writel(bits, plx_iobase + PLX_DMA0_MODE_REG);
+@@ -484,7 +484,7 @@ static int init_hpdi(struct comedi_device * dev)
+ 
+ 	writel(0, priv(dev)->hpdi_iobase + INTERRUPT_CONTROL_REG);
+ 
+-	// enable interrupts
++	/*  enable interrupts */
+ 	plx_intcsr_bits =
+ 		ICS_AERR | ICS_PERR | ICS_PIE | ICS_PLIE | ICS_PAIE | ICS_LIE |
+ 		ICS_DMA0_E;
+@@ -493,7 +493,7 @@ static int init_hpdi(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-// setup dma descriptors so a link completes every 'transfer_size' bytes
++/* setup dma descriptors so a link completes every 'transfer_size' bytes */
+ static int setup_dma_descriptors(struct comedi_device * dev,
+ 	unsigned int transfer_size)
+ {
+@@ -545,7 +545,7 @@ static int setup_dma_descriptors(struct comedi_device * dev,
+ 			(unsigned long)priv(dev)->dma_desc[i].next);
+ 	}
+ 	priv(dev)->num_dma_descriptors = i;
+-	// fix last descriptor to point back to first
++	/*  fix last descriptor to point back to first */
+ 	priv(dev)->dma_desc[i - 1].next =
+ 		cpu_to_le32(priv(dev)->dma_desc_phys_addr | next_bits);
+ 	DEBUG_PRINT(" desc %i next fixup 0x%lx\n", i - 1,
+@@ -573,9 +573,9 @@ static int hpdi_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ 			pcidev = pci_get_subsys(PCI_VENDOR_ID_PLX,
+ 				hpdi_boards[i].device_id, PCI_VENDOR_ID_PLX,
+ 				hpdi_boards[i].subdevice_id, pcidev);
+-			// was a particular bus/slot requested?
++			/*  was a particular bus/slot requested? */
+ 			if (it->options[0] || it->options[1]) {
+-				// are we on the wrong bus/slot?
++				/*  are we on the wrong bus/slot? */
+ 				if (pcidev->bus->number != it->options[0] ||
+ 					PCI_SLOT(pcidev->devfn) !=
+ 					it->options[1])
+@@ -603,7 +603,7 @@ static int hpdi_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ 	}
+ 	pci_set_master(pcidev);
+ 
+-	//Initialize dev->board_name
++	/* Initialize dev->board_name */
+ 	dev->board_name = board(dev)->name;
+ 
+ 	priv(dev)->plx9080_phys_iobase =
+@@ -611,7 +611,7 @@ static int hpdi_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ 	priv(dev)->hpdi_phys_iobase =
+ 		pci_resource_start(pcidev, HPDI_BADDRINDEX);
+ 
+-	// remap, won't work with 2.0 kernels but who cares
++	/*  remap, won't work with 2.0 kernels but who cares */
+ 	priv(dev)->plx9080_iobase = ioremap(priv(dev)->plx9080_phys_iobase,
+ 		pci_resource_len(pcidev, PLX9080_BADDRINDEX));
+ 	priv(dev)->hpdi_iobase = ioremap(priv(dev)->hpdi_phys_iobase,
+@@ -626,7 +626,7 @@ static int hpdi_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ 
+ 	init_plx9080(dev);
+ 
+-	// get irq
++	/*  get irq */
+ 	if (comedi_request_irq(pcidev->irq, handle_interrupt, IRQF_SHARED,
+ 			driver_hpdi.driver_name, dev)) {
+ 		printk(" unable to allocate irq %u\n", pcidev->irq);
+@@ -636,7 +636,7 @@ static int hpdi_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ 
+ 	printk(" irq %u\n", dev->irq);
+ 
+-	// alocate pci dma buffers
++	/*  alocate pci dma buffers */
+ 	for (i = 0; i < NUM_DMA_BUFFERS; i++) {
+ 		priv(dev)->dio_buffer[i] =
+ 			pci_alloc_consistent(priv(dev)->hw_dev, DMA_BUFFER_SIZE,
+@@ -645,7 +645,7 @@ static int hpdi_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ 			priv(dev)->dio_buffer[i],
+ 			(unsigned long)priv(dev)->dio_buffer_phys_addr[i]);
+ 	}
+-	// allocate dma descriptors
++	/*  allocate dma descriptors */
+ 	priv(dev)->dma_desc = pci_alloc_consistent(priv(dev)->hw_dev,
+ 		sizeof(struct plx_dma_desc) * NUM_DMA_DESCRIPTORS,
+ 		&priv(dev)->dma_desc_phys_addr);
+@@ -681,7 +681,7 @@ static int hpdi_detach(struct comedi_device * dev)
+ 			}
+ 			if (priv(dev)->hpdi_iobase)
+ 				iounmap((void *)priv(dev)->hpdi_iobase);
+-			// free pci dma buffers
++			/*  free pci dma buffers */
+ 			for (i = 0; i < NUM_DMA_BUFFERS; i++) {
+ 				if (priv(dev)->dio_buffer[i])
+ 					pci_free_consistent(priv(dev)->hw_dev,
+@@ -690,7 +690,7 @@ static int hpdi_detach(struct comedi_device * dev)
+ 						priv(dev)->
+ 						dio_buffer_phys_addr[i]);
+ 			}
+-			// free dma descriptors
++			/*  free dma descriptors */
+ 			if (priv(dev)->dma_desc)
+ 				pci_free_consistent(priv(dev)->hw_dev,
+ 					sizeof(struct plx_dma_desc) *
+@@ -761,7 +761,7 @@ static int di_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+ 
+ 	/* step 2: make sure trigger sources are unique and mutually compatible */
+ 
+-	// uniqueness check
++	/*  uniqueness check */
+ 	if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
+ 		err++;
+ 
+@@ -807,7 +807,7 @@ static int di_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	if (cmd->chanlist) {
+ 		for (i = 1; i < cmd->chanlist_len; i++) {
+ 			if (CR_CHAN(cmd->chanlist[i]) != i) {
+-				// XXX could support 8 channels or 16 channels
++				/*  XXX could support 8 channels or 16 channels */
+ 				comedi_error(dev,
+ 					"chanlist must be channels 0 to 31 in order");
+ 				err++;
+@@ -860,15 +860,15 @@ static int di_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	writel(0, priv(dev)->plx9080_iobase + PLX_DMA0_TRANSFER_SIZE_REG);
+ 	writel(0, priv(dev)->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG);
+ 	writel(0, priv(dev)->plx9080_iobase + PLX_DMA0_LOCAL_ADDRESS_REG);
+-	// give location of first dma descriptor
++	/*  give location of first dma descriptor */
+ 	bits = priv(dev)->
+ 		dma_desc_phys_addr | PLX_DESC_IN_PCI_BIT | PLX_INTR_TERM_COUNT |
+ 		PLX_XFER_LOCAL_TO_PCI;
+ 	writel(bits, priv(dev)->plx9080_iobase + PLX_DMA0_DESCRIPTOR_REG);
+ 
+-	// spinlock for plx dma control/status reg
++	/*  spinlock for plx dma control/status reg */
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+-	// enable dma transfer
++	/*  enable dma transfer */
+ 	writeb(PLX_DMA_EN_BIT | PLX_DMA_START_BIT | PLX_CLEAR_DMA_INTR_BIT,
+ 		priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG);
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+@@ -878,10 +878,10 @@ static int di_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	else
+ 		priv(dev)->dio_count = 1;
+ 
+-	// clear over/under run status flags
++	/*  clear over/under run status flags */
+ 	writel(RX_UNDERRUN_BIT | RX_OVERRUN_BIT,
+ 		priv(dev)->hpdi_iobase + BOARD_STATUS_REG);
+-	// enable interrupts
++	/*  enable interrupts */
+ 	writel(intr_bit(RX_FULL_INTR),
+ 		priv(dev)->hpdi_iobase + INTERRUPT_CONTROL_REG);
+ 
+@@ -914,7 +914,7 @@ static void drain_dma_buffers(struct comedi_device * dev, unsigned int channel)
+ 		pci_addr_reg =
+ 			priv(dev)->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG;
+ 
+-	// loop until we have read all the full buffers
++	/*  loop until we have read all the full buffers */
+ 	j = 0;
+ 	for (next_transfer_addr = readl(pci_addr_reg);
+ 		(next_transfer_addr <
+@@ -925,7 +925,7 @@ static void drain_dma_buffers(struct comedi_device * dev, unsigned int channel)
+ 					dma_desc_index].pci_start_addr) +
+ 			priv(dev)->block_size)
+ 		&& j < priv(dev)->num_dma_descriptors; j++) {
+-		// transfer data from dma buffer to comedi buffer
++		/*  transfer data from dma buffer to comedi buffer */
+ 		num_samples = priv(dev)->block_size / sizeof(uint32_t);
+ 		if (async->cmd.stop_src == TRIG_COUNT) {
+ 			if (num_samples > priv(dev)->dio_count)
+@@ -942,7 +942,7 @@ static void drain_dma_buffers(struct comedi_device * dev, unsigned int channel)
+ 			priv(dev)->dma_desc[priv(dev)->dma_desc_index].next);
+ 		DEBUG_PRINT("pci addr reg 0x%x\n", next_transfer_addr);
+ 	}
+-	// XXX check for buffer overrun somehow
++	/*  XXX check for buffer overrun somehow */
+ }
+ 
+ static irqreturn_t handle_interrupt(int irq, void *d PT_REGS_ARG)
+@@ -975,10 +975,10 @@ static irqreturn_t handle_interrupt(int irq, void *d PT_REGS_ARG)
+ 		writel(hpdi_intr_status,
+ 			priv(dev)->hpdi_iobase + INTERRUPT_STATUS_REG);
+ 	}
+-	// spin lock makes sure noone else changes plx dma control reg
++	/*  spin lock makes sure noone else changes plx dma control reg */
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 	dma0_status = readb(priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG);
+-	if (plx_status & ICS_DMA0_A) {	// dma chan 0 interrupt
++	if (plx_status & ICS_DMA0_A) {	/*  dma chan 0 interrupt */
+ 		writeb((dma0_status & PLX_DMA_EN_BIT) | PLX_CLEAR_DMA_INTR_BIT,
+ 			priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG);
+ 
+@@ -990,11 +990,11 @@ static irqreturn_t handle_interrupt(int irq, void *d PT_REGS_ARG)
+ 	}
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ 
+-	// spin lock makes sure noone else changes plx dma control reg
++	/*  spin lock makes sure noone else changes plx dma control reg */
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 	dma1_status = readb(priv(dev)->plx9080_iobase + PLX_DMA1_CS_REG);
+-	if (plx_status & ICS_DMA1_A)	// XXX
+-	{			// dma chan 1 interrupt
++	if (plx_status & ICS_DMA1_A)	/*  XXX */
++	{			/*  dma chan 1 interrupt */
+ 		writeb((dma1_status & PLX_DMA_EN_BIT) | PLX_CLEAR_DMA_INTR_BIT,
+ 			priv(dev)->plx9080_iobase + PLX_DMA1_CS_REG);
+ 		DEBUG_PRINT("dma1 status 0x%x\n", dma1_status);
+@@ -1003,8 +1003,8 @@ static irqreturn_t handle_interrupt(int irq, void *d PT_REGS_ARG)
+ 	}
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ 
+-	// clear possible plx9080 interrupt sources
+-	if (plx_status & ICS_LDIA) {	// clear local doorbell interrupt
++	/*  clear possible plx9080 interrupt sources */
++	if (plx_status & ICS_LDIA) {	/*  clear local doorbell interrupt */
+ 		plx_bits = readl(priv(dev)->plx9080_iobase + PLX_DBR_OUT_REG);
+ 		writel(plx_bits, priv(dev)->plx9080_iobase + PLX_DBR_OUT_REG);
+ 		DEBUG_PRINT(" cleared local doorbell bits 0x%x\n", plx_bits);
+@@ -1040,7 +1040,7 @@ void abort_dma(struct comedi_device * dev, unsigned int channel)
+ {
+ 	unsigned long flags;
+ 
+-	// spinlock for plx dma control/status reg
++	/*  spinlock for plx dma control/status reg */
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 
+ 	plx9080_abort_dma(priv(dev)->plx9080_iobase, channel);

commit 6eef3af5ddb1fa9c05c2f6457c23c4cfe9d83470
+Author: Bill Pemberton 
+Date:   Fri Mar 27 11:30:50 2009 -0400
+
+    Staging: comedi: remove C99 comments in cb_pcimdas.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
+index af705fa092c0..49d32fb4a4b4 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
+@@ -48,24 +48,24 @@ See http://www.measurementcomputing.com/PDFManuals/pcim-das1602_16.pdf for more
+ #include "plx9052.h"
+ #include "8255.h"
+ 
+-//#define CBPCIMDAS_DEBUG
++/* #define CBPCIMDAS_DEBUG */
+ #undef CBPCIMDAS_DEBUG
+ 
+ /* Registers for the PCIM-DAS1602/16 */
+ 
+-// sizes of io regions (bytes)
+-#define BADR0_SIZE 2		//??
++/* sizes of io regions (bytes) */
++#define BADR0_SIZE 2		/* ?? */
+ #define BADR1_SIZE 4
+ #define BADR2_SIZE 6
+ #define BADR3_SIZE 16
+ #define BADR4_SIZE 4
+ 
+-//DAC Offsets
++/* DAC Offsets */
+ #define ADC_TRIG 0
+ #define DAC0_OFFSET 2
+ #define DAC1_OFFSET 4
+ 
+-//AI and Counter Constants
++/* AI and Counter Constants */
+ #define MUX_LIMITS 0
+ #define MAIN_CONN_DIO 1
+ #define ADC_STAT 2
+@@ -86,17 +86,17 @@ See http://www.measurementcomputing.com/PDFManuals/pcim-das1602_16.pdf for more
+ struct cb_pcimdas_board {
+ 	const char *name;
+ 	unsigned short device_id;
+-	int ai_se_chans;	// Inputs in single-ended mode
+-	int ai_diff_chans;	// Inputs in differential mode
+-	int ai_bits;		// analog input resolution
+-	int ai_speed;		// fastest conversion period in ns
+-	int ao_nchan;		// number of analog out channels
+-	int ao_bits;		// analogue output resolution
+-	int has_ao_fifo;	// analog output has fifo
+-	int ao_scan_speed;	// analog output speed for 1602 series (for a scan, not conversion)
+-	int fifo_size;		// number of samples fifo can hold
+-	int dio_bits;		// number of dio bits
+-	int has_dio;		// has DIO
++	int ai_se_chans;	/*  Inputs in single-ended mode */
++	int ai_diff_chans;	/*  Inputs in differential mode */
++	int ai_bits;		/*  analog input resolution */
++	int ai_speed;		/*  fastest conversion period in ns */
++	int ao_nchan;		/*  number of analog out channels */
++	int ao_bits;		/*  analogue output resolution */
++	int has_ao_fifo;	/*  analog output has fifo */
++	int ao_scan_speed;	/*  analog output speed for 1602 series (for a scan, not conversion) */
++	int fifo_size;		/*  number of samples fifo can hold */
++	int dio_bits;		/*  number of dio bits */
++	int has_dio;		/*  has DIO */
+ 	const struct comedi_lrange *ranges;
+ };
+ 
+@@ -107,16 +107,16 @@ static const struct cb_pcimdas_board cb_pcimdas_boards[] = {
+ 	      ai_se_chans:16,
+ 	      ai_diff_chans:8,
+ 	      ai_bits:	16,
+-	      ai_speed:10000,	//??
++	      ai_speed:10000,	/* ?? */
+ 	      ao_nchan:2,
+ 	      ao_bits:	12,
+-	      has_ao_fifo:0,	//??
++	      has_ao_fifo:0,	/* ?? */
+ 	      ao_scan_speed:10000,
+-			//??
++			/* ?? */
+ 	      fifo_size:1024,
+ 	      dio_bits:24,
+ 	      has_dio:	1,
+-//              ranges:         &cb_pcimdas_ranges,
++/* ranges:         &cb_pcimdas_ranges, */
+ 		},
+ };
+ 
+@@ -129,7 +129,7 @@ static DEFINE_PCI_DEVICE_TABLE(cb_pcimdas_pci_table) = {
+ 
+ MODULE_DEVICE_TABLE(pci, cb_pcimdas_pci_table);
+ 
+-#define N_BOARDS 1		// Max number of boards supported
++#define N_BOARDS 1		/*  Max number of boards supported */
+ 
+ /*
+  * Useful for shorthand access to the particular board structure
+@@ -142,10 +142,10 @@ MODULE_DEVICE_TABLE(pci, cb_pcimdas_pci_table);
+ struct cb_pcimdas_private {
+ 	int data;
+ 
+-	// would be useful for a PCI device
++	/*  would be useful for a PCI device */
+ 	struct pci_dev *pci_dev;
+ 
+-	//base addresses
++	/* base addresses */
+ 	unsigned long BADR0;
+ 	unsigned long BADR1;
+ 	unsigned long BADR2;
+@@ -155,11 +155,11 @@ struct cb_pcimdas_private {
+ 	/* Used for AO readback */
+ 	unsigned int ao_readback[2];
+ 
+-	// Used for DIO
+-	unsigned short int port_a;	// copy of BADR4+0
+-	unsigned short int port_b;	// copy of BADR4+1
+-	unsigned short int port_c;	// copy of BADR4+2
+-	unsigned short int dio_mode;	// copy of BADR4+3
++	/*  Used for DIO */
++	unsigned short int port_a;	/*  copy of BADR4+0 */
++	unsigned short int port_b;	/*  copy of BADR4+1 */
++	unsigned short int port_c;	/*  copy of BADR4+2 */
++	unsigned short int dio_mode;	/*  copy of BADR4+3 */
+ 
+ };
+ 
+@@ -202,7 +202,7 @@ static int cb_pcimdas_attach(struct comedi_device * dev, struct comedi_devconfig
+ 	struct comedi_subdevice *s;
+ 	struct pci_dev *pcidev;
+ 	int index;
+-	//int i;
++	/* int i; */
+ 
+ 	printk("comedi%d: cb_pcimdas: ", dev->minor);
+ 
+@@ -220,17 +220,17 @@ static int cb_pcimdas_attach(struct comedi_device * dev, struct comedi_devconfig
+ 	for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
+ 		pcidev != NULL;
+ 		pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
+-		// is it not a computer boards card?
++		/*  is it not a computer boards card? */
+ 		if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS)
+ 			continue;
+-		// loop through cards supported by this driver
++		/*  loop through cards supported by this driver */
+ 		for (index = 0; index < N_BOARDS; index++) {
+ 			if (cb_pcimdas_boards[index].device_id !=
+ 				pcidev->device)
+ 				continue;
+-			// was a particular bus/slot requested?
++			/*  was a particular bus/slot requested? */
+ 			if (it->options[0] || it->options[1]) {
+-				// are we on the wrong bus/slot?
++				/*  are we on the wrong bus/slot? */
+ 				if (pcidev->bus->number != it->options[0] ||
+ 					PCI_SLOT(pcidev->devfn) !=
+ 					it->options[1]) {
+@@ -252,7 +252,7 @@ static int cb_pcimdas_attach(struct comedi_device * dev, struct comedi_devconfig
+ 	printk("Found %s on bus %i, slot %i\n", cb_pcimdas_boards[index].name,
+ 		pcidev->bus->number, PCI_SLOT(pcidev->devfn));
+ 
+-	// Warn about non-tested features
++	/*  Warn about non-tested features */
+ 	switch (thisboard->device_id) {
+ 	case 0x56:
+ 		break;
+@@ -280,16 +280,16 @@ static int cb_pcimdas_attach(struct comedi_device * dev, struct comedi_devconfig
+ 	printk("devpriv->BADR4 = 0x%lx\n", devpriv->BADR4);
+ #endif
+ 
+-// Dont support IRQ yet
+-//      // get irq
+-//      if(comedi_request_irq(devpriv->pci_dev->irq, cb_pcimdas_interrupt, IRQF_SHARED, "cb_pcimdas", dev ))
+-//      {
+-//              printk(" unable to allocate irq %u\n", devpriv->pci_dev->irq);
+-//              return -EINVAL;
+-//      }
+-//      dev->irq = devpriv->pci_dev->irq;
++/* Dont support IRQ yet */
++/*  get irq */
++/* if(comedi_request_irq(devpriv->pci_dev->irq, cb_pcimdas_interrupt, IRQF_SHARED, "cb_pcimdas", dev )) */
++/* { */
++/* printk(" unable to allocate irq %u\n", devpriv->pci_dev->irq); */
++/* return -EINVAL; */
++/* } */
++/* dev->irq = devpriv->pci_dev->irq; */
+ 
+-	//Initialize dev->board_name
++	/* Initialize dev->board_name */
+ 	dev->board_name = thisboard->name;
+ 
+ /*
+@@ -300,24 +300,24 @@ static int cb_pcimdas_attach(struct comedi_device * dev, struct comedi_devconfig
+ 		return -ENOMEM;
+ 
+ 	s = dev->subdevices + 0;
+-	//dev->read_subdev=s;
+-	// analog input subdevice
++	/* dev->read_subdev=s; */
++	/*  analog input subdevice */
+ 	s->type = COMEDI_SUBD_AI;
+ 	s->subdev_flags = SDF_READABLE | SDF_GROUND;
+ 	s->n_chan = thisboard->ai_se_chans;
+ 	s->maxdata = (1 << thisboard->ai_bits) - 1;
+ 	s->range_table = &range_unknown;
+-	s->len_chanlist = 1;	// This is the maximum chanlist length that
+-	// the board can handle
++	s->len_chanlist = 1;	/*  This is the maximum chanlist length that */
++	/*  the board can handle */
+ 	s->insn_read = cb_pcimdas_ai_rinsn;
+ 
+ 	s = dev->subdevices + 1;
+-	// analog output subdevice
++	/*  analog output subdevice */
+ 	s->type = COMEDI_SUBD_AO;
+ 	s->subdev_flags = SDF_WRITABLE;
+ 	s->n_chan = thisboard->ao_nchan;
+ 	s->maxdata = 1 << thisboard->ao_bits;
+-	s->range_table = &range_unknown;	//ranges are hardware settable, but not software readable.
++	s->range_table = &range_unknown;	/* ranges are hardware settable, but not software readable. */
+ 	s->insn_write = &cb_pcimdas_ao_winsn;
+ 	s->insn_read = &cb_pcimdas_ao_rinsn;
+ 
+@@ -382,27 +382,27 @@ static int cb_pcimdas_ai_rinsn(struct comedi_device * dev, struct comedi_subdevi
+ 	unsigned short chanlims;
+ 	int maxchans;
+ 
+-	// only support sw initiated reads from a single channel
++	/*  only support sw initiated reads from a single channel */
+ 
+-	//check channel number
+-	if ((inb(devpriv->BADR3 + 2) & 0x20) == 0)	//differential mode
++	/* check channel number */
++	if ((inb(devpriv->BADR3 + 2) & 0x20) == 0)	/* differential mode */
+ 		maxchans = thisboard->ai_diff_chans;
+ 	else
+ 		maxchans = thisboard->ai_se_chans;
+ 
+ 	if (chan > (maxchans - 1))
+-		return -ETIMEDOUT;	//*** Wrong error code. Fixme.
++		return -ETIMEDOUT;	/* *** Wrong error code. Fixme. */
+ 
+-	//configure for sw initiated read
++	/* configure for sw initiated read */
+ 	d = inb(devpriv->BADR3 + 5);
+-	if ((d & 0x03) > 0) {	//only reset if needed.
++	if ((d & 0x03) > 0) {	/* only reset if needed. */
+ 		d = d & 0xfd;
+ 		outb(d, devpriv->BADR3 + 5);
+ 	}
+-	outb(0x01, devpriv->BADR3 + 6);	//set bursting off, conversions on
+-	outb(0x00, devpriv->BADR3 + 7);	//set range to 10V. UP/BP is controlled by a switch on the board
++	outb(0x01, devpriv->BADR3 + 6);	/* set bursting off, conversions on */
++	outb(0x00, devpriv->BADR3 + 7);	/* set range to 10V. UP/BP is controlled by a switch on the board */
+ 
+-	// write channel limits to multiplexer, set Low (bits 0-3) and High (bits 4-7) channels to chan.
++	/*  write channel limits to multiplexer, set Low (bits 0-3) and High (bits 4-7) channels to chan. */
+ 	chanlims = chan | (chan << 4);
+ 	outb(chanlims, devpriv->BADR3 + 0);
+ 
+@@ -411,8 +411,8 @@ static int cb_pcimdas_ai_rinsn(struct comedi_device * dev, struct comedi_subdevi
+ 		/* trigger conversion */
+ 		outw(0, devpriv->BADR2 + 0);
+ 
+-#define TIMEOUT 1000		//typically takes 5 loops on a lightly loaded Pentium 100MHz,
+-		//this is likely to be 100 loops on a 2GHz machine, so set 1000 as the limit.
++#define TIMEOUT 1000		/* typically takes 5 loops on a lightly loaded Pentium 100MHz, */
++		/* this is likely to be 100 loops on a 2GHz machine, so set 1000 as the limit. */
+ 
+ 		/* wait for conversion to end */
+ 		for (i = 0; i < TIMEOUT; i++) {
+@@ -428,7 +428,7 @@ static int cb_pcimdas_ai_rinsn(struct comedi_device * dev, struct comedi_subdevi
+ 		d = inw(devpriv->BADR2 + 0);
+ 
+ 		/* mangle the data as necessary */
+-		//d ^= 1<<(thisboard->ai_bits-1); // 16 bit data from ADC, so no mangle needed.
++		/* d ^= 1<<(thisboard->ai_bits-1); // 16 bit data from ADC, so no mangle needed. */
+ 
+ 		data[n] = d;
+ 	}

commit cf530aa4385c97f668d76c8268d509ef9edebb70
+Author: Bill Pemberton 
+Date:   Fri Mar 27 11:30:44 2009 -0400
+
+    Staging: comedi: remove C99 comments in cb_pcidas.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
+index fcc551651367..93dac5110149 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas.c
+@@ -70,14 +70,14 @@ analog triggering on 1602 series
+ #include "comedi_pci.h"
+ #include "comedi_fc.h"
+ 
+-#undef CB_PCIDAS_DEBUG		// disable debugging code
+-//#define CB_PCIDAS_DEBUG       // enable debugging code
++#undef CB_PCIDAS_DEBUG		/*  disable debugging code */
++/* #define CB_PCIDAS_DEBUG         enable debugging code */
+ 
+-// PCI vendor number of ComputerBoards/MeasurementComputing
++/* PCI vendor number of ComputerBoards/MeasurementComputing */
+ #define PCI_VENDOR_ID_CB	0x1307
+-#define TIMER_BASE 100		// 10MHz master clock
+-#define AI_BUFFER_SIZE 1024	// maximum fifo size of any supported board
+-#define AO_BUFFER_SIZE 1024	// maximum fifo size of any supported board
++#define TIMER_BASE 100		/*  10MHz master clock */
++#define AI_BUFFER_SIZE 1024	/*  maximum fifo size of any supported board */
++#define AO_BUFFER_SIZE 1024	/*  maximum fifo size of any supported board */
+ #define NUM_CHANNELS_8800 8
+ #define NUM_CHANNELS_7376 1
+ #define NUM_CHANNELS_8402 2
+@@ -85,71 +85,71 @@ analog triggering on 1602 series
+ 
+ /* PCI-DAS base addresses */
+ 
+-// indices of base address regions
++/* indices of base address regions */
+ #define S5933_BADRINDEX 0
+ #define CONT_STAT_BADRINDEX 1
+ #define ADC_FIFO_BADRINDEX 2
+ #define PACER_BADRINDEX 3
+ #define AO_BADRINDEX 4
+-// sizes of io regions
++/* sizes of io regions */
+ #define CONT_STAT_SIZE 10
+ #define ADC_FIFO_SIZE 4
+ #define PACER_SIZE 12
+ #define AO_SIZE 4
+ 
+ /* Control/Status registers */
+-#define INT_ADCFIFO	0	// INTERRUPT / ADC FIFO register
+-#define   INT_EOS 0x1		// interrupt end of scan
+-#define   INT_FHF 0x2		// interrupt fifo half full
+-#define   INT_FNE 0x3		// interrupt fifo not empty
+-#define   INT_MASK 0x3		// mask of interrupt select bits
+-#define   INTE 0x4		// interrupt enable
+-#define   DAHFIE 0x8		// dac half full interrupt enable
+-#define   EOAIE	0x10		// end of aquisition interrupt enable
+-#define   DAHFI	0x20		// dac half full read status / write interrupt clear
+-#define   EOAI 0x40		// read end of acq. interrupt status / write clear
+-#define   INT 0x80		// read interrupt status / write clear
+-#define   EOBI 0x200		// read end of burst interrupt status
+-#define   ADHFI 0x400		// read half-full interrupt status
+-#define   ADNEI 0x800		// read fifo not empty interrupt latch status
+-#define   ADNE 0x1000		// read, fifo not empty (realtime, not latched) status
+-#define   DAEMIE	0x1000	// write, dac empty interrupt enable
+-#define   LADFUL 0x2000		// read fifo overflow / write clear
+-#define   DAEMI 0x4000		// dac fifo empty interrupt status / write clear
+-
+-#define ADCMUX_CONT	2	// ADC CHANNEL MUX AND CONTROL register
++#define INT_ADCFIFO	0	/*  INTERRUPT / ADC FIFO register */
++#define   INT_EOS 0x1		/*  interrupt end of scan */
++#define   INT_FHF 0x2		/*  interrupt fifo half full */
++#define   INT_FNE 0x3		/*  interrupt fifo not empty */
++#define   INT_MASK 0x3		/*  mask of interrupt select bits */
++#define   INTE 0x4		/*  interrupt enable */
++#define   DAHFIE 0x8		/*  dac half full interrupt enable */
++#define   EOAIE	0x10		/*  end of aquisition interrupt enable */
++#define   DAHFI	0x20		/*  dac half full read status / write interrupt clear */
++#define   EOAI 0x40		/*  read end of acq. interrupt status / write clear */
++#define   INT 0x80		/*  read interrupt status / write clear */
++#define   EOBI 0x200		/*  read end of burst interrupt status */
++#define   ADHFI 0x400		/*  read half-full interrupt status */
++#define   ADNEI 0x800		/*  read fifo not empty interrupt latch status */
++#define   ADNE 0x1000		/*  read, fifo not empty (realtime, not latched) status */
++#define   DAEMIE	0x1000	/*  write, dac empty interrupt enable */
++#define   LADFUL 0x2000		/*  read fifo overflow / write clear */
++#define   DAEMI 0x4000		/*  dac fifo empty interrupt status / write clear */
++
++#define ADCMUX_CONT	2	/*  ADC CHANNEL MUX AND CONTROL register */
+ #define   BEGIN_SCAN(x)	((x) & 0xf)
+ #define   END_SCAN(x)	(((x) & 0xf) << 4)
+ #define   GAIN_BITS(x)	(((x) & 0x3) << 8)
+-#define   UNIP	0x800		// Analog front-end unipolar for range
+-#define   SE	0x400		// Inputs in single-ended mode
+-#define   PACER_MASK	0x3000	// pacer source bits
+-#define   PACER_INT 0x1000	// internal pacer
+-#define   PACER_EXT_FALL	0x2000	// external falling edge
+-#define   PACER_EXT_RISE	0x3000	// external rising edge
+-#define   EOC	0x4000		// adc not busy
+-
+-#define TRIG_CONTSTAT 4		// TRIGGER CONTROL/STATUS register
+-#define   SW_TRIGGER 0x1	// software start trigger
+-#define   EXT_TRIGGER 0x2	// external start trigger
+-#define   ANALOG_TRIGGER 0x3	// external analog trigger
+-#define   TRIGGER_MASK	0x3	// mask of bits that determine start trigger
+-#define   TGEN	0x10		// enable external start trigger
+-#define   BURSTE 0x20		// burst mode enable
+-#define   XTRCL	0x80		// clear external trigger
+-
+-#define CALIBRATION_REG	6	// CALIBRATION register
+-#define   SELECT_8800_BIT	0x100	// select 8800 caldac
+-#define   SELECT_TRIMPOT_BIT	0x200	// select ad7376 trim pot
+-#define   SELECT_DAC08_BIT	0x400	// select dac08 caldac
++#define   UNIP	0x800		/*  Analog front-end unipolar for range */
++#define   SE	0x400		/*  Inputs in single-ended mode */
++#define   PACER_MASK	0x3000	/*  pacer source bits */
++#define   PACER_INT 0x1000	/*  internal pacer */
++#define   PACER_EXT_FALL	0x2000	/*  external falling edge */
++#define   PACER_EXT_RISE	0x3000	/*  external rising edge */
++#define   EOC	0x4000		/*  adc not busy */
++
++#define TRIG_CONTSTAT 4		/*  TRIGGER CONTROL/STATUS register */
++#define   SW_TRIGGER 0x1	/*  software start trigger */
++#define   EXT_TRIGGER 0x2	/*  external start trigger */
++#define   ANALOG_TRIGGER 0x3	/*  external analog trigger */
++#define   TRIGGER_MASK	0x3	/*  mask of bits that determine start trigger */
++#define   TGEN	0x10		/*  enable external start trigger */
++#define   BURSTE 0x20		/*  burst mode enable */
++#define   XTRCL	0x80		/*  clear external trigger */
++
++#define CALIBRATION_REG	6	/*  CALIBRATION register */
++#define   SELECT_8800_BIT	0x100	/*  select 8800 caldac */
++#define   SELECT_TRIMPOT_BIT	0x200	/*  select ad7376 trim pot */
++#define   SELECT_DAC08_BIT	0x400	/*  select dac08 caldac */
+ #define   CAL_SRC_BITS(x)	(((x) & 0x7) << 11)
+-#define   CAL_EN_BIT	0x4000	// read calibration source instead of analog input channel 0
+-#define   SERIAL_DATA_IN_BIT	0x8000	// serial data stream going to 8800 and 7376
++#define   CAL_EN_BIT	0x4000	/*  read calibration source instead of analog input channel 0 */
++#define   SERIAL_DATA_IN_BIT	0x8000	/*  serial data stream going to 8800 and 7376 */
+ 
+-#define DAC_CSR	0x8		// dac control and status register
++#define DAC_CSR	0x8		/*  dac control and status register */
+ enum dac_csr_bits {
+-	DACEN = 0x2,		// dac enable
+-	DAC_MODE_UPDATE_BOTH = 0x80,	// update both dacs when dac0 is written
++	DACEN = 0x2,		/*  dac enable */
++	DAC_MODE_UPDATE_BOTH = 0x80,	/*  update both dacs when dac0 is written */
+ };
+ static inline unsigned int DAC_RANGE(unsigned int channel, unsigned int range)
+ {
+@@ -160,42 +160,42 @@ static inline unsigned int DAC_RANGE_MASK(unsigned int channel)
+ 	return 0x3 << (8 + 2 * (channel & 0x1));
+ };
+ 
+-// bits for 1602 series only
++/* bits for 1602 series only */
+ enum dac_csr_bits_1602 {
+-	DAC_EMPTY = 0x1,	// dac fifo empty, read, write clear
+-	DAC_START = 0x4,	// start/arm dac fifo operations
+-	DAC_PACER_MASK = 0x18,	// bits that set dac pacer source
+-	DAC_PACER_INT = 0x8,	// dac internal pacing
+-	DAC_PACER_EXT_FALL = 0x10,	// dac external pacing, falling edge
+-	DAC_PACER_EXT_RISE = 0x18,	// dac external pacing, rising edge
++	DAC_EMPTY = 0x1,	/*  dac fifo empty, read, write clear */
++	DAC_START = 0x4,	/*  start/arm dac fifo operations */
++	DAC_PACER_MASK = 0x18,	/*  bits that set dac pacer source */
++	DAC_PACER_INT = 0x8,	/*  dac internal pacing */
++	DAC_PACER_EXT_FALL = 0x10,	/*  dac external pacing, falling edge */
++	DAC_PACER_EXT_RISE = 0x18,	/*  dac external pacing, rising edge */
+ };
+ static inline unsigned int DAC_CHAN_EN(unsigned int channel)
+ {
+-	return 1 << (5 + (channel & 0x1));	// enable channel 0 or 1
++	return 1 << (5 + (channel & 0x1));	/*  enable channel 0 or 1 */
+ };
+ 
+ /* analog input fifo */
+-#define ADCDATA	0		// ADC DATA register
+-#define ADCFIFOCLR	2	// ADC FIFO CLEAR
++#define ADCDATA	0		/*  ADC DATA register */
++#define ADCFIFOCLR	2	/*  ADC FIFO CLEAR */
+ 
+-// pacer, counter, dio registers
++/* pacer, counter, dio registers */
+ #define ADC8254 0
+ #define DIO_8255 4
+ #define DAC8254 8
+ 
+-// analog output registers for 100x, 1200 series
++/* analog output registers for 100x, 1200 series */
+ static inline unsigned int DAC_DATA_REG(unsigned int channel)
+ {
+ 	return 2 * (channel & 0x1);
+ }
+ 
+ /* analog output registers for 1602 series*/
+-#define DACDATA	0		// DAC DATA register
+-#define DACFIFOCLR	2	// DAC FIFO CLEAR
++#define DACDATA	0		/*  DAC DATA register */
++#define DACFIFOCLR	2	/*  DAC FIFO CLEAR */
+ 
+-// bit in hexadecimal representation of range index that indicates unipolar input range
++/* bit in hexadecimal representation of range index that indicates unipolar input range */
+ #define IS_UNIPOLAR 0x4
+-// analog input ranges for most boards
++/* analog input ranges for most boards */
+ static const struct comedi_lrange cb_pcidas_ranges = {
+ 	8,
+ 	{
+@@ -210,7 +210,7 @@ static const struct comedi_lrange cb_pcidas_ranges = {
+ 		}
+ };
+ 
+-// pci-das1001 input ranges
++/* pci-das1001 input ranges */
+ static const struct comedi_lrange cb_pcidas_alt_ranges = {
+ 	8,
+ 	{
+@@ -225,7 +225,7 @@ static const struct comedi_lrange cb_pcidas_alt_ranges = {
+ 		}
+ };
+ 
+-// analog output ranges
++/* analog output ranges */
+ static const struct comedi_lrange cb_pcidas_ao_ranges = {
+ 	4,
+ 	{
+@@ -244,14 +244,14 @@ enum trimpot_model {
+ struct cb_pcidas_board {
+ 	const char *name;
+ 	unsigned short device_id;
+-	int ai_se_chans;	// Inputs in single-ended mode
+-	int ai_diff_chans;	// Inputs in differential mode
+-	int ai_bits;		// analog input resolution
+-	int ai_speed;		// fastest conversion period in ns
+-	int ao_nchan;		// number of analog out channels
+-	int has_ao_fifo;	// analog output has fifo
+-	int ao_scan_speed;	// analog output speed for 1602 series (for a scan, not conversion)
+-	int fifo_size;		// number of samples fifo can hold
++	int ai_se_chans;	/*  Inputs in single-ended mode */
++	int ai_diff_chans;	/*  Inputs in differential mode */
++	int ai_bits;		/*  analog input resolution */
++	int ai_speed;		/*  fastest conversion period in ns */
++	int ao_nchan;		/*  number of analog out channels */
++	int has_ao_fifo;	/*  analog output has fifo */
++	int ao_scan_speed;	/*  analog output speed for 1602 series (for a scan, not conversion) */
++	int fifo_size;		/*  number of samples fifo can hold */
+ 	const struct comedi_lrange *ranges;
+ 	enum trimpot_model trimpot;
+ 	unsigned has_dac08:1;
+@@ -374,7 +374,7 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = {
+ 		},
+ };
+ 
+-// Number of boards in cb_pcidas_boards
++/* Number of boards in cb_pcidas_boards */
+ #define N_BOARDS	(sizeof(cb_pcidas_boards) / sizeof(struct cb_pcidas_board))
+ 
+ static DEFINE_PCI_DEVICE_TABLE(cb_pcidas_pci_table) = {
+@@ -402,28 +402,28 @@ MODULE_DEVICE_TABLE(pci, cb_pcidas_pci_table);
+ struct cb_pcidas_private {
+ 	/* would be useful for a PCI device */
+ 	struct pci_dev *pci_dev;
+-	// base addresses
++	/*  base addresses */
+ 	unsigned long s5933_config;
+ 	unsigned long control_status;
+ 	unsigned long adc_fifo;
+ 	unsigned long pacer_counter_dio;
+ 	unsigned long ao_registers;
+-	// divisors of master clock for analog input pacing
++	/*  divisors of master clock for analog input pacing */
+ 	unsigned int divisor1;
+ 	unsigned int divisor2;
+-	volatile unsigned int count;	// number of analog input samples remaining
+-	volatile unsigned int adc_fifo_bits;	// bits to write to interupt/adcfifo register
+-	volatile unsigned int s5933_intcsr_bits;	// bits to write to amcc s5933 interrupt control/status register
+-	volatile unsigned int ao_control_bits;	// bits to write to ao control and status register
++	volatile unsigned int count;	/*  number of analog input samples remaining */
++	volatile unsigned int adc_fifo_bits;	/*  bits to write to interupt/adcfifo register */
++	volatile unsigned int s5933_intcsr_bits;	/*  bits to write to amcc s5933 interrupt control/status register */
++	volatile unsigned int ao_control_bits;	/*  bits to write to ao control and status register */
+ 	short ai_buffer[AI_BUFFER_SIZE];
+ 	short ao_buffer[AO_BUFFER_SIZE];
+-	// divisors of master clock for analog output pacing
++	/*  divisors of master clock for analog output pacing */
+ 	unsigned int ao_divisor1;
+ 	unsigned int ao_divisor2;
+-	volatile unsigned int ao_count;	// number of analog output samples remaining
+-	int ao_value[2];	// remember what the analog outputs are set to, to allow readback
+-	unsigned int caldac_value[NUM_CHANNELS_8800];	// for readback of caldac
+-	unsigned int trimpot_value[NUM_CHANNELS_8402];	// for readback of trimpot
++	volatile unsigned int ao_count;	/*  number of analog output samples remaining */
++	int ao_value[2];	/*  remember what the analog outputs are set to, to allow readback */
++	unsigned int caldac_value[NUM_CHANNELS_8800];	/*  for readback of caldac */
++	unsigned int trimpot_value[NUM_CHANNELS_8402];	/*  for readback of trimpot */
+ 	unsigned int dac08_value;
+ 	unsigned int calibration_source;
+ };
+@@ -531,16 +531,16 @@ static int cb_pcidas_attach(struct comedi_device * dev, struct comedi_devconfig
+ 	for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
+ 		pcidev != NULL;
+ 		pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
+-		// is it not a computer boards card?
++		/*  is it not a computer boards card? */
+ 		if (pcidev->vendor != PCI_VENDOR_ID_CB)
+ 			continue;
+-		// loop through cards supported by this driver
++		/*  loop through cards supported by this driver */
+ 		for (index = 0; index < N_BOARDS; index++) {
+ 			if (cb_pcidas_boards[index].device_id != pcidev->device)
+ 				continue;
+-			// was a particular bus/slot requested?
++			/*  was a particular bus/slot requested? */
+ 			if (it->options[0] || it->options[1]) {
+-				// are we on the wrong bus/slot?
++				/*  are we on the wrong bus/slot? */
+ 				if (pcidev->bus->number != it->options[0] ||
+ 					PCI_SLOT(pcidev->devfn) !=
+ 					it->options[1]) {
+@@ -585,11 +585,11 @@ static int cb_pcidas_attach(struct comedi_device * dev, struct comedi_devconfig
+ 		devpriv->ao_registers =
+ 			pci_resource_start(devpriv->pci_dev, AO_BADRINDEX);
+ 	}
+-	// disable and clear interrupts on amcc s5933
++	/*  disable and clear interrupts on amcc s5933 */
+ 	outl(INTCSR_INBOX_INTR_STATUS,
+ 		devpriv->s5933_config + AMCC_OP_REG_INTCSR);
+ 
+-	// get irq
++	/*  get irq */
+ 	if (comedi_request_irq(devpriv->pci_dev->irq, cb_pcidas_interrupt,
+ 			IRQF_SHARED, "cb_pcidas", dev)) {
+ 		printk(" unable to allocate irq %d\n", devpriv->pci_dev->irq);
+@@ -597,7 +597,7 @@ static int cb_pcidas_attach(struct comedi_device * dev, struct comedi_devconfig
+ 	}
+ 	dev->irq = devpriv->pci_dev->irq;
+ 
+-	//Initialize dev->board_name
++	/* Initialize dev->board_name */
+ 	dev->board_name = thisboard->name;
+ 
+ /*
+@@ -628,7 +628,7 @@ static int cb_pcidas_attach(struct comedi_device * dev, struct comedi_devconfig
+ 		s->type = COMEDI_SUBD_AO;
+ 		s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND;
+ 		s->n_chan = thisboard->ao_nchan;
+-		// analog out resolution is the same as analog input resolution, so use ai_bits
++		/*  analog out resolution is the same as analog input resolution, so use ai_bits */
+ 		s->maxdata = (1 << thisboard->ai_bits) - 1;
+ 		s->range_table = &cb_pcidas_ao_ranges;
+ 		s->insn_read = cb_pcidas_ao_readback_insn;
+@@ -650,7 +650,7 @@ static int cb_pcidas_attach(struct comedi_device * dev, struct comedi_devconfig
+ 	s = dev->subdevices + 2;
+ 	subdev_8255_init(dev, s, NULL, devpriv->pacer_counter_dio + DIO_8255);
+ 
+-	// serial EEPROM,
++	/*  serial EEPROM, */
+ 	s = dev->subdevices + 3;
+ 	s->type = COMEDI_SUBD_MEMORY;
+ 	s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
+@@ -658,7 +658,7 @@ static int cb_pcidas_attach(struct comedi_device * dev, struct comedi_devconfig
+ 	s->maxdata = 0xff;
+ 	s->insn_read = eeprom_read_insn;
+ 
+-	// 8800 caldac
++	/*  8800 caldac */
+ 	s = dev->subdevices + 4;
+ 	s->type = COMEDI_SUBD_CALIB;
+ 	s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
+@@ -669,7 +669,7 @@ static int cb_pcidas_attach(struct comedi_device * dev, struct comedi_devconfig
+ 	for (i = 0; i < s->n_chan; i++)
+ 		caldac_8800_write(dev, i, s->maxdata / 2);
+ 
+-	// trim potentiometer
++	/*  trim potentiometer */
+ 	s = dev->subdevices + 5;
+ 	s->type = COMEDI_SUBD_CALIB;
+ 	s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
+@@ -685,7 +685,7 @@ static int cb_pcidas_attach(struct comedi_device * dev, struct comedi_devconfig
+ 	for (i = 0; i < s->n_chan; i++)
+ 		cb_pcidas_trimpot_write(dev, i, s->maxdata / 2);
+ 
+-	// dac08 caldac
++	/*  dac08 caldac */
+ 	s = dev->subdevices + 6;
+ 	if (thisboard->has_dac08) {
+ 		s->type = COMEDI_SUBD_CALIB;
+@@ -698,13 +698,13 @@ static int cb_pcidas_attach(struct comedi_device * dev, struct comedi_devconfig
+ 	} else
+ 		s->type = COMEDI_SUBD_UNUSED;
+ 
+-	// make sure mailbox 4 is empty
++	/*  make sure mailbox 4 is empty */
+ 	inl(devpriv->s5933_config + AMCC_OP_REG_IMB4);
+ 	/* Set bits to enable incoming mailbox interrupts on amcc s5933. */
+ 	devpriv->s5933_intcsr_bits =
+ 		INTCSR_INBOX_BYTE(3) | INTCSR_INBOX_SELECT(3) |
+ 		INTCSR_INBOX_FULL_INT;
+-	// clear and enable interrupt on amcc s5933
++	/*  clear and enable interrupt on amcc s5933 */
+ 	outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
+ 		devpriv->s5933_config + AMCC_OP_REG_INTCSR);
+ 
+@@ -725,7 +725,7 @@ static int cb_pcidas_detach(struct comedi_device * dev)
+ 
+ 	if (devpriv) {
+ 		if (devpriv->s5933_config) {
+-			// disable and clear interrupts on amcc s5933
++			/*  disable and clear interrupts on amcc s5933 */
+ 			outl(INTCSR_INBOX_INTR_STATUS,
+ 				devpriv->s5933_config + AMCC_OP_REG_INTCSR);
+ #ifdef CB_PCIDAS_DEBUG
+@@ -760,7 +760,7 @@ static int cb_pcidas_ai_rinsn(struct comedi_device * dev, struct comedi_subdevic
+ 	unsigned int bits;
+ 	static const int timeout = 10000;
+ 	int channel;
+-	// enable calibration input if appropriate
++	/*  enable calibration input if appropriate */
+ 	if (insn->chanspec & CR_ALT_SOURCE) {
+ 		outw(cal_enable_bits(dev),
+ 			devpriv->control_status + CALIBRATION_REG);
+@@ -769,13 +769,13 @@ static int cb_pcidas_ai_rinsn(struct comedi_device * dev, struct comedi_subdevic
+ 		outw(0, devpriv->control_status + CALIBRATION_REG);
+ 		channel = CR_CHAN(insn->chanspec);
+ 	}
+-	// set mux limits and gain
++	/*  set mux limits and gain */
+ 	bits = BEGIN_SCAN(channel) |
+ 		END_SCAN(channel) | GAIN_BITS(CR_RANGE(insn->chanspec));
+-	// set unipolar/bipolar
++	/*  set unipolar/bipolar */
+ 	if (CR_RANGE(insn->chanspec) & IS_UNIPOLAR)
+ 		bits |= UNIP;
+-	// set singleended/differential
++	/*  set singleended/differential */
+ 	if (CR_AREF(insn->chanspec) != AREF_DIFF)
+ 		bits |= SE;
+ 	outw(bits, devpriv->control_status + ADCMUX_CONT);
+@@ -836,14 +836,14 @@ static int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice *
+ 	return -EINVAL;
+ }
+ 
+-// analog output insn for pcidas-1000 and 1200 series
++/* analog output insn for pcidas-1000 and 1200 series */
+ static int cb_pcidas_ao_nofifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel;
+ 	unsigned long flags;
+ 
+-	// set channel and range
++	/*  set channel and range */
+ 	channel = CR_CHAN(insn->chanspec);
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 	devpriv->ao_control_bits &=
+@@ -853,25 +853,25 @@ static int cb_pcidas_ao_nofifo_winsn(struct comedi_device * dev, struct comedi_s
+ 	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ 
+-	// remember value for readback
++	/*  remember value for readback */
+ 	devpriv->ao_value[channel] = data[0];
+-	// send data
++	/*  send data */
+ 	outw(data[0], devpriv->ao_registers + DAC_DATA_REG(channel));
+ 
+ 	return 1;
+ }
+ 
+-// analog output insn for pcidas-1602 series
++/* analog output insn for pcidas-1602 series */
+ static int cb_pcidas_ao_fifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel;
+ 	unsigned long flags;
+ 
+-	// clear dac fifo
++	/*  clear dac fifo */
+ 	outw(0, devpriv->ao_registers + DACFIFOCLR);
+ 
+-	// set channel and range
++	/*  set channel and range */
+ 	channel = CR_CHAN(insn->chanspec);
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 	devpriv->ao_control_bits &=
+@@ -883,16 +883,16 @@ static int cb_pcidas_ao_fifo_winsn(struct comedi_device * dev, struct comedi_sub
+ 	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ 
+-	// remember value for readback
++	/*  remember value for readback */
+ 	devpriv->ao_value[channel] = data[0];
+-	// send data
++	/*  send data */
+ 	outw(data[0], devpriv->ao_registers + DACDATA);
+ 
+ 	return 1;
+ }
+ 
+-// analog output readback insn
+-// XXX loses track of analog output value back after an analog ouput command is executed
++/* analog output readback insn */
++/* XXX loses track of analog output value back after an analog ouput command is executed */
+ static int cb_pcidas_ao_readback_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+@@ -1066,7 +1066,7 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device * dev, struct comedi_subdev
+ 	if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
+ 		err++;
+ 
+-	// make sure trigger sources are compatible with each other
++	/*  make sure trigger sources are compatible with each other */
+ 	if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
+ 		err++;
+ 	if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
+@@ -1138,7 +1138,7 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device * dev, struct comedi_subdev
+ 	if (err)
+ 		return 4;
+ 
+-	// check channel/gain list against card's limitations
++	/*  check channel/gain list against card's limitations */
+ 	if (cmd->chanlist) {
+ 		gain = CR_RANGE(cmd->chanlist[0]);
+ 		start_chan = CR_CHAN(cmd->chanlist[0]);
+@@ -1170,24 +1170,24 @@ static int cb_pcidas_ai_cmd(struct comedi_device * dev, struct comedi_subdevice
+ 	unsigned int bits;
+ 	unsigned long flags;
+ 
+-	// make sure CAL_EN_BIT is disabled
++	/*  make sure CAL_EN_BIT is disabled */
+ 	outw(0, devpriv->control_status + CALIBRATION_REG);
+-	// initialize before settings pacer source and count values
++	/*  initialize before settings pacer source and count values */
+ 	outw(0, devpriv->control_status + TRIG_CONTSTAT);
+-	// clear fifo
++	/*  clear fifo */
+ 	outw(0, devpriv->adc_fifo + ADCFIFOCLR);
+ 
+-	// set mux limits, gain and pacer source
++	/*  set mux limits, gain and pacer source */
+ 	bits = BEGIN_SCAN(CR_CHAN(cmd->chanlist[0])) |
+ 		END_SCAN(CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1])) |
+ 		GAIN_BITS(CR_RANGE(cmd->chanlist[0]));
+-	// set unipolar/bipolar
++	/*  set unipolar/bipolar */
+ 	if (CR_RANGE(cmd->chanlist[0]) & IS_UNIPOLAR)
+ 		bits |= UNIP;
+-	// set singleended/differential
++	/*  set singleended/differential */
+ 	if (CR_AREF(cmd->chanlist[0]) != AREF_DIFF)
+ 		bits |= SE;
+-	// set pacer source
++	/*  set pacer source */
+ 	if (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT)
+ 		bits |= PACER_EXT_RISE;
+ 	else
+@@ -1198,7 +1198,7 @@ static int cb_pcidas_ai_cmd(struct comedi_device * dev, struct comedi_subdevice
+ 	rt_printk("comedi: sent 0x%x to adcmux control\n", bits);
+ #endif
+ 
+-	// load counters
++	/*  load counters */
+ 	if (cmd->convert_src == TRIG_TIMER)
+ 		cb_pcidas_load_counters(dev, &cmd->convert_arg,
+ 			cmd->flags & TRIG_ROUND_MASK);
+@@ -1206,31 +1206,31 @@ static int cb_pcidas_ai_cmd(struct comedi_device * dev, struct comedi_subdevice
+ 		cb_pcidas_load_counters(dev, &cmd->scan_begin_arg,
+ 			cmd->flags & TRIG_ROUND_MASK);
+ 
+-	// set number of conversions
++	/*  set number of conversions */
+ 	if (cmd->stop_src == TRIG_COUNT) {
+ 		devpriv->count = cmd->chanlist_len * cmd->stop_arg;
+ 	}
+-	// enable interrupts
++	/*  enable interrupts */
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 	devpriv->adc_fifo_bits |= INTE;
+ 	devpriv->adc_fifo_bits &= ~INT_MASK;
+ 	if (cmd->flags & TRIG_WAKE_EOS) {
+ 		if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1)
+-			devpriv->adc_fifo_bits |= INT_EOS;	// interrupt end of burst
++			devpriv->adc_fifo_bits |= INT_EOS;	/*  interrupt end of burst */
+ 		else
+-			devpriv->adc_fifo_bits |= INT_FNE;	// interrupt fifo not empty
++			devpriv->adc_fifo_bits |= INT_FNE;	/*  interrupt fifo not empty */
+ 	} else {
+-		devpriv->adc_fifo_bits |= INT_FHF;	//interrupt fifo half full
++		devpriv->adc_fifo_bits |= INT_FHF;	/* interrupt fifo half full */
+ 	}
+ #ifdef CB_PCIDAS_DEBUG
+ 	rt_printk("comedi: adc_fifo_bits are 0x%x\n", devpriv->adc_fifo_bits);
+ #endif
+-	// enable (and clear) interrupts
++	/*  enable (and clear) interrupts */
+ 	outw(devpriv->adc_fifo_bits | EOAI | INT | LADFUL,
+ 		devpriv->control_status + INT_ADCFIFO);
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ 
+-	// set start trigger and burst mode
++	/*  set start trigger and burst mode */
+ 	bits = 0;
+ 	if (cmd->start_src == TRIG_NOW)
+ 		bits |= SW_TRIGGER;
+@@ -1347,7 +1347,7 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device * dev, struct comedi_subdev
+ 	if (err)
+ 		return 4;
+ 
+-	// check channel/gain list against card's limitations
++	/*  check channel/gain list against card's limitations */
+ 	if (cmd->chanlist && cmd->chanlist_len > 1) {
+ 		if (CR_CHAN(cmd->chanlist[0]) != 0 ||
+ 			CR_CHAN(cmd->chanlist[1]) != 1) {
+@@ -1370,25 +1370,25 @@ static int cb_pcidas_ao_cmd(struct comedi_device * dev, struct comedi_subdevice
+ 	unsigned int i;
+ 	unsigned long flags;
+ 
+-	// set channel limits, gain
++	/*  set channel limits, gain */
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 	for (i = 0; i < cmd->chanlist_len; i++) {
+-		// enable channel
++		/*  enable channel */
+ 		devpriv->ao_control_bits |=
+ 			DAC_CHAN_EN(CR_CHAN(cmd->chanlist[i]));
+-		// set range
++		/*  set range */
+ 		devpriv->ao_control_bits |= DAC_RANGE(CR_CHAN(cmd->chanlist[i]),
+ 			CR_RANGE(cmd->chanlist[i]));
+ 	}
+ 
+-	// disable analog out before settings pacer source and count values
++	/*  disable analog out before settings pacer source and count values */
+ 	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ 
+-	// clear fifo
++	/*  clear fifo */
+ 	outw(0, devpriv->ao_registers + DACFIFOCLR);
+ 
+-	// load counters
++	/*  load counters */
+ 	if (cmd->scan_begin_src == TRIG_TIMER) {
+ 		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
+ 			&(devpriv->ao_divisor1), &(devpriv->ao_divisor2),
+@@ -1400,11 +1400,11 @@ static int cb_pcidas_ao_cmd(struct comedi_device * dev, struct comedi_subdevice
+ 		i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 2,
+ 			devpriv->ao_divisor2, 2);
+ 	}
+-	// set number of conversions
++	/*  set number of conversions */
+ 	if (cmd->stop_src == TRIG_COUNT) {
+ 		devpriv->ao_count = cmd->chanlist_len * cmd->stop_arg;
+ 	}
+-	// set pacer source
++	/*  set pacer source */
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 	switch (cmd->scan_begin_src) {
+ 	case TRIG_TIMER:
+@@ -1438,7 +1438,7 @@ static int cb_pcidas_ao_inttrig(struct comedi_device *dev,
+ 	if (trig_num != 0)
+ 		return -EINVAL;
+ 
+-	// load up fifo
++	/*  load up fifo */
+ 	if (cmd->stop_src == TRIG_COUNT && devpriv->ao_count < num_points)
+ 		num_points = devpriv->ao_count;
+ 
+@@ -1449,20 +1449,20 @@ static int cb_pcidas_ao_inttrig(struct comedi_device *dev,
+ 	if (cmd->stop_src == TRIG_COUNT) {
+ 		devpriv->ao_count -= num_points;
+ 	}
+-	// write data to board's fifo
++	/*  write data to board's fifo */
+ 	outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, num_bytes);
+ 
+-	// enable dac half-full and empty interrupts
++	/*  enable dac half-full and empty interrupts */
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 	devpriv->adc_fifo_bits |= DAEMIE | DAHFIE;
+ #ifdef CB_PCIDAS_DEBUG
+ 	rt_printk("comedi: adc_fifo_bits are 0x%x\n", devpriv->adc_fifo_bits);
+ #endif
+-	// enable and clear interrupts
++	/*  enable and clear interrupts */
+ 	outw(devpriv->adc_fifo_bits | DAEMI | DAHFI,
+ 		devpriv->control_status + INT_ADCFIFO);
+ 
+-	// start dac
++	/*  start dac */
+ 	devpriv->ao_control_bits |= DAC_START | DACEN | DAC_EMPTY;
+ 	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
+ #ifdef CB_PCIDAS_DEBUG
+@@ -1503,9 +1503,9 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d PT_REGS_ARG)
+ 	if ((INTCSR_INTR_ASSERTED & s5933_status) == 0)
+ 		return IRQ_NONE;
+ 
+-	// make sure mailbox 4 is empty
++	/*  make sure mailbox 4 is empty */
+ 	inl_p(devpriv->s5933_config + AMCC_OP_REG_IMB4);
+-	// clear interrupt on amcc s5933
++	/*  clear interrupt on amcc s5933 */
+ 	outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
+ 		devpriv->s5933_config + AMCC_OP_REG_INTCSR);
+ 
+@@ -1516,14 +1516,14 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d PT_REGS_ARG)
+ 	}
+ #endif
+ 
+-	// check for analog output interrupt
++	/*  check for analog output interrupt */
+ 	if (status & (DAHFI | DAEMI)) {
+ 		handle_ao_interrupt(dev, status);
+ 	}
+-	// check for analog input interrupts
+-	// if fifo half-full
++	/*  check for analog input interrupts */
++	/*  if fifo half-full */
+ 	if (status & ADHFI) {
+-		// read data
++		/*  read data */
+ 		num_samples = half_fifo;
+ 		if (async->cmd.stop_src == TRIG_COUNT &&
+ 			num_samples > devpriv->count) {
+@@ -1538,15 +1538,15 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d PT_REGS_ARG)
+ 			async->events |= COMEDI_CB_EOA;
+ 			cb_pcidas_cancel(dev, s);
+ 		}
+-		// clear half-full interrupt latch
++		/*  clear half-full interrupt latch */
+ 		comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 		outw(devpriv->adc_fifo_bits | INT,
+ 			devpriv->control_status + INT_ADCFIFO);
+ 		comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+-		// else if fifo not empty
++		/*  else if fifo not empty */
+ 	} else if (status & (ADNEI | EOBI)) {
+ 		for (i = 0; i < timeout; i++) {
+-			// break if fifo is empty
++			/*  break if fifo is empty */
+ 			if ((ADNE & inw(devpriv->control_status +
+ 						INT_ADCFIFO)) == 0)
+ 				break;
+@@ -1557,7 +1557,7 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d PT_REGS_ARG)
+ 				break;
+ 			}
+ 		}
+-		// clear not-empty interrupt latch
++		/*  clear not-empty interrupt latch */
+ 		comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 		outw(devpriv->adc_fifo_bits | INT,
+ 			devpriv->control_status + INT_ADCFIFO);
+@@ -1565,16 +1565,16 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d PT_REGS_ARG)
+ 	} else if (status & EOAI) {
+ 		comedi_error(dev,
+ 			"bug! encountered end of aquisition interrupt?");
+-		// clear EOA interrupt latch
++		/*  clear EOA interrupt latch */
+ 		comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 		outw(devpriv->adc_fifo_bits | EOAI,
+ 			devpriv->control_status + INT_ADCFIFO);
+ 		comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ 	}
+-	//check for fifo overflow
++	/* check for fifo overflow */
+ 	if (status & LADFUL) {
+ 		comedi_error(dev, "fifo overflow");
+-		// clear overflow interrupt latch
++		/*  clear overflow interrupt latch */
+ 		comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 		outw(devpriv->adc_fifo_bits | LADFUL,
+ 			devpriv->control_status + INT_ADCFIFO);
+@@ -1600,7 +1600,7 @@ static void handle_ao_interrupt(struct comedi_device * dev, unsigned int status)
+ 	async->events = 0;
+ 
+ 	if (status & DAEMI) {
+-		// clear dac empty interrupt latch
++		/*  clear dac empty interrupt latch */
+ 		comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 		outw(devpriv->adc_fifo_bits | DAEMI,
+ 			devpriv->control_status + INT_ADCFIFO);
+@@ -1618,7 +1618,7 @@ static void handle_ao_interrupt(struct comedi_device * dev, unsigned int status)
+ 	} else if (status & DAHFI) {
+ 		unsigned int num_bytes;
+ 
+-		// figure out how many points we are writing to fifo
++		/*  figure out how many points we are writing to fifo */
+ 		num_points = half_fifo;
+ 		if (cmd->stop_src == TRIG_COUNT &&
+ 			devpriv->ao_count < num_points)
+@@ -1631,10 +1631,10 @@ static void handle_ao_interrupt(struct comedi_device * dev, unsigned int status)
+ 		if (async->cmd.stop_src == TRIG_COUNT) {
+ 			devpriv->ao_count -= num_points;
+ 		}
+-		// write data to board's fifo
++		/*  write data to board's fifo */
+ 		outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer,
+ 			num_points);
+-		// clear half-full interrupt latch
++		/*  clear half-full interrupt latch */
+ 		comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 		outw(devpriv->adc_fifo_bits | DAHFI,
+ 			devpriv->control_status + INT_ADCFIFO);
+@@ -1650,14 +1650,14 @@ static int cb_pcidas_cancel(struct comedi_device * dev, struct comedi_subdevice
+ 	unsigned long flags;
+ 
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+-	// disable interrupts
++	/*  disable interrupts */
+ 	devpriv->adc_fifo_bits &= ~INTE & ~EOAIE;
+ 	outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO);
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ 
+-	// disable start trigger source and burst mode
++	/*  disable start trigger source and burst mode */
+ 	outw(0, devpriv->control_status + TRIG_CONTSTAT);
+-	// software pacer source
++	/*  software pacer source */
+ 	outw(0, devpriv->control_status + ADCMUX_CONT);
+ 
+ 	return 0;
+@@ -1670,11 +1670,11 @@ static int cb_pcidas_ao_cancel(struct comedi_device *dev,
+ 	unsigned long flags;
+ 
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+-	// disable interrupts
++	/*  disable interrupts */
+ 	devpriv->adc_fifo_bits &= ~DAHFIE & ~DAEMIE;
+ 	outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO);
+ 
+-	// disable output
++	/*  disable output */
+ 	devpriv->ao_control_bits &= ~DACEN & ~DAC_PACER_MASK;
+ 	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);

commit 9ef4dea6eb9ff671ffd62f5304c7d8de716807a2
+Author: Bill Pemberton 
+Date:   Fri Mar 27 11:30:39 2009 -0400
+
+    Staging: comedi: remove C99 comments in cb_pcidas64.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
+index 1a580bd2247a..7b57e3ab79c2 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
+@@ -93,8 +93,8 @@ known. If you have such a board, please file a bug report at
+ #include "plx9080.h"
+ #include "comedi_fc.h"
+ 
+-#undef PCIDAS64_DEBUG		// disable debugging code
+-//#define PCIDAS64_DEBUG        // enable debugging code
++#undef PCIDAS64_DEBUG		/*  disable debugging code */
++/* #define PCIDAS64_DEBUG         enable debugging code */
+ 
+ #ifdef PCIDAS64_DEBUG
+ #define DEBUG_PRINT(format, args...)  rt_printk(format , ## args )
+@@ -102,8 +102,8 @@ known. If you have such a board, please file a bug report at
+ #define DEBUG_PRINT(format, args...)
+ #endif
+ 
+-#define TIMER_BASE 25		// 40MHz master clock
+-#define PRESCALED_TIMER_BASE	10000	// 100kHz 'prescaled' clock for slow aquisition, maybe I'll support this someday
++#define TIMER_BASE 25		/*  40MHz master clock */
++#define PRESCALED_TIMER_BASE	10000	/*  100kHz 'prescaled' clock for slow aquisition, maybe I'll support this someday */
+ #define DMA_BUFFER_SIZE 0x1000
+ 
+ /* maximum value that can be loaded into board's 24-bit counters*/
+@@ -111,41 +111,41 @@ static const int max_counter_value = 0xffffff;
+ 
+ /* PCI-DAS64xxx base addresses */
+ 
+-// indices of base address regions
++/* indices of base address regions */
+ enum base_address_regions {
+ 	PLX9080_BADDRINDEX = 0,
+ 	MAIN_BADDRINDEX = 2,
+ 	DIO_COUNTER_BADDRINDEX = 3,
+ };
+ 
+-// priv(dev)->main_iobase registers
++/* priv(dev)->main_iobase registers */
+ enum write_only_registers {
+-	INTR_ENABLE_REG = 0x0,	// interrupt enable register
+-	HW_CONFIG_REG = 0x2,	// hardware config register
++	INTR_ENABLE_REG = 0x0,	/*  interrupt enable register */
++	HW_CONFIG_REG = 0x2,	/*  hardware config register */
+ 	DAQ_SYNC_REG = 0xc,
+ 	DAQ_ATRIG_LOW_4020_REG = 0xc,
+-	ADC_CONTROL0_REG = 0x10,	// adc control register 0
+-	ADC_CONTROL1_REG = 0x12,	// adc control register 1
++	ADC_CONTROL0_REG = 0x10,	/*  adc control register 0 */
++	ADC_CONTROL1_REG = 0x12,	/*  adc control register 1 */
+ 	CALIBRATION_REG = 0x14,
+-	ADC_SAMPLE_INTERVAL_LOWER_REG = 0x16,	// lower 16 bits of adc sample interval counter
+-	ADC_SAMPLE_INTERVAL_UPPER_REG = 0x18,	// upper 8 bits of adc sample interval counter
+-	ADC_DELAY_INTERVAL_LOWER_REG = 0x1a,	// lower 16 bits of delay interval counter
+-	ADC_DELAY_INTERVAL_UPPER_REG = 0x1c,	// upper 8 bits of delay interval counter
+-	ADC_COUNT_LOWER_REG = 0x1e,	// lower 16 bits of hardware conversion/scan counter
+-	ADC_COUNT_UPPER_REG = 0x20,	// upper 8 bits of hardware conversion/scan counter
+-	ADC_START_REG = 0x22,	// software trigger to start aquisition
+-	ADC_CONVERT_REG = 0x24,	// initiates single conversion
+-	ADC_QUEUE_CLEAR_REG = 0x26,	// clears adc queue
+-	ADC_QUEUE_LOAD_REG = 0x28,	// loads adc queue
++	ADC_SAMPLE_INTERVAL_LOWER_REG = 0x16,	/*  lower 16 bits of adc sample interval counter */
++	ADC_SAMPLE_INTERVAL_UPPER_REG = 0x18,	/*  upper 8 bits of adc sample interval counter */
++	ADC_DELAY_INTERVAL_LOWER_REG = 0x1a,	/*  lower 16 bits of delay interval counter */
++	ADC_DELAY_INTERVAL_UPPER_REG = 0x1c,	/*  upper 8 bits of delay interval counter */
++	ADC_COUNT_LOWER_REG = 0x1e,	/*  lower 16 bits of hardware conversion/scan counter */
++	ADC_COUNT_UPPER_REG = 0x20,	/*  upper 8 bits of hardware conversion/scan counter */
++	ADC_START_REG = 0x22,	/*  software trigger to start aquisition */
++	ADC_CONVERT_REG = 0x24,	/*  initiates single conversion */
++	ADC_QUEUE_CLEAR_REG = 0x26,	/*  clears adc queue */
++	ADC_QUEUE_LOAD_REG = 0x28,	/*  loads adc queue */
+ 	ADC_BUFFER_CLEAR_REG = 0x2a,
+-	ADC_QUEUE_HIGH_REG = 0x2c,	// high channel for internal queue, use adc_chan_bits() inline above
+-	DAC_CONTROL0_REG = 0x50,	// dac control register 0
+-	DAC_CONTROL1_REG = 0x52,	// dac control register 0
+-	DAC_SAMPLE_INTERVAL_LOWER_REG = 0x54,	// lower 16 bits of dac sample interval counter
+-	DAC_SAMPLE_INTERVAL_UPPER_REG = 0x56,	// upper 8 bits of dac sample interval counter
++	ADC_QUEUE_HIGH_REG = 0x2c,	/*  high channel for internal queue, use adc_chan_bits() inline above */
++	DAC_CONTROL0_REG = 0x50,	/*  dac control register 0 */
++	DAC_CONTROL1_REG = 0x52,	/*  dac control register 0 */
++	DAC_SAMPLE_INTERVAL_LOWER_REG = 0x54,	/*  lower 16 bits of dac sample interval counter */
++	DAC_SAMPLE_INTERVAL_UPPER_REG = 0x56,	/*  upper 8 bits of dac sample interval counter */
+ 	DAC_SELECT_REG = 0x60,
+ 	DAC_START_REG = 0x64,
+-	DAC_BUFFER_CLEAR_REG = 0x66,	// clear dac buffer
++	DAC_BUFFER_CLEAR_REG = 0x66,	/*  clear dac buffer */
+ };
+ static inline unsigned int dac_convert_reg(unsigned int channel)
+ {
+@@ -161,7 +161,7 @@ static inline unsigned int dac_msb_4020_reg(unsigned int channel)
+ }
+ 
+ enum read_only_registers {
+-	HW_STATUS_REG = 0x0,	// hardware status register, reading this apparently clears pending interrupts as well
++	HW_STATUS_REG = 0x0,	/*  hardware status register, reading this apparently clears pending interrupts as well */
+ 	PIPE1_READ_REG = 0x4,
+ 	ADC_READ_PNTR_REG = 0x8,
+ 	LOWER_XFER_REG = 0x10,
+@@ -170,13 +170,13 @@ enum read_only_registers {
+ };
+ 
+ enum read_write_registers {
+-	I8255_4020_REG = 0x48,	// 8255 offset, for 4020 only
+-	ADC_QUEUE_FIFO_REG = 0x100,	// external channel/gain queue, uses same bits as ADC_QUEUE_LOAD_REG
++	I8255_4020_REG = 0x48,	/*  8255 offset, for 4020 only */
++	ADC_QUEUE_FIFO_REG = 0x100,	/*  external channel/gain queue, uses same bits as ADC_QUEUE_LOAD_REG */
+ 	ADC_FIFO_REG = 0x200,	/* adc data fifo */
+ 	DAC_FIFO_REG = 0x300,	/* dac data fifo, has weird interactions with external channel queue */
+ };
+ 
+-// priv(dev)->dio_counter_iobase registers
++/* priv(dev)->dio_counter_iobase registers */
+ enum dio_counter_registers {
+ 	DIO_8255_OFFSET = 0x0,
+ 	DO_REG = 0x20,
+@@ -185,47 +185,47 @@ enum dio_counter_registers {
+ 	DIO_DATA_60XX_REG = 0x48,
+ };
+ 
+-// bit definitions for write-only registers
++/* bit definitions for write-only registers */
+ 
+ enum intr_enable_contents {
+-	ADC_INTR_SRC_MASK = 0x3,	// bits that set adc interrupt source
+-	ADC_INTR_QFULL_BITS = 0x0,	// interrupt fifo quater full
+-	ADC_INTR_EOC_BITS = 0x1,	// interrupt end of conversion
+-	ADC_INTR_EOSCAN_BITS = 0x2,	// interrupt end of scan
+-	ADC_INTR_EOSEQ_BITS = 0x3,	// interrupt end of sequence (probably wont use this it's pretty fancy)
+-	EN_ADC_INTR_SRC_BIT = 0x4,	// enable adc interrupt source
+-	EN_ADC_DONE_INTR_BIT = 0x8,	// enable adc aquisition done interrupt
++	ADC_INTR_SRC_MASK = 0x3,	/*  bits that set adc interrupt source */
++	ADC_INTR_QFULL_BITS = 0x0,	/*  interrupt fifo quater full */
++	ADC_INTR_EOC_BITS = 0x1,	/*  interrupt end of conversion */
++	ADC_INTR_EOSCAN_BITS = 0x2,	/*  interrupt end of scan */
++	ADC_INTR_EOSEQ_BITS = 0x3,	/*  interrupt end of sequence (probably wont use this it's pretty fancy) */
++	EN_ADC_INTR_SRC_BIT = 0x4,	/*  enable adc interrupt source */
++	EN_ADC_DONE_INTR_BIT = 0x8,	/*  enable adc aquisition done interrupt */
+ 	DAC_INTR_SRC_MASK = 0x30,
+ 	DAC_INTR_QEMPTY_BITS = 0x0,
+ 	DAC_INTR_HIGH_CHAN_BITS = 0x10,
+-	EN_DAC_INTR_SRC_BIT = 0x40,	// enable dac interrupt source
++	EN_DAC_INTR_SRC_BIT = 0x40,	/*  enable dac interrupt source */
+ 	EN_DAC_DONE_INTR_BIT = 0x80,
+-	EN_ADC_ACTIVE_INTR_BIT = 0x200,	// enable adc active interrupt
+-	EN_ADC_STOP_INTR_BIT = 0x400,	// enable adc stop trigger interrupt
+-	EN_DAC_ACTIVE_INTR_BIT = 0x800,	// enable dac active interrupt
+-	EN_DAC_UNDERRUN_BIT = 0x4000,	// enable dac underrun status bit
+-	EN_ADC_OVERRUN_BIT = 0x8000,	// enable adc overrun status bit
++	EN_ADC_ACTIVE_INTR_BIT = 0x200,	/*  enable adc active interrupt */
++	EN_ADC_STOP_INTR_BIT = 0x400,	/*  enable adc stop trigger interrupt */
++	EN_DAC_ACTIVE_INTR_BIT = 0x800,	/*  enable dac active interrupt */
++	EN_DAC_UNDERRUN_BIT = 0x4000,	/*  enable dac underrun status bit */
++	EN_ADC_OVERRUN_BIT = 0x8000,	/*  enable adc overrun status bit */
+ };
+ 
+ enum hw_config_contents {
+-	MASTER_CLOCK_4020_MASK = 0x3,	// bits that specify master clock source for 4020
+-	INTERNAL_CLOCK_4020_BITS = 0x1,	// use 40 MHz internal master clock for 4020
+-	BNC_CLOCK_4020_BITS = 0x2,	// use BNC input for master clock
+-	EXT_CLOCK_4020_BITS = 0x3,	// use dio input for master clock
+-	EXT_QUEUE_BIT = 0x200,	// use external channel/gain queue (more versatile than internal queue)
+-	SLOW_DAC_BIT = 0x400,	// use 225 nanosec strobe when loading dac instead of 50 nanosec
+-	HW_CONFIG_DUMMY_BITS = 0x2000,	// bit with unknown function yet given as default value in pci-das64 manual
+-	DMA_CH_SELECT_BIT = 0x8000,	// bit selects channels 1/0 for analog input/output, otherwise 0/1
+-	FIFO_SIZE_REG = 0x4,	// allows adjustment of fifo sizes
+-	DAC_FIFO_SIZE_MASK = 0xff00,	// bits that set dac fifo size
++	MASTER_CLOCK_4020_MASK = 0x3,	/*  bits that specify master clock source for 4020 */
++	INTERNAL_CLOCK_4020_BITS = 0x1,	/*  use 40 MHz internal master clock for 4020 */
++	BNC_CLOCK_4020_BITS = 0x2,	/*  use BNC input for master clock */
++	EXT_CLOCK_4020_BITS = 0x3,	/*  use dio input for master clock */
++	EXT_QUEUE_BIT = 0x200,	/*  use external channel/gain queue (more versatile than internal queue) */
++	SLOW_DAC_BIT = 0x400,	/*  use 225 nanosec strobe when loading dac instead of 50 nanosec */
++	HW_CONFIG_DUMMY_BITS = 0x2000,	/*  bit with unknown function yet given as default value in pci-das64 manual */
++	DMA_CH_SELECT_BIT = 0x8000,	/*  bit selects channels 1/0 for analog input/output, otherwise 0/1 */
++	FIFO_SIZE_REG = 0x4,	/*  allows adjustment of fifo sizes */
++	DAC_FIFO_SIZE_MASK = 0xff00,	/*  bits that set dac fifo size */
+ 	DAC_FIFO_BITS = 0xf800,	/* 8k sample ao fifo */
+ };
+ #define DAC_FIFO_SIZE 0x2000
+ 
+ enum daq_atrig_low_4020_contents {
+-	EXT_AGATE_BNC_BIT = 0x8000,	// use trig/ext clk bnc input for analog gate signal
+-	EXT_STOP_TRIG_BNC_BIT = 0x4000,	// use trig/ext clk bnc input for external stop trigger signal
+-	EXT_START_TRIG_BNC_BIT = 0x2000,	// use trig/ext clk bnc input for external start trigger signal
++	EXT_AGATE_BNC_BIT = 0x8000,	/*  use trig/ext clk bnc input for analog gate signal */
++	EXT_STOP_TRIG_BNC_BIT = 0x4000,	/*  use trig/ext clk bnc input for external stop trigger signal */
++	EXT_START_TRIG_BNC_BIT = 0x2000,	/*  use trig/ext clk bnc input for external start trigger signal */
+ };
+ static inline uint16_t analog_trig_low_threshold_bits(uint16_t threshold)
+ {
+@@ -233,34 +233,34 @@ static inline uint16_t analog_trig_low_threshold_bits(uint16_t threshold)
+ }
+ 
+ enum adc_control0_contents {
+-	ADC_GATE_SRC_MASK = 0x3,	// bits that select gate
+-	ADC_SOFT_GATE_BITS = 0x1,	// software gate
+-	ADC_EXT_GATE_BITS = 0x2,	// external digital gate
+-	ADC_ANALOG_GATE_BITS = 0x3,	// analog level gate
+-	ADC_GATE_LEVEL_BIT = 0x4,	// level-sensitive gate (for digital)
+-	ADC_GATE_POLARITY_BIT = 0x8,	// gate active low
++	ADC_GATE_SRC_MASK = 0x3,	/*  bits that select gate */
++	ADC_SOFT_GATE_BITS = 0x1,	/*  software gate */
++	ADC_EXT_GATE_BITS = 0x2,	/*  external digital gate */
++	ADC_ANALOG_GATE_BITS = 0x3,	/*  analog level gate */
++	ADC_GATE_LEVEL_BIT = 0x4,	/*  level-sensitive gate (for digital) */
++	ADC_GATE_POLARITY_BIT = 0x8,	/*  gate active low */
+ 	ADC_START_TRIG_SOFT_BITS = 0x10,
+ 	ADC_START_TRIG_EXT_BITS = 0x20,
+ 	ADC_START_TRIG_ANALOG_BITS = 0x30,
+ 	ADC_START_TRIG_MASK = 0x30,
+-	ADC_START_TRIG_FALLING_BIT = 0x40,	// trig 1 uses falling edge
+-	ADC_EXT_CONV_FALLING_BIT = 0x800,	// external pacing uses falling edge
+-	ADC_SAMPLE_COUNTER_EN_BIT = 0x1000,	// enable hardware scan counter
+-	ADC_DMA_DISABLE_BIT = 0x4000,	// disables dma
+-	ADC_ENABLE_BIT = 0x8000,	// master adc enable
++	ADC_START_TRIG_FALLING_BIT = 0x40,	/*  trig 1 uses falling edge */
++	ADC_EXT_CONV_FALLING_BIT = 0x800,	/*  external pacing uses falling edge */
++	ADC_SAMPLE_COUNTER_EN_BIT = 0x1000,	/*  enable hardware scan counter */
++	ADC_DMA_DISABLE_BIT = 0x4000,	/*  disables dma */
++	ADC_ENABLE_BIT = 0x8000,	/*  master adc enable */
+ };
+ 
+ enum adc_control1_contents {
+-	ADC_QUEUE_CONFIG_BIT = 0x1,	// should be set for boards with > 16 channels
++	ADC_QUEUE_CONFIG_BIT = 0x1,	/*  should be set for boards with > 16 channels */
+ 	CONVERT_POLARITY_BIT = 0x10,
+ 	EOC_POLARITY_BIT = 0x20,
+-	ADC_SW_GATE_BIT = 0x40,	// software gate of adc
+-	ADC_DITHER_BIT = 0x200,	// turn on extra noise for dithering
++	ADC_SW_GATE_BIT = 0x40,	/*  software gate of adc */
++	ADC_DITHER_BIT = 0x200,	/*  turn on extra noise for dithering */
+ 	RETRIGGER_BIT = 0x800,
+ 	ADC_LO_CHANNEL_4020_MASK = 0x300,
+ 	ADC_HI_CHANNEL_4020_MASK = 0xc00,
+-	TWO_CHANNEL_4020_BITS = 0x1000,	// two channel mode for 4020
+-	FOUR_CHANNEL_4020_BITS = 0x2000,	// four channel mode for 4020
++	TWO_CHANNEL_4020_BITS = 0x1000,	/*  two channel mode for 4020 */
++	FOUR_CHANNEL_4020_BITS = 0x2000,	/*  four channel mode for 4020 */
+ 	CHANNEL_MODE_4020_MASK = 0x3000,
+ 	ADC_MODE_MASK = 0xf000,
+ };
+@@ -281,10 +281,10 @@ enum calibration_contents {
+ 	SELECT_8800_BIT = 0x1,
+ 	SELECT_8402_64XX_BIT = 0x2,
+ 	SELECT_1590_60XX_BIT = 0x2,
+-	CAL_EN_64XX_BIT = 0x40,	// calibration enable for 64xx series
++	CAL_EN_64XX_BIT = 0x40,	/*  calibration enable for 64xx series */
+ 	SERIAL_DATA_IN_BIT = 0x80,
+ 	SERIAL_CLOCK_BIT = 0x100,
+-	CAL_EN_60XX_BIT = 0x200,	// calibration enable for 60xx series
++	CAL_EN_60XX_BIT = 0x200,	/*  calibration enable for 60xx series */
+ 	CAL_GAIN_BIT = 0x800,
+ };
+ /* calibration sources for 6025 are:
+@@ -308,11 +308,11 @@ static inline uint16_t adc_convert_chan_4020_bits(unsigned int channel)
+ };
+ 
+ enum adc_queue_load_contents {
+-	UNIP_BIT = 0x800,	// unipolar/bipolar bit
+-	ADC_SE_DIFF_BIT = 0x1000,	// single-ended/ differential bit
+-	ADC_COMMON_BIT = 0x2000,	// non-referenced single-ended (common-mode input)
+-	QUEUE_EOSEQ_BIT = 0x4000,	// queue end of sequence
+-	QUEUE_EOSCAN_BIT = 0x8000,	// queue end of scan
++	UNIP_BIT = 0x800,	/*  unipolar/bipolar bit */
++	ADC_SE_DIFF_BIT = 0x1000,	/*  single-ended/ differential bit */
++	ADC_COMMON_BIT = 0x2000,	/*  non-referenced single-ended (common-mode input) */
++	QUEUE_EOSEQ_BIT = 0x4000,	/*  queue end of sequence */
++	QUEUE_EOSCAN_BIT = 0x8000,	/*  queue end of scan */
+ };
+ static inline uint16_t adc_chan_bits(unsigned int channel)
+ {
+@@ -320,7 +320,7 @@ static inline uint16_t adc_chan_bits(unsigned int channel)
+ };
+ 
+ enum dac_control0_contents {
+-	DAC_ENABLE_BIT = 0x8000,	// dac controller enable bit
++	DAC_ENABLE_BIT = 0x8000,	/*  dac controller enable bit */
+ 	DAC_CYCLIC_STOP_BIT = 0x4000,
+ 	DAC_WAVEFORM_MODE_BIT = 0x100,
+ 	DAC_EXT_UPDATE_FALLING_BIT = 0x80,
+@@ -340,14 +340,14 @@ enum dac_control1_contents {
+ 	DAC_WRITE_POLARITY_BIT = 0x800,	/* board-dependent setting */
+ 	DAC1_EXT_REF_BIT = 0x200,
+ 	DAC0_EXT_REF_BIT = 0x100,
+-	DAC_OUTPUT_ENABLE_BIT = 0x80,	// dac output enable bit
++	DAC_OUTPUT_ENABLE_BIT = 0x80,	/*  dac output enable bit */
+ 	DAC_UPDATE_POLARITY_BIT = 0x40,	/* board-dependent setting */
+ 	DAC_SW_GATE_BIT = 0x20,
+ 	DAC1_UNIPOLAR_BIT = 0x8,
+ 	DAC0_UNIPOLAR_BIT = 0x2,
+ };
+ 
+-// bit definitions for read-only registers
++/* bit definitions for read-only registers */
+ enum hw_status_contents {
+ 	DAC_UNDERRUN_BIT = 0x1,
+ 	ADC_OVERRUN_BIT = 0x2,
+@@ -378,7 +378,7 @@ static inline unsigned int adc_upper_write_ptr_code(uint16_t prepost_bits)
+ 	return (prepost_bits >> 14) & 0x3;
+ }
+ 
+-// I2C addresses for 4020
++/* I2C addresses for 4020 */
+ enum i2c_addresses {
+ 	RANGE_CAL_I2C_ADDR = 0x20,
+ 	CALDAC0_I2C_ADDR = 0xc,
+@@ -386,8 +386,8 @@ enum i2c_addresses {
+ };
+ 
+ enum range_cal_i2c_contents {
+-	ADC_SRC_4020_MASK = 0x70,	// bits that set what source the adc converter measures
+-	BNC_TRIG_THRESHOLD_0V_BIT = 0x80,	// make bnc trig/ext clock threshold 0V instead of 2.5V
++	ADC_SRC_4020_MASK = 0x70,	/*  bits that set what source the adc converter measures */
++	BNC_TRIG_THRESHOLD_0V_BIT = 0x80,	/*  make bnc trig/ext clock threshold 0V instead of 2.5V */
+ };
+ static inline uint8_t adc_src_4020_bits(unsigned int source)
+ {
+@@ -395,11 +395,11 @@ static inline uint8_t adc_src_4020_bits(unsigned int source)
+ };
+ static inline uint8_t attenuate_bit(unsigned int channel)
+ {
+-	// attenuate channel (+-5V input range)
++	/*  attenuate channel (+-5V input range) */
+ 	return 1 << (channel & 0x3);
+ };
+ 
+-// analog input ranges for 64xx boards
++/* analog input ranges for 64xx boards */
+ static const struct comedi_lrange ai_ranges_64xx = {
+ 	8,
+ 	{
+@@ -468,7 +468,7 @@ static const struct comedi_lrange ai_ranges_6052 = {
+ 		}
+ };
+ 
+-// analog input ranges for 4020 board
++/* analog input ranges for 4020 board */
+ static const struct comedi_lrange ai_ranges_4020 = {
+ 	2,
+ 	{
+@@ -477,7 +477,7 @@ static const struct comedi_lrange ai_ranges_4020 = {
+ 		}
+ };
+ 
+-// analog output ranges
++/* analog output ranges */
+ static const struct comedi_lrange ao_ranges_64xx = {
+ 	4,
+ 	{
+@@ -543,18 +543,18 @@ struct hw_fifo_info {
+ 
+ struct pcidas64_board {
+ 	const char *name;
+-	int device_id;		// pci device id
+-	int ai_se_chans;	// number of ai inputs in single-ended mode
+-	int ai_bits;		// analog input resolution
+-	int ai_speed;		// fastest conversion period in ns
++	int device_id;		/*  pci device id */
++	int ai_se_chans;	/*  number of ai inputs in single-ended mode */
++	int ai_bits;		/*  analog input resolution */
++	int ai_speed;		/*  fastest conversion period in ns */
+ 	const struct comedi_lrange *ai_range_table;
+-	int ao_nchan;		// number of analog out channels
+-	int ao_bits;		// analog output resolution
+-	int ao_scan_speed;	// analog output speed (for a scan, not conversion)
++	int ao_nchan;		/*  number of analog out channels */
++	int ao_bits;		/*  analog output resolution */
++	int ao_scan_speed;	/*  analog output speed (for a scan, not conversion) */
+ 	const struct comedi_lrange *ao_range_table;
+ 	const int *ao_range_code;
+ 	const struct hw_fifo_info *const ai_fifo;
+-	enum register_layout layout;	// different board families have slightly different registers
++	enum register_layout layout;	/*  different board families have slightly different registers */
+ 	unsigned has_8255:1;
+ };
+ 
+@@ -612,7 +612,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
+ 	      has_8255:1,
+ 		},
+ 	{
+-	      name:	"pci-das6402/12",	// XXX check
++	      name:	"pci-das6402/12",	/*  XXX check */
+ 	      device_id:0x1e,
+ 	      ai_se_chans:64,
+ 	      ai_bits:	12,
+@@ -910,7 +910,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
+ 	      ai_speed:50,
+ 	      ao_bits:	12,
+ 	      ao_nchan:2,
+-	      ao_scan_speed:0,	// no hardware pacing on ao
++	      ao_scan_speed:0,	/*  no hardware pacing on ao */
+ 	      layout:	LAYOUT_4020,
+ 	      ai_range_table:&ai_ranges_4020,
+ 	      ao_range_table:&ao_ranges_4020,
+@@ -921,7 +921,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
+ #if 0
+ 	{
+ 	      name:	"pci-das6402/16/jr",
+-	      device_id:0	// XXX,
++	      device_id:0	/*  XXX, */
+ 	      ai_se_chans:64,
+ 	      ai_bits:	16,
+ 	      ai_speed:5000,
+@@ -934,7 +934,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
+ 		},
+ 	{
+ 	      name:	"pci-das64/m1/16/jr",
+-	      device_id:0	// XXX,
++	      device_id:0	/*  XXX, */
+ 	      ai_se_chans:64,
+ 	      ai_bits:	16,
+ 	      ai_speed:1000,
+@@ -947,7 +947,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
+ 		},
+ 	{
+ 	      name:	"pci-das64/m2/16/jr",
+-	      device_id:0	// XXX,
++	      device_id:0	/*  XXX, */
+ 	      ai_se_chans:64,
+ 	      ai_bits:	16,
+ 	      ai_speed:500,
+@@ -960,7 +960,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
+ 		},
+ 	{
+ 	      name:	"pci-das64/m3/16/jr",
+-	      device_id:0	// XXX,
++	      device_id:0	/*  XXX, */
+ 	      ai_se_chans:64,
+ 	      ai_bits:	16,
+ 	      ai_speed:333,
+@@ -973,7 +973,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
+ 		},
+ 	{
+ 	      name:	"pci-das64/m1/14",
+-	      device_id:0,	// XXX
++	      device_id:0,	/*  XXX */
+ 	      ai_se_chans:64,
+ 	      ai_bits:	14,
+ 	      ai_speed:1000,
+@@ -986,7 +986,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
+ 		},
+ 	{
+ 	      name:	"pci-das64/m2/14",
+-	      device_id:0,	// XXX
++	      device_id:0,	/*  XXX */
+ 	      ai_se_chans:64,
+ 	      ai_bits:	14,
+ 	      ai_speed:500,
+@@ -999,7 +999,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
+ 		},
+ 	{
+ 	      name:	"pci-das64/m3/14",
+-	      device_id:0,	// XXX
++	      device_id:0,	/*  XXX */
+ 	      ai_se_chans:64,
+ 	      ai_bits:	14,
+ 	      ai_speed:333,
+@@ -1013,7 +1013,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
+ #endif
+ };
+ 
+-// Number of boards in cb_pcidas_boards
++/* Number of boards in cb_pcidas_boards */
+ static inline unsigned int num_boards(void)
+ {
+ 	return sizeof(pcidas64_boards) / sizeof(struct pcidas64_board);
+@@ -1060,50 +1060,50 @@ static inline unsigned short se_diff_bit_6xxx(struct comedi_device * dev,
+ };
+ 
+ struct ext_clock_info {
+-	unsigned int divisor;	// master clock divisor to use for scans with external master clock
+-	unsigned int chanspec;	// chanspec for master clock input when used as scan begin src
++	unsigned int divisor;	/*  master clock divisor to use for scans with external master clock */
++	unsigned int chanspec;	/*  chanspec for master clock input when used as scan begin src */
+ };
+ 
+ /* this structure is for data unique to this hardware driver. */
+ struct pcidas64_private {
+ 
+-	struct pci_dev *hw_dev;	// pointer to board's pci_dev struct
+-	// base addresses (physical)
++	struct pci_dev *hw_dev;	/*  pointer to board's pci_dev struct */
++	/*  base addresses (physical) */
+ 	resource_size_t plx9080_phys_iobase;
+ 	resource_size_t main_phys_iobase;
+ 	resource_size_t dio_counter_phys_iobase;
+-	// base addresses (ioremapped)
++	/*  base addresses (ioremapped) */
+ 	void *plx9080_iobase;
+ 	void *main_iobase;
+ 	void *dio_counter_iobase;
+-	// local address (used by dma controller)
++	/*  local address (used by dma controller) */
+ 	uint32_t local0_iobase;
+ 	uint32_t local1_iobase;
+-	volatile unsigned int ai_count;	// number of analog input samples remaining
+-	uint16_t *ai_buffer[MAX_AI_DMA_RING_COUNT];	// dma buffers for analog input
+-	dma_addr_t ai_buffer_bus_addr[MAX_AI_DMA_RING_COUNT];	// physical addresses of ai dma buffers
+-	struct plx_dma_desc *ai_dma_desc;	// array of ai dma descriptors read by plx9080, allocated to get proper alignment
+-	dma_addr_t ai_dma_desc_bus_addr;	// physical address of ai dma descriptor array
+-	volatile unsigned int ai_dma_index;	// index of the ai dma descriptor/buffer that is currently being used
+-	uint16_t *ao_buffer[AO_DMA_RING_COUNT];	// dma buffers for analog output
+-	dma_addr_t ao_buffer_bus_addr[AO_DMA_RING_COUNT];	// physical addresses of ao dma buffers
++	volatile unsigned int ai_count;	/*  number of analog input samples remaining */
++	uint16_t *ai_buffer[MAX_AI_DMA_RING_COUNT];	/*  dma buffers for analog input */
++	dma_addr_t ai_buffer_bus_addr[MAX_AI_DMA_RING_COUNT];	/*  physical addresses of ai dma buffers */
++	struct plx_dma_desc *ai_dma_desc;	/*  array of ai dma descriptors read by plx9080, allocated to get proper alignment */
++	dma_addr_t ai_dma_desc_bus_addr;	/*  physical address of ai dma descriptor array */
++	volatile unsigned int ai_dma_index;	/*  index of the ai dma descriptor/buffer that is currently being used */
++	uint16_t *ao_buffer[AO_DMA_RING_COUNT];	/*  dma buffers for analog output */
++	dma_addr_t ao_buffer_bus_addr[AO_DMA_RING_COUNT];	/*  physical addresses of ao dma buffers */
+ 	struct plx_dma_desc *ao_dma_desc;
+ 	dma_addr_t ao_dma_desc_bus_addr;
+-	volatile unsigned int ao_dma_index;	// keeps track of buffer where the next ao sample should go
+-	volatile unsigned long ao_count;	// number of analog output samples remaining
+-	volatile unsigned int ao_value[2];	// remember what the analog outputs are set to, to allow readback
+-	unsigned int hw_revision;	// stc chip hardware revision number
+-	volatile unsigned int intr_enable_bits;	// last bits sent to INTR_ENABLE_REG register
+-	volatile uint16_t adc_control1_bits;	// last bits sent to ADC_CONTROL1_REG register
+-	volatile uint16_t fifo_size_bits;	// last bits sent to FIFO_SIZE_REG register
+-	volatile uint16_t hw_config_bits;	// last bits sent to HW_CONFIG_REG register
++	volatile unsigned int ao_dma_index;	/*  keeps track of buffer where the next ao sample should go */
++	volatile unsigned long ao_count;	/*  number of analog output samples remaining */
++	volatile unsigned int ao_value[2];	/*  remember what the analog outputs are set to, to allow readback */
++	unsigned int hw_revision;	/*  stc chip hardware revision number */
++	volatile unsigned int intr_enable_bits;	/*  last bits sent to INTR_ENABLE_REG register */
++	volatile uint16_t adc_control1_bits;	/*  last bits sent to ADC_CONTROL1_REG register */
++	volatile uint16_t fifo_size_bits;	/*  last bits sent to FIFO_SIZE_REG register */
++	volatile uint16_t hw_config_bits;	/*  last bits sent to HW_CONFIG_REG register */
+ 	volatile uint16_t dac_control1_bits;
+-	volatile uint32_t plx_control_bits;	// last bits written to plx9080 control register
+-	volatile uint32_t plx_intcsr_bits;	// last bits written to plx interrupt control and status register
+-	volatile int calibration_source;	// index of calibration source readable through ai ch0
+-	volatile uint8_t i2c_cal_range_bits;	// bits written to i2c calibration/range register
+-	volatile unsigned int ext_trig_falling;	// configure digital triggers to trigger on falling edge
+-	// states of various devices stored to enable read-back
++	volatile uint32_t plx_control_bits;	/*  last bits written to plx9080 control register */
++	volatile uint32_t plx_intcsr_bits;	/*  last bits written to plx interrupt control and status register */
++	volatile int calibration_source;	/*  index of calibration source readable through ai ch0 */
++	volatile uint8_t i2c_cal_range_bits;	/*  bits written to i2c calibration/range register */
++	volatile unsigned int ext_trig_falling;	/*  configure digital triggers to trigger on falling edge */
++	/*  states of various devices stored to enable read-back */
+ 	unsigned int ad8402_state[2];
+ 	unsigned int caldac_state[8];
+ 	volatile short ai_cmd_running;
+@@ -1185,7 +1185,7 @@ static void caldac_write(struct comedi_device * dev, unsigned int channel,
+ 	unsigned int value);
+ static int caldac_8800_write(struct comedi_device * dev, unsigned int address,
+ 	uint8_t value);
+-//static int dac_1590_write(struct comedi_device *dev, unsigned int dac_a, unsigned int dac_b);
++/* static int dac_1590_write(struct comedi_device *dev, unsigned int dac_a, unsigned int dac_b); */
+ static int caldac_i2c_write(struct comedi_device * dev, unsigned int caldac_channel,
+ 	unsigned int value);
+ static void abort_dma(struct comedi_device * dev, unsigned int channel);
+@@ -1274,7 +1274,7 @@ static inline int ao_cmd_is_supported(const struct pcidas64_board * board)
+ 	return board->ao_nchan && board->layout != LAYOUT_4020;
+ }
+ 
+-// initialize plx9080 chip
++/* initialize plx9080 chip */
+ static void init_plx9080(struct comedi_device * dev)
+ {
+ 	uint32_t bits;
+@@ -1283,7 +1283,7 @@ static void init_plx9080(struct comedi_device * dev)
+ 	priv(dev)->plx_control_bits =
+ 		readl(priv(dev)->plx9080_iobase + PLX_CONTROL_REG);
+ 
+-	// plx9080 dump
++	/*  plx9080 dump */
+ 	DEBUG_PRINT(" plx interrupt status 0x%x\n",
+ 		readl(plx_iobase + PLX_INTRCS_REG));
+ 	DEBUG_PRINT(" plx id bits 0x%x\n", readl(plx_iobase + PLX_ID_REG));
+@@ -1327,35 +1327,35 @@ static void init_plx9080(struct comedi_device * dev)
+ 	abort_dma(dev, 0);
+ 	abort_dma(dev, 1);
+ 
+-	// configure dma0 mode
++	/*  configure dma0 mode */
+ 	bits = 0;
+-	// enable ready input, not sure if this is necessary
++	/*  enable ready input, not sure if this is necessary */
+ 	bits |= PLX_DMA_EN_READYIN_BIT;
+-	// enable bterm, not sure if this is necessary
++	/*  enable bterm, not sure if this is necessary */
+ 	bits |= PLX_EN_BTERM_BIT;
+-	// enable dma chaining
++	/*  enable dma chaining */
+ 	bits |= PLX_EN_CHAIN_BIT;
+-	// enable interrupt on dma done (probably don't need this, since chain never finishes)
++	/*  enable interrupt on dma done (probably don't need this, since chain never finishes) */
+ 	bits |= PLX_EN_DMA_DONE_INTR_BIT;
+-	// don't increment local address during transfers (we are transferring from a fixed fifo register)
++	/*  don't increment local address during transfers (we are transferring from a fixed fifo register) */
+ 	bits |= PLX_LOCAL_ADDR_CONST_BIT;
+-	// route dma interrupt to pci bus
++	/*  route dma interrupt to pci bus */
+ 	bits |= PLX_DMA_INTR_PCI_BIT;
+-	// enable demand mode
++	/*  enable demand mode */
+ 	bits |= PLX_DEMAND_MODE_BIT;
+-	// enable local burst mode
++	/*  enable local burst mode */
+ 	bits |= PLX_DMA_LOCAL_BURST_EN_BIT;
+-	// 4020 uses 32 bit dma
++	/*  4020 uses 32 bit dma */
+ 	if (board(dev)->layout == LAYOUT_4020) {
+ 		bits |= PLX_LOCAL_BUS_32_WIDE_BITS;
+-	} else {		// localspace0 bus is 16 bits wide
++	} else {		/*  localspace0 bus is 16 bits wide */
+ 		bits |= PLX_LOCAL_BUS_16_WIDE_BITS;
+ 	}
+ 	writel(bits, plx_iobase + PLX_DMA1_MODE_REG);
+ 	if (ao_cmd_is_supported(board(dev)))
+ 		writel(bits, plx_iobase + PLX_DMA0_MODE_REG);
+ 
+-	// enable interrupts on plx 9080
++	/*  enable interrupts on plx 9080 */
+ 	priv(dev)->plx_intcsr_bits |=
+ 		ICS_AERR | ICS_PERR | ICS_PIE | ICS_PLIE | ICS_PAIE | ICS_LIE |
+ 		ICS_DMA0_E | ICS_DMA1_E;
+@@ -1396,9 +1396,9 @@ static int setup_subdevices(struct comedi_device * dev)
+ 	if (board(dev)->layout == LAYOUT_4020) {
+ 		unsigned int i;
+ 		uint8_t data;
+-		// set adc to read from inputs (not internal calibration sources)
++		/*  set adc to read from inputs (not internal calibration sources) */
+ 		priv(dev)->i2c_cal_range_bits = adc_src_4020_bits(4);
+-		// set channels to +-5 volt input ranges
++		/*  set channels to +-5 volt input ranges */
+ 		for (i = 0; i < s->n_chan; i++)
+ 			priv(dev)->i2c_cal_range_bits |= attenuate_bit(i);
+ 		data = priv(dev)->i2c_cal_range_bits;
+@@ -1428,7 +1428,7 @@ static int setup_subdevices(struct comedi_device * dev)
+ 		s->type = COMEDI_SUBD_UNUSED;
+ 	}
+ 
+-	// digital input
++	/*  digital input */
+ 	s = dev->subdevices + 2;
+ 	if (board(dev)->layout == LAYOUT_64XX) {
+ 		s->type = COMEDI_SUBD_DI;
+@@ -1440,7 +1440,7 @@ static int setup_subdevices(struct comedi_device * dev)
+ 	} else
+ 		s->type = COMEDI_SUBD_UNUSED;
+ 
+-	// digital output
++	/*  digital output */
+ 	if (board(dev)->layout == LAYOUT_64XX) {
+ 		s = dev->subdevices + 3;
+ 		s->type = COMEDI_SUBD_DO;
+@@ -1469,7 +1469,7 @@ static int setup_subdevices(struct comedi_device * dev)
+ 	} else
+ 		s->type = COMEDI_SUBD_UNUSED;
+ 
+-	// 8 channel dio for 60xx
++	/*  8 channel dio for 60xx */
+ 	s = dev->subdevices + 5;
+ 	if (board(dev)->layout == LAYOUT_60XX) {
+ 		s->type = COMEDI_SUBD_DIO;
+@@ -1482,7 +1482,7 @@ static int setup_subdevices(struct comedi_device * dev)
+ 	} else
+ 		s->type = COMEDI_SUBD_UNUSED;
+ 
+-	// caldac
++	/*  caldac */
+ 	s = dev->subdevices + 6;
+ 	s->type = COMEDI_SUBD_CALIB;
+ 	s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
+@@ -1496,7 +1496,7 @@ static int setup_subdevices(struct comedi_device * dev)
+ 	for (i = 0; i < s->n_chan; i++)
+ 		caldac_write(dev, i, s->maxdata / 2);
+ 
+-	// 2 channel ad8402 potentiometer
++	/*  2 channel ad8402 potentiometer */
+ 	s = dev->subdevices + 7;
+ 	if (board(dev)->layout == LAYOUT_64XX) {
+ 		s->type = COMEDI_SUBD_CALIB;
+@@ -1510,7 +1510,7 @@ static int setup_subdevices(struct comedi_device * dev)
+ 	} else
+ 		s->type = COMEDI_SUBD_UNUSED;
+ 
+-	//serial EEPROM, if present
++	/* serial EEPROM, if present */
+ 	s = dev->subdevices + 8;
+ 	if (readl(priv(dev)->plx9080_iobase + PLX_CONTROL_REG) & CTL_EECHK) {
+ 		s->type = COMEDI_SUBD_MEMORY;
+@@ -1521,7 +1521,7 @@ static int setup_subdevices(struct comedi_device * dev)
+ 	} else
+ 		s->type = COMEDI_SUBD_UNUSED;
+ 
+-	// user counter subd XXX
++	/*  user counter subd XXX */
+ 	s = dev->subdevices + 9;
+ 	s->type = COMEDI_SUBD_UNUSED;
+ 
+@@ -1542,13 +1542,13 @@ static void init_stc_registers(struct comedi_device * dev)
+ 
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 
+-	// bit should be set for 6025, although docs say boards with <= 16 chans should be cleared XXX
++	/*  bit should be set for 6025, although docs say boards with <= 16 chans should be cleared XXX */
+ 	if (1)
+ 		priv(dev)->adc_control1_bits |= ADC_QUEUE_CONFIG_BIT;
+ 	writew(priv(dev)->adc_control1_bits,
+ 		priv(dev)->main_iobase + ADC_CONTROL1_REG);
+ 
+-	// 6402/16 manual says this register must be initialized to 0xff?
++	/*  6402/16 manual says this register must be initialized to 0xff? */
+ 	writew(0xff, priv(dev)->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG);
+ 
+ 	bits = SLOW_DAC_BIT | DMA_CH_SELECT_BIT;
+@@ -1563,7 +1563,7 @@ static void init_stc_registers(struct comedi_device * dev)
+ 
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ 
+-	// set fifos to maximum size
++	/*  set fifos to maximum size */
+ 	priv(dev)->fifo_size_bits |= DAC_FIFO_BITS;
+ 	set_ai_fifo_segment_length(dev,
+ 		board(dev)->ai_fifo->max_segment_length);
+@@ -1581,7 +1581,7 @@ int alloc_and_init_dma_members(struct comedi_device * dev)
+ {
+ 	int i;
+ 
+-	// alocate pci dma buffers
++	/*  alocate pci dma buffers */
+ 	for (i = 0; i < ai_dma_ring_count(board(dev)); i++) {
+ 		priv(dev)->ai_buffer[i] =
+ 			pci_alloc_consistent(priv(dev)->hw_dev, DMA_BUFFER_SIZE,
+@@ -1601,7 +1601,7 @@ int alloc_and_init_dma_members(struct comedi_device * dev)
+ 			}
+ 		}
+ 	}
+-	// allocate dma descriptors
++	/*  allocate dma descriptors */
+ 	priv(dev)->ai_dma_desc =
+ 		pci_alloc_consistent(priv(dev)->hw_dev,
+ 		sizeof(struct plx_dma_desc) * ai_dma_ring_count(board(dev)),
+@@ -1622,7 +1622,7 @@ int alloc_and_init_dma_members(struct comedi_device * dev)
+ 		DEBUG_PRINT("ao dma descriptors start at bus addr 0x%x\n",
+ 			priv(dev)->ao_dma_desc_bus_addr);
+ 	}
+-	// initialize dma descriptors
++	/*  initialize dma descriptors */
+ 	for (i = 0; i < ai_dma_ring_count(board(dev)); i++) {
+ 		priv(dev)->ai_dma_desc[i].pci_start_addr =
+ 			cpu_to_le32(priv(dev)->ai_buffer_bus_addr[i]);
+@@ -1697,16 +1697,16 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
+ 		pcidev != NULL;
+ 		pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
+-		// is it not a computer boards card?
++		/*  is it not a computer boards card? */
+ 		if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS)
+ 			continue;
+-		// loop through cards supported by this driver
++		/*  loop through cards supported by this driver */
+ 		for (index = 0; index < num_boards(); index++) {
+ 			if (pcidas64_boards[index].device_id != pcidev->device)
+ 				continue;
+-			// was a particular bus/slot requested?
++			/*  was a particular bus/slot requested? */
+ 			if (it->options[0] || it->options[1]) {
+-				// are we on the wrong bus/slot?
++				/*  are we on the wrong bus/slot? */
+ 				if (pcidev->bus->number != it->options[0] ||
+ 					PCI_SLOT(pcidev->devfn) !=
+ 					it->options[1]) {
+@@ -1736,7 +1736,7 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	}
+ 	pci_set_master(pcidev);
+ 
+-	//Initialize dev->board_name
++	/* Initialize dev->board_name */
+ 	dev->board_name = board(dev)->name;
+ 
+ 	priv(dev)->plx9080_phys_iobase =
+@@ -1746,7 +1746,7 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	priv(dev)->dio_counter_phys_iobase =
+ 		pci_resource_start(pcidev, DIO_COUNTER_BADDRINDEX);
+ 
+-	// remap, won't work with 2.0 kernels but who cares
++	/*  remap, won't work with 2.0 kernels but who cares */
+ 	priv(dev)->plx9080_iobase = ioremap(priv(dev)->plx9080_phys_iobase,
+ 		pci_resource_len(pcidev, PLX9080_BADDRINDEX));
+ 	priv(dev)->main_iobase = ioremap(priv(dev)->main_phys_iobase,
+@@ -1766,7 +1766,7 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	DEBUG_PRINT(" diocounter remapped to 0x%p\n",
+ 		priv(dev)->dio_counter_iobase);
+ 
+-	// figure out what local addresses are
++	/*  figure out what local addresses are */
+ 	local_range =
+ 		readl(priv(dev)->plx9080_iobase +
+ 		PLX_LAS0RNG_REG) & LRNG_MEM_MASK;
+@@ -1798,7 +1798,7 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	printk(" stc hardware revision %i\n", priv(dev)->hw_revision);
+ 	init_plx9080(dev);
+ 	init_stc_registers(dev);
+-	// get irq
++	/*  get irq */
+ 	if (comedi_request_irq(pcidev->irq, handle_interrupt, IRQF_SHARED,
+ 			"cb_pcidas64", dev)) {
+ 		printk(" unable to allocate irq %u\n", pcidev->irq);
+@@ -1841,7 +1841,7 @@ static int detach(struct comedi_device * dev)
+ 				iounmap((void *)priv(dev)->main_iobase);
+ 			if (priv(dev)->dio_counter_iobase)
+ 				iounmap((void *)priv(dev)->dio_counter_iobase);
+-			// free pci dma buffers
++			/*  free pci dma buffers */
+ 			for (i = 0; i < ai_dma_ring_count(board(dev)); i++) {
+ 				if (priv(dev)->ai_buffer[i])
+ 					pci_free_consistent(priv(dev)->hw_dev,
+@@ -1858,7 +1858,7 @@ static int detach(struct comedi_device * dev)
+ 						priv(dev)->
+ 						ao_buffer_bus_addr[i]);
+ 			}
+-			// free dma descriptors
++			/*  free dma descriptors */
+ 			if (priv(dev)->ai_dma_desc)
+ 				pci_free_consistent(priv(dev)->hw_dev,
+ 					sizeof(struct plx_dma_desc) *
+@@ -1896,8 +1896,8 @@ static int ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	range = CR_RANGE(insn->chanspec);
+ 	aref = CR_AREF(insn->chanspec);
+ 
+-	// disable card's analog input interrupt sources and pacing
+-	// 4020 generates dac done interrupts even though they are disabled
++	/*  disable card's analog input interrupt sources and pacing */
++	/*  4020 generates dac done interrupts even though they are disabled */
+ 	disable_ai_pacing(dev);
+ 
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+@@ -1910,12 +1910,12 @@ static int ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ 
+ 	if (board(dev)->layout != LAYOUT_4020) {
+-		// use internal queue
++		/*  use internal queue */
+ 		priv(dev)->hw_config_bits &= ~EXT_QUEUE_BIT;
+ 		writew(priv(dev)->hw_config_bits,
+ 			priv(dev)->main_iobase + HW_CONFIG_REG);
+ 
+-		// ALT_SOURCE is internal calibration reference
++		/*  ALT_SOURCE is internal calibration reference */
+ 		if (insn->chanspec & CR_ALT_SOURCE) {
+ 			unsigned int cal_en_bit;
+ 
+@@ -1924,27 +1924,27 @@ static int ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 				cal_en_bit = CAL_EN_60XX_BIT;
+ 			else
+ 				cal_en_bit = CAL_EN_64XX_BIT;
+-			// select internal reference source to connect to channel 0
++			/*  select internal reference source to connect to channel 0 */
+ 			writew(cal_en_bit | adc_src_bits(priv(dev)->
+ 					calibration_source),
+ 				priv(dev)->main_iobase + CALIBRATION_REG);
+ 		} else {
+-			// make sure internal calibration source is turned off
++			/*  make sure internal calibration source is turned off */
+ 			writew(0, priv(dev)->main_iobase + CALIBRATION_REG);
+ 		}
+-		// load internal queue
++		/*  load internal queue */
+ 		bits = 0;
+-		// set gain
++		/*  set gain */
+ 		bits |= ai_range_bits_6xxx(dev, CR_RANGE(insn->chanspec));
+-		// set single-ended / differential
++		/*  set single-ended / differential */
+ 		bits |= se_diff_bit_6xxx(dev, aref == AREF_DIFF);
+ 		if (aref == AREF_COMMON)
+ 			bits |= ADC_COMMON_BIT;
+ 		bits |= adc_chan_bits(channel);
+-		// set stop channel
++		/*  set stop channel */
+ 		writew(adc_chan_bits(channel),
+ 			priv(dev)->main_iobase + ADC_QUEUE_HIGH_REG);
+-		// set start channel, and rest of settings
++		/*  set start channel, and rest of settings */
+ 		writew(bits, priv(dev)->main_iobase + ADC_QUEUE_LOAD_REG);
+ 	} else {
+ 		uint8_t old_cal_range_bits = priv(dev)->i2c_cal_range_bits;
+@@ -1955,16 +1955,16 @@ static int ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 			priv(dev)->i2c_cal_range_bits |=
+ 				adc_src_4020_bits(priv(dev)->
+ 				calibration_source);
+-		} else {	//select BNC inputs
++		} else {	/* select BNC inputs */
+ 			priv(dev)->i2c_cal_range_bits |= adc_src_4020_bits(4);
+ 		}
+-		// select range
++		/*  select range */
+ 		if (range == 0)
+ 			priv(dev)->i2c_cal_range_bits |= attenuate_bit(channel);
+ 		else
+ 			priv(dev)->i2c_cal_range_bits &=
+ 				~attenuate_bit(channel);
+-		// update calibration/range i2c register only if necessary, as it is very slow
++		/*  update calibration/range i2c register only if necessary, as it is very slow */
+ 		if (old_cal_range_bits != priv(dev)->i2c_cal_range_bits) {
+ 			uint8_t i2c_data = priv(dev)->i2c_cal_range_bits;
+ 			i2c_write(dev, RANGE_CAL_I2C_ADDR, &i2c_data,
+@@ -1981,14 +1981,14 @@ static int ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 
+ 	for (n = 0; n < insn->n; n++) {
+ 
+-		// clear adc buffer (inside loop for 4020 sake)
++		/*  clear adc buffer (inside loop for 4020 sake) */
+ 		writew(0, priv(dev)->main_iobase + ADC_BUFFER_CLEAR_REG);
+ 
+ 		/* trigger conversion, bits sent only matter for 4020 */
+ 		writew(adc_convert_chan_4020_bits(CR_CHAN(insn->chanspec)),
+ 			priv(dev)->main_iobase + ADC_CONVERT_REG);
+ 
+-		// wait for data
++		/*  wait for data */
+ 		for (i = 0; i < timeout; i++) {
+ 			bits = readw(priv(dev)->main_iobase + HW_STATUS_REG);
+ 			DEBUG_PRINT(" pipe bits 0x%x\n", pipe_full_bits(bits));
+@@ -2092,7 +2092,7 @@ static int ai_config_master_clock_4020(struct comedi_device * dev, unsigned int
+ 	return retval ? retval : 5;
+ }
+ 
+-// XXX could add support for 60xx series
++/* XXX could add support for 60xx series */
+ static int ai_config_master_clock(struct comedi_device * dev, unsigned int * data)
+ {
+ 
+@@ -2182,7 +2182,7 @@ static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 
+ 	/* step 2: make sure trigger sources are unique and mutually compatible */
+ 
+-	// uniqueness check
++	/*  uniqueness check */
+ 	if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
+ 		err++;
+ 	if (cmd->scan_begin_src != TRIG_TIMER &&
+@@ -2196,7 +2196,7 @@ static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 		cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_EXT)
+ 		err++;
+ 
+-	// compatibility check
++	/*  compatibility check */
+ 	if (cmd->convert_src == TRIG_EXT && cmd->scan_begin_src == TRIG_TIMER)
+ 		err++;
+ 	if (cmd->stop_src != TRIG_COUNT &&
+@@ -2220,7 +2220,7 @@ static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 				err++;
+ 			}
+ 			if (cmd->scan_begin_src == TRIG_TIMER) {
+-				// if scans are timed faster than conversion rate allows
++				/*  if scans are timed faster than conversion rate allows */
+ 				if (cmd->convert_arg * cmd->chanlist_len >
+ 					cmd->scan_begin_arg) {
+ 					cmd->scan_begin_arg =
+@@ -2278,7 +2278,7 @@ static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	if (err)
+ 		return 4;
+ 
+-	// make sure user is doesn't change analog reference mid chanlist
++	/*  make sure user is doesn't change analog reference mid chanlist */
+ 	if (cmd->chanlist) {
+ 		aref = CR_AREF(cmd->chanlist[0]);
+ 		for (i = 1; i < cmd->chanlist_len; i++) {
+@@ -2289,7 +2289,7 @@ static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 				break;
+ 			}
+ 		}
+-		// check 4020 chanlist
++		/*  check 4020 chanlist */
+ 		if (board(dev)->layout == LAYOUT_4020) {
+ 			unsigned int first_channel = CR_CHAN(cmd->chanlist[0]);
+ 			for (i = 1; i < cmd->chanlist_len; i++) {
+@@ -2317,7 +2317,7 @@ static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 
+ static int use_hw_sample_counter(struct comedi_cmd * cmd)
+ {
+-// disable for now until I work out a race
++/* disable for now until I work out a race */
+ 	return 0;
+ 
+ 	if (cmd->stop_src == TRIG_COUNT && cmd->stop_arg <= max_counter_value)
+@@ -2329,10 +2329,10 @@ static int use_hw_sample_counter(struct comedi_cmd * cmd)
+ static void setup_sample_counters(struct comedi_device * dev, struct comedi_cmd * cmd)
+ {
+ 	if (cmd->stop_src == TRIG_COUNT) {
+-		// set software count
++		/*  set software count */
+ 		priv(dev)->ai_count = cmd->stop_arg * cmd->chanlist_len;
+ 	}
+-	// load hardware conversion counter
++	/*  load hardware conversion counter */
+ 	if (use_hw_sample_counter(cmd)) {
+ 		writew(cmd->stop_arg & 0xffff,
+ 			priv(dev)->main_iobase + ADC_COUNT_LOWER_REG);
+@@ -2396,9 +2396,9 @@ static void enable_ai_interrupts(struct comedi_device * dev, const struct comedi
+ 
+ 	bits = EN_ADC_OVERRUN_BIT | EN_ADC_DONE_INTR_BIT |
+ 		EN_ADC_ACTIVE_INTR_BIT | EN_ADC_STOP_INTR_BIT;
+-	// Use pio transfer and interrupt on end of conversion if TRIG_WAKE_EOS flag is set.
++	/*  Use pio transfer and interrupt on end of conversion if TRIG_WAKE_EOS flag is set. */
+ 	if (cmd->flags & TRIG_WAKE_EOS) {
+-		// 4020 doesn't support pio transfers except for fifo dregs
++		/*  4020 doesn't support pio transfers except for fifo dregs */
+ 		if (board(dev)->layout != LAYOUT_4020)
+ 			bits |= ADC_INTR_EOSCAN_BITS | EN_ADC_INTR_SRC_BIT;
+ 	}
+@@ -2413,14 +2413,14 @@ static void enable_ai_interrupts(struct comedi_device * dev, const struct comedi
+ static uint32_t ai_convert_counter_6xxx(const struct comedi_device * dev,
+ 	const struct comedi_cmd * cmd)
+ {
+-	// supposed to load counter with desired divisor minus 3
++	/*  supposed to load counter with desired divisor minus 3 */
+ 	return cmd->convert_arg / TIMER_BASE - 3;
+ }
+ 
+ static uint32_t ai_scan_counter_6xxx(struct comedi_device * dev, struct comedi_cmd * cmd)
+ {
+ 	uint32_t count;
+-	// figure out how long we need to delay at end of scan
++	/*  figure out how long we need to delay at end of scan */
+ 	switch (cmd->scan_begin_src) {
+ 	case TRIG_TIMER:
+ 		count = (cmd->scan_begin_arg -
+@@ -2448,20 +2448,20 @@ static uint32_t ai_convert_counter_4020(struct comedi_device * dev, struct comed
+ 	case TRIG_OTHER:
+ 		divisor = priv(dev)->ext_clock.divisor;
+ 		break;
+-	default:		// should never happen
++	default:		/*  should never happen */
+ 		comedi_error(dev, "bug! failed to set ai pacing!");
+ 		divisor = 1000;
+ 		break;
+ 	}
+ 
+-	// supposed to load counter with desired divisor minus 2 for 4020
++	/*  supposed to load counter with desired divisor minus 2 for 4020 */
+ 	return divisor - 2;
+ }
+ 
+ static void select_master_clock_4020(struct comedi_device * dev,
+ 	const struct comedi_cmd * cmd)
+ {
+-	// select internal/external master clock
++	/*  select internal/external master clock */
+ 	priv(dev)->hw_config_bits &= ~MASTER_CLOCK_4020_MASK;
+ 	if (cmd->scan_begin_src == TRIG_OTHER) {
+ 		int chanspec = priv(dev)->ext_clock.chanspec;
+@@ -2492,7 +2492,7 @@ static inline void dma_start_sync(struct comedi_device * dev, unsigned int chann
+ {
+ 	unsigned long flags;
+ 
+-	// spinlock for plx dma control/status reg
++	/*  spinlock for plx dma control/status reg */
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 	if (channel)
+ 		writeb(PLX_DMA_EN_BIT | PLX_DMA_START_BIT |
+@@ -2520,17 +2520,17 @@ static void set_ai_pacing(struct comedi_device * dev, struct comedi_cmd * cmd)
+ 		scan_counter = ai_scan_counter_6xxx(dev, cmd);
+ 	}
+ 
+-	// load lower 16 bits of convert interval
++	/*  load lower 16 bits of convert interval */
+ 	writew(convert_counter & 0xffff,
+ 		priv(dev)->main_iobase + ADC_SAMPLE_INTERVAL_LOWER_REG);
+ 	DEBUG_PRINT("convert counter 0x%x\n", convert_counter);
+-	// load upper 8 bits of convert interval
++	/*  load upper 8 bits of convert interval */
+ 	writew((convert_counter >> 16) & 0xff,
+ 		priv(dev)->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG);
+-	// load lower 16 bits of scan delay
++	/*  load lower 16 bits of scan delay */
+ 	writew(scan_counter & 0xffff,
+ 		priv(dev)->main_iobase + ADC_DELAY_INTERVAL_LOWER_REG);
+-	// load upper 8 bits of scan delay
++	/*  load upper 8 bits of scan delay */
+ 	writew((scan_counter >> 16) & 0xff,
+ 		priv(dev)->main_iobase + ADC_DELAY_INTERVAL_UPPER_REG);
+ 	DEBUG_PRINT("scan counter 0x%x\n", scan_counter);
+@@ -2563,25 +2563,25 @@ static int setup_channel_queue(struct comedi_device * dev, const struct comedi_c
+ 			writew(priv(dev)->hw_config_bits,
+ 				priv(dev)->main_iobase + HW_CONFIG_REG);
+ 			bits = 0;
+-			// set channel
++			/*  set channel */
+ 			bits |= adc_chan_bits(CR_CHAN(cmd->chanlist[0]));
+-			// set gain
++			/*  set gain */
+ 			bits |= ai_range_bits_6xxx(dev,
+ 				CR_RANGE(cmd->chanlist[0]));
+-			// set single-ended / differential
++			/*  set single-ended / differential */
+ 			bits |= se_diff_bit_6xxx(dev,
+ 				CR_AREF(cmd->chanlist[0]) == AREF_DIFF);
+ 			if (CR_AREF(cmd->chanlist[0]) == AREF_COMMON)
+ 				bits |= ADC_COMMON_BIT;
+-			// set stop channel
++			/*  set stop channel */
+ 			writew(adc_chan_bits(CR_CHAN(cmd->chanlist[cmd->
+ 							chanlist_len - 1])),
+ 				priv(dev)->main_iobase + ADC_QUEUE_HIGH_REG);
+-			// set start channel, and rest of settings
++			/*  set start channel, and rest of settings */
+ 			writew(bits,
+ 				priv(dev)->main_iobase + ADC_QUEUE_LOAD_REG);
+ 		} else {
+-			// use external queue
++			/*  use external queue */
+ 			if (dev->write_subdev && dev->write_subdev->busy) {
+ 				warn_external_queue(dev);
+ 				return -EBUSY;
+@@ -2589,26 +2589,26 @@ static int setup_channel_queue(struct comedi_device * dev, const struct comedi_c
+ 			priv(dev)->hw_config_bits |= EXT_QUEUE_BIT;
+ 			writew(priv(dev)->hw_config_bits,
+ 				priv(dev)->main_iobase + HW_CONFIG_REG);
+-			// clear DAC buffer to prevent weird interactions
++			/*  clear DAC buffer to prevent weird interactions */
+ 			writew(0,
+ 				priv(dev)->main_iobase + DAC_BUFFER_CLEAR_REG);
+-			// clear queue pointer
++			/*  clear queue pointer */
+ 			writew(0, priv(dev)->main_iobase + ADC_QUEUE_CLEAR_REG);
+-			// load external queue
++			/*  load external queue */
+ 			for (i = 0; i < cmd->chanlist_len; i++) {
+ 				bits = 0;
+-				// set channel
++				/*  set channel */
+ 				bits |= adc_chan_bits(CR_CHAN(cmd->
+ 						chanlist[i]));
+-				// set gain
++				/*  set gain */
+ 				bits |= ai_range_bits_6xxx(dev,
+ 					CR_RANGE(cmd->chanlist[i]));
+-				// set single-ended / differential
++				/*  set single-ended / differential */
+ 				bits |= se_diff_bit_6xxx(dev,
+ 					CR_AREF(cmd->chanlist[i]) == AREF_DIFF);
+ 				if (CR_AREF(cmd->chanlist[i]) == AREF_COMMON)
+ 					bits |= ADC_COMMON_BIT;
+-				// mark end of queue
++				/*  mark end of queue */
+ 				if (i == cmd->chanlist_len - 1)
+ 					bits |= QUEUE_EOSCAN_BIT |
+ 						QUEUE_EOSEQ_BIT;
+@@ -2622,7 +2622,7 @@ static int setup_channel_queue(struct comedi_device * dev, const struct comedi_c
+ 			/* doing a queue clear is not specified in board docs,
+ 			 * but required for reliable operation */
+ 			writew(0, priv(dev)->main_iobase + ADC_QUEUE_CLEAR_REG);
+-			// prime queue holding register
++			/*  prime queue holding register */
+ 			writew(0, priv(dev)->main_iobase + ADC_QUEUE_LOAD_REG);
+ 		}
+ 	} else {
+@@ -2630,9 +2630,9 @@ static int setup_channel_queue(struct comedi_device * dev, const struct comedi_c
+ 			priv(dev)->i2c_cal_range_bits;
+ 
+ 		priv(dev)->i2c_cal_range_bits &= ~ADC_SRC_4020_MASK;
+-		//select BNC inputs
++		/* select BNC inputs */
+ 		priv(dev)->i2c_cal_range_bits |= adc_src_4020_bits(4);
+-		// select ranges
++		/*  select ranges */
+ 		for (i = 0; i < cmd->chanlist_len; i++) {
+ 			unsigned int channel = CR_CHAN(cmd->chanlist[i]);
+ 			unsigned int range = CR_RANGE(cmd->chanlist[i]);
+@@ -2644,7 +2644,7 @@ static int setup_channel_queue(struct comedi_device * dev, const struct comedi_c
+ 				priv(dev)->i2c_cal_range_bits &=
+ 					~attenuate_bit(channel);
+ 		}
+-		// update calibration/range i2c register only if necessary, as it is very slow
++		/*  update calibration/range i2c register only if necessary, as it is very slow */
+ 		if (old_cal_range_bits != priv(dev)->i2c_cal_range_bits) {
+ 			uint8_t i2c_data = priv(dev)->i2c_cal_range_bits;
+ 			i2c_write(dev, RANGE_CAL_I2C_ADDR, &i2c_data,
+@@ -2697,7 +2697,7 @@ static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	if (retval < 0)
+ 		return retval;
+ 
+-	// make sure internal calibration source is turned off
++	/*  make sure internal calibration source is turned off */
+ 	writew(0, priv(dev)->main_iobase + CALIBRATION_REG);
+ 
+ 	set_ai_pacing(dev, cmd);
+@@ -2713,9 +2713,9 @@ static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	if (board(dev)->layout != LAYOUT_4020) {
+ 		priv(dev)->adc_control1_bits &= ~ADC_MODE_MASK;
+ 		if (cmd->convert_src == TRIG_EXT)
+-			priv(dev)->adc_control1_bits |= adc_mode_bits(13);	// good old mode 13
++			priv(dev)->adc_control1_bits |= adc_mode_bits(13);	/*  good old mode 13 */
+ 		else
+-			priv(dev)->adc_control1_bits |= adc_mode_bits(8);	// mode 8.  What else could you need?
++			priv(dev)->adc_control1_bits |= adc_mode_bits(8);	/*  mode 8.  What else could you need? */
+ 	} else {
+ 		priv(dev)->adc_control1_bits &= ~CHANNEL_MODE_4020_MASK;
+ 		if (cmd->chanlist_len == 4)
+@@ -2735,20 +2735,20 @@ static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	DEBUG_PRINT("control1 bits 0x%x\n", priv(dev)->adc_control1_bits);
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ 
+-	// clear adc buffer
++	/*  clear adc buffer */
+ 	writew(0, priv(dev)->main_iobase + ADC_BUFFER_CLEAR_REG);
+ 
+ 	if ((cmd->flags & TRIG_WAKE_EOS) == 0 ||
+ 		board(dev)->layout == LAYOUT_4020) {
+ 		priv(dev)->ai_dma_index = 0;
+ 
+-		// set dma transfer size
++		/*  set dma transfer size */
+ 		for (i = 0; i < ai_dma_ring_count(board(dev)); i++)
+ 			priv(dev)->ai_dma_desc[i].transfer_size =
+ 				cpu_to_le32(dma_transfer_size(dev) *
+ 				sizeof(uint16_t));
+ 
+-		// give location of first dma descriptor
++		/*  give location of first dma descriptor */
+ 		load_first_dma_descriptor(dev, 1,
+ 			priv(dev)->
+ 			ai_dma_desc_bus_addr | PLX_DESC_IN_PCI_BIT |
+@@ -2773,7 +2773,7 @@ static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	bits = ADC_ENABLE_BIT | ADC_SOFT_GATE_BITS | ADC_GATE_LEVEL_BIT;
+ 	if (cmd->flags & TRIG_WAKE_EOS)
+ 		bits |= ADC_DMA_DISABLE_BIT;
+-	// set start trigger
++	/*  set start trigger */
+ 	if (cmd->start_src == TRIG_EXT) {
+ 		bits |= ADC_START_TRIG_EXT_BITS;
+ 		if (cmd->start_arg & CR_INVERT)
+@@ -2789,7 +2789,7 @@ static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ 
+-	// start aquisition
++	/*  start aquisition */
+ 	if (cmd->start_src == TRIG_NOW) {
+ 		writew(0, priv(dev)->main_iobase + ADC_START_REG);
+ 		DEBUG_PRINT("soft trig\n");
+@@ -2798,7 +2798,7 @@ static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-// read num_samples from 16 bit wide ai fifo
++/* read num_samples from 16 bit wide ai fifo */
+ static void pio_drain_ai_fifo_16(struct comedi_device * dev)
+ {
+ 	struct comedi_subdevice *s = dev->read_subdev;
+@@ -2810,7 +2810,7 @@ static void pio_drain_ai_fifo_16(struct comedi_device * dev)
+ 	int num_samples;
+ 
+ 	do {
+-		// get least significant 15 bits
++		/*  get least significant 15 bits */
+ 		read_index =
+ 			readw(priv(dev)->main_iobase +
+ 			ADC_READ_PNTR_REG) & 0x7fff;
+@@ -2899,7 +2899,7 @@ static void pio_drain_ai_fifo_32(struct comedi_device * dev)
+ 	priv(dev)->ai_count -= i;
+ }
+ 
+-// empty fifo
++/* empty fifo */
+ static void pio_drain_ai_fifo(struct comedi_device * dev)
+ {
+ 	if (board(dev)->layout == LAYOUT_4020) {
+@@ -2923,7 +2923,7 @@ static void drain_dma_buffers(struct comedi_device * dev, unsigned int channel)
+ 		pci_addr_reg =
+ 			priv(dev)->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG;
+ 
+-	// loop until we have read all the full buffers
++	/*  loop until we have read all the full buffers */
+ 	for (j = 0, next_transfer_addr = readl(pci_addr_reg);
+ 		(next_transfer_addr <
+ 			priv(dev)->ai_buffer_bus_addr[priv(dev)->ai_dma_index]
+@@ -2931,7 +2931,7 @@ static void drain_dma_buffers(struct comedi_device * dev, unsigned int channel)
+ 			priv(dev)->ai_buffer_bus_addr[priv(dev)->ai_dma_index] +
+ 			DMA_BUFFER_SIZE) && j < ai_dma_ring_count(board(dev));
+ 		j++) {
+-		// transfer data from dma buffer to comedi buffer
++		/*  transfer data from dma buffer to comedi buffer */
+ 		num_samples = dma_transfer_size(dev);
+ 		if (async->cmd.stop_src == TRIG_COUNT) {
+ 			if (num_samples > priv(dev)->ai_count)
+@@ -2963,15 +2963,15 @@ void handle_ai_interrupt(struct comedi_device * dev, unsigned short status,
+ 	uint8_t dma1_status;
+ 	unsigned long flags;
+ 
+-	// check for fifo overrun
++	/*  check for fifo overrun */
+ 	if (status & ADC_OVERRUN_BIT) {
+ 		comedi_error(dev, "fifo overrun");
+ 		async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
+ 	}
+-	// spin lock makes sure noone else changes plx dma control reg
++	/*  spin lock makes sure noone else changes plx dma control reg */
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 	dma1_status = readb(priv(dev)->plx9080_iobase + PLX_DMA1_CS_REG);
+-	if (plx_status & ICS_DMA1_A) {	// dma chan 1 interrupt
++	if (plx_status & ICS_DMA1_A) {	/*  dma chan 1 interrupt */
+ 		writeb((dma1_status & PLX_DMA_EN_BIT) | PLX_CLEAR_DMA_INTR_BIT,
+ 			priv(dev)->plx9080_iobase + PLX_DMA1_CS_REG);
+ 		DEBUG_PRINT("dma1 status 0x%x\n", dma1_status);
+@@ -2986,7 +2986,7 @@ void handle_ai_interrupt(struct comedi_device * dev, unsigned short status,
+ 	if (status & ADC_DONE_BIT)
+ 		DEBUG_PRINT("adc done interrupt\n");
+ 
+-	// drain fifo with pio
++	/*  drain fifo with pio */
+ 	if ((status & ADC_DONE_BIT) ||
+ 		((cmd->flags & TRIG_WAKE_EOS) &&
+ 			(status & ADC_INTR_PENDING_BIT) &&
+@@ -2999,7 +2999,7 @@ void handle_ai_interrupt(struct comedi_device * dev, unsigned short status,
+ 		} else
+ 			comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ 	}
+-	// if we are have all the data, then quit
++	/*  if we are have all the data, then quit */
+ 	if ((cmd->stop_src == TRIG_COUNT && priv(dev)->ai_count <= 0) ||
+ 		(cmd->stop_src == TRIG_EXT && (status & ADC_STOP_BIT))) {
+ 		async->events |= COMEDI_CB_EOA;
+@@ -3091,10 +3091,10 @@ static void handle_ao_interrupt(struct comedi_device * dev, unsigned short statu
+ 	async = s->async;
+ 	cmd = &async->cmd;
+ 
+-	// spin lock makes sure noone else changes plx dma control reg
++	/*  spin lock makes sure noone else changes plx dma control reg */
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 	dma0_status = readb(priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG);
+-	if (plx_status & ICS_DMA0_A) {	// dma chan 0 interrupt
++	if (plx_status & ICS_DMA0_A) {	/*  dma chan 0 interrupt */
+ 		if ((dma0_status & PLX_DMA_EN_BIT)
+ 			&& !(dma0_status & PLX_DMA_DONE_BIT))
+ 			writeb(PLX_DMA_EN_BIT | PLX_CLEAR_DMA_INTR_BIT,
+@@ -3152,8 +3152,8 @@ static irqreturn_t handle_interrupt(int irq, void *d PT_REGS_ARG)
+ 	handle_ai_interrupt(dev, status, plx_status);
+ 	handle_ao_interrupt(dev, status, plx_status);
+ 
+-	// clear possible plx9080 interrupt sources
+-	if (plx_status & ICS_LDIA) {	// clear local doorbell interrupt
++	/*  clear possible plx9080 interrupt sources */
++	if (plx_status & ICS_LDIA) {	/*  clear local doorbell interrupt */
+ 		plx_bits = readl(priv(dev)->plx9080_iobase + PLX_DBR_OUT_REG);
+ 		writel(plx_bits, priv(dev)->plx9080_iobase + PLX_DBR_OUT_REG);
+ 		DEBUG_PRINT(" cleared local doorbell bits 0x%x\n", plx_bits);
+@@ -3168,7 +3168,7 @@ void abort_dma(struct comedi_device * dev, unsigned int channel)
+ {
+ 	unsigned long flags;
+ 
+-	// spinlock for plx dma control/status reg
++	/*  spinlock for plx dma control/status reg */
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 
+ 	plx9080_abort_dma(priv(dev)->plx9080_iobase, channel);
+@@ -3202,15 +3202,15 @@ static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	int range = CR_RANGE(insn->chanspec);
+ 
+-	// do some initializing
++	/*  do some initializing */
+ 	writew(0, priv(dev)->main_iobase + DAC_CONTROL0_REG);
+ 
+-	// set range
++	/*  set range */
+ 	set_dac_range_bits(dev, &priv(dev)->dac_control1_bits, chan, range);
+ 	writew(priv(dev)->dac_control1_bits,
+ 		priv(dev)->main_iobase + DAC_CONTROL1_REG);
+ 
+-	// write to channel
++	/*  write to channel */
+ 	if (board(dev)->layout == LAYOUT_4020) {
+ 		writew(data[0] & 0xff,
+ 			priv(dev)->main_iobase + dac_lsb_4020_reg(chan));
+@@ -3220,7 +3220,7 @@ static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 		writew(data[0], priv(dev)->main_iobase + dac_convert_reg(chan));
+ 	}
+ 
+-	// remember output value
++	/*  remember output value */
+ 	priv(dev)->ao_value[chan] = data[0];
+ 
+ 	return 1;
+@@ -3503,14 +3503,14 @@ static int ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 
+ 	/* step 2: make sure trigger sources are unique and mutually compatible */
+ 
+-	// uniqueness check
++	/*  uniqueness check */
+ 	if (cmd->start_src != TRIG_INT && cmd->start_src != TRIG_EXT)
+ 		err++;
+ 	if (cmd->scan_begin_src != TRIG_TIMER &&
+ 		cmd->scan_begin_src != TRIG_EXT)
+ 		err++;
+ 
+-	// compatibility check
++	/*  compatibility check */
+ 	if (cmd->convert_src == TRIG_EXT && cmd->scan_begin_src == TRIG_TIMER)
+ 		err++;
+ 	if (cmd->stop_src != TRIG_COUNT &&
+@@ -3624,9 +3624,9 @@ static int do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] &= 0xf;
+-	// zero bits we are going to change
++	/*  zero bits we are going to change */
+ 	s->state &= ~data[0];
+-	// set new bits
++	/*  set new bits */
+ 	s->state |= data[0] & data[1];
+ 
+ 	writeb(s->state, priv(dev)->dio_counter_iobase + DO_REG);
+@@ -3793,24 +3793,24 @@ static uint16_t read_eeprom(struct comedi_device * dev, uint8_t address)
+ 
+ 	comedi_udelay(eeprom_comedi_udelay);
+ 	priv(dev)->plx_control_bits &= ~CTL_EE_CLK & ~CTL_EE_CS;
+-	// make sure we don't send anything to the i2c bus on 4020
++	/*  make sure we don't send anything to the i2c bus on 4020 */
+ 	priv(dev)->plx_control_bits |= CTL_USERO;
+ 	writel(priv(dev)->plx_control_bits, plx_control_addr);
+-	// activate serial eeprom
++	/*  activate serial eeprom */
+ 	comedi_udelay(eeprom_comedi_udelay);
+ 	priv(dev)->plx_control_bits |= CTL_EE_CS;
+ 	writel(priv(dev)->plx_control_bits, plx_control_addr);
+ 
+-	// write read command and desired memory address
++	/*  write read command and desired memory address */
+ 	for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) {
+-		// set bit to be written
++		/*  set bit to be written */
+ 		comedi_udelay(eeprom_comedi_udelay);
+ 		if (bitstream & bit)
+ 			priv(dev)->plx_control_bits |= CTL_EE_W;
+ 		else
+ 			priv(dev)->plx_control_bits &= ~CTL_EE_W;
+ 		writel(priv(dev)->plx_control_bits, plx_control_addr);
+-		// clock in bit
++		/*  clock in bit */
+ 		comedi_udelay(eeprom_comedi_udelay);
+ 		priv(dev)->plx_control_bits |= CTL_EE_CLK;
+ 		writel(priv(dev)->plx_control_bits, plx_control_addr);
+@@ -3818,10 +3818,10 @@ static uint16_t read_eeprom(struct comedi_device * dev, uint8_t address)
+ 		priv(dev)->plx_control_bits &= ~CTL_EE_CLK;
+ 		writel(priv(dev)->plx_control_bits, plx_control_addr);
+ 	}
+-	// read back value from eeprom memory location
++	/*  read back value from eeprom memory location */
+ 	value = 0;
+ 	for (bit = 1 << (value_length - 1); bit; bit >>= 1) {
+-		// clock out bit
++		/*  clock out bit */
+ 		comedi_udelay(eeprom_comedi_udelay);
+ 		priv(dev)->plx_control_bits |= CTL_EE_CLK;
+ 		writel(priv(dev)->plx_control_bits, plx_control_addr);
+@@ -3833,7 +3833,7 @@ static uint16_t read_eeprom(struct comedi_device * dev, uint8_t address)
+ 			value |= bit;
+ 	}
+ 
+-	// deactivate eeprom serial input
++	/*  deactivate eeprom serial input */
+ 	comedi_udelay(eeprom_comedi_udelay);
+ 	priv(dev)->plx_control_bits &= ~CTL_EE_CS;
+ 	writel(priv(dev)->plx_control_bits, plx_control_addr);
+@@ -3880,7 +3880,7 @@ static void check_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd)
+ 	if (cmd->scan_begin_src == TRIG_TIMER) {
+ 		scan_divisor = get_divisor(cmd->scan_begin_arg, cmd->flags);
+ 		if (cmd->convert_src == TRIG_TIMER) {
+-			// XXX check for integer overflows
++			/*  XXX check for integer overflows */
+ 			min_scan_divisor = convert_divisor * cmd->chanlist_len;
+ 			max_scan_divisor =
+ 				(convert_divisor * cmd->chanlist_len - 1) +
+@@ -3926,7 +3926,7 @@ static unsigned int get_ao_divisor(unsigned int ns, unsigned int flags)
+ 	return get_divisor(ns, flags) - 2;
+ }
+ 
+-// adjusts the size of hardware fifo (which determines block size for dma xfers)
++/* adjusts the size of hardware fifo (which determines block size for dma xfers) */
+ static int set_ai_fifo_size(struct comedi_device * dev, unsigned int num_samples)
+ {
+ 	unsigned int num_fifo_entries;
+@@ -3947,7 +3947,7 @@ static int set_ai_fifo_size(struct comedi_device * dev, unsigned int num_samples
+ 	return num_samples;
+ }
+ 
+-// query length of fifo
++/* query length of fifo */
+ static unsigned int ai_fifo_size(struct comedi_device * dev)
+ {
+ 	return priv(dev)->ai_fifo_segment_length *
+@@ -3968,7 +3968,7 @@ static int set_ai_fifo_segment_length(struct comedi_device * dev,
+ 	if (num_entries > fifo->max_segment_length)
+ 		num_entries = fifo->max_segment_length;
+ 
+-	// 1 == 256 entries, 2 == 512 entries, etc
++	/*  1 == 256 entries, 2 == 512 entries, etc */
+ 	num_increments = (num_entries + increment_size / 2) / increment_size;
+ 
+ 	bits = (~(num_increments - 1)) & fifo->fifo_size_reg_mask;
+@@ -4037,14 +4037,14 @@ static int caldac_8800_write(struct comedi_device * dev, unsigned int address,
+ 	return 0;
+ }
+ 
+-// 4020 caldacs
++/* 4020 caldacs */
+ static int caldac_i2c_write(struct comedi_device * dev, unsigned int caldac_channel,
+ 	unsigned int value)
+ {
+ 	uint8_t serial_bytes[3];
+ 	uint8_t i2c_addr;
+ 	enum pointer_bits {
+-		// manual has gain and offset bits switched
++		/*  manual has gain and offset bits switched */
+ 		OFFSET_0_2 = 0x1,
+ 		GAIN_0_2 = 0x2,
+ 		OFFSET_1_3 = 0x4,
+@@ -4055,35 +4055,35 @@ static int caldac_i2c_write(struct comedi_device * dev, unsigned int caldac_chan
+ 	};
+ 
+ 	switch (caldac_channel) {
+-	case 0:		// chan 0 offset
++	case 0:		/*  chan 0 offset */
+ 		i2c_addr = CALDAC0_I2C_ADDR;
+ 		serial_bytes[0] = OFFSET_0_2;
+ 		break;
+-	case 1:		// chan 1 offset
++	case 1:		/*  chan 1 offset */
+ 		i2c_addr = CALDAC0_I2C_ADDR;
+ 		serial_bytes[0] = OFFSET_1_3;
+ 		break;
+-	case 2:		// chan 2 offset
++	case 2:		/*  chan 2 offset */
+ 		i2c_addr = CALDAC1_I2C_ADDR;
+ 		serial_bytes[0] = OFFSET_0_2;
+ 		break;
+-	case 3:		// chan 3 offset
++	case 3:		/*  chan 3 offset */
+ 		i2c_addr = CALDAC1_I2C_ADDR;
+ 		serial_bytes[0] = OFFSET_1_3;
+ 		break;
+-	case 4:		// chan 0 gain
++	case 4:		/*  chan 0 gain */
+ 		i2c_addr = CALDAC0_I2C_ADDR;
+ 		serial_bytes[0] = GAIN_0_2;
+ 		break;
+-	case 5:		// chan 1 gain
++	case 5:		/*  chan 1 gain */
+ 		i2c_addr = CALDAC0_I2C_ADDR;
+ 		serial_bytes[0] = GAIN_1_3;
+ 		break;
+-	case 6:		// chan 2 gain
++	case 6:		/*  chan 2 gain */
+ 		i2c_addr = CALDAC1_I2C_ADDR;
+ 		serial_bytes[0] = GAIN_0_2;
+ 		break;
+-	case 7:		// chan 3 gain
++	case 7:		/*  chan 3 gain */
+ 		i2c_addr = CALDAC1_I2C_ADDR;
+ 		serial_bytes[0] = GAIN_1_3;
+ 		break;
+@@ -4098,22 +4098,22 @@ static int caldac_i2c_write(struct comedi_device * dev, unsigned int caldac_chan
+ 	return 0;
+ }
+ 
+-// Their i2c requires a huge delay on setting clock or data high for some reason
++/* Their i2c requires a huge delay on setting clock or data high for some reason */
+ static const int i2c_high_comedi_udelay = 1000;
+ static const int i2c_low_comedi_udelay = 10;
+ 
+-// set i2c data line high or low
++/* set i2c data line high or low */
+ static void i2c_set_sda(struct comedi_device * dev, int state)
+ {
+ 	static const int data_bit = CTL_EE_W;
+ 	void *plx_control_addr = priv(dev)->plx9080_iobase + PLX_CONTROL_REG;
+ 
+ 	if (state) {
+-		// set data line high
++		/*  set data line high */
+ 		priv(dev)->plx_control_bits &= ~data_bit;
+ 		writel(priv(dev)->plx_control_bits, plx_control_addr);
+ 		comedi_udelay(i2c_high_comedi_udelay);
+-	} else			// set data line low
++	} else			/*  set data line low */
+ 	{
+ 		priv(dev)->plx_control_bits |= data_bit;
+ 		writel(priv(dev)->plx_control_bits, plx_control_addr);
+@@ -4121,18 +4121,18 @@ static void i2c_set_sda(struct comedi_device * dev, int state)
+ 	}
+ }
+ 
+-// set i2c clock line high or low
++/* set i2c clock line high or low */
+ static void i2c_set_scl(struct comedi_device * dev, int state)
+ {
+ 	static const int clock_bit = CTL_USERO;
+ 	void *plx_control_addr = priv(dev)->plx9080_iobase + PLX_CONTROL_REG;
+ 
+ 	if (state) {
+-		// set clock line high
++		/*  set clock line high */
+ 		priv(dev)->plx_control_bits &= ~clock_bit;
+ 		writel(priv(dev)->plx_control_bits, plx_control_addr);
+ 		comedi_udelay(i2c_high_comedi_udelay);
+-	} else			// set clock line low
++	} else			/*  set clock line low */
+ 	{
+ 		priv(dev)->plx_control_bits |= clock_bit;
+ 		writel(priv(dev)->plx_control_bits, plx_control_addr);
+@@ -4157,17 +4157,17 @@ static void i2c_write_byte(struct comedi_device * dev, uint8_t byte)
+ 	}
+ }
+ 
+-// we can't really read the lines, so fake it
++/* we can't really read the lines, so fake it */
+ static int i2c_read_ack(struct comedi_device * dev)
+ {
+ 	i2c_set_scl(dev, 0);
+ 	i2c_set_sda(dev, 1);
+ 	i2c_set_scl(dev, 1);
+ 
+-	return 0;		// return fake acknowledge bit
++	return 0;		/*  return fake acknowledge bit */
+ }
+ 
+-// send start bit
++/* send start bit */
+ static void i2c_start(struct comedi_device * dev)
+ {
+ 	i2c_set_scl(dev, 1);
+@@ -4175,7 +4175,7 @@ static void i2c_start(struct comedi_device * dev)
+ 	i2c_set_sda(dev, 0);
+ }
+ 
+-// send stop bit
++/* send stop bit */
+ static void i2c_stop(struct comedi_device * dev)
+ {
+ 	i2c_set_scl(dev, 0);
+@@ -4191,25 +4191,25 @@ static void i2c_write(struct comedi_device * dev, unsigned int address,
+ 	uint8_t bitstream;
+ 	static const int read_bit = 0x1;
+ 
+-//XXX need mutex to prevent simultaneous attempts to access eeprom and i2c bus
++/* XXX need mutex to prevent simultaneous attempts to access eeprom and i2c bus */
+ 
+-	// make sure we dont send anything to eeprom
++	/*  make sure we dont send anything to eeprom */
+ 	priv(dev)->plx_control_bits &= ~CTL_EE_CS;
+ 
+ 	i2c_stop(dev);
+ 	i2c_start(dev);
+ 
+-	// send address and write bit
++	/*  send address and write bit */
+ 	bitstream = (address << 1) & ~read_bit;
+ 	i2c_write_byte(dev, bitstream);
+ 
+-	// get acknowledge
++	/*  get acknowledge */
+ 	if (i2c_read_ack(dev) != 0) {
+ 		comedi_error(dev, "i2c write failed: no acknowledge");
+ 		i2c_stop(dev);
+ 		return;
+ 	}
+-	// write data bytes
++	/*  write data bytes */
+ 	for (i = 0; i < length; i++) {
+ 		i2c_write_byte(dev, data[i]);
+ 		if (i2c_read_ack(dev) != 0) {

commit 6a438139a8963839a9b14709286075b2e38cf9e0
+Author: Bill Pemberton 
+Date:   Fri Mar 27 11:30:34 2009 -0400
+
+    Staging: comedi: remove C99 comments in c6xdigio.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c
+index 2efffb14610d..c8ffddf4add4 100644
+--- a/drivers/staging/comedi/drivers/c6xdigio.c
++++ b/drivers/staging/comedi/drivers/c6xdigio.c
+@@ -77,7 +77,7 @@ struct pwmbitstype {
+ 	unsigned sb4:2;
+ };
+ union pwmcmdtype {
+-	unsigned cmd;		// assuming here that int is 32bit
++	unsigned cmd;		/*  assuming here that int is 32bit */
+ 	struct pwmbitstype bits;
+ };
+ struct encbitstype {
+@@ -110,7 +110,7 @@ static void C6X_pwmInit(unsigned long baseAddr)
+ {
+ 	int timeout = 0;
+ 
+-//printk("Inside C6X_pwmInit\n");
++/* printk("Inside C6X_pwmInit\n"); */
+ 
+ 	WriteByteToHwPort(baseAddr, 0x70);
+ 	while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0)
+@@ -148,7 +148,7 @@ static void C6X_pwmOutput(unsigned long baseAddr, unsigned channel, int value)
+ 	int timeout = 0;
+ 	unsigned tmp;
+ 
+-	//printk("Inside C6X_pwmOutput\n");
++	/* printk("Inside C6X_pwmOutput\n"); */
+ 
+ 	pwm.cmd = value;
+ 	if (pwm.cmd > 498)
+@@ -158,7 +158,7 @@ static void C6X_pwmOutput(unsigned long baseAddr, unsigned channel, int value)
+ 
+ 	if (channel == 0) {
+ 		ppcmd = 0x28;
+-	} else {		// if channel == 1
++	} else {		/*  if channel == 1 */
+ 		ppcmd = 0x30;
+ 	}			/* endif */
+ 
+@@ -216,7 +216,7 @@ static int C6X_encInput(unsigned long baseAddr, unsigned channel)
+ 	int timeout = 0;
+ 	int tmp;
+ 
+-	//printk("Inside C6X_encInput\n");
++	/* printk("Inside C6X_encInput\n"); */
+ 
+ 	enc.value = 0;
+ 	if (channel == 0) {
+@@ -311,7 +311,7 @@ static void C6X_encResetAll(unsigned long baseAddr)
+ {
+ 	unsigned timeout = 0;
+ 
+-//printk("Inside C6X_encResetAll\n");
++/* printk("Inside C6X_encResetAll\n"); */
+ 
+ 	WriteByteToHwPort(baseAddr, 0x68);
+ 	while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0)
+@@ -351,7 +351,7 @@ static int c6xdigio_pwmo_insn_write(struct comedi_device * dev,
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+-	//  printk("c6xdigio_pwmo_insn_write %x\n", insn->n);
++	/*   printk("c6xdigio_pwmo_insn_write %x\n", insn->n); */
+ 	for (i = 0; i < insn->n; i++) {
+ 		C6X_pwmOutput(dev->iobase, chan, data[i]);
+ 		/*    devpriv->ao_readback[chan] = data[i]; */
+@@ -359,32 +359,30 @@ static int c6xdigio_pwmo_insn_write(struct comedi_device * dev,
+ 	return i;
+ }
+ 
+-//static int c6xdigio_ei_init_insn_read(struct comedi_device *dev,
+-//                                 struct comedi_subdevice *s,
+-//                                 struct comedi_insn *insn,
+-//                                 unsigned int *data)
+-//{
+-//  printk("c6xdigio_ei_init_insn_read %x\n", insn->n);
+-//  return insn->n;
+-//}
+-
+-//static int c6xdigio_ei_init_insn_write(struct comedi_device *dev,
+-//                                 struct comedi_subdevice *s,
+-//                                 struct comedi_insn *insn,
+-//                                 unsigned int *data)
+-//{
+-//  int i;
+-//  int chan = CR_CHAN(insn->chanspec);
+-//
+-//  C6X_encResetAll( dev->iobase );
+-//
+-//  return insn->n;
+-//}
++/* static int c6xdigio_ei_init_insn_read(struct comedi_device *dev, */
++/* struct comedi_subdevice *s, */
++/* struct comedi_insn *insn, */
++/* unsigned int *data) */
++/* { */
++/* printk("c6xdigio_ei_init_insn_read %x\n", insn->n); */
++/* return insn->n; */
++/* } */
++
++/* static int c6xdigio_ei_init_insn_write(struct comedi_device *dev, */
++/* struct comedi_subdevice *s, */
++/* struct comedi_insn *insn, */
++/* unsigned int *data) */
++/* { */
++/* int i; */
++/* int chan = CR_CHAN(insn->chanspec); */
++/*  *//* C6X_encResetAll( dev->iobase ); */
++/*  *//* return insn->n; */
++/* } */
+ 
+ static int c6xdigio_ei_insn_read(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	//  printk("c6xdigio_ei__insn_read %x\n", insn->n);
++	/*   printk("c6xdigio_ei__insn_read %x\n", insn->n); */
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+@@ -398,16 +396,16 @@ static int c6xdigio_ei_insn_read(struct comedi_device * dev,
+ static void board_init(struct comedi_device * dev)
+ {
+ 
+-	//printk("Inside board_init\n");
++	/* printk("Inside board_init\n"); */
+ 
+ 	C6X_pwmInit(dev->iobase);
+ 	C6X_encResetAll(dev->iobase);
+ 
+ }
+ 
+-//static void board_halt(struct comedi_device *dev) {
+-//  C6X_pwmInit(dev->iobase);
+-//}
++/* static void board_halt(struct comedi_device *dev) { */
++/* C6X_pwmInit(dev->iobase); */
++/* } */
+ 
+ /*
+    options[0] - I/O port
+@@ -444,11 +442,11 @@ static int c6xdigio_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	dev->iobase = iobase;
+ 	dev->board_name = "c6xdigio";
+ 
+-	result = alloc_subdevices(dev, 2);	// 3 with encoder_init write
++	result = alloc_subdevices(dev, 2);	/*  3 with encoder_init write */
+ 	if (result < 0)
+ 		return result;
+ 
+-	// Make sure that PnP ports gets activated
++	/*  Make sure that PnP ports gets activated */
+ 	pnp_register_driver(&c6xdigio_pnp_driver);
+ 
+ 	irq = it->options[1];
+@@ -460,14 +458,14 @@ static int c6xdigio_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 
+ 	s = dev->subdevices + 0;
+ 	/* pwm output subdevice */
+-	s->type = COMEDI_SUBD_AO;	// Not sure what to put here
++	s->type = COMEDI_SUBD_AO;	/*  Not sure what to put here */
+ 	s->subdev_flags = SDF_WRITEABLE;
+ 	s->n_chan = 2;
+ 	/*      s->trig[0] = c6xdigio_pwmo; */
+ 	s->insn_read = c6xdigio_pwmo_insn_read;
+ 	s->insn_write = c6xdigio_pwmo_insn_write;
+ 	s->maxdata = 500;
+-	s->range_table = &range_bipolar10;	// A suitable lie
++	s->range_table = &range_bipolar10;	/*  A suitable lie */
+ 
+ 	s = dev->subdevices + 1;
+ 	/* encoder (counter) subdevice */
+@@ -479,19 +477,19 @@ static int c6xdigio_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	s->maxdata = 0xffffff;
+ 	s->range_table = &range_unknown;
+ 
+-	//          s = dev->subdevices + 2;
+-	//      /* pwm output subdevice */
+-	//      s->type = COMEDI_SUBD_COUNTER;  // Not sure what to put here
+-	//      s->subdev_flags = SDF_WRITEABLE;
+-	//      s->n_chan = 1;
+-	//      /* s->trig[0] = c6xdigio_ei_init; */
+-	//      s->insn_read = c6xdigio_ei_init_insn_read;
+-	//      s->insn_write = c6xdigio_ei_init_insn_write;
+-	//      s->maxdata = 0xFFFF;  // Really just a don't care
+-	//      s->range_table = &range_unknown; // Not sure what to put here
+-
+-	// I will call this init anyway but more than likely the DSP board will not be connect
+-	// when device driver is loaded.
++	/*           s = dev->subdevices + 2; */
++	      /* pwm output subdevice */
++	/*       s->type = COMEDI_SUBD_COUNTER;  // Not sure what to put here */
++	/*       s->subdev_flags = SDF_WRITEABLE; */
++	/*       s->n_chan = 1; */
++	/*       s->trig[0] = c6xdigio_ei_init; */
++	/*       s->insn_read = c6xdigio_ei_init_insn_read; */
++	/*       s->insn_write = c6xdigio_ei_init_insn_write; */
++	/*       s->maxdata = 0xFFFF;  // Really just a don't care */
++	/*       s->range_table = &range_unknown; // Not sure what to put here */
++
++	/*  I will call this init anyway but more than likely the DSP board will not be connect */
++	/*  when device driver is loaded. */
+ 	board_init(dev);
+ 
+ 	return 0;
+@@ -499,7 +497,7 @@ static int c6xdigio_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 
+ static int c6xdigio_detach(struct comedi_device * dev)
+ {
+-//  board_halt(dev);  // may not need this
++/* board_halt(dev);  may not need this */
+ 
+ 	printk("comedi%d: c6xdigio: remove\n", dev->minor);
+ 
+@@ -508,7 +506,7 @@ static int c6xdigio_detach(struct comedi_device * dev)
+ 	}
+ 	if (dev->irq) {
+ 		free_irq(dev->irq, dev);
+-	}			// Not using IRQ so I am not sure if I need this
++	}			/*  Not using IRQ so I am not sure if I need this */
+ 	pnp_unregister_driver(&c6xdigio_pnp_driver);
+ 
+ 	return 0;

commit d6d9bd32a02bd6da4ea3412f0b5131cc5a442399
+Author: Bill Pemberton 
+Date:   Fri Mar 27 11:30:28 2009 -0400
+
+    Staging: comedi: remove C99 comments in adv_pci1723.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
+index 81f7ee18c150..eb4bf1f47b30 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1723.c
++++ b/drivers/staging/comedi/drivers/adv_pci1723.c
+@@ -54,7 +54,7 @@ configures all channels in the same group.
+ 
+ #define ADVANTECH_VENDOR        0x13fe	/* Advantech PCI vendor ID */
+ 
+-// hardware types of the cards
++/* hardware types of the cards */
+ #define TYPE_PCI1723 0
+ 
+ #define IORANGE_1723  0x2A
+@@ -92,7 +92,7 @@ configures all channels in the same group.
+ 
+ #define PCI1723_SELECT_CALIBRATION 0x28	/* Select the calibration Ref_V */
+ 
+-//static unsigned short pci_list_builded=0;     /*=1 list of card is know */
++/* static unsigned short pci_list_builded=0;      =1 list of card is know */
+ 
+ static const struct comedi_lrange range_pci1723 = { 1, {
+ 			BIP_RANGE(10)
+@@ -104,14 +104,14 @@ static const struct comedi_lrange range_pci1723 = { 1, {
+  */
+ struct pci1723_board {
+ 	const char *name;
+-	int vendor_id;		// PCI vendor a device ID of card
++	int vendor_id;		/*  PCI vendor a device ID of card */
+ 	int device_id;
+ 	int iorange;
+ 	char cardtype;
+-	int n_aochan;		// num of D/A chans
+-	int n_diochan;		// num of DIO chans
+-	int ao_maxdata;		// resolution of D/A
+-	const struct comedi_lrange *rangelist_ao;	// rangelist for D/A
++	int n_aochan;		/*  num of D/A chans */
++	int n_diochan;		/*  num of DIO chans */
++	int ao_maxdata;		/*  resolution of D/A */
++	const struct comedi_lrange *rangelist_ao;	/*  rangelist for D/A */
+ };
+ 
+ static const struct pci1723_board boardtypes[] = {
+@@ -157,12 +157,12 @@ static struct comedi_driver driver_pci1723 = {
+ 
+ /* this structure is for data unique to this hardware driver. */
+ struct pci1723_private {
+-	int valid;		//card is usable;
++	int valid;		/* card is usable; */
+ 
+ 	struct pci_dev *pcidev;
+-	unsigned char da_range[8];	// D/A output range for each channel
++	unsigned char da_range[8];	/*  D/A output range for each channel */
+ 
+-	short ao_data[8];	// data output buffer
++	short ao_data[8];	/*  data output buffer */
+ };
+ 
+ /*the following macro to make it easy to
+@@ -180,22 +180,22 @@ static int pci1723_reset(struct comedi_device * dev)
+ 	int i;
+ 	DPRINTK("adv_pci1723 EDBG: BGN: pci1723_reset(...)\n");
+ 
+-	outw(0x01, dev->iobase + PCI1723_SYN_SET);	// set synchronous output mode
++	outw(0x01, dev->iobase + PCI1723_SYN_SET);	/*  set synchronous output mode */
+ 
+ 	for (i = 0; i < 8; i++) {
+-		// set all outputs to 0V
++		/*  set all outputs to 0V */
+ 		devpriv->ao_data[i] = 0x8000;
+ 		outw(devpriv->ao_data[i], dev->iobase + PCI1723_DA(i));
+-		// set all ranges to +/- 10V
++		/*  set all ranges to +/- 10V */
+ 		devpriv->da_range[i] = 0;
+ 		outw(((devpriv->da_range[i] << 4) | i),
+ 			PCI1723_RANGE_CALIBRATION_MODE);
+ 	}
+ 
+-	outw(0, dev->iobase + PCI1723_CHANGE_CHA_OUTPUT_TYPE_STROBE);	// update ranges
+-	outw(0, dev->iobase + PCI1723_SYN_STROBE);	// update outputs
++	outw(0, dev->iobase + PCI1723_CHANGE_CHA_OUTPUT_TYPE_STROBE);	/*  update ranges */
++	outw(0, dev->iobase + PCI1723_SYN_STROBE);	/*  update outputs */
+ 
+-	// set asynchronous output mode
++	/*  set asynchronous output mode */
+ 	outw(0, dev->iobase + PCI1723_SYN_SET);
+ 
+ 	DPRINTK("adv_pci1723 EDBG: END: pci1723_reset(...)\n");
+@@ -265,12 +265,12 @@ static int pci1723_dio_insn_config(struct comedi_device * dev, struct comedi_sub
+ 		return -EINVAL;
+ 	}
+ 
+-	// update hardware DIO mode
+-	dio_mode = 0x0000;	// low byte output, high byte output
++	/*  update hardware DIO mode */
++	dio_mode = 0x0000;	/*  low byte output, high byte output */
+ 	if ((s->io_bits & 0x00FF) == 0)
+-		dio_mode |= 0x0001;	// low byte input
++		dio_mode |= 0x0001;	/*  low byte input */
+ 	if ((s->io_bits & 0xFF00) == 0)
+-		dio_mode |= 0x0002;	// high byte input
++		dio_mode |= 0x0002;	/*  high byte input */
+ 	outw(dio_mode, dev->iobase + PCI1723_DIGITAL_IO_PORT_SET);
+ 	return 1;
+ }
+@@ -389,22 +389,22 @@ static int pci1723_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 		s->insn_write = pci1723_ao_write_winsn;
+ 		s->insn_read = pci1723_insn_read_ao;
+ 
+-		// read DIO config
++		/*  read DIO config */
+ 		switch (inw(dev->iobase + PCI1723_DIGITAL_IO_PORT_MODE) & 0x03) {
+-		case 0x00:	// low byte output, high byte output
++		case 0x00:	/*  low byte output, high byte output */
+ 			s->io_bits = 0xFFFF;
+ 			break;
+-		case 0x01:	// low byte input, high byte output
++		case 0x01:	/*  low byte input, high byte output */
+ 			s->io_bits = 0xFF00;
+ 			break;
+-		case 0x02:	// low byte output, high byte input
++		case 0x02:	/*  low byte output, high byte input */
+ 			s->io_bits = 0x00FF;
+ 			break;
+-		case 0x03:	// low byte input, high byte input
++		case 0x03:	/*  low byte input, high byte input */
+ 			s->io_bits = 0x0000;
+ 			break;
+ 		}
+-		// read DIO port state
++		/*  read DIO port state */
+ 		s->state = inw(dev->iobase + PCI1723_READ_DIGITAL_INPUT_DATA);
+ 
+ 		subdev++;

commit 0f04c356551f9ae55d9a0c5ea211699903cf1f93
+Author: Bill Pemberton 
+Date:   Fri Mar 27 11:30:23 2009 -0400
+
+    Staging: comedi: remove C99 comments in adl_pci9118.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
+index 278cf30cc4a3..9f0f9deafc3d 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9118.c
++++ b/drivers/staging/comedi/drivers/adl_pci9118.c
+@@ -107,7 +107,7 @@ Configuration options:
+ #define PCI9118_INTSRC	0x38	/* R:   interrupt reason register */
+ #define PCI9118_INTCTRL	0x38	/* W:   interrupt control register */
+ 
+-// bits from A/D control register (PCI9118_ADCNTRL)
++/* bits from A/D control register (PCI9118_ADCNTRL) */
+ #define AdControl_UniP	0x80	/* 1=bipolar, 0=unipolar */
+ #define AdControl_Diff	0x40	/* 1=differential, 0= single end inputs */
+ #define AdControl_SoftG	0x20	/* 1=8254 counter works, 0=counter stops */
+@@ -117,7 +117,7 @@ Configuration options:
+ #define AdControl_Int	0x02	/* 1=enable INT, 0=disable */
+ #define AdControl_Dma	0x01	/* 1=enable DMA, 0=disable */
+ 
+-// bits from A/D function register (PCI9118_ADFUNC)
++/* bits from A/D function register (PCI9118_ADFUNC) */
+ #define AdFunction_PDTrg	0x80	/* 1=positive, 0=negative digital trigger (only positive is correct) */
+ #define AdFunction_PETrg	0x40	/* 1=positive, 0=negative external trigger (only positive is correct) */
+ #define AdFunction_BSSH		0x20	/* 1=with sample&hold, 0=without */
+@@ -127,7 +127,7 @@ Configuration options:
+ #define AdFunction_AM		0x02	/* 1=about trigger mode, 0=not about trigger */
+ #define AdFunction_Start	0x01	/* 1=trigger start, 0=trigger stop */
+ 
+-// bits from A/D status register (PCI9118_ADSTAT)
++/* bits from A/D status register (PCI9118_ADSTAT) */
+ #define AdStatus_nFull	0x100	/* 0=FIFO full (fatal), 1=not full */
+ #define AdStatus_nHfull	0x080	/* 0=FIFO half full, 1=FIFO not half full */
+ #define AdStatus_nEpty	0x040	/* 0=FIFO empty, 1=FIFO not empty */
+@@ -138,8 +138,8 @@ Configuration options:
+ #define AdStatus_ADOR	0x002	/* 1=A/D overrun (fatal) */
+ #define AdStatus_ADrdy	0x001	/* 1=A/D already ready, 0=not ready */
+ 
+-// bits for interrupt reason and control (PCI9118_INTSRC, PCI9118_INTCTRL)
+-// 1=interrupt occur, enable source,  0=interrupt not occur, disable source
++/* bits for interrupt reason and control (PCI9118_INTSRC, PCI9118_INTCTRL) */
++/* 1=interrupt occur, enable source,  0=interrupt not occur, disable source */
+ #define Int_Timer	0x08	/* timer interrupt */
+ #define Int_About	0x04	/* about trigger complete */
+ #define Int_Hfull	0x02	/* A/D FIFO hlaf full */
+@@ -182,23 +182,23 @@ static int pci9118_attach(struct comedi_device * dev, struct comedi_devconfig *
+ static int pci9118_detach(struct comedi_device * dev);
+ 
+ struct boardtype {
+-	const char *name;	// board name
+-	int vendor_id;		// PCI vendor a device ID of card
++	const char *name;	/*  board name */
++	int vendor_id;		/*  PCI vendor a device ID of card */
+ 	int device_id;
+-	int iorange_amcc;	// iorange for own S5933 region
+-	int iorange_9118;	// pass thru card region size
+-	int n_aichan;		// num of A/D chans
+-	int n_aichand;		// num of A/D chans in diff mode
+-	int mux_aichan;		// num of A/D chans with external multiplexor
+-	int n_aichanlist;	// len of chanlist
+-	int n_aochan;		// num of D/A chans
+-	int ai_maxdata;		// resolution of A/D
+-	int ao_maxdata;		// resolution of D/A
+-	const struct comedi_lrange *rangelist_ai;	// rangelist for A/D
+-	const struct comedi_lrange *rangelist_ao;	// rangelist for D/A
+-	unsigned int ai_ns_min;	// max sample speed of card v ns
+-	unsigned int ai_pacer_min;	// minimal pacer value (c1*c2 or c1 in burst)
+-	int half_fifo_size;	// size of FIFO/2
++	int iorange_amcc;	/*  iorange for own S5933 region */
++	int iorange_9118;	/*  pass thru card region size */
++	int n_aichan;		/*  num of A/D chans */
++	int n_aichand;		/*  num of A/D chans in diff mode */
++	int mux_aichan;		/*  num of A/D chans with external multiplexor */
++	int n_aichanlist;	/*  len of chanlist */
++	int n_aochan;		/*  num of D/A chans */
++	int ai_maxdata;		/*  resolution of A/D */
++	int ao_maxdata;		/*  resolution of D/A */
++	const struct comedi_lrange *rangelist_ai;	/*  rangelist for A/D */
++	const struct comedi_lrange *rangelist_ao;	/*  rangelist for D/A */
++	unsigned int ai_ns_min;	/*  max sample speed of card v ns */
++	unsigned int ai_pacer_min;	/*  minimal pacer value (c1*c2 or c1 in burst) */
++	int half_fifo_size;	/*  size of FIFO/2 */
+ 
+ };
+ 
+@@ -242,63 +242,63 @@ static struct comedi_driver driver_pci9118 = {
+ COMEDI_PCI_INITCLEANUP(driver_pci9118, pci9118_pci_table);
+ 
+ struct pci9118_private {
+-	unsigned long iobase_a;	// base+size for AMCC chip
+-	unsigned int master;	// master capable
+-	struct pci_dev *pcidev;	// ptr to actual pcidev
+-	unsigned int usemux;	// we want to use external multiplexor!
++	unsigned long iobase_a;	/*  base+size for AMCC chip */
++	unsigned int master;	/*  master capable */
++	struct pci_dev *pcidev;	/*  ptr to actual pcidev */
++	unsigned int usemux;	/*  we want to use external multiplexor! */
+ #ifdef PCI9118_PARANOIDCHECK
+-	unsigned short chanlist[PCI9118_CHANLEN + 1];	// list of scaned channel
+-	unsigned char chanlistlen;	// number of scanlist
++	unsigned short chanlist[PCI9118_CHANLEN + 1];	/*  list of scaned channel */
++	unsigned char chanlistlen;	/*  number of scanlist */
+ #endif
+-	unsigned char AdControlReg;	// A/D control register
+-	unsigned char IntControlReg;	// Interrupt control register
+-	unsigned char AdFunctionReg;	// A/D function register
+-	char valid;		// driver is ok
+-	char ai_neverending;	// we do unlimited AI
+-	unsigned int i8254_osc_base;	// frequence of onboard oscilator
+-	unsigned int ai_do;	// what do AI? 0=nothing, 1 to 4 mode
+-	unsigned int ai_act_scan;	// how many scans we finished
+-	unsigned int ai_buf_ptr;	// data buffer ptr in samples
+-	unsigned int ai_n_chan;	// how many channels is measured
+-	unsigned int ai_n_scanlen;	// len of actual scanlist
+-	unsigned int ai_n_realscanlen;	// what we must transfer for one outgoing scan include front/back adds
+-	unsigned int ai_act_dmapos;	// position in actual real stream
+-	unsigned int ai_add_front;	// how many channels we must add before scan to satisfy S&H?
+-	unsigned int ai_add_back;	// how many channels we must add before scan to satisfy DMA?
+-	unsigned int *ai_chanlist;	// actaul chanlist
++	unsigned char AdControlReg;	/*  A/D control register */
++	unsigned char IntControlReg;	/*  Interrupt control register */
++	unsigned char AdFunctionReg;	/*  A/D function register */
++	char valid;		/*  driver is ok */
++	char ai_neverending;	/*  we do unlimited AI */
++	unsigned int i8254_osc_base;	/*  frequence of onboard oscilator */
++	unsigned int ai_do;	/*  what do AI? 0=nothing, 1 to 4 mode */
++	unsigned int ai_act_scan;	/*  how many scans we finished */
++	unsigned int ai_buf_ptr;	/*  data buffer ptr in samples */
++	unsigned int ai_n_chan;	/*  how many channels is measured */
++	unsigned int ai_n_scanlen;	/*  len of actual scanlist */
++	unsigned int ai_n_realscanlen;	/*  what we must transfer for one outgoing scan include front/back adds */
++	unsigned int ai_act_dmapos;	/*  position in actual real stream */
++	unsigned int ai_add_front;	/*  how many channels we must add before scan to satisfy S&H? */
++	unsigned int ai_add_back;	/*  how many channels we must add before scan to satisfy DMA? */
++	unsigned int *ai_chanlist;	/*  actaul chanlist */
+ 	unsigned int ai_timer1;
+ 	unsigned int ai_timer2;
+ 	unsigned int ai_flags;
+-	char ai12_startstop;	// measure can start/stop on external trigger
+-	unsigned int ai_divisor1, ai_divisor2;	// divisors for start of measure on external start
++	char ai12_startstop;	/*  measure can start/stop on external trigger */
++	unsigned int ai_divisor1, ai_divisor2;	/*  divisors for start of measure on external start */
+ 	unsigned int ai_data_len;
+ 	short *ai_data;
+-	short ao_data[2];	// data output buffer
+-	unsigned int ai_scans;	// number of scans to do
+-	char dma_doublebuf;	// we can use double buffring
+-	unsigned int dma_actbuf;	// which buffer is used now
+-	short *dmabuf_virt[2];	// pointers to begin of DMA buffer
+-	unsigned long dmabuf_hw[2];	// hw address of DMA buff
+-	unsigned int dmabuf_size[2];	// size of dma buffer in bytes
+-	unsigned int dmabuf_use_size[2];	// which size we may now used for transfer
+-	unsigned int dmabuf_used_size[2];	// which size was trully used
++	short ao_data[2];	/*  data output buffer */
++	unsigned int ai_scans;	/*  number of scans to do */
++	char dma_doublebuf;	/*  we can use double buffring */
++	unsigned int dma_actbuf;	/*  which buffer is used now */
++	short *dmabuf_virt[2];	/*  pointers to begin of DMA buffer */
++	unsigned long dmabuf_hw[2];	/*  hw address of DMA buff */
++	unsigned int dmabuf_size[2];	/*  size of dma buffer in bytes */
++	unsigned int dmabuf_use_size[2];	/*  which size we may now used for transfer */
++	unsigned int dmabuf_used_size[2];	/*  which size was trully used */
+ 	unsigned int dmabuf_panic_size[2];
+-	unsigned int dmabuf_samples[2];	// size in samples
+-	int dmabuf_pages[2];	// number of pages in buffer
+-	unsigned char cnt0_users;	// bit field of 8254 CNT0 users (0-unused, 1-AO, 2-DI, 3-DO)
+-	unsigned char exttrg_users;	// bit field of external trigger users (0-AI, 1-AO, 2-DI, 3-DO)
+-	unsigned int cnt0_divisor;	// actual CNT0 divisor
+-	void (*int_ai_func) (struct comedi_device *, struct comedi_subdevice *, unsigned short, unsigned int, unsigned short);	// ptr to actual interrupt AI function
+-	unsigned char ai16bits;	// =1 16 bit card
+-	unsigned char usedma;	// =1 use DMA transfer and not INT
+-	unsigned char useeoshandle;	// =1 change WAKE_EOS DMA transfer to fit on every second
+-	unsigned char usessh;	// =1 turn on S&H support
+-	int softsshdelay;	// >0 use software S&H, numer is requested delay in ns
+-	unsigned char softsshsample;	// polarity of S&H signal in sample state
+-	unsigned char softsshhold;	// polarity of S&H signal in hold state
+-	unsigned int ai_maskerr;	// which warning was printed
+-	unsigned int ai_maskharderr;	// on which error bits stops
+-	unsigned int ai_inttrig_start;	// TRIG_INT for start
++	unsigned int dmabuf_samples[2];	/*  size in samples */
++	int dmabuf_pages[2];	/*  number of pages in buffer */
++	unsigned char cnt0_users;	/*  bit field of 8254 CNT0 users (0-unused, 1-AO, 2-DI, 3-DO) */
++	unsigned char exttrg_users;	/*  bit field of external trigger users (0-AI, 1-AO, 2-DI, 3-DO) */
++	unsigned int cnt0_divisor;	/*  actual CNT0 divisor */
++	void (*int_ai_func) (struct comedi_device *, struct comedi_subdevice *, unsigned short, unsigned int, unsigned short);	/*  ptr to actual interrupt AI function */
++	unsigned char ai16bits;	/*  =1 16 bit card */
++	unsigned char usedma;	/*  =1 use DMA transfer and not INT */
++	unsigned char useeoshandle;	/*  =1 change WAKE_EOS DMA transfer to fit on every second */
++	unsigned char usessh;	/*  =1 turn on S&H support */
++	int softsshdelay;	/*  >0 use software S&H, numer is requested delay in ns */
++	unsigned char softsshsample;	/*  polarity of S&H signal in sample state */
++	unsigned char softsshhold;	/*  polarity of S&H signal in hold state */
++	unsigned int ai_maskerr;	/*  which warning was printed */
++	unsigned int ai_maskharderr;	/*  on which error bits stops */
++	unsigned int ai_inttrig_start;	/*  TRIG_INT for start */
+ };
+ 
+ #define devpriv ((struct pci9118_private *)dev->private)
+@@ -335,12 +335,12 @@ static int pci9118_insn_read_ai(struct comedi_device * dev, struct comedi_subdev
+ 
+ 	devpriv->AdControlReg = AdControl_Int & 0xff;
+ 	devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
+-	outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);	// positive triggers, no S&H, no burst, burst stop, no post trigger, no about trigger, trigger stop
++	outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);	/*  positive triggers, no S&H, no burst, burst stop, no post trigger, no about trigger, trigger stop */
+ 
+ 	if (!setup_channel_list(dev, s, 1, &insn->chanspec, 0, 0, 0, 0, 0))
+ 		return -EINVAL;
+ 
+-	outl(0, dev->iobase + PCI9118_DELFIFO);	// flush FIFO
++	outl(0, dev->iobase + PCI9118_DELFIFO);	/*  flush FIFO */
+ 
+ 	for (n = 0; n < insn->n; n++) {
+ 		outw(0, dev->iobase + PCI9118_SOFTTRG);	/* start conversion */
+@@ -354,7 +354,7 @@ static int pci9118_insn_read_ai(struct comedi_device * dev, struct comedi_subdev
+ 
+ 		comedi_error(dev, "A/D insn timeout");
+ 		data[n] = 0;
+-		outl(0, dev->iobase + PCI9118_DELFIFO);	// flush FIFO
++		outl(0, dev->iobase + PCI9118_DELFIFO);	/*  flush FIFO */
+ 		return -ETIME;
+ 
+ 	      conv_finish:
+@@ -369,7 +369,7 @@ static int pci9118_insn_read_ai(struct comedi_device * dev, struct comedi_subdev
+ 		}
+ 	}
+ 
+-	outl(0, dev->iobase + PCI9118_DELFIFO);	// flush FIFO
++	outl(0, dev->iobase + PCI9118_DELFIFO);	/*  flush FIFO */
+ 	return n;
+ 
+ }
+@@ -567,7 +567,7 @@ static void interrupt_pci9118_ai_onesample(struct comedi_device * dev,
+ 
+ #ifdef PCI9118_PARANOIDCHECK
+ 	if (devpriv->ai16bits == 0) {
+-		if ((sampl & 0x000f) != devpriv->chanlist[s->async->cur_chan]) {	// data dropout!
++		if ((sampl & 0x000f) != devpriv->chanlist[s->async->cur_chan]) {	/*  data dropout! */
+ 			rt_printk
+ 				("comedi: A/D  SAMPL - data dropout: received channel %d, expected %d!\n",
+ 				sampl & 0x000f,
+@@ -621,14 +621,14 @@ static void interrupt_pci9118_ai_dma(struct comedi_device * dev, struct comedi_s
+ 	}
+ 
+ 	if (int_adstat & devpriv->ai_maskerr)
+-//      if (int_adstat & 0x106)
++/* if (int_adstat & 0x106) */
+ 		if (pci9118_decode_error_status(dev, s, int_adstat))
+ 			return;
+ 
+-	samplesinbuf = devpriv->dmabuf_use_size[devpriv->dma_actbuf] >> 1;	// number of received real samples
+-//      DPRINTK("dma_actbuf=%d\n",devpriv->dma_actbuf);
++	samplesinbuf = devpriv->dmabuf_use_size[devpriv->dma_actbuf] >> 1;	/*  number of received real samples */
++/* DPRINTK("dma_actbuf=%d\n",devpriv->dma_actbuf); */
+ 
+-	if (devpriv->dma_doublebuf) {	// switch DMA buffers if is used double buffering
++	if (devpriv->dma_doublebuf) {	/*  switch DMA buffers if is used double buffering */
+ 		next_dma_buf = 1 - devpriv->dma_actbuf;
+ 		outl(devpriv->dmabuf_hw[next_dma_buf],
+ 			devpriv->iobase_a + AMCC_OP_REG_MWAR);
+@@ -641,15 +641,15 @@ static void interrupt_pci9118_ai_dma(struct comedi_device * dev, struct comedi_s
+ 	}
+ 
+ 	if (samplesinbuf) {
+-		m = devpriv->ai_data_len >> 1;	// how many samples is to end of buffer
+-//              DPRINTK("samps=%d m=%d %d %d\n",samplesinbuf,m,s->async->buf_int_count,s->async->buf_int_ptr);
++		m = devpriv->ai_data_len >> 1;	/*  how many samples is to end of buffer */
++/* DPRINTK("samps=%d m=%d %d %d\n",samplesinbuf,m,s->async->buf_int_count,s->async->buf_int_ptr); */
+ 		sampls = m;
+ 		move_block_from_dma(dev, s,
+ 			devpriv->dmabuf_virt[devpriv->dma_actbuf],
+ 			samplesinbuf);
+-		m = m - sampls;	// m= how many samples was transfered
++		m = m - sampls;	/*  m= how many samples was transfered */
+ 	}
+-//      DPRINTK("YYY\n");
++/* DPRINTK("YYY\n"); */
+ 
+ 	if (!devpriv->ai_neverending)
+ 		if (devpriv->ai_act_scan >= devpriv->ai_scans) {	/* all data sampled */
+@@ -657,9 +657,9 @@ static void interrupt_pci9118_ai_dma(struct comedi_device * dev, struct comedi_s
+ 			s->async->events |= COMEDI_CB_EOA;
+ 		}
+ 
+-	if (devpriv->dma_doublebuf) {	// switch dma buffers
++	if (devpriv->dma_doublebuf) {	/*  switch dma buffers */
+ 		devpriv->dma_actbuf = 1 - devpriv->dma_actbuf;
+-	} else {		// restart DMA if is not used double buffering
++	} else {		/*  restart DMA if is not used double buffering */
+ 		outl(devpriv->dmabuf_hw[0],
+ 			devpriv->iobase_a + AMCC_OP_REG_MWAR);
+ 		outl(devpriv->dmabuf_use_size[0],
+@@ -680,30 +680,30 @@ static irqreturn_t interrupt_pci9118(int irq, void *d PT_REGS_ARG)
+ 	unsigned int int_daq = 0, int_amcc, int_adstat;
+ 
+ 	if (!dev->attached)
+-		return IRQ_NONE;	// not fully initialized
++		return IRQ_NONE;	/*  not fully initialized */
+ 
+-	int_daq = inl(dev->iobase + PCI9118_INTSRC) & 0xf;	// get IRQ reasons from card
+-	int_amcc = inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR);	// get INT register from AMCC chip
++	int_daq = inl(dev->iobase + PCI9118_INTSRC) & 0xf;	/*  get IRQ reasons from card */
++	int_amcc = inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR);	/*  get INT register from AMCC chip */
+ 
+-//      DPRINTK("INT daq=0x%01x amcc=0x%08x MWAR=0x%08x MWTC=0x%08x ADSTAT=0x%02x ai_do=%d\n", int_daq, int_amcc, inl(devpriv->iobase_a+AMCC_OP_REG_MWAR), inl(devpriv->iobase_a+AMCC_OP_REG_MWTC), inw(dev->iobase+PCI9118_ADSTAT)&0x1ff,devpriv->ai_do);
++/* DPRINTK("INT daq=0x%01x amcc=0x%08x MWAR=0x%08x MWTC=0x%08x ADSTAT=0x%02x ai_do=%d\n", int_daq, int_amcc, inl(devpriv->iobase_a+AMCC_OP_REG_MWAR), inl(devpriv->iobase_a+AMCC_OP_REG_MWTC), inw(dev->iobase+PCI9118_ADSTAT)&0x1ff,devpriv->ai_do); */
+ 
+ 	if ((!int_daq) && (!(int_amcc & ANY_S593X_INT)))
+-		return IRQ_NONE;	// interrupt from other source
++		return IRQ_NONE;	/*  interrupt from other source */
+ 
+-	outl(int_amcc | 0x00ff0000, devpriv->iobase_a + AMCC_OP_REG_INTCSR);	// shutdown IRQ reasons in AMCC
++	outl(int_amcc | 0x00ff0000, devpriv->iobase_a + AMCC_OP_REG_INTCSR);	/*  shutdown IRQ reasons in AMCC */
+ 
+-	int_adstat = inw(dev->iobase + PCI9118_ADSTAT) & 0x1ff;	// get STATUS register
++	int_adstat = inw(dev->iobase + PCI9118_ADSTAT) & 0x1ff;	/*  get STATUS register */
+ 
+ 	if (devpriv->ai_do) {
+ 		if (devpriv->ai12_startstop)
+-			if ((int_adstat & AdStatus_DTH) && (int_daq & Int_DTrg)) {	// start stop of measure
++			if ((int_adstat & AdStatus_DTH) && (int_daq & Int_DTrg)) {	/*  start stop of measure */
+ 				if (devpriv->ai12_startstop & START_AI_EXT) {
+ 					devpriv->ai12_startstop &=
+ 						~START_AI_EXT;
+ 					if (!(devpriv->ai12_startstop &
+ 							STOP_AI_EXT))
+-						pci9118_exttrg_del(dev, EXTTRG_AI);	// deactivate EXT trigger
+-					start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1, devpriv->ai_divisor2);	// start pacer
++						pci9118_exttrg_del(dev, EXTTRG_AI);	/*  deactivate EXT trigger */
++					start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1, devpriv->ai_divisor2);	/*  start pacer */
+ 					outl(devpriv->AdControlReg,
+ 						dev->iobase + PCI9118_ADCNTRL);
+ 				} else {
+@@ -711,8 +711,8 @@ static irqreturn_t interrupt_pci9118(int irq, void *d PT_REGS_ARG)
+ 						ai12_startstop & STOP_AI_EXT) {
+ 						devpriv->ai12_startstop &=
+ 							~STOP_AI_EXT;
+-						pci9118_exttrg_del(dev, EXTTRG_AI);	// deactivate EXT trigger
+-						devpriv->ai_neverending = 0;	//well, on next interrupt from DMA/EOC measure will stop
++						pci9118_exttrg_del(dev, EXTTRG_AI);	/*  deactivate EXT trigger */
++						devpriv->ai_neverending = 0;	/* well, on next interrupt from DMA/EOC measure will stop */
+ 					}
+ 				}
+ 			}
+@@ -949,11 +949,11 @@ static int pci9118_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevic
+ 
+ 	if (cmd->scan_begin_src == TRIG_TIMER) {
+ 		tmp = cmd->scan_begin_arg;
+-//              rt_printk("S1 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg);
++/* rt_printk("S1 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
+ 		i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
+ 			&divisor2, &cmd->scan_begin_arg,
+ 			cmd->flags & TRIG_ROUND_MASK);
+-//              rt_printk("S2 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg);
++/* rt_printk("S2 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
+ 		if (cmd->scan_begin_arg < this_board->ai_ns_min)
+ 			cmd->scan_begin_arg = this_board->ai_ns_min;
+ 		if (tmp != cmd->scan_begin_arg)
+@@ -965,7 +965,7 @@ static int pci9118_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevic
+ 		i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
+ 			&divisor2, &cmd->convert_arg,
+ 			cmd->flags & TRIG_ROUND_MASK);
+-//              rt_printk("s1 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg);
++/* rt_printk("s1 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
+ 		if (cmd->convert_arg < this_board->ai_ns_min)
+ 			cmd->convert_arg = this_board->ai_ns_min;
+ 		if (tmp != cmd->convert_arg)
+@@ -979,7 +979,7 @@ static int pci9118_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevic
+ 					cmd->scan_begin_arg =
+ 						this_board->ai_ns_min *
+ 						(cmd->scan_end_arg + 2);
+-//              rt_printk("s2 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg);
++/* rt_printk("s2 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
+ 					err++;
+ 				}
+ 			} else {
+@@ -988,7 +988,7 @@ static int pci9118_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevic
+ 					cmd->scan_begin_arg =
+ 						cmd->convert_arg *
+ 						cmd->chanlist_len;
+-//              rt_printk("s3 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg);
++/* rt_printk("s3 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
+ 					err++;
+ 				}
+ 			}
+@@ -1001,7 +1001,7 @@ static int pci9118_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevic
+ 	if (cmd->chanlist)
+ 		if (!check_channel_list(dev, s, cmd->chanlist_len,
+ 				cmd->chanlist, 0, 0))
+-			return 5;	// incorrect channels list
++			return 5;	/*  incorrect channels list */
+ 
+ 	return 0;
+ }
+@@ -1018,26 +1018,26 @@ static int Compute_and_setup_dma(struct comedi_device * dev)
+ 	dmalen1 = devpriv->dmabuf_size[1];
+ 	DPRINTK("1 dmalen0=%d dmalen1=%d ai_data_len=%d\n", dmalen0, dmalen1,
+ 		devpriv->ai_data_len);
+-	// isn't output buff smaller that our DMA buff?
++	/*  isn't output buff smaller that our DMA buff? */
+ 	if (dmalen0 > (devpriv->ai_data_len)) {
+-		dmalen0 = devpriv->ai_data_len & ~3L;	// allign to 32bit down
++		dmalen0 = devpriv->ai_data_len & ~3L;	/*  allign to 32bit down */
+ 	}
+ 	if (dmalen1 > (devpriv->ai_data_len)) {
+-		dmalen1 = devpriv->ai_data_len & ~3L;	// allign to 32bit down
++		dmalen1 = devpriv->ai_data_len & ~3L;	/*  allign to 32bit down */
+ 	}
+ 	DPRINTK("2 dmalen0=%d dmalen1=%d \n", dmalen0, dmalen1);
+ 
+-	// we want wake up every scan?
++	/*  we want wake up every scan? */
+ 	if (devpriv->ai_flags & TRIG_WAKE_EOS) {
+ 		if (dmalen0 < (devpriv->ai_n_realscanlen << 1)) {
+-			// uff, too short DMA buffer, disable EOS support!
++			/*  uff, too short DMA buffer, disable EOS support! */
+ 			devpriv->ai_flags &= (~TRIG_WAKE_EOS);
+ 			rt_printk
+ 				("comedi%d: WAR: DMA0 buf too short, cann't support TRIG_WAKE_EOS (%d<%d)\n",
+ 				dev->minor, dmalen0,
+ 				devpriv->ai_n_realscanlen << 1);
+ 		} else {
+-			// short first DMA buffer to one scan
++			/*  short first DMA buffer to one scan */
+ 			dmalen0 = devpriv->ai_n_realscanlen << 1;
+ 			DPRINTK("21 dmalen0=%d ai_n_realscanlen=%d useeoshandle=%d\n", dmalen0, devpriv->ai_n_realscanlen, devpriv->useeoshandle);
+ 			if (devpriv->useeoshandle)
+@@ -1052,14 +1052,14 @@ static int Compute_and_setup_dma(struct comedi_device * dev)
+ 	}
+ 	if (devpriv->ai_flags & TRIG_WAKE_EOS) {
+ 		if (dmalen1 < (devpriv->ai_n_realscanlen << 1)) {
+-			// uff, too short DMA buffer, disable EOS support!
++			/*  uff, too short DMA buffer, disable EOS support! */
+ 			devpriv->ai_flags &= (~TRIG_WAKE_EOS);
+ 			rt_printk
+ 				("comedi%d: WAR: DMA1 buf too short, cann't support TRIG_WAKE_EOS (%d<%d)\n",
+ 				dev->minor, dmalen1,
+ 				devpriv->ai_n_realscanlen << 1);
+ 		} else {
+-			// short second DMA buffer to one scan
++			/*  short second DMA buffer to one scan */
+ 			dmalen1 = devpriv->ai_n_realscanlen << 1;
+ 			DPRINTK("22 dmalen1=%d ai_n_realscanlen=%d useeoshandle=%d\n", dmalen1, devpriv->ai_n_realscanlen, devpriv->useeoshandle);
+ 			if (devpriv->useeoshandle)
+@@ -1074,26 +1074,26 @@ static int Compute_and_setup_dma(struct comedi_device * dev)
+ 	}
+ 
+ 	DPRINTK("3 dmalen0=%d dmalen1=%d \n", dmalen0, dmalen1);
+-	// transfer without TRIG_WAKE_EOS
++	/*  transfer without TRIG_WAKE_EOS */
+ 	if (!(devpriv->ai_flags & TRIG_WAKE_EOS)) {
+-		// if it's possible then allign DMA buffers to length of scan
++		/*  if it's possible then allign DMA buffers to length of scan */
+ 		i = dmalen0;
+ 		dmalen0 =
+ 			(dmalen0 / (devpriv->ai_n_realscanlen << 1)) *
+ 			(devpriv->ai_n_realscanlen << 1);
+ 		dmalen0 &= ~3L;
+ 		if (!dmalen0)
+-			dmalen0 = i;	// uff. very long scan?
++			dmalen0 = i;	/*  uff. very long scan? */
+ 		i = dmalen1;
+ 		dmalen1 =
+ 			(dmalen1 / (devpriv->ai_n_realscanlen << 1)) *
+ 			(devpriv->ai_n_realscanlen << 1);
+ 		dmalen1 &= ~3L;
+ 		if (!dmalen1)
+-			dmalen1 = i;	// uff. very long scan?
+-		// if measure isn't neverending then test, if it whole fits into one or two DMA buffers
++			dmalen1 = i;	/*  uff. very long scan? */
++		/*  if measure isn't neverending then test, if it whole fits into one or two DMA buffers */
+ 		if (!devpriv->ai_neverending) {
+-			// fits whole measure into one DMA buffer?
++			/*  fits whole measure into one DMA buffer? */
+ 			if (dmalen0 >
+ 				((devpriv->ai_n_realscanlen << 1) *
+ 					devpriv->ai_scans)) {
+@@ -1104,7 +1104,7 @@ static int Compute_and_setup_dma(struct comedi_device * dev)
+ 				DPRINTK("3.1 dmalen0=%d dmalen1=%d \n", dmalen0,
+ 					dmalen1);
+ 				dmalen0 &= ~3L;
+-			} else {	// fits whole measure into two DMA buffer?
++			} else {	/*  fits whole measure into two DMA buffer? */
+ 				if (dmalen1 >
+ 					((devpriv->ai_n_realscanlen << 1) *
+ 						devpriv->ai_scans - dmalen0))
+@@ -1121,7 +1121,7 @@ static int Compute_and_setup_dma(struct comedi_device * dev)
+ 
+ 	DPRINTK("4 dmalen0=%d dmalen1=%d \n", dmalen0, dmalen1);
+ 
+-	// these DMA buffer size we'll be used
++	/*  these DMA buffer size we'll be used */
+ 	devpriv->dma_actbuf = 0;
+ 	devpriv->dmabuf_use_size[0] = dmalen0;
+ 	devpriv->dmabuf_use_size[1] = dmalen1;
+@@ -1143,18 +1143,18 @@ static int Compute_and_setup_dma(struct comedi_device * dev)
+ 	}
+ #endif
+ 
+-	outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS), devpriv->iobase_a + AMCC_OP_REG_MCSR);	// stop DMA
++	outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS), devpriv->iobase_a + AMCC_OP_REG_MCSR);	/*  stop DMA */
+ 	outl(devpriv->dmabuf_hw[0], devpriv->iobase_a + AMCC_OP_REG_MWAR);
+ 	outl(devpriv->dmabuf_use_size[0], devpriv->iobase_a + AMCC_OP_REG_MWTC);
+-	// init DMA transfer
++	/*  init DMA transfer */
+ 	outl(0x00000000 | AINT_WRITE_COMPL,
+ 		devpriv->iobase_a + AMCC_OP_REG_INTCSR);
+-//      outl(0x02000000|AINT_WRITE_COMPL, devpriv->iobase_a+AMCC_OP_REG_INTCSR);
++/* outl(0x02000000|AINT_WRITE_COMPL, devpriv->iobase_a+AMCC_OP_REG_INTCSR); */
+ 
+ 	outl(inl(devpriv->iobase_a +
+ 			AMCC_OP_REG_MCSR) | RESET_A2P_FLAGS | A2P_HI_PRIORITY |
+ 		EN_A2P_TRANSFERS, devpriv->iobase_a + AMCC_OP_REG_MCSR);
+-	outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | EN_A2P_TRANSFERS, devpriv->iobase_a + AMCC_OP_REG_INTCSR);	// allow bus mastering
++	outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | EN_A2P_TRANSFERS, devpriv->iobase_a + AMCC_OP_REG_INTCSR);	/*  allow bus mastering */
+ 
+ 	DPRINTK("adl_pci9118 EDBG: END: Compute_and_setup_dma()\n");
+ 	return 0;
+@@ -1186,17 +1186,17 @@ static int pci9118_ai_docmd_sampl(struct comedi_device * dev, struct comedi_subd
+ 		return -EIO;
+ 	};
+ 
+-	devpriv->int_ai_func = interrupt_pci9118_ai_onesample;	//transfer function
++	devpriv->int_ai_func = interrupt_pci9118_ai_onesample;	/* transfer function */
+ 
+ 	if (devpriv->ai12_startstop)
+-		pci9118_exttrg_add(dev, EXTTRG_AI);	// activate EXT trigger
++		pci9118_exttrg_add(dev, EXTTRG_AI);	/*  activate EXT trigger */
+ 
+ 	if ((devpriv->ai_do == 1) || (devpriv->ai_do == 2))
+ 		devpriv->IntControlReg |= Int_Timer;
+ 
+ 	devpriv->AdControlReg |= AdControl_Int;
+ 
+-	outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, devpriv->iobase_a + AMCC_OP_REG_INTCSR);	// allow INT in AMCC
++	outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, devpriv->iobase_a + AMCC_OP_REG_INTCSR);	/*  allow INT in AMCC */
+ 
+ 	if (!(devpriv->ai12_startstop & (START_AI_EXT | START_AI_INT))) {
+ 		outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
+@@ -1261,10 +1261,10 @@ static int pci9118_ai_docmd_dma(struct comedi_device * dev, struct comedi_subdev
+ 	};
+ 
+ 	if (devpriv->ai12_startstop) {
+-		pci9118_exttrg_add(dev, EXTTRG_AI);	// activate EXT trigger
++		pci9118_exttrg_add(dev, EXTTRG_AI);	/*  activate EXT trigger */
+ 	}
+ 
+-	devpriv->int_ai_func = interrupt_pci9118_ai_dma;	//transfer function
++	devpriv->int_ai_func = interrupt_pci9118_ai_dma;	/* transfer function */
+ 
+ 	outl(0x02000000 | AINT_WRITE_COMPL,
+ 		devpriv->iobase_a + AMCC_OP_REG_INTCSR);
+@@ -1307,7 +1307,7 @@ static int pci9118_ai_cmd(struct comedi_device * dev, struct comedi_subdevice *
+ 	devpriv->ai_add_back = 0;
+ 	devpriv->ai_maskerr = 0x10e;
+ 
+-	// prepare for start/stop conditions
++	/*  prepare for start/stop conditions */
+ 	if (cmd->start_src == TRIG_EXT)
+ 		devpriv->ai12_startstop |= START_AI_EXT;
+ 	if (cmd->stop_src == TRIG_EXT) {
+@@ -1334,19 +1334,19 @@ static int pci9118_ai_cmd(struct comedi_device * dev, struct comedi_subdevice *
+ 		devpriv->ai_scans = 0;
+ 	}
+ 
+-	// use sample&hold signal?
++	/*  use sample&hold signal? */
+ 	if (cmd->convert_src == TRIG_NOW) {
+ 		devpriv->usessh = 1;
+-	}			// yes
++	}			/*  yes */
+ 	else {
+ 		devpriv->usessh = 0;
+-	}			// no
++	}			/*  no */
+ 
+ 	DPRINTK("1 neverending=%d scans=%u usessh=%d ai_startstop=0x%2x\n",
+ 		devpriv->ai_neverending, devpriv->ai_scans, devpriv->usessh,
+ 		devpriv->ai12_startstop);
+ 
+-	// use additional sample at end of every scan to satisty DMA 32 bit transfer?
++	/*  use additional sample at end of every scan to satisty DMA 32 bit transfer? */
+ 	devpriv->ai_add_front = 0;
+ 	devpriv->ai_add_back = 0;
+ 	devpriv->useeoshandle = 0;
+@@ -1358,27 +1358,27 @@ static int pci9118_ai_cmd(struct comedi_device * dev, struct comedi_subdevice *
+ 				devpriv->ai_add_back = 1;
+ 			}
+ 			if (cmd->convert_src == TRIG_TIMER) {
+-				devpriv->usedma = 0;	// use INT transfer if scanlist have only one channel
++				devpriv->usedma = 0;	/*  use INT transfer if scanlist have only one channel */
+ 			}
+ 		}
+ 		if ((cmd->flags & TRIG_WAKE_EOS) &&
+ 			(devpriv->ai_n_scanlen & 1) &&
+ 			(devpriv->ai_n_scanlen > 1)) {
+ 			if (cmd->scan_begin_src == TRIG_FOLLOW) {
+-				//vpriv->useeoshandle=1; // change DMA transfer block to fit EOS on every second call
+-				devpriv->usedma = 0;	// XXX maybe can be corrected to use 16 bit DMA
+-			} else {	// well, we must insert one sample to end of EOS to meet 32 bit transfer
++				/* vpriv->useeoshandle=1; // change DMA transfer block to fit EOS on every second call */
++				devpriv->usedma = 0;	/*  XXX maybe can be corrected to use 16 bit DMA */
++			} else {	/*  well, we must insert one sample to end of EOS to meet 32 bit transfer */
+ 				devpriv->ai_add_back = 1;
+ 			}
+ 		}
+-	} else {		// interrupt transfer don't need any correction
++	} else {		/*  interrupt transfer don't need any correction */
+ 		devpriv->usedma = 0;
+ 	}
+ 
+-	// we need software S&H signal? It add  two samples before every scan as minimum
++	/*  we need software S&H signal? It add  two samples before every scan as minimum */
+ 	if (devpriv->usessh && devpriv->softsshdelay) {
+ 		devpriv->ai_add_front = 2;
+-		if ((devpriv->usedma == 1) && (devpriv->ai_add_back == 1)) {	// move it to front
++		if ((devpriv->usedma == 1) && (devpriv->ai_add_back == 1)) {	/*  move it to front */
+ 			devpriv->ai_add_front++;
+ 			devpriv->ai_add_back = 0;
+ 		}
+@@ -1387,17 +1387,17 @@ static int pci9118_ai_cmd(struct comedi_device * dev, struct comedi_subdevice *
+ 		addchans = devpriv->softsshdelay / cmd->convert_arg;
+ 		if (devpriv->softsshdelay % cmd->convert_arg)
+ 			addchans++;
+-		if (addchans > (devpriv->ai_add_front - 1)) {	// uff, still short :-(
++		if (addchans > (devpriv->ai_add_front - 1)) {	/*  uff, still short :-( */
+ 			devpriv->ai_add_front = addchans + 1;
+ 			if (devpriv->usedma == 1)
+ 				if ((devpriv->ai_add_front +
+ 						devpriv->ai_n_chan +
+ 						devpriv->ai_add_back) & 1)
+-					devpriv->ai_add_front++;	// round up to 32 bit
++					devpriv->ai_add_front++;	/*  round up to 32 bit */
+ 		}
+-	}			// well, we now know what must be all added
++	}			/*  well, we now know what must be all added */
+ 
+-	devpriv->ai_n_realscanlen =	// what we must take from card in real to have ai_n_scanlen on output?
++	devpriv->ai_n_realscanlen =	/*  what we must take from card in real to have ai_n_scanlen on output? */
+ 		(devpriv->ai_add_front + devpriv->ai_n_chan +
+ 		devpriv->ai_add_back) * (devpriv->ai_n_scanlen /
+ 		devpriv->ai_n_chan);
+@@ -1408,7 +1408,7 @@ static int pci9118_ai_cmd(struct comedi_device * dev, struct comedi_subdevice *
+ 		devpriv->ai_n_chan, devpriv->ai_add_back,
+ 		devpriv->ai_n_scanlen);
+ 
+-	// check and setup channel list
++	/*  check and setup channel list */
+ 	if (!check_channel_list(dev, s, devpriv->ai_n_chan,
+ 			devpriv->ai_chanlist, devpriv->ai_add_front,
+ 			devpriv->ai_add_back))
+@@ -1419,9 +1419,9 @@ static int pci9118_ai_cmd(struct comedi_device * dev, struct comedi_subdevice *
+ 			devpriv->useeoshandle))
+ 		return -EINVAL;
+ 
+-	// compute timers settings
+-	// simplest way, fr=4Mhz/(tim1*tim2), channel manipulation without timers effect
+-	if (((cmd->scan_begin_src == TRIG_FOLLOW) || (cmd->scan_begin_src == TRIG_EXT) || (cmd->scan_begin_src == TRIG_INT)) && (cmd->convert_src == TRIG_TIMER)) {	// both timer is used for one time
++	/*  compute timers settings */
++	/*  simplest way, fr=4Mhz/(tim1*tim2), channel manipulation without timers effect */
++	if (((cmd->scan_begin_src == TRIG_FOLLOW) || (cmd->scan_begin_src == TRIG_EXT) || (cmd->scan_begin_src == TRIG_INT)) && (cmd->convert_src == TRIG_TIMER)) {	/*  both timer is used for one time */
+ 		if (cmd->scan_begin_src == TRIG_EXT) {
+ 			devpriv->ai_do = 4;
+ 		} else {
+@@ -1435,7 +1435,7 @@ static int pci9118_ai_cmd(struct comedi_device * dev, struct comedi_subdevice *
+ 		devpriv->ai_timer2 = cmd->convert_arg;
+ 	}
+ 
+-	if ((cmd->scan_begin_src == TRIG_TIMER) && ((cmd->convert_src == TRIG_TIMER) || (cmd->convert_src == TRIG_NOW))) {	// double timed action
++	if ((cmd->scan_begin_src == TRIG_TIMER) && ((cmd->convert_src == TRIG_TIMER) || (cmd->convert_src == TRIG_NOW))) {	/*  double timed action */
+ 		if (!devpriv->usedma) {
+ 			comedi_error(dev,
+ 				"cmd->scan_begin_src=TRIG_TIMER works only with bus mastering!");
+@@ -1457,15 +1457,15 @@ static int pci9118_ai_cmd(struct comedi_device * dev, struct comedi_subdevice *
+ 		devpriv->ai_do = 3;
+ 	}
+ 
+-	start_pacer(dev, -1, 0, 0);	// stop pacer
++	start_pacer(dev, -1, 0, 0);	/*  stop pacer */
+ 
+-	devpriv->AdControlReg = 0;	// bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable DMA
++	devpriv->AdControlReg = 0;	/*  bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable DMA */
+ 	outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
+-	devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;	// positive triggers, no S&H, no burst, burst stop, no post trigger, no about trigger, trigger stop
++	devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;	/*  positive triggers, no S&H, no burst, burst stop, no post trigger, no about trigger, trigger stop */
+ 	outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
+ 	comedi_udelay(1);
+-	outl(0, dev->iobase + PCI9118_DELFIFO);	// flush FIFO
+-	inl(dev->iobase + PCI9118_ADSTAT);	// flush A/D and INT status register
++	outl(0, dev->iobase + PCI9118_DELFIFO);	/*  flush FIFO */
++	inl(dev->iobase + PCI9118_ADSTAT);	/*  flush A/D and INT status register */
+ 	inl(dev->iobase + PCI9118_INTSRC);
+ 
+ 	devpriv->ai_act_scan = 0;
+@@ -1505,11 +1505,11 @@ static int check_channel_list(struct comedi_device * dev, struct comedi_subdevic
+ 	}
+ 
+ 	if (CR_AREF(chanlist[0]) == AREF_DIFF)
+-		differencial = 1;	// all input must be diff
++		differencial = 1;	/*  all input must be diff */
+ 	if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
+-		bipolar = 1;	// all input must be bipolar
++		bipolar = 1;	/*  all input must be bipolar */
+ 	if (n_chan > 1)
+-		for (i = 1; i < n_chan; i++) {	// check S.E/diff
++		for (i = 1; i < n_chan; i++) {	/*  check S.E/diff */
+ 			if ((CR_AREF(chanlist[i]) == AREF_DIFF) !=
+ 				(differencial)) {
+ 				comedi_error(dev,
+@@ -1552,27 +1552,27 @@ static int setup_channel_list(struct comedi_device * dev, struct comedi_subdevic
+ 	}
+ 
+ 	if (CR_AREF(chanlist[0]) == AREF_DIFF)
+-		differencial = 1;	// all input must be diff
++		differencial = 1;	/*  all input must be diff */
+ 	if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
+-		bipolar = 1;	// all input must be bipolar
++		bipolar = 1;	/*  all input must be bipolar */
+ 
+-	// All is ok, so we can setup channel/range list
++	/*  All is ok, so we can setup channel/range list */
+ 
+ 	if (!bipolar) {
+-		devpriv->AdControlReg |= AdControl_UniP;	// set unibipolar
++		devpriv->AdControlReg |= AdControl_UniP;	/*  set unibipolar */
+ 	} else {
+-		devpriv->AdControlReg &= ((~AdControl_UniP) & 0xff);	// enable bipolar
++		devpriv->AdControlReg &= ((~AdControl_UniP) & 0xff);	/*  enable bipolar */
+ 	}
+ 
+ 	if (differencial) {
+-		devpriv->AdControlReg |= AdControl_Diff;	// enable diff inputs
++		devpriv->AdControlReg |= AdControl_Diff;	/*  enable diff inputs */
+ 	} else {
+-		devpriv->AdControlReg &= ((~AdControl_Diff) & 0xff);	// set single ended inputs
++		devpriv->AdControlReg &= ((~AdControl_Diff) & 0xff);	/*  set single ended inputs */
+ 	}
+ 
+-	outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);	// setup mode
++	outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);	/*  setup mode */
+ 
+-	outl(2, dev->iobase + PCI9118_SCANMOD);	// gods know why this sequence!
++	outl(2, dev->iobase + PCI9118_SCANMOD);	/*  gods know why this sequence! */
+ 	outl(0, dev->iobase + PCI9118_SCANMOD);
+ 	outl(1, dev->iobase + PCI9118_SCANMOD);
+ 
+@@ -1582,12 +1582,12 @@ static int setup_channel_list(struct comedi_device * dev, struct comedi_subdevic
+ 		devpriv->chanlist[i] = 0x55aa;
+ #endif
+ 
+-	if (frontadd) {		// insert channels for S&H
++	if (frontadd) {		/*  insert channels for S&H */
+ 		ssh = devpriv->softsshsample;
+ 		DPRINTK("FA: %04x: ", ssh);
+-		for (i = 0; i < frontadd; i++) {	// store range list to card
+-			scanquad = CR_CHAN(chanlist[0]);	// get channel number;
+-			gain = CR_RANGE(chanlist[0]);	// get gain number
++		for (i = 0; i < frontadd; i++) {	/*  store range list to card */
++			scanquad = CR_CHAN(chanlist[0]);	/*  get channel number; */
++			gain = CR_RANGE(chanlist[0]);	/*  get gain number */
+ 			scanquad |= ((gain & 0x03) << 8);
+ 			outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
+ 			DPRINTK("%02x ", scanquad | ssh);
+@@ -1597,23 +1597,23 @@ static int setup_channel_list(struct comedi_device * dev, struct comedi_subdevic
+ 	}
+ 
+ 	DPRINTK("SL: ", ssh);
+-	for (i = 0; i < n_chan; i++) {	// store range list to card
+-		scanquad = CR_CHAN(chanlist[i]);	// get channel number;
++	for (i = 0; i < n_chan; i++) {	/*  store range list to card */
++		scanquad = CR_CHAN(chanlist[i]);	/*  get channel number; */
+ #ifdef PCI9118_PARANOIDCHECK
+ 		devpriv->chanlist[i ^ usedma] = (scanquad & 0xf) << rot;
+ #endif
+-		gain = CR_RANGE(chanlist[i]);	// get gain number
++		gain = CR_RANGE(chanlist[i]);	/*  get gain number */
+ 		scanquad |= ((gain & 0x03) << 8);
+ 		outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
+ 		DPRINTK("%02x ", scanquad | ssh);
+ 	}
+ 	DPRINTK("\n ");
+ 
+-	if (backadd) {		// insert channels for fit onto 32bit DMA
++	if (backadd) {		/*  insert channels for fit onto 32bit DMA */
+ 		DPRINTK("BA: %04x: ", ssh);
+-		for (i = 0; i < backadd; i++) {	// store range list to card
+-			scanquad = CR_CHAN(chanlist[0]);	// get channel number;
+-			gain = CR_RANGE(chanlist[0]);	// get gain number
++		for (i = 0; i < backadd; i++) {	/*  store range list to card */
++			scanquad = CR_CHAN(chanlist[0]);	/*  get channel number; */
++			gain = CR_RANGE(chanlist[0]);	/*  get gain number */
+ 			scanquad |= ((gain & 0x03) << 8);
+ 			outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
+ 			DPRINTK("%02x ", scanquad | ssh);
+@@ -1621,13 +1621,13 @@ static int setup_channel_list(struct comedi_device * dev, struct comedi_subdevic
+ 		DPRINTK("\n ");
+ 	}
+ #ifdef PCI9118_PARANOIDCHECK
+-	devpriv->chanlist[n_chan ^ usedma] = devpriv->chanlist[0 ^ usedma];	// for 32bit oerations
++	devpriv->chanlist[n_chan ^ usedma] = devpriv->chanlist[0 ^ usedma];	/*  for 32bit oerations */
+ 	if (useeos) {
+-		for (i = 1; i < n_chan; i++) {	// store range list to card
++		for (i = 1; i < n_chan; i++) {	/*  store range list to card */
+ 			devpriv->chanlist[(n_chan + i) ^ usedma] =
+ 				(CR_CHAN(chanlist[i]) & 0xf) << rot;
+ 		}
+-		devpriv->chanlist[(2 * n_chan) ^ usedma] = devpriv->chanlist[0 ^ usedma];	// for 32bit oerations
++		devpriv->chanlist[(2 * n_chan) ^ usedma] = devpriv->chanlist[0 ^ usedma];	/*  for 32bit oerations */
+ 		useeos = 2;
+ 	} else {
+ 		useeos = 1;
+@@ -1640,11 +1640,11 @@ static int setup_channel_list(struct comedi_device * dev, struct comedi_subdevic
+ 	DPRINTK("\n ");
+ #endif
+ #endif
+-	outl(0, dev->iobase + PCI9118_SCANMOD);	// close scan queue
+-//      comedi_udelay(100);                             // important delay, or first sample will be cripled
++	outl(0, dev->iobase + PCI9118_SCANMOD);	/*  close scan queue */
++/* comedi_udelay(100);                               important delay, or first sample will be cripled */
+ 
+ 	DPRINTK("adl_pci9118 EDBG: END: setup_channel_list()\n");
+-	return 1;		// we can serve this with scan logic
++	return 1;		/*  we can serve this with scan logic */
+ }
+ 
+ /*
+@@ -1672,17 +1672,17 @@ static void pci9118_calc_divisors(char mode, struct comedi_device * dev,
+ 			*tim2 = this_board->ai_ns_min;
+ 		DPRINTK("1 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
+ 			*tim1, *tim2);
+-		*div1 = *tim2 / devpriv->i8254_osc_base;	// convert timer (burst)
++		*div1 = *tim2 / devpriv->i8254_osc_base;	/*  convert timer (burst) */
+ 		DPRINTK("2 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
+ 			*tim1, *tim2);
+ 		if (*div1 < this_board->ai_pacer_min)
+ 			*div1 = this_board->ai_pacer_min;
+ 		DPRINTK("3 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
+ 			*tim1, *tim2);
+-		*div2 = *tim1 / devpriv->i8254_osc_base;	// scan timer
++		*div2 = *tim1 / devpriv->i8254_osc_base;	/*  scan timer */
+ 		DPRINTK("4 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
+ 			*tim1, *tim2);
+-		*div2 = *div2 / *div1;	// major timer is c1*c2
++		*div2 = *div2 / *div1;	/*  major timer is c1*c2 */
+ 		DPRINTK("5 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
+ 			*tim1, *tim2);
+ 		if (*div2 < chans)
+@@ -1690,9 +1690,9 @@ static void pci9118_calc_divisors(char mode, struct comedi_device * dev,
+ 		DPRINTK("6 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
+ 			*tim1, *tim2);
+ 
+-		*tim2 = *div1 * devpriv->i8254_osc_base;	// real convert timer
++		*tim2 = *div1 * devpriv->i8254_osc_base;	/*  real convert timer */
+ 
+-		if (usessh & (chnsshfront == 0))	// use BSSH signal
++		if (usessh & (chnsshfront == 0))	/*  use BSSH signal */
+ 			if (*div2 < (chans + 2))
+ 				*div2 = chans + 2;
+ 
+@@ -1715,7 +1715,7 @@ static void start_pacer(struct comedi_device * dev, int mode, unsigned int divis
+ {
+ 	outl(0x74, dev->iobase + PCI9118_CNTCTRL);
+ 	outl(0xb4, dev->iobase + PCI9118_CNTCTRL);
+-//      outl(0x30, dev->iobase + PCI9118_CNTCTRL);
++/* outl(0x30, dev->iobase + PCI9118_CNTCTRL); */
+ 	comedi_udelay(1);
+ 
+ 	if ((mode == 1) || (mode == 2) || (mode == 4)) {
+@@ -1732,11 +1732,11 @@ static void start_pacer(struct comedi_device * dev, int mode, unsigned int divis
+ static int pci9118_exttrg_add(struct comedi_device * dev, unsigned char source)
+ {
+ 	if (source > 3)
+-		return -1;	// incorrect source
++		return -1;	/*  incorrect source */
+ 	devpriv->exttrg_users |= (1 << source);
+ 	devpriv->IntControlReg |= Int_DTrg;
+ 	outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
+-	outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, devpriv->iobase_a + AMCC_OP_REG_INTCSR);	// allow INT in AMCC
++	outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, devpriv->iobase_a + AMCC_OP_REG_INTCSR);	/*  allow INT in AMCC */
+ 	return 0;
+ }
+ 
+@@ -1746,12 +1746,12 @@ static int pci9118_exttrg_add(struct comedi_device * dev, unsigned char source)
+ static int pci9118_exttrg_del(struct comedi_device * dev, unsigned char source)
+ {
+ 	if (source > 3)
+-		return -1;	// incorrect source
++		return -1;	/*  incorrect source */
+ 	devpriv->exttrg_users &= ~(1 << source);
+-	if (!devpriv->exttrg_users) {	// shutdown ext trg intterrupts
++	if (!devpriv->exttrg_users) {	/*  shutdown ext trg intterrupts */
+ 		devpriv->IntControlReg &= ~Int_DTrg;
+-		if (!devpriv->IntControlReg)	// all IRQ disabled
+-			outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) & (~0x00001f00), devpriv->iobase_a + AMCC_OP_REG_INTCSR);	// disable int in AMCC
++		if (!devpriv->IntControlReg)	/*  all IRQ disabled */
++			outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) & (~0x00001f00), devpriv->iobase_a + AMCC_OP_REG_INTCSR);	/*  disable int in AMCC */
+ 		outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
+ 	}
+ 	return 0;
+@@ -1763,17 +1763,17 @@ static int pci9118_exttrg_del(struct comedi_device * dev, unsigned char source)
+ static int pci9118_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	if (devpriv->usedma)
+-		outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS), devpriv->iobase_a + AMCC_OP_REG_MCSR);	// stop DMA
++		outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS), devpriv->iobase_a + AMCC_OP_REG_MCSR);	/*  stop DMA */
+ 	pci9118_exttrg_del(dev, EXTTRG_AI);
+-	start_pacer(dev, 0, 0, 0);	// stop 8254 counters
++	start_pacer(dev, 0, 0, 0);	/*  stop 8254 counters */
+ 	devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
+-	outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);	// positive triggers, no S&H, no burst, burst stop, no post trigger, no about trigger, trigger stop
++	outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);	/*  positive triggers, no S&H, no burst, burst stop, no post trigger, no about trigger, trigger stop */
+ 	devpriv->AdControlReg = 0x00;
+-	outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);	// bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable INT and DMA
++	outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);	/*  bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable INT and DMA */
+ 	outl(0, dev->iobase + PCI9118_BURST);
+ 	outl(1, dev->iobase + PCI9118_SCANMOD);
+-	outl(2, dev->iobase + PCI9118_SCANMOD);	// reset scan queue
+-	outl(0, dev->iobase + PCI9118_DELFIFO);	// flush FIFO
++	outl(2, dev->iobase + PCI9118_SCANMOD);	/*  reset scan queue */
++	outl(0, dev->iobase + PCI9118_DELFIFO);	/*  flush FIFO */
+ 
+ 	devpriv->ai_do = 0;
+ 	devpriv->usedma = 0;
+@@ -1787,7 +1787,7 @@ static int pci9118_ai_cancel(struct comedi_device * dev, struct comedi_subdevice
+ 	devpriv->dma_actbuf = 0;
+ 
+ 	if (!devpriv->IntControlReg)
+-		outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, devpriv->iobase_a + AMCC_OP_REG_INTCSR);	// allow INT in AMCC
++		outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, devpriv->iobase_a + AMCC_OP_REG_INTCSR);	/*  allow INT in AMCC */
+ 
+ 	return 0;
+ }
+@@ -1800,31 +1800,31 @@ static int pci9118_reset(struct comedi_device * dev)
+ 	devpriv->IntControlReg = 0;
+ 	devpriv->exttrg_users = 0;
+ 	inl(dev->iobase + PCI9118_INTCTRL);
+-	outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);	// disable interrupts source
++	outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);	/*  disable interrupts source */
+ 	outl(0x30, dev->iobase + PCI9118_CNTCTRL);
+-//        outl(0xb4, dev->iobase + PCI9118_CNTCTRL);
+-	start_pacer(dev, 0, 0, 0);	// stop 8254 counters
++/* outl(0xb4, dev->iobase + PCI9118_CNTCTRL); */
++	start_pacer(dev, 0, 0, 0);	/*  stop 8254 counters */
+ 	devpriv->AdControlReg = 0;
+-	outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);	// bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable INT and DMA
++	outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);	/*  bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable INT and DMA */
+ 	outl(0, dev->iobase + PCI9118_BURST);
+ 	outl(1, dev->iobase + PCI9118_SCANMOD);
+-	outl(2, dev->iobase + PCI9118_SCANMOD);	// reset scan queue
++	outl(2, dev->iobase + PCI9118_SCANMOD);	/*  reset scan queue */
+ 	devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
+-	outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);	// positive triggers, no S&H, no burst, burst stop, no post trigger, no about trigger, trigger stop
++	outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);	/*  positive triggers, no S&H, no burst, burst stop, no post trigger, no about trigger, trigger stop */
+ 
+ 	devpriv->ao_data[0] = 2047;
+ 	devpriv->ao_data[1] = 2047;
+-	outl(devpriv->ao_data[0], dev->iobase + PCI9118_DA1);	// reset A/D outs to 0V
++	outl(devpriv->ao_data[0], dev->iobase + PCI9118_DA1);	/*  reset A/D outs to 0V */
+ 	outl(devpriv->ao_data[1], dev->iobase + PCI9118_DA2);
+-	outl(0, dev->iobase + PCI9118_DO);	// reset digi outs to L
++	outl(0, dev->iobase + PCI9118_DO);	/*  reset digi outs to L */
+ 	comedi_udelay(10);
+ 	inl(dev->iobase + PCI9118_AD_DATA);
+-	outl(0, dev->iobase + PCI9118_DELFIFO);	// flush FIFO
+-	outl(0, dev->iobase + PCI9118_INTSRC);	// remove INT requests
+-	inl(dev->iobase + PCI9118_ADSTAT);	// flush A/D status register
+-	inl(dev->iobase + PCI9118_INTSRC);	// flush INT requests
++	outl(0, dev->iobase + PCI9118_DELFIFO);	/*  flush FIFO */
++	outl(0, dev->iobase + PCI9118_INTSRC);	/*  remove INT requests */
++	inl(dev->iobase + PCI9118_ADSTAT);	/*  flush A/D status register */
++	inl(dev->iobase + PCI9118_INTSRC);	/*  flush INT requests */
+ 	devpriv->AdControlReg = 0;
+-	outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);	// bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable INT and DMA
++	outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);	/*  bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable INT and DMA */
+ 
+ 	devpriv->cnt0_users = 0;
+ 	devpriv->exttrg_users = 0;
+@@ -1854,7 +1854,7 @@ static int pci9118_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	opt_bus = it->options[0];
+ 	opt_slot = it->options[1];
+ 	if (it->options[3] & 1) {
+-		master = 0;	// user don't want use bus master
++		master = 0;	/*  user don't want use bus master */
+ 	} else {
+ 		master = 1;
+ 	}
+@@ -1920,7 +1920,7 @@ static int pci9118_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	pci9118_reset(dev);
+ 
+ 	if (it->options[3] & 2)
+-		irq = 0;	// user don't want use IRQ
++		irq = 0;	/*  user don't want use IRQ */
+ 	if (irq > 0) {
+ 		if (comedi_request_irq(irq, interrupt_pci9118, IRQF_SHARED,
+ 				"ADLink PCI-9118", dev)) {
+@@ -1936,7 +1936,7 @@ static int pci9118_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 
+ 	dev->irq = irq;
+ 
+-	if (master) {		// alloc DMA buffers
++	if (master) {		/*  alloc DMA buffers */
+ 		devpriv->dma_doublebuf = 0;
+ 		for (i = 0; i < 2; i++) {
+ 			for (pages = 4; pages >= 0; pages--)
+@@ -1974,16 +1974,16 @@ static int pci9118_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	if (it->options[2] > 0) {
+ 		devpriv->usemux = it->options[2];
+ 		if (devpriv->usemux > 256)
+-			devpriv->usemux = 256;	// max 256 channels!
++			devpriv->usemux = 256;	/*  max 256 channels! */
+ 		if (it->options[4] > 0)
+ 			if (devpriv->usemux > 128) {
+-				devpriv->usemux = 128;	// max 128 channels with softare S&H!
++				devpriv->usemux = 128;	/*  max 128 channels with softare S&H! */
+ 			}
+ 		rt_printk(", ext. mux %d channels", devpriv->usemux);
+ 	}
+ 
+ 	devpriv->softsshdelay = it->options[4];
+-	if (devpriv->softsshdelay < 0) {	// select sample&hold signal polarity
++	if (devpriv->softsshdelay < 0) {	/*  select sample&hold signal polarity */
+ 		devpriv->softsshdelay = -devpriv->softsshdelay;
+ 		devpriv->softsshsample = 0x80;
+ 		devpriv->softsshhold = 0x00;
+@@ -1995,7 +1995,7 @@ static int pci9118_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	rt_printk(".\n");
+ 
+ 	pci_read_config_word(devpriv->pcidev, PCI_COMMAND, &u16w);
+-	pci_write_config_word(devpriv->pcidev, PCI_COMMAND, u16w | 64);	// Enable parity check for parity error
++	pci_write_config_word(devpriv->pcidev, PCI_COMMAND, u16w | 64);	/*  Enable parity check for parity error */
+ 
+ 	if ((ret = alloc_subdevices(dev, 4)) < 0)
+ 		return ret;
+@@ -2052,9 +2052,9 @@ static int pci9118_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	s->insn_bits = pci9118_insn_bits_do;
+ 
+ 	devpriv->valid = 1;
+-	devpriv->i8254_osc_base = 250;	// 250ns=4MHz
+-	devpriv->ai_maskharderr = 0x10a;	// default measure crash condition
+-	if (it->options[5])	// disable some requested
++	devpriv->i8254_osc_base = 250;	/*  250ns=4MHz */
++	devpriv->ai_maskharderr = 0x10a;	/*  default measure crash condition */
++	if (it->options[5])	/*  disable some requested */
+ 		devpriv->ai_maskharderr &= ~it->options[5];
+ 
+ 	switch (this_board->ai_maxdata) {

commit 14458b19e51d434990d9a8c110ddeefd09678e64
+Author: Bill Pemberton 
+Date:   Fri Mar 27 11:30:18 2009 -0400
+
+    Staging: comedi: remove C99 comments in adl_pci6208.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c
+index f710f551820d..7e27f92a9e6d 100644
+--- a/drivers/staging/comedi/drivers/adl_pci6208.c
++++ b/drivers/staging/comedi/drivers/adl_pci6208.c
+@@ -61,35 +61,35 @@ struct pci6208_board {
+ 	const char *name;
+ 	unsigned short dev_id;	/* `lspci` will show you this */
+ 	int ao_chans;
+-	//int ao_bits;
++	/* int ao_bits; */
+ };
+ 
+ static const struct pci6208_board pci6208_boards[] = {
+ 	/*{
+ 	   name :  "pci6208v",
+-	   dev_id       :  0x6208,      //not sure
++	   dev_id       :  0x6208,      // not sure
+ 	   ao_chans:  8
+-	   //,  ao_bits :  16
++	   // ,  ao_bits :  16
+ 	   },
+ 	   {
+ 	   name :  "pci6216v",
+-	   dev_id       :  0x6208,      //not sure
++	   dev_id       :  0x6208,      // not sure
+ 	   ao_chans:  16
+-	   //,  ao_bits :  16
++	   // ,  ao_bits :  16
+ 	   }, */
+ 	{
+ 	      name:	"pci6208a",
+ 	      dev_id:	0x6208,
+ 	      ao_chans:8
+-			//,     ao_bits :  16
++			/* ,     ao_bits :  16 */
+ 		}
+ };
+ 
+ /* This is used by modprobe to translate PCI IDs to drivers.  Should
+  * only be used for PCI and ISA-PnP devices */
+ static DEFINE_PCI_DEVICE_TABLE(pci6208_pci_table) = {
+-	//{ PCI_VENDOR_ID_ADLINK, 0x6208, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+-	//{ PCI_VENDOR_ID_ADLINK, 0x6208, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
++	/* { PCI_VENDOR_ID_ADLINK, 0x6208, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, */
++	/* { PCI_VENDOR_ID_ADLINK, 0x6208, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, */
+ 	{PCI_VENDOR_ID_ADLINK, 0x6208, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ 	{0}
+ };
+@@ -132,10 +132,10 @@ static int pci6208_ao_winsn(struct comedi_device * dev, struct comedi_subdevice
+ 	struct comedi_insn * insn, unsigned int * data);
+ static int pci6208_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data);
+-//static int pci6208_dio_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s,
+-//      struct comedi_insn *insn,unsigned int *data);
+-//static int pci6208_dio_insn_config(struct comedi_device *dev,struct comedi_subdevice *s,
+-//      struct comedi_insn *insn,unsigned int *data);
++/* static int pci6208_dio_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, */
++/* struct comedi_insn *insn,unsigned int *data); */
++/* static int pci6208_dio_insn_config(struct comedi_device *dev,struct comedi_subdevice *s, */
++/* struct comedi_insn *insn,unsigned int *data); */
+ 
+ /*
+  * Attach is called by the Comedi core to configure the driver
+@@ -176,22 +176,22 @@ static int pci6208_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	s = dev->subdevices + 0;
+ 	/* analog output subdevice */
+ 	s->type = COMEDI_SUBD_AO;
+-	s->subdev_flags = SDF_WRITABLE;	//anything else to add here??
++	s->subdev_flags = SDF_WRITABLE;	/* anything else to add here?? */
+ 	s->n_chan = thisboard->ao_chans;
+-	s->maxdata = 0xffff;	//16-bit DAC
+-	s->range_table = &range_bipolar10;	//this needs to be checked.
++	s->maxdata = 0xffff;	/* 16-bit DAC */
++	s->range_table = &range_bipolar10;	/* this needs to be checked. */
+ 	s->insn_write = pci6208_ao_winsn;
+ 	s->insn_read = pci6208_ao_rinsn;
+ 
+-	//s=dev->subdevices+1;
++	/* s=dev->subdevices+1; */
+ 	/* digital i/o subdevice */
+-	//s->type=COMEDI_SUBD_DIO;
+-	//s->subdev_flags=SDF_READABLE|SDF_WRITABLE;
+-	//s->n_chan=16;
+-	//s->maxdata=1;
+-	//s->range_table=&range_digital;
+-	//s->insn_bits = pci6208_dio_insn_bits;
+-	//s->insn_config = pci6208_dio_insn_config;
++	/* s->type=COMEDI_SUBD_DIO; */
++	/* s->subdev_flags=SDF_READABLE|SDF_WRITABLE; */
++	/* s->n_chan=16; */
++	/* s->maxdata=1; */
++	/* s->range_table=&range_digital; */
++	/* s->insn_bits = pci6208_dio_insn_bits; */
++	/* s->insn_config = pci6208_dio_insn_config; */
+ 
+ 	printk("attached\n");
+ 
+@@ -262,49 +262,49 @@ static int pci6208_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice
+  * useful to applications if you implement the insn_bits interface.
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+-//static int pci6208_dio_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s,
+-//      struct comedi_insn *insn,unsigned int *data)
+-//{
+-//      if(insn->n!=2)return -EINVAL;
++/* static int pci6208_dio_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, */
++/* struct comedi_insn *insn,unsigned int *data) */
++/* { */
++/* if(insn->n!=2)return -EINVAL; */
+ 
+ 	/* The insn data is a mask in data[0] and the new data
+ 	 * in data[1], each channel cooresponding to a bit. */
+-//      if(data[0]){
+-//              s->state &= ~data[0];
+-//              s->state |= data[0]&data[1];
++/* if(data[0]){ */
++/* s->state &= ~data[0]; */
++/* s->state |= data[0]&data[1]; */
+ 		/* Write out the new digital output lines */
+-		//outw(s->state,dev->iobase + SKEL_DIO);
+-//      }
++		/* outw(s->state,dev->iobase + SKEL_DIO); */
++/* } */
+ 
+ 	/* on return, data[1] contains the value of the digital
+ 	 * input and output lines. */
+-	//data[1]=inw(dev->iobase + SKEL_DIO);
++	/* data[1]=inw(dev->iobase + SKEL_DIO); */
+ 	/* or we could just return the software copy of the output values if
+ 	 * it was a purely digital output subdevice */
+-	//data[1]=s->state;
++	/* data[1]=s->state; */
+ 
+-//      return 2;
+-//}
++/* return 2; */
++/* } */
+ 
+-//static int pci6208_dio_insn_config(struct comedi_device *dev,struct comedi_subdevice *s,
+-//      struct comedi_insn *insn,unsigned int *data)
+-//{
+-//      int chan=CR_CHAN(insn->chanspec);
++/* static int pci6208_dio_insn_config(struct comedi_device *dev,struct comedi_subdevice *s, */
++/* struct comedi_insn *insn,unsigned int *data) */
++/* { */
++/* int chan=CR_CHAN(insn->chanspec); */
+ 
+ 	/* The input or output configuration of each digital line is
+ 	 * configured by a special insn_config instruction.  chanspec
+ 	 * contains the channel to be changed, and data[0] contains the
+ 	 * value COMEDI_INPUT or COMEDI_OUTPUT. */
+ 
+-//      if(data[0]==COMEDI_OUTPUT){
+-//              s->io_bits |= 1<io_bits &= ~(1<io_bits,dev->iobase + SKEL_DIO_CONFIG);
++/* if(data[0]==COMEDI_OUTPUT){ */
++/* s->io_bits |= 1<io_bits &= ~(1<io_bits,dev->iobase + SKEL_DIO_CONFIG); */
+ 
+-//      return 1;
+-//}
++/* return 1; */
++/* } */
+ 
+ static int pci6208_find_device(struct comedi_device * dev, int bus, int slot)
+ {
+@@ -317,9 +317,9 @@ static int pci6208_find_device(struct comedi_device * dev, int bus, int slot)
+ 		if (pci_dev->vendor == PCI_VENDOR_ID_ADLINK) {
+ 			for (i = 0; i < pci6208_board_nbr; i++) {
+ 				if (pci6208_boards[i].dev_id == pci_dev->device) {
+-					// was a particular bus/slot requested?
++					/*  was a particular bus/slot requested? */
+ 					if ((bus != 0) || (slot != 0)) {
+-						// are we on the wrong bus/slot?
++						/*  are we on the wrong bus/slot? */
+ 						if (pci_dev->bus->number
+ 							!= bus ||
+ 							PCI_SLOT(pci_dev->devfn)
+@@ -346,10 +346,10 @@ static int pci6208_find_device(struct comedi_device * dev, int bus, int slot)
+ 		PCI_SLOT(pci_dev->devfn),
+ 		PCI_FUNC(pci_dev->devfn), pci_dev->irq);
+ 
+-	// TODO: Warn about non-tested boards.
+-	//switch(board->device_id)
+-	//{
+-	//};
++	/*  TODO: Warn about non-tested boards. */
++	/* switch(board->device_id) */
++	/* { */
++	/* }; */
+ 
+ 	devpriv->pci_dev = pci_dev;
+ 
+@@ -362,19 +362,19 @@ pci6208_pci_setup(struct pci_dev *pci_dev, unsigned long *io_base_ptr,
+ {
+ 	unsigned long io_base, io_range, lcr_io_base, lcr_io_range;
+ 
+-	// Enable PCI device and request regions
++	/*  Enable PCI device and request regions */
+ 	if (comedi_pci_enable(pci_dev, PCI6208_DRIVER_NAME) < 0) {
+ 		printk("comedi%d: Failed to enable PCI device and request regions\n", dev_minor);
+ 		return -EIO;
+ 	}
+-	// Read local configuration register base address [PCI_BASE_ADDRESS #1].
++	/*  Read local configuration register base address [PCI_BASE_ADDRESS #1]. */
+ 	lcr_io_base = pci_resource_start(pci_dev, 1);
+ 	lcr_io_range = pci_resource_len(pci_dev, 1);
+ 
+ 	printk("comedi%d: local config registers at address 0x%4lx [0x%4lx]\n",
+ 		dev_minor, lcr_io_base, lcr_io_range);
+ 
+-	// Read PCI6208 register base address [PCI_BASE_ADDRESS #2].
++	/*  Read PCI6208 register base address [PCI_BASE_ADDRESS #2]. */
+ 	io_base = pci_resource_start(pci_dev, 2);
+ 	io_range = pci_resource_end(pci_dev, 2) - io_base + 1;
+ 
+@@ -382,10 +382,10 @@ pci6208_pci_setup(struct pci_dev *pci_dev, unsigned long *io_base_ptr,
+ 		dev_minor, io_base, io_range);
+ 
+ 	*io_base_ptr = io_base;
+-	//devpriv->io_range = io_range;
+-	//devpriv->is_valid=0;
+-	//devpriv->lcr_io_base=lcr_io_base;
+-	//devpriv->lcr_io_range=lcr_io_range;
++	/* devpriv->io_range = io_range; */
++	/* devpriv->is_valid=0; */
++	/* devpriv->lcr_io_base=lcr_io_base; */
++	/* devpriv->lcr_io_range=lcr_io_range; */
+ 
+ 	return 0;
+ }

commit 1efd18f0cca7251a283625e07dbb4ec8e95a4b6b
+Author: Bill Pemberton 
+Date:   Fri Mar 27 11:30:12 2009 -0400
+
+    Staging: comedi: remove C99 comments in hwdrv_apci3120.c
+    
+    This replaces C99 comments with traditional C comments.  This
+    also removes 3 blocks of code that were already commented out.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+index f3556e0d52cb..4808acbebd8c 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+@@ -47,7 +47,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ #include "hwdrv_apci3120.h"
+ static unsigned int ui_Temp = 0;
+ 
+-// FUNCTION DEFINITIONS
++/* FUNCTION DEFINITIONS */
+ 
+ /*
+ +----------------------------------------------------------------------------+
+@@ -82,12 +82,12 @@ int i_APCI3120_InsnConfigAnalogInput(struct comedi_device * dev, struct comedi_s
+ 	if ((data[0] != APCI3120_EOC_MODE) && (data[0] != APCI3120_EOS_MODE))
+ 		return -1;
+ 
+-	// Check for Conversion time to be added ??
++	/*  Check for Conversion time to be added ?? */
+ 	devpriv->ui_EocEosConversionTime = data[2];
+ 
+ 	if (data[0] == APCI3120_EOS_MODE) {
+ 
+-		//Test the number of the channel
++		/* Test the number of the channel */
+ 		for (i = 0; i < data[3]; i++) {
+ 
+ 			if (CR_CHAN(data[4 + i]) >= this_board->i_NbrAiChannel) {
+@@ -102,14 +102,14 @@ int i_APCI3120_InsnConfigAnalogInput(struct comedi_device * dev, struct comedi_s
+ 			devpriv->b_EocEosInterrupt = APCI3120_ENABLE;
+ 		} else
+ 			devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
+-		// Copy channel list and Range List to devpriv
++		/*  Copy channel list and Range List to devpriv */
+ 
+ 		devpriv->ui_AiNbrofChannels = data[3];
+ 		for (i = 0; i < devpriv->ui_AiNbrofChannels; i++) {
+ 			devpriv->ui_AiChannelList[i] = data[4 + i];
+ 		}
+ 
+-	} else			// EOC
++	} else			/*  EOC */
+ 	{
+ 		devpriv->b_InterruptMode = APCI3120_EOC_MODE;
+ 		if (data[1]) {
+@@ -151,22 +151,22 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_sub
+ 	unsigned short us_ConvertTiming, us_TmpValue, i;
+ 	unsigned char b_Tmp;
+ 
+-	// fix convertion time to 10 us
++	/*  fix convertion time to 10 us */
+ 	if (!devpriv->ui_EocEosConversionTime) {
+ 		printk("No timer0 Value using 10 us\n");
+ 		us_ConvertTiming = 10;
+ 	} else
+-		us_ConvertTiming = (unsigned short) (devpriv->ui_EocEosConversionTime / 1000);	// nano to useconds
++		us_ConvertTiming = (unsigned short) (devpriv->ui_EocEosConversionTime / 1000);	/*  nano to useconds */
+ 
+-	// this_board->i_hwdrv_InsnReadAnalogInput(dev,us_ConvertTiming,insn->n,&insn->chanspec,data,insn->unused[0]);
++	/*  this_board->i_hwdrv_InsnReadAnalogInput(dev,us_ConvertTiming,insn->n,&insn->chanspec,data,insn->unused[0]); */
+ 
+-	// Clear software registers
++	/*  Clear software registers */
+ 	devpriv->b_TimerSelectMode = 0;
+ 	devpriv->b_ModeSelectRegister = 0;
+ 	devpriv->us_OutputRegister = 0;
+-//        devpriv->b_DigitalOutputRegister=0;
++/* devpriv->b_DigitalOutputRegister=0; */
+ 
+-	if (insn->unused[0] == 222)	// second insn read
++	if (insn->unused[0] == 222)	/*  second insn read */
+ 	{
+ 
+ 		for (i = 0; i < insn->n; i++) {
+@@ -174,14 +174,16 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_sub
+ 		}
+ 
+ 	} else {
+-		devpriv->tsk_Current = current;	// Save the current process task structure
+-		//Testing if board have the new Quartz and calculate the time value
+-		//to set in the timer
++		devpriv->tsk_Current = current;	/*  Save the current process task structure */
++/*
++ * Testing if board have the new Quartz and calculate the time value
++ * to set in the timer
++ */
+ 
+ 		us_TmpValue =
+ 			(unsigned short) inw(devpriv->iobase + APCI3120_RD_STATUS);
+ 
+-		//EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001
++		/* EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001 */
+ 		if ((us_TmpValue & 0x00B0) == 0x00B0
+ 			|| !strcmp(this_board->pc_DriverName, "apci3001")) {
+ 			us_ConvertTiming = (us_ConvertTiming * 2) - 2;
+@@ -196,19 +198,20 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_sub
+ 
+ 		case APCI3120_EOC_MODE:
+ 
+-			// Testing the interrupt flag and set the EOC bit
+-			// Clears the FIFO
++/*
++ * Testing the interrupt flag and set the EOC bit Clears the FIFO
++ */
+ 			inw(devpriv->iobase + APCI3120_RESET_FIFO);
+ 
+-			// Initialize the sequence array
++			/*  Initialize the sequence array */
+ 
+-			//if (!i_APCI3120_SetupChannelList(dev,s,1,chanlist,0))  return -EINVAL;
++			/* if (!i_APCI3120_SetupChannelList(dev,s,1,chanlist,0))  return -EINVAL; */
+ 
+ 			if (!i_APCI3120_SetupChannelList(dev, s, 1,
+ 					&insn->chanspec, 0))
+ 				return -EINVAL;
+ 
+-			//Initialize Timer 0 mode 4
++			/* Initialize Timer 0 mode 4 */
+ 			devpriv->b_TimerSelectMode =
+ 				(devpriv->
+ 				b_TimerSelectMode & 0xFC) |
+@@ -216,14 +219,14 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_sub
+ 			outb(devpriv->b_TimerSelectMode,
+ 				devpriv->iobase + APCI3120_TIMER_CRT1);
+ 
+-			// Reset the scan bit and Disables the  EOS, DMA, EOC interrupt
++			/*  Reset the scan bit and Disables the  EOS, DMA, EOC interrupt */
+ 			devpriv->b_ModeSelectRegister =
+ 				devpriv->
+ 				b_ModeSelectRegister & APCI3120_DISABLE_SCAN;
+ 
+ 			if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) {
+ 
+-				//Disables the EOS,DMA and enables the EOC interrupt
++				/* Disables the EOS,DMA and enables the EOC interrupt */
+ 				devpriv->b_ModeSelectRegister =
+ 					(devpriv->
+ 					b_ModeSelectRegister &
+@@ -241,7 +244,7 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_sub
+ 			outb(devpriv->b_ModeSelectRegister,
+ 				devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
+ 
+-			// Sets gate 0
++			/*  Sets gate 0 */
+ 			devpriv->us_OutputRegister =
+ 				(devpriv->
+ 				us_OutputRegister & APCI3120_CLEAR_PA_PR) |
+@@ -249,13 +252,13 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_sub
+ 			outw(devpriv->us_OutputRegister,
+ 				devpriv->iobase + APCI3120_WR_ADDRESS);
+ 
+-			// Select Timer 0
++			/*  Select Timer 0 */
+ 			b_Tmp = ((devpriv->
+ 					b_DigitalOutputRegister) & 0xF0) |
+ 				APCI3120_SELECT_TIMER_0_WORD;
+ 			outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
+ 
+-			//Set the convertion time
++			/* Set the convertion time */
+ 			outw(us_ConvertTiming,
+ 				devpriv->iobase + APCI3120_TIMER_VALUE);
+ 
+@@ -265,14 +268,14 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_sub
+ 			if (devpriv->b_EocEosInterrupt == APCI3120_DISABLE) {
+ 
+ 				do {
+-					// Waiting for the end of conversion
++					/*  Waiting for the end of conversion */
+ 					us_TmpValue =
+ 						inw(devpriv->iobase +
+ 						APCI3120_RD_STATUS);
+ 				} while ((us_TmpValue & APCI3120_EOC) ==
+ 					APCI3120_EOC);
+ 
+-				//Read the result in FIFO  and put it in insn data pointer
++				/* Read the result in FIFO  and put it in insn data pointer */
+ 				us_TmpValue = inw(devpriv->iobase + 0);
+ 				*data = us_TmpValue;
+ 
+@@ -284,9 +287,9 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_sub
+ 		case APCI3120_EOS_MODE:
+ 
+ 			inw(devpriv->iobase);
+-			// Clears the FIFO
++			/*  Clears the FIFO */
+ 			inw(devpriv->iobase + APCI3120_RESET_FIFO);
+-			// clear PA PR  and disable timer 0
++			/*  clear PA PR  and disable timer 0 */
+ 
+ 			devpriv->us_OutputRegister =
+ 				(devpriv->
+@@ -301,7 +304,7 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_sub
+ 					devpriv->ui_AiChannelList, 0))
+ 				return -EINVAL;
+ 
+-			//Initialize Timer 0 mode 2
++			/* Initialize Timer 0 mode 2 */
+ 			devpriv->b_TimerSelectMode =
+ 				(devpriv->
+ 				b_TimerSelectMode & 0xFC) |
+@@ -309,26 +312,26 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_sub
+ 			outb(devpriv->b_TimerSelectMode,
+ 				devpriv->iobase + APCI3120_TIMER_CRT1);
+ 
+-			//Select Timer 0
++			/* Select Timer 0 */
+ 			b_Tmp = ((devpriv->
+ 					b_DigitalOutputRegister) & 0xF0) |
+ 				APCI3120_SELECT_TIMER_0_WORD;
+ 			outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
+ 
+-			//Set the convertion time
++			/* Set the convertion time */
+ 			outw(us_ConvertTiming,
+ 				devpriv->iobase + APCI3120_TIMER_VALUE);
+ 
+-			//Set the scan bit
++			/* Set the scan bit */
+ 			devpriv->b_ModeSelectRegister =
+ 				devpriv->
+ 				b_ModeSelectRegister | APCI3120_ENABLE_SCAN;
+ 			outb(devpriv->b_ModeSelectRegister,
+ 				devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
+ 
+-			//If Interrupt function is loaded
++			/* If Interrupt function is loaded */
+ 			if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) {
+-				//Disables the EOC,DMA and enables the EOS interrupt
++				/* Disables the EOC,DMA and enables the EOS interrupt */
+ 				devpriv->b_ModeSelectRegister =
+ 					(devpriv->
+ 					b_ModeSelectRegister &
+@@ -347,7 +350,7 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_sub
+ 
+ 			inw(devpriv->iobase + APCI3120_RD_STATUS);
+ 
+-			//Sets gate 0
++			/* Sets gate 0 */
+ 
+ 			devpriv->us_OutputRegister =
+ 				devpriv->
+@@ -355,12 +358,12 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_sub
+ 			outw(devpriv->us_OutputRegister,
+ 				devpriv->iobase + APCI3120_WR_ADDRESS);
+ 
+-			//Start conversion
++			/* Start conversion */
+ 			outw(0, devpriv->iobase + APCI3120_START_CONVERSION);
+ 
+-			//Waiting of end of convertion if interrupt is not installed
++			/* Waiting of end of convertion if interrupt is not installed */
+ 			if (devpriv->b_EocEosInterrupt == APCI3120_DISABLE) {
+-				//Waiting the end of convertion
++				/* Waiting the end of convertion */
+ 				do {
+ 					us_TmpValue =
+ 						inw(devpriv->iobase +
+@@ -371,12 +374,12 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_sub
+ 
+ 				for (i = 0; i < devpriv->ui_AiNbrofChannels;
+ 					i++) {
+-					//Read the result in FIFO and write them in shared memory
++					/* Read the result in FIFO and write them in shared memory */
+ 					us_TmpValue = inw(devpriv->iobase);
+ 					data[i] = (unsigned int) us_TmpValue;
+ 				}
+ 
+-				devpriv->b_InterruptMode = APCI3120_EOC_MODE;	// Restore defaults.
++				devpriv->b_InterruptMode = APCI3120_EOC_MODE;	/*  Restore defaults. */
+ 			}
+ 			break;
+ 
+@@ -384,7 +387,7 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_sub
+ 			printk("inputs wrong\n");
+ 
+ 		}
+-		devpriv->ui_EocEosConversionTime = 0;	// re initializing the variable;
++		devpriv->ui_EocEosConversionTime = 0;	/*  re initializing the variable; */
+ 	}
+ 
+ 	return insn->n;
+@@ -411,36 +414,39 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_sub
+ 
+ int i_APCI3120_StopCyclicAcquisition(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	// Disable A2P Fifo write and AMWEN signal
++	/*  Disable A2P Fifo write and AMWEN signal */
+ 	outw(0, devpriv->i_IobaseAddon + 4);
+ 
+-	//Disable Bus Master ADD ON
++	/* Disable Bus Master ADD ON */
+ 	outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0);
+ 	outw(0, devpriv->i_IobaseAddon + 2);
+ 	outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0);
+ 	outw(0, devpriv->i_IobaseAddon + 2);
+ 
+-	//Disable BUS Master PCI
++	/* Disable BUS Master PCI */
+ 	outl(0, devpriv->i_IobaseAmcc + AMCC_OP_REG_MCSR);
+ 
+-	//outl(inl(devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR)&(~AINT_WRITE_COMPL), devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR);    // stop amcc irqs
+-	//outl(inl(devpriv->i_IobaseAmcc+AMCC_OP_REG_MCSR)&(~EN_A2P_TRANSFERS), devpriv->i_IobaseAmcc+AMCC_OP_REG_MCSR); // stop DMA
++	/* outl(inl(devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR)&(~AINT_WRITE_COMPL),
++	 * devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR);  stop amcc irqs */
++
++	/* outl(inl(devpriv->i_IobaseAmcc+AMCC_OP_REG_MCSR)&(~EN_A2P_TRANSFERS),
++	 * devpriv->i_IobaseAmcc+AMCC_OP_REG_MCSR);  stop DMA */
+ 
+-	//Disable ext trigger
++	/* Disable ext trigger */
+ 	i_APCI3120_ExttrigDisable(dev);
+ 
+ 	devpriv->us_OutputRegister = 0;
+-	//stop  counters
++	/* stop  counters */
+ 	outw(devpriv->
+ 		us_OutputRegister & APCI3120_DISABLE_TIMER0 &
+ 		APCI3120_DISABLE_TIMER1, dev->iobase + APCI3120_WR_ADDRESS);
+ 
+ 	outw(APCI3120_DISABLE_ALL_TIMER, dev->iobase + APCI3120_WR_ADDRESS);
+ 
+-	//DISABLE_ALL_INTERRUPT
++	/* DISABLE_ALL_INTERRUPT */
+ 	outb(APCI3120_DISABLE_ALL_INTERRUPT,
+ 		dev->iobase + APCI3120_WRITE_MODE_SELECT);
+-	//Flush FIFO
++	/* Flush FIFO */
+ 	inb(dev->iobase + APCI3120_RESET_FIFO);
+ 	inw(dev->iobase + APCI3120_RD_STATUS);
+ 	devpriv->ui_AiActualScan = 0;
+@@ -480,9 +486,9 @@ int i_APCI3120_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_
+ 	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+-	int tmp;		// divisor1,divisor2;
++	int tmp;		/*  divisor1,divisor2; */
+ 
+-	// step 1: make sure trigger sources are trivially valid
++	/*  step 1: make sure trigger sources are trivially valid */
+ 
+ 	tmp = cmd->start_src;
+ 	cmd->start_src &= TRIG_NOW | TRIG_EXT;
+@@ -512,7 +518,7 @@ int i_APCI3120_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_
+ 	if (err)
+ 		return 1;
+ 
+-	//step 2: make sure trigger sources are unique and mutually compatible
++	/* step 2: make sure trigger sources are unique and mutually compatible */
+ 
+ 	if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) {
+ 		err++;
+@@ -536,14 +542,14 @@ int i_APCI3120_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_
+ 	if (err)
+ 		return 2;
+ 
+-	// step 3: make sure arguments are trivially compatible
++	/*  step 3: make sure arguments are trivially compatible */
+ 
+ 	if (cmd->start_arg != 0) {
+ 		cmd->start_arg = 0;
+ 		err++;
+ 	}
+ 
+-	if (cmd->scan_begin_src == TRIG_TIMER)	// Test Delay timing
++	if (cmd->scan_begin_src == TRIG_TIMER)	/*  Test Delay timing */
+ 	{
+ 		if (cmd->scan_begin_arg < this_board->ui_MinDelaytimeNs) {
+ 			cmd->scan_begin_arg = this_board->ui_MinDelaytimeNs;
+@@ -551,7 +557,7 @@ int i_APCI3120_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_
+ 		}
+ 	}
+ 
+-	if (cmd->convert_src == TRIG_TIMER)	// Test Acquisition timing
++	if (cmd->convert_src == TRIG_TIMER)	/*  Test Acquisition timing */
+ 	{
+ 		if (cmd->scan_begin_src == TRIG_TIMER) {
+ 			if ((cmd->convert_arg)
+@@ -585,7 +591,7 @@ int i_APCI3120_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_
+ 			cmd->stop_arg = 1;
+ 			err++;
+ 		}
+-	} else {		// TRIG_NONE
++	} else {		/*  TRIG_NONE */
+ 		if (cmd->stop_arg != 0) {
+ 			cmd->stop_arg = 0;
+ 			err++;
+@@ -595,7 +601,7 @@ int i_APCI3120_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_
+ 	if (err)
+ 		return 3;
+ 
+-	// step 4: fix up any arguments
++	/*  step 4: fix up any arguments */
+ 
+ 	if (cmd->convert_src == TRIG_TIMER) {
+ 
+@@ -637,15 +643,15 @@ int i_APCI3120_CommandAnalogInput(struct comedi_device * dev, struct comedi_subd
+ {
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+ 
+-	//loading private structure with cmd structure inputs
++	/* loading private structure with cmd structure inputs */
+ 	devpriv->ui_AiFlags = cmd->flags;
+ 	devpriv->ui_AiNbrofChannels = cmd->chanlist_len;
+ 	devpriv->ui_AiScanLength = cmd->scan_end_arg;
+ 	devpriv->pui_AiChannelList = cmd->chanlist;
+ 
+-	//UPDATE-0.7.57->0.7.68devpriv->AiData=s->async->data;
++	/* UPDATE-0.7.57->0.7.68devpriv->AiData=s->async->data; */
+ 	devpriv->AiData = s->async->prealloc_buf;
+-	//UPDATE-0.7.57->0.7.68devpriv->ui_AiDataLength=s->async->data_len;
++	/* UPDATE-0.7.57->0.7.68devpriv->ui_AiDataLength=s->async->data_len; */
+ 	devpriv->ui_AiDataLength = s->async->prealloc_bufsz;
+ 
+ 	if (cmd->stop_src == TRIG_COUNT) {
+@@ -654,11 +660,11 @@ int i_APCI3120_CommandAnalogInput(struct comedi_device * dev, struct comedi_subd
+ 		devpriv->ui_AiNbrofScans = 0;
+ 	}
+ 
+-	devpriv->ui_AiTimer0 = 0;	// variables changed to timer0,timer1
++	devpriv->ui_AiTimer0 = 0;	/*  variables changed to timer0,timer1 */
+ 	devpriv->ui_AiTimer1 = 0;
+ 	if ((devpriv->ui_AiNbrofScans == 0) || (devpriv->ui_AiNbrofScans == -1))
+-		devpriv->b_AiContinuous = 1;	// user want neverending analog acquisition
+-	// stopped using cancel
++		devpriv->b_AiContinuous = 1;	/*  user want neverending analog acquisition */
++	/*  stopped using cancel */
+ 
+ 	if (cmd->start_src == TRIG_EXT)
+ 		devpriv->b_ExttrigEnable = APCI3120_ENABLE;
+@@ -666,22 +672,22 @@ int i_APCI3120_CommandAnalogInput(struct comedi_device * dev, struct comedi_subd
+ 		devpriv->b_ExttrigEnable = APCI3120_DISABLE;
+ 
+ 	if (cmd->scan_begin_src == TRIG_FOLLOW) {
+-		// mode 1 or 3
++		/*  mode 1 or 3 */
+ 		if (cmd->convert_src == TRIG_TIMER) {
+-			// mode 1
++			/*  mode 1 */
+ 
+-			devpriv->ui_AiTimer0 = cmd->convert_arg;	// timer constant in nano seconds
+-			//return this_board->i_hwdrv_CommandAnalogInput(1,dev,s);
++			devpriv->ui_AiTimer0 = cmd->convert_arg;	/*  timer constant in nano seconds */
++			/* return this_board->i_hwdrv_CommandAnalogInput(1,dev,s); */
+ 			return i_APCI3120_CyclicAnalogInput(1, dev, s);
+ 		}
+ 
+ 	}
+ 	if ((cmd->scan_begin_src == TRIG_TIMER)
+ 		&& (cmd->convert_src == TRIG_TIMER)) {
+-		// mode 2
++		/*  mode 2 */
+ 		devpriv->ui_AiTimer1 = cmd->scan_begin_arg;
+-		devpriv->ui_AiTimer0 = cmd->convert_arg;	// variable changed timer2 to timer0
+-		//return this_board->i_hwdrv_CommandAnalogInput(2,dev,s);
++		devpriv->ui_AiTimer0 = cmd->convert_arg;	/*  variable changed timer2 to timer0 */
++		/* return this_board->i_hwdrv_CommandAnalogInput(2,dev,s); */
+ 		return i_APCI3120_CyclicAnalogInput(2, dev, s);
+ 	}
+ 	return -1;
+@@ -716,64 +722,65 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 		0, ui_TimerValue0, ui_ConvertTiming;
+ 	unsigned short us_TmpValue;
+ 
+-	//BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+-	//devpriv->b_AiCyclicAcquisition=APCI3120_ENABLE;
+-	//END JK 07.05.04: Comparison between WIN32 and Linux driver
++	/* BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver */
++	/* devpriv->b_AiCyclicAcquisition=APCI3120_ENABLE; */
++	/* END JK 07.05.04: Comparison between WIN32 and Linux driver */
+ 
+ 	/*******************/
+ 	/* Resets the FIFO */
+ 	/*******************/
+ 	inb(dev->iobase + APCI3120_RESET_FIFO);
+ 
+-	//BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+-	//inw(dev->iobase+APCI3120_RD_STATUS);
+-	//END JK 07.05.04: Comparison between WIN32 and Linux driver
++	/* BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver */
++	/* inw(dev->iobase+APCI3120_RD_STATUS); */
++	/* END JK 07.05.04: Comparison between WIN32 and Linux driver */
+ 
+ 	/***************************/
+ 	/* Acquisition initialized */
+ 	/***************************/
+-	//BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
++	/* BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver */
+ 	devpriv->b_AiCyclicAcquisition = APCI3120_ENABLE;
+-	//END JK 07.05.04: Comparison between WIN32 and Linux driver
++	/* END JK 07.05.04: Comparison between WIN32 and Linux driver */
+ 
+-	// clear software  registers
++	/*  clear software  registers */
+ 	devpriv->b_TimerSelectMode = 0;
+ 	devpriv->us_OutputRegister = 0;
+ 	devpriv->b_ModeSelectRegister = 0;
+-	//devpriv->b_DigitalOutputRegister=0;
++	/* devpriv->b_DigitalOutputRegister=0; */
+ 
+-	//COMMENT JK 07.05.04: Followings calls are in i_APCI3120_StartAnalogInputAcquisition
++	/* COMMENT JK 07.05.04: Followings calls are in i_APCI3120_StartAnalogInputAcquisition */
+ 
+-   /****************************/
++	/****************************/
+ 	/* Clear Timer Write TC int */
+-   /****************************/
++	/****************************/
+ 	outl(APCI3120_CLEAR_WRITE_TC_INT,
+ 		devpriv->i_IobaseAmcc + APCI3120_AMCC_OP_REG_INTCSR);
+ 
+-   /************************************/
++	/************************************/
+ 	/* Clears the timer status register */
+-   /************************************/
+-	//BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+-	//inw(dev->iobase+APCI3120_TIMER_STATUS_REGISTER);
+-	inb(dev->iobase + APCI3120_TIMER_STATUS_REGISTER);
+-	//END JK 07.05.04: Comparison between WIN32 and Linux driver
++	/************************************/
+ 
+-   /**************************/
++	/* BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver */
++	/* inw(dev->iobase+APCI3120_TIMER_STATUS_REGISTER); */
++	/* inb(dev->iobase + APCI3120_TIMER_STATUS_REGISTER); */
++	/* END JK 07.05.04: Comparison between WIN32 and Linux driver */
++
++	/**************************/
+ 	/* Disables All Timer     */
+ 	/* Sets PR and PA to 0    */
+-   /**************************/
++	/**************************/
+ 	devpriv->us_OutputRegister = devpriv->us_OutputRegister &
+ 		APCI3120_DISABLE_TIMER0 &
+ 		APCI3120_DISABLE_TIMER1 & APCI3120_CLEAR_PA_PR;
+ 
+ 	outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
+ 
+-   /*******************/
++	/*******************/
+ 	/* Resets the FIFO */
+-   /*******************/
+-	//BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
++	/*******************/
++	/* BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver */
+ 	inb(devpriv->iobase + APCI3120_RESET_FIFO);
+-	//END JK 07.05.04: Comparison between WIN32 and Linux driver
++	/* END JK 07.05.04: Comparison between WIN32 and Linux driver */
+ 
+ 	devpriv->ui_AiActualScan = 0;
+ 	devpriv->ui_AiActualScanPosition = 0;
+@@ -781,7 +788,7 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 	devpriv->ui_AiBufferPtr = 0;
+ 	devpriv->ui_DmaActualBuffer = 0;
+ 
+-	// value for timer2  minus -2 has to be done .....dunno y??
++	/*  value for timer2  minus -2 has to be done .....dunno y?? */
+ 	ui_TimerValue2 = devpriv->ui_AiNbrofScans - 2;
+ 	ui_ConvertTiming = devpriv->ui_AiTimer0;
+ 
+@@ -819,7 +826,7 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 	}
+ ***********************************************************************************************/
+ /*** EL241003 Begin : add this section to replace floats calculation by integer calculations **/
+-	//EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001
++	/* EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001 */
+ 	if ((us_TmpValue & 0x00B0) == 0x00B0
+ 		|| !strcmp(this_board->pc_DriverName, "apci3001")) {
+ 		ui_TimerValue0 = ui_ConvertTiming * 2 - 2000;
+@@ -844,79 +851,82 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ /*** EL241003 End ******************************************************************************/
+ 
+ 	if (devpriv->b_ExttrigEnable == APCI3120_ENABLE) {
+-		i_APCI3120_ExttrigEnable(dev);	// activate EXT trigger
++		i_APCI3120_ExttrigEnable(dev);	/*  activate EXT trigger */
+ 	}
+ 	switch (mode) {
+ 	case 1:
+-		// init timer0 in mode 2
++		/*  init timer0 in mode 2 */
+ 		devpriv->b_TimerSelectMode =
+ 			(devpriv->
+ 			b_TimerSelectMode & 0xFC) | APCI3120_TIMER_0_MODE_2;
+ 		outb(devpriv->b_TimerSelectMode,
+ 			dev->iobase + APCI3120_TIMER_CRT1);
+ 
+-		//Select Timer 0
++		/* Select Timer 0 */
+ 		b_Tmp = ((devpriv->
+ 				b_DigitalOutputRegister) & 0xF0) |
+ 			APCI3120_SELECT_TIMER_0_WORD;
+ 		outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
+-		//Set the convertion time
++		/* Set the convertion time */
+ 		outw(((unsigned short) ui_TimerValue0),
+ 			dev->iobase + APCI3120_TIMER_VALUE);
+ 		break;
+ 
+ 	case 2:
+-		// init timer1 in mode 2
++		/*  init timer1 in mode 2 */
+ 		devpriv->b_TimerSelectMode =
+ 			(devpriv->
+ 			b_TimerSelectMode & 0xF3) | APCI3120_TIMER_1_MODE_2;
+ 		outb(devpriv->b_TimerSelectMode,
+ 			dev->iobase + APCI3120_TIMER_CRT1);
+ 
+-		//Select Timer 1
++		/* Select Timer 1 */
+ 		b_Tmp = ((devpriv->
+ 				b_DigitalOutputRegister) & 0xF0) |
+ 			APCI3120_SELECT_TIMER_1_WORD;
+ 		outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
+-		//Set the convertion time
++		/* Set the convertion time */
+ 		outw(((unsigned short) ui_TimerValue1),
+ 			dev->iobase + APCI3120_TIMER_VALUE);
+ 
+-		// init timer0 in mode 2
++		/*  init timer0 in mode 2 */
+ 		devpriv->b_TimerSelectMode =
+ 			(devpriv->
+ 			b_TimerSelectMode & 0xFC) | APCI3120_TIMER_0_MODE_2;
+ 		outb(devpriv->b_TimerSelectMode,
+ 			dev->iobase + APCI3120_TIMER_CRT1);
+ 
+-		//Select Timer 0
++		/* Select Timer 0 */
+ 		b_Tmp = ((devpriv->
+ 				b_DigitalOutputRegister) & 0xF0) |
+ 			APCI3120_SELECT_TIMER_0_WORD;
+ 		outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
+ 
+-		//Set the convertion time
++		/* Set the convertion time */
+ 		outw(((unsigned short) ui_TimerValue0),
+ 			dev->iobase + APCI3120_TIMER_VALUE);
+ 		break;
+ 
+ 	}
+-	//   ##########common for all modes#################
++	/*    ##########common for all modes################# */
+ 
+ 	/***********************/
+ 	/* Clears the SCAN bit */
+ 	/***********************/
+-	//BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+-	//devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister | APCI3120_DISABLE_SCAN;
++
++	/* BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver */
++	/* devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister | APCI3120_DISABLE_SCAN; */
++
+ 	devpriv->b_ModeSelectRegister = devpriv->b_ModeSelectRegister &
+ 		APCI3120_DISABLE_SCAN;
+-	//END JK 07.05.04: Comparison between WIN32 and Linux driver
++	/* END JK 07.05.04: Comparison between WIN32 and Linux driver */
++
+ 	outb(devpriv->b_ModeSelectRegister,
+ 		dev->iobase + APCI3120_WRITE_MODE_SELECT);
+ 
+-	// If DMA is disabled
++	/*  If DMA is disabled */
+ 	if (devpriv->us_UseDma == APCI3120_DISABLE) {
+-		// disable EOC and enable EOS
++		/*  disable EOC and enable EOS */
+ 		devpriv->b_InterruptMode = APCI3120_EOS_MODE;
+ 		devpriv->b_EocEosInterrupt = APCI3120_ENABLE;
+ 
+@@ -928,15 +938,17 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 			dev->iobase + APCI3120_WRITE_MODE_SELECT);
+ 
+ 		if (!devpriv->b_AiContinuous) {
+-			// configure Timer2 For counting  EOS
+-			//Reset gate 2 of Timer 2 to disable it (Set Bit D14 to 0)
++/*
++ * configure Timer2 For counting EOS Reset gate 2 of Timer 2 to
++ * disable it (Set Bit D14 to 0)
++ */
+ 			devpriv->us_OutputRegister =
+ 				devpriv->
+ 				us_OutputRegister & APCI3120_DISABLE_TIMER2;
+ 			outw(devpriv->us_OutputRegister,
+ 				dev->iobase + APCI3120_WR_ADDRESS);
+ 
+-			// DISABLE TIMER intERRUPT
++			/*  DISABLE TIMER intERRUPT */
+ 			devpriv->b_ModeSelectRegister =
+ 				devpriv->
+ 				b_ModeSelectRegister &
+@@ -944,7 +956,7 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 			outb(devpriv->b_ModeSelectRegister,
+ 				dev->iobase + APCI3120_WRITE_MODE_SELECT);
+ 
+-			//(1) Init timer 2 in mode 0 and write timer value
++			/* (1) Init timer 2 in mode 0 and write timer value */
+ 			devpriv->b_TimerSelectMode =
+ 				(devpriv->
+ 				b_TimerSelectMode & 0x0F) |
+@@ -952,7 +964,7 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 			outb(devpriv->b_TimerSelectMode,
+ 				dev->iobase + APCI3120_TIMER_CRT1);
+ 
+-			//Writing LOW unsigned short
++			/* Writing LOW unsigned short */
+ 			b_Tmp = ((devpriv->
+ 					b_DigitalOutputRegister) & 0xF0) |
+ 				APCI3120_SELECT_TIMER_2_LOW_WORD;
+@@ -960,7 +972,7 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 			outw(LOWORD(ui_TimerValue2),
+ 				dev->iobase + APCI3120_TIMER_VALUE);
+ 
+-			//Writing HIGH unsigned short
++			/* Writing HIGH unsigned short */
+ 			b_Tmp = ((devpriv->
+ 					b_DigitalOutputRegister) & 0xF0) |
+ 				APCI3120_SELECT_TIMER_2_HIGH_WORD;
+@@ -968,20 +980,20 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 			outw(HIWORD(ui_TimerValue2),
+ 				dev->iobase + APCI3120_TIMER_VALUE);
+ 
+-			//(2) Reset FC_TIMER BIT  Clearing timer status register
++			/* (2) Reset FC_TIMER BIT  Clearing timer status register */
+ 			inb(dev->iobase + APCI3120_TIMER_STATUS_REGISTER);
+-			// enable timer counter and disable watch dog
++			/*  enable timer counter and disable watch dog */
+ 			devpriv->b_ModeSelectRegister =
+ 				(devpriv->
+ 				b_ModeSelectRegister |
+ 				APCI3120_ENABLE_TIMER_COUNTER) &
+ 				APCI3120_DISABLE_WATCHDOG;
+-			// select EOS clock input for timer 2
++			/*  select EOS clock input for timer 2 */
+ 			devpriv->b_ModeSelectRegister =
+ 				devpriv->
+ 				b_ModeSelectRegister |
+ 				APCI3120_TIMER2_SELECT_EOS;
+-			// Enable timer2  interrupt
++			/*  Enable timer2  interrupt */
+ 			devpriv->b_ModeSelectRegister =
+ 				devpriv->
+ 				b_ModeSelectRegister |
+@@ -992,15 +1004,16 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 			devpriv->b_Timer2Interrupt = APCI3120_ENABLE;
+ 		}
+ 	} else {
+-		// If DMA Enabled
+-		//BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+-		//inw(dev->iobase+0);// reset EOC bit
+-		//END JK 07.05.04: Comparison between WIN32 and Linux driver
++		/* If DMA Enabled */
++
++		/* BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver */
++		/* inw(dev->iobase+0); reset EOC bit */
++		/* END JK 07.05.04: Comparison between WIN32 and Linux driver */
+ 		devpriv->b_InterruptMode = APCI3120_DMA_MODE;
+ 
+-      /************************************/
++		/************************************/
+ 		/* Disables the EOC, EOS interrupt  */
+-	  /************************************/
++		/************************************/
+ 		devpriv->b_ModeSelectRegister = devpriv->b_ModeSelectRegister &
+ 			APCI3120_DISABLE_EOC_INT & APCI3120_DISABLE_EOS_INT;
+ 
+@@ -1012,18 +1025,18 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 
+ 		if (!devpriv->b_AiContinuous) {
+ 
+-			if (dmalen0 > (devpriv->ui_AiNbrofScans * devpriv->ui_AiScanLength * 2)) {	// must we fill full first buffer?
++			if (dmalen0 > (devpriv->ui_AiNbrofScans * devpriv->ui_AiScanLength * 2)) {	/*  must we fill full first buffer? */
+ 				dmalen0 =
+ 					devpriv->ui_AiNbrofScans *
+ 					devpriv->ui_AiScanLength * 2;
+-			} else if (dmalen1 > (devpriv->ui_AiNbrofScans * devpriv->ui_AiScanLength * 2 - dmalen0))	// and must we fill full second buffer when first is once filled?
++			} else if (dmalen1 > (devpriv->ui_AiNbrofScans * devpriv->ui_AiScanLength * 2 - dmalen0))	/*  and must we fill full second buffer when first is once filled? */
+ 				dmalen1 =
+ 					devpriv->ui_AiNbrofScans *
+ 					devpriv->ui_AiScanLength * 2 - dmalen0;
+ 		}
+ 
+ 		if (devpriv->ui_AiFlags & TRIG_WAKE_EOS) {
+-			// don't we want wake up every scan?
++			/*  don't we want wake up every scan? */
+ 			if (dmalen0 > (devpriv->ui_AiScanLength * 2)) {
+ 				dmalen0 = devpriv->ui_AiScanLength * 2;
+ 				if (devpriv->ui_AiScanLength & 1)
+@@ -1036,7 +1049,7 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 				if (dmalen1 < 4)
+ 					dmalen1 = 4;
+ 			}
+-		} else {	// isn't output buff smaller that our DMA buff?
++		} else {	/*  isn't output buff smaller that our DMA buff? */
+ 			if (dmalen0 > (devpriv->ui_AiDataLength)) {
+ 				dmalen0 = devpriv->ui_AiDataLength;
+ 			}
+@@ -1047,14 +1060,16 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 		devpriv->ui_DmaBufferUsesize[0] = dmalen0;
+ 		devpriv->ui_DmaBufferUsesize[1] = dmalen1;
+ 
+-		//Initialize DMA
++		/* Initialize DMA */
+ 
+-		// Set Transfer count enable bit and A2P_fifo reset bit in AGCSTS register
+-		//1
++/*
++ * Set Transfer count enable bit and A2P_fifo reset bit in AGCSTS
++ * register 1
++ */
+ 		ui_Tmp = AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO;
+ 		outl(ui_Tmp, devpriv->i_IobaseAmcc + AMCC_OP_REG_AGCSTS);
+ 
+-		// changed  since 16 bit interface for add on
++		/*  changed  since 16 bit interface for add on */
+ 		/*********************/
+ 		/* ENABLE BUS MASTER */
+ 		/*********************/
+@@ -1066,78 +1081,95 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 		outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH,
+ 			devpriv->i_IobaseAddon + 2);
+ 
+-		// TO VERIFIED
+-		//BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
++/*
++ * TO VERIFIED BEGIN JK 07.05.04: Comparison between WIN32 and Linux
++ * driver
++ */
+ 		outw(0x1000, devpriv->i_IobaseAddon + 2);
+-		//END JK 07.05.04: Comparison between WIN32 and Linux driver
++		/* END JK 07.05.04: Comparison between WIN32 and Linux driver */
+ 
+-		//2  No change
+-		// A2P FIFO MANAGEMENT
+-		// A2P fifo reset  & transfer control enable
+-		 /***********************/
++		/* 2 No change */
+ 		/* A2P FIFO MANAGEMENT */
+-		 /***********************/
++		/* A2P fifo reset & transfer control enable */
++
++		/***********************/
++		/* A2P FIFO MANAGEMENT */
++		/***********************/
+ 		outl(APCI3120_A2P_FIFO_MANAGEMENT, devpriv->i_IobaseAmcc +
+ 			APCI3120_AMCC_OP_MCSR);
+ 
+-		//3
+-		//beginning address of dma buf
+-		//The 32 bit address of dma buffer is converted into two 16 bit addresses
+-		// Can done by using _attach and put into into an array
+-		// array used may be for differnet pages
++/*
++ * 3
++ * beginning address of dma buf The 32 bit address of dma buffer
++ * is converted into two 16 bit addresses Can done by using _attach
++ * and put into into an array array used may be for differnet pages
++ */
+ 
+-		// DMA Start Adress Low
++		/*  DMA Start Adress Low */
+ 		outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0);
+ 		outw((devpriv->ul_DmaBufferHw[0] & 0xFFFF),
+ 			devpriv->i_IobaseAddon + 2);
+ 
+-		 /*************************/
++		/*************************/
+ 		/* DMA Start Adress High */
+-		 /*************************/
++		/*************************/
+ 		outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0);
+ 		outw((devpriv->ul_DmaBufferHw[0] / 65536),
+ 			devpriv->i_IobaseAddon + 2);
+ 
+-		//4
+-		// amount of bytes to be transfered  set transfer count
+-		// used ADDON MWTC register
+-		//commented testing             outl(devpriv->ui_DmaBufferUsesize[0], devpriv->i_IobaseAddon+AMCC_OP_REG_AMWTC);
+-
+-		 /**************************/
++/*
++ * 4
++ * amount of bytes to be transfered set transfer count used ADDON
++ * MWTC register commented testing
++ * outl(devpriv->ui_DmaBufferUsesize[0],
++ * devpriv->i_IobaseAddon+AMCC_OP_REG_AMWTC);
++ */
++
++		/**************************/
+ 		/* Nbr of acquisition LOW */
+-		 /**************************/
++		/**************************/
+ 		outw(APCI3120_ADD_ON_MWTC_LOW, devpriv->i_IobaseAddon + 0);
+ 		outw((devpriv->ui_DmaBufferUsesize[0] & 0xFFFF),
+ 			devpriv->i_IobaseAddon + 2);
+ 
+-		 /***************************/
++		/***************************/
+ 		/* Nbr of acquisition HIGH */
+-		 /***************************/
++		/***************************/
+ 		outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->i_IobaseAddon + 0);
+ 		outw((devpriv->ui_DmaBufferUsesize[0] / 65536),
+ 			devpriv->i_IobaseAddon + 2);
+ 
+-		//5
+-		// To configure A2P FIFO
+-		// testing outl( FIFO_ADVANCE_ON_BYTE_2,devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR);
++/*
++ * 5
++ * To configure A2P FIFO testing outl(
++ * FIFO_ADVANCE_ON_BYTE_2,devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR);
++ */
+ 
+ 		/******************/
+ 		/* A2P FIFO RESET */
+ 		/******************/
+-		// TO VERIFY
+-		//BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
++/*
++ * TO VERIFY BEGIN JK 07.05.04: Comparison between WIN32 and Linux
++ * driver
++ */
+ 		outl(0x04000000UL, devpriv->i_IobaseAmcc + AMCC_OP_REG_MCSR);
+-		//END JK 07.05.04: Comparison between WIN32 and Linux driver
++		/* END JK 07.05.04: Comparison between WIN32 and Linux driver */
++
++/*
++ * 6
++ * ENABLE A2P FIFO WRITE AND ENABLE AMWEN AMWEN_ENABLE |
++ * A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03
++ */
+ 
+-		//6
+-		//ENABLE A2P FIFO WRITE AND ENABLE AMWEN
+-		// AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03
+-		//BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+-		//outw(3,devpriv->i_IobaseAddon + 4);
+-		//END JK 07.05.04: Comparison between WIN32 and Linux driver
++		/* BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver */
++		/* outw(3,devpriv->i_IobaseAddon + 4); */
++		/* END JK 07.05.04: Comparison between WIN32 and Linux driver */
+ 
+-		//7
+-		//initialise end of dma interrupt  AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI)
++/*
++ * 7
++ * initialise end of dma interrupt AINT_WRITE_COMPL =
++ * ENABLE_WRITE_TC_INT(ADDI)
++ */
+ 		/***************************************************/
+ 		/* A2P FIFO CONFIGURATE, END OF DMA intERRUPT INIT */
+ 		/***************************************************/
+@@ -1145,25 +1177,25 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 				APCI3120_ENABLE_WRITE_TC_INT),
+ 			devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);
+ 
+-		//BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
++		/* BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver */
+ 		/******************************************/
+ 		/* ENABLE A2P FIFO WRITE AND ENABLE AMWEN */
+ 		/******************************************/
+ 		outw(3, devpriv->i_IobaseAddon + 4);
+-		//END JK 07.05.04: Comparison between WIN32 and Linux driver
++		/* END JK 07.05.04: Comparison between WIN32 and Linux driver */
+ 
+ 		/******************/
+ 		/* A2P FIFO RESET */
+ 		/******************/
+-		//BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
++		/* BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver */
+ 		outl(0x04000000UL,
+ 			devpriv->i_IobaseAmcc + APCI3120_AMCC_OP_MCSR);
+-		//END JK 07.05.04: Comparison between WIN32 and Linux driver
++		/* END JK 07.05.04: Comparison between WIN32 and Linux driver */
+ 	}
+ 
+ 	if ((devpriv->us_UseDma == APCI3120_DISABLE)
+ 		&& !devpriv->b_AiContinuous) {
+-		// set gate 2   to start conversion
++		/*  set gate 2   to start conversion */
+ 		devpriv->us_OutputRegister =
+ 			devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER2;
+ 		outw(devpriv->us_OutputRegister,
+@@ -1172,14 +1204,14 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 
+ 	switch (mode) {
+ 	case 1:
+-		// set gate 0   to start conversion
++		/*  set gate 0   to start conversion */
+ 		devpriv->us_OutputRegister =
+ 			devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER0;
+ 		outw(devpriv->us_OutputRegister,
+ 			dev->iobase + APCI3120_WR_ADDRESS);
+ 		break;
+ 	case 2:
+-		// set  gate 0 and gate 1
++		/*  set  gate 0 and gate 1 */
+ 		devpriv->us_OutputRegister =
+ 			devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER1;
+ 		devpriv->us_OutputRegister =
+@@ -1226,47 +1258,49 @@ int i_APCI3120_Reset(struct comedi_device * dev)
+ 	devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
+ 	devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
+ 	devpriv->b_InterruptMode = APCI3120_EOC_MODE;
+-	devpriv->ui_EocEosConversionTime = 0;	// set eoc eos conv time to 0
++	devpriv->ui_EocEosConversionTime = 0;	/*  set eoc eos conv time to 0 */
+ 	devpriv->b_OutputMemoryStatus = 0;
+ 
+-	// variables used in timer subdevice
++	/*  variables used in timer subdevice */
+ 	devpriv->b_Timer2Mode = 0;
+ 	devpriv->b_Timer2Interrupt = 0;
+-	devpriv->b_ExttrigEnable = 0;	// Disable ext trigger
++	devpriv->b_ExttrigEnable = 0;	/*  Disable ext trigger */
+ 
+ 	/* Disable all interrupts, watchdog for the anolog output */
+ 	devpriv->b_ModeSelectRegister = 0;
+ 	outb(devpriv->b_ModeSelectRegister,
+ 		dev->iobase + APCI3120_WRITE_MODE_SELECT);
+ 
+-	// Disables all counters, ext trigger and clears PA, PR
++	/*  Disables all counters, ext trigger and clears PA, PR */
+ 	devpriv->us_OutputRegister = 0;
+ 	outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
+ 
+-	//Code to set the all anolog o/p channel to 0v
+-	//8191 is decimal value for zero(0 v)volt in bipolar mode(default)
+-	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_1, dev->iobase + APCI3120_ANALOG_OUTPUT_1);	//channel 1
+-	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_2, dev->iobase + APCI3120_ANALOG_OUTPUT_1);	//channel 2
+-	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_3, dev->iobase + APCI3120_ANALOG_OUTPUT_1);	//channel 3
+-	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_4, dev->iobase + APCI3120_ANALOG_OUTPUT_1);	//channel 4
+-
+-	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_5, dev->iobase + APCI3120_ANALOG_OUTPUT_2);	//channel 5
+-	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_6, dev->iobase + APCI3120_ANALOG_OUTPUT_2);	//channel 6
+-	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_7, dev->iobase + APCI3120_ANALOG_OUTPUT_2);	//channel 7
+-	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_8, dev->iobase + APCI3120_ANALOG_OUTPUT_2);	//channel 8
+-
+-	//  Reset digital output to L0W
+-
+-//ES05  outb(0x0,dev->iobase+APCI3120_DIGITAL_OUTPUT);
++/*
++ * Code to set the all anolog o/p channel to 0v 8191 is decimal
++ * value for zero(0 v)volt in bipolar mode(default)
++ */
++	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_1, dev->iobase + APCI3120_ANALOG_OUTPUT_1);	/* channel 1 */
++	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_2, dev->iobase + APCI3120_ANALOG_OUTPUT_1);	/* channel 2 */
++	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_3, dev->iobase + APCI3120_ANALOG_OUTPUT_1);	/* channel 3 */
++	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_4, dev->iobase + APCI3120_ANALOG_OUTPUT_1);	/* channel 4 */
++
++	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_5, dev->iobase + APCI3120_ANALOG_OUTPUT_2);	/* channel 5 */
++	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_6, dev->iobase + APCI3120_ANALOG_OUTPUT_2);	/* channel 6 */
++	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_7, dev->iobase + APCI3120_ANALOG_OUTPUT_2);	/* channel 7 */
++	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_8, dev->iobase + APCI3120_ANALOG_OUTPUT_2);	/* channel 8 */
++
++	/*   Reset digital output to L0W */
++
++/* ES05  outb(0x0,dev->iobase+APCI3120_DIGITAL_OUTPUT); */
+ 	udelay(10);
+ 
+-	inw(dev->iobase + 0);	//make a dummy read
+-	inb(dev->iobase + APCI3120_RESET_FIFO);	// flush FIFO
+-	inw(dev->iobase + APCI3120_RD_STATUS);	// flush A/D status register
++	inw(dev->iobase + 0);	/* make a dummy read */
++	inb(dev->iobase + APCI3120_RESET_FIFO);	/*  flush FIFO */
++	inw(dev->iobase + APCI3120_RD_STATUS);	/*  flush A/D status register */
+ 
+-	//code to reset the RAM sequence
++	/* code to reset the RAM sequence */
+ 	for (i = 0; i < 16; i++) {
+-		us_TmpValue = i << 8;	//select the location
++		us_TmpValue = i << 8;	/* select the location */
+ 		outw(us_TmpValue, dev->iobase + APCI3120_SEQ_RAM_ADDRESS);
+ 	}
+ 	return 0;
+@@ -1299,7 +1333,7 @@ int i_APCI3120_Reset(struct comedi_device * dev)
+ int i_APCI3120_SetupChannelList(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	int n_chan, unsigned int *chanlist, char check)
+ {
+-	unsigned int i;		//, differencial=0, bipolar=0;
++	unsigned int i;		/* , differencial=0, bipolar=0; */
+ 	unsigned int gain;
+ 	unsigned short us_TmpValue;
+ 
+@@ -1309,29 +1343,29 @@ int i_APCI3120_SetupChannelList(struct comedi_device * dev, struct comedi_subdev
+ 			comedi_error(dev, "range/channel list is empty!");
+ 		return 0;
+ 	}
+-	// All is ok, so we can setup channel/range list
++	/*  All is ok, so we can setup channel/range list */
+ 	if (check)
+ 		return 1;
+ 
+-	//Code  to set the PA and PR...Here it set PA to 0..
++	/* Code  to set the PA and PR...Here it set PA to 0.. */
+ 	devpriv->us_OutputRegister =
+ 		devpriv->us_OutputRegister & APCI3120_CLEAR_PA_PR;
+ 	devpriv->us_OutputRegister = ((n_chan - 1) & 0xf) << 8;
+ 	outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
+ 
+ 	for (i = 0; i < n_chan; i++) {
+-		// store range list to card
+-		us_TmpValue = CR_CHAN(chanlist[i]);	// get channel number;
++		/*  store range list to card */
++		us_TmpValue = CR_CHAN(chanlist[i]);	/*  get channel number; */
+ 
+ 		if (CR_RANGE(chanlist[i]) < APCI3120_BIPOLAR_RANGES) {
+-			us_TmpValue &= ((~APCI3120_UNIPOLAR) & 0xff);	// set bipolar
++			us_TmpValue &= ((~APCI3120_UNIPOLAR) & 0xff);	/*  set bipolar */
+ 		} else {
+-			us_TmpValue |= APCI3120_UNIPOLAR;	// enable unipolar......
++			us_TmpValue |= APCI3120_UNIPOLAR;	/*  enable unipolar...... */
+ 		}
+ 
+-		gain = CR_RANGE(chanlist[i]);	// get gain number
+-		us_TmpValue |= ((gain & 0x03) << 4);	//<<4 for G0 and G1 bit in RAM
+-		us_TmpValue |= i << 8;	//To select the RAM LOCATION....
++		gain = CR_RANGE(chanlist[i]);	/*  get gain number */
++		us_TmpValue |= ((gain & 0x03) << 4);	/* <<4 for G0 and G1 bit in RAM */
++		us_TmpValue |= i << 8;	/* To select the RAM LOCATION.... */
+ 		outw(us_TmpValue, dev->iobase + APCI3120_SEQ_RAM_ADDRESS);
+ 
+ 		printk("\n Gain = %i",
+@@ -1339,7 +1373,7 @@ int i_APCI3120_SetupChannelList(struct comedi_device * dev, struct comedi_subdev
+ 		printk("\n Channel = %i", CR_CHAN(chanlist[i]));
+ 		printk("\n Polarity = %i", us_TmpValue & APCI3120_UNIPOLAR);
+ 	}
+-	return 1;		// we can serve this with scan logic
++	return 1;		/*  we can serve this with scan logic */
+ }
+ 
+ /*
+@@ -1431,24 +1465,24 @@ void v_APCI3120_Interrupt(int irq, void *d)
+ 	struct comedi_subdevice *s = dev->subdevices + 0;
+ 	ui_Check = 1;
+ 
+-	int_daq = inw(dev->iobase + APCI3120_RD_STATUS) & 0xf000;	// get IRQ reasons
+-	int_amcc = inl(devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);	// get AMCC int register
++	int_daq = inw(dev->iobase + APCI3120_RD_STATUS) & 0xf000;	/*  get IRQ reasons */
++	int_amcc = inl(devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);	/*  get AMCC int register */
+ 
+ 	if ((!int_daq) && (!(int_amcc & ANY_S593X_INT))) {
+ 		comedi_error(dev, "IRQ from unknow source");
+ 		return;
+ 	}
+ 
+-	outl(int_amcc | 0x00ff0000, devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);	// shutdown IRQ reasons in AMCC
++	outl(int_amcc | 0x00ff0000, devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);	/*  shutdown IRQ reasons in AMCC */
+ 
+ 	int_daq = (int_daq >> 12) & 0xF;
+ 
+ 	if (devpriv->b_ExttrigEnable == APCI3120_ENABLE) {
+-		//Disable ext trigger
++		/* Disable ext trigger */
+ 		i_APCI3120_ExttrigDisable(dev);
+ 		devpriv->b_ExttrigEnable = APCI3120_DISABLE;
+ 	}
+-	//clear the timer 2 interrupt
++	/* clear the timer 2 interrupt */
+ 	inb(devpriv->i_IobaseAmcc + APCI3120_TIMER_STATUS_REGISTER);
+ 
+ 	if (int_amcc & MASTER_ABORT_INT)
+@@ -1456,19 +1490,19 @@ void v_APCI3120_Interrupt(int irq, void *d)
+ 	if (int_amcc & TARGET_ABORT_INT)
+ 		comedi_error(dev, "AMCC IRQ - TARGET DMA ABORT!");
+ 
+-	// Ckeck if EOC interrupt
++	/*  Ckeck if EOC interrupt */
+ 	if (((int_daq & 0x8) == 0)
+ 		&& (devpriv->b_InterruptMode == APCI3120_EOC_MODE)) {
+ 		if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) {
+ 
+-			// Read the AI Value
++			/*  Read the AI Value */
+ 
+ 			devpriv->ui_AiReadData[0] =
+ 				(unsigned int) inw(devpriv->iobase + 0);
+ 			devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
+-			send_sig(SIGIO, devpriv->tsk_Current, 0);	// send signal to the sample
++			send_sig(SIGIO, devpriv->tsk_Current, 0);	/*  send signal to the sample */
+ 		} else {
+-			//Disable EOC Interrupt
++			/* Disable EOC Interrupt */
+ 			devpriv->b_ModeSelectRegister =
+ 				devpriv->
+ 				b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT;
+@@ -1478,10 +1512,10 @@ void v_APCI3120_Interrupt(int irq, void *d)
+ 		}
+ 	}
+ 
+-	// Check If EOS interrupt
++	/*  Check If EOS interrupt */
+ 	if ((int_daq & 0x2) && (devpriv->b_InterruptMode == APCI3120_EOS_MODE)) {
+ 
+-		if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE)	// enable this in without DMA ???
++		if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE)	/*  enable this in without DMA ??? */
+ 		{
+ 
+ 			if (devpriv->b_AiCyclicAcquisition == APCI3120_ENABLE) {
+@@ -1506,7 +1540,7 @@ void v_APCI3120_Interrupt(int irq, void *d)
+ 				devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
+ 				devpriv->b_InterruptMode = APCI3120_EOC_MODE;
+ 
+-				send_sig(SIGIO, devpriv->tsk_Current, 0);	// send signal to the sample
++				send_sig(SIGIO, devpriv->tsk_Current, 0);	/*  send signal to the sample */
+ 
+ 			}
+ 
+@@ -1516,12 +1550,12 @@ void v_APCI3120_Interrupt(int irq, void *d)
+ 				b_ModeSelectRegister & APCI3120_DISABLE_EOS_INT;
+ 			outb(devpriv->b_ModeSelectRegister,
+ 				dev->iobase + APCI3120_WRITE_MODE_SELECT);
+-			devpriv->b_EocEosInterrupt = APCI3120_DISABLE;	//Default settings
++			devpriv->b_EocEosInterrupt = APCI3120_DISABLE;	/* Default settings */
+ 			devpriv->b_InterruptMode = APCI3120_EOC_MODE;
+ 		}
+ 
+ 	}
+-	//Timer2 interrupt
++	/* Timer2 interrupt */
+ 	if (int_daq & 0x1) {
+ 
+ 		switch (devpriv->b_Timer2Mode) {
+@@ -1534,18 +1568,18 @@ void v_APCI3120_Interrupt(int irq, void *d)
+ 			outb(devpriv->b_ModeSelectRegister,
+ 				dev->iobase + APCI3120_WRITE_MODE_SELECT);
+ 
+-			// stop timer 2
++			/*  stop timer 2 */
+ 			devpriv->us_OutputRegister =
+ 				devpriv->
+ 				us_OutputRegister & APCI3120_DISABLE_ALL_TIMER;
+ 			outw(devpriv->us_OutputRegister,
+ 				dev->iobase + APCI3120_WR_ADDRESS);
+ 
+-			//stop timer 0 and timer 1
++			/* stop timer 0 and timer 1 */
+ 			i_APCI3120_StopCyclicAcquisition(dev, s);
+ 			devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
+ 
+-			//UPDATE-0.7.57->0.7.68comedi_done(dev,s);
++			/* UPDATE-0.7.57->0.7.68comedi_done(dev,s); */
+ 			s->async->events |= COMEDI_CB_EOA;
+ 			comedi_event(dev, s);
+ 
+@@ -1553,19 +1587,19 @@ void v_APCI3120_Interrupt(int irq, void *d)
+ 
+ 		case APCI3120_TIMER:
+ 
+-			//Send a signal to from kernel to user space
++			/* Send a signal to from kernel to user space */
+ 			send_sig(SIGIO, devpriv->tsk_Current, 0);
+ 			break;
+ 
+ 		case APCI3120_WATCHDOG:
+ 
+-			//Send a signal to from kernel to user space
++			/* Send a signal to from kernel to user space */
+ 			send_sig(SIGIO, devpriv->tsk_Current, 0);
+ 			break;
+ 
+ 		default:
+ 
+-			// disable Timer Interrupt
++			/*  disable Timer Interrupt */
+ 
+ 			devpriv->b_ModeSelectRegister =
+ 				devpriv->
+@@ -1596,7 +1630,7 @@ void v_APCI3120_Interrupt(int irq, void *d)
+ 			/* Clears the timer status register */
+ 			/************************************/
+ 			inw(dev->iobase + APCI3120_TIMER_STATUS_REGISTER);
+-			v_APCI3120_InterruptDma(irq, d);	// do some data transfer
++			v_APCI3120_InterruptDma(irq, d);	/*  do some data transfer */
+ 		} else {
+ 			/* Stops the Timer */
+ 			outw(devpriv->
+@@ -1630,31 +1664,7 @@ void v_APCI3120_Interrupt(int irq, void *d)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-/*
+- * int i_APCI3120_InterruptHandleEos(struct comedi_device *dev)
+-{
+-       int n_chan,i;
+-       short *data;
+-       struct comedi_subdevice *s=dev->subdevices+0;
+-       struct comedi_async *async = s->async;
+-       data=async->data+async->buf_int_ptr;
+-        n_chan=devpriv->ui_AiNbrofChannels;
+-
+-       for(i=0;iiobase+0);
+-         }
+-       async->buf_int_count+=n_chan*sizeof(short);
+-       async->buf_int_ptr+=n_chan*sizeof(short);
+-       comedi_eos(dev,s);
+-       if (s->async->buf_int_ptr>=s->async->data_len) //  for buffer rool over
+-		         {
+-*//* buffer rollover */
+-/*	        s->async->buf_int_ptr=0;
+-		comedi_eobuf(dev,s);
+-         }
+- 	return 0;
+-}*/
++
+ int i_APCI3120_InterruptHandleEos(struct comedi_device * dev)
+ {
+ 	int n_chan, i;
+@@ -1720,20 +1730,20 @@ void v_APCI3120_InterruptDma(int irq, void *d)
+ 
+ 		return;
+ 	}
+-	samplesinbuf = samplesinbuf >> 1;	// number of received samples
++	samplesinbuf = samplesinbuf >> 1;	/*  number of received samples */
+ 	if (devpriv->b_DmaDoubleBuffer) {
+-		// switch DMA buffers if is used double buffering
++		/*  switch DMA buffers if is used double buffering */
+ 		next_dma_buf = 1 - devpriv->ui_DmaActualBuffer;
+ 
+ 		ui_Tmp = AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO;
+ 		outl(ui_Tmp, devpriv->i_IobaseAddon + AMCC_OP_REG_AGCSTS);
+ 
+-		// changed  since 16 bit interface for add on
++		/*  changed  since 16 bit interface for add on */
+ 		outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0);
+ 		outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW,
+ 			devpriv->i_IobaseAddon + 2);
+ 		outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0);
+-		outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH, devpriv->i_IobaseAddon + 2);	// 0x1000 is out putted in windows driver
++		outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH, devpriv->i_IobaseAddon + 2);	/*  0x1000 is out putted in windows driver */
+ 
+ 		var = devpriv->ul_DmaBufferHw[next_dma_buf];
+ 		low_word = var & 0xffff;
+@@ -1761,54 +1771,18 @@ void v_APCI3120_InterruptDma(int irq, void *d)
+ 		outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->i_IobaseAddon + 0);
+ 		outw(high_word, devpriv->i_IobaseAddon + 2);
+ 
+-		// To configure A2P FIFO
+-		// ENABLE A2P FIFO WRITE AND ENABLE AMWEN
+-		// AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03
++/*
++ * To configure A2P FIFO
++ * ENABLE A2P FIFO WRITE AND ENABLE AMWEN
++ * AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03
++ */
+ 		outw(3, devpriv->i_IobaseAddon + 4);
+-		//initialise end of dma interrupt  AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI)
++		/* initialise end of dma interrupt  AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI) */
+ 		outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2 |
+ 				APCI3120_ENABLE_WRITE_TC_INT),
+ 			devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);
+ 
+ 	}
+-/*UPDATE-0.7.57->0.7.68
+-	ptr=(short *)devpriv->ul_DmaBufferVirtual[devpriv->ui_DmaActualBuffer];
+-
+-
+-	// if there is not enough space left in the buffer to copy all data contained in the DMABufferVirtual
+-	if(s->async->buf_int_ptr+samplesinbuf*sizeof(short)>=devpriv->ui_AiDataLength)
+-	{
+-		m=(devpriv->ui_AiDataLength-s->async->buf_int_ptr)/sizeof(short);
+-		v_APCI3120_InterruptDmaMoveBlock16bit(dev,s,(void *)ptr,((void *)(devpriv->AiData))+s->async->buf_int_ptr,m);
+-		s->async->buf_int_count+=m*sizeof(short);
+-		ptr+=m*sizeof(short);
+-                samplesinbuf-=m;
+-		s->async->buf_int_ptr=0;
+-		comedi_eobuf(dev,s);
+-	}
+-
+-	if (samplesinbuf)
+-	{
+-	        v_APCI3120_InterruptDmaMoveBlock16bit(dev,s,(void *)ptr,((void *)(devpriv->AiData))+s->async->buf_int_ptr,samplesinbuf);
+-
+-		s->async->buf_int_count+=samplesinbuf*sizeof(short);
+-		s->async->buf_int_ptr+=samplesinbuf*sizeof(short);
+-		if (!(devpriv->ui_AiFlags & TRIG_WAKE_EOS))
+-		{
+-			comedi_bufcheck(dev,s);
+-                }
+-	}
+-	if (!devpriv->b_AiContinuous)
+-	if ( devpriv->ui_AiActualScan>=devpriv->ui_AiNbrofScans )
+-	{
+-	    // all data sampled
+-	    i_APCI3120_StopCyclicAcquisition(dev,s);
+-            devpriv->b_AiCyclicAcquisition=APCI3120_DISABLE;
+-	    //DPRINTK("\n Single DMA completed..\n");
+-		comedi_done(dev,s);
+-            	return;
+-	}
+-*/
+ 	if (samplesinbuf) {
+ 		v_APCI3120_InterruptDmaMoveBlock16bit(dev, s,
+ 			devpriv->ul_DmaBufferVirtual[devpriv->
+@@ -1821,7 +1795,7 @@ void v_APCI3120_InterruptDma(int irq, void *d)
+ 	}
+ 	if (!devpriv->b_AiContinuous)
+ 		if (devpriv->ui_AiActualScan >= devpriv->ui_AiNbrofScans) {
+-			// all data sampled
++			/*  all data sampled */
+ 			i_APCI3120_StopCyclicAcquisition(dev, s);
+ 			devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
+ 			s->async->events |= COMEDI_CB_EOA;
+@@ -1829,22 +1803,26 @@ void v_APCI3120_InterruptDma(int irq, void *d)
+ 			return;
+ 		}
+ 
+-	if (devpriv->b_DmaDoubleBuffer) {	// switch dma buffers
++	if (devpriv->b_DmaDoubleBuffer) {	/*  switch dma buffers */
+ 		devpriv->ui_DmaActualBuffer = 1 - devpriv->ui_DmaActualBuffer;
+ 	} else {
+-		// restart DMA if is not used double buffering
+-		//ADDED REINITIALISE THE DMA
++/*
++ * restart DMA if is not used double buffering
++ * ADDED REINITIALISE THE DMA
++ */
+ 		ui_Tmp = AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO;
+ 		outl(ui_Tmp, devpriv->i_IobaseAddon + AMCC_OP_REG_AGCSTS);
+ 
+-		// changed  since 16 bit interface for add on
++		/*  changed  since 16 bit interface for add on */
+ 		outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0);
+ 		outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW,
+ 			devpriv->i_IobaseAddon + 2);
+ 		outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0);
+-		outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH, devpriv->i_IobaseAddon + 2);	//
+-		// A2P FIFO MANAGEMENT
+-		// A2P fifo reset  & transfer control enable
++		outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH, devpriv->i_IobaseAddon + 2);	/*  */
++/*
++ * A2P FIFO MANAGEMENT
++ * A2P fifo reset & transfer control enable
++ */
+ 		outl(APCI3120_A2P_FIFO_MANAGEMENT,
+ 			devpriv->i_IobaseAmcc + AMCC_OP_REG_MCSR);
+ 
+@@ -1858,7 +1836,7 @@ void v_APCI3120_InterruptDma(int irq, void *d)
+ 		outw(high_word, devpriv->i_IobaseAddon + 2);
+ 
+ 		var = devpriv->ui_DmaBufferUsesize[0];
+-		low_word = var & 0xffff;	//changed
++		low_word = var & 0xffff;	/* changed */
+ 		var = devpriv->ui_DmaBufferUsesize[0];
+ 		high_word = var / 65536;
+ 		outw(APCI3120_ADD_ON_MWTC_LOW, devpriv->i_IobaseAddon + 0);
+@@ -1866,11 +1844,13 @@ void v_APCI3120_InterruptDma(int irq, void *d)
+ 		outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->i_IobaseAddon + 0);
+ 		outw(high_word, devpriv->i_IobaseAddon + 2);
+ 
+-		// To configure A2P FIFO
+-		//ENABLE A2P FIFO WRITE AND ENABLE AMWEN
+-		// AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03
++/*
++ * To configure A2P FIFO
++ * ENABLE A2P FIFO WRITE AND ENABLE AMWEN
++ * AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03
++ */
+ 		outw(3, devpriv->i_IobaseAddon + 4);
+-		//initialise end of dma interrupt  AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI)
++		/* initialise end of dma interrupt  AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI) */
+ 		outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2 |
+ 				APCI3120_ENABLE_WRITE_TC_INT),
+ 			devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);
+@@ -1897,35 +1877,6 @@ void v_APCI3120_InterruptDma(int irq, void *d)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-/*void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,struct comedi_subdevice *s,short *dma,short *data,int n)
+-{
+-	int i,j,m;
+-
+-	j=s->async->cur_chan;
+-	m=devpriv->ui_AiActualScanPosition;
+-        for(i=0;i=devpriv->ui_AiNbrofChannels)
+-		{
+-			m+=j;
+-			j=0;
+-			if(m>=devpriv->ui_AiScanLength)
+-			{
+-				m=0;
+-			        devpriv->ui_AiActualScan++;
+-				if (devpriv->ui_AiFlags & TRIG_WAKE_EOS)
+-;//UPDATE-0.7.57->0.7.68					comedi_eos(dev,s);
+-			}
+-		}
+-	}
+-        devpriv->ui_AiActualScanPosition=m;
+-	s->async->cur_chan=j;
+-
+-}
+-*/
+ void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, short * dma_buffer, unsigned int num_samples)
+ {
+@@ -1979,60 +1930,66 @@ int i_APCI3120_InsnConfigTimer(struct comedi_device * dev, struct comedi_subdevi
+ 	if (!data[1])
+ 		comedi_error(dev, "config:No timer constant !");
+ 
+-	devpriv->b_Timer2Interrupt = (unsigned char) data[2];	// save info whether to enable or disable interrupt
++	devpriv->b_Timer2Interrupt = (unsigned char) data[2];	/*  save info whether to enable or disable interrupt */
+ 
+-	ui_Timervalue2 = data[1] / 1000;	// convert nano seconds  to u seconds
++	ui_Timervalue2 = data[1] / 1000;	/*  convert nano seconds  to u seconds */
+ 
+-	//this_board->i_hwdrv_InsnConfigTimer(dev, ui_Timervalue2,(unsigned char)data[0]);
++	/* this_board->i_hwdrv_InsnConfigTimer(dev, ui_Timervalue2,(unsigned char)data[0]); */
+ 	us_TmpValue = (unsigned short) inw(devpriv->iobase + APCI3120_RD_STATUS);
+ 
+-	//EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001
+-	// and calculate the time value to set in the timer
++/*
++ * EL250804: Testing if board APCI3120 have the new Quartz or if it
++ * is an APCI3001 and calculate the time value to set in the timer
++ */
+ 	if ((us_TmpValue & 0x00B0) == 0x00B0
+ 		|| !strcmp(this_board->pc_DriverName, "apci3001")) {
+-		//Calculate the time value to set in the timer
++		/* Calculate the time value to set in the timer */
+ 		ui_Timervalue2 = ui_Timervalue2 / 50;
+ 	} else {
+-		//Calculate the time value to set in the timer
++		/* Calculate the time value to set in the timer */
+ 		ui_Timervalue2 = ui_Timervalue2 / 70;
+ 	}
+ 
+-	//Reset gate 2 of Timer 2 to disable it (Set Bit D14 to 0)
++	/* Reset gate 2 of Timer 2 to disable it (Set Bit D14 to 0) */
+ 	devpriv->us_OutputRegister =
+ 		devpriv->us_OutputRegister & APCI3120_DISABLE_TIMER2;
+ 	outw(devpriv->us_OutputRegister, devpriv->iobase + APCI3120_WR_ADDRESS);
+ 
+-	// Disable TIMER Interrupt
++	/*  Disable TIMER Interrupt */
+ 	devpriv->b_ModeSelectRegister =
+ 		devpriv->
+ 		b_ModeSelectRegister & APCI3120_DISABLE_TIMER_INT & 0xEF;
+ 
+-	// Disable Eoc and Eos Interrupts
++	/*  Disable Eoc and Eos Interrupts */
+ 	devpriv->b_ModeSelectRegister =
+ 		devpriv->
+ 		b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT &
+ 		APCI3120_DISABLE_EOS_INT;
+ 	outb(devpriv->b_ModeSelectRegister,
+ 		devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
+-	if (data[0] == APCI3120_TIMER)	//initialize timer
++	if (data[0] == APCI3120_TIMER)	/* initialize timer */
+ 	{
++		/* devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister |
++		 * APCI3120_ENABLE_TIMER_INT; */
+ 
+-		//devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister| APCI3120_ENABLE_TIMER_INT ;
+-		//outb(devpriv->b_ModeSelectRegister,devpriv->iobase+APCI3120_WRITE_MODE_SELECT);
++		/* outb(devpriv->b_ModeSelectRegister,devpriv->iobase+APCI3120_WRITE_MODE_SELECT); */
+ 
+-		//Set the Timer 2 in mode 2(Timer)
++		/* Set the Timer 2 in mode 2(Timer) */
+ 		devpriv->b_TimerSelectMode =
+ 			(devpriv->
+ 			b_TimerSelectMode & 0x0F) | APCI3120_TIMER_2_MODE_2;
+ 		outb(devpriv->b_TimerSelectMode,
+ 			devpriv->iobase + APCI3120_TIMER_CRT1);
+ 
+-		//Configure the timer 2 for writing the LOW unsigned short of timer is Delay value
+-		//You must make a b_tmp variable with DigitalOutPutRegister because at Address_1+APCI3120_TIMER_CRT0
+-		//you can set the digital output and configure the timer 2,and if you don't make this, digital output
+-		//are erase (Set to 0)
+-
+-		//Writing LOW unsigned short
++/*
++ * Configure the timer 2 for writing the LOW unsigned short of timer
++ * is Delay value You must make a b_tmp variable with
++ * DigitalOutPutRegister because at Address_1+APCI3120_TIMER_CRT0
++ * you can set the digital output and configure the timer 2,and if
++ * you don't make this, digital output are erase (Set to 0)
++ */
++
++		/* Writing LOW unsigned short */
+ 		b_Tmp = ((devpriv->
+ 				b_DigitalOutputRegister) & 0xF0) |
+ 			APCI3120_SELECT_TIMER_2_LOW_WORD;
+@@ -2040,20 +1997,20 @@ int i_APCI3120_InsnConfigTimer(struct comedi_device * dev, struct comedi_subdevi
+ 		outw(LOWORD(ui_Timervalue2),
+ 			devpriv->iobase + APCI3120_TIMER_VALUE);
+ 
+-		//Writing HIGH unsigned short
++		/* Writing HIGH unsigned short */
+ 		b_Tmp = ((devpriv->
+ 				b_DigitalOutputRegister) & 0xF0) |
+ 			APCI3120_SELECT_TIMER_2_HIGH_WORD;
+ 		outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
+ 		outw(HIWORD(ui_Timervalue2),
+ 			devpriv->iobase + APCI3120_TIMER_VALUE);
+-		// timer2 in Timer mode enabled
++		/*  timer2 in Timer mode enabled */
+ 		devpriv->b_Timer2Mode = APCI3120_TIMER;
+ 
+-	} else			// Initialize Watch dog
++	} else			/*  Initialize Watch dog */
+ 	{
+ 
+-		//Set the Timer 2 in mode 5(Watchdog)
++		/* Set the Timer 2 in mode 5(Watchdog) */
+ 
+ 		devpriv->b_TimerSelectMode =
+ 			(devpriv->
+@@ -2061,12 +2018,15 @@ int i_APCI3120_InsnConfigTimer(struct comedi_device * dev, struct comedi_subdevi
+ 		outb(devpriv->b_TimerSelectMode,
+ 			devpriv->iobase + APCI3120_TIMER_CRT1);
+ 
+-		//Configure the timer 2 for writing the LOW unsigned short of timer is Delay value
+-		//You must make a b_tmp variable with DigitalOutPutRegister because at Address_1+APCI3120_TIMER_CRT0
+-		//you can set the digital output and configure the timer 2,and if you don't make this, digital output
+-		//are erase (Set to 0)
+-
+-		//Writing LOW unsigned short
++/*
++ * Configure the timer 2 for writing the LOW unsigned short of timer
++ * is Delay value You must make a b_tmp variable with
++ * DigitalOutPutRegister because at Address_1+APCI3120_TIMER_CRT0
++ * you can set the digital output and configure the timer 2,and if
++ * you don't make this, digital output are erase (Set to 0)
++ */
++
++		/* Writing LOW unsigned short */
+ 		b_Tmp = ((devpriv->
+ 				b_DigitalOutputRegister) & 0xF0) |
+ 			APCI3120_SELECT_TIMER_2_LOW_WORD;
+@@ -2074,7 +2034,7 @@ int i_APCI3120_InsnConfigTimer(struct comedi_device * dev, struct comedi_subdevi
+ 		outw(LOWORD(ui_Timervalue2),
+ 			devpriv->iobase + APCI3120_TIMER_VALUE);
+ 
+-		//Writing HIGH unsigned short
++		/* Writing HIGH unsigned short */
+ 		b_Tmp = ((devpriv->
+ 				b_DigitalOutputRegister) & 0xF0) |
+ 			APCI3120_SELECT_TIMER_2_HIGH_WORD;
+@@ -2082,7 +2042,7 @@ int i_APCI3120_InsnConfigTimer(struct comedi_device * dev, struct comedi_subdevi
+ 
+ 		outw(HIWORD(ui_Timervalue2),
+ 			devpriv->iobase + APCI3120_TIMER_VALUE);
+-		//watchdog enabled
++		/* watchdog enabled */
+ 		devpriv->b_Timer2Mode = APCI3120_WATCHDOG;
+ 
+ 	}
+@@ -2133,7 +2093,7 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device * dev, struct comedi_subdevic
+ 		return -EINVAL;
+ 	}
+ 
+-	if (data[0] == 2)	// write new value
++	if (data[0] == 2)	/*  write new value */
+ 	{
+ 		if (devpriv->b_Timer2Mode != APCI3120_TIMER) {
+ 			comedi_error(dev,
+@@ -2147,35 +2107,35 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device * dev, struct comedi_subdevic
+ 			ui_Timervalue2 = 0;
+ 	}
+ 
+-	//this_board->i_hwdrv_InsnWriteTimer(dev,data[0],ui_Timervalue2);
++	/* this_board->i_hwdrv_InsnWriteTimer(dev,data[0],ui_Timervalue2); */
+ 
+ 	switch (data[0]) {
+ 	case APCI3120_START:
+ 
+-		// Reset FC_TIMER BIT
++		/*  Reset FC_TIMER BIT */
+ 		inb(devpriv->iobase + APCI3120_TIMER_STATUS_REGISTER);
+-		if (devpriv->b_Timer2Mode == APCI3120_TIMER)	//start timer
++		if (devpriv->b_Timer2Mode == APCI3120_TIMER)	/* start timer */
+ 		{
+-			//Enable Timer
++			/* Enable Timer */
+ 			devpriv->b_ModeSelectRegister =
+ 				devpriv->b_ModeSelectRegister & 0x0B;
+-		} else		//start watch dog
++		} else		/* start watch dog */
+ 		{
+-			//Enable WatchDog
++			/* Enable WatchDog */
+ 			devpriv->b_ModeSelectRegister =
+ 				(devpriv->
+ 				b_ModeSelectRegister & 0x0B) |
+ 				APCI3120_ENABLE_WATCHDOG;
+ 		}
+ 
+-		//enable disable interrupt
++		/* enable disable interrupt */
+ 		if ((devpriv->b_Timer2Interrupt) == APCI3120_ENABLE) {
+ 
+ 			devpriv->b_ModeSelectRegister =
+ 				devpriv->
+ 				b_ModeSelectRegister |
+ 				APCI3120_ENABLE_TIMER_INT;
+-			// save the task structure to pass info to user
++			/*  save the task structure to pass info to user */
+ 			devpriv->tsk_Current = current;
+ 		} else {
+ 
+@@ -2187,9 +2147,9 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device * dev, struct comedi_subdevic
+ 		outb(devpriv->b_ModeSelectRegister,
+ 			devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
+ 
+-		if (devpriv->b_Timer2Mode == APCI3120_TIMER)	//start timer
++		if (devpriv->b_Timer2Mode == APCI3120_TIMER)	/* start timer */
+ 		{
+-			//For Timer mode is  Gate2 must be activated   **timer started
++			/* For Timer mode is  Gate2 must be activated   **timer started */
+ 			devpriv->us_OutputRegister =
+ 				devpriv->
+ 				us_OutputRegister | APCI3120_ENABLE_TIMER2;
+@@ -2201,62 +2161,64 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device * dev, struct comedi_subdevic
+ 
+ 	case APCI3120_STOP:
+ 		if (devpriv->b_Timer2Mode == APCI3120_TIMER) {
+-			//Disable timer
++			/* Disable timer */
+ 			devpriv->b_ModeSelectRegister =
+ 				devpriv->
+ 				b_ModeSelectRegister &
+ 				APCI3120_DISABLE_TIMER_COUNTER;
+ 		} else {
+-			//Disable WatchDog
++			/* Disable WatchDog */
+ 			devpriv->b_ModeSelectRegister =
+ 				devpriv->
+ 				b_ModeSelectRegister &
+ 				APCI3120_DISABLE_WATCHDOG;
+ 		}
+-		// Disable timer interrupt
++		/*  Disable timer interrupt */
+ 		devpriv->b_ModeSelectRegister =
+ 			devpriv->
+ 			b_ModeSelectRegister & APCI3120_DISABLE_TIMER_INT;
+ 
+-		// Write above states  to register
++		/*  Write above states  to register */
+ 		outb(devpriv->b_ModeSelectRegister,
+ 			devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
+ 
+-		// Reset Gate 2
++		/*  Reset Gate 2 */
+ 		devpriv->us_OutputRegister =
+ 			devpriv->us_OutputRegister & APCI3120_DISABLE_TIMER_INT;
+ 		outw(devpriv->us_OutputRegister,
+ 			devpriv->iobase + APCI3120_WR_ADDRESS);
+ 
+-		// Reset FC_TIMER BIT
++		/*  Reset FC_TIMER BIT */
+ 		inb(devpriv->iobase + APCI3120_TIMER_STATUS_REGISTER);
+ 
+-		// Disable timer
+-		//devpriv->b_Timer2Mode=APCI3120_DISABLE;
++		/* Disable timer */
++		/* devpriv->b_Timer2Mode=APCI3120_DISABLE;  */
+ 
+ 		break;
+ 
+-	case 2:		//write new value to Timer
++	case 2:		/* write new value to Timer */
+ 		if (devpriv->b_Timer2Mode != APCI3120_TIMER) {
+ 			comedi_error(dev,
+ 				"write :timer2  not configured  in TIMER MODE");
+ 			return -EINVAL;
+ 		}
+-		// ui_Timervalue2=data[1]; // passed as argument
++		/*  ui_Timervalue2=data[1]; // passed as argument */
+ 		us_TmpValue =
+ 			(unsigned short) inw(devpriv->iobase + APCI3120_RD_STATUS);
+ 
+-		//EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001
+-		// and calculate the time value to set in the timer
++/*
++ * EL250804: Testing if board APCI3120 have the new Quartz or if it
++ * is an APCI3001 and calculate the time value to set in the timer
++ */
+ 		if ((us_TmpValue & 0x00B0) == 0x00B0
+ 			|| !strcmp(this_board->pc_DriverName, "apci3001")) {
+-			//Calculate the time value to set in the timer
++			/* Calculate the time value to set in the timer */
+ 			ui_Timervalue2 = ui_Timervalue2 / 50;
+ 		} else {
+-			//Calculate the time value to set in the timer
++			/* Calculate the time value to set in the timer */
+ 			ui_Timervalue2 = ui_Timervalue2 / 70;
+ 		}
+-		//Writing LOW unsigned short
++		/* Writing LOW unsigned short */
+ 		b_Tmp = ((devpriv->
+ 				b_DigitalOutputRegister) & 0xF0) |
+ 			APCI3120_SELECT_TIMER_2_LOW_WORD;
+@@ -2265,7 +2227,7 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device * dev, struct comedi_subdevic
+ 		outw(LOWORD(ui_Timervalue2),
+ 			devpriv->iobase + APCI3120_TIMER_VALUE);
+ 
+-		//Writing HIGH unsigned short
++		/* Writing HIGH unsigned short */
+ 		b_Tmp = ((devpriv->
+ 				b_DigitalOutputRegister) & 0xF0) |
+ 			APCI3120_SELECT_TIMER_2_HIGH_WORD;
+@@ -2276,7 +2238,7 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device * dev, struct comedi_subdevic
+ 
+ 		break;
+ 	default:
+-		return -EINVAL;	// Not a valid input
++		return -EINVAL;	/*  Not a valid input */
+ 	}
+ 
+ 	return insn->n;
+@@ -2316,10 +2278,10 @@ int i_APCI3120_InsnReadTimer(struct comedi_device * dev, struct comedi_subdevice
+ 		comedi_error(dev, "\nread:timer2  not configured ");
+ 	}
+ 
+-	//this_board->i_hwdrv_InsnReadTimer(dev,data);
++	/* this_board->i_hwdrv_InsnReadTimer(dev,data); */
+ 	if (devpriv->b_Timer2Mode == APCI3120_TIMER) {
+ 
+-		//Read the LOW unsigned short of Timer 2 register
++		/* Read the LOW unsigned short of Timer 2 register */
+ 		b_Tmp = ((devpriv->
+ 				b_DigitalOutputRegister) & 0xF0) |
+ 			APCI3120_SELECT_TIMER_2_LOW_WORD;
+@@ -2327,7 +2289,7 @@ int i_APCI3120_InsnReadTimer(struct comedi_device * dev, struct comedi_subdevice
+ 
+ 		us_TmpValue = inw(devpriv->iobase + APCI3120_TIMER_VALUE);
+ 
+-		//Read the HIGH unsigned short of Timer 2 register
++		/* Read the HIGH unsigned short of Timer 2 register */
+ 		b_Tmp = ((devpriv->
+ 				b_DigitalOutputRegister) & 0xF0) |
+ 			APCI3120_SELECT_TIMER_2_HIGH_WORD;
+@@ -2335,20 +2297,20 @@ int i_APCI3120_InsnReadTimer(struct comedi_device * dev, struct comedi_subdevice
+ 
+ 		us_TmpValue_2 = inw(devpriv->iobase + APCI3120_TIMER_VALUE);
+ 
+-		// combining both words
++		/*  combining both words */
+ 		data[0] = (unsigned int) ((us_TmpValue) | ((us_TmpValue_2) << 16));
+ 
+-	} else			// Read watch dog status
++	} else			/*  Read watch dog status */
+ 	{
+ 
+ 		us_StatusValue = inw(devpriv->iobase + APCI3120_RD_STATUS);
+ 		us_StatusValue =
+ 			((us_StatusValue & APCI3120_FC_TIMER) >> 12) & 1;
+ 		if (us_StatusValue == 1) {
+-			// RESET FC_TIMER BIT
++			/*  RESET FC_TIMER BIT */
+ 			inb(devpriv->iobase + APCI3120_TIMER_STATUS_REGISTER);
+ 		}
+-		data[0] = us_StatusValue;	// when data[0] = 1 then the watch dog has rundown
++		data[0] = us_StatusValue;	/*  when data[0] = 1 then the watch dog has rundown */
+ 	}
+ 	return insn->n;
+ }
+@@ -2386,19 +2348,21 @@ int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev,
+ {
+ 	unsigned int ui_Chan, ui_TmpValue;
+ 
+-	ui_Chan = CR_CHAN(insn->chanspec);	// channel specified
++	ui_Chan = CR_CHAN(insn->chanspec);	/*  channel specified */
+ 
+-	//this_board->i_hwdrv_InsnReadDigitalInput(dev,ui_Chan,data);
++	/* this_board->i_hwdrv_InsnReadDigitalInput(dev,ui_Chan,data); */
+ 	if (ui_Chan >= 0 && ui_Chan <= 3) {
+ 		ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI3120_RD_STATUS);
+ 
+-		//      since only 1 channel reqd  to bring it to last bit it is rotated
+-		//  8 +(chan - 1) times then ANDed with 1 for last bit.
++/*
++ * since only 1 channel reqd to bring it to last bit it is rotated 8
++ * +(chan - 1) times then ANDed with 1 for last bit.
++ */
+ 		*data = (ui_TmpValue >> (ui_Chan + 8)) & 1;
+-		//return 0;
++		/* return 0; */
+ 	} else {
+-		//      comedi_error(dev," chan spec wrong");
+-		return -EINVAL;	// "sorry channel spec wrong "
++		/*       comedi_error(dev," chan spec wrong"); */
++		return -EINVAL;	/*  "sorry channel spec wrong " */
+ 	}
+ 	return insn->n;
+ 
+@@ -2434,7 +2398,7 @@ int i_APCI3120_InsnBitsDigitalInput(struct comedi_device * dev, struct comedi_su
+ 	*****/
+ 
+ 	*data = (ui_TmpValue >> 8) & 0xf;
+-	//this_board->i_hwdrv_InsnBitsDigitalInput(dev,data);
++	/* this_board->i_hwdrv_InsnBitsDigitalInput(dev,data); */
+ 	return insn->n;
+ }
+ 
+@@ -2481,7 +2445,7 @@ int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device * dev,
+ 	if (!devpriv->b_OutputMemoryStatus) {
+ 		ui_Temp = 0;
+ 
+-	}			//if(!devpriv->b_OutputMemoryStatus )
++	}			/* if(!devpriv->b_OutputMemoryStatus ) */
+ 
+ 	return insn->n;
+ }
+@@ -2530,7 +2494,7 @@ int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device * dev,
+ 	default:
+ 		printk("\nThe parameter passed is in error \n");
+ 		return -EINVAL;
+-	}			// switch(data[1])
++	}			/*  switch(data[1]) */
+ 	outb(data[0], devpriv->iobase + APCI3120_DIGITAL_OUTPUT);
+ 
+ 	devpriv->b_DigitalOutputRegister = data[0] & 0xF0;
+@@ -2569,7 +2533,7 @@ int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev,
+ 
+ 	unsigned int ui_Temp1;
+ 
+-	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
++	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	/*  get the channel */
+ 
+ 	if ((data[0] != 0) && (data[0] != 1)) {
+ 		comedi_error(dev,
+@@ -2586,7 +2550,7 @@ int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev,
+ 	switch (data[1]) {
+ 	case 1:
+ 		data[0] = (data[0] << ui_NoOfChannel);
+-//ES05                   data[0]=(data[0]<<4)|ui_Temp;
++/* ES05                   data[0]=(data[0]<<4)|ui_Temp; */
+ 		data[0] = (data[0] << 4) | devpriv->b_DigitalOutputRegister;
+ 		break;
+ 
+@@ -2595,22 +2559,22 @@ int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev,
+ 		ui_Temp1 = 1;
+ 		ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
+ 		ui_Temp1 = ui_Temp1 << 4;
+-//ES05                   ui_Temp=ui_Temp|ui_Temp1;
++/* ES05                   ui_Temp=ui_Temp|ui_Temp1; */
+ 		devpriv->b_DigitalOutputRegister =
+ 			devpriv->b_DigitalOutputRegister | ui_Temp1;
+ 
+ 		data[0] = (data[0] << ui_NoOfChannel) ^ 0xf;
+ 		data[0] = data[0] << 4;
+-//ES05                   data[0]=data[0]& ui_Temp;
++/* ES05                   data[0]=data[0]& ui_Temp; */
+ 		data[0] = data[0] & devpriv->b_DigitalOutputRegister;
+ 		break;
+ 	default:
+ 		printk("\nThe parameter passed is in error \n");
+ 		return -EINVAL;
+-	}			// switch(data[1])
++	}			/*  switch(data[1]) */
+ 	outb(data[0], devpriv->iobase + APCI3120_DIGITAL_OUTPUT);
+ 
+-//ES05        ui_Temp=data[0] & 0xf0;
++/* ES05        ui_Temp=data[0] & 0xf0; */
+ 	devpriv->b_DigitalOutputRegister = data[0] & 0xf0;
+ 	return (insn->n);
+ 
+@@ -2652,8 +2616,8 @@ int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev,
+ 	ui_Range = CR_RANGE(insn->chanspec);
+ 	ui_Channel = CR_CHAN(insn->chanspec);
+ 
+-	//this_board->i_hwdrv_InsnWriteAnalogOutput(dev, ui_Range, ui_Channel,data[0]);
+-	if (ui_Range)		// if 1 then unipolar
++	/* this_board->i_hwdrv_InsnWriteAnalogOutput(dev, ui_Range, ui_Channel,data[0]); */
++	if (ui_Range)		/*  if 1 then unipolar */
+ 	{
+ 
+ 		if (data[0] != 0)
+@@ -2665,7 +2629,7 @@ int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev,
+ 				((((ui_Channel & 0x03) << 14) & 0xC000) | (1 <<
+ 					13) | 8192);
+ 
+-	} else			// if 0 then   bipolar
++	} else			/*  if 0 then   bipolar */
+ 	{
+ 		data[0] =
+ 			((((ui_Channel & 0x03) << 14) & 0xC000) | (0 << 13) |
+@@ -2673,9 +2637,11 @@ int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev,
+ 
+ 	}
+ 
+-	//out put n values at the given channel.
+-	// rt_printk("\nwaiting for DA_READY BIT");
+-	do			//Waiting of DA_READY BIT
++/*
++ * out put n values at the given channel. rt_printk("\nwaiting for
++ * DA_READY BIT");
++ */
++	do			/* Waiting of DA_READY BIT */
+ 	{
+ 		us_TmpValue =
+ 			((unsigned short) inw(devpriv->iobase +
+@@ -2683,13 +2649,17 @@ int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev,
+ 	} while (us_TmpValue != 0x0001);
+ 
+ 	if (ui_Channel <= 3)
+-		// for channel 0-3 out at  the register 1 (wrDac1-8)
+-		// data[i] typecasted to ushort since  word write is to be done
++/*
++ * for channel 0-3 out at the register 1 (wrDac1-8) data[i]
++ * typecasted to ushort since word write is to be done
++ */
+ 		outw((unsigned short) data[0],
+ 			devpriv->iobase + APCI3120_ANALOG_OUTPUT_1);
+ 	else
+-		// for channel 4-7 out at the register 2 (wrDac5-8)
+-		//data[i] typecasted to ushort since  word write is to be done
++/*
++ * for channel 4-7 out at the register 2 (wrDac5-8) data[i]
++ * typecasted to ushort since word write is to be done
++ */
+ 		outw((unsigned short) data[0],
+ 			devpriv->iobase + APCI3120_ANALOG_OUTPUT_2);
+ 

commit f147598bc19efbb6ef1f34ae022b2d29d3ca3837
+Author: Bill Pemberton 
+Date:   Fri Mar 27 11:30:07 2009 -0400
+
+    Staging: comedi: remove C99 comments in hwdrv_apci3200.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+index 64dc68c112dd..8981b0feaba7 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+@@ -57,21 +57,21 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+   +----------------------------------------------------------------------------+
+ */
+ #include "hwdrv_apci3200.h"
+-//Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++/* Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ #include "addi_amcc_S5920.h"
+-//#define PRINT_INFO
++/* #define PRINT_INFO */
+ 
+-//End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++/* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ 
+-//BEGIN JK 06.07.04: Management of sevrals boards
++/* BEGIN JK 06.07.04: Management of sevrals boards */
+ /*
+   int i_CJCAvailable=1;
+   int i_CJCPolarity=0;
+-  int i_CJCGain=2;//changed from 0 to 2
++  int i_CJCGain=2;/* changed from 0 to 2 */
+   int i_InterruptFlag=0;
+   int i_ADDIDATAPolarity;
+   int i_ADDIDATAGain;
+-  int i_AutoCalibration=0;   //: auto calibration
++  int i_AutoCalibration=0;   /* : auto calibration */
+   int i_ADDIDATAConversionTime;
+   int i_ADDIDATAConversionTimeUnit;
+   int i_ADDIDATAType;
+@@ -85,12 +85,12 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+   unsigned int ui_Channel_num=0;
+   static int i_Count=0;
+   int i_Initialised=0;
+-  unsigned int ui_InterruptChannelValue[96]; //Buffer
++  unsigned int ui_InterruptChannelValue[96]; /* Buffer */
+ */
+-struct str_BoardInfos s_BoardInfos[100];	// 100 will be the max number of boards to be used
+-//END JK 06.07.04: Management of sevrals boards
++struct str_BoardInfos s_BoardInfos[100];	/*  100 will be the max number of boards to be used */
++/* END JK 06.07.04: Management of sevrals boards */
+ 
+-//Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++/* Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ 
+ /*+----------------------------------------------------------------------------+*/
+ /*| Function   Name   : int i_AddiHeaderRW_ReadEeprom                          |*/
+@@ -136,15 +136,15 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 		while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+ 		for (i_Counter = 0; i_Counter < 2; i_Counter++) {
+-			b_SelectedAddressLow = (w_EepromStartAddress + i_Counter) % 256;	//Read the low 8 bit part
+-			b_SelectedAddressHigh = (w_EepromStartAddress + i_Counter) / 256;	//Read the high 8 bit part
++			b_SelectedAddressLow = (w_EepromStartAddress + i_Counter) % 256;	/* Read the low 8 bit part */
++			b_SelectedAddressHigh = (w_EepromStartAddress + i_Counter) / 256;	/* Read the high 8 bit part */
+ 
+-			//Select the load low address mode
++			/* Select the load low address mode */
+ 			outb(NVCMD_LOAD_LOW,
+ 				dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+ 				3);
+ 
+-			//Wait on busy
++			/* Wait on busy */
+ 			do {
+ 				dw_eeprom_busy =
+ 					inl(dw_PCIBoardEepromAddress +
+@@ -153,12 +153,12 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 			}
+ 			while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+-			//Load the low address
++			/* Load the low address */
+ 			outb(b_SelectedAddressLow,
+ 				dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+ 				2);
+ 
+-			//Wait on busy
++			/* Wait on busy */
+ 			do {
+ 				dw_eeprom_busy =
+ 					inl(dw_PCIBoardEepromAddress +
+@@ -167,12 +167,12 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 			}
+ 			while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+-			//Select the load high address mode
++			/* Select the load high address mode */
+ 			outb(NVCMD_LOAD_HIGH,
+ 				dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+ 				3);
+ 
+-			//Wait on busy
++			/* Wait on busy */
+ 			do {
+ 				dw_eeprom_busy =
+ 					inl(dw_PCIBoardEepromAddress +
+@@ -181,12 +181,12 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 			}
+ 			while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+-			//Load the high address
++			/* Load the high address */
+ 			outb(b_SelectedAddressHigh,
+ 				dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+ 				2);
+ 
+-			//Wait on busy
++			/* Wait on busy */
+ 			do {
+ 				dw_eeprom_busy =
+ 					inl(dw_PCIBoardEepromAddress +
+@@ -195,12 +195,12 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 			}
+ 			while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+-			//Select the READ mode
++			/* Select the READ mode */
+ 			outb(NVCMD_BEGIN_READ,
+ 				dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+ 				3);
+ 
+-			//Wait on busy
++			/* Wait on busy */
+ 			do {
+ 				dw_eeprom_busy =
+ 					inl(dw_PCIBoardEepromAddress +
+@@ -209,12 +209,12 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 			}
+ 			while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+-			//Read data into the EEPROM
++			/* Read data into the EEPROM */
+ 			*pb_ReadByte =
+ 				inb(dw_PCIBoardEepromAddress +
+ 				AMCC_OP_REG_MCSR + 2);
+ 
+-			//Wait on busy
++			/* Wait on busy */
+ 			do {
+ 				dw_eeprom_busy =
+ 					inl(dw_PCIBoardEepromAddress +
+@@ -223,14 +223,14 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 			}
+ 			while (dw_eeprom_busy == EEPROM_BUSY);
+ 
+-			//Select the upper address part
++			/* Select the upper address part */
+ 			if (i_Counter == 0) {
+ 				b_ReadLowByte = pb_ReadByte[0];
+ 			} else {
+ 				b_ReadHighByte = pb_ReadByte[0];
+ 			}
+ 
+-			//Sleep
++			/* Sleep */
+ 			for (i = 0; i < 10000; i++) ;
+ 
+ 		}
+@@ -240,9 +240,9 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 
+ 		pw_DataRead[i_WordCounter] = w_ReadWord;
+ 
+-		w_EepromStartAddress += 2;	// to read the next word
++		w_EepromStartAddress += 2;	/*  to read the next word */
+ 
+-	}			// for (...) i_NbOfWordsToRead
++	}			/*  for (...) i_NbOfWordsToRead */
+ 	return (0);
+ }
+ 
+@@ -281,8 +281,8 @@ void v_GetAPCI3200EepromCalibrationValue(unsigned int dw_PCIBoardEepromAddress,
+   /*****************************************/
+   /** Get the Analog input header address **/
+   /*****************************************/
+-	i_AddiHeaderRW_ReadEeprom(1,	//i_NbOfWordsToRead
+-		dw_PCIBoardEepromAddress, 0x116,	//w_EepromStartAddress: Analog input header address
++	i_AddiHeaderRW_ReadEeprom(1,	/* i_NbOfWordsToRead */
++		dw_PCIBoardEepromAddress, 0x116,	/* w_EepromStartAddress: Analog input header address */
+ 		&w_AnalogInputMainHeaderAddress);
+ 
+   /*******************************************/
+@@ -293,8 +293,8 @@ void v_GetAPCI3200EepromCalibrationValue(unsigned int dw_PCIBoardEepromAddress,
+   /******************************/
+   /** Get the number of moduls **/
+   /******************************/
+-	i_AddiHeaderRW_ReadEeprom(1,	//i_NbOfWordsToRead
+-		dw_PCIBoardEepromAddress, w_AnalogInputMainHeaderAddress + 0x02,	//w_EepromStartAddress: Number of conponment
++	i_AddiHeaderRW_ReadEeprom(1,	/* i_NbOfWordsToRead */
++		dw_PCIBoardEepromAddress, w_AnalogInputMainHeaderAddress + 0x02,	/* w_EepromStartAddress: Number of conponment */
+ 		&w_NumberOfModuls);
+ 
+ 	for (w_ModulCounter = 0; w_ModulCounter < w_NumberOfModuls;
+@@ -309,8 +309,8 @@ void v_GetAPCI3200EepromCalibrationValue(unsigned int dw_PCIBoardEepromAddress,
+       /****************************/
+       /** Read first header size **/
+       /****************************/
+-		i_AddiHeaderRW_ReadEeprom(1,	//i_NbOfWordsToRead
+-			dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress,	// Address of the first header
++		i_AddiHeaderRW_ReadEeprom(1,	/* i_NbOfWordsToRead */
++			dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress,	/*  Address of the first header */
+ 			&w_FirstHeaderSize);
+ 
+ 		w_FirstHeaderSize = w_FirstHeaderSize >> 4;
+@@ -318,8 +318,8 @@ void v_GetAPCI3200EepromCalibrationValue(unsigned int dw_PCIBoardEepromAddress,
+       /***************************/
+       /** Read number of inputs **/
+       /***************************/
+-		i_AddiHeaderRW_ReadEeprom(1,	//i_NbOfWordsToRead
+-			dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 0x06,	// Number of inputs for the first modul
++		i_AddiHeaderRW_ReadEeprom(1,	/* i_NbOfWordsToRead */
++			dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 0x06,	/*  Number of inputs for the first modul */
+ 			&w_NumberOfInputs);
+ 
+ 		w_NumberOfInputs = w_NumberOfInputs >> 4;
+@@ -327,17 +327,17 @@ void v_GetAPCI3200EepromCalibrationValue(unsigned int dw_PCIBoardEepromAddress,
+       /***********************/
+       /** Read the CJC flag **/
+       /***********************/
+-		i_AddiHeaderRW_ReadEeprom(1,	//i_NbOfWordsToRead
+-			dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 0x08,	// CJC flag
++		i_AddiHeaderRW_ReadEeprom(1,	/* i_NbOfWordsToRead */
++			dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 0x08,	/*  CJC flag */
+ 			&w_CJCFlag);
+ 
+-		w_CJCFlag = (w_CJCFlag >> 3) & 0x1;	// Get only the CJC flag
++		w_CJCFlag = (w_CJCFlag >> 3) & 0x1;	/*  Get only the CJC flag */
+ 
+       /*******************************/
+       /** Read number of gain value **/
+       /*******************************/
+-		i_AddiHeaderRW_ReadEeprom(1,	//i_NbOfWordsToRead
+-			dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 0x44,	// Number of gain value
++		i_AddiHeaderRW_ReadEeprom(1,	/* i_NbOfWordsToRead */
++			dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 0x44,	/*  Number of gain value */
+ 			&w_NumberOfGainValue);
+ 
+ 		w_NumberOfGainValue = w_NumberOfGainValue & 0xFF;
+@@ -354,8 +354,8 @@ void v_GetAPCI3200EepromCalibrationValue(unsigned int dw_PCIBoardEepromAddress,
+       /********************************************/
+       /** Read current sources value for input 1 **/
+       /********************************************/
+-		i_AddiHeaderRW_ReadEeprom(1,	//i_NbOfWordsToRead
+-			dw_PCIBoardEepromAddress, w_SingleHeaderAddress,	//w_EepromStartAddress: Single header address
++		i_AddiHeaderRW_ReadEeprom(1,	/* i_NbOfWordsToRead */
++			dw_PCIBoardEepromAddress, w_SingleHeaderAddress,	/* w_EepromStartAddress: Single header address */
+ 			&w_SingleHeaderSize);
+ 
+ 		w_SingleHeaderSize = w_SingleHeaderSize >> 4;
+@@ -370,8 +370,8 @@ void v_GetAPCI3200EepromCalibrationValue(unsigned int dw_PCIBoardEepromAddress,
+ 	  /************************************/
+ 	  /** Read gain value for the module **/
+ 	  /************************************/
+-			i_AddiHeaderRW_ReadEeprom(1,	//i_NbOfWordsToRead
+-				dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 70 + (2 * (1 + (w_NumberOfGainValue / 16))) + (0x02 * w_GainIndex),	// Gain value
++			i_AddiHeaderRW_ReadEeprom(1,	/* i_NbOfWordsToRead */
++				dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 70 + (2 * (1 + (w_NumberOfGainValue / 16))) + (0x02 * w_GainIndex),	/*  Gain value */
+ 				&w_GainValue);
+ 
+ 			BoardInformations->s_Module[w_ModulCounter].
+@@ -386,8 +386,8 @@ void v_GetAPCI3200EepromCalibrationValue(unsigned int dw_PCIBoardEepromAddress,
+ 	  /*************************************/
+ 	  /** Read gain factor for the module **/
+ 	  /*************************************/
+-			i_AddiHeaderRW_ReadEeprom(2,	//i_NbOfWordsToRead
+-				dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 70 + ((2 * w_NumberOfGainValue) + (2 * (1 + (w_NumberOfGainValue / 16)))) + (0x04 * w_GainIndex),	// Gain factor
++			i_AddiHeaderRW_ReadEeprom(2,	/* i_NbOfWordsToRead */
++				dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 70 + ((2 * w_NumberOfGainValue) + (2 * (1 + (w_NumberOfGainValue / 16)))) + (0x04 * w_GainIndex),	/*  Gain factor */
+ 				w_GainFactorValue);
+ 
+ 			BoardInformations->s_Module[w_ModulCounter].
+@@ -409,7 +409,7 @@ void v_GetAPCI3200EepromCalibrationValue(unsigned int dw_PCIBoardEepromAddress,
+ 	  /********************************************/
+ 	  /** Read current sources value for input 1 **/
+ 	  /********************************************/
+-			i_AddiHeaderRW_ReadEeprom(2,	//i_NbOfWordsToRead
++			i_AddiHeaderRW_ReadEeprom(2,	/* i_NbOfWordsToRead */
+ 				dw_PCIBoardEepromAddress,
+ 				(w_Input * w_SingleHeaderSize) +
+ 				w_SingleHeaderAddress + 0x0C, w_CurrentSources);
+@@ -432,7 +432,7 @@ void v_GetAPCI3200EepromCalibrationValue(unsigned int dw_PCIBoardEepromAddress,
+       /***************************************/
+       /** Read the CJC current source value **/
+       /***************************************/
+-		i_AddiHeaderRW_ReadEeprom(2,	//i_NbOfWordsToRead
++		i_AddiHeaderRW_ReadEeprom(2,	/* i_NbOfWordsToRead */
+ 			dw_PCIBoardEepromAddress,
+ 			(w_Input * w_SingleHeaderSize) + w_SingleHeaderAddress +
+ 			0x0C, w_CurrentSources);
+@@ -464,9 +464,9 @@ int i_APCI3200_GetChannelCalibrationValue(struct comedi_device * dev,
+ 	printk("\n Channel = %u", ui_Channel_num);
+ #endif
+ 
+-	//Test if single or differential mode
++	/* Test if single or differential mode */
+ 	if (s_BoardInfos[dev->minor].i_ConnectionType == 1) {
+-		//if diff
++		/* if diff */
+ 
+ 		if ((ui_Channel_num >= 0) && (ui_Channel_num <= 1))
+ 			i_DiffChannel = ui_Channel_num, i_Module = 0;
+@@ -478,7 +478,7 @@ int i_APCI3200_GetChannelCalibrationValue(struct comedi_device * dev,
+ 			i_DiffChannel = ui_Channel_num - 6, i_Module = 3;
+ 
+ 	} else {
+-		// if single
++		/*  if single */
+ 		if ((ui_Channel_num == 0) || (ui_Channel_num == 1))
+ 			i_DiffChannel = 0, i_Module = 0;
+ 		else if ((ui_Channel_num == 2) || (ui_Channel_num == 3))
+@@ -497,7 +497,7 @@ int i_APCI3200_GetChannelCalibrationValue(struct comedi_device * dev,
+ 			i_DiffChannel = 1, i_Module = 3;
+ 	}
+ 
+-	//Test if thermocouple or RTD mode
++	/* Test if thermocouple or RTD mode */
+ 	*CJCCurrentSource =
+ 		s_BoardInfos[dev->minor].s_Module[i_Module].ul_CurrentSourceCJC;
+ #ifdef PRINT_INFO
+@@ -510,22 +510,22 @@ int i_APCI3200_GetChannelCalibrationValue(struct comedi_device * dev,
+ #ifdef PRINT_INFO
+ 	printk("\n ChannelCurrentSource = %lu", *ChannelCurrentSource);
+ #endif
+-	//      }
+-	//   }
++	/*       } */
++	/*    } */
+ 
+-	//Channle gain factor
++	/* Channle gain factor */
+ 	*ChannelGainFactor =
+ 		s_BoardInfos[dev->minor].s_Module[i_Module].
+ 		ul_GainFactor[s_BoardInfos[dev->minor].i_ADDIDATAGain];
+ #ifdef PRINT_INFO
+ 	printk("\n ChannelGainFactor = %lu", *ChannelGainFactor);
+ #endif
+-	//End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++	/* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ 
+ 	return (0);
+ }
+ 
+-//End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++/* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ 
+ /*
+   +----------------------------------------------------------------------------+
+@@ -561,13 +561,13 @@ int i_APCI3200_ReadDigitalInput(struct comedi_device * dev, struct comedi_subdev
+ 
+ 	if (ui_Temp == 0) {
+ 		*data = (*data >> ui_NoOfChannel) & 0x1;
+-	}			//if  (ui_Temp==0)
++	}			/* if  (ui_Temp==0) */
+ 	else {
+ 		if (ui_Temp == 1) {
+ 			if (data[1] < 0 || data[1] > 1) {
+ 				printk("\nThe port number is in error\n");
+ 				return -EINVAL;
+-			}	//if(data[1] < 0 || data[1] >1)
++			}	/* if(data[1] < 0 || data[1] >1) */
+ 			switch (ui_NoOfChannel) {
+ 
+ 			case 2:
+@@ -578,13 +578,13 @@ int i_APCI3200_ReadDigitalInput(struct comedi_device * dev, struct comedi_subdev
+ 				break;
+ 			default:
+ 				comedi_error(dev, " chan spec wrong");
+-				return -EINVAL;	// "sorry channel spec wrong "
++				return -EINVAL;	/*  "sorry channel spec wrong " */
+ 
+-			}	//switch(ui_NoOfChannels)
+-		}		//if  (ui_Temp==1)
++			}	/* switch(ui_NoOfChannels) */
++		}		/* if  (ui_Temp==1) */
+ 		else {
+ 			printk("\nSpecified channel not supported \n");
+-		}		//elseif  (ui_Temp==1)
++		}		/* elseif  (ui_Temp==1) */
+ 	}
+ 	return insn->n;
+ }
+@@ -616,13 +616,13 @@ int i_APCI3200_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ 		comedi_error(dev,
+ 			"Not a valid Data !!! ,Data should be 1 or 0\n");
+ 		return -EINVAL;
+-	}			//if  ( (data[0]!=0) && (data[0]!=1) )
++	}			/* if  ( (data[0]!=0) && (data[0]!=1) ) */
+ 	if (data[0]) {
+ 		devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
+-	}			// if  (data[0])
++	}			/*  if  (data[0]) */
+ 	else {
+ 		devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
+-	}			//else if  (data[0])
++	}			/* else if  (data[0]) */
+ 	return insn->n;
+ }
+ 
+@@ -657,19 +657,19 @@ int i_APCI3200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int ui_Temp = 0, ui_Temp1 = 0;
+-	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
++	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	/*  get the channel */
+ 	if (devpriv->b_OutputMemoryStatus) {
+ 		ui_Temp = inl(devpriv->i_IobaseAddon);
+ 
+-	}			//if(devpriv->b_OutputMemoryStatus )
++	}			/* if(devpriv->b_OutputMemoryStatus ) */
+ 	else {
+ 		ui_Temp = 0;
+-	}			//if(devpriv->b_OutputMemoryStatus )
++	}			/* if(devpriv->b_OutputMemoryStatus ) */
+ 	if (data[3] == 0) {
+ 		if (data[1] == 0) {
+ 			data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
+ 			outl(data[0], devpriv->i_IobaseAddon);
+-		}		//if(data[1]==0)
++		}		/* if(data[1]==0) */
+ 		else {
+ 			if (data[1] == 1) {
+ 				switch (ui_NoOfChannel) {
+@@ -682,15 +682,15 @@ int i_APCI3200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 				case 3:
+ 					data[0] = (data[0] | ui_Temp);
+ 					break;
+-				}	//switch(ui_NoOfChannels)
++				}	/* switch(ui_NoOfChannels) */
+ 
+ 				outl(data[0], devpriv->i_IobaseAddon);
+-			}	// if(data[1]==1)
++			}	/*  if(data[1]==1) */
+ 			else {
+ 				printk("\nSpecified channel not supported\n");
+-			}	//else if(data[1]==1)
+-		}		//elseif(data[1]==0)
+-	}			//if(data[3]==0)
++			}	/* else if(data[1]==1) */
++		}		/* elseif(data[1]==0) */
++	}			/* if(data[3]==0) */
+ 	else {
+ 		if (data[3] == 1) {
+ 			if (data[1] == 0) {
+@@ -701,7 +701,7 @@ int i_APCI3200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 				data[0] = (data[0] << ui_NoOfChannel) ^ 0xf;
+ 				data[0] = data[0] & ui_Temp;
+ 				outl(data[0], devpriv->i_IobaseAddon);
+-			}	//if(data[1]==0)
++			}	/* if(data[1]==0) */
+ 			else {
+ 				if (data[1] == 1) {
+ 					switch (ui_NoOfChannel) {
+@@ -725,21 +725,21 @@ int i_APCI3200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 					default:
+ 						comedi_error(dev,
+ 							" chan spec wrong");
+-						return -EINVAL;	// "sorry channel spec wrong "
+-					}	//switch(ui_NoOfChannels)
++						return -EINVAL;	/*  "sorry channel spec wrong " */
++					}	/* switch(ui_NoOfChannels) */
+ 
+ 					outl(data[0], devpriv->i_IobaseAddon);
+-				}	// if(data[1]==1)
++				}	/*  if(data[1]==1) */
+ 				else {
+ 					printk("\nSpecified channel not supported\n");
+-				}	//else if(data[1]==1)
+-			}	//elseif(data[1]==0)
+-		}		//if(data[3]==1);
++				}	/* else if(data[1]==1) */
++			}	/* elseif(data[1]==0) */
++		}		/* if(data[3]==1); */
+ 		else {
+ 			printk("\nSpecified functionality does not exist\n");
+ 			return -EINVAL;
+-		}		//if else data[3]==1)
+-	}			//if else data[3]==0)
++		}		/* if else data[3]==1) */
++	}			/* if else data[3]==0) */
+ 	return insn->n;
+ }
+ 
+@@ -776,13 +776,13 @@ int i_APCI3200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ 	*data = inl(devpriv->i_IobaseAddon);
+ 	if (ui_Temp == 0) {
+ 		*data = (*data >> ui_NoOfChannel) & 0x1;
+-	}			// if  (ui_Temp==0)
++	}			/*  if  (ui_Temp==0) */
+ 	else {
+ 		if (ui_Temp == 1) {
+ 			if (data[1] < 0 || data[1] > 1) {
+ 				printk("\nThe port selection is in error\n");
+ 				return -EINVAL;
+-			}	//if(data[1] <0 ||data[1] >1)
++			}	/* if(data[1] <0 ||data[1] >1) */
+ 			switch (ui_NoOfChannel) {
+ 			case 2:
+ 				*data = (*data >> (2 * data[1])) & 3;
+@@ -793,14 +793,14 @@ int i_APCI3200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ 
+ 			default:
+ 				comedi_error(dev, " chan spec wrong");
+-				return -EINVAL;	// "sorry channel spec wrong "
++				return -EINVAL;	/*  "sorry channel spec wrong " */
+ 				break;
+-			}	// switch(ui_NoOfChannels)
+-		}		// if  (ui_Temp==1)
++			}	/*  switch(ui_NoOfChannels) */
++		}		/*  if  (ui_Temp==1) */
+ 		else {
+ 			printk("\nSpecified channel not supported \n");
+-		}		// else if (ui_Temp==1)
+-	}			// else if  (ui_Temp==0)
++		}		/*  else if (ui_Temp==1) */
++	}			/*  else if  (ui_Temp==0) */
+ 	return insn->n;
+ }
+ 
+@@ -883,21 +883,21 @@ int i_APCI3200_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subde
+ 	unsigned int ui_Dummy = 0;
+ 	int i_err = 0;
+ 
+-	//Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++	/* Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ 
+ #ifdef PRINT_INFO
+ 	int i = 0, i2 = 0;
+ #endif
+-	//End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++	/* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ 
+-	//BEGIN JK 06.07.04: Management of sevrals boards
+-	// Initialize the structure
++	/* BEGIN JK 06.07.04: Management of sevrals boards */
++	/*  Initialize the structure */
+ 	if (s_BoardInfos[dev->minor].b_StructInitialized != 1) {
+ 		s_BoardInfos[dev->minor].i_CJCAvailable = 1;
+ 		s_BoardInfos[dev->minor].i_CJCPolarity = 0;
+-		s_BoardInfos[dev->minor].i_CJCGain = 2;	//changed from 0 to 2
++		s_BoardInfos[dev->minor].i_CJCGain = 2;	/* changed from 0 to 2 */
+ 		s_BoardInfos[dev->minor].i_InterruptFlag = 0;
+-		s_BoardInfos[dev->minor].i_AutoCalibration = 0;	//: auto calibration
++		s_BoardInfos[dev->minor].i_AutoCalibration = 0;	/* : auto calibration */
+ 		s_BoardInfos[dev->minor].i_ChannelCount = 0;
+ 		s_BoardInfos[dev->minor].i_Sum = 0;
+ 		s_BoardInfos[dev->minor].ui_Channel_num = 0;
+@@ -905,11 +905,11 @@ int i_APCI3200_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subde
+ 		s_BoardInfos[dev->minor].i_Initialised = 0;
+ 		s_BoardInfos[dev->minor].b_StructInitialized = 1;
+ 
+-		//Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++		/* Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ 		s_BoardInfos[dev->minor].i_ConnectionType = 0;
+-		//End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++		/* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ 
+-		//Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++		/* Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ 		memset(s_BoardInfos[dev->minor].s_Module, 0,
+ 			sizeof(s_BoardInfos[dev->minor].s_Module[MAX_MODULE]));
+ 
+@@ -938,72 +938,72 @@ int i_APCI3200_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subde
+ 			}
+ 		}
+ #endif
+-		//End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++		/* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ 	}
+ 
+ 	if (data[0] != 0 && data[0] != 1 && data[0] != 2) {
+ 		printk("\nThe selection of acquisition type is in error\n");
+ 		i_err++;
+-	}			//if(data[0]!=0 && data[0]!=1 && data[0]!=2)
++	}			/* if(data[0]!=0 && data[0]!=1 && data[0]!=2) */
+ 	if (data[0] == 1) {
+ 		if (data[14] != 0 && data[14] != 1 && data[14] != 2
+ 			&& data[14] != 4) {
+ 			printk("\n Error in selection of RTD connection type\n");
+ 			i_err++;
+-		}		//if(data[14]!=0 && data[14]!=1 && data[14]!=2 && data[14]!=4)
+-	}			//if(data[0]==1 )
++		}		/* if(data[14]!=0 && data[14]!=1 && data[14]!=2 && data[14]!=4) */
++	}			/* if(data[0]==1 ) */
+ 	if (data[1] < 0 || data[1] > 7) {
+ 		printk("\nThe selection of gain is in error\n");
+ 		i_err++;
+-	}			// if(data[1]<0 || data[1]>7)
++	}			/*  if(data[1]<0 || data[1]>7) */
+ 	if (data[2] != 0 && data[2] != 1) {
+ 		printk("\nThe selection of polarity is in error\n");
+ 		i_err++;
+-	}			//if(data[2]!=0 &&  data[2]!=1)
++	}			/* if(data[2]!=0 &&  data[2]!=1) */
+ 	if (data[3] != 0) {
+ 		printk("\nThe selection of offset range  is in error\n");
+ 		i_err++;
+-	}			// if(data[3]!=0)
++	}			/*  if(data[3]!=0) */
+ 	if (data[4] != 0 && data[4] != 1) {
+ 		printk("\nThe selection of coupling is in error\n");
+ 		i_err++;
+-	}			//if(data[4]!=0 &&  data[4]!=1)
++	}			/* if(data[4]!=0 &&  data[4]!=1) */
+ 	if (data[5] != 0 && data[5] != 1) {
+ 		printk("\nThe selection of single/differential mode is in error\n");
+ 		i_err++;
+-	}			//if(data[5]!=0 &&  data[5]!=1)
++	}			/* if(data[5]!=0 &&  data[5]!=1) */
+ 	if (data[8] != 0 && data[8] != 1 && data[2] != 2) {
+ 		printk("\nError in selection of functionality\n");
+-	}			//if(data[8]!=0 && data[8]!=1 && data[2]!=2)
++	}			/* if(data[8]!=0 && data[8]!=1 && data[2]!=2) */
+ 	if (data[12] == 0 || data[12] == 1) {
+ 		if (data[6] != 20 && data[6] != 40 && data[6] != 80
+ 			&& data[6] != 160) {
+ 			printk("\nThe selection of conversion time reload value is in error\n");
+ 			i_err++;
+-		}		// if (data[6]!=20 && data[6]!=40 && data[6]!=80 && data[6]!=160 )
++		}		/*  if (data[6]!=20 && data[6]!=40 && data[6]!=80 && data[6]!=160 ) */
+ 		if (data[7] != 2) {
+ 			printk("\nThe selection of conversion time unit  is in error\n");
+ 			i_err++;
+-		}		// if(data[7]!=2)
++		}		/*  if(data[7]!=2) */
+ 	}
+ 	if (data[9] != 0 && data[9] != 1) {
+ 		printk("\nThe selection of interrupt enable is in error\n");
+ 		i_err++;
+-	}			//if(data[9]!=0 &&  data[9]!=1)
++	}			/* if(data[9]!=0 &&  data[9]!=1) */
+ 	if (data[11] < 0 || data[11] > 4) {
+ 		printk("\nThe selection of module is in error\n");
+ 		i_err++;
+-	}			//if(data[11] <0 ||  data[11]>1)
++	}			/* if(data[11] <0 ||  data[11]>1) */
+ 	if (data[12] < 0 || data[12] > 3) {
+ 		printk("\nThe selection of singlechannel/scan selection is in error\n");
+ 		i_err++;
+-	}			//if(data[12] < 0 ||  data[12]> 3)
++	}			/* if(data[12] < 0 ||  data[12]> 3) */
+ 	if (data[13] < 0 || data[13] > 16) {
+ 		printk("\nThe selection of number of channels is in error\n");
+ 		i_err++;
+-	}			// if(data[13] <0 ||data[13] >15)
++	}			/*  if(data[13] <0 ||data[13] >15) */
+ 
+-	//BEGIN JK 06.07.04: Management of sevrals boards
++	/* BEGIN JK 06.07.04: Management of sevrals boards */
+ 	/*
+ 	   i_ChannelCount=data[13];
+ 	   i_ScanType=data[12];
+@@ -1014,7 +1014,7 @@ int i_APCI3200_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subde
+ 	   i_ADDIDATAType=data[0];
+ 	 */
+ 
+-	// Save acquisition configuration for the actual board
++	/*  Save acquisition configuration for the actual board */
+ 	s_BoardInfos[dev->minor].i_ChannelCount = data[13];
+ 	s_BoardInfos[dev->minor].i_ScanType = data[12];
+ 	s_BoardInfos[dev->minor].i_ADDIDATAPolarity = data[2];
+@@ -1022,307 +1022,307 @@ int i_APCI3200_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subde
+ 	s_BoardInfos[dev->minor].i_ADDIDATAConversionTime = data[6];
+ 	s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit = data[7];
+ 	s_BoardInfos[dev->minor].i_ADDIDATAType = data[0];
+-	//Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
++	/* Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
+ 	s_BoardInfos[dev->minor].i_ConnectionType = data[5];
+-	//End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+-	//END JK 06.07.04: Management of sevrals boards
++	/* End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
++	/* END JK 06.07.04: Management of sevrals boards */
+ 
+-	//Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+-	memset(s_BoardInfos[dev->minor].ui_ScanValueArray, 0, (7 + 12) * sizeof(unsigned int));	// 7 is the maximal number of channels
+-	//End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
++	/* Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
++	memset(s_BoardInfos[dev->minor].ui_ScanValueArray, 0, (7 + 12) * sizeof(unsigned int));	/*  7 is the maximal number of channels */
++	/* End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
+ 
+-	//BEGIN JK 02.07.04 : This while can't be do, it block the process when using severals boards
+-	//while(i_InterruptFlag==1)
++	/* BEGIN JK 02.07.04 : This while can't be do, it block the process when using severals boards */
++	/* while(i_InterruptFlag==1) */
+ 	while (s_BoardInfos[dev->minor].i_InterruptFlag == 1) {
+ #ifndef MSXBOX
+ 		udelay(1);
+ #else
+-		// In the case where the driver is compiled for the MSX-Box
+-		// we used a printk to have a little delay because udelay
+-		// seems to be broken under the MSX-Box.
+-		// This solution hat to be studied.
++		/*  In the case where the driver is compiled for the MSX-Box */
++		/*  we used a printk to have a little delay because udelay */
++		/*  seems to be broken under the MSX-Box. */
++		/*  This solution hat to be studied. */
+ 		printk("");
+ #endif
+ 	}
+-	//END JK 02.07.04 : This while can't be do, it block the process when using severals boards
++	/* END JK 02.07.04 : This while can't be do, it block the process when using severals boards */
+ 
+-	ui_ChannelNo = CR_CHAN(insn->chanspec);	// get the channel
+-	//BEGIN JK 06.07.04: Management of sevrals boards
+-	//i_ChannelNo=ui_ChannelNo;
+-	//ui_Channel_num =ui_ChannelNo;
++	ui_ChannelNo = CR_CHAN(insn->chanspec);	/*  get the channel */
++	/* BEGIN JK 06.07.04: Management of sevrals boards */
++	/* i_ChannelNo=ui_ChannelNo; */
++	/* ui_Channel_num =ui_ChannelNo; */
+ 
+ 	s_BoardInfos[dev->minor].i_ChannelNo = ui_ChannelNo;
+ 	s_BoardInfos[dev->minor].ui_Channel_num = ui_ChannelNo;
+ 
+-	//END JK 06.07.04: Management of sevrals boards
++	/* END JK 06.07.04: Management of sevrals boards */
+ 
+ 	if (data[5] == 0) {
+ 		if (ui_ChannelNo < 0 || ui_ChannelNo > 15) {
+ 			printk("\nThe Selection of the channel is in error\n");
+ 			i_err++;
+-		}		// if(ui_ChannelNo<0 || ui_ChannelNo>15)
+-	}			//if(data[5]==0)
++		}		/*  if(ui_ChannelNo<0 || ui_ChannelNo>15) */
++	}			/* if(data[5]==0) */
+ 	else {
+ 		if (data[14] == 2) {
+ 			if (ui_ChannelNo < 0 || ui_ChannelNo > 3) {
+ 				printk("\nThe Selection of the channel is in error\n");
+ 				i_err++;
+-			}	// if(ui_ChannelNo<0 || ui_ChannelNo>3)
+-		}		//if(data[14]==2)
++			}	/*  if(ui_ChannelNo<0 || ui_ChannelNo>3) */
++		}		/* if(data[14]==2) */
+ 		else {
+ 			if (ui_ChannelNo < 0 || ui_ChannelNo > 7) {
+ 				printk("\nThe Selection of the channel is in error\n");
+ 				i_err++;
+-			}	// if(ui_ChannelNo<0 || ui_ChannelNo>7)
+-		}		//elseif(data[14]==2)
+-	}			//elseif(data[5]==0)
++			}	/*  if(ui_ChannelNo<0 || ui_ChannelNo>7) */
++		}		/* elseif(data[14]==2) */
++	}			/* elseif(data[5]==0) */
+ 	if (data[12] == 0 || data[12] == 1) {
+ 		switch (data[5]) {
+ 		case 0:
+ 			if (ui_ChannelNo >= 0 && ui_ChannelNo <= 3) {
+-				//BEGIN JK 06.07.04: Management of sevrals boards
+-				//i_Offset=0;
++				/* BEGIN JK 06.07.04: Management of sevrals boards */
++				/* i_Offset=0; */
+ 				s_BoardInfos[dev->minor].i_Offset = 0;
+-				//END JK 06.07.04: Management of sevrals boards
+-			}	//if(ui_ChannelNo >=0 && ui_ChannelNo <=3)
++				/* END JK 06.07.04: Management of sevrals boards */
++			}	/* if(ui_ChannelNo >=0 && ui_ChannelNo <=3) */
+ 			if (ui_ChannelNo >= 4 && ui_ChannelNo <= 7) {
+-				//BEGIN JK 06.07.04: Management of sevrals boards
+-				//i_Offset=64;
++				/* BEGIN JK 06.07.04: Management of sevrals boards */
++				/* i_Offset=64; */
+ 				s_BoardInfos[dev->minor].i_Offset = 64;
+-				//END JK 06.07.04: Management of sevrals boards
+-			}	//if(ui_ChannelNo >=4 && ui_ChannelNo <=7)
++				/* END JK 06.07.04: Management of sevrals boards */
++			}	/* if(ui_ChannelNo >=4 && ui_ChannelNo <=7) */
+ 			if (ui_ChannelNo >= 8 && ui_ChannelNo <= 11) {
+-				//BEGIN JK 06.07.04: Management of sevrals boards
+-				//i_Offset=128;
++				/* BEGIN JK 06.07.04: Management of sevrals boards */
++				/* i_Offset=128; */
+ 				s_BoardInfos[dev->minor].i_Offset = 128;
+-				//END JK 06.07.04: Management of sevrals boards
+-			}	//if(ui_ChannelNo >=8 && ui_ChannelNo <=11)
++				/* END JK 06.07.04: Management of sevrals boards */
++			}	/* if(ui_ChannelNo >=8 && ui_ChannelNo <=11) */
+ 			if (ui_ChannelNo >= 12 && ui_ChannelNo <= 15) {
+-				//BEGIN JK 06.07.04: Management of sevrals boards
+-				//i_Offset=192;
++				/* BEGIN JK 06.07.04: Management of sevrals boards */
++				/* i_Offset=192; */
+ 				s_BoardInfos[dev->minor].i_Offset = 192;
+-				//END JK 06.07.04: Management of sevrals boards
+-			}	//if(ui_ChannelNo >=12 && ui_ChannelNo <=15)
++				/* END JK 06.07.04: Management of sevrals boards */
++			}	/* if(ui_ChannelNo >=12 && ui_ChannelNo <=15) */
+ 			break;
+ 		case 1:
+ 			if (data[14] == 2) {
+ 				if (ui_ChannelNo == 0) {
+-					//BEGIN JK 06.07.04: Management of sevrals boards
+-					//i_Offset=0;
++					/* BEGIN JK 06.07.04: Management of sevrals boards */
++					/* i_Offset=0; */
+ 					s_BoardInfos[dev->minor].i_Offset = 0;
+-					//END JK 06.07.04: Management of sevrals boards
+-				}	//if(ui_ChannelNo ==0 )
++					/* END JK 06.07.04: Management of sevrals boards */
++				}	/* if(ui_ChannelNo ==0 ) */
+ 				if (ui_ChannelNo == 1) {
+-					//BEGIN JK 06.07.04: Management of sevrals boards
+-					//i_Offset=0;
++					/* BEGIN JK 06.07.04: Management of sevrals boards */
++					/* i_Offset=0; */
+ 					s_BoardInfos[dev->minor].i_Offset = 64;
+-					//END JK 06.07.04: Management of sevrals boards
+-				}	// if(ui_ChannelNo ==1)
++					/* END JK 06.07.04: Management of sevrals boards */
++				}	/*  if(ui_ChannelNo ==1) */
+ 				if (ui_ChannelNo == 2) {
+-					//BEGIN JK 06.07.04: Management of sevrals boards
+-					//i_Offset=128;
++					/* BEGIN JK 06.07.04: Management of sevrals boards */
++					/* i_Offset=128; */
+ 					s_BoardInfos[dev->minor].i_Offset = 128;
+-					//END JK 06.07.04: Management of sevrals boards
+-				}	//if(ui_ChannelNo ==2 )
++					/* END JK 06.07.04: Management of sevrals boards */
++				}	/* if(ui_ChannelNo ==2 ) */
+ 				if (ui_ChannelNo == 3) {
+-					//BEGIN JK 06.07.04: Management of sevrals boards
+-					//i_Offset=192;
++					/* BEGIN JK 06.07.04: Management of sevrals boards */
++					/* i_Offset=192; */
+ 					s_BoardInfos[dev->minor].i_Offset = 192;
+-					//END JK 06.07.04: Management of sevrals boards
+-				}	//if(ui_ChannelNo ==3)
++					/* END JK 06.07.04: Management of sevrals boards */
++				}	/* if(ui_ChannelNo ==3) */
+ 
+-				//BEGIN JK 06.07.04: Management of sevrals boards
+-				//i_ChannelNo=0;
++				/* BEGIN JK 06.07.04: Management of sevrals boards */
++				/* i_ChannelNo=0; */
+ 				s_BoardInfos[dev->minor].i_ChannelNo = 0;
+-				//END JK 06.07.04: Management of sevrals boards
++				/* END JK 06.07.04: Management of sevrals boards */
+ 				ui_ChannelNo = 0;
+ 				break;
+-			}	//if(data[14]==2)
++			}	/* if(data[14]==2) */
+ 			if (ui_ChannelNo >= 0 && ui_ChannelNo <= 1) {
+-				//BEGIN JK 06.07.04: Management of sevrals boards
+-				//i_Offset=0;
++				/* BEGIN JK 06.07.04: Management of sevrals boards */
++				/* i_Offset=0; */
+ 				s_BoardInfos[dev->minor].i_Offset = 0;
+-				//END JK 06.07.04: Management of sevrals boards
+-			}	//if(ui_ChannelNo >=0 && ui_ChannelNo <=1)
++				/* END JK 06.07.04: Management of sevrals boards */
++			}	/* if(ui_ChannelNo >=0 && ui_ChannelNo <=1) */
+ 			if (ui_ChannelNo >= 2 && ui_ChannelNo <= 3) {
+-				//BEGIN JK 06.07.04: Management of sevrals boards
+-				//i_ChannelNo=i_ChannelNo-2;
+-				//i_Offset=64;
++				/* BEGIN JK 06.07.04: Management of sevrals boards */
++				/* i_ChannelNo=i_ChannelNo-2; */
++				/* i_Offset=64; */
+ 				s_BoardInfos[dev->minor].i_ChannelNo =
+ 					s_BoardInfos[dev->minor].i_ChannelNo -
+ 					2;
+ 				s_BoardInfos[dev->minor].i_Offset = 64;
+-				//END JK 06.07.04: Management of sevrals boards
++				/* END JK 06.07.04: Management of sevrals boards */
+ 				ui_ChannelNo = ui_ChannelNo - 2;
+-			}	//if(ui_ChannelNo >=2 && ui_ChannelNo <=3)
++			}	/* if(ui_ChannelNo >=2 && ui_ChannelNo <=3) */
+ 			if (ui_ChannelNo >= 4 && ui_ChannelNo <= 5) {
+-				//BEGIN JK 06.07.04: Management of sevrals boards
+-				//i_ChannelNo=i_ChannelNo-4;
+-				//i_Offset=128;
++				/* BEGIN JK 06.07.04: Management of sevrals boards */
++				/* i_ChannelNo=i_ChannelNo-4; */
++				/* i_Offset=128; */
+ 				s_BoardInfos[dev->minor].i_ChannelNo =
+ 					s_BoardInfos[dev->minor].i_ChannelNo -
+ 					4;
+ 				s_BoardInfos[dev->minor].i_Offset = 128;
+-				//END JK 06.07.04: Management of sevrals boards
++				/* END JK 06.07.04: Management of sevrals boards */
+ 				ui_ChannelNo = ui_ChannelNo - 4;
+-			}	//if(ui_ChannelNo >=4 && ui_ChannelNo <=5)
++			}	/* if(ui_ChannelNo >=4 && ui_ChannelNo <=5) */
+ 			if (ui_ChannelNo >= 6 && ui_ChannelNo <= 7) {
+-				//BEGIN JK 06.07.04: Management of sevrals boards
+-				//i_ChannelNo=i_ChannelNo-6;
+-				//i_Offset=192;
++				/* BEGIN JK 06.07.04: Management of sevrals boards */
++				/* i_ChannelNo=i_ChannelNo-6; */
++				/* i_Offset=192; */
+ 				s_BoardInfos[dev->minor].i_ChannelNo =
+ 					s_BoardInfos[dev->minor].i_ChannelNo -
+ 					6;
+ 				s_BoardInfos[dev->minor].i_Offset = 192;
+-				//END JK 06.07.04: Management of sevrals boards
++				/* END JK 06.07.04: Management of sevrals boards */
+ 				ui_ChannelNo = ui_ChannelNo - 6;
+-			}	//if(ui_ChannelNo >=6 && ui_ChannelNo <=7)
++			}	/* if(ui_ChannelNo >=6 && ui_ChannelNo <=7) */
+ 			break;
+ 
+ 		default:
+ 			printk("\n This selection of polarity does not exist\n");
+ 			i_err++;
+-		}		//switch(data[2])
+-	}			//if(data[12]==0 || data[12]==1)
++		}		/* switch(data[2]) */
++	}			/* if(data[12]==0 || data[12]==1) */
+ 	else {
+ 		switch (data[11]) {
+ 		case 1:
+-			//BEGIN JK 06.07.04: Management of sevrals boards
+-			//i_Offset=0;
++			/* BEGIN JK 06.07.04: Management of sevrals boards */
++			/* i_Offset=0; */
+ 			s_BoardInfos[dev->minor].i_Offset = 0;
+-			//END JK 06.07.04: Management of sevrals boards
++			/* END JK 06.07.04: Management of sevrals boards */
+ 			break;
+ 		case 2:
+-			//BEGIN JK 06.07.04: Management of sevrals boards
+-			//i_Offset=64;
++			/* BEGIN JK 06.07.04: Management of sevrals boards */
++			/* i_Offset=64; */
+ 			s_BoardInfos[dev->minor].i_Offset = 64;
+-			//END JK 06.07.04: Management of sevrals boards
++			/* END JK 06.07.04: Management of sevrals boards */
+ 			break;
+ 		case 3:
+-			//BEGIN JK 06.07.04: Management of sevrals boards
+-			//i_Offset=128;
++			/* BEGIN JK 06.07.04: Management of sevrals boards */
++			/* i_Offset=128; */
+ 			s_BoardInfos[dev->minor].i_Offset = 128;
+-			//END JK 06.07.04: Management of sevrals boards
++			/* END JK 06.07.04: Management of sevrals boards */
+ 			break;
+ 		case 4:
+-			//BEGIN JK 06.07.04: Management of sevrals boards
+-			//i_Offset=192;
++			/* BEGIN JK 06.07.04: Management of sevrals boards */
++			/* i_Offset=192; */
+ 			s_BoardInfos[dev->minor].i_Offset = 192;
+-			//END JK 06.07.04: Management of sevrals boards
++			/* END JK 06.07.04: Management of sevrals boards */
+ 			break;
+ 		default:
+ 			printk("\nError in module selection\n");
+ 			i_err++;
+-		}		// switch(data[11])
+-	}			// elseif(data[12]==0 || data[12]==1)
++		}		/*  switch(data[11]) */
++	}			/*  elseif(data[12]==0 || data[12]==1) */
+ 	if (i_err) {
+ 		i_APCI3200_Reset(dev);
+ 		return -EINVAL;
+ 	}
+-	//if(i_ScanType!=1)
++	/* if(i_ScanType!=1) */
+ 	if (s_BoardInfos[dev->minor].i_ScanType != 1) {
+-		//BEGIN JK 06.07.04: Management of sevrals boards
+-		//i_Count=0;
+-		//i_Sum=0;
++		/* BEGIN JK 06.07.04: Management of sevrals boards */
++		/* i_Count=0; */
++		/* i_Sum=0; */
+ 		s_BoardInfos[dev->minor].i_Count = 0;
+ 		s_BoardInfos[dev->minor].i_Sum = 0;
+-		//END JK 06.07.04: Management of sevrals boards
+-	}			//if(i_ScanType!=1)
++		/* END JK 06.07.04: Management of sevrals boards */
++	}			/* if(i_ScanType!=1) */
+ 
+ 	ul_Config =
+ 		data[1] | (data[2] << 6) | (data[5] << 7) | (data[3] << 8) |
+ 		(data[4] << 9);
+-	//BEGIN JK 06.07.04: Management of sevrals boards
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* BEGIN JK 06.07.04: Management of sevrals boards */
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//END JK 06.07.04: Management of sevrals boards
++	/* END JK 06.07.04: Management of sevrals boards */
+   /*********************************/
+ 	/* Write the channel to configure */
+   /*********************************/
+-	//BEGIN JK 06.07.04: Management of sevrals boards
+-	//outl(0 | ui_ChannelNo , devpriv->iobase+i_Offset + 0x4);
++	/* BEGIN JK 06.07.04: Management of sevrals boards */
++	/* outl(0 | ui_ChannelNo , devpriv->iobase+i_Offset + 0x4); */
+ 	outl(0 | ui_ChannelNo,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x4);
+-	//END JK 06.07.04: Management of sevrals boards
++	/* END JK 06.07.04: Management of sevrals boards */
+ 
+-	//BEGIN JK 06.07.04: Management of sevrals boards
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* BEGIN JK 06.07.04: Management of sevrals boards */
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//END JK 06.07.04: Management of sevrals boards
++	/* END JK 06.07.04: Management of sevrals boards */
+   /**************************/
+ 	/* Reset the configuration */
+   /**************************/
+-	//BEGIN JK 06.07.04: Management of sevrals boards
+-	//outl(0 , devpriv->iobase+i_Offset + 0x0);
++	/* BEGIN JK 06.07.04: Management of sevrals boards */
++	/* outl(0 , devpriv->iobase+i_Offset + 0x0); */
+ 	outl(0, devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x0);
+-	//END JK 06.07.04: Management of sevrals boards
++	/* END JK 06.07.04: Management of sevrals boards */
+ 
+-	//BEGIN JK 06.07.04: Management of sevrals boards
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* BEGIN JK 06.07.04: Management of sevrals boards */
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//END JK 06.07.04: Management of sevrals boards
++	/* END JK 06.07.04: Management of sevrals boards */
+ 
+   /***************************/
+ 	/* Write the configuration */
+   /***************************/
+-	//BEGIN JK 06.07.04: Management of sevrals boards
+-	//outl(ul_Config , devpriv->iobase+i_Offset + 0x0);
++	/* BEGIN JK 06.07.04: Management of sevrals boards */
++	/* outl(ul_Config , devpriv->iobase+i_Offset + 0x0); */
+ 	outl(ul_Config,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x0);
+-	//END JK 06.07.04: Management of sevrals boards
++	/* END JK 06.07.04: Management of sevrals boards */
+ 
+   /***************************/
+ 	/*Reset the calibration bit */
+   /***************************/
+-	//BEGIN JK 06.07.04: Management of sevrals boards
+-	//ul_Temp = inl(devpriv->iobase+i_Offset + 12);
++	/* BEGIN JK 06.07.04: Management of sevrals boards */
++	/* ul_Temp = inl(devpriv->iobase+i_Offset + 12); */
+ 	ul_Temp = inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+-	//END JK 06.07.04: Management of sevrals boards
++	/* END JK 06.07.04: Management of sevrals boards */
+ 
+-	//BEGIN JK 06.07.04: Management of sevrals boards
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* BEGIN JK 06.07.04: Management of sevrals boards */
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//END JK 06.07.04: Management of sevrals boards
++	/* END JK 06.07.04: Management of sevrals boards */
+ 
+-	//BEGIN JK 06.07.04: Management of sevrals boards
+-	//outl((ul_Temp & 0xFFF9FFFF) , devpriv->iobase+.i_Offset + 12);
++	/* BEGIN JK 06.07.04: Management of sevrals boards */
++	/* outl((ul_Temp & 0xFFF9FFFF) , devpriv->iobase+.i_Offset + 12); */
+ 	outl((ul_Temp & 0xFFF9FFFF),
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+-	//END JK 06.07.04: Management of sevrals boards
++	/* END JK 06.07.04: Management of sevrals boards */
+ 
+ 	if (data[9] == 1) {
+ 		devpriv->tsk_Current = current;
+-		//BEGIN JK 06.07.04: Management of sevrals boards
+-		//i_InterruptFlag=1;
++		/* BEGIN JK 06.07.04: Management of sevrals boards */
++		/* i_InterruptFlag=1; */
+ 		s_BoardInfos[dev->minor].i_InterruptFlag = 1;
+-		//END JK 06.07.04: Management of sevrals boards
+-	}			// if(data[9]==1)
++		/* END JK 06.07.04: Management of sevrals boards */
++	}			/*  if(data[9]==1) */
+ 	else {
+-		//BEGIN JK 06.07.04: Management of sevrals boards
+-		//i_InterruptFlag=0;
++		/* BEGIN JK 06.07.04: Management of sevrals boards */
++		/* i_InterruptFlag=0; */
+ 		s_BoardInfos[dev->minor].i_InterruptFlag = 0;
+-		//END JK 06.07.04: Management of sevrals boards
+-	}			//else  if(data[9]==1)
++		/* END JK 06.07.04: Management of sevrals boards */
++	}			/* else  if(data[9]==1) */
+ 
+-	//BEGIN JK 06.07.04: Management of sevrals boards
+-	//i_Initialised=1;
++	/* BEGIN JK 06.07.04: Management of sevrals boards */
++	/* i_Initialised=1; */
+ 	s_BoardInfos[dev->minor].i_Initialised = 1;
+-	//END JK 06.07.04: Management of sevrals boards
++	/* END JK 06.07.04: Management of sevrals boards */
+ 
+-	//BEGIN JK 06.07.04: Management of sevrals boards
+-	//if(i_ScanType==1)
++	/* BEGIN JK 06.07.04: Management of sevrals boards */
++	/* if(i_ScanType==1) */
+ 	if (s_BoardInfos[dev->minor].i_ScanType == 1)
+-		//END JK 06.07.04: Management of sevrals boards
++		/* END JK 06.07.04: Management of sevrals boards */
+ 	{
+-		//BEGIN JK 06.07.04: Management of sevrals boards
+-		//i_Sum=i_Sum+1;
++		/* BEGIN JK 06.07.04: Management of sevrals boards */
++		/* i_Sum=i_Sum+1; */
+ 		s_BoardInfos[dev->minor].i_Sum =
+ 			s_BoardInfos[dev->minor].i_Sum + 1;
+-		//END JK 06.07.04: Management of sevrals boards
++		/* END JK 06.07.04: Management of sevrals boards */
+ 
+ 		insn->unused[0] = 0;
+ 		i_APCI3200_ReadAnalogInput(dev, s, insn, &ui_Dummy);
+@@ -1368,14 +1368,14 @@ int i_APCI3200_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevi
+ 	int i_ConvertCJCCalibration;
+ 	int i = 0;
+ 
+-	//BEGIN JK 06.07.04: Management of sevrals boards
+-	//if(i_Initialised==0)
++	/* BEGIN JK 06.07.04: Management of sevrals boards */
++	/* if(i_Initialised==0) */
+ 	if (s_BoardInfos[dev->minor].i_Initialised == 0)
+-		//END JK 06.07.04: Management of sevrals boards
++		/* END JK 06.07.04: Management of sevrals boards */
+ 	{
+ 		i_APCI3200_Reset(dev);
+ 		return -EINVAL;
+-	}			//if(i_Initialised==0);
++	}			/* if(i_Initialised==0); */
+ 
+ #ifdef PRINT_INFO
+ 	printk("\n insn->unused[0] = %i", insn->unused[0]);
+@@ -1386,14 +1386,14 @@ int i_APCI3200_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevi
+ 
+ 		i_APCI3200_Read1AnalogInputChannel(dev, s, insn,
+ 			&ui_DummyValue);
+-		//BEGIN JK 06.07.04: Management of sevrals boards
+-		//ui_InterruptChannelValue[i_Count+0]=ui_DummyValue;
++		/* BEGIN JK 06.07.04: Management of sevrals boards */
++		/* ui_InterruptChannelValue[i_Count+0]=ui_DummyValue; */
+ 		s_BoardInfos[dev->minor].
+ 			ui_InterruptChannelValue[s_BoardInfos[dev->minor].
+ 			i_Count + 0] = ui_DummyValue;
+-		//END JK 06.07.04: Management of sevrals boards
++		/* END JK 06.07.04: Management of sevrals boards */
+ 
+-		//Begin JK 25.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++		/* Begin JK 25.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ 		i_APCI3200_GetChannelCalibrationValue(dev,
+ 			s_BoardInfos[dev->minor].ui_Channel_num,
+ 			&s_BoardInfos[dev->minor].
+@@ -1414,62 +1414,62 @@ int i_APCI3200_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevi
+ 		printk("\n s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count+8] = %lu", s_BoardInfos[dev->minor].ui_InterruptChannelValue[s_BoardInfos[dev->minor].i_Count + 8]);
+ #endif
+ 
+-		//End JK 25.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++		/* End JK 25.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ 
+-		//BEGIN JK 06.07.04: Management of sevrals boards
+-		//if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE) && (i_CJCAvailable==1))
++		/* BEGIN JK 06.07.04: Management of sevrals boards */
++		/* if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE) && (i_CJCAvailable==1)) */
+ 		if ((s_BoardInfos[dev->minor].i_ADDIDATAType == 2)
+ 			&& (s_BoardInfos[dev->minor].i_InterruptFlag == FALSE)
+ 			&& (s_BoardInfos[dev->minor].i_CJCAvailable == 1))
+-			//END JK 06.07.04: Management of sevrals boards
++			/* END JK 06.07.04: Management of sevrals boards */
+ 		{
+ 			i_APCI3200_ReadCJCValue(dev, &ui_DummyValue);
+-			//BEGIN JK 06.07.04: Management of sevrals boards
+-			//ui_InterruptChannelValue[i_Count + 3]=ui_DummyValue;
++			/* BEGIN JK 06.07.04: Management of sevrals boards */
++			/* ui_InterruptChannelValue[i_Count + 3]=ui_DummyValue; */
+ 			s_BoardInfos[dev->minor].
+ 				ui_InterruptChannelValue[s_BoardInfos[dev->
+ 					minor].i_Count + 3] = ui_DummyValue;
+-			//END JK 06.07.04: Management of sevrals boards
+-		}		//if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE))
++			/* END JK 06.07.04: Management of sevrals boards */
++		}		/* if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE)) */
+ 		else {
+-			//BEGIN JK 06.07.04: Management of sevrals boards
+-			//ui_InterruptChannelValue[i_Count + 3]=0;
++			/* BEGIN JK 06.07.04: Management of sevrals boards */
++			/* ui_InterruptChannelValue[i_Count + 3]=0; */
+ 			s_BoardInfos[dev->minor].
+ 				ui_InterruptChannelValue[s_BoardInfos[dev->
+ 					minor].i_Count + 3] = 0;
+-			//END JK 06.07.04: Management of sevrals boards
+-		}		//elseif((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE) && (i_CJCAvailable==1))
++			/* END JK 06.07.04: Management of sevrals boards */
++		}		/* elseif((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE) && (i_CJCAvailable==1)) */
+ 
+-		//BEGIN JK 06.07.04: Management of sevrals boards
+-		//if (( i_AutoCalibration == FALSE) && (i_InterruptFlag == FALSE))
++		/* BEGIN JK 06.07.04: Management of sevrals boards */
++		/* if (( i_AutoCalibration == FALSE) && (i_InterruptFlag == FALSE)) */
+ 		if ((s_BoardInfos[dev->minor].i_AutoCalibration == FALSE)
+ 			&& (s_BoardInfos[dev->minor].i_InterruptFlag == FALSE))
+-			//END JK 06.07.04: Management of sevrals boards
++			/* END JK 06.07.04: Management of sevrals boards */
+ 		{
+ 			i_APCI3200_ReadCalibrationOffsetValue(dev,
+ 				&ui_DummyValue);
+-			//BEGIN JK 06.07.04: Management of sevrals boards
+-			//ui_InterruptChannelValue[i_Count + 1]=ui_DummyValue;
++			/* BEGIN JK 06.07.04: Management of sevrals boards */
++			/* ui_InterruptChannelValue[i_Count + 1]=ui_DummyValue; */
+ 			s_BoardInfos[dev->minor].
+ 				ui_InterruptChannelValue[s_BoardInfos[dev->
+ 					minor].i_Count + 1] = ui_DummyValue;
+-			//END JK 06.07.04: Management of sevrals boards
++			/* END JK 06.07.04: Management of sevrals boards */
+ 			i_APCI3200_ReadCalibrationGainValue(dev,
+ 				&ui_DummyValue);
+-			//BEGIN JK 06.07.04: Management of sevrals boards
+-			//ui_InterruptChannelValue[i_Count + 2]=ui_DummyValue;
++			/* BEGIN JK 06.07.04: Management of sevrals boards */
++			/* ui_InterruptChannelValue[i_Count + 2]=ui_DummyValue; */
+ 			s_BoardInfos[dev->minor].
+ 				ui_InterruptChannelValue[s_BoardInfos[dev->
+ 					minor].i_Count + 2] = ui_DummyValue;
+-			//END JK 06.07.04: Management of sevrals boards
+-		}		//if (( i_AutoCalibration == FALSE) && (i_InterruptFlag == FALSE))
++			/* END JK 06.07.04: Management of sevrals boards */
++		}		/* if (( i_AutoCalibration == FALSE) && (i_InterruptFlag == FALSE)) */
+ 
+-		//BEGIN JK 06.07.04: Management of sevrals boards
+-		//if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE)&& (i_CJCAvailable==1))
++		/* BEGIN JK 06.07.04: Management of sevrals boards */
++		/* if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE)&& (i_CJCAvailable==1)) */
+ 		if ((s_BoardInfos[dev->minor].i_ADDIDATAType == 2)
+ 			&& (s_BoardInfos[dev->minor].i_InterruptFlag == FALSE)
+ 			&& (s_BoardInfos[dev->minor].i_CJCAvailable == 1))
+-			//END JK 06.07.04: Management of sevrals boards
++			/* END JK 06.07.04: Management of sevrals boards */
+ 		{
+ 	  /**********************************************************/
+ 			/*Test if the Calibration channel must be read for the CJC */
+@@ -1477,52 +1477,52 @@ int i_APCI3200_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevi
+ 	  /**********************************/
+ 			/*Test if the polarity is the same */
+ 	  /**********************************/
+-			//BEGIN JK 06.07.04: Management of sevrals boards
+-			//if(i_CJCPolarity!=i_ADDIDATAPolarity)
++			/* BEGIN JK 06.07.04: Management of sevrals boards */
++			/* if(i_CJCPolarity!=i_ADDIDATAPolarity) */
+ 			if (s_BoardInfos[dev->minor].i_CJCPolarity !=
+ 				s_BoardInfos[dev->minor].i_ADDIDATAPolarity)
+-				//END JK 06.07.04: Management of sevrals boards
++				/* END JK 06.07.04: Management of sevrals boards */
+ 			{
+ 				i_ConvertCJCCalibration = 1;
+-			}	//if(i_CJCPolarity!=i_ADDIDATAPolarity)
++			}	/* if(i_CJCPolarity!=i_ADDIDATAPolarity) */
+ 			else {
+-				//BEGIN JK 06.07.04: Management of sevrals boards
+-				//if(i_CJCGain==i_ADDIDATAGain)
++				/* BEGIN JK 06.07.04: Management of sevrals boards */
++				/* if(i_CJCGain==i_ADDIDATAGain) */
+ 				if (s_BoardInfos[dev->minor].i_CJCGain ==
+ 					s_BoardInfos[dev->minor].i_ADDIDATAGain)
+-					//END JK 06.07.04: Management of sevrals boards
++					/* END JK 06.07.04: Management of sevrals boards */
+ 				{
+ 					i_ConvertCJCCalibration = 0;
+-				}	//if(i_CJCGain==i_ADDIDATAGain)
++				}	/* if(i_CJCGain==i_ADDIDATAGain) */
+ 				else {
+ 					i_ConvertCJCCalibration = 1;
+-				}	//elseif(i_CJCGain==i_ADDIDATAGain)
+-			}	//elseif(i_CJCPolarity!=i_ADDIDATAPolarity)
++				}	/* elseif(i_CJCGain==i_ADDIDATAGain) */
++			}	/* elseif(i_CJCPolarity!=i_ADDIDATAPolarity) */
+ 			if (i_ConvertCJCCalibration == 1) {
+ 				i_APCI3200_ReadCJCCalOffset(dev,
+ 					&ui_DummyValue);
+-				//BEGIN JK 06.07.04: Management of sevrals boards
+-				//ui_InterruptChannelValue[i_Count+4]=ui_DummyValue;
++				/* BEGIN JK 06.07.04: Management of sevrals boards */
++				/* ui_InterruptChannelValue[i_Count+4]=ui_DummyValue; */
+ 				s_BoardInfos[dev->minor].
+ 					ui_InterruptChannelValue[s_BoardInfos
+ 					[dev->minor].i_Count + 4] =
+ 					ui_DummyValue;
+-				//END JK 06.07.04: Management of sevrals boards
++				/* END JK 06.07.04: Management of sevrals boards */
+ 
+ 				i_APCI3200_ReadCJCCalGain(dev, &ui_DummyValue);
+ 
+-				//BEGIN JK 06.07.04: Management of sevrals boards
+-				//ui_InterruptChannelValue[i_Count+5]=ui_DummyValue;
++				/* BEGIN JK 06.07.04: Management of sevrals boards */
++				/* ui_InterruptChannelValue[i_Count+5]=ui_DummyValue; */
+ 				s_BoardInfos[dev->minor].
+ 					ui_InterruptChannelValue[s_BoardInfos
+ 					[dev->minor].i_Count + 5] =
+ 					ui_DummyValue;
+-				//END JK 06.07.04: Management of sevrals boards
+-			}	//if(i_ConvertCJCCalibration==1)
++				/* END JK 06.07.04: Management of sevrals boards */
++			}	/* if(i_ConvertCJCCalibration==1) */
+ 			else {
+-				//BEGIN JK 06.07.04: Management of sevrals boards
+-				//ui_InterruptChannelValue[i_Count+4]=0;
+-				//ui_InterruptChannelValue[i_Count+5]=0;
++				/* BEGIN JK 06.07.04: Management of sevrals boards */
++				/* ui_InterruptChannelValue[i_Count+4]=0; */
++				/* ui_InterruptChannelValue[i_Count+5]=0; */
+ 
+ 				s_BoardInfos[dev->minor].
+ 					ui_InterruptChannelValue[s_BoardInfos
+@@ -1530,36 +1530,36 @@ int i_APCI3200_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevi
+ 				s_BoardInfos[dev->minor].
+ 					ui_InterruptChannelValue[s_BoardInfos
+ 					[dev->minor].i_Count + 5] = 0;
+-				//END JK 06.07.04: Management of sevrals boards
+-			}	//elseif(i_ConvertCJCCalibration==1)
+-		}		//if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE))
++				/* END JK 06.07.04: Management of sevrals boards */
++			}	/* elseif(i_ConvertCJCCalibration==1) */
++		}		/* if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE)) */
+ 
+-		//BEGIN JK 06.07.04: Management of sevrals boards
+-		//if(i_ScanType!=1)
++		/* BEGIN JK 06.07.04: Management of sevrals boards */
++		/* if(i_ScanType!=1) */
+ 		if (s_BoardInfos[dev->minor].i_ScanType != 1) {
+-			//i_Count=0;
++			/* i_Count=0; */
+ 			s_BoardInfos[dev->minor].i_Count = 0;
+-		}		//if(i_ScanType!=1)
++		}		/* if(i_ScanType!=1) */
+ 		else {
+-			//i_Count=i_Count +6;
+-			//Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+-			//s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count +6;
++			/* i_Count=i_Count +6; */
++			/* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
++			/* s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count +6; */
+ 			s_BoardInfos[dev->minor].i_Count =
+ 				s_BoardInfos[dev->minor].i_Count + 9;
+-			//End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+-		}		//else if(i_ScanType!=1)
++			/* End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
++		}		/* else if(i_ScanType!=1) */
+ 
+-		//if((i_ScanType==1) &&(i_InterruptFlag==1))
++		/* if((i_ScanType==1) &&(i_InterruptFlag==1)) */
+ 		if ((s_BoardInfos[dev->minor].i_ScanType == 1)
+ 			&& (s_BoardInfos[dev->minor].i_InterruptFlag == 1)) {
+-			//i_Count=i_Count-6;
+-			//Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+-			//s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count-6;
++			/* i_Count=i_Count-6; */
++			/* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
++			/* s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count-6; */
+ 			s_BoardInfos[dev->minor].i_Count =
+ 				s_BoardInfos[dev->minor].i_Count - 9;
+-			//End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++			/* End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ 		}
+-		//if(i_ScanType==0)
++		/* if(i_ScanType==0) */
+ 		if (s_BoardInfos[dev->minor].i_ScanType == 0) {
+ 			/*
+ 			   data[0]= ui_InterruptChannelValue[0];
+@@ -1591,41 +1591,41 @@ int i_APCI3200_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevi
+ 				s_BoardInfos[dev->minor].
+ 				ui_InterruptChannelValue[5];
+ 
+-			//Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+-			//printk("\n 0 - i_APCI3200_GetChannelCalibrationValue data [6] = %lu, data [7] = %lu, data [8] = %lu", data [6], data [7], data [8]);
++			/* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
++			/* printk("\n 0 - i_APCI3200_GetChannelCalibrationValue data [6] = %lu, data [7] = %lu, data [8] = %lu", data [6], data [7], data [8]); */
+ 			i_APCI3200_GetChannelCalibrationValue(dev,
+ 				s_BoardInfos[dev->minor].ui_Channel_num,
+ 				&data[6], &data[7], &data[8]);
+-			//End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++			/* End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ 		}
+ 		break;
+ 	case 1:
+ 
+ 		for (i = 0; i < insn->n; i++) {
+-			//data[i]=ui_InterruptChannelValue[i];
++			/* data[i]=ui_InterruptChannelValue[i]; */
+ 			data[i] =
+ 				s_BoardInfos[dev->minor].
+ 				ui_InterruptChannelValue[i];
+ 		}
+ 
+-		//i_Count=0;
+-		//i_Sum=0;
+-		//if(i_ScanType==1)
++		/* i_Count=0; */
++		/* i_Sum=0; */
++		/* if(i_ScanType==1) */
+ 		s_BoardInfos[dev->minor].i_Count = 0;
+ 		s_BoardInfos[dev->minor].i_Sum = 0;
+ 		if (s_BoardInfos[dev->minor].i_ScanType == 1) {
+-			//i_Initialised=0;
+-			//i_InterruptFlag=0;
++			/* i_Initialised=0; */
++			/* i_InterruptFlag=0; */
+ 			s_BoardInfos[dev->minor].i_Initialised = 0;
+ 			s_BoardInfos[dev->minor].i_InterruptFlag = 0;
+-			//END JK 06.07.04: Management of sevrals boards
++			/* END JK 06.07.04: Management of sevrals boards */
+ 		}
+ 		break;
+ 	default:
+ 		printk("\nThe parameters passed are in error\n");
+ 		i_APCI3200_Reset(dev);
+ 		return -EINVAL;
+-	}			//switch(insn->unused[0])
++	}			/* switch(insn->unused[0]) */
+ 
+ 	return insn->n;
+ }
+@@ -1658,42 +1658,42 @@ int i_APCI3200_Read1AnalogInputChannel(struct comedi_device * dev,
+ 	unsigned int ui_ChannelNo = 0;
+ 	unsigned int ui_CommandRegister = 0;
+ 
+-	//BEGIN JK 06.07.04: Management of sevrals boards
+-	//ui_ChannelNo=i_ChannelNo;
++	/* BEGIN JK 06.07.04: Management of sevrals boards */
++	/* ui_ChannelNo=i_ChannelNo; */
+ 	ui_ChannelNo = s_BoardInfos[dev->minor].i_ChannelNo;
+ 
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+   /*********************************/
+ 	/* Write the channel to configure */
+   /*********************************/
+-	//Begin JK 20.10.2004: Bad channel value is used when using differential mode
+-	//outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4);
+-	//outl(0 | s_BoardInfos [dev->minor].ui_Channel_num , devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 0x4);
++	/* Begin JK 20.10.2004: Bad channel value is used when using differential mode */
++	/* outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4); */
++	/* outl(0 | s_BoardInfos [dev->minor].ui_Channel_num , devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 0x4); */
+ 	outl(0 | s_BoardInfos[dev->minor].i_ChannelNo,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x4);
+-	//End JK 20.10.2004: Bad channel value is used when using differential mode
++	/* End JK 20.10.2004: Bad channel value is used when using differential mode */
+ 
+   /*******************************/
+ 	/* Set the convert timing unit */
+   /*******************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+ 
+-	//outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36);
++	/* outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); */
+ 	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
+ 
+   /**************************/
+ 	/* Set the convert timing */
+   /**************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+ 
+-	//outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32);
++	/* outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); */
+ 	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
+ 
+@@ -1707,36 +1707,36 @@ int i_APCI3200_Read1AnalogInputChannel(struct comedi_device * dev,
+ 	/*Test if the interrupt is enable */
+   /*********************************/
+ 
+-	//if (i_InterruptFlag == ADDIDATA_ENABLE)
++	/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
+ 	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
+       /************************/
+ 		/* Enable the interrupt */
+       /************************/
+ 		ui_CommandRegister = ui_CommandRegister | 0x00100000;
+-	}			//if (i_InterruptFlag == ADDIDATA_ENABLE)
++	}			/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
+ 
+   /******************************/
+ 	/* Write the command register */
+   /******************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+ 
+-	//outl(ui_CommandRegister, devpriv->iobase+i_Offset + 8);
++	/* outl(ui_CommandRegister, devpriv->iobase+i_Offset + 8); */
+ 	outl(ui_CommandRegister,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+ 
+   /*****************************/
+ 	/*Test if interrupt is enable */
+   /*****************************/
+-	//if (i_InterruptFlag == ADDIDATA_DISABLE)
++	/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
+ 	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
+ 		do {
+ 	  /*************************/
+ 			/*Read the EOC Status bit */
+ 	  /*************************/
+ 
+-			//ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1;
++			/* ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; */
+ 			ui_EOC = inl(devpriv->iobase +
+ 				s_BoardInfos[dev->minor].i_Offset + 20) & 1;
+ 
+@@ -1746,13 +1746,13 @@ int i_APCI3200_Read1AnalogInputChannel(struct comedi_device * dev,
+ 		/* Read the digital value of the input */
+       /***************************************/
+ 
+-		//data[0] = inl (devpriv->iobase+i_Offset + 28);
++		/* data[0] = inl (devpriv->iobase+i_Offset + 28); */
+ 		data[0] =
+ 			inl(devpriv->iobase +
+ 			s_BoardInfos[dev->minor].i_Offset + 28);
+-		//END JK 06.07.04: Management of sevrals boards
++		/* END JK 06.07.04: Management of sevrals boards */
+ 
+-	}			// if (i_InterruptFlag == ADDIDATA_DISABLE)
++	}			/*  if (i_InterruptFlag == ADDIDATA_DISABLE) */
+ 	return 0;
+ }
+ 
+@@ -1781,49 +1781,49 @@ int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device * dev, unsigned i
+ 	unsigned int ui_Temp = 0, ui_EOC = 0;
+ 	unsigned int ui_CommandRegister = 0;
+ 
+-	//BEGIN JK 06.07.04: Management of sevrals boards
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* BEGIN JK 06.07.04: Management of sevrals boards */
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+   /*********************************/
+ 	/* Write the channel to configure */
+   /*********************************/
+-	//Begin JK 20.10.2004: This seems not necessary !
+-	//outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4);
+-	//outl(0 | s_BoardInfos [dev->minor].ui_Channel_num , devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 0x4);
+-	//End JK 20.10.2004: This seems not necessary !
++	/* Begin JK 20.10.2004: This seems not necessary ! */
++	/* outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4); */
++	/* outl(0 | s_BoardInfos [dev->minor].ui_Channel_num , devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 0x4); */
++	/* End JK 20.10.2004: This seems not necessary ! */
+ 
+   /*******************************/
+ 	/* Set the convert timing unit */
+   /*******************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36);
++	/* outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); */
+ 	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
+   /**************************/
+ 	/* Set the convert timing */
+   /**************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32);
++	/* outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); */
+ 	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
+   /*****************************/
+ 	/*Read the calibration offset */
+   /*****************************/
+-	//ui_Temp = inl(devpriv->iobase+i_Offset + 12);
++	/* ui_Temp = inl(devpriv->iobase+i_Offset + 12); */
+ 	ui_Temp = inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+ 
+   /*********************************/
+ 	/*Configure the Offset Conversion */
+   /*********************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl((ui_Temp | 0x00020000), devpriv->iobase+i_Offset + 12);
++	/* outl((ui_Temp | 0x00020000), devpriv->iobase+i_Offset + 12); */
+ 	outl((ui_Temp | 0x00020000),
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+   /*******************************/
+@@ -1836,7 +1836,7 @@ int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device * dev, unsigned i
+ 	/*Test if the interrupt is enable */
+   /*********************************/
+ 
+-	//if (i_InterruptFlag == ADDIDATA_ENABLE)
++	/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
+ 	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
+ 
+       /**********************/
+@@ -1845,7 +1845,7 @@ int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device * dev, unsigned i
+ 
+ 		ui_CommandRegister = ui_CommandRegister | 0x00100000;
+ 
+-	}			//if (i_InterruptFlag == ADDIDATA_ENABLE)
++	}			/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
+ 
+   /**********************/
+ 	/*Start the conversion */
+@@ -1855,10 +1855,10 @@ int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device * dev, unsigned i
+   /***************************/
+ 	/*Write the command regiter */
+   /***************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl(ui_CommandRegister, devpriv->iobase+i_Offset + 8);
++	/* outl(ui_CommandRegister, devpriv->iobase+i_Offset + 8); */
+ 	outl(ui_CommandRegister,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+ 
+@@ -1866,7 +1866,7 @@ int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device * dev, unsigned i
+ 	/*Test if interrupt is enable */
+   /*****************************/
+ 
+-	//if (i_InterruptFlag == ADDIDATA_DISABLE)
++	/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
+ 	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
+ 
+ 		do {
+@@ -1874,7 +1874,7 @@ int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device * dev, unsigned i
+ 			/*Read the EOC flag */
+ 	  /*******************/
+ 
+-			//ui_EOC = inl (devpriv->iobase+i_Offset + 20) & 1;
++			/* ui_EOC = inl (devpriv->iobase+i_Offset + 20) & 1; */
+ 			ui_EOC = inl(devpriv->iobase +
+ 				s_BoardInfos[dev->minor].i_Offset + 20) & 1;
+ 
+@@ -1884,11 +1884,11 @@ int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device * dev, unsigned i
+ 		/*Read the digital value of the calibration Offset */
+       /**************************************************/
+ 
+-		//data[0] = inl(devpriv->iobase+i_Offset+ 28);
++		/* data[0] = inl(devpriv->iobase+i_Offset+ 28); */
+ 		data[0] =
+ 			inl(devpriv->iobase +
+ 			s_BoardInfos[dev->minor].i_Offset + 28);
+-	}			//if (i_InterruptFlag == ADDIDATA_DISABLE)
++	}			/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
+ 	return 0;
+ }
+ 
+@@ -1917,16 +1917,16 @@ int i_APCI3200_ReadCalibrationGainValue(struct comedi_device * dev, unsigned int
+ 	unsigned int ui_EOC = 0;
+ 	int ui_CommandRegister = 0;
+ 
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+   /*********************************/
+ 	/* Write the channel to configure */
+   /*********************************/
+-	//Begin JK 20.10.2004: This seems not necessary !
+-	//outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4);
+-	//outl(0 | s_BoardInfos [dev->minor].ui_Channel_num , devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 0x4);
+-	//End JK 20.10.2004: This seems not necessary !
++	/* Begin JK 20.10.2004: This seems not necessary ! */
++	/* outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4); */
++	/* outl(0 | s_BoardInfos [dev->minor].ui_Channel_num , devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 0x4); */
++	/* End JK 20.10.2004: This seems not necessary ! */
+ 
+   /***************************/
+ 	/*Read the calibration gain */
+@@ -1934,28 +1934,28 @@ int i_APCI3200_ReadCalibrationGainValue(struct comedi_device * dev, unsigned int
+   /*******************************/
+ 	/* Set the convert timing unit */
+   /*******************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36);
++	/* outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); */
+ 	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
+   /**************************/
+ 	/* Set the convert timing */
+   /**************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32);
++	/* outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); */
+ 	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
+   /*******************************/
+ 	/*Configure the Gain Conversion */
+   /*******************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl(0x00040000 , devpriv->iobase+i_Offset + 12);
++	/* outl(0x00040000 , devpriv->iobase+i_Offset + 12); */
+ 	outl(0x00040000,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+ 
+@@ -1969,7 +1969,7 @@ int i_APCI3200_ReadCalibrationGainValue(struct comedi_device * dev, unsigned int
+ 	/*Test if the interrupt is enable */
+   /*********************************/
+ 
+-	//if (i_InterruptFlag == ADDIDATA_ENABLE)
++	/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
+ 	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
+ 
+       /**********************/
+@@ -1978,7 +1978,7 @@ int i_APCI3200_ReadCalibrationGainValue(struct comedi_device * dev, unsigned int
+ 
+ 		ui_CommandRegister = ui_CommandRegister | 0x00100000;
+ 
+-	}			//if (i_InterruptFlag == ADDIDATA_ENABLE)
++	}			/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
+ 
+   /**********************/
+ 	/*Start the conversion */
+@@ -1988,10 +1988,10 @@ int i_APCI3200_ReadCalibrationGainValue(struct comedi_device * dev, unsigned int
+   /***************************/
+ 	/*Write the command regiter */
+   /***************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl(ui_CommandRegister , devpriv->iobase+i_Offset + 8);
++	/* outl(ui_CommandRegister , devpriv->iobase+i_Offset + 8); */
+ 	outl(ui_CommandRegister,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+ 
+@@ -1999,7 +1999,7 @@ int i_APCI3200_ReadCalibrationGainValue(struct comedi_device * dev, unsigned int
+ 	/*Test if interrupt is enable */
+   /*****************************/
+ 
+-	//if (i_InterruptFlag == ADDIDATA_DISABLE)
++	/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
+ 	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
+ 
+ 		do {
+@@ -2008,7 +2008,7 @@ int i_APCI3200_ReadCalibrationGainValue(struct comedi_device * dev, unsigned int
+ 			/*Read the EOC flag */
+ 	  /*******************/
+ 
+-			//ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1;
++			/* ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; */
+ 			ui_EOC = inl(devpriv->iobase +
+ 				s_BoardInfos[dev->minor].i_Offset + 20) & 1;
+ 
+@@ -2018,12 +2018,12 @@ int i_APCI3200_ReadCalibrationGainValue(struct comedi_device * dev, unsigned int
+ 		/*Read the digital value of the calibration Gain */
+       /************************************************/
+ 
+-		//data[0] = inl(devpriv->iobase+i_Offset + 28);
++		/* data[0] = inl(devpriv->iobase+i_Offset + 28); */
+ 		data[0] =
+ 			inl(devpriv->iobase +
+ 			s_BoardInfos[dev->minor].i_Offset + 28);
+ 
+-	}			//if (i_InterruptFlag == ADDIDATA_DISABLE)
++	}			/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
+ 	return 0;
+ }
+ 
+@@ -2057,32 +2057,32 @@ int i_APCI3200_ReadCJCValue(struct comedi_device * dev, unsigned int * data)
+ 	/*Set the converting time unit */
+   /******************************/
+ 
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+ 
+-	//outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36);
++	/* outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); */
+ 	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
+   /**************************/
+ 	/* Set the convert timing */
+   /**************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+ 
+-	//outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32);
++	/* outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); */
+ 	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
+ 
+   /******************************/
+ 	/*Configure the CJC Conversion */
+   /******************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+ 
+-	//outl( 0x00000400 , devpriv->iobase+i_Offset + 4);
++	/* outl( 0x00000400 , devpriv->iobase+i_Offset + 4); */
+ 	outl(0x00000400,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
+   /*******************************/
+@@ -2092,7 +2092,7 @@ int i_APCI3200_ReadCJCValue(struct comedi_device * dev, unsigned int * data)
+   /*********************************/
+ 	/*Test if the interrupt is enable */
+   /*********************************/
+-	//if (i_InterruptFlag == ADDIDATA_ENABLE)
++	/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
+ 	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
+       /**********************/
+ 		/*Enable the interrupt */
+@@ -2109,10 +2109,10 @@ int i_APCI3200_ReadCJCValue(struct comedi_device * dev, unsigned int * data)
+   /***************************/
+ 	/*Write the command regiter */
+   /***************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl(ui_CommandRegister , devpriv->iobase+i_Offset + 8);
++	/* outl(ui_CommandRegister , devpriv->iobase+i_Offset + 8); */
+ 	outl(ui_CommandRegister,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+ 
+@@ -2120,7 +2120,7 @@ int i_APCI3200_ReadCJCValue(struct comedi_device * dev, unsigned int * data)
+ 	/*Test if interrupt is enable */
+   /*****************************/
+ 
+-	//if (i_InterruptFlag == ADDIDATA_DISABLE)
++	/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
+ 	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
+ 		do {
+ 
+@@ -2128,7 +2128,7 @@ int i_APCI3200_ReadCJCValue(struct comedi_device * dev, unsigned int * data)
+ 			/*Read the EOC flag */
+ 	  /*******************/
+ 
+-			//ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1;
++			/* ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; */
+ 			ui_EOC = inl(devpriv->iobase +
+ 				s_BoardInfos[dev->minor].i_Offset + 20) & 1;
+ 
+@@ -2138,12 +2138,12 @@ int i_APCI3200_ReadCJCValue(struct comedi_device * dev, unsigned int * data)
+ 		/*Read the digital value of the CJC */
+       /***********************************/
+ 
+-		//data[0] = inl(devpriv->iobase+i_Offset + 28);
++		/* data[0] = inl(devpriv->iobase+i_Offset + 28); */
+ 		data[0] =
+ 			inl(devpriv->iobase +
+ 			s_BoardInfos[dev->minor].i_Offset + 28);
+ 
+-	}			//if (i_InterruptFlag == ADDIDATA_DISABLE)
++	}			/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
+ 	return 0;
+ }
+ 
+@@ -2177,37 +2177,37 @@ int i_APCI3200_ReadCJCCalOffset(struct comedi_device * dev, unsigned int * data)
+   /*******************************/
+ 	/* Set the convert timing unit */
+   /*******************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36);
++	/* outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); */
+ 	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
+   /**************************/
+ 	/* Set the convert timing */
+   /**************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32);
++	/* outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); */
+ 	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
+   /******************************/
+ 	/*Configure the CJC Conversion */
+   /******************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl(0x00000400 , devpriv->iobase+i_Offset + 4);
++	/* outl(0x00000400 , devpriv->iobase+i_Offset + 4); */
+ 	outl(0x00000400,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
+   /*********************************/
+ 	/*Configure the Offset Conversion */
+   /*********************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl(0x00020000, devpriv->iobase+i_Offset + 12);
++	/* outl(0x00020000, devpriv->iobase+i_Offset + 12); */
+ 	outl(0x00020000,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+   /*******************************/
+@@ -2218,7 +2218,7 @@ int i_APCI3200_ReadCJCCalOffset(struct comedi_device * dev, unsigned int * data)
+ 	/*Test if the interrupt is enable */
+   /*********************************/
+ 
+-	//if (i_InterruptFlag == ADDIDATA_ENABLE)
++	/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
+ 	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
+       /**********************/
+ 		/*Enable the interrupt */
+@@ -2234,19 +2234,19 @@ int i_APCI3200_ReadCJCCalOffset(struct comedi_device * dev, unsigned int * data)
+   /***************************/
+ 	/*Write the command regiter */
+   /***************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl(ui_CommandRegister,devpriv->iobase+i_Offset + 8);
++	/* outl(ui_CommandRegister,devpriv->iobase+i_Offset + 8); */
+ 	outl(ui_CommandRegister,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+-	//if (i_InterruptFlag == ADDIDATA_DISABLE)
++	/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
+ 	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
+ 		do {
+ 	  /*******************/
+ 			/*Read the EOC flag */
+ 	  /*******************/
+-			//ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1;
++			/* ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; */
+ 			ui_EOC = inl(devpriv->iobase +
+ 				s_BoardInfos[dev->minor].i_Offset + 20) & 1;
+ 		} while (ui_EOC != 1);
+@@ -2254,11 +2254,11 @@ int i_APCI3200_ReadCJCCalOffset(struct comedi_device * dev, unsigned int * data)
+       /**************************************************/
+ 		/*Read the digital value of the calibration Offset */
+       /**************************************************/
+-		//data[0] = inl(devpriv->iobase+i_Offset + 28);
++		/* data[0] = inl(devpriv->iobase+i_Offset + 28); */
+ 		data[0] =
+ 			inl(devpriv->iobase +
+ 			s_BoardInfos[dev->minor].i_Offset + 28);
+-	}			//if (i_InterruptFlag == ADDIDATA_DISABLE)
++	}			/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
+ 	return 0;
+ }
+ 
+@@ -2290,37 +2290,37 @@ int i_APCI3200_ReadCJCCalGain(struct comedi_device * dev, unsigned int * data)
+   /*******************************/
+ 	/* Set the convert timing unit */
+   /*******************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36);
++	/* outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); */
+ 	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
+   /**************************/
+ 	/* Set the convert timing */
+   /**************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32);
++	/* outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); */
+ 	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
+   /******************************/
+ 	/*Configure the CJC Conversion */
+   /******************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl(0x00000400,devpriv->iobase+i_Offset + 4);
++	/* outl(0x00000400,devpriv->iobase+i_Offset + 4); */
+ 	outl(0x00000400,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
+   /*******************************/
+ 	/*Configure the Gain Conversion */
+   /*******************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl(0x00040000,devpriv->iobase+i_Offset + 12);
++	/* outl(0x00040000,devpriv->iobase+i_Offset + 12); */
+ 	outl(0x00040000,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+ 
+@@ -2331,7 +2331,7 @@ int i_APCI3200_ReadCJCCalGain(struct comedi_device * dev, unsigned int * data)
+   /*********************************/
+ 	/*Test if the interrupt is enable */
+   /*********************************/
+-	//if (i_InterruptFlag == ADDIDATA_ENABLE)
++	/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
+ 	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
+       /**********************/
+ 		/*Enable the interrupt */
+@@ -2345,30 +2345,30 @@ int i_APCI3200_ReadCJCCalGain(struct comedi_device * dev, unsigned int * data)
+   /***************************/
+ 	/*Write the command regiter */
+   /***************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl(ui_CommandRegister ,devpriv->iobase+i_Offset + 8);
++	/* outl(ui_CommandRegister ,devpriv->iobase+i_Offset + 8); */
+ 	outl(ui_CommandRegister,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+-	//if (i_InterruptFlag == ADDIDATA_DISABLE)
++	/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
+ 	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
+ 		do {
+ 	  /*******************/
+ 			/*Read the EOC flag */
+ 	  /*******************/
+-			//ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1;
++			/* ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; */
+ 			ui_EOC = inl(devpriv->iobase +
+ 				s_BoardInfos[dev->minor].i_Offset + 20) & 1;
+ 		} while (ui_EOC != 1);
+       /************************************************/
+ 		/*Read the digital value of the calibration Gain */
+       /************************************************/
+-		//data[0] = inl (devpriv->iobase+i_Offset + 28);
++		/* data[0] = inl (devpriv->iobase+i_Offset + 28); */
+ 		data[0] =
+ 			inl(devpriv->iobase +
+ 			s_BoardInfos[dev->minor].i_Offset + 28);
+-	}			//if (i_InterruptFlag == ADDIDATA_DISABLE)
++	}			/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
+ 	return 0;
+ }
+ 
+@@ -2408,29 +2408,29 @@ int i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int ui_Configuration = 0;
+-	int i_Temp;		//,i_TimeUnit;
+-	//if(i_Initialised==0)
++	int i_Temp;		/* ,i_TimeUnit; */
++	/* if(i_Initialised==0) */
+ 
+ 	if (s_BoardInfos[dev->minor].i_Initialised == 0) {
+ 		i_APCI3200_Reset(dev);
+ 		return -EINVAL;
+-	}			//if(i_Initialised==0);
++	}			/* if(i_Initialised==0); */
+ 	if (data[0] != 0 && data[0] != 1) {
+ 		printk("\nError in selection of functionality\n");
+ 		i_APCI3200_Reset(dev);
+ 		return -EINVAL;
+-	}			//if(data[0]!=0 && data[0]!=1)
++	}			/* if(data[0]!=0 && data[0]!=1) */
+ 
+-	if (data[0] == 1)	//Perform Short Circuit TEST
++	if (data[0] == 1)	/* Perform Short Circuit TEST */
+ 	{
+       /**************************/
+ 		/*Set the short-cicuit bit */
+       /**************************/
+-		//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++		/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 		while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].
+ 						i_Offset + 12) >> 19) & 1) !=
+ 			1) ;
+-		//outl((0x00001000 |i_ChannelNo) , devpriv->iobase+i_Offset + 4);
++		/* outl((0x00001000 |i_ChannelNo) , devpriv->iobase+i_Offset + 4); */
+ 		outl((0x00001000 | s_BoardInfos[dev->minor].i_ChannelNo),
+ 			devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 			4);
+@@ -2439,19 +2439,19 @@ int i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device * dev,
+       /*************************/
+ 		/* i_TimeUnit= i_ADDIDATAConversionTimeUnit;
+ 		   i_ADDIDATAConversionTimeUnit= 1; */
+-		//i_Temp= i_InterruptFlag ;
++		/* i_Temp= i_InterruptFlag ; */
+ 		i_Temp = s_BoardInfos[dev->minor].i_InterruptFlag;
+-		//i_InterruptFlag = ADDIDATA_DISABLE;
++		/* i_InterruptFlag = ADDIDATA_DISABLE; */
+ 		s_BoardInfos[dev->minor].i_InterruptFlag = ADDIDATA_DISABLE;
+ 		i_APCI3200_Read1AnalogInputChannel(dev, s, insn, data);
+-		//if(i_AutoCalibration == FALSE)
++		/* if(i_AutoCalibration == FALSE) */
+ 		if (s_BoardInfos[dev->minor].i_AutoCalibration == FALSE) {
+-			//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++			/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 			while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].
+ 							i_Offset +
+ 							12) >> 19) & 1) != 1) ;
+ 
+-			//outl((0x00001000 |i_ChannelNo) , devpriv->iobase+i_Offset + 4);
++			/* outl((0x00001000 |i_ChannelNo) , devpriv->iobase+i_Offset + 4); */
+ 			outl((0x00001000 | s_BoardInfos[dev->minor].
+ 					i_ChannelNo),
+ 				devpriv->iobase +
+@@ -2462,15 +2462,15 @@ int i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device * dev,
+ 			i_APCI3200_ReadCalibrationGainValue(dev, data);
+ 		}
+ 	} else {
+-		//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++		/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 		while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].
+ 						i_Offset + 12) >> 19) & 1) !=
+ 			1) ;
+-		//outl((0x00000800|i_ChannelNo) , devpriv->iobase+i_Offset + 4);
++		/* outl((0x00000800|i_ChannelNo) , devpriv->iobase+i_Offset + 4); */
+ 		outl((0x00000800 | s_BoardInfos[dev->minor].i_ChannelNo),
+ 			devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 			4);
+-		//ui_Configuration = inl(devpriv->iobase+i_Offset + 0);
++		/* ui_Configuration = inl(devpriv->iobase+i_Offset + 0); */
+ 		ui_Configuration =
+ 			inl(devpriv->iobase +
+ 			s_BoardInfos[dev->minor].i_Offset + 0);
+@@ -2479,18 +2479,18 @@ int i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device * dev,
+       /*************************/
+ 		/* i_TimeUnit= i_ADDIDATAConversionTimeUnit;
+ 		   i_ADDIDATAConversionTimeUnit= 1; */
+-		//i_Temp= i_InterruptFlag ;
++		/* i_Temp= i_InterruptFlag ; */
+ 		i_Temp = s_BoardInfos[dev->minor].i_InterruptFlag;
+-		//i_InterruptFlag = ADDIDATA_DISABLE;
++		/* i_InterruptFlag = ADDIDATA_DISABLE; */
+ 		s_BoardInfos[dev->minor].i_InterruptFlag = ADDIDATA_DISABLE;
+ 		i_APCI3200_Read1AnalogInputChannel(dev, s, insn, data);
+-		//if(i_AutoCalibration == FALSE)
++		/* if(i_AutoCalibration == FALSE) */
+ 		if (s_BoardInfos[dev->minor].i_AutoCalibration == FALSE) {
+-			//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++			/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 			while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].
+ 							i_Offset +
+ 							12) >> 19) & 1) != 1) ;
+-			//outl((0x00000800|i_ChannelNo) , devpriv->iobase+i_Offset + 4);
++			/* outl((0x00000800|i_ChannelNo) , devpriv->iobase+i_Offset + 4); */
+ 			outl((0x00000800 | s_BoardInfos[dev->minor].
+ 					i_ChannelNo),
+ 				devpriv->iobase +
+@@ -2501,9 +2501,9 @@ int i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device * dev,
+ 			i_APCI3200_ReadCalibrationGainValue(dev, data);
+ 		}
+ 	}
+-	//i_InterruptFlag=i_Temp ;
++	/* i_InterruptFlag=i_Temp ; */
+ 	s_BoardInfos[dev->minor].i_InterruptFlag = i_Temp;
+-	//printk("\ni_InterruptFlag=%d\n",i_InterruptFlag);
++	/* printk("\ni_InterruptFlag=%d\n",i_InterruptFlag); */
+ 	return insn->n;
+ }
+ 
+@@ -2565,7 +2565,7 @@ int i_APCI3200_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_
+ {
+ 
+ 	int err = 0;
+-	int tmp;		// divisor1,divisor2;
++	int tmp;		/*  divisor1,divisor2; */
+ 	unsigned int ui_ConvertTime = 0;
+ 	unsigned int ui_ConvertTimeBase = 0;
+ 	unsigned int ui_DelayTime = 0;
+@@ -2576,7 +2576,7 @@ int i_APCI3200_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_
+ 	int i_Cpt = 0;
+ 	double d_ConversionTimeForAllChannels = 0.0;
+ 	double d_SCANTimeNewUnit = 0.0;
+-	// step 1: make sure trigger sources are trivially valid
++	/*  step 1: make sure trigger sources are trivially valid */
+ 
+ 	tmp = cmd->start_src;
+ 	cmd->start_src &= TRIG_NOW | TRIG_EXT;
+@@ -2598,10 +2598,10 @@ int i_APCI3200_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_
+ 	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
+ 	if (!cmd->stop_src || tmp != cmd->stop_src)
+ 		err++;
+-	//if(i_InterruptFlag==0)
++	/* if(i_InterruptFlag==0) */
+ 	if (s_BoardInfos[dev->minor].i_InterruptFlag == 0) {
+ 		err++;
+-		//          printk("\nThe interrupt should be enabled\n");
++		/*           printk("\nThe interrupt should be enabled\n"); */
+ 	}
+ 	if (err) {
+ 		i_APCI3200_Reset(dev);
+@@ -2643,9 +2643,9 @@ int i_APCI3200_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_
+ 		i_APCI3200_Reset(dev);
+ 		return 2;
+ 	}
+-	//i_FirstChannel=cmd->chanlist[0];
++	/* i_FirstChannel=cmd->chanlist[0]; */
+ 	s_BoardInfos[dev->minor].i_FirstChannel = cmd->chanlist[0];
+-	//i_LastChannel=cmd->chanlist[1];
++	/* i_LastChannel=cmd->chanlist[1]; */
+ 	s_BoardInfos[dev->minor].i_LastChannel = cmd->chanlist[1];
+ 
+ 	if (cmd->convert_src == TRIG_TIMER) {
+@@ -2656,11 +2656,11 @@ int i_APCI3200_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_
+ 		{
+ 			printk("\nThe selection of conversion time reload value is in error\n");
+ 			err++;
+-		}		// if (ui_ConvertTime!=20 && ui_ConvertTime!=40 && ui_ConvertTime!=80 && ui_ConvertTime!=160 )
++		}		/*  if (ui_ConvertTime!=20 && ui_ConvertTime!=40 && ui_ConvertTime!=80 && ui_ConvertTime!=160 ) */
+ 		if (ui_ConvertTimeBase != 2) {
+ 			printk("\nThe selection of conversion time unit  is in error\n");
+ 			err++;
+-		}		//if(ui_ConvertTimeBase!=2)
++		}		/* if(ui_ConvertTimeBase!=2) */
+ 	} else {
+ 		ui_ConvertTime = 0;
+ 		ui_ConvertTimeBase = 0;
+@@ -2668,7 +2668,7 @@ int i_APCI3200_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_
+ 	if (cmd->scan_begin_src == TRIG_FOLLOW) {
+ 		ui_DelayTime = 0;
+ 		ui_DelayTimeBase = 0;
+-	}			//if(cmd->scan_begin_src==TRIG_FOLLOW)
++	}			/* if(cmd->scan_begin_src==TRIG_FOLLOW) */
+ 	else {
+ 		ui_DelayTime = cmd->scan_begin_arg & 0xFFFF;
+ 		ui_DelayTimeBase = cmd->scan_begin_arg >> 16;
+@@ -2686,7 +2686,7 @@ int i_APCI3200_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_
+ 		}
+ 		fpu_begin();
+ 		d_SCANTimeNewUnit = (double)ui_DelayTime;
+-		//i_NbrOfChannel= i_LastChannel-i_FirstChannel + 4;
++		/* i_NbrOfChannel= i_LastChannel-i_FirstChannel + 4; */
+ 		i_NbrOfChannel =
+ 			s_BoardInfos[dev->minor].i_LastChannel -
+ 			s_BoardInfos[dev->minor].i_FirstChannel + 4;
+@@ -2736,7 +2736,7 @@ int i_APCI3200_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_
+ 			err++;
+ 		}
+ 		fpu_end();
+-	}			//else if(cmd->scan_begin_src==TRIG_FOLLOW)
++	}			/* else if(cmd->scan_begin_src==TRIG_FOLLOW) */
+ 
+ 	if (err) {
+ 		i_APCI3200_Reset(dev);
+@@ -2767,10 +2767,10 @@ int i_APCI3200_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_
+ int i_APCI3200_StopCyclicAcquisition(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned int ui_Configuration = 0;
+-	//i_InterruptFlag=0;
+-	//i_Initialised=0;
+-	//i_Count=0;
+-	//i_Sum=0;
++	/* i_InterruptFlag=0; */
++	/* i_Initialised=0; */
++	/* i_Count=0; */
++	/* i_Sum=0; */
+ 	s_BoardInfos[dev->minor].i_InterruptFlag = 0;
+ 	s_BoardInfos[dev->minor].i_Initialised = 0;
+ 	s_BoardInfos[dev->minor].i_Count = 0;
+@@ -2779,16 +2779,16 @@ int i_APCI3200_StopCyclicAcquisition(struct comedi_device * dev, struct comedi_s
+   /*******************/
+ 	/*Read the register */
+   /*******************/
+-	//ui_Configuration = inl(devpriv->iobase+i_Offset + 8);
++	/* ui_Configuration = inl(devpriv->iobase+i_Offset + 8); */
+ 	ui_Configuration =
+ 		inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+   /*****************************/
+ 	/*Reset the START and IRQ bit */
+   /*****************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl((ui_Configuration & 0xFFE7FFFF),devpriv->iobase+i_Offset + 8);
++	/* outl((ui_Configuration & 0xFFE7FFFF),devpriv->iobase+i_Offset + 8); */
+ 	outl((ui_Configuration & 0xFFE7FFFF),
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+ 	return 0;
+@@ -2818,7 +2818,7 @@ int i_APCI3200_CommandAnalogInput(struct comedi_device * dev, struct comedi_subd
+ {
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned int ui_Configuration = 0;
+-	//INT  i_CurrentSource = 0;
++	/* INT  i_CurrentSource = 0; */
+ 	unsigned int ui_Trigger = 0;
+ 	unsigned int ui_TriggerEdge = 0;
+ 	unsigned int ui_Triggermode = 0;
+@@ -2828,38 +2828,38 @@ int i_APCI3200_CommandAnalogInput(struct comedi_device * dev, struct comedi_subd
+ 	unsigned int ui_DelayTime = 0;
+ 	unsigned int ui_DelayTimeBase = 0;
+ 	unsigned int ui_DelayMode = 0;
+-	//i_FirstChannel=cmd->chanlist[0];
+-	//i_LastChannel=cmd->chanlist[1];
++	/* i_FirstChannel=cmd->chanlist[0]; */
++	/* i_LastChannel=cmd->chanlist[1]; */
+ 	s_BoardInfos[dev->minor].i_FirstChannel = cmd->chanlist[0];
+ 	s_BoardInfos[dev->minor].i_LastChannel = cmd->chanlist[1];
+ 	if (cmd->start_src == TRIG_EXT) {
+ 		ui_Trigger = 1;
+ 		ui_TriggerEdge = cmd->start_arg & 0xFFFF;
+ 		ui_Triggermode = cmd->start_arg >> 16;
+-	}			//if(cmd->start_src==TRIG_EXT)
++	}			/* if(cmd->start_src==TRIG_EXT) */
+ 	else {
+ 		ui_Trigger = 0;
+-	}			//elseif(cmd->start_src==TRIG_EXT)
++	}			/* elseif(cmd->start_src==TRIG_EXT) */
+ 
+ 	if (cmd->stop_src == TRIG_COUNT) {
+ 		ui_ScanMode = 0;
+-	}			// if (cmd->stop_src==TRIG_COUNT)
++	}			/*  if (cmd->stop_src==TRIG_COUNT) */
+ 	else {
+ 		ui_ScanMode = 2;
+-	}			//else if (cmd->stop_src==TRIG_COUNT)
++	}			/* else if (cmd->stop_src==TRIG_COUNT) */
+ 
+ 	if (cmd->scan_begin_src == TRIG_FOLLOW) {
+ 		ui_DelayTime = 0;
+ 		ui_DelayTimeBase = 0;
+ 		ui_DelayMode = 0;
+-	}			//if(cmd->scan_begin_src==TRIG_FOLLOW)
++	}			/* if(cmd->scan_begin_src==TRIG_FOLLOW) */
+ 	else {
+ 		ui_DelayTime = cmd->scan_begin_arg & 0xFFFF;
+ 		ui_DelayTimeBase = cmd->scan_begin_arg >> 16;
+ 		ui_DelayMode = 1;
+-	}			//else if(cmd->scan_begin_src==TRIG_FOLLOW)
+-	//        printk("\nui_DelayTime=%u\n",ui_DelayTime);
+-	//        printk("\nui_DelayTimeBase=%u\n",ui_DelayTimeBase);
++	}			/* else if(cmd->scan_begin_src==TRIG_FOLLOW) */
++	/*         printk("\nui_DelayTime=%u\n",ui_DelayTime); */
++	/*         printk("\nui_DelayTimeBase=%u\n",ui_DelayTimeBase); */
+ 	if (cmd->convert_src == TRIG_TIMER) {
+ 		ui_ConvertTime = cmd->convert_arg & 0xFFFF;
+ 		ui_ConvertTimeBase = cmd->convert_arg >> 16;
+@@ -2868,34 +2868,34 @@ int i_APCI3200_CommandAnalogInput(struct comedi_device * dev, struct comedi_subd
+ 		ui_ConvertTimeBase = 0;
+ 	}
+ 
+-	// if(i_ADDIDATAType ==1 || ((i_ADDIDATAType==2)))
+-	//   {
++	/*  if(i_ADDIDATAType ==1 || ((i_ADDIDATAType==2))) */
++	/*    { */
+   /**************************************************/
+ 	/*Read the old configuration of the current source */
+   /**************************************************/
+-	//ui_Configuration = inl(devpriv->iobase+i_Offset + 12);
++	/* ui_Configuration = inl(devpriv->iobase+i_Offset + 12); */
+ 	ui_Configuration =
+ 		inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+   /***********************************************/
+ 	/*Write the configuration of the current source */
+   /***********************************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl((ui_Configuration & 0xFFC00000 ), devpriv->iobase+i_Offset +12);
++	/* outl((ui_Configuration & 0xFFC00000 ), devpriv->iobase+i_Offset +12); */
+ 	outl((ui_Configuration & 0xFFC00000),
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+-	// }
++	/*  } */
+ 	ui_Configuration = 0;
+-	//     printk("\nfirstchannel=%u\n",i_FirstChannel);
+-	//     printk("\nlastchannel=%u\n",i_LastChannel);
+-	//     printk("\nui_Trigger=%u\n",ui_Trigger);
+-	//     printk("\nui_TriggerEdge=%u\n",ui_TriggerEdge);
+-	//     printk("\nui_Triggermode=%u\n",ui_Triggermode);
+-	//      printk("\nui_DelayMode=%u\n",ui_DelayMode);
+-	//     printk("\nui_ScanMode=%u\n",ui_ScanMode);
+-
+-	//ui_Configuration = i_FirstChannel |(i_LastChannel << 8)| 0x00100000 |
++	/*      printk("\nfirstchannel=%u\n",i_FirstChannel); */
++	/*      printk("\nlastchannel=%u\n",i_LastChannel); */
++	/*      printk("\nui_Trigger=%u\n",ui_Trigger); */
++	/*      printk("\nui_TriggerEdge=%u\n",ui_TriggerEdge); */
++	/*      printk("\nui_Triggermode=%u\n",ui_Triggermode); */
++	/*       printk("\nui_DelayMode=%u\n",ui_DelayMode); */
++	/*      printk("\nui_ScanMode=%u\n",ui_ScanMode); */
++
++	/* ui_Configuration = i_FirstChannel |(i_LastChannel << 8)| 0x00100000 | */
+ 	ui_Configuration =
+ 		s_BoardInfos[dev->minor].i_FirstChannel | (s_BoardInfos[dev->
+ 			minor].
+@@ -2906,80 +2906,80 @@ int i_APCI3200_CommandAnalogInput(struct comedi_device * dev, struct comedi_subd
+   /*************************/
+ 	/*Write the Configuration */
+   /*************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl( ui_Configuration, devpriv->iobase+i_Offset + 0x8);
++	/* outl( ui_Configuration, devpriv->iobase+i_Offset + 0x8); */
+ 	outl(ui_Configuration,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x8);
+   /***********************/
+ 	/*Write the Delay Value */
+   /***********************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl(ui_DelayTime,devpriv->iobase+i_Offset + 40);
++	/* outl(ui_DelayTime,devpriv->iobase+i_Offset + 40); */
+ 	outl(ui_DelayTime,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 40);
+   /***************************/
+ 	/*Write the Delay time base */
+   /***************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl(ui_DelayTimeBase,devpriv->iobase+i_Offset + 44);
++	/* outl(ui_DelayTimeBase,devpriv->iobase+i_Offset + 44); */
+ 	outl(ui_DelayTimeBase,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 44);
+   /*********************************/
+ 	/*Write the conversion time value */
+   /*********************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl(ui_ConvertTime,devpriv->iobase+i_Offset + 32);
++	/* outl(ui_ConvertTime,devpriv->iobase+i_Offset + 32); */
+ 	outl(ui_ConvertTime,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
+ 
+   /********************************/
+ 	/*Write the conversion time base */
+   /********************************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl(ui_ConvertTimeBase,devpriv->iobase+i_Offset + 36);
++	/* outl(ui_ConvertTimeBase,devpriv->iobase+i_Offset + 36); */
+ 	outl(ui_ConvertTimeBase,
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
+   /*******************/
+ 	/*Read the register */
+   /*******************/
+-	//ui_Configuration = inl(devpriv->iobase+i_Offset + 4);
++	/* ui_Configuration = inl(devpriv->iobase+i_Offset + 4); */
+ 	ui_Configuration =
+ 		inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
+   /******************/
+ 	/*Set the SCAN bit */
+   /******************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+ 
+-	//outl(((ui_Configuration & 0x1E0FF) | 0x00002000),devpriv->iobase+i_Offset + 4);
++	/* outl(((ui_Configuration & 0x1E0FF) | 0x00002000),devpriv->iobase+i_Offset + 4); */
+ 	outl(((ui_Configuration & 0x1E0FF) | 0x00002000),
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
+   /*******************/
+ 	/*Read the register */
+   /*******************/
+ 	ui_Configuration = 0;
+-	//ui_Configuration = inl(devpriv->iobase+i_Offset + 8);
++	/* ui_Configuration = inl(devpriv->iobase+i_Offset + 8); */
+ 	ui_Configuration =
+ 		inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+ 
+   /*******************/
+ 	/*Set the START bit */
+   /*******************/
+-	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
++	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+ 					12) >> 19) & 1) != 1) ;
+-	//outl((ui_Configuration | 0x00080000),devpriv->iobase+i_Offset + 8);
++	/* outl((ui_Configuration | 0x00080000),devpriv->iobase+i_Offset + 8); */
+ 	outl((ui_Configuration | 0x00080000),
+ 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+ 	return 0;
+@@ -3005,10 +3005,10 @@ int i_APCI3200_Reset(struct comedi_device * dev)
+ {
+ 	int i_Temp;
+ 	unsigned int dw_Dummy;
+-	//i_InterruptFlag=0;
+-	//i_Initialised==0;
+-	//i_Count=0;
+-	//i_Sum=0;
++	/* i_InterruptFlag=0; */
++	/* i_Initialised==0; */
++	/* i_Count=0; */
++	/* i_Sum=0; */
+ 
+ 	s_BoardInfos[dev->minor].i_InterruptFlag = 0;
+ 	s_BoardInfos[dev->minor].i_Initialised = 0;
+@@ -3018,17 +3018,17 @@ int i_APCI3200_Reset(struct comedi_device * dev)
+ 
+ 	outl(0x83838383, devpriv->i_IobaseAmcc + 0x60);
+ 
+-	// Enable the interrupt for the controler
++	/*  Enable the interrupt for the controler */
+ 	dw_Dummy = inl(devpriv->i_IobaseAmcc + 0x38);
+ 	outl(dw_Dummy | 0x2000, devpriv->i_IobaseAmcc + 0x38);
+-	outl(0, devpriv->i_IobaseAddon);	//Resets the output
++	outl(0, devpriv->i_IobaseAddon);	/* Resets the output */
+   /***************/
+ 	/*Empty the buffer */
+   /**************/
+ 	for (i_Temp = 0; i_Temp <= 95; i_Temp++) {
+-		//ui_InterruptChannelValue[i_Temp]=0;
++		/* ui_InterruptChannelValue[i_Temp]=0; */
+ 		s_BoardInfos[dev->minor].ui_InterruptChannelValue[i_Temp] = 0;
+-	}			//for(i_Temp=0;i_Temp<=95;i_Temp++)
++	}			/* for(i_Temp=0;i_Temp<=95;i_Temp++) */
+   /*****************************/
+ 	/*Reset the START and IRQ bit */
+   /*****************************/
+@@ -3036,7 +3036,7 @@ int i_APCI3200_Reset(struct comedi_device * dev)
+ 		while (((inl(devpriv->iobase + i_Temp + 12) >> 19) & 1) != 1) ;
+ 		outl(0, devpriv->iobase + i_Temp + 8);
+ 		i_Temp = i_Temp + 64;
+-	}			//for(i_Temp=0;i_Temp<=192;i_Temp+64)
++	}			/* for(i_Temp=0;i_Temp<=192;i_Temp+64) */
+ 	return 0;
+ }
+ 
+@@ -3069,17 +3069,17 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 	unsigned int ui_DigitalInput = 0;
+ 	int i_ConvertCJCCalibration;
+ 
+-	//BEGIN JK TEST
++	/* BEGIN JK TEST */
+ 	int i_ReturnValue = 0;
+-	//END JK TEST
++	/* END JK TEST */
+ 
+-	//printk ("\n i_ScanType = %i i_ADDIDATAType = %i", s_BoardInfos [dev->minor].i_ScanType, s_BoardInfos [dev->minor].i_ADDIDATAType);
++	/* printk ("\n i_ScanType = %i i_ADDIDATAType = %i", s_BoardInfos [dev->minor].i_ScanType, s_BoardInfos [dev->minor].i_ADDIDATAType); */
+ 
+-	//switch(i_ScanType)
++	/* switch(i_ScanType) */
+ 	switch (s_BoardInfos[dev->minor].i_ScanType) {
+ 	case 0:
+ 	case 1:
+-		//switch(i_ADDIDATAType)
++		/* switch(i_ADDIDATAType) */
+ 		switch (s_BoardInfos[dev->minor].i_ADDIDATAType) {
+ 		case 0:
+ 		case 1:
+@@ -3087,12 +3087,12 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 	  /************************************/
+ 			/*Read the interrupt status register */
+ 	  /************************************/
+-			//ui_StatusRegister = inl(devpriv->iobase+i_Offset + 16);
++			/* ui_StatusRegister = inl(devpriv->iobase+i_Offset + 16); */
+ 			ui_StatusRegister =
+ 				inl(devpriv->iobase +
+ 				s_BoardInfos[dev->minor].i_Offset + 16);
+ 			if ((ui_StatusRegister & 0x2) == 0x2) {
+-				//i_CalibrationFlag = ((inl(devpriv->iobase+i_Offset + 12) & 0x00060000) >> 17);
++				/* i_CalibrationFlag = ((inl(devpriv->iobase+i_Offset + 12) & 0x00060000) >> 17); */
+ 				i_CalibrationFlag =
+ 					((inl(devpriv->iobase +
+ 							s_BoardInfos[dev->
+@@ -3103,12 +3103,12 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 	      /*************************/
+ 				/*Read the channel number */
+ 	      /*************************/
+-				//ui_ChannelNumber = inl(devpriv->iobase+i_Offset + 24);
++				/* ui_ChannelNumber = inl(devpriv->iobase+i_Offset + 24); */
+ 
+ 	      /*************************************/
+ 				/*Read the digital analog input value */
+ 	      /*************************************/
+-				//ui_DigitalInput = inl(devpriv->iobase+i_Offset + 28);
++				/* ui_DigitalInput = inl(devpriv->iobase+i_Offset + 28); */
+ 				ui_DigitalInput =
+ 					inl(devpriv->iobase +
+ 					s_BoardInfos[dev->minor].i_Offset + 28);
+@@ -3117,13 +3117,13 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 				/* Test if the value read is the channel value */
+ 	      /***********************************************/
+ 				if (i_CalibrationFlag == 0) {
+-					//ui_InterruptChannelValue[i_Count + 0] = ui_DigitalInput;
++					/* ui_InterruptChannelValue[i_Count + 0] = ui_DigitalInput; */
+ 					s_BoardInfos[dev->minor].
+ 						ui_InterruptChannelValue
+ 						[s_BoardInfos[dev->minor].
+ 						i_Count + 0] = ui_DigitalInput;
+ 
+-					//Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++					/* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ 					/*
+ 					   printk("\n 1 - i_APCI3200_GetChannelCalibrationValue (dev, s_BoardInfos %i", ui_ChannelNumber);
+ 					   i_APCI3200_GetChannelCalibrationValue (dev, s_BoardInfos [dev->minor].ui_Channel_num,
+@@ -3131,14 +3131,14 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 					   &s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count + 7],
+ 					   &s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count + 8]);
+ 					 */
+-					//End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++					/* End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ 
+ 		  /******************************************************/
+ 					/*Start the conversion of the calibration offset value */
+ 		  /******************************************************/
+ 					i_APCI3200_ReadCalibrationOffsetValue
+ 						(dev, &ui_DummyValue);
+-				}	//if (i_CalibrationFlag == 0)
++				}	/* if (i_CalibrationFlag == 0) */
+ 	      /**********************************************************/
+ 				/* Test if the value read is the calibration offset value */
+ 	      /**********************************************************/
+@@ -3149,7 +3149,7 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 					/* Save the value */
+ 		  /******************/
+ 
+-					//ui_InterruptChannelValue[i_Count + 1] = ui_DigitalInput;
++					/* ui_InterruptChannelValue[i_Count + 1] = ui_DigitalInput; */
+ 					s_BoardInfos[dev->minor].
+ 						ui_InterruptChannelValue
+ 						[s_BoardInfos[dev->minor].
+@@ -3160,7 +3160,7 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 		  /******************************************************/
+ 					i_APCI3200_ReadCalibrationGainValue(dev,
+ 						&ui_DummyValue);
+-				}	//if (i_CalibrationFlag == 1)
++				}	/* if (i_CalibrationFlag == 1) */
+ 	      /******************************************************/
+ 				/*Test if the value read is the calibration gain value */
+ 	      /******************************************************/
+@@ -3170,48 +3170,48 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 		  /****************/
+ 					/*Save the value */
+ 		  /****************/
+-					//ui_InterruptChannelValue[i_Count + 2] = ui_DigitalInput;
++					/* ui_InterruptChannelValue[i_Count + 2] = ui_DigitalInput; */
+ 					s_BoardInfos[dev->minor].
+ 						ui_InterruptChannelValue
+ 						[s_BoardInfos[dev->minor].
+ 						i_Count + 2] = ui_DigitalInput;
+-					//if(i_ScanType==1)
++					/* if(i_ScanType==1) */
+ 					if (s_BoardInfos[dev->minor].
+ 						i_ScanType == 1) {
+ 
+-						//i_InterruptFlag=0;
++						/* i_InterruptFlag=0; */
+ 						s_BoardInfos[dev->minor].
+ 							i_InterruptFlag = 0;
+-						//i_Count=i_Count + 6;
+-						//Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+-						//s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count + 6;
++						/* i_Count=i_Count + 6; */
++						/* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
++						/* s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count + 6; */
+ 						s_BoardInfos[dev->minor].
+ 							i_Count =
+ 							s_BoardInfos[dev->
+ 							minor].i_Count + 9;
+-						//End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+-					}	//if(i_ScanType==1)
++						/* End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
++					}	/* if(i_ScanType==1) */
+ 					else {
+-						//i_Count=0;
++						/* i_Count=0; */
+ 						s_BoardInfos[dev->minor].
+ 							i_Count = 0;
+-					}	//elseif(i_ScanType==1)
+-					//if(i_ScanType!=1)
++					}	/* elseif(i_ScanType==1) */
++					/* if(i_ScanType!=1) */
+ 					if (s_BoardInfos[dev->minor].
+ 						i_ScanType != 1) {
+-						i_ReturnValue = send_sig(SIGIO, devpriv->tsk_Current, 0);	// send signal to the sample
+-					}	//if(i_ScanType!=1)
++						i_ReturnValue = send_sig(SIGIO, devpriv->tsk_Current, 0);	/*  send signal to the sample */
++					}	/* if(i_ScanType!=1) */
+ 					else {
+-						//if(i_ChannelCount==i_Sum)
++						/* if(i_ChannelCount==i_Sum) */
+ 						if (s_BoardInfos[dev->minor].
+ 							i_ChannelCount ==
+ 							s_BoardInfos[dev->
+ 								minor].i_Sum) {
+-							send_sig(SIGIO, devpriv->tsk_Current, 0);	// send signal to the sample
++							send_sig(SIGIO, devpriv->tsk_Current, 0);	/*  send signal to the sample */
+ 						}
+-					}	//if(i_ScanType!=1)
+-				}	//if (i_CalibrationFlag == 2)
+-			}	// if ((ui_StatusRegister & 0x2) == 0x2)
++					}	/* if(i_ScanType!=1) */
++				}	/* if (i_CalibrationFlag == 2) */
++			}	/*  if ((ui_StatusRegister & 0x2) == 0x2) */
+ 
+ 			break;
+ 
+@@ -3220,7 +3220,7 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 			/*Read the interrupt status register */
+ 	  /************************************/
+ 
+-			//ui_StatusRegister = inl(devpriv->iobase+i_Offset + 16);
++			/* ui_StatusRegister = inl(devpriv->iobase+i_Offset + 16); */
+ 			ui_StatusRegister =
+ 				inl(devpriv->iobase +
+ 				s_BoardInfos[dev->minor].i_Offset + 16);
+@@ -3230,7 +3230,7 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 
+ 			if ((ui_StatusRegister & 0x2) == 0x2) {
+ 
+-				//i_CJCFlag = ((inl(devpriv->iobase+i_Offset + 4) & 0x00000400) >> 10);
++				/* i_CJCFlag = ((inl(devpriv->iobase+i_Offset + 4) & 0x00000400) >> 10); */
+ 				i_CJCFlag =
+ 					((inl(devpriv->iobase +
+ 							s_BoardInfos[dev->
+@@ -3238,7 +3238,7 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 							i_Offset +
+ 							4) & 0x00000400) >> 10);
+ 
+-				//i_CalibrationFlag = ((inl(devpriv->iobase+i_Offset + 12) & 0x00060000) >> 17);
++				/* i_CalibrationFlag = ((inl(devpriv->iobase+i_Offset + 12) & 0x00060000) >> 17); */
+ 				i_CalibrationFlag =
+ 					((inl(devpriv->iobase +
+ 							s_BoardInfos[dev->
+@@ -3251,19 +3251,19 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 				/*Read the channel number */
+ 	      /*************************/
+ 
+-				//ui_ChannelNumber = inl(devpriv->iobase+i_Offset + 24);
++				/* ui_ChannelNumber = inl(devpriv->iobase+i_Offset + 24); */
+ 				ui_ChannelNumber =
+ 					inl(devpriv->iobase +
+ 					s_BoardInfos[dev->minor].i_Offset + 24);
+-				//Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++				/* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ 				s_BoardInfos[dev->minor].ui_Channel_num =
+ 					ui_ChannelNumber;
+-				//End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++				/* End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ 
+ 	      /************************************/
+ 				/*Read the digital temperature value */
+ 	      /************************************/
+-				//ui_DigitalTemperature = inl(devpriv->iobase+i_Offset + 28);
++				/* ui_DigitalTemperature = inl(devpriv->iobase+i_Offset + 28); */
+ 				ui_DigitalTemperature =
+ 					inl(devpriv->iobase +
+ 					s_BoardInfos[dev->minor].i_Offset + 28);
+@@ -3274,7 +3274,7 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 
+ 				if ((i_CalibrationFlag == 0)
+ 					&& (i_CJCFlag == 0)) {
+-					//ui_InterruptChannelValue[i_Count + 0]=ui_DigitalTemperature;
++					/* ui_InterruptChannelValue[i_Count + 0]=ui_DigitalTemperature; */
+ 					s_BoardInfos[dev->minor].
+ 						ui_InterruptChannelValue
+ 						[s_BoardInfos[dev->minor].
+@@ -3287,7 +3287,7 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 					i_APCI3200_ReadCJCValue(dev,
+ 						&ui_DummyValue);
+ 
+-				}	//if ((i_CalibrationFlag == 0) && (i_CJCFlag == 0))
++				}	/* if ((i_CalibrationFlag == 0) && (i_CJCFlag == 0)) */
+ 
+ 		 /*****************************************/
+ 				/*Test if the value read is the CJC value */
+@@ -3295,7 +3295,7 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 
+ 				if ((i_CJCFlag == 1)
+ 					&& (i_CalibrationFlag == 0)) {
+-					//ui_InterruptChannelValue[i_Count + 3]=ui_DigitalTemperature;
++					/* ui_InterruptChannelValue[i_Count + 3]=ui_DigitalTemperature; */
+ 					s_BoardInfos[dev->minor].
+ 						ui_InterruptChannelValue
+ 						[s_BoardInfos[dev->minor].
+@@ -3307,7 +3307,7 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 		  /******************************************************/
+ 					i_APCI3200_ReadCalibrationOffsetValue
+ 						(dev, &ui_DummyValue);
+-				}	// if ((i_CJCFlag == 1) && (i_CalibrationFlag == 0))
++				}	/*  if ((i_CJCFlag == 1) && (i_CalibrationFlag == 0)) */
+ 
+ 		 /********************************************************/
+ 				/*Test if the value read is the calibration offset value */
+@@ -3315,7 +3315,7 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 
+ 				if ((i_CalibrationFlag == 1)
+ 					&& (i_CJCFlag == 0)) {
+-					//ui_InterruptChannelValue[i_Count + 1]=ui_DigitalTemperature;
++					/* ui_InterruptChannelValue[i_Count + 1]=ui_DigitalTemperature; */
+ 					s_BoardInfos[dev->minor].
+ 						ui_InterruptChannelValue
+ 						[s_BoardInfos[dev->minor].
+@@ -3328,7 +3328,7 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 					i_APCI3200_ReadCalibrationGainValue(dev,
+ 						&ui_DummyValue);
+ 
+-				}	//if ((i_CalibrationFlag == 1) && (i_CJCFlag == 0))
++				}	/* if ((i_CalibrationFlag == 1) && (i_CJCFlag == 0)) */
+ 
+ 	      /******************************************************/
+ 				/*Test if the value read is the calibration gain value */
+@@ -3336,7 +3336,7 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 
+ 				if ((i_CalibrationFlag == 2)
+ 					&& (i_CJCFlag == 0)) {
+-					//ui_InterruptChannelValue[i_Count + 2]=ui_DigitalTemperature;
++					/* ui_InterruptChannelValue[i_Count + 2]=ui_DigitalTemperature; */
+ 					s_BoardInfos[dev->minor].
+ 						ui_InterruptChannelValue
+ 						[s_BoardInfos[dev->minor].
+@@ -3349,15 +3349,15 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 
+ 					/*Test if the polarity is the same */
+ 		  /**********************************/
+-					//if(i_CJCPolarity!=i_ADDIDATAPolarity)
++					/* if(i_CJCPolarity!=i_ADDIDATAPolarity) */
+ 					if (s_BoardInfos[dev->minor].
+ 						i_CJCPolarity !=
+ 						s_BoardInfos[dev->minor].
+ 						i_ADDIDATAPolarity) {
+ 						i_ConvertCJCCalibration = 1;
+-					}	//if(i_CJCPolarity!=i_ADDIDATAPolarity)
++					}	/* if(i_CJCPolarity!=i_ADDIDATAPolarity) */
+ 					else {
+-						//if(i_CJCGain==i_ADDIDATAGain)
++						/* if(i_CJCGain==i_ADDIDATAGain) */
+ 						if (s_BoardInfos[dev->minor].
+ 							i_CJCGain ==
+ 							s_BoardInfos[dev->
+@@ -3365,12 +3365,12 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 							i_ADDIDATAGain) {
+ 							i_ConvertCJCCalibration
+ 								= 0;
+-						}	//if(i_CJCGain==i_ADDIDATAGain)
++						}	/* if(i_CJCGain==i_ADDIDATAGain) */
+ 						else {
+ 							i_ConvertCJCCalibration
+ 								= 1;
+-						}	//elseif(i_CJCGain==i_ADDIDATAGain)
+-					}	//elseif(i_CJCPolarity!=i_ADDIDATAPolarity)
++						}	/* elseif(i_CJCGain==i_ADDIDATAGain) */
++					}	/* elseif(i_CJCPolarity!=i_ADDIDATAPolarity) */
+ 					if (i_ConvertCJCCalibration == 1) {
+ 		      /****************************************************************/
+ 						/*Start the conversion of the calibration gain value for the CJC */
+@@ -3378,10 +3378,10 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 						i_APCI3200_ReadCJCCalOffset(dev,
+ 							&ui_DummyValue);
+ 
+-					}	//if(i_ConvertCJCCalibration==1)
++					}	/* if(i_ConvertCJCCalibration==1) */
+ 					else {
+-						//ui_InterruptChannelValue[i_Count + 4]=0;
+-						//ui_InterruptChannelValue[i_Count + 5]=0;
++						/* ui_InterruptChannelValue[i_Count + 4]=0; */
++						/* ui_InterruptChannelValue[i_Count + 5]=0; */
+ 						s_BoardInfos[dev->minor].
+ 							ui_InterruptChannelValue
+ 							[s_BoardInfos[dev->
+@@ -3392,8 +3392,8 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 							[s_BoardInfos[dev->
+ 								minor].i_Count +
+ 							5] = 0;
+-					}	//elseif(i_ConvertCJCCalibration==1)
+-				}	//else if ((i_CalibrationFlag == 2) && (i_CJCFlag == 0))
++					}	/* elseif(i_ConvertCJCCalibration==1) */
++				}	/* else if ((i_CalibrationFlag == 2) && (i_CJCFlag == 0)) */
+ 
+ 		 /********************************************************************/
+ 				/*Test if the value read is the calibration offset value for the CJC */
+@@ -3401,7 +3401,7 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 
+ 				if ((i_CalibrationFlag == 1)
+ 					&& (i_CJCFlag == 1)) {
+-					//ui_InterruptChannelValue[i_Count + 4]=ui_DigitalTemperature;
++					/* ui_InterruptChannelValue[i_Count + 4]=ui_DigitalTemperature; */
+ 					s_BoardInfos[dev->minor].
+ 						ui_InterruptChannelValue
+ 						[s_BoardInfos[dev->minor].
+@@ -3414,7 +3414,7 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 					i_APCI3200_ReadCJCCalGain(dev,
+ 						&ui_DummyValue);
+ 
+-				}	//if ((i_CalibrationFlag == 1) && (i_CJCFlag == 1))
++				}	/* if ((i_CalibrationFlag == 1) && (i_CJCFlag == 1)) */
+ 
+ 	      /******************************************************************/
+ 				/*Test if the value read is the calibration gain value for the CJC */
+@@ -3422,61 +3422,61 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 
+ 				if ((i_CalibrationFlag == 2)
+ 					&& (i_CJCFlag == 1)) {
+-					//ui_InterruptChannelValue[i_Count + 5]=ui_DigitalTemperature;
++					/* ui_InterruptChannelValue[i_Count + 5]=ui_DigitalTemperature; */
+ 					s_BoardInfos[dev->minor].
+ 						ui_InterruptChannelValue
+ 						[s_BoardInfos[dev->minor].
+ 						i_Count + 5] =
+ 						ui_DigitalTemperature;
+ 
+-					//if(i_ScanType==1)
++					/* if(i_ScanType==1) */
+ 					if (s_BoardInfos[dev->minor].
+ 						i_ScanType == 1) {
+ 
+-						//i_InterruptFlag=0;
++						/* i_InterruptFlag=0; */
+ 						s_BoardInfos[dev->minor].
+ 							i_InterruptFlag = 0;
+-						//i_Count=i_Count + 6;
+-						//Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+-						//s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count + 6;
++						/* i_Count=i_Count + 6; */
++						/* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
++						/* s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count + 6; */
+ 						s_BoardInfos[dev->minor].
+ 							i_Count =
+ 							s_BoardInfos[dev->
+ 							minor].i_Count + 9;
+-						//End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+-					}	//if(i_ScanType==1)
++						/* End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
++					}	/* if(i_ScanType==1) */
+ 					else {
+-						//i_Count=0;
++						/* i_Count=0; */
+ 						s_BoardInfos[dev->minor].
+ 							i_Count = 0;
+-					}	//elseif(i_ScanType==1)
++					}	/* elseif(i_ScanType==1) */
+ 
+-					//if(i_ScanType!=1)
++					/* if(i_ScanType!=1) */
+ 					if (s_BoardInfos[dev->minor].
+ 						i_ScanType != 1) {
+-						send_sig(SIGIO, devpriv->tsk_Current, 0);	// send signal to the sample
+-					}	//if(i_ScanType!=1)
++						send_sig(SIGIO, devpriv->tsk_Current, 0);	/*  send signal to the sample */
++					}	/* if(i_ScanType!=1) */
+ 					else {
+-						//if(i_ChannelCount==i_Sum)
++						/* if(i_ChannelCount==i_Sum) */
+ 						if (s_BoardInfos[dev->minor].
+ 							i_ChannelCount ==
+ 							s_BoardInfos[dev->
+ 								minor].i_Sum) {
+-							send_sig(SIGIO, devpriv->tsk_Current, 0);	// send signal to the sample
++							send_sig(SIGIO, devpriv->tsk_Current, 0);	/*  send signal to the sample */
+ 
+-						}	//if(i_ChannelCount==i_Sum)
+-					}	//else if(i_ScanType!=1)
+-				}	//if ((i_CalibrationFlag == 2) && (i_CJCFlag == 1))
++						}	/* if(i_ChannelCount==i_Sum) */
++					}	/* else if(i_ScanType!=1) */
++				}	/* if ((i_CalibrationFlag == 2) && (i_CJCFlag == 1)) */
+ 
+-			}	//else if ((ui_StatusRegister & 0x2) == 0x2)
++			}	/* else if ((ui_StatusRegister & 0x2) == 0x2) */
+ 			break;
+-		}		//switch(i_ADDIDATAType)
++		}		/* switch(i_ADDIDATAType) */
+ 		break;
+ 	case 2:
+ 	case 3:
+ 		i_APCI3200_InterruptHandleEos(dev);
+ 		break;
+-	}			//switch(i_ScanType)
++	}			/* switch(i_ScanType) */
+ 	return;
+ }
+ 
+@@ -3504,17 +3504,17 @@ int i_APCI3200_InterruptHandleEos(struct comedi_device * dev)
+ 	unsigned int ui_StatusRegister = 0;
+ 	struct comedi_subdevice *s = dev->subdevices + 0;
+ 
+-	//BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+-	//comedi_async *async = s->async;
+-	//UINT *data;
+-	//data=async->data+async->buf_int_ptr;//new samples added from here onwards
++	/* BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
++	/* comedi_async *async = s->async; */
++	/* UINT *data; */
++	/* data=async->data+async->buf_int_ptr;//new samples added from here onwards */
+ 	int n = 0, i = 0;
+-	//END JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
++	/* END JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
+ 
+   /************************************/
+ 	/*Read the interrupt status register */
+   /************************************/
+-	//ui_StatusRegister = inl(devpriv->iobase+i_Offset + 16);
++	/* ui_StatusRegister = inl(devpriv->iobase+i_Offset + 16); */
+ 	ui_StatusRegister =
+ 		inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 16);
+ 
+@@ -3526,33 +3526,33 @@ int i_APCI3200_InterruptHandleEos(struct comedi_device * dev)
+       /*************************/
+ 		/*Read the channel number */
+       /*************************/
+-		//ui_ChannelNumber = inl(devpriv->iobase+i_Offset + 24);
+-		//BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+-		//This value is not used
+-		//ui_ChannelNumber = inl(devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 24);
++		/* ui_ChannelNumber = inl(devpriv->iobase+i_Offset + 24); */
++		/* BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
++		/* This value is not used */
++		/* ui_ChannelNumber = inl(devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 24); */
+ 		s->async->events = 0;
+-		//END JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
++		/* END JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
+ 
+       /*************************************/
+ 		/*Read the digital Analog Input value */
+       /*************************************/
+ 
+-		//data[i_Count] = inl(devpriv->iobase+i_Offset + 28);
+-		//Begin JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+-		//data[s_BoardInfos [dev->minor].i_Count] = inl(devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 28);
++		/* data[i_Count] = inl(devpriv->iobase+i_Offset + 28); */
++		/* Begin JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
++		/* data[s_BoardInfos [dev->minor].i_Count] = inl(devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 28); */
+ 		s_BoardInfos[dev->minor].ui_ScanValueArray[s_BoardInfos[dev->
+ 				minor].i_Count] =
+ 			inl(devpriv->iobase +
+ 			s_BoardInfos[dev->minor].i_Offset + 28);
+-		//End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
++		/* End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
+ 
+-		//if((i_Count == (i_LastChannel-i_FirstChannel+3)))
++		/* if((i_Count == (i_LastChannel-i_FirstChannel+3))) */
+ 		if ((s_BoardInfos[dev->minor].i_Count ==
+ 				(s_BoardInfos[dev->minor].i_LastChannel -
+ 					s_BoardInfos[dev->minor].
+ 					i_FirstChannel + 3))) {
+ 
+-			//Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++			/* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ 			s_BoardInfos[dev->minor].i_Count++;
+ 
+ 			for (i = s_BoardInfos[dev->minor].i_FirstChannel;
+@@ -3582,61 +3582,61 @@ int i_APCI3200_InterruptHandleEos(struct comedi_device * dev)
+ 							* 3) + 2]);
+ 			}
+ 
+-			//End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
++			/* End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+ 
+-			//i_Count=-1;
++			/* i_Count=-1; */
+ 
+ 			s_BoardInfos[dev->minor].i_Count = -1;
+ 
+-			//async->buf_int_count+=(i_LastChannel-i_FirstChannel+4)*sizeof(unsigned int);
+-			//Begin JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+-			//async->buf_int_count+=(s_BoardInfos [dev->minor].i_LastChannel-s_BoardInfos [dev->minor].i_FirstChannel+4)*sizeof(unsigned int);
+-			//End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+-			//async->buf_int_ptr+=(i_LastChannel-i_FirstChannel+4)*sizeof(unsigned int);
+-			//Begin JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+-			//async->buf_int_ptr+=(s_BoardInfos [dev->minor].i_LastChannel-s_BoardInfos [dev->minor].i_FirstChannel+4)*sizeof(unsigned int);
+-			//comedi_eos(dev,s);
++			/* async->buf_int_count+=(i_LastChannel-i_FirstChannel+4)*sizeof(unsigned int); */
++			/* Begin JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
++			/* async->buf_int_count+=(s_BoardInfos [dev->minor].i_LastChannel-s_BoardInfos [dev->minor].i_FirstChannel+4)*sizeof(unsigned int); */
++			/* End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
++			/* async->buf_int_ptr+=(i_LastChannel-i_FirstChannel+4)*sizeof(unsigned int); */
++			/* Begin JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
++			/* async->buf_int_ptr+=(s_BoardInfos [dev->minor].i_LastChannel-s_BoardInfos [dev->minor].i_FirstChannel+4)*sizeof(unsigned int); */
++			/* comedi_eos(dev,s); */
+ 
+-			// Set the event type (Comedi Buffer End Of Scan)
++			/*  Set the event type (Comedi Buffer End Of Scan) */
+ 			s->async->events |= COMEDI_CB_EOS;
+ 
+-			// Test if enougth memory is available and allocate it for 7 values
+-			//n = comedi_buf_write_alloc(s->async, 7*sizeof(unsigned int));
++			/*  Test if enougth memory is available and allocate it for 7 values */
++			/* n = comedi_buf_write_alloc(s->async, 7*sizeof(unsigned int)); */
+ 			n = comedi_buf_write_alloc(s->async,
+ 				(7 + 12) * sizeof(unsigned int));
+ 
+-			// If not enougth memory available, event is set to Comedi Buffer Errror
++			/*  If not enougth memory available, event is set to Comedi Buffer Errror */
+ 			if (n > ((7 + 12) * sizeof(unsigned int))) {
+ 				printk("\ncomedi_buf_write_alloc n = %i", n);
+ 				s->async->events |= COMEDI_CB_ERROR;
+ 			}
+-			// Write all 7 scan values in the comedi buffer
++			/*  Write all 7 scan values in the comedi buffer */
+ 			comedi_buf_memcpy_to(s->async, 0,
+ 				(unsigned int *) s_BoardInfos[dev->minor].
+ 				ui_ScanValueArray, (7 + 12) * sizeof(unsigned int));
+ 
+-			// Update comedi buffer pinters indexes
++			/*  Update comedi buffer pinters indexes */
+ 			comedi_buf_write_free(s->async,
+ 				(7 + 12) * sizeof(unsigned int));
+ 
+-			// Send events
++			/*  Send events */
+ 			comedi_event(dev, s);
+-			//End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+-
+-			//BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+-			//
+-			//if (s->async->buf_int_ptr>=s->async->data_len) //  for buffer rool over
+-			//  {
+-			//    /* buffer rollover */
+-			//    s->async->buf_int_ptr=0;
+-			//    comedi_eobuf(dev,s);
+-			//  }
+-			//End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
++			/* End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
++
++			/* BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
++			/*  */
++			/* if (s->async->buf_int_ptr>=s->async->data_len) //  for buffer rool over */
++			/*   { */
++			/*     /* buffer rollover */ */
++			/*     s->async->buf_int_ptr=0; */
++			/*     comedi_eobuf(dev,s); */
++			/*   } */
++			/* End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
+ 		}
+-		//i_Count++;
++		/* i_Count++; */
+ 		s_BoardInfos[dev->minor].i_Count++;
+ 	}
+-	//i_InterruptFlag=0;
++	/* i_InterruptFlag=0; */
+ 	s_BoardInfos[dev->minor].i_InterruptFlag = 0;
+ 	return 0;
+ }

commit b58d9b17db71e5d6f7531e9a922f37aa9aae5bdb
+Author: Bill Pemberton 
+Date:   Fri Mar 27 11:30:01 2009 -0400
+
+    Staging: comedi: remove C99 comments in hwdrv_apci1564.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+index 13c5c6faf127..304079bbb80a 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+@@ -55,7 +55,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ #include 
+ #include "hwdrv_apci1564.h"
+ 
+-//Global variables
++/* Global variables */
+ unsigned int ui_InterruptStatus_1564 = 0;
+ unsigned int ui_InterruptData, ui_Type;
+ 
+@@ -106,13 +106,13 @@ int i_APCI1564_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subd
+ 			outl(0x4,
+ 				devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+ 				APCI1564_DIGITAL_IP_IRQ);
+-		}		// if  (data[1] == ADDIDATA_OR)
++		}		/*  if  (data[1] == ADDIDATA_OR) */
+ 		else {
+ 			outl(0x6,
+ 				devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+ 				APCI1564_DIGITAL_IP_IRQ);
+-		}		// else if  (data[1] == ADDIDATA_OR)
+-	}			// if  (data[0] == ADDIDATA_ENABLE)
++		}		/*  else if  (data[1] == ADDIDATA_OR) */
++	}			/*  if  (data[0] == ADDIDATA_ENABLE) */
+ 	else {
+ 		outl(0x0,
+ 			devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+@@ -123,7 +123,7 @@ int i_APCI1564_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subd
+ 		outl(0x0,
+ 			devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+ 			APCI1564_DIGITAL_IP_IRQ);
+-	}			// else if  (data[0] == ADDIDATA_ENABLE)
++	}			/*  else if  (data[0] == ADDIDATA_ENABLE) */
+ 
+ 	return insn->n;
+ }
+@@ -157,14 +157,16 @@ int i_APCI1564_Read1DigitalInput(struct comedi_device * dev, struct comedi_subde
+ 	if (ui_Channel >= 0 && ui_Channel <= 31) {
+ 		ui_TmpValue =
+ 			(unsigned int) inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP);
+-		//  since only 1 channel reqd  to bring it to last bit it is rotated
+-		//  8 +(chan - 1) times then ANDed with 1 for last bit.
++/*
++* since only 1 channel reqd to bring it to last bit it is rotated 8
++* +(chan - 1) times then ANDed with 1 for last bit.
++*/
+ 		*data = (ui_TmpValue >> ui_Channel) & 0x1;
+-	}			// if  (ui_Channel >= 0 && ui_Channel <=31)
++	}			/*  if  (ui_Channel >= 0 && ui_Channel <=31) */
+ 	else {
+ 		comedi_error(dev, "Not a valid channel number !!! \n");
+-		return -EINVAL;	// "sorry channel spec wrong "
+-	}			//else if  (ui_Channel >= 0 && ui_Channel <=31)
++		return -EINVAL;	/*  "sorry channel spec wrong " */
++	}			/* else if  (ui_Channel >= 0 && ui_Channel <=31) */
+ 	return insn->n;
+ }
+ 
+@@ -218,15 +220,15 @@ int i_APCI1564_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ 			break;
+ 		default:
+ 			comedi_error(dev, "Not a valid Channel number !!!\n");
+-			return -EINVAL;	// "sorry channel spec wrong "
++			return -EINVAL;	/*  "sorry channel spec wrong " */
+ 			break;
+-		}		// switch  (ui_NoOfChannels)
+-	}			// if  (data[1]==0)
++		}		/*  switch  (ui_NoOfChannels) */
++	}			/*  if  (data[1]==0) */
+ 	else {
+ 		if (data[1] == 1) {
+ 			*data = ui_InterruptStatus_1564;
+-		}		// if  (data[1]==1)
+-	}			// else if  (data[1]==0)
++		}		/*  if  (data[1]==1) */
++	}			/*  else if  (data[1]==0) */
+ 	return insn->n;
+ }
+ 
+@@ -264,25 +266,25 @@ int i_APCI1564_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ 		comedi_error(dev,
+ 			"Not a valid Data !!! ,Data should be 1 or 0\n");
+ 		return -EINVAL;
+-	}			// if  ((data[0]!=0) && (data[0]!=1))
++	}			/*  if  ((data[0]!=0) && (data[0]!=1)) */
+ 	if (data[0]) {
+ 		devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
+-	}			// if  (data[0])
++	}			/*  if  (data[0]) */
+ 	else {
+ 		devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
+-	}			// else if  (data[0])
++	}			/*  else if  (data[0]) */
+ 	if (data[1] == ADDIDATA_ENABLE) {
+ 		ul_Command = ul_Command | 0x1;
+-	}			// if  (data[1] == ADDIDATA_ENABLE)
++	}			/*  if  (data[1] == ADDIDATA_ENABLE) */
+ 	else {
+ 		ul_Command = ul_Command & 0xFFFFFFFE;
+-	}			// else if  (data[1] == ADDIDATA_ENABLE)
++	}			/*  else if  (data[1] == ADDIDATA_ENABLE) */
+ 	if (data[2] == ADDIDATA_ENABLE) {
+ 		ul_Command = ul_Command | 0x2;
+-	}			// if  (data[2] == ADDIDATA_ENABLE)
++	}			/*  if  (data[2] == ADDIDATA_ENABLE) */
+ 	else {
+ 		ul_Command = ul_Command & 0xFFFFFFFD;
+-	}			// else if  (data[2] == ADDIDATA_ENABLE)
++	}			/*  else if  (data[2] == ADDIDATA_ENABLE) */
+ 	outl(ul_Command,
+ 		devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
+ 		APCI1564_DIGITAL_OP_INTERRUPT);
+@@ -323,17 +325,17 @@ int i_APCI1564_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 		ui_Temp =
+ 			inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
+ 			APCI1564_DIGITAL_OP_RW);
+-	}			// if  (devpriv->b_OutputMemoryStatus )
++	}			/*  if  (devpriv->b_OutputMemoryStatus ) */
+ 	else {
+ 		ui_Temp = 0;
+-	}			// else if  (devpriv->b_OutputMemoryStatus )
++	}			/*  else if  (devpriv->b_OutputMemoryStatus ) */
+ 	if (data[3] == 0) {
+ 		if (data[1] == 0) {
+ 			data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
+ 			outl(data[0],
+ 				devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
+ 				APCI1564_DIGITAL_OP_RW);
+-		}		// if  (data[1]==0)
++		}		/*  if  (data[1]==0) */
+ 		else {
+ 			if (data[1] == 1) {
+ 				switch (ui_NoOfChannel) {
+@@ -362,18 +364,18 @@ int i_APCI1564_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 					break;
+ 				default:
+ 					comedi_error(dev, " chan spec wrong");
+-					return -EINVAL;	// "sorry channel spec wrong "
+-				}	// switch (ui_NoOfChannels)
++					return -EINVAL;	/*  "sorry channel spec wrong " */
++				}	/*  switch (ui_NoOfChannels) */
+ 				outl(data[0],
+ 					devpriv->i_IobaseAmcc +
+ 					APCI1564_DIGITAL_OP +
+ 					APCI1564_DIGITAL_OP_RW);
+-			}	// if  (data[1]==1)
++			}	/*  if  (data[1]==1) */
+ 			else {
+ 				printk("\nSpecified channel not supported\n");
+-			}	// else if  (data[1]==1)
+-		}		// else if (data[1]==0)
+-	}			//if(data[3]==0)
++			}	/*  else if  (data[1]==1) */
++		}		/*  else if (data[1]==0) */
++	}			/* if(data[3]==0) */
+ 	else {
+ 		if (data[3] == 1) {
+ 			if (data[1] == 0) {
+@@ -389,7 +391,7 @@ int i_APCI1564_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 					devpriv->i_IobaseAmcc +
+ 					APCI1564_DIGITAL_OP +
+ 					APCI1564_DIGITAL_OP_RW);
+-			}	// if  (data[1]==0)
++			}	/*  if  (data[1]==0) */
+ 			else {
+ 				if (data[1] == 1) {
+ 					switch (ui_NoOfChannel) {
+@@ -447,23 +449,23 @@ int i_APCI1564_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 					default:
+ 						comedi_error(dev,
+ 							" chan spec wrong");
+-						return -EINVAL;	// "sorry channel spec wrong "
+-					}	//switch(ui_NoOfChannels)
++						return -EINVAL;	/*  "sorry channel spec wrong " */
++					}	/* switch(ui_NoOfChannels) */
+ 					outl(data[0],
+ 						devpriv->i_IobaseAmcc +
+ 						APCI1564_DIGITAL_OP +
+ 						APCI1564_DIGITAL_OP_RW);
+-				}	// if  (data[1]==1)
++				}	/*  if  (data[1]==1) */
+ 				else {
+ 					printk("\nSpecified channel not supported\n");
+-				}	// else if  (data[1]==1)
+-			}	// else if  (data[1]==0)
+-		}		// if  (data[3]==1);
++				}	/*  else if  (data[1]==1) */
++			}	/*  else if  (data[1]==0) */
++		}		/*  if  (data[3]==1); */
+ 		else {
+ 			printk("\nSpecified functionality does not exist\n");
+ 			return -EINVAL;
+-		}		// else if (data[3]==1)
+-	}			// else if (data[3]==0)
++		}		/*  else if (data[3]==1) */
++	}			/*  else if (data[3]==0) */
+ 	return insn->n;
+ }
+ 
+@@ -498,7 +500,7 @@ int i_APCI1564_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ 		APCI1564_DIGITAL_OP_RW);
+ 	if (ui_Temp == 0) {
+ 		*data = (*data >> ui_NoOfChannel) & 0x1;
+-	}			// if  (ui_Temp==0)
++	}			/*  if  (ui_Temp==0) */
+ 	else {
+ 		if (ui_Temp == 1) {
+ 			switch (ui_NoOfChannel) {
+@@ -523,14 +525,14 @@ int i_APCI1564_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ 
+ 			default:
+ 				comedi_error(dev, " chan spec wrong");
+-				return -EINVAL;	// "sorry channel spec wrong "
++				return -EINVAL;	/*  "sorry channel spec wrong " */
+ 				break;
+-			}	// switch(ui_NoOfChannels)
+-		}		// if  (ui_Temp==1)
++			}	/*  switch(ui_NoOfChannels) */
++		}		/*  if  (ui_Temp==1) */
+ 		else {
+ 			printk("\nSpecified channel not supported \n");
+-		}		// else if (ui_Temp==1)
+-	}			// else if  (ui_Temp==0)
++		}		/*  else if (ui_Temp==1) */
++	}			/*  else if  (ui_Temp==0) */
+ 	return insn->n;
+ }
+ 
+@@ -572,26 +574,26 @@ int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ 	if (data[0] == ADDIDATA_WATCHDOG) {
+ 		devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG;
+ 
+-		//Disable the watchdog
++		/* Disable the watchdog */
+ 		outl(0x0,
+ 			devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG +
+ 			APCI1564_TCW_PROG);
+-		//Loading the Reload value
++		/* Loading the Reload value */
+ 		outl(data[3],
+ 			devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG +
+ 			APCI1564_TCW_RELOAD_VALUE);
+-	}			// if  (data[0]==ADDIDATA_WATCHDOG)
++	}			/*  if  (data[0]==ADDIDATA_WATCHDOG) */
+ 	else if (data[0] == ADDIDATA_TIMER) {
+-		//First Stop The Timer
++		/* First Stop The Timer */
+ 		ul_Command1 =
+ 			inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
+ 			APCI1564_TCW_PROG);
+ 		ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
+-		outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG);	//Stop The Timer
++		outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG);	/* Stop The Timer */
+ 
+ 		devpriv->b_TimerSelectMode = ADDIDATA_TIMER;
+ 		if (data[1] == 1) {
+-			outl(0x02, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG);	//Enable TIMER int & DISABLE ALL THE OTHER int SOURCES
++			outl(0x02, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG);	/* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */
+ 			outl(0x0,
+ 				devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+ 				APCI1564_DIGITAL_IP_IRQ);
+@@ -614,18 +616,18 @@ int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ 			outl(0x0,
+ 				devpriv->iobase + APCI1564_COUNTER4 +
+ 				APCI1564_TCW_IRQ);
+-		}		// if  (data[1]==1)
++		}		/*  if  (data[1]==1) */
+ 		else {
+-			outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG);	//disable Timer interrupt
+-		}		// else if  (data[1]==1)
++			outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG);	/* disable Timer interrupt */
++		}		/*  else if  (data[1]==1) */
+ 
+-		// Loading Timebase
++		/*  Loading Timebase */
+ 
+ 		outl(data[2],
+ 			devpriv->i_IobaseAmcc + APCI1564_TIMER +
+ 			APCI1564_TCW_TIMEBASE);
+ 
+-		//Loading the Reload value
++		/* Loading the Reload value */
+ 		outl(data[3],
+ 			devpriv->i_IobaseAmcc + APCI1564_TIMER +
+ 			APCI1564_TCW_RELOAD_VALUE);
+@@ -635,18 +637,18 @@ int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ 			APCI1564_TCW_PROG);
+ 		ul_Command1 =
+ 			(ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL;
+-		outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG);	//mode 2
+-	}			// else if  (data[0]==ADDIDATA_TIMER)
++		outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG);	/* mode 2 */
++	}			/*  else if  (data[0]==ADDIDATA_TIMER) */
+ 	else if (data[0] == ADDIDATA_COUNTER) {
+ 		devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
+ 		devpriv->b_ModeSelectRegister = data[5];
+ 
+-		//First Stop The Counter
++		/* First Stop The Counter */
+ 		ul_Command1 =
+ 			inl(devpriv->iobase + ((data[5] - 1) * 0x20) +
+ 			APCI1564_TCW_PROG);
+ 		ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
+-		outl(ul_Command1, devpriv->iobase + ((data[5] - 1) * 0x20) + APCI1564_TCW_PROG);	//Stop The Timer
++		outl(ul_Command1, devpriv->iobase + ((data[5] - 1) * 0x20) + APCI1564_TCW_PROG);	/* Stop The Timer */
+ 
+       /************************/
+ 		/* Set the reload value */
+@@ -671,7 +673,7 @@ int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ 			devpriv->iobase + ((data[5] - 1) * 0x20) +
+ 			APCI1564_TCW_PROG);
+ 
+-		// Enable or Disable Interrupt
++		/*  Enable or Disable Interrupt */
+ 		ul_Command1 = (ul_Command1 & 0xFFFFF9FD) | (data[1] << 1);
+ 		outl(ul_Command1,
+ 			devpriv->iobase + ((data[5] - 1) * 0x20) +
+@@ -684,10 +686,10 @@ int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ 		outl(ul_Command1,
+ 			devpriv->iobase + ((data[5] - 1) * 0x20) +
+ 			APCI1564_TCW_PROG);
+-	}			// else if  (data[0]==ADDIDATA_COUNTER)
++	}			/*  else if  (data[0]==ADDIDATA_COUNTER) */
+ 	else {
+ 		printk(" Invalid subdevice.");
+-	}			// else if  (data[0]==ADDIDATA_WATCHDOG)
++	}			/*  else if  (data[0]==ADDIDATA_WATCHDOG) */
+ 
+ 	return insn->n;
+ }
+@@ -724,16 +726,16 @@ int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ 	unsigned int ul_Command1 = 0;
+ 	if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+ 		switch (data[1]) {
+-		case 0:	//stop the watchdog
+-			outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG + APCI1564_TCW_PROG);	//disable the watchdog
++		case 0:	/* stop the watchdog */
++			outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG + APCI1564_TCW_PROG);	/* disable the watchdog */
+ 			break;
+-		case 1:	//start the watchdog
++		case 1:	/* start the watchdog */
+ 			outl(0x0001,
+ 				devpriv->i_IobaseAmcc +
+ 				APCI1564_DIGITAL_OP_WATCHDOG +
+ 				APCI1564_TCW_PROG);
+ 			break;
+-		case 2:	//Software trigger
++		case 2:	/* Software trigger */
+ 			outl(0x0201,
+ 				devpriv->i_IobaseAmcc +
+ 				APCI1564_DIGITAL_OP_WATCHDOG +
+@@ -742,8 +744,8 @@ int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ 		default:
+ 			printk("\nSpecified functionality does not exist\n");
+ 			return -EINVAL;
+-		}		// switch (data[1])
+-	}			// if  (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG)
++		}		/*  switch (data[1]) */
++	}			/*  if  (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) */
+ 	if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
+ 		if (data[1] == 1) {
+ 			ul_Command1 =
+@@ -751,13 +753,13 @@ int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ 				APCI1564_TCW_PROG);
+ 			ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
+ 
+-			//Enable the Timer
++			/* Enable the Timer */
+ 			outl(ul_Command1,
+ 				devpriv->i_IobaseAmcc + APCI1564_TIMER +
+ 				APCI1564_TCW_PROG);
+-		}		// if  (data[1]==1)
++		}		/*  if  (data[1]==1) */
+ 		else if (data[1] == 0) {
+-			//Stop The Timer
++			/* Stop The Timer */
+ 
+ 			ul_Command1 =
+ 				inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
+@@ -766,29 +768,29 @@ int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ 			outl(ul_Command1,
+ 				devpriv->i_IobaseAmcc + APCI1564_TIMER +
+ 				APCI1564_TCW_PROG);
+-		}		// else if(data[1]==0)
+-	}			// if  (devpriv->b_TimerSelectMode==ADDIDATA_TIMER)
++		}		/*  else if(data[1]==0) */
++	}			/*  if  (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */
+ 	if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) {
+ 		ul_Command1 =
+ 			inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister -
+ 					1) * 0x20) + APCI1564_TCW_PROG);
+ 		if (data[1] == 1) {
+-			//Start the Counter subdevice
++			/* Start the Counter subdevice */
+ 			ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
+-		}		// if  (data[1] == 1)
++		}		/*  if  (data[1] == 1) */
+ 		else if (data[1] == 0) {
+-			// Stops the Counter subdevice
++			/*  Stops the Counter subdevice */
+ 			ul_Command1 = 0;
+ 
+-		}		// else if  (data[1] == 0)
++		}		/*  else if  (data[1] == 0) */
+ 		else if (data[1] == 2) {
+-			// Clears the Counter subdevice
++			/*  Clears the Counter subdevice */
+ 			ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x400;
+-		}		// else if  (data[1] == 3)
++		}		/*  else if  (data[1] == 3) */
+ 		outl(ul_Command1,
+ 			devpriv->iobase + ((devpriv->b_ModeSelectRegister -
+ 					1) * 0x20) + APCI1564_TCW_PROG);
+-	}			// if (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER)
++	}			/*  if (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER) */
+ 	return insn->n;
+ }
+ 
+@@ -819,7 +821,7 @@ int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device * dev,
+ 	unsigned int ul_Command1 = 0;
+ 
+ 	if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+-		// Stores the status of the Watchdog
++		/*  Stores the status of the Watchdog */
+ 		data[0] =
+ 			inl(devpriv->i_IobaseAmcc +
+ 			APCI1564_DIGITAL_OP_WATCHDOG +
+@@ -827,18 +829,18 @@ int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device * dev,
+ 		data[1] =
+ 			inl(devpriv->i_IobaseAmcc +
+ 			APCI1564_DIGITAL_OP_WATCHDOG);
+-	}			// if  (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG)
++	}			/*  if  (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) */
+ 	else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
+-		// Stores the status of the Timer
++		/*  Stores the status of the Timer */
+ 		data[0] =
+ 			inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
+ 			APCI1564_TCW_TRIG_STATUS) & 0x1;
+ 
+-		// Stores the Actual value of the Timer
++		/*  Stores the Actual value of the Timer */
+ 		data[1] = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER);
+-	}			// else if  (devpriv->b_TimerSelectMode==ADDIDATA_TIMER)
++	}			/*  else if  (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */
+ 	else if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) {
+-		// Read the Counter Actual Value.
++		/*  Read the Counter Actual Value. */
+ 		data[0] =
+ 			inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister -
+ 					1) * 0x20) +
+@@ -866,12 +868,12 @@ int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device * dev,
+ 		/* Get the overflow status */
+       /***************************/
+ 		data[4] = (unsigned char) ((ul_Command1 >> 0) & 1);
+-	}			// else  if  (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER)
++	}			/*  else  if  (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER) */
+ 	else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER)
+ 		&& (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG)
+ 		&& (devpriv->b_TimerSelectMode != ADDIDATA_COUNTER)) {
+ 		printk("\n Invalid Subdevice !!!\n");
+-	}			// else if ((devpriv->b_TimerSelectMode!=ADDIDATA_TIMER) && (devpriv->b_TimerSelectMode!=ADDIDATA_WATCHDOG)&& (devpriv->b_TimerSelectMode!=ADDIDATA_COUNTER))
++	}			/*  else if ((devpriv->b_TimerSelectMode!=ADDIDATA_TIMER) && (devpriv->b_TimerSelectMode!=ADDIDATA_WATCHDOG)&& (devpriv->b_TimerSelectMode!=ADDIDATA_COUNTER)) */
+ 	return insn->n;
+ }
+ 
+@@ -941,7 +943,7 @@ static void v_APCI1564_Interrupt(int irq, void *d)
+ 	if (ui_DI == 0 && ui_DO == 0 && ui_Timer == 0 && ui_C1 == 0
+ 		&& ui_C2 == 0 && ui_C3 == 0 && ui_C4 == 0) {
+ 		printk("\nInterrupt from unknown source\n");
+-	}			// if(ui_DI==0 && ui_DO==0 && ui_Timer==0 && ui_C1==0 && ui_C2==0 && ui_C3==0 && ui_C4==0)
++	}			/*  if(ui_DI==0 && ui_DO==0 && ui_Timer==0 && ui_C1==0 && ui_C2==0 && ui_C3==0 && ui_C4==0) */
+ 
+ 	if (ui_DI == 1) {
+ 		ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+@@ -953,28 +955,28 @@ static void v_APCI1564_Interrupt(int irq, void *d)
+ 			inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+ 			APCI1564_DIGITAL_IP_INTERRUPT_STATUS);
+ 		ui_InterruptStatus_1564 = ui_InterruptStatus_1564 & 0X000FFFF0;
+-		send_sig(SIGIO, devpriv->tsk_Current, 0);	// send signal to the sample
+-		outl(ui_DI, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + APCI1564_DIGITAL_IP_IRQ);	//enable the interrupt
++		send_sig(SIGIO, devpriv->tsk_Current, 0);	/*  send signal to the sample */
++		outl(ui_DI, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + APCI1564_DIGITAL_IP_IRQ);	/* enable the interrupt */
+ 		return;
+ 	}
+ 
+ 	if (ui_DO == 1) {
+-		// Check for Digital Output interrupt Type - 1: Vcc interrupt 2: CC interrupt.
++		/*  Check for Digital Output interrupt Type - 1: Vcc interrupt 2: CC interrupt. */
+ 		ui_Type =
+ 			inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
+ 			APCI1564_DIGITAL_OP_INTERRUPT_STATUS) & 0x3;
+-		//Disable the  Interrupt
++		/* Disable the  Interrupt */
+ 		outl(0x0,
+ 			devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
+ 			APCI1564_DIGITAL_OP_INTERRUPT);
+ 
+-		//Sends signal to user space
++		/* Sends signal to user space */
+ 		send_sig(SIGIO, devpriv->tsk_Current, 0);
+ 
+-	}			// if  (ui_DO)
++	}			/*  if  (ui_DO) */
+ 
+ 	if ((ui_Timer == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_TIMER)) {
+-		// Disable Timer Interrupt
++		/*  Disable Timer Interrupt */
+ 		ul_Command2 =
+ 			inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
+ 			APCI1564_TCW_PROG);
+@@ -982,18 +984,18 @@ static void v_APCI1564_Interrupt(int irq, void *d)
+ 			devpriv->i_IobaseAmcc + APCI1564_TIMER +
+ 			APCI1564_TCW_PROG);
+ 
+-		//Send a signal to from kernel to user space
++		/* Send a signal to from kernel to user space */
+ 		send_sig(SIGIO, devpriv->tsk_Current, 0);
+ 
+-		// Enable Timer Interrupt
++		/*  Enable Timer Interrupt */
+ 
+ 		outl(ul_Command2,
+ 			devpriv->i_IobaseAmcc + APCI1564_TIMER +
+ 			APCI1564_TCW_PROG);
+-	}			// if  ((ui_Timer == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_TIMER))
++	}			/*  if  ((ui_Timer == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_TIMER)) */
+ 
+ 	if ((ui_C1 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) {
+-		// Disable Counter Interrupt
++		/*  Disable Counter Interrupt */
+ 		ul_Command2 =
+ 			inl(devpriv->iobase + APCI1564_COUNTER1 +
+ 			APCI1564_TCW_PROG);
+@@ -1001,17 +1003,17 @@ static void v_APCI1564_Interrupt(int irq, void *d)
+ 			devpriv->iobase + APCI1564_COUNTER1 +
+ 			APCI1564_TCW_PROG);
+ 
+-		//Send a signal to from kernel to user space
++		/* Send a signal to from kernel to user space */
+ 		send_sig(SIGIO, devpriv->tsk_Current, 0);
+ 
+-		// Enable Counter Interrupt
++		/*  Enable Counter Interrupt */
+ 		outl(ul_Command2,
+ 			devpriv->iobase + APCI1564_COUNTER1 +
+ 			APCI1564_TCW_PROG);
+-	}			// if  ((ui_C1 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER))
++	}			/*  if  ((ui_C1 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) */
+ 
+ 	if ((ui_C2 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) {
+-		// Disable Counter Interrupt
++		/*  Disable Counter Interrupt */
+ 		ul_Command2 =
+ 			inl(devpriv->iobase + APCI1564_COUNTER2 +
+ 			APCI1564_TCW_PROG);
+@@ -1019,17 +1021,17 @@ static void v_APCI1564_Interrupt(int irq, void *d)
+ 			devpriv->iobase + APCI1564_COUNTER2 +
+ 			APCI1564_TCW_PROG);
+ 
+-		//Send a signal to from kernel to user space
++		/* Send a signal to from kernel to user space */
+ 		send_sig(SIGIO, devpriv->tsk_Current, 0);
+ 
+-		// Enable Counter Interrupt
++		/*  Enable Counter Interrupt */
+ 		outl(ul_Command2,
+ 			devpriv->iobase + APCI1564_COUNTER2 +
+ 			APCI1564_TCW_PROG);
+-	}			// if  ((ui_C2 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER))
++	}			/*  if  ((ui_C2 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER)) */
+ 
+ 	if ((ui_C3 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) {
+-		// Disable Counter Interrupt
++		/*  Disable Counter Interrupt */
+ 		ul_Command2 =
+ 			inl(devpriv->iobase + APCI1564_COUNTER3 +
+ 			APCI1564_TCW_PROG);
+@@ -1037,17 +1039,17 @@ static void v_APCI1564_Interrupt(int irq, void *d)
+ 			devpriv->iobase + APCI1564_COUNTER3 +
+ 			APCI1564_TCW_PROG);
+ 
+-		//Send a signal to from kernel to user space
++		/* Send a signal to from kernel to user space */
+ 		send_sig(SIGIO, devpriv->tsk_Current, 0);
+ 
+-		// Enable Counter Interrupt
++		/*  Enable Counter Interrupt */
+ 		outl(ul_Command2,
+ 			devpriv->iobase + APCI1564_COUNTER3 +
+ 			APCI1564_TCW_PROG);
+-	}			// if ((ui_C3 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER))
++	}			/*  if ((ui_C3 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER)) */
+ 
+ 	if ((ui_C4 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) {
+-		// Disable Counter Interrupt
++		/*  Disable Counter Interrupt */
+ 		ul_Command2 =
+ 			inl(devpriv->iobase + APCI1564_COUNTER4 +
+ 			APCI1564_TCW_PROG);
+@@ -1055,14 +1057,14 @@ static void v_APCI1564_Interrupt(int irq, void *d)
+ 			devpriv->iobase + APCI1564_COUNTER4 +
+ 			APCI1564_TCW_PROG);
+ 
+-		//Send a signal to from kernel to user space
++		/* Send a signal to from kernel to user space */
+ 		send_sig(SIGIO, devpriv->tsk_Current, 0);
+ 
+-		// Enable Counter Interrupt
++		/*  Enable Counter Interrupt */
+ 		outl(ul_Command2,
+ 			devpriv->iobase + APCI1564_COUNTER4 +
+ 			APCI1564_TCW_PROG);
+-	}			// if ((ui_C4 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER))
++	}			/*  if ((ui_C4 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER)) */
+ 	return;
+ }
+ 
+@@ -1083,14 +1085,14 @@ static void v_APCI1564_Interrupt(int irq, void *d)
+ 
+ int i_APCI1564_Reset(struct comedi_device * dev)
+ {
+-	outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_IRQ);	//disable the interrupts
+-	inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_STATUS);	//Reset the interrupt status register
+-	outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_MODE1);	//Disable the and/or interrupt
++	outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_IRQ);	/* disable the interrupts */
++	inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_STATUS);	/* Reset the interrupt status register */
++	outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_MODE1);	/* Disable the and/or interrupt */
+ 	outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_MODE2);
+ 	devpriv->b_DigitalOutputRegister = 0;
+ 	ui_Type = 0;
+-	outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP);	//Resets the output channels
+-	outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_INTERRUPT);	//Disables the interrupt.
++	outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP);	/* Resets the output channels */
++	outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_INTERRUPT);	/* Disables the interrupt. */
+ 	outl(0x0,
+ 		devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG +
+ 		APCI1564_TCW_RELOAD_VALUE);

commit 0110c4432aab7f119d38d1389964e51685721ed4
+Author: Bill Pemberton 
+Date:   Fri Mar 27 11:29:56 2009 -0400
+
+    Staging: comedi: remove C99 comments in APCI1710_Pwm.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+index 2ebb121c2d22..976fe5863e49 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+@@ -79,29 +79,29 @@ int i_APCI1710_InsnConfigPWM(struct comedi_device * dev, struct comedi_subdevice
+ 
+ 	switch (b_ConfigType) {
+ 	case APCI1710_PWM_INIT:
+-		i_ReturnValue = i_APCI1710_InitPWM(dev, (unsigned char) CR_AREF(insn->chanspec),	//  b_ModulNbr
+-			(unsigned char) data[0],	//b_PWM
+-			(unsigned char) data[1],	// b_ClockSelection
+-			(unsigned char) data[2],	// b_TimingUnit
+-			(unsigned int) data[3],	//ul_LowTiming
+-			(unsigned int) data[4],	//ul_HighTiming
+-			(unsigned int *) & data[0],	//pul_RealLowTiming
+-			(unsigned int *) & data[1]	//pul_RealHighTiming
++		i_ReturnValue = i_APCI1710_InitPWM(dev, (unsigned char) CR_AREF(insn->chanspec),	/*   b_ModulNbr */
++			(unsigned char) data[0],	/* b_PWM */
++			(unsigned char) data[1],	/*  b_ClockSelection */
++			(unsigned char) data[2],	/*  b_TimingUnit */
++			(unsigned int) data[3],	/* ul_LowTiming */
++			(unsigned int) data[4],	/* ul_HighTiming */
++			(unsigned int *) & data[0],	/* pul_RealLowTiming */
++			(unsigned int *) & data[1]	/* pul_RealHighTiming */
+ 			);
+ 		break;
+ 
+ 	case APCI1710_PWM_GETINITDATA:
+-		i_ReturnValue = i_APCI1710_GetPWMInitialisation(dev, (unsigned char) CR_AREF(insn->chanspec),	// b_ModulNbr
+-			(unsigned char) data[0],	//b_PWM
+-			(unsigned char *) & data[0],	//pb_TimingUnit
+-			(unsigned int *) & data[1],	//pul_LowTiming
+-			(unsigned int *) & data[2],	//pul_HighTiming
+-			(unsigned char *) & data[3],	// pb_StartLevel
+-			(unsigned char *) & data[4],	// pb_StopMode
+-			(unsigned char *) & data[5],	// pb_StopLevel
+-			(unsigned char *) & data[6],	// pb_ExternGate
+-			(unsigned char *) & data[7],	// pb_InterruptEnable
+-			(unsigned char *) & data[8]	// pb_Enable
++		i_ReturnValue = i_APCI1710_GetPWMInitialisation(dev, (unsigned char) CR_AREF(insn->chanspec),	/*  b_ModulNbr */
++			(unsigned char) data[0],	/* b_PWM */
++			(unsigned char *) & data[0],	/* pb_TimingUnit */
++			(unsigned int *) & data[1],	/* pul_LowTiming */
++			(unsigned int *) & data[2],	/* pul_HighTiming */
++			(unsigned char *) & data[3],	/*  pb_StartLevel */
++			(unsigned char *) & data[4],	/*  pb_StopMode */
++			(unsigned char *) & data[5],	/*  pb_StopLevel */
++			(unsigned char *) & data[6],	/*  pb_ExternGate */
++			(unsigned char *) & data[7],	/*  pb_InterruptEnable */
++			(unsigned char *) & data[8]	/*  pb_Enable */
+ 			);
+ 		break;
+ 
+@@ -200,33 +200,33 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 	/**************************/
+ 
+ 	if (b_ModulNbr < 4) {
+-	   /***************/
++		/***************/
+ 		/* Test if PWM */
+-	   /***************/
++		/***************/
+ 
+ 		if ((devpriv->s_BoardInfos.
+ 				dw_MolduleConfiguration[b_ModulNbr] &
+ 				0xFFFF0000UL) == APCI1710_PWM) {
+-	      /**************************/
++			/**************************/
+ 			/* Test the PWM selection */
+-	      /**************************/
++			/**************************/
+ 
+ 			if (b_PWM <= 1) {
+-		 /******************/
++				/******************/
+ 				/* Test the clock */
+-		 /******************/
++				/******************/
+ 
+ 				if ((b_ClockSelection == APCI1710_30MHZ) ||
+ 					(b_ClockSelection == APCI1710_33MHZ) ||
+ 					(b_ClockSelection == APCI1710_40MHZ)) {
+-		    /************************/
++					/************************/
+ 					/* Test the timing unit */
+-		    /************************/
++					/************************/
+ 
+ 					if (b_TimingUnit <= 4) {
+-		       /*********************************/
++						/*********************************/
+ 						/* Test the low timing selection */
+-		       /*********************************/
++						/*********************************/
+ 
+ 						if (((b_ClockSelection ==
+ 									APCI1710_30MHZ)
+@@ -361,34 +361,34 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 								&& (ul_LowTiming
+ 									<=
+ 									7UL))) {
+-			  /**********************************/
++							/**********************************/
+ 							/* Test the High timing selection */
+-			  /**********************************/
++							/**********************************/
+ 
+ 							if (((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 266) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230650UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 9UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 242) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691043UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 520UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 8UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 200) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496729UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 7UL))) {
+-			     /**************************/
++								/**************************/
+ 								/* Test the board version */
+-			     /**************************/
++								/**************************/
+ 
+ 								if (((b_ClockSelection == APCI1710_40MHZ) && (devpriv->s_BoardInfos.b_BoardVersion > 0)) || (b_ClockSelection != APCI1710_40MHZ)) {
+ 
+-				/************************************/
++									/************************************/
+ 									/* Calculate the low division fator */
+-				/************************************/
++									/************************************/
+ 
+ 									fpu_begin
+ 										();
+ 
+ 									switch (b_TimingUnit) {
+-				   /******/
++										/******/
+ 										/* ns */
+-				   /******/
++										/******/
+ 
+ 									case 0:
+ 
+-					   /******************/
++										/******************/
+ 										/* Timer 0 factor */
+-					   /******************/
++										/******************/
+ 
+ 										ul_LowTimerValue
+ 											=
+@@ -397,9 +397,9 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 											*
+ 											(0.00025 * b_ClockSelection));
+ 
+-					   /*******************/
++										/*******************/
+ 										/* Round the value */
+-					   /*******************/
++										/*******************/
+ 
+ 										if ((double)((double)ul_LowTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+ 											ul_LowTimerValue
+@@ -409,9 +409,9 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 												1;
+ 										}
+ 
+-					   /*****************************/
++										/*****************************/
+ 										/* Calculate the real timing */
+-					   /*****************************/
++										/*****************************/
+ 
+ 										*pul_RealLowTiming
+ 											=
+@@ -461,15 +461,15 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 
+ 										break;
+ 
+-				   /******/
++										/******/
+ 										/* æs */
+-				   /******/
++										/******/
+ 
+ 									case 1:
+ 
+-					   /******************/
++										/******************/
+ 										/* Timer 0 factor */
+-					   /******************/
++										/******************/
+ 
+ 										ul_LowTimerValue
+ 											=
+@@ -478,9 +478,9 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 											*
+ 											(0.25 * b_ClockSelection));
+ 
+-					   /*******************/
++										/*******************/
+ 										/* Round the value */
+-					   /*******************/
++										/*******************/
+ 
+ 										if ((double)((double)ul_LowTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+ 											ul_LowTimerValue
+@@ -490,9 +490,9 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 												1;
+ 										}
+ 
+-					   /*****************************/
++										/*****************************/
+ 										/* Calculate the real timing */
+-					   /*****************************/
++										/*****************************/
+ 
+ 										*pul_RealLowTiming
+ 											=
+@@ -544,15 +544,15 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 
+ 										break;
+ 
+-				   /******/
++										/******/
+ 										/* ms */
+-				   /******/
++										/******/
+ 
+ 									case 2:
+ 
+-					   /******************/
++										/******************/
+ 										/* Timer 0 factor */
+-					   /******************/
++										/******************/
+ 
+ 										ul_LowTimerValue
+ 											=
+@@ -562,9 +562,9 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 											*
+ 											b_ClockSelection);
+ 
+-					   /*******************/
++										/*******************/
+ 										/* Round the value */
+-					   /*******************/
++										/*******************/
+ 
+ 										if ((double)((double)ul_LowTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+ 											ul_LowTimerValue
+@@ -574,9 +574,9 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 												1;
+ 										}
+ 
+-					   /*****************************/
++										/*****************************/
+ 										/* Calculate the real timing */
+-					   /*****************************/
++										/*****************************/
+ 
+ 										*pul_RealLowTiming
+ 											=
+@@ -626,14 +626,14 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 
+ 										break;
+ 
+-				   /*****/
++										/*****/
+ 										/* s */
+-				   /*****/
++										/*****/
+ 
+ 									case 3:
+-					   /******************/
++										/******************/
+ 										/* Timer 0 factor */
+-					   /******************/
++										/******************/
+ 
+ 										ul_LowTimerValue
+ 											=
+@@ -644,9 +644,9 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 												*
+ 												b_ClockSelection));
+ 
+-					   /*******************/
++										/*******************/
+ 										/* Round the value */
+-					   /*******************/
++										/*******************/
+ 
+ 										if ((double)((double)ul_LowTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+ 											ul_LowTimerValue
+@@ -656,9 +656,9 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 												1;
+ 										}
+ 
+-					   /*****************************/
++										/*****************************/
+ 										/* Calculate the real timing */
+-					   /*****************************/
++										/*****************************/
+ 
+ 										*pul_RealLowTiming
+ 											=
+@@ -711,15 +711,15 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 
+ 										break;
+ 
+-				   /******/
++										/******/
+ 										/* mn */
+-				   /******/
++										/******/
+ 
+ 									case 4:
+ 
+-					   /******************/
++										/******************/
+ 										/* Timer 0 factor */
+-					   /******************/
++										/******************/
+ 
+ 										ul_LowTimerValue
+ 											=
+@@ -733,9 +733,9 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 												*
+ 												b_ClockSelection));
+ 
+-					   /*******************/
++										/*******************/
+ 										/* Round the value */
+-					   /*******************/
++										/*******************/
+ 
+ 										if ((double)((double)(ul_LowTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+ 											ul_LowTimerValue
+@@ -745,9 +745,9 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 												1;
+ 										}
+ 
+-					   /*****************************/
++										/*****************************/
+ 										/* Calculate the real timing */
+-					   /*****************************/
++										/*****************************/
+ 
+ 										*pul_RealLowTiming
+ 											=
+@@ -806,20 +806,20 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 										break;
+ 									}
+ 
+-				/*************************************/
++									/*************************************/
+ 									/* Calculate the high division fator */
+-				/*************************************/
++									/*************************************/
+ 
+ 									switch (b_TimingUnit) {
+-				   /******/
++										/******/
+ 										/* ns */
+-				   /******/
++										/******/
+ 
+ 									case 0:
+ 
+-					   /******************/
++										/******************/
+ 										/* Timer 0 factor */
+-					   /******************/
++										/******************/
+ 
+ 										ul_HighTimerValue
+ 											=
+@@ -828,9 +828,9 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 											*
+ 											(0.00025 * b_ClockSelection));
+ 
+-					   /*******************/
++										/*******************/
+ 										/* Round the value */
+-					   /*******************/
++										/*******************/
+ 
+ 										if ((double)((double)ul_HighTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+ 											ul_HighTimerValue
+@@ -840,9 +840,9 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 												1;
+ 										}
+ 
+-					   /*****************************/
++										/*****************************/
+ 										/* Calculate the real timing */
+-					   /*****************************/
++										/*****************************/
+ 
+ 										*pul_RealHighTiming
+ 											=
+@@ -892,15 +892,15 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 
+ 										break;
+ 
+-				   /******/
++										/******/
+ 										/* æs */
+-				   /******/
++										/******/
+ 
+ 									case 1:
+ 
+-					   /******************/
++										/******************/
+ 										/* Timer 0 factor */
+-					   /******************/
++										/******************/
+ 
+ 										ul_HighTimerValue
+ 											=
+@@ -909,9 +909,9 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 											*
+ 											(0.25 * b_ClockSelection));
+ 
+-					   /*******************/
++										/*******************/
+ 										/* Round the value */
+-					   /*******************/
++										/*******************/
+ 
+ 										if ((double)((double)ul_HighTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+ 											ul_HighTimerValue
+@@ -921,9 +921,9 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 												1;
+ 										}
+ 
+-					   /*****************************/
++										/*****************************/
+ 										/* Calculate the real timing */
+-					   /*****************************/
++										/*****************************/
+ 
+ 										*pul_RealHighTiming
+ 											=
+@@ -975,15 +975,15 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 
+ 										break;
+ 
+-				   /******/
++										/******/
+ 										/* ms */
+-				   /******/
++										/******/
+ 
+ 									case 2:
+ 
+-					   /******************/
++										/******************/
+ 										/* Timer 0 factor */
+-					   /******************/
++										/******************/
+ 
+ 										ul_HighTimerValue
+ 											=
+@@ -993,9 +993,9 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 											*
+ 											b_ClockSelection);
+ 
+-					   /*******************/
++										/*******************/
+ 										/* Round the value */
+-					   /*******************/
++										/*******************/
+ 
+ 										if ((double)((double)ul_HighTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+ 											ul_HighTimerValue
+@@ -1005,9 +1005,9 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 												1;
+ 										}
+ 
+-					   /*****************************/
++										/*****************************/
+ 										/* Calculate the real timing */
+-					   /*****************************/
++										/*****************************/
+ 
+ 										*pul_RealHighTiming
+ 											=
+@@ -1057,15 +1057,15 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 
+ 										break;
+ 
+-				   /*****/
++										/*****/
+ 										/* s */
+-				   /*****/
++										/*****/
+ 
+ 									case 3:
+ 
+-					   /******************/
++										/******************/
+ 										/* Timer 0 factor */
+-					   /******************/
++										/******************/
+ 
+ 										ul_HighTimerValue
+ 											=
+@@ -1076,9 +1076,9 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 												*
+ 												b_ClockSelection));
+ 
+-					   /*******************/
++										/*******************/
+ 										/* Round the value */
+-					   /*******************/
++										/*******************/
+ 
+ 										if ((double)((double)ul_HighTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+ 											ul_HighTimerValue
+@@ -1088,9 +1088,9 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 												1;
+ 										}
+ 
+-					   /*****************************/
++										/*****************************/
+ 										/* Calculate the real timing */
+-					   /*****************************/
++										/*****************************/
+ 
+ 										*pul_RealHighTiming
+ 											=
+@@ -1143,15 +1143,15 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 
+ 										break;
+ 
+-				   /******/
++										/******/
+ 										/* mn */
+-				   /******/
++										/******/
+ 
+ 									case 4:
+ 
+-					   /******************/
++										/******************/
+ 										/* Timer 0 factor */
+-					   /******************/
++										/******************/
+ 
+ 										ul_HighTimerValue
+ 											=
+@@ -1165,9 +1165,9 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 												*
+ 												b_ClockSelection));
+ 
+-					   /*******************/
++										/*******************/
+ 										/* Round the value */
+-					   /*******************/
++										/*******************/
+ 
+ 										if ((double)((double)(ul_HighTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+ 											ul_HighTimerValue
+@@ -1177,9 +1177,9 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 												1;
+ 										}
+ 
+-					   /*****************************/
++										/*****************************/
+ 										/* Calculate the real timing */
+-					   /*****************************/
++										/*****************************/
+ 
+ 										*pul_RealHighTiming
+ 											=
+@@ -1239,9 +1239,9 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 									}
+ 
+ 									fpu_end();
+-				/****************************/
++									/****************************/
+ 									/* Save the clock selection */
+-				/****************************/
++									/****************************/
+ 
+ 									devpriv->
+ 										s_ModuleInfo
+@@ -1251,9 +1251,9 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 										=
+ 										b_ClockSelection;
+ 
+-				/************************/
++									/************************/
+ 									/* Save the timing unit */
+-				/************************/
++									/************************/
+ 
+ 									devpriv->
+ 										s_ModuleInfo
+@@ -1265,9 +1265,9 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 										=
+ 										b_TimingUnit;
+ 
+-				/****************************/
++									/****************************/
+ 									/* Save the low base timing */
+-				/****************************/
++									/****************************/
+ 
+ 									devpriv->
+ 										s_ModuleInfo
+@@ -1289,9 +1289,9 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 										=
+ 										*pul_RealLowTiming;
+ 
+-				/****************************/
++									/****************************/
+ 									/* Save the high base timing */
+-				/****************************/
++									/****************************/
+ 
+ 									devpriv->
+ 										s_ModuleInfo
+@@ -1313,21 +1313,21 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 										=
+ 										*pul_RealHighTiming;
+ 
+-				/************************/
++									/************************/
+ 									/* Write the low timing */
+-				/************************/
++									/************************/
+ 
+ 									outl(ul_LowTimerValue, devpriv->s_BoardInfos.ui_Address + 0 + (20 * b_PWM) + (64 * b_ModulNbr));
+ 
+-				/*************************/
++									/*************************/
+ 									/* Write the high timing */
+-				/*************************/
++									/*************************/
+ 
+ 									outl(ul_HighTimerValue, devpriv->s_BoardInfos.ui_Address + 4 + (20 * b_PWM) + (64 * b_ModulNbr));
+ 
+-				/***************************/
++									/***************************/
+ 									/* Set the clock selection */
+-				/***************************/
++									/***************************/
+ 
+ 									dw_Command
+ 										=
+@@ -1354,15 +1354,15 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 											0x80;
+ 									}
+ 
+-				/***************************/
++									/***************************/
+ 									/* Set the clock selection */
+-				/***************************/
++									/***************************/
+ 
+ 									outl(dw_Command, devpriv->s_BoardInfos.ui_Address + 8 + (20 * b_PWM) + (64 * b_ModulNbr));
+ 
+-				/*************/
++									/*************/
+ 									/* PWM init. */
+-				/*************/
++									/*************/
+ 									devpriv->
+ 										s_ModuleInfo
+ 										[b_ModulNbr].
+@@ -1373,65 +1373,65 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 										=
+ 										1;
+ 								} else {
+-				/***************************************************/
++									/***************************************************/
+ 									/* You can not used the 40MHz clock selection with */
+ 									/* this board                                      */
+-				/***************************************************/
++									/***************************************************/
+ 									DPRINTK("You can not used the 40MHz clock selection with this board\n");
+ 									i_ReturnValue
+ 										=
+ 										-9;
+ 								}
+ 							} else {
+-			     /***************************************/
++								/***************************************/
+ 								/* High base timing selection is wrong */
+-			     /***************************************/
++								/***************************************/
+ 								DPRINTK("High base timing selection is wrong\n");
+ 								i_ReturnValue =
+ 									-8;
+ 							}
+ 						} else {
+-			  /**************************************/
++							/**************************************/
+ 							/* Low base timing selection is wrong */
+-			  /**************************************/
++							/**************************************/
+ 							DPRINTK("Low base timing selection is wrong\n");
+ 							i_ReturnValue = -7;
+ 						}
+-					}	// if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))
++					}	/*  if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) */
+ 					else {
+-		       /**********************************/
++						/**********************************/
+ 						/* Timing unit selection is wrong */
+-		       /**********************************/
++						/**********************************/
+ 						DPRINTK("Timing unit selection is wrong\n");
+ 						i_ReturnValue = -6;
+-					}	// if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))
+-				}	// if ((b_ClockSelection == APCI1710_30MHZ) || (b_ClockSelection == APCI1710_33MHZ) || (b_ClockSelection == APCI1710_40MHZ))
++					}	/*  if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) */
++				}	/*  if ((b_ClockSelection == APCI1710_30MHZ) || (b_ClockSelection == APCI1710_33MHZ) || (b_ClockSelection == APCI1710_40MHZ)) */
+ 				else {
+-		    /*******************************/
++					/*******************************/
+ 					/* The selected clock is wrong */
+-		    /*******************************/
++					/*******************************/
+ 					DPRINTK("The selected clock is wrong\n");
+ 					i_ReturnValue = -5;
+-				}	// if ((b_ClockSelection == APCI1710_30MHZ) || (b_ClockSelection == APCI1710_33MHZ) || (b_ClockSelection == APCI1710_40MHZ))
+-			}	// if (b_PWM >= 0 && b_PWM <= 1)
++				}	/*  if ((b_ClockSelection == APCI1710_30MHZ) || (b_ClockSelection == APCI1710_33MHZ) || (b_ClockSelection == APCI1710_40MHZ)) */
++			}	/*  if (b_PWM >= 0 && b_PWM <= 1) */
+ 			else {
+-		 /******************************/
++				/******************************/
+ 				/* Tor PWM selection is wrong */
+-		 /******************************/
++				/******************************/
+ 				DPRINTK("Tor PWM selection is wrong\n");
+ 				i_ReturnValue = -4;
+-			}	// if (b_PWM >= 0 && b_PWM <= 1)
++			}	/*  if (b_PWM >= 0 && b_PWM <= 1) */
+ 		} else {
+-	      /**********************************/
++			/**********************************/
+ 			/* The module is not a PWM module */
+-	      /**********************************/
++			/**********************************/
+ 			DPRINTK("The module is not a PWM module\n");
+ 			i_ReturnValue = -3;
+ 		}
+ 	} else {
+-	   /***********************/
++		/***********************/
+ 		/* Module number error */
+-	   /***********************/
++		/***********************/
+ 		DPRINTK("Module number error\n");
+ 		i_ReturnValue = -2;
+ 	}
+@@ -1554,48 +1554,48 @@ int i_APCI1710_GetPWMInitialisation(struct comedi_device * dev,
+ 	/**************************/
+ 
+ 	if (b_ModulNbr < 4) {
+-	   /***************/
++		/***************/
+ 		/* Test if PWM */
+-	   /***************/
++		/***************/
+ 
+ 		if ((devpriv->s_BoardInfos.
+ 				dw_MolduleConfiguration[b_ModulNbr] &
+ 				0xFFFF0000UL) == APCI1710_PWM) {
+-	      /**************************/
++			/**************************/
+ 			/* Test the PWM selection */
+-	      /**************************/
++			/**************************/
+ 
+ 			if (b_PWM <= 1) {
+-		 /***************************/
++				/***************************/
+ 				/* Test if PWM initialised */
+-		 /***************************/
++				/***************************/
+ 
+ 				dw_Status = inl(devpriv->s_BoardInfos.
+ 					ui_Address + 12 + (20 * b_PWM) +
+ 					(64 * b_ModulNbr));
+ 
+ 				if (dw_Status & 0x10) {
+-		    /***********************/
++					/***********************/
+ 					/* Read the low timing */
+-		    /***********************/
++					/***********************/
+ 
+ 					*pul_LowTiming =
+ 						inl(devpriv->s_BoardInfos.
+ 						ui_Address + 0 + (20 * b_PWM) +
+ 						(64 * b_ModulNbr));
+ 
+-		    /************************/
++					/************************/
+ 					/* Read the high timing */
+-		    /************************/
++					/************************/
+ 
+ 					*pul_HighTiming =
+ 						inl(devpriv->s_BoardInfos.
+ 						ui_Address + 4 + (20 * b_PWM) +
+ 						(64 * b_ModulNbr));
+ 
+-		    /********************/
++					/********************/
+ 					/* Read the command */
+-		    /********************/
++					/********************/
+ 
+ 					dw_Command = inl(devpriv->s_BoardInfos.
+ 						ui_Address + 8 + (20 * b_PWM) +
+@@ -1619,9 +1619,9 @@ int i_APCI1710_GetPWMInitialisation(struct comedi_device * dev,
+ 								2) & 1);
+ 					}
+ 
+-		    /********************/
++					/********************/
+ 					/* Read the command */
+-		    /********************/
++					/********************/
+ 
+ 					dw_Command = inl(devpriv->s_BoardInfos.
+ 						ui_Address + 8 + (20 * b_PWM) +
+@@ -1634,33 +1634,33 @@ int i_APCI1710_GetPWMInitialisation(struct comedi_device * dev,
+ 						s_ModuleInfo[b_ModulNbr].
+ 						s_PWMModuleInfo.
+ 						s_PWMInfo[b_PWM].b_TimingUnit;
+-				}	// if (dw_Status & 0x10)
++				}	/*  if (dw_Status & 0x10) */
+ 				else {
+-		    /***********************/
++					/***********************/
+ 					/* PWM not initialised */
+-		    /***********************/
++					/***********************/
+ 					DPRINTK("PWM not initialised\n");
+ 					i_ReturnValue = -5;
+-				}	// if (dw_Status & 0x10)
+-			}	// if (b_PWM >= 0 && b_PWM <= 1)
++				}	/*  if (dw_Status & 0x10) */
++			}	/*  if (b_PWM >= 0 && b_PWM <= 1) */
+ 			else {
+-		 /******************************/
++				/******************************/
+ 				/* Tor PWM selection is wrong */
+-		 /******************************/
++				/******************************/
+ 				DPRINTK("Tor PWM selection is wrong\n");
+ 				i_ReturnValue = -4;
+-			}	// if (b_PWM >= 0 && b_PWM <= 1)
++			}	/*  if (b_PWM >= 0 && b_PWM <= 1) */
+ 		} else {
+-	      /**********************************/
++			/**********************************/
+ 			/* The module is not a PWM module */
+-	      /**********************************/
++			/**********************************/
+ 			DPRINTK("The module is not a PWM module\n");
+ 			i_ReturnValue = -3;
+ 		}
+ 	} else {
+-	   /***********************/
++		/***********************/
+ 		/* Module number error */
+-	   /***********************/
++		/***********************/
+ 		DPRINTK("Module number error\n");
+ 		i_ReturnValue = -2;
+ 	}
+@@ -1817,66 +1817,66 @@ int i_APCI1710_EnablePWM(struct comedi_device * dev,
+ 	unsigned int dw_Status;
+ 	unsigned int dw_Command;
+ 
+-	devpriv->tsk_Current = current;	// Save the current process task structure
++	devpriv->tsk_Current = current;	/*  Save the current process task structure */
+ 	/**************************/
+ 	/* Test the module number */
+ 	/**************************/
+ 
+ 	if (b_ModulNbr < 4) {
+-	   /***************/
++		/***************/
+ 		/* Test if PWM */
+-	   /***************/
++		/***************/
+ 
+ 		if ((devpriv->s_BoardInfos.
+ 				dw_MolduleConfiguration[b_ModulNbr] &
+ 				0xFFFF0000UL) == APCI1710_PWM) {
+-	      /**************************/
++			/**************************/
+ 			/* Test the PWM selection */
+-	      /**************************/
++			/**************************/
+ 
+ 			if (b_PWM <= 1) {
+-		 /***************************/
++				/***************************/
+ 				/* Test if PWM initialised */
+-		 /***************************/
++				/***************************/
+ 
+ 				dw_Status = inl(devpriv->s_BoardInfos.
+ 					ui_Address + 12 + (20 * b_PWM) +
+ 					(64 * b_ModulNbr));
+ 
+ 				if (dw_Status & 0x10) {
+-		    /**********************************/
++					/**********************************/
+ 					/* Test the start level selection */
+-		    /**********************************/
++					/**********************************/
+ 
+ 					if (b_StartLevel <= 1) {
+-		       /**********************/
++						/**********************/
+ 						/* Test the stop mode */
+-		       /**********************/
++						/**********************/
+ 
+ 						if (b_StopMode <= 1) {
+-			  /***********************/
++							/***********************/
+ 							/* Test the stop level */
+-			  /***********************/
++							/***********************/
+ 
+ 							if (b_StopLevel <= 2) {
+-			     /*****************************/
++								/*****************************/
+ 								/* Test the extern gate mode */
+-			     /*****************************/
++								/*****************************/
+ 
+ 								if (b_ExternGate
+ 									<= 1) {
+-				/*****************************/
++									/*****************************/
+ 									/* Test the interrupt action */
+-				/*****************************/
++									/*****************************/
+ 
+ 									if (b_InterruptEnable == APCI1710_ENABLE || b_InterruptEnable == APCI1710_DISABLE) {
+-				   /******************************************/
++										/******************************************/
+ 										/* Test if interrupt function initialised */
+-				   /******************************************/
++										/******************************************/
+ 
+-				      /********************/
++										/********************/
+ 										/* Read the command */
+-				      /********************/
++										/********************/
+ 
+ 										dw_Command
+ 											=
+@@ -1895,9 +1895,9 @@ int i_APCI1710_EnablePWM(struct comedi_device * dev,
+ 											&
+ 											0x80;
+ 
+-				      /********************/
++										/********************/
+ 										/* Make the command */
+-				      /********************/
++										/********************/
+ 
+ 										dw_Command
+ 											=
+@@ -1943,88 +1943,88 @@ int i_APCI1710_EnablePWM(struct comedi_device * dev,
+ 											=
+ 											b_InterruptEnable;
+ 
+-				      /*******************/
++										/*******************/
+ 										/* Set the command */
+-				      /*******************/
++										/*******************/
+ 
+ 										outl(dw_Command, devpriv->s_BoardInfos.ui_Address + 8 + (20 * b_PWM) + (64 * b_ModulNbr));
+ 
+-				      /******************/
++										/******************/
+ 										/* Enable the PWM */
+-				      /******************/
++										/******************/
+ 										outl(1, devpriv->s_BoardInfos.ui_Address + 12 + (20 * b_PWM) + (64 * b_ModulNbr));
+-									}	// if (b_InterruptEnable == APCI1710_ENABLE || b_InterruptEnable == APCI1710_DISABLE)
++									}	/*  if (b_InterruptEnable == APCI1710_ENABLE || b_InterruptEnable == APCI1710_DISABLE) */
+ 									else {
+-				   /********************************/
++										/********************************/
+ 										/* Interrupt parameter is wrong */
+-				   /********************************/
++										/********************************/
+ 										DPRINTK("Interrupt parameter is wrong\n");
+ 										i_ReturnValue
+ 											=
+ 											-10;
+-									}	// if (b_InterruptEnable == APCI1710_ENABLE || b_InterruptEnable == APCI1710_DISABLE)
+-								}	// if (b_ExternGate >= 0 && b_ExternGate <= 1)
++									}	/*  if (b_InterruptEnable == APCI1710_ENABLE || b_InterruptEnable == APCI1710_DISABLE) */
++								}	/*  if (b_ExternGate >= 0 && b_ExternGate <= 1) */
+ 								else {
+-				/*****************************************/
++									/*****************************************/
+ 									/* Extern gate signal selection is wrong */
+-				/*****************************************/
++									/*****************************************/
+ 									DPRINTK("Extern gate signal selection is wrong\n");
+ 									i_ReturnValue
+ 										=
+ 										-9;
+-								}	// if (b_ExternGate >= 0 && b_ExternGate <= 1)
+-							}	// if (b_StopLevel >= 0 && b_StopLevel <= 2)
++								}	/*  if (b_ExternGate >= 0 && b_ExternGate <= 1) */
++							}	/*  if (b_StopLevel >= 0 && b_StopLevel <= 2) */
+ 							else {
+-			     /*************************************/
++								/*************************************/
+ 								/* PWM stop level selection is wrong */
+-			     /*************************************/
++								/*************************************/
+ 								DPRINTK("PWM stop level selection is wrong\n");
+ 								i_ReturnValue =
+ 									-8;
+-							}	// if (b_StopLevel >= 0 && b_StopLevel <= 2)
+-						}	// if (b_StopMode >= 0 && b_StopMode <= 1)
++							}	/*  if (b_StopLevel >= 0 && b_StopLevel <= 2) */
++						}	/*  if (b_StopMode >= 0 && b_StopMode <= 1) */
+ 						else {
+-			  /************************************/
++							/************************************/
+ 							/* PWM stop mode selection is wrong */
+-			  /************************************/
++							/************************************/
+ 							DPRINTK("PWM stop mode selection is wrong\n");
+ 							i_ReturnValue = -7;
+-						}	// if (b_StopMode >= 0 && b_StopMode <= 1)
+-					}	// if (b_StartLevel >= 0 && b_StartLevel <= 1)
++						}	/*  if (b_StopMode >= 0 && b_StopMode <= 1) */
++					}	/*  if (b_StartLevel >= 0 && b_StartLevel <= 1) */
+ 					else {
+-		       /**************************************/
++						/**************************************/
+ 						/* PWM start level selection is wrong */
+-		       /**************************************/
++						/**************************************/
+ 						DPRINTK("PWM start level selection is wrong\n");
+ 						i_ReturnValue = -6;
+-					}	// if (b_StartLevel >= 0 && b_StartLevel <= 1)
+-				}	// if (dw_Status & 0x10)
++					}	/*  if (b_StartLevel >= 0 && b_StartLevel <= 1) */
++				}	/*  if (dw_Status & 0x10) */
+ 				else {
+-		    /***********************/
++					/***********************/
+ 					/* PWM not initialised */
+-		    /***********************/
++					/***********************/
+ 					DPRINTK("PWM not initialised\n");
+ 					i_ReturnValue = -5;
+-				}	// if (dw_Status & 0x10)
+-			}	// if (b_PWM >= 0 && b_PWM <= 1)
++				}	/*  if (dw_Status & 0x10) */
++			}	/*  if (b_PWM >= 0 && b_PWM <= 1) */
+ 			else {
+-		 /******************************/
++				/******************************/
+ 				/* Tor PWM selection is wrong */
+-		 /******************************/
++				/******************************/
+ 				DPRINTK("Tor PWM selection is wrong\n");
+ 				i_ReturnValue = -4;
+-			}	// if (b_PWM >= 0 && b_PWM <= 1)
++			}	/*  if (b_PWM >= 0 && b_PWM <= 1) */
+ 		} else {
+-	      /**********************************/
++			/**********************************/
+ 			/* The module is not a PWM module */
+-	      /**********************************/
++			/**********************************/
+ 			DPRINTK("The module is not a PWM module\n");
+ 			i_ReturnValue = -3;
+ 		}
+ 	} else {
+-	   /***********************/
++		/***********************/
+ 		/* Module number error */
+-	   /***********************/
++		/***********************/
+ 		DPRINTK("Module number error\n");
+ 		i_ReturnValue = -2;
+ 	}
+@@ -2072,74 +2072,74 @@ int i_APCI1710_DisablePWM(struct comedi_device * dev, unsigned char b_ModulNbr,
+ 	/**************************/
+ 
+ 	if (b_ModulNbr < 4) {
+-	   /***************/
++		/***************/
+ 		/* Test if PWM */
+-	   /***************/
++		/***************/
+ 
+ 		if ((devpriv->s_BoardInfos.
+ 				dw_MolduleConfiguration[b_ModulNbr] &
+ 				0xFFFF0000UL) == APCI1710_PWM) {
+-	      /**************************/
++			/**************************/
+ 			/* Test the PWM selection */
+-	      /**************************/
++			/**************************/
+ 
+ 			if (b_PWM <= 1) {
+-		 /***************************/
++				/***************************/
+ 				/* Test if PWM initialised */
+-		 /***************************/
++				/***************************/
+ 
+ 				dw_Status = inl(devpriv->s_BoardInfos.
+ 					ui_Address + 12 + (20 * b_PWM) +
+ 					(64 * b_ModulNbr));
+ 
+ 				if (dw_Status & 0x10) {
+-		    /***********************/
++					/***********************/
+ 					/* Test if PWM enabled */
+-		    /***********************/
++					/***********************/
+ 
+ 					if (dw_Status & 0x1) {
+-		       /*******************/
++						/*******************/
+ 						/* Disable the PWM */
+-		       /*******************/
++						/*******************/
+ 						outl(0, devpriv->s_BoardInfos.
+ 							ui_Address + 12 +
+ 							(20 * b_PWM) +
+ 							(64 * b_ModulNbr));
+-					}	// if (dw_Status & 0x1)
++					}	/*  if (dw_Status & 0x1) */
+ 					else {
+-		       /*******************/
++						/*******************/
+ 						/* PWM not enabled */
+-		       /*******************/
++						/*******************/
+ 						DPRINTK("PWM not enabled\n");
+ 						i_ReturnValue = -6;
+-					}	// if (dw_Status & 0x1)
+-				}	// if (dw_Status & 0x10)
++					}	/*  if (dw_Status & 0x1) */
++				}	/*  if (dw_Status & 0x10) */
+ 				else {
+-		    /***********************/
++					/***********************/
+ 					/* PWM not initialised */
+-		    /***********************/
++					/***********************/
+ 					DPRINTK(" PWM not initialised\n");
+ 					i_ReturnValue = -5;
+-				}	// if (dw_Status & 0x10)
+-			}	// if (b_PWM >= 0 && b_PWM <= 1)
++				}	/*  if (dw_Status & 0x10) */
++			}	/*  if (b_PWM >= 0 && b_PWM <= 1) */
+ 			else {
+-		 /******************************/
++				/******************************/
+ 				/* Tor PWM selection is wrong */
+-		 /******************************/
++				/******************************/
+ 				DPRINTK("Tor PWM selection is wrong\n");
+ 				i_ReturnValue = -4;
+-			}	// if (b_PWM >= 0 && b_PWM <= 1)
++			}	/*  if (b_PWM >= 0 && b_PWM <= 1) */
+ 		} else {
+-	      /**********************************/
++			/**********************************/
+ 			/* The module is not a PWM module */
+-	      /**********************************/
++			/**********************************/
+ 			DPRINTK("The module is not a PWM module\n");
+ 			i_ReturnValue = -3;
+ 		}
+ 	} else {
+-	   /***********************/
++		/***********************/
+ 		/* Module number error */
+-	   /***********************/
++		/***********************/
+ 		DPRINTK("Module number error\n");
+ 		i_ReturnValue = -2;
+ 	}
+@@ -2209,21 +2209,21 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 	/**************************/
+ 
+ 	if (b_ModulNbr < 4) {
+-	   /***************/
++		/***************/
+ 		/* Test if PWM */
+-	   /***************/
++		/***************/
+ 
+ 		if ((devpriv->s_BoardInfos.
+ 				dw_MolduleConfiguration[b_ModulNbr] &
+ 				0xFFFF0000UL) == APCI1710_PWM) {
+-	      /**************************/
++			/**************************/
+ 			/* Test the PWM selection */
+-	      /**************************/
++			/**************************/
+ 
+ 			if (b_PWM <= 1) {
+-		 /***************************/
++				/***************************/
+ 				/* Test if PWM initialised */
+-		 /***************************/
++				/***************************/
+ 
+ 				dw_Status = inl(devpriv->s_BoardInfos.
+ 					ui_Address + 12 + (20 * b_PWM) +
+@@ -2235,14 +2235,14 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 						s_PWMModuleInfo.
+ 						b_ClockSelection;
+ 
+-		    /************************/
++					/************************/
+ 					/* Test the timing unit */
+-		    /************************/
++					/************************/
+ 
+ 					if (b_TimingUnit <= 4) {
+-		       /*********************************/
++						/*********************************/
+ 						/* Test the low timing selection */
+-		       /*********************************/
++						/*********************************/
+ 
+ 						if (((b_ClockSelection ==
+ 									APCI1710_30MHZ)
+@@ -2377,26 +2377,26 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 								&& (ul_LowTiming
+ 									<=
+ 									7UL))) {
+-			  /**********************************/
++							/**********************************/
+ 							/* Test the High timing selection */
+-			  /**********************************/
++							/**********************************/
+ 
+ 							if (((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 266) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230650UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 9UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 242) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691043UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 520UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 8UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 200) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496729UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 7UL))) {
+-			     /************************************/
++								/************************************/
+ 								/* Calculate the low division fator */
+-			     /************************************/
++								/************************************/
+ 
+ 								fpu_begin();
+ 								switch (b_TimingUnit) {
+-				/******/
++									/******/
+ 									/* ns */
+-				/******/
++									/******/
+ 
+ 								case 0:
+ 
+-					/******************/
++									/******************/
+ 									/* Timer 0 factor */
+-					/******************/
++									/******************/
+ 
+ 									ul_LowTimerValue
+ 										=
+@@ -2405,9 +2405,9 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 										*
+ 										(0.00025 * b_ClockSelection));
+ 
+-					/*******************/
++									/*******************/
+ 									/* Round the value */
+-					/*******************/
++									/*******************/
+ 
+ 									if ((double)((double)ul_LowTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+ 										ul_LowTimerValue
+@@ -2417,9 +2417,9 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 											1;
+ 									}
+ 
+-					/*****************************/
++									/*****************************/
+ 									/* Calculate the real timing */
+-					/*****************************/
++									/*****************************/
+ 
+ 									ul_RealLowTiming
+ 										=
+@@ -2469,15 +2469,15 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 									break;
+ 
+-				/******/
++									/******/
+ 									/* æs */
+-				/******/
++									/******/
+ 
+ 								case 1:
+ 
+-					/******************/
++									/******************/
+ 									/* Timer 0 factor */
+-					/******************/
++									/******************/
+ 
+ 									ul_LowTimerValue
+ 										=
+@@ -2486,9 +2486,9 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 										*
+ 										(0.25 * b_ClockSelection));
+ 
+-					/*******************/
++									/*******************/
+ 									/* Round the value */
+-					/*******************/
++									/*******************/
+ 
+ 									if ((double)((double)ul_LowTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+ 										ul_LowTimerValue
+@@ -2498,9 +2498,9 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 											1;
+ 									}
+ 
+-					/*****************************/
++									/*****************************/
+ 									/* Calculate the real timing */
+-					/*****************************/
++									/*****************************/
+ 
+ 									ul_RealLowTiming
+ 										=
+@@ -2552,15 +2552,15 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 									break;
+ 
+-				/******/
++									/******/
+ 									/* ms */
+-				/******/
++									/******/
+ 
+ 								case 2:
+ 
+-					/******************/
++									/******************/
+ 									/* Timer 0 factor */
+-					/******************/
++									/******************/
+ 
+ 									ul_LowTimerValue
+ 										=
+@@ -2570,9 +2570,9 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 										*
+ 										b_ClockSelection);
+ 
+-					/*******************/
++									/*******************/
+ 									/* Round the value */
+-					/*******************/
++									/*******************/
+ 
+ 									if ((double)((double)ul_LowTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+ 										ul_LowTimerValue
+@@ -2582,9 +2582,9 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 											1;
+ 									}
+ 
+-					/*****************************/
++									/*****************************/
+ 									/* Calculate the real timing */
+-					/*****************************/
++									/*****************************/
+ 
+ 									ul_RealLowTiming
+ 										=
+@@ -2634,15 +2634,15 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 									break;
+ 
+-				/*****/
++									/*****/
+ 									/* s */
+-				/*****/
++									/*****/
+ 
+ 								case 3:
+ 
+-					/******************/
++									/******************/
+ 									/* Timer 0 factor */
+-					/******************/
++									/******************/
+ 
+ 									ul_LowTimerValue
+ 										=
+@@ -2653,9 +2653,9 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 											*
+ 											b_ClockSelection));
+ 
+-					/*******************/
++									/*******************/
+ 									/* Round the value */
+-					/*******************/
++									/*******************/
+ 
+ 									if ((double)((double)ul_LowTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+ 										ul_LowTimerValue
+@@ -2665,9 +2665,9 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 											1;
+ 									}
+ 
+-					/*****************************/
++									/*****************************/
+ 									/* Calculate the real timing */
+-					/*****************************/
++									/*****************************/
+ 
+ 									ul_RealLowTiming
+ 										=
+@@ -2720,15 +2720,15 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 									break;
+ 
+-				/******/
++									/******/
+ 									/* mn */
+-				/******/
++									/******/
+ 
+ 								case 4:
+ 
+-					/******************/
++									/******************/
+ 									/* Timer 0 factor */
+-					/******************/
++									/******************/
+ 
+ 									ul_LowTimerValue
+ 										=
+@@ -2742,9 +2742,9 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 											*
+ 											b_ClockSelection));
+ 
+-					/*******************/
++									/*******************/
+ 									/* Round the value */
+-					/*******************/
++									/*******************/
+ 
+ 									if ((double)((double)(ul_LowTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+ 										ul_LowTimerValue
+@@ -2754,9 +2754,9 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 											1;
+ 									}
+ 
+-					/*****************************/
++									/*****************************/
+ 									/* Calculate the real timing */
+-					/*****************************/
++									/*****************************/
+ 
+ 									ul_RealLowTiming
+ 										=
+@@ -2815,20 +2815,20 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 									break;
+ 								}
+ 
+-			     /*************************************/
++								/*************************************/
+ 								/* Calculate the high division fator */
+-			     /*************************************/
++								/*************************************/
+ 
+ 								switch (b_TimingUnit) {
+-				/******/
++									/******/
+ 									/* ns */
+-				/******/
++									/******/
+ 
+ 								case 0:
+ 
+-					/******************/
++									/******************/
+ 									/* Timer 0 factor */
+-					/******************/
++									/******************/
+ 
+ 									ul_HighTimerValue
+ 										=
+@@ -2837,9 +2837,9 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 										*
+ 										(0.00025 * b_ClockSelection));
+ 
+-					/*******************/
++									/*******************/
+ 									/* Round the value */
+-					/*******************/
++									/*******************/
+ 
+ 									if ((double)((double)ul_HighTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+ 										ul_HighTimerValue
+@@ -2849,9 +2849,9 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 											1;
+ 									}
+ 
+-					/*****************************/
++									/*****************************/
+ 									/* Calculate the real timing */
+-					/*****************************/
++									/*****************************/
+ 
+ 									ul_RealHighTiming
+ 										=
+@@ -2901,15 +2901,15 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 									break;
+ 
+-				/******/
++									/******/
+ 									/* æs */
+-				/******/
++									/******/
+ 
+ 								case 1:
+ 
+-					/******************/
++									/******************/
+ 									/* Timer 0 factor */
+-					/******************/
++									/******************/
+ 
+ 									ul_HighTimerValue
+ 										=
+@@ -2918,9 +2918,9 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 										*
+ 										(0.25 * b_ClockSelection));
+ 
+-					/*******************/
++									/*******************/
+ 									/* Round the value */
+-					/*******************/
++									/*******************/
+ 
+ 									if ((double)((double)ul_HighTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+ 										ul_HighTimerValue
+@@ -2930,9 +2930,9 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 											1;
+ 									}
+ 
+-					/*****************************/
++									/*****************************/
+ 									/* Calculate the real timing */
+-					/*****************************/
++									/*****************************/
+ 
+ 									ul_RealHighTiming
+ 										=
+@@ -2984,15 +2984,15 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 									break;
+ 
+-				/******/
++									/******/
+ 									/* ms */
+-				/******/
++									/******/
+ 
+ 								case 2:
+ 
+-					/******************/
++									/******************/
+ 									/* Timer 0 factor */
+-					/******************/
++									/******************/
+ 
+ 									ul_HighTimerValue
+ 										=
+@@ -3002,9 +3002,9 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 										*
+ 										b_ClockSelection);
+ 
+-					/*******************/
++									/*******************/
+ 									/* Round the value */
+-					/*******************/
++									/*******************/
+ 
+ 									if ((double)((double)ul_HighTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+ 										ul_HighTimerValue
+@@ -3014,9 +3014,9 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 											1;
+ 									}
+ 
+-					/*****************************/
++									/*****************************/
+ 									/* Calculate the real timing */
+-					/*****************************/
++									/*****************************/
+ 
+ 									ul_RealHighTiming
+ 										=
+@@ -3066,15 +3066,15 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 									break;
+ 
+-				/*****/
++									/*****/
+ 									/* s */
+-				/*****/
++									/*****/
+ 
+ 								case 3:
+ 
+-					/******************/
++									/******************/
+ 									/* Timer 0 factor */
+-					/******************/
++									/******************/
+ 
+ 									ul_HighTimerValue
+ 										=
+@@ -3085,9 +3085,9 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 											*
+ 											b_ClockSelection));
+ 
+-					/*******************/
++									/*******************/
+ 									/* Round the value */
+-					/*******************/
++									/*******************/
+ 
+ 									if ((double)((double)ul_HighTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+ 										ul_HighTimerValue
+@@ -3097,9 +3097,9 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 											1;
+ 									}
+ 
+-					/*****************************/
++									/*****************************/
+ 									/* Calculate the real timing */
+-					/*****************************/
++									/*****************************/
+ 
+ 									ul_RealHighTiming
+ 										=
+@@ -3152,15 +3152,15 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 									break;
+ 
+-				/******/
++									/******/
+ 									/* mn */
+-				/******/
++									/******/
+ 
+ 								case 4:
+ 
+-					/******************/
++									/******************/
+ 									/* Timer 0 factor */
+-					/******************/
++									/******************/
+ 
+ 									ul_HighTimerValue
+ 										=
+@@ -3174,9 +3174,9 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 											*
+ 											b_ClockSelection));
+ 
+-					/*******************/
++									/*******************/
+ 									/* Round the value */
+-					/*******************/
++									/*******************/
+ 
+ 									if ((double)((double)(ul_HighTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+ 										ul_HighTimerValue
+@@ -3186,9 +3186,9 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 											1;
+ 									}
+ 
+-					/*****************************/
++									/*****************************/
+ 									/* Calculate the real timing */
+-					/*****************************/
++									/*****************************/
+ 
+ 									ul_RealHighTiming
+ 										=
+@@ -3249,9 +3249,9 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 								fpu_end();
+ 
+-			     /************************/
++								/************************/
+ 								/* Save the timing unit */
+-			     /************************/
++								/************************/
+ 
+ 								devpriv->
+ 									s_ModuleInfo
+@@ -3263,9 +3263,9 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 									=
+ 									b_TimingUnit;
+ 
+-			     /****************************/
++								/****************************/
+ 								/* Save the low base timing */
+-			     /****************************/
++								/****************************/
+ 
+ 								devpriv->
+ 									s_ModuleInfo
+@@ -3287,9 +3287,9 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 									=
+ 									ul_RealLowTiming;
+ 
+-			     /****************************/
++								/****************************/
+ 								/* Save the high base timing */
+-			     /****************************/
++								/****************************/
+ 
+ 								devpriv->
+ 									s_ModuleInfo
+@@ -3311,21 +3311,21 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 									=
+ 									ul_RealHighTiming;
+ 
+-			     /************************/
++								/************************/
+ 								/* Write the low timing */
+-			     /************************/
++								/************************/
+ 
+ 								outl(ul_LowTimerValue, devpriv->s_BoardInfos.ui_Address + 0 + (20 * b_PWM) + (64 * b_ModulNbr));
+ 
+-			     /*************************/
++								/*************************/
+ 								/* Write the high timing */
+-			     /*************************/
++								/*************************/
+ 
+ 								outl(ul_HighTimerValue, devpriv->s_BoardInfos.ui_Address + 4 + (20 * b_PWM) + (64 * b_ModulNbr));
+ 
+-			     /***************************/
++								/***************************/
+ 								/* Set the clock selection */
+-			     /***************************/
++								/***************************/
+ 
+ 								dw_Command =
+ 									inl
+@@ -3347,9 +3347,9 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 										0x80;
+ 								}
+ 
+-			     /***************************/
++								/***************************/
+ 								/* Set the clock selection */
+-			     /***************************/
++								/***************************/
+ 
+ 								outl(dw_Command,
+ 									devpriv->
+@@ -3358,55 +3358,55 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 									+ 8 +
+ 									(20 * b_PWM) + (64 * b_ModulNbr));
+ 							} else {
+-			     /***************************************/
++								/***************************************/
+ 								/* High base timing selection is wrong */
+-			     /***************************************/
++								/***************************************/
+ 								DPRINTK("High base timing selection is wrong\n");
+ 								i_ReturnValue =
+ 									-8;
+ 							}
+ 						} else {
+-			  /**************************************/
++							/**************************************/
+ 							/* Low base timing selection is wrong */
+-			  /**************************************/
++							/**************************************/
+ 							DPRINTK("Low base timing selection is wrong\n");
+ 							i_ReturnValue = -7;
+ 						}
+-					}	// if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))
++					}	/*  if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) */
+ 					else {
+-		       /**********************************/
++						/**********************************/
+ 						/* Timing unit selection is wrong */
+-		       /**********************************/
++						/**********************************/
+ 						DPRINTK("Timing unit selection is wrong\n");
+ 						i_ReturnValue = -6;
+-					}	// if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))
+-				}	// if (dw_Status & 0x10)
++					}	/*  if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) */
++				}	/*  if (dw_Status & 0x10) */
+ 				else {
+-		    /***********************/
++					/***********************/
+ 					/* PWM not initialised */
+-		    /***********************/
++					/***********************/
+ 					DPRINTK("PWM not initialised\n");
+ 					i_ReturnValue = -5;
+-				}	// if (dw_Status & 0x10)
+-			}	// if (b_PWM >= 0 && b_PWM <= 1)
++				}	/*  if (dw_Status & 0x10) */
++			}	/*  if (b_PWM >= 0 && b_PWM <= 1) */
+ 			else {
+-		 /******************************/
++				/******************************/
+ 				/* Tor PWM selection is wrong */
+-		 /******************************/
++				/******************************/
+ 				DPRINTK("Tor PWM selection is wrong\n");
+ 				i_ReturnValue = -4;
+-			}	// if (b_PWM >= 0 && b_PWM <= 1)
++			}	/*  if (b_PWM >= 0 && b_PWM <= 1) */
+ 		} else {
+-	      /**********************************/
++			/**********************************/
+ 			/* The module is not a PWM module */
+-	      /**********************************/
++			/**********************************/
+ 			DPRINTK("The module is not a PWM module\n");
+ 			i_ReturnValue = -3;
+ 		}
+ 	} else {
+-	   /***********************/
++		/***********************/
+ 		/* Module number error */
+-	   /***********************/
++		/***********************/
+ 		DPRINTK("Module number error\n");
+ 		i_ReturnValue = -2;
+ 	}
+@@ -3482,30 +3482,30 @@ int i_APCI1710_InsnReadGetPWMStatus(struct comedi_device * dev, struct comedi_su
+ 	/**************************/
+ 
+ 	if (b_ModulNbr < 4) {
+-	   /***************/
++		/***************/
+ 		/* Test if PWM */
+-	   /***************/
++		/***************/
+ 
+ 		if ((devpriv->s_BoardInfos.
+ 				dw_MolduleConfiguration[b_ModulNbr] &
+ 				0xFFFF0000UL) == APCI1710_PWM) {
+-	      /**************************/
++			/**************************/
+ 			/* Test the PWM selection */
+-	      /**************************/
++			/**************************/
+ 
+ 			if (b_PWM <= 1) {
+-		 /***************************/
++				/***************************/
+ 				/* Test if PWM initialised */
+-		 /***************************/
++				/***************************/
+ 
+ 				dw_Status = inl(devpriv->s_BoardInfos.
+ 					ui_Address + 12 + (20 * b_PWM) +
+ 					(64 * b_ModulNbr));
+ 
+ 				if (dw_Status & 0x10) {
+-		    /***********************/
++					/***********************/
+ 					/* Test if PWM enabled */
+-		    /***********************/
++					/***********************/
+ 
+ 					if (dw_Status & 0x1) {
+ 						*pb_PWMOutputStatus =
+@@ -3514,45 +3514,45 @@ int i_APCI1710_InsnReadGetPWMStatus(struct comedi_device * dev, struct comedi_su
+ 						*pb_ExternGateStatus =
+ 							(unsigned char) ((dw_Status >> 6)
+ 							& 1);
+-					}	// if (dw_Status & 0x1)
++					}	/*  if (dw_Status & 0x1) */
+ 					else {
+-		       /*******************/
++						/*******************/
+ 						/* PWM not enabled */
+-		       /*******************/
++						/*******************/
+ 
+ 						DPRINTK("PWM not enabled \n");
+ 						i_ReturnValue = -6;
+-					}	// if (dw_Status & 0x1)
+-				}	// if (dw_Status & 0x10)
++					}	/*  if (dw_Status & 0x1) */
++				}	/*  if (dw_Status & 0x10) */
+ 				else {
+-		    /***********************/
++					/***********************/
+ 					/* PWM not initialised */
+-		    /***********************/
++					/***********************/
+ 
+ 					DPRINTK("PWM not initialised\n");
+ 					i_ReturnValue = -5;
+-				}	// if (dw_Status & 0x10)
+-			}	// if (b_PWM >= 0 && b_PWM <= 1)
++				}	/*  if (dw_Status & 0x10) */
++			}	/*  if (b_PWM >= 0 && b_PWM <= 1) */
+ 			else {
+-		 /******************************/
++				/******************************/
+ 				/* Tor PWM selection is wrong */
+-		 /******************************/
++				/******************************/
+ 
+ 				DPRINTK("Tor PWM selection is wrong\n");
+ 				i_ReturnValue = -4;
+-			}	// if (b_PWM >= 0 && b_PWM <= 1)
++			}	/*  if (b_PWM >= 0 && b_PWM <= 1) */
+ 		} else {
+-	      /**********************************/
++			/**********************************/
+ 			/* The module is not a PWM module */
+-	      /**********************************/
++			/**********************************/
+ 
+ 			DPRINTK("The module is not a PWM module\n");
+ 			i_ReturnValue = -3;
+ 		}
+ 	} else {
+-	   /***********************/
++		/***********************/
+ 		/* Module number error */
+-	   /***********************/
++		/***********************/
+ 
+ 		DPRINTK("Module number error\n");
+ 		i_ReturnValue = -2;
+@@ -3574,9 +3574,9 @@ int i_APCI1710_InsnBitsReadPWMInterrupt(struct comedi_device * dev,
+ 		s_FIFOInterruptParameters[devpriv->
+ 		s_InterruptParameters.ui_Read].ul_OldCounterLatchValue;
+ 
+-			     /**************************/
++	/**************************/
+ 	/* Increment the read FIFO */
+-			     /***************************/
++	/***************************/
+ 
+ 	devpriv->
+ 		s_InterruptParameters.

commit c47375f3de0f478d8c2c0ce210cb2c5aeb1b411f
+Author: Bill Pemberton 
+Date:   Fri Mar 27 11:29:51 2009 -0400
+
+    Staging: comedi: remove C99 comments in hwdrv_apci1500.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+index 3c97ed7ee9fe..8f2cae90be79 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+@@ -157,16 +157,16 @@ int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device * dev,
+ 
+ 	if (data[0] == 1) {
+ 		i_MaxChannel = 8;
+-	}			// if (data[0] == 1)
++	}			/*  if (data[0] == 1) */
+ 	else {
+ 		if (data[0] == 2) {
+ 			i_MaxChannel = 6;
+-		}		// if(data[0]==2)
++		}		/*  if(data[0]==2) */
+ 		else {
+ 			printk("\nThe specified port event  does not exist\n");
+ 			return -EINVAL;
+-		}		//else if(data[0]==2)
+-	}			//else  if (data[0] == 1)
++		}		/* else if(data[0]==2) */
++	}			/* else  if (data[0] == 1) */
+ 	switch (data[1]) {
+ 	case 0:
+ 		data[1] = APCI1500_AND;
+@@ -180,7 +180,7 @@ int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device * dev,
+ 	default:
+ 		printk("\nThe specified interrupt logic does not exist\n");
+ 		return -EINVAL;
+-	}			//switch(data[1]);
++	}			/* switch(data[1]); */
+ 
+ 	i_Logic = data[1];
+ 	for (i_Count = i_MaxChannel, i = 0; i_Count > 0; i_Count--, i++) {
+@@ -224,8 +224,8 @@ int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device * dev,
+ 		default:
+ 			printk("\nThe option indicated in the event mask does not exist\n");
+ 			return -EINVAL;
+-		}		// switch(i_EventMask)
+-	}			//for (i_Count = i_MaxChannel; i_Count >0;i_Count --)
++		}		/*  switch(i_EventMask) */
++	}			/* for (i_Count = i_MaxChannel; i_Count >0;i_Count --) */
+ 
+ 	if (data[0] == 1) {
+ 		    /****************************/
+@@ -247,7 +247,7 @@ int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device * dev,
+ 			      /********************************************/
+ 				printk("\nTransition error on an OR PRIORITY logic\n");
+ 				return -EINVAL;
+-			}	// if (data[1]== APCI1500_OR_PRIORITY && i_PatternTransition != 0)
++			}	/*  if (data[1]== APCI1500_OR_PRIORITY && i_PatternTransition != 0) */
+ 
+ 		       /*************************************/
+ 			/* Tests if more than one transition */
+@@ -261,7 +261,7 @@ int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device * dev,
+ 						((i_PatternTransition >>
+ 							i_Count) & 0x1);
+ 
+-				}	//for (i_Count = 0; i_Count < 8; i_Count++)
++				}	/* for (i_Count = 0; i_Count < 8; i_Count++) */
+ 
+ 				if (i_PatternTransitionCount > 1) {
+ 				  /****************************************/
+@@ -269,8 +269,8 @@ int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device * dev,
+ 				  /****************************************/
+ 					printk("\n Transition error on an AND logic\n");
+ 					return -EINVAL;
+-				}	// if (i_PatternTransitionCount > 1)
+-			}	// if (data[1]== APCI1500_AND)
++				}	/*  if (i_PatternTransitionCount > 1) */
++			}	/*  if (data[1]== APCI1500_AND) */
+ 
+ 			    /*****************************************************************/
+ 			/* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+@@ -359,12 +359,12 @@ int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device * dev,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-		}		// if(data[1]==APCI1500_AND||data[1]==APCI1500_OR||data[1]==APCI1500_OR_PRIORITY)
++		}		/*  if(data[1]==APCI1500_AND||data[1]==APCI1500_OR||data[1]==APCI1500_OR_PRIORITY) */
+ 		else {
+ 			printk("\nThe choice for interrupt logic does not exist\n");
+ 			return -EINVAL;
+-		}		// else }// if(data[1]==APCI1500_AND||data[1]==APCI1500_OR||data[1]==APCI1500_OR_PRIORITY)
+-	}			//   if (data[0]== 1)
++		}		/*  else }// if(data[1]==APCI1500_AND||data[1]==APCI1500_OR||data[1]==APCI1500_OR_PRIORITY) */
++	}			/*    if (data[0]== 1) */
+ 
+ 		 /************************************/
+ 	/* Test if event setting for port 2 */
+@@ -487,12 +487,12 @@ int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device * dev,
+ 			outb(0xF4,
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+-		}		//  if (data[1] == APCI1500_OR)
++		}		/*   if (data[1] == APCI1500_OR) */
+ 		else {
+ 			printk("\nThe choice for interrupt logic does not exist\n");
+ 			return -EINVAL;
+-		}		//elseif (data[1] == APCI1500_OR)
+-	}			//if(data[0]==2)
++		}		/* elseif (data[1] == APCI1500_OR) */
++	}			/* if(data[0]==2) */
+ 
+ 	return insn->n;
+ }
+@@ -589,12 +589,12 @@ int i_APCI1500_StartStopInputEvent(struct comedi_device * dev, struct comedi_sub
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				}	// if(i_Event1Status==1)
++				}	/*  if(i_Event1Status==1) */
+ 				else {
+ 					printk("\nEvent 1 not initialised\n");
+ 					return -EINVAL;
+-				}	//else if(i_Event1Status==1)
+-			}	//if (data[1]==1)
++				}	/* else if(i_Event1Status==1) */
++			}	/* if (data[1]==1) */
+ 			if (data[1] == 2) {
+ 
+ 				if (i_Event2Status == 1) {
+@@ -640,17 +640,17 @@ int i_APCI1500_StartStopInputEvent(struct comedi_device * dev, struct comedi_sub
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+ 					i_Event2InterruptStatus = 1;
+-				}	// if(i_Event2Status==1)
++				}	/*  if(i_Event2Status==1) */
+ 				else {
+ 					printk("\nEvent 2 not initialised\n");
+ 					return -EINVAL;
+-				}	//else if(i_Event2Status==1)
+-			}	// if(data[1]==2)
+-		}		// if (data[1] == 1 || data[0] == 2)
++				}	/* else if(i_Event2Status==1) */
++			}	/*  if(data[1]==2) */
++		}		/*  if (data[1] == 1 || data[0] == 2) */
+ 		else {
+ 			printk("\nThe port parameter is in error\n");
+ 			return -EINVAL;
+-		}		//else if (data[1] == 1 || data[0] == 2)
++		}		/* else if (data[1] == 1 || data[0] == 2) */
+ 
+ 		break;
+ 
+@@ -701,12 +701,12 @@ int i_APCI1500_StartStopInputEvent(struct comedi_device * dev, struct comedi_sub
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+ 					i_Event1InterruptStatus = 0;
+-				}	// if(i_Event1Status==1)
++				}	/*  if(i_Event1Status==1) */
+ 				else {
+ 					printk("\nEvent 1 not initialised\n");
+ 					return -EINVAL;
+-				}	//else if(i_Event1Status==1)
+-			}	//if (data[1]==1)
++				}	/* else if(i_Event1Status==1) */
++			}	/* if (data[1]==1) */
+ 			if (data[1] == 2) {
+ 			 /*****************************/
+ 				/* Test if event initialised */
+@@ -744,23 +744,23 @@ int i_APCI1500_StartStopInputEvent(struct comedi_device * dev, struct comedi_sub
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+ 					i_Event2InterruptStatus = 0;
+-				}	// if(i_Event2Status==1)
++				}	/*  if(i_Event2Status==1) */
+ 				else {
+ 					printk("\nEvent 2 not initialised\n");
+ 					return -EINVAL;
+-				}	//else if(i_Event2Status==1)
+-			}	//if(data[1]==2)
++				}	/* else if(i_Event2Status==1) */
++			}	/* if(data[1]==2) */
+ 
+-		}		// if (data[1] == 1 || data[1] == 2)
++		}		/*  if (data[1] == 1 || data[1] == 2) */
+ 		else {
+ 			printk("\nThe port parameter is in error\n");
+ 			return -EINVAL;
+-		}		//else if (data[1] == 1 || data[1] == 2)
++		}		/* else if (data[1] == 1 || data[1] == 2) */
+ 		break;
+ 	default:
+ 		printk("\nThe option of START/STOP logic does not exist\n");
+ 		return -EINVAL;
+-	}			//switch(data[0])
++	}			/* switch(data[0]) */
+ 
+ 	return insn->n;
+ }
+@@ -973,11 +973,11 @@ int i_APCI1500_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ 				(unsigned int) inw(devpriv->i_IobaseAddon +
+ 				APCI1500_DIGITAL_IP);
+ 			*data = (ui_TmpValue >> ui_Channel) & 0x1;
+-		}		//if(ui_Channel >= 0 && ui_Channel <=15)
++		}		/* if(ui_Channel >= 0 && ui_Channel <=15) */
+ 		else {
+ 			printk("\nThe channel specification are in error\n");
+-			return -EINVAL;	// "sorry channel spec wrong "
+-		}		//else if(ui_Channel >= 0 && ui_Channel <=15)
++			return -EINVAL;	/*  "sorry channel spec wrong " */
++		}		/* else if(ui_Channel >= 0 && ui_Channel <=15) */
+ 		break;
+ 	case 1:
+ 
+@@ -1001,14 +1001,14 @@ int i_APCI1500_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ 
+ 		default:
+ 			printk("\nSpecified channel cannot be read \n");
+-			return -EINVAL;	// "sorry channel spec wrong "
++			return -EINVAL;	/*  "sorry channel spec wrong " */
+ 			break;
+-		}		//switch(ui_Channel)
++		}		/* switch(ui_Channel) */
+ 		break;
+ 	default:
+ 		printk("\nThe specified functionality does not exist\n");
+ 		return -EINVAL;
+-	}			//switch(data[0])
++	}			/* switch(data[0]) */
+ 	return insn->n;
+ }
+ 
+@@ -1073,18 +1073,18 @@ int i_APCI1500_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 	static unsigned int ui_Temp = 0;
+ 	unsigned int ui_Temp1;
+ 
+-	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
++	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	/*  get the channel */
+ 
+ 	if (!devpriv->b_OutputMemoryStatus) {
+ 		ui_Temp = 0;
+ 
+-	}			//if(!devpriv->b_OutputMemoryStatus )
++	}			/* if(!devpriv->b_OutputMemoryStatus ) */
+ 	if (data[3] == 0) {
+ 		if (data[1] == 0) {
+ 			data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
+ 			outw(data[0],
+ 				devpriv->i_IobaseAddon + APCI1500_DIGITAL_OP);
+-		}		//if(data[1]==0)
++		}		/* if(data[1]==0) */
+ 		else {
+ 			if (data[1] == 1) {
+ 				switch (ui_NoOfChannel) {
+@@ -1113,19 +1113,19 @@ int i_APCI1500_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 
+ 				default:
+ 					comedi_error(dev, " chan spec wrong");
+-					return -EINVAL;	// "sorry channel spec wrong "
++					return -EINVAL;	/*  "sorry channel spec wrong " */
+ 
+-				}	//switch(ui_NoOfChannels)
++				}	/* switch(ui_NoOfChannels) */
+ 
+ 				outw(data[0],
+ 					devpriv->i_IobaseAddon +
+ 					APCI1500_DIGITAL_OP);
+-			}	// if(data[1]==1)
++			}	/*  if(data[1]==1) */
+ 			else {
+ 				printk("\nSpecified channel not supported\n");
+-			}	//else if(data[1]==1)
+-		}		//elseif(data[1]==0)
+-	}			//if(data[3]==0)
++			}	/* else if(data[1]==1) */
++		}		/* elseif(data[1]==0) */
++	}			/* if(data[3]==0) */
+ 	else {
+ 		if (data[3] == 1) {
+ 			if (data[1] == 0) {
+@@ -1140,7 +1140,7 @@ int i_APCI1500_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 				outw(data[0],
+ 					devpriv->i_IobaseAddon +
+ 					APCI1500_DIGITAL_OP);
+-			}	//if(data[1]==0)
++			}	/* if(data[1]==0) */
+ 			else {
+ 				if (data[1] == 1) {
+ 					switch (ui_NoOfChannel) {
+@@ -1190,24 +1190,24 @@ int i_APCI1500_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ 					default:
+ 						comedi_error(dev,
+ 							" chan spec wrong");
+-						return -EINVAL;	// "sorry channel spec wrong "
++						return -EINVAL;	/*  "sorry channel spec wrong " */
+ 
+-					}	//switch(ui_NoOfChannels)
++					}	/* switch(ui_NoOfChannels) */
+ 
+ 					outw(data[0],
+ 						devpriv->i_IobaseAddon +
+ 						APCI1500_DIGITAL_OP);
+-				}	// if(data[1]==1)
++				}	/*  if(data[1]==1) */
+ 				else {
+ 					printk("\nSpecified channel not supported\n");
+-				}	//else if(data[1]==1)
+-			}	//elseif(data[1]==0)
+-		}		//if(data[3]==1);
++				}	/* else if(data[1]==1) */
++			}	/* elseif(data[1]==0) */
++		}		/* if(data[3]==1); */
+ 		else {
+ 			printk("\nSpecified functionality does not exist\n");
+ 			return -EINVAL;
+-		}		//if else data[3]==1)
+-	}			//if else data[3]==0)
++		}		/* if else data[3]==1) */
++	}			/* if else data[3]==0) */
+ 	ui_Temp = data[0];
+ 	return (insn->n);;
+ }
+@@ -1268,20 +1268,20 @@ int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device * dev,
+ 
+ 	devpriv->tsk_Current = current;
+ 
+-//Selection of the input clock
++/* Selection of the input clock */
+ 	if (data[0] == 0 || data[0] == 1 || data[0] == 2) {
+ 		outw(data[0], devpriv->i_IobaseAddon + APCI1500_CLK_SELECT);
+-	}			// if(data[0]==0||data[0]==1||data[0]==2)
++	}			/*  if(data[0]==0||data[0]==1||data[0]==2) */
+ 	else {
+ 		if (data[0] != 3) {
+ 			printk("\nThe option for input clock selection does not exist\n");
+ 			return -EINVAL;
+-		}		// if(data[0]!=3)
+-	}			//elseif(data[0]==0||data[0]==1||data[0]==2)
+-	//Select the counter/timer
++		}		/*  if(data[0]!=3) */
++	}			/* elseif(data[0]==0||data[0]==1||data[0]==2) */
++	/* Select the counter/timer */
+ 	switch (data[1]) {
+ 	case COUNTER1:
+-		//selecting counter or timer
++		/* selecting counter or timer */
+ 		switch (data[2]) {
+ 		case 0:
+ 			data[2] = APCI1500_COUNTER;
+@@ -1292,9 +1292,9 @@ int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device * dev,
+ 		default:
+ 			printk("\nThis choice is not a timer nor a counter\n");
+ 			return -EINVAL;
+-		}		// switch(data[2])
++		}		/*  switch(data[2]) */
+ 
+-		//Selecting  single or continuous mode
++		/* Selecting  single or continuous mode */
+ 		switch (data[4]) {
+ 		case 0:
+ 			data[4] = APCI1500_CONTINUOUS;
+@@ -1305,7 +1305,7 @@ int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device * dev,
+ 		default:
+ 			printk("\nThis option for single/continuous mode does not exist\n");
+ 			return -EINVAL;
+-		}		// switch(data[4])
++		}		/*  switch(data[4]) */
+ 
+ 		i_TimerCounterMode = data[2] | data[4] | 7;
+ 			 /*************************/
+@@ -1428,21 +1428,21 @@ int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device * dev,
+ 				outb(0x2,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+-			}	//if(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE)
++			}	/* if(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) */
+ 			else {
+ 				printk("\nError in selection of interrupt enable or disable\n");
+ 				return -EINVAL;
+-			}	//elseif(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE)
+-		}		// if ((data[3]>= 0) && (data[3] <= 65535))
++			}	/* elseif(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) */
++		}		/*  if ((data[3]>= 0) && (data[3] <= 65535)) */
+ 		else {
+ 			printk("\nError in selection of reload value\n");
+ 			return -EINVAL;
+-		}		//else if ((data[3]>= 0) && (data[3] <= 65535))
++		}		/* else if ((data[3]>= 0) && (data[3] <= 65535)) */
+ 		i_TimerCounterWatchdogInterrupt = data[7];
+ 		i_TimerCounter1Init = 1;
+ 		break;
+ 
+-	case COUNTER2:		//selecting counter or timer
++	case COUNTER2:		/* selecting counter or timer */
+ 		switch (data[2]) {
+ 		case 0:
+ 			data[2] = APCI1500_COUNTER;
+@@ -1453,9 +1453,9 @@ int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device * dev,
+ 		default:
+ 			printk("\nThis choice is not a timer nor a counter\n");
+ 			return -EINVAL;
+-		}		// switch(data[2])
++		}		/*  switch(data[2]) */
+ 
+-		//Selecting  single or continuous mode
++		/* Selecting  single or continuous mode */
+ 		switch (data[4]) {
+ 		case 0:
+ 			data[4] = APCI1500_CONTINUOUS;
+@@ -1466,9 +1466,9 @@ int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device * dev,
+ 		default:
+ 			printk("\nThis option for single/continuous mode does not exist\n");
+ 			return -EINVAL;
+-		}		// switch(data[4])
++		}		/*  switch(data[4]) */
+ 
+-		//Selecting  software or hardware trigger
++		/* Selecting  software or hardware trigger */
+ 		switch (data[5]) {
+ 		case 0:
+ 			data[5] = APCI1500_SOFTWARE_TRIGGER;
+@@ -1479,9 +1479,9 @@ int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device * dev,
+ 		default:
+ 			printk("\nThis choice for software or hardware trigger does not exist\n");
+ 			return -EINVAL;
+-		}		// switch(data[5])
++		}		/*  switch(data[5]) */
+ 
+-		//Selecting  software or hardware gate
++		/* Selecting  software or hardware gate */
+ 		switch (data[6]) {
+ 		case 0:
+ 			data[6] = APCI1500_SOFTWARE_GATE;
+@@ -1492,7 +1492,7 @@ int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device * dev,
+ 		default:
+ 			printk("\nThis choice for software or hardware gate does not exist\n");
+ 			return -EINVAL;
+-		}		// switch(data[6])
++		}		/*  switch(data[6]) */
+ 
+ 		i_TimerCounterMode = data[2] | data[4] | data[5] | data[6] | 7;
+ 
+@@ -1616,21 +1616,21 @@ int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device * dev,
+ 				outb(0x2,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+-			}	//if(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE)
++			}	/* if(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) */
+ 			else {
+ 				printk("\nError in selection of interrupt enable or disable\n");
+ 				return -EINVAL;
+-			}	//elseif(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE)
+-		}		// if ((data[3]>= 0) && (data[3] <= 65535))
++			}	/* elseif(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) */
++		}		/*  if ((data[3]>= 0) && (data[3] <= 65535)) */
+ 		else {
+ 			printk("\nError in selection of reload value\n");
+ 			return -EINVAL;
+-		}		//else if ((data[3]>= 0) && (data[3] <= 65535))
++		}		/* else if ((data[3]>= 0) && (data[3] <= 65535)) */
+ 		i_TimerCounterWatchdogInterrupt = data[7];
+ 		i_TimerCounter2Init = 1;
+ 		break;
+ 
+-	case COUNTER3:		//selecting counter or watchdog
++	case COUNTER3:		/* selecting counter or watchdog */
+ 		switch (data[2]) {
+ 		case 0:
+ 			data[2] = APCI1500_COUNTER;
+@@ -1641,9 +1641,9 @@ int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device * dev,
+ 		default:
+ 			printk("\nThis choice is not a watchdog nor a counter\n");
+ 			return -EINVAL;
+-		}		// switch(data[2])
++		}		/*  switch(data[2]) */
+ 
+-		//Selecting  single or continuous mode
++		/* Selecting  single or continuous mode */
+ 		switch (data[4]) {
+ 		case 0:
+ 			data[4] = APCI1500_CONTINUOUS;
+@@ -1654,9 +1654,9 @@ int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device * dev,
+ 		default:
+ 			printk("\nThis option for single/continuous mode does not exist\n");
+ 			return -EINVAL;
+-		}		// switch(data[4])
++		}		/*  switch(data[4]) */
+ 
+-		//Selecting  software or hardware gate
++		/* Selecting  software or hardware gate */
+ 		switch (data[6]) {
+ 		case 0:
+ 			data[6] = APCI1500_SOFTWARE_GATE;
+@@ -1667,7 +1667,7 @@ int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device * dev,
+ 		default:
+ 			printk("\nThis choice for software or hardware gate does not exist\n");
+ 			return -EINVAL;
+-		}		// switch(data[6])
++		}		/*  switch(data[6]) */
+ 
+ 		      /*****************************/
+ 		/* Test if used for watchdog */
+@@ -1680,10 +1680,10 @@ int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device * dev,
+ 			/* - Pulses output           */
+ 			     /*****************************/
+ 			i_TimerCounterMode = data[2] | data[4] | 0x54;
+-		}		//if (data[2] == APCI1500_WATCHDOG)
++		}		/* if (data[2] == APCI1500_WATCHDOG) */
+ 		else {
+ 			i_TimerCounterMode = data[2] | data[4] | data[6] | 7;
+-		}		//elseif (data[2] == APCI1500_WATCHDOG)
++		}		/* elseif (data[2] == APCI1500_WATCHDOG) */
+ 				 /*************************/
+ 		/* Test the reload value */
+ 			     /*************************/
+@@ -1809,25 +1809,25 @@ int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device * dev,
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-				}	//elseif(data[2]==APCI1500_COUNTER)
++				}	/* elseif(data[2]==APCI1500_COUNTER) */
+ 
+-			}	//if(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE)
++			}	/* if(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) */
+ 			else {
+ 				printk("\nError in selection of interrupt enable or disable\n");
+ 				return -EINVAL;
+-			}	//elseif(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE)
+-		}		// if ((data[3]>= 0) && (data[3] <= 65535))
++			}	/* elseif(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) */
++		}		/*  if ((data[3]>= 0) && (data[3] <= 65535)) */
+ 		else {
+ 			printk("\nError in selection of reload value\n");
+ 			return -EINVAL;
+-		}		//else if ((data[3]>= 0) && (data[3] <= 65535))
++		}		/* else if ((data[3]>= 0) && (data[3] <= 65535)) */
+ 		i_TimerCounterWatchdogInterrupt = data[7];
+ 		i_WatchdogCounter3Init = 1;
+ 		break;
+ 
+ 	default:
+ 		printk("\nThe specified counter\timer option does not exist\n");
+-	}			//switch(data[1])
++	}			/* switch(data[1]) */
+ 	i_CounterLogic = data[2];
+ 	return insn->n;
+ }
+@@ -1871,11 +1871,11 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+ 		case START:
+ 			if (i_TimerCounter1Init == 1) {
+ 				if (i_TimerCounterWatchdogInterrupt == 1) {
+-					i_CommandAndStatusValue = 0xC4;	//Enable the interrupt
+-				}	// if(i_TimerCounterWatchdogInterrupt==1)
++					i_CommandAndStatusValue = 0xC4;	/* Enable the interrupt */
++				}	/*  if(i_TimerCounterWatchdogInterrupt==1) */
+ 				else {
+-					i_CommandAndStatusValue = 0xE4;	//disable the interrupt
+-				}	//elseif(i_TimerCounterWatchdogInterrupt==1)
++					i_CommandAndStatusValue = 0xE4;	/* disable the interrupt */
++				}	/* elseif(i_TimerCounterWatchdogInterrupt==1) */
+ 					      /**************************/
+ 				/* Starts timer/counter 1 */
+ 					      /**************************/
+@@ -1889,7 +1889,7 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+ 				outb(i_CommandAndStatusValue,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+-			}	//if( i_TimerCounter1Init==1)
++			}	/* if( i_TimerCounter1Init==1) */
+ 			else {
+ 				printk("\nCounter/Timer1 not configured\n");
+ 				return -EINVAL;
+@@ -1922,14 +1922,14 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+ 						 /************************/
+ 
+ 					i_CommandAndStatusValue = 0x6;
+-				}	//if( i_TimerCounter1Enabled==1)
++				}	/* if( i_TimerCounter1Enabled==1) */
+ 				else {
+ 						   /***************/
+ 					/* Set Trigger */
+ 						   /***************/
+ 
+ 					i_CommandAndStatusValue = 0x2;
+-				}	//elseif(i_TimerCounter1Enabled==1)
++				}	/* elseif(i_TimerCounter1Enabled==1) */
+ 
+ 						/********************************************/
+ 				/* Selects the commands and status register */
+@@ -1940,7 +1940,7 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+ 				outb(i_CommandAndStatusValue,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+-			}	//if( i_TimerCounter1Init==1)
++			}	/* if( i_TimerCounter1Init==1) */
+ 			else {
+ 				printk("\nCounter/Timer1 not configured\n");
+ 				return -EINVAL;
+@@ -1950,7 +1950,7 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+ 		default:
+ 			printk("\nThe specified option for start/stop/trigger does not exist\n");
+ 			return -EINVAL;
+-		}		//switch(data[1])
++		}		/* switch(data[1]) */
+ 		break;
+ 
+ 	case COUNTER2:
+@@ -1958,11 +1958,11 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+ 		case START:
+ 			if (i_TimerCounter2Init == 1) {
+ 				if (i_TimerCounterWatchdogInterrupt == 1) {
+-					i_CommandAndStatusValue = 0xC4;	//Enable the interrupt
+-				}	// if(i_TimerCounterWatchdogInterrupt==1)
++					i_CommandAndStatusValue = 0xC4;	/* Enable the interrupt */
++				}	/*  if(i_TimerCounterWatchdogInterrupt==1) */
+ 				else {
+-					i_CommandAndStatusValue = 0xE4;	//disable the interrupt
+-				}	//elseif(i_TimerCounterWatchdogInterrupt==1)
++					i_CommandAndStatusValue = 0xE4;	/* disable the interrupt */
++				}	/* elseif(i_TimerCounterWatchdogInterrupt==1) */
+ 					      /**************************/
+ 				/* Starts timer/counter 2 */
+ 					      /**************************/
+@@ -1976,7 +1976,7 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+ 				outb(i_CommandAndStatusValue,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+-			}	//if( i_TimerCounter2Init==1)
++			}	/* if( i_TimerCounter2Init==1) */
+ 			else {
+ 				printk("\nCounter/Timer2 not configured\n");
+ 				return -EINVAL;
+@@ -2008,14 +2008,14 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+ 						 /************************/
+ 
+ 					i_CommandAndStatusValue = 0x6;
+-				}	//if( i_TimerCounter2Enabled==1)
++				}	/* if( i_TimerCounter2Enabled==1) */
+ 				else {
+ 						   /***************/
+ 					/* Set Trigger */
+ 						   /***************/
+ 
+ 					i_CommandAndStatusValue = 0x2;
+-				}	//elseif(i_TimerCounter2Enabled==1)
++				}	/* elseif(i_TimerCounter2Enabled==1) */
+ 
+ 						/********************************************/
+ 				/* Selects the commands and status register */
+@@ -2026,7 +2026,7 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+ 				outb(i_CommandAndStatusValue,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+-			}	//if( i_TimerCounter2Init==1)
++			}	/* if( i_TimerCounter2Init==1) */
+ 			else {
+ 				printk("\nCounter/Timer2 not configured\n");
+ 				return -EINVAL;
+@@ -2035,7 +2035,7 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+ 		default:
+ 			printk("\nThe specified option for start/stop/trigger does not exist\n");
+ 			return -EINVAL;
+-		}		//switch(data[1])
++		}		/* switch(data[1]) */
+ 		break;
+ 	case COUNTER3:
+ 		switch (data[1]) {
+@@ -2043,11 +2043,11 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+ 			if (i_WatchdogCounter3Init == 1) {
+ 
+ 				if (i_TimerCounterWatchdogInterrupt == 1) {
+-					i_CommandAndStatusValue = 0xC4;	//Enable the interrupt
+-				}	// if(i_TimerCounterWatchdogInterrupt==1)
++					i_CommandAndStatusValue = 0xC4;	/* Enable the interrupt */
++				}	/*  if(i_TimerCounterWatchdogInterrupt==1) */
+ 				else {
+-					i_CommandAndStatusValue = 0xE4;	//disable the interrupt
+-				}	//elseif(i_TimerCounterWatchdogInterrupt==1)
++					i_CommandAndStatusValue = 0xE4;	/* disable the interrupt */
++				}	/* elseif(i_TimerCounterWatchdogInterrupt==1) */
+ 					      /**************************/
+ 				/* Starts Watchdog/counter 3 */
+ 					      /**************************/
+@@ -2062,7 +2062,7 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+ 					devpriv->iobase +
+ 					APCI1500_Z8536_CONTROL_REGISTER);
+ 
+-			}	// if( i_WatchdogCounter3init==1)
++			}	/*  if( i_WatchdogCounter3init==1) */
+ 			else {
+ 				printk("\nWatchdog/Counter3 not configured\n");
+ 				return -EINVAL;
+@@ -2089,7 +2089,7 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+ 
+ 		case TRIGGER:
+ 			switch (data[2]) {
+-			case 0:	//triggering counter 3
++			case 0:	/* triggering counter 3 */
+ 				if (i_WatchdogCounter3Init == 1) {
+ 					if (i_WatchdogCounter3Enabled == 1) {
+ 							       /************************/
+@@ -2097,14 +2097,14 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+ 							       /************************/
+ 
+ 						i_CommandAndStatusValue = 0x6;
+-					}	//if( i_WatchdogCounter3Enabled==1)
++					}	/* if( i_WatchdogCounter3Enabled==1) */
+ 					else {
+ 							   /***************/
+ 						/* Set Trigger */
+ 							   /***************/
+ 
+ 						i_CommandAndStatusValue = 0x2;
+-					}	//elseif(i_WatchdogCounter3Enabled==1)
++					}	/* elseif(i_WatchdogCounter3Enabled==1) */
+ 
+ 						/********************************************/
+ 					/* Selects the commands and status register */
+@@ -2115,14 +2115,14 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+ 					outb(i_CommandAndStatusValue,
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+-				}	//if( i_WatchdogCounter3Init==1)
++				}	/* if( i_WatchdogCounter3Init==1) */
+ 				else {
+ 					printk("\nCounter3 not configured\n");
+ 					return -EINVAL;
+ 				}
+ 				break;
+ 			case 1:
+-				//triggering Watchdog 3
++				/* triggering Watchdog 3 */
+ 				if (i_WatchdogCounter3Init == 1) {
+ 
+ 						/********************************************/
+@@ -2134,7 +2134,7 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+ 					outb(0x6,
+ 						devpriv->iobase +
+ 						APCI1500_Z8536_CONTROL_REGISTER);
+-				}	//if( i_WatchdogCounter3Init==1)
++				}	/* if( i_WatchdogCounter3Init==1) */
+ 				else {
+ 					printk("\nWatchdog 3 not configured\n");
+ 					return -EINVAL;
+@@ -2143,17 +2143,17 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+ 			default:
+ 				printk("\nWrong choice of watchdog/counter3\n");
+ 				return -EINVAL;
+-			}	//switch(data[2])
++			}	/* switch(data[2]) */
+ 			break;
+ 		default:
+ 			printk("\nThe specified option for start/stop/trigger does not exist\n");
+ 			return -EINVAL;
+-		}		//switch(data[1])
++		}		/* switch(data[1]) */
+ 		break;
+ 	default:
+ 		printk("\nThe specified choice for counter/watchdog/timer does not exist\n");
+ 		return -EINVAL;
+-	}			//switch(data[0])
++	}			/* switch(data[0]) */
+ 	return insn->n;
+ }
+ 
+@@ -2188,7 +2188,7 @@ int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device * dev,
+ 	int i_CommandAndStatusValue;
+ 	switch (data[0]) {
+ 	case COUNTER1:
+-		//Read counter/timer1
++		/* Read counter/timer1 */
+ 		if (i_TimerCounter1Init == 1) {
+ 			if (i_TimerCounter1Enabled == 1) {
+ 		  /************************/
+@@ -2196,14 +2196,14 @@ int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device * dev,
+ 		  /************************/
+ 
+ 				i_CommandAndStatusValue = 0xC;
+-			}	//if( i_TimerCounter1Init==1)
++			}	/* if( i_TimerCounter1Init==1) */
+ 			else {
+ 		    /***************/
+ 				/* Set RCC */
+ 		    /***************/
+ 
+ 				i_CommandAndStatusValue = 0x8;
+-			}	//elseif(i_TimerCounter1Init==1)
++			}	/* elseif(i_TimerCounter1Init==1) */
+ 
+ 		/********************************************/
+ 			/* Selects the commands and status register */
+@@ -2232,14 +2232,14 @@ int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device * dev,
+ 			data[0] =
+ 				data[0] | inb(devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+-		}		//if( i_TimerCounter1Init==1)
++		}		/* if( i_TimerCounter1Init==1) */
+ 		else {
+ 			printk("\nTimer/Counter1 not configured\n");
+ 			return -EINVAL;
+-		}		//elseif( i_TimerCounter1Init==1)
++		}		/* elseif( i_TimerCounter1Init==1) */
+ 		break;
+ 	case COUNTER2:
+-		//Read counter/timer2
++		/* Read counter/timer2 */
+ 		if (i_TimerCounter2Init == 1) {
+ 			if (i_TimerCounter2Enabled == 1) {
+ 		  /************************/
+@@ -2247,14 +2247,14 @@ int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device * dev,
+ 		  /************************/
+ 
+ 				i_CommandAndStatusValue = 0xC;
+-			}	//if( i_TimerCounter2Init==1)
++			}	/* if( i_TimerCounter2Init==1) */
+ 			else {
+ 		    /***************/
+ 				/* Set RCC */
+ 		    /***************/
+ 
+ 				i_CommandAndStatusValue = 0x8;
+-			}	//elseif(i_TimerCounter2Init==1)
++			}	/* elseif(i_TimerCounter2Init==1) */
+ 
+ 		/********************************************/
+ 			/* Selects the commands and status register */
+@@ -2283,14 +2283,14 @@ int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device * dev,
+ 			data[0] =
+ 				data[0] | inb(devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+-		}		//if( i_TimerCounter2Init==1)
++		}		/* if( i_TimerCounter2Init==1) */
+ 		else {
+ 			printk("\nTimer/Counter2 not configured\n");
+ 			return -EINVAL;
+-		}		//elseif( i_TimerCounter2Init==1)
++		}		/* elseif( i_TimerCounter2Init==1) */
+ 		break;
+ 	case COUNTER3:
+-		//Read counter/watchdog2
++		/* Read counter/watchdog2 */
+ 		if (i_WatchdogCounter3Init == 1) {
+ 			if (i_WatchdogCounter3Enabled == 1) {
+ 		  /************************/
+@@ -2298,14 +2298,14 @@ int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device * dev,
+ 		  /************************/
+ 
+ 				i_CommandAndStatusValue = 0xC;
+-			}	//if( i_TimerCounter2Init==1)
++			}	/* if( i_TimerCounter2Init==1) */
+ 			else {
+ 		    /***************/
+ 				/* Set RCC */
+ 		    /***************/
+ 
+ 				i_CommandAndStatusValue = 0x8;
+-			}	//elseif(i_WatchdogCounter3Init==1)
++			}	/* elseif(i_WatchdogCounter3Init==1) */
+ 
+ 		/********************************************/
+ 			/* Selects the commands and status register */
+@@ -2334,16 +2334,16 @@ int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device * dev,
+ 			data[0] =
+ 				data[0] | inb(devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+-		}		//if( i_WatchdogCounter3Init==1)
++		}		/* if( i_WatchdogCounter3Init==1) */
+ 		else {
+ 			printk("\nWatchdogCounter3 not configured\n");
+ 			return -EINVAL;
+-		}		//elseif( i_WatchdogCounter3Init==1)
++		}		/* elseif( i_WatchdogCounter3Init==1) */
+ 		break;
+ 	default:
+ 		printk("\nThe choice of timer/counter/watchdog does not exist\n");
+ 		return -EINVAL;
+-	}			//switch(data[0])
++	}			/* switch(data[0]) */
+ 
+ 	return insn->n;
+ }
+@@ -2411,16 +2411,16 @@ int i_APCI1500_ConfigureInterrupt(struct comedi_device * dev, struct comedi_subd
+ 	outl(0x0, devpriv->i_IobaseAmcc + 0x38);
+ 	if (data[0] == 1) {
+ 		i_Constant = 0xC0;
+-	}			//if(data[0]==1)
++	}			/* if(data[0]==1) */
+ 	else {
+ 		if (data[0] == 0) {
+ 			i_Constant = 0x00;
+-		}		//if{data[0]==0)
++		}		/* if{data[0]==0) */
+ 		else {
+ 			printk("\nThe parameter passed to driver is in error for enabling the voltage interrupt\n");
+ 			return -EINVAL;
+-		}		//else if(data[0]==0)
+-	}			//elseif(data[0]==1)
++		}		/* else if(data[0]==0) */
++	}			/* elseif(data[0]==1) */
+ 
+ 	 /*****************************************************/
+ 	/* Selects the mode specification register of port B */
+@@ -2599,11 +2599,11 @@ static void v_APCI1500_Interrupt(int irq, void *d)
+       /*************************************************/
+ 		/* Selects the master interrupt control register */
+       /*************************************************/
+-		//outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER);
++		/* outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); */
+ 	/**********************************************/
+ 		/* Disables  the main interrupt on the board */
+ 	/**********************************************/
+-		//outb(0x00,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER);
++		/* outb(0x00,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); */
+ 
+    /*****************************************************/
+ 		/* Selects the command and status register of port A */
+@@ -2647,11 +2647,11 @@ static void v_APCI1500_Interrupt(int irq, void *d)
+ 
+ 				i_InputChannel = 1 + (i_RegValue >> 1);
+ 
+-			}	// if(i_Logic==APCI1500_OR_PRIORITY)
++			}	/*  if(i_Logic==APCI1500_OR_PRIORITY) */
+ 			else {
+ 				i_InputChannel = 0;
+-			}	//elseif(i_Logic==APCI1500_OR_PRIORITY)
+-		}		// if ((i_RegValue & 0x60) == 0x60)
++			}	/* elseif(i_Logic==APCI1500_OR_PRIORITY) */
++		}		/*  if ((i_RegValue & 0x60) == 0x60) */
+ 
+ 	   /*****************************************************/
+ 		/* Selects the command and status register of port B */
+@@ -2688,7 +2688,7 @@ static void v_APCI1500_Interrupt(int irq, void *d)
+ 	      /**************************************/
+ 
+ 			if (i_RegValue) {
+-				//Disable the interrupt
++				/* Disable the interrupt */
+ 		     /*****************************************************/
+ 				/* Selects the command and status register of port B */
+ 		     /*****************************************************/
+@@ -2697,17 +2697,17 @@ static void v_APCI1500_Interrupt(int irq, void *d)
+ 				if (i_RegValue & 0x80) {
+ 					i_InterruptMask =
+ 						i_InterruptMask | 0x40;
+-				}	//if (i_RegValue & 0x80)
++				}	/* if (i_RegValue & 0x80) */
+ 
+ 				if (i_RegValue & 0x40) {
+ 					i_InterruptMask =
+ 						i_InterruptMask | 0x80;
+-				}	//if (i_RegValue & 0x40)
+-			}	// if (i_RegValue)
++				}	/* if (i_RegValue & 0x40) */
++			}	/*  if (i_RegValue) */
+ 			else {
+ 				i_InterruptMask = i_InterruptMask | 2;
+-			}	// if (i_RegValue)
+-		}		//if ((i_RegValue & 0x60) == 0x60)
++			}	/*  if (i_RegValue) */
++		}		/* if ((i_RegValue & 0x60) == 0x60) */
+ 
+ 		/*****************************************************/
+ 		/* Selects the command and status register of timer 1 */
+@@ -2731,7 +2731,7 @@ static void v_APCI1500_Interrupt(int irq, void *d)
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+ 			i_InterruptMask = i_InterruptMask | 4;
+-		}		// if ((i_RegValue & 0x60) == 0x60)
++		}		/*  if ((i_RegValue & 0x60) == 0x60) */
+ 		/*****************************************************/
+ 		/* Selects the command and status register of timer 2 */
+ 		/*****************************************************/
+@@ -2754,7 +2754,7 @@ static void v_APCI1500_Interrupt(int irq, void *d)
+ 				devpriv->iobase +
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+ 			i_InterruptMask = i_InterruptMask | 8;
+-		}		// if ((i_RegValue & 0x60) == 0x60)
++		}		/*  if ((i_RegValue & 0x60) == 0x60) */
+ 
+ 		/*****************************************************/
+ 		/* Selects the command and status register of timer 3 */
+@@ -2779,13 +2779,13 @@ static void v_APCI1500_Interrupt(int irq, void *d)
+ 				APCI1500_Z8536_CONTROL_REGISTER);
+ 			if (i_CounterLogic == APCI1500_COUNTER) {
+ 				i_InterruptMask = i_InterruptMask | 0x10;
+-			}	//if(i_CounterLogic==APCI1500_COUNTER)
++			}	/* if(i_CounterLogic==APCI1500_COUNTER) */
+ 			else {
+ 				i_InterruptMask = i_InterruptMask | 0x20;
+ 			}
+-		}		// if ((i_RegValue & 0x60) == 0x60)
++		}		/*  if ((i_RegValue & 0x60) == 0x60) */
+ 
+-		send_sig(SIGIO, devpriv->tsk_Current, 0);	// send signal to the sample
++		send_sig(SIGIO, devpriv->tsk_Current, 0);	/*  send signal to the sample */
+ 	       /***********************/
+ 		/* Enable all Interrupts */
+ 	       /***********************/
+@@ -2799,11 +2799,11 @@ static void v_APCI1500_Interrupt(int irq, void *d)
+ 		/* Authorizes the main interrupt on the board */
+ 	       /**********************************************/
+ 		outb(0xD0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-	}			//  if ((ui_InterruptStatus & 0x800000) == 0x800000)
++	}			/*   if ((ui_InterruptStatus & 0x800000) == 0x800000) */
+ 	else {
+ 		printk("\nInterrupt from unknown source\n");
+ 
+-	}			//else if ((ui_InterruptStatus & 0x800000) == 0x800000)
++	}			/* else if ((ui_InterruptStatus & 0x800000) == 0x800000) */
+ 	return;
+ }
+ 
+@@ -2982,7 +2982,7 @@ int i_APCI1500_Reset(struct comedi_device * dev)
+ 		devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ 	/* Deletes all interrupts */
+ 	outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+-	//reset all the digital outputs
++	/* reset all the digital outputs */
+ 	outw(0x0, devpriv->i_IobaseAddon + APCI1500_DIGITAL_OP);
+ /*******************************/
+ /* Disable the board interrupt */

commit 0109253dee3d211619876d3345ecc4c312d1b153
+Author: Bill Pemberton 
+Date:   Fri Mar 27 11:29:45 2009 -0400
+
+    Staging: comedi: remove C99 comments in pcl818.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
+index 43a9d56c6a43..b65a44bfdde9 100644
+--- a/drivers/staging/comedi/drivers/pcl818.c
++++ b/drivers/staging/comedi/drivers/pcl818.c
+@@ -107,9 +107,9 @@ A word or two about DMA. Driver support DMA operations at two ways:
+ 
+ #include "8253.h"
+ 
+-// #define PCL818_MODE13_AO 1
++/* #define PCL818_MODE13_AO 1 */
+ 
+-// boards constants
++/* boards constants */
+ 
+ #define boardPCL818L 0
+ #define boardPCL818H 1
+@@ -118,60 +118,60 @@ A word or two about DMA. Driver support DMA operations at two ways:
+ #define boardPCL818 4
+ #define boardPCL718 5
+ 
+-// IO space len
++/* IO space len */
+ #define PCLx1x_RANGE 16
+-// IO space len if we use FIFO
++/* IO space len if we use FIFO */
+ #define PCLx1xFIFO_RANGE 32
+ 
+-// W: clear INT request
++/* W: clear INT request */
+ #define PCL818_CLRINT 8
+-// R: return status byte
++/* R: return status byte */
+ #define PCL818_STATUS 8
+-// R: A/D high byte W: A/D range control
++/* R: A/D high byte W: A/D range control */
+ #define PCL818_RANGE 1
+-// R: next mux scan channel W: mux scan channel & range control pointer
++/* R: next mux scan channel W: mux scan channel & range control pointer */
+ #define PCL818_MUX 2
+-// R/W: operation control register
++/* R/W: operation control register */
+ #define PCL818_CONTROL 9
+-// W: counter enable
++/* W: counter enable */
+ #define PCL818_CNTENABLE 10
+ 
+-// R: low byte of A/D W: soft A/D trigger
++/* R: low byte of A/D W: soft A/D trigger */
+ #define PCL818_AD_LO 0
+-// R: high byte of A/D W: A/D range control
++/* R: high byte of A/D W: A/D range control */
+ #define PCL818_AD_HI 1
+-// W: D/A low&high byte
++/* W: D/A low&high byte */
+ #define PCL818_DA_LO 4
+ #define PCL818_DA_HI 5
+-// R: low&high byte of DI
++/* R: low&high byte of DI */
+ #define PCL818_DI_LO 3
+ #define PCL818_DI_HI 11
+-// W: low&high byte of DO
++/* W: low&high byte of DO */
+ #define PCL818_DO_LO 3
+ #define PCL818_DO_HI 11
+-// W: PCL718 second D/A
++/* W: PCL718 second D/A */
+ #define PCL718_DA2_LO 6
+ #define PCL718_DA2_HI 7
+-// counters
++/* counters */
+ #define PCL818_CTR0 12
+ #define PCL818_CTR1 13
+ #define PCL818_CTR2 14
+-// W: counter control
++/* W: counter control */
+ #define PCL818_CTRCTL 15
+ 
+-// W: fifo enable/disable
++/* W: fifo enable/disable */
+ #define PCL818_FI_ENABLE 6
+-// W: fifo interrupt clear
++/* W: fifo interrupt clear */
+ #define PCL818_FI_INTCLR 20
+-// W: fifo interrupt clear
++/* W: fifo interrupt clear */
+ #define PCL818_FI_FLUSH 25
+-// R: fifo status
++/* R: fifo status */
+ #define PCL818_FI_STATUS 25
+-// R: one record from FIFO
++/* R: one record from FIFO */
+ #define PCL818_FI_DATALO 23
+ #define PCL818_FI_DATAHI 23
+ 
+-// type of interrupt handler
++/* type of interrupt handler */
+ #define INT_TYPE_AI1_INT 1
+ #define INT_TYPE_AI1_DMA 2
+ #define INT_TYPE_AI1_FIFO 3
+@@ -184,7 +184,7 @@ A word or two about DMA. Driver support DMA operations at two ways:
+ #endif
+ 
+ #ifdef unused
+-// RTC stuff...
++/* RTC stuff... */
+ #define INT_TYPE_AI1_DMA_RTC 9
+ #define INT_TYPE_AI3_DMA_RTC 10
+ 
+@@ -254,22 +254,22 @@ static int RTC_timer_lock = 0;	/* RTC int lock */
+ 
+ struct pcl818_board {
+ 
+-	const char *name;	// driver name
+-	int n_ranges;		// len of range list
+-	int n_aichan_se;	// num of A/D chans in single ended  mode
+-	int n_aichan_diff;	// num of A/D chans in diferencial mode
+-	unsigned int ns_min;	// minimal alllowed delay between samples (in ns)
+-	int n_aochan;		// num of D/A chans
+-	int n_dichan;		// num of DI chans
+-	int n_dochan;		// num of DO chans
+-	const struct comedi_lrange *ai_range_type;	// default A/D rangelist
+-	const struct comedi_lrange *ao_range_type;	// default D/A rangelist
+-	unsigned int io_range;	// len of IO space
+-	unsigned int IRQbits;	// allowed interrupts
+-	unsigned int DMAbits;	// allowed DMA chans
+-	int ai_maxdata;		// maxdata for A/D
+-	int ao_maxdata;		// maxdata for D/A
+-	unsigned char fifo;	// 1=board has FIFO
++	const char *name;	/*  driver name */
++	int n_ranges;		/*  len of range list */
++	int n_aichan_se;	/*  num of A/D chans in single ended  mode */
++	int n_aichan_diff;	/*  num of A/D chans in diferencial mode */
++	unsigned int ns_min;	/*  minimal alllowed delay between samples (in ns) */
++	int n_aochan;		/*  num of D/A chans */
++	int n_dichan;		/*  num of DI chans */
++	int n_dochan;		/*  num of DO chans */
++	const struct comedi_lrange *ai_range_type;	/*  default A/D rangelist */
++	const struct comedi_lrange *ao_range_type;	/*  default D/A rangelist */
++	unsigned int io_range;	/*  len of IO space */
++	unsigned int IRQbits;	/*  allowed interrupts */
++	unsigned int DMAbits;	/*  allowed DMA chans */
++	int ai_maxdata;		/*  maxdata for A/D */
++	int ao_maxdata;		/*  maxdata for D/A */
++	unsigned char fifo;	/*  1=board has FIFO */
+ 	int is_818;
+ };
+ 
+@@ -315,54 +315,54 @@ COMEDI_INITCLEANUP(driver_pcl818);
+ 
+ struct pcl818_private {
+ 
+-	unsigned int dma;	// used DMA, 0=don't use DMA
+-	int dma_rtc;		// 1=RTC used with DMA, 0=no RTC alloc
++	unsigned int dma;	/*  used DMA, 0=don't use DMA */
++	int dma_rtc;		/*  1=RTC used with DMA, 0=no RTC alloc */
+ 	unsigned int io_range;
+ #ifdef unused
+-	unsigned long rtc_iobase;	// RTC port region
++	unsigned long rtc_iobase;	/*  RTC port region */
+ 	unsigned int rtc_iosize;
+ 	unsigned int rtc_irq;
+-	struct timer_list rtc_irq_timer;	// timer for RTC sanity check
+-	unsigned long rtc_freq;	// RTC int freq
+-	int rtc_irq_blocked;	// 1=we now do AI with DMA&RTC
++	struct timer_list rtc_irq_timer;	/*  timer for RTC sanity check */
++	unsigned long rtc_freq;	/*  RTC int freq */
++	int rtc_irq_blocked;	/*  1=we now do AI with DMA&RTC */
+ #endif
+-	unsigned long dmabuf[2];	// pointers to begin of DMA buffers
+-	unsigned int dmapages[2];	// len of DMA buffers in PAGE_SIZEs
+-	unsigned int hwdmaptr[2];	// hardware address of DMA buffers
+-	unsigned int hwdmasize[2];	// len of DMA buffers in Bytes
+-	unsigned int dmasamplsize;	// size in samples hwdmasize[0]/2
+-	unsigned int last_top_dma;	// DMA pointer in last RTC int
+-	int next_dma_buf;	// which DMA buffer will be used next round
+-	long dma_runs_to_end;	// how many we must permorm DMA transfer to end of record
+-	unsigned long last_dma_run;	// how many bytes we must transfer on last DMA page
+-	unsigned char neverending_ai;	// if=1, then we do neverending record (you must use cancel())
+-	unsigned int ns_min;	// manimal alllowed delay between samples (in us) for actual card
+-	int i8253_osc_base;	// 1/frequency of on board oscilator in ns
+-	int irq_free;		// 1=have allocated IRQ
+-	int irq_blocked;	// 1=IRQ now uses any subdev
+-	int irq_was_now_closed;	// when IRQ finish, there's stored int818_mode for last interrupt
+-	int ai_mode;		// who now uses IRQ - 1=AI1 int, 2=AI1 dma, 3=AI3 int, 4AI3 dma
+-	struct comedi_subdevice *last_int_sub;	// ptr to subdevice which now finish
+-	int ai_act_scan;	// how many scans we finished
+-	int ai_act_chan;	// actual position in actual scan
+-	unsigned int act_chanlist[16];	// MUX setting for actual AI operations
+-	unsigned int act_chanlist_len;	// how long is actual MUX list
+-	unsigned int act_chanlist_pos;	// actual position in MUX list
+-	unsigned int ai_scans;	// len of scanlist
+-	unsigned int ai_n_chan;	// how many channels is measured
+-	unsigned int *ai_chanlist;	// actaul chanlist
+-	unsigned int ai_flags;	// flaglist
+-	unsigned int ai_data_len;	// len of data buffer
+-	short *ai_data;	// data buffer
+-	unsigned int ai_timer1;	// timers
++	unsigned long dmabuf[2];	/*  pointers to begin of DMA buffers */
++	unsigned int dmapages[2];	/*  len of DMA buffers in PAGE_SIZEs */
++	unsigned int hwdmaptr[2];	/*  hardware address of DMA buffers */
++	unsigned int hwdmasize[2];	/*  len of DMA buffers in Bytes */
++	unsigned int dmasamplsize;	/*  size in samples hwdmasize[0]/2 */
++	unsigned int last_top_dma;	/*  DMA pointer in last RTC int */
++	int next_dma_buf;	/*  which DMA buffer will be used next round */
++	long dma_runs_to_end;	/*  how many we must permorm DMA transfer to end of record */
++	unsigned long last_dma_run;	/*  how many bytes we must transfer on last DMA page */
++	unsigned char neverending_ai;	/*  if=1, then we do neverending record (you must use cancel()) */
++	unsigned int ns_min;	/*  manimal alllowed delay between samples (in us) for actual card */
++	int i8253_osc_base;	/*  1/frequency of on board oscilator in ns */
++	int irq_free;		/*  1=have allocated IRQ */
++	int irq_blocked;	/*  1=IRQ now uses any subdev */
++	int irq_was_now_closed;	/*  when IRQ finish, there's stored int818_mode for last interrupt */
++	int ai_mode;		/*  who now uses IRQ - 1=AI1 int, 2=AI1 dma, 3=AI3 int, 4AI3 dma */
++	struct comedi_subdevice *last_int_sub;	/*  ptr to subdevice which now finish */
++	int ai_act_scan;	/*  how many scans we finished */
++	int ai_act_chan;	/*  actual position in actual scan */
++	unsigned int act_chanlist[16];	/*  MUX setting for actual AI operations */
++	unsigned int act_chanlist_len;	/*  how long is actual MUX list */
++	unsigned int act_chanlist_pos;	/*  actual position in MUX list */
++	unsigned int ai_scans;	/*  len of scanlist */
++	unsigned int ai_n_chan;	/*  how many channels is measured */
++	unsigned int *ai_chanlist;	/*  actaul chanlist */
++	unsigned int ai_flags;	/*  flaglist */
++	unsigned int ai_data_len;	/*  len of data buffer */
++	short *ai_data;	/*  data buffer */
++	unsigned int ai_timer1;	/*  timers */
+ 	unsigned int ai_timer2;
+-	struct comedi_subdevice *sub_ai;	// ptr to AI subdevice
+-	unsigned char usefifo;	// 1=use fifo
++	struct comedi_subdevice *sub_ai;	/*  ptr to AI subdevice */
++	unsigned char usefifo;	/*  1=use fifo */
+ 	unsigned int ao_readback[2];
+ };
+ 
+ 
+-static const unsigned int muxonechan[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,	// used for gain list programming
++static const unsigned int muxonechan[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,	/*  used for gain list programming */
+ 	0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
+ };
+ 
+@@ -535,10 +535,10 @@ static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d)
+ 
+       conv_finish:
+ 	low = inb(dev->iobase + PCL818_AD_LO);
+-	comedi_buf_put(s->async, ((inb(dev->iobase + PCL818_AD_HI) << 4) | (low >> 4)));	// get one sample
++	comedi_buf_put(s->async, ((inb(dev->iobase + PCL818_AD_HI) << 4) | (low >> 4)));	/*  get one sample */
+ 	outb(0, dev->iobase + PCL818_CLRINT);	/* clear INT request */
+ 
+-	if ((low & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) {	// dropout!
++	if ((low & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) {	/*  dropout! */
+ 		rt_printk
+ 			("comedi: A/D mode1/3 IRQ - channel dropout %x!=%x !\n",
+ 			(low & 0xf),
+@@ -549,7 +549,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d)
+ 		return IRQ_HANDLED;
+ 	}
+ 	if (s->async->cur_chan == 0) {
+-		// rt_printk("E");
++		/*  rt_printk("E"); */
+ 		devpriv->ai_act_scan--;
+ 	}
+ 
+@@ -577,7 +577,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
+ 
+ 	disable_dma(devpriv->dma);
+ 	devpriv->next_dma_buf = 1 - devpriv->next_dma_buf;
+-	if ((devpriv->dma_runs_to_end) > -1 || devpriv->neverending_ai) {	// switch dma bufs
++	if ((devpriv->dma_runs_to_end) > -1 || devpriv->neverending_ai) {	/*  switch dma bufs */
+ 		set_dma_mode(devpriv->dma, DMA_MODE_READ);
+ 		flags = claim_dma_lock();
+ 		set_dma_addr(devpriv->dma,
+@@ -601,7 +601,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
+ 	bufptr = 0;
+ 
+ 	for (i = 0; i < len; i++) {
+-		if ((ptr[bufptr] & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) {	// dropout!
++		if ((ptr[bufptr] & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) {	/*  dropout! */
+ 			rt_printk
+ 				("comedi: A/D mode1/3 DMA - channel dropout %d(card)!=%d(chanlist) at %d !\n",
+ 				(ptr[bufptr] & 0xf),
+@@ -614,7 +614,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
+ 			return IRQ_HANDLED;
+ 		}
+ 
+-		comedi_buf_put(s->async, ptr[bufptr++] >> 4);	// get one sample
++		comedi_buf_put(s->async, ptr[bufptr++] >> 4);	/*  get one sample */
+ 
+ 		devpriv->act_chanlist_pos++;
+ 		if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len) {
+@@ -627,7 +627,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
+ 				pcl818_ai_cancel(dev, s);
+ 				s->async->events |= COMEDI_CB_EOA;
+ 				comedi_event(dev, s);
+-				// printk("done int ai13 dma\n");
++				/*  printk("done int ai13 dma\n"); */
+ 				return IRQ_HANDLED;
+ 			}
+ 	}
+@@ -651,7 +651,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d)
+ 	long ofs_dats;
+ 	short *dmabuf = (short *) devpriv->dmabuf[0];
+ 
+-	//outb(2,0x378);
++	/* outb(2,0x378); */
+ 	switch (devpriv->ai_mode) {
+ 	case INT_TYPE_AI1_DMA_RTC:
+ 	case INT_TYPE_AI3_DMA_RTC:
+@@ -668,31 +668,31 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d)
+ 
+ 		if (top1 != top2)
+ 			return IRQ_HANDLED;
+-		top1 = devpriv->hwdmasize[0] - top1;	// where is now DMA in buffer
++		top1 = devpriv->hwdmasize[0] - top1;	/*  where is now DMA in buffer */
+ 		top1 >>= 1;
+-		ofs_dats = top1 - devpriv->last_top_dma;	// new samples from last call
++		ofs_dats = top1 - devpriv->last_top_dma;	/*  new samples from last call */
+ 		if (ofs_dats < 0)
+ 			ofs_dats = (devpriv->dmasamplsize) + ofs_dats;
+ 		if (!ofs_dats)
+-			return IRQ_HANDLED;	// exit=no new samples from last call
+-		// obsluz data
++			return IRQ_HANDLED;	/*  exit=no new samples from last call */
++		/*  obsluz data */
+ 		i = devpriv->last_top_dma - 1;
+ 		i &= (devpriv->dmasamplsize - 1);
+ 
+-		if (dmabuf[i] != MAGIC_DMA_WORD) {	// DMA overflow!
++		if (dmabuf[i] != MAGIC_DMA_WORD) {	/*  DMA overflow! */
+ 			comedi_error(dev, "A/D mode1/3 DMA buffer overflow!");
+-			//rt_printk("I %d dmabuf[i] %d %d\n",i,dmabuf[i],devpriv->dmasamplsize);
++			/* rt_printk("I %d dmabuf[i] %d %d\n",i,dmabuf[i],devpriv->dmasamplsize); */
+ 			pcl818_ai_cancel(dev, s);
+ 			s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
+ 			comedi_event(dev, s);
+ 			return IRQ_HANDLED;
+ 		}
+-		//rt_printk("r %ld ",ofs_dats);
++		/* rt_printk("r %ld ",ofs_dats); */
+ 
+ 		bufptr = devpriv->last_top_dma;
+ 
+ 		for (i = 0; i < ofs_dats; i++) {
+-			if ((dmabuf[bufptr] & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) {	// dropout!
++			if ((dmabuf[bufptr] & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) {	/*  dropout! */
+ 				rt_printk
+ 					("comedi: A/D mode1/3 DMA - channel dropout %d!=%d !\n",
+ 					(dmabuf[bufptr] & 0xf),
+@@ -705,7 +705,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d)
+ 				return IRQ_HANDLED;
+ 			}
+ 
+-			comedi_buf_put(s->async, dmabuf[bufptr++] >> 4);	// get one sample
++			comedi_buf_put(s->async, dmabuf[bufptr++] >> 4);	/*  get one sample */
+ 			bufptr &= (devpriv->dmasamplsize - 1);
+ 
+ 			if (s->async->cur_chan == 0) {
+@@ -717,7 +717,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d)
+ 					pcl818_ai_cancel(dev, s);
+ 					s->async->events |= COMEDI_CB_EOA;
+ 					comedi_event(dev, s);
+-					//printk("done int ai13 dma\n");
++					/* printk("done int ai13 dma\n"); */
+ 					return IRQ_HANDLED;
+ 				}
+ 		}
+@@ -727,11 +727,11 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d)
+ 		bufptr &= (devpriv->dmasamplsize - 1);
+ 		dmabuf[bufptr] = MAGIC_DMA_WORD;
+ 		comedi_event(dev, s);
+-		//outb(0,0x378);
++		/* outb(0,0x378); */
+ 		return IRQ_HANDLED;
+ 	}
+ 
+-	//outb(0,0x378);
++	/* outb(0,0x378); */
+ 	return IRQ_HANDLED;
+ }
+ #endif
+@@ -746,7 +746,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
+ 	struct comedi_subdevice *s = dev->subdevices + 0;
+ 	int i, len, lo;
+ 
+-	outb(0, dev->iobase + PCL818_FI_INTCLR);	// clear fifo int request
++	outb(0, dev->iobase + PCL818_FI_INTCLR);	/*  clear fifo int request */
+ 
+ 	lo = inb(dev->iobase + PCL818_FI_STATUS);
+ 
+@@ -774,7 +774,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
+ 
+ 	for (i = 0; i < len; i++) {
+ 		lo = inb(dev->iobase + PCL818_FI_DATALO);
+-		if ((lo & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) {	// dropout!
++		if ((lo & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) {	/*  dropout! */
+ 			rt_printk
+ 				("comedi: A/D mode1/3 FIFO - channel dropout %d!=%d !\n",
+ 				(lo & 0xf),
+@@ -786,7 +786,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
+ 			return IRQ_HANDLED;
+ 		}
+ 
+-		comedi_buf_put(s->async, (lo >> 4) | (inb(dev->iobase + PCL818_FI_DATAHI) << 4));	// get one sample
++		comedi_buf_put(s->async, (lo >> 4) | (inb(dev->iobase + PCL818_FI_DATAHI) << 4));	/*  get one sample */
+ 
+ 		if (s->async->cur_chan == 0) {
+ 			devpriv->ai_act_scan--;
+@@ -818,7 +818,7 @@ static irqreturn_t interrupt_pcl818(int irq, void *d PT_REGS_ARG)
+ 		comedi_error(dev, "premature interrupt");
+ 		return IRQ_HANDLED;
+ 	}
+-	//rt_printk("I\n");
++	/* rt_printk("I\n"); */
+ 
+ 	switch (devpriv->ai_mode) {
+ 	case INT_TYPE_AI1_DMA:
+@@ -881,12 +881,12 @@ static void pcl818_ai_mode13dma_int(int mode, struct comedi_device * dev,
+ 	unsigned int bytes;
+ 
+ 	rt_printk("mode13dma_int, mode: %d\n", mode);
+-	disable_dma(devpriv->dma);	// disable dma
++	disable_dma(devpriv->dma);	/*  disable dma */
+ 	bytes = devpriv->hwdmasize[0];
+ 	if (!devpriv->neverending_ai) {
+-		bytes = devpriv->ai_n_chan * devpriv->ai_scans * sizeof(short);	// how many
+-		devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize[0];	// how many DMA pages we must fiil
+-		devpriv->last_dma_run = bytes % devpriv->hwdmasize[0];	//on last dma transfer must be moved
++		bytes = devpriv->ai_n_chan * devpriv->ai_scans * sizeof(short);	/*  how many */
++		devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize[0];	/*  how many DMA pages we must fiil */
++		devpriv->last_dma_run = bytes % devpriv->hwdmasize[0];	/* on last dma transfer must be moved */
+ 		devpriv->dma_runs_to_end--;
+ 		if (devpriv->dma_runs_to_end >= 0)
+ 			bytes = devpriv->hwdmasize[0];
+@@ -928,7 +928,7 @@ static void pcl818_ai_mode13dma_rtc(int mode, struct comedi_device * dev,
+ 	set_dma_count(devpriv->dma, devpriv->hwdmasize[0]);
+ 	release_dma_lock(flags);
+ 	enable_dma(devpriv->dma);
+-	devpriv->last_top_dma = 0;	//devpriv->hwdmasize[0];
++	devpriv->last_top_dma = 0;	/* devpriv->hwdmasize[0]; */
+ 	pole = (short *) devpriv->dmabuf[0];
+ 	devpriv->dmasamplsize = devpriv->hwdmasize[0] / 2;
+ 	pole[devpriv->dmasamplsize - 1] = MAGIC_DMA_WORD;
+@@ -972,7 +972,7 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device * dev,
+ 	if (devpriv->irq_blocked)
+ 		return -EBUSY;
+ 
+-	start_pacer(dev, -1, 0, 0);	// stop pacer
++	start_pacer(dev, -1, 0, 0);	/*  stop pacer */
+ 
+ 	seglen = check_channel_list(dev, s, devpriv->ai_chanlist,
+ 		devpriv->ai_n_chan);
+@@ -992,7 +992,7 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device * dev,
+ 	devpriv->dma_runs_to_end = 0;
+ 
+ 	if ((devpriv->ai_scans == 0) || (devpriv->ai_scans == -1))
+-		devpriv->neverending_ai = 1;	//well, user want neverending
++		devpriv->neverending_ai = 1;	/* well, user want neverending */
+ 
+ 	if (mode == 1) {
+ 		i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
+@@ -1010,7 +1010,7 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device * dev,
+ 	outb(0, dev->iobase + PCL818_CNTENABLE);	/* enable pacer */
+ 
+ 	switch (devpriv->dma) {
+-	case 1:		// DMA
++	case 1:		/*  DMA */
+ 	case 3:
+ 		if (devpriv->dma_rtc == 0) {
+ 			pcl818_ai_mode13dma_int(mode, dev, s);
+@@ -1025,8 +1025,8 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device * dev,
+ 		}
+ #endif
+ 		break;
+-	case 0:		// IRQ
+-		// rt_printk("IRQ\n");
++	case 0:		/*  IRQ */
++		/*  rt_printk("IRQ\n"); */
+ 		if (mode == 1) {
+ 			devpriv->ai_mode = INT_TYPE_AI1_INT;
+ 			outb(0x83 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);	/* Pacer+IRQ */
+@@ -1035,8 +1035,8 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device * dev,
+ 			outb(0x82 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);	/* Ext trig+IRQ */
+ 		};
+ 		break;
+-	case -1:		// FIFO
+-		outb(1, dev->iobase + PCL818_FI_ENABLE);	// enable FIFO
++	case -1:		/*  FIFO */
++		outb(1, dev->iobase + PCL818_FI_ENABLE);	/*  enable FIFO */
+ 		if (mode == 1) {
+ 			devpriv->ai_mode = INT_TYPE_AI1_FIFO;
+ 			outb(0x03, dev->iobase + PCL818_CONTROL);	/* Pacer */
+@@ -1080,7 +1080,7 @@ static int pcl818_ao_mode13(int mode, struct comedi_device * dev, struct comedi_
+ 	if (devpriv->irq_blocked)
+ 		return -EBUSY;
+ 
+-	start_pacer(dev, -1, 0, 0);	// stop pacer
++	start_pacer(dev, -1, 0, 0);	/*  stop pacer */
+ 
+ 	devpriv->int13_act_scan = it->n;
+ 	devpriv->int13_act_chan = 0;
+@@ -1175,30 +1175,34 @@ static int check_channel_list(struct comedi_device * dev, struct comedi_subdevic
+ 	}
+ 
+ 	if (n_chan > 1) {
+-		// first channel is everytime ok
++		/*  first channel is everytime ok */
+ 		chansegment[0] = chanlist[0];
+-		// build part of chanlist
++		/*  build part of chanlist */
+ 		for (i = 1, seglen = 1; i < n_chan; i++, seglen++) {
+-			// rt_printk("%d. %d %d\n",i,CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i]));
+-			// we detect loop, this must by finish
++
++			/* rt_printk("%d. %d * %d\n",i,
++			 * CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i]));*/
++
++			/* we detect loop, this must by finish */
++
+ 			if (chanlist[0] == chanlist[i])
+ 				break;
+ 			nowmustbechan =
+ 				(CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan;
+-			if (nowmustbechan != CR_CHAN(chanlist[i])) {	// channel list isn't continous :-(
++			if (nowmustbechan != CR_CHAN(chanlist[i])) {	/*  channel list isn't continous :-( */
+ 				rt_printk
+ 					("comedi%d: pcl818: channel list must be continous! chanlist[%i]=%d but must be %d or %d!\n",
+ 					dev->minor, i, CR_CHAN(chanlist[i]),
+ 					nowmustbechan, CR_CHAN(chanlist[0]));
+ 				return 0;
+ 			}
+-			// well, this is next correct channel in list
++			/*  well, this is next correct channel in list */
+ 			chansegment[i] = chanlist[i];
+ 		}
+ 
+-		// check whole chanlist
++		/*  check whole chanlist */
+ 		for (i = 0, segpos = 0; i < n_chan; i++) {
+-			//rt_printk("%d %d=%d %d\n",CR_CHAN(chansegment[i%seglen]),CR_RANGE(chansegment[i%seglen]),CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i]));
++			/* rt_printk("%d %d=%d %d\n",CR_CHAN(chansegment[i%seglen]),CR_RANGE(chansegment[i%seglen]),CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i])); */
+ 			if (chanlist[i] != chansegment[i % seglen]) {
+ 				rt_printk
+ 					("comedi%d: pcl818: bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
+@@ -1208,7 +1212,7 @@ static int check_channel_list(struct comedi_device * dev, struct comedi_subdevic
+ 					CR_CHAN(chanlist[i % seglen]),
+ 					CR_RANGE(chanlist[i % seglen]),
+ 					CR_AREF(chansegment[i % seglen]));
+-				return 0;	// chan/gain list is strange
++				return 0;	/*  chan/gain list is strange */
+ 			}
+ 		}
+ 	} else {
+@@ -1226,7 +1230,7 @@ static void setup_channel_list(struct comedi_device * dev, struct comedi_subdevi
+ 	devpriv->act_chanlist_len = seglen;
+ 	devpriv->act_chanlist_pos = 0;
+ 
+-	for (i = 0; i < seglen; i++) {	// store range list to card
++	for (i = 0; i < seglen; i++) {	/*  store range list to card */
+ 		devpriv->act_chanlist[i] = CR_CHAN(chanlist[i]);
+ 		outb(muxonechan[CR_CHAN(chanlist[i])], dev->iobase + PCL818_MUX);	/* select channel */
+ 		outb(CR_RANGE(chanlist[i]), dev->iobase + PCL818_RANGE);	/* select gain */
+@@ -1391,7 +1395,7 @@ static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	if (cmd->chanlist) {
+ 		if (!check_channel_list(dev, s, cmd->chanlist,
+ 				cmd->chanlist_len))
+-			return 5;	// incorrect channels list
++			return 5;	/*  incorrect channels list */
+ 	}
+ 
+ 	return 0;
+@@ -1420,14 +1424,14 @@ static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 		devpriv->ai_scans = 0;
+ 	}
+ 
+-	if (cmd->scan_begin_src == TRIG_FOLLOW) {	// mode 1, 3
+-		if (cmd->convert_src == TRIG_TIMER) {	// mode 1
++	if (cmd->scan_begin_src == TRIG_FOLLOW) {	/*  mode 1, 3 */
++		if (cmd->convert_src == TRIG_TIMER) {	/*  mode 1 */
+ 			devpriv->ai_timer1 = cmd->convert_arg;
+ 			retval = pcl818_ai_cmd_mode(1, dev, s);
+ 			rt_printk("pcl818_ai_cmd() end\n");
+ 			return retval;
+ 		}
+-		if (cmd->convert_src == TRIG_EXT) {	// mode 3
++		if (cmd->convert_src == TRIG_EXT) {	/*  mode 3 */
+ 			return pcl818_ai_cmd_mode(3, dev, s);
+ 		}
+ 	}
+@@ -1450,7 +1454,7 @@ static int pcl818_ai_cancel(struct comedi_device * dev, struct comedi_subdevice
+ #ifdef unused
+ 		case INT_TYPE_AI1_DMA_RTC:
+ 		case INT_TYPE_AI3_DMA_RTC:
+-			set_rtc_irq_bit(0);	// stop RTC
++			set_rtc_irq_bit(0);	/*  stop RTC */
+ 			del_timer(&devpriv->rtc_irq_timer);
+ #endif
+ 		case INT_TYPE_AI1_DMA:
+@@ -1476,7 +1480,7 @@ static int pcl818_ai_cancel(struct comedi_device * dev, struct comedi_subdevice
+ 			inb(dev->iobase + PCL818_AD_HI);
+ 			outb(0, dev->iobase + PCL818_CLRINT);	/* clear INT request */
+ 			outb(0, dev->iobase + PCL818_CONTROL);	/* Stop A/D */
+-			if (devpriv->usefifo) {	// FIFO shutdown
++			if (devpriv->usefifo) {	/*  FIFO shutdown */
+ 				outb(0, dev->iobase + PCL818_FI_INTCLR);
+ 				outb(0, dev->iobase + PCL818_FI_FLUSH);
+ 				outb(0, dev->iobase + PCL818_FI_ENABLE);
+@@ -1502,18 +1506,18 @@ static int pcl818_check(unsigned long iobase)
+ 	outb(0x00, iobase + PCL818_MUX);
+ 	comedi_udelay(1);
+ 	if (inb(iobase + PCL818_MUX) != 0x00)
+-		return 1;	//there isn't card
++		return 1;	/* there isn't card */
+ 	outb(0x55, iobase + PCL818_MUX);
+ 	comedi_udelay(1);
+ 	if (inb(iobase + PCL818_MUX) != 0x55)
+-		return 1;	//there isn't card
++		return 1;	/* there isn't card */
+ 	outb(0x00, iobase + PCL818_MUX);
+ 	comedi_udelay(1);
+ 	outb(0x18, iobase + PCL818_CONTROL);
+ 	comedi_udelay(1);
+ 	if (inb(iobase + PCL818_CONTROL) != 0x18)
+-		return 1;	//there isn't card
+-	return 0;		// ok, card exist
++		return 1;	/* there isn't card */
++	return 0;		/*  ok, card exist */
+ }
+ 
+ /*
+@@ -1522,15 +1526,15 @@ static int pcl818_check(unsigned long iobase)
+ */
+ static void pcl818_reset(struct comedi_device * dev)
+ {
+-	if (devpriv->usefifo) {	// FIFO shutdown
++	if (devpriv->usefifo) {	/*  FIFO shutdown */
+ 		outb(0, dev->iobase + PCL818_FI_INTCLR);
+ 		outb(0, dev->iobase + PCL818_FI_FLUSH);
+ 		outb(0, dev->iobase + PCL818_FI_ENABLE);
+ 	}
+-	outb(0, dev->iobase + PCL818_DA_LO);	// DAC=0V
++	outb(0, dev->iobase + PCL818_DA_LO);	/*  DAC=0V */
+ 	outb(0, dev->iobase + PCL818_DA_HI);
+ 	comedi_udelay(1);
+-	outb(0, dev->iobase + PCL818_DO_HI);	// DO=$0000
++	outb(0, dev->iobase + PCL818_DO_HI);	/*  DO=$0000 */
+ 	outb(0, dev->iobase + PCL818_DO_LO);
+ 	comedi_udelay(1);
+ 	outb(0, dev->iobase + PCL818_CONTROL);
+@@ -1643,7 +1647,7 @@ static int rtc_setfreq_irq(int freq)
+ */
+ static void free_resources(struct comedi_device * dev)
+ {
+-	//rt_printk("free_resource()\n");
++	/* rt_printk("free_resource()\n"); */
+ 	if (dev->private) {
+ 		pcl818_ai_cancel(dev, devpriv->sub_ai);
+ 		pcl818_reset(dev);
+@@ -1670,7 +1674,7 @@ static void free_resources(struct comedi_device * dev)
+ 		free_irq(dev->irq, dev);
+ 	if (dev->iobase)
+ 		release_region(dev->iobase, devpriv->io_range);
+-	//rt_printk("free_resource() end\n");
++	/* rt_printk("free_resource() end\n"); */
+ }
+ 
+ /*
+@@ -1695,7 +1699,7 @@ static int pcl818_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	printk("comedi%d: pcl818:  board=%s, ioport=0x%03lx",
+ 		dev->minor, this_board->name, iobase);
+ 	devpriv->io_range = this_board->io_range;
+-	if ((this_board->fifo) && (it->options[2] == -1)) {	// we've board with FIFO and we want to use FIFO
++	if ((this_board->fifo) && (it->options[2] == -1)) {	/*  we've board with FIFO and we want to use FIFO */
+ 		devpriv->io_range = PCLx1xFIFO_RANGE;
+ 		devpriv->usefifo = 1;
+ 	}
+@@ -1750,7 +1754,7 @@ static int pcl818_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ #ifdef unused
+ 	/* grab RTC for DMA operations */
+ 	devpriv->dma_rtc = 0;
+-	if (it->options[2] > 0) {	// we want to use DMA
++	if (it->options[2] > 0) {	/*  we want to use DMA */
+ 		if (RTC_lock == 0) {
+ 			if (!request_region(RTC_PORT(0), RTC_IO_EXTENT,
+ 					"pcl818 (RTC)"))
+@@ -1809,8 +1813,8 @@ static int pcl818_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 		devpriv->dmapages[0] = pages;
+ 		devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]);
+ 		devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE;
+-		//rt_printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE);
+-		if (devpriv->dma_rtc == 0) {	// we must do duble buff :-(
++		/* rt_printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE); */
++		if (devpriv->dma_rtc == 0) {	/*  we must do duble buff :-( */
+ 			devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages);
+ 			if (!devpriv->dmabuf[1]) {
+ 				rt_printk
+@@ -1858,7 +1862,7 @@ static int pcl818_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 		}
+ 		if (this_board->is_818) {
+ 			if ((it->options[4] == 1) || (it->options[4] == 10))
+-				s->range_table = &range_pcl818l_h_ai;	// secondary range list jumper selectable
++				s->range_table = &range_pcl818l_h_ai;	/*  secondary range list jumper selectable */
+ 		} else {
+ 			switch (it->options[4]) {
+ 			case 0:
+@@ -1982,7 +1986,7 @@ static int pcl818_attach(struct comedi_device * dev, struct comedi_devconfig * i
+  */
+ static int pcl818_detach(struct comedi_device * dev)
+ {
+-	//  rt_printk("comedi%d: pcl818: remove\n", dev->minor);
++	/*   rt_printk("comedi%d: pcl818: remove\n", dev->minor); */
+ 	free_resources(dev);
+ 	return 0;
+ }

commit a351ecf3081f94796cf915dba820f9f5e62c43cf
+Author: Bill Pemberton 
+Date:   Fri Mar 27 11:29:40 2009 -0400
+
+    Staging: comedi: remove C99 comments in das1800.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
+index cd4cd4e6a79b..60724600607c 100644
+--- a/drivers/staging/comedi/drivers/das1800.c
++++ b/drivers/staging/comedi/drivers/das1800.c
+@@ -108,12 +108,12 @@ Unipolar and bipolar ranges cannot be mixed in the channel/gain list.
+ #include "8253.h"
+ #include "comedi_fc.h"
+ 
+-// misc. defines
+-#define DAS1800_SIZE           16	//uses 16 io addresses
+-#define FIFO_SIZE              1024	// 1024 sample fifo
+-#define TIMER_BASE             200	// 5 Mhz master clock
+-#define UNIPOLAR               0x4	// bit that determines whether input range is uni/bipolar
+-#define DMA_BUF_SIZE           0x1ff00	// size in bytes of dma buffers
++/* misc. defines */
++#define DAS1800_SIZE           16	/* uses 16 io addresses */
++#define FIFO_SIZE              1024	/*  1024 sample fifo */
++#define TIMER_BASE             200	/*  5 Mhz master clock */
++#define UNIPOLAR               0x4	/*  bit that determines whether input range is uni/bipolar */
++#define DMA_BUF_SIZE           0x1ff00	/*  size in bytes of dma buffers */
+ 
+ /* Registers for the das1800 */
+ #define DAS1800_FIFO            0x0
+@@ -138,7 +138,7 @@ Unipolar and bipolar ranges cannot be mixed in the channel/gain list.
+ #define   DMA_CH5_CH6             0x5
+ #define   DMA_CH6_CH7             0x6
+ #define   DMA_CH7_CH5             0x7
+-#define   DMA_ENABLED             0x3	//mask used to determine if dma is enabled
++#define   DMA_ENABLED             0x3	/* mask used to determine if dma is enabled */
+ #define   DMA_DUAL                0x4
+ #define   IRQ3                    0x8
+ #define   IRQ5                    0x10
+@@ -156,7 +156,7 @@ Unipolar and bipolar ranges cannot be mixed in the channel/gain list.
+ #define   SD                      0x40
+ #define   UB                      0x80
+ #define DAS1800_STATUS          0x7
+-// bits that prevent interrupt status bits (and CVEN) from being cleared on write
++/* bits that prevent interrupt status bits (and CVEN) from being cleared on write */
+ #define   CLEAR_INTR_MASK         (CVEN_MASK | 0x1f)
+ #define   INT                     0x1
+ #define   DMATC                   0x2
+@@ -164,14 +164,14 @@ Unipolar and bipolar ranges cannot be mixed in the channel/gain list.
+ #define   OVF                     0x10
+ #define   FHF                     0x20
+ #define   FNE                     0x40
+-#define   CVEN_MASK               0x40	// masks CVEN on write
++#define   CVEN_MASK               0x40	/*  masks CVEN on write */
+ #define   CVEN                    0x80
+ #define DAS1800_BURST_LENGTH    0x8
+ #define DAS1800_BURST_RATE      0x9
+ #define DAS1800_QRAM_ADDRESS    0xa
+ #define DAS1800_COUNTER         0xc
+ 
+-#define IOBASE2                   0x400	//offset of additional ioports used on 'ao' cards
++#define IOBASE2                   0x400	/* offset of additional ioports used on 'ao' cards */
+ 
+ enum {
+ 	das1701st, das1701st_da, das1702st, das1702st_da, das1702hr,
+@@ -212,7 +212,7 @@ static int das1800_set_frequency(struct comedi_device * dev);
+ static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode);
+ static unsigned int suggest_transfer_size(struct comedi_cmd * cmd);
+ 
+-// analog input ranges
++/* analog input ranges */
+ static const struct comedi_lrange range_ai_das1801 = {
+ 	8,
+ 	{
+@@ -485,7 +485,7 @@ struct das1800_private {
+ 
+ #define devpriv ((struct das1800_private *)dev->private)
+ 
+-// analog out range for boards with basic analog out
++/* analog out range for boards with basic analog out */
+ static const struct comedi_lrange range_ao_1 = {
+ 	1,
+ 	{
+@@ -493,7 +493,7 @@ static const struct comedi_lrange range_ao_1 = {
+ 		}
+ };
+ 
+-// analog out range for 'ao' boards
++/* analog out range for 'ao' boards */
+ /*
+ static const struct comedi_lrange range_ao_2 = {
+ 	2,
+@@ -525,26 +525,26 @@ static int das1800_init_dma(struct comedi_device * dev, unsigned int dma0,
+ {
+ 	unsigned long flags;
+ 
+-	// need an irq to do dma
++	/*  need an irq to do dma */
+ 	if (dev->irq && dma0) {
+-		//encode dma0 and dma1 into 2 digit hexadecimal for switch
++		/* encode dma0 and dma1 into 2 digit hexadecimal for switch */
+ 		switch ((dma0 & 0x7) | (dma1 << 4)) {
+-		case 0x5:	// dma0 == 5
++		case 0x5:	/*  dma0 == 5 */
+ 			devpriv->dma_bits |= DMA_CH5;
+ 			break;
+-		case 0x6:	// dma0 == 6
++		case 0x6:	/*  dma0 == 6 */
+ 			devpriv->dma_bits |= DMA_CH6;
+ 			break;
+-		case 0x7:	// dma0 == 7
++		case 0x7:	/*  dma0 == 7 */
+ 			devpriv->dma_bits |= DMA_CH7;
+ 			break;
+-		case 0x65:	// dma0 == 5, dma1 == 6
++		case 0x65:	/*  dma0 == 5, dma1 == 6 */
+ 			devpriv->dma_bits |= DMA_CH5_CH6;
+ 			break;
+-		case 0x76:	// dma0 == 6, dma1 == 7
++		case 0x76:	/*  dma0 == 6, dma1 == 7 */
+ 			devpriv->dma_bits |= DMA_CH6_CH7;
+ 			break;
+-		case 0x57:	// dma0 == 7, dma1 == 5
++		case 0x57:	/*  dma0 == 7, dma1 == 5 */
+ 			devpriv->dma_bits |= DMA_CH7_CH5;
+ 			break;
+ 		default:
+@@ -638,7 +638,7 @@ static int das1800_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	dev->board_ptr = das1800_boards + board;
+ 	dev->board_name = thisboard->name;
+ 
+-	// if it is an 'ao' board with fancy analog out then we need extra io ports
++	/*  if it is an 'ao' board with fancy analog out then we need extra io ports */
+ 	if (thisboard->ao_ability == 2) {
+ 		iobase2 = iobase + IOBASE2;
+ 		if (!request_region(iobase2, DAS1800_SIZE,
+@@ -659,7 +659,7 @@ static int das1800_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	}
+ 	dev->irq = irq;
+ 
+-	// set bits that tell card which irq to use
++	/*  set bits that tell card which irq to use */
+ 	switch (irq) {
+ 	case 0:
+ 		break;
+@@ -751,12 +751,12 @@ static int das1800_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 
+ 	das1800_cancel(dev, dev->read_subdev);
+ 
+-	// initialize digital out channels
++	/*  initialize digital out channels */
+ 	outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL);
+ 
+-	// initialize analog out channels
++	/*  initialize analog out channels */
+ 	if (thisboard->ao_ability == 1) {
+-		// select 'update' dac channel for baseAddress + 0x0
++		/*  select 'update' dac channel for baseAddress + 0x0 */
+ 		outb(DAC(thisboard->ao_n_chan - 1),
+ 			dev->iobase + DAS1800_SELECT);
+ 		outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
+@@ -871,7 +871,7 @@ static int das1800_ai_poll(struct comedi_device * dev, struct comedi_subdevice *
+ {
+ 	unsigned long flags;
+ 
+-	// prevent race with interrupt handler
++	/*  prevent race with interrupt handler */
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 	das1800_ai_handler(dev);
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+@@ -901,14 +901,14 @@ static irqreturn_t das1800_interrupt(int irq, void *d PT_REGS_ARG)
+ 	}
+ 	/* clear the interrupt status bit INT */
+ 	outb(CLEAR_INTR_MASK & ~INT, dev->iobase + DAS1800_STATUS);
+-	// handle interrupt
++	/*  handle interrupt */
+ 	das1800_ai_handler(dev);
+ 
+ 	spin_unlock(&dev->spinlock);
+ 	return IRQ_HANDLED;
+ }
+ 
+-// the guts of the interrupt handler, that is shared with das1800_ai_poll
++/* the guts of the interrupt handler, that is shared with das1800_ai_poll */
+ static void das1800_ai_handler(struct comedi_device * dev)
+ {
+ 	struct comedi_subdevice *s = dev->subdevices + 0;	/* analog input subdevice */
+@@ -917,22 +917,22 @@ static void das1800_ai_handler(struct comedi_device * dev)
+ 	unsigned int status = inb(dev->iobase + DAS1800_STATUS);
+ 
+ 	async->events = 0;
+-	// select adc for base address + 0
++	/*  select adc for base address + 0 */
+ 	outb(ADC, dev->iobase + DAS1800_SELECT);
+-	// dma buffer full
++	/*  dma buffer full */
+ 	if (devpriv->irq_dma_bits & DMA_ENABLED) {
+-		// look for data from dma transfer even if dma terminal count hasn't happened yet
++		/*  look for data from dma transfer even if dma terminal count hasn't happened yet */
+ 		das1800_handle_dma(dev, s, status);
+-	} else if (status & FHF) {	// if fifo half full
++	} else if (status & FHF) {	/*  if fifo half full */
+ 		das1800_handle_fifo_half_full(dev, s);
+-	} else if (status & FNE) {	// if fifo not empty
++	} else if (status & FNE) {	/*  if fifo not empty */
+ 		das1800_handle_fifo_not_empty(dev, s);
+ 	}
+ 
+ 	async->events |= COMEDI_CB_BLOCK;
+ 	/* if the card's fifo has overflowed */
+ 	if (status & OVF) {
+-		// clear OVF interrupt bit
++		/*  clear OVF interrupt bit */
+ 		outb(CLEAR_INTR_MASK & ~OVF, dev->iobase + DAS1800_STATUS);
+ 		comedi_error(dev, "DAS1800 FIFO overflow");
+ 		das1800_cancel(dev, s);
+@@ -940,19 +940,19 @@ static void das1800_ai_handler(struct comedi_device * dev)
+ 		comedi_event(dev, s);
+ 		return;
+ 	}
+-	// stop taking data if appropriate
++	/*  stop taking data if appropriate */
+ 	/* stop_src TRIG_EXT */
+ 	if (status & CT0TC) {
+-		// clear CT0TC interrupt bit
++		/*  clear CT0TC interrupt bit */
+ 		outb(CLEAR_INTR_MASK & ~CT0TC, dev->iobase + DAS1800_STATUS);
+-		// make sure we get all remaining data from board before quitting
++		/*  make sure we get all remaining data from board before quitting */
+ 		if (devpriv->irq_dma_bits & DMA_ENABLED)
+ 			das1800_flush_dma(dev, s);
+ 		else
+ 			das1800_handle_fifo_not_empty(dev, s);
+ 		das1800_cancel(dev, s);	/* disable hardware conversions */
+ 		async->events |= COMEDI_CB_EOA;
+-	} else if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0) {	// stop_src TRIG_COUNT
++	} else if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0) {	/*  stop_src TRIG_COUNT */
+ 		das1800_cancel(dev, s);	/* disable hardware conversions */
+ 		async->events |= COMEDI_CB_EOA;
+ 	}
+@@ -971,7 +971,7 @@ static void das1800_handle_dma(struct comedi_device * dev, struct comedi_subdevi
+ 	flags = claim_dma_lock();
+ 	das1800_flush_dma_channel(dev, s, devpriv->dma_current,
+ 		devpriv->dma_current_buf);
+-	// re-enable  dma channel
++	/*  re-enable  dma channel */
+ 	set_dma_addr(devpriv->dma_current,
+ 		virt_to_bus(devpriv->dma_current_buf));
+ 	set_dma_count(devpriv->dma_current, devpriv->dma_transfer_size);
+@@ -979,11 +979,11 @@ static void das1800_handle_dma(struct comedi_device * dev, struct comedi_subdevi
+ 	release_dma_lock(flags);
+ 
+ 	if (status & DMATC) {
+-		// clear DMATC interrupt bit
++		/*  clear DMATC interrupt bit */
+ 		outb(CLEAR_INTR_MASK & ~DMATC, dev->iobase + DAS1800_STATUS);
+-		// switch dma channels for next time, if appropriate
++		/*  switch dma channels for next time, if appropriate */
+ 		if (dual_dma) {
+-			// read data from the other channel next time
++			/*  read data from the other channel next time */
+ 			if (devpriv->dma_current == devpriv->dma0) {
+ 				devpriv->dma_current = devpriv->dma1;
+ 				devpriv->dma_current_buf = devpriv->ai_buf1;
+@@ -1035,7 +1035,7 @@ static void das1800_flush_dma_channel(struct comedi_device * dev, struct comedi_
+ 	 * get set correctly */
+ 	clear_dma_ff(channel);
+ 
+-	// figure out how many points to read
++	/*  figure out how many points to read */
+ 	num_bytes = devpriv->dma_transfer_size - get_dma_residue(channel);
+ 	num_samples = num_bytes / sizeof(short);
+ 
+@@ -1063,7 +1063,7 @@ static void das1800_flush_dma(struct comedi_device * dev, struct comedi_subdevic
+ 		devpriv->dma_current_buf);
+ 
+ 	if (dual_dma) {
+-		// switch to other channel and flush it
++		/*  switch to other channel and flush it */
+ 		if (devpriv->dma_current == devpriv->dma0) {
+ 			devpriv->dma_current = devpriv->dma1;
+ 			devpriv->dma_current_buf = devpriv->ai_buf1;
+@@ -1077,7 +1077,7 @@ static void das1800_flush_dma(struct comedi_device * dev, struct comedi_subdevic
+ 
+ 	release_dma_lock(flags);
+ 
+-	// get any remaining samples in fifo
++	/*  get any remaining samples in fifo */
+ 	das1800_handle_fifo_not_empty(dev, s);
+ 
+ 	return;
+@@ -1180,7 +1180,7 @@ static int das1800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subde
+ 
+ 	/* step 2: make sure trigger sources are unique and mutually compatible */
+ 
+-	// uniqueness check
++	/*  uniqueness check */
+ 	if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
+ 		err++;
+ 	if (cmd->scan_begin_src != TRIG_FOLLOW &&
+@@ -1192,7 +1192,7 @@ static int das1800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subde
+ 	if (cmd->stop_src != TRIG_COUNT &&
+ 		cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_EXT)
+ 		err++;
+-	//compatibility check
++	/* compatibility check */
+ 	if (cmd->scan_begin_src != TRIG_FOLLOW &&
+ 		cmd->convert_src != TRIG_TIMER)
+ 		err++;
+@@ -1244,7 +1244,7 @@ static int das1800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subde
+ 	/* step 4: fix up any arguments */
+ 
+ 	if (cmd->convert_src == TRIG_TIMER) {
+-		// if we are not in burst mode
++		/*  if we are not in burst mode */
+ 		if (cmd->scan_begin_src == TRIG_FOLLOW) {
+ 			tmp_arg = cmd->convert_arg;
+ 			/* calculate counter values that give desired timing */
+@@ -1255,9 +1255,9 @@ static int das1800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subde
+ 			if (tmp_arg != cmd->convert_arg)
+ 				err++;
+ 		}
+-		// if we are in burst mode
++		/*  if we are in burst mode */
+ 		else {
+-			// check that convert_arg is compatible
++			/*  check that convert_arg is compatible */
+ 			tmp_arg = cmd->convert_arg;
+ 			cmd->convert_arg =
+ 				burst_convert_arg(cmd->convert_arg,
+@@ -1266,7 +1266,7 @@ static int das1800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subde
+ 				err++;
+ 
+ 			if (cmd->scan_begin_src == TRIG_TIMER) {
+-				// if scans are timed faster than conversion rate allows
++				/*  if scans are timed faster than conversion rate allows */
+ 				if (cmd->convert_arg * cmd->chanlist_len >
+ 					cmd->scan_begin_arg) {
+ 					cmd->scan_begin_arg =
+@@ -1290,7 +1290,7 @@ static int das1800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subde
+ 	if (err)
+ 		return 4;
+ 
+-	// make sure user is not trying to mix unipolar and bipolar ranges
++	/*  make sure user is not trying to mix unipolar and bipolar ranges */
+ 	if (cmd->chanlist) {
+ 		unipolar = CR_RANGE(cmd->chanlist[0]) & UNIPOLAR;
+ 		for (i = 1; i < cmd->chanlist_len; i++) {
+@@ -1311,14 +1311,14 @@ static int das1800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subde
+ 
+ /* analog input cmd interface */
+ 
+-// first, some utility functions used in the main ai_do_cmd()
++/* first, some utility functions used in the main ai_do_cmd() */
+ 
+-// returns appropriate bits for control register a, depending on command
++/* returns appropriate bits for control register a, depending on command */
+ static int control_a_bits(struct comedi_cmd cmd)
+ {
+ 	int control_a;
+ 
+-	control_a = FFEN;	//enable fifo
++	control_a = FFEN;	/* enable fifo */
+ 	if (cmd.stop_src == TRIG_EXT) {
+ 		control_a |= ATEN;
+ 	}
+@@ -1336,7 +1336,7 @@ static int control_a_bits(struct comedi_cmd cmd)
+ 	return control_a;
+ }
+ 
+-// returns appropriate bits for control register c, depending on command
++/* returns appropriate bits for control register c, depending on command */
+ static int control_c_bits(struct comedi_cmd cmd)
+ {
+ 	int control_c;
+@@ -1346,7 +1346,7 @@ static int control_c_bits(struct comedi_cmd cmd)
+ 	 * select unipolar / bipolar
+ 	 */
+ 	aref = CR_AREF(cmd.chanlist[0]);
+-	control_c = UQEN;	//enable upper qram addresses
++	control_c = UQEN;	/* enable upper qram addresses */
+ 	if (aref != AREF_DIFF)
+ 		control_c |= SD;
+ 	if (aref == AREF_COMMON)
+@@ -1355,7 +1355,7 @@ static int control_c_bits(struct comedi_cmd cmd)
+ 	if (CR_RANGE(cmd.chanlist[0]) & UNIPOLAR)
+ 		control_c |= UB;
+ 	switch (cmd.scan_begin_src) {
+-	case TRIG_FOLLOW:	// not in burst mode
++	case TRIG_FOLLOW:	/*  not in burst mode */
+ 		switch (cmd.convert_src) {
+ 		case TRIG_TIMER:
+ 			/* trig on cascaded counters */
+@@ -1370,11 +1370,11 @@ static int control_c_bits(struct comedi_cmd cmd)
+ 		}
+ 		break;
+ 	case TRIG_TIMER:
+-		// burst mode with internal pacer clock
++		/*  burst mode with internal pacer clock */
+ 		control_c |= BMDE | IPCLK;
+ 		break;
+ 	case TRIG_EXT:
+-		// burst mode with external trigger
++		/*  burst mode with external trigger */
+ 		control_c |= BMDE | XPCLK;
+ 		break;
+ 	default:
+@@ -1384,12 +1384,12 @@ static int control_c_bits(struct comedi_cmd cmd)
+ 	return control_c;
+ }
+ 
+-// sets up counters
++/* sets up counters */
+ static int setup_counters(struct comedi_device * dev, struct comedi_cmd cmd)
+ {
+-	// setup cascaded counters for conversion/scan frequency
++	/*  setup cascaded counters for conversion/scan frequency */
+ 	switch (cmd.scan_begin_src) {
+-	case TRIG_FOLLOW:	// not in burst mode
++	case TRIG_FOLLOW:	/*  not in burst mode */
+ 		if (cmd.convert_src == TRIG_TIMER) {
+ 			/* set conversion frequency */
+ 			i8253_cascade_ns_to_timer_2div(TIMER_BASE,
+@@ -1401,7 +1401,7 @@ static int setup_counters(struct comedi_device * dev, struct comedi_cmd cmd)
+ 			}
+ 		}
+ 		break;
+-	case TRIG_TIMER:	// in burst mode
++	case TRIG_TIMER:	/*  in burst mode */
+ 		/* set scan frequency */
+ 		i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1),
+ 			&(devpriv->divisor2), &(cmd.scan_begin_arg),
+@@ -1414,16 +1414,16 @@ static int setup_counters(struct comedi_device * dev, struct comedi_cmd cmd)
+ 		break;
+ 	}
+ 
+-	// setup counter 0 for 'about triggering'
++	/*  setup counter 0 for 'about triggering' */
+ 	if (cmd.stop_src == TRIG_EXT) {
+-		// load counter 0 in mode 0
++		/*  load counter 0 in mode 0 */
+ 		i8254_load(dev->iobase + DAS1800_COUNTER, 0, 0, 1, 0);
+ 	}
+ 
+ 	return 0;
+ }
+ 
+-// sets up dma
++/* sets up dma */
+ static void setup_dma(struct comedi_device * dev, struct comedi_cmd cmd)
+ {
+ 	unsigned long lock_flags;
+@@ -1440,19 +1440,19 @@ static void setup_dma(struct comedi_device * dev, struct comedi_cmd cmd)
+ 	 * count and address get set correctly */
+ 	clear_dma_ff(devpriv->dma0);
+ 	set_dma_addr(devpriv->dma0, virt_to_bus(devpriv->ai_buf0));
+-	// set appropriate size of transfer
++	/*  set appropriate size of transfer */
+ 	set_dma_count(devpriv->dma0, devpriv->dma_transfer_size);
+ 	devpriv->dma_current = devpriv->dma0;
+ 	devpriv->dma_current_buf = devpriv->ai_buf0;
+ 	enable_dma(devpriv->dma0);
+-	// set up dual dma if appropriate
++	/*  set up dual dma if appropriate */
+ 	if (dual_dma) {
+ 		disable_dma(devpriv->dma1);
+ 		/* clear flip-flop to make sure 2-byte registers for
+ 		 * count and address get set correctly */
+ 		clear_dma_ff(devpriv->dma1);
+ 		set_dma_addr(devpriv->dma1, virt_to_bus(devpriv->ai_buf1));
+-		// set appropriate size of transfer
++		/*  set appropriate size of transfer */
+ 		set_dma_count(devpriv->dma1, devpriv->dma_transfer_size);
+ 		enable_dma(devpriv->dma1);
+ 	}
+@@ -1461,16 +1461,16 @@ static void setup_dma(struct comedi_device * dev, struct comedi_cmd cmd)
+ 	return;
+ }
+ 
+-// programs channel/gain list into card
++/* programs channel/gain list into card */
+ static void program_chanlist(struct comedi_device * dev, struct comedi_cmd cmd)
+ {
+ 	int i, n, chan_range;
+ 	unsigned long irq_flags;
+-	const int range_mask = 0x3;	//masks unipolar/bipolar bit off range
++	const int range_mask = 0x3;	/* masks unipolar/bipolar bit off range */
+ 	const int range_bitshift = 8;
+ 
+ 	n = cmd.chanlist_len;
+-	// spinlock protects indirect addressing
++	/*  spinlock protects indirect addressing */
+ 	comedi_spin_lock_irqsave(&dev->spinlock, irq_flags);
+ 	outb(QRAM, dev->iobase + DAS1800_SELECT);	/* select QRAM for baseAddress + 0x0 */
+ 	outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS);	/*set QRAM address start */
+@@ -1488,7 +1488,7 @@ static void program_chanlist(struct comedi_device * dev, struct comedi_cmd cmd)
+ 	return;
+ }
+ 
+-// analog input do_cmd
++/* analog input do_cmd */
+ static int das1800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	int ret;
+@@ -1509,22 +1509,22 @@ static int das1800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice
+ 	} else {
+ 		devpriv->irq_dma_bits |= devpriv->dma_bits;
+ 	}
+-	// interrupt on end of conversion for TRIG_WAKE_EOS
++	/*  interrupt on end of conversion for TRIG_WAKE_EOS */
+ 	if (cmd.flags & TRIG_WAKE_EOS) {
+-		// interrupt fifo not empty
++		/*  interrupt fifo not empty */
+ 		devpriv->irq_dma_bits &= ~FIMD;
+ 	} else {
+-		// interrupt fifo half full
++		/*  interrupt fifo half full */
+ 		devpriv->irq_dma_bits |= FIMD;
+ 	}
+-	// determine how many conversions we need
++	/*  determine how many conversions we need */
+ 	if (cmd.stop_src == TRIG_COUNT) {
+ 		devpriv->count = cmd.stop_arg * cmd.chanlist_len;
+ 	}
+ 
+ 	das1800_cancel(dev, s);
+ 
+-	// determine proper bits for control registers
++	/*  determine proper bits for control registers */
+ 	control_a = control_a_bits(cmd);
+ 	control_c = control_c_bits(cmd);
+ 
+@@ -1537,14 +1537,14 @@ static int das1800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice
+ 	}
+ 	setup_dma(dev, cmd);
+ 	outb(control_c, dev->iobase + DAS1800_CONTROL_C);
+-	// set conversion rate and length for burst mode
++	/*  set conversion rate and length for burst mode */
+ 	if (control_c & BMDE) {
+-		// program conversion period with number of microseconds minus 1
++		/*  program conversion period with number of microseconds minus 1 */
+ 		outb(cmd.convert_arg / 1000 - 1,
+ 			dev->iobase + DAS1800_BURST_RATE);
+ 		outb(cmd.chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH);
+ 	}
+-	outb(devpriv->irq_dma_bits, dev->iobase + DAS1800_CONTROL_B);	// enable irq/dma
++	outb(devpriv->irq_dma_bits, dev->iobase + DAS1800_CONTROL_B);	/*  enable irq/dma */
+ 	outb(control_a, dev->iobase + DAS1800_CONTROL_A);	/* enable fifo and triggering */
+ 	outb(CVEN, dev->iobase + DAS1800_STATUS);	/* enable conversions */
+ 
+@@ -1616,21 +1616,21 @@ static int das1800_ao_winsn(struct comedi_device * dev, struct comedi_subdevice
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+-//      int range = CR_RANGE(insn->chanspec);
++/* int range = CR_RANGE(insn->chanspec); */
+ 	int update_chan = thisboard->ao_n_chan - 1;
+ 	short output;
+ 	unsigned long irq_flags;
+ 
+-	//  card expects two's complement data
++	/*   card expects two's complement data */
+ 	output = data[0] - (1 << (thisboard->resolution - 1));
+-	// if the write is to the 'update' channel, we need to remember its value
++	/*  if the write is to the 'update' channel, we need to remember its value */
+ 	if (chan == update_chan)
+ 		devpriv->ao_update_bits = output;
+-	// write to channel
++	/*  write to channel */
+ 	comedi_spin_lock_irqsave(&dev->spinlock, irq_flags);
+ 	outb(DAC(chan), dev->iobase + DAS1800_SELECT);	/* select dac channel for baseAddress + 0x0 */
+ 	outw(output, dev->iobase + DAS1800_DAC);
+-	// now we need to write to 'update' channel to update all dac channels
++	/*  now we need to write to 'update' channel to update all dac channels */
+ 	if (chan != update_chan) {
+ 		outb(DAC(update_chan), dev->iobase + DAS1800_SELECT);	/* select 'update' channel for baseAddress + 0x0 */
+ 		outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
+@@ -1657,7 +1657,7 @@ static int das1800_do_wbits(struct comedi_device * dev, struct comedi_subdevice
+ {
+ 	unsigned int wbits;
+ 
+-	// only set bits that have been masked
++	/*  only set bits that have been masked */
+ 	data[0] &= (1 << s->n_chan) - 1;
+ 	wbits = devpriv->do_bits;
+ 	wbits &= ~data[0];
+@@ -1676,11 +1676,11 @@ static int das1800_set_frequency(struct comedi_device * dev)
+ {
+ 	int err = 0;
+ 
+-	// counter 1, mode 2
++	/*  counter 1, mode 2 */
+ 	if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 1, devpriv->divisor1,
+ 			2))
+ 		err++;
+-	// counter 2, mode 2
++	/*  counter 2, mode 2 */
+ 	if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 2, devpriv->divisor2,
+ 			2))
+ 		err++;
+@@ -1697,11 +1697,11 @@ static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode)
+ {
+ 	unsigned int micro_sec;
+ 
+-	// in burst mode, the maximum conversion time is 64 microseconds
++	/*  in burst mode, the maximum conversion time is 64 microseconds */
+ 	if (convert_arg > 64000)
+ 		convert_arg = 64000;
+ 
+-	// the conversion time must be an integral number of microseconds
++	/*  the conversion time must be an integral number of microseconds */
+ 	switch (round_mode) {
+ 	case TRIG_ROUND_NEAREST:
+ 	default:
+@@ -1715,21 +1715,21 @@ static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode)
+ 		break;
+ 	}
+ 
+-	// return number of nanoseconds
++	/*  return number of nanoseconds */
+ 	return micro_sec * 1000;
+ }
+ 
+-// utility function that suggests a dma transfer size based on the conversion period 'ns'
++/* utility function that suggests a dma transfer size based on the conversion period 'ns' */
+ static unsigned int suggest_transfer_size(struct comedi_cmd * cmd)
+ {
+ 	unsigned int size = DMA_BUF_SIZE;
+-	static const int sample_size = 2;	// size in bytes of one sample from board
+-	unsigned int fill_time = 300000000;	// target time in nanoseconds for filling dma buffer
+-	unsigned int max_size;	// maximum size we will allow for a transfer
++	static const int sample_size = 2;	/*  size in bytes of one sample from board */
++	unsigned int fill_time = 300000000;	/*  target time in nanoseconds for filling dma buffer */
++	unsigned int max_size;	/*  maximum size we will allow for a transfer */
+ 
+-	// make dma buffer fill in 0.3 seconds for timed modes
++	/*  make dma buffer fill in 0.3 seconds for timed modes */
+ 	switch (cmd->scan_begin_src) {
+-	case TRIG_FOLLOW:	// not in burst mode
++	case TRIG_FOLLOW:	/*  not in burst mode */
+ 		if (cmd->convert_src == TRIG_TIMER)
+ 			size = (fill_time / cmd->convert_arg) * sample_size;
+ 		break;
+@@ -1742,9 +1742,9 @@ static unsigned int suggest_transfer_size(struct comedi_cmd * cmd)
+ 		break;
+ 	}
+ 
+-	// set a minimum and maximum size allowed
++	/*  set a minimum and maximum size allowed */
+ 	max_size = DMA_BUF_SIZE;
+-	// if we are taking limited number of conversions, limit transfer size to that
++	/*  if we are taking limited number of conversions, limit transfer size to that */
+ 	if (cmd->stop_src == TRIG_COUNT &&
+ 		cmd->stop_arg * cmd->chanlist_len * sample_size < max_size)
+ 		max_size = cmd->stop_arg * cmd->chanlist_len * sample_size;

commit cf0fd1086cbb55fb5c0ecbd652fec34335fb7657
+Author: Bill Pemberton 
+Date:   Fri Mar 27 11:29:29 2009 -0400
+
+    Staging: comedi: remove C99 comments in APCI1710_82x54.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+index 3f8ffa2c3e87..b3ee729c50ca 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+@@ -233,9 +233,9 @@ int i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, struct comedi_sub
+ 	unsigned char b_OutputLevel;
+ 	unsigned char b_HardwareGateLevel;
+ 
+-	//BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz
++	/* BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */
+ 	unsigned int dw_Test = 0;
+-	//END JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz
++	/* END JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */
+ 
+ 	i_ReturnValue = insn->n;
+ 	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+@@ -256,7 +256,7 @@ int i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, struct comedi_sub
+ 			if (b_TimerNbr <= 2) {
+ 				/* Test the timer mode */
+ 				if (b_TimerMode <= 5) {
+-					//BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz
++					/* BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */
+ 					/* Test te imput clock selection */
+ 					/*
+ 					   if (((b_TimerNbr == 0) && (b_InputClockSelection == 0)) ||
+@@ -271,11 +271,11 @@ int i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, struct comedi_sub
+ 					     ((b_InputClockSelection == APCI1710_PCI_BUS_CLOCK) ||
+ 					      (b_InputClockSelection == APCI1710_FRONT_CONNECTOR_INPUT) ||
+ 					      (b_InputClockSelection == APCI1710_10MHZ)))) {
+-						//BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz
++						/* BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */
+ 						if (((b_InputClockSelection == APCI1710_10MHZ) &&
+ 						     ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0x0000FFFFUL) >= 0x3131)) ||
+ 						     (b_InputClockSelection != APCI1710_10MHZ)) {
+-							//END JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz
++							/* END JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */
+ 							/* Test the input clock level selection */
+ 
+ 							if ((b_InputClockLevel == 0) ||
+@@ -284,7 +284,7 @@ int i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, struct comedi_sub
+ 								if ((b_OutputLevel == 0) || (b_OutputLevel == 1)) {
+ 									/* Test the hardware gate level selection */
+ 									if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1)) {
+-										//BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz
++										/* BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
+ 										/* Test if version > 1.1 and clock selection = 10MHz */
+ 										if ((b_InputClockSelection == APCI1710_10MHZ) && ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0x0000FFFFUL) > 0x3131)) {
+ 											/* Test if 40MHz quartz on board */
+@@ -297,7 +297,7 @@ int i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, struct comedi_sub
+ 
+ 										/* Test if detection OK */
+ 										if (dw_Test == 1) {
+-											//END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz
++											/* END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
+ 											/* Initialisation OK */
+ 											devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init = 1;
+ 
+@@ -314,7 +314,7 @@ int i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, struct comedi_sub
+ 											devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_HardwareGateLevel = b_HardwareGateLevel;
+ 
+ 											/* Set the configuration word and disable the timer */
+-											//BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz
++											/* BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
+ 											/*
+ 											   devpriv->s_ModuleInfo [b_ModulNbr].
+ 											   s_82X54ModuleInfo.
+@@ -330,7 +330,7 @@ int i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, struct comedi_sub
+ 											}
+ 
+ 											devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord = (unsigned int)(((b_HardwareGateLevel << 0) & 0x1) | ((b_InputClockLevel << 1) & 0x2) | (((~b_OutputLevel & 1) << 2) & 0x4) | ((b_InputClockSelection << 4) & 0x30));
+-											//END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz
++											/* END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
+ 											outl(devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord, devpriv->s_BoardInfos.ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
+ 
+ 											/* Initialise the 82X54 Timer */
+@@ -338,31 +338,31 @@ int i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, struct comedi_sub
+ 
+ 											/* Write the reload value */
+ 											outl(ul_ReloadValue, devpriv->s_BoardInfos.ui_Address + 0 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
+-											//BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz
+-										}	// if (dw_Test == 1)
++											/* BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
++										}	/*  if (dw_Test == 1) */
+ 										else {
+ 											/* Input timer clock selection is wrong */
+ 											i_ReturnValue = -6;
+-										}	// if (dw_Test == 1)
+-										//END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz
+-									}	// if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1))
++										}	/*  if (dw_Test == 1) */
++										/* END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
++									}	/*  if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1)) */
+ 									else {
+ 										/* Selection from hardware gate level is wrong */
+ 										DPRINTK("Selection from hardware gate level is wrong\n");
+ 										i_ReturnValue = -9;
+-									}	// if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1))
+-								}	// if ((b_OutputLevel == 0) || (b_OutputLevel == 1))
++									}	/*  if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1)) */
++								}	/*  if ((b_OutputLevel == 0) || (b_OutputLevel == 1)) */
+ 								else {
+ 									/* Selection from output clock level is wrong */
+ 									DPRINTK("Selection from output clock level is wrong\n");
+ 									i_ReturnValue = -8;
+-								}	// if ((b_OutputLevel == 0) || (b_OutputLevel == 1))
+-							}	// if ((b_InputClockLevel == 0) || (b_InputClockLevel == 1))
++								}	/*  if ((b_OutputLevel == 0) || (b_OutputLevel == 1)) */
++							}	/*  if ((b_InputClockLevel == 0) || (b_InputClockLevel == 1)) */
+ 							else {
+ 								/* Selection from input clock level is wrong */
+ 								DPRINTK("Selection from input clock level is wrong\n");
+ 								i_ReturnValue = -7;
+-							}	// if ((b_InputClockLevel == 0) || (b_InputClockLevel == 1))
++							}	/*  if ((b_InputClockLevel == 0) || (b_InputClockLevel == 1)) */
+ 						} else {
+ 							/* Input timer clock selection is wrong */
+ 							DPRINTK("Input timer clock selection is wrong\n");
+@@ -373,18 +373,18 @@ int i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, struct comedi_sub
+ 						DPRINTK("Input timer clock selection is wrong\n");
+ 						i_ReturnValue = -6;
+ 					}
+-				}	// if ((b_TimerMode >= 0) && (b_TimerMode <= 5))
++				}	/*  if ((b_TimerMode >= 0) && (b_TimerMode <= 5)) */
+ 				else {
+ 					/* Timer mode selection is wrong */
+ 					DPRINTK("Timer mode selection is wrong\n");
+ 					i_ReturnValue = -5;
+-				}	// if ((b_TimerMode >= 0) && (b_TimerMode <= 5))
+-			}	// if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
++				}	/*  if ((b_TimerMode >= 0) && (b_TimerMode <= 5)) */
++			}	/*  if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
+ 			else {
+ 				/* Timer selection wrong */
+ 				DPRINTK("Timer selection wrong\n");
+ 				i_ReturnValue = -3;
+-			}	// if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
++			}	/*  if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
+ 		} else {
+ 			/* The module is not a TIMER module */
+ 			DPRINTK("The module is not a TIMER module\n");
+@@ -431,7 +431,7 @@ int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,struct come
+ i_ReturnValue=insn->n;
+ 	b_ModulNbr        = (unsigned char) CR_AREF(insn->chanspec);
+ 	b_TimerNbr		  = (unsigned char) CR_CHAN(insn->chanspec);
+-	b_ActionType      = (unsigned char) data[0]; // enable disable
++	b_ActionType      = (unsigned char) data[0]; /*  enable disable */
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+ +----------------------------------------------------------------------------+
+@@ -462,7 +462,7 @@ int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device * dev,
+ 	i_ReturnValue = insn->n;
+ 	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+ 	b_TimerNbr = (unsigned char) CR_CHAN(insn->chanspec);
+-	b_ActionType = (unsigned char) data[0];	// enable disable
++	b_ActionType = (unsigned char) data[0];	/*  enable disable */
+ 
+ 	/* Test the module number */
+ 	if (b_ModulNbr < 4) {
+@@ -487,9 +487,9 @@ int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device * dev,
+ 								devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord | 0x8;
+ 
+ 								outl(devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord, devpriv->s_BoardInfos.ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
+-								devpriv->tsk_Current = current;	// Save the current process task structure
++								devpriv->tsk_Current = current;	/*  Save the current process task structure */
+ 
+-							}	// if (b_InterruptEnable == APCI1710_ENABLE)
++							}	/*  if (b_InterruptEnable == APCI1710_ENABLE) */
+ 							else {
+ 								/* Disable the interrupt */
+ 								devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord & 0xF7;
+@@ -498,7 +498,7 @@ int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device * dev,
+ 
+ 								/* Save the interrupt flag */
+ 								devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask & (0xFF - (1 << b_TimerNbr));
+-							}	// if (b_InterruptEnable == APCI1710_ENABLE)
++							}	/*  if (b_InterruptEnable == APCI1710_ENABLE) */
+ 
+ 							/* Test if error occur */
+ 							if (i_ReturnValue >= 0) {
+@@ -530,7 +530,7 @@ int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device * dev,
+ 						/* Disable the timer */
+ 						outl(0, devpriv->s_BoardInfos.ui_Address + 44 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
+ 						break;
+-					}	// Switch end
++					}	/*  Switch end */
+ 				} else {
+ 					/* Timer not initialised see function */
+ 					DPRINTK ("Timer not initialised see function\n");
+@@ -540,7 +540,7 @@ int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device * dev,
+ 				/* Timer selection wrong */
+ 				DPRINTK("Timer selection wrong\n");
+ 				i_ReturnValue = -3;
+-			}	// if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
++			}	/*  if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
+ 		} else {
+ 			/* The module is not a TIMER module */
+ 			DPRINTK("The module is not a TIMER module\n");
+@@ -662,7 +662,7 @@ int i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, struct comedi_su
+ 			i_ReturnValue = -2;
+ 		}
+ 
+-	}			// End of Switch
++	}			/*  End of Switch */
+ 	return (i_ReturnValue);
+ }
+ 
+@@ -800,7 +800,7 @@ int i_APCI1710_ReadTimerValue(struct comedi_device * dev,
+ 				/* Timer selection wrong */
+ 				DPRINTK("Timer selection wrong\n");
+ 				i_ReturnValue = -3;
+-			}	// if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
++			}	/*  if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
+ 		} else {
+ 			/* The module is not a TIMER module */
+ 			DPRINTK("The module is not a TIMER module\n");
+@@ -879,7 +879,7 @@ int i_APCI1710_GetTimerOutputLevel(struct comedi_device * dev,
+ 				/* Timer selection wrong */
+ 				DPRINTK("Timer selection wrong\n");
+ 				i_ReturnValue = -3;
+-			}	// if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
++			}	/*  if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
+ 		} else {
+ 			/* The module is not a TIMER module */
+ 			DPRINTK("The module is not a TIMER module\n");
+@@ -958,7 +958,7 @@ int i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
+ 			} else {
+ 				/* Timer selection wrong */
+ 				i_ReturnValue = -3;
+-			}	// if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
++			}	/*  if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
+ 		} else {
+ 			/* The module is not a TIMER module */
+ 
+@@ -1031,7 +1031,7 @@ int i_APCI1710_WriteTimerValue(struct comedi_device * dev,
+ 				/* Timer selection wrong */
+ 				DPRINTK("Timer selection wrong\n");
+ 				i_ReturnValue = -3;
+-			}	// if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
++			}	/*  if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
+ 		} else {
+ 			/* The module is not a TIMER module */
+ 			DPRINTK("The module is not a TIMER module\n");

commit ed27614451c3f35412b83aabdcd4af6d76be7cd7
+Author: Bill Pemberton 
+Date:   Fri Mar 27 11:29:23 2009 -0400
+
+    Staging: comedi: remove C99 comments in acl7225b.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/acl7225b.c b/drivers/staging/comedi/drivers/acl7225b.c
+index b21320f0959f..057753991323 100644
+--- a/drivers/staging/comedi/drivers/acl7225b.c
++++ b/drivers/staging/comedi/drivers/acl7225b.c
+@@ -26,8 +26,8 @@ static int acl7225b_attach(struct comedi_device *dev, struct comedi_devconfig *
+ static int acl7225b_detach(struct comedi_device *dev);
+ 
+ struct boardtype {
+-	const char *name;	// driver name
+-	int io_range;		// len of I/O space
++	const char *name;	/*  driver name */
++	int io_range;		/*  len of I/O space */
+ };
+ 
+ static const struct boardtype boardtypes[] = {

commit 67d83b4fb96ab304a47ba5af9a99818b38c9fd3e
+Author: Bill Pemberton 
+Date:   Fri Mar 27 11:29:18 2009 -0400
+
+    Staging: comedi: remove C99 comments in 8253.h
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/8253.h b/drivers/staging/comedi/drivers/8253.h
+index 08a11a5a16e6..bcf0170e93d7 100644
+--- a/drivers/staging/comedi/drivers/8253.h
++++ b/drivers/staging/comedi/drivers/8253.h
+@@ -205,7 +205,7 @@ static inline void i8253_cascade_ns_to_timer_2div(int i8253_osc_base,
+ 	}
+ 
+ 	*nanosec = div1 * div2 * i8253_osc_base;
+-	*d1 = div1 & 0xffff;	// masking is done since counter maps zero to 0x10000
++	*d1 = div1 & 0xffff;	/*  masking is done since counter maps zero to 0x10000 */
+ 	*d2 = div2 & 0xffff;
+ 	return;
+ }
+@@ -247,12 +247,12 @@ static inline int i8254_load(unsigned long base_address, unsigned int regshift,
+ 		return -1;
+ 
+ 	byte = counter_number << 6;
+-	byte |= 0x30;		// load low then high byte
+-	byte |= (mode << 1);	// set counter mode
++	byte |= 0x30;		/*  load low then high byte */
++	byte |= (mode << 1);	/*  set counter mode */
+ 	outb(byte, base_address + (i8254_control_reg << regshift));
+-	byte = count & 0xff;	// lsb of counter value
++	byte = count & 0xff;	/*  lsb of counter value */
+ 	outb(byte, base_address + (counter_number << regshift));
+-	byte = (count >> 8) & 0xff;	// msb of counter value
++	byte = (count >> 8) & 0xff;	/*  msb of counter value */
+ 	outb(byte, base_address + (counter_number << regshift));
+ 
+ 	return 0;
+@@ -273,12 +273,12 @@ static inline int i8254_mm_load(void *base_address, unsigned int regshift,
+ 		return -1;
+ 
+ 	byte = counter_number << 6;
+-	byte |= 0x30;		// load low then high byte
+-	byte |= (mode << 1);	// set counter mode
++	byte |= 0x30;		/*  load low then high byte */
++	byte |= (mode << 1);	/*  set counter mode */
+ 	writeb(byte, base_address + (i8254_control_reg << regshift));
+-	byte = count & 0xff;	// lsb of counter value
++	byte = count & 0xff;	/*  lsb of counter value */
+ 	writeb(byte, base_address + (counter_number << regshift));
+-	byte = (count >> 8) & 0xff;	// msb of counter value
++	byte = (count >> 8) & 0xff;	/*  msb of counter value */
+ 	writeb(byte, base_address + (counter_number << regshift));
+ 
+ 	return 0;
+@@ -294,13 +294,13 @@ static inline int i8254_read(unsigned long base_address, unsigned int regshift,
+ 	if (counter_number > 2)
+ 		return -1;
+ 
+-	// latch counter
++	/*  latch counter */
+ 	byte = counter_number << 6;
+ 	outb(byte, base_address + (i8254_control_reg << regshift));
+ 
+-	// read lsb
++	/*  read lsb */
+ 	ret = inb(base_address + (counter_number << regshift));
+-	// read msb
++	/*  read msb */
+ 	ret += inb(base_address + (counter_number << regshift)) << 8;
+ 
+ 	return ret;
+@@ -315,13 +315,13 @@ static inline int i8254_mm_read(void *base_address, unsigned int regshift,
+ 	if (counter_number > 2)
+ 		return -1;
+ 
+-	// latch counter
++	/*  latch counter */
+ 	byte = counter_number << 6;
+ 	writeb(byte, base_address + (i8254_control_reg << regshift));
+ 
+-	// read lsb
++	/*  read lsb */
+ 	ret = readb(base_address + (counter_number << regshift));
+-	// read msb
++	/*  read msb */
+ 	ret += readb(base_address + (counter_number << regshift)) << 8;
+ 
+ 	return ret;
+@@ -336,9 +336,9 @@ static inline void i8254_write(unsigned long base_address,
+ 	if (counter_number > 2)
+ 		return;
+ 
+-	byte = count & 0xff;	// lsb of counter value
++	byte = count & 0xff;	/*  lsb of counter value */
+ 	outb(byte, base_address + (counter_number << regshift));
+-	byte = (count >> 8) & 0xff;	// msb of counter value
++	byte = (count >> 8) & 0xff;	/*  msb of counter value */
+ 	outb(byte, base_address + (counter_number << regshift));
+ }
+ 
+@@ -350,9 +350,9 @@ static inline void i8254_mm_write(void *base_address,
+ 	if (counter_number > 2)
+ 		return;
+ 
+-	byte = count & 0xff;	// lsb of counter value
++	byte = count & 0xff;	/*  lsb of counter value */
+ 	writeb(byte, base_address + (counter_number << regshift));
+-	byte = (count >> 8) & 0xff;	// msb of counter value
++	byte = (count >> 8) & 0xff;	/*  msb of counter value */
+ 	writeb(byte, base_address + (counter_number << regshift));
+ }
+ 
+@@ -374,8 +374,8 @@ static inline int i8254_set_mode(unsigned long base_address,
+ 		return -1;
+ 
+ 	byte = counter_number << 6;
+-	byte |= 0x30;		// load low then high byte
+-	byte |= mode;		// set counter mode and BCD|binary
++	byte |= 0x30;		/*  load low then high byte */
++	byte |= mode;		/*  set counter mode and BCD|binary */
+ 	outb(byte, base_address + (i8254_control_reg << regshift));
+ 
+ 	return 0;
+@@ -392,8 +392,8 @@ static inline int i8254_mm_set_mode(void *base_address,
+ 		return -1;
+ 
+ 	byte = counter_number << 6;
+-	byte |= 0x30;		// load low then high byte
+-	byte |= mode;		// set counter mode and BCD|binary
++	byte |= 0x30;		/*  load low then high byte */
++	byte |= mode;		/*  set counter mode and BCD|binary */
+ 	writeb(byte, base_address + (i8254_control_reg << regshift));
+ 
+ 	return 0;

commit 6a037d5f655fbf1853d28cd8a02ffe5c466d81a5
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:06:30 2009 -0400
+
+    Staging: comedi: Remove str_AnalogInputHeader typedef in addi-data/addi_eeprom.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+index 2e9c15debdb4..e57692dc9e83 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+@@ -106,13 +106,14 @@ typedef struct {
+ 	unsigned char b_Resolution;
+ } str_AnalogOutputHeader;
+ 
+-typedef struct {
++struct str_AnalogInputHeader {
+ 	unsigned short w_Nchannel;
+ 	unsigned short w_MinConvertTiming;
+ 	unsigned short w_MinDelayTiming;
+ 	unsigned char b_HasDma;
+ 	unsigned char b_Resolution;
+-} str_AnalogInputHeader;
++};
++
+ 
+ 		/*****************************************/
+ 		/*            Read Header Functions              */
+@@ -139,7 +140,7 @@ int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ 
+ int i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+-	str_AnalogInputHeader * s_Header);
++	struct str_AnalogInputHeader * s_Header);
+ 
+ 		/******************************************/
+ 		/*      Eeprom Specific Functions                         */
+@@ -812,7 +813,7 @@ int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
+ 	struct str_DigitalOutputHeader s_DigitalOutputHeader;
+ 	//struct str_TimerMainHeader     s_TimerMainHeader,s_WatchdogMainHeader;
+ 	str_AnalogOutputHeader s_AnalogOutputHeader;
+-	str_AnalogInputHeader s_AnalogInputHeader;
++	struct str_AnalogInputHeader s_AnalogInputHeader;
+ 
+ 	// Read size
+ 	s_MainHeader.w_HeaderSize =
+@@ -1099,7 +1100,7 @@ int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ +----------------------------------------------------------------------------+
+ | Function Name  : int i_EepromReadAnlogInputHeader(unsigned short 					 |
+ |			w_PCIBoardEepromAddress,char *pc_PCIChipInformation,     |
+-|			unsigned short w_Address,str_AnalogInputHeader *s_Header)          |
++|			unsigned short w_Address,struct str_AnalogInputHeader *s_Header)          |
+ +----------------------------------------------------------------------------+
+ | Task              : Read Nalog Output  Header                              |
+ +----------------------------------------------------------------------------+
+@@ -1107,7 +1108,7 @@ int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ |																	 |
+ |		      char *pc_PCIChipInformation  : PCI Chip Type.          |
+ |																	 |
+-|			 str_AnalogInputHeader *s_Header:Anlog Input Header      |
++|			 struct str_AnalogInputHeader *s_Header:Anlog Input Header      |
+ |											   Pointer				 |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+@@ -1119,7 +1120,7 @@ int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ // Reads only for ONE  hardware component
+ int i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+-	str_AnalogInputHeader * s_Header)
++	struct str_AnalogInputHeader * s_Header)
+ {
+ 	unsigned short w_Temp, w_Offset;
+ 	w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,

commit 0a4eb4b6c7c12730254be53d93a67ed2955d5c66
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:07:01 2009 -0400
+
+    Staging: comedi: Remove labpc_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
+index d7641cd920be..c0da5c75b4bb 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc.c
++++ b/drivers/staging/comedi/drivers/ni_labpc.c
+@@ -427,7 +427,7 @@ static const struct labpc_board_struct labpc_boards[] = {
+ static const int dma_buffer_size = 0xff00;	// size in bytes of dma buffer
+ static const int sample_size = 2;	// 2 bytes per sample
+ 
+-#define devpriv ((labpc_private *)dev->private)
++#define devpriv ((struct labpc_private *)dev->private)
+ 
+ static struct comedi_driver driver_labpc = {
+ 	.driver_name = DRV_NAME,
+@@ -653,7 +653,7 @@ static int labpc_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ #endif
+ 
+ 	/* allocate and initialize dev->private */
+-	if (alloc_private(dev, sizeof(labpc_private)) < 0)
++	if (alloc_private(dev, sizeof(struct labpc_private)) < 0)
+ 		return -ENOMEM;
+ 
+ 	// get base address, irq etc. based on bustype
+diff --git a/drivers/staging/comedi/drivers/ni_labpc.h b/drivers/staging/comedi/drivers/ni_labpc.h
+index cf53a94a51a2..6f76db026b9b 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc.h
++++ b/drivers/staging/comedi/drivers/ni_labpc.h
+@@ -46,7 +46,7 @@ struct labpc_board_struct {
+ 	unsigned memory_mapped_io:1;	/* uses memory mapped io instead of ioports */
+ };
+ 
+-typedef struct {
++struct labpc_private {
+ 	struct mite_struct *mite;	// for mite chip on pci-1200
+ 	volatile unsigned long long count;	/* number of data points left to be taken */
+ 	unsigned int ao_value[NUM_AO_CHAN];	// software copy of analog output values
+@@ -72,7 +72,7 @@ typedef struct {
+ 	// function pointers so we can use inb/outb or readb/writeb as appropriate
+ 	unsigned int (*read_byte) (unsigned long address);
+ 	void (*write_byte) (unsigned int byte, unsigned long address);
+-} labpc_private;
++};
+ 
+ int labpc_common_attach(struct comedi_device * dev, unsigned long iobase,
+ 	unsigned int irq, unsigned int dma);
+diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
+index 1e58d2e40ab8..884074ddaac8 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
++++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
+@@ -133,7 +133,7 @@ static int labpc_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 	struct pcmcia_device *link;
+ 
+ 	/* allocate and initialize dev->private */
+-	if (alloc_private(dev, sizeof(labpc_private)) < 0)
++	if (alloc_private(dev, sizeof(struct labpc_private)) < 0)
+ 		return -ENOMEM;
+ 
+ 	// get base address, irq etc. based on bustype

commit 9ad007403fa4326586060e443ee344697daa60ec
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:06:56 2009 -0400
+
+    Staging: comedi: Remove labpc_board_struct typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
+index 37898d8474cd..d7641cd920be 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc.c
++++ b/drivers/staging/comedi/drivers/ni_labpc.c
+@@ -360,7 +360,7 @@ static inline void labpc_writeb(unsigned int byte, unsigned long address)
+ 	writeb(byte, (void *)address);
+ }
+ 
+-static const labpc_board labpc_boards[] = {
++static const struct labpc_board_struct labpc_boards[] = {
+ 	{
+ 	      name:	"lab-pc-1200",
+ 	      ai_speed:10000,
+@@ -422,7 +422,7 @@ static const labpc_board labpc_boards[] = {
+ /*
+  * Useful for shorthand access to the particular board structure
+  */
+-#define thisboard ((labpc_board *)dev->board_ptr)
++#define thisboard ((struct labpc_board_struct *)dev->board_ptr)
+ 
+ static const int dma_buffer_size = 0xff00;	// size in bytes of dma buffer
+ static const int sample_size = 2;	// 2 bytes per sample
+@@ -434,9 +434,9 @@ static struct comedi_driver driver_labpc = {
+ 	.module = THIS_MODULE,
+ 	.attach = labpc_attach,
+ 	.detach = labpc_common_detach,
+-	.num_names = sizeof(labpc_boards) / sizeof(labpc_board),
++	.num_names = sizeof(labpc_boards) / sizeof(struct labpc_board_struct),
+ 	.board_name = &labpc_boards[0].name,
+-	.offset = sizeof(labpc_board),
++	.offset = sizeof(struct labpc_board_struct),
+ };
+ 
+ #ifdef CONFIG_COMEDI_PCI
+diff --git a/drivers/staging/comedi/drivers/ni_labpc.h b/drivers/staging/comedi/drivers/ni_labpc.h
+index b44b0d3d02f1..cf53a94a51a2 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc.h
++++ b/drivers/staging/comedi/drivers/ni_labpc.h
+@@ -32,7 +32,7 @@ enum labpc_register_layout { labpc_plus_layout, labpc_1200_layout };
+ enum transfer_type { fifo_not_empty_transfer, fifo_half_full_transfer,
+ 		isa_dma_transfer };
+ 
+-typedef struct labpc_board_struct {
++struct labpc_board_struct {
+ 	const char *name;
+ 	int device_id;		// device id for pci and pcmcia boards
+ 	int ai_speed;		// maximum input speed in nanoseconds
+@@ -44,7 +44,7 @@ typedef struct labpc_board_struct {
+ 	const int *ai_range_is_unipolar;
+ 	unsigned ai_scan_up:1;	// board can auto scan up in ai channels, not just down
+ 	unsigned memory_mapped_io:1;	/* uses memory mapped io instead of ioports */
+-} labpc_board;
++};
+ 
+ typedef struct {
+ 	struct mite_struct *mite;	// for mite chip on pci-1200
+diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
+index 0c2a196adaff..1e58d2e40ab8 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
++++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
+@@ -81,7 +81,7 @@ static struct pcmcia_device *pcmcia_cur_dev = NULL;
+ 
+ static int labpc_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ 
+-static const labpc_board labpc_cs_boards[] = {
++static const struct labpc_board_struct labpc_cs_boards[] = {
+ 	{
+ 	      name:	"daqcard-1200",
+ 	      device_id:0x103,	// 0x10b is manufacturer id, 0x103 is device id
+@@ -114,16 +114,16 @@ static const labpc_board labpc_cs_boards[] = {
+ /*
+  * Useful for shorthand access to the particular board structure
+  */
+-#define thisboard ((const labpc_board *)dev->board_ptr)
++#define thisboard ((const struct labpc_board_struct *)dev->board_ptr)
+ 
+ static struct comedi_driver driver_labpc_cs = {
+ 	.driver_name = "ni_labpc_cs",
+ 	.module = THIS_MODULE,
+ 	.attach = &labpc_attach,
+ 	.detach = &labpc_common_detach,
+-	.num_names = sizeof(labpc_cs_boards) / sizeof(labpc_board),
++	.num_names = sizeof(labpc_cs_boards) / sizeof(struct labpc_board_struct),
+ 	.board_name = &labpc_cs_boards[0].name,
+-	.offset = sizeof(labpc_board),
++	.offset = sizeof(struct labpc_board_struct),
+ };
+ 
+ static int labpc_attach(struct comedi_device * dev, struct comedi_devconfig * it)

commit 70275063e44f0005149f17a74d03c8e7937b33bc
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:06:51 2009 -0400
+
+    Staging: comedi: Remove str_ADDIDATA_RTDStruct typedef in addi-data/hwdrv_apci3200
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+index a78efb7f2c3f..d25fdf690d1b 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+@@ -93,11 +93,11 @@ static const struct comedi_lrange range_apci3300_ai = { 4, {
+ #define MAX_MODULE				4
+ //END JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+ 
+-typedef struct {
++struct str_ADDIDATA_RTDStruct {
+ 	unsigned int ul_NumberOfValue;
+ 	unsigned int *pul_ResistanceValue;
+ 	unsigned int *pul_TemperatureValue;
+-} str_ADDIDATA_RTDStruct, *pstr_ADDIDATA_RTDStruct;
++};
+ 
+ //BEGIN JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+ struct str_Module {

commit 0a4de47be0cd74c6665a5519c40f692dbbd54110
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:06:45 2009 -0400
+
+    Staging: comedi: Remove str_BoardInfos typedef in addi-data/hwdrv_apci3200
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+index f7c2cff5e932..64dc68c112dd 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+@@ -87,7 +87,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+   int i_Initialised=0;
+   unsigned int ui_InterruptChannelValue[96]; //Buffer
+ */
+-str_BoardInfos s_BoardInfos[100];	// 100 will be the max number of boards to be used
++struct str_BoardInfos s_BoardInfos[100];	// 100 will be the max number of boards to be used
+ //END JK 06.07.04: Management of sevrals boards
+ 
+ //Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+@@ -259,7 +259,7 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ /*+----------------------------------------------------------------------------+*/
+ 
+ void v_GetAPCI3200EepromCalibrationValue(unsigned int dw_PCIBoardEepromAddress,
+-	str_BoardInfos * BoardInformations)
++	struct str_BoardInfos *BoardInformations)
+ {
+ 	unsigned short w_AnalogInputMainHeaderAddress;
+ 	unsigned short w_AnalogInputComponentAddress;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+index 4daace588cc7..a78efb7f2c3f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+@@ -116,7 +116,8 @@ struct str_Module {
+ //END JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+ 
+ //BEGIN JK 06.07.04: Management of sevrals boards
+-typedef struct {
++struct str_BoardInfos {
++
+ 	int i_CJCAvailable;
+ 	int i_CJCPolarity;
+ 	int i_CJCGain;
+@@ -149,7 +150,8 @@ typedef struct {
+ 	int i_NbrOfModule;
+ 	struct str_Module s_Module[MAX_MODULE];
+ 	//End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+-} str_BoardInfos;
++};
++
+ //END JK 06.07.04: Management of sevrals boards
+ 
+ // Hardware Layer  functions for Apci3200

commit ecab384b155816ce1579eeb8f1dcbdbc0e9fe4e0
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:06:40 2009 -0400
+
+    Staging: comedi: Remove str_Module typedef in addi-data/hwdrv_apci3200.h
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+index 9118ef46b495..4daace588cc7 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+@@ -100,7 +100,8 @@ typedef struct {
+ } str_ADDIDATA_RTDStruct, *pstr_ADDIDATA_RTDStruct;
+ 
+ //BEGIN JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+-typedef struct {
++struct str_Module {
++
+ 	// Begin JK 05/08/2003 change for Linux
+ 	unsigned long ul_CurrentSourceCJC;
+ 	unsigned long ul_CurrentSource[5];
+@@ -110,7 +111,8 @@ typedef struct {
+ 	unsigned long ul_GainFactor[8];	// Gain Factor
+ 	unsigned int w_GainValue[10];
+ 	// End CG 15/02/02 Rev 1.0 -> Rev 1.1 : Add Header Type 1
+-} str_Module;
++};
++
+ //END JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+ 
+ //BEGIN JK 06.07.04: Management of sevrals boards
+@@ -145,7 +147,7 @@ typedef struct {
+ 	//Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+ 	int i_ConnectionType;
+ 	int i_NbrOfModule;
+-	str_Module s_Module[MAX_MODULE];
++	struct str_Module s_Module[MAX_MODULE];
+ 	//End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+ } str_BoardInfos;
+ //END JK 06.07.04: Management of sevrals boards

commit 0077f93c5a7fa82857f6b50a3be5f732e0079e1c
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:06:35 2009 -0400
+
+    Staging: comedi: Remove str_AnalogReadInformation typedef in addi-data/hwdrv_apci3120.h
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
+index db5b291a3278..f6755cdfcba2 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
+@@ -165,7 +165,8 @@ static const struct comedi_lrange range_apci3120_ao = { 2, {
+ 
+ #define MAX_ANALOGINPUT_CHANNELS    32
+ 
+-typedef struct {
++struct str_AnalogReadInformation {
++
+ 	unsigned char b_Type;		/* EOC or EOS */
+ 	unsigned char b_InterruptFlag;	/* Interrupt use or not                    */
+ 	unsigned int ui_ConvertTiming;	/* Selection of the convertion time        */
+@@ -173,7 +174,8 @@ typedef struct {
+ 	unsigned int ui_ChannelList[MAX_ANALOGINPUT_CHANNELS];	/* Number of the channel to be read        */
+ 	unsigned int ui_RangeList[MAX_ANALOGINPUT_CHANNELS];	/* Gain of each channel                    */
+ 
+-} str_AnalogReadInformation;
++};
++
+ 
+ // Function Declaration For APCI-3120
+ 

commit 73b0d70aeb089bcfa131d8f14f547dcd933335d6
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:06:19 2009 -0400
+
+    Staging: comedi: Remove str_TimerMainHeader typedef in addi-data/addi_eeprom.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+index e0da604373e3..2e9c15debdb4 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+@@ -93,11 +93,13 @@ struct str_TimerDetails {
+ 	unsigned char b_TimeBase;
+ };
+ 
+-typedef struct {
++struct str_TimerMainHeader {
++
+ 
+ 	unsigned short w_Ntimer;
+ 	struct str_TimerDetails s_TimerDetails[4];	//  supports 4 timers
+-} str_TimerMainHeader;
++};
++
+ 
+ typedef struct {
+ 	unsigned short w_Nchannel;
+@@ -129,7 +131,7 @@ int i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ 
+ int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+-	str_TimerMainHeader * s_Header);
++	struct str_TimerMainHeader * s_Header);
+ 
+ int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+@@ -808,7 +810,7 @@ int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
+ 	struct str_MainHeader s_MainHeader;
+ 	struct str_DigitalInputHeader s_DigitalInputHeader;
+ 	struct str_DigitalOutputHeader s_DigitalOutputHeader;
+-	//str_TimerMainHeader     s_TimerMainHeader,s_WatchdogMainHeader;
++	//struct str_TimerMainHeader     s_TimerMainHeader,s_WatchdogMainHeader;
+ 	str_AnalogOutputHeader s_AnalogOutputHeader;
+ 	str_AnalogInputHeader s_AnalogInputHeader;
+ 
+@@ -995,7 +997,7 @@ int i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ +----------------------------------------------------------------------------+
+ | Function Name  : int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress, |
+ |			char *pc_PCIChipInformation,WORD w_Address,				 |
+-|			str_TimerMainHeader *s_Header)							 |
++|			struct str_TimerMainHeader *s_Header)							 |
+ +----------------------------------------------------------------------------+
+ | Task              : Read Timer or Watchdog Header                          |
+ +----------------------------------------------------------------------------+
+@@ -1003,7 +1005,7 @@ int i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ |																	 |
+ |		      char *pc_PCIChipInformation  : PCI Chip Type.          |
+ |																	 |
+-|			 str_TimerMainHeader *s_Header: Timer Header			 |
++|			 struct str_TimerMainHeader *s_Header: Timer Header			 |
+ |											   Pointer				 |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+@@ -1013,7 +1015,7 @@ int i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ */
+ int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+-	str_TimerMainHeader * s_Header)
++	struct str_TimerMainHeader * s_Header)
+ {
+ 
+ 	unsigned short i, w_Size = 0, w_Temp;

commit cc0ea813f2f3027f43e7233add423be676dd8ff3
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:06:13 2009 -0400
+
+    Staging: comedi: Remove str_TimerDetails typedef in addi-data/addi_eeprom.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+index f7e5a78a3733..e0da604373e3 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+@@ -84,17 +84,19 @@ struct str_DigitalOutputHeader {
+ 
+ // used for timer as well as watchdog
+ 
+-typedef struct {
++struct str_TimerDetails {
++
+ 	unsigned short w_HeaderSize;
+ 	unsigned char b_Resolution;
+ 	unsigned char b_Mode;		// in case of Watchdog it is functionality
+ 	unsigned short w_MinTiming;
+ 	unsigned char b_TimeBase;
+-} str_TimerDetails;
++};
++
+ typedef struct {
+ 
+ 	unsigned short w_Ntimer;
+-	str_TimerDetails s_TimerDetails[4];	//  supports 4 timers
++	struct str_TimerDetails s_TimerDetails[4];	//  supports 4 timers
+ } str_TimerMainHeader;
+ 
+ typedef struct {

commit d2e0cc9ae156b1b9d6143d6b1855e515c93a7997
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:06:08 2009 -0400
+
+    Staging: comedi: Remove str_DigitalOutputHeader typedef in addi-data/addi_eeprom.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+index 6e23dbf28a6b..f7e5a78a3733 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+@@ -76,9 +76,11 @@ struct str_DigitalInputHeader {
+ 	unsigned short w_NinterruptLogic;
+ };
+ 
+-typedef struct {
++struct str_DigitalOutputHeader {
++
+ 	unsigned short w_Nchannel;
+-} str_DigitalOutputHeader;
++};
++
+ 
+ // used for timer as well as watchdog
+ 
+@@ -121,7 +123,7 @@ int i_EepromReadDigitalInputHeader(unsigned short w_PCIBoardEepromAddress,
+ 
+ int i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+-	str_DigitalOutputHeader * s_Header);
++	struct str_DigitalOutputHeader * s_Header);
+ 
+ int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+@@ -803,7 +805,7 @@ int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
+ 	unsigned int ui_Temp;
+ 	struct str_MainHeader s_MainHeader;
+ 	struct str_DigitalInputHeader s_DigitalInputHeader;
+-	str_DigitalOutputHeader s_DigitalOutputHeader;
++	struct str_DigitalOutputHeader s_DigitalOutputHeader;
+ 	//str_TimerMainHeader     s_TimerMainHeader,s_WatchdogMainHeader;
+ 	str_AnalogOutputHeader s_AnalogOutputHeader;
+ 	str_AnalogInputHeader s_AnalogInputHeader;
+@@ -959,7 +961,7 @@ int i_EepromReadDigitalInputHeader(unsigned short w_PCIBoardEepromAddress,
+ +----------------------------------------------------------------------------+
+ | Function Name  : int i_EepromReadDigitalOutputHeader(unsigned short 				 |
+ |			w_PCIBoardEepromAddress,char *pc_PCIChipInformation,	 |
+-|			unsigned short w_Address,str_DigitalOutputHeader *s_Header)	     |
++|			unsigned short w_Address,struct str_DigitalOutputHeader *s_Header)	     |
+ |																	 |
+ +----------------------------------------------------------------------------+
+ | Task              : Read Digital Output Header                             |
+@@ -968,7 +970,7 @@ int i_EepromReadDigitalInputHeader(unsigned short w_PCIBoardEepromAddress,
+ |																	 |
+ |		      char *pc_PCIChipInformation  : PCI Chip Type.          |
+ |																	 |
+-|			 str_DigitalOutputHeader *s_Header: Digital Output Header|
++|			 struct str_DigitalOutputHeader *s_Header: Digital Output Header|
+ |											   Pointer				 |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+@@ -978,7 +980,7 @@ int i_EepromReadDigitalInputHeader(unsigned short w_PCIBoardEepromAddress,
+ */
+ int i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+-	str_DigitalOutputHeader * s_Header)
++	struct str_DigitalOutputHeader * s_Header)
+ {
+ // Read Nbr channels
+ 	s_Header->w_Nchannel =

commit a28f34b7e9c41464bb70a3dfe849efe74084e45d
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:06:03 2009 -0400
+
+    Staging: comedi: Remove str_DigitalInputHeader typedef in addi-data/addi_eeprom.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+index 5184c6de6dba..6e23dbf28a6b 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+@@ -70,11 +70,11 @@ struct str_MainHeader {
+ 	struct str_Functionality s_Functions[7];
+ };
+ 
+-typedef struct {
++struct str_DigitalInputHeader {
+ 	unsigned short w_Nchannel;
+ 	unsigned char b_Interruptible;
+ 	unsigned short w_NinterruptLogic;
+-} str_DigitalInputHeader;
++};
+ 
+ typedef struct {
+ 	unsigned short w_Nchannel;
+@@ -117,7 +117,7 @@ int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
+ 
+ int i_EepromReadDigitalInputHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+-	str_DigitalInputHeader * s_Header);
++	struct str_DigitalInputHeader * s_Header);
+ 
+ int i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+@@ -802,7 +802,7 @@ int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
+ 	unsigned short w_Temp, i, w_Count = 0;
+ 	unsigned int ui_Temp;
+ 	struct str_MainHeader s_MainHeader;
+-	str_DigitalInputHeader s_DigitalInputHeader;
++	struct str_DigitalInputHeader s_DigitalInputHeader;
+ 	str_DigitalOutputHeader s_DigitalOutputHeader;
+ 	//str_TimerMainHeader     s_TimerMainHeader,s_WatchdogMainHeader;
+ 	str_AnalogOutputHeader s_AnalogOutputHeader;
+@@ -914,7 +914,7 @@ int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
+ +----------------------------------------------------------------------------+
+ | Function Name  : int i_EepromReadDigitalInputHeader(unsigned short 					 |
+ |			w_PCIBoardEepromAddress,char *pc_PCIChipInformation,	 |
+-|			unsigned short w_Address,str_DigitalInputHeader *s_Header)		 |
++|			unsigned short w_Address,struct str_DigitalInputHeader *s_Header)		 |
+ |																	 |
+ +----------------------------------------------------------------------------+
+ | Task              : Read Digital Input Header                              |
+@@ -923,7 +923,7 @@ int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
+ |																	 |
+ |		      char *pc_PCIChipInformation  : PCI Chip Type.          |
+ |																	 |
+-|			 str_DigitalInputHeader *s_Header: Digita Input Header   |
++|			 struct str_DigitalInputHeader *s_Header: Digita Input Header   |
+ |												   Pointer			 |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+@@ -933,7 +933,7 @@ int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
+ */
+ int i_EepromReadDigitalInputHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+-	str_DigitalInputHeader * s_Header)
++	struct str_DigitalInputHeader *s_Header)
+ {
+ 	unsigned short w_Temp;
+ 

commit 8881b568bf6665a6705daf2251ce40526ee4691d
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:05:57 2009 -0400
+
+    Staging: comedi: Remove str_MainHeader typedef in addi-data/addi_eeprom.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+index 10f8ed88205c..5184c6de6dba 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+@@ -64,11 +64,11 @@ struct str_Functionality {
+ 	unsigned short w_Address;
+ };
+ 
+-typedef struct {
++struct str_MainHeader {
+ 	unsigned short w_HeaderSize;
+ 	unsigned char b_Nfunctions;
+ 	struct str_Functionality s_Functions[7];
+-} str_MainHeader;
++};
+ 
+ typedef struct {
+ 	unsigned short w_Nchannel;
+@@ -801,7 +801,7 @@ int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
+ {
+ 	unsigned short w_Temp, i, w_Count = 0;
+ 	unsigned int ui_Temp;
+-	str_MainHeader s_MainHeader;
++	struct str_MainHeader s_MainHeader;
+ 	str_DigitalInputHeader s_DigitalInputHeader;
+ 	str_DigitalOutputHeader s_DigitalOutputHeader;
+ 	//str_TimerMainHeader     s_TimerMainHeader,s_WatchdogMainHeader;

commit e320671e6356ad589b7433c3fd5eff4c742a500e
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:05:52 2009 -0400
+
+    Staging: comedi: Remove addi_private typedef in addi-data
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+index cc21587657cc..50f59fa97d24 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+@@ -72,7 +72,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ //Update-0.7.57->0.7.68MODULE_DESCRIPTION("Comedi ADDI-DATA module");
+ //Update-0.7.57->0.7.68MODULE_LICENSE("GPL");
+ 
+-#define devpriv ((addi_private *)dev->private)
++#define devpriv ((struct addi_private *)dev->private)
+ #define this_board ((struct addi_board *)dev->board_ptr)
+ 
+ #if defined(CONFIG_APCI_1710) || defined(CONFIG_APCI_3200) || defined(CONFIG_APCI_3300)
+@@ -2575,7 +2575,7 @@ static int i_ADDI_Attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	sprintf(c_Identifier, "Addi-Data GmbH Comedi %s",
+ 		this_board->pc_DriverName);
+ 
+-	if ((ret = alloc_private(dev, sizeof(addi_private))) < 0) {
++	if ((ret = alloc_private(dev, sizeof(struct addi_private))) < 0) {
+ 	  	return -ENOMEM;
+ 	}
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+index 60e7291e496d..aeb3df00a752 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+@@ -345,7 +345,7 @@ union str_ModuleInfo {
+ };
+ 
+ /* Private structure for the addi_apci3120 driver */
+-typedef struct {
++struct addi_private {
+ 
+ 	int iobase;
+ 	int i_IobaseAmcc;	// base+size for AMCC chip
+@@ -434,7 +434,7 @@ typedef struct {
+ 	union str_ModuleInfo s_ModuleInfo[4];
+ 	unsigned int ul_TTLPortConfiguration[10];
+ 
+-} addi_private;
++};
+ 
+ static unsigned short pci_list_builded;	/* set to 1 when list of card is known */
+ 

commit b4ce4f165c4d081f6b6e969f800d9e37c3ac1d73
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:05:47 2009 -0400
+
+    Staging: comedi: Remove str_ModuleInfo typedef in addi-data
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+index fe98981e754e..60e7291e496d 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+@@ -201,9 +201,9 @@ struct addi_board {
+ 					 struct comedi_insn *insn, unsigned int *data);
+ };
+ 
+-//MODULE INFO STRUCTURE
++/* MODULE INFO STRUCTURE */
+ 
+-typedef union {
++union str_ModuleInfo {
+ 	/* Incremental counter infos */
+ 	struct {
+ 		union {
+@@ -342,7 +342,7 @@ typedef union {
+ 		unsigned char b_CDAReadFIFOOverflow;
+ 	} s_CDAModuleInfo;
+ 
+-} str_ModuleInfo;
++};
+ 
+ /* Private structure for the addi_apci3120 driver */
+ typedef struct {
+@@ -431,7 +431,7 @@ typedef struct {
+ 		} s_FIFOInterruptParameters[APCI1710_SAVE_INTERRUPT];
+ 	} s_InterruptParameters;
+ 
+-	str_ModuleInfo s_ModuleInfo[4];
++	union str_ModuleInfo s_ModuleInfo[4];
+ 	unsigned int ul_TTLPortConfiguration[10];
+ 
+ } addi_private;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+index c79bf473220d..098cd792e035 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+@@ -261,7 +261,7 @@ void v_APCI1710_Interrupt(int irq, void *d)
+ 	unsigned int ul_82X54InterruptStatus;
+ 	unsigned int ul_StatusRegister;
+ 
+-	str_ModuleInfo *ps_ModuleInfo;
++	union str_ModuleInfo *ps_ModuleInfo;
+ 
+ 	printk("APCI1710 Interrupt\n");
+ 	for (b_ModuleCpt = 0; b_ModuleCpt < 4; b_ModuleCpt++, ps_ModuleInfo++) {

commit 6a770eca8a679741dbe32207858638bb0ca71e38
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:05:41 2009 -0400
+
+    Staging: comedi: Remove boardtype typedef in addi-data
+    
+    typedef for boardtype removed and struct renamed to
+    addi_board
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+index 7e3193ce446e..cc21587657cc 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+@@ -73,7 +73,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ //Update-0.7.57->0.7.68MODULE_LICENSE("GPL");
+ 
+ #define devpriv ((addi_private *)dev->private)
+-#define this_board ((boardtype *)dev->board_ptr)
++#define this_board ((struct addi_board *)dev->board_ptr)
+ 
+ #if defined(CONFIG_APCI_1710) || defined(CONFIG_APCI_3200) || defined(CONFIG_APCI_3300)
+ //BYTE b_SaveFPUReg [94];
+@@ -219,7 +219,7 @@ static DEFINE_PCI_DEVICE_TABLE(addi_apci_tbl) = {
+ 
+ MODULE_DEVICE_TABLE(pci, addi_apci_tbl);
+ 
+-static const boardtype boardtypes[] = {
++static const struct addi_board boardtypes[] = {
+ #ifdef CONFIG_APCI_3120
+ 	{"apci3120",
+ 			APCI3120_BOARD_VENDOR_ID,
+@@ -2525,7 +2525,7 @@ static const boardtype boardtypes[] = {
+ #endif
+ };
+ 
+-#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
++#define n_boardtypes (sizeof(boardtypes)/sizeof(struct addi_board))
+ 
+ struct comedi_driver driver_addi = {
+       driver_name:"addi_common",
+@@ -2534,7 +2534,7 @@ struct comedi_driver driver_addi = {
+       detach:i_ADDI_Detach,
+       num_names:n_boardtypes,
+       board_name:&boardtypes[0].pc_DriverName,
+-      offset:sizeof(boardtype),
++      offset:sizeof(struct addi_board),
+ };
+ 
+ COMEDI_PCI_INITCLEANUP(driver_addi, addi_apci_tbl);
+@@ -2662,7 +2662,7 @@ static int i_ADDI_Attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 		it->options[2]);
+ 	dev->irq = irq;
+ 
+-	// Read eepeom and fill boardtype Structure
++	// Read eepeom and fill addi_board Structure
+ 
+ 	if (this_board->i_PCIEeprom) {
+ 		printk("\nPCI Eeprom used");
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+index badc38304611..fe98981e754e 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+@@ -61,7 +61,7 @@
+ /* Structures */
+ 
+ /* structure for the boardtype */
+-typedef struct {
++struct addi_board {
+ 	const char *pc_DriverName;	// driver name
+ 	int i_VendorId;		//PCI vendor a device ID of card
+ 	int i_DeviceId;
+@@ -199,7 +199,7 @@ typedef struct {
+ 	int (*i_hwdr_WriteTTLIOChlOnOff)(struct comedi_device *dev,
+ 					 struct comedi_subdevice *s,
+ 					 struct comedi_insn *insn, unsigned int *data);
+-} boardtype;
++};
+ 
+ //MODULE INFO STRUCTURE
+ 
+@@ -406,7 +406,7 @@ typedef struct {
+ 
+ 	/* Pointer to the current process */
+ 	struct task_struct *tsk_Current;
+-	boardtype *ps_BoardInfo;
++	struct addi_board *ps_BoardInfo;
+ 
+ 	/* Hardware board infos for 1710 */
+ 	struct {

commit 1c09a82cedcda1541adf81f19d86a7773f3f87c6
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:05:36 2009 -0400
+
+    Staging: comedi: Remove PCRANGE typedef in addi-data
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+index 1050a5208c44..badc38304611 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+@@ -36,10 +36,6 @@
+ #define ERROR	-1
+ #define SUCCESS	1
+ 
+-/* variable type definition */
+-
+-typedef const struct comedi_lrange *PCRANGE;
+-
+ #define LOBYTE(W)	(unsigned char)((W) & 0xFF)
+ #define HIBYTE(W)	(unsigned char)(((W) >> 8) & 0xFF)
+ #define MAKEWORD(H, L)	(unsigned short)((L) | ((H) << 8))
+@@ -81,15 +77,15 @@ typedef struct {
+ 	int i_NbrAoChannel;	// num of D/A chans
+ 	int i_AiMaxdata;	// resolution of A/D
+ 	int i_AoMaxdata;	// resolution of D/A
+-	PCRANGE pr_AiRangelist;	// rangelist for A/D
+-	PCRANGE pr_AoRangelist;	// rangelist for D/A
++        const struct comedi_lrange *pr_AiRangelist;	/* rangelist for A/D */
++        const struct comedi_lrange *pr_AoRangelist;	/* rangelist for D/A */
+ 
+ 	int i_NbrDiChannel;	// Number of DI channels
+ 	int i_NbrDoChannel;	// Number of DO channels
+ 	int i_DoMaxdata;	// data to set all chanels high
+ 
+ 	int i_NbrTTLChannel;	// Number of TTL channels
+-	PCRANGE pr_TTLRangelist;	// rangelist for TTL
++	const struct comedi_lrange *pr_TTLRangelist;	/* rangelist for TTL */
+ 
+ 	int i_Dma;		// dma present or not
+ 	int i_Timer;		//   timer subdevice present or not

commit a3435c92d0625cbba28bd12bbbf708bbf5675f3f
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:05:30 2009 -0400
+
+    Staging: comedi: Remove ULONG_PTR typedef in addi-data
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+index 1066150eb796..7e3193ce446e 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+@@ -2638,7 +2638,7 @@ static int i_ADDI_Attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 		devpriv->i_IobaseReserved = (int) io_addr[3];
+ 		printk("\nioremap begin");
+ 		devpriv->dw_AiBase =
+-			(ULONG_PTR) ioremap(io_addr[3],
++			(unsigned long ) ioremap(io_addr[3],
+ 			this_board->i_IorangeBase3);
+ 		printk("\nioremap end");
+ 	}
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+index a1b363d56f38..1050a5208c44 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+@@ -37,7 +37,6 @@
+ #define SUCCESS	1
+ 
+ /* variable type definition */
+-typedef unsigned long ULONG_PTR;
+ 
+ typedef const struct comedi_lrange *PCRANGE;
+ 
+@@ -356,7 +355,7 @@ typedef struct {
+ 	int i_IobaseAmcc;	// base+size for AMCC chip
+ 	int i_IobaseAddon;	//addon base address
+ 	int i_IobaseReserved;
+-	ULONG_PTR dw_AiBase;
++	unsigned long dw_AiBase;
+ 	struct pcilst_struct *amcc;	// ptr too AMCC data
+ 	unsigned char allocated;		// we have blocked card
+ 	unsigned char b_ValidDriver;	// driver is ok

commit 756e9d7ca6292ba21a6a63bf35ed1abc5250b98d
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:05:25 2009 -0400
+
+    Staging: comedi: Remove DWORD and *PDWORD typedefs in addi-data
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+index 135228caf861..3f8ffa2c3e87 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+@@ -234,7 +234,7 @@ int i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, struct comedi_sub
+ 	unsigned char b_HardwareGateLevel;
+ 
+ 	//BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz
+-	DWORD dw_Test = 0;
++	unsigned int dw_Test = 0;
+ 	//END JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz
+ 
+ 	i_ReturnValue = insn->n;
+@@ -319,7 +319,7 @@ int i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, struct comedi_sub
+ 											   devpriv->s_ModuleInfo [b_ModulNbr].
+ 											   s_82X54ModuleInfo.
+ 											   s_82X54TimerInfo  [b_TimerNbr].
+-											   dw_ConfigurationWord = (DWORD) (((b_HardwareGateLevel         << 0) & 0x1) |
++											   dw_ConfigurationWord = (unsigned int) (((b_HardwareGateLevel         << 0) & 0x1) |
+ 											   ((b_InputClockLevel           << 1) & 0x2) |
+ 											   (((~b_OutputLevel       & 1)  << 2) & 0x4) |
+ 											   ((b_InputClockSelection       << 4) & 0x10));
+@@ -329,12 +329,12 @@ int i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, struct comedi_sub
+ 												b_InputClockSelection = 2;
+ 											}
+ 
+-											devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord = (DWORD)(((b_HardwareGateLevel << 0) & 0x1) | ((b_InputClockLevel << 1) & 0x2) | (((~b_OutputLevel & 1) << 2) & 0x4) | ((b_InputClockSelection << 4) & 0x30));
++											devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord = (unsigned int)(((b_HardwareGateLevel << 0) & 0x1) | ((b_InputClockLevel << 1) & 0x2) | (((~b_OutputLevel & 1) << 2) & 0x4) | ((b_InputClockSelection << 4) & 0x30));
+ 											//END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz
+ 											outl(devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord, devpriv->s_BoardInfos.ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
+ 
+ 											/* Initialise the 82X54 Timer */
+-											outl((DWORD) b_TimerMode, devpriv->s_BoardInfos.ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
++											outl((unsigned int) b_TimerMode, devpriv->s_BoardInfos.ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
+ 
+ 											/* Write the reload value */
+ 											outl(ul_ReloadValue, devpriv->s_BoardInfos.ui_Address + 0 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
+@@ -453,7 +453,7 @@ int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device * dev,
+ 					   struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_DummyRead;
++	unsigned int dw_DummyRead;
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_TimerNbr;
+ 	unsigned char b_ActionType;
+@@ -853,7 +853,7 @@ int i_APCI1710_GetTimerOutputLevel(struct comedi_device * dev,
+ 				   unsigned char * pb_OutputLevel)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_TimerStatus;
++	unsigned int dw_TimerStatus;
+ 
+ 	/* Test the module number */
+ 	if (b_ModulNbr < 4) {
+@@ -932,7 +932,7 @@ int i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
+ 				      unsigned char * pb_TimerStatus)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_TimerStatus;
++	unsigned int dw_TimerStatus;
+ 
+ 	/* Test the module number */
+ 	if (b_ModulNbr < 4) {
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+index f615e1f4c2ab..26f9d91e8130 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+@@ -139,7 +139,7 @@ int i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_su
+ 	unsigned int ul_TimingInterval = 0;
+ 	unsigned int ul_RealTimingInterval = 0;
+ 	double d_RealTimingInterval = 0;
+-	DWORD dw_ModeArray[8] =
++	unsigned int dw_ModeArray[8] =
+ 		{ 0x01, 0x05, 0x00, 0x04, 0x02, 0x0E, 0x0A, 0x06 };
+ 	unsigned char b_ModulNbr, b_ChronoMode, b_PCIInputClock, b_TimingUnit;
+ 
+@@ -1198,7 +1198,7 @@ int i_APCI1710_GetChronoProgressStatus(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char * pb_ChronoStatus)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_Status;
++	unsigned int dw_Status;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -1360,8 +1360,8 @@ int i_APCI1710_ReadChronoValue(struct comedi_device * dev,
+ 	unsigned int ui_TimeOut, unsigned char * pb_ChronoStatus, unsigned int * pul_ChronoValue)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_Status;
+-	DWORD dw_TimeOut = 0;
++	unsigned int dw_Status;
++	unsigned int dw_TimeOut = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -1881,7 +1881,7 @@ int i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device * dev,
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned char b_ModulNbr, b_OutputChannel, b_InputChannel, b_IOType;
+-	DWORD dw_Status;
++	unsigned int dw_Status;
+ 	unsigned char * pb_ChannelStatus;
+ 	unsigned char * pb_PortValue;
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+index 1e0e0b394ce5..819d46f24c21 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+@@ -105,7 +105,7 @@ int i_APCI1710_InsnConfigDigitalIO(struct comedi_device * dev, struct comedi_sub
+ 	unsigned char b_ModulNbr, b_ChannelAMode, b_ChannelBMode;
+ 	unsigned char b_MemoryOnOff, b_ConfigType;
+ 	int i_ReturnValue = 0;
+-	DWORD dw_WriteConfig = 0;
++	unsigned int dw_WriteConfig = 0;
+ 
+ 	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+ 	b_ConfigType = (unsigned char) data[0];	// Memory or  Init
+@@ -197,7 +197,7 @@ int i_APCI1710_InsnConfigDigitalIO(struct comedi_device * dev, struct comedi_sub
+ 	/*****************************************/
+ 
+ 					dw_WriteConfig =
+-						(DWORD) (b_ChannelAMode |
++						(unsigned int) (b_ChannelAMode |
+ 						(b_ChannelBMode * 2));
+ 
+ 	/***************************/
+@@ -297,7 +297,7 @@ int i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_StatusReg;
++	unsigned int dw_StatusReg;
+ 	unsigned char b_ModulNbr, b_InputChannel;
+ 	unsigned char * pb_ChannelStatus;
+ 	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+@@ -485,7 +485,7 @@ int i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_WriteValue = 0;
++	unsigned int dw_WriteValue = 0;
+ 	unsigned char b_ModulNbr, b_OutputChannel;
+ 	i_ReturnValue = insn->n;
+ 	b_ModulNbr = CR_AREF(insn->chanspec);
+@@ -732,8 +732,8 @@ int i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_WriteValue = 0;
+-	DWORD dw_StatusReg;
++	unsigned int dw_WriteValue = 0;
++	unsigned int dw_StatusReg;
+ 	unsigned char b_ModulNbr, b_PortValue;
+ 	unsigned char b_PortOperation, b_PortOnOFF;
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+index 8b65cd80a78e..3292abd6088e 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+@@ -549,7 +549,7 @@ int i_APCI1710_CounterAutoTest(struct comedi_device * dev, unsigned char * pb_Te
+ {
+ 	unsigned char b_ModulCpt = 0;
+ 	int i_ReturnValue = 0;
+-	DWORD dw_LathchValue;
++	unsigned int dw_LathchValue;
+ 
+ 	*pb_TestStatus = 0;
+ 
+@@ -1496,7 +1496,7 @@ int i_APCI1710_InitFrequencyMeasurement(struct comedi_device * dev,
+ 	int i_ReturnValue = 0;
+ 	unsigned int ul_TimerValue = 0;
+ 	double d_RealTimingInterval;
+-	DWORD dw_Status = 0;
++	unsigned int dw_Status = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -2301,7 +2301,7 @@ int i_APCI1710_SetInputFilter(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char b_PCIInputClock, unsigned char b_Filter)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_Status = 0;
++	unsigned int dw_Status = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -4197,7 +4197,7 @@ int i_APCI1710_ReadLatchRegisterStatus(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char b_LatchReg, unsigned char * pb_LatchStatus)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_LatchReg;
++	unsigned int dw_LatchReg;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -4368,7 +4368,7 @@ int i_APCI1710_Read16BitCounterValue(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char b_SelectedCounter, unsigned int * pui_CounterValue)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_LathchValue = 0;
++	unsigned int dw_LathchValue = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -4539,7 +4539,7 @@ int i_APCI1710_GetIndexStatus(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char * pb_IndexStatus)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_StatusReg = 0;
++	unsigned int dw_StatusReg = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -4623,7 +4623,7 @@ int i_APCI1710_GetReferenceStatus(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char * pb_ReferenceStatus)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_StatusReg = 0;
++	unsigned int dw_StatusReg = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -4707,7 +4707,7 @@ int i_APCI1710_GetUASStatus(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char * pb_UASStatus)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_StatusReg = 0;
++	unsigned int dw_StatusReg = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -4775,7 +4775,7 @@ int i_APCI1710_GetCBStatus(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char * pb_CBStatus)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_StatusReg = 0;
++	unsigned int dw_StatusReg = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -4857,7 +4857,7 @@ int i_APCI1710_Get16BitCBStatus(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char * pb_CBStatusCounter0, unsigned char * pb_CBStatusCounter1)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_StatusReg = 0;
++	unsigned int dw_StatusReg = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -4970,7 +4970,7 @@ int i_APCI1710_GetUDStatus(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char * pb_UDStatus)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_StatusReg = 0;
++	unsigned int dw_StatusReg = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -5044,7 +5044,7 @@ int i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char * pb_UDStatus)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_StatusReg = 0;
++	unsigned int dw_StatusReg = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -5151,7 +5151,7 @@ int i_APCI1710_ReadFrequencyMeasurement(struct comedi_device * dev,
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int ui_16BitValue;
+-	DWORD dw_StatusReg;
++	unsigned int dw_StatusReg;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+index 8071d63e7b4f..637898cef12d 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+@@ -127,7 +127,7 @@ int i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_IntRegister;
++	unsigned int dw_IntRegister;
+ 
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_PulseEncoderNbr;
+@@ -712,7 +712,7 @@ int i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_StatusRegister;
++	unsigned int dw_StatusRegister;
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_PulseEncoderNbr;
+ 	unsigned char * pb_Status;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+index 93552bd5e508..2ebb121c2d22 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+@@ -191,7 +191,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 	int i_ReturnValue = 0;
+ 	unsigned int ul_LowTimerValue = 0;
+ 	unsigned int ul_HighTimerValue = 0;
+-	DWORD dw_Command;
++	unsigned int dw_Command;
+ 	double d_RealLowTiming = 0;
+ 	double d_RealHighTiming = 0;
+ 
+@@ -1546,8 +1546,8 @@ int i_APCI1710_GetPWMInitialisation(struct comedi_device * dev,
+ 	unsigned char * pb_ExternGate, unsigned char * pb_InterruptEnable, unsigned char * pb_Enable)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_Status;
+-	DWORD dw_Command;
++	unsigned int dw_Status;
++	unsigned int dw_Command;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -1814,8 +1814,8 @@ int i_APCI1710_EnablePWM(struct comedi_device * dev,
+ 	unsigned char b_StopLevel, unsigned char b_ExternGate, unsigned char b_InterruptEnable)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_Status;
+-	DWORD dw_Command;
++	unsigned int dw_Status;
++	unsigned int dw_Command;
+ 
+ 	devpriv->tsk_Current = current;	// Save the current process task structure
+ 	/**************************/
+@@ -2065,7 +2065,7 @@ int i_APCI1710_EnablePWM(struct comedi_device * dev,
+ int i_APCI1710_DisablePWM(struct comedi_device * dev, unsigned char b_ModulNbr, unsigned char b_PWM)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_Status;
++	unsigned int dw_Status;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -2199,8 +2199,8 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 	unsigned int ul_HighTimerValue = 0;
+ 	unsigned int ul_RealLowTiming = 0;
+ 	unsigned int ul_RealHighTiming = 0;
+-	DWORD dw_Status;
+-	DWORD dw_Command;
++	unsigned int dw_Status;
++	unsigned int dw_Command;
+ 	double d_RealLowTiming = 0;
+ 	double d_RealHighTiming = 0;
+ 
+@@ -3464,7 +3464,7 @@ int i_APCI1710_InsnReadGetPWMStatus(struct comedi_device * dev, struct comedi_su
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_Status;
++	unsigned int dw_Status;
+ 
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_PWM;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+index 7e61305cec3b..acf421b7a821 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+@@ -408,11 +408,11 @@ int i_APCI1710_InsnReadSSIValue(struct comedi_device * dev, struct comedi_subdev
+ 	unsigned char b_Length;
+ 	unsigned char b_Schift;
+ 	unsigned char b_SSICpt;
+-	DWORD dw_And;
+-	DWORD dw_And1;
+-	DWORD dw_And2;
+-	DWORD dw_StatusReg;
+-	DWORD dw_CounterValue;
++	unsigned int dw_And;
++	unsigned int dw_And1;
++	unsigned int dw_And2;
++	unsigned int dw_StatusReg;
++	unsigned int dw_CounterValue;
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_SelectedSSI;
+ 	unsigned char b_ReadType;
+@@ -739,7 +739,7 @@ int i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device * dev, struct comedi_su
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_StatusReg;
++	unsigned int dw_StatusReg;
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_InputChannel;
+ 	unsigned char * pb_ChannelStatus;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+index a0aa24fbfbb4..03da9db2b31d 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+@@ -135,7 +135,7 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int ul_TimerValue = 0;
+-	DWORD dw_Command;
++	unsigned int dw_Command;
+ 	double d_RealTimingInterval = 0;
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_TorCounter;
+@@ -991,9 +991,9 @@ int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_Status;
+-	DWORD dw_DummyRead;
+-	DWORD dw_ConfigReg;
++	unsigned int dw_Status;
++	unsigned int dw_DummyRead;
++	unsigned int dw_ConfigReg;
+ 	unsigned char b_ModulNbr, b_Action;
+ 	unsigned char b_TorCounter;
+ 	unsigned char b_InputMode;
+@@ -1464,7 +1464,7 @@ int i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_Status;
++	unsigned int dw_Status;
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_TorCounter;
+ 	unsigned char * pb_TimingUnit;
+@@ -1704,8 +1704,8 @@ int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_Status;
+-	DWORD dw_TimeOut = 0;
++	unsigned int dw_Status;
++	unsigned int dw_TimeOut = 0;
+ 
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_TorCounter;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+index b8a0ee37319e..2cd0209e143d 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+@@ -410,7 +410,7 @@ int i_APCI1710_InsnBitsReadTTLIO(struct comedi_device * dev, struct comedi_subde
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_StatusReg;
++	unsigned int dw_StatusReg;
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_SelectedPort;
+ 	unsigned char b_InputChannel;
+@@ -659,7 +659,7 @@ int i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_StatusReg;
++	unsigned int dw_StatusReg;
+ 	unsigned char b_ModulNbr;
+ 	unsigned int * pul_PortValue;
+ 
+@@ -829,7 +829,7 @@ int i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_ReturnValue = 0;
+-	DWORD dw_StatusReg = 0;
++	unsigned int dw_StatusReg = 0;
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_OutputChannel;
+ 	unsigned int ui_State;
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
+index de49dca42e83..0328ecac4550 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
+@@ -51,14 +51,14 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*+----------------------------------------------------------------------------+*/
+ /*| Function   Name   : int i_AddiHeaderRW_ReadEeprom                          |*/
+ /*|                               (int    i_NbOfWordsToRead,                   |*/
+-/*|                                DWORD dw_PCIBoardEepromAddress,             |*/
++/*|                                unsigned int dw_PCIBoardEepromAddress,             |*/
+ /*|                                unsigned short   w_EepromStartAddress,                |*/
+ /*|                                unsigned short * pw_DataRead)                          |*/
+ /*+----------------------------------------------------------------------------+*/
+ /*| Task              : Read word from the 5920 eeprom.                        |*/
+ /*+----------------------------------------------------------------------------+*/
+ /*| Input Parameters  : int    i_NbOfWordsToRead : Nbr. of word to read        |*/
+-/*|                     DWORD dw_PCIBoardEepromAddress : Address of the eeprom |*/
++/*|                     unsigned int dw_PCIBoardEepromAddress : Address of the eeprom |*/
+ /*|                     unsigned short   w_EepromStartAddress : Eeprom strat address     |*/
+ /*+----------------------------------------------------------------------------+*/
+ /*| Output Parameters : unsigned short * pw_DataRead : Read data                          |*/
+@@ -67,10 +67,10 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*+----------------------------------------------------------------------------+*/
+ 
+ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+-	DWORD dw_PCIBoardEepromAddress,
++	unsigned int dw_PCIBoardEepromAddress,
+ 	unsigned short w_EepromStartAddress, unsigned short * pw_DataRead)
+ {
+-	DWORD dw_eeprom_busy = 0;
++	unsigned int dw_eeprom_busy = 0;
+ 	int i_Counter = 0;
+ 	int i_WordCounter;
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h
+index 7e4415772bc0..1e5ddd4516aa 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h
+@@ -23,5 +23,5 @@
+ #define NVCMD_BEGIN_WRITE	(0x6 << 5)	/* EEPROM begin write command */
+ 
+ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+-			      DWORD dw_PCIBoardEepromAddress,
++			      unsigned int dw_PCIBoardEepromAddress,
+ 			      unsigned short w_EepromStartAddress, unsigned short * pw_DataRead);
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+index b0bacf8420f3..1066150eb796 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+@@ -2563,7 +2563,7 @@ static int i_ADDI_Attach(struct comedi_device * dev, struct comedi_devconfig * i
+ {
+ 	struct comedi_subdevice *s;
+ 	int ret, pages, i, n_subdevices;
+-	DWORD dw_Dummy;
++	unsigned int dw_Dummy;
+ 	resource_size_t io_addr[5];
+ 	unsigned int irq;
+ 	resource_size_t iobase_a, iobase_main, iobase_addon, iobase_reserved;
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+index 6b9f08cfe11d..a1b363d56f38 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+@@ -37,7 +37,6 @@
+ #define SUCCESS	1
+ 
+ /* variable type definition */
+-typedef unsigned int DWORD, *PDWORD;	/* 32-bit */
+ typedef unsigned long ULONG_PTR;
+ 
+ typedef const struct comedi_lrange *PCRANGE;
+@@ -219,7 +218,7 @@ typedef union {
+ 				unsigned char b_ModeRegister3;
+ 				unsigned char b_ModeRegister4;
+ 			} s_ByteModeRegister;
+-			DWORD dw_ModeRegister1_2_3_4;
++			unsigned int dw_ModeRegister1_2_3_4;
+ 		} s_ModeRegister;
+ 
+ 		struct {
+@@ -254,7 +253,7 @@ typedef union {
+ 		unsigned char b_ChannelAMode;
+ 		unsigned char b_ChannelBMode;
+ 		unsigned char b_OutputMemoryEnabled;
+-		DWORD dw_OutputMemory;
++		unsigned int dw_OutputMemory;
+ 	} s_DigitalIOInfo;
+ 
+       /*********************/
+@@ -268,7 +267,7 @@ typedef union {
+ 			unsigned char b_InputClockLevel;
+ 			unsigned char b_OutputLevel;
+ 			unsigned char b_HardwareGateLevel;
+-			DWORD dw_ConfigurationWord;
++			unsigned int dw_ConfigurationWord;
+ 		} s_82X54TimerInfo[3];
+ 		unsigned char b_InterruptMask;
+ 	} s_82X54ModuleInfo;
+@@ -284,7 +283,7 @@ typedef union {
+ 		unsigned char b_TimingUnit;
+ 		unsigned char b_CycleMode;
+ 		double d_TimingInterval;
+-		DWORD dw_ConfigReg;
++		unsigned int dw_ConfigReg;
+ 	} s_ChronoModuleInfo;
+ 
+       /***********************/
+@@ -295,9 +294,9 @@ typedef union {
+ 		struct {
+ 			unsigned char b_PulseEncoderInit;
+ 		} s_PulseEncoderInfo[4];
+-		DWORD dw_SetRegister;
+-		DWORD dw_ControlRegister;
+-		DWORD dw_StatusRegister;
++		unsigned int dw_SetRegister;
++		unsigned int dw_ControlRegister;
++		unsigned int dw_StatusRegister;
+ 	} s_PulseEncoderModuleInfo;
+ 
+ 	/* Tor conter infos */
+@@ -372,7 +371,7 @@ typedef struct {
+ 	unsigned int ui_AiChannelList[32];	// actual chanlist
+ 	unsigned char b_AiChannelConfiguration[32];	// actual chanlist
+ 	unsigned int ui_AiReadData[32];
+-	DWORD dw_AiInitialised;
++	unsigned int dw_AiInitialised;
+ 	unsigned int ui_AiTimer0;	//Timer Constant for Timer0
+ 	unsigned int ui_AiTimer1;	//Timer constant for Timer1
+ 	unsigned int ui_AiFlags;
+@@ -421,7 +420,7 @@ typedef struct {
+ 		unsigned char b_InterruptNbr;	/* Board interrupt number */
+ 		unsigned char b_SlotNumber;	/* PCI slot number */
+ 		unsigned char b_BoardVersion;
+-		DWORD dw_MolduleConfiguration[4];	/* Module config */
++		unsigned int dw_MolduleConfiguration[4];	/* Module config */
+ 	} s_BoardInfos;
+ 
+ 	/* Interrupt infos */
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+index e35e282d209e..10f8ed88205c 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+@@ -51,12 +51,6 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ #define EE76_CMD_LEN    	13	// bits in instructions
+ #define EE_READ         	0x0180	// 01 1000 0000 read instruction
+ 
+-#define PDWORD				unsigned int  *
+-
+-#ifndef DWORD
+-#define	DWORD				unsigned int
+-#endif
+-
+ #define EEPROM_DIGITALINPUT 			0
+ #define EEPROM_DIGITALOUTPUT			1
+ #define EEPROM_ANALOGINPUT				2
+@@ -147,11 +141,11 @@ int i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress,
+ unsigned short w_EepromReadWord(unsigned short w_PCIBoardEepromAddress, char *pc_PCIChipInformation,
+ 	unsigned short w_EepromStartAddress);
+ void v_EepromWaitBusy(unsigned short w_PCIBoardEepromAddress);
+-void v_EepromClock76(DWORD dw_Address, DWORD dw_RegisterValue);
++void v_EepromClock76(unsigned int dw_Address, unsigned int dw_RegisterValue);
+ void v_EepromWaitBusy(unsigned short w_PCIBoardEepromAddress);
+-void v_EepromSendCommand76(DWORD dw_Address, DWORD dw_EepromCommand,
++void v_EepromSendCommand76(unsigned int dw_Address, unsigned int dw_EepromCommand,
+ 	unsigned char b_DataLengthInBits);
+-void v_EepromCs76Read(DWORD dw_Address, unsigned short w_offset, unsigned short * pw_Value);
++void v_EepromCs76Read(unsigned int dw_Address, unsigned short w_offset, unsigned short * pw_Value);
+ 
+ /*
+ +----------------------------------------------------------------------------+
+@@ -403,7 +397,7 @@ void v_EepromWaitBusy(unsigned short w_PCIBoardEepromAddress)
+ 
+ 		/*      unsigned short read  EEPROM=0x8000 andAMCC_OP_REG_MCSR+2                  */
+ 
+-		/*      DWORD read  EEPROM=0x80000000 and AMCC_OP_REG_MCSR */
++		/*      unsigned int read  EEPROM=0x80000000 and AMCC_OP_REG_MCSR */
+ 
+ 	   /************************************************************************/
+ 
+@@ -419,9 +413,9 @@ void v_EepromWaitBusy(unsigned short w_PCIBoardEepromAddress)
+ 
+ +---------------------------------------------------------------------------------+
+ 
+-| Function   Name   : void v_EepromClock76(DWORD dw_Address,                      |
++| Function   Name   : void v_EepromClock76(unsigned int dw_Address,                      |
+ 
+-|					   DWORD dw_RegisterValue)                 			  |
++|					   unsigned int dw_RegisterValue)                 			  |
+ 
+ +---------------------------------------------------------------------------------+
+ 
+@@ -429,9 +423,9 @@ void v_EepromWaitBusy(unsigned short w_PCIBoardEepromAddress)
+ 
+ +---------------------------------------------------------------------------------+
+ 
+-| Input Parameters  : DWORD dw_Address : PCI eeprom base address                  |
++| Input Parameters  : unsigned int dw_Address : PCI eeprom base address                  |
+ 
+-|		      DWORD dw_RegisterValue : PCI eeprom register value to write.|
++|		      unsigned int dw_RegisterValue : PCI eeprom register value to write.|
+ 
+ +---------------------------------------------------------------------------------+
+ 
+@@ -445,7 +439,7 @@ void v_EepromWaitBusy(unsigned short w_PCIBoardEepromAddress)
+ 
+ */
+ 
+-void v_EepromClock76(DWORD dw_Address, DWORD dw_RegisterValue)
++void v_EepromClock76(unsigned int dw_Address, unsigned int dw_RegisterValue)
+ {
+ 
+    /************************/
+@@ -486,9 +480,9 @@ void v_EepromClock76(DWORD dw_Address, DWORD dw_RegisterValue)
+ 
+ +---------------------------------------------------------------------------------+
+ 
+-| Function   Name   : void v_EepromSendCommand76(DWORD dw_Address,                |
++| Function   Name   : void v_EepromSendCommand76(unsigned int dw_Address,                |
+ 
+-|					   DWORD   dw_EepromCommand,                		  |
++|					   unsigned int   dw_EepromCommand,                		  |
+ 
+ |					   unsigned char    b_DataLengthInBits)                        |
+ 
+@@ -498,9 +492,9 @@ void v_EepromClock76(DWORD dw_Address, DWORD dw_RegisterValue)
+ 
+ +---------------------------------------------------------------------------------+
+ 
+-| Input Parameters  : DWORD dw_Address : PCI eeprom base address                  |
++| Input Parameters  : unsigned int dw_Address : PCI eeprom base address                  |
+ 
+-|		      DWORD dw_EepromCommand : PCI eeprom command to write.       |
++|		      unsigned int dw_EepromCommand : PCI eeprom command to write.       |
+ 
+ |		      unsigned char  b_DataLengthInBits : PCI eeprom command data length.  |
+ 
+@@ -516,13 +510,13 @@ void v_EepromClock76(DWORD dw_Address, DWORD dw_RegisterValue)
+ 
+ */
+ 
+-void v_EepromSendCommand76(DWORD dw_Address, DWORD dw_EepromCommand,
++void v_EepromSendCommand76(unsigned int dw_Address, unsigned int dw_EepromCommand,
+ 	unsigned char b_DataLengthInBits)
+ {
+ 
+ 	char c_BitPos = 0;
+ 
+-	DWORD dw_RegisterValue = 0;
++	unsigned int dw_RegisterValue = 0;
+ 
+    /*****************************/
+ 
+@@ -621,7 +615,7 @@ void v_EepromSendCommand76(DWORD dw_Address, DWORD dw_EepromCommand,
+ 
+ +---------------------------------------------------------------------------------+
+ 
+-| Function   Name   : void v_EepromCs76Read(DWORD dw_Address,                     |
++| Function   Name   : void v_EepromCs76Read(unsigned int dw_Address,                     |
+ 
+ |					   unsigned short    w_offset,                      			  |
+ 
+@@ -633,7 +627,7 @@ void v_EepromSendCommand76(DWORD dw_Address, DWORD dw_EepromCommand,
+ 
+ +---------------------------------------------------------------------------------+
+ 
+-| Input Parameters  : DWORD dw_Address : PCI eeprom base address                  |
++| Input Parameters  : unsigned int dw_Address : PCI eeprom base address                  |
+ 
+ |		      unsigned short    w_offset : Offset of the adress to read             |
+ 
+@@ -651,14 +645,14 @@ void v_EepromSendCommand76(DWORD dw_Address, DWORD dw_EepromCommand,
+ 
+ */
+ 
+-void v_EepromCs76Read(DWORD dw_Address, unsigned short w_offset, unsigned short * pw_Value)
++void v_EepromCs76Read(unsigned int dw_Address, unsigned short w_offset, unsigned short * pw_Value)
+ {
+ 
+         char c_BitPos = 0;
+ 
+-	DWORD dw_RegisterValue = 0;
++	unsigned int dw_RegisterValue = 0;
+ 
+-	DWORD dw_RegisterValueRead = 0;
++	unsigned int dw_RegisterValueRead = 0;
+ 
+    /*************************************************/
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+index b97003b5db5f..c79bf473220d 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+@@ -202,7 +202,7 @@ void v_APCI1710_Interrupt(int irq, void *d);
+ int i_APCI1710_Reset(struct comedi_device * dev)
+ {
+ 	int ret;
+-	DWORD dw_Dummy;
++	unsigned int dw_Dummy;
+ 
+ 	/*********************************/
+ 	/* Read all module configuration */
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
+index a5e93d32e54e..b22739a6c9a6 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
+@@ -293,7 +293,7 @@ int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device * dev,
+ 	unsigned char b_SelectedPort = CR_RANGE(insn->chanspec);
+ 	unsigned char b_InputChannel = CR_CHAN(insn->chanspec);
+ 	unsigned char *pb_Status;
+-	DWORD dw_Status;
++	unsigned int dw_Status;
+ 
+ 	/************************/
+ 	/* Test the buffer size */
+@@ -579,7 +579,7 @@ int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device * dev,
+ 		(unsigned char) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 8);
+ 	unsigned char b_SelectedPort = CR_RANGE(insn->chanspec);
+ 	unsigned char b_OutputChannel = CR_CHAN(insn->chanspec);
+-	DWORD dw_Status = 0;
++	unsigned int dw_Status = 0;
+ 
+ 	/************************/
+ 	/* Test the buffer size */
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+index 1aa60d6c3456..f7c2cff5e932 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+@@ -95,14 +95,14 @@ str_BoardInfos s_BoardInfos[100];	// 100 will be the max number of boards to be
+ /*+----------------------------------------------------------------------------+*/
+ /*| Function   Name   : int i_AddiHeaderRW_ReadEeprom                          |*/
+ /*|                               (int    i_NbOfWordsToRead,                   |*/
+-/*|                                DWORD dw_PCIBoardEepromAddress,             |*/
++/*|                                unsigned int dw_PCIBoardEepromAddress,             |*/
+ /*|                                unsigned short   w_EepromStartAddress,                |*/
+ /*|                                unsigned short * pw_DataRead)                          |*/
+ /*+----------------------------------------------------------------------------+*/
+ /*| Task              : Read word from the 5920 eeprom.                        |*/
+ /*+----------------------------------------------------------------------------+*/
+ /*| Input Parameters  : int    i_NbOfWordsToRead : Nbr. of word to read        |*/
+-/*|                     DWORD dw_PCIBoardEepromAddress : Address of the eeprom |*/
++/*|                     unsigned int dw_PCIBoardEepromAddress : Address of the eeprom |*/
+ /*|                     unsigned short   w_EepromStartAddress : Eeprom strat address     |*/
+ /*+----------------------------------------------------------------------------+*/
+ /*| Output Parameters : unsigned short * pw_DataRead : Read data                          |*/
+@@ -111,10 +111,10 @@ str_BoardInfos s_BoardInfos[100];	// 100 will be the max number of boards to be
+ /*+----------------------------------------------------------------------------+*/
+ 
+ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+-	DWORD dw_PCIBoardEepromAddress,
++	unsigned int dw_PCIBoardEepromAddress,
+ 	unsigned short w_EepromStartAddress, unsigned short * pw_DataRead)
+ {
+-	DWORD dw_eeprom_busy = 0;
++	unsigned int dw_eeprom_busy = 0;
+ 	int i_Counter = 0;
+ 	int i_WordCounter;
+ 	int i;
+@@ -258,7 +258,7 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ /*| Return Value      : -                                                      |*/
+ /*+----------------------------------------------------------------------------+*/
+ 
+-void v_GetAPCI3200EepromCalibrationValue(DWORD dw_PCIBoardEepromAddress,
++void v_GetAPCI3200EepromCalibrationValue(unsigned int dw_PCIBoardEepromAddress,
+ 	str_BoardInfos * BoardInformations)
+ {
+ 	unsigned short w_AnalogInputMainHeaderAddress;
+@@ -3004,7 +3004,7 @@ int i_APCI3200_CommandAnalogInput(struct comedi_device * dev, struct comedi_subd
+ int i_APCI3200_Reset(struct comedi_device * dev)
+ {
+ 	int i_Temp;
+-	DWORD dw_Dummy;
++	unsigned int dw_Dummy;
+ 	//i_InterruptFlag=0;
+ 	//i_Initialised==0;
+ 	//i_Count=0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+index 54f9ea52af94..8c630d72ad41 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+@@ -89,7 +89,7 @@ int i_APCI3XXX_TestConversionStarted(struct comedi_device * dev)
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : b_SingleDiff  = (unsigned char)  data[1];                       |
+ |                     b_TimeBase    = (unsigned char)  data[2]; (0: ns, 1:micros 2:ms)|
+-|                    dw_ReloadValue = (DWORD) data[3];                       |
++|                    dw_ReloadValue = (unsigned int) data[3];                       |
+ |                     ........                                               |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+@@ -111,8 +111,8 @@ int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device * dev,
+ 	int i_ReturnValue = insn->n;
+ 	unsigned char b_TimeBase = 0;
+ 	unsigned char b_SingleDiff = 0;
+-	DWORD dw_ReloadValue = 0;
+-	DWORD dw_TestReloadValue = 0;
++	unsigned int dw_ReloadValue = 0;
++	unsigned int dw_TestReloadValue = 0;
+ 
+ 	/************************/
+ 	/* Test the buffer size */
+@@ -135,7 +135,7 @@ int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device * dev,
+ 		/* Get the convert time reload value */
+ 	   /*************************************/
+ 
+-		dw_ReloadValue = (DWORD) data[3];
++		dw_ReloadValue = (unsigned int) data[3];
+ 
+ 	   /**********************/
+ 		/* Test the time base */
+@@ -204,7 +204,7 @@ int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device * dev,
+ 								/* Set the convert timing unit */
+ 			      /*******************************/
+ 
+-								writel((DWORD)
++								writel((unsigned int)
+ 									b_TimeBase,
+ 									(void *)
+ 									(devpriv->
+@@ -283,7 +283,7 @@ int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : b_ConvertMode = (unsigned char)  data[0];                       |
+ |                     b_TimeBase    = (unsigned char)  data[1]; (0: ns, 1:micros 2:ms)|
+-|                    dw_ReloadValue = (DWORD) data[2];                       |
++|                    dw_ReloadValue = (unsigned int) data[2];                       |
+ |                     ........                                               |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+@@ -361,9 +361,9 @@ int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device * dev,
+ 	int i_ReturnValue = insn->n;
+ 	unsigned char b_Configuration = (unsigned char) CR_RANGE(insn->chanspec);
+ 	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
+-	DWORD dw_Temp = 0;
+-	DWORD dw_Configuration = 0;
+-	DWORD dw_AcquisitionCpt = 0;
++	unsigned int dw_Temp = 0;
++	unsigned int dw_Configuration = 0;
++	unsigned int dw_AcquisitionCpt = 0;
+ 	unsigned char b_Interrupt = 0;
+ 
+ 	/*************************************/
+@@ -449,8 +449,8 @@ int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device * dev,
+ 
+ 					dw_Configuration =
+ 						(b_Configuration & 3) |
+-						((DWORD) (b_Configuration >> 2)
+-						<< 6) | ((DWORD) devpriv->
++						((unsigned int) (b_Configuration >> 2)
++						<< 6) | ((unsigned int) devpriv->
+ 						b_SingelDiff << 7);
+ 
+ 		    /***************************/
+@@ -468,7 +468,7 @@ int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device * dev,
+ 					writel(dw_Temp | 0x100UL,
+ 						(void *)(devpriv->dw_AiBase +
+ 							4));
+-					writel((DWORD) b_Channel,
++					writel((unsigned int) b_Channel,
+ 						(void *)(devpriv->dw_AiBase +
+ 							0));
+ 
+@@ -608,7 +608,7 @@ void v_APCI3XXX_Interrupt(int irq, void *d)
+ {
+ 	struct comedi_device *dev = d;
+ 	unsigned char b_CopyCpt = 0;
+-	DWORD dw_Status = 0;
++	unsigned int dw_Status = 0;
+ 
+ 	/***************************/
+ 	/* Test if interrupt occur */
+@@ -689,7 +689,7 @@ int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device * dev,
+ {
+ 	unsigned char b_Range = (unsigned char) CR_RANGE(insn->chanspec);
+ 	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
+-	DWORD dw_Status = 0;
++	unsigned int dw_Status = 0;
+ 	int i_ReturnValue = insn->n;
+ 
+ 	/************************/
+@@ -924,9 +924,9 @@ int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device * dev,
+ {
+ 	int i_ReturnValue = insn->n;
+ 	unsigned char b_ChannelCpt = 0;
+-	DWORD dw_ChannelMask = 0;
+-	DWORD dw_BitMask = 0;
+-	DWORD dw_Status = 0;
++	unsigned int dw_ChannelMask = 0;
++	unsigned int dw_BitMask = 0;
++	unsigned int dw_Status = 0;
+ 
+ 	/************************/
+ 	/* Test the buffer size */
+@@ -1193,7 +1193,7 @@ int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device * dev,
+ 	int i_ReturnValue = insn->n;
+ 	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
+ 	unsigned char b_State = 0;
+-	DWORD dw_Status = 0;
++	unsigned int dw_Status = 0;
+ 
+ 	/************************/
+ 	/* Test the buffer size */
+@@ -1303,7 +1303,7 @@ int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device * dev,
+ {
+ 	int i_ReturnValue = insn->n;
+ 	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
+-	DWORD dw_Temp = 0;
++	unsigned int dw_Temp = 0;
+ 
+ 	/***************************/
+ 	/* Test the channel number */
+@@ -1360,7 +1360,7 @@ int i_APCI3XXX_InsnBitsDigitalInput(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_ReturnValue = insn->n;
+-	DWORD dw_Temp = 0;
++	unsigned int dw_Temp = 0;
+ 
+ 	/************************/
+ 	/* Test the buffer size */
+@@ -1414,9 +1414,9 @@ int i_APCI3XXX_InsnBitsDigitalOutput(struct comedi_device * dev,
+ {
+ 	int i_ReturnValue = insn->n;
+ 	unsigned char b_ChannelCpt = 0;
+-	DWORD dw_ChannelMask = 0;
+-	DWORD dw_BitMask = 0;
+-	DWORD dw_Status = 0;
++	unsigned int dw_ChannelMask = 0;
++	unsigned int dw_BitMask = 0;
++	unsigned int dw_Status = 0;
+ 
+ 	/************************/
+ 	/* Test the buffer size */
+@@ -1511,7 +1511,7 @@ int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device * dev,
+ 	int i_ReturnValue = insn->n;
+ 	unsigned char b_Channel = CR_CHAN(insn->chanspec);
+ 	unsigned char b_State = 0;
+-	DWORD dw_Status = 0;
++	unsigned int dw_Status = 0;
+ 
+ 	/************************/
+ 	/* Test the buffer size */
+@@ -1585,7 +1585,7 @@ int i_APCI3XXX_InsnReadDigitalOutput(struct comedi_device * dev,
+ {
+ 	int i_ReturnValue = insn->n;
+ 	unsigned char b_Channel = CR_CHAN(insn->chanspec);
+-	DWORD dw_Status = 0;
++	unsigned int dw_Status = 0;
+ 
+ 	/************************/
+ 	/* Test the buffer size */

commit 82a6e2e7ab47b940d5d1d7c1d13498be27f238f8
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:05:20 2009 -0400
+
+    Staging: comedi: Remove ULONG and *PULONG typedefs in addi-data
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+index 99042017f268..135228caf861 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+@@ -198,7 +198,7 @@ int i_InsnConfig_InitTimer(struct comedi_device *dev,struct comedi_subdevice *s,
+ |b_ModulNbr        = (unsigned char) CR_AREF(insn->chanspec);
+ 	b_TimerNbr		  = (unsigned char) CR_CHAN(insn->chanspec);
+ 	b_TimerMode		  = (unsigned char) data[0];
+-	ul_ReloadValue	  = (ULONG) data[1];
++	ul_ReloadValue	  = (unsigned int) data[1];
+ 	b_InputClockSelection	=(unsigned char) data[2];
+ 	b_InputClockLevel		=(unsigned char) data[3];
+ 	b_OutputLevel			=(unsigned char) data[4];
+@@ -227,7 +227,7 @@ int i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, struct comedi_sub
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_TimerNbr;
+ 	unsigned char b_TimerMode;
+-	ULONG ul_ReloadValue;
++	unsigned int ul_ReloadValue;
+ 	unsigned char b_InputClockSelection;
+ 	unsigned char b_InputClockLevel;
+ 	unsigned char b_OutputLevel;
+@@ -241,7 +241,7 @@ int i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, struct comedi_sub
+ 	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+ 	b_TimerNbr = (unsigned char) CR_CHAN(insn->chanspec);
+ 	b_TimerMode = (unsigned char) data[0];
+-	ul_ReloadValue = (ULONG) data[1];
++	ul_ReloadValue = (unsigned int) data[1];
+ 	b_InputClockSelection = (unsigned char) data[2];
+ 	b_InputClockLevel = (unsigned char) data[3];
+ 	b_OutputLevel = (unsigned char) data[4];
+@@ -595,11 +595,11 @@ int i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, struct comedi_su
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned char b_ModulNbr, b_ReadType;
+-	PULONG pul_TimerValueArray;
++	unsigned int * pul_TimerValueArray;
+ 
+ 	b_ModulNbr = CR_AREF(insn->chanspec);
+ 	b_ReadType = CR_CHAN(insn->chanspec);
+-	pul_TimerValueArray = (PULONG) data;
++	pul_TimerValueArray = (unsigned int *) data;
+ 	i_ReturnValue = insn->n;
+ 
+ 	switch (b_ReadType) {
+@@ -695,7 +695,7 @@ int i_APCI1710_InsnBitsTimer(struct comedi_device * dev, struct comedi_subdevice
+ 		i_ReturnValue = i_APCI1710_ReadTimerValue(dev,
+ 							  (unsigned char)CR_AREF(insn->chanspec),
+ 							  (unsigned char)CR_CHAN(insn->chanspec),
+-							  (PULONG) & data[0]);
++							  (unsigned int *) & data[0]);
+ 		break;
+ 
+ 	case APCI1710_TIMER_GETOUTPUTLEVEL:
+@@ -716,7 +716,7 @@ int i_APCI1710_InsnBitsTimer(struct comedi_device * dev, struct comedi_subdevice
+ 		i_ReturnValue = i_APCI1710_WriteTimerValue(dev,
+ 							   (unsigned char)CR_AREF(insn->chanspec),
+ 							   (unsigned char)CR_CHAN(insn->chanspec),
+-							   (ULONG)data[1]);
++							   (unsigned int)data[1]);
+ 
+ 		break;
+ 
+@@ -762,7 +762,7 @@ int i_APCI1710_InsnBitsTimer(struct comedi_device * dev, struct comedi_subdevice
+ 
+ int i_APCI1710_ReadTimerValue(struct comedi_device * dev,
+ 			      unsigned char b_ModulNbr, unsigned char b_TimerNbr,
+-			      PULONG pul_TimerValue)
++			      unsigned int * pul_TimerValue)
+ {
+ 	int i_ReturnValue = 0;
+ 
+@@ -1008,7 +1008,7 @@ int i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
+ 
+ int i_APCI1710_WriteTimerValue(struct comedi_device * dev,
+ 			       unsigned char b_ModulNbr, unsigned char b_TimerNbr,
+-			       ULONG ul_WriteValue)
++			       unsigned int ul_WriteValue)
+ {
+ 	int i_ReturnValue = 0;
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
+index 928da64482dc..cf6de0912a24 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
+@@ -55,7 +55,7 @@ int i_APCI1710_InsnBitsTimer(struct comedi_device *dev, struct comedi_subdevice
+  */
+ int i_APCI1710_ReadTimerValue(struct comedi_device *dev,
+ 			      unsigned char b_ModulNbr, unsigned char b_TimerNbr,
+-			      PULONG pul_TimerValue);
++			      unsigned int * pul_TimerValue);
+ 
+ int i_APCI1710_GetTimerOutputLevel(struct comedi_device *dev,
+ 				   unsigned char b_ModulNbr, unsigned char b_TimerNbr,
+@@ -70,4 +70,4 @@ int i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
+  */
+ int i_APCI1710_WriteTimerValue(struct comedi_device *dev,
+ 			       unsigned char b_ModulNbr, unsigned char b_TimerNbr,
+-			       ULONG ul_WriteValue);
++			       unsigned int ul_WriteValue);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+index ed7ff89b5431..f615e1f4c2ab 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+@@ -135,9 +135,9 @@ int i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_su
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_ReturnValue = 0;
+-	ULONG ul_TimerValue = 0;
+-	ULONG ul_TimingInterval = 0;
+-	ULONG ul_RealTimingInterval = 0;
++	unsigned int ul_TimerValue = 0;
++	unsigned int ul_TimingInterval = 0;
++	unsigned int ul_RealTimingInterval = 0;
+ 	double d_RealTimingInterval = 0;
+ 	DWORD dw_ModeArray[8] =
+ 		{ 0x01, 0x05, 0x00, 0x04, 0x02, 0x0E, 0x0A, 0x06 };
+@@ -147,7 +147,7 @@ int i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_su
+ 	b_ChronoMode = (unsigned char) data[0];
+ 	b_PCIInputClock = (unsigned char) data[1];
+ 	b_TimingUnit = (unsigned char) data[2];
+-	ul_TimingInterval = (ULONG) data[3];
++	ul_TimingInterval = (unsigned int) data[3];
+ 	i_ReturnValue = insn->n;
+ 
+ 	/**************************/
+@@ -214,7 +214,7 @@ int i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_su
+ 
+ 										ul_TimerValue
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(ul_TimingInterval
+ 											*
+ 											(0.001 * b_PCIInputClock));
+@@ -237,7 +237,7 @@ int i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_su
+ 
+ 										ul_RealTimingInterval
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(ul_TimerValue
+ 											/
+ 											(0.001 * (double)b_PCIInputClock));
+@@ -272,7 +272,7 @@ int i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_su
+ 										if (b_PCIInputClock != APCI1710_40MHZ) {
+ 											ul_TimerValue
+ 												=
+-												(ULONG)
++												(unsigned int)
+ 												(
+ 												(double)
+ 												(ul_TimerValue)
+@@ -294,7 +294,7 @@ int i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_su
+ 
+ 										ul_TimerValue
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(ul_TimingInterval
+ 											*
+ 											(1.0 * b_PCIInputClock));
+@@ -317,7 +317,7 @@ int i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_su
+ 
+ 										ul_RealTimingInterval
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(ul_TimerValue
+ 											/
+ 											(1.0 * (double)b_PCIInputClock));
+@@ -354,7 +354,7 @@ int i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_su
+ 										if (b_PCIInputClock != APCI1710_40MHZ) {
+ 											ul_TimerValue
+ 												=
+-												(ULONG)
++												(unsigned int)
+ 												(
+ 												(double)
+ 												(ul_TimerValue)
+@@ -400,7 +400,7 @@ int i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_su
+ 
+ 										ul_RealTimingInterval
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(ul_TimerValue
+ 											/
+ 											(1000.0 * (double)b_PCIInputClock));
+@@ -435,7 +435,7 @@ int i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_su
+ 										if (b_PCIInputClock != APCI1710_40MHZ) {
+ 											ul_TimerValue
+ 												=
+-												(ULONG)
++												(unsigned int)
+ 												(
+ 												(double)
+ 												(ul_TimerValue)
+@@ -457,7 +457,7 @@ int i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_su
+ 
+ 										ul_TimerValue
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(ul_TimingInterval
+ 											*
+ 											(1000000.0
+@@ -482,7 +482,7 @@ int i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_su
+ 
+ 										ul_RealTimingInterval
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(ul_TimerValue
+ 											/
+ 											(1000000.0
+@@ -520,7 +520,7 @@ int i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_su
+ 										if (b_PCIInputClock != APCI1710_40MHZ) {
+ 											ul_TimerValue
+ 												=
+-												(ULONG)
++												(unsigned int)
+ 												(
+ 												(double)
+ 												(ul_TimerValue)
+@@ -542,7 +542,7 @@ int i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_su
+ 
+ 										ul_TimerValue
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(
+ 											(ul_TimingInterval
+ 												*
+@@ -570,7 +570,7 @@ int i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_su
+ 
+ 										ul_RealTimingInterval
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(ul_TimerValue
+ 											/
+ 											(1000000.0
+@@ -608,7 +608,7 @@ int i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_su
+ 										if (b_PCIInputClock != APCI1710_40MHZ) {
+ 											ul_TimerValue
+ 												=
+-												(ULONG)
++												(unsigned int)
+ 												(
+ 												(double)
+ 												(ul_TimerValue)
+@@ -1108,14 +1108,14 @@ int i_APCI1710_InsnReadChrono(struct comedi_device * dev, struct comedi_subdevic
+ 		i_ReturnValue = i_APCI1710_ReadChronoValue(dev,
+ 			(unsigned char) CR_AREF(insn->chanspec),
+ 			(unsigned int) insn->unused[0],
+-			(unsigned char *) & data[0], (PULONG) & data[1]);
++			(unsigned char *) & data[0], (unsigned int *) & data[1]);
+ 		break;
+ 
+ 	case APCI1710_CHRONO_CONVERTVALUE:
+ 		i_ReturnValue = i_APCI1710_ConvertChronoValue(dev,
+ 			(unsigned char) CR_AREF(insn->chanspec),
+-			(ULONG) insn->unused[0],
+-			(PULONG) & data[0],
++			(unsigned int) insn->unused[0],
++			(unsigned int *) & data[0],
+ 			(unsigned char *) & data[1],
+ 			(unsigned char *) & data[2],
+ 			(unsigned int *) & data[3],
+@@ -1341,7 +1341,7 @@ int i_APCI1710_GetChronoProgressStatus(struct comedi_device * dev,
+ |                                                   timing witch the         |
+ |                                                   function                 |
+ |                                                   "i_APCI1710_InitChrono"  |
+-|                     PULONG  pul_ChronoValue  : Chronometer timing value.   |
++|                     unsigned int *  pul_ChronoValue  : Chronometer timing value.   |
+ +----------------------------------------------------------------------------+
+ | Return Value      :  0: No error                                           |
+ |                     -1: The handle parameter of the board is wrong         |
+@@ -1357,7 +1357,7 @@ int i_APCI1710_GetChronoProgressStatus(struct comedi_device * dev,
+ 
+ int i_APCI1710_ReadChronoValue(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr,
+-	unsigned int ui_TimeOut, unsigned char * pb_ChronoStatus, PULONG pul_ChronoValue)
++	unsigned int ui_TimeOut, unsigned char * pb_ChronoStatus, unsigned int * pul_ChronoValue)
+ {
+ 	int i_ReturnValue = 0;
+ 	DWORD dw_Status;
+@@ -1621,8 +1621,8 @@ int i_APCI1710_ReadChronoValue(struct comedi_device * dev,
+ 
+ int i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr,
+-	ULONG ul_ChronoValue,
+-	PULONG pul_Hour,
++	unsigned int ul_ChronoValue,
++	unsigned int * pul_Hour,
+ 	unsigned char * pb_Minute,
+ 	unsigned char * pb_Second,
+ 	unsigned int * pui_MilliSecond, unsigned int * pui_MicroSecond, unsigned int * pui_NanoSecond)
+@@ -1681,7 +1681,7 @@ int i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
+ 			    /**********************/
+ 
+ 					d_Hour = d_Hour / (double)60.0;
+-					*pul_Hour = (ULONG) d_Hour;
++					*pul_Hour = (unsigned int) d_Hour;
+ 
+ 			    /************************/
+ 					/* Calculate the minute */
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
+index 082ef2f9e84a..16c6aff8859f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
+@@ -55,12 +55,12 @@ int i_APCI1710_GetChronoProgressStatus(struct comedi_device *dev,
+ int i_APCI1710_ReadChronoValue(struct comedi_device *dev,
+ 			       unsigned char b_ModulNbr,
+ 			       unsigned int ui_TimeOut, unsigned char * pb_ChronoStatus,
+-			       PULONG pul_ChronoValue);
++			       unsigned int * pul_ChronoValue);
+ 
+ int i_APCI1710_ConvertChronoValue(struct comedi_device *dev,
+ 				  unsigned char b_ModulNbr,
+-				  ULONG ul_ChronoValue,
+-				  PULONG pul_Hour,
++				  unsigned int ul_ChronoValue,
++				  unsigned int * pul_Hour,
+ 				  unsigned char * pb_Minute,
+ 				  unsigned char * pb_Second,
+ 				  unsigned int * pui_MilliSecond, unsigned int * pui_MicroSecond,
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+index e15d9e11124c..8b65cd80a78e 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+@@ -126,7 +126,7 @@ int i_APCI1710_InsnConfigINCCPT(struct comedi_device * dev, struct comedi_subdev
+ 		i_ReturnValue = i_APCI1710_InitFrequencyMeasurement(dev,
+ 			CR_AREF(insn->chanspec),
+ 			(unsigned char) data[0],
+-			(unsigned char) data[1], (ULONG) data[2], (PULONG) & data[0]);
++			(unsigned char) data[1], (unsigned int) data[2], (unsigned int *) & data[0]);
+ 		break;
+ 
+ 	default:
+@@ -1491,10 +1491,10 @@ int i_APCI1710_InitFrequencyMeasurement(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr,
+ 	unsigned char b_PCIInputClock,
+ 	unsigned char b_TimingUnity,
+-	ULONG ul_TimingInterval, PULONG pul_RealTimingInterval)
++	unsigned int ul_TimingInterval, unsigned int * pul_RealTimingInterval)
+ {
+ 	int i_ReturnValue = 0;
+-	ULONG ul_TimerValue = 0;
++	unsigned int ul_TimerValue = 0;
+ 	double d_RealTimingInterval;
+ 	DWORD dw_Status = 0;
+ 
+@@ -1720,7 +1720,7 @@ int i_APCI1710_InitFrequencyMeasurement(struct comedi_device * dev,
+ 
+ 									ul_TimerValue
+ 										=
+-										(ULONG)
++										(unsigned int)
+ 										(ul_TimingInterval
+ 										*
+ 										(0.00025 * b_PCIInputClock));
+@@ -1743,7 +1743,7 @@ int i_APCI1710_InitFrequencyMeasurement(struct comedi_device * dev,
+ 
+ 									*pul_RealTimingInterval
+ 										=
+-										(ULONG)
++										(unsigned int)
+ 										(ul_TimerValue
+ 										/
+ 										(0.00025 * (double)b_PCIInputClock));
+@@ -1790,7 +1790,7 @@ int i_APCI1710_InitFrequencyMeasurement(struct comedi_device * dev,
+ 
+ 									ul_TimerValue
+ 										=
+-										(ULONG)
++										(unsigned int)
+ 										(ul_TimingInterval
+ 										*
+ 										(0.25 * b_PCIInputClock));
+@@ -1813,7 +1813,7 @@ int i_APCI1710_InitFrequencyMeasurement(struct comedi_device * dev,
+ 
+ 									*pul_RealTimingInterval
+ 										=
+-										(ULONG)
++										(unsigned int)
+ 										(ul_TimerValue
+ 										/
+ 										(0.25 * (double)b_PCIInputClock));
+@@ -1886,7 +1886,7 @@ int i_APCI1710_InitFrequencyMeasurement(struct comedi_device * dev,
+ 
+ 									*pul_RealTimingInterval
+ 										=
+-										(ULONG)
++										(unsigned int)
+ 										(ul_TimerValue
+ 										/
+ 										(250.0 * (double)b_PCIInputClock));
+@@ -2979,7 +2979,7 @@ int i_APCI1710_InsnWriteINCCPT(struct comedi_device * dev, struct comedi_subdevi
+ 
+ 	case APCI1710_INCCPT_WRITE32BITCOUNTERVALUE:
+ 		i_ReturnValue = i_APCI1710_Write32BitCounterValue(dev,
+-			(unsigned char) CR_AREF(insn->chanspec), (ULONG) data[0]);
++			(unsigned char) CR_AREF(insn->chanspec), (unsigned int) data[0]);
+ 
+ 		break;
+ 
+@@ -3257,7 +3257,7 @@ int i_APCI1710_Write16BitCounterValue(struct comedi_device * dev,
+ 				/* Write the value */
+ 		 /*******************/
+ 
+-				outl((ULONG) ((ULONG) (ui_WriteValue) << (16 *
++				outl((unsigned int) ((unsigned int) (ui_WriteValue) << (16 *
+ 							b_SelectedCounter)),
+ 					devpriv->s_BoardInfos.ui_Address + 8 +
+ 					(b_SelectedCounter * 4) +
+@@ -3317,7 +3317,7 @@ int i_APCI1710_Write16BitCounterValue(struct comedi_device * dev,
+ */
+ 
+ int i_APCI1710_Write32BitCounterValue(struct comedi_device * dev,
+-	unsigned char b_ModulNbr, ULONG ul_WriteValue)
++	unsigned char b_ModulNbr, unsigned int ul_WriteValue)
+ {
+ 	int i_ReturnValue = 0;
+ 
+@@ -3386,7 +3386,7 @@ int i_APCI1710_Write32BitCounterValue(struct comedi_device * dev,
+ int i_APCI1710_EnableIndex(struct comedi_device * dev, unsigned char b_ModulNbr)
+ {
+ 	int i_ReturnValue = 0;
+-	ULONG ul_InterruptLatchReg;
++	unsigned int ul_InterruptLatchReg;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -4068,7 +4068,7 @@ int i_APCI1710_InsnReadINCCPT(struct comedi_device * dev, struct comedi_subdevic
+ 	case APCI1710_INCCPT_READLATCHREGISTERVALUE:
+ 		i_ReturnValue = i_APCI1710_ReadLatchRegisterValue(dev,
+ 			(unsigned char) CR_AREF(insn->chanspec),
+-			(unsigned char) CR_RANGE(insn->chanspec), (PULONG) & data[0]);
++			(unsigned char) CR_RANGE(insn->chanspec), (unsigned int *) & data[0]);
+ 		printk("Latch Register Value %d\n", data[0]);
+ 		break;
+ 
+@@ -4080,7 +4080,7 @@ int i_APCI1710_InsnReadINCCPT(struct comedi_device * dev, struct comedi_subdevic
+ 
+ 	case APCI1710_INCCPT_READ32BITCOUNTERVALUE:
+ 		i_ReturnValue = i_APCI1710_Read32BitCounterValue(dev,
+-			(unsigned char) CR_AREF(insn->chanspec), (PULONG) & data[0]);
++			(unsigned char) CR_AREF(insn->chanspec), (unsigned int *) & data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_GETINDEXSTATUS:
+@@ -4124,7 +4124,7 @@ int i_APCI1710_InsnReadINCCPT(struct comedi_device * dev, struct comedi_subdevic
+ 		i_ReturnValue = i_APCI1710_ReadFrequencyMeasurement(dev,
+ 			(unsigned char) CR_AREF(insn->chanspec),
+ 			(unsigned char *) & data[0],
+-			(unsigned char *) & data[1], (PULONG) & data[2]);
++			(unsigned char *) & data[1], (unsigned int *) & data[2]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_READINTERRUPT:
+@@ -4281,7 +4281,7 @@ int i_APCI1710_ReadLatchRegisterStatus(struct comedi_device * dev,
+ */
+ 
+ int i_APCI1710_ReadLatchRegisterValue(struct comedi_device * dev,
+-	unsigned char b_ModulNbr, unsigned char b_LatchReg, PULONG pul_LatchValue)
++	unsigned char b_ModulNbr, unsigned char b_LatchReg, unsigned int * pul_LatchValue)
+ {
+ 	int i_ReturnValue = 0;
+ 
+@@ -4460,7 +4460,7 @@ int i_APCI1710_Read16BitCounterValue(struct comedi_device * dev,
+ */
+ 
+ int i_APCI1710_Read32BitCounterValue(struct comedi_device * dev,
+-	unsigned char b_ModulNbr, PULONG pul_CounterValue)
++	unsigned char b_ModulNbr, unsigned int * pul_CounterValue)
+ {
+ 	int i_ReturnValue = 0;
+ 
+@@ -5147,7 +5147,7 @@ int i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device * dev,
+ 
+ int i_APCI1710_ReadFrequencyMeasurement(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr,
+-	unsigned char * pb_Status, unsigned char * pb_UDStatus, PULONG pul_ReadValue)
++	unsigned char * pb_Status, unsigned char * pb_UDStatus, unsigned int * pul_ReadValue)
+ {
+ 	int i_ReturnValue = 0;
+ 	unsigned int ui_16BitValue;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
+index cb17feba63f4..51c759bdc3b0 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
+@@ -177,8 +177,8 @@ int i_APCI1710_InitFrequencyMeasurement(struct comedi_device *dev,
+ 					unsigned char b_ModulNbr,
+ 					unsigned char b_PCIInputClock,
+ 					unsigned char b_TimingUnity,
+-					ULONG ul_TimingInterval,
+-					PULONG pul_RealTimingInterval);
++					unsigned int ul_TimingInterval,
++					unsigned int * pul_RealTimingInterval);
+ 
+ /* INSN BITS */
+ int i_APCI1710_ClearCounterValue(struct comedi_device *dev, unsigned char b_ModulNbr);
+@@ -210,7 +210,7 @@ int i_APCI1710_Write16BitCounterValue(struct comedi_device *dev,
+ 				      unsigned int ui_WriteValue);
+ 
+ int i_APCI1710_Write32BitCounterValue(struct comedi_device *dev,
+-				      unsigned char b_ModulNbr, ULONG ul_WriteValue);
++				      unsigned char b_ModulNbr, unsigned int ul_WriteValue);
+ 
+ int i_APCI1710_EnableIndex(struct comedi_device *dev, unsigned char b_ModulNbr);
+ 
+@@ -234,14 +234,14 @@ int i_APCI1710_ReadLatchRegisterStatus(struct comedi_device *dev,
+ 
+ int i_APCI1710_ReadLatchRegisterValue(struct comedi_device *dev,
+ 				      unsigned char b_ModulNbr, unsigned char b_LatchReg,
+-				      PULONG pul_LatchValue);
++				      unsigned int * pul_LatchValue);
+ 
+ int i_APCI1710_Read16BitCounterValue(struct comedi_device *dev,
+ 				     unsigned char b_ModulNbr, unsigned char b_SelectedCounter,
+ 				     unsigned int * pui_CounterValue);
+ 
+ int i_APCI1710_Read32BitCounterValue(struct comedi_device *dev,
+-				     unsigned char b_ModulNbr, PULONG pul_CounterValue);
++				     unsigned char b_ModulNbr, unsigned int * pul_CounterValue);
+ 
+ int i_APCI1710_GetIndexStatus(struct comedi_device *dev,
+ 			      unsigned char b_ModulNbr, unsigned char * pb_IndexStatus);
+@@ -268,4 +268,4 @@ int i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device *dev,
+ int i_APCI1710_ReadFrequencyMeasurement(struct comedi_device *dev,
+ 					unsigned char b_ModulNbr,
+ 					unsigned char * pb_Status, unsigned char * pb_UDStatus,
+-					PULONG pul_ReadValue);
++					unsigned int * pul_ReadValue);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+index 1f9bdcd01dd3..8071d63e7b4f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+@@ -108,7 +108,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ 	b_PulseEncoderNbr		=(unsigned char) data[0];
+ 	b_InputLevelSelection	=(unsigned char) data[1];
+ 	b_TriggerOutputAction	=(unsigned char) data[2];
+-	ul_StartValue			=(ULONG) data[3];
++	ul_StartValue			=(unsigned int) data[3];
+        |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+@@ -133,13 +133,13 @@ int i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device * dev,
+ 	unsigned char b_PulseEncoderNbr;
+ 	unsigned char b_InputLevelSelection;
+ 	unsigned char b_TriggerOutputAction;
+-	ULONG ul_StartValue;
++	unsigned int ul_StartValue;
+ 
+ 	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+ 	b_PulseEncoderNbr = (unsigned char) data[0];
+ 	b_InputLevelSelection = (unsigned char) data[1];
+ 	b_TriggerOutputAction = (unsigned char) data[2];
+-	ul_StartValue = (ULONG) data[3];
++	ul_StartValue = (unsigned int) data[3];
+ 
+ 	i_ReturnValue = insn->n;
+ 
+@@ -717,15 +717,15 @@ int i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device * dev,
+ 	unsigned char b_PulseEncoderNbr;
+ 	unsigned char * pb_Status;
+ 	unsigned char b_Type;
+-	PULONG pul_ReadValue;
+-	ULONG ul_WriteValue;
++	unsigned int * pul_ReadValue;
++	unsigned int ul_WriteValue;
+ 
+ 	i_ReturnValue = insn->n;
+ 	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+ 	b_Type = (unsigned char) data[0];
+ 	b_PulseEncoderNbr = (unsigned char) data[1];
+ 	pb_Status = (unsigned char *) & data[0];
+-	pul_ReadValue = (PULONG) & data[1];
++	pul_ReadValue = (unsigned int *) & data[1];
+ 
+ 	/***********************************/
+ 	/* Test the selected module number */
+@@ -794,7 +794,7 @@ int i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device * dev,
+ 					break;
+ 
+ 				case APCI1710_PULSEENCODER_WRITE:
+-					ul_WriteValue = (ULONG) data[2];
++					ul_WriteValue = (unsigned int) data[2];
+ 			/*******************/
+ 					/* Write the value */
+ 			/*******************/
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+index 6f9a0d5aeb24..93552bd5e508 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+@@ -83,10 +83,10 @@ int i_APCI1710_InsnConfigPWM(struct comedi_device * dev, struct comedi_subdevice
+ 			(unsigned char) data[0],	//b_PWM
+ 			(unsigned char) data[1],	// b_ClockSelection
+ 			(unsigned char) data[2],	// b_TimingUnit
+-			(ULONG) data[3],	//ul_LowTiming
+-			(ULONG) data[4],	//ul_HighTiming
+-			(PULONG) & data[0],	//pul_RealLowTiming
+-			(PULONG) & data[1]	//pul_RealHighTiming
++			(unsigned int) data[3],	//ul_LowTiming
++			(unsigned int) data[4],	//ul_HighTiming
++			(unsigned int *) & data[0],	//pul_RealLowTiming
++			(unsigned int *) & data[1]	//pul_RealHighTiming
+ 			);
+ 		break;
+ 
+@@ -94,8 +94,8 @@ int i_APCI1710_InsnConfigPWM(struct comedi_device * dev, struct comedi_subdevice
+ 		i_ReturnValue = i_APCI1710_GetPWMInitialisation(dev, (unsigned char) CR_AREF(insn->chanspec),	// b_ModulNbr
+ 			(unsigned char) data[0],	//b_PWM
+ 			(unsigned char *) & data[0],	//pb_TimingUnit
+-			(PULONG) & data[1],	//pul_LowTiming
+-			(PULONG) & data[2],	//pul_HighTiming
++			(unsigned int *) & data[1],	//pul_LowTiming
++			(unsigned int *) & data[2],	//pul_HighTiming
+ 			(unsigned char *) & data[3],	// pb_StartLevel
+ 			(unsigned char *) & data[4],	// pb_StopMode
+ 			(unsigned char *) & data[5],	// pb_StopLevel
+@@ -184,13 +184,13 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 	unsigned char b_PWM,
+ 	unsigned char b_ClockSelection,
+ 	unsigned char b_TimingUnit,
+-	ULONG ul_LowTiming,
+-	ULONG ul_HighTiming,
+-	PULONG pul_RealLowTiming, PULONG pul_RealHighTiming)
++	unsigned int ul_LowTiming,
++	unsigned int ul_HighTiming,
++	unsigned int * pul_RealLowTiming, unsigned int * pul_RealHighTiming)
+ {
+ 	int i_ReturnValue = 0;
+-	ULONG ul_LowTimerValue = 0;
+-	ULONG ul_HighTimerValue = 0;
++	unsigned int ul_LowTimerValue = 0;
++	unsigned int ul_HighTimerValue = 0;
+ 	DWORD dw_Command;
+ 	double d_RealLowTiming = 0;
+ 	double d_RealHighTiming = 0;
+@@ -392,7 +392,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 
+ 										ul_LowTimerValue
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(ul_LowTiming
+ 											*
+ 											(0.00025 * b_ClockSelection));
+@@ -415,7 +415,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 
+ 										*pul_RealLowTiming
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(ul_LowTimerValue
+ 											/
+ 											(0.00025 * (double)b_ClockSelection));
+@@ -451,7 +451,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 										if (b_ClockSelection != APCI1710_40MHZ) {
+ 											ul_LowTimerValue
+ 												=
+-												(ULONG)
++												(unsigned int)
+ 												(
+ 												(double)
+ 												(ul_LowTimerValue)
+@@ -473,7 +473,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 
+ 										ul_LowTimerValue
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(ul_LowTiming
+ 											*
+ 											(0.25 * b_ClockSelection));
+@@ -496,7 +496,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 
+ 										*pul_RealLowTiming
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(ul_LowTimerValue
+ 											/
+ 											(0.25 * (double)b_ClockSelection));
+@@ -534,7 +534,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 										if (b_ClockSelection != APCI1710_40MHZ) {
+ 											ul_LowTimerValue
+ 												=
+-												(ULONG)
++												(unsigned int)
+ 												(
+ 												(double)
+ 												(ul_LowTimerValue)
+@@ -580,7 +580,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 
+ 										*pul_RealLowTiming
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(ul_LowTimerValue
+ 											/
+ 											(250.0 * (double)b_ClockSelection));
+@@ -616,7 +616,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 										if (b_ClockSelection != APCI1710_40MHZ) {
+ 											ul_LowTimerValue
+ 												=
+-												(ULONG)
++												(unsigned int)
+ 												(
+ 												(double)
+ 												(ul_LowTimerValue)
+@@ -637,7 +637,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 
+ 										ul_LowTimerValue
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(ul_LowTiming
+ 											*
+ 											(250000.0
+@@ -662,7 +662,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 
+ 										*pul_RealLowTiming
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(ul_LowTimerValue
+ 											/
+ 											(250000.0
+@@ -701,7 +701,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 										if (b_ClockSelection != APCI1710_40MHZ) {
+ 											ul_LowTimerValue
+ 												=
+-												(ULONG)
++												(unsigned int)
+ 												(
+ 												(double)
+ 												(ul_LowTimerValue)
+@@ -723,7 +723,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 
+ 										ul_LowTimerValue
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(
+ 											(ul_LowTiming
+ 												*
+@@ -751,7 +751,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 
+ 										*pul_RealLowTiming
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(ul_LowTimerValue
+ 											/
+ 											(250000.0
+@@ -795,7 +795,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 										if (b_ClockSelection != APCI1710_40MHZ) {
+ 											ul_LowTimerValue
+ 												=
+-												(ULONG)
++												(unsigned int)
+ 												(
+ 												(double)
+ 												(ul_LowTimerValue)
+@@ -823,7 +823,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 
+ 										ul_HighTimerValue
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(ul_HighTiming
+ 											*
+ 											(0.00025 * b_ClockSelection));
+@@ -846,7 +846,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 
+ 										*pul_RealHighTiming
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(ul_HighTimerValue
+ 											/
+ 											(0.00025 * (double)b_ClockSelection));
+@@ -882,7 +882,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 										if (b_ClockSelection != APCI1710_40MHZ) {
+ 											ul_HighTimerValue
+ 												=
+-												(ULONG)
++												(unsigned int)
+ 												(
+ 												(double)
+ 												(ul_HighTimerValue)
+@@ -904,7 +904,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 
+ 										ul_HighTimerValue
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(ul_HighTiming
+ 											*
+ 											(0.25 * b_ClockSelection));
+@@ -927,7 +927,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 
+ 										*pul_RealHighTiming
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(ul_HighTimerValue
+ 											/
+ 											(0.25 * (double)b_ClockSelection));
+@@ -965,7 +965,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 										if (b_ClockSelection != APCI1710_40MHZ) {
+ 											ul_HighTimerValue
+ 												=
+-												(ULONG)
++												(unsigned int)
+ 												(
+ 												(double)
+ 												(ul_HighTimerValue)
+@@ -1011,7 +1011,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 
+ 										*pul_RealHighTiming
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(ul_HighTimerValue
+ 											/
+ 											(250.0 * (double)b_ClockSelection));
+@@ -1047,7 +1047,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 										if (b_ClockSelection != APCI1710_40MHZ) {
+ 											ul_HighTimerValue
+ 												=
+-												(ULONG)
++												(unsigned int)
+ 												(
+ 												(double)
+ 												(ul_HighTimerValue)
+@@ -1069,7 +1069,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 
+ 										ul_HighTimerValue
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(ul_HighTiming
+ 											*
+ 											(250000.0
+@@ -1094,7 +1094,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 
+ 										*pul_RealHighTiming
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(ul_HighTimerValue
+ 											/
+ 											(250000.0
+@@ -1133,7 +1133,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 										if (b_ClockSelection != APCI1710_40MHZ) {
+ 											ul_HighTimerValue
+ 												=
+-												(ULONG)
++												(unsigned int)
+ 												(
+ 												(double)
+ 												(ul_HighTimerValue)
+@@ -1155,7 +1155,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 
+ 										ul_HighTimerValue
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(
+ 											(ul_HighTiming
+ 												*
+@@ -1183,7 +1183,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 
+ 										*pul_RealHighTiming
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(ul_HighTimerValue
+ 											/
+ 											(250000.0
+@@ -1227,7 +1227,7 @@ int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 										if (b_ClockSelection != APCI1710_40MHZ) {
+ 											ul_HighTimerValue
+ 												=
+-												(ULONG)
++												(unsigned int)
+ 												(
+ 												(double)
+ 												(ul_HighTimerValue)
+@@ -1538,8 +1538,8 @@ int i_APCI1710_GetPWMInitialisation(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr,
+ 	unsigned char b_PWM,
+ 	unsigned char * pb_TimingUnit,
+-	PULONG pul_LowTiming,
+-	PULONG pul_HighTiming,
++	unsigned int * pul_LowTiming,
++	unsigned int * pul_HighTiming,
+ 	unsigned char * pb_StartLevel,
+ 	unsigned char * pb_StopMode,
+ 	unsigned char * pb_StopLevel,
+@@ -1709,7 +1709,7 @@ int i_APCI1710_InsnWritePWM(struct comedi_device * dev, struct comedi_subdevice
+ 		i_ReturnValue = i_APCI1710_SetNewPWMTiming(dev,
+ 			(unsigned char) CR_AREF(insn->chanspec),
+ 			(unsigned char) data[0],
+-			(unsigned char) data[1], (ULONG) data[2], (ULONG) data[3]);
++			(unsigned char) data[1], (unsigned int) data[2], (unsigned int) data[3]);
+ 		break;
+ 
+ 	default:
+@@ -2191,14 +2191,14 @@ int i_APCI1710_DisablePWM(struct comedi_device * dev, unsigned char b_ModulNbr,
+ 
+ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr,
+-	unsigned char b_PWM, unsigned char b_TimingUnit, ULONG ul_LowTiming, ULONG ul_HighTiming)
++	unsigned char b_PWM, unsigned char b_TimingUnit, unsigned int ul_LowTiming, unsigned int ul_HighTiming)
+ {
+ 	unsigned char b_ClockSelection;
+ 	int i_ReturnValue = 0;
+-	ULONG ul_LowTimerValue = 0;
+-	ULONG ul_HighTimerValue = 0;
+-	ULONG ul_RealLowTiming = 0;
+-	ULONG ul_RealHighTiming = 0;
++	unsigned int ul_LowTimerValue = 0;
++	unsigned int ul_HighTimerValue = 0;
++	unsigned int ul_RealLowTiming = 0;
++	unsigned int ul_RealHighTiming = 0;
+ 	DWORD dw_Status;
+ 	DWORD dw_Command;
+ 	double d_RealLowTiming = 0;
+@@ -2400,7 +2400,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 									ul_LowTimerValue
+ 										=
+-										(ULONG)
++										(unsigned int)
+ 										(ul_LowTiming
+ 										*
+ 										(0.00025 * b_ClockSelection));
+@@ -2423,7 +2423,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 									ul_RealLowTiming
+ 										=
+-										(ULONG)
++										(unsigned int)
+ 										(ul_LowTimerValue
+ 										/
+ 										(0.00025 * (double)b_ClockSelection));
+@@ -2459,7 +2459,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 									if (b_ClockSelection != APCI1710_40MHZ) {
+ 										ul_LowTimerValue
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(
+ 											(double)
+ 											(ul_LowTimerValue)
+@@ -2481,7 +2481,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 									ul_LowTimerValue
+ 										=
+-										(ULONG)
++										(unsigned int)
+ 										(ul_LowTiming
+ 										*
+ 										(0.25 * b_ClockSelection));
+@@ -2504,7 +2504,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 									ul_RealLowTiming
+ 										=
+-										(ULONG)
++										(unsigned int)
+ 										(ul_LowTimerValue
+ 										/
+ 										(0.25 * (double)b_ClockSelection));
+@@ -2542,7 +2542,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 									if (b_ClockSelection != APCI1710_40MHZ) {
+ 										ul_LowTimerValue
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(
+ 											(double)
+ 											(ul_LowTimerValue)
+@@ -2588,7 +2588,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 									ul_RealLowTiming
+ 										=
+-										(ULONG)
++										(unsigned int)
+ 										(ul_LowTimerValue
+ 										/
+ 										(250.0 * (double)b_ClockSelection));
+@@ -2624,7 +2624,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 									if (b_ClockSelection != APCI1710_40MHZ) {
+ 										ul_LowTimerValue
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(
+ 											(double)
+ 											(ul_LowTimerValue)
+@@ -2646,7 +2646,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 									ul_LowTimerValue
+ 										=
+-										(ULONG)
++										(unsigned int)
+ 										(ul_LowTiming
+ 										*
+ 										(250000.0
+@@ -2671,7 +2671,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 									ul_RealLowTiming
+ 										=
+-										(ULONG)
++										(unsigned int)
+ 										(ul_LowTimerValue
+ 										/
+ 										(250000.0
+@@ -2710,7 +2710,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 									if (b_ClockSelection != APCI1710_40MHZ) {
+ 										ul_LowTimerValue
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(
+ 											(double)
+ 											(ul_LowTimerValue)
+@@ -2732,7 +2732,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 									ul_LowTimerValue
+ 										=
+-										(ULONG)
++										(unsigned int)
+ 										(
+ 										(ul_LowTiming
+ 											*
+@@ -2760,7 +2760,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 									ul_RealLowTiming
+ 										=
+-										(ULONG)
++										(unsigned int)
+ 										(ul_LowTimerValue
+ 										/
+ 										(250000.0
+@@ -2804,7 +2804,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 									if (b_ClockSelection != APCI1710_40MHZ) {
+ 										ul_LowTimerValue
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(
+ 											(double)
+ 											(ul_LowTimerValue)
+@@ -2832,7 +2832,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 									ul_HighTimerValue
+ 										=
+-										(ULONG)
++										(unsigned int)
+ 										(ul_HighTiming
+ 										*
+ 										(0.00025 * b_ClockSelection));
+@@ -2855,7 +2855,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 									ul_RealHighTiming
+ 										=
+-										(ULONG)
++										(unsigned int)
+ 										(ul_HighTimerValue
+ 										/
+ 										(0.00025 * (double)b_ClockSelection));
+@@ -2891,7 +2891,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 									if (b_ClockSelection != APCI1710_40MHZ) {
+ 										ul_HighTimerValue
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(
+ 											(double)
+ 											(ul_HighTimerValue)
+@@ -2913,7 +2913,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 									ul_HighTimerValue
+ 										=
+-										(ULONG)
++										(unsigned int)
+ 										(ul_HighTiming
+ 										*
+ 										(0.25 * b_ClockSelection));
+@@ -2936,7 +2936,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 									ul_RealHighTiming
+ 										=
+-										(ULONG)
++										(unsigned int)
+ 										(ul_HighTimerValue
+ 										/
+ 										(0.25 * (double)b_ClockSelection));
+@@ -2974,7 +2974,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 									if (b_ClockSelection != APCI1710_40MHZ) {
+ 										ul_HighTimerValue
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(
+ 											(double)
+ 											(ul_HighTimerValue)
+@@ -3020,7 +3020,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 									ul_RealHighTiming
+ 										=
+-										(ULONG)
++										(unsigned int)
+ 										(ul_HighTimerValue
+ 										/
+ 										(250.0 * (double)b_ClockSelection));
+@@ -3056,7 +3056,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 									if (b_ClockSelection != APCI1710_40MHZ) {
+ 										ul_HighTimerValue
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(
+ 											(double)
+ 											(ul_HighTimerValue)
+@@ -3078,7 +3078,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 									ul_HighTimerValue
+ 										=
+-										(ULONG)
++										(unsigned int)
+ 										(ul_HighTiming
+ 										*
+ 										(250000.0
+@@ -3103,7 +3103,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 									ul_RealHighTiming
+ 										=
+-										(ULONG)
++										(unsigned int)
+ 										(ul_HighTimerValue
+ 										/
+ 										(250000.0
+@@ -3142,7 +3142,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 									if (b_ClockSelection != APCI1710_40MHZ) {
+ 										ul_HighTimerValue
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(
+ 											(double)
+ 											(ul_HighTimerValue)
+@@ -3164,7 +3164,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 									ul_HighTimerValue
+ 										=
+-										(ULONG)
++										(unsigned int)
+ 										(
+ 										(ul_HighTiming
+ 											*
+@@ -3192,7 +3192,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 
+ 									ul_RealHighTiming
+ 										=
+-										(ULONG)
++										(unsigned int)
+ 										(ul_HighTimerValue
+ 										/
+ 										(250000.0
+@@ -3236,7 +3236,7 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 									if (b_ClockSelection != APCI1710_40MHZ) {
+ 										ul_HighTimerValue
+ 											=
+-											(ULONG)
++											(unsigned int)
+ 											(
+ 											(double)
+ 											(ul_HighTimerValue)
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
+index 7f57fd433c66..07abf9126f78 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
+@@ -34,16 +34,16 @@ int i_APCI1710_InitPWM(struct comedi_device *dev,
+ 		       unsigned char b_PWM,
+ 		       unsigned char b_ClockSelection,
+ 		       unsigned char b_TimingUnit,
+-		       ULONG ul_LowTiming,
+-		       ULONG ul_HighTiming,
+-		       PULONG pul_RealLowTiming, PULONG pul_RealHighTiming);
++		       unsigned int ul_LowTiming,
++		       unsigned int ul_HighTiming,
++		       unsigned int * pul_RealLowTiming, unsigned int * pul_RealHighTiming);
+ 
+ int i_APCI1710_GetPWMInitialisation(struct comedi_device *dev,
+ 				    unsigned char b_ModulNbr,
+ 				    unsigned char b_PWM,
+ 				    unsigned char * pb_TimingUnit,
+-				    PULONG pul_LowTiming,
+-				    PULONG pul_HighTiming,
++				    unsigned int * pul_LowTiming,
++				    unsigned int * pul_HighTiming,
+ 				    unsigned char * pb_StartLevel,
+ 				    unsigned char * pb_StopMode,
+ 				    unsigned char * pb_StopLevel,
+@@ -64,7 +64,7 @@ int i_APCI1710_EnablePWM(struct comedi_device *dev,
+ int i_APCI1710_SetNewPWMTiming(struct comedi_device *dev,
+ 			       unsigned char b_ModulNbr,
+ 			       unsigned char b_PWM, unsigned char b_TimingUnit,
+-			       ULONG ul_LowTiming, ULONG ul_HighTiming);
++			       unsigned int ul_LowTiming, unsigned int ul_HighTiming);
+ 
+ int i_APCI1710_DisablePWM(struct comedi_device *dev, unsigned char b_ModulNbr, unsigned char b_PWM);
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+index 03ff861c02f6..7e61305cec3b 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+@@ -115,7 +115,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ 	b_PositionTurnLength= (unsigned char) data[1];
+ 	b_TurnCptLength		= (unsigned char) data[2];
+ 	b_PCIInputClock		= (unsigned char) data[3];
+-	ul_SSIOutputClock	= (ULONG) data[4];
++	ul_SSIOutputClock	= (unsigned int) data[4];
+ 	b_SSICountingMode	= (unsigned char)  data[5];     |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+@@ -140,14 +140,14 @@ int i_APCI1710_InsnConfigInitSSI(struct comedi_device * dev, struct comedi_subde
+ 	unsigned int ui_TimerValue;
+ 	unsigned char b_ModulNbr, b_SSIProfile, b_PositionTurnLength, b_TurnCptLength,
+ 		b_PCIInputClock, b_SSICountingMode;
+-	ULONG ul_SSIOutputClock;
++	unsigned int ul_SSIOutputClock;
+ 
+ 	b_ModulNbr = CR_AREF(insn->chanspec);
+ 	b_SSIProfile = (unsigned char) data[0];
+ 	b_PositionTurnLength = (unsigned char) data[1];
+ 	b_TurnCptLength = (unsigned char) data[2];
+ 	b_PCIInputClock = (unsigned char) data[3];
+-	ul_SSIOutputClock = (ULONG) data[4];
++	ul_SSIOutputClock = (unsigned int) data[4];
+ 	b_SSICountingMode = (unsigned char) data[5];
+ 
+ 	i_ReturnValue = insn->n;
+@@ -252,7 +252,7 @@ int i_APCI1710_InsnConfigInitSSI(struct comedi_device * dev, struct comedi_subde
+ 											=
+ 											(unsigned int)
+ 											(
+-											((ULONG) (b_PCIInputClock) * 500000UL) / ul_SSIOutputClock);
++											((unsigned int) (b_PCIInputClock) * 500000UL) / ul_SSIOutputClock);
+ 
+ 				   /************************/
+ 										/* Initialise the timer */
+@@ -387,8 +387,8 @@ int i_APCI1710_InsnConfigInitSSI(struct comedi_device * dev, struct comedi_subde
+ | Output Parameters : PULONG_  pul_Position       : SSI position in the turn |
+ |                     PULONG_  pul_TurnCpt        : Number of turns
+ 
+-pul_Position	=	(PULONG) &data[0];
+-	pul_TurnCpt		=	(PULONG) &data[1];         |
++pul_Position	=	(unsigned int *) &data[0];
++	pul_TurnCpt		=	(unsigned int *) &data[1];         |
+ +----------------------------------------------------------------------------+
+ | Return Value      : 0: No error                                            |
+ |                    -1: The handle parameter of the board is wrong          |
+@@ -416,18 +416,18 @@ int i_APCI1710_InsnReadSSIValue(struct comedi_device * dev, struct comedi_subdev
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_SelectedSSI;
+ 	unsigned char b_ReadType;
+-	PULONG pul_Position;
+-	PULONG pul_TurnCpt;
+-	PULONG pul_Position1;
+-	PULONG pul_TurnCpt1;
++	unsigned int * pul_Position;
++	unsigned int * pul_TurnCpt;
++	unsigned int * pul_Position1;
++	unsigned int * pul_TurnCpt1;
+ 
+ 	i_ReturnValue = insn->n;
+-	pul_Position1 = (PULONG) & data[0];
++	pul_Position1 = (unsigned int *) & data[0];
+ // For Read1
+-	pul_TurnCpt1 = (PULONG) & data[1];
++	pul_TurnCpt1 = (unsigned int *) & data[1];
+ // For Read all
+-	pul_Position = (PULONG) & data[0];	//0-2
+-	pul_TurnCpt = (PULONG) & data[3];	//3-5
++	pul_Position = (unsigned int *) & data[0];	//0-2
++	pul_TurnCpt = (unsigned int *) & data[3];	//3-5
+ 	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+ 	b_SelectedSSI = (unsigned char) CR_CHAN(insn->chanspec);
+ 	b_ReadType = (unsigned char) CR_RANGE(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+index 030ca773f016..a0aa24fbfbb4 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+@@ -134,15 +134,15 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_ReturnValue = 0;
+-	ULONG ul_TimerValue = 0;
++	unsigned int ul_TimerValue = 0;
+ 	DWORD dw_Command;
+ 	double d_RealTimingInterval = 0;
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_TorCounter;
+ 	unsigned char b_PCIInputClock;
+ 	unsigned char b_TimingUnit;
+-	ULONG ul_TimingInterval;
+-	ULONG ul_RealTimingInterval = 0;
++	unsigned int ul_TimingInterval;
++	unsigned int ul_RealTimingInterval = 0;
+ 
+ 	i_ReturnValue = insn->n;
+ 	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+@@ -150,7 +150,7 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ 	b_TorCounter = (unsigned char) data[0];
+ 	b_PCIInputClock = (unsigned char) data[1];
+ 	b_TimingUnit = (unsigned char) data[2];
+-	ul_TimingInterval = (ULONG) data[3];
++	ul_TimingInterval = (unsigned int) data[3];
+ 	printk("INPUT clock %d\n", b_PCIInputClock);
+ 
+ 		/**************************/
+@@ -225,7 +225,7 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ 
+ 											ul_TimerValue
+ 												=
+-												(ULONG)
++												(unsigned int)
+ 												(ul_TimingInterval
+ 												*
+ 												(0.00025 * b_PCIInputClock));
+@@ -248,7 +248,7 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ 
+ 											ul_RealTimingInterval
+ 												=
+-												(ULONG)
++												(unsigned int)
+ 												(ul_TimerValue
+ 												/
+ 												(0.00025 * (double)b_PCIInputClock));
+@@ -284,7 +284,7 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ 											if (b_PCIInputClock != APCI1710_40MHZ) {
+ 												ul_TimerValue
+ 													=
+-													(ULONG)
++													(unsigned int)
+ 													(
+ 													(double)
+ 													(ul_TimerValue)
+@@ -306,7 +306,7 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ 
+ 											ul_TimerValue
+ 												=
+-												(ULONG)
++												(unsigned int)
+ 												(ul_TimingInterval
+ 												*
+ 												(0.25 * b_PCIInputClock));
+@@ -329,7 +329,7 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ 
+ 											ul_RealTimingInterval
+ 												=
+-												(ULONG)
++												(unsigned int)
+ 												(ul_TimerValue
+ 												/
+ 												(0.25 * (double)b_PCIInputClock));
+@@ -367,7 +367,7 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ 											if (b_PCIInputClock != APCI1710_40MHZ) {
+ 												ul_TimerValue
+ 													=
+-													(ULONG)
++													(unsigned int)
+ 													(
+ 													(double)
+ 													(ul_TimerValue)
+@@ -413,7 +413,7 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ 
+ 											ul_RealTimingInterval
+ 												=
+-												(ULONG)
++												(unsigned int)
+ 												(ul_TimerValue
+ 												/
+ 												(250.0 * (double)b_PCIInputClock));
+@@ -449,7 +449,7 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ 											if (b_PCIInputClock != APCI1710_40MHZ) {
+ 												ul_TimerValue
+ 													=
+-													(ULONG)
++													(unsigned int)
+ 													(
+ 													(double)
+ 													(ul_TimerValue)
+@@ -471,7 +471,7 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ 
+ 											ul_TimerValue
+ 												=
+-												(ULONG)
++												(unsigned int)
+ 												(ul_TimingInterval
+ 												*
+ 												(250000.0
+@@ -496,7 +496,7 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ 
+ 											ul_RealTimingInterval
+ 												=
+-												(ULONG)
++												(unsigned int)
+ 												(ul_TimerValue
+ 												/
+ 												(250000.0
+@@ -535,7 +535,7 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ 											if (b_PCIInputClock != APCI1710_40MHZ) {
+ 												ul_TimerValue
+ 													=
+-													(ULONG)
++													(unsigned int)
+ 													(
+ 													(double)
+ 													(ul_TimerValue)
+@@ -557,7 +557,7 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ 
+ 											ul_TimerValue
+ 												=
+-												(ULONG)
++												(unsigned int)
+ 												(
+ 												(ul_TimingInterval
+ 													*
+@@ -585,7 +585,7 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ 
+ 											ul_RealTimingInterval
+ 												=
+-												(ULONG)
++												(unsigned int)
+ 												(ul_TimerValue
+ 												/
+ 												(250000.0
+@@ -629,7 +629,7 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ 											if (b_PCIInputClock != APCI1710_40MHZ) {
+ 												ul_TimerValue
+ 													=
+-													(ULONG)
++													(unsigned int)
+ 													(
+ 													(double)
+ 													(ul_TimerValue)
+@@ -1442,7 +1442,7 @@ int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+ |                                                 Disable the tor counter    |
+ |                                                 interrupt
+ 	pb_TimingUnit		=	(unsigned char *) &data[0];
+-	pul_TimingInterval	=  (PULONG) &data[1];
++	pul_TimingInterval	=  (unsigned int *) &data[1];
+ 	pb_InputMode		=	(unsigned char *) &data[2];
+ 	pb_ExternGate		=	(unsigned char *) &data[3];
+ 	pb_CycleMode		=	(unsigned char *) &data[4];
+@@ -1468,7 +1468,7 @@ int i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_TorCounter;
+ 	unsigned char * pb_TimingUnit;
+-	PULONG pul_TimingInterval;
++	unsigned int * pul_TimingInterval;
+ 	unsigned char * pb_InputMode;
+ 	unsigned char * pb_ExternGate;
+ 	unsigned char * pb_CycleMode;
+@@ -1480,7 +1480,7 @@ int i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
+ 	b_TorCounter = CR_CHAN(insn->chanspec);
+ 
+ 	pb_TimingUnit = (unsigned char *) & data[0];
+-	pul_TimingInterval = (PULONG) & data[1];
++	pul_TimingInterval = (unsigned int *) & data[1];
+ 	pb_InputMode = (unsigned char *) & data[2];
+ 	pb_ExternGate = (unsigned char *) & data[3];
+ 	pb_CycleMode = (unsigned char *) & data[4];
+@@ -1683,9 +1683,9 @@ int i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
+ |                                                   function                 |
+ |                                                 "i_APCI1710_InitTorCounter"|
+ |						4 : Timeeout occur           |
+-|                     PULONG  pul_TorCounterValue  : Tor counter value.
++|                     unsigned int *  pul_TorCounterValue  : Tor counter value.
+ 	pb_TorCounterStatus=(unsigned char *) &data[0];
+-	pul_TorCounterValue=(PULONG) &data[1];    |
++	pul_TorCounterValue=(unsigned int *) &data[1];    |
+ +----------------------------------------------------------------------------+
+ | Return Value      :  0: No error                                           |
+ |                     -1: The handle parameter of the board is wrong         |
+@@ -1712,7 +1712,7 @@ int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device
+ 	unsigned char b_ReadType;
+ 	unsigned int ui_TimeOut;
+ 	unsigned char * pb_TorCounterStatus;
+-	PULONG pul_TorCounterValue;
++	unsigned int * pul_TorCounterValue;
+ 
+ 	i_ReturnValue = insn->n;
+ 	b_ModulNbr = CR_AREF(insn->chanspec);
+@@ -1720,7 +1720,7 @@ int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device
+ 	b_TorCounter = (unsigned char) data[1];
+ 	ui_TimeOut = (unsigned int) data[2];
+ 	pb_TorCounterStatus = (unsigned char *) & data[0];
+-	pul_TorCounterValue = (PULONG) & data[1];
++	pul_TorCounterValue = (unsigned int *) & data[1];
+ 
+ 	/**************************/
+ 	/* Test the module number */
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+index 4af2cfdd2de1..b8a0ee37319e 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+@@ -661,11 +661,11 @@ int i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+ 	int i_ReturnValue = 0;
+ 	DWORD dw_StatusReg;
+ 	unsigned char b_ModulNbr;
+-	PULONG pul_PortValue;
++	unsigned int * pul_PortValue;
+ 
+ 	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+ 	i_ReturnValue = insn->n;
+-	pul_PortValue = (PULONG) & data[0];
++	pul_PortValue = (unsigned int *) & data[0];
+ 
+ 	/**************************/
+ 	/* Test the module number */
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+index a3c62bc1f8b5..6b9f08cfe11d 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+@@ -37,7 +37,6 @@
+ #define SUCCESS	1
+ 
+ /* variable type definition */
+-typedef unsigned int ULONG, *PULONG;	/* 32-bit */
+ typedef unsigned int DWORD, *PDWORD;	/* 32-bit */
+ typedef unsigned long ULONG_PTR;
+ 
+@@ -308,7 +307,7 @@ typedef union {
+ 			unsigned char b_TimingUnit;
+ 			unsigned char b_InterruptEnable;
+ 			double d_TimingInterval;
+-			ULONG ul_RealTimingInterval;
++			unsigned int ul_RealTimingInterval;
+ 		} s_TorCounterInfo[2];
+ 		unsigned char b_PCIInputClock;
+ 	} s_TorCounterModuleInfo;
+@@ -321,8 +320,8 @@ typedef union {
+ 			unsigned char b_InterruptEnable;
+ 			double d_LowTiming;
+ 			double d_HighTiming;
+-			ULONG ul_RealLowTiming;
+-			ULONG ul_RealHighTiming;
++			unsigned int ul_RealLowTiming;
++			unsigned int ul_RealHighTiming;
+ 		} s_PWMInfo[2];
+ 		unsigned char b_ClockSelection;
+ 	} s_PWMModuleInfo;
+@@ -337,7 +336,7 @@ typedef union {
+ 		unsigned char b_TimingUnit;
+ 		unsigned char b_ClockSelection;
+ 		double d_TimingInterval;
+-		ULONG ul_Timing;
++		unsigned int ul_Timing;
+ 	} s_ETMModuleInfo;
+ 
+ 	/* CDA infos */
+@@ -383,10 +382,10 @@ typedef struct {
+ 	unsigned short us_UseDma;	// To use Dma or not
+ 	unsigned char b_DmaDoubleBuffer;	// we can use double buffering
+ 	unsigned int ui_DmaActualBuffer;	// which buffer is used now
+-	//*UPDATE-0.7.57->0.7.68
+-	//ULONG               ul_DmaBufferVirtual[2];// pointers to begin of DMA buffer
++	/* UPDATE-0.7.57->0.7.68 */
++	/* unsigned int               ul_DmaBufferVirtual[2]; pointers to begin of DMA buffer */
+ 	short *ul_DmaBufferVirtual[2];	// pointers to begin of DMA buffer
+-	ULONG ul_DmaBufferHw[2];	// hw address of DMA buff
++	unsigned int ul_DmaBufferHw[2];	// hw address of DMA buff
+ 	unsigned int ui_DmaBufferSize[2];	// size of dma buffer in bytes
+ 	unsigned int ui_DmaBufferUsesize[2];	// which size we may now used for transfer
+ 	unsigned int ui_DmaBufferSamples[2];	// size in samples
+@@ -427,19 +426,19 @@ typedef struct {
+ 
+ 	/* Interrupt infos */
+ 	struct {
+-		ULONG ul_InterruptOccur;	/* 0   : No interrupt occur */
++		unsigned int ul_InterruptOccur;	/* 0   : No interrupt occur */
+ 						/* > 0 : Interrupt occur */
+ 		unsigned int ui_Read;	/* Read FIFO */
+ 		unsigned int ui_Write;	/* Write FIFO */
+ 		struct {
+ 			unsigned char b_OldModuleMask;
+-			ULONG ul_OldInterruptMask;	/* Interrupt mask */
+-			ULONG ul_OldCounterLatchValue;	/* Interrupt counter value */
++			unsigned int ul_OldInterruptMask;	/* Interrupt mask */
++			unsigned int ul_OldCounterLatchValue;	/* Interrupt counter value */
+ 		} s_FIFOInterruptParameters[APCI1710_SAVE_INTERRUPT];
+ 	} s_InterruptParameters;
+ 
+ 	str_ModuleInfo s_ModuleInfo[4];
+-	ULONG ul_TTLPortConfiguration[10];
++	unsigned int ul_TTLPortConfiguration[10];
+ 
+ } addi_private;
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+index 1db7f32ab801..b97003b5db5f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+@@ -256,10 +256,10 @@ void v_APCI1710_Interrupt(int irq, void *d)
+ 	unsigned char b_TorCounterCpt = 0;
+ 	unsigned char b_PulseIncoderCpt = 0;
+ 	unsigned int ui_16BitValue;
+-	ULONG ul_InterruptLatchReg = 0;
+-	ULONG ul_LatchRegisterValue = 0;
+-	ULONG ul_82X54InterruptStatus;
+-	ULONG ul_StatusRegister;
++	unsigned int ul_InterruptLatchReg = 0;
++	unsigned int ul_LatchRegisterValue = 0;
++	unsigned int ul_82X54InterruptStatus;
++	unsigned int ul_StatusRegister;
+ 
+ 	str_ModuleInfo *ps_ModuleInfo;
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+index 8711aaf07a50..3c4086521412 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+@@ -89,8 +89,8 @@ int i_APCI1032_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subd
+ {
+ 	unsigned int ui_TmpValue;
+ 
+-	ULONG ul_Command1 = 0;
+-	ULONG ul_Command2 = 0;
++	unsigned int ul_Command1 = 0;
++	unsigned int ul_Command2 = 0;
+ 	devpriv->tsk_Current = current;
+ 
+   /*******************************/
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+index 183976c98158..13c5c6faf127 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+@@ -258,7 +258,7 @@ int i_APCI1564_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ int i_APCI1564_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	ULONG ul_Command = 0;
++	unsigned int ul_Command = 0;
+ 
+ 	if ((data[0] != 0) && (data[0] != 1)) {
+ 		comedi_error(dev,
+@@ -567,7 +567,7 @@ int i_APCI1564_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	ULONG ul_Command1 = 0;
++	unsigned int ul_Command1 = 0;
+ 	devpriv->tsk_Current = current;
+ 	if (data[0] == ADDIDATA_WATCHDOG) {
+ 		devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG;
+@@ -666,7 +666,7 @@ int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+       /******************************/
+ 		ul_Command1 =
+ 			(ul_Command1 & 0xFFFC19E2UL) | 0x80000UL |
+-			(ULONG) ((ULONG) data[4] << 16UL);
++			(unsigned int) ((unsigned int) data[4] << 16UL);
+ 		outl(ul_Command1,
+ 			devpriv->iobase + ((data[5] - 1) * 0x20) +
+ 			APCI1564_TCW_PROG);
+@@ -721,7 +721,7 @@ int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	ULONG ul_Command1 = 0;
++	unsigned int ul_Command1 = 0;
+ 	if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+ 		switch (data[1]) {
+ 		case 0:	//stop the watchdog
+@@ -816,7 +816,7 @@ int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	ULONG ul_Command1 = 0;
++	unsigned int ul_Command1 = 0;
+ 
+ 	if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+ 		// Stores the status of the Watchdog
+@@ -922,7 +922,7 @@ static void v_APCI1564_Interrupt(int irq, void *d)
+ 	unsigned int ui_DO, ui_DI;
+ 	unsigned int ui_Timer;
+ 	unsigned int ui_C1, ui_C2, ui_C3, ui_C4;
+-	ULONG ul_Command2 = 0;
++	unsigned int ul_Command2 = 0;
+ 	ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+ 		APCI1564_DIGITAL_IP_IRQ) & 0x01;
+ 	ui_DO = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
+index 888aee4d1d47..84d84a1ce3e0 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
+@@ -82,7 +82,7 @@ unsigned int ui_InterruptData, ui_Type;
+ int i_APCI2032_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	ULONG ul_Command = 0;
++	unsigned int ul_Command = 0;
+ 	devpriv->tsk_Current = current;
+ 
+ 	if ((data[0] != 0) && (data[0] != 1)) {
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+index 3fc7b0b1e566..9118ef46b495 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+@@ -94,9 +94,9 @@ static const struct comedi_lrange range_apci3300_ai = { 4, {
+ //END JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+ 
+ typedef struct {
+-	ULONG ul_NumberOfValue;
+-	ULONG *pul_ResistanceValue;
+-	ULONG *pul_TemperatureValue;
++	unsigned int ul_NumberOfValue;
++	unsigned int *pul_ResistanceValue;
++	unsigned int *pul_TemperatureValue;
+ } str_ADDIDATA_RTDStruct, *pstr_ADDIDATA_RTDStruct;
+ 
+ //BEGIN JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
+index 4a78cecd2ebf..da2221d51d61 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
+@@ -339,7 +339,7 @@ int i_APCI3501_ConfigAnalogOutput(struct comedi_device * dev, struct comedi_subd
+ int i_APCI3501_WriteAnalogOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	ULONG ul_Command1 = 0, ul_Channel_no, ul_Polarity, ul_DAC_Ready = 0;;
++	unsigned int ul_Command1 = 0, ul_Channel_no, ul_Polarity, ul_DAC_Ready = 0;;
+ 
+ 	ul_Channel_no = CR_CHAN(insn->chanspec);
+ 
+@@ -372,9 +372,9 @@ int i_APCI3501_WriteAnalogOutput(struct comedi_device * dev, struct comedi_subde
+ 	if (ul_DAC_Ready) {
+ // Output the Value on the output channels.
+ 		ul_Command1 =
+-			(ULONG) ((ULONG) (ul_Channel_no & 0xFF) |
+-			(ULONG) ((*data << 0x8) & 0x7FFFFF00L) |
+-			(ULONG) (ul_Polarity));
++			(unsigned int) ((unsigned int) (ul_Channel_no & 0xFF) |
++			(unsigned int) ((*data << 0x8) & 0x7FFFFF00L) |
++			(unsigned int) (ul_Polarity));
+ 		outl(ul_Command1,
+ 			devpriv->iobase + APCI3501_ANALOG_OUTPUT +
+ 			APCI3501_AO_PROG);
+@@ -413,7 +413,7 @@ int i_APCI3501_WriteAnalogOutput(struct comedi_device * dev, struct comedi_subde
+ int i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	ULONG ul_Command1 = 0;
++	unsigned int ul_Command1 = 0;
+ 	devpriv->tsk_Current = current;
+ 	if (data[0] == ADDIDATA_WATCHDOG) {
+ 
+@@ -514,7 +514,7 @@ int i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	ULONG ul_Command1 = 0;
++	unsigned int ul_Command1 = 0;
+ 	int i_Temp;
+ 	if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+ 
+@@ -657,7 +657,7 @@ int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device * dev,
+ int i_APCI3501_Reset(struct comedi_device * dev)
+ {
+ 	int i_Count = 0, i_temp = 0;
+-	ULONG ul_Command1 = 0, ul_Polarity, ul_DAC_Ready = 0;
++	unsigned int ul_Command1 = 0, ul_Polarity, ul_DAC_Ready = 0;
+ 	outl(0x0, devpriv->iobase + APCI3501_DIGITAL_OP);
+ 	outl(1, devpriv->iobase + APCI3501_ANALOG_OUTPUT +
+ 		APCI3501_AO_VOLT_MODE);
+@@ -676,9 +676,9 @@ int i_APCI3501_Reset(struct comedi_device * dev)
+ 		if (ul_DAC_Ready) {
+ 			// Output the Value on the output channels.
+ 			ul_Command1 =
+-				(ULONG) ((ULONG) (i_Count & 0xFF) |
+-				(ULONG) ((i_temp << 0x8) & 0x7FFFFF00L) |
+-				(ULONG) (ul_Polarity));
++				(unsigned int) ((unsigned int) (i_Count & 0xFF) |
++				(unsigned int) ((i_temp << 0x8) & 0x7FFFFF00L) |
++				(unsigned int) (ul_Polarity));
+ 			outl(ul_Command1,
+ 				devpriv->iobase + APCI3501_ANALOG_OUTPUT +
+ 				APCI3501_AO_PROG);

commit 2b6257c53425df60de153f1906183f4c9391a45b
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:05:14 2009 -0400
+
+    Staging: comedi: Remove LONG and *PLONG typedefs in addi-data
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+index bf04602d8381..a3c62bc1f8b5 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+@@ -37,7 +37,6 @@
+ #define SUCCESS	1
+ 
+ /* variable type definition */
+-typedef int LONG, *PLONG;		/* 32-bit */
+ typedef unsigned int ULONG, *PULONG;	/* 32-bit */
+ typedef unsigned int DWORD, *PDWORD;	/* 32-bit */
+ typedef unsigned long ULONG_PTR;

commit 117102b0f6e0a9ab3ea4fa9fd89b7eb4a8888fb9
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:05:09 2009 -0400
+
+    Staging: comedi: Remove UINT and *PUINT typedefs in addi-data
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+index 70b01db2d3bb..ed7ff89b5431 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+@@ -1107,7 +1107,7 @@ int i_APCI1710_InsnReadChrono(struct comedi_device * dev, struct comedi_subdevic
+ 	case APCI1710_CHRONO_READVALUE:
+ 		i_ReturnValue = i_APCI1710_ReadChronoValue(dev,
+ 			(unsigned char) CR_AREF(insn->chanspec),
+-			(UINT) insn->unused[0],
++			(unsigned int) insn->unused[0],
+ 			(unsigned char *) & data[0], (PULONG) & data[1]);
+ 		break;
+ 
+@@ -1118,8 +1118,8 @@ int i_APCI1710_InsnReadChrono(struct comedi_device * dev, struct comedi_subdevic
+ 			(PULONG) & data[0],
+ 			(unsigned char *) & data[1],
+ 			(unsigned char *) & data[2],
+-			(PUINT) & data[3],
+-			(PUINT) & data[4], (PUINT) & data[5]);
++			(unsigned int *) & data[3],
++			(unsigned int *) & data[4], (unsigned int *) & data[5]);
+ 		break;
+ 
+ 	case APCI1710_CHRONO_READINTERRUPT:
+@@ -1297,7 +1297,7 @@ int i_APCI1710_GetChronoProgressStatus(struct comedi_device * dev,
+ | Function Name     : _INT_ i_APCI1710_ReadChronoValue                       |
+ |                               (unsigned char_     b_BoardHandle,                    |
+ |                                unsigned char_     b_ModulNbr,                       |
+-|                                UINT_    ui_TimeOut,                        |
++|                                unsigned int_    ui_TimeOut,                        |
+ |                                unsigned char *_   pb_ChronoStatus,                   |
+ |                                PULONG_ pul_ChronoValue)                    |
+ +----------------------------------------------------------------------------+
+@@ -1357,7 +1357,7 @@ int i_APCI1710_GetChronoProgressStatus(struct comedi_device * dev,
+ 
+ int i_APCI1710_ReadChronoValue(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr,
+-	UINT ui_TimeOut, unsigned char * pb_ChronoStatus, PULONG pul_ChronoValue)
++	unsigned int ui_TimeOut, unsigned char * pb_ChronoStatus, PULONG pul_ChronoValue)
+ {
+ 	int i_ReturnValue = 0;
+ 	DWORD dw_Status;
+@@ -1587,9 +1587,9 @@ int i_APCI1710_ReadChronoValue(struct comedi_device * dev,
+ |                                PULONG_ pul_Hour,                           |
+ |                                unsigned char *_   pb_Minute,                         |
+ |                                unsigned char *_   pb_Second,                         |
+-|                                PUINT_  pui_MilliSecond,                    |
+-|                                PUINT_  pui_MicroSecond,                    |
+-|                                PUINT_  pui_NanoSecond)                     |
++|                                unsigned int *_  pui_MilliSecond,                    |
++|                                unsigned int *_  pui_MicroSecond,                    |
++|                                unsigned int *_  pui_NanoSecond)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Convert the chronometer measured timing                |
+ |                     (ul_ChronoValue) in to h, mn, s, ms, µs, ns.           |
+@@ -1603,11 +1603,11 @@ int i_APCI1710_ReadChronoValue(struct comedi_device * dev,
+ | Output Parameters : PULONG_   pul_Hour        : Chronometer timing hour    |
+ |                     unsigned char *_     pb_Minute      : Chronometer timing minute  |
+ |                     unsigned char *_     pb_Second      : Chronometer timing second  |
+-|                     PUINT_    pui_MilliSecond  : Chronometer timing mini   |
++|                     unsigned int *_    pui_MilliSecond  : Chronometer timing mini   |
+ |                                                 second                     |
+-|                     PUINT_    pui_MicroSecond : Chronometer timing micro   |
++|                     unsigned int *_    pui_MicroSecond : Chronometer timing micro   |
+ |                                                 second                     |
+-|                     PUINT_    pui_NanoSecond  : Chronometer timing nano    |
++|                     unsigned int *_    pui_NanoSecond  : Chronometer timing nano    |
+ |                                                 second                     |
+ +----------------------------------------------------------------------------+
+ | Return Value      :  0: No error                                           |
+@@ -1625,7 +1625,7 @@ int i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
+ 	PULONG pul_Hour,
+ 	unsigned char * pb_Minute,
+ 	unsigned char * pb_Second,
+-	PUINT pui_MilliSecond, PUINT pui_MicroSecond, PUINT pui_NanoSecond)
++	unsigned int * pui_MilliSecond, unsigned int * pui_MicroSecond, unsigned int * pui_NanoSecond)
+ {
+ 	int i_ReturnValue = 0;
+ 	double d_Hour;
+@@ -1705,7 +1705,7 @@ int i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
+ 
+ 					d_MilliSecond = d_Second - *pb_Second;
+ 					d_MilliSecond = d_MilliSecond * 1000;
+-					*pui_MilliSecond = (UINT) d_MilliSecond;
++					*pui_MilliSecond = (unsigned int) d_MilliSecond;
+ 
+ 			    /******************************/
+ 					/* Calculate the micro second */
+@@ -1715,7 +1715,7 @@ int i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
+ 						d_MilliSecond -
+ 						*pui_MilliSecond;
+ 					d_MicroSecond = d_MicroSecond * 1000;
+-					*pui_MicroSecond = (UINT) d_MicroSecond;
++					*pui_MicroSecond = (unsigned int) d_MicroSecond;
+ 
+ 			    /******************************/
+ 					/* Calculate the micro second */
+@@ -1725,7 +1725,7 @@ int i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
+ 						d_MicroSecond -
+ 						*pui_MicroSecond;
+ 					d_NanoSecond = d_NanoSecond * 1000;
+-					*pui_NanoSecond = (UINT) d_NanoSecond;
++					*pui_NanoSecond = (unsigned int) d_NanoSecond;
+ 					break;
+ 				}
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
+index 1c0bfe1c4004..082ef2f9e84a 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
+@@ -54,7 +54,7 @@ int i_APCI1710_GetChronoProgressStatus(struct comedi_device *dev,
+ 
+ int i_APCI1710_ReadChronoValue(struct comedi_device *dev,
+ 			       unsigned char b_ModulNbr,
+-			       UINT ui_TimeOut, unsigned char * pb_ChronoStatus,
++			       unsigned int ui_TimeOut, unsigned char * pb_ChronoStatus,
+ 			       PULONG pul_ChronoValue);
+ 
+ int i_APCI1710_ConvertChronoValue(struct comedi_device *dev,
+@@ -63,8 +63,8 @@ int i_APCI1710_ConvertChronoValue(struct comedi_device *dev,
+ 				  PULONG pul_Hour,
+ 				  unsigned char * pb_Minute,
+ 				  unsigned char * pb_Second,
+-				  PUINT pui_MilliSecond, PUINT pui_MicroSecond,
+-				  PUINT pui_NanoSecond);
++				  unsigned int * pui_MilliSecond, unsigned int * pui_MicroSecond,
++				  unsigned int * pui_NanoSecond);
+ 
+ /*
+  * CHRONOMETER DIGITAL INPUT OUTPUT FUNCTION
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+index f5abd1cecd95..e15d9e11124c 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+@@ -78,7 +78,7 @@ struct comedi_insn *insn,unsigned int *data)
+ int i_APCI1710_InsnConfigINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_ConfigType;
++	unsigned int ui_ConfigType;
+ 	int i_ReturnValue = 0;
+ 	ui_ConfigType = CR_CHAN(insn->chanspec);
+ 
+@@ -119,7 +119,7 @@ int i_APCI1710_InsnConfigINCCPT(struct comedi_device * dev, struct comedi_subdev
+ 
+ 	case APCI1710_INCCPT_INITCOMPARELOGIC:
+ 		i_ReturnValue = i_APCI1710_InitCompareLogic(dev,
+-			CR_AREF(insn->chanspec), (UINT) data[0]);
++			CR_AREF(insn->chanspec), (unsigned int) data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_INITFREQUENCYMEASUREMENT:
+@@ -1370,7 +1370,7 @@ int i_APCI1710_InitExternalStrobe(struct comedi_device * dev,
+ 	   | Function Name     : _INT_ i_APCI1710_InitCompareLogic                      |
+ 	   |                               (unsigned char_   b_BoardHandle,                      |
+ 	   |                                unsigned char_   b_ModulNbr,                         |
+-	   |                                UINT_  ui_CompareValue)                     |
++	   |                                unsigned int_  ui_CompareValue)                     |
+ 	   +----------------------------------------------------------------------------+
+ 	   | Task              : Set the 32-Bit compare value. At that moment that the  |
+ 	   |                     incremental counter arrive to the compare value        |
+@@ -1379,7 +1379,7 @@ int i_APCI1710_InitExternalStrobe(struct comedi_device * dev,
+ 	   | Input Parameters  : unsigned char_  b_BoardHandle    : Handle of board APCI-1710    |
+ 	   |                     unsigned char_  b_ModulNbr       : Module number to configure   |
+ 	   |                                               (0 to 3)                     |
+-	   |                     UINT_ ui_CompareValue   : 32-Bit compare value         |
++	   |                     unsigned int_ ui_CompareValue   : 32-Bit compare value         |
+ 	   +----------------------------------------------------------------------------+
+ 	   | Output Parameters : -
+ 	   +----------------------------------------------------------------------------+
+@@ -1392,7 +1392,7 @@ int i_APCI1710_InitExternalStrobe(struct comedi_device * dev,
+ 	 */
+ 
+ int i_APCI1710_InitCompareLogic(struct comedi_device * dev,
+-	unsigned char b_ModulNbr, UINT ui_CompareValue)
++	unsigned char b_ModulNbr, unsigned int ui_CompareValue)
+ {
+ 	int i_ReturnValue = 0;
+ 
+@@ -2018,7 +2018,7 @@ struct comedi_insn *insn,unsigned int *data)                   |
+ int i_APCI1710_InsnBitsINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_BitsType;
++	unsigned int ui_BitsType;
+ 	int i_ReturnValue = 0;
+ 	ui_BitsType = CR_CHAN(insn->chanspec);
+ 	devpriv->tsk_Current = current;	// Save the current process task structure
+@@ -2954,7 +2954,7 @@ struct comedi_insn *insn,unsigned int *data)                   |
+ int i_APCI1710_InsnWriteINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_WriteType;
++	unsigned int ui_WriteType;
+ 	int i_ReturnValue = 0;
+ 
+ 	ui_WriteType = CR_CHAN(insn->chanspec);
+@@ -2974,7 +2974,7 @@ int i_APCI1710_InsnWriteINCCPT(struct comedi_device * dev, struct comedi_subdevi
+ 	case APCI1710_INCCPT_WRITE16BITCOUNTERVALUE:
+ 		i_ReturnValue = i_APCI1710_Write16BitCounterValue(dev,
+ 			(unsigned char) CR_AREF(insn->chanspec),
+-			(unsigned char) data[0], (UINT) data[1]);
++			(unsigned char) data[0], (unsigned int) data[1]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_WRITE32BITCOUNTERVALUE:
+@@ -3207,7 +3207,7 @@ int i_APCI1710_DisableLatchInterrupt(struct comedi_device * dev, unsigned char b
+ |                                               (unsigned char_  b_BoardHandle        |
+ |                                                unsigned char_  b_ModulNbr,          |
+ |                                                unsigned char_  b_SelectedCounter,   |
+-|                                                UINT_ ui_WriteValue)        |
++|                                                unsigned int_ ui_WriteValue)        |
+ +----------------------------------------------------------------------------+
+ | Task              : Write a 16-Bit value (ui_WriteValue) in to the selected|
+ |                     16-Bit counter (b_SelectedCounter) from selected module|
+@@ -3218,7 +3218,7 @@ int i_APCI1710_DisableLatchInterrupt(struct comedi_device * dev, unsigned char b
+ |                                              (0 to 3)                      |
+ |                     unsigned char_ b_SelectedCounter : Selected 16-Bit counter      |
+ |                                               (0 or 1)                     |
+-|                     UINT_ ui_WriteValue     : 16-Bit write value           |
++|                     unsigned int_ ui_WriteValue     : 16-Bit write value           |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+ +----------------------------------------------------------------------------+
+@@ -3232,7 +3232,7 @@ int i_APCI1710_DisableLatchInterrupt(struct comedi_device * dev, unsigned char b
+ */
+ 
+ int i_APCI1710_Write16BitCounterValue(struct comedi_device * dev,
+-	unsigned char b_ModulNbr, unsigned char b_SelectedCounter, UINT ui_WriteValue)
++	unsigned char b_ModulNbr, unsigned char b_SelectedCounter, unsigned int ui_WriteValue)
+ {
+ 	int i_ReturnValue = 0;
+ 
+@@ -4052,7 +4052,7 @@ struct comedi_insn *insn,unsigned int *data)                   |
+ int i_APCI1710_InsnReadINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_ReadType;
++	unsigned int ui_ReadType;
+ 	int i_ReturnValue = 0;
+ 
+ 	ui_ReadType = CR_CHAN(insn->chanspec);
+@@ -4075,7 +4075,7 @@ int i_APCI1710_InsnReadINCCPT(struct comedi_device * dev, struct comedi_subdevic
+ 	case APCI1710_INCCPT_READ16BITCOUNTERVALUE:
+ 		i_ReturnValue = i_APCI1710_Read16BitCounterValue(dev,
+ 			(unsigned char) CR_AREF(insn->chanspec),
+-			(unsigned char) CR_RANGE(insn->chanspec), (PUINT) & data[0]);
++			(unsigned char) CR_RANGE(insn->chanspec), (unsigned int *) & data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_READ32BITCOUNTERVALUE:
+@@ -4341,7 +4341,7 @@ int i_APCI1710_ReadLatchRegisterValue(struct comedi_device * dev,
+ |                                       (unsigned char_     b_BoardHandle,            |
+ |                                        unsigned char_     b_ModulNbr,               |
+ |                                        unsigned char_     b_SelectedCounter,        |
+-|                                        PUINT_   pui_CounterValue)          |
++|                                        unsigned int *_   pui_CounterValue)          |
+ +----------------------------------------------------------------------------+
+ | Task              : Latch the selected 16-Bit counter (b_SelectedCounter)  |
+ |                     from selected module (b_ModulNbr) in to the first      |
+@@ -4353,7 +4353,7 @@ int i_APCI1710_ReadLatchRegisterValue(struct comedi_device * dev,
+ |                     unsigned char_ b_SelectedCounter : Selected 16-Bit counter      |
+ |                                               (0 or 1)                     |
+ +----------------------------------------------------------------------------+
+-| Output Parameters : PUINT_ pui_CounterValue : 16-Bit counter value         |
++| Output Parameters : unsigned int *_ pui_CounterValue : 16-Bit counter value         |
+ +----------------------------------------------------------------------------+
+ | Return Value      :  0: No error                                           |
+ |                     -1: The handle parameter of the board is wrong         |
+@@ -4365,7 +4365,7 @@ int i_APCI1710_ReadLatchRegisterValue(struct comedi_device * dev,
+ */
+ 
+ int i_APCI1710_Read16BitCounterValue(struct comedi_device * dev,
+-	unsigned char b_ModulNbr, unsigned char b_SelectedCounter, PUINT pui_CounterValue)
++	unsigned char b_ModulNbr, unsigned char b_SelectedCounter, unsigned int * pui_CounterValue)
+ {
+ 	int i_ReturnValue = 0;
+ 	DWORD dw_LathchValue = 0;
+@@ -4402,7 +4402,7 @@ int i_APCI1710_Read16BitCounterValue(struct comedi_device * dev,
+ 					ui_Address + 4 + (64 * b_ModulNbr));
+ 
+ 				*pui_CounterValue =
+-					(UINT) ((dw_LathchValue >> (16 *
++					(unsigned int) ((dw_LathchValue >> (16 *
+ 							b_SelectedCounter)) &
+ 					0xFFFFU);
+ 			} else {
+@@ -5150,7 +5150,7 @@ int i_APCI1710_ReadFrequencyMeasurement(struct comedi_device * dev,
+ 	unsigned char * pb_Status, unsigned char * pb_UDStatus, PULONG pul_ReadValue)
+ {
+ 	int i_ReturnValue = 0;
+-	UINT ui_16BitValue;
++	unsigned int ui_16BitValue;
+ 	DWORD dw_StatusReg;
+ 
+ 	/**************************/
+@@ -5224,7 +5224,7 @@ int i_APCI1710_ReadFrequencyMeasurement(struct comedi_device * dev,
+ 								if ((*pul_ReadValue & 0xFFFFU) != 0) {
+ 									ui_16BitValue
+ 										=
+-										(UINT)
++										(unsigned int)
+ 										*
+ 										pul_ReadValue
+ 										&
+@@ -5247,7 +5247,7 @@ int i_APCI1710_ReadFrequencyMeasurement(struct comedi_device * dev,
+ 								if ((*pul_ReadValue & 0xFFFF0000UL) != 0) {
+ 									ui_16BitValue
+ 										=
+-										(UINT)
++										(unsigned int)
+ 										(
+ 										(*pul_ReadValue
+ 											>>
+@@ -5281,7 +5281,7 @@ int i_APCI1710_ReadFrequencyMeasurement(struct comedi_device * dev,
+ 								if ((*pul_ReadValue & 0xFFFF0000UL) != 0) {
+ 									ui_16BitValue
+ 										=
+-										(UINT)
++										(unsigned int)
+ 										(
+ 										(*pul_ReadValue
+ 											>>
+@@ -5307,7 +5307,7 @@ int i_APCI1710_ReadFrequencyMeasurement(struct comedi_device * dev,
+ 									if ((*pul_ReadValue & 0xFFFFU) != 0) {
+ 										ui_16BitValue
+ 											=
+-											(UINT)
++											(unsigned int)
+ 											*
+ 											pul_ReadValue
+ 											&
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
+index 03cd1afee10e..cb17feba63f4 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
+@@ -171,7 +171,7 @@ int i_APCI1710_InitExternalStrobe(struct comedi_device *dev,
+ 				  unsigned char b_ExternalStrobeLevel);
+ 
+ int i_APCI1710_InitCompareLogic(struct comedi_device *dev,
+-				unsigned char b_ModulNbr, UINT ui_CompareValue);
++				unsigned char b_ModulNbr, unsigned int ui_CompareValue);
+ 
+ int i_APCI1710_InitFrequencyMeasurement(struct comedi_device *dev,
+ 					unsigned char b_ModulNbr,
+@@ -207,7 +207,7 @@ int i_APCI1710_DisableLatchInterrupt(struct comedi_device *dev, unsigned char b_
+ 
+ int i_APCI1710_Write16BitCounterValue(struct comedi_device *dev,
+ 				      unsigned char b_ModulNbr, unsigned char b_SelectedCounter,
+-				      UINT ui_WriteValue);
++				      unsigned int ui_WriteValue);
+ 
+ int i_APCI1710_Write32BitCounterValue(struct comedi_device *dev,
+ 				      unsigned char b_ModulNbr, ULONG ul_WriteValue);
+@@ -238,7 +238,7 @@ int i_APCI1710_ReadLatchRegisterValue(struct comedi_device *dev,
+ 
+ int i_APCI1710_Read16BitCounterValue(struct comedi_device *dev,
+ 				     unsigned char b_ModulNbr, unsigned char b_SelectedCounter,
+-				     PUINT pui_CounterValue);
++				     unsigned int * pui_CounterValue);
+ 
+ int i_APCI1710_Read32BitCounterValue(struct comedi_device *dev,
+ 				     unsigned char b_ModulNbr, PULONG pul_CounterValue);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+index 3db614172571..03ff861c02f6 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+@@ -137,7 +137,7 @@ int i_APCI1710_InsnConfigInitSSI(struct comedi_device * dev, struct comedi_subde
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_ReturnValue = 0;
+-	UINT ui_TimerValue;
++	unsigned int ui_TimerValue;
+ 	unsigned char b_ModulNbr, b_SSIProfile, b_PositionTurnLength, b_TurnCptLength,
+ 		b_PCIInputClock, b_SSICountingMode;
+ 	ULONG ul_SSIOutputClock;
+@@ -250,7 +250,7 @@ int i_APCI1710_InsnConfigInitSSI(struct comedi_device * dev, struct comedi_subde
+ 
+ 										ui_TimerValue
+ 											=
+-											(UINT)
++											(unsigned int)
+ 											(
+ 											((ULONG) (b_PCIInputClock) * 500000UL) / ul_SSIOutputClock);
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+index 2feaef431336..030ca773f016 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+@@ -857,7 +857,7 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ 		DPRINTK("Module number error\n");
+ 		i_ReturnValue = -2;
+ 	}
+-	data[0] = (UINT) ul_RealTimingInterval;
++	data[0] = (unsigned int) ul_RealTimingInterval;
+ 	return (i_ReturnValue);
+ }
+ 
+@@ -1646,7 +1646,7 @@ int i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
+ |                               (unsigned char_     b_BoardHandle,                    |
+ |                                unsigned char_     b_ModulNbr,                       |
+ |				 unsigned char_     b_TorCounter,                     |
+-|                                UINT_    ui_TimeOut,                        |
++|                                unsigned int_    ui_TimeOut,                        |
+ |                                unsigned char *_   pb_TorCounterStatus,               |
+ |                                PULONG_ pul_TorCounterValue)                |
+ +----------------------------------------------------------------------------+
+@@ -1666,7 +1666,7 @@ int i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
+ 	b_ModulNbr    = CR_AREF(insn->chanspec);
+ 	b_ReadType    = (unsigned char) data[0];
+ 	b_TorCounter  =	(unsigned char) data[1];
+-	ui_TimeOut	  = (UINT) data[2]; |
++	ui_TimeOut	  = (unsigned int) data[2]; |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : unsigned char *_  pb_TorCounterStatus : Return the tor counter   |
+ |                                                    status.                 |
+@@ -1710,7 +1710,7 @@ int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_TorCounter;
+ 	unsigned char b_ReadType;
+-	UINT ui_TimeOut;
++	unsigned int ui_TimeOut;
+ 	unsigned char * pb_TorCounterStatus;
+ 	PULONG pul_TorCounterValue;
+ 
+@@ -1718,7 +1718,7 @@ int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device
+ 	b_ModulNbr = CR_AREF(insn->chanspec);
+ 	b_ReadType = (unsigned char) data[0];
+ 	b_TorCounter = (unsigned char) data[1];
+-	ui_TimeOut = (UINT) data[2];
++	ui_TimeOut = (unsigned int) data[2];
+ 	pb_TorCounterStatus = (unsigned char *) & data[0];
+ 	pul_TorCounterValue = (PULONG) & data[1];
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+index 746fa529f82c..4af2cfdd2de1 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+@@ -832,7 +832,7 @@ int i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device * dev,
+ 	DWORD dw_StatusReg = 0;
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_OutputChannel;
+-	UINT ui_State;
++	unsigned int ui_State;
+ 
+ 	i_ReturnValue = insn->n;
+ 	b_ModulNbr = CR_AREF(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+index daea1c25434b..bf04602d8381 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+@@ -37,7 +37,6 @@
+ #define SUCCESS	1
+ 
+ /* variable type definition */
+-typedef unsigned int UINT, *PUINT;
+ typedef int LONG, *PLONG;		/* 32-bit */
+ typedef unsigned int ULONG, *PULONG;	/* 32-bit */
+ typedef unsigned int DWORD, *PDWORD;	/* 32-bit */
+@@ -50,7 +49,7 @@ typedef const struct comedi_lrange *PCRANGE;
+ #define MAKEWORD(H, L)	(unsigned short)((L) | ((H) << 8))
+ #define LOWORD(W)	(unsigned short)((W) & 0xFFFF)
+ #define HIWORD(W)	(unsigned short)(((W) >> 16) & 0xFFFF)
+-#define MAKEDWORD(H, L)	(UINT)((L) | ((H) << 16))
++#define MAKEDWORD(H, L)	(unsigned int)((L) | ((H) << 16))
+ 
+ #define ADDI_ENABLE		1
+ #define ADDI_DISABLE		0
+@@ -99,8 +98,8 @@ typedef struct {
+ 	int i_Dma;		// dma present or not
+ 	int i_Timer;		//   timer subdevice present or not
+ 	unsigned char b_AvailableConvertUnit;
+-	UINT ui_MinAcquisitiontimeNs;	// Minimum Acquisition in Nano secs
+-	UINT ui_MinDelaytimeNs;	// Minimum Delay in Nano secs
++	unsigned int ui_MinAcquisitiontimeNs;	// Minimum Acquisition in Nano secs
++	unsigned int ui_MinDelaytimeNs;	// Minimum Delay in Nano secs
+ 
+ 	/* interrupt and reset */
+ 	void (*v_hwdrv_Interrupt)(int irq, void *d);
+@@ -366,33 +365,33 @@ typedef struct {
+ 	unsigned char b_ValidDriver;	// driver is ok
+ 	unsigned char b_AiContinuous;	// we do unlimited AI
+ 	unsigned char b_AiInitialisation;
+-	UINT ui_AiActualScan;	//how many scans we finished
+-	UINT ui_AiBufferPtr;	// data buffer ptr in samples
+-	UINT ui_AiNbrofChannels;	// how many channels is measured
+-	UINT ui_AiScanLength;	// Length of actual scanlist
+-	UINT ui_AiActualScanPosition;	// position in actual scan
+-	PUINT pui_AiChannelList;	// actual chanlist
+-	UINT ui_AiChannelList[32];	// actual chanlist
++	unsigned int ui_AiActualScan;	//how many scans we finished
++	unsigned int ui_AiBufferPtr;	// data buffer ptr in samples
++	unsigned int ui_AiNbrofChannels;	// how many channels is measured
++	unsigned int ui_AiScanLength;	// Length of actual scanlist
++	unsigned int ui_AiActualScanPosition;	// position in actual scan
++	unsigned int * pui_AiChannelList;	// actual chanlist
++	unsigned int ui_AiChannelList[32];	// actual chanlist
+ 	unsigned char b_AiChannelConfiguration[32];	// actual chanlist
+-	UINT ui_AiReadData[32];
++	unsigned int ui_AiReadData[32];
+ 	DWORD dw_AiInitialised;
+-	UINT ui_AiTimer0;	//Timer Constant for Timer0
+-	UINT ui_AiTimer1;	//Timer constant for Timer1
+-	UINT ui_AiFlags;
+-	UINT ui_AiDataLength;
++	unsigned int ui_AiTimer0;	//Timer Constant for Timer0
++	unsigned int ui_AiTimer1;	//Timer constant for Timer1
++	unsigned int ui_AiFlags;
++	unsigned int ui_AiDataLength;
+ 	short *AiData;	// Pointer to sample data
+-	UINT ui_AiNbrofScans;	// number of scans to do
++	unsigned int ui_AiNbrofScans;	// number of scans to do
+ 	unsigned short us_UseDma;	// To use Dma or not
+ 	unsigned char b_DmaDoubleBuffer;	// we can use double buffering
+-	UINT ui_DmaActualBuffer;	// which buffer is used now
++	unsigned int ui_DmaActualBuffer;	// which buffer is used now
+ 	//*UPDATE-0.7.57->0.7.68
+ 	//ULONG               ul_DmaBufferVirtual[2];// pointers to begin of DMA buffer
+ 	short *ul_DmaBufferVirtual[2];	// pointers to begin of DMA buffer
+ 	ULONG ul_DmaBufferHw[2];	// hw address of DMA buff
+-	UINT ui_DmaBufferSize[2];	// size of dma buffer in bytes
+-	UINT ui_DmaBufferUsesize[2];	// which size we may now used for transfer
+-	UINT ui_DmaBufferSamples[2];	// size in samples
+-	UINT ui_DmaBufferPages[2];	// number of pages in buffer
++	unsigned int ui_DmaBufferSize[2];	// size of dma buffer in bytes
++	unsigned int ui_DmaBufferUsesize[2];	// which size we may now used for transfer
++	unsigned int ui_DmaBufferSamples[2];	// size in samples
++	unsigned int ui_DmaBufferPages[2];	// number of pages in buffer
+ 	unsigned char b_DigitalOutputRegister;	// Digital Output Register
+ 	unsigned char b_OutputMemoryStatus;
+ 	unsigned char b_AnalogInputChannelNbr;	// Analog input channel Nbr
+@@ -408,7 +407,7 @@ typedef struct {
+ 	unsigned char b_AiCyclicAcquisition;	// indicate cyclic acquisition
+ 	unsigned char b_InterruptMode;	// eoc eos or dma
+ 	unsigned char b_EocEosInterrupt;	// Enable disable eoc eos interrupt
+-	UINT ui_EocEosConversionTime;
++	unsigned int ui_EocEosConversionTime;
+ 	unsigned char b_EocEosConversionTimeBase;
+ 	unsigned char b_SingelDiff;
+ 	unsigned char b_ExttrigEnable;	/* To enable or disable external trigger */
+@@ -419,8 +418,8 @@ typedef struct {
+ 
+ 	/* Hardware board infos for 1710 */
+ 	struct {
+-		UINT ui_Address;	/* Board address */
+-		UINT ui_FlashAddress;
++		unsigned int ui_Address;	/* Board address */
++		unsigned int ui_FlashAddress;
+ 		unsigned char b_InterruptNbr;	/* Board interrupt number */
+ 		unsigned char b_SlotNumber;	/* PCI slot number */
+ 		unsigned char b_BoardVersion;
+@@ -431,8 +430,8 @@ typedef struct {
+ 	struct {
+ 		ULONG ul_InterruptOccur;	/* 0   : No interrupt occur */
+ 						/* > 0 : Interrupt occur */
+-		UINT ui_Read;	/* Read FIFO */
+-		UINT ui_Write;	/* Write FIFO */
++		unsigned int ui_Read;	/* Read FIFO */
++		unsigned int ui_Write;	/* Write FIFO */
+ 		struct {
+ 			unsigned char b_OldModuleMask;
+ 			ULONG ul_OldInterruptMask;	/* Interrupt mask */
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+index ba902bf4a52c..e35e282d209e 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+@@ -806,7 +806,7 @@ int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, struct comedi_device *dev)
+ {
+ 	unsigned short w_Temp, i, w_Count = 0;
+-	UINT ui_Temp;
++	unsigned int ui_Temp;
+ 	str_MainHeader s_MainHeader;
+ 	str_DigitalInputHeader s_DigitalInputHeader;
+ 	str_DigitalOutputHeader s_DigitalOutputHeader;
+@@ -876,10 +876,10 @@ int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
+ 					s_AnalogInputHeader.w_Nchannel;
+ 			this_board->i_Dma = s_AnalogInputHeader.b_HasDma;
+ 			this_board->ui_MinAcquisitiontimeNs =
+-				(UINT) s_AnalogInputHeader.w_MinConvertTiming *
++				(unsigned int) s_AnalogInputHeader.w_MinConvertTiming *
+ 				1000;
+ 			this_board->ui_MinDelaytimeNs =
+-				(UINT) s_AnalogInputHeader.w_MinDelayTiming *
++				(unsigned int) s_AnalogInputHeader.w_MinDelayTiming *
+ 				1000;
+ 			ui_Temp = 0xffff;
+ 			this_board->i_AiMaxdata =
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+index f2578bbe3a3b..1db7f32ab801 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+@@ -255,7 +255,7 @@ void v_APCI1710_Interrupt(int irq, void *d)
+ 	unsigned char b_PWMCpt = 0;
+ 	unsigned char b_TorCounterCpt = 0;
+ 	unsigned char b_PulseIncoderCpt = 0;
+-	UINT ui_16BitValue;
++	unsigned int ui_16BitValue;
+ 	ULONG ul_InterruptLatchReg = 0;
+ 	ULONG ul_LatchRegisterValue = 0;
+ 	ULONG ul_82X54InterruptStatus;
+@@ -675,7 +675,7 @@ void v_APCI1710_Interrupt(int irq, void *d)
+ 						if ((ul_LatchRegisterValue &
+ 								0xFFFFU) != 0) {
+ 							ui_16BitValue =
+-								(UINT)
++								(unsigned int)
+ 								ul_LatchRegisterValue
+ 								& 0xFFFFU;
+ 							ul_LatchRegisterValue =
+@@ -693,7 +693,7 @@ void v_APCI1710_Interrupt(int irq, void *d)
+ 								0xFFFF0000UL) !=
+ 							0) {
+ 							ui_16BitValue =
+-								(UINT) (
++								(unsigned int) (
+ 								(ul_LatchRegisterValue
+ 									>> 16) &
+ 								0xFFFFU);
+@@ -721,7 +721,7 @@ void v_APCI1710_Interrupt(int irq, void *d)
+ 					if ((ul_LatchRegisterValue &
+ 							0xFFFF0000UL) != 0) {
+ 						ui_16BitValue =
+-							(UINT) (
++							(unsigned int) (
+ 							(ul_LatchRegisterValue
+ 								>> 16) &
+ 							0xFFFFU);
+@@ -741,7 +741,7 @@ void v_APCI1710_Interrupt(int irq, void *d)
+ 					if ((ul_LatchRegisterValue & 0xFFFFU) !=
+ 						0) {
+ 						ui_16BitValue =
+-							(UINT)
++							(unsigned int)
+ 							ul_LatchRegisterValue &
+ 							0xFFFFU;
+ 						ul_LatchRegisterValue =
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
+index 1c82f92c228f..42160d82e0be 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
+@@ -64,7 +64,7 @@ int i_Flag = 1;
+ | Task              : Configures The Timer , Counter or Watchdog             |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev : Driver handle                     |
+-|                     UINT *data         : Data Pointer contains             |
++|                     unsigned int *data         : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |                                                                            |
+ |					  data[0]            : 0 Configure As Timer      |
+@@ -112,9 +112,9 @@ int i_Flag = 1;
+ int i_APCI035_ConfigTimerWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_Status = 0;
+-	UINT ui_Command = 0;
+-	UINT ui_Mode = 0;
++	unsigned int ui_Status = 0;
++	unsigned int ui_Command = 0;
++	unsigned int ui_Mode = 0;
+ 	i_Temp = 0;
+ 	devpriv->tsk_Current = current;
+ 	devpriv->b_TimerSelectMode = data[0];
+@@ -260,7 +260,7 @@ int i_APCI035_ConfigTimerWatchdog(struct comedi_device * dev, struct comedi_subd
+ | Task              : Start / Stop The Selected Timer , or Watchdog  |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev : Driver handle                     |
+-|                     UINT *data         : Data Pointer contains             |
++|                     unsigned int *data         : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |					                                                 |
+ |					  data[0] : 0 - Stop Selected Timer/Watchdog     |
+@@ -281,7 +281,7 @@ int i_APCI035_ConfigTimerWatchdog(struct comedi_device * dev, struct comedi_subd
+ int i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_Command = 0;
++	unsigned int ui_Command = 0;
+ 	int i_Count = 0;
+ 	if (data[0] == 1) {
+ 		ui_Command =
+@@ -373,7 +373,7 @@ int i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device * dev,
+ | Task              : Read The Selected Timer , Counter or Watchdog          |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev : Driver handle                     |
+-|                     UINT *data         : Data Pointer contains             |
++|                     unsigned int *data         : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |                                                                            |
+ |     																	 |
+@@ -394,7 +394,7 @@ int i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device * dev,
+ int i_APCI035_ReadTimerWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_Status = 0;	// Status register
++	unsigned int ui_Status = 0;	// Status register
+ 	i_WatchdogNbr = insn->unused[0];
+ 	      /******************/
+ 	/* Get the status */
+@@ -472,8 +472,8 @@ int i_APCI035_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subdev
+ | Task              : Read  value  of the selected channel			         |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                     UINT ui_NoOfChannels    : No Of Channels To read       |
+-|                     UINT *data              : Data Pointer to read status  |
++|                     unsigned int ui_NoOfChannels    : No Of Channels To read       |
++|                     unsigned int *data              : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ |			          data[0]  : Digital Value Of Input              |
+@@ -487,7 +487,7 @@ int i_APCI035_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subdev
+ int i_APCI035_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_CommandRegister = 0;
++	unsigned int ui_CommandRegister = 0;
+ /******************/
+ /*  Set the start */
+ /******************/
+@@ -551,11 +551,11 @@ int i_APCI035_Reset(struct comedi_device * dev)
+ static void v_APCI035_Interrupt(int irq, void *d)
+ {
+ 	struct comedi_device *dev = d;
+-	UINT ui_StatusRegister1 = 0;
+-	UINT ui_StatusRegister2 = 0;
+-	UINT ui_ReadCommand = 0;
+-	UINT ui_ChannelNumber = 0;
+-	UINT ui_DigitalTemperature = 0;
++	unsigned int ui_StatusRegister1 = 0;
++	unsigned int ui_StatusRegister2 = 0;
++	unsigned int ui_ReadCommand = 0;
++	unsigned int ui_ChannelNumber = 0;
++	unsigned int ui_DigitalTemperature = 0;
+ 	if (i_Temp == 1) {
+ 		i_WatchdogNbr = i_Flag;
+ 		i_Flag = i_Flag + 1;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
+index 6ff69aba2217..e0023c8cb628 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
+@@ -27,8 +27,8 @@ struct {
+ 	int i_Coupling;
+ 	int i_SingleDiff;
+ 	int i_AutoCalibration;
+-	UINT ui_ReloadValue;
+-	UINT ui_TimeUnitReloadVal;
++	unsigned int ui_ReloadValue;
++	unsigned int ui_TimeUnitReloadVal;
+ 	int i_Interrupt;
+ 	int i_ModuleSelection;
+ } Config_Parameters_Main;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+index c56b9a52cf6f..8711aaf07a50 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+@@ -54,7 +54,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ #include "hwdrv_apci1032.h"
+ #include 
+ //Global variables
+-UINT ui_InterruptStatus = 0;
++unsigned int ui_InterruptStatus = 0;
+ 
+ /*
+ +----------------------------------------------------------------------------+
+@@ -87,7 +87,7 @@ UINT ui_InterruptStatus = 0;
+ int i_APCI1032_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_TmpValue;
++	unsigned int ui_TmpValue;
+ 
+ 	ULONG ul_Command1 = 0;
+ 	ULONG ul_Command2 = 0;
+@@ -134,7 +134,7 @@ int i_APCI1032_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subd
+ | Task              : Return the status of the digital input                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|		              UINT ui_Channel : Channel number to read       |
++|		              unsigned int ui_Channel : Channel number to read       |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -147,11 +147,11 @@ int i_APCI1032_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subd
+ int i_APCI1032_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_TmpValue = 0;
+-	UINT ui_Channel;
++	unsigned int ui_TmpValue = 0;
++	unsigned int ui_Channel;
+ 	ui_Channel = CR_CHAN(insn->chanspec);
+ 	if (ui_Channel >= 0 && ui_Channel <= 31) {
+-		ui_TmpValue = (UINT) inl(devpriv->iobase + APCI1032_DIGITAL_IP);
++		ui_TmpValue = (unsigned int) inl(devpriv->iobase + APCI1032_DIGITAL_IP);
+ 		//  since only 1 channel reqd  to bring it to last bit it is rotated
+ 		//  8 +(chan - 1) times then ANDed with 1 for last bit.
+ 		*data = (ui_TmpValue >> ui_Channel) & 0x1;
+@@ -172,8 +172,8 @@ int i_APCI1032_Read1DigitalInput(struct comedi_device * dev, struct comedi_subde
+ | Task              : Return the status of the Requested digital inputs      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                     UINT ui_NoOfChannels    : No Of Channels To be Read    |
+-|                      UINT *data             : Data Pointer to read status  |
++|                     unsigned int ui_NoOfChannels    : No Of Channels To be Read    |
++|                      unsigned int *data             : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -186,13 +186,13 @@ int i_APCI1032_Read1DigitalInput(struct comedi_device * dev, struct comedi_subde
+ int i_APCI1032_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_PortValue = data[0];
+-	UINT ui_Mask = 0;
+-	UINT ui_NoOfChannels;
++	unsigned int ui_PortValue = data[0];
++	unsigned int ui_Mask = 0;
++	unsigned int ui_NoOfChannels;
+ 
+ 	ui_NoOfChannels = CR_CHAN(insn->chanspec);
+ 	if (data[1] == 0) {
+-		*data = (UINT) inl(devpriv->iobase + APCI1032_DIGITAL_IP);
++		*data = (unsigned int) inl(devpriv->iobase + APCI1032_DIGITAL_IP);
+ 		switch (ui_NoOfChannels) {
+ 		case 2:
+ 			ui_Mask = 3;
+@@ -247,7 +247,7 @@ static void v_APCI1032_Interrupt(int irq, void *d)
+ {
+ 	struct comedi_device *dev = d;
+ 
+-	UINT ui_Temp;
++	unsigned int ui_Temp;
+ 	//disable the interrupt
+ 	ui_Temp = inl(devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
+ 	outl(ui_Temp & APCI1032_DIGITAL_IP_INTERRUPT_DISABLE,
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+index 646972ce8f69..3c97ed7ee9fe 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+@@ -506,7 +506,7 @@ int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device * dev,
+ | Task              :  Allows or disallows a port event                      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|		              UINT ui_Channel : Channel number to read       |
++|		              unsigned int ui_Channel : Channel number to read       |
+ |                     unsigned int *data          : Data Pointer to read status  |
+                       data[0]                 :0 Start input event
+                                                1 Stop input event
+@@ -774,7 +774,7 @@ int i_APCI1500_StartStopInputEvent(struct comedi_device * dev, struct comedi_sub
+ | Task              : Return the status of the digital input                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|		              UINT ui_Channel : Channel number to read       |
++|		              unsigned int ui_Channel : Channel number to read       |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -943,8 +943,8 @@ int i_APCI1500_Initialisation(struct comedi_device * dev, struct comedi_subdevic
+ | Task              : Return the status of the Requested digital inputs      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                     UINT ui_NoOfChannels    : No Of Channels To be Read    |
+-|                      UINT *data             : Data Pointer
++|                     unsigned int ui_NoOfChannels    : No Of Channels To be Read    |
++|                      unsigned int *data             : Data Pointer
+                       data[0]                 : 0 Read a single channel
+                                                 1 read a port value
+                       data[1]                 : port value
+@@ -960,17 +960,17 @@ int i_APCI1500_Initialisation(struct comedi_device * dev, struct comedi_subdevic
+ int i_APCI1500_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_PortValue = data[1];
+-	UINT ui_Mask = 0;
+-	UINT ui_Channel;
+-	UINT ui_TmpValue = 0;
++	unsigned int ui_PortValue = data[1];
++	unsigned int ui_Mask = 0;
++	unsigned int ui_Channel;
++	unsigned int ui_TmpValue = 0;
+ 	ui_Channel = CR_CHAN(insn->chanspec);
+ 
+ 	switch (data[0]) {
+ 	case 0:
+ 		if (ui_Channel >= 0 && ui_Channel <= 15) {
+ 			ui_TmpValue =
+-				(UINT) inw(devpriv->i_IobaseAddon +
++				(unsigned int) inw(devpriv->i_IobaseAddon +
+ 				APCI1500_DIGITAL_IP);
+ 			*data = (ui_TmpValue >> ui_Channel) & 0x1;
+ 		}		//if(ui_Channel >= 0 && ui_Channel <=15)
+@@ -981,7 +981,7 @@ int i_APCI1500_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ 		break;
+ 	case 1:
+ 
+-		*data = (UINT) inw(devpriv->i_IobaseAddon +
++		*data = (unsigned int) inw(devpriv->i_IobaseAddon +
+ 			APCI1500_DIGITAL_IP);
+ 		switch (ui_Channel) {
+ 		case 2:
+@@ -1056,8 +1056,8 @@ int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device * dev,
+ | Task              : Writes port value  To the selected port                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                     UINT ui_NoOfChannels    : No Of Channels To Write      |
+-|                     UINT *data              : Data Pointer to read status  |
++|                     unsigned int ui_NoOfChannels    : No Of Channels To Write      |
++|                     unsigned int *data              : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -1070,10 +1070,10 @@ int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device * dev,
+ int i_APCI1500_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	static UINT ui_Temp = 0;
+-	UINT ui_Temp1;
++	static unsigned int ui_Temp = 0;
++	unsigned int ui_Temp1;
+ 
+-	UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
++	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
+ 
+ 	if (!devpriv->b_OutputMemoryStatus) {
+ 		ui_Temp = 0;
+@@ -2404,7 +2404,7 @@ int i_APCI1500_ReadInterruptMask(struct comedi_device * dev, struct comedi_subde
+ int i_APCI1500_ConfigureInterrupt(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_Status;
++	unsigned int ui_Status;
+ 	int i_RegValue;
+ 	int i_Constant;
+ 	devpriv->tsk_Current = current;
+@@ -2580,7 +2580,7 @@ static void v_APCI1500_Interrupt(int irq, void *d)
+ {
+ 
+ 	struct comedi_device *dev = d;
+-	UINT ui_InterruptStatus = 0;
++	unsigned int ui_InterruptStatus = 0;
+ 	int i_RegValue = 0;
+ 	i_InterruptMask = 0;
+ 
+@@ -2679,7 +2679,7 @@ static void v_APCI1500_Interrupt(int irq, void *d)
+ 			/* Reads port B */
+ 	     /****************/
+ 			i_RegValue =
+-				inb((UINT) devpriv->iobase +
++				inb((unsigned int) devpriv->iobase +
+ 				APCI1500_Z8536_PORT_B);
+ 
+ 			i_RegValue = i_RegValue & 0xC0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
+index 18e5fbfd493e..3d09025c548a 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
+@@ -76,11 +76,11 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ int i_APCI1516_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_TmpValue = 0;
+-	UINT ui_Channel;
++	unsigned int ui_TmpValue = 0;
++	unsigned int ui_Channel;
+ 	ui_Channel = CR_CHAN(insn->chanspec);
+ 	if (ui_Channel >= 0 && ui_Channel <= 7) {
+-		ui_TmpValue = (UINT) inw(devpriv->iobase + APCI1516_DIGITAL_IP);
++		ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI1516_DIGITAL_IP);
+ 		//  since only 1 channel reqd  to bring it to last bit it is rotated
+ 		//  8 +(chan - 1) times then ANDed with 1 for last bit.
+ 		*data = (ui_TmpValue >> ui_Channel) & 0x1;
+@@ -118,13 +118,13 @@ int i_APCI1516_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+-	UINT ui_PortValue = data[0];
+-	UINT ui_Mask = 0;
+-	UINT ui_NoOfChannels;
++	unsigned int ui_PortValue = data[0];
++	unsigned int ui_Mask = 0;
++	unsigned int ui_NoOfChannels;
+ 
+ 	ui_NoOfChannels = CR_CHAN(insn->chanspec);
+ 
+-	*data = (UINT) inw(devpriv->iobase + APCI1516_DIGITAL_IP);
++	*data = (unsigned int) inw(devpriv->iobase + APCI1516_DIGITAL_IP);
+ 	switch (ui_NoOfChannels) {
+ 	case 2:
+ 		ui_Mask = 3;
+@@ -202,8 +202,8 @@ int i_APCI1516_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ int i_APCI1516_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_Temp, ui_Temp1;
+-	UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
++	unsigned int ui_Temp, ui_Temp1;
++	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
+ 
+ 	printk("EL311003 : @=%x\n", devpriv->iobase + APCI1516_DIGITAL_OP);
+ 
+@@ -363,8 +363,8 @@ int i_APCI1516_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+-	UINT ui_Temp;
+-	UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
++	unsigned int ui_Temp;
++	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
+ 	ui_Temp = data[0];
+ 	*data = inw(devpriv->iobase + APCI1516_DIGITAL_OP_RW);
+ 	if (ui_Temp == 0) {
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+index db0d1795906e..183976c98158 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+@@ -56,8 +56,8 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ #include "hwdrv_apci1564.h"
+ 
+ //Global variables
+-UINT ui_InterruptStatus_1564 = 0;
+-UINT ui_InterruptData, ui_Type;
++unsigned int ui_InterruptStatus_1564 = 0;
++unsigned int ui_InterruptData, ui_Type;
+ 
+ /*
+ +----------------------------------------------------------------------------+
+@@ -137,7 +137,7 @@ int i_APCI1564_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subd
+ | Task              : Return the status of the digital input                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|		              UINT ui_Channel : Channel number to read       |
++|		              unsigned int ui_Channel : Channel number to read       |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -150,13 +150,13 @@ int i_APCI1564_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subd
+ int i_APCI1564_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_TmpValue = 0;
+-	UINT ui_Channel;
++	unsigned int ui_TmpValue = 0;
++	unsigned int ui_Channel;
+ 
+ 	ui_Channel = CR_CHAN(insn->chanspec);
+ 	if (ui_Channel >= 0 && ui_Channel <= 31) {
+ 		ui_TmpValue =
+-			(UINT) inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP);
++			(unsigned int) inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP);
+ 		//  since only 1 channel reqd  to bring it to last bit it is rotated
+ 		//  8 +(chan - 1) times then ANDed with 1 for last bit.
+ 		*data = (ui_TmpValue >> ui_Channel) & 0x1;
+@@ -177,8 +177,8 @@ int i_APCI1564_Read1DigitalInput(struct comedi_device * dev, struct comedi_subde
+ | Task              : Return the status of the Requested digital inputs      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                     UINT ui_NoOfChannels    : No Of Channels To be Read    |
+-|                      UINT *data             : Data Pointer to read status  |
++|                     unsigned int ui_NoOfChannels    : No Of Channels To be Read    |
++|                      unsigned int *data             : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -190,13 +190,13 @@ int i_APCI1564_Read1DigitalInput(struct comedi_device * dev, struct comedi_subde
+ int i_APCI1564_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_PortValue = data[0];
+-	UINT ui_Mask = 0;
+-	UINT ui_NoOfChannels;
++	unsigned int ui_PortValue = data[0];
++	unsigned int ui_Mask = 0;
++	unsigned int ui_NoOfChannels;
+ 
+ 	ui_NoOfChannels = CR_CHAN(insn->chanspec);
+ 	if (data[1] == 0) {
+-		*data = (UINT) inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP);
++		*data = (unsigned int) inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP);
+ 		switch (ui_NoOfChannels) {
+ 		case 2:
+ 			ui_Mask = 3;
+@@ -239,7 +239,7 @@ int i_APCI1564_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ | Task              : Configures The Digital Output Subdevice.               |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev : Driver handle                     |
+-|                     UINT *data         : Data Pointer contains             |
++|                     unsigned int *data         : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |                                                                            |
+ |					  data[1]            : 1 Enable  VCC  Interrupt  |
+@@ -302,8 +302,8 @@ int i_APCI1564_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ | Task              : Writes port value  To the selected port                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                     UINT ui_NoOfChannels    : No Of Channels To Write      |
+-|                     UINT *data              : Data Pointer to read status  |
++|                     unsigned int ui_NoOfChannels    : No Of Channels To Write      |
++|                     unsigned int *data              : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -315,8 +315,8 @@ int i_APCI1564_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ int i_APCI1564_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_Temp, ui_Temp1;
+-	UINT ui_NoOfChannel;
++	unsigned int ui_Temp, ui_Temp1;
++	unsigned int ui_NoOfChannel;
+ 
+ 	ui_NoOfChannel = CR_CHAN(insn->chanspec);
+ 	if (devpriv->b_OutputMemoryStatus) {
+@@ -476,8 +476,8 @@ int i_APCI1564_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                     UINT ui_NoOfChannels    : No Of Channels To read       |
+-|                     UINT *data              : Data Pointer to read status  |
++|                     unsigned int ui_NoOfChannels    : No Of Channels To read       |
++|                     unsigned int *data              : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -489,8 +489,8 @@ int i_APCI1564_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ int i_APCI1564_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_Temp;
+-	UINT ui_NoOfChannel;
++	unsigned int ui_Temp;
++	unsigned int ui_NoOfChannel;
+ 
+ 	ui_NoOfChannel = CR_CHAN(insn->chanspec);
+ 	ui_Temp = data[0];
+@@ -543,7 +543,7 @@ int i_APCI1564_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ | Task              : Configures The Timer , Counter or Watchdog             |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev : Driver handle                     |
+-|                     UINT *data         : Data Pointer contains             |
++|                     unsigned int *data         : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |                                                                            |
+ |					  data[0]            : 0 Configure As Timer      |
+@@ -701,7 +701,7 @@ int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ | Task              : Start / Stop The Selected Timer , Counter or Watchdog  |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev : Driver handle                     |
+-|                     UINT *data         : Data Pointer contains             |
++|                     unsigned int *data         : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |                                                                            |
+ |					  data[0]            : 0 Timer                   |
+@@ -801,7 +801,7 @@ int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ | Task              : Read The Selected Timer , Counter or Watchdog          |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev : Driver handle                     |
+-|                     UINT *data         : Data Pointer contains             |
++|                     unsigned int *data         : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |                                                                            |
+ 
+@@ -919,9 +919,9 @@ int i_APCI1564_ReadInterruptStatus(struct comedi_device * dev, struct comedi_sub
+ static void v_APCI1564_Interrupt(int irq, void *d)
+ {
+ 	struct comedi_device *dev = d;
+-	UINT ui_DO, ui_DI;
+-	UINT ui_Timer;
+-	UINT ui_C1, ui_C2, ui_C3, ui_C4;
++	unsigned int ui_DO, ui_DI;
++	unsigned int ui_Timer;
++	unsigned int ui_C1, ui_C2, ui_C3, ui_C4;
+ 	ULONG ul_Command2 = 0;
+ 	ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+ 		APCI1564_DIGITAL_IP_IRQ) & 0x01;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
+index 6b1e29fd56f6..5bcea0f58eed 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
+@@ -62,7 +62,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ | Task              : Configures The Digital Output Subdevice.               |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev : Driver handle                     |
+-|                     UINT *data         : Data Pointer contains             |
++|                     unsigned int *data         : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |                                                                            |
+ |			  data[0]            : 1 Digital Memory On               |
+@@ -101,8 +101,8 @@ int i_APCI2016_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ | Task              : Writes port value  To the selected port                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                     UINT ui_NoOfChannels    : No Of Channels To Write      |
+-|                     UINT *data              : Data Pointer to read status  |
++|                     unsigned int ui_NoOfChannels    : No Of Channels To Write      |
++|                     unsigned int *data              : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -114,8 +114,8 @@ int i_APCI2016_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ int i_APCI2016_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_NoOfChannel;
+-	UINT ui_Temp, ui_Temp1;
++	unsigned int ui_NoOfChannel;
++	unsigned int ui_Temp, ui_Temp1;
+ 	ui_NoOfChannel = CR_CHAN(insn->chanspec);
+ 	if ((ui_NoOfChannel < 0) || (ui_NoOfChannel > 15)) {
+ 		comedi_error(dev,
+@@ -256,8 +256,8 @@ int i_APCI2016_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                     UINT ui_NoOfChannels    : No Of Channels To read       |
+-|                     UINT *data              : Data Pointer to read status  |
++|                     unsigned int ui_NoOfChannels    : No Of Channels To read       |
++|                     unsigned int *data              : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -269,8 +269,8 @@ int i_APCI2016_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ int i_APCI2016_BitsDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_Temp;
+-	UINT ui_NoOfChannel;
++	unsigned int ui_Temp;
++	unsigned int ui_NoOfChannel;
+ 	ui_NoOfChannel = CR_CHAN(insn->chanspec);
+ 	if ((ui_NoOfChannel < 0) || (ui_NoOfChannel > 15)) {
+ 		comedi_error(dev,
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
+index 82e50d9c371a..888aee4d1d47 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
+@@ -53,7 +53,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ */
+ 
+ #include "hwdrv_apci2032.h"
+-UINT ui_InterruptData, ui_Type;
++unsigned int ui_InterruptData, ui_Type;
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2032_ConfigDigitalOutput                     |
+@@ -63,7 +63,7 @@ UINT ui_InterruptData, ui_Type;
+ | Task              : Configures The Digital Output Subdevice.               |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev : Driver handle                     |
+-|                     UINT *data         : Data Pointer contains             |
++|                     unsigned int *data         : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |                                                                            |
+ |					  data[1]            : 1 Enable  VCC  Interrupt  |
+@@ -123,8 +123,8 @@ int i_APCI2032_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ | Task              : Writes port value  To the selected port                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                     UINT ui_NoOfChannels    : No Of Channels To Write      |
+-|                     UINT *data              : Data Pointer to read status  |
++|                     unsigned int ui_NoOfChannels    : No Of Channels To Write      |
++|                     unsigned int *data              : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -137,8 +137,8 @@ int i_APCI2032_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ int i_APCI2032_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_Temp, ui_Temp1;
+-	UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
++	unsigned int ui_Temp, ui_Temp1;
++	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
+ 	if (devpriv->b_OutputMemoryStatus) {
+ 		ui_Temp = inl(devpriv->iobase + APCI2032_DIGITAL_OP);
+ 
+@@ -302,8 +302,8 @@ int i_APCI2032_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                     UINT ui_NoOfChannels    : No Of Channels To read       |
+-|                     UINT *data              : Data Pointer to read status  |
++|                     unsigned int ui_NoOfChannels    : No Of Channels To read       |
++|                     unsigned int *data              : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -316,8 +316,8 @@ int i_APCI2032_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ int i_APCI2032_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_Temp;
+-	UINT ui_NoOfChannel;
++	unsigned int ui_Temp;
++	unsigned int ui_NoOfChannel;
+ 	ui_NoOfChannel = CR_CHAN(insn->chanspec);
+ 	ui_Temp = data[0];
+ 	*data = inl(devpriv->iobase + APCI2032_DIGITAL_OP_RW);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
+index 404bebb5a706..e56647f28c2e 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
+@@ -76,11 +76,11 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ int i_APCI2200_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_TmpValue = 0;
+-	UINT ui_Channel;
++	unsigned int ui_TmpValue = 0;
++	unsigned int ui_Channel;
+ 	ui_Channel = CR_CHAN(insn->chanspec);
+ 	if (ui_Channel >= 0 && ui_Channel <= 7) {
+-		ui_TmpValue = (UINT) inw(devpriv->iobase + APCI2200_DIGITAL_IP);
++		ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI2200_DIGITAL_IP);
+ 		*data = (ui_TmpValue >> ui_Channel) & 0x1;
+ 	}			//if(ui_Channel >= 0 && ui_Channel <=7)
+ 	else {
+@@ -116,13 +116,13 @@ int i_APCI2200_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+-	UINT ui_PortValue = data[0];
+-	UINT ui_Mask = 0;
+-	UINT ui_NoOfChannels;
++	unsigned int ui_PortValue = data[0];
++	unsigned int ui_Mask = 0;
++	unsigned int ui_NoOfChannels;
+ 
+ 	ui_NoOfChannels = CR_CHAN(insn->chanspec);
+ 
+-	*data = (UINT) inw(devpriv->iobase + APCI2200_DIGITAL_IP);
++	*data = (unsigned int) inw(devpriv->iobase + APCI2200_DIGITAL_IP);
+ 	switch (ui_NoOfChannels) {
+ 	case 2:
+ 		ui_Mask = 3;
+@@ -200,8 +200,8 @@ int i_APCI2200_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ int i_APCI2200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_Temp, ui_Temp1;
+-	UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
++	unsigned int ui_Temp, ui_Temp1;
++	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
+ 	if (devpriv->b_OutputMemoryStatus) {
+ 		ui_Temp = inw(devpriv->iobase + APCI2200_DIGITAL_OP);
+ 
+@@ -358,8 +358,8 @@ int i_APCI2200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+-	UINT ui_Temp;
+-	UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
++	unsigned int ui_Temp;
++	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
+ 	ui_Temp = data[0];
+ 	*data = inw(devpriv->iobase + APCI2200_DIGITAL_OP);
+ 	if (ui_Temp == 0) {
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+index 84582f45726c..f3556e0d52cb 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+@@ -45,7 +45,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ */
+ 
+ #include "hwdrv_apci3120.h"
+-static UINT ui_Temp = 0;
++static unsigned int ui_Temp = 0;
+ 
+ // FUNCTION DEFINITIONS
+ 
+@@ -77,7 +77,7 @@ static UINT ui_Temp = 0;
+ int i_APCI3120_InsnConfigAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT i;
++	unsigned int i;
+ 
+ 	if ((data[0] != APCI3120_EOC_MODE) && (data[0] != APCI3120_EOS_MODE))
+ 		return -1;
+@@ -373,7 +373,7 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_sub
+ 					i++) {
+ 					//Read the result in FIFO and write them in shared memory
+ 					us_TmpValue = inw(devpriv->iobase);
+-					data[i] = (UINT) us_TmpValue;
++					data[i] = (unsigned int) us_TmpValue;
+ 				}
+ 
+ 				devpriv->b_InterruptMode = APCI3120_EOC_MODE;	// Restore defaults.
+@@ -711,7 +711,7 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 	struct comedi_subdevice * s)
+ {
+ 	unsigned char b_Tmp;
+-	UINT ui_Tmp, ui_DelayTiming = 0, ui_TimerValue1 = 0, dmalen0 =
++	unsigned int ui_Tmp, ui_DelayTiming = 0, ui_TimerValue1 = 0, dmalen0 =
+ 		0, dmalen1 = 0, ui_TimerValue2 =
+ 		0, ui_TimerValue0, ui_ConvertTiming;
+ 	unsigned short us_TmpValue;
+@@ -800,21 +800,21 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 	 if((us_TmpValue & 0x00B0)==0x00B0)
+ 	 {
+            f_ConvertValue=(((float)ui_ConvertTiming * 0.002) - 2);
+-		ui_TimerValue0=(UINT)f_ConvertValue;
++		ui_TimerValue0=(unsigned int)f_ConvertValue;
+ 		if (mode==2)
+ 		{
+ 			f_DelayValue     = (((float)ui_DelayTiming * 0.00002) - 2);
+-			ui_TimerValue1  =   (UINT) f_DelayValue;
++			ui_TimerValue1  =   (unsigned int) f_DelayValue;
+ 		}
+ 	 }
+    	 else
+ 	 {
+ 		f_ConvertValue=(((float)ui_ConvertTiming * 0.0012926) - 1);
+-		ui_TimerValue0=(UINT)f_ConvertValue;
++		ui_TimerValue0=(unsigned int)f_ConvertValue;
+ 		if (mode == 2)
+ 		{
+ 		     f_DelayValue     = (((float)ui_DelayTiming * 0.000012926) - 1);
+-		     ui_TimerValue1  =   (UINT) f_DelayValue;
++		     ui_TimerValue1  =   (unsigned int) f_DelayValue;
+ 		}
+ 	}
+ ***********************************************************************************************/
+@@ -1464,7 +1464,7 @@ void v_APCI3120_Interrupt(int irq, void *d)
+ 			// Read the AI Value
+ 
+ 			devpriv->ui_AiReadData[0] =
+-				(UINT) inw(devpriv->iobase + 0);
++				(unsigned int) inw(devpriv->iobase + 0);
+ 			devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
+ 			send_sig(SIGIO, devpriv->tsk_Current, 0);	// send signal to the sample
+ 		} else {
+@@ -1501,7 +1501,7 @@ void v_APCI3120_Interrupt(int irq, void *d)
+ 					i++) {
+ 					us_TmpValue = inw(devpriv->iobase + 0);
+ 					devpriv->ui_AiReadData[i] =
+-						(UINT) us_TmpValue;
++						(unsigned int) us_TmpValue;
+ 				}
+ 				devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
+ 				devpriv->b_InterruptMode = APCI3120_EOC_MODE;
+@@ -1704,7 +1704,7 @@ void v_APCI3120_InterruptDma(int irq, void *d)
+ 	unsigned int next_dma_buf, samplesinbuf;
+ 	unsigned long low_word, high_word, var;
+ 
+-	UINT ui_Tmp;
++	unsigned int ui_Tmp;
+ 	samplesinbuf =
+ 		devpriv->ui_DmaBufferUsesize[devpriv->ui_DmaActualBuffer] -
+ 		inl(devpriv->i_IobaseAmcc + AMCC_OP_REG_MWTC);
+@@ -1972,7 +1972,7 @@ int i_APCI3120_InsnConfigTimer(struct comedi_device * dev, struct comedi_subdevi
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+-	UINT ui_Timervalue2;
++	unsigned int ui_Timervalue2;
+ 	unsigned short us_TmpValue;
+ 	unsigned char b_Tmp;
+ 
+@@ -2123,7 +2123,7 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device * dev, struct comedi_subdevic
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+-	UINT ui_Timervalue2 = 0;
++	unsigned int ui_Timervalue2 = 0;
+ 	unsigned short us_TmpValue;
+ 	unsigned char b_Tmp;
+ 
+@@ -2336,7 +2336,7 @@ int i_APCI3120_InsnReadTimer(struct comedi_device * dev, struct comedi_subdevice
+ 		us_TmpValue_2 = inw(devpriv->iobase + APCI3120_TIMER_VALUE);
+ 
+ 		// combining both words
+-		data[0] = (UINT) ((us_TmpValue) | ((us_TmpValue_2) << 16));
++		data[0] = (unsigned int) ((us_TmpValue) | ((us_TmpValue_2) << 16));
+ 
+ 	} else			// Read watch dog status
+ 	{
+@@ -2384,13 +2384,13 @@ int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev,
+ 				    struct comedi_insn *insn,
+ 				    unsigned int *data)
+ {
+-	UINT ui_Chan, ui_TmpValue;
++	unsigned int ui_Chan, ui_TmpValue;
+ 
+ 	ui_Chan = CR_CHAN(insn->chanspec);	// channel specified
+ 
+ 	//this_board->i_hwdrv_InsnReadDigitalInput(dev,ui_Chan,data);
+ 	if (ui_Chan >= 0 && ui_Chan <= 3) {
+-		ui_TmpValue = (UINT) inw(devpriv->iobase + APCI3120_RD_STATUS);
++		ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI3120_RD_STATUS);
+ 
+ 		//      since only 1 channel reqd  to bring it to last bit it is rotated
+ 		//  8 +(chan - 1) times then ANDed with 1 for last bit.
+@@ -2426,8 +2426,8 @@ int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev,
+ int i_APCI3120_InsnBitsDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_TmpValue;
+-	ui_TmpValue = (UINT) inw(devpriv->iobase + APCI3120_RD_STATUS);
++	unsigned int ui_TmpValue;
++	ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI3120_RD_STATUS);
+ 	/*****	state of 4 channels  in the 11, 10, 9, 8   bits of status reg
+ 			rotated right 8 times to bring them to last four bits
+ 			ANDed with oxf for  value.
+@@ -2567,9 +2567,9 @@ int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev,
+ 				      unsigned int *data)
+ {
+ 
+-	UINT ui_Temp1;
++	unsigned int ui_Temp1;
+ 
+-	UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
++	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
+ 
+ 	if ((data[0] != 0) && (data[0] != 1)) {
+ 		comedi_error(dev,
+@@ -2646,7 +2646,7 @@ int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev,
+ 				     struct comedi_insn *insn,
+ 				     unsigned int *data)
+ {
+-	UINT ui_Range, ui_Channel;
++	unsigned int ui_Range, ui_Channel;
+ 	unsigned short us_TmpValue;
+ 
+ 	ui_Range = CR_RANGE(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
+index 03031bb027a2..db5b291a3278 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
+@@ -168,10 +168,10 @@ static const struct comedi_lrange range_apci3120_ao = { 2, {
+ typedef struct {
+ 	unsigned char b_Type;		/* EOC or EOS */
+ 	unsigned char b_InterruptFlag;	/* Interrupt use or not                    */
+-	UINT ui_ConvertTiming;	/* Selection of the convertion time        */
++	unsigned int ui_ConvertTiming;	/* Selection of the convertion time        */
+ 	unsigned char b_NbrOfChannel;	/* Number of channel to read               */
+-	UINT ui_ChannelList[MAX_ANALOGINPUT_CHANNELS];	/* Number of the channel to be read        */
+-	UINT ui_RangeList[MAX_ANALOGINPUT_CHANNELS];	/* Gain of each channel                    */
++	unsigned int ui_ChannelList[MAX_ANALOGINPUT_CHANNELS];	/* Number of the channel to be read        */
++	unsigned int ui_RangeList[MAX_ANALOGINPUT_CHANNELS];	/* Gain of each channel                    */
+ 
+ } str_AnalogReadInformation;
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+index 92e57b32b8fb..1aa60d6c3456 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+@@ -82,10 +82,10 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+   int i_LastChannel;
+   int i_Sum=0;
+   int i_Offset;
+-  UINT ui_Channel_num=0;
++  unsigned int ui_Channel_num=0;
+   static int i_Count=0;
+   int i_Initialised=0;
+-  UINT ui_InterruptChannelValue[96]; //Buffer
++  unsigned int ui_InterruptChannelValue[96]; //Buffer
+ */
+ str_BoardInfos s_BoardInfos[100];	// 100 will be the max number of boards to be used
+ //END JK 06.07.04: Management of sevrals boards
+@@ -536,9 +536,9 @@ int i_APCI3200_GetChannelCalibrationValue(struct comedi_device * dev,
+   | Task              : Read  value  of the selected channel or port           |
+   +----------------------------------------------------------------------------+
+   | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-  |                     UINT ui_NoOfChannels    : No Of Channels To read  for Port
++  |                     unsigned int ui_NoOfChannels    : No Of Channels To read  for Port
+   Channel Numberfor single channel
+-  |                     UINT data[0]            : 0: Read single channel
++  |                     unsigned int data[0]            : 0: Read single channel
+   1: Read port value
+   data[1]              Port number
+   +----------------------------------------------------------------------------+
+@@ -553,8 +553,8 @@ int i_APCI3200_GetChannelCalibrationValue(struct comedi_device * dev,
+ int i_APCI3200_ReadDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_Temp = 0;
+-	UINT ui_NoOfChannel = 0;
++	unsigned int ui_Temp = 0;
++	unsigned int ui_NoOfChannel = 0;
+ 	ui_NoOfChannel = CR_CHAN(insn->chanspec);
+ 	ui_Temp = data[0];
+ 	*data = inl(devpriv->i_IobaseReserved);
+@@ -656,8 +656,8 @@ int i_APCI3200_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ int i_APCI3200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_Temp = 0, ui_Temp1 = 0;
+-	UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
++	unsigned int ui_Temp = 0, ui_Temp1 = 0;
++	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
+ 	if (devpriv->b_OutputMemoryStatus) {
+ 		ui_Temp = inl(devpriv->i_IobaseAddon);
+ 
+@@ -752,8 +752,8 @@ int i_APCI3200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+   | Task              : Read  value  of the selected channel or port           |
+   +----------------------------------------------------------------------------+
+   | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-  |                     UINT ui_NoOfChannels    : No Of Channels To read       |
+-  |                     UINT *data              : Data Pointer to read status  |
++  |                     unsigned int ui_NoOfChannels    : No Of Channels To read       |
++  |                     unsigned int *data              : Data Pointer to read status  |
+   data[0]                 :0 read single channel
+   1 read port value
+   data[1]                  port no
+@@ -769,8 +769,8 @@ int i_APCI3200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ int i_APCI3200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_Temp;
+-	UINT ui_NoOfChannel;
++	unsigned int ui_Temp;
++	unsigned int ui_NoOfChannel;
+ 	ui_NoOfChannel = CR_CHAN(insn->chanspec);
+ 	ui_Temp = data[0];
+ 	*data = inl(devpriv->i_IobaseAddon);
+@@ -878,9 +878,9 @@ int i_APCI3200_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subde
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+-	UINT ul_Config = 0, ul_Temp = 0;
+-	UINT ui_ChannelNo = 0;
+-	UINT ui_Dummy = 0;
++	unsigned int ul_Config = 0, ul_Temp = 0;
++	unsigned int ui_ChannelNo = 0;
++	unsigned int ui_Dummy = 0;
+ 	int i_err = 0;
+ 
+ 	//Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+@@ -1340,8 +1340,8 @@ int i_APCI3200_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subde
+   | Task              : Read  value  of the selected channel			         |
+   +----------------------------------------------------------------------------+
+   | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-  |                     UINT ui_NoOfChannels    : No Of Channels To read       |
+-  |                     UINT *data              : Data Pointer to read status  |
++  |                     unsigned int ui_NoOfChannels    : No Of Channels To read       |
++  |                     unsigned int *data              : Data Pointer to read status  |
+   +----------------------------------------------------------------------------+
+   | Output Parameters :	--													 |
+   |				data[0]  : Digital Value Of Input             |
+@@ -1364,7 +1364,7 @@ int i_APCI3200_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subde
+ int i_APCI3200_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_DummyValue = 0;
++	unsigned int ui_DummyValue = 0;
+ 	int i_ConvertCJCCalibration;
+ 	int i = 0;
+ 
+@@ -1639,8 +1639,8 @@ int i_APCI3200_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevi
+   | Task              : Read  value  of the selected channel			         |
+   +----------------------------------------------------------------------------+
+   | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-  |                     UINT ui_NoOfChannel    : Channel No to read            |
+-  |                     UINT *data              : Data Pointer to read status  |
++  |                     unsigned int ui_NoOfChannel    : Channel No to read            |
++  |                     unsigned int *data              : Data Pointer to read status  |
+   +----------------------------------------------------------------------------+
+   | Output Parameters :	--													 |
+   |			          data[0]  : Digital Value read                   |
+@@ -1654,9 +1654,9 @@ int i_APCI3200_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevi
+ int i_APCI3200_Read1AnalogInputChannel(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_EOC = 0;
+-	UINT ui_ChannelNo = 0;
+-	UINT ui_CommandRegister = 0;
++	unsigned int ui_EOC = 0;
++	unsigned int ui_ChannelNo = 0;
++	unsigned int ui_CommandRegister = 0;
+ 
+ 	//BEGIN JK 06.07.04: Management of sevrals boards
+ 	//ui_ChannelNo=i_ChannelNo;
+@@ -1765,7 +1765,7 @@ int i_APCI3200_Read1AnalogInputChannel(struct comedi_device * dev,
+   | Task              : Read calibration offset  value  of the selected channel|
+   +----------------------------------------------------------------------------+
+   | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-  |                     UINT *data              : Data Pointer to read status  |
++  |                     unsigned int *data              : Data Pointer to read status  |
+   +----------------------------------------------------------------------------+
+   | Output Parameters :	--													 |
+   |			          data[0]  : Calibration offset Value   |
+@@ -1776,10 +1776,10 @@ int i_APCI3200_Read1AnalogInputChannel(struct comedi_device * dev,
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device * dev, UINT * data)
++int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device * dev, unsigned int * data)
+ {
+-	UINT ui_Temp = 0, ui_EOC = 0;
+-	UINT ui_CommandRegister = 0;
++	unsigned int ui_Temp = 0, ui_EOC = 0;
++	unsigned int ui_CommandRegister = 0;
+ 
+ 	//BEGIN JK 06.07.04: Management of sevrals boards
+ 	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+@@ -1901,7 +1901,7 @@ int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device * dev, UINT * dat
+   | Task              : Read calibration gain  value  of the selected channel  |
+   +----------------------------------------------------------------------------+
+   | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-  |                     UINT *data              : Data Pointer to read status  |
++  |                     unsigned int *data              : Data Pointer to read status  |
+   +----------------------------------------------------------------------------+
+   | Output Parameters :	--													 |
+   |			          data[0]  : Calibration gain Value Of Input     |
+@@ -1912,9 +1912,9 @@ int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device * dev, UINT * dat
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-int i_APCI3200_ReadCalibrationGainValue(struct comedi_device * dev, UINT * data)
++int i_APCI3200_ReadCalibrationGainValue(struct comedi_device * dev, unsigned int * data)
+ {
+-	UINT ui_EOC = 0;
++	unsigned int ui_EOC = 0;
+ 	int ui_CommandRegister = 0;
+ 
+ 	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+@@ -2036,7 +2036,7 @@ int i_APCI3200_ReadCalibrationGainValue(struct comedi_device * dev, UINT * data)
+   | Task              : Read CJC  value  of the selected channel               |
+   +----------------------------------------------------------------------------+
+   | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-  |                     UINT *data              : Data Pointer to read status  |
++  |                     unsigned int *data              : Data Pointer to read status  |
+   +----------------------------------------------------------------------------+
+   | Output Parameters :	--													 |
+   |			          data[0]  : CJC Value                           |
+@@ -2050,7 +2050,7 @@ int i_APCI3200_ReadCalibrationGainValue(struct comedi_device * dev, UINT * data)
+ 
+ int i_APCI3200_ReadCJCValue(struct comedi_device * dev, unsigned int * data)
+ {
+-	UINT ui_EOC = 0;
++	unsigned int ui_EOC = 0;
+ 	int ui_CommandRegister = 0;
+ 
+   /******************************/
+@@ -2156,7 +2156,7 @@ int i_APCI3200_ReadCJCValue(struct comedi_device * dev, unsigned int * data)
+   | Task              : Read CJC calibration offset  value  of the selected channel
+   +----------------------------------------------------------------------------+
+   | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-  |                     UINT *data              : Data Pointer to read status  |
++  |                     unsigned int *data              : Data Pointer to read status  |
+   +----------------------------------------------------------------------------+
+   | Output Parameters :	--													 |
+   |			          data[0]  : CJC calibration offset Value
+@@ -2169,7 +2169,7 @@ int i_APCI3200_ReadCJCValue(struct comedi_device * dev, unsigned int * data)
+ */
+ int i_APCI3200_ReadCJCCalOffset(struct comedi_device * dev, unsigned int * data)
+ {
+-	UINT ui_EOC = 0;
++	unsigned int ui_EOC = 0;
+ 	int ui_CommandRegister = 0;
+   /*******************************************/
+ 	/*Read calibration offset value for the CJC */
+@@ -2271,8 +2271,8 @@ int i_APCI3200_ReadCJCCalOffset(struct comedi_device * dev, unsigned int * data)
+   | Task              : Read CJC calibration gain value
+   +----------------------------------------------------------------------------+
+   | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-  |                     UINT ui_NoOfChannels    : No Of Channels To read       |
+-  |                     UINT *data              : Data Pointer to read status  |
++  |                     unsigned int ui_NoOfChannels    : No Of Channels To read       |
++  |                     unsigned int *data              : Data Pointer to read status  |
+   +----------------------------------------------------------------------------+
+   | Output Parameters :	--													 |
+   |			          data[0]  : CJC calibration gain value
+@@ -2285,7 +2285,7 @@ int i_APCI3200_ReadCJCCalOffset(struct comedi_device * dev, unsigned int * data)
+ */
+ int i_APCI3200_ReadCJCCalGain(struct comedi_device * dev, unsigned int * data)
+ {
+-	UINT ui_EOC = 0;
++	unsigned int ui_EOC = 0;
+ 	int ui_CommandRegister = 0;
+   /*******************************/
+ 	/* Set the convert timing unit */
+@@ -2407,7 +2407,7 @@ int i_APCI3200_ReadCJCCalGain(struct comedi_device * dev, unsigned int * data)
+ int i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_Configuration = 0;
++	unsigned int ui_Configuration = 0;
+ 	int i_Temp;		//,i_TimeUnit;
+ 	//if(i_Initialised==0)
+ 
+@@ -2566,10 +2566,10 @@ int i_APCI3200_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_
+ 
+ 	int err = 0;
+ 	int tmp;		// divisor1,divisor2;
+-	UINT ui_ConvertTime = 0;
+-	UINT ui_ConvertTimeBase = 0;
+-	UINT ui_DelayTime = 0;
+-	UINT ui_DelayTimeBase = 0;
++	unsigned int ui_ConvertTime = 0;
++	unsigned int ui_ConvertTimeBase = 0;
++	unsigned int ui_DelayTime = 0;
++	unsigned int ui_DelayTimeBase = 0;
+ 	int i_Triggermode = 0;
+ 	int i_TriggerEdge = 0;
+ 	int i_NbrOfChannel = 0;
+@@ -2766,7 +2766,7 @@ int i_APCI3200_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_
+ 
+ int i_APCI3200_StopCyclicAcquisition(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	UINT ui_Configuration = 0;
++	unsigned int ui_Configuration = 0;
+ 	//i_InterruptFlag=0;
+ 	//i_Initialised=0;
+ 	//i_Count=0;
+@@ -2817,17 +2817,17 @@ int i_APCI3200_StopCyclicAcquisition(struct comedi_device * dev, struct comedi_s
+ int i_APCI3200_CommandAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+-	UINT ui_Configuration = 0;
++	unsigned int ui_Configuration = 0;
+ 	//INT  i_CurrentSource = 0;
+-	UINT ui_Trigger = 0;
+-	UINT ui_TriggerEdge = 0;
+-	UINT ui_Triggermode = 0;
+-	UINT ui_ScanMode = 0;
+-	UINT ui_ConvertTime = 0;
+-	UINT ui_ConvertTimeBase = 0;
+-	UINT ui_DelayTime = 0;
+-	UINT ui_DelayTimeBase = 0;
+-	UINT ui_DelayMode = 0;
++	unsigned int ui_Trigger = 0;
++	unsigned int ui_TriggerEdge = 0;
++	unsigned int ui_Triggermode = 0;
++	unsigned int ui_ScanMode = 0;
++	unsigned int ui_ConvertTime = 0;
++	unsigned int ui_ConvertTimeBase = 0;
++	unsigned int ui_DelayTime = 0;
++	unsigned int ui_DelayTimeBase = 0;
++	unsigned int ui_DelayMode = 0;
+ 	//i_FirstChannel=cmd->chanlist[0];
+ 	//i_LastChannel=cmd->chanlist[1];
+ 	s_BoardInfos[dev->minor].i_FirstChannel = cmd->chanlist[0];
+@@ -3060,13 +3060,13 @@ int i_APCI3200_Reset(struct comedi_device * dev)
+ void v_APCI3200_Interrupt(int irq, void *d)
+ {
+ 	struct comedi_device *dev = d;
+-	UINT ui_StatusRegister = 0;
+-	UINT ui_ChannelNumber = 0;
++	unsigned int ui_StatusRegister = 0;
++	unsigned int ui_ChannelNumber = 0;
+ 	int i_CalibrationFlag = 0;
+ 	int i_CJCFlag = 0;
+-	UINT ui_DummyValue = 0;
+-	UINT ui_DigitalTemperature = 0;
+-	UINT ui_DigitalInput = 0;
++	unsigned int ui_DummyValue = 0;
++	unsigned int ui_DigitalTemperature = 0;
++	unsigned int ui_DigitalInput = 0;
+ 	int i_ConvertCJCCalibration;
+ 
+ 	//BEGIN JK TEST
+@@ -3501,7 +3501,7 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ */
+ int i_APCI3200_InterruptHandleEos(struct comedi_device * dev)
+ {
+-	UINT ui_StatusRegister = 0;
++	unsigned int ui_StatusRegister = 0;
+ 	struct comedi_subdevice *s = dev->subdevices + 0;
+ 
+ 	//BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+@@ -3588,13 +3588,13 @@ int i_APCI3200_InterruptHandleEos(struct comedi_device * dev)
+ 
+ 			s_BoardInfos[dev->minor].i_Count = -1;
+ 
+-			//async->buf_int_count+=(i_LastChannel-i_FirstChannel+4)*sizeof(UINT);
++			//async->buf_int_count+=(i_LastChannel-i_FirstChannel+4)*sizeof(unsigned int);
+ 			//Begin JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+-			//async->buf_int_count+=(s_BoardInfos [dev->minor].i_LastChannel-s_BoardInfos [dev->minor].i_FirstChannel+4)*sizeof(UINT);
++			//async->buf_int_count+=(s_BoardInfos [dev->minor].i_LastChannel-s_BoardInfos [dev->minor].i_FirstChannel+4)*sizeof(unsigned int);
+ 			//End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+-			//async->buf_int_ptr+=(i_LastChannel-i_FirstChannel+4)*sizeof(UINT);
++			//async->buf_int_ptr+=(i_LastChannel-i_FirstChannel+4)*sizeof(unsigned int);
+ 			//Begin JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+-			//async->buf_int_ptr+=(s_BoardInfos [dev->minor].i_LastChannel-s_BoardInfos [dev->minor].i_FirstChannel+4)*sizeof(UINT);
++			//async->buf_int_ptr+=(s_BoardInfos [dev->minor].i_LastChannel-s_BoardInfos [dev->minor].i_FirstChannel+4)*sizeof(unsigned int);
+ 			//comedi_eos(dev,s);
+ 
+ 			// Set the event type (Comedi Buffer End Of Scan)
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+index 416a7f0370d7..3fc7b0b1e566 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+@@ -27,8 +27,8 @@ struct {
+ 	int i_Coupling;
+ 	int i_SingleDiff;
+ 	int i_AutoCalibration;
+-	UINT ui_ReloadValue;
+-	UINT ui_TimeUnitReloadVal;
++	unsigned int ui_ReloadValue;
++	unsigned int ui_TimeUnitReloadVal;
+ 	int i_Interrupt;
+ 	int i_ModuleSelection;
+ } Config_Parameters_Module1, Config_Parameters_Module2,
+@@ -132,11 +132,11 @@ typedef struct {
+ 	int i_LastChannel;
+ 	int i_Sum;
+ 	int i_Offset;
+-	UINT ui_Channel_num;
++	unsigned int ui_Channel_num;
+ 	int i_Count;
+ 	int i_Initialised;
+ 	//UINT ui_InterruptChannelValue[96]; //Buffer
+-	UINT ui_InterruptChannelValue[144];	//Buffer
++	unsigned int ui_InterruptChannelValue[144];	//Buffer
+ 	unsigned char b_StructInitialized;
+ 	//Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+ 	unsigned int ui_ScanValueArray[7 + 12];	// 7 is the maximal number of channels
+@@ -179,8 +179,8 @@ int i_APCI3200_Reset(struct comedi_device *dev);
+ 
+ int i_APCI3200_ReadCJCCalOffset(struct comedi_device *dev, unsigned int *data);
+ int i_APCI3200_ReadCJCValue(struct comedi_device *dev, unsigned int *data);
+-int i_APCI3200_ReadCalibrationGainValue(struct comedi_device *dev, UINT *data);
+-int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device *dev, UINT *data);
++int i_APCI3200_ReadCalibrationGainValue(struct comedi_device *dev, unsigned int *data);
++int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device *dev, unsigned int *data);
+ int i_APCI3200_Read1AnalogInputChannel(struct comedi_device *dev,
+ 				       struct comedi_subdevice *s, struct comedi_insn *insn,
+ 				       unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
+index 59234e82e552..4a78cecd2ebf 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
+@@ -62,8 +62,8 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                     UINT ui_NoOfChannels    : No Of Channels To read       |
+-|                     UINT *data              : Data Pointer to read status  |
++|                     unsigned int ui_NoOfChannels    : No Of Channels To read       |
++|                     unsigned int *data              : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -76,8 +76,8 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ int i_APCI3501_ReadDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_Temp;
+-	UINT ui_NoOfChannel;
++	unsigned int ui_Temp;
++	unsigned int ui_NoOfChannel;
+ 	ui_NoOfChannel = CR_CHAN(insn->chanspec);
+ 	ui_Temp = data[0];
+ 	*data = inl(devpriv->iobase + APCI3501_DIGITAL_IP);
+@@ -105,7 +105,7 @@ int i_APCI3501_ReadDigitalInput(struct comedi_device * dev, struct comedi_subdev
+ | Task              : Configures The Digital Output Subdevice.               |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev : Driver handle                     |
+-|                     UINT *data         : Data Pointer contains             |
++|                     unsigned int *data         : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |                                                                            |
+ |					  data[1]            : 1 Enable  VCC  Interrupt  |
+@@ -164,8 +164,8 @@ int i_APCI3501_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ int i_APCI3501_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_Temp, ui_Temp1;
+-	UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
++	unsigned int ui_Temp, ui_Temp1;
++	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
+ 	if (devpriv->b_OutputMemoryStatus) {
+ 		ui_Temp = inl(devpriv->iobase + APCI3501_DIGITAL_OP);
+ 	}			//if(devpriv->b_OutputMemoryStatus )
+@@ -238,8 +238,8 @@ int i_APCI3501_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                     UINT ui_NoOfChannels    : No Of Channels To read       |
+-|                     UINT *data              : Data Pointer to read status  |
++|                     unsigned int ui_NoOfChannels    : No Of Channels To read       |
++|                     unsigned int *data              : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -251,8 +251,8 @@ int i_APCI3501_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ int i_APCI3501_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	UINT ui_Temp;
+-	UINT ui_NoOfChannel;
++	unsigned int ui_Temp;
++	unsigned int ui_NoOfChannel;
+ 
+ 	ui_NoOfChannel = CR_CHAN(insn->chanspec);
+ 	ui_Temp = data[0];
+@@ -392,7 +392,7 @@ int i_APCI3501_WriteAnalogOutput(struct comedi_device * dev, struct comedi_subde
+ | Task              : Configures The Timer , Counter or Watchdog             |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev : Driver handle                     |
+-|                     UINT *data         : Data Pointer contains             |
++|                     unsigned int *data         : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |                                                                            |
+ |					  data[0]            : 0 Configure As Timer      |
+@@ -495,7 +495,7 @@ int i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ | Task              : Start / Stop The Selected Timer , Counter or Watchdog  |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev : Driver handle                     |
+-|                     UINT *data         : Data Pointer contains             |
++|                     unsigned int *data         : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |                                                                            |
+ |					  data[0]            : 0 Timer                   |
+@@ -598,7 +598,7 @@ int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ | Task              : Read The Selected Timer , Counter or Watchdog          |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev : Driver handle                     |
+-|                     UINT *data         : Data Pointer contains             |
++|                     unsigned int *data         : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |                                                                            |
+ |					  data[0]            : 0 Timer                   |
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+index f7745278e53a..54f9ea52af94 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+@@ -186,7 +186,7 @@ int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device * dev,
+ 								devpriv->
+ 									ui_EocEosConversionTime
+ 									=
+-									(UINT)
++									(unsigned int)
+ 									dw_ReloadValue;
+ 								devpriv->
+ 									b_EocEosConversionTimeBase
+@@ -635,7 +635,7 @@ void v_APCI3XXX_Interrupt(int irq, void *d)
+ 				b_CopyCpt < devpriv->ui_AiNbrofChannels;
+ 				b_CopyCpt++) {
+ 				devpriv->ui_AiReadData[b_CopyCpt] =
+-					(UINT) readl((void *)(devpriv->
++					(unsigned int) readl((void *)(devpriv->
+ 						dw_AiBase + 28));
+ 			}
+ 

commit 74b894e56abcb2403894b268100773f4aabe1999
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:05:03 2009 -0400
+
+    Staging: comedi: Remove INT and *PINT typedefs in addi-data
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+index 1dd195d55167..99042017f268 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+@@ -32,7 +32,7 @@
+ |                                unsigned char_   b_InputClockLevel,                  |
+ |                                unsigned char_   b_OutputLevel,                      |
+ |                                unsigned char_   b_HardwareGateLevel)
+-INT i_InsnConfig_InitTimer(struct comedi_device *dev,struct comedi_subdevice *s,
++int i_InsnConfig_InitTimer(struct comedi_device *dev,struct comedi_subdevice *s,
+ 	struct comedi_insn *insn,unsigned int *data)
+ |
+ +----------------------------------------------------------------------------+
+@@ -219,11 +219,11 @@ INT i_InsnConfig_InitTimer(struct comedi_device *dev,struct comedi_subdevice *s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, struct comedi_subdevice * s,
+ 				   struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_TimerNbr;
+ 	unsigned char b_TimerMode;
+@@ -406,7 +406,7 @@ INT i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, struct comedi_sub
+ |                                unsigned char_ b_ModulNbr,                           |
+ |                                unsigned char_ b_TimerNbr,                           |
+ |                                unsigned char_ b_InterruptEnable)
+-INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,struct comedi_subdevice *s,
++int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,struct comedi_subdevice *s,
+ 	struct comedi_insn *insn,unsigned int *data)                |
+ +----------------------------------------------------------------------------+
+ | Task              : Enable OR Disable the Timer (b_TimerNbr) from selected module     |
+@@ -448,11 +448,11 @@ i_ReturnValue=insn->n;
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device * dev,
++int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device * dev,
+ 					   struct comedi_subdevice * s,
+ 					   struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_DummyRead;
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_TimerNbr;
+@@ -561,7 +561,7 @@ INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device * dev,
+ |                                       (unsigned char_     b_BoardHandle,            |
+ |                                        unsigned char_     b_ModulNbr,               |
+ |                                        PULONG_ pul_TimerValueArray)
+-INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev,struct comedi_subdevice *s,
++int i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev,struct comedi_subdevice *s,
+ 	struct comedi_insn *insn,unsigned int *data)        |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the all timer values from selected timer        |
+@@ -590,10 +590,10 @@ INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev,struct comedi_sub
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				     struct comedi_insn *insn, unsigned int *data)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	unsigned char b_ModulNbr, b_ReadType;
+ 	PULONG pul_TimerValueArray;
+ 
+@@ -681,11 +681,11 @@ struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnBitsTimer(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1710_InsnBitsTimer(struct comedi_device * dev, struct comedi_subdevice * s,
+ 			     struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned char b_BitsType;
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	b_BitsType = data[0];
+ 
+ 	printk("\n82X54");
+@@ -760,11 +760,11 @@ INT i_APCI1710_InsnBitsTimer(struct comedi_device * dev, struct comedi_subdevice
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_ReadTimerValue(struct comedi_device * dev,
++int i_APCI1710_ReadTimerValue(struct comedi_device * dev,
+ 			      unsigned char b_ModulNbr, unsigned char b_TimerNbr,
+ 			      PULONG pul_TimerValue)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 
+ 	/* Test the module number */
+ 	if (b_ModulNbr < 4) {
+@@ -848,11 +848,11 @@ INT i_APCI1710_ReadTimerValue(struct comedi_device * dev,
+ 	   +----------------------------------------------------------------------------+
+ 	 */
+ 
+-INT i_APCI1710_GetTimerOutputLevel(struct comedi_device * dev,
++int i_APCI1710_GetTimerOutputLevel(struct comedi_device * dev,
+ 				   unsigned char b_ModulNbr, unsigned char b_TimerNbr,
+ 				   unsigned char * pb_OutputLevel)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_TimerStatus;
+ 
+ 	/* Test the module number */
+@@ -927,11 +927,11 @@ INT i_APCI1710_GetTimerOutputLevel(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
++int i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
+ 				      unsigned char b_ModulNbr, unsigned char b_TimerNbr,
+ 				      unsigned char * pb_TimerStatus)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_TimerStatus;
+ 
+ 	/* Test the module number */
+@@ -1006,11 +1006,11 @@ INT i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_WriteTimerValue(struct comedi_device * dev,
++int i_APCI1710_WriteTimerValue(struct comedi_device * dev,
+ 			       unsigned char b_ModulNbr, unsigned char b_TimerNbr,
+ 			       ULONG ul_WriteValue)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 
+ 	/* Test the module number */
+ 	if (b_ModulNbr < 4) {
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
+index e8dd4968c036..928da64482dc 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
+@@ -34,40 +34,40 @@
+ /*
+  * 82X54 TIMER INISIALISATION FUNCTION
+  */
+-INT i_APCI1710_InsnConfigInitTimer(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1710_InsnConfigInitTimer(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   struct comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,
++int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,
+ 					   struct comedi_subdevice *s,
+ 					   struct comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * 82X54 READ FUNCTION
+  */
+-INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				     struct comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_InsnBitsTimer(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1710_InsnBitsTimer(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			     struct comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * 82X54 READ & WRITE FUNCTION
+  */
+-INT i_APCI1710_ReadTimerValue(struct comedi_device *dev,
++int i_APCI1710_ReadTimerValue(struct comedi_device *dev,
+ 			      unsigned char b_ModulNbr, unsigned char b_TimerNbr,
+ 			      PULONG pul_TimerValue);
+ 
+-INT i_APCI1710_GetTimerOutputLevel(struct comedi_device *dev,
++int i_APCI1710_GetTimerOutputLevel(struct comedi_device *dev,
+ 				   unsigned char b_ModulNbr, unsigned char b_TimerNbr,
+ 				   unsigned char * pb_OutputLevel);
+ 
+-INT i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
++int i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
+ 				      unsigned char b_ModulNbr, unsigned char b_TimerNbr,
+ 				      unsigned char * pb_TimerStatus);
+ 
+ /*
+  * 82X54 WRITE FUNCTION
+  */
+-INT i_APCI1710_WriteTimerValue(struct comedi_device *dev,
++int i_APCI1710_WriteTimerValue(struct comedi_device *dev,
+ 			       unsigned char b_ModulNbr, unsigned char b_TimerNbr,
+ 			       ULONG ul_WriteValue);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+index f8d5914dcdea..70b01db2d3bb 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+@@ -131,10 +131,10 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	ULONG ul_TimerValue = 0;
+ 	ULONG ul_TimingInterval = 0;
+ 	ULONG ul_RealTimingInterval = 0;
+@@ -790,7 +790,7 @@ INT i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_su
+ |                                                unsigned char_ b_ModulNbr,           |
+ |                                                unsigned char_ b_CycleMode,          |
+ |                                                unsigned char_ b_InterruptEnable)
+-INT i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
++int i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
+ struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)						 |
+ +----------------------------------------------------------------------------+
+ | Task              : Enable the chronometer from selected module            |
+@@ -840,10 +840,10 @@ struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)						 |
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device * dev,
++int i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	unsigned char b_ModulNbr, b_CycleMode, b_InterruptEnable, b_Action;
+ 	b_ModulNbr = CR_AREF(insn->chanspec);
+ 	b_Action = (unsigned char) data[0];
+@@ -1090,11 +1090,11 @@ struct comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnReadChrono(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1710_InsnReadChrono(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned char b_ReadType;
+-	INT i_ReturnValue = insn->n;
++	int i_ReturnValue = insn->n;
+ 
+ 	b_ReadType = CR_CHAN(insn->chanspec);
+ 
+@@ -1194,10 +1194,10 @@ INT i_APCI1710_InsnReadChrono(struct comedi_device * dev, struct comedi_subdevic
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_GetChronoProgressStatus(struct comedi_device * dev,
++int i_APCI1710_GetChronoProgressStatus(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char * pb_ChronoStatus)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_Status;
+ 
+ 	/**************************/
+@@ -1355,11 +1355,11 @@ INT i_APCI1710_GetChronoProgressStatus(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_ReadChronoValue(struct comedi_device * dev,
++int i_APCI1710_ReadChronoValue(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr,
+ 	UINT ui_TimeOut, unsigned char * pb_ChronoStatus, PULONG pul_ChronoValue)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_Status;
+ 	DWORD dw_TimeOut = 0;
+ 
+@@ -1619,7 +1619,7 @@ INT i_APCI1710_ReadChronoValue(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
++int i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr,
+ 	ULONG ul_ChronoValue,
+ 	PULONG pul_Hour,
+@@ -1627,7 +1627,7 @@ INT i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
+ 	unsigned char * pb_Second,
+ 	PUINT pui_MilliSecond, PUINT pui_MicroSecond, PUINT pui_NanoSecond)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	double d_Hour;
+ 	double d_Minute;
+ 	double d_Second;
+@@ -1757,7 +1757,7 @@ INT i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     : INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,struct comedi_subdevice *s,
++| Function Name     : int i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,struct comedi_subdevice *s,
+ 	struct comedi_insn *insn,unsigned int *data)                    |
+ +----------------------------------------------------------------------------+
+ | Task              : Sets the output witch has been passed with the         |
+@@ -1876,10 +1876,10 @@ INT i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device * dev,
++int i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	unsigned char b_ModulNbr, b_OutputChannel, b_InputChannel, b_IOType;
+ 	DWORD dw_Status;
+ 	unsigned char * pb_ChannelStatus;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
+index 31f76d51b4a3..1c0bfe1c4004 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
+@@ -35,10 +35,10 @@
+ /*
+  * CHRONOMETER INISIALISATION FUNCTION
+  */
+-INT i_APCI1710_InsnConfigInitChrono(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1710_InsnConfigInitChrono(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				    struct comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
++int i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
+ 					    struct comedi_subdevice *s,
+ 					    struct comedi_insn *insn,
+ 					    unsigned int *data);
+@@ -46,18 +46,18 @@ INT i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
+ /*
+  * CHRONOMETER READ FUNCTION
+  */
+-INT i_APCI1710_InsnReadChrono(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1710_InsnReadChrono(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			      struct comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_GetChronoProgressStatus(struct comedi_device *dev,
++int i_APCI1710_GetChronoProgressStatus(struct comedi_device *dev,
+ 				       unsigned char b_ModulNbr, unsigned char * pb_ChronoStatus);
+ 
+-INT i_APCI1710_ReadChronoValue(struct comedi_device *dev,
++int i_APCI1710_ReadChronoValue(struct comedi_device *dev,
+ 			       unsigned char b_ModulNbr,
+ 			       UINT ui_TimeOut, unsigned char * pb_ChronoStatus,
+ 			       PULONG pul_ChronoValue);
+ 
+-INT i_APCI1710_ConvertChronoValue(struct comedi_device *dev,
++int i_APCI1710_ConvertChronoValue(struct comedi_device *dev,
+ 				  unsigned char b_ModulNbr,
+ 				  ULONG ul_ChronoValue,
+ 				  PULONG pul_Hour,
+@@ -69,6 +69,6 @@ INT i_APCI1710_ConvertChronoValue(struct comedi_device *dev,
+ /*
+  * CHRONOMETER DIGITAL INPUT OUTPUT FUNCTION
+  */
+-INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,
++int i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,
+ 				       struct comedi_subdevice *s, struct comedi_insn *insn,
+ 				       unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+index 37af24259876..1e0e0b394ce5 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+@@ -61,7 +61,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     : INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device *dev, |
++| Function Name     : int i_APCI1710_InsnConfigDigitalIO(struct comedi_device *dev, |
+ |						struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)|
+ +----------------------------------------------------------------------------+
+ | Task              : Configure the digital I/O operating mode from selected |
+@@ -99,12 +99,12 @@ Activates and deactivates the digital output memory.
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1710_InsnConfigDigitalIO(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned char b_ModulNbr, b_ChannelAMode, b_ChannelBMode;
+ 	unsigned char b_MemoryOnOff, b_ConfigType;
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_WriteConfig = 0;
+ 
+ 	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+@@ -293,10 +293,10 @@ INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device * dev, struct comedi_sub
+ //                                             unsigned char_    b_InputChannel,
+ //
+ //                                             unsigned char *_  pb_ChannelStatus)
+-INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device * dev,
++int i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_StatusReg;
+ 	unsigned char b_ModulNbr, b_InputChannel;
+ 	unsigned char * pb_ChannelStatus;
+@@ -445,7 +445,7 @@ INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     : INT i_APCI1710_InsnWriteDigitalIOChlOnOff(comedi_device
++| Function Name     : int i_APCI1710_InsnWriteDigitalIOChlOnOff(comedi_device
+ |*dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)
+ 
+ +----------------------------------------------------------------------------+
+@@ -481,10 +481,10 @@ INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device * dev,
+ //_INT_   i_APCI1710_SetDigitalIOChlOn    (unsigned char_ b_BoardHandle,
+ //                                       unsigned char_ b_ModulNbr,
+ //                                       unsigned char_ b_OutputChannel)
+-INT i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device * dev,
++int i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_WriteValue = 0;
+ 	unsigned char b_ModulNbr, b_OutputChannel;
+ 	i_ReturnValue = insn->n;
+@@ -728,10 +728,10 @@ INT i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device * dev,
+ //_INT_   i_APCI1710_SetDigitalIOPortOn   (unsigned char_ b_BoardHandle,
+ //                                       unsigned char_ b_ModulNbr,
+ //                                       unsigned char_ b_PortValue)
+-INT i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device * dev,
++int i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_WriteValue = 0;
+ 	DWORD dw_StatusReg;
+ 	unsigned char b_ModulNbr, b_PortValue;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h
+index 5ef157a55ca1..af1b9cdecfb3 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h
+@@ -27,20 +27,20 @@
+ /*
+  * DIGITAL I/O INISIALISATION FUNCTION
+  */
+-INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1710_InsnConfigDigitalIO(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   struct comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * INPUT OUTPUT  FUNCTIONS
+  */
+-INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device *dev,
++int i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device *dev,
+ 					 struct comedi_subdevice *s,
+ 					 struct comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device *dev,
++int i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device *dev,
+ 					  struct comedi_subdevice *s,
+ 					  struct comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device *dev,
++int i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device *dev,
+ 					  struct comedi_subdevice *s,
+ 					  struct comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+index cad8ac960f7b..f5abd1cecd95 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+@@ -61,7 +61,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| INT	i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev,struct comedi_subdevice *s,
++| int	i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev,struct comedi_subdevice *s,
+ struct comedi_insn *insn,unsigned int *data)
+ 
+ +----------------------------------------------------------------------------+
+@@ -75,11 +75,11 @@ struct comedi_insn *insn,unsigned int *data)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnConfigINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1710_InsnConfigINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_ConfigType;
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	ui_ConfigType = CR_CHAN(insn->chanspec);
+ 
+ 	printk("\nINC_CPT");
+@@ -299,14 +299,14 @@ INT i_APCI1710_InsnConfigINCCPT(struct comedi_device * dev, struct comedi_subdev
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InitCounter(struct comedi_device * dev,
++int i_APCI1710_InitCounter(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr,
+ 	unsigned char b_CounterRange,
+ 	unsigned char b_FirstCounterModus,
+ 	unsigned char b_FirstCounterOption,
+ 	unsigned char b_SecondCounterModus, unsigned char b_SecondCounterOption)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 
+ 	/*******************************/
+ 	/* Test if incremental counter */
+@@ -545,10 +545,10 @@ INT i_APCI1710_InitCounter(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_CounterAutoTest(struct comedi_device * dev, unsigned char * pb_TestStatus)
++int i_APCI1710_CounterAutoTest(struct comedi_device * dev, unsigned char * pb_TestStatus)
+ {
+ 	unsigned char b_ModulCpt = 0;
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_LathchValue;
+ 
+ 	*pb_TestStatus = 0;
+@@ -708,12 +708,12 @@ INT i_APCI1710_CounterAutoTest(struct comedi_device * dev, unsigned char * pb_Te
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InitIndex(struct comedi_device * dev,
++int i_APCI1710_InitIndex(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr,
+ 	unsigned char b_ReferenceAction,
+ 	unsigned char b_IndexOperation, unsigned char b_AutoMode, unsigned char b_InterruptEnable)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -1152,10 +1152,10 @@ INT i_APCI1710_InitIndex(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InitReference(struct comedi_device * dev,
++int i_APCI1710_InitReference(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char b_ReferenceLevel)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -1277,10 +1277,10 @@ INT i_APCI1710_InitReference(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InitExternalStrobe(struct comedi_device * dev,
++int i_APCI1710_InitExternalStrobe(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char b_ExternalStrobe, unsigned char b_ExternalStrobeLevel)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -1391,10 +1391,10 @@ INT i_APCI1710_InitExternalStrobe(struct comedi_device * dev,
+ 	   +----------------------------------------------------------------------------+
+ 	 */
+ 
+-INT i_APCI1710_InitCompareLogic(struct comedi_device * dev,
++int i_APCI1710_InitCompareLogic(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, UINT ui_CompareValue)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -1487,13 +1487,13 @@ INT i_APCI1710_InitCompareLogic(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InitFrequencyMeasurement(struct comedi_device * dev,
++int i_APCI1710_InitFrequencyMeasurement(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr,
+ 	unsigned char b_PCIInputClock,
+ 	unsigned char b_TimingUnity,
+ 	ULONG ul_TimingInterval, PULONG pul_RealTimingInterval)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	ULONG ul_TimerValue = 0;
+ 	double d_RealTimingInterval;
+ 	DWORD dw_Status = 0;
+@@ -2015,11 +2015,11 @@ struct comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnBitsINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1710_InsnBitsINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_BitsType;
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	ui_BitsType = CR_CHAN(insn->chanspec);
+ 	devpriv->tsk_Current = current;	// Save the current process task structure
+ 
+@@ -2091,9 +2091,9 @@ INT i_APCI1710_InsnBitsINCCPT(struct comedi_device * dev, struct comedi_subdevic
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_ClearCounterValue(struct comedi_device * dev, unsigned char b_ModulNbr)
++int i_APCI1710_ClearCounterValue(struct comedi_device * dev, unsigned char b_ModulNbr)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -2151,10 +2151,10 @@ INT i_APCI1710_ClearCounterValue(struct comedi_device * dev, unsigned char b_Mod
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_ClearAllCounterValue(struct comedi_device * dev)
++int i_APCI1710_ClearAllCounterValue(struct comedi_device * dev)
+ {
+ 	unsigned char b_ModulCpt = 0;
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 
+ 	/********************************/
+ 	/* Test if counter module found */
+@@ -2297,10 +2297,10 @@ INT i_APCI1710_ClearAllCounterValue(struct comedi_device * dev)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_SetInputFilter(struct comedi_device * dev,
++int i_APCI1710_SetInputFilter(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char b_PCIInputClock, unsigned char b_Filter)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_Status = 0;
+ 
+ 	/**************************/
+@@ -2561,10 +2561,10 @@ INT i_APCI1710_SetInputFilter(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_LatchCounter(struct comedi_device * dev,
++int i_APCI1710_LatchCounter(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char b_LatchReg)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -2658,10 +2658,10 @@ INT i_APCI1710_LatchCounter(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_SetIndexAndReferenceSource(struct comedi_device * dev,
++int i_APCI1710_SetIndexAndReferenceSource(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char b_SourceSelection)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -2795,9 +2795,9 @@ INT i_APCI1710_SetIndexAndReferenceSource(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_SetDigitalChlOn(struct comedi_device * dev, unsigned char b_ModulNbr)
++int i_APCI1710_SetDigitalChlOn(struct comedi_device * dev, unsigned char b_ModulNbr)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -2875,9 +2875,9 @@ INT i_APCI1710_SetDigitalChlOn(struct comedi_device * dev, unsigned char b_Modul
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_SetDigitalChlOff(struct comedi_device * dev, unsigned char b_ModulNbr)
++int i_APCI1710_SetDigitalChlOff(struct comedi_device * dev, unsigned char b_ModulNbr)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -2951,11 +2951,11 @@ struct comedi_insn *insn,unsigned int *data)                   |
+ | Return Value      :
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1710_InsnWriteINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1710_InsnWriteINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_WriteType;
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 
+ 	ui_WriteType = CR_CHAN(insn->chanspec);
+ 	devpriv->tsk_Current = current;	// Save the current process task structure
+@@ -3047,9 +3047,9 @@ INT i_APCI1710_InsnWriteINCCPT(struct comedi_device * dev, struct comedi_subdevi
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_EnableLatchInterrupt(struct comedi_device * dev, unsigned char b_ModulNbr)
++int i_APCI1710_EnableLatchInterrupt(struct comedi_device * dev, unsigned char b_ModulNbr)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -3133,9 +3133,9 @@ INT i_APCI1710_EnableLatchInterrupt(struct comedi_device * dev, unsigned char b_
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_DisableLatchInterrupt(struct comedi_device * dev, unsigned char b_ModulNbr)
++int i_APCI1710_DisableLatchInterrupt(struct comedi_device * dev, unsigned char b_ModulNbr)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -3231,10 +3231,10 @@ INT i_APCI1710_DisableLatchInterrupt(struct comedi_device * dev, unsigned char b
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_Write16BitCounterValue(struct comedi_device * dev,
++int i_APCI1710_Write16BitCounterValue(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char b_SelectedCounter, UINT ui_WriteValue)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -3316,10 +3316,10 @@ INT i_APCI1710_Write16BitCounterValue(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_Write32BitCounterValue(struct comedi_device * dev,
++int i_APCI1710_Write32BitCounterValue(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, ULONG ul_WriteValue)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -3383,9 +3383,9 @@ INT i_APCI1710_Write32BitCounterValue(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_EnableIndex(struct comedi_device * dev, unsigned char b_ModulNbr)
++int i_APCI1710_EnableIndex(struct comedi_device * dev, unsigned char b_ModulNbr)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	ULONG ul_InterruptLatchReg;
+ 
+ 	/**************************/
+@@ -3481,9 +3481,9 @@ INT i_APCI1710_EnableIndex(struct comedi_device * dev, unsigned char b_ModulNbr)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_DisableIndex(struct comedi_device * dev, unsigned char b_ModulNbr)
++int i_APCI1710_DisableIndex(struct comedi_device * dev, unsigned char b_ModulNbr)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -3580,9 +3580,9 @@ INT i_APCI1710_DisableIndex(struct comedi_device * dev, unsigned char b_ModulNbr
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_EnableCompareLogic(struct comedi_device * dev, unsigned char b_ModulNbr)
++int i_APCI1710_EnableCompareLogic(struct comedi_device * dev, unsigned char b_ModulNbr)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -3680,9 +3680,9 @@ INT i_APCI1710_EnableCompareLogic(struct comedi_device * dev, unsigned char b_Mo
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_DisableCompareLogic(struct comedi_device * dev, unsigned char b_ModulNbr)
++int i_APCI1710_DisableCompareLogic(struct comedi_device * dev, unsigned char b_ModulNbr)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -3789,10 +3789,10 @@ INT i_APCI1710_DisableCompareLogic(struct comedi_device * dev, unsigned char b_M
+ 	   +----------------------------------------------------------------------------+
+ 	 */
+ 
+-INT i_APCI1710_EnableFrequencyMeasurement(struct comedi_device * dev,
++int i_APCI1710_EnableFrequencyMeasurement(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char b_InterruptEnable)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -3936,9 +3936,9 @@ INT i_APCI1710_EnableFrequencyMeasurement(struct comedi_device * dev,
+ 	   +----------------------------------------------------------------------------+
+ 	 */
+ 
+-INT i_APCI1710_DisableFrequencyMeasurement(struct comedi_device * dev, unsigned char b_ModulNbr)
++int i_APCI1710_DisableFrequencyMeasurement(struct comedi_device * dev, unsigned char b_ModulNbr)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -4049,11 +4049,11 @@ struct comedi_insn *insn,unsigned int *data)                   |
+ | Return Value      :
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1710_InsnReadINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1710_InsnReadINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_ReadType;
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 
+ 	ui_ReadType = CR_CHAN(insn->chanspec);
+ 
+@@ -4193,10 +4193,10 @@ INT i_APCI1710_InsnReadINCCPT(struct comedi_device * dev, struct comedi_subdevic
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_ReadLatchRegisterStatus(struct comedi_device * dev,
++int i_APCI1710_ReadLatchRegisterStatus(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char b_LatchReg, unsigned char * pb_LatchStatus)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_LatchReg;
+ 
+ 	/**************************/
+@@ -4280,10 +4280,10 @@ INT i_APCI1710_ReadLatchRegisterStatus(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_ReadLatchRegisterValue(struct comedi_device * dev,
++int i_APCI1710_ReadLatchRegisterValue(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char b_LatchReg, PULONG pul_LatchValue)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -4364,10 +4364,10 @@ INT i_APCI1710_ReadLatchRegisterValue(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_Read16BitCounterValue(struct comedi_device * dev,
++int i_APCI1710_Read16BitCounterValue(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char b_SelectedCounter, PUINT pui_CounterValue)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_LathchValue = 0;
+ 
+ 	/**************************/
+@@ -4459,10 +4459,10 @@ INT i_APCI1710_Read16BitCounterValue(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_Read32BitCounterValue(struct comedi_device * dev,
++int i_APCI1710_Read32BitCounterValue(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, PULONG pul_CounterValue)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -4535,10 +4535,10 @@ INT i_APCI1710_Read32BitCounterValue(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_GetIndexStatus(struct comedi_device * dev,
++int i_APCI1710_GetIndexStatus(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char * pb_IndexStatus)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_StatusReg = 0;
+ 
+ 	/**************************/
+@@ -4619,10 +4619,10 @@ INT i_APCI1710_GetIndexStatus(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_GetReferenceStatus(struct comedi_device * dev,
++int i_APCI1710_GetReferenceStatus(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char * pb_ReferenceStatus)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_StatusReg = 0;
+ 
+ 	/**************************/
+@@ -4703,10 +4703,10 @@ INT i_APCI1710_GetReferenceStatus(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_GetUASStatus(struct comedi_device * dev,
++int i_APCI1710_GetUASStatus(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char * pb_UASStatus)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_StatusReg = 0;
+ 
+ 	/**************************/
+@@ -4771,10 +4771,10 @@ INT i_APCI1710_GetUASStatus(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_GetCBStatus(struct comedi_device * dev,
++int i_APCI1710_GetCBStatus(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char * pb_CBStatus)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_StatusReg = 0;
+ 
+ 	/**************************/
+@@ -4853,10 +4853,10 @@ INT i_APCI1710_GetCBStatus(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_Get16BitCBStatus(struct comedi_device * dev,
++int i_APCI1710_Get16BitCBStatus(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char * pb_CBStatusCounter0, unsigned char * pb_CBStatusCounter1)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_StatusReg = 0;
+ 
+ 	/**************************/
+@@ -4966,10 +4966,10 @@ INT i_APCI1710_Get16BitCBStatus(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_GetUDStatus(struct comedi_device * dev,
++int i_APCI1710_GetUDStatus(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char * pb_UDStatus)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_StatusReg = 0;
+ 
+ 	/**************************/
+@@ -5040,10 +5040,10 @@ INT i_APCI1710_GetUDStatus(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device * dev,
++int i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr, unsigned char * pb_UDStatus)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_StatusReg = 0;
+ 
+ 	/**************************/
+@@ -5145,11 +5145,11 @@ INT i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device * dev,
+ 	   +----------------------------------------------------------------------------+
+ 	 */
+ 
+-INT i_APCI1710_ReadFrequencyMeasurement(struct comedi_device * dev,
++int i_APCI1710_ReadFrequencyMeasurement(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr,
+ 	unsigned char * pb_Status, unsigned char * pb_UDStatus, PULONG pul_ReadValue)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	UINT ui_16BitValue;
+ 	DWORD dw_StatusReg;
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
+index 62719b240b3c..03cd1afee10e 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
+@@ -132,22 +132,22 @@
+ #define APCI1710_INCCPT_DISABLEFREQUENCYMEASUREMENT		409
+ 
+ /************ Main Functions *************/
+-INT i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				struct comedi_insn *insn, unsigned int * data);
+ 
+-INT i_APCI1710_InsnBitsINCCPT(struct comedi_device *dev, struct comedi_subdevice * s,
++int i_APCI1710_InsnBitsINCCPT(struct comedi_device *dev, struct comedi_subdevice * s,
+ 			      struct comedi_insn *insn, unsigned int * data);
+ 
+-INT i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev, struct comedi_subdevice * s,
++int i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev, struct comedi_subdevice * s,
+ 			       struct comedi_insn *insn, unsigned int * data);
+ 
+-INT i_APCI1710_InsnReadINCCPT(struct comedi_device *dev, struct comedi_subdevice * s,
++int i_APCI1710_InsnReadINCCPT(struct comedi_device *dev, struct comedi_subdevice * s,
+ 			      struct comedi_insn *insn, unsigned int * data);
+ 
+ /*********** Supplementary Functions********/
+ 
+ /* INSN CONFIG */
+-INT i_APCI1710_InitCounter(struct comedi_device *dev,
++int i_APCI1710_InitCounter(struct comedi_device *dev,
+ 			   unsigned char b_ModulNbr,
+ 			   unsigned char b_CounterRange,
+ 			   unsigned char b_FirstCounterModus,
+@@ -155,25 +155,25 @@ INT i_APCI1710_InitCounter(struct comedi_device *dev,
+ 			   unsigned char b_SecondCounterModus,
+ 			   unsigned char b_SecondCounterOption);
+ 
+-INT i_APCI1710_CounterAutoTest(struct comedi_device *dev, unsigned char * pb_TestStatus);
++int i_APCI1710_CounterAutoTest(struct comedi_device *dev, unsigned char * pb_TestStatus);
+ 
+-INT i_APCI1710_InitIndex(struct comedi_device *dev,
++int i_APCI1710_InitIndex(struct comedi_device *dev,
+ 			 unsigned char b_ModulNbr,
+ 			 unsigned char b_ReferenceAction,
+ 			 unsigned char b_IndexOperation, unsigned char b_AutoMode,
+ 			 unsigned char b_InterruptEnable);
+ 
+-INT i_APCI1710_InitReference(struct comedi_device *dev,
++int i_APCI1710_InitReference(struct comedi_device *dev,
+ 			     unsigned char b_ModulNbr, unsigned char b_ReferenceLevel);
+ 
+-INT i_APCI1710_InitExternalStrobe(struct comedi_device *dev,
++int i_APCI1710_InitExternalStrobe(struct comedi_device *dev,
+ 				  unsigned char b_ModulNbr, unsigned char b_ExternalStrobe,
+ 				  unsigned char b_ExternalStrobeLevel);
+ 
+-INT i_APCI1710_InitCompareLogic(struct comedi_device *dev,
++int i_APCI1710_InitCompareLogic(struct comedi_device *dev,
+ 				unsigned char b_ModulNbr, UINT ui_CompareValue);
+ 
+-INT i_APCI1710_InitFrequencyMeasurement(struct comedi_device *dev,
++int i_APCI1710_InitFrequencyMeasurement(struct comedi_device *dev,
+ 					unsigned char b_ModulNbr,
+ 					unsigned char b_PCIInputClock,
+ 					unsigned char b_TimingUnity,
+@@ -181,91 +181,91 @@ INT i_APCI1710_InitFrequencyMeasurement(struct comedi_device *dev,
+ 					PULONG pul_RealTimingInterval);
+ 
+ /* INSN BITS */
+-INT i_APCI1710_ClearCounterValue(struct comedi_device *dev, unsigned char b_ModulNbr);
++int i_APCI1710_ClearCounterValue(struct comedi_device *dev, unsigned char b_ModulNbr);
+ 
+-INT i_APCI1710_ClearAllCounterValue(struct comedi_device *dev);
++int i_APCI1710_ClearAllCounterValue(struct comedi_device *dev);
+ 
+-INT i_APCI1710_SetInputFilter(struct comedi_device *dev,
++int i_APCI1710_SetInputFilter(struct comedi_device *dev,
+ 			      unsigned char b_ModulNbr, unsigned char b_PCIInputClock,
+ 			      unsigned char b_Filter);
+ 
+-INT i_APCI1710_LatchCounter(struct comedi_device *dev,
++int i_APCI1710_LatchCounter(struct comedi_device *dev,
+ 			    unsigned char b_ModulNbr, unsigned char b_LatchReg);
+ 
+-INT i_APCI1710_SetIndexAndReferenceSource(struct comedi_device *dev,
++int i_APCI1710_SetIndexAndReferenceSource(struct comedi_device *dev,
+ 					  unsigned char b_ModulNbr,
+ 					  unsigned char b_SourceSelection);
+ 
+-INT i_APCI1710_SetDigitalChlOn(struct comedi_device *dev, unsigned char b_ModulNbr);
++int i_APCI1710_SetDigitalChlOn(struct comedi_device *dev, unsigned char b_ModulNbr);
+ 
+-INT i_APCI1710_SetDigitalChlOff(struct comedi_device *dev, unsigned char b_ModulNbr);
++int i_APCI1710_SetDigitalChlOff(struct comedi_device *dev, unsigned char b_ModulNbr);
+ 
+ /* INSN WRITE */
+-INT i_APCI1710_EnableLatchInterrupt(struct comedi_device *dev, unsigned char b_ModulNbr);
++int i_APCI1710_EnableLatchInterrupt(struct comedi_device *dev, unsigned char b_ModulNbr);
+ 
+-INT i_APCI1710_DisableLatchInterrupt(struct comedi_device *dev, unsigned char b_ModulNbr);
++int i_APCI1710_DisableLatchInterrupt(struct comedi_device *dev, unsigned char b_ModulNbr);
+ 
+-INT i_APCI1710_Write16BitCounterValue(struct comedi_device *dev,
++int i_APCI1710_Write16BitCounterValue(struct comedi_device *dev,
+ 				      unsigned char b_ModulNbr, unsigned char b_SelectedCounter,
+ 				      UINT ui_WriteValue);
+ 
+-INT i_APCI1710_Write32BitCounterValue(struct comedi_device *dev,
++int i_APCI1710_Write32BitCounterValue(struct comedi_device *dev,
+ 				      unsigned char b_ModulNbr, ULONG ul_WriteValue);
+ 
+-INT i_APCI1710_EnableIndex(struct comedi_device *dev, unsigned char b_ModulNbr);
++int i_APCI1710_EnableIndex(struct comedi_device *dev, unsigned char b_ModulNbr);
+ 
+-INT i_APCI1710_DisableIndex(struct comedi_device *dev, unsigned char b_ModulNbr);
++int i_APCI1710_DisableIndex(struct comedi_device *dev, unsigned char b_ModulNbr);
+ 
+-INT i_APCI1710_EnableCompareLogic(struct comedi_device *dev, unsigned char b_ModulNbr);
++int i_APCI1710_EnableCompareLogic(struct comedi_device *dev, unsigned char b_ModulNbr);
+ 
+-INT i_APCI1710_DisableCompareLogic(struct comedi_device *dev, unsigned char b_ModulNbr);
++int i_APCI1710_DisableCompareLogic(struct comedi_device *dev, unsigned char b_ModulNbr);
+ 
+-INT i_APCI1710_EnableFrequencyMeasurement(struct comedi_device *dev,
++int i_APCI1710_EnableFrequencyMeasurement(struct comedi_device *dev,
+ 					  unsigned char b_ModulNbr,
+ 					  unsigned char b_InterruptEnable);
+ 
+-INT i_APCI1710_DisableFrequencyMeasurement(struct comedi_device *dev,
++int i_APCI1710_DisableFrequencyMeasurement(struct comedi_device *dev,
+ 					   unsigned char b_ModulNbr);
+ 
+ /* INSN READ */
+-INT i_APCI1710_ReadLatchRegisterStatus(struct comedi_device *dev,
++int i_APCI1710_ReadLatchRegisterStatus(struct comedi_device *dev,
+ 				       unsigned char b_ModulNbr, unsigned char b_LatchReg,
+ 				       unsigned char * pb_LatchStatus);
+ 
+-INT i_APCI1710_ReadLatchRegisterValue(struct comedi_device *dev,
++int i_APCI1710_ReadLatchRegisterValue(struct comedi_device *dev,
+ 				      unsigned char b_ModulNbr, unsigned char b_LatchReg,
+ 				      PULONG pul_LatchValue);
+ 
+-INT i_APCI1710_Read16BitCounterValue(struct comedi_device *dev,
++int i_APCI1710_Read16BitCounterValue(struct comedi_device *dev,
+ 				     unsigned char b_ModulNbr, unsigned char b_SelectedCounter,
+ 				     PUINT pui_CounterValue);
+ 
+-INT i_APCI1710_Read32BitCounterValue(struct comedi_device *dev,
++int i_APCI1710_Read32BitCounterValue(struct comedi_device *dev,
+ 				     unsigned char b_ModulNbr, PULONG pul_CounterValue);
+ 
+-INT i_APCI1710_GetIndexStatus(struct comedi_device *dev,
++int i_APCI1710_GetIndexStatus(struct comedi_device *dev,
+ 			      unsigned char b_ModulNbr, unsigned char * pb_IndexStatus);
+ 
+-INT i_APCI1710_GetReferenceStatus(struct comedi_device *dev,
++int i_APCI1710_GetReferenceStatus(struct comedi_device *dev,
+ 				  unsigned char b_ModulNbr, unsigned char * pb_ReferenceStatus);
+ 
+-INT i_APCI1710_GetUASStatus(struct comedi_device *dev,
++int i_APCI1710_GetUASStatus(struct comedi_device *dev,
+ 			    unsigned char b_ModulNbr, unsigned char * pb_UASStatus);
+ 
+-INT i_APCI1710_GetCBStatus(struct comedi_device *dev,
++int i_APCI1710_GetCBStatus(struct comedi_device *dev,
+ 			   unsigned char b_ModulNbr, unsigned char * pb_CBStatus);
+ 
+-INT i_APCI1710_Get16BitCBStatus(struct comedi_device *dev,
++int i_APCI1710_Get16BitCBStatus(struct comedi_device *dev,
+ 				unsigned char b_ModulNbr, unsigned char * pb_CBStatusCounter0,
+ 				unsigned char * pb_CBStatusCounter1);
+ 
+-INT i_APCI1710_GetUDStatus(struct comedi_device *dev,
++int i_APCI1710_GetUDStatus(struct comedi_device *dev,
+ 			   unsigned char b_ModulNbr, unsigned char * pb_UDStatus);
+ 
+-INT i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device *dev,
++int i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device *dev,
+ 					   unsigned char b_ModulNbr, unsigned char * pb_UDStatus);
+ 
+-INT i_APCI1710_ReadFrequencyMeasurement(struct comedi_device *dev,
++int i_APCI1710_ReadFrequencyMeasurement(struct comedi_device *dev,
+ 					unsigned char b_ModulNbr,
+ 					unsigned char * pb_Status, unsigned char * pb_UDStatus,
+ 					PULONG pul_ReadValue);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+index 7364cf075917..1f9bdcd01dd3 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+@@ -123,10 +123,10 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device * dev,
++int i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_IntRegister;
+ 
+ 	unsigned char b_ModulNbr;
+@@ -414,10 +414,10 @@ INT i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device * dev,
++int i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_PulseEncoderNbr;
+ 	unsigned char b_CycleSelection;
+@@ -708,10 +708,10 @@ INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device * dev,
+ 
+ 						 unsigned char *_ pb_Status)
+ 						 */
+-INT i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device * dev,
++int i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_StatusRegister;
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_PulseEncoderNbr;
+@@ -834,7 +834,7 @@ INT i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device * dev,
+ 	return (i_ReturnValue);
+ }
+ 
+-INT i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device * dev,
++int i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h
+index 28252873e862..61a21cc94063 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h
+@@ -21,11 +21,11 @@
+ #define APCI1710_PULSEENCODER_READ	0
+ #define APCI1710_PULSEENCODER_WRITE	1
+ 
+-INT i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device *dev,
++int i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device *dev,
+ 					  struct comedi_subdevice *s,
+ 					  struct comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device *dev,
++int i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device *dev,
+ 						  struct comedi_subdevice *s,
+ 						  struct comedi_insn *insn,
+ 						  unsigned int *data);
+@@ -33,7 +33,7 @@ INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device *dev,
+ /*
+  * READ PULSE ENCODER FUNCTIONS
+  */
+-INT i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device *dev,
++int i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device *dev,
+ 					     struct comedi_subdevice *s,
+ 					     struct comedi_insn *insn,
+ 					     unsigned int *data);
+@@ -41,7 +41,7 @@ INT i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device *dev,
+ /*
+  * WRITE PULSE ENCODER FUNCTIONS
+  */
+-INT i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device *dev,
++int i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device *dev,
+ 					     struct comedi_subdevice *s,
+ 					     struct comedi_insn *insn,
+ 					     unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+index fffd0f2463d5..6f9a0d5aeb24 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+@@ -70,11 +70,11 @@ struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnConfigPWM(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1710_InsnConfigPWM(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned char b_ConfigType;
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	b_ConfigType = CR_CHAN(insn->chanspec);
+ 
+ 	switch (b_ConfigType) {
+@@ -179,7 +179,7 @@ INT i_APCI1710_InsnConfigPWM(struct comedi_device * dev, struct comedi_subdevice
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InitPWM(struct comedi_device * dev,
++int i_APCI1710_InitPWM(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr,
+ 	unsigned char b_PWM,
+ 	unsigned char b_ClockSelection,
+@@ -188,7 +188,7 @@ INT i_APCI1710_InitPWM(struct comedi_device * dev,
+ 	ULONG ul_HighTiming,
+ 	PULONG pul_RealLowTiming, PULONG pul_RealHighTiming)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	ULONG ul_LowTimerValue = 0;
+ 	ULONG ul_HighTimerValue = 0;
+ 	DWORD dw_Command;
+@@ -1534,7 +1534,7 @@ INT i_APCI1710_InitPWM(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_GetPWMInitialisation(struct comedi_device * dev,
++int i_APCI1710_GetPWMInitialisation(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr,
+ 	unsigned char b_PWM,
+ 	unsigned char * pb_TimingUnit,
+@@ -1545,7 +1545,7 @@ INT i_APCI1710_GetPWMInitialisation(struct comedi_device * dev,
+ 	unsigned char * pb_StopLevel,
+ 	unsigned char * pb_ExternGate, unsigned char * pb_InterruptEnable, unsigned char * pb_Enable)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_Status;
+ 	DWORD dw_Command;
+ 
+@@ -1683,11 +1683,11 @@ struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnWritePWM(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1710_InsnWritePWM(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned char b_WriteType;
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	b_WriteType = CR_CHAN(insn->chanspec);
+ 
+ 	switch (b_WriteType) {
+@@ -1806,14 +1806,14 @@ INT i_APCI1710_InsnWritePWM(struct comedi_device * dev, struct comedi_subdevice
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_EnablePWM(struct comedi_device * dev,
++int i_APCI1710_EnablePWM(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr,
+ 	unsigned char b_PWM,
+ 	unsigned char b_StartLevel,
+ 	unsigned char b_StopMode,
+ 	unsigned char b_StopLevel, unsigned char b_ExternGate, unsigned char b_InterruptEnable)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_Status;
+ 	DWORD dw_Command;
+ 
+@@ -2062,9 +2062,9 @@ INT i_APCI1710_EnablePWM(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_DisablePWM(struct comedi_device * dev, unsigned char b_ModulNbr, unsigned char b_PWM)
++int i_APCI1710_DisablePWM(struct comedi_device * dev, unsigned char b_ModulNbr, unsigned char b_PWM)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_Status;
+ 
+ 	/**************************/
+@@ -2189,12 +2189,12 @@ INT i_APCI1710_DisablePWM(struct comedi_device * dev, unsigned char b_ModulNbr,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
++int i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 	unsigned char b_ModulNbr,
+ 	unsigned char b_PWM, unsigned char b_TimingUnit, ULONG ul_LowTiming, ULONG ul_HighTiming)
+ {
+ 	unsigned char b_ClockSelection;
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	ULONG ul_LowTimerValue = 0;
+ 	ULONG ul_HighTimerValue = 0;
+ 	ULONG ul_RealLowTiming = 0;
+@@ -3460,10 +3460,10 @@ INT i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnReadGetPWMStatus(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1710_InsnReadGetPWMStatus(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_Status;
+ 
+ 	unsigned char b_ModulNbr;
+@@ -3561,7 +3561,7 @@ INT i_APCI1710_InsnReadGetPWMStatus(struct comedi_device * dev, struct comedi_su
+ 	return (i_ReturnValue);
+ }
+ 
+-INT i_APCI1710_InsnBitsReadPWMInterrupt(struct comedi_device * dev,
++int i_APCI1710_InsnBitsReadPWMInterrupt(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->s_InterruptParameters.
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
+index 8d8052d4b3f9..7f57fd433c66 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
+@@ -26,10 +26,10 @@
+ #define APCI1710_PWM_ENABLE		1
+ #define APCI1710_PWM_NEWTIMING		2
+ 
+-INT i_APCI1710_InsnConfigPWM(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1710_InsnConfigPWM(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			     struct comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_InitPWM(struct comedi_device *dev,
++int i_APCI1710_InitPWM(struct comedi_device *dev,
+ 		       unsigned char b_ModulNbr,
+ 		       unsigned char b_PWM,
+ 		       unsigned char b_ClockSelection,
+@@ -38,7 +38,7 @@ INT i_APCI1710_InitPWM(struct comedi_device *dev,
+ 		       ULONG ul_HighTiming,
+ 		       PULONG pul_RealLowTiming, PULONG pul_RealHighTiming);
+ 
+-INT i_APCI1710_GetPWMInitialisation(struct comedi_device *dev,
++int i_APCI1710_GetPWMInitialisation(struct comedi_device *dev,
+ 				    unsigned char b_ModulNbr,
+ 				    unsigned char b_PWM,
+ 				    unsigned char * pb_TimingUnit,
+@@ -50,10 +50,10 @@ INT i_APCI1710_GetPWMInitialisation(struct comedi_device *dev,
+ 				    unsigned char * pb_ExternGate,
+ 				    unsigned char * pb_InterruptEnable, unsigned char * pb_Enable);
+ 
+-INT i_APCI1710_InsnWritePWM(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1710_InsnWritePWM(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			    struct comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_EnablePWM(struct comedi_device *dev,
++int i_APCI1710_EnablePWM(struct comedi_device *dev,
+ 			 unsigned char b_ModulNbr,
+ 			 unsigned char b_PWM,
+ 			 unsigned char b_StartLevel,
+@@ -61,16 +61,16 @@ INT i_APCI1710_EnablePWM(struct comedi_device *dev,
+ 			 unsigned char b_StopLevel, unsigned char b_ExternGate,
+ 			 unsigned char b_InterruptEnable);
+ 
+-INT i_APCI1710_SetNewPWMTiming(struct comedi_device *dev,
++int i_APCI1710_SetNewPWMTiming(struct comedi_device *dev,
+ 			       unsigned char b_ModulNbr,
+ 			       unsigned char b_PWM, unsigned char b_TimingUnit,
+ 			       ULONG ul_LowTiming, ULONG ul_HighTiming);
+ 
+-INT i_APCI1710_DisablePWM(struct comedi_device *dev, unsigned char b_ModulNbr, unsigned char b_PWM);
++int i_APCI1710_DisablePWM(struct comedi_device *dev, unsigned char b_ModulNbr, unsigned char b_PWM);
+ 
+-INT i_APCI1710_InsnReadGetPWMStatus(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1710_InsnReadGetPWMStatus(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				    struct comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_InsnBitsReadPWMInterrupt(struct comedi_device *dev,
++int i_APCI1710_InsnBitsReadPWMInterrupt(struct comedi_device *dev,
+ 					struct comedi_subdevice *s,
+ 					struct comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+index 35153b142d81..3db614172571 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+@@ -133,10 +133,10 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnConfigInitSSI(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1710_InsnConfigInitSSI(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	UINT ui_TimerValue;
+ 	unsigned char b_ModulNbr, b_SSIProfile, b_PositionTurnLength, b_TurnCptLength,
+ 		b_PCIInputClock, b_SSICountingMode;
+@@ -362,7 +362,7 @@ INT i_APCI1710_InsnConfigInitSSI(struct comedi_device * dev, struct comedi_subde
+ |                                unsigned char_     b_SelectedSSI,                    |
+ |                                PULONG_ pul_Position,                       |
+ |                                PULONG_ pul_TurnCpt)
+- INT i_APCI1710_ReadSSIValue(struct comedi_device *dev,struct comedi_subdevice *s,
++ int i_APCI1710_ReadSSIValue(struct comedi_device *dev,struct comedi_subdevice *s,
+ 	struct comedi_insn *insn,unsigned int *data)                       |
+ +----------------------------------------------------------------------------+
+ | Task              :
+@@ -400,10 +400,10 @@ pul_Position	=	(PULONG) &data[0];
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnReadSSIValue(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1710_InsnReadSSIValue(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	unsigned char b_Cpt;
+ 	unsigned char b_Length;
+ 	unsigned char b_Schift;
+@@ -735,10 +735,10 @@ INT i_APCI1710_InsnReadSSIValue(struct comedi_device * dev, struct comedi_subdev
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_StatusReg;
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_InputChannel;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h
+index 88daad1a3912..eb7f101d2d61 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h
+@@ -33,11 +33,11 @@
+ /*
+  * SSI INISIALISATION FUNCTION
+  */
+-INT i_APCI1710_InsnConfigInitSSI(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1710_InsnConfigInitSSI(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 struct comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_InsnReadSSIValue(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1710_InsnReadSSIValue(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				struct comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				    struct comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+index c1b4f07beb17..2feaef431336 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+@@ -130,10 +130,10 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
++int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	ULONG ul_TimerValue = 0;
+ 	DWORD dw_Command;
+ 	double d_RealTimingInterval = 0;
+@@ -987,10 +987,10 @@ INT i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
++int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_Status;
+ 	DWORD dw_DummyRead;
+ 	DWORD dw_ConfigReg;
+@@ -1460,10 +1460,10 @@ INT i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
++int i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_Status;
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_TorCounter;
+@@ -1700,10 +1700,10 @@ INT i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device * dev,
++int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_Status;
+ 	DWORD dw_TimeOut = 0;
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h
+index c245d16207b8..03a93cb26d7a 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h
+@@ -35,23 +35,23 @@
+ /*
+  * TOR_COUNTER INISIALISATION FUNCTION
+  */
+-INT i_APCI1710_InsnConfigInitTorCounter(struct comedi_device *dev,
++int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device *dev,
+ 					struct comedi_subdevice *s,
+ 					struct comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device *dev,
++int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device *dev,
+ 						struct comedi_subdevice *s,
+ 						struct comedi_insn *insn,
+ 						unsigned int *data);
+ 
+-INT i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device *dev,
++int i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device *dev,
+ 						   struct comedi_subdevice *s,
+ 						   struct comedi_insn *insn,
+ 						   unsigned int *data);
+ /*
+  * TOR_COUNTER READ FUNCTION
+  */
+-INT i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device *dev,
++int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device *dev,
+ 							   struct comedi_subdevice *s,
+ 							   struct comedi_insn *insn,
+ 							   unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+index eb1551d0eca3..746fa529f82c 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+@@ -100,10 +100,10 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnConfigInitTTLIO(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1710_InsnConfigInitTTLIO(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_InitType;
+ 	unsigned char b_PortAMode;
+@@ -406,10 +406,10 @@ APCI1710_TTL_READCHANNEL
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1710_InsnBitsReadTTLIO(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_StatusReg;
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_SelectedPort;
+@@ -633,7 +633,7 @@ INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device * dev, struct comedi_subde
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     : INT i_APCI1710_InsnReadTTLIOAllPortValue(comedi_device
++| Function Name     : int i_APCI1710_InsnReadTTLIOAllPortValue(comedi_device
+ *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)              |
+ +----------------------------------------------------------------------------+
+ | Task              : Read the status from all digital input ports           |
+@@ -655,10 +655,10 @@ INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device * dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
++int i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_StatusReg;
+ 	unsigned char b_ModulNbr;
+ 	PULONG pul_PortValue;
+@@ -792,7 +792,7 @@ INT i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+ |                               (unsigned char_           b_BoardHandle,              |
+ |                                unsigned char_           b_ModulNbr,                 |
+ |                                unsigned char_           b_OutputChannel)
+-INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,struct comedi_subdevice *s,
++int i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,struct comedi_subdevice *s,
+ 	struct comedi_insn *insn,unsigned int *data)           |
+ +----------------------------------------------------------------------------+
+ | Task              : Sets or resets  the output witch has been passed with the         |
+@@ -825,10 +825,10 @@ INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,struct comedi
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device * dev,
++int i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = 0;
++	int i_ReturnValue = 0;
+ 	DWORD dw_StatusReg = 0;
+ 	unsigned char b_ModulNbr;
+ 	unsigned char b_OutputChannel;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h
+index 00915ddf9218..c4f11347f243 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h
+@@ -24,21 +24,21 @@
+ /*
+  * TTL INISIALISATION FUNCTION
+  */
+-INT i_APCI1710_InsnConfigInitTTLIO(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1710_InsnConfigInitTTLIO(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   struct comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * TTL INPUT FUNCTION
+  */
+-INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1710_InsnBitsReadTTLIO(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 struct comedi_insn *insn, unsigned int *data);
+-INT i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
++int i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
+ 					 struct comedi_subdevice *s,
+ 					 struct comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * TTL OUTPUT FUNCTIONS
+  */
+-INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,
++int i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,
+ 					 struct comedi_subdevice *s,
+ 					 struct comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
+index 3ea2f0756095..de49dca42e83 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
+@@ -49,15 +49,15 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ #include "addi_amcc_S5920.h"
+ 
+ /*+----------------------------------------------------------------------------+*/
+-/*| Function   Name   : INT i_AddiHeaderRW_ReadEeprom                          |*/
+-/*|                               (INT    i_NbOfWordsToRead,                   |*/
++/*| Function   Name   : int i_AddiHeaderRW_ReadEeprom                          |*/
++/*|                               (int    i_NbOfWordsToRead,                   |*/
+ /*|                                DWORD dw_PCIBoardEepromAddress,             |*/
+ /*|                                unsigned short   w_EepromStartAddress,                |*/
+ /*|                                unsigned short * pw_DataRead)                          |*/
+ /*+----------------------------------------------------------------------------+*/
+ /*| Task              : Read word from the 5920 eeprom.                        |*/
+ /*+----------------------------------------------------------------------------+*/
+-/*| Input Parameters  : INT    i_NbOfWordsToRead : Nbr. of word to read        |*/
++/*| Input Parameters  : int    i_NbOfWordsToRead : Nbr. of word to read        |*/
+ /*|                     DWORD dw_PCIBoardEepromAddress : Address of the eeprom |*/
+ /*|                     unsigned short   w_EepromStartAddress : Eeprom strat address     |*/
+ /*+----------------------------------------------------------------------------+*/
+@@ -66,14 +66,14 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*| Return Value      : -                                                      |*/
+ /*+----------------------------------------------------------------------------+*/
+ 
+-INT i_AddiHeaderRW_ReadEeprom(INT i_NbOfWordsToRead,
++int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 	DWORD dw_PCIBoardEepromAddress,
+ 	unsigned short w_EepromStartAddress, unsigned short * pw_DataRead)
+ {
+ 	DWORD dw_eeprom_busy = 0;
+-	INT i_Counter = 0;
+-	INT i_WordCounter;
+-	INT i;
++	int i_Counter = 0;
++	int i_WordCounter;
++	int i;
+ 	unsigned char pb_ReadByte[1];
+ 	unsigned char b_ReadLowByte = 0;
+ 	unsigned char b_ReadHighByte = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h
+index 4a0f3c1ef03c..7e4415772bc0 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h
+@@ -22,6 +22,6 @@
+ #define NVCMD_BEGIN_READ	(0x7 << 5)	/* nvRam begin read command */
+ #define NVCMD_BEGIN_WRITE	(0x6 << 5)	/* EEPROM begin write command */
+ 
+-INT i_AddiHeaderRW_ReadEeprom(INT i_NbOfWordsToRead,
++int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 			      DWORD dw_PCIBoardEepromAddress,
+ 			      unsigned short w_EepromStartAddress, unsigned short * pw_DataRead);
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h b/drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h
+index b50774cdcf77..4ad8253dc08f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h
+@@ -85,7 +85,7 @@
+ #define AMCC_OP_REG_MRTC		0x30
+ #define AMCC_OP_REG_MBEF		0x34
+ #define AMCC_OP_REG_INTCSR		0x38
+-/* INT source */
++/* int source */
+ #define  AMCC_OP_REG_INTCSR_SRC		(AMCC_OP_REG_INTCSR + 2)
+ /* FIFO ctrl */
+ #define  AMCC_OP_REG_INTCSR_FEC		(AMCC_OP_REG_INTCSR + 3)
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+index 724e030d83e2..b0bacf8420f3 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+@@ -2624,18 +2624,18 @@ static int i_ADDI_Attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 
+ 		dev->board_name = this_board->pc_DriverName;
+ 		devpriv->amcc = card;
+-		devpriv->iobase = (INT) dev->iobase;
+-		devpriv->i_IobaseAmcc = (INT) iobase_a;	//AMCC base address...
+-		devpriv->i_IobaseAddon = (INT) iobase_addon;	//ADD ON base address....
+-		devpriv->i_IobaseReserved = (INT) iobase_reserved;
++		devpriv->iobase = (int) dev->iobase;
++		devpriv->i_IobaseAmcc = (int) iobase_a;	//AMCC base address...
++		devpriv->i_IobaseAddon = (int) iobase_addon;	//ADD ON base address....
++		devpriv->i_IobaseReserved = (int) iobase_reserved;
+ 		devpriv->ps_BoardInfo = this_board;
+ 	} else {
+ 		dev->board_name = this_board->pc_DriverName;
+ 		dev->iobase = (unsigned long)io_addr[2];
+ 		devpriv->amcc = card;
+-		devpriv->iobase = (INT) io_addr[2];
++		devpriv->iobase = (int) io_addr[2];
+ 		devpriv->ps_BoardInfo = this_board;
+-		devpriv->i_IobaseReserved = (INT) io_addr[3];
++		devpriv->i_IobaseReserved = (int) io_addr[3];
+ 		printk("\nioremap begin");
+ 		devpriv->dw_AiBase =
+ 			(ULONG_PTR) ioremap(io_addr[3],
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+index 1b8e2b1b5564..daea1c25434b 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+@@ -37,7 +37,6 @@
+ #define SUCCESS	1
+ 
+ /* variable type definition */
+-typedef int INT, *PINT;;
+ typedef unsigned int UINT, *PUINT;
+ typedef int LONG, *PLONG;		/* 32-bit */
+ typedef unsigned int ULONG, *PULONG;	/* 32-bit */
+@@ -73,32 +72,32 @@ typedef const struct comedi_lrange *PCRANGE;
+ /* structure for the boardtype */
+ typedef struct {
+ 	const char *pc_DriverName;	// driver name
+-	INT i_VendorId;		//PCI vendor a device ID of card
+-	INT i_DeviceId;
+-	INT i_IorangeBase0;
+-	INT i_IorangeBase1;
+-	INT i_IorangeBase2;	//  base 2 range
+-	INT i_IorangeBase3;	//  base 3 range
+-	INT i_PCIEeprom;	// eeprom present or not
++	int i_VendorId;		//PCI vendor a device ID of card
++	int i_DeviceId;
++	int i_IorangeBase0;
++	int i_IorangeBase1;
++	int i_IorangeBase2;	//  base 2 range
++	int i_IorangeBase3;	//  base 3 range
++	int i_PCIEeprom;	// eeprom present or not
+ 	char *pc_EepromChip;	// type of chip
+-	INT i_NbrAiChannel;	// num of A/D chans
+-	INT i_NbrAiChannelDiff;	// num of A/D chans in diff mode
+-	INT i_AiChannelList;	// len of chanlist
+-	INT i_NbrAoChannel;	// num of D/A chans
+-	INT i_AiMaxdata;	// resolution of A/D
+-	INT i_AoMaxdata;	// resolution of D/A
++	int i_NbrAiChannel;	// num of A/D chans
++	int i_NbrAiChannelDiff;	// num of A/D chans in diff mode
++	int i_AiChannelList;	// len of chanlist
++	int i_NbrAoChannel;	// num of D/A chans
++	int i_AiMaxdata;	// resolution of A/D
++	int i_AoMaxdata;	// resolution of D/A
+ 	PCRANGE pr_AiRangelist;	// rangelist for A/D
+ 	PCRANGE pr_AoRangelist;	// rangelist for D/A
+ 
+-	INT i_NbrDiChannel;	// Number of DI channels
+-	INT i_NbrDoChannel;	// Number of DO channels
+-	INT i_DoMaxdata;	// data to set all chanels high
++	int i_NbrDiChannel;	// Number of DI channels
++	int i_NbrDoChannel;	// Number of DO channels
++	int i_DoMaxdata;	// data to set all chanels high
+ 
+-	INT i_NbrTTLChannel;	// Number of TTL channels
++	int i_NbrTTLChannel;	// Number of TTL channels
+ 	PCRANGE pr_TTLRangelist;	// rangelist for TTL
+ 
+-	INT i_Dma;		// dma present or not
+-	INT i_Timer;		//   timer subdevice present or not
++	int i_Dma;		// dma present or not
++	int i_Timer;		//   timer subdevice present or not
+ 	unsigned char b_AvailableConvertUnit;
+ 	UINT ui_MinAcquisitiontimeNs;	// Minimum Acquisition in Nano secs
+ 	UINT ui_MinDelaytimeNs;	// Minimum Delay in Nano secs
+@@ -357,10 +356,10 @@ typedef union {
+ /* Private structure for the addi_apci3120 driver */
+ typedef struct {
+ 
+-	INT iobase;
+-	INT i_IobaseAmcc;	// base+size for AMCC chip
+-	INT i_IobaseAddon;	//addon base address
+-	INT i_IobaseReserved;
++	int iobase;
++	int i_IobaseAmcc;	// base+size for AMCC chip
++	int i_IobaseAddon;	//addon base address
++	int i_IobaseReserved;
+ 	ULONG_PTR dw_AiBase;
+ 	struct pcilst_struct *amcc;	// ptr too AMCC data
+ 	unsigned char allocated;		// we have blocked card
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+index c0372bee9619..ba902bf4a52c 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+@@ -118,26 +118,26 @@ typedef struct {
+ 		/*            Read Header Functions              */
+ 		/*****************************************/
+ 
+-INT i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
++int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, struct comedi_device *dev);
+ 
+-INT i_EepromReadDigitalInputHeader(unsigned short w_PCIBoardEepromAddress,
++int i_EepromReadDigitalInputHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+ 	str_DigitalInputHeader * s_Header);
+ 
+-INT i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress,
++int i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+ 	str_DigitalOutputHeader * s_Header);
+ 
+-INT i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
++int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+ 	str_TimerMainHeader * s_Header);
+ 
+-INT i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
++int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+ 	str_AnalogOutputHeader * s_Header);
+ 
+-INT i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress,
++int i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+ 	str_AnalogInputHeader * s_Header);
+ 
+@@ -784,7 +784,7 @@ void v_EepromCs76Read(DWORD dw_Address, unsigned short w_offset, unsigned short
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name  : INT i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,  |
++| Function Name  : int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,  |
+ |				char *	pc_PCIChipInformation,struct comedi_device *dev)    |
+ +----------------------------------------------------------------------------+
+ | Task              : Read from eeprom Main Header                           |
+@@ -802,7 +802,7 @@ void v_EepromCs76Read(DWORD dw_Address, unsigned short w_offset, unsigned short
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
++int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, struct comedi_device *dev)
+ {
+ 	unsigned short w_Temp, i, w_Count = 0;
+@@ -918,7 +918,7 @@ INT i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name  : INT i_EepromReadDigitalInputHeader(unsigned short 					 |
++| Function Name  : int i_EepromReadDigitalInputHeader(unsigned short 					 |
+ |			w_PCIBoardEepromAddress,char *pc_PCIChipInformation,	 |
+ |			unsigned short w_Address,str_DigitalInputHeader *s_Header)		 |
+ |																	 |
+@@ -937,7 +937,7 @@ INT i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
+ | Return Value      : 0							                             |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_EepromReadDigitalInputHeader(unsigned short w_PCIBoardEepromAddress,
++int i_EepromReadDigitalInputHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+ 	str_DigitalInputHeader * s_Header)
+ {
+@@ -963,7 +963,7 @@ INT i_EepromReadDigitalInputHeader(unsigned short w_PCIBoardEepromAddress,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name  : INT i_EepromReadDigitalOutputHeader(unsigned short 				 |
++| Function Name  : int i_EepromReadDigitalOutputHeader(unsigned short 				 |
+ |			w_PCIBoardEepromAddress,char *pc_PCIChipInformation,	 |
+ |			unsigned short w_Address,str_DigitalOutputHeader *s_Header)	     |
+ |																	 |
+@@ -982,7 +982,7 @@ INT i_EepromReadDigitalInputHeader(unsigned short w_PCIBoardEepromAddress,
+ | Return Value      : 0							                             |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress,
++int i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+ 	str_DigitalOutputHeader * s_Header)
+ {
+@@ -995,7 +995,7 @@ INT i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name  : INT i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress, |
++| Function Name  : int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress, |
+ |			char *pc_PCIChipInformation,WORD w_Address,				 |
+ |			str_TimerMainHeader *s_Header)							 |
+ +----------------------------------------------------------------------------+
+@@ -1013,7 +1013,7 @@ INT i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ | Return Value      : 0							                             |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
++int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+ 	str_TimerMainHeader * s_Header)
+ {
+@@ -1060,7 +1060,7 @@ INT i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name  : INT i_EepromReadAnlogOutputHeader(unsigned short 					 |
++| Function Name  : int i_EepromReadAnlogOutputHeader(unsigned short 					 |
+ |			w_PCIBoardEepromAddress,char *pc_PCIChipInformation,	 |
+ |			unsigned short w_Address,str_AnalogOutputHeader *s_Header)         |
+ +----------------------------------------------------------------------------+
+@@ -1079,7 +1079,7 @@ INT i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
++int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+ 	str_AnalogOutputHeader * s_Header)
+ {
+@@ -1097,7 +1097,7 @@ INT i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name  : INT i_EepromReadAnlogInputHeader(unsigned short 					 |
++| Function Name  : int i_EepromReadAnlogInputHeader(unsigned short 					 |
+ |			w_PCIBoardEepromAddress,char *pc_PCIChipInformation,     |
+ |			unsigned short w_Address,str_AnalogInputHeader *s_Header)          |
+ +----------------------------------------------------------------------------+
+@@ -1117,7 +1117,7 @@ INT i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
+ */
+ 
+ // Reads only for ONE  hardware component
+-INT i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress,
++int i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, unsigned short w_Address,
+ 	str_AnalogInputHeader * s_Header)
+ {
+diff --git a/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h b/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h
+index 617dc087dcbf..86e6578a20fe 100644
+--- a/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h
++++ b/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h
+@@ -85,7 +85,7 @@
+ #define AMCC_OP_REG_MRTC         0x30
+ #define AMCC_OP_REG_MBEF         0x34
+ #define AMCC_OP_REG_INTCSR       0x38
+-#define  AMCC_OP_REG_INTCSR_SRC  (AMCC_OP_REG_INTCSR + 2)	/* INT source */
++#define  AMCC_OP_REG_INTCSR_SRC  (AMCC_OP_REG_INTCSR + 2)	/* int source */
+ #define  AMCC_OP_REG_INTCSR_FEC  (AMCC_OP_REG_INTCSR + 3)	/* FIFO ctrl */
+ #define AMCC_OP_REG_MCSR         0x3c
+ #define  AMCC_OP_REG_MCSR_NVDATA (AMCC_OP_REG_MCSR + 2)	/* Data in byte 2 */
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
+index e4527926c2df..1c82f92c228f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
+@@ -52,9 +52,9 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ #include "hwdrv_apci035.h"
+-INT i_WatchdogNbr = 0;
+-INT i_Temp = 0;
+-INT i_Flag = 1;
++int i_WatchdogNbr = 0;
++int i_Temp = 0;
++int i_Flag = 1;
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI035_ConfigTimerWatchdog                      |
+@@ -109,7 +109,7 @@ INT i_Flag = 1;
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI035_ConfigTimerWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI035_ConfigTimerWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Status = 0;
+@@ -278,11 +278,11 @@ INT i_APCI035_ConfigTimerWatchdog(struct comedi_device * dev, struct comedi_subd
+ |					                                                 |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device * dev,
++int i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Command = 0;
+-	INT i_Count = 0;
++	int i_Count = 0;
+ 	if (data[0] == 1) {
+ 		ui_Command =
+ 			inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+@@ -391,7 +391,7 @@ INT i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device * dev,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI035_ReadTimerWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI035_ReadTimerWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Status = 0;	// Status register
+@@ -426,7 +426,7 @@ INT i_APCI035_ReadTimerWatchdog(struct comedi_device * dev, struct comedi_subdev
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function   Name   : INT i_APCI035_ConfigAnalogInput                        |
++| Function   Name   : int i_APCI035_ConfigAnalogInput                        |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+@@ -447,7 +447,7 @@ INT i_APCI035_ReadTimerWatchdog(struct comedi_device * dev, struct comedi_subdev
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI035_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI035_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	devpriv->tsk_Current = current;
+@@ -484,7 +484,7 @@ INT i_APCI035_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subdev
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI035_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI035_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_CommandRegister = 0;
+@@ -519,9 +519,9 @@ INT i_APCI035_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevic
+ |			                                                                 |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI035_Reset(struct comedi_device * dev)
++int i_APCI035_Reset(struct comedi_device * dev)
+ {
+-	INT i_Count = 0;
++	int i_Count = 0;
+ 	for (i_Count = 1; i_Count <= 4; i_Count++) {
+ 		i_WatchdogNbr = i_Count;
+ 		outl(0x0, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0);	//stop all timers
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
+index 80d7c0d39aab..6ff69aba2217 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
+@@ -19,18 +19,18 @@
+ #define APCI035_BOARD_VENDOR_ID		0x15B8
+ #define APCI035_ADDRESS_RANGE		255
+ 
+-INT i_TW_Number;
++int i_TW_Number;
+ struct {
+-	INT i_Gain;
+-	INT i_Polarity;
+-	INT i_OffsetRange;
+-	INT i_Coupling;
+-	INT i_SingleDiff;
+-	INT i_AutoCalibration;
++	int i_Gain;
++	int i_Polarity;
++	int i_OffsetRange;
++	int i_Coupling;
++	int i_SingleDiff;
++	int i_AutoCalibration;
+ 	UINT ui_ReloadValue;
+ 	UINT ui_TimeUnitReloadVal;
+-	INT i_Interrupt;
+-	INT i_ModuleSelection;
++	int i_Interrupt;
++	int i_ModuleSelection;
+ } Config_Parameters_Main;
+ 
+ /* ANALOG INPUT RANGE */
+@@ -101,23 +101,23 @@ struct comedi_lrange range_apci035_ai = { 8, {
+ 
+ /* TIMER */
+ /* timer value is passed as u seconds */
+-INT i_APCI035_ConfigTimerWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI035_ConfigTimerWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				  struct comedi_insn *insn, unsigned int *data);
+-INT i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device *dev,
++int i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device *dev,
+ 					  struct comedi_subdevice *s,
+ 					  struct comedi_insn *insn, unsigned int *data);
+-INT i_APCI035_ReadTimerWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI035_ReadTimerWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				struct comedi_insn *insn, unsigned int *data);
+ 
+ /* Temperature Related Defines (Analog Input Subdevice) */
+ 
+-INT i_APCI035_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI035_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				struct comedi_insn *insn, unsigned int *data);
+-INT i_APCI035_ReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI035_ReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			      struct comedi_insn *insn, unsigned int *data);
+ 
+ /* Interrupt */
+ static void v_APCI035_Interrupt(int irq, void *d);
+ 
+ /* Reset functions */
+-INT i_APCI035_Reset(struct comedi_device *dev);
++int i_APCI035_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+index 32796ceb946e..c56b9a52cf6f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+@@ -84,7 +84,7 @@ UINT ui_InterruptStatus = 0;
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1032_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1032_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue;
+@@ -144,7 +144,7 @@ INT i_APCI1032_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subd
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1032_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1032_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue = 0;
+@@ -183,7 +183,7 @@ INT i_APCI1032_Read1DigitalInput(struct comedi_device * dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1032_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1032_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_PortValue = data[0];
+@@ -275,7 +275,7 @@ static void v_APCI1032_Interrupt(int irq, void *d)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1032_Reset(struct comedi_device * dev)
++int i_APCI1032_Reset(struct comedi_device * dev)
+ {
+ 	outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);	//disable the interrupts
+ 	inl(devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_STATUS);	//Reset the interrupt status register
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
+index 659ef85088cd..cb1fb9dbe1f4 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
+@@ -47,17 +47,17 @@
+ //DI
+ // for di read
+ 
+-INT i_APCI1032_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1032_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				  struct comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1032_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1032_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 struct comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1032_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1032_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				    struct comedi_insn *insn, unsigned int *data);
+ 
+ // Interrupt functions.....
+ 
+ static void v_APCI1032_Interrupt(int irq, void *d);
+ //Reset
+-INT i_APCI1032_Reset(struct comedi_device *dev);
++int i_APCI1032_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+index 2d6adcff41e3..646972ce8f69 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+@@ -137,7 +137,7 @@ int i_TimerCounter1Enabled = 0, i_TimerCounter2Enabled =
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1500_ConfigDigitalInputEvent(struct comedi_device * dev,
++int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_PatternPolarity = 0, i_PatternTransition = 0, i_PatternMask = 0;
+@@ -784,7 +784,7 @@ int i_APCI1500_StartStopInputEvent(struct comedi_device * dev, struct comedi_sub
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1500_Initialisation(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1500_Initialisation(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_DummyRead = 0;
+@@ -957,7 +957,7 @@ INT i_APCI1500_Initialisation(struct comedi_device * dev, struct comedi_subdevic
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1500_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1500_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_PortValue = data[1];
+@@ -1067,7 +1067,7 @@ int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1500_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1500_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	static UINT ui_Temp = 0;
+@@ -2822,7 +2822,7 @@ static void v_APCI1500_Interrupt(int irq, void *d)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1500_Reset(struct comedi_device * dev)
++int i_APCI1500_Reset(struct comedi_device * dev)
+ {
+ 	int i_DummyRead = 0;
+ 	i_TimerCounter1Init = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
+index 5ae9a93844e7..18e5fbfd493e 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
+@@ -73,7 +73,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1516_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1516_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue = 0;
+@@ -114,7 +114,7 @@ INT i_APCI1516_Read1DigitalInput(struct comedi_device * dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1516_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1516_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -199,7 +199,7 @@ int i_APCI1516_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1516_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1516_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp, ui_Temp1;
+@@ -359,7 +359,7 @@ INT i_APCI1516_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1516_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1516_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -532,7 +532,7 @@ int i_APCI1516_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1516_Reset(struct comedi_device * dev)
++int i_APCI1516_Reset(struct comedi_device * dev)
+ {
+ 	outw(0x0, devpriv->iobase + APCI1516_DIGITAL_OP);	//RESETS THE DIGITAL OUTPUTS
+ 	outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_ENABLEDISABLE);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h
+index 398baa04a163..b1367efa243e 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h
+@@ -38,17 +38,17 @@
+ // Hardware Layer  functions for Apci1516
+ 
+ //Digital Input
+-INT i_APCI1516_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1516_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				    struct comedi_insn *insn, unsigned int *data);
+-INT i_APCI1516_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1516_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 struct comedi_insn *insn, unsigned int *data);
+ 
+ //Digital Output
+ int i_APCI1516_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   struct comedi_insn *insn, unsigned int *data);
+-INT i_APCI1516_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1516_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				  struct comedi_insn *insn, unsigned int *data);
+-INT i_APCI1516_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1516_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 struct comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+@@ -61,4 +61,4 @@ int i_APCI1516_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *
+ 			    struct comedi_insn *insn, unsigned int *data);
+ 
+ //reset
+-INT i_APCI1516_Reset(struct comedi_device *dev);
++int i_APCI1516_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+index 54d23591bfc3..db0d1795906e 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+@@ -86,7 +86,7 @@ UINT ui_InterruptData, ui_Type;
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1564_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1564_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	devpriv->tsk_Current = current;
+@@ -147,7 +147,7 @@ INT i_APCI1564_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subd
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1564_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1564_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue = 0;
+@@ -187,7 +187,7 @@ INT i_APCI1564_Read1DigitalInput(struct comedi_device * dev, struct comedi_subde
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1564_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1564_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_PortValue = data[0];
+@@ -255,7 +255,7 @@ INT i_APCI1564_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1564_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1564_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command = 0;
+@@ -312,7 +312,7 @@ INT i_APCI1564_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1564_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1564_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp, ui_Temp1;
+@@ -486,7 +486,7 @@ INT i_APCI1564_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1564_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI1564_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+@@ -564,7 +564,7 @@ INT i_APCI1564_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device * dev,
++int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0;
+@@ -718,7 +718,7 @@ INT i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
++int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0;
+@@ -813,7 +813,7 @@ INT i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device * dev,
++int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0;
+@@ -1081,7 +1081,7 @@ static void v_APCI1564_Interrupt(int irq, void *d)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1564_Reset(struct comedi_device * dev)
++int i_APCI1564_Reset(struct comedi_device * dev)
+ {
+ 	outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_IRQ);	//disable the interrupts
+ 	inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_STATUS);	//Reset the interrupt status register
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
+index f0c461ca5396..19ded14c88d7 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
+@@ -82,26 +82,26 @@
+ 
+ //DI
+ // for di read
+-INT i_APCI1564_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1564_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				  struct comedi_insn *insn, unsigned int *data);
+-INT i_APCI1564_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1564_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 struct comedi_insn *insn, unsigned int *data);
+-INT i_APCI1564_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1564_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				    struct comedi_insn *insn, unsigned int *data);
+ 
+ //DO
+ int i_APCI1564_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   struct comedi_insn *insn, unsigned int *data);
+-INT i_APCI1564_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1564_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				  struct comedi_insn *insn, unsigned int *data);
+-INT i_APCI1564_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI1564_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 struct comedi_insn *insn, unsigned int *data);
+ int i_APCI1564_ReadInterruptStatus(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   struct comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+ // timer value is passed as u seconds
+-INT i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev,
++int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev,
+ 					  struct comedi_subdevice *s,
+ 					  struct comedi_insn *insn, unsigned int *data);
+ int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
+@@ -112,8 +112,8 @@ int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device *dev,
+ 					struct comedi_subdevice *s,
+ 					struct comedi_insn *insn, unsigned int *data);
+ 
+-// INTERRUPT
++// intERRUPT
+ static void v_APCI1564_Interrupt(int irq, void *d);
+ 
+ // RESET
+-INT i_APCI1564_Reset(struct comedi_device *dev);
++int i_APCI1564_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
+index c9249ea543a8..a5e93d32e54e 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
+@@ -57,7 +57,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     : INT   i_APCI16XX_InsnConfigInitTTLIO                   |
++| Function Name     : int   i_APCI16XX_InsnConfigInitTTLIO                   |
+ |                          (struct comedi_device    *dev,                           |
+ |                           struct comedi_subdevice *s,                             |
+ |                           struct comedi_insn      *insn,                          |
+@@ -93,7 +93,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = insn->n;
++	int i_ReturnValue = insn->n;
+ 	unsigned char b_Command = 0;
+ 	unsigned char b_Cpt = 0;
+ 	unsigned char b_NumberOfPort =
+@@ -182,8 +182,8 @@ int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ 		 /************************/
+ 
+ 				printk("\nPort %d direction selection error",
+-					(INT) b_Cpt);
+-				i_ReturnValue = -(INT) b_Cpt;
++					(int) b_Cpt);
++				i_ReturnValue = -(int) b_Cpt;
+ 			}
+ 
+ 	      /**************************/
+@@ -250,7 +250,7 @@ int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     : INT     i_APCI16XX_InsnBitsReadTTLIO                   |
++| Function Name     : int     i_APCI16XX_InsnBitsReadTTLIO                   |
+ |                          (struct comedi_device    *dev,                           |
+ |                           struct comedi_subdevice *s,                             |
+ |                           struct comedi_insn      *insn,                          |
+@@ -286,7 +286,7 @@ int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = insn->n;
++	int i_ReturnValue = insn->n;
+ 	unsigned char b_Command = 0;
+ 	unsigned char b_NumberOfPort =
+ 		(unsigned char) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 8);
+@@ -410,7 +410,7 @@ int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     : INT i_APCI16XX_InsnReadTTLIOAllPortValue               |
++| Function Name     : int i_APCI16XX_InsnReadTTLIOAllPortValue               |
+ |                          (struct comedi_device    *dev,                           |
+ |                           struct comedi_subdevice *s,                             |
+ |                           struct comedi_insn      *insn,                          |
+@@ -434,7 +434,7 @@ int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned char b_Command = (unsigned char) CR_AREF(insn->chanspec);
+-	INT i_ReturnValue = insn->n;
++	int i_ReturnValue = insn->n;
+ 	unsigned char b_Cpt = 0;
+ 	unsigned char b_NumberOfPort = 0;
+ 	unsigned int *pls_ReadData = data;
+@@ -535,7 +535,7 @@ int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     : INT     i_APCI16XX_InsnBitsWriteTTLIO                  |
++| Function Name     : int     i_APCI16XX_InsnBitsWriteTTLIO                  |
+ |                          (struct comedi_device    *dev,                           |
+ |                           struct comedi_subdevice *s,                             |
+ |                           struct comedi_insn      *insn,                          |
+@@ -573,7 +573,7 @@ int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+ int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = insn->n;
++	int i_ReturnValue = insn->n;
+ 	unsigned char b_Command = 0;
+ 	unsigned char b_NumberOfPort =
+ 		(unsigned char) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 8);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
+index 31f55da39ea8..6b1e29fd56f6 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
+@@ -450,7 +450,7 @@ int i_APCI2016_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI2016_Reset(struct comedi_device * dev)
++int i_APCI2016_Reset(struct comedi_device * dev)
+ {
+ 	outw(0x0, devpriv->iobase + APCI2016_DIGITAL_OP);	// Resets the digital output channels
+ 	outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_ENABLEDISABLE);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
+index 9261aacd25f1..80e907e87f08 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
+@@ -67,4 +67,4 @@ int i_APCI2016_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *
+ 
+  //void v_APCI2016_Interrupt(int irq, void *d);
+ // RESET
+-INT i_APCI2016_Reset(struct comedi_device *dev);
++int i_APCI2016_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
+index 1347bc388f3e..82e50d9c371a 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
+@@ -134,7 +134,7 @@ int i_APCI2032_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI2032_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI2032_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp, ui_Temp1;
+@@ -313,7 +313,7 @@ INT i_APCI2032_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI2032_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI2032_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+@@ -362,7 +362,7 @@ INT i_APCI2032_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function   Name   : INT i_APCI2032_ConfigWatchdog(comedi_device
++| Function   Name   : int i_APCI2032_ConfigWatchdog(comedi_device
+                    *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)|
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+@@ -380,7 +380,7 @@ INT i_APCI2032_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI2032_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI2032_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0] == 0) {
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h
+index 55002e0288b5..15f09e3ab2eb 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h
+@@ -57,16 +57,16 @@
+ //DO
+ int i_APCI2032_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   struct comedi_insn *insn, unsigned int *data);
+-INT i_APCI2032_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI2032_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				  struct comedi_insn *insn, unsigned int *data);
+-INT i_APCI2032_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI2032_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 struct comedi_insn *insn, unsigned int *data);
+ int i_APCI2032_ReadInterruptStatus(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   struct comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+ // timer value is passed as u seconds
+-INT i_APCI2032_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI2032_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			      struct comedi_insn *insn, unsigned int *data);
+ int i_APCI2032_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				      struct comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
+index 947e18ef3ab3..404bebb5a706 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
+@@ -73,7 +73,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI2200_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI2200_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue = 0;
+@@ -112,7 +112,7 @@ INT i_APCI2200_Read1DigitalInput(struct comedi_device * dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI2200_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI2200_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -197,7 +197,7 @@ int i_APCI2200_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI2200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI2200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp, ui_Temp1;
+@@ -354,7 +354,7 @@ INT i_APCI2200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI2200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI2200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -533,7 +533,7 @@ int i_APCI2200_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI2200_Reset(struct comedi_device * dev)
++int i_APCI2200_Reset(struct comedi_device * dev)
+ {
+ 	outw(0x0, devpriv->iobase + APCI2200_DIGITAL_OP);	//RESETS THE DIGITAL OUTPUTS
+ 	outw(0x0,
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h
+index 0a115b4c44c9..37b795106093 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h
+@@ -36,17 +36,17 @@
+ // Hardware Layer  functions for Apci2200
+ 
+ //Digital Input
+-INT i_APCI2200_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI2200_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				    struct comedi_insn *insn, unsigned int *data);
+-INT i_APCI2200_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI2200_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 struct comedi_insn *insn, unsigned int *data);
+ 
+ //Digital Output
+ int i_APCI2200_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   struct comedi_insn *insn, unsigned int *data);
+-INT i_APCI2200_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI2200_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				  struct comedi_insn *insn, unsigned int *data);
+-INT i_APCI2200_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI2200_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 struct comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+@@ -58,4 +58,4 @@ int i_APCI2200_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *
+ 			    struct comedi_insn *insn, unsigned int *data);
+ 
+ //reset
+-INT i_APCI2200_Reset(struct comedi_device *dev);
++int i_APCI2200_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+index b06ff1ed345f..84582f45726c 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+@@ -745,7 +745,7 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 	//COMMENT JK 07.05.04: Followings calls are in i_APCI3120_StartAnalogInputAcquisition
+ 
+    /****************************/
+-	/* Clear Timer Write TC INT */
++	/* Clear Timer Write TC int */
+    /****************************/
+ 	outl(APCI3120_CLEAR_WRITE_TC_INT,
+ 		devpriv->i_IobaseAmcc + APCI3120_AMCC_OP_REG_INTCSR);
+@@ -936,7 +936,7 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 			outw(devpriv->us_OutputRegister,
+ 				dev->iobase + APCI3120_WR_ADDRESS);
+ 
+-			// DISABLE TIMER INTERRUPT
++			// DISABLE TIMER intERRUPT
+ 			devpriv->b_ModeSelectRegister =
+ 				devpriv->
+ 				b_ModeSelectRegister &
+@@ -1139,7 +1139,7 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 		//7
+ 		//initialise end of dma interrupt  AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI)
+ 		/***************************************************/
+-		/* A2P FIFO CONFIGURATE, END OF DMA INTERRUPT INIT */
++		/* A2P FIFO CONFIGURATE, END OF DMA intERRUPT INIT */
+ 		/***************************************************/
+ 		outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2 |
+ 				APCI3120_ENABLE_WRITE_TC_INT),
+@@ -1196,7 +1196,7 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| 			INTERNAL FUNCTIONS						                 |
++| 			intERNAL FUNCTIONS						                 |
+ +----------------------------------------------------------------------------+
+ */
+ 
+@@ -1394,7 +1394,7 @@ int i_APCI3120_ExttrigDisable(struct comedi_device * dev)
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-|                    INTERRUPT FUNCTIONS		    		                 |
++|                    intERRUPT FUNCTIONS		    		                 |
+ +----------------------------------------------------------------------------+
+ */
+ 
+@@ -1432,7 +1432,7 @@ void v_APCI3120_Interrupt(int irq, void *d)
+ 	ui_Check = 1;
+ 
+ 	int_daq = inw(dev->iobase + APCI3120_RD_STATUS) & 0xf000;	// get IRQ reasons
+-	int_amcc = inl(devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);	// get AMCC INT register
++	int_amcc = inl(devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);	// get AMCC int register
+ 
+ 	if ((!int_daq) && (!(int_amcc & ANY_S593X_INT))) {
+ 		comedi_error(dev, "IRQ from unknow source");
+@@ -1585,7 +1585,7 @@ void v_APCI3120_Interrupt(int irq, void *d)
+ 		if (devpriv->b_AiCyclicAcquisition == APCI3120_ENABLE) {
+ 
+ 			/****************************/
+-			/* Clear Timer Write TC INT */
++			/* Clear Timer Write TC int */
+ 			/****************************/
+ 
+ 			outl(APCI3120_CLEAR_WRITE_TC_INT,
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+index 12513624a794..92e57b32b8fb 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+@@ -65,26 +65,26 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ 
+ //BEGIN JK 06.07.04: Management of sevrals boards
+ /*
+-  INT i_CJCAvailable=1;
+-  INT i_CJCPolarity=0;
+-  INT i_CJCGain=2;//changed from 0 to 2
+-  INT i_InterruptFlag=0;
+-  INT i_ADDIDATAPolarity;
+-  INT i_ADDIDATAGain;
+-  INT i_AutoCalibration=0;   //: auto calibration
+-  INT i_ADDIDATAConversionTime;
+-  INT i_ADDIDATAConversionTimeUnit;
+-  INT i_ADDIDATAType;
+-  INT i_ChannelNo;
+-  INT i_ChannelCount=0;
+-  INT i_ScanType;
+-  INT i_FirstChannel;
+-  INT i_LastChannel;
+-  INT i_Sum=0;
+-  INT i_Offset;
++  int i_CJCAvailable=1;
++  int i_CJCPolarity=0;
++  int i_CJCGain=2;//changed from 0 to 2
++  int i_InterruptFlag=0;
++  int i_ADDIDATAPolarity;
++  int i_ADDIDATAGain;
++  int i_AutoCalibration=0;   //: auto calibration
++  int i_ADDIDATAConversionTime;
++  int i_ADDIDATAConversionTimeUnit;
++  int i_ADDIDATAType;
++  int i_ChannelNo;
++  int i_ChannelCount=0;
++  int i_ScanType;
++  int i_FirstChannel;
++  int i_LastChannel;
++  int i_Sum=0;
++  int i_Offset;
+   UINT ui_Channel_num=0;
+   static int i_Count=0;
+-  INT i_Initialised=0;
++  int i_Initialised=0;
+   UINT ui_InterruptChannelValue[96]; //Buffer
+ */
+ str_BoardInfos s_BoardInfos[100];	// 100 will be the max number of boards to be used
+@@ -93,15 +93,15 @@ str_BoardInfos s_BoardInfos[100];	// 100 will be the max number of boards to be
+ //Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+ 
+ /*+----------------------------------------------------------------------------+*/
+-/*| Function   Name   : INT i_AddiHeaderRW_ReadEeprom                          |*/
+-/*|                               (INT    i_NbOfWordsToRead,                   |*/
++/*| Function   Name   : int i_AddiHeaderRW_ReadEeprom                          |*/
++/*|                               (int    i_NbOfWordsToRead,                   |*/
+ /*|                                DWORD dw_PCIBoardEepromAddress,             |*/
+ /*|                                unsigned short   w_EepromStartAddress,                |*/
+ /*|                                unsigned short * pw_DataRead)                          |*/
+ /*+----------------------------------------------------------------------------+*/
+ /*| Task              : Read word from the 5920 eeprom.                        |*/
+ /*+----------------------------------------------------------------------------+*/
+-/*| Input Parameters  : INT    i_NbOfWordsToRead : Nbr. of word to read        |*/
++/*| Input Parameters  : int    i_NbOfWordsToRead : Nbr. of word to read        |*/
+ /*|                     DWORD dw_PCIBoardEepromAddress : Address of the eeprom |*/
+ /*|                     unsigned short   w_EepromStartAddress : Eeprom strat address     |*/
+ /*+----------------------------------------------------------------------------+*/
+@@ -110,14 +110,14 @@ str_BoardInfos s_BoardInfos[100];	// 100 will be the max number of boards to be
+ /*| Return Value      : -                                                      |*/
+ /*+----------------------------------------------------------------------------+*/
+ 
+-INT i_AddiHeaderRW_ReadEeprom(INT i_NbOfWordsToRead,
++int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+ 	DWORD dw_PCIBoardEepromAddress,
+ 	unsigned short w_EepromStartAddress, unsigned short * pw_DataRead)
+ {
+ 	DWORD dw_eeprom_busy = 0;
+-	INT i_Counter = 0;
+-	INT i_WordCounter;
+-	INT i;
++	int i_Counter = 0;
++	int i_WordCounter;
++	int i;
+ 	unsigned char pb_ReadByte[1];
+ 	unsigned char b_ReadLowByte = 0;
+ 	unsigned char b_ReadHighByte = 0;
+@@ -453,7 +453,7 @@ void v_GetAPCI3200EepromCalibrationValue(DWORD dw_PCIBoardEepromAddress,
+ 	}
+ }
+ 
+-INT i_APCI3200_GetChannelCalibrationValue(struct comedi_device * dev,
++int i_APCI3200_GetChannelCalibrationValue(struct comedi_device * dev,
+ 	unsigned int ui_Channel_num, unsigned int * CJCCurrentSource,
+ 	unsigned int * ChannelCurrentSource, unsigned int * ChannelGainFactor)
+ {
+@@ -550,7 +550,7 @@ INT i_APCI3200_GetChannelCalibrationValue(struct comedi_device * dev,
+   +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI3200_ReadDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI3200_ReadDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp = 0;
+@@ -653,7 +653,7 @@ int i_APCI3200_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI3200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp = 0, ui_Temp1 = 0;
+@@ -766,7 +766,7 @@ INT i_APCI3200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI3200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+@@ -806,7 +806,7 @@ INT i_APCI3200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ 
+ /*
+   +----------------------------------------------------------------------------+
+-  | Function   Name   : INT i_APCI3200_ConfigAnalogInput                       |
++  | Function   Name   : int i_APCI3200_ConfigAnalogInput                       |
+   |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+   |                      struct comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+@@ -874,19 +874,19 @@ INT i_APCI3200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3200_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI3200_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	UINT ul_Config = 0, ul_Temp = 0;
+ 	UINT ui_ChannelNo = 0;
+ 	UINT ui_Dummy = 0;
+-	INT i_err = 0;
++	int i_err = 0;
+ 
+ 	//Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+ 
+ #ifdef PRINT_INFO
+-	INT i = 0, i2 = 0;
++	int i = 0, i2 = 0;
+ #endif
+ 	//End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+ 
+@@ -1361,7 +1361,7 @@ INT i_APCI3200_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subde
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3200_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI3200_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_DummyValue = 0;
+@@ -1651,7 +1651,7 @@ INT i_APCI3200_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevi
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3200_Read1AnalogInputChannel(struct comedi_device * dev,
++int i_APCI3200_Read1AnalogInputChannel(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_EOC = 0;
+@@ -1915,7 +1915,7 @@ int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device * dev, UINT * dat
+ int i_APCI3200_ReadCalibrationGainValue(struct comedi_device * dev, UINT * data)
+ {
+ 	UINT ui_EOC = 0;
+-	INT ui_CommandRegister = 0;
++	int ui_CommandRegister = 0;
+ 
+ 	//while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+ 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+@@ -2051,7 +2051,7 @@ int i_APCI3200_ReadCalibrationGainValue(struct comedi_device * dev, UINT * data)
+ int i_APCI3200_ReadCJCValue(struct comedi_device * dev, unsigned int * data)
+ {
+ 	UINT ui_EOC = 0;
+-	INT ui_CommandRegister = 0;
++	int ui_CommandRegister = 0;
+ 
+   /******************************/
+ 	/*Set the converting time unit */
+@@ -2170,7 +2170,7 @@ int i_APCI3200_ReadCJCValue(struct comedi_device * dev, unsigned int * data)
+ int i_APCI3200_ReadCJCCalOffset(struct comedi_device * dev, unsigned int * data)
+ {
+ 	UINT ui_EOC = 0;
+-	INT ui_CommandRegister = 0;
++	int ui_CommandRegister = 0;
+   /*******************************************/
+ 	/*Read calibration offset value for the CJC */
+   /*******************************************/
+@@ -2286,7 +2286,7 @@ int i_APCI3200_ReadCJCCalOffset(struct comedi_device * dev, unsigned int * data)
+ int i_APCI3200_ReadCJCCalGain(struct comedi_device * dev, unsigned int * data)
+ {
+ 	UINT ui_EOC = 0;
+-	INT ui_CommandRegister = 0;
++	int ui_CommandRegister = 0;
+   /*******************************/
+ 	/* Set the convert timing unit */
+   /*******************************/
+@@ -2404,11 +2404,11 @@ int i_APCI3200_ReadCJCCalGain(struct comedi_device * dev, unsigned int * data)
+   +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device * dev,
++int i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Configuration = 0;
+-	INT i_Temp;		//,i_TimeUnit;
++	int i_Temp;		//,i_TimeUnit;
+ 	//if(i_Initialised==0)
+ 
+ 	if (s_BoardInfos[dev->minor].i_Initialised == 0) {
+@@ -2529,7 +2529,7 @@ INT i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device * dev,
+   +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device * dev,
++int i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	i_APCI3200_Reset(dev);
+@@ -2570,10 +2570,10 @@ int i_APCI3200_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_
+ 	UINT ui_ConvertTimeBase = 0;
+ 	UINT ui_DelayTime = 0;
+ 	UINT ui_DelayTimeBase = 0;
+-	INT i_Triggermode = 0;
+-	INT i_TriggerEdge = 0;
+-	INT i_NbrOfChannel = 0;
+-	INT i_Cpt = 0;
++	int i_Triggermode = 0;
++	int i_TriggerEdge = 0;
++	int i_NbrOfChannel = 0;
++	int i_Cpt = 0;
+ 	double d_ConversionTimeForAllChannels = 0.0;
+ 	double d_SCANTimeNewUnit = 0.0;
+ 	// step 1: make sure trigger sources are trivially valid
+@@ -3003,7 +3003,7 @@ int i_APCI3200_CommandAnalogInput(struct comedi_device * dev, struct comedi_subd
+ 
+ int i_APCI3200_Reset(struct comedi_device * dev)
+ {
+-	INT i_Temp;
++	int i_Temp;
+ 	DWORD dw_Dummy;
+ 	//i_InterruptFlag=0;
+ 	//i_Initialised==0;
+@@ -3062,8 +3062,8 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 	struct comedi_device *dev = d;
+ 	UINT ui_StatusRegister = 0;
+ 	UINT ui_ChannelNumber = 0;
+-	INT i_CalibrationFlag = 0;
+-	INT i_CJCFlag = 0;
++	int i_CalibrationFlag = 0;
++	int i_CJCFlag = 0;
+ 	UINT ui_DummyValue = 0;
+ 	UINT ui_DigitalTemperature = 0;
+ 	UINT ui_DigitalInput = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+index d93fff37df84..416a7f0370d7 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+@@ -21,16 +21,16 @@
+ 
+ int MODULE_NO;
+ struct {
+-	INT i_Gain;
+-	INT i_Polarity;
+-	INT i_OffsetRange;
+-	INT i_Coupling;
+-	INT i_SingleDiff;
+-	INT i_AutoCalibration;
++	int i_Gain;
++	int i_Polarity;
++	int i_OffsetRange;
++	int i_Coupling;
++	int i_SingleDiff;
++	int i_AutoCalibration;
+ 	UINT ui_ReloadValue;
+ 	UINT ui_TimeUnitReloadVal;
+-	INT i_Interrupt;
+-	INT i_ModuleSelection;
++	int i_Interrupt;
++	int i_ModuleSelection;
+ } Config_Parameters_Module1, Config_Parameters_Module2,
+     Config_Parameters_Module3, Config_Parameters_Module4;
+ 
+@@ -115,26 +115,26 @@ typedef struct {
+ 
+ //BEGIN JK 06.07.04: Management of sevrals boards
+ typedef struct {
+-	INT i_CJCAvailable;
+-	INT i_CJCPolarity;
+-	INT i_CJCGain;
+-	INT i_InterruptFlag;
+-	INT i_ADDIDATAPolarity;
+-	INT i_ADDIDATAGain;
+-	INT i_AutoCalibration;
+-	INT i_ADDIDATAConversionTime;
+-	INT i_ADDIDATAConversionTimeUnit;
+-	INT i_ADDIDATAType;
+-	INT i_ChannelNo;
+-	INT i_ChannelCount;
+-	INT i_ScanType;
+-	INT i_FirstChannel;
+-	INT i_LastChannel;
+-	INT i_Sum;
+-	INT i_Offset;
++	int i_CJCAvailable;
++	int i_CJCPolarity;
++	int i_CJCGain;
++	int i_InterruptFlag;
++	int i_ADDIDATAPolarity;
++	int i_ADDIDATAGain;
++	int i_AutoCalibration;
++	int i_ADDIDATAConversionTime;
++	int i_ADDIDATAConversionTimeUnit;
++	int i_ADDIDATAType;
++	int i_ChannelNo;
++	int i_ChannelCount;
++	int i_ScanType;
++	int i_FirstChannel;
++	int i_LastChannel;
++	int i_Sum;
++	int i_Offset;
+ 	UINT ui_Channel_num;
+-	INT i_Count;
+-	INT i_Initialised;
++	int i_Count;
++	int i_Initialised;
+ 	//UINT ui_InterruptChannelValue[96]; //Buffer
+ 	UINT ui_InterruptChannelValue[144];	//Buffer
+ 	unsigned char b_StructInitialized;
+@@ -143,8 +143,8 @@ typedef struct {
+ 	//End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+ 
+ 	//Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+-	INT i_ConnectionType;
+-	INT i_NbrOfModule;
++	int i_ConnectionType;
++	int i_NbrOfModule;
+ 	str_Module s_Module[MAX_MODULE];
+ 	//End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+ } str_BoardInfos;
+@@ -154,28 +154,28 @@ typedef struct {
+ 
+ //AI
+ 
+-INT i_APCI3200_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI3200_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 struct comedi_insn *insn, unsigned int *data);
+-INT i_APCI3200_ReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI3200_ReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			       struct comedi_insn *insn, unsigned int *data);
+-INT i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device *dev,
++int i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device *dev,
+ 					   struct comedi_subdevice *s,
+ 					   struct comedi_insn *insn, unsigned int *data);
+-INT i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device *dev,
++int i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device *dev,
+ 					 struct comedi_subdevice *s,
+ 					 struct comedi_insn *insn, unsigned int *data);
+-INT i_APCI3200_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s);
+-INT i_APCI3200_InterruptHandleEos(struct comedi_device *dev);
+-INT i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI3200_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s);
++int i_APCI3200_InterruptHandleEos(struct comedi_device *dev);
++int i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				      struct comedi_cmd *cmd);
+-INT i_APCI3200_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s);
+-INT i_APCI3200_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI3200_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s);
++int i_APCI3200_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				struct comedi_insn *insn, unsigned int *data);
+ //Interrupt
+ void v_APCI3200_Interrupt(int irq, void *d);
+ int i_APCI3200_InterruptHandleEos(struct comedi_device *dev);
+ //Reset functions
+-INT i_APCI3200_Reset(struct comedi_device *dev);
++int i_APCI3200_Reset(struct comedi_device *dev);
+ 
+ int i_APCI3200_ReadCJCCalOffset(struct comedi_device *dev, unsigned int *data);
+ int i_APCI3200_ReadCJCValue(struct comedi_device *dev, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
+index 20391a91da03..59234e82e552 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
+@@ -73,7 +73,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI3501_ReadDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI3501_ReadDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+@@ -161,7 +161,7 @@ int i_APCI3501_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3501_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI3501_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp, ui_Temp1;
+@@ -248,7 +248,7 @@ INT i_APCI3501_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3501_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI3501_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+@@ -298,7 +298,7 @@ INT i_APCI3501_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3501_ConfigAnalogOutput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI3501_ConfigAnalogOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	outl(data[0],
+@@ -336,7 +336,7 @@ INT i_APCI3501_ConfigAnalogOutput(struct comedi_device * dev, struct comedi_subd
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3501_WriteAnalogOutput(struct comedi_device * dev, struct comedi_subdevice * s,
++int i_APCI3501_WriteAnalogOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0, ul_Channel_no, ul_Polarity, ul_DAC_Ready = 0;;
+@@ -410,7 +410,7 @@ INT i_APCI3501_WriteAnalogOutput(struct comedi_device * dev, struct comedi_subde
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device * dev,
++int i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
+index 51e7b66544ac..ba71f2dc760a 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
+@@ -55,29 +55,29 @@ struct comedi_lrange range_apci3501_ao = { 2, {
+ // Hardware Layer  functions for Apci3501
+ 
+ //AO
+-INT i_APCI3501_ConfigAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI3501_ConfigAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				  struct comedi_insn *insn, unsigned int *data);
+-INT i_APCI3501_WriteAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI3501_WriteAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 struct comedi_insn *insn, unsigned int *data);
+ 
+ //DI
+ // for di read
+ //INT i_APCI3501_ReadDigitalInput(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data);
+ 
+-INT i_APCI3501_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI3501_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				struct comedi_insn *insn, unsigned int *data);
+ 
+ //DO
+ int i_APCI3501_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   struct comedi_insn *insn, unsigned int *data);
+-INT i_APCI3501_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI3501_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				  struct comedi_insn *insn, unsigned int *data);
+-INT i_APCI3501_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
++int i_APCI3501_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 struct comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+ // timer value is passed as u seconds
+-INT i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device *dev,
++int i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device *dev,
+ 					  struct comedi_subdevice *s,
+ 					  struct comedi_insn *insn, unsigned int *data);
+ int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+index 6914637992a0..f7745278e53a 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+@@ -54,7 +54,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     : INT   i_APCI3XXX_TestConversionStarted                 |
++| Function Name     : int   i_APCI3XXX_TestConversionStarted                 |
+ |                          (struct comedi_device    *dev)                           |
+ +----------------------------------------------------------------------------+
+ | Task                Test if any conversion started                         |
+@@ -79,7 +79,7 @@ int i_APCI3XXX_TestConversionStarted(struct comedi_device * dev)
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     : INT   i_APCI3XXX_AnalogInputConfigOperatingMode        |
++| Function Name     : int   i_APCI3XXX_AnalogInputConfigOperatingMode        |
+ |                          (struct comedi_device    *dev,                           |
+ |                           struct comedi_subdevice *s,                             |
+ |                           struct comedi_insn      *insn,                          |
+@@ -108,7 +108,7 @@ int i_APCI3XXX_TestConversionStarted(struct comedi_device * dev)
+ int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = insn->n;
++	int i_ReturnValue = insn->n;
+ 	unsigned char b_TimeBase = 0;
+ 	unsigned char b_SingleDiff = 0;
+ 	DWORD dw_ReloadValue = 0;
+@@ -273,7 +273,7 @@ int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     : INT   i_APCI3XXX_InsnConfigAnalogInput                 |
++| Function Name     : int   i_APCI3XXX_InsnConfigAnalogInput                 |
+ |                          (struct comedi_device    *dev,                           |
+ |                           struct comedi_subdevice *s,                             |
+ |                           struct comedi_insn      *insn,                          |
+@@ -298,7 +298,7 @@ int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device * dev,
+ int i_APCI3XXX_InsnConfigAnalogInput(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = insn->n;
++	int i_ReturnValue = insn->n;
+ 
+ 	/************************/
+ 	/* Test the buffer size */
+@@ -331,7 +331,7 @@ int i_APCI3XXX_InsnConfigAnalogInput(struct comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     : INT   i_APCI3XXX_InsnReadAnalogInput                   |
++| Function Name     : int   i_APCI3XXX_InsnReadAnalogInput                   |
+ |                          (struct comedi_device    *dev,                           |
+ |                           struct comedi_subdevice *s,                             |
+ |                           struct comedi_insn      *insn,                          |
+@@ -358,7 +358,7 @@ int i_APCI3XXX_InsnConfigAnalogInput(struct comedi_device * dev,
+ int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = insn->n;
++	int i_ReturnValue = insn->n;
+ 	unsigned char b_Configuration = (unsigned char) CR_RANGE(insn->chanspec);
+ 	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
+ 	DWORD dw_Temp = 0;
+@@ -662,7 +662,7 @@ void v_APCI3XXX_Interrupt(int irq, void *d)
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     : INT   i_APCI3XXX_InsnWriteAnalogOutput                 |
++| Function Name     : int   i_APCI3XXX_InsnWriteAnalogOutput                 |
+ |                          (struct comedi_device    *dev,                           |
+ |                           struct comedi_subdevice *s,                             |
+ |                           struct comedi_insn      *insn,                          |
+@@ -690,7 +690,7 @@ int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device * dev,
+ 	unsigned char b_Range = (unsigned char) CR_RANGE(insn->chanspec);
+ 	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
+ 	DWORD dw_Status = 0;
+-	INT i_ReturnValue = insn->n;
++	int i_ReturnValue = insn->n;
+ 
+ 	/************************/
+ 	/* Test the buffer size */
+@@ -768,7 +768,7 @@ int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     : INT   i_APCI3XXX_InsnConfigInitTTLIO                   |
++| Function Name     : int   i_APCI3XXX_InsnConfigInitTTLIO                   |
+ |                          (struct comedi_device    *dev,                           |
+ |                           struct comedi_subdevice *s,                             |
+ |                           struct comedi_insn      *insn,                          |
+@@ -794,7 +794,7 @@ int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device * dev,
+ int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = insn->n;
++	int i_ReturnValue = insn->n;
+ 	unsigned char b_Command = 0;
+ 
+ 	/************************/
+@@ -899,7 +899,7 @@ int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     : INT     i_APCI3XXX_InsnBitsTTLIO                       |
++| Function Name     : int     i_APCI3XXX_InsnBitsTTLIO                       |
+ |                          (struct comedi_device    *dev,                           |
+ |                           struct comedi_subdevice *s,                             |
+ |                           struct comedi_insn      *insn,                          |
+@@ -922,7 +922,7 @@ int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = insn->n;
++	int i_ReturnValue = insn->n;
+ 	unsigned char b_ChannelCpt = 0;
+ 	DWORD dw_ChannelMask = 0;
+ 	DWORD dw_BitMask = 0;
+@@ -1056,7 +1056,7 @@ int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     : INT i_APCI3XXX_InsnReadTTLIO                           |
++| Function Name     : int i_APCI3XXX_InsnReadTTLIO                           |
+ |                          (struct comedi_device    *dev,                           |
+ |                           struct comedi_subdevice *s,                             |
+ |                           struct comedi_insn      *insn,                          |
+@@ -1078,7 +1078,7 @@ int i_APCI3XXX_InsnReadTTLIO(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
+-	INT i_ReturnValue = insn->n;
++	int i_ReturnValue = insn->n;
+ 	unsigned int *pls_ReadData = data;
+ 
+ 	/************************/
+@@ -1168,7 +1168,7 @@ int i_APCI3XXX_InsnReadTTLIO(struct comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     : INT     i_APCI3XXX_InsnWriteTTLIO                      |
++| Function Name     : int     i_APCI3XXX_InsnWriteTTLIO                      |
+ |                          (struct comedi_device    *dev,                           |
+ |                           struct comedi_subdevice *s,                             |
+ |                           struct comedi_insn      *insn,                          |
+@@ -1190,7 +1190,7 @@ int i_APCI3XXX_InsnReadTTLIO(struct comedi_device * dev,
+ int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = insn->n;
++	int i_ReturnValue = insn->n;
+ 	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
+ 	unsigned char b_State = 0;
+ 	DWORD dw_Status = 0;
+@@ -1301,7 +1301,7 @@ int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device * dev,
+ int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = insn->n;
++	int i_ReturnValue = insn->n;
+ 	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
+ 	DWORD dw_Temp = 0;
+ 
+@@ -1359,7 +1359,7 @@ int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device * dev,
+ int i_APCI3XXX_InsnBitsDigitalInput(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = insn->n;
++	int i_ReturnValue = insn->n;
+ 	DWORD dw_Temp = 0;
+ 
+ 	/************************/
+@@ -1412,7 +1412,7 @@ int i_APCI3XXX_InsnBitsDigitalInput(struct comedi_device * dev,
+ int i_APCI3XXX_InsnBitsDigitalOutput(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = insn->n;
++	int i_ReturnValue = insn->n;
+ 	unsigned char b_ChannelCpt = 0;
+ 	DWORD dw_ChannelMask = 0;
+ 	DWORD dw_BitMask = 0;
+@@ -1508,7 +1508,7 @@ int i_APCI3XXX_InsnBitsDigitalOutput(struct comedi_device * dev,
+ int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = insn->n;
++	int i_ReturnValue = insn->n;
+ 	unsigned char b_Channel = CR_CHAN(insn->chanspec);
+ 	unsigned char b_State = 0;
+ 	DWORD dw_Status = 0;
+@@ -1583,7 +1583,7 @@ int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device * dev,
+ int i_APCI3XXX_InsnReadDigitalOutput(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	INT i_ReturnValue = insn->n;
++	int i_ReturnValue = insn->n;
+ 	unsigned char b_Channel = CR_CHAN(insn->chanspec);
+ 	DWORD dw_Status = 0;
+ 

commit babf0ede302697486a6633e72d051bbb8e31e2b2
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:04:58 2009 -0400
+
+    Staging: comedi: Remove WORD and *PWORD typedefs in addi-data
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
+index 007ae8c05d3c..3ea2f0756095 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
+@@ -52,23 +52,23 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*| Function   Name   : INT i_AddiHeaderRW_ReadEeprom                          |*/
+ /*|                               (INT    i_NbOfWordsToRead,                   |*/
+ /*|                                DWORD dw_PCIBoardEepromAddress,             |*/
+-/*|                                WORD   w_EepromStartAddress,                |*/
+-/*|                                PWORD pw_DataRead)                          |*/
++/*|                                unsigned short   w_EepromStartAddress,                |*/
++/*|                                unsigned short * pw_DataRead)                          |*/
+ /*+----------------------------------------------------------------------------+*/
+ /*| Task              : Read word from the 5920 eeprom.                        |*/
+ /*+----------------------------------------------------------------------------+*/
+ /*| Input Parameters  : INT    i_NbOfWordsToRead : Nbr. of word to read        |*/
+ /*|                     DWORD dw_PCIBoardEepromAddress : Address of the eeprom |*/
+-/*|                     WORD   w_EepromStartAddress : Eeprom strat address     |*/
++/*|                     unsigned short   w_EepromStartAddress : Eeprom strat address     |*/
+ /*+----------------------------------------------------------------------------+*/
+-/*| Output Parameters : PWORD pw_DataRead : Read data                          |*/
++/*| Output Parameters : unsigned short * pw_DataRead : Read data                          |*/
+ /*+----------------------------------------------------------------------------+*/
+ /*| Return Value      : -                                                      |*/
+ /*+----------------------------------------------------------------------------+*/
+ 
+ INT i_AddiHeaderRW_ReadEeprom(INT i_NbOfWordsToRead,
+ 	DWORD dw_PCIBoardEepromAddress,
+-	WORD w_EepromStartAddress, PWORD pw_DataRead)
++	unsigned short w_EepromStartAddress, unsigned short * pw_DataRead)
+ {
+ 	DWORD dw_eeprom_busy = 0;
+ 	INT i_Counter = 0;
+@@ -79,7 +79,7 @@ INT i_AddiHeaderRW_ReadEeprom(INT i_NbOfWordsToRead,
+ 	unsigned char b_ReadHighByte = 0;
+ 	unsigned char b_SelectedAddressLow = 0;
+ 	unsigned char b_SelectedAddressHigh = 0;
+-	WORD w_ReadWord = 0;
++	unsigned short w_ReadWord = 0;
+ 
+ 	for (i_WordCounter = 0; i_WordCounter < i_NbOfWordsToRead;
+ 		i_WordCounter++) {
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h
+index 9ae56bc3adad..4a0f3c1ef03c 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h
+@@ -24,4 +24,4 @@
+ 
+ INT i_AddiHeaderRW_ReadEeprom(INT i_NbOfWordsToRead,
+ 			      DWORD dw_PCIBoardEepromAddress,
+-			      WORD w_EepromStartAddress, PWORD pw_DataRead);
++			      unsigned short w_EepromStartAddress, unsigned short * pw_DataRead);
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+index 618c69b6838d..724e030d83e2 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+@@ -3049,8 +3049,8 @@ static irqreturn_t v_ADDI_Interrupt(int irq, void *d PT_REGS_ARG)
+ static int i_ADDIDATA_InsnReadEeprom(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	WORD w_Data;
+-	WORD w_Address;
++	unsigned short w_Data;
++	unsigned short w_Address;
+ 	w_Address = CR_CHAN(insn->chanspec);	// address to be read as 0,1,2,3...255
+ 
+ 	w_Data = w_EepromReadWord(devpriv->i_IobaseAmcc,
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+index 3dd7c98b1de5..1b8e2b1b5564 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+@@ -37,7 +37,6 @@
+ #define SUCCESS	1
+ 
+ /* variable type definition */
+-typedef unsigned short WORD, *PWORD;
+ typedef int INT, *PINT;;
+ typedef unsigned int UINT, *PUINT;
+ typedef int LONG, *PLONG;		/* 32-bit */
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+index 5cab63836e4c..c0372bee9619 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+@@ -51,8 +51,6 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ #define EE76_CMD_LEN    	13	// bits in instructions
+ #define EE_READ         	0x0180	// 01 1000 0000 read instruction
+ 
+-#define	WORD				unsigned short
+-#define PWORD				unsigned short *
+ #define PDWORD				unsigned int  *
+ 
+ #ifndef DWORD
+@@ -69,49 +67,49 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ 
+ struct str_Functionality {
+ 	unsigned char b_Type;
+-	WORD w_Address;
++	unsigned short w_Address;
+ };
+ 
+ typedef struct {
+-	WORD w_HeaderSize;
++	unsigned short w_HeaderSize;
+ 	unsigned char b_Nfunctions;
+ 	struct str_Functionality s_Functions[7];
+ } str_MainHeader;
+ 
+ typedef struct {
+-	WORD w_Nchannel;
++	unsigned short w_Nchannel;
+ 	unsigned char b_Interruptible;
+-	WORD w_NinterruptLogic;
++	unsigned short w_NinterruptLogic;
+ } str_DigitalInputHeader;
+ 
+ typedef struct {
+-	WORD w_Nchannel;
++	unsigned short w_Nchannel;
+ } str_DigitalOutputHeader;
+ 
+ // used for timer as well as watchdog
+ 
+ typedef struct {
+-	WORD w_HeaderSize;
++	unsigned short w_HeaderSize;
+ 	unsigned char b_Resolution;
+ 	unsigned char b_Mode;		// in case of Watchdog it is functionality
+-	WORD w_MinTiming;
++	unsigned short w_MinTiming;
+ 	unsigned char b_TimeBase;
+ } str_TimerDetails;
+ typedef struct {
+ 
+-	WORD w_Ntimer;
++	unsigned short w_Ntimer;
+ 	str_TimerDetails s_TimerDetails[4];	//  supports 4 timers
+ } str_TimerMainHeader;
+ 
+ typedef struct {
+-	WORD w_Nchannel;
++	unsigned short w_Nchannel;
+ 	unsigned char b_Resolution;
+ } str_AnalogOutputHeader;
+ 
+ typedef struct {
+-	WORD w_Nchannel;
+-	WORD w_MinConvertTiming;
+-	WORD w_MinDelayTiming;
++	unsigned short w_Nchannel;
++	unsigned short w_MinConvertTiming;
++	unsigned short w_MinDelayTiming;
+ 	unsigned char b_HasDma;
+ 	unsigned char b_Resolution;
+ } str_AnalogInputHeader;
+@@ -120,55 +118,55 @@ typedef struct {
+ 		/*            Read Header Functions              */
+ 		/*****************************************/
+ 
+-INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress,
++INT i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, struct comedi_device *dev);
+ 
+-INT i_EepromReadDigitalInputHeader(WORD w_PCIBoardEepromAddress,
+-	char *pc_PCIChipInformation, WORD w_Address,
++INT i_EepromReadDigitalInputHeader(unsigned short w_PCIBoardEepromAddress,
++	char *pc_PCIChipInformation, unsigned short w_Address,
+ 	str_DigitalInputHeader * s_Header);
+ 
+-INT i_EepromReadDigitalOutputHeader(WORD w_PCIBoardEepromAddress,
+-	char *pc_PCIChipInformation, WORD w_Address,
++INT i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress,
++	char *pc_PCIChipInformation, unsigned short w_Address,
+ 	str_DigitalOutputHeader * s_Header);
+ 
+-INT i_EepromReadTimerHeader(WORD w_PCIBoardEepromAddress,
+-	char *pc_PCIChipInformation, WORD w_Address,
++INT i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
++	char *pc_PCIChipInformation, unsigned short w_Address,
+ 	str_TimerMainHeader * s_Header);
+ 
+-INT i_EepromReadAnlogOutputHeader(WORD w_PCIBoardEepromAddress,
+-	char *pc_PCIChipInformation, WORD w_Address,
++INT i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
++	char *pc_PCIChipInformation, unsigned short w_Address,
+ 	str_AnalogOutputHeader * s_Header);
+ 
+-INT i_EepromReadAnlogInputHeader(WORD w_PCIBoardEepromAddress,
+-	char *pc_PCIChipInformation, WORD w_Address,
++INT i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress,
++	char *pc_PCIChipInformation, unsigned short w_Address,
+ 	str_AnalogInputHeader * s_Header);
+ 
+ 		/******************************************/
+ 		/*      Eeprom Specific Functions                         */
+ 		/******************************************/
+-WORD w_EepromReadWord(WORD w_PCIBoardEepromAddress, char *pc_PCIChipInformation,
+-	WORD w_EepromStartAddress);
+-void v_EepromWaitBusy(WORD w_PCIBoardEepromAddress);
++unsigned short w_EepromReadWord(unsigned short w_PCIBoardEepromAddress, char *pc_PCIChipInformation,
++	unsigned short w_EepromStartAddress);
++void v_EepromWaitBusy(unsigned short w_PCIBoardEepromAddress);
+ void v_EepromClock76(DWORD dw_Address, DWORD dw_RegisterValue);
+-void v_EepromWaitBusy(WORD w_PCIBoardEepromAddress);
++void v_EepromWaitBusy(unsigned short w_PCIBoardEepromAddress);
+ void v_EepromSendCommand76(DWORD dw_Address, DWORD dw_EepromCommand,
+ 	unsigned char b_DataLengthInBits);
+-void v_EepromCs76Read(DWORD dw_Address, WORD w_offset, PWORD pw_Value);
++void v_EepromCs76Read(DWORD dw_Address, unsigned short w_offset, unsigned short * pw_Value);
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function   Name   : WORD w_EepromReadWord                                  |
+-|				(WORD	w_PCIBoardEepromAddress,             		 |
++| Function   Name   : unsigned short w_EepromReadWord                                  |
++|				(unsigned short	w_PCIBoardEepromAddress,             		 |
+ |				 char *	pc_PCIChipInformation,               		 |
+-|				 WORD   w_EepromStartAddress)                		 |
++|				 unsigned short   w_EepromStartAddress)                		 |
+ +----------------------------------------------------------------------------+
+ | Task              : Read from eepromn a word                               |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : WORD w_PCIBoardEepromAddress : PCI eeprom address      |
++| Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
+ |																	 |
+ |		      char *pc_PCIChipInformation  : PCI Chip Type.          |
+ |																	 |
+-|		      WORD w_EepromStartAddress    : Selected eeprom address |
++|		      unsigned short w_EepromStartAddress    : Selected eeprom address |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+ +----------------------------------------------------------------------------+
+@@ -176,8 +174,8 @@ void v_EepromCs76Read(DWORD dw_Address, WORD w_offset, PWORD pw_Value);
+ +----------------------------------------------------------------------------+
+ */
+ 
+-WORD w_EepromReadWord(WORD w_PCIBoardEepromAddress, char *pc_PCIChipInformation,
+-	WORD w_EepromStartAddress)
++unsigned short w_EepromReadWord(unsigned short w_PCIBoardEepromAddress, char *pc_PCIChipInformation,
++	unsigned short w_EepromStartAddress)
+ {
+ 
+ 	unsigned char b_Counter = 0;
+@@ -192,7 +190,7 @@ WORD w_EepromReadWord(WORD w_PCIBoardEepromAddress, char *pc_PCIChipInformation,
+ 
+ 	unsigned char b_SelectedAddressHigh = 0;
+ 
+-	WORD w_ReadWord = 0;
++	unsigned short w_ReadWord = 0;
+ 
+ 	/**************************/
+ 
+@@ -331,7 +329,7 @@ WORD w_EepromReadWord(WORD w_PCIBoardEepromAddress, char *pc_PCIChipInformation,
+ 
+ 		}		// for (b_Counter=0; b_Counter<2; b_Counter++)
+ 
+-		w_ReadWord = (b_ReadLowByte | (((WORD) b_ReadHighByte) * 256));
++		w_ReadWord = (b_ReadLowByte | (((unsigned short) b_ReadHighByte) * 256));
+ 
+ 	}			// end of if ((!strcmp(pc_PCIChipInformation, "S5920")) || (!strcmp(pc_PCIChipInformation, "S5933")))
+ 
+@@ -359,7 +357,7 @@ WORD w_EepromReadWord(WORD w_PCIBoardEepromAddress, char *pc_PCIChipInformation,
+ 
+ | Function   Name   : void v_EepromWaitBusy                                  |
+ 
+-|			(WORD	w_PCIBoardEepromAddress)                    	 |
++|			(unsigned short	w_PCIBoardEepromAddress)                    	 |
+ 
+ +----------------------------------------------------------------------------+
+ 
+@@ -367,7 +365,7 @@ WORD w_EepromReadWord(WORD w_PCIBoardEepromAddress, char *pc_PCIChipInformation,
+ 
+ +----------------------------------------------------------------------------+
+ 
+-| Input Parameters  : WORD w_PCIBoardEepromAddress : PCI eeprom base address |
++| Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom base address |
+ 
+ +----------------------------------------------------------------------------+
+ 
+@@ -381,7 +379,7 @@ WORD w_EepromReadWord(WORD w_PCIBoardEepromAddress, char *pc_PCIChipInformation,
+ 
+ */
+ 
+-void v_EepromWaitBusy(WORD w_PCIBoardEepromAddress)
++void v_EepromWaitBusy(unsigned short w_PCIBoardEepromAddress)
+ {
+ 
+ 	unsigned char b_EepromBusy = 0;
+@@ -403,7 +401,7 @@ void v_EepromWaitBusy(WORD w_PCIBoardEepromAddress)
+ 
+ 		/*      the operator register is AMCC_OP_REG_MCSR+3 */
+ 
+-		/*      WORD read  EEPROM=0x8000 andAMCC_OP_REG_MCSR+2                  */
++		/*      unsigned short read  EEPROM=0x8000 andAMCC_OP_REG_MCSR+2                  */
+ 
+ 		/*      DWORD read  EEPROM=0x80000000 and AMCC_OP_REG_MCSR */
+ 
+@@ -625,9 +623,9 @@ void v_EepromSendCommand76(DWORD dw_Address, DWORD dw_EepromCommand,
+ 
+ | Function   Name   : void v_EepromCs76Read(DWORD dw_Address,                     |
+ 
+-|					   WORD    w_offset,                      			  |
++|					   unsigned short    w_offset,                      			  |
+ 
+-|					   PWORD   pw_Value)                      			  |
++|					   unsigned short *   pw_Value)                      			  |
+ 
+ +---------------------------------------------------------------------------------+
+ 
+@@ -637,9 +635,9 @@ void v_EepromSendCommand76(DWORD dw_Address, DWORD dw_EepromCommand,
+ 
+ | Input Parameters  : DWORD dw_Address : PCI eeprom base address                  |
+ 
+-|		      WORD    w_offset : Offset of the adress to read             |
++|		      unsigned short    w_offset : Offset of the adress to read             |
+ 
+-|		      PWORD   pw_Value : PCI eeprom 16 bit read value.            |
++|		      unsigned short *   pw_Value : PCI eeprom 16 bit read value.            |
+ 
+ +---------------------------------------------------------------------------------+
+ 
+@@ -653,7 +651,7 @@ void v_EepromSendCommand76(DWORD dw_Address, DWORD dw_EepromCommand,
+ 
+ */
+ 
+-void v_EepromCs76Read(DWORD dw_Address, WORD w_offset, PWORD pw_Value)
++void v_EepromCs76Read(DWORD dw_Address, unsigned short w_offset, unsigned short * pw_Value)
+ {
+ 
+         char c_BitPos = 0;
+@@ -786,12 +784,12 @@ void v_EepromCs76Read(DWORD dw_Address, WORD w_offset, PWORD pw_Value)
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name  : INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress,  |
++| Function Name  : INT i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,  |
+ |				char *	pc_PCIChipInformation,struct comedi_device *dev)    |
+ +----------------------------------------------------------------------------+
+ | Task              : Read from eeprom Main Header                           |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : WORD w_PCIBoardEepromAddress : PCI eeprom address      |
++| Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
+ |																	 |
+ |		      char *pc_PCIChipInformation  : PCI Chip Type.          |
+ |																	 |
+@@ -804,10 +802,10 @@ void v_EepromCs76Read(DWORD dw_Address, WORD w_offset, PWORD pw_Value)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress,
++INT i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
+ 	char *pc_PCIChipInformation, struct comedi_device *dev)
+ {
+-	WORD w_Temp, i, w_Count = 0;
++	unsigned short w_Temp, i, w_Count = 0;
+ 	UINT ui_Temp;
+ 	str_MainHeader s_MainHeader;
+ 	str_DigitalInputHeader s_DigitalInputHeader;
+@@ -920,14 +918,14 @@ INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name  : INT i_EepromReadDigitalInputHeader(WORD 					 |
++| Function Name  : INT i_EepromReadDigitalInputHeader(unsigned short 					 |
+ |			w_PCIBoardEepromAddress,char *pc_PCIChipInformation,	 |
+-|			WORD w_Address,str_DigitalInputHeader *s_Header)		 |
++|			unsigned short w_Address,str_DigitalInputHeader *s_Header)		 |
+ |																	 |
+ +----------------------------------------------------------------------------+
+ | Task              : Read Digital Input Header                              |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : WORD w_PCIBoardEepromAddress : PCI eeprom address      |
++| Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
+ |																	 |
+ |		      char *pc_PCIChipInformation  : PCI Chip Type.          |
+ |																	 |
+@@ -939,11 +937,11 @@ INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress,
+ | Return Value      : 0							                             |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_EepromReadDigitalInputHeader(WORD w_PCIBoardEepromAddress,
+-	char *pc_PCIChipInformation, WORD w_Address,
++INT i_EepromReadDigitalInputHeader(unsigned short w_PCIBoardEepromAddress,
++	char *pc_PCIChipInformation, unsigned short w_Address,
+ 	str_DigitalInputHeader * s_Header)
+ {
+-	WORD w_Temp;
++	unsigned short w_Temp;
+ 
+ 	// read nbr of channels
+ 	s_Header->w_Nchannel =
+@@ -965,14 +963,14 @@ INT i_EepromReadDigitalInputHeader(WORD w_PCIBoardEepromAddress,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name  : INT i_EepromReadDigitalOutputHeader(WORD 				 |
++| Function Name  : INT i_EepromReadDigitalOutputHeader(unsigned short 				 |
+ |			w_PCIBoardEepromAddress,char *pc_PCIChipInformation,	 |
+-|			WORD w_Address,str_DigitalOutputHeader *s_Header)	     |
++|			unsigned short w_Address,str_DigitalOutputHeader *s_Header)	     |
+ |																	 |
+ +----------------------------------------------------------------------------+
+ | Task              : Read Digital Output Header                             |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : WORD w_PCIBoardEepromAddress : PCI eeprom address      |
++| Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
+ |																	 |
+ |		      char *pc_PCIChipInformation  : PCI Chip Type.          |
+ |																	 |
+@@ -984,8 +982,8 @@ INT i_EepromReadDigitalInputHeader(WORD w_PCIBoardEepromAddress,
+ | Return Value      : 0							                             |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_EepromReadDigitalOutputHeader(WORD w_PCIBoardEepromAddress,
+-	char *pc_PCIChipInformation, WORD w_Address,
++INT i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress,
++	char *pc_PCIChipInformation, unsigned short w_Address,
+ 	str_DigitalOutputHeader * s_Header)
+ {
+ // Read Nbr channels
+@@ -997,13 +995,13 @@ INT i_EepromReadDigitalOutputHeader(WORD w_PCIBoardEepromAddress,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name  : INT i_EepromReadTimerHeader(WORD w_PCIBoardEepromAddress, |
++| Function Name  : INT i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress, |
+ |			char *pc_PCIChipInformation,WORD w_Address,				 |
+ |			str_TimerMainHeader *s_Header)							 |
+ +----------------------------------------------------------------------------+
+ | Task              : Read Timer or Watchdog Header                          |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : WORD w_PCIBoardEepromAddress : PCI eeprom address      |
++| Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
+ |																	 |
+ |		      char *pc_PCIChipInformation  : PCI Chip Type.          |
+ |																	 |
+@@ -1015,12 +1013,12 @@ INT i_EepromReadDigitalOutputHeader(WORD w_PCIBoardEepromAddress,
+ | Return Value      : 0							                             |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_EepromReadTimerHeader(WORD w_PCIBoardEepromAddress,
+-	char *pc_PCIChipInformation, WORD w_Address,
++INT i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
++	char *pc_PCIChipInformation, unsigned short w_Address,
+ 	str_TimerMainHeader * s_Header)
+ {
+ 
+-	WORD i, w_Size = 0, w_Temp;
++	unsigned short i, w_Size = 0, w_Temp;
+ 
+ //Read No of Timer
+ 	s_Header->w_Ntimer =
+@@ -1062,13 +1060,13 @@ INT i_EepromReadTimerHeader(WORD w_PCIBoardEepromAddress,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name  : INT i_EepromReadAnlogOutputHeader(WORD 					 |
++| Function Name  : INT i_EepromReadAnlogOutputHeader(unsigned short 					 |
+ |			w_PCIBoardEepromAddress,char *pc_PCIChipInformation,	 |
+-|			WORD w_Address,str_AnalogOutputHeader *s_Header)         |
++|			unsigned short w_Address,str_AnalogOutputHeader *s_Header)         |
+ +----------------------------------------------------------------------------+
+ | Task              : Read Nalog Output  Header                              |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : WORD w_PCIBoardEepromAddress : PCI eeprom address      |
++| Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
+ |																	 |
+ |		      char *pc_PCIChipInformation  : PCI Chip Type.          |
+ |																	 |
+@@ -1081,11 +1079,11 @@ INT i_EepromReadTimerHeader(WORD w_PCIBoardEepromAddress,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_EepromReadAnlogOutputHeader(WORD w_PCIBoardEepromAddress,
+-	char *pc_PCIChipInformation, WORD w_Address,
++INT i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
++	char *pc_PCIChipInformation, unsigned short w_Address,
+ 	str_AnalogOutputHeader * s_Header)
+ {
+-	WORD w_Temp;
++	unsigned short w_Temp;
+ 	// No of channels for 1st hard component
+ 	w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+ 		pc_PCIChipInformation, 0x100 + w_Address + 10);
+@@ -1099,13 +1097,13 @@ INT i_EepromReadAnlogOutputHeader(WORD w_PCIBoardEepromAddress,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name  : INT i_EepromReadAnlogInputHeader(WORD 					 |
++| Function Name  : INT i_EepromReadAnlogInputHeader(unsigned short 					 |
+ |			w_PCIBoardEepromAddress,char *pc_PCIChipInformation,     |
+-|			WORD w_Address,str_AnalogInputHeader *s_Header)          |
++|			unsigned short w_Address,str_AnalogInputHeader *s_Header)          |
+ +----------------------------------------------------------------------------+
+ | Task              : Read Nalog Output  Header                              |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : WORD w_PCIBoardEepromAddress : PCI eeprom address      |
++| Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
+ |																	 |
+ |		      char *pc_PCIChipInformation  : PCI Chip Type.          |
+ |																	 |
+@@ -1119,11 +1117,11 @@ INT i_EepromReadAnlogOutputHeader(WORD w_PCIBoardEepromAddress,
+ */
+ 
+ // Reads only for ONE  hardware component
+-INT i_EepromReadAnlogInputHeader(WORD w_PCIBoardEepromAddress,
+-	char *pc_PCIChipInformation, WORD w_Address,
++INT i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress,
++	char *pc_PCIChipInformation, unsigned short w_Address,
+ 	str_AnalogInputHeader * s_Header)
+ {
+-	WORD w_Temp, w_Offset;
++	unsigned short w_Temp, w_Offset;
+ 	w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+ 		pc_PCIChipInformation, 0x100 + w_Address + 10);
+ 	s_Header->w_Nchannel = (w_Temp >> 4) & 0x03FF;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+index 47b859ef8f1f..b06ff1ed345f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+@@ -952,7 +952,7 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 			outb(devpriv->b_TimerSelectMode,
+ 				dev->iobase + APCI3120_TIMER_CRT1);
+ 
+-			//Writing LOW WORD
++			//Writing LOW unsigned short
+ 			b_Tmp = ((devpriv->
+ 					b_DigitalOutputRegister) & 0xF0) |
+ 				APCI3120_SELECT_TIMER_2_LOW_WORD;
+@@ -960,7 +960,7 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 			outw(LOWORD(ui_TimerValue2),
+ 				dev->iobase + APCI3120_TIMER_VALUE);
+ 
+-			//Writing HIGH WORD
++			//Writing HIGH unsigned short
+ 			b_Tmp = ((devpriv->
+ 					b_DigitalOutputRegister) & 0xF0) |
+ 				APCI3120_SELECT_TIMER_2_HIGH_WORD;
+@@ -2027,12 +2027,12 @@ int i_APCI3120_InsnConfigTimer(struct comedi_device * dev, struct comedi_subdevi
+ 		outb(devpriv->b_TimerSelectMode,
+ 			devpriv->iobase + APCI3120_TIMER_CRT1);
+ 
+-		//Configure the timer 2 for writing the LOW WORD of timer is Delay value
++		//Configure the timer 2 for writing the LOW unsigned short of timer is Delay value
+ 		//You must make a b_tmp variable with DigitalOutPutRegister because at Address_1+APCI3120_TIMER_CRT0
+ 		//you can set the digital output and configure the timer 2,and if you don't make this, digital output
+ 		//are erase (Set to 0)
+ 
+-		//Writing LOW WORD
++		//Writing LOW unsigned short
+ 		b_Tmp = ((devpriv->
+ 				b_DigitalOutputRegister) & 0xF0) |
+ 			APCI3120_SELECT_TIMER_2_LOW_WORD;
+@@ -2040,7 +2040,7 @@ int i_APCI3120_InsnConfigTimer(struct comedi_device * dev, struct comedi_subdevi
+ 		outw(LOWORD(ui_Timervalue2),
+ 			devpriv->iobase + APCI3120_TIMER_VALUE);
+ 
+-		//Writing HIGH WORD
++		//Writing HIGH unsigned short
+ 		b_Tmp = ((devpriv->
+ 				b_DigitalOutputRegister) & 0xF0) |
+ 			APCI3120_SELECT_TIMER_2_HIGH_WORD;
+@@ -2061,12 +2061,12 @@ int i_APCI3120_InsnConfigTimer(struct comedi_device * dev, struct comedi_subdevi
+ 		outb(devpriv->b_TimerSelectMode,
+ 			devpriv->iobase + APCI3120_TIMER_CRT1);
+ 
+-		//Configure the timer 2 for writing the LOW WORD of timer is Delay value
++		//Configure the timer 2 for writing the LOW unsigned short of timer is Delay value
+ 		//You must make a b_tmp variable with DigitalOutPutRegister because at Address_1+APCI3120_TIMER_CRT0
+ 		//you can set the digital output and configure the timer 2,and if you don't make this, digital output
+ 		//are erase (Set to 0)
+ 
+-		//Writing LOW WORD
++		//Writing LOW unsigned short
+ 		b_Tmp = ((devpriv->
+ 				b_DigitalOutputRegister) & 0xF0) |
+ 			APCI3120_SELECT_TIMER_2_LOW_WORD;
+@@ -2074,7 +2074,7 @@ int i_APCI3120_InsnConfigTimer(struct comedi_device * dev, struct comedi_subdevi
+ 		outw(LOWORD(ui_Timervalue2),
+ 			devpriv->iobase + APCI3120_TIMER_VALUE);
+ 
+-		//Writing HIGH WORD
++		//Writing HIGH unsigned short
+ 		b_Tmp = ((devpriv->
+ 				b_DigitalOutputRegister) & 0xF0) |
+ 			APCI3120_SELECT_TIMER_2_HIGH_WORD;
+@@ -2256,7 +2256,7 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device * dev, struct comedi_subdevic
+ 			//Calculate the time value to set in the timer
+ 			ui_Timervalue2 = ui_Timervalue2 / 70;
+ 		}
+-		//Writing LOW WORD
++		//Writing LOW unsigned short
+ 		b_Tmp = ((devpriv->
+ 				b_DigitalOutputRegister) & 0xF0) |
+ 			APCI3120_SELECT_TIMER_2_LOW_WORD;
+@@ -2265,7 +2265,7 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device * dev, struct comedi_subdevic
+ 		outw(LOWORD(ui_Timervalue2),
+ 			devpriv->iobase + APCI3120_TIMER_VALUE);
+ 
+-		//Writing HIGH WORD
++		//Writing HIGH unsigned short
+ 		b_Tmp = ((devpriv->
+ 				b_DigitalOutputRegister) & 0xF0) |
+ 			APCI3120_SELECT_TIMER_2_HIGH_WORD;
+@@ -2319,7 +2319,7 @@ int i_APCI3120_InsnReadTimer(struct comedi_device * dev, struct comedi_subdevice
+ 	//this_board->i_hwdrv_InsnReadTimer(dev,data);
+ 	if (devpriv->b_Timer2Mode == APCI3120_TIMER) {
+ 
+-		//Read the LOW WORD of Timer 2 register
++		//Read the LOW unsigned short of Timer 2 register
+ 		b_Tmp = ((devpriv->
+ 				b_DigitalOutputRegister) & 0xF0) |
+ 			APCI3120_SELECT_TIMER_2_LOW_WORD;
+@@ -2327,7 +2327,7 @@ int i_APCI3120_InsnReadTimer(struct comedi_device * dev, struct comedi_subdevice
+ 
+ 		us_TmpValue = inw(devpriv->iobase + APCI3120_TIMER_VALUE);
+ 
+-		//Read the HIGH WORD of Timer 2 register
++		//Read the HIGH unsigned short of Timer 2 register
+ 		b_Tmp = ((devpriv->
+ 				b_DigitalOutputRegister) & 0xF0) |
+ 			APCI3120_SELECT_TIMER_2_HIGH_WORD;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+index d44837c333ff..12513624a794 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+@@ -96,23 +96,23 @@ str_BoardInfos s_BoardInfos[100];	// 100 will be the max number of boards to be
+ /*| Function   Name   : INT i_AddiHeaderRW_ReadEeprom                          |*/
+ /*|                               (INT    i_NbOfWordsToRead,                   |*/
+ /*|                                DWORD dw_PCIBoardEepromAddress,             |*/
+-/*|                                WORD   w_EepromStartAddress,                |*/
+-/*|                                PWORD pw_DataRead)                          |*/
++/*|                                unsigned short   w_EepromStartAddress,                |*/
++/*|                                unsigned short * pw_DataRead)                          |*/
+ /*+----------------------------------------------------------------------------+*/
+ /*| Task              : Read word from the 5920 eeprom.                        |*/
+ /*+----------------------------------------------------------------------------+*/
+ /*| Input Parameters  : INT    i_NbOfWordsToRead : Nbr. of word to read        |*/
+ /*|                     DWORD dw_PCIBoardEepromAddress : Address of the eeprom |*/
+-/*|                     WORD   w_EepromStartAddress : Eeprom strat address     |*/
++/*|                     unsigned short   w_EepromStartAddress : Eeprom strat address     |*/
+ /*+----------------------------------------------------------------------------+*/
+-/*| Output Parameters : PWORD pw_DataRead : Read data                          |*/
++/*| Output Parameters : unsigned short * pw_DataRead : Read data                          |*/
+ /*+----------------------------------------------------------------------------+*/
+ /*| Return Value      : -                                                      |*/
+ /*+----------------------------------------------------------------------------+*/
+ 
+ INT i_AddiHeaderRW_ReadEeprom(INT i_NbOfWordsToRead,
+ 	DWORD dw_PCIBoardEepromAddress,
+-	WORD w_EepromStartAddress, PWORD pw_DataRead)
++	unsigned short w_EepromStartAddress, unsigned short * pw_DataRead)
+ {
+ 	DWORD dw_eeprom_busy = 0;
+ 	INT i_Counter = 0;
+@@ -123,7 +123,7 @@ INT i_AddiHeaderRW_ReadEeprom(INT i_NbOfWordsToRead,
+ 	unsigned char b_ReadHighByte = 0;
+ 	unsigned char b_SelectedAddressLow = 0;
+ 	unsigned char b_SelectedAddressHigh = 0;
+-	WORD w_ReadWord = 0;
++	unsigned short w_ReadWord = 0;
+ 
+ 	for (i_WordCounter = 0; i_WordCounter < i_NbOfWordsToRead;
+ 		i_WordCounter++) {
+@@ -261,22 +261,22 @@ INT i_AddiHeaderRW_ReadEeprom(INT i_NbOfWordsToRead,
+ void v_GetAPCI3200EepromCalibrationValue(DWORD dw_PCIBoardEepromAddress,
+ 	str_BoardInfos * BoardInformations)
+ {
+-	WORD w_AnalogInputMainHeaderAddress;
+-	WORD w_AnalogInputComponentAddress;
+-	WORD w_NumberOfModuls = 0;
+-	WORD w_CurrentSources[2];
+-	WORD w_ModulCounter = 0;
+-	WORD w_FirstHeaderSize = 0;
+-	WORD w_NumberOfInputs = 0;
+-	WORD w_CJCFlag = 0;
+-	WORD w_NumberOfGainValue = 0;
+-	WORD w_SingleHeaderAddress = 0;
+-	WORD w_SingleHeaderSize = 0;
+-	WORD w_Input = 0;
+-	WORD w_GainFactorAddress = 0;
+-	WORD w_GainFactorValue[2];
+-	WORD w_GainIndex = 0;
+-	WORD w_GainValue = 0;
++	unsigned short w_AnalogInputMainHeaderAddress;
++	unsigned short w_AnalogInputComponentAddress;
++	unsigned short w_NumberOfModuls = 0;
++	unsigned short w_CurrentSources[2];
++	unsigned short w_ModulCounter = 0;
++	unsigned short w_FirstHeaderSize = 0;
++	unsigned short w_NumberOfInputs = 0;
++	unsigned short w_CJCFlag = 0;
++	unsigned short w_NumberOfGainValue = 0;
++	unsigned short w_SingleHeaderAddress = 0;
++	unsigned short w_SingleHeaderSize = 0;
++	unsigned short w_Input = 0;
++	unsigned short w_GainFactorAddress = 0;
++	unsigned short w_GainFactorValue[2];
++	unsigned short w_GainIndex = 0;
++	unsigned short w_GainValue = 0;
+ 
+   /*****************************************/
+   /** Get the Analog input header address **/

commit a9fce7c9a3b796334916b216a618fd7586f10d76
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:04:52 2009 -0400
+
+    Staging: comedi: Remove USHORT and *PUSHORT typedefs in addi-data
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+index f94bd9da43cd..3dd7c98b1de5 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+@@ -37,7 +37,6 @@
+ #define SUCCESS	1
+ 
+ /* variable type definition */
+-typedef unsigned short USHORT, *PUSHORT;
+ typedef unsigned short WORD, *PWORD;
+ typedef int INT, *PINT;;
+ typedef unsigned int UINT, *PUINT;
+@@ -50,9 +49,9 @@ typedef const struct comedi_lrange *PCRANGE;
+ 
+ #define LOBYTE(W)	(unsigned char)((W) & 0xFF)
+ #define HIBYTE(W)	(unsigned char)(((W) >> 8) & 0xFF)
+-#define MAKEWORD(H, L)	(USHORT)((L) | ((H) << 8))
+-#define LOWORD(W)	(USHORT)((W) & 0xFFFF)
+-#define HIWORD(W)	(USHORT)(((W) >> 16) & 0xFFFF)
++#define MAKEWORD(H, L)	(unsigned short)((L) | ((H) << 8))
++#define LOWORD(W)	(unsigned short)((W) & 0xFFFF)
++#define HIWORD(W)	(unsigned short)(((W) >> 16) & 0xFFFF)
+ #define MAKEDWORD(H, L)	(UINT)((L) | ((H) << 16))
+ 
+ #define ADDI_ENABLE		1
+@@ -385,7 +384,7 @@ typedef struct {
+ 	UINT ui_AiDataLength;
+ 	short *AiData;	// Pointer to sample data
+ 	UINT ui_AiNbrofScans;	// number of scans to do
+-	USHORT us_UseDma;	// To use Dma or not
++	unsigned short us_UseDma;	// To use Dma or not
+ 	unsigned char b_DmaDoubleBuffer;	// we can use double buffering
+ 	UINT ui_DmaActualBuffer;	// which buffer is used now
+ 	//*UPDATE-0.7.57->0.7.68
+@@ -402,7 +401,7 @@ typedef struct {
+ 	unsigned char b_AnalogOutputChannelNbr;	// Analog input Output  Nbr
+ 	unsigned char b_TimerSelectMode;	// Contain data written at iobase + 0C
+ 	unsigned char b_ModeSelectRegister;	// Contain data written at iobase + 0E
+-	USHORT us_OutputRegister;	// Contain data written at iobase + 0
++	unsigned short us_OutputRegister;	// Contain data written at iobase + 0
+ 	unsigned char b_InterruptState;
+ 	unsigned char b_TimerInit;	// Specify if InitTimerWatchdog was load
+ 	unsigned char b_TimerStarted;	// Specify if timer 2 is running or not
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+index c1509ef2fce8..47b859ef8f1f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+@@ -148,7 +148,7 @@ int i_APCI3120_InsnConfigAnalogInput(struct comedi_device * dev, struct comedi_s
+ int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	USHORT us_ConvertTiming, us_TmpValue, i;
++	unsigned short us_ConvertTiming, us_TmpValue, i;
+ 	unsigned char b_Tmp;
+ 
+ 	// fix convertion time to 10 us
+@@ -156,7 +156,7 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_sub
+ 		printk("No timer0 Value using 10 us\n");
+ 		us_ConvertTiming = 10;
+ 	} else
+-		us_ConvertTiming = (USHORT) (devpriv->ui_EocEosConversionTime / 1000);	// nano to useconds
++		us_ConvertTiming = (unsigned short) (devpriv->ui_EocEosConversionTime / 1000);	// nano to useconds
+ 
+ 	// this_board->i_hwdrv_InsnReadAnalogInput(dev,us_ConvertTiming,insn->n,&insn->chanspec,data,insn->unused[0]);
+ 
+@@ -179,7 +179,7 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_sub
+ 		//to set in the timer
+ 
+ 		us_TmpValue =
+-			(USHORT) inw(devpriv->iobase + APCI3120_RD_STATUS);
++			(unsigned short) inw(devpriv->iobase + APCI3120_RD_STATUS);
+ 
+ 		//EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001
+ 		if ((us_TmpValue & 0x00B0) == 0x00B0
+@@ -190,7 +190,7 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_sub
+ 				((us_ConvertTiming * 12926) / 10000) - 1;
+ 		}
+ 
+-		us_TmpValue = (USHORT) devpriv->b_InterruptMode;
++		us_TmpValue = (unsigned short) devpriv->b_InterruptMode;
+ 
+ 		switch (us_TmpValue) {
+ 
+@@ -260,7 +260,7 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_sub
+ 				devpriv->iobase + APCI3120_TIMER_VALUE);
+ 
+ 			us_TmpValue =
+-				(USHORT) inw(dev->iobase + APCI3120_RD_STATUS);
++				(unsigned short) inw(dev->iobase + APCI3120_RD_STATUS);
+ 
+ 			if (devpriv->b_EocEosInterrupt == APCI3120_DISABLE) {
+ 
+@@ -714,7 +714,7 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 	UINT ui_Tmp, ui_DelayTiming = 0, ui_TimerValue1 = 0, dmalen0 =
+ 		0, dmalen1 = 0, ui_TimerValue2 =
+ 		0, ui_TimerValue0, ui_ConvertTiming;
+-	USHORT us_TmpValue;
++	unsigned short us_TmpValue;
+ 
+ 	//BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+ 	//devpriv->b_AiCyclicAcquisition=APCI3120_ENABLE;
+@@ -795,7 +795,7 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 			devpriv->pui_AiChannelList, 0))
+ 		return -EINVAL;
+ 
+-	us_TmpValue = (USHORT) inw(dev->iobase + APCI3120_RD_STATUS);
++	us_TmpValue = (unsigned short) inw(dev->iobase + APCI3120_RD_STATUS);
+ /*** EL241003 : add this section in comment because floats must not be used
+ 	 if((us_TmpValue & 0x00B0)==0x00B0)
+ 	 {
+@@ -861,7 +861,7 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 			APCI3120_SELECT_TIMER_0_WORD;
+ 		outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
+ 		//Set the convertion time
+-		outw(((USHORT) ui_TimerValue0),
++		outw(((unsigned short) ui_TimerValue0),
+ 			dev->iobase + APCI3120_TIMER_VALUE);
+ 		break;
+ 
+@@ -879,7 +879,7 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 			APCI3120_SELECT_TIMER_1_WORD;
+ 		outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
+ 		//Set the convertion time
+-		outw(((USHORT) ui_TimerValue1),
++		outw(((unsigned short) ui_TimerValue1),
+ 			dev->iobase + APCI3120_TIMER_VALUE);
+ 
+ 		// init timer0 in mode 2
+@@ -896,7 +896,7 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 		outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
+ 
+ 		//Set the convertion time
+-		outw(((USHORT) ui_TimerValue0),
++		outw(((unsigned short) ui_TimerValue0),
+ 			dev->iobase + APCI3120_TIMER_VALUE);
+ 		break;
+ 
+@@ -1422,10 +1422,10 @@ int i_APCI3120_ExttrigDisable(struct comedi_device * dev)
+ void v_APCI3120_Interrupt(int irq, void *d)
+ {
+ 	struct comedi_device *dev = d;
+-	USHORT int_daq;
++	unsigned short int_daq;
+ 
+ 	unsigned int int_amcc, ui_Check, i;
+-	USHORT us_TmpValue;
++	unsigned short us_TmpValue;
+ 	unsigned char b_DummyRead;
+ 
+ 	struct comedi_subdevice *s = dev->subdevices + 0;
+@@ -1973,7 +1973,7 @@ int i_APCI3120_InsnConfigTimer(struct comedi_device * dev, struct comedi_subdevi
+ {
+ 
+ 	UINT ui_Timervalue2;
+-	USHORT us_TmpValue;
++	unsigned short us_TmpValue;
+ 	unsigned char b_Tmp;
+ 
+ 	if (!data[1])
+@@ -1984,7 +1984,7 @@ int i_APCI3120_InsnConfigTimer(struct comedi_device * dev, struct comedi_subdevi
+ 	ui_Timervalue2 = data[1] / 1000;	// convert nano seconds  to u seconds
+ 
+ 	//this_board->i_hwdrv_InsnConfigTimer(dev, ui_Timervalue2,(unsigned char)data[0]);
+-	us_TmpValue = (USHORT) inw(devpriv->iobase + APCI3120_RD_STATUS);
++	us_TmpValue = (unsigned short) inw(devpriv->iobase + APCI3120_RD_STATUS);
+ 
+ 	//EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001
+ 	// and calculate the time value to set in the timer
+@@ -2124,7 +2124,7 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device * dev, struct comedi_subdevic
+ {
+ 
+ 	UINT ui_Timervalue2 = 0;
+-	USHORT us_TmpValue;
++	unsigned short us_TmpValue;
+ 	unsigned char b_Tmp;
+ 
+ 	if ((devpriv->b_Timer2Mode != APCI3120_WATCHDOG)
+@@ -2244,7 +2244,7 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device * dev, struct comedi_subdevic
+ 		}
+ 		// ui_Timervalue2=data[1]; // passed as argument
+ 		us_TmpValue =
+-			(USHORT) inw(devpriv->iobase + APCI3120_RD_STATUS);
++			(unsigned short) inw(devpriv->iobase + APCI3120_RD_STATUS);
+ 
+ 		//EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001
+ 		// and calculate the time value to set in the timer
+@@ -2309,7 +2309,7 @@ int i_APCI3120_InsnReadTimer(struct comedi_device * dev, struct comedi_subdevice
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned char b_Tmp;
+-	USHORT us_TmpValue, us_TmpValue_2, us_StatusValue;
++	unsigned short us_TmpValue, us_TmpValue_2, us_StatusValue;
+ 
+ 	if ((devpriv->b_Timer2Mode != APCI3120_WATCHDOG)
+ 		&& (devpriv->b_Timer2Mode != APCI3120_TIMER)) {
+@@ -2647,7 +2647,7 @@ int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev,
+ 				     unsigned int *data)
+ {
+ 	UINT ui_Range, ui_Channel;
+-	USHORT us_TmpValue;
++	unsigned short us_TmpValue;
+ 
+ 	ui_Range = CR_RANGE(insn->chanspec);
+ 	ui_Channel = CR_CHAN(insn->chanspec);
+@@ -2678,19 +2678,19 @@ int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev,
+ 	do			//Waiting of DA_READY BIT
+ 	{
+ 		us_TmpValue =
+-			((USHORT) inw(devpriv->iobase +
++			((unsigned short) inw(devpriv->iobase +
+ 				APCI3120_RD_STATUS)) & 0x0001;
+ 	} while (us_TmpValue != 0x0001);
+ 
+ 	if (ui_Channel <= 3)
+ 		// for channel 0-3 out at  the register 1 (wrDac1-8)
+ 		// data[i] typecasted to ushort since  word write is to be done
+-		outw((USHORT) data[0],
++		outw((unsigned short) data[0],
+ 			devpriv->iobase + APCI3120_ANALOG_OUTPUT_1);
+ 	else
+ 		// for channel 4-7 out at the register 2 (wrDac5-8)
+ 		//data[i] typecasted to ushort since  word write is to be done
+-		outw((USHORT) data[0],
++		outw((unsigned short) data[0],
+ 			devpriv->iobase + APCI3120_ANALOG_OUTPUT_2);
+ 
+ 	return insn->n;

commit 66673a7c8421784c0c7780b396014bc7d0afcc85
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:04:47 2009 -0400
+
+    Staging: comedi: Remove SHORT and *PSHORT typedefs in addi-data
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+index afe41263c749..f94bd9da43cd 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+@@ -37,7 +37,6 @@
+ #define SUCCESS	1
+ 
+ /* variable type definition */
+-typedef short SHORT, *PSHORT;
+ typedef unsigned short USHORT, *PUSHORT;
+ typedef unsigned short WORD, *PWORD;
+ typedef int INT, *PINT;;

commit 1783fbfe023b7c2b912fbb020e01ff46985aa0ab
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:04:41 2009 -0400
+
+    Staging: comedi: Remove BYTE and *PBYTE typedefs in addi-data
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+index c96aee09e1b6..1dd195d55167 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+@@ -23,15 +23,15 @@
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_     i_APCI1710_InitTimer                         |
+-|                               (BYTE_   b_BoardHandle,                      |
+-|                                BYTE_   b_ModulNbr,                         |
+-|                                BYTE_   b_TimerNbr,                         |
+-|                                BYTE_   b_TimerMode,                        |
++|                               (unsigned char_   b_BoardHandle,                      |
++|                                unsigned char_   b_ModulNbr,                         |
++|                                unsigned char_   b_TimerNbr,                         |
++|                                unsigned char_   b_TimerMode,                        |
+ |                                ULONG_ ul_ReloadValue,                      |
+-|                                BYTE_   b_InputClockSelection,              |
+-|                                BYTE_   b_InputClockLevel,                  |
+-|                                BYTE_   b_OutputLevel,                      |
+-|                                BYTE_   b_HardwareGateLevel)
++|                                unsigned char_   b_InputClockSelection,              |
++|                                unsigned char_   b_InputClockLevel,                  |
++|                                unsigned char_   b_OutputLevel,                      |
++|                                unsigned char_   b_HardwareGateLevel)
+ INT i_InsnConfig_InitTimer(struct comedi_device *dev,struct comedi_subdevice *s,
+ 	struct comedi_insn *insn,unsigned int *data)
+ |
+@@ -148,13 +148,13 @@ INT i_InsnConfig_InitTimer(struct comedi_device *dev,struct comedi_subdevice *s,
+ |  +--------------------------------+------------------------------------+   |
+ |                                                                            |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_   b_BoardHandle        : Handle of board         |
++| Input Parameters  : unsigned char_   b_BoardHandle        : Handle of board         |
+ |                                                    APCI-1710               |
+-|                     BYTE_   b_ModulNbr           : Module number to        |
++|                     unsigned char_   b_ModulNbr           : Module number to        |
+ |                                                    configure (0 to 3)      |
+-|                     BYTE_   b_TimerNbr           : Timer number to         |
++|                     unsigned char_   b_TimerNbr           : Timer number to         |
+ |                                                    configure (0 to 2)      |
+-|                     BYTE_   b_TimerMode          : Timer mode selection    |
++|                     unsigned char_   b_TimerMode          : Timer mode selection    |
+ |                                                    (0 to 5)                |
+ |                                                    0: Interrupt on terminal|
+ |                                                       count                |
+@@ -173,21 +173,21 @@ INT i_InsnConfig_InitTimer(struct comedi_device *dev,struct comedi_subdevice *s,
+ |                                                     or division factor     |
+ |                                                     See timer mode         |
+ |                                                     description table.     |
+-|                     BYTE_   b_InputClockSelection : Selection from input   |
++|                     unsigned char_   b_InputClockSelection : Selection from input   |
+ |                                                     timer clock.           |
+ |                                                     See input clock        |
+ |                                                     selection table.       |
+-|                     BYTE_   b_InputClockLevel     : Selection from input   |
++|                     unsigned char_   b_InputClockLevel     : Selection from input   |
+ |                                                     clock level.           |
+ |                                                     0 : Low active         |
+ |                                                         (Input inverted)   |
+ |                                                     1 : High active        |
+-|                     BYTE_   b_OutputLevel,        : Selection from output  |
++|                     unsigned char_   b_OutputLevel,        : Selection from output  |
+ |                                                     clock level.           |
+ |                                                     0 : Low active         |
+ |                                                     1 : High active        |
+ |                                                         (Output inverted)  |
+-|                     BYTE_   b_HardwareGateLevel   : Selection from         |
++|                     unsigned char_   b_HardwareGateLevel   : Selection from         |
+ |                                                     hardware gate level.   |
+ |                                                     0 : Low active         |
+ |                                                         (Input inverted)   |
+@@ -195,14 +195,14 @@ INT i_InsnConfig_InitTimer(struct comedi_device *dev,struct comedi_subdevice *s,
+ |                                                     If you will not used   |
+ |                                                     the hardware gate set  |
+ |                                                     this value to 0.
+-|b_ModulNbr        = (BYTE) CR_AREF(insn->chanspec);
+-	b_TimerNbr		  = (BYTE) CR_CHAN(insn->chanspec);
+-	b_TimerMode		  = (BYTE) data[0];
++|b_ModulNbr        = (unsigned char) CR_AREF(insn->chanspec);
++	b_TimerNbr		  = (unsigned char) CR_CHAN(insn->chanspec);
++	b_TimerMode		  = (unsigned char) data[0];
+ 	ul_ReloadValue	  = (ULONG) data[1];
+-	b_InputClockSelection	=(BYTE) data[2];
+-	b_InputClockLevel		=(BYTE) data[3];
+-	b_OutputLevel			=(BYTE) data[4];
+-	b_HardwareGateLevel		=(BYTE) data[5];
++	b_InputClockSelection	=(unsigned char) data[2];
++	b_InputClockLevel		=(unsigned char) data[3];
++	b_OutputLevel			=(unsigned char) data[4];
++	b_HardwareGateLevel		=(unsigned char) data[5];
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+ +----------------------------------------------------------------------------+
+@@ -224,28 +224,28 @@ INT i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, struct comedi_sub
+ {
+ 
+ 	INT i_ReturnValue = 0;
+-	BYTE b_ModulNbr;
+-	BYTE b_TimerNbr;
+-	BYTE b_TimerMode;
++	unsigned char b_ModulNbr;
++	unsigned char b_TimerNbr;
++	unsigned char b_TimerMode;
+ 	ULONG ul_ReloadValue;
+-	BYTE b_InputClockSelection;
+-	BYTE b_InputClockLevel;
+-	BYTE b_OutputLevel;
+-	BYTE b_HardwareGateLevel;
++	unsigned char b_InputClockSelection;
++	unsigned char b_InputClockLevel;
++	unsigned char b_OutputLevel;
++	unsigned char b_HardwareGateLevel;
+ 
+ 	//BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz
+ 	DWORD dw_Test = 0;
+ 	//END JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz
+ 
+ 	i_ReturnValue = insn->n;
+-	b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+-	b_TimerNbr = (BYTE) CR_CHAN(insn->chanspec);
+-	b_TimerMode = (BYTE) data[0];
++	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
++	b_TimerNbr = (unsigned char) CR_CHAN(insn->chanspec);
++	b_TimerMode = (unsigned char) data[0];
+ 	ul_ReloadValue = (ULONG) data[1];
+-	b_InputClockSelection = (BYTE) data[2];
+-	b_InputClockLevel = (BYTE) data[3];
+-	b_OutputLevel = (BYTE) data[4];
+-	b_HardwareGateLevel = (BYTE) data[5];
++	b_InputClockSelection = (unsigned char) data[2];
++	b_InputClockLevel = (unsigned char) data[3];
++	b_OutputLevel = (unsigned char) data[4];
++	b_HardwareGateLevel = (unsigned char) data[5];
+ 
+ 	/* Test the module number */
+ 	if (b_ModulNbr < 4) {
+@@ -402,10 +402,10 @@ INT i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, struct comedi_sub
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_     i_APCI1710_EnableTimer                       |
+-|                               (BYTE_ b_BoardHandle,                        |
+-|                                BYTE_ b_ModulNbr,                           |
+-|                                BYTE_ b_TimerNbr,                           |
+-|                                BYTE_ b_InterruptEnable)
++|                               (unsigned char_ b_BoardHandle,                        |
++|                                unsigned char_ b_ModulNbr,                           |
++|                                unsigned char_ b_TimerNbr,                           |
++|                                unsigned char_ b_InterruptEnable)
+ INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,struct comedi_subdevice *s,
+ 	struct comedi_insn *insn,unsigned int *data)                |
+ +----------------------------------------------------------------------------+
+@@ -416,22 +416,22 @@ INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,struct come
+ |                     generate a interrupt after the timer value reach       |
+ |                     the zero. See function "i_APCI1710_SetBoardIntRoutineX"|
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_   b_BoardHandle     : Handle of board            |
++| Input Parameters  : unsigned char_   b_BoardHandle     : Handle of board            |
+ |                                                 APCI-1710                  |
+-|                     BYTE_   b_ModulNbr        : Selected module number     |
++|                     unsigned char_   b_ModulNbr        : Selected module number     |
+ |                                                 (0 to 3)                   |
+-|                     BYTE_   b_TimerNbr        : Timer number to enable     |
++|                     unsigned char_   b_TimerNbr        : Timer number to enable     |
+ |                                                 (0 to 2)                   |
+-|                     BYTE_   b_InterruptEnable : Enable or disable the      |
++|                     unsigned char_   b_InterruptEnable : Enable or disable the      |
+ |                                                 timer interrupt.           |
+ |                                                 APCI1710_ENABLE :          |
+ |                                                 Enable the timer interrupt |
+ |                                                 APCI1710_DISABLE :         |
+ |                                                 Disable the timer interrupt|
+ i_ReturnValue=insn->n;
+-	b_ModulNbr        = (BYTE) CR_AREF(insn->chanspec);
+-	b_TimerNbr		  = (BYTE) CR_CHAN(insn->chanspec);
+-	b_ActionType      = (BYTE) data[0]; // enable disable
++	b_ModulNbr        = (unsigned char) CR_AREF(insn->chanspec);
++	b_TimerNbr		  = (unsigned char) CR_CHAN(insn->chanspec);
++	b_ActionType      = (unsigned char) data[0]; // enable disable
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+ +----------------------------------------------------------------------------+
+@@ -454,15 +454,15 @@ INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device * dev,
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_DummyRead;
+-	BYTE b_ModulNbr;
+-	BYTE b_TimerNbr;
+-	BYTE b_ActionType;
+-	BYTE b_InterruptEnable;
++	unsigned char b_ModulNbr;
++	unsigned char b_TimerNbr;
++	unsigned char b_ActionType;
++	unsigned char b_InterruptEnable;
+ 
+ 	i_ReturnValue = insn->n;
+-	b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+-	b_TimerNbr = (BYTE) CR_CHAN(insn->chanspec);
+-	b_ActionType = (BYTE) data[0];	// enable disable
++	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
++	b_TimerNbr = (unsigned char) CR_CHAN(insn->chanspec);
++	b_ActionType = (unsigned char) data[0];	// enable disable
+ 
+ 	/* Test the module number */
+ 	if (b_ModulNbr < 4) {
+@@ -475,7 +475,7 @@ INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device * dev,
+ 
+ 					switch (b_ActionType) {
+ 					case APCI1710_ENABLE:
+-						b_InterruptEnable = (BYTE) data[1];
++						b_InterruptEnable = (unsigned char) data[1];
+ 						/* Test the interrupt selection */
+ 						if ((b_InterruptEnable == APCI1710_ENABLE) ||
+ 						    (b_InterruptEnable == APCI1710_DISABLE)) {
+@@ -558,8 +558,8 @@ INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_     i_APCI1710_ReadAllTimerValue                 |
+-|                                       (BYTE_     b_BoardHandle,            |
+-|                                        BYTE_     b_ModulNbr,               |
++|                                       (unsigned char_     b_BoardHandle,            |
++|                                        unsigned char_     b_ModulNbr,               |
+ |                                        PULONG_ pul_TimerValueArray)
+ INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev,struct comedi_subdevice *s,
+ 	struct comedi_insn *insn,unsigned int *data)        |
+@@ -567,9 +567,9 @@ INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev,struct comedi_sub
+ | Task              : Return the all timer values from selected timer        |
+ |                     module (b_ModulNbr).                                   |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_   b_BoardHandle     : Handle of board            |
++| Input Parameters  : unsigned char_   b_BoardHandle     : Handle of board            |
+ |                                                 APCI-1710                  |
+-|                     BYTE_   b_ModulNbr        : Selected module number     |
++|                     unsigned char_   b_ModulNbr        : Selected module number     |
+ |                                                 (0 to 3)                   |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : PULONG_ pul_TimerValueArray : Timer value array.       |
+@@ -594,7 +594,7 @@ INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, struct comedi_su
+ 				     struct comedi_insn *insn, unsigned int *data)
+ {
+ 	INT i_ReturnValue = 0;
+-	BYTE b_ModulNbr, b_ReadType;
++	unsigned char b_ModulNbr, b_ReadType;
+ 	PULONG pul_TimerValueArray;
+ 
+ 	b_ModulNbr = CR_AREF(insn->chanspec);
+@@ -684,7 +684,7 @@ struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)
+ INT i_APCI1710_InsnBitsTimer(struct comedi_device * dev, struct comedi_subdevice * s,
+ 			     struct comedi_insn * insn, unsigned int * data)
+ {
+-	BYTE b_BitsType;
++	unsigned char b_BitsType;
+ 	INT i_ReturnValue = 0;
+ 	b_BitsType = data[0];
+ 
+@@ -693,29 +693,29 @@ INT i_APCI1710_InsnBitsTimer(struct comedi_device * dev, struct comedi_subdevice
+ 	switch (b_BitsType) {
+ 	case APCI1710_TIMER_READVALUE:
+ 		i_ReturnValue = i_APCI1710_ReadTimerValue(dev,
+-							  (BYTE)CR_AREF(insn->chanspec),
+-							  (BYTE)CR_CHAN(insn->chanspec),
++							  (unsigned char)CR_AREF(insn->chanspec),
++							  (unsigned char)CR_CHAN(insn->chanspec),
+ 							  (PULONG) & data[0]);
+ 		break;
+ 
+ 	case APCI1710_TIMER_GETOUTPUTLEVEL:
+ 		i_ReturnValue = i_APCI1710_GetTimerOutputLevel(dev,
+-							       (BYTE)CR_AREF(insn->chanspec),
+-							       (BYTE)CR_CHAN(insn->chanspec),
+-							       (PBYTE) &data[0]);
++							       (unsigned char)CR_AREF(insn->chanspec),
++							       (unsigned char)CR_CHAN(insn->chanspec),
++							       (unsigned char *) &data[0]);
+ 		break;
+ 
+ 	case APCI1710_TIMER_GETPROGRESSSTATUS:
+ 		i_ReturnValue = i_APCI1710_GetTimerProgressStatus(dev,
+-								  (BYTE)CR_AREF(insn->chanspec),
+-								  (BYTE)CR_CHAN(insn->chanspec),
+-								  (PBYTE)&data[0]);
++								  (unsigned char)CR_AREF(insn->chanspec),
++								  (unsigned char)CR_CHAN(insn->chanspec),
++								  (unsigned char *)&data[0]);
+ 		break;
+ 
+ 	case APCI1710_TIMER_WRITEVALUE:
+ 		i_ReturnValue = i_APCI1710_WriteTimerValue(dev,
+-							   (BYTE)CR_AREF(insn->chanspec),
+-							   (BYTE)CR_CHAN(insn->chanspec),
++							   (unsigned char)CR_AREF(insn->chanspec),
++							   (unsigned char)CR_CHAN(insn->chanspec),
+ 							   (ULONG)data[1]);
+ 
+ 		break;
+@@ -733,19 +733,19 @@ INT i_APCI1710_InsnBitsTimer(struct comedi_device * dev, struct comedi_subdevice
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_     i_APCI1710_ReadTimerValue                    |
+-|                                       (BYTE_     b_BoardHandle,            |
+-|                                        BYTE_     b_ModulNbr,               |
+-|                                        BYTE_     b_TimerNbr,               |
++|                                       (unsigned char_     b_BoardHandle,            |
++|                                        unsigned char_     b_ModulNbr,               |
++|                                        unsigned char_     b_TimerNbr,               |
+ |                                        PULONG_ pul_TimerValue)             |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the timer value from selected digital timer     |
+ |                     (b_TimerNbr) from selected timer  module (b_ModulNbr). |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_   b_BoardHandle     : Handle of board            |
++| Input Parameters  : unsigned char_   b_BoardHandle     : Handle of board            |
+ |                                                 APCI-1710                  |
+-|                     BYTE_   b_ModulNbr        : Selected module number     |
++|                     unsigned char_   b_ModulNbr        : Selected module number     |
+ |                                                 (0 to 3)                   |
+-|                     BYTE_   b_TimerNbr        : Timer number to read       |
++|                     unsigned char_   b_TimerNbr        : Timer number to read       |
+ |                                                 (0 to 2)                   |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : PULONG_ pul_TimerValue    : Timer value                |
+@@ -761,7 +761,7 @@ INT i_APCI1710_InsnBitsTimer(struct comedi_device * dev, struct comedi_subdevice
+ */
+ 
+ INT i_APCI1710_ReadTimerValue(struct comedi_device * dev,
+-			      BYTE b_ModulNbr, BYTE b_TimerNbr,
++			      unsigned char b_ModulNbr, unsigned char b_TimerNbr,
+ 			      PULONG pul_TimerValue)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -818,23 +818,23 @@ INT i_APCI1710_ReadTimerValue(struct comedi_device * dev,
+ 	/*
+ 	   +----------------------------------------------------------------------------+
+ 	   | Function Name     : _INT_     i_APCI1710_GetTimerOutputLevel               |
+-	   |                                       (BYTE_     b_BoardHandle,            |
+-	   |                                        BYTE_     b_ModulNbr,               |
+-	   |                                        BYTE_     b_TimerNbr,               |
+-	   |                                        PBYTE_   pb_OutputLevel)            |
++	   |                                       (unsigned char_     b_BoardHandle,            |
++	   |                                        unsigned char_     b_ModulNbr,               |
++	   |                                        unsigned char_     b_TimerNbr,               |
++	   |                                        unsigned char *_   pb_OutputLevel)            |
+ 	   +----------------------------------------------------------------------------+
+ 	   | Task              : Return the output signal level (pb_OutputLevel) from   |
+ 	   |                     selected digital timer (b_TimerNbr) from selected timer|
+ 	   |                     module (b_ModulNbr).                                   |
+ 	   +----------------------------------------------------------------------------+
+-	   | Input Parameters  : BYTE_   b_BoardHandle     : Handle of board            |
++	   | Input Parameters  : unsigned char_   b_BoardHandle     : Handle of board            |
+ 	   |                                                 APCI-1710                  |
+-	   |                     BYTE_   b_ModulNbr        : Selected module number     |
++	   |                     unsigned char_   b_ModulNbr        : Selected module number     |
+ 	   |                                                 (0 to 3)                   |
+-	   |                     BYTE_   b_TimerNbr        : Timer number to test       |
++	   |                     unsigned char_   b_TimerNbr        : Timer number to test       |
+ 	   |                                                 (0 to 2)                   |
+ 	   +----------------------------------------------------------------------------+
+-	   | Output Parameters : PBYTE_ pb_OutputLevel     : Output signal level        |
++	   | Output Parameters : unsigned char *_ pb_OutputLevel     : Output signal level        |
+ 	   |                                                 0 : The output is low      |
+ 	   |                                                 1 : The output is high     |
+ 	   +----------------------------------------------------------------------------+
+@@ -849,8 +849,8 @@ INT i_APCI1710_ReadTimerValue(struct comedi_device * dev,
+ 	 */
+ 
+ INT i_APCI1710_GetTimerOutputLevel(struct comedi_device * dev,
+-				   BYTE b_ModulNbr, BYTE b_TimerNbr,
+-				   PBYTE pb_OutputLevel)
++				   unsigned char b_ModulNbr, unsigned char b_TimerNbr,
++				   unsigned char * pb_OutputLevel)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_TimerStatus;
+@@ -869,7 +869,7 @@ INT i_APCI1710_GetTimerOutputLevel(struct comedi_device * dev,
+ 					/* Read the timer status */
+ 					dw_TimerStatus = inl(devpriv->s_BoardInfos.ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
+ 
+-					*pb_OutputLevel = (BYTE) (((dw_TimerStatus >> 7) & 1) ^ devpriv-> s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_OutputLevel);
++					*pb_OutputLevel = (unsigned char) (((dw_TimerStatus >> 7) & 1) ^ devpriv-> s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_OutputLevel);
+ 				} else {
+ 					/* Timer not initialised see function */
+ 					DPRINTK("Timer not initialised see function\n");
+@@ -897,23 +897,23 @@ INT i_APCI1710_GetTimerOutputLevel(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_     i_APCI1710_GetTimerProgressStatus            |
+-|                                       (BYTE_     b_BoardHandle,            |
+-|                                        BYTE_     b_ModulNbr,               |
+-|                                        BYTE_     b_TimerNbr,               |
+-|                                        PBYTE_   pb_TimerStatus)            |
++|                                       (unsigned char_     b_BoardHandle,            |
++|                                        unsigned char_     b_ModulNbr,               |
++|                                        unsigned char_     b_TimerNbr,               |
++|                                        unsigned char *_   pb_TimerStatus)            |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the progress status (pb_TimerStatus) from       |
+ |                     selected digital timer (b_TimerNbr) from selected timer|
+ |                     module (b_ModulNbr).                                   |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_   b_BoardHandle     : Handle of board            |
++| Input Parameters  : unsigned char_   b_BoardHandle     : Handle of board            |
+ |                                                 APCI-1710                  |
+-|                     BYTE_   b_ModulNbr        : Selected module number     |
++|                     unsigned char_   b_ModulNbr        : Selected module number     |
+ |                                                 (0 to 3)                   |
+-|                     BYTE_   b_TimerNbr        : Timer number to test       |
++|                     unsigned char_   b_TimerNbr        : Timer number to test       |
+ |                                                 (0 to 2)                   |
+ +----------------------------------------------------------------------------+
+-| Output Parameters : PBYTE_ pb_TimerStatus     : Output signal level        |
++| Output Parameters : unsigned char *_ pb_TimerStatus     : Output signal level        |
+ |                                                 0 : Timer not in progress  |
+ |                                                 1 : Timer in progress      |
+ +----------------------------------------------------------------------------+
+@@ -928,8 +928,8 @@ INT i_APCI1710_GetTimerOutputLevel(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
+-				      BYTE b_ModulNbr, BYTE b_TimerNbr,
+-				      PBYTE pb_TimerStatus)
++				      unsigned char b_ModulNbr, unsigned char b_TimerNbr,
++				      unsigned char * pb_TimerStatus)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_TimerStatus;
+@@ -949,7 +949,7 @@ INT i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
+ 					/* Read the timer status */
+ 					dw_TimerStatus = inl(devpriv->s_BoardInfos.ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
+ 
+-					*pb_TimerStatus = (BYTE) ((dw_TimerStatus) >> 8) & 1;
++					*pb_TimerStatus = (unsigned char) ((dw_TimerStatus) >> 8) & 1;
+ 					printk("ProgressStatus : %d", *pb_TimerStatus);
+ 				} else {
+ 					/* Timer not initialised see function */
+@@ -976,9 +976,9 @@ INT i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_     i_APCI1710_WriteTimerValue                   |
+-|                                       (BYTE_   b_BoardHandle,              |
+-|                                        BYTE_   b_ModulNbr,                 |
+-|                                        BYTE_   b_TimerNbr,                 |
++|                                       (unsigned char_   b_BoardHandle,              |
++|                                        unsigned char_   b_ModulNbr,                 |
++|                                        unsigned char_   b_TimerNbr,                 |
+ |                                        ULONG_ ul_WriteValue)               |
+ +----------------------------------------------------------------------------+
+ | Task              : Write the value (ul_WriteValue) into the selected timer|
+@@ -986,11 +986,11 @@ INT i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
+ |                     The action in depend of the time mode selection.       |
+ |                     See timer mode description table.                      |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_   b_BoardHandle     : Handle of board            |
++| Input Parameters  : unsigned char_   b_BoardHandle     : Handle of board            |
+ |                                                 APCI-1710                  |
+-|                     BYTE_   b_ModulNbr        : Selected module number     |
++|                     unsigned char_   b_ModulNbr        : Selected module number     |
+ |                                                 (0 to 3)                   |
+-|                     BYTE_   b_TimerNbr        : Timer number to write      |
++|                     unsigned char_   b_TimerNbr        : Timer number to write      |
+ |                                                 (0 to 2)                   |
+ |                     ULONG_ ul_WriteValue      : Value to write             |
+ +----------------------------------------------------------------------------+
+@@ -1007,7 +1007,7 @@ INT i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
+ */
+ 
+ INT i_APCI1710_WriteTimerValue(struct comedi_device * dev,
+-			       BYTE b_ModulNbr, BYTE b_TimerNbr,
++			       unsigned char b_ModulNbr, unsigned char b_TimerNbr,
+ 			       ULONG ul_WriteValue)
+ {
+ 	INT i_ReturnValue = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
+index 4797c0b77a43..e8dd4968c036 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
+@@ -54,20 +54,20 @@ INT i_APCI1710_InsnBitsTimer(struct comedi_device *dev, struct comedi_subdevice
+  * 82X54 READ & WRITE FUNCTION
+  */
+ INT i_APCI1710_ReadTimerValue(struct comedi_device *dev,
+-			      BYTE b_ModulNbr, BYTE b_TimerNbr,
++			      unsigned char b_ModulNbr, unsigned char b_TimerNbr,
+ 			      PULONG pul_TimerValue);
+ 
+ INT i_APCI1710_GetTimerOutputLevel(struct comedi_device *dev,
+-				   BYTE b_ModulNbr, BYTE b_TimerNbr,
+-				   PBYTE pb_OutputLevel);
++				   unsigned char b_ModulNbr, unsigned char b_TimerNbr,
++				   unsigned char * pb_OutputLevel);
+ 
+ INT i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
+-				      BYTE b_ModulNbr, BYTE b_TimerNbr,
+-				      PBYTE pb_TimerStatus);
++				      unsigned char b_ModulNbr, unsigned char b_TimerNbr,
++				      unsigned char * pb_TimerStatus);
+ 
+ /*
+  * 82X54 WRITE FUNCTION
+  */
+ INT i_APCI1710_WriteTimerValue(struct comedi_device *dev,
+-			       BYTE b_ModulNbr, BYTE b_TimerNbr,
++			       unsigned char b_ModulNbr, unsigned char b_TimerNbr,
+ 			       ULONG ul_WriteValue);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+index 1a54d3b2c694..f8d5914dcdea 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+@@ -62,11 +62,11 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_     i_APCI1710_InitChrono                        |
+-|                                       (BYTE_     b_BoardHandle,            |
+-|                                        BYTE_     b_ModulNbr,               |
+-|                                        BYTE_     b_ChronoMode,             |
+-|                                        BYTE_     b_PCIInputClock,          |
+-|                                        BYTE_     b_TimingUnit,             |
++|                                       (unsigned char_     b_BoardHandle,            |
++|                                        unsigned char_     b_ModulNbr,               |
++|                                        unsigned char_     b_ChronoMode,             |
++|                                        unsigned char_     b_PCIInputClock,          |
++|                                        unsigned char_     b_TimingUnit,             |
+ |                                        ULONG_   ul_TimingInterval,         |
+ |                                        PULONG_ pul_RealTimingInterval)
+ 
+@@ -88,12 +88,12 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ |                     The mode 4 to 7 is appropriate for measuring the timing|
+ |                     between  two event.                                    |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_   b_BoardHandle    : Handle of board APCI-1710   |
+-| BYTE_   b_ModulNbr  CR_AREF(insn->chanspec)  : Module number to configure  |
++| Input Parameters  : unsigned char_   b_BoardHandle    : Handle of board APCI-1710   |
++| unsigned char_   b_ModulNbr  CR_AREF(insn->chanspec)  : Module number to configure  |
+ |                                                (0 to 3)                    |
+-| BYTE_   b_ChronoMode				data[0]    : Chronometer action mode     |
++| unsigned char_   b_ChronoMode				data[0]    : Chronometer action mode     |
+ |                                                (0 to 7).                   |
+-| BYTE_   b_PCIInputClock			data[1] : Selection from PCI bus clock|
++| unsigned char_   b_PCIInputClock			data[1] : Selection from PCI bus clock|
+ |                                                - APCI1710_30MHZ :          |
+ |                                                  The PC have a PCI bus     |
+ |                                                  clock from 30 MHz         |
+@@ -104,7 +104,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ |                                                  The APCI-1710 have a      |
+ |                                                  integrated 40Mhz          |
+ |                                                  quartz.                   |
+-|               BYTE_   b_TimingUnit	data[2]    : Base timing unity (0 to 4) |
++|               unsigned char_   b_TimingUnit	data[2]    : Base timing unity (0 to 4) |
+ |                                                 0 : ns                     |
+ |                                                 1 : µs                     |
+ |                                                 2 : ms                     |
+@@ -141,12 +141,12 @@ INT i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_su
+ 	double d_RealTimingInterval = 0;
+ 	DWORD dw_ModeArray[8] =
+ 		{ 0x01, 0x05, 0x00, 0x04, 0x02, 0x0E, 0x0A, 0x06 };
+-	BYTE b_ModulNbr, b_ChronoMode, b_PCIInputClock, b_TimingUnit;
++	unsigned char b_ModulNbr, b_ChronoMode, b_PCIInputClock, b_TimingUnit;
+ 
+ 	b_ModulNbr = CR_AREF(insn->chanspec);
+-	b_ChronoMode = (BYTE) data[0];
+-	b_PCIInputClock = (BYTE) data[1];
+-	b_TimingUnit = (BYTE) data[2];
++	b_ChronoMode = (unsigned char) data[0];
++	b_PCIInputClock = (unsigned char) data[1];
++	b_TimingUnit = (unsigned char) data[2];
+ 	ul_TimingInterval = (ULONG) data[3];
+ 	i_ReturnValue = insn->n;
+ 
+@@ -786,10 +786,10 @@ INT i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_su
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_EnableChrono                          |
+-|                                               (BYTE_ b_BoardHandle,        |
+-|                                                BYTE_ b_ModulNbr,           |
+-|                                                BYTE_ b_CycleMode,          |
+-|                                                BYTE_ b_InterruptEnable)
++|                                               (unsigned char_ b_BoardHandle,        |
++|                                                unsigned char_ b_ModulNbr,           |
++|                                                unsigned char_ b_CycleMode,          |
++|                                                unsigned char_ b_InterruptEnable)
+ INT i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
+ struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)						 |
+ +----------------------------------------------------------------------------+
+@@ -810,12 +810,12 @@ struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)						 |
+ |                     witch the " i_APCI1710_EnableChrono" function, if no   |
+ |                     stop signal occur this start signal is ignored.
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle  : Handle of board APCI-1710       |
+-|                     BYTE_ b_ModulNbr   CR_AREF(chanspec)  : Selected module number (0 to 3) |
++| Input Parameters  : unsigned char_ b_BoardHandle  : Handle of board APCI-1710       |
++|                     unsigned char_ b_ModulNbr   CR_AREF(chanspec)  : Selected module number (0 to 3) |
+                                   data[0]  ENABle/Disable chrono
+-|                     BYTE_ b_CycleMode    : Selected the chronometer        |
++|                     unsigned char_ b_CycleMode    : Selected the chronometer        |
+ |                                  data[1]           acquisition mode                |
+-|                     BYTE_ b_InterruptEnable : Enable or disable the        |
++|                     unsigned char_ b_InterruptEnable : Enable or disable the        |
+ |                                   data[2]            chronometer interrupt.       |
+ |                                               APCI1710_ENABLE:             |
+ |                                               Enable the chronometer       |
+@@ -844,11 +844,11 @@ INT i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+-	BYTE b_ModulNbr, b_CycleMode, b_InterruptEnable, b_Action;
++	unsigned char b_ModulNbr, b_CycleMode, b_InterruptEnable, b_Action;
+ 	b_ModulNbr = CR_AREF(insn->chanspec);
+-	b_Action = (BYTE) data[0];
+-	b_CycleMode = (BYTE) data[1];
+-	b_InterruptEnable = (BYTE) data[2];
++	b_Action = (unsigned char) data[0];
++	b_CycleMode = (unsigned char) data[1];
++	b_InterruptEnable = (unsigned char) data[2];
+ 	i_ReturnValue = insn->n;
+ 
+ 	/**************************/
+@@ -1093,7 +1093,7 @@ struct comedi_insn *insn,unsigned int *data)                   |
+ INT i_APCI1710_InsnReadChrono(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	BYTE b_ReadType;
++	unsigned char b_ReadType;
+ 	INT i_ReturnValue = insn->n;
+ 
+ 	b_ReadType = CR_CHAN(insn->chanspec);
+@@ -1101,23 +1101,23 @@ INT i_APCI1710_InsnReadChrono(struct comedi_device * dev, struct comedi_subdevic
+ 	switch (b_ReadType) {
+ 	case APCI1710_CHRONO_PROGRESS_STATUS:
+ 		i_ReturnValue = i_APCI1710_GetChronoProgressStatus(dev,
+-			(BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]);
++			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) & data[0]);
+ 		break;
+ 
+ 	case APCI1710_CHRONO_READVALUE:
+ 		i_ReturnValue = i_APCI1710_ReadChronoValue(dev,
+-			(BYTE) CR_AREF(insn->chanspec),
++			(unsigned char) CR_AREF(insn->chanspec),
+ 			(UINT) insn->unused[0],
+-			(PBYTE) & data[0], (PULONG) & data[1]);
++			(unsigned char *) & data[0], (PULONG) & data[1]);
+ 		break;
+ 
+ 	case APCI1710_CHRONO_CONVERTVALUE:
+ 		i_ReturnValue = i_APCI1710_ConvertChronoValue(dev,
+-			(BYTE) CR_AREF(insn->chanspec),
++			(unsigned char) CR_AREF(insn->chanspec),
+ 			(ULONG) insn->unused[0],
+ 			(PULONG) & data[0],
+-			(PBYTE) & data[1],
+-			(PBYTE) & data[2],
++			(unsigned char *) & data[1],
++			(unsigned char *) & data[2],
+ 			(PUINT) & data[3],
+ 			(PUINT) & data[4], (PUINT) & data[5]);
+ 		break;
+@@ -1159,15 +1159,15 @@ INT i_APCI1710_InsnReadChrono(struct comedi_device * dev, struct comedi_subdevic
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_GetChronoProgressStatus               |
+-|                               (BYTE_    b_BoardHandle,                     |
+-|                                BYTE_    b_ModulNbr,                        |
+-|                                PBYTE_  pb_ChronoStatus)                    |
++|                               (unsigned char_    b_BoardHandle,                     |
++|                                unsigned char_    b_ModulNbr,                        |
++|                                unsigned char *_  pb_ChronoStatus)                    |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the chronometer status (pb_ChronoStatus) from   |
+ |                     selected chronometer module (b_ModulNbr).              |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle  : Handle of board APCI-1710       |
+-|                     BYTE_ b_ModulNbr     : Selected module number (0 to 3) |
++| Input Parameters  : unsigned char_ b_BoardHandle  : Handle of board APCI-1710       |
++|                     unsigned char_ b_ModulNbr     : Selected module number (0 to 3) |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : PULONG_  pb_ChronoStatus : Return the chronometer      |
+ |                                                status.                     |
+@@ -1195,7 +1195,7 @@ INT i_APCI1710_InsnReadChrono(struct comedi_device * dev, struct comedi_subdevic
+ */
+ 
+ INT i_APCI1710_GetChronoProgressStatus(struct comedi_device * dev,
+-	BYTE b_ModulNbr, PBYTE pb_ChronoStatus)
++	unsigned char b_ModulNbr, unsigned char * pb_ChronoStatus)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_Status;
+@@ -1295,10 +1295,10 @@ INT i_APCI1710_GetChronoProgressStatus(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_ReadChronoValue                       |
+-|                               (BYTE_     b_BoardHandle,                    |
+-|                                BYTE_     b_ModulNbr,                       |
++|                               (unsigned char_     b_BoardHandle,                    |
++|                                unsigned char_     b_ModulNbr,                       |
+ |                                UINT_    ui_TimeOut,                        |
+-|                                PBYTE_   pb_ChronoStatus,                   |
++|                                unsigned char *_   pb_ChronoStatus,                   |
+ |                                PULONG_ pul_ChronoValue)                    |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the chronometer status (pb_ChronoStatus) and the|
+@@ -1323,8 +1323,8 @@ INT i_APCI1710_GetChronoProgressStatus(struct comedi_device * dev,
+ |                     "i_APCI1710_InitChrono" function and the time unity is |
+ |                     the b_TimingUnit from "i_APCI1710_InitChrono" function|
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle  : Handle of board APCI-1710       |
+-|                     BYTE_ b_ModulNbr     : Selected module number (0 to 3) |
++| Input Parameters  : unsigned char_ b_BoardHandle  : Handle of board APCI-1710       |
++|                     unsigned char_ b_ModulNbr     : Selected module number (0 to 3) |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : PULONG_  pb_ChronoStatus : Return the chronometer      |
+ |                                                status.                     |
+@@ -1356,8 +1356,8 @@ INT i_APCI1710_GetChronoProgressStatus(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_ReadChronoValue(struct comedi_device * dev,
+-	BYTE b_ModulNbr,
+-	UINT ui_TimeOut, PBYTE pb_ChronoStatus, PULONG pul_ChronoValue)
++	unsigned char b_ModulNbr,
++	UINT ui_TimeOut, unsigned char * pb_ChronoStatus, PULONG pul_ChronoValue)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_Status;
+@@ -1581,12 +1581,12 @@ INT i_APCI1710_ReadChronoValue(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_ConvertChronoValue                    |
+-|                               (BYTE_     b_BoardHandle,                    |
+-|                                BYTE_     b_ModulNbr,                       |
++|                               (unsigned char_     b_BoardHandle,                    |
++|                                unsigned char_     b_ModulNbr,                       |
+ |                                ULONG_   ul_ChronoValue,                    |
+ |                                PULONG_ pul_Hour,                           |
+-|                                PBYTE_   pb_Minute,                         |
+-|                                PBYTE_   pb_Second,                         |
++|                                unsigned char *_   pb_Minute,                         |
++|                                unsigned char *_   pb_Second,                         |
+ |                                PUINT_  pui_MilliSecond,                    |
+ |                                PUINT_  pui_MicroSecond,                    |
+ |                                PUINT_  pui_NanoSecond)                     |
+@@ -1594,15 +1594,15 @@ INT i_APCI1710_ReadChronoValue(struct comedi_device * dev,
+ | Task              : Convert the chronometer measured timing                |
+ |                     (ul_ChronoValue) in to h, mn, s, ms, µs, ns.           |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_   b_BoardHandle : Handle of board APCI-1710      |
+-|                     BYTE_   b_ModulNbr    : Selected module number (0 to 3)|
++| Input Parameters  : unsigned char_   b_BoardHandle : Handle of board APCI-1710      |
++|                     unsigned char_   b_ModulNbr    : Selected module number (0 to 3)|
+ |                     ULONG_ ul_ChronoValue : Measured chronometer timing    |
+ |                                             value.                         |
+ |                                             See"i_APCI1710_ReadChronoValue"|
+ +----------------------------------------------------------------------------+
+ | Output Parameters : PULONG_   pul_Hour        : Chronometer timing hour    |
+-|                     PBYTE_     pb_Minute      : Chronometer timing minute  |
+-|                     PBYTE_     pb_Second      : Chronometer timing second  |
++|                     unsigned char *_     pb_Minute      : Chronometer timing minute  |
++|                     unsigned char *_     pb_Second      : Chronometer timing second  |
+ |                     PUINT_    pui_MilliSecond  : Chronometer timing mini   |
+ |                                                 second                     |
+ |                     PUINT_    pui_MicroSecond : Chronometer timing micro   |
+@@ -1620,11 +1620,11 @@ INT i_APCI1710_ReadChronoValue(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
+-	BYTE b_ModulNbr,
++	unsigned char b_ModulNbr,
+ 	ULONG ul_ChronoValue,
+ 	PULONG pul_Hour,
+-	PBYTE pb_Minute,
+-	PBYTE pb_Second,
++	unsigned char * pb_Minute,
++	unsigned char * pb_Second,
+ 	PUINT pui_MilliSecond, PUINT pui_MicroSecond, PUINT pui_NanoSecond)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -1689,7 +1689,7 @@ INT i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
+ 
+ 					d_Minute = d_Hour - *pul_Hour;
+ 					d_Minute = d_Minute * 60;
+-					*pb_Minute = (BYTE) d_Minute;
++					*pb_Minute = (unsigned char) d_Minute;
+ 
+ 			    /************************/
+ 					/* Calculate the second */
+@@ -1697,7 +1697,7 @@ INT i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
+ 
+ 					d_Second = d_Minute - *pb_Minute;
+ 					d_Second = d_Second * 60;
+-					*pb_Second = (BYTE) d_Second;
++					*pb_Second = (unsigned char) d_Second;
+ 
+ 			    /*****************************/
+ 					/* Calculate the mini second */
+@@ -1764,9 +1764,9 @@ INT i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
+ |                     parameter b_Channel. Setting an output means setting an|
+ |                     output high.                                           |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle   : Handle of board APCI-1710      |
+-|                     BYTE_ b_ModulNbr      : Selected module number (0 to 3)|
+-|                     BYTE_ b_OutputChannel : Selection from digital output  |
++| Input Parameters  : unsigned char_ b_BoardHandle   : Handle of board APCI-1710      |
++|                     unsigned char_ b_ModulNbr      : Selected module number (0 to 3)|
++|                     unsigned char_ b_OutputChannel : Selection from digital output  |
+ |                           CR_CHAN()                  channel (0 to 2)               |
+ |                                              0 : Channel H                 |
+ |                                              1 : Channel A                 |
+@@ -1787,19 +1787,19 @@ INT i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_SetChronoChlOff                       |
+-|                               (BYTE_  b_BoardHandle,                       |
+-|                                BYTE_  b_ModulNbr,                          |
+-|                                BYTE_  b_OutputChannel)                     |
++|                               (unsigned char_  b_BoardHandle,                       |
++|                                unsigned char_  b_ModulNbr,                          |
++|                                unsigned char_  b_OutputChannel)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Resets the output witch has been passed with the       |
+ |                     parameter b_Channel. Resetting an output means setting |
+ |                     an output low.                                         |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle   : Handle of board APCI-1710
++| Input Parameters  : unsigned char_ b_BoardHandle   : Handle of board APCI-1710
+                         data[0] : Chl ON, Chl OFF , Chl Read , Port Read
+ 
+-|                     BYTE_ b_ModulNbr  CR_AREF    : Selected module number (0 to 3)|
+-|                     BYTE_ b_OutputChannel CR_CHAN : Selection from digital output  |
++|                     unsigned char_ b_ModulNbr  CR_AREF    : Selected module number (0 to 3)|
++|                     unsigned char_ b_OutputChannel CR_CHAN : Selection from digital output  |
+ |                                             channel (0 to 2)               |
+ |                                              0 : Channel H                 |
+ |                                              1 : Channel A                 |
+@@ -1820,24 +1820,24 @@ INT i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_ReadChronoChlValue                    |
+-|                               (BYTE_   b_BoardHandle,                      |
+-|                                BYTE_   b_ModulNbr,                         |
+-|                                BYTE_   b_InputChannel,                     |
+-|                                PBYTE_ pb_ChannelStatus)                    |
++|                               (unsigned char_   b_BoardHandle,                      |
++|                                unsigned char_   b_ModulNbr,                         |
++|                                unsigned char_   b_InputChannel,                     |
++|                                unsigned char *_ pb_ChannelStatus)                    |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status from selected digital input          |
+ |                     (b_InputChannel) from selected chronometer             |
+ |                     module (b_ModulNbr).                                   |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle   : Handle of board APCI-1710      |
+-|                     BYTE_ b_ModulNbr      : Selected module number (0 to 3)|
+-|                     BYTE_ b_InputChannel  : Selection from digital input   |
++| Input Parameters  : unsigned char_ b_BoardHandle   : Handle of board APCI-1710      |
++|                     unsigned char_ b_ModulNbr      : Selected module number (0 to 3)|
++|                     unsigned char_ b_InputChannel  : Selection from digital input   |
+ |                                             channel (0 to 2)               |
+ |                                   CR_CHAN()             0 : Channel E               |
+ |                                                1 : Channel F               |
+ |                                                2 : Channel G               |
+ +----------------------------------------------------------------------------+
+-| Output Parameters : PBYTE_ pb_ChannelStatus : Digital input channel status.|
++| Output Parameters : unsigned char *_ pb_ChannelStatus : Digital input channel status.|
+ |                                data[0]                0 : Channel is not active   |
+ |                                                1 : Channel is active       |
+ +----------------------------------------------------------------------------+
+@@ -1854,17 +1854,17 @@ INT i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_ReadChronoPortValue                   |
+-|                               (BYTE_   b_BoardHandle,                      |
+-|                                BYTE_   b_ModulNbr,                         |
+-|                                PBYTE_ pb_PortValue)                        |
++|                               (unsigned char_   b_BoardHandle,                      |
++|                                unsigned char_   b_ModulNbr,                         |
++|                                unsigned char *_ pb_PortValue)                        |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status from digital inputs port from        |
+ |                     selected  (b_ModulNbr) chronometer module.             |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle   : Handle of board APCI-1710      |
+-|                     BYTE_ b_ModulNbr      : Selected module number (0 to 3)|
++| Input Parameters  : unsigned char_ b_BoardHandle   : Handle of board APCI-1710      |
++|                     unsigned char_ b_ModulNbr      : Selected module number (0 to 3)|
+ +----------------------------------------------------------------------------+
+-| Output Parameters : PBYTE_ pb_PortValue   : Digital inputs port status.
++| Output Parameters : unsigned char *_ pb_PortValue   : Digital inputs port status.
+ |                     data[0]
+ +----------------------------------------------------------------------------+
+ | Return Value      :  0: No error                                           |
+@@ -1880,14 +1880,14 @@ INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+-	BYTE b_ModulNbr, b_OutputChannel, b_InputChannel, b_IOType;
++	unsigned char b_ModulNbr, b_OutputChannel, b_InputChannel, b_IOType;
+ 	DWORD dw_Status;
+-	PBYTE pb_ChannelStatus;
+-	PBYTE pb_PortValue;
++	unsigned char * pb_ChannelStatus;
++	unsigned char * pb_PortValue;
+ 
+ 	b_ModulNbr = CR_AREF(insn->chanspec);
+ 	i_ReturnValue = insn->n;
+-	b_IOType = (BYTE) data[0];
++	b_IOType = (unsigned char) data[0];
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -1915,7 +1915,7 @@ INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device * dev,
+ 				case APCI1710_CHRONO_SET_CHANNELOFF:
+ 
+ 					b_OutputChannel =
+-						(BYTE) CR_CHAN(insn->chanspec);
++						(unsigned char) CR_CHAN(insn->chanspec);
+ 					if (b_OutputChannel <= 2) {
+ 
+ 						outl(0, devpriv->s_BoardInfos.
+@@ -1938,7 +1938,7 @@ INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device * dev,
+ 				case APCI1710_CHRONO_SET_CHANNELON:
+ 
+ 					b_OutputChannel =
+-						(BYTE) CR_CHAN(insn->chanspec);
++						(unsigned char) CR_CHAN(insn->chanspec);
+ 					if (b_OutputChannel <= 2) {
+ 
+ 						outl(1, devpriv->s_BoardInfos.
+@@ -1962,9 +1962,9 @@ INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device * dev,
+ 		 /**********************************/
+ 					/* Test the digital input channel */
+ 		 /**********************************/
+-					pb_ChannelStatus = (PBYTE) & data[0];
++					pb_ChannelStatus = (unsigned char *) & data[0];
+ 					b_InputChannel =
+-						(BYTE) CR_CHAN(insn->chanspec);
++						(unsigned char) CR_CHAN(insn->chanspec);
+ 
+ 					if (b_InputChannel <= 2) {
+ 
+@@ -1975,7 +1975,7 @@ INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device * dev,
+ 							(64 * b_ModulNbr));
+ 
+ 						*pb_ChannelStatus =
+-							(BYTE) (((dw_Status >>
++							(unsigned char) (((dw_Status >>
+ 									b_InputChannel)
+ 								& 1) ^ 1);
+ 					}	// if ((b_InputChannel >= 0) && (b_InputChannel <= 2))
+@@ -1992,7 +1992,7 @@ INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device * dev,
+ 
+ 				case APCI1710_CHRONO_READ_PORT:
+ 
+-					pb_PortValue = (PBYTE) & data[0];
++					pb_PortValue = (unsigned char *) & data[0];
+ 
+ 					dw_Status =
+ 						inl(devpriv->s_BoardInfos.
+@@ -2000,7 +2000,7 @@ INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device * dev,
+ 						(64 * b_ModulNbr));
+ 
+ 					*pb_PortValue =
+-						(BYTE) ((dw_Status & 0x7) ^ 7);
++						(unsigned char) ((dw_Status & 0x7) ^ 7);
+ 					break;
+ 				}
+ 			} else {
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
+index 26b50cefee5a..31f76d51b4a3 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
+@@ -50,19 +50,19 @@ INT i_APCI1710_InsnReadChrono(struct comedi_device *dev, struct comedi_subdevice
+ 			      struct comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_GetChronoProgressStatus(struct comedi_device *dev,
+-				       BYTE b_ModulNbr, PBYTE pb_ChronoStatus);
++				       unsigned char b_ModulNbr, unsigned char * pb_ChronoStatus);
+ 
+ INT i_APCI1710_ReadChronoValue(struct comedi_device *dev,
+-			       BYTE b_ModulNbr,
+-			       UINT ui_TimeOut, PBYTE pb_ChronoStatus,
++			       unsigned char b_ModulNbr,
++			       UINT ui_TimeOut, unsigned char * pb_ChronoStatus,
+ 			       PULONG pul_ChronoValue);
+ 
+ INT i_APCI1710_ConvertChronoValue(struct comedi_device *dev,
+-				  BYTE b_ModulNbr,
++				  unsigned char b_ModulNbr,
+ 				  ULONG ul_ChronoValue,
+ 				  PULONG pul_Hour,
+-				  PBYTE pb_Minute,
+-				  PBYTE pb_Second,
++				  unsigned char * pb_Minute,
++				  unsigned char * pb_Second,
+ 				  PUINT pui_MilliSecond, PUINT pui_MicroSecond,
+ 				  PUINT pui_NanoSecond);
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+index 8be27aedaaf5..37af24259876 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+@@ -70,14 +70,14 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ |                     I/O.                                                   |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :													     |
+-|                  BYTE_ b_ModulNbr      data[0]: Module number to               |
++|                  unsigned char_ b_ModulNbr      data[0]: Module number to               |
+ |                                             configure (0 to 3)             |
+-|                     BYTE_ b_ChannelAMode data[1]  : Channel A mode selection       |
++|                     unsigned char_ b_ChannelAMode data[1]  : Channel A mode selection       |
+ |                                             0 : Channel used for digital   |
+ |                                                 input                      |
+ |                                             1 : Channel used for digital   |
+ |                                                 output                     |
+-|                     BYTE_ b_ChannelBMode data[2] : Channel B mode selection       |
++|                     unsigned char_ b_ChannelBMode data[2] : Channel B mode selection       |
+ |                                             0 : Channel used for digital   |
+ |                                                 input                      |
+ |                                             1 : Channel used for digital   |
+@@ -102,16 +102,16 @@ Activates and deactivates the digital output memory.
+ INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	BYTE b_ModulNbr, b_ChannelAMode, b_ChannelBMode;
+-	BYTE b_MemoryOnOff, b_ConfigType;
++	unsigned char b_ModulNbr, b_ChannelAMode, b_ChannelBMode;
++	unsigned char b_MemoryOnOff, b_ConfigType;
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_WriteConfig = 0;
+ 
+-	b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+-	b_ConfigType = (BYTE) data[0];	// Memory or  Init
+-	b_ChannelAMode = (BYTE) data[1];
+-	b_ChannelBMode = (BYTE) data[2];
+-	b_MemoryOnOff = (BYTE) data[1];	// if memory operation
++	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
++	b_ConfigType = (unsigned char) data[0];	// Memory or  Init
++	b_ChannelAMode = (unsigned char) data[1];
++	b_ChannelBMode = (unsigned char) data[2];
++	b_MemoryOnOff = (unsigned char) data[1];	// if memory operation
+ 	i_ReturnValue = insn->n;
+ 
+ 		/**************************/
+@@ -257,9 +257,9 @@ INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device * dev, struct comedi_sub
+ 
+ 
+ |
+-|  BYTE_ b_ModulNbr  CR_AREF(chanspec)          : Selected module number   |
++|  unsigned char_ b_ModulNbr  CR_AREF(chanspec)          : Selected module number   |
+ |                                                   (0 to 3)                 |
+-|  BYTE_ b_InputChannel CR_CHAN(chanspec)        : Selection from digital   |
++|  unsigned char_ b_InputChannel CR_CHAN(chanspec)        : Selection from digital   |
+ |                                                   input ( 0 to 6)          |
+ |                                                      0 : Channel C         |
+ |                                                      1 : Channel D         |
+@@ -288,22 +288,22 @@ INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device * dev, struct comedi_sub
+ +----------------------------------------------------------------------------+
+ */
+ 
+-//_INT_   i_APCI1710_ReadDigitalIOChlValue      (BYTE_    b_BoardHandle,
+-//                                             BYTE_    b_ModulNbr,
+-//                                             BYTE_    b_InputChannel,
++//_INT_   i_APCI1710_ReadDigitalIOChlValue      (unsigned char_    b_BoardHandle,
++//                                             unsigned char_    b_ModulNbr,
++//                                             unsigned char_    b_InputChannel,
+ //
+-//                                             PBYTE_  pb_ChannelStatus)
++//                                             unsigned char *_  pb_ChannelStatus)
+ INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusReg;
+-	BYTE b_ModulNbr, b_InputChannel;
+-	PBYTE pb_ChannelStatus;
+-	b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+-	b_InputChannel = (BYTE) CR_CHAN(insn->chanspec);
++	unsigned char b_ModulNbr, b_InputChannel;
++	unsigned char * pb_ChannelStatus;
++	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
++	b_InputChannel = (unsigned char) CR_CHAN(insn->chanspec);
+ 	data[0] = 0;
+-	pb_ChannelStatus = (PBYTE) & data[0];
++	pb_ChannelStatus = (unsigned char *) & data[0];
+ 	i_ReturnValue = insn->n;
+ 
+ 	/**************************/
+@@ -400,7 +400,7 @@ INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device * dev,
+ 							(64 * b_ModulNbr));
+ 
+ 						*pb_ChannelStatus =
+-							(BYTE) ((dw_StatusReg ^
++							(unsigned char) ((dw_StatusReg ^
+ 								0x1C) >>
+ 							b_InputChannel) & 1;
+ 
+@@ -453,9 +453,9 @@ INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device * dev,
+ |                     parameter b_Channel. Setting an output means setting   |
+ |                     an ouput high.                                         |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle   : Handle of board APCI-1710      |
+-|                     BYTE_ b_ModulNbr (aref )    : Selected module number (0 to 3)|
+-|                     BYTE_ b_OutputChannel (CR_CHAN) : Selection from digital output  |
++| Input Parameters  : unsigned char_ b_BoardHandle   : Handle of board APCI-1710      |
++|                     unsigned char_ b_ModulNbr (aref )    : Selected module number (0 to 3)|
++|                     unsigned char_ b_OutputChannel (CR_CHAN) : Selection from digital output  |
+ |                                             channel (0 to 2)               |
+ |                                                0 : Channel H               |
+ |                                                1 : Channel A               |
+@@ -478,15 +478,15 @@ INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-//_INT_   i_APCI1710_SetDigitalIOChlOn    (BYTE_ b_BoardHandle,
+-//                                       BYTE_ b_ModulNbr,
+-//                                       BYTE_ b_OutputChannel)
++//_INT_   i_APCI1710_SetDigitalIOChlOn    (unsigned char_ b_BoardHandle,
++//                                       unsigned char_ b_ModulNbr,
++//                                       unsigned char_ b_OutputChannel)
+ INT i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_WriteValue = 0;
+-	BYTE b_ModulNbr, b_OutputChannel;
++	unsigned char b_ModulNbr, b_OutputChannel;
+ 	i_ReturnValue = insn->n;
+ 	b_ModulNbr = CR_AREF(insn->chanspec);
+ 	b_OutputChannel = CR_CHAN(insn->chanspec);
+@@ -690,9 +690,9 @@ INT i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device * dev,
+ |                     from selected digital I/O module (b_ModulNbr)
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :
+-	BYTE_ b_BoardHandle   : Handle of board APCI-1710      |
+-|   BYTE_ b_ModulNbr  CR_AREF(aref)    : Selected module number (0 to 3)|
+-|   BYTE_ b_PortValue CR_CHAN(chanspec) : Output Value ( 0 To 7 )
++	unsigned char_ b_BoardHandle   : Handle of board APCI-1710      |
++|   unsigned char_ b_ModulNbr  CR_AREF(aref)    : Selected module number (0 to 3)|
++|   unsigned char_ b_PortValue CR_CHAN(chanspec) : Output Value ( 0 To 7 )
+ |                       data[0]           read or write port
+                         data[1]            if write then indicate ON or OFF
+ 
+@@ -725,26 +725,26 @@ INT i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-//_INT_   i_APCI1710_SetDigitalIOPortOn   (BYTE_ b_BoardHandle,
+-//                                       BYTE_ b_ModulNbr,
+-//                                       BYTE_ b_PortValue)
++//_INT_   i_APCI1710_SetDigitalIOPortOn   (unsigned char_ b_BoardHandle,
++//                                       unsigned char_ b_ModulNbr,
++//                                       unsigned char_ b_PortValue)
+ INT i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_WriteValue = 0;
+ 	DWORD dw_StatusReg;
+-	BYTE b_ModulNbr, b_PortValue;
+-	BYTE b_PortOperation, b_PortOnOFF;
++	unsigned char b_ModulNbr, b_PortValue;
++	unsigned char b_PortOperation, b_PortOnOFF;
+ 
+-	PBYTE pb_PortValue;
++	unsigned char * pb_PortValue;
+ 
+-	b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+-	b_PortOperation = (BYTE) data[0];	// Input or output
+-	b_PortOnOFF = (BYTE) data[1];	// if output then On or Off
+-	b_PortValue = (BYTE) data[2];	// if out put then Value
++	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
++	b_PortOperation = (unsigned char) data[0];	// Input or output
++	b_PortOnOFF = (unsigned char) data[1];	// if output then On or Off
++	b_PortValue = (unsigned char) data[2];	// if out put then Value
+ 	i_ReturnValue = insn->n;
+-	pb_PortValue = (PBYTE) & data[0];
++	pb_PortValue = (unsigned char *) & data[0];
+ // if input then read value
+ 
+ 	switch (b_PortOperation) {
+@@ -781,7 +781,7 @@ INT i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device * dev,
+ 						inl(devpriv->s_BoardInfos.
+ 						ui_Address + (64 * b_ModulNbr));
+ 					*pb_PortValue =
+-						(BYTE) (dw_StatusReg ^ 0x1C);
++						(unsigned char) (dw_StatusReg ^ 0x1C);
+ 
+ 				} else {
+ 		 /*******************************/
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+index 1062f2fdec30..cad8ac960f7b 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+@@ -89,32 +89,32 @@ INT i_APCI1710_InsnConfigINCCPT(struct comedi_device * dev, struct comedi_subdev
+ 	case APCI1710_INCCPT_INITCOUNTER:
+ 		i_ReturnValue = i_APCI1710_InitCounter(dev,
+ 			CR_AREF(insn->chanspec),
+-			(BYTE) data[0],
+-			(BYTE) data[1],
+-			(BYTE) data[2], (BYTE) data[3], (BYTE) data[4]);
++			(unsigned char) data[0],
++			(unsigned char) data[1],
++			(unsigned char) data[2], (unsigned char) data[3], (unsigned char) data[4]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_COUNTERAUTOTEST:
+ 		i_ReturnValue = i_APCI1710_CounterAutoTest(dev,
+-			(PBYTE) & data[0]);
++			(unsigned char *) & data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_INITINDEX:
+ 		i_ReturnValue = i_APCI1710_InitIndex(dev,
+ 			CR_AREF(insn->chanspec),
+-			(BYTE) data[0],
+-			(BYTE) data[1], (BYTE) data[2], (BYTE) data[3]);
++			(unsigned char) data[0],
++			(unsigned char) data[1], (unsigned char) data[2], (unsigned char) data[3]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_INITREFERENCE:
+ 		i_ReturnValue = i_APCI1710_InitReference(dev,
+-			CR_AREF(insn->chanspec), (BYTE) data[0]);
++			CR_AREF(insn->chanspec), (unsigned char) data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_INITEXTERNALSTROBE:
+ 		i_ReturnValue = i_APCI1710_InitExternalStrobe(dev,
+ 			CR_AREF(insn->chanspec),
+-			(BYTE) data[0], (BYTE) data[1]);
++			(unsigned char) data[0], (unsigned char) data[1]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_INITCOMPARELOGIC:
+@@ -125,8 +125,8 @@ INT i_APCI1710_InsnConfigINCCPT(struct comedi_device * dev, struct comedi_subdev
+ 	case APCI1710_INCCPT_INITFREQUENCYMEASUREMENT:
+ 		i_ReturnValue = i_APCI1710_InitFrequencyMeasurement(dev,
+ 			CR_AREF(insn->chanspec),
+-			(BYTE) data[0],
+-			(BYTE) data[1], (ULONG) data[2], (PULONG) & data[0]);
++			(unsigned char) data[0],
++			(unsigned char) data[1], (ULONG) data[2], (PULONG) & data[0]);
+ 		break;
+ 
+ 	default:
+@@ -142,13 +142,13 @@ INT i_APCI1710_InsnConfigINCCPT(struct comedi_device * dev, struct comedi_subdev
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_InitCounter                           |
+-|                               (BYTE_          b_BoardHandle,               |
+-|                                BYTE_          b_ModulNbr,                  |
+-|                                BYTE_          b_CounterRange,              |
+-|                                BYTE_          b_FirstCounterModus,         |
+-|                                BYTE_          b_FirstCounterOption,        |
+-|                                BYTE_          b_SecondCounterModus,        |
+-|                                BYTE_          b_SecondCounterOption)       |
++|                               (unsigned char_          b_BoardHandle,               |
++|                                unsigned char_          b_ModulNbr,                  |
++|                                unsigned char_          b_CounterRange,              |
++|                                unsigned char_          b_FirstCounterModus,         |
++|                                unsigned char_          b_FirstCounterOption,        |
++|                                unsigned char_          b_SecondCounterModus,        |
++|                                unsigned char_          b_SecondCounterOption)       |
+ +----------------------------------------------------------------------------+
+ | Task              : Configure the counter operating mode from selected     |
+ |                     module (b_ModulNbr). You must calling this function be |
+@@ -273,17 +273,17 @@ INT i_APCI1710_InsnConfigINCCPT(struct comedi_device * dev, struct comedi_subdev
+ | +----------------------+--------------------+----------------------------+ |
+ |                                                                            |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle         : Handle of board APCI-1710|
+-|                     BYTE_ b_ModulNbr            : Module number to         |
++| Input Parameters  : unsigned char_ b_BoardHandle         : Handle of board APCI-1710|
++|                     unsigned char_ b_ModulNbr            : Module number to         |
+ |                                                   configure (0 to 3)       |
+-|                     BYTE_ b_CounterRange        : Selection form counter   |
++|                     unsigned char_ b_CounterRange        : Selection form counter   |
+ |                                                   range.                   |
+-|                     BYTE_ b_FirstCounterModus   : First counter operating  |
++|                     unsigned char_ b_FirstCounterModus   : First counter operating  |
+ |                                                   mode.                    |
+-|                     BYTE_ b_FirstCounterOption  : First counter  option.   |
+-|                     BYTE_ b_SecondCounterModus  : Second counter operating |
++|                     unsigned char_ b_FirstCounterOption  : First counter  option.   |
++|                     unsigned char_ b_SecondCounterModus  : Second counter operating |
+ |                                                   mode.                    |
+-|                     BYTE_ b_SecondCounterOption : Second counter  option.  |
++|                     unsigned char_ b_SecondCounterOption : Second counter  option.  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+ +----------------------------------------------------------------------------+
+@@ -300,11 +300,11 @@ INT i_APCI1710_InsnConfigINCCPT(struct comedi_device * dev, struct comedi_subdev
+ */
+ 
+ INT i_APCI1710_InitCounter(struct comedi_device * dev,
+-	BYTE b_ModulNbr,
+-	BYTE b_CounterRange,
+-	BYTE b_FirstCounterModus,
+-	BYTE b_FirstCounterOption,
+-	BYTE b_SecondCounterModus, BYTE b_SecondCounterOption)
++	unsigned char b_ModulNbr,
++	unsigned char b_CounterRange,
++	unsigned char b_FirstCounterModus,
++	unsigned char b_FirstCounterOption,
++	unsigned char b_SecondCounterModus, unsigned char b_SecondCounterOption)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -508,8 +508,8 @@ INT i_APCI1710_InitCounter(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_CounterAutoTest                       |
+-|                                               (BYTE_     b_BoardHandle,    |
+-|                                                PBYTE_   pb_TestStatus)     |
++|                                               (unsigned char_     b_BoardHandle,    |
++|                                                unsigned char *_   pb_TestStatus)     |
+ +----------------------------------------------------------------------------+
+ | Task              : A test mode is intended for testing the component and  |
+ |                     the connected periphery. All the 8-bit counter chains  |
+@@ -535,9 +535,9 @@ INT i_APCI1710_InitCounter(struct comedi_device * dev,
+ |              |    1000         | Error detected of counter 3 |             |
+ |              +-----------------+-----------------------------+             |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_   b_BoardHandle : Handle of board APCI-1710      |  |
++| Input Parameters  : unsigned char_   b_BoardHandle : Handle of board APCI-1710      |  |
+ +----------------------------------------------------------------------------+
+-| Output Parameters : PBYTE_ pb_TestStatus  : Auto test conclusion. See table|
++| Output Parameters : unsigned char *_ pb_TestStatus  : Auto test conclusion. See table|
+ +----------------------------------------------------------------------------+
+ | Return Value      :  0: No error                                           |
+ |                     -1: The handle parameter of the board is wrong         |
+@@ -545,9 +545,9 @@ INT i_APCI1710_InitCounter(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_CounterAutoTest(struct comedi_device * dev, PBYTE pb_TestStatus)
++INT i_APCI1710_CounterAutoTest(struct comedi_device * dev, unsigned char * pb_TestStatus)
+ {
+-	BYTE b_ModulCpt = 0;
++	unsigned char b_ModulCpt = 0;
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_LathchValue;
+ 
+@@ -632,12 +632,12 @@ INT i_APCI1710_CounterAutoTest(struct comedi_device * dev, PBYTE pb_TestStatus)
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     : _INT_ i_APCI1710_InitIndex (BYTE_ b_BoardHandle,       |
+-|                                                 BYTE_ b_ModulNbr,          |
+-|                                                 BYTE_ b_ReferenceAction,   |
+-|                                                 BYTE_ b_IndexOperation,    |
+-|                                                 BYTE_ b_AutoMode,          |
+-|                                                 BYTE_ b_InterruptEnable)   |
++| Function Name     : _INT_ i_APCI1710_InitIndex (unsigned char_ b_BoardHandle,       |
++|                                                 unsigned char_ b_ModulNbr,          |
++|                                                 unsigned char_ b_ReferenceAction,   |
++|                                                 unsigned char_ b_IndexOperation,    |
++|                                                 unsigned char_ b_AutoMode,          |
++|                                                 unsigned char_ b_InterruptEnable)   |
+ +----------------------------------------------------------------------------+
+ | Task              : Initialise the index corresponding to the selected     |
+ |                     module (b_ModulNbr). If a INDEX flag occur, you have   |
+@@ -665,10 +665,10 @@ INT i_APCI1710_CounterAutoTest(struct comedi_device * dev, PBYTE pb_TestStatus)
+ |           |                        | value is cleared (32-Bit)          |  |
+ |           +------------------------+------------------------------------+  |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+-|                     BYTE_ b_ModulNbr        : Module number to configure   |
++| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
++|                     unsigned char_ b_ModulNbr        : Module number to configure   |
+ |                                               (0 to 3)                     |
+-|                     BYTE_ b_ReferenceAction : Determine if the reference   |
++|                     unsigned char_ b_ReferenceAction : Determine if the reference   |
+ |                                               must set or no for the       |
+ |                                               acceptance from index        |
+ |                                               APCI1710_ENABLE :            |
+@@ -677,15 +677,15 @@ INT i_APCI1710_CounterAutoTest(struct comedi_device * dev, PBYTE pb_TestStatus)
+ |                                               APCI1710_DISABLE :           |
+ |                                                  Reference have not        |
+ |                                                  importance                |
+-|                     BYTE_ b_IndexOperation  : Index operating mode.        |
++|                     unsigned char_ b_IndexOperation  : Index operating mode.        |
+ |                                               See table.                   |
+-|                     BYTE_ b_AutoMode        : Enable or disable the        |
++|                     unsigned char_ b_AutoMode        : Enable or disable the        |
+ |                                               automatic index reset.       |
+ |                                               APCI1710_ENABLE :            |
+ |                                                 Enable the automatic mode  |
+ |                                               APCI1710_DISABLE :           |
+ |                                                 Disable the automatic mode |
+-|                     BYTE_ b_InterruptEnable : Enable or disable the        |
++|                     unsigned char_ b_InterruptEnable : Enable or disable the        |
+ |                                               interrupt.                   |
+ |                                               APCI1710_ENABLE :            |
+ |                                               Enable the interrupt         |
+@@ -709,9 +709,9 @@ INT i_APCI1710_CounterAutoTest(struct comedi_device * dev, PBYTE pb_TestStatus)
+ */
+ 
+ INT i_APCI1710_InitIndex(struct comedi_device * dev,
+-	BYTE b_ModulNbr,
+-	BYTE b_ReferenceAction,
+-	BYTE b_IndexOperation, BYTE b_AutoMode, BYTE b_InterruptEnable)
++	unsigned char b_ModulNbr,
++	unsigned char b_ReferenceAction,
++	unsigned char b_IndexOperation, unsigned char b_AutoMode, unsigned char b_InterruptEnable)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -1119,9 +1119,9 @@ INT i_APCI1710_InitIndex(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_InitReference                         |
+-|                                                (BYTE_ b_BoardHandle,       |
+-|                                                 BYTE_ b_ModulNbr,          |
+-|                                                 BYTE_ b_ReferenceLevel)    |
++|                                                (unsigned char_ b_BoardHandle,       |
++|                                                 unsigned char_ b_ModulNbr,          |
++|                                                 unsigned char_ b_ReferenceLevel)    |
+ +----------------------------------------------------------------------------+
+ | Task              : Initialise the reference corresponding to the selected |
+ |                     module (b_ModulNbr).                                   |
+@@ -1136,10 +1136,10 @@ INT i_APCI1710_InitIndex(struct comedi_device * dev,
+ |             |   APCI1710_HIGH    |  Reference occur if "1" |               |
+ |             +--------------------+-------------------------+               |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+-|                     BYTE_ b_ModulNbr        : Module number to configure   |
++| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
++|                     unsigned char_ b_ModulNbr        : Module number to configure   |
+ |                                               (0 to 3)                     |
+-|                     BYTE_ b_ReferenceLevel  : Reference level.             |
++|                     unsigned char_ b_ReferenceLevel  : Reference level.             |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+ +----------------------------------------------------------------------------+
+@@ -1153,7 +1153,7 @@ INT i_APCI1710_InitIndex(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_InitReference(struct comedi_device * dev,
+-	BYTE b_ModulNbr, BYTE b_ReferenceLevel)
++	unsigned char b_ModulNbr, unsigned char b_ReferenceLevel)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -1245,21 +1245,21 @@ INT i_APCI1710_InitReference(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_	i_APCI1710_InitExternalStrobe                |
+-|					(BYTE_ b_BoardHandle,                |
+-|					 BYTE_ b_ModulNbr,                   |
+-|					 BYTE_ b_ExternalStrobe,             |
+-|					 BYTE_ b_ExternalStrobeLevel)        |
++|					(unsigned char_ b_BoardHandle,                |
++|					 unsigned char_ b_ModulNbr,                   |
++|					 unsigned char_ b_ExternalStrobe,             |
++|					 unsigned char_ b_ExternalStrobeLevel)        |
+ +----------------------------------------------------------------------------+
+ | Task              : Initialises the external strobe level corresponding to |
+ |		      the selected module (b_ModulNbr).                      |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+-|                     BYTE_ b_ModulNbr        : Module number to configure   |
++| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
++|                     unsigned char_ b_ModulNbr        : Module number to configure   |
+ |                                               (0 to 3)                     |
+-|		      BYTE_ b_ExternalStrobe  : External strobe selection    |
++|		      unsigned char_ b_ExternalStrobe  : External strobe selection    |
+ |						0 : External strobe A        |
+ |						1 : External strobe B        |
+-|		      BYTE_ b_ExternalStrobeLevel : External strobe level    |
++|		      unsigned char_ b_ExternalStrobeLevel : External strobe level    |
+ |						APCI1710_LOW :               |
+ |						External latch occurs if "0" |
+ |						APCI1710_HIGH :              |
+@@ -1278,7 +1278,7 @@ INT i_APCI1710_InitReference(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_InitExternalStrobe(struct comedi_device * dev,
+-	BYTE b_ModulNbr, BYTE b_ExternalStrobe, BYTE b_ExternalStrobeLevel)
++	unsigned char b_ModulNbr, unsigned char b_ExternalStrobe, unsigned char b_ExternalStrobeLevel)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -1368,16 +1368,16 @@ INT i_APCI1710_InitExternalStrobe(struct comedi_device * dev,
+ 	/*
+ 	   +----------------------------------------------------------------------------+
+ 	   | Function Name     : _INT_ i_APCI1710_InitCompareLogic                      |
+-	   |                               (BYTE_   b_BoardHandle,                      |
+-	   |                                BYTE_   b_ModulNbr,                         |
++	   |                               (unsigned char_   b_BoardHandle,                      |
++	   |                                unsigned char_   b_ModulNbr,                         |
+ 	   |                                UINT_  ui_CompareValue)                     |
+ 	   +----------------------------------------------------------------------------+
+ 	   | Task              : Set the 32-Bit compare value. At that moment that the  |
+ 	   |                     incremental counter arrive to the compare value        |
+ 	   |                     (ui_CompareValue) a interrupt is generated.            |
+ 	   +----------------------------------------------------------------------------+
+-	   | Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |
+-	   |                     BYTE_  b_ModulNbr       : Module number to configure   |
++	   | Input Parameters  : unsigned char_  b_BoardHandle    : Handle of board APCI-1710    |
++	   |                     unsigned char_  b_ModulNbr       : Module number to configure   |
+ 	   |                                               (0 to 3)                     |
+ 	   |                     UINT_ ui_CompareValue   : 32-Bit compare value         |
+ 	   +----------------------------------------------------------------------------+
+@@ -1392,7 +1392,7 @@ INT i_APCI1710_InitExternalStrobe(struct comedi_device * dev,
+ 	 */
+ 
+ INT i_APCI1710_InitCompareLogic(struct comedi_device * dev,
+-	BYTE b_ModulNbr, UINT ui_CompareValue)
++	unsigned char b_ModulNbr, UINT ui_CompareValue)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -1440,10 +1440,10 @@ INT i_APCI1710_InitCompareLogic(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_InitFrequencyMeasurement              |
+-|				(BYTE_		 b_BoardHandle,              |
+-|				 BYTE_		 b_ModulNbr,                 |
+-|				 BYTE_		 b_PCIInputClock,            |
+-|				 BYTE_		 b_TimingUnity,              |
++|				(unsigned char_		 b_BoardHandle,              |
++|				 unsigned char_		 b_ModulNbr,                 |
++|				 unsigned char_		 b_PCIInputClock,            |
++|				 unsigned char_		 b_TimingUnity,              |
+ |				 ULONG_ 	ul_TimingInterval,           |
+ |				 PULONG_       pul_RealTimingInterval)       |
+ +----------------------------------------------------------------------------+
+@@ -1456,10 +1456,10 @@ INT i_APCI1710_InitCompareLogic(struct comedi_device * dev,
+ |		      you call up any other function which gives access to   |
+ |		      the frequency measurement.                             |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |
+-|		      BYTE_  b_ModulNbr	      :	Number of the module to be   |
++| Input Parameters  : unsigned char_  b_BoardHandle    : Handle of board APCI-1710    |
++|		      unsigned char_  b_ModulNbr	      :	Number of the module to be   |
+ |						configured (0 to 3)          |
+-|		      BYTE_  b_PCIInputClock  :	Selection of the PCI bus     |
++|		      unsigned char_  b_PCIInputClock  :	Selection of the PCI bus     |
+ |						clock                        |
+ |						- APCI1710_30MHZ :           |
+ |						  The PC has a PCI bus clock |
+@@ -1467,7 +1467,7 @@ INT i_APCI1710_InitCompareLogic(struct comedi_device * dev,
+ |						- APCI1710_33MHZ :           |
+ |						  The PC has a PCI bus clock |
+ |						  of 33 MHz                  |
+-|		      BYTE_  b_TimingUnity    : Base time unit (0 to 2)      |
++|		      unsigned char_  b_TimingUnity    : Base time unit (0 to 2)      |
+ |						  0 : ns                     |
+ |						  1 : æs                     |
+ |						  2 : ms                     |
+@@ -1488,9 +1488,9 @@ INT i_APCI1710_InitCompareLogic(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_InitFrequencyMeasurement(struct comedi_device * dev,
+-	BYTE b_ModulNbr,
+-	BYTE b_PCIInputClock,
+-	BYTE b_TimingUnity,
++	unsigned char b_ModulNbr,
++	unsigned char b_PCIInputClock,
++	unsigned char b_TimingUnity,
+ 	ULONG ul_TimingInterval, PULONG pul_RealTimingInterval)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -2026,7 +2026,7 @@ INT i_APCI1710_InsnBitsINCCPT(struct comedi_device * dev, struct comedi_subdevic
+ 	switch (ui_BitsType) {
+ 	case APCI1710_INCCPT_CLEARCOUNTERVALUE:
+ 		i_ReturnValue = i_APCI1710_ClearCounterValue(dev,
+-			(BYTE) CR_AREF(insn->chanspec));
++			(unsigned char) CR_AREF(insn->chanspec));
+ 		break;
+ 
+ 	case APCI1710_INCCPT_CLEARALLCOUNTERVALUE:
+@@ -2035,28 +2035,28 @@ INT i_APCI1710_InsnBitsINCCPT(struct comedi_device * dev, struct comedi_subdevic
+ 
+ 	case APCI1710_INCCPT_SETINPUTFILTER:
+ 		i_ReturnValue = i_APCI1710_SetInputFilter(dev,
+-			(BYTE) CR_AREF(insn->chanspec),
+-			(BYTE) data[0], (BYTE) data[1]);
++			(unsigned char) CR_AREF(insn->chanspec),
++			(unsigned char) data[0], (unsigned char) data[1]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_LATCHCOUNTER:
+ 		i_ReturnValue = i_APCI1710_LatchCounter(dev,
+-			(BYTE) CR_AREF(insn->chanspec), (BYTE) data[0]);
++			(unsigned char) CR_AREF(insn->chanspec), (unsigned char) data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_SETINDEXANDREFERENCESOURCE:
+ 		i_ReturnValue = i_APCI1710_SetIndexAndReferenceSource(dev,
+-			(BYTE) CR_AREF(insn->chanspec), (BYTE) data[0]);
++			(unsigned char) CR_AREF(insn->chanspec), (unsigned char) data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_SETDIGITALCHLON:
+ 		i_ReturnValue = i_APCI1710_SetDigitalChlOn(dev,
+-			(BYTE) CR_AREF(insn->chanspec));
++			(unsigned char) CR_AREF(insn->chanspec));
+ 		break;
+ 
+ 	case APCI1710_INCCPT_SETDIGITALCHLOFF:
+ 		i_ReturnValue = i_APCI1710_SetDigitalChlOff(dev,
+-			(BYTE) CR_AREF(insn->chanspec));
++			(unsigned char) CR_AREF(insn->chanspec));
+ 		break;
+ 
+ 	default:
+@@ -2071,14 +2071,14 @@ INT i_APCI1710_InsnBitsINCCPT(struct comedi_device * dev, struct comedi_subdevic
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_ClearCounterValue                     |
+-|                               (BYTE_      b_BoardHandle,                   |
+-|                                BYTE_       b_ModulNbr)                     |
++|                               (unsigned char_      b_BoardHandle,                   |
++|                                unsigned char_       b_ModulNbr)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Clear the counter value from selected module           |
+ |                     (b_ModulNbr).                                          |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle : Handle of board APCI-1710        |
+-|                     BYTE_ b_ModulNbr    : Module number to configure       |
++| Input Parameters  : unsigned char_ b_BoardHandle : Handle of board APCI-1710        |
++|                     unsigned char_ b_ModulNbr    : Module number to configure       |
+ |                                           (0 to 3)                         |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+@@ -2091,7 +2091,7 @@ INT i_APCI1710_InsnBitsINCCPT(struct comedi_device * dev, struct comedi_subdevic
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_ClearCounterValue(struct comedi_device * dev, BYTE b_ModulNbr)
++INT i_APCI1710_ClearCounterValue(struct comedi_device * dev, unsigned char b_ModulNbr)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -2137,11 +2137,11 @@ INT i_APCI1710_ClearCounterValue(struct comedi_device * dev, BYTE b_ModulNbr)
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_ClearAllCounterValue                  |
+-|                               (BYTE_      b_BoardHandle)                   |
++|                               (unsigned char_      b_BoardHandle)                   |
+ +----------------------------------------------------------------------------+
+ | Task              : Clear all counter value.                               |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle : Handle of board APCI-1710        |
++| Input Parameters  : unsigned char_ b_BoardHandle : Handle of board APCI-1710        |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+ +----------------------------------------------------------------------------+
+@@ -2153,7 +2153,7 @@ INT i_APCI1710_ClearCounterValue(struct comedi_device * dev, BYTE b_ModulNbr)
+ 
+ INT i_APCI1710_ClearAllCounterValue(struct comedi_device * dev)
+ {
+-	BYTE b_ModulCpt = 0;
++	unsigned char b_ModulCpt = 0;
+ 	INT i_ReturnValue = 0;
+ 
+ 	/********************************/
+@@ -2204,18 +2204,18 @@ INT i_APCI1710_ClearAllCounterValue(struct comedi_device * dev)
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_SetInputFilter                        |
+-|					(BYTE_ b_BoardHandle,                |
+-|					 BYTE_ b_Module,                     |
+-|					 BYTE_ b_PCIInputClock,              |
+-|					 BYTE_ b_Filter)     		     |
++|					(unsigned char_ b_BoardHandle,                |
++|					 unsigned char_ b_Module,                     |
++|					 unsigned char_ b_PCIInputClock,              |
++|					 unsigned char_ b_Filter)     		     |
+ +----------------------------------------------------------------------------+
+ | Task              : Disable or enable the software filter from selected    |
+ |		      module (b_ModulNbr). b_Filter determine the filter time|
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |
+-|		      BYTE_  b_ModulNbr	      :	Number of the module to be   |
++| Input Parameters  : unsigned char_  b_BoardHandle    : Handle of board APCI-1710    |
++|		      unsigned char_  b_ModulNbr	      :	Number of the module to be   |
+ |						configured (0 to 3)          |
+-|		      BYTE_  b_PCIInputClock  :	Selection of the PCI bus     |
++|		      unsigned char_  b_PCIInputClock  :	Selection of the PCI bus     |
+ |						clock                        |
+ |						- APCI1710_30MHZ :           |
+ |						  The PC has a PCI bus clock |
+@@ -2226,7 +2226,7 @@ INT i_APCI1710_ClearAllCounterValue(struct comedi_device * dev)
+ |						- APCI1710_40MHZ :           |
+ |						  The APCI1710 has a 40MHz    |
+ |						  quartz		     |
+-|		      BYTE_  b_Filter	      : Filter selection             |
++|		      unsigned char_  b_Filter	      : Filter selection             |
+ |                                                                            |
+ |				30 MHz                                       |
+ |				------                                       |
+@@ -2298,7 +2298,7 @@ INT i_APCI1710_ClearAllCounterValue(struct comedi_device * dev)
+ */
+ 
+ INT i_APCI1710_SetInputFilter(struct comedi_device * dev,
+-	BYTE b_ModulNbr, BYTE b_PCIInputClock, BYTE b_Filter)
++	unsigned char b_ModulNbr, unsigned char b_PCIInputClock, unsigned char b_Filter)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_Status = 0;
+@@ -2535,18 +2535,18 @@ INT i_APCI1710_SetInputFilter(struct comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     : _INT_ i_APCI1710_LatchCounter (BYTE_ b_BoardHandle,    |
+-|                                                    BYTE_ b_ModulNbr,       |
+-|                                                    BYTE_ b_LatchReg)       |
++| Function Name     : _INT_ i_APCI1710_LatchCounter (unsigned char_ b_BoardHandle,    |
++|                                                    unsigned char_ b_ModulNbr,       |
++|                                                    unsigned char_ b_LatchReg)       |
+ +----------------------------------------------------------------------------+
+ | Task              : Latch the courant value from selected module           |
+ |                     (b_ModulNbr) in to the selected latch register         |
+ |                     (b_LatchReg).                                          |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle : Handle of board APCI-1710        |
+-|                     BYTE_ b_ModulNbr    : Module number to configure       |
++| Input Parameters  : unsigned char_ b_BoardHandle : Handle of board APCI-1710        |
++|                     unsigned char_ b_ModulNbr    : Module number to configure       |
+ |                                           (0 to 3)                         |
+-|                     BYTE_ b_LatchReg    : Selected latch register          |
++|                     unsigned char_ b_LatchReg    : Selected latch register          |
+ |                               0 : for the first latch register             |
+ |                               1 : for the second latch register            |
+ +----------------------------------------------------------------------------+
+@@ -2562,7 +2562,7 @@ INT i_APCI1710_SetInputFilter(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_LatchCounter(struct comedi_device * dev,
+-	BYTE b_ModulNbr, BYTE b_LatchReg)
++	unsigned char b_ModulNbr, unsigned char b_LatchReg)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -2622,19 +2622,19 @@ INT i_APCI1710_LatchCounter(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_	i_APCI1710_SetIndexAndReferenceSource        |
+-|					(BYTE_ b_BoardHandle,                |
+-|					 BYTE_ b_ModulNbr,                   |
+-|					 BYTE_ b_SourceSelection)            |
++|					(unsigned char_ b_BoardHandle,                |
++|					 unsigned char_ b_ModulNbr,                   |
++|					 unsigned char_ b_SourceSelection)            |
+ +----------------------------------------------------------------------------+
+ | Task              : Determine the hardware source for the index and the    |
+ |		      reference logic. Per default the index logic is        |
+ |		      connected to the difference input C and the reference  |
+ |		      logic is connected to the 24V input E                  |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+-|                     BYTE_ b_ModulNbr        : Module number to configure   |
++| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
++|                     unsigned char_ b_ModulNbr        : Module number to configure   |
+ |                                               (0 to 3)                     |
+-|		      BYTE_ b_SourceSelection : APCI1710_SOURCE_0 :          |
++|		      unsigned char_ b_SourceSelection : APCI1710_SOURCE_0 :          |
+ |						The index logic is connected |
+ |						to the difference input C and|
+ |						the reference logic is       |
+@@ -2659,7 +2659,7 @@ INT i_APCI1710_LatchCounter(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_SetIndexAndReferenceSource(struct comedi_device * dev,
+-	BYTE b_ModulNbr, BYTE b_SourceSelection)
++	unsigned char b_ModulNbr, unsigned char b_SourceSelection)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -2775,14 +2775,14 @@ INT i_APCI1710_SetIndexAndReferenceSource(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_	i_APCI1710_SetDigitalChlOn                   |
+-|				   (BYTE_  b_BoardHandle,                    |
+-|				    BYTE_  b_ModulNbr)                       |
++|				   (unsigned char_  b_BoardHandle,                    |
++|				    unsigned char_  b_ModulNbr)                       |
+ +----------------------------------------------------------------------------+
+ | Task              : Sets the digital output H Setting an output means      |
+ |		      setting an ouput high.                                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |
+-|		      BYTE_  b_ModulNbr	      :	Number of the module to be   |
++| Input Parameters  : unsigned char_  b_BoardHandle    : Handle of board APCI-1710    |
++|		      unsigned char_  b_ModulNbr	      :	Number of the module to be   |
+ |						configured (0 to 3)          |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+@@ -2795,7 +2795,7 @@ INT i_APCI1710_SetIndexAndReferenceSource(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_SetDigitalChlOn(struct comedi_device * dev, BYTE b_ModulNbr)
++INT i_APCI1710_SetDigitalChlOn(struct comedi_device * dev, unsigned char b_ModulNbr)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -2855,14 +2855,14 @@ INT i_APCI1710_SetDigitalChlOn(struct comedi_device * dev, BYTE b_ModulNbr)
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_	i_APCI1710_SetDigitalChlOff                  |
+-|				   (BYTE_  b_BoardHandle,                    |
+-|				    BYTE_  b_ModulNbr)                       |
++|				   (unsigned char_  b_BoardHandle,                    |
++|				    unsigned char_  b_ModulNbr)                       |
+ +----------------------------------------------------------------------------+
+ | Task              : Resets the digital output H. Resetting an output means |
+ |		      setting an ouput low.                                  |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |
+-|		      BYTE_  b_ModulNbr	      :	Number of the module to be   |
++| Input Parameters  : unsigned char_  b_BoardHandle    : Handle of board APCI-1710    |
++|		      unsigned char_  b_ModulNbr	      :	Number of the module to be   |
+ |						configured (0 to 3)          |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+@@ -2875,7 +2875,7 @@ INT i_APCI1710_SetDigitalChlOn(struct comedi_device * dev, BYTE b_ModulNbr)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_SetDigitalChlOff(struct comedi_device * dev, BYTE b_ModulNbr)
++INT i_APCI1710_SetDigitalChlOff(struct comedi_device * dev, unsigned char b_ModulNbr)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -2963,53 +2963,53 @@ INT i_APCI1710_InsnWriteINCCPT(struct comedi_device * dev, struct comedi_subdevi
+ 	switch (ui_WriteType) {
+ 	case APCI1710_INCCPT_ENABLELATCHINTERRUPT:
+ 		i_ReturnValue = i_APCI1710_EnableLatchInterrupt(dev,
+-			(BYTE) CR_AREF(insn->chanspec));
++			(unsigned char) CR_AREF(insn->chanspec));
+ 		break;
+ 
+ 	case APCI1710_INCCPT_DISABLELATCHINTERRUPT:
+ 		i_ReturnValue = i_APCI1710_DisableLatchInterrupt(dev,
+-			(BYTE) CR_AREF(insn->chanspec));
++			(unsigned char) CR_AREF(insn->chanspec));
+ 		break;
+ 
+ 	case APCI1710_INCCPT_WRITE16BITCOUNTERVALUE:
+ 		i_ReturnValue = i_APCI1710_Write16BitCounterValue(dev,
+-			(BYTE) CR_AREF(insn->chanspec),
+-			(BYTE) data[0], (UINT) data[1]);
++			(unsigned char) CR_AREF(insn->chanspec),
++			(unsigned char) data[0], (UINT) data[1]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_WRITE32BITCOUNTERVALUE:
+ 		i_ReturnValue = i_APCI1710_Write32BitCounterValue(dev,
+-			(BYTE) CR_AREF(insn->chanspec), (ULONG) data[0]);
++			(unsigned char) CR_AREF(insn->chanspec), (ULONG) data[0]);
+ 
+ 		break;
+ 
+ 	case APCI1710_INCCPT_ENABLEINDEX:
+-		i_APCI1710_EnableIndex(dev, (BYTE) CR_AREF(insn->chanspec));
++		i_APCI1710_EnableIndex(dev, (unsigned char) CR_AREF(insn->chanspec));
+ 		break;
+ 
+ 	case APCI1710_INCCPT_DISABLEINDEX:
+ 		i_ReturnValue = i_APCI1710_DisableIndex(dev,
+-			(BYTE) CR_AREF(insn->chanspec));
++			(unsigned char) CR_AREF(insn->chanspec));
+ 		break;
+ 
+ 	case APCI1710_INCCPT_ENABLECOMPARELOGIC:
+ 		i_ReturnValue = i_APCI1710_EnableCompareLogic(dev,
+-			(BYTE) CR_AREF(insn->chanspec));
++			(unsigned char) CR_AREF(insn->chanspec));
+ 		break;
+ 
+ 	case APCI1710_INCCPT_DISABLECOMPARELOGIC:
+ 		i_ReturnValue = i_APCI1710_DisableCompareLogic(dev,
+-			(BYTE) CR_AREF(insn->chanspec));
++			(unsigned char) CR_AREF(insn->chanspec));
+ 		break;
+ 
+ 	case APCI1710_INCCPT_ENABLEFREQUENCYMEASUREMENT:
+ 		i_ReturnValue = i_APCI1710_EnableFrequencyMeasurement(dev,
+-			(BYTE) CR_AREF(insn->chanspec), (BYTE) data[0]);
++			(unsigned char) CR_AREF(insn->chanspec), (unsigned char) data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_DISABLEFREQUENCYMEASUREMENT:
+ 		i_ReturnValue = i_APCI1710_DisableFrequencyMeasurement(dev,
+-			(BYTE) CR_AREF(insn->chanspec));
++			(unsigned char) CR_AREF(insn->chanspec));
+ 		break;
+ 
+ 	default:
+@@ -3024,15 +3024,15 @@ INT i_APCI1710_InsnWriteINCCPT(struct comedi_device * dev, struct comedi_subdevi
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_EnableLatchInterrupt                  |
+-|                               (BYTE_ b_BoardHandle,                        |
+-|                                BYTE_ b_ModulNbr)                           |
++|                               (unsigned char_ b_BoardHandle,                        |
++|                                unsigned char_ b_ModulNbr)                           |
+ +----------------------------------------------------------------------------+
+ | Task              : Enable the latch interrupt from selected module        |
+ |                     (b_ModulNbr). Each software or hardware latch occur a  |
+ |                     interrupt.                                             |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle : Handle of board APCI-1710        |
+-|                     BYTE_ b_ModulNbr    : Module number to configure       |
++| Input Parameters  : unsigned char_ b_BoardHandle : Handle of board APCI-1710        |
++|                     unsigned char_ b_ModulNbr    : Module number to configure       |
+ |                                           (0 to 3)                         |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+@@ -3047,7 +3047,7 @@ INT i_APCI1710_InsnWriteINCCPT(struct comedi_device * dev, struct comedi_subdevi
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_EnableLatchInterrupt(struct comedi_device * dev, BYTE b_ModulNbr)
++INT i_APCI1710_EnableLatchInterrupt(struct comedi_device * dev, unsigned char b_ModulNbr)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -3111,14 +3111,14 @@ INT i_APCI1710_EnableLatchInterrupt(struct comedi_device * dev, BYTE b_ModulNbr)
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_DisableLatchInterrupt                 |
+-|                               (BYTE_ b_BoardHandle,                        |
+-|                                BYTE_ b_ModulNbr)                           |
++|                               (unsigned char_ b_BoardHandle,                        |
++|                                unsigned char_ b_ModulNbr)                           |
+ +----------------------------------------------------------------------------+
+ | Task              : Disable the latch interrupt from selected module       |
+ |                     (b_ModulNbr).                                          |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle : Handle of board APCI-1710        |
+-|                     BYTE_ b_ModulNbr    : Module number to configure       |
++| Input Parameters  : unsigned char_ b_BoardHandle : Handle of board APCI-1710        |
++|                     unsigned char_ b_ModulNbr    : Module number to configure       |
+ |                                           (0 to 3)                         |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+@@ -3133,7 +3133,7 @@ INT i_APCI1710_EnableLatchInterrupt(struct comedi_device * dev, BYTE b_ModulNbr)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_DisableLatchInterrupt(struct comedi_device * dev, BYTE b_ModulNbr)
++INT i_APCI1710_DisableLatchInterrupt(struct comedi_device * dev, unsigned char b_ModulNbr)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -3204,19 +3204,19 @@ INT i_APCI1710_DisableLatchInterrupt(struct comedi_device * dev, BYTE b_ModulNbr
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_Write16BitCounterValue                |
+-|                                               (BYTE_  b_BoardHandle        |
+-|                                                BYTE_  b_ModulNbr,          |
+-|                                                BYTE_  b_SelectedCounter,   |
++|                                               (unsigned char_  b_BoardHandle        |
++|                                                unsigned char_  b_ModulNbr,          |
++|                                                unsigned char_  b_SelectedCounter,   |
+ |                                                UINT_ ui_WriteValue)        |
+ +----------------------------------------------------------------------------+
+ | Task              : Write a 16-Bit value (ui_WriteValue) in to the selected|
+ |                     16-Bit counter (b_SelectedCounter) from selected module|
+ |                     (b_ModulNbr).                                          |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+-|                     BYTE_ b_ModulNbr        : Module number to configure   |
++| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
++|                     unsigned char_ b_ModulNbr        : Module number to configure   |
+ |                                              (0 to 3)                      |
+-|                     BYTE_ b_SelectedCounter : Selected 16-Bit counter      |
++|                     unsigned char_ b_SelectedCounter : Selected 16-Bit counter      |
+ |                                               (0 or 1)                     |
+ |                     UINT_ ui_WriteValue     : 16-Bit write value           |
+ +----------------------------------------------------------------------------+
+@@ -3232,7 +3232,7 @@ INT i_APCI1710_DisableLatchInterrupt(struct comedi_device * dev, BYTE b_ModulNbr
+ */
+ 
+ INT i_APCI1710_Write16BitCounterValue(struct comedi_device * dev,
+-	BYTE b_ModulNbr, BYTE b_SelectedCounter, UINT ui_WriteValue)
++	unsigned char b_ModulNbr, unsigned char b_SelectedCounter, UINT ui_WriteValue)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -3294,15 +3294,15 @@ INT i_APCI1710_Write16BitCounterValue(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_Write32BitCounterValue                |
+-|                                               (BYTE_   b_BoardHandle       |
+-|                                                BYTE_   b_ModulNbr,         |
++|                                               (unsigned char_   b_BoardHandle       |
++|                                                unsigned char_   b_ModulNbr,         |
+ |                                                ULONG_ ul_WriteValue)       |
+ +----------------------------------------------------------------------------+
+ | Task              : Write a 32-Bit value (ui_WriteValue) in to the selected|
+ |                     module (b_ModulNbr).                                   |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+-|                     BYTE_ b_ModulNbr        : Module number to configure   |
++| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
++|                     unsigned char_ b_ModulNbr        : Module number to configure   |
+ |                                              (0 to 3)                      |
+ |                     ULONG_ ul_WriteValue    : 32-Bit write value           |
+ +----------------------------------------------------------------------------+
+@@ -3317,7 +3317,7 @@ INT i_APCI1710_Write16BitCounterValue(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_Write32BitCounterValue(struct comedi_device * dev,
+-	BYTE b_ModulNbr, ULONG ul_WriteValue)
++	unsigned char b_ModulNbr, ULONG ul_WriteValue)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -3362,13 +3362,13 @@ INT i_APCI1710_Write32BitCounterValue(struct comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     : _INT_ i_APCI1710_EnableIndex (BYTE_  b_BoardHandle,    |
+-|                                                   BYTE_  b_ModulNbr)       |
++| Function Name     : _INT_ i_APCI1710_EnableIndex (unsigned char_  b_BoardHandle,    |
++|                                                   unsigned char_  b_ModulNbr)       |
+ +----------------------------------------------------------------------------+
+ | Task              : Enable the INDEX actions                               |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+-|                     BYTE_ b_ModulNbr        : Module number to configure   |
++| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
++|                     unsigned char_ b_ModulNbr        : Module number to configure   |
+ |                                               (0 to 3)                     |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+@@ -3383,7 +3383,7 @@ INT i_APCI1710_Write32BitCounterValue(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_EnableIndex(struct comedi_device * dev, BYTE b_ModulNbr)
++INT i_APCI1710_EnableIndex(struct comedi_device * dev, unsigned char b_ModulNbr)
+ {
+ 	INT i_ReturnValue = 0;
+ 	ULONG ul_InterruptLatchReg;
+@@ -3460,13 +3460,13 @@ INT i_APCI1710_EnableIndex(struct comedi_device * dev, BYTE b_ModulNbr)
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     : _INT_ i_APCI1710_DisableIndex (BYTE_  b_BoardHandle,   |
+-|                                                    BYTE_  b_ModulNbr)      |
++| Function Name     : _INT_ i_APCI1710_DisableIndex (unsigned char_  b_BoardHandle,   |
++|                                                    unsigned char_  b_ModulNbr)      |
+ +----------------------------------------------------------------------------+
+ | Task              : Disable the INDEX actions                              |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+-|                     BYTE_ b_ModulNbr        : Module number to configure   |
++| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
++|                     unsigned char_ b_ModulNbr        : Module number to configure   |
+ |                                               (0 to 3)                     |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+@@ -3481,7 +3481,7 @@ INT i_APCI1710_EnableIndex(struct comedi_device * dev, BYTE b_ModulNbr)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_DisableIndex(struct comedi_device * dev, BYTE b_ModulNbr)
++INT i_APCI1710_DisableIndex(struct comedi_device * dev, unsigned char b_ModulNbr)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -3555,15 +3555,15 @@ INT i_APCI1710_DisableIndex(struct comedi_device * dev, BYTE b_ModulNbr)
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_EnableCompareLogic                    |
+-|                               (BYTE_   b_BoardHandle,                      |
+-|                                BYTE_   b_ModulNbr)                         |
++|                               (unsigned char_   b_BoardHandle,                      |
++|                                unsigned char_   b_ModulNbr)                         |
+ +----------------------------------------------------------------------------+
+ | Task              : Enable the 32-Bit compare logic. At that moment that   |
+ |                     the incremental counter arrive to the compare value a  |
+ |                     interrupt is generated.                                |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |
+-|                     BYTE_  b_ModulNbr       : Module number to configure   |
++| Input Parameters  : unsigned char_  b_BoardHandle    : Handle of board APCI-1710    |
++|                     unsigned char_  b_ModulNbr       : Module number to configure   |
+ |                                               (0 to 3)                     |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -
+@@ -3580,7 +3580,7 @@ INT i_APCI1710_DisableIndex(struct comedi_device * dev, BYTE b_ModulNbr)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_EnableCompareLogic(struct comedi_device * dev, BYTE b_ModulNbr)
++INT i_APCI1710_EnableCompareLogic(struct comedi_device * dev, unsigned char b_ModulNbr)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -3659,13 +3659,13 @@ INT i_APCI1710_EnableCompareLogic(struct comedi_device * dev, BYTE b_ModulNbr)
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_DisableCompareLogic                   |
+-|                               (BYTE_   b_BoardHandle,                      |
+-|                                BYTE_   b_ModulNbr)                         |
++|                               (unsigned char_   b_BoardHandle,                      |
++|                                unsigned char_   b_ModulNbr)                         |
+ +----------------------------------------------------------------------------+
+ | Task              : Disable the 32-Bit compare logic.
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |
+-|                     BYTE_  b_ModulNbr       : Module number to configure   |
++| Input Parameters  : unsigned char_  b_BoardHandle    : Handle of board APCI-1710    |
++|                     unsigned char_  b_ModulNbr       : Module number to configure   |
+ |                                               (0 to 3)                     |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -
+@@ -3680,7 +3680,7 @@ INT i_APCI1710_EnableCompareLogic(struct comedi_device * dev, BYTE b_ModulNbr)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_DisableCompareLogic(struct comedi_device * dev, BYTE b_ModulNbr)
++INT i_APCI1710_DisableCompareLogic(struct comedi_device * dev, unsigned char b_ModulNbr)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -3759,16 +3759,16 @@ INT i_APCI1710_DisableCompareLogic(struct comedi_device * dev, BYTE b_ModulNbr)
+ 	/*
+ 	   +----------------------------------------------------------------------------+
+ 	   | Function Name     : _INT_ i_APCI1710_EnableFrequencyMeasurement            |
+-	   |                            (BYTE_   b_BoardHandle,                      |
+-	   |                             BYTE_   b_ModulNbr,                         |
+-	   |                             BYTE_   b_InterruptEnable)                  |
++	   |                            (unsigned char_   b_BoardHandle,                      |
++	   |                             unsigned char_   b_ModulNbr,                         |
++	   |                             unsigned char_   b_InterruptEnable)                  |
+ 	   +----------------------------------------------------------------------------+
+ 	   | Task              : Enables the frequency measurement function             |
+ 	   +----------------------------------------------------------------------------+
+-	   | Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |
+-	   |                  BYTE_  b_ModulNbr       : Number of the module to be   |
++	   | Input Parameters  : unsigned char_  b_BoardHandle    : Handle of board APCI-1710    |
++	   |                  unsigned char_  b_ModulNbr       : Number of the module to be   |
+ 	   |                                            configured (0 to 3)          |
+-	   |                  BYTE_  b_InterruptEnable: Enable or disable the        |
++	   |                  unsigned char_  b_InterruptEnable: Enable or disable the        |
+ 	   |                                            interrupt.                   |
+ 	   |                                            APCI1710_ENABLE:             |
+ 	   |                                            Enable the interrupt         |
+@@ -3790,7 +3790,7 @@ INT i_APCI1710_DisableCompareLogic(struct comedi_device * dev, BYTE b_ModulNbr)
+ 	 */
+ 
+ INT i_APCI1710_EnableFrequencyMeasurement(struct comedi_device * dev,
+-	BYTE b_ModulNbr, BYTE b_InterruptEnable)
++	unsigned char b_ModulNbr, unsigned char b_InterruptEnable)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -3915,13 +3915,13 @@ INT i_APCI1710_EnableFrequencyMeasurement(struct comedi_device * dev,
+ 	/*
+ 	   +----------------------------------------------------------------------------+
+ 	   | Function Name     : _INT_ i_APCI1710_DisableFrequencyMeasurement           |
+-	   |                            (BYTE_   b_BoardHandle,                      |
+-	   |                             BYTE_   b_ModulNbr)                         |
++	   |                            (unsigned char_   b_BoardHandle,                      |
++	   |                             unsigned char_   b_ModulNbr)                         |
+ 	   +----------------------------------------------------------------------------+
+ 	   | Task              : Disables the frequency measurement function             |
+ 	   +----------------------------------------------------------------------------+
+-	   | Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |
+-	   |                  BYTE_  b_ModulNbr       : Number of the module to be   |
++	   | Input Parameters  : unsigned char_  b_BoardHandle    : Handle of board APCI-1710    |
++	   |                  unsigned char_  b_ModulNbr       : Number of the module to be   |
+ 	   |                                            configured (0 to 3)          |
+ 	   +----------------------------------------------------------------------------+
+ 	   | Output Parameters : -                                                      |
+@@ -3936,7 +3936,7 @@ INT i_APCI1710_EnableFrequencyMeasurement(struct comedi_device * dev,
+ 	   +----------------------------------------------------------------------------+
+ 	 */
+ 
+-INT i_APCI1710_DisableFrequencyMeasurement(struct comedi_device * dev, BYTE b_ModulNbr)
++INT i_APCI1710_DisableFrequencyMeasurement(struct comedi_device * dev, unsigned char b_ModulNbr)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -4061,70 +4061,70 @@ INT i_APCI1710_InsnReadINCCPT(struct comedi_device * dev, struct comedi_subdevic
+ 	switch (ui_ReadType) {
+ 	case APCI1710_INCCPT_READLATCHREGISTERSTATUS:
+ 		i_ReturnValue = i_APCI1710_ReadLatchRegisterStatus(dev,
+-			(BYTE) CR_AREF(insn->chanspec),
+-			(BYTE) CR_RANGE(insn->chanspec), (PBYTE) & data[0]);
++			(unsigned char) CR_AREF(insn->chanspec),
++			(unsigned char) CR_RANGE(insn->chanspec), (unsigned char *) & data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_READLATCHREGISTERVALUE:
+ 		i_ReturnValue = i_APCI1710_ReadLatchRegisterValue(dev,
+-			(BYTE) CR_AREF(insn->chanspec),
+-			(BYTE) CR_RANGE(insn->chanspec), (PULONG) & data[0]);
++			(unsigned char) CR_AREF(insn->chanspec),
++			(unsigned char) CR_RANGE(insn->chanspec), (PULONG) & data[0]);
+ 		printk("Latch Register Value %d\n", data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_READ16BITCOUNTERVALUE:
+ 		i_ReturnValue = i_APCI1710_Read16BitCounterValue(dev,
+-			(BYTE) CR_AREF(insn->chanspec),
+-			(BYTE) CR_RANGE(insn->chanspec), (PUINT) & data[0]);
++			(unsigned char) CR_AREF(insn->chanspec),
++			(unsigned char) CR_RANGE(insn->chanspec), (PUINT) & data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_READ32BITCOUNTERVALUE:
+ 		i_ReturnValue = i_APCI1710_Read32BitCounterValue(dev,
+-			(BYTE) CR_AREF(insn->chanspec), (PULONG) & data[0]);
++			(unsigned char) CR_AREF(insn->chanspec), (PULONG) & data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_GETINDEXSTATUS:
+ 		i_ReturnValue = i_APCI1710_GetIndexStatus(dev,
+-			(BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]);
++			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) & data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_GETREFERENCESTATUS:
+ 		i_ReturnValue = i_APCI1710_GetReferenceStatus(dev,
+-			(BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]);
++			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) & data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_GETUASSTATUS:
+ 		i_ReturnValue = i_APCI1710_GetUASStatus(dev,
+-			(BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]);
++			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) & data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_GETCBSTATUS:
+ 		i_ReturnValue = i_APCI1710_GetCBStatus(dev,
+-			(BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]);
++			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) & data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_GET16BITCBSTATUS:
+ 		i_ReturnValue = i_APCI1710_Get16BitCBStatus(dev,
+-			(BYTE) CR_AREF(insn->chanspec),
+-			(PBYTE) & data[0], (PBYTE) & data[1]);
++			(unsigned char) CR_AREF(insn->chanspec),
++			(unsigned char *) & data[0], (unsigned char *) & data[1]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_GETUDSTATUS:
+ 		i_ReturnValue = i_APCI1710_GetUDStatus(dev,
+-			(BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]);
++			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) & data[0]);
+ 
+ 		break;
+ 
+ 	case APCI1710_INCCPT_GETINTERRUPTUDLATCHEDSTATUS:
+ 		i_ReturnValue = i_APCI1710_GetInterruptUDLatchedStatus(dev,
+-			(BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]);
++			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) & data[0]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_READFREQUENCYMEASUREMENT:
+ 		i_ReturnValue = i_APCI1710_ReadFrequencyMeasurement(dev,
+-			(BYTE) CR_AREF(insn->chanspec),
+-			(PBYTE) & data[0],
+-			(PBYTE) & data[1], (PULONG) & data[2]);
++			(unsigned char) CR_AREF(insn->chanspec),
++			(unsigned char *) & data[0],
++			(unsigned char *) & data[1], (PULONG) & data[2]);
+ 		break;
+ 
+ 	case APCI1710_INCCPT_READINTERRUPT:
+@@ -4162,22 +4162,22 @@ INT i_APCI1710_InsnReadINCCPT(struct comedi_device * dev, struct comedi_subdevic
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_ReadLatchRegisterStatus               |
+-|                                                   (BYTE_   b_BoardHandle,  |
+-|                                                    BYTE_   b_ModulNbr,     |
+-|                                                    BYTE_   b_LatchReg,     |
+-|                                                    PBYTE_ pb_LatchStatus)  |
++|                                                   (unsigned char_   b_BoardHandle,  |
++|                                                    unsigned char_   b_ModulNbr,     |
++|                                                    unsigned char_   b_LatchReg,     |
++|                                                    unsigned char *_ pb_LatchStatus)  |
+ +----------------------------------------------------------------------------+
+ | Task              : Read the latch register status from selected module    |
+ |                     (b_ModulNbr) and selected latch register (b_LatchReg). |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle : Handle of board APCI-1710        |
+-|                     BYTE_ b_ModulNbr    : Module number to configure       |
++| Input Parameters  : unsigned char_ b_BoardHandle : Handle of board APCI-1710        |
++|                     unsigned char_ b_ModulNbr    : Module number to configure       |
+ |                                           (0 to 3)                         |
+-|                     BYTE_ b_LatchReg    : Selected latch register          |
++|                     unsigned char_ b_LatchReg    : Selected latch register          |
+ |                               0 : for the first latch register             |
+ |                               1 : for the second latch register            |
+ +----------------------------------------------------------------------------+
+-| Output Parameters : PBYTE_ pb_LatchStatus :   Latch register status.       |
++| Output Parameters : unsigned char *_ pb_LatchStatus :   Latch register status.       |
+ |                                               0 : No latch occur           |
+ |                                               1 : A software latch occur   |
+ |                                               2 : A hardware latch occur   |
+@@ -4194,7 +4194,7 @@ INT i_APCI1710_InsnReadINCCPT(struct comedi_device * dev, struct comedi_subdevic
+ */
+ 
+ INT i_APCI1710_ReadLatchRegisterStatus(struct comedi_device * dev,
+-	BYTE b_ModulNbr, BYTE b_LatchReg, PBYTE pb_LatchStatus)
++	unsigned char b_ModulNbr, unsigned char b_LatchReg, unsigned char * pb_LatchStatus)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_LatchReg;
+@@ -4220,7 +4220,7 @@ INT i_APCI1710_ReadLatchRegisterStatus(struct comedi_device * dev,
+ 					ui_Address + (64 * b_ModulNbr));
+ 
+ 				*pb_LatchStatus =
+-					(BYTE) ((dw_LatchReg >> (b_LatchReg *
++					(unsigned char) ((dw_LatchReg >> (b_LatchReg *
+ 							4)) & 0x3);
+ 			} else {
+ 		 /**************************************************/
+@@ -4254,18 +4254,18 @@ INT i_APCI1710_ReadLatchRegisterStatus(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_ReadLatchRegisterValue                |
+-|                                                   (BYTE_     b_BoardHandle,|
+-|                                                    BYTE_     b_ModulNbr,   |
+-|                                                    BYTE_     b_LatchReg,   |
++|                                                   (unsigned char_     b_BoardHandle,|
++|                                                    unsigned char_     b_ModulNbr,   |
++|                                                    unsigned char_     b_LatchReg,   |
+ |                                                    PULONG_ pul_LatchValue) |
+ +----------------------------------------------------------------------------+
+ | Task              : Read the latch register value from selected module     |
+ |                     (b_ModulNbr) and selected latch register (b_LatchReg). |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle : Handle of board APCI-1710        |
+-|                     BYTE_ b_ModulNbr    : Module number to configure       |
++| Input Parameters  : unsigned char_ b_BoardHandle : Handle of board APCI-1710        |
++|                     unsigned char_ b_ModulNbr    : Module number to configure       |
+ |                                           (0 to 3)                         |
+-|                     BYTE_ b_LatchReg    : Selected latch register          |
++|                     unsigned char_ b_LatchReg    : Selected latch register          |
+ |                               0 : for the first latch register             |
+ |                               1 : for the second latch register            |
+ +----------------------------------------------------------------------------+
+@@ -4281,7 +4281,7 @@ INT i_APCI1710_ReadLatchRegisterStatus(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_ReadLatchRegisterValue(struct comedi_device * dev,
+-	BYTE b_ModulNbr, BYTE b_LatchReg, PULONG pul_LatchValue)
++	unsigned char b_ModulNbr, unsigned char b_LatchReg, PULONG pul_LatchValue)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -4338,19 +4338,19 @@ INT i_APCI1710_ReadLatchRegisterValue(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_Read16BitCounterValue                 |
+-|                                       (BYTE_     b_BoardHandle,            |
+-|                                        BYTE_     b_ModulNbr,               |
+-|                                        BYTE_     b_SelectedCounter,        |
++|                                       (unsigned char_     b_BoardHandle,            |
++|                                        unsigned char_     b_ModulNbr,               |
++|                                        unsigned char_     b_SelectedCounter,        |
+ |                                        PUINT_   pui_CounterValue)          |
+ +----------------------------------------------------------------------------+
+ | Task              : Latch the selected 16-Bit counter (b_SelectedCounter)  |
+ |                     from selected module (b_ModulNbr) in to the first      |
+ |                     latch register and return the latched value.           |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+-|                     BYTE_ b_ModulNbr        : Module number to configure   |
++| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
++|                     unsigned char_ b_ModulNbr        : Module number to configure   |
+ |                                              (0 to 3)                      |
+-|                     BYTE_ b_SelectedCounter : Selected 16-Bit counter      |
++|                     unsigned char_ b_SelectedCounter : Selected 16-Bit counter      |
+ |                                               (0 or 1)                     |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : PUINT_ pui_CounterValue : 16-Bit counter value         |
+@@ -4365,7 +4365,7 @@ INT i_APCI1710_ReadLatchRegisterValue(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_Read16BitCounterValue(struct comedi_device * dev,
+-	BYTE b_ModulNbr, BYTE b_SelectedCounter, PUINT pui_CounterValue)
++	unsigned char b_ModulNbr, unsigned char b_SelectedCounter, PUINT pui_CounterValue)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_LathchValue = 0;
+@@ -4437,16 +4437,16 @@ INT i_APCI1710_Read16BitCounterValue(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_Read32BitCounterValue                 |
+-|                                       (BYTE_     b_BoardHandle,            |
+-|                                        BYTE_     b_ModulNbr,               |
++|                                       (unsigned char_     b_BoardHandle,            |
++|                                        unsigned char_     b_ModulNbr,               |
+ |                                        PULONG_ pul_CounterValue)           |
+ +----------------------------------------------------------------------------+
+ | Task              : Latch the 32-Bit counter from selected module          |
+ |                     (b_ModulNbr) in to the first latch register and return |
+ |                     the latched value.                                     |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+-|                     BYTE_ b_ModulNbr        : Module number to configure   |
++| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
++|                     unsigned char_ b_ModulNbr        : Module number to configure   |
+ |                                              (0 to 3)                      |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : PULONG_  pul_CounterValue : 32-Bit counter value       |
+@@ -4460,7 +4460,7 @@ INT i_APCI1710_Read16BitCounterValue(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_Read32BitCounterValue(struct comedi_device * dev,
+-	BYTE b_ModulNbr, PULONG pul_CounterValue)
++	unsigned char b_ModulNbr, PULONG pul_CounterValue)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -4512,17 +4512,17 @@ INT i_APCI1710_Read32BitCounterValue(struct comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     : _INT_ i_APCI1710_GetIndexStatus (BYTE_   b_BoardHandle,|
+-|                                                      BYTE_   b_ModulNbr,   |
+-|                                                      PBYTE_ pb_IndexStatus)|
++| Function Name     : _INT_ i_APCI1710_GetIndexStatus (unsigned char_   b_BoardHandle,|
++|                                                      unsigned char_   b_ModulNbr,   |
++|                                                      unsigned char *_ pb_IndexStatus)|
+ +----------------------------------------------------------------------------+
+ | Task              : Return the index status                                |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+-|                     BYTE_ b_ModulNbr        : Module number to configure   |
++| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
++|                     unsigned char_ b_ModulNbr        : Module number to configure   |
+ |                                               (0 to 3)                     |
+ +----------------------------------------------------------------------------+
+-| Output Parameters : PBYTE_ pb_IndexStatus   : 0 : No INDEX occur           |
++| Output Parameters : unsigned char *_ pb_IndexStatus   : 0 : No INDEX occur           |
+ |                                               1 : A INDEX occur            |
+ +----------------------------------------------------------------------------+
+ | Return Value      :  0: No error                                           |
+@@ -4536,7 +4536,7 @@ INT i_APCI1710_Read32BitCounterValue(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_GetIndexStatus(struct comedi_device * dev,
+-	BYTE b_ModulNbr, PBYTE pb_IndexStatus)
++	unsigned char b_ModulNbr, unsigned char * pb_IndexStatus)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusReg = 0;
+@@ -4563,7 +4563,7 @@ INT i_APCI1710_GetIndexStatus(struct comedi_device * dev,
+ 				dw_StatusReg = inl(devpriv->s_BoardInfos.
+ 					ui_Address + 12 + (64 * b_ModulNbr));
+ 
+-				*pb_IndexStatus = (BYTE) (dw_StatusReg & 1);
++				*pb_IndexStatus = (unsigned char) (dw_StatusReg & 1);
+ 			} else {
+ 		 /*************************************************************/
+ 				/* Index not initialised see function "i_APCI1710_InitIndex" */
+@@ -4596,17 +4596,17 @@ INT i_APCI1710_GetIndexStatus(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_GetReferenceStatus                    |
+-|                                                (BYTE_   b_BoardHandle,     |
+-|                                                 BYTE_   b_ModulNbr,        |
+-|                                                 PBYTE_ pb_ReferenceStatus) |
++|                                                (unsigned char_   b_BoardHandle,     |
++|                                                 unsigned char_   b_ModulNbr,        |
++|                                                 unsigned char *_ pb_ReferenceStatus) |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the reference status                            |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+-|                     BYTE_ b_ModulNbr        : Module number to configure   |
++| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
++|                     unsigned char_ b_ModulNbr        : Module number to configure   |
+ |                                               (0 to 3)                     |
+ +----------------------------------------------------------------------------+
+-| Output Parameters : PBYTE_ pb_ReferenceStatus   : 0 : No REFERENCE occur   |
++| Output Parameters : unsigned char *_ pb_ReferenceStatus   : 0 : No REFERENCE occur   |
+ |                                                   1 : A REFERENCE occur    |
+ +----------------------------------------------------------------------------+
+ | Return Value      :  0: No error                                           |
+@@ -4620,7 +4620,7 @@ INT i_APCI1710_GetIndexStatus(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_GetReferenceStatus(struct comedi_device * dev,
+-	BYTE b_ModulNbr, PBYTE pb_ReferenceStatus)
++	unsigned char b_ModulNbr, unsigned char * pb_ReferenceStatus)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusReg = 0;
+@@ -4649,7 +4649,7 @@ INT i_APCI1710_GetReferenceStatus(struct comedi_device * dev,
+ 					ui_Address + 24 + (64 * b_ModulNbr));
+ 
+ 				*pb_ReferenceStatus =
+-					(BYTE) (~dw_StatusReg & 1);
++					(unsigned char) (~dw_StatusReg & 1);
+ 			} else {
+ 		 /*********************************************************************/
+ 				/* Reference not initialised see function "i_APCI1710_InitReference" */
+@@ -4682,17 +4682,17 @@ INT i_APCI1710_GetReferenceStatus(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_GetUASStatus                          |
+-|                               (BYTE_   b_BoardHandle,                      |
+-|                                BYTE_   b_ModulNbr,                         |
+-|                                PBYTE_ pb_UASStatus)                        |
++|                               (unsigned char_   b_BoardHandle,                      |
++|                                unsigned char_   b_ModulNbr,                         |
++|                                unsigned char *_ pb_UASStatus)                        |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the error signal (UAS) status                   |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+-|                     BYTE_ b_ModulNbr        : Module number to configure   |
++| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
++|                     unsigned char_ b_ModulNbr        : Module number to configure   |
+ |                                               (0 to 3)                     |
+ +----------------------------------------------------------------------------+
+-| Output Parameters : PBYTE_ pb_UASStatus      : 0 : UAS is low "0"          |
++| Output Parameters : unsigned char *_ pb_UASStatus      : 0 : UAS is low "0"          |
+ |                                                1 : UAS is high "1"         |
+ +----------------------------------------------------------------------------+
+ | Return Value      :  0: No error                                           |
+@@ -4704,7 +4704,7 @@ INT i_APCI1710_GetReferenceStatus(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_GetUASStatus(struct comedi_device * dev,
+-	BYTE b_ModulNbr, PBYTE pb_UASStatus)
++	unsigned char b_ModulNbr, unsigned char * pb_UASStatus)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusReg = 0;
+@@ -4724,7 +4724,7 @@ INT i_APCI1710_GetUASStatus(struct comedi_device * dev,
+ 			dw_StatusReg = inl(devpriv->s_BoardInfos.
+ 				ui_Address + 24 + (64 * b_ModulNbr));
+ 
+-			*pb_UASStatus = (BYTE) ((dw_StatusReg >> 1) & 1);
++			*pb_UASStatus = (unsigned char) ((dw_StatusReg >> 1) & 1);
+ 		} else {
+ 	      /****************************************/
+ 			/* Counter not initialised see function */
+@@ -4750,17 +4750,17 @@ INT i_APCI1710_GetUASStatus(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_GetCBStatus                           |
+-|                               (BYTE_   b_BoardHandle,                      |
+-|                                BYTE_   b_ModulNbr,                         |
+-|                                PBYTE_ pb_CBStatus)                         |
++|                               (unsigned char_   b_BoardHandle,                      |
++|                                unsigned char_   b_ModulNbr,                         |
++|                                unsigned char *_ pb_CBStatus)                         |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the counter overflow status                     |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+-|                     BYTE_ b_ModulNbr        : Module number to configure   |
++| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
++|                     unsigned char_ b_ModulNbr        : Module number to configure   |
+ |                                               (0 to 3)                     |
+ +----------------------------------------------------------------------------+
+-| Output Parameters : PBYTE_ pb_CBStatus      : 0 : Counter no overflow      |
++| Output Parameters : unsigned char *_ pb_CBStatus      : 0 : Counter no overflow      |
+ |                                               1 : Counter overflow         |
+ +----------------------------------------------------------------------------+
+ | Return Value      :  0: No error                                           |
+@@ -4772,7 +4772,7 @@ INT i_APCI1710_GetUASStatus(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_GetCBStatus(struct comedi_device * dev,
+-	BYTE b_ModulNbr, PBYTE pb_CBStatus)
++	unsigned char b_ModulNbr, unsigned char * pb_CBStatus)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusReg = 0;
+@@ -4792,7 +4792,7 @@ INT i_APCI1710_GetCBStatus(struct comedi_device * dev,
+ 			dw_StatusReg = inl(devpriv->s_BoardInfos.
+ 				ui_Address + 16 + (64 * b_ModulNbr));
+ 
+-			*pb_CBStatus = (BYTE) (dw_StatusReg & 1);
++			*pb_CBStatus = (unsigned char) (dw_StatusReg & 1);
+ 
+ 		} else {
+ 	      /****************************************/
+@@ -4818,25 +4818,25 @@ INT i_APCI1710_GetCBStatus(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_Get16BitCBStatus                      |
+-|					(BYTE_     b_BoardHandle,            |
+-|					 BYTE_     b_ModulNbr,               |
+-|					 PBYTE_ pb_CBStatusCounter0,         |
+-|					 PBYTE_ pb_CBStatusCounter1)         |
++|					(unsigned char_     b_BoardHandle,            |
++|					 unsigned char_     b_ModulNbr,               |
++|					 unsigned char *_ pb_CBStatusCounter0,         |
++|					 unsigned char *_ pb_CBStatusCounter1)         |
+ +----------------------------------------------------------------------------+
+ | Task              : Returns the counter overflow (counter initialised to   |
+ |		      2*16-bit) status from selected incremental counter     |
+ |		      module                                                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+-|                     BYTE_ b_ModulNbr        : Module number to configure   |
++| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
++|                     unsigned char_ b_ModulNbr        : Module number to configure   |
+ |                                               (0 to 3)                     |
+ +----------------------------------------------------------------------------+
+-| Output Parameters : PBYTE_ pb_CBStatusCounter0 : 0 : No overflow occur for |
++| Output Parameters : unsigned char *_ pb_CBStatusCounter0 : 0 : No overflow occur for |
+ |						       the first 16-bit      |
+ |						       counter               |
+ |						   1 : Overflow occur for the|
+ |						       first 16-bit counter  |
+-|		      PBYTE_ pb_CBStatusCounter1 : 0 : No overflow occur for |
++|		      unsigned char *_ pb_CBStatusCounter1 : 0 : No overflow occur for |
+ |						       the second 16-bit     |
+ |						       counter               |
+ |						   1 : Overflow occur for the|
+@@ -4854,7 +4854,7 @@ INT i_APCI1710_GetCBStatus(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_Get16BitCBStatus(struct comedi_device * dev,
+-	BYTE b_ModulNbr, PBYTE pb_CBStatusCounter0, PBYTE pb_CBStatusCounter1)
++	unsigned char b_ModulNbr, unsigned char * pb_CBStatusCounter0, unsigned char * pb_CBStatusCounter1)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusReg = 0;
+@@ -4894,10 +4894,10 @@ INT i_APCI1710_Get16BitCBStatus(struct comedi_device * dev,
+ 						(64 * b_ModulNbr));
+ 
+ 					*pb_CBStatusCounter1 =
+-						(BYTE) ((dw_StatusReg >> 0) &
++						(unsigned char) ((dw_StatusReg >> 0) &
+ 						1);
+ 					*pb_CBStatusCounter0 =
+-						(BYTE) ((dw_StatusReg >> 1) &
++						(unsigned char) ((dw_StatusReg >> 1) &
+ 						1);
+ 				}	// if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_BoardInfos.dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3136)
+ 				else {
+@@ -4943,17 +4943,17 @@ INT i_APCI1710_Get16BitCBStatus(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_GetUDStatus                           |
+-|                               (BYTE_   b_BoardHandle,                      |
+-|                                BYTE_   b_ModulNbr,                         |
+-|                                PBYTE_ pb_UDStatus)                         |
++|                               (unsigned char_   b_BoardHandle,                      |
++|                                unsigned char_   b_ModulNbr,                         |
++|                                unsigned char *_ pb_UDStatus)                         |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the counter progress status                     |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+-|                     BYTE_ b_ModulNbr        : Module number to configure   |
++| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
++|                     unsigned char_ b_ModulNbr        : Module number to configure   |
+ |                                               (0 to 3)                     |
+ +----------------------------------------------------------------------------+
+-| Output Parameters : PBYTE_ pb_UDStatus      : 0 : Counter progress in the  |
++| Output Parameters : unsigned char *_ pb_UDStatus      : 0 : Counter progress in the  |
+ |                                                   selected mode down       |
+ |                                               1 : Counter progress in the  |
+ |                                                   selected mode up         |
+@@ -4967,7 +4967,7 @@ INT i_APCI1710_Get16BitCBStatus(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_GetUDStatus(struct comedi_device * dev,
+-	BYTE b_ModulNbr, PBYTE pb_UDStatus)
++	unsigned char b_ModulNbr, unsigned char * pb_UDStatus)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusReg = 0;
+@@ -4987,7 +4987,7 @@ INT i_APCI1710_GetUDStatus(struct comedi_device * dev,
+ 			dw_StatusReg = inl(devpriv->s_BoardInfos.
+ 				ui_Address + 24 + (64 * b_ModulNbr));
+ 
+-			*pb_UDStatus = (BYTE) ((dw_StatusReg >> 2) & 1);
++			*pb_UDStatus = (unsigned char) ((dw_StatusReg >> 2) & 1);
+ 
+ 		} else {
+ 	      /****************************************/
+@@ -5013,18 +5013,18 @@ INT i_APCI1710_GetUDStatus(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_GetInterruptUDLatchedStatus           |
+-|                               (BYTE_   b_BoardHandle,                      |
+-|                                BYTE_   b_ModulNbr,                         |
+-|                                PBYTE_ pb_UDStatus)                         |
++|                               (unsigned char_   b_BoardHandle,                      |
++|                                unsigned char_   b_ModulNbr,                         |
++|                                unsigned char *_ pb_UDStatus)                         |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the counter progress latched status after a     |
+ |                     index interrupt occur.                                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+-|                     BYTE_ b_ModulNbr        : Module number to configure   |
++| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
++|                     unsigned char_ b_ModulNbr        : Module number to configure   |
+ |                                               (0 to 3)                     |
+ +----------------------------------------------------------------------------+
+-| Output Parameters : PBYTE_ pb_UDStatus      : 0 : Counter progress in the  |
++| Output Parameters : unsigned char *_ pb_UDStatus      : 0 : Counter progress in the  |
+ |                                                   selected mode down       |
+ |                                               1 : Counter progress in the  |
+ |                                                   selected mode up         |
+@@ -5041,7 +5041,7 @@ INT i_APCI1710_GetUDStatus(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device * dev,
+-	BYTE b_ModulNbr, PBYTE pb_UDStatus)
++	unsigned char b_ModulNbr, unsigned char * pb_UDStatus)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusReg = 0;
+@@ -5074,7 +5074,7 @@ INT i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device * dev,
+ 				dw_StatusReg = inl(devpriv->s_BoardInfos.
+ 					ui_Address + 12 + (64 * b_ModulNbr));
+ 
+-				*pb_UDStatus = (BYTE) ((dw_StatusReg >> 1) & 1);
++				*pb_UDStatus = (unsigned char) ((dw_StatusReg >> 1) & 1);
+ 			} else {
+ 		    /****************************/
+ 				/* No index interrupt occur */
+@@ -5106,20 +5106,20 @@ INT i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device * dev,
+ 	/*
+ 	   +----------------------------------------------------------------------------+
+ 	   | Function Name     : _INT_ i_APCI1710_ReadFrequencyMeasurement              |
+-	   |                            (BYTE_            b_BoardHandle,             |
+-	   |                             BYTE_            b_ModulNbr,                |
+-	   |                             PBYTE_          pb_Status,                  |
++	   |                            (unsigned char_            b_BoardHandle,             |
++	   |                             unsigned char_            b_ModulNbr,                |
++	   |                             unsigned char *_          pb_Status,                  |
+ 	   |                             PULONG_        pul_ReadValue)               |
+ 	   +----------------------------------------------------------------------------+
+ 	   | Task              : Returns the status (pb_Status) and the number of       |
+ 	   |                  increments in the set time.                            |
+ 	   |                  See function " i_APCI1710_InitFrequencyMeasurement "   |
+ 	   +----------------------------------------------------------------------------+
+-	   | Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |
+-	   |                  BYTE_  b_ModulNbr       : Number of the module to be   |
++	   | Input Parameters  : unsigned char_  b_BoardHandle    : Handle of board APCI-1710    |
++	   |                  unsigned char_  b_ModulNbr       : Number of the module to be   |
+ 	   |                                            configured (0 to 3)          |
+ 	   +----------------------------------------------------------------------------+
+-	   | Output Parameters : PBYTE_ pb_Status     : Returns the frequency        |
++	   | Output Parameters : unsigned char *_ pb_Status     : Returns the frequency        |
+ 	   |                                            measurement status           |
+ 	   |                                            0 : Counting cycle not       |
+ 	   |                                                started.                 |
+@@ -5127,7 +5127,7 @@ INT i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device * dev,
+ 	   |                                            2 : Counting cycle stopped.  |
+ 	   |                                                The measurement cycle is |
+ 	   |                                                completed.               |
+-	   |                  PBYTE_ pb_UDStatus      : 0 : Counter progress in the  |
++	   |                  unsigned char *_ pb_UDStatus      : 0 : Counter progress in the  |
+ 	   |                                                   selected mode down       |
+ 	   |                                               1 : Counter progress in the  |
+ 	   |                                                   selected mode up         |
+@@ -5146,8 +5146,8 @@ INT i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device * dev,
+ 	 */
+ 
+ INT i_APCI1710_ReadFrequencyMeasurement(struct comedi_device * dev,
+-	BYTE b_ModulNbr,
+-	PBYTE pb_Status, PBYTE pb_UDStatus, PULONG pul_ReadValue)
++	unsigned char b_ModulNbr,
++	unsigned char * pb_Status, unsigned char * pb_UDStatus, PULONG pul_ReadValue)
+ {
+ 	INT i_ReturnValue = 0;
+ 	UINT ui_16BitValue;
+@@ -5198,7 +5198,7 @@ INT i_APCI1710_ReadFrequencyMeasurement(struct comedi_device * dev,
+ 					if (dw_StatusReg & 1) {
+ 						*pb_Status = 2;
+ 						*pb_UDStatus =
+-							(BYTE) ((dw_StatusReg >>
++							(unsigned char) ((dw_StatusReg >>
+ 								1) & 3);
+ 
+ 		       /******************/
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
+index 5153cf686658..62719b240b3c 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
+@@ -148,124 +148,124 @@ INT i_APCI1710_InsnReadINCCPT(struct comedi_device *dev, struct comedi_subdevice
+ 
+ /* INSN CONFIG */
+ INT i_APCI1710_InitCounter(struct comedi_device *dev,
+-			   BYTE b_ModulNbr,
+-			   BYTE b_CounterRange,
+-			   BYTE b_FirstCounterModus,
+-			   BYTE b_FirstCounterOption,
+-			   BYTE b_SecondCounterModus,
+-			   BYTE b_SecondCounterOption);
++			   unsigned char b_ModulNbr,
++			   unsigned char b_CounterRange,
++			   unsigned char b_FirstCounterModus,
++			   unsigned char b_FirstCounterOption,
++			   unsigned char b_SecondCounterModus,
++			   unsigned char b_SecondCounterOption);
+ 
+-INT i_APCI1710_CounterAutoTest(struct comedi_device *dev, PBYTE pb_TestStatus);
++INT i_APCI1710_CounterAutoTest(struct comedi_device *dev, unsigned char * pb_TestStatus);
+ 
+ INT i_APCI1710_InitIndex(struct comedi_device *dev,
+-			 BYTE b_ModulNbr,
+-			 BYTE b_ReferenceAction,
+-			 BYTE b_IndexOperation, BYTE b_AutoMode,
+-			 BYTE b_InterruptEnable);
++			 unsigned char b_ModulNbr,
++			 unsigned char b_ReferenceAction,
++			 unsigned char b_IndexOperation, unsigned char b_AutoMode,
++			 unsigned char b_InterruptEnable);
+ 
+ INT i_APCI1710_InitReference(struct comedi_device *dev,
+-			     BYTE b_ModulNbr, BYTE b_ReferenceLevel);
++			     unsigned char b_ModulNbr, unsigned char b_ReferenceLevel);
+ 
+ INT i_APCI1710_InitExternalStrobe(struct comedi_device *dev,
+-				  BYTE b_ModulNbr, BYTE b_ExternalStrobe,
+-				  BYTE b_ExternalStrobeLevel);
++				  unsigned char b_ModulNbr, unsigned char b_ExternalStrobe,
++				  unsigned char b_ExternalStrobeLevel);
+ 
+ INT i_APCI1710_InitCompareLogic(struct comedi_device *dev,
+-				BYTE b_ModulNbr, UINT ui_CompareValue);
++				unsigned char b_ModulNbr, UINT ui_CompareValue);
+ 
+ INT i_APCI1710_InitFrequencyMeasurement(struct comedi_device *dev,
+-					BYTE b_ModulNbr,
+-					BYTE b_PCIInputClock,
+-					BYTE b_TimingUnity,
++					unsigned char b_ModulNbr,
++					unsigned char b_PCIInputClock,
++					unsigned char b_TimingUnity,
+ 					ULONG ul_TimingInterval,
+ 					PULONG pul_RealTimingInterval);
+ 
+ /* INSN BITS */
+-INT i_APCI1710_ClearCounterValue(struct comedi_device *dev, BYTE b_ModulNbr);
++INT i_APCI1710_ClearCounterValue(struct comedi_device *dev, unsigned char b_ModulNbr);
+ 
+ INT i_APCI1710_ClearAllCounterValue(struct comedi_device *dev);
+ 
+ INT i_APCI1710_SetInputFilter(struct comedi_device *dev,
+-			      BYTE b_ModulNbr, BYTE b_PCIInputClock,
+-			      BYTE b_Filter);
++			      unsigned char b_ModulNbr, unsigned char b_PCIInputClock,
++			      unsigned char b_Filter);
+ 
+ INT i_APCI1710_LatchCounter(struct comedi_device *dev,
+-			    BYTE b_ModulNbr, BYTE b_LatchReg);
++			    unsigned char b_ModulNbr, unsigned char b_LatchReg);
+ 
+ INT i_APCI1710_SetIndexAndReferenceSource(struct comedi_device *dev,
+-					  BYTE b_ModulNbr,
+-					  BYTE b_SourceSelection);
++					  unsigned char b_ModulNbr,
++					  unsigned char b_SourceSelection);
+ 
+-INT i_APCI1710_SetDigitalChlOn(struct comedi_device *dev, BYTE b_ModulNbr);
++INT i_APCI1710_SetDigitalChlOn(struct comedi_device *dev, unsigned char b_ModulNbr);
+ 
+-INT i_APCI1710_SetDigitalChlOff(struct comedi_device *dev, BYTE b_ModulNbr);
++INT i_APCI1710_SetDigitalChlOff(struct comedi_device *dev, unsigned char b_ModulNbr);
+ 
+ /* INSN WRITE */
+-INT i_APCI1710_EnableLatchInterrupt(struct comedi_device *dev, BYTE b_ModulNbr);
++INT i_APCI1710_EnableLatchInterrupt(struct comedi_device *dev, unsigned char b_ModulNbr);
+ 
+-INT i_APCI1710_DisableLatchInterrupt(struct comedi_device *dev, BYTE b_ModulNbr);
++INT i_APCI1710_DisableLatchInterrupt(struct comedi_device *dev, unsigned char b_ModulNbr);
+ 
+ INT i_APCI1710_Write16BitCounterValue(struct comedi_device *dev,
+-				      BYTE b_ModulNbr, BYTE b_SelectedCounter,
++				      unsigned char b_ModulNbr, unsigned char b_SelectedCounter,
+ 				      UINT ui_WriteValue);
+ 
+ INT i_APCI1710_Write32BitCounterValue(struct comedi_device *dev,
+-				      BYTE b_ModulNbr, ULONG ul_WriteValue);
++				      unsigned char b_ModulNbr, ULONG ul_WriteValue);
+ 
+-INT i_APCI1710_EnableIndex(struct comedi_device *dev, BYTE b_ModulNbr);
++INT i_APCI1710_EnableIndex(struct comedi_device *dev, unsigned char b_ModulNbr);
+ 
+-INT i_APCI1710_DisableIndex(struct comedi_device *dev, BYTE b_ModulNbr);
++INT i_APCI1710_DisableIndex(struct comedi_device *dev, unsigned char b_ModulNbr);
+ 
+-INT i_APCI1710_EnableCompareLogic(struct comedi_device *dev, BYTE b_ModulNbr);
++INT i_APCI1710_EnableCompareLogic(struct comedi_device *dev, unsigned char b_ModulNbr);
+ 
+-INT i_APCI1710_DisableCompareLogic(struct comedi_device *dev, BYTE b_ModulNbr);
++INT i_APCI1710_DisableCompareLogic(struct comedi_device *dev, unsigned char b_ModulNbr);
+ 
+ INT i_APCI1710_EnableFrequencyMeasurement(struct comedi_device *dev,
+-					  BYTE b_ModulNbr,
+-					  BYTE b_InterruptEnable);
++					  unsigned char b_ModulNbr,
++					  unsigned char b_InterruptEnable);
+ 
+ INT i_APCI1710_DisableFrequencyMeasurement(struct comedi_device *dev,
+-					   BYTE b_ModulNbr);
++					   unsigned char b_ModulNbr);
+ 
+ /* INSN READ */
+ INT i_APCI1710_ReadLatchRegisterStatus(struct comedi_device *dev,
+-				       BYTE b_ModulNbr, BYTE b_LatchReg,
+-				       PBYTE pb_LatchStatus);
++				       unsigned char b_ModulNbr, unsigned char b_LatchReg,
++				       unsigned char * pb_LatchStatus);
+ 
+ INT i_APCI1710_ReadLatchRegisterValue(struct comedi_device *dev,
+-				      BYTE b_ModulNbr, BYTE b_LatchReg,
++				      unsigned char b_ModulNbr, unsigned char b_LatchReg,
+ 				      PULONG pul_LatchValue);
+ 
+ INT i_APCI1710_Read16BitCounterValue(struct comedi_device *dev,
+-				     BYTE b_ModulNbr, BYTE b_SelectedCounter,
++				     unsigned char b_ModulNbr, unsigned char b_SelectedCounter,
+ 				     PUINT pui_CounterValue);
+ 
+ INT i_APCI1710_Read32BitCounterValue(struct comedi_device *dev,
+-				     BYTE b_ModulNbr, PULONG pul_CounterValue);
++				     unsigned char b_ModulNbr, PULONG pul_CounterValue);
+ 
+ INT i_APCI1710_GetIndexStatus(struct comedi_device *dev,
+-			      BYTE b_ModulNbr, PBYTE pb_IndexStatus);
++			      unsigned char b_ModulNbr, unsigned char * pb_IndexStatus);
+ 
+ INT i_APCI1710_GetReferenceStatus(struct comedi_device *dev,
+-				  BYTE b_ModulNbr, PBYTE pb_ReferenceStatus);
++				  unsigned char b_ModulNbr, unsigned char * pb_ReferenceStatus);
+ 
+ INT i_APCI1710_GetUASStatus(struct comedi_device *dev,
+-			    BYTE b_ModulNbr, PBYTE pb_UASStatus);
++			    unsigned char b_ModulNbr, unsigned char * pb_UASStatus);
+ 
+ INT i_APCI1710_GetCBStatus(struct comedi_device *dev,
+-			   BYTE b_ModulNbr, PBYTE pb_CBStatus);
++			   unsigned char b_ModulNbr, unsigned char * pb_CBStatus);
+ 
+ INT i_APCI1710_Get16BitCBStatus(struct comedi_device *dev,
+-				BYTE b_ModulNbr, PBYTE pb_CBStatusCounter0,
+-				PBYTE pb_CBStatusCounter1);
++				unsigned char b_ModulNbr, unsigned char * pb_CBStatusCounter0,
++				unsigned char * pb_CBStatusCounter1);
+ 
+ INT i_APCI1710_GetUDStatus(struct comedi_device *dev,
+-			   BYTE b_ModulNbr, PBYTE pb_UDStatus);
++			   unsigned char b_ModulNbr, unsigned char * pb_UDStatus);
+ 
+ INT i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device *dev,
+-					   BYTE b_ModulNbr, PBYTE pb_UDStatus);
++					   unsigned char b_ModulNbr, unsigned char * pb_UDStatus);
+ 
+ INT i_APCI1710_ReadFrequencyMeasurement(struct comedi_device *dev,
+-					BYTE b_ModulNbr,
+-					PBYTE pb_Status, PBYTE pb_UDStatus,
++					unsigned char b_ModulNbr,
++					unsigned char * pb_Status, unsigned char * pb_UDStatus,
+ 					PULONG pul_ReadValue);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+index 3ac6a264ef54..7364cf075917 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+@@ -60,11 +60,11 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_InitPulseEncoder                      |
+-|                               (BYTE_          b_BoardHandle,               |
+-|                                BYTE_          b_ModulNbr,                  |
+-|                                BYTE_          b_PulseEncoderNbr,           |
+-|                                BYTE_          b_InputLevelSelection,       |
+-|                                BYTE_          b_TriggerOutputAction,       |
++|                               (unsigned char_          b_BoardHandle,               |
++|                                unsigned char_          b_ModulNbr,                  |
++|                                unsigned char_          b_PulseEncoderNbr,           |
++|                                unsigned char_          b_InputLevelSelection,       |
++|                                unsigned char_          b_TriggerOutputAction,       |
+ |                                ULONG_        ul_StartValue)                |
+ +----------------------------------------------------------------------------+
+ | Task              : Configure the pulse encoder operating mode selected via|
+@@ -74,12 +74,12 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ |                     You must calling this function be for you call any     |
+ |                     other function witch access of pulse encoders.         |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle         : Handle of board APCI-1710|
+-|                     BYTE_ b_ModulNbr            : Module number to         |
++| Input Parameters  : unsigned char_ b_BoardHandle         : Handle of board APCI-1710|
++|                     unsigned char_ b_ModulNbr            : Module number to         |
+ |                                                   configure (0 to 3)       |
+-|                     BYTE_ b_PulseEncoderNbr     : Pulse encoder selection  |
++|                     unsigned char_ b_PulseEncoderNbr     : Pulse encoder selection  |
+ |                                                   (0 to 3)                 |
+-|                     BYTE_ b_InputLevelSelection : Input level selection    |
++|                     unsigned char_ b_InputLevelSelection : Input level selection    |
+ |                                                   (0 or 1)                 |
+ |                                                       0 : Set pulse encoder|
+ |                                                           count the the low|
+@@ -87,7 +87,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ |                                                       1 : Set pulse encoder|
+ |                                                           count the the    |
+ |                                                           high level pulse.|
+-|                     BYTE_ b_TriggerOutputAction : Digital TRIGGER output   |
++|                     unsigned char_ b_TriggerOutputAction : Digital TRIGGER output   |
+ |                                                   action                   |
+ |                                                       0 : No action        |
+ |                                                       1 : Set the trigger  |
+@@ -104,10 +104,10 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ |                                                           encoder          |
+ |                     ULONG_ ul_StartValue        : Pulse encoder start value|
+ |                                                   (1 to 4294967295)
+-	b_ModulNbr				=(BYTE) CR_AREF(insn->chanspec);
+-	b_PulseEncoderNbr		=(BYTE) data[0];
+-	b_InputLevelSelection	=(BYTE) data[1];
+-	b_TriggerOutputAction	=(BYTE) data[2];
++	b_ModulNbr				=(unsigned char) CR_AREF(insn->chanspec);
++	b_PulseEncoderNbr		=(unsigned char) data[0];
++	b_InputLevelSelection	=(unsigned char) data[1];
++	b_TriggerOutputAction	=(unsigned char) data[2];
+ 	ul_StartValue			=(ULONG) data[3];
+        |
+ +----------------------------------------------------------------------------+
+@@ -129,16 +129,16 @@ INT i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device * dev,
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_IntRegister;
+ 
+-	BYTE b_ModulNbr;
+-	BYTE b_PulseEncoderNbr;
+-	BYTE b_InputLevelSelection;
+-	BYTE b_TriggerOutputAction;
++	unsigned char b_ModulNbr;
++	unsigned char b_PulseEncoderNbr;
++	unsigned char b_InputLevelSelection;
++	unsigned char b_TriggerOutputAction;
+ 	ULONG ul_StartValue;
+ 
+-	b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+-	b_PulseEncoderNbr = (BYTE) data[0];
+-	b_InputLevelSelection = (BYTE) data[1];
+-	b_TriggerOutputAction = (BYTE) data[2];
++	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
++	b_PulseEncoderNbr = (unsigned char) data[0];
++	b_InputLevelSelection = (unsigned char) data[1];
++	b_TriggerOutputAction = (unsigned char) data[2];
+ 	ul_StartValue = (ULONG) data[3];
+ 
+ 	i_ReturnValue = insn->n;
+@@ -352,11 +352,11 @@ INT i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_EnablePulseEncoder                    |
+-|                                       (BYTE_  b_BoardHandle,               |
+-|                                        BYTE_  b_ModulNbr,                  |
+-|                                        BYTE_  b_PulseEncoderNbr,           |
+-|                                        BYTE_  b_CycleSelection,            |
+-|                                        BYTE_  b_InterruptHandling)         |
++|                                       (unsigned char_  b_BoardHandle,               |
++|                                        unsigned char_  b_ModulNbr,                  |
++|                                        unsigned char_  b_PulseEncoderNbr,           |
++|                                        unsigned char_  b_CycleSelection,            |
++|                                        unsigned char_  b_InterruptHandling)         |
+ +----------------------------------------------------------------------------+
+ | Task              : Enableor disable  the selected pulse encoder (b_PulseEncoderNbr)  |
+ |                     from selected module (b_ModulNbr). Each input pulse    |
+@@ -365,12 +365,12 @@ INT i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device * dev,
+ |                     interrupt is generated when the pulse encoder has run  |
+ |                     down.                                                  |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_   b_BoardHandle       : Handle of board APCI-1710|
+-|                     BYTE_   b_ModulNbr          : Module number to         |
++| Input Parameters  : unsigned char_   b_BoardHandle       : Handle of board APCI-1710|
++|                     unsigned char_   b_ModulNbr          : Module number to         |
+ |                                                   configure (0 to 3)       |
+-|                     BYTE_   b_PulseEncoderNbr   : Pulse encoder selection  |
++|                     unsigned char_   b_PulseEncoderNbr   : Pulse encoder selection  |
+ |                                                   (0 to 3)                 |
+-|                     BYTE_   b_CycleSelection    : APCI1710_CONTINUOUS:     |
++|                     unsigned char_   b_CycleSelection    : APCI1710_CONTINUOUS:     |
+ |                                                       Each time the        |
+ |                                                       counting value is set|
+ |                                                       on "0", the pulse    |
+@@ -381,7 +381,7 @@ INT i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device * dev,
+ |                                                       If the counter is set|
+ |                                                       on "0", the pulse    |
+ |                                                       encoder is stopped.  |
+-|                     BYTE_   b_InterruptHandling : Interrupts can be        |
++|                     unsigned char_   b_InterruptHandling : Interrupts can be        |
+ |                                                   generated, when the pulse|
+ |                                                   encoder has run down.    |
+ |                                                   With this parameter the  |
+@@ -393,11 +393,11 @@ INT i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device * dev,
+ |                                                     APCI1710_DISABLE:      |
+ |                                                     Interrupts are disabled
+ 
+-  	b_ModulNbr			=(BYTE) CR_AREF(insn->chanspec);
+-	b_Action			=(BYTE) data[0];
+-	b_PulseEncoderNbr	=(BYTE) data[1];
+-	b_CycleSelection	=(BYTE) data[2];
+-	b_InterruptHandling	=(BYTE) data[3];|
++	b_ModulNbr			=(unsigned char) CR_AREF(insn->chanspec);
++	b_Action			=(unsigned char) data[0];
++	b_PulseEncoderNbr	=(unsigned char) data[1];
++	b_CycleSelection	=(unsigned char) data[2];
++	b_InterruptHandling	=(unsigned char) data[3];|
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+ +----------------------------------------------------------------------------+
+@@ -418,18 +418,18 @@ INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+-	BYTE b_ModulNbr;
+-	BYTE b_PulseEncoderNbr;
+-	BYTE b_CycleSelection;
+-	BYTE b_InterruptHandling;
+-	BYTE b_Action;
++	unsigned char b_ModulNbr;
++	unsigned char b_PulseEncoderNbr;
++	unsigned char b_CycleSelection;
++	unsigned char b_InterruptHandling;
++	unsigned char b_Action;
+ 
+ 	i_ReturnValue = insn->n;
+-	b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+-	b_Action = (BYTE) data[0];
+-	b_PulseEncoderNbr = (BYTE) data[1];
+-	b_CycleSelection = (BYTE) data[2];
+-	b_InterruptHandling = (BYTE) data[3];
++	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
++	b_Action = (unsigned char) data[0];
++	b_PulseEncoderNbr = (unsigned char) data[1];
++	b_CycleSelection = (unsigned char) data[2];
++	b_InterruptHandling = (unsigned char) data[3];
+ 
+ 	/***********************************/
+ 	/* Test the selected module number */
+@@ -662,33 +662,33 @@ INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_ReadPulseEncoderStatus                |
+-|                                       (BYTE_  b_BoardHandle,               |
+-|                                        BYTE_  b_ModulNbr,                  |
+-|                                        BYTE_  b_PulseEncoderNbr,           |
+-|                                        PBYTE_ pb_Status)                   |
++|                                       (unsigned char_  b_BoardHandle,               |
++|                                        unsigned char_  b_ModulNbr,                  |
++|                                        unsigned char_  b_PulseEncoderNbr,           |
++|                                        unsigned char *_ pb_Status)                   |
+ +----------------------------------------------------------------------------+
+ | Task    APCI1710_PULSEENCODER_READ          : Reads the pulse encoder status
+ 											and valuefrom selected pulse     |
+ |                     encoder (b_PulseEncoderNbr) from selected module       |
+ |                     (b_ModulNbr).                                          |
+ +----------------------------------------------------------------------------+
+-	BYTE   b_Type; data[0]
++	unsigned char   b_Type; data[0]
+    APCI1710_PULSEENCODER_WRITE
+  Writes a 32-bit value (ul_WriteValue) into the selected|
+ |                     pulse encoder (b_PulseEncoderNbr) from selected module |
+ |                     (b_ModulNbr). This operation set the new start pulse   |
+ |                     encoder value.
+  APCI1710_PULSEENCODER_READ
+-| Input Parameters  : BYTE_   b_BoardHandle       : Handle of board APCI-1710|
+-|            CRAREF()         BYTE_   b_ModulNbr          : Module number to         |
++| Input Parameters  : unsigned char_   b_BoardHandle       : Handle of board APCI-1710|
++|            CRAREF()         unsigned char_   b_ModulNbr          : Module number to         |
+ |                                                   configure (0 to 3)       |
+-|              data[1]       BYTE_   b_PulseEncoderNbr   : Pulse encoder selection  |
++|              data[1]       unsigned char_   b_PulseEncoderNbr   : Pulse encoder selection  |
+ |                                                   (0 to 3)
+    APCI1710_PULSEENCODER_WRITE
+ 				data[2]		ULONG_ ul_WriteValue        : 32-bit value to be       |
+ |                                                   written             |
+ +----------------------------------------------------------------------------+
+-| Output Parameters : PBYTE_ pb_Status            : Pulse encoder status.    |
++| Output Parameters : unsigned char *_ pb_Status            : Pulse encoder status.    |
+ |                                                       0 : No overflow occur|
+ |                                                       1 : Overflow occur
+ 						PULONG_ pul_ReadValue       : Pulse encoder value      |  |
+@@ -702,29 +702,29 @@ INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-/*_INT_   i_APCI1710_ReadPulseEncoderStatus       (BYTE_   b_BoardHandle,
+-						 BYTE_   b_ModulNbr,
+-						 BYTE_   b_PulseEncoderNbr,
++/*_INT_   i_APCI1710_ReadPulseEncoderStatus       (unsigned char_   b_BoardHandle,
++						 unsigned char_   b_ModulNbr,
++						 unsigned char_   b_PulseEncoderNbr,
+ 
+-   						 PBYTE_ pb_Status)
++						 unsigned char *_ pb_Status)
+ 						 */
+ INT i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusRegister;
+-	BYTE b_ModulNbr;
+-	BYTE b_PulseEncoderNbr;
+-	PBYTE pb_Status;
+-	BYTE b_Type;
++	unsigned char b_ModulNbr;
++	unsigned char b_PulseEncoderNbr;
++	unsigned char * pb_Status;
++	unsigned char b_Type;
+ 	PULONG pul_ReadValue;
+ 	ULONG ul_WriteValue;
+ 
+ 	i_ReturnValue = insn->n;
+-	b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+-	b_Type = (BYTE) data[0];
+-	b_PulseEncoderNbr = (BYTE) data[1];
+-	pb_Status = (PBYTE) & data[0];
++	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
++	b_Type = (unsigned char) data[0];
++	b_PulseEncoderNbr = (unsigned char) data[1];
++	pb_Status = (unsigned char *) & data[0];
+ 	pul_ReadValue = (PULONG) & data[1];
+ 
+ 	/***********************************/
+@@ -766,7 +766,7 @@ INT i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device * dev,
+ 						dw_StatusRegister;
+ 
+ 					*pb_Status =
+-						(BYTE) (devpriv->
++						(unsigned char) (devpriv->
+ 						s_ModuleInfo[b_ModulNbr].
+ 						s_PulseEncoderModuleInfo.
+ 						dw_StatusRegister >> (1 +
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+index 5ddd092a656a..fffd0f2463d5 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+@@ -73,16 +73,16 @@ struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)
+ INT i_APCI1710_InsnConfigPWM(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	BYTE b_ConfigType;
++	unsigned char b_ConfigType;
+ 	INT i_ReturnValue = 0;
+ 	b_ConfigType = CR_CHAN(insn->chanspec);
+ 
+ 	switch (b_ConfigType) {
+ 	case APCI1710_PWM_INIT:
+-		i_ReturnValue = i_APCI1710_InitPWM(dev, (BYTE) CR_AREF(insn->chanspec),	//  b_ModulNbr
+-			(BYTE) data[0],	//b_PWM
+-			(BYTE) data[1],	// b_ClockSelection
+-			(BYTE) data[2],	// b_TimingUnit
++		i_ReturnValue = i_APCI1710_InitPWM(dev, (unsigned char) CR_AREF(insn->chanspec),	//  b_ModulNbr
++			(unsigned char) data[0],	//b_PWM
++			(unsigned char) data[1],	// b_ClockSelection
++			(unsigned char) data[2],	// b_TimingUnit
+ 			(ULONG) data[3],	//ul_LowTiming
+ 			(ULONG) data[4],	//ul_HighTiming
+ 			(PULONG) & data[0],	//pul_RealLowTiming
+@@ -91,17 +91,17 @@ INT i_APCI1710_InsnConfigPWM(struct comedi_device * dev, struct comedi_subdevice
+ 		break;
+ 
+ 	case APCI1710_PWM_GETINITDATA:
+-		i_ReturnValue = i_APCI1710_GetPWMInitialisation(dev, (BYTE) CR_AREF(insn->chanspec),	// b_ModulNbr
+-			(BYTE) data[0],	//b_PWM
+-			(PBYTE) & data[0],	//pb_TimingUnit
++		i_ReturnValue = i_APCI1710_GetPWMInitialisation(dev, (unsigned char) CR_AREF(insn->chanspec),	// b_ModulNbr
++			(unsigned char) data[0],	//b_PWM
++			(unsigned char *) & data[0],	//pb_TimingUnit
+ 			(PULONG) & data[1],	//pul_LowTiming
+ 			(PULONG) & data[2],	//pul_HighTiming
+-			(PBYTE) & data[3],	// pb_StartLevel
+-			(PBYTE) & data[4],	// pb_StopMode
+-			(PBYTE) & data[5],	// pb_StopLevel
+-			(PBYTE) & data[6],	// pb_ExternGate
+-			(PBYTE) & data[7],	// pb_InterruptEnable
+-			(PBYTE) & data[8]	// pb_Enable
++			(unsigned char *) & data[3],	// pb_StartLevel
++			(unsigned char *) & data[4],	// pb_StopMode
++			(unsigned char *) & data[5],	// pb_StopLevel
++			(unsigned char *) & data[6],	// pb_ExternGate
++			(unsigned char *) & data[7],	// pb_InterruptEnable
++			(unsigned char *) & data[8]	// pb_Enable
+ 			);
+ 		break;
+ 
+@@ -117,11 +117,11 @@ INT i_APCI1710_InsnConfigPWM(struct comedi_device * dev, struct comedi_subdevice
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_InitPWM                               |
+-|                                       (BYTE_     b_BoardHandle,            |
+-|                                        BYTE_     b_ModulNbr,               |
+-|                                        BYTE_     b_PWM,                    |
+-|                                        BYTE_     b_ClockSelection,         |
+-|                                        BYTE_     b_TimingUnit,             |
++|                                       (unsigned char_     b_BoardHandle,            |
++|                                        unsigned char_     b_ModulNbr,               |
++|                                        unsigned char_     b_PWM,                    |
++|                                        unsigned char_     b_ClockSelection,         |
++|                                        unsigned char_     b_TimingUnit,             |
+ |                                        ULONG_   ul_LowTiming,              |
+ |                                        ULONG_   ul_HighTiming,             |
+ |                                        PULONG_ pul_RealLowTiming,          |
+@@ -135,11 +135,11 @@ INT i_APCI1710_InsnConfigPWM(struct comedi_device * dev, struct comedi_subdevice
+ |                     You must calling this function be for you call any     |
+ |                     other function witch access of the PWM.                |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_     b_BoardHandle    : Handle of board APCI-1710 |
+-|                     BYTE_     b_ModulNbr       : Module number to configure|
++| Input Parameters  : unsigned char_     b_BoardHandle    : Handle of board APCI-1710 |
++|                     unsigned char_     b_ModulNbr       : Module number to configure|
+ |                                                  (0 to 3)                  |
+-|                     BYTE_     b_PWM            : Selected PWM (0 or 1).    |
+-|                     BYTE_     b_ClockSelection : Selection from PCI bus    |
++|                     unsigned char_     b_PWM            : Selected PWM (0 or 1).    |
++|                     unsigned char_     b_ClockSelection : Selection from PCI bus    |
+ |                                                  clock                     |
+ |                                                   - APCI1710_30MHZ :       |
+ |                                                     The PC have a 30 MHz   |
+@@ -151,7 +151,7 @@ INT i_APCI1710_InsnConfigPWM(struct comedi_device * dev, struct comedi_subdevice
+ |                                                     The APCI-1710 have a   |
+ |                                                     integrated 40Mhz       |
+ |                                                     quartz.                |
+-|                     BYTE_     b_TimingUnit     : Base timing Unit (0 to 4) |
++|                     unsigned char_     b_TimingUnit     : Base timing Unit (0 to 4) |
+ |                                                       0 : ns               |
+ |                                                       1 : æs               |
+ |                                                       2 : ms               |
+@@ -180,10 +180,10 @@ INT i_APCI1710_InsnConfigPWM(struct comedi_device * dev, struct comedi_subdevice
+ */
+ 
+ INT i_APCI1710_InitPWM(struct comedi_device * dev,
+-	BYTE b_ModulNbr,
+-	BYTE b_PWM,
+-	BYTE b_ClockSelection,
+-	BYTE b_TimingUnit,
++	unsigned char b_ModulNbr,
++	unsigned char b_PWM,
++	unsigned char b_ClockSelection,
++	unsigned char b_TimingUnit,
+ 	ULONG ul_LowTiming,
+ 	ULONG ul_HighTiming,
+ 	PULONG pul_RealLowTiming, PULONG pul_RealHighTiming)
+@@ -1442,29 +1442,29 @@ INT i_APCI1710_InitPWM(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_GetPWMInitialisation                  |
+-|                                       (BYTE_     b_BoardHandle,            |
+-|                                        BYTE_     b_ModulNbr,               |
+-|                                        BYTE_     b_PWM,                    |
+-|                                        PBYTE_   pb_TimingUnit,             |
++|                                       (unsigned char_     b_BoardHandle,            |
++|                                        unsigned char_     b_ModulNbr,               |
++|                                        unsigned char_     b_PWM,                    |
++|                                        unsigned char *_   pb_TimingUnit,             |
+ |                                        PULONG_ pul_LowTiming,              |
+ |                                        PULONG_ pul_HighTiming,             |
+-|                                        PBYTE_   pb_StartLevel,             |
+-|                                        PBYTE_   pb_StopMode,               |
+-|                                        PBYTE_   pb_StopLevel,              |
+-|                                        PBYTE_   pb_ExternGate,             |
+-|                                        PBYTE_   pb_InterruptEnable,        |
+-|                                        PBYTE_   pb_Enable)                 |
++|                                        unsigned char *_   pb_StartLevel,             |
++|                                        unsigned char *_   pb_StopMode,               |
++|                                        unsigned char *_   pb_StopLevel,              |
++|                                        unsigned char *_   pb_ExternGate,             |
++|                                        unsigned char *_   pb_InterruptEnable,        |
++|                                        unsigned char *_   pb_Enable)                 |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the PWM (b_PWM) initialisation from selected    |
+ |                     module (b_ModulNbr). You must calling the              |
+ |                     "i_APCI1710_InitPWM" function be for you call this     |
+ |                     function.                                              |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle : Handle of board APCI-1710        |
+-|                     BYTE_ b_ModulNbr    : Selected module number (0 to 3)  |
+-|                     BYTE_ b_PWM         : Selected PWM (0 or 1)            |
++| Input Parameters  : unsigned char_ b_BoardHandle : Handle of board APCI-1710        |
++|                     unsigned char_ b_ModulNbr    : Selected module number (0 to 3)  |
++|                     unsigned char_ b_PWM         : Selected PWM (0 or 1)            |
+ +----------------------------------------------------------------------------+
+-| Output Parameters : PBYTE_  pb_TimingUnit      : Base timing Unit (0 to 4) |
++| Output Parameters : unsigned char *_  pb_TimingUnit      : Base timing Unit (0 to 4) |
+ |                                                       0 : ns               |
+ |                                                       1 : æs               |
+ |                                                       2 : ms               |
+@@ -1472,13 +1472,13 @@ INT i_APCI1710_InitPWM(struct comedi_device * dev,
+ |                                                       4 : mn               |
+ |                     PULONG_ pul_LowTiming      : Low base timing value.    |
+ |                     PULONG_ pul_HighTiming     : High base timing value.   |
+-|                     PBYTE_  pb_StartLevel      : Start period level        |
++|                     unsigned char *_  pb_StartLevel      : Start period level        |
+ |                                                  selection                 |
+ |                                                       0 : The period start |
+ |                                                           with a low level |
+ |                                                       1 : The period start |
+ |                                                           with a high level|
+-|                     PBYTE_  pb_StopMode        : Stop mode selection       |
++|                     unsigned char *_  pb_StopMode        : Stop mode selection       |
+ |                                                  0 : The PWM is stopped    |
+ |                                                      directly after the    |
+ |                                                     "i_APCI1710_DisablePWM"|
+@@ -1489,7 +1489,7 @@ INT i_APCI1710_InitPWM(struct comedi_device * dev,
+ |                                                      function the PWM is   |
+ |                                                      stopped at the end    |
+ |                                                      from last period cycle|
+-|                     PBYTE_  pb_StopLevel        : Stop PWM level selection |
++|                     unsigned char *_  pb_StopLevel        : Stop PWM level selection |
+ |                                                    0 : The output signal   |
+ |                                                        keep the level after|
+ |                                                        the                 |
+@@ -1504,13 +1504,13 @@ INT i_APCI1710_InitPWM(struct comedi_device * dev,
+ |                                                        the                 |
+ |                                                     "i_APCI1710_DisablePWM"|
+ |                                                        function            |
+-|                     PBYTE_  pb_ExternGate      : Extern gate action        |
++|                     unsigned char *_  pb_ExternGate      : Extern gate action        |
+ |                                                  selection                 |
+ |                                                   0 : Extern gate signal   |
+ |                                                       not used.            |
+ |                                                   1 : Extern gate signal   |
+ |                                                       used.                |
+-|                     PBYTE_  pb_InterruptEnable : Enable or disable the PWM |
++|                     unsigned char *_  pb_InterruptEnable : Enable or disable the PWM |
+ |                                                  interrupt.                |
+ |                                                  - APCI1710_ENABLE :       |
+ |                                                    Enable the PWM interrupt|
+@@ -1519,7 +1519,7 @@ INT i_APCI1710_InitPWM(struct comedi_device * dev,
+ |                                                  - APCI1710_DISABLE :      |
+ |                                                    Disable the PWM         |
+ |                                                    interrupt               |
+-|                     PBYTE_  pb_Enable          : Indicate if the PWM is    |
++|                     unsigned char *_  pb_Enable          : Indicate if the PWM is    |
+ |                                                  enabled or no             |
+ |                                                       0 : PWM not enabled  |
+ |                                                       1 : PWM enabled      |
+@@ -1535,15 +1535,15 @@ INT i_APCI1710_InitPWM(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_GetPWMInitialisation(struct comedi_device * dev,
+-	BYTE b_ModulNbr,
+-	BYTE b_PWM,
+-	PBYTE pb_TimingUnit,
++	unsigned char b_ModulNbr,
++	unsigned char b_PWM,
++	unsigned char * pb_TimingUnit,
+ 	PULONG pul_LowTiming,
+ 	PULONG pul_HighTiming,
+-	PBYTE pb_StartLevel,
+-	PBYTE pb_StopMode,
+-	PBYTE pb_StopLevel,
+-	PBYTE pb_ExternGate, PBYTE pb_InterruptEnable, PBYTE pb_Enable)
++	unsigned char * pb_StartLevel,
++	unsigned char * pb_StopMode,
++	unsigned char * pb_StopLevel,
++	unsigned char * pb_ExternGate, unsigned char * pb_InterruptEnable, unsigned char * pb_Enable)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_Status;
+@@ -1602,20 +1602,20 @@ INT i_APCI1710_GetPWMInitialisation(struct comedi_device * dev,
+ 						(64 * b_ModulNbr));
+ 
+ 					*pb_StartLevel =
+-						(BYTE) ((dw_Command >> 5) & 1);
++						(unsigned char) ((dw_Command >> 5) & 1);
+ 					*pb_StopMode =
+-						(BYTE) ((dw_Command >> 0) & 1);
++						(unsigned char) ((dw_Command >> 0) & 1);
+ 					*pb_StopLevel =
+-						(BYTE) ((dw_Command >> 1) & 1);
++						(unsigned char) ((dw_Command >> 1) & 1);
+ 					*pb_ExternGate =
+-						(BYTE) ((dw_Command >> 4) & 1);
++						(unsigned char) ((dw_Command >> 4) & 1);
+ 					*pb_InterruptEnable =
+-						(BYTE) ((dw_Command >> 3) & 1);
++						(unsigned char) ((dw_Command >> 3) & 1);
+ 
+ 					if (*pb_StopLevel) {
+ 						*pb_StopLevel =
+ 							*pb_StopLevel +
+-							(BYTE) ((dw_Command >>
++							(unsigned char) ((dw_Command >>
+ 								2) & 1);
+ 					}
+ 
+@@ -1628,7 +1628,7 @@ INT i_APCI1710_GetPWMInitialisation(struct comedi_device * dev,
+ 						(64 * b_ModulNbr));
+ 
+ 					*pb_Enable =
+-						(BYTE) ((dw_Command >> 0) & 1);
++						(unsigned char) ((dw_Command >> 0) & 1);
+ 
+ 					*pb_TimingUnit = devpriv->
+ 						s_ModuleInfo[b_ModulNbr].
+@@ -1686,30 +1686,30 @@ struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)
+ INT i_APCI1710_InsnWritePWM(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	BYTE b_WriteType;
++	unsigned char b_WriteType;
+ 	INT i_ReturnValue = 0;
+ 	b_WriteType = CR_CHAN(insn->chanspec);
+ 
+ 	switch (b_WriteType) {
+ 	case APCI1710_PWM_ENABLE:
+ 		i_ReturnValue = i_APCI1710_EnablePWM(dev,
+-			(BYTE) CR_AREF(insn->chanspec),
+-			(BYTE) data[0],
+-			(BYTE) data[1],
+-			(BYTE) data[2],
+-			(BYTE) data[3], (BYTE) data[4], (BYTE) data[5]);
++			(unsigned char) CR_AREF(insn->chanspec),
++			(unsigned char) data[0],
++			(unsigned char) data[1],
++			(unsigned char) data[2],
++			(unsigned char) data[3], (unsigned char) data[4], (unsigned char) data[5]);
+ 		break;
+ 
+ 	case APCI1710_PWM_DISABLE:
+ 		i_ReturnValue = i_APCI1710_DisablePWM(dev,
+-			(BYTE) CR_AREF(insn->chanspec), (BYTE) data[0]);
++			(unsigned char) CR_AREF(insn->chanspec), (unsigned char) data[0]);
+ 		break;
+ 
+ 	case APCI1710_PWM_NEWTIMING:
+ 		i_ReturnValue = i_APCI1710_SetNewPWMTiming(dev,
+-			(BYTE) CR_AREF(insn->chanspec),
+-			(BYTE) data[0],
+-			(BYTE) data[1], (ULONG) data[2], (ULONG) data[3]);
++			(unsigned char) CR_AREF(insn->chanspec),
++			(unsigned char) data[0],
++			(unsigned char) data[1], (ULONG) data[2], (ULONG) data[3]);
+ 		break;
+ 
+ 	default:
+@@ -1724,14 +1724,14 @@ INT i_APCI1710_InsnWritePWM(struct comedi_device * dev, struct comedi_subdevice
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_     i_APCI1710_EnablePWM                         |
+-|                                       (BYTE_  b_BoardHandle,               |
+-|                                        BYTE_  b_ModulNbr,                  |
+-|                                        BYTE_  b_PWM,                       |
+-|                                        BYTE_  b_StartLevel,                |
+-|                                        BYTE_  b_StopMode,                  |
+-|                                        BYTE_  b_StopLevel,                 |
+-|                                        BYTE_  b_ExternGate,                |
+-|                                        BYTE_  b_InterruptEnable)           |
++|                                       (unsigned char_  b_BoardHandle,               |
++|                                        unsigned char_  b_ModulNbr,                  |
++|                                        unsigned char_  b_PWM,                       |
++|                                        unsigned char_  b_StartLevel,                |
++|                                        unsigned char_  b_StopMode,                  |
++|                                        unsigned char_  b_StopLevel,                 |
++|                                        unsigned char_  b_ExternGate,                |
++|                                        unsigned char_  b_InterruptEnable)           |
+ +----------------------------------------------------------------------------+
+ | Task              : Enable the selected PWM (b_PWM) from selected module   |
+ |                     (b_ModulNbr). You must calling the "i_APCI1710_InitPWM"|
+@@ -1741,16 +1741,16 @@ INT i_APCI1710_InsnWritePWM(struct comedi_device * dev, struct comedi_subdevice
+ |                     See function "i_APCI1710_SetBoardIntRoutineX" and the  |
+ |                     Interrupt mask description chapter.                    |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+-|                     BYTE_ b_ModulNbr        : Selected module number       |
++| Input Parameters  : unsigned char_ b_BoardHandle     : Handle of board APCI-1710    |
++|                     unsigned char_ b_ModulNbr        : Selected module number       |
+ |                                               (0 to 3)                     |
+-|                     BYTE_ b_PWM             : Selected PWM (0 or 1)        |
+-|                     BYTE_ b_StartLevel      : Start period level selection |
++|                     unsigned char_ b_PWM             : Selected PWM (0 or 1)        |
++|                     unsigned char_ b_StartLevel      : Start period level selection |
+ |                                                0 : The period start with a |
+ |                                                    low level               |
+ |                                                1 : The period start with a |
+ |                                                    high level              |
+-|                     BYTE_ b_StopMode        : Stop mode selection          |
++|                     unsigned char_ b_StopMode        : Stop mode selection          |
+ |                                                0 : The PWM is stopped      |
+ |                                                    directly after the      |
+ |                                                    "i_APCI1710_DisablePWM" |
+@@ -1761,7 +1761,7 @@ INT i_APCI1710_InsnWritePWM(struct comedi_device * dev, struct comedi_subdevice
+ |                                                     function the PWM is    |
+ |                                                     stopped at the end from|
+ |                                                     last period cycle.     |
+-|                     BYTE_ b_StopLevel       : Stop PWM level selection     |
++|                     unsigned char_ b_StopLevel       : Stop PWM level selection     |
+ |                                                0 : The output signal keep  |
+ |                                                    the level after the     |
+ |                                                    "i_APCI1710_DisablePWM" |
+@@ -1774,11 +1774,11 @@ INT i_APCI1710_InsnWritePWM(struct comedi_device * dev, struct comedi_subdevice
+ |                                                    to high after the       |
+ |                                                    "i_APCI1710_DisablePWM" |
+ |                                                    function                |
+-|                     BYTE_ b_ExternGate      : Extern gate action selection |
++|                     unsigned char_ b_ExternGate      : Extern gate action selection |
+ |                                                0 : Extern gate signal not  |
+ |                                                    used.                   |
+ |                                                1 : Extern gate signal used.|
+-|                     BYTE_ b_InterruptEnable : Enable or disable the PWM    |
++|                     unsigned char_ b_InterruptEnable : Enable or disable the PWM    |
+ |                                               interrupt.                   |
+ |                                               - APCI1710_ENABLE :          |
+ |                                                 Enable the PWM interrupt   |
+@@ -1807,11 +1807,11 @@ INT i_APCI1710_InsnWritePWM(struct comedi_device * dev, struct comedi_subdevice
+ */
+ 
+ INT i_APCI1710_EnablePWM(struct comedi_device * dev,
+-	BYTE b_ModulNbr,
+-	BYTE b_PWM,
+-	BYTE b_StartLevel,
+-	BYTE b_StopMode,
+-	BYTE b_StopLevel, BYTE b_ExternGate, BYTE b_InterruptEnable)
++	unsigned char b_ModulNbr,
++	unsigned char b_PWM,
++	unsigned char b_StartLevel,
++	unsigned char b_StopMode,
++	unsigned char b_StopLevel, unsigned char b_ExternGate, unsigned char b_InterruptEnable)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_Status;
+@@ -2034,9 +2034,9 @@ INT i_APCI1710_EnablePWM(struct comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     : _INT_ i_APCI1710_DisablePWM (BYTE_  b_BoardHandle,     |
+-|                                                  BYTE_  b_ModulNbr,        |
+-|                                                  BYTE_  b_PWM)             |
++| Function Name     : _INT_ i_APCI1710_DisablePWM (unsigned char_  b_BoardHandle,     |
++|                                                  unsigned char_  b_ModulNbr,        |
++|                                                  unsigned char_  b_PWM)             |
+ +----------------------------------------------------------------------------+
+ | Task              : Disable the selected PWM (b_PWM) from selected module  |
+ |                     (b_ModulNbr). The output signal level depend of the    |
+@@ -2045,8 +2045,8 @@ INT i_APCI1710_EnablePWM(struct comedi_device * dev,
+ |                     parameters from this function.                         |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :BYTE_ b_BoardHandle : Handle of board APCI-1710         |
+-|                    BYTE_ b_ModulNbr    : Selected module number (0 to 3)   |
+-|                    BYTE_ b_PWM         : Selected PWM (0 or 1)             |
++|                    unsigned char_ b_ModulNbr    : Selected module number (0 to 3)   |
++|                    unsigned char_ b_PWM         : Selected PWM (0 or 1)             |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+ +----------------------------------------------------------------------------+
+@@ -2062,7 +2062,7 @@ INT i_APCI1710_EnablePWM(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_DisablePWM(struct comedi_device * dev, BYTE b_ModulNbr, BYTE b_PWM)
++INT i_APCI1710_DisablePWM(struct comedi_device * dev, unsigned char b_ModulNbr, unsigned char b_PWM)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_Status;
+@@ -2150,11 +2150,11 @@ INT i_APCI1710_DisablePWM(struct comedi_device * dev, BYTE b_ModulNbr, BYTE b_PW
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_SetNewPWMTiming                       |
+-|                                       (BYTE_     b_BoardHandle,            |
+-|                                        BYTE_     b_ModulNbr,               |
+-|                                        BYTE_     b_PWM,                    |
+-|                                        BYTE_     b_ClockSelection,         |
+-|                                        BYTE_     b_TimingUnit,             |
++|                                       (unsigned char_     b_BoardHandle,            |
++|                                        unsigned char_     b_ModulNbr,               |
++|                                        unsigned char_     b_PWM,                    |
++|                                        unsigned char_     b_ClockSelection,         |
++|                                        unsigned char_     b_TimingUnit,             |
+ |                                        ULONG_   ul_LowTiming,              |
+ |                                        ULONG_   ul_HighTiming)             |
+ +----------------------------------------------------------------------------+
+@@ -2162,11 +2162,11 @@ INT i_APCI1710_DisablePWM(struct comedi_device * dev, BYTE b_ModulNbr, BYTE b_PW
+ |                     ul_TimingUnit determine the low/high timing base for   |
+ |                     the period.                                            |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_     b_BoardHandle    : Handle of board APCI-1710 |
+-|                     BYTE_     b_ModulNbr       : Module number to configure|
++| Input Parameters  : unsigned char_     b_BoardHandle    : Handle of board APCI-1710 |
++|                     unsigned char_     b_ModulNbr       : Module number to configure|
+ |                                                  (0 to 3)                  |
+-|                     BYTE_     b_PWM            : Selected PWM (0 or 1).    |
+-|                     BYTE_     b_TimingUnit     : Base timing Unit (0 to 4) |
++|                     unsigned char_     b_PWM            : Selected PWM (0 or 1).    |
++|                     unsigned char_     b_TimingUnit     : Base timing Unit (0 to 4) |
+ |                                                       0 : ns               |
+ |                                                       1 : æs               |
+ |                                                       2 : ms               |
+@@ -2190,10 +2190,10 @@ INT i_APCI1710_DisablePWM(struct comedi_device * dev, BYTE b_ModulNbr, BYTE b_PW
+ */
+ 
+ INT i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+-	BYTE b_ModulNbr,
+-	BYTE b_PWM, BYTE b_TimingUnit, ULONG ul_LowTiming, ULONG ul_HighTiming)
++	unsigned char b_ModulNbr,
++	unsigned char b_PWM, unsigned char b_TimingUnit, ULONG ul_LowTiming, ULONG ul_HighTiming)
+ {
+-	BYTE b_ClockSelection;
++	unsigned char b_ClockSelection;
+ 	INT i_ReturnValue = 0;
+ 	ULONG ul_LowTimerValue = 0;
+ 	ULONG ul_HighTimerValue = 0;
+@@ -3417,37 +3417,37 @@ INT i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_GetPWMStatus                          |
+-|                               (BYTE_    b_BoardHandle,                     |
+-|                                BYTE_    b_ModulNbr,                        |
+-|                                BYTE_    b_PWM,                             |
+-|                                PBYTE_  pb_PWMOutputStatus,                 |
+-|                                PBYTE_  pb_ExternGateStatus)                |
++|                               (unsigned char_    b_BoardHandle,                     |
++|                                unsigned char_    b_ModulNbr,                        |
++|                                unsigned char_    b_PWM,                             |
++|                                unsigned char *_  pb_PWMOutputStatus,                 |
++|                                unsigned char *_  pb_ExternGateStatus)                |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status from selected PWM (b_PWM) from       |
+ |                     selected module (b_ModulNbr).                          |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_  b_BoardHandle : Handle of board APCI-1710       |
+-|                     BYTE_  b_PWM         : Selected PWM (0 or 1)           |
+-|                     BYTE_  b_ModulNbr    : Selected module number (0 to 3)
+-	b_ModulNbr			=(BYTE)  CR_AREF(insn->chanspec);
+-	b_PWM				=(BYTE)  data[0];
++| Input Parameters  : unsigned char_  b_BoardHandle : Handle of board APCI-1710       |
++|                     unsigned char_  b_PWM         : Selected PWM (0 or 1)           |
++|                     unsigned char_  b_ModulNbr    : Selected module number (0 to 3)
++	b_ModulNbr			=(unsigned char)  CR_AREF(insn->chanspec);
++	b_PWM				=(unsigned char)  data[0];
+ 
+  |
+ +----------------------------------------------------------------------------+
+-| Output Parameters : PBYTE_  pb_PWMOutputStatus  : Return the PWM output    |
++| Output Parameters : unsigned char *_  pb_PWMOutputStatus  : Return the PWM output    |
+ |                                                   level status.            |
+ |                                                    0 : The PWM output level|
+ |                                                        is low.             |
+ |                                                    1 : The PWM output level|
+ |                                                        is high.            |
+-|                     PBYTE_  pb_ExternGateStatus : Return the extern gate   |
++|                     unsigned char *_  pb_ExternGateStatus : Return the extern gate   |
+ |                                                   level status.            |
+ |                                                    0 : The extern gate is  |
+ |                                                        low.                |
+ |                                                    1 : The extern gate is  |
+ |                                                        high.
+-    pb_PWMOutputStatus	=(PBYTE) data[0];
+-	pb_ExternGateStatus =(PBYTE) data[1];             |
++    pb_PWMOutputStatus	=(unsigned char *) data[0];
++	pb_ExternGateStatus =(unsigned char *) data[1];             |
+ +----------------------------------------------------------------------------+
+ | Return Value      :  0: No error                                           |
+ |                     -1: The handle parameter of the board is wrong         |
+@@ -3466,16 +3466,16 @@ INT i_APCI1710_InsnReadGetPWMStatus(struct comedi_device * dev, struct comedi_su
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_Status;
+ 
+-	BYTE b_ModulNbr;
+-	BYTE b_PWM;
+-	PBYTE pb_PWMOutputStatus;
+-	PBYTE pb_ExternGateStatus;
++	unsigned char b_ModulNbr;
++	unsigned char b_PWM;
++	unsigned char * pb_PWMOutputStatus;
++	unsigned char * pb_ExternGateStatus;
+ 
+ 	i_ReturnValue = insn->n;
+-	b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+-	b_PWM = (BYTE) CR_CHAN(insn->chanspec);
+-	pb_PWMOutputStatus = (PBYTE) & data[0];
+-	pb_ExternGateStatus = (PBYTE) & data[1];
++	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
++	b_PWM = (unsigned char) CR_CHAN(insn->chanspec);
++	pb_PWMOutputStatus = (unsigned char *) & data[0];
++	pb_ExternGateStatus = (unsigned char *) & data[1];
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -3509,10 +3509,10 @@ INT i_APCI1710_InsnReadGetPWMStatus(struct comedi_device * dev, struct comedi_su
+ 
+ 					if (dw_Status & 0x1) {
+ 						*pb_PWMOutputStatus =
+-							(BYTE) ((dw_Status >> 7)
++							(unsigned char) ((dw_Status >> 7)
+ 							& 1);
+ 						*pb_ExternGateStatus =
+-							(BYTE) ((dw_Status >> 6)
++							(unsigned char) ((dw_Status >> 6)
+ 							& 1);
+ 					}	// if (dw_Status & 0x1)
+ 					else {
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
+index c1b7f4ca47c3..8d8052d4b3f9 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
+@@ -30,43 +30,43 @@ INT i_APCI1710_InsnConfigPWM(struct comedi_device *dev, struct comedi_subdevice
+ 			     struct comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InitPWM(struct comedi_device *dev,
+-		       BYTE b_ModulNbr,
+-		       BYTE b_PWM,
+-		       BYTE b_ClockSelection,
+-		       BYTE b_TimingUnit,
++		       unsigned char b_ModulNbr,
++		       unsigned char b_PWM,
++		       unsigned char b_ClockSelection,
++		       unsigned char b_TimingUnit,
+ 		       ULONG ul_LowTiming,
+ 		       ULONG ul_HighTiming,
+ 		       PULONG pul_RealLowTiming, PULONG pul_RealHighTiming);
+ 
+ INT i_APCI1710_GetPWMInitialisation(struct comedi_device *dev,
+-				    BYTE b_ModulNbr,
+-				    BYTE b_PWM,
+-				    PBYTE pb_TimingUnit,
++				    unsigned char b_ModulNbr,
++				    unsigned char b_PWM,
++				    unsigned char * pb_TimingUnit,
+ 				    PULONG pul_LowTiming,
+ 				    PULONG pul_HighTiming,
+-				    PBYTE pb_StartLevel,
+-				    PBYTE pb_StopMode,
+-				    PBYTE pb_StopLevel,
+-				    PBYTE pb_ExternGate,
+-				    PBYTE pb_InterruptEnable, PBYTE pb_Enable);
++				    unsigned char * pb_StartLevel,
++				    unsigned char * pb_StopMode,
++				    unsigned char * pb_StopLevel,
++				    unsigned char * pb_ExternGate,
++				    unsigned char * pb_InterruptEnable, unsigned char * pb_Enable);
+ 
+ INT i_APCI1710_InsnWritePWM(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			    struct comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_EnablePWM(struct comedi_device *dev,
+-			 BYTE b_ModulNbr,
+-			 BYTE b_PWM,
+-			 BYTE b_StartLevel,
+-			 BYTE b_StopMode,
+-			 BYTE b_StopLevel, BYTE b_ExternGate,
+-			 BYTE b_InterruptEnable);
++			 unsigned char b_ModulNbr,
++			 unsigned char b_PWM,
++			 unsigned char b_StartLevel,
++			 unsigned char b_StopMode,
++			 unsigned char b_StopLevel, unsigned char b_ExternGate,
++			 unsigned char b_InterruptEnable);
+ 
+ INT i_APCI1710_SetNewPWMTiming(struct comedi_device *dev,
+-			       BYTE b_ModulNbr,
+-			       BYTE b_PWM, BYTE b_TimingUnit,
++			       unsigned char b_ModulNbr,
++			       unsigned char b_PWM, unsigned char b_TimingUnit,
+ 			       ULONG ul_LowTiming, ULONG ul_HighTiming);
+ 
+-INT i_APCI1710_DisablePWM(struct comedi_device *dev, BYTE b_ModulNbr, BYTE b_PWM);
++INT i_APCI1710_DisablePWM(struct comedi_device *dev, unsigned char b_ModulNbr, unsigned char b_PWM);
+ 
+ INT i_APCI1710_InsnReadGetPWMStatus(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				    struct comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+index bb6e1622e379..35153b142d81 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+@@ -65,31 +65,31 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_InitSSI                               |
+-|                               (BYTE_    b_BoardHandle,                     |
+-|                                BYTE_    b_ModulNbr,                        |
+-|                                BYTE_    b_SSIProfile,                      |
+-|                                BYTE_    b_PositionTurnLength,              |
+-|                                BYTE_    b_TurnCptLength,                   |
+-|                                BYTE_    b_PCIInputClock,                   |
++|                               (unsigned char_    b_BoardHandle,                     |
++|                                unsigned char_    b_ModulNbr,                        |
++|                                unsigned char_    b_SSIProfile,                      |
++|                                unsigned char_    b_PositionTurnLength,              |
++|                                unsigned char_    b_TurnCptLength,                   |
++|                                unsigned char_    b_PCIInputClock,                   |
+ |                                ULONG_  ul_SSIOutputClock,                  |
+-|                                BYTE_    b_SSICountingMode)                 |
++|                                unsigned char_    b_SSICountingMode)                 |
+ +----------------------------------------------------------------------------+
+ | Task              : Configure the SSI operating mode from selected module  |
+ |                     (b_ModulNbr). You must calling this function be for you|
+ |                     call any other function witch access of SSI.           |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle         : Handle of board APCI-1710|
+-|                     BYTE_ b_ModulNbr            : Module number to         |
++| Input Parameters  : unsigned char_ b_BoardHandle         : Handle of board APCI-1710|
++|                     unsigned char_ b_ModulNbr            : Module number to         |
+ |                                                   configure (0 to 3)       |
+-|                     BYTE_  b_SSIProfile         : Selection from SSI       |
++|                     unsigned char_  b_SSIProfile         : Selection from SSI       |
+ |                                                   profile length (2 to 32).|
+-|                     BYTE_  b_PositionTurnLength : Selection from SSI       |
++|                     unsigned char_  b_PositionTurnLength : Selection from SSI       |
+ |                                                   position data length     |
+ |                                                   (1 to 31).               |
+-|                     BYTE_  b_TurnCptLength      : Selection from SSI turn  |
++|                     unsigned char_  b_TurnCptLength      : Selection from SSI turn  |
+ |                                                   counter data length      |
+ |                                                   (1 to 31).               |
+-|                     BYTE   b_PCIInputClock      : Selection from PCI bus   |
++|                     unsigned char   b_PCIInputClock      : Selection from PCI bus   |
+ |                                                   clock                    |
+ |                                                 - APCI1710_30MHZ :         |
+ |                                                   The PC have a PCI bus    |
+@@ -103,7 +103,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ |                                                   for 30 MHz selection.    |
+ |                                                   From  252 to 5 000 000 Hz|
+ |                                                   for 33 MHz selection.    |
+-|                     BYTE   b_SSICountingMode    : SSI counting mode        |
++|                     unsigned char   b_SSICountingMode    : SSI counting mode        |
+ |                                                   selection                |
+ |                                                 - APCI1710_BINARY_MODE :   |
+ |                                                    Binary counting mode.   |
+@@ -111,12 +111,12 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ |                                                    Gray counting mode.
+ 
+ 	b_ModulNbr			= CR_AREF(insn->chanspec);
+-	b_SSIProfile		= (BYTE) data[0];
+-	b_PositionTurnLength= (BYTE) data[1];
+-	b_TurnCptLength		= (BYTE) data[2];
+-	b_PCIInputClock		= (BYTE) data[3];
++	b_SSIProfile		= (unsigned char) data[0];
++	b_PositionTurnLength= (unsigned char) data[1];
++	b_TurnCptLength		= (unsigned char) data[2];
++	b_PCIInputClock		= (unsigned char) data[3];
+ 	ul_SSIOutputClock	= (ULONG) data[4];
+-	b_SSICountingMode	= (BYTE)  data[5];     |
++	b_SSICountingMode	= (unsigned char)  data[5];     |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+ +----------------------------------------------------------------------------+
+@@ -138,17 +138,17 @@ INT i_APCI1710_InsnConfigInitSSI(struct comedi_device * dev, struct comedi_subde
+ {
+ 	INT i_ReturnValue = 0;
+ 	UINT ui_TimerValue;
+-	BYTE b_ModulNbr, b_SSIProfile, b_PositionTurnLength, b_TurnCptLength,
++	unsigned char b_ModulNbr, b_SSIProfile, b_PositionTurnLength, b_TurnCptLength,
+ 		b_PCIInputClock, b_SSICountingMode;
+ 	ULONG ul_SSIOutputClock;
+ 
+ 	b_ModulNbr = CR_AREF(insn->chanspec);
+-	b_SSIProfile = (BYTE) data[0];
+-	b_PositionTurnLength = (BYTE) data[1];
+-	b_TurnCptLength = (BYTE) data[2];
+-	b_PCIInputClock = (BYTE) data[3];
++	b_SSIProfile = (unsigned char) data[0];
++	b_PositionTurnLength = (unsigned char) data[1];
++	b_TurnCptLength = (unsigned char) data[2];
++	b_PCIInputClock = (unsigned char) data[3];
+ 	ul_SSIOutputClock = (ULONG) data[4];
+-	b_SSICountingMode = (BYTE) data[5];
++	b_SSICountingMode = (unsigned char) data[5];
+ 
+ 	i_ReturnValue = insn->n;
+ 	/**************************/
+@@ -357,9 +357,9 @@ INT i_APCI1710_InsnConfigInitSSI(struct comedi_device * dev, struct comedi_subde
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_  i_APCI1710_Read1SSIValue                        |
+-|                               (BYTE_     b_BoardHandle,                    |
+-|                                BYTE_     b_ModulNbr,                       |
+-|                                BYTE_     b_SelectedSSI,                    |
++|                               (unsigned char_     b_BoardHandle,                    |
++|                                unsigned char_     b_ModulNbr,                       |
++|                                unsigned char_     b_SelectedSSI,                    |
+ |                                PULONG_ pul_Position,                       |
+ |                                PULONG_ pul_TurnCpt)
+  INT i_APCI1710_ReadSSIValue(struct comedi_device *dev,struct comedi_subdevice *s,
+@@ -373,15 +373,15 @@ INT i_APCI1710_InsnConfigInitSSI(struct comedi_device * dev, struct comedi_subde
+ 						or Read all SSI counter (b_SelectedSSI) from              |
+ |                     selected module (b_ModulNbr).                            |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle         : Handle of board APCI-1710|
+-|                     BYTE_ b_ModulNbr            : Module number to         |
++| Input Parameters  : unsigned char_ b_BoardHandle         : Handle of board APCI-1710|
++|                     unsigned char_ b_ModulNbr            : Module number to         |
+ |                                                   configure (0 to 3)       |
+-|                     BYTE_ b_SelectedSSI         : Selection from SSI       |
++|                     unsigned char_ b_SelectedSSI         : Selection from SSI       |
+ |                                                   counter (0 to 2)
+ 
+-    b_ModulNbr		=   (BYTE) CR_AREF(insn->chanspec);
+-	b_SelectedSSI	=	(BYTE) CR_CHAN(insn->chanspec); (in case of single ssi)
+-	b_ReadType		=	(BYTE) CR_RANGE(insn->chanspec);
++    b_ModulNbr		=   (unsigned char) CR_AREF(insn->chanspec);
++	b_SelectedSSI	=	(unsigned char) CR_CHAN(insn->chanspec); (in case of single ssi)
++	b_ReadType		=	(unsigned char) CR_RANGE(insn->chanspec);
+ |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : PULONG_  pul_Position       : SSI position in the turn |
+@@ -404,18 +404,18 @@ INT i_APCI1710_InsnReadSSIValue(struct comedi_device * dev, struct comedi_subdev
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+-	BYTE b_Cpt;
+-	BYTE b_Length;
+-	BYTE b_Schift;
+-	BYTE b_SSICpt;
++	unsigned char b_Cpt;
++	unsigned char b_Length;
++	unsigned char b_Schift;
++	unsigned char b_SSICpt;
+ 	DWORD dw_And;
+ 	DWORD dw_And1;
+ 	DWORD dw_And2;
+ 	DWORD dw_StatusReg;
+ 	DWORD dw_CounterValue;
+-	BYTE b_ModulNbr;
+-	BYTE b_SelectedSSI;
+-	BYTE b_ReadType;
++	unsigned char b_ModulNbr;
++	unsigned char b_SelectedSSI;
++	unsigned char b_ReadType;
+ 	PULONG pul_Position;
+ 	PULONG pul_TurnCpt;
+ 	PULONG pul_Position1;
+@@ -428,9 +428,9 @@ INT i_APCI1710_InsnReadSSIValue(struct comedi_device * dev, struct comedi_subdev
+ // For Read all
+ 	pul_Position = (PULONG) & data[0];	//0-2
+ 	pul_TurnCpt = (PULONG) & data[3];	//3-5
+-	b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+-	b_SelectedSSI = (BYTE) CR_CHAN(insn->chanspec);
+-	b_ReadType = (BYTE) CR_RANGE(insn->chanspec);
++	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
++	b_SelectedSSI = (unsigned char) CR_CHAN(insn->chanspec);
++	b_ReadType = (unsigned char) CR_RANGE(insn->chanspec);
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -701,10 +701,10 @@ INT i_APCI1710_InsnReadSSIValue(struct comedi_device * dev, struct comedi_subdev
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_   i_APCI1710_ReadSSI1DigitalInput                |
+-|                                       (BYTE_     b_BoardHandle,            |
+-|                                        BYTE_     b_ModulNbr,               |
+-|                                        BYTE_     b_InputChannel,           |
+-|                                        PBYTE_   pb_ChannelStatus)          |
++|                                       (unsigned char_     b_BoardHandle,            |
++|                                        unsigned char_     b_ModulNbr,               |
++|                                        unsigned char_     b_InputChannel,           |
++|                                        unsigned char *_   pb_ChannelStatus)          |
+ +----------------------------------------------------------------------------+
+ | Task              :
+ 					(0) Set the digital output from selected SSI moule         |
+@@ -716,13 +716,13 @@ INT i_APCI1710_InsnReadSSIValue(struct comedi_device * dev, struct comedi_subdev
+                     (3)Read the status from all SSI digital inputs from       |
+ |                     selected SSI module (b_ModulNbr)                   |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle         : Handle of board APCI-1710|
+-|                     BYTE_ b_ModulNbr    CR_AREF        : Module number to         |
++| Input Parameters  : unsigned char_ b_BoardHandle         : Handle of board APCI-1710|
++|                     unsigned char_ b_ModulNbr    CR_AREF        : Module number to         |
+ |                                                   configure (0 to 3)       |
+-|                     BYTE_ b_InputChannel CR_CHAN       : Selection from digital   |
++|                     unsigned char_ b_InputChannel CR_CHAN       : Selection from digital   |
+ |                        data[0] which IOTYPE                           input ( 0 to 2)          |
+ +----------------------------------------------------------------------------+
+-| Output Parameters : PBYTE_  pb_ChannelStatus    : Digital input channel    |
++| Output Parameters : unsigned char *_  pb_ChannelStatus    : Digital input channel    |
+ |                                 data[0]                  status                   |
+ |                                                   0 : Channle is not active|
+ |                                                   1 : Channle is active    |
+@@ -740,14 +740,14 @@ INT i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device * dev, struct comedi_su
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusReg;
+-	BYTE b_ModulNbr;
+-	BYTE b_InputChannel;
+-	PBYTE pb_ChannelStatus;
+-	PBYTE pb_InputStatus;
+-	BYTE b_IOType;
++	unsigned char b_ModulNbr;
++	unsigned char b_InputChannel;
++	unsigned char * pb_ChannelStatus;
++	unsigned char * pb_InputStatus;
++	unsigned char b_IOType;
+ 	i_ReturnValue = insn->n;
+-	b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+-	b_IOType = (BYTE) data[0];
++	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
++	b_IOType = (unsigned char) data[0];
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -785,8 +785,8 @@ INT i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device * dev, struct comedi_su
+ 				/* Test the digital imnput channel number */
+ 				   /******************************************/
+ 
+-				b_InputChannel = (BYTE) CR_CHAN(insn->chanspec);
+-				pb_ChannelStatus = (PBYTE) & data[0];
++				b_InputChannel = (unsigned char) CR_CHAN(insn->chanspec);
++				pb_ChannelStatus = (unsigned char *) & data[0];
+ 
+ 				if (b_InputChannel <= 2) {
+ 					/**************************/
+@@ -797,7 +797,7 @@ INT i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device * dev, struct comedi_su
+ 						inl(devpriv->s_BoardInfos.
+ 						ui_Address + (64 * b_ModulNbr));
+ 					*pb_ChannelStatus =
+-						(BYTE) (((~dw_StatusReg) >> (4 +
++						(unsigned char) (((~dw_StatusReg) >> (4 +
+ 								b_InputChannel))
+ 						& 1);
+ 				} else {
+@@ -814,13 +814,13 @@ INT i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device * dev, struct comedi_su
+ 					/**************************/
+ 				/* Read all digital input */
+ 					/**************************/
+-				pb_InputStatus = (PBYTE) & data[0];
++				pb_InputStatus = (unsigned char *) & data[0];
+ 
+ 				dw_StatusReg =
+ 					inl(devpriv->s_BoardInfos.ui_Address +
+ 					(64 * b_ModulNbr));
+ 				*pb_InputStatus =
+-					(BYTE) (((~dw_StatusReg) >> 4) & 7);
++					(unsigned char) (((~dw_StatusReg) >> 4) & 7);
+ 				break;
+ 
+ 			default:
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+index 90316e10a3bd..c1b4f07beb17 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+@@ -63,11 +63,11 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_     i_APCI1710_InitTorCounter                    |
+-|                                       (BYTE_     b_BoardHandle,            |
+-|                                        BYTE_     b_ModulNbr,               |
+-|                                        BYTE_     b_TorCounter,             |
+-|                                        BYTE_     b_PCIInputClock,          |
+-|                                        BYTE_     b_TimingUnit,             |
++|                                       (unsigned char_     b_BoardHandle,            |
++|                                        unsigned char_     b_ModulNbr,               |
++|                                        unsigned char_     b_TorCounter,             |
++|                                        unsigned char_     b_PCIInputClock,          |
++|                                        unsigned char_     b_TimingUnit,             |
+ |                                        ULONG_   ul_TimingInterval,         |
+ |                                        PULONG_ pul_RealTimingInterval)     |
+ +----------------------------------------------------------------------------+
+@@ -82,11 +82,11 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :    |
+ |
+-		CR_AREF	BYTE_   b_ModulNbr       : Module number to configure  |
++		CR_AREF	unsigned char_   b_ModulNbr       : Module number to configure  |
+ |                                                (0 to 3)                    |
+-|           data[0] BYTE_   b_TorCounter     : Tor counter selection       |
++|           data[0] unsigned char_   b_TorCounter     : Tor counter selection       |
+ |                                                (0 or 1).                   |
+-|           data[1] BYTE_   b_PCIInputClock  : Selection from PCI bus clock|
++|           data[1] unsigned char_   b_PCIInputClock  : Selection from PCI bus clock|
+ |                                                - APCI1710_30MHZ :          |
+ |                                                  The PC have a PCI bus     |
+ |                                                  clock from 30 MHz         |
+@@ -104,7 +104,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ |						   than it is not possibl to |
+ |						   used the gate input for   |
+ |						   enabled the acquisition   |
+-|           data[2] BYTE_   b_TimingUnit    : Base timing unit (0 to 4)    |
++|           data[2] unsigned char_   b_TimingUnit    : Base timing unit (0 to 4)    |
+ |                                                 0 : ns                     |
+ |                                                 1 : µs                     |
+ |                                                 2 : ms                     |
+@@ -137,19 +137,19 @@ INT i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ 	ULONG ul_TimerValue = 0;
+ 	DWORD dw_Command;
+ 	double d_RealTimingInterval = 0;
+-	BYTE b_ModulNbr;
+-	BYTE b_TorCounter;
+-	BYTE b_PCIInputClock;
+-	BYTE b_TimingUnit;
++	unsigned char b_ModulNbr;
++	unsigned char b_TorCounter;
++	unsigned char b_PCIInputClock;
++	unsigned char b_TimingUnit;
+ 	ULONG ul_TimingInterval;
+ 	ULONG ul_RealTimingInterval = 0;
+ 
+ 	i_ReturnValue = insn->n;
+-	b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
++	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+ 
+-	b_TorCounter = (BYTE) data[0];
+-	b_PCIInputClock = (BYTE) data[1];
+-	b_TimingUnit = (BYTE) data[2];
++	b_TorCounter = (unsigned char) data[0];
++	b_PCIInputClock = (unsigned char) data[1];
++	b_TimingUnit = (unsigned char) data[2];
+ 	ul_TimingInterval = (ULONG) data[3];
+ 	printk("INPUT clock %d\n", b_PCIInputClock);
+ 
+@@ -864,13 +864,13 @@ INT i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_EnableTorCounter                      |
+-|                                               (BYTE_ b_BoardHandle,        |
+-|                                                BYTE_ b_ModulNbr,           |
+-|						 BYTE_ b_TorCounter,         |
+-|						 BYTE_ b_InputMode,          |
+-|						 BYTE_ b_ExternGate,         |
+-|                                                BYTE_ b_CycleMode,          |
+-|                                                BYTE_ b_InterruptEnable)    |
++|                                               (unsigned char_ b_BoardHandle,        |
++|                                                unsigned char_ b_ModulNbr,           |
++|						 unsigned char_ b_TorCounter,         |
++|						 unsigned char_ b_InputMode,          |
++|						 unsigned char_ b_ExternGate,         |
++|                                                unsigned char_ b_CycleMode,          |
++|                                                unsigned char_ b_InterruptEnable)    |
+ +----------------------------------------------------------------------------+
+ | Task              : Enable the tor counter (b_TorCounter) from selected    |
+ |		      module (b_ModulNbr). You must calling the              |
+@@ -883,13 +883,13 @@ INT i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ |                     The b_CycleMode parameter determine if you will        |
+ |                     measured a single or more cycle.                       |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle  : Handle of board APCI-1710       |
+-|                     BYTE_ b_ModulNbr     : Selected module number (0 to 3) |
+-|                     BYTE_ b_TorCounter   : Tor counter selection (0 or 1). |
+-|		      BYTE_ b_InputMode    : Input signal level selection    |
++| Input Parameters  : unsigned char_ b_BoardHandle  : Handle of board APCI-1710       |
++|                     unsigned char_ b_ModulNbr     : Selected module number (0 to 3) |
++|                     unsigned char_ b_TorCounter   : Tor counter selection (0 or 1). |
++|		      unsigned char_ b_InputMode    : Input signal level selection    |
+ |						0 : Tor count each low level |
+ |						1 : Tor count each high level|
+-|		      BYTE_ b_ExternGate   : Extern gate action selection    |
++|		      unsigned char_ b_ExternGate   : Extern gate action selection    |
+ |						0 : Extern gate signal not   |
+ |						    used                     |
+ |						1 : Extern gate signal used. |
+@@ -928,9 +928,9 @@ INT i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ |					      The gate input is used for the |
+ |					      signal B                       |
+ |									     |
+-|                     BYTE_ b_CycleMode    : Selected the tor counter        |
++|                     unsigned char_ b_CycleMode    : Selected the tor counter        |
+ |                                            acquisition mode                |
+-|                     BYTE_ b_InterruptEnable : Enable or disable the        |
++|                     unsigned char_ b_InterruptEnable : Enable or disable the        |
+ |                                               tor counter interrupt.       |
+ |                                               APCI1710_ENABLE:             |
+ |                                               Enable the tor counter       |
+@@ -959,9 +959,9 @@ INT i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_DisableTorCounter                     |
+-|                                               (BYTE_  b_BoardHandle,       |
+-|                                                BYTE_  b_ModulNbr,          |
+-|						 BYTE_  b_TorCounter)        |
++|                                               (unsigned char_  b_BoardHandle,       |
++|                                                unsigned char_  b_ModulNbr,          |
++|						 unsigned char_  b_TorCounter)        |
+ +----------------------------------------------------------------------------+
+ | Task              : Disable the tor counter (b_TorCounter) from selected   |
+ |		      module (b_ModulNbr). If you disable the tor counter    |
+@@ -969,9 +969,9 @@ INT i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ |		      counter witch the " i_APCI1710_EnableTorCounter"       |
+ |		      function, the status register is cleared               |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle  : Handle of board APCI-1710       |
+-|                     BYTE_ b_ModulNbr     : Selected module number (0 to 3) |
+-|                     BYTE_ b_TorCounter   : Tor counter selection (0 or 1). |
++| Input Parameters  : unsigned char_ b_BoardHandle  : Handle of board APCI-1710       |
++|                     unsigned char_ b_ModulNbr     : Selected module number (0 to 3) |
++|                     unsigned char_ b_TorCounter   : Tor counter selection (0 or 1). |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+ +----------------------------------------------------------------------------+
+@@ -994,20 +994,20 @@ INT i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+ 	DWORD dw_Status;
+ 	DWORD dw_DummyRead;
+ 	DWORD dw_ConfigReg;
+-	BYTE b_ModulNbr, b_Action;
+-	BYTE b_TorCounter;
+-	BYTE b_InputMode;
+-	BYTE b_ExternGate;
+-	BYTE b_CycleMode;
+-	BYTE b_InterruptEnable;
+-
+-	b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+-	b_Action = (BYTE) data[0];	// enable or disable
+-	b_TorCounter = (BYTE) data[1];
+-	b_InputMode = (BYTE) data[2];
+-	b_ExternGate = (BYTE) data[3];
+-	b_CycleMode = (BYTE) data[4];
+-	b_InterruptEnable = (BYTE) data[5];
++	unsigned char b_ModulNbr, b_Action;
++	unsigned char b_TorCounter;
++	unsigned char b_InputMode;
++	unsigned char b_ExternGate;
++	unsigned char b_CycleMode;
++	unsigned char b_InterruptEnable;
++
++	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
++	b_Action = (unsigned char) data[0];	// enable or disable
++	b_TorCounter = (unsigned char) data[1];
++	b_InputMode = (unsigned char) data[2];
++	b_ExternGate = (unsigned char) data[3];
++	b_CycleMode = (unsigned char) data[4];
++	b_InterruptEnable = (unsigned char) data[5];
+ 	i_ReturnValue = insn->n;;
+ 	devpriv->tsk_Current = current;	// Save the current process task structure
+ 	/**************************/
+@@ -1381,16 +1381,16 @@ INT i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_GetTorCounterInitialisation           |
+-|                                               (BYTE_     b_BoardHandle,    |
+-|                                                BYTE_     b_ModulNbr,       |
+-|						 BYTE_     b_TorCounter,     |
+-|                                        	 PBYTE_   pb_TimingUnit,     |
++|                                               (unsigned char_     b_BoardHandle,    |
++|                                                unsigned char_     b_ModulNbr,       |
++|						 unsigned char_     b_TorCounter,     |
++|                                        	 unsigned char *_   pb_TimingUnit,     |
+ |                                        	 PULONG_ pul_TimingInterval, |
+-|						 PBYTE_   pb_InputMode,      |
+-|						 PBYTE_   pb_ExternGate,     |
+-|                                                PBYTE_   pb_CycleMode,      |
+-|						 PBYTE_   pb_Enable,         |
+-|                                                PBYTE_   pb_InterruptEnable)|
++|						 unsigned char *_   pb_InputMode,      |
++|						 unsigned char *_   pb_ExternGate,     |
++|                                                unsigned char *_   pb_CycleMode,      |
++|						 unsigned char *_   pb_Enable,         |
++|                                                unsigned char *_   pb_InterruptEnable)|
+ +----------------------------------------------------------------------------+
+ | Task              : Enable the tor counter (b_TorCounter) from selected    |
+ |		      module (b_ModulNbr). You must calling the              |
+@@ -1403,37 +1403,37 @@ INT i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+ |                     The b_CycleMode parameter determine if you will        |
+ |                     measured a single or more cycle.                       |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle  : Handle of board APCI-1710       |
+-|                     BYTE_ b_ModulNbr     : Selected module number (0 to 3) |
+-|                     BYTE_ b_TorCounter   : Tor counter selection (0 or 1)
++| Input Parameters  : unsigned char_ b_BoardHandle  : Handle of board APCI-1710       |
++|                     unsigned char_ b_ModulNbr     : Selected module number (0 to 3) |
++|                     unsigned char_ b_TorCounter   : Tor counter selection (0 or 1)
+ 
+ 	b_ModulNbr			=	CR_AREF(insn->chanspec);
+ 	b_TorCounter		=	CR_CHAN(insn->chanspec);
+ . |
+ +----------------------------------------------------------------------------+
+-| Output Parameters : PBYTE_  pb_TimingUnit    : Base timing unit (0 to 4)   |
++| Output Parameters : unsigned char *_  pb_TimingUnit    : Base timing unit (0 to 4)   |
+ |                                                 0 : ns                     |
+ |                                                 1 : µs                     |
+ |                                                 2 : ms                     |
+ |                                                 3 : s                      |
+ |                                                 4 : mn                     |
+ |                     PULONG_ pul_TimingInterval : Base timing value.        |
+-|		      PBYTE_ pb_InputMode        : Input signal level        |
++|		      unsigned char *_ pb_InputMode        : Input signal level        |
+ |						   selection  		     |
+ |						0 : Tor count each low level |
+ |						1 : Tor count each high level|
+-|		      PBYTE_ pb_ExternGate	: Extern gate action         |
++|		      unsigned char *_ pb_ExternGate	: Extern gate action         |
+ |						  selection                  |
+ |						  0 : Extern gate signal not |
+ |						      used                   |
+ |						  1 : Extern gate signal used|
+-|                     PBYTE_ pb_CycleMode       : Tor counter acquisition    |
++|                     unsigned char *_ pb_CycleMode       : Tor counter acquisition    |
+ |						  mode           	     |
+-|		      PBYTE_ pb_Enable		: Indicate if the tor counter|
++|		      unsigned char *_ pb_Enable		: Indicate if the tor counter|
+ |						  is enabled or no           |
+ |						  0 : Tor counter disabled   |
+ |						  1 : Tor counter enabled    |
+-|                     PBYTE_ pb_InterruptEnable : Enable or disable the      |
++|                     unsigned char *_ pb_InterruptEnable : Enable or disable the      |
+ |                                                 tor counter interrupt.     |
+ |                                                 APCI1710_ENABLE:           |
+ |                                                 Enable the tor counter     |
+@@ -1441,13 +1441,13 @@ INT i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+ |                                                 APCI1710_DISABLE:          |
+ |                                                 Disable the tor counter    |
+ |                                                 interrupt
+-	pb_TimingUnit		=	(PBYTE) &data[0];
++	pb_TimingUnit		=	(unsigned char *) &data[0];
+ 	pul_TimingInterval	=  (PULONG) &data[1];
+-	pb_InputMode		=	(PBYTE) &data[2];
+-	pb_ExternGate		=	(PBYTE) &data[3];
+-	pb_CycleMode		=	(PBYTE) &data[4];
+-	pb_Enable			=	(PBYTE) &data[5];
+-	pb_InterruptEnable	=	(PBYTE) &data[6];
++	pb_InputMode		=	(unsigned char *) &data[2];
++	pb_ExternGate		=	(unsigned char *) &data[3];
++	pb_CycleMode		=	(unsigned char *) &data[4];
++	pb_Enable			=	(unsigned char *) &data[5];
++	pb_InterruptEnable	=	(unsigned char *) &data[6];
+                  |
+ +----------------------------------------------------------------------------+
+ | Return Value      :  0: No error                                           |
+@@ -1465,27 +1465,27 @@ INT i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_Status;
+-	BYTE b_ModulNbr;
+-	BYTE b_TorCounter;
+-	PBYTE pb_TimingUnit;
++	unsigned char b_ModulNbr;
++	unsigned char b_TorCounter;
++	unsigned char * pb_TimingUnit;
+ 	PULONG pul_TimingInterval;
+-	PBYTE pb_InputMode;
+-	PBYTE pb_ExternGate;
+-	PBYTE pb_CycleMode;
+-	PBYTE pb_Enable;
+-	PBYTE pb_InterruptEnable;
++	unsigned char * pb_InputMode;
++	unsigned char * pb_ExternGate;
++	unsigned char * pb_CycleMode;
++	unsigned char * pb_Enable;
++	unsigned char * pb_InterruptEnable;
+ 
+ 	i_ReturnValue = insn->n;
+ 	b_ModulNbr = CR_AREF(insn->chanspec);
+ 	b_TorCounter = CR_CHAN(insn->chanspec);
+ 
+-	pb_TimingUnit = (PBYTE) & data[0];
++	pb_TimingUnit = (unsigned char *) & data[0];
+ 	pul_TimingInterval = (PULONG) & data[1];
+-	pb_InputMode = (PBYTE) & data[2];
+-	pb_ExternGate = (PBYTE) & data[3];
+-	pb_CycleMode = (PBYTE) & data[4];
+-	pb_Enable = (PBYTE) & data[5];
+-	pb_InterruptEnable = (PBYTE) & data[6];
++	pb_InputMode = (unsigned char *) & data[2];
++	pb_ExternGate = (unsigned char *) & data[3];
++	pb_CycleMode = (unsigned char *) & data[4];
++	pb_Enable = (unsigned char *) & data[5];
++	pb_InterruptEnable = (unsigned char *) & data[6];
+ 
+ 	/**************************/
+ 	/* Test the module number */
+@@ -1526,9 +1526,9 @@ INT i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
+ 						(64 * b_ModulNbr));
+ 
+ 					*pb_CycleMode =
+-						(BYTE) ((dw_Status >> 4) & 1);
++						(unsigned char) ((dw_Status >> 4) & 1);
+ 					*pb_InterruptEnable =
+-						(BYTE) ((dw_Status >> 5) & 1);
++						(unsigned char) ((dw_Status >> 5) & 1);
+ 
+ 		    /******************************************************/
+ 					/* Test if extern gate used for clock or for signal B */
+@@ -1582,10 +1582,10 @@ INT i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
+ 					}	// if (dw_Status & 0x600)
+ 					else {
+ 						*pb_InputMode =
+-							(BYTE) ((dw_Status >> 6)
++							(unsigned char) ((dw_Status >> 6)
+ 							& 1);
+ 						*pb_ExternGate =
+-							(BYTE) ((dw_Status >> 7)
++							(unsigned char) ((dw_Status >> 7)
+ 							& 1);
+ 					}	// if (dw_Status & 0x600)
+ 
+@@ -1643,11 +1643,11 @@ INT i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_ReadTorCounterValue                   |
+-|                               (BYTE_     b_BoardHandle,                    |
+-|                                BYTE_     b_ModulNbr,                       |
+-|				 BYTE_     b_TorCounter,                     |
++|                               (unsigned char_     b_BoardHandle,                    |
++|                                unsigned char_     b_ModulNbr,                       |
++|				 unsigned char_     b_TorCounter,                     |
+ |                                UINT_    ui_TimeOut,                        |
+-|                                PBYTE_   pb_TorCounterStatus,               |
++|                                unsigned char *_   pb_TorCounterStatus,               |
+ |                                PULONG_ pul_TorCounterValue)                |
+ +----------------------------------------------------------------------------+
+ | Task        	case APCI1710_TOR_GETPROGRESSSTATUS: Return the tor counter
+@@ -1660,15 +1660,15 @@ INT i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
+ |		      (pul_TorCounterValue) after a conting cycle stop       |
+ |                     from selected tor counter module (b_ModulNbr).         |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle  : Handle of board APCI-1710       |
+-|                     BYTE_ b_ModulNbr     : Selected module number (0 to 3) |
+-|                     BYTE_ b_TorCounter   : Tor counter selection (0 or 1).
++| Input Parameters  : unsigned char_ b_BoardHandle  : Handle of board APCI-1710       |
++|                     unsigned char_ b_ModulNbr     : Selected module number (0 to 3) |
++|                     unsigned char_ b_TorCounter   : Tor counter selection (0 or 1).
+ 	b_ModulNbr    = CR_AREF(insn->chanspec);
+-	b_ReadType    = (BYTE) data[0];
+-	b_TorCounter  =	(BYTE) data[1];
++	b_ReadType    = (unsigned char) data[0];
++	b_TorCounter  =	(unsigned char) data[1];
+ 	ui_TimeOut	  = (UINT) data[2]; |
+ +----------------------------------------------------------------------------+
+-| Output Parameters : PBYTE_  pb_TorCounterStatus : Return the tor counter   |
++| Output Parameters : unsigned char *_  pb_TorCounterStatus : Return the tor counter   |
+ |                                                    status.                 |
+ |                                               0 : Conting cycle not started|
+ |                                                   Software gate not set.   |
+@@ -1684,7 +1684,7 @@ INT i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
+ |                                                 "i_APCI1710_InitTorCounter"|
+ |						4 : Timeeout occur           |
+ |                     PULONG  pul_TorCounterValue  : Tor counter value.
+-	pb_TorCounterStatus=(PBYTE) &data[0];
++	pb_TorCounterStatus=(unsigned char *) &data[0];
+ 	pul_TorCounterValue=(PULONG) &data[1];    |
+ +----------------------------------------------------------------------------+
+ | Return Value      :  0: No error                                           |
+@@ -1707,19 +1707,19 @@ INT i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device
+ 	DWORD dw_Status;
+ 	DWORD dw_TimeOut = 0;
+ 
+-	BYTE b_ModulNbr;
+-	BYTE b_TorCounter;
+-	BYTE b_ReadType;
++	unsigned char b_ModulNbr;
++	unsigned char b_TorCounter;
++	unsigned char b_ReadType;
+ 	UINT ui_TimeOut;
+-	PBYTE pb_TorCounterStatus;
++	unsigned char * pb_TorCounterStatus;
+ 	PULONG pul_TorCounterValue;
+ 
+ 	i_ReturnValue = insn->n;
+ 	b_ModulNbr = CR_AREF(insn->chanspec);
+-	b_ReadType = (BYTE) data[0];
+-	b_TorCounter = (BYTE) data[1];
++	b_ReadType = (unsigned char) data[0];
++	b_TorCounter = (unsigned char) data[1];
+ 	ui_TimeOut = (UINT) data[2];
+-	pb_TorCounterStatus = (PBYTE) & data[0];
++	pb_TorCounterStatus = (unsigned char *) & data[0];
+ 	pul_TorCounterValue = (PULONG) & data[1];
+ 
+ 	/**************************/
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+index 68b1d26bae13..eb1551d0eca3 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+@@ -63,12 +63,12 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_InitTTLIODirection                    |
+-|                               (BYTE_    b_BoardHandle,                     |
+-|				 BYTE_    b_ModulNbr,                        |
+-|				 BYTE_    b_PortAMode,                       |
+-|				 BYTE_    b_PortBMode,                       |
+-|				 BYTE_    b_PortCMode,                       |
+-|				 BYTE_    b_PortDMode)                       |
++|                               (unsigned char_    b_BoardHandle,                     |
++|				 unsigned char_    b_ModulNbr,                        |
++|				 unsigned char_    b_PortAMode,                       |
++|				 unsigned char_    b_PortBMode,                       |
++|				 unsigned char_    b_PortCMode,                       |
++|				 unsigned char_    b_PortDMode)                       |
+ +----------------------------------------------------------------------------+
+ | Task           APCI1710_TTL_INIT (using defaults)   : Configure the TTL I/O operating mode from selected     |
+ |                     module  (b_ModulNbr). You must calling this function be|
+@@ -76,15 +76,15 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ 				 APCI1710_TTL_INITDIRECTION(user inputs for direction)
+ 
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle         : Handle of board APCI-1710|
+-|                     BYTE_ b_ModulNbr            : Module number to         |
++| Input Parameters  : unsigned char_ b_BoardHandle         : Handle of board APCI-1710|
++|                     unsigned char_ b_ModulNbr            : Module number to         |
+ |                                                   configure (0 to 3)
+-		b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+-		b_InitType = (BYTE) data[0];
+-		b_PortAMode	= (BYTE) data[1];
+-		b_PortBMode = (BYTE) data[2];
+-		b_PortCMode = (BYTE) data[3];
+-		b_PortDMode	= (BYTE) data[4];|
++		b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
++		b_InitType = (unsigned char) data[0];
++		b_PortAMode	= (unsigned char) data[1];
++		b_PortBMode = (unsigned char) data[2];
++		b_PortCMode = (unsigned char) data[3];
++		b_PortDMode	= (unsigned char) data[4];|
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+ +----------------------------------------------------------------------------+
+@@ -104,15 +104,15 @@ INT i_APCI1710_InsnConfigInitTTLIO(struct comedi_device * dev, struct comedi_sub
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+-	BYTE b_ModulNbr;
+-	BYTE b_InitType;
+-	BYTE b_PortAMode;
+-	BYTE b_PortBMode;
+-	BYTE b_PortCMode;
+-	BYTE b_PortDMode;
+-
+-	b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+-	b_InitType = (BYTE) data[0];
++	unsigned char b_ModulNbr;
++	unsigned char b_InitType;
++	unsigned char b_PortAMode;
++	unsigned char b_PortBMode;
++	unsigned char b_PortCMode;
++	unsigned char b_PortDMode;
++
++	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
++	b_InitType = (unsigned char) data[0];
+ 	i_ReturnValue = insn->n;
+ 
+ 	/**************************/
+@@ -172,10 +172,10 @@ INT i_APCI1710_InsnConfigInitTTLIO(struct comedi_device * dev, struct comedi_sub
+ 
+ 			case APCI1710_TTL_INITDIRECTION:
+ 
+-				b_PortAMode = (BYTE) data[1];
+-				b_PortBMode = (BYTE) data[2];
+-				b_PortCMode = (BYTE) data[3];
+-				b_PortDMode = (BYTE) data[4];
++				b_PortAMode = (unsigned char) data[1];
++				b_PortBMode = (unsigned char) data[2];
++				b_PortCMode = (unsigned char) data[3];
++				b_PortDMode = (unsigned char) data[4];
+ 
+ 	      /********************/
+ 				/* Test the version */
+@@ -352,11 +352,11 @@ INT i_APCI1710_InsnConfigInitTTLIO(struct comedi_device * dev, struct comedi_sub
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_   i_APCI1710_ReadTTLIOChannelValue               |
+-|                                       (BYTE_     b_BoardHandle,            |
+-|                                        BYTE_     b_ModulNbr,               |
+-|                                        BYTE_     b_SelectedPort,           |
+-|                                        BYTE_     b_InputChannel,           |
+-|                                        PBYTE_   pb_ChannelStatus)          |
++|                                       (unsigned char_     b_BoardHandle,            |
++|                                        unsigned char_     b_ModulNbr,               |
++|                                        unsigned char_     b_SelectedPort,           |
++|                                        unsigned char_     b_InputChannel,           |
++|                                        unsigned char *_   pb_ChannelStatus)          |
+ +----------------------------------------------------------------------------+
+ | Task              : Read the status from selected TTL digital input        |
+ |                     (b_InputChannel)
+@@ -366,32 +366,32 @@ INT i_APCI1710_InsnConfigInitTTLIO(struct comedi_device * dev, struct comedi_sub
+ +----------------------------------------------------------------------------+
+ 
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle         : Handle of board APCI-1710|
+-|                     BYTE_ b_ModulNbr            : Module number to         |
++| Input Parameters  : unsigned char_ b_BoardHandle         : Handle of board APCI-1710|
++|                     unsigned char_ b_ModulNbr            : Module number to         |
+ |                                                   configure (0 to 7)       |
+-|                     BYTE_ b_SelectedPort,       : Selection from TTL I/O   |
++|                     unsigned char_ b_SelectedPort,       : Selection from TTL I/O   |
+ |                                                   port (0 to 2)            |
+ |                                                      0 : Port A selection  |
+ |                                                      1 : Port B selection  |
+ |                                                      2 : Port C selection  |
+ |                                                      3 : Port D selection  |
+-|                     BYTE_ b_InputChannel        : Selection from digital   |
++|                     unsigned char_ b_InputChannel        : Selection from digital   |
+ |                                                   input ( 0 to 2)
+ APCI1710_TTL_READCHANNEL
+ 	b_ModulNbr	  = CR_AREF(insn->chanspec);
+ 	b_SelectedPort= CR_RANGE(insn->chanspec);
+ 	b_InputChannel= CR_CHAN(insn->chanspec);
+-	b_ReadType	  = (BYTE) data[0];
++	b_ReadType	  = (unsigned char) data[0];
+ 
+  APCI1710_TTL_READPORT|
+ 	b_ModulNbr	  = CR_AREF(insn->chanspec);
+ 	b_SelectedPort= CR_RANGE(insn->chanspec);
+-	b_ReadType	  = (BYTE) data[0];
++	b_ReadType	  = (unsigned char) data[0];
+ 
+ +----------------------------------------------------------------------------+
+ | Output Parameters : data[0]
+ 
+-	PBYTE_  pb_ChannelStatus    : Digital input channel    |
++	unsigned char *_  pb_ChannelStatus    : Digital input channel    |
+ |                                                   status                   |
+ |                                                   0 : Channle is not active|
+ |                                                   1 : Channle is active    |
+@@ -411,15 +411,15 @@ INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device * dev, struct comedi_subde
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusReg;
+-	BYTE b_ModulNbr;
+-	BYTE b_SelectedPort;
+-	BYTE b_InputChannel;
+-	BYTE b_ReadType;
+-	PBYTE pb_ChannelStatus;
+-	PBYTE pb_PortValue;
++	unsigned char b_ModulNbr;
++	unsigned char b_SelectedPort;
++	unsigned char b_InputChannel;
++	unsigned char b_ReadType;
++	unsigned char * pb_ChannelStatus;
++	unsigned char * pb_PortValue;
+ 
+ 	i_ReturnValue = insn->n;
+-	b_ReadType = (BYTE) data[0];
++	b_ReadType = (unsigned char) data[0];
+ 	b_ModulNbr = CR_AREF(insn->chanspec);
+ 	b_SelectedPort = CR_RANGE(insn->chanspec);
+ 	b_InputChannel = CR_CHAN(insn->chanspec);
+@@ -439,7 +439,7 @@ INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device * dev, struct comedi_subde
+ 			switch (b_ReadType) {
+ 
+ 			case APCI1710_TTL_READCHANNEL:
+-				pb_ChannelStatus = (PBYTE) & data[0];
++				pb_ChannelStatus = (unsigned char *) & data[0];
+ 	      /********************************/
+ 				/* Test the TTL I/O port number */
+ 	      /********************************/
+@@ -493,7 +493,7 @@ INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device * dev, struct comedi_subde
+ 
+ 								*pb_ChannelStatus
+ 									=
+-									(BYTE) (
++									(unsigned char) (
+ 									(dw_StatusReg
+ 										>>
+ 										(8 * b_SelectedPort)) >> b_InputChannel) & 1;
+@@ -533,7 +533,7 @@ INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device * dev, struct comedi_subde
+ 				break;
+ 
+ 			case APCI1710_TTL_READPORT:
+-				pb_PortValue = (PBYTE) & data[0];
++				pb_PortValue = (unsigned char *) & data[0];
+ 			  /********************************/
+ 				/* Test the TTL I/O port number */
+ 			  /********************************/
+@@ -578,7 +578,7 @@ INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device * dev, struct comedi_subde
+ 								(64 * b_ModulNbr));
+ 
+ 							*pb_PortValue =
+-								(BYTE) (
++								(unsigned char) (
+ 								(dw_StatusReg >>
+ 									(8 * b_SelectedPort)) & 0xFF);
+ 						} else {
+@@ -640,8 +640,8 @@ INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device * dev, struct comedi_subde
+ |                     (port A, port B and port C) from selected TTL          |
+ |		      module (b_ModulNbr) 				     |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle         : Handle of board APCI-1710|
+-|                     BYTE_ b_ModulNbr            : Module number to         |
++| Input Parameters  : unsigned char_ b_BoardHandle         : Handle of board APCI-1710|
++|                     unsigned char_ b_ModulNbr            : Module number to         |
+ |                                                   configure (0 to 3)       |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : PULONG_  pul_PortValue      : Digital TTL inputs port  |
+@@ -660,10 +660,10 @@ INT i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusReg;
+-	BYTE b_ModulNbr;
++	unsigned char b_ModulNbr;
+ 	PULONG pul_PortValue;
+ 
+-	b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
++	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
+ 	i_ReturnValue = insn->n;
+ 	pul_PortValue = (PULONG) & data[0];
+ 
+@@ -789,9 +789,9 @@ INT i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : _INT_ i_APCI1710_SetTTLIOChlOn                         |
+-|                               (BYTE_           b_BoardHandle,              |
+-|                                BYTE_           b_ModulNbr,                 |
+-|                                BYTE_           b_OutputChannel)
++|                               (unsigned char_           b_BoardHandle,              |
++|                                unsigned char_           b_ModulNbr,                 |
++|                                unsigned char_           b_OutputChannel)
+ INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,struct comedi_subdevice *s,
+ 	struct comedi_insn *insn,unsigned int *data)           |
+ +----------------------------------------------------------------------------+
+@@ -799,9 +799,9 @@ INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,struct comedi
+ |                     parameter b_Channel. Setting an output means setting   |
+ |                     an ouput high.                                         |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE_ b_BoardHandle   : Handle of board APCI-1710      |
+-|                     BYTE_ b_ModulNbr      : Selected module number (0 to 3)|
+-|                     BYTE_ b_OutputChannel : Selection from digital output  |
++| Input Parameters  : unsigned char_ b_BoardHandle   : Handle of board APCI-1710      |
++|                     unsigned char_ b_ModulNbr      : Selected module number (0 to 3)|
++|                     unsigned char_ b_OutputChannel : Selection from digital output  |
+ |                                             channel (0 or 1)               |
+ |                                                0      : PD0                |
+ |                                                1      : PD1                |
+@@ -830,8 +830,8 @@ INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device * dev,
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusReg = 0;
+-	BYTE b_ModulNbr;
+-	BYTE b_OutputChannel;
++	unsigned char b_ModulNbr;
++	unsigned char b_OutputChannel;
+ 	UINT ui_State;
+ 
+ 	i_ReturnValue = insn->n;
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
+index b0907ec14667..007ae8c05d3c 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
+@@ -74,11 +74,11 @@ INT i_AddiHeaderRW_ReadEeprom(INT i_NbOfWordsToRead,
+ 	INT i_Counter = 0;
+ 	INT i_WordCounter;
+ 	INT i;
+-	BYTE pb_ReadByte[1];
+-	BYTE b_ReadLowByte = 0;
+-	BYTE b_ReadHighByte = 0;
+-	BYTE b_SelectedAddressLow = 0;
+-	BYTE b_SelectedAddressHigh = 0;
++	unsigned char pb_ReadByte[1];
++	unsigned char b_ReadLowByte = 0;
++	unsigned char b_ReadHighByte = 0;
++	unsigned char b_SelectedAddressLow = 0;
++	unsigned char b_SelectedAddressHigh = 0;
+ 	WORD w_ReadWord = 0;
+ 
+ 	for (i_WordCounter = 0; i_WordCounter < i_NbOfWordsToRead;
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+index 19df5c1444a4..afe41263c749 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+@@ -37,7 +37,6 @@
+ #define SUCCESS	1
+ 
+ /* variable type definition */
+-typedef unsigned char BYTE, *PBYTE;
+ typedef short SHORT, *PSHORT;
+ typedef unsigned short USHORT, *PUSHORT;
+ typedef unsigned short WORD, *PWORD;
+@@ -50,8 +49,8 @@ typedef unsigned long ULONG_PTR;
+ 
+ typedef const struct comedi_lrange *PCRANGE;
+ 
+-#define LOBYTE(W)	(BYTE)((W) & 0xFF)
+-#define HIBYTE(W)	(BYTE)(((W) >> 8) & 0xFF)
++#define LOBYTE(W)	(unsigned char)((W) & 0xFF)
++#define HIBYTE(W)	(unsigned char)(((W) >> 8) & 0xFF)
+ #define MAKEWORD(H, L)	(USHORT)((L) | ((H) << 8))
+ #define LOWORD(W)	(USHORT)((W) & 0xFFFF)
+ #define HIWORD(W)	(USHORT)(((W) >> 16) & 0xFFFF)
+@@ -103,7 +102,7 @@ typedef struct {
+ 
+ 	INT i_Dma;		// dma present or not
+ 	INT i_Timer;		//   timer subdevice present or not
+-	BYTE b_AvailableConvertUnit;
++	unsigned char b_AvailableConvertUnit;
+ 	UINT ui_MinAcquisitiontimeNs;	// Minimum Acquisition in Nano secs
+ 	UINT ui_MinDelaytimeNs;	// Minimum Delay in Nano secs
+ 
+@@ -222,10 +221,10 @@ typedef union {
+ 	struct {
+ 		union {
+ 			struct {
+-				BYTE b_ModeRegister1;
+-				BYTE b_ModeRegister2;
+-				BYTE b_ModeRegister3;
+-				BYTE b_ModeRegister4;
++				unsigned char b_ModeRegister1;
++				unsigned char b_ModeRegister2;
++				unsigned char b_ModeRegister3;
++				unsigned char b_ModeRegister4;
+ 			} s_ByteModeRegister;
+ 			DWORD dw_ModeRegister1_2_3_4;
+ 		} s_ModeRegister;
+@@ -244,24 +243,24 @@ typedef union {
+ 
+ 	/* SSI infos */
+ 	struct {
+-		BYTE b_SSIProfile;
+-		BYTE b_PositionTurnLength;
+-		BYTE b_TurnCptLength;
+-		BYTE b_SSIInit;
++		unsigned char b_SSIProfile;
++		unsigned char b_PositionTurnLength;
++		unsigned char b_TurnCptLength;
++		unsigned char b_SSIInit;
+ 	} s_SSICounterInfo;
+ 
+ 	/* TTL I/O infos */
+ 	struct {
+-		BYTE b_TTLInit;
+-		BYTE b_PortConfiguration[4];
++		unsigned char b_TTLInit;
++		unsigned char b_PortConfiguration[4];
+ 	} s_TTLIOInfo;
+ 
+ 	/* Digital I/O infos */
+ 	struct {
+-		BYTE b_DigitalInit;
+-		BYTE b_ChannelAMode;
+-		BYTE b_ChannelBMode;
+-		BYTE b_OutputMemoryEnabled;
++		unsigned char b_DigitalInit;
++		unsigned char b_ChannelAMode;
++		unsigned char b_ChannelBMode;
++		unsigned char b_OutputMemoryEnabled;
+ 		DWORD dw_OutputMemory;
+ 	} s_DigitalIOInfo;
+ 
+@@ -271,14 +270,14 @@ typedef union {
+ 
+ 	struct {
+ 		struct {
+-			BYTE b_82X54Init;
+-			BYTE b_InputClockSelection;
+-			BYTE b_InputClockLevel;
+-			BYTE b_OutputLevel;
+-			BYTE b_HardwareGateLevel;
++			unsigned char b_82X54Init;
++			unsigned char b_InputClockSelection;
++			unsigned char b_InputClockLevel;
++			unsigned char b_OutputLevel;
++			unsigned char b_HardwareGateLevel;
+ 			DWORD dw_ConfigurationWord;
+ 		} s_82X54TimerInfo[3];
+-		BYTE b_InterruptMask;
++		unsigned char b_InterruptMask;
+ 	} s_82X54ModuleInfo;
+ 
+       /*********************/
+@@ -286,11 +285,11 @@ typedef union {
+       /*********************/
+ 
+ 	struct {
+-		BYTE b_ChronoInit;
+-		BYTE b_InterruptMask;
+-		BYTE b_PCIInputClock;
+-		BYTE b_TimingUnit;
+-		BYTE b_CycleMode;
++		unsigned char b_ChronoInit;
++		unsigned char b_InterruptMask;
++		unsigned char b_PCIInputClock;
++		unsigned char b_TimingUnit;
++		unsigned char b_CycleMode;
+ 		double d_TimingInterval;
+ 		DWORD dw_ConfigReg;
+ 	} s_ChronoModuleInfo;
+@@ -301,7 +300,7 @@ typedef union {
+ 
+ 	struct {
+ 		struct {
+-			BYTE b_PulseEncoderInit;
++			unsigned char b_PulseEncoderInit;
+ 		} s_PulseEncoderInfo[4];
+ 		DWORD dw_SetRegister;
+ 		DWORD dw_ControlRegister;
+@@ -311,49 +310,49 @@ typedef union {
+ 	/* Tor conter infos */
+ 	struct {
+ 		struct {
+-			BYTE b_TorCounterInit;
+-			BYTE b_TimingUnit;
+-			BYTE b_InterruptEnable;
++			unsigned char b_TorCounterInit;
++			unsigned char b_TimingUnit;
++			unsigned char b_InterruptEnable;
+ 			double d_TimingInterval;
+ 			ULONG ul_RealTimingInterval;
+ 		} s_TorCounterInfo[2];
+-		BYTE b_PCIInputClock;
++		unsigned char b_PCIInputClock;
+ 	} s_TorCounterModuleInfo;
+ 
+ 	/* PWM infos */
+ 	struct {
+ 		struct {
+-			BYTE b_PWMInit;
+-			BYTE b_TimingUnit;
+-			BYTE b_InterruptEnable;
++			unsigned char b_PWMInit;
++			unsigned char b_TimingUnit;
++			unsigned char b_InterruptEnable;
+ 			double d_LowTiming;
+ 			double d_HighTiming;
+ 			ULONG ul_RealLowTiming;
+ 			ULONG ul_RealHighTiming;
+ 		} s_PWMInfo[2];
+-		BYTE b_ClockSelection;
++		unsigned char b_ClockSelection;
+ 	} s_PWMModuleInfo;
+ 
+ 	/* ETM infos */
+ 	struct {
+ 		struct {
+-			BYTE b_ETMEnable;
+-			BYTE b_ETMInterrupt;
++			unsigned char b_ETMEnable;
++			unsigned char b_ETMInterrupt;
+ 		} s_ETMInfo[2];
+-		BYTE b_ETMInit;
+-		BYTE b_TimingUnit;
+-		BYTE b_ClockSelection;
++		unsigned char b_ETMInit;
++		unsigned char b_TimingUnit;
++		unsigned char b_ClockSelection;
+ 		double d_TimingInterval;
+ 		ULONG ul_Timing;
+ 	} s_ETMModuleInfo;
+ 
+ 	/* CDA infos */
+ 	struct {
+-		BYTE b_CDAEnable;
+-		BYTE b_CDAInterrupt;
+-		BYTE b_CDAInit;
+-		BYTE b_FctSelection;
+-		BYTE b_CDAReadFIFOOverflow;
++		unsigned char b_CDAEnable;
++		unsigned char b_CDAInterrupt;
++		unsigned char b_CDAInit;
++		unsigned char b_FctSelection;
++		unsigned char b_CDAReadFIFOOverflow;
+ 	} s_CDAModuleInfo;
+ 
+ } str_ModuleInfo;
+@@ -367,10 +366,10 @@ typedef struct {
+ 	INT i_IobaseReserved;
+ 	ULONG_PTR dw_AiBase;
+ 	struct pcilst_struct *amcc;	// ptr too AMCC data
+-	BYTE allocated;		// we have blocked card
+-	BYTE b_ValidDriver;	// driver is ok
+-	BYTE b_AiContinuous;	// we do unlimited AI
+-	BYTE b_AiInitialisation;
++	unsigned char allocated;		// we have blocked card
++	unsigned char b_ValidDriver;	// driver is ok
++	unsigned char b_AiContinuous;	// we do unlimited AI
++	unsigned char b_AiInitialisation;
+ 	UINT ui_AiActualScan;	//how many scans we finished
+ 	UINT ui_AiBufferPtr;	// data buffer ptr in samples
+ 	UINT ui_AiNbrofChannels;	// how many channels is measured
+@@ -378,7 +377,7 @@ typedef struct {
+ 	UINT ui_AiActualScanPosition;	// position in actual scan
+ 	PUINT pui_AiChannelList;	// actual chanlist
+ 	UINT ui_AiChannelList[32];	// actual chanlist
+-	BYTE b_AiChannelConfiguration[32];	// actual chanlist
++	unsigned char b_AiChannelConfiguration[32];	// actual chanlist
+ 	UINT ui_AiReadData[32];
+ 	DWORD dw_AiInitialised;
+ 	UINT ui_AiTimer0;	//Timer Constant for Timer0
+@@ -388,7 +387,7 @@ typedef struct {
+ 	short *AiData;	// Pointer to sample data
+ 	UINT ui_AiNbrofScans;	// number of scans to do
+ 	USHORT us_UseDma;	// To use Dma or not
+-	BYTE b_DmaDoubleBuffer;	// we can use double buffering
++	unsigned char b_DmaDoubleBuffer;	// we can use double buffering
+ 	UINT ui_DmaActualBuffer;	// which buffer is used now
+ 	//*UPDATE-0.7.57->0.7.68
+ 	//ULONG               ul_DmaBufferVirtual[2];// pointers to begin of DMA buffer
+@@ -398,25 +397,25 @@ typedef struct {
+ 	UINT ui_DmaBufferUsesize[2];	// which size we may now used for transfer
+ 	UINT ui_DmaBufferSamples[2];	// size in samples
+ 	UINT ui_DmaBufferPages[2];	// number of pages in buffer
+-	BYTE b_DigitalOutputRegister;	// Digital Output Register
+-	BYTE b_OutputMemoryStatus;
+-	BYTE b_AnalogInputChannelNbr;	// Analog input channel Nbr
+-	BYTE b_AnalogOutputChannelNbr;	// Analog input Output  Nbr
+-	BYTE b_TimerSelectMode;	// Contain data written at iobase + 0C
+-	BYTE b_ModeSelectRegister;	// Contain data written at iobase + 0E
++	unsigned char b_DigitalOutputRegister;	// Digital Output Register
++	unsigned char b_OutputMemoryStatus;
++	unsigned char b_AnalogInputChannelNbr;	// Analog input channel Nbr
++	unsigned char b_AnalogOutputChannelNbr;	// Analog input Output  Nbr
++	unsigned char b_TimerSelectMode;	// Contain data written at iobase + 0C
++	unsigned char b_ModeSelectRegister;	// Contain data written at iobase + 0E
+ 	USHORT us_OutputRegister;	// Contain data written at iobase + 0
+-	BYTE b_InterruptState;
+-	BYTE b_TimerInit;	// Specify if InitTimerWatchdog was load
+-	BYTE b_TimerStarted;	// Specify if timer 2 is running or not
+-	BYTE b_Timer2Mode;	// Specify the timer 2 mode
+-	BYTE b_Timer2Interrupt;	//Timer2  interrupt enable or disable
+-	BYTE b_AiCyclicAcquisition;	// indicate cyclic acquisition
+-	BYTE b_InterruptMode;	// eoc eos or dma
+-	BYTE b_EocEosInterrupt;	// Enable disable eoc eos interrupt
++	unsigned char b_InterruptState;
++	unsigned char b_TimerInit;	// Specify if InitTimerWatchdog was load
++	unsigned char b_TimerStarted;	// Specify if timer 2 is running or not
++	unsigned char b_Timer2Mode;	// Specify the timer 2 mode
++	unsigned char b_Timer2Interrupt;	//Timer2  interrupt enable or disable
++	unsigned char b_AiCyclicAcquisition;	// indicate cyclic acquisition
++	unsigned char b_InterruptMode;	// eoc eos or dma
++	unsigned char b_EocEosInterrupt;	// Enable disable eoc eos interrupt
+ 	UINT ui_EocEosConversionTime;
+-	BYTE b_EocEosConversionTimeBase;
+-	BYTE b_SingelDiff;
+-	BYTE b_ExttrigEnable;	/* To enable or disable external trigger */
++	unsigned char b_EocEosConversionTimeBase;
++	unsigned char b_SingelDiff;
++	unsigned char b_ExttrigEnable;	/* To enable or disable external trigger */
+ 
+ 	/* Pointer to the current process */
+ 	struct task_struct *tsk_Current;
+@@ -426,9 +425,9 @@ typedef struct {
+ 	struct {
+ 		UINT ui_Address;	/* Board address */
+ 		UINT ui_FlashAddress;
+-		BYTE b_InterruptNbr;	/* Board interrupt number */
+-		BYTE b_SlotNumber;	/* PCI slot number */
+-		BYTE b_BoardVersion;
++		unsigned char b_InterruptNbr;	/* Board interrupt number */
++		unsigned char b_SlotNumber;	/* PCI slot number */
++		unsigned char b_BoardVersion;
+ 		DWORD dw_MolduleConfiguration[4];	/* Module config */
+ 	} s_BoardInfos;
+ 
+@@ -439,7 +438,7 @@ typedef struct {
+ 		UINT ui_Read;	/* Read FIFO */
+ 		UINT ui_Write;	/* Write FIFO */
+ 		struct {
+-			BYTE b_OldModuleMask;
++			unsigned char b_OldModuleMask;
+ 			ULONG ul_OldInterruptMask;	/* Interrupt mask */
+ 			ULONG ul_OldCounterLatchValue;	/* Interrupt counter value */
+ 		} s_FIFOInterruptParameters[APCI1710_SAVE_INTERRUPT];
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+index a8a1bb2e8fa5..5cab63836e4c 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+@@ -68,19 +68,19 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ #define EEPROM_TIMER_WATCHDOG_COUNTER	10
+ 
+ struct str_Functionality {
+-	BYTE b_Type;
++	unsigned char b_Type;
+ 	WORD w_Address;
+ };
+ 
+ typedef struct {
+ 	WORD w_HeaderSize;
+-	BYTE b_Nfunctions;
++	unsigned char b_Nfunctions;
+ 	struct str_Functionality s_Functions[7];
+ } str_MainHeader;
+ 
+ typedef struct {
+ 	WORD w_Nchannel;
+-	BYTE b_Interruptible;
++	unsigned char b_Interruptible;
+ 	WORD w_NinterruptLogic;
+ } str_DigitalInputHeader;
+ 
+@@ -92,10 +92,10 @@ typedef struct {
+ 
+ typedef struct {
+ 	WORD w_HeaderSize;
+-	BYTE b_Resolution;
+-	BYTE b_Mode;		// in case of Watchdog it is functionality
++	unsigned char b_Resolution;
++	unsigned char b_Mode;		// in case of Watchdog it is functionality
+ 	WORD w_MinTiming;
+-	BYTE b_TimeBase;
++	unsigned char b_TimeBase;
+ } str_TimerDetails;
+ typedef struct {
+ 
+@@ -105,15 +105,15 @@ typedef struct {
+ 
+ typedef struct {
+ 	WORD w_Nchannel;
+-	BYTE b_Resolution;
++	unsigned char b_Resolution;
+ } str_AnalogOutputHeader;
+ 
+ typedef struct {
+ 	WORD w_Nchannel;
+ 	WORD w_MinConvertTiming;
+ 	WORD w_MinDelayTiming;
+-	BYTE b_HasDma;
+-	BYTE b_Resolution;
++	unsigned char b_HasDma;
++	unsigned char b_Resolution;
+ } str_AnalogInputHeader;
+ 
+ 		/*****************************************/
+@@ -152,7 +152,7 @@ void v_EepromWaitBusy(WORD w_PCIBoardEepromAddress);
+ void v_EepromClock76(DWORD dw_Address, DWORD dw_RegisterValue);
+ void v_EepromWaitBusy(WORD w_PCIBoardEepromAddress);
+ void v_EepromSendCommand76(DWORD dw_Address, DWORD dw_EepromCommand,
+-	BYTE b_DataLengthInBits);
++	unsigned char b_DataLengthInBits);
+ void v_EepromCs76Read(DWORD dw_Address, WORD w_offset, PWORD pw_Value);
+ 
+ /*
+@@ -180,17 +180,17 @@ WORD w_EepromReadWord(WORD w_PCIBoardEepromAddress, char *pc_PCIChipInformation,
+ 	WORD w_EepromStartAddress)
+ {
+ 
+-	BYTE b_Counter = 0;
++	unsigned char b_Counter = 0;
+ 
+-	BYTE b_ReadByte = 0;
++	unsigned char b_ReadByte = 0;
+ 
+-	BYTE b_ReadLowByte = 0;
++	unsigned char b_ReadLowByte = 0;
+ 
+-	BYTE b_ReadHighByte = 0;
++	unsigned char b_ReadHighByte = 0;
+ 
+-	BYTE b_SelectedAddressLow = 0;
++	unsigned char b_SelectedAddressLow = 0;
+ 
+-	BYTE b_SelectedAddressHigh = 0;
++	unsigned char b_SelectedAddressHigh = 0;
+ 
+ 	WORD w_ReadWord = 0;
+ 
+@@ -384,7 +384,7 @@ WORD w_EepromReadWord(WORD w_PCIBoardEepromAddress, char *pc_PCIChipInformation,
+ void v_EepromWaitBusy(WORD w_PCIBoardEepromAddress)
+ {
+ 
+-	BYTE b_EepromBusy = 0;
++	unsigned char b_EepromBusy = 0;
+ 
+ 	do
+ 	{
+@@ -492,7 +492,7 @@ void v_EepromClock76(DWORD dw_Address, DWORD dw_RegisterValue)
+ 
+ |					   DWORD   dw_EepromCommand,                		  |
+ 
+-|					   BYTE    b_DataLengthInBits)                        |
++|					   unsigned char    b_DataLengthInBits)                        |
+ 
+ +---------------------------------------------------------------------------------+
+ 
+@@ -504,7 +504,7 @@ void v_EepromClock76(DWORD dw_Address, DWORD dw_RegisterValue)
+ 
+ |		      DWORD dw_EepromCommand : PCI eeprom command to write.       |
+ 
+-|		      BYTE  b_DataLengthInBits : PCI eeprom command data length.  |
++|		      unsigned char  b_DataLengthInBits : PCI eeprom command data length.  |
+ 
+ +---------------------------------------------------------------------------------+
+ 
+@@ -519,7 +519,7 @@ void v_EepromClock76(DWORD dw_Address, DWORD dw_RegisterValue)
+ */
+ 
+ void v_EepromSendCommand76(DWORD dw_Address, DWORD dw_EepromCommand,
+-	BYTE b_DataLengthInBits)
++	unsigned char b_DataLengthInBits)
+ {
+ 
+ 	char c_BitPos = 0;
+@@ -824,14 +824,14 @@ INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress,
+ 	// Read nbr of functionality
+ 	w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+ 		pc_PCIChipInformation, 0x100 + 10);
+-	s_MainHeader.b_Nfunctions = (BYTE) w_Temp & 0x00FF;
++	s_MainHeader.b_Nfunctions = (unsigned char) w_Temp & 0x00FF;
+ 
+ 	// Read functionality details
+ 	for (i = 0; i < s_MainHeader.b_Nfunctions; i++) {
+ 		// Read Type
+ 		w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+ 			pc_PCIChipInformation, 0x100 + 12 + w_Count);
+-		s_MainHeader.s_Functions[i].b_Type = (BYTE) w_Temp & 0x3F;
++		s_MainHeader.s_Functions[i].b_Type = (unsigned char) w_Temp & 0x3F;
+ 		w_Count = w_Count + 2;
+ 		//Read Address
+ 		s_MainHeader.s_Functions[i].w_Address =
+@@ -953,7 +953,7 @@ INT i_EepromReadDigitalInputHeader(WORD w_PCIBoardEepromAddress,
+ 	// interruptible or not
+ 	w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+ 		pc_PCIChipInformation, 0x100 + w_Address + 8);
+-	s_Header->b_Interruptible = (BYTE) (w_Temp >> 7) & 0x01;
++	s_Header->b_Interruptible = (unsigned char) (w_Temp >> 7) & 0x01;
+ 
+ // How many interruptible logic
+ 	s_Header->w_NinterruptLogic =
+@@ -1039,11 +1039,11 @@ INT i_EepromReadTimerHeader(WORD w_PCIBoardEepromAddress,
+ 
+ 		//Read Resolution
+ 		s_Header->s_TimerDetails[i].b_Resolution =
+-			(BYTE) (w_Temp >> 10) & 0x3F;
++			(unsigned char) (w_Temp >> 10) & 0x3F;
+ 
+ 		//Read Mode
+ 		s_Header->s_TimerDetails[i].b_Mode =
+-			(BYTE) (w_Temp >> 4) & 0x3F;
++			(unsigned char) (w_Temp >> 4) & 0x3F;
+ 
+ 		w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+ 			pc_PCIChipInformation,
+@@ -1053,7 +1053,7 @@ INT i_EepromReadTimerHeader(WORD w_PCIBoardEepromAddress,
+ 		s_Header->s_TimerDetails[i].w_MinTiming = (w_Temp >> 6) & 0x3FF;
+ 
+ 		//Read Timebase
+-		s_Header->s_TimerDetails[i].b_TimeBase = (BYTE) (w_Temp) & 0x3F;
++		s_Header->s_TimerDetails[i].b_TimeBase = (unsigned char) (w_Temp) & 0x3F;
+ 		w_Size += s_Header->s_TimerDetails[i].w_HeaderSize;
+ 	}
+ 
+@@ -1093,7 +1093,7 @@ INT i_EepromReadAnlogOutputHeader(WORD w_PCIBoardEepromAddress,
+ 	// Resolution for 1st hard component
+ 	w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+ 		pc_PCIChipInformation, 0x100 + w_Address + 16);
+-	s_Header->b_Resolution = (BYTE) (w_Temp >> 8) & 0xFF;
++	s_Header->b_Resolution = (unsigned char) (w_Temp >> 8) & 0xFF;
+ 	return 0;
+ }
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+index 3f8929c09070..f2578bbe3a3b 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+@@ -234,11 +234,11 @@ int i_APCI1710_Reset(struct comedi_device * dev)
+ /*
+ +----------------------------------------------------------------------------+
+ | Function's Name   : __void__ v_APCI1710_InterruptFunction                  |
+-|				(BYTE b_Interrupt, __CPPARGS)                |
++|				(unsigned char b_Interrupt, __CPPARGS)                |
+ +----------------------------------------------------------------------------+
+ | Task              : APCI-1710 interrupt function                           |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : BYTE b_Interrupt : Interrupt number                    |
++| Input Parameters  : unsigned char b_Interrupt : Interrupt number                    |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+ +----------------------------------------------------------------------------+
+@@ -250,11 +250,11 @@ int i_APCI1710_Reset(struct comedi_device * dev)
+ void v_APCI1710_Interrupt(int irq, void *d)
+ {
+ 	struct comedi_device *dev = d;
+-	BYTE b_ModuleCpt = 0;
+-	BYTE b_InterruptFlag = 0;
+-	BYTE b_PWMCpt = 0;
+-	BYTE b_TorCounterCpt = 0;
+-	BYTE b_PulseIncoderCpt = 0;
++	unsigned char b_ModuleCpt = 0;
++	unsigned char b_InterruptFlag = 0;
++	unsigned char b_PWMCpt = 0;
++	unsigned char b_TorCounterCpt = 0;
++	unsigned char b_PulseIncoderCpt = 0;
+ 	UINT ui_16BitValue;
+ 	ULONG ul_InterruptLatchReg = 0;
+ 	ULONG ul_LatchRegisterValue = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+index a6b504c3d391..54d23591bfc3 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+@@ -850,22 +850,22 @@ INT i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device * dev,
+       /***********************************/
+ 		/* Get the software trigger status */
+       /***********************************/
+-		data[1] = (BYTE) ((ul_Command1 >> 1) & 1);
++		data[1] = (unsigned char) ((ul_Command1 >> 1) & 1);
+ 
+       /***********************************/
+ 		/* Get the hardware trigger status */
+       /***********************************/
+-		data[2] = (BYTE) ((ul_Command1 >> 2) & 1);
++		data[2] = (unsigned char) ((ul_Command1 >> 2) & 1);
+ 
+       /*********************************/
+ 		/* Get the software clear status */
+       /*********************************/
+-		data[3] = (BYTE) ((ul_Command1 >> 3) & 1);
++		data[3] = (unsigned char) ((ul_Command1 >> 3) & 1);
+ 
+       /***************************/
+ 		/* Get the overflow status */
+       /***************************/
+-		data[4] = (BYTE) ((ul_Command1 >> 0) & 1);
++		data[4] = (unsigned char) ((ul_Command1 >> 0) & 1);
+ 	}			// else  if  (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER)
+ 	else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER)
+ 		&& (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG)
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
+index 906d635da6b2..c9249ea543a8 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
+@@ -69,11 +69,11 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ |                for you call any other function witch access of TTL.        |
+ |                APCI16XX_TTL_INITDIRECTION(user inputs for direction)       |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : b_InitType    = (BYTE) data[0];                        |
+-|                     b_Port0Mode   = (BYTE) data[1];                        |
+-|                     b_Port1Mode   = (BYTE) data[2];                        |
+-|                     b_Port2Mode   = (BYTE) data[3];                        |
+-|                     b_Port3Mode   = (BYTE) data[4];                        |
++| Input Parameters  : b_InitType    = (unsigned char) data[0];                        |
++|                     b_Port0Mode   = (unsigned char) data[1];                        |
++|                     b_Port1Mode   = (unsigned char) data[2];                        |
++|                     b_Port2Mode   = (unsigned char) data[3];                        |
++|                     b_Port3Mode   = (unsigned char) data[4];                        |
+ |                     ........                                               |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+@@ -94,10 +94,10 @@ int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+-	BYTE b_Command = 0;
+-	BYTE b_Cpt = 0;
+-	BYTE b_NumberOfPort =
+-		(BYTE) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 8);
++	unsigned char b_Command = 0;
++	unsigned char b_Cpt = 0;
++	unsigned char b_NumberOfPort =
++		(unsigned char) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 8);
+ 
+ 	/************************/
+ 	/* Test the buffer size */
+@@ -108,7 +108,7 @@ int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ 		/* Get the command */
+ 		/* **************** */
+ 
+-		b_Command = (BYTE) data[0];
++		b_Command = (unsigned char) data[0];
+ 
+ 	   /********************/
+ 		/* Test the command */
+@@ -122,7 +122,7 @@ int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ 	      /***************************************/
+ 
+ 			if ((b_Command == APCI16XX_TTL_INITDIRECTION)
+-				&& ((BYTE) (insn->n - 1) != b_NumberOfPort)) {
++				&& ((unsigned char) (insn->n - 1) != b_NumberOfPort)) {
+ 		 /*******************/
+ 				/* Data size error */
+ 		 /*******************/
+@@ -132,7 +132,7 @@ int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ 			}
+ 
+ 			if ((b_Command == APCI16XX_TTL_OUTPUTMEMORY)
+-				&& ((BYTE) (insn->n) != 2)) {
++				&& ((unsigned char) (insn->n) != 2)) {
+ 		 /*******************/
+ 				/* Data size error */
+ 		 /*******************/
+@@ -266,11 +266,11 @@ int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ |              APCI16XX_TTL_READCHANNEL                                      |
+ |                    b_SelectedPort= CR_RANGE(insn->chanspec);               |
+ |                    b_InputChannel= CR_CHAN(insn->chanspec);                |
+-|                    b_ReadType	  = (BYTE) data[0];                          |
++|                    b_ReadType	  = (unsigned char) data[0];                          |
+ |                                                                            |
+ |              APCI16XX_TTL_READPORT                                         |
+ |                    b_SelectedPort= CR_RANGE(insn->chanspec);               |
+-|                    b_ReadType	  = (BYTE) data[0];                          |
++|                    b_ReadType	  = (unsigned char) data[0];                          |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : data[0]    0 : Channle is not active                   |
+ |                                1 : Channle is active                       |
+@@ -287,12 +287,12 @@ int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+-	BYTE b_Command = 0;
+-	BYTE b_NumberOfPort =
+-		(BYTE) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 8);
+-	BYTE b_SelectedPort = CR_RANGE(insn->chanspec);
+-	BYTE b_InputChannel = CR_CHAN(insn->chanspec);
+-	BYTE *pb_Status;
++	unsigned char b_Command = 0;
++	unsigned char b_NumberOfPort =
++		(unsigned char) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 8);
++	unsigned char b_SelectedPort = CR_RANGE(insn->chanspec);
++	unsigned char b_InputChannel = CR_CHAN(insn->chanspec);
++	unsigned char *pb_Status;
+ 	DWORD dw_Status;
+ 
+ 	/************************/
+@@ -304,7 +304,7 @@ int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device * dev,
+ 		/* Get the command */
+ 		/* **************** */
+ 
+-		b_Command = (BYTE) data[0];
++		b_Command = (unsigned char) data[0];
+ 
+ 	   /********************/
+ 		/* Test the command */
+@@ -380,7 +380,7 @@ int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device * dev,
+ 	/**************************/
+ 
+ 	if (i_ReturnValue >= 0) {
+-		pb_Status = (PBYTE) & data[0];
++		pb_Status = (unsigned char *) & data[0];
+ 
+ 	   /*******************************/
+ 		/* Get the digital inpu status */
+@@ -394,7 +394,7 @@ int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device * dev,
+ 		/* Save the port value */
+ 	   /***********************/
+ 
+-		*pb_Status = (BYTE) dw_Status;
++		*pb_Status = (unsigned char) dw_Status;
+ 
+ 	   /***************************************/
+ 		/* Test if read channel status command */
+@@ -433,10 +433,10 @@ int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device * dev,
+ int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	BYTE b_Command = (BYTE) CR_AREF(insn->chanspec);
++	unsigned char b_Command = (unsigned char) CR_AREF(insn->chanspec);
+ 	INT i_ReturnValue = insn->n;
+-	BYTE b_Cpt = 0;
+-	BYTE b_NumberOfPort = 0;
++	unsigned char b_Cpt = 0;
++	unsigned char b_NumberOfPort = 0;
+ 	unsigned int *pls_ReadData = data;
+ 
+ 	/********************/
+@@ -450,7 +450,7 @@ int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+ 	   /**********************************/
+ 
+ 		b_NumberOfPort =
+-			(BYTE) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 32);
++			(unsigned char) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 32);
+ 		if ((b_NumberOfPort * 32) <
+ 			devpriv->ps_BoardInfo->i_NbrTTLChannel) {
+ 			b_NumberOfPort = b_NumberOfPort + 1;
+@@ -551,11 +551,11 @@ int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+ |              APCI16XX_TTL_WRITECHANNEL_ON | APCI16XX_TTL_WRITECHANNEL_OFF  |
+ |                    b_SelectedPort = CR_RANGE(insn->chanspec);              |
+ |                    b_OutputChannel= CR_CHAN(insn->chanspec);               |
+-|                    b_Command      = (BYTE) data[0];                        |
++|                    b_Command      = (unsigned char) data[0];                        |
+ |                                                                            |
+ |              APCI16XX_TTL_WRITEPORT_ON | APCI16XX_TTL_WRITEPORT_OFF        |
+ |                    b_SelectedPort = CR_RANGE(insn->chanspec);              |
+-|                    b_Command      = (BYTE) data[0];                        |
++|                    b_Command      = (unsigned char) data[0];                        |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : data[0] : TTL output port 0 to 3 data                  |
+ |                     data[1] : TTL output port 4 to 7 data                  |
+@@ -574,11 +574,11 @@ int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+-	BYTE b_Command = 0;
+-	BYTE b_NumberOfPort =
+-		(BYTE) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 8);
+-	BYTE b_SelectedPort = CR_RANGE(insn->chanspec);
+-	BYTE b_OutputChannel = CR_CHAN(insn->chanspec);
++	unsigned char b_Command = 0;
++	unsigned char b_NumberOfPort =
++		(unsigned char) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 8);
++	unsigned char b_SelectedPort = CR_RANGE(insn->chanspec);
++	unsigned char b_OutputChannel = CR_CHAN(insn->chanspec);
+ 	DWORD dw_Status = 0;
+ 
+ 	/************************/
+@@ -590,7 +590,7 @@ int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device * dev,
+ 		/* Get the command */
+ 		/* **************** */
+ 
+-		b_Command = (BYTE) data[0];
++		b_Command = (unsigned char) data[0];
+ 
+ 	   /********************/
+ 		/* Test the command */
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+index 68eb8dfd5139..c1509ef2fce8 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+@@ -149,7 +149,7 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_sub
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	USHORT us_ConvertTiming, us_TmpValue, i;
+-	BYTE b_Tmp;
++	unsigned char b_Tmp;
+ 
+ 	// fix convertion time to 10 us
+ 	if (!devpriv->ui_EocEosConversionTime) {
+@@ -710,7 +710,7 @@ int i_APCI3120_CommandAnalogInput(struct comedi_device * dev, struct comedi_subd
+ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 	struct comedi_subdevice * s)
+ {
+-	BYTE b_Tmp;
++	unsigned char b_Tmp;
+ 	UINT ui_Tmp, ui_DelayTiming = 0, ui_TimerValue1 = 0, dmalen0 =
+ 		0, dmalen1 = 0, ui_TimerValue2 =
+ 		0, ui_TimerValue0, ui_ConvertTiming;
+@@ -1426,7 +1426,7 @@ void v_APCI3120_Interrupt(int irq, void *d)
+ 
+ 	unsigned int int_amcc, ui_Check, i;
+ 	USHORT us_TmpValue;
+-	BYTE b_DummyRead;
++	unsigned char b_DummyRead;
+ 
+ 	struct comedi_subdevice *s = dev->subdevices + 0;
+ 	ui_Check = 1;
+@@ -1974,16 +1974,16 @@ int i_APCI3120_InsnConfigTimer(struct comedi_device * dev, struct comedi_subdevi
+ 
+ 	UINT ui_Timervalue2;
+ 	USHORT us_TmpValue;
+-	BYTE b_Tmp;
++	unsigned char b_Tmp;
+ 
+ 	if (!data[1])
+ 		comedi_error(dev, "config:No timer constant !");
+ 
+-	devpriv->b_Timer2Interrupt = (BYTE) data[2];	// save info whether to enable or disable interrupt
++	devpriv->b_Timer2Interrupt = (unsigned char) data[2];	// save info whether to enable or disable interrupt
+ 
+ 	ui_Timervalue2 = data[1] / 1000;	// convert nano seconds  to u seconds
+ 
+-	//this_board->i_hwdrv_InsnConfigTimer(dev, ui_Timervalue2,(BYTE)data[0]);
++	//this_board->i_hwdrv_InsnConfigTimer(dev, ui_Timervalue2,(unsigned char)data[0]);
+ 	us_TmpValue = (USHORT) inw(devpriv->iobase + APCI3120_RD_STATUS);
+ 
+ 	//EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001
+@@ -2125,7 +2125,7 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device * dev, struct comedi_subdevic
+ 
+ 	UINT ui_Timervalue2 = 0;
+ 	USHORT us_TmpValue;
+-	BYTE b_Tmp;
++	unsigned char b_Tmp;
+ 
+ 	if ((devpriv->b_Timer2Mode != APCI3120_WATCHDOG)
+ 		&& (devpriv->b_Timer2Mode != APCI3120_TIMER)) {
+@@ -2308,7 +2308,7 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device * dev, struct comedi_subdevic
+ int i_APCI3120_InsnReadTimer(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	BYTE b_Tmp;
++	unsigned char b_Tmp;
+ 	USHORT us_TmpValue, us_TmpValue_2, us_StatusValue;
+ 
+ 	if ((devpriv->b_Timer2Mode != APCI3120_WATCHDOG)
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
+index 59d5d87a845b..03031bb027a2 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
+@@ -166,10 +166,10 @@ static const struct comedi_lrange range_apci3120_ao = { 2, {
+ #define MAX_ANALOGINPUT_CHANNELS    32
+ 
+ typedef struct {
+-	BYTE b_Type;		/* EOC or EOS */
+-	BYTE b_InterruptFlag;	/* Interrupt use or not                    */
++	unsigned char b_Type;		/* EOC or EOS */
++	unsigned char b_InterruptFlag;	/* Interrupt use or not                    */
+ 	UINT ui_ConvertTiming;	/* Selection of the convertion time        */
+-	BYTE b_NbrOfChannel;	/* Number of channel to read               */
++	unsigned char b_NbrOfChannel;	/* Number of channel to read               */
+ 	UINT ui_ChannelList[MAX_ANALOGINPUT_CHANNELS];	/* Number of the channel to be read        */
+ 	UINT ui_RangeList[MAX_ANALOGINPUT_CHANNELS];	/* Gain of each channel                    */
+ 
+@@ -214,7 +214,7 @@ int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev, struct comedi_sub
+ 				    struct comedi_insn *insn, unsigned int *data);
+ 
+ //DO
+-//int i_APCI3120_WriteDigitalOutput(struct comedi_device *dev, BYTE data);
++//int i_APCI3120_WriteDigitalOutput(struct comedi_device *dev, unsigned char data);
+ int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device *dev,
+ 				       struct comedi_subdevice *s, struct comedi_insn *insn,
+ 				       unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+index 1ff66bee548d..d44837c333ff 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+@@ -118,11 +118,11 @@ INT i_AddiHeaderRW_ReadEeprom(INT i_NbOfWordsToRead,
+ 	INT i_Counter = 0;
+ 	INT i_WordCounter;
+ 	INT i;
+-	BYTE pb_ReadByte[1];
+-	BYTE b_ReadLowByte = 0;
+-	BYTE b_ReadHighByte = 0;
+-	BYTE b_SelectedAddressLow = 0;
+-	BYTE b_SelectedAddressHigh = 0;
++	unsigned char pb_ReadByte[1];
++	unsigned char b_ReadLowByte = 0;
++	unsigned char b_ReadHighByte = 0;
++	unsigned char b_SelectedAddressLow = 0;
++	unsigned char b_SelectedAddressHigh = 0;
+ 	WORD w_ReadWord = 0;
+ 
+ 	for (i_WordCounter = 0; i_WordCounter < i_NbOfWordsToRead;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+index a6f57f55e79c..d93fff37df84 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+@@ -137,7 +137,7 @@ typedef struct {
+ 	INT i_Initialised;
+ 	//UINT ui_InterruptChannelValue[96]; //Buffer
+ 	UINT ui_InterruptChannelValue[144];	//Buffer
+-	BYTE b_StructInitialized;
++	unsigned char b_StructInitialized;
+ 	//Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+ 	unsigned int ui_ScanValueArray[7 + 12];	// 7 is the maximal number of channels
+ 	//End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+index b7268e4da64e..6914637992a0 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+@@ -87,8 +87,8 @@ int i_APCI3XXX_TestConversionStarted(struct comedi_device * dev)
+ +----------------------------------------------------------------------------+
+ | Task           Converting mode and convert time selection                  |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : b_SingleDiff  = (BYTE)  data[1];                       |
+-|                     b_TimeBase    = (BYTE)  data[2]; (0: ns, 1:micros 2:ms)|
++| Input Parameters  : b_SingleDiff  = (unsigned char)  data[1];                       |
++|                     b_TimeBase    = (unsigned char)  data[2]; (0: ns, 1:micros 2:ms)|
+ |                    dw_ReloadValue = (DWORD) data[3];                       |
+ |                     ........                                               |
+ +----------------------------------------------------------------------------+
+@@ -109,8 +109,8 @@ int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+-	BYTE b_TimeBase = 0;
+-	BYTE b_SingleDiff = 0;
++	unsigned char b_TimeBase = 0;
++	unsigned char b_SingleDiff = 0;
+ 	DWORD dw_ReloadValue = 0;
+ 	DWORD dw_TestReloadValue = 0;
+ 
+@@ -123,13 +123,13 @@ int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device * dev,
+ 		/* Get the Singel/Diff flag */
+ 	   /****************************/
+ 
+-		b_SingleDiff = (BYTE) data[1];
++		b_SingleDiff = (unsigned char) data[1];
+ 
+ 	   /****************************/
+ 		/* Get the time base unitiy */
+ 	   /****************************/
+ 
+-		b_TimeBase = (BYTE) data[2];
++		b_TimeBase = (unsigned char) data[2];
+ 
+ 	   /*************************************/
+ 		/* Get the convert time reload value */
+@@ -281,8 +281,8 @@ int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Task           Converting mode and convert time selection                  |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : b_ConvertMode = (BYTE)  data[0];                       |
+-|                     b_TimeBase    = (BYTE)  data[1]; (0: ns, 1:micros 2:ms)|
++| Input Parameters  : b_ConvertMode = (unsigned char)  data[0];                       |
++|                     b_TimeBase    = (unsigned char)  data[1]; (0: ns, 1:micros 2:ms)|
+ |                    dw_ReloadValue = (DWORD) data[2];                       |
+ |                     ........                                               |
+ +----------------------------------------------------------------------------+
+@@ -305,7 +305,7 @@ int i_APCI3XXX_InsnConfigAnalogInput(struct comedi_device * dev,
+ 	/************************/
+ 
+ 	if (insn->n >= 1) {
+-		switch ((BYTE) data[0]) {
++		switch ((unsigned char) data[0]) {
+ 		case APCI3XXX_CONFIGURATION:
+ 			i_ReturnValue =
+ 				i_APCI3XXX_AnalogInputConfigOperatingMode(dev,
+@@ -359,12 +359,12 @@ int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+-	BYTE b_Configuration = (BYTE) CR_RANGE(insn->chanspec);
+-	BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
++	unsigned char b_Configuration = (unsigned char) CR_RANGE(insn->chanspec);
++	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
+ 	DWORD dw_Temp = 0;
+ 	DWORD dw_Configuration = 0;
+ 	DWORD dw_AcquisitionCpt = 0;
+-	BYTE b_Interrupt = 0;
++	unsigned char b_Interrupt = 0;
+ 
+ 	/*************************************/
+ 	/* Test if operating mode configured */
+@@ -607,7 +607,7 @@ int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device * dev,
+ void v_APCI3XXX_Interrupt(int irq, void *d)
+ {
+ 	struct comedi_device *dev = d;
+-	BYTE b_CopyCpt = 0;
++	unsigned char b_CopyCpt = 0;
+ 	DWORD dw_Status = 0;
+ 
+ 	/***************************/
+@@ -687,8 +687,8 @@ void v_APCI3XXX_Interrupt(int irq, void *d)
+ int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	BYTE b_Range = (BYTE) CR_RANGE(insn->chanspec);
+-	BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
++	unsigned char b_Range = (unsigned char) CR_RANGE(insn->chanspec);
++	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
+ 	DWORD dw_Status = 0;
+ 	INT i_ReturnValue = insn->n;
+ 
+@@ -778,8 +778,8 @@ int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device * dev,
+ |                for you call any other function witch access of TTL.        |
+ |                APCI3XXX_TTL_INIT_DIRECTION_PORT2(user inputs for direction)|
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : b_InitType    = (BYTE) data[0];                        |
+-|                     b_Port2Mode   = (BYTE) data[1];                        |
++| Input Parameters  : b_InitType    = (unsigned char) data[0];                        |
++|                     b_Port2Mode   = (unsigned char) data[1];                        |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+ +----------------------------------------------------------------------------+
+@@ -795,7 +795,7 @@ int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+-	BYTE b_Command = 0;
++	unsigned char b_Command = 0;
+ 
+ 	/************************/
+ 	/* Test the buffer size */
+@@ -806,7 +806,7 @@ int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ 		/* Get the command */
+ 		/* **************** */
+ 
+-		b_Command = (BYTE) data[0];
++		b_Command = (unsigned char) data[0];
+ 
+ 	   /********************/
+ 		/* Test the command */
+@@ -923,7 +923,7 @@ int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+-	BYTE b_ChannelCpt = 0;
++	unsigned char b_ChannelCpt = 0;
+ 	DWORD dw_ChannelMask = 0;
+ 	DWORD dw_BitMask = 0;
+ 	DWORD dw_Status = 0;
+@@ -1077,7 +1077,7 @@ int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device * dev,
+ int i_APCI3XXX_InsnReadTTLIO(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+-	BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
++	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
+ 	INT i_ReturnValue = insn->n;
+ 	unsigned int *pls_ReadData = data;
+ 
+@@ -1191,8 +1191,8 @@ int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+-	BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
+-	BYTE b_State = 0;
++	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
++	unsigned char b_State = 0;
+ 	DWORD dw_Status = 0;
+ 
+ 	/************************/
+@@ -1200,7 +1200,7 @@ int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device * dev,
+ 	/************************/
+ 
+ 	if (insn->n >= 1) {
+-		b_State = (BYTE) data[0];
++		b_State = (unsigned char) data[0];
+ 
+ 	   /***********************/
+ 		/* Test if read port 0 */
+@@ -1302,7 +1302,7 @@ int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+-	BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
++	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
+ 	DWORD dw_Temp = 0;
+ 
+ 	/***************************/
+@@ -1413,7 +1413,7 @@ int i_APCI3XXX_InsnBitsDigitalOutput(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+-	BYTE b_ChannelCpt = 0;
++	unsigned char b_ChannelCpt = 0;
+ 	DWORD dw_ChannelMask = 0;
+ 	DWORD dw_BitMask = 0;
+ 	DWORD dw_Status = 0;
+@@ -1509,8 +1509,8 @@ int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+-	BYTE b_Channel = CR_CHAN(insn->chanspec);
+-	BYTE b_State = 0;
++	unsigned char b_Channel = CR_CHAN(insn->chanspec);
++	unsigned char b_State = 0;
+ 	DWORD dw_Status = 0;
+ 
+ 	/************************/
+@@ -1527,7 +1527,7 @@ int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device * dev,
+ 			/* Get the command */
+ 	      /*******************/
+ 
+-			b_State = (BYTE) data[0];
++			b_State = (unsigned char) data[0];
+ 
+ 	      /********************************/
+ 			/* Read the digital output port */
+@@ -1584,7 +1584,7 @@ int i_APCI3XXX_InsnReadDigitalOutput(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+-	BYTE b_Channel = CR_CHAN(insn->chanspec);
++	unsigned char b_Channel = CR_CHAN(insn->chanspec);
+ 	DWORD dw_Status = 0;
+ 
+ 	/************************/

commit 2ec9f875f8f60c9102f97fba23e9abe9ed4480a6
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:04:36 2009 -0400
+
+    Staging: comedi: Remove local_info_t typedef in ni_daq_dio24
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
+index e3ff9acc7dd1..38ba49ec1def 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
++++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
+@@ -236,12 +236,12 @@ static void dio24_cs_detach(struct pcmcia_device *);
+ 
+ static const dev_info_t dev_info = "ni_daq_dio24";
+ 
+-typedef struct local_info_t {
++struct local_info_t {
+ 	struct pcmcia_device *link;
+ 	dev_node_t node;
+ 	int stop;
+ 	struct bus_operations *bus;
+-} local_info_t;
++};
+ 
+ /*======================================================================
+ 
+@@ -257,14 +257,14 @@ typedef struct local_info_t {
+ 
+ static int dio24_cs_attach(struct pcmcia_device *link)
+ {
+-	local_info_t *local;
++	struct local_info_t *local;
+ 
+ 	printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO - CS-attach!\n");
+ 
+ 	DEBUG(0, "dio24_cs_attach()\n");
+ 
+ 	/* Allocate space for private device-specific data */
+-	local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
++	local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
+ 	if (!local)
+ 		return -ENOMEM;
+ 	local->link = link;
+@@ -309,7 +309,7 @@ static void dio24_cs_detach(struct pcmcia_device *link)
+ 	DEBUG(0, "dio24_cs_detach(0x%p)\n", link);
+ 
+ 	if (link->dev_node) {
+-		((local_info_t *) link->priv)->stop = 1;
++		((struct local_info_t *) link->priv)->stop = 1;
+ 		dio24_release(link);
+ 	}
+ 
+@@ -329,7 +329,7 @@ static void dio24_cs_detach(struct pcmcia_device *link)
+ 
+ static void dio24_config(struct pcmcia_device *link)
+ {
+-	local_info_t *dev = link->priv;
++	struct local_info_t *dev = link->priv;
+ 	tuple_t tuple;
+ 	cisparse_t parse;
+ 	int last_ret;
+@@ -529,7 +529,7 @@ static void dio24_release(struct pcmcia_device *link)
+ 
+ static int dio24_cs_suspend(struct pcmcia_device *link)
+ {
+-	local_info_t *local = link->priv;
++	struct local_info_t *local = link->priv;
+ 
+ 	/* Mark the device as stopped, to block IO until later */
+ 	local->stop = 1;
+@@ -538,7 +538,7 @@ static int dio24_cs_suspend(struct pcmcia_device *link)
+ 
+ static int dio24_cs_resume(struct pcmcia_device *link)
+ {
+-	local_info_t *local = link->priv;
++	struct local_info_t *local = link->priv;
+ 
+ 	local->stop = 0;
+ 	return 0;

commit cf4c8d1b8f59ae5591bba0936f378e52df09aa04
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:04:30 2009 -0400
+
+    Staging: comedi: Remove dio24_board_struct typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
+index daec5c4b4c95..e3ff9acc7dd1 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
++++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
+@@ -61,7 +61,7 @@ static int dio24_detach(struct comedi_device * dev);
+ 
+ enum dio24_bustype { pcmcia_bustype };
+ 
+-typedef struct dio24_board_struct {
++struct dio24_board_struct {
+ 	const char *name;
+ 	int device_id;		// device id for pcmcia board
+ 	enum dio24_bustype bustype;	// PCMCIA
+@@ -69,9 +69,9 @@ typedef struct dio24_board_struct {
+ 	// function pointers so we can use inb/outb or readb/writeb as appropriate
+ 	unsigned int (*read_byte) (unsigned int address);
+ 	void (*write_byte) (unsigned int byte, unsigned int address);
+-} dio24_board;
++};
+ 
+-static const dio24_board dio24_boards[] = {
++static const struct dio24_board_struct dio24_boards[] = {
+ 	{
+ 	      name:	"daqcard-dio24",
+ 	      device_id:0x475c,// 0x10b is manufacturer id, 0x475c is device id
+@@ -89,7 +89,7 @@ static const dio24_board dio24_boards[] = {
+ /*
+  * Useful for shorthand access to the particular board structure
+  */
+-#define thisboard ((const dio24_board *)dev->board_ptr)
++#define thisboard ((const struct dio24_board_struct *)dev->board_ptr)
+ 
+ struct dio24_private {
+ 
+@@ -104,9 +104,9 @@ static struct comedi_driver driver_dio24 = {
+       module:THIS_MODULE,
+       attach:dio24_attach,
+       detach:dio24_detach,
+-      num_names:sizeof(dio24_boards) / sizeof(dio24_board),
++      num_names:sizeof(dio24_boards) / sizeof(struct dio24_board_struct),
+       board_name:&dio24_boards[0].name,
+-      offset:sizeof(dio24_board),
++      offset:sizeof(struct dio24_board_struct),
+ };
+ 
+ static int dio24_attach(struct comedi_device * dev, struct comedi_devconfig * it)

commit e3f9f2c8e6f048ab017ecdc2e7fae102f3344f98
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:04:25 2009 -0400
+
+    Staging: comedi: Remove local_info_t typedef in ni_labpc_cs
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
+index ac0ce2f58f5f..0c2a196adaff 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
++++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
+@@ -213,12 +213,12 @@ static void labpc_cs_detach(struct pcmcia_device *);
+ 
+ static const dev_info_t dev_info = "daqcard-1200";
+ 
+-typedef struct local_info_t {
++struct local_info_t {
+ 	struct pcmcia_device *link;
+ 	dev_node_t node;
+ 	int stop;
+ 	struct bus_operations *bus;
+-} local_info_t;
++};
+ 
+ /*======================================================================
+ 
+@@ -234,12 +234,12 @@ typedef struct local_info_t {
+ 
+ static int labpc_cs_attach(struct pcmcia_device *link)
+ {
+-	local_info_t *local;
++	struct local_info_t *local;
+ 
+ 	DEBUG(0, "labpc_cs_attach()\n");
+ 
+ 	/* Allocate space for private device-specific data */
+-	local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
++	local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
+ 	if (!local)
+ 		return -ENOMEM;
+ 	local->link = link;
+@@ -287,7 +287,7 @@ static void labpc_cs_detach(struct pcmcia_device *link)
+ 	   detach().
+ 	 */
+ 	if (link->dev_node) {
+-		((local_info_t *) link->priv)->stop = 1;
++		((struct local_info_t *) link->priv)->stop = 1;
+ 		labpc_release(link);
+ 	}
+ 
+@@ -307,7 +307,7 @@ static void labpc_cs_detach(struct pcmcia_device *link)
+ 
+ static void labpc_config(struct pcmcia_device *link)
+ {
+-	local_info_t *dev = link->priv;
++	struct local_info_t *dev = link->priv;
+ 	tuple_t tuple;
+ 	cisparse_t parse;
+ 	int last_ret;
+@@ -501,7 +501,7 @@ static void labpc_release(struct pcmcia_device *link)
+ 
+ static int labpc_cs_suspend(struct pcmcia_device *link)
+ {
+-	local_info_t *local = link->priv;
++	struct local_info_t *local = link->priv;
+ 
+ 	/* Mark the device as stopped, to block IO until later */
+ 	local->stop = 1;
+@@ -510,7 +510,7 @@ static int labpc_cs_suspend(struct pcmcia_device *link)
+ 
+ static int labpc_cs_resume(struct pcmcia_device *link)
+ {
+-	local_info_t *local = link->priv;
++	struct local_info_t *local = link->priv;
+ 
+ 	local->stop = 0;
+ 	return 0;

commit 3301cc76656c5fee5b638378d9057e93796d490f
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:04:20 2009 -0400
+
+    Staging: comedi: Remove ni_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c
+index 72985e084f09..76def4b9e8fb 100644
+--- a/drivers/staging/comedi/drivers/ni_atmio.c
++++ b/drivers/staging/comedi/drivers/ni_atmio.c
+@@ -276,10 +276,12 @@ static const int ni_irqpin[] =
+ 
+ #define NI_E_IRQ_FLAGS		0
+ 
+-typedef struct {
++struct ni_private {
+ 	struct pnp_dev *isapnp_dev;
+- NI_PRIVATE_COMMON} ni_private;
+-#define devpriv ((ni_private *)dev->private)
++         NI_PRIVATE_COMMON
++};
++
++#define devpriv ((struct ni_private *)dev->private)
+ 
+ /* How we access registers */
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index 542bd0dcd44d..e46545048c3a 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -4278,7 +4278,7 @@ static int ni_alloc_private(struct comedi_device * dev)
+ {
+ 	int ret;
+ 
+-	ret = alloc_private(dev, sizeof(ni_private));
++	ret = alloc_private(dev, sizeof(struct ni_private));
+ 	if (ret < 0)
+ 		return ret;
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
+index 225f39785f0b..90e228b0ae0f 100644
+--- a/drivers/staging/comedi/drivers/ni_pcimio.c
++++ b/drivers/staging/comedi/drivers/ni_pcimio.c
+@@ -1218,9 +1218,11 @@ static struct comedi_driver driver_pcimio = {
+ 
+ COMEDI_PCI_INITCLEANUP(driver_pcimio, ni_pci_table)
+ 
+-typedef struct {
+-NI_PRIVATE_COMMON} ni_private;
+-#define devpriv ((ni_private *)dev->private)
++struct ni_private {
++NI_PRIVATE_COMMON
++};
++
++#define devpriv ((struct ni_private *)dev->private)
+ 
+ /* How we access registers */
+ 

commit 8ab41df0d7399567372d75d1a3c552dccb42063d
+Author: Bill Pemberton 
+Date:   Wed Mar 25 11:04:14 2009 -0400
+
+    Staging: comedi: Remove ni_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c
+index fcc38535afc5..72985e084f09 100644
+--- a/drivers/staging/comedi/drivers/ni_atmio.c
++++ b/drivers/staging/comedi/drivers/ni_atmio.c
+@@ -114,7 +114,7 @@ are not supported.
+ 
+ #define MAX_N_CALDACS 32
+ 
+-static const ni_board ni_boards[] = {
++static const struct ni_board_struct ni_boards[] = {
+       {device_id:44,
+ 	      isapnp_id:0x0000,/* XXX unknown */
+ 	      name:	"at-mio-16e-1",
+diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
+index 3a2aba7c8dd3..225f39785f0b 100644
+--- a/drivers/staging/comedi/drivers/ni_pcimio.c
++++ b/drivers/staging/comedi/drivers/ni_pcimio.c
+@@ -216,7 +216,7 @@ static const struct comedi_lrange range_ni_M_622x_ao = { 1, {
+ 	}
+ };
+ 
+-static const ni_board ni_boards[] = {
++static const struct ni_board_struct ni_boards[] = {
+ 	{
+ 			.device_id = 0x0162,	// NI also says 0x1620.  typo?
+ 			.name = "pci-mio-16xe-50",
+diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h
+index 1ebf521ab773..8c03e7d85e84 100644
+--- a/drivers/staging/comedi/drivers/ni_stc.h
++++ b/drivers/staging/comedi/drivers/ni_stc.h
+@@ -1374,7 +1374,7 @@ enum Interrupt_C_Status_Bits {
+ 
+ #define M_SERIES_EEPROM_SIZE 1024
+ 
+-typedef struct ni_board_struct {
++struct ni_board_struct {
+ 	int device_id;
+ 	int isapnp_id;
+ 	char *name;
+@@ -1401,11 +1401,11 @@ typedef struct ni_board_struct {
+ 	unsigned int has_analog_trig:1;
+ 
+ 	enum caldac_enum caldac[3];
+-} ni_board;
++};
+ 
+-#define n_ni_boards  (sizeof(ni_boards)/sizeof(ni_board))
++#define n_ni_boards  (sizeof(ni_boards)/sizeof(struct ni_board_struct))
+ 
+-#define boardtype (*(ni_board *)dev->board_ptr)
++#define boardtype (*(struct ni_board_struct *)dev->board_ptr)
+ 
+ #define MAX_N_AO_CHAN 8
+ #define NUM_GPCT 2

commit 180027136b30d25f3824573e77c080056dc3e6d4
+Author: Bill Pemberton 
+Date:   Thu Mar 19 18:00:52 2009 -0400
+
+    Staging: comedi: Remove CHAR, *PCHAR, and *PCSTR typedefs in addi-data
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+index fb8e25d250a0..19df5c1444a4 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+@@ -37,8 +37,6 @@
+ #define SUCCESS	1
+ 
+ /* variable type definition */
+-typedef char CHAR, *PCHAR;
+-typedef const CHAR *PCSTR;
+ typedef unsigned char BYTE, *PBYTE;
+ typedef short SHORT, *PSHORT;
+ typedef unsigned short USHORT, *PUSHORT;
+@@ -78,7 +76,7 @@ typedef const struct comedi_lrange *PCRANGE;
+ 
+ /* structure for the boardtype */
+ typedef struct {
+-	PCSTR pc_DriverName;	// driver name
++	const char *pc_DriverName;	// driver name
+ 	INT i_VendorId;		//PCI vendor a device ID of card
+ 	INT i_DeviceId;
+ 	INT i_IorangeBase0;
+@@ -86,7 +84,7 @@ typedef struct {
+ 	INT i_IorangeBase2;	//  base 2 range
+ 	INT i_IorangeBase3;	//  base 3 range
+ 	INT i_PCIEeprom;	// eeprom present or not
+-	PCHAR pc_EepromChip;	// type of chip
++	char *pc_EepromChip;	// type of chip
+ 	INT i_NbrAiChannel;	// num of A/D chans
+ 	INT i_NbrAiChannelDiff;	// num of A/D chans in diff mode
+ 	INT i_AiChannelList;	// len of chanlist
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+index 29026ab5c61d..a8a1bb2e8fa5 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+@@ -121,32 +121,32 @@ typedef struct {
+ 		/*****************************************/
+ 
+ INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress,
+-	PCHAR pc_PCIChipInformation, struct comedi_device *dev);
++	char *pc_PCIChipInformation, struct comedi_device *dev);
+ 
+ INT i_EepromReadDigitalInputHeader(WORD w_PCIBoardEepromAddress,
+-	PCHAR pc_PCIChipInformation, WORD w_Address,
++	char *pc_PCIChipInformation, WORD w_Address,
+ 	str_DigitalInputHeader * s_Header);
+ 
+ INT i_EepromReadDigitalOutputHeader(WORD w_PCIBoardEepromAddress,
+-	PCHAR pc_PCIChipInformation, WORD w_Address,
++	char *pc_PCIChipInformation, WORD w_Address,
+ 	str_DigitalOutputHeader * s_Header);
+ 
+ INT i_EepromReadTimerHeader(WORD w_PCIBoardEepromAddress,
+-	PCHAR pc_PCIChipInformation, WORD w_Address,
++	char *pc_PCIChipInformation, WORD w_Address,
+ 	str_TimerMainHeader * s_Header);
+ 
+ INT i_EepromReadAnlogOutputHeader(WORD w_PCIBoardEepromAddress,
+-	PCHAR pc_PCIChipInformation, WORD w_Address,
++	char *pc_PCIChipInformation, WORD w_Address,
+ 	str_AnalogOutputHeader * s_Header);
+ 
+ INT i_EepromReadAnlogInputHeader(WORD w_PCIBoardEepromAddress,
+-	PCHAR pc_PCIChipInformation, WORD w_Address,
++	char *pc_PCIChipInformation, WORD w_Address,
+ 	str_AnalogInputHeader * s_Header);
+ 
+ 		/******************************************/
+ 		/*      Eeprom Specific Functions                         */
+ 		/******************************************/
+-WORD w_EepromReadWord(WORD w_PCIBoardEepromAddress, PCHAR pc_PCIChipInformation,
++WORD w_EepromReadWord(WORD w_PCIBoardEepromAddress, char *pc_PCIChipInformation,
+ 	WORD w_EepromStartAddress);
+ void v_EepromWaitBusy(WORD w_PCIBoardEepromAddress);
+ void v_EepromClock76(DWORD dw_Address, DWORD dw_RegisterValue);
+@@ -159,14 +159,14 @@ void v_EepromCs76Read(DWORD dw_Address, WORD w_offset, PWORD pw_Value);
+ +----------------------------------------------------------------------------+
+ | Function   Name   : WORD w_EepromReadWord                                  |
+ |				(WORD	w_PCIBoardEepromAddress,             		 |
+-|				 PCHAR 	pc_PCIChipInformation,               		 |
++|				 char *	pc_PCIChipInformation,               		 |
+ |				 WORD   w_EepromStartAddress)                		 |
+ +----------------------------------------------------------------------------+
+ | Task              : Read from eepromn a word                               |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : WORD w_PCIBoardEepromAddress : PCI eeprom address      |
+ |																	 |
+-|		      PCHAR pc_PCIChipInformation  : PCI Chip Type.          |
++|		      char *pc_PCIChipInformation  : PCI Chip Type.          |
+ |																	 |
+ |		      WORD w_EepromStartAddress    : Selected eeprom address |
+ +----------------------------------------------------------------------------+
+@@ -176,7 +176,7 @@ void v_EepromCs76Read(DWORD dw_Address, WORD w_offset, PWORD pw_Value);
+ +----------------------------------------------------------------------------+
+ */
+ 
+-WORD w_EepromReadWord(WORD w_PCIBoardEepromAddress, PCHAR pc_PCIChipInformation,
++WORD w_EepromReadWord(WORD w_PCIBoardEepromAddress, char *pc_PCIChipInformation,
+ 	WORD w_EepromStartAddress)
+ {
+ 
+@@ -522,7 +522,7 @@ void v_EepromSendCommand76(DWORD dw_Address, DWORD dw_EepromCommand,
+ 	BYTE b_DataLengthInBits)
+ {
+ 
+-	CHAR c_BitPos = 0;
++	char c_BitPos = 0;
+ 
+ 	DWORD dw_RegisterValue = 0;
+ 
+@@ -656,7 +656,7 @@ void v_EepromSendCommand76(DWORD dw_Address, DWORD dw_EepromCommand,
+ void v_EepromCs76Read(DWORD dw_Address, WORD w_offset, PWORD pw_Value)
+ {
+ 
+-	CHAR c_BitPos = 0;
++        char c_BitPos = 0;
+ 
+ 	DWORD dw_RegisterValue = 0;
+ 
+@@ -787,13 +787,13 @@ void v_EepromCs76Read(DWORD dw_Address, WORD w_offset, PWORD pw_Value)
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name  : INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress,  |
+-|				PCHAR 	pc_PCIChipInformation,struct comedi_device *dev)    |
++|				char *	pc_PCIChipInformation,struct comedi_device *dev)    |
+ +----------------------------------------------------------------------------+
+ | Task              : Read from eeprom Main Header                           |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : WORD w_PCIBoardEepromAddress : PCI eeprom address      |
+ |																	 |
+-|		      PCHAR pc_PCIChipInformation  : PCI Chip Type.          |
++|		      char *pc_PCIChipInformation  : PCI Chip Type.          |
+ |																	 |
+ |			  struct comedi_device *dev		   : comedi device structure |
+ |											 pointer				 |
+@@ -805,7 +805,7 @@ void v_EepromCs76Read(DWORD dw_Address, WORD w_offset, PWORD pw_Value)
+ */
+ 
+ INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress,
+-	PCHAR pc_PCIChipInformation, struct comedi_device *dev)
++	char *pc_PCIChipInformation, struct comedi_device *dev)
+ {
+ 	WORD w_Temp, i, w_Count = 0;
+ 	UINT ui_Temp;
+@@ -921,7 +921,7 @@ INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name  : INT i_EepromReadDigitalInputHeader(WORD 					 |
+-|			w_PCIBoardEepromAddress,PCHAR pc_PCIChipInformation,	 |
++|			w_PCIBoardEepromAddress,char *pc_PCIChipInformation,	 |
+ |			WORD w_Address,str_DigitalInputHeader *s_Header)		 |
+ |																	 |
+ +----------------------------------------------------------------------------+
+@@ -929,7 +929,7 @@ INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress,
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : WORD w_PCIBoardEepromAddress : PCI eeprom address      |
+ |																	 |
+-|		      PCHAR pc_PCIChipInformation  : PCI Chip Type.          |
++|		      char *pc_PCIChipInformation  : PCI Chip Type.          |
+ |																	 |
+ |			 str_DigitalInputHeader *s_Header: Digita Input Header   |
+ |												   Pointer			 |
+@@ -940,7 +940,7 @@ INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_EepromReadDigitalInputHeader(WORD w_PCIBoardEepromAddress,
+-	PCHAR pc_PCIChipInformation, WORD w_Address,
++	char *pc_PCIChipInformation, WORD w_Address,
+ 	str_DigitalInputHeader * s_Header)
+ {
+ 	WORD w_Temp;
+@@ -966,7 +966,7 @@ INT i_EepromReadDigitalInputHeader(WORD w_PCIBoardEepromAddress,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name  : INT i_EepromReadDigitalOutputHeader(WORD 				 |
+-|			w_PCIBoardEepromAddress,PCHAR pc_PCIChipInformation,	 |
++|			w_PCIBoardEepromAddress,char *pc_PCIChipInformation,	 |
+ |			WORD w_Address,str_DigitalOutputHeader *s_Header)	     |
+ |																	 |
+ +----------------------------------------------------------------------------+
+@@ -974,7 +974,7 @@ INT i_EepromReadDigitalInputHeader(WORD w_PCIBoardEepromAddress,
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : WORD w_PCIBoardEepromAddress : PCI eeprom address      |
+ |																	 |
+-|		      PCHAR pc_PCIChipInformation  : PCI Chip Type.          |
++|		      char *pc_PCIChipInformation  : PCI Chip Type.          |
+ |																	 |
+ |			 str_DigitalOutputHeader *s_Header: Digital Output Header|
+ |											   Pointer				 |
+@@ -985,7 +985,7 @@ INT i_EepromReadDigitalInputHeader(WORD w_PCIBoardEepromAddress,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_EepromReadDigitalOutputHeader(WORD w_PCIBoardEepromAddress,
+-	PCHAR pc_PCIChipInformation, WORD w_Address,
++	char *pc_PCIChipInformation, WORD w_Address,
+ 	str_DigitalOutputHeader * s_Header)
+ {
+ // Read Nbr channels
+@@ -998,14 +998,14 @@ INT i_EepromReadDigitalOutputHeader(WORD w_PCIBoardEepromAddress,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name  : INT i_EepromReadTimerHeader(WORD w_PCIBoardEepromAddress, |
+-|			PCHAR pc_PCIChipInformation,WORD w_Address,				 |
++|			char *pc_PCIChipInformation,WORD w_Address,				 |
+ |			str_TimerMainHeader *s_Header)							 |
+ +----------------------------------------------------------------------------+
+ | Task              : Read Timer or Watchdog Header                          |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : WORD w_PCIBoardEepromAddress : PCI eeprom address      |
+ |																	 |
+-|		      PCHAR pc_PCIChipInformation  : PCI Chip Type.          |
++|		      char *pc_PCIChipInformation  : PCI Chip Type.          |
+ |																	 |
+ |			 str_TimerMainHeader *s_Header: Timer Header			 |
+ |											   Pointer				 |
+@@ -1016,7 +1016,7 @@ INT i_EepromReadDigitalOutputHeader(WORD w_PCIBoardEepromAddress,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_EepromReadTimerHeader(WORD w_PCIBoardEepromAddress,
+-	PCHAR pc_PCIChipInformation, WORD w_Address,
++	char *pc_PCIChipInformation, WORD w_Address,
+ 	str_TimerMainHeader * s_Header)
+ {
+ 
+@@ -1063,14 +1063,14 @@ INT i_EepromReadTimerHeader(WORD w_PCIBoardEepromAddress,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name  : INT i_EepromReadAnlogOutputHeader(WORD 					 |
+-|			w_PCIBoardEepromAddress,PCHAR pc_PCIChipInformation,	 |
++|			w_PCIBoardEepromAddress,char *pc_PCIChipInformation,	 |
+ |			WORD w_Address,str_AnalogOutputHeader *s_Header)         |
+ +----------------------------------------------------------------------------+
+ | Task              : Read Nalog Output  Header                              |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : WORD w_PCIBoardEepromAddress : PCI eeprom address      |
+ |																	 |
+-|		      PCHAR pc_PCIChipInformation  : PCI Chip Type.          |
++|		      char *pc_PCIChipInformation  : PCI Chip Type.          |
+ |																	 |
+ |			 str_AnalogOutputHeader *s_Header:Anlog Output Header    |
+ |											   Pointer				 |
+@@ -1082,7 +1082,7 @@ INT i_EepromReadTimerHeader(WORD w_PCIBoardEepromAddress,
+ */
+ 
+ INT i_EepromReadAnlogOutputHeader(WORD w_PCIBoardEepromAddress,
+-	PCHAR pc_PCIChipInformation, WORD w_Address,
++	char *pc_PCIChipInformation, WORD w_Address,
+ 	str_AnalogOutputHeader * s_Header)
+ {
+ 	WORD w_Temp;
+@@ -1100,14 +1100,14 @@ INT i_EepromReadAnlogOutputHeader(WORD w_PCIBoardEepromAddress,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name  : INT i_EepromReadAnlogInputHeader(WORD 					 |
+-|			w_PCIBoardEepromAddress,PCHAR pc_PCIChipInformation,     |
++|			w_PCIBoardEepromAddress,char *pc_PCIChipInformation,     |
+ |			WORD w_Address,str_AnalogInputHeader *s_Header)          |
+ +----------------------------------------------------------------------------+
+ | Task              : Read Nalog Output  Header                              |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : WORD w_PCIBoardEepromAddress : PCI eeprom address      |
+ |																	 |
+-|		      PCHAR pc_PCIChipInformation  : PCI Chip Type.          |
++|		      char *pc_PCIChipInformation  : PCI Chip Type.          |
+ |																	 |
+ |			 str_AnalogInputHeader *s_Header:Anlog Input Header      |
+ |											   Pointer				 |
+@@ -1120,7 +1120,7 @@ INT i_EepromReadAnlogOutputHeader(WORD w_PCIBoardEepromAddress,
+ 
+ // Reads only for ONE  hardware component
+ INT i_EepromReadAnlogInputHeader(WORD w_PCIBoardEepromAddress,
+-	PCHAR pc_PCIChipInformation, WORD w_Address,
++	char *pc_PCIChipInformation, WORD w_Address,
+ 	str_AnalogInputHeader * s_Header)
+ {
+ 	WORD w_Temp, w_Offset;

commit 3019b4106bf8c2658343a84361f4f1abb6280633
+Author: Bill Pemberton 
+Date:   Thu Mar 19 18:00:47 2009 -0400
+
+    Staging: comedi: Remove use of VOID typedef in addi-data
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+index b3ad58e9df93..fb8e25d250a0 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+@@ -37,7 +37,6 @@
+ #define SUCCESS	1
+ 
+ /* variable type definition */
+-typedef void VOID, *PVOID;
+ typedef char CHAR, *PCHAR;
+ typedef const CHAR *PCSTR;
+ typedef unsigned char BYTE, *PBYTE;
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+index bf83af20f489..29026ab5c61d 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+@@ -148,12 +148,12 @@ INT i_EepromReadAnlogInputHeader(WORD w_PCIBoardEepromAddress,
+ 		/******************************************/
+ WORD w_EepromReadWord(WORD w_PCIBoardEepromAddress, PCHAR pc_PCIChipInformation,
+ 	WORD w_EepromStartAddress);
+-VOID v_EepromWaitBusy(WORD w_PCIBoardEepromAddress);
+-VOID v_EepromClock76(DWORD dw_Address, DWORD dw_RegisterValue);
+-VOID v_EepromWaitBusy(WORD w_PCIBoardEepromAddress);
+-VOID v_EepromSendCommand76(DWORD dw_Address, DWORD dw_EepromCommand,
++void v_EepromWaitBusy(WORD w_PCIBoardEepromAddress);
++void v_EepromClock76(DWORD dw_Address, DWORD dw_RegisterValue);
++void v_EepromWaitBusy(WORD w_PCIBoardEepromAddress);
++void v_EepromSendCommand76(DWORD dw_Address, DWORD dw_EepromCommand,
+ 	BYTE b_DataLengthInBits);
+-VOID v_EepromCs76Read(DWORD dw_Address, WORD w_offset, PWORD pw_Value);
++void v_EepromCs76Read(DWORD dw_Address, WORD w_offset, PWORD pw_Value);
+ 
+ /*
+ +----------------------------------------------------------------------------+
+@@ -357,7 +357,7 @@ WORD w_EepromReadWord(WORD w_PCIBoardEepromAddress, PCHAR pc_PCIChipInformation,
+ 
+ +----------------------------------------------------------------------------+
+ 
+-| Function   Name   : VOID v_EepromWaitBusy                                  |
++| Function   Name   : void v_EepromWaitBusy                                  |
+ 
+ |			(WORD	w_PCIBoardEepromAddress)                    	 |
+ 
+@@ -381,7 +381,7 @@ WORD w_EepromReadWord(WORD w_PCIBoardEepromAddress, PCHAR pc_PCIChipInformation,
+ 
+ */
+ 
+-VOID v_EepromWaitBusy(WORD w_PCIBoardEepromAddress)
++void v_EepromWaitBusy(WORD w_PCIBoardEepromAddress)
+ {
+ 
+ 	BYTE b_EepromBusy = 0;
+@@ -421,7 +421,7 @@ VOID v_EepromWaitBusy(WORD w_PCIBoardEepromAddress)
+ 
+ +---------------------------------------------------------------------------------+
+ 
+-| Function   Name   : VOID v_EepromClock76(DWORD dw_Address,                      |
++| Function   Name   : void v_EepromClock76(DWORD dw_Address,                      |
+ 
+ |					   DWORD dw_RegisterValue)                 			  |
+ 
+@@ -447,7 +447,7 @@ VOID v_EepromWaitBusy(WORD w_PCIBoardEepromAddress)
+ 
+ */
+ 
+-VOID v_EepromClock76(DWORD dw_Address, DWORD dw_RegisterValue)
++void v_EepromClock76(DWORD dw_Address, DWORD dw_RegisterValue)
+ {
+ 
+    /************************/
+@@ -488,7 +488,7 @@ VOID v_EepromClock76(DWORD dw_Address, DWORD dw_RegisterValue)
+ 
+ +---------------------------------------------------------------------------------+
+ 
+-| Function   Name   : VOID v_EepromSendCommand76(DWORD dw_Address,                |
++| Function   Name   : void v_EepromSendCommand76(DWORD dw_Address,                |
+ 
+ |					   DWORD   dw_EepromCommand,                		  |
+ 
+@@ -518,7 +518,7 @@ VOID v_EepromClock76(DWORD dw_Address, DWORD dw_RegisterValue)
+ 
+ */
+ 
+-VOID v_EepromSendCommand76(DWORD dw_Address, DWORD dw_EepromCommand,
++void v_EepromSendCommand76(DWORD dw_Address, DWORD dw_EepromCommand,
+ 	BYTE b_DataLengthInBits)
+ {
+ 
+@@ -623,7 +623,7 @@ VOID v_EepromSendCommand76(DWORD dw_Address, DWORD dw_EepromCommand,
+ 
+ +---------------------------------------------------------------------------------+
+ 
+-| Function   Name   : VOID v_EepromCs76Read(DWORD dw_Address,                     |
++| Function   Name   : void v_EepromCs76Read(DWORD dw_Address,                     |
+ 
+ |					   WORD    w_offset,                      			  |
+ 
+@@ -653,7 +653,7 @@ VOID v_EepromSendCommand76(DWORD dw_Address, DWORD dw_EepromCommand,
+ 
+ */
+ 
+-VOID v_EepromCs76Read(DWORD dw_Address, WORD w_offset, PWORD pw_Value)
++void v_EepromCs76Read(DWORD dw_Address, WORD w_offset, PWORD pw_Value)
+ {
+ 
+ 	CHAR c_BitPos = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+index 510323d7b7cb..3f8929c09070 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+@@ -196,7 +196,7 @@ void i_ADDI_AttachPCI1710(struct comedi_device * dev)
+ }
+ 
+ int i_APCI1710_Reset(struct comedi_device * dev);
+-VOID v_APCI1710_Interrupt(int irq, void *d);
++void v_APCI1710_Interrupt(int irq, void *d);
+ //for 1710
+ 
+ int i_APCI1710_Reset(struct comedi_device * dev)
+@@ -233,7 +233,7 @@ int i_APCI1710_Reset(struct comedi_device * dev)
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function's Name   : __VOID__ v_APCI1710_InterruptFunction                  |
++| Function's Name   : __void__ v_APCI1710_InterruptFunction                  |
+ |				(BYTE b_Interrupt, __CPPARGS)                |
+ +----------------------------------------------------------------------------+
+ | Task              : APCI-1710 interrupt function                           |
+@@ -247,7 +247,7 @@ int i_APCI1710_Reset(struct comedi_device * dev)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-VOID v_APCI1710_Interrupt(int irq, void *d)
++void v_APCI1710_Interrupt(int irq, void *d)
+ {
+ 	struct comedi_device *dev = d;
+ 	BYTE b_ModuleCpt = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+index 05ea0784d764..32796ceb946e 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+@@ -243,7 +243,7 @@ INT i_APCI1032_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ |			                                                     |
+ +----------------------------------------------------------------------------+
+ */
+-static VOID v_APCI1032_Interrupt(int irq, void *d)
++static void v_APCI1032_Interrupt(int irq, void *d)
+ {
+ 	struct comedi_device *dev = d;
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
+index d45707f3eaf2..659ef85088cd 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
+@@ -58,6 +58,6 @@ INT i_APCI1032_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_sub
+ 
+ // Interrupt functions.....
+ 
+-static VOID v_APCI1032_Interrupt(int irq, void *d);
++static void v_APCI1032_Interrupt(int irq, void *d);
+ //Reset
+ INT i_APCI1032_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+index c9035ceaade4..2d6adcff41e3 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+@@ -2576,7 +2576,7 @@ int i_APCI1500_ConfigureInterrupt(struct comedi_device * dev, struct comedi_subd
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-static VOID v_APCI1500_Interrupt(int irq, void *d)
++static void v_APCI1500_Interrupt(int irq, void *d)
+ {
+ 
+ 	struct comedi_device *dev = d;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+index da69bee176e6..a6b504c3d391 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+@@ -916,7 +916,7 @@ int i_APCI1564_ReadInterruptStatus(struct comedi_device * dev, struct comedi_sub
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-static VOID v_APCI1564_Interrupt(int irq, void *d)
++static void v_APCI1564_Interrupt(int irq, void *d)
+ {
+ 	struct comedi_device *dev = d;
+ 	UINT ui_DO, ui_DI;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
+index 2fbc8ce7b764..f0c461ca5396 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
+@@ -113,7 +113,7 @@ int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device *dev,
+ 					struct comedi_insn *insn, unsigned int *data);
+ 
+ // INTERRUPT
+-static VOID v_APCI1564_Interrupt(int irq, void *d);
++static void v_APCI1564_Interrupt(int irq, void *d);
+ 
+ // RESET
+ INT i_APCI1564_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
+index b6a3a999c906..9261aacd25f1 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
+@@ -63,8 +63,8 @@ int i_APCI2016_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *
+ 
+ // Interrupt functions.....
+ 
+-// VOID v_APCI2016_Interrupt(int irq, void *d) ;
++// void v_APCI2016_Interrupt(int irq, void *d) ;
+ 
+- //VOID v_APCI2016_Interrupt(int irq, void *d);
++ //void v_APCI2016_Interrupt(int irq, void *d);
+ // RESET
+ INT i_APCI2016_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+index b4a900308b96..1ff66bee548d 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+@@ -247,7 +247,7 @@ INT i_AddiHeaderRW_ReadEeprom(INT i_NbOfWordsToRead,
+ }
+ 
+ /*+----------------------------------------------------------------------------+*/
+-/*| Function   Name   : VOID v_GetAPCI3200EepromCalibrationValue (VOID)        |*/
++/*| Function   Name   : void v_GetAPCI3200EepromCalibrationValue (void)        |*/
+ /*+----------------------------------------------------------------------------+*/
+ /*| Task              : Read calibration value from the APCI-3200 eeprom.      |*/
+ /*+----------------------------------------------------------------------------+*/
+@@ -258,7 +258,7 @@ INT i_AddiHeaderRW_ReadEeprom(INT i_NbOfWordsToRead,
+ /*| Return Value      : -                                                      |*/
+ /*+----------------------------------------------------------------------------+*/
+ 
+-VOID v_GetAPCI3200EepromCalibrationValue(DWORD dw_PCIBoardEepromAddress,
++void v_GetAPCI3200EepromCalibrationValue(DWORD dw_PCIBoardEepromAddress,
+ 	str_BoardInfos * BoardInformations)
+ {
+ 	WORD w_AnalogInputMainHeaderAddress;

commit 63aa142aca0e4b63347e91b8c6909fbad7e7c7ac
+Author: Bill Pemberton 
+Date:   Thu Mar 19 18:00:42 2009 -0400
+
+    Staging: comedi: Remove me4000_info_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
+index 8a2e109cde70..12481a032b9f 100644
+--- a/drivers/staging/comedi/drivers/me4000.c
++++ b/drivers/staging/comedi/drivers/me4000.c
+@@ -378,7 +378,7 @@ static int me4000_probe(struct comedi_device *dev, struct comedi_devconfig *it)
+ 	CALL_PDEBUG("In me4000_probe()\n");
+ 
+ 	/* Allocate private memory */
+-	if (alloc_private(dev, sizeof(me4000_info_t)) < 0)
++	if (alloc_private(dev, sizeof(struct me4000_info)) < 0)
+ 		return -ENOMEM;
+ 
+ 	/*
+diff --git a/drivers/staging/comedi/drivers/me4000.h b/drivers/staging/comedi/drivers/me4000.h
+index 6f167a7c9c82..733b19243c75 100644
+--- a/drivers/staging/comedi/drivers/me4000.h
++++ b/drivers/staging/comedi/drivers/me4000.h
+@@ -376,7 +376,7 @@ struct me4000_cnt_context {
+ 	unsigned long counter_2_reg;
+ };
+ 
+-typedef struct me4000_info {
++struct me4000_info {
+ 	unsigned long plx_regbase;	/*  PLX configuration space base address */
+ 	unsigned long me4000_regbase;	/*  Base address of the ME4000 */
+ 	unsigned long timer_regbase;	/*  Base address of the timer circuit */
+@@ -400,9 +400,9 @@ typedef struct me4000_info {
+ 	struct me4000_ao_context ao_context[4];	/*  Vector with analog output specific context */
+ 	struct me4000_dio_context dio_context;	/*  Digital I/O specific context */
+ 	struct me4000_cnt_context cnt_context;	/*  Counter specific context */
+-} me4000_info_t;
++};
+ 
+-#define info	((me4000_info_t *)dev->private)
++#define info	((struct me4000_info *)dev->private)
+ 
+ /*-----------------------------------------------------------------------------
+   Defines for analog input

commit 126974dc8c432535f9eef36956056b88a153bfb3
+Author: Bill Pemberton 
+Date:   Thu Mar 19 18:00:37 2009 -0400
+
+    Staging: comedi: Remove me4000_cnt_context_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/me4000.h b/drivers/staging/comedi/drivers/me4000.h
+index 22a25a463b8b..6f167a7c9c82 100644
+--- a/drivers/staging/comedi/drivers/me4000.h
++++ b/drivers/staging/comedi/drivers/me4000.h
+@@ -369,12 +369,12 @@ struct me4000_dio_context {
+ 	unsigned long port_3_reg;
+ };
+ 
+-typedef struct me4000_cnt_context {
++struct me4000_cnt_context {
+ 	unsigned long ctrl_reg;
+ 	unsigned long counter_0_reg;
+ 	unsigned long counter_1_reg;
+ 	unsigned long counter_2_reg;
+-} me4000_cnt_context_t;
++};
+ 
+ typedef struct me4000_info {
+ 	unsigned long plx_regbase;	/*  PLX configuration space base address */

commit ff585603bdca766398e24037e9375b76507e2e60
+Author: Bill Pemberton 
+Date:   Thu Mar 19 18:00:31 2009 -0400
+
+    Staging: comedi: Remove me4000_dio_context_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/me4000.h b/drivers/staging/comedi/drivers/me4000.h
+index 6e6dc0e8f25e..22a25a463b8b 100644
+--- a/drivers/staging/comedi/drivers/me4000.h
++++ b/drivers/staging/comedi/drivers/me4000.h
+@@ -360,14 +360,14 @@ struct me4000_ai_context {
+ 	unsigned long sample_counter_reg;
+ };
+ 
+-typedef struct me4000_dio_context {
++struct me4000_dio_context {
+ 	unsigned long dir_reg;
+ 	unsigned long ctrl_reg;
+ 	unsigned long port_0_reg;
+ 	unsigned long port_1_reg;
+ 	unsigned long port_2_reg;
+ 	unsigned long port_3_reg;
+-} me4000_dio_context_t;
++};
+ 
+ typedef struct me4000_cnt_context {
+ 	unsigned long ctrl_reg;

commit 8b95a0e17f416e1db80c26ecd8f3e894ad271d0b
+Author: Bill Pemberton 
+Date:   Thu Mar 19 18:00:26 2009 -0400
+
+    Staging: comedi: Remove me4000_ai_context_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
+index 31f35e0eceb1..8a2e109cde70 100644
+--- a/drivers/staging/comedi/drivers/me4000.c
++++ b/drivers/staging/comedi/drivers/me4000.c
+@@ -1745,7 +1745,7 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id PT_REGS_ARG)
+ 	unsigned int tmp;
+ 	struct comedi_device *dev = dev_id;
+ 	struct comedi_subdevice *s = dev->subdevices;
+-	me4000_ai_context_t *ai_context = &info->ai_context;
++	struct me4000_ai_context *ai_context = &info->ai_context;
+ 	int i;
+ 	int c = 0;
+ 	long lval;
+diff --git a/drivers/staging/comedi/drivers/me4000.h b/drivers/staging/comedi/drivers/me4000.h
+index db38c9915d39..6e6dc0e8f25e 100644
+--- a/drivers/staging/comedi/drivers/me4000.h
++++ b/drivers/staging/comedi/drivers/me4000.h
+@@ -342,7 +342,7 @@ struct me4000_ao_context {
+ 	unsigned long preload_reg;
+ };
+ 
+-typedef struct me4000_ai_context {
++struct me4000_ai_context {
+ 	int irq;
+ 
+ 	unsigned long ctrl_reg;
+@@ -358,7 +358,7 @@ typedef struct me4000_ai_context {
+ 	unsigned long start_reg;
+ 	unsigned long irq_status_reg;
+ 	unsigned long sample_counter_reg;
+-} me4000_ai_context_t;
++};
+ 
+ typedef struct me4000_dio_context {
+ 	unsigned long dir_reg;

commit 21921108bef40b75495301f5dd3d992ed66a7ba8
+Author: Bill Pemberton 
+Date:   Thu Mar 19 18:00:21 2009 -0400
+
+    Staging: comedi: Remove me4000_ao_context_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/me4000.h b/drivers/staging/comedi/drivers/me4000.h
+index 27c48ff2b212..db38c9915d39 100644
+--- a/drivers/staging/comedi/drivers/me4000.h
++++ b/drivers/staging/comedi/drivers/me4000.h
+@@ -328,7 +328,7 @@ struct me4000_board {
+   Global board and subdevice information structures
+   ===========================================================================*/
+ 
+-typedef struct me4000_ao_context {
++struct me4000_ao_context {
+ 	int irq;
+ 
+ 	unsigned long mirror;	/*  Store the last written value */
+@@ -340,7 +340,7 @@ typedef struct me4000_ao_context {
+ 	unsigned long timer_reg;
+ 	unsigned long irq_status_reg;
+ 	unsigned long preload_reg;
+-} me4000_ao_context_t;
++};
+ 
+ typedef struct me4000_ai_context {
+ 	int irq;

commit 27f4caaa3b27badb3e245a50b09ba35f040f3a77
+Author: Bill Pemberton 
+Date:   Thu Mar 19 18:00:16 2009 -0400
+
+    Staging: comedi: Remove me4000_board_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
+index d0a17a1adfc2..31f35e0eceb1 100644
+--- a/drivers/staging/comedi/drivers/me4000.c
++++ b/drivers/staging/comedi/drivers/me4000.c
+@@ -92,7 +92,7 @@ static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table) = {
+ 
+ MODULE_DEVICE_TABLE(pci, me4000_pci_table);
+ 
+-static const me4000_board_t me4000_boards[] = {
++static const struct me4000_board me4000_boards[] = {
+ 	{"ME-4650", 0x4650, {0, 0}, {16, 0, 0, 0}, {4}, {0}},
+ 
+ 	{"ME-4660", 0x4660, {0, 0}, {32, 0, 16, 0}, {4}, {3}},
+@@ -113,7 +113,7 @@ static const me4000_board_t me4000_boards[] = {
+ 	{0},
+ };
+ 
+-#define ME4000_BOARD_VERSIONS (sizeof(me4000_boards) / sizeof(me4000_board_t) - 1)
++#define ME4000_BOARD_VERSIONS (sizeof(me4000_boards) / sizeof(struct me4000_board) - 1)
+ 
+ /*-----------------------------------------------------------------------------
+   Comedi function prototypes
+@@ -373,7 +373,7 @@ static int me4000_probe(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct pci_dev *pci_device;
+ 	int result, i;
+-	me4000_board_t *board;
++	struct me4000_board *board;
+ 
+ 	CALL_PDEBUG("In me4000_probe()\n");
+ 
+@@ -405,7 +405,7 @@ static int me4000_probe(struct comedi_device *dev, struct comedi_devconfig *it)
+ 						}
+ 					}
+ 					dev->board_ptr = me4000_boards + i;
+-					board = (me4000_board_t *) dev->
++					board = (struct me4000_board *) dev->
+ 						board_ptr;
+ 					info->pci_dev_p = pci_device;
+ 					goto found;
+diff --git a/drivers/staging/comedi/drivers/me4000.h b/drivers/staging/comedi/drivers/me4000.h
+index d1c36e2f97b4..27c48ff2b212 100644
+--- a/drivers/staging/comedi/drivers/me4000.h
++++ b/drivers/staging/comedi/drivers/me4000.h
+@@ -313,16 +313,16 @@ struct me4000_cnt_info {
+ 	int count;
+ };
+ 
+-typedef struct me4000_board {
++struct me4000_board {
+ 	const char *name;
+ 	unsigned short device_id;
+ 	struct me4000_ao_info ao;
+ 	struct me4000_ai_info ai;
+ 	struct me4000_dio_info dio;
+ 	struct me4000_cnt_info cnt;
+-} me4000_board_t;
++};
+ 
+-#define thisboard ((const me4000_board_t *)dev->board_ptr)
++#define thisboard ((const struct me4000_board *)dev->board_ptr)
+ 
+ /*=============================================================================
+   Global board and subdevice information structures

commit 79dcd042246ea49879bc9c15ed6592848f2f3828
+Author: Bill Pemberton 
+Date:   Thu Mar 19 18:00:10 2009 -0400
+
+    Staging: comedi: Remove me4000_cnt_info_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/me4000.h b/drivers/staging/comedi/drivers/me4000.h
+index a17b910acdac..d1c36e2f97b4 100644
+--- a/drivers/staging/comedi/drivers/me4000.h
++++ b/drivers/staging/comedi/drivers/me4000.h
+@@ -309,9 +309,9 @@ struct me4000_dio_info {
+ 	int count;
+ };
+ 
+-typedef struct me4000_cnt_info {
++struct me4000_cnt_info {
+ 	int count;
+-} me4000_cnt_info_t;
++};
+ 
+ typedef struct me4000_board {
+ 	const char *name;
+@@ -319,7 +319,7 @@ typedef struct me4000_board {
+ 	struct me4000_ao_info ao;
+ 	struct me4000_ai_info ai;
+ 	struct me4000_dio_info dio;
+-	me4000_cnt_info_t cnt;
++	struct me4000_cnt_info cnt;
+ } me4000_board_t;
+ 
+ #define thisboard ((const me4000_board_t *)dev->board_ptr)

commit e81d65b30ccc3f663f7bb3158567c247c3084ece
+Author: Bill Pemberton 
+Date:   Thu Mar 19 18:00:05 2009 -0400
+
+    Staging: comedi: Remove me4000_dio_info_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/me4000.h b/drivers/staging/comedi/drivers/me4000.h
+index 1c9dc1d7f214..a17b910acdac 100644
+--- a/drivers/staging/comedi/drivers/me4000.h
++++ b/drivers/staging/comedi/drivers/me4000.h
+@@ -305,9 +305,9 @@ struct me4000_ai_info {
+ 	int ex_trig_analog;
+ };
+ 
+-typedef struct me4000_dio_info {
++struct me4000_dio_info {
+ 	int count;
+-} me4000_dio_info_t;
++};
+ 
+ typedef struct me4000_cnt_info {
+ 	int count;
+@@ -318,7 +318,7 @@ typedef struct me4000_board {
+ 	unsigned short device_id;
+ 	struct me4000_ao_info ao;
+ 	struct me4000_ai_info ai;
+-	me4000_dio_info_t dio;
++	struct me4000_dio_info dio;
+ 	me4000_cnt_info_t cnt;
+ } me4000_board_t;
+ 

commit 0c18e8c046b5ec21e9e0b458807db260309a8f5d
+Author: Bill Pemberton 
+Date:   Thu Mar 19 18:00:00 2009 -0400
+
+    Staging: comedi: Remove me4000_ai_info_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/me4000.h b/drivers/staging/comedi/drivers/me4000.h
+index ed24d34bc27e..1c9dc1d7f214 100644
+--- a/drivers/staging/comedi/drivers/me4000.h
++++ b/drivers/staging/comedi/drivers/me4000.h
+@@ -298,12 +298,12 @@ struct me4000_ao_info {
+ 	int fifo_count;
+ };
+ 
+-typedef struct me4000_ai_info {
++struct me4000_ai_info {
+ 	int count;
+ 	int sh_count;
+ 	int diff_count;
+ 	int ex_trig_analog;
+-} me4000_ai_info_t;
++};
+ 
+ typedef struct me4000_dio_info {
+ 	int count;
+@@ -317,7 +317,7 @@ typedef struct me4000_board {
+ 	const char *name;
+ 	unsigned short device_id;
+ 	struct me4000_ao_info ao;
+-	me4000_ai_info_t ai;
++	struct me4000_ai_info ai;
+ 	me4000_dio_info_t dio;
+ 	me4000_cnt_info_t cnt;
+ } me4000_board_t;

commit 8d95123295fde18ac22cfeb8eaa0dcc05898b35b
+Author: Bill Pemberton 
+Date:   Thu Mar 19 17:59:55 2009 -0400
+
+    Staging: comedi: Remove me4000_ao_info_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/me4000.h b/drivers/staging/comedi/drivers/me4000.h
+index 37af3a80263a..ed24d34bc27e 100644
+--- a/drivers/staging/comedi/drivers/me4000.h
++++ b/drivers/staging/comedi/drivers/me4000.h
+@@ -293,10 +293,10 @@
+   Information about the hardware capabilities
+   ===========================================================================*/
+ 
+-typedef struct me4000_ao_info {
++struct me4000_ao_info {
+ 	int count;
+ 	int fifo_count;
+-} me4000_ao_info_t;
++};
+ 
+ typedef struct me4000_ai_info {
+ 	int count;
+@@ -316,7 +316,7 @@ typedef struct me4000_cnt_info {
+ typedef struct me4000_board {
+ 	const char *name;
+ 	unsigned short device_id;
+-	me4000_ao_info_t ao;
++	struct me4000_ao_info ao;
+ 	me4000_ai_info_t ai;
+ 	me4000_dio_info_t dio;
+ 	me4000_cnt_info_t cnt;

commit 05d21f4af416d9c7e1c8458a00efd69e44c3dc8c
+Author: Bill Pemberton 
+Date:   Thu Mar 19 17:59:49 2009 -0400
+
+    Staging: comedi: Remove das08_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/das08.h b/drivers/staging/comedi/drivers/das08.h
+index 9f82527ec834..69089ce690f2 100644
+--- a/drivers/staging/comedi/drivers/das08.h
++++ b/drivers/staging/comedi/drivers/das08.h
+@@ -30,7 +30,7 @@ enum das08_ai_encoding { das08_encode12, das08_encode16, das08_pcm_encode12 };
+ enum das08_lrange { das08_pg_none, das08_bipolar5, das08_pgh, das08_pgl,
+ 		das08_pgm };
+ 
+-typedef struct das08_board_struct {
++struct das08_board_struct {
+ 	const char *name;
+ 	unsigned int id;	// id for pci/pcmcia boards
+ 	enum das08_bustype bustype;
+@@ -46,7 +46,7 @@ typedef struct das08_board_struct {
+ 	unsigned int i8255_offset;
+ 	unsigned int i8254_offset;
+ 	unsigned int iosize;	// number of ioports used
+-} das08_board;
++};
+ 
+ struct i8254_struct {
+ 	int channels;		// available channels. Some could be used internally.

commit 2e93aa5b5b8050090a22e162f9af6b18ca3ec47a
+Author: Bill Pemberton 
+Date:   Thu Mar 19 17:59:44 2009 -0400
+
+    Staging: comedi: Remove nidio96_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
+index 639c1676a805..87def2cc9a29 100644
+--- a/drivers/staging/comedi/drivers/ni_pcidio.c
++++ b/drivers/staging/comedi/drivers/ni_pcidio.c
+@@ -390,7 +390,7 @@ static DEFINE_PCI_DEVICE_TABLE(ni_pcidio_pci_table) = {
+ 
+ MODULE_DEVICE_TABLE(pci, ni_pcidio_pci_table);
+ 
+-typedef struct {
++struct nidio96_private {
+ 	struct mite_struct *mite;
+ 	int boardtype;
+ 	int dio;
+@@ -398,8 +398,8 @@ typedef struct {
+ 	struct mite_channel *di_mite_chan;
+ 	struct mite_dma_descriptor_ring *di_mite_ring;
+ 	spinlock_t mite_channel_lock;
+-} nidio96_private;
+-#define devpriv ((nidio96_private *)dev->private)
++};
++#define devpriv ((struct nidio96_private *)dev->private)
+ 
+ static int ni_pcidio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_cmd * cmd);
+@@ -1161,7 +1161,7 @@ static int nidio_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 
+ 	printk("comedi%d: nidio:", dev->minor);
+ 
+-	if ((ret = alloc_private(dev, sizeof(nidio96_private))) < 0)
++	if ((ret = alloc_private(dev, sizeof(struct nidio96_private))) < 0)
+ 		return ret;
+ 	spin_lock_init(&devpriv->mite_channel_lock);
+ 

commit 30570f0dee2b0e3ede09e08eb5dfd514317a7587
+Author: Bill Pemberton 
+Date:   Thu Mar 19 17:59:39 2009 -0400
+
+    Staging: comedi: ni_daq_700.c: Remove local_info_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
+index 1e40348430ea..61a31ad2d030 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_700.c
++++ b/drivers/staging/comedi/drivers/ni_daq_700.c
+@@ -479,12 +479,12 @@ static void dio700_cs_detach(struct pcmcia_device *);
+ 
+ static const dev_info_t dev_info = "ni_daq_700";
+ 
+-typedef struct local_info_t {
++struct local_info_t {
+ 	struct pcmcia_device *link;
+ 	dev_node_t node;
+ 	int stop;
+ 	struct bus_operations *bus;
+-} local_info_t;
++};
+ 
+ /*======================================================================
+ 
+@@ -500,14 +500,14 @@ typedef struct local_info_t {
+ 
+ static int dio700_cs_attach(struct pcmcia_device *link)
+ {
+-	local_info_t *local;
++	struct local_info_t *local;
+ 
+ 	printk(KERN_INFO "ni_daq_700:  cs-attach\n");
+ 
+ 	DEBUG(0, "dio700_cs_attach()\n");
+ 
+ 	/* Allocate space for private device-specific data */
+-	local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
++	local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
+ 	if (!local)
+ 		return -ENOMEM;
+ 	local->link = link;
+@@ -552,11 +552,11 @@ static void dio700_cs_detach(struct pcmcia_device *link)
+ 	DEBUG(0, "dio700_cs_detach(0x%p)\n", link);
+ 
+ 	if (link->dev_node) {
+-		((local_info_t *) link->priv)->stop = 1;
++		((struct local_info_t *) link->priv)->stop = 1;
+ 		dio700_release(link);
+ 	}
+ 
+-	/* This points to the parent local_info_t struct */
++	/* This points to the parent struct local_info_t struct */
+ 	if (link->priv)
+ 		kfree(link->priv);
+ 
+@@ -572,7 +572,7 @@ static void dio700_cs_detach(struct pcmcia_device *link)
+ 
+ static void dio700_config(struct pcmcia_device *link)
+ {
+-	local_info_t *dev = link->priv;
++	struct local_info_t *dev = link->priv;
+ 	tuple_t tuple;
+ 	cisparse_t parse;
+ 	int last_ret;
+@@ -772,7 +772,7 @@ static void dio700_release(struct pcmcia_device *link)
+ 
+ static int dio700_cs_suspend(struct pcmcia_device *link)
+ {
+-	local_info_t *local = link->priv;
++	struct local_info_t *local = link->priv;
+ 
+ 	/* Mark the device as stopped, to block IO until later */
+ 	local->stop = 1;
+@@ -781,7 +781,7 @@ static int dio700_cs_suspend(struct pcmcia_device *link)
+ 
+ static int dio700_cs_resume(struct pcmcia_device *link)
+ {
+-	local_info_t *local = link->priv;
++	struct local_info_t *local = link->priv;
+ 
+ 	local->stop = 0;
+ 	return 0;

commit 4cab3740734fb8582fa68f899105790c05935b55
+Author: Bill Pemberton 
+Date:   Thu Mar 19 17:59:34 2009 -0400
+
+    Staging: comedi: Remove dio700_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
+index 41c1e1ab5c00..1e40348430ea 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_700.c
++++ b/drivers/staging/comedi/drivers/ni_daq_700.c
+@@ -60,7 +60,7 @@ static int dio700_detach(struct comedi_device * dev);
+ 
+ enum dio700_bustype { pcmcia_bustype };
+ 
+-typedef struct dio700_board_struct {
++struct dio700_board {
+ 	const char *name;
+ 	int device_id;		// device id for pcmcia board
+ 	enum dio700_bustype bustype;	// PCMCIA
+@@ -69,9 +69,9 @@ typedef struct dio700_board_struct {
+ 	// as appropriate
+ 	unsigned int (*read_byte) (unsigned int address);
+ 	void (*write_byte) (unsigned int byte, unsigned int address);
+-} dio700_board;
++};
+ 
+-static const dio700_board dio700_boards[] = {
++static const struct dio700_board dio700_boards[] = {
+ 	{
+ 	      name:	"daqcard-700",
+ 	      device_id:0x4743,// 0x10b is manufacturer id, 0x4743 is device id
+@@ -89,7 +89,7 @@ static const dio700_board dio700_boards[] = {
+ /*
+  * Useful for shorthand access to the particular board structure
+  */
+-#define thisboard ((const dio700_board *)dev->board_ptr)
++#define thisboard ((const struct dio700_board *)dev->board_ptr)
+ 
+ struct dio700_private {
+ 
+@@ -104,9 +104,9 @@ static struct comedi_driver driver_dio700 = {
+       module:THIS_MODULE,
+       attach:dio700_attach,
+       detach:dio700_detach,
+-      num_names:sizeof(dio700_boards) / sizeof(dio700_board),
++      num_names:sizeof(dio700_boards) / sizeof(struct dio700_board),
+       board_name:&dio700_boards[0].name,
+-      offset:sizeof(dio700_board),
++      offset:sizeof(struct dio700_board),
+ };
+ 
+ /*	the real driver routines	*/

commit 8c8a28852be4e876afdac208a41ab001dc817f99
+Author: Bill Pemberton 
+Date:   Thu Mar 19 17:59:28 2009 -0400
+
+    Staging: comedi: Remove atmio16d_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
+index 1e6eea5533c7..35fcd172af2e 100644
+--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
++++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
+@@ -100,7 +100,7 @@ Devices: [National Instruments] AT-MIO-16 (atmio16), AT-MIO-16D (atmio16d)
+ #define CLOCK_100_HZ	0x8F25
+ /* Other miscellaneous defines */
+ #define ATMIO16D_SIZE	32	/* bus address range */
+-#define devpriv ((atmio16d_private *)dev->private)
++#define devpriv ((struct atmio16d_private *)dev->private)
+ #define ATMIO16D_TIMEOUT 10
+ 
+ struct atmio16_board_t {
+@@ -174,7 +174,7 @@ static const struct comedi_lrange range_atmio16d_ai_unipolar = { 4, {
+ };
+ 
+ /* private data struct */
+-typedef struct {
++struct atmio16d_private {
+ 	enum { adc_diff, adc_singleended } adc_mux;
+ 	enum { adc_bipolar10, adc_bipolar5, adc_unipolar10 } adc_range;
+ 	enum { adc_2comp, adc_straight } adc_coding;
+@@ -185,7 +185,7 @@ typedef struct {
+ 	unsigned int ao_readback[2];
+ 	unsigned int com_reg_1_state;	/* current state of command register 1 */
+ 	unsigned int com_reg_2_state;	/* current state of command register 2 */
+-} atmio16d_private;
++};
+ 
+ static void reset_counters(struct comedi_device * dev)
+ {
+@@ -728,7 +728,7 @@ static int atmio16d_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 
+ 	if ((ret = alloc_subdevices(dev, 4)) < 0)
+ 		return ret;
+-	if ((ret = alloc_private(dev, sizeof(atmio16d_private))) < 0)
++	if ((ret = alloc_private(dev, sizeof(struct atmio16d_private))) < 0)
+ 		return ret;
+ 
+ 	/* reset the atmio16d hardware */

commit 01983c39f023efa7204eb6b61480d5c495124240
+Author: Bill Pemberton 
+Date:   Thu Mar 19 17:59:23 2009 -0400
+
+    Staging: comedi: Remove atao_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c
+index efacfda03b2f..2cc46b672588 100644
+--- a/drivers/staging/comedi/drivers/ni_at_ao.c
++++ b/drivers/staging/comedi/drivers/ni_at_ao.c
+@@ -151,11 +151,12 @@ Configuration options:
+  * boards in this way is optional, and completely driver-dependent.
+  * Some drivers use arrays such as this, other do not.
+  */
+-typedef struct atao_board_struct {
++struct atao_board {
+ 	const char *name;
+ 	int n_ao_chans;
+-} atao_board;
+-static const atao_board atao_boards[] = {
++};
++
++static const struct atao_board atao_boards[] = {
+ 	{
+ 	      name:	"ai-ao-6",
+ 	      n_ao_chans:6,
+@@ -166,7 +167,7 @@ static const atao_board atao_boards[] = {
+ 		},
+ };
+ 
+-#define thisboard ((atao_board *)dev->board_ptr)
++#define thisboard ((struct atao_board *)dev->board_ptr)
+ 
+ struct atao_private {
+ 
+@@ -188,8 +189,8 @@ static struct comedi_driver driver_atao = {
+       attach:atao_attach,
+       detach:atao_detach,
+       board_name:&atao_boards[0].name,
+-      offset:sizeof(atao_board),
+-      num_names:sizeof(atao_boards) / sizeof(atao_board),
++      offset:sizeof(struct atao_board),
++      num_names:sizeof(atao_boards) / sizeof(struct atao_board),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_atao);

commit 92b635c5bea18d7eb3c46bfdcc930d9d86d3d177
+Author: Bill Pemberton 
+Date:   Thu Mar 19 17:59:18 2009 -0400
+
+    Staging: comedi: Remove a2150_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
+index ed5f5576d992..5d45bf24a5ef 100644
+--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
++++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
+@@ -119,12 +119,12 @@ TRIG_WAKE_EOS
+ #define I8253_MODE_REG		0x17
+ #define   HW_COUNT_DISABLE		0x30	// disable hardware counting of conversions
+ 
+-typedef struct a2150_board_struct {
++struct a2150_board {
+ 	const char *name;
+ 	int clock[4];		// master clock periods, in nanoseconds
+ 	int num_clocks;		// number of available master clock speeds
+ 	int ai_speed;		// maximum conversion rate in nanoseconds
+-} a2150_board;
++};
+ 
+ //analog input range
+ static const struct comedi_lrange range_a2150 = {
+@@ -136,7 +136,7 @@ static const struct comedi_lrange range_a2150 = {
+ 
+ // enum must match board indices
+ enum { a2150_c, a2150_s };
+-static const a2150_board a2150_boards[] = {
++static const struct a2150_board a2150_boards[] = {
+ 	{
+ 	      name:	"at-a2150c",
+ 	      clock:	{31250, 22676, 20833, 19531},
+@@ -154,7 +154,7 @@ static const a2150_board a2150_boards[] = {
+ /*
+  * Useful for shorthand access to the particular board structure
+  */
+-#define thisboard ((const a2150_board *)dev->board_ptr)
++#define thisboard ((const struct a2150_board *)dev->board_ptr)
+ 
+ struct a2150_private {
+ 

commit 43313b07343b81463c8edd99a8c315c6dc2d5c7d
+Author: Bill Pemberton 
+Date:   Thu Mar 19 17:59:12 2009 -0400
+
+    Staging: comedi: Remove ni_670x_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
+index dbadb8e8e1e6..d1312e073a65 100644
+--- a/drivers/staging/comedi/drivers/ni_670x.c
++++ b/drivers/staging/comedi/drivers/ni_670x.c
+@@ -60,13 +60,14 @@ Commands are not supported.
+ 
+ /* Board description*/
+ 
+-typedef struct ni_670x_board_struct {
++struct ni_670x_board {
+ 	unsigned short dev_id;
+ 	const char *name;
+ 	unsigned short ao_chans;
+ 	unsigned short ao_bits;
+-} ni_670x_board;
+-static const ni_670x_board ni_670x_boards[] = {
++};
++
++static const struct ni_670x_board ni_670x_boards[] = {
+ 	{
+ 	      dev_id:	0x2c90,
+ 	      name:	"PCI-6703",
+@@ -96,7 +97,7 @@ static DEFINE_PCI_DEVICE_TABLE(ni_670x_pci_table) = {
+ 
+ MODULE_DEVICE_TABLE(pci, ni_670x_pci_table);
+ 
+-#define thisboard ((ni_670x_board *)dev->board_ptr)
++#define thisboard ((struct ni_670x_board *)dev->board_ptr)
+ 
+ struct ni_670x_private {
+ 

commit b3be94eade6d07270e2a89599f99d42bbcfd6e84
+Author: Bill Pemberton 
+Date:   Thu Mar 19 17:59:07 2009 -0400
+
+    Staging: comedi: Remove ni_660x_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
+index dabafa641e7e..14e35ba721e9 100644
+--- a/drivers/staging/comedi/drivers/ni_660x.c
++++ b/drivers/staging/comedi/drivers/ni_660x.c
+@@ -421,7 +421,7 @@ static DEFINE_PCI_DEVICE_TABLE(ni_660x_pci_table) = {
+ 
+ MODULE_DEVICE_TABLE(pci, ni_660x_pci_table);
+ 
+-typedef struct {
++struct ni_660x_private {
+ 	struct mite_struct *mite;
+ 	struct ni_gpct_device *counter_dev;
+ 	uint64_t pfi_direction_bits;
+@@ -431,9 +431,9 @@ typedef struct {
+ 	unsigned dma_configuration_soft_copies[NI_660X_MAX_NUM_CHIPS];
+ 	spinlock_t soft_reg_copy_lock;
+ 	unsigned short pfi_output_selects[NUM_PFI_CHANNELS];
+-} ni_660x_private;
++};
+ 
+-static inline ni_660x_private *private(struct comedi_device * dev)
++static inline struct ni_660x_private *private(struct comedi_device * dev)
+ {
+ 	return dev->private;
+ }
+@@ -765,7 +765,7 @@ static unsigned ni_gpct_read_register(struct ni_gpct *counter,
+ 		ni_660x_register);
+ }
+ 
+-static inline struct mite_dma_descriptor_ring *mite_ring(ni_660x_private * priv,
++static inline struct mite_dma_descriptor_ring *mite_ring(struct ni_660x_private * priv,
+ 	struct ni_gpct *counter)
+ {
+ 	return priv->mite_rings[counter->chip_index][counter->counter_index];
+@@ -943,7 +943,7 @@ static int ni_660x_allocate_private(struct comedi_device * dev)
+ 	int retval;
+ 	unsigned i;
+ 
+-	if ((retval = alloc_private(dev, sizeof(ni_660x_private))) < 0)
++	if ((retval = alloc_private(dev, sizeof(struct ni_660x_private))) < 0)
+ 		return retval;
+ 	spin_lock_init(&private(dev)->mite_channel_lock);
+ 	spin_lock_init(&private(dev)->soft_reg_copy_lock);

commit 50792813130b94a64e34b89cd2cbfddeb85b7518
+Author: Bill Pemberton 
+Date:   Thu Mar 19 17:59:02 2009 -0400
+
+    Staging: comedi: Remove ni_660x_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
+index 44036069a548..dabafa641e7e 100644
+--- a/drivers/staging/comedi/drivers/ni_660x.c
++++ b/drivers/staging/comedi/drivers/ni_660x.c
+@@ -379,13 +379,13 @@ static const unsigned GPCT_OFFSET[2] = { 0x0, 0x800 };	/* First chip is at base-
+ 							   0x00, etc. */
+ 
+ /* Board description*/
+-typedef struct {
++struct ni_660x_board {
+ 	unsigned short dev_id;	/* `lspci` will show you this */
+ 	const char *name;
+ 	unsigned n_chips;	/* total number of TIO chips */
+-} ni_660x_board;
++};
+ 
+-static const ni_660x_board ni_660x_boards[] = {
++static const struct ni_660x_board ni_660x_boards[] = {
+ 	{
+ 	      dev_id:	0x2c60,
+ 	      name:	"PCI-6601",
+@@ -439,7 +439,7 @@ static inline ni_660x_private *private(struct comedi_device * dev)
+ }
+ 
+ /* initialized in ni_660x_find_device() */
+-static inline const ni_660x_board *board(struct comedi_device * dev)
++static inline const struct ni_660x_board *board(struct comedi_device * dev)
+ {
+ 	return dev->board_ptr;
+ }

commit 251411cf05f3e7630f600a89f51fe9a82da967f8
+Author: Bill Pemberton 
+Date:   Thu Mar 19 17:58:57 2009 -0400
+
+    Staging: comedi: Remove NI_660x_Register typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
+index 2a3c1302d620..44036069a548 100644
+--- a/drivers/staging/comedi/drivers/ni_660x.c
++++ b/drivers/staging/comedi/drivers/ni_660x.c
+@@ -55,7 +55,7 @@ enum ni_660x_constants {
+ #define MAX_DMA_CHANNEL 4
+ 
+ /* See Register-Level Programmer Manual page 3.1 */
+-typedef enum {
++enum NI_660x_Register {
+ 	G0InterruptAcknowledge,
+ 	G0StatusRegister,
+ 	G1InterruptAcknowledge,
+@@ -155,7 +155,7 @@ typedef enum {
+ 	IOConfigReg36_37,
+ 	IOConfigReg38_39,
+ 	NumRegisters,
+-} NI_660x_Register;
++};
+ 
+ static inline unsigned IOConfigReg(unsigned pfi_channel)
+ {
+@@ -484,9 +484,9 @@ static inline unsigned ni_660x_num_counters(struct comedi_device * dev)
+ 	return board(dev)->n_chips * counters_per_chip;
+ }
+ 
+-static NI_660x_Register ni_gpct_to_660x_register(enum ni_gpct_register reg)
++static enum NI_660x_Register ni_gpct_to_660x_register(enum ni_gpct_register reg)
+ {
+-	NI_660x_Register ni_660x_register;
++	enum NI_660x_Register ni_660x_register;
+ 	switch (reg) {
+ 	case NITIO_G0_Autoincrement_Reg:
+ 		ni_660x_register = G0AutoincrementRegister;
+@@ -703,7 +703,7 @@ static NI_660x_Register ni_gpct_to_660x_register(enum ni_gpct_register reg)
+ }
+ 
+ static inline void ni_660x_write_register(struct comedi_device * dev,
+-	unsigned chip_index, unsigned bits, NI_660x_Register reg)
++	unsigned chip_index, unsigned bits, enum NI_660x_Register reg)
+ {
+ 	void *const write_address =
+ 		private(dev)->mite->daq_io_addr + GPCT_OFFSET[chip_index] +
+@@ -725,7 +725,7 @@ static inline void ni_660x_write_register(struct comedi_device * dev,
+ }
+ 
+ static inline unsigned ni_660x_read_register(struct comedi_device * dev,
+-	unsigned chip_index, NI_660x_Register reg)
++	unsigned chip_index, enum NI_660x_Register reg)
+ {
+ 	void *const read_address =
+ 		private(dev)->mite->daq_io_addr + GPCT_OFFSET[chip_index] +
+@@ -751,7 +751,7 @@ static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits,
+ 	enum ni_gpct_register reg)
+ {
+ 	struct comedi_device *dev = counter->counter_dev->dev;
+-	NI_660x_Register ni_660x_register = ni_gpct_to_660x_register(reg);
++	enum NI_660x_Register ni_660x_register = ni_gpct_to_660x_register(reg);
+ 	ni_660x_write_register(dev, counter->chip_index, bits,
+ 		ni_660x_register);
+ }
+@@ -760,7 +760,7 @@ static unsigned ni_gpct_read_register(struct ni_gpct *counter,
+ 	enum ni_gpct_register reg)
+ {
+ 	struct comedi_device *dev = counter->counter_dev->dev;
+-	NI_660x_Register ni_660x_register = ni_gpct_to_660x_register(reg);
++	enum NI_660x_Register ni_660x_register = ni_gpct_to_660x_register(reg);
+ 	return ni_660x_read_register(dev, counter->chip_index,
+ 		ni_660x_register);
+ }

commit 6179e3e9bbec5df830ccca3970df80967347b410
+Author: Bill Pemberton 
+Date:   Thu Mar 19 17:58:51 2009 -0400
+
+    Staging: comedi: Remove ni_65xx_subdevice_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
+index 4f6e77879338..6e85da16a241 100644
+--- a/drivers/staging/comedi/drivers/ni_65xx.c
++++ b/drivers/staging/comedi/drivers/ni_65xx.c
+@@ -295,17 +295,18 @@ static inline struct ni_65xx_private *private(struct comedi_device * dev)
+ 	return dev->private;
+ }
+ 
+-typedef struct {
++struct ni_65xx_subdevice_private {
+ 	unsigned base_port;
+-} ni_65xx_subdevice_private;
+-static inline ni_65xx_subdevice_private *sprivate(struct comedi_subdevice * subdev)
++};
++
++static inline struct ni_65xx_subdevice_private *sprivate(struct comedi_subdevice * subdev)
+ {
+ 	return subdev->private;
+ }
+-static ni_65xx_subdevice_private *ni_65xx_alloc_subdevice_private(void)
++static struct ni_65xx_subdevice_private *ni_65xx_alloc_subdevice_private(void)
+ {
+-	ni_65xx_subdevice_private *subdev_private =
+-		kzalloc(sizeof(ni_65xx_subdevice_private), GFP_KERNEL);
++	struct ni_65xx_subdevice_private *subdev_private =
++		kzalloc(sizeof(struct ni_65xx_subdevice_private), GFP_KERNEL);
+ 	if (subdev_private == NULL)
+ 		return NULL;
+ 	return subdev_private;

commit 47c30a2cc336d493d624d8437f41c19a270bb672
+Author: Bill Pemberton 
+Date:   Thu Mar 19 17:58:46 2009 -0400
+
+    Staging: comedi: Remove ni_65xx_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
+index c5fac96f25dd..4f6e77879338 100644
+--- a/drivers/staging/comedi/drivers/ni_65xx.c
++++ b/drivers/staging/comedi/drivers/ni_65xx.c
+@@ -282,14 +282,15 @@ static DEFINE_PCI_DEVICE_TABLE(ni_65xx_pci_table) = {
+ 
+ MODULE_DEVICE_TABLE(pci, ni_65xx_pci_table);
+ 
+-typedef struct {
++struct ni_65xx_private {
+ 	struct mite_struct *mite;
+ 	unsigned int filter_interval;
+ 	unsigned short filter_enable[NI_65XX_MAX_NUM_PORTS];
+ 	unsigned short output_bits[NI_65XX_MAX_NUM_PORTS];
+ 	unsigned short dio_direction[NI_65XX_MAX_NUM_PORTS];
+-} ni_65xx_private;
+-static inline ni_65xx_private *private(struct comedi_device * dev)
++};
++
++static inline struct ni_65xx_private *private(struct comedi_device * dev)
+ {
+ 	return dev->private;
+ }
+@@ -625,7 +626,7 @@ static int ni_65xx_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 
+ 	printk("comedi%d: ni_65xx:", dev->minor);
+ 
+-	if ((ret = alloc_private(dev, sizeof(ni_65xx_private))) < 0)
++	if ((ret = alloc_private(dev, sizeof(struct ni_65xx_private))) < 0)
+ 		return ret;
+ 
+ 	ret = ni_65xx_find_device(dev, it->options[0], it->options[1]);

commit f4c6b31958afecc08c8e83f3bc25161ce4442542
+Author: Bill Pemberton 
+Date:   Thu Mar 19 17:58:41 2009 -0400
+
+    Staging: comedi: Remove ni6527_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
+index 0d07c8514336..e01ecb6760f9 100644
+--- a/drivers/staging/comedi/drivers/ni_6527.c
++++ b/drivers/staging/comedi/drivers/ni_6527.c
+@@ -112,12 +112,13 @@ static DEFINE_PCI_DEVICE_TABLE(ni6527_pci_table) = {
+ 
+ MODULE_DEVICE_TABLE(pci, ni6527_pci_table);
+ 
+-typedef struct {
++struct ni6527_private {
+ 	struct mite_struct *mite;
+ 	unsigned int filter_interval;
+ 	unsigned int filter_enable;
+-} ni6527_private;
+-#define devpriv ((ni6527_private *)dev->private)
++};
++
++#define devpriv ((struct ni6527_private *)dev->private)
+ 
+ static int ni6527_find_device(struct comedi_device * dev, int bus, int slot);
+ 
+@@ -370,7 +371,7 @@ static int ni6527_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 
+ 	printk("comedi%d: ni6527:", dev->minor);
+ 
+-	if ((ret = alloc_private(dev, sizeof(ni6527_private))) < 0)
++	if ((ret = alloc_private(dev, sizeof(struct ni6527_private))) < 0)
+ 		return ret;
+ 
+ 	ret = ni6527_find_device(dev, it->options[0], it->options[1]);

commit 97070b32a886d53b7343bcb28ed38d906fa95f50
+Author: Bill Pemberton 
+Date:   Thu Mar 19 17:58:25 2009 -0400
+
+    Staging: comedi: comedi: remove C99 comments in skel.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c
+index b2268aa49bc8..c7700d134cc1 100644
+--- a/drivers/staging/comedi/drivers/skel.c
++++ b/drivers/staging/comedi/drivers/skel.c
+@@ -215,7 +215,7 @@ static int skel_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+  * it is, this is the place to do it.  Otherwise, dev->board_ptr
+  * should already be initialized.
+  */
+-	//dev->board_ptr = skel_probe(dev, it);
++	/* dev->board_ptr = skel_probe(dev, it); */
+ 
+ /*
+  * Initialize dev->board_name.  Note that we can use the "thisboard"
+@@ -238,7 +238,7 @@ static int skel_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ 		return -ENOMEM;
+ 
+ 	s = dev->subdevices + 0;
+-	//dev->read_subdev=s;
++	/* dev->read_subdev=s; */
+ 	/* analog input subdevice */
+ 	s->type = COMEDI_SUBD_AI;
+ 	/* we support single-ended (ground) and differential */
+@@ -249,8 +249,10 @@ static int skel_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ 	s->len_chanlist = 16;	/* This is the maximum chanlist length that
+ 				   the board can handle */
+ 	s->insn_read = skel_ai_rinsn;
+-//      s->subdev_flags |= SDF_CMD_READ;
+-//      s->do_cmd = skel_ai_cmd;
++/*
++*       s->subdev_flags |= SDF_CMD_READ;
++*       s->do_cmd = skel_ai_cmd;
++*/
+ 	s->do_cmdtest = skel_ai_cmdtest;
+ 
+ 	s = dev->subdevices + 1;
+@@ -311,20 +313,20 @@ static int skel_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s
+ 	/* a typical programming sequence */
+ 
+ 	/* write channel to multiplexer */
+-	//outw(chan,dev->iobase + SKEL_MUX);
++	/* outw(chan,dev->iobase + SKEL_MUX); */
+ 
+ 	/* don't wait for mux to settle */
+ 
+ 	/* convert n samples */
+ 	for (n = 0; n < insn->n; n++) {
+ 		/* trigger conversion */
+-		//outw(0,dev->iobase + SKEL_CONVERT);
++		/* outw(0,dev->iobase + SKEL_CONVERT); */
+ 
+ #define TIMEOUT 100
+ 		/* wait for conversion to end */
+ 		for (i = 0; i < TIMEOUT; i++) {
+ 			status = 1;
+-			//status = inb(dev->iobase + SKEL_STATUS);
++			/* status = inb(dev->iobase + SKEL_STATUS); */
+ 			if (status)
+ 				break;
+ 		}
+@@ -336,7 +338,7 @@ static int skel_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s
+ 		}
+ 
+ 		/* read data */
+-		//d = inw(dev->iobase + SKEL_AI_DATA);
++		/* d = inw(dev->iobase + SKEL_AI_DATA); */
+ 		d = 0;
+ 
+ 		/* mangle the data as necessary */
+@@ -529,7 +531,7 @@ static int skel_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s
+ 	 * very useful, but that's how the interface is defined. */
+ 	for (i = 0; i < insn->n; i++) {
+ 		/* a typical programming sequence */
+-		//outw(data[i],dev->iobase + SKEL_DA0 + chan);
++		/* outw(data[i],dev->iobase + SKEL_DA0 + chan); */
+ 		devpriv->ao_readback[chan] = data[i];
+ 	}
+ 
+@@ -568,15 +570,15 @@ static int skel_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevic
+ 		s->state &= ~data[0];
+ 		s->state |= data[0] & data[1];
+ 		/* Write out the new digital output lines */
+-		//outw(s->state,dev->iobase + SKEL_DIO);
++		/* outw(s->state,dev->iobase + SKEL_DIO); */
+ 	}
+ 
+ 	/* on return, data[1] contains the value of the digital
+ 	 * input and output lines. */
+-	//data[1]=inw(dev->iobase + SKEL_DIO);
++	/* data[1]=inw(dev->iobase + SKEL_DIO); */
+ 	/* or we could just return the software copy of the output values if
+ 	 * it was a purely digital output subdevice */
+-	//data[1]=s->state;
++	/* data[1]=s->state; */
+ 
+ 	return 2;
+ }
+@@ -607,7 +609,7 @@ static int skel_dio_insn_config(struct comedi_device * dev, struct comedi_subdev
+ 		return -EINVAL;
+ 		break;
+ 	}
+-	//outw(s->io_bits,dev->iobase + SKEL_DIO_CONFIG);
++	/* outw(s->io_bits,dev->iobase + SKEL_DIO_CONFIG); */
+ 
+ 	return insn->n;
+ }
+@@ -619,4 +621,4 @@ static int skel_dio_insn_config(struct comedi_device * dev, struct comedi_subdev
+ COMEDI_INITCLEANUP(driver_skel);
+ /* If you are writing a PCI driver you should use COMEDI_PCI_INITCLEANUP instead.
+ */
+-// COMEDI_PCI_INITCLEANUP(driver_skel, skel_pci_table)
++/* COMEDI_PCI_INITCLEANUP(driver_skel, skel_pci_table) */

commit 450032a318ebfc95121fc548442217592803f4a7
+Author: Bill Pemberton 
+Date:   Thu Mar 19 17:57:22 2009 -0400
+
+    Staging: comedi: Remove pcidas64_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
+index 4c2e97302a35..1a580bd2247a 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
+@@ -1065,7 +1065,8 @@ struct ext_clock_info {
+ };
+ 
+ /* this structure is for data unique to this hardware driver. */
+-typedef struct {
++struct pcidas64_private {
++
+ 	struct pci_dev *hw_dev;	// pointer to board's pci_dev struct
+ 	// base addresses (physical)
+ 	resource_size_t plx9080_phys_iobase;
+@@ -1109,12 +1110,13 @@ typedef struct {
+ 	unsigned int ai_fifo_segment_length;
+ 	struct ext_clock_info ext_clock;
+ 	short ao_bounce_buffer[DAC_FIFO_SIZE];
+-} pcidas64_private;
++};
++
+ 
+ /* inline function that makes it easier to
+  * access the private structure.
+  */
+-static inline pcidas64_private *priv(struct comedi_device * dev)
++static inline struct pcidas64_private *priv(struct comedi_device * dev)
+ {
+ 	return dev->private;
+ }
+@@ -1685,7 +1687,7 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ /*
+  * Allocate the private structure area.
+  */
+-	if (alloc_private(dev, sizeof(pcidas64_private)) < 0)
++	if (alloc_private(dev, sizeof(struct pcidas64_private)) < 0)
+ 		return -ENOMEM;
+ 
+ /*

commit 222ab1bc78dd8a48576e904da37fd6f71cb41a7e
+Author: Bill Pemberton 
+Date:   Thu Mar 19 17:57:11 2009 -0400
+
+    Staging: comedi: Remove pcidas64_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
+index 0e9eeefc93bd..4c2e97302a35 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
+@@ -541,7 +541,7 @@ struct hw_fifo_info {
+ 	uint16_t fifo_size_reg_mask;
+ };
+ 
+-typedef struct pcidas64_board_struct {
++struct pcidas64_board {
+ 	const char *name;
+ 	int device_id;		// pci device id
+ 	int ai_se_chans;	// number of ai inputs in single-ended mode
+@@ -556,7 +556,7 @@ typedef struct pcidas64_board_struct {
+ 	const struct hw_fifo_info *const ai_fifo;
+ 	enum register_layout layout;	// different board families have slightly different registers
+ 	unsigned has_8255:1;
+-} pcidas64_board;
++};
+ 
+ static const struct hw_fifo_info ai_fifo_4020 = {
+       num_segments:2,
+@@ -584,7 +584,7 @@ static const struct hw_fifo_info ai_fifo_60xx = {
+ #define MAX_AI_DMA_RING_COUNT (0x80000 / DMA_BUFFER_SIZE)
+ #define MIN_AI_DMA_RING_COUNT (0x10000 / DMA_BUFFER_SIZE)
+ #define AO_DMA_RING_COUNT (0x10000 / DMA_BUFFER_SIZE)
+-static inline unsigned int ai_dma_ring_count(pcidas64_board * board)
++static inline unsigned int ai_dma_ring_count(struct pcidas64_board * board)
+ {
+ 	if (board->layout == LAYOUT_4020)
+ 		return MAX_AI_DMA_RING_COUNT;
+@@ -594,7 +594,7 @@ static inline unsigned int ai_dma_ring_count(pcidas64_board * board)
+ 
+ static const int bytes_in_sample = 2;
+ 
+-static const pcidas64_board pcidas64_boards[] = {
++static const struct pcidas64_board pcidas64_boards[] = {
+ 	{
+ 	      name:	"pci-das6402/16",
+ 	      device_id:0x1d,
+@@ -1016,7 +1016,7 @@ static const pcidas64_board pcidas64_boards[] = {
+ // Number of boards in cb_pcidas_boards
+ static inline unsigned int num_boards(void)
+ {
+-	return sizeof(pcidas64_boards) / sizeof(pcidas64_board);
++	return sizeof(pcidas64_boards) / sizeof(struct pcidas64_board);
+ }
+ 
+ static DEFINE_PCI_DEVICE_TABLE(pcidas64_pci_table) = {
+@@ -1044,9 +1044,9 @@ static DEFINE_PCI_DEVICE_TABLE(pcidas64_pci_table) = {
+ 
+ MODULE_DEVICE_TABLE(pci, pcidas64_pci_table);
+ 
+-static inline pcidas64_board *board(const struct comedi_device * dev)
++static inline struct pcidas64_board *board(const struct comedi_device * dev)
+ {
+-	return (pcidas64_board *) dev->board_ptr;
++	return (struct pcidas64_board *) dev->board_ptr;
+ }
+ 
+ static inline unsigned short se_diff_bit_6xxx(struct comedi_device * dev,
+@@ -1267,7 +1267,7 @@ static void set_dac_range_bits(struct comedi_device * dev, volatile uint16_t * b
+ 	*bits |= code << (2 * channel);
+ };
+ 
+-static inline int ao_cmd_is_supported(const pcidas64_board * board)
++static inline int ao_cmd_is_supported(const struct pcidas64_board * board)
+ {
+ 	return board->ao_nchan && board->layout != LAYOUT_4020;
+ }

commit 675935dd95cf24e81982e57021d03d5bf8bdac60
+Author: Bill Pemberton 
+Date:   Thu Mar 19 17:57:06 2009 -0400
+
+    Staging: comedi: Remove hw_fifo_info_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
+index 707e3ccc9d72..0e9eeefc93bd 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
+@@ -534,12 +534,12 @@ enum register_layout {
+ 	LAYOUT_4020,
+ };
+ 
+-typedef struct hw_fifo_info_struct {
++struct hw_fifo_info {
+ 	unsigned int num_segments;
+ 	unsigned int max_segment_length;
+ 	unsigned int sample_packing_ratio;
+ 	uint16_t fifo_size_reg_mask;
+-} hw_fifo_info_t;
++};
+ 
+ typedef struct pcidas64_board_struct {
+ 	const char *name;
+@@ -553,26 +553,26 @@ typedef struct pcidas64_board_struct {
+ 	int ao_scan_speed;	// analog output speed (for a scan, not conversion)
+ 	const struct comedi_lrange *ao_range_table;
+ 	const int *ao_range_code;
+-	const hw_fifo_info_t *const ai_fifo;
++	const struct hw_fifo_info *const ai_fifo;
+ 	enum register_layout layout;	// different board families have slightly different registers
+ 	unsigned has_8255:1;
+ } pcidas64_board;
+ 
+-static const hw_fifo_info_t ai_fifo_4020 = {
++static const struct hw_fifo_info ai_fifo_4020 = {
+       num_segments:2,
+       max_segment_length:0x8000,
+       sample_packing_ratio:2,
+       fifo_size_reg_mask:0x7f,
+ };
+ 
+-static const hw_fifo_info_t ai_fifo_64xx = {
++static const struct hw_fifo_info ai_fifo_64xx = {
+       num_segments:4,
+       max_segment_length:0x800,
+       sample_packing_ratio:1,
+       fifo_size_reg_mask:0x3f,
+ };
+ 
+-static const hw_fifo_info_t ai_fifo_60xx = {
++static const struct hw_fifo_info ai_fifo_60xx = {
+       num_segments:4,
+       max_segment_length:0x800,
+       sample_packing_ratio:1,
+@@ -2041,7 +2041,7 @@ static int ai_config_calibration_source(struct comedi_device * dev, unsigned int
+ static int ai_config_block_size(struct comedi_device * dev, unsigned int * data)
+ {
+ 	int fifo_size;
+-	const hw_fifo_info_t *const fifo = board(dev)->ai_fifo;
++	const struct hw_fifo_info *const fifo = board(dev)->ai_fifo;
+ 	unsigned int block_size, requested_block_size;
+ 	int retval;
+ 
+@@ -3929,7 +3929,7 @@ static int set_ai_fifo_size(struct comedi_device * dev, unsigned int num_samples
+ {
+ 	unsigned int num_fifo_entries;
+ 	int retval;
+-	const hw_fifo_info_t *const fifo = board(dev)->ai_fifo;
++	const struct hw_fifo_info *const fifo = board(dev)->ai_fifo;
+ 
+ 	num_fifo_entries = num_samples / fifo->sample_packing_ratio;
+ 
+@@ -3957,7 +3957,7 @@ static int set_ai_fifo_segment_length(struct comedi_device * dev,
+ 	unsigned int num_entries)
+ {
+ 	static const int increment_size = 0x100;
+-	const hw_fifo_info_t *const fifo = board(dev)->ai_fifo;
++	const struct hw_fifo_info *const fifo = board(dev)->ai_fifo;
+ 	unsigned int num_increments;
+ 	uint16_t bits;
+ 

commit 4a5a33b622ca46acd0a7c593a804964353d54a7b
+Author: Bill Pemberton 
+Date:   Thu Mar 19 14:22:44 2009 -0400
+
+    Staging: comedi: Remove 2.4 irqreturn_t compatibility in comedi/interrupt.h
+    
+    This allows the comedi driver to build after commit bedd3..058bb
+    is applied.
+    
+    Signed-off-by: Bill Pemberton 
+    Reported-by: Sachin Sant 
+    Reported-by: Randy Dunlap 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/interrupt.h b/drivers/staging/comedi/interrupt.h
+index 50cf823dbd04..d1f09892da2e 100644
+--- a/drivers/staging/comedi/interrupt.h
++++ b/drivers/staging/comedi/interrupt.h
+@@ -21,13 +21,6 @@
+ 
+ #include 
+ 
+-#ifndef IRQ_NONE
+-typedef void irqreturn_t;
+-#define IRQ_NONE
+-#define IRQ_HANDLED
+-#define IRQ_RETVAL(x) (void)(x)
+-#endif
+-
+ #ifndef IRQF_DISABLED
+ #define IRQF_DISABLED           SA_INTERRUPT
+ #define IRQF_SAMPLE_RANDOM      SA_SAMPLE_RANDOM

commit ab64f663412716193ccafefd7e6cc27dcf691ac8
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:19:53 2009 -0400
+
+    Staging: comedi: quatech_daqp_cs: Remove local_info_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+index f405341c95f6..795c4522867f 100644
+--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
++++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+@@ -75,7 +75,7 @@ static char *version = "quatech_daqp_cs.c 1.10 2003/04/21 (Brent Baccala)";
+ /* Maximum number of separate DAQP devices we'll allow */
+ #define MAX_DEV         4
+ 
+-typedef struct local_info_t {
++struct local_info_t {
+ 	struct pcmcia_device *link;
+ 	dev_node_t node;
+ 	int stop;
+@@ -89,11 +89,11 @@ typedef struct local_info_t {
+ 	struct comedi_device *dev;
+ 	struct comedi_subdevice *s;
+ 	int count;
+-} local_info_t;
++};
+ 
+ /* A list of "instances" of the device. */
+ 
+-static local_info_t *dev_table[MAX_DEV] = { NULL, /* ... */  };
++static struct local_info_t *dev_table[MAX_DEV] = { NULL, /* ... */  };
+ 
+ /* The DAQP communicates with the system through a 16 byte I/O window. */
+ 
+@@ -236,7 +236,7 @@ static void hex_dump(char *str, void *ptr, int len)
+ 
+ static int daqp_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	local_info_t *local = (local_info_t *) s->private;
++	struct local_info_t *local = (struct local_info_t *) s->private;
+ 
+ 	if (local->stop) {
+ 		return -EIO;
+@@ -264,7 +264,7 @@ static int daqp_ai_cancel(struct comedi_device * dev, struct comedi_subdevice *
+ 
+ static void daqp_interrupt(int irq, void *dev_id PT_REGS_ARG)
+ {
+-	local_info_t *local = (local_info_t *) dev_id;
++	struct local_info_t *local = (struct local_info_t *) dev_id;
+ 	struct comedi_device *dev;
+ 	struct comedi_subdevice *s;
+ 	int loop_limit = 10000;
+@@ -295,7 +295,7 @@ static void daqp_interrupt(int irq, void *dev_id PT_REGS_ARG)
+ 		return;
+ 	}
+ 
+-	if ((local_info_t *) s->private != local) {
++	if ((struct local_info_t *) s->private != local) {
+ 		printk(KERN_WARNING
+ 			"daqp_interrupt(): invalid comedi_subdevice.\n");
+ 		return;
+@@ -364,7 +364,7 @@ static void daqp_interrupt(int irq, void *dev_id PT_REGS_ARG)
+ static int daqp_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	local_info_t *local = (local_info_t *) s->private;
++	struct local_info_t *local = (struct local_info_t *) s->private;
+ 	int i;
+ 	int v;
+ 	int counter = 10000;
+@@ -595,7 +595,7 @@ static int daqp_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice *
+ 
+ static int daqp_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	local_info_t *local = (local_info_t *) s->private;
++	struct local_info_t *local = (struct local_info_t *) s->private;
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+ 	int counter = 100;
+ 	int scanlist_start_on_every_entry;
+@@ -796,7 +796,7 @@ static int daqp_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ static int daqp_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	local_info_t *local = (local_info_t *) s->private;
++	struct local_info_t *local = (struct local_info_t *) s->private;
+ 	int d;
+ 	unsigned int chan;
+ 
+@@ -823,7 +823,7 @@ static int daqp_ao_insn_write(struct comedi_device * dev, struct comedi_subdevic
+ static int daqp_di_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	local_info_t *local = (local_info_t *) s->private;
++	struct local_info_t *local = (struct local_info_t *) s->private;
+ 
+ 	if (local->stop) {
+ 		return -EIO;
+@@ -839,7 +839,7 @@ static int daqp_di_insn_read(struct comedi_device * dev, struct comedi_subdevice
+ static int daqp_do_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	local_info_t *local = (local_info_t *) s->private;
++	struct local_info_t *local = (struct local_info_t *) s->private;
+ 
+ 	if (local->stop) {
+ 		return -EIO;
+@@ -859,7 +859,7 @@ static int daqp_do_insn_write(struct comedi_device * dev, struct comedi_subdevic
+ static int daqp_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	int ret;
+-	local_info_t *local = dev_table[it->options[0]];
++	struct local_info_t *local = dev_table[it->options[0]];
+ 	tuple_t tuple;
+ 	int i;
+ 	struct comedi_subdevice *s;
+@@ -1051,7 +1051,7 @@ static const dev_info_t dev_info = "quatech_daqp_cs";
+ 
+ static int daqp_cs_attach(struct pcmcia_device *link)
+ {
+-	local_info_t *local;
++	struct local_info_t *local;
+ 	int i;
+ 
+ 	DEBUG(0, "daqp_cs_attach()\n");
+@@ -1065,7 +1065,7 @@ static int daqp_cs_attach(struct pcmcia_device *link)
+ 	}
+ 
+ 	/* Allocate space for private device-specific data */
+-	local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
++	local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
+ 	if (!local)
+ 		return -ENOMEM;
+ 
+@@ -1106,7 +1106,7 @@ static int daqp_cs_attach(struct pcmcia_device *link)
+ 
+ static void daqp_cs_detach(struct pcmcia_device *link)
+ {
+-	local_info_t *dev = link->priv;
++	struct local_info_t *dev = link->priv;
+ 
+ 	DEBUG(0, "daqp_cs_detach(0x%p)\n", link);
+ 
+@@ -1132,7 +1132,7 @@ static void daqp_cs_detach(struct pcmcia_device *link)
+ 
+ static void daqp_cs_config(struct pcmcia_device *link)
+ {
+-	local_info_t *dev = link->priv;
++	struct local_info_t *dev = link->priv;
+ 	tuple_t tuple;
+ 	cisparse_t parse;
+ 	int last_ret;
+@@ -1306,7 +1306,7 @@ static void daqp_cs_release(struct pcmcia_device *link)
+ 
+ static int daqp_cs_suspend(struct pcmcia_device *link)
+ {
+-	local_info_t *local = link->priv;
++	struct local_info_t *local = link->priv;
+ 
+ 	/* Mark the device as stopped, to block IO until later */
+ 	local->stop = 1;
+@@ -1315,7 +1315,7 @@ static int daqp_cs_suspend(struct pcmcia_device *link)
+ 
+ static int daqp_cs_resume(struct pcmcia_device *link)
+ {
+-	local_info_t *local = link->priv;
++	struct local_info_t *local = link->priv;
+ 
+ 	local->stop = 0;
+ 

commit e21ffa44f55ebf7f6f7d1e60a49463ca579c056a
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:18:54 2009 -0400
+
+    Staging: comedi: serial2002: Remove serial2002_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
+index 0e48887b55cb..844fd5e2e3a9 100644
+--- a/drivers/staging/comedi/drivers/serial2002.c
++++ b/drivers/staging/comedi/drivers/serial2002.c
+@@ -68,7 +68,8 @@ struct serial2002_range_table_t {
+ };
+ 
+ 
+-typedef struct {
++struct serial2002_private {
++
+ 	int port;		// /dev/ttyS
+ 	int speed;		// baudrate
+ 	struct file *tty;
+@@ -79,13 +80,14 @@ typedef struct {
+ 	unsigned char analog_out_mapping[32];
+ 	unsigned char encoder_in_mapping[32];
+ 	struct serial2002_range_table_t in_range[32], out_range[32];
+-} serial2002_private;
++};
++
+ 
+ /*
+  * most drivers define the following macro to make it easy to
+  * access the private structure.
+  */
+-#define devpriv ((serial2002_private *)dev->private)
++#define devpriv ((struct serial2002_private *)dev->private)
+ 
+ static int serial2002_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int serial2002_detach(struct comedi_device * dev);
+@@ -786,7 +788,7 @@ static int serial2002_attach(struct comedi_device * dev, struct comedi_devconfig
+ 
+ 	printk("comedi%d: serial2002: ", dev->minor);
+ 	dev->board_name = thisboard->name;
+-	if (alloc_private(dev, sizeof(serial2002_private)) < 0) {
++	if (alloc_private(dev, sizeof(struct serial2002_private)) < 0) {
+ 		return -ENOMEM;
+ 	}
+ 	dev->open = serial_2002_open;

commit 404d108d8f5968f47ba72417a3532f213e020914
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:17:49 2009 -0400
+
+    Staging: comedi: skel.c: Remove skel_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c
+index 9009d77146ed..b2268aa49bc8 100644
+--- a/drivers/staging/comedi/drivers/skel.c
++++ b/drivers/staging/comedi/drivers/skel.c
+@@ -131,7 +131,8 @@ MODULE_DEVICE_TABLE(pci, skel_pci_table);
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+    feel free to suggest moving the variable to the struct comedi_device struct.  */
+-typedef struct {
++struct skel_private {
++
+ 	int data;
+ 
+ 	/* would be useful for a PCI device */
+@@ -139,12 +140,13 @@ typedef struct {
+ 
+ 	/* Used for AO readback */
+ 	unsigned int ao_readback[2];
+-} skel_private;
++};
++
+ /*
+  * most drivers define the following macro to make it easy to
+  * access the private structure.
+  */
+-#define devpriv ((skel_private *)dev->private)
++#define devpriv ((struct skel_private *)dev->private)
+ 
+ /*
+  * The struct comedi_driver structure tells the Comedi core module
+@@ -225,7 +227,7 @@ static int skel_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+  * Allocate the private structure area.  alloc_private() is a
+  * convenient macro defined in comedidev.h.
+  */
+-	if (alloc_private(dev, sizeof(skel_private)) < 0)
++	if (alloc_private(dev, sizeof(struct skel_private)) < 0)
+ 		return -ENOMEM;
+ 
+ /*

commit 1de6a6fd5b672f3a2d8aa6ebe4c85552f091277b
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:17:33 2009 -0400
+
+    Staging: comedi: rti800: Remove boardtype typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c
+index 594c5e82211f..334ac5773a13 100644
+--- a/drivers/staging/comedi/drivers/rti800.c
++++ b/drivers/staging/comedi/drivers/rti800.c
+@@ -118,16 +118,18 @@ static const struct comedi_lrange range_rti800_ai_unipolar = { 4, {
+ 	}
+ };
+ 
+-typedef struct {
++struct rti800_board {
++
+ 	const char *name;
+ 	int has_ao;
+-} boardtype;
+-static const boardtype boardtypes[] = {
++};
++
++static const struct rti800_board boardtypes[] = {
+ 	{"rti800", 0},
+ 	{"rti815", 1},
+ };
+ 
+-#define this_board ((const boardtype *)dev->board_ptr)
++#define this_board ((const struct rti800_board *)dev->board_ptr)
+ 
+ static int rti800_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int rti800_detach(struct comedi_device * dev);
+@@ -136,9 +138,9 @@ static struct comedi_driver driver_rti800 = {
+       module:THIS_MODULE,
+       attach:rti800_attach,
+       detach:rti800_detach,
+-      num_names:sizeof(boardtypes) / sizeof(boardtype),
++      num_names:sizeof(boardtypes) / sizeof(struct rti800_board),
+       board_name:&boardtypes[0].name,
+-      offset:sizeof(boardtype),
++      offset:sizeof(struct rti800_board),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_rti800);

commit 180089a8966e712cb8cb9af1d7401c3e12453d74
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:17:22 2009 -0400
+
+    Staging: comedi: pcm3724: Remove boardtype typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c
+index 3839c8dd96a5..a3ed3a0e855a 100644
+--- a/drivers/staging/comedi/drivers/pcm3724.c
++++ b/drivers/staging/comedi/drivers/pcm3724.c
+@@ -65,13 +65,13 @@ Copy/pasted/hacked from pcm724.c
+ static int pcm3724_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pcm3724_detach(struct comedi_device * dev);
+ 
+-typedef struct {
++struct pcm3724_board {
+ 	const char *name;	// driver name
+ 	int dio;		// num of DIO
+ 	int numofports;		// num of 8255 subdevices
+ 	unsigned int IRQbits;	// allowed interrupts
+ 	unsigned int io_range;	// len of IO space
+-} boardtype;
++};
+ 
+ //used to track configured dios
+ struct priv_pcm3724 {
+@@ -79,12 +79,12 @@ struct priv_pcm3724 {
+ 	int dio_2;
+ };
+ 
+-static const boardtype boardtypes[] = {
++static const struct pcm3724_board boardtypes[] = {
+ 	{"pcm3724", 48, 2, 0x00fc, PCM3724_SIZE,},
+ };
+ 
+-#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+-#define this_board ((const boardtype *)dev->board_ptr)
++#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcm3724_board))
++#define this_board ((const struct pcm3724_board *)dev->board_ptr)
+ 
+ static struct comedi_driver driver_pcm3724 = {
+       driver_name:"pcm3724",
+@@ -93,7 +93,7 @@ static struct comedi_driver driver_pcm3724 = {
+       detach:pcm3724_detach,
+       board_name:&boardtypes[0].name,
+       num_names:n_boardtypes,
+-      offset:sizeof(boardtype),
++      offset:sizeof(struct pcm3724_board),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_pcm3724);

commit 1c7f40d91b99e73ae11056708225058afd0278d7
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:17:11 2009 -0400
+
+    Staging: comedi: pcl816: Remove boardtype typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
+index 6ed19e21c9a4..515ba74cc7fe 100644
+--- a/drivers/staging/comedi/drivers/pcl816.c
++++ b/drivers/staging/comedi/drivers/pcl816.c
+@@ -101,7 +101,8 @@ static const struct comedi_lrange range_pcl816 = { 8, {
+ 			UNI_RANGE(1.25),
+ 	}
+ };
+-typedef struct {
++struct pcl816_board {
++
+ 	const char *name;	// board name
+ 	int n_ranges;		// len of range list
+ 	int n_aichan;		// num of A/D chans in diferencial mode
+@@ -119,9 +120,10 @@ typedef struct {
+ 	int ai_chanlist;	// allowed len of channel list A/D
+ 	int ao_chanlist;	// allowed len of channel list D/A
+ 	int i8254_osc_base;	// 1/frequency of on board oscilator in ns
+-} boardtype;
++};
++
+ 
+-static const boardtype boardtypes[] = {
++static const struct pcl816_board boardtypes[] = {
+ 	{"pcl816", 8, 16, 10000, 1, 16, 16, &range_pcl816,
+ 			&range_pcl816, PCLx1x_RANGE,
+ 			0x00fc,	// IRQ mask
+@@ -142,9 +144,9 @@ static const boardtype boardtypes[] = {
+ 		100},
+ };
+ 
+-#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
++#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl816_board))
+ #define devpriv ((struct pcl816_private *)dev->private)
+-#define this_board ((const boardtype *)dev->board_ptr)
++#define this_board ((const struct pcl816_board *)dev->board_ptr)
+ 
+ static int pcl816_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pcl816_detach(struct comedi_device * dev);
+@@ -161,7 +163,7 @@ static struct comedi_driver driver_pcl816 = {
+       detach:pcl816_detach,
+       board_name:&boardtypes[0].name,
+       num_names:n_boardtypes,
+-      offset:sizeof(boardtype),
++      offset:sizeof(struct pcl816_board),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_pcl816);

commit fb1314de41d8fbd14e7aeb735d7849be8a852dbc
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:17:06 2009 -0400
+
+    Staging: comedi: pcl812: Remove boardtype typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
+index 424e8096624b..11dfd230e565 100644
+--- a/drivers/staging/comedi/drivers/pcl812.c
++++ b/drivers/staging/comedi/drivers/pcl812.c
+@@ -295,7 +295,8 @@ static const struct comedi_lrange range_a821pgh_ai = { 4, {
+ static int pcl812_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pcl812_detach(struct comedi_device * dev);
+ 
+-typedef struct {
++struct pcl812_board {
++
+ 	const char *name;	// board name
+ 	int board_type;		// type of this board
+ 	int n_aichan;		// num of AI chans in S.E.
+@@ -312,9 +313,10 @@ typedef struct {
+ 	unsigned char DMAbits;	// allowed DMA chans
+ 	unsigned char io_range;	// iorange for this board
+ 	unsigned char haveMPC508;	// 1=board use MPC508A multiplexor
+-} boardtype;
++};
++
+ 
+-static const boardtype boardtypes[] = {
++static const struct pcl812_board boardtypes[] = {
+ 	{"pcl812", boardPCL812, 16, 0, 2, 16, 16, 0x0fff,
+ 			33000, 500, &range_bipolar10, &range_unipolar5,
+ 		0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
+@@ -371,8 +373,8 @@ static const boardtype boardtypes[] = {
+ 		0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
+ };
+ 
+-#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+-#define this_board ((const boardtype *)dev->board_ptr)
++#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl812_board))
++#define this_board ((const struct pcl812_board *)dev->board_ptr)
+ 
+ static struct comedi_driver driver_pcl812 = {
+       driver_name:"pcl812",
+@@ -381,7 +383,7 @@ static struct comedi_driver driver_pcl812 = {
+       detach:pcl812_detach,
+       board_name:&boardtypes[0].name,
+       num_names:n_boardtypes,
+-      offset:sizeof(boardtype),
++      offset:sizeof(struct pcl812_board),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_pcl812);

commit 292090dcc85a6e8a4132a6551d73bc467b270693
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:17:01 2009 -0400
+
+    Staging: comedi: pcl730: Remove boardtype typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c
+index f290e1195865..f2c6d7c5693c 100644
+--- a/drivers/staging/comedi/drivers/pcl730.c
++++ b/drivers/staging/comedi/drivers/pcl730.c
+@@ -29,19 +29,21 @@ The ACL-7130 card have an 8254 timer/counter not supported by this driver.
+ static int pcl730_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pcl730_detach(struct comedi_device * dev);
+ 
+-typedef struct {
++struct pcl730_board {
++
+ 	const char *name;	// board name
+ 	unsigned int io_range;	// len of I/O space
+-} boardtype;
++};
++
+ 
+-static const boardtype boardtypes[] = {
++static const struct pcl730_board boardtypes[] = {
+ 	{"pcl730", PCL730_SIZE,},
+ 	{"iso730", PCL730_SIZE,},
+ 	{"acl7130", ACL7130_SIZE,},
+ };
+ 
+-#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+-#define this_board ((const boardtype *)dev->board_ptr)
++#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl730_board))
++#define this_board ((const struct pcl730_board *)dev->board_ptr)
+ 
+ static struct comedi_driver driver_pcl730 = {
+       driver_name:"pcl730",
+@@ -50,7 +52,7 @@ static struct comedi_driver driver_pcl730 = {
+       detach:pcl730_detach,
+       board_name:&boardtypes[0].name,
+       num_names:n_boardtypes,
+-      offset:sizeof(boardtype),
++      offset:sizeof(struct pcl730_board),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_pcl730);

commit 747887a6210a6dc3dcfd40bdcc88ea65c85fcea3
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:16:55 2009 -0400
+
+    Staging: comedi: pcl726: Remove boardtype typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c
+index deda5de70579..6dbd33d7907b 100644
+--- a/drivers/staging/comedi/drivers/pcl726.c
++++ b/drivers/staging/comedi/drivers/pcl726.c
+@@ -114,7 +114,8 @@ static const struct comedi_lrange *const rangelist_728[] = {
+ static int pcl726_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pcl726_detach(struct comedi_device * dev);
+ 
+-typedef struct {
++struct pcl726_board {
++
+ 	const char *name;	// driver name
+ 	int n_aochan;		// num of D/A chans
+ 	int num_of_ranges;	// num of ranges
+@@ -126,9 +127,10 @@ typedef struct {
+ 	int do_hi;
+ 	int do_lo;
+ 	const struct comedi_lrange *const *range_type_list;	// list of supported ranges
+-} boardtype;
++};
++
+ 
+-static const boardtype boardtypes[] = {
++static const struct pcl726_board boardtypes[] = {
+ 	{"pcl726", 6, 6, 0x0000, PCL726_SIZE, 1,
+ 			PCL726_DI_HI, PCL726_DI_LO, PCL726_DO_HI, PCL726_DO_LO,
+ 		&rangelist_726[0],},
+@@ -146,8 +148,8 @@ static const boardtype boardtypes[] = {
+ 		&rangelist_728[0],},
+ };
+ 
+-#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+-#define this_board ((const boardtype *)dev->board_ptr)
++#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl726_board))
++#define this_board ((const struct pcl726_board *)dev->board_ptr)
+ 
+ static struct comedi_driver driver_pcl726 = {
+       driver_name:"pcl726",
+@@ -156,7 +158,7 @@ static struct comedi_driver driver_pcl726 = {
+       detach:pcl726_detach,
+       board_name:&boardtypes[0].name,
+       num_names:n_boardtypes,
+-      offset:sizeof(boardtype),
++      offset:sizeof(struct pcl726_board),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_pcl726);

commit 01820e023e5cd162ce629bd5961aabf6dd999e7a
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:16:50 2009 -0400
+
+    Staging: comedi: pcl724: Remove boardtype typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c
+index 108649f31c14..cd1e784f25f9 100644
+--- a/drivers/staging/comedi/drivers/pcl724.c
++++ b/drivers/staging/comedi/drivers/pcl724.c
+@@ -59,7 +59,8 @@ See the source for configuration details.
+ static int pcl724_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pcl724_detach(struct comedi_device * dev);
+ 
+-typedef struct {
++struct pcl724_board {
++
+ 	const char *name;	// board name
+ 	int dio;		// num of DIO
+ 	int numofports;		// num of 8255 subdevices
+@@ -67,9 +68,10 @@ typedef struct {
+ 	unsigned int io_range;	// len of IO space
+ 	char can_have96;
+ 	char is_pet48;
+-} boardtype;
++};
++
+ 
+-static const boardtype boardtypes[] = {
++static const struct pcl724_board boardtypes[] = {
+ 	{"pcl724", 24, 1, 0x00fc, PCL724_SIZE, 0, 0,},
+ 	{"pcl722", 144, 6, 0x00fc, PCL722_SIZE, 1, 0,},
+ 	{"pcl731", 48, 2, 0x9cfc, PCL731_SIZE, 0, 0,},
+@@ -78,8 +80,8 @@ static const boardtype boardtypes[] = {
+ 	{"pet48dio", 48, 2, 0x9eb8, PET48_SIZE, 0, 1,},
+ };
+ 
+-#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+-#define this_board ((const boardtype *)dev->board_ptr)
++#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl724_board))
++#define this_board ((const struct pcl724_board *)dev->board_ptr)
+ 
+ static struct comedi_driver driver_pcl724 = {
+       driver_name:"pcl724",
+@@ -88,7 +90,7 @@ static struct comedi_driver driver_pcl724 = {
+       detach:pcl724_detach,
+       board_name:&boardtypes[0].name,
+       num_names:n_boardtypes,
+-      offset:sizeof(boardtype),
++      offset:sizeof(struct pcl724_board),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_pcl724);

commit 6445296e9857ff4a3992454eda7ebb63f90cdca9
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:16:45 2009 -0400
+
+    Staging: comedi: pcl711: Remove boardtype typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c
+index fefbe1ca654a..ce42506d47b5 100644
+--- a/drivers/staging/comedi/drivers/pcl711.c
++++ b/drivers/staging/comedi/drivers/pcl711.c
+@@ -132,7 +132,8 @@ static const struct comedi_lrange range_acl8112dg_ai = { 9, {
+ 
+ static const int i8253_osc_base = 500;	/* 2 Mhz */
+ 
+-typedef struct {
++struct pcl711_board {
++
+ 	const char *name;
+ 	int is_pcl711b;
+ 	int is_8112;
+@@ -142,17 +143,18 @@ typedef struct {
+ 	int n_aochan;
+ 	int maxirq;
+ 	const struct comedi_lrange *ai_range_type;
+-} boardtype;
++};
++
+ 
+-static const boardtype boardtypes[] = {
++static const struct pcl711_board boardtypes[] = {
+ 	{"pcl711", 0, 0, 0, 5, 8, 1, 0, &range_bipolar5},
+ 	{"pcl711b", 1, 0, 0, 5, 8, 1, 7, &range_pcl711b_ai},
+ 	{"acl8112hg", 0, 1, 0, 12, 16, 2, 15, &range_acl8112hg_ai},
+ 	{"acl8112dg", 0, 1, 1, 9, 16, 2, 15, &range_acl8112dg_ai},
+ };
+ 
+-#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+-#define this_board ((const boardtype *)dev->board_ptr)
++#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl711_board))
++#define this_board ((const struct pcl711_board *)dev->board_ptr)
+ 
+ static int pcl711_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pcl711_detach(struct comedi_device * dev);
+@@ -163,7 +165,7 @@ static struct comedi_driver driver_pcl711 = {
+       detach:pcl711_detach,
+       board_name:&boardtypes[0].name,
+       num_names:n_boardtypes,
+-      offset:sizeof(boardtype),
++      offset:sizeof(struct pcl711_board),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_pcl711);

commit 42f1884d0683d0d0d4b0895aaed02dbed5d8b921
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:14:46 2009 -0400
+
+    Staging: comedi: dt2811: Remove boardtype typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c
+index d5e529826ad9..795932ec67d3 100644
+--- a/drivers/staging/comedi/drivers/dt2811.c
++++ b/drivers/staging/comedi/drivers/dt2811.c
+@@ -191,13 +191,15 @@ static const struct comedi_lrange range_dt2811_pgl_ai_5_bipolar = { 4, {
+ #define DT2811_INTENB   0x04
+ #define DT2811_ADMODE   0x03
+ 
+-typedef struct {
++struct dt2811_board {
++
+ 	const char *name;
+ 	const struct comedi_lrange *bip_5;
+ 	const struct comedi_lrange *bip_2_5;
+ 	const struct comedi_lrange *unip_5;
+-} boardtype;
+-static const boardtype boardtypes[] = {
++};
++
++static const struct dt2811_board boardtypes[] = {
+ 	{"dt2811-pgh",
+ 			&range_dt2811_pgh_ai_5_bipolar,
+ 			&range_dt2811_pgh_ai_2_5_bipolar,
+@@ -210,7 +212,7 @@ static const boardtype boardtypes[] = {
+ 		},
+ };
+ 
+-#define this_board ((const boardtype *)dev->board_ptr)
++#define this_board ((const struct dt2811_board *)dev->board_ptr)
+ 
+ static int dt2811_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int dt2811_detach(struct comedi_device * dev);
+@@ -220,8 +222,8 @@ static struct comedi_driver driver_dt2811 = {
+       attach:dt2811_attach,
+       detach:dt2811_detach,
+       board_name:&boardtypes[0].name,
+-      num_names:sizeof(boardtypes) / sizeof(boardtype),
+-      offset:sizeof(boardtype),
++      num_names:sizeof(boardtypes) / sizeof(struct dt2811_board),
++      offset:sizeof(struct dt2811_board),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_dt2811);

commit 938f185d4eea489ad802554e2faef9c99e377aa5
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:13:47 2009 -0400
+
+    Staging: comedi: das800: Remove das800_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
+index 71586cccdaca..7a6656bf809c 100644
+--- a/drivers/staging/comedi/drivers/das800.c
++++ b/drivers/staging/comedi/drivers/das800.c
+@@ -232,15 +232,15 @@ static const struct das800_board das800_boards[] = {
+  */
+ #define thisboard ((const struct das800_board *)dev->board_ptr)
+ 
+-typedef struct {
++struct das800_private {
+ 	volatile unsigned int count;	/* number of data points left to be taken */
+ 	volatile int forever;	/* flag indicating whether we should take data forever */
+ 	unsigned int divisor1;	/* value to load into board's counter 1 for timed conversions */
+ 	unsigned int divisor2;	/* value to load into board's counter 2 for timed conversions */
+ 	volatile int do_bits;	/* digital output bits */
+-} das800_private;
++};
+ 
+-#define devpriv ((das800_private *)dev->private)
++#define devpriv ((struct das800_private *)dev->private)
+ 
+ static int das800_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int das800_detach(struct comedi_device * dev);
+@@ -456,7 +456,7 @@ static int das800_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	printk("\n");
+ 
+ 	/* allocate and initialize dev->private */
+-	if (alloc_private(dev, sizeof(das800_private)) < 0)
++	if (alloc_private(dev, sizeof(struct das800_private)) < 0)
+ 		return -ENOMEM;
+ 
+ 	if (iobase == 0) {

commit b90c76fd78a101835eb1cc17271d008ed51688d3
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:11:27 2009 -0400
+
+    Staging: comedi: cb_pcimdas: Remove timer_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
+index 3c78c42b7f41..af705fa092c0 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
+@@ -139,7 +139,7 @@ MODULE_DEVICE_TABLE(pci, cb_pcimdas_pci_table);
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+    feel free to suggest moving the variable to the struct comedi_device struct.  */
+-typedef struct {
++struct cb_pcimdas_private {
+ 	int data;
+ 
+ 	// would be useful for a PCI device
+@@ -161,13 +161,13 @@ typedef struct {
+ 	unsigned short int port_c;	// copy of BADR4+2
+ 	unsigned short int dio_mode;	// copy of BADR4+3
+ 
+-} cb_pcimdas_private;
++};
+ 
+ /*
+  * most drivers define the following macro to make it easy to
+  * access the private structure.
+  */
+-#define devpriv ((cb_pcimdas_private *)dev->private)
++#define devpriv ((struct cb_pcimdas_private *)dev->private)
+ 
+ /*
+  * The struct comedi_driver structure tells the Comedi core module
+@@ -209,7 +209,7 @@ static int cb_pcimdas_attach(struct comedi_device * dev, struct comedi_devconfig
+ /*
+  * Allocate the private structure area.
+  */
+-	if (alloc_private(dev, sizeof(cb_pcimdas_private)) < 0)
++	if (alloc_private(dev, sizeof(struct cb_pcimdas_private)) < 0)
+ 		return -ENOMEM;
+ 
+ /*

commit 502dd07999b48994dc3c86a0c44f1a684299d44f
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:06:53 2009 -0400
+
+    Staging: comedi: acl7225b: Remove boardtype typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/acl7225b.c b/drivers/staging/comedi/drivers/acl7225b.c
+index 78349300ecd3..b21320f0959f 100644
+--- a/drivers/staging/comedi/drivers/acl7225b.c
++++ b/drivers/staging/comedi/drivers/acl7225b.c
+@@ -25,18 +25,18 @@ Devices: [Adlink] ACL-7225b (acl7225b), [ICP] P16R16DIO (p16r16dio)
+ static int acl7225b_attach(struct comedi_device *dev, struct comedi_devconfig * it);
+ static int acl7225b_detach(struct comedi_device *dev);
+ 
+-typedef struct {
++struct boardtype {
+ 	const char *name;	// driver name
+ 	int io_range;		// len of I/O space
+-} boardtype;
++};
+ 
+-static const boardtype boardtypes[] = {
++static const struct boardtype boardtypes[] = {
+ 	{"acl7225b", ACL7225_SIZE,},
+ 	{"p16r16dio", P16R16DIO_SIZE,},
+ };
+ 
+-#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+-#define this_board ((const boardtype *)dev->board_ptr)
++#define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype))
++#define this_board ((const struct boardtype *)dev->board_ptr)
+ 
+ static struct comedi_driver driver_acl7225b = {
+       driver_name:"acl7225b",
+@@ -45,7 +45,7 @@ static struct comedi_driver driver_acl7225b = {
+       detach:acl7225b_detach,
+       board_name:&boardtypes[0].name,
+       num_names:n_boardtypes,
+-      offset:sizeof(boardtype),
++      offset:sizeof(struct boardtype),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_acl7225b);

commit fe0ff175329a83de8f9aac7c0b759cde15cb2247
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:18:43 2009 -0400
+
+    Staging: comedi: Remove pcl816_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
+index 1d1137f602a0..6ed19e21c9a4 100644
+--- a/drivers/staging/comedi/drivers/pcl816.c
++++ b/drivers/staging/comedi/drivers/pcl816.c
+@@ -143,7 +143,7 @@ static const boardtype boardtypes[] = {
+ };
+ 
+ #define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+-#define devpriv ((pcl816_private *)dev->private)
++#define devpriv ((struct pcl816_private *)dev->private)
+ #define this_board ((const boardtype *)dev->board_ptr)
+ 
+ static int pcl816_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+@@ -166,7 +166,8 @@ static struct comedi_driver driver_pcl816 = {
+ 
+ COMEDI_INITCLEANUP(driver_pcl816);
+ 
+-typedef struct {
++struct pcl816_private {
++
+ 	unsigned int dma;	// used DMA, 0=don't use DMA
+ 	int dma_rtc;		// 1=RTC used with DMA, 0=no RTC alloc
+ #ifdef unused
+@@ -204,7 +205,8 @@ typedef struct {
+ 	struct timer_list rtc_irq_timer;	// timer for RTC sanity check
+ 	unsigned long rtc_freq;	// RTC int freq
+ #endif
+-} pcl816_private;
++};
++
+ 
+ /*
+ ==============================================================================
+@@ -1037,7 +1039,7 @@ static int pcl816_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 		return -EIO;
+ 	}
+ 
+-	if ((ret = alloc_private(dev, sizeof(pcl816_private))) < 0)
++	if ((ret = alloc_private(dev, sizeof(struct pcl816_private))) < 0)
+ 		return ret;	/* Can't alloc mem */
+ 
+ 	/* set up some name stuff */

commit 8e7b864b3c8357dd8318ade3970cd3b5fe0571e0
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:18:48 2009 -0400
+
+    Staging: comedi: Remove priv_pcm3724 typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c
+index ba4de985ff3b..3839c8dd96a5 100644
+--- a/drivers/staging/comedi/drivers/pcm3724.c
++++ b/drivers/staging/comedi/drivers/pcm3724.c
+@@ -74,10 +74,11 @@ typedef struct {
+ } boardtype;
+ 
+ //used to track configured dios
+-typedef struct {
++struct priv_pcm3724 {
+ 	int dio_1;
+ 	int dio_2;
+-} priv_pcm3724;
++};
++
+ static const boardtype boardtypes[] = {
+ 	{"pcm3724", 48, 2, 0x00fc, PCM3724_SIZE,},
+ };
+@@ -180,10 +181,10 @@ static void enable_chan(struct comedi_device * dev, struct comedi_subdevice * s,
+ {
+ 	unsigned int mask;
+ 	int gatecfg;
+-	priv_pcm3724 *priv;
++	struct priv_pcm3724 *priv;
+ 
+ 	gatecfg = 0;
+-	priv = (priv_pcm3724 *) (dev->private);
++	priv = (struct priv_pcm3724 *) (dev->private);
+ 
+ 	mask = 1 << CR_CHAN(chanspec);
+ 	if (s == dev->subdevices) {	// subdev 0
+@@ -259,11 +260,11 @@ static int pcm3724_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 
+ 	iobase = it->options[0];
+ 	iorange = this_board->io_range;
+-	if ((ret = alloc_private(dev, sizeof(priv_pcm3724))) < 0)
++	if ((ret = alloc_private(dev, sizeof(struct priv_pcm3724))) < 0)
+ 		return -ENOMEM;
+ 
+-	((priv_pcm3724 *) (dev->private))->dio_1 = 0;
+-	((priv_pcm3724 *) (dev->private))->dio_2 = 0;
++	((struct priv_pcm3724 *) (dev->private))->dio_1 = 0;
++	((struct priv_pcm3724 *) (dev->private))->dio_2 = 0;
+ 
+ 	printk("comedi%d: pcm3724: board=%s, 0x%03lx ", dev->minor,
+ 		this_board->name, iobase);

commit 050509fa558306399f2a987956514a8f849846ef
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:20:57 2009 -0400
+
+    Staging: comedi: Remove six_axis_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
+index 8ff7b986235b..a3c887f3b2c6 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -224,17 +224,17 @@ static void set_offset(volatile struct jr3_channel *channel)
+ 	set_s16(&channel->command_word0, 0x0700);
+ }
+ 
+-typedef struct {
++struct six_axis_t {
+ 	s16 fx;
+ 	s16 fy;
+ 	s16 fz;
+ 	s16 mx;
+ 	s16 my;
+ 	s16 mz;
+-} six_axis_t;
++};
+ 
+ static void set_full_scales(volatile struct jr3_channel *channel,
+-	six_axis_t full_scale)
++	struct six_axis_t full_scale)
+ {
+ 	printk("%d %d %d %d %d %d\n",
+ 		full_scale.fx,
+@@ -249,9 +249,9 @@ static void set_full_scales(volatile struct jr3_channel *channel,
+ 	set_s16(&channel->command_word0, 0x0a00);
+ }
+ 
+-static six_axis_t get_min_full_scales(volatile struct jr3_channel *channel)
++static struct six_axis_t get_min_full_scales(volatile struct jr3_channel *channel)
+ {
+-	six_axis_t result;
++	struct six_axis_t result;
+ 	result.fx = get_s16(&channel->min_full_scale.fx);
+ 	result.fy = get_s16(&channel->min_full_scale.fy);
+ 	result.fz = get_s16(&channel->min_full_scale.fz);
+@@ -261,9 +261,9 @@ static six_axis_t get_min_full_scales(volatile struct jr3_channel *channel)
+ 	return result;
+ }
+ 
+-static six_axis_t get_max_full_scales(volatile struct jr3_channel *channel)
++static struct six_axis_t get_max_full_scales(volatile struct jr3_channel *channel)
+ {
+-	six_axis_t result;
++	struct six_axis_t result;
+ 	result.fx = get_s16(&channel->max_full_scale.fx);
+ 	result.fy = get_s16(&channel->max_full_scale.fy);
+ 	result.fz = get_s16(&channel->max_full_scale.fz);
+@@ -609,8 +609,8 @@ static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice * s)
+ 					result = poll_delay_min_max(20, 100);
+ 				} else {
+ 					// Set full scale
+-					six_axis_t min_full_scale;
+-					six_axis_t max_full_scale;
++					struct six_axis_t min_full_scale;
++					struct six_axis_t max_full_scale;
+ 
+ 					min_full_scale =
+ 						get_min_full_scales(channel);

commit c611ad3313831f1f79b063b282deb4248e283f39
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:20:52 2009 -0400
+
+    Staging: comedi: Remove s526_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
+index 5d98162734b5..a7b6f711afca 100644
+--- a/drivers/staging/comedi/drivers/s526.c
++++ b/drivers/staging/comedi/drivers/s526.c
+@@ -156,7 +156,7 @@ struct s526GPCTConfig {
+  * boards in this way is optional, and completely driver-dependent.
+  * Some drivers use arrays such as this, other do not.
+  */
+-typedef struct s526_board_struct {
++struct s526_board {
+ 	const char *name;
+ 	int gpct_chans;
+ 	int gpct_bits;
+@@ -165,9 +165,9 @@ typedef struct s526_board_struct {
+ 	int da_chans;
+ 	int da_bits;
+ 	int have_dio;
+-} s526_board;
++};
+ 
+-static const s526_board s526_boards[] = {
++static const struct s526_board s526_boards[] = {
+ 	{
+ 	      name:	"s526",
+ 	      gpct_chans:4,
+@@ -186,7 +186,7 @@ static const s526_board s526_boards[] = {
+ /*
+  * Useful for shorthand access to the particular board structure
+  */
+-#define thisboard ((const s526_board *)dev->board_ptr)
++#define thisboard ((const struct s526_board *)dev->board_ptr)
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+@@ -243,8 +243,8 @@ static struct comedi_driver driver_s526 = {
+ 	 * devices are such boards.
+ 	 */
+       board_name:&s526_boards[0].name,
+-      offset:sizeof(s526_board),
+-      num_names:sizeof(s526_boards) / sizeof(s526_board),
++      offset:sizeof(struct s526_board),
++      num_names:sizeof(s526_boards) / sizeof(struct s526_board),
+ };
+ 
+ static int s526_gpct_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,

commit 6ae9488bafce561c087310c051f92bbd0a27b891
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:20:47 2009 -0400
+
+    Staging: comedi: Remove transform_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
+index 7cd88546b201..8ff7b986235b 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -182,15 +182,15 @@ static int is_complete(volatile struct jr3_channel *channel)
+ 	return get_s16(&channel->command_word0) == 0;
+ }
+ 
+-typedef struct {
++struct transform_t {
+ 	struct {
+ 		u16 link_type;
+ 		s16 link_amount;
+ 	} link[8];
+-} transform_t;
++};
+ 
+ static void set_transforms(volatile struct jr3_channel *channel,
+-	transform_t transf, short num)
++	struct transform_t transf, short num)
+ {
+ 	int i;
+ 
+@@ -569,7 +569,7 @@ static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice * s)
+ 					// Wait for offeset to stabilize (< 10 s according to manual)
+ 					result = poll_delay_min_max(1000, 2000);
+ 				} else {
+-					transform_t transf;
++					struct transform_t transf;
+ 
+ 					p->model_no =
+ 						get_u16(&channel->model_no);

commit 39f7666080909466c0ed6d5fa48cce3403033ced
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:20:41 2009 -0400
+
+    Staging: comedi: Remove s526_gpct_config_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
+index 939e17f993d9..5d98162734b5 100644
+--- a/drivers/staging/comedi/drivers/s526.c
++++ b/drivers/staging/comedi/drivers/s526.c
+@@ -146,10 +146,10 @@ enum S526_GPCT_APP_CLASS {
+ /* Config struct for different GPCT subdevice Application Classes and
+    their options
+ */
+-typedef struct s526GPCTConfig {
++struct s526GPCTConfig {
+ 	enum S526_GPCT_APP_CLASS app;
+ 	int data[MAX_GPCT_CONFIG_DATA];
+-} s526_gpct_config_t;
++};
+ 
+ /*
+  * Board descriptions for two imaginary boards.  Describing the
+@@ -201,7 +201,7 @@ struct s526_private {
+ 	/* Used for AO readback */
+ 	unsigned int ao_readback[2];
+ 
+-	s526_gpct_config_t s526_gpct_config[4];
++	struct s526GPCTConfig s526_gpct_config[4];
+ 	unsigned short s526_ai_config;
+ };
+ 

commit 055f6636d9eb27bc13236e07739e019496c21221
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:20:36 2009 -0400
+
+    Staging: comedi: Remove pcmuio_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
+index 89cf5d417748..4e7d8b6327fd 100644
+--- a/drivers/staging/comedi/drivers/pcmuio.c
++++ b/drivers/staging/comedi/drivers/pcmuio.c
+@@ -197,7 +197,7 @@ struct pcmuio_subdev_private {
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+    feel free to suggest moving the variable to the struct comedi_device struct.  */
+-typedef struct {
++struct pcmuio_private {
+ 	struct {
+ 		unsigned char pagelock;	/* current page and lock */
+ 		unsigned char pol[NUM_PAGED_REGS];	/* shadow of POLx registers */
+@@ -208,13 +208,13 @@ typedef struct {
+ 		spinlock_t spinlock;
+ 	} asics[MAX_ASICS];
+ 	struct pcmuio_subdev_private *sprivs;
+-} pcmuio_private;
++};
+ 
+ /*
+  * most drivers define the following macro to make it easy to
+  * access the private structure.
+  */
+-#define devpriv ((pcmuio_private *)dev->private)
++#define devpriv ((struct pcmuio_private *)dev->private)
+ #define subpriv ((struct pcmuio_subdev_private *)s->private)
+ /*
+  * The struct comedi_driver structure tells the Comedi core module
+@@ -312,7 +312,7 @@ static int pcmuio_attach(struct comedi_device * dev, struct comedi_devconfig * i
+  * Allocate the private structure area.  alloc_private() is a
+  * convenient macro defined in comedidev.h.
+  */
+-	if (alloc_private(dev, sizeof(pcmuio_private)) < 0) {
++	if (alloc_private(dev, sizeof(struct pcmuio_private)) < 0) {
+ 		printk("cannot allocate private data structure\n");
+ 		return -ENOMEM;
+ 	}

commit e56ab7156f5f4918eb89a19b3061de1a7fe69354
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:20:30 2009 -0400
+
+    Staging: comedi: Remove pcmmio_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
+index 2d4f9689dd84..01e40f1b5628 100644
+--- a/drivers/staging/comedi/drivers/pcmmio.c
++++ b/drivers/staging/comedi/drivers/pcmmio.c
+@@ -238,7 +238,7 @@ struct pcmmio_subdev_private {
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+    feel free to suggest moving the variable to the struct comedi_device struct.  */
+-typedef struct {
++struct pcmmio_private {
+ 	/* stuff for DIO */
+ 	struct {
+ 		unsigned char pagelock;	/* current page and lock */
+@@ -250,13 +250,13 @@ typedef struct {
+ 		spinlock_t spinlock;
+ 	} asics[MAX_ASICS];
+ 	struct pcmmio_subdev_private *sprivs;
+-} pcmmio_private;
++};
+ 
+ /*
+  * most drivers define the following macro to make it easy to
+  * access the private structure.
+  */
+-#define devpriv ((pcmmio_private *)dev->private)
++#define devpriv ((struct pcmmio_private *)dev->private)
+ #define subpriv ((struct pcmmio_subdev_private *)s->private)
+ /*
+  * The struct comedi_driver structure tells the Comedi core module
+@@ -353,7 +353,7 @@ static int pcmmio_attach(struct comedi_device * dev, struct comedi_devconfig * i
+  * Allocate the private structure area.  alloc_private() is a
+  * convenient macro defined in comedidev.h.
+  */
+-	if (alloc_private(dev, sizeof(pcmmio_private)) < 0) {
++	if (alloc_private(dev, sizeof(struct pcmmio_private)) < 0) {
+ 		printk("cannot allocate private data structure\n");
+ 		return -ENOMEM;
+ 	}

commit c6a3b7b657fb91500bd6946117056284bb0a20c1
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:20:25 2009 -0400
+
+    Staging: comedi: Remove jr3_pci_subdev_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
+index a147772c83fe..7cd88546b201 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -144,7 +144,7 @@ struct poll_delay_t {
+ };
+ 
+ 
+-typedef struct {
++struct jr3_pci_subdev_private {
+ 	volatile struct jr3_channel *channel;
+ 	unsigned long next_time_min;
+ 	unsigned long next_time_max;
+@@ -166,7 +166,7 @@ typedef struct {
+ 	unsigned int maxdata_list[8 * 7 + 2];
+ 	u16 errors;
+ 	int retries;
+-} jr3_pci_subdev_private;
++};
+ 
+ static struct poll_delay_t poll_delay_min_max(int min, int max)
+ {
+@@ -277,7 +277,7 @@ static int jr3_pci_ai_insn_read(struct comedi_device * dev, struct comedi_subdev
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int result;
+-	jr3_pci_subdev_private *p;
++	struct jr3_pci_subdev_private *p;
+ 	int channel;
+ 
+ 	p = s->private;
+@@ -396,7 +396,7 @@ static void jr3_pci_open(struct comedi_device * dev)
+ 
+ 	printk("jr3_pci_open\n");
+ 	for (i = 0; i < devpriv->n_channels; i++) {
+-		jr3_pci_subdev_private *p;
++		struct jr3_pci_subdev_private *p;
+ 
+ 		p = dev->subdevices[i].private;
+ 		if (p) {
+@@ -465,7 +465,7 @@ static int jr3_download_firmware(struct comedi_device * dev, const u8 * data,
+ 		struct jr3_pci_dev_private *p = dev->private;
+ 
+ 		for (i = 0; i < p->n_channels; i++) {
+-			jr3_pci_subdev_private *sp;
++			struct jr3_pci_subdev_private *sp;
+ 
+ 			sp = dev->subdevices[i].private;
+ 			more = 1;
+@@ -530,7 +530,7 @@ static int jr3_download_firmware(struct comedi_device * dev, const u8 * data,
+ static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice * s)
+ {
+ 	struct poll_delay_t result = poll_delay_min_max(1000, 2000);
+-	jr3_pci_subdev_private *p = s->private;
++	struct jr3_pci_subdev_private *p = s->private;
+ 
+ 	if (p) {
+ 		volatile struct jr3_channel *channel = p->channel;
+@@ -752,7 +752,7 @@ static void jr3_pci_poll_dev(unsigned long data)
+ 	now = jiffies;
+ 	// Poll all channels that are ready to be polled
+ 	for (i = 0; i < devpriv->n_channels; i++) {
+-		jr3_pci_subdev_private *subdevpriv = dev->subdevices[i].private;
++		struct jr3_pci_subdev_private *subdevpriv = dev->subdevices[i].private;
+ 		if (now > subdevpriv->next_time_min) {
+ 			struct poll_delay_t sub_delay;
+ 
+@@ -861,9 +861,9 @@ static int jr3_pci_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 		dev->subdevices[i].n_chan = 8 * 7 + 2;
+ 		dev->subdevices[i].insn_read = jr3_pci_ai_insn_read;
+ 		dev->subdevices[i].private =
+-			kzalloc(sizeof(jr3_pci_subdev_private), GFP_KERNEL);
++			kzalloc(sizeof(struct jr3_pci_subdev_private), GFP_KERNEL);
+ 		if (dev->subdevices[i].private) {
+-			jr3_pci_subdev_private *p;
++			struct jr3_pci_subdev_private *p;
+ 			int j;
+ 
+ 			p = dev->subdevices[i].private;
+@@ -929,7 +929,7 @@ static int jr3_pci_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 
+ 	// Start card timer
+ 	for (i = 0; i < devpriv->n_channels; i++) {
+-		jr3_pci_subdev_private *p = dev->subdevices[i].private;
++		struct jr3_pci_subdev_private *p = dev->subdevices[i].private;
+ 
+ 		p->next_time_min = jiffies + msecs_to_jiffies(500);
+ 		p->next_time_max = jiffies + msecs_to_jiffies(2000);

commit 33a4640f312c4ee583470e7d4b1aaed5026438f6
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:20:20 2009 -0400
+
+    Staging: comedi: Remove unioxx5_subd_priv typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c
+index bf541d472ee0..dd3b1119319b 100644
+--- a/drivers/staging/comedi/drivers/unioxx5.c
++++ b/drivers/staging/comedi/drivers/unioxx5.c
+@@ -72,13 +72,13 @@ Devices: [Fastwel] UNIOxx-5 (unioxx5),
+ #define ALL_2_OUTPUT 1		/* config all digital channels to output */
+ 
+ /* 'private' structure for each subdevice */
+-typedef struct unioxx5_subd_priv {
++struct unioxx5_subd_priv {
+ 	int usp_iobase;
+ 	unsigned char usp_module_type[12];	/* 12 modules. each can be 70L or 73L */
+ 	unsigned char usp_extra_data[12][4];	/* for saving previous written value for analog modules */
+ 	unsigned char usp_prev_wr_val[3];	/* previous written value */
+ 	unsigned char usp_prev_cn_val[3];	/* previous channel value */
+-} unioxx5_subd_priv;
++};
+ 
+ static int unioxx5_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int unioxx5_subdev_write(struct comedi_device * dev, struct comedi_subdevice * subdev,
+@@ -90,17 +90,17 @@ static int unioxx5_insn_config(struct comedi_device * dev, struct comedi_subdevi
+ static int unioxx5_detach(struct comedi_device * dev);
+ static int __unioxx5_subdev_init(struct comedi_subdevice * subdev, int subdev_iobase,
+ 	int minor);
+-static int __unioxx5_digital_write(unioxx5_subd_priv * usp, unsigned int * data,
++static int __unioxx5_digital_write(struct unioxx5_subd_priv * usp, unsigned int * data,
+ 	int channel, int minor);
+-static int __unioxx5_digital_read(unioxx5_subd_priv * usp, unsigned int * data,
++static int __unioxx5_digital_read(struct unioxx5_subd_priv * usp, unsigned int * data,
+ 	int channel, int minor);
+-//static void __unioxx5_digital_config(unioxx5_subd_priv* usp, int mode);
+-static int __unioxx5_analog_write(unioxx5_subd_priv * usp, unsigned int * data,
++//static void __unioxx5_digital_config(struct unioxx5_subd_priv* usp, int mode);
++static int __unioxx5_analog_write(struct unioxx5_subd_priv * usp, unsigned int * data,
+ 	int channel, int minor);
+-static int __unioxx5_analog_read(unioxx5_subd_priv * usp, unsigned int * data,
++static int __unioxx5_analog_read(struct unioxx5_subd_priv * usp, unsigned int * data,
+ 	int channel, int minor);
+ static int __unioxx5_define_chan_offset(int chan_num);
+-static void __unioxx5_analog_config(unioxx5_subd_priv * usp, int channel);
++static void __unioxx5_analog_config(struct unioxx5_subd_priv * usp, int channel);
+ 
+ static struct comedi_driver unioxx5_driver = {
+       driver_name:DRIVER_NAME,
+@@ -159,7 +159,7 @@ static int unioxx5_attach(struct comedi_device * dev, struct comedi_devconfig *
+ static int unioxx5_subdev_read(struct comedi_device * dev, struct comedi_subdevice * subdev,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	unioxx5_subd_priv *usp = subdev->private;
++	struct unioxx5_subd_priv *usp = subdev->private;
+ 	int channel, type;
+ 
+ 	channel = CR_CHAN(insn->chanspec);
+@@ -179,7 +179,7 @@ static int unioxx5_subdev_read(struct comedi_device * dev, struct comedi_subdevi
+ static int unioxx5_subdev_write(struct comedi_device * dev, struct comedi_subdevice * subdev,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	unioxx5_subd_priv *usp = subdev->private;
++	struct unioxx5_subd_priv *usp = subdev->private;
+ 	int channel, type;
+ 
+ 	channel = CR_CHAN(insn->chanspec);
+@@ -201,7 +201,7 @@ static int unioxx5_insn_config(struct comedi_device * dev, struct comedi_subdevi
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel_offset, flags, channel = CR_CHAN(insn->chanspec), type;
+-	unioxx5_subd_priv *usp = subdev->private;
++	struct unioxx5_subd_priv *usp = subdev->private;
+ 	int mask = 1 << (channel & 0x07);
+ 
+ 	type = usp->usp_module_type[channel / 2];
+@@ -251,7 +251,7 @@ static int unioxx5_detach(struct comedi_device * dev)
+ {
+ 	int i;
+ 	struct comedi_subdevice *subdev;
+-	unioxx5_subd_priv *usp;
++	struct unioxx5_subd_priv *usp;
+ 
+ 	for (i = 0; i < dev->n_subdevices; i++) {
+ 		subdev = &dev->subdevices[i];
+@@ -267,7 +267,7 @@ static int unioxx5_detach(struct comedi_device * dev)
+ static int __unioxx5_subdev_init(struct comedi_subdevice * subdev, int subdev_iobase,
+ 	int minor)
+ {
+-	unioxx5_subd_priv *usp;
++	struct unioxx5_subd_priv *usp;
+ 	int i, to, ndef_flag = 0;
+ 
+ 	if (!request_region(subdev_iobase, UNIOXX5_SIZE, DRIVER_NAME)) {
+@@ -275,7 +275,7 @@ static int __unioxx5_subdev_init(struct comedi_subdevice * subdev, int subdev_io
+ 		return -EIO;
+ 	}
+ 
+-	if ((usp = (unioxx5_subd_priv *) kzalloc(sizeof(*usp),
++	if ((usp = (struct unioxx5_subd_priv *) kzalloc(sizeof(*usp),
+ 				GFP_KERNEL)) == NULL) {
+ 		printk(KERN_ERR "comedi%d: erorr! --> out of memory!\n", minor);
+ 		return -1;
+@@ -330,7 +330,7 @@ static int __unioxx5_subdev_init(struct comedi_subdevice * subdev, int subdev_io
+ 	return 0;
+ }
+ 
+-static int __unioxx5_digital_write(unioxx5_subd_priv * usp, unsigned int * data,
++static int __unioxx5_digital_write(struct unioxx5_subd_priv * usp, unsigned int * data,
+ 	int channel, int minor)
+ {
+ 	int channel_offset, val;
+@@ -357,7 +357,7 @@ static int __unioxx5_digital_write(unioxx5_subd_priv * usp, unsigned int * data,
+ }
+ 
+ /* function for digital reading */
+-static int __unioxx5_digital_read(unioxx5_subd_priv * usp, unsigned int * data,
++static int __unioxx5_digital_read(struct unioxx5_subd_priv * usp, unsigned int * data,
+ 	int channel, int minor)
+ {
+ 	int channel_offset, mask = 1 << (channel & 0x07);
+@@ -380,7 +380,7 @@ static int __unioxx5_digital_read(unioxx5_subd_priv * usp, unsigned int * data,
+ }
+ 
+ #if 0				/* not used? */
+-static void __unioxx5_digital_config(unioxx5_subd_priv * usp, int mode)
++static void __unioxx5_digital_config(struct unioxx5_subd_priv * usp, int mode)
+ {
+ 	int i, mask;
+ 
+@@ -396,7 +396,7 @@ static void __unioxx5_digital_config(unioxx5_subd_priv * usp, int mode)
+ }
+ #endif
+ 
+-static int __unioxx5_analog_write(unioxx5_subd_priv * usp, unsigned int * data,
++static int __unioxx5_analog_write(struct unioxx5_subd_priv * usp, unsigned int * data,
+ 	int channel, int minor)
+ {
+ 	int module, i;
+@@ -431,7 +431,7 @@ static int __unioxx5_analog_write(unioxx5_subd_priv * usp, unsigned int * data,
+ 	return 1;
+ }
+ 
+-static int __unioxx5_analog_read(unioxx5_subd_priv * usp, unsigned int * data,
++static int __unioxx5_analog_read(struct unioxx5_subd_priv * usp, unsigned int * data,
+ 	int channel, int minor)
+ {
+ 	int module_no, read_ch;
+@@ -471,7 +471,7 @@ static int __unioxx5_analog_read(unioxx5_subd_priv * usp, unsigned int * data,
+ }
+ 
+ /* configure channels for analog i/o (even to output, odd to input) */
+-static void __unioxx5_analog_config(unioxx5_subd_priv * usp, int channel)
++static void __unioxx5_analog_config(struct unioxx5_subd_priv * usp, int channel)
+ {
+ 	int chan_a, chan_b, conf, channel_offset;
+ 

commit c0d1482252b9b87c62b8d0ddb7ceecc369c6e34e
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:20:14 2009 -0400
+
+    Staging: comedi: Remove dnp_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c
+index 098b7b098828..1628d216cdd4 100644
+--- a/drivers/staging/comedi/drivers/ssv_dnp.c
++++ b/drivers/staging/comedi/drivers/ssv_dnp.c
+@@ -52,14 +52,14 @@ Status: unknown
+ 
+ /* This data structure holds information about the supported boards -------- */
+ 
+-typedef struct dnp_board_struct {
++struct dnp_board {
+ 	const char *name;
+ 	int ai_chans;
+ 	int ai_bits;
+ 	int have_dio;
+-} dnp_board;
++};
+ 
+-static const dnp_board dnp_boards[] = {	/* we only support one DNP 'board'   */
++static const struct dnp_board dnp_boards[] = {	/* we only support one DNP 'board'   */
+ 	{			/* variant at the moment             */
+ 	      name:	"dnp-1486",
+ 	      ai_chans:16,
+@@ -69,7 +69,7 @@ static const dnp_board dnp_boards[] = {	/* we only support one DNP 'board'   */
+ };
+ 
+ /* Useful for shorthand access to the particular board structure ----------- */
+-#define thisboard ((const dnp_board *)dev->board_ptr)
++#define thisboard ((const struct dnp_board *)dev->board_ptr)
+ 
+ /* This structure is for data unique to the DNP driver --------------------- */
+ struct dnp_private_data {
+@@ -99,8 +99,8 @@ static struct comedi_driver driver_dnp = {
+       detach:dnp_detach,
+       board_name:&dnp_boards[0].name,
+ 	/* only necessary for non-PnP devs   */
+-      offset:sizeof(dnp_board),/* like ISA-PnP, PCI or PCMCIA.      */
+-      num_names:sizeof(dnp_boards) / sizeof(dnp_board),
++      offset:sizeof(struct dnp_board),/* like ISA-PnP, PCI or PCMCIA.      */
++      num_names:sizeof(dnp_boards) / sizeof(struct dnp_board),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_dnp);

commit c1dd2fa6a12bfba92d3522fa43173480f52dbaed
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:20:09 2009 -0400
+
+    Staging: comedi: Remove skel_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c
+index b8cdd6f8fc0e..9009d77146ed 100644
+--- a/drivers/staging/comedi/drivers/skel.c
++++ b/drivers/staging/comedi/drivers/skel.c
+@@ -88,13 +88,14 @@ Configuration Options:
+  * boards in this way is optional, and completely driver-dependent.
+  * Some drivers use arrays such as this, other do not.
+  */
+-typedef struct skel_board_struct {
++struct skel_board {
+ 	const char *name;
+ 	int ai_chans;
+ 	int ai_bits;
+ 	int have_dio;
+-} skel_board;
+-static const skel_board skel_boards[] = {
++};
++
++static const struct skel_board skel_boards[] = {
+ 	{
+ 	      name:	"skel-100",
+ 	      ai_chans:16,
+@@ -125,7 +126,7 @@ MODULE_DEVICE_TABLE(pci, skel_pci_table);
+ /*
+  * Useful for shorthand access to the particular board structure
+  */
+-#define thisboard ((const skel_board *)dev->board_ptr)
++#define thisboard ((const struct skel_board *)dev->board_ptr)
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+@@ -177,8 +178,8 @@ static struct comedi_driver driver_skel = {
+ 	 * devices are such boards.
+ 	 */
+       board_name:&skel_boards[0].name,
+-      offset:sizeof(skel_board),
+-      num_names:sizeof(skel_boards) / sizeof(skel_board),
++      offset:sizeof(struct skel_board),
++      num_names:sizeof(skel_boards) / sizeof(struct skel_board),
+ };
+ 
+ static int skel_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,

commit ca9ed0f295a5e85861c63713406d86643e570580
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:20:03 2009 -0400
+
+    Staging: comedi: Remove serial2002_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
+index 77c234533005..0e48887b55cb 100644
+--- a/drivers/staging/comedi/drivers/serial2002.c
++++ b/drivers/staging/comedi/drivers/serial2002.c
+@@ -46,11 +46,11 @@ Status: in development
+  * boards in this way is optional, and completely driver-dependent.
+  * Some drivers use arrays such as this, other do not.
+  */
+-typedef struct serial2002_board_struct {
++struct serial2002_board {
+ 	const char *name;
+-} serial2002_board;
++};
+ 
+-static const serial2002_board serial2002_boards[] = {
++static const struct serial2002_board serial2002_boards[] = {
+ 	{
+       name:	"serial2002"}
+ };
+@@ -58,7 +58,7 @@ static const serial2002_board serial2002_boards[] = {
+ /*
+  * Useful for shorthand access to the particular board structure
+  */
+-#define thisboard ((const serial2002_board *)dev->board_ptr)
++#define thisboard ((const struct serial2002_board *)dev->board_ptr)
+ 
+ struct serial2002_range_table_t {
+ 
+@@ -95,8 +95,8 @@ struct comedi_driver driver_serial2002 = {
+       attach:serial2002_attach,
+       detach:serial2002_detach,
+       board_name:&serial2002_boards[0].name,
+-      offset:sizeof(serial2002_board),
+-      num_names:sizeof(serial2002_boards) / sizeof(serial2002_board),
++      offset:sizeof(struct serial2002_board),
++      num_names:sizeof(serial2002_boards) / sizeof(struct serial2002_board),
+ };
+ 
+ static int serial2002_di_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,

commit dfb0503e2baf2292da93faae78db4bb98d9f095e
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:19:58 2009 -0400
+
+    Staging: comedi: Remove S526_GPCT_APP_CLASS typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
+index d112515feccd..939e17f993d9 100644
+--- a/drivers/staging/comedi/drivers/s526.c
++++ b/drivers/staging/comedi/drivers/s526.c
+@@ -135,19 +135,19 @@ union {
+ 
+ /* Different Application Classes for GPCT Subdevices */
+ /* The list is not exhaustive and needs discussion! */
+-typedef enum {
++enum S526_GPCT_APP_CLASS {
+ 	CountingAndTimeMeasurement,
+ 	SinglePulseGeneration,
+ 	PulseTrainGeneration,
+ 	PositionMeasurement,
+ 	Miscellaneous
+-} S526_GPCT_APP_CLASS;
++};
+ 
+ /* Config struct for different GPCT subdevice Application Classes and
+    their options
+ */
+ typedef struct s526GPCTConfig {
+-	S526_GPCT_APP_CLASS app;
++	enum S526_GPCT_APP_CLASS app;
+ 	int data[MAX_GPCT_CONFIG_DATA];
+ } s526_gpct_config_t;
+ 

commit 387c136adc72da7f06f37274822ad9c38f529156
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:19:47 2009 -0400
+
+    Staging: comedi: Remove pcmda12_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c
+index 81233355d67b..2a1ff465602a 100644
+--- a/drivers/staging/comedi/drivers/pcmda12.c
++++ b/drivers/staging/comedi/drivers/pcmda12.c
+@@ -68,9 +68,9 @@ Configuration Options:
+ /*
+  * Bords
+  */
+-typedef struct pcmda12_board_struct {
++struct pcmda12_board {
+ 	const char *name;
+-} pcmda12_board;
++};
+ 
+ /* note these have no effect and are merely here for reference..
+    these are configured by jumpering the board! */
+@@ -81,7 +81,7 @@ static const struct comedi_lrange pcmda12_ranges = {
+ 		}
+ };
+ 
+-static const pcmda12_board pcmda12_boards[] = {
++static const struct pcmda12_board pcmda12_boards[] = {
+ 	{
+ 	      name:	"pcmda12",
+ 		},
+@@ -90,7 +90,7 @@ static const pcmda12_board pcmda12_boards[] = {
+ /*
+  * Useful for shorthand access to the particular board structure
+  */
+-#define thisboard ((const pcmda12_board *)dev->board_ptr)
++#define thisboard ((const struct pcmda12_board *)dev->board_ptr)
+ 
+ struct pcmda12_private {
+ 
+@@ -136,8 +136,8 @@ static struct comedi_driver driver = {
+ 	 * devices are such boards.
+ 	 */
+       board_name:&pcmda12_boards[0].name,
+-      offset:sizeof(pcmda12_board),
+-      num_names:sizeof(pcmda12_boards) / sizeof(pcmda12_board),
++      offset:sizeof(struct pcmda12_board),
++      num_names:sizeof(pcmda12_boards) / sizeof(struct pcmda12_board),
+ };
+ 
+ static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,

commit e15849e54405152087cd343437747db8d931fcd7
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:19:42 2009 -0400
+
+    Staging: comedi: Remove pcmuio_subdev_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
+index b995107779b4..89cf5d417748 100644
+--- a/drivers/staging/comedi/drivers/pcmuio.c
++++ b/drivers/staging/comedi/drivers/pcmuio.c
+@@ -172,7 +172,7 @@ static const struct pcmuio_board pcmuio_boards[] = {
+ #define thisboard ((const struct pcmuio_board *)dev->board_ptr)
+ 
+ /* this structure is for data unique to this subdevice.  */
+-typedef struct {
++struct pcmuio_subdev_private {
+ 	/* mapping of halfwords (bytes) in port/chanarray to iobase */
+ 	unsigned long iobases[PORTS_PER_SUBDEV];
+ 
+@@ -192,7 +192,7 @@ typedef struct {
+ 		int continuous;
+ 		spinlock_t spinlock;
+ 	} intr;
+-} pcmuio_subdev_private;
++};
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+@@ -207,7 +207,7 @@ typedef struct {
+ 		unsigned int irq;
+ 		spinlock_t spinlock;
+ 	} asics[MAX_ASICS];
+-	pcmuio_subdev_private *sprivs;
++	struct pcmuio_subdev_private *sprivs;
+ } pcmuio_private;
+ 
+ /*
+@@ -215,7 +215,7 @@ typedef struct {
+  * access the private structure.
+  */
+ #define devpriv ((pcmuio_private *)dev->private)
+-#define subpriv ((pcmuio_subdev_private *)s->private)
++#define subpriv ((struct pcmuio_subdev_private *)s->private)
+ /*
+  * The struct comedi_driver structure tells the Comedi core module
+  * which functions to call to configure/deconfigure (attach/detach)
+@@ -329,7 +329,7 @@ static int pcmuio_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	chans_left = CHANS_PER_ASIC * thisboard->num_asics;
+ 	n_subdevs = CALC_N_SUBDEVS(chans_left);
+ 	devpriv->sprivs =
+-		kcalloc(n_subdevs, sizeof(pcmuio_subdev_private), GFP_KERNEL);
++		kcalloc(n_subdevs, sizeof(struct pcmuio_subdev_private), GFP_KERNEL);
+ 	if (!devpriv->sprivs) {
+ 		printk("cannot allocate subdevice private data structures\n");
+ 		return -ENOMEM;

commit 4467df9406bc40fdbc9cf64cfb2e95cba8f77e1e
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:19:37 2009 -0400
+
+    Staging: comedi: Remove pcmmio_subdev_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
+index 75db61055db3..2d4f9689dd84 100644
+--- a/drivers/staging/comedi/drivers/pcmmio.c
++++ b/drivers/staging/comedi/drivers/pcmmio.c
+@@ -200,7 +200,7 @@ static const struct pcmmio_board pcmmio_boards[] = {
+ #define thisboard ((const struct pcmmio_board *)dev->board_ptr)
+ 
+ /* this structure is for data unique to this subdevice.  */
+-typedef struct {
++struct pcmmio_subdev_private {
+ 
+ 	union {
+ 		/* for DIO: mapping of halfwords (bytes) in port/chanarray to iobase */
+@@ -233,7 +233,7 @@ typedef struct {
+ 			unsigned int shadow_samples[8];	/* the last unsigned int data written */
+ 		} ao;
+ 	};
+-} pcmmio_subdev_private;
++};
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+@@ -249,7 +249,7 @@ typedef struct {
+ 		unsigned int irq;
+ 		spinlock_t spinlock;
+ 	} asics[MAX_ASICS];
+-	pcmmio_subdev_private *sprivs;
++	struct pcmmio_subdev_private *sprivs;
+ } pcmmio_private;
+ 
+ /*
+@@ -257,7 +257,7 @@ typedef struct {
+  * access the private structure.
+  */
+ #define devpriv ((pcmmio_private *)dev->private)
+-#define subpriv ((pcmmio_subdev_private *)s->private)
++#define subpriv ((struct pcmmio_subdev_private *)s->private)
+ /*
+  * The struct comedi_driver structure tells the Comedi core module
+  * which functions to call to configure/deconfigure (attach/detach)
+@@ -372,7 +372,7 @@ static int pcmmio_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	n_dio_subdevs = CALC_N_DIO_SUBDEVS(chans_left);
+ 	n_subdevs = n_dio_subdevs + 2;
+ 	devpriv->sprivs =
+-		kcalloc(n_subdevs, sizeof(pcmmio_subdev_private), GFP_KERNEL);
++		kcalloc(n_subdevs, sizeof(struct pcmmio_subdev_private), GFP_KERNEL);
+ 	if (!devpriv->sprivs) {
+ 		printk("cannot allocate subdevice private data structures\n");
+ 		return -ENOMEM;

commit 97baaedfa440fb988d8725cc9a3b16bcc12ff611
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:19:31 2009 -0400
+
+    Staging: comedi: Remove pci20xxx_subdev_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c
+index 624d44c3969f..80825ba25418 100644
+--- a/drivers/staging/comedi/drivers/ii_pci20kc.c
++++ b/drivers/staging/comedi/drivers/ii_pci20kc.c
+@@ -133,7 +133,7 @@ options for PCI-20341M:
+ #define PCI20341_MUX			0x04	/* Enable on-board MUX */
+ #define PCI20341_SCANLIST		0x80	/* Channel/Gain Scan List */
+ 
+-typedef union {
++union pci20xxx_subdev_private {
+ 	void *iobase;
+ 	struct {
+ 		void *iobase;
+@@ -146,12 +146,12 @@ typedef union {
+ 		int settling_time;
+ 		int ai_gain;
+ 	} pci20341;
+-} pci20xxx_subdev_private;
++};
+ 
+ struct pci20xxx_private {
+ 
+ 	void *ioaddr;
+-	pci20xxx_subdev_private subdev_private[PCI20000_MODULES];
++	union pci20xxx_subdev_private subdev_private[PCI20000_MODULES];
+ };
+ 
+ 
+@@ -207,7 +207,7 @@ static int pci20xxx_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	int ret;
+ 	int id;
+ 	struct comedi_subdevice *s;
+-	pci20xxx_subdev_private *sdp;
++	union pci20xxx_subdev_private *sdp;
+ 
+ 	if ((ret = alloc_subdevices(dev, 1 + PCI20000_MODULES)) < 0)
+ 		return ret;
+@@ -286,7 +286,7 @@ static const struct comedi_lrange *pci20006_range_list[] = {
+ static int pci20006_init(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	int opt0, int opt1)
+ {
+-	pci20xxx_subdev_private *sdp = s->private;
++	union pci20xxx_subdev_private *sdp = s->private;
+ 
+ 	if (opt0 < 0 || opt0 > 2)
+ 		opt0 = 0;
+@@ -311,7 +311,7 @@ static int pci20006_init(struct comedi_device * dev, struct comedi_subdevice * s
+ static int pci20006_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	pci20xxx_subdev_private *sdp = s->private;
++	union pci20xxx_subdev_private *sdp = s->private;
+ 
+ 	data[0] = sdp->pci20006.last_data[CR_CHAN(insn->chanspec)];
+ 
+@@ -321,7 +321,7 @@ static int pci20006_insn_read(struct comedi_device * dev, struct comedi_subdevic
+ static int pci20006_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	pci20xxx_subdev_private *sdp = s->private;
++	union pci20xxx_subdev_private *sdp = s->private;
+ 	int hi, lo;
+ 	unsigned int boarddata;
+ 
+@@ -371,7 +371,7 @@ static const struct comedi_lrange *const pci20341_ranges[] = {
+ static int pci20341_init(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	int opt0, int opt1)
+ {
+-	pci20xxx_subdev_private *sdp = s->private;
++	union pci20xxx_subdev_private *sdp = s->private;
+ 	int option;
+ 
+ 	/* options handling */
+@@ -402,7 +402,7 @@ static int pci20341_init(struct comedi_device * dev, struct comedi_subdevice * s
+ static int pci20341_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	pci20xxx_subdev_private *sdp = s->private;
++        union pci20xxx_subdev_private *sdp = s->private;
+ 	unsigned int i = 0, j = 0;
+ 	int lo, hi;
+ 	unsigned char eoc;	/* end of conversion */

commit e2b523aab1b04e7edc092588abbafa67f560deb4
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:19:26 2009 -0400
+
+    Staging: comedi: Remove config_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
+index 91fc281c1e9f..77c234533005 100644
+--- a/drivers/staging/comedi/drivers/serial2002.c
++++ b/drivers/staging/comedi/drivers/serial2002.c
+@@ -401,16 +401,18 @@ static void serial_2002_open(struct comedi_device * dev)
+ 		printk("serial_2002: file open error = %ld\n",
+ 			PTR_ERR(devpriv->tty));
+ 	} else {
+-		typedef struct {
++		struct config_t {
++
+ 			int kind;
+ 			int bits;
+ 			int min;
+ 			int max;
+-		} config_t;
+-		config_t dig_in_config[32];
+-		config_t dig_out_config[32];
+-		config_t chan_in_config[32];
+-		config_t chan_out_config[32];
++		};
++
++		struct config_t dig_in_config[32];
++		struct config_t dig_out_config[32];
++		struct config_t chan_in_config[32];
++		struct config_t chan_out_config[32];
+ 		int i;
+ 
+ 		for (i = 0; i < 32; i++) {
+@@ -443,7 +445,7 @@ static void serial_2002_open(struct comedi_device * dev)
+ 				break;
+ 			} else {
+ 				int command, channel, kind;
+-				config_t *cur_config = 0;
++				struct config_t *cur_config = 0;
+ 
+ 				channel = data.value & 0x1f;
+ 				kind = (data.value >> 5) & 0x7;
+@@ -554,7 +556,7 @@ static void serial_2002_open(struct comedi_device * dev)
+ 		}
+ 		for (i = 0; i <= 4; i++) {
+ 			// Fill in subdev data
+-			config_t *c;
++			struct config_t *c;
+ 			unsigned char *mapping = 0;
+ 			struct serial2002_range_table_t *range = 0;
+ 			int kind = 0;

commit 201007e8bc7b3e94be823eda5a684199152410d1
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:19:20 2009 -0400
+
+    Staging: comedi: Remove rti802_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c
+index 656742be898a..cc2c385db0b0 100644
+--- a/drivers/staging/comedi/drivers/rti802.c
++++ b/drivers/staging/comedi/drivers/rti802.c
+@@ -58,15 +58,15 @@ static struct comedi_driver driver_rti802 = {
+ 
+ COMEDI_INITCLEANUP(driver_rti802);
+ 
+-typedef struct {
++struct rti802_private {
+ 	enum {
+ 		dac_2comp, dac_straight
+ 	} dac_coding[8];
+ 	const struct comedi_lrange *range_type_list[8];
+ 	unsigned int ao_readback[8];
+-} rti802_private;
++};
+ 
+-#define devpriv ((rti802_private *)dev->private)
++#define devpriv ((struct rti802_private *)dev->private)
+ 
+ static int rti802_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+@@ -113,7 +113,7 @@ static int rti802_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	dev->board_name = "rti802";
+ 
+ 	if (alloc_subdevices(dev, 1) < 0
+-		|| alloc_private(dev, sizeof(rti802_private))) {
++		|| alloc_private(dev, sizeof(struct rti802_private))) {
+ 		return -ENOMEM;
+ 	}
+ 

commit 9335f2613b6beca0f3f3e20ce5a550d1ffe66aa2
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:19:15 2009 -0400
+
+    Staging: comedi: Remove rti800_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c
+index bd579711a519..594c5e82211f 100644
+--- a/drivers/staging/comedi/drivers/rti800.c
++++ b/drivers/staging/comedi/drivers/rti800.c
+@@ -145,7 +145,7 @@ COMEDI_INITCLEANUP(driver_rti800);
+ 
+ static irqreturn_t rti800_interrupt(int irq, void *dev PT_REGS_ARG);
+ 
+-typedef struct {
++struct rti800_private {
+ 	enum {
+ 		adc_diff, adc_pseudodiff, adc_singleended
+ 	} adc_mux;
+@@ -164,9 +164,9 @@ typedef struct {
+ 	const struct comedi_lrange *ao_range_type_list[2];
+ 	unsigned int ao_readback[2];
+ 	int muxgain_bits;
+-} rti800_private;
++};
+ 
+-#define devpriv ((rti800_private *)dev->private)
++#define devpriv ((struct rti800_private *)dev->private)
+ 
+ #define RTI800_TIMEOUT 100
+ 
+@@ -351,7 +351,7 @@ static int rti800_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 
+ 	if ((ret = alloc_subdevices(dev, 4)) < 0)
+ 		return ret;
+-	if ((ret = alloc_private(dev, sizeof(rti800_private))) < 0)
++	if ((ret = alloc_private(dev, sizeof(struct rti800_private))) < 0)
+ 		return ret;
+ 
+ 	devpriv->adc_mux = it->options[2];

commit 70a6001aeffeaa12f2a1c21470e8f3bdfb6ef8e7
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:19:10 2009 -0400
+
+    Staging: comedi: Remove pcmuio_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
+index 97ae34955d67..b995107779b4 100644
+--- a/drivers/staging/comedi/drivers/pcmuio.c
++++ b/drivers/staging/comedi/drivers/pcmuio.c
+@@ -146,14 +146,14 @@ Configuration Options:
+  * boards in this way is optional, and completely driver-dependent.
+  * Some drivers use arrays such as this, other do not.
+  */
+-typedef struct pcmuio_board_struct {
++struct pcmuio_board {
+ 	const char *name;
+ 	const int num_asics;
+ 	const int num_channels_per_port;
+ 	const int num_ports;
+-} pcmuio_board;
++};
+ 
+-static const pcmuio_board pcmuio_boards[] = {
++static const struct pcmuio_board pcmuio_boards[] = {
+ 	{
+ 	      name:	"pcmuio48",
+ 	      num_asics:1,
+@@ -169,7 +169,7 @@ static const pcmuio_board pcmuio_boards[] = {
+ /*
+  * Useful for shorthand access to the particular board structure
+  */
+-#define thisboard ((const pcmuio_board *)dev->board_ptr)
++#define thisboard ((const struct pcmuio_board *)dev->board_ptr)
+ 
+ /* this structure is for data unique to this subdevice.  */
+ typedef struct {
+@@ -249,8 +249,8 @@ static struct comedi_driver driver = {
+ 	 * devices are such boards.
+ 	 */
+       board_name:&pcmuio_boards[0].name,
+-      offset:sizeof(pcmuio_board),
+-      num_names:sizeof(pcmuio_boards) / sizeof(pcmuio_board),
++      offset:sizeof(struct pcmuio_board),
++      num_names:sizeof(pcmuio_boards) / sizeof(struct pcmuio_board),
+ };
+ 
+ static int pcmuio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,

commit 657f81ec27758ddb859ea9c74929996bea607194
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:19:04 2009 -0400
+
+    Staging: comedi: Remove pcmmio_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
+index 85c205418703..75db61055db3 100644
+--- a/drivers/staging/comedi/drivers/pcmmio.c
++++ b/drivers/staging/comedi/drivers/pcmmio.c
+@@ -154,7 +154,7 @@ static int ao_winsn(struct comedi_device *, struct comedi_subdevice *, struct co
+  * boards in this way is optional, and completely driver-dependent.
+  * Some drivers use arrays such as this, other do not.
+  */
+-typedef struct pcmmio_board_struct {
++struct pcmmio_board {
+ 	const char *name;
+ 	const int dio_num_asics;
+ 	const int dio_num_ports;
+@@ -165,7 +165,7 @@ typedef struct pcmmio_board_struct {
+ 	const int n_ao_chans;
+ 	const struct comedi_lrange *ai_range_table, *ao_range_table;
+ 	comedi_insn_fn_t ai_rinsn, ao_rinsn, ao_winsn;
+-} pcmmio_board;
++};
+ 
+ static const struct comedi_lrange ranges_ai =
+ 	{ 4, {RANGE(-5., 5.), RANGE(-10., 10.), RANGE(0., 5.), RANGE(0.,
+@@ -177,7 +177,7 @@ static const struct comedi_lrange ranges_ao =
+ 	RANGE(-2.5, 2.5), RANGE(-2.5, 7.5)}
+ };
+ 
+-static const pcmmio_board pcmmio_boards[] = {
++static const struct pcmmio_board pcmmio_boards[] = {
+ 	{
+ 	      name:	"pcmmio",
+ 	      dio_num_asics:1,
+@@ -197,7 +197,7 @@ static const pcmmio_board pcmmio_boards[] = {
+ /*
+  * Useful for shorthand access to the particular board structure
+  */
+-#define thisboard ((const pcmmio_board *)dev->board_ptr)
++#define thisboard ((const struct pcmmio_board *)dev->board_ptr)
+ 
+ /* this structure is for data unique to this subdevice.  */
+ typedef struct {
+@@ -291,8 +291,8 @@ static struct comedi_driver driver = {
+ 	 * devices are such boards.
+ 	 */
+       board_name:&pcmmio_boards[0].name,
+-      offset:sizeof(pcmmio_board),
+-      num_names:sizeof(pcmmio_boards) / sizeof(pcmmio_board),
++      offset:sizeof(struct pcmmio_board),
++      num_names:sizeof(pcmmio_boards) / sizeof(struct pcmmio_board),
+ };
+ 
+ static int pcmmio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,

commit d89da61754236aee5ab8faf0cab7f5449a2fdd34
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:18:59 2009 -0400
+
+    Staging: comedi: Remove dt2811_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c
+index 722e3f54e468..d5e529826ad9 100644
+--- a/drivers/staging/comedi/drivers/dt2811.c
++++ b/drivers/staging/comedi/drivers/dt2811.c
+@@ -238,7 +238,8 @@ static int dt2811_do_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+ 	struct comedi_insn * insn, unsigned int * data);
+ 
+ enum { card_2811_pgh, card_2811_pgl };
+-typedef struct {
++
++struct dt2811_private {
+ 	int ntrig;
+ 	int curadchan;
+ 	enum {
+@@ -249,9 +250,9 @@ typedef struct {
+ 	} dac_range[2];
+ 	const struct comedi_lrange *range_type_list[2];
+ 	unsigned int ao_readback[2];
+-} dt2811_private;
++};
+ 
+-#define devpriv ((dt2811_private *)dev->private)
++#define devpriv ((struct dt2811_private *)dev->private)
+ 
+ static const struct comedi_lrange *dac_range_types[] = {
+ 	&range_bipolar5,
+@@ -377,7 +378,7 @@ static int dt2811_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 
+ 	if ((ret = alloc_subdevices(dev, 4)) < 0)
+ 		return ret;
+-	if ((ret = alloc_private(dev, sizeof(dt2811_private))) < 0)
++	if ((ret = alloc_private(dev, sizeof(struct dt2811_private))) < 0)
+ 		return ret;
+ 	switch (it->options[2]) {
+ 	case 0:

commit 51091b5420c564093d721d2dad99a55bbb22d0d0
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:18:37 2009 -0400
+
+    Staging: comedi: Remove pcl812_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
+index 07a109839b42..424e8096624b 100644
+--- a/drivers/staging/comedi/drivers/pcl812.c
++++ b/drivers/staging/comedi/drivers/pcl812.c
+@@ -386,7 +386,8 @@ static struct comedi_driver driver_pcl812 = {
+ 
+ COMEDI_INITCLEANUP(driver_pcl812);
+ 
+-typedef struct {
++struct pcl812_private {
++
+ 	unsigned char valid;	// =1 device is OK
+ 	unsigned char dma;	// >0 use dma ( usedDMA channel)
+ 	unsigned char use_diff;	// =1 diff inputs
+@@ -418,9 +419,10 @@ typedef struct {
+ 	unsigned int last_dma_run;	// how many bytes to transfer on last DMA buffer
+ 	unsigned int max_812_ai_mode0_rangewait;	// setling time for gain
+ 	unsigned int ao_readback[2];	// data for AO readback
+-} pcl812_private;
++};
++
+ 
+-#define devpriv ((pcl812_private *)dev->private)
++#define devpriv ((struct pcl812_private *)dev->private)
+ 
+ /*
+ ==============================================================================
+@@ -1282,7 +1284,7 @@ static int pcl812_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	}
+ 	dev->iobase = iobase;
+ 
+-	if ((ret = alloc_private(dev, sizeof(pcl812_private))) < 0) {
++	if ((ret = alloc_private(dev, sizeof(struct pcl812_private))) < 0) {
+ 		free_resources(dev);
+ 		return ret;	/* Can't alloc mem */
+ 	}

commit bf7f0610c6c215fb8a8cd26b697902810ee5b9e9
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:18:32 2009 -0400
+
+    Staging: comedi: Remove pcl726_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c
+index 8f0425f280ec..deda5de70579 100644
+--- a/drivers/staging/comedi/drivers/pcl726.c
++++ b/drivers/staging/comedi/drivers/pcl726.c
+@@ -161,12 +161,14 @@ static struct comedi_driver driver_pcl726 = {
+ 
+ COMEDI_INITCLEANUP(driver_pcl726);
+ 
+-typedef struct {
++struct pcl726_private {
++
+ 	int bipolar[12];
+ 	const struct comedi_lrange *rangelist[12];
+ 	unsigned int ao_readback[12];
+-} pcl726_private;
+-#define devpriv ((pcl726_private *)dev->private)
++};
++
++#define devpriv ((struct pcl726_private *)dev->private)
+ 
+ static int pcl726_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+@@ -260,7 +262,7 @@ static int pcl726_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 
+ 	dev->board_name = this_board->name;
+ 
+-	if ((ret = alloc_private(dev, sizeof(pcl726_private))) < 0)
++	if ((ret = alloc_private(dev, sizeof(struct pcl726_private))) < 0)
+ 		return -ENOMEM;
+ 
+ 	for (i = 0; i < 12; i++) {

commit e1c8638f3fb47c25b8dba170aadc8e29619fcd67
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:18:27 2009 -0400
+
+    Staging: comedi: Remove pcl711_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c
+index 3e83b6cf693e..fefbe1ca654a 100644
+--- a/drivers/staging/comedi/drivers/pcl711.c
++++ b/drivers/staging/comedi/drivers/pcl711.c
+@@ -168,7 +168,8 @@ static struct comedi_driver driver_pcl711 = {
+ 
+ COMEDI_INITCLEANUP(driver_pcl711);
+ 
+-typedef struct {
++struct pcl711_private {
++
+ 	int board;
+ 	int adchan;
+ 	int ntrig;
+@@ -177,9 +178,10 @@ typedef struct {
+ 	unsigned int ao_readback[2];
+ 	unsigned int divisor1;
+ 	unsigned int divisor2;
+-} pcl711_private;
++};
++
+ 
+-#define devpriv ((pcl711_private *)dev->private)
++#define devpriv ((struct pcl711_private *)dev->private)
+ 
+ static irqreturn_t pcl711_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+@@ -548,7 +550,7 @@ static int pcl711_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 
+ 	if ((ret = alloc_subdevices(dev, 4)) < 0)
+ 		return ret;
+-	if ((ret = alloc_private(dev, sizeof(pcl711_private))) < 0)
++	if ((ret = alloc_private(dev, sizeof(struct pcl711_private))) < 0)
+ 		return ret;
+ 
+ 	s = dev->subdevices + 0;

commit 2e2269f90f2bb4e9438849f0690daba5cba29fc5
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:18:21 2009 -0400
+
+    Staging: comedi: Remove cnt_device_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c
+index 6f538720d79f..79f6fe5646c5 100644
+--- a/drivers/staging/comedi/drivers/ke_counter.c
++++ b/drivers/staging/comedi/drivers/ke_counter.c
+@@ -82,11 +82,13 @@ static const struct cnt_board_struct cnt_boards[] = {
+ 
+ /*-- device private structure -----------------------------------------------*/
+ 
+-typedef struct {
++struct cnt_device_private {
++
+ 	struct pci_dev *pcidev;
+-} cnt_device_private;
++};
++
+ 
+-#define devpriv ((cnt_device_private *)dev->private)
++#define devpriv ((struct cnt_device_private *)dev->private)
+ 
+ static struct comedi_driver cnt_driver = {
+       driver_name:CNT_DRIVER_NAME,
+@@ -155,7 +157,7 @@ static int cnt_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ 	int error, i;
+ 
+ 	/* allocate device private structure */
+-	if ((error = alloc_private(dev, sizeof(cnt_device_private))) < 0) {
++	if ((error = alloc_private(dev, sizeof(struct cnt_device_private))) < 0) {
+ 		return error;
+ 	}
+ 

commit 83101a1770982817ecbcb7679439352795bc7a47
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:18:16 2009 -0400
+
+    Staging: comedi: Remove poll_delay_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
+index 680cc738cc5c..a147772c83fe 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -137,10 +137,12 @@ struct jr3_pci_dev_private {
+ };
+ 
+ 
+-typedef struct {
++struct poll_delay_t {
++
+ 	int min;
+ 	int max;
+-} poll_delay_t;
++};
++
+ 
+ typedef struct {
+ 	volatile struct jr3_channel *channel;
+@@ -166,9 +168,9 @@ typedef struct {
+ 	int retries;
+ } jr3_pci_subdev_private;
+ 
+-static poll_delay_t poll_delay_min_max(int min, int max)
++static struct poll_delay_t poll_delay_min_max(int min, int max)
+ {
+-	poll_delay_t result;
++	struct poll_delay_t result;
+ 
+ 	result.min = min;
+ 	result.max = max;
+@@ -525,9 +527,9 @@ static int jr3_download_firmware(struct comedi_device * dev, const u8 * data,
+ 	return result;
+ }
+ 
+-static poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice * s)
++static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice * s)
+ {
+-	poll_delay_t result = poll_delay_min_max(1000, 2000);
++	struct poll_delay_t result = poll_delay_min_max(1000, 2000);
+ 	jr3_pci_subdev_private *p = s->private;
+ 
+ 	if (p) {
+@@ -752,7 +754,7 @@ static void jr3_pci_poll_dev(unsigned long data)
+ 	for (i = 0; i < devpriv->n_channels; i++) {
+ 		jr3_pci_subdev_private *subdevpriv = dev->subdevices[i].private;
+ 		if (now > subdevpriv->next_time_min) {
+-			poll_delay_t sub_delay;
++			struct poll_delay_t sub_delay;
+ 
+ 			sub_delay = jr3_pci_poll_subdevice(&dev->subdevices[i]);
+ 			subdevpriv->next_time_min =

commit 352dec620aea9529180034fa461d290026ff57e9
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:18:10 2009 -0400
+
+    Staging: comedi: Remove hpdi_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
+index 001284f1583d..49e5c86c2dd8 100644
+--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
++++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
+@@ -301,7 +301,8 @@ static inline struct hpdi_board *board(const struct comedi_device * dev)
+ 	return (struct hpdi_board *) dev->board_ptr;
+ }
+ 
+-typedef struct {
++struct hpdi_private {
++
+ 	struct pci_dev *hw_dev;	// pointer to board's pci_dev struct
+ 	// base addresses (physical)
+ 	resource_size_t plx9080_phys_iobase;
+@@ -322,9 +323,10 @@ typedef struct {
+ 	volatile uint32_t bits[24];	// software copies of values written to hpdi registers
+ 	volatile unsigned int block_size;	// number of bytes at which to generate COMEDI_CB_BLOCK events
+ 	unsigned dio_config_output:1;
+-} hpdi_private;
++};
++
+ 
+-static inline hpdi_private *priv(struct comedi_device * dev)
++static inline struct hpdi_private *priv(struct comedi_device * dev)
+ {
+ 	return dev->private;
+ }
+@@ -562,7 +564,7 @@ static int hpdi_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ 
+ 	printk("comedi%d: gsc_hpdi\n", dev->minor);
+ 
+-	if (alloc_private(dev, sizeof(hpdi_private)) < 0)
++	if (alloc_private(dev, sizeof(struct hpdi_private)) < 0)
+ 		return -ENOMEM;
+ 
+ 	pcidev = NULL;

commit b81c8035ff531ae47b45f132cc0305d8c5c412c6
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:18:05 2009 -0400
+
+    Staging: comedi: Remove dt3k_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
+index fc4389f25eb0..d9467984706e 100644
+--- a/drivers/staging/comedi/drivers/dt3000.c
++++ b/drivers/staging/comedi/drivers/dt3000.c
+@@ -262,7 +262,8 @@ MODULE_DEVICE_TABLE(pci, dt3k_pci_table);
+ #define DT3000_CHANNEL_MODE_SE		0
+ #define DT3000_CHANNEL_MODE_DI		1
+ 
+-typedef struct {
++struct dt3k_private {
++
+ 	struct pci_dev *pci_dev;
+ 	resource_size_t phys_addr;
+ 	void *io_addr;
+@@ -270,8 +271,9 @@ typedef struct {
+ 	unsigned int ao_readback[2];
+ 	unsigned int ai_front;
+ 	unsigned int ai_rear;
+-} dt3k_private;
+-#define devpriv ((dt3k_private *)dev->private)
++};
++
++#define devpriv ((struct dt3k_private *)dev->private)
+ 
+ static int dt3000_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int dt3000_detach(struct comedi_device * dev);
+@@ -809,7 +811,7 @@ static int dt3000_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	bus = it->options[0];
+ 	slot = it->options[1];
+ 
+-	if ((ret = alloc_private(dev, sizeof(dt3k_private))) < 0)
++	if ((ret = alloc_private(dev, sizeof(struct dt3k_private))) < 0)
+ 		return ret;
+ 
+ 	ret = dt_pci_probe(dev, bus, slot);

commit 60efa611c788c4f5b9fdc206aeb9e7c91e0c3ffb
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:18:00 2009 -0400
+
+    Staging: comedi: Remove comment mentioning typedefs
+    
+    There are no typedefs left in this file, so no need for a comment
+    pointing out the typedefs.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c
+index d6fe2b08d1e7..5e0eed835d1a 100644
+--- a/drivers/staging/comedi/drivers/dt2801.c
++++ b/drivers/staging/comedi/drivers/dt2801.c
+@@ -43,7 +43,7 @@ Configuration options:
+ /* Ports */
+ #define DT2801_IOSIZE 2
+ 
+-/* define's & typedef's */
++/* define's */
+ /* ====================== */
+ 
+ /* Commands */

commit 8532530040c05ab60e7d83c705713ef2629cd3bb
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:17:54 2009 -0400
+
+    Staging: comedi: Remove dnp_private_data typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c
+index 8965df7a93cb..098b7b098828 100644
+--- a/drivers/staging/comedi/drivers/ssv_dnp.c
++++ b/drivers/staging/comedi/drivers/ssv_dnp.c
+@@ -72,9 +72,11 @@ static const dnp_board dnp_boards[] = {	/* we only support one DNP 'board'   */
+ #define thisboard ((const dnp_board *)dev->board_ptr)
+ 
+ /* This structure is for data unique to the DNP driver --------------------- */
+-typedef struct {
++struct dnp_private_data {
++
+ 	//
+-} dnp_private_data;
++};
++
+ 
+ /* Shorthand macro for faster access to the private data ------------------- */
+ #define devpriv ((dnp_private *)dev->private)
+@@ -131,7 +133,7 @@ static int dnp_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ 
+ 	/* Allocate the private structure area. alloc_private() is a convenient    */
+ 	/* macro defined in comedidev.h.                                           */
+-	if (alloc_private(dev, sizeof(dnp_private_data)) < 0)
++	if (alloc_private(dev, sizeof(struct dnp_private_data)) < 0)
+ 		return -ENOMEM;
+ 
+ 	/* Allocate the subdevice structures. alloc_subdevice() is a convenient    */

commit b3fb588d463c575706fe80e9c30bf4b1c7702034
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:17:44 2009 -0400
+
+    Staging: comedi: Remove serial2002_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
+index 96430d2955b1..91fc281c1e9f 100644
+--- a/drivers/staging/comedi/drivers/serial2002.c
++++ b/drivers/staging/comedi/drivers/serial2002.c
+@@ -60,11 +60,13 @@ static const serial2002_board serial2002_boards[] = {
+  */
+ #define thisboard ((const serial2002_board *)dev->board_ptr)
+ 
+-typedef struct {
++struct serial2002_range_table_t {
++
+ 	// HACK...
+ 	int length;
+ 	struct comedi_krange range;
+-} serial2002_range_table_t;
++};
++
+ 
+ typedef struct {
+ 	int port;		// /dev/ttyS
+@@ -76,7 +78,7 @@ typedef struct {
+ 	unsigned char analog_in_mapping[32];
+ 	unsigned char analog_out_mapping[32];
+ 	unsigned char encoder_in_mapping[32];
+-	serial2002_range_table_t in_range[32], out_range[32];
++	struct serial2002_range_table_t in_range[32], out_range[32];
+ } serial2002_private;
+ 
+ /*
+@@ -554,7 +556,7 @@ static void serial_2002_open(struct comedi_device * dev)
+ 			// Fill in subdev data
+ 			config_t *c;
+ 			unsigned char *mapping = 0;
+-			serial2002_range_table_t *range = 0;
++			struct serial2002_range_table_t *range = 0;
+ 			int kind = 0;
+ 
+ 			switch (i) {
+@@ -623,7 +625,7 @@ static void serial_2002_open(struct comedi_device * dev)
+ 					s->range_table = 0;
+ 					s->range_table_list = range_table_list =
+ 						kmalloc(sizeof
+-						(serial2002_range_table_t) *
++						(struct serial2002_range_table_t) *
+ 						s->n_chan, GFP_KERNEL);
+ 				}
+ 				for (chan = 0, j = 0; j < 32; j++) {

commit 6dc1ece008ab4e2bdddec3eca6d326a16b4f9849
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:17:38 2009 -0400
+
+    Staging: comedi: Remove s526_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
+index 08666e637e47..d112515feccd 100644
+--- a/drivers/staging/comedi/drivers/s526.c
++++ b/drivers/staging/comedi/drivers/s526.c
+@@ -191,7 +191,8 @@ static const s526_board s526_boards[] = {
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+    feel free to suggest moving the variable to the struct comedi_device struct.  */
+-typedef struct {
++struct s526_private {
++
+ 	int data;
+ 
+ 	/* would be useful for a PCI device */
+@@ -202,12 +203,13 @@ typedef struct {
+ 
+ 	s526_gpct_config_t s526_gpct_config[4];
+ 	unsigned short s526_ai_config;
+-} s526_private;
++};
++
+ /*
+  * most drivers define the following macro to make it easy to
+  * access the private structure.
+  */
+-#define devpriv ((s526_private *)dev->private)
++#define devpriv ((struct s526_private *)dev->private)
+ 
+ /*
+  * The struct comedi_driver structure tells the Comedi core module
+@@ -307,7 +309,7 @@ static int s526_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+  * Allocate the private structure area.  alloc_private() is a
+  * convenient macro defined in comedidev.h.
+  */
+-	if (alloc_private(dev, sizeof(s526_private)) < 0)
++	if (alloc_private(dev, sizeof(struct s526_private)) < 0)
+ 		return -ENOMEM;
+ 
+ /*

commit 39eb312d648b530afd147a7c8198f7536f441a94
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:17:28 2009 -0400
+
+    Staging: comedi: Remove pcmda12_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c
+index ad7726853808..81233355d67b 100644
+--- a/drivers/staging/comedi/drivers/pcmda12.c
++++ b/drivers/staging/comedi/drivers/pcmda12.c
+@@ -92,12 +92,14 @@ static const pcmda12_board pcmda12_boards[] = {
+  */
+ #define thisboard ((const pcmda12_board *)dev->board_ptr)
+ 
+-typedef struct {
++struct pcmda12_private {
++
+ 	unsigned int ao_readback[CHANS];
+ 	int simultaneous_xfer_mode;
+-} pcmda12_private;
++};
++
+ 
+-#define devpriv ((pcmda12_private *)(dev->private))
++#define devpriv ((struct pcmda12_private *)(dev->private))
+ 
+ /*
+  * The struct comedi_driver structure tells the Comedi core module
+@@ -174,7 +176,7 @@ static int pcmda12_attach(struct comedi_device * dev, struct comedi_devconfig *
+  * Allocate the private structure area.  alloc_private() is a
+  * convenient macro defined in comedidev.h.
+  */
+-	if (alloc_private(dev, sizeof(pcmda12_private)) < 0) {
++	if (alloc_private(dev, sizeof(struct pcmda12_private)) < 0) {
+ 		printk("cannot allocate private data structure\n");
+ 		return -ENOMEM;
+ 	}

commit 087ea31bdabb0395f83223c153a0557136461a85
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:17:17 2009 -0400
+
+    Staging: comedi: Remove pcl818_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
+index 274741f76158..43a9d56c6a43 100644
+--- a/drivers/staging/comedi/drivers/pcl818.c
++++ b/drivers/staging/comedi/drivers/pcl818.c
+@@ -313,7 +313,8 @@ static struct comedi_driver driver_pcl818 = {
+ 
+ COMEDI_INITCLEANUP(driver_pcl818);
+ 
+-typedef struct {
++struct pcl818_private {
++
+ 	unsigned int dma;	// used DMA, 0=don't use DMA
+ 	int dma_rtc;		// 1=RTC used with DMA, 0=no RTC alloc
+ 	unsigned int io_range;
+@@ -358,13 +359,14 @@ typedef struct {
+ 	struct comedi_subdevice *sub_ai;	// ptr to AI subdevice
+ 	unsigned char usefifo;	// 1=use fifo
+ 	unsigned int ao_readback[2];
+-} pcl818_private;
++};
++
+ 
+ static const unsigned int muxonechan[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,	// used for gain list programming
+ 	0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
+ };
+ 
+-#define devpriv ((pcl818_private *)dev->private)
++#define devpriv ((struct pcl818_private *)dev->private)
+ #define this_board ((const struct pcl818_board *)dev->board_ptr)
+ 
+ /*
+@@ -1685,7 +1687,7 @@ static int pcl818_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	unsigned long pages;
+ 	struct comedi_subdevice *s;
+ 
+-	if ((ret = alloc_private(dev, sizeof(pcl818_private))) < 0)
++	if ((ret = alloc_private(dev, sizeof(struct pcl818_private))) < 0)
+ 		return ret;	/* Can't alloc mem */
+ 
+ 	/* claim our I/O space */

commit a7195f3d92f5fc560e597598a56d9c394b65ee81
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:16:39 2009 -0400
+
+    Staging: comedi: Remove nidio_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
+index 339f059bab8e..639c1676a805 100644
+--- a/drivers/staging/comedi/drivers/ni_pcidio.c
++++ b/drivers/staging/comedi/drivers/ni_pcidio.c
+@@ -298,14 +298,16 @@ static struct comedi_driver driver_pcidio = {
+       detach:nidio_detach,
+ };
+ 
+-typedef struct {
++struct nidio_board {
++
+ 	int dev_id;
+ 	const char *name;
+ 	int n_8255;
+ 	unsigned int is_diodaq:1;
+ 	unsigned int uses_firmware:1;
+-} nidio_board;
+-static const nidio_board nidio_boards[] = {
++};
++
++static const struct nidio_board nidio_boards[] = {
+ 	{
+ 	      dev_id:	0x1150,
+ 	      name:	"pci-dio-32hs",
+@@ -370,7 +372,7 @@ static const nidio_board nidio_boards[] = {
+ };
+ 
+ #define n_nidio_boards (sizeof(nidio_boards)/sizeof(nidio_boards[0]))
+-#define this_board ((const nidio_board *)dev->board_ptr)
++#define this_board ((const struct nidio_board *)dev->board_ptr)
+ 
+ static DEFINE_PCI_DEVICE_TABLE(ni_pcidio_pci_table) = {
+ 	{PCI_VENDOR_ID_NATINST, 0x1150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},

commit c7ef22985517e35d3b5cf5cffa962a4b8ed8899b
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:16:34 2009 -0400
+
+    Staging: comedi: Remove ni_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c
+index 9822f5e70229..d6357c25aca5 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_cs.c
++++ b/drivers/staging/comedi/drivers/ni_mio_cs.c
+@@ -173,11 +173,13 @@ static const ni_board ni_boards[] = {
+ 
+ #define NI_E_IRQ_FLAGS		IRQF_SHARED
+ 
+-typedef struct {
++struct ni_private {
++
+ 	struct pcmcia_device *link;
+ 
+- NI_PRIVATE_COMMON} ni_private;
+-#define devpriv ((ni_private *)dev->private)
++ NI_PRIVATE_COMMON};
++
++#define devpriv ((struct ni_private *)dev->private)
+ 
+ /* How we access registers */
+ 

commit 344d23e931fdb982489753e5189d9c60ffbdfd67
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:16:28 2009 -0400
+
+    Staging: comedi: Remove dio24_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
+index ed734bb3647e..daec5c4b4c95 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
++++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
+@@ -91,11 +91,13 @@ static const dio24_board dio24_boards[] = {
+  */
+ #define thisboard ((const dio24_board *)dev->board_ptr)
+ 
+-typedef struct {
++struct dio24_private {
++
+ 	int data;		/* number of data points left to be taken */
+-} dio24_private;
++};
++
+ 
+-#define devpriv ((dio24_private *)dev->private)
++#define devpriv ((struct dio24_private *)dev->private)
+ 
+ static struct comedi_driver driver_dio24 = {
+       driver_name:"ni_daq_dio24",
+@@ -117,7 +119,7 @@ static int dio24_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 	struct pcmcia_device *link;
+ 
+ 	/* allocate and initialize dev->private */
+-	if (alloc_private(dev, sizeof(dio24_private)) < 0)
++	if (alloc_private(dev, sizeof(struct dio24_private)) < 0)
+ 		return -ENOMEM;
+ 
+ 	// get base address, irq etc. based on bustype

commit adf328432473a9baf2b7b0a50864d9736890fa8a
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:16:23 2009 -0400
+
+    Staging: comedi: Remove dio700_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
+index 1530416e4fa6..41c1e1ab5c00 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_700.c
++++ b/drivers/staging/comedi/drivers/ni_daq_700.c
+@@ -91,11 +91,13 @@ static const dio700_board dio700_boards[] = {
+  */
+ #define thisboard ((const dio700_board *)dev->board_ptr)
+ 
+-typedef struct {
++struct dio700_private {
++
+ 	int data;		/* number of data points left to be taken */
+-} dio700_private;
++};
++
+ 
+-#define devpriv ((dio700_private *)dev->private)
++#define devpriv ((struct dio700_private *)dev->private)
+ 
+ static struct comedi_driver driver_dio700 = {
+       driver_name:"ni_daq_700",
+@@ -360,7 +362,7 @@ static int dio700_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	struct pcmcia_device *link;
+ 
+ 	/* allocate and initialize dev->private */
+-	if (alloc_private(dev, sizeof(dio700_private)) < 0)
++	if (alloc_private(dev, sizeof(struct dio700_private)) < 0)
+ 		return -ENOMEM;
+ 
+ 	// get base address, irq etc. based on bustype

commit 9f30c243c86483f24dc2687a8708985d147d63e0
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:16:18 2009 -0400
+
+    Staging: comedi: Remove atmio16_board_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
+index 5edaa67fd40f..1e6eea5533c7 100644
+--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
++++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
+@@ -103,11 +103,13 @@ Devices: [National Instruments] AT-MIO-16 (atmio16), AT-MIO-16D (atmio16d)
+ #define devpriv ((atmio16d_private *)dev->private)
+ #define ATMIO16D_TIMEOUT 10
+ 
+-typedef struct {
++struct atmio16_board_t {
++
+ 	const char *name;
+ 	int has_8255;
+-} atmio16_board_t;
+-static const atmio16_board_t atmio16_boards[] = {
++};
++
++static const struct atmio16_board_t atmio16_boards[] = {
+ 	{
+ 	      name:	"atmio16",
+ 	      has_8255:0,
+@@ -120,7 +122,7 @@ static const atmio16_board_t atmio16_boards[] = {
+ 
+ #define n_atmio16_boards sizeof(atmio16_boards)/sizeof(atmio16_boards[0])
+ 
+-#define boardtype ((const atmio16_board_t *)dev->board_ptr)
++#define boardtype ((const struct atmio16_board_t *)dev->board_ptr)
+ 
+ /* function prototypes */
+ static int atmio16d_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+@@ -141,7 +143,7 @@ static struct comedi_driver driver_atmio16d = {
+       detach:atmio16d_detach,
+       board_name:&atmio16_boards[0].name,
+       num_names:n_atmio16_boards,
+-      offset:sizeof(atmio16_board_t),
++      offset:sizeof(struct atmio16_board_t),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_atmio16d);

commit 75b807393272fcfcf54d1188c667dc0fccd1fb69
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:16:12 2009 -0400
+
+    Staging: comedi: Remove atao_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c
+index f8c950d52ab6..efacfda03b2f 100644
+--- a/drivers/staging/comedi/drivers/ni_at_ao.c
++++ b/drivers/staging/comedi/drivers/ni_at_ao.c
+@@ -168,15 +168,17 @@ static const atao_board atao_boards[] = {
+ 
+ #define thisboard ((atao_board *)dev->board_ptr)
+ 
+-typedef struct {
++struct atao_private {
++
+ 	unsigned short cfg1;
+ 	unsigned short cfg2;
+ 	unsigned short cfg3;
+ 
+ 	/* Used for AO readback */
+ 	unsigned int ao_readback[10];
+-} atao_private;
+-#define devpriv ((atao_private *)dev->private)
++};
++
++#define devpriv ((struct atao_private *)dev->private)
+ 
+ static int atao_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int atao_detach(struct comedi_device * dev);
+@@ -230,7 +232,7 @@ static int atao_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ 
+ 	dev->board_name = thisboard->name;
+ 
+-	if (alloc_private(dev, sizeof(atao_private)) < 0)
++	if (alloc_private(dev, sizeof(struct atao_private)) < 0)
+ 		return -ENOMEM;
+ 
+ 	if (alloc_subdevices(dev, 4) < 0)

commit 3cc3872bbd097a2bcbe740b7041b3d35cc8f0d3e
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:16:07 2009 -0400
+
+    Staging: comedi: Remove a2150_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
+index d14227826817..ed5f5576d992 100644
+--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
++++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
+@@ -156,16 +156,18 @@ static const a2150_board a2150_boards[] = {
+  */
+ #define thisboard ((const a2150_board *)dev->board_ptr)
+ 
+-typedef struct {
++struct a2150_private {
++
+ 	volatile unsigned int count;	/* number of data points left to be taken */
+ 	unsigned int dma;	// dma channel
+ 	s16 *dma_buffer;	// dma buffer
+ 	unsigned int dma_transfer_size;	// size in bytes of dma transfers
+ 	int irq_dma_bits;	// irq/dma register bits
+ 	int config_bits;	// config register bits
+-} a2150_private;
++};
++
+ 
+-#define devpriv ((a2150_private *)dev->private)
++#define devpriv ((struct a2150_private *)dev->private)
+ 
+ static int a2150_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int a2150_detach(struct comedi_device * dev);
+@@ -346,7 +348,7 @@ static int a2150_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 	printk("\n");
+ 
+ 	/* allocate and initialize dev->private */
+-	if (alloc_private(dev, sizeof(a2150_private)) < 0)
++	if (alloc_private(dev, sizeof(struct a2150_private)) < 0)
+ 		return -ENOMEM;
+ 
+ 	if (iobase == 0) {

commit 8ce8a1fff26a88498cfa435cf964bcba87682daf
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:16:01 2009 -0400
+
+    Staging: comedi: Remove ni_670x_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
+index 28b3355f5b03..dbadb8e8e1e6 100644
+--- a/drivers/staging/comedi/drivers/ni_670x.c
++++ b/drivers/staging/comedi/drivers/ni_670x.c
+@@ -98,14 +98,16 @@ MODULE_DEVICE_TABLE(pci, ni_670x_pci_table);
+ 
+ #define thisboard ((ni_670x_board *)dev->board_ptr)
+ 
+-typedef struct {
++struct ni_670x_private {
++
+ 	struct mite_struct *mite;
+ 	int boardtype;
+ 	int dio;
+ 	unsigned int ao_readback[32];
+-} ni_670x_private;
++};
++
+ 
+-#define devpriv ((ni_670x_private *)dev->private)
++#define devpriv ((struct ni_670x_private *)dev->private)
+ #define n_ni_670x_boards (sizeof(ni_670x_boards)/sizeof(ni_670x_boards[0]))
+ 
+ static int ni_670x_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+@@ -141,7 +143,7 @@ static int ni_670x_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 
+ 	printk("comedi%d: ni_670x: ", dev->minor);
+ 
+-	if ((ret = alloc_private(dev, sizeof(ni_670x_private))) < 0)
++	if ((ret = alloc_private(dev, sizeof(struct ni_670x_private))) < 0)
+ 		return ret;
+ 
+ 	ret = ni_670x_find_device(dev, it->options[0], it->options[1]);

commit 0cb5e8ff4502d60967177038e2d740dae759e4b2
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:15:56 2009 -0400
+
+    Staging: comedi: Remove NI_660xRegisterData typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
+index 0af2049feb99..2a3c1302d620 100644
+--- a/drivers/staging/comedi/drivers/ni_660x.c
++++ b/drivers/staging/comedi/drivers/ni_660x.c
+@@ -192,14 +192,16 @@ static inline unsigned NI_660X_GPCT_SUBDEV(unsigned index)
+ 	return NI_660X_GPCT_SUBDEV_0 + index;
+ }
+ 
+-typedef struct {
++struct NI_660xRegisterData {
++
+ 	const char *name;	// Register Name
+ 	int offset;		// Offset from base address from GPCT chip
+ 	enum ni_660x_register_direction direction;
+ 	enum ni_660x_register_width size;	// 1 byte, 2 bytes, or 4 bytes
+-} NI_660xRegisterData;
++};
++
+ 
+-static const NI_660xRegisterData registerData[NumRegisters] = {
++static const struct NI_660xRegisterData registerData[NumRegisters] = {
+ 	{"G0 Interrupt Acknowledge", 0x004, NI_660x_WRITE, DATA_2B},
+ 	{"G0 Status Register", 0x004, NI_660x_READ, DATA_2B},
+ 	{"G1 Interrupt Acknowledge", 0x006, NI_660x_WRITE, DATA_2B},

commit 125edf55eb4c722afa76b43da40f24a6fd2421ef
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:15:51 2009 -0400
+
+    Staging: comedi: Remove ni_65xx_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
+index 59edcdf8e032..c5fac96f25dd 100644
+--- a/drivers/staging/comedi/drivers/ni_65xx.c
++++ b/drivers/staging/comedi/drivers/ni_65xx.c
+@@ -111,15 +111,17 @@ static struct comedi_driver driver_ni_65xx = {
+       detach:ni_65xx_detach,
+ };
+ 
+-typedef struct {
++struct ni_65xx_board {
++
+ 	int dev_id;
+ 	const char *name;
+ 	unsigned num_dio_ports;
+ 	unsigned num_di_ports;
+ 	unsigned num_do_ports;
+ 	unsigned invert_outputs:1;
+-} ni_65xx_board;
+-static const ni_65xx_board ni_65xx_boards[] = {
++};
++
++static const struct ni_65xx_board ni_65xx_boards[] = {
+ 	{
+ 	      dev_id:	0x7085,
+ 	      name:	"pci-6509",
+@@ -239,7 +241,7 @@ static const ni_65xx_board ni_65xx_boards[] = {
+ };
+ 
+ #define n_ni_65xx_boards (sizeof(ni_65xx_boards)/sizeof(ni_65xx_boards[0]))
+-static inline const ni_65xx_board *board(struct comedi_device * dev)
++static inline const struct ni_65xx_board *board(struct comedi_device * dev)
+ {
+ 	return dev->board_ptr;
+ }
+@@ -247,7 +249,7 @@ static inline unsigned ni_65xx_port_by_channel(unsigned channel)
+ {
+ 	return channel / ni_65xx_channels_per_port;
+ }
+-static inline unsigned ni_65xx_total_num_ports(const ni_65xx_board * board)
++static inline unsigned ni_65xx_total_num_ports(const struct ni_65xx_board * board)
+ {
+ 	return board->num_dio_ports + board->num_di_ports + board->num_do_ports;
+ }

commit 16d38ca3514bfcfad78f97dc136c955616303bf4
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:15:45 2009 -0400
+
+    Staging: comedi: Remove ni6527_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
+index 18fb7995c7c5..0d07c8514336 100644
+--- a/drivers/staging/comedi/drivers/ni_6527.c
++++ b/drivers/staging/comedi/drivers/ni_6527.c
+@@ -84,11 +84,13 @@ static struct comedi_driver driver_ni6527 = {
+       detach:ni6527_detach,
+ };
+ 
+-typedef struct {
++struct ni6527_board {
++
+ 	int dev_id;
+ 	const char *name;
+-} ni6527_board;
+-static const ni6527_board ni6527_boards[] = {
++};
++
++static const struct ni6527_board ni6527_boards[] = {
+ 	{
+ 	      dev_id:	0x2b20,
+ 	      name:	"pci-6527",
+@@ -100,7 +102,7 @@ static const ni6527_board ni6527_boards[] = {
+ };
+ 
+ #define n_ni6527_boards (sizeof(ni6527_boards)/sizeof(ni6527_boards[0]))
+-#define this_board ((const ni6527_board *)dev->board_ptr)
++#define this_board ((const struct ni6527_board *)dev->board_ptr)
+ 
+ static DEFINE_PCI_DEVICE_TABLE(ni6527_pci_table) = {
+ 	{PCI_VENDOR_ID_NATINST, 0x2b10, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},

commit 6555be0a1c25576be6270bb43f1bd444df7d86f8
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:15:40 2009 -0400
+
+    Staging: comedi: Remove mpc8260cpm_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/mpc8260cpm.c b/drivers/staging/comedi/drivers/mpc8260cpm.c
+index 7250865e8d6e..bac0a7bb9cbd 100644
+--- a/drivers/staging/comedi/drivers/mpc8260cpm.c
++++ b/drivers/staging/comedi/drivers/mpc8260cpm.c
+@@ -38,11 +38,13 @@ It is apparently missing some code.
+ 
+ extern unsigned long mpc8260_dio_reserved[4];
+ 
+-typedef struct {
++struct mpc8260cpm_private {
++
+ 	int data;
+ 
+-} mpc8260cpm_private;
+-#define devpriv ((mpc8260cpm_private *)dev->private)
++};
++
++#define devpriv ((struct mpc8260cpm_private *)dev->private)
+ 
+ static int mpc8260cpm_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int mpc8260cpm_detach(struct comedi_device * dev);
+@@ -71,7 +73,7 @@ static int mpc8260cpm_attach(struct comedi_device * dev, struct comedi_devconfig
+ 
+ 	dev->board_name = thisboard->name;
+ 
+-	if (alloc_private(dev, sizeof(mpc8260cpm_private)) < 0)
++	if (alloc_private(dev, sizeof(struct mpc8260cpm_private)) < 0)
+ 		return -ENOMEM;
+ 
+ 	if (alloc_subdevices(dev, 4) < 0)

commit 16450130a9f7006c91c9f49d725b9029fe711240
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:15:34 2009 -0400
+
+    Staging: comedi: Remove skel_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c
+index ee053f149dd9..a151602929d9 100644
+--- a/drivers/staging/comedi/drivers/mpc624.c
++++ b/drivers/staging/comedi/drivers/mpc624.c
+@@ -120,11 +120,13 @@ Configuration Options:
+ #define MPC624_SPEED_13_75_Hz   (MPC624_OSR4 | MPC624_OSR3                             | MPC624_OSR0)
+ #define MPC624_SPEED_6_875_Hz   (MPC624_OSR4 | MPC624_OSR3 | MPC624_OSR2 | MPC624_OSR1 | MPC624_OSR0)
+ //----------------------------------------------------------------------------
+-typedef struct {
++struct skel_private {
++
+ 	unsigned long int ulConvertionRate;	// set by mpc624_attach() from driver's parameters
+-} skel_private;
++};
++
+ 
+-#define devpriv ((skel_private *)dev->private)
++#define devpriv ((struct skel_private *)dev->private)
+ //----------------------------------------------------------------------------
+ static const struct comedi_lrange range_mpc624_bipolar1 = {
+ 	1,
+@@ -174,7 +176,7 @@ static int mpc624_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	dev->board_name = "mpc624";
+ 
+ 	// Private structure initialization
+-	if (alloc_private(dev, sizeof(skel_private)) < 0)
++	if (alloc_private(dev, sizeof(struct skel_private)) < 0)
+ 		return -ENOMEM;
+ 
+ 	switch (it->options[1]) {

commit 9beff277bb14a844b5cb437fcdca9db7534ee44a
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:15:29 2009 -0400
+
+    Staging: comedi: Remove cnt_board_struct typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c
+index 105a9cfeb745..6f538720d79f 100644
+--- a/drivers/staging/comedi/drivers/ke_counter.c
++++ b/drivers/staging/comedi/drivers/ke_counter.c
+@@ -61,14 +61,16 @@ MODULE_DEVICE_TABLE(pci, cnt_pci_table);
+ 
+ /*-- board specification structure ------------------------------------------*/
+ 
+-typedef struct {
++struct cnt_board_struct {
++
+ 	const char *name;
+ 	int device_id;
+ 	int cnt_channel_nbr;
+ 	int cnt_bits;
+-} cnt_board_struct;
++};
++
+ 
+-static const cnt_board_struct cnt_boards[] = {
++static const struct cnt_board_struct cnt_boards[] = {
+ 	{
+ 	      name:	CNT_DRIVER_NAME,
+ 	      device_id:CNT_CARD_DEVICE_ID,
+@@ -76,7 +78,7 @@ static const cnt_board_struct cnt_boards[] = {
+       cnt_bits:24}
+ };
+ 
+-#define cnt_board_nbr (sizeof(cnt_boards)/sizeof(cnt_board_struct))
++#define cnt_board_nbr (sizeof(cnt_boards)/sizeof(struct cnt_board_struct))
+ 
+ /*-- device private structure -----------------------------------------------*/
+ 
+@@ -148,7 +150,7 @@ static int cnt_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *subdevice;
+ 	struct pci_dev *pci_device;
+-	cnt_board_struct *board;
++	struct cnt_board_struct *board;
+ 	unsigned long io_base;
+ 	int error, i;
+ 
+@@ -180,7 +182,7 @@ static int cnt_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ 					}
+ 
+ 					dev->board_ptr = cnt_boards + i;
+-					board = (cnt_board_struct *) dev->
++					board = (struct cnt_board_struct *) dev->
+ 						board_ptr;
+ 					goto found;
+ 				}

commit 217fbbbc74f136f35530cf9acb06d7231fbdc1f3
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:15:24 2009 -0400
+
+    Staging: comedi: Remove jr3_pci_dev_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
+index 179fd9d637b4..680cc738cc5c 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -127,13 +127,15 @@ static DEFINE_PCI_DEVICE_TABLE(jr3_pci_pci_table) = {
+ 
+ MODULE_DEVICE_TABLE(pci, jr3_pci_pci_table);
+ 
+-typedef struct {
++struct jr3_pci_dev_private {
++
+ 	struct pci_dev *pci_dev;
+ 	int pci_enabled;
+ 	volatile struct jr3_t *iobase;
+ 	int n_channels;
+ 	struct timer_list timer;
+-} jr3_pci_dev_private;
++};
++
+ 
+ typedef struct {
+ 	int min;
+@@ -388,7 +390,7 @@ static int jr3_pci_ai_insn_read(struct comedi_device * dev, struct comedi_subdev
+ static void jr3_pci_open(struct comedi_device * dev)
+ {
+ 	int i;
+-	jr3_pci_dev_private *devpriv = dev->private;
++	struct jr3_pci_dev_private *devpriv = dev->private;
+ 
+ 	printk("jr3_pci_open\n");
+ 	for (i = 0; i < devpriv->n_channels; i++) {
+@@ -458,7 +460,7 @@ static int jr3_download_firmware(struct comedi_device * dev, const u8 * data,
+ 		result = -ENODATA;
+ 	} else {
+ 		int i;
+-		jr3_pci_dev_private *p = dev->private;
++		struct jr3_pci_dev_private *p = dev->private;
+ 
+ 		for (i = 0; i < p->n_channels; i++) {
+ 			jr3_pci_subdev_private *sp;
+@@ -738,7 +740,7 @@ static void jr3_pci_poll_dev(unsigned long data)
+ {
+ 	unsigned long flags;
+ 	struct comedi_device *dev = (struct comedi_device *) data;
+-	jr3_pci_dev_private *devpriv = dev->private;
++	struct jr3_pci_dev_private *devpriv = dev->private;
+ 	unsigned long now;
+ 	int delay;
+ 	int i;
+@@ -775,7 +777,7 @@ static int jr3_pci_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	int result = 0;
+ 	struct pci_dev *card = NULL;
+ 	int opt_bus, opt_slot, i;
+-	jr3_pci_dev_private *devpriv;
++	struct jr3_pci_dev_private *devpriv;
+ 
+ 	printk("comedi%d: jr3_pci\n", dev->minor);
+ 
+@@ -788,7 +790,7 @@ static int jr3_pci_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 		return -EINVAL;
+ 	}
+ 
+-	result = alloc_private(dev, sizeof(jr3_pci_dev_private));
++	result = alloc_private(dev, sizeof(struct jr3_pci_dev_private));
+ 	if (result < 0) {
+ 		return -ENOMEM;
+ 	}
+@@ -943,7 +945,7 @@ static int jr3_pci_attach(struct comedi_device * dev, struct comedi_devconfig *
+ static int jr3_pci_detach(struct comedi_device * dev)
+ {
+ 	int i;
+-	jr3_pci_dev_private *devpriv = dev->private;
++	struct jr3_pci_dev_private *devpriv = dev->private;
+ 
+ 	printk("comedi%d: jr3_pci: remove\n", dev->minor);
+ 	if (devpriv) {

commit 0e99a2b9a2367e47bebf8bdbb5aa0ce14d586968
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:15:18 2009 -0400
+
+    Staging: comedi: Remove pci20xxx_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c
+index a31f0d20fcf2..624d44c3969f 100644
+--- a/drivers/staging/comedi/drivers/ii_pci20kc.c
++++ b/drivers/staging/comedi/drivers/ii_pci20kc.c
+@@ -148,12 +148,14 @@ typedef union {
+ 	} pci20341;
+ } pci20xxx_subdev_private;
+ 
+-typedef struct {
++struct pci20xxx_private {
++
+ 	void *ioaddr;
+ 	pci20xxx_subdev_private subdev_private[PCI20000_MODULES];
+-} pci20xxx_private;
++};
++
+ 
+-#define devpriv ((pci20xxx_private *)dev->private)
++#define devpriv ((struct pci20xxx_private *)dev->private)
+ #define CHAN (CR_CHAN(it->chanlist[0]))
+ 
+ static int pci20xxx_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+@@ -209,7 +211,7 @@ static int pci20xxx_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 
+ 	if ((ret = alloc_subdevices(dev, 1 + PCI20000_MODULES)) < 0)
+ 		return ret;
+-	if ((ret = alloc_private(dev, sizeof(pci20xxx_private))) < 0)
++	if ((ret = alloc_private(dev, sizeof(struct pci20xxx_private))) < 0)
+ 		return ret;
+ 
+ 	devpriv->ioaddr = (void *)(unsigned long)it->options[0];
+@@ -255,7 +257,7 @@ static int pci20xxx_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 		}
+ 	}
+ 
+-	/* initialize pci20xxx_private */
++	/* initialize struct pci20xxx_private */
+ 	pci20xxx_dio_init(dev, dev->subdevices + PCI20000_MODULES);
+ 
+ 	return 1;
+@@ -449,7 +451,7 @@ static int pci20xxx_dio_insn_bits(struct comedi_device * dev, struct comedi_subd
+ static int pci20xxx_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data);
+ 
+-/* initialize pci20xxx_private */
++/* initialize struct pci20xxx_private */
+ static int pci20xxx_dio_init(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 

commit 52b3e3483d12f03ad6c1fa051a5db0b5656596c9
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:15:13 2009 -0400
+
+    Staging: comedi: Remove hpdi_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
+index 535aadb98dcc..001284f1583d 100644
+--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
++++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
+@@ -260,13 +260,15 @@ uint32_t intr_active_high_bit(int interrupt_source)
+ 	return 0x1 << interrupt_source;
+ }
+ 
+-typedef struct {
++struct hpdi_board {
++
+ 	char *name;
+ 	int device_id;		// pci device id
+ 	int subdevice_id;	// pci subdevice id
+-} hpdi_board;
++};
++
+ 
+-static const hpdi_board hpdi_boards[] = {
++static const struct hpdi_board hpdi_boards[] = {
+ 	{
+ 	      name:	"pci-hpdi32",
+ 	      device_id:PCI_DEVICE_ID_PLX_9080,
+@@ -283,7 +285,7 @@ static const hpdi_board hpdi_boards[] = {
+ 
+ static inline unsigned int num_boards(void)
+ {
+-	return sizeof(hpdi_boards) / sizeof(hpdi_board);
++	return sizeof(hpdi_boards) / sizeof(struct hpdi_board);
+ }
+ 
+ static DEFINE_PCI_DEVICE_TABLE(hpdi_pci_table) = {
+@@ -294,9 +296,9 @@ static DEFINE_PCI_DEVICE_TABLE(hpdi_pci_table) = {
+ 
+ MODULE_DEVICE_TABLE(pci, hpdi_pci_table);
+ 
+-static inline hpdi_board *board(const struct comedi_device * dev)
++static inline struct hpdi_board *board(const struct comedi_device * dev)
+ {
+-	return (hpdi_board *) dev->board_ptr;
++	return (struct hpdi_board *) dev->board_ptr;
+ }
+ 
+ typedef struct {

commit fa11f7a978b9b93f46408ead81dba035828c1ff9
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:15:08 2009 -0400
+
+    Staging: comedi: Remove fl512_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c
+index 6fe747d8dd11..6d7bb37d2b1c 100644
+--- a/drivers/staging/comedi/drivers/fl512.c
++++ b/drivers/staging/comedi/drivers/fl512.c
+@@ -24,10 +24,12 @@ Configuration options:
+ #include 
+ 
+ #define FL512_SIZE 16		/* the size of the used memory */
+-typedef struct {
++struct fl512_private {
++
+ 	short ao_readback[2];
+-} fl512_private;
+-#define devpriv ((fl512_private *) dev->private)
++};
++
++#define devpriv ((struct fl512_private *) dev->private)
+ 
+ static const struct comedi_lrange range_fl512 = { 4, {
+ 			BIP_RANGE(0.5),
+@@ -138,7 +140,7 @@ static int fl512_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 	}
+ 	dev->iobase = iobase;
+ 	dev->board_name = "fl512";
+-	if (alloc_private(dev, sizeof(fl512_private)) < 0)
++	if (alloc_private(dev, sizeof(struct fl512_private)) < 0)
+ 		return -ENOMEM;
+ 
+ #if DEBUG

commit c14e9208359c615f2e565277a607237635a1e413
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:15:02 2009 -0400
+
+    Staging: comedi: Remove dt3k_boardtype typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
+index a8367d9c0a4c..fc4389f25eb0 100644
+--- a/drivers/staging/comedi/drivers/dt3000.c
++++ b/drivers/staging/comedi/drivers/dt3000.c
+@@ -81,7 +81,8 @@ static const struct comedi_lrange range_dt3000_ai_pgl = { 4, {
+ 	}
+ };
+ 
+-typedef struct {
++struct dt3k_boardtype {
++
+ 	const char *name;
+ 	unsigned int device_id;
+ 	int adchan;
+@@ -90,9 +91,10 @@ typedef struct {
+ 	const struct comedi_lrange *adrange;
+ 	int dachan;
+ 	int dabits;
+-} dt3k_boardtype;
++};
++
+ 
+-static const dt3k_boardtype dt3k_boardtypes[] = {
++static const struct dt3k_boardtype dt3k_boardtypes[] = {
+       {name:"dt3001",
+ 	      device_id:0x22,
+ 	      adchan:	16,
+@@ -158,8 +160,8 @@ static const dt3k_boardtype dt3k_boardtypes[] = {
+ 		},
+ };
+ 
+-#define n_dt3k_boards sizeof(dt3k_boardtypes)/sizeof(dt3k_boardtype)
+-#define this_board ((const dt3k_boardtype *)dev->board_ptr)
++#define n_dt3k_boards sizeof(dt3k_boardtypes)/sizeof(struct dt3k_boardtype)
++#define this_board ((const struct dt3k_boardtype *)dev->board_ptr)
+ 
+ static DEFINE_PCI_DEVICE_TABLE(dt3k_pci_table) = {
+ 	{PCI_VENDOR_ID_DT, 0x0022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},

commit 0b011a6f40dfdda0e33cf5b38ce9ffb6fd7a825b
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:14:57 2009 -0400
+
+    Staging: comedi: Remove dt2815_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c
+index 553842e120f0..fccec8a77d50 100644
+--- a/drivers/staging/comedi/drivers/dt2815.c
++++ b/drivers/staging/comedi/drivers/dt2815.c
+@@ -88,12 +88,14 @@ COMEDI_INITCLEANUP(driver_dt2815);
+ 
+ static void dt2815_free_resources(struct comedi_device * dev);
+ 
+-typedef struct {
++struct dt2815_private {
++
+ 	const struct comedi_lrange *range_type_list[8];
+ 	unsigned int ao_readback[8];
+-} dt2815_private;
++};
++
+ 
+-#define devpriv ((dt2815_private *)dev->private)
++#define devpriv ((struct dt2815_private *)dev->private)
+ 
+ static int dt2815_wait_for_status(struct comedi_device * dev, int status)
+ {
+@@ -196,7 +198,7 @@ static int dt2815_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 
+ 	if (alloc_subdevices(dev, 1) < 0)
+ 		return -ENOMEM;
+-	if (alloc_private(dev, sizeof(dt2815_private)) < 0)
++	if (alloc_private(dev, sizeof(struct dt2815_private)) < 0)
+ 		return -ENOMEM;
+ 
+ 	s = dev->subdevices;

commit ca6f10ca8630d709e0d291fb9601f8c8d81c19a0
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:14:52 2009 -0400
+
+    Staging: comedi: Remove dt2814_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c
+index 660079acd223..8320139160a4 100644
+--- a/drivers/staging/comedi/drivers/dt2814.c
++++ b/drivers/staging/comedi/drivers/dt2814.c
+@@ -72,11 +72,13 @@ COMEDI_INITCLEANUP(driver_dt2814);
+ 
+ static irqreturn_t dt2814_interrupt(int irq, void *dev PT_REGS_ARG);
+ 
+-typedef struct {
++struct dt2814_private {
++
+ 	int ntrig;
+ 	int curadchan;
+-} dt2814_private;
+-#define devpriv ((dt2814_private *)dev->private)
++};
++
++#define devpriv ((struct dt2814_private *)dev->private)
+ 
+ #define DT2814_TIMEOUT 10
+ #define DT2814_MAX_SPEED 100000	/* Arbitrary 10 khz limit */
+@@ -309,7 +311,7 @@ static int dt2814_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 
+ 	if ((ret = alloc_subdevices(dev, 1)) < 0)
+ 		return ret;
+-	if ((ret = alloc_private(dev, sizeof(dt2814_private))) < 0)
++	if ((ret = alloc_private(dev, sizeof(struct dt2814_private))) < 0)
+ 		return ret;
+ 
+ 	s = dev->subdevices + 0;

commit 7f435c068c488527842461b9872c0484a3c9ae61
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:14:41 2009 -0400
+
+    Staging: comedi: Remove dt2801_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c
+index 0374e9f82d26..d6fe2b08d1e7 100644
+--- a/drivers/staging/comedi/drivers/dt2801.c
++++ b/drivers/staging/comedi/drivers/dt2801.c
+@@ -220,11 +220,13 @@ static const struct dt2801_board boardtypes[] = {
+ #define n_boardtypes ((sizeof(boardtypes))/(sizeof(boardtypes[0])))
+ #define boardtype (*(const struct dt2801_board *)dev->board_ptr)
+ 
+-typedef struct {
++struct dt2801_private {
++
+ 	const struct comedi_lrange *dac_range_types[2];
+ 	unsigned int ao_readback[2];
+-} dt2801_private;
+-#define devpriv ((dt2801_private *)dev->private)
++};
++
++#define devpriv ((struct dt2801_private *)dev->private)
+ 
+ static int dt2801_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data);
+@@ -521,7 +523,7 @@ static int dt2801_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	if ((ret = alloc_subdevices(dev, 4)) < 0)
+ 		goto out;
+ 
+-	if ((ret = alloc_private(dev, sizeof(dt2801_private))) < 0)
++	if ((ret = alloc_private(dev, sizeof(struct dt2801_private))) < 0)
+ 		goto out;
+ 
+ 	dev->board_name = boardtype.name;

commit 4634b8154e23ced2f70a00ab3a22e6b1987fc348
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:14:35 2009 -0400
+
+    Staging: comedi: Remove boardtype typedef in pcl818.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
+index fb5ddad18735..274741f76158 100644
+--- a/drivers/staging/comedi/drivers/pcl818.c
++++ b/drivers/staging/comedi/drivers/pcl818.c
+@@ -252,7 +252,8 @@ static int RTC_lock = 0;	/* RTC lock */
+ static int RTC_timer_lock = 0;	/* RTC int lock */
+ #endif
+ 
+-typedef struct {
++struct pcl818_board {
++
+ 	const char *name;	// driver name
+ 	int n_ranges;		// len of range list
+ 	int n_aichan_se;	// num of A/D chans in single ended  mode
+@@ -270,9 +271,10 @@ typedef struct {
+ 	int ao_maxdata;		// maxdata for D/A
+ 	unsigned char fifo;	// 1=board has FIFO
+ 	int is_818;
+-} boardtype;
++};
++
+ 
+-static const boardtype boardtypes[] = {
++static const struct pcl818_board boardtypes[] = {
+ 	{"pcl818l", 4, 16, 8, 25000, 1, 16, 16, &range_pcl818l_l_ai,
+ 			&range_unipolar5, PCLx1x_RANGE, 0x00fc,
+ 		0x0a, 0xfff, 0xfff, 0, 1},
+@@ -297,7 +299,7 @@ static const boardtype boardtypes[] = {
+ 		0x0a, 0xfff, 0xfff, 0, 1 /* XXX ? */ },
+ };
+ 
+-#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
++#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl818_board))
+ 
+ static struct comedi_driver driver_pcl818 = {
+       driver_name:"pcl818",
+@@ -306,7 +308,7 @@ static struct comedi_driver driver_pcl818 = {
+       detach:pcl818_detach,
+       board_name:&boardtypes[0].name,
+       num_names:n_boardtypes,
+-      offset:sizeof(boardtype),
++      offset:sizeof(struct pcl818_board),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_pcl818);
+@@ -363,7 +365,7 @@ static const unsigned int muxonechan[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0
+ };
+ 
+ #define devpriv ((pcl818_private *)dev->private)
+-#define this_board ((const boardtype *)dev->board_ptr)
++#define this_board ((const struct pcl818_board *)dev->board_ptr)
+ 
+ /*
+ ==============================================================================

commit d438a1795754030b9b389d7a64981907a1869dc7
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:14:30 2009 -0400
+
+    Staging: comedi: Remove boardtype_t typedef in dt2801.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c
+index 0915d39101b8..0374e9f82d26 100644
+--- a/drivers/staging/comedi/drivers/dt2801.c
++++ b/drivers/staging/comedi/drivers/dt2801.c
+@@ -135,7 +135,8 @@ static const struct comedi_lrange range_dt2801_ai_pgl_unipolar = { 4, {
+ 	}
+ };
+ 
+-typedef struct {
++struct dt2801_board {
++
+ 	const char *name;
+ 	int boardcode;
+ 	int ad_diff;
+@@ -143,12 +144,13 @@ typedef struct {
+ 	int adbits;
+ 	int adrangetype;
+ 	int dabits;
+-} boardtype_t;
++};
++
+ 
+ /* Typeid's for the different boards of the DT2801-series
+    (taken from the test-software, that comes with the board)
+    */
+-static const boardtype_t boardtypes[] = {
++static const struct dt2801_board boardtypes[] = {
+ 	{
+ 	      name:	"dt2801",
+ 	      boardcode:0x09,
+@@ -216,7 +218,7 @@ static const boardtype_t boardtypes[] = {
+ };
+ 
+ #define n_boardtypes ((sizeof(boardtypes))/(sizeof(boardtypes[0])))
+-#define boardtype (*(const boardtype_t *)dev->board_ptr)
++#define boardtype (*(const struct dt2801_board *)dev->board_ptr)
+ 
+ typedef struct {
+ 	const struct comedi_lrange *dac_range_types[2];

commit 68b08cdad78c79fc87df52f8c8d4adf60ec5d7fc
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:14:25 2009 -0400
+
+    Staging: comedi: Remove dt282x_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
+index 6d76d98126d8..4882c3e679cc 100644
+--- a/drivers/staging/comedi/drivers/dt282x.c
++++ b/drivers/staging/comedi/drivers/dt282x.c
+@@ -340,7 +340,7 @@ static const struct dt282x_board boardtypes[] = {
+ #define n_boardtypes sizeof(boardtypes)/sizeof(struct dt282x_board)
+ #define this_board ((const struct dt282x_board *)dev->board_ptr)
+ 
+-typedef struct {
++struct dt282x_private {
+ 	int ad_2scomp;		/* we have 2's comp jumper set  */
+ 	int da0_2scomp;		/* same, for DAC0               */
+ 	int da1_2scomp;		/* same, for DAC1               */
+@@ -365,9 +365,9 @@ typedef struct {
+ 	int usedma;		/* driver uses DMA              */
+ 	volatile int current_dma_index;
+ 	int dma_dir;
+-} dt282x_private;
++};
+ 
+-#define devpriv ((dt282x_private *)dev->private)
++#define devpriv ((struct dt282x_private *)dev->private)
+ #define boardtype (*(const struct dt282x_board *)dev->board_ptr)
+ 
+ /*
+@@ -1326,7 +1326,7 @@ static int dt282x_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ #endif
+ 	}
+ 
+-	if ((ret = alloc_private(dev, sizeof(dt282x_private))) < 0)
++	if ((ret = alloc_private(dev, sizeof(struct dt282x_private))) < 0)
+ 		return ret;
+ 
+ 	ret = dt282x_grab_dma(dev, it->options[opt_dma1],

commit 98484c1ae621eb784c4b2a7dd6c76a069bad6214
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:14:19 2009 -0400
+
+    Staging: comedi: Remove boardtype_t typedef in dt282x.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
+index 1cc0e3b17bb2..6d76d98126d8 100644
+--- a/drivers/staging/comedi/drivers/dt282x.c
++++ b/drivers/staging/comedi/drivers/dt282x.c
+@@ -197,7 +197,7 @@ static const struct comedi_lrange range_dt282x_ai_hi_unipolar = { 4, {
+ 	}
+ };
+ 
+-typedef struct {
++struct dt282x_board {
+ 	const char *name;
+ 	int adbits;
+ 	int adchan_se;
+@@ -206,9 +206,9 @@ typedef struct {
+ 	int ispgl;
+ 	int dachan;
+ 	int dabits;
+-} boardtype_t;
++};
+ 
+-static const boardtype_t boardtypes[] = {
++static const struct dt282x_board boardtypes[] = {
+       {name:"dt2821",
+ 	      adbits:	12,
+ 	      adchan_se:16,
+@@ -337,8 +337,8 @@ static const boardtype_t boardtypes[] = {
+ 		},
+ };
+ 
+-#define n_boardtypes sizeof(boardtypes)/sizeof(boardtype_t)
+-#define this_board ((const boardtype_t *)dev->board_ptr)
++#define n_boardtypes sizeof(boardtypes)/sizeof(struct dt282x_board)
++#define this_board ((const struct dt282x_board *)dev->board_ptr)
+ 
+ typedef struct {
+ 	int ad_2scomp;		/* we have 2's comp jumper set  */
+@@ -368,7 +368,7 @@ typedef struct {
+ } dt282x_private;
+ 
+ #define devpriv ((dt282x_private *)dev->private)
+-#define boardtype (*(const boardtype_t *)dev->board_ptr)
++#define boardtype (*(const struct dt282x_board *)dev->board_ptr)
+ 
+ /*
+  *    Some useless abstractions
+@@ -403,7 +403,7 @@ static struct comedi_driver driver_dt282x = {
+       detach:dt282x_detach,
+       board_name:&boardtypes[0].name,
+       num_names:n_boardtypes,
+-      offset:sizeof(boardtype_t),
++      offset:sizeof(struct dt282x_board),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_dt282x);

commit 39d31e09a0cc299e01b8acb66b60fbcc453b9c8b
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:14:14 2009 -0400
+
+    Staging: comedi: Remove dmm32at_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
+index 4245ad5eef99..829083651edc 100644
+--- a/drivers/staging/comedi/drivers/dmm32at.c
++++ b/drivers/staging/comedi/drivers/dmm32at.c
+@@ -234,7 +234,7 @@ static const struct dmm32at_board dmm32at_boards[] = {
+  * several hardware drivers keep similar information in this structure,
+  * feel free to suggest moving the variable to the struct comedi_device struct.
+  */
+-typedef struct {
++struct dmm32at_private {
+ 
+ 	int data;
+ 	int ai_inuse;
+@@ -244,13 +244,13 @@ typedef struct {
+ 	unsigned int ao_readback[4];
+ 	unsigned char dio_config;
+ 
+-} dmm32at_private;
++};
+ 
+ /*
+  * most drivers define the following macro to make it easy to
+  * access the private structure.
+  */
+-#define devpriv ((dmm32at_private *)dev->private)
++#define devpriv ((struct dmm32at_private *)dev->private)
+ 
+ /*
+  * The struct comedi_driver structure tells the Comedi core module
+@@ -406,7 +406,7 @@ static int dmm32at_attach(struct comedi_device * dev, struct comedi_devconfig *
+  * Allocate the private structure area.  alloc_private() is a
+  * convenient macro defined in comedidev.h.
+  */
+-	if (alloc_private(dev, sizeof(dmm32at_private)) < 0)
++	if (alloc_private(dev, sizeof(struct dmm32at_private)) < 0)
+ 		return -ENOMEM;
+ 
+ /*

commit 38baea3abba76b48ff599e1c5b7eccc80b2a7e3d
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:14:09 2009 -0400
+
+    Staging: comedi: Remove dmm32at_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
+index 1b2c58f7eb3f..4245ad5eef99 100644
+--- a/drivers/staging/comedi/drivers/dmm32at.c
++++ b/drivers/staging/comedi/drivers/dmm32at.c
+@@ -200,7 +200,7 @@ static const struct comedi_lrange dmm32at_aoranges = {
+  * boards in this way is optional, and completely driver-dependent.
+  * Some drivers use arrays such as this, other do not.
+  */
+-typedef struct dmm32at_board_struct {
++struct dmm32at_board {
+ 	const char *name;
+ 	int ai_chans;
+ 	int ai_bits;
+@@ -210,8 +210,8 @@ typedef struct dmm32at_board_struct {
+ 	const struct comedi_lrange *ao_ranges;
+ 	int have_dio;
+ 	int dio_chans;
+-} dmm32at_board;
+-static const dmm32at_board dmm32at_boards[] = {
++};
++static const struct dmm32at_board dmm32at_boards[] = {
+ 	{
+ 	      name:	"dmm32at",
+ 	      ai_chans:32,
+@@ -228,7 +228,7 @@ static const dmm32at_board dmm32at_boards[] = {
+ /*
+  * Useful for shorthand access to the particular board structure
+  */
+-#define thisboard ((const dmm32at_board *)dev->board_ptr)
++#define thisboard ((const struct dmm32at_board *)dev->board_ptr)
+ 
+ /* this structure is for data unique to this hardware driver.  If
+  * several hardware drivers keep similar information in this structure,
+@@ -284,8 +284,8 @@ static struct comedi_driver driver_dmm32at = {
+  * devices are such boards.
+  */
+       board_name:&dmm32at_boards[0].name,
+-      offset:sizeof(dmm32at_board),
+-      num_names:sizeof(dmm32at_boards) / sizeof(dmm32at_board),
++      offset:sizeof(struct dmm32at_board),
++      num_names:sizeof(dmm32at_boards) / sizeof(struct dmm32at_board),
+ };
+ 
+ /* prototypes for driver functions below */

commit c7b8bb98a46e475ae848642cf60160fc7135cd52
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:14:03 2009 -0400
+
+    Staging: comedi: Remove das6402_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c
+index 37b47267149c..2a8ca0525104 100644
+--- a/drivers/staging/comedi/drivers/das6402.c
++++ b/drivers/staging/comedi/drivers/das6402.c
+@@ -109,12 +109,12 @@ static struct comedi_driver driver_das6402 = {
+ 
+ COMEDI_INITCLEANUP(driver_das6402);
+ 
+-typedef struct {
++struct das6402_private {
+ 	int ai_bytes_to_read;
+ 
+ 	int das6402_ignoreirq;
+-} das6402_private;
+-#define devpriv ((das6402_private *)dev->private)
++};
++#define devpriv ((struct das6402_private *)dev->private)
+ 
+ static void das6402_ai_fifo_dregs(struct comedi_device * dev, struct comedi_subdevice * s);
+ 
+@@ -331,7 +331,7 @@ static int das6402_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	}
+ 	dev->irq = irq;
+ 
+-	if ((ret = alloc_private(dev, sizeof(das6402_private))) < 0)
++	if ((ret = alloc_private(dev, sizeof(struct das6402_private))) < 0)
+ 		return ret;
+ 
+ 	if ((ret = alloc_subdevices(dev, 1)) < 0)

commit 0c5a144d730a68967dfb3f8163260a142e3282e3
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:13:58 2009 -0400
+
+    Staging: comedi: Remove das1800_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
+index 950ee2c7cd57..cd4cd4e6a79b 100644
+--- a/drivers/staging/comedi/drivers/das1800.c
++++ b/drivers/staging/comedi/drivers/das1800.c
+@@ -463,7 +463,7 @@ static const struct das1800_board das1800_boards[] = {
+  */
+ #define thisboard ((const struct das1800_board *)dev->board_ptr)
+ 
+-typedef struct {
++struct das1800_private {
+ 	volatile unsigned int count;	/* number of data points left to be taken */
+ 	unsigned int divisor1;	/* value to load into board's counter 1 for timed conversions */
+ 	unsigned int divisor2;	/* value to load into board's counter 2 for timed conversions */
+@@ -481,9 +481,9 @@ typedef struct {
+ 	unsigned int dma_transfer_size;	/* size of transfer currently used, in bytes */
+ 	unsigned long iobase2;	/* secondary io address used for analog out on 'ao' boards */
+ 	short ao_update_bits;	/* remembers the last write to the 'update' dac */
+-} das1800_private;
++};
+ 
+-#define devpriv ((das1800_private *)dev->private)
++#define devpriv ((struct das1800_private *)dev->private)
+ 
+ // analog out range for boards with basic analog out
+ static const struct comedi_lrange range_ao_1 = {
+@@ -602,7 +602,7 @@ static int das1800_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	int retval;
+ 
+ 	/* allocate and initialize dev->private */
+-	if (alloc_private(dev, sizeof(das1800_private)) < 0)
++	if (alloc_private(dev, sizeof(struct das1800_private)) < 0)
+ 		return -ENOMEM;
+ 
+ 	printk("comedi%d: %s: io 0x%lx", dev->minor, driver_das1800.driver_name,

commit ce422cf3569444116d7d826b274bd59cc34d3b28
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:13:53 2009 -0400
+
+    Staging: comedi: Remove das1800_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
+index 06f755a5d32c..950ee2c7cd57 100644
+--- a/drivers/staging/comedi/drivers/das1800.c
++++ b/drivers/staging/comedi/drivers/das1800.c
+@@ -241,7 +241,7 @@ static const struct comedi_lrange range_ai_das1802 = {
+ 		}
+ };
+ 
+-typedef struct das1800_board_struct {
++struct das1800_board {
+ 	const char *name;
+ 	int ai_speed;		/* max conversion period in nanoseconds */
+ 	int resolution;		/* bits of ai resolution */
+@@ -251,13 +251,13 @@ typedef struct das1800_board_struct {
+ 	int ao_ability;		/* 0 == no analog out, 1 == basic analog out, 2 == waveform analog out */
+ 	int ao_n_chan;		/* number of analog out channels */
+ 	const struct comedi_lrange *range_ai;	/* available input ranges */
+-} das1800_board;
++};
+ 
+ /* Warning: the maximum conversion speeds listed below are
+  * not always achievable depending on board setup (see
+  * user manual.)
+  */
+-static const das1800_board das1800_boards[] = {
++static const struct das1800_board das1800_boards[] = {
+ 	{
+ 	      name:	"das-1701st",
+ 	      ai_speed:6250,
+@@ -461,7 +461,7 @@ static const das1800_board das1800_boards[] = {
+ /*
+  * Useful for shorthand access to the particular board structure
+  */
+-#define thisboard ((const das1800_board *)dev->board_ptr)
++#define thisboard ((const struct das1800_board *)dev->board_ptr)
+ 
+ typedef struct {
+ 	volatile unsigned int count;	/* number of data points left to be taken */
+@@ -509,9 +509,9 @@ static struct comedi_driver driver_das1800 = {
+       module:THIS_MODULE,
+       attach:das1800_attach,
+       detach:das1800_detach,
+-      num_names:sizeof(das1800_boards) / sizeof(das1800_board),
++      num_names:sizeof(das1800_boards) / sizeof(struct das1800_board),
+       board_name:&das1800_boards[0].name,
+-      offset:sizeof(das1800_board),
++      offset:sizeof(struct das1800_board),
+ };
+ 
+ /*
+@@ -799,7 +799,7 @@ static int das1800_probe(struct comedi_device * dev)
+ 	int board;
+ 
+ 	id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf;	/* get id bits */
+-	board = ((das1800_board *) dev->board_ptr) - das1800_boards;
++	board = ((struct das1800_board *) dev->board_ptr) - das1800_boards;
+ 
+ 	switch (id) {
+ 	case 0x3:

commit febc2ed696fe88e3e438554f94dc0d2901a37c1f
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:13:42 2009 -0400
+
+    Staging: comedi: Remove das800_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
+index 85407ef8dfb1..71586cccdaca 100644
+--- a/drivers/staging/comedi/drivers/das800.c
++++ b/drivers/staging/comedi/drivers/das800.c
+@@ -106,12 +106,12 @@ cmd triggers supported:
+ #define   STATUS2_INTE          0X20
+ #define DAS800_ID             7
+ 
+-typedef struct das800_board_struct {
++struct das800_board {
+ 	const char *name;
+ 	int ai_speed;
+ 	const struct comedi_lrange *ai_range;
+ 	int resolution;
+-} das800_board;
++};
+ 
+ //analog input ranges
+ static const struct comedi_lrange range_das800_ai = {
+@@ -182,7 +182,7 @@ static const struct comedi_lrange range_das80216_ai = {
+ 
+ enum { das800, ciodas800, das801, ciodas801, das802, ciodas802, ciodas80216 };
+ 
+-static const das800_board das800_boards[] = {
++static const struct das800_board das800_boards[] = {
+ 	{
+ 	      name:	"das-800",
+ 	      ai_speed:25000,
+@@ -230,7 +230,7 @@ static const das800_board das800_boards[] = {
+ /*
+  * Useful for shorthand access to the particular board structure
+  */
+-#define thisboard ((const das800_board *)dev->board_ptr)
++#define thisboard ((const struct das800_board *)dev->board_ptr)
+ 
+ typedef struct {
+ 	volatile unsigned int count;	/* number of data points left to be taken */
+@@ -251,9 +251,9 @@ static struct comedi_driver driver_das800 = {
+       module:THIS_MODULE,
+       attach:das800_attach,
+       detach:das800_detach,
+-      num_names:sizeof(das800_boards) / sizeof(das800_board),
++      num_names:sizeof(das800_boards) / sizeof(struct das800_board),
+       board_name:&das800_boards[0].name,
+-      offset:sizeof(das800_board),
++      offset:sizeof(struct das800_board),
+ };
+ 
+ static irqreturn_t das800_interrupt(int irq, void *d PT_REGS_ARG);

commit 65a457a1496f660a5469e4bb7edbe0195b9d887c
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:13:36 2009 -0400
+
+    Staging: comedi: Remove das16m1_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
+index 039d8e549298..0e423e199ed6 100644
+--- a/drivers/staging/comedi/drivers/das16m1.c
++++ b/drivers/staging/comedi/drivers/das16m1.c
+@@ -152,12 +152,12 @@ static unsigned int das16m1_set_pacer(struct comedi_device * dev, unsigned int n
+ 
+ static int das16m1_irq_bits(unsigned int irq);
+ 
+-typedef struct das16m1_board_struct {
++struct das16m1_board {
+ 	const char *name;
+ 	unsigned int ai_speed;
+-} das16m1_board;
++};
+ 
+-static const das16m1_board das16m1_boards[] = {
++static const struct das16m1_board das16m1_boards[] = {
+ 	{
+ 	      name:	"cio-das16/m1",	// CIO-DAS16_M1.pdf
+ 	      ai_speed:1000,	// 1MHz max speed
+@@ -191,7 +191,7 @@ struct das16m1_private_struct {
+ 	unsigned int divisor2;	// divides master clock to obtain conversion speed
+ };
+ #define devpriv ((struct das16m1_private_struct *)(dev->private))
+-#define thisboard ((const das16m1_board *)(dev->board_ptr))
++#define thisboard ((const struct das16m1_board *)(dev->board_ptr))
+ 
+ COMEDI_INITCLEANUP(driver_das16m1);
+ 

commit 67080790a44f6633acc250db915a4f6481e81ba1
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:13:31 2009 -0400
+
+    Staging: comedi: Remove jr3_channel_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
+index 059fa2d32a99..179fd9d637b4 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -141,7 +141,7 @@ typedef struct {
+ } poll_delay_t;
+ 
+ typedef struct {
+-	volatile jr3_channel_t *channel;
++	volatile struct jr3_channel *channel;
+ 	unsigned long next_time_min;
+ 	unsigned long next_time_max;
+ 	enum { state_jr3_poll,
+@@ -173,7 +173,7 @@ static poll_delay_t poll_delay_min_max(int min, int max)
+ 	return result;
+ }
+ 
+-static int is_complete(volatile jr3_channel_t * channel)
++static int is_complete(volatile struct jr3_channel *channel)
+ {
+ 	return get_s16(&channel->command_word0) == 0;
+ }
+@@ -185,7 +185,7 @@ typedef struct {
+ 	} link[8];
+ } transform_t;
+ 
+-static void set_transforms(volatile jr3_channel_t * channel,
++static void set_transforms(volatile struct jr3_channel *channel,
+ 	transform_t transf, short num)
+ {
+ 	int i;
+@@ -205,17 +205,17 @@ static void set_transforms(volatile jr3_channel_t * channel,
+ 	}
+ }
+ 
+-static void use_transform(volatile jr3_channel_t * channel, short transf_num)
++static void use_transform(volatile struct jr3_channel *channel, short transf_num)
+ {
+ 	set_s16(&channel->command_word0, 0x0500 + (transf_num & 0x000f));
+ }
+ 
+-static void use_offset(volatile jr3_channel_t * channel, short offset_num)
++static void use_offset(volatile struct jr3_channel *channel, short offset_num)
+ {
+ 	set_s16(&channel->command_word0, 0x0600 + (offset_num & 0x000f));
+ }
+ 
+-static void set_offset(volatile jr3_channel_t * channel)
++static void set_offset(volatile struct jr3_channel *channel)
+ {
+ 	set_s16(&channel->command_word0, 0x0700);
+ }
+@@ -229,7 +229,7 @@ typedef struct {
+ 	s16 mz;
+ } six_axis_t;
+ 
+-static void set_full_scales(volatile jr3_channel_t * channel,
++static void set_full_scales(volatile struct jr3_channel *channel,
+ 	six_axis_t full_scale)
+ {
+ 	printk("%d %d %d %d %d %d\n",
+@@ -245,7 +245,7 @@ static void set_full_scales(volatile jr3_channel_t * channel,
+ 	set_s16(&channel->command_word0, 0x0a00);
+ }
+ 
+-static six_axis_t get_min_full_scales(volatile jr3_channel_t * channel)
++static six_axis_t get_min_full_scales(volatile struct jr3_channel *channel)
+ {
+ 	six_axis_t result;
+ 	result.fx = get_s16(&channel->min_full_scale.fx);
+@@ -257,7 +257,7 @@ static six_axis_t get_min_full_scales(volatile jr3_channel_t * channel)
+ 	return result;
+ }
+ 
+-static six_axis_t get_max_full_scales(volatile jr3_channel_t * channel)
++static six_axis_t get_max_full_scales(volatile struct jr3_channel *channel)
+ {
+ 	six_axis_t result;
+ 	result.fx = get_s16(&channel->max_full_scale.fx);
+@@ -529,7 +529,7 @@ static poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice * s)
+ 	jr3_pci_subdev_private *p = s->private;
+ 
+ 	if (p) {
+-		volatile jr3_channel_t *channel = p->channel;
++		volatile struct jr3_channel *channel = p->channel;
+ 		int errors = get_u16(&channel->errors);
+ 
+ 		if (errors != p->errors) {
+@@ -782,9 +782,9 @@ static int jr3_pci_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	opt_bus = it->options[0];
+ 	opt_slot = it->options[1];
+ 
+-	if (sizeof(jr3_channel_t) != 0xc00) {
+-		printk("sizeof(jr3_channel_t) = %x [expected %x]\n",
+-			(unsigned)sizeof(jr3_channel_t), 0xc00);
++	if (sizeof(struct jr3_channel) != 0xc00) {
++		printk("sizeof(struct jr3_channel) = %x [expected %x]\n",
++			(unsigned)sizeof(struct jr3_channel), 0xc00);
+ 		return -EINVAL;
+ 	}
+ 
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.h b/drivers/staging/comedi/drivers/jr3_pci.h
+index d98aaa7c6f5c..3585f2941bca 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.h
++++ b/drivers/staging/comedi/drivers/jr3_pci.h
+@@ -264,7 +264,7 @@ struct intern_transform {
+ /*  JR3 force/torque sensor data definition. For more information see sensor and */
+ /*  hardware manuals. */
+ 
+-typedef struct force_sensor_data {
++struct jr3_channel {
+ 	/*  Raw_channels is the area used to store the raw data coming from */
+ 	/*  the sensor. */
+ 
+@@ -667,12 +667,12 @@ typedef struct force_sensor_data {
+ 	 */
+ 
+ 	struct intern_transform transforms[0x10];	/* offset 0x0200 */
+-} jr3_channel_t;
++};
+ 
+ struct jr3_t {
+ 	struct {
+ 		u32 program_low[0x4000];	/*  0x00000 - 0x10000 */
+-		jr3_channel_t data;	/*  0x10000 - 0x10c00 */
++		struct jr3_channel data;	/*  0x10000 - 0x10c00 */
+ 		char pad2[0x30000 - 0x00c00];	/*  0x10c00 - 0x40000 */
+ 		u32 program_high[0x8000];	/*  0x40000 - 0x60000 */
+ 		u32 reset;	/*  0x60000 - 0x60004 */

commit 1c31ddaf9b46bec3df20b3a3b95049f45f43bf84
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:13:26 2009 -0400
+
+    Staging: comedi: Remove intern_transform_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.h b/drivers/staging/comedi/drivers/jr3_pci.h
+index dc9273239e2a..d98aaa7c6f5c 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.h
++++ b/drivers/staging/comedi/drivers/jr3_pci.h
+@@ -254,12 +254,12 @@ enum link_types {
+ 
+ /*  TRANSFORM */
+ /*  Structure used to describe a transform. */
+-typedef struct {
++struct intern_transform {
+ 	struct {
+ 		u32 link_type;
+ 		s32 link_amount;
+ 	} link[8];
+-} intern_transform_t;
++};
+ 
+ /*  JR3 force/torque sensor data definition. For more information see sensor and */
+ /*  hardware manuals. */
+@@ -666,7 +666,7 @@ typedef struct force_sensor_data {
+ 	 * definition of the transform structure (pg. 26).
+ 	 */
+ 
+-	intern_transform_t transforms[0x10];	/* offset 0x0200 */
++	struct intern_transform transforms[0x10];	/* offset 0x0200 */
+ } jr3_channel_t;
+ 
+ struct jr3_t {

commit 4e1ccd9717df80a6207fe89eb0761415cbe5b2e7
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:13:20 2009 -0400
+
+    Staging: comedi: Remove link_types typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.h b/drivers/staging/comedi/drivers/jr3_pci.h
+index d8a21dea3ca2..dc9273239e2a 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.h
++++ b/drivers/staging/comedi/drivers/jr3_pci.h
+@@ -241,7 +241,7 @@ struct le_struct {
+  * 7 - negate all axes (NEG)
+  */
+ 
+-typedef enum link_types {
++enum link_types {
+ 	end_x_form,
+ 	tx,
+ 	ty,
+@@ -250,7 +250,7 @@ typedef enum link_types {
+ 	ry,
+ 	rz,
+ 	neg
+-} link_types;
++};
+ 
+ /*  TRANSFORM */
+ /*  Structure used to describe a transform. */

commit b2e1b3c2bd6245c6d3d79f69fa94813b7db9a61e
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:13:15 2009 -0400
+
+    Staging: comedi: Remove jr3_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
+index 75867c95b49d..059fa2d32a99 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -130,7 +130,7 @@ MODULE_DEVICE_TABLE(pci, jr3_pci_pci_table);
+ typedef struct {
+ 	struct pci_dev *pci_dev;
+ 	int pci_enabled;
+-	volatile jr3_t *iobase;
++	volatile struct jr3_t *iobase;
+ 	int n_channels;
+ 	struct timer_list timer;
+ } jr3_pci_dev_private;
+@@ -845,7 +845,7 @@ static int jr3_pci_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 		return -EIO;
+ 	}
+ 	devpriv->pci_enabled = 1;
+-	devpriv->iobase = ioremap(pci_resource_start(card, 0), sizeof(jr3_t));
++	devpriv->iobase = ioremap(pci_resource_start(card, 0), sizeof(struct jr3_t));
+ 	result = alloc_subdevices(dev, devpriv->n_channels);
+ 	if (result < 0)
+ 		goto out;
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.h b/drivers/staging/comedi/drivers/jr3_pci.h
+index d77f0ad62c51..d8a21dea3ca2 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.h
++++ b/drivers/staging/comedi/drivers/jr3_pci.h
+@@ -669,7 +669,7 @@ typedef struct force_sensor_data {
+ 	intern_transform_t transforms[0x10];	/* offset 0x0200 */
+ } jr3_channel_t;
+ 
+-typedef struct {
++struct jr3_t {
+ 	struct {
+ 		u32 program_low[0x4000];	/*  0x00000 - 0x10000 */
+ 		jr3_channel_t data;	/*  0x10000 - 0x10c00 */
+@@ -678,4 +678,4 @@ typedef struct {
+ 		u32 reset;	/*  0x60000 - 0x60004 */
+ 		char pad3[0x20000 - 0x00004];	/*  0x60004 - 0x80000 */
+ 	} channel[4];
+-} jr3_t;
++};

commit 0306b0cb8e13d51c16adf9bc3285de80f6dc93b3
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:13:09 2009 -0400
+
+    Staging: comedi: Remove le_struct_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.h b/drivers/staging/comedi/drivers/jr3_pci.h
+index 7c5a15bb4bf1..d77f0ad62c51 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.h
++++ b/drivers/staging/comedi/drivers/jr3_pci.h
+@@ -220,13 +220,13 @@ struct thresh_struct {
+  *    command.
+  * 2. number_of_xx_thresholds specify how many GE/LE threshold there are.
+  */
+-typedef struct {
++struct le_struct {
+ 	s32 latch_bits;
+ 	s32 number_of_ge_thresholds;
+ 	s32 number_of_le_thresholds;
+ 	struct thresh_struct thresholds[4];
+ 	s32 reserved;
+-} le_struct_t;
++};
+ 
+ /*  LINK_TYPES */
+ /* Link types is an enumerated value showing the different possible transform
+@@ -652,7 +652,7 @@ typedef struct force_sensor_data {
+ 	 * le_struct structure (pg. 23).
+ 	 */
+ 
+-	le_struct_t load_envelopes[0x10];	/* offset 0x0100 */
++	struct le_struct load_envelopes[0x10];	/* offset 0x0100 */
+ 
+ 	/* Transforms is a table containing the transform descriptions.
+ 	 * There are 16 possible transform slots in the table. The slots are

commit 38443673506e19ad9af9785c5e5ebead81b6be39
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:13:04 2009 -0400
+
+    Staging: comedi: Remove thresh_struct typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.h b/drivers/staging/comedi/drivers/jr3_pci.h
+index b385596c7755..7c5a15bb4bf1 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.h
++++ b/drivers/staging/comedi/drivers/jr3_pci.h
+@@ -204,11 +204,11 @@ enum error_bits_t {
+  *    met or exceeded.
+  */
+ 
+-typedef struct thresh_struct {
++struct thresh_struct {
+ 	s32 data_address;
+ 	s32 threshold;
+ 	s32 bit_pattern;
+-} thresh_struct;
++};
+ 
+ /*  LE_STRUCT */
+ 

commit f3fd0937adacadd368126d1999d1060390497915
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:12:59 2009 -0400
+
+    Staging: comedi: Remove vect_bits_t, warning_bits_t, and error_bits_t typedefs
+    
+    These are enums that are not used anywhere at this time.
+    This removes the typedef, but leaves the enum in place.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.h b/drivers/staging/comedi/drivers/jr3_pci.h
+index 325ed0527519..b385596c7755 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.h
++++ b/drivers/staging/comedi/drivers/jr3_pci.h
+@@ -87,7 +87,8 @@ struct six_axis_array {
+  * have two force vectors, set changeV1 to 1.
+  */
+ 
+-typedef enum {
++/* vect_bits appears to be unused at this time */
++enum {
+ 	fx = 0x0001,
+ 	fy = 0x0002,
+ 	fz = 0x0004,
+@@ -108,7 +109,7 @@ typedef enum {
+  * exceeded the near saturation value.
+  */
+ 
+-typedef enum {
++enum {
+ 	fx_near_sat = 0x0001,
+ 	fy_near_sat = 0x0002,
+ 	fz_near_sat = 0x0004,
+@@ -176,7 +177,7 @@ typedef enum {
+  * the sensor data is not being received correctly.
+  */
+ 
+-typedef enum {
++enum error_bits_t {
+ 	fx_sat = 0x0001,
+ 	fy_sat = 0x0002,
+ 	fz_sat = 0x0004,
+@@ -189,7 +190,7 @@ typedef enum {
+ 	cal_crc_bad = 0x2000,
+ 	watch_dog2 = 0x4000,
+ 	watch_dog = 0x8000
+-} error_bits_t;
++};
+ 
+ /*  THRESH_STRUCT */
+ 

commit 5671c0c2d85203472b02100a517ce5c565e5c1e0
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:12:53 2009 -0400
+
+    Staging: comedi: Remove six_axis_array_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.h b/drivers/staging/comedi/drivers/jr3_pci.h
+index 06c32f507197..325ed0527519 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.h
++++ b/drivers/staging/comedi/drivers/jr3_pci.h
+@@ -64,14 +64,14 @@ struct force_array {
+ /* The six_axis_array structure shows the layout for the offsets and
+  * the full scales.
+  */
+-typedef struct six_axis_array {
++struct six_axis_array {
+ 	s32 fx;
+ 	s32 fy;
+ 	s32 fz;
+ 	s32 mx;
+ 	s32 my;
+ 	s32 mz;
+-} six_axis_array_t;
++};
+ 
+ /* VECT_BITS */
+ /* The vect_bits structure shows the layout for indicating
+@@ -296,13 +296,13 @@ typedef struct force_sensor_data {
+ 	 * command (10) set new full scales (pg. 38).
+ 	 */
+ 
+-	six_axis_array_t shunts;	/* offset 0x0060 */
++	struct six_axis_array shunts;	/* offset 0x0060 */
+ 	s32 reserved2[2];	/* offset 0x0066 */
+ 
+ 	/* Default_FS contains the full scale that is used if the user does */
+ 	/* not set a full scale. */
+ 
+-	six_axis_array_t default_FS;	/* offset 0x0068 */
++	struct six_axis_array default_FS;	/* offset 0x0068 */
+ 	s32 reserved3;	/* offset 0x006e */
+ 
+ 	/* Load_envelope_num is the load envelope number that is currently
+@@ -339,7 +339,7 @@ typedef struct force_sensor_data {
+ 	 * cause erroneous results.
+ 	 */
+ 
+-	six_axis_array_t min_full_scale;	/* offset 0x0070 */
++	struct six_axis_array min_full_scale;	/* offset 0x0070 */
+ 	s32 reserved4;	/* offset 0x0076 */
+ 
+ 	/* Transform_num is the transform number that is currently in use.
+@@ -352,7 +352,7 @@ typedef struct force_sensor_data {
+ 	/*  Max_full_scale is the recommended maximum full scale. See */
+ 	/*  min_full_scale (pg. 9) for more details. */
+ 
+-	six_axis_array_t max_full_scale;	/* offset 0x0078 */
++	struct six_axis_array max_full_scale;	/* offset 0x0078 */
+ 	s32 reserved5;	/* offset 0x007e */
+ 
+ 	/* Peak_address is the address of the data which will be monitored
+@@ -390,7 +390,7 @@ typedef struct force_sensor_data {
+ 	 * about Z by 90 degrees, FY would be 5 and all others would be zero.
+ 	 */
+ 
+-	six_axis_array_t offsets;	/* offset 0x0088 */
++	struct six_axis_array offsets;	/* offset 0x0088 */
+ 
+ 	/* Offset_num is the number of the offset currently in use. This
+ 	 * value is set by the JR3 DSP after the user has executed the use

commit cdc14cd0ea064b4838f63073ebf5cd2fdf13f309
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:12:48 2009 -0400
+
+    Staging: comedi: Remove force_array_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
+index bb0e499d8b83..75867c95b49d 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -644,7 +644,7 @@ static poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice * s)
+ 					printk("state_jr3_init_set_full_scale_complete complete = %d\n", is_complete(channel));
+ 					result = poll_delay_min_max(20, 100);
+ 				} else {
+-					volatile force_array_t *full_scale;
++					volatile struct force_array *full_scale;
+ 
+ 					// Use ranges in kN or we will overflow arount 2000N!
+ 					full_scale = &channel->full_scale;
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.h b/drivers/staging/comedi/drivers/jr3_pci.h
+index 43d1411417a4..06c32f507197 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.h
++++ b/drivers/staging/comedi/drivers/jr3_pci.h
+@@ -50,7 +50,7 @@ struct raw_channel {
+ /* The force_array structure shows the layout for the decoupled and
+  * filtered force data.
+  */
+-typedef struct force_array {
++struct force_array {
+ 	s32 fx;
+ 	s32 fy;
+ 	s32 fz;
+@@ -59,7 +59,7 @@ typedef struct force_array {
+ 	s32 mz;
+ 	s32 v1;
+ 	s32 v2;
+-} force_array_t;
++};
+ 
+ /* The six_axis_array structure shows the layout for the offsets and
+  * the full scales.
+@@ -375,7 +375,7 @@ typedef struct force_sensor_data {
+ 	 * axes used for each vector respectively.
+ 	 */
+ 
+-	force_array_t full_scale;	/* offset 0x0080 */
++	struct force_array full_scale;	/* offset 0x0080 */
+ 
+ 	/* Offsets contains the sensor offsets. These values are subtracted from
+ 	 * the sensor data to obtain the decoupled data. The offsets are set a
+@@ -432,7 +432,7 @@ typedef struct force_sensor_data {
+ 	 * calculated is specified by the variable rate_address (pg. 12).
+ 	 */
+ 
+-	force_array_t rate_data;	/* offset 0x00c8 */
++	struct force_array rate_data;	/* offset 0x00c8 */
+ 
+ 	/* Minimum_data & maximum_data are the minimum and maximum (peak)
+ 	 * data values. The JR3 DSP can monitor any 8 contiguous data items
+@@ -446,8 +446,8 @@ typedef struct force_sensor_data {
+ 	 * also lost when plugging in a new sensor.
+ 	 */
+ 
+-	force_array_t minimum_data;	/* offset 0x00d0 */
+-	force_array_t maximum_data;	/* offset 0x00d8 */
++	struct force_array minimum_data;	/* offset 0x00d0 */
++	struct force_array maximum_data;	/* offset 0x00d8 */
+ 
+ 	/* Near_sat_value & sat_value contain the value used to determine if
+ 	 * the raw sensor is saturated. Because of decoupling and offset

commit 2deee55e66d0de60ca28703da5aba8bdaf27b4ba
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:12:43 2009 -0400
+
+    Staging: comedi: Remove raw_channel typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.h b/drivers/staging/comedi/drivers/jr3_pci.h
+index 4576dd28ae47..43d1411417a4 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.h
++++ b/drivers/staging/comedi/drivers/jr3_pci.h
+@@ -41,11 +41,11 @@ static inline void set_s16(volatile s32 * p, s16 val)
+  * varies with different sensors.
+  */
+ 
+-typedef struct raw_channel {
++struct raw_channel {
+ 	u32 raw_time;
+ 	s32 raw_data;
+ 	s32 reserved[2];
+-} raw_channel_t;
++};
+ 
+ /* The force_array structure shows the layout for the decoupled and
+  * filtered force data.
+@@ -267,7 +267,7 @@ typedef struct force_sensor_data {
+ 	/*  Raw_channels is the area used to store the raw data coming from */
+ 	/*  the sensor. */
+ 
+-	raw_channel_t raw_channels[16];	/* offset 0x0000 */
++	struct raw_channel raw_channels[16];	/* offset 0x0000 */
+ 
+ 	/*  Copyright is a null terminated ASCII string containing the JR3 */
+ 	/*  copyright notice. */

commit 0642feb3e1ffe896ff0fd67cad5fc33a51fe4651
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:12:37 2009 -0400
+
+    Staging: comedi: Remove s_val_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.h b/drivers/staging/comedi/drivers/jr3_pci.h
+index 669521e6cb84..4576dd28ae47 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.h
++++ b/drivers/staging/comedi/drivers/jr3_pci.h
+@@ -2,8 +2,6 @@
+  * is 16 bits, but aligned on a 32 bit PCI boundary
+  */
+ 
+-typedef s32 s_val_t;
+-
+ static inline u16 get_u16(volatile const u32 * p)
+ {
+ 	return (u16) readl(p);
+@@ -14,12 +12,12 @@ static inline void set_u16(volatile u32 * p, u16 val)
+ 	writel(val, p);
+ }
+ 
+-static inline s16 get_s16(volatile const s_val_t * p)
++static inline s16 get_s16(volatile const s32 * p)
+ {
+ 	return (s16) readl(p);
+ }
+ 
+-static inline void set_s16(volatile s_val_t * p, s16 val)
++static inline void set_s16(volatile s32 * p, s16 val)
+ {
+ 	writel(val, p);
+ }
+@@ -45,34 +43,34 @@ static inline void set_s16(volatile s_val_t * p, s16 val)
+ 
+ typedef struct raw_channel {
+ 	u32 raw_time;
+-	s_val_t raw_data;
+-	s_val_t reserved[2];
++	s32 raw_data;
++	s32 reserved[2];
+ } raw_channel_t;
+ 
+ /* The force_array structure shows the layout for the decoupled and
+  * filtered force data.
+  */
+ typedef struct force_array {
+-	s_val_t fx;
+-	s_val_t fy;
+-	s_val_t fz;
+-	s_val_t mx;
+-	s_val_t my;
+-	s_val_t mz;
+-	s_val_t v1;
+-	s_val_t v2;
++	s32 fx;
++	s32 fy;
++	s32 fz;
++	s32 mx;
++	s32 my;
++	s32 mz;
++	s32 v1;
++	s32 v2;
+ } force_array_t;
+ 
+ /* The six_axis_array structure shows the layout for the offsets and
+  * the full scales.
+  */
+ typedef struct six_axis_array {
+-	s_val_t fx;
+-	s_val_t fy;
+-	s_val_t fz;
+-	s_val_t mx;
+-	s_val_t my;
+-	s_val_t mz;
++	s32 fx;
++	s32 fy;
++	s32 fz;
++	s32 mx;
++	s32 my;
++	s32 mz;
+ } six_axis_array_t;
+ 
+ /* VECT_BITS */
+@@ -258,7 +256,7 @@ typedef enum link_types {
+ typedef struct {
+ 	struct {
+ 		u32 link_type;
+-		s_val_t link_amount;
++		s32 link_amount;
+ 	} link[8];
+ } intern_transform_t;
+ 
+@@ -275,7 +273,7 @@ typedef struct force_sensor_data {
+ 	/*  copyright notice. */
+ 
+ 	u32 copyright[0x0018];	/* offset 0x0040 */
+-	s_val_t reserved1[0x0008];	/* offset 0x0058 */
++	s32 reserved1[0x0008];	/* offset 0x0058 */
+ 
+ 	/* Shunts contains the sensor shunt readings. Some JR3 sensors have
+ 	 * the ability to have their gains adjusted. This allows the
+@@ -305,14 +303,14 @@ typedef struct force_sensor_data {
+ 	/* not set a full scale. */
+ 
+ 	six_axis_array_t default_FS;	/* offset 0x0068 */
+-	s_val_t reserved3;	/* offset 0x006e */
++	s32 reserved3;	/* offset 0x006e */
+ 
+ 	/* Load_envelope_num is the load envelope number that is currently
+ 	 * in use. This value is set by the user after one of the load
+ 	 * envelopes has been initialized.
+ 	 */
+ 
+-	s_val_t load_envelope_num;	/* offset 0x006f */
++	s32 load_envelope_num;	/* offset 0x006f */
+ 
+ 	/* Min_full_scale is the recommend minimum full scale. */
+ 
+@@ -342,20 +340,20 @@ typedef struct force_sensor_data {
+ 	 */
+ 
+ 	six_axis_array_t min_full_scale;	/* offset 0x0070 */
+-	s_val_t reserved4;	/* offset 0x0076 */
++	s32 reserved4;	/* offset 0x0076 */
+ 
+ 	/* Transform_num is the transform number that is currently in use.
+ 	 * This value is set by the JR3 DSP after the user has used command
+ 	 * (5) use transform # (pg. 33).
+ 	 */
+ 
+-	s_val_t transform_num;	/* offset 0x0077 */
++	s32 transform_num;	/* offset 0x0077 */
+ 
+ 	/*  Max_full_scale is the recommended maximum full scale. See */
+ 	/*  min_full_scale (pg. 9) for more details. */
+ 
+ 	six_axis_array_t max_full_scale;	/* offset 0x0078 */
+-	s_val_t reserved5;	/* offset 0x007e */
++	s32 reserved5;	/* offset 0x007e */
+ 
+ 	/* Peak_address is the address of the data which will be monitored
+ 	 * by the peak routine. This value is set by the user. The peak
+@@ -363,7 +361,7 @@ typedef struct force_sensor_data {
+ 	 * (ex. to watch filter3 data for peaks, set this value to 0x00a8).
+ 	 */
+ 
+-	s_val_t peak_address;	/* offset 0x007f */
++	s32 peak_address;	/* offset 0x007f */
+ 
+ 	/* Full_scale is the sensor full scales which are currently in use.
+ 	 * Decoupled and filtered data is scaled so that +/- 16384 is equal
+@@ -399,7 +397,7 @@ typedef struct force_sensor_data {
+ 	 * offset # command (pg. 34). It can vary between 0 and 15.
+ 	 */
+ 
+-	s_val_t offset_num;	/* offset 0x008e */
++	s32 offset_num;	/* offset 0x008e */
+ 
+ 	/* Vect_axes is a bit map showing which of the axes are being used
+ 	 * in the vector calculations. This value is set by the JR3 DSP
+@@ -465,8 +463,8 @@ typedef struct force_sensor_data {
+ 	 *   sat_value = 32768 - 2^(16 - ADC bits)
+ 	 */
+ 
+-	s_val_t near_sat_value;	/* offset 0x00e0 */
+-	s_val_t sat_value;	/* offset 0x00e1 */
++	s32 near_sat_value;	/* offset 0x00e0 */
++	s32 sat_value;	/* offset 0x00e1 */
+ 
+ 	/* Rate_address, rate_divisor & rate_count contain the data used to
+ 	 * control the calculations of the rates. Rate_address is the
+@@ -485,7 +483,7 @@ typedef struct force_sensor_data {
+ 	 * will minimize the time necessary to start the rate calculations.
+ 	 */
+ 
+-	s_val_t rate_address;	/* offset 0x00e2 */
++	s32 rate_address;	/* offset 0x00e2 */
+ 	u32 rate_divisor;	/* offset 0x00e3 */
+ 	u32 rate_count;	/* offset 0x00e4 */
+ 
+@@ -502,9 +500,9 @@ typedef struct force_sensor_data {
+ 	 * command_word1).
+ 	 */
+ 
+-	s_val_t command_word2;	/* offset 0x00e5 */
+-	s_val_t command_word1;	/* offset 0x00e6 */
+-	s_val_t command_word0;	/* offset 0x00e7 */
++	s32 command_word2;	/* offset 0x00e5 */
++	s32 command_word1;	/* offset 0x00e6 */
++	s32 command_word0;	/* offset 0x00e7 */
+ 
+ 	/* Count1 through count6 are unsigned counters which are incremented
+ 	 * every time the matching filters are calculated. Filter1 is
+@@ -559,14 +557,14 @@ typedef struct force_sensor_data {
+ 	 * (pg. 23) for more details.
+ 	 */
+ 
+-	s_val_t threshold_bits;	/* offset 0x00f2 */
++	s32 threshold_bits;	/* offset 0x00f2 */
+ 
+ 	/* Last_crc is the value that shows the actual calculated CRC. CRC
+ 	 * is short for cyclic redundancy code. It should be zero. See the
+ 	 * description for cal_crc_bad (pg. 21) for more information.
+ 	 */
+ 
+-	s_val_t last_CRC;	/* offset 0x00f3 */
++	s32 last_CRC;	/* offset 0x00f3 */
+ 
+ 	/* EEProm_ver_no contains the version number of the sensor EEProm.
+ 	 * EEProm version numbers can vary between 0 and 255.
+@@ -574,8 +572,8 @@ typedef struct force_sensor_data {
+ 	 * 3.02 would be stored as 302.
+ 	 */
+ 
+-	s_val_t eeprom_ver_no;	/* offset 0x00f4 */
+-	s_val_t software_ver_no;	/* offset 0x00f5 */
++	s32 eeprom_ver_no;	/* offset 0x00f4 */
++	s32 software_ver_no;	/* offset 0x00f5 */
+ 
+ 	/* Software_day & software_year are the release date of the software
+ 	 * the JR3 DSP is currently running. Day is the day of the year,
+@@ -583,8 +581,8 @@ typedef struct force_sensor_data {
+ 	 * years.
+ 	 */
+ 
+-	s_val_t software_day;	/* offset 0x00f6 */
+-	s_val_t software_year;	/* offset 0x00f7 */
++	s32 software_day;	/* offset 0x00f6 */
++	s32 software_year;	/* offset 0x00f7 */
+ 
+ 	/* Serial_no & model_no are the two values which uniquely identify a
+ 	 * sensor. This model number does not directly correspond to the JR3
+@@ -600,8 +598,8 @@ typedef struct force_sensor_data {
+ 	 * 366 for leap years.
+ 	 */
+ 
+-	s_val_t cal_day;	/* offset 0x00fa */
+-	s_val_t cal_year;	/* offset 0x00fb */
++	s32 cal_day;	/* offset 0x00fa */
++	s32 cal_year;	/* offset 0x00fb */
+ 
+ 	/* Units is an enumerated read only value defining the engineering
+ 	 * units used in the sensor full scale. The meanings of particular
+@@ -627,8 +625,8 @@ typedef struct force_sensor_data {
+ 	 */
+ 
+ 	u32 units;		/* offset 0x00fc */
+-	s_val_t bits;		/* offset 0x00fd */
+-	s_val_t channels;	/* offset 0x00fe */
++	s32 bits;		/* offset 0x00fd */
++	s32 channels;	/* offset 0x00fe */
+ 
+ 	/* Thickness specifies the overall thickness of the sensor from
+ 	 * flange to flange. The engineering units for this value are
+@@ -637,7 +635,7 @@ typedef struct force_sensor_data {
+ 	 * transformation from the center of the sensor to either flange.
+ 	 */
+ 
+-	s_val_t thickness;	/* offset 0x00ff */
++	s32 thickness;	/* offset 0x00ff */
+ 
+ 	/* Load_envelopes is a table containing the load envelope
+ 	 * descriptions. There are 16 possible load envelope slots in the

commit 54298a8d0696046874a644c9a2be71a1e582f688
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:12:32 2009 -0400
+
+    Staging: comedi: Remove u_val_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.h b/drivers/staging/comedi/drivers/jr3_pci.h
+index 1b43a2ad7112..669521e6cb84 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.h
++++ b/drivers/staging/comedi/drivers/jr3_pci.h
+@@ -2,16 +2,14 @@
+  * is 16 bits, but aligned on a 32 bit PCI boundary
+  */
+ 
+-typedef u32 u_val_t;
+-
+ typedef s32 s_val_t;
+ 
+-static inline u16 get_u16(volatile const u_val_t * p)
++static inline u16 get_u16(volatile const u32 * p)
+ {
+ 	return (u16) readl(p);
+ }
+ 
+-static inline void set_u16(volatile u_val_t * p, u16 val)
++static inline void set_u16(volatile u32 * p, u16 val)
+ {
+ 	writel(val, p);
+ }
+@@ -46,7 +44,7 @@ static inline void set_s16(volatile s_val_t * p, s16 val)
+  */
+ 
+ typedef struct raw_channel {
+-	u_val_t raw_time;
++	u32 raw_time;
+ 	s_val_t raw_data;
+ 	s_val_t reserved[2];
+ } raw_channel_t;
+@@ -259,7 +257,7 @@ typedef enum link_types {
+ /*  Structure used to describe a transform. */
+ typedef struct {
+ 	struct {
+-		u_val_t link_type;
++		u32 link_type;
+ 		s_val_t link_amount;
+ 	} link[8];
+ } intern_transform_t;
+@@ -276,7 +274,7 @@ typedef struct force_sensor_data {
+ 	/*  Copyright is a null terminated ASCII string containing the JR3 */
+ 	/*  copyright notice. */
+ 
+-	u_val_t copyright[0x0018];	/* offset 0x0040 */
++	u32 copyright[0x0018];	/* offset 0x0040 */
+ 	s_val_t reserved1[0x0008];	/* offset 0x0058 */
+ 
+ 	/* Shunts contains the sensor shunt readings. Some JR3 sensors have
+@@ -408,7 +406,7 @@ typedef struct force_sensor_data {
+ 	 * after the user has executed the set vector axes command (pg. 37).
+ 	 */
+ 
+-	u_val_t vect_axes;	/* offset 0x008f */
++	u32 vect_axes;	/* offset 0x008f */
+ 
+ 	/* Filter0 is the decoupled, unfiltered data from the JR3 sensor.
+ 	 * This data has had the offsets removed.
+@@ -488,8 +486,8 @@ typedef struct force_sensor_data {
+ 	 */
+ 
+ 	s_val_t rate_address;	/* offset 0x00e2 */
+-	u_val_t rate_divisor;	/* offset 0x00e3 */
+-	u_val_t rate_count;	/* offset 0x00e4 */
++	u32 rate_divisor;	/* offset 0x00e3 */
++	u32 rate_count;	/* offset 0x00e4 */
+ 
+ 	/* Command_word2 through command_word0 are the locations used to
+ 	 * send commands to the JR3 DSP. Their usage varies with the command
+@@ -520,12 +518,12 @@ typedef struct force_sensor_data {
+ 	 * once.
+ 	 */
+ 
+-	u_val_t count1;		/* offset 0x00e8 */
+-	u_val_t count2;		/* offset 0x00e9 */
+-	u_val_t count3;		/* offset 0x00ea */
+-	u_val_t count4;		/* offset 0x00eb */
+-	u_val_t count5;		/* offset 0x00ec */
+-	u_val_t count6;		/* offset 0x00ed */
++	u32 count1;		/* offset 0x00e8 */
++	u32 count2;		/* offset 0x00e9 */
++	u32 count3;		/* offset 0x00ea */
++	u32 count4;		/* offset 0x00eb */
++	u32 count5;		/* offset 0x00ec */
++	u32 count6;		/* offset 0x00ed */
+ 
+ 	/* Error_count is a running count of data reception errors. If this
+ 	 * counter is changing rapidly, it probably indicates a bad sensor
+@@ -537,7 +535,7 @@ typedef struct force_sensor_data {
+ 	 * where this counter counts a bad sample, that sample is ignored.
+ 	 */
+ 
+-	u_val_t error_count;	/* offset 0x00ee */
++	u32 error_count;	/* offset 0x00ee */
+ 
+ 	/* Count_x is a counter which is incremented every time the JR3 DSP
+ 	 * searches its job queues and finds nothing to do. It indicates the
+@@ -546,15 +544,15 @@ typedef struct force_sensor_data {
+ 	 * Issues section on pg. 49 for more details.
+ 	 */
+ 
+-	u_val_t count_x;	/* offset 0x00ef */
++	u32 count_x;	/* offset 0x00ef */
+ 
+ 	/* Warnings & errors contain the warning and error bits
+ 	 * respectively. The format of these two words is discussed on page
+ 	 * 21 under the headings warnings_bits and error_bits.
+ 	 */
+ 
+-	u_val_t warnings;	/* offset 0x00f0 */
+-	u_val_t errors;		/* offset 0x00f1 */
++	u32 warnings;	/* offset 0x00f0 */
++	u32 errors;		/* offset 0x00f1 */
+ 
+ 	/* Threshold_bits is a word containing the bits that are set by the
+ 	 * load envelopes. See load_envelopes (pg. 17) and thresh_struct
+@@ -594,8 +592,8 @@ typedef struct force_sensor_data {
+ 	 * different sensor configurations.
+ 	 */
+ 
+-	u_val_t serial_no;	/* offset 0x00f8 */
+-	u_val_t model_no;	/* offset 0x00f9 */
++	u32 serial_no;	/* offset 0x00f8 */
++	u32 model_no;	/* offset 0x00f9 */
+ 
+ 	/* Cal_day & cal_year are the sensor calibration date. Day is the
+ 	 * day of the year, with January 1 being 1, and December 31, being
+@@ -628,7 +626,7 @@ typedef struct force_sensor_data {
+ 	 * received.
+ 	 */
+ 
+-	u_val_t units;		/* offset 0x00fc */
++	u32 units;		/* offset 0x00fc */
+ 	s_val_t bits;		/* offset 0x00fd */
+ 	s_val_t channels;	/* offset 0x00fe */
+ 
+@@ -674,10 +672,10 @@ typedef struct force_sensor_data {
+ 
+ typedef struct {
+ 	struct {
+-		u_val_t program_low[0x4000];	/*  0x00000 - 0x10000 */
++		u32 program_low[0x4000];	/*  0x00000 - 0x10000 */
+ 		jr3_channel_t data;	/*  0x10000 - 0x10c00 */
+ 		char pad2[0x30000 - 0x00c00];	/*  0x10c00 - 0x40000 */
+-		u_val_t program_high[0x8000];	/*  0x40000 - 0x60000 */
++		u32 program_high[0x8000];	/*  0x40000 - 0x60000 */
+ 		u32 reset;	/*  0x60000 - 0x60004 */
+ 		char pad3[0x20000 - 0x00004];	/*  0x60004 - 0x80000 */
+ 	} channel[4];

commit b2be969bf9092cdd091e450a614798cfd42ad1f6
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:12:26 2009 -0400
+
+    Staging: comedi: Replace C99 comments in jr3_pci.h
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.h b/drivers/staging/comedi/drivers/jr3_pci.h
+index 286cdaadfa1c..1b43a2ad7112 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.h
++++ b/drivers/staging/comedi/drivers/jr3_pci.h
+@@ -1,5 +1,7 @@
+-// Helper types to take care of the fact that the DSP card memory
+-//   is 16 bits, but aligned on a 32 bit PCI boundary
++/* Helper types to take care of the fact that the DSP card memory
++ * is 16 bits, but aligned on a 32 bit PCI boundary
++ */
++
+ typedef u32 u_val_t;
+ 
+ typedef s32 s_val_t;
+@@ -24,31 +26,34 @@ static inline void set_s16(volatile s_val_t * p, s16 val)
+ 	writel(val, p);
+ }
+ 
+-// The raw data is stored in a format which facilitates rapid
+-// processing by the JR3 DSP chip. The raw_channel structure shows the
+-// format for a single channel of data. Each channel takes four,
+-// two-byte words.
+-//
+-// Raw_time is an unsigned integer which shows the value of the JR3
+-// DSP's internal clock at the time the sample was received. The clock
+-// runs at 1/10 the JR3 DSP cycle time. JR3's slowest DSP runs at 10
+-// Mhz. At 10 Mhz raw_time would therefore clock at 1 Mhz.
+-//
+-// Raw_data is the raw data received directly from the sensor. The
+-// sensor data stream is capable of representing 16 different
+-// channels. Channel 0 shows the excitation voltage at the sensor. It
+-// is used to regulate the voltage over various cable lengths.
+-// Channels 1-6 contain the coupled force data Fx through Mz. Channel
+-// 7 contains the sensor's calibration data. The use of channels 8-15
+-// varies with different sensors.
++/* The raw data is stored in a format which facilitates rapid
++ * processing by the JR3 DSP chip. The raw_channel structure shows the
++ * format for a single channel of data. Each channel takes four,
++ * two-byte words.
++ *
++ * Raw_time is an unsigned integer which shows the value of the JR3
++ * DSP's internal clock at the time the sample was received. The clock
++ * runs at 1/10 the JR3 DSP cycle time. JR3's slowest DSP runs at 10
++ * Mhz. At 10 Mhz raw_time would therefore clock at 1 Mhz.
++ *
++ * Raw_data is the raw data received directly from the sensor. The
++ * sensor data stream is capable of representing 16 different
++ * channels. Channel 0 shows the excitation voltage at the sensor. It
++ * is used to regulate the voltage over various cable lengths.
++ * Channels 1-6 contain the coupled force data Fx through Mz. Channel
++ * 7 contains the sensor's calibration data. The use of channels 8-15
++ * varies with different sensors.
++ */
++
+ typedef struct raw_channel {
+ 	u_val_t raw_time;
+ 	s_val_t raw_data;
+ 	s_val_t reserved[2];
+ } raw_channel_t;
+ 
+-// The force_array structure shows the layout for the decoupled and
+-// filtered force data.
++/* The force_array structure shows the layout for the decoupled and
++ * filtered force data.
++ */
+ typedef struct force_array {
+ 	s_val_t fx;
+ 	s_val_t fy;
+@@ -60,8 +65,9 @@ typedef struct force_array {
+ 	s_val_t v2;
+ } force_array_t;
+ 
+-// The six_axis_array structure shows the layout for the offsets and
+-// the full scales.
++/* The six_axis_array structure shows the layout for the offsets and
++ * the full scales.
++ */
+ typedef struct six_axis_array {
+ 	s_val_t fx;
+ 	s_val_t fy;
+@@ -71,18 +77,19 @@ typedef struct six_axis_array {
+ 	s_val_t mz;
+ } six_axis_array_t;
+ 
+-// VECT_BITS
+-// The vect_bits structure shows the layout for indicating
+-// which axes to use in computing the vectors. Each bit signifies
+-// selection of a single axis. The V1x axis bit corresponds to a hex
+-// value of 0x0001 and the V2z bit corresponds to a hex value of
+-// 0x0020. Example: to specify the axes V1x, V1y, V2x, and V2z the
+-// pattern would be 0x002b. Vector 1 defaults to a force vector and
+-// vector 2 defaults to a moment vector. It is possible to change one
+-// or the other so that two force vectors or two moment vectors are
+-// calculated. Setting the changeV1 bit or the changeV2 bit will
+-// change that vector to be the opposite of its default. Therefore to
+-// have two force vectors, set changeV1 to 1.
++/* VECT_BITS */
++/* The vect_bits structure shows the layout for indicating
++ * which axes to use in computing the vectors. Each bit signifies
++ * selection of a single axis. The V1x axis bit corresponds to a hex
++ * value of 0x0001 and the V2z bit corresponds to a hex value of
++ * 0x0020. Example: to specify the axes V1x, V1y, V2x, and V2z the
++ * pattern would be 0x002b. Vector 1 defaults to a force vector and
++ * vector 2 defaults to a moment vector. It is possible to change one
++ * or the other so that two force vectors or two moment vectors are
++ * calculated. Setting the changeV1 bit or the changeV2 bit will
++ * change that vector to be the opposite of its default. Therefore to
++ * have two force vectors, set changeV1 to 1.
++ */
+ 
+ typedef enum {
+ 	fx = 0x0001,
+@@ -95,13 +102,15 @@ typedef enum {
+ 	changeV1 = 0x0080
+ } vect_bits_t;
+ 
+-// WARNING_BITS
+-// The warning_bits structure shows the bit pattern for the warning
+-// word. The bit fields are shown from bit 0 (lsb) to bit 15 (msb).
+-//
+-// XX_NEAR_SET
+-// The xx_near_sat bits signify that the indicated axis has reached or
+-// exceeded the near saturation value.
++/* WARNING_BITS */
++/* The warning_bits structure shows the bit pattern for the warning
++ * word. The bit fields are shown from bit 0 (lsb) to bit 15 (msb).
++ */
++
++/*  XX_NEAR_SET */
++/* The xx_near_sat bits signify that the indicated axis has reached or
++ * exceeded the near saturation value.
++ */
+ 
+ typedef enum {
+ 	fx_near_sat = 0x0001,
+@@ -112,59 +121,64 @@ typedef enum {
+ 	mz_near_sat = 0x0020
+ } warning_bits_t;
+ 
+-// ERROR_BITS
+-// XX_SAT
+-// MEMORY_ERROR
+-// SENSOR_CHANGE
+-//
+-// The error_bits structure shows the bit pattern for the error word.
+-// The bit fields are shown from bit 0 (lsb) to bit 15 (msb). The
+-// xx_sat bits signify that the indicated axis has reached or exceeded
+-// the saturation value. The memory_error bit indicates that a problem
+-// was detected in the on-board RAM during the power-up
+-// initialization. The sensor_change bit indicates that a sensor other
+-// than the one originally plugged in has passed its CRC check. This
+-// bit latches, and must be reset by the user.
+-//
+-// SYSTEM_BUSY
+-//
+-// The system_busy bit indicates that the JR3 DSP is currently busy
+-// and is not calculating force data. This occurs when a new
+-// coordinate transformation, or new sensor full scale is set by the
+-// user. A very fast system using the force data for feedback might
+-// become unstable during the approximately 4 ms needed to accomplish
+-// these calculations. This bit will also become active when a new
+-// sensor is plugged in and the system needs to recalculate the
+-// calibration CRC.
+-//
+-// CAL_CRC_BAD
+-//
+-// The cal_crc_bad bit indicates that the calibration CRC has not
+-// calculated to zero. CRC is short for cyclic redundancy code. It is
+-// a method for determining the integrity of messages in data
+-// communication. The calibration data stored inside the sensor is
+-// transmitted to the JR3 DSP along with the sensor data. The
+-// calibration data has a CRC attached to the end of it, to assist in
+-// determining the completeness and integrity of the calibration data
+-// received from the sensor. There are two reasons the CRC may not
+-// have calculated to zero. The first is that all the calibration data
+-// has not yet been received, the second is that the calibration data
+-// has been corrupted. A typical sensor transmits the entire contents
+-// of its calibration matrix over 30 times a second. Therefore, if
+-// this bit is not zero within a couple of seconds after the sensor
+-// has been plugged in, there is a problem with the sensor's
+-// calibration data.
+-//
+-// WATCH_DOG
+-// WATCH_DOG2
+-//
+-// The watch_dog and watch_dog2 bits are sensor, not processor, watch
+-// dog bits. Watch_dog indicates that the sensor data line seems to be
+-// acting correctly, while watch_dog2 indicates that sensor data and
+-// clock are being received. It is possible for watch_dog2 to go off
+-// while watch_dog does not. This would indicate an improper clock
+-// signal, while data is acting correctly. If either watch dog barks,
+-// the sensor data is not being received correctly.
++/*  ERROR_BITS */
++/*  XX_SAT */
++/*  MEMORY_ERROR */
++/*  SENSOR_CHANGE */
++
++/* The error_bits structure shows the bit pattern for the error word.
++ * The bit fields are shown from bit 0 (lsb) to bit 15 (msb). The
++ * xx_sat bits signify that the indicated axis has reached or exceeded
++ * the saturation value. The memory_error bit indicates that a problem
++ * was detected in the on-board RAM during the power-up
++ * initialization. The sensor_change bit indicates that a sensor other
++ * than the one originally plugged in has passed its CRC check. This
++ * bit latches, and must be reset by the user.
++ *
++ */
++
++/*  SYSTEM_BUSY */
++
++/* The system_busy bit indicates that the JR3 DSP is currently busy
++ * and is not calculating force data. This occurs when a new
++ * coordinate transformation, or new sensor full scale is set by the
++ * user. A very fast system using the force data for feedback might
++ * become unstable during the approximately 4 ms needed to accomplish
++ * these calculations. This bit will also become active when a new
++ * sensor is plugged in and the system needs to recalculate the
++ * calibration CRC.
++ */
++
++/*  CAL_CRC_BAD */
++
++/* The cal_crc_bad bit indicates that the calibration CRC has not
++ * calculated to zero. CRC is short for cyclic redundancy code. It is
++ * a method for determining the integrity of messages in data
++ * communication. The calibration data stored inside the sensor is
++ * transmitted to the JR3 DSP along with the sensor data. The
++ * calibration data has a CRC attached to the end of it, to assist in
++ * determining the completeness and integrity of the calibration data
++ * received from the sensor. There are two reasons the CRC may not
++ * have calculated to zero. The first is that all the calibration data
++ * has not yet been received, the second is that the calibration data
++ * has been corrupted. A typical sensor transmits the entire contents
++ * of its calibration matrix over 30 times a second. Therefore, if
++ * this bit is not zero within a couple of seconds after the sensor
++ * has been plugged in, there is a problem with the sensor's
++ * calibration data.
++ */
++
++/* WATCH_DOG */
++/* WATCH_DOG2 */
++
++/* The watch_dog and watch_dog2 bits are sensor, not processor, watch
++ * dog bits. Watch_dog indicates that the sensor data line seems to be
++ * acting correctly, while watch_dog2 indicates that sensor data and
++ * clock are being received. It is possible for watch_dog2 to go off
++ * while watch_dog does not. This would indicate an improper clock
++ * signal, while data is acting correctly. If either watch dog barks,
++ * the sensor data is not being received correctly.
++ */
+ 
+ typedef enum {
+ 	fx_sat = 0x0001,
+@@ -181,29 +195,34 @@ typedef enum {
+ 	watch_dog = 0x8000
+ } error_bits_t;
+ 
+-// THRESH_STRUCT
+-// This structure shows the layout for a single threshold packet inside of a
+-// load envelope. Each load envelope can contain several threshold structures.
+-// 1. data_address contains the address of the data for that threshold. This
+-//    includes filtered, unfiltered, raw, rate, counters, error and warning data
+-// 2. threshold is the is the value at which, if data is above or below, the
+-//    bits will be set ... (pag.24).
+-// 3. bit_pattern contains the bits that will be set if the threshold value is
+-//    met or exceeded.
++/*  THRESH_STRUCT */
++
++/* This structure shows the layout for a single threshold packet inside of a
++ * load envelope. Each load envelope can contain several threshold structures.
++ * 1. data_address contains the address of the data for that threshold. This
++ *    includes filtered, unfiltered, raw, rate, counters, error and warning data
++ * 2. threshold is the is the value at which, if data is above or below, the
++ *    bits will be set ... (pag.24).
++ * 3. bit_pattern contains the bits that will be set if the threshold value is
++ *    met or exceeded.
++ */
++
+ typedef struct thresh_struct {
+ 	s32 data_address;
+ 	s32 threshold;
+ 	s32 bit_pattern;
+ } thresh_struct;
+ 
+-// LE_STRUCT
+-// Layout of a load enveloped packet. Four thresholds are showed ... for more
+-// see manual (pag.25)
+-// 1. latch_bits is a bit pattern that show which bits the user wants to latch.
+-//    The latched bits will not be reset once the threshold which set them is
+-//    no longer true. In that case the user must reset them using the reset_bit
+-//    command.
+-// 2. number_of_xx_thresholds specify how many GE/LE threshold there are.
++/*  LE_STRUCT */
++
++/* Layout of a load enveloped packet. Four thresholds are showed ... for more
++ * see manual (pag.25)
++ * 1. latch_bits is a bit pattern that show which bits the user wants to latch.
++ *    The latched bits will not be reset once the threshold which set them is
++ *    no longer true. In that case the user must reset them using the reset_bit
++ *    command.
++ * 2. number_of_xx_thresholds specify how many GE/LE threshold there are.
++ */
+ typedef struct {
+ 	s32 latch_bits;
+ 	s32 number_of_ge_thresholds;
+@@ -212,17 +231,19 @@ typedef struct {
+ 	s32 reserved;
+ } le_struct_t;
+ 
+-// LINK_TYPES
+-// Link types is an enumerated value showing the different possible transform
+-// link types.
+-// 0 - end transform packet
+-// 1 - translate along X axis (TX)
+-// 2 - translate along Y axis (TY)
+-// 3 - translate along Z axis (TZ)
+-// 4 - rotate about X axis (RX)
+-// 5 - rotate about Y axis (RY)
+-// 6 - rotate about Z axis (RZ)
+-// 7 - negate all axes (NEG)
++/*  LINK_TYPES */
++/* Link types is an enumerated value showing the different possible transform
++ * link types.
++ * 0 - end transform packet
++ * 1 - translate along X axis (TX)
++ * 2 - translate along Y axis (TY)
++ * 3 - translate along Z axis (TZ)
++ * 4 - rotate about X axis (RX)
++ * 5 - rotate about Y axis (RY)
++ * 6 - rotate about Z axis (RZ)
++ * 7 - negate all axes (NEG)
++ */
++
+ typedef enum link_types {
+ 	end_x_form,
+ 	tx,
+@@ -234,8 +255,8 @@ typedef enum link_types {
+ 	neg
+ } link_types;
+ 
+-// TRANSFORM
+-// Structure used to describe a transform.
++/*  TRANSFORM */
++/*  Structure used to describe a transform. */
+ typedef struct {
+ 	struct {
+ 		u_val_t link_type;
+@@ -243,153 +264,163 @@ typedef struct {
+ 	} link[8];
+ } intern_transform_t;
+ 
+-// JR3 force/torque sensor data definition. For more information see sensor and
+-// hardware manuals.
++/*  JR3 force/torque sensor data definition. For more information see sensor and */
++/*  hardware manuals. */
+ 
+ typedef struct force_sensor_data {
+-	// Raw_channels is the area used to store the raw data coming from
+-	// the sensor.
++	/*  Raw_channels is the area used to store the raw data coming from */
++	/*  the sensor. */
+ 
+ 	raw_channel_t raw_channels[16];	/* offset 0x0000 */
+ 
+-	// Copyright is a null terminated ASCII string containing the JR3
+-	// copyright notice.
++	/*  Copyright is a null terminated ASCII string containing the JR3 */
++	/*  copyright notice. */
+ 
+ 	u_val_t copyright[0x0018];	/* offset 0x0040 */
+ 	s_val_t reserved1[0x0008];	/* offset 0x0058 */
+ 
+-	// Shunts contains the sensor shunt readings. Some JR3 sensors have
+-	//  the ability to have their gains adjusted. This allows the
+-	//  hardware full scales to be adjusted to potentially allow
+-	//  better resolution or dynamic range. For sensors that have
+-	//  this ability, the gain of each sensor channel is measured at
+-	//  the time of calibration using a shunt resistor. The shunt
+-	//  resistor is placed across one arm of the resistor bridge, and
+-	//  the resulting change in the output of that channel is
+-	//  measured. This measurement is called the shunt reading, and
+-	//  is recorded here. If the user has changed the gain of the //
+-	// sensor, and made new shunt measurements, those shunt
+-	//  measurements can be placed here. The JR3 DSP will then scale
+-	//  the calibration matrix such so that the gains are again
+-	//  proper for the indicated shunt readings. If shunts is 0, then
+-	//  the sensor cannot have its gain changed. For details on
+-	//  changing the sensor gain, and making shunts readings, please
+-	//  see the sensor manual. To make these values take effect the
+-	//  user must call either command (5) use transform # (pg. 33) or
+-	//  command (10) set new full scales (pg. 38).
++	/* Shunts contains the sensor shunt readings. Some JR3 sensors have
++	 * the ability to have their gains adjusted. This allows the
++	 * hardware full scales to be adjusted to potentially allow
++	 * better resolution or dynamic range. For sensors that have
++	 * this ability, the gain of each sensor channel is measured at
++	 * the time of calibration using a shunt resistor. The shunt
++	 * resistor is placed across one arm of the resistor bridge, and
++	 * the resulting change in the output of that channel is
++	 * measured. This measurement is called the shunt reading, and
++	 * is recorded here. If the user has changed the gain of the //
++	 * sensor, and made new shunt measurements, those shunt
++	 * measurements can be placed here. The JR3 DSP will then scale
++	 * the calibration matrix such so that the gains are again
++	 * proper for the indicated shunt readings. If shunts is 0, then
++	 * the sensor cannot have its gain changed. For details on
++	 * changing the sensor gain, and making shunts readings, please
++	 * see the sensor manual. To make these values take effect the
++	 * user must call either command (5) use transform # (pg. 33) or
++	 * command (10) set new full scales (pg. 38).
++	 */
+ 
+ 	six_axis_array_t shunts;	/* offset 0x0060 */
+ 	s32 reserved2[2];	/* offset 0x0066 */
+ 
+-	// Default_FS contains the full scale that is used if the user does
+-	// not set a full scale.
++	/* Default_FS contains the full scale that is used if the user does */
++	/* not set a full scale. */
+ 
+ 	six_axis_array_t default_FS;	/* offset 0x0068 */
+ 	s_val_t reserved3;	/* offset 0x006e */
+ 
+-	// Load_envelope_num is the load envelope number that is currently
+-	// in use. This value is set by the user after one of the load
+-	// envelopes has been initialized.
++	/* Load_envelope_num is the load envelope number that is currently
++	 * in use. This value is set by the user after one of the load
++	 * envelopes has been initialized.
++	 */
+ 
+ 	s_val_t load_envelope_num;	/* offset 0x006f */
+ 
+-	// Min_full_scale is the recommend minimum full scale.
+-	//
+-	// These values in conjunction with max_full_scale (pg. 9) helps
+-	// determine the appropriate value for setting the full scales. The
+-	// software allows the user to set the sensor full scale to an
+-	// arbitrary value. But setting the full scales has some hazards. If
+-	// the full scale is set too low, the data will saturate
+-	// prematurely, and dynamic range will be lost. If the full scale is
+-	// set too high, then resolution is lost as the data is shifted to
+-	// the right and the least significant bits are lost. Therefore the
+-	// maximum full scale is the maximum value at which no resolution is
+-	// lost, and the minimum full scale is the value at which the data
+-	// will not saturate prematurely. These values are calculated
+-	// whenever a new coordinate transformation is calculated. It is
+-	// possible for the recommended maximum to be less than the
+-	// recommended minimum. This comes about primarily when using
+-	// coordinate translations. If this is the case, it means that any
+-	// full scale selection will be a compromise between dynamic range
+-	// and resolution. It is usually recommended to compromise in favor
+-	// of resolution which means that the recommend maximum full scale
+-	// should be chosen.
+-	//
+-	// WARNING: Be sure that the full scale is no less than 0.4% of the
+-	// recommended minimum full scale. Full scales below this value will
+-	// cause erroneous results.
++	/* Min_full_scale is the recommend minimum full scale. */
++
++	/* These values in conjunction with max_full_scale (pg. 9) helps
++	 * determine the appropriate value for setting the full scales. The
++	 * software allows the user to set the sensor full scale to an
++	 * arbitrary value. But setting the full scales has some hazards. If
++	 * the full scale is set too low, the data will saturate
++	 * prematurely, and dynamic range will be lost. If the full scale is
++	 * set too high, then resolution is lost as the data is shifted to
++	 * the right and the least significant bits are lost. Therefore the
++	 * maximum full scale is the maximum value at which no resolution is
++	 * lost, and the minimum full scale is the value at which the data
++	 * will not saturate prematurely. These values are calculated
++	 * whenever a new coordinate transformation is calculated. It is
++	 * possible for the recommended maximum to be less than the
++	 * recommended minimum. This comes about primarily when using
++	 * coordinate translations. If this is the case, it means that any
++	 * full scale selection will be a compromise between dynamic range
++	 * and resolution. It is usually recommended to compromise in favor
++	 * of resolution which means that the recommend maximum full scale
++	 * should be chosen.
++	 *
++	 * WARNING: Be sure that the full scale is no less than 0.4% of the
++	 * recommended minimum full scale. Full scales below this value will
++	 * cause erroneous results.
++	 */
+ 
+ 	six_axis_array_t min_full_scale;	/* offset 0x0070 */
+ 	s_val_t reserved4;	/* offset 0x0076 */
+ 
+-	// Transform_num is the transform number that is currently in use.
+-	// This value is set by the JR3 DSP after the user has used command
+-	// (5) use transform # (pg. 33).
++	/* Transform_num is the transform number that is currently in use.
++	 * This value is set by the JR3 DSP after the user has used command
++	 * (5) use transform # (pg. 33).
++	 */
+ 
+ 	s_val_t transform_num;	/* offset 0x0077 */
+ 
+-	// Max_full_scale is the recommended maximum full scale. See
+-	// min_full_scale (pg. 9) for more details.
++	/*  Max_full_scale is the recommended maximum full scale. See */
++	/*  min_full_scale (pg. 9) for more details. */
+ 
+ 	six_axis_array_t max_full_scale;	/* offset 0x0078 */
+ 	s_val_t reserved5;	/* offset 0x007e */
+ 
+-	// Peak_address is the address of the data which will be monitored
+-	// by the peak routine. This value is set by the user. The peak
+-	// routine will monitor any 8 contiguous addresses for peak values.
+-	// (ex. to watch filter3 data for peaks, set this value to 0x00a8).
++	/* Peak_address is the address of the data which will be monitored
++	 * by the peak routine. This value is set by the user. The peak
++	 * routine will monitor any 8 contiguous addresses for peak values.
++	 * (ex. to watch filter3 data for peaks, set this value to 0x00a8).
++	 */
+ 
+ 	s_val_t peak_address;	/* offset 0x007f */
+ 
+-	// Full_scale is the sensor full scales which are currently in use.
+-	// Decoupled and filtered data is scaled so that +/- 16384 is equal
+-	// to the full scales. The engineering units used are indicated by
+-	// the units value discussed on page 16. The full scales for Fx, Fy,
+-	// Fz, Mx, My and Mz can be written by the user prior to calling
+-	// command (10) set new full scales (pg. 38). The full scales for V1
+-	// and V2 are set whenever the full scales are changed or when the
+-	// axes used to calculate the vectors are changed. The full scale of
+-	// V1 and V2 will always be equal to the largest full scale of the
+-	// axes used for each vector respectively.
++	/* Full_scale is the sensor full scales which are currently in use.
++	 * Decoupled and filtered data is scaled so that +/- 16384 is equal
++	 * to the full scales. The engineering units used are indicated by
++	 * the units value discussed on page 16. The full scales for Fx, Fy,
++	 * Fz, Mx, My and Mz can be written by the user prior to calling
++	 * command (10) set new full scales (pg. 38). The full scales for V1
++	 * and V2 are set whenever the full scales are changed or when the
++	 * axes used to calculate the vectors are changed. The full scale of
++	 * V1 and V2 will always be equal to the largest full scale of the
++	 * axes used for each vector respectively.
++	 */
+ 
+ 	force_array_t full_scale;	/* offset 0x0080 */
+ 
+-	// Offsets contains the sensor offsets. These values are subtracted from
+-	// the sensor data to obtain the decoupled data. The offsets are set a
+-	// few seconds (< 10) after the calibration data has been received.
+-	// They are set so that the output data will be zero. These values
+-	// can be written as well as read. The JR3 DSP will use the values
+-	// written here within 2 ms of being written. To set future
+-	// decoupled data to zero, add these values to the current decoupled
+-	// data values and place the sum here. The JR3 DSP will change these
+-	// values when a new transform is applied. So if the offsets are
+-	// such that FX is 5 and all other values are zero, after rotating
+-	// about Z by 90 degrees, FY would be 5 and all others would be zero.
++	/* Offsets contains the sensor offsets. These values are subtracted from
++	 * the sensor data to obtain the decoupled data. The offsets are set a
++	 * few seconds (< 10) after the calibration data has been received.
++	 * They are set so that the output data will be zero. These values
++	 * can be written as well as read. The JR3 DSP will use the values
++	 * written here within 2 ms of being written. To set future
++	 * decoupled data to zero, add these values to the current decoupled
++	 * data values and place the sum here. The JR3 DSP will change these
++	 * values when a new transform is applied. So if the offsets are
++	 * such that FX is 5 and all other values are zero, after rotating
++	 * about Z by 90 degrees, FY would be 5 and all others would be zero.
++	 */
+ 
+ 	six_axis_array_t offsets;	/* offset 0x0088 */
+ 
+-	// Offset_num is the number of the offset currently in use. This
+-	// value is set by the JR3 DSP after the user has executed the use
+-	// offset # command (pg. 34). It can vary between 0 and 15.
++	/* Offset_num is the number of the offset currently in use. This
++	 * value is set by the JR3 DSP after the user has executed the use
++	 * offset # command (pg. 34). It can vary between 0 and 15.
++	 */
+ 
+ 	s_val_t offset_num;	/* offset 0x008e */
+ 
+-	// Vect_axes is a bit map showing which of the axes are being used
+-	// in the vector calculations. This value is set by the JR3 DSP
+-	// after the user has executed the set vector axes command (pg. 37).
++	/* Vect_axes is a bit map showing which of the axes are being used
++	 * in the vector calculations. This value is set by the JR3 DSP
++	 * after the user has executed the set vector axes command (pg. 37).
++	 */
+ 
+ 	u_val_t vect_axes;	/* offset 0x008f */
+ 
+-	// Filter0 is the decoupled, unfiltered data from the JR3 sensor.
+-	// This data has had the offsets removed.
+-	//
+-	// These force_arrays hold the filtered data. The decoupled data is
+-	// passed through cascaded low pass filters. Each succeeding filter
+-	// has a cutoff frequency of 1/4 of the preceding filter. The cutoff
+-	// frequency of filter1 is 1/16 of the sample rate from the sensor.
+-	// For a typical sensor with a sample rate of 8 kHz, the cutoff
+-	// frequency of filter1 would be 500 Hz. The following filters would
+-	// cutoff at 125 Hz, 31.25 Hz, 7.813 Hz, 1.953 Hz and 0.4883 Hz.
++	/* Filter0 is the decoupled, unfiltered data from the JR3 sensor.
++	 * This data has had the offsets removed.
++	 *
++	 * These force_arrays hold the filtered data. The decoupled data is
++	 * passed through cascaded low pass filters. Each succeeding filter
++	 * has a cutoff frequency of 1/4 of the preceding filter. The cutoff
++	 * frequency of filter1 is 1/16 of the sample rate from the sensor.
++	 * For a typical sensor with a sample rate of 8 kHz, the cutoff
++	 * frequency of filter1 would be 500 Hz. The following filters would
++	 * cutoff at 125 Hz, 31.25 Hz, 7.813 Hz, 1.953 Hz and 0.4883 Hz.
++	 */
+ 
+ 	struct force_array filter[7];	/* offset 0x0090,
+ 					   offset 0x0098,
+@@ -399,89 +430,95 @@ typedef struct force_sensor_data {
+ 					   offset 0x00b8 ,
+ 					   offset 0x00c0 */
+ 
+-	// Rate_data is the calculated rate data. It is a first derivative
+-	// calculation. It is calculated at a frequency specified by the
+-	// variable rate_divisor (pg. 12). The data on which the rate is
+-	// calculated is specified by the variable rate_address (pg. 12).
++	/* Rate_data is the calculated rate data. It is a first derivative
++	 * calculation. It is calculated at a frequency specified by the
++	 * variable rate_divisor (pg. 12). The data on which the rate is
++	 * calculated is specified by the variable rate_address (pg. 12).
++	 */
+ 
+ 	force_array_t rate_data;	/* offset 0x00c8 */
+ 
+-	// Minimum_data & maximum_data are the minimum and maximum (peak)
+-	// data values. The JR3 DSP can monitor any 8 contiguous data items
+-	// for minimums and maximums at full sensor bandwidth. This area is
+-	// only updated at user request. This is done so that the user does
+-	// not miss any peaks. To read the data, use either the read peaks
+-	// command (pg. 40), or the read and reset peaks command (pg. 39).
+-	// The address of the data to watch for peaks is stored in the
+-	// variable peak_address (pg. 10). Peak data is lost when executing
+-	// a coordinate transformation or a full scale change. Peak data is
+-	// also lost when plugging in a new sensor.
++	/* Minimum_data & maximum_data are the minimum and maximum (peak)
++	 * data values. The JR3 DSP can monitor any 8 contiguous data items
++	 * for minimums and maximums at full sensor bandwidth. This area is
++	 * only updated at user request. This is done so that the user does
++	 * not miss any peaks. To read the data, use either the read peaks
++	 * command (pg. 40), or the read and reset peaks command (pg. 39).
++	 * The address of the data to watch for peaks is stored in the
++	 * variable peak_address (pg. 10). Peak data is lost when executing
++	 * a coordinate transformation or a full scale change. Peak data is
++	 * also lost when plugging in a new sensor.
++	 */
+ 
+ 	force_array_t minimum_data;	/* offset 0x00d0 */
+ 	force_array_t maximum_data;	/* offset 0x00d8 */
+ 
+-	// Near_sat_value & sat_value contain the value used to determine if
+-	// the raw sensor is saturated. Because of decoupling and offset
+-	// removal, it is difficult to tell from the processed data if the
+-	// sensor is saturated. These values, in conjunction with the error
+-	// and warning words (pg. 14), provide this critical information.
+-	// These two values may be set by the host processor. These values
+-	// are positive signed values, since the saturation logic uses the
+-	// absolute values of the raw data. The near_sat_value defaults to
+-	// approximately 80% of the ADC's full scale, which is 26214, while
+-	// sat_value defaults to the ADC's full scale:
+-	//
+-	//   sat_value = 32768 - 2^(16 - ADC bits)
++	/* Near_sat_value & sat_value contain the value used to determine if
++	 * the raw sensor is saturated. Because of decoupling and offset
++	 * removal, it is difficult to tell from the processed data if the
++	 * sensor is saturated. These values, in conjunction with the error
++	 * and warning words (pg. 14), provide this critical information.
++	 * These two values may be set by the host processor. These values
++	 * are positive signed values, since the saturation logic uses the
++	 * absolute values of the raw data. The near_sat_value defaults to
++	 * approximately 80% of the ADC's full scale, which is 26214, while
++	 * sat_value defaults to the ADC's full scale:
++	 *
++	 *   sat_value = 32768 - 2^(16 - ADC bits)
++	 */
+ 
+ 	s_val_t near_sat_value;	/* offset 0x00e0 */
+ 	s_val_t sat_value;	/* offset 0x00e1 */
+ 
+-	// Rate_address, rate_divisor & rate_count contain the data used to
+-	// control the calculations of the rates. Rate_address is the
+-	// address of the data used for the rate calculation. The JR3 DSP
+-	// will calculate rates for any 8 contiguous values (ex. to
+-	// calculate rates for filter3 data set rate_address to 0x00a8).
+-	// Rate_divisor is how often the rate is calculated. If rate_divisor
+-	// is 1, the rates are calculated at full sensor bandwidth. If
+-	// rate_divisor is 200, rates are calculated every 200 samples.
+-	// Rate_divisor can be any value between 1 and 65536. Set
+-	// rate_divisor to 0 to calculate rates every 65536 samples.
+-	// Rate_count starts at zero and counts until it equals
+-	// rate_divisor, at which point the rates are calculated, and
+-	// rate_count is reset to 0. When setting a new rate divisor, it is
+-	// a good idea to set rate_count to one less than rate divisor. This
+-	// will minimize the time necessary to start the rate calculations.
++	/* Rate_address, rate_divisor & rate_count contain the data used to
++	 * control the calculations of the rates. Rate_address is the
++	 * address of the data used for the rate calculation. The JR3 DSP
++	 * will calculate rates for any 8 contiguous values (ex. to
++	 * calculate rates for filter3 data set rate_address to 0x00a8).
++	 * Rate_divisor is how often the rate is calculated. If rate_divisor
++	 * is 1, the rates are calculated at full sensor bandwidth. If
++	 * rate_divisor is 200, rates are calculated every 200 samples.
++	 * Rate_divisor can be any value between 1 and 65536. Set
++	 * rate_divisor to 0 to calculate rates every 65536 samples.
++	 * Rate_count starts at zero and counts until it equals
++	 * rate_divisor, at which point the rates are calculated, and
++	 * rate_count is reset to 0. When setting a new rate divisor, it is
++	 * a good idea to set rate_count to one less than rate divisor. This
++	 * will minimize the time necessary to start the rate calculations.
++	 */
+ 
+ 	s_val_t rate_address;	/* offset 0x00e2 */
+ 	u_val_t rate_divisor;	/* offset 0x00e3 */
+ 	u_val_t rate_count;	/* offset 0x00e4 */
+ 
+-	// Command_word2 through command_word0 are the locations used to
+-	// send commands to the JR3 DSP. Their usage varies with the command
+-	// and is detailed later in the Command Definitions section (pg.
+-	// 29). In general the user places values into various memory
+-	// locations, and then places the command word into command_word0.
+-	// The JR3 DSP will process the command and place a 0 into
+-	// command_word0 to indicate successful completion. Alternatively
+-	// the JR3 DSP will place a negative number into command_word0 to
+-	// indicate an error condition. Please note the command locations
+-	// are numbered backwards. (I.E. command_word2 comes before
+-	// command_word1).
++	/* Command_word2 through command_word0 are the locations used to
++	 * send commands to the JR3 DSP. Their usage varies with the command
++	 * and is detailed later in the Command Definitions section (pg.
++	 * 29). In general the user places values into various memory
++	 * locations, and then places the command word into command_word0.
++	 * The JR3 DSP will process the command and place a 0 into
++	 * command_word0 to indicate successful completion. Alternatively
++	 * the JR3 DSP will place a negative number into command_word0 to
++	 * indicate an error condition. Please note the command locations
++	 * are numbered backwards. (I.E. command_word2 comes before
++	 * command_word1).
++	 */
+ 
+ 	s_val_t command_word2;	/* offset 0x00e5 */
+ 	s_val_t command_word1;	/* offset 0x00e6 */
+ 	s_val_t command_word0;	/* offset 0x00e7 */
+ 
+-	// Count1 through count6 are unsigned counters which are incremented
+-	// every time the matching filters are calculated. Filter1 is
+-	// calculated at the sensor data bandwidth. So this counter would
+-	// increment at 8 kHz for a typical sensor. The rest of the counters
+-	// are incremented at 1/4 the interval of the counter immediately
+-	// preceding it, so they would count at 2 kHz, 500 Hz, 125 Hz etc.
+-	// These counters can be used to wait for data. Each time the
+-	// counter changes, the corresponding data set can be sampled, and
+-	// this will insure that the user gets each sample, once, and only
+-	// once.
++	/* Count1 through count6 are unsigned counters which are incremented
++	 * every time the matching filters are calculated. Filter1 is
++	 * calculated at the sensor data bandwidth. So this counter would
++	 * increment at 8 kHz for a typical sensor. The rest of the counters
++	 * are incremented at 1/4 the interval of the counter immediately
++	 * preceding it, so they would count at 2 kHz, 500 Hz, 125 Hz etc.
++	 * These counters can be used to wait for data. Each time the
++	 * counter changes, the corresponding data set can be sampled, and
++	 * this will insure that the user gets each sample, once, and only
++	 * once.
++	 */
+ 
+ 	u_val_t count1;		/* offset 0x00e8 */
+ 	u_val_t count2;		/* offset 0x00e9 */
+@@ -490,145 +527,158 @@ typedef struct force_sensor_data {
+ 	u_val_t count5;		/* offset 0x00ec */
+ 	u_val_t count6;		/* offset 0x00ed */
+ 
+-	// Error_count is a running count of data reception errors. If this
+-	// counter is changing rapidly, it probably indicates a bad sensor
+-	// cable connection or other hardware problem. In most installations
+-	// error_count should not change at all. But it is possible in an
+-	// extremely noisy environment to experience occasional errors even
+-	// without a hardware problem. If the sensor is well grounded, this
+-	// is probably unavoidable in these environments. On the occasions
+-	// where this counter counts a bad sample, that sample is ignored.
++	/* Error_count is a running count of data reception errors. If this
++	 * counter is changing rapidly, it probably indicates a bad sensor
++	 * cable connection or other hardware problem. In most installations
++	 * error_count should not change at all. But it is possible in an
++	 * extremely noisy environment to experience occasional errors even
++	 * without a hardware problem. If the sensor is well grounded, this
++	 * is probably unavoidable in these environments. On the occasions
++	 * where this counter counts a bad sample, that sample is ignored.
++	 */
+ 
+ 	u_val_t error_count;	/* offset 0x00ee */
+ 
+-	// Count_x is a counter which is incremented every time the JR3 DSP
+-	// searches its job queues and finds nothing to do. It indicates the
+-	// amount of idle time the JR3 DSP has available. It can also be
+-	// used to determine if the JR3 DSP is alive. See the Performance
+-	// Issues section on pg. 49 for more details.
++	/* Count_x is a counter which is incremented every time the JR3 DSP
++	 * searches its job queues and finds nothing to do. It indicates the
++	 * amount of idle time the JR3 DSP has available. It can also be
++	 * used to determine if the JR3 DSP is alive. See the Performance
++	 * Issues section on pg. 49 for more details.
++	 */
+ 
+ 	u_val_t count_x;	/* offset 0x00ef */
+ 
+-	// Warnings & errors contain the warning and error bits
+-	// respectively. The format of these two words is discussed on page
+-	// 21 under the headings warnings_bits and error_bits.
++	/* Warnings & errors contain the warning and error bits
++	 * respectively. The format of these two words is discussed on page
++	 * 21 under the headings warnings_bits and error_bits.
++	 */
+ 
+ 	u_val_t warnings;	/* offset 0x00f0 */
+ 	u_val_t errors;		/* offset 0x00f1 */
+ 
+-	// Threshold_bits is a word containing the bits that are set by the
+-	// load envelopes. See load_envelopes (pg. 17) and thresh_struct
+-	// (pg. 23) for more details.
++	/* Threshold_bits is a word containing the bits that are set by the
++	 * load envelopes. See load_envelopes (pg. 17) and thresh_struct
++	 * (pg. 23) for more details.
++	 */
+ 
+ 	s_val_t threshold_bits;	/* offset 0x00f2 */
+ 
+-	// Last_crc is the value that shows the actual calculated CRC. CRC
+-	// is short for cyclic redundancy code. It should be zero. See the
+-	// description for cal_crc_bad (pg. 21) for more information.
++	/* Last_crc is the value that shows the actual calculated CRC. CRC
++	 * is short for cyclic redundancy code. It should be zero. See the
++	 * description for cal_crc_bad (pg. 21) for more information.
++	 */
+ 
+ 	s_val_t last_CRC;	/* offset 0x00f3 */
+ 
+-	// EEProm_ver_no contains the version number of the sensor EEProm.
+-	// EEProm version numbers can vary between 0 and 255.
+-	// Software_ver_no contains the software version number. Version
+-	// 3.02 would be stored as 302.
++	/* EEProm_ver_no contains the version number of the sensor EEProm.
++	 * EEProm version numbers can vary between 0 and 255.
++	 * Software_ver_no contains the software version number. Version
++	 * 3.02 would be stored as 302.
++	 */
+ 
+ 	s_val_t eeprom_ver_no;	/* offset 0x00f4 */
+ 	s_val_t software_ver_no;	/* offset 0x00f5 */
+ 
+-	// Software_day & software_year are the release date of the software
+-	// the JR3 DSP is currently running. Day is the day of the year,
+-	// with January 1 being 1, and December 31, being 365 for non leap
+-	// years.
++	/* Software_day & software_year are the release date of the software
++	 * the JR3 DSP is currently running. Day is the day of the year,
++	 * with January 1 being 1, and December 31, being 365 for non leap
++	 * years.
++	 */
+ 
+ 	s_val_t software_day;	/* offset 0x00f6 */
+ 	s_val_t software_year;	/* offset 0x00f7 */
+ 
+-	// Serial_no & model_no are the two values which uniquely identify a
+-	// sensor. This model number does not directly correspond to the JR3
+-	// model number, but it will provide a unique identifier for
+-	// different sensor configurations.
++	/* Serial_no & model_no are the two values which uniquely identify a
++	 * sensor. This model number does not directly correspond to the JR3
++	 * model number, but it will provide a unique identifier for
++	 * different sensor configurations.
++	 */
+ 
+ 	u_val_t serial_no;	/* offset 0x00f8 */
+ 	u_val_t model_no;	/* offset 0x00f9 */
+ 
+-	// Cal_day & cal_year are the sensor calibration date. Day is the
+-	// day of the year, with January 1 being 1, and December 31, being
+-	// 366 for leap years.
++	/* Cal_day & cal_year are the sensor calibration date. Day is the
++	 * day of the year, with January 1 being 1, and December 31, being
++	 * 366 for leap years.
++	 */
+ 
+ 	s_val_t cal_day;	/* offset 0x00fa */
+ 	s_val_t cal_year;	/* offset 0x00fb */
+ 
+-	// Units is an enumerated read only value defining the engineering
+-	// units used in the sensor full scale. The meanings of particular
+-	// values are discussed in the section detailing the force_units
+-	// structure on page 22. The engineering units are setto customer
+-	// specifications during sensor manufacture and cannot be changed by
+-	// writing to Units.
+-	//
+-	// Bits contains the number of bits of resolution of the ADC
+-	// currently in use.
+-	//
+-	// Channels is a bit field showing which channels the current sensor
+-	// is capable of sending. If bit 0 is active, this sensor can send
+-	// channel 0, if bit 13 is active, this sensor can send channel 13,
+-	// etc. This bit can be active, even if the sensor is not currently
+-	// sending this channel. Some sensors are configurable as to which
+-	// channels to send, and this field only contains information on the
+-	// channels available to send, not on the current configuration. To
+-	// find which channels are currently being sent, monitor the
+-	// Raw_time fields (pg. 19) in the raw_channels array (pg. 7). If
+-	// the time is changing periodically, then that channel is being
+-	// received.
++	/* Units is an enumerated read only value defining the engineering
++	 * units used in the sensor full scale. The meanings of particular
++	 * values are discussed in the section detailing the force_units
++	 * structure on page 22. The engineering units are setto customer
++	 * specifications during sensor manufacture and cannot be changed by
++	 * writing to Units.
++	 *
++	 * Bits contains the number of bits of resolution of the ADC
++	 * currently in use.
++	 *
++	 * Channels is a bit field showing which channels the current sensor
++	 * is capable of sending. If bit 0 is active, this sensor can send
++	 * channel 0, if bit 13 is active, this sensor can send channel 13,
++	 * etc. This bit can be active, even if the sensor is not currently
++	 * sending this channel. Some sensors are configurable as to which
++	 * channels to send, and this field only contains information on the
++	 * channels available to send, not on the current configuration. To
++	 * find which channels are currently being sent, monitor the
++	 * Raw_time fields (pg. 19) in the raw_channels array (pg. 7). If
++	 * the time is changing periodically, then that channel is being
++	 * received.
++	 */
+ 
+ 	u_val_t units;		/* offset 0x00fc */
+ 	s_val_t bits;		/* offset 0x00fd */
+ 	s_val_t channels;	/* offset 0x00fe */
+ 
+-	// Thickness specifies the overall thickness of the sensor from
+-	// flange to flange. The engineering units for this value are
+-	// contained in units (pg. 16). The sensor calibration is relative
+-	// to the center of the sensor. This value allows easy coordinate
+-	// transformation from the center of the sensor to either flange.
++	/* Thickness specifies the overall thickness of the sensor from
++	 * flange to flange. The engineering units for this value are
++	 * contained in units (pg. 16). The sensor calibration is relative
++	 * to the center of the sensor. This value allows easy coordinate
++	 * transformation from the center of the sensor to either flange.
++	 */
+ 
+ 	s_val_t thickness;	/* offset 0x00ff */
+ 
+-	// Load_envelopes is a table containing the load envelope
+-	// descriptions. There are 16 possible load envelope slots in the
+-	// table. The slots are on 16 word boundaries and are numbered 0-15.
+-	// Each load envelope needs to start at the beginning of a slot but
+-	// need not be fully contained in that slot. That is to say that a
+-	// single load envelope can be larger than a single slot. The
+-	// software has been tested and ran satisfactorily with 50
+-	// thresholds active. A single load envelope this large would take
+-	// up 5 of the 16 slots. The load envelope data is laid out in an
+-	// order that is most efficient for the JR3 DSP. The structure is
+-	// detailed later in the section showing the definition of the
+-	// le_struct structure (pg. 23).
++	/* Load_envelopes is a table containing the load envelope
++	 * descriptions. There are 16 possible load envelope slots in the
++	 * table. The slots are on 16 word boundaries and are numbered 0-15.
++	 * Each load envelope needs to start at the beginning of a slot but
++	 * need not be fully contained in that slot. That is to say that a
++	 * single load envelope can be larger than a single slot. The
++	 * software has been tested and ran satisfactorily with 50
++	 * thresholds active. A single load envelope this large would take
++	 * up 5 of the 16 slots. The load envelope data is laid out in an
++	 * order that is most efficient for the JR3 DSP. The structure is
++	 * detailed later in the section showing the definition of the
++	 * le_struct structure (pg. 23).
++	 */
+ 
+ 	le_struct_t load_envelopes[0x10];	/* offset 0x0100 */
+ 
+-	// Transforms is a table containing the transform descriptions.
+-	// There are 16 possible transform slots in the table. The slots are
+-	// on 16 word boundaries and are numbered 0-15. Each transform needs
+-	// to start at the beginning of a slot but need not be fully
+-	// contained in that slot. That is to say that a single transform
+-	// can be larger than a single slot. A transform is 2 * no of links
+-	// + 1 words in length. So a single slot can contain a transform
+-	// with 7 links. Two slots can contain a transform that is 15 links.
+-	// The layout is detailed later in the section showing the
+-	// definition of the transform structure (pg. 26).
++	/* Transforms is a table containing the transform descriptions.
++	 * There are 16 possible transform slots in the table. The slots are
++	 * on 16 word boundaries and are numbered 0-15. Each transform needs
++	 * to start at the beginning of a slot but need not be fully
++	 * contained in that slot. That is to say that a single transform
++	 * can be larger than a single slot. A transform is 2 * no of links
++	 * + 1 words in length. So a single slot can contain a transform
++	 * with 7 links. Two slots can contain a transform that is 15 links.
++	 * The layout is detailed later in the section showing the
++	 * definition of the transform structure (pg. 26).
++	 */
+ 
+ 	intern_transform_t transforms[0x10];	/* offset 0x0200 */
+ } jr3_channel_t;
+ 
+ typedef struct {
+ 	struct {
+-		u_val_t program_low[0x4000];	// 0x00000 - 0x10000
+-		jr3_channel_t data;	// 0x10000 - 0x10c00
+-		char pad2[0x30000 - 0x00c00];	// 0x10c00 - 0x40000
+-		u_val_t program_high[0x8000];	// 0x40000 - 0x60000
+-		u32 reset;	// 0x60000 - 0x60004
+-		char pad3[0x20000 - 0x00004];	// 0x60004 - 0x80000
++		u_val_t program_low[0x4000];	/*  0x00000 - 0x10000 */
++		jr3_channel_t data;	/*  0x10000 - 0x10c00 */
++		char pad2[0x30000 - 0x00c00];	/*  0x10c00 - 0x40000 */
++		u_val_t program_high[0x8000];	/*  0x40000 - 0x60000 */
++		u32 reset;	/*  0x60000 - 0x60004 */
++		char pad3[0x20000 - 0x00004];	/*  0x60004 - 0x80000 */
+ 	} channel[4];
+ } jr3_t;

commit 947a33fd2196209a1aa8f00de4068e8a09a19cd9
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:12:21 2009 -0400
+
+    Staging: comedi: Remove das16_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
+index 0219c32e853c..6b6b042099de 100644
+--- a/drivers/staging/comedi/drivers/das16.c
++++ b/drivers/staging/comedi/drivers/das16.c
+@@ -355,7 +355,7 @@ static unsigned int das16_suggest_transfer_size(struct comedi_device * dev,
+ 
+ static void reg_dump(struct comedi_device * dev);
+ 
+-typedef struct das16_board_struct {
++struct das16_board {
+ 	const char *name;
+ 	void *ai;
+ 	unsigned int ai_nbits;
+@@ -371,9 +371,9 @@ typedef struct das16_board_struct {
+ 
+ 	unsigned int size;
+ 	unsigned int id;
+-} das16_board;
++};
+ 
+-static const struct das16_board_struct das16_boards[] = {
++static const struct das16_board das16_boards[] = {
+ 	{
+ 	      name:	"das-16",
+ 	      ai:	das16_ai_rinsn,
+@@ -696,7 +696,7 @@ static const struct das16_board_struct das16_boards[] = {
+ #endif
+ };
+ 
+-#define n_das16_boards ((sizeof(das16_boards))/(sizeof(das16_board)))
++#define n_das16_boards ((sizeof(das16_boards))/(sizeof(struct das16_board)))
+ 
+ static int das16_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int das16_detach(struct comedi_device * dev);
+@@ -740,7 +740,7 @@ struct das16_private_struct {
+ 	volatile short timer_mode;	// true if using timer mode
+ };
+ #define devpriv ((struct das16_private_struct *)(dev->private))
+-#define thisboard ((struct das16_board_struct *)(dev->board_ptr))
++#define thisboard ((struct das16_board *)(dev->board_ptr))
+ 
+ static int das16_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_cmd * cmd)

commit d8961467e60d42c1997fdf783fee4802c9fea8cc
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:12:16 2009 -0400
+
+    Staging: comedi: Remove local_info_t typedef in das08_cs.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
+index 7079f7c8fa6a..be6c88788c4b 100644
+--- a/drivers/staging/comedi/drivers/das08_cs.c
++++ b/drivers/staging/comedi/drivers/das08_cs.c
+@@ -156,12 +156,12 @@ static void das08_pcmcia_detach(struct pcmcia_device *);
+ 
+ static const dev_info_t dev_info = "pcm-das08";
+ 
+-typedef struct local_info_t {
++struct local_info_t {
+ 	struct pcmcia_device *link;
+ 	dev_node_t node;
+ 	int stop;
+ 	struct bus_operations *bus;
+-} local_info_t;
++};
+ 
+ /*======================================================================
+ 
+@@ -177,12 +177,12 @@ typedef struct local_info_t {
+ 
+ static int das08_pcmcia_attach(struct pcmcia_device *link)
+ {
+-	local_info_t *local;
++	struct local_info_t *local;
+ 
+ 	DEBUG(0, "das08_pcmcia_attach()\n");
+ 
+ 	/* Allocate space for private device-specific data */
+-	local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
++	local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
+ 	if (!local)
+ 		return -ENOMEM;
+ 	local->link = link;
+@@ -225,11 +225,11 @@ static void das08_pcmcia_detach(struct pcmcia_device *link)
+ 	DEBUG(0, "das08_pcmcia_detach(0x%p)\n", link);
+ 
+ 	if (link->dev_node) {
+-		((local_info_t *) link->priv)->stop = 1;
++		((struct local_info_t *) link->priv)->stop = 1;
+ 		das08_pcmcia_release(link);
+ 	}
+ 
+-	/* This points to the parent local_info_t struct */
++	/* This points to the parent struct local_info_t struct */
+ 	if (link->priv)
+ 		kfree(link->priv);
+ 
+@@ -245,7 +245,7 @@ static void das08_pcmcia_detach(struct pcmcia_device *link)
+ 
+ static void das08_pcmcia_config(struct pcmcia_device *link)
+ {
+-	local_info_t *dev = link->priv;
++	struct local_info_t *dev = link->priv;
+ 	tuple_t tuple;
+ 	cisparse_t parse;
+ 	int last_fn, last_ret;
+@@ -417,7 +417,7 @@ static void das08_pcmcia_release(struct pcmcia_device *link)
+ 
+ static int das08_pcmcia_suspend(struct pcmcia_device *link)
+ {
+-	local_info_t *local = link->priv;
++	struct local_info_t *local = link->priv;
+ 	/* Mark the device as stopped, to block IO until later */
+ 	local->stop = 1;
+ 
+@@ -426,7 +426,7 @@ static int das08_pcmcia_suspend(struct pcmcia_device *link)
+ 
+ static int das08_pcmcia_resume(struct pcmcia_device *link)
+ {
+-	local_info_t *local = link->priv;
++	struct local_info_t *local = link->priv;
+ 
+ 	local->stop = 0;
+ 	return 0;

commit b36536816e1f34b2be1da9edb78e8b55bc414081
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:12:10 2009 -0400
+
+    Staging: comedi: Remove daqboard2000_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
+index ae1f6145c565..3b8444f09f28 100644
+--- a/drivers/staging/comedi/drivers/daqboard2000.c
++++ b/drivers/staging/comedi/drivers/daqboard2000.c
+@@ -325,7 +325,7 @@ static DEFINE_PCI_DEVICE_TABLE(daqboard2000_pci_table) = {
+ 
+ MODULE_DEVICE_TABLE(pci, daqboard2000_pci_table);
+ 
+-typedef struct {
++struct daqboard2000_private {
+ 	enum {
+ 		card_daqboard_2000
+ 	} card;
+@@ -334,9 +334,9 @@ typedef struct {
+ 	void *plx;
+ 	int got_regions;
+ 	unsigned int ao_readback[2];
+-} daqboard2000_private;
++};
+ 
+-#define devpriv ((daqboard2000_private*)dev->private)
++#define devpriv ((struct daqboard2000_private *)dev->private)
+ 
+ static void writeAcqScanListEntry(struct comedi_device * dev, u16 entry)
+ {
+@@ -731,7 +731,7 @@ static int daqboard2000_attach(struct comedi_device * dev, struct comedi_devconf
+ 	bus = it->options[0];
+ 	slot = it->options[1];
+ 
+-	result = alloc_private(dev, sizeof(daqboard2000_private));
++	result = alloc_private(dev, sizeof(struct daqboard2000_private));
+ 	if (result < 0) {
+ 		return -ENOMEM;
+ 	}

commit 9da18ff8c352c8827abee8ebd8570d8bf2767ebb
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:12:05 2009 -0400
+
+    Staging: comedi: Remove boardtype typedef in daqboard2000.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
+index b02bf5c8d079..ae1f6145c565 100644
+--- a/drivers/staging/comedi/drivers/daqboard2000.c
++++ b/drivers/staging/comedi/drivers/daqboard2000.c
+@@ -306,17 +306,17 @@ static struct comedi_driver driver_daqboard2000 = {
+       detach:daqboard2000_detach,
+ };
+ 
+-typedef struct {
++struct daq200_boardtype {
+ 	const char *name;
+ 	int id;
+-} boardtype;
+-static const boardtype boardtypes[] = {
++};
++static const struct daq200_boardtype boardtypes[] = {
+ 	{"ids2", DAQBOARD2000_SUBSYSTEM_IDS2},
+ 	{"ids4", DAQBOARD2000_SUBSYSTEM_IDS4},
+ };
+ 
+-#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+-#define this_board ((const boardtype *)dev->board_ptr)
++#define n_boardtypes (sizeof(boardtypes)/sizeof(struct daq200_boardtype))
++#define this_board ((const struct daq200_boardtype *)dev->board_ptr)
+ 
+ static DEFINE_PCI_DEVICE_TABLE(daqboard2000_pci_table) = {
+ 	{0x1616, 0x0409, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},

commit 79c7b392b32fc3154911fe3d8c65274cda5d5728
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:12:00 2009 -0400
+
+    Staging: comedi: Remove daqboard2000_hw typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
+index a2408ebf9c8a..b02bf5c8d079 100644
+--- a/drivers/staging/comedi/drivers/daqboard2000.c
++++ b/drivers/staging/comedi/drivers/daqboard2000.c
+@@ -167,7 +167,7 @@ static const struct comedi_lrange range_daqboard2000_ao = { 1, {
+ 	}
+ };
+ 
+-typedef struct daqboard2000_hw {
++struct daqboard2000_hw {
+ 	volatile u16 acqControl;	// 0x00
+ 	volatile u16 acqScanListFIFO;	// 0x02
+ 	volatile u32 acqPacerClockDivLow;	// 0x04
+@@ -215,7 +215,7 @@ typedef struct daqboard2000_hw {
+ 	volatile u16 trigDacs;	// 0xbc
+ 	volatile u16 fill14;	// 0xbe
+ 	volatile s16 dioP2ExpansionIO16Bit[32];	// 0xc0
+-} daqboard2000_hw;
++};
+ 
+ /* Scan Sequencer programming */
+ #define DAQBOARD2000_SeqStartScanList            0x0011
+@@ -340,7 +340,7 @@ typedef struct {
+ 
+ static void writeAcqScanListEntry(struct comedi_device * dev, u16 entry)
+ {
+-	daqboard2000_hw *fpga = devpriv->daq;
++	struct daqboard2000_hw *fpga = devpriv->daq;
+ 
+ //  comedi_udelay(4);
+ 	fpga->acqScanListFIFO = entry & 0x00ff;
+@@ -397,7 +397,7 @@ static int daqboard2000_ai_insn_read(struct comedi_device * dev, struct comedi_s
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+-	daqboard2000_hw *fpga = devpriv->daq;
++	struct daqboard2000_hw *fpga = devpriv->daq;
+ 	int gain, chan, timeout;
+ 
+ 	fpga->acqControl =
+@@ -468,7 +468,7 @@ static int daqboard2000_ao_insn_write(struct comedi_device * dev, struct comedi_
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+-	daqboard2000_hw *fpga = devpriv->daq;
++	struct daqboard2000_hw *fpga = devpriv->daq;
+ 	int timeout;
+ 
+ 	for (i = 0; i < insn->n; i++) {
+@@ -620,7 +620,7 @@ static void daqboard2000_adcStopDmaTransfer(struct comedi_device * dev)
+ 
+ static void daqboard2000_adcDisarm(struct comedi_device * dev)
+ {
+-	daqboard2000_hw *fpga = devpriv->daq;
++	struct daqboard2000_hw *fpga = devpriv->daq;
+ 
+ 	/* Disable hardware triggers */
+ 	comedi_udelay(2);
+@@ -642,7 +642,7 @@ static void daqboard2000_adcDisarm(struct comedi_device * dev)
+ 
+ static void daqboard2000_activateReferenceDacs(struct comedi_device * dev)
+ {
+-	daqboard2000_hw *fpga = devpriv->daq;
++	struct daqboard2000_hw *fpga = devpriv->daq;
+ 	int timeout;
+ 
+ 	// Set the + reference dac value in the FPGA

commit 216ed755f720eb4df79a184fbb13798831976adb
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:11:54 2009 -0400
+
+    Staging: comedi: Remove contec_model typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
+index 123ccb6e6be1..1f194a0a45d6 100644
+--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
++++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
+@@ -38,9 +38,9 @@ Configuration Options:
+ 
+ #include "comedi_pci.h"
+ 
+-typedef enum contec_model {
++enum contec_model {
+ 	PIO1616L = 0,
+-} contec_model;
++};
+ 
+ struct contec_board {
+ 	const char *name;

commit 4f4123ba6dba07ae20c7b6eb9ca5532c0cee8614
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:11:49 2009 -0400
+
+    Staging: comedi: Remove contec_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
+index 8c7017471a98..123ccb6e6be1 100644
+--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
++++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
+@@ -66,14 +66,14 @@ MODULE_DEVICE_TABLE(pci, contec_pci_table);
+ 
+ #define thisboard ((const struct contec_board *)dev->board_ptr)
+ 
+-typedef struct {
++struct contec_private {
+ 	int data;
+ 
+ 	struct pci_dev *pci_dev;
+ 
+-} contec_private;
++};
+ 
+-#define devpriv ((contec_private *)dev->private)
++#define devpriv ((struct contec_private *)dev->private)
+ 
+ static int contec_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int contec_detach(struct comedi_device * dev);
+@@ -106,7 +106,7 @@ static int contec_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 
+ 	dev->board_name = thisboard->name;
+ 
+-	if (alloc_private(dev, sizeof(contec_private)) < 0)
++	if (alloc_private(dev, sizeof(struct contec_private)) < 0)
+ 		return -ENOMEM;
+ 
+ 	if (alloc_subdevices(dev, 2) < 0)

commit 72e7b74d505f901450e92d873dd3605a57435c1a
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:11:43 2009 -0400
+
+    Staging: comedi: Remove contec_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
+index 46e13c6faf40..8c7017471a98 100644
+--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
++++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
+@@ -42,7 +42,7 @@ typedef enum contec_model {
+ 	PIO1616L = 0,
+ } contec_model;
+ 
+-typedef struct contec_board {
++struct contec_board {
+ 	const char *name;
+ 	int model;
+ 	int in_ports;
+@@ -50,8 +50,8 @@ typedef struct contec_board {
+ 	int in_offs;
+ 	int out_offs;
+ 	int out_boffs;
+-} contec_board;
+-static const contec_board contec_boards[] = {
++};
++static const struct contec_board contec_boards[] = {
+ 	{"PIO1616L", PIO1616L, 16, 16, 0, 2, 10},
+ };
+ 
+@@ -64,7 +64,7 @@ static DEFINE_PCI_DEVICE_TABLE(contec_pci_table) = {
+ 
+ MODULE_DEVICE_TABLE(pci, contec_pci_table);
+ 
+-#define thisboard ((const contec_board *)dev->board_ptr)
++#define thisboard ((const struct contec_board *)dev->board_ptr)
+ 
+ typedef struct {
+ 	int data;

commit 0ff297c4ebf5f7119e928d74a9d952158d329aca
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:11:38 2009 -0400
+
+    Staging: comedi: Remove typedef private in cb_pcimdda.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
+index 6edbb47d4e33..e4c5b460fbd5 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
+@@ -155,7 +155,7 @@ MODULE_DEVICE_TABLE(pci, pci_table);
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+    feel free to suggest moving the variable to the struct comedi_device struct.  */
+-typedef struct {
++struct board_private_struct {
+ 	unsigned long registers;	/* set by probe */
+ 	unsigned long dio_registers;
+ 	char attached_to_8255;	/* boolean */
+@@ -167,13 +167,13 @@ typedef struct {
+ 	/* Used for AO readback */
+ 	unsigned int ao_readback[MAX_AO_READBACK_CHANNELS];
+ 
+-} private;
++};
+ 
+ /*
+  * most drivers define the following macro to make it easy to
+  * access the private structure.
+  */
+-#define devpriv ((private *)dev->private)
++#define devpriv ((struct board_private_struct *)dev->private)
+ 
+ /*
+  * The struct comedi_driver structure tells the Comedi core module
+@@ -249,7 +249,7 @@ static int attach(struct comedi_device * dev, struct comedi_devconfig * it)
+  * if this function fails (returns negative) then the private area is
+  * kfree'd by comedi
+  */
+-	if (alloc_private(dev, sizeof(private)) < 0)
++	if (alloc_private(dev, sizeof(struct board_private_struct)) < 0)
+ 		return -ENOMEM;
+ 
+ /*

commit 324da11efaea562c8270834ac03c7c3df03aa79b
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:11:33 2009 -0400
+
+    Staging: comedi: Remove board_struct typedef
+    
+    A more descriptive structure name is probably in order here.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
+index c4600d0c9bc3..6edbb47d4e33 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
+@@ -97,7 +97,7 @@ Configuration Options:
+  * This is straight from skel.c -- I did this in case this source file
+  * will someday support more than 1 board...
+  */
+-typedef struct board_struct {
++struct board_struct {
+ 	const char *name;
+ 	unsigned short device_id;
+ 	int ao_chans;
+@@ -108,7 +108,7 @@ typedef struct board_struct {
+ 	int regs_badrindex;	/* IO Region for the control, analog output,
+ 				   and DIO registers */
+ 	int reg_sz;		/* number of bytes of registers in io region */
+-} board;
++};
+ 
+ enum DIO_METHODS {
+ 	DIO_NONE = 0,
+@@ -116,7 +116,7 @@ enum DIO_METHODS {
+ 	DIO_INTERNAL		/* unimplemented */
+ };
+ 
+-static const board boards[] = {
++static const struct board_struct boards[] = {
+ 	{
+ 	      name:	"cb_pcimdda06-16",
+ 	      device_id:PCI_ID_PCIM_DDA06_16,
+@@ -133,10 +133,10 @@ static const board boards[] = {
+ /*
+  * Useful for shorthand access to the particular board structure
+  */
+-#define thisboard    ((const board *)dev->board_ptr)
++#define thisboard    ((const struct board_struct *)dev->board_ptr)
+ 
+ /* Number of boards in boards[] */
+-#define N_BOARDS	(sizeof(boards) / sizeof(board))
++#define N_BOARDS	(sizeof(boards) / sizeof(struct board_struct))
+ #define REG_SZ (thisboard->reg_sz)
+ #define REGS_BADRINDEX (thisboard->regs_badrindex)
+ 

commit ecce6332ef5f88ba0ac8e9e7511538431952dda7
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:11:22 2009 -0400
+
+    Staging: comedi: Remove timer_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/comedi_rt_timer.c b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+index 29dd715e3ff2..f40c8cffd4bb 100644
+--- a/drivers/staging/comedi/drivers/comedi_rt_timer.c
++++ b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+@@ -138,7 +138,7 @@ static struct comedi_driver driver_timer = {
+ 
+ COMEDI_INITCLEANUP(driver_timer);
+ 
+-typedef struct {
++struct timer_private {
+ 	comedi_t *device;	// device we are emulating commands for
+ 	int subd;		// subdevice we are emulating commands for
+ 	RT_TASK *rt_task;	// rt task that starts scans
+@@ -159,8 +159,8 @@ typedef struct {
+ 	volatile int rt_task_active;	// indicates rt_task is servicing a struct comedi_cmd
+ 	volatile int scan_task_active;	// indicates scan_task is servicing a struct comedi_cmd
+ 	unsigned timer_running:1;
+-} timer_private;
+-#define devpriv ((timer_private *)dev->private)
++};
++#define devpriv ((struct timer_private *)dev->private)
+ 
+ static int timer_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+@@ -623,7 +623,7 @@ static int timer_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 
+ 	if ((ret = alloc_subdevices(dev, 1)) < 0)
+ 		return ret;
+-	if ((ret = alloc_private(dev, sizeof(timer_private))) < 0)
++	if ((ret = alloc_private(dev, sizeof(struct timer_private))) < 0)
+ 		return ret;
+ 
+ 	sprintf(path, "/dev/comedi%d", it->options[0]);

commit cfee7b998b2407f5ee53d76bae9e2805baf6dbb4
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:11:17 2009 -0400
+
+    Staging: comedi: Remove cb_pcimdas_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
+index dcd56f809944..3c78c42b7f41 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
+@@ -83,7 +83,7 @@ See http://www.measurementcomputing.com/PDFManuals/pcim-das1602_16.pdf for more
+ #define RESID_COUNT_L 14
+ 
+ /* Board description */
+-typedef struct cb_pcimdas_board_struct {
++struct cb_pcimdas_board {
+ 	const char *name;
+ 	unsigned short device_id;
+ 	int ai_se_chans;	// Inputs in single-ended mode
+@@ -98,9 +98,9 @@ typedef struct cb_pcimdas_board_struct {
+ 	int dio_bits;		// number of dio bits
+ 	int has_dio;		// has DIO
+ 	const struct comedi_lrange *ranges;
+-} cb_pcimdas_board;
++};
+ 
+-static const cb_pcimdas_board cb_pcimdas_boards[] = {
++static const struct cb_pcimdas_board cb_pcimdas_boards[] = {
+ 	{
+ 	      name:	"PCIM-DAS1602/16",
+ 	      device_id:0x56,
+@@ -134,7 +134,7 @@ MODULE_DEVICE_TABLE(pci, cb_pcimdas_pci_table);
+ /*
+  * Useful for shorthand access to the particular board structure
+  */
+-#define thisboard ((const cb_pcimdas_board *)dev->board_ptr)
++#define thisboard ((const struct cb_pcimdas_board *)dev->board_ptr)
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,

commit fe7858af4f04d6ea5d18a513433846c63c70d0ec
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:11:11 2009 -0400
+
+    Staging: comedi: Remove pcidio_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c
+index 06e1306dd5fd..71a4b1482e36 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidio.c
++++ b/drivers/staging/comedi/drivers/cb_pcidio.c
+@@ -103,7 +103,7 @@ MODULE_DEVICE_TABLE(pci, pcidio_pci_table);
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+    feel free to suggest moving the variable to the struct comedi_device struct.  */
+-typedef struct {
++struct pcidio_private {
+ 	int data;		// curently unused
+ 
+ 	/* would be useful for a PCI device */
+@@ -113,13 +113,13 @@ typedef struct {
+ 	unsigned int do_readback[4];	/* up to 4 unsigned int suffice to hold 96 bits for PCI-DIO96 */
+ 
+ 	unsigned long dio_reg_base;	// address of port A of the first 8255 chip on board
+-} pcidio_private;
++};
+ 
+ /*
+  * most drivers define the following macro to make it easy to
+  * access the private structure.
+  */
+-#define devpriv ((pcidio_private *)dev->private)
++#define devpriv ((struct pcidio_private *)dev->private)
+ 
+ /*
+  * The struct comedi_driver structure tells the Comedi core module
+@@ -178,7 +178,7 @@ static int pcidio_attach(struct comedi_device * dev, struct comedi_devconfig * i
+  * Allocate the private structure area.  alloc_private() is a
+  * convenient macro defined in comedidev.h.
+  */
+-	if (alloc_private(dev, sizeof(pcidio_private)) < 0)
++	if (alloc_private(dev, sizeof(struct pcidio_private)) < 0)
+ 		return -ENOMEM;
+ /*
+  * If you can probe the device to determine what device in a series

commit c98d3debeb1101858f7bd720116d00e15ae9124d
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:11:06 2009 -0400
+
+    Staging: comedi: Remove pcidio_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c
+index a34dc9543f9d..06e1306dd5fd 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidio.c
++++ b/drivers/staging/comedi/drivers/cb_pcidio.c
+@@ -52,16 +52,16 @@ Passing a zero for an option is the same as leaving it unspecified.
+  * boards in this way is optional, and completely driver-dependent.
+  * Some drivers use arrays such as this, other do not.
+  */
+-typedef struct pcidio_board_struct {
++struct pcidio_board {
+ 	const char *name;	// anme of the board
+ 	int n_8255;		// number of 8255 chips on board
+ 
+ 	// indices of base address regions
+ 	int pcicontroler_badrindex;
+ 	int dioregs_badrindex;
+-} pcidio_board;
++};
+ 
+-static const pcidio_board pcidio_boards[] = {
++static const struct pcidio_board pcidio_boards[] = {
+ 	{
+ 	      name:	"pci-dio24",
+ 	      n_8255:	1,
+@@ -98,7 +98,7 @@ MODULE_DEVICE_TABLE(pci, pcidio_pci_table);
+ /*
+  * Useful for shorthand access to the particular board structure
+  */
+-#define thisboard ((const pcidio_board *)dev->board_ptr)
++#define thisboard ((const struct pcidio_board *)dev->board_ptr)
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+@@ -154,8 +154,8 @@ static struct comedi_driver driver_cb_pcidio = {
+ 	 */
+ // The following fields should NOT be initialized if you are dealing with PCI devices
+ //      board_name:     pcidio_boards,
+-//      offset:         sizeof(pcidio_board),
+-//      num_names:      sizeof(pcidio_boards) / sizeof(pcidio_board),
++//      offset:         sizeof(struct pcidio_board),
++//      num_names:      sizeof(pcidio_boards) / sizeof(struct pcidio_board),
+ };
+ 
+ /*------------------------------- FUNCTIONS -----------------------------------*/
+@@ -197,7 +197,7 @@ static int pcidio_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 			continue;
+ 		// loop through cards supported by this driver
+ 		for (index = 0;
+-			index < sizeof pcidio_boards / sizeof(pcidio_board);
++			index < sizeof pcidio_boards / sizeof(struct pcidio_board);
+ 			index++) {
+ 			if (pcidio_pci_table[index].device != pcidev->device)
+ 				continue;

commit cc7bb61e00a2e9e4e0d742b9917cb37406080922
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:11:00 2009 -0400
+
+    Staging: comedi: Remove cb_pcidda_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
+index 7918e322d7a2..ed0a5eb3dd91 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidda.c
++++ b/drivers/staging/comedi/drivers/cb_pcidda.c
+@@ -211,7 +211,7 @@ MODULE_DEVICE_TABLE(pci, cb_pcidda_pci_table);
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+    feel free to suggest moving the variable to the struct comedi_device struct.  */
+-typedef struct {
++struct cb_pcidda_private {
+ 	int data;
+ 
+ 	/* would be useful for a PCI device */
+@@ -224,13 +224,13 @@ typedef struct {
+ 	unsigned int dac_cal1_bits;	// bits last written to da calibration register 1
+ 	unsigned int ao_range[MAX_AO_CHANNELS];	// current range settings for output channels
+ 	u16 eeprom_data[EEPROM_SIZE];	// software copy of board's eeprom
+-} cb_pcidda_private;
++};
+ 
+ /*
+  * most drivers define the following macro to make it easy to
+  * access the private structure.
+  */
+-#define devpriv ((cb_pcidda_private *)dev->private)
++#define devpriv ((struct cb_pcidda_private *)dev->private)
+ 
+ static int cb_pcidda_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int cb_pcidda_detach(struct comedi_device * dev);
+@@ -276,7 +276,7 @@ static int cb_pcidda_attach(struct comedi_device * dev, struct comedi_devconfig
+ /*
+  * Allocate the private structure area.
+  */
+-	if (alloc_private(dev, sizeof(cb_pcidda_private)) < 0)
++	if (alloc_private(dev, sizeof(struct cb_pcidda_private)) < 0)
+ 		return -ENOMEM;
+ 
+ /*

commit 1657e325042ffc723182377a47d38ccc7319078f
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:10:55 2009 -0400
+
+    Staging: comedi: Remove cb_pcidda_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
+index 27f46a609e39..7918e322d7a2 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidda.c
++++ b/drivers/staging/comedi/drivers/cb_pcidda.c
+@@ -129,7 +129,7 @@ static const struct comedi_lrange cb_pcidda_ranges = {
+  * boards in this way is optional, and completely driver-dependent.
+  * Some drivers use arrays such as this, other do not.
+  */
+-typedef struct cb_pcidda_board_struct {
++struct cb_pcidda_board {
+ 	const char *name;
+ 	char status;		// Driver status:
+ 	// 0 - tested
+@@ -139,8 +139,8 @@ typedef struct cb_pcidda_board_struct {
+ 	int ao_chans;
+ 	int ao_bits;
+ 	const struct comedi_lrange *ranges;
+-} cb_pcidda_board;
+-static const cb_pcidda_board cb_pcidda_boards[] = {
++};
++static const struct cb_pcidda_board cb_pcidda_boards[] = {
+ 	{
+ 	      name:	"pci-dda02/12",
+ 	      status:	1,
+@@ -206,7 +206,7 @@ MODULE_DEVICE_TABLE(pci, cb_pcidda_pci_table);
+ /*
+  * Useful for shorthand access to the particular board structure
+  */
+-#define thisboard ((const cb_pcidda_board *)dev->board_ptr)
++#define thisboard ((const struct cb_pcidda_board *)dev->board_ptr)
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,

commit c77e25898523395b56e1d120195e1ad2e3efa14d
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:10:50 2009 -0400
+
+    Staging: comedi: Remove cb_pcidas_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
+index 2d73f64002b1..fcc551651367 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas.c
+@@ -399,7 +399,7 @@ MODULE_DEVICE_TABLE(pci, cb_pcidas_pci_table);
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+    feel free to suggest moving the variable to the struct comedi_device struct.  */
+-typedef struct {
++struct cb_pcidas_private {
+ 	/* would be useful for a PCI device */
+ 	struct pci_dev *pci_dev;
+ 	// base addresses
+@@ -426,13 +426,13 @@ typedef struct {
+ 	unsigned int trimpot_value[NUM_CHANNELS_8402];	// for readback of trimpot
+ 	unsigned int dac08_value;
+ 	unsigned int calibration_source;
+-} cb_pcidas_private;
++};
+ 
+ /*
+  * most drivers define the following macro to make it easy to
+  * access the private structure.
+  */
+-#define devpriv ((cb_pcidas_private *)dev->private)
++#define devpriv ((struct cb_pcidas_private *)dev->private)
+ 
+ /*
+  * The struct comedi_driver structure tells the Comedi core module
+@@ -520,7 +520,7 @@ static int cb_pcidas_attach(struct comedi_device * dev, struct comedi_devconfig
+ /*
+  * Allocate the private structure area.
+  */
+-	if (alloc_private(dev, sizeof(cb_pcidas_private)) < 0)
++	if (alloc_private(dev, sizeof(struct cb_pcidas_private)) < 0)
+ 		return -ENOMEM;
+ 
+ /*

commit 5c2670cba2a5fd1a27f938ae11b3a24518d999db
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:10:44 2009 -0400
+
+    Staging: comedi: Remove cb_pcidas_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
+index b0366e81445c..2d73f64002b1 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas.c
+@@ -241,7 +241,7 @@ enum trimpot_model {
+ 	AD8402,
+ };
+ 
+-typedef struct cb_pcidas_board_struct {
++struct cb_pcidas_board {
+ 	const char *name;
+ 	unsigned short device_id;
+ 	int ai_se_chans;	// Inputs in single-ended mode
+@@ -255,9 +255,9 @@ typedef struct cb_pcidas_board_struct {
+ 	const struct comedi_lrange *ranges;
+ 	enum trimpot_model trimpot;
+ 	unsigned has_dac08:1;
+-} cb_pcidas_board;
++};
+ 
+-static const cb_pcidas_board cb_pcidas_boards[] = {
++static const struct cb_pcidas_board cb_pcidas_boards[] = {
+ 	{
+ 	      name:	"pci-das1602/16",
+ 	      device_id:0x1,
+@@ -375,7 +375,7 @@ static const cb_pcidas_board cb_pcidas_boards[] = {
+ };
+ 
+ // Number of boards in cb_pcidas_boards
+-#define N_BOARDS	(sizeof(cb_pcidas_boards) / sizeof(cb_pcidas_board))
++#define N_BOARDS	(sizeof(cb_pcidas_boards) / sizeof(struct cb_pcidas_board))
+ 
+ static DEFINE_PCI_DEVICE_TABLE(cb_pcidas_pci_table) = {
+ 	{PCI_VENDOR_ID_CB, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+@@ -394,7 +394,7 @@ MODULE_DEVICE_TABLE(pci, cb_pcidas_pci_table);
+ /*
+  * Useful for shorthand access to the particular board structure
+  */
+-#define thisboard ((const cb_pcidas_board *)dev->board_ptr)
++#define thisboard ((const struct cb_pcidas_board *)dev->board_ptr)
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,

commit d2755d518620bfa3ab6d25aed4048a2d35868e3d
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:10:39 2009 -0400
+
+    Staging: comedi: Remove local_info_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
+index fc08d039705c..0bfe4c954eb5 100644
+--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
++++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
+@@ -685,12 +685,12 @@ static void das16cs_pcmcia_detach(struct pcmcia_device *);
+ 
+ static dev_info_t dev_info = "cb_das16_cs";
+ 
+-typedef struct local_info_t {
++struct local_info_t {
+ 	struct pcmcia_device *link;
+ 	dev_node_t node;
+ 	int stop;
+ 	struct bus_operations *bus;
+-} local_info_t;
++};
+ 
+ /*======================================================================
+ 
+@@ -706,12 +706,12 @@ typedef struct local_info_t {
+ 
+ static int das16cs_pcmcia_attach(struct pcmcia_device *link)
+ {
+-	local_info_t *local;
++	struct local_info_t *local;
+ 
+ 	DEBUG(0, "das16cs_pcmcia_attach()\n");
+ 
+ 	/* Allocate space for private device-specific data */
+-	local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
++	local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
+ 	if (!local)
+ 		return -ENOMEM;
+ 	local->link = link;
+@@ -738,17 +738,17 @@ static void das16cs_pcmcia_detach(struct pcmcia_device *link)
+ 	DEBUG(0, "das16cs_pcmcia_detach(0x%p)\n", link);
+ 
+ 	if (link->dev_node) {
+-		((local_info_t *) link->priv)->stop = 1;
++		((struct local_info_t *) link->priv)->stop = 1;
+ 		das16cs_pcmcia_release(link);
+ 	}
+-	/* This points to the parent local_info_t struct */
++	/* This points to the parent struct local_info_t struct */
+ 	if (link->priv)
+ 		kfree(link->priv);
+ }				/* das16cs_pcmcia_detach */
+ 
+ static void das16cs_pcmcia_config(struct pcmcia_device *link)
+ {
+-	local_info_t *dev = link->priv;
++	struct local_info_t *dev = link->priv;
+ 	tuple_t tuple;
+ 	cisparse_t parse;
+ 	int last_fn, last_ret;
+@@ -903,7 +903,7 @@ static void das16cs_pcmcia_release(struct pcmcia_device *link)
+ 
+ static int das16cs_pcmcia_suspend(struct pcmcia_device *link)
+ {
+-	local_info_t *local = link->priv;
++	struct local_info_t *local = link->priv;
+ 
+ 	/* Mark the device as stopped, to block IO until later */
+ 	local->stop = 1;
+@@ -913,7 +913,7 @@ static int das16cs_pcmcia_suspend(struct pcmcia_device *link)
+ 
+ static int das16cs_pcmcia_resume(struct pcmcia_device *link)
+ {
+-	local_info_t *local = link->priv;
++	struct local_info_t *local = link->priv;
+ 
+ 	local->stop = 0;
+ 	return 0;

commit bfae362ab6a9737e67a07ff82632a16181bb2d3c
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:10:34 2009 -0400
+
+    Staging: comedi: Remove das16cs_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
+index 12f0085b1894..fc08d039705c 100644
+--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
++++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
+@@ -80,14 +80,14 @@ static const struct das16cs_board das16cs_boards[] = {
+ #define n_boards (sizeof(das16cs_boards)/sizeof(das16cs_boards[0]))
+ #define thisboard ((const struct das16cs_board *)dev->board_ptr)
+ 
+-typedef struct {
++struct das16cs_private {
+ 	struct pcmcia_device *link;
+ 
+ 	unsigned int ao_readback[2];
+ 	unsigned short status1;
+ 	unsigned short status2;
+-} das16cs_private;
+-#define devpriv ((das16cs_private *)dev->private)
++};
++#define devpriv ((struct das16cs_private *)dev->private)
+ 
+ static int das16cs_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int das16cs_detach(struct comedi_device * dev);
+@@ -201,7 +201,7 @@ static int das16cs_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 
+ 	dev->board_name = thisboard->name;
+ 
+-	if (alloc_private(dev, sizeof(das16cs_private)) < 0)
++	if (alloc_private(dev, sizeof(struct das16cs_private)) < 0)
+ 		return -ENOMEM;
+ 
+ 	if (alloc_subdevices(dev, 4) < 0)

commit 3281a63d0b1eecbb21848c3e123c2fc0cd1d4a80
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:10:28 2009 -0400
+
+    Staging: comedi: Remove das16cs_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
+index 487ae3bd21d5..12f0085b1894 100644
+--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
++++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
+@@ -54,12 +54,12 @@ Status: experimental
+ #define DAS16CS_CTR_CONTROL		14
+ #define DAS16CS_DIO			16
+ 
+-typedef struct das16cs_board_struct {
++struct das16cs_board {
+ 	const char *name;
+ 	int device_id;
+ 	int n_ao_chans;
+-} das16cs_board;
+-static const das16cs_board das16cs_boards[] = {
++};
++static const struct das16cs_board das16cs_boards[] = {
+ 	{
+ 	      device_id:0x0000,/* unknown */
+ 	      name:	"PC-CARD DAS16/16",
+@@ -78,7 +78,7 @@ static const das16cs_board das16cs_boards[] = {
+ };
+ 
+ #define n_boards (sizeof(das16cs_boards)/sizeof(das16cs_boards[0]))
+-#define thisboard ((const das16cs_board *)dev->board_ptr)
++#define thisboard ((const struct das16cs_board *)dev->board_ptr)
+ 
+ typedef struct {
+ 	struct pcmcia_device *link;
+@@ -146,7 +146,7 @@ static int get_prodid(struct comedi_device * dev, struct pcmcia_device *link)
+ 	return prodid;
+ }
+ 
+-static const das16cs_board *das16cs_probe(struct comedi_device * dev,
++static const struct das16cs_board *das16cs_probe(struct comedi_device * dev,
+ 	struct pcmcia_device *link)
+ {
+ 	int id;

commit b3e8fa97c454246be2bc6f4ddf20951c5b74bc22
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:10:23 2009 -0400
+
+    Staging: comedi: Remove pci230_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
+index a534763a90f9..0c9e5737e100 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci230.c
++++ b/drivers/staging/comedi/drivers/amplc_pci230.c
+@@ -443,7 +443,7 @@ enum {
+  * Board descriptions for the two boards supported.
+  */
+ 
+-typedef struct pci230_board_struct {
++struct pci230_board {
+ 	const char *name;
+ 	unsigned short id;
+ 	int ai_chans;
+@@ -452,8 +452,8 @@ typedef struct pci230_board_struct {
+ 	int ao_bits;
+ 	int have_dio;
+ 	unsigned int min_hwver;	/* Minimum hardware version supported. */
+-} pci230_board;
+-static const pci230_board pci230_boards[] = {
++};
++static const struct pci230_board pci230_boards[] = {
+ 	{
+ 	      name:	"pci230+",
+ 	      id:	PCI_DEVICE_ID_PCI230,
+@@ -511,7 +511,7 @@ MODULE_DEVICE_TABLE(pci, pci230_pci_table);
+  * Useful for shorthand access to the particular board structure
+  */
+ #define n_pci230_boards (sizeof(pci230_boards)/sizeof(pci230_boards[0]))
+-#define thisboard ((const pci230_board *)dev->board_ptr)
++#define thisboard ((const struct pci230_board *)dev->board_ptr)
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,

commit a27872bf7b3fc4ac7ddb561662cf7eb06e8b3895
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:10:17 2009 -0400
+
+    Staging: comedi: Remove pci224_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
+index 74c5a2a9485f..770b96648932 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci224.c
++++ b/drivers/staging/comedi/drivers/amplc_pci224.c
+@@ -398,7 +398,7 @@ MODULE_DEVICE_TABLE(pci, pci224_pci_table);
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+    feel free to suggest moving the variable to the struct comedi_device struct.  */
+-typedef struct {
++struct pci224_private {
+ 	struct pci_dev *pci_dev;	/* PCI device */
+ 	const unsigned short *hwrange;
+ 	unsigned long iobase1;
+@@ -416,9 +416,9 @@ typedef struct {
+ 	short ao_stop_continuous;
+ 	unsigned short ao_enab;	/* max 16 channels so 'short' will do */
+ 	unsigned char intsce;
+-} pci224_private;
++};
+ 
+-#define devpriv ((pci224_private *)dev->private)
++#define devpriv ((struct pci224_private *)dev->private)
+ 
+ /*
+  * The struct comedi_driver structure tells the Comedi core module
+@@ -1336,7 +1336,7 @@ static int pci224_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 
+ 	bus = it->options[0];
+ 	slot = it->options[1];
+-	if ((ret = alloc_private(dev, sizeof(pci224_private))) < 0) {
++	if ((ret = alloc_private(dev, sizeof(struct pci224_private))) < 0) {
+ 		printk(KERN_ERR "comedi%d: error! out of memory!\n",
+ 			dev->minor);
+ 		return ret;

commit 5a676a21f496b68506d6ebc94bc137b7acecdbd3
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:10:12 2009 -0400
+
+    Staging: comedi: Remove pci224_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
+index f0beaa69256e..74c5a2a9485f 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci224.c
++++ b/drivers/staging/comedi/drivers/amplc_pci224.c
+@@ -346,15 +346,15 @@ static const unsigned short hwrange_pci234[1] = {
+ 
+ enum pci224_model { any_model, pci224_model, pci234_model };
+ 
+-typedef struct pci224_board_struct {
++struct pci224_board {
+ 	const char *name;
+ 	unsigned short devid;
+ 	enum pci224_model model;
+ 	unsigned int ao_chans;
+ 	unsigned int ao_bits;
+-} pci224_board;
++};
+ 
+-static const pci224_board pci224_boards[] = {
++static const struct pci224_board pci224_boards[] = {
+ 	{
+ 	      name:	"pci224",
+ 	      devid: PCI_DEVICE_ID_AMPLICON_PCI224,
+@@ -393,7 +393,7 @@ MODULE_DEVICE_TABLE(pci, pci224_pci_table);
+ /*
+  * Useful for shorthand access to the particular board structure
+  */
+-#define thisboard ((pci224_board *)dev->board_ptr)
++#define thisboard ((struct pci224_board *)dev->board_ptr)
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+@@ -434,8 +434,8 @@ static struct comedi_driver driver_amplc_pci224 = {
+       attach:pci224_attach,
+       detach:pci224_detach,
+       board_name:&pci224_boards[0].name,
+-      offset:sizeof(pci224_board),
+-      num_names:sizeof(pci224_boards) / sizeof(pci224_board),
++      offset:sizeof(struct pci224_board),
++      num_names:sizeof(pci224_boards) / sizeof(struct pci224_board),
+ };
+ 
+ COMEDI_PCI_INITCLEANUP(driver_amplc_pci224, pci224_pci_table);

commit cd60d1ec0ca6c3be3df1a2edb548613e9d175cee
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:10:06 2009 -0400
+
+    Staging: comedi: Remove pc263_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
+index 2602e7e7b2de..97ac4157adaf 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc263.c
++++ b/drivers/staging/comedi/drivers/amplc_pc263.c
+@@ -118,12 +118,12 @@ MODULE_DEVICE_TABLE(pci, pc263_pci_table);
+    several hardware drivers keep similar information in this structure,
+    feel free to suggest moving the variable to the struct comedi_device struct.  */
+ #ifdef CONFIG_COMEDI_PCI
+-typedef struct {
++struct pc263_private {
+ 	/* PCI device. */
+ 	struct pci_dev *pci_dev;
+-} pc263_private;
++};
+ 
+-#define devpriv ((pc263_private *)dev->private)
++#define devpriv ((struct pc263_private *)dev->private)
+ #endif /* CONFIG_COMEDI_PCI */
+ 
+ /*
+@@ -236,7 +236,7 @@ static int pc263_attach(struct comedi_device * dev, struct comedi_devconfig * it
+  * convenient macro defined in comedidev.h.
+  */
+ #ifdef CONFIG_COMEDI_PCI
+-	if ((ret = alloc_private(dev, sizeof(pc263_private))) < 0) {
++	if ((ret = alloc_private(dev, sizeof(struct pc263_private))) < 0) {
+ 		printk(KERN_ERR "comedi%d: error! out of memory!\n",
+ 			dev->minor);
+ 		return ret;

commit 4beb86c25085f875935480aa0422e0a983a917f3
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:10:01 2009 -0400
+
+    Staging: comedi: Remove pc263_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
+index 99db1a987ca2..2602e7e7b2de 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc263.c
++++ b/drivers/staging/comedi/drivers/amplc_pc263.c
+@@ -65,14 +65,14 @@ The state of the outputs can be read.
+ enum pc263_bustype { isa_bustype, pci_bustype };
+ enum pc263_model { pc263_model, pci263_model, anypci_model };
+ 
+-typedef struct pc263_board_struct {
++struct pc263_board {
+ 	const char *name;
+ 	const char *fancy_name;
+ 	unsigned short devid;
+ 	enum pc263_bustype bustype;
+ 	enum pc263_model model;
+-} pc263_board;
+-static const pc263_board pc263_boards[] = {
++};
++static const struct pc263_board pc263_boards[] = {
+ 	{
+ 	      name:	"pc263",
+ 	      fancy_name:"PC263",
+@@ -112,7 +112,7 @@ MODULE_DEVICE_TABLE(pci, pc263_pci_table);
+ /*
+  * Useful for shorthand access to the particular board structure
+  */
+-#define thisboard ((const pc263_board *)dev->board_ptr)
++#define thisboard ((const struct pc263_board *)dev->board_ptr)
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+@@ -140,8 +140,8 @@ static struct comedi_driver driver_amplc_pc263 = {
+       attach:pc263_attach,
+       detach:pc263_detach,
+       board_name:&pc263_boards[0].name,
+-      offset:sizeof(pc263_board),
+-      num_names:sizeof(pc263_boards) / sizeof(pc263_board),
++      offset:sizeof(struct pc263_board),
++      num_names:sizeof(pc263_boards) / sizeof(struct pc263_board),
+ };
+ 
+ static int pc263_request_region(unsigned minor, unsigned long from,

commit f1ee810a1383b623ec523edd521467a7b620a09a
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:09:56 2009 -0400
+
+    Staging: comedi: Remove pc236_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
+index 9bdd7a5628d8..2027c75feaca 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc236.c
++++ b/drivers/staging/comedi/drivers/amplc_pc236.c
+@@ -148,16 +148,16 @@ MODULE_DEVICE_TABLE(pci, pc236_pci_table);
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+    feel free to suggest moving the variable to the struct comedi_device struct.  */
+-typedef struct {
++struct pc236_private {
+ #ifdef CONFIG_COMEDI_PCI
+ 	/* PCI device */
+ 	struct pci_dev *pci_dev;
+ 	unsigned long lcr_iobase;	/* PLX PCI9052 config registers in PCIBAR1 */
+ #endif
+ 	int enable_irq;
+-} pc236_private;
++};
+ 
+-#define devpriv ((pc236_private *)dev->private)
++#define devpriv ((struct pc236_private *)dev->private)
+ 
+ /*
+  * The struct comedi_driver structure tells the Comedi core module
+@@ -282,7 +282,7 @@ static int pc236_attach(struct comedi_device * dev, struct comedi_devconfig * it
+  * Allocate the private structure area.  alloc_private() is a
+  * convenient macro defined in comedidev.h.
+  */
+-	if ((ret = alloc_private(dev, sizeof(pc236_private))) < 0) {
++	if ((ret = alloc_private(dev, sizeof(struct pc236_private))) < 0) {
+ 		printk(KERN_ERR "comedi%d: error! out of memory!\n",
+ 			dev->minor);
+ 		return ret;

commit 57ad869651d1d2f163a1c5ccb577ee794847fd77
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:09:50 2009 -0400
+
+    Staging: comedi: Remove pc236_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
+index ed253482d991..9bdd7a5628d8 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc236.c
++++ b/drivers/staging/comedi/drivers/amplc_pc236.c
+@@ -96,14 +96,14 @@ unused.
+ enum pc236_bustype { isa_bustype, pci_bustype };
+ enum pc236_model { pc36at_model, pci236_model, anypci_model };
+ 
+-typedef struct pc236_board_struct {
++struct pc236_board {
+ 	const char *name;
+ 	const char *fancy_name;
+ 	unsigned short devid;
+ 	enum pc236_bustype bustype;
+ 	enum pc236_model model;
+-} pc236_board;
+-static const pc236_board pc236_boards[] = {
++};
++static const struct pc236_board pc236_boards[] = {
+ 	{
+ 	      name:	"pc36at",
+ 	      fancy_name:"PC36AT",
+@@ -143,7 +143,7 @@ MODULE_DEVICE_TABLE(pci, pc236_pci_table);
+ /*
+  * Useful for shorthand access to the particular board structure
+  */
+-#define thisboard ((const pc236_board *)dev->board_ptr)
++#define thisboard ((const struct pc236_board *)dev->board_ptr)
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+@@ -173,8 +173,8 @@ static struct comedi_driver driver_amplc_pc236 = {
+       attach:pc236_attach,
+       detach:pc236_detach,
+       board_name:&pc236_boards[0].name,
+-      offset:sizeof(pc236_board),
+-      num_names:sizeof(pc236_boards) / sizeof(pc236_board),
++      offset:sizeof(struct pc236_board),
++      num_names:sizeof(pc236_boards) / sizeof(struct pc236_board),
+ };
+ 
+ #ifdef CONFIG_COMEDI_PCI

commit d9752ee071117f32495da04d3cc9cb4453b5a46e
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:09:45 2009 -0400
+
+    Staging: comedi: Remove dio200_subdev_intr typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
+index e8faf2b61a05..8555e272a861 100644
+--- a/drivers/staging/comedi/drivers/amplc_dio200.c
++++ b/drivers/staging/comedi/drivers/amplc_dio200.c
+@@ -456,7 +456,7 @@ struct dio200_subdev_8254 {
+ 	unsigned gate_src[3];	/* Current gate sources */
+ };
+ 
+-typedef struct {
++struct dio200_subdev_intr {
+ 	unsigned long iobase;
+ 	spinlock_t spinlock;
+ 	int active;
+@@ -465,7 +465,7 @@ typedef struct {
+ 	unsigned int enabled_isns;
+ 	unsigned int stopcount;
+ 	int continuous;
+-} dio200_subdev_intr;
++};
+ 
+ /*
+  * The struct comedi_driver structure tells the Comedi core module
+@@ -575,7 +575,7 @@ static int
+ dio200_subdev_intr_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	dio200_subdev_intr *subpriv = s->private;
++	struct dio200_subdev_intr *subpriv = s->private;
+ 
+ 	if (subpriv->has_int_sce) {
+ 		/* Just read the interrupt status register.  */
+@@ -593,7 +593,7 @@ dio200_subdev_intr_insn_bits(struct comedi_device * dev, struct comedi_subdevice
+  */
+ static void dio200_stop_intr(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	dio200_subdev_intr *subpriv = s->private;
++	struct dio200_subdev_intr *subpriv = s->private;
+ 
+ 	subpriv->active = 0;
+ 	subpriv->enabled_isns = 0;
+@@ -609,7 +609,7 @@ static int dio200_start_intr(struct comedi_device * dev, struct comedi_subdevice
+ {
+ 	unsigned int n;
+ 	unsigned isn_bits;
+-	dio200_subdev_intr *subpriv = s->private;
++	struct dio200_subdev_intr *subpriv = s->private;
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+ 	int retval = 0;
+ 
+@@ -644,7 +644,7 @@ static int
+ dio200_inttrig_start_intr(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int trignum)
+ {
+-	dio200_subdev_intr *subpriv;
++	struct dio200_subdev_intr *subpriv;
+ 	unsigned long flags;
+ 	int event = 0;
+ 
+@@ -673,7 +673,7 @@ dio200_inttrig_start_intr(struct comedi_device * dev, struct comedi_subdevice *
+  */
+ static int dio200_handle_read_intr(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	dio200_subdev_intr *subpriv = s->private;
++	struct dio200_subdev_intr *subpriv = s->private;
+ 	unsigned triggered;
+ 	unsigned intstat;
+ 	unsigned cur_enabled;
+@@ -785,7 +785,7 @@ static int dio200_handle_read_intr(struct comedi_device * dev, struct comedi_sub
+  */
+ static int dio200_subdev_intr_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	dio200_subdev_intr *subpriv = s->private;
++	struct dio200_subdev_intr *subpriv = s->private;
+ 	unsigned long flags;
+ 
+ 	comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
+@@ -910,7 +910,7 @@ dio200_subdev_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevice *
+ static int dio200_subdev_intr_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+-	dio200_subdev_intr *subpriv = s->private;
++	struct dio200_subdev_intr *subpriv = s->private;
+ 	unsigned long flags;
+ 	int event = 0;
+ 
+@@ -956,7 +956,7 @@ static int
+ dio200_subdev_intr_init(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned long iobase, unsigned valid_isns, int has_int_sce)
+ {
+-	dio200_subdev_intr *subpriv;
++	struct dio200_subdev_intr *subpriv;
+ 
+ 	subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
+ 	if (!subpriv) {
+@@ -1000,7 +1000,7 @@ dio200_subdev_intr_init(struct comedi_device * dev, struct comedi_subdevice * s,
+ static void
+ dio200_subdev_intr_cleanup(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	dio200_subdev_intr *subpriv = s->private;
++	struct dio200_subdev_intr *subpriv = s->private;
+ 
+ 	if (subpriv) {
+ 		kfree(subpriv);
+@@ -1249,7 +1249,7 @@ dio200_subdev_8254_init(struct comedi_device * dev, struct comedi_subdevice * s,
+ static void
+ dio200_subdev_8254_cleanup(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	dio200_subdev_intr *subpriv = s->private;
++	struct dio200_subdev_intr *subpriv = s->private;
+ 
+ 	if (subpriv) {
+ 		kfree(subpriv);

commit 93ba42e9093718729291dd6332d92a99f041eb78
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:09:39 2009 -0400
+
+    Staging: comedi: Remove dio200_subdev_8254 typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
+index dad65e40095b..e8faf2b61a05 100644
+--- a/drivers/staging/comedi/drivers/amplc_dio200.c
++++ b/drivers/staging/comedi/drivers/amplc_dio200.c
+@@ -446,7 +446,7 @@ struct dio200_private {
+ 
+ #define devpriv ((struct dio200_private *)dev->private)
+ 
+-typedef struct {
++struct dio200_subdev_8254 {
+ 	unsigned long iobase;	/* Counter base address */
+ 	unsigned long clk_sce_iobase;	/* CLK_SCE base address */
+ 	unsigned long gat_sce_iobase;	/* GAT_SCE base address */
+@@ -454,7 +454,7 @@ typedef struct {
+ 	int has_clk_gat_sce;
+ 	unsigned clock_src[3];	/* Current clock sources */
+ 	unsigned gate_src[3];	/* Current gate sources */
+-} dio200_subdev_8254;
++};
+ 
+ typedef struct {
+ 	unsigned long iobase;
+@@ -1036,7 +1036,7 @@ static int
+ dio200_subdev_8254_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	dio200_subdev_8254 *subpriv = s->private;
++	struct dio200_subdev_8254 *subpriv = s->private;
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+ 	data[0] = i8254_read(subpriv->iobase, 0, chan);
+@@ -1051,7 +1051,7 @@ static int
+ dio200_subdev_8254_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	dio200_subdev_8254 *subpriv = s->private;
++	struct dio200_subdev_8254 *subpriv = s->private;
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+ 	i8254_write(subpriv->iobase, 0, chan, data[0]);
+@@ -1063,7 +1063,7 @@ dio200_subdev_8254_write(struct comedi_device * dev, struct comedi_subdevice * s
+  * Set gate source for an '8254' counter subdevice channel.
+  */
+ static int
+-dio200_set_gate_src(dio200_subdev_8254 * subpriv, unsigned int counter_number,
++dio200_set_gate_src(struct dio200_subdev_8254 * subpriv, unsigned int counter_number,
+ 	unsigned int gate_src)
+ {
+ 	unsigned char byte;
+@@ -1086,7 +1086,7 @@ dio200_set_gate_src(dio200_subdev_8254 * subpriv, unsigned int counter_number,
+  * Get gate source for an '8254' counter subdevice channel.
+  */
+ static int
+-dio200_get_gate_src(dio200_subdev_8254 * subpriv, unsigned int counter_number)
++dio200_get_gate_src(struct dio200_subdev_8254 * subpriv, unsigned int counter_number)
+ {
+ 	if (!subpriv->has_clk_gat_sce)
+ 		return -1;
+@@ -1100,7 +1100,7 @@ dio200_get_gate_src(dio200_subdev_8254 * subpriv, unsigned int counter_number)
+  * Set clock source for an '8254' counter subdevice channel.
+  */
+ static int
+-dio200_set_clock_src(dio200_subdev_8254 * subpriv, unsigned int counter_number,
++dio200_set_clock_src(struct dio200_subdev_8254 * subpriv, unsigned int counter_number,
+ 	unsigned int clock_src)
+ {
+ 	unsigned char byte;
+@@ -1123,7 +1123,7 @@ dio200_set_clock_src(dio200_subdev_8254 * subpriv, unsigned int counter_number,
+  * Get clock source for an '8254' counter subdevice channel.
+  */
+ static int
+-dio200_get_clock_src(dio200_subdev_8254 * subpriv, unsigned int counter_number,
++dio200_get_clock_src(struct dio200_subdev_8254 * subpriv, unsigned int counter_number,
+ 	unsigned int * period_ns)
+ {
+ 	unsigned clock_src;
+@@ -1145,7 +1145,7 @@ static int
+ dio200_subdev_8254_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	dio200_subdev_8254 *subpriv = s->private;
++	struct dio200_subdev_8254 *subpriv = s->private;
+ 	int ret;
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+@@ -1197,7 +1197,7 @@ static int
+ dio200_subdev_8254_init(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned long iobase, unsigned offset, int has_clk_gat_sce)
+ {
+-	dio200_subdev_8254 *subpriv;
++	struct dio200_subdev_8254 *subpriv;
+ 	unsigned int chan;
+ 
+ 	subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);

commit 692560db4187c5c5e906f95c287d75e1b96e4846
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:09:34 2009 -0400
+
+    Staging: comedi: Remove dio200_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
+index 7ad70ae47404..dad65e40095b 100644
+--- a/drivers/staging/comedi/drivers/amplc_dio200.c
++++ b/drivers/staging/comedi/drivers/amplc_dio200.c
+@@ -437,14 +437,14 @@ MODULE_DEVICE_TABLE(pci, dio200_pci_table);
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+    feel free to suggest moving the variable to the struct comedi_device struct.  */
+-typedef struct {
++struct dio200_private {
+ #ifdef CONFIG_COMEDI_PCI
+ 	struct pci_dev *pci_dev;	/* PCI device */
+ #endif
+ 	int intr_sd;
+-} dio200_private;
++};
+ 
+-#define devpriv ((dio200_private *)dev->private)
++#define devpriv ((struct dio200_private *)dev->private)
+ 
+ typedef struct {
+ 	unsigned long iobase;	/* Counter base address */
+@@ -1280,7 +1280,7 @@ static int dio200_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor,
+ 		DIO200_DRIVER_NAME);
+ 
+-	if ((ret = alloc_private(dev, sizeof(dio200_private))) < 0) {
++	if ((ret = alloc_private(dev, sizeof(struct dio200_private))) < 0) {
+ 		printk(KERN_ERR "comedi%d: error! out of memory!\n",
+ 			dev->minor);
+ 		return ret;

commit af105ad3f57421a36dd60c8f54edcebc7a09256b
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:09:29 2009 -0400
+
+    Staging: comedi: Remove dio200_layout typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
+index 2a46e7eb59f6..7ad70ae47404 100644
+--- a/drivers/staging/comedi/drivers/amplc_dio200.c
++++ b/drivers/staging/comedi/drivers/amplc_dio200.c
+@@ -355,15 +355,15 @@ enum dio200_sdtype { sd_none, sd_intr, sd_8255, sd_8254 };
+ #define DIO200_MAX_SUBDEVS	7
+ #define DIO200_MAX_ISNS		6
+ 
+-typedef struct dio200_layout_struct {
++struct dio200_layout_struct {
+ 	unsigned short n_subdevs;	/* number of subdevices */
+ 	unsigned char sdtype[DIO200_MAX_SUBDEVS];	/* enum dio200_sdtype */
+ 	unsigned char sdinfo[DIO200_MAX_SUBDEVS];	/* depends on sdtype */
+ 	char has_int_sce;	/* has interrupt enable/status register */
+ 	char has_clk_gat_sce;	/* has clock/gate selection registers */
+-} dio200_layout;
++};
+ 
+-static const dio200_layout dio200_layouts[] = {
++static const struct dio200_layout_struct dio200_layouts[] = {
+ 	[pc212_layout] = {
+ 	      n_subdevs:6,
+ 	      sdtype:	{sd_8255, sd_8254, sd_8254, sd_8254,
+@@ -1271,7 +1271,7 @@ static int dio200_attach(struct comedi_device * dev, struct comedi_devconfig * i
+ 	struct pci_dev *pci_dev = NULL;
+ 	int bus = 0, slot = 0;
+ #endif
+-	const dio200_layout *layout;
++	const struct dio200_layout_struct *layout;
+ 	int share_irq = 0;
+ 	int sdx;
+ 	unsigned n;
+@@ -1431,7 +1431,7 @@ static int dio200_attach(struct comedi_device * dev, struct comedi_devconfig * i
+  */
+ static int dio200_detach(struct comedi_device * dev)
+ {
+-	const dio200_layout *layout;
++	const struct dio200_layout_struct *layout;
+ 	unsigned n;
+ 
+ 	printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,

commit 3d7a42ef60e93352b49c5da7cba00f20ce255afc
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:09:23 2009 -0400
+
+    Staging: comedi: Remove dio200_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
+index f5f20edddae0..2a46e7eb59f6 100644
+--- a/drivers/staging/comedi/drivers/amplc_dio200.c
++++ b/drivers/staging/comedi/drivers/amplc_dio200.c
+@@ -278,15 +278,15 @@ enum dio200_layout {
+ 	pc272_layout
+ };
+ 
+-typedef struct dio200_board_struct {
++struct dio200_board {
+ 	const char *name;
+ 	unsigned short devid;
+ 	enum dio200_bustype bustype;
+ 	enum dio200_model model;
+ 	enum dio200_layout layout;
+-} dio200_board;
++};
+ 
+-static const dio200_board dio200_boards[] = {
++static const struct dio200_board dio200_boards[] = {
+ 	{
+ 	      name:	"pc212e",
+ 	      bustype:	isa_bustype,
+@@ -431,8 +431,8 @@ MODULE_DEVICE_TABLE(pci, dio200_pci_table);
+ /*
+  * Useful for shorthand access to the particular board structure
+  */
+-#define thisboard ((const dio200_board *)dev->board_ptr)
+-#define thislayout (&dio200_layouts[((dio200_board *)dev->board_ptr)->layout])
++#define thisboard ((const struct dio200_board *)dev->board_ptr)
++#define thislayout (&dio200_layouts[((struct dio200_board *)dev->board_ptr)->layout])
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+@@ -481,8 +481,8 @@ static struct comedi_driver driver_amplc_dio200 = {
+       attach:dio200_attach,
+       detach:dio200_detach,
+       board_name:&dio200_boards[0].name,
+-      offset:sizeof(dio200_board),
+-      num_names:sizeof(dio200_boards) / sizeof(dio200_board),
++      offset:sizeof(struct dio200_board),
++      num_names:sizeof(dio200_boards) / sizeof(struct dio200_board),
+ };
+ 
+ #ifdef CONFIG_COMEDI_PCI

commit 55d996391fa73df06e33609f0d6f82de775d1045
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:09:18 2009 -0400
+
+    Staging: comedi: Remove aio_iiro_16_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c
+index c14069a5e075..9160fdf0ca37 100644
+--- a/drivers/staging/comedi/drivers/aio_iiro_16.c
++++ b/drivers/staging/comedi/drivers/aio_iiro_16.c
+@@ -59,13 +59,13 @@ static const struct aio_iiro_16_board aio_iiro_16_boards[] = {
+ 
+ #define	thisboard	((const struct aio_iiro_16_board *) dev->board_ptr)
+ 
+-typedef struct {
++struct aio_iiro_16_private {
+ 	int data;
+ 	struct pci_dev *pci_dev;
+ 	unsigned int ao_readback[2];
+-} aio_iiro_16_private;
++};
+ 
+-#define	devpriv	((aio_iiro_16_private *) dev->private)
++#define	devpriv	((struct aio_iiro_16_private *) dev->private)
+ 
+ static int aio_iiro_16_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ 
+@@ -105,7 +105,7 @@ static int aio_iiro_16_attach(struct comedi_device * dev, struct comedi_devconfi
+ 
+ 	dev->iobase = iobase;
+ 
+-	if (alloc_private(dev, sizeof(aio_iiro_16_private)) < 0)
++	if (alloc_private(dev, sizeof(struct aio_iiro_16_private)) < 0)
+ 		return -ENOMEM;
+ 
+ 	if (alloc_subdevices(dev, 2) < 0)

commit 28fa7754e5a3fe9f696643808862d37b5ffc3083
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:09:13 2009 -0400
+
+    Staging: comedi: Remove aio_iiro_16_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c
+index f6979eb57a8d..c14069a5e075 100644
+--- a/drivers/staging/comedi/drivers/aio_iiro_16.c
++++ b/drivers/staging/comedi/drivers/aio_iiro_16.c
+@@ -44,20 +44,20 @@ Configuration Options:
+ #define AIO_IIRO_16_RELAY_8_15	0x04
+ #define AIO_IIRO_16_INPUT_8_15	0x05
+ 
+-typedef struct aio_iiro_16_board_struct {
++struct aio_iiro_16_board {
+ 	const char *name;
+ 	int do_;
+ 	int di;
+-} aio_iiro_16_board;
++};
+ 
+-static const aio_iiro_16_board aio_iiro_16_boards[] = {
++static const struct aio_iiro_16_board aio_iiro_16_boards[] = {
+ 	{
+ 	      name:	"aio_iiro_16",
+ 	      di:	16,
+       do_:	16},
+ };
+ 
+-#define	thisboard	((const aio_iiro_16_board *) dev->board_ptr)
++#define	thisboard	((const struct aio_iiro_16_board *) dev->board_ptr)
+ 
+ typedef struct {
+ 	int data;
+@@ -77,8 +77,8 @@ static struct comedi_driver driver_aio_iiro_16 = {
+       attach:aio_iiro_16_attach,
+       detach:aio_iiro_16_detach,
+       board_name:&aio_iiro_16_boards[0].name,
+-      offset:sizeof(aio_iiro_16_board),
+-      num_names:sizeof(aio_iiro_16_boards) / sizeof(aio_iiro_16_board),
++      offset:sizeof(struct aio_iiro_16_board),
++      num_names:sizeof(aio_iiro_16_boards) / sizeof(struct aio_iiro_16_board),
+ };
+ 
+ static int aio_iiro_16_dio_insn_bits_read(struct comedi_device * dev,

commit 4b1d53f061bd3e622ba44c106e083a30a92eb223
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:09:07 2009 -0400
+
+    Staging: comedi: Remove counter_mode_register_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
+index e5ee54332e8a..08666e637e47 100644
+--- a/drivers/staging/comedi/drivers/s526.c
++++ b/drivers/staging/comedi/drivers/s526.c
+@@ -112,7 +112,7 @@ static const int s526_ports[] = {
+ 	REG_EEC
+ };
+ 
+-typedef struct {
++struct counter_mode_register_t {
+ 	unsigned short coutSource:1;
+ 	unsigned short coutPolarity:1;
+ 	unsigned short autoLoadResetRcap:3;
+@@ -124,10 +124,10 @@ typedef struct {
+ 	unsigned short outputRegLatchCtrl:1;
+ 	unsigned short preloadRegSel:1;
+ 	unsigned short reserved:1;
+-} counter_mode_register_t;
++};
+ 
+ union {
+-	counter_mode_register_t reg;
++	struct counter_mode_register_t reg;
+ 	unsigned short value;
+ } cmReg;
+ 

commit 4651db97324b77972309fa22bc441dfbebb5b825
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:09:02 2009 -0400
+
+    Staging: comedi: Remove aio12_8_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c
+index 883dd11c0a15..b97b4d82611b 100644
+--- a/drivers/staging/comedi/drivers/aio_aio12_8.c
++++ b/drivers/staging/comedi/drivers/aio_aio12_8.c
+@@ -82,11 +82,11 @@ static const struct aio12_8_boardtype board_types[] = {
+ 
+ #define	thisboard	((const struct aio12_8_boardtype  *) dev->board_ptr)
+ 
+-typedef struct {
++struct aio12_8_private {
+ 	unsigned int ao_readback[4];
+-} aio12_8_private;
++};
+ 
+-#define devpriv	((aio12_8_private *) dev->private)
++#define devpriv	((struct aio12_8_private *) dev->private)
+ 
+ static int aio_aio12_8_ai_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+@@ -176,7 +176,7 @@ static int aio_aio12_8_attach(struct comedi_device * dev, struct comedi_devconfi
+ 
+ 	dev->iobase = iobase;
+ 
+-	if (alloc_private(dev, sizeof(aio12_8_private)) < 0)
++	if (alloc_private(dev, sizeof(struct aio12_8_private)) < 0)
+ 		return -ENOMEM;
+ 
+ 	if (alloc_subdevices(dev, 3) < 0)

commit 747537121d060557132ac82e7e37cae393e16dcc
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:08:56 2009 -0400
+
+    Staging: comedi: Remove board_type typedef in aio_aio12_8.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c
+index c3e8f99ec4e9..883dd11c0a15 100644
+--- a/drivers/staging/comedi/drivers/aio_aio12_8.c
++++ b/drivers/staging/comedi/drivers/aio_aio12_8.c
+@@ -71,16 +71,16 @@ Configuration Options:
+ 
+ #define DAC_ENABLE			0x18
+ 
+-typedef struct {
++struct aio12_8_boardtype {
+ 	const char *name;
+-} board_type;
++};
+ 
+-static const board_type board_types[] = {
++static const struct aio12_8_boardtype board_types[] = {
+ 	{
+       name:	"aio_aio12_8"},
+ };
+ 
+-#define	thisboard	((const board_type *) dev->board_ptr)
++#define	thisboard	((const struct aio12_8_boardtype  *) dev->board_ptr)
+ 
+ typedef struct {
+ 	unsigned int ao_readback[4];
+@@ -220,7 +220,7 @@ static struct comedi_driver driver_aio_aio12_8 = {
+       detach:aio_aio12_8_detach,
+       board_name:&board_types[0].name,
+       num_names:1,
+-      offset:sizeof(board_type),
++      offset:sizeof(struct aio12_8_boardtype),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_aio_aio12_8);

commit 4cb133565aaf9b04f4fb6af5e5200982258b107c
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:08:51 2009 -0400
+
+    Staging: comedi: Remove pci_dio_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
+index 27f37371a7e9..2604425c3a0f 100644
+--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
++++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
+@@ -328,10 +328,10 @@ static struct comedi_driver driver_pci_dio = {
+       attach:pci_dio_attach,
+       detach:pci_dio_detach
+ };
+-typedef struct pci_dio_private_st pci_dio_private;
+-struct pci_dio_private_st {
+-	pci_dio_private *prev;	/*  previous private struct */
+-	pci_dio_private *next;	/*  next private struct */
++
++struct pci_dio_private {
++	struct pci_dio_private *prev;	/*  previous private struct */
++	struct pci_dio_private *next;	/*  next private struct */
+ 	struct pci_dev *pcidev;	/*  pointer to board's pci_dev */
+ 	char valid;		/*  card is usable */
+ 	char GlobalIrqEnabled;	/*  1= any IRQ source is enabled */
+@@ -349,9 +349,9 @@ struct pci_dio_private_st {
+ 	unsigned short IDIFiltrHigh[8];	/*  IDI's filter value high signal */
+ };
+ 
+-static pci_dio_private *pci_priv = NULL;	/* list of allocated cards */
++static struct pci_dio_private *pci_priv = NULL;	/* list of allocated cards */
+ 
+-#define devpriv ((pci_dio_private *)dev->private)
++#define devpriv ((struct pci_dio_private *)dev->private)
+ #define this_board ((const struct dio_boardtype *)dev->board_ptr)
+ 
+ /*
+@@ -860,7 +860,7 @@ static int pci_dio_add_do(struct comedi_device * dev, struct comedi_subdevice *
+ static int CheckAndAllocCard(struct comedi_device * dev, struct comedi_devconfig * it,
+ 	struct pci_dev *pcidev)
+ {
+-	pci_dio_private *pr, *prev;
++	struct pci_dio_private *pr, *prev;
+ 
+ 	for (pr = pci_priv, prev = NULL; pr != NULL; prev = pr, pr = pr->next) {
+ 		if (pr->pcidev == pcidev) {
+@@ -892,7 +892,7 @@ static int pci_dio_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 
+ 	rt_printk("comedi%d: adv_pci_dio: ", dev->minor);
+ 
+-	if ((ret = alloc_private(dev, sizeof(pci_dio_private))) < 0) {
++	if ((ret = alloc_private(dev, sizeof(struct pci_dio_private))) < 0) {
+ 		rt_printk(", Error: Cann't allocate private memory!\n");
+ 		return -ENOMEM;
+ 	}

commit ba23095c03a8b5efa3427b63b988b396bea2e485
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:08:46 2009 -0400
+
+    Staging: comedi: Remove C99 style comments in adv_pci_dio.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
+index 45b18243a88e..27f37371a7e9 100644
+--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
++++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
+@@ -71,7 +71,7 @@ enum hw_io_access {
+ #define PCIDIO_MAINREG	   2	/* main I/O region for all Advantech cards? */
+ 
+ /* Register offset definitions */
+-// Advantech PCI-1730/3/4
++/*  Advantech PCI-1730/3/4 */
+ #define PCI1730_IDI	   0	/* R:   Isolated digital input  0-15 */
+ #define PCI1730_IDO	   0	/* W:   Isolated digital output 0-15 */
+ #define PCI1730_DI	   2	/* R:   Digital input  0-15 */
+@@ -83,7 +83,7 @@ enum hw_io_access {
+ #define PCI1734_IDO	   0	/* W:   Isolated digital output 0-31 */
+ #define PCI173x_BOARDID	   4	/* R:   Board I/D switch for 1730/3/4 */
+ 
+-// Advantech PCI-1736UP
++/*  Advantech PCI-1736UP */
+ #define PCI1736_IDI        0    /* R:   Isolated digital input  0-15 */
+ #define PCI1736_IDO        0    /* W:   Isolated digital output 0-15 */
+ #define PCI1736_3_INT_EN        0x08    /* R/W: enable/disable interrupts */
+@@ -92,13 +92,13 @@ enum hw_io_access {
+ #define PCI1736_BOARDID    4            /* R:   Board I/D switch for 1736UP */
+ #define PCI1736_MAINREG    0            /* Normal register (2) doesn't work */
+ 
+-// Advantech PCI-1750
++/*  Advantech PCI-1750 */
+ #define PCI1750_IDI	   0	/* R:   Isolated digital input  0-15 */
+ #define PCI1750_IDO	   0	/* W:   Isolated digital output 0-15 */
+ #define PCI1750_ICR	  32	/* W:   Interrupt control register */
+ #define PCI1750_ISR	  32	/* R:   Interrupt status register */
+ 
+-// Advantech PCI-1751/3/3E
++/*  Advantech PCI-1751/3/3E */
+ #define PCI1751_DIO	   0	/* R/W: begin of 8255 registers block */
+ #define PCI1751_ICR	  32	/* W:   Interrupt control register */
+ #define PCI1751_ISR	  32	/* R:   Interrupt status register */
+@@ -113,7 +113,7 @@ enum hw_io_access {
+ #define PCI1753E_ICR2	  50	/* R/W: Interrupt control register group 2 */
+ #define PCI1753E_ICR3	  51	/* R/W: Interrupt control register group 3 */
+ 
+-// Advantech PCI-1752/4/6
++/*  Advantech PCI-1752/4/6 */
+ #define PCI1752_IDO	   0	/* R/W: Digital output  0-31 */
+ #define PCI1752_IDO2	   4	/* R/W: Digital output 32-63 */
+ #define PCI1754_IDI	   0	/* R:   Digital input   0-31 */
+@@ -127,14 +127,14 @@ enum hw_io_access {
+ #define PCI1752_6_CFC	0x12	/* R/W: set/read channel freeze function */
+ #define PCI175x_BOARDID	0x10	/* R:   Board I/D switch for 1752/4/6 */
+ 
+-// Advantech PCI-1762 registers
++/*  Advantech PCI-1762 registers */
+ #define PCI1762_RO	   0	/* R/W: Relays status/output */
+ #define PCI1762_IDI	   2	/* R:   Isolated input status */
+ #define PCI1762_BOARDID	   4	/* R:   Board I/D switch */
+ #define PCI1762_ICR	   6	/* W:   Interrupt control register */
+ #define PCI1762_ISR	   6	/* R:   Interrupt status register */
+ 
+-// Advantech PCI-1760 registers
++/*  Advantech PCI-1760 registers */
+ #define OMB0		0x0c	/* W:   Mailbox outgoing registers */
+ #define OMB1		0x0d
+ #define OMB2		0x0e
+@@ -148,7 +148,7 @@ enum hw_io_access {
+ #define INTCSR2		0x3a
+ #define INTCSR3		0x3b
+ 
+-// PCI-1760 mailbox commands
++/*  PCI-1760 mailbox commands */
+ #define CMD_ClearIMB2		0x00	/* Clear IMB2 status and return actaul DI status in IMB3 */
+ #define CMD_SetRelaysOutput	0x01	/* Set relay output from OMB0 */
+ #define CMD_GetRelaysStatus	0x02	/* Get relay status to IMB0 */
+@@ -187,22 +187,22 @@ static int pci_dio_attach(struct comedi_device * dev, struct comedi_devconfig *
+ static int pci_dio_detach(struct comedi_device * dev);
+ 
+ struct diosubd_data {
+-	int chans;		// num of chans
+-	int addr;		// PCI address ofset
+-	int regs;		// number of registers to read or 8255 subdevices
+-	unsigned int specflags;	// addon subdevice flags
++	int chans;		/*  num of chans */
++	int addr;		/*  PCI address ofset */
++	int regs;		/*  number of registers to read or 8255 subdevices */
++	unsigned int specflags;	/*  addon subdevice flags */
+ };
+ 
+ struct dio_boardtype {
+-	const char *name;	// board name
+-	int vendor_id;		// vendor/device PCI ID
++	const char *name;	/*  board name */
++	int vendor_id;		/*  vendor/device PCI ID */
+ 	int device_id;
+-	int main_pci_region;	// main I/O PCI region
++	int main_pci_region;	/*  main I/O PCI region */
+ 	enum hw_cards_id cardtype;
+-	struct diosubd_data sdi[MAX_DI_SUBDEVS];	// DI chans
+-	struct diosubd_data sdo[MAX_DO_SUBDEVS];	// DO chans
+-	struct diosubd_data sdio[MAX_DIO_SUBDEVG];	// DIO 8255 chans
+-	struct diosubd_data boardid;	// card supports board ID switch
++	struct diosubd_data sdi[MAX_DI_SUBDEVS];	/*  DI chans */
++	struct diosubd_data sdo[MAX_DO_SUBDEVS];	/*  DO chans */
++	struct diosubd_data sdio[MAX_DIO_SUBDEVG];	/*  DIO 8255 chans */
++	struct diosubd_data boardid;	/*  card supports board ID switch */
+ 	enum hw_io_access io_access;
+ };
+ 
+@@ -306,7 +306,7 @@ static const struct dio_boardtype boardtypes[] = {
+ 		IO_16b},
+ 	{"pci1760", PCI_VENDOR_ID_ADVANTECH, 0x1760, 0,
+ 			TYPE_PCI1760,
+-			{{0, 0, 0, 0}, {0, 0, 0, 0}},	// This card have own setup work
++			{{0, 0, 0, 0}, {0, 0, 0, 0}},	/*  This card have own setup work */
+ 			{{0, 0, 0, 0}, {0, 0, 0, 0}},
+ 			{{0, 0, 0, 0}, {0, 0, 0, 0}},
+ 			{0, 0, 0, 0},
+@@ -330,23 +330,23 @@ static struct comedi_driver driver_pci_dio = {
+ };
+ typedef struct pci_dio_private_st pci_dio_private;
+ struct pci_dio_private_st {
+-	pci_dio_private *prev;	// previous private struct
+-	pci_dio_private *next;	// next private struct
+-	struct pci_dev *pcidev;	// pointer to board's pci_dev
+-	char valid;		// card is usable
+-	char GlobalIrqEnabled;	// 1= any IRQ source is enabled
+-	// PCI-1760 specific data
+-	unsigned char IDICntEnable;	// counter's counting enable status
+-	unsigned char IDICntOverEnable;	// counter's overflow interrupts enable status
+-	unsigned char IDICntMatchEnable;	// counter's match interrupts enable status
+-	unsigned char IDICntEdge;	// counter's count edge value (bit=0 - rising, =1 - falling)
+-	unsigned short CntResValue[8];	// counters' reset value
+-	unsigned short CntMatchValue[8];	// counters' match interrupt value
+-	unsigned char IDIFiltersEn;	// IDI's digital filters enable status
+-	unsigned char IDIPatMatchEn;	// IDI's pattern match enable status
+-	unsigned char IDIPatMatchValue;	// IDI's pattern match value
+-	unsigned short IDIFiltrLow[8];	// IDI's filter value low signal
+-	unsigned short IDIFiltrHigh[8];	// IDI's filter value high signal
++	pci_dio_private *prev;	/*  previous private struct */
++	pci_dio_private *next;	/*  next private struct */
++	struct pci_dev *pcidev;	/*  pointer to board's pci_dev */
++	char valid;		/*  card is usable */
++	char GlobalIrqEnabled;	/*  1= any IRQ source is enabled */
++	/*  PCI-1760 specific data */
++	unsigned char IDICntEnable;	/*  counter's counting enable status */
++	unsigned char IDICntOverEnable;	/*  counter's overflow interrupts enable status */
++	unsigned char IDICntMatchEnable;	/*  counter's match interrupts enable status */
++	unsigned char IDICntEdge;	/*  counter's count edge value (bit=0 - rising, =1 - falling) */
++	unsigned short CntResValue[8];	/*  counters' reset value */
++	unsigned short CntMatchValue[8];	/*  counters' match interrupt value */
++	unsigned char IDIFiltersEn;	/*  IDI's digital filters enable status */
++	unsigned char IDIPatMatchEn;	/*  IDI's pattern match enable status */
++	unsigned char IDIPatMatchValue;	/*  IDI's pattern match value */
++	unsigned short IDIFiltrLow[8];	/*  IDI's filter value low signal */
++	unsigned short IDIFiltrHigh[8];	/*  IDI's filter value high signal */
+ };
+ 
+ static pci_dio_private *pci_priv = NULL;	/* list of allocated cards */
+@@ -566,18 +566,18 @@ static int pci1760_insn_cnt_write(struct comedi_device * dev, struct comedi_subd
+ 	};
+ 	unsigned char imb[4];
+ 
+-	if (devpriv->CntResValue[chan] != (data[0] & 0xffff)) {	// Set reset value if different
++	if (devpriv->CntResValue[chan] != (data[0] & 0xffff)) {	/*  Set reset value if different */
+ 		if (!(ret = pci1760_mbxrequest(dev, omb, imb)))
+ 			return ret;
+ 		devpriv->CntResValue[chan] = data[0] & 0xffff;
+ 	}
+ 
+-	omb[0] = bitmask;	// reset counter to it reset value
++	omb[0] = bitmask;	/*  reset counter to it reset value */
+ 	omb[2] = CMD_ResetIDICounters;
+ 	if (!(ret = pci1760_mbxrequest(dev, omb, imb)))
+ 		return ret;
+ 
+-	if (!(bitmask & devpriv->IDICntEnable)) {	// start counter if it don't run
++	if (!(bitmask & devpriv->IDICntEnable)) {	/*  start counter if it don't run */
+ 		omb[0] = bitmask;
+ 		omb[2] = CMD_EnableIDICounters;
+ 		if (!(ret = pci1760_mbxrequest(dev, omb, imb)))
+@@ -596,34 +596,34 @@ static int pci1760_reset(struct comedi_device * dev)
+ 	unsigned char omb[4] = { 0x00, 0x00, 0x00, 0x00 };
+ 	unsigned char imb[4];
+ 
+-	outb(0, dev->iobase + INTCSR0);	// disable IRQ
++	outb(0, dev->iobase + INTCSR0);	/*  disable IRQ */
+ 	outb(0, dev->iobase + INTCSR1);
+ 	outb(0, dev->iobase + INTCSR2);
+ 	outb(0, dev->iobase + INTCSR3);
+ 	devpriv->GlobalIrqEnabled = 0;
+ 
+ 	omb[0] = 0x00;
+-	omb[2] = CMD_SetRelaysOutput;	// reset relay outputs
++	omb[2] = CMD_SetRelaysOutput;	/*  reset relay outputs */
+ 	pci1760_mbxrequest(dev, omb, imb);
+ 
+ 	omb[0] = 0x00;
+-	omb[2] = CMD_EnableIDICounters;	// disable IDI up counters
++	omb[2] = CMD_EnableIDICounters;	/*  disable IDI up counters */
+ 	pci1760_mbxrequest(dev, omb, imb);
+ 	devpriv->IDICntEnable = 0;
+ 
+ 	omb[0] = 0x00;
+-	omb[2] = CMD_OverflowIDICounters;	// disable counters overflow interrupts
++	omb[2] = CMD_OverflowIDICounters;	/*  disable counters overflow interrupts */
+ 	pci1760_mbxrequest(dev, omb, imb);
+ 	devpriv->IDICntOverEnable = 0;
+ 
+ 	omb[0] = 0x00;
+-	omb[2] = CMD_MatchIntIDICounters;	// disable counters match value interrupts
++	omb[2] = CMD_MatchIntIDICounters;	/*  disable counters match value interrupts */
+ 	pci1760_mbxrequest(dev, omb, imb);
+ 	devpriv->IDICntMatchEnable = 0;
+ 
+ 	omb[0] = 0x00;
+ 	omb[1] = 0x80;
+-	for (i = 0; i < 8; i++) {	// set IDI up counters match value
++	for (i = 0; i < 8; i++) {	/*  set IDI up counters match value */
+ 		omb[2] = CMD_SetIDI0CntMatchValue + i;
+ 		pci1760_mbxrequest(dev, omb, imb);
+ 		devpriv->CntMatchValue[i] = 0x8000;
+@@ -631,33 +631,33 @@ static int pci1760_reset(struct comedi_device * dev)
+ 
+ 	omb[0] = 0x00;
+ 	omb[1] = 0x00;
+-	for (i = 0; i < 8; i++) {	// set IDI up counters reset value
++	for (i = 0; i < 8; i++) {	/*  set IDI up counters reset value */
+ 		omb[2] = CMD_SetIDI0CntResetValue + i;
+ 		pci1760_mbxrequest(dev, omb, imb);
+ 		devpriv->CntResValue[i] = 0x0000;
+ 	}
+ 
+ 	omb[0] = 0xff;
+-	omb[2] = CMD_ResetIDICounters;	// reset IDI up counters to reset values
++	omb[2] = CMD_ResetIDICounters;	/*  reset IDI up counters to reset values */
+ 	pci1760_mbxrequest(dev, omb, imb);
+ 
+ 	omb[0] = 0x00;
+-	omb[2] = CMD_EdgeIDICounters;	// set IDI up counters count edge
++	omb[2] = CMD_EdgeIDICounters;	/*  set IDI up counters count edge */
+ 	pci1760_mbxrequest(dev, omb, imb);
+ 	devpriv->IDICntEdge = 0x00;
+ 
+ 	omb[0] = 0x00;
+-	omb[2] = CMD_EnableIDIFilters;	// disable all digital in filters
++	omb[2] = CMD_EnableIDIFilters;	/*  disable all digital in filters */
+ 	pci1760_mbxrequest(dev, omb, imb);
+ 	devpriv->IDIFiltersEn = 0x00;
+ 
+ 	omb[0] = 0x00;
+-	omb[2] = CMD_EnableIDIPatternMatch;	// disable pattern matching
++	omb[2] = CMD_EnableIDIPatternMatch;	/*  disable pattern matching */
+ 	pci1760_mbxrequest(dev, omb, imb);
+ 	devpriv->IDIPatMatchEn = 0x00;
+ 
+ 	omb[0] = 0x00;
+-	omb[2] = CMD_SetIDIPatternMatch;	// set pattern match value
++	omb[2] = CMD_SetIDIPatternMatch;	/*  set pattern match value */
+ 	pci1760_mbxrequest(dev, omb, imb);
+ 	devpriv->IDIPatMatchValue = 0x00;
+ 
+@@ -673,18 +673,18 @@ static int pci_dio_reset(struct comedi_device * dev)
+ 
+ 	switch (this_board->cardtype) {
+ 	case TYPE_PCI1730:
+-		outb(0, dev->iobase + PCI1730_DO);	// clear outputs
++		outb(0, dev->iobase + PCI1730_DO);	/*  clear outputs */
+ 		outb(0, dev->iobase + PCI1730_DO + 1);
+ 		outb(0, dev->iobase + PCI1730_IDO);
+ 		outb(0, dev->iobase + PCI1730_IDO + 1);
+ 		/* NO break there! */
+ 	case TYPE_PCI1733:
+-		outb(0, dev->iobase + PCI1730_3_INT_EN);	// disable interrupts
+-		outb(0x0f, dev->iobase + PCI1730_3_INT_CLR);	// clear interrupts
+-		outb(0, dev->iobase + PCI1730_3_INT_RF);	// set rising edge trigger
++		outb(0, dev->iobase + PCI1730_3_INT_EN);	/*  disable interrupts */
++		outb(0x0f, dev->iobase + PCI1730_3_INT_CLR);	/*  clear interrupts */
++		outb(0, dev->iobase + PCI1730_3_INT_RF);	/*  set rising edge trigger */
+ 		break;
+ 	case TYPE_PCI1734:
+-		outb(0, dev->iobase + PCI1734_IDO);	// clear outputs
++		outb(0, dev->iobase + PCI1734_IDO);	/*  clear outputs */
+ 		outb(0, dev->iobase + PCI1734_IDO + 1);
+ 		outb(0, dev->iobase + PCI1734_IDO + 2);
+ 		outb(0, dev->iobase + PCI1734_IDO + 3);
+@@ -693,52 +693,52 @@ static int pci_dio_reset(struct comedi_device * dev)
+ 	case TYPE_PCI1736:
+ 		outb(0, dev->iobase+PCI1736_IDO);
+ 		outb(0, dev->iobase+PCI1736_IDO+1);
+-		outb(0, dev->iobase+PCI1736_3_INT_EN);  // disable interrupts
+-		outb(0x0f, dev->iobase+PCI1736_3_INT_CLR);// clear interrupts
+-		outb(0, dev->iobase+PCI1736_3_INT_RF);  // set rising edge trigger
++		outb(0, dev->iobase+PCI1736_3_INT_EN);  /*  disable interrupts */
++		outb(0x0f, dev->iobase+PCI1736_3_INT_CLR);/*  clear interrupts */
++		outb(0, dev->iobase+PCI1736_3_INT_RF);  /*  set rising edge trigger */
+ 		break;
+ 
+ 	case TYPE_PCI1750:
+ 	case TYPE_PCI1751:
+-		outb(0x88, dev->iobase + PCI1750_ICR);	// disable & clear interrupts
++		outb(0x88, dev->iobase + PCI1750_ICR);	/*  disable & clear interrupts */
+ 		break;
+ 	case TYPE_PCI1752:
+-		outw(0, dev->iobase + PCI1752_6_CFC);	// disable channel freeze function
+-		outw(0, dev->iobase + PCI1752_IDO);	// clear outputs
++		outw(0, dev->iobase + PCI1752_6_CFC);	/*  disable channel freeze function */
++		outw(0, dev->iobase + PCI1752_IDO);	/*  clear outputs */
+ 		outw(0, dev->iobase + PCI1752_IDO + 2);
+ 		outw(0, dev->iobase + PCI1752_IDO2);
+ 		outw(0, dev->iobase + PCI1752_IDO2 + 2);
+ 		break;
+ 	case TYPE_PCI1753E:
+-		outb(0x88, dev->iobase + PCI1753E_ICR0);	// disable & clear interrupts
++		outb(0x88, dev->iobase + PCI1753E_ICR0);	/*  disable & clear interrupts */
+ 		outb(0x80, dev->iobase + PCI1753E_ICR1);
+ 		outb(0x80, dev->iobase + PCI1753E_ICR2);
+ 		outb(0x80, dev->iobase + PCI1753E_ICR3);
+ 		/* NO break there! */
+ 	case TYPE_PCI1753:
+-		outb(0x88, dev->iobase + PCI1753_ICR0);	// disable & clear interrupts
++		outb(0x88, dev->iobase + PCI1753_ICR0);	/*  disable & clear interrupts */
+ 		outb(0x80, dev->iobase + PCI1753_ICR1);
+ 		outb(0x80, dev->iobase + PCI1753_ICR2);
+ 		outb(0x80, dev->iobase + PCI1753_ICR3);
+ 		break;
+ 	case TYPE_PCI1754:
+-		outw(0x08, dev->iobase + PCI1754_6_ICR0);	// disable and clear interrupts
++		outw(0x08, dev->iobase + PCI1754_6_ICR0);	/*  disable and clear interrupts */
+ 		outw(0x08, dev->iobase + PCI1754_6_ICR1);
+ 		outw(0x08, dev->iobase + PCI1754_ICR2);
+ 		outw(0x08, dev->iobase + PCI1754_ICR3);
+ 		break;
+ 	case TYPE_PCI1756:
+-		outw(0, dev->iobase + PCI1752_6_CFC);	// disable channel freeze function
+-		outw(0x08, dev->iobase + PCI1754_6_ICR0);	// disable and clear interrupts
++		outw(0, dev->iobase + PCI1752_6_CFC);	/*  disable channel freeze function */
++		outw(0x08, dev->iobase + PCI1754_6_ICR0);	/*  disable and clear interrupts */
+ 		outw(0x08, dev->iobase + PCI1754_6_ICR1);
+-		outw(0, dev->iobase + PCI1756_IDO);	// clear outputs
++		outw(0, dev->iobase + PCI1756_IDO);	/*  clear outputs */
+ 		outw(0, dev->iobase + PCI1756_IDO + 2);
+ 		break;
+ 	case TYPE_PCI1760:
+ 		pci1760_reset(dev);
+ 		break;
+ 	case TYPE_PCI1762:
+-		outw(0x0101, dev->iobase + PCI1762_ICR);	// disable & clear interrupts
++		outw(0x0101, dev->iobase + PCI1762_ICR);	/*  disable & clear interrupts */
+ 		break;
+ 	}
+ 
+@@ -782,7 +782,7 @@ static int pci1760_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	s->n_chan = 2;
+ 	s->maxdata = 0xffffffff;
+ 	s->len_chanlist = 2;
+-//      s->insn_config=pci1760_insn_pwm_cfg;
++/*       s->insn_config=pci1760_insn_pwm_cfg; */
+ 	subdev++;
+ 
+ 	s = dev->subdevices + subdev;
+@@ -793,7 +793,7 @@ static int pci1760_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	s->len_chanlist = 8;
+ 	s->insn_read = pci1760_insn_cnt_read;
+ 	s->insn_write = pci1760_insn_cnt_write;
+-//      s->insn_config=pci1760_insn_cnt_cfg;
++/*       s->insn_config=pci1760_insn_cnt_cfg; */
+ 	subdev++;
+ 
+ 	return 0;
+@@ -864,7 +864,7 @@ static int CheckAndAllocCard(struct comedi_device * dev, struct comedi_devconfig
+ 
+ 	for (pr = pci_priv, prev = NULL; pr != NULL; prev = pr, pr = pr->next) {
+ 		if (pr->pcidev == pcidev) {
+-			return 0;	// this card is used, look for another
++			return 0;	/*  this card is used, look for another */
+ 		}
+ 	}
+ 
+@@ -900,15 +900,15 @@ static int pci_dio_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
+ 		pcidev != NULL;
+ 		pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
+-		// loop through cards supported by this driver
++		/*  loop through cards supported by this driver */
+ 		for (i = 0; i < n_boardtypes; ++i) {
+ 			if (boardtypes[i].vendor_id != pcidev->vendor)
+ 				continue;
+ 			if (boardtypes[i].device_id != pcidev->device)
+ 				continue;
+-			// was a particular bus/slot requested?
++			/*  was a particular bus/slot requested? */
+ 			if (it->options[0] || it->options[1]) {
+-				// are we on the wrong bus/slot?
++				/*  are we on the wrong bus/slot? */
+ 				if (pcidev->bus->number != it->options[0] ||
+ 					PCI_SLOT(pcidev->devfn) !=
+ 					it->options[1]) {
+@@ -944,7 +944,7 @@ static int pci_dio_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	dev->board_name = this_board->name;
+ 
+ 	if (this_board->cardtype == TYPE_PCI1760) {
+-		n_subdevices = 4;	// 8 IDI, 8 IDO, 2 PWM, 8 CNT
++		n_subdevices = 4;	/*  8 IDI, 8 IDO, 2 PWM, 8 CNT */
+ 	} else {
+ 		n_subdevices = 0;
+ 		for (i = 0; i < MAX_DI_SUBDEVS; i++)

commit dea1776abaaf9652f1f8e9d69ef7b70ec4cc381a
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:08:40 2009 -0400
+
+    Staging: comedi: Remove boardtype typedef in adv_pci_dio.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
+index 0229734cacb1..45b18243a88e 100644
+--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
++++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
+@@ -193,7 +193,7 @@ struct diosubd_data {
+ 	unsigned int specflags;	// addon subdevice flags
+ };
+ 
+-typedef struct {
++struct dio_boardtype {
+ 	const char *name;	// board name
+ 	int vendor_id;		// vendor/device PCI ID
+ 	int device_id;
+@@ -204,7 +204,7 @@ typedef struct {
+ 	struct diosubd_data sdio[MAX_DIO_SUBDEVG];	// DIO 8255 chans
+ 	struct diosubd_data boardid;	// card supports board ID switch
+ 	enum hw_io_access io_access;
+-} boardtype;
++};
+ 
+ static DEFINE_PCI_DEVICE_TABLE(pci_dio_pci_table) = {
+ 	{PCI_VENDOR_ID_ADVANTECH, 0x1730, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+@@ -224,7 +224,7 @@ static DEFINE_PCI_DEVICE_TABLE(pci_dio_pci_table) = {
+ 
+ MODULE_DEVICE_TABLE(pci, pci_dio_pci_table);
+ 
+-static const boardtype boardtypes[] = {
++static const struct dio_boardtype boardtypes[] = {
+ 	{"pci1730", PCI_VENDOR_ID_ADVANTECH, 0x1730, PCIDIO_MAINREG,
+ 			TYPE_PCI1730,
+ 			{{16, PCI1730_DI, 2, 0}, {16, PCI1730_IDI, 2, 0}},
+@@ -320,7 +320,7 @@ static const boardtype boardtypes[] = {
+ 		IO_16b}
+ };
+ 
+-#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
++#define n_boardtypes (sizeof(boardtypes)/sizeof(struct dio_boardtype))
+ 
+ static struct comedi_driver driver_pci_dio = {
+       driver_name:"adv_pci_dio",
+@@ -352,7 +352,7 @@ struct pci_dio_private_st {
+ static pci_dio_private *pci_priv = NULL;	/* list of allocated cards */
+ 
+ #define devpriv ((pci_dio_private *)dev->private)
+-#define this_board ((const boardtype *)dev->board_ptr)
++#define this_board ((const struct dio_boardtype *)dev->board_ptr)
+ 
+ /*
+ ==============================================================================

commit 673bc56adb5df0e041231493eb75de146c63ac74
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:08:35 2009 -0400
+
+    Staging: comedi: Remove diosubd_data typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
+index e571496e55c3..0229734cacb1 100644
+--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
++++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
+@@ -186,12 +186,12 @@ enum hw_io_access {
+ static int pci_dio_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pci_dio_detach(struct comedi_device * dev);
+ 
+-typedef struct {
++struct diosubd_data {
+ 	int chans;		// num of chans
+ 	int addr;		// PCI address ofset
+ 	int regs;		// number of registers to read or 8255 subdevices
+ 	unsigned int specflags;	// addon subdevice flags
+-} diosubd_data;
++};
+ 
+ typedef struct {
+ 	const char *name;	// board name
+@@ -199,10 +199,10 @@ typedef struct {
+ 	int device_id;
+ 	int main_pci_region;	// main I/O PCI region
+ 	enum hw_cards_id cardtype;
+-	diosubd_data sdi[MAX_DI_SUBDEVS];	// DI chans
+-	diosubd_data sdo[MAX_DO_SUBDEVS];	// DO chans
+-	diosubd_data sdio[MAX_DIO_SUBDEVG];	// DIO 8255 chans
+-	diosubd_data boardid;	// card supports board ID switch
++	struct diosubd_data sdi[MAX_DI_SUBDEVS];	// DI chans
++	struct diosubd_data sdo[MAX_DO_SUBDEVS];	// DO chans
++	struct diosubd_data sdio[MAX_DIO_SUBDEVG];	// DIO 8255 chans
++	struct diosubd_data boardid;	// card supports board ID switch
+ 	enum hw_io_access io_access;
+ } boardtype;
+ 
+@@ -360,7 +360,7 @@ static pci_dio_private *pci_priv = NULL;	/* list of allocated cards */
+ static int pci_dio_insn_bits_di_b(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	const diosubd_data *d = (const diosubd_data *)s->private;
++	const struct diosubd_data *d = (const struct diosubd_data *)s->private;
+ 	int i;
+ 
+ 	data[1] = 0;
+@@ -377,7 +377,7 @@ static int pci_dio_insn_bits_di_b(struct comedi_device * dev, struct comedi_subd
+ static int pci_dio_insn_bits_di_w(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	const diosubd_data *d = (const diosubd_data *)s->private;
++	const struct diosubd_data *d = (const struct diosubd_data *)s->private;
+ 	int i;
+ 
+ 	data[1] = 0;
+@@ -393,7 +393,7 @@ static int pci_dio_insn_bits_di_w(struct comedi_device * dev, struct comedi_subd
+ static int pci_dio_insn_bits_do_b(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	const diosubd_data *d = (const diosubd_data *)s->private;
++	const struct diosubd_data *d = (const struct diosubd_data *)s->private;
+ 	int i;
+ 
+ 	if (data[0]) {
+@@ -414,7 +414,7 @@ static int pci_dio_insn_bits_do_b(struct comedi_device * dev, struct comedi_subd
+ static int pci_dio_insn_bits_do_w(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data)
+ {
+-	const diosubd_data *d = (const diosubd_data *)s->private;
++	const struct diosubd_data *d = (const struct diosubd_data *)s->private;
+ 	int i;
+ 
+ 	if (data[0]) {
+@@ -803,7 +803,7 @@ static int pci1760_attach(struct comedi_device * dev, struct comedi_devconfig *
+ ==============================================================================
+ */
+ static int pci_dio_add_di(struct comedi_device * dev, struct comedi_subdevice * s,
+-	const diosubd_data * d, int subdev)
++	const struct diosubd_data * d, int subdev)
+ {
+ 	s->type = COMEDI_SUBD_DI;
+ 	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON | d->specflags;
+@@ -830,7 +830,7 @@ static int pci_dio_add_di(struct comedi_device * dev, struct comedi_subdevice *
+ ==============================================================================
+ */
+ static int pci_dio_add_do(struct comedi_device * dev, struct comedi_subdevice * s,
+-	const diosubd_data * d, int subdev)
++	const struct diosubd_data * d, int subdev)
+ {
+ 	s->type = COMEDI_SUBD_DO;
+ 	s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;

commit a8f1152e2027ce4987350a6d1d06b3159af80082
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:08:29 2009 -0400
+
+    Staging: comedi: Remove hw_cards_id and hw_io_access typedefs in adv_pci_dio.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
+index 8f920db83d14..e571496e55c3 100644
+--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
++++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
+@@ -45,8 +45,8 @@ Configuration options:
+ #define DPRINTK(fmt, args...)
+ #endif
+ 
+-// hardware types of the cards
+-typedef enum {
++/* hardware types of the cards */
++enum hw_cards_id {
+ 	TYPE_PCI1730, TYPE_PCI1733, TYPE_PCI1734, TYPE_PCI1736,
+ 	TYPE_PCI1750,
+ 	TYPE_PCI1751,
+@@ -55,12 +55,12 @@ typedef enum {
+ 	TYPE_PCI1754, TYPE_PCI1756,
+ 	TYPE_PCI1760,
+ 	TYPE_PCI1762
+-} hw_cards_id;
++};
+ 
+-// which I/O instructions to use
+-typedef enum {
++/* which I/O instructions to use */
++enum hw_io_access {
+ 	IO_8b, IO_16b
+-} hw_io_access;
++};
+ 
+ #define MAX_DI_SUBDEVS	2	/* max number of DI subdevices per card */
+ #define MAX_DO_SUBDEVS	2	/* max number of DO subdevices per card */
+@@ -198,12 +198,12 @@ typedef struct {
+ 	int vendor_id;		// vendor/device PCI ID
+ 	int device_id;
+ 	int main_pci_region;	// main I/O PCI region
+-	hw_cards_id cardtype;	// {enum hw_cards_id_enum}
++	enum hw_cards_id cardtype;
+ 	diosubd_data sdi[MAX_DI_SUBDEVS];	// DI chans
+ 	diosubd_data sdo[MAX_DO_SUBDEVS];	// DO chans
+ 	diosubd_data sdio[MAX_DIO_SUBDEVG];	// DIO 8255 chans
+ 	diosubd_data boardid;	// card supports board ID switch
+-	hw_io_access io_access;	// {enum hw_io_access_enum}
++	enum hw_io_access io_access;
+ } boardtype;
+ 
+ static DEFINE_PCI_DEVICE_TABLE(pci_dio_pci_table) = {

commit 006449f0fe747774438d714dcc4c6193d3a801ea
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:08:24 2009 -0400
+
+    Staging: comedi: Remove boardtype and pci1723_private typedefs in adv_pci1723.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
+index f6492fa3e9a9..81f7ee18c150 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1723.c
++++ b/drivers/staging/comedi/drivers/adv_pci1723.c
+@@ -102,7 +102,7 @@ static const struct comedi_lrange range_pci1723 = { 1, {
+ /*
+  * Board descriptions for pci1723 boards.
+  */
+-typedef struct pci1723_board_struct {
++struct pci1723_board {
+ 	const char *name;
+ 	int vendor_id;		// PCI vendor a device ID of card
+ 	int device_id;
+@@ -112,9 +112,9 @@ typedef struct pci1723_board_struct {
+ 	int n_diochan;		// num of DIO chans
+ 	int ao_maxdata;		// resolution of D/A
+ 	const struct comedi_lrange *rangelist_ao;	// rangelist for D/A
+-} boardtype;
++};
+ 
+-static const boardtype boardtypes[] = {
++static const struct pci1723_board boardtypes[] = {
+ 	{
+ 	      name:	"pci1723",
+ 	      vendor_id:ADVANTECH_VENDOR,
+@@ -146,7 +146,7 @@ MODULE_DEVICE_TABLE(pci, pci1723_pci_table);
+ static int pci1723_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pci1723_detach(struct comedi_device * dev);
+ 
+-#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
++#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pci1723_board))
+ 
+ static struct comedi_driver driver_pci1723 = {
+       driver_name:"adv_pci1723",
+@@ -156,19 +156,19 @@ static struct comedi_driver driver_pci1723 = {
+ };
+ 
+ /* this structure is for data unique to this hardware driver. */
+-typedef struct {
++struct pci1723_private {
+ 	int valid;		//card is usable;
+ 
+ 	struct pci_dev *pcidev;
+ 	unsigned char da_range[8];	// D/A output range for each channel
+ 
+ 	short ao_data[8];	// data output buffer
+-} pci1723_private;
++};
+ 
+ /*the following macro to make it easy to
+ * access the private structure.
+ */
+-#define devpriv ((pci1723_private *)dev->private)
++#define devpriv ((struct pci1723_private *)dev->private)
+ 
+ #define this_board boardtypes
+ 
+@@ -310,7 +310,7 @@ static int pci1723_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	opt_bus = it->options[0];
+ 	opt_slot = it->options[1];
+ 
+-	if ((ret = alloc_private(dev, sizeof(pci1723_private))) < 0) {
++	if ((ret = alloc_private(dev, sizeof(struct pci1723_private))) < 0) {
+ 		rt_printk(" - Allocation failed!\n");
+ 		return -ENOMEM;
+ 	}

commit 6e8131a86d6c1a9896282f572d17c447a85262ad
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:08:19 2009 -0400
+
+    Staging: comedi: Remove pci1710_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
+index 1d392d99a40c..29eac743c8e0 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1710.c
++++ b/drivers/staging/comedi/drivers/adv_pci1710.c
+@@ -266,7 +266,7 @@ static struct comedi_driver driver_pci1710 = {
+ 	.offset = sizeof(struct boardtype),
+ };
+ 
+-typedef struct {
++struct pci1710_private {
+ 	struct pci_dev *pcidev;	// ptr to PCI device
+ 	char valid;		// card is usable
+ 	char neverending_ai;	// we do unlimited AI
+@@ -295,9 +295,9 @@ typedef struct {
+ 	unsigned int ai_timer2;
+ 	short ao_data[4];	// data output buffer
+ 	unsigned int cnt0_write_wait;	// after a write, wait for update of the internal state
+-} pci1710_private;
++};
+ 
+-#define devpriv ((pci1710_private *)dev->private)
++#define devpriv ((struct pci1710_private *)dev->private)
+ #define this_board ((const struct boardtype *)dev->board_ptr)
+ 
+ /*
+@@ -1334,7 +1334,7 @@ static int pci1710_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	opt_bus = it->options[0];
+ 	opt_slot = it->options[1];
+ 
+-	if ((ret = alloc_private(dev, sizeof(pci1710_private))) < 0) {
++	if ((ret = alloc_private(dev, sizeof(struct pci1710_private))) < 0) {
+ 		rt_printk(" - Allocation failed!\n");
+ 		return -ENOMEM;
+ 	}

commit 7875a00b702e62ebafe68cd2abf96570e2d747e5
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:08:13 2009 -0400
+
+    Staging: comedi: Remove boardtype typedef in adv_pci1710.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
+index 934468be44c5..1d392d99a40c 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1710.c
++++ b/drivers/staging/comedi/drivers/adv_pci1710.c
+@@ -185,7 +185,7 @@ static const struct comedi_lrange range_pci171x_da = { 2, {
+ static int pci1710_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pci1710_detach(struct comedi_device * dev);
+ 
+-typedef struct {
++struct boardtype {
+ 	const char *name;	// board name
+ 	int device_id;
+ 	int iorange;		// I/O range len
+@@ -204,7 +204,7 @@ typedef struct {
+ 	const struct comedi_lrange *rangelist_ao;	// rangelist for D/A
+ 	unsigned int ai_ns_min;	// max sample speed of card v ns
+ 	unsigned int fifo_half_size;	// size of FIFO/2
+-} boardtype;
++};
+ 
+ static DEFINE_PCI_DEVICE_TABLE(pci1710_pci_table) = {
+ 	{PCI_VENDOR_ID_ADVANTECH, 0x1710, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+@@ -217,7 +217,7 @@ static DEFINE_PCI_DEVICE_TABLE(pci1710_pci_table) = {
+ 
+ MODULE_DEVICE_TABLE(pci, pci1710_pci_table);
+ 
+-static const boardtype boardtypes[] = {
++static const struct boardtype boardtypes[] = {
+ 	{"pci1710", 0x1710,
+ 		IORANGE_171x, 1, TYPE_PCI171X,
+ 		16, 8, 2, 16, 16, 1, 0x0fff, 0x0fff,
+@@ -254,7 +254,7 @@ static const boardtype boardtypes[] = {
+ 	{.name = DRV_NAME},
+ };
+ 
+-#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
++#define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype))
+ 
+ static struct comedi_driver driver_pci1710 = {
+ 	.driver_name = DRV_NAME,
+@@ -263,7 +263,7 @@ static struct comedi_driver driver_pci1710 = {
+ 	.detach = pci1710_detach,
+ 	.num_names = n_boardtypes,
+ 	.board_name = &boardtypes[0].name,
+-	.offset = sizeof(boardtype),
++	.offset = sizeof(struct boardtype),
+ };
+ 
+ typedef struct {
+@@ -298,7 +298,7 @@ typedef struct {
+ } pci1710_private;
+ 
+ #define devpriv ((pci1710_private *)dev->private)
+-#define this_board ((const boardtype *)dev->board_ptr)
++#define this_board ((const struct boardtype *)dev->board_ptr)
+ 
+ /*
+ ==============================================================================

commit 1ade3157f4ea4e4a090097e2b2b816a627c32a32
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:08:08 2009 -0400
+
+    Staging: comedi: Remove adq12b_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c
+index 242ff78564b0..92f62854d6dc 100644
+--- a/drivers/staging/comedi/drivers/adq12b.c
++++ b/drivers/staging/comedi/drivers/adq12b.c
+@@ -146,15 +146,15 @@ static const struct adq12b_board adq12b_boards[] = {
+ 
+ #define thisboard ((const struct adq12b_board *)dev->board_ptr)
+ 
+-typedef struct{
++struct adq12b_private {
+         int unipolar;          /* option 2 of comedi_config (1 is iobase) */
+         int differential;      /* option 3 of comedi_config */
+         int last_channel;
+         int last_range;
+         unsigned int digital_state;
+- }adq12b_private;
++};
+ 
+-#define devpriv ((adq12b_private *)dev->private)
++#define devpriv ((struct adq12b_private *)dev->private)
+ 
+ /*
+  * The struct comedi_driver structure tells the Comedi core module
+@@ -219,7 +219,7 @@ static int adq12b_attach(struct comedi_device *dev,struct comedi_devconfig *it)
+  * Allocate the private structure area.  alloc_private() is a
+  * convenient macro defined in comedidev.h.
+  */
+-        if(alloc_private(dev, sizeof(adq12b_private)) < 0)
++        if(alloc_private(dev, sizeof(struct adq12b_private)) < 0)
+           return -ENOMEM;
+ 
+ /* fill in devpriv structure */

commit 47c6e95869228a8b464174ee0e85904a92b7baf4
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:08:03 2009 -0400
+
+    Staging: comedi: Remove adq12b_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c
+index d112a64ad119..242ff78564b0 100644
+--- a/drivers/staging/comedi/drivers/adq12b.c
++++ b/drivers/staging/comedi/drivers/adq12b.c
+@@ -116,16 +116,16 @@ static const struct comedi_lrange range_adq12b_ai_unipolar = { 4, {
+ 
+ 
+ 
+-typedef struct adq12b_board_struct{
++struct adq12b_board {
+         const char *name;
+         int ai_se_chans;
+         int ai_diff_chans;
+         int ai_bits;
+         int di_chans;
+         int do_chans;
+-}adq12b_board;
++};
+ 
+-static const adq12b_board adq12b_boards[] = {
++static const struct adq12b_board adq12b_boards[] = {
+         {
+         name:           "adq12b",
+         ai_se_chans:    16,
+@@ -144,7 +144,7 @@ static const adq12b_board adq12b_boards[] = {
+         }*/
+ };
+ 
+-#define thisboard ((const adq12b_board *)dev->board_ptr)
++#define thisboard ((const struct adq12b_board *)dev->board_ptr)
+ 
+ typedef struct{
+         int unipolar;          /* option 2 of comedi_config (1 is iobase) */
+@@ -170,8 +170,8 @@ static struct comedi_driver driver_adq12b={
+         attach:         adq12b_attach,
+         detach:         adq12b_detach,
+         board_name:     &adq12b_boards[0].name,
+-        offset:         sizeof(adq12b_board),
+-        num_names:      sizeof(adq12b_boards) / sizeof(adq12b_board),
++        offset:         sizeof(struct adq12b_board),
++        num_names:      sizeof(adq12b_boards) / sizeof(struct adq12b_board),
+ };
+ 
+ static int adq12b_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data);

commit 5b5fc21b060cc7a2a68ea3f3e145442f589000b6
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:07:57 2009 -0400
+
+    Staging: comedi: Remove pci9118_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
+index ca4d780f0785..278cf30cc4a3 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9118.c
++++ b/drivers/staging/comedi/drivers/adl_pci9118.c
+@@ -241,7 +241,7 @@ static struct comedi_driver driver_pci9118 = {
+ 
+ COMEDI_PCI_INITCLEANUP(driver_pci9118, pci9118_pci_table);
+ 
+-typedef struct {
++struct pci9118_private {
+ 	unsigned long iobase_a;	// base+size for AMCC chip
+ 	unsigned int master;	// master capable
+ 	struct pci_dev *pcidev;	// ptr to actual pcidev
+@@ -299,9 +299,9 @@ typedef struct {
+ 	unsigned int ai_maskerr;	// which warning was printed
+ 	unsigned int ai_maskharderr;	// on which error bits stops
+ 	unsigned int ai_inttrig_start;	// TRIG_INT for start
+-} pci9118_private;
++};
+ 
+-#define devpriv ((pci9118_private *)dev->private)
++#define devpriv ((struct pci9118_private *)dev->private)
+ #define this_board ((struct boardtype *)dev->board_ptr)
+ 
+ /*
+@@ -1859,7 +1859,7 @@ static int pci9118_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 		master = 1;
+ 	}
+ 
+-	if ((ret = alloc_private(dev, sizeof(pci9118_private))) < 0) {
++	if ((ret = alloc_private(dev, sizeof(struct pci9118_private))) < 0) {
+ 		rt_printk(" - Allocation failed!\n");
+ 		return -ENOMEM;
+ 	}

commit 193a21e402f023c786490dacd864b642898976d0
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:07:52 2009 -0400
+
+    Staging: comedi: Remove boardtype typedef in adl_pci9118.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
+index 131498a5b69a..ca4d780f0785 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9118.c
++++ b/drivers/staging/comedi/drivers/adl_pci9118.c
+@@ -181,7 +181,7 @@ static const struct comedi_lrange range_pci9118hg = { 8, {
+ static int pci9118_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pci9118_detach(struct comedi_device * dev);
+ 
+-typedef struct {
++struct boardtype {
+ 	const char *name;	// board name
+ 	int vendor_id;		// PCI vendor a device ID of card
+ 	int device_id;
+@@ -200,7 +200,7 @@ typedef struct {
+ 	unsigned int ai_pacer_min;	// minimal pacer value (c1*c2 or c1 in burst)
+ 	int half_fifo_size;	// size of FIFO/2
+ 
+-} boardtype;
++};
+ 
+ static DEFINE_PCI_DEVICE_TABLE(pci9118_pci_table) = {
+ 	{PCI_VENDOR_ID_AMCC, 0x80d9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+@@ -209,7 +209,7 @@ static DEFINE_PCI_DEVICE_TABLE(pci9118_pci_table) = {
+ 
+ MODULE_DEVICE_TABLE(pci, pci9118_pci_table);
+ 
+-static const boardtype boardtypes[] = {
++static const struct boardtype boardtypes[] = {
+ 	{"pci9118dg", PCI_VENDOR_ID_AMCC, 0x80d9,
+ 			AMCC_OP_REG_SIZE, IORANGE_9118,
+ 			16, 8, 256, PCI9118_CHANLEN, 2, 0x0fff, 0x0fff,
+@@ -227,7 +227,7 @@ static const boardtype boardtypes[] = {
+ 		10000, 40, 512},
+ };
+ 
+-#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
++#define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype))
+ 
+ static struct comedi_driver driver_pci9118 = {
+       driver_name:"adl_pci9118",
+@@ -236,7 +236,7 @@ static struct comedi_driver driver_pci9118 = {
+       detach:pci9118_detach,
+       num_names:n_boardtypes,
+       board_name:&boardtypes[0].name,
+-      offset:sizeof(boardtype),
++      offset:sizeof(struct boardtype),
+ };
+ 
+ COMEDI_PCI_INITCLEANUP(driver_pci9118, pci9118_pci_table);
+@@ -302,7 +302,7 @@ typedef struct {
+ } pci9118_private;
+ 
+ #define devpriv ((pci9118_private *)dev->private)
+-#define this_board ((boardtype *)dev->board_ptr)
++#define this_board ((struct boardtype *)dev->board_ptr)
+ 
+ /*
+ ==============================================================================

commit 52f8ac983079ad6bba3c055152a39ccc5e76350a
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:07:46 2009 -0400
+
+    Staging: comedi: Remove C99 style comments in adl_pci9111.c
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
+index 1e040827fd18..b4a61c560c5b 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9111.c
++++ b/drivers/staging/comedi/drivers/adl_pci9111.c
+@@ -85,7 +85,7 @@ Configuration options:
+ #define PCI9111_DRIVER_NAME 	"adl_pci9111"
+ #define PCI9111_HR_DEVICE_ID 	0x9111
+ 
+-// TODO: Add other pci9111 board id
++/*  TODO: Add other pci9111 board id */
+ 
+ #define PCI9111_IO_RANGE 	0x0100
+ 
+@@ -133,11 +133,11 @@ Configuration options:
+ 
+ /* IO address map */
+ 
+-#define PCI9111_REGISTER_AD_FIFO_VALUE 			0x00	// AD Data stored in FIFO
++#define PCI9111_REGISTER_AD_FIFO_VALUE 			0x00	/*  AD Data stored in FIFO */
+ #define PCI9111_REGISTER_DA_OUTPUT 			0x00
+ #define PCI9111_REGISTER_DIGITAL_IO 			0x02
+ #define PCI9111_REGISTER_EXTENDED_IO_PORTS 		0x04
+-#define PCI9111_REGISTER_AD_CHANNEL_CONTROL 		0x06	// Channel selection
++#define PCI9111_REGISTER_AD_CHANNEL_CONTROL 		0x06	/*  Channel selection */
+ #define PCI9111_REGISTER_AD_CHANNEL_READBACK 		0x06
+ #define PCI9111_REGISTER_INPUT_SIGNAL_RANGE 		0x08
+ #define PCI9111_REGISTER_RANGE_STATUS_READBACK 		0x08
+@@ -261,9 +261,7 @@ Configuration options:
+   outb(data & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_2); \
+   outb( (data >> 8) & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_2)
+ 
+-//
+-// Function prototypes
+-//
++/*  Function prototypes */
+ 
+ static int pci9111_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pci9111_detach(struct comedi_device * dev);
+@@ -284,27 +282,27 @@ static const struct comedi_lrange pci9111_hr_ai_range = {
+ static DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = {
+ 	{PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0,
+ 		0, 0},
+-	//{ PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
++	/* { PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, */
+ 	{0}
+ };
+ 
+ MODULE_DEVICE_TABLE(pci, pci9111_pci_table);
+ 
+-//
+-// Board specification structure
+-//
++/*  */
++/*  Board specification structure */
++/*  */
+ 
+ struct pci9111_board {
+-	const char *name;	// driver name
++	const char *name;	/*  driver name */
+ 	int device_id;
+-	int ai_channel_nbr;	// num of A/D chans
+-	int ao_channel_nbr;	// num of D/A chans
+-	int ai_resolution;	// resolution of A/D
++	int ai_channel_nbr;	/*  num of A/D chans */
++	int ao_channel_nbr;	/*  num of D/A chans */
++	int ai_resolution;	/*  resolution of A/D */
+ 	int ai_resolution_mask;
+-	int ao_resolution;	// resolution of D/A
++	int ao_resolution;	/*  resolution of D/A */
+ 	int ao_resolution_mask;
+-	const struct comedi_lrange *ai_range_list;	// rangelist for A/D
+-	const struct comedi_lrange *ao_range_list;	// rangelist for D/A
++	const struct comedi_lrange *ai_range_list;	/*  rangelist for A/D */
++	const struct comedi_lrange *ao_range_list;	/*  rangelist for D/A */
+ 	unsigned int ai_acquisition_period_min_ns;
+ };
+ 
+@@ -335,15 +333,13 @@ static struct comedi_driver pci9111_driver = {
+ 
+ COMEDI_PCI_INITCLEANUP(pci9111_driver, pci9111_pci_table);
+ 
+-//
+-// Private data structure
+-//
++/*  Private data structure */
+ 
+ struct pci9111_private_data {
+ 	struct pci_dev *pci_device;
+-	unsigned long io_range;	// PCI6503 io range
++	unsigned long io_range;	/*  PCI6503 io range */
+ 
+-	unsigned long lcr_io_base;	// Local configuration register base address
++	unsigned long lcr_io_base;	/*  Local configuration register base address */
+ 	unsigned long lcr_io_range;
+ 
+ 	int stop_counter;
+@@ -354,23 +350,21 @@ struct pci9111_private_data {
+ 	unsigned int chunk_counter;
+ 	unsigned int chunk_num_samples;
+ 
+-	int ao_readback;	// Last written analog output data
++	int ao_readback;	/*  Last written analog output data */
+ 
+-	int timer_divisor_1;	// Divisor values for the 8254 timer pacer
++	int timer_divisor_1;	/*  Divisor values for the 8254 timer pacer */
+ 	int timer_divisor_2;
+ 
+-	int is_valid;		// Is device valid
++	int is_valid;		/*  Is device valid */
+ 
+ 	short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE];
+ };
+ 
+ #define dev_private 	((struct pci9111_private_data *)dev->private)
+ 
+-// ------------------------------------------------------------------
+-//
+-// PLX9050 SECTION
+-//
+-// ------------------------------------------------------------------
++/*  ------------------------------------------------------------------ */
++/*  PLX9050 SECTION */
++/*  ------------------------------------------------------------------ */
+ 
+ #define PLX9050_REGISTER_INTERRUPT_CONTROL 0x4c
+ 
+@@ -405,15 +399,11 @@ static void plx9050_interrupt_control(unsigned long io_base,
+ 	outb(flags, io_base + PLX9050_REGISTER_INTERRUPT_CONTROL);
+ }
+ 
+-// ------------------------------------------------------------------
+-//
+-// MISCELLANEOUS SECTION
+-//
+-// ------------------------------------------------------------------
++/*  ------------------------------------------------------------------ */
++/*  MISCELLANEOUS SECTION */
++/*  ------------------------------------------------------------------ */
+ 
+-//
+-// 8254 timer
+-//
++/*  8254 timer */
+ 
+ static void pci9111_timer_set(struct comedi_device * dev)
+ {
+@@ -494,13 +484,13 @@ enum pci9111_ISC0_sources {
+ 	irq_on_fifo_half_full
+ };
+ 
+-typedef enum {
++enum pci9111_ISC1_sources {
+ 	irq_on_timer_tick,
+ 	irq_on_external_trigger
+-} pci9111_ISC1_sources;
++};
+ 
+ static void pci9111_interrupt_source_set(struct comedi_device * dev,
+-	enum pci9111_ISC0_sources irq_0_source, pci9111_ISC1_sources irq_1_source)
++	enum pci9111_ISC0_sources irq_0_source, enum pci9111_ISC1_sources irq_1_source)
+ {
+ 	int flags;
+ 
+@@ -515,21 +505,17 @@ static void pci9111_interrupt_source_set(struct comedi_device * dev,
+ 	pci9111_interrupt_and_fifo_set(flags);
+ }
+ 
+-// ------------------------------------------------------------------
+-//
+-// HARDWARE TRIGGERED ANALOG INPUT SECTION
+-//
+-// ------------------------------------------------------------------
++/*  ------------------------------------------------------------------ */
++/*  HARDWARE TRIGGERED ANALOG INPUT SECTION */
++/*  ------------------------------------------------------------------ */
+ 
+-//
+-// Cancel analog input autoscan
+-//
++/*  Cancel analog input autoscan */
+ 
+ #undef AI_DO_CMD_DEBUG
+ 
+ static int pci9111_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	// Disable interrupts
++	/*  Disable interrupts */
+ 
+ 	plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
+ 		true, false);
+@@ -547,9 +533,7 @@ static int pci9111_ai_cancel(struct comedi_device * dev, struct comedi_subdevice
+ 	return 0;
+ }
+ 
+-//
+-// Test analog input command
+-//
++/*  Test analog input command */
+ 
+ #define pci9111_check_trigger_src(src,flags) \
+   tmp = src; \
+@@ -566,7 +550,7 @@ pci9111_ai_do_cmd_test(struct comedi_device * dev,
+ 	int i;
+ 	struct pci9111_board *board = (struct pci9111_board *) dev->board_ptr;
+ 
+-	// Step 1 : check if trigger are trivialy valid
++	/*  Step 1 : check if trigger are trivialy valid */
+ 
+ 	pci9111_check_trigger_src(cmd->start_src, TRIG_NOW);
+ 	pci9111_check_trigger_src(cmd->scan_begin_src,
+@@ -578,7 +562,7 @@ pci9111_ai_do_cmd_test(struct comedi_device * dev,
+ 	if (error)
+ 		return 1;
+ 
+-	// step 2 : make sure trigger sources are unique and mutually compatible
++	/*  step 2 : make sure trigger sources are unique and mutually compatible */
+ 
+ 	if (cmd->start_src != TRIG_NOW)
+ 		error++;
+@@ -610,7 +594,7 @@ pci9111_ai_do_cmd_test(struct comedi_device * dev,
+ 	if (error)
+ 		return 2;
+ 
+-	// Step 3 : make sure arguments are trivialy compatible
++	/*  Step 3 : make sure arguments are trivialy compatible */
+ 
+ 	if (cmd->chanlist_len < 1) {
+ 		cmd->chanlist_len = 1;
+@@ -669,7 +653,7 @@ pci9111_ai_do_cmd_test(struct comedi_device * dev,
+ 	if (error)
+ 		return 3;
+ 
+-	// Step 4 : fix up any arguments
++	/*  Step 4 : fix up any arguments */
+ 
+ 	if (cmd->convert_src == TRIG_TIMER) {
+ 		tmp = cmd->convert_arg;
+@@ -680,8 +664,8 @@ pci9111_ai_do_cmd_test(struct comedi_device * dev,
+ 		if (tmp != cmd->convert_arg)
+ 			error++;
+ 	}
+-	// There's only one timer on this card, so the scan_begin timer must
+-	// be a multiple of chanlist_len*convert_arg
++	/*  There's only one timer on this card, so the scan_begin timer must */
++	/*  be a multiple of chanlist_len*convert_arg */
+ 
+ 	if (cmd->scan_begin_src == TRIG_TIMER) {
+ 
+@@ -710,7 +694,7 @@ pci9111_ai_do_cmd_test(struct comedi_device * dev,
+ 	if (error)
+ 		return 4;
+ 
+-	// Step 5 : check channel list
++	/*  Step 5 : check channel list */
+ 
+ 	if (cmd->chanlist) {
+ 
+@@ -754,9 +738,7 @@ pci9111_ai_do_cmd_test(struct comedi_device * dev,
+ 
+ }
+ 
+-//
+-// Analog input command
+-//
++/*  Analog input command */
+ 
+ static int pci9111_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * subdevice)
+ {
+@@ -767,12 +749,9 @@ static int pci9111_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice
+ 			"no irq assigned for PCI9111, cannot do hardware conversion");
+ 		return -1;
+ 	}
+-	// Set channel scan limit
+-	//
+-	// PCI9111 allows only scanning from channel 0 to channel n
+-	//
+-	// TODO: handle the case of an external multiplexer
+-	//
++	/*  Set channel scan limit */
++	/*  PCI9111 allows only scanning from channel 0 to channel n */
++	/*  TODO: handle the case of an external multiplexer */
+ 
+ 	if (async_cmd->chanlist_len > 1) {
+ 		pci9111_ai_channel_set((async_cmd->chanlist_len) - 1);
+@@ -782,10 +761,8 @@ static int pci9111_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice
+ 		pci9111_autoscan_set(dev, false);
+ 	}
+ 
+-	// Set gain
+-	//
+-	// This is the same gain on every channel
+-	//
++	/*  Set gain */
++	/*  This is the same gain on every channel */
+ 
+ 	pci9111_ai_range_set(CR_RANGE(async_cmd->chanlist[0]));
+ 
+@@ -808,7 +785,7 @@ static int pci9111_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice
+ 		return -1;
+ 	}
+ 
+-	// Set timer pacer
++	/*  Set timer pacer */
+ 
+ 	dev_private->scan_delay = 0;
+ 	switch (async_cmd->convert_src) {
+@@ -901,11 +878,9 @@ static void pci9111_ai_munge(struct comedi_device * dev, struct comedi_subdevice
+ 	}
+ }
+ 
+-// ------------------------------------------------------------------
+-//
+-// INTERRUPT SECTION
+-//
+-// ------------------------------------------------------------------
++/*  ------------------------------------------------------------------ */
++/*  INTERRUPT SECTION */
++/*  ------------------------------------------------------------------ */
+ 
+ #undef INTERRUPT_DEBUG
+ 
+@@ -918,8 +893,8 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device PT_REGS_ARG)
+ 	unsigned char intcsr;
+ 
+ 	if (!dev->attached) {
+-		// Ignore interrupt before device fully attached.
+-		// Might not even have allocated subdevices yet!
++		/*  Ignore interrupt before device fully attached. */
++		/*  Might not even have allocated subdevices yet! */
+ 		return IRQ_NONE;
+ 	}
+ 
+@@ -927,7 +902,7 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device PT_REGS_ARG)
+ 
+ 	comedi_spin_lock_irqsave(&dev->spinlock, irq_flags);
+ 
+-	// Check if we are source of interrupt
++	/*  Check if we are source of interrupt */
+ 	intcsr = inb(dev_private->lcr_io_base +
+ 		PLX9050_REGISTER_INTERRUPT_CONTROL);
+ 	if (!(((intcsr & PLX9050_PCI_INTERRUPT_ENABLE) != 0)
+@@ -941,15 +916,15 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device PT_REGS_ARG)
+ 					==
+ 					(PLX9050_LINTI2_ENABLE |
+ 						PLX9050_LINTI2_STATUS))))) {
+-		// Not the source of the interrupt.
+-		// (N.B. not using PLX9050_SOFTWARE_INTERRUPT)
++		/*  Not the source of the interrupt. */
++		/*  (N.B. not using PLX9050_SOFTWARE_INTERRUPT) */
+ 		comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags);
+ 		return IRQ_NONE;
+ 	}
+ 
+ 	if ((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) ==
+ 		(PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) {
+-		// Interrupt comes from fifo_half-full signal
++		/*  Interrupt comes from fifo_half-full signal */
+ 
+ 		if (pci9111_is_fifo_full()) {
+ 			comedi_spin_unlock_irqrestore(&dev->spinlock,
+@@ -1059,15 +1034,11 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-// ------------------------------------------------------------------
+-//
+-// INSTANT ANALOG INPUT OUTPUT SECTION
+-//
+-// ------------------------------------------------------------------
++/*  ------------------------------------------------------------------ */
++/*  INSTANT ANALOG INPUT OUTPUT SECTION */
++/*  ------------------------------------------------------------------ */
+ 
+-//
+-// analog instant input
+-//
++/*  analog instant input */
+ 
+ #undef AI_INSN_DEBUG
+ 
+@@ -1126,9 +1097,7 @@ static int pci9111_ai_insn_read(struct comedi_device * dev,
+ 	return i;
+ }
+ 
+-//
+-// Analog instant output
+-//
++/*  Analog instant output */
+ 
+ static int
+ pci9111_ao_insn_write(struct comedi_device * dev,
+@@ -1144,9 +1113,7 @@ pci9111_ao_insn_write(struct comedi_device * dev,
+ 	return i;
+ }
+ 
+-//
+-// Analog output readback
+-//
++/*  Analog output readback */
+ 
+ static int pci9111_ao_insn_read(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+@@ -1160,15 +1127,11 @@ static int pci9111_ao_insn_read(struct comedi_device * dev,
+ 	return i;
+ }
+ 
+-// ------------------------------------------------------------------
+-//
+-// DIGITAL INPUT OUTPUT SECTION
+-//
+-// ------------------------------------------------------------------
++/*  ------------------------------------------------------------------ */
++/*  DIGITAL INPUT OUTPUT SECTION */
++/*  ------------------------------------------------------------------ */
+ 
+-//
+-// Digital inputs
+-//
++/*  Digital inputs */
+ 
+ static int pci9111_di_insn_bits(struct comedi_device * dev,
+ 	struct comedi_subdevice * subdevice, struct comedi_insn * insn, unsigned int * data)
+@@ -1181,18 +1144,16 @@ static int pci9111_di_insn_bits(struct comedi_device * dev,
+ 	return 2;
+ }
+ 
+-//
+-// Digital outputs
+-//
++/*  Digital outputs */
+ 
+ static int pci9111_do_insn_bits(struct comedi_device * dev,
+ 	struct comedi_subdevice * subdevice, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bits;
+ 
+-	// Only set bits that have been masked
+-	// data[0] = mask
+-	// data[1] = bit state
++	/*  Only set bits that have been masked */
++	/*  data[0] = mask */
++	/*  data[1] = bit state */
+ 
+ 	data[0] &= PCI9111_DO_MASK;
+ 
+@@ -1208,19 +1169,15 @@ static int pci9111_do_insn_bits(struct comedi_device * dev,
+ 	return 2;
+ }
+ 
+-// ------------------------------------------------------------------
+-//
+-// INITIALISATION SECTION
+-//
+-// ------------------------------------------------------------------
++/*  ------------------------------------------------------------------ */
++/*  INITIALISATION SECTION */
++/*  ------------------------------------------------------------------ */
+ 
+-//
+-// Reset device
+-//
++/*  Reset device */
+ 
+ static int pci9111_reset(struct comedi_device * dev)
+ {
+-	// Set trigger source to software
++	/*  Set trigger source to software */
+ 
+ 	plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
+ 		true, false);
+@@ -1229,7 +1186,7 @@ static int pci9111_reset(struct comedi_device * dev)
+ 	pci9111_pretrigger_set(dev, false);
+ 	pci9111_autoscan_set(dev, false);
+ 
+-	// Reset 8254 chip
++	/*  Reset 8254 chip */
+ 
+ 	dev_private->timer_divisor_1 = 0;
+ 	dev_private->timer_divisor_2 = 0;
+@@ -1239,12 +1196,9 @@ static int pci9111_reset(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-//
+-// Attach
+-//
+-//      - Register PCI device
+-//      - Declare device driver capability
+-//
++/*  Attach */
++/*       - Register PCI device */
++/*       - Declare device driver capability */
+ 
+ static int pci9111_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+@@ -1257,9 +1211,7 @@ static int pci9111_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	if (alloc_private(dev, sizeof(struct pci9111_private_data)) < 0) {
+ 		return -ENOMEM;
+ 	}
+-	//
+-	// Probe the device to determine what device in the series it is.
+-	//
++	/*  Probe the device to determine what device in the series it is. */
+ 
+ 	printk("comedi%d: " PCI9111_DRIVER_NAME " driver\n", dev->minor);
+ 
+@@ -1271,10 +1223,10 @@ static int pci9111_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 			for (i = 0; i < pci9111_board_nbr; i++) {
+ 				if (pci9111_boards[i].device_id ==
+ 					pci_device->device) {
+-					// was a particular bus/slot requested?
++					/*  was a particular bus/slot requested? */
+ 					if ((it->options[0] != 0)
+ 						|| (it->options[1] != 0)) {
+-						// are we on the wrong bus/slot?
++						/*  are we on the wrong bus/slot? */
+ 						if (pci_device->bus->number !=
+ 							it->options[0]
+ 							|| PCI_SLOT(pci_device->
+@@ -1307,24 +1259,24 @@ static int pci9111_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 		PCI_SLOT(pci_device->devfn),
+ 		PCI_FUNC(pci_device->devfn), pci_device->irq);
+ 
+-	// TODO: Warn about non-tested boards.
++	/*  TODO: Warn about non-tested boards. */
+ 
+ 	switch (board->device_id) {
+ 	};
+ 
+-	// Read local configuration register base address [PCI_BASE_ADDRESS #1].
++	/*  Read local configuration register base address [PCI_BASE_ADDRESS #1]. */
+ 
+ 	lcr_io_base = pci_resource_start(pci_device, 1);
+ 	lcr_io_range = pci_resource_len(pci_device, 1);
+ 
+ 	printk("comedi%d: local configuration registers at address 0x%4lx [0x%4lx]\n", dev->minor, lcr_io_base, lcr_io_range);
+ 
+-	// Enable PCI device and request regions
++	/*  Enable PCI device and request regions */
+ 	if (comedi_pci_enable(pci_device, PCI9111_DRIVER_NAME) < 0) {
+ 		printk("comedi%d: Failed to enable PCI device and request regions\n", dev->minor);
+ 		return -EIO;
+ 	}
+-	// Read PCI6308 register base address [PCI_BASE_ADDRESS #2].
++	/*  Read PCI6308 register base address [PCI_BASE_ADDRESS #2]. */
+ 
+ 	io_base = pci_resource_start(pci_device, 2);
+ 	io_range = pci_resource_len(pci_device, 2);
+@@ -1341,7 +1293,7 @@ static int pci9111_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 
+ 	pci9111_reset(dev);
+ 
+-	// Irq setup
++	/*  Irq setup */
+ 
+ 	dev->irq = 0;
+ 	if (pci_device->irq > 0) {
+@@ -1355,9 +1307,7 @@ static int pci9111_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	}
+ 	dev->irq = pci_device->irq;
+ 
+-	//
+-	// TODO: Add external multiplexer setup (according to option[2]).
+-	//
++	/*  TODO: Add external multiplexer setup (according to option[2]). */
+ 
+ 	if ((error = alloc_subdevices(dev, 4)) < 0)
+ 		return error;
+@@ -1368,12 +1318,9 @@ static int pci9111_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	subdevice->type = COMEDI_SUBD_AI;
+ 	subdevice->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ;
+ 
+-	//
+-	// TODO: Add external multiplexer data
+-	//
+-	//    if (devpriv->usemux) { subdevice->n_chan = devpriv->usemux; }
+-	//    else { subdevice->n_chan = this_board->n_aichan; }
+-	//
++	/*  TODO: Add external multiplexer data */
++	/*     if (devpriv->usemux) { subdevice->n_chan = devpriv->usemux; } */
++	/*     else { subdevice->n_chan = this_board->n_aichan; } */
+ 
+ 	subdevice->n_chan = board->ai_channel_nbr;
+ 	subdevice->maxdata = board->ai_resolution_mask;
+@@ -1416,20 +1363,18 @@ static int pci9111_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	return 0;
+ }
+ 
+-//
+-// Detach
+-//
++/*  Detach */
+ 
+ static int pci9111_detach(struct comedi_device * dev)
+ {
+-	// Reset device
++	/*  Reset device */
+ 
+ 	if (dev->private != 0) {
+ 		if (dev_private->is_valid)
+ 			pci9111_reset(dev);
+ 
+ 	}
+-	// Release previously allocated irq
++	/*  Release previously allocated irq */
+ 
+ 	if (dev->irq != 0) {
+ 		comedi_free_irq(dev->irq, dev);

commit 3ba97b3c6258cb67450e0873584489f97d0debc5
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:07:41 2009 -0400
+
+    Staging: comedi: Remove pci9111_ISC0_sources typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
+index c5f7471a6b8b..1e040827fd18 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9111.c
++++ b/drivers/staging/comedi/drivers/adl_pci9111.c
+@@ -489,10 +489,10 @@ static void pci9111_autoscan_set(struct comedi_device * dev, bool autoscan)
+ 	pci9111_trigger_and_autoscan_set(flags);
+ }
+ 
+-typedef enum {
++enum pci9111_ISC0_sources {
+ 	irq_on_eoc,
+ 	irq_on_fifo_half_full
+-} pci9111_ISC0_sources;
++};
+ 
+ typedef enum {
+ 	irq_on_timer_tick,
+@@ -500,7 +500,7 @@ typedef enum {
+ } pci9111_ISC1_sources;
+ 
+ static void pci9111_interrupt_source_set(struct comedi_device * dev,
+-	pci9111_ISC0_sources irq_0_source, pci9111_ISC1_sources irq_1_source)
++	enum pci9111_ISC0_sources irq_0_source, pci9111_ISC1_sources irq_1_source)
+ {
+ 	int flags;
+ 

commit 655f78f6aaa059ad262bc55e1c3575724c14867b
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:07:36 2009 -0400
+
+    Staging: comedi: Remove pci9111_trigger_sources typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
+index 601676139538..c5f7471a6b8b 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9111.c
++++ b/drivers/staging/comedi/drivers/adl_pci9111.c
+@@ -435,14 +435,14 @@ static void pci9111_timer_set(struct comedi_device * dev)
+ 	pci9111_8254_counter_1_set(dev_private->timer_divisor_1);
+ }
+ 
+-typedef enum {
++enum pci9111_trigger_sources {
+ 	software,
+ 	timer_pacer,
+ 	external
+-} pci9111_trigger_sources;
++};
+ 
+ static void pci9111_trigger_source_set(struct comedi_device * dev,
+-	pci9111_trigger_sources source)
++	enum pci9111_trigger_sources source)
+ {
+ 	int flags;
+ 

commit c350fa1944f4ec1fe392ce0f3fc879f3899bb15d
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:07:30 2009 -0400
+
+    Staging: comedi: Remove pci9111_private_data typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
+index babb777c9701..601676139538 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9111.c
++++ b/drivers/staging/comedi/drivers/adl_pci9111.c
+@@ -339,7 +339,7 @@ COMEDI_PCI_INITCLEANUP(pci9111_driver, pci9111_pci_table);
+ // Private data structure
+ //
+ 
+-typedef struct {
++struct pci9111_private_data {
+ 	struct pci_dev *pci_device;
+ 	unsigned long io_range;	// PCI6503 io range
+ 
+@@ -362,9 +362,9 @@ typedef struct {
+ 	int is_valid;		// Is device valid
+ 
+ 	short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE];
+-} pci9111_private_data_struct;
++};
+ 
+-#define dev_private 	((pci9111_private_data_struct *)dev->private)
++#define dev_private 	((struct pci9111_private_data *)dev->private)
+ 
+ // ------------------------------------------------------------------
+ //
+@@ -1254,7 +1254,7 @@ static int pci9111_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	int error, i;
+ 	const struct pci9111_board *board;
+ 
+-	if (alloc_private(dev, sizeof(pci9111_private_data_struct)) < 0) {
++	if (alloc_private(dev, sizeof(struct pci9111_private_data)) < 0) {
+ 		return -ENOMEM;
+ 	}
+ 	//

commit 940579fbae1a3a8967fe619562c8e78080dd873d
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:07:25 2009 -0400
+
+    Staging: comedi: Remove pci9111_board_struct typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
+index cce2c8303137..babb777c9701 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9111.c
++++ b/drivers/staging/comedi/drivers/adl_pci9111.c
+@@ -294,7 +294,7 @@ MODULE_DEVICE_TABLE(pci, pci9111_pci_table);
+ // Board specification structure
+ //
+ 
+-typedef struct {
++struct pci9111_board {
+ 	const char *name;	// driver name
+ 	int device_id;
+ 	int ai_channel_nbr;	// num of A/D chans
+@@ -306,9 +306,9 @@ typedef struct {
+ 	const struct comedi_lrange *ai_range_list;	// rangelist for A/D
+ 	const struct comedi_lrange *ao_range_list;	// rangelist for D/A
+ 	unsigned int ai_acquisition_period_min_ns;
+-} pci9111_board_struct;
++};
+ 
+-static const pci9111_board_struct pci9111_boards[] = {
++static const struct pci9111_board pci9111_boards[] = {
+ 	{
+ 	      name:	"pci9111_hr",
+ 	      device_id:PCI9111_HR_DEVICE_ID,
+@@ -324,7 +324,7 @@ static const pci9111_board_struct pci9111_boards[] = {
+ };
+ 
+ #define pci9111_board_nbr \
+-  (sizeof(pci9111_boards)/sizeof(pci9111_board_struct))
++  (sizeof(pci9111_boards)/sizeof(struct pci9111_board))
+ 
+ static struct comedi_driver pci9111_driver = {
+       driver_name:PCI9111_DRIVER_NAME,
+@@ -564,7 +564,7 @@ pci9111_ai_do_cmd_test(struct comedi_device * dev,
+ 	int error = 0;
+ 	int range, reference;
+ 	int i;
+-	pci9111_board_struct *board = (pci9111_board_struct *) dev->board_ptr;
++	struct pci9111_board *board = (struct pci9111_board *) dev->board_ptr;
+ 
+ 	// Step 1 : check if trigger are trivialy valid
+ 
+@@ -887,7 +887,7 @@ static void pci9111_ai_munge(struct comedi_device * dev, struct comedi_subdevice
+ 	unsigned int i, num_samples = num_bytes / sizeof(short);
+ 	short *array = data;
+ 	int resolution =
+-		((pci9111_board_struct *) dev->board_ptr)->ai_resolution;
++		((struct pci9111_board *) dev->board_ptr)->ai_resolution;
+ 
+ 	for (i = 0; i < num_samples; i++) {
+ 		if (resolution == PCI9111_HR_AI_RESOLUTION)
+@@ -1075,7 +1075,7 @@ static int pci9111_ai_insn_read(struct comedi_device * dev,
+ 	struct comedi_subdevice * subdevice, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int resolution =
+-		((pci9111_board_struct *) dev->board_ptr)->ai_resolution;
++		((struct pci9111_board *) dev->board_ptr)->ai_resolution;
+ 
+ 	int timeout, i;
+ 
+@@ -1252,7 +1252,7 @@ static int pci9111_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 	unsigned long io_base, io_range, lcr_io_base, lcr_io_range;
+ 	struct pci_dev *pci_device;
+ 	int error, i;
+-	const pci9111_board_struct *board;
++	const struct pci9111_board *board;
+ 
+ 	if (alloc_private(dev, sizeof(pci9111_private_data_struct)) < 0) {
+ 		return -ENOMEM;
+@@ -1285,7 +1285,7 @@ static int pci9111_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 					}
+ 
+ 					dev->board_ptr = pci9111_boards + i;
+-					board = (pci9111_board_struct *) dev->
++					board = (struct pci9111_board *) dev->
+ 						board_ptr;
+ 					dev_private->pci_device = pci_device;
+ 					goto found;

commit 07b666b72b122958ec125715bd4b07557c6cb889
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:07:19 2009 -0400
+
+    Staging: comedi: Remove adl_pci8164_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c
+index c401e110770c..adf90be79983 100644
+--- a/drivers/staging/comedi/drivers/adl_pci8164.c
++++ b/drivers/staging/comedi/drivers/adl_pci8164.c
+@@ -63,12 +63,12 @@ static DEFINE_PCI_DEVICE_TABLE(adl_pci8164_pci_table) = {
+ 
+ MODULE_DEVICE_TABLE(pci, adl_pci8164_pci_table);
+ 
+-typedef struct {
++struct adl_pci8164_private {
+ 	int data;
+ 	struct pci_dev *pci_dev;
+-} adl_pci8164_private;
++};
+ 
+-#define devpriv ((adl_pci8164_private *)dev->private)
++#define devpriv ((struct adl_pci8164_private *)dev->private)
+ 
+ static int adl_pci8164_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int adl_pci8164_detach(struct comedi_device * dev);
+@@ -116,7 +116,7 @@ static int adl_pci8164_attach(struct comedi_device * dev, struct comedi_devconfi
+ 	bus = it->options[0];
+ 	slot = it->options[1];
+ 
+-	if (alloc_private(dev, sizeof(adl_pci8164_private)) < 0)
++	if (alloc_private(dev, sizeof(struct adl_pci8164_private)) < 0)
+ 		return -ENOMEM;
+ 
+ 	if (alloc_subdevices(dev, 4) < 0)

commit ddc3dbf4dfd38b309c4c26b2fa91e3784457a0f8
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:07:14 2009 -0400
+
+    Staging: comedi: Remove adl_pci7432_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adl_pci7432.c b/drivers/staging/comedi/drivers/adl_pci7432.c
+index 8fdea81b59fc..a8f1715608d1 100644
+--- a/drivers/staging/comedi/drivers/adl_pci7432.c
++++ b/drivers/staging/comedi/drivers/adl_pci7432.c
+@@ -51,12 +51,12 @@ static DEFINE_PCI_DEVICE_TABLE(adl_pci7432_pci_table) = {
+ 
+ MODULE_DEVICE_TABLE(pci, adl_pci7432_pci_table);
+ 
+-typedef struct {
++struct adl_pci7432_private {
+ 	int data;
+ 	struct pci_dev *pci_dev;
+-} adl_pci7432_private;
++};
+ 
+-#define devpriv ((adl_pci7432_private *)dev->private)
++#define devpriv ((struct adl_pci7432_private *)dev->private)
+ 
+ static int adl_pci7432_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int adl_pci7432_detach(struct comedi_device * dev);
+@@ -90,7 +90,7 @@ static int adl_pci7432_attach(struct comedi_device * dev, struct comedi_devconfi
+ 	bus = it->options[0];
+ 	slot = it->options[1];
+ 
+-	if (alloc_private(dev, sizeof(adl_pci7432_private)) < 0)
++	if (alloc_private(dev, sizeof(struct adl_pci7432_private)) < 0)
+ 		return -ENOMEM;
+ 
+ 	if (alloc_subdevices(dev, 2) < 0)

commit 8dca707e148ed7c25a5d9fc37a831e5fc56776fa
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:07:09 2009 -0400
+
+    Staging: comedi: Remove adl_pci7296_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adl_pci7296.c b/drivers/staging/comedi/drivers/adl_pci7296.c
+index 7fe4ce14fcf3..bd0f9ab226ef 100644
+--- a/drivers/staging/comedi/drivers/adl_pci7296.c
++++ b/drivers/staging/comedi/drivers/adl_pci7296.c
+@@ -56,12 +56,13 @@ static DEFINE_PCI_DEVICE_TABLE(adl_pci7296_pci_table) = {
+ 
+ MODULE_DEVICE_TABLE(pci, adl_pci7296_pci_table);
+ 
+-typedef struct {
++struct adl_pci7296_private {
+ 	int data;
+ 	struct pci_dev *pci_dev;
+-} adl_pci7296_private;
++};
++
+ 
+-#define devpriv ((adl_pci7296_private *)dev->private)
++#define devpriv ((struct adl_pci7296_private *)dev->private)
+ 
+ static int adl_pci7296_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int adl_pci7296_detach(struct comedi_device * dev);
+@@ -86,7 +87,7 @@ static int adl_pci7296_attach(struct comedi_device * dev, struct comedi_devconfi
+ 	bus = it->options[0];
+ 	slot = it->options[1];
+ 
+-	if (alloc_private(dev, sizeof(adl_pci7296_private)) < 0)
++	if (alloc_private(dev, sizeof(struct adl_pci7296_private)) < 0)
+ 		return -ENOMEM;
+ 
+ 	if (alloc_subdevices(dev, 4) < 0)

commit 3d393c865b745a37a53081203b49278476a47a56
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:07:03 2009 -0400
+
+    Staging: comedi: Remove pci6208_private typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c
+index 449cf87c477c..f710f551820d 100644
+--- a/drivers/staging/comedi/drivers/adl_pci6208.c
++++ b/drivers/staging/comedi/drivers/adl_pci6208.c
+@@ -99,13 +99,13 @@ MODULE_DEVICE_TABLE(pci, pci6208_pci_table);
+ /* Will be initialized in pci6208_find device(). */
+ #define thisboard ((const struct pci6208_board *)dev->board_ptr)
+ 
+-typedef struct {
++struct pci6208_private {
+ 	int data;
+ 	struct pci_dev *pci_dev;	/* for a PCI device */
+ 	unsigned int ao_readback[2];	/* Used for AO readback */
+-} pci6208_private;
++};
+ 
+-#define devpriv ((pci6208_private *)dev->private)
++#define devpriv ((struct pci6208_private *)dev->private)
+ 
+ static int pci6208_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pci6208_detach(struct comedi_device * dev);
+@@ -151,7 +151,7 @@ static int pci6208_attach(struct comedi_device * dev, struct comedi_devconfig *
+ 
+ 	printk("comedi%d: pci6208: ", dev->minor);
+ 
+-	retval = alloc_private(dev, sizeof(pci6208_private));
++	retval = alloc_private(dev, sizeof(struct pci6208_private));
+ 	if (retval < 0)
+ 		return retval;
+ 

commit c1b31c44a38e2b5153193680e4bee4856b3307e1
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:06:58 2009 -0400
+
+    Staging: comedi: Remove pci6208_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c
+index fa290ba4690f..449cf87c477c 100644
+--- a/drivers/staging/comedi/drivers/adl_pci6208.c
++++ b/drivers/staging/comedi/drivers/adl_pci6208.c
+@@ -57,13 +57,14 @@ Configuration Options:
+ #define PCI6208_DRIVER_NAME 	"adl_pci6208"
+ 
+ /* Board descriptions */
+-typedef struct {
++struct pci6208_board {
+ 	const char *name;
+ 	unsigned short dev_id;	/* `lspci` will show you this */
+ 	int ao_chans;
+ 	//int ao_bits;
+-} pci6208_board;
+-static const pci6208_board pci6208_boards[] = {
++};
++
++static const struct pci6208_board pci6208_boards[] = {
+ 	/*{
+ 	   name :  "pci6208v",
+ 	   dev_id       :  0x6208,      //not sure
+@@ -96,7 +97,7 @@ static DEFINE_PCI_DEVICE_TABLE(pci6208_pci_table) = {
+ MODULE_DEVICE_TABLE(pci, pci6208_pci_table);
+ 
+ /* Will be initialized in pci6208_find device(). */
+-#define thisboard ((const pci6208_board *)dev->board_ptr)
++#define thisboard ((const struct pci6208_board *)dev->board_ptr)
+ 
+ typedef struct {
+ 	int data;
+@@ -110,7 +111,7 @@ static int pci6208_attach(struct comedi_device * dev, struct comedi_devconfig *
+ static int pci6208_detach(struct comedi_device * dev);
+ 
+ #define pci6208_board_nbr \
+-	(sizeof(pci6208_boards) / sizeof(pci6208_board))
++	(sizeof(pci6208_boards) / sizeof(struct pci6208_board))
+ 
+ static struct comedi_driver driver_pci6208 = {
+       driver_name:PCI6208_DRIVER_NAME,

commit 4753d235e76b14c9f4585d569795a4ccb51485f8
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:06:47 2009 -0400
+
+    Staging: comedi: Remove DMABUF typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
+index 3e6f1f0d99e5..30dec9dab19b 100644
+--- a/drivers/staging/comedi/drivers/s626.c
++++ b/drivers/staging/comedi/drivers/s626.c
+@@ -144,8 +144,8 @@ struct s626_private {
+ 	uint16_t CounterIntEnabs;
+ 	/* Counter interrupt enable  mask for MISC2 register. */
+ 	uint8_t AdcItems;	/* Number of items in ADC poll  list. */
+-	DMABUF RPSBuf;		/* DMA buffer used to hold ADC (RPS1) program. */
+-	DMABUF ANABuf;
++	struct bufferDMA RPSBuf;		/* DMA buffer used to hold ADC (RPS1) program. */
++	struct bufferDMA ANABuf;
+ 	/* DMA buffer used to receive ADC data and hold DAC data. */
+ 	uint32_t *pDacWBuf;
+ 	/* Pointer to logical adrs of DMA buffer used to hold DAC  data. */
+@@ -275,7 +275,7 @@ static uint16_t DEBIread(struct comedi_device *dev, uint16_t addr);
+ static void DEBIwrite(struct comedi_device *dev, uint16_t addr, uint16_t wdata);
+ static void DEBIreplace(struct comedi_device *dev, uint16_t addr, uint16_t mask,
+ 	uint16_t wdata);
+-static void CloseDMAB(struct comedi_device *dev, DMABUF *pdma, size_t bsize);
++static void CloseDMAB(struct comedi_device *dev, struct bufferDMA *pdma, size_t bsize);
+ 
+ /*  COUNTER OBJECT ------------------------------------------------ */
+ struct enc_private {
+@@ -2733,7 +2733,7 @@ static void DEBIreplace(struct comedi_device *dev, uint16_t addr, uint16_t mask,
+ 	DEBItransfer(dev);	/*  Execute the DEBI Write transfer. */
+ }
+ 
+-static void CloseDMAB(struct comedi_device *dev, DMABUF *pdma, size_t bsize)
++static void CloseDMAB(struct comedi_device *dev, struct bufferDMA *pdma, size_t bsize)
+ {
+ 	void *vbptr;
+ 	dma_addr_t vpptr;
+diff --git a/drivers/staging/comedi/drivers/s626.h b/drivers/staging/comedi/drivers/s626.h
+index c48957be2e1c..891126f25099 100644
+--- a/drivers/staging/comedi/drivers/s626.h
++++ b/drivers/staging/comedi/drivers/s626.h
+@@ -739,8 +739,8 @@
+ /*   unsigned int enc; */
+ /* }CallCounter; */
+ 
+-typedef struct bufferDMA {
++struct bufferDMA {
+ 	dma_addr_t PhysicalBase;
+ 	void *LogicalBase;
+ 	uint32_t DMAHandle;
+-} DMABUF;
++};

commit 9aa5339ac1eba5268df69bbcdf1abb9fae5afeca
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:06:42 2009 -0400
+
+    Staging: comedi: Remove comedi_bufinfo typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
+index 17c014922b7f..e6b5f16edb02 100644
+--- a/drivers/staging/comedi/comedi.h
++++ b/drivers/staging/comedi/comedi.h
+@@ -305,13 +305,11 @@ enum comedi_support_level {
+ #define COMEDI_INSNLIST _IOR(CIO, 11, struct comedi_insnlist)
+ #define COMEDI_INSN _IOR(CIO, 12, struct comedi_insn)
+ #define COMEDI_BUFCONFIG _IOR(CIO, 13, struct comedi_bufconfig)
+-#define COMEDI_BUFINFO _IOWR(CIO, 14, comedi_bufinfo)
++#define COMEDI_BUFINFO _IOWR(CIO, 14, struct comedi_bufinfo)
+ #define COMEDI_POLL _IO(CIO, 15)
+ 
+ /* structures */
+ 
+-typedef struct comedi_bufinfo_struct comedi_bufinfo;
+-
+ struct comedi_trig {
+ 	unsigned int subdev;	/* subdevice */
+ 	unsigned int mode;	/* mode */
+@@ -426,7 +424,7 @@ struct comedi_bufconfig {
+ 	unsigned int unused[4];
+ };
+ 
+-struct comedi_bufinfo_struct {
++struct comedi_bufinfo {
+ 	unsigned int subdevice;
+ 	unsigned int bytes_read;
+ 
+diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
+index 5cb6031656bb..19dce2ebfc19 100644
+--- a/drivers/staging/comedi/comedi_fops.c
++++ b/drivers/staging/comedi/comedi_fops.c
+@@ -556,11 +556,11 @@ static int do_chaninfo_ioctl(struct comedi_device *dev, struct comedi_chaninfo *
+   */
+ static int do_bufinfo_ioctl(struct comedi_device *dev, void *arg)
+ {
+-	comedi_bufinfo bi;
++	struct comedi_bufinfo bi;
+ 	struct comedi_subdevice *s;
+ 	struct comedi_async *async;
+ 
+-	if (copy_from_user(&bi, arg, sizeof(comedi_bufinfo)))
++	if (copy_from_user(&bi, arg, sizeof(struct comedi_bufinfo)))
+ 		return -EFAULT;
+ 
+ 	if (bi.subdevice >= dev->n_subdevices || bi.subdevice < 0)
+@@ -601,7 +601,7 @@ static int do_bufinfo_ioctl(struct comedi_device *dev, void *arg)
+ 	bi.buf_read_ptr = async->buf_read_ptr;
+ 
+ copyback:
+-	if (copy_to_user(arg, &bi, sizeof(comedi_bufinfo)))
++	if (copy_to_user(arg, &bi, sizeof(struct comedi_bufinfo)))
+ 		return -EFAULT;
+ 
+ 	return 0;

commit be6aba4a423629126f318d351b2d0eb00abb9dd5
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:06:37 2009 -0400
+
+    Staging: comedi: Remove comedi_bufconfig typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
+index 079cb6e80c7e..17c014922b7f 100644
+--- a/drivers/staging/comedi/comedi.h
++++ b/drivers/staging/comedi/comedi.h
+@@ -304,13 +304,12 @@ enum comedi_support_level {
+ #define COMEDI_CMDTEST _IOR(CIO, 10, struct comedi_cmd)
+ #define COMEDI_INSNLIST _IOR(CIO, 11, struct comedi_insnlist)
+ #define COMEDI_INSN _IOR(CIO, 12, struct comedi_insn)
+-#define COMEDI_BUFCONFIG _IOR(CIO, 13, comedi_bufconfig)
++#define COMEDI_BUFCONFIG _IOR(CIO, 13, struct comedi_bufconfig)
+ #define COMEDI_BUFINFO _IOWR(CIO, 14, comedi_bufinfo)
+ #define COMEDI_POLL _IO(CIO, 15)
+ 
+ /* structures */
+ 
+-typedef struct comedi_bufconfig_struct comedi_bufconfig;
+ typedef struct comedi_bufinfo_struct comedi_bufinfo;
+ 
+ struct comedi_trig {
+@@ -417,7 +416,7 @@ struct comedi_devconfig {
+ 	int options[COMEDI_NDEVCONFOPTS];
+ };
+ 
+-struct comedi_bufconfig_struct {
++struct comedi_bufconfig {
+ 	unsigned int subdevice;
+ 	unsigned int flags;
+ 
+diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
+index 0e9ad62c6ec9..5cb6031656bb 100644
+--- a/drivers/staging/comedi/comedi_fops.c
++++ b/drivers/staging/comedi/comedi_fops.c
+@@ -274,12 +274,12 @@ static int do_devconfig_ioctl(struct comedi_device *dev, struct comedi_devconfig
+ */
+ static int do_bufconfig_ioctl(struct comedi_device *dev, void *arg)
+ {
+-	comedi_bufconfig bc;
++	struct comedi_bufconfig bc;
+ 	struct comedi_async *async;
+ 	struct comedi_subdevice *s;
+ 	int ret = 0;
+ 
+-	if (copy_from_user(&bc, arg, sizeof(comedi_bufconfig)))
++	if (copy_from_user(&bc, arg, sizeof(struct comedi_bufconfig)))
+ 		return -EFAULT;
+ 
+ 	if (bc.subdevice >= dev->n_subdevices || bc.subdevice < 0)
+@@ -340,7 +340,7 @@ static int do_bufconfig_ioctl(struct comedi_device *dev, void *arg)
+ 	bc.maximum_size = async->max_bufsize;
+ 
+ copyback:
+-	if (copy_to_user(arg, &bc, sizeof(comedi_bufconfig)))
++	if (copy_to_user(arg, &bc, sizeof(struct comedi_bufconfig)))
+ 		return -EFAULT;
+ 
+ 	return 0;

commit 1f6325d629ce03501e8927480495685828561f26
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:06:31 2009 -0400
+
+    Staging: comedi: Remove comedi_krange typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
+index 82298faac2c3..079cb6e80c7e 100644
+--- a/drivers/staging/comedi/comedi.h
++++ b/drivers/staging/comedi/comedi.h
+@@ -310,7 +310,6 @@ enum comedi_support_level {
+ 
+ /* structures */
+ 
+-typedef struct comedi_krange_struct comedi_krange;
+ typedef struct comedi_bufconfig_struct comedi_bufconfig;
+ typedef struct comedi_bufinfo_struct comedi_bufinfo;
+ 
+@@ -382,7 +381,7 @@ struct comedi_rangeinfo {
+ 	void *range_ptr;
+ };
+ 
+-struct comedi_krange_struct {
++struct comedi_krange {
+ 	int min;	/* fixed point, multiply by 1e-6 */
+ 	int max;	/* fixed point, multiply by 1e-6 */
+ 	unsigned int flags;
+diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
+index 15e457a0cd9e..ea319360ae68 100644
+--- a/drivers/staging/comedi/comedidev.h
++++ b/drivers/staging/comedi/comedidev.h
+@@ -409,7 +409,7 @@ extern const struct comedi_lrange range_unknown;
+ 
+ struct comedi_lrange {
+ 	int length;
+-	comedi_krange range[GCC_ZERO_LENGTH_ARRAY];
++	struct comedi_krange range[GCC_ZERO_LENGTH_ARRAY];
+ };
+ 
+ /* some silly little inline functions */
+diff --git a/drivers/staging/comedi/comedilib.h b/drivers/staging/comedi/comedilib.h
+index f27ef837c3d2..c2729312d57e 100644
+--- a/drivers/staging/comedi/comedilib.h
++++ b/drivers/staging/comedi/comedilib.h
+@@ -103,7 +103,7 @@ int comedi_get_rangetype(void *dev, unsigned int subdevice,
+ unsigned int comedi_get_subdevice_flags(void *dev, unsigned int subdevice);
+ int comedi_get_len_chanlist(void *dev, unsigned int subdevice);
+ int comedi_get_krange(void *dev, unsigned int subdevice, unsigned int
+-	chan, unsigned int range, comedi_krange *krange);
++	chan, unsigned int range, struct comedi_krange *krange);
+ unsigned int comedi_get_buf_head_pos(void *dev, unsigned int subdevice);
+ int comedi_set_user_int_count(void *dev, unsigned int subdevice,
+ 	unsigned int buf_user_count);
+@@ -177,7 +177,7 @@ unsigned int comedi_get_subdevice_flags(unsigned int minor, unsigned int
+ 	subdevice);
+ int comedi_get_len_chanlist(unsigned int minor, unsigned int subdevice);
+ int comedi_get_krange(unsigned int minor, unsigned int subdevice, unsigned int
+-	chan, unsigned int range, comedi_krange *krange);
++	chan, unsigned int range, struct comedi_krange *krange);
+ unsigned int comedi_get_buf_head_pos(unsigned int minor, unsigned int
+ 	subdevice);
+ int comedi_set_user_int_count(unsigned int minor, unsigned int subdevice,
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
+index b6fc5c119701..707e3ccc9d72 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
+@@ -1203,7 +1203,7 @@ COMEDI_PCI_INITCLEANUP(driver_cb_pcidas, pcidas64_pci_table);
+ static unsigned int ai_range_bits_6xxx(const struct comedi_device * dev,
+ 	unsigned int range_index)
+ {
+-	const comedi_krange *range =
++	const struct comedi_krange *range =
+ 		&board(dev)->ai_range_table->range[range_index];
+ 	unsigned int bits = 0;
+ 
+diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c
+index a31817b12629..e679328a4f8f 100644
+--- a/drivers/staging/comedi/drivers/comedi_test.c
++++ b/drivers/staging/comedi/drivers/comedi_test.c
+@@ -442,7 +442,7 @@ static short fake_sawtooth(struct comedi_device *dev, unsigned int range_index,
+ 	struct comedi_subdevice *s = dev->read_subdev;
+ 	unsigned int offset = s->maxdata / 2;
+ 	u64 value;
+-	const comedi_krange *krange = &s->range_table->range[range_index];
++	const struct comedi_krange *krange = &s->range_table->range[range_index];
+ 	u64 binary_amplitude;
+ 
+ 	binary_amplitude = s->maxdata;
+@@ -463,7 +463,7 @@ static short fake_squarewave(struct comedi_device *dev, unsigned int range_index
+ 	struct comedi_subdevice *s = dev->read_subdev;
+ 	unsigned int offset = s->maxdata / 2;
+ 	u64 value;
+-	const comedi_krange *krange = &s->range_table->range[range_index];
++	const struct comedi_krange *krange = &s->range_table->range[range_index];
+ 	current_time %= devpriv->usec_period;
+ 
+ 	value = s->maxdata;
+diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
+index b959ba8e29fb..0219c32e853c 100644
+--- a/drivers/staging/comedi/drivers/das16.c
++++ b/drivers/staging/comedi/drivers/das16.c
+@@ -1375,7 +1375,7 @@ static int das16_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 	unsigned int dma_chan;
+ 	int timer_mode;
+ 	unsigned long flags;
+-	comedi_krange *user_ai_range, *user_ao_range;
++	struct comedi_krange *user_ai_range, *user_ao_range;
+ 
+ 	iobase = it->options[0];
+ #if 0
+@@ -1496,7 +1496,7 @@ static int das16_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 		(it->options[4] || it->options[5])) {
+ 		// allocate single-range range table
+ 		devpriv->user_ai_range_table =
+-			kmalloc(sizeof(struct comedi_lrange) + sizeof(comedi_krange),
++			kmalloc(sizeof(struct comedi_lrange) + sizeof(struct comedi_krange),
+ 			GFP_KERNEL);
+ 		// initialize ai range
+ 		devpriv->user_ai_range_table->length = 1;
+@@ -1509,7 +1509,7 @@ static int das16_attach(struct comedi_device * dev, struct comedi_devconfig * it
+ 	if (it->options[6] || it->options[7]) {
+ 		// allocate single-range range table
+ 		devpriv->user_ao_range_table =
+-			kmalloc(sizeof(struct comedi_lrange) + sizeof(comedi_krange),
++			kmalloc(sizeof(struct comedi_lrange) + sizeof(struct comedi_krange),
+ 			GFP_KERNEL);
+ 		// initialize ao range
+ 		devpriv->user_ao_range_table->length = 1;
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
+index 8f481b545643..bb0e499d8b83 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -156,7 +156,7 @@ typedef struct {
+ 	int model_no;
+ 	struct {
+ 		int length;
+-		comedi_krange range;
++		struct comedi_krange range;
+ 	} range[9];
+ 	const struct comedi_lrange *range_table_list[8 * 7 + 2];
+ 	unsigned int maxdata_list[8 * 7 + 2];
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index ce8c704565d2..542bd0dcd44d 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -2818,7 +2818,7 @@ static int ni_m_series_ao_config_chanlist(struct comedi_device * dev,
+ 		}
+ 	}
+ 	for (i = 0; i < n_chans; i++) {
+-		const comedi_krange *krange;
++		const struct comedi_krange *krange;
+ 		chan = CR_CHAN(chanspec[i]);
+ 		range = CR_RANGE(chanspec[i]);
+ 		krange = s->range_table->range + range;
+diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
+index ca41baa37645..96430d2955b1 100644
+--- a/drivers/staging/comedi/drivers/serial2002.c
++++ b/drivers/staging/comedi/drivers/serial2002.c
+@@ -63,7 +63,7 @@ static const serial2002_board serial2002_boards[] = {
+ typedef struct {
+ 	// HACK...
+ 	int length;
+-	comedi_krange range;
++	struct comedi_krange range;
+ } serial2002_range_table_t;
+ 
+ typedef struct {
+diff --git a/drivers/staging/comedi/kcomedilib/get.c b/drivers/staging/comedi/kcomedilib/get.c
+index a7d4ff638444..b6b726a69f14 100644
+--- a/drivers/staging/comedi/kcomedilib/get.c
++++ b/drivers/staging/comedi/kcomedilib/get.c
+@@ -149,7 +149,7 @@ int comedi_get_n_ranges(void *d, unsigned int subdevice, unsigned int chan)
+  * ALPHA (non-portable)
+ */
+ int comedi_get_krange(void *d, unsigned int subdevice, unsigned int chan,
+-	unsigned int range, comedi_krange *krange)
++	unsigned int range, struct comedi_krange *krange)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+ 	struct comedi_subdevice *s = dev->subdevices + subdevice;
+@@ -163,7 +163,7 @@ int comedi_get_krange(void *d, unsigned int subdevice, unsigned int chan,
+ 	if (range >= lr->length)
+ 		return -EINVAL;
+ 
+-	memcpy(krange, lr->range + range, sizeof(comedi_krange));
++	memcpy(krange, lr->range + range, sizeof(struct comedi_krange));
+ 
+ 	return 0;
+ }
+diff --git a/drivers/staging/comedi/range.c b/drivers/staging/comedi/range.c
+index 3778873cd5e7..ac200d929f35 100644
+--- a/drivers/staging/comedi/range.c
++++ b/drivers/staging/comedi/range.c
+@@ -42,7 +42,7 @@ const struct comedi_lrange range_unknown = { 1, {{0, 1000000, UNIT_none}} };
+ 		range info structure
+ 
+ 	writes:
+-		n comedi_krange structures to rangeinfo->range_ptr
++		n struct comedi_krange structures to rangeinfo->range_ptr
+ */
+ int do_rangeinfo_ioctl(struct comedi_device *dev, struct comedi_rangeinfo *arg)
+ {
+@@ -78,7 +78,7 @@ int do_rangeinfo_ioctl(struct comedi_device *dev, struct comedi_rangeinfo *arg)
+ 	}
+ 
+ 	if (copy_to_user(it.range_ptr, lr->range,
+-			sizeof(comedi_krange) * lr->length))
++			sizeof(struct comedi_krange) * lr->length))
+ 		return -EFAULT;
+ 
+ 	return 0;

commit d0a353f637593ce8b0e08848cc7c871b766cb4ee
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:06:26 2009 -0400
+
+    Staging: comedi: Remove comedi_rangeinfo typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
+index fe7f1c4a4450..82298faac2c3 100644
+--- a/drivers/staging/comedi/comedi.h
++++ b/drivers/staging/comedi/comedi.h
+@@ -299,7 +299,7 @@ enum comedi_support_level {
+ #define COMEDI_LOCK _IO(CIO, 5)
+ #define COMEDI_UNLOCK _IO(CIO, 6)
+ #define COMEDI_CANCEL _IO(CIO, 7)
+-#define COMEDI_RANGEINFO _IOR(CIO, 8, comedi_rangeinfo)
++#define COMEDI_RANGEINFO _IOR(CIO, 8, struct comedi_rangeinfo)
+ #define COMEDI_CMD _IOR(CIO, 9, struct comedi_cmd)
+ #define COMEDI_CMDTEST _IOR(CIO, 10, struct comedi_cmd)
+ #define COMEDI_INSNLIST _IOR(CIO, 11, struct comedi_insnlist)
+@@ -310,7 +310,6 @@ enum comedi_support_level {
+ 
+ /* structures */
+ 
+-typedef struct comedi_rangeinfo_struct comedi_rangeinfo;
+ typedef struct comedi_krange_struct comedi_krange;
+ typedef struct comedi_bufconfig_struct comedi_bufconfig;
+ typedef struct comedi_bufinfo_struct comedi_bufinfo;
+@@ -378,7 +377,7 @@ struct comedi_chaninfo {
+ 	unsigned int unused[4];
+ };
+ 
+-struct comedi_rangeinfo_struct {
++struct comedi_rangeinfo {
+ 	unsigned int range_type;
+ 	void *range_ptr;
+ };
+diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c
+index f3cedb528e49..2fa771e4c127 100644
+--- a/drivers/staging/comedi/comedi_compat32.c
++++ b/drivers/staging/comedi/comedi_compat32.c
+@@ -158,7 +158,7 @@ static int compat_chaninfo(struct file *file, unsigned long arg)
+ /* Handle 32-bit COMEDI_RANGEINFO ioctl. */
+ static int compat_rangeinfo(struct file *file, unsigned long arg)
+ {
+-	comedi_rangeinfo __user *rangeinfo;
++	struct comedi_rangeinfo __user *rangeinfo;
+ 	struct comedi32_rangeinfo_struct __user *rangeinfo32;
+ 	int err;
+ 	union {
+diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
+index e6a3005e19de..15e457a0cd9e 100644
+--- a/drivers/staging/comedi/comedidev.h
++++ b/drivers/staging/comedi/comedidev.h
+@@ -375,7 +375,7 @@ enum subdevice_runflags {
+    various internal comedi functions
+  */
+ 
+-int do_rangeinfo_ioctl(struct comedi_device *dev, comedi_rangeinfo *arg);
++int do_rangeinfo_ioctl(struct comedi_device *dev, struct comedi_rangeinfo *arg);
+ int check_chanlist(struct comedi_subdevice *s, int n, unsigned int *chanlist);
+ void comedi_set_subdevice_runflags(struct comedi_subdevice *s, unsigned mask,
+ 	unsigned bits);
+diff --git a/drivers/staging/comedi/range.c b/drivers/staging/comedi/range.c
+index ef7ad56174bf..3778873cd5e7 100644
+--- a/drivers/staging/comedi/range.c
++++ b/drivers/staging/comedi/range.c
+@@ -44,14 +44,14 @@ const struct comedi_lrange range_unknown = { 1, {{0, 1000000, UNIT_none}} };
+ 	writes:
+ 		n comedi_krange structures to rangeinfo->range_ptr
+ */
+-int do_rangeinfo_ioctl(struct comedi_device *dev, comedi_rangeinfo *arg)
++int do_rangeinfo_ioctl(struct comedi_device *dev, struct comedi_rangeinfo *arg)
+ {
+-	comedi_rangeinfo it;
++	struct comedi_rangeinfo it;
+ 	int subd, chan;
+ 	const struct comedi_lrange *lr;
+ 	struct comedi_subdevice *s;
+ 
+-	if (copy_from_user(&it, arg, sizeof(comedi_rangeinfo)))
++	if (copy_from_user(&it, arg, sizeof(struct comedi_rangeinfo)))
+ 		return -EFAULT;
+ 	subd = (it.range_type >> 24) & 0xf;
+ 	chan = (it.range_type >> 16) & 0xff;

commit 0707bb04be89b18ee83b5a997e36cc585f0b988d
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:06:20 2009 -0400
+
+    Staging: comedi: Remove comedi_devconfig typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
+index 8ed6f96442cf..fe7f1c4a4450 100644
+--- a/drivers/staging/comedi/comedi.h
++++ b/drivers/staging/comedi/comedi.h
+@@ -291,7 +291,7 @@ enum comedi_support_level {
+ /* ioctls */
+ 
+ #define CIO 'd'
+-#define COMEDI_DEVCONFIG _IOW(CIO, 0, comedi_devconfig)
++#define COMEDI_DEVCONFIG _IOW(CIO, 0, struct comedi_devconfig)
+ #define COMEDI_DEVINFO _IOR(CIO, 1, struct comedi_devinfo)
+ #define COMEDI_SUBDINFO _IOR(CIO, 2, struct comedi_subdinfo)
+ #define COMEDI_CHANINFO _IOR(CIO, 3, struct comedi_chaninfo)
+@@ -310,7 +310,6 @@ enum comedi_support_level {
+ 
+ /* structures */
+ 
+-typedef struct comedi_devconfig_struct comedi_devconfig;
+ typedef struct comedi_rangeinfo_struct comedi_rangeinfo;
+ typedef struct comedi_krange_struct comedi_krange;
+ typedef struct comedi_bufconfig_struct comedi_bufconfig;
+@@ -415,7 +414,7 @@ struct comedi_devinfo {
+ 	int unused[30];
+ };
+ 
+-struct comedi_devconfig_struct {
++struct comedi_devconfig {
+ 	char board_name[COMEDI_NAMELEN];
+ 	int options[COMEDI_NDEVCONFOPTS];
+ };
+diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
+index 2d99a4e33b58..0e9ad62c6ec9 100644
+--- a/drivers/staging/comedi/comedi_fops.c
++++ b/drivers/staging/comedi/comedi_fops.c
+@@ -69,7 +69,7 @@ static DEFINE_SPINLOCK(comedi_file_info_table_lock);
+ static struct comedi_device_file_info
+     *comedi_file_info_table[COMEDI_NUM_MINORS];
+ 
+-static int do_devconfig_ioctl(struct comedi_device *dev, comedi_devconfig *arg);
++static int do_devconfig_ioctl(struct comedi_device *dev, struct comedi_devconfig *arg);
+ static int do_bufconfig_ioctl(struct comedi_device *dev, void *arg);
+ static int do_devinfo_ioctl(struct comedi_device *dev, struct comedi_devinfo *arg,
+ 			    struct file *file);
+@@ -192,9 +192,9 @@ static int comedi_ioctl(struct inode *inode, struct file *file,
+ 	writes:
+ 		none
+ */
+-static int do_devconfig_ioctl(struct comedi_device *dev, comedi_devconfig *arg)
++static int do_devconfig_ioctl(struct comedi_device *dev, struct comedi_devconfig *arg)
+ {
+-	comedi_devconfig it;
++	struct comedi_devconfig it;
+ 	int ret;
+ 	unsigned char *aux_data = NULL;
+ 	int aux_len;
+@@ -213,7 +213,7 @@ static int do_devconfig_ioctl(struct comedi_device *dev, comedi_devconfig *arg)
+ 		return 0;
+ 	}
+ 
+-	if (copy_from_user(&it, arg, sizeof(comedi_devconfig)))
++	if (copy_from_user(&it, arg, sizeof(struct comedi_devconfig)))
+ 		return -EFAULT;
+ 
+ 	it.board_name[COMEDI_NAMELEN - 1] = 0;
+diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
+index 36dd82299c0a..e6a3005e19de 100644
+--- a/drivers/staging/comedi/comedidev.h
++++ b/drivers/staging/comedi/comedidev.h
+@@ -239,7 +239,7 @@ struct comedi_driver {
+ 
+ 	const char *driver_name;
+ 	struct module *module;
+-	int (*attach) (struct comedi_device *, comedi_devconfig *);
++	int (*attach) (struct comedi_device *, struct comedi_devconfig *);
+ 	int (*detach) (struct comedi_device *);
+ 
+ 	/* number of elements in board_name and board_id arrays */
+@@ -337,7 +337,7 @@ static inline struct comedi_subdevice *comedi_get_write_subdevice(
+ }
+ 
+ void comedi_device_detach(struct comedi_device *dev);
+-int comedi_device_attach(struct comedi_device *dev, comedi_devconfig *it);
++int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ int comedi_driver_register(struct comedi_driver *);
+ int comedi_driver_unregister(struct comedi_driver *);
+ 
+diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
+index 9728c7430f8b..3e397d01ccce 100644
+--- a/drivers/staging/comedi/drivers.c
++++ b/drivers/staging/comedi/drivers.c
+@@ -113,7 +113,7 @@ void comedi_device_detach(struct comedi_device *dev)
+ 	__comedi_device_detach(dev);
+ }
+ 
+-int comedi_device_attach(struct comedi_device *dev, comedi_devconfig *it)
++int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_driver *driv;
+ 	int ret;
+@@ -791,7 +791,7 @@ void comedi_reset_async_buf(struct comedi_async *async)
+ 
+ int comedi_auto_config(struct device *hardware_device, const char *board_name, const int *options, unsigned num_options)
+ {
+-	comedi_devconfig it;
++	struct comedi_devconfig it;
+ 	int minor;
+ 	struct comedi_device_file_info *dev_file_info;
+ 	int retval;
+diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c
+index ec5f9167110b..0369c7c84ac5 100644
+--- a/drivers/staging/comedi/drivers/8255.c
++++ b/drivers/staging/comedi/drivers/8255.c
+@@ -105,7 +105,7 @@ struct subdev_8255_struct {
+ #define CALLBACK_FUNC	(((struct subdev_8255_struct *)s->private)->cb_func)
+ #define subdevpriv	((struct subdev_8255_struct *)s->private)
+ 
+-static int dev_8255_attach(struct comedi_device *dev, comedi_devconfig * it);
++static int dev_8255_attach(struct comedi_device *dev, struct comedi_devconfig * it);
+ static int dev_8255_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_8255 = {
+       driver_name:"8255",
+@@ -374,7 +374,7 @@ void subdev_8255_cleanup(struct comedi_device *dev, struct comedi_subdevice * s)
+ 
+  */
+ 
+-static int dev_8255_attach(struct comedi_device *dev, comedi_devconfig * it)
++static int dev_8255_attach(struct comedi_device *dev, struct comedi_devconfig * it)
+ {
+ 	int ret;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/acl7225b.c b/drivers/staging/comedi/drivers/acl7225b.c
+index 3e257cd9eb02..78349300ecd3 100644
+--- a/drivers/staging/comedi/drivers/acl7225b.c
++++ b/drivers/staging/comedi/drivers/acl7225b.c
+@@ -22,7 +22,7 @@ Devices: [Adlink] ACL-7225b (acl7225b), [ICP] P16R16DIO (p16r16dio)
+ #define ACL7225_DI_LO  2	/* Digital input low byte (DI0-DI7) */
+ #define ACL7225_DI_HI  3	/* Digital input high byte (DI8-DI15) */
+ 
+-static int acl7225b_attach(struct comedi_device *dev, comedi_devconfig * it);
++static int acl7225b_attach(struct comedi_device *dev, struct comedi_devconfig * it);
+ static int acl7225b_detach(struct comedi_device *dev);
+ 
+ typedef struct {
+@@ -83,7 +83,7 @@ static int acl7225b_di_insn(struct comedi_device *dev, struct comedi_subdevice *
+ 	return 2;
+ }
+ 
+-static int acl7225b_attach(struct comedi_device *dev, comedi_devconfig * it)
++static int acl7225b_attach(struct comedi_device *dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int iobase, iorange;
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+index adb5deacd947..618c69b6838d 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+@@ -2542,7 +2542,7 @@ COMEDI_PCI_INITCLEANUP(driver_addi, addi_apci_tbl);
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :static int i_ADDI_Attach(struct comedi_device *dev,            |
+-|										comedi_devconfig *it)        |
++|										struct comedi_devconfig *it)        |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              :Detects the card.                                       |
+@@ -2551,7 +2551,7 @@ COMEDI_PCI_INITCLEANUP(driver_addi, addi_apci_tbl);
+ |			 allocation of data structures for the driver.	         |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :struct comedi_device *dev										 |
+-|                    comedi_devconfig *it									 |
++|                    struct comedi_devconfig *it									 |
+ |                                                 					         |
+ +----------------------------------------------------------------------------+
+ | Return Value      :  0            					                     |
+@@ -2559,7 +2559,7 @@ COMEDI_PCI_INITCLEANUP(driver_addi, addi_apci_tbl);
+ +----------------------------------------------------------------------------+
+ */
+ 
+-static int i_ADDI_Attach(struct comedi_device * dev, comedi_devconfig * it)
++static int i_ADDI_Attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int ret, pages, i, n_subdevices;
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+index 2b01577683b5..b3ad58e9df93 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+@@ -456,7 +456,7 @@ typedef struct {
+ static unsigned short pci_list_builded;	/* set to 1 when list of card is known */
+ 
+ /* Function declarations */
+-static int i_ADDI_Attach(struct comedi_device *dev, comedi_devconfig *it);
++static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int i_ADDI_Detach(struct comedi_device *dev);
+ static int i_ADDI_Reset(struct comedi_device *dev);
+ 
+diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c
+index cb0073156718..fa290ba4690f 100644
+--- a/drivers/staging/comedi/drivers/adl_pci6208.c
++++ b/drivers/staging/comedi/drivers/adl_pci6208.c
+@@ -106,7 +106,7 @@ typedef struct {
+ 
+ #define devpriv ((pci6208_private *)dev->private)
+ 
+-static int pci6208_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pci6208_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pci6208_detach(struct comedi_device * dev);
+ 
+ #define pci6208_board_nbr \
+@@ -142,7 +142,7 @@ static int pci6208_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pci6208_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pci6208_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int retval;
+diff --git a/drivers/staging/comedi/drivers/adl_pci7296.c b/drivers/staging/comedi/drivers/adl_pci7296.c
+index 21b8ba80dac9..7fe4ce14fcf3 100644
+--- a/drivers/staging/comedi/drivers/adl_pci7296.c
++++ b/drivers/staging/comedi/drivers/adl_pci7296.c
+@@ -63,7 +63,7 @@ typedef struct {
+ 
+ #define devpriv ((adl_pci7296_private *)dev->private)
+ 
+-static int adl_pci7296_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int adl_pci7296_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int adl_pci7296_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_adl_pci7296 = {
+       driver_name:"adl_pci7296",
+@@ -72,7 +72,7 @@ static struct comedi_driver driver_adl_pci7296 = {
+       detach:adl_pci7296_detach,
+ };
+ 
+-static int adl_pci7296_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int adl_pci7296_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct pci_dev *pcidev;
+ 	struct comedi_subdevice *s;
+diff --git a/drivers/staging/comedi/drivers/adl_pci7432.c b/drivers/staging/comedi/drivers/adl_pci7432.c
+index 6759cb39d564..8fdea81b59fc 100644
+--- a/drivers/staging/comedi/drivers/adl_pci7432.c
++++ b/drivers/staging/comedi/drivers/adl_pci7432.c
+@@ -58,7 +58,7 @@ typedef struct {
+ 
+ #define devpriv ((adl_pci7432_private *)dev->private)
+ 
+-static int adl_pci7432_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int adl_pci7432_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int adl_pci7432_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_adl_pci7432 = {
+       driver_name:"adl_pci7432",
+@@ -77,7 +77,7 @@ static int adl_pci7432_do_insn_bits(struct comedi_device * dev, struct comedi_su
+ 
+ /*            */
+ 
+-static int adl_pci7432_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int adl_pci7432_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct pci_dev *pcidev;
+ 	struct comedi_subdevice *s;
+diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c
+index 0c93efc761a4..c401e110770c 100644
+--- a/drivers/staging/comedi/drivers/adl_pci8164.c
++++ b/drivers/staging/comedi/drivers/adl_pci8164.c
+@@ -70,7 +70,7 @@ typedef struct {
+ 
+ #define devpriv ((adl_pci8164_private *)dev->private)
+ 
+-static int adl_pci8164_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int adl_pci8164_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int adl_pci8164_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_adl_pci8164 = {
+       driver_name:"adl_pci8164",
+@@ -103,7 +103,7 @@ static int adl_pci8164_insn_write_buf0(struct comedi_device * dev,
+ static int adl_pci8164_insn_write_buf1(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
+ 
+-static int adl_pci8164_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int adl_pci8164_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct pci_dev *pcidev;
+ 	struct comedi_subdevice *s;
+diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
+index f6ec53728800..cce2c8303137 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9111.c
++++ b/drivers/staging/comedi/drivers/adl_pci9111.c
+@@ -265,7 +265,7 @@ Configuration options:
+ // Function prototypes
+ //
+ 
+-static int pci9111_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pci9111_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pci9111_detach(struct comedi_device * dev);
+ static void pci9111_ai_munge(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	void *data, unsigned int num_bytes, unsigned int start_chan_index);
+@@ -1246,7 +1246,7 @@ static int pci9111_reset(struct comedi_device * dev)
+ //      - Declare device driver capability
+ //
+ 
+-static int pci9111_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pci9111_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *subdevice;
+ 	unsigned long io_base, io_range, lcr_io_base, lcr_io_range;
+diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
+index 406eab7fd435..131498a5b69a 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9118.c
++++ b/drivers/staging/comedi/drivers/adl_pci9118.c
+@@ -178,7 +178,7 @@ static const struct comedi_lrange range_pci9118hg = { 8, {
+ 
+ #define PCI9118_BIPOLAR_RANGES	4	/* used for test on mixture of BIP/UNI ranges */
+ 
+-static int pci9118_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pci9118_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pci9118_detach(struct comedi_device * dev);
+ 
+ typedef struct {
+@@ -1835,7 +1835,7 @@ static int pci9118_reset(struct comedi_device * dev)
+ /*
+ ==============================================================================
+ */
+-static int pci9118_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pci9118_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int ret, pages, i;
+diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c
+index 07eea09e81fb..d112a64ad119 100644
+--- a/drivers/staging/comedi/drivers/adq12b.c
++++ b/drivers/staging/comedi/drivers/adq12b.c
+@@ -162,7 +162,7 @@ typedef struct{
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int adq12b_attach(struct comedi_device *dev,comedi_devconfig *it);
++static int adq12b_attach(struct comedi_device *dev,struct comedi_devconfig *it);
+ static int adq12b_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_adq12b={
+         driver_name:    "adq12b",
+@@ -184,7 +184,7 @@ static int adq12b_do_insn_bits(struct comedi_device *dev,struct comedi_subdevice
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int adq12b_attach(struct comedi_device *dev,comedi_devconfig *it)
++static int adq12b_attach(struct comedi_device *dev,struct comedi_devconfig *it)
+ {
+         struct comedi_subdevice *s;
+         unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
+index 64aec321274d..934468be44c5 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1710.c
++++ b/drivers/staging/comedi/drivers/adv_pci1710.c
+@@ -182,7 +182,7 @@ static const struct comedi_lrange range_pci171x_da = { 2, {
+ 	}
+ };
+ 
+-static int pci1710_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pci1710_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pci1710_detach(struct comedi_device * dev);
+ 
+ typedef struct {
+@@ -1316,7 +1316,7 @@ static int pci1710_reset(struct comedi_device * dev)
+ /*
+ ==============================================================================
+ */
+-static int pci1710_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pci1710_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int ret, subdev, n_subdevices;
+diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
+index 002144a9f6bd..f6492fa3e9a9 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1723.c
++++ b/drivers/staging/comedi/drivers/adv_pci1723.c
+@@ -143,7 +143,7 @@ MODULE_DEVICE_TABLE(pci, pci1723_pci_table);
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pci1723_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pci1723_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pci1723_detach(struct comedi_device * dev);
+ 
+ #define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+@@ -294,7 +294,7 @@ static int pci1723_dio_insn_bits(struct comedi_device * dev, struct comedi_subde
+  * Attach is called by the Comedi core to configure the driver
+  * for a pci1723 board.
+  */
+-static int pci1723_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pci1723_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int ret, subdev, n_subdevices;
+diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
+index 7ed30317073c..8f920db83d14 100644
+--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
++++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
+@@ -183,7 +183,7 @@ typedef enum {
+ 
+ #define OMBCMD_RETRY	0x03	/* 3 times try request before error */
+ 
+-static int pci_dio_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pci_dio_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pci_dio_detach(struct comedi_device * dev);
+ 
+ typedef struct {
+@@ -750,7 +750,7 @@ static int pci_dio_reset(struct comedi_device * dev)
+ /*
+ ==============================================================================
+ */
+-static int pci1760_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pci1760_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int subdev = 0;
+@@ -857,7 +857,7 @@ static int pci_dio_add_do(struct comedi_device * dev, struct comedi_subdevice *
+ /*
+ ==============================================================================
+ */
+-static int CheckAndAllocCard(struct comedi_device * dev, comedi_devconfig * it,
++static int CheckAndAllocCard(struct comedi_device * dev, struct comedi_devconfig * it,
+ 	struct pci_dev *pcidev)
+ {
+ 	pci_dio_private *pr, *prev;
+@@ -883,7 +883,7 @@ static int CheckAndAllocCard(struct comedi_device * dev, comedi_devconfig * it,
+ /*
+ ==============================================================================
+ */
+-static int pci_dio_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pci_dio_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int ret, subdev, n_subdevices, i, j;
+diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c
+index 10fd18aeb3fe..c3e8f99ec4e9 100644
+--- a/drivers/staging/comedi/drivers/aio_aio12_8.c
++++ b/drivers/staging/comedi/drivers/aio_aio12_8.c
+@@ -161,7 +161,7 @@ static const struct comedi_lrange range_aio_aio12_8 = {
+ 		}
+ };
+ 
+-static int aio_aio12_8_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int aio_aio12_8_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	int iobase;
+ 	struct comedi_subdevice *s;
+diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c
+index a739bfa2b59b..f6979eb57a8d 100644
+--- a/drivers/staging/comedi/drivers/aio_iiro_16.c
++++ b/drivers/staging/comedi/drivers/aio_iiro_16.c
+@@ -67,7 +67,7 @@ typedef struct {
+ 
+ #define	devpriv	((aio_iiro_16_private *) dev->private)
+ 
+-static int aio_iiro_16_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int aio_iiro_16_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ 
+ static int aio_iiro_16_detach(struct comedi_device * dev);
+ 
+@@ -87,7 +87,7 @@ static int aio_iiro_16_dio_insn_bits_read(struct comedi_device * dev,
+ static int aio_iiro_16_dio_insn_bits_write(struct comedi_device * dev,
+ 	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
+ 
+-static int aio_iiro_16_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int aio_iiro_16_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	int iobase;
+ 	struct comedi_subdevice *s;
+diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
+index 88c127566b8a..f5f20edddae0 100644
+--- a/drivers/staging/comedi/drivers/amplc_dio200.c
++++ b/drivers/staging/comedi/drivers/amplc_dio200.c
+@@ -473,7 +473,7 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int dio200_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int dio200_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int dio200_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_amplc_dio200 = {
+       driver_name:DIO200_DRIVER_NAME,
+@@ -1262,7 +1262,7 @@ dio200_subdev_8254_cleanup(struct comedi_device * dev, struct comedi_subdevice *
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int dio200_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int dio200_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase = 0;
+diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
+index b9c883500ca5..ed253482d991 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc236.c
++++ b/drivers/staging/comedi/drivers/amplc_pc236.c
+@@ -165,7 +165,7 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pc236_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pc236_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pc236_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_amplc_pc236 = {
+       driver_name:PC236_DRIVER_NAME,
+@@ -264,7 +264,7 @@ pc236_find_pci(struct comedi_device * dev, int bus, int slot,
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pc236_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pc236_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase = 0;
+diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
+index d7c33e1403bb..99db1a987ca2 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc263.c
++++ b/drivers/staging/comedi/drivers/amplc_pc263.c
+@@ -132,7 +132,7 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pc263_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pc263_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pc263_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_amplc_pc263 = {
+       driver_name:PC263_DRIVER_NAME,
+@@ -219,7 +219,7 @@ pc263_find_pci(struct comedi_device * dev, int bus, int slot,
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pc263_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pc263_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase = 0;
+diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
+index ec60574786a9..f0beaa69256e 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci224.c
++++ b/drivers/staging/comedi/drivers/amplc_pci224.c
+@@ -426,7 +426,7 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pci224_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pci224_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pci224_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_amplc_pci224 = {
+       driver_name:DRIVER_NAME,
+@@ -1323,7 +1323,7 @@ pci224_find_pci(struct comedi_device * dev, int bus, int slot,
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pci224_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pci224_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	struct pci_dev *pci_dev;
+diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
+index 432f05ba3bc5..a534763a90f9 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci230.c
++++ b/drivers/staging/comedi/drivers/amplc_pci230.c
+@@ -601,7 +601,7 @@ static const unsigned char pci230_ao_bipolar[2] = { 0, 1 };
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pci230_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pci230_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pci230_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_amplc_pci230 = {
+       driver_name:"amplc_pci230",
+@@ -702,7 +702,7 @@ static inline void pci230_ao_write_fifo(struct comedi_device * dev, short datum,
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pci230_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pci230_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase1, iobase2;
+diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c
+index 8b10ff927d41..2efffb14610d 100644
+--- a/drivers/staging/comedi/drivers/c6xdigio.c
++++ b/drivers/staging/comedi/drivers/c6xdigio.c
+@@ -97,7 +97,7 @@ union encvaluetype {
+ 
+ #define C6XDIGIO_TIME_OUT 20
+ 
+-static int c6xdigio_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int c6xdigio_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int c6xdigio_detach(struct comedi_device * dev);
+ struct comedi_driver driver_c6xdigio = {
+       driver_name:"c6xdigio",
+@@ -428,7 +428,7 @@ static struct pnp_driver c6xdigio_pnp_driver = {
+ 	.id_table = c6xdigio_pnp_tbl,
+ };
+ 
+-static int c6xdigio_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int c6xdigio_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	int result = 0;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
+index df77102cfa5e..487ae3bd21d5 100644
+--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
++++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
+@@ -89,7 +89,7 @@ typedef struct {
+ } das16cs_private;
+ #define devpriv ((das16cs_private *)dev->private)
+ 
+-static int das16cs_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int das16cs_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int das16cs_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_das16cs = {
+       driver_name:"cb_das16_cs",
+@@ -165,7 +165,7 @@ static const das16cs_board *das16cs_probe(struct comedi_device * dev,
+ 	return NULL;
+ }
+ 
+-static int das16cs_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int das16cs_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct pcmcia_device *link;
+ 	struct comedi_subdevice *s;
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
+index f2d09e3e7fa8..b0366e81445c 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas.c
+@@ -440,7 +440,7 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int cb_pcidas_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int cb_pcidas_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int cb_pcidas_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_cb_pcidas = {
+       driver_name:"cb_pcidas",
+@@ -508,7 +508,7 @@ static inline unsigned int cal_enable_bits(struct comedi_device * dev)
+  * Attach is called by the Comedi core to configure the driver
+  * for a particular board.
+  */
+-static int cb_pcidas_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int cb_pcidas_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	struct pci_dev *pcidev;
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
+index 40d97134e384..b6fc5c119701 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
+@@ -1125,7 +1125,7 @@ static inline pcidas64_private *priv(struct comedi_device * dev)
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int attach(struct comedi_device * dev, comedi_devconfig * it);
++static int attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int detach(struct comedi_device * dev);
+ static struct comedi_driver driver_cb_pcidas = {
+       driver_name:"cb_pcidas64",
+@@ -1673,7 +1673,7 @@ static inline void warn_external_queue(struct comedi_device * dev)
+  * Attach is called by the Comedi core to configure the driver
+  * for a particular board.
+  */
+-static int attach(struct comedi_device * dev, comedi_devconfig * it)
++static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct pci_dev *pcidev;
+ 	int index;
+diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
+index ade2ef1cbbd8..27f46a609e39 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidda.c
++++ b/drivers/staging/comedi/drivers/cb_pcidda.c
+@@ -232,7 +232,7 @@ typedef struct {
+  */
+ #define devpriv ((cb_pcidda_private *)dev->private)
+ 
+-static int cb_pcidda_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int cb_pcidda_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int cb_pcidda_detach(struct comedi_device * dev);
+ //static int cb_pcidda_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data);
+ static int cb_pcidda_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+@@ -265,7 +265,7 @@ static struct comedi_driver driver_cb_pcidda = {
+  * Attach is called by the Comedi core to configure the driver
+  * for a particular board.
+  */
+-static int cb_pcidda_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int cb_pcidda_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	struct pci_dev *pcidev;
+diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c
+index 61da4f0bab55..a34dc9543f9d 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidio.c
++++ b/drivers/staging/comedi/drivers/cb_pcidio.c
+@@ -127,7 +127,7 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pcidio_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcidio_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pcidio_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_cb_pcidio = {
+       driver_name:"cb_pcidio",
+@@ -166,7 +166,7 @@ static struct comedi_driver driver_cb_pcidio = {
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pcidio_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pcidio_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct pci_dev *pcidev = NULL;
+ 	int index;
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
+index ab588d15f576..dcd56f809944 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
+@@ -175,7 +175,7 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int cb_pcimdas_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int cb_pcimdas_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int cb_pcimdas_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_cb_pcimdas = {
+       driver_name:"cb_pcimdas",
+@@ -197,7 +197,7 @@ static int cb_pcimdas_ao_rinsn(struct comedi_device * dev, struct comedi_subdevi
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int cb_pcimdas_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int cb_pcimdas_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	struct pci_dev *pcidev;
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
+index dfbdcfaa49af..c4600d0c9bc3 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
+@@ -181,7 +181,7 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int attach(struct comedi_device * dev, comedi_devconfig * it);
++static int attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int detach(struct comedi_device * dev);
+ static struct comedi_driver cb_pcimdda_driver = {
+       driver_name:"cb_pcimdda",
+@@ -226,7 +226,7 @@ static inline unsigned int figure_out_maxdata(int bits)
+  *
+  *  Otherwise, returns a -errno on error
+  */
+-static int probe(struct comedi_device * dev, const comedi_devconfig * it);
++static int probe(struct comedi_device * dev, const struct comedi_devconfig * it);
+ 
+ /*---------------------------------------------------------------------------
+   FUNCTION DEFINITIONS
+@@ -238,7 +238,7 @@ static int probe(struct comedi_device * dev, const comedi_devconfig * it);
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int attach(struct comedi_device * dev, comedi_devconfig * it)
++static int attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int err;
+@@ -425,7 +425,7 @@ static int ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+  *
+  *  Otherwise, returns a -errno on error
+  */
+-static int probe(struct comedi_device * dev, const comedi_devconfig * it)
++static int probe(struct comedi_device * dev, const struct comedi_devconfig * it)
+ {
+ 	struct pci_dev *pcidev;
+ 	int index;
+diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c
+index be46f17560db..1ee489864d3b 100644
+--- a/drivers/staging/comedi/drivers/comedi_bond.c
++++ b/drivers/staging/comedi/drivers/comedi_bond.c
+@@ -176,10 +176,10 @@ struct Private {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int bonding_attach(struct comedi_device *dev, comedi_devconfig *it);
++static int bonding_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int bonding_detach(struct comedi_device *dev);
+ /** Build Private array of all devices.. */
+-static int doDevConfig(struct comedi_device *dev, comedi_devconfig *it);
++static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it);
+ static void doDevUnconfig(struct comedi_device *dev);
+ /* Ugly implementation of realloc that always copies memory around -- I'm lazy,
+  * what can I say?  I like to do wasteful memcopies.. :) */
+@@ -224,7 +224,7 @@ static int bonding_dio_insn_config(struct comedi_device *dev, struct comedi_subd
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int bonding_attach(struct comedi_device *dev, comedi_devconfig *it)
++static int bonding_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 
+@@ -394,7 +394,7 @@ static void *Realloc(const void *oldmem, size_t newlen, size_t oldlen)
+ 	return newmem;
+ }
+ 
+-static int doDevConfig(struct comedi_device *dev, comedi_devconfig *it)
++static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int i;
+ 	void *devs_opened[COMEDI_NUM_BOARD_MINORS];
+diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c
+index d58ceff063d4..a23339155ffc 100644
+--- a/drivers/staging/comedi/drivers/comedi_parport.c
++++ b/drivers/staging/comedi/drivers/comedi_parport.c
+@@ -90,7 +90,7 @@ pin, which can be used to wake up tasks.
+ #define PARPORT_B 1
+ #define PARPORT_C 2
+ 
+-static int parport_attach(struct comedi_device *dev, comedi_devconfig *it);
++static int parport_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int parport_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_parport = {
+       .driver_name =	"comedi_parport",
+@@ -291,7 +291,7 @@ static irqreturn_t parport_interrupt(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int parport_attach(struct comedi_device *dev, comedi_devconfig *it)
++static int parport_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int ret;
+ 	unsigned int irq;
+diff --git a/drivers/staging/comedi/drivers/comedi_rt_timer.c b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+index 91a865d7ed9a..29dd715e3ff2 100644
+--- a/drivers/staging/comedi/drivers/comedi_rt_timer.c
++++ b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+@@ -122,7 +122,7 @@ static inline RTIME nano2count(long long ns)
+  * task period because analog input tends to be slow. */
+ #define SPEED_LIMIT 100000	/* in nanoseconds */
+ 
+-static int timer_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int timer_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int timer_detach(struct comedi_device * dev);
+ static int timer_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int trig_num);
+@@ -607,7 +607,7 @@ static int timer_start_cmd(struct comedi_device * dev, struct comedi_subdevice *
+ 	return 0;
+ }
+ 
+-static int timer_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int timer_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	int ret;
+ 	struct comedi_subdevice *s, *emul_s;
+diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c
+index 09df3d33d22a..a31817b12629 100644
+--- a/drivers/staging/comedi/drivers/comedi_test.c
++++ b/drivers/staging/comedi/drivers/comedi_test.c
+@@ -93,7 +93,7 @@ struct waveform_private {
+ };
+ #define devpriv ((struct waveform_private *)dev->private)
+ 
+-static int waveform_attach(struct comedi_device *dev, comedi_devconfig *it);
++static int waveform_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int waveform_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_waveform = {
+       .driver_name =	"comedi_test",
+@@ -192,7 +192,7 @@ static void waveform_ai_interrupt(unsigned long arg)
+ 	comedi_event(dev, dev->read_subdev);
+ }
+ 
+-static int waveform_attach(struct comedi_device *dev, comedi_devconfig *it)
++static int waveform_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int amplitude = it->options[0];
+diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
+index 0e0c790ac740..46e13c6faf40 100644
+--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
++++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
+@@ -75,7 +75,7 @@ typedef struct {
+ 
+ #define devpriv ((contec_private *)dev->private)
+ 
+-static int contec_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int contec_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int contec_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_contec = {
+       driver_name:"contec_pci_dio",
+@@ -97,7 +97,7 @@ static int contec_cmdtest(struct comedi_device * dev, struct comedi_subdevice *
+ static int contec_ns_to_timer(unsigned int *ns, int round);
+ #endif
+ 
+-static int contec_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int contec_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct pci_dev *pcidev;
+ 	struct comedi_subdevice *s;
+diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
+index adda2c4eef12..a2408ebf9c8a 100644
+--- a/drivers/staging/comedi/drivers/daqboard2000.c
++++ b/drivers/staging/comedi/drivers/daqboard2000.c
+@@ -296,7 +296,7 @@ typedef struct daqboard2000_hw {
+ #define DAQBOARD2000_PosRefDacSelect             0x0100
+ #define DAQBOARD2000_NegRefDacSelect             0x0000
+ 
+-static int daqboard2000_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int daqboard2000_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int daqboard2000_detach(struct comedi_device * dev);
+ 
+ static struct comedi_driver driver_daqboard2000 = {
+@@ -717,7 +717,7 @@ static int daqboard2000_8255_cb(int dir, int port, int data,
+ 	return result;
+ }
+ 
+-static int daqboard2000_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int daqboard2000_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	int result = 0;
+ 	struct comedi_subdevice *s;
+diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
+index 8943a42badd6..e4563331e963 100644
+--- a/drivers/staging/comedi/drivers/das08.c
++++ b/drivers/staging/comedi/drivers/das08.c
+@@ -827,7 +827,7 @@ static int das08_counter_config(struct comedi_device * dev, struct comedi_subdev
+ 	return 2;
+ }
+ 
+-static int das08_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int das08_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ 
+ static struct comedi_driver driver_das08 = {
+       driver_name: DRV_NAME,
+@@ -952,7 +952,7 @@ int das08_common_attach(struct comedi_device * dev, unsigned long iobase)
+ 	return 0;
+ }
+ 
+-static int das08_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int das08_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	int ret;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
+index 310903a89e42..7079f7c8fa6a 100644
+--- a/drivers/staging/comedi/drivers/das08_cs.c
++++ b/drivers/staging/comedi/drivers/das08_cs.c
+@@ -56,7 +56,7 @@ static struct pcmcia_device *cur_dev = NULL;
+ 
+ #define thisboard ((const struct das08_board_struct *)dev->board_ptr)
+ 
+-static int das08_cs_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int das08_cs_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ 
+ static struct comedi_driver driver_das08_cs = {
+       driver_name:"das08_cs",
+@@ -69,7 +69,7 @@ static struct comedi_driver driver_das08_cs = {
+       offset:sizeof(struct das08_board_struct),
+ };
+ 
+-static int das08_cs_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int das08_cs_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	int ret;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
+index c4c12e6b1a71..b959ba8e29fb 100644
+--- a/drivers/staging/comedi/drivers/das16.c
++++ b/drivers/staging/comedi/drivers/das16.c
+@@ -698,7 +698,7 @@ static const struct das16_board_struct das16_boards[] = {
+ 
+ #define n_das16_boards ((sizeof(das16_boards))/(sizeof(das16_board)))
+ 
+-static int das16_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int das16_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int das16_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_das16 = {
+       driver_name:"das16",
+@@ -1304,7 +1304,7 @@ static void reg_dump(struct comedi_device * dev)
+ 		inb(dev->iobase + DAS1600_STATUS_B));
+ }
+ 
+-static int das16_probe(struct comedi_device * dev, comedi_devconfig * it)
++static int das16_probe(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	int status;
+ 	int diobits;
+@@ -1366,7 +1366,7 @@ static int das1600_mode_detect(struct comedi_device * dev)
+  *   3  Clock speed (in MHz)
+  */
+ 
+-static int das16_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int das16_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int ret;
+diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
+index ea1fd6ec699d..039d8e549298 100644
+--- a/drivers/staging/comedi/drivers/das16m1.c
++++ b/drivers/staging/comedi/drivers/das16m1.c
+@@ -166,7 +166,7 @@ static const das16m1_board das16m1_boards[] = {
+ 
+ #define das16m1_num_boards ((sizeof(das16m1_boards)) / (sizeof(das16m1_boards[0])))
+ 
+-static int das16m1_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int das16m1_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int das16m1_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_das16m1 = {
+       driver_name:"das16m1",
+@@ -635,7 +635,7 @@ static int das16m1_irq_bits(unsigned int irq)
+  *   1  IRQ
+  */
+ 
+-static int das16m1_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int das16m1_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int ret;
+diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
+index cb53e8fe2403..06f755a5d32c 100644
+--- a/drivers/staging/comedi/drivers/das1800.c
++++ b/drivers/staging/comedi/drivers/das1800.c
+@@ -180,7 +180,7 @@ enum {
+ 	das1802hr, das1802hr_da, das1801hc, das1802hc, das1801ao, das1802ao
+ };
+ 
+-static int das1800_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int das1800_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int das1800_detach(struct comedi_device * dev);
+ static int das1800_probe(struct comedi_device * dev);
+ static int das1800_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+@@ -590,7 +590,7 @@ static int das1800_init_dma(struct comedi_device * dev, unsigned int dma0,
+ 	return 0;
+ }
+ 
+-static int das1800_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int das1800_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase = it->options[0];
+diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c
+index 628e11160825..37b47267149c 100644
+--- a/drivers/staging/comedi/drivers/das6402.c
++++ b/drivers/staging/comedi/drivers/das6402.c
+@@ -98,7 +98,7 @@ This driver has suffered bitrot.
+ #define	C2 0x80
+ #define	RWLH 0x30
+ 
+-static int das6402_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int das6402_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int das6402_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_das6402 = {
+       driver_name:"das6402",
+@@ -299,7 +299,7 @@ static int das6402_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int das6402_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int das6402_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	unsigned int irq;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
+index 179a694b0745..85407ef8dfb1 100644
+--- a/drivers/staging/comedi/drivers/das800.c
++++ b/drivers/staging/comedi/drivers/das800.c
+@@ -242,7 +242,7 @@ typedef struct {
+ 
+ #define devpriv ((das800_private *)dev->private)
+ 
+-static int das800_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int das800_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int das800_detach(struct comedi_device * dev);
+ static int das800_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ 
+@@ -441,7 +441,7 @@ static irqreturn_t das800_interrupt(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int das800_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int das800_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase = it->options[0];
+diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
+index 36e283ba753d..1b2c58f7eb3f 100644
+--- a/drivers/staging/comedi/drivers/dmm32at.c
++++ b/drivers/staging/comedi/drivers/dmm32at.c
+@@ -258,7 +258,7 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int dmm32at_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int dmm32at_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int dmm32at_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_dmm32at = {
+       driver_name:"dmm32at",
+@@ -313,7 +313,7 @@ void dmm32at_setaitimer(struct comedi_device * dev, unsigned int nansec);
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int dmm32at_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int dmm32at_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	int ret;
+ 	struct comedi_subdevice *s;
+diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c
+index 847aa951d9c1..0915d39101b8 100644
+--- a/drivers/staging/comedi/drivers/dt2801.c
++++ b/drivers/staging/comedi/drivers/dt2801.c
+@@ -88,7 +88,7 @@ Configuration options:
+ #define DT2801_STATUS		1
+ #define DT2801_CMD		1
+ 
+-static int dt2801_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int dt2801_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int dt2801_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_dt2801 = {
+       driver_name:"dt2801",
+@@ -478,7 +478,7 @@ static const struct comedi_lrange *ai_range_lkup(int type, int opt)
+ 	[4] - dac0 range 0=[-10,10], 1=[-5,5], 2=[-2.5,2.5] 3=[0,10], 4=[0,5]
+ 	[5] - dac1 range 0=[-10,10], 1=[-5,5], 2=[-2.5,2.5] 3=[0,10], 4=[0,5]
+ */
+-static int dt2801_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int dt2801_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c
+index 165ea6f22ba4..722e3f54e468 100644
+--- a/drivers/staging/comedi/drivers/dt2811.c
++++ b/drivers/staging/comedi/drivers/dt2811.c
+@@ -212,7 +212,7 @@ static const boardtype boardtypes[] = {
+ 
+ #define this_board ((const boardtype *)dev->board_ptr)
+ 
+-static int dt2811_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int dt2811_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int dt2811_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_dt2811 = {
+       driver_name:"dt2811",
+@@ -308,7 +308,7 @@ static irqreturn_t dt2811_interrupt(int irq, void *d PT_REGS_ARG)
+                  2 == unipolar 5V  (0V -- +5V)
+ */
+ 
+-static int dt2811_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int dt2811_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	//int i, irq;
+ 	//unsigned long irqs;
+diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c
+index f97fed0552a2..660079acd223 100644
+--- a/drivers/staging/comedi/drivers/dt2814.c
++++ b/drivers/staging/comedi/drivers/dt2814.c
+@@ -59,7 +59,7 @@ addition, the clock does not seem to be very accurate.
+ #define DT2814_ENB 0x10
+ #define DT2814_CHANMASK 0x0f
+ 
+-static int dt2814_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int dt2814_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int dt2814_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_dt2814 = {
+       driver_name:"dt2814",
+@@ -243,7 +243,7 @@ static int dt2814_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s
+ 
+ }
+ 
+-static int dt2814_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int dt2814_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	int i, irq;
+ 	int ret;
+diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c
+index f9b79d2867eb..553842e120f0 100644
+--- a/drivers/staging/comedi/drivers/dt2815.c
++++ b/drivers/staging/comedi/drivers/dt2815.c
+@@ -75,7 +75,7 @@ static const struct comedi_lrange range_dt2815_ao_20_current = { 1, {
+ #define DT2815_DATA 0
+ #define DT2815_STATUS 1
+ 
+-static int dt2815_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int dt2815_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int dt2815_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_dt2815 = {
+       driver_name:"dt2815",
+@@ -177,7 +177,7 @@ static int dt2815_ao_insn(struct comedi_device * dev, struct comedi_subdevice *
+                  1 == current
+  */
+ 
+-static int dt2815_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int dt2815_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c
+index 59376ac6c254..2dc396a44e6f 100644
+--- a/drivers/staging/comedi/drivers/dt2817.c
++++ b/drivers/staging/comedi/drivers/dt2817.c
+@@ -47,7 +47,7 @@ Configuration options:
+ #define DT2817_CR 0
+ #define DT2817_DATA 1
+ 
+-static int dt2817_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int dt2817_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int dt2817_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_dt2817 = {
+       driver_name:"dt2817",
+@@ -131,7 +131,7 @@ static int dt2817_dio_insn_bits(struct comedi_device * dev, struct comedi_subdev
+ 	return 2;
+ }
+ 
+-static int dt2817_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int dt2817_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	int ret;
+ 	struct comedi_subdevice *s;
+diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
+index 1a74f31ad3ff..1cc0e3b17bb2 100644
+--- a/drivers/staging/comedi/drivers/dt282x.c
++++ b/drivers/staging/comedi/drivers/dt282x.c
+@@ -394,7 +394,7 @@ typedef struct {
+ 		if(_i){b}				\
+ 	}while(0)
+ 
+-static int dt282x_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int dt282x_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int dt282x_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_dt282x = {
+       driver_name:"dt282x",
+@@ -1240,7 +1240,7 @@ enum { opt_iobase = 0, opt_irq, opt_dma1, opt_dma2,	/* i/o base, irq, dma channe
+    9	ao0 0=±10 V, 1=0-10 V, 2=±5 V, 3=0-5 V, 4=±2.5 V
+    10	ao1 0=±10 V, 1=0-10 V, 2=±5 V, 3=0-5 V, 4=±2.5 V
+  */
+-static int dt282x_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int dt282x_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	int i, irq;
+ 	int ret;
+diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
+index 4b140f21cbdf..a8367d9c0a4c 100644
+--- a/drivers/staging/comedi/drivers/dt3000.c
++++ b/drivers/staging/comedi/drivers/dt3000.c
+@@ -271,7 +271,7 @@ typedef struct {
+ } dt3k_private;
+ #define devpriv ((dt3k_private *)dev->private)
+ 
+-static int dt3000_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int dt3000_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int dt3000_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_dt3000 = {
+       driver_name:"dt3000",
+@@ -797,7 +797,7 @@ static int dt3k_mem_insn_read(struct comedi_device * dev, struct comedi_subdevic
+ 
+ static int dt_pci_probe(struct comedi_device * dev, int bus, int slot);
+ 
+-static int dt3000_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int dt3000_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int bus, slot;
+diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c
+index e2131fd4f45f..cc4c04630086 100644
+--- a/drivers/staging/comedi/drivers/dt9812.c
++++ b/drivers/staging/comedi/drivers/dt9812.c
+@@ -1009,7 +1009,7 @@ static int dt9812_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s
+ 	return n;
+ }
+ 
+-static int dt9812_attach(struct comedi_device *dev, comedi_devconfig *it)
++static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int i;
+ 	struct comedi_subdevice *s;
+diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c
+index cd6b3e037515..6fe747d8dd11 100644
+--- a/drivers/staging/comedi/drivers/fl512.c
++++ b/drivers/staging/comedi/drivers/fl512.c
+@@ -40,7 +40,7 @@ static const struct comedi_lrange range_fl512 = { 4, {
+ 	}
+ };
+ 
+-static int fl512_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int fl512_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int fl512_detach(struct comedi_device * dev);
+ 
+ static struct comedi_driver driver_fl512 = {
+@@ -124,7 +124,7 @@ static int fl512_ao_insn_readback(struct comedi_device * dev,
+ /*
+  * start attach
+  */
+-static int fl512_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int fl512_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	unsigned long iobase;
+ 	struct comedi_subdevice *s;	/* pointer to the subdevice:
+diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
+index 5227e3ee273b..535aadb98dcc 100644
+--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
++++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
+@@ -52,7 +52,7 @@ support could be added to this driver.
+ #include "plx9080.h"
+ #include "comedi_fc.h"
+ 
+-static int hpdi_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int hpdi_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int hpdi_detach(struct comedi_device * dev);
+ void abort_dma(struct comedi_device * dev, unsigned int channel);
+ static int hpdi_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+@@ -552,7 +552,7 @@ static int setup_dma_descriptors(struct comedi_device * dev,
+ 	return transfer_size;
+ }
+ 
+-static int hpdi_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int hpdi_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct pci_dev *pcidev;
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
+index 5463718e5ff7..15fce0190b2f 100644
+--- a/drivers/staging/comedi/drivers/icp_multi.c
++++ b/drivers/staging/comedi/drivers/icp_multi.c
+@@ -123,7 +123,7 @@ static const char range_codes_analog[] = { 0x00, 0x20, 0x10, 0x30 };
+ 	Forward declarations
+ ==============================================================================
+ */
+-static int icp_multi_attach(struct comedi_device *dev, comedi_devconfig *it);
++static int icp_multi_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int icp_multi_detach(struct comedi_device *dev);
+ 
+ /*
+@@ -864,13 +864,13 @@ static int icp_multi_reset(struct comedi_device *dev)
+ 
+ 	Parameters:
+ 		struct comedi_device *dev	Pointer to current device structure
+-		comedi_devconfig *it	Pointer to current device configuration
++		struct comedi_devconfig *it	Pointer to current device configuration
+ 
+ 	Returns:int	0 = success
+ 
+ ==============================================================================
+ */
+-static int icp_multi_attach(struct comedi_device *dev, comedi_devconfig *it)
++static int icp_multi_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int ret, subdev, n_subdevices;
+diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c
+index 5f513bac8e47..a31f0d20fcf2 100644
+--- a/drivers/staging/comedi/drivers/ii_pci20kc.c
++++ b/drivers/staging/comedi/drivers/ii_pci20kc.c
+@@ -156,7 +156,7 @@ typedef struct {
+ #define devpriv ((pci20xxx_private *)dev->private)
+ #define CHAN (CR_CHAN(it->chanlist[0]))
+ 
+-static int pci20xxx_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pci20xxx_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pci20xxx_detach(struct comedi_device * dev);
+ 
+ static struct comedi_driver driver_pci20xxx = {
+@@ -199,7 +199,7 @@ static int pci20xxx_dio_init(struct comedi_device * dev, struct comedi_subdevice
+ 		1 == unipolar 10V  (0V -- +10V)
+ 		2 == bipolar 5V  (-5V -- +5V)
+ */
+-static int pci20xxx_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pci20xxx_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	unsigned char i;
+ 	int ret;
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
+index 19371c6048d3..8f481b545643 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -103,7 +103,7 @@ static int comedi_load_firmware(struct comedi_device * dev,
+ #define PCI_DEVICE_ID_JR3_3_CHANNEL 0x3113
+ #define PCI_DEVICE_ID_JR3_4_CHANNEL 0x3114
+ 
+-static int jr3_pci_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int jr3_pci_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int jr3_pci_detach(struct comedi_device * dev);
+ 
+ static struct comedi_driver driver_jr3_pci = {
+@@ -770,7 +770,7 @@ static void jr3_pci_poll_dev(unsigned long data)
+ 	add_timer(&devpriv->timer);
+ }
+ 
+-static int jr3_pci_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int jr3_pci_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	int result = 0;
+ 	struct pci_dev *card = NULL;
+diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c
+index f3b4f74e873d..105a9cfeb745 100644
+--- a/drivers/staging/comedi/drivers/ke_counter.c
++++ b/drivers/staging/comedi/drivers/ke_counter.c
+@@ -48,7 +48,7 @@ Kolter Electronic PCI Counter Card.
+ 
+ /*-- function prototypes ----------------------------------------------------*/
+ 
+-static int cnt_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int cnt_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int cnt_detach(struct comedi_device * dev);
+ 
+ static DEFINE_PCI_DEVICE_TABLE(cnt_pci_table) = {
+@@ -144,7 +144,7 @@ static int cnt_rinsn(struct comedi_device * dev,
+ 
+ /*-- attach -----------------------------------------------------------------*/
+ 
+-static int cnt_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int cnt_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *subdevice;
+ 	struct pci_dev *pci_device;
+diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
+index 70c3cc2c307d..d0a17a1adfc2 100644
+--- a/drivers/staging/comedi/drivers/me4000.c
++++ b/drivers/staging/comedi/drivers/me4000.c
+@@ -118,7 +118,7 @@ static const me4000_board_t me4000_boards[] = {
+ /*-----------------------------------------------------------------------------
+   Comedi function prototypes
+   ---------------------------------------------------------------------------*/
+-static int me4000_attach(struct comedi_device *dev, comedi_devconfig *it);
++static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int me4000_detach(struct comedi_device *dev);
+ static struct comedi_driver driver_me4000 = {
+       driver_name:"me4000",
+@@ -130,7 +130,7 @@ static struct comedi_driver driver_me4000 = {
+ /*-----------------------------------------------------------------------------
+   Meilhaus function prototypes
+   ---------------------------------------------------------------------------*/
+-static int me4000_probe(struct comedi_device *dev, comedi_devconfig *it);
++static int me4000_probe(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int get_registers(struct comedi_device *dev, struct pci_dev *pci_dev_p);
+ static int init_board_info(struct comedi_device *dev, struct pci_dev *pci_dev_p);
+ static int init_ao_context(struct comedi_device *dev);
+@@ -247,7 +247,7 @@ static const struct comedi_lrange me4000_ao_range = {
+ 		}
+ };
+ 
+-static int me4000_attach(struct comedi_device *dev, comedi_devconfig *it)
++static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int result;
+@@ -369,7 +369,7 @@ static int me4000_attach(struct comedi_device *dev, comedi_devconfig *it)
+ 	return 0;
+ }
+ 
+-static int me4000_probe(struct comedi_device *dev, comedi_devconfig *it)
++static int me4000_probe(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct pci_dev *pci_device;
+ 	int result, i;
+diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c
+index 901e1d13fcf2..0f023d009e61 100644
+--- a/drivers/staging/comedi/drivers/me_daq.c
++++ b/drivers/staging/comedi/drivers/me_daq.c
+@@ -144,7 +144,7 @@ from http://www.comedi.org
+ #define ME_COUNTER_VALUE_B		0x0022	/* R | - */
+ 
+ /* Function prototypes */
+-static int me_attach(struct comedi_device *dev, comedi_devconfig *it);
++static int me_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int me_detach(struct comedi_device *dev);
+ 
+ static const struct comedi_lrange me2000_ai_range = {
+@@ -632,7 +632,7 @@ static int me_reset(struct comedi_device *dev)
+  * - Register PCI device
+  * - Declare device driver capability
+  */
+-static int me_attach(struct comedi_device *dev, comedi_devconfig *it)
++static int me_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	struct pci_dev *pci_device;
+ 	struct comedi_subdevice *subdevice;
+diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c
+index 59e8ecd66088..ee053f149dd9 100644
+--- a/drivers/staging/comedi/drivers/mpc624.c
++++ b/drivers/staging/comedi/drivers/mpc624.c
+@@ -144,7 +144,7 @@ static const struct comedi_lrange range_mpc624_bipolar10 = {
+ };
+ 
+ //----------------------------------------------------------------------------
+-static int mpc624_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int mpc624_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int mpc624_detach(struct comedi_device * dev);
+ //----------------------------------------------------------------------------
+ static struct comedi_driver driver_mpc624 = {
+@@ -158,7 +158,7 @@ static struct comedi_driver driver_mpc624 = {
+ static int mpc624_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data);
+ //----------------------------------------------------------------------------
+-static int mpc624_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int mpc624_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/mpc8260cpm.c b/drivers/staging/comedi/drivers/mpc8260cpm.c
+index 645c47053242..7250865e8d6e 100644
+--- a/drivers/staging/comedi/drivers/mpc8260cpm.c
++++ b/drivers/staging/comedi/drivers/mpc8260cpm.c
+@@ -44,7 +44,7 @@ typedef struct {
+ } mpc8260cpm_private;
+ #define devpriv ((mpc8260cpm_private *)dev->private)
+ 
+-static int mpc8260cpm_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int mpc8260cpm_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int mpc8260cpm_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_mpc8260cpm = {
+       driver_name:"mpc8260cpm",
+@@ -60,7 +60,7 @@ static int mpc8260cpm_dio_config(struct comedi_device * dev, struct comedi_subde
+ static int mpc8260cpm_dio_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data);
+ 
+-static int mpc8260cpm_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int mpc8260cpm_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c
+index 1ff60fa53842..9e47574171de 100644
+--- a/drivers/staging/comedi/drivers/multiq3.c
++++ b/drivers/staging/comedi/drivers/multiq3.c
+@@ -82,7 +82,7 @@ Devices: [Quanser Consulting] MultiQ-3 (multiq3)
+ 
+ #define MULTIQ3_TIMEOUT 30
+ 
+-static int multiq3_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int multiq3_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int multiq3_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_multiq3 = {
+       driver_name:"multiq3",
+@@ -235,7 +235,7 @@ static void encoder_reset(struct comedi_device * dev)
+    options[2] - number of encoder chips installed
+  */
+ 
+-static int multiq3_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int multiq3_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	int result = 0;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
+index 52c35c4f0c03..18fb7995c7c5 100644
+--- a/drivers/staging/comedi/drivers/ni_6527.c
++++ b/drivers/staging/comedi/drivers/ni_6527.c
+@@ -75,7 +75,7 @@ Updated: Sat, 25 Jan 2003 13:24:40 -0800
+ #define Rising_Edge_Detection_Enable(x)		(0x018+(x))
+ #define Falling_Edge_Detection_Enable(x)	(0x020+(x))
+ 
+-static int ni6527_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int ni6527_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int ni6527_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_ni6527 = {
+       driver_name:"ni6527",
+@@ -361,7 +361,7 @@ static int ni6527_intr_insn_config(struct comedi_device * dev, struct comedi_sub
+ 	return 2;
+ }
+ 
+-static int ni6527_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int ni6527_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int ret;
+diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
+index 7b439972290b..59edcdf8e032 100644
+--- a/drivers/staging/comedi/drivers/ni_65xx.c
++++ b/drivers/staging/comedi/drivers/ni_65xx.c
+@@ -102,7 +102,7 @@ static inline unsigned Filter_Enable(unsigned port)
+ #define OverflowIntEnable		0x02
+ #define EdgeIntEnable			0x01
+ 
+-static int ni_65xx_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int ni_65xx_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int ni_65xx_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_ni_65xx = {
+       driver_name:"ni_65xx",
+@@ -615,7 +615,7 @@ static int ni_65xx_intr_insn_config(struct comedi_device * dev, struct comedi_su
+ 	return 2;
+ }
+ 
+-static int ni_65xx_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int ni_65xx_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned i;
+diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
+index 7760df604359..0af2049feb99 100644
+--- a/drivers/staging/comedi/drivers/ni_660x.c
++++ b/drivers/staging/comedi/drivers/ni_660x.c
+@@ -444,7 +444,7 @@ static inline const ni_660x_board *board(struct comedi_device * dev)
+ 
+ #define n_ni_660x_boards (sizeof(ni_660x_boards)/sizeof(ni_660x_boards[0]))
+ 
+-static int ni_660x_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int ni_660x_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int ni_660x_detach(struct comedi_device * dev);
+ static void init_tio_chip(struct comedi_device * dev, int chipset);
+ static void ni_660x_select_pfi_output(struct comedi_device * dev, unsigned pfi_channel,
+@@ -980,7 +980,7 @@ static void ni_660x_free_mite_rings(struct comedi_device * dev)
+ 	}
+ }
+ 
+-static int ni_660x_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int ni_660x_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int ret;
+diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
+index 7c07ebbd2f07..28b3355f5b03 100644
+--- a/drivers/staging/comedi/drivers/ni_670x.c
++++ b/drivers/staging/comedi/drivers/ni_670x.c
+@@ -108,7 +108,7 @@ typedef struct {
+ #define devpriv ((ni_670x_private *)dev->private)
+ #define n_ni_670x_boards (sizeof(ni_670x_boards)/sizeof(ni_670x_boards[0]))
+ 
+-static int ni_670x_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int ni_670x_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int ni_670x_detach(struct comedi_device * dev);
+ 
+ static struct comedi_driver driver_ni_670x = {
+@@ -133,7 +133,7 @@ static int ni_670x_dio_insn_bits(struct comedi_device * dev, struct comedi_subde
+ static int ni_670x_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data);
+ 
+-static int ni_670x_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int ni_670x_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int ret;
+diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
+index 6f2f8d35dc11..d14227826817 100644
+--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
++++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
+@@ -167,7 +167,7 @@ typedef struct {
+ 
+ #define devpriv ((a2150_private *)dev->private)
+ 
+-static int a2150_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int a2150_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int a2150_detach(struct comedi_device * dev);
+ static int a2150_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ 
+@@ -322,7 +322,7 @@ static int a2150_probe(struct comedi_device * dev)
+ 	return ID_BITS(status);
+ }
+ 
+-static int a2150_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int a2150_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase = it->options[0];
+diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c
+index c42d89d41e7a..f8c950d52ab6 100644
+--- a/drivers/staging/comedi/drivers/ni_at_ao.c
++++ b/drivers/staging/comedi/drivers/ni_at_ao.c
+@@ -178,7 +178,7 @@ typedef struct {
+ } atao_private;
+ #define devpriv ((atao_private *)dev->private)
+ 
+-static int atao_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int atao_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int atao_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_atao = {
+       driver_name:"ni_at_ao",
+@@ -207,7 +207,7 @@ static int atao_calib_insn_read(struct comedi_device * dev, struct comedi_subdev
+ static int atao_calib_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data);
+ 
+-static int atao_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int atao_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c
+index d5baaa1ca3ff..fcc38535afc5 100644
+--- a/drivers/staging/comedi/drivers/ni_atmio.c
++++ b/drivers/staging/comedi/drivers/ni_atmio.c
+@@ -338,7 +338,7 @@ static struct pnp_device_id device_ids[] = {
+ 
+ MODULE_DEVICE_TABLE(pnp, device_ids);
+ 
+-static int ni_atmio_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int ni_atmio_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int ni_atmio_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_atmio = {
+       driver_name:"ni_atmio",
+@@ -404,7 +404,7 @@ static int ni_isapnp_find_board(struct pnp_dev **dev)
+ 	return 0;
+ }
+ 
+-static int ni_atmio_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int ni_atmio_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct pnp_dev *isapnp_dev;
+ 	int ret;
+diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
+index 4d3cb5fa48b0..5edaa67fd40f 100644
+--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
++++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
+@@ -123,7 +123,7 @@ static const atmio16_board_t atmio16_boards[] = {
+ #define boardtype ((const atmio16_board_t *)dev->board_ptr)
+ 
+ /* function prototypes */
+-static int atmio16d_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int atmio16d_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int atmio16d_detach(struct comedi_device * dev);
+ static irqreturn_t atmio16d_interrupt(int irq, void *d PT_REGS_ARG);
+ static int atmio16d_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+@@ -704,7 +704,7 @@ static int atmio16d_dio_insn_config(struct comedi_device * dev, struct comedi_su
+    options[12] - dac1 coding
+  */
+ 
+-static int atmio16d_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int atmio16d_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	unsigned int irq;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
+index a1a0663b82b3..1530416e4fa6 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_700.c
++++ b/drivers/staging/comedi/drivers/ni_daq_700.c
+@@ -55,7 +55,7 @@ static struct pcmcia_device *pcmcia_cur_dev = NULL;
+ 
+ #define DIO700_SIZE 8		// size of io region used by board
+ 
+-static int dio700_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int dio700_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int dio700_detach(struct comedi_device * dev);
+ 
+ enum dio700_bustype { pcmcia_bustype };
+@@ -350,7 +350,7 @@ EXPORT_SYMBOL(subdev_700_init_irq);
+ EXPORT_SYMBOL(subdev_700_cleanup);
+ EXPORT_SYMBOL(subdev_700_interrupt);
+ 
+-static int dio700_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int dio700_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase = 0;
+diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
+index 5783a8f57730..ed734bb3647e 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
++++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
+@@ -56,7 +56,7 @@ static struct pcmcia_device *pcmcia_cur_dev = NULL;
+ 
+ #define DIO24_SIZE 4		// size of io region used by board
+ 
+-static int dio24_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int dio24_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int dio24_detach(struct comedi_device * dev);
+ 
+ enum dio24_bustype { pcmcia_bustype };
+@@ -107,7 +107,7 @@ static struct comedi_driver driver_dio24 = {
+       offset:sizeof(dio24_board),
+ };
+ 
+-static int dio24_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int dio24_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase = 0;
+diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
+index f6ab0fde2c11..37898d8474cd 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc.c
++++ b/drivers/staging/comedi/drivers/ni_labpc.c
+@@ -163,7 +163,7 @@ NI manuals:
+ #define   INIT_A1_BITS	0x70	// put hardware conversion counter output in harmless state (a1 mode 0)
+ #define COUNTER_B_BASE_REG	0x18
+ 
+-static int labpc_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int labpc_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int labpc_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static irqreturn_t labpc_interrupt(int irq, void *d PT_REGS_ARG);
+ static int labpc_drain_fifo(struct comedi_device * dev);
+@@ -643,7 +643,7 @@ int labpc_common_attach(struct comedi_device * dev, unsigned long iobase,
+ 	return 0;
+ }
+ 
+-static int labpc_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int labpc_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	unsigned long iobase = 0;
+ 	unsigned int irq = 0;
+diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
+index f94cde904dd7..ac0ce2f58f5f 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
++++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
+@@ -79,7 +79,7 @@ NI manuals:
+ 
+ static struct pcmcia_device *pcmcia_cur_dev = NULL;
+ 
+-static int labpc_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int labpc_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ 
+ static const labpc_board labpc_cs_boards[] = {
+ 	{
+@@ -126,7 +126,7 @@ static struct comedi_driver driver_labpc_cs = {
+ 	.offset = sizeof(labpc_board),
+ };
+ 
+-static int labpc_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int labpc_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	unsigned long iobase = 0;
+ 	unsigned int irq = 0;
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index 52984b0a1b7b..ce8c704565d2 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -4289,7 +4289,7 @@ static int ni_alloc_private(struct comedi_device * dev)
+ 	return 0;
+ };
+ 
+-static int ni_E_init(struct comedi_device * dev, comedi_devconfig * it)
++static int ni_E_init(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned j;
+diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c
+index c3dad5937e05..9822f5e70229 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_cs.c
++++ b/drivers/staging/comedi/drivers/ni_mio_cs.c
+@@ -225,7 +225,7 @@ static uint16_t mio_cs_win_in(struct comedi_device * dev, int addr)
+ 	return ret;
+ }
+ 
+-static int mio_cs_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int mio_cs_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int mio_cs_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_ni_mio_cs = {
+       driver_name:"ni_mio_cs",
+@@ -401,7 +401,7 @@ static void mio_cs_config(struct pcmcia_device *link)
+ 	link->dev_node = &dev_node;
+ }
+ 
+-static int mio_cs_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int mio_cs_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct pcmcia_device *link;
+ 	unsigned int irq;
+diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
+index d7cdb38d5097..339f059bab8e 100644
+--- a/drivers/staging/comedi/drivers/ni_pcidio.c
++++ b/drivers/staging/comedi/drivers/ni_pcidio.c
+@@ -287,7 +287,7 @@ enum FPGA_Control_Bits {
+ #define IntEn (TransferReady|CountExpired|Waited|PrimaryTC|SecondaryTC)
+ #endif
+ 
+-static int nidio_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int nidio_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int nidio_detach(struct comedi_device * dev);
+ static int ni_pcidio_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ 
+@@ -1149,7 +1149,7 @@ static int pci_6534_upload_firmware(struct comedi_device * dev, int options[])
+ 	return 0;
+ }
+ 
+-static int nidio_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int nidio_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
+index f67fa6dec22a..3a2aba7c8dd3 100644
+--- a/drivers/staging/comedi/drivers/ni_pcimio.c
++++ b/drivers/staging/comedi/drivers/ni_pcimio.c
+@@ -1207,7 +1207,7 @@ static const ni_board ni_boards[] = {
+ 
+ #define n_pcimio_boards ((sizeof(ni_boards)/sizeof(ni_boards[0])))
+ 
+-static int pcimio_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcimio_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pcimio_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_pcimio = {
+ 	driver_name: DRV_NAME,
+@@ -1616,7 +1616,7 @@ static int pcimio_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int pcimio_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pcimio_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	int ret;
+ 
+diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c
+index 01ea3eb7554a..3e83b6cf693e 100644
+--- a/drivers/staging/comedi/drivers/pcl711.c
++++ b/drivers/staging/comedi/drivers/pcl711.c
+@@ -154,7 +154,7 @@ static const boardtype boardtypes[] = {
+ #define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+ #define this_board ((const boardtype *)dev->board_ptr)
+ 
+-static int pcl711_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcl711_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pcl711_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_pcl711 = {
+       driver_name:"pcl711",
+@@ -508,7 +508,7 @@ static int pcl711_detach(struct comedi_device * dev)
+ }
+ 
+ /*  Initialization */
+-static int pcl711_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pcl711_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	int ret;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c
+index 455117d043b5..108649f31c14 100644
+--- a/drivers/staging/comedi/drivers/pcl724.c
++++ b/drivers/staging/comedi/drivers/pcl724.c
+@@ -56,7 +56,7 @@ See the source for configuration details.
+ 
+ // #define PCL724_IRQ   1  /* no IRQ support now */
+ 
+-static int pcl724_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcl724_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pcl724_detach(struct comedi_device * dev);
+ 
+ typedef struct {
+@@ -122,7 +122,7 @@ static int subdev_8255mapped_cb(int dir, int port, int data,
+ 	}
+ }
+ 
+-static int pcl724_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pcl724_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	unsigned long iobase;
+ 	unsigned int iorange;
+diff --git a/drivers/staging/comedi/drivers/pcl725.c b/drivers/staging/comedi/drivers/pcl725.c
+index d9f7c24bbdb0..0766ba02bd03 100644
+--- a/drivers/staging/comedi/drivers/pcl725.c
++++ b/drivers/staging/comedi/drivers/pcl725.c
+@@ -20,7 +20,7 @@ Devices: [Advantech] PCL-725 (pcl725)
+ #define PCL725_DO 0
+ #define PCL725_DI 1
+ 
+-static int pcl725_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcl725_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pcl725_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_pcl725 = {
+       driver_name:"pcl725",
+@@ -59,7 +59,7 @@ static int pcl725_di_insn(struct comedi_device * dev, struct comedi_subdevice *
+ 	return 2;
+ }
+ 
+-static int pcl725_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pcl725_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c
+index f0c8b0af8d56..8f0425f280ec 100644
+--- a/drivers/staging/comedi/drivers/pcl726.c
++++ b/drivers/staging/comedi/drivers/pcl726.c
+@@ -111,7 +111,7 @@ static const struct comedi_lrange *const rangelist_728[] = {
+ 	&range_4_20mA, &range_0_20mA
+ };
+ 
+-static int pcl726_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcl726_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pcl726_detach(struct comedi_device * dev);
+ 
+ typedef struct {
+@@ -237,7 +237,7 @@ static int pcl726_do_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+ 	return 2;
+ }
+ 
+-static int pcl726_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pcl726_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c
+index 05d9f76e9336..f290e1195865 100644
+--- a/drivers/staging/comedi/drivers/pcl730.c
++++ b/drivers/staging/comedi/drivers/pcl730.c
+@@ -26,7 +26,7 @@ The ACL-7130 card have an 8254 timer/counter not supported by this driver.
+ #define PCL730_DIO_LO	2	/* TTL Digital I/O low byte (D0-D7) */
+ #define PCL730_DIO_HI	3	/* TTL Digital I/O high byte (D8-D15) */
+ 
+-static int pcl730_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcl730_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pcl730_detach(struct comedi_device * dev);
+ 
+ typedef struct {
+@@ -89,7 +89,7 @@ static int pcl730_di_insn(struct comedi_device * dev, struct comedi_subdevice *
+ 	return 2;
+ }
+ 
+-static int pcl730_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pcl730_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
+index 7b0a95c0e983..07a109839b42 100644
+--- a/drivers/staging/comedi/drivers/pcl812.c
++++ b/drivers/staging/comedi/drivers/pcl812.c
+@@ -292,7 +292,7 @@ static const struct comedi_lrange range_a821pgh_ai = { 4, {
+ 	}
+ };
+ 
+-static int pcl812_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcl812_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pcl812_detach(struct comedi_device * dev);
+ 
+ typedef struct {
+@@ -1262,7 +1262,7 @@ static void pcl812_reset(struct comedi_device * dev)
+ /*
+ ==============================================================================
+ */
+-static int pcl812_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pcl812_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	int ret, subdev;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
+index 9542d0e8e5fb..1d1137f602a0 100644
+--- a/drivers/staging/comedi/drivers/pcl816.c
++++ b/drivers/staging/comedi/drivers/pcl816.c
+@@ -146,7 +146,7 @@ static const boardtype boardtypes[] = {
+ #define devpriv ((pcl816_private *)dev->private)
+ #define this_board ((const boardtype *)dev->board_ptr)
+ 
+-static int pcl816_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcl816_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pcl816_detach(struct comedi_device * dev);
+ 
+ #ifdef unused
+@@ -1011,7 +1011,7 @@ static void free_resources(struct comedi_device * dev)
+    Initialization
+ 
+ */
+-static int pcl816_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pcl816_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	int ret;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
+index 4b315c090baf..fb5ddad18735 100644
+--- a/drivers/staging/comedi/drivers/pcl818.c
++++ b/drivers/staging/comedi/drivers/pcl818.c
+@@ -244,7 +244,7 @@ static const struct comedi_lrange range718_bipolar0_5 = { 1, {BIP_RANGE(0.5),} }
+ static const struct comedi_lrange range718_unipolar2 = { 1, {UNI_RANGE(2),} };
+ static const struct comedi_lrange range718_unipolar1 = { 1, {BIP_RANGE(1),} };
+ 
+-static int pcl818_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcl818_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pcl818_detach(struct comedi_device * dev);
+ 
+ #ifdef unused
+@@ -1675,7 +1675,7 @@ static void free_resources(struct comedi_device * dev)
+    Initialization
+ 
+ */
+-static int pcl818_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pcl818_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	int ret;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c
+index 08a63ebfa62e..ba4de985ff3b 100644
+--- a/drivers/staging/comedi/drivers/pcm3724.c
++++ b/drivers/staging/comedi/drivers/pcm3724.c
+@@ -62,7 +62,7 @@ Copy/pasted/hacked from pcm724.c
+ #define CR_A_MODE(a)	((a)<<5)
+ #define CR_CW		0x80
+ 
+-static int pcm3724_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcm3724_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pcm3724_detach(struct comedi_device * dev);
+ 
+ typedef struct {
+@@ -251,7 +251,7 @@ static int subdev_3724_insn_config(struct comedi_device * dev, struct comedi_sub
+ 	return 1;
+ }
+ 
+-static int pcm3724_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pcm3724_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	unsigned long iobase;
+ 	unsigned int iorange;
+diff --git a/drivers/staging/comedi/drivers/pcm3730.c b/drivers/staging/comedi/drivers/pcm3730.c
+index 63b961b32e2b..1de555fe645c 100644
+--- a/drivers/staging/comedi/drivers/pcm3730.c
++++ b/drivers/staging/comedi/drivers/pcm3730.c
+@@ -28,7 +28,7 @@ Configuration options:
+ #define PCM3730_DIB 2
+ #define PCM3730_DIC 3
+ 
+-static int pcm3730_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcm3730_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pcm3730_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_pcm3730 = {
+       driver_name:"pcm3730",
+@@ -63,7 +63,7 @@ static int pcm3730_di_insn_bits(struct comedi_device * dev, struct comedi_subdev
+ 	return 2;
+ }
+ 
+-static int pcm3730_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pcm3730_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c
+index fe3990983aeb..fc2a73d97c24 100644
+--- a/drivers/staging/comedi/drivers/pcmad.c
++++ b/drivers/staging/comedi/drivers/pcmad.c
+@@ -76,7 +76,7 @@ struct pcmad_priv_struct {
+ };
+ #define devpriv ((struct pcmad_priv_struct *)dev->private)
+ 
+-static int pcmad_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcmad_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pcmad_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_pcmad = {
+       driver_name:"pcmad",
+@@ -126,7 +126,7 @@ static int pcmad_ai_insn_read(struct comedi_device * dev, struct comedi_subdevic
+  * 2	0=single ended 1=differential
+  * 3	0=straight binary 1=two's comp
+  */
+-static int pcmad_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pcmad_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	int ret;
+ 	struct comedi_subdevice *s;
+diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c
+index d9f0b03486d0..ad7726853808 100644
+--- a/drivers/staging/comedi/drivers/pcmda12.c
++++ b/drivers/staging/comedi/drivers/pcmda12.c
+@@ -105,7 +105,7 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pcmda12_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcmda12_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pcmda12_detach(struct comedi_device * dev);
+ 
+ static void zero_chans(struct comedi_device * dev);
+@@ -149,7 +149,7 @@ static int ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pcmda12_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pcmda12_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
+index e44dee964aaa..85c205418703 100644
+--- a/drivers/staging/comedi/drivers/pcmmio.c
++++ b/drivers/staging/comedi/drivers/pcmmio.c
+@@ -264,7 +264,7 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pcmmio_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcmmio_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pcmmio_detach(struct comedi_device * dev);
+ 
+ static struct comedi_driver driver = {
+@@ -321,7 +321,7 @@ static void unlock_port(struct comedi_device * dev, int asic, int port);
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pcmmio_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pcmmio_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int sdev_no, chans_left, n_dio_subdevs, n_subdevs, port, asic,
+diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
+index fca574b60436..97ae34955d67 100644
+--- a/drivers/staging/comedi/drivers/pcmuio.c
++++ b/drivers/staging/comedi/drivers/pcmuio.c
+@@ -222,7 +222,7 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pcmuio_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcmuio_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int pcmuio_detach(struct comedi_device * dev);
+ 
+ static struct comedi_driver driver = {
+@@ -279,7 +279,7 @@ static void unlock_port(struct comedi_device * dev, int asic, int port);
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pcmuio_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int pcmuio_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int sdev_no, chans_left, n_subdevs, port, asic, thisasic_chanct = 0;
+diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c
+index 39a6f94f2e1e..8a0bf6854939 100644
+--- a/drivers/staging/comedi/drivers/poc.c
++++ b/drivers/staging/comedi/drivers/poc.c
+@@ -41,7 +41,7 @@ Configuration options:
+ 
+ #include 
+ 
+-static int poc_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int poc_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int poc_detach(struct comedi_device * dev);
+ static int readback_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_insn * insn, unsigned int * data);
+@@ -113,7 +113,7 @@ static struct comedi_driver driver_poc = {
+       offset:sizeof(boards[0]),
+ };
+ 
+-static int poc_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int poc_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+index 6494312cb169..f405341c95f6 100644
+--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
++++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+@@ -197,7 +197,7 @@ static const struct comedi_lrange range_daqp_ao = { 1, {BIP_RANGE(5)} };
+ 
+ /* comedi interface code */
+ 
+-static int daqp_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int daqp_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int daqp_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_daqp = {
+       driver_name:"quatech_daqp_cs",
+@@ -856,7 +856,7 @@ static int daqp_do_insn_write(struct comedi_device * dev, struct comedi_subdevic
+  * when it is inserted.
+  */
+ 
+-static int daqp_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int daqp_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	int ret;
+ 	local_info_t *local = dev_table[it->options[0]];
+diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
+index c919b8efdb3e..ca347f21d140 100644
+--- a/drivers/staging/comedi/drivers/rtd520.c
++++ b/drivers/staging/comedi/drivers/rtd520.c
+@@ -680,7 +680,7 @@ struct rtdPrivate {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int rtd_attach(struct comedi_device *dev, comedi_devconfig *it);
++static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int rtd_detach(struct comedi_device *dev);
+ 
+ static struct comedi_driver rtd520Driver = {
+@@ -715,7 +715,7 @@ static int rtd520_probe_fifo_depth(struct comedi_device *dev);
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int rtd_attach(struct comedi_device *dev, comedi_devconfig *it)
++static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {				/* board name and options flags */
+ 	struct comedi_subdevice *s;
+ 	struct pci_dev *pcidev;
+diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c
+index a93f5705bf19..bd579711a519 100644
+--- a/drivers/staging/comedi/drivers/rti800.c
++++ b/drivers/staging/comedi/drivers/rti800.c
+@@ -129,7 +129,7 @@ static const boardtype boardtypes[] = {
+ 
+ #define this_board ((const boardtype *)dev->board_ptr)
+ 
+-static int rti800_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int rti800_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int rti800_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_rti800 = {
+       driver_name:"rti800",
+@@ -307,7 +307,7 @@ static int rti800_do_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+    options[8] - dac1 coding
+  */
+ 
+-static int rti800_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int rti800_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	unsigned int irq;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c
+index 3249d08c3cea..656742be898a 100644
+--- a/drivers/staging/comedi/drivers/rti802.c
++++ b/drivers/staging/comedi/drivers/rti802.c
+@@ -47,7 +47,7 @@ Configuration Options:
+ #define RTI802_DATALOW 1
+ #define RTI802_DATAHIGH 2
+ 
+-static int rti802_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int rti802_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int rti802_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_rti802 = {
+       driver_name:"rti802",
+@@ -96,7 +96,7 @@ static int rti802_ao_insn_write(struct comedi_device * dev, struct comedi_subdev
+ 	return i;
+ }
+ 
+-static int rti802_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int rti802_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
+index b9b48b2f222d..e5ee54332e8a 100644
+--- a/drivers/staging/comedi/drivers/s526.c
++++ b/drivers/staging/comedi/drivers/s526.c
+@@ -215,7 +215,7 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int s526_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int s526_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int s526_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_s526 = {
+       driver_name:"s526",
+@@ -270,7 +270,7 @@ static int s526_dio_insn_config(struct comedi_device * dev, struct comedi_subdev
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int s526_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int s526_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int iobase;
+diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
+index 7385031f2b8b..3e6f1f0d99e5 100644
+--- a/drivers/staging/comedi/drivers/s626.c
++++ b/drivers/staging/comedi/drivers/s626.c
+@@ -118,7 +118,7 @@ static DEFINE_PCI_DEVICE_TABLE(s626_pci_table) = {
+ 
+ MODULE_DEVICE_TABLE(pci, s626_pci_table);
+ 
+-static int s626_attach(struct comedi_device *dev, comedi_devconfig *it);
++static int s626_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+ static int s626_detach(struct comedi_device *dev);
+ 
+ static struct comedi_driver driver_s626 = {
+@@ -485,7 +485,7 @@ static const struct comedi_lrange s626_range_table = { 2, {
+ 	}
+ };
+ 
+-static int s626_attach(struct comedi_device *dev, comedi_devconfig *it)
++static int s626_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ /*   uint8_t	PollList; */
+ /*   uint16_t	AdcData; */
+diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
+index 2271bd45fc0f..ca41baa37645 100644
+--- a/drivers/staging/comedi/drivers/serial2002.c
++++ b/drivers/staging/comedi/drivers/serial2002.c
+@@ -85,7 +85,7 @@ typedef struct {
+  */
+ #define devpriv ((serial2002_private *)dev->private)
+ 
+-static int serial2002_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int serial2002_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int serial2002_detach(struct comedi_device * dev);
+ struct comedi_driver driver_serial2002 = {
+       driver_name:"serial2002",
+@@ -776,7 +776,7 @@ static int serial2002_ei_rinsn(struct comedi_device * dev, struct comedi_subdevi
+ 	return n;
+ }
+ 
+-static int serial2002_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int serial2002_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 
+diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c
+index 2d25354b9acb..b8cdd6f8fc0e 100644
+--- a/drivers/staging/comedi/drivers/skel.c
++++ b/drivers/staging/comedi/drivers/skel.c
+@@ -151,7 +151,7 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int skel_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int skel_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int skel_detach(struct comedi_device * dev);
+ static struct comedi_driver driver_skel = {
+       driver_name:"dummy",
+@@ -201,7 +201,7 @@ static int skel_ns_to_timer(unsigned int *ns, int round);
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int skel_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int skel_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 
+diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c
+index cf3adf77ea12..8965df7a93cb 100644
+--- a/drivers/staging/comedi/drivers/ssv_dnp.c
++++ b/drivers/staging/comedi/drivers/ssv_dnp.c
+@@ -87,7 +87,7 @@ typedef struct {
+ /* In the following section we define the API of this driver.                */
+ /* ------------------------------------------------------------------------- */
+ 
+-static int dnp_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int dnp_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int dnp_detach(struct comedi_device * dev);
+ 
+ static struct comedi_driver driver_dnp = {
+@@ -115,7 +115,7 @@ static int dnp_dio_insn_config(struct comedi_device * dev,
+ /* dev->board_ptr contains that address.                                     */
+ /* ------------------------------------------------------------------------- */
+ 
+-static int dnp_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int dnp_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 
+ 	struct comedi_subdevice *s;
+diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c
+index 04b7ec65b63f..bf541d472ee0 100644
+--- a/drivers/staging/comedi/drivers/unioxx5.c
++++ b/drivers/staging/comedi/drivers/unioxx5.c
+@@ -80,7 +80,7 @@ typedef struct unioxx5_subd_priv {
+ 	unsigned char usp_prev_cn_val[3];	/* previous channel value */
+ } unioxx5_subd_priv;
+ 
+-static int unioxx5_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int unioxx5_attach(struct comedi_device * dev, struct comedi_devconfig * it);
+ static int unioxx5_subdev_write(struct comedi_device * dev, struct comedi_subdevice * subdev,
+ 	struct comedi_insn * insn, unsigned int * data);
+ static int unioxx5_subdev_read(struct comedi_device * dev, struct comedi_subdevice * subdev,
+@@ -111,7 +111,7 @@ static struct comedi_driver unioxx5_driver = {
+ 
+ COMEDI_INITCLEANUP(unioxx5_driver);
+ 
+-static int unioxx5_attach(struct comedi_device * dev, comedi_devconfig * it)
++static int unioxx5_attach(struct comedi_device * dev, struct comedi_devconfig * it)
+ {
+ 	int iobase, i, n_subd;
+ 	int id, num, ba;
+diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
+index 692df7a0e5eb..d0b59e98314b 100644
+--- a/drivers/staging/comedi/drivers/usbdux.c
++++ b/drivers/staging/comedi/drivers/usbdux.c
+@@ -2703,7 +2703,7 @@ static void usbduxsub_disconnect(struct usb_interface *intf)
+ }
+ 
+ /* is called when comedi-config is called */
+-static int usbdux_attach(struct comedi_device *dev, comedi_devconfig *it)
++static int usbdux_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int ret;
+ 	int index;
+diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c
+index d1ea6ed934ef..2fb64de3f86b 100644
+--- a/drivers/staging/comedi/drivers/usbduxfast.c
++++ b/drivers/staging/comedi/drivers/usbduxfast.c
+@@ -1715,7 +1715,7 @@ static void usbduxfastsub_disconnect(struct usb_interface *intf)
+ /*
+  * is called when comedi-config is called
+  */
+-static int usbduxfast_attach(struct comedi_device *dev, comedi_devconfig *it)
++static int usbduxfast_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+ {
+ 	int ret;
+ 	int index;

commit 063db04b8901c5cf84c552a5053748d183d34e61
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:06:15 2009 -0400
+
+    Staging: comedi: Remove comedi_devinfo typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
+index d2293d287516..8ed6f96442cf 100644
+--- a/drivers/staging/comedi/comedi.h
++++ b/drivers/staging/comedi/comedi.h
+@@ -292,7 +292,7 @@ enum comedi_support_level {
+ 
+ #define CIO 'd'
+ #define COMEDI_DEVCONFIG _IOW(CIO, 0, comedi_devconfig)
+-#define COMEDI_DEVINFO _IOR(CIO, 1, comedi_devinfo)
++#define COMEDI_DEVINFO _IOR(CIO, 1, struct comedi_devinfo)
+ #define COMEDI_SUBDINFO _IOR(CIO, 2, struct comedi_subdinfo)
+ #define COMEDI_CHANINFO _IOR(CIO, 3, struct comedi_chaninfo)
+ #define COMEDI_TRIG _IOWR(CIO, 4, comedi_trig)
+@@ -310,7 +310,6 @@ enum comedi_support_level {
+ 
+ /* structures */
+ 
+-typedef struct comedi_devinfo_struct comedi_devinfo;
+ typedef struct comedi_devconfig_struct comedi_devconfig;
+ typedef struct comedi_rangeinfo_struct comedi_rangeinfo;
+ typedef struct comedi_krange_struct comedi_krange;
+@@ -406,7 +405,7 @@ struct comedi_subdinfo {
+ 	unsigned int unused[8];
+ };
+ 
+-struct comedi_devinfo_struct {
++struct comedi_devinfo {
+ 	unsigned int version_code;
+ 	unsigned int n_subdevs;
+ 	char driver_name[COMEDI_NAMELEN];
+diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
+index bc1bc3df9197..2d99a4e33b58 100644
+--- a/drivers/staging/comedi/comedi_fops.c
++++ b/drivers/staging/comedi/comedi_fops.c
+@@ -71,7 +71,7 @@ static struct comedi_device_file_info
+ 
+ static int do_devconfig_ioctl(struct comedi_device *dev, comedi_devconfig *arg);
+ static int do_bufconfig_ioctl(struct comedi_device *dev, void *arg);
+-static int do_devinfo_ioctl(struct comedi_device *dev, comedi_devinfo *arg,
++static int do_devinfo_ioctl(struct comedi_device *dev, struct comedi_devinfo *arg,
+ 			    struct file *file);
+ static int do_subdinfo_ioctl(struct comedi_device *dev, struct comedi_subdinfo *arg,
+ 			     void *file);
+@@ -360,10 +360,10 @@ static int do_bufconfig_ioctl(struct comedi_device *dev, void *arg)
+ 		devinfo structure
+ 
+ */
+-static int do_devinfo_ioctl(struct comedi_device *dev, comedi_devinfo *arg,
++static int do_devinfo_ioctl(struct comedi_device *dev, struct comedi_devinfo *arg,
+ 			    struct file *file)
+ {
+-	comedi_devinfo devinfo;
++	struct comedi_devinfo devinfo;
+ 	const unsigned minor = iminor(file->f_dentry->d_inode);
+ 	struct comedi_device_file_info *dev_file_info =
+ 	    comedi_get_device_file_info(minor);
+@@ -390,7 +390,7 @@ static int do_devinfo_ioctl(struct comedi_device *dev, comedi_devinfo *arg,
+ 	else
+ 		devinfo.write_subdevice = -1;
+ 
+-	if (copy_to_user(arg, &devinfo, sizeof(comedi_devinfo)))
++	if (copy_to_user(arg, &devinfo, sizeof(struct comedi_devinfo)))
+ 		return -EFAULT;
+ 
+ 	return 0;

commit bd52efbbcc9f5d70c736b9b73c82aee149da1fe5
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:06:09 2009 -0400
+
+    Staging: comedi: Remove comedi_subdinfo typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
+index 22a082fd78ee..d2293d287516 100644
+--- a/drivers/staging/comedi/comedi.h
++++ b/drivers/staging/comedi/comedi.h
+@@ -293,7 +293,7 @@ enum comedi_support_level {
+ #define CIO 'd'
+ #define COMEDI_DEVCONFIG _IOW(CIO, 0, comedi_devconfig)
+ #define COMEDI_DEVINFO _IOR(CIO, 1, comedi_devinfo)
+-#define COMEDI_SUBDINFO _IOR(CIO, 2, comedi_subdinfo)
++#define COMEDI_SUBDINFO _IOR(CIO, 2, struct comedi_subdinfo)
+ #define COMEDI_CHANINFO _IOR(CIO, 3, struct comedi_chaninfo)
+ #define COMEDI_TRIG _IOWR(CIO, 4, comedi_trig)
+ #define COMEDI_LOCK _IO(CIO, 5)
+@@ -310,7 +310,6 @@ enum comedi_support_level {
+ 
+ /* structures */
+ 
+-typedef struct comedi_subdinfo_struct comedi_subdinfo;
+ typedef struct comedi_devinfo_struct comedi_devinfo;
+ typedef struct comedi_devconfig_struct comedi_devconfig;
+ typedef struct comedi_rangeinfo_struct comedi_rangeinfo;
+@@ -393,7 +392,7 @@ struct comedi_krange_struct {
+ };
+ 
+ 
+-struct comedi_subdinfo_struct {
++struct comedi_subdinfo {
+ 	unsigned int type;
+ 	unsigned int n_chan;
+ 	unsigned int subd_flags;
+diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
+index 1ffaf8c38f13..bc1bc3df9197 100644
+--- a/drivers/staging/comedi/comedi_fops.c
++++ b/drivers/staging/comedi/comedi_fops.c
+@@ -73,7 +73,7 @@ static int do_devconfig_ioctl(struct comedi_device *dev, comedi_devconfig *arg);
+ static int do_bufconfig_ioctl(struct comedi_device *dev, void *arg);
+ static int do_devinfo_ioctl(struct comedi_device *dev, comedi_devinfo *arg,
+ 			    struct file *file);
+-static int do_subdinfo_ioctl(struct comedi_device *dev, comedi_subdinfo *arg,
++static int do_subdinfo_ioctl(struct comedi_device *dev, struct comedi_subdinfo *arg,
+ 			     void *file);
+ static int do_chaninfo_ioctl(struct comedi_device *dev, struct comedi_chaninfo *arg);
+ static int do_bufinfo_ioctl(struct comedi_device *dev, void *arg);
+@@ -410,14 +410,14 @@ static int do_devinfo_ioctl(struct comedi_device *dev, comedi_devinfo *arg,
+ 		array of subdevice info structures at arg
+ 
+ */
+-static int do_subdinfo_ioctl(struct comedi_device *dev, comedi_subdinfo *arg,
++static int do_subdinfo_ioctl(struct comedi_device *dev, struct comedi_subdinfo *arg,
+ 			     void *file)
+ {
+ 	int ret, i;
+-	comedi_subdinfo *tmp, *us;
++	struct comedi_subdinfo *tmp, *us;
+ 	struct comedi_subdevice *s;
+ 
+-	tmp = kcalloc(dev->n_subdevices, sizeof(comedi_subdinfo), GFP_KERNEL);
++	tmp = kcalloc(dev->n_subdevices, sizeof(struct comedi_subdinfo), GFP_KERNEL);
+ 	if (!tmp)
+ 		return -ENOMEM;
+ 
+@@ -469,7 +469,7 @@ static int do_subdinfo_ioctl(struct comedi_device *dev, comedi_subdinfo *arg,
+ 	}
+ 
+ 	ret = copy_to_user(arg, tmp,
+-			   dev->n_subdevices * sizeof(comedi_subdinfo));
++			   dev->n_subdevices * sizeof(struct comedi_subdinfo));
+ 
+ 	kfree(tmp);
+ 

commit a18b416dc11ff9596ebf2012b1d15f485b951b28
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:06:04 2009 -0400
+
+    Staging: comedi: Remove comedi_chaninfo typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
+index a2dc749ef6b9..22a082fd78ee 100644
+--- a/drivers/staging/comedi/comedi.h
++++ b/drivers/staging/comedi/comedi.h
+@@ -294,7 +294,7 @@ enum comedi_support_level {
+ #define COMEDI_DEVCONFIG _IOW(CIO, 0, comedi_devconfig)
+ #define COMEDI_DEVINFO _IOR(CIO, 1, comedi_devinfo)
+ #define COMEDI_SUBDINFO _IOR(CIO, 2, comedi_subdinfo)
+-#define COMEDI_CHANINFO _IOR(CIO, 3, comedi_chaninfo)
++#define COMEDI_CHANINFO _IOR(CIO, 3, struct comedi_chaninfo)
+ #define COMEDI_TRIG _IOWR(CIO, 4, comedi_trig)
+ #define COMEDI_LOCK _IO(CIO, 5)
+ #define COMEDI_UNLOCK _IO(CIO, 6)
+@@ -310,7 +310,6 @@ enum comedi_support_level {
+ 
+ /* structures */
+ 
+-typedef struct comedi_chaninfo_struct comedi_chaninfo;
+ typedef struct comedi_subdinfo_struct comedi_subdinfo;
+ typedef struct comedi_devinfo_struct comedi_devinfo;
+ typedef struct comedi_devconfig_struct comedi_devconfig;
+@@ -374,7 +373,7 @@ struct comedi_cmd {
+ 	unsigned int data_len;
+ };
+ 
+-struct comedi_chaninfo_struct {
++struct comedi_chaninfo {
+ 	unsigned int subdev;
+ 	unsigned int *maxdata_list;
+ 	unsigned int *flaglist;
+diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
+index a70d71b8b0f0..1ffaf8c38f13 100644
+--- a/drivers/staging/comedi/comedi_fops.c
++++ b/drivers/staging/comedi/comedi_fops.c
+@@ -75,7 +75,7 @@ static int do_devinfo_ioctl(struct comedi_device *dev, comedi_devinfo *arg,
+ 			    struct file *file);
+ static int do_subdinfo_ioctl(struct comedi_device *dev, comedi_subdinfo *arg,
+ 			     void *file);
+-static int do_chaninfo_ioctl(struct comedi_device *dev, comedi_chaninfo *arg);
++static int do_chaninfo_ioctl(struct comedi_device *dev, struct comedi_chaninfo *arg);
+ static int do_bufinfo_ioctl(struct comedi_device *dev, void *arg);
+ static int do_cmd_ioctl(struct comedi_device *dev, void *arg, void *file);
+ static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg, void *file);
+@@ -490,12 +490,12 @@ static int do_subdinfo_ioctl(struct comedi_device *dev, comedi_subdinfo *arg,
+ 		arrays at elements of chaninfo structure
+ 
+ */
+-static int do_chaninfo_ioctl(struct comedi_device *dev, comedi_chaninfo *arg)
++static int do_chaninfo_ioctl(struct comedi_device *dev, struct comedi_chaninfo *arg)
+ {
+ 	struct comedi_subdevice *s;
+-	comedi_chaninfo it;
++	struct comedi_chaninfo it;
+ 
+-	if (copy_from_user(&it, arg, sizeof(comedi_chaninfo)))
++	if (copy_from_user(&it, arg, sizeof(struct comedi_chaninfo)))
+ 		return -EFAULT;
+ 
+ 	if (it.subdev >= dev->n_subdevices)

commit da613f4fabb43b8bc551bb874792e1f22a698696
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:05:59 2009 -0400
+
+    Staging: comedi: Remove comedi_insnlist typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
+index 3c99179f90ef..a2dc749ef6b9 100644
+--- a/drivers/staging/comedi/comedi.h
++++ b/drivers/staging/comedi/comedi.h
+@@ -302,7 +302,7 @@ enum comedi_support_level {
+ #define COMEDI_RANGEINFO _IOR(CIO, 8, comedi_rangeinfo)
+ #define COMEDI_CMD _IOR(CIO, 9, struct comedi_cmd)
+ #define COMEDI_CMDTEST _IOR(CIO, 10, struct comedi_cmd)
+-#define COMEDI_INSNLIST _IOR(CIO, 11, comedi_insnlist)
++#define COMEDI_INSNLIST _IOR(CIO, 11, struct comedi_insnlist)
+ #define COMEDI_INSN _IOR(CIO, 12, struct comedi_insn)
+ #define COMEDI_BUFCONFIG _IOR(CIO, 13, comedi_bufconfig)
+ #define COMEDI_BUFINFO _IOWR(CIO, 14, comedi_bufinfo)
+@@ -310,7 +310,6 @@ enum comedi_support_level {
+ 
+ /* structures */
+ 
+-typedef struct comedi_insnlist_struct comedi_insnlist;
+ typedef struct comedi_chaninfo_struct comedi_chaninfo;
+ typedef struct comedi_subdinfo_struct comedi_subdinfo;
+ typedef struct comedi_devinfo_struct comedi_devinfo;
+@@ -344,7 +343,7 @@ struct comedi_insn {
+ 	unsigned int unused[3];
+ };
+ 
+-struct comedi_insnlist_struct {
++struct comedi_insnlist {
+ 	unsigned int n_insns;
+ 	struct comedi_insn *insns;
+ };
+diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c
+index 62990905774d..f3cedb528e49 100644
+--- a/drivers/staging/comedi/comedi_compat32.c
++++ b/drivers/staging/comedi/comedi_compat32.c
+@@ -361,7 +361,7 @@ static int get_compat_insn(struct comedi_insn __user *insn,
+ static int compat_insnlist(struct file *file, unsigned long arg)
+ {
+ 	struct combined_insnlist {
+-		comedi_insnlist insnlist;
++		struct comedi_insnlist insnlist;
+ 		struct comedi_insn insn[1];
+ 	} __user *s;
+ 	struct comedi32_insnlist_struct __user *insnlist32;
+diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
+index d944c5e64eb4..a70d71b8b0f0 100644
+--- a/drivers/staging/comedi/comedi_fops.c
++++ b/drivers/staging/comedi/comedi_fops.c
+@@ -628,13 +628,13 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, unsig
+ #define MAX_SAMPLES 256
+ static int do_insnlist_ioctl(struct comedi_device *dev, void *arg, void *file)
+ {
+-	comedi_insnlist insnlist;
++	struct comedi_insnlist insnlist;
+ 	struct comedi_insn *insns = NULL;
+ 	unsigned int *data = NULL;
+ 	int i = 0;
+ 	int ret = 0;
+ 
+-	if (copy_from_user(&insnlist, arg, sizeof(comedi_insnlist)))
++	if (copy_from_user(&insnlist, arg, sizeof(struct comedi_insnlist)))
+ 		return -EFAULT;
+ 
+ 	data = kmalloc(sizeof(unsigned int) * MAX_SAMPLES, GFP_KERNEL);

commit 90035c0886b256d75bced13b3b3cea5234aff136
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:05:53 2009 -0400
+
+    Staging: comedi: Remove comedi_insn typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
+index 1057c9126b85..3c99179f90ef 100644
+--- a/drivers/staging/comedi/comedi.h
++++ b/drivers/staging/comedi/comedi.h
+@@ -303,14 +303,13 @@ enum comedi_support_level {
+ #define COMEDI_CMD _IOR(CIO, 9, struct comedi_cmd)
+ #define COMEDI_CMDTEST _IOR(CIO, 10, struct comedi_cmd)
+ #define COMEDI_INSNLIST _IOR(CIO, 11, comedi_insnlist)
+-#define COMEDI_INSN _IOR(CIO, 12, comedi_insn)
++#define COMEDI_INSN _IOR(CIO, 12, struct comedi_insn)
+ #define COMEDI_BUFCONFIG _IOR(CIO, 13, comedi_bufconfig)
+ #define COMEDI_BUFINFO _IOWR(CIO, 14, comedi_bufinfo)
+ #define COMEDI_POLL _IO(CIO, 15)
+ 
+ /* structures */
+ 
+-typedef struct comedi_insn_struct comedi_insn;
+ typedef struct comedi_insnlist_struct comedi_insnlist;
+ typedef struct comedi_chaninfo_struct comedi_chaninfo;
+ typedef struct comedi_subdinfo_struct comedi_subdinfo;
+@@ -336,7 +335,7 @@ struct comedi_trig {
+ 	unsigned int unused[3];
+ };
+ 
+-struct comedi_insn_struct {
++struct comedi_insn {
+ 	unsigned int insn;
+ 	unsigned int n;
+ 	unsigned int *data;
+@@ -347,7 +346,7 @@ struct comedi_insn_struct {
+ 
+ struct comedi_insnlist_struct {
+ 	unsigned int n_insns;
+-	comedi_insn *insns;
++	struct comedi_insn *insns;
+ };
+ 
+ struct comedi_cmd {
+diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c
+index 3eb1d5cdbe7a..62990905774d 100644
+--- a/drivers/staging/comedi/comedi_compat32.c
++++ b/drivers/staging/comedi/comedi_compat32.c
+@@ -91,7 +91,7 @@ struct comedi32_insn_struct {
+ 
+ struct comedi32_insnlist_struct {
+ 	unsigned int n_insns;
+-	compat_uptr_t insns;		/* 32-bit 'comedi_insn *' */
++	compat_uptr_t insns;		/* 32-bit 'struct comedi_insn *' */
+ };
+ 
+ /* Handle translated ioctl. */
+@@ -329,7 +329,7 @@ static int compat_cmdtest(struct file *file, unsigned long arg)
+ }
+ 
+ /* Copy 32-bit insn structure to native insn structure. */
+-static int get_compat_insn(comedi_insn __user *insn,
++static int get_compat_insn(struct comedi_insn __user *insn,
+ 		struct comedi32_insn_struct __user *insn32)
+ {
+ 	int err;
+@@ -362,7 +362,7 @@ static int compat_insnlist(struct file *file, unsigned long arg)
+ {
+ 	struct combined_insnlist {
+ 		comedi_insnlist insnlist;
+-		comedi_insn insn[1];
++		struct comedi_insn insn[1];
+ 	} __user *s;
+ 	struct comedi32_insnlist_struct __user *insnlist32;
+ 	struct comedi32_insn_struct __user *insn32;
+@@ -410,7 +410,7 @@ static int compat_insnlist(struct file *file, unsigned long arg)
+ /* Handle 32-bit COMEDI_INSN ioctl. */
+ static int compat_insn(struct file *file, unsigned long arg)
+ {
+-	comedi_insn __user *insn;
++	struct comedi_insn __user *insn;
+ 	struct comedi32_insn_struct __user *insn32;
+ 	int rc;
+ 
+diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
+index 1d83c0890b4e..d944c5e64eb4 100644
+--- a/drivers/staging/comedi/comedi_fops.c
++++ b/drivers/staging/comedi/comedi_fops.c
+@@ -607,7 +607,7 @@ static int do_bufinfo_ioctl(struct comedi_device *dev, void *arg)
+ 	return 0;
+ }
+ 
+-static int parse_insn(struct comedi_device *dev, comedi_insn *insn, unsigned int *data,
++static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data,
+ 		      void *file);
+ /*
+  * 	COMEDI_INSNLIST
+@@ -629,7 +629,7 @@ static int parse_insn(struct comedi_device *dev, comedi_insn *insn, unsigned int
+ static int do_insnlist_ioctl(struct comedi_device *dev, void *arg, void *file)
+ {
+ 	comedi_insnlist insnlist;
+-	comedi_insn *insns = NULL;
++	struct comedi_insn *insns = NULL;
+ 	unsigned int *data = NULL;
+ 	int i = 0;
+ 	int ret = 0;
+@@ -644,7 +644,7 @@ static int do_insnlist_ioctl(struct comedi_device *dev, void *arg, void *file)
+ 		goto error;
+ 	}
+ 
+-	insns = kmalloc(sizeof(comedi_insn) * insnlist.n_insns, GFP_KERNEL);
++	insns = kmalloc(sizeof(struct comedi_insn) * insnlist.n_insns, GFP_KERNEL);
+ 	if (!insns) {
+ 		DPRINTK("kmalloc failed\n");
+ 		ret = -ENOMEM;
+@@ -652,7 +652,7 @@ static int do_insnlist_ioctl(struct comedi_device *dev, void *arg, void *file)
+ 	}
+ 
+ 	if (copy_from_user(insns, insnlist.insns,
+-			   sizeof(comedi_insn) * insnlist.n_insns)) {
++			   sizeof(struct comedi_insn) * insnlist.n_insns)) {
+ 		DPRINTK("copy_from_user failed\n");
+ 		ret = -EFAULT;
+ 		goto error;
+@@ -696,7 +696,7 @@ static int do_insnlist_ioctl(struct comedi_device *dev, void *arg, void *file)
+ 	return i;
+ }
+ 
+-static int check_insn_config_length(comedi_insn *insn, unsigned int *data)
++static int check_insn_config_length(struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n < 1)
+ 		return -EINVAL;
+@@ -757,7 +757,7 @@ static int check_insn_config_length(comedi_insn *insn, unsigned int *data)
+ 	return -EINVAL;
+ }
+ 
+-static int parse_insn(struct comedi_device *dev, comedi_insn *insn, unsigned int *data,
++static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data,
+ 		      void *file)
+ {
+ 	struct comedi_subdevice *s;
+@@ -911,7 +911,7 @@ static int parse_insn(struct comedi_device *dev, comedi_insn *insn, unsigned int
+  * 		pointer to insn
+  *
+  * 	reads:
+- * 		comedi_insn struct at arg
++ * 		struct comedi_insn struct at arg
+  * 		data (for writes)
+  *
+  * 	writes:
+@@ -919,7 +919,7 @@ static int parse_insn(struct comedi_device *dev, comedi_insn *insn, unsigned int
+  */
+ static int do_insn_ioctl(struct comedi_device *dev, void *arg, void *file)
+ {
+-	comedi_insn insn;
++	struct comedi_insn insn;
+ 	unsigned int *data = NULL;
+ 	int ret = 0;
+ 
+@@ -929,7 +929,7 @@ static int do_insn_ioctl(struct comedi_device *dev, void *arg, void *file)
+ 		goto error;
+ 	}
+ 
+-	if (copy_from_user(&insn, arg, sizeof(comedi_insn))) {
++	if (copy_from_user(&insn, arg, sizeof(struct comedi_insn))) {
+ 		ret = -EFAULT;
+ 		goto error;
+ 	}
+diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
+index 8e60fdb33964..36dd82299c0a 100644
+--- a/drivers/staging/comedi/comedidev.h
++++ b/drivers/staging/comedi/comedidev.h
+@@ -155,13 +155,13 @@ struct comedi_subdevice {
+ 
+ 	unsigned int *chanlist;	/* driver-owned chanlist (not used) */
+ 
+-	int (*insn_read) (struct comedi_device *, struct comedi_subdevice *, comedi_insn *,
++	int (*insn_read) (struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *,
+ 		unsigned int *);
+-	int (*insn_write) (struct comedi_device *, struct comedi_subdevice *, comedi_insn *,
++	int (*insn_write) (struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *,
+ 		unsigned int *);
+-	int (*insn_bits) (struct comedi_device *, struct comedi_subdevice *, comedi_insn *,
++	int (*insn_bits) (struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *,
+ 		unsigned int *);
+-	int (*insn_config) (struct comedi_device *, struct comedi_subdevice *, comedi_insn *,
++	int (*insn_config) (struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *,
+ 		unsigned int *);
+ 
+ 	int (*do_cmd) (struct comedi_device *, struct comedi_subdevice *);
+@@ -381,7 +381,7 @@ void comedi_set_subdevice_runflags(struct comedi_subdevice *s, unsigned mask,
+ 	unsigned bits);
+ unsigned comedi_get_subdevice_runflags(struct comedi_subdevice *s);
+ int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data);
++	struct comedi_insn *insn, unsigned int *data);
+ 
+ /* range stuff */
+ 
+diff --git a/drivers/staging/comedi/comedilib.h b/drivers/staging/comedi/comedilib.h
+index e94f1b79d2c3..f27ef837c3d2 100644
+--- a/drivers/staging/comedi/comedilib.h
++++ b/drivers/staging/comedi/comedilib.h
+@@ -92,7 +92,7 @@ unsigned int comedi_get_maxdata(void *dev, unsigned int subdevice, unsigned
+ 	int chan);
+ int comedi_get_n_ranges(void *dev, unsigned int subdevice, unsigned int
+ 	chan);
+-int comedi_do_insn(void *dev, comedi_insn *insn);
++int comedi_do_insn(void *dev, struct comedi_insn *insn);
+ int comedi_poll(void *dev, unsigned int subdev);
+ 
+ /* DEPRECATED functions */
+@@ -165,7 +165,7 @@ unsigned int comedi_get_maxdata(unsigned int minor, unsigned int subdevice, unsi
+ 	int chan);
+ int comedi_get_n_ranges(unsigned int minor, unsigned int subdevice, unsigned int
+ 	chan);
+-int comedi_do_insn(unsigned int minor, comedi_insn *insn);
++int comedi_do_insn(unsigned int minor, struct comedi_insn *insn);
+ int comedi_poll(unsigned int minor, unsigned int subdev);
+ 
+ /* DEPRECATED functions */
+diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
+index 2d09a01c86c3..9728c7430f8b 100644
+--- a/drivers/staging/comedi/drivers.c
++++ b/drivers/staging/comedi/drivers.c
+@@ -49,7 +49,7 @@
+ 
+ static int postconfig(struct comedi_device *dev);
+ static int insn_rw_emulate_bits(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data);
++	struct comedi_insn *insn, unsigned int *data);
+ static void *comedi_recognize(struct comedi_driver * driv, const char *name);
+ static void comedi_report_boards(struct comedi_driver *driv);
+ static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s);
+@@ -337,15 +337,15 @@ static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s)
+ }
+ 
+ int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data)
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	return -EINVAL;
+ }
+ 
+ static int insn_rw_emulate_bits(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data)
++	struct comedi_insn *insn, unsigned int *data)
+ {
+-	comedi_insn new_insn;
++	struct comedi_insn new_insn;
+ 	int ret;
+ 	static const unsigned channels_per_bitfield = 32;
+ 
+diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c
+index 2b57041bfe9d..ec5f9167110b 100644
+--- a/drivers/staging/comedi/drivers/8255.c
++++ b/drivers/staging/comedi/drivers/8255.c
+@@ -144,7 +144,7 @@ static int subdev_8255_cb(int dir, int port, int data, unsigned long arg)
+ }
+ 
+ static int subdev_8255_insn(struct comedi_device *dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+ 		s->state &= ~data[0];
+@@ -169,7 +169,7 @@ static int subdev_8255_insn(struct comedi_device *dev, struct comedi_subdevice *
+ }
+ 
+ static int subdev_8255_insn_config(struct comedi_device *dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int mask;
+ 	unsigned int bits;
+diff --git a/drivers/staging/comedi/drivers/acl7225b.c b/drivers/staging/comedi/drivers/acl7225b.c
+index 235dcfea49d4..3e257cd9eb02 100644
+--- a/drivers/staging/comedi/drivers/acl7225b.c
++++ b/drivers/staging/comedi/drivers/acl7225b.c
+@@ -51,7 +51,7 @@ static struct comedi_driver driver_acl7225b = {
+ COMEDI_INITCLEANUP(driver_acl7225b);
+ 
+ static int acl7225b_do_insn(struct comedi_device *dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -72,7 +72,7 @@ static int acl7225b_do_insn(struct comedi_device *dev, struct comedi_subdevice *
+ }
+ 
+ static int acl7225b_di_insn(struct comedi_device *dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+index d69b87a1691a..c96aee09e1b6 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+@@ -33,7 +33,7 @@
+ |                                BYTE_   b_OutputLevel,                      |
+ |                                BYTE_   b_HardwareGateLevel)
+ INT i_InsnConfig_InitTimer(struct comedi_device *dev,struct comedi_subdevice *s,
+-	comedi_insn *insn,unsigned int *data)
++	struct comedi_insn *insn,unsigned int *data)
+ |
+ +----------------------------------------------------------------------------+
+ | Task              : Configure the Timer (b_TimerNbr) operating mode        |
+@@ -220,7 +220,7 @@ INT i_InsnConfig_InitTimer(struct comedi_device *dev,struct comedi_subdevice *s,
+ */
+ 
+ INT i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, struct comedi_subdevice * s,
+-				   comedi_insn * insn, unsigned int * data)
++				   struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	INT i_ReturnValue = 0;
+@@ -407,7 +407,7 @@ INT i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, struct comedi_sub
+ |                                BYTE_ b_TimerNbr,                           |
+ |                                BYTE_ b_InterruptEnable)
+ INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,struct comedi_subdevice *s,
+-	comedi_insn *insn,unsigned int *data)                |
++	struct comedi_insn *insn,unsigned int *data)                |
+ +----------------------------------------------------------------------------+
+ | Task              : Enable OR Disable the Timer (b_TimerNbr) from selected module     |
+ |                     (b_ModulNbr). You must calling the                     |
+@@ -450,7 +450,7 @@ i_ReturnValue=insn->n;
+ 
+ INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device * dev,
+ 					   struct comedi_subdevice * s,
+-					   comedi_insn * insn, unsigned int * data)
++					   struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_DummyRead;
+@@ -562,7 +562,7 @@ INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device * dev,
+ |                                        BYTE_     b_ModulNbr,               |
+ |                                        PULONG_ pul_TimerValueArray)
+ INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev,struct comedi_subdevice *s,
+-	comedi_insn *insn,unsigned int *data)        |
++	struct comedi_insn *insn,unsigned int *data)        |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the all timer values from selected timer        |
+ |                     module (b_ModulNbr).                                   |
+@@ -591,7 +591,7 @@ INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev,struct comedi_sub
+ */
+ 
+ INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, struct comedi_subdevice *s,
+-				     comedi_insn *insn, unsigned int *data)
++				     struct comedi_insn *insn, unsigned int *data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	BYTE b_ModulNbr, b_ReadType;
+@@ -669,7 +669,7 @@ INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, struct comedi_su
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     :INT i_APCI1710_InsnBitsTimer(struct comedi_device *dev,
+-struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)                   |
++struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ | Task              : Read write functions for Timer                                          |
+ +----------------------------------------------------------------------------+
+@@ -682,7 +682,7 @@ struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)
+ */
+ 
+ INT i_APCI1710_InsnBitsTimer(struct comedi_device * dev, struct comedi_subdevice * s,
+-			     comedi_insn * insn, unsigned int * data)
++			     struct comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_BitsType;
+ 	INT i_ReturnValue = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
+index 9785f925a1d4..4797c0b77a43 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
+@@ -35,20 +35,20 @@
+  * 82X54 TIMER INISIALISATION FUNCTION
+  */
+ INT i_APCI1710_InsnConfigInitTimer(struct comedi_device *dev, struct comedi_subdevice *s,
+-				   comedi_insn *insn, unsigned int *data);
++				   struct comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,
+ 					   struct comedi_subdevice *s,
+-					   comedi_insn *insn, unsigned int *data);
++					   struct comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * 82X54 READ FUNCTION
+  */
+ INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, struct comedi_subdevice *s,
+-				     comedi_insn *insn, unsigned int *data);
++				     struct comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnBitsTimer(struct comedi_device *dev, struct comedi_subdevice *s,
+-			     comedi_insn *insn, unsigned int *data);
++			     struct comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * 82X54 READ & WRITE FUNCTION
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+index 472e182a582a..1a54d3b2c694 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+@@ -132,7 +132,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ */
+ 
+ INT i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	ULONG ul_TimerValue = 0;
+@@ -791,7 +791,7 @@ INT i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_su
+ |                                                BYTE_ b_CycleMode,          |
+ |                                                BYTE_ b_InterruptEnable)
+ INT i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
+-struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)						 |
++struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)						 |
+ +----------------------------------------------------------------------------+
+ | Task              : Enable the chronometer from selected module            |
+ |                     (b_ModulNbr). You must calling the                     |
+@@ -841,7 +841,7 @@ struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)						 |
+ */
+ 
+ INT i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	BYTE b_ModulNbr, b_CycleMode, b_InterruptEnable, b_Action;
+@@ -1078,7 +1078,7 @@ INT i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     :INT	i_APCI1710_InsnReadChrono(struct comedi_device *dev,struct comedi_subdevice *s,
+-comedi_insn *insn,unsigned int *data)                   |
++struct comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  functions for Timer                                     |
+ +----------------------------------------------------------------------------+
+@@ -1091,7 +1091,7 @@ comedi_insn *insn,unsigned int *data)                   |
+ */
+ 
+ INT i_APCI1710_InsnReadChrono(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_ReadType;
+ 	INT i_ReturnValue = insn->n;
+@@ -1758,7 +1758,7 @@ INT i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,struct comedi_subdevice *s,
+-	comedi_insn *insn,unsigned int *data)                    |
++	struct comedi_insn *insn,unsigned int *data)                    |
+ +----------------------------------------------------------------------------+
+ | Task              : Sets the output witch has been passed with the         |
+ |                     parameter b_Channel. Setting an output means setting an|
+@@ -1877,7 +1877,7 @@ INT i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	BYTE b_ModulNbr, b_OutputChannel, b_InputChannel, b_IOType;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
+index 588f5735e24d..26b50cefee5a 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
+@@ -36,18 +36,18 @@
+  * CHRONOMETER INISIALISATION FUNCTION
+  */
+ INT i_APCI1710_InsnConfigInitChrono(struct comedi_device *dev, struct comedi_subdevice *s,
+-				    comedi_insn *insn, unsigned int *data);
++				    struct comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
+ 					    struct comedi_subdevice *s,
+-					    comedi_insn *insn,
++					    struct comedi_insn *insn,
+ 					    unsigned int *data);
+ 
+ /*
+  * CHRONOMETER READ FUNCTION
+  */
+ INT i_APCI1710_InsnReadChrono(struct comedi_device *dev, struct comedi_subdevice *s,
+-			      comedi_insn *insn, unsigned int *data);
++			      struct comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_GetChronoProgressStatus(struct comedi_device *dev,
+ 				       BYTE b_ModulNbr, PBYTE pb_ChronoStatus);
+@@ -70,5 +70,5 @@ INT i_APCI1710_ConvertChronoValue(struct comedi_device *dev,
+  * CHRONOMETER DIGITAL INPUT OUTPUT FUNCTION
+  */
+ INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,
+-				       struct comedi_subdevice *s, comedi_insn *insn,
++				       struct comedi_subdevice *s, struct comedi_insn *insn,
+ 				       unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+index 3b0c502de480..8be27aedaaf5 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+@@ -62,7 +62,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device *dev, |
+-|						struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)|
++|						struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)|
+ +----------------------------------------------------------------------------+
+ | Task              : Configure the digital I/O operating mode from selected |
+ |                     module  (b_ModulNbr). You must calling this function be|
+@@ -100,7 +100,7 @@ Activates and deactivates the digital output memory.
+ */
+ 
+ INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_ModulNbr, b_ChannelAMode, b_ChannelBMode;
+ 	BYTE b_MemoryOnOff, b_ConfigType;
+@@ -248,7 +248,7 @@ INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device * dev, struct comedi_sub
+ +----------------------------------------------------------------------------+
+ 
+ |INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device *dev,comedi_subdevice
+-*s,	comedi_insn *insn,unsigned int *data)
++*s,	struct comedi_insn *insn,unsigned int *data)
+ 
+ +----------------------------------------------------------------------------+
+ | Task              : Read the status from selected digital I/O digital input|
+@@ -294,7 +294,7 @@ INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device * dev, struct comedi_sub
+ //
+ //                                             PBYTE_  pb_ChannelStatus)
+ INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusReg;
+@@ -446,7 +446,7 @@ INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT i_APCI1710_InsnWriteDigitalIOChlOnOff(comedi_device
+-|*dev,struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)
++|*dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)
+ 
+ +----------------------------------------------------------------------------+
+ | Task              : Sets or resets the output witch has been passed with the         |
+@@ -482,7 +482,7 @@ INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device * dev,
+ //                                       BYTE_ b_ModulNbr,
+ //                                       BYTE_ b_OutputChannel)
+ INT i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_WriteValue = 0;
+@@ -677,7 +677,7 @@ INT i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ 
+ |INT i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device *dev,comedi_subdevice
+-	*s,	comedi_insn *insn,unsigned int *data)
++	*s,	struct comedi_insn *insn,unsigned int *data)
+ +----------------------------------------------------------------------------+
+ | Task              : write:
+ 					  Sets or resets one or several outputs from port.                 |
+@@ -729,7 +729,7 @@ INT i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device * dev,
+ //                                       BYTE_ b_ModulNbr,
+ //                                       BYTE_ b_PortValue)
+ INT i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_WriteValue = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h
+index 68a00d69e5f9..5ef157a55ca1 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h
+@@ -28,19 +28,19 @@
+  * DIGITAL I/O INISIALISATION FUNCTION
+  */
+ INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device *dev, struct comedi_subdevice *s,
+-				   comedi_insn *insn, unsigned int *data);
++				   struct comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * INPUT OUTPUT  FUNCTIONS
+  */
+ INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device *dev,
+ 					 struct comedi_subdevice *s,
+-					 comedi_insn *insn, unsigned int *data);
++					 struct comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device *dev,
+ 					  struct comedi_subdevice *s,
+-					  comedi_insn *insn, unsigned int *data);
++					  struct comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device *dev,
+ 					  struct comedi_subdevice *s,
+-					  comedi_insn *insn, unsigned int *data);
++					  struct comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+index 6939895bc401..1062f2fdec30 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+@@ -62,7 +62,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*
+ +----------------------------------------------------------------------------+
+ | INT	i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev,struct comedi_subdevice *s,
+-comedi_insn *insn,unsigned int *data)
++struct comedi_insn *insn,unsigned int *data)
+ 
+ +----------------------------------------------------------------------------+
+ | Task              : Configuration function for INC_CPT                             |
+@@ -76,7 +76,7 @@ comedi_insn *insn,unsigned int *data)
+ */
+ 
+ INT i_APCI1710_InsnConfigINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_ConfigType;
+ 	INT i_ReturnValue = 0;
+@@ -2003,7 +2003,7 @@ INT i_APCI1710_InitFrequencyMeasurement(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     :INT	i_APCI1710_InsnBitsINCCPT(struct comedi_device *dev,struct comedi_subdevice *s,
+-comedi_insn *insn,unsigned int *data)                   |
++struct comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ | Task              : Set & Clear Functions for INC_CPT                                          |
+ +----------------------------------------------------------------------------+
+@@ -2016,7 +2016,7 @@ comedi_insn *insn,unsigned int *data)                   |
+ */
+ 
+ INT i_APCI1710_InsnBitsINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_BitsType;
+ 	INT i_ReturnValue = 0;
+@@ -2940,7 +2940,7 @@ INT i_APCI1710_SetDigitalChlOff(struct comedi_device * dev, BYTE b_ModulNbr)
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     :INT	i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev,struct comedi_subdevice *s,
+-comedi_insn *insn,unsigned int *data)                   |
++struct comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ | Task              : Enable Disable functions for INC_CPT                                       |
+ +----------------------------------------------------------------------------+
+@@ -2952,7 +2952,7 @@ comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1710_InsnWriteINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_WriteType;
+ 	INT i_ReturnValue = 0;
+@@ -4038,7 +4038,7 @@ INT i_APCI1710_DisableFrequencyMeasurement(struct comedi_device * dev, BYTE b_Mo
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     :INT	i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev,struct comedi_subdevice *s,
+-comedi_insn *insn,unsigned int *data)                   |
++struct comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ | Task              : Read and Get functions for INC_CPT                                       |
+ +----------------------------------------------------------------------------+
+@@ -4050,7 +4050,7 @@ comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1710_InsnReadINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_ReadType;
+ 	INT i_ReturnValue = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
+index a4ffd8a1b15c..5153cf686658 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
+@@ -133,16 +133,16 @@
+ 
+ /************ Main Functions *************/
+ INT i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev, struct comedi_subdevice *s,
+-				comedi_insn *insn, unsigned int * data);
++				struct comedi_insn *insn, unsigned int * data);
+ 
+ INT i_APCI1710_InsnBitsINCCPT(struct comedi_device *dev, struct comedi_subdevice * s,
+-			      comedi_insn *insn, unsigned int * data);
++			      struct comedi_insn *insn, unsigned int * data);
+ 
+ INT i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev, struct comedi_subdevice * s,
+-			       comedi_insn *insn, unsigned int * data);
++			       struct comedi_insn *insn, unsigned int * data);
+ 
+ INT i_APCI1710_InsnReadINCCPT(struct comedi_device *dev, struct comedi_subdevice * s,
+-			      comedi_insn *insn, unsigned int * data);
++			      struct comedi_insn *insn, unsigned int * data);
+ 
+ /*********** Supplementary Functions********/
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+index 6f654a39ff7f..3ac6a264ef54 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+@@ -124,7 +124,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ */
+ 
+ INT i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_IntRegister;
+@@ -415,7 +415,7 @@ INT i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	BYTE b_ModulNbr;
+@@ -709,7 +709,7 @@ INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device * dev,
+    						 PBYTE_ pb_Status)
+ 						 */
+ INT i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusRegister;
+@@ -835,7 +835,7 @@ INT i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device * dev,
+ }
+ 
+ INT i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	data[0] = devpriv->s_InterruptParameters.
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h
+index bf84cb625ea7..28252873e862 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h
+@@ -23,11 +23,11 @@
+ 
+ INT i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device *dev,
+ 					  struct comedi_subdevice *s,
+-					  comedi_insn *insn, unsigned int *data);
++					  struct comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device *dev,
+ 						  struct comedi_subdevice *s,
+-						  comedi_insn *insn,
++						  struct comedi_insn *insn,
+ 						  unsigned int *data);
+ 
+ /*
+@@ -35,7 +35,7 @@ INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device *dev,
+  */
+ INT i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device *dev,
+ 					     struct comedi_subdevice *s,
+-					     comedi_insn *insn,
++					     struct comedi_insn *insn,
+ 					     unsigned int *data);
+ 
+ /*
+@@ -43,5 +43,5 @@ INT i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device *dev,
+  */
+ INT i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device *dev,
+ 					     struct comedi_subdevice *s,
+-					     comedi_insn *insn,
++					     struct comedi_insn *insn,
+ 					     unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+index 11927b503f45..5ddd092a656a 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+@@ -58,7 +58,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     :INT i_APCI1710_InsnConfigPWM(struct comedi_device *dev,
+-struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)                        |
++struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)                        |
+ +----------------------------------------------------------------------------+
+ | Task              : Pwm Init and Get Pwm Initialisation                    |
+ +----------------------------------------------------------------------------+
+@@ -71,7 +71,7 @@ struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)
+ */
+ 
+ INT i_APCI1710_InsnConfigPWM(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_ConfigType;
+ 	INT i_ReturnValue = 0;
+@@ -1671,7 +1671,7 @@ INT i_APCI1710_GetPWMInitialisation(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     :INT i_APCI1710_InsnWritePWM(struct comedi_device *dev,
+-struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)                        |
++struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)                        |
+ +----------------------------------------------------------------------------+
+ | Task              : Pwm Enable Disable and Set New Timing                  |
+ +----------------------------------------------------------------------------+
+@@ -1684,7 +1684,7 @@ struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)
+ */
+ 
+ INT i_APCI1710_InsnWritePWM(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_WriteType;
+ 	INT i_ReturnValue = 0;
+@@ -3461,7 +3461,7 @@ INT i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_InsnReadGetPWMStatus(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_Status;
+@@ -3562,7 +3562,7 @@ INT i_APCI1710_InsnReadGetPWMStatus(struct comedi_device * dev, struct comedi_su
+ }
+ 
+ INT i_APCI1710_InsnBitsReadPWMInterrupt(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->s_InterruptParameters.
+ 		s_FIFOInterruptParameters[devpriv->
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
+index 31a217842e4a..c1b7f4ca47c3 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
+@@ -27,7 +27,7 @@
+ #define APCI1710_PWM_NEWTIMING		2
+ 
+ INT i_APCI1710_InsnConfigPWM(struct comedi_device *dev, struct comedi_subdevice *s,
+-			     comedi_insn *insn, unsigned int *data);
++			     struct comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InitPWM(struct comedi_device *dev,
+ 		       BYTE b_ModulNbr,
+@@ -51,7 +51,7 @@ INT i_APCI1710_GetPWMInitialisation(struct comedi_device *dev,
+ 				    PBYTE pb_InterruptEnable, PBYTE pb_Enable);
+ 
+ INT i_APCI1710_InsnWritePWM(struct comedi_device *dev, struct comedi_subdevice *s,
+-			    comedi_insn *insn, unsigned int *data);
++			    struct comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_EnablePWM(struct comedi_device *dev,
+ 			 BYTE b_ModulNbr,
+@@ -69,8 +69,8 @@ INT i_APCI1710_SetNewPWMTiming(struct comedi_device *dev,
+ INT i_APCI1710_DisablePWM(struct comedi_device *dev, BYTE b_ModulNbr, BYTE b_PWM);
+ 
+ INT i_APCI1710_InsnReadGetPWMStatus(struct comedi_device *dev, struct comedi_subdevice *s,
+-				    comedi_insn *insn, unsigned int *data);
++				    struct comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnBitsReadPWMInterrupt(struct comedi_device *dev,
+ 					struct comedi_subdevice *s,
+-					comedi_insn *insn, unsigned int *data);
++					struct comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+index e67a2236cb60..bb6e1622e379 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+@@ -134,7 +134,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ */
+ 
+ INT i_APCI1710_InsnConfigInitSSI(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	UINT ui_TimerValue;
+@@ -363,7 +363,7 @@ INT i_APCI1710_InsnConfigInitSSI(struct comedi_device * dev, struct comedi_subde
+ |                                PULONG_ pul_Position,                       |
+ |                                PULONG_ pul_TurnCpt)
+  INT i_APCI1710_ReadSSIValue(struct comedi_device *dev,struct comedi_subdevice *s,
+-	comedi_insn *insn,unsigned int *data)                       |
++	struct comedi_insn *insn,unsigned int *data)                       |
+ +----------------------------------------------------------------------------+
+ | Task              :
+ 
+@@ -401,7 +401,7 @@ pul_Position	=	(PULONG) &data[0];
+ */
+ 
+ INT i_APCI1710_InsnReadSSIValue(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	BYTE b_Cpt;
+@@ -736,7 +736,7 @@ INT i_APCI1710_InsnReadSSIValue(struct comedi_device * dev, struct comedi_subdev
+ */
+ 
+ INT i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusReg;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h
+index 3fc70532729f..88daad1a3912 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h
+@@ -34,10 +34,10 @@
+  * SSI INISIALISATION FUNCTION
+  */
+ INT i_APCI1710_InsnConfigInitSSI(struct comedi_device *dev, struct comedi_subdevice *s,
+-				 comedi_insn *insn, unsigned int *data);
++				 struct comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnReadSSIValue(struct comedi_device *dev, struct comedi_subdevice *s,
+-				comedi_insn *insn, unsigned int *data);
++				struct comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev, struct comedi_subdevice *s,
+-				    comedi_insn *insn, unsigned int *data);
++				    struct comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+index 97655db21458..90316e10a3bd 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+@@ -131,7 +131,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ */
+ 
+ INT i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	ULONG ul_TimerValue = 0;
+@@ -988,7 +988,7 @@ INT i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_Status;
+@@ -1461,7 +1461,7 @@ INT i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_Status;
+@@ -1701,7 +1701,7 @@ INT i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_Status;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h
+index a2940f6d845f..c245d16207b8 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h
+@@ -37,21 +37,21 @@
+  */
+ INT i_APCI1710_InsnConfigInitTorCounter(struct comedi_device *dev,
+ 					struct comedi_subdevice *s,
+-					comedi_insn *insn, unsigned int *data);
++					struct comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device *dev,
+ 						struct comedi_subdevice *s,
+-						comedi_insn *insn,
++						struct comedi_insn *insn,
+ 						unsigned int *data);
+ 
+ INT i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device *dev,
+ 						   struct comedi_subdevice *s,
+-						   comedi_insn *insn,
++						   struct comedi_insn *insn,
+ 						   unsigned int *data);
+ /*
+  * TOR_COUNTER READ FUNCTION
+  */
+ INT i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device *dev,
+ 							   struct comedi_subdevice *s,
+-							   comedi_insn *insn,
++							   struct comedi_insn *insn,
+ 							   unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+index 61c1526c43fa..68b1d26bae13 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+@@ -101,7 +101,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ */
+ 
+ INT i_APCI1710_InsnConfigInitTTLIO(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	BYTE b_ModulNbr;
+@@ -407,7 +407,7 @@ APCI1710_TTL_READCHANNEL
+ */
+ 
+ INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusReg;
+@@ -634,7 +634,7 @@ INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device * dev, struct comedi_subde
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT i_APCI1710_InsnReadTTLIOAllPortValue(comedi_device
+-*dev,struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)              |
++*dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)              |
+ +----------------------------------------------------------------------------+
+ | Task              : Read the status from all digital input ports           |
+ |                     (port A, port B and port C) from selected TTL          |
+@@ -656,7 +656,7 @@ INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device * dev, struct comedi_subde
+ */
+ 
+ INT i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusReg;
+@@ -793,7 +793,7 @@ INT i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+ |                                BYTE_           b_ModulNbr,                 |
+ |                                BYTE_           b_OutputChannel)
+ INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,struct comedi_subdevice *s,
+-	comedi_insn *insn,unsigned int *data)           |
++	struct comedi_insn *insn,unsigned int *data)           |
+ +----------------------------------------------------------------------------+
+ | Task              : Sets or resets  the output witch has been passed with the         |
+ |                     parameter b_Channel. Setting an output means setting   |
+@@ -826,7 +826,7 @@ INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,struct comedi
+ */
+ 
+ INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusReg = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h
+index fe168db93ae6..00915ddf9218 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h
+@@ -25,20 +25,20 @@
+  * TTL INISIALISATION FUNCTION
+  */
+ INT i_APCI1710_InsnConfigInitTTLIO(struct comedi_device *dev, struct comedi_subdevice *s,
+-				   comedi_insn *insn, unsigned int *data);
++				   struct comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * TTL INPUT FUNCTION
+  */
+ INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device *dev, struct comedi_subdevice *s,
+-				 comedi_insn *insn, unsigned int *data);
++				 struct comedi_insn *insn, unsigned int *data);
+ INT i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
+ 					 struct comedi_subdevice *s,
+-					 comedi_insn *insn, unsigned int *data);
++					 struct comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * TTL OUTPUT FUNCTIONS
+  */
+ INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,
+ 					 struct comedi_subdevice *s,
+-					 comedi_insn *insn, unsigned int *data);
++					 struct comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+index 718c4be560f0..adb5deacd947 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+@@ -3030,14 +3030,14 @@ static irqreturn_t v_ADDI_Interrupt(int irq, void *d PT_REGS_ARG)
+ +----------------------------------------------------------------------------+
+ | Function name     :                                                        |
+ |INT i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev,struct comedi_subdevice *s,
+-							comedi_insn *insn,unsigned int *data)
++							struct comedi_insn *insn,unsigned int *data)
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              : Read 256 words from EEPROM          				     |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :(struct comedi_device *dev,struct comedi_subdevice *s,
+-			comedi_insn *insn,unsigned int *data) 						 |
++			struct comedi_insn *insn,unsigned int *data) 						 |
+ |                     														 |
+ |                                                 					         |
+ +----------------------------------------------------------------------------+
+@@ -3047,7 +3047,7 @@ static irqreturn_t v_ADDI_Interrupt(int irq, void *d PT_REGS_ARG)
+ */
+ 
+ static int i_ADDIDATA_InsnReadEeprom(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	WORD w_Data;
+ 	WORD w_Address;
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+index 2f3fc3c43060..2b01577683b5 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+@@ -119,19 +119,19 @@ typedef struct {
+ 	/* ANALOG INPUT */
+ 	int (*i_hwdrv_InsnConfigAnalogInput)(struct comedi_device *dev,
+ 					     struct comedi_subdevice *s,
+-					     comedi_insn *insn,
++					     struct comedi_insn *insn,
+ 					     unsigned int *data);
+ 	int (*i_hwdrv_InsnReadAnalogInput)(struct comedi_device *dev,
+ 					    struct comedi_subdevice *s,
+-					    comedi_insn *insn,
++					    struct comedi_insn *insn,
+ 					    unsigned int *data);
+ 	int (*i_hwdrv_InsnWriteAnalogInput)(struct comedi_device *dev,
+ 					    struct comedi_subdevice *s,
+-					    comedi_insn *insn,
++					    struct comedi_insn *insn,
+ 					    unsigned int *data);
+ 	int (*i_hwdrv_InsnBitsAnalogInput)(struct comedi_device *dev,
+ 					   struct comedi_subdevice *s,
+-					   comedi_insn *insn,
++					   struct comedi_insn *insn,
+ 					   unsigned int *data);
+ 	int (*i_hwdrv_CommandTestAnalogInput)(struct comedi_device *dev,
+ 					      struct comedi_subdevice *s,
+@@ -144,78 +144,78 @@ typedef struct {
+ 	/* Analog Output */
+ 	int (*i_hwdrv_InsnConfigAnalogOutput)(struct comedi_device *dev,
+ 					      struct comedi_subdevice *s,
+-					      comedi_insn *insn,
++					      struct comedi_insn *insn,
+ 					      unsigned int *data);
+ 	int (*i_hwdrv_InsnWriteAnalogOutput)(struct comedi_device *dev,
+ 					     struct comedi_subdevice *s,
+-					     comedi_insn *insn,
++					     struct comedi_insn *insn,
+ 					     unsigned int *data);
+ 	int (*i_hwdrv_InsnBitsAnalogOutput)(struct comedi_device *dev,
+ 					    struct comedi_subdevice *s,
+-					    comedi_insn *insn,
++					    struct comedi_insn *insn,
+ 					    unsigned int *data);
+ 
+ 	/* Digital Input */
+ 	int (*i_hwdrv_InsnConfigDigitalInput) (struct comedi_device *dev,
+ 					       struct comedi_subdevice *s,
+-					       comedi_insn *insn,
++					       struct comedi_insn *insn,
+ 					       unsigned int *data);
+ 	int (*i_hwdrv_InsnReadDigitalInput) (struct comedi_device *dev,
+ 					     struct comedi_subdevice *s,
+-					     comedi_insn *insn,
++					     struct comedi_insn *insn,
+ 					     unsigned int *data);
+ 	int (*i_hwdrv_InsnWriteDigitalInput) (struct comedi_device *dev,
+ 					      struct comedi_subdevice *s,
+-					      comedi_insn *insn,
++					      struct comedi_insn *insn,
+ 					      unsigned int *data);
+ 	int (*i_hwdrv_InsnBitsDigitalInput) (struct comedi_device *dev,
+ 					     struct comedi_subdevice *s,
+-					     comedi_insn *insn,
++					     struct comedi_insn *insn,
+ 					     unsigned int *data);
+ 
+ 	/* Digital Output */
+ 	int (*i_hwdrv_InsnConfigDigitalOutput)(struct comedi_device *dev,
+ 					       struct comedi_subdevice *s,
+-					       comedi_insn *insn,
++					       struct comedi_insn *insn,
+ 					       unsigned int *data);
+ 	int (*i_hwdrv_InsnWriteDigitalOutput)(struct comedi_device *dev,
+ 					      struct comedi_subdevice *s,
+-					      comedi_insn *insn,
++					      struct comedi_insn *insn,
+ 					      unsigned int *data);
+ 	int (*i_hwdrv_InsnBitsDigitalOutput)(struct comedi_device *dev,
+ 					     struct comedi_subdevice *s,
+-					     comedi_insn *insn,
++					     struct comedi_insn *insn,
+ 					     unsigned int *data);
+ 	int (*i_hwdrv_InsnReadDigitalOutput)(struct comedi_device *dev,
+ 					     struct comedi_subdevice *s,
+-					     comedi_insn *insn,
++					     struct comedi_insn *insn,
+ 					     unsigned int *data);
+ 
+ 	/* TIMER */
+ 	int (*i_hwdrv_InsnConfigTimer)(struct comedi_device *dev,
+ 				       struct comedi_subdevice *s,
+-				       comedi_insn *insn, unsigned int *data);
++				       struct comedi_insn *insn, unsigned int *data);
+ 	int (*i_hwdrv_InsnWriteTimer)(struct comedi_device *dev,
+-				      struct comedi_subdevice *s, comedi_insn *insn,
++				      struct comedi_subdevice *s, struct comedi_insn *insn,
+ 				      unsigned int *data);
+ 	int (*i_hwdrv_InsnReadTimer)(struct comedi_device *dev, struct comedi_subdevice *s,
+-				     comedi_insn *insn, unsigned int *data);
++				     struct comedi_insn *insn, unsigned int *data);
+ 	int (*i_hwdrv_InsnBitsTimer)(struct comedi_device *dev, struct comedi_subdevice *s,
+-				     comedi_insn *insn, unsigned int *data);
++				     struct comedi_insn *insn, unsigned int *data);
+ 
+ 	/* TTL IO */
+ 	int (*i_hwdr_ConfigInitTTLIO)(struct comedi_device *dev,
+-				      struct comedi_subdevice *s, comedi_insn *insn,
++				      struct comedi_subdevice *s, struct comedi_insn *insn,
+ 				      unsigned int *data);
+ 	int (*i_hwdr_ReadTTLIOBits)(struct comedi_device *dev, struct comedi_subdevice *s,
+-				    comedi_insn *insn, unsigned int *data);
++				    struct comedi_insn *insn, unsigned int *data);
+ 	int (*i_hwdr_ReadTTLIOAllPortValue)(struct comedi_device *dev,
+ 					    struct comedi_subdevice *s,
+-					    comedi_insn *insn,
++					    struct comedi_insn *insn,
+ 					    unsigned int *data);
+ 	int (*i_hwdr_WriteTTLIOChlOnOff)(struct comedi_device *dev,
+ 					 struct comedi_subdevice *s,
+-					 comedi_insn *insn, unsigned int *data);
++					 struct comedi_insn *insn, unsigned int *data);
+ } boardtype;
+ 
+ //MODULE INFO STRUCTURE
+@@ -462,4 +462,4 @@ static int i_ADDI_Reset(struct comedi_device *dev);
+ 
+ static irqreturn_t v_ADDI_Interrupt(int irq, void *d PT_REGS_ARG);
+ static int i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev, struct comedi_subdevice *s,
+-				     comedi_insn *insn, unsigned int *data);
++				     struct comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
+index 360e9da4c999..e4527926c2df 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
+@@ -59,7 +59,7 @@ INT i_Flag = 1;
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI035_ConfigTimerWatchdog                      |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Timer , Counter or Watchdog             |
+ +----------------------------------------------------------------------------+
+@@ -110,7 +110,7 @@ INT i_Flag = 1;
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI035_ConfigTimerWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Status = 0;
+ 	UINT ui_Command = 0;
+@@ -255,7 +255,7 @@ INT i_APCI035_ConfigTimerWatchdog(struct comedi_device * dev, struct comedi_subd
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI035_StartStopWriteTimerWatchdog              |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Start / Stop The Selected Timer , or Watchdog  |
+ +----------------------------------------------------------------------------+
+@@ -279,7 +279,7 @@ INT i_APCI035_ConfigTimerWatchdog(struct comedi_device * dev, struct comedi_subd
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Command = 0;
+ 	INT i_Count = 0;
+@@ -368,7 +368,7 @@ INT i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI035_ReadTimerWatchdog                        |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Selected Timer , Counter or Watchdog          |
+ +----------------------------------------------------------------------------+
+@@ -392,7 +392,7 @@ INT i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI035_ReadTimerWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Status = 0;	// Status register
+ 	i_WatchdogNbr = insn->unused[0];
+@@ -428,13 +428,13 @@ INT i_APCI035_ReadTimerWatchdog(struct comedi_device * dev, struct comedi_subdev
+ +----------------------------------------------------------------------------+
+ | Function   Name   : INT i_APCI035_ConfigAnalogInput                        |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Analog Input Subdevice                  |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     struct comedi_subdevice *s     : Subdevice Pointer            |
+-|                     comedi_insn *insn       : Insn Structure Pointer       |
++|                     struct comedi_insn *insn       : Insn Structure Pointer       |
+ |                     unsigned int *data          : Data Pointer contains        |
+ |                                          configuration parameters as below |
+ |                     data[0]                  : Warning delay value
+@@ -448,7 +448,7 @@ INT i_APCI035_ReadTimerWatchdog(struct comedi_device * dev, struct comedi_subdev
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI035_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	devpriv->tsk_Current = current;
+ 	outl(0x200 | 0, devpriv->iobase + 128 + 0x4);
+@@ -467,7 +467,7 @@ INT i_APCI035_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subdev
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI035_ReadAnalogInput                          |
+ |			          (struct comedi_device *dev,struct comedi_subdevice *s,       |
+-|                     comedi_insn *insn,unsigned int *data)                      |
++|                     struct comedi_insn *insn,unsigned int *data)                      |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel			         |
+ +----------------------------------------------------------------------------+
+@@ -485,7 +485,7 @@ INT i_APCI035_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subdev
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI035_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_CommandRegister = 0;
+ /******************/
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
+index 01964823b34f..80d7c0d39aab 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
+@@ -102,19 +102,19 @@ struct comedi_lrange range_apci035_ai = { 8, {
+ /* TIMER */
+ /* timer value is passed as u seconds */
+ INT i_APCI035_ConfigTimerWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+-				  comedi_insn *insn, unsigned int *data);
++				  struct comedi_insn *insn, unsigned int *data);
+ INT i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device *dev,
+ 					  struct comedi_subdevice *s,
+-					  comedi_insn *insn, unsigned int *data);
++					  struct comedi_insn *insn, unsigned int *data);
+ INT i_APCI035_ReadTimerWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+-				comedi_insn *insn, unsigned int *data);
++				struct comedi_insn *insn, unsigned int *data);
+ 
+ /* Temperature Related Defines (Analog Input Subdevice) */
+ 
+ INT i_APCI035_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				comedi_insn *insn, unsigned int *data);
++				struct comedi_insn *insn, unsigned int *data);
+ INT i_APCI035_ReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+-			      comedi_insn *insn, unsigned int *data);
++			      struct comedi_insn *insn, unsigned int *data);
+ 
+ /* Interrupt */
+ static void v_APCI035_Interrupt(int irq, void *d);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+index d3f13eafb6f5..05ea0784d764 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+@@ -60,7 +60,7 @@ UINT ui_InterruptStatus = 0;
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1032_ConfigDigitalInput                      |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures the digital input Subdevice                 |
+ +----------------------------------------------------------------------------+
+@@ -85,7 +85,7 @@ UINT ui_InterruptStatus = 0;
+ */
+ 
+ INT i_APCI1032_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue;
+ 
+@@ -129,7 +129,7 @@ INT i_APCI1032_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subd
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1032_Read1DigitalInput                       |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the digital input                 |
+ +----------------------------------------------------------------------------+
+@@ -145,7 +145,7 @@ INT i_APCI1032_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subd
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1032_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue = 0;
+ 	UINT ui_Channel;
+@@ -167,7 +167,7 @@ INT i_APCI1032_Read1DigitalInput(struct comedi_device * dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1032_ReadMoreDigitalInput                    |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                     comedi_insn *insn,unsigned int *data)                      |
++|                     struct comedi_insn *insn,unsigned int *data)                      |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the Requested digital inputs      |
+ +----------------------------------------------------------------------------+
+@@ -184,7 +184,7 @@ INT i_APCI1032_Read1DigitalInput(struct comedi_device * dev, struct comedi_subde
+ */
+ 
+ INT i_APCI1032_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_PortValue = data[0];
+ 	UINT ui_Mask = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
+index f24704f99f81..d45707f3eaf2 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
+@@ -48,13 +48,13 @@
+ // for di read
+ 
+ INT i_APCI1032_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				  comedi_insn *insn, unsigned int *data);
++				  struct comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1032_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				 comedi_insn *insn, unsigned int *data);
++				 struct comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1032_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				    comedi_insn *insn, unsigned int *data);
++				    struct comedi_insn *insn, unsigned int *data);
+ 
+ // Interrupt functions.....
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+index 9806199e0d16..c9035ceaade4 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+@@ -62,7 +62,7 @@ int i_TimerCounter1Enabled = 0, i_TimerCounter2Enabled =
+   +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_ConfigDigitalInputEvent                 |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : An event can be generated for each port.               |
+ |                     The first event is related to the first 8 channels     |
+@@ -138,7 +138,7 @@ int i_TimerCounter1Enabled = 0, i_TimerCounter2Enabled =
+ */
+ 
+ INT i_APCI1500_ConfigDigitalInputEvent(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_PatternPolarity = 0, i_PatternTransition = 0, i_PatternMask = 0;
+ 	int i_MaxChannel = 0, i_Count = 0, i_EventMask = 0;
+@@ -501,7 +501,7 @@ INT i_APCI1500_ConfigDigitalInputEvent(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_StartStopInputEvent                     |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              :  Allows or disallows a port event                      |
+ +----------------------------------------------------------------------------+
+@@ -520,7 +520,7 @@ INT i_APCI1500_ConfigDigitalInputEvent(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI1500_StartStopInputEvent(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_Event1InterruptStatus = 0, i_Event2InterruptStatus =
+ 		0, i_RegValue;
+@@ -769,7 +769,7 @@ int i_APCI1500_StartStopInputEvent(struct comedi_device * dev, struct comedi_sub
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_Initialisation                          |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the digital input                 |
+ +----------------------------------------------------------------------------+
+@@ -785,7 +785,7 @@ int i_APCI1500_StartStopInputEvent(struct comedi_device * dev, struct comedi_sub
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1500_Initialisation(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_DummyRead = 0;
+     /******************/
+@@ -938,7 +938,7 @@ INT i_APCI1500_Initialisation(struct comedi_device * dev, struct comedi_subdevic
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_ReadMoreDigitalInput                    |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                     comedi_insn *insn,unsigned int *data)                      |
++|                     struct comedi_insn *insn,unsigned int *data)                      |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the Requested digital inputs      |
+ +----------------------------------------------------------------------------+
+@@ -958,7 +958,7 @@ INT i_APCI1500_Initialisation(struct comedi_device * dev, struct comedi_subdevic
+ */
+ 
+ INT i_APCI1500_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_PortValue = data[1];
+ 	UINT ui_Mask = 0;
+@@ -1015,7 +1015,7 @@ INT i_APCI1500_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_ConfigDigitalOutputErrorInterrupt
+-                      (struct comedi_device *dev,struct comedi_subdevice *s comedi_insn
++                      (struct comedi_device *dev,struct comedi_subdevice *s struct comedi_insn
+                       *insn,unsigned int *data)                                  |
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+@@ -1026,7 +1026,7 @@ INT i_APCI1500_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ |                     unsigned int *data         : Data Pointer contains         |
+ |                                          configuration parameters as below |
+ |                      struct comedi_subdevice *s,   :pointer to subdevice structure
+-                       comedi_insn *insn      :pointer to insn structure                                                                                                                |
++                       struct comedi_insn *insn      :pointer to insn structure                                                                                                                |
+ |					  data[0]  :1:Memory on                          |
+ |					            0:Memory off                         |
+                               data[1]  :1 Enable the voltage error interrupt
+@@ -1041,7 +1041,7 @@ INT i_APCI1500_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	devpriv->b_OutputMemoryStatus = data[0];
+ 	return insn->n;
+@@ -1051,7 +1051,7 @@ int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_WriteDigitalOutput                      |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes port value  To the selected port                |
+ +----------------------------------------------------------------------------+
+@@ -1068,7 +1068,7 @@ int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1500_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	static UINT ui_Temp = 0;
+ 	UINT ui_Temp1;
+@@ -1215,14 +1215,14 @@ INT i_APCI1500_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_ConfigCounterTimerWatchdog(comedi_device
+-                   *dev,struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)|
++                   *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)|
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Watchdog                                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      comedi_insn *insn      :pointer to insn structure      |
++                      struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data         : Data Pointer to read status                                                       data[0]                : 2     APCI1500_1_8_KHZ
+ |                                              1     APCI1500_3_6_KHZ        |
+ |                                              0     APCI1500_115_KHZ
+@@ -1262,7 +1262,7 @@ INT i_APCI1500_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ */
+ 
+ int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_TimerCounterMode, i_MasterConfiguration;
+ 
+@@ -1836,13 +1836,13 @@ int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_StartStopTriggerTimerCounterWatchdog      |
+ |				(struct comedi_device *dev,struct comedi_subdevice *s,
+-                         comedi_insn *insn,unsigned int *data);                  |
++                         struct comedi_insn *insn,unsigned int *data);                  |
+ +----------------------------------------------------------------------------+
+ | Task              : Start / Stop or trigger the timer counter or Watchdog  |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev     : Driver handle                 |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      comedi_insn *insn      :pointer to insn structure      |
++                      struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data         : Data Pointer to read status   |
+                       data[0]                : 0     Counter1/Timer1
+                                                1     Counter2/Timer2
+@@ -1861,7 +1861,7 @@ int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_CommandAndStatusValue;
+ 
+@@ -2160,14 +2160,14 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_ReadCounterTimerWatchdog                |
+-|			(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+                     unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Watchdog                                      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      comedi_insn *insn      :pointer to insn structure      |
++                      struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+                       data[0]                : 0     Counter1/Timer1
+                                                1     Counter2/Timer2
+@@ -2183,7 +2183,7 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+ */
+ 
+ int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_CommandAndStatusValue;
+ 	switch (data[0]) {
+@@ -2351,14 +2351,14 @@ int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int  i_APCI1500_ReadInterruptMask                      |
+-|			(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+                     unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read the interrupt mask                                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      comedi_insn *insn      :pointer to insn structure      |
++                      struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ 
+ 
+@@ -2371,7 +2371,7 @@ int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI1500_ReadInterruptMask(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = i_InterruptMask;
+ 	data[1] = i_InputChannel;
+@@ -2382,14 +2382,14 @@ int i_APCI1500_ReadInterruptMask(struct comedi_device * dev, struct comedi_subde
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int  i_APCI1500_ConfigureInterrupt                     |
+-|			(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+                     unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures the interrupt registers                     |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      comedi_insn *insn      :pointer to insn structure      |
++                      struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer                 |
+ 
+ 
+@@ -2402,7 +2402,7 @@ int i_APCI1500_ReadInterruptMask(struct comedi_device * dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI1500_ConfigureInterrupt(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Status;
+ 	int i_RegValue;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h
+index d824934370b1..5d960b40a6a8 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h
+@@ -117,49 +117,49 @@ enum {
+ 
+  /*----------DIGITAL INPUT----------------*/
+ static int i_APCI1500_Initialisation(struct comedi_device *dev, struct comedi_subdevice *s,
+-				     comedi_insn *insn, unsigned int *data);
++				     struct comedi_insn *insn, unsigned int *data);
+ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
+ 					      struct comedi_subdevice *s,
+-					      comedi_insn *insn,
++					      struct comedi_insn *insn,
+ 					      unsigned int *data);
+ 
+ static int i_APCI1500_StartStopInputEvent(struct comedi_device *dev,
+ 					  struct comedi_subdevice *s,
+-					  comedi_insn *insn, unsigned int *data);
++					  struct comedi_insn *insn, unsigned int *data);
+ static int i_APCI1500_ReadMoreDigitalInput(struct comedi_device *dev,
+ 					   struct comedi_subdevice *s,
+-					   comedi_insn *insn, unsigned int *data);
++					   struct comedi_insn *insn, unsigned int *data);
+ 
+ /*----------	DIGITAL OUTPUT------------*/
+ static int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device *dev,
+ 							struct comedi_subdevice *s,
+-							comedi_insn *insn,
++							struct comedi_insn *insn,
+ 							unsigned int *data);
+ static int i_APCI1500_WriteDigitalOutput(struct comedi_device *dev,
+ 					 struct comedi_subdevice *s,
+-					 comedi_insn *insn, unsigned int *data);
++					 struct comedi_insn *insn, unsigned int *data);
+ 
+ /*----------TIMER----------------*/
+ static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
+ 						 struct comedi_subdevice *s,
+-						 comedi_insn *insn,
++						 struct comedi_insn *insn,
+ 						 unsigned int *data);
+ static int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device *dev,
+ 							   struct comedi_subdevice *s,
+-							   comedi_insn *insn,
++							   struct comedi_insn *insn,
+ 							   unsigned int *data);
+ static int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device *dev,
+ 					       struct comedi_subdevice *s,
+-					       comedi_insn *insn,
++					       struct comedi_insn *insn,
+ 					       unsigned int *data);
+ static int i_APCI1500_ReadInterruptMask(struct comedi_device *dev,
+ 					struct comedi_subdevice *s,
+-					comedi_insn *insn, unsigned int *data);
++					struct comedi_insn *insn, unsigned int *data);
+ 
+ /*----------INTERRUPT HANDLER------*/
+ static void v_APCI1500_Interrupt(int irq, void *d);
+ static int i_APCI1500_ConfigureInterrupt(struct comedi_device *dev,
+ 					 struct comedi_subdevice *s,
+-					 comedi_insn *insn, unsigned int *data);
++					 struct comedi_insn *insn, unsigned int *data);
+ /*----------RESET---------------*/
+ static int i_APCI1500_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
+index 21dde69dad03..5ae9a93844e7 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
+@@ -57,13 +57,13 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_Read1DigitalInput                       |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the digital input                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |		       struct comedi_subdevice *s,   :pointer to subdevice structure
+-                       comedi_insn *insn      :pointer to insn structure     |
++                       struct comedi_insn *insn      :pointer to insn structure     |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -74,7 +74,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1516_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue = 0;
+ 	UINT ui_Channel;
+@@ -97,13 +97,13 @@ INT i_APCI1516_Read1DigitalInput(struct comedi_device * dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_ReadMoreDigitalInput                    |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                     comedi_insn *insn,unsigned int *data)                      |
++|                     struct comedi_insn *insn,unsigned int *data)                      |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the Requested digital inputs      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                      struct comedi_subdevice *s,   :pointer to subdevice structure
+-                       comedi_insn *insn      :pointer to insn structure     |
++                       struct comedi_insn *insn      :pointer to insn structure     |
+ |                      unsigned int *data         : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -115,7 +115,7 @@ INT i_APCI1516_Read1DigitalInput(struct comedi_device * dev, struct comedi_subde
+ */
+ 
+ INT i_APCI1516_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	UINT ui_PortValue = data[0];
+@@ -149,7 +149,7 @@ INT i_APCI1516_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_ConfigDigitalOutput (struct comedi_device *dev,
+-                    struct comedi_subdevice *s comedi_insn *insn,unsigned int *data)    |
++                    struct comedi_subdevice *s struct comedi_insn *insn,unsigned int *data)    |
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Digital Output Subdevice.               |
+@@ -158,7 +158,7 @@ INT i_APCI1516_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ |                     unsigned int *data         : Data Pointer contains         |
+ |                                          configuration parameters as below |
+ |                      struct comedi_subdevice *s,   :pointer to subdevice structure
+-                       comedi_insn *insn      :pointer to insn structure                                                           |
++                       struct comedi_insn *insn      :pointer to insn structure                                                           |
+ |					  data[0]  :1:Memory on                          |
+ |					            0:Memory off                         |
+ |										                             |
+@@ -172,7 +172,7 @@ INT i_APCI1516_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI1516_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	devpriv->b_OutputMemoryStatus = data[0];
+ 	return insn->n;
+@@ -181,14 +181,14 @@ int i_APCI1516_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_WriteDigitalOutput                      |
+-|			(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+                      unsigned int *data)                                         |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes port value  To the selected port                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      comedi_insn *insn      :pointer to insn structure      |
++                      struct comedi_insn *insn      :pointer to insn structure      |
+ |                    unsigned int *data           : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -200,7 +200,7 @@ int i_APCI1516_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ */
+ 
+ INT i_APCI1516_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp, ui_Temp1;
+ 	UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
+@@ -341,14 +341,14 @@ INT i_APCI1516_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_ReadDigitalOutput                       |
+-|			(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+                     unsigned int *data) 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      comedi_insn *insn      :pointer to insn structure      |
++                      struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -360,7 +360,7 @@ INT i_APCI1516_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ */
+ 
+ INT i_APCI1516_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	UINT ui_Temp;
+@@ -401,14 +401,14 @@ INT i_APCI1516_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_ConfigWatchdog(struct comedi_device *dev,
+-                      struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)  |
++                      struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)  |
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Watchdog                                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      comedi_insn *insn      :pointer to insn structure      |
++                      struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status                                                     |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -420,7 +420,7 @@ INT i_APCI1516_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ */
+ 
+ int i_APCI1516_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0] == 0) {
+ 		//Disable the watchdog
+@@ -448,13 +448,13 @@ int i_APCI1516_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevic
+     +----------------------------------------------------------------------------+
+     | Function   Name   : int i_APCI1516_StartStopWriteWatchdog                  |
+     |                           (struct comedi_device *dev,struct comedi_subdevice *s,
+-    comedi_insn *insn,unsigned int *data);                      |
++    struct comedi_insn *insn,unsigned int *data);                      |
+     +----------------------------------------------------------------------------+
+     | Task              : Start / Stop The Watchdog                              |
+     +----------------------------------------------------------------------------+
+     | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+     |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-    comedi_insn *insn      :pointer to insn structure      |
++    struct comedi_insn *insn      :pointer to insn structure      |
+     |                     unsigned int *data          : Data Pointer to read status  |
+     +----------------------------------------------------------------------------+
+     | Output Parameters :       --                                                                                                       |
+@@ -466,7 +466,7 @@ int i_APCI1516_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevic
+   */
+ 
+ int i_APCI1516_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+ 	case 0:		//stop the watchdog
+@@ -492,14 +492,14 @@ int i_APCI1516_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_ReadWatchdog                            |
+-|			(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+                     unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Watchdog                                      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      comedi_insn *insn      :pointer to insn structure      |
++                      struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -511,7 +511,7 @@ int i_APCI1516_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_
+ */
+ 
+ int i_APCI1516_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = inw(devpriv->i_IobaseAddon + APCI1516_WATCHDOG_STATUS) & 0x1;
+ 	return insn->n;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h
+index 8d857e7adc13..398baa04a163 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h
+@@ -39,26 +39,26 @@
+ 
+ //Digital Input
+ INT i_APCI1516_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				    comedi_insn *insn, unsigned int *data);
++				    struct comedi_insn *insn, unsigned int *data);
+ INT i_APCI1516_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				 comedi_insn *insn, unsigned int *data);
++				 struct comedi_insn *insn, unsigned int *data);
+ 
+ //Digital Output
+ int i_APCI1516_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				   comedi_insn *insn, unsigned int *data);
++				   struct comedi_insn *insn, unsigned int *data);
+ INT i_APCI1516_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				  comedi_insn *insn, unsigned int *data);
++				  struct comedi_insn *insn, unsigned int *data);
+ INT i_APCI1516_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				 comedi_insn *insn, unsigned int *data);
++				 struct comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+ // timer value is passed as u seconds
+ int i_APCI1516_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+-			      comedi_insn *insn, unsigned int *data);
++			      struct comedi_insn *insn, unsigned int *data);
+ int i_APCI1516_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+-				      comedi_insn *insn, unsigned int *data);
++				      struct comedi_insn *insn, unsigned int *data);
+ int i_APCI1516_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+-			    comedi_insn *insn, unsigned int *data);
++			    struct comedi_insn *insn, unsigned int *data);
+ 
+ //reset
+ INT i_APCI1516_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+index e45390f3f988..da69bee176e6 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+@@ -63,7 +63,7 @@ UINT ui_InterruptData, ui_Type;
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_ConfigDigitalInput                      |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures the digital input Subdevice                 |
+ +----------------------------------------------------------------------------+
+@@ -87,7 +87,7 @@ UINT ui_InterruptData, ui_Type;
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1564_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	devpriv->tsk_Current = current;
+    /*******************************/
+@@ -132,7 +132,7 @@ INT i_APCI1564_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subd
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_Read1DigitalInput                       |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the digital input                 |
+ +----------------------------------------------------------------------------+
+@@ -148,7 +148,7 @@ INT i_APCI1564_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subd
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1564_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue = 0;
+ 	UINT ui_Channel;
+@@ -172,7 +172,7 @@ INT i_APCI1564_Read1DigitalInput(struct comedi_device * dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_ReadMoreDigitalInput                    |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                     comedi_insn *insn,unsigned int *data)                      |
++|                     struct comedi_insn *insn,unsigned int *data)                      |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the Requested digital inputs      |
+ +----------------------------------------------------------------------------+
+@@ -188,7 +188,7 @@ INT i_APCI1564_Read1DigitalInput(struct comedi_device * dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1564_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_PortValue = data[0];
+ 	UINT ui_Mask = 0;
+@@ -234,7 +234,7 @@ INT i_APCI1564_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_ConfigDigitalOutput                     |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Digital Output Subdevice.               |
+ +----------------------------------------------------------------------------+
+@@ -256,7 +256,7 @@ INT i_APCI1564_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1564_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command = 0;
+ 
+@@ -297,7 +297,7 @@ INT i_APCI1564_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_WriteDigitalOutput                      |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes port value  To the selected port                |
+ +----------------------------------------------------------------------------+
+@@ -313,7 +313,7 @@ INT i_APCI1564_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1564_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp, ui_Temp1;
+ 	UINT ui_NoOfChannel;
+@@ -471,7 +471,7 @@ INT i_APCI1564_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_ReadDigitalOutput                       |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+@@ -487,7 +487,7 @@ INT i_APCI1564_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1564_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+ 	UINT ui_NoOfChannel;
+@@ -538,7 +538,7 @@ INT i_APCI1564_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_ConfigTimerCounterWatchdog              |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Timer , Counter or Watchdog             |
+ +----------------------------------------------------------------------------+
+@@ -565,7 +565,7 @@ INT i_APCI1564_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0;
+ 	devpriv->tsk_Current = current;
+@@ -696,7 +696,7 @@ INT i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_StartStopWriteTimerCounterWatchdog      |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Start / Stop The Selected Timer , Counter or Watchdog  |
+ +----------------------------------------------------------------------------+
+@@ -719,7 +719,7 @@ INT i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0;
+ 	if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+@@ -796,7 +796,7 @@ INT i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_ReadTimerCounterWatchdog                |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Selected Timer , Counter or Watchdog          |
+ +----------------------------------------------------------------------------+
+@@ -814,7 +814,7 @@ INT i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0;
+ 
+@@ -879,7 +879,7 @@ INT i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function   Name   :  int i_APCI1564_ReadInterruptStatus                    |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              :Reads the interrupt status register                     |
+ +----------------------------------------------------------------------------+
+@@ -893,7 +893,7 @@ INT i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device * dev,
+ */
+ 
+ int i_APCI1564_ReadInterruptStatus(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	*data = ui_Type;
+ 	return insn->n;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
+index ff094f043caf..2fbc8ce7b764 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
+@@ -83,34 +83,34 @@
+ //DI
+ // for di read
+ INT i_APCI1564_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				  comedi_insn *insn, unsigned int *data);
++				  struct comedi_insn *insn, unsigned int *data);
+ INT i_APCI1564_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				 comedi_insn *insn, unsigned int *data);
++				 struct comedi_insn *insn, unsigned int *data);
+ INT i_APCI1564_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				    comedi_insn *insn, unsigned int *data);
++				    struct comedi_insn *insn, unsigned int *data);
+ 
+ //DO
+ int i_APCI1564_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				   comedi_insn *insn, unsigned int *data);
++				   struct comedi_insn *insn, unsigned int *data);
+ INT i_APCI1564_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				  comedi_insn *insn, unsigned int *data);
++				  struct comedi_insn *insn, unsigned int *data);
+ INT i_APCI1564_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				 comedi_insn *insn, unsigned int *data);
++				 struct comedi_insn *insn, unsigned int *data);
+ int i_APCI1564_ReadInterruptStatus(struct comedi_device *dev, struct comedi_subdevice *s,
+-				   comedi_insn *insn, unsigned int *data);
++				   struct comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+ // timer value is passed as u seconds
+ INT i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev,
+ 					  struct comedi_subdevice *s,
+-					  comedi_insn *insn, unsigned int *data);
++					  struct comedi_insn *insn, unsigned int *data);
+ int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
+ 						  struct comedi_subdevice *s,
+-						  comedi_insn *insn,
++						  struct comedi_insn *insn,
+ 						  unsigned int *data);
+ int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device *dev,
+ 					struct comedi_subdevice *s,
+-					comedi_insn *insn, unsigned int *data);
++					struct comedi_insn *insn, unsigned int *data);
+ 
+ // INTERRUPT
+ static VOID v_APCI1564_Interrupt(int irq, void *d);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
+index 0cab42aa0bb8..906d635da6b2 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
+@@ -60,7 +60,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ | Function Name     : INT   i_APCI16XX_InsnConfigInitTTLIO                   |
+ |                          (struct comedi_device    *dev,                           |
+ |                           struct comedi_subdevice *s,                             |
+-|                           comedi_insn      *insn,                          |
++|                           struct comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+ | Task           APCI16XX_TTL_INIT (using defaults)   :                      |
+@@ -91,7 +91,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ */
+ 
+ int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Command = 0;
+@@ -253,7 +253,7 @@ int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ | Function Name     : INT     i_APCI16XX_InsnBitsReadTTLIO                   |
+ |                          (struct comedi_device    *dev,                           |
+ |                           struct comedi_subdevice *s,                             |
+-|                           comedi_insn      *insn,                          |
++|                           struct comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+ | Task              : Read the status from selected TTL digital input        |
+@@ -284,7 +284,7 @@ int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ */
+ 
+ int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Command = 0;
+@@ -413,7 +413,7 @@ int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device * dev,
+ | Function Name     : INT i_APCI16XX_InsnReadTTLIOAllPortValue               |
+ |                          (struct comedi_device    *dev,                           |
+ |                           struct comedi_subdevice *s,                             |
+-|                           comedi_insn      *insn,                          |
++|                           struct comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+ | Task              : Read the status from all digital input ports           |
+@@ -431,7 +431,7 @@ int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device * dev,
+ */
+ 
+ int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_Command = (BYTE) CR_AREF(insn->chanspec);
+ 	INT i_ReturnValue = insn->n;
+@@ -538,7 +538,7 @@ int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+ | Function Name     : INT     i_APCI16XX_InsnBitsWriteTTLIO                  |
+ |                          (struct comedi_device    *dev,                           |
+ |                           struct comedi_subdevice *s,                             |
+-|                           comedi_insn      *insn,                          |
++|                           struct comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+ | Task              : Set the state from selected TTL digital output         |
+@@ -571,7 +571,7 @@ int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+ */
+ 
+ int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Command = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h
+index 63ec520bb3a7..5bf91e13a035 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h
+@@ -63,7 +63,7 @@ static const struct comedi_lrange range_apci16xx_ttl = { 12,
+ */
+ 
+ int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device *dev,
+-				   struct comedi_subdevice *s, comedi_insn *insn,
++				   struct comedi_subdevice *s, struct comedi_insn *insn,
+ 				   unsigned int *data);
+ 
+ /*
+@@ -73,12 +73,12 @@ int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device *dev,
+ */
+ 
+ int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device *dev,
+-				 struct comedi_subdevice *s, comedi_insn *insn,
++				 struct comedi_subdevice *s, struct comedi_insn *insn,
+ 				 unsigned int *data);
+ 
+ int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
+ 					 struct comedi_subdevice *s,
+-					 comedi_insn *insn, unsigned int *data);
++					 struct comedi_insn *insn, unsigned int *data);
+ 
+ /*
+ +----------------------------------------------------------------------------+
+@@ -87,7 +87,7 @@ int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
+ */
+ 
+ int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device *dev,
+-				  struct comedi_subdevice *s, comedi_insn *insn,
++				  struct comedi_subdevice *s, struct comedi_insn *insn,
+ 				  unsigned int *data);
+ 
+ int i_APCI16XX_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
+index 6a692cf3fb13..31f55da39ea8 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
+@@ -57,7 +57,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2016_ConfigDigitalOutput                     |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Digital Output Subdevice.               |
+ +----------------------------------------------------------------------------+
+@@ -76,7 +76,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI2016_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if ((data[0] != 0) && (data[0] != 1)) {
+ 		comedi_error(dev,
+@@ -96,7 +96,7 @@ int i_APCI2016_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2016_WriteDigitalOutput                      |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes port value  To the selected port                |
+ +----------------------------------------------------------------------------+
+@@ -112,7 +112,7 @@ int i_APCI2016_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI2016_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_NoOfChannel;
+ 	UINT ui_Temp, ui_Temp1;
+@@ -251,7 +251,7 @@ int i_APCI2016_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2016_BitsDigitalOutput                       |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+@@ -267,7 +267,7 @@ int i_APCI2016_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI2016_BitsDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+ 	UINT ui_NoOfChannel;
+@@ -321,13 +321,13 @@ int i_APCI2016_BitsDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2016_ConfigWatchdog                          |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Watchdog                                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure |
+-|                     comedi_insn *insn      :pointer to insn structure      |
++|                     struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -338,7 +338,7 @@ int i_APCI2016_BitsDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI2016_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	if (data[0] == 0) {
+@@ -364,13 +364,13 @@ int i_APCI2016_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevic
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2016_StartStopWriteWatchdog                  |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Start / Stop The Watchdog                              |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure |
+-|                     comedi_insn *insn      :pointer to insn structure      |
++|                     struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -381,7 +381,7 @@ int i_APCI2016_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevic
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI2016_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	switch (data[0]) {
+@@ -410,13 +410,13 @@ int i_APCI2016_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2016_ReadWatchdog                            |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Watchdog                                      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure |
+-|                     comedi_insn *insn      :pointer to insn structure      |
++|                     struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -428,7 +428,7 @@ int i_APCI2016_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_
+ */
+ 
+ int i_APCI2016_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	udelay(5);
+ 	data[0] = inw(devpriv->i_IobaseAddon + APCI2016_WATCHDOG_STATUS) & 0x1;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
+index ca98f6a51675..b6a3a999c906 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
+@@ -41,25 +41,25 @@
+ 
+ //DO
+ int i_APCI2016_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				   comedi_insn *insn, unsigned int *data);
++				   struct comedi_insn *insn, unsigned int *data);
+ 
+ int i_APCI2016_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				  comedi_insn *insn, unsigned int *data);
++				  struct comedi_insn *insn, unsigned int *data);
+ 
+ int i_APCI2016_BitsDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				 comedi_insn *insn, unsigned int *data);
++				 struct comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+ // timer value is passed as u seconds
+ 
+ int i_APCI2016_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+-			      comedi_insn *insn, unsigned int *data);
++			      struct comedi_insn *insn, unsigned int *data);
+ 
+ int i_APCI2016_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+-				      comedi_insn *insn, unsigned int *data);
++				      struct comedi_insn *insn, unsigned int *data);
+ 
+ int i_APCI2016_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+-			    comedi_insn *insn, unsigned int *data);
++			    struct comedi_insn *insn, unsigned int *data);
+ 
+ // Interrupt functions.....
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
+index 067ee8679d3e..1347bc388f3e 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
+@@ -58,7 +58,7 @@ UINT ui_InterruptData, ui_Type;
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2032_ConfigDigitalOutput                     |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Digital Output Subdevice.               |
+ +----------------------------------------------------------------------------+
+@@ -80,7 +80,7 @@ UINT ui_InterruptData, ui_Type;
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI2032_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command = 0;
+ 	devpriv->tsk_Current = current;
+@@ -118,7 +118,7 @@ int i_APCI2032_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2032_WriteDigitalOutput                      |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes port value  To the selected port                |
+ +----------------------------------------------------------------------------+
+@@ -135,7 +135,7 @@ int i_APCI2032_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ */
+ 
+ INT i_APCI2032_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp, ui_Temp1;
+ 	UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
+@@ -297,7 +297,7 @@ INT i_APCI2032_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2032_ReadDigitalOutput                       |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+@@ -314,7 +314,7 @@ INT i_APCI2032_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ */
+ 
+ INT i_APCI2032_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+ 	UINT ui_NoOfChannel;
+@@ -363,14 +363,14 @@ INT i_APCI2032_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : INT i_APCI2032_ConfigWatchdog(comedi_device
+-                   *dev,struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)|
++                   *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)|
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Watchdog                                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      comedi_insn *insn      :pointer to insn structure      |
++                      struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status                                                                                                             |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -381,7 +381,7 @@ INT i_APCI2032_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI2032_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0] == 0) {
+ 		//Disable the watchdog
+@@ -404,13 +404,13 @@ INT i_APCI2032_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevic
+     +----------------------------------------------------------------------------+
+     | Function   Name   : int i_APCI2032_StartStopWriteWatchdog                  |
+     |                           (struct comedi_device *dev,struct comedi_subdevice *s,
+-    comedi_insn *insn,unsigned int *data);                      |
++    struct comedi_insn *insn,unsigned int *data);                      |
+     +----------------------------------------------------------------------------+
+     | Task              : Start / Stop The Watchdog                              |
+     +----------------------------------------------------------------------------+
+     | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+     |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-    comedi_insn *insn      :pointer to insn structure      |
++    struct comedi_insn *insn      :pointer to insn structure      |
+     |                     unsigned int *data          : Data Pointer to read status  |
+     +----------------------------------------------------------------------------+
+     | Output Parameters :       --                                                                                                       |
+@@ -422,7 +422,7 @@ INT i_APCI2032_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevic
+   */
+ 
+ int i_APCI2032_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+ 	case 0:		//stop the watchdog
+@@ -448,14 +448,14 @@ int i_APCI2032_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2032_ReadWatchdog                            |
+-|			(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+                     unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Watchdog                                      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      comedi_insn *insn      :pointer to insn structure      |
++                      struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -467,7 +467,7 @@ int i_APCI2032_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_
+ */
+ 
+ int i_APCI2032_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	data[0] =
+@@ -531,7 +531,7 @@ void v_APCI2032_Interrupt(int irq, void *d)
+ +----------------------------------------------------------------------------+
+ | Function   Name   :  int i_APCI2032_ReadInterruptStatus                    |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              :Reads the interrupt status register                     |
+ +----------------------------------------------------------------------------+
+@@ -545,7 +545,7 @@ void v_APCI2032_Interrupt(int irq, void *d)
+ */
+ 
+ int i_APCI2032_ReadInterruptStatus(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	*data = ui_Type;
+ 	return insn->n;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h
+index 3aab1d999315..55002e0288b5 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h
+@@ -56,22 +56,22 @@
+ 
+ //DO
+ int i_APCI2032_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				   comedi_insn *insn, unsigned int *data);
++				   struct comedi_insn *insn, unsigned int *data);
+ INT i_APCI2032_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				  comedi_insn *insn, unsigned int *data);
++				  struct comedi_insn *insn, unsigned int *data);
+ INT i_APCI2032_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				 comedi_insn *insn, unsigned int *data);
++				 struct comedi_insn *insn, unsigned int *data);
+ int i_APCI2032_ReadInterruptStatus(struct comedi_device *dev, struct comedi_subdevice *s,
+-				   comedi_insn *insn, unsigned int *data);
++				   struct comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+ // timer value is passed as u seconds
+ INT i_APCI2032_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+-			      comedi_insn *insn, unsigned int *data);
++			      struct comedi_insn *insn, unsigned int *data);
+ int i_APCI2032_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+-				      comedi_insn *insn, unsigned int *data);
++				      struct comedi_insn *insn, unsigned int *data);
+ int i_APCI2032_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+-			    comedi_insn *insn, unsigned int *data);
++			    struct comedi_insn *insn, unsigned int *data);
+ 
+ // Interrupt functions.....
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
+index 3f7dc9a67197..947e18ef3ab3 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
+@@ -57,13 +57,13 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_Read1DigitalInput                       |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the digital input                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |		       struct comedi_subdevice *s,   :pointer to subdevice structure
+-                       comedi_insn *insn      :pointer to insn structure     |
++                       struct comedi_insn *insn      :pointer to insn structure     |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -74,7 +74,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI2200_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue = 0;
+ 	UINT ui_Channel;
+@@ -95,13 +95,13 @@ INT i_APCI2200_Read1DigitalInput(struct comedi_device * dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_ReadMoreDigitalInput                    |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                     comedi_insn *insn,unsigned int *data)                      |
++|                     struct comedi_insn *insn,unsigned int *data)                      |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the Requested digital inputs      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                      struct comedi_subdevice *s,   :pointer to subdevice structure
+-                       comedi_insn *insn      :pointer to insn structure     |
++                       struct comedi_insn *insn      :pointer to insn structure     |
+ |                      unsigned int *data         : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -113,7 +113,7 @@ INT i_APCI2200_Read1DigitalInput(struct comedi_device * dev, struct comedi_subde
+ */
+ 
+ INT i_APCI2200_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	UINT ui_PortValue = data[0];
+@@ -147,7 +147,7 @@ INT i_APCI2200_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_ConfigDigitalOutput (struct comedi_device *dev,
+-                    struct comedi_subdevice *s comedi_insn *insn,unsigned int *data)    |
++                    struct comedi_subdevice *s struct comedi_insn *insn,unsigned int *data)    |
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Digital Output Subdevice.               |
+@@ -156,7 +156,7 @@ INT i_APCI2200_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ |                     unsigned int *data         : Data Pointer contains         |
+ |                                          configuration parameters as below |
+ |                      struct comedi_subdevice *s,   :pointer to subdevice structure
+-                       comedi_insn *insn      :pointer to insn structure                                                           |
++                       struct comedi_insn *insn      :pointer to insn structure                                                           |
+ |					  data[0]  :1:Memory on                          |
+ |					            0:Memory off                         |
+ |										                             |
+@@ -170,7 +170,7 @@ INT i_APCI2200_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_su
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI2200_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	devpriv->b_OutputMemoryStatus = data[0];
+ 	return insn->n;
+@@ -179,14 +179,14 @@ int i_APCI2200_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_WriteDigitalOutput                      |
+-|			(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+                      unsigned int *data)                                         |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes port value  To the selected port                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      comedi_insn *insn      :pointer to insn structure      |
++                      struct comedi_insn *insn      :pointer to insn structure      |
+ |                    unsigned int *data           : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -198,7 +198,7 @@ int i_APCI2200_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ */
+ 
+ INT i_APCI2200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp, ui_Temp1;
+ 	UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
+@@ -336,14 +336,14 @@ INT i_APCI2200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_ReadDigitalOutput                       |
+-|			(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+                     unsigned int *data) 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      comedi_insn *insn      :pointer to insn structure      |
++                      struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -355,7 +355,7 @@ INT i_APCI2200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ */
+ 
+ INT i_APCI2200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	UINT ui_Temp;
+@@ -400,14 +400,14 @@ INT i_APCI2200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_ConfigWatchdog(struct comedi_device *dev,
+-                      struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)  |
++                      struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)  |
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Watchdog                                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      comedi_insn *insn      :pointer to insn structure      |
++                      struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status                                                                                                             |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -419,7 +419,7 @@ INT i_APCI2200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ */
+ 
+ int i_APCI2200_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0] == 0) {
+ 		//Disable the watchdog
+@@ -447,13 +447,13 @@ int i_APCI2200_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevic
+     +----------------------------------------------------------------------------+
+     | Function   Name   : int i_APCI2200_StartStopWriteWatchdog                  |
+     |                           (struct comedi_device *dev,struct comedi_subdevice *s,
+-    comedi_insn *insn,unsigned int *data);                      |
++    struct comedi_insn *insn,unsigned int *data);                      |
+     +----------------------------------------------------------------------------+
+     | Task              : Start / Stop The Watchdog                              |
+     +----------------------------------------------------------------------------+
+     | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+     |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-    comedi_insn *insn      :pointer to insn structure      |
++    struct comedi_insn *insn      :pointer to insn structure      |
+     |                     unsigned int *data          : Data Pointer to read status  |
+     +----------------------------------------------------------------------------+
+     | Output Parameters :       --                                                                                                       |
+@@ -465,7 +465,7 @@ int i_APCI2200_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevic
+   */
+ 
+ int i_APCI2200_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+ 	case 0:		//stop the watchdog
+@@ -491,14 +491,14 @@ int i_APCI2200_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_ReadWatchdog                            |
+-|			(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+                     unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Watchdog                                      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+ |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+-                      comedi_insn *insn      :pointer to insn structure      |
++                      struct comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+@@ -510,7 +510,7 @@ int i_APCI2200_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_
+ */
+ 
+ int i_APCI2200_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] =
+ 		inw(devpriv->iobase + APCI2200_WATCHDOG +
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h
+index 778bea21dd63..0a115b4c44c9 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h
+@@ -37,25 +37,25 @@
+ 
+ //Digital Input
+ INT i_APCI2200_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				    comedi_insn *insn, unsigned int *data);
++				    struct comedi_insn *insn, unsigned int *data);
+ INT i_APCI2200_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				 comedi_insn *insn, unsigned int *data);
++				 struct comedi_insn *insn, unsigned int *data);
+ 
+ //Digital Output
+ int i_APCI2200_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				   comedi_insn *insn, unsigned int *data);
++				   struct comedi_insn *insn, unsigned int *data);
+ INT i_APCI2200_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				  comedi_insn *insn, unsigned int *data);
++				  struct comedi_insn *insn, unsigned int *data);
+ INT i_APCI2200_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				 comedi_insn *insn, unsigned int *data);
++				 struct comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+ int i_APCI2200_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+-			      comedi_insn *insn, unsigned int *data);
++			      struct comedi_insn *insn, unsigned int *data);
+ int i_APCI2200_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+-				      comedi_insn *insn, unsigned int *data);
++				      struct comedi_insn *insn, unsigned int *data);
+ int i_APCI2200_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+-			    comedi_insn *insn, unsigned int *data);
++			    struct comedi_insn *insn, unsigned int *data);
+ 
+ //reset
+ INT i_APCI2200_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+index 0bebf87c7b29..68eb8dfd5139 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+@@ -58,7 +58,7 @@ static UINT ui_Temp = 0;
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnConfigAnalogInput(struct comedi_device *dev,|
+-|  struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)					 |
++|  struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)					 |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+ | Task              : Calls card specific function  					     |
+@@ -66,7 +66,7 @@ static UINT ui_Temp = 0;
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev									 |
+ |                     struct comedi_subdevice *s									 |
+-|                     comedi_insn *insn                                      |
++|                     struct comedi_insn *insn                                      |
+ |                     unsigned int *data      					         		 |
+ +----------------------------------------------------------------------------+
+ | Return Value      :              					                         |
+@@ -75,7 +75,7 @@ static UINT ui_Temp = 0;
+ */
+ 
+ int i_APCI3120_InsnConfigAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT i;
+ 
+@@ -125,7 +125,7 @@ int i_APCI3120_InsnConfigAnalogInput(struct comedi_device * dev, struct comedi_s
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev,  |
+-|			struct comedi_subdevice *s,comedi_insn *insn, unsigned int *data)	 |
++|			struct comedi_subdevice *s,struct comedi_insn *insn, unsigned int *data)	 |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+ | Task              :  card specific function								 |
+@@ -137,7 +137,7 @@ int i_APCI3120_InsnConfigAnalogInput(struct comedi_device * dev, struct comedi_s
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev									 |
+ |                     struct comedi_subdevice *s									 |
+-|                     comedi_insn *insn                                      |
++|                     struct comedi_insn *insn                                      |
+ |                     unsigned int *data     									 |
+ +----------------------------------------------------------------------------+
+ | Return Value      :              					                         |
+@@ -146,7 +146,7 @@ int i_APCI3120_InsnConfigAnalogInput(struct comedi_device * dev, struct comedi_s
+ */
+ 
+ int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	USHORT us_ConvertTiming, us_TmpValue, i;
+ 	BYTE b_Tmp;
+@@ -1946,7 +1946,7 @@ void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnConfigTimer(struct comedi_device *dev,          |
+-|	struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data) 			     |
++|	struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) 			     |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              :Configure Timer 2  								     |
+@@ -1954,7 +1954,7 @@ void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev									 |
+ |                     struct comedi_subdevice *s									 |
+-|                     comedi_insn *insn                                      |
++|                     struct comedi_insn *insn                                      |
+ |                     unsigned int *data 										 |
+ |                     														 |
+ |                      data[0]= TIMER  configure as timer                    |
+@@ -1969,7 +1969,7 @@ void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device * dev,
+ */
+ 
+ int i_APCI3120_InsnConfigTimer(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	UINT ui_Timervalue2;
+@@ -2094,14 +2094,14 @@ int i_APCI3120_InsnConfigTimer(struct comedi_device * dev, struct comedi_subdevi
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnWriteTimer(struct comedi_device *dev,           |
+-|                    struct comedi_subdevice *s, comedi_insn *insn,unsigned int *data)  |
++|                    struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data)  |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+ | Task              :    To start and stop the timer		                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev									 |
+ |                     struct comedi_subdevice *s									 |
+-|                     comedi_insn *insn                                      |
++|                     struct comedi_insn *insn                                      |
+ |                     unsigned int *data                                         |
+ |                                                                            |
+ |				data[0] = 1 (start)                                  |
+@@ -2120,7 +2120,7 @@ int i_APCI3120_InsnConfigTimer(struct comedi_device * dev, struct comedi_subdevi
+ */
+ 
+ int i_APCI3120_InsnWriteTimer(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	UINT ui_Timervalue2 = 0;
+@@ -2285,7 +2285,7 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device * dev, struct comedi_subdevic
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     : int i_APCI3120_InsnReadTimer(struct comedi_device *dev,           |
+-|		struct comedi_subdevice *s,comedi_insn *insn, unsigned int *data) 		 |
++|		struct comedi_subdevice *s,struct comedi_insn *insn, unsigned int *data) 		 |
+ |                                        									 |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+@@ -2293,7 +2293,7 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device * dev, struct comedi_subdevic
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : 	struct comedi_device *dev									 |
+ |                     struct comedi_subdevice *s									 |
+-|                     comedi_insn *insn                                      |
++|                     struct comedi_insn *insn                                      |
+ |                     unsigned int *data 										 |
+ |                     														 |
+ +----------------------------------------------------------------------------+
+@@ -2306,7 +2306,7 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device * dev, struct comedi_subdevic
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI3120_InsnReadTimer(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_Tmp;
+ 	USHORT us_TmpValue, us_TmpValue_2, us_StatusValue;
+@@ -2362,7 +2362,7 @@ int i_APCI3120_InsnReadTimer(struct comedi_device * dev, struct comedi_subdevice
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev,     |
+-|			struct comedi_subdevice *s, comedi_insn *insn,unsigned int *data)   |
++|			struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data)   |
+ |                                        									 |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+@@ -2371,7 +2371,7 @@ int i_APCI3120_InsnReadTimer(struct comedi_device * dev, struct comedi_subdevice
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev									 |
+ |                     struct comedi_subdevice *s									 |
+-|                     comedi_insn *insn                                      |
++|                     struct comedi_insn *insn                                      |
+ |                     unsigned int *data 										 |
+ +----------------------------------------------------------------------------+
+ | Return Value      :              					                         |
+@@ -2381,7 +2381,7 @@ int i_APCI3120_InsnReadTimer(struct comedi_device * dev, struct comedi_subdevice
+ 
+ int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev,
+ 				    struct comedi_subdevice *s,
+-				    comedi_insn *insn,
++				    struct comedi_insn *insn,
+ 				    unsigned int *data)
+ {
+ 	UINT ui_Chan, ui_TmpValue;
+@@ -2407,7 +2407,7 @@ int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnBitsDigitalInput(struct comedi_device *dev, |
+-|struct comedi_subdevice *s, comedi_insn *insn,unsigned int *data)                      |
++|struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data)                      |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              : Reads the value of the Digital input Port i.e.4channels|
+@@ -2416,7 +2416,7 @@ int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev,
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev									 |
+ |                     struct comedi_subdevice *s									 |
+-|                     comedi_insn *insn                                      |
++|                     struct comedi_insn *insn                                      |
+ |                     unsigned int *data 										 |
+ +----------------------------------------------------------------------------+
+ | Return Value      :              					                         |
+@@ -2424,7 +2424,7 @@ int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev,
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI3120_InsnBitsDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue;
+ 	ui_TmpValue = (UINT) inw(devpriv->iobase + APCI3120_RD_STATUS);
+@@ -2446,7 +2446,7 @@ int i_APCI3120_InsnBitsDigitalInput(struct comedi_device * dev, struct comedi_su
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device    |
+-| *dev,struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)				 |
++| *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)				 |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+ | Task              :Configure the output memory ON or OFF				     |
+@@ -2454,7 +2454,7 @@ int i_APCI3120_InsnBitsDigitalInput(struct comedi_device * dev, struct comedi_su
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :struct comedi_device *dev									 	 |
+ |                     struct comedi_subdevice *s									 |
+-|                     comedi_insn *insn                                      |
++|                     struct comedi_insn *insn                                      |
+ |                     unsigned int *data 										 |
+ +----------------------------------------------------------------------------+
+ | Return Value      :              					                         |
+@@ -2463,7 +2463,7 @@ int i_APCI3120_InsnBitsDigitalInput(struct comedi_device * dev, struct comedi_su
+ */
+ 
+ int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	if ((data[0] != 0) && (data[0] != 1)) {
+@@ -2489,7 +2489,7 @@ int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device *dev,    |
+-|		struct comedi_subdevice *s, comedi_insn *insn,unsigned int *data) 		 |
++|		struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data) 		 |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              : write diatal output port							     |
+@@ -2497,7 +2497,7 @@ int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev									 |
+ |                     struct comedi_subdevice *s									 |
+-|                     comedi_insn *insn                                      |
++|                     struct comedi_insn *insn                                      |
+ |                     unsigned int *data 										 |
+                       data[0]     Value to be written
+                       data[1]    :1 Set digital o/p ON
+@@ -2510,7 +2510,7 @@ int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device * dev,
+ 
+ int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device * dev,
+ 				     struct comedi_subdevice *s,
+-				     comedi_insn *insn,
++				     struct comedi_insn *insn,
+ 				     unsigned int *data)
+ {
+ 	if ((data[0] > this_board->i_DoMaxdata) || (data[0] < 0)) {
+@@ -2542,7 +2542,7 @@ int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev,|
+-|struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data) 			             |
++|struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) 			             |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+ | Task              : Write digiatl output								     |
+@@ -2550,7 +2550,7 @@ int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev								 	 |
+ |                     struct comedi_subdevice *s									 |
+-|                     comedi_insn *insn                                      |
++|                     struct comedi_insn *insn                                      |
+ |                     unsigned int *data 										 |
+                       data[0]     Value to be written
+                       data[1]    :1 Set digital o/p ON
+@@ -2563,7 +2563,7 @@ int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device * dev,
+ 
+ int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev,
+ 				      struct comedi_subdevice *s,
+-				      comedi_insn *insn,
++				      struct comedi_insn *insn,
+ 				      unsigned int *data)
+ {
+ 
+@@ -2625,7 +2625,7 @@ int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev,|
+-|struct comedi_subdevice *s, comedi_insn *insn,unsigned int *data)			             |
++|struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data)			             |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              : Write  analog output   							     |
+@@ -2633,7 +2633,7 @@ int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev,
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev									 |
+ |                     struct comedi_subdevice *s									 |
+-|                     comedi_insn *insn                                      |
++|                     struct comedi_insn *insn                                      |
+ |                     unsigned int *data  										 |
+ +----------------------------------------------------------------------------+
+ | Return Value      :              					                         |
+@@ -2643,7 +2643,7 @@ int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev,
+ 
+ int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev,
+ 				     struct comedi_subdevice *s,
+-				     comedi_insn *insn,
++				     struct comedi_insn *insn,
+ 				     unsigned int *data)
+ {
+ 	UINT ui_Range, ui_Channel;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
+index 0fb31835a68b..59d5d87a845b 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
+@@ -199,41 +199,41 @@ void v_APCI3120_InterruptDma(int irq, void *d);
+ // TIMER
+ 
+ int i_APCI3120_InsnConfigTimer(struct comedi_device *dev, struct comedi_subdevice *s,
+-			       comedi_insn *insn, unsigned int *data);
++			       struct comedi_insn *insn, unsigned int *data);
+ int i_APCI3120_InsnWriteTimer(struct comedi_device *dev, struct comedi_subdevice *s,
+-			      comedi_insn *insn, unsigned int *data);
++			      struct comedi_insn *insn, unsigned int *data);
+ int i_APCI3120_InsnReadTimer(struct comedi_device *dev, struct comedi_subdevice *s,
+-			     comedi_insn *insn, unsigned int *data);
++			     struct comedi_insn *insn, unsigned int *data);
+ 
+ //DI
+ // for di read
+ 
+ int i_APCI3120_InsnBitsDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				    comedi_insn *insn, unsigned int *data);
++				    struct comedi_insn *insn, unsigned int *data);
+ int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				    comedi_insn *insn, unsigned int *data);
++				    struct comedi_insn *insn, unsigned int *data);
+ 
+ //DO
+ //int i_APCI3120_WriteDigitalOutput(struct comedi_device *dev, BYTE data);
+ int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device *dev,
+-				       struct comedi_subdevice *s, comedi_insn *insn,
++				       struct comedi_subdevice *s, struct comedi_insn *insn,
+ 				       unsigned int *data);
+ int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				     comedi_insn *insn, unsigned int *data);
++				     struct comedi_insn *insn, unsigned int *data);
+ int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				      comedi_insn *insn, unsigned int *data);
++				      struct comedi_insn *insn, unsigned int *data);
+ 
+ //AO
+ //int i_APCI3120_Write1AnalogValue(struct comedi_device *dev,UINT ui_Range,UINT ui_Channel,UINT data );
+ int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				     comedi_insn *insn, unsigned int *data);
++				     struct comedi_insn *insn, unsigned int *data);
+ 
+ //AI HArdware layer
+ 
+ int i_APCI3120_InsnConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				     comedi_insn *insn, unsigned int *data);
++				     struct comedi_insn *insn, unsigned int *data);
+ int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				   comedi_insn *insn, unsigned int *data);
++				   struct comedi_insn *insn, unsigned int *data);
+ int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				      struct comedi_cmd *cmd);
+ int i_APCI3120_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+index c7e42b54daf7..b4a900308b96 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+@@ -531,7 +531,7 @@ INT i_APCI3200_GetChannelCalibrationValue(struct comedi_device * dev,
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadDigitalInput                       |
+   |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-  |                      comedi_insn *insn,unsigned int *data)                     |
++  |                      struct comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              : Read  value  of the selected channel or port           |
+   +----------------------------------------------------------------------------+
+@@ -551,7 +551,7 @@ INT i_APCI3200_GetChannelCalibrationValue(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI3200_ReadDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp = 0;
+ 	UINT ui_NoOfChannel = 0;
+@@ -593,7 +593,7 @@ INT i_APCI3200_ReadDigitalInput(struct comedi_device * dev, struct comedi_subdev
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ConfigDigitalOutput                     |
+   |			  (struct comedi_device *dev,struct comedi_subdevice *s,				 |
+-  |                      comedi_insn *insn,unsigned int *data)                     |
++  |                      struct comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              : Configures The Digital Output Subdevice.               |
+   +----------------------------------------------------------------------------+
+@@ -609,7 +609,7 @@ INT i_APCI3200_ReadDigitalInput(struct comedi_device * dev, struct comedi_subdev
+   +----------------------------------------------------------------------------+
+ */
+ int i_APCI3200_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	if ((data[0] != 0) && (data[0] != 1)) {
+@@ -630,13 +630,13 @@ int i_APCI3200_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_WriteDigitalOutput                      |
+   |			  (struct comedi_device *dev,struct comedi_subdevice *s,				 |
+-  |                      comedi_insn *insn,unsigned int *data)                     |
++  |                      struct comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              : writes To the digital Output Subdevice                 |
+   +----------------------------------------------------------------------------+
+   | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+   |                     struct comedi_subdevice *s     : Subdevice Pointer            |
+-  |                     comedi_insn *insn       : Insn Structure Pointer       |
++  |                     struct comedi_insn *insn       : Insn Structure Pointer       |
+   |                     unsigned int *data          : Data Pointer contains        |
+   |                                          configuration parameters as below |
+   |                     data[0]             :Value to output
+@@ -654,7 +654,7 @@ int i_APCI3200_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+   +----------------------------------------------------------------------------+
+ */
+ INT i_APCI3200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp = 0, ui_Temp1 = 0;
+ 	UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
+@@ -747,7 +747,7 @@ INT i_APCI3200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadDigitalOutput                       |
+   |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-  |                      comedi_insn *insn,unsigned int *data)                     |
++  |                      struct comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              : Read  value  of the selected channel or port           |
+   +----------------------------------------------------------------------------+
+@@ -767,7 +767,7 @@ INT i_APCI3200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+   +----------------------------------------------------------------------------+
+ */
+ INT i_APCI3200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+ 	UINT ui_NoOfChannel;
+@@ -808,13 +808,13 @@ INT i_APCI3200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+   +----------------------------------------------------------------------------+
+   | Function   Name   : INT i_APCI3200_ConfigAnalogInput                       |
+   |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-  |                      comedi_insn *insn,unsigned int *data)                     |
++  |                      struct comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              : Configures The Analog Input Subdevice                  |
+   +----------------------------------------------------------------------------+
+   | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+   |                     struct comedi_subdevice *s     : Subdevice Pointer            |
+-  |                     comedi_insn *insn       : Insn Structure Pointer       |
++  |                     struct comedi_insn *insn       : Insn Structure Pointer       |
+   |                     unsigned int *data          : Data Pointer contains        |
+   |                                          configuration parameters as below |
+   |                                                                            |
+@@ -875,7 +875,7 @@ INT i_APCI3200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+   +----------------------------------------------------------------------------+
+ */
+ INT i_APCI3200_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	UINT ul_Config = 0, ul_Temp = 0;
+@@ -1335,7 +1335,7 @@ INT i_APCI3200_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subde
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadAnalogInput                         |
+   |			          (struct comedi_device *dev,struct comedi_subdevice *s,       |
+-  |                     comedi_insn *insn,unsigned int *data)                      |
++  |                     struct comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read  value  of the selected channel			         |
+   +----------------------------------------------------------------------------+
+@@ -1362,7 +1362,7 @@ INT i_APCI3200_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subde
+   +----------------------------------------------------------------------------+
+ */
+ INT i_APCI3200_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_DummyValue = 0;
+ 	int i_ConvertCJCCalibration;
+@@ -1634,7 +1634,7 @@ INT i_APCI3200_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevi
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_Read1AnalogInputChannel                 |
+   |			          (struct comedi_device *dev,struct comedi_subdevice *s,       |
+-  |                     comedi_insn *insn,unsigned int *data)                      |
++  |                     struct comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read  value  of the selected channel			         |
+   +----------------------------------------------------------------------------+
+@@ -1652,7 +1652,7 @@ INT i_APCI3200_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevi
+   +----------------------------------------------------------------------------+
+ */
+ INT i_APCI3200_Read1AnalogInputChannel(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_EOC = 0;
+ 	UINT ui_ChannelNo = 0;
+@@ -1760,7 +1760,7 @@ INT i_APCI3200_Read1AnalogInputChannel(struct comedi_device * dev,
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadCalibrationOffsetValue              |
+   |			          (struct comedi_device *dev,struct comedi_subdevice *s,       |
+-  |                     comedi_insn *insn,unsigned int *data)                      |
++  |                     struct comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read calibration offset  value  of the selected channel|
+   +----------------------------------------------------------------------------+
+@@ -1896,7 +1896,7 @@ int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device * dev, UINT * dat
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadCalibrationGainValue                |
+   |			          (struct comedi_device *dev,struct comedi_subdevice *s,       |
+-  |                     comedi_insn *insn,unsigned int *data)                      |
++  |                     struct comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read calibration gain  value  of the selected channel  |
+   +----------------------------------------------------------------------------+
+@@ -2031,7 +2031,7 @@ int i_APCI3200_ReadCalibrationGainValue(struct comedi_device * dev, UINT * data)
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadCJCValue                            |
+   |			          (struct comedi_device *dev,struct comedi_subdevice *s,       |
+-  |                     comedi_insn *insn,unsigned int *data)                      |
++  |                     struct comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read CJC  value  of the selected channel               |
+   +----------------------------------------------------------------------------+
+@@ -2151,7 +2151,7 @@ int i_APCI3200_ReadCJCValue(struct comedi_device * dev, unsigned int * data)
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadCJCCalOffset                        |
+   |			          (struct comedi_device *dev,struct comedi_subdevice *s,       |
+-  |                     comedi_insn *insn,unsigned int *data)                      |
++  |                     struct comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read CJC calibration offset  value  of the selected channel
+   +----------------------------------------------------------------------------+
+@@ -2266,7 +2266,7 @@ int i_APCI3200_ReadCJCCalOffset(struct comedi_device * dev, unsigned int * data)
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadCJCGainValue                        |
+   |			          (struct comedi_device *dev,struct comedi_subdevice *s,       |
+-  |                     comedi_insn *insn,unsigned int *data)                      |
++  |                     struct comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read CJC calibration gain value
+   +----------------------------------------------------------------------------+
+@@ -2376,13 +2376,13 @@ int i_APCI3200_ReadCJCCalGain(struct comedi_device * dev, unsigned int * data)
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_InsnBits_AnalogInput_Test               |
+   |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-  |                      comedi_insn *insn,unsigned int *data)                     |
++  |                      struct comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              : Tests the Selected Anlog Input Channel                 |
+   +----------------------------------------------------------------------------+
+   | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+   |                     struct comedi_subdevice *s     : Subdevice Pointer            |
+-  |                     comedi_insn *insn       : Insn Structure Pointer       |
++  |                     struct comedi_insn *insn       : Insn Structure Pointer       |
+   |                     unsigned int *data          : Data Pointer contains        |
+   |                                          configuration parameters as below |
+   |
+@@ -2405,7 +2405,7 @@ int i_APCI3200_ReadCJCCalGain(struct comedi_device * dev, unsigned int * data)
+ */
+ 
+ INT i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Configuration = 0;
+ 	INT i_Temp;		//,i_TimeUnit;
+@@ -2511,13 +2511,13 @@ INT i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device * dev,
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_InsnWriteReleaseAnalogInput             |
+   |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-  |                      comedi_insn *insn,unsigned int *data)                     |
++  |                      struct comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              :  Resets the channels                                                      |
+   +----------------------------------------------------------------------------+
+   | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+   |                     struct comedi_subdevice *s     : Subdevice Pointer            |
+-  |                     comedi_insn *insn       : Insn Structure Pointer       |
++  |                     struct comedi_insn *insn       : Insn Structure Pointer       |
+   |                     unsigned int *data          : Data Pointer
+   +----------------------------------------------------------------------------+
+   | Output Parameters :	--													 |
+@@ -2530,7 +2530,7 @@ INT i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	i_APCI3200_Reset(dev);
+ 	return insn->n;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+index 94d9cef4bce5..a6f57f55e79c 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+@@ -155,22 +155,22 @@ typedef struct {
+ //AI
+ 
+ INT i_APCI3200_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				 comedi_insn *insn, unsigned int *data);
++				 struct comedi_insn *insn, unsigned int *data);
+ INT i_APCI3200_ReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+-			       comedi_insn *insn, unsigned int *data);
++			       struct comedi_insn *insn, unsigned int *data);
+ INT i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device *dev,
+ 					   struct comedi_subdevice *s,
+-					   comedi_insn *insn, unsigned int *data);
++					   struct comedi_insn *insn, unsigned int *data);
+ INT i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device *dev,
+ 					 struct comedi_subdevice *s,
+-					 comedi_insn *insn, unsigned int *data);
++					 struct comedi_insn *insn, unsigned int *data);
+ INT i_APCI3200_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s);
+ INT i_APCI3200_InterruptHandleEos(struct comedi_device *dev);
+ INT i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				      struct comedi_cmd *cmd);
+ INT i_APCI3200_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s);
+ INT i_APCI3200_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				comedi_insn *insn, unsigned int *data);
++				struct comedi_insn *insn, unsigned int *data);
+ //Interrupt
+ void v_APCI3200_Interrupt(int irq, void *d);
+ int i_APCI3200_InterruptHandleEos(struct comedi_device *dev);
+@@ -182,6 +182,6 @@ int i_APCI3200_ReadCJCValue(struct comedi_device *dev, unsigned int *data);
+ int i_APCI3200_ReadCalibrationGainValue(struct comedi_device *dev, UINT *data);
+ int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device *dev, UINT *data);
+ int i_APCI3200_Read1AnalogInputChannel(struct comedi_device *dev,
+-				       struct comedi_subdevice *s, comedi_insn *insn,
++				       struct comedi_subdevice *s, struct comedi_insn *insn,
+ 				       unsigned int *data);
+ int i_APCI3200_ReadCJCCalGain(struct comedi_device *dev, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
+index 2e4c8ad54db2..20391a91da03 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
+@@ -57,7 +57,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_ReadDigitalInput                    |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+@@ -74,7 +74,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ */
+ 
+ INT i_APCI3501_ReadDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+ 	UINT ui_NoOfChannel;
+@@ -100,7 +100,7 @@ INT i_APCI3501_ReadDigitalInput(struct comedi_device * dev, struct comedi_subdev
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_ConfigDigitalOutput                     |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Digital Output Subdevice.               |
+ +----------------------------------------------------------------------------+
+@@ -122,7 +122,7 @@ INT i_APCI3501_ReadDigitalInput(struct comedi_device * dev, struct comedi_subdev
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI3501_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	if ((data[0] != 0) && (data[0] != 1)) {
+@@ -143,13 +143,13 @@ int i_APCI3501_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_WriteDigitalOutput                      |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : writes To the digital Output Subdevice                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     struct comedi_subdevice *s     : Subdevice Pointer            |
+-|                     comedi_insn *insn       : Insn Structure Pointer       |
++|                     struct comedi_insn *insn       : Insn Structure Pointer       |
+ |                     unsigned int *data          : Data Pointer contains        |
+ |                                          configuration parameters as below |
+ |                                                                            |
+@@ -162,7 +162,7 @@ int i_APCI3501_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_sub
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI3501_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp, ui_Temp1;
+ 	UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
+@@ -233,7 +233,7 @@ INT i_APCI3501_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_ReadDigitalOutput                       |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+@@ -249,7 +249,7 @@ INT i_APCI3501_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subd
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI3501_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+ 	UINT ui_NoOfChannel;
+@@ -276,13 +276,13 @@ INT i_APCI3501_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_ConfigAnalogOutput                      |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Analog Output Subdevice                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     struct comedi_subdevice *s     : Subdevice Pointer            |
+-|                     comedi_insn *insn       : Insn Structure Pointer       |
++|                     struct comedi_insn *insn       : Insn Structure Pointer       |
+ |                     unsigned int *data          : Data Pointer contains        |
+ |                                          configuration parameters as below |
+ |                                                                            |
+@@ -299,7 +299,7 @@ INT i_APCI3501_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI3501_ConfigAnalogOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	outl(data[0],
+ 		devpriv->iobase + APCI3501_ANALOG_OUTPUT +
+@@ -317,13 +317,13 @@ INT i_APCI3501_ConfigAnalogOutput(struct comedi_device * dev, struct comedi_subd
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_WriteAnalogOutput                       |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes To the Selected Anlog Output Channel            |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     struct comedi_subdevice *s     : Subdevice Pointer            |
+-|                     comedi_insn *insn       : Insn Structure Pointer       |
++|                     struct comedi_insn *insn       : Insn Structure Pointer       |
+ |                     unsigned int *data          : Data Pointer contains        |
+ |                                          configuration parameters as below |
+ |                                                                            |
+@@ -337,7 +337,7 @@ INT i_APCI3501_ConfigAnalogOutput(struct comedi_device * dev, struct comedi_subd
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI3501_WriteAnalogOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0, ul_Channel_no, ul_Polarity, ul_DAC_Ready = 0;;
+ 
+@@ -387,7 +387,7 @@ INT i_APCI3501_WriteAnalogOutput(struct comedi_device * dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_ConfigTimerCounterWatchdog              |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Timer , Counter or Watchdog             |
+ +----------------------------------------------------------------------------+
+@@ -411,7 +411,7 @@ INT i_APCI3501_WriteAnalogOutput(struct comedi_device * dev, struct comedi_subde
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0;
+ 	devpriv->tsk_Current = current;
+@@ -490,7 +490,7 @@ INT i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_StartStopWriteTimerCounterWatchdog      |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Start / Stop The Selected Timer , Counter or Watchdog  |
+ +----------------------------------------------------------------------------+
+@@ -512,7 +512,7 @@ INT i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ */
+ 
+ int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0;
+ 	int i_Temp;
+@@ -593,7 +593,7 @@ int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_ReadTimerCounterWatchdog                |
+ |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+-|                      comedi_insn *insn,unsigned int *data)                     |
++|                      struct comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Selected Timer , Counter or Watchdog          |
+ +----------------------------------------------------------------------------+
+@@ -614,7 +614,7 @@ int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ */
+ 
+ int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
+index 550d81543b16..51e7b66544ac 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
+@@ -56,37 +56,37 @@ struct comedi_lrange range_apci3501_ao = { 2, {
+ 
+ //AO
+ INT i_APCI3501_ConfigAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				  comedi_insn *insn, unsigned int *data);
++				  struct comedi_insn *insn, unsigned int *data);
+ INT i_APCI3501_WriteAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				 comedi_insn *insn, unsigned int *data);
++				 struct comedi_insn *insn, unsigned int *data);
+ 
+ //DI
+ // for di read
+-//INT i_APCI3501_ReadDigitalInput(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data);
++//INT i_APCI3501_ReadDigitalInput(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data);
+ 
+ INT i_APCI3501_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				comedi_insn *insn, unsigned int *data);
++				struct comedi_insn *insn, unsigned int *data);
+ 
+ //DO
+ int i_APCI3501_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				   comedi_insn *insn, unsigned int *data);
++				   struct comedi_insn *insn, unsigned int *data);
+ INT i_APCI3501_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				  comedi_insn *insn, unsigned int *data);
++				  struct comedi_insn *insn, unsigned int *data);
+ INT i_APCI3501_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				 comedi_insn *insn, unsigned int *data);
++				 struct comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+ // timer value is passed as u seconds
+ INT i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device *dev,
+ 					  struct comedi_subdevice *s,
+-					  comedi_insn *insn, unsigned int *data);
++					  struct comedi_insn *insn, unsigned int *data);
+ int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
+ 						  struct comedi_subdevice *s,
+-						  comedi_insn *insn,
++						  struct comedi_insn *insn,
+ 						  unsigned int *data);
+ int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device *dev,
+ 					struct comedi_subdevice *s,
+-					comedi_insn *insn, unsigned int *data);
++					struct comedi_insn *insn, unsigned int *data);
+ //Interrupt
+ void v_APCI3501_Interrupt(int irq, void *d);
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+index ae11fb7af323..b7268e4da64e 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+@@ -82,7 +82,7 @@ int i_APCI3XXX_TestConversionStarted(struct comedi_device * dev)
+ | Function Name     : INT   i_APCI3XXX_AnalogInputConfigOperatingMode        |
+ |                          (struct comedi_device    *dev,                           |
+ |                           struct comedi_subdevice *s,                             |
+-|                           comedi_insn      *insn,                          |
++|                           struct comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+ | Task           Converting mode and convert time selection                  |
+@@ -106,7 +106,7 @@ int i_APCI3XXX_TestConversionStarted(struct comedi_device * dev)
+ */
+ 
+ int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_TimeBase = 0;
+@@ -276,7 +276,7 @@ int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device * dev,
+ | Function Name     : INT   i_APCI3XXX_InsnConfigAnalogInput                 |
+ |                          (struct comedi_device    *dev,                           |
+ |                           struct comedi_subdevice *s,                             |
+-|                           comedi_insn      *insn,                          |
++|                           struct comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+ | Task           Converting mode and convert time selection                  |
+@@ -296,7 +296,7 @@ int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnConfigAnalogInput(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 
+@@ -334,7 +334,7 @@ int i_APCI3XXX_InsnConfigAnalogInput(struct comedi_device * dev,
+ | Function Name     : INT   i_APCI3XXX_InsnReadAnalogInput                   |
+ |                          (struct comedi_device    *dev,                           |
+ |                           struct comedi_subdevice *s,                             |
+-|                           comedi_insn      *insn,                          |
++|                           struct comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+ | Task                Read 1 analog input                                    |
+@@ -356,7 +356,7 @@ int i_APCI3XXX_InsnConfigAnalogInput(struct comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Configuration = (BYTE) CR_RANGE(insn->chanspec);
+@@ -665,7 +665,7 @@ void v_APCI3XXX_Interrupt(int irq, void *d)
+ | Function Name     : INT   i_APCI3XXX_InsnWriteAnalogOutput                 |
+ |                          (struct comedi_device    *dev,                           |
+ |                           struct comedi_subdevice *s,                             |
+-|                           comedi_insn      *insn,                          |
++|                           struct comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+ | Task                Read 1 analog input                                    |
+@@ -685,7 +685,7 @@ void v_APCI3XXX_Interrupt(int irq, void *d)
+ */
+ 
+ int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_Range = (BYTE) CR_RANGE(insn->chanspec);
+ 	BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
+@@ -771,7 +771,7 @@ int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device * dev,
+ | Function Name     : INT   i_APCI3XXX_InsnConfigInitTTLIO                   |
+ |                          (struct comedi_device    *dev,                           |
+ |                           struct comedi_subdevice *s,                             |
+-|                           comedi_insn      *insn,                          |
++|                           struct comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+ | Task           You must calling this function be                           |
+@@ -792,7 +792,7 @@ int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Command = 0;
+@@ -902,7 +902,7 @@ int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ | Function Name     : INT     i_APCI3XXX_InsnBitsTTLIO                       |
+ |                          (struct comedi_device    *dev,                           |
+ |                           struct comedi_subdevice *s,                             |
+-|                           comedi_insn      *insn,                          |
++|                           struct comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+ | Task              : Write the selected output mask and read the status from|
+@@ -920,7 +920,7 @@ int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_ChannelCpt = 0;
+@@ -1059,7 +1059,7 @@ int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device * dev,
+ | Function Name     : INT i_APCI3XXX_InsnReadTTLIO                           |
+ |                          (struct comedi_device    *dev,                           |
+ |                           struct comedi_subdevice *s,                             |
+-|                           comedi_insn      *insn,                          |
++|                           struct comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+ | Task              : Read the status from selected channel                  |
+@@ -1075,7 +1075,7 @@ int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnReadTTLIO(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
+ 	INT i_ReturnValue = insn->n;
+@@ -1171,7 +1171,7 @@ int i_APCI3XXX_InsnReadTTLIO(struct comedi_device * dev,
+ | Function Name     : INT     i_APCI3XXX_InsnWriteTTLIO                      |
+ |                          (struct comedi_device    *dev,                           |
+ |                           struct comedi_subdevice *s,                             |
+-|                           comedi_insn      *insn,                          |
++|                           struct comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+ | Task              : Set the state from TTL output channel                  |
+@@ -1188,7 +1188,7 @@ int i_APCI3XXX_InsnReadTTLIO(struct comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
+@@ -1283,7 +1283,7 @@ int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device * dev,
+ | Function name     :int i_APCI3XXX_InsnReadDigitalInput                     |
+ |                                          (struct comedi_device *dev,              |
+ |                                           struct comedi_subdevice *s,             |
+-|                                           comedi_insn *insn,               |
++|                                           struct comedi_insn *insn,               |
+ |                                           unsigned int *data)                  |
+ +----------------------------------------------------------------------------+
+ | Task              : Reads the value of the specified Digital input channel |
+@@ -1299,7 +1299,7 @@ int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
+@@ -1342,7 +1342,7 @@ int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device * dev,
+ | Function name     :int i_APCI3XXX_InsnBitsDigitalInput                     |
+ |                                          (struct comedi_device *dev,              |
+ |                                           struct comedi_subdevice *s,             |
+-|                                           comedi_insn *insn,               |
++|                                           struct comedi_insn *insn,               |
+ |                                           unsigned int *data)                  |
+ +----------------------------------------------------------------------------+
+ | Task              : Reads the value of the Digital input Port i.e.4channels|
+@@ -1357,7 +1357,7 @@ int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI3XXX_InsnBitsDigitalInput(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	DWORD dw_Temp = 0;
+@@ -1393,7 +1393,7 @@ int i_APCI3XXX_InsnBitsDigitalInput(struct comedi_device * dev,
+ | Function name     :int i_APCI3XXX_InsnBitsDigitalOutput                    |
+ |                                          (struct comedi_device *dev,              |
+ |                                           struct comedi_subdevice *s,             |
+-|                                           comedi_insn *insn,               |
++|                                           struct comedi_insn *insn,               |
+ |                                           unsigned int *data)                  |
+ +----------------------------------------------------------------------------+
+ | Task              : Write the selected output mask and read the status from|
+@@ -1410,7 +1410,7 @@ int i_APCI3XXX_InsnBitsDigitalInput(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI3XXX_InsnBitsDigitalOutput(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_ChannelCpt = 0;
+@@ -1489,7 +1489,7 @@ int i_APCI3XXX_InsnBitsDigitalOutput(struct comedi_device * dev,
+ | Function name     :int i_APCI3XXX_InsnWriteDigitalOutput                   |
+ |                                          (struct comedi_device *dev,              |
+ |                                           struct comedi_subdevice *s,             |
+-|                                           comedi_insn *insn,               |
++|                                           struct comedi_insn *insn,               |
+ |                                           unsigned int *data)                  |
+ +----------------------------------------------------------------------------+
+ | Task              : Set the state from digital output channel              |
+@@ -1506,7 +1506,7 @@ int i_APCI3XXX_InsnBitsDigitalOutput(struct comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Channel = CR_CHAN(insn->chanspec);
+@@ -1565,7 +1565,7 @@ int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device * dev,
+ | Function name     :int i_APCI3XXX_InsnReadDigitalOutput                    |
+ |                                          (struct comedi_device *dev,              |
+ |                                           struct comedi_subdevice *s,             |
+-|                                           comedi_insn *insn,               |
++|                                           struct comedi_insn *insn,               |
+ |                                           unsigned int *data)                  |
+ +----------------------------------------------------------------------------+
+ | Task              : Read the state from digital output channel             |
+@@ -1581,7 +1581,7 @@ int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnReadDigitalOutput(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Channel = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c
+index 9572f04c4cdd..cb0073156718 100644
+--- a/drivers/staging/comedi/drivers/adl_pci6208.c
++++ b/drivers/staging/comedi/drivers/adl_pci6208.c
+@@ -128,13 +128,13 @@ pci6208_pci_setup(struct pci_dev *pci_dev, unsigned long *io_base_ptr,
+ 
+ /*read/write functions*/
+ static int pci6208_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int pci6208_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ //static int pci6208_dio_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s,
+-//      comedi_insn *insn,unsigned int *data);
++//      struct comedi_insn *insn,unsigned int *data);
+ //static int pci6208_dio_insn_config(struct comedi_device *dev,struct comedi_subdevice *s,
+-//      comedi_insn *insn,unsigned int *data);
++//      struct comedi_insn *insn,unsigned int *data);
+ 
+ /*
+  * Attach is called by the Comedi core to configure the driver
+@@ -220,7 +220,7 @@ static int pci6208_detach(struct comedi_device * dev)
+ }
+ 
+ static int pci6208_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i = 0, Data_Read;
+ 	unsigned short chan = CR_CHAN(insn->chanspec);
+@@ -245,7 +245,7 @@ static int pci6208_ao_winsn(struct comedi_device * dev, struct comedi_subdevice
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+ static int pci6208_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -262,7 +262,7 @@ static int pci6208_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+ //static int pci6208_dio_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s,
+-//      comedi_insn *insn,unsigned int *data)
++//      struct comedi_insn *insn,unsigned int *data)
+ //{
+ //      if(insn->n!=2)return -EINVAL;
+ 
+@@ -286,7 +286,7 @@ static int pci6208_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice
+ //}
+ 
+ //static int pci6208_dio_insn_config(struct comedi_device *dev,struct comedi_subdevice *s,
+-//      comedi_insn *insn,unsigned int *data)
++//      struct comedi_insn *insn,unsigned int *data)
+ //{
+ //      int chan=CR_CHAN(insn->chanspec);
+ 
+diff --git a/drivers/staging/comedi/drivers/adl_pci7432.c b/drivers/staging/comedi/drivers/adl_pci7432.c
+index 7e8741e51cec..6759cb39d564 100644
+--- a/drivers/staging/comedi/drivers/adl_pci7432.c
++++ b/drivers/staging/comedi/drivers/adl_pci7432.c
+@@ -70,10 +70,10 @@ static struct comedi_driver driver_adl_pci7432 = {
+ /* Digital IO */
+ 
+ static int adl_pci7432_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ static int adl_pci7432_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ /*            */
+ 
+@@ -165,7 +165,7 @@ static int adl_pci7432_detach(struct comedi_device * dev)
+ }
+ 
+ static int adl_pci7432_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	printk("comedi: pci7432_do_insn_bits called\n");
+ 	printk("comedi: data0: %8x data1: %8x\n", data[0], data[1]);
+@@ -185,7 +185,7 @@ static int adl_pci7432_do_insn_bits(struct comedi_device * dev, struct comedi_su
+ }
+ 
+ static int adl_pci7432_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	printk("comedi: pci7432_di_insn_bits called\n");
+ 	printk("comedi: data0: %8x data1: %8x\n", data[0], data[1]);
+diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c
+index fd925f5d86f6..0c93efc761a4 100644
+--- a/drivers/staging/comedi/drivers/adl_pci8164.c
++++ b/drivers/staging/comedi/drivers/adl_pci8164.c
+@@ -80,28 +80,28 @@ static struct comedi_driver driver_adl_pci8164 = {
+ };
+ 
+ static int adl_pci8164_insn_read_msts(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ static int adl_pci8164_insn_read_ssts(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ static int adl_pci8164_insn_read_buf0(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ static int adl_pci8164_insn_read_buf1(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ static int adl_pci8164_insn_write_cmd(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ static int adl_pci8164_insn_write_otp(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ static int adl_pci8164_insn_write_buf0(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
+ 
+ static int adl_pci8164_insn_write_buf1(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
+ 
+ static int adl_pci8164_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+@@ -209,7 +209,7 @@ static int adl_pci8164_detach(struct comedi_device * dev)
+ }
+ 
+ static int adl_pci8164_insn_read_msts(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+ 	char *axisname;
+@@ -246,7 +246,7 @@ static int adl_pci8164_insn_read_msts(struct comedi_device * dev, struct comedi_
+ }
+ 
+ static int adl_pci8164_insn_read_ssts(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+ 	char *axisname;
+@@ -283,7 +283,7 @@ static int adl_pci8164_insn_read_ssts(struct comedi_device * dev, struct comedi_
+ }
+ 
+ static int adl_pci8164_insn_read_buf0(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+ 	char *axisname;
+@@ -320,7 +320,7 @@ static int adl_pci8164_insn_read_buf0(struct comedi_device * dev, struct comedi_
+ }
+ 
+ static int adl_pci8164_insn_read_buf1(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+ 
+@@ -358,7 +358,7 @@ static int adl_pci8164_insn_read_buf1(struct comedi_device * dev, struct comedi_
+ }
+ 
+ static int adl_pci8164_insn_write_cmd(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int axis, axis_reg;
+ 
+@@ -396,7 +396,7 @@ static int adl_pci8164_insn_write_cmd(struct comedi_device * dev, struct comedi_
+ }
+ 
+ static int adl_pci8164_insn_write_otp(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+ 
+@@ -434,7 +434,7 @@ static int adl_pci8164_insn_write_otp(struct comedi_device * dev, struct comedi_
+ }
+ 
+ static int adl_pci8164_insn_write_buf0(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+ 
+@@ -472,7 +472,7 @@ static int adl_pci8164_insn_write_buf0(struct comedi_device * dev,
+ }
+ 
+ static int adl_pci8164_insn_write_buf1(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+ 
+diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
+index 41aaac7dfa4a..f6ec53728800 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9111.c
++++ b/drivers/staging/comedi/drivers/adl_pci9111.c
+@@ -1072,7 +1072,7 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device PT_REGS_ARG)
+ #undef AI_INSN_DEBUG
+ 
+ static int pci9111_ai_insn_read(struct comedi_device * dev,
+-	struct comedi_subdevice * subdevice, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * subdevice, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int resolution =
+ 		((pci9111_board_struct *) dev->board_ptr)->ai_resolution;
+@@ -1132,7 +1132,7 @@ static int pci9111_ai_insn_read(struct comedi_device * dev,
+ 
+ static int
+ pci9111_ao_insn_write(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 
+@@ -1149,7 +1149,7 @@ pci9111_ao_insn_write(struct comedi_device * dev,
+ //
+ 
+ static int pci9111_ao_insn_read(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 
+@@ -1171,7 +1171,7 @@ static int pci9111_ao_insn_read(struct comedi_device * dev,
+ //
+ 
+ static int pci9111_di_insn_bits(struct comedi_device * dev,
+-	struct comedi_subdevice * subdevice, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * subdevice, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bits;
+ 
+@@ -1186,7 +1186,7 @@ static int pci9111_di_insn_bits(struct comedi_device * dev,
+ //
+ 
+ static int pci9111_do_insn_bits(struct comedi_device * dev,
+-	struct comedi_subdevice * subdevice, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * subdevice, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bits;
+ 
+diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
+index cc3ea6cfdb81..406eab7fd435 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9118.c
++++ b/drivers/staging/comedi/drivers/adl_pci9118.c
+@@ -328,7 +328,7 @@ static void pci9118_calc_divisors(char mode, struct comedi_device * dev,
+ ==============================================================================
+ */
+ static int pci9118_insn_read_ai(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	int n, timeout;
+@@ -378,7 +378,7 @@ static int pci9118_insn_read_ai(struct comedi_device * dev, struct comedi_subdev
+ ==============================================================================
+ */
+ static int pci9118_insn_write_ao(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, chanreg, ch;
+ 
+@@ -401,7 +401,7 @@ static int pci9118_insn_write_ao(struct comedi_device * dev, struct comedi_subde
+ ==============================================================================
+ */
+ static int pci9118_insn_read_ao(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, chan;
+ 
+@@ -416,7 +416,7 @@ static int pci9118_insn_read_ao(struct comedi_device * dev, struct comedi_subdev
+ ==============================================================================
+ */
+ static int pci9118_insn_bits_di(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[1] = inl(dev->iobase + PCI9118_DI) & 0xf;
+ 
+@@ -427,7 +427,7 @@ static int pci9118_insn_bits_di(struct comedi_device * dev, struct comedi_subdev
+ ==============================================================================
+ */
+ static int pci9118_insn_bits_do(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+ 		s->state &= ~data[0];
+diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c
+index fd2a6f7733b2..07eea09e81fb 100644
+--- a/drivers/staging/comedi/drivers/adq12b.c
++++ b/drivers/staging/comedi/drivers/adq12b.c
+@@ -174,9 +174,9 @@ static struct comedi_driver driver_adq12b={
+         num_names:      sizeof(adq12b_boards) / sizeof(adq12b_board),
+ };
+ 
+-static int adq12b_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data);
+-static int adq12b_di_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, comedi_insn *insn,unsigned int *data);
+-static int adq12b_do_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, comedi_insn *insn,unsigned int *data);
++static int adq12b_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data);
++static int adq12b_di_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data);
++static int adq12b_do_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data);
+ 
+ /*
+  * Attach is called by the Comedi core to configure the driver
+@@ -314,7 +314,7 @@ static int adq12b_detach(struct comedi_device *dev)
+  * mode.
+  */
+ 
+-static int adq12b_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)
++static int adq12b_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)
+ {
+         int n, i;
+         int range, channel;
+@@ -357,7 +357,7 @@ static int adq12b_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,
+ }
+ 
+ 
+-static int adq12b_di_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, 	comedi_insn *insn,unsigned int *data)
++static int adq12b_di_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, 	struct comedi_insn *insn,unsigned int *data)
+ {
+ 
+         /* only bits 0-4 have information about digital inputs */
+@@ -367,7 +367,7 @@ static int adq12b_di_insn_bits(struct comedi_device *dev,struct comedi_subdevice
+ }
+ 
+ 
+-static int adq12b_do_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, 	comedi_insn *insn,unsigned int *data)
++static int adq12b_do_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, 	struct comedi_insn *insn,unsigned int *data)
+ {
+         int channel;
+ 
+diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
+index 0732cac2e710..64aec321274d 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1710.c
++++ b/drivers/staging/comedi/drivers/adv_pci1710.c
+@@ -323,7 +323,7 @@ static const unsigned int muxonechan[] = { 0x0000, 0x0101, 0x0202, 0x0303, 0x040
+ ==============================================================================
+ */
+ static int pci171x_insn_read_ai(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, timeout;
+ #ifdef PCI171x_PARANOIDCHECK
+@@ -391,7 +391,7 @@ static int pci171x_insn_read_ai(struct comedi_device * dev, struct comedi_subdev
+ ==============================================================================
+ */
+ static int pci171x_insn_write_ao(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, chan, range, ofs;
+ 
+@@ -422,7 +422,7 @@ static int pci171x_insn_write_ao(struct comedi_device * dev, struct comedi_subde
+ ==============================================================================
+ */
+ static int pci171x_insn_read_ao(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, chan;
+ 
+@@ -437,7 +437,7 @@ static int pci171x_insn_read_ao(struct comedi_device * dev, struct comedi_subdev
+ ==============================================================================
+ */
+ static int pci171x_insn_bits_di(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[1] = inw(dev->iobase + PCI171x_DI);
+ 
+@@ -448,7 +448,7 @@ static int pci171x_insn_bits_di(struct comedi_device * dev, struct comedi_subdev
+ ==============================================================================
+ */
+ static int pci171x_insn_bits_do(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+ 		s->state &= ~data[0];
+@@ -464,7 +464,7 @@ static int pci171x_insn_bits_do(struct comedi_device * dev, struct comedi_subdev
+ ==============================================================================
+ */
+ static int pci171x_insn_counter_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int msb, lsb, ccntrl;
+ 	int i;
+@@ -486,7 +486,7 @@ static int pci171x_insn_counter_read(struct comedi_device * dev, struct comedi_s
+ ==============================================================================
+ */
+ static int pci171x_insn_counter_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	uint msb, lsb, ccntrl, status;
+ 
+@@ -513,7 +513,7 @@ static int pci171x_insn_counter_write(struct comedi_device * dev, struct comedi_
+ ==============================================================================
+ */
+ static int pci171x_insn_counter_config(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ #ifdef unused
+ 	/* This doesn't work like a normal Comedi counter config */
+@@ -549,7 +549,7 @@ static int pci171x_insn_counter_config(struct comedi_device * dev,
+ ==============================================================================
+ */
+ static int pci1720_insn_write_ao(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, rangereg, chan;
+ 
+diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
+index c50578dfab9c..002144a9f6bd 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1723.c
++++ b/drivers/staging/comedi/drivers/adv_pci1723.c
+@@ -203,7 +203,7 @@ static int pci1723_reset(struct comedi_device * dev)
+ }
+ 
+ static int pci1723_insn_read_ao(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, chan;
+ 
+@@ -219,7 +219,7 @@ static int pci1723_insn_read_ao(struct comedi_device * dev, struct comedi_subdev
+   analog data output;
+ */
+ static int pci1723_ao_write_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, chan;
+ 	chan = CR_CHAN(insn->chanspec);
+@@ -239,7 +239,7 @@ static int pci1723_ao_write_winsn(struct comedi_device * dev, struct comedi_subd
+   digital i/o config/query
+ */
+ static int pci1723_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int mask;
+ 	unsigned int bits;
+@@ -279,7 +279,7 @@ static int pci1723_dio_insn_config(struct comedi_device * dev, struct comedi_sub
+   digital i/o bits read/write
+ */
+ static int pci1723_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+ 		s->state &= ~data[0];
+diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
+index 5fcba548a786..7ed30317073c 100644
+--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
++++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
+@@ -358,7 +358,7 @@ static pci_dio_private *pci_priv = NULL;	/* list of allocated cards */
+ ==============================================================================
+ */
+ static int pci_dio_insn_bits_di_b(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	const diosubd_data *d = (const diosubd_data *)s->private;
+ 	int i;
+@@ -375,7 +375,7 @@ static int pci_dio_insn_bits_di_b(struct comedi_device * dev, struct comedi_subd
+ ==============================================================================
+ */
+ static int pci_dio_insn_bits_di_w(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	const diosubd_data *d = (const diosubd_data *)s->private;
+ 	int i;
+@@ -391,7 +391,7 @@ static int pci_dio_insn_bits_di_w(struct comedi_device * dev, struct comedi_subd
+ ==============================================================================
+ */
+ static int pci_dio_insn_bits_do_b(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	const diosubd_data *d = (const diosubd_data *)s->private;
+ 	int i;
+@@ -412,7 +412,7 @@ static int pci_dio_insn_bits_do_b(struct comedi_device * dev, struct comedi_subd
+ ==============================================================================
+ */
+ static int pci_dio_insn_bits_do_w(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	const diosubd_data *d = (const diosubd_data *)s->private;
+ 	int i;
+@@ -491,7 +491,7 @@ static int pci1760_mbxrequest(struct comedi_device * dev,
+ ==============================================================================
+ */
+ static int pci1760_insn_bits_di(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[1] = inb(dev->iobase + IMB3);
+ 
+@@ -502,7 +502,7 @@ static int pci1760_insn_bits_di(struct comedi_device * dev, struct comedi_subdev
+ ==============================================================================
+ */
+ static int pci1760_insn_bits_do(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int ret;
+ 	unsigned char omb[4] = {
+@@ -529,7 +529,7 @@ static int pci1760_insn_bits_do(struct comedi_device * dev, struct comedi_subdev
+ ==============================================================================
+ */
+ static int pci1760_insn_cnt_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int ret, n;
+ 	unsigned char omb[4] = {
+@@ -553,7 +553,7 @@ static int pci1760_insn_cnt_read(struct comedi_device * dev, struct comedi_subde
+ ==============================================================================
+ */
+ static int pci1760_insn_cnt_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int ret;
+ 	unsigned char chan = CR_CHAN(insn->chanspec) & 0x07;
+diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c
+index 2d1b8d269645..10fd18aeb3fe 100644
+--- a/drivers/staging/comedi/drivers/aio_aio12_8.c
++++ b/drivers/staging/comedi/drivers/aio_aio12_8.c
+@@ -89,7 +89,7 @@ typedef struct {
+ #define devpriv	((aio12_8_private *) dev->private)
+ 
+ static int aio_aio12_8_ai_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	unsigned char control =
+@@ -123,7 +123,7 @@ static int aio_aio12_8_ai_read(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int aio_aio12_8_ao_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int val = devpriv->ao_readback[CR_CHAN(insn->chanspec)];
+@@ -134,7 +134,7 @@ static int aio_aio12_8_ao_read(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int aio_aio12_8_ao_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c
+index b04ad03c85e7..a739bfa2b59b 100644
+--- a/drivers/staging/comedi/drivers/aio_iiro_16.c
++++ b/drivers/staging/comedi/drivers/aio_iiro_16.c
+@@ -82,10 +82,10 @@ static struct comedi_driver driver_aio_iiro_16 = {
+ };
+ 
+ static int aio_iiro_16_dio_insn_bits_read(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
+ 
+ static int aio_iiro_16_dio_insn_bits_write(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
+ 
+ static int aio_iiro_16_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+@@ -143,7 +143,7 @@ static int aio_iiro_16_detach(struct comedi_device * dev)
+ }
+ 
+ static int aio_iiro_16_dio_insn_bits_write(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -162,7 +162,7 @@ static int aio_iiro_16_dio_insn_bits_write(struct comedi_device * dev,
+ }
+ 
+ static int aio_iiro_16_dio_insn_bits_read(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
+index 25b8f4fa1c1a..88c127566b8a 100644
+--- a/drivers/staging/comedi/drivers/amplc_dio200.c
++++ b/drivers/staging/comedi/drivers/amplc_dio200.c
+@@ -573,7 +573,7 @@ dio200_request_region(unsigned minor, unsigned long from, unsigned long extent)
+  */
+ static int
+ dio200_subdev_intr_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	dio200_subdev_intr *subpriv = s->private;
+ 
+@@ -1034,7 +1034,7 @@ static irqreturn_t dio200_interrupt(int irq, void *d PT_REGS_ARG)
+  */
+ static int
+ dio200_subdev_8254_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	dio200_subdev_8254 *subpriv = s->private;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -1049,7 +1049,7 @@ dio200_subdev_8254_read(struct comedi_device * dev, struct comedi_subdevice * s,
+  */
+ static int
+ dio200_subdev_8254_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	dio200_subdev_8254 *subpriv = s->private;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -1143,7 +1143,7 @@ dio200_get_clock_src(dio200_subdev_8254 * subpriv, unsigned int counter_number,
+  */
+ static int
+ dio200_subdev_8254_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	dio200_subdev_8254 *subpriv = s->private;
+ 	int ret;
+diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
+index 64cfcc8296e7..b9c883500ca5 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc236.c
++++ b/drivers/staging/comedi/drivers/amplc_pc236.c
+@@ -189,7 +189,7 @@ static void pc236_intr_disable(struct comedi_device * dev);
+ static void pc236_intr_enable(struct comedi_device * dev);
+ static int pc236_intr_check(struct comedi_device * dev);
+ static int pc236_intr_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int pc236_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_cmd * cmd);
+ static int pc236_intr_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+@@ -529,7 +529,7 @@ static int pc236_intr_check(struct comedi_device * dev)
+  * Copied from the comedi_parport driver.
+  */
+ static int pc236_intr_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[1] = 0;
+ 	return 2;
+diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
+index 313f4a094653..d7c33e1403bb 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc263.c
++++ b/drivers/staging/comedi/drivers/amplc_pc263.c
+@@ -147,9 +147,9 @@ static struct comedi_driver driver_amplc_pc263 = {
+ static int pc263_request_region(unsigned minor, unsigned long from,
+ 	unsigned long extent);
+ static int pc263_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int pc263_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ /*
+  * This function looks for a PCI device matching the requested board name,
+@@ -388,7 +388,7 @@ static int pc263_request_region(unsigned minor, unsigned long from,
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+ static int pc263_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -413,7 +413,7 @@ static int pc263_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int pc263_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 1)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
+index 639bd2f588c5..ec60574786a9 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci224.c
++++ b/drivers/staging/comedi/drivers/amplc_pci224.c
+@@ -478,7 +478,7 @@ pci224_ao_set_data(struct comedi_device * dev, int chan, int range, unsigned int
+  */
+ static int
+ pci224_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan, range;
+@@ -505,7 +505,7 @@ pci224_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+  */
+ static int
+ pci224_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan;
+diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
+index d985f649f9fb..432f05ba3bc5 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci230.c
++++ b/drivers/staging/comedi/drivers/amplc_pci230.c
+@@ -616,11 +616,11 @@ static struct comedi_driver driver_amplc_pci230 = {
+ COMEDI_PCI_INITCLEANUP(driver_amplc_pci230, pci230_pci_table);
+ 
+ static int pci230_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int pci230_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int pci230_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static void pci230_ct_setup_ns_mode(struct comedi_device * dev, unsigned int ct,
+ 	unsigned int mode, uint64_t ns, unsigned int round);
+ static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round);
+@@ -1059,7 +1059,7 @@ static inline void put_all_resources(struct comedi_device * dev, unsigned char o
+  *  COMEDI_SUBD_AI instruction;
+  */
+ static int pci230_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int n, i;
+ 	unsigned int chan, range, aref;
+@@ -1164,7 +1164,7 @@ static int pci230_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+  *  COMEDI_SUBD_AO instructions;
+  */
+ static int pci230_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan, range;
+@@ -1192,7 +1192,7 @@ static int pci230_ao_winsn(struct comedi_device * dev, struct comedi_subdevice *
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+ static int pci230_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c
+index 612a04afb294..8b10ff927d41 100644
+--- a/drivers/staging/comedi/drivers/c6xdigio.c
++++ b/drivers/staging/comedi/drivers/c6xdigio.c
+@@ -339,14 +339,14 @@ static void C6X_encResetAll(unsigned long baseAddr)
+ }
+ 
+ static int c6xdigio_pwmo_insn_read(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	printk("c6xdigio_pwmo_insn_read %x\n", insn->n);
+ 	return insn->n;
+ }
+ 
+ static int c6xdigio_pwmo_insn_write(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -361,7 +361,7 @@ static int c6xdigio_pwmo_insn_write(struct comedi_device * dev,
+ 
+ //static int c6xdigio_ei_init_insn_read(struct comedi_device *dev,
+ //                                 struct comedi_subdevice *s,
+-//                                 comedi_insn *insn,
++//                                 struct comedi_insn *insn,
+ //                                 unsigned int *data)
+ //{
+ //  printk("c6xdigio_ei_init_insn_read %x\n", insn->n);
+@@ -370,7 +370,7 @@ static int c6xdigio_pwmo_insn_write(struct comedi_device * dev,
+ 
+ //static int c6xdigio_ei_init_insn_write(struct comedi_device *dev,
+ //                                 struct comedi_subdevice *s,
+-//                                 comedi_insn *insn,
++//                                 struct comedi_insn *insn,
+ //                                 unsigned int *data)
+ //{
+ //  int i;
+@@ -382,7 +382,7 @@ static int c6xdigio_pwmo_insn_write(struct comedi_device * dev,
+ //}
+ 
+ static int c6xdigio_ei_insn_read(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	//  printk("c6xdigio_ei__insn_read %x\n", insn->n);
+ 	int n;
+diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
+index ef126bcf6d07..df77102cfa5e 100644
+--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
++++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
+@@ -110,22 +110,22 @@ static const struct comedi_lrange das16cs_ai_range = { 4, {
+ 
+ static irqreturn_t das16cs_interrupt(int irq, void *d PT_REGS_ARG);
+ static int das16cs_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int das16cs_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int das16cs_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_cmd * cmd);
+ static int das16cs_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int das16cs_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int das16cs_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int das16cs_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int das16cs_timer_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int das16cs_timer_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ static int get_prodid(struct comedi_device * dev, struct pcmcia_device *link)
+ {
+@@ -287,7 +287,7 @@ static irqreturn_t das16cs_interrupt(int irq, void *d PT_REGS_ARG)
+  * mode.
+  */
+ static int das16cs_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int to;
+@@ -490,7 +490,7 @@ static int das16cs_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevic
+ }
+ 
+ static int das16cs_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -536,7 +536,7 @@ static int das16cs_ao_winsn(struct comedi_device * dev, struct comedi_subdevice
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+ static int das16cs_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -553,7 +553,7 @@ static int das16cs_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+ static int das16cs_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -573,7 +573,7 @@ static int das16cs_dio_insn_bits(struct comedi_device * dev, struct comedi_subde
+ }
+ 
+ static int das16cs_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	int bits;
+@@ -611,13 +611,13 @@ static int das16cs_dio_insn_config(struct comedi_device * dev, struct comedi_sub
+ }
+ 
+ static int das16cs_timer_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	return -EINVAL;
+ }
+ 
+ static int das16cs_timer_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	return -EINVAL;
+ }
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
+index 70cb220f6422..f2d09e3e7fa8 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas.c
+@@ -450,15 +450,15 @@ static struct comedi_driver driver_cb_pcidas = {
+ };
+ 
+ static int cb_pcidas_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int cb_pcidas_ao_nofifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int cb_pcidas_ao_fifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int cb_pcidas_ao_readback_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int cb_pcidas_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int cb_pcidas_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_cmd * cmd);
+@@ -475,22 +475,22 @@ static int cb_pcidas_ao_cancel(struct comedi_device * dev, struct comedi_subdevi
+ static void cb_pcidas_load_counters(struct comedi_device * dev, unsigned int *ns,
+ 	int round_flags);
+ static int eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int caldac_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int caldac_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int trimpot_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int cb_pcidas_trimpot_write(struct comedi_device * dev, unsigned int channel,
+ 	unsigned int value);
+ static int trimpot_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int dac08_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int dac08_write(struct comedi_device * dev, unsigned int value);
+ static int dac08_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int caldac_8800_write(struct comedi_device * dev, unsigned int address,
+ 	uint8_t value);
+ static int trimpot_7376_write(struct comedi_device * dev, uint8_t value);
+@@ -754,7 +754,7 @@ static int cb_pcidas_detach(struct comedi_device * dev)
+  * mode.
+  */
+ static int cb_pcidas_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i;
+ 	unsigned int bits;
+@@ -821,7 +821,7 @@ static int ai_config_calibration_source(struct comedi_device * dev, unsigned int
+ }
+ 
+ static int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int id = data[0];
+ 
+@@ -838,7 +838,7 @@ static int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice *
+ 
+ // analog output insn for pcidas-1000 and 1200 series
+ static int cb_pcidas_ao_nofifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel;
+ 	unsigned long flags;
+@@ -863,7 +863,7 @@ static int cb_pcidas_ao_nofifo_winsn(struct comedi_device * dev, struct comedi_s
+ 
+ // analog output insn for pcidas-1602 series
+ static int cb_pcidas_ao_fifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel;
+ 	unsigned long flags;
+@@ -894,7 +894,7 @@ static int cb_pcidas_ao_fifo_winsn(struct comedi_device * dev, struct comedi_sub
+ // analog output readback insn
+ // XXX loses track of analog output value back after an analog ouput command is executed
+ static int cb_pcidas_ao_readback_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)];
+ 
+@@ -902,7 +902,7 @@ static int cb_pcidas_ao_readback_insn(struct comedi_device * dev, struct comedi_
+ }
+ 
+ static int eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	uint8_t nvram_data;
+ 	int retval;
+@@ -917,7 +917,7 @@ static int eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ static int caldac_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	const unsigned int channel = CR_CHAN(insn->chanspec);
+ 
+@@ -925,7 +925,7 @@ static int caldac_write_insn(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ static int caldac_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->caldac_value[CR_CHAN(insn->chanspec)];
+ 
+@@ -954,13 +954,13 @@ static int dac08_write(struct comedi_device * dev, unsigned int value)
+ }
+ 
+ static int dac08_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	return dac08_write(dev, data[0]);
+ }
+ 
+ static int dac08_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->dac08_value;
+ 
+@@ -991,7 +991,7 @@ static int cb_pcidas_trimpot_write(struct comedi_device * dev,
+ }
+ 
+ static int trimpot_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int channel = CR_CHAN(insn->chanspec);
+ 
+@@ -999,7 +999,7 @@ static int trimpot_write_insn(struct comedi_device * dev, struct comedi_subdevic
+ }
+ 
+ static int trimpot_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int channel = CR_CHAN(insn->chanspec);
+ 
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
+index dd7a35cf7d5d..40d97134e384 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
+@@ -1135,13 +1135,13 @@ static struct comedi_driver driver_cb_pcidas = {
+ };
+ 
+ static int ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int ao_readback_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_cmd * cmd);
+@@ -1156,25 +1156,25 @@ static int ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int dio_callback(int dir, int port, int data, unsigned long arg);
+ static int dio_callback_4020(int dir, int port, int data, unsigned long arg);
+ static int di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int dio_60xx_config_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int dio_60xx_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int calib_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int calib_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int ad8402_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static void ad8402_write(struct comedi_device * dev, unsigned int channel,
+ 	unsigned int value);
+ static int ad8402_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static void check_adc_timing(struct comedi_device * dev, struct comedi_cmd * cmd);
+ static unsigned int get_divisor(unsigned int ns, unsigned int flags);
+ static void i2c_write(struct comedi_device * dev, unsigned int address,
+@@ -1882,7 +1882,7 @@ static int detach(struct comedi_device * dev)
+ }
+ 
+ static int ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bits = 0, n, i;
+ 	unsigned int channel, range, aref;
+@@ -2107,7 +2107,7 @@ static int ai_config_master_clock(struct comedi_device * dev, unsigned int * dat
+ }
+ 
+ static int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int id = data[0];
+ 
+@@ -3195,7 +3195,7 @@ static int ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ }
+ 
+ static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	int range = CR_RANGE(insn->chanspec);
+@@ -3225,7 +3225,7 @@ static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ }
+ 
+ static int ao_readback_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = priv(dev)->ao_value[CR_CHAN(insn->chanspec)];
+ 
+@@ -3606,7 +3606,7 @@ static int dio_callback_4020(int dir, int port, int data, unsigned long iobase)
+ }
+ 
+ static int di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bits;
+ 
+@@ -3619,7 +3619,7 @@ static int di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ }
+ 
+ static int do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] &= 0xf;
+ 	// zero bits we are going to change
+@@ -3635,7 +3635,7 @@ static int do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ }
+ 
+ static int dio_60xx_config_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int mask;
+ 
+@@ -3662,7 +3662,7 @@ static int dio_60xx_config_insn(struct comedi_device * dev, struct comedi_subdev
+ }
+ 
+ static int dio_60xx_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+ 		s->state &= ~data[0];
+@@ -3695,7 +3695,7 @@ static void caldac_write(struct comedi_device * dev, unsigned int channel,
+ }
+ 
+ static int calib_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel = CR_CHAN(insn->chanspec);
+ 
+@@ -3710,7 +3710,7 @@ static int calib_write_insn(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ static int calib_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int channel = CR_CHAN(insn->chanspec);
+ 
+@@ -3751,7 +3751,7 @@ static void ad8402_write(struct comedi_device * dev, unsigned int channel,
+ 
+ /* for pci-das6402/16, channel 0 is analog input gain and channel 1 is offset */
+ static int ad8402_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel = CR_CHAN(insn->chanspec);
+ 
+@@ -3768,7 +3768,7 @@ static int ad8402_write_insn(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ static int ad8402_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int channel = CR_CHAN(insn->chanspec);
+ 
+@@ -3840,7 +3840,7 @@ static uint16_t read_eeprom(struct comedi_device * dev, uint8_t address)
+ }
+ 
+ static int eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = read_eeprom(dev, CR_CHAN(insn->chanspec));
+ 
+diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
+index 794e5de21837..ade2ef1cbbd8 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidda.c
++++ b/drivers/staging/comedi/drivers/cb_pcidda.c
+@@ -234,9 +234,9 @@ typedef struct {
+ 
+ static int cb_pcidda_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int cb_pcidda_detach(struct comedi_device * dev);
+-//static int cb_pcidda_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data);
++//static int cb_pcidda_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data);
+ static int cb_pcidda_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ //static int cb_pcidda_ai_cmd(struct comedi_device *dev,struct comedi_subdevice *s);
+ //static int cb_pcidda_ai_cmdtest(struct comedi_device *dev,struct comedi_subdevice *s, struct comedi_cmd *cmd);
+ //static int cb_pcidda_ns_to_timer(unsigned int *ns,int round);
+@@ -599,7 +599,7 @@ static int cb_pcidda_ns_to_timer(unsigned int *ns, int round)
+ #endif
+ 
+ static int cb_pcidda_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int command;
+ 	unsigned int channel, range;
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
+index ac983b17f594..ab588d15f576 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
+@@ -185,11 +185,11 @@ static struct comedi_driver driver_cb_pcimdas = {
+ };
+ 
+ static int cb_pcimdas_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int cb_pcimdas_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int cb_pcimdas_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ /*
+  * Attach is called by the Comedi core to configure the driver
+@@ -373,7 +373,7 @@ static int cb_pcimdas_detach(struct comedi_device * dev)
+  * mode.
+  */
+ static int cb_pcimdas_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i;
+ 	unsigned int d;
+@@ -438,7 +438,7 @@ static int cb_pcimdas_ai_rinsn(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int cb_pcimdas_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -466,7 +466,7 @@ static int cb_pcimdas_ao_winsn(struct comedi_device * dev, struct comedi_subdevi
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+ static int cb_pcimdas_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
+index 976b789c27e0..dfbdcfaa49af 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
+@@ -198,9 +198,9 @@ MODULE_LICENSE("GPL");
+ COMEDI_PCI_INITCLEANUP_NOMODULE(cb_pcimdda_driver, pci_table);
+ 
+ static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ /*---------------------------------------------------------------------------
+   HELPER FUNCTION DECLARATIONS
+@@ -353,7 +353,7 @@ static int detach(struct comedi_device * dev)
+ }
+ 
+ static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -392,7 +392,7 @@ static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+    applications, I would imagine.
+ */
+ static int ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c
+index deba16fb2fa8..be46f17560db 100644
+--- a/drivers/staging/comedi/drivers/comedi_bond.c
++++ b/drivers/staging/comedi/drivers/comedi_bond.c
+@@ -214,9 +214,9 @@ static struct comedi_driver driver_bonding = {
+ };
+ 
+ static int bonding_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
+-				 comedi_insn *insn, unsigned int *data);
++				 struct comedi_insn *insn, unsigned int *data);
+ static int bonding_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
+-				   comedi_insn *insn, unsigned int *data);
++				   struct comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * Attach is called by the Comedi core to configure the driver
+@@ -294,7 +294,7 @@ static int bonding_detach(struct comedi_device *dev)
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+ static int bonding_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
+-				 comedi_insn *insn, unsigned int *data)
++				 struct comedi_insn *insn, unsigned int *data)
+ {
+ #define LSAMPL_BITS (sizeof(unsigned int)*8)
+ 	unsigned nchans = LSAMPL_BITS, num_done = 0, i;
+@@ -341,7 +341,7 @@ static int bonding_dio_insn_bits(struct comedi_device *dev, struct comedi_subdev
+ }
+ 
+ static int bonding_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
+-				   comedi_insn *insn, unsigned int *data)
++				   struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec), ret, io_bits = s->io_bits;
+ 	unsigned int io;
+diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c
+index 3adb1240e4c9..d58ceff063d4 100644
+--- a/drivers/staging/comedi/drivers/comedi_parport.c
++++ b/drivers/staging/comedi/drivers/comedi_parport.c
+@@ -109,7 +109,7 @@ struct parport_private {
+ #define devpriv ((struct parport_private *)(dev->private))
+ 
+ static int parport_insn_a(struct comedi_device *dev, struct comedi_subdevice *s,
+-			  comedi_insn *insn, unsigned int *data)
++			  struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (data[0]) {
+ 		devpriv->a_data &= ~data[0];
+@@ -124,7 +124,7 @@ static int parport_insn_a(struct comedi_device *dev, struct comedi_subdevice *s,
+ }
+ 
+ static int parport_insn_config_a(struct comedi_device *dev, struct comedi_subdevice *s,
+-				 comedi_insn *insn, unsigned int *data)
++				 struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (data[0]) {
+ 		s->io_bits = 0xff;
+@@ -139,7 +139,7 @@ static int parport_insn_config_a(struct comedi_device *dev, struct comedi_subdev
+ }
+ 
+ static int parport_insn_b(struct comedi_device *dev, struct comedi_subdevice *s,
+-			  comedi_insn *insn, unsigned int *data)
++			  struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (data[0]) {
+ 		/* should writes be ignored? */
+@@ -152,7 +152,7 @@ static int parport_insn_b(struct comedi_device *dev, struct comedi_subdevice *s,
+ }
+ 
+ static int parport_insn_c(struct comedi_device *dev, struct comedi_subdevice *s,
+-			  comedi_insn *insn, unsigned int *data)
++			  struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[0] &= 0x0f;
+ 	if (data[0]) {
+@@ -168,7 +168,7 @@ static int parport_insn_c(struct comedi_device *dev, struct comedi_subdevice *s,
+ }
+ 
+ static int parport_intr_insn(struct comedi_device *dev, struct comedi_subdevice *s,
+-			     comedi_insn *insn, unsigned int *data)
++			     struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n < 1)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/comedi_rt_timer.c b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+index f57a6467ae4f..91a865d7ed9a 100644
+--- a/drivers/staging/comedi/drivers/comedi_rt_timer.c
++++ b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+@@ -397,9 +397,9 @@ static void timer_task_func(comedi_rt_task_context_t d)
+ }
+ 
+ static int timer_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+-	comedi_insn xinsn = *insn;
++	struct comedi_insn xinsn = *insn;
+ 
+ 	xinsn.data = data;
+ 	xinsn.subdev = devpriv->subd;
+diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c
+index 8fcec97a84dc..09df3d33d22a 100644
+--- a/drivers/staging/comedi/drivers/comedi_test.c
++++ b/drivers/staging/comedi/drivers/comedi_test.c
+@@ -112,9 +112,9 @@ static int waveform_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevic
+ static int waveform_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
+ static int waveform_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
+ static int waveform_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
+-				 comedi_insn *insn, unsigned int *data);
++				 struct comedi_insn *insn, unsigned int *data);
+ static int waveform_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
+-				  comedi_insn *insn, unsigned int *data);
++				  struct comedi_insn *insn, unsigned int *data);
+ static short fake_sawtooth(struct comedi_device *dev, unsigned int range,
+ 			     unsigned long current_time);
+ static short fake_squarewave(struct comedi_device *dev, unsigned int range,
+@@ -505,7 +505,7 @@ static short fake_waveform(struct comedi_device *dev, unsigned int channel,
+ }
+ 
+ static int waveform_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
+-				 comedi_insn *insn, unsigned int *data)
++				 struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, chan = CR_CHAN(insn->chanspec);
+ 
+@@ -516,7 +516,7 @@ static int waveform_ai_insn_read(struct comedi_device *dev, struct comedi_subdev
+ }
+ 
+ static int waveform_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
+-				  comedi_insn *insn, unsigned int *data)
++				  struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, chan = CR_CHAN(insn->chanspec);
+ 
+diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
+index bbe58550083c..0e0c790ac740 100644
+--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
++++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
+@@ -86,9 +86,9 @@ static struct comedi_driver driver_contec = {
+ 
+ /* Classic digital IO */
+ static int contec_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int contec_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ #if 0
+ static int contec_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+@@ -193,7 +193,7 @@ static int contec_ns_to_timer(unsigned int *ns, int round)
+ #endif
+ 
+ static int contec_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	printk("contec_do_insn_bits called\n");
+@@ -213,7 +213,7 @@ static int contec_do_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int contec_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	rt_printk("contec_di_insn_bits called\n");
+diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
+index 05058bf8d5e9..adda2c4eef12 100644
+--- a/drivers/staging/comedi/drivers/daqboard2000.c
++++ b/drivers/staging/comedi/drivers/daqboard2000.c
+@@ -394,7 +394,7 @@ static void setup_sampling(struct comedi_device * dev, int chan, int gain)
+ }
+ 
+ static int daqboard2000_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	daqboard2000_hw *fpga = devpriv->daq;
+@@ -451,7 +451,7 @@ static int daqboard2000_ai_insn_read(struct comedi_device * dev, struct comedi_s
+ }
+ 
+ static int daqboard2000_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -464,7 +464,7 @@ static int daqboard2000_ao_insn_read(struct comedi_device * dev, struct comedi_s
+ }
+ 
+ static int daqboard2000_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
+index 3cd44cc2fc67..8943a42badd6 100644
+--- a/drivers/staging/comedi/drivers/das08.c
++++ b/drivers/staging/comedi/drivers/das08.c
+@@ -155,19 +155,19 @@ driver.
+ /* gainlist same as _pgx_ below */
+ 
+ static int das08_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int das08_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int das08_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int das08jr_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int das08jr_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int das08jr_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int das08ao_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static void i8254_set_mode_low(unsigned int base, int channel,
+ 	unsigned int mode);
+ 
+@@ -513,7 +513,7 @@ MODULE_DEVICE_TABLE(pci, das08_pci_table);
+ #define TIMEOUT 100000
+ 
+ static int das08_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+ 	int chan;
+@@ -580,7 +580,7 @@ static int das08_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ static int das08_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = 0;
+ 	data[1] = DAS08_IP(inb(dev->iobase + DAS08_STATUS));
+@@ -589,7 +589,7 @@ static int das08_di_rbits(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ static int das08_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int wbits;
+ 
+@@ -612,7 +612,7 @@ static int das08_do_wbits(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ static int das08jr_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = 0;
+ 	data[1] = inb(dev->iobase + DAS08JR_DIO);
+@@ -621,7 +621,7 @@ static int das08jr_di_rbits(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ static int das08jr_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	// null bits we are going to set
+ 	devpriv->do_bits &= ~data[0];
+@@ -635,7 +635,7 @@ static int das08jr_do_wbits(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ static int das08jr_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int lsb, msb;
+@@ -669,7 +669,7 @@ static int das08jr_ao_winsn(struct comedi_device * dev, struct comedi_subdevice
+  *
+  */
+ static int das08ao_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int lsb, msb;
+@@ -783,7 +783,7 @@ static unsigned int i8254_read_status(struct i8254_struct *st, int channel)
+ }
+ 
+ static int das08_counter_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = insn->chanspec;
+ 
+@@ -795,7 +795,7 @@ static int das08_counter_read(struct comedi_device * dev, struct comedi_subdevic
+ }
+ 
+ static int das08_counter_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = insn->chanspec;
+ 
+@@ -806,7 +806,7 @@ static int das08_counter_write(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int das08_counter_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = insn->chanspec;
+ 
+diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
+index 1ca8f2eb48ab..c4c12e6b1a71 100644
+--- a/drivers/staging/comedi/drivers/das16.c
++++ b/drivers/staging/comedi/drivers/das16.c
+@@ -327,13 +327,13 @@ struct munge_info {
+ };
+ 
+ static int das16_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int das16_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int das16_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int das16_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ static int das16_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_cmd * cmd);
+@@ -1032,7 +1032,7 @@ static void das16_reset(struct comedi_device * dev)
+ }
+ 
+ static int das16_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+ 	int range;
+@@ -1080,7 +1080,7 @@ static int das16_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ static int das16_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bits;
+ 
+@@ -1092,7 +1092,7 @@ static int das16_di_rbits(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ static int das16_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int wbits;
+ 
+@@ -1112,7 +1112,7 @@ static int das16_do_wbits(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ static int das16_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int lsb, msb;
+diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
+index 0de3afcc0ece..ea1fd6ec699d 100644
+--- a/drivers/staging/comedi/drivers/das16m1.c
++++ b/drivers/staging/comedi/drivers/das16m1.c
+@@ -132,11 +132,11 @@ static const struct comedi_lrange range_das16m1 = { 9,
+ };
+ 
+ static int das16m1_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int das16m1_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int das16m1_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ static int das16m1_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_cmd * cmd);
+@@ -394,7 +394,7 @@ static int das16m1_cancel(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ static int das16m1_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+ 	int byte;
+@@ -431,7 +431,7 @@ static int das16m1_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ static int das16m1_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bits;
+ 
+@@ -443,7 +443,7 @@ static int das16m1_di_rbits(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ static int das16m1_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int wbits;
+ 
+diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
+index 8d8ecac73a08..cb53e8fe2403 100644
+--- a/drivers/staging/comedi/drivers/das1800.c
++++ b/drivers/staging/comedi/drivers/das1800.c
+@@ -200,13 +200,13 @@ static int das1800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subde
+ 	struct comedi_cmd * cmd);
+ static int das1800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int das1800_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int das1800_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int das1800_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int das1800_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ static int das1800_set_frequency(struct comedi_device * dev);
+ static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode);
+@@ -1553,7 +1553,7 @@ static int das1800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice
+ 
+ /* read analog input */
+ static int das1800_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+ 	int chan, range, aref, chan_range;
+@@ -1613,7 +1613,7 @@ static int das1800_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice
+ 
+ /* writes to an analog output channel */
+ static int das1800_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ //      int range = CR_RANGE(insn->chanspec);
+@@ -1642,7 +1642,7 @@ static int das1800_ao_winsn(struct comedi_device * dev, struct comedi_subdevice
+ 
+ /* reads from digital input channels */
+ static int das1800_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	data[1] = inb(dev->iobase + DAS1800_DIGITAL) & 0xf;
+@@ -1653,7 +1653,7 @@ static int das1800_di_rbits(struct comedi_device * dev, struct comedi_subdevice
+ 
+ /* writes to digital output channels */
+ static int das1800_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int wbits;
+ 
+diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
+index 6f94a6663eca..179a694b0745 100644
+--- a/drivers/staging/comedi/drivers/das800.c
++++ b/drivers/staging/comedi/drivers/das800.c
+@@ -263,11 +263,11 @@ static int das800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subdev
+ 	struct comedi_cmd * cmd);
+ static int das800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int das800_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int das800_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int das800_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int das800_probe(struct comedi_device * dev);
+ static int das800_set_frequency(struct comedi_device * dev);
+ 
+@@ -789,7 +789,7 @@ static int das800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ static int das800_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+ 	int chan;
+@@ -843,7 +843,7 @@ static int das800_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ static int das800_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bits;
+ 
+@@ -856,7 +856,7 @@ static int das800_di_rbits(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ static int das800_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int wbits;
+ 	unsigned long irq_flags;
+diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
+index 42c6c0e9a857..36e283ba753d 100644
+--- a/drivers/staging/comedi/drivers/dmm32at.c
++++ b/drivers/staging/comedi/drivers/dmm32at.c
+@@ -290,15 +290,15 @@ static struct comedi_driver driver_dmm32at = {
+ 
+ /* prototypes for driver functions below */
+ static int dmm32at_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int dmm32at_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int dmm32at_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int dmm32at_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int dmm32at_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int dmm32at_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_cmd * cmd);
+ static int dmm32at_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+@@ -498,7 +498,7 @@ static int dmm32at_detach(struct comedi_device * dev)
+  */
+ 
+ static int dmm32at_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i;
+ 	unsigned int d;
+@@ -894,7 +894,7 @@ static int dmm32at_ns_to_timer(unsigned int *ns, int round)
+ }
+ 
+ static int dmm32at_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -937,7 +937,7 @@ static int dmm32at_ao_winsn(struct comedi_device * dev, struct comedi_subdevice
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+ static int dmm32at_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -954,7 +954,7 @@ static int dmm32at_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+ static int dmm32at_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned char diobits;
+ 
+@@ -1007,7 +1007,7 @@ static int dmm32at_dio_insn_bits(struct comedi_device * dev, struct comedi_subde
+ }
+ 
+ static int dmm32at_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned char chanbit;
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c
+index dc815c130be0..847aa951d9c1 100644
+--- a/drivers/staging/comedi/drivers/dt2801.c
++++ b/drivers/staging/comedi/drivers/dt2801.c
+@@ -225,15 +225,15 @@ typedef struct {
+ #define devpriv ((dt2801_private *)dev->private)
+ 
+ static int dt2801_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int dt2801_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int dt2801_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int dt2801_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int dt2801_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ /* These are the low-level routines:
+    writecommand: write a command to the board
+@@ -606,7 +606,7 @@ static int dt2801_error(struct comedi_device * dev, int stat)
+ }
+ 
+ static int dt2801_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int d;
+ 	int stat;
+@@ -628,7 +628,7 @@ static int dt2801_ai_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int dt2801_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->ao_readback[CR_CHAN(insn->chanspec)];
+ 
+@@ -636,7 +636,7 @@ static int dt2801_ao_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int dt2801_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	dt2801_writecmd(dev, DT_C_WRITE_DAIM);
+ 	dt2801_writedata(dev, CR_CHAN(insn->chanspec));
+@@ -648,7 +648,7 @@ static int dt2801_ao_insn_write(struct comedi_device * dev, struct comedi_subdev
+ }
+ 
+ static int dt2801_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int which = 0;
+ 
+@@ -672,7 +672,7 @@ static int dt2801_dio_insn_bits(struct comedi_device * dev, struct comedi_subdev
+ }
+ 
+ static int dt2801_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int which = 0;
+ 
+diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c
+index 70d7bcf36820..165ea6f22ba4 100644
+--- a/drivers/staging/comedi/drivers/dt2811.c
++++ b/drivers/staging/comedi/drivers/dt2811.c
+@@ -227,15 +227,15 @@ static struct comedi_driver driver_dt2811 = {
+ COMEDI_INITCLEANUP(driver_dt2811);
+ 
+ static int dt2811_ai_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int dt2811_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int dt2811_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int dt2811_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int dt2811_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ enum { card_2811_pgh, card_2811_pgl };
+ typedef struct {
+@@ -491,7 +491,7 @@ static int dt2811_detach(struct comedi_device * dev)
+ }
+ 
+ static int dt2811_ai_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	int timeout = DT2811_TIMEOUT;
+@@ -542,7 +542,7 @@ int dt2811_adtrig(kdev_t minor, comedi_adtrig * adtrig)
+ #endif
+ 
+ static int dt2811_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan;
+@@ -560,7 +560,7 @@ static int dt2811_ao_insn(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ static int dt2811_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan;
+@@ -575,7 +575,7 @@ static int dt2811_ao_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int dt2811_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -586,7 +586,7 @@ static int dt2811_di_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int dt2811_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c
+index 2ee2fa307b10..f97fed0552a2 100644
+--- a/drivers/staging/comedi/drivers/dt2814.c
++++ b/drivers/staging/comedi/drivers/dt2814.c
+@@ -82,7 +82,7 @@ typedef struct {
+ #define DT2814_MAX_SPEED 100000	/* Arbitrary 10 khz limit */
+ 
+ static int dt2814_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i, hi, lo;
+ 	int chan;
+diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c
+index ffd75c7b9263..f9b79d2867eb 100644
+--- a/drivers/staging/comedi/drivers/dt2815.c
++++ b/drivers/staging/comedi/drivers/dt2815.c
+@@ -107,7 +107,7 @@ static int dt2815_wait_for_status(struct comedi_device * dev, int status)
+ }
+ 
+ static int dt2815_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -120,7 +120,7 @@ static int dt2815_ao_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int dt2815_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c
+index 203c6b3e8cbf..59376ac6c254 100644
+--- a/drivers/staging/comedi/drivers/dt2817.c
++++ b/drivers/staging/comedi/drivers/dt2817.c
+@@ -59,7 +59,7 @@ static struct comedi_driver driver_dt2817 = {
+ COMEDI_INITCLEANUP(driver_dt2817);
+ 
+ static int dt2817_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int mask;
+ 	int chan;
+@@ -97,7 +97,7 @@ static int dt2817_dio_insn_config(struct comedi_device * dev, struct comedi_subd
+ }
+ 
+ static int dt2817_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int changed;
+ 
+diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
+index 79308492bcb0..1a74f31ad3ff 100644
+--- a/drivers/staging/comedi/drivers/dt282x.c
++++ b/drivers/staging/comedi/drivers/dt282x.c
+@@ -675,7 +675,7 @@ static void dt282x_load_changain(struct comedi_device * dev, int n,
+  *      - trigger conversion and wait for it to finish
+  */
+ static int dt282x_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 
+@@ -938,7 +938,7 @@ static int dt282x_ns_to_timer(int *nanosec, int round_mode)
+  *      data register, and performs the conversion.
+  */
+ static int dt282x_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->ao[CR_CHAN(insn->chanspec)];
+ 
+@@ -946,7 +946,7 @@ static int dt282x_ao_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int dt282x_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	short d;
+ 	unsigned int chan;
+@@ -1146,7 +1146,7 @@ static int dt282x_ao_cancel(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ static int dt282x_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+ 		s->state &= ~data[0];
+@@ -1160,7 +1160,7 @@ static int dt282x_dio_insn_bits(struct comedi_device * dev, struct comedi_subdev
+ }
+ 
+ static int dt282x_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int mask;
+ 
+diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
+index 10875cfaa71c..4b140f21cbdf 100644
+--- a/drivers/staging/comedi/drivers/dt3000.c
++++ b/drivers/staging/comedi/drivers/dt3000.c
+@@ -668,7 +668,7 @@ static int dt3k_ai_cancel(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ static int dt3k_ai_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	unsigned int chan, gain, aref;
+@@ -686,7 +686,7 @@ static int dt3k_ai_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ }
+ 
+ static int dt3k_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	unsigned int chan;
+@@ -701,7 +701,7 @@ static int dt3k_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ }
+ 
+ static int dt3k_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	unsigned int chan;
+@@ -730,7 +730,7 @@ static void dt3k_dio_config(struct comedi_device * dev, int bits)
+ }
+ 
+ static int dt3k_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int mask;
+ 
+@@ -761,7 +761,7 @@ static int dt3k_dio_insn_config(struct comedi_device * dev, struct comedi_subdev
+ }
+ 
+ static int dt3k_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -777,7 +777,7 @@ static int dt3k_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevic
+ }
+ 
+ static int dt3k_mem_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int addr = CR_CHAN(insn->chanspec);
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c
+index a3d4afc60421..e2131fd4f45f 100644
+--- a/drivers/staging/comedi/drivers/dt9812.c
++++ b/drivers/staging/comedi/drivers/dt9812.c
+@@ -941,7 +941,7 @@ static void dt9812_comedi_open(struct comedi_device *dev)
+ }
+ 
+ static int dt9812_di_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
+-			   comedi_insn *insn, unsigned int *data)
++			   struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	u8 bits = 0;
+@@ -953,7 +953,7 @@ static int dt9812_di_rinsn(struct comedi_device *dev, struct comedi_subdevice *s
+ }
+ 
+ static int dt9812_do_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
+-			   comedi_insn *insn, unsigned int *data)
++			   struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	u8 bits = 0;
+@@ -971,7 +971,7 @@ static int dt9812_do_winsn(struct comedi_device *dev, struct comedi_subdevice *s
+ }
+ 
+ static int dt9812_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
+-			   comedi_insn *insn, unsigned int *data)
++			   struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 
+@@ -986,7 +986,7 @@ static int dt9812_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s
+ }
+ 
+ static int dt9812_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
+-			   comedi_insn *insn, unsigned int *data)
++			   struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	u16 value;
+@@ -1000,7 +1000,7 @@ static int dt9812_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s
+ }
+ 
+ static int dt9812_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
+-			   comedi_insn *insn, unsigned int *data)
++			   struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 
+diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c
+index 8b1e6c896517..cd6b3e037515 100644
+--- a/drivers/staging/comedi/drivers/fl512.c
++++ b/drivers/staging/comedi/drivers/fl512.c
+@@ -53,17 +53,17 @@ static struct comedi_driver driver_fl512 = {
+ COMEDI_INITCLEANUP(driver_fl512);
+ 
+ static int fl512_ai_insn(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
+ static int fl512_ao_insn(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
+ static int fl512_ao_insn_readback(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
+ 
+ /*
+  * fl512_ai_insn : this is the analog input function
+  */
+ static int fl512_ai_insn(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	unsigned int lo_byte, hi_byte;
+@@ -88,7 +88,7 @@ static int fl512_ai_insn(struct comedi_device * dev,
+  * fl512_ao_insn : used to write to a DA port n times
+  */
+ static int fl512_ao_insn(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);	/* get chan to write */
+@@ -109,7 +109,7 @@ static int fl512_ao_insn(struct comedi_device * dev,
+  * DA port
+  */
+ static int fl512_ao_insn_readback(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
+index 828fd315e644..5227e3ee273b 100644
+--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
++++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
+@@ -337,7 +337,7 @@ static struct comedi_driver driver_hpdi = {
+ COMEDI_PCI_INITCLEANUP(driver_hpdi, hpdi_pci_table);
+ 
+ static int dio_config_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+ 	case INSN_CONFIG_DIO_OUTPUT:
+diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
+index 7b10bc48a5ec..5463718e5ff7 100644
+--- a/drivers/staging/comedi/drivers/icp_multi.c
++++ b/drivers/staging/comedi/drivers/icp_multi.c
+@@ -238,7 +238,7 @@ static int icp_multi_reset(struct comedi_device *dev);
+ 	Parameters:
+ 		struct comedi_device *dev	Pointer to current device structure
+ 		struct comedi_subdevice *s	Pointer to current subdevice structure
+-		comedi_insn *insn	Pointer to current comedi instruction
++		struct comedi_insn *insn	Pointer to current comedi instruction
+ 		unsigned int *data		Pointer to analogue input data
+ 
+ 	Returns:int			Nmuber of instructions executed
+@@ -246,7 +246,7 @@ static int icp_multi_reset(struct comedi_device *dev);
+ ==============================================================================
+ */
+ static int icp_multi_insn_read_ai(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data)
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, timeout;
+ 
+@@ -357,7 +357,7 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev, struct comedi_subde
+ 	Parameters:
+ 		struct comedi_device *dev	Pointer to current device structure
+ 		struct comedi_subdevice *s	Pointer to current subdevice structure
+-		comedi_insn *insn	Pointer to current comedi instruction
++		struct comedi_insn *insn	Pointer to current comedi instruction
+ 		unsigned int *data		Pointer to analogue output data
+ 
+ 	Returns:int			Nmuber of instructions executed
+@@ -365,7 +365,7 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev, struct comedi_subde
+ ==============================================================================
+ */
+ static int icp_multi_insn_write_ao(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data)
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, chan, range, timeout;
+ 
+@@ -465,7 +465,7 @@ static int icp_multi_insn_write_ao(struct comedi_device *dev, struct comedi_subd
+ 	Parameters:
+ 		struct comedi_device *dev	Pointer to current device structure
+ 		struct comedi_subdevice *s	Pointer to current subdevice structure
+-		comedi_insn *insn	Pointer to current comedi instruction
++		struct comedi_insn *insn	Pointer to current comedi instruction
+ 		unsigned int *data		Pointer to analogue output data
+ 
+ 	Returns:int			Nmuber of instructions executed
+@@ -473,7 +473,7 @@ static int icp_multi_insn_write_ao(struct comedi_device *dev, struct comedi_subd
+ ==============================================================================
+ */
+ static int icp_multi_insn_read_ao(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data)
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, chan;
+ 
+@@ -498,7 +498,7 @@ static int icp_multi_insn_read_ao(struct comedi_device *dev, struct comedi_subde
+ 	Parameters:
+ 		struct comedi_device *dev	Pointer to current device structure
+ 		struct comedi_subdevice *s	Pointer to current subdevice structure
+-		comedi_insn *insn	Pointer to current comedi instruction
++		struct comedi_insn *insn	Pointer to current comedi instruction
+ 		unsigned int *data		Pointer to analogue output data
+ 
+ 	Returns:int			Nmuber of instructions executed
+@@ -506,7 +506,7 @@ static int icp_multi_insn_read_ao(struct comedi_device *dev, struct comedi_subde
+ ==============================================================================
+ */
+ static int icp_multi_insn_bits_di(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data)
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	data[1] = readw(devpriv->io_addr + ICP_MULTI_DI);
+ 
+@@ -524,7 +524,7 @@ static int icp_multi_insn_bits_di(struct comedi_device *dev, struct comedi_subde
+ 	Parameters:
+ 		struct comedi_device *dev	Pointer to current device structure
+ 		struct comedi_subdevice *s	Pointer to current subdevice structure
+-		comedi_insn *insn	Pointer to current comedi instruction
++		struct comedi_insn *insn	Pointer to current comedi instruction
+ 		unsigned int *data		Pointer to analogue output data
+ 
+ 	Returns:int			Nmuber of instructions executed
+@@ -532,7 +532,7 @@ static int icp_multi_insn_bits_di(struct comedi_device *dev, struct comedi_subde
+ ==============================================================================
+ */
+ static int icp_multi_insn_bits_do(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data)
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ #ifdef ICP_MULTI_EXTDEBUG
+ 	printk("icp multi EDBG: BGN: icp_multi_insn_bits_do(...)\n");
+@@ -566,7 +566,7 @@ static int icp_multi_insn_bits_do(struct comedi_device *dev, struct comedi_subde
+ 	Parameters:
+ 		struct comedi_device *dev	Pointer to current device structure
+ 		struct comedi_subdevice *s	Pointer to current subdevice structure
+-		comedi_insn *insn	Pointer to current comedi instruction
++		struct comedi_insn *insn	Pointer to current comedi instruction
+ 		unsigned int *data		Pointer to counter data
+ 
+ 	Returns:int			Nmuber of instructions executed
+@@ -574,7 +574,7 @@ static int icp_multi_insn_bits_do(struct comedi_device *dev, struct comedi_subde
+ ==============================================================================
+ */
+ static int icp_multi_insn_read_ctr(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data)
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	return 0;
+ }
+@@ -590,7 +590,7 @@ static int icp_multi_insn_read_ctr(struct comedi_device *dev, struct comedi_subd
+ 	Parameters:
+ 		struct comedi_device *dev	Pointer to current device structure
+ 		struct comedi_subdevice *s	Pointer to current subdevice structure
+-		comedi_insn *insn	Pointer to current comedi instruction
++		struct comedi_insn *insn	Pointer to current comedi instruction
+ 		unsigned int *data		Pointer to counter data
+ 
+ 	Returns:int			Nmuber of instructions executed
+@@ -598,7 +598,7 @@ static int icp_multi_insn_read_ctr(struct comedi_device *dev, struct comedi_subd
+ ==============================================================================
+ */
+ static int icp_multi_insn_write_ctr(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data)
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	return 0;
+ }
+diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c
+index ab62af50993b..5f513bac8e47 100644
+--- a/drivers/staging/comedi/drivers/ii_pci20kc.c
++++ b/drivers/staging/comedi/drivers/ii_pci20kc.c
+@@ -271,9 +271,9 @@ static int pci20xxx_detach(struct comedi_device * dev)
+ /* pci20006m */
+ 
+ static int pci20006_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int pci20006_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ static const struct comedi_lrange *pci20006_range_list[] = {
+ 	&range_bipolar10,
+@@ -307,7 +307,7 @@ static int pci20006_init(struct comedi_device * dev, struct comedi_subdevice * s
+ }
+ 
+ static int pci20006_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	pci20xxx_subdev_private *sdp = s->private;
+ 
+@@ -317,7 +317,7 @@ static int pci20006_insn_read(struct comedi_device * dev, struct comedi_subdevic
+ }
+ 
+ static int pci20006_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	pci20xxx_subdev_private *sdp = s->private;
+ 	int hi, lo;
+@@ -350,7 +350,7 @@ static int pci20006_insn_write(struct comedi_device * dev, struct comedi_subdevi
+ /* PCI20341M */
+ 
+ static int pci20341_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ static const int pci20341_timebase[] = { 0x00, 0x00, 0x00, 0x04 };
+ static const int pci20341_settling_time[] = { 0x58, 0x58, 0x93, 0x99 };
+@@ -398,7 +398,7 @@ static int pci20341_init(struct comedi_device * dev, struct comedi_subdevice * s
+ }
+ 
+ static int pci20341_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	pci20xxx_subdev_private *sdp = s->private;
+ 	unsigned int i = 0, j = 0;
+@@ -445,9 +445,9 @@ static int pci20341_insn_read(struct comedi_device * dev, struct comedi_subdevic
+ 
+ static void pci20xxx_dio_config(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int pci20xxx_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int pci20xxx_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ /* initialize pci20xxx_private */
+ static int pci20xxx_dio_init(struct comedi_device * dev, struct comedi_subdevice * s)
+@@ -470,7 +470,7 @@ static int pci20xxx_dio_init(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ static int pci20xxx_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int mask, bits;
+ 
+@@ -495,7 +495,7 @@ static int pci20xxx_dio_insn_config(struct comedi_device * dev, struct comedi_su
+ }
+ 
+ static int pci20xxx_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int mask = data[0];
+ 
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
+index 1f993147ad91..19371c6048d3 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -270,7 +270,7 @@ static six_axis_t get_max_full_scales(volatile jr3_channel_t * channel)
+ }
+ 
+ static int jr3_pci_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int result;
+ 	jr3_pci_subdev_private *p;
+diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c
+index 5ee1cf51aa13..f3b4f74e873d 100644
+--- a/drivers/staging/comedi/drivers/ke_counter.c
++++ b/drivers/staging/comedi/drivers/ke_counter.c
+@@ -100,7 +100,7 @@ COMEDI_PCI_INITCLEANUP(cnt_driver, cnt_pci_table);
+ /* This should be used only for resetting the counters; maybe it is better
+    to make a special command 'reset'. */
+ static int cnt_winsn(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+@@ -120,7 +120,7 @@ static int cnt_winsn(struct comedi_device * dev,
+ /*-- counter read -----------------------------------------------------------*/
+ 
+ static int cnt_rinsn(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned char a0, a1, a2, a3, a4;
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
+index 48802836346f..70c3cc2c307d 100644
+--- a/drivers/staging/comedi/drivers/me4000.c
++++ b/drivers/staging/comedi/drivers/me4000.c
+@@ -141,10 +141,10 @@ static int xilinx_download(struct comedi_device *dev);
+ static int reset_board(struct comedi_device *dev);
+ 
+ static int me4000_dio_insn_bits(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
+ 
+ static int me4000_dio_insn_config(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
+ 
+ static int cnt_reset(struct comedi_device *dev, unsigned int channel);
+ 
+@@ -152,16 +152,16 @@ static int cnt_config(struct comedi_device *dev,
+ 	unsigned int channel, unsigned int mode);
+ 
+ static int me4000_cnt_insn_config(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
+ 
+ static int me4000_cnt_insn_write(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
+ 
+ static int me4000_cnt_insn_read(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
+ 
+ static int me4000_ai_insn_read(struct comedi_device *dev,
+-	struct comedi_subdevice *subdevice, comedi_insn *insn, unsigned int *data);
++	struct comedi_subdevice *subdevice, struct comedi_insn *insn, unsigned int *data);
+ 
+ static int me4000_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
+ 
+@@ -191,10 +191,10 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
+ static int me4000_ai_do_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
+ 
+ static int me4000_ao_insn_write(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
+ 
+ static int me4000_ao_insn_read(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
+ 
+ /*-----------------------------------------------------------------------------
+   Meilhaus inline functions
+@@ -914,7 +914,7 @@ static int me4000_detach(struct comedi_device *dev)
+   ===========================================================================*/
+ 
+ static int me4000_ai_insn_read(struct comedi_device *dev,
+-	struct comedi_subdevice *subdevice, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *subdevice, struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -1904,7 +1904,7 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id PT_REGS_ARG)
+   ===========================================================================*/
+ 
+ static int me4000_ao_insn_write(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -1962,7 +1962,7 @@ static int me4000_ao_insn_write(struct comedi_device *dev,
+ }
+ 
+ static int me4000_ao_insn_read(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+@@ -1983,7 +1983,7 @@ static int me4000_ao_insn_read(struct comedi_device *dev,
+   ===========================================================================*/
+ 
+ static int me4000_dio_insn_bits(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	CALL_PDEBUG("In me4000_dio_insn_bits()\n");
+@@ -2034,7 +2034,7 @@ static int me4000_dio_insn_bits(struct comedi_device *dev,
+ }
+ 
+ static int me4000_dio_insn_config(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned long tmp;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -2216,7 +2216,7 @@ static int cnt_config(struct comedi_device *dev, unsigned int channel,
+ }
+ 
+ static int me4000_cnt_insn_config(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	int err;
+@@ -2259,7 +2259,7 @@ static int me4000_cnt_insn_config(struct comedi_device *dev,
+ }
+ 
+ static int me4000_cnt_insn_read(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	unsigned short tmp;
+@@ -2306,7 +2306,7 @@ static int me4000_cnt_insn_read(struct comedi_device *dev,
+ }
+ 
+ static int me4000_cnt_insn_write(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	unsigned short tmp;
+diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c
+index 1c19358a0ad4..901e1d13fcf2 100644
+--- a/drivers/staging/comedi/drivers/me_daq.c
++++ b/drivers/staging/comedi/drivers/me_daq.c
+@@ -292,7 +292,7 @@ static inline void sleep(unsigned sec)
+  * ------------------------------------------------------------------
+  */
+ static int me_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
+-			      comedi_insn *insn, unsigned int *data)
++			      struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int bits;
+ 	int mask = 1 << CR_CHAN(insn->chanspec);
+@@ -328,7 +328,7 @@ static int me_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice
+ 
+ /* Digital instant input/outputs */
+ static int me_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
+-			    comedi_insn *insn, unsigned int *data)
++			    struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int mask = data[0];
+ 	s->state &= ~mask;
+@@ -364,7 +364,7 @@ static int me_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *
+ 
+ /* Analog instant input */
+ static int me_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *subdevice,
+-			   comedi_insn *insn, unsigned int *data)
++			   struct comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned short value;
+ 	int chan = CR_CHAN((&insn->chanspec)[0]);
+@@ -471,7 +471,7 @@ static int me_ai_do_cmd(struct comedi_device *dev, struct comedi_subdevice *subd
+ 
+ /* Analog instant output */
+ static int me_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
+-			    comedi_insn *insn, unsigned int *data)
++			    struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan;
+ 	int rang;
+@@ -521,7 +521,7 @@ static int me_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *
+ 
+ /* Analog output readback */
+ static int me_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
+-			   comedi_insn *insn, unsigned int *data)
++			   struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 
+diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c
+index 59c3c17b616c..59e8ecd66088 100644
+--- a/drivers/staging/comedi/drivers/mpc624.c
++++ b/drivers/staging/comedi/drivers/mpc624.c
+@@ -156,7 +156,7 @@ static struct comedi_driver driver_mpc624 = {
+ 
+ //----------------------------------------------------------------------------
+ static int mpc624_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ //----------------------------------------------------------------------------
+ static int mpc624_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+@@ -269,7 +269,7 @@ static int mpc624_detach(struct comedi_device * dev)
+ #define TIMEOUT 200
+ 
+ static int mpc624_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i;
+ 	unsigned long int data_in, data_out;
+diff --git a/drivers/staging/comedi/drivers/mpc8260cpm.c b/drivers/staging/comedi/drivers/mpc8260cpm.c
+index 9588f2652d22..645c47053242 100644
+--- a/drivers/staging/comedi/drivers/mpc8260cpm.c
++++ b/drivers/staging/comedi/drivers/mpc8260cpm.c
+@@ -56,9 +56,9 @@ static struct comedi_driver driver_mpc8260cpm = {
+ COMEDI_INITCLEANUP(driver_mpc8260cpm);
+ 
+ static int mpc8260cpm_dio_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int mpc8260cpm_dio_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ static int mpc8260cpm_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+@@ -113,7 +113,7 @@ static unsigned long *cpm_pdat(int port)
+ }
+ 
+ static int mpc8260cpm_dio_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	unsigned int d;
+@@ -156,7 +156,7 @@ static int mpc8260cpm_dio_config(struct comedi_device * dev, struct comedi_subde
+ }
+ 
+ static int mpc8260cpm_dio_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int port;
+ 	unsigned long *p;
+diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c
+index 186676e5f86d..1ff60fa53842 100644
+--- a/drivers/staging/comedi/drivers/multiq3.c
++++ b/drivers/staging/comedi/drivers/multiq3.c
+@@ -99,7 +99,7 @@ struct multiq3_private {
+ #define devpriv ((struct multiq3_private *)dev->private)
+ 
+ static int multiq3_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+ 	int chan;
+@@ -135,7 +135,7 @@ static int multiq3_ai_insn_read(struct comedi_device * dev, struct comedi_subdev
+ }
+ 
+ static int multiq3_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -148,7 +148,7 @@ static int multiq3_ao_insn_read(struct comedi_device * dev, struct comedi_subdev
+ }
+ 
+ static int multiq3_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -166,7 +166,7 @@ static int multiq3_ao_insn_write(struct comedi_device * dev, struct comedi_subde
+ }
+ 
+ static int multiq3_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -177,7 +177,7 @@ static int multiq3_di_insn_bits(struct comedi_device * dev, struct comedi_subdev
+ }
+ 
+ static int multiq3_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -192,7 +192,7 @@ static int multiq3_do_insn_bits(struct comedi_device * dev, struct comedi_subdev
+ }
+ 
+ static int multiq3_encoder_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
+index f2ab049ee78c..52c35c4f0c03 100644
+--- a/drivers/staging/comedi/drivers/ni_6527.c
++++ b/drivers/staging/comedi/drivers/ni_6527.c
+@@ -120,7 +120,7 @@ typedef struct {
+ static int ni6527_find_device(struct comedi_device * dev, int bus, int slot);
+ 
+ static int ni6527_di_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	unsigned int interval;
+@@ -168,7 +168,7 @@ static int ni6527_di_insn_config(struct comedi_device * dev, struct comedi_subde
+ }
+ 
+ static int ni6527_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -181,7 +181,7 @@ static int ni6527_di_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int ni6527_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -327,7 +327,7 @@ static int ni6527_intr_cancel(struct comedi_device * dev, struct comedi_subdevic
+ }
+ 
+ static int ni6527_intr_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n < 1)
+ 		return -EINVAL;
+@@ -337,7 +337,7 @@ static int ni6527_intr_insn_bits(struct comedi_device * dev, struct comedi_subde
+ }
+ 
+ static int ni6527_intr_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n < 1)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
+index 95159e411d3e..7b439972290b 100644
+--- a/drivers/staging/comedi/drivers/ni_65xx.c
++++ b/drivers/staging/comedi/drivers/ni_65xx.c
+@@ -311,7 +311,7 @@ static ni_65xx_subdevice_private *ni_65xx_alloc_subdevice_private(void)
+ static int ni_65xx_find_device(struct comedi_device * dev, int bus, int slot);
+ 
+ static int ni_65xx_config_filter(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	const unsigned chan = CR_CHAN(insn->chanspec);
+ 	const unsigned port =
+@@ -350,7 +350,7 @@ static int ni_65xx_config_filter(struct comedi_device * dev, struct comedi_subde
+ }
+ 
+ static int ni_65xx_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned port;
+ 
+@@ -389,7 +389,7 @@ static int ni_65xx_dio_insn_config(struct comedi_device * dev, struct comedi_sub
+ }
+ 
+ static int ni_65xx_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned base_bitfield_channel;
+ 	const unsigned max_ports_per_bitfield = 5;
+@@ -569,7 +569,7 @@ static int ni_65xx_intr_cancel(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int ni_65xx_intr_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n < 1)
+ 		return -EINVAL;
+@@ -579,7 +579,7 @@ static int ni_65xx_intr_insn_bits(struct comedi_device * dev, struct comedi_subd
+ }
+ 
+ static int ni_65xx_intr_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n < 1)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
+index c347c9b3c2fa..7760df604359 100644
+--- a/drivers/staging/comedi/drivers/ni_660x.c
++++ b/drivers/staging/comedi/drivers/ni_660x.c
+@@ -465,17 +465,17 @@ static int ni_660x_set_pfi_routing(struct comedi_device * dev, unsigned chan,
+ 
+ /* Possible instructions for a GPCT */
+ static int ni_660x_GPCT_rinsn(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
+ static int ni_660x_GPCT_insn_config(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
+ static int ni_660x_GPCT_winsn(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
+ 
+ /* Possible instructions for Digital IO */
+ static int ni_660x_dio_insn_config(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
+ static int ni_660x_dio_insn_bits(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
+ 
+ static inline unsigned ni_660x_num_counters(struct comedi_device * dev)
+ {
+@@ -1121,7 +1121,7 @@ static int ni_660x_detach(struct comedi_device * dev)
+ 
+ static int
+ ni_660x_GPCT_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	return ni_tio_rinsn(subdev_to_counter(s), insn, data);
+ }
+@@ -1148,13 +1148,13 @@ static void init_tio_chip(struct comedi_device * dev, int chipset)
+ 
+ static int
+ ni_660x_GPCT_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	return ni_tio_insn_config(subdev_to_counter(s), insn, data);
+ }
+ 
+ static int ni_660x_GPCT_winsn(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	return ni_tio_winsn(subdev_to_counter(s), insn, data);
+ }
+@@ -1187,7 +1187,7 @@ static int ni_660x_find_device(struct comedi_device * dev, int bus, int slot)
+ }
+ 
+ static int ni_660x_dio_insn_bits(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned base_bitfield_channel = CR_CHAN(insn->chanspec);
+ 
+@@ -1280,7 +1280,7 @@ static void ni660x_config_filter(struct comedi_device * dev, unsigned pfi_channe
+ }
+ 
+ static int ni_660x_dio_insn_config(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
+index e66bde6dbf21..7c07ebbd2f07 100644
+--- a/drivers/staging/comedi/drivers/ni_670x.c
++++ b/drivers/staging/comedi/drivers/ni_670x.c
+@@ -125,13 +125,13 @@ static struct comedi_lrange range_0_20mA = { 1, {RANGE_mA(0, 20)} };
+ static int ni_670x_find_device(struct comedi_device * dev, int bus, int slot);
+ 
+ static int ni_670x_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int ni_670x_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int ni_670x_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int ni_670x_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ static int ni_670x_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+@@ -219,7 +219,7 @@ static int ni_670x_detach(struct comedi_device * dev)
+ }
+ 
+ static int ni_670x_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -245,7 +245,7 @@ static int ni_670x_ao_winsn(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ static int ni_670x_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -257,7 +257,7 @@ static int ni_670x_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ static int ni_670x_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -279,7 +279,7 @@ static int ni_670x_dio_insn_bits(struct comedi_device * dev, struct comedi_subde
+ }
+ 
+ static int ni_670x_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
+index 8a13e8624b04..6f2f8d35dc11 100644
+--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
++++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
+@@ -183,7 +183,7 @@ static int a2150_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice
+ 	struct comedi_cmd * cmd);
+ static int a2150_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int a2150_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int a2150_get_timing(struct comedi_device * dev, unsigned int *period,
+ 	int flags);
+ static int a2150_probe(struct comedi_device * dev);
+@@ -727,7 +727,7 @@ static int a2150_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ }
+ 
+ static int a2150_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int i, n;
+ 	static const int timeout = 100000;
+diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c
+index 2176bb2d743d..c42d89d41e7a 100644
+--- a/drivers/staging/comedi/drivers/ni_at_ao.c
++++ b/drivers/staging/comedi/drivers/ni_at_ao.c
+@@ -195,17 +195,17 @@ COMEDI_INITCLEANUP(driver_atao);
+ static void atao_reset(struct comedi_device * dev);
+ 
+ static int atao_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int atao_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int atao_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int atao_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int atao_calib_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int atao_calib_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ static int atao_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+@@ -321,7 +321,7 @@ static void atao_reset(struct comedi_device * dev)
+ }
+ 
+ static int atao_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -345,7 +345,7 @@ static int atao_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s
+ }
+ 
+ static int atao_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -357,7 +357,7 @@ static int atao_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s
+ }
+ 
+ static int atao_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -374,7 +374,7 @@ static int atao_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevic
+ }
+ 
+ static int atao_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	unsigned int mask, bit;
+@@ -419,7 +419,7 @@ static int atao_dio_insn_config(struct comedi_device * dev, struct comedi_subdev
+  * the caldacs, but we can guess.
+  */
+ static int atao_calib_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	for (i = 0; i < insn->n; i++) {
+@@ -429,7 +429,7 @@ static int atao_calib_insn_read(struct comedi_device * dev, struct comedi_subdev
+ }
+ 
+ static int atao_calib_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bitstring, bit;
+ 	unsigned int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
+index 09cafa966747..4d3cb5fa48b0 100644
+--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
++++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
+@@ -526,7 +526,7 @@ static int atmio16d_ai_cancel(struct comedi_device * dev, struct comedi_subdevic
+ 
+ /* Mode 0 is used to get a single conversion on demand */
+ static int atmio16d_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, t;
+ 	int chan;
+@@ -585,7 +585,7 @@ static int atmio16d_ai_insn_read(struct comedi_device * dev, struct comedi_subde
+ }
+ 
+ static int atmio16d_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ #ifdef DEBUG1
+@@ -600,7 +600,7 @@ static int atmio16d_ao_insn_read(struct comedi_device * dev, struct comedi_subde
+ }
+ 
+ static int atmio16d_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan;
+@@ -635,7 +635,7 @@ static int atmio16d_ao_insn_write(struct comedi_device * dev, struct comedi_subd
+ }
+ 
+ static int atmio16d_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -651,7 +651,7 @@ static int atmio16d_dio_insn_bits(struct comedi_device * dev, struct comedi_subd
+ }
+ 
+ static int atmio16d_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int mask;
+diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
+index d592ab368ff5..a1a0663b82b3 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_700.c
++++ b/drivers/staging/comedi/drivers/ni_daq_700.c
+@@ -154,7 +154,7 @@ static int subdev_700_cb(int dir, int port, int data, unsigned long arg)
+ }
+ 
+ static int subdev_700_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+ 		s->state &= ~data[0];
+@@ -172,7 +172,7 @@ static int subdev_700_insn(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ static int subdev_700_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	switch (data[0]) {
+diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
+index 2b3b4664bead..f6ab0fde2c11 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc.c
++++ b/drivers/staging/comedi/drivers/ni_labpc.c
+@@ -174,19 +174,19 @@ static int labpc_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice
+ 	struct comedi_cmd * cmd);
+ static int labpc_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int labpc_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int labpc_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int labpc_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int labpc_calib_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int labpc_calib_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int labpc_eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int labpc_eeprom_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd);
+ static void labpc_adc_timing(struct comedi_device * dev, struct comedi_cmd * cmd);
+ #ifdef CONFIG_COMEDI_PCI
+@@ -1501,7 +1501,7 @@ static void labpc_drain_dregs(struct comedi_device * dev)
+ }
+ 
+ static int labpc_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+ 	int chan, range;
+@@ -1587,7 +1587,7 @@ static int labpc_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ 
+ // analog output insn
+ static int labpc_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel, range;
+ 	unsigned long flags;
+@@ -1628,7 +1628,7 @@ static int labpc_ao_winsn(struct comedi_device * dev, struct comedi_subdevice *
+ 
+ // analog output readback insn
+ static int labpc_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)];
+ 
+@@ -1636,7 +1636,7 @@ static int labpc_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ static int labpc_calib_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->caldac[CR_CHAN(insn->chanspec)];
+ 
+@@ -1644,7 +1644,7 @@ static int labpc_calib_read_insn(struct comedi_device * dev, struct comedi_subde
+ }
+ 
+ static int labpc_calib_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel = CR_CHAN(insn->chanspec);
+ 
+@@ -1653,7 +1653,7 @@ static int labpc_calib_write_insn(struct comedi_device * dev, struct comedi_subd
+ }
+ 
+ static int labpc_eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->eeprom_data[CR_CHAN(insn->chanspec)];
+ 
+@@ -1661,7 +1661,7 @@ static int labpc_eeprom_read_insn(struct comedi_device * dev, struct comedi_subd
+ }
+ 
+ static int labpc_eeprom_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel = CR_CHAN(insn->chanspec);
+ 	int ret;
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index a2988bdb2652..52984b0a1b7b 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -194,9 +194,9 @@ static const struct comedi_lrange *const ni_range_lkup[] = {
+ };
+ 
+ static int ni_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int ni_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int ni_cdio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_cmd * cmd);
+ static int ni_cdio_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+@@ -206,33 +206,33 @@ static int ni_cdo_inttrig(struct comedi_device * dev, struct comedi_subdevice *
+ 	unsigned int trignum);
+ 
+ static int ni_serial_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int ni_serial_hw_readwrite8(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned char data_out, unsigned char *data_in);
+ static int ni_serial_sw_readwrite8(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned char data_out, unsigned char *data_in);
+ 
+ static int ni_calib_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int ni_calib_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ static int ni_eeprom_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int ni_m_series_eeprom_insn_read(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
+ 
+ static int ni_pfi_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int ni_pfi_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static unsigned ni_old_get_pfi_routing(struct comedi_device * dev, unsigned chan);
+ 
+ static void ni_rtsi_init(struct comedi_device * dev);
+ static int ni_rtsi_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int ni_rtsi_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ static void caldac_setup(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int ni_read_eeprom(struct comedi_device * dev, int addr);
+@@ -268,11 +268,11 @@ static int ni_ao_reset(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int ni_8255_callback(int dir, int port, int data, unsigned long arg);
+ 
+ static int ni_gpct_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int ni_gpct_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int ni_gpct_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int ni_gpct_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int ni_gpct_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_cmd * cmd);
+@@ -283,7 +283,7 @@ static void handle_gpct_interrupt(struct comedi_device * dev,
+ static int init_cs5529(struct comedi_device * dev);
+ static int cs5529_do_conversion(struct comedi_device * dev, unsigned short *data);
+ static int cs5529_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ #ifdef NI_CS5529_DEBUG
+ static unsigned int cs5529_config_read(struct comedi_device * dev,
+ 	unsigned int reg_select_bits);
+@@ -292,9 +292,9 @@ static void cs5529_config_write(struct comedi_device * dev, unsigned int value,
+ 	unsigned int reg_select_bits);
+ 
+ static int ni_m_series_pwm_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int ni_6143_pwm_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ static int ni_set_master_clock(struct comedi_device * dev, unsigned source,
+ 	unsigned period_ns);
+@@ -1719,7 +1719,7 @@ static int ni_ai_poll(struct comedi_device * dev, struct comedi_subdevice * s)
+ }
+ 
+ static int ni_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+ 	const unsigned int mask = (1 << boardtype.adbits) - 1;
+@@ -2626,10 +2626,10 @@ static int ni_ai_inttrig(struct comedi_device * dev, struct comedi_subdevice * s
+ }
+ 
+ static int ni_ai_config_analog_trig(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ static int ni_ai_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n < 1)
+ 		return -EINVAL;
+@@ -2680,7 +2680,7 @@ static int ni_ai_insn_config(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ static int ni_ai_config_analog_trig(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int a, b, modebits;
+ 	int err = 0;
+@@ -2922,7 +2922,7 @@ static int ni_ao_config_chanlist(struct comedi_device * dev, struct comedi_subde
+ 		return ni_old_ao_config_chanlist(dev, s, chanspec, n_chans);
+ }
+ static int ni_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->ao[CR_CHAN(insn->chanspec)];
+ 
+@@ -2930,7 +2930,7 @@ static int ni_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ static int ni_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int chan = CR_CHAN(insn->chanspec);
+ 	unsigned int invert;
+@@ -2949,7 +2949,7 @@ static int ni_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ static int ni_ao_insn_write_671x(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int chan = CR_CHAN(insn->chanspec);
+ 	unsigned int invert;
+@@ -2966,7 +2966,7 @@ static int ni_ao_insn_write_671x(struct comedi_device * dev, struct comedi_subde
+ }
+ 
+ static int ni_ao_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+ 	case INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE:
+@@ -3437,7 +3437,7 @@ static int ni_ao_reset(struct comedi_device * dev, struct comedi_subdevice * s)
+ // digital io
+ 
+ static int ni_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ #ifdef DEBUG_DIO
+ 	rt_printk("ni_dio_insn_config() chan=%d io=%d\n",
+@@ -3469,7 +3469,7 @@ static int ni_dio_insn_config(struct comedi_device * dev, struct comedi_subdevic
+ }
+ 
+ static int ni_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ #ifdef DEBUG_DIO
+ 	rt_printk("ni_dio_insn_bits() mask=0x%x bits=0x%x\n", data[0], data[1]);
+@@ -3496,7 +3496,7 @@ static int ni_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ static int ni_m_series_dio_insn_config(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ #ifdef DEBUG_DIO
+ 	rt_printk("ni_m_series_dio_insn_config() chan=%d io=%d\n",
+@@ -3526,7 +3526,7 @@ static int ni_m_series_dio_insn_config(struct comedi_device * dev,
+ }
+ 
+ static int ni_m_series_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ #ifdef DEBUG_DIO
+ 	rt_printk("ni_m_series_dio_insn_bits() mask=0x%x bits=0x%x\n", data[0],
+@@ -3791,7 +3791,7 @@ static void handle_cdio_interrupt(struct comedi_device * dev)
+ }
+ 
+ static int ni_serial_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int err = insn->n;
+ 	unsigned char byte_out, byte_in = 0;
+@@ -4209,14 +4209,14 @@ static unsigned ni_gpct_read_register(struct ni_gpct *counter,
+ }
+ 
+ static int ni_freq_out_insn_read(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->clock_and_fout & FOUT_Divider_mask;
+ 	return 1;
+ }
+ 
+ static int ni_freq_out_insn_write(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	devpriv->clock_and_fout &= ~FOUT_Enable;
+ 	devpriv->stc_writew(dev, devpriv->clock_and_fout,
+@@ -4259,7 +4259,7 @@ static void ni_get_freq_out_clock(struct comedi_device * dev, unsigned int * clo
+ }
+ 
+ static int ni_freq_out_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+ 	case INSN_CONFIG_SET_CLOCK_SRC:
+@@ -4624,7 +4624,7 @@ static int ni_8255_callback(int dir, int port, int data, unsigned long arg)
+ */
+ 
+ static int ni_eeprom_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = ni_read_eeprom(dev, CR_CHAN(insn->chanspec));
+ 
+@@ -4660,7 +4660,7 @@ static int ni_read_eeprom(struct comedi_device * dev, int addr)
+ }
+ 
+ static int ni_m_series_eeprom_insn_read(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->eeprom_buffer[CR_CHAN(insn->chanspec)];
+ 
+@@ -4675,7 +4675,7 @@ static int ni_get_pwm_config(struct comedi_device * dev, unsigned int * data)
+ }
+ 
+ static int ni_m_series_pwm_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned up_count, down_count;
+ 	switch (data[0]) {
+@@ -4740,7 +4740,7 @@ static int ni_m_series_pwm_config(struct comedi_device * dev, struct comedi_subd
+ }
+ 
+ static int ni_6143_pwm_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned up_count, down_count;
+ 	switch (data[0]) {
+@@ -4807,7 +4807,7 @@ static void ni_write_caldac(struct comedi_device * dev, int addr, int val);
+ 	calibration subdevice
+ */
+ static int ni_calib_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	ni_write_caldac(dev, CR_CHAN(insn->chanspec), data[0]);
+ 
+@@ -4815,7 +4815,7 @@ static int ni_calib_insn_write(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int ni_calib_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->caldacs[CR_CHAN(insn->chanspec)];
+ 
+@@ -5071,21 +5071,21 @@ static void GPCT_Reset(struct comedi_device * dev, int chan)
+ #endif
+ 
+ static int ni_gpct_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	struct ni_gpct *counter = s->private;
+ 	return ni_tio_insn_config(counter, insn, data);
+ }
+ 
+ static int ni_gpct_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	struct ni_gpct *counter = s->private;
+ 	return ni_tio_rinsn(counter, insn, data);
+ }
+ 
+ static int ni_gpct_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	struct ni_gpct *counter = s->private;
+ 	return ni_tio_winsn(counter, insn, data);
+@@ -5254,7 +5254,7 @@ static int ni_config_filter(struct comedi_device * dev, unsigned pfi_channel,
+ }
+ 
+ static int ni_pfi_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if ((boardtype.reg_type & ni_reg_m_series_mask) == 0) {
+ 		return -ENOTSUPP;
+@@ -5269,7 +5269,7 @@ static int ni_pfi_insn_bits(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ static int ni_pfi_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int chan;
+ 
+@@ -5346,7 +5346,7 @@ static void ni_rtsi_init(struct comedi_device * dev)
+ }
+ 
+ static int ni_rtsi_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -5627,7 +5627,7 @@ static unsigned ni_get_rtsi_routing(struct comedi_device * dev, unsigned chan)
+ }
+ 
+ static int ni_rtsi_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int chan = CR_CHAN(insn->chanspec);
+ 	switch (data[0]) {
+@@ -5806,7 +5806,7 @@ static int cs5529_do_conversion(struct comedi_device * dev, unsigned short *data
+ }
+ 
+ static int cs5529_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, retval;
+ 	unsigned short sample;
+diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
+index 9787a6e9f951..d7cdb38d5097 100644
+--- a/drivers/staging/comedi/drivers/ni_pcidio.c
++++ b/drivers/staging/comedi/drivers/ni_pcidio.c
+@@ -703,7 +703,7 @@ static void debug_int(struct comedi_device * dev)
+ #endif
+ 
+ static int ni_pcidio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 1)
+ 		return -EINVAL;
+@@ -730,7 +730,7 @@ static int ni_pcidio_insn_config(struct comedi_device * dev, struct comedi_subde
+ }
+ 
+ static int ni_pcidio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c
+index f5385b903d41..05a957540398 100644
+--- a/drivers/staging/comedi/drivers/ni_tio.c
++++ b/drivers/staging/comedi/drivers/ni_tio.c
+@@ -1534,7 +1534,7 @@ static int ni_tio_get_gate_src(struct ni_gpct *counter, unsigned gate_index,
+ }
+ 
+ int ni_tio_insn_config(struct ni_gpct *counter,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+ 	case INSN_CONFIG_SET_COUNTER_MODE:
+@@ -1578,7 +1578,7 @@ int ni_tio_insn_config(struct ni_gpct *counter,
+ 	return -EINVAL;
+ }
+ 
+-int ni_tio_rinsn(struct ni_gpct *counter, comedi_insn * insn, unsigned int * data)
++int ni_tio_rinsn(struct ni_gpct *counter, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	struct ni_gpct_device *counter_dev = counter->counter_dev;
+ 	const unsigned channel = CR_CHAN(insn->chanspec);
+@@ -1642,7 +1642,7 @@ static unsigned ni_tio_next_load_register(struct ni_gpct *counter)
+ 	}
+ }
+ 
+-int ni_tio_winsn(struct ni_gpct *counter, comedi_insn * insn, unsigned int * data)
++int ni_tio_winsn(struct ni_gpct *counter, struct comedi_insn * insn, unsigned int * data)
+ {
+ 	struct ni_gpct_device *counter_dev = counter->counter_dev;
+ 	const unsigned channel = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/ni_tio.h b/drivers/staging/comedi/drivers/ni_tio.h
+index de68c8694dfa..0729d60b01cc 100644
+--- a/drivers/staging/comedi/drivers/ni_tio.h
++++ b/drivers/staging/comedi/drivers/ni_tio.h
+@@ -140,11 +140,11 @@ extern struct ni_gpct_device *ni_gpct_device_construct(struct comedi_device * de
+ extern void ni_gpct_device_destroy(struct ni_gpct_device *counter_dev);
+ extern void ni_tio_init_counter(struct ni_gpct *counter);
+ extern int ni_tio_rinsn(struct ni_gpct *counter,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ extern int ni_tio_insn_config(struct ni_gpct *counter,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ extern int ni_tio_winsn(struct ni_gpct *counter,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ extern int ni_tio_cmd(struct ni_gpct *counter, struct comedi_async *async);
+ extern int ni_tio_cmdtest(struct ni_gpct *counter, struct comedi_cmd * cmd);
+ extern int ni_tio_cancel(struct ni_gpct *counter);
+diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c
+index 68bd7e963db4..01ea3eb7554a 100644
+--- a/drivers/staging/comedi/drivers/pcl711.c
++++ b/drivers/staging/comedi/drivers/pcl711.c
+@@ -241,7 +241,7 @@ static void pcl711_set_changain(struct comedi_device * dev, int chan)
+ }
+ 
+ static int pcl711_ai_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+ 	int hi, lo;
+@@ -428,7 +428,7 @@ static int pcl711_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s
+    analog output
+ */
+ static int pcl711_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -446,7 +446,7 @@ static int pcl711_ao_insn(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ static int pcl711_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -461,7 +461,7 @@ static int pcl711_ao_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ 
+ /* Digital port read - Untested on 8112 */
+ static int pcl711_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -474,7 +474,7 @@ static int pcl711_di_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+ 
+ /* Digital port write - Untested on 8112 */
+ static int pcl711_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c
+index b9af0c045e7c..455117d043b5 100644
+--- a/drivers/staging/comedi/drivers/pcl724.c
++++ b/drivers/staging/comedi/drivers/pcl724.c
+@@ -36,7 +36,7 @@ See the source for configuration details.
+ */
+ /*
+  * check_driver overrides:
+- *   comedi_insn
++ *   struct comedi_insn
+  */
+ 
+ #include "../comedidev.h"
+diff --git a/drivers/staging/comedi/drivers/pcl725.c b/drivers/staging/comedi/drivers/pcl725.c
+index 570193598d98..d9f7c24bbdb0 100644
+--- a/drivers/staging/comedi/drivers/pcl725.c
++++ b/drivers/staging/comedi/drivers/pcl725.c
+@@ -32,7 +32,7 @@ static struct comedi_driver driver_pcl725 = {
+ COMEDI_INITCLEANUP(driver_pcl725);
+ 
+ static int pcl725_do_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -49,7 +49,7 @@ static int pcl725_do_insn(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ static int pcl725_di_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c
+index a76cf622aef5..f0c8b0af8d56 100644
+--- a/drivers/staging/comedi/drivers/pcl726.c
++++ b/drivers/staging/comedi/drivers/pcl726.c
+@@ -169,7 +169,7 @@ typedef struct {
+ #define devpriv ((pcl726_private *)dev->private)
+ 
+ static int pcl726_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int hi, lo;
+ 	int n;
+@@ -194,7 +194,7 @@ static int pcl726_ao_insn(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ static int pcl726_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	int n;
+@@ -206,7 +206,7 @@ static int pcl726_ao_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int pcl726_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -218,7 +218,7 @@ static int pcl726_di_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int pcl726_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c
+index 63b4a35159a8..05d9f76e9336 100644
+--- a/drivers/staging/comedi/drivers/pcl730.c
++++ b/drivers/staging/comedi/drivers/pcl730.c
+@@ -56,7 +56,7 @@ static struct comedi_driver driver_pcl730 = {
+ COMEDI_INITCLEANUP(driver_pcl730);
+ 
+ static int pcl730_do_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -78,7 +78,7 @@ static int pcl730_do_insn(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ static int pcl730_di_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
+index c554ed583eed..7b0a95c0e983 100644
+--- a/drivers/staging/comedi/drivers/pcl812.c
++++ b/drivers/staging/comedi/drivers/pcl812.c
+@@ -434,7 +434,7 @@ static int pcl812_ai_cancel(struct comedi_device * dev, struct comedi_subdevice
+ ==============================================================================
+ */
+ static int pcl812_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int timeout, hi;
+@@ -468,7 +468,7 @@ static int pcl812_ai_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ ==============================================================================
+ */
+ static int acl8216_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int timeout;
+@@ -504,7 +504,7 @@ static int acl8216_ai_insn_read(struct comedi_device * dev, struct comedi_subdev
+ ==============================================================================
+ */
+ static int pcl812_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	int i;
+@@ -524,7 +524,7 @@ static int pcl812_ao_insn_write(struct comedi_device * dev, struct comedi_subdev
+ ==============================================================================
+ */
+ static int pcl812_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	int i;
+@@ -540,7 +540,7 @@ static int pcl812_ao_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ ==============================================================================
+ */
+ static int pcl812_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -555,7 +555,7 @@ static int pcl812_di_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+ ==============================================================================
+ */
+ static int pcl812_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
+index 60d7a2c1d190..9542d0e8e5fb 100644
+--- a/drivers/staging/comedi/drivers/pcl816.c
++++ b/drivers/staging/comedi/drivers/pcl816.c
+@@ -227,7 +227,7 @@ static int pcl816_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s
+    ANALOG INPUT MODE0, 816 cards, slow version
+ */
+ static int pcl816_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int timeout;
+diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
+index 9eaabfb18042..4b315c090baf 100644
+--- a/drivers/staging/comedi/drivers/pcl818.c
++++ b/drivers/staging/comedi/drivers/pcl818.c
+@@ -388,7 +388,7 @@ static int rtc_setfreq_irq(int freq);
+    ANALOG INPUT MODE0, 818 cards, slow version
+ */
+ static int pcl818_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int timeout;
+@@ -435,7 +435,7 @@ static int pcl818_ai_insn_read(struct comedi_device * dev, struct comedi_subdevi
+    only one sample per call is supported
+ */
+ static int pcl818_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -448,7 +448,7 @@ static int pcl818_ao_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int pcl818_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -471,7 +471,7 @@ static int pcl818_ao_insn_write(struct comedi_device * dev, struct comedi_subdev
+    only one sample per call is supported
+ */
+ static int pcl818_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -489,7 +489,7 @@ static int pcl818_di_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+    only one sample per call is supported
+ */
+ static int pcl818_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c
+index 5d965466f0f2..08a63ebfa62e 100644
+--- a/drivers/staging/comedi/drivers/pcm3724.c
++++ b/drivers/staging/comedi/drivers/pcm3724.c
+@@ -25,7 +25,7 @@ Copy/pasted/hacked from pcm724.c
+ */
+ /*
+  * check_driver overrides:
+- *   comedi_insn
++ *   struct comedi_insn
+  */
+ 
+ #include "../comedidev.h"
+@@ -215,7 +215,7 @@ static void enable_chan(struct comedi_device * dev, struct comedi_subdevice * s,
+ 
+ /* overriding the 8255 insn config */
+ static int subdev_3724_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int mask;
+ 	unsigned int bits;
+diff --git a/drivers/staging/comedi/drivers/pcm3730.c b/drivers/staging/comedi/drivers/pcm3730.c
+index b505a015be06..63b961b32e2b 100644
+--- a/drivers/staging/comedi/drivers/pcm3730.c
++++ b/drivers/staging/comedi/drivers/pcm3730.c
+@@ -40,7 +40,7 @@ static struct comedi_driver driver_pcm3730 = {
+ COMEDI_INITCLEANUP(driver_pcm3730);
+ 
+ static int pcm3730_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -55,7 +55,7 @@ static int pcm3730_do_insn_bits(struct comedi_device * dev, struct comedi_subdev
+ }
+ 
+ static int pcm3730_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c
+index b129a473587b..fe3990983aeb 100644
+--- a/drivers/staging/comedi/drivers/pcmad.c
++++ b/drivers/staging/comedi/drivers/pcmad.c
+@@ -93,7 +93,7 @@ COMEDI_INITCLEANUP(driver_pcmad);
+ #define TIMEOUT	100
+ 
+ static int pcmad_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan;
+diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c
+index 9442eed9271d..d9f0b03486d0 100644
+--- a/drivers/staging/comedi/drivers/pcmda12.c
++++ b/drivers/staging/comedi/drivers/pcmda12.c
+@@ -139,9 +139,9 @@ static struct comedi_driver driver = {
+ };
+ 
+ static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ /*
+  * Attach is called by the Comedi core to configure the driver
+@@ -240,7 +240,7 @@ static void zero_chans(struct comedi_device * dev)
+ }
+ 
+ static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -282,7 +282,7 @@ static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+    This is useful for some control applications, I would imagine.
+ */
+ static int ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
+index f428f6923f59..e44dee964aaa 100644
+--- a/drivers/staging/comedi/drivers/pcmmio.c
++++ b/drivers/staging/comedi/drivers/pcmmio.c
+@@ -140,13 +140,13 @@ Configuration Options:
+ #define PAGE_INT_ID 3
+ 
+ typedef int (*comedi_insn_fn_t) (struct comedi_device *, struct comedi_subdevice *,
+-	comedi_insn *, unsigned int *);
++	struct comedi_insn *, unsigned int *);
+ 
+-static int ai_rinsn(struct comedi_device *, struct comedi_subdevice *, comedi_insn *,
++static int ai_rinsn(struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *,
+ 	unsigned int *);
+-static int ao_rinsn(struct comedi_device *, struct comedi_subdevice *, comedi_insn *,
++static int ao_rinsn(struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *,
+ 	unsigned int *);
+-static int ao_winsn(struct comedi_device *, struct comedi_subdevice *, comedi_insn *,
++static int ao_winsn(struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *,
+ 	unsigned int *);
+ 
+ /*
+@@ -296,9 +296,9 @@ static struct comedi_driver driver = {
+ };
+ 
+ static int pcmmio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int pcmmio_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ static irqreturn_t interrupt_pcmmio(int irq, void *d PT_REGS_ARG);
+ static void pcmmio_stop_intr(struct comedi_device *, struct comedi_subdevice *);
+@@ -551,7 +551,7 @@ static int pcmmio_detach(struct comedi_device * dev)
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+ static int pcmmio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int byte_no;
+ 	if (insn->n != 2)
+@@ -625,7 +625,7 @@ static int pcmmio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdev
+  * contains the channel to be changed, and data[0] contains the
+  * value COMEDI_INPUT or COMEDI_OUTPUT. */
+ static int pcmmio_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec), byte_no = chan / 8, bit_no =
+ 		chan % 8;
+@@ -1195,7 +1195,7 @@ static int adc_wait_ready(unsigned long iobase)
+ 
+ /* All this is for AI and AO */
+ static int ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	unsigned long iobase = subpriv->iobase;
+@@ -1259,7 +1259,7 @@ static int ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ }
+ 
+ static int ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	for (n = 0; n < insn->n; n++) {
+@@ -1289,7 +1289,7 @@ static int wait_dac_ready(unsigned long iobase)
+ }
+ 
+ static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	unsigned iobase = subpriv->iobase, iooffset = 0;
+diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
+index 2c460cf67c89..fca574b60436 100644
+--- a/drivers/staging/comedi/drivers/pcmuio.c
++++ b/drivers/staging/comedi/drivers/pcmuio.c
+@@ -254,9 +254,9 @@ static struct comedi_driver driver = {
+ };
+ 
+ static int pcmuio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int pcmuio_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ static irqreturn_t interrupt_pcmuio(int irq, void *d PT_REGS_ARG);
+ static void pcmuio_stop_intr(struct comedi_device *, struct comedi_subdevice *);
+@@ -475,7 +475,7 @@ static int pcmuio_detach(struct comedi_device * dev)
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+ static int pcmuio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int byte_no;
+ 	if (insn->n != 2)
+@@ -549,7 +549,7 @@ static int pcmuio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdev
+  * contains the channel to be changed, and data[0] contains the
+  * value COMEDI_INPUT or COMEDI_OUTPUT. */
+ static int pcmuio_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec), byte_no = chan / 8, bit_no =
+ 		chan % 8;
+diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c
+index b1b1138c4d50..39a6f94f2e1e 100644
+--- a/drivers/staging/comedi/drivers/poc.c
++++ b/drivers/staging/comedi/drivers/poc.c
+@@ -44,14 +44,14 @@ Configuration options:
+ static int poc_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int poc_detach(struct comedi_device * dev);
+ static int readback_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ static int dac02_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int pcl733_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int pcl734_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ struct boarddef_struct {
+ 	const char *name;
+@@ -60,11 +60,11 @@ struct boarddef_struct {
+ 	int type;
+ 	int n_chan;
+ 	int n_bits;
+-	int (*winsn) (struct comedi_device *, struct comedi_subdevice *, comedi_insn *,
++	int (*winsn) (struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *,
+ 		unsigned int *);
+-	int (*rinsn) (struct comedi_device *, struct comedi_subdevice *, comedi_insn *,
++	int (*rinsn) (struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *,
+ 		unsigned int *);
+-	int (*insnbits) (struct comedi_device *, struct comedi_subdevice *, comedi_insn *,
++	int (*insnbits) (struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *,
+ 		unsigned int *);
+ 	const struct comedi_lrange *range;
+ };
+@@ -171,7 +171,7 @@ static int poc_detach(struct comedi_device * dev)
+ }
+ 
+ static int readback_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan;
+ 
+@@ -186,7 +186,7 @@ static int readback_insn(struct comedi_device * dev, struct comedi_subdevice * s
+ #define DAC02_MSB(a)	(2 * a + 1)
+ 
+ static int dac02_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int temp;
+ 	int chan;
+@@ -209,7 +209,7 @@ static int dac02_ao_winsn(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ static int pcl733_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -223,7 +223,7 @@ static int pcl733_insn_bits(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ static int pcl734_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+index 9a188d44551f..6494312cb169 100644
+--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
++++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+@@ -362,7 +362,7 @@ static void daqp_interrupt(int irq, void *dev_id PT_REGS_ARG)
+ /* One-shot analog data acquisition routine */
+ 
+ static int daqp_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	local_info_t *local = (local_info_t *) s->private;
+ 	int i;
+@@ -794,7 +794,7 @@ static int daqp_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ /* Single-shot analog output routine */
+ 
+ static int daqp_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	local_info_t *local = (local_info_t *) s->private;
+ 	int d;
+@@ -821,7 +821,7 @@ static int daqp_ao_insn_write(struct comedi_device * dev, struct comedi_subdevic
+ /* Digital input routine */
+ 
+ static int daqp_di_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	local_info_t *local = (local_info_t *) s->private;
+ 
+@@ -837,7 +837,7 @@ static int daqp_di_insn_read(struct comedi_device * dev, struct comedi_subdevice
+ /* Digital output routine */
+ 
+ static int daqp_do_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	local_info_t *local = (local_info_t *) s->private;
+ 
+diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
+index 6ce02fa6082d..c919b8efdb3e 100644
+--- a/drivers/staging/comedi/drivers/rtd520.c
++++ b/drivers/staging/comedi/drivers/rtd520.c
+@@ -691,15 +691,15 @@ static struct comedi_driver rtd520Driver = {
+ };
+ 
+ static int rtd_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data);
++	struct comedi_insn *insn, unsigned int *data);
+ static int rtd_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data);
++	struct comedi_insn *insn, unsigned int *data);
+ static int rtd_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data);
++	struct comedi_insn *insn, unsigned int *data);
+ static int rtd_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data);
++	struct comedi_insn *insn, unsigned int *data);
+ static int rtd_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data);
++	struct comedi_insn *insn, unsigned int *data);
+ static int rtd_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	struct comedi_cmd *cmd);
+ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
+@@ -1255,7 +1255,7 @@ static int rtd520_probe_fifo_depth(struct comedi_device *dev)
+   select, delay, then read.
+  */
+ static int rtd_ai_rinsn(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, ii;
+ 	int stat;
+@@ -2136,7 +2136,7 @@ static int rtd_ns_to_timer(unsigned int *ns, int round_mode)
+   Output one (or more) analog values to a single port as fast as possible.
+ */
+ static int rtd_ao_winsn(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -2191,7 +2191,7 @@ static int rtd_ao_winsn(struct comedi_device *dev,
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+ static int rtd_ao_rinsn(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -2214,7 +2214,7 @@ static int rtd_ao_rinsn(struct comedi_device *dev,
+  * comedi core can convert between insn_bits and insn_read/write
+  */
+ static int rtd_dio_insn_bits(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -2241,7 +2241,7 @@ static int rtd_dio_insn_bits(struct comedi_device *dev,
+   Configure one bit on a IO port as Input or Output (hence the name :-).
+ */
+ static int rtd_dio_insn_config(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c
+index 463ef4841f0d..a93f5705bf19 100644
+--- a/drivers/staging/comedi/drivers/rti800.c
++++ b/drivers/staging/comedi/drivers/rti800.c
+@@ -179,7 +179,7 @@ static irqreturn_t rti800_interrupt(int irq, void *dev PT_REGS_ARG)
+ static const int gaindelay[] = { 10, 20, 40, 80 };
+ 
+ static int rti800_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, t;
+ 	int status;
+@@ -232,7 +232,7 @@ static int rti800_ai_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int rti800_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -244,7 +244,7 @@ static int rti800_ao_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int rti800_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	int d;
+@@ -264,7 +264,7 @@ static int rti800_ao_insn_write(struct comedi_device * dev, struct comedi_subdev
+ }
+ 
+ static int rti800_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -273,7 +273,7 @@ static int rti800_di_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int rti800_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c
+index 44bf3451d730..3249d08c3cea 100644
+--- a/drivers/staging/comedi/drivers/rti802.c
++++ b/drivers/staging/comedi/drivers/rti802.c
+@@ -69,7 +69,7 @@ typedef struct {
+ #define devpriv ((rti802_private *)dev->private)
+ 
+ static int rti802_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 
+@@ -80,7 +80,7 @@ static int rti802_ao_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int rti802_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, d;
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
+index d3881498e164..b9b48b2f222d 100644
+--- a/drivers/staging/comedi/drivers/s526.c
++++ b/drivers/staging/comedi/drivers/s526.c
+@@ -246,23 +246,23 @@ static struct comedi_driver driver_s526 = {
+ };
+ 
+ static int s526_gpct_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int s526_gpct_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int s526_gpct_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int s526_ai_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int s526_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int s526_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int s526_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int s526_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int s526_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ /*
+  * Attach is called by the Comedi core to configure the driver
+@@ -477,7 +477,7 @@ static int s526_detach(struct comedi_device * dev)
+ }
+ 
+ static int s526_gpct_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;			// counts the Data
+ 	int counter_channel = CR_CHAN(insn->chanspec);
+@@ -501,7 +501,7 @@ static int s526_gpct_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ static int s526_gpct_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int subdev_channel = CR_CHAN(insn->chanspec);	// Unpack chanspec
+ 	int i;
+@@ -726,7 +726,7 @@ static int s526_gpct_insn_config(struct comedi_device * dev, struct comedi_subde
+ }
+ 
+ static int s526_gpct_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int subdev_channel = CR_CHAN(insn->chanspec);	// Unpack chanspec
+ 	short value;
+@@ -785,7 +785,7 @@ static int s526_gpct_winsn(struct comedi_device * dev, struct comedi_subdevice *
+ 
+ #define ISR_ADC_DONE 0x4
+ static int s526_ai_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int result = -EINVAL;
+ 
+@@ -818,7 +818,7 @@ static int s526_ai_insn_config(struct comedi_device * dev, struct comedi_subdevi
+  * mode.
+  */
+ static int s526_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -868,7 +868,7 @@ static int s526_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s
+ }
+ 
+ static int s526_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -897,7 +897,7 @@ static int s526_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+ static int s526_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -914,7 +914,7 @@ static int s526_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+ static int s526_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -939,7 +939,7 @@ static int s526_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevic
+ }
+ 
+ static int s526_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	short value;
+diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
+index 80fedbb47b76..7385031f2b8b 100644
+--- a/drivers/staging/comedi/drivers/s626.c
++++ b/drivers/staging/comedi/drivers/s626.c
+@@ -223,32 +223,32 @@ COMEDI_PCI_INITCLEANUP_NOMODULE(driver_s626, s626_pci_table);
+ 
+ /* ioctl routines */
+ static int s626_ai_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data);
+-/* static int s626_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data); */
++	struct comedi_insn *insn, unsigned int *data);
++/* static int s626_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data); */
+ static int s626_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data);
++	struct comedi_insn *insn, unsigned int *data);
+ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
+ static int s626_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	struct comedi_cmd *cmd);
+ static int s626_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
+ static int s626_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data);
++	struct comedi_insn *insn, unsigned int *data);
+ static int s626_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data);
++	struct comedi_insn *insn, unsigned int *data);
+ static int s626_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data);
++	struct comedi_insn *insn, unsigned int *data);
+ static int s626_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data);
++	struct comedi_insn *insn, unsigned int *data);
+ static int s626_dio_set_irq(struct comedi_device *dev, unsigned int chan);
+ static int s626_dio_reset_irq(struct comedi_device *dev, unsigned int gruop,
+ 	unsigned int mask);
+ static int s626_dio_clear_irq(struct comedi_device *dev);
+ static int s626_enc_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data);
++	struct comedi_insn *insn, unsigned int *data);
+ static int s626_enc_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data);
++	struct comedi_insn *insn, unsigned int *data);
+ static int s626_enc_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data);
++	struct comedi_insn *insn, unsigned int *data);
+ static int s626_ns_to_timer(int *nanosec, int round_mode);
+ static int s626_ai_load_polllist(uint8_t *ppl, struct comedi_cmd *cmd);
+ static int s626_ai_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
+@@ -1504,13 +1504,13 @@ void ResetADC(struct comedi_device *dev, uint8_t *ppl)
+ 
+ /* TO COMPLETE, IF NECESSARY */
+ static int s626_ai_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data)
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	return -EINVAL;
+ }
+ 
+-/* static int s626_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data) */
++/* static int s626_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) */
+ /* { */
+ /*   register uint8_t	i; */
+ /*   register int32_t	*readaddr; */
+@@ -1541,7 +1541,7 @@ static int s626_ai_insn_config(struct comedi_device *dev, struct comedi_subdevic
+ /* } */
+ 
+ static int s626_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data)
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	uint16_t chan = CR_CHAN(insn->chanspec);
+ 	uint16_t range = CR_RANGE(insn->chanspec);
+@@ -2046,7 +2046,7 @@ static int s626_ns_to_timer(int *nanosec, int round_mode)
+ }
+ 
+ static int s626_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data)
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	int i;
+@@ -2065,7 +2065,7 @@ static int s626_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
+ }
+ 
+ static int s626_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data)
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 
+@@ -2111,7 +2111,7 @@ static void s626_dio_init(struct comedi_device *dev)
+  * core can convert between insn_bits and insn_read/write */
+ 
+ static int s626_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data)
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	/* Length of data must be 2 (mask and new data, see below) */
+@@ -2147,7 +2147,7 @@ static int s626_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice
+ }
+ 
+ static int s626_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data)
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	switch (data[0]) {
+@@ -2252,7 +2252,7 @@ static int s626_dio_clear_irq(struct comedi_device *dev)
+    and set the subdevice. To complete with trigger and interrupt
+    configuration */
+ static int s626_enc_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data)
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 	uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) |	/*  Preload upon */
+ 		/*  index. */
+@@ -2282,7 +2282,7 @@ static int s626_enc_insn_config(struct comedi_device *dev, struct comedi_subdevi
+ }
+ 
+ static int s626_enc_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data)
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	int n;
+@@ -2300,7 +2300,7 @@ static int s626_enc_insn_read(struct comedi_device *dev, struct comedi_subdevice
+ }
+ 
+ static int s626_enc_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_insn *insn, unsigned int *data)
++	struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	struct enc_private *k = &encpriv[CR_CHAN(insn->chanspec)];
+diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
+index 61cf19ebc278..2271bd45fc0f 100644
+--- a/drivers/staging/comedi/drivers/serial2002.c
++++ b/drivers/staging/comedi/drivers/serial2002.c
+@@ -98,15 +98,15 @@ struct comedi_driver driver_serial2002 = {
+ };
+ 
+ static int serial2002_di_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int serial2002_do_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int serial2002_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int serial2002_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int serial2002_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ 
+ struct serial_data {
+ 	enum { is_invalid, is_digital, is_channel } kind;
+@@ -661,7 +661,7 @@ static void serial_2002_close(struct comedi_device * dev)
+ }
+ 
+ static int serial2002_di_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan;
+@@ -683,7 +683,7 @@ static int serial2002_di_rinsn(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int serial2002_do_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan;
+@@ -701,7 +701,7 @@ static int serial2002_do_winsn(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int serial2002_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan;
+@@ -723,7 +723,7 @@ static int serial2002_ai_rinsn(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int serial2002_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan;
+@@ -742,7 +742,7 @@ static int serial2002_ao_winsn(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int serial2002_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -755,7 +755,7 @@ static int serial2002_ao_rinsn(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int serial2002_ei_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan;
+diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c
+index 511c4e32479c..2d25354b9acb 100644
+--- a/drivers/staging/comedi/drivers/skel.c
++++ b/drivers/staging/comedi/drivers/skel.c
+@@ -182,15 +182,15 @@ static struct comedi_driver driver_skel = {
+ };
+ 
+ static int skel_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int skel_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int skel_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int skel_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int skel_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int skel_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	struct comedi_cmd * cmd);
+ static int skel_ns_to_timer(unsigned int *ns, int round);
+@@ -299,7 +299,7 @@ static int skel_detach(struct comedi_device * dev)
+  * mode.
+  */
+ static int skel_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i;
+ 	unsigned int d;
+@@ -516,7 +516,7 @@ static int skel_ns_to_timer(unsigned int *ns, int round)
+ }
+ 
+ static int skel_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -537,7 +537,7 @@ static int skel_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+ static int skel_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -554,7 +554,7 @@ static int skel_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+ static int skel_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -579,7 +579,7 @@ static int skel_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevic
+ }
+ 
+ static int skel_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c
+index a5fda67f4a6a..cf3adf77ea12 100644
+--- a/drivers/staging/comedi/drivers/ssv_dnp.c
++++ b/drivers/staging/comedi/drivers/ssv_dnp.c
+@@ -104,10 +104,10 @@ static struct comedi_driver driver_dnp = {
+ COMEDI_INITCLEANUP(driver_dnp);
+ 
+ static int dnp_dio_insn_bits(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
+ 
+ static int dnp_dio_insn_config(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data);
+ 
+ /* ------------------------------------------------------------------------- */
+ /* Attach is called by comedi core to configure the driver for a particular  */
+@@ -201,7 +201,7 @@ static int dnp_detach(struct comedi_device * dev)
+ /* ------------------------------------------------------------------------- */
+ 
+ static int dnp_dio_insn_bits(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	if (insn->n != 2)
+@@ -251,7 +251,7 @@ static int dnp_dio_insn_bits(struct comedi_device * dev,
+ /* ------------------------------------------------------------------------- */
+ 
+ static int dnp_dio_insn_config(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	u8 register_buffer;
+diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c
+index bc5511d03ced..04b7ec65b63f 100644
+--- a/drivers/staging/comedi/drivers/unioxx5.c
++++ b/drivers/staging/comedi/drivers/unioxx5.c
+@@ -82,11 +82,11 @@ typedef struct unioxx5_subd_priv {
+ 
+ static int unioxx5_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int unioxx5_subdev_write(struct comedi_device * dev, struct comedi_subdevice * subdev,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int unioxx5_subdev_read(struct comedi_device * dev, struct comedi_subdevice * subdev,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int unioxx5_insn_config(struct comedi_device * dev, struct comedi_subdevice * subdev,
+-	comedi_insn * insn, unsigned int * data);
++	struct comedi_insn * insn, unsigned int * data);
+ static int unioxx5_detach(struct comedi_device * dev);
+ static int __unioxx5_subdev_init(struct comedi_subdevice * subdev, int subdev_iobase,
+ 	int minor);
+@@ -157,7 +157,7 @@ static int unioxx5_attach(struct comedi_device * dev, comedi_devconfig * it)
+ }
+ 
+ static int unioxx5_subdev_read(struct comedi_device * dev, struct comedi_subdevice * subdev,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unioxx5_subd_priv *usp = subdev->private;
+ 	int channel, type;
+@@ -177,7 +177,7 @@ static int unioxx5_subdev_read(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int unioxx5_subdev_write(struct comedi_device * dev, struct comedi_subdevice * subdev,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	unioxx5_subd_priv *usp = subdev->private;
+ 	int channel, type;
+@@ -198,7 +198,7 @@ static int unioxx5_subdev_write(struct comedi_device * dev, struct comedi_subdev
+ 
+ /* for digital modules only */
+ static int unioxx5_insn_config(struct comedi_device * dev, struct comedi_subdevice * subdev,
+-	comedi_insn * insn, unsigned int * data)
++	struct comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel_offset, flags, channel = CR_CHAN(insn->chanspec), type;
+ 	unioxx5_subd_priv *usp = subdev->private;
+diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
+index 7ec175aadbef..692df7a0e5eb 100644
+--- a/drivers/staging/comedi/drivers/usbdux.c
++++ b/drivers/staging/comedi/drivers/usbdux.c
+@@ -1277,7 +1277,7 @@ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ 
+ /* Mode 0 is used to get a single conversion on demand */
+ static int usbdux_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
+-			       comedi_insn *insn, unsigned int *data)
++			       struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	unsigned int one = 0;
+@@ -1338,7 +1338,7 @@ static int usbdux_ai_insn_read(struct comedi_device *dev, struct comedi_subdevic
+ /* analog out */
+ 
+ static int usbdux_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
+-			       comedi_insn *insn, unsigned int *data)
++			       struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -1360,7 +1360,7 @@ static int usbdux_ao_insn_read(struct comedi_device *dev, struct comedi_subdevic
+ }
+ 
+ static int usbdux_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
+-				comedi_insn *insn, unsigned int *data)
++				struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, err;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -1698,7 +1698,7 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ }
+ 
+ static int usbdux_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
+-				  comedi_insn *insn, unsigned int *data)
++				  struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+@@ -1729,7 +1729,7 @@ static int usbdux_dio_insn_config(struct comedi_device *dev, struct comedi_subde
+ }
+ 
+ static int usbdux_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
+-				comedi_insn *insn, unsigned int *data)
++				struct comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+@@ -1776,7 +1776,7 @@ static int usbdux_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevi
+ 
+ /* reads the 4 counters, only two are used just now */
+ static int usbdux_counter_read(struct comedi_device *dev, struct comedi_subdevice *s,
+-			       comedi_insn *insn, unsigned int *data)
++			       struct comedi_insn *insn, unsigned int *data)
+ {
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+ 	int chan = insn->chanspec;
+@@ -1810,7 +1810,7 @@ static int usbdux_counter_read(struct comedi_device *dev, struct comedi_subdevic
+ }
+ 
+ static int usbdux_counter_write(struct comedi_device *dev, struct comedi_subdevice *s,
+-				comedi_insn *insn, unsigned int *data)
++				struct comedi_insn *insn, unsigned int *data)
+ {
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+ 	int err;
+@@ -1840,7 +1840,7 @@ static int usbdux_counter_write(struct comedi_device *dev, struct comedi_subdevi
+ }
+ 
+ static int usbdux_counter_config(struct comedi_device *dev, struct comedi_subdevice *s,
+-				 comedi_insn *insn, unsigned int *data)
++				 struct comedi_insn *insn, unsigned int *data)
+ {
+ 	/* nothing to do so far */
+ 	return 2;
+@@ -2098,7 +2098,7 @@ static int usbdux_pwm_pattern(struct comedi_device *dev, struct comedi_subdevice
+ }
+ 
+ static int usbdux_pwm_write(struct comedi_device *dev, struct comedi_subdevice *s,
+-			    comedi_insn *insn, unsigned int *data)
++			    struct comedi_insn *insn, unsigned int *data)
+ {
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+ 
+@@ -2123,7 +2123,7 @@ static int usbdux_pwm_write(struct comedi_device *dev, struct comedi_subdevice *
+ }
+ 
+ static int usbdux_pwm_read(struct comedi_device *x1, struct comedi_subdevice *x2,
+-			   comedi_insn *x3, unsigned int *x4)
++			   struct comedi_insn *x3, unsigned int *x4)
+ {
+ 	/* not needed */
+ 	return -EINVAL;
+@@ -2131,7 +2131,7 @@ static int usbdux_pwm_read(struct comedi_device *x1, struct comedi_subdevice *x2
+ 
+ /* switches on/off PWM */
+ static int usbdux_pwm_config(struct comedi_device *dev, struct comedi_subdevice *s,
+-			     comedi_insn *insn, unsigned int *data)
++			     struct comedi_insn *insn, unsigned int *data)
+ {
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+ 	switch (data[0]) {
+diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c
+index bbd552f2a500..d1ea6ed934ef 100644
+--- a/drivers/staging/comedi/drivers/usbduxfast.c
++++ b/drivers/staging/comedi/drivers/usbduxfast.c
+@@ -1231,7 +1231,7 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev, struct comedi_subdevice
+  * Mode 0 is used to get a single conversion on demand.
+  */
+ static int usbduxfast_ai_insn_read(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, j, n, actual_length;
+ 	int chan, range, rngmask;
+diff --git a/drivers/staging/comedi/kcomedilib/data.c b/drivers/staging/comedi/kcomedilib/data.c
+index 53f20476e99b..9797e13e3774 100644
+--- a/drivers/staging/comedi/kcomedilib/data.c
++++ b/drivers/staging/comedi/kcomedilib/data.c
+@@ -30,7 +30,7 @@
+ int comedi_data_write(void *dev, unsigned int subdev, unsigned int chan,
+ 	unsigned int range, unsigned int aref, unsigned int data)
+ {
+-	comedi_insn insn;
++	struct comedi_insn insn;
+ 
+ 	memset(&insn, 0, sizeof(insn));
+ 	insn.insn = INSN_WRITE;
+@@ -45,7 +45,7 @@ int comedi_data_write(void *dev, unsigned int subdev, unsigned int chan,
+ int comedi_data_read(void *dev, unsigned int subdev, unsigned int chan,
+ 	unsigned int range, unsigned int aref, unsigned int *data)
+ {
+-	comedi_insn insn;
++	struct comedi_insn insn;
+ 
+ 	memset(&insn, 0, sizeof(insn));
+ 	insn.insn = INSN_READ;
+@@ -60,7 +60,7 @@ int comedi_data_read(void *dev, unsigned int subdev, unsigned int chan,
+ int comedi_data_read_hint(void *dev, unsigned int subdev,
+ 	unsigned int chan, unsigned int range, unsigned int aref)
+ {
+-	comedi_insn insn;
++	struct comedi_insn insn;
+ 	unsigned int dummy_data;
+ 
+ 	memset(&insn, 0, sizeof(insn));
+diff --git a/drivers/staging/comedi/kcomedilib/dio.c b/drivers/staging/comedi/kcomedilib/dio.c
+index 1a76ef57537c..8595567e48fb 100644
+--- a/drivers/staging/comedi/kcomedilib/dio.c
++++ b/drivers/staging/comedi/kcomedilib/dio.c
+@@ -29,7 +29,7 @@
+ int comedi_dio_config(void *dev, unsigned int subdev, unsigned int chan,
+ 	unsigned int io)
+ {
+-	comedi_insn insn;
++	struct comedi_insn insn;
+ 
+ 	memset(&insn, 0, sizeof(insn));
+ 	insn.insn = INSN_CONFIG;
+@@ -44,7 +44,7 @@ int comedi_dio_config(void *dev, unsigned int subdev, unsigned int chan,
+ int comedi_dio_read(void *dev, unsigned int subdev, unsigned int chan,
+ 	unsigned int *val)
+ {
+-	comedi_insn insn;
++	struct comedi_insn insn;
+ 
+ 	memset(&insn, 0, sizeof(insn));
+ 	insn.insn = INSN_READ;
+@@ -59,7 +59,7 @@ int comedi_dio_read(void *dev, unsigned int subdev, unsigned int chan,
+ int comedi_dio_write(void *dev, unsigned int subdev, unsigned int chan,
+ 	unsigned int val)
+ {
+-	comedi_insn insn;
++	struct comedi_insn insn;
+ 
+ 	memset(&insn, 0, sizeof(insn));
+ 	insn.insn = INSN_WRITE;
+@@ -74,7 +74,7 @@ int comedi_dio_write(void *dev, unsigned int subdev, unsigned int chan,
+ int comedi_dio_bitfield(void *dev, unsigned int subdev, unsigned int mask,
+ 	unsigned int *bits)
+ {
+-	comedi_insn insn;
++	struct comedi_insn insn;
+ 	unsigned int data[2];
+ 	int ret;
+ 
+diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+index 43dae3e40379..a4fa9571c58f 100644
+--- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
++++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+@@ -183,7 +183,7 @@ int comedi_command_test(void *d, struct comedi_cmd *cmd)
+  *	COMEDI_INSN
+  *	perform an instruction
+  */
+-int comedi_do_insn(void *d, comedi_insn *insn)
++int comedi_do_insn(void *d, struct comedi_insn *insn)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+ 	struct comedi_subdevice *s;

commit ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3f
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:05:47 2009 -0400
+
+    Staging: comedi: Remove comedi_cmd typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
+index ab9bd016a567..1057c9126b85 100644
+--- a/drivers/staging/comedi/comedi.h
++++ b/drivers/staging/comedi/comedi.h
+@@ -300,8 +300,8 @@ enum comedi_support_level {
+ #define COMEDI_UNLOCK _IO(CIO, 6)
+ #define COMEDI_CANCEL _IO(CIO, 7)
+ #define COMEDI_RANGEINFO _IOR(CIO, 8, comedi_rangeinfo)
+-#define COMEDI_CMD _IOR(CIO, 9, comedi_cmd)
+-#define COMEDI_CMDTEST _IOR(CIO, 10, comedi_cmd)
++#define COMEDI_CMD _IOR(CIO, 9, struct comedi_cmd)
++#define COMEDI_CMDTEST _IOR(CIO, 10, struct comedi_cmd)
+ #define COMEDI_INSNLIST _IOR(CIO, 11, comedi_insnlist)
+ #define COMEDI_INSN _IOR(CIO, 12, comedi_insn)
+ #define COMEDI_BUFCONFIG _IOR(CIO, 13, comedi_bufconfig)
+@@ -310,7 +310,6 @@ enum comedi_support_level {
+ 
+ /* structures */
+ 
+-typedef struct comedi_cmd_struct comedi_cmd;
+ typedef struct comedi_insn_struct comedi_insn;
+ typedef struct comedi_insnlist_struct comedi_insnlist;
+ typedef struct comedi_chaninfo_struct comedi_chaninfo;
+@@ -351,7 +350,7 @@ struct comedi_insnlist_struct {
+ 	comedi_insn *insns;
+ };
+ 
+-struct comedi_cmd_struct {
++struct comedi_cmd {
+ 	unsigned int subdev;
+ 	unsigned int flags;
+ 
+diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c
+index ef3caa9d0e02..3eb1d5cdbe7a 100644
+--- a/drivers/staging/comedi/comedi_compat32.c
++++ b/drivers/staging/comedi/comedi_compat32.c
+@@ -188,7 +188,7 @@ static int compat_rangeinfo(struct file *file, unsigned long arg)
+ }
+ 
+ /* Copy 32-bit cmd structure to native cmd structure. */
+-static int get_compat_cmd(comedi_cmd __user *cmd,
++static int get_compat_cmd(struct comedi_cmd __user *cmd,
+ 		struct comedi32_cmd_struct __user *cmd32)
+ {
+ 	int err;
+@@ -239,7 +239,7 @@ static int get_compat_cmd(comedi_cmd __user *cmd,
+ }
+ 
+ /* Copy native cmd structure to 32-bit cmd structure. */
+-static int put_compat_cmd(struct comedi32_cmd_struct __user *cmd32, comedi_cmd __user *cmd)
++static int put_compat_cmd(struct comedi32_cmd_struct __user *cmd32, struct comedi_cmd __user *cmd)
+ {
+ 	int err;
+ 	unsigned int temp;
+@@ -289,7 +289,7 @@ static int put_compat_cmd(struct comedi32_cmd_struct __user *cmd32, comedi_cmd _
+ /* Handle 32-bit COMEDI_CMD ioctl. */
+ static int compat_cmd(struct file *file, unsigned long arg)
+ {
+-	comedi_cmd __user *cmd;
++	struct comedi_cmd __user *cmd;
+ 	struct comedi32_cmd_struct __user *cmd32;
+ 	int rc;
+ 
+@@ -306,7 +306,7 @@ static int compat_cmd(struct file *file, unsigned long arg)
+ /* Handle 32-bit COMEDI_CMDTEST ioctl. */
+ static int compat_cmdtest(struct file *file, unsigned long arg)
+ {
+-	comedi_cmd __user *cmd;
++	struct comedi_cmd __user *cmd;
+ 	struct comedi32_cmd_struct __user *cmd32;
+ 	int rc, err;
+ 
+diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
+index 524bef968a1c..1d83c0890b4e 100644
+--- a/drivers/staging/comedi/comedi_fops.c
++++ b/drivers/staging/comedi/comedi_fops.c
+@@ -977,13 +977,13 @@ static int do_insn_ioctl(struct comedi_device *dev, void *arg, void *file)
+ */
+ static int do_cmd_ioctl(struct comedi_device *dev, void *arg, void *file)
+ {
+-	comedi_cmd user_cmd;
++	struct comedi_cmd user_cmd;
+ 	struct comedi_subdevice *s;
+ 	struct comedi_async *async;
+ 	int ret = 0;
+ 	unsigned int *chanlist_saver = NULL;
+ 
+-	if (copy_from_user(&user_cmd, arg, sizeof(comedi_cmd))) {
++	if (copy_from_user(&user_cmd, arg, sizeof(struct comedi_cmd))) {
+ 		DPRINTK("bad cmd address\n");
+ 		return -EFAULT;
+ 	}
+@@ -1072,7 +1072,7 @@ static int do_cmd_ioctl(struct comedi_device *dev, void *arg, void *file)
+ 		/* restore chanlist pointer before copying back */
+ 		user_cmd.chanlist = chanlist_saver;
+ 		user_cmd.data = NULL;
+-		if (copy_to_user(arg, &user_cmd, sizeof(comedi_cmd))) {
++		if (copy_to_user(arg, &user_cmd, sizeof(struct comedi_cmd))) {
+ 			DPRINTK("fault writing cmd\n");
+ 			ret = -EFAULT;
+ 			goto cleanup;
+@@ -1131,13 +1131,13 @@ static int do_cmd_ioctl(struct comedi_device *dev, void *arg, void *file)
+ */
+ static int do_cmdtest_ioctl(struct comedi_device *dev, void *arg, void *file)
+ {
+-	comedi_cmd user_cmd;
++	struct comedi_cmd user_cmd;
+ 	struct comedi_subdevice *s;
+ 	int ret = 0;
+ 	unsigned int *chanlist = NULL;
+ 	unsigned int *chanlist_saver = NULL;
+ 
+-	if (copy_from_user(&user_cmd, arg, sizeof(comedi_cmd))) {
++	if (copy_from_user(&user_cmd, arg, sizeof(struct comedi_cmd))) {
+ 		DPRINTK("bad cmd address\n");
+ 		return -EFAULT;
+ 	}
+@@ -1201,7 +1201,7 @@ static int do_cmdtest_ioctl(struct comedi_device *dev, void *arg, void *file)
+ 	/* restore chanlist pointer before copying back */
+ 	user_cmd.chanlist = chanlist_saver;
+ 
+-	if (copy_to_user(arg, &user_cmd, sizeof(comedi_cmd))) {
++	if (copy_to_user(arg, &user_cmd, sizeof(struct comedi_cmd))) {
+ 		DPRINTK("bad cmd address\n");
+ 		ret = -EFAULT;
+ 		goto cleanup;
+diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
+index 4333139e5245..8e60fdb33964 100644
+--- a/drivers/staging/comedi/comedidev.h
++++ b/drivers/staging/comedi/comedidev.h
+@@ -165,7 +165,7 @@ struct comedi_subdevice {
+ 		unsigned int *);
+ 
+ 	int (*do_cmd) (struct comedi_device *, struct comedi_subdevice *);
+-	int (*do_cmdtest) (struct comedi_device *, struct comedi_subdevice *, comedi_cmd *);
++	int (*do_cmdtest) (struct comedi_device *, struct comedi_subdevice *, struct comedi_cmd *);
+ 	int (*poll) (struct comedi_device *, struct comedi_subdevice *);
+ 	int (*cancel) (struct comedi_device *, struct comedi_subdevice *);
+ 	/* int (*do_lock)(struct comedi_device *,struct comedi_subdevice *); */
+@@ -221,7 +221,7 @@ struct comedi_async {
+ 
+ 	unsigned int events;	/* events that have occurred */
+ 
+-	comedi_cmd cmd;
++	struct comedi_cmd cmd;
+ 
+ 	wait_queue_head_t wait_head;
+ 
+diff --git a/drivers/staging/comedi/comedilib.h b/drivers/staging/comedi/comedilib.h
+index 523497740212..e94f1b79d2c3 100644
+--- a/drivers/staging/comedi/comedilib.h
++++ b/drivers/staging/comedi/comedilib.h
+@@ -60,8 +60,8 @@ int comedi_cancel(void *dev, unsigned int subdev);
+ int comedi_register_callback(void *dev, unsigned int subdev,
+ 	unsigned int mask, int (*cb) (unsigned int, void *), void *arg);
+ 
+-int comedi_command(void *dev, comedi_cmd *cmd);
+-int comedi_command_test(void *dev, comedi_cmd *cmd);
++int comedi_command(void *dev, struct comedi_cmd *cmd);
++int comedi_command_test(void *dev, struct comedi_cmd *cmd);
+ int comedi_trigger(void *dev, unsigned int subdev, struct comedi_trig *it);
+ int __comedi_trigger(void *dev, unsigned int subdev, struct comedi_trig *it);
+ int comedi_data_write(void *dev, unsigned int subdev, unsigned int chan,
+@@ -137,8 +137,8 @@ int comedi_cancel(unsigned int minor, unsigned int subdev);
+ int comedi_register_callback(unsigned int minor, unsigned int subdev,
+ 	unsigned int mask, int (*cb) (unsigned int, void *), void *arg);
+ 
+-int comedi_command(unsigned int minor, comedi_cmd *cmd);
+-int comedi_command_test(unsigned int minor, comedi_cmd *cmd);
++int comedi_command(unsigned int minor, struct comedi_cmd *cmd);
++int comedi_command_test(unsigned int minor, struct comedi_cmd *cmd);
+ int comedi_trigger(unsigned int minor, unsigned int subdev, struct comedi_trig *it);
+ int __comedi_trigger(unsigned int minor, unsigned int subdev, struct comedi_trig *it);
+ int comedi_data_write(unsigned int dev, unsigned int subdev, unsigned int chan,
+diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c
+index 6e1786059d22..2b57041bfe9d 100644
+--- a/drivers/staging/comedi/drivers/8255.c
++++ b/drivers/staging/comedi/drivers/8255.c
+@@ -223,7 +223,7 @@ static void do_config(struct comedi_device *dev, struct comedi_subdevice * s)
+ }
+ 
+ static int subdev_8255_cmdtest(struct comedi_device *dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	unsigned int tmp;
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+index 0e06121f13e5..2f3fc3c43060 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+@@ -135,7 +135,7 @@ typedef struct {
+ 					   unsigned int *data);
+ 	int (*i_hwdrv_CommandTestAnalogInput)(struct comedi_device *dev,
+ 					      struct comedi_subdevice *s,
+-					      comedi_cmd *cmd);
++					      struct comedi_cmd *cmd);
+ 	int (*i_hwdrv_CommandAnalogInput)(struct comedi_device *dev,
+ 					  struct comedi_subdevice *s);
+ 	int (*i_hwdrv_CancelAnalogInput)(struct comedi_device *dev,
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+index 9af284314913..0bebf87c7b29 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+@@ -460,7 +460,7 @@ int i_APCI3120_StopCyclicAcquisition(struct comedi_device * dev, struct comedi_s
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev|
+-|			,struct comedi_subdevice *s,comedi_cmd *cmd)					 |
++|			,struct comedi_subdevice *s,struct comedi_cmd *cmd)					 |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              : Test validity for a command for cyclic anlog input     |
+@@ -469,7 +469,7 @@ int i_APCI3120_StopCyclicAcquisition(struct comedi_device * dev, struct comedi_s
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev									 |
+ |                     struct comedi_subdevice *s									 |
+-|                     comedi_cmd *cmd              					         |
++|                     struct comedi_cmd *cmd              					         |
+ +----------------------------------------------------------------------------+
+ | Return Value      :0              					                     |
+ |                    													     |
+@@ -477,7 +477,7 @@ int i_APCI3120_StopCyclicAcquisition(struct comedi_device * dev, struct comedi_s
+ */
+ 
+ int i_APCI3120_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp;		// divisor1,divisor2;
+@@ -635,7 +635,7 @@ int i_APCI3120_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_
+ 
+ int i_APCI3120_CommandAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 
+ 	//loading private structure with cmd structure inputs
+ 	devpriv->ui_AiFlags = cmd->flags;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
+index 1a0806249457..0fb31835a68b 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
+@@ -235,7 +235,7 @@ int i_APCI3120_InsnConfigAnalogInput(struct comedi_device *dev, struct comedi_su
+ int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+ int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				      comedi_cmd *cmd);
++				      struct comedi_cmd *cmd);
+ int i_APCI3120_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s);
+ //int i_APCI3120_CancelAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s);
+ int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+index 2fdbd7d2ef13..c7e42b54daf7 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+@@ -2539,7 +2539,7 @@ INT i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device * dev,
+ /*
+   +----------------------------------------------------------------------------+
+   | Function name     :int i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev|
+-  |			,struct comedi_subdevice *s,comedi_cmd *cmd)			         |
++  |			,struct comedi_subdevice *s,struct comedi_cmd *cmd)			         |
+   |                                        									 |
+   +----------------------------------------------------------------------------+
+   | Task              : Test validity for a command for cyclic anlog input     |
+@@ -2548,7 +2548,7 @@ INT i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device * dev,
+   +----------------------------------------------------------------------------+
+   | Input Parameters  : struct comedi_device *dev									 |
+   |                     struct comedi_subdevice *s									 |
+-  |                     comedi_cmd *cmd              					         |
++  |                     struct comedi_cmd *cmd              					         |
+   |                     										                 |
+   |
+   |                     										                 |
+@@ -2561,7 +2561,7 @@ INT i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device * dev,
+ */
+ 
+ int i_APCI3200_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 
+ 	int err = 0;
+@@ -2816,7 +2816,7 @@ int i_APCI3200_StopCyclicAcquisition(struct comedi_device * dev, struct comedi_s
+ 
+ int i_APCI3200_CommandAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 	UINT ui_Configuration = 0;
+ 	//INT  i_CurrentSource = 0;
+ 	UINT ui_Trigger = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+index 12ecce2db670..94d9cef4bce5 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+@@ -167,7 +167,7 @@ INT i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device *dev,
+ INT i_APCI3200_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s);
+ INT i_APCI3200_InterruptHandleEos(struct comedi_device *dev);
+ INT i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+-				      comedi_cmd *cmd);
++				      struct comedi_cmd *cmd);
+ INT i_APCI3200_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s);
+ INT i_APCI3200_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
+index b4c6722ea766..41aaac7dfa4a 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9111.c
++++ b/drivers/staging/comedi/drivers/adl_pci9111.c
+@@ -558,7 +558,7 @@ static int pci9111_ai_cancel(struct comedi_device * dev, struct comedi_subdevice
+ 
+ static int
+ pci9111_ai_do_cmd_test(struct comedi_device * dev,
+-	struct comedi_subdevice * s, comedi_cmd * cmd)
++	struct comedi_subdevice * s, struct comedi_cmd * cmd)
+ {
+ 	int tmp;
+ 	int error = 0;
+@@ -760,7 +760,7 @@ pci9111_ai_do_cmd_test(struct comedi_device * dev,
+ 
+ static int pci9111_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * subdevice)
+ {
+-	comedi_cmd *async_cmd = &subdevice->async->cmd;
++	struct comedi_cmd *async_cmd = &subdevice->async->cmd;
+ 
+ 	if (!dev->irq) {
+ 		comedi_error(dev,
+diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
+index 71745f128722..cc3ea6cfdb81 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9118.c
++++ b/drivers/staging/comedi/drivers/adl_pci9118.c
+@@ -752,7 +752,7 @@ static int pci9118_ai_inttrig(struct comedi_device * dev, struct comedi_subdevic
+ ==============================================================================
+ */
+ static int pci9118_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp, divisor1, divisor2;
+@@ -1289,7 +1289,7 @@ static int pci9118_ai_docmd_dma(struct comedi_device * dev, struct comedi_subdev
+ */
+ static int pci9118_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned int addchans = 0;
+ 	int ret = 0;
+ 
+diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
+index 6742baf7ffa8..0732cac2e710 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1710.c
++++ b/drivers/staging/comedi/drivers/adv_pci1710.c
+@@ -884,7 +884,7 @@ static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device * dev,
+ /*
+ ==============================================================================
+ */
+-static void pci171x_cmdtest_out(int e, comedi_cmd * cmd)
++static void pci171x_cmdtest_out(int e, struct comedi_cmd * cmd)
+ {
+ 	rt_printk("adv_pci1710 e=%d startsrc=%x scansrc=%x convsrc=%x\n", e,
+ 		cmd->start_src, cmd->scan_begin_src, cmd->convert_src);
+@@ -901,7 +901,7 @@ static void pci171x_cmdtest_out(int e, comedi_cmd * cmd)
+ ==============================================================================
+ */
+ static int pci171x_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp, divisor1, divisor2;
+@@ -1067,7 +1067,7 @@ static int pci171x_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevic
+ */
+ static int pci171x_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 
+ 	DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmd(...)\n");
+ 	devpriv->ai_n_chan = cmd->chanlist_len;
+diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
+index 6323b571f61e..25b8f4fa1c1a 100644
+--- a/drivers/staging/comedi/drivers/amplc_dio200.c
++++ b/drivers/staging/comedi/drivers/amplc_dio200.c
+@@ -610,7 +610,7 @@ static int dio200_start_intr(struct comedi_device * dev, struct comedi_subdevice
+ 	unsigned int n;
+ 	unsigned isn_bits;
+ 	dio200_subdev_intr *subpriv = s->private;
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 	int retval = 0;
+ 
+ 	if (!subpriv->continuous && subpriv->stopcount == 0) {
+@@ -802,7 +802,7 @@ static int dio200_subdev_intr_cancel(struct comedi_device * dev, struct comedi_s
+  */
+ static int
+ dio200_subdev_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	unsigned int tmp;
+@@ -909,7 +909,7 @@ dio200_subdev_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevice *
+  */
+ static int dio200_subdev_intr_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 	dio200_subdev_intr *subpriv = s->private;
+ 	unsigned long flags;
+ 	int event = 0;
+diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
+index f9cc28317302..64cfcc8296e7 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc236.c
++++ b/drivers/staging/comedi/drivers/amplc_pc236.c
+@@ -191,7 +191,7 @@ static int pc236_intr_check(struct comedi_device * dev);
+ static int pc236_intr_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ static int pc236_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd);
++	struct comedi_cmd * cmd);
+ static int pc236_intr_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int pc236_intr_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static irqreturn_t pc236_interrupt(int irq, void *d PT_REGS_ARG);
+@@ -540,7 +540,7 @@ static int pc236_intr_insn(struct comedi_device * dev, struct comedi_subdevice *
+  * Copied from the comedi_parport driver.
+  */
+ static int pc236_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
+index 7ef57bf309cb..639bd2f588c5 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci224.c
++++ b/drivers/staging/comedi/drivers/amplc_pci224.c
+@@ -574,7 +574,7 @@ static void pci224_ao_stop(struct comedi_device * dev, struct comedi_subdevice *
+  */
+ static void pci224_ao_start(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned long flags;
+ 
+ 	set_bit(AO_CMD_STARTED, &devpriv->state);
+@@ -601,7 +601,7 @@ static void pci224_ao_start(struct comedi_device * dev, struct comedi_subdevice
+  */
+ static void pci224_ao_handle_fifo(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned int num_scans;
+ 	unsigned int room;
+ 	unsigned short dacstat;
+@@ -748,7 +748,7 @@ pci224_ao_inttrig_start(struct comedi_device * dev, struct comedi_subdevice * s,
+  * 'do_cmdtest' function for AO subdevice.
+  */
+ static int
+-pci224_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, comedi_cmd * cmd)
++pci224_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	unsigned int tmp;
+@@ -1017,7 +1017,7 @@ pci224_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, comed
+  */
+ static int pci224_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 	int range;
+ 	unsigned int i, j;
+ 	unsigned int ch;
+@@ -1216,7 +1216,7 @@ static irqreturn_t pci224_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	struct comedi_device *dev = d;
+ 	struct comedi_subdevice *s = &dev->subdevices[0];
+-	comedi_cmd *cmd;
++	struct comedi_cmd *cmd;
+ 	unsigned char intstat, valid_intstat;
+ 	unsigned char curenab;
+ 	int retval = 0;
+diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
+index 7e7f627abb24..d985f649f9fb 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci230.c
++++ b/drivers/staging/comedi/drivers/amplc_pci230.c
+@@ -627,14 +627,14 @@ static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round);
+ static void pci230_cancel_ct(struct comedi_device * dev, unsigned int ct);
+ static irqreturn_t pci230_interrupt(int irq, void *d PT_REGS_ARG);
+ static int pci230_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd);
++	struct comedi_cmd * cmd);
+ static int pci230_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int pci230_ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static void pci230_ao_stop(struct comedi_device * dev, struct comedi_subdevice * s);
+ static void pci230_handle_ao_nofifo(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int pci230_handle_ao_fifo(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int pci230_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd);
++	struct comedi_cmd * cmd);
+ static int pci230_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int pci230_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static void pci230_ai_stop(struct comedi_device * dev, struct comedi_subdevice * s);
+@@ -1204,7 +1204,7 @@ static int pci230_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ static int pci230_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	unsigned int tmp;
+@@ -1451,7 +1451,7 @@ static int pci230_ao_inttrig_scan_begin(struct comedi_device * dev,
+ static void pci230_ao_start(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	struct comedi_async *async = s->async;
+-	comedi_cmd *cmd = &async->cmd;
++	struct comedi_cmd *cmd = &async->cmd;
+ 	unsigned long irqflags;
+ 
+ 	set_bit(AO_CMD_STARTED, &devpriv->state);
+@@ -1554,7 +1554,7 @@ static int pci230_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s
+ 	unsigned int range;
+ 
+ 	/* Get the command. */
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 
+ 	if (cmd->scan_begin_src == TRIG_TIMER) {
+ 		/* Claim Z2-CT1. */
+@@ -1624,7 +1624,7 @@ static int pci230_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s
+ 	return 0;
+ }
+ 
+-static int pci230_ai_check_scan_period(comedi_cmd * cmd)
++static int pci230_ai_check_scan_period(struct comedi_cmd * cmd)
+ {
+ 	unsigned int min_scan_period, chanlist_len;
+ 	int err = 0;
+@@ -1649,7 +1649,7 @@ static int pci230_ai_check_scan_period(comedi_cmd * cmd)
+ }
+ 
+ static int pci230_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	unsigned int tmp;
+@@ -2037,7 +2037,7 @@ static int pci230_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice
+ static void pci230_ai_update_fifo_trigger_level(struct comedi_device * dev,
+ 	struct comedi_subdevice * s)
+ {
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned int scanlen = cmd->scan_end_arg;
+ 	unsigned int wake;
+ 	unsigned short triglev;
+@@ -2148,7 +2148,7 @@ static void pci230_ai_start(struct comedi_device * dev, struct comedi_subdevice
+ 	unsigned long irqflags;
+ 	unsigned short conv;
+ 	struct comedi_async *async = s->async;
+-	comedi_cmd *cmd = &async->cmd;
++	struct comedi_cmd *cmd = &async->cmd;
+ 
+ 	set_bit(AI_CMD_STARTED, &devpriv->state);
+ 	if (!devpriv->ai_continuous && (devpriv->ai_scan_count == 0)) {
+@@ -2301,7 +2301,7 @@ static int pci230_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s
+ 
+ 	/* Get the command. */
+ 	struct comedi_async *async = s->async;
+-	comedi_cmd *cmd = &async->cmd;
++	struct comedi_cmd *cmd = &async->cmd;
+ 
+ 	/*
+ 	 * Determine which shared resources are needed.
+@@ -2627,7 +2627,7 @@ static void pci230_handle_ao_nofifo(struct comedi_device * dev, struct comedi_su
+ 	short data;
+ 	int i, ret;
+ 	struct comedi_async *async = s->async;
+-	comedi_cmd *cmd = &async->cmd;
++	struct comedi_cmd *cmd = &async->cmd;
+ 
+ 	if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0)) {
+ 		return;
+@@ -2662,7 +2662,7 @@ static void pci230_handle_ao_nofifo(struct comedi_device * dev, struct comedi_su
+ static int pci230_handle_ao_fifo(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	struct comedi_async *async = s->async;
+-	comedi_cmd *cmd = &async->cmd;
++	struct comedi_cmd *cmd = &async->cmd;
+ 	unsigned int num_scans;
+ 	unsigned int room;
+ 	unsigned short dacstat;
+@@ -2866,7 +2866,7 @@ static void pci230_ao_stop(struct comedi_device * dev, struct comedi_subdevice *
+ 	unsigned long irqflags;
+ 	unsigned char intsrc;
+ 	int started;
+-	comedi_cmd *cmd;
++	struct comedi_cmd *cmd;
+ 
+ 	comedi_spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags);
+ 	started = test_and_clear_bit(AO_CMD_STARTED, &devpriv->state);
+@@ -2925,7 +2925,7 @@ static int pci230_ao_cancel(struct comedi_device * dev, struct comedi_subdevice
+ static void pci230_ai_stop(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned long irqflags;
+-	comedi_cmd *cmd;
++	struct comedi_cmd *cmd;
+ 	int started;
+ 
+ 	comedi_spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
+diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
+index 8152970e8dfe..ef126bcf6d07 100644
+--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
++++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
+@@ -113,7 +113,7 @@ static int das16cs_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice
+ 	comedi_insn * insn, unsigned int * data);
+ static int das16cs_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int das16cs_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd);
++	struct comedi_cmd * cmd);
+ static int das16cs_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ static int das16cs_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+@@ -334,7 +334,7 @@ static int das16cs_ai_cmd(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ static int das16cs_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
+index 1dcf7dde78ee..70cb220f6422 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas.c
+@@ -461,13 +461,13 @@ static int cb_pcidas_ao_readback_insn(struct comedi_device * dev, struct comedi_
+ 	comedi_insn * insn, unsigned int * data);
+ static int cb_pcidas_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int cb_pcidas_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd);
++	struct comedi_cmd * cmd);
+ static int cb_pcidas_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int cb_pcidas_ao_inttrig(struct comedi_device *dev,
+ 				struct comedi_subdevice *subdev,
+ 				unsigned int trig_num);
+ static int cb_pcidas_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd);
++	struct comedi_cmd * cmd);
+ static irqreturn_t cb_pcidas_interrupt(int irq, void *d PT_REGS_ARG);
+ static void handle_ao_interrupt(struct comedi_device * dev, unsigned int status);
+ static int cb_pcidas_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+@@ -1009,7 +1009,7 @@ static int trimpot_read_insn(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ static int cb_pcidas_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -1166,7 +1166,7 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device * dev, struct comedi_subdev
+ static int cb_pcidas_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	struct comedi_async *async = s->async;
+-	comedi_cmd *cmd = &async->cmd;
++	struct comedi_cmd *cmd = &async->cmd;
+ 	unsigned int bits;
+ 	unsigned long flags;
+ 
+@@ -1251,7 +1251,7 @@ static int cb_pcidas_ai_cmd(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ static int cb_pcidas_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -1366,7 +1366,7 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device * dev, struct comedi_subdev
+ static int cb_pcidas_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	struct comedi_async *async = s->async;
+-	comedi_cmd *cmd = &async->cmd;
++	struct comedi_cmd *cmd = &async->cmd;
+ 	unsigned int i;
+ 	unsigned long flags;
+ 
+@@ -1432,7 +1432,7 @@ static int cb_pcidas_ao_inttrig(struct comedi_device *dev,
+ {
+ 	unsigned int num_bytes, num_points = thisboard->fifo_size;
+ 	struct comedi_async *async = s->async;
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned long flags;
+ 
+ 	if (trig_num != 0)
+@@ -1592,7 +1592,7 @@ static void handle_ao_interrupt(struct comedi_device * dev, unsigned int status)
+ {
+ 	struct comedi_subdevice *s = dev->write_subdev;
+ 	struct comedi_async *async = s->async;
+-	comedi_cmd *cmd = &async->cmd;
++	struct comedi_cmd *cmd = &async->cmd;
+ 	unsigned int half_fifo = thisboard->fifo_size / 2;
+ 	unsigned int num_points;
+ 	unsigned int flags;
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
+index ce1638d72d6b..dd7a35cf7d5d 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
+@@ -1144,12 +1144,12 @@ static int ao_readback_insn(struct comedi_device * dev, struct comedi_subdevice
+ 	comedi_insn * insn, unsigned int * data);
+ static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd);
++	struct comedi_cmd * cmd);
+ static int ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int ao_inttrig(struct comedi_device * dev, struct comedi_subdevice * subdev,
+ 	unsigned int trig_num);
+ static int ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd);
++	struct comedi_cmd * cmd);
+ static irqreturn_t handle_interrupt(int irq, void *d PT_REGS_ARG);
+ static int ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+@@ -1175,7 +1175,7 @@ static int ad8402_write_insn(struct comedi_device * dev, struct comedi_subdevice
+ 	comedi_insn * insn, unsigned int * data);
+ static int eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static void check_adc_timing(struct comedi_device * dev, comedi_cmd * cmd);
++static void check_adc_timing(struct comedi_device * dev, struct comedi_cmd * cmd);
+ static unsigned int get_divisor(unsigned int ns, unsigned int flags);
+ static void i2c_write(struct comedi_device * dev, unsigned int address,
+ 	const uint8_t * data, unsigned int length);
+@@ -1194,9 +1194,9 @@ static int set_ai_fifo_segment_length(struct comedi_device * dev,
+ 	unsigned int num_entries);
+ static void disable_ai_pacing(struct comedi_device * dev);
+ static void disable_ai_interrupts(struct comedi_device * dev);
+-static void enable_ai_interrupts(struct comedi_device * dev, const comedi_cmd * cmd);
++static void enable_ai_interrupts(struct comedi_device * dev, const struct comedi_cmd * cmd);
+ static unsigned int get_ao_divisor(unsigned int ns, unsigned int flags);
+-static void load_ao_dma(struct comedi_device * dev, const comedi_cmd * cmd);
++static void load_ao_dma(struct comedi_device * dev, const struct comedi_cmd * cmd);
+ 
+ COMEDI_PCI_INITCLEANUP(driver_cb_pcidas, pcidas64_pci_table);
+ 
+@@ -2129,7 +2129,7 @@ static int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -2313,7 +2313,7 @@ static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int use_hw_sample_counter(comedi_cmd * cmd)
++static int use_hw_sample_counter(struct comedi_cmd * cmd)
+ {
+ // disable for now until I work out a race
+ 	return 0;
+@@ -2324,7 +2324,7 @@ static int use_hw_sample_counter(comedi_cmd * cmd)
+ 		return 0;
+ }
+ 
+-static void setup_sample_counters(struct comedi_device * dev, comedi_cmd * cmd)
++static void setup_sample_counters(struct comedi_device * dev, struct comedi_cmd * cmd)
+ {
+ 	if (cmd->stop_src == TRIG_COUNT) {
+ 		// set software count
+@@ -2387,7 +2387,7 @@ static void disable_ai_interrupts(struct comedi_device * dev)
+ 	DEBUG_PRINT("intr enable bits 0x%x\n", priv(dev)->intr_enable_bits);
+ }
+ 
+-static void enable_ai_interrupts(struct comedi_device * dev, const comedi_cmd * cmd)
++static void enable_ai_interrupts(struct comedi_device * dev, const struct comedi_cmd * cmd)
+ {
+ 	uint32_t bits;
+ 	unsigned long flags;
+@@ -2409,13 +2409,13 @@ static void enable_ai_interrupts(struct comedi_device * dev, const comedi_cmd *
+ }
+ 
+ static uint32_t ai_convert_counter_6xxx(const struct comedi_device * dev,
+-	const comedi_cmd * cmd)
++	const struct comedi_cmd * cmd)
+ {
+ 	// supposed to load counter with desired divisor minus 3
+ 	return cmd->convert_arg / TIMER_BASE - 3;
+ }
+ 
+-static uint32_t ai_scan_counter_6xxx(struct comedi_device * dev, comedi_cmd * cmd)
++static uint32_t ai_scan_counter_6xxx(struct comedi_device * dev, struct comedi_cmd * cmd)
+ {
+ 	uint32_t count;
+ 	// figure out how long we need to delay at end of scan
+@@ -2435,7 +2435,7 @@ static uint32_t ai_scan_counter_6xxx(struct comedi_device * dev, comedi_cmd * cm
+ 	return count - 3;
+ }
+ 
+-static uint32_t ai_convert_counter_4020(struct comedi_device * dev, comedi_cmd * cmd)
++static uint32_t ai_convert_counter_4020(struct comedi_device * dev, struct comedi_cmd * cmd)
+ {
+ 	unsigned int divisor;
+ 
+@@ -2457,7 +2457,7 @@ static uint32_t ai_convert_counter_4020(struct comedi_device * dev, comedi_cmd *
+ }
+ 
+ static void select_master_clock_4020(struct comedi_device * dev,
+-	const comedi_cmd * cmd)
++	const struct comedi_cmd * cmd)
+ {
+ 	// select internal/external master clock
+ 	priv(dev)->hw_config_bits &= ~MASTER_CLOCK_4020_MASK;
+@@ -2475,7 +2475,7 @@ static void select_master_clock_4020(struct comedi_device * dev,
+ 		priv(dev)->main_iobase + HW_CONFIG_REG);
+ }
+ 
+-static void select_master_clock(struct comedi_device * dev, const comedi_cmd * cmd)
++static void select_master_clock(struct comedi_device * dev, const struct comedi_cmd * cmd)
+ {
+ 	switch (board(dev)->layout) {
+ 	case LAYOUT_4020:
+@@ -2503,7 +2503,7 @@ static inline void dma_start_sync(struct comedi_device * dev, unsigned int chann
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ }
+ 
+-static void set_ai_pacing(struct comedi_device * dev, comedi_cmd * cmd)
++static void set_ai_pacing(struct comedi_device * dev, struct comedi_cmd * cmd)
+ {
+ 	uint32_t convert_counter = 0, scan_counter = 0;
+ 
+@@ -2534,7 +2534,7 @@ static void set_ai_pacing(struct comedi_device * dev, comedi_cmd * cmd)
+ 	DEBUG_PRINT("scan counter 0x%x\n", scan_counter);
+ }
+ 
+-static int use_internal_queue_6xxx(const comedi_cmd * cmd)
++static int use_internal_queue_6xxx(const struct comedi_cmd * cmd)
+ {
+ 	int i;
+ 	for (i = 0; i + 1 < cmd->chanlist_len; i++) {
+@@ -2550,7 +2550,7 @@ static int use_internal_queue_6xxx(const comedi_cmd * cmd)
+ 	return 1;
+ }
+ 
+-static int setup_channel_queue(struct comedi_device * dev, const comedi_cmd * cmd)
++static int setup_channel_queue(struct comedi_device * dev, const struct comedi_cmd * cmd)
+ {
+ 	unsigned short bits;
+ 	int i;
+@@ -2682,7 +2682,7 @@ static inline void load_first_dma_descriptor(struct comedi_device * dev,
+ static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	struct comedi_async *async = s->async;
+-	comedi_cmd *cmd = &async->cmd;
++	struct comedi_cmd *cmd = &async->cmd;
+ 	uint32_t bits;
+ 	unsigned int i;
+ 	unsigned long flags;
+@@ -2801,7 +2801,7 @@ static void pio_drain_ai_fifo_16(struct comedi_device * dev)
+ {
+ 	struct comedi_subdevice *s = dev->read_subdev;
+ 	struct comedi_async *async = s->async;
+-	comedi_cmd *cmd = &async->cmd;
++	struct comedi_cmd *cmd = &async->cmd;
+ 	unsigned int i;
+ 	uint16_t prepost_bits;
+ 	int read_segment, read_index, write_segment, write_index;
+@@ -2868,7 +2868,7 @@ static void pio_drain_ai_fifo_32(struct comedi_device * dev)
+ {
+ 	struct comedi_subdevice *s = dev->read_subdev;
+ 	struct comedi_async *async = s->async;
+-	comedi_cmd *cmd = &async->cmd;
++	struct comedi_cmd *cmd = &async->cmd;
+ 	unsigned int i;
+ 	unsigned int max_transfer = 100000;
+ 	uint32_t fifo_data;
+@@ -2957,7 +2957,7 @@ void handle_ai_interrupt(struct comedi_device * dev, unsigned short status,
+ {
+ 	struct comedi_subdevice *s = dev->read_subdev;
+ 	struct comedi_async *async = s->async;
+-	comedi_cmd *cmd = &async->cmd;
++	struct comedi_cmd *cmd = &async->cmd;
+ 	uint8_t dma1_status;
+ 	unsigned long flags;
+ 
+@@ -3036,7 +3036,7 @@ static int last_ao_dma_load_completed(struct comedi_device * dev)
+ 	return 1;
+ }
+ 
+-static int ao_stopped_by_error(struct comedi_device * dev, const comedi_cmd * cmd)
++static int ao_stopped_by_error(struct comedi_device * dev, const struct comedi_cmd * cmd)
+ {
+ 	if (cmd->stop_src == TRIG_NONE)
+ 		return 1;
+@@ -3079,7 +3079,7 @@ static void handle_ao_interrupt(struct comedi_device * dev, unsigned short statu
+ {
+ 	struct comedi_subdevice *s = dev->write_subdev;
+ 	struct comedi_async *async;
+-	comedi_cmd *cmd;
++	struct comedi_cmd *cmd;
+ 	uint8_t dma0_status;
+ 	unsigned long flags;
+ 
+@@ -3232,7 +3232,7 @@ static int ao_readback_insn(struct comedi_device * dev, struct comedi_subdevice
+ 	return 1;
+ }
+ 
+-static void set_dac_control0_reg(struct comedi_device * dev, const comedi_cmd * cmd)
++static void set_dac_control0_reg(struct comedi_device * dev, const struct comedi_cmd * cmd)
+ {
+ 	unsigned int bits = DAC_ENABLE_BIT | WAVEFORM_GATE_LEVEL_BIT |
+ 		WAVEFORM_GATE_ENABLE_BIT | WAVEFORM_GATE_SELECT_BIT;
+@@ -3252,7 +3252,7 @@ static void set_dac_control0_reg(struct comedi_device * dev, const comedi_cmd *
+ 	writew(bits, priv(dev)->main_iobase + DAC_CONTROL0_REG);
+ }
+ 
+-static void set_dac_control1_reg(struct comedi_device * dev, const comedi_cmd * cmd)
++static void set_dac_control1_reg(struct comedi_device * dev, const struct comedi_cmd * cmd)
+ {
+ 	int i;
+ 
+@@ -3269,7 +3269,7 @@ static void set_dac_control1_reg(struct comedi_device * dev, const comedi_cmd *
+ 		priv(dev)->main_iobase + DAC_CONTROL1_REG);
+ }
+ 
+-static void set_dac_select_reg(struct comedi_device * dev, const comedi_cmd * cmd)
++static void set_dac_select_reg(struct comedi_device * dev, const struct comedi_cmd * cmd)
+ {
+ 	uint16_t bits;
+ 	unsigned int first_channel, last_channel;
+@@ -3284,7 +3284,7 @@ static void set_dac_select_reg(struct comedi_device * dev, const comedi_cmd * cm
+ 	writew(bits, priv(dev)->main_iobase + DAC_SELECT_REG);
+ }
+ 
+-static void set_dac_interval_regs(struct comedi_device * dev, const comedi_cmd * cmd)
++static void set_dac_interval_regs(struct comedi_device * dev, const struct comedi_cmd * cmd)
+ {
+ 	unsigned int divisor;
+ 
+@@ -3303,7 +3303,7 @@ static void set_dac_interval_regs(struct comedi_device * dev, const comedi_cmd *
+ }
+ 
+ static unsigned int load_ao_dma_buffer(struct comedi_device * dev,
+-	const comedi_cmd * cmd)
++	const struct comedi_cmd * cmd)
+ {
+ 	unsigned int num_bytes, buffer_index, prev_buffer_index;
+ 	unsigned int next_bits;
+@@ -3346,7 +3346,7 @@ static unsigned int load_ao_dma_buffer(struct comedi_device * dev,
+ 	return num_bytes;
+ }
+ 
+-static void load_ao_dma(struct comedi_device * dev, const comedi_cmd * cmd)
++static void load_ao_dma(struct comedi_device * dev, const struct comedi_cmd * cmd)
+ {
+ 	unsigned int num_bytes;
+ 	unsigned int next_transfer_addr;
+@@ -3368,7 +3368,7 @@ static void load_ao_dma(struct comedi_device * dev, const comedi_cmd * cmd)
+ 	} while (num_bytes >= DMA_BUFFER_SIZE);
+ }
+ 
+-static int prep_ao_dma(struct comedi_device * dev, const comedi_cmd * cmd)
++static int prep_ao_dma(struct comedi_device * dev, const struct comedi_cmd * cmd)
+ {
+ 	unsigned int num_bytes;
+ 	int i;
+@@ -3415,7 +3415,7 @@ static inline int external_ai_queue_in_use(struct comedi_device * dev)
+ 
+ static int ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 
+ 	if (external_ai_queue_in_use(dev)) {
+ 		warn_external_queue(dev);
+@@ -3441,7 +3441,7 @@ static int ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ static int ao_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int trig_num)
+ {
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 	int retval;
+ 
+ 	if (trig_num != 0)
+@@ -3462,7 +3462,7 @@ static int ao_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
+ }
+ 
+ static int ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -3851,7 +3851,7 @@ static int eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice
+  * sets cmd members appropriately.
+  * adc paces conversions from master clock by dividing by (x + 3) where x is 24 bit number
+  */
+-static void check_adc_timing(struct comedi_device * dev, comedi_cmd * cmd)
++static void check_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd)
+ {
+ 	unsigned int convert_divisor = 0, scan_divisor;
+ 	static const int min_convert_divisor = 3;
+diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
+index 2cc525f65163..794e5de21837 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidda.c
++++ b/drivers/staging/comedi/drivers/cb_pcidda.c
+@@ -238,7 +238,7 @@ static int cb_pcidda_detach(struct comedi_device * dev);
+ static int cb_pcidda_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ //static int cb_pcidda_ai_cmd(struct comedi_device *dev,struct comedi_subdevice *s);
+-//static int cb_pcidda_ai_cmdtest(struct comedi_device *dev,struct comedi_subdevice *s, comedi_cmd *cmd);
++//static int cb_pcidda_ai_cmdtest(struct comedi_device *dev,struct comedi_subdevice *s, struct comedi_cmd *cmd);
+ //static int cb_pcidda_ns_to_timer(unsigned int *ns,int round);
+ static unsigned int cb_pcidda_serial_in(struct comedi_device * dev);
+ static void cb_pcidda_serial_out(struct comedi_device * dev, unsigned int value,
+@@ -433,7 +433,7 @@ static int cb_pcidda_ai_cmd(struct comedi_device * dev, struct comedi_subdevice
+ 
+ #if 0
+ static int cb_pcidda_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c
+index 774a72722899..3adb1240e4c9 100644
+--- a/drivers/staging/comedi/drivers/comedi_parport.c
++++ b/drivers/staging/comedi/drivers/comedi_parport.c
+@@ -178,7 +178,7 @@ static int parport_intr_insn(struct comedi_device *dev, struct comedi_subdevice
+ }
+ 
+ static int parport_intr_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+-				comedi_cmd *cmd)
++				struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+diff --git a/drivers/staging/comedi/drivers/comedi_rt_timer.c b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+index 1ba425fda31a..f57a6467ae4f 100644
+--- a/drivers/staging/comedi/drivers/comedi_rt_timer.c
++++ b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+@@ -145,7 +145,7 @@ typedef struct {
+ 	RT_TASK *scan_task;	// rt task that controls conversion timing in a scan
+ 	/* io_function can point to either an input or output function
+ 	 * depending on what kind of subdevice we are emulating for */
+-	int (*io_function) (struct comedi_device * dev, comedi_cmd * cmd,
++	int (*io_function) (struct comedi_device * dev, struct comedi_cmd * cmd,
+ 		unsigned int index);
+ 	// RTIME has units of 1 = 838 nanoseconds
+ 	// time at which first scan started, used to check scan timing
+@@ -156,8 +156,8 @@ typedef struct {
+ 	RTIME convert_period;
+ 	// flags
+ 	volatile int stop;	// indicates we should stop
+-	volatile int rt_task_active;	// indicates rt_task is servicing a comedi_cmd
+-	volatile int scan_task_active;	// indicates scan_task is servicing a comedi_cmd
++	volatile int rt_task_active;	// indicates rt_task is servicing a struct comedi_cmd
++	volatile int scan_task_active;	// indicates scan_task is servicing a struct comedi_cmd
+ 	unsigned timer_running:1;
+ } timer_private;
+ #define devpriv ((timer_private *)dev->private)
+@@ -206,7 +206,7 @@ inline static int check_conversion_timing(struct comedi_device * dev,
+ }
+ 
+ // devpriv->io_function for an input subdevice
+-static int timer_data_read(struct comedi_device * dev, comedi_cmd * cmd,
++static int timer_data_read(struct comedi_device * dev, struct comedi_cmd * cmd,
+ 	unsigned int index)
+ {
+ 	struct comedi_subdevice *s = dev->read_subdev;
+@@ -231,7 +231,7 @@ static int timer_data_read(struct comedi_device * dev, comedi_cmd * cmd,
+ }
+ 
+ // devpriv->io_function for an output subdevice
+-static int timer_data_write(struct comedi_device * dev, comedi_cmd * cmd,
++static int timer_data_write(struct comedi_device * dev, struct comedi_cmd * cmd,
+ 	unsigned int index)
+ {
+ 	struct comedi_subdevice *s = dev->write_subdev;
+@@ -266,7 +266,7 @@ static int timer_data_write(struct comedi_device * dev, comedi_cmd * cmd,
+ }
+ 
+ // devpriv->io_function for DIO subdevices
+-static int timer_dio_read(struct comedi_device * dev, comedi_cmd * cmd,
++static int timer_dio_read(struct comedi_device * dev, struct comedi_cmd * cmd,
+ 	unsigned int index)
+ {
+ 	struct comedi_subdevice *s = dev->read_subdev;
+@@ -293,12 +293,12 @@ static void scan_task_func(comedi_rt_task_context_t d)
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+ 	struct comedi_subdevice *s = dev->subdevices + 0;
+ 	struct comedi_async *async = s->async;
+-	comedi_cmd *cmd = &async->cmd;
++	struct comedi_cmd *cmd = &async->cmd;
+ 	int i, ret;
+ 	unsigned long long n;
+ 	RTIME scan_start;
+ 
+-	// every comedi_cmd causes one execution of while loop
++	// every struct comedi_cmd causes one execution of while loop
+ 	while (1) {
+ 		devpriv->scan_task_active = 1;
+ 		// each for loop completes one scan
+@@ -353,7 +353,7 @@ static void scan_task_func(comedi_rt_task_context_t d)
+ 		comedi_event(dev, s);
+ 		async->events = 0;
+ 		devpriv->scan_task_active = 0;
+-		// suspend task until next comedi_cmd
++		// suspend task until next struct comedi_cmd
+ 		rt_task_suspend(devpriv->scan_task);
+ 	}
+ }
+@@ -362,11 +362,11 @@ static void timer_task_func(comedi_rt_task_context_t d)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+ 	struct comedi_subdevice *s = dev->subdevices + 0;
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 	int ret;
+ 	unsigned long long n;
+ 
+-	// every comedi_cmd causes one execution of while loop
++	// every struct comedi_cmd causes one execution of while loop
+ 	while (1) {
+ 		devpriv->rt_task_active = 1;
+ 		devpriv->scan_task_active = 1;
+@@ -391,7 +391,7 @@ static void timer_task_func(comedi_rt_task_context_t d)
+ 	      cleanup:
+ 
+ 		devpriv->rt_task_active = 0;
+-		// suspend until next comedi_cmd
++		// suspend until next struct comedi_cmd
+ 		rt_task_suspend(devpriv->rt_task);
+ 	}
+ }
+@@ -407,7 +407,7 @@ static int timer_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	return comedi_do_insn(devpriv->device, &xinsn);
+ }
+ 
+-static int cmdtest_helper(comedi_cmd * cmd,
++static int cmdtest_helper(struct comedi_cmd * cmd,
+ 	unsigned int start_src,
+ 	unsigned int scan_begin_src,
+ 	unsigned int convert_src,
+@@ -445,7 +445,7 @@ static int cmdtest_helper(comedi_cmd * cmd,
+ }
+ 
+ static int timer_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	unsigned int start_src = 0;
+@@ -519,12 +519,12 @@ static int timer_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s
+ static int timer_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	int ret;
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 
+ 	/* hack attack: drivers are not supposed to do this: */
+ 	dev->rt = 1;
+ 
+-	// make sure tasks have finished cleanup of last comedi_cmd
++	// make sure tasks have finished cleanup of last struct comedi_cmd
+ 	if (devpriv->rt_task_active || devpriv->scan_task_active)
+ 		return -EBUSY;
+ 
+@@ -581,7 +581,7 @@ static int timer_inttrig(struct comedi_device * dev, struct comedi_subdevice * s
+ static int timer_start_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	struct comedi_async *async = s->async;
+-	comedi_cmd *cmd = &async->cmd;
++	struct comedi_cmd *cmd = &async->cmd;
+ 	RTIME now, delay, period;
+ 	int ret;
+ 
+diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c
+index 671f56f0a542..8fcec97a84dc 100644
+--- a/drivers/staging/comedi/drivers/comedi_test.c
++++ b/drivers/staging/comedi/drivers/comedi_test.c
+@@ -108,7 +108,7 @@ static struct comedi_driver driver_waveform = {
+ COMEDI_INITCLEANUP(driver_waveform);
+ 
+ static int waveform_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+-			       comedi_cmd *cmd);
++			       struct comedi_cmd *cmd);
+ static int waveform_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
+ static int waveform_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
+ static int waveform_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
+@@ -145,7 +145,7 @@ static void waveform_ai_interrupt(unsigned long arg)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) arg;
+ 	struct comedi_async *async = dev->read_subdev->async;
+-	comedi_cmd *cmd = &async->cmd;
++	struct comedi_cmd *cmd = &async->cmd;
+ 	unsigned int i, j;
+ 	/* all times in microsec */
+ 	unsigned long elapsed_time;
+@@ -270,7 +270,7 @@ static int waveform_detach(struct comedi_device *dev)
+ }
+ 
+ static int waveform_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+-			       comedi_cmd *cmd)
++			       struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -399,7 +399,7 @@ static int waveform_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevic
+ 
+ static int waveform_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 
+ 	if (cmd->flags & TRIG_RT) {
+ 		comedi_error(dev,
+diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
+index 87303081f616..bbe58550083c 100644
+--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
++++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
+@@ -92,7 +92,7 @@ static int contec_do_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+ 
+ #if 0
+ static int contec_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd);
++	struct comedi_cmd * cmd);
+ 
+ static int contec_ns_to_timer(unsigned int *ns, int round);
+ #endif
+@@ -180,7 +180,7 @@ static int contec_detach(struct comedi_device * dev)
+ 
+ #if 0
+ static int contec_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	printk("contec_cmdtest called\n");
+ 	return 0;
+diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
+index 6c2b214dfefc..1ca8f2eb48ab 100644
+--- a/drivers/staging/comedi/drivers/das16.c
++++ b/drivers/staging/comedi/drivers/das16.c
+@@ -336,7 +336,7 @@ static int das16_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice *
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ static int das16_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd);
++	struct comedi_cmd * cmd);
+ static int das16_cmd_exec(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int das16_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static void das16_ai_munge(struct comedi_device * dev, struct comedi_subdevice * s,
+@@ -351,7 +351,7 @@ static unsigned int das16_set_pacer(struct comedi_device * dev, unsigned int ns,
+ 	int flags);
+ static int das1600_mode_detect(struct comedi_device * dev);
+ static unsigned int das16_suggest_transfer_size(struct comedi_device * dev,
+-	comedi_cmd cmd);
++	struct comedi_cmd cmd);
+ 
+ static void reg_dump(struct comedi_device * dev);
+ 
+@@ -743,7 +743,7 @@ struct das16_private_struct {
+ #define thisboard ((struct das16_board_struct *)(dev->board_ptr))
+ 
+ static int das16_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0, tmp;
+ 	int gain, start_chan, i;
+@@ -896,7 +896,7 @@ static int das16_cmd_test(struct comedi_device * dev, struct comedi_subdevice *
+ static int das16_cmd_exec(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	struct comedi_async *async = s->async;
+-	comedi_cmd *cmd = &async->cmd;
++	struct comedi_cmd *cmd = &async->cmd;
+ 	unsigned int byte;
+ 	unsigned long flags;
+ 	int range;
+@@ -1202,7 +1202,7 @@ static void das16_interrupt(struct comedi_device * dev)
+ 	unsigned long dma_flags, spin_flags;
+ 	struct comedi_subdevice *s = dev->read_subdev;
+ 	struct comedi_async *async;
+-	comedi_cmd *cmd;
++	struct comedi_cmd *cmd;
+ 	int num_bytes, residue;
+ 	int buffer_index;
+ 
+@@ -1675,7 +1675,7 @@ COMEDI_INITCLEANUP(driver_das16);
+ 
+ // utility function that suggests a dma transfer size in bytes
+ static unsigned int das16_suggest_transfer_size(struct comedi_device * dev,
+-	comedi_cmd cmd)
++	struct comedi_cmd cmd)
+ {
+ 	unsigned int size;
+ 	unsigned int freq;
+diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
+index eea48493756e..0de3afcc0ece 100644
+--- a/drivers/staging/comedi/drivers/das16m1.c
++++ b/drivers/staging/comedi/drivers/das16m1.c
+@@ -38,7 +38,7 @@ significantly different.
+ 
+ I was _barely_ able to reach the full 1 MHz capability
+ of this board, using a hard real-time interrupt
+-(set the TRIG_RT flag in your comedi_cmd and use
++(set the TRIG_RT flag in your struct comedi_cmd and use
+ rtlinux or RTAI).  The board can't do dma, so the bottleneck is
+ pulling the data across the ISA bus.  I timed the interrupt
+ handler, and it took my computer ~470 microseconds to pull 512
+@@ -139,7 +139,7 @@ static int das16m1_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ static int das16m1_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd);
++	struct comedi_cmd * cmd);
+ static int das16m1_cmd_exec(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int das16m1_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ 
+@@ -201,7 +201,7 @@ static inline short munge_sample(short data)
+ }
+ 
+ static int das16m1_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	unsigned int err = 0, tmp, i;
+ 
+@@ -325,7 +325,7 @@ static int das16m1_cmd_test(struct comedi_device * dev, struct comedi_subdevice
+ static int das16m1_cmd_exec(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	struct comedi_async *async = s->async;
+-	comedi_cmd *cmd = &async->cmd;
++	struct comedi_cmd *cmd = &async->cmd;
+ 	unsigned int byte, i;
+ 
+ 	if (dev->irq == 0) {
+@@ -518,7 +518,7 @@ static void das16m1_handler(struct comedi_device * dev, unsigned int status)
+ {
+ 	struct comedi_subdevice *s;
+ 	struct comedi_async *async;
+-	comedi_cmd *cmd;
++	struct comedi_cmd *cmd;
+ 	u16 num_samples;
+ 	u16 hw_counter;
+ 
+diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
+index 2e066727fda3..8d8ecac73a08 100644
+--- a/drivers/staging/comedi/drivers/das1800.c
++++ b/drivers/staging/comedi/drivers/das1800.c
+@@ -197,7 +197,7 @@ static void das1800_handle_fifo_half_full(struct comedi_device * dev,
+ static void das1800_handle_fifo_not_empty(struct comedi_device * dev,
+ 	struct comedi_subdevice * s);
+ static int das1800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd);
++	struct comedi_cmd * cmd);
+ static int das1800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int das1800_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+@@ -210,7 +210,7 @@ static int das1800_do_wbits(struct comedi_device * dev, struct comedi_subdevice
+ 
+ static int das1800_set_frequency(struct comedi_device * dev);
+ static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode);
+-static unsigned int suggest_transfer_size(comedi_cmd * cmd);
++static unsigned int suggest_transfer_size(struct comedi_cmd * cmd);
+ 
+ // analog input ranges
+ static const struct comedi_lrange range_ai_das1801 = {
+@@ -913,7 +913,7 @@ static void das1800_ai_handler(struct comedi_device * dev)
+ {
+ 	struct comedi_subdevice *s = dev->subdevices + 0;	/* analog input subdevice */
+ 	struct comedi_async *async = s->async;
+-	comedi_cmd *cmd = &async->cmd;
++	struct comedi_cmd *cmd = &async->cmd;
+ 	unsigned int status = inb(dev->iobase + DAS1800_STATUS);
+ 
+ 	async->events = 0;
+@@ -1027,7 +1027,7 @@ static void das1800_flush_dma_channel(struct comedi_device * dev, struct comedi_
+ 	unsigned int channel, uint16_t * buffer)
+ {
+ 	unsigned int num_bytes, num_samples;
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 
+ 	disable_dma(channel);
+ 
+@@ -1087,7 +1087,7 @@ static void das1800_handle_fifo_half_full(struct comedi_device * dev,
+ 	struct comedi_subdevice * s)
+ {
+ 	int numPoints = 0;	/* number of points to read */
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 
+ 	numPoints = FIFO_SIZE / 2;
+ 	/* if we only need some of the points */
+@@ -1107,7 +1107,7 @@ static void das1800_handle_fifo_not_empty(struct comedi_device * dev,
+ {
+ 	short dpnt;
+ 	int unipolar;
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 
+ 	unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB;
+ 
+@@ -1140,7 +1140,7 @@ static int das1800_cancel(struct comedi_device * dev, struct comedi_subdevice *
+ 
+ /* test analog input cmd */
+ static int das1800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -1314,7 +1314,7 @@ static int das1800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subde
+ // first, some utility functions used in the main ai_do_cmd()
+ 
+ // returns appropriate bits for control register a, depending on command
+-static int control_a_bits(comedi_cmd cmd)
++static int control_a_bits(struct comedi_cmd cmd)
+ {
+ 	int control_a;
+ 
+@@ -1337,7 +1337,7 @@ static int control_a_bits(comedi_cmd cmd)
+ }
+ 
+ // returns appropriate bits for control register c, depending on command
+-static int control_c_bits(comedi_cmd cmd)
++static int control_c_bits(struct comedi_cmd cmd)
+ {
+ 	int control_c;
+ 	int aref;
+@@ -1385,7 +1385,7 @@ static int control_c_bits(comedi_cmd cmd)
+ }
+ 
+ // sets up counters
+-static int setup_counters(struct comedi_device * dev, comedi_cmd cmd)
++static int setup_counters(struct comedi_device * dev, struct comedi_cmd cmd)
+ {
+ 	// setup cascaded counters for conversion/scan frequency
+ 	switch (cmd.scan_begin_src) {
+@@ -1424,7 +1424,7 @@ static int setup_counters(struct comedi_device * dev, comedi_cmd cmd)
+ }
+ 
+ // sets up dma
+-static void setup_dma(struct comedi_device * dev, comedi_cmd cmd)
++static void setup_dma(struct comedi_device * dev, struct comedi_cmd cmd)
+ {
+ 	unsigned long lock_flags;
+ 	const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
+@@ -1462,7 +1462,7 @@ static void setup_dma(struct comedi_device * dev, comedi_cmd cmd)
+ }
+ 
+ // programs channel/gain list into card
+-static void program_chanlist(struct comedi_device * dev, comedi_cmd cmd)
++static void program_chanlist(struct comedi_device * dev, struct comedi_cmd cmd)
+ {
+ 	int i, n, chan_range;
+ 	unsigned long irq_flags;
+@@ -1494,7 +1494,7 @@ static int das1800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice
+ 	int ret;
+ 	int control_a, control_c;
+ 	struct comedi_async *async = s->async;
+-	comedi_cmd cmd = async->cmd;
++	struct comedi_cmd cmd = async->cmd;
+ 
+ 	if (!dev->irq) {
+ 		comedi_error(dev,
+@@ -1720,7 +1720,7 @@ static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode)
+ }
+ 
+ // utility function that suggests a dma transfer size based on the conversion period 'ns'
+-static unsigned int suggest_transfer_size(comedi_cmd * cmd)
++static unsigned int suggest_transfer_size(struct comedi_cmd * cmd)
+ {
+ 	unsigned int size = DMA_BUF_SIZE;
+ 	static const int sample_size = 2;	// size in bytes of one sample from board
+diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
+index 6485e33fb520..6f94a6663eca 100644
+--- a/drivers/staging/comedi/drivers/das800.c
++++ b/drivers/staging/comedi/drivers/das800.c
+@@ -260,7 +260,7 @@ static irqreturn_t das800_interrupt(int irq, void *d PT_REGS_ARG);
+ static void enable_das800(struct comedi_device * dev);
+ static void disable_das800(struct comedi_device * dev);
+ static int das800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd);
++	struct comedi_cmd * cmd);
+ static int das800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int das800_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+@@ -585,7 +585,7 @@ static void disable_das800(struct comedi_device * dev)
+ }
+ 
+ static int das800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
+index 17713b3934fe..42c6c0e9a857 100644
+--- a/drivers/staging/comedi/drivers/dmm32at.c
++++ b/drivers/staging/comedi/drivers/dmm32at.c
+@@ -300,7 +300,7 @@ static int dmm32at_dio_insn_bits(struct comedi_device * dev, struct comedi_subde
+ static int dmm32at_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ static int dmm32at_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd);
++	struct comedi_cmd * cmd);
+ static int dmm32at_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int dmm32at_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int dmm32at_ns_to_timer(unsigned int *ns, int round);
+@@ -569,7 +569,7 @@ static int dmm32at_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice
+ }
+ 
+ static int dmm32at_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -754,7 +754,7 @@ static int dmm32at_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevic
+ 
+ static int dmm32at_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 	int i, range;
+ 	unsigned char chanlo, chanhi, status;
+ 
+@@ -845,7 +845,7 @@ static irqreturn_t dmm32at_isr(int irq, void *d PT_REGS_ARG)
+ 
+ 	if (intstat & DMM32AT_ADINT) {
+ 		struct comedi_subdevice *s = dev->read_subdev;
+-		comedi_cmd *cmd = &s->async->cmd;
++		struct comedi_cmd *cmd = &s->async->cmd;
+ 
+ 		for (i = 0; i < cmd->chanlist_len; i++) {
+ 			/* read data */
+diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c
+index eb46d0f5e0db..2ee2fa307b10 100644
+--- a/drivers/staging/comedi/drivers/dt2814.c
++++ b/drivers/staging/comedi/drivers/dt2814.c
+@@ -133,7 +133,7 @@ static int dt2814_ns_to_timer(unsigned int *ns, unsigned int flags)
+ }
+ 
+ static int dt2814_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -226,7 +226,7 @@ static int dt2814_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice
+ 
+ static int dt2814_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 	int chan;
+ 	int trigvar;
+ 
+diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
+index 9e8d1bc45d59..79308492bcb0 100644
+--- a/drivers/staging/comedi/drivers/dt282x.c
++++ b/drivers/staging/comedi/drivers/dt282x.c
+@@ -707,7 +707,7 @@ static int dt282x_ai_insn_read(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int dt282x_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -820,7 +820,7 @@ static int dt282x_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice
+ 
+ static int dt282x_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 	int timer;
+ 
+ 	if (devpriv->usedma == 0) {
+@@ -979,7 +979,7 @@ static int dt282x_ao_insn_write(struct comedi_device * dev, struct comedi_subdev
+ }
+ 
+ static int dt282x_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -1102,7 +1102,7 @@ static int dt282x_ao_inttrig(struct comedi_device * dev, struct comedi_subdevice
+ static int dt282x_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	int timer;
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 
+ 	if (devpriv->usedma == 0) {
+ 		comedi_error(dev,
+diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
+index 60763e51435a..10875cfaa71c 100644
+--- a/drivers/staging/comedi/drivers/dt3000.c
++++ b/drivers/staging/comedi/drivers/dt3000.c
+@@ -426,7 +426,7 @@ static void dt3k_ai_empty_fifo(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int dt3k_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -589,7 +589,7 @@ static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
+ 
+ static int dt3k_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 	int i;
+ 	unsigned int chan, range, aref;
+ 	unsigned int divider;
+diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
+index ccc010f40d47..828fd315e644 100644
+--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
++++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
+@@ -57,7 +57,7 @@ static int hpdi_detach(struct comedi_device * dev);
+ void abort_dma(struct comedi_device * dev, unsigned int channel);
+ static int hpdi_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int hpdi_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd);
++	struct comedi_cmd * cmd);
+ static int hpdi_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static irqreturn_t handle_interrupt(int irq, void *d PT_REGS_ARG);
+ static int dio_config_block_size(struct comedi_device * dev, unsigned int * data);
+@@ -719,7 +719,7 @@ static int dio_config_block_size(struct comedi_device * dev, unsigned int * data
+ }
+ 
+ static int di_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -819,7 +819,7 @@ static int di_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+ }
+ 
+ static int hpdi_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	if (priv(dev)->dio_config_output) {
+ 		return -EINVAL;
+@@ -839,7 +839,7 @@ static int di_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	uint32_t bits;
+ 	unsigned long flags;
+ 	struct comedi_async *async = s->async;
+-	comedi_cmd *cmd = &async->cmd;
++	struct comedi_cmd *cmd = &async->cmd;
+ 
+ 	hpdi_writel(dev, RX_FIFO_RESET_BIT, BOARD_CONTROL_REG);
+ 
+diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
+index 16a34111fe1d..48802836346f 100644
+--- a/drivers/staging/comedi/drivers/me4000.c
++++ b/drivers/staging/comedi/drivers/me4000.c
+@@ -166,27 +166,27 @@ static int me4000_ai_insn_read(struct comedi_device *dev,
+ static int me4000_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
+ 
+ static int ai_check_chanlist(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_cmd *cmd);
++	struct comedi_subdevice *s, struct comedi_cmd *cmd);
+ 
+ static int ai_round_cmd_args(struct comedi_device *dev,
+ 	struct comedi_subdevice *s,
+-	comedi_cmd *cmd,
++	struct comedi_cmd *cmd,
+ 	unsigned int *init_ticks,
+ 	unsigned int *scan_ticks, unsigned int *chan_ticks);
+ 
+ static int ai_prepare(struct comedi_device *dev,
+ 	struct comedi_subdevice *s,
+-	comedi_cmd *cmd,
++	struct comedi_cmd *cmd,
+ 	unsigned int init_ticks,
+ 	unsigned int scan_ticks, unsigned int chan_ticks);
+ 
+ static int ai_write_chanlist(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_cmd *cmd);
++	struct comedi_subdevice *s, struct comedi_cmd *cmd);
+ 
+ static irqreturn_t me4000_ai_isr(int irq, void *dev_id PT_REGS_ARG);
+ 
+ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_cmd *cmd);
++	struct comedi_subdevice *s, struct comedi_cmd *cmd);
+ 
+ static int me4000_ai_do_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
+ 
+@@ -1055,7 +1055,7 @@ static int me4000_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *
+ }
+ 
+ static int ai_check_chanlist(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_cmd *cmd)
++	struct comedi_subdevice *s, struct comedi_cmd *cmd)
+ {
+ 	int aref;
+ 	int i;
+@@ -1137,7 +1137,7 @@ static int ai_check_chanlist(struct comedi_device *dev,
+ 
+ static int ai_round_cmd_args(struct comedi_device *dev,
+ 	struct comedi_subdevice *s,
+-	comedi_cmd *cmd,
++	struct comedi_cmd *cmd,
+ 	unsigned int *init_ticks,
+ 	unsigned int *scan_ticks, unsigned int *chan_ticks)
+ {
+@@ -1224,7 +1224,7 @@ static void ai_write_timer(struct comedi_device *dev,
+ 
+ static int ai_prepare(struct comedi_device *dev,
+ 	struct comedi_subdevice *s,
+-	comedi_cmd *cmd,
++	struct comedi_cmd *cmd,
+ 	unsigned int init_ticks,
+ 	unsigned int scan_ticks, unsigned int chan_ticks)
+ {
+@@ -1292,7 +1292,7 @@ static int ai_prepare(struct comedi_device *dev,
+ }
+ 
+ static int ai_write_chanlist(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_cmd *cmd)
++	struct comedi_subdevice *s, struct comedi_cmd *cmd)
+ {
+ 	unsigned int entry;
+ 	unsigned int chan;
+@@ -1337,7 +1337,7 @@ static int me4000_ai_do_cmd(struct comedi_device *dev, struct comedi_subdevice *
+ 	unsigned int init_ticks = 0;
+ 	unsigned int scan_ticks = 0;
+ 	unsigned int chan_ticks = 0;
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 
+ 	CALL_PDEBUG("In me4000_ai_do_cmd()\n");
+ 
+@@ -1376,7 +1376,7 @@ static int me4000_ai_do_cmd(struct comedi_device *dev, struct comedi_subdevice *
+  * So I tried to adopt this scheme.
+  */
+ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_cmd *cmd)
++	struct comedi_subdevice *s, struct comedi_cmd *cmd)
+ {
+ 
+ 	unsigned int init_ticks;
+diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c
+index a87c8ddf8945..1c19358a0ad4 100644
+--- a/drivers/staging/comedi/drivers/me_daq.c
++++ b/drivers/staging/comedi/drivers/me_daq.c
+@@ -450,7 +450,7 @@ static int me_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ 
+ /* Test analog input command */
+ static int me_ai_do_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
+-			     comedi_cmd *cmd)
++			     struct comedi_cmd *cmd)
+ {
+ 	return 0;
+ }
+diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
+index 7879f8675820..f2ab049ee78c 100644
+--- a/drivers/staging/comedi/drivers/ni_6527.c
++++ b/drivers/staging/comedi/drivers/ni_6527.c
+@@ -231,7 +231,7 @@ static irqreturn_t ni6527_interrupt(int irq, void *d PT_REGS_ARG)
+ }
+ 
+ static int ni6527_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -308,7 +308,7 @@ static int ni6527_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevi
+ 
+ static int ni6527_intr_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	//comedi_cmd *cmd = &s->async->cmd;
++	//struct comedi_cmd *cmd = &s->async->cmd;
+ 
+ 	writeb(ClrEdge | ClrOverflow,
+ 		devpriv->mite->daq_io_addr + Clear_Register);
+diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
+index b89543115c27..95159e411d3e 100644
+--- a/drivers/staging/comedi/drivers/ni_65xx.c
++++ b/drivers/staging/comedi/drivers/ni_65xx.c
+@@ -472,7 +472,7 @@ static irqreturn_t ni_65xx_interrupt(int irq, void *d PT_REGS_ARG)
+ }
+ 
+ static int ni_65xx_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -549,7 +549,7 @@ static int ni_65xx_intr_cmdtest(struct comedi_device * dev, struct comedi_subdev
+ 
+ static int ni_65xx_intr_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	//comedi_cmd *cmd = &s->async->cmd;
++	//struct comedi_cmd *cmd = &s->async->cmd;
+ 
+ 	writeb(ClrEdge | ClrOverflow,
+ 		private(dev)->mite->daq_io_addr + Clear_Register);
+diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
+index 469f9553f034..c347c9b3c2fa 100644
+--- a/drivers/staging/comedi/drivers/ni_660x.c
++++ b/drivers/staging/comedi/drivers/ni_660x.c
+@@ -848,7 +848,7 @@ static int ni_660x_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	int retval;
+ 
+ 	struct ni_gpct *counter = subdev_to_counter(s);
+-//      const comedi_cmd *cmd = &s->async->cmd;
++//      const struct comedi_cmd *cmd = &s->async->cmd;
+ 
+ 	retval = ni_660x_request_mite_channel(dev, counter, COMEDI_INPUT);
+ 	if (retval) {
+@@ -863,7 +863,7 @@ static int ni_660x_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ }
+ 
+ static int ni_660x_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	struct ni_gpct *counter = subdev_to_counter(s);
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
+index 2a3032bbcced..8a13e8624b04 100644
+--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
++++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
+@@ -180,7 +180,7 @@ static struct comedi_driver driver_a2150 = {
+ 
+ static irqreturn_t a2150_interrupt(int irq, void *d PT_REGS_ARG);
+ static int a2150_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd);
++	struct comedi_cmd * cmd);
+ static int a2150_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int a2150_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+@@ -215,7 +215,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d PT_REGS_ARG)
+ 	struct comedi_device *dev = d;
+ 	struct comedi_subdevice *s = dev->read_subdev;
+ 	struct comedi_async *async;
+-	comedi_cmd *cmd;
++	struct comedi_cmd *cmd;
+ 	unsigned int max_points, num_points, residue, leftover;
+ 	short dpnt;
+ 	static const int sample_size = sizeof(devpriv->dma_buffer[0]);
+@@ -486,7 +486,7 @@ static int a2150_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ }
+ 
+ static int a2150_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -618,7 +618,7 @@ static int a2150_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice
+ static int a2150_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	struct comedi_async *async = s->async;
+-	comedi_cmd *cmd = &async->cmd;
++	struct comedi_cmd *cmd = &async->cmd;
+ 	unsigned long lock_flags;
+ 	unsigned int old_config_bits = devpriv->config_bits;
+ 	unsigned int trigger_bits;
+diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
+index 4cbe558a9f04..09cafa966747 100644
+--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
++++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
+@@ -127,7 +127,7 @@ static int atmio16d_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int atmio16d_detach(struct comedi_device * dev);
+ static irqreturn_t atmio16d_interrupt(int irq, void *d PT_REGS_ARG);
+ static int atmio16d_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd);
++	struct comedi_cmd * cmd);
+ static int atmio16d_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int atmio16d_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static void reset_counters(struct comedi_device * dev);
+@@ -269,7 +269,7 @@ static irqreturn_t atmio16d_interrupt(int irq, void *d PT_REGS_ARG)
+ }
+ 
+ static int atmio16d_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0, tmp;
+ #ifdef DEBUG1
+@@ -371,7 +371,7 @@ static int atmio16d_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevi
+ 
+ static int atmio16d_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned int timer, base_clock;
+ 	unsigned int sample_count, tmp, chan, gain;
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
+index ea906a7fef14..d592ab368ff5 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_700.c
++++ b/drivers/staging/comedi/drivers/ni_daq_700.c
+@@ -200,7 +200,7 @@ static void do_config(struct comedi_device * dev, struct comedi_subdevice * s)
+ }
+ 
+ static int subdev_700_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	unsigned int tmp;
+diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
+index f1a284e6358c..2b3b4664bead 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc.c
++++ b/drivers/staging/comedi/drivers/ni_labpc.c
+@@ -171,7 +171,7 @@ static void labpc_drain_dma(struct comedi_device * dev);
+ static void handle_isa_dma(struct comedi_device * dev);
+ static void labpc_drain_dregs(struct comedi_device * dev);
+ static int labpc_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd);
++	struct comedi_cmd * cmd);
+ static int labpc_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int labpc_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+@@ -187,8 +187,8 @@ static int labpc_eeprom_read_insn(struct comedi_device * dev, struct comedi_subd
+ 	comedi_insn * insn, unsigned int * data);
+ static int labpc_eeprom_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static unsigned int labpc_suggest_transfer_size(comedi_cmd cmd);
+-static void labpc_adc_timing(struct comedi_device * dev, comedi_cmd * cmd);
++static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd);
++static void labpc_adc_timing(struct comedi_device * dev, struct comedi_cmd * cmd);
+ #ifdef CONFIG_COMEDI_PCI
+ static int labpc_find_device(struct comedi_device *dev, int bus, int slot);
+ #endif
+@@ -770,7 +770,7 @@ static int labpc_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static enum scan_mode labpc_ai_scan_mode(const comedi_cmd * cmd)
++static enum scan_mode labpc_ai_scan_mode(const struct comedi_cmd * cmd)
+ {
+ 	if (cmd->chanlist_len == 1)
+ 		return MODE_SINGLE_CHAN;
+@@ -794,7 +794,7 @@ static enum scan_mode labpc_ai_scan_mode(const comedi_cmd * cmd)
+ }
+ 
+ static int labpc_ai_chanlist_invalid(const struct comedi_device * dev,
+-	const comedi_cmd * cmd)
++	const struct comedi_cmd * cmd)
+ {
+ 	int mode, channel, range, aref, i;
+ 
+@@ -865,7 +865,7 @@ static int labpc_ai_chanlist_invalid(const struct comedi_device * dev,
+ 	return 0;
+ }
+ 
+-static int labpc_use_continuous_mode(const comedi_cmd * cmd)
++static int labpc_use_continuous_mode(const struct comedi_cmd * cmd)
+ {
+ 	if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN)
+ 		return 1;
+@@ -876,7 +876,7 @@ static int labpc_use_continuous_mode(const comedi_cmd * cmd)
+ 	return 0;
+ }
+ 
+-static unsigned int labpc_ai_convert_period(const comedi_cmd * cmd)
++static unsigned int labpc_ai_convert_period(const struct comedi_cmd * cmd)
+ {
+ 	if (cmd->convert_src != TRIG_TIMER)
+ 		return 0;
+@@ -888,7 +888,7 @@ static unsigned int labpc_ai_convert_period(const comedi_cmd * cmd)
+ 	return cmd->convert_arg;
+ }
+ 
+-static void labpc_set_ai_convert_period(comedi_cmd * cmd, unsigned int ns)
++static void labpc_set_ai_convert_period(struct comedi_cmd * cmd, unsigned int ns)
+ {
+ 	if (cmd->convert_src != TRIG_TIMER)
+ 		return;
+@@ -902,7 +902,7 @@ static void labpc_set_ai_convert_period(comedi_cmd * cmd, unsigned int ns)
+ 		cmd->convert_arg = ns;
+ }
+ 
+-static unsigned int labpc_ai_scan_period(const comedi_cmd * cmd)
++static unsigned int labpc_ai_scan_period(const struct comedi_cmd * cmd)
+ {
+ 	if (cmd->scan_begin_src != TRIG_TIMER)
+ 		return 0;
+@@ -914,7 +914,7 @@ static unsigned int labpc_ai_scan_period(const comedi_cmd * cmd)
+ 	return cmd->scan_begin_arg;
+ }
+ 
+-static void labpc_set_ai_scan_period(comedi_cmd * cmd, unsigned int ns)
++static void labpc_set_ai_scan_period(struct comedi_cmd * cmd, unsigned int ns)
+ {
+ 	if (cmd->scan_begin_src != TRIG_TIMER)
+ 		return;
+@@ -927,7 +927,7 @@ static void labpc_set_ai_scan_period(comedi_cmd * cmd, unsigned int ns)
+ }
+ 
+ static int labpc_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp, tmp2;
+@@ -1069,7 +1069,7 @@ static int labpc_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	unsigned long irq_flags;
+ 	int ret;
+ 	struct comedi_async *async = s->async;
+-	comedi_cmd *cmd = &async->cmd;
++	struct comedi_cmd *cmd = &async->cmd;
+ 	enum transfer_type xfer;
+ 	unsigned long flags;
+ 
+@@ -1314,7 +1314,7 @@ static irqreturn_t labpc_interrupt(int irq, void *d PT_REGS_ARG)
+ 	struct comedi_device *dev = d;
+ 	struct comedi_subdevice *s = dev->read_subdev;
+ 	struct comedi_async *async;
+-	comedi_cmd *cmd;
++	struct comedi_cmd *cmd;
+ 
+ 	if (dev->attached == 0) {
+ 		comedi_error(dev, "premature interrupt");
+@@ -1680,7 +1680,7 @@ static int labpc_eeprom_write_insn(struct comedi_device * dev, struct comedi_sub
+ }
+ 
+ // utility function that suggests a dma transfer size in bytes
+-static unsigned int labpc_suggest_transfer_size(comedi_cmd cmd)
++static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd)
+ {
+ 	unsigned int size;
+ 	unsigned int freq;
+@@ -1704,7 +1704,7 @@ static unsigned int labpc_suggest_transfer_size(comedi_cmd cmd)
+ }
+ 
+ // figures out what counter values to use based on command
+-static void labpc_adc_timing(struct comedi_device * dev, comedi_cmd * cmd)
++static void labpc_adc_timing(struct comedi_device * dev, struct comedi_cmd * cmd)
+ {
+ 	const int max_counter_value = 0x10000;	// max value for 16 bit counter in mode 2
+ 	const int min_counter_value = 2;	// min value for 16 bit counter in mode 2
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index eaa141daafae..a2988bdb2652 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -198,7 +198,7 @@ static int ni_dio_insn_config(struct comedi_device * dev, struct comedi_subdevic
+ static int ni_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ static int ni_cdio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd);
++	struct comedi_cmd * cmd);
+ static int ni_cdio_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int ni_cdio_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static void handle_cdio_interrupt(struct comedi_device * dev);
+@@ -275,7 +275,7 @@ static int ni_gpct_insn_config(struct comedi_device * dev, struct comedi_subdevi
+ 	comedi_insn * insn, unsigned int * data);
+ static int ni_gpct_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int ni_gpct_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd);
++	struct comedi_cmd * cmd);
+ static int ni_gpct_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static void handle_gpct_interrupt(struct comedi_device * dev,
+ 	unsigned short counter_index);
+@@ -1207,7 +1207,7 @@ static void ni_mio_print_status_b(int status)
+ static void ni_ao_fifo_load(struct comedi_device * dev, struct comedi_subdevice * s, int n)
+ {
+ 	struct comedi_async *async = s->async;
+-	comedi_cmd *cmd = &async->cmd;
++	struct comedi_cmd *cmd = &async->cmd;
+ 	int chan;
+ 	int i;
+ 	short d;
+@@ -2096,7 +2096,7 @@ static unsigned ni_min_ai_scan_period_ns(struct comedi_device * dev,
+ }
+ 
+ static int ni_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -2310,7 +2310,7 @@ static int ni_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s
+ 
+ static int ni_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	const comedi_cmd *cmd = &s->async->cmd;
++	const struct comedi_cmd *cmd = &s->async->cmd;
+ 	int timer;
+ 	int mode1 = 0;		/* mode1 is needed for both stop and convert */
+ 	int mode2 = 0;
+@@ -3064,7 +3064,7 @@ static int ni_ao_inttrig(struct comedi_device * dev, struct comedi_subdevice * s
+ 
+ static int ni_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	const comedi_cmd *cmd = &s->async->cmd;
++	const struct comedi_cmd *cmd = &s->async->cmd;
+ 	int bits;
+ 	int i;
+ 	unsigned trigvar;
+@@ -3262,7 +3262,7 @@ static int ni_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ }
+ 
+ static int ni_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -3545,7 +3545,7 @@ static int ni_m_series_dio_insn_bits(struct comedi_device * dev, struct comedi_s
+ }
+ 
+ static int ni_cdio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -3655,7 +3655,7 @@ static int ni_cdio_cmdtest(struct comedi_device * dev, struct comedi_subdevice *
+ 
+ static int ni_cdio_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	const comedi_cmd *cmd = &s->async->cmd;
++	const struct comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned cdo_mode_bits = CDO_FIFO_Mode_Bit | CDO_Halt_On_Error_Bit;
+ 	int retval;
+ 
+@@ -5096,7 +5096,7 @@ static int ni_gpct_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	int retval;
+ #ifdef PCIDMA
+ 	struct ni_gpct *counter = s->private;
+-//      const comedi_cmd *cmd = &s->async->cmd;
++//      const struct comedi_cmd *cmd = &s->async->cmd;
+ 
+ 	retval = ni_request_gpct_mite_channel(dev, counter->counter_index,
+ 		COMEDI_INPUT);
+@@ -5115,7 +5115,7 @@ static int ni_gpct_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ }
+ 
+ static int ni_gpct_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ #ifdef PCIDMA
+ 	struct ni_gpct *counter = s->private;
+diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
+index 5b0f2b61b1ee..9787a6e9f951 100644
+--- a/drivers/staging/comedi/drivers/ni_pcidio.c
++++ b/drivers/staging/comedi/drivers/ni_pcidio.c
+@@ -400,7 +400,7 @@ typedef struct {
+ #define devpriv ((nidio96_private *)dev->private)
+ 
+ static int ni_pcidio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd);
++	struct comedi_cmd * cmd);
+ static int ni_pcidio_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int ni_pcidio_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int trignum);
+@@ -745,7 +745,7 @@ static int ni_pcidio_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+ }
+ 
+ static int ni_pcidio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -878,7 +878,7 @@ static int ni_pcidio_ns_to_timer(int *nanosec, int round_mode)
+ 
+ static int ni_pcidio_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 
+ 	/* XXX configure ports for input */
+ 	writel(0x0000, devpriv->mite->daq_io_addr + Port_Pin_Directions(0));
+diff --git a/drivers/staging/comedi/drivers/ni_tio.h b/drivers/staging/comedi/drivers/ni_tio.h
+index e5dbd82826b0..de68c8694dfa 100644
+--- a/drivers/staging/comedi/drivers/ni_tio.h
++++ b/drivers/staging/comedi/drivers/ni_tio.h
+@@ -146,7 +146,7 @@ extern int ni_tio_insn_config(struct ni_gpct *counter,
+ extern int ni_tio_winsn(struct ni_gpct *counter,
+ 	comedi_insn * insn, unsigned int * data);
+ extern int ni_tio_cmd(struct ni_gpct *counter, struct comedi_async *async);
+-extern int ni_tio_cmdtest(struct ni_gpct *counter, comedi_cmd * cmd);
++extern int ni_tio_cmdtest(struct ni_gpct *counter, struct comedi_cmd * cmd);
+ extern int ni_tio_cancel(struct ni_gpct *counter);
+ extern void ni_tio_handle_interrupt(struct ni_gpct *counter,
+ 	struct comedi_subdevice * s);
+diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c
+index 2c3a21771875..16a26e73c994 100644
+--- a/drivers/staging/comedi/drivers/ni_tiocmd.c
++++ b/drivers/staging/comedi/drivers/ni_tiocmd.c
+@@ -124,7 +124,7 @@ static int ni_tio_input_inttrig(struct comedi_device * dev, struct comedi_subdev
+ static int ni_tio_input_cmd(struct ni_gpct *counter, struct comedi_async *async)
+ {
+ 	struct ni_gpct_device *counter_dev = counter->counter_dev;
+-	comedi_cmd *cmd = &async->cmd;
++	struct comedi_cmd *cmd = &async->cmd;
+ 	int retval = 0;
+ 
+ 	/* write alloc the entire buffer */
+@@ -183,7 +183,7 @@ static int ni_tio_output_cmd(struct ni_gpct *counter, struct comedi_async *async
+ 
+ static int ni_tio_cmd_setup(struct ni_gpct *counter, struct comedi_async *async)
+ {
+-	comedi_cmd *cmd = &async->cmd;
++	struct comedi_cmd *cmd = &async->cmd;
+ 	int set_gate_source = 0;
+ 	unsigned gate_source;
+ 	int retval = 0;
+@@ -209,7 +209,7 @@ static int ni_tio_cmd_setup(struct ni_gpct *counter, struct comedi_async *async)
+ 
+ int ni_tio_cmd(struct ni_gpct *counter, struct comedi_async *async)
+ {
+-	comedi_cmd *cmd = &async->cmd;
++	struct comedi_cmd *cmd = &async->cmd;
+ 	int retval = 0;
+ 	unsigned long flags;
+ 
+@@ -232,7 +232,7 @@ int ni_tio_cmd(struct ni_gpct *counter, struct comedi_async *async)
+ 	return retval;
+ }
+ 
+-int ni_tio_cmdtest(struct ni_gpct *counter, comedi_cmd * cmd)
++int ni_tio_cmdtest(struct ni_gpct *counter, struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c
+index 8603cd18383c..68bd7e963db4 100644
+--- a/drivers/staging/comedi/drivers/pcl711.c
++++ b/drivers/staging/comedi/drivers/pcl711.c
+@@ -280,7 +280,7 @@ static int pcl711_ai_insn(struct comedi_device * dev, struct comedi_subdevice *
+ }
+ 
+ static int pcl711_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int tmp;
+ 	int err = 0;
+@@ -384,7 +384,7 @@ static int pcl711_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice
+ static int pcl711_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	int timer1, timer2;
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 
+ 	pcl711_set_changain(dev, cmd->chanlist[0]);
+ 
+diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
+index 522cb0527cfc..c554ed583eed 100644
+--- a/drivers/staging/comedi/drivers/pcl812.c
++++ b/drivers/staging/comedi/drivers/pcl812.c
+@@ -575,7 +575,7 @@ static int pcl812_do_insn_bits(struct comedi_device * dev, struct comedi_subdevi
+ /*
+ ==============================================================================
+ */
+-static void pcl812_cmdtest_out(int e, comedi_cmd * cmd)
++static void pcl812_cmdtest_out(int e, struct comedi_cmd * cmd)
+ {
+ 	rt_printk("pcl812 e=%d startsrc=%x scansrc=%x convsrc=%x\n", e,
+ 		cmd->start_src, cmd->scan_begin_src, cmd->convert_src);
+@@ -592,7 +592,7 @@ static void pcl812_cmdtest_out(int e, comedi_cmd * cmd)
+ ==============================================================================
+ */
+ static int pcl812_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp, divisor1, divisor2;
+@@ -773,7 +773,7 @@ static int pcl812_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice
+ static int pcl812_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned int divisor1 = 0, divisor2 = 0, i, dma_flags, bytes;
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 
+ #ifdef PCL812_EXTDEBUG
+ 	rt_printk("pcl812 EDBG: BGN: pcl812_ai_cmd(...)\n");
+diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
+index d90e2e584f63..60d7a2c1d190 100644
+--- a/drivers/staging/comedi/drivers/pcl816.c
++++ b/drivers/staging/comedi/drivers/pcl816.c
+@@ -219,7 +219,7 @@ static int set_rtc_irq_bit(unsigned char bit);
+ #endif
+ 
+ static int pcl816_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd);
++	struct comedi_cmd * cmd);
+ static int pcl816_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ 
+ /*
+@@ -443,7 +443,7 @@ static irqreturn_t interrupt_pcl816(int irq, void *d PT_REGS_ARG)
+ ==============================================================================
+    COMMAND MODE
+ */
+-static void pcl816_cmdtest_out(int e, comedi_cmd * cmd)
++static void pcl816_cmdtest_out(int e, struct comedi_cmd * cmd)
+ {
+ 	rt_printk("pcl816 e=%d startsrc=%x scansrc=%x convsrc=%x\n", e,
+ 		cmd->start_src, cmd->scan_begin_src, cmd->convert_src);
+@@ -459,7 +459,7 @@ static void pcl816_cmdtest_out(int e, comedi_cmd * cmd)
+ ==============================================================================
+ */
+ static int pcl816_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp, divisor1, divisor2;
+@@ -596,7 +596,7 @@ static int pcl816_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice
+ static int pcl816_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned int divisor1 = 0, divisor2 = 0, dma_flags, bytes, dmairq;
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 
+ 	if (cmd->start_src != TRIG_NOW)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
+index d1992969c037..9eaabfb18042 100644
+--- a/drivers/staging/comedi/drivers/pcl818.c
++++ b/drivers/staging/comedi/drivers/pcl818.c
+@@ -955,7 +955,7 @@ static void pcl818_ai_mode13dma_rtc(int mode, struct comedi_device * dev,
+ static int pcl818_ai_cmd_mode(int mode, struct comedi_device * dev,
+ 	struct comedi_subdevice * s)
+ {
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 	int divisor1, divisor2;
+ 	unsigned int seglen;
+ 
+@@ -1252,7 +1252,7 @@ static int check_single_ended(unsigned int port)
+ ==============================================================================
+ */
+ static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp, divisor1, divisor2;
+@@ -1398,7 +1398,7 @@ static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ */
+ static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 	int retval;
+ 
+ 	rt_printk("pcl818_ai_cmd()\n");
+diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
+index 780de845034a..f428f6923f59 100644
+--- a/drivers/staging/comedi/drivers/pcmmio.c
++++ b/drivers/staging/comedi/drivers/pcmmio.c
+@@ -305,7 +305,7 @@ static void pcmmio_stop_intr(struct comedi_device *, struct comedi_subdevice *);
+ static int pcmmio_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int pcmmio_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int pcmmio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd);
++	struct comedi_cmd * cmd);
+ 
+ /* some helper functions to deal with specifics of this device's registers */
+ static void init_asics(struct comedi_device * dev);	/* sets up/clears ASIC chips to defaults */
+@@ -946,7 +946,7 @@ static int pcmmio_start_intr(struct comedi_device * dev, struct comedi_subdevice
+ 	} else {
+ 		unsigned bits = 0, pol_bits = 0, n;
+ 		int nports, firstport, asic, port;
+-		comedi_cmd *cmd = &s->async->cmd;
++		struct comedi_cmd *cmd = &s->async->cmd;
+ 
+ 		if ((asic = subpriv->dio.intr.asic) < 0)
+ 			return 1;	/* not an interrupt
+@@ -1039,7 +1039,7 @@ pcmmio_inttrig_start_intr(struct comedi_device * dev, struct comedi_subdevice *
+  */
+ static int pcmmio_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned long flags;
+ 	int event = 0;
+ 
+@@ -1082,7 +1082,7 @@ static int pcmmio_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+  * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
+  */
+ static int
+-pcmmio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, comedi_cmd * cmd)
++pcmmio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	unsigned int tmp;
+diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
+index 7204084073f0..2c460cf67c89 100644
+--- a/drivers/staging/comedi/drivers/pcmuio.c
++++ b/drivers/staging/comedi/drivers/pcmuio.c
+@@ -263,7 +263,7 @@ static void pcmuio_stop_intr(struct comedi_device *, struct comedi_subdevice *);
+ static int pcmuio_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int pcmuio_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int pcmuio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd);
++	struct comedi_cmd * cmd);
+ 
+ /* some helper functions to deal with specifics of this device's registers */
+ static void init_asics(struct comedi_device * dev);	/* sets up/clears ASIC chips to defaults */
+@@ -866,7 +866,7 @@ static int pcmuio_start_intr(struct comedi_device * dev, struct comedi_subdevice
+ 	} else {
+ 		unsigned bits = 0, pol_bits = 0, n;
+ 		int nports, firstport, asic, port;
+-		comedi_cmd *cmd = &s->async->cmd;
++		struct comedi_cmd *cmd = &s->async->cmd;
+ 
+ 		if ((asic = subpriv->intr.asic) < 0)
+ 			return 1;	/* not an interrupt
+@@ -949,7 +949,7 @@ pcmuio_inttrig_start_intr(struct comedi_device * dev, struct comedi_subdevice *
+  */
+ static int pcmuio_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned long flags;
+ 	int event = 0;
+ 
+@@ -992,7 +992,7 @@ static int pcmuio_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+  * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
+  */
+ static int
+-pcmuio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, comedi_cmd * cmd)
++pcmuio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	unsigned int tmp;
+diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+index d83cc3295dd4..9a188d44551f 100644
+--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
++++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+@@ -468,7 +468,7 @@ static int daqp_ns_to_timer(unsigned int *ns, int round)
+  */
+ 
+ static int daqp_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -596,7 +596,7 @@ static int daqp_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice *
+ static int daqp_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	local_info_t *local = (local_info_t *) s->private;
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 	int counter = 100;
+ 	int scanlist_start_on_every_entry;
+ 	int threshold;
+diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
+index 42b96fae7100..6ce02fa6082d 100644
+--- a/drivers/staging/comedi/drivers/rtd520.c
++++ b/drivers/staging/comedi/drivers/rtd520.c
+@@ -701,7 +701,7 @@ static int rtd_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice
+ static int rtd_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+ static int rtd_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_cmd *cmd);
++	struct comedi_cmd *cmd);
+ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
+ static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
+ /* static int rtd_ai_poll (struct comedi_device *dev,struct comedi_subdevice *s); */
+@@ -1666,7 +1666,7 @@ static int rtd_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
+ */
+ 
+ static int rtd_ai_cmdtest(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_cmd *cmd)
++	struct comedi_subdevice *s, struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -1872,7 +1872,7 @@ static int rtd_ai_cmdtest(struct comedi_device *dev,
+ */
+ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 	int timer;
+ 
+ 	/* stop anything currently running */
+diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
+index 4f7068fb2bc0..80fedbb47b76 100644
+--- a/drivers/staging/comedi/drivers/s626.c
++++ b/drivers/staging/comedi/drivers/s626.c
+@@ -229,7 +229,7 @@ static int s626_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice
+ 	comedi_insn *insn, unsigned int *data);
+ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
+ static int s626_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_cmd *cmd);
++	struct comedi_cmd *cmd);
+ static int s626_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
+ static int s626_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+@@ -250,7 +250,7 @@ static int s626_enc_insn_read(struct comedi_device *dev, struct comedi_subdevice
+ static int s626_enc_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+ static int s626_ns_to_timer(int *nanosec, int round_mode);
+-static int s626_ai_load_polllist(uint8_t *ppl, comedi_cmd *cmd);
++static int s626_ai_load_polllist(uint8_t *ppl, struct comedi_cmd *cmd);
+ static int s626_ai_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int trignum);
+ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG);
+@@ -972,7 +972,7 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG)
+ {
+ 	struct comedi_device *dev = d;
+ 	struct comedi_subdevice *s;
+-	comedi_cmd *cmd;
++	struct comedi_cmd *cmd;
+ 	struct enc_private *k;
+ 	unsigned long flags;
+ 	int32_t *readaddr;
+@@ -1318,7 +1318,7 @@ void ResetADC(struct comedi_device *dev, uint8_t *ppl)
+ 	uint16_t i;
+ 	uint16_t n;
+ 	uint32_t LocalPPL;
+-	comedi_cmd *cmd = &(dev->subdevices->async->cmd);
++	struct comedi_cmd *cmd = &(dev->subdevices->async->cmd);
+ 
+ 	/*  Stop RPS program in case it is currently running. */
+ 	MC_DISABLE(P_MC1, MC1_ERPS1);
+@@ -1638,7 +1638,7 @@ static int s626_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice
+ 	return n;
+ }
+ 
+-static int s626_ai_load_polllist(uint8_t *ppl, comedi_cmd *cmd)
++static int s626_ai_load_polllist(uint8_t *ppl, struct comedi_cmd *cmd)
+ {
+ 
+ 	int n;
+@@ -1677,7 +1677,7 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 
+ 	uint8_t ppl[16];
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 	struct enc_private *k;
+ 	int tick;
+ 
+@@ -1820,7 +1820,7 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ }
+ 
+ static int s626_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+-	comedi_cmd *cmd)
++	struct comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c
+index 5dda0cd6c990..511c4e32479c 100644
+--- a/drivers/staging/comedi/drivers/skel.c
++++ b/drivers/staging/comedi/drivers/skel.c
+@@ -192,7 +192,7 @@ static int skel_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevic
+ static int skel_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ static int skel_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd);
++	struct comedi_cmd * cmd);
+ static int skel_ns_to_timer(unsigned int *ns, int round);
+ 
+ /*
+@@ -347,7 +347,7 @@ static int skel_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s
+ }
+ 
+ static int skel_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+-	comedi_cmd * cmd)
++	struct comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
+index 108f2d71cd83..7ec175aadbef 100644
+--- a/drivers/staging/comedi/drivers/usbdux.c
++++ b/drivers/staging/comedi/drivers/usbdux.c
+@@ -897,7 +897,7 @@ static int usbduxsub_submit_OutURBs(struct usbduxsub *usbduxsub)
+ }
+ 
+ static int usbdux_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+-			     comedi_cmd *cmd)
++			     struct comedi_cmd *cmd)
+ {
+ 	int err = 0, tmp, i;
+ 	unsigned int tmpTimer;
+@@ -1162,7 +1162,7 @@ static int usbdux_ai_inttrig(struct comedi_device *dev, struct comedi_subdevice
+ 
+ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned int chan, range;
+ 	int i, ret;
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+@@ -1451,7 +1451,7 @@ static int usbdux_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice
+ }
+ 
+ static int usbdux_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+-			     comedi_cmd *cmd)
++			     struct comedi_cmd *cmd)
+ {
+ 	int err = 0, tmp;
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+@@ -1591,7 +1591,7 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice
+ 
+ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned int chan, gain;
+ 	int i, ret;
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c
+index a5e93ac066bb..bbd552f2a500 100644
+--- a/drivers/staging/comedi/drivers/usbduxfast.c
++++ b/drivers/staging/comedi/drivers/usbduxfast.c
+@@ -578,7 +578,7 @@ int usbduxfastsub_submit_InURBs(struct usbduxfastsub_s *udfs)
+ }
+ 
+ static int usbduxfast_ai_cmdtest(struct comedi_device *dev,
+-	struct comedi_subdevice *s, comedi_cmd *cmd)
++	struct comedi_subdevice *s, struct comedi_cmd *cmd)
+ {
+ 	int err = 0, stop_mask = 0;
+ 	long int steps, tmp;
+@@ -773,7 +773,7 @@ static int usbduxfast_ai_inttrig(struct comedi_device *dev,
+ 
+ static int usbduxfast_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+-	comedi_cmd *cmd = &s->async->cmd;
++	struct comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned int chan, gain, rngmask = 0xff;
+ 	int i, j, ret;
+ 	struct usbduxfastsub_s *udfs;
+diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+index 31b749d4962a..43dae3e40379 100644
+--- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
++++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+@@ -121,7 +121,7 @@ int comedi_fileno(void *d)
+ 	return dev->minor;
+ }
+ 
+-int comedi_command(void *d, comedi_cmd *cmd)
++int comedi_command(void *d, struct comedi_cmd *cmd)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+ 	struct comedi_subdevice *s;
+@@ -161,7 +161,7 @@ int comedi_command(void *d, comedi_cmd *cmd)
+ 	return s->do_cmd(dev, s);
+ }
+ 
+-int comedi_command_test(void *d, comedi_cmd *cmd)
++int comedi_command_test(void *d, struct comedi_cmd *cmd)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+ 	struct comedi_subdevice *s;

commit b50d88d08069ba14d9ba7ba6a15414fdbd077508
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:05:42 2009 -0400
+
+    Staging: comedi: Remove comedi_trig typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
+index 665dbc7de003..ab9bd016a567 100644
+--- a/drivers/staging/comedi/comedi.h
++++ b/drivers/staging/comedi/comedi.h
+@@ -310,7 +310,6 @@ enum comedi_support_level {
+ 
+ /* structures */
+ 
+-typedef struct comedi_trig_struct comedi_trig;
+ typedef struct comedi_cmd_struct comedi_cmd;
+ typedef struct comedi_insn_struct comedi_insn;
+ typedef struct comedi_insnlist_struct comedi_insnlist;
+@@ -323,7 +322,7 @@ typedef struct comedi_krange_struct comedi_krange;
+ typedef struct comedi_bufconfig_struct comedi_bufconfig;
+ typedef struct comedi_bufinfo_struct comedi_bufinfo;
+ 
+-struct comedi_trig_struct {
++struct comedi_trig {
+ 	unsigned int subdev;	/* subdevice */
+ 	unsigned int mode;	/* mode */
+ 	unsigned int flags;
+diff --git a/drivers/staging/comedi/comedilib.h b/drivers/staging/comedi/comedilib.h
+index b4192e486aa5..523497740212 100644
+--- a/drivers/staging/comedi/comedilib.h
++++ b/drivers/staging/comedi/comedilib.h
+@@ -62,8 +62,8 @@ int comedi_register_callback(void *dev, unsigned int subdev,
+ 
+ int comedi_command(void *dev, comedi_cmd *cmd);
+ int comedi_command_test(void *dev, comedi_cmd *cmd);
+-int comedi_trigger(void *dev, unsigned int subdev, comedi_trig *it);
+-int __comedi_trigger(void *dev, unsigned int subdev, comedi_trig *it);
++int comedi_trigger(void *dev, unsigned int subdev, struct comedi_trig *it);
++int __comedi_trigger(void *dev, unsigned int subdev, struct comedi_trig *it);
+ int comedi_data_write(void *dev, unsigned int subdev, unsigned int chan,
+ 	unsigned int range, unsigned int aref, unsigned int data);
+ int comedi_data_read(void *dev, unsigned int subdev, unsigned int chan,
+@@ -139,8 +139,8 @@ int comedi_register_callback(unsigned int minor, unsigned int subdev,
+ 
+ int comedi_command(unsigned int minor, comedi_cmd *cmd);
+ int comedi_command_test(unsigned int minor, comedi_cmd *cmd);
+-int comedi_trigger(unsigned int minor, unsigned int subdev, comedi_trig *it);
+-int __comedi_trigger(unsigned int minor, unsigned int subdev, comedi_trig *it);
++int comedi_trigger(unsigned int minor, unsigned int subdev, struct comedi_trig *it);
++int __comedi_trigger(unsigned int minor, unsigned int subdev, struct comedi_trig *it);
+ int comedi_data_write(unsigned int dev, unsigned int subdev, unsigned int chan,
+ 	unsigned int range, unsigned int aref, unsigned int data);
+ int comedi_data_read(unsigned int dev, unsigned int subdev, unsigned int chan,

commit 0bfbbe8f09617247c87d3b626cbf007c423afff1
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:05:36 2009 -0400
+
+    Staging: comedi: Remove device_create_result_type typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
+index d38addd01d4a..524bef968a1c 100644
+--- a/drivers/staging/comedi/comedi_fops.c
++++ b/drivers/staging/comedi/comedi_fops.c
+@@ -2130,7 +2130,7 @@ int comedi_alloc_board_minor(struct device *hardware_device)
+ {
+ 	unsigned long flags;
+ 	struct comedi_device_file_info *info;
+-	device_create_result_type *csdev;
++	struct device *csdev;
+ 	unsigned i;
+ 
+ 	info = kzalloc(sizeof(struct comedi_device_file_info), GFP_KERNEL);
+@@ -2197,7 +2197,7 @@ int comedi_alloc_subdevice_minor(struct comedi_device *dev, struct comedi_subdev
+ {
+ 	unsigned long flags;
+ 	struct comedi_device_file_info *info;
+-	device_create_result_type *csdev;
++	struct device *csdev;
+ 	unsigned i;
+ 
+ 	info = kmalloc(sizeof(struct comedi_device_file_info), GFP_KERNEL);
+diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
+index 3f9b2d027168..4333139e5245 100644
+--- a/drivers/staging/comedi/comedidev.h
++++ b/drivers/staging/comedi/comedidev.h
+@@ -121,8 +121,6 @@
+ #define COMEDI_NUM_BOARD_MINORS 0x30
+ #define COMEDI_FIRST_SUBDEVICE_MINOR COMEDI_NUM_BOARD_MINORS
+ 
+-typedef struct device device_create_result_type;
+-
+ #define COMEDI_DEVICE_CREATE(cs, parent, devt, drvdata, device, fmt...) \
+ 	device_create(cs, ((parent) ? (parent) : (device)), devt, drvdata, fmt)
+ 
+@@ -183,7 +181,7 @@ struct comedi_subdevice {
+ 
+ 	unsigned int state;
+ 
+-	device_create_result_type *class_dev;
++	struct device *class_dev;
+ 	int minor;
+ };
+ 
+@@ -256,7 +254,7 @@ struct comedi_device {
+ 	struct comedi_driver *driver;
+ 	void *private;
+ 
+-	device_create_result_type *class_dev;
++	struct device *class_dev;
+ 	int minor;
+ 	/* hw_dev is passed to dma_alloc_coherent when allocating async buffers
+ 	 * for subdevices that have async_dma_dir set to something other than

commit 9ced1de69125b60f40127eddaa3be2a92bb0a1df
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:05:31 2009 -0400
+
+    Staging: comedi: Remove comedi_lrange typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
+index 83c45a691bdd..3f9b2d027168 100644
+--- a/drivers/staging/comedi/comedidev.h
++++ b/drivers/staging/comedi/comedidev.h
+@@ -121,8 +121,6 @@
+ #define COMEDI_NUM_BOARD_MINORS 0x30
+ #define COMEDI_FIRST_SUBDEVICE_MINOR COMEDI_NUM_BOARD_MINORS
+ 
+-typedef struct comedi_lrange_struct comedi_lrange;
+-
+ typedef struct device device_create_result_type;
+ 
+ #define COMEDI_DEVICE_CREATE(cs, parent, devt, drvdata, device, fmt...) \
+@@ -154,8 +152,8 @@ struct comedi_subdevice {
+ 
+ 	unsigned int settling_time_0;
+ 
+-	const comedi_lrange *range_table;
+-	const comedi_lrange *const *range_table_list;
++	const struct comedi_lrange *range_table;
++	const struct comedi_lrange *const *range_table_list;
+ 
+ 	unsigned int *chanlist;	/* driver-owned chanlist (not used) */
+ 
+@@ -396,12 +394,12 @@ int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s,
+ #define BIP_RANGE(a)		{-(a)*1e6, (a)*1e6, 0}
+ #define UNI_RANGE(a)		{0, (a)*1e6, 0}
+ 
+-extern const comedi_lrange range_bipolar10;
+-extern const comedi_lrange range_bipolar5;
+-extern const comedi_lrange range_bipolar2_5;
+-extern const comedi_lrange range_unipolar10;
+-extern const comedi_lrange range_unipolar5;
+-extern const comedi_lrange range_unknown;
++extern const struct comedi_lrange range_bipolar10;
++extern const struct comedi_lrange range_bipolar5;
++extern const struct comedi_lrange range_bipolar2_5;
++extern const struct comedi_lrange range_unipolar10;
++extern const struct comedi_lrange range_unipolar5;
++extern const struct comedi_lrange range_unknown;
+ 
+ #define range_digital		range_unipolar5
+ 
+@@ -411,7 +409,7 @@ extern const comedi_lrange range_unknown;
+ #define GCC_ZERO_LENGTH_ARRAY 0
+ #endif
+ 
+-struct comedi_lrange_struct {
++struct comedi_lrange {
+ 	int length;
+ 	comedi_krange range[GCC_ZERO_LENGTH_ARRAY];
+ };
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+index 0df1287d14c8..0e06121f13e5 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+@@ -51,7 +51,7 @@ typedef unsigned int ULONG, *PULONG;	/* 32-bit */
+ typedef unsigned int DWORD, *PDWORD;	/* 32-bit */
+ typedef unsigned long ULONG_PTR;
+ 
+-typedef const comedi_lrange *PCRANGE;
++typedef const struct comedi_lrange *PCRANGE;
+ 
+ #define LOBYTE(W)	(BYTE)((W) & 0xFF)
+ #define HIBYTE(W)	(BYTE)(((W) >> 8) & 0xFF)
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.h
+index bdef85867433..998cbba8afeb 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.h
+@@ -46,7 +46,7 @@
+ 
+ //MODULE INFO STRUCTURE
+ 
+-static const comedi_lrange range_apci1710_ttl = { 4, {
++static const struct comedi_lrange range_apci1710_ttl = { 4, {
+ 						      BIP_RANGE(10),
+ 						      BIP_RANGE(5),
+ 						      BIP_RANGE(2),
+@@ -54,7 +54,7 @@ static const comedi_lrange range_apci1710_ttl = { 4, {
+ 						      }
+ };
+ 
+-static const comedi_lrange range_apci1710_ssi = { 4, {
++static const struct comedi_lrange range_apci1710_ssi = { 4, {
+ 						      BIP_RANGE(10),
+ 						      BIP_RANGE(5),
+ 						      BIP_RANGE(2),
+@@ -62,7 +62,7 @@ static const comedi_lrange range_apci1710_ssi = { 4, {
+ 						      }
+ };
+ 
+-static const comedi_lrange range_apci1710_inccpt = { 4, {
++static const struct comedi_lrange range_apci1710_inccpt = { 4, {
+ 							 BIP_RANGE(10),
+ 							 BIP_RANGE(5),
+ 							 BIP_RANGE(2),
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
+index 2f9af7b20b3e..01964823b34f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
+@@ -34,7 +34,7 @@ struct {
+ } Config_Parameters_Main;
+ 
+ /* ANALOG INPUT RANGE */
+-comedi_lrange range_apci035_ai = { 8, {
++struct comedi_lrange range_apci035_ai = { 8, {
+ 				       BIP_RANGE(10),
+ 				       BIP_RANGE(5),
+ 				       BIP_RANGE(2),
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h
+index ae66bfeeefaf..63ec520bb3a7 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h
+@@ -41,7 +41,7 @@
+ 
+ #ifdef __KERNEL__
+ 
+-static const comedi_lrange range_apci16xx_ttl = { 12,
++static const struct comedi_lrange range_apci16xx_ttl = { 12,
+ 	{BIP_RANGE(1),
+ 	 BIP_RANGE(1),
+ 	 BIP_RANGE(1),
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
+index f5fdb6c4894f..1a0806249457 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
+@@ -21,7 +21,7 @@
+ // comedi related defines
+ 
+ //ANALOG INPUT RANGE
+-static const comedi_lrange range_apci3120_ai = { 8, {
++static const struct comedi_lrange range_apci3120_ai = { 8, {
+ 						     BIP_RANGE(10),
+ 						     BIP_RANGE(5),
+ 						     BIP_RANGE(2),
+@@ -34,7 +34,7 @@ static const comedi_lrange range_apci3120_ai = { 8, {
+ };
+ 
+ // ANALOG OUTPUT RANGE
+-static const comedi_lrange range_apci3120_ao = { 2, {
++static const struct comedi_lrange range_apci3120_ao = { 2, {
+ 						     BIP_RANGE(10),
+ 						     UNI_RANGE(10)
+ 						     }
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+index 528673939f17..12ecce2db670 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+@@ -35,7 +35,7 @@ struct {
+     Config_Parameters_Module3, Config_Parameters_Module4;
+ 
+ //ANALOG INPUT RANGE
+-static const comedi_lrange range_apci3200_ai = { 8, {
++static const struct comedi_lrange range_apci3200_ai = { 8, {
+ 						     BIP_RANGE(10),
+ 						     BIP_RANGE(5),
+ 						     BIP_RANGE(2),
+@@ -47,7 +47,7 @@ static const comedi_lrange range_apci3200_ai = { 8, {
+ 						     }
+ };
+ 
+-static const comedi_lrange range_apci3300_ai = { 4, {
++static const struct comedi_lrange range_apci3300_ai = { 4, {
+ 						     UNI_RANGE(10),
+ 						     UNI_RANGE(5),
+ 						     UNI_RANGE(2),
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
+index 3b47634bfb91..550d81543b16 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
+@@ -32,7 +32,7 @@
+ #define MODE0                                     0
+ #define MODE1                                     1
+ // ANALOG OUTPUT RANGE
+-comedi_lrange range_apci3501_ao = { 2, {
++struct comedi_lrange range_apci3501_ao = { 2, {
+ 					BIP_RANGE(10),
+ 					UNI_RANGE(10)
+ 					}
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.h
+index 5dde36f68876..788d7c1cf5c1 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.h
+@@ -32,7 +32,7 @@
+ 
+ #ifdef __KERNEL__
+ 
+-static const comedi_lrange range_apci3XXX_ai = { 8, {BIP_RANGE(10),
++static const struct comedi_lrange range_apci3XXX_ai = { 8, {BIP_RANGE(10),
+ 						     BIP_RANGE(5),
+ 						     BIP_RANGE(2),
+ 						     BIP_RANGE(1),
+@@ -42,7 +42,7 @@ static const comedi_lrange range_apci3XXX_ai = { 8, {BIP_RANGE(10),
+ 						     UNI_RANGE(1)}
+ };
+ 
+-static const comedi_lrange range_apci3XXX_ttl = { 12, {BIP_RANGE(1),
++static const struct comedi_lrange range_apci3XXX_ttl = { 12, {BIP_RANGE(1),
+ 						       BIP_RANGE(1),
+ 						       BIP_RANGE(1),
+ 						       BIP_RANGE(1),
+@@ -56,7 +56,7 @@ static const comedi_lrange range_apci3XXX_ttl = { 12, {BIP_RANGE(1),
+ 						       BIP_RANGE(1)}
+ };
+ 
+-static const comedi_lrange range_apci3XXX_ao = { 2, {BIP_RANGE(10),
++static const struct comedi_lrange range_apci3XXX_ao = { 2, {BIP_RANGE(10),
+ 						     UNI_RANGE(10)}
+ };
+ #endif
+diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
+index 8b4c201aa4af..b4c6722ea766 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9111.c
++++ b/drivers/staging/comedi/drivers/adl_pci9111.c
+@@ -270,7 +270,7 @@ static int pci9111_detach(struct comedi_device * dev);
+ static void pci9111_ai_munge(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	void *data, unsigned int num_bytes, unsigned int start_chan_index);
+ 
+-static const comedi_lrange pci9111_hr_ai_range = {
++static const struct comedi_lrange pci9111_hr_ai_range = {
+ 	5,
+ 	{
+ 			BIP_RANGE(10),
+@@ -303,8 +303,8 @@ typedef struct {
+ 	int ai_resolution_mask;
+ 	int ao_resolution;	// resolution of D/A
+ 	int ao_resolution_mask;
+-	const comedi_lrange *ai_range_list;	// rangelist for A/D
+-	const comedi_lrange *ao_range_list;	// rangelist for D/A
++	const struct comedi_lrange *ai_range_list;	// rangelist for A/D
++	const struct comedi_lrange *ao_range_list;	// rangelist for D/A
+ 	unsigned int ai_acquisition_period_min_ns;
+ } pci9111_board_struct;
+ 
+diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
+index e2a6c29534d2..71745f128722 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9118.c
++++ b/drivers/staging/comedi/drivers/adl_pci9118.c
+@@ -152,7 +152,7 @@ Configuration options:
+ 
+ #define EXTTRG_AI	0	/* ext trg is used by AI */
+ 
+-static const comedi_lrange range_pci9118dg_hr = { 8, {
++static const struct comedi_lrange range_pci9118dg_hr = { 8, {
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(2.5),
+ 			BIP_RANGE(1.25),
+@@ -164,7 +164,7 @@ static const comedi_lrange range_pci9118dg_hr = { 8, {
+ 	}
+ };
+ 
+-static const comedi_lrange range_pci9118hg = { 8, {
++static const struct comedi_lrange range_pci9118hg = { 8, {
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(0.5),
+ 			BIP_RANGE(0.05),
+@@ -194,8 +194,8 @@ typedef struct {
+ 	int n_aochan;		// num of D/A chans
+ 	int ai_maxdata;		// resolution of A/D
+ 	int ao_maxdata;		// resolution of D/A
+-	const comedi_lrange *rangelist_ai;	// rangelist for A/D
+-	const comedi_lrange *rangelist_ao;	// rangelist for D/A
++	const struct comedi_lrange *rangelist_ai;	// rangelist for A/D
++	const struct comedi_lrange *rangelist_ao;	// rangelist for D/A
+ 	unsigned int ai_ns_min;	// max sample speed of card v ns
+ 	unsigned int ai_pacer_min;	// minimal pacer value (c1*c2 or c1 in burst)
+ 	int half_fifo_size;	// size of FIFO/2
+diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c
+index b5a328116807..fd2a6f7733b2 100644
+--- a/drivers/staging/comedi/drivers/adq12b.c
++++ b/drivers/staging/comedi/drivers/adq12b.c
+@@ -100,14 +100,14 @@ If you do not specify any options, they will default to
+ #define TIMEOUT        20
+ 
+ // available ranges through the PGA gains
+-static const comedi_lrange range_adq12b_ai_bipolar = { 4, {
++static const struct comedi_lrange range_adq12b_ai_bipolar = { 4, {
+         BIP_RANGE( 5 ),
+         BIP_RANGE( 2 ),
+         BIP_RANGE( 1 ),
+         BIP_RANGE( 0.5 )
+ }};
+ 
+-static const comedi_lrange range_adq12b_ai_unipolar = { 4, {
++static const struct comedi_lrange range_adq12b_ai_unipolar = { 4, {
+         UNI_RANGE( 5 ),
+         UNI_RANGE( 2 ),
+         UNI_RANGE( 1 ),
+diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
+index 776f93dc5ecb..6742baf7ffa8 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1710.c
++++ b/drivers/staging/comedi/drivers/adv_pci1710.c
+@@ -121,7 +121,7 @@ Configuration options:
+ // D/A synchronized control (PCI1720_SYNCONT)
+ #define Syncont_SC0	 1	/* set synchronous output mode */
+ 
+-static const comedi_lrange range_pci1710_3 = { 9, {
++static const struct comedi_lrange range_pci1710_3 = { 9, {
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(2.5),
+ 			BIP_RANGE(1.25),
+@@ -137,7 +137,7 @@ static const comedi_lrange range_pci1710_3 = { 9, {
+ static const char range_codes_pci1710_3[] =
+ 	{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x10, 0x11, 0x12, 0x13 };
+ 
+-static const comedi_lrange range_pci1710hg = { 12, {
++static const struct comedi_lrange range_pci1710hg = { 12, {
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(0.5),
+ 			BIP_RANGE(0.05),
+@@ -157,7 +157,7 @@ static const char range_codes_pci1710hg[] =
+ 	{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12,
+ 		0x13 };
+ 
+-static const comedi_lrange range_pci17x1 = { 5, {
++static const struct comedi_lrange range_pci17x1 = { 5, {
+ 			BIP_RANGE(10),
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(2.5),
+@@ -168,7 +168,7 @@ static const comedi_lrange range_pci17x1 = { 5, {
+ 
+ static const char range_codes_pci17x1[] = { 0x00, 0x01, 0x02, 0x03, 0x04 };
+ 
+-static const comedi_lrange range_pci1720 = { 4, {
++static const struct comedi_lrange range_pci1720 = { 4, {
+ 			UNI_RANGE(5),
+ 			UNI_RANGE(10),
+ 			BIP_RANGE(5),
+@@ -176,7 +176,7 @@ static const comedi_lrange range_pci1720 = { 4, {
+ 	}
+ };
+ 
+-static const comedi_lrange range_pci171x_da = { 2, {
++static const struct comedi_lrange range_pci171x_da = { 2, {
+ 			UNI_RANGE(5),
+ 			UNI_RANGE(10),
+ 	}
+@@ -199,9 +199,9 @@ typedef struct {
+ 	int n_counter;		// num of counters
+ 	int ai_maxdata;		// resolution of A/D
+ 	int ao_maxdata;		// resolution of D/A
+-	const comedi_lrange *rangelist_ai;	// rangelist for A/D
++	const struct comedi_lrange *rangelist_ai;	// rangelist for A/D
+ 	const char *rangecode_ai;	// range codes for programming
+-	const comedi_lrange *rangelist_ao;	// rangelist for D/A
++	const struct comedi_lrange *rangelist_ao;	// rangelist for D/A
+ 	unsigned int ai_ns_min;	// max sample speed of card v ns
+ 	unsigned int fifo_half_size;	// size of FIFO/2
+ } boardtype;
+diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
+index 5ce393043d17..c50578dfab9c 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1723.c
++++ b/drivers/staging/comedi/drivers/adv_pci1723.c
+@@ -94,7 +94,7 @@ configures all channels in the same group.
+ 
+ //static unsigned short pci_list_builded=0;     /*=1 list of card is know */
+ 
+-static const comedi_lrange range_pci1723 = { 1, {
++static const struct comedi_lrange range_pci1723 = { 1, {
+ 			BIP_RANGE(10)
+ 	}
+ };
+@@ -111,7 +111,7 @@ typedef struct pci1723_board_struct {
+ 	int n_aochan;		// num of D/A chans
+ 	int n_diochan;		// num of DIO chans
+ 	int ao_maxdata;		// resolution of D/A
+-	const comedi_lrange *rangelist_ao;	// rangelist for D/A
++	const struct comedi_lrange *rangelist_ao;	// rangelist for D/A
+ } boardtype;
+ 
+ static const boardtype boardtypes[] = {
+diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c
+index 4c569ddb195e..2d1b8d269645 100644
+--- a/drivers/staging/comedi/drivers/aio_aio12_8.c
++++ b/drivers/staging/comedi/drivers/aio_aio12_8.c
+@@ -151,7 +151,7 @@ static int aio_aio12_8_ao_write(struct comedi_device * dev, struct comedi_subdev
+ 	return insn->n;
+ }
+ 
+-static const comedi_lrange range_aio_aio12_8 = {
++static const struct comedi_lrange range_aio_aio12_8 = {
+ 	4,
+ 	{
+ 			UNI_RANGE(5),
+diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
+index 4ca283bb58ae..7ef57bf309cb 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci224.c
++++ b/drivers/staging/comedi/drivers/amplc_pci224.c
+@@ -278,7 +278,7 @@ Passing a zero for an option is the same as leaving it unspecified.
+  */
+ 
+ /* The software selectable internal ranges for PCI224 (option[2] == 0). */
+-static const comedi_lrange range_pci224_internal = {
++static const struct comedi_lrange range_pci224_internal = {
+ 	8,
+ 	{
+ 			BIP_RANGE(10),
+@@ -304,7 +304,7 @@ static const unsigned short hwrange_pci224_internal[8] = {
+ };
+ 
+ /* The software selectable external ranges for PCI224 (option[2] == 1). */
+-static const comedi_lrange range_pci224_external = {
++static const struct comedi_lrange range_pci224_external = {
+ 	2,
+ 	{
+ 			RANGE_ext(-1, 1),	/* bipolar [-Vref,+Vref] */
+@@ -319,7 +319,7 @@ static const unsigned short hwrange_pci224_external[2] = {
+ 
+ /* The hardware selectable Vref*2 external range for PCI234
+  * (option[2] == 1, option[3+n] == 0). */
+-static const comedi_lrange range_pci234_ext2 = {
++static const struct comedi_lrange range_pci234_ext2 = {
+ 	1,
+ 	{
+ 			RANGE_ext(-2, 2),
+@@ -328,7 +328,7 @@ static const comedi_lrange range_pci234_ext2 = {
+ 
+ /* The hardware selectable Vref external range for PCI234
+  * (option[2] == 1, option[3+n] == 1). */
+-static const comedi_lrange range_pci234_ext = {
++static const struct comedi_lrange range_pci234_ext = {
+ 	1,
+ 	{
+ 			RANGE_ext(-1, 1),
+@@ -1417,10 +1417,10 @@ static int pci224_attach(struct comedi_device * dev, comedi_devconfig * it)
+ 	/* Sort out channel range options. */
+ 	if (thisboard->model == pci234_model) {
+ 		/* PCI234 range options. */
+-		const comedi_lrange **range_table_list;
++		const struct comedi_lrange **range_table_list;
+ 
+ 		s->range_table_list = range_table_list =
+-			kmalloc(sizeof(comedi_lrange *) * s->n_chan,
++			kmalloc(sizeof(struct comedi_lrange *) * s->n_chan,
+ 			GFP_KERNEL);
+ 		if (!s->range_table_list) {
+ 			return -ENOMEM;
+diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
+index 7676f22772bf..7e7f627abb24 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci230.c
++++ b/drivers/staging/comedi/drivers/amplc_pci230.c
+@@ -568,7 +568,7 @@ static const unsigned int pci230_timebase[8] = {
+ };
+ 
+ /* PCI230 analogue input range table */
+-static const comedi_lrange pci230_ai_range = { 7, {
++static const struct comedi_lrange pci230_ai_range = { 7, {
+ 			BIP_RANGE(10),
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(2.5),
+@@ -586,7 +586,7 @@ static const unsigned char pci230_ai_gain[7] = { 0, 1, 2, 3, 1, 2, 3 };
+ static const unsigned char pci230_ai_bipolar[7] = { 1, 1, 1, 1, 0, 0, 0 };
+ 
+ /* PCI230 analogue output range table */
+-static const comedi_lrange pci230_ao_range = { 2, {
++static const struct comedi_lrange pci230_ao_range = { 2, {
+ 			UNI_RANGE(10),
+ 			BIP_RANGE(10)
+ 	}
+diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
+index d16a9278db10..8152970e8dfe 100644
+--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
++++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
+@@ -100,7 +100,7 @@ static struct comedi_driver driver_das16cs = {
+ 
+ static struct pcmcia_device *cur_dev = NULL;
+ 
+-static const comedi_lrange das16cs_ai_range = { 4, {
++static const struct comedi_lrange das16cs_ai_range = { 4, {
+ 			RANGE(-10, 10),
+ 			RANGE(-5, 5),
+ 			RANGE(-2.5, 2.5),
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
+index 75bf1d173509..1dcf7dde78ee 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas.c
+@@ -196,7 +196,7 @@ static inline unsigned int DAC_DATA_REG(unsigned int channel)
+ // bit in hexadecimal representation of range index that indicates unipolar input range
+ #define IS_UNIPOLAR 0x4
+ // analog input ranges for most boards
+-static const comedi_lrange cb_pcidas_ranges = {
++static const struct comedi_lrange cb_pcidas_ranges = {
+ 	8,
+ 	{
+ 			BIP_RANGE(10),
+@@ -211,7 +211,7 @@ static const comedi_lrange cb_pcidas_ranges = {
+ };
+ 
+ // pci-das1001 input ranges
+-static const comedi_lrange cb_pcidas_alt_ranges = {
++static const struct comedi_lrange cb_pcidas_alt_ranges = {
+ 	8,
+ 	{
+ 			BIP_RANGE(10),
+@@ -226,7 +226,7 @@ static const comedi_lrange cb_pcidas_alt_ranges = {
+ };
+ 
+ // analog output ranges
+-static const comedi_lrange cb_pcidas_ao_ranges = {
++static const struct comedi_lrange cb_pcidas_ao_ranges = {
+ 	4,
+ 	{
+ 			BIP_RANGE(5),
+@@ -252,7 +252,7 @@ typedef struct cb_pcidas_board_struct {
+ 	int has_ao_fifo;	// analog output has fifo
+ 	int ao_scan_speed;	// analog output speed for 1602 series (for a scan, not conversion)
+ 	int fifo_size;		// number of samples fifo can hold
+-	const comedi_lrange *ranges;
++	const struct comedi_lrange *ranges;
+ 	enum trimpot_model trimpot;
+ 	unsigned has_dac08:1;
+ } cb_pcidas_board;
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
+index ea55c2bf3e78..ce1638d72d6b 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
+@@ -400,7 +400,7 @@ static inline uint8_t attenuate_bit(unsigned int channel)
+ };
+ 
+ // analog input ranges for 64xx boards
+-static const comedi_lrange ai_ranges_64xx = {
++static const struct comedi_lrange ai_ranges_64xx = {
+ 	8,
+ 	{
+ 			BIP_RANGE(10),
+@@ -415,7 +415,7 @@ static const comedi_lrange ai_ranges_64xx = {
+ };
+ 
+ /* analog input ranges for 60xx boards */
+-static const comedi_lrange ai_ranges_60xx = {
++static const struct comedi_lrange ai_ranges_60xx = {
+ 	4,
+ 	{
+ 			BIP_RANGE(10),
+@@ -426,7 +426,7 @@ static const comedi_lrange ai_ranges_60xx = {
+ };
+ 
+ /* analog input ranges for 6030, etc boards */
+-static const comedi_lrange ai_ranges_6030 = {
++static const struct comedi_lrange ai_ranges_6030 = {
+ 	14,
+ 	{
+ 			BIP_RANGE(10),
+@@ -447,7 +447,7 @@ static const comedi_lrange ai_ranges_6030 = {
+ };
+ 
+ /* analog input ranges for 6052, etc boards */
+-static const comedi_lrange ai_ranges_6052 = {
++static const struct comedi_lrange ai_ranges_6052 = {
+ 	15,
+ 	{
+ 			BIP_RANGE(10),
+@@ -469,7 +469,7 @@ static const comedi_lrange ai_ranges_6052 = {
+ };
+ 
+ // analog input ranges for 4020 board
+-static const comedi_lrange ai_ranges_4020 = {
++static const struct comedi_lrange ai_ranges_4020 = {
+ 	2,
+ 	{
+ 			BIP_RANGE(5),
+@@ -478,7 +478,7 @@ static const comedi_lrange ai_ranges_4020 = {
+ };
+ 
+ // analog output ranges
+-static const comedi_lrange ao_ranges_64xx = {
++static const struct comedi_lrange ao_ranges_64xx = {
+ 	4,
+ 	{
+ 			BIP_RANGE(5),
+@@ -494,7 +494,7 @@ static const int ao_range_code_64xx[] = {
+ 	0x3,
+ };
+ 
+-static const comedi_lrange ao_ranges_60xx = {
++static const struct comedi_lrange ao_ranges_60xx = {
+ 	1,
+ 	{
+ 			BIP_RANGE(10),
+@@ -504,7 +504,7 @@ static const int ao_range_code_60xx[] = {
+ 	0x0,
+ };
+ 
+-static const comedi_lrange ao_ranges_6030 = {
++static const struct comedi_lrange ao_ranges_6030 = {
+ 	2,
+ 	{
+ 			BIP_RANGE(10),
+@@ -516,7 +516,7 @@ static const int ao_range_code_6030[] = {
+ 	0x2,
+ };
+ 
+-static const comedi_lrange ao_ranges_4020 = {
++static const struct comedi_lrange ao_ranges_4020 = {
+ 	2,
+ 	{
+ 			BIP_RANGE(5),
+@@ -547,11 +547,11 @@ typedef struct pcidas64_board_struct {
+ 	int ai_se_chans;	// number of ai inputs in single-ended mode
+ 	int ai_bits;		// analog input resolution
+ 	int ai_speed;		// fastest conversion period in ns
+-	const comedi_lrange *ai_range_table;
++	const struct comedi_lrange *ai_range_table;
+ 	int ao_nchan;		// number of analog out channels
+ 	int ao_bits;		// analog output resolution
+ 	int ao_scan_speed;	// analog output speed (for a scan, not conversion)
+-	const comedi_lrange *ao_range_table;
++	const struct comedi_lrange *ao_range_table;
+ 	const int *ao_range_code;
+ 	const hw_fifo_info_t *const ai_fifo;
+ 	enum register_layout layout;	// different board families have slightly different registers
+diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
+index dc107d1df261..2cc525f65163 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidda.c
++++ b/drivers/staging/comedi/drivers/cb_pcidda.c
+@@ -112,7 +112,7 @@ Please report success/failure with other different cards to
+ 
+ #define DADATA	8		// FIRST D/A DATA REGISTER (0)
+ 
+-static const comedi_lrange cb_pcidda_ranges = {
++static const struct comedi_lrange cb_pcidda_ranges = {
+ 	6,
+ 	{
+ 			BIP_RANGE(10),
+@@ -138,7 +138,7 @@ typedef struct cb_pcidda_board_struct {
+ 	unsigned short device_id;
+ 	int ao_chans;
+ 	int ao_bits;
+-	const comedi_lrange *ranges;
++	const struct comedi_lrange *ranges;
+ } cb_pcidda_board;
+ static const cb_pcidda_board cb_pcidda_boards[] = {
+ 	{
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
+index 0e739a567eb9..ac983b17f594 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
+@@ -97,7 +97,7 @@ typedef struct cb_pcimdas_board_struct {
+ 	int fifo_size;		// number of samples fifo can hold
+ 	int dio_bits;		// number of dio bits
+ 	int has_dio;		// has DIO
+-	const comedi_lrange *ranges;
++	const struct comedi_lrange *ranges;
+ } cb_pcimdas_board;
+ 
+ static const cb_pcimdas_board cb_pcimdas_boards[] = {
+diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c
+index 908dddcc5a45..671f56f0a542 100644
+--- a/drivers/staging/comedi/drivers/comedi_test.c
++++ b/drivers/staging/comedi/drivers/comedi_test.c
+@@ -128,7 +128,7 @@ static short fake_waveform(struct comedi_device *dev, unsigned int channel,
+ static const int nano_per_micro = 1000;
+ 
+ /* fake analog input ranges */
+-static const comedi_lrange waveform_ai_ranges = {
++static const struct comedi_lrange waveform_ai_ranges = {
+ 	2,
+ 	{
+ 			BIP_RANGE(10),
+diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
+index 378ec9471778..05058bf8d5e9 100644
+--- a/drivers/staging/comedi/drivers/daqboard2000.c
++++ b/drivers/staging/comedi/drivers/daqboard2000.c
+@@ -145,7 +145,7 @@ Configuration options:
+ #define DAQBOARD2000_CPLD_DONE 		0x0004
+ 
+ // Available ranges
+-static const comedi_lrange range_daqboard2000_ai = { 13, {
++static const struct comedi_lrange range_daqboard2000_ai = { 13, {
+ 			RANGE(-10, 10),
+ 			RANGE(-5, 5),
+ 			RANGE(-2.5, 2.5),
+@@ -162,7 +162,7 @@ static const comedi_lrange range_daqboard2000_ai = { 13, {
+ 	}
+ };
+ 
+-static const comedi_lrange range_daqboard2000_ao = { 1, {
++static const struct comedi_lrange range_daqboard2000_ao = { 1, {
+ 			RANGE(-10, 10)
+ 	}
+ };
+diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
+index e8d8d67d513a..3cd44cc2fc67 100644
+--- a/drivers/staging/comedi/drivers/das08.c
++++ b/drivers/staging/comedi/drivers/das08.c
+@@ -171,7 +171,7 @@ static int das08ao_ao_winsn(struct comedi_device * dev, struct comedi_subdevice
+ static void i8254_set_mode_low(unsigned int base, int channel,
+ 	unsigned int mode);
+ 
+-static const comedi_lrange range_das08_pgl = { 9, {
++static const struct comedi_lrange range_das08_pgl = { 9, {
+ 			BIP_RANGE(10),
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(2.5),
+@@ -183,7 +183,7 @@ static const comedi_lrange range_das08_pgl = { 9, {
+ 			UNI_RANGE(1.25)
+ 	}
+ };
+-static const comedi_lrange range_das08_pgh = { 12, {
++static const struct comedi_lrange range_das08_pgh = { 12, {
+ 			BIP_RANGE(10),
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(1),
+@@ -198,7 +198,7 @@ static const comedi_lrange range_das08_pgh = { 12, {
+ 			UNI_RANGE(0.01),
+ 	}
+ };
+-static const comedi_lrange range_das08_pgm = { 9, {
++static const struct comedi_lrange range_das08_pgm = { 9, {
+ 			BIP_RANGE(10),
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(0.5),
+@@ -225,7 +225,7 @@ static const comedi_lrange range_das08_pgm = { 9, {
+ 
+ 				 */
+ 
+-static const comedi_lrange *const das08_ai_lranges[] = {
++static const struct comedi_lrange *const das08_ai_lranges[] = {
+ 	&range_unknown,
+ 	&range_bipolar5,
+ 	&range_das08_pgh,
+diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
+index a0998a2efd62..6c2b214dfefc 100644
+--- a/drivers/staging/comedi/drivers/das16.c
++++ b/drivers/staging/comedi/drivers/das16.c
+@@ -236,35 +236,35 @@ static const int sample_size = 2;	// size in bytes of a sample from board
+ #define   DAS1600_WS			0x02
+ #define   DAS1600_CLK_10MHZ		0x01
+ 
+-static const comedi_lrange range_das1x01_bip = { 4, {
++static const struct comedi_lrange range_das1x01_bip = { 4, {
+ 			BIP_RANGE(10),
+ 			BIP_RANGE(1),
+ 			BIP_RANGE(0.1),
+ 			BIP_RANGE(0.01),
+ 	}
+ };
+-static const comedi_lrange range_das1x01_unip = { 4, {
++static const struct comedi_lrange range_das1x01_unip = { 4, {
+ 			UNI_RANGE(10),
+ 			UNI_RANGE(1),
+ 			UNI_RANGE(0.1),
+ 			UNI_RANGE(0.01),
+ 	}
+ };
+-static const comedi_lrange range_das1x02_bip = { 4, {
++static const struct comedi_lrange range_das1x02_bip = { 4, {
+ 			BIP_RANGE(10),
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(2.5),
+ 			BIP_RANGE(1.25),
+ 	}
+ };
+-static const comedi_lrange range_das1x02_unip = { 4, {
++static const struct comedi_lrange range_das1x02_unip = { 4, {
+ 			UNI_RANGE(10),
+ 			UNI_RANGE(5),
+ 			UNI_RANGE(2.5),
+ 			UNI_RANGE(1.25),
+ 	}
+ };
+-static const comedi_lrange range_das16jr = { 9, {
++static const struct comedi_lrange range_das16jr = { 9, {
+ 			// also used by 16/330
+ 			BIP_RANGE(10),
+ 			BIP_RANGE(5),
+@@ -277,7 +277,7 @@ static const comedi_lrange range_das16jr = { 9, {
+ 			UNI_RANGE(1.25),
+ 	}
+ };
+-static const comedi_lrange range_das16jr_16 = { 8, {
++static const struct comedi_lrange range_das16jr_16 = { 8, {
+ 			BIP_RANGE(10),
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(2.5),
+@@ -306,14 +306,14 @@ static const int *const das16_gainlists[] = {
+ 	das1600_gainlist,
+ 	das1600_gainlist,
+ };
+-static const comedi_lrange *const das16_ai_uni_lranges[] = {
++static const struct comedi_lrange *const das16_ai_uni_lranges[] = {
+ 	&range_unknown,
+ 	&range_das16jr,
+ 	&range_das16jr_16,
+ 	&range_das1x01_unip,
+ 	&range_das1x02_unip,
+ };
+-static const comedi_lrange *const das16_ai_bip_lranges[] = {
++static const struct comedi_lrange *const das16_ai_bip_lranges[] = {
+ 	&range_unknown,
+ 	&range_das16jr,
+ 	&range_das16jr_16,
+@@ -732,8 +732,8 @@ struct das16_private_struct {
+ 	unsigned int current_buffer;
+ 	volatile unsigned int dma_transfer_size;	// target number of bytes to transfer per dma shot
+ 	// user-defined analog input and output ranges defined from config options
+-	comedi_lrange *user_ai_range_table;
+-	comedi_lrange *user_ao_range_table;
++	struct comedi_lrange *user_ai_range_table;
++	struct comedi_lrange *user_ao_range_table;
+ 
+ 	struct timer_list timer;	// for timed interrupt
+ 	volatile short timer_running;
+@@ -1496,7 +1496,7 @@ static int das16_attach(struct comedi_device * dev, comedi_devconfig * it)
+ 		(it->options[4] || it->options[5])) {
+ 		// allocate single-range range table
+ 		devpriv->user_ai_range_table =
+-			kmalloc(sizeof(comedi_lrange) + sizeof(comedi_krange),
++			kmalloc(sizeof(struct comedi_lrange) + sizeof(comedi_krange),
+ 			GFP_KERNEL);
+ 		// initialize ai range
+ 		devpriv->user_ai_range_table->length = 1;
+@@ -1509,7 +1509,7 @@ static int das16_attach(struct comedi_device * dev, comedi_devconfig * it)
+ 	if (it->options[6] || it->options[7]) {
+ 		// allocate single-range range table
+ 		devpriv->user_ao_range_table =
+-			kmalloc(sizeof(comedi_lrange) + sizeof(comedi_krange),
++			kmalloc(sizeof(struct comedi_lrange) + sizeof(comedi_krange),
+ 			GFP_KERNEL);
+ 		// initialize ao range
+ 		devpriv->user_ao_range_table->length = 1;
+diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
+index d87fd21a3bb6..eea48493756e 100644
+--- a/drivers/staging/comedi/drivers/das16m1.c
++++ b/drivers/staging/comedi/drivers/das16m1.c
+@@ -117,7 +117,7 @@ irq can be omitted, although the cmd interface will not work without it.
+ #define DAS16M1_82C55                  0x400
+ #define DAS16M1_8254_THIRD             0x404
+ 
+-static const comedi_lrange range_das16m1 = { 9,
++static const struct comedi_lrange range_das16m1 = { 9,
+ 	{
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(2.5),
+diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
+index 2bdb6a33dde4..2e066727fda3 100644
+--- a/drivers/staging/comedi/drivers/das1800.c
++++ b/drivers/staging/comedi/drivers/das1800.c
+@@ -213,7 +213,7 @@ static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode);
+ static unsigned int suggest_transfer_size(comedi_cmd * cmd);
+ 
+ // analog input ranges
+-static const comedi_lrange range_ai_das1801 = {
++static const struct comedi_lrange range_ai_das1801 = {
+ 	8,
+ 	{
+ 			RANGE(-5, 5),
+@@ -227,7 +227,7 @@ static const comedi_lrange range_ai_das1801 = {
+ 		}
+ };
+ 
+-static const comedi_lrange range_ai_das1802 = {
++static const struct comedi_lrange range_ai_das1802 = {
+ 	8,
+ 	{
+ 			RANGE(-10, 10),
+@@ -250,7 +250,7 @@ typedef struct das1800_board_struct {
+ 	int do_n_chan;		/* number of digital output channels */
+ 	int ao_ability;		/* 0 == no analog out, 1 == basic analog out, 2 == waveform analog out */
+ 	int ao_n_chan;		/* number of analog out channels */
+-	const comedi_lrange *range_ai;	/* available input ranges */
++	const struct comedi_lrange *range_ai;	/* available input ranges */
+ } das1800_board;
+ 
+ /* Warning: the maximum conversion speeds listed below are
+@@ -486,7 +486,7 @@ typedef struct {
+ #define devpriv ((das1800_private *)dev->private)
+ 
+ // analog out range for boards with basic analog out
+-static const comedi_lrange range_ao_1 = {
++static const struct comedi_lrange range_ao_1 = {
+ 	1,
+ 	{
+ 			RANGE(-10, 10),
+@@ -495,7 +495,7 @@ static const comedi_lrange range_ao_1 = {
+ 
+ // analog out range for 'ao' boards
+ /*
+-static const comedi_lrange range_ao_2 = {
++static const struct comedi_lrange range_ao_2 = {
+ 	2,
+ 	{
+ 		RANGE(-10, 10),
+diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
+index 83422936021f..6485e33fb520 100644
+--- a/drivers/staging/comedi/drivers/das800.c
++++ b/drivers/staging/comedi/drivers/das800.c
+@@ -109,19 +109,19 @@ cmd triggers supported:
+ typedef struct das800_board_struct {
+ 	const char *name;
+ 	int ai_speed;
+-	const comedi_lrange *ai_range;
++	const struct comedi_lrange *ai_range;
+ 	int resolution;
+ } das800_board;
+ 
+ //analog input ranges
+-static const comedi_lrange range_das800_ai = {
++static const struct comedi_lrange range_das800_ai = {
+ 	1,
+ 	{
+ 			RANGE(-5, 5),
+ 		}
+ };
+ 
+-static const comedi_lrange range_das801_ai = {
++static const struct comedi_lrange range_das801_ai = {
+ 	9,
+ 	{
+ 			RANGE(-5, 5),
+@@ -136,7 +136,7 @@ static const comedi_lrange range_das801_ai = {
+ 		}
+ };
+ 
+-static const comedi_lrange range_cio_das801_ai = {
++static const struct comedi_lrange range_cio_das801_ai = {
+ 	9,
+ 	{
+ 			RANGE(-5, 5),
+@@ -151,7 +151,7 @@ static const comedi_lrange range_cio_das801_ai = {
+ 		}
+ };
+ 
+-static const comedi_lrange range_das802_ai = {
++static const struct comedi_lrange range_das802_ai = {
+ 	9,
+ 	{
+ 			RANGE(-5, 5),
+@@ -166,7 +166,7 @@ static const comedi_lrange range_das802_ai = {
+ 		}
+ };
+ 
+-static const comedi_lrange range_das80216_ai = {
++static const struct comedi_lrange range_das80216_ai = {
+ 	8,
+ 	{
+ 			RANGE(-10, 10),
+diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
+index 68c18fff5369..17713b3934fe 100644
+--- a/drivers/staging/comedi/drivers/dmm32at.c
++++ b/drivers/staging/comedi/drivers/dmm32at.c
+@@ -164,7 +164,7 @@ Configuration Options:
+ #define DMM32AT_DIRCH 0x08
+ 
+ /* board AI ranges in comedi structure */
+-static const comedi_lrange dmm32at_airanges = {
++static const struct comedi_lrange dmm32at_airanges = {
+ 	4,
+ 	{
+ 			UNI_RANGE(10),
+@@ -185,7 +185,7 @@ static const unsigned char dmm32at_rangebits[] = {
+ /* only one of these ranges is valid, as set by a jumper on the
+  * board. The application should only use the range set by the jumper
+  */
+-static const comedi_lrange dmm32at_aoranges = {
++static const struct comedi_lrange dmm32at_aoranges = {
+ 	4,
+ 	{
+ 			UNI_RANGE(10),
+@@ -204,10 +204,10 @@ typedef struct dmm32at_board_struct {
+ 	const char *name;
+ 	int ai_chans;
+ 	int ai_bits;
+-	const comedi_lrange *ai_ranges;
++	const struct comedi_lrange *ai_ranges;
+ 	int ao_chans;
+ 	int ao_bits;
+-	const comedi_lrange *ao_ranges;
++	const struct comedi_lrange *ao_ranges;
+ 	int have_dio;
+ 	int dio_chans;
+ } dmm32at_board;
+diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c
+index 944489791da8..dc815c130be0 100644
+--- a/drivers/staging/comedi/drivers/dt2801.c
++++ b/drivers/staging/comedi/drivers/dt2801.c
+@@ -101,7 +101,7 @@ COMEDI_INITCLEANUP(driver_dt2801);
+ 
+ #if 0
+ // ignore 'defined but not used' warning
+-static const comedi_lrange range_dt2801_ai_pgh_bipolar = { 4, {
++static const struct comedi_lrange range_dt2801_ai_pgh_bipolar = { 4, {
+ 			RANGE(-10, 10),
+ 			RANGE(-5, 5),
+ 			RANGE(-2.5, 2.5),
+@@ -109,7 +109,7 @@ static const comedi_lrange range_dt2801_ai_pgh_bipolar = { 4, {
+ 	}
+ };
+ #endif
+-static const comedi_lrange range_dt2801_ai_pgl_bipolar = { 4, {
++static const struct comedi_lrange range_dt2801_ai_pgl_bipolar = { 4, {
+ 			RANGE(-10, 10),
+ 			RANGE(-1, 1),
+ 			RANGE(-0.1, 0.1),
+@@ -119,7 +119,7 @@ static const comedi_lrange range_dt2801_ai_pgl_bipolar = { 4, {
+ 
+ #if 0
+ // ignore 'defined but not used' warning
+-static const comedi_lrange range_dt2801_ai_pgh_unipolar = { 4, {
++static const struct comedi_lrange range_dt2801_ai_pgh_unipolar = { 4, {
+ 			RANGE(0, 10),
+ 			RANGE(0, 5),
+ 			RANGE(0, 2.5),
+@@ -127,7 +127,7 @@ static const comedi_lrange range_dt2801_ai_pgh_unipolar = { 4, {
+ 	}
+ };
+ #endif
+-static const comedi_lrange range_dt2801_ai_pgl_unipolar = { 4, {
++static const struct comedi_lrange range_dt2801_ai_pgl_unipolar = { 4, {
+ 			RANGE(0, 10),
+ 			RANGE(0, 1),
+ 			RANGE(0, 0.1),
+@@ -219,7 +219,7 @@ static const boardtype_t boardtypes[] = {
+ #define boardtype (*(const boardtype_t *)dev->board_ptr)
+ 
+ typedef struct {
+-	const comedi_lrange *dac_range_types[2];
++	const struct comedi_lrange *dac_range_types[2];
+ 	unsigned int ao_readback[2];
+ } dt2801_private;
+ #define devpriv ((dt2801_private *)dev->private)
+@@ -439,7 +439,7 @@ static int probe_number_of_ai_chans(struct comedi_device * dev)
+ 	return n_chans;
+ }
+ 
+-static const comedi_lrange *dac_range_table[] = {
++static const struct comedi_lrange *dac_range_table[] = {
+ 	&range_bipolar10,
+ 	&range_bipolar5,
+ 	&range_bipolar2_5,
+@@ -447,14 +447,14 @@ static const comedi_lrange *dac_range_table[] = {
+ 	&range_unipolar5
+ };
+ 
+-static const comedi_lrange *dac_range_lkup(int opt)
++static const struct comedi_lrange *dac_range_lkup(int opt)
+ {
+ 	if (opt < 0 || opt > 5)
+ 		return &range_unknown;
+ 	return dac_range_table[opt];
+ }
+ 
+-static const comedi_lrange *ai_range_lkup(int type, int opt)
++static const struct comedi_lrange *ai_range_lkup(int type, int opt)
+ {
+ 	switch (type) {
+ 	case 0:
+diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c
+index 8190ae15878a..70d7bcf36820 100644
+--- a/drivers/staging/comedi/drivers/dt2811.c
++++ b/drivers/staging/comedi/drivers/dt2811.c
+@@ -51,42 +51,42 @@ Configuration options:
+ 
+ static const char *driver_name = "dt2811";
+ 
+-static const comedi_lrange range_dt2811_pgh_ai_5_unipolar = { 4, {
++static const struct comedi_lrange range_dt2811_pgh_ai_5_unipolar = { 4, {
+ 			RANGE(0, 5),
+ 			RANGE(0, 2.5),
+ 			RANGE(0, 1.25),
+ 			RANGE(0, 0.625)
+ 	}
+ };
+-static const comedi_lrange range_dt2811_pgh_ai_2_5_bipolar = { 4, {
++static const struct comedi_lrange range_dt2811_pgh_ai_2_5_bipolar = { 4, {
+ 			RANGE(-2.5, 2.5),
+ 			RANGE(-1.25, 1.25),
+ 			RANGE(-0.625, 0.625),
+ 			RANGE(-0.3125, 0.3125)
+ 	}
+ };
+-static const comedi_lrange range_dt2811_pgh_ai_5_bipolar = { 4, {
++static const struct comedi_lrange range_dt2811_pgh_ai_5_bipolar = { 4, {
+ 			RANGE(-5, 5),
+ 			RANGE(-2.5, 2.5),
+ 			RANGE(-1.25, 1.25),
+ 			RANGE(-0.625, 0.625)
+ 	}
+ };
+-static const comedi_lrange range_dt2811_pgl_ai_5_unipolar = { 4, {
++static const struct comedi_lrange range_dt2811_pgl_ai_5_unipolar = { 4, {
+ 			RANGE(0, 5),
+ 			RANGE(0, 0.5),
+ 			RANGE(0, 0.05),
+ 			RANGE(0, 0.01)
+ 	}
+ };
+-static const comedi_lrange range_dt2811_pgl_ai_2_5_bipolar = { 4, {
++static const struct comedi_lrange range_dt2811_pgl_ai_2_5_bipolar = { 4, {
+ 			RANGE(-2.5, 2.5),
+ 			RANGE(-0.25, 0.25),
+ 			RANGE(-0.025, 0.025),
+ 			RANGE(-0.005, 0.005)
+ 	}
+ };
+-static const comedi_lrange range_dt2811_pgl_ai_5_bipolar = { 4, {
++static const struct comedi_lrange range_dt2811_pgl_ai_5_bipolar = { 4, {
+ 			RANGE(-5, 5),
+ 			RANGE(-0.5, 0.5),
+ 			RANGE(-0.05, 0.05),
+@@ -193,9 +193,9 @@ static const comedi_lrange range_dt2811_pgl_ai_5_bipolar = { 4, {
+ 
+ typedef struct {
+ 	const char *name;
+-	const comedi_lrange *bip_5;
+-	const comedi_lrange *bip_2_5;
+-	const comedi_lrange *unip_5;
++	const struct comedi_lrange *bip_5;
++	const struct comedi_lrange *bip_2_5;
++	const struct comedi_lrange *unip_5;
+ } boardtype;
+ static const boardtype boardtypes[] = {
+ 	{"dt2811-pgh",
+@@ -247,13 +247,13 @@ typedef struct {
+ 	enum {
+ 		dac_bipolar_5, dac_bipolar_2_5, dac_unipolar_5
+ 	} dac_range[2];
+-	const comedi_lrange *range_type_list[2];
++	const struct comedi_lrange *range_type_list[2];
+ 	unsigned int ao_readback[2];
+ } dt2811_private;
+ 
+ #define devpriv ((dt2811_private *)dev->private)
+ 
+-static const comedi_lrange *dac_range_types[] = {
++static const struct comedi_lrange *dac_range_types[] = {
+ 	&range_bipolar5,
+ 	&range_bipolar2_5,
+ 	&range_unipolar5
+diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c
+index 0f45cadca370..ffd75c7b9263 100644
+--- a/drivers/staging/comedi/drivers/dt2815.c
++++ b/drivers/staging/comedi/drivers/dt2815.c
+@@ -61,11 +61,11 @@ Configuration options:
+ #include 
+ #include 
+ 
+-static const comedi_lrange range_dt2815_ao_32_current = { 1, {
++static const struct comedi_lrange range_dt2815_ao_32_current = { 1, {
+ 			RANGE_mA(0, 32)
+ 	}
+ };
+-static const comedi_lrange range_dt2815_ao_20_current = { 1, {
++static const struct comedi_lrange range_dt2815_ao_20_current = { 1, {
+ 			RANGE_mA(4, 20)
+ 	}
+ };
+@@ -89,7 +89,7 @@ COMEDI_INITCLEANUP(driver_dt2815);
+ static void dt2815_free_resources(struct comedi_device * dev);
+ 
+ typedef struct {
+-	const comedi_lrange *range_type_list[8];
++	const struct comedi_lrange *range_type_list[8];
+ 	unsigned int ao_readback[8];
+ } dt2815_private;
+ 
+@@ -181,7 +181,7 @@ static int dt2815_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	struct comedi_subdevice *s;
+ 	int i;
+-	const comedi_lrange *current_range_type, *voltage_range_type;
++	const struct comedi_lrange *current_range_type, *voltage_range_type;
+ 	unsigned long iobase;
+ 
+ 	iobase = it->options[0];
+diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
+index bed21029871b..9e8d1bc45d59 100644
+--- a/drivers/staging/comedi/drivers/dt282x.c
++++ b/drivers/staging/comedi/drivers/dt282x.c
+@@ -154,42 +154,42 @@ Configuration options:
+ #define DT2821_XCLK	0x0002	/* (R/W) external clock enable            */
+ #define DT2821_BDINIT	0x0001	/* (W)   initialize board         */
+ 
+-static const comedi_lrange range_dt282x_ai_lo_bipolar = { 4, {
++static const struct comedi_lrange range_dt282x_ai_lo_bipolar = { 4, {
+ 			RANGE(-10, 10),
+ 			RANGE(-5, 5),
+ 			RANGE(-2.5, 2.5),
+ 			RANGE(-1.25, 1.25)
+ 	}
+ };
+-static const comedi_lrange range_dt282x_ai_lo_unipolar = { 4, {
++static const struct comedi_lrange range_dt282x_ai_lo_unipolar = { 4, {
+ 			RANGE(0, 10),
+ 			RANGE(0, 5),
+ 			RANGE(0, 2.5),
+ 			RANGE(0, 1.25)
+ 	}
+ };
+-static const comedi_lrange range_dt282x_ai_5_bipolar = { 4, {
++static const struct comedi_lrange range_dt282x_ai_5_bipolar = { 4, {
+ 			RANGE(-5, 5),
+ 			RANGE(-2.5, 2.5),
+ 			RANGE(-1.25, 1.25),
+ 			RANGE(-0.625, 0.625),
+ 	}
+ };
+-static const comedi_lrange range_dt282x_ai_5_unipolar = { 4, {
++static const struct comedi_lrange range_dt282x_ai_5_unipolar = { 4, {
+ 			RANGE(0, 5),
+ 			RANGE(0, 2.5),
+ 			RANGE(0, 1.25),
+ 			RANGE(0, 0.625),
+ 	}
+ };
+-static const comedi_lrange range_dt282x_ai_hi_bipolar = { 4, {
++static const struct comedi_lrange range_dt282x_ai_hi_bipolar = { 4, {
+ 			RANGE(-10, 10),
+ 			RANGE(-1, 1),
+ 			RANGE(-0.1, 0.1),
+ 			RANGE(-0.02, 0.02)
+ 	}
+ };
+-static const comedi_lrange range_dt282x_ai_hi_unipolar = { 4, {
++static const struct comedi_lrange range_dt282x_ai_hi_unipolar = { 4, {
+ 			RANGE(0, 10),
+ 			RANGE(0, 1),
+ 			RANGE(0, 0.1),
+@@ -345,7 +345,7 @@ typedef struct {
+ 	int da0_2scomp;		/* same, for DAC0               */
+ 	int da1_2scomp;		/* same, for DAC1               */
+ 
+-	const comedi_lrange *darangelist[2];
++	const struct comedi_lrange *darangelist[2];
+ 
+ 	short ao[2];
+ 
+@@ -1184,17 +1184,17 @@ static int dt282x_dio_insn_config(struct comedi_device * dev, struct comedi_subd
+ 	return 1;
+ }
+ 
+-static const comedi_lrange *const ai_range_table[] = {
++static const struct comedi_lrange *const ai_range_table[] = {
+ 	&range_dt282x_ai_lo_bipolar,
+ 	&range_dt282x_ai_lo_unipolar,
+ 	&range_dt282x_ai_5_bipolar,
+ 	&range_dt282x_ai_5_unipolar
+ };
+-static const comedi_lrange *const ai_range_pgl_table[] = {
++static const struct comedi_lrange *const ai_range_pgl_table[] = {
+ 	&range_dt282x_ai_hi_bipolar,
+ 	&range_dt282x_ai_hi_unipolar
+ };
+-static const comedi_lrange *opt_ai_range_lkup(int ispgl, int x)
++static const struct comedi_lrange *opt_ai_range_lkup(int ispgl, int x)
+ {
+ 	if (ispgl) {
+ 		if (x < 0 || x >= 2)
+@@ -1206,14 +1206,14 @@ static const comedi_lrange *opt_ai_range_lkup(int ispgl, int x)
+ 		return ai_range_table[x];
+ 	}
+ }
+-static const comedi_lrange *const ao_range_table[] = {
++static const struct comedi_lrange *const ao_range_table[] = {
+ 	&range_bipolar10,
+ 	&range_unipolar10,
+ 	&range_bipolar5,
+ 	&range_unipolar5,
+ 	&range_bipolar2_5
+ };
+-static const comedi_lrange *opt_ao_range_lkup(int x)
++static const struct comedi_lrange *opt_ao_range_lkup(int x)
+ {
+ 	if (x < 0 || x >= 5)
+ 		x = 0;
+diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
+index 0e29d7f8c71c..60763e51435a 100644
+--- a/drivers/staging/comedi/drivers/dt3000.c
++++ b/drivers/staging/comedi/drivers/dt3000.c
+@@ -66,14 +66,14 @@ AO commands are not supported.
+ 
+ #define PCI_VENDOR_ID_DT	0x1116
+ 
+-static const comedi_lrange range_dt3000_ai = { 4, {
++static const struct comedi_lrange range_dt3000_ai = { 4, {
+ 			RANGE(-10, 10),
+ 			RANGE(-5, 5),
+ 			RANGE(-2.5, 2.5),
+ 			RANGE(-1.25, 1.25)
+ 	}
+ };
+-static const comedi_lrange range_dt3000_ai_pgl = { 4, {
++static const struct comedi_lrange range_dt3000_ai_pgl = { 4, {
+ 			RANGE(-10, 10),
+ 			RANGE(-1, 1),
+ 			RANGE(-0.1, 0.1),
+@@ -87,7 +87,7 @@ typedef struct {
+ 	int adchan;
+ 	int adbits;
+ 	int ai_speed;
+-	const comedi_lrange *adrange;
++	const struct comedi_lrange *adrange;
+ 	int dachan;
+ 	int dabits;
+ } dt3k_boardtype;
+diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c
+index e304a614a97e..a3d4afc60421 100644
+--- a/drivers/staging/comedi/drivers/dt9812.c
++++ b/drivers/staging/comedi/drivers/dt9812.c
+@@ -300,22 +300,22 @@ struct slot_dt9812 {
+ 	struct comedi_dt9812 *comedi;
+ };
+ 
+-static const comedi_lrange dt9812_10_ain_range = { 1, {
++static const struct comedi_lrange dt9812_10_ain_range = { 1, {
+ 			BIP_RANGE(10),
+ 	}
+ };
+ 
+-static const comedi_lrange dt9812_2pt5_ain_range = { 1, {
++static const struct comedi_lrange dt9812_2pt5_ain_range = { 1, {
+ 			UNI_RANGE(2.5),
+ 	}
+ };
+ 
+-static const comedi_lrange dt9812_10_aout_range = { 1, {
++static const struct comedi_lrange dt9812_10_aout_range = { 1, {
+ 			BIP_RANGE(10),
+ 	}
+ };
+ 
+-static const comedi_lrange dt9812_2pt5_aout_range = { 1, {
++static const struct comedi_lrange dt9812_2pt5_aout_range = { 1, {
+ 			UNI_RANGE(2.5),
+ 	}
+ };
+diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c
+index a2f4db9aa4ad..8b1e6c896517 100644
+--- a/drivers/staging/comedi/drivers/fl512.c
++++ b/drivers/staging/comedi/drivers/fl512.c
+@@ -29,7 +29,7 @@ typedef struct {
+ } fl512_private;
+ #define devpriv ((fl512_private *) dev->private)
+ 
+-static const comedi_lrange range_fl512 = { 4, {
++static const struct comedi_lrange range_fl512 = { 4, {
+ 			BIP_RANGE(0.5),
+ 			BIP_RANGE(1),
+ 			BIP_RANGE(5),
+diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
+index b30318172b28..7b10bc48a5ec 100644
+--- a/drivers/staging/comedi/drivers/icp_multi.c
++++ b/drivers/staging/comedi/drivers/icp_multi.c
+@@ -108,7 +108,7 @@ There are 4 x 12-bit Analogue Outputs.  Ranges : 5V, 10V, +/-5V, +/-10V
+ #define	Status_IRQ	0x00ff	/*  All interrupts */
+ 
+ /*  Define analogue range */
+-static const comedi_lrange range_analog = { 4, {
++static const struct comedi_lrange range_analog = { 4, {
+ 			UNI_RANGE(5),
+ 			UNI_RANGE(10),
+ 			BIP_RANGE(5),
+@@ -147,9 +147,9 @@ struct boardtype {
+ 	int n_ctrs;		/*  num of counters */
+ 	int ai_maxdata;		/*  resolution of A/D */
+ 	int ao_maxdata;		/*  resolution of D/A */
+-	const comedi_lrange *rangelist_ai;	/*  rangelist for A/D */
++	const struct comedi_lrange *rangelist_ai;	/*  rangelist for A/D */
+ 	const char *rangecode;	/*  range codes for programming */
+-	const comedi_lrange *rangelist_ao;	/*  rangelist for D/A */
++	const struct comedi_lrange *rangelist_ao;	/*  rangelist for D/A */
+ };
+ 
+ static const struct boardtype boardtypes[] = {
+diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c
+index e1376a173f33..ab62af50993b 100644
+--- a/drivers/staging/comedi/drivers/ii_pci20kc.c
++++ b/drivers/staging/comedi/drivers/ii_pci20kc.c
+@@ -137,7 +137,7 @@ typedef union {
+ 	void *iobase;
+ 	struct {
+ 		void *iobase;
+-		const comedi_lrange *ao_range_list[2];	/* range of channels of ao module */
++		const struct comedi_lrange *ao_range_list[2];	/* range of channels of ao module */
+ 		unsigned int last_data[2];
+ 	} pci20006;
+ 	struct {
+@@ -275,7 +275,7 @@ static int pci20006_insn_read(struct comedi_device * dev, struct comedi_subdevic
+ static int pci20006_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static const comedi_lrange *pci20006_range_list[] = {
++static const struct comedi_lrange *pci20006_range_list[] = {
+ 	&range_bipolar10,
+ 	&range_unipolar10,
+ 	&range_bipolar5,
+@@ -355,11 +355,11 @@ static int pci20341_insn_read(struct comedi_device * dev, struct comedi_subdevic
+ static const int pci20341_timebase[] = { 0x00, 0x00, 0x00, 0x04 };
+ static const int pci20341_settling_time[] = { 0x58, 0x58, 0x93, 0x99 };
+ 
+-static const comedi_lrange range_bipolar0_5 = { 1, {BIP_RANGE(0.5)} };
+-static const comedi_lrange range_bipolar0_05 = { 1, {BIP_RANGE(0.05)} };
+-static const comedi_lrange range_bipolar0_025 = { 1, {BIP_RANGE(0.025)} };
++static const struct comedi_lrange range_bipolar0_5 = { 1, {BIP_RANGE(0.5)} };
++static const struct comedi_lrange range_bipolar0_05 = { 1, {BIP_RANGE(0.05)} };
++static const struct comedi_lrange range_bipolar0_025 = { 1, {BIP_RANGE(0.025)} };
+ 
+-static const comedi_lrange *const pci20341_ranges[] = {
++static const struct comedi_lrange *const pci20341_ranges[] = {
+ 	&range_bipolar5,
+ 	&range_bipolar0_5,
+ 	&range_bipolar0_05,
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
+index f256b9981c32..1f993147ad91 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -158,7 +158,7 @@ typedef struct {
+ 		int length;
+ 		comedi_krange range;
+ 	} range[9];
+-	const comedi_lrange *range_table_list[8 * 7 + 2];
++	const struct comedi_lrange *range_table_list[8 * 7 + 2];
+ 	unsigned int maxdata_list[8 * 7 + 2];
+ 	u16 errors;
+ 	int retries;
+@@ -877,7 +877,7 @@ static int jr3_pci_attach(struct comedi_device * dev, comedi_devconfig * it)
+ 				p->range[j].range.max = 1000000;
+ 				for (k = 0; k < 7; k++) {
+ 					p->range_table_list[j + k * 8] =
+-						(comedi_lrange *) & p->range[j];
++						(struct comedi_lrange *) & p->range[j];
+ 					p->maxdata_list[j + k * 8] = 0x7fff;
+ 				}
+ 			}
+@@ -886,9 +886,9 @@ static int jr3_pci_attach(struct comedi_device * dev, comedi_devconfig * it)
+ 			p->range[8].range.max = 65536;
+ 
+ 			p->range_table_list[56] =
+-				(comedi_lrange *) & p->range[8];
++				(struct comedi_lrange *) & p->range[8];
+ 			p->range_table_list[57] =
+-				(comedi_lrange *) & p->range[8];
++				(struct comedi_lrange *) & p->range[8];
+ 			p->maxdata_list[56] = 0xffff;
+ 			p->maxdata_list[57] = 0xffff;
+ 			// Channel specific range and maxdata
+diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
+index 095da3f1315d..16a34111fe1d 100644
+--- a/drivers/staging/comedi/drivers/me4000.c
++++ b/drivers/staging/comedi/drivers/me4000.c
+@@ -230,7 +230,7 @@ static inline unsigned char me4000_inb(struct comedi_device *dev, unsigned long
+ 	return value;
+ }
+ 
+-static const comedi_lrange me4000_ai_range = {
++static const struct comedi_lrange me4000_ai_range = {
+ 	4,
+ 	{
+ 			UNI_RANGE(2.5),
+@@ -240,7 +240,7 @@ static const comedi_lrange me4000_ai_range = {
+ 		}
+ };
+ 
+-static const comedi_lrange me4000_ao_range = {
++static const struct comedi_lrange me4000_ao_range = {
+ 	1,
+ 	{
+ 			BIP_RANGE(10),
+diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c
+index e47a954f189e..a87c8ddf8945 100644
+--- a/drivers/staging/comedi/drivers/me_daq.c
++++ b/drivers/staging/comedi/drivers/me_daq.c
+@@ -147,7 +147,7 @@ from http://www.comedi.org
+ static int me_attach(struct comedi_device *dev, comedi_devconfig *it);
+ static int me_detach(struct comedi_device *dev);
+ 
+-static const comedi_lrange me2000_ai_range = {
++static const struct comedi_lrange me2000_ai_range = {
+ 	8,
+ 	{
+ 		BIP_RANGE(10),
+@@ -161,7 +161,7 @@ static const comedi_lrange me2000_ai_range = {
+ 	}
+ };
+ 
+-static const comedi_lrange me2600_ai_range = {
++static const struct comedi_lrange me2600_ai_range = {
+ 	8,
+ 	{
+ 			BIP_RANGE(10),
+@@ -175,7 +175,7 @@ static const comedi_lrange me2600_ai_range = {
+ 		}
+ };
+ 
+-static const comedi_lrange me2600_ao_range = {
++static const struct comedi_lrange me2600_ao_range = {
+ 	3,
+ 	{
+ 			BIP_RANGE(10),
+@@ -201,11 +201,11 @@ struct me_board {
+ 	int ao_channel_nbr;	/* DA config */
+ 	int ao_resolution;
+ 	int ao_resolution_mask;
+-	const comedi_lrange *ao_range_list;
++	const struct comedi_lrange *ao_range_list;
+ 	int ai_channel_nbr;	/* AD config */
+ 	int ai_resolution;
+ 	int ai_resolution_mask;
+-	const comedi_lrange *ai_range_list;
++	const struct comedi_lrange *ai_range_list;
+ 	int dio_channel_nbr;	/* DIO config */
+ };
+ 
+diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c
+index 9b9c8c038dbd..59c3c17b616c 100644
+--- a/drivers/staging/comedi/drivers/mpc624.c
++++ b/drivers/staging/comedi/drivers/mpc624.c
+@@ -126,7 +126,7 @@ typedef struct {
+ 
+ #define devpriv ((skel_private *)dev->private)
+ //----------------------------------------------------------------------------
+-static const comedi_lrange range_mpc624_bipolar1 = {
++static const struct comedi_lrange range_mpc624_bipolar1 = {
+ 	1,
+ 	{
+ //    BIP_RANGE(1.01) // this is correct,
+@@ -134,7 +134,7 @@ static const comedi_lrange range_mpc624_bipolar1 = {
+ 			BIP_RANGE(2.02)
+ 		}
+ };
+-static const comedi_lrange range_mpc624_bipolar10 = {
++static const struct comedi_lrange range_mpc624_bipolar10 = {
+ 	1,
+ 	{
+ //    BIP_RANGE(10.1) // this is correct,
+diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
+index 7dbbfdcb1973..e66bde6dbf21 100644
+--- a/drivers/staging/comedi/drivers/ni_670x.c
++++ b/drivers/staging/comedi/drivers/ni_670x.c
+@@ -120,7 +120,7 @@ static struct comedi_driver driver_ni_670x = {
+ 
+ COMEDI_PCI_INITCLEANUP(driver_ni_670x, ni_670x_pci_table);
+ 
+-static comedi_lrange range_0_20mA = { 1, {RANGE_mA(0, 20)} };
++static struct comedi_lrange range_0_20mA = { 1, {RANGE_mA(0, 20)} };
+ 
+ static int ni_670x_find_device(struct comedi_device * dev, int bus, int slot);
+ 
+@@ -167,9 +167,9 @@ static int ni_670x_attach(struct comedi_device * dev, comedi_devconfig * it)
+ 	s->n_chan = thisboard->ao_chans;
+ 	s->maxdata = 0xffff;
+ 	if (s->n_chan == 32) {
+-		const comedi_lrange **range_table_list;
++		const struct comedi_lrange **range_table_list;
+ 
+-		range_table_list = kmalloc(sizeof(comedi_lrange *) * 32,
++		range_table_list = kmalloc(sizeof(struct comedi_lrange *) * 32,
+ 			GFP_KERNEL);
+ 		if (!range_table_list)
+ 			return -ENOMEM;
+diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
+index 87edc61f6a4e..2a3032bbcced 100644
+--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
++++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
+@@ -127,7 +127,7 @@ typedef struct a2150_board_struct {
+ } a2150_board;
+ 
+ //analog input range
+-static const comedi_lrange range_a2150 = {
++static const struct comedi_lrange range_a2150 = {
+ 	1,
+ 	{
+ 			RANGE(-2.828, 2.828),
+diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
+index 592922aad85c..4cbe558a9f04 100644
+--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
++++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
+@@ -147,7 +147,7 @@ static struct comedi_driver driver_atmio16d = {
+ COMEDI_INITCLEANUP(driver_atmio16d);
+ 
+ /* range structs */
+-static const comedi_lrange range_atmio16d_ai_10_bipolar = { 4, {
++static const struct comedi_lrange range_atmio16d_ai_10_bipolar = { 4, {
+ 			BIP_RANGE(10),
+ 			BIP_RANGE(1),
+ 			BIP_RANGE(0.1),
+@@ -155,7 +155,7 @@ static const comedi_lrange range_atmio16d_ai_10_bipolar = { 4, {
+ 	}
+ };
+ 
+-static const comedi_lrange range_atmio16d_ai_5_bipolar = { 4, {
++static const struct comedi_lrange range_atmio16d_ai_5_bipolar = { 4, {
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(0.5),
+ 			BIP_RANGE(0.05),
+@@ -163,7 +163,7 @@ static const comedi_lrange range_atmio16d_ai_5_bipolar = { 4, {
+ 	}
+ };
+ 
+-static const comedi_lrange range_atmio16d_ai_unipolar = { 4, {
++static const struct comedi_lrange range_atmio16d_ai_unipolar = { 4, {
+ 			UNI_RANGE(10),
+ 			UNI_RANGE(1),
+ 			UNI_RANGE(0.1),
+@@ -179,7 +179,7 @@ typedef struct {
+ 	enum { dac_bipolar, dac_unipolar } dac0_range, dac1_range;
+ 	enum { dac_internal, dac_external } dac0_reference, dac1_reference;
+ 	enum { dac_2comp, dac_straight } dac0_coding, dac1_coding;
+-	const comedi_lrange *ao_range_type_list[2];
++	const struct comedi_lrange *ao_range_type_list[2];
+ 	unsigned int ao_readback[2];
+ 	unsigned int com_reg_1_state;	/* current state of command register 1 */
+ 	unsigned int com_reg_2_state;	/* current state of command register 2 */
+diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
+index e1326a35e78c..f1a284e6358c 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc.c
++++ b/drivers/staging/comedi/drivers/ni_labpc.c
+@@ -253,7 +253,7 @@ static const int labpc_plus_ai_gain_bits[NUM_LABPC_PLUS_AI_RANGES] = {
+ 	0x60,
+ 	0x70,
+ };
+-static const comedi_lrange range_labpc_plus_ai = {
++static const struct comedi_lrange range_labpc_plus_ai = {
+ 	NUM_LABPC_PLUS_AI_RANGES,
+ 	{
+ 			BIP_RANGE(5),
+@@ -311,7 +311,7 @@ const int labpc_1200_ai_gain_bits[NUM_LABPC_1200_AI_RANGES] = {
+ 	0x60,
+ 	0x70,
+ };
+-const comedi_lrange range_labpc_1200_ai = {
++const struct comedi_lrange range_labpc_1200_ai = {
+ 	NUM_LABPC_1200_AI_RANGES,
+ 	{
+ 			BIP_RANGE(5),
+@@ -333,7 +333,7 @@ const comedi_lrange range_labpc_1200_ai = {
+ 
+ //analog output ranges
+ #define AO_RANGE_IS_UNIPOLAR 0x1
+-static const comedi_lrange range_labpc_ao = {
++static const struct comedi_lrange range_labpc_ao = {
+ 	2,
+ 	{
+ 			BIP_RANGE(5),
+diff --git a/drivers/staging/comedi/drivers/ni_labpc.h b/drivers/staging/comedi/drivers/ni_labpc.h
+index d80f05eae52f..b44b0d3d02f1 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc.h
++++ b/drivers/staging/comedi/drivers/ni_labpc.h
+@@ -39,7 +39,7 @@ typedef struct labpc_board_struct {
+ 	enum labpc_bustype bustype;	// ISA/PCI/etc.
+ 	enum labpc_register_layout register_layout;	// 1200 has extra registers compared to pc+
+ 	int has_ao;		// has analog output true/false
+-	const comedi_lrange *ai_range_table;
++	const struct comedi_lrange *ai_range_table;
+ 	const int *ai_range_code;
+ 	const int *ai_range_is_unipolar;
+ 	unsigned ai_scan_up:1;	// board can auto scan up in ai channels, not just down
+@@ -80,6 +80,6 @@ int labpc_common_detach(struct comedi_device * dev);
+ 
+ extern const int labpc_1200_is_unipolar[];
+ extern const int labpc_1200_ai_gain_bits[];
+-extern const comedi_lrange range_labpc_1200_ai;
++extern const struct comedi_lrange range_labpc_1200_ai;
+ 
+ #endif /* _NI_LABPC_H */
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index 8f3c959f6265..eaa141daafae 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -88,7 +88,7 @@ static const short ni_gainlkup[][16] = {
+ 	[ai_gain_6143] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ };
+ 
+-static const comedi_lrange range_ni_E_ai = { 16, {
++static const struct comedi_lrange range_ni_E_ai = { 16, {
+ 			RANGE(-10, 10),
+ 			RANGE(-5, 5),
+ 			RANGE(-2.5, 2.5),
+@@ -107,7 +107,7 @@ static const comedi_lrange range_ni_E_ai = { 16, {
+ 			RANGE(0, 0.1),
+ 	}
+ };
+-static const comedi_lrange range_ni_E_ai_limited = { 8, {
++static const struct comedi_lrange range_ni_E_ai_limited = { 8, {
+ 			RANGE(-10, 10),
+ 			RANGE(-5, 5),
+ 			RANGE(-1, 1),
+@@ -118,7 +118,7 @@ static const comedi_lrange range_ni_E_ai_limited = { 8, {
+ 			RANGE(0, 0.1),
+ 	}
+ };
+-static const comedi_lrange range_ni_E_ai_limited14 = { 14, {
++static const struct comedi_lrange range_ni_E_ai_limited14 = { 14, {
+ 			RANGE(-10, 10),
+ 			RANGE(-5, 5),
+ 			RANGE(-2, 2),
+@@ -135,14 +135,14 @@ static const comedi_lrange range_ni_E_ai_limited14 = { 14, {
+ 			RANGE(0, 0.1),
+ 	}
+ };
+-static const comedi_lrange range_ni_E_ai_bipolar4 = { 4, {
++static const struct comedi_lrange range_ni_E_ai_bipolar4 = { 4, {
+ 			RANGE(-10, 10),
+ 			RANGE(-5, 5),
+ 			RANGE(-0.5, 0.5),
+ 			RANGE(-0.05, 0.05),
+ 	}
+ };
+-static const comedi_lrange range_ni_E_ai_611x = { 8, {
++static const struct comedi_lrange range_ni_E_ai_611x = { 8, {
+ 			RANGE(-50, 50),
+ 			RANGE(-20, 20),
+ 			RANGE(-10, 10),
+@@ -153,14 +153,14 @@ static const comedi_lrange range_ni_E_ai_611x = { 8, {
+ 			RANGE(-0.2, 0.2),
+ 	}
+ };
+-static const comedi_lrange range_ni_M_ai_622x = { 4, {
++static const struct comedi_lrange range_ni_M_ai_622x = { 4, {
+ 			RANGE(-10, 10),
+ 			RANGE(-5, 5),
+ 			RANGE(-1, 1),
+ 			RANGE(-0.2, 0.2),
+ 	}
+ };
+-static const comedi_lrange range_ni_M_ai_628x = { 7, {
++static const struct comedi_lrange range_ni_M_ai_628x = { 7, {
+ 			RANGE(-10, 10),
+ 			RANGE(-5, 5),
+ 			RANGE(-2, 2),
+@@ -170,11 +170,11 @@ static const comedi_lrange range_ni_M_ai_628x = { 7, {
+ 			RANGE(-0.1, 0.1),
+ 	}
+ };
+-static const comedi_lrange range_ni_S_ai_6143 = { 1, {
++static const struct comedi_lrange range_ni_S_ai_6143 = { 1, {
+ 			RANGE(-5, +5),
+ 	}
+ };
+-static const comedi_lrange range_ni_E_ao_ext = { 4, {
++static const struct comedi_lrange range_ni_E_ao_ext = { 4, {
+ 			RANGE(-10, 10),
+ 			RANGE(0, 10),
+ 			RANGE_ext(-1, 1),
+@@ -182,7 +182,7 @@ static const comedi_lrange range_ni_E_ao_ext = { 4, {
+ 	}
+ };
+ 
+-static const comedi_lrange *const ni_range_lkup[] = {
++static const struct comedi_lrange *const ni_range_lkup[] = {
+ 	[ai_gain_16] = &range_ni_E_ai,
+ 	[ai_gain_8] = &range_ni_E_ai_limited,
+ 	[ai_gain_14] = &range_ni_E_ai_limited14,
+diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
+index 173d0a57245a..f67fa6dec22a 100644
+--- a/drivers/staging/comedi/drivers/ni_pcimio.c
++++ b/drivers/staging/comedi/drivers/ni_pcimio.c
+@@ -193,7 +193,7 @@ MODULE_DEVICE_TABLE(pci, ni_pci_table);
+  63 different possibilities.  An AO channel
+  can not act as it's own OFFSET or REFERENCE.
+ */
+-static const comedi_lrange range_ni_M_628x_ao = { 8, {
++static const struct comedi_lrange range_ni_M_628x_ao = { 8, {
+ 			RANGE(-10, 10),
+ 			RANGE(-5, 5),
+ 			RANGE(-2, 2),
+@@ -205,13 +205,13 @@ static const comedi_lrange range_ni_M_628x_ao = { 8, {
+ 			RANGE_ext(-1, 1)
+ 	}
+ };
+-static const comedi_lrange range_ni_M_625x_ao = { 3, {
++static const struct comedi_lrange range_ni_M_625x_ao = { 3, {
+ 			RANGE(-10, 10),
+ 			RANGE(-5, 5),
+ 			RANGE_ext(-1, 1)
+ 	}
+ };
+-static const comedi_lrange range_ni_M_622x_ao = { 1, {
++static const struct comedi_lrange range_ni_M_622x_ao = { 1, {
+ 			RANGE(-10, 10),
+ 	}
+ };
+diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h
+index 2c0929147585..1ebf521ab773 100644
+--- a/drivers/staging/comedi/drivers/ni_stc.h
++++ b/drivers/staging/comedi/drivers/ni_stc.h
+@@ -917,7 +917,7 @@ enum ni_reg_type {
+ 	ni_reg_6143 = 0x20
+ };
+ 
+-static const comedi_lrange range_ni_E_ao_ext;
++static const struct comedi_lrange range_ni_E_ao_ext;
+ 
+ enum m_series_register_offsets {
+ 	M_Offset_CDIO_DMA_Select = 0x7,	// write
+@@ -1390,7 +1390,7 @@ typedef struct ni_board_struct {
+ 	int n_aochan;
+ 	int aobits;
+ 	int ao_fifo_depth;
+-	const comedi_lrange *ao_range_table;
++	const struct comedi_lrange *ao_range_table;
+ 	unsigned ao_speed;
+ 
+ 	unsigned num_p0_dio_channels;
+diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c
+index e2f73ca1aa15..8603cd18383c 100644
+--- a/drivers/staging/comedi/drivers/pcl711.c
++++ b/drivers/staging/comedi/drivers/pcl711.c
+@@ -87,7 +87,7 @@ supported.
+ #define PCL711_DO_LO 13
+ #define PCL711_DO_HI 14
+ 
+-static const comedi_lrange range_pcl711b_ai = { 5, {
++static const struct comedi_lrange range_pcl711b_ai = { 5, {
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(2.5),
+ 			BIP_RANGE(1.25),
+@@ -95,7 +95,7 @@ static const comedi_lrange range_pcl711b_ai = { 5, {
+ 			BIP_RANGE(0.3125)
+ 	}
+ };
+-static const comedi_lrange range_acl8112hg_ai = { 12, {
++static const struct comedi_lrange range_acl8112hg_ai = { 12, {
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(0.5),
+ 			BIP_RANGE(0.05),
+@@ -110,7 +110,7 @@ static const comedi_lrange range_acl8112hg_ai = { 12, {
+ 			BIP_RANGE(0.01)
+ 	}
+ };
+-static const comedi_lrange range_acl8112dg_ai = { 9, {
++static const struct comedi_lrange range_acl8112dg_ai = { 9, {
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(2.5),
+ 			BIP_RANGE(1.25),
+@@ -141,7 +141,7 @@ typedef struct {
+ 	int n_aichan;
+ 	int n_aochan;
+ 	int maxirq;
+-	const comedi_lrange *ai_range_type;
++	const struct comedi_lrange *ai_range_type;
+ } boardtype;
+ 
+ static const boardtype boardtypes[] = {
+diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c
+index f63b60f6f7d4..a76cf622aef5 100644
+--- a/drivers/staging/comedi/drivers/pcl726.c
++++ b/drivers/staging/comedi/drivers/pcl726.c
+@@ -90,22 +90,22 @@ Interrupts are not supported.
+ #define PCL727_DI_HI  0
+ #define PCL727_DI_LO  1
+ 
+-static const comedi_lrange range_4_20mA = { 1, {RANGE_mA(4, 20)} };
+-static const comedi_lrange range_0_20mA = { 1, {RANGE_mA(0, 20)} };
++static const struct comedi_lrange range_4_20mA = { 1, {RANGE_mA(4, 20)} };
++static const struct comedi_lrange range_0_20mA = { 1, {RANGE_mA(0, 20)} };
+ 
+-static const comedi_lrange *const rangelist_726[] = {
++static const struct comedi_lrange *const rangelist_726[] = {
+ 	&range_unipolar5, &range_unipolar10,
+ 	&range_bipolar5, &range_bipolar10,
+ 	&range_4_20mA, &range_unknown
+ };
+ 
+-static const comedi_lrange *const rangelist_727[] = {
++static const struct comedi_lrange *const rangelist_727[] = {
+ 	&range_unipolar5, &range_unipolar10,
+ 	&range_bipolar5,
+ 	&range_4_20mA
+ };
+ 
+-static const comedi_lrange *const rangelist_728[] = {
++static const struct comedi_lrange *const rangelist_728[] = {
+ 	&range_unipolar5, &range_unipolar10,
+ 	&range_bipolar5, &range_bipolar10,
+ 	&range_4_20mA, &range_0_20mA
+@@ -125,7 +125,7 @@ typedef struct {
+ 	int di_lo;
+ 	int do_hi;
+ 	int do_lo;
+-	const comedi_lrange *const *range_type_list;	// list of supported ranges
++	const struct comedi_lrange *const *range_type_list;	// list of supported ranges
+ } boardtype;
+ 
+ static const boardtype boardtypes[] = {
+@@ -163,7 +163,7 @@ COMEDI_INITCLEANUP(driver_pcl726);
+ 
+ typedef struct {
+ 	int bipolar[12];
+-	const comedi_lrange *rangelist[12];
++	const struct comedi_lrange *rangelist[12];
+ 	unsigned int ao_readback[12];
+ } pcl726_private;
+ #define devpriv ((pcl726_private *)dev->private)
+diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
+index a44f1fb3af54..522cb0527cfc 100644
+--- a/drivers/staging/comedi/drivers/pcl812.c
++++ b/drivers/staging/comedi/drivers/pcl812.c
+@@ -159,7 +159,7 @@ Options for ACL-8113, ISO-813:
+ 
+ #define MAX_CHANLIST_LEN	256	/* length of scan list */
+ 
+-static const comedi_lrange range_pcl812pg_ai = { 5, {
++static const struct comedi_lrange range_pcl812pg_ai = { 5, {
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(2.5),
+ 			BIP_RANGE(1.25),
+@@ -167,7 +167,7 @@ static const comedi_lrange range_pcl812pg_ai = { 5, {
+ 			BIP_RANGE(0.3125),
+ 	}
+ };
+-static const comedi_lrange range_pcl812pg2_ai = { 5, {
++static const struct comedi_lrange range_pcl812pg2_ai = { 5, {
+ 			BIP_RANGE(10),
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(2.5),
+@@ -175,33 +175,33 @@ static const comedi_lrange range_pcl812pg2_ai = { 5, {
+ 			BIP_RANGE(0.625),
+ 	}
+ };
+-static const comedi_lrange range812_bipolar1_25 = { 1, {
++static const struct comedi_lrange range812_bipolar1_25 = { 1, {
+ 			BIP_RANGE(1.25),
+ 	}
+ };
+-static const comedi_lrange range812_bipolar0_625 = { 1, {
++static const struct comedi_lrange range812_bipolar0_625 = { 1, {
+ 			BIP_RANGE(0.625),
+ 	}
+ };
+-static const comedi_lrange range812_bipolar0_3125 = { 1, {
++static const struct comedi_lrange range812_bipolar0_3125 = { 1, {
+ 			BIP_RANGE(0.3125),
+ 	}
+ };
+-static const comedi_lrange range_pcl813b_ai = { 4, {
++static const struct comedi_lrange range_pcl813b_ai = { 4, {
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(2.5),
+ 			BIP_RANGE(1.25),
+ 			BIP_RANGE(0.625),
+ 	}
+ };
+-static const comedi_lrange range_pcl813b2_ai = { 4, {
++static const struct comedi_lrange range_pcl813b2_ai = { 4, {
+ 			UNI_RANGE(10),
+ 			UNI_RANGE(5),
+ 			UNI_RANGE(2.5),
+ 			UNI_RANGE(1.25),
+ 	}
+ };
+-static const comedi_lrange range_iso813_1_ai = { 5, {
++static const struct comedi_lrange range_iso813_1_ai = { 5, {
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(2.5),
+ 			BIP_RANGE(1.25),
+@@ -209,7 +209,7 @@ static const comedi_lrange range_iso813_1_ai = { 5, {
+ 			BIP_RANGE(0.3125),
+ 	}
+ };
+-static const comedi_lrange range_iso813_1_2_ai = { 5, {
++static const struct comedi_lrange range_iso813_1_2_ai = { 5, {
+ 			UNI_RANGE(10),
+ 			UNI_RANGE(5),
+ 			UNI_RANGE(2.5),
+@@ -217,47 +217,47 @@ static const comedi_lrange range_iso813_1_2_ai = { 5, {
+ 			UNI_RANGE(0.625),
+ 	}
+ };
+-static const comedi_lrange range_iso813_2_ai = { 4, {
++static const struct comedi_lrange range_iso813_2_ai = { 4, {
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(2.5),
+ 			BIP_RANGE(1.25),
+ 			BIP_RANGE(0.625),
+ 	}
+ };
+-static const comedi_lrange range_iso813_2_2_ai = { 4, {
++static const struct comedi_lrange range_iso813_2_2_ai = { 4, {
+ 			UNI_RANGE(10),
+ 			UNI_RANGE(5),
+ 			UNI_RANGE(2.5),
+ 			UNI_RANGE(1.25),
+ 	}
+ };
+-static const comedi_lrange range_acl8113_1_ai = { 4, {
++static const struct comedi_lrange range_acl8113_1_ai = { 4, {
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(2.5),
+ 			BIP_RANGE(1.25),
+ 			BIP_RANGE(0.625),
+ 	}
+ };
+-static const comedi_lrange range_acl8113_1_2_ai = { 4, {
++static const struct comedi_lrange range_acl8113_1_2_ai = { 4, {
+ 			UNI_RANGE(10),
+ 			UNI_RANGE(5),
+ 			UNI_RANGE(2.5),
+ 			UNI_RANGE(1.25),
+ 	}
+ };
+-static const comedi_lrange range_acl8113_2_ai = { 3, {
++static const struct comedi_lrange range_acl8113_2_ai = { 3, {
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(2.5),
+ 			BIP_RANGE(1.25),
+ 	}
+ };
+-static const comedi_lrange range_acl8113_2_2_ai = { 3, {
++static const struct comedi_lrange range_acl8113_2_2_ai = { 3, {
+ 			UNI_RANGE(10),
+ 			UNI_RANGE(5),
+ 			UNI_RANGE(2.5),
+ 	}
+ };
+-static const comedi_lrange range_acl8112dg_ai = { 9, {
++static const struct comedi_lrange range_acl8112dg_ai = { 9, {
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(2.5),
+ 			BIP_RANGE(1.25),
+@@ -269,7 +269,7 @@ static const comedi_lrange range_acl8112dg_ai = { 9, {
+ 			BIP_RANGE(10),
+ 	}
+ };
+-static const comedi_lrange range_acl8112hg_ai = { 12, {
++static const struct comedi_lrange range_acl8112hg_ai = { 12, {
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(0.5),
+ 			BIP_RANGE(0.05),
+@@ -284,7 +284,7 @@ static const comedi_lrange range_acl8112hg_ai = { 12, {
+ 			BIP_RANGE(0.01),
+ 	}
+ };
+-static const comedi_lrange range_a821pgh_ai = { 4, {
++static const struct comedi_lrange range_a821pgh_ai = { 4, {
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(0.5),
+ 			BIP_RANGE(0.05),
+@@ -306,8 +306,8 @@ typedef struct {
+ 	int ai_maxdata;		// AI resolution
+ 	unsigned int ai_ns_min;	// max sample speed of card v ns
+ 	unsigned int i8254_osc_base;	// clock base
+-	const comedi_lrange *rangelist_ai;	// rangelist for A/D
+-	const comedi_lrange *rangelist_ao;	// rangelist for D/A
++	const struct comedi_lrange *rangelist_ai;	// rangelist for A/D
++	const struct comedi_lrange *rangelist_ao;	// rangelist for D/A
+ 	unsigned int IRQbits;	// allowed IRQ
+ 	unsigned char DMAbits;	// allowed DMA chans
+ 	unsigned char io_range;	// iorange for this board
+diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
+index c5a969898c12..d90e2e584f63 100644
+--- a/drivers/staging/comedi/drivers/pcl816.c
++++ b/drivers/staging/comedi/drivers/pcl816.c
+@@ -90,7 +90,7 @@ Configuration Options:
+ 
+ #define MAGIC_DMA_WORD 0x5a5a
+ 
+-static const comedi_lrange range_pcl816 = { 8, {
++static const struct comedi_lrange range_pcl816 = { 8, {
+ 			BIP_RANGE(10),
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(2.5),
+@@ -109,8 +109,8 @@ typedef struct {
+ 	int n_aochan;		// num of D/A chans
+ 	int n_dichan;		// num of DI chans
+ 	int n_dochan;		// num of DO chans
+-	const comedi_lrange *ai_range_type;	// default A/D rangelist
+-	const comedi_lrange *ao_range_type;	// dafault D/A rangelist
++	const struct comedi_lrange *ai_range_type;	// default A/D rangelist
++	const struct comedi_lrange *ao_range_type;	// dafault D/A rangelist
+ 	unsigned int io_range;	// len of IO space
+ 	unsigned int IRQbits;	// allowed interrupts
+ 	unsigned int DMAbits;	// allowed DMA chans
+diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
+index afe326e7d98c..d1992969c037 100644
+--- a/drivers/staging/comedi/drivers/pcl818.c
++++ b/drivers/staging/comedi/drivers/pcl818.c
+@@ -194,7 +194,7 @@ A word or two about DMA. Driver support DMA operations at two ways:
+ 
+ #define MAGIC_DMA_WORD 0x5a5a
+ 
+-static const comedi_lrange range_pcl818h_ai = { 9, {
++static const struct comedi_lrange range_pcl818h_ai = { 9, {
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(2.5),
+ 			BIP_RANGE(1.25),
+@@ -207,7 +207,7 @@ static const comedi_lrange range_pcl818h_ai = { 9, {
+ 	}
+ };
+ 
+-static const comedi_lrange range_pcl818hg_ai = { 10, {
++static const struct comedi_lrange range_pcl818hg_ai = { 10, {
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(0.5),
+ 			BIP_RANGE(0.05),
+@@ -223,7 +223,7 @@ static const comedi_lrange range_pcl818hg_ai = { 10, {
+ 	}
+ };
+ 
+-static const comedi_lrange range_pcl818l_l_ai = { 4, {
++static const struct comedi_lrange range_pcl818l_l_ai = { 4, {
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(2.5),
+ 			BIP_RANGE(1.25),
+@@ -231,7 +231,7 @@ static const comedi_lrange range_pcl818l_l_ai = { 4, {
+ 	}
+ };
+ 
+-static const comedi_lrange range_pcl818l_h_ai = { 4, {
++static const struct comedi_lrange range_pcl818l_h_ai = { 4, {
+ 			BIP_RANGE(10),
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(2.5),
+@@ -239,10 +239,10 @@ static const comedi_lrange range_pcl818l_h_ai = { 4, {
+ 	}
+ };
+ 
+-static const comedi_lrange range718_bipolar1 = { 1, {BIP_RANGE(1),} };
+-static const comedi_lrange range718_bipolar0_5 = { 1, {BIP_RANGE(0.5),} };
+-static const comedi_lrange range718_unipolar2 = { 1, {UNI_RANGE(2),} };
+-static const comedi_lrange range718_unipolar1 = { 1, {BIP_RANGE(1),} };
++static const struct comedi_lrange range718_bipolar1 = { 1, {BIP_RANGE(1),} };
++static const struct comedi_lrange range718_bipolar0_5 = { 1, {BIP_RANGE(0.5),} };
++static const struct comedi_lrange range718_unipolar2 = { 1, {UNI_RANGE(2),} };
++static const struct comedi_lrange range718_unipolar1 = { 1, {BIP_RANGE(1),} };
+ 
+ static int pcl818_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int pcl818_detach(struct comedi_device * dev);
+@@ -261,8 +261,8 @@ typedef struct {
+ 	int n_aochan;		// num of D/A chans
+ 	int n_dichan;		// num of DI chans
+ 	int n_dochan;		// num of DO chans
+-	const comedi_lrange *ai_range_type;	// default A/D rangelist
+-	const comedi_lrange *ao_range_type;	// default D/A rangelist
++	const struct comedi_lrange *ai_range_type;	// default A/D rangelist
++	const struct comedi_lrange *ao_range_type;	// default D/A rangelist
+ 	unsigned int io_range;	// len of IO space
+ 	unsigned int IRQbits;	// allowed interrupts
+ 	unsigned int DMAbits;	// allowed DMA chans
+diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c
+index a2dfb4bf65f8..9442eed9271d 100644
+--- a/drivers/staging/comedi/drivers/pcmda12.c
++++ b/drivers/staging/comedi/drivers/pcmda12.c
+@@ -74,7 +74,7 @@ typedef struct pcmda12_board_struct {
+ 
+ /* note these have no effect and are merely here for reference..
+    these are configured by jumpering the board! */
+-static const comedi_lrange pcmda12_ranges = {
++static const struct comedi_lrange pcmda12_ranges = {
+ 	3,
+ 	{
+ 			UNI_RANGE(5), UNI_RANGE(10), BIP_RANGE(5)
+diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
+index 0dcc09982fa6..780de845034a 100644
+--- a/drivers/staging/comedi/drivers/pcmmio.c
++++ b/drivers/staging/comedi/drivers/pcmmio.c
+@@ -163,16 +163,16 @@ typedef struct pcmmio_board_struct {
+ 	const int ao_bits;
+ 	const int n_ai_chans;
+ 	const int n_ao_chans;
+-	const comedi_lrange *ai_range_table, *ao_range_table;
++	const struct comedi_lrange *ai_range_table, *ao_range_table;
+ 	comedi_insn_fn_t ai_rinsn, ao_rinsn, ao_winsn;
+ } pcmmio_board;
+ 
+-static const comedi_lrange ranges_ai =
++static const struct comedi_lrange ranges_ai =
+ 	{ 4, {RANGE(-5., 5.), RANGE(-10., 10.), RANGE(0., 5.), RANGE(0.,
+ 		10.)}
+ };
+ 
+-static const comedi_lrange ranges_ao =
++static const struct comedi_lrange ranges_ao =
+ 	{ 6, {RANGE(0., 5.), RANGE(0., 10.), RANGE(-5., 5.), RANGE(-10., 10.),
+ 	RANGE(-2.5, 2.5), RANGE(-2.5, 7.5)}
+ };
+diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c
+index dde46b126312..b1b1138c4d50 100644
+--- a/drivers/staging/comedi/drivers/poc.c
++++ b/drivers/staging/comedi/drivers/poc.c
+@@ -66,7 +66,7 @@ struct boarddef_struct {
+ 		unsigned int *);
+ 	int (*insnbits) (struct comedi_device *, struct comedi_subdevice *, comedi_insn *,
+ 		unsigned int *);
+-	const comedi_lrange *range;
++	const struct comedi_lrange *range;
+ };
+ static const struct boarddef_struct boards[] = {
+ 	{
+diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+index c30b1ccb2903..d83cc3295dd4 100644
+--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
++++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+@@ -183,7 +183,7 @@ static local_info_t *dev_table[MAX_DEV] = { NULL, /* ... */  };
+  * +/- 1.25V, and the D/A converter has only one: +/- 5V.
+  */
+ 
+-static const comedi_lrange range_daqp_ai = { 4, {
++static const struct comedi_lrange range_daqp_ai = { 4, {
+ 			BIP_RANGE(10),
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(2.5),
+@@ -191,7 +191,7 @@ static const comedi_lrange range_daqp_ai = { 4, {
+ 	}
+ };
+ 
+-static const comedi_lrange range_daqp_ao = { 1, {BIP_RANGE(5)} };
++static const struct comedi_lrange range_daqp_ao = { 1, {BIP_RANGE(5)} };
+ 
+ /*====================================================================*/
+ 
+diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
+index c238f5b97d85..42b96fae7100 100644
+--- a/drivers/staging/comedi/drivers/rtd520.c
++++ b/drivers/staging/comedi/drivers/rtd520.c
+@@ -196,7 +196,7 @@ Configuration options:
+ /*
+   The board has 3 input modes and the gains of 1,2,4,...32 (, 64, 128)
+ */
+-static const comedi_lrange rtd_ai_7520_range = { 18, {
++static const struct comedi_lrange rtd_ai_7520_range = { 18, {
+ 			/* +-5V input range gain steps */
+ 			BIP_RANGE(5.0),
+ 			BIP_RANGE(5.0 / 2),
+@@ -223,7 +223,7 @@ static const comedi_lrange rtd_ai_7520_range = { 18, {
+ };
+ 
+ /* PCI4520 has two more gains (6 more entries) */
+-static const comedi_lrange rtd_ai_4520_range = { 24, {
++static const struct comedi_lrange rtd_ai_4520_range = { 24, {
+ 			/* +-5V input range gain steps */
+ 			BIP_RANGE(5.0),
+ 			BIP_RANGE(5.0 / 2),
+@@ -255,7 +255,7 @@ static const comedi_lrange rtd_ai_4520_range = { 24, {
+ };
+ 
+ /* Table order matches range values */
+-static const comedi_lrange rtd_ao_range = { 4, {
++static const struct comedi_lrange rtd_ao_range = { 4, {
+ 			RANGE(0, 5),
+ 			RANGE(0, 10),
+ 			RANGE(-5, 5),
+diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c
+index 0d2e9ff4f4f6..463ef4841f0d 100644
+--- a/drivers/staging/comedi/drivers/rti800.c
++++ b/drivers/staging/comedi/drivers/rti800.c
+@@ -96,21 +96,21 @@ Configuration options:
+ 
+ #include "am9513.h"
+ 
+-static const comedi_lrange range_rti800_ai_10_bipolar = { 4, {
++static const struct comedi_lrange range_rti800_ai_10_bipolar = { 4, {
+ 			BIP_RANGE(10),
+ 			BIP_RANGE(1),
+ 			BIP_RANGE(0.1),
+ 			BIP_RANGE(0.02)
+ 	}
+ };
+-static const comedi_lrange range_rti800_ai_5_bipolar = { 4, {
++static const struct comedi_lrange range_rti800_ai_5_bipolar = { 4, {
+ 			BIP_RANGE(5),
+ 			BIP_RANGE(0.5),
+ 			BIP_RANGE(0.05),
+ 			BIP_RANGE(0.01)
+ 	}
+ };
+-static const comedi_lrange range_rti800_ai_unipolar = { 4, {
++static const struct comedi_lrange range_rti800_ai_unipolar = { 4, {
+ 			UNI_RANGE(10),
+ 			UNI_RANGE(1),
+ 			UNI_RANGE(0.1),
+@@ -161,7 +161,7 @@ typedef struct {
+ 	enum {
+ 		dac_2comp, dac_straight
+ 	} dac0_coding, dac1_coding;
+-	const comedi_lrange *ao_range_type_list[2];
++	const struct comedi_lrange *ao_range_type_list[2];
+ 	unsigned int ao_readback[2];
+ 	int muxgain_bits;
+ } rti800_private;
+diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c
+index 0d2d1c310d03..44bf3451d730 100644
+--- a/drivers/staging/comedi/drivers/rti802.c
++++ b/drivers/staging/comedi/drivers/rti802.c
+@@ -62,7 +62,7 @@ typedef struct {
+ 	enum {
+ 		dac_2comp, dac_straight
+ 	} dac_coding[8];
+-	const comedi_lrange *range_type_list[8];
++	const struct comedi_lrange *range_type_list[8];
+ 	unsigned int ao_readback[8];
+ } rti802_private;
+ 
+diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
+index ac6424ca25da..4f7068fb2bc0 100644
+--- a/drivers/staging/comedi/drivers/s626.c
++++ b/drivers/staging/comedi/drivers/s626.c
+@@ -479,7 +479,7 @@ static struct enc_private enc_private_data[] = {
+ #define I2C_B1(ATTR, VAL)	(((ATTR) << 4) | ((VAL) << 16))
+ #define I2C_B0(ATTR, VAL)	(((ATTR) << 2) | ((VAL) <<  8))
+ 
+-static const comedi_lrange s626_range_table = { 2, {
++static const struct comedi_lrange s626_range_table = { 2, {
+ 			RANGE(-5, 5),
+ 			RANGE(-10, 10),
+ 	}
+diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
+index 7c056a328c0d..61cf19ebc278 100644
+--- a/drivers/staging/comedi/drivers/serial2002.c
++++ b/drivers/staging/comedi/drivers/serial2002.c
+@@ -598,7 +598,7 @@ static void serial_2002_open(struct comedi_device * dev)
+ 			}
+ 			if (c) {
+ 				struct comedi_subdevice *s;
+-				const comedi_lrange **range_table_list = NULL;
++				const struct comedi_lrange **range_table_list = NULL;
+ 				unsigned int *maxdata_list;
+ 				int j, chan;
+ 
+@@ -638,7 +638,7 @@ static void serial_2002_open(struct comedi_device * dev)
+ 							range[j].range.max =
+ 								c[j].max;
+ 							range_table_list[chan] =
+-								(const
++								(const struct
+ 								comedi_lrange *)
+ 								&range[j];
+ 						}
+diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
+index e3462c4a5a65..108f2d71cd83 100644
+--- a/drivers/staging/comedi/drivers/usbdux.c
++++ b/drivers/staging/comedi/drivers/usbdux.c
+@@ -214,7 +214,7 @@ sampling rate. If you sample two channels you get 4kHz and so on.
+ 
+ /**************************************************/
+ /* comedi constants */
+-static const comedi_lrange range_usbdux_ai_range = { 4, {
++static const struct comedi_lrange range_usbdux_ai_range = { 4, {
+ 			BIP_RANGE(4.096),
+ 			BIP_RANGE(4.096 / 2),
+ 			UNI_RANGE(4.096),
+@@ -222,7 +222,7 @@ static const comedi_lrange range_usbdux_ai_range = { 4, {
+ 	}
+ };
+ 
+-static const comedi_lrange range_usbdux_ao_range = { 2, {
++static const struct comedi_lrange range_usbdux_ao_range = { 2, {
+ 			BIP_RANGE(4.096),
+ 			UNI_RANGE(4.096),
+ 	}
+diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c
+index 54b49580505a..a5e93ac066bb 100644
+--- a/drivers/staging/comedi/drivers/usbduxfast.c
++++ b/drivers/staging/comedi/drivers/usbduxfast.c
+@@ -160,7 +160,7 @@
+ /*
+  * comedi constants
+  */
+-static const comedi_lrange range_usbduxfast_ai_range = {
++static const struct comedi_lrange range_usbduxfast_ai_range = {
+ 	2, { BIP_RANGE(0.75), BIP_RANGE(0.5) }
+ };
+ 
+diff --git a/drivers/staging/comedi/kcomedilib/get.c b/drivers/staging/comedi/kcomedilib/get.c
+index 8890fcb7c1c5..a7d4ff638444 100644
+--- a/drivers/staging/comedi/kcomedilib/get.c
++++ b/drivers/staging/comedi/kcomedilib/get.c
+@@ -153,7 +153,7 @@ int comedi_get_krange(void *d, unsigned int subdevice, unsigned int chan,
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+ 	struct comedi_subdevice *s = dev->subdevices + subdevice;
+-	const comedi_lrange *lr;
++	const struct comedi_lrange *lr;
+ 
+ 	if (s->range_table_list) {
+ 		lr = s->range_table_list[chan];
+diff --git a/drivers/staging/comedi/range.c b/drivers/staging/comedi/range.c
+index 98f53df35573..ef7ad56174bf 100644
+--- a/drivers/staging/comedi/range.c
++++ b/drivers/staging/comedi/range.c
+@@ -24,12 +24,12 @@
+ #include "comedidev.h"
+ #include 
+ 
+-const comedi_lrange range_bipolar10 = { 1, {BIP_RANGE(10)} };
+-const comedi_lrange range_bipolar5 = { 1, {BIP_RANGE(5)} };
+-const comedi_lrange range_bipolar2_5 = { 1, {BIP_RANGE(2.5)} };
+-const comedi_lrange range_unipolar10 = { 1, {UNI_RANGE(10)} };
+-const comedi_lrange range_unipolar5 = { 1, {UNI_RANGE(5)} };
+-const comedi_lrange range_unknown = { 1, {{0, 1000000, UNIT_none}} };
++const struct comedi_lrange range_bipolar10 = { 1, {BIP_RANGE(10)} };
++const struct comedi_lrange range_bipolar5 = { 1, {BIP_RANGE(5)} };
++const struct comedi_lrange range_bipolar2_5 = { 1, {BIP_RANGE(2.5)} };
++const struct comedi_lrange range_unipolar10 = { 1, {UNI_RANGE(10)} };
++const struct comedi_lrange range_unipolar5 = { 1, {UNI_RANGE(5)} };
++const struct comedi_lrange range_unknown = { 1, {{0, 1000000, UNIT_none}} };
+ 
+ /*
+    	COMEDI_RANGEINFO
+@@ -48,7 +48,7 @@ int do_rangeinfo_ioctl(struct comedi_device *dev, comedi_rangeinfo *arg)
+ {
+ 	comedi_rangeinfo it;
+ 	int subd, chan;
+-	const comedi_lrange *lr;
++	const struct comedi_lrange *lr;
+ 	struct comedi_subdevice *s;
+ 
+ 	if (copy_from_user(&it, arg, sizeof(comedi_rangeinfo)))

commit 139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:05:25 2009 -0400
+
+    Staging: comedi: Remove comedi_driver typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
+index 1fdb093f9318..83c45a691bdd 100644
+--- a/drivers/staging/comedi/comedidev.h
++++ b/drivers/staging/comedi/comedidev.h
+@@ -121,7 +121,6 @@
+ #define COMEDI_NUM_BOARD_MINORS 0x30
+ #define COMEDI_FIRST_SUBDEVICE_MINOR COMEDI_NUM_BOARD_MINORS
+ 
+-typedef struct comedi_driver_struct comedi_driver;
+ typedef struct comedi_lrange_struct comedi_lrange;
+ 
+ typedef struct device device_create_result_type;
+@@ -239,8 +238,8 @@ struct comedi_async {
+ 			unsigned int x);
+ };
+ 
+-struct comedi_driver_struct {
+-	struct comedi_driver_struct *next;
++struct comedi_driver {
++	struct comedi_driver *next;
+ 
+ 	const char *driver_name;
+ 	struct module *module;
+@@ -256,7 +255,7 @@ struct comedi_driver_struct {
+ 
+ struct comedi_device {
+ 	int use_count;
+-	comedi_driver *driver;
++	struct comedi_driver *driver;
+ 	void *private;
+ 
+ 	device_create_result_type *class_dev;
+@@ -343,8 +342,8 @@ static inline struct comedi_subdevice *comedi_get_write_subdevice(
+ 
+ void comedi_device_detach(struct comedi_device *dev);
+ int comedi_device_attach(struct comedi_device *dev, comedi_devconfig *it);
+-int comedi_driver_register(comedi_driver *);
+-int comedi_driver_unregister(comedi_driver *);
++int comedi_driver_register(struct comedi_driver *);
++int comedi_driver_unregister(struct comedi_driver *);
+ 
+ void init_polling(void);
+ void cleanup_polling(void);
+diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
+index 30e3beb6e97b..2d09a01c86c3 100644
+--- a/drivers/staging/comedi/drivers.c
++++ b/drivers/staging/comedi/drivers.c
+@@ -50,13 +50,13 @@
+ static int postconfig(struct comedi_device *dev);
+ static int insn_rw_emulate_bits(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+-static void *comedi_recognize(comedi_driver * driv, const char *name);
+-static void comedi_report_boards(comedi_driver *driv);
++static void *comedi_recognize(struct comedi_driver * driv, const char *name);
++static void comedi_report_boards(struct comedi_driver *driv);
+ static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s);
+ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned long new_size);
+ 
+-comedi_driver *comedi_drivers;
++struct comedi_driver *comedi_drivers;
+ 
+ int comedi_modprobe(int minor)
+ {
+@@ -115,7 +115,7 @@ void comedi_device_detach(struct comedi_device *dev)
+ 
+ int comedi_device_attach(struct comedi_device *dev, comedi_devconfig *it)
+ {
+-	comedi_driver *driv;
++	struct comedi_driver *driv;
+ 	int ret;
+ 
+ 	if (dev->attached)
+@@ -180,7 +180,7 @@ int comedi_device_attach(struct comedi_device *dev, comedi_devconfig *it)
+ 	return 0;
+ }
+ 
+-int comedi_driver_register(comedi_driver *driver)
++int comedi_driver_register(struct comedi_driver *driver)
+ {
+ 	driver->next = comedi_drivers;
+ 	comedi_drivers = driver;
+@@ -188,9 +188,9 @@ int comedi_driver_register(comedi_driver *driver)
+ 	return 0;
+ }
+ 
+-int comedi_driver_unregister(comedi_driver *driver)
++int comedi_driver_unregister(struct comedi_driver *driver)
+ {
+-	comedi_driver *prev;
++	struct comedi_driver *prev;
+ 	int i;
+ 
+ 	/* check for devices using this driver */
+@@ -298,7 +298,7 @@ static int postconfig(struct comedi_device *dev)
+ }
+ 
+ /*  generic recognize function for drivers that register their supported board names */
+-void *comedi_recognize(comedi_driver * driv, const char *name)
++void *comedi_recognize(struct comedi_driver * driv, const char *name)
+ {
+ 	unsigned i;
+ 	const char *const *name_ptr = driv->board_name;
+@@ -313,7 +313,7 @@ void *comedi_recognize(comedi_driver * driv, const char *name)
+ 	return NULL;
+ }
+ 
+-void comedi_report_boards(comedi_driver *driv)
++void comedi_report_boards(struct comedi_driver *driv)
+ {
+ 	unsigned int i;
+ 	const char *const *name_ptr;
+diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c
+index e4920ae934ae..6e1786059d22 100644
+--- a/drivers/staging/comedi/drivers/8255.c
++++ b/drivers/staging/comedi/drivers/8255.c
+@@ -107,7 +107,7 @@ struct subdev_8255_struct {
+ 
+ static int dev_8255_attach(struct comedi_device *dev, comedi_devconfig * it);
+ static int dev_8255_detach(struct comedi_device *dev);
+-static comedi_driver driver_8255 = {
++static struct comedi_driver driver_8255 = {
+       driver_name:"8255",
+       module:THIS_MODULE,
+       attach:dev_8255_attach,
+diff --git a/drivers/staging/comedi/drivers/acl7225b.c b/drivers/staging/comedi/drivers/acl7225b.c
+index f273a6f0094e..235dcfea49d4 100644
+--- a/drivers/staging/comedi/drivers/acl7225b.c
++++ b/drivers/staging/comedi/drivers/acl7225b.c
+@@ -38,7 +38,7 @@ static const boardtype boardtypes[] = {
+ #define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+ #define this_board ((const boardtype *)dev->board_ptr)
+ 
+-static comedi_driver driver_acl7225b = {
++static struct comedi_driver driver_acl7225b = {
+       driver_name:"acl7225b",
+       module:THIS_MODULE,
+       attach:acl7225b_attach,
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+index 49d6332d9db2..718c4be560f0 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+@@ -2527,7 +2527,7 @@ static const boardtype boardtypes[] = {
+ 
+ #define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+ 
+-comedi_driver driver_addi = {
++struct comedi_driver driver_addi = {
+       driver_name:"addi_common",
+       module:THIS_MODULE,
+       attach:i_ADDI_Attach,
+diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c
+index 9e1597caf21d..9572f04c4cdd 100644
+--- a/drivers/staging/comedi/drivers/adl_pci6208.c
++++ b/drivers/staging/comedi/drivers/adl_pci6208.c
+@@ -112,7 +112,7 @@ static int pci6208_detach(struct comedi_device * dev);
+ #define pci6208_board_nbr \
+ 	(sizeof(pci6208_boards) / sizeof(pci6208_board))
+ 
+-static comedi_driver driver_pci6208 = {
++static struct comedi_driver driver_pci6208 = {
+       driver_name:PCI6208_DRIVER_NAME,
+       module:THIS_MODULE,
+       attach:pci6208_attach,
+diff --git a/drivers/staging/comedi/drivers/adl_pci7296.c b/drivers/staging/comedi/drivers/adl_pci7296.c
+index f38aa06d3c4e..21b8ba80dac9 100644
+--- a/drivers/staging/comedi/drivers/adl_pci7296.c
++++ b/drivers/staging/comedi/drivers/adl_pci7296.c
+@@ -65,7 +65,7 @@ typedef struct {
+ 
+ static int adl_pci7296_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int adl_pci7296_detach(struct comedi_device * dev);
+-static comedi_driver driver_adl_pci7296 = {
++static struct comedi_driver driver_adl_pci7296 = {
+       driver_name:"adl_pci7296",
+       module:THIS_MODULE,
+       attach:adl_pci7296_attach,
+diff --git a/drivers/staging/comedi/drivers/adl_pci7432.c b/drivers/staging/comedi/drivers/adl_pci7432.c
+index a36be5e14f63..7e8741e51cec 100644
+--- a/drivers/staging/comedi/drivers/adl_pci7432.c
++++ b/drivers/staging/comedi/drivers/adl_pci7432.c
+@@ -60,7 +60,7 @@ typedef struct {
+ 
+ static int adl_pci7432_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int adl_pci7432_detach(struct comedi_device * dev);
+-static comedi_driver driver_adl_pci7432 = {
++static struct comedi_driver driver_adl_pci7432 = {
+       driver_name:"adl_pci7432",
+       module:THIS_MODULE,
+       attach:adl_pci7432_attach,
+diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c
+index cc95acf762f8..fd925f5d86f6 100644
+--- a/drivers/staging/comedi/drivers/adl_pci8164.c
++++ b/drivers/staging/comedi/drivers/adl_pci8164.c
+@@ -72,7 +72,7 @@ typedef struct {
+ 
+ static int adl_pci8164_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int adl_pci8164_detach(struct comedi_device * dev);
+-static comedi_driver driver_adl_pci8164 = {
++static struct comedi_driver driver_adl_pci8164 = {
+       driver_name:"adl_pci8164",
+       module:THIS_MODULE,
+       attach:adl_pci8164_attach,
+diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
+index cc6b1c6713c4..8b4c201aa4af 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9111.c
++++ b/drivers/staging/comedi/drivers/adl_pci9111.c
+@@ -326,7 +326,7 @@ static const pci9111_board_struct pci9111_boards[] = {
+ #define pci9111_board_nbr \
+   (sizeof(pci9111_boards)/sizeof(pci9111_board_struct))
+ 
+-static comedi_driver pci9111_driver = {
++static struct comedi_driver pci9111_driver = {
+       driver_name:PCI9111_DRIVER_NAME,
+       module:THIS_MODULE,
+       attach:pci9111_attach,
+diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
+index 67e26a3c847c..e2a6c29534d2 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9118.c
++++ b/drivers/staging/comedi/drivers/adl_pci9118.c
+@@ -229,7 +229,7 @@ static const boardtype boardtypes[] = {
+ 
+ #define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+ 
+-static comedi_driver driver_pci9118 = {
++static struct comedi_driver driver_pci9118 = {
+       driver_name:"adl_pci9118",
+       module:THIS_MODULE,
+       attach:pci9118_attach,
+diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c
+index 99a7a0562082..b5a328116807 100644
+--- a/drivers/staging/comedi/drivers/adq12b.c
++++ b/drivers/staging/comedi/drivers/adq12b.c
+@@ -157,14 +157,14 @@ typedef struct{
+ #define devpriv ((adq12b_private *)dev->private)
+ 
+ /*
+- * The comedi_driver structure tells the Comedi core module
++ * The struct comedi_driver structure tells the Comedi core module
+  * which functions to call to configure/deconfigure (attach/detach)
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+ static int adq12b_attach(struct comedi_device *dev,comedi_devconfig *it);
+ static int adq12b_detach(struct comedi_device *dev);
+-static comedi_driver driver_adq12b={
++static struct comedi_driver driver_adq12b={
+         driver_name:    "adq12b",
+         module:         THIS_MODULE,
+         attach:         adq12b_attach,
+diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
+index e66c2560b2cd..776f93dc5ecb 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1710.c
++++ b/drivers/staging/comedi/drivers/adv_pci1710.c
+@@ -256,7 +256,7 @@ static const boardtype boardtypes[] = {
+ 
+ #define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+ 
+-static comedi_driver driver_pci1710 = {
++static struct comedi_driver driver_pci1710 = {
+ 	.driver_name = DRV_NAME,
+ 	.module = THIS_MODULE,
+ 	.attach = pci1710_attach,
+diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
+index 8209e60c783c..5ce393043d17 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1723.c
++++ b/drivers/staging/comedi/drivers/adv_pci1723.c
+@@ -138,7 +138,7 @@ static DEFINE_PCI_DEVICE_TABLE(pci1723_pci_table) = {
+ MODULE_DEVICE_TABLE(pci, pci1723_pci_table);
+ 
+ /*
+- * The comedi_driver structure tells the Comedi core module
++ * The struct comedi_driver structure tells the Comedi core module
+  * which functions to call to configure/deconfigure (attach/detach)
+  * the board, and also about the kernel module that contains
+  * the device code.
+@@ -148,7 +148,7 @@ static int pci1723_detach(struct comedi_device * dev);
+ 
+ #define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+ 
+-static comedi_driver driver_pci1723 = {
++static struct comedi_driver driver_pci1723 = {
+       driver_name:"adv_pci1723",
+       module:THIS_MODULE,
+       attach:pci1723_attach,
+diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
+index e0e62ea57f7e..5fcba548a786 100644
+--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
++++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
+@@ -322,7 +322,7 @@ static const boardtype boardtypes[] = {
+ 
+ #define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+ 
+-static comedi_driver driver_pci_dio = {
++static struct comedi_driver driver_pci_dio = {
+       driver_name:"adv_pci_dio",
+       module:THIS_MODULE,
+       attach:pci_dio_attach,
+diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c
+index 5b62ec9608a8..4c569ddb195e 100644
+--- a/drivers/staging/comedi/drivers/aio_aio12_8.c
++++ b/drivers/staging/comedi/drivers/aio_aio12_8.c
+@@ -213,7 +213,7 @@ static int aio_aio12_8_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static comedi_driver driver_aio_aio12_8 = {
++static struct comedi_driver driver_aio_aio12_8 = {
+       driver_name:"aio_aio12_8",
+       module:THIS_MODULE,
+       attach:aio_aio12_8_attach,
+diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c
+index 0e3f8d5aa06c..b04ad03c85e7 100644
+--- a/drivers/staging/comedi/drivers/aio_iiro_16.c
++++ b/drivers/staging/comedi/drivers/aio_iiro_16.c
+@@ -71,7 +71,7 @@ static int aio_iiro_16_attach(struct comedi_device * dev, comedi_devconfig * it)
+ 
+ static int aio_iiro_16_detach(struct comedi_device * dev);
+ 
+-static comedi_driver driver_aio_iiro_16 = {
++static struct comedi_driver driver_aio_iiro_16 = {
+       driver_name:"aio_iiro_16",
+       module:THIS_MODULE,
+       attach:aio_iiro_16_attach,
+diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
+index f34e45028256..6323b571f61e 100644
+--- a/drivers/staging/comedi/drivers/amplc_dio200.c
++++ b/drivers/staging/comedi/drivers/amplc_dio200.c
+@@ -468,14 +468,14 @@ typedef struct {
+ } dio200_subdev_intr;
+ 
+ /*
+- * The comedi_driver structure tells the Comedi core module
++ * The struct comedi_driver structure tells the Comedi core module
+  * which functions to call to configure/deconfigure (attach/detach)
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+ static int dio200_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int dio200_detach(struct comedi_device * dev);
+-static comedi_driver driver_amplc_dio200 = {
++static struct comedi_driver driver_amplc_dio200 = {
+       driver_name:DIO200_DRIVER_NAME,
+       module:THIS_MODULE,
+       attach:dio200_attach,
+diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
+index ba91debae962..f9cc28317302 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc236.c
++++ b/drivers/staging/comedi/drivers/amplc_pc236.c
+@@ -160,14 +160,14 @@ typedef struct {
+ #define devpriv ((pc236_private *)dev->private)
+ 
+ /*
+- * The comedi_driver structure tells the Comedi core module
++ * The struct comedi_driver structure tells the Comedi core module
+  * which functions to call to configure/deconfigure (attach/detach)
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+ static int pc236_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int pc236_detach(struct comedi_device * dev);
+-static comedi_driver driver_amplc_pc236 = {
++static struct comedi_driver driver_amplc_pc236 = {
+       driver_name:PC236_DRIVER_NAME,
+       module:THIS_MODULE,
+       attach:pc236_attach,
+diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
+index 43bd5324be4a..313f4a094653 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc263.c
++++ b/drivers/staging/comedi/drivers/amplc_pc263.c
+@@ -127,14 +127,14 @@ typedef struct {
+ #endif /* CONFIG_COMEDI_PCI */
+ 
+ /*
+- * The comedi_driver structure tells the Comedi core module
++ * The struct comedi_driver structure tells the Comedi core module
+  * which functions to call to configure/deconfigure (attach/detach)
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+ static int pc263_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int pc263_detach(struct comedi_device * dev);
+-static comedi_driver driver_amplc_pc263 = {
++static struct comedi_driver driver_amplc_pc263 = {
+       driver_name:PC263_DRIVER_NAME,
+       module:THIS_MODULE,
+       attach:pc263_attach,
+diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
+index e575f7deb31d..4ca283bb58ae 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci224.c
++++ b/drivers/staging/comedi/drivers/amplc_pci224.c
+@@ -421,14 +421,14 @@ typedef struct {
+ #define devpriv ((pci224_private *)dev->private)
+ 
+ /*
+- * The comedi_driver structure tells the Comedi core module
++ * The struct comedi_driver structure tells the Comedi core module
+  * which functions to call to configure/deconfigure (attach/detach)
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+ static int pci224_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int pci224_detach(struct comedi_device * dev);
+-static comedi_driver driver_amplc_pci224 = {
++static struct comedi_driver driver_amplc_pci224 = {
+       driver_name:DRIVER_NAME,
+       module:THIS_MODULE,
+       attach:pci224_attach,
+diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
+index 99ffbd2a961c..7676f22772bf 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci230.c
++++ b/drivers/staging/comedi/drivers/amplc_pci230.c
+@@ -596,14 +596,14 @@ static const comedi_lrange pci230_ao_range = { 2, {
+ static const unsigned char pci230_ao_bipolar[2] = { 0, 1 };
+ 
+ /*
+- * The comedi_driver structure tells the Comedi core module
++ * The struct comedi_driver structure tells the Comedi core module
+  * which functions to call to configure/deconfigure (attach/detach)
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+ static int pci230_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int pci230_detach(struct comedi_device * dev);
+-static comedi_driver driver_amplc_pci230 = {
++static struct comedi_driver driver_amplc_pci230 = {
+       driver_name:"amplc_pci230",
+       module:THIS_MODULE,
+       attach:pci230_attach,
+diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c
+index afe3550fe8f1..612a04afb294 100644
+--- a/drivers/staging/comedi/drivers/c6xdigio.c
++++ b/drivers/staging/comedi/drivers/c6xdigio.c
+@@ -99,7 +99,7 @@ union encvaluetype {
+ 
+ static int c6xdigio_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int c6xdigio_detach(struct comedi_device * dev);
+-comedi_driver driver_c6xdigio = {
++struct comedi_driver driver_c6xdigio = {
+       driver_name:"c6xdigio",
+       module:THIS_MODULE,
+       attach:c6xdigio_attach,
+diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
+index ad01884479c0..d16a9278db10 100644
+--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
++++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
+@@ -91,7 +91,7 @@ typedef struct {
+ 
+ static int das16cs_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int das16cs_detach(struct comedi_device * dev);
+-static comedi_driver driver_das16cs = {
++static struct comedi_driver driver_das16cs = {
+       driver_name:"cb_das16_cs",
+       module:THIS_MODULE,
+       attach:das16cs_attach,
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
+index 53fa8ee0fb7b..75bf1d173509 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas.c
+@@ -435,14 +435,14 @@ typedef struct {
+ #define devpriv ((cb_pcidas_private *)dev->private)
+ 
+ /*
+- * The comedi_driver structure tells the Comedi core module
++ * The struct comedi_driver structure tells the Comedi core module
+  * which functions to call to configure/deconfigure (attach/detach)
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+ static int cb_pcidas_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int cb_pcidas_detach(struct comedi_device * dev);
+-static comedi_driver driver_cb_pcidas = {
++static struct comedi_driver driver_cb_pcidas = {
+       driver_name:"cb_pcidas",
+       module:THIS_MODULE,
+       attach:cb_pcidas_attach,
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
+index 345eeb6241bf..ea55c2bf3e78 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
+@@ -1127,7 +1127,7 @@ static inline pcidas64_private *priv(struct comedi_device * dev)
+  */
+ static int attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int detach(struct comedi_device * dev);
+-static comedi_driver driver_cb_pcidas = {
++static struct comedi_driver driver_cb_pcidas = {
+       driver_name:"cb_pcidas64",
+       module:THIS_MODULE,
+       attach:attach,
+diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
+index 474ffedc6daa..dc107d1df261 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidda.c
++++ b/drivers/staging/comedi/drivers/cb_pcidda.c
+@@ -249,12 +249,12 @@ static void cb_pcidda_calibrate(struct comedi_device * dev, unsigned int channel
+ 	unsigned int range);
+ 
+ /*
+- * The comedi_driver structure tells the Comedi core module
++ * The struct comedi_driver structure tells the Comedi core module
+  * which functions to call to configure/deconfigure (attach/detach)
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static comedi_driver driver_cb_pcidda = {
++static struct comedi_driver driver_cb_pcidda = {
+       driver_name:"cb_pcidda",
+       module:THIS_MODULE,
+       attach:cb_pcidda_attach,
+diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c
+index 7f749bd61b58..61da4f0bab55 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidio.c
++++ b/drivers/staging/comedi/drivers/cb_pcidio.c
+@@ -122,14 +122,14 @@ typedef struct {
+ #define devpriv ((pcidio_private *)dev->private)
+ 
+ /*
+- * The comedi_driver structure tells the Comedi core module
++ * The struct comedi_driver structure tells the Comedi core module
+  * which functions to call to configure/deconfigure (attach/detach)
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+ static int pcidio_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int pcidio_detach(struct comedi_device * dev);
+-static comedi_driver driver_cb_pcidio = {
++static struct comedi_driver driver_cb_pcidio = {
+       driver_name:"cb_pcidio",
+       module:THIS_MODULE,
+       attach:pcidio_attach,
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
+index 435bb39e8e46..0e739a567eb9 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
+@@ -170,14 +170,14 @@ typedef struct {
+ #define devpriv ((cb_pcimdas_private *)dev->private)
+ 
+ /*
+- * The comedi_driver structure tells the Comedi core module
++ * The struct comedi_driver structure tells the Comedi core module
+  * which functions to call to configure/deconfigure (attach/detach)
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+ static int cb_pcimdas_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int cb_pcimdas_detach(struct comedi_device * dev);
+-static comedi_driver driver_cb_pcimdas = {
++static struct comedi_driver driver_cb_pcimdas = {
+       driver_name:"cb_pcimdas",
+       module:THIS_MODULE,
+       attach:cb_pcimdas_attach,
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
+index 2b953c2e1959..976b789c27e0 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
+@@ -176,14 +176,14 @@ typedef struct {
+ #define devpriv ((private *)dev->private)
+ 
+ /*
+- * The comedi_driver structure tells the Comedi core module
++ * The struct comedi_driver structure tells the Comedi core module
+  * which functions to call to configure/deconfigure (attach/detach)
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+ static int attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int detach(struct comedi_device * dev);
+-static comedi_driver cb_pcimdda_driver = {
++static struct comedi_driver cb_pcimdda_driver = {
+       driver_name:"cb_pcimdda",
+       module:THIS_MODULE,
+       attach:attach,
+diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c
+index aa6892254f39..deba16fb2fa8 100644
+--- a/drivers/staging/comedi/drivers/comedi_bond.c
++++ b/drivers/staging/comedi/drivers/comedi_bond.c
+@@ -59,7 +59,7 @@ Configuration Options:
+  * Devices: a full list of the boards that attempt to be supported by
+  *   the driver.  Format is "(manufacturer) board name [comedi name]",
+  *   where comedi_name is the name that is used to configure the board.
+- *   See the comment near board_name: in the comedi_driver structure
++ *   See the comment near board_name: in the struct comedi_driver structure
+  *   below.  If (manufacturer) or [comedi name] is missing, the previous
+  *   value is used.
+  * Author: you
+@@ -171,7 +171,7 @@ struct Private {
+ #define devpriv ((struct Private *)dev->private)
+ 
+ /*
+- * The comedi_driver structure tells the Comedi core module
++ * The struct comedi_driver structure tells the Comedi core module
+  * which functions to call to configure/deconfigure (attach/detach)
+  * the board, and also about the kernel module that contains
+  * the device code.
+@@ -185,7 +185,7 @@ static void doDevUnconfig(struct comedi_device *dev);
+  * what can I say?  I like to do wasteful memcopies.. :) */
+ static void *Realloc(const void *ptr, size_t len, size_t old_len);
+ 
+-static comedi_driver driver_bonding = {
++static struct comedi_driver driver_bonding = {
+       .driver_name =	MODULE_NAME,
+       .module =		THIS_MODULE,
+       .attach =		bonding_attach,
+diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c
+index 50790b651cef..774a72722899 100644
+--- a/drivers/staging/comedi/drivers/comedi_parport.c
++++ b/drivers/staging/comedi/drivers/comedi_parport.c
+@@ -92,7 +92,7 @@ pin, which can be used to wake up tasks.
+ 
+ static int parport_attach(struct comedi_device *dev, comedi_devconfig *it);
+ static int parport_detach(struct comedi_device *dev);
+-static comedi_driver driver_parport = {
++static struct comedi_driver driver_parport = {
+       .driver_name =	"comedi_parport",
+       .module =		THIS_MODULE,
+       .attach =		parport_attach,
+diff --git a/drivers/staging/comedi/drivers/comedi_rt_timer.c b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+index 93a43bdf3bcf..1ba425fda31a 100644
+--- a/drivers/staging/comedi/drivers/comedi_rt_timer.c
++++ b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+@@ -128,7 +128,7 @@ static int timer_inttrig(struct comedi_device * dev, struct comedi_subdevice * s
+ 	unsigned int trig_num);
+ static int timer_start_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ 
+-static comedi_driver driver_timer = {
++static struct comedi_driver driver_timer = {
+       module:THIS_MODULE,
+       driver_name:"comedi_rt_timer",
+       attach:timer_attach,
+diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c
+index f8baf83c588c..908dddcc5a45 100644
+--- a/drivers/staging/comedi/drivers/comedi_test.c
++++ b/drivers/staging/comedi/drivers/comedi_test.c
+@@ -95,7 +95,7 @@ struct waveform_private {
+ 
+ static int waveform_attach(struct comedi_device *dev, comedi_devconfig *it);
+ static int waveform_detach(struct comedi_device *dev);
+-static comedi_driver driver_waveform = {
++static struct comedi_driver driver_waveform = {
+       .driver_name =	"comedi_test",
+       .module =		THIS_MODULE,
+       .attach =		waveform_attach,
+diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
+index 0b96859cc3bf..87303081f616 100644
+--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
++++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
+@@ -77,7 +77,7 @@ typedef struct {
+ 
+ static int contec_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int contec_detach(struct comedi_device * dev);
+-static comedi_driver driver_contec = {
++static struct comedi_driver driver_contec = {
+       driver_name:"contec_pci_dio",
+       module:THIS_MODULE,
+       attach:contec_attach,
+diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
+index 9ef655eec40b..378ec9471778 100644
+--- a/drivers/staging/comedi/drivers/daqboard2000.c
++++ b/drivers/staging/comedi/drivers/daqboard2000.c
+@@ -299,7 +299,7 @@ typedef struct daqboard2000_hw {
+ static int daqboard2000_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int daqboard2000_detach(struct comedi_device * dev);
+ 
+-static comedi_driver driver_daqboard2000 = {
++static struct comedi_driver driver_daqboard2000 = {
+       driver_name:"daqboard2000",
+       module:THIS_MODULE,
+       attach:daqboard2000_attach,
+diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
+index a0029dc7e389..e8d8d67d513a 100644
+--- a/drivers/staging/comedi/drivers/das08.c
++++ b/drivers/staging/comedi/drivers/das08.c
+@@ -829,7 +829,7 @@ static int das08_counter_config(struct comedi_device * dev, struct comedi_subdev
+ 
+ static int das08_attach(struct comedi_device * dev, comedi_devconfig * it);
+ 
+-static comedi_driver driver_das08 = {
++static struct comedi_driver driver_das08 = {
+       driver_name: DRV_NAME,
+       module:THIS_MODULE,
+       attach:das08_attach,
+diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
+index 0e56f1d762de..310903a89e42 100644
+--- a/drivers/staging/comedi/drivers/das08_cs.c
++++ b/drivers/staging/comedi/drivers/das08_cs.c
+@@ -58,7 +58,7 @@ static struct pcmcia_device *cur_dev = NULL;
+ 
+ static int das08_cs_attach(struct comedi_device * dev, comedi_devconfig * it);
+ 
+-static comedi_driver driver_das08_cs = {
++static struct comedi_driver driver_das08_cs = {
+       driver_name:"das08_cs",
+       module:THIS_MODULE,
+       attach:das08_cs_attach,
+diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
+index 7e51137fcf5c..a0998a2efd62 100644
+--- a/drivers/staging/comedi/drivers/das16.c
++++ b/drivers/staging/comedi/drivers/das16.c
+@@ -700,7 +700,7 @@ static const struct das16_board_struct das16_boards[] = {
+ 
+ static int das16_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int das16_detach(struct comedi_device * dev);
+-static comedi_driver driver_das16 = {
++static struct comedi_driver driver_das16 = {
+       driver_name:"das16",
+       module:THIS_MODULE,
+       attach:das16_attach,
+diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
+index 48211a87961e..d87fd21a3bb6 100644
+--- a/drivers/staging/comedi/drivers/das16m1.c
++++ b/drivers/staging/comedi/drivers/das16m1.c
+@@ -168,7 +168,7 @@ static const das16m1_board das16m1_boards[] = {
+ 
+ static int das16m1_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int das16m1_detach(struct comedi_device * dev);
+-static comedi_driver driver_das16m1 = {
++static struct comedi_driver driver_das16m1 = {
+       driver_name:"das16m1",
+       module:THIS_MODULE,
+       attach:das16m1_attach,
+diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
+index 47d92c70ca0a..2bdb6a33dde4 100644
+--- a/drivers/staging/comedi/drivers/das1800.c
++++ b/drivers/staging/comedi/drivers/das1800.c
+@@ -504,7 +504,7 @@ static const comedi_lrange range_ao_2 = {
+ };
+ */
+ 
+-static comedi_driver driver_das1800 = {
++static struct comedi_driver driver_das1800 = {
+       driver_name:"das1800",
+       module:THIS_MODULE,
+       attach:das1800_attach,
+diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c
+index 6c0a28cb712c..628e11160825 100644
+--- a/drivers/staging/comedi/drivers/das6402.c
++++ b/drivers/staging/comedi/drivers/das6402.c
+@@ -100,7 +100,7 @@ This driver has suffered bitrot.
+ 
+ static int das6402_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int das6402_detach(struct comedi_device * dev);
+-static comedi_driver driver_das6402 = {
++static struct comedi_driver driver_das6402 = {
+       driver_name:"das6402",
+       module:THIS_MODULE,
+       attach:das6402_attach,
+diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
+index 92df82216f3e..83422936021f 100644
+--- a/drivers/staging/comedi/drivers/das800.c
++++ b/drivers/staging/comedi/drivers/das800.c
+@@ -246,7 +246,7 @@ static int das800_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int das800_detach(struct comedi_device * dev);
+ static int das800_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ 
+-static comedi_driver driver_das800 = {
++static struct comedi_driver driver_das800 = {
+       driver_name:"das800",
+       module:THIS_MODULE,
+       attach:das800_attach,
+diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
+index d710dd652053..68c18fff5369 100644
+--- a/drivers/staging/comedi/drivers/dmm32at.c
++++ b/drivers/staging/comedi/drivers/dmm32at.c
+@@ -46,7 +46,7 @@ Configuration Options:
+  * Devices: a full list of the boards that attempt to be supported by
+  *   the driver.  Format is "(manufacturer) board name [comedi name]",
+  *   where comedi_name is the name that is used to configure the board.
+- *   See the comment near board_name: in the comedi_driver structure
++ *   See the comment near board_name: in the struct comedi_driver structure
+  *   below.  If (manufacturer) or [comedi name] is missing, the previous
+  *   value is used.
+  * Author: you
+@@ -253,14 +253,14 @@ typedef struct {
+ #define devpriv ((dmm32at_private *)dev->private)
+ 
+ /*
+- * The comedi_driver structure tells the Comedi core module
++ * The struct comedi_driver structure tells the Comedi core module
+  * which functions to call to configure/deconfigure (attach/detach)
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+ static int dmm32at_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int dmm32at_detach(struct comedi_device * dev);
+-static comedi_driver driver_dmm32at = {
++static struct comedi_driver driver_dmm32at = {
+       driver_name:"dmm32at",
+       module:THIS_MODULE,
+       attach:dmm32at_attach,
+diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c
+index 1f6e4bfa8cd2..944489791da8 100644
+--- a/drivers/staging/comedi/drivers/dt2801.c
++++ b/drivers/staging/comedi/drivers/dt2801.c
+@@ -90,7 +90,7 @@ Configuration options:
+ 
+ static int dt2801_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int dt2801_detach(struct comedi_device * dev);
+-static comedi_driver driver_dt2801 = {
++static struct comedi_driver driver_dt2801 = {
+       driver_name:"dt2801",
+       module:THIS_MODULE,
+       attach:dt2801_attach,
+diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c
+index ca2e83f3630f..8190ae15878a 100644
+--- a/drivers/staging/comedi/drivers/dt2811.c
++++ b/drivers/staging/comedi/drivers/dt2811.c
+@@ -214,7 +214,7 @@ static const boardtype boardtypes[] = {
+ 
+ static int dt2811_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int dt2811_detach(struct comedi_device * dev);
+-static comedi_driver driver_dt2811 = {
++static struct comedi_driver driver_dt2811 = {
+       driver_name:"dt2811",
+       module:THIS_MODULE,
+       attach:dt2811_attach,
+diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c
+index f886d1c376ed..eb46d0f5e0db 100644
+--- a/drivers/staging/comedi/drivers/dt2814.c
++++ b/drivers/staging/comedi/drivers/dt2814.c
+@@ -61,7 +61,7 @@ addition, the clock does not seem to be very accurate.
+ 
+ static int dt2814_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int dt2814_detach(struct comedi_device * dev);
+-static comedi_driver driver_dt2814 = {
++static struct comedi_driver driver_dt2814 = {
+       driver_name:"dt2814",
+       module:THIS_MODULE,
+       attach:dt2814_attach,
+diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c
+index 75b89430be8c..0f45cadca370 100644
+--- a/drivers/staging/comedi/drivers/dt2815.c
++++ b/drivers/staging/comedi/drivers/dt2815.c
+@@ -77,7 +77,7 @@ static const comedi_lrange range_dt2815_ao_20_current = { 1, {
+ 
+ static int dt2815_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int dt2815_detach(struct comedi_device * dev);
+-static comedi_driver driver_dt2815 = {
++static struct comedi_driver driver_dt2815 = {
+       driver_name:"dt2815",
+       module:THIS_MODULE,
+       attach:dt2815_attach,
+diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c
+index 5e012856a58e..203c6b3e8cbf 100644
+--- a/drivers/staging/comedi/drivers/dt2817.c
++++ b/drivers/staging/comedi/drivers/dt2817.c
+@@ -49,7 +49,7 @@ Configuration options:
+ 
+ static int dt2817_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int dt2817_detach(struct comedi_device * dev);
+-static comedi_driver driver_dt2817 = {
++static struct comedi_driver driver_dt2817 = {
+       driver_name:"dt2817",
+       module:THIS_MODULE,
+       attach:dt2817_attach,
+diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
+index 5da648d2399b..bed21029871b 100644
+--- a/drivers/staging/comedi/drivers/dt282x.c
++++ b/drivers/staging/comedi/drivers/dt282x.c
+@@ -396,7 +396,7 @@ typedef struct {
+ 
+ static int dt282x_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int dt282x_detach(struct comedi_device * dev);
+-static comedi_driver driver_dt282x = {
++static struct comedi_driver driver_dt282x = {
+       driver_name:"dt282x",
+       module:THIS_MODULE,
+       attach:dt282x_attach,
+diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
+index add9b11fa157..0e29d7f8c71c 100644
+--- a/drivers/staging/comedi/drivers/dt3000.c
++++ b/drivers/staging/comedi/drivers/dt3000.c
+@@ -273,7 +273,7 @@ typedef struct {
+ 
+ static int dt3000_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int dt3000_detach(struct comedi_device * dev);
+-static comedi_driver driver_dt3000 = {
++static struct comedi_driver driver_dt3000 = {
+       driver_name:"dt3000",
+       module:THIS_MODULE,
+       attach:dt3000_attach,
+diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c
+index 3dd357336fa7..e304a614a97e 100644
+--- a/drivers/staging/comedi/drivers/dt9812.c
++++ b/drivers/staging/comedi/drivers/dt9812.c
+@@ -1108,7 +1108,7 @@ static int dt9812_detach(struct comedi_device *dev)
+ 	return 0;
+ }
+ 
+-static comedi_driver dt9812_comedi_driver = {
++static struct comedi_driver dt9812_comedi_driver = {
+ 	.module = THIS_MODULE,
+ 	.driver_name = "dt9812",
+ 	.attach = dt9812_attach,
+diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c
+index 54f2c2a6c51c..a2f4db9aa4ad 100644
+--- a/drivers/staging/comedi/drivers/fl512.c
++++ b/drivers/staging/comedi/drivers/fl512.c
+@@ -43,7 +43,7 @@ static const comedi_lrange range_fl512 = { 4, {
+ static int fl512_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int fl512_detach(struct comedi_device * dev);
+ 
+-static comedi_driver driver_fl512 = {
++static struct comedi_driver driver_fl512 = {
+       driver_name:"fl512",
+       module:THIS_MODULE,
+       attach:fl512_attach,
+diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
+index aefee40710c1..ccc010f40d47 100644
+--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
++++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
+@@ -327,7 +327,7 @@ static inline hpdi_private *priv(struct comedi_device * dev)
+ 	return dev->private;
+ }
+ 
+-static comedi_driver driver_hpdi = {
++static struct comedi_driver driver_hpdi = {
+       driver_name:"gsc_hpdi",
+       module:THIS_MODULE,
+       attach:hpdi_attach,
+diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
+index ee17c6ce838c..b30318172b28 100644
+--- a/drivers/staging/comedi/drivers/icp_multi.c
++++ b/drivers/staging/comedi/drivers/icp_multi.c
+@@ -173,7 +173,7 @@ static const struct boardtype boardtypes[] = {
+ 
+ #define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype))
+ 
+-static comedi_driver driver_icp_multi = {
++static struct comedi_driver driver_icp_multi = {
+       driver_name:"icp_multi",
+       module : THIS_MODULE,
+       attach : icp_multi_attach,
+diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c
+index df21bf255d02..e1376a173f33 100644
+--- a/drivers/staging/comedi/drivers/ii_pci20kc.c
++++ b/drivers/staging/comedi/drivers/ii_pci20kc.c
+@@ -159,7 +159,7 @@ typedef struct {
+ static int pci20xxx_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int pci20xxx_detach(struct comedi_device * dev);
+ 
+-static comedi_driver driver_pci20xxx = {
++static struct comedi_driver driver_pci20xxx = {
+       driver_name:"ii_pci20kc",
+       module:THIS_MODULE,
+       attach:pci20xxx_attach,
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
+index 44b5c4ff3648..f256b9981c32 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -106,7 +106,7 @@ static int comedi_load_firmware(struct comedi_device * dev,
+ static int jr3_pci_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int jr3_pci_detach(struct comedi_device * dev);
+ 
+-static comedi_driver driver_jr3_pci = {
++static struct comedi_driver driver_jr3_pci = {
+       driver_name:"jr3_pci",
+       module:THIS_MODULE,
+       attach:jr3_pci_attach,
+diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c
+index 08f09ac19d70..5ee1cf51aa13 100644
+--- a/drivers/staging/comedi/drivers/ke_counter.c
++++ b/drivers/staging/comedi/drivers/ke_counter.c
+@@ -86,7 +86,7 @@ typedef struct {
+ 
+ #define devpriv ((cnt_device_private *)dev->private)
+ 
+-static comedi_driver cnt_driver = {
++static struct comedi_driver cnt_driver = {
+       driver_name:CNT_DRIVER_NAME,
+       module:THIS_MODULE,
+       attach:cnt_attach,
+diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
+index 17de86a3988c..095da3f1315d 100644
+--- a/drivers/staging/comedi/drivers/me4000.c
++++ b/drivers/staging/comedi/drivers/me4000.c
+@@ -120,7 +120,7 @@ static const me4000_board_t me4000_boards[] = {
+   ---------------------------------------------------------------------------*/
+ static int me4000_attach(struct comedi_device *dev, comedi_devconfig *it);
+ static int me4000_detach(struct comedi_device *dev);
+-static comedi_driver driver_me4000 = {
++static struct comedi_driver driver_me4000 = {
+       driver_name:"me4000",
+       module : THIS_MODULE,
+       attach : me4000_attach,
+diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c
+index 084b903d0cd6..e47a954f189e 100644
+--- a/drivers/staging/comedi/drivers/me_daq.c
++++ b/drivers/staging/comedi/drivers/me_daq.c
+@@ -246,7 +246,8 @@ static const struct me_board me_boards[] = {
+ 
+ #define me_board_nbr (sizeof(me_boards)/sizeof(struct me_board))
+ 
+-static comedi_driver me_driver = {
++
++static struct comedi_driver me_driver = {
+       .driver_name =	ME_DRIVER_NAME,
+       .module =		THIS_MODULE,
+       .attach =		me_attach,
+diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c
+index 2a30dda24bc4..9b9c8c038dbd 100644
+--- a/drivers/staging/comedi/drivers/mpc624.c
++++ b/drivers/staging/comedi/drivers/mpc624.c
+@@ -147,7 +147,7 @@ static const comedi_lrange range_mpc624_bipolar10 = {
+ static int mpc624_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int mpc624_detach(struct comedi_device * dev);
+ //----------------------------------------------------------------------------
+-static comedi_driver driver_mpc624 = {
++static struct comedi_driver driver_mpc624 = {
+       driver_name:"mpc624",
+       module:THIS_MODULE,
+       attach:mpc624_attach,
+diff --git a/drivers/staging/comedi/drivers/mpc8260cpm.c b/drivers/staging/comedi/drivers/mpc8260cpm.c
+index 40057a0b8f97..9588f2652d22 100644
+--- a/drivers/staging/comedi/drivers/mpc8260cpm.c
++++ b/drivers/staging/comedi/drivers/mpc8260cpm.c
+@@ -46,7 +46,7 @@ typedef struct {
+ 
+ static int mpc8260cpm_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int mpc8260cpm_detach(struct comedi_device * dev);
+-static comedi_driver driver_mpc8260cpm = {
++static struct comedi_driver driver_mpc8260cpm = {
+       driver_name:"mpc8260cpm",
+       module:THIS_MODULE,
+       attach:mpc8260cpm_attach,
+diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c
+index 151d6d4bdde4..186676e5f86d 100644
+--- a/drivers/staging/comedi/drivers/multiq3.c
++++ b/drivers/staging/comedi/drivers/multiq3.c
+@@ -84,7 +84,7 @@ Devices: [Quanser Consulting] MultiQ-3 (multiq3)
+ 
+ static int multiq3_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int multiq3_detach(struct comedi_device * dev);
+-static comedi_driver driver_multiq3 = {
++static struct comedi_driver driver_multiq3 = {
+       driver_name:"multiq3",
+       module:THIS_MODULE,
+       attach:multiq3_attach,
+diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
+index 453588813293..7879f8675820 100644
+--- a/drivers/staging/comedi/drivers/ni_6527.c
++++ b/drivers/staging/comedi/drivers/ni_6527.c
+@@ -77,7 +77,7 @@ Updated: Sat, 25 Jan 2003 13:24:40 -0800
+ 
+ static int ni6527_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int ni6527_detach(struct comedi_device * dev);
+-static comedi_driver driver_ni6527 = {
++static struct comedi_driver driver_ni6527 = {
+       driver_name:"ni6527",
+       module:THIS_MODULE,
+       attach:ni6527_attach,
+diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
+index c12dcb6cae60..b89543115c27 100644
+--- a/drivers/staging/comedi/drivers/ni_65xx.c
++++ b/drivers/staging/comedi/drivers/ni_65xx.c
+@@ -104,7 +104,7 @@ static inline unsigned Filter_Enable(unsigned port)
+ 
+ static int ni_65xx_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int ni_65xx_detach(struct comedi_device * dev);
+-static comedi_driver driver_ni_65xx = {
++static struct comedi_driver driver_ni_65xx = {
+       driver_name:"ni_65xx",
+       module:THIS_MODULE,
+       attach:ni_65xx_attach,
+diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
+index 3304472d0a76..469f9553f034 100644
+--- a/drivers/staging/comedi/drivers/ni_660x.c
++++ b/drivers/staging/comedi/drivers/ni_660x.c
+@@ -450,7 +450,7 @@ static void init_tio_chip(struct comedi_device * dev, int chipset);
+ static void ni_660x_select_pfi_output(struct comedi_device * dev, unsigned pfi_channel,
+ 	unsigned output_select);
+ 
+-static comedi_driver driver_ni_660x = {
++static struct comedi_driver driver_ni_660x = {
+       driver_name:"ni_660x",
+       module:THIS_MODULE,
+       attach:ni_660x_attach,
+diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
+index 0bcbfd1cd5ba..7dbbfdcb1973 100644
+--- a/drivers/staging/comedi/drivers/ni_670x.c
++++ b/drivers/staging/comedi/drivers/ni_670x.c
+@@ -111,7 +111,7 @@ typedef struct {
+ static int ni_670x_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int ni_670x_detach(struct comedi_device * dev);
+ 
+-static comedi_driver driver_ni_670x = {
++static struct comedi_driver driver_ni_670x = {
+       driver_name:"ni_670x",
+       module:THIS_MODULE,
+       attach:ni_670x_attach,
+diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
+index c15568d3cd46..87edc61f6a4e 100644
+--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
++++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
+@@ -171,7 +171,7 @@ static int a2150_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int a2150_detach(struct comedi_device * dev);
+ static int a2150_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ 
+-static comedi_driver driver_a2150 = {
++static struct comedi_driver driver_a2150 = {
+       driver_name:"ni_at_a2150",
+       module:THIS_MODULE,
+       attach:a2150_attach,
+diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c
+index e5083a2111c3..2176bb2d743d 100644
+--- a/drivers/staging/comedi/drivers/ni_at_ao.c
++++ b/drivers/staging/comedi/drivers/ni_at_ao.c
+@@ -180,7 +180,7 @@ typedef struct {
+ 
+ static int atao_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int atao_detach(struct comedi_device * dev);
+-static comedi_driver driver_atao = {
++static struct comedi_driver driver_atao = {
+       driver_name:"ni_at_ao",
+       module:THIS_MODULE,
+       attach:atao_attach,
+diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c
+index 0e30050b91e6..d5baaa1ca3ff 100644
+--- a/drivers/staging/comedi/drivers/ni_atmio.c
++++ b/drivers/staging/comedi/drivers/ni_atmio.c
+@@ -340,7 +340,7 @@ MODULE_DEVICE_TABLE(pnp, device_ids);
+ 
+ static int ni_atmio_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int ni_atmio_detach(struct comedi_device * dev);
+-static comedi_driver driver_atmio = {
++static struct comedi_driver driver_atmio = {
+       driver_name:"ni_atmio",
+       module:THIS_MODULE,
+       attach:ni_atmio_attach,
+diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
+index 9c59c51863fe..592922aad85c 100644
+--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
++++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
+@@ -134,7 +134,7 @@ static void reset_counters(struct comedi_device * dev);
+ static void reset_atmio16d(struct comedi_device * dev);
+ 
+ /* main driver struct */
+-static comedi_driver driver_atmio16d = {
++static struct comedi_driver driver_atmio16d = {
+       driver_name:"atmio16",
+       module:THIS_MODULE,
+       attach:atmio16d_attach,
+diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
+index 8a0a5fa50eee..ea906a7fef14 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_700.c
++++ b/drivers/staging/comedi/drivers/ni_daq_700.c
+@@ -97,7 +97,7 @@ typedef struct {
+ 
+ #define devpriv ((dio700_private *)dev->private)
+ 
+-static comedi_driver driver_dio700 = {
++static struct comedi_driver driver_dio700 = {
+       driver_name:"ni_daq_700",
+       module:THIS_MODULE,
+       attach:dio700_attach,
+diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
+index f2c73a4af068..5783a8f57730 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
++++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
+@@ -97,7 +97,7 @@ typedef struct {
+ 
+ #define devpriv ((dio24_private *)dev->private)
+ 
+-static comedi_driver driver_dio24 = {
++static struct comedi_driver driver_dio24 = {
+       driver_name:"ni_daq_dio24",
+       module:THIS_MODULE,
+       attach:dio24_attach,
+diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
+index 6ba97da42def..e1326a35e78c 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc.c
++++ b/drivers/staging/comedi/drivers/ni_labpc.c
+@@ -429,7 +429,7 @@ static const int sample_size = 2;	// 2 bytes per sample
+ 
+ #define devpriv ((labpc_private *)dev->private)
+ 
+-static comedi_driver driver_labpc = {
++static struct comedi_driver driver_labpc = {
+ 	.driver_name = DRV_NAME,
+ 	.module = THIS_MODULE,
+ 	.attach = labpc_attach,
+diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
+index f41d39b75df9..f94cde904dd7 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
++++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
+@@ -116,7 +116,7 @@ static const labpc_board labpc_cs_boards[] = {
+  */
+ #define thisboard ((const labpc_board *)dev->board_ptr)
+ 
+-static comedi_driver driver_labpc_cs = {
++static struct comedi_driver driver_labpc_cs = {
+ 	.driver_name = "ni_labpc_cs",
+ 	.module = THIS_MODULE,
+ 	.attach = &labpc_attach,
+diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c
+index 4891bc2805f8..c3dad5937e05 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_cs.c
++++ b/drivers/staging/comedi/drivers/ni_mio_cs.c
+@@ -227,7 +227,7 @@ static uint16_t mio_cs_win_in(struct comedi_device * dev, int addr)
+ 
+ static int mio_cs_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int mio_cs_detach(struct comedi_device * dev);
+-static comedi_driver driver_ni_mio_cs = {
++static struct comedi_driver driver_ni_mio_cs = {
+       driver_name:"ni_mio_cs",
+       module:THIS_MODULE,
+       attach:mio_cs_attach,
+diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
+index d75939bcca17..5b0f2b61b1ee 100644
+--- a/drivers/staging/comedi/drivers/ni_pcidio.c
++++ b/drivers/staging/comedi/drivers/ni_pcidio.c
+@@ -291,7 +291,7 @@ static int nidio_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int nidio_detach(struct comedi_device * dev);
+ static int ni_pcidio_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ 
+-static comedi_driver driver_pcidio = {
++static struct comedi_driver driver_pcidio = {
+       driver_name:"ni_pcidio",
+       module:THIS_MODULE,
+       attach:nidio_attach,
+diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
+index 105dab0758f1..173d0a57245a 100644
+--- a/drivers/staging/comedi/drivers/ni_pcimio.c
++++ b/drivers/staging/comedi/drivers/ni_pcimio.c
+@@ -1209,7 +1209,7 @@ static const ni_board ni_boards[] = {
+ 
+ static int pcimio_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int pcimio_detach(struct comedi_device * dev);
+-static comedi_driver driver_pcimio = {
++static struct comedi_driver driver_pcimio = {
+ 	driver_name: DRV_NAME,
+ 	module:THIS_MODULE,
+ 	attach:pcimio_attach,
+diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c
+index 4261fcc85adf..e2f73ca1aa15 100644
+--- a/drivers/staging/comedi/drivers/pcl711.c
++++ b/drivers/staging/comedi/drivers/pcl711.c
+@@ -156,7 +156,7 @@ static const boardtype boardtypes[] = {
+ 
+ static int pcl711_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int pcl711_detach(struct comedi_device * dev);
+-static comedi_driver driver_pcl711 = {
++static struct comedi_driver driver_pcl711 = {
+       driver_name:"pcl711",
+       module:THIS_MODULE,
+       attach:pcl711_attach,
+diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c
+index a65bcfb1043b..b9af0c045e7c 100644
+--- a/drivers/staging/comedi/drivers/pcl724.c
++++ b/drivers/staging/comedi/drivers/pcl724.c
+@@ -81,7 +81,7 @@ static const boardtype boardtypes[] = {
+ #define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+ #define this_board ((const boardtype *)dev->board_ptr)
+ 
+-static comedi_driver driver_pcl724 = {
++static struct comedi_driver driver_pcl724 = {
+       driver_name:"pcl724",
+       module:THIS_MODULE,
+       attach:pcl724_attach,
+diff --git a/drivers/staging/comedi/drivers/pcl725.c b/drivers/staging/comedi/drivers/pcl725.c
+index a2ea3e154bb2..570193598d98 100644
+--- a/drivers/staging/comedi/drivers/pcl725.c
++++ b/drivers/staging/comedi/drivers/pcl725.c
+@@ -22,7 +22,7 @@ Devices: [Advantech] PCL-725 (pcl725)
+ 
+ static int pcl725_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int pcl725_detach(struct comedi_device * dev);
+-static comedi_driver driver_pcl725 = {
++static struct comedi_driver driver_pcl725 = {
+       driver_name:"pcl725",
+       module:THIS_MODULE,
+       attach:pcl725_attach,
+diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c
+index 23e98550c58b..f63b60f6f7d4 100644
+--- a/drivers/staging/comedi/drivers/pcl726.c
++++ b/drivers/staging/comedi/drivers/pcl726.c
+@@ -149,7 +149,7 @@ static const boardtype boardtypes[] = {
+ #define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+ #define this_board ((const boardtype *)dev->board_ptr)
+ 
+-static comedi_driver driver_pcl726 = {
++static struct comedi_driver driver_pcl726 = {
+       driver_name:"pcl726",
+       module:THIS_MODULE,
+       attach:pcl726_attach,
+diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c
+index 974f96cfcf45..63b4a35159a8 100644
+--- a/drivers/staging/comedi/drivers/pcl730.c
++++ b/drivers/staging/comedi/drivers/pcl730.c
+@@ -43,7 +43,7 @@ static const boardtype boardtypes[] = {
+ #define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+ #define this_board ((const boardtype *)dev->board_ptr)
+ 
+-static comedi_driver driver_pcl730 = {
++static struct comedi_driver driver_pcl730 = {
+       driver_name:"pcl730",
+       module:THIS_MODULE,
+       attach:pcl730_attach,
+diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
+index b678dd6dd73f..a44f1fb3af54 100644
+--- a/drivers/staging/comedi/drivers/pcl812.c
++++ b/drivers/staging/comedi/drivers/pcl812.c
+@@ -374,7 +374,7 @@ static const boardtype boardtypes[] = {
+ #define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+ #define this_board ((const boardtype *)dev->board_ptr)
+ 
+-static comedi_driver driver_pcl812 = {
++static struct comedi_driver driver_pcl812 = {
+       driver_name:"pcl812",
+       module:THIS_MODULE,
+       attach:pcl812_attach,
+diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
+index f1282c68d7ef..c5a969898c12 100644
+--- a/drivers/staging/comedi/drivers/pcl816.c
++++ b/drivers/staging/comedi/drivers/pcl816.c
+@@ -154,7 +154,7 @@ static int RTC_lock = 0;	/* RTC lock */
+ static int RTC_timer_lock = 0;	/* RTC int lock */
+ #endif
+ 
+-static comedi_driver driver_pcl816 = {
++static struct comedi_driver driver_pcl816 = {
+       driver_name:"pcl816",
+       module:THIS_MODULE,
+       attach:pcl816_attach,
+diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
+index d202022c1be6..afe326e7d98c 100644
+--- a/drivers/staging/comedi/drivers/pcl818.c
++++ b/drivers/staging/comedi/drivers/pcl818.c
+@@ -299,7 +299,7 @@ static const boardtype boardtypes[] = {
+ 
+ #define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+ 
+-static comedi_driver driver_pcl818 = {
++static struct comedi_driver driver_pcl818 = {
+       driver_name:"pcl818",
+       module:THIS_MODULE,
+       attach:pcl818_attach,
+diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c
+index dedf92c6a149..5d965466f0f2 100644
+--- a/drivers/staging/comedi/drivers/pcm3724.c
++++ b/drivers/staging/comedi/drivers/pcm3724.c
+@@ -85,7 +85,7 @@ static const boardtype boardtypes[] = {
+ #define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+ #define this_board ((const boardtype *)dev->board_ptr)
+ 
+-static comedi_driver driver_pcm3724 = {
++static struct comedi_driver driver_pcm3724 = {
+       driver_name:"pcm3724",
+       module:THIS_MODULE,
+       attach:pcm3724_attach,
+diff --git a/drivers/staging/comedi/drivers/pcm3730.c b/drivers/staging/comedi/drivers/pcm3730.c
+index e89b3c7ea550..b505a015be06 100644
+--- a/drivers/staging/comedi/drivers/pcm3730.c
++++ b/drivers/staging/comedi/drivers/pcm3730.c
+@@ -30,7 +30,7 @@ Configuration options:
+ 
+ static int pcm3730_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int pcm3730_detach(struct comedi_device * dev);
+-static comedi_driver driver_pcm3730 = {
++static struct comedi_driver driver_pcm3730 = {
+       driver_name:"pcm3730",
+       module:THIS_MODULE,
+       attach:pcm3730_attach,
+diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c
+index 5cb0e59cb216..b129a473587b 100644
+--- a/drivers/staging/comedi/drivers/pcmad.c
++++ b/drivers/staging/comedi/drivers/pcmad.c
+@@ -78,7 +78,7 @@ struct pcmad_priv_struct {
+ 
+ static int pcmad_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int pcmad_detach(struct comedi_device * dev);
+-static comedi_driver driver_pcmad = {
++static struct comedi_driver driver_pcmad = {
+       driver_name:"pcmad",
+       module:THIS_MODULE,
+       attach:pcmad_attach,
+diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c
+index 32cfc35daee2..a2dfb4bf65f8 100644
+--- a/drivers/staging/comedi/drivers/pcmda12.c
++++ b/drivers/staging/comedi/drivers/pcmda12.c
+@@ -100,7 +100,7 @@ typedef struct {
+ #define devpriv ((pcmda12_private *)(dev->private))
+ 
+ /*
+- * The comedi_driver structure tells the Comedi core module
++ * The struct comedi_driver structure tells the Comedi core module
+  * which functions to call to configure/deconfigure (attach/detach)
+  * the board, and also about the kernel module that contains
+  * the device code.
+@@ -110,7 +110,7 @@ static int pcmda12_detach(struct comedi_device * dev);
+ 
+ static void zero_chans(struct comedi_device * dev);
+ 
+-static comedi_driver driver = {
++static struct comedi_driver driver = {
+       driver_name:"pcmda12",
+       module:THIS_MODULE,
+       attach:pcmda12_attach,
+diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
+index 6af8637880c0..0dcc09982fa6 100644
+--- a/drivers/staging/comedi/drivers/pcmmio.c
++++ b/drivers/staging/comedi/drivers/pcmmio.c
+@@ -259,7 +259,7 @@ typedef struct {
+ #define devpriv ((pcmmio_private *)dev->private)
+ #define subpriv ((pcmmio_subdev_private *)s->private)
+ /*
+- * The comedi_driver structure tells the Comedi core module
++ * The struct comedi_driver structure tells the Comedi core module
+  * which functions to call to configure/deconfigure (attach/detach)
+  * the board, and also about the kernel module that contains
+  * the device code.
+@@ -267,7 +267,7 @@ typedef struct {
+ static int pcmmio_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int pcmmio_detach(struct comedi_device * dev);
+ 
+-static comedi_driver driver = {
++static struct comedi_driver driver = {
+       driver_name:"pcmmio",
+       module:THIS_MODULE,
+       attach:pcmmio_attach,
+diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
+index 6dc42eb047d3..7204084073f0 100644
+--- a/drivers/staging/comedi/drivers/pcmuio.c
++++ b/drivers/staging/comedi/drivers/pcmuio.c
+@@ -217,7 +217,7 @@ typedef struct {
+ #define devpriv ((pcmuio_private *)dev->private)
+ #define subpriv ((pcmuio_subdev_private *)s->private)
+ /*
+- * The comedi_driver structure tells the Comedi core module
++ * The struct comedi_driver structure tells the Comedi core module
+  * which functions to call to configure/deconfigure (attach/detach)
+  * the board, and also about the kernel module that contains
+  * the device code.
+@@ -225,7 +225,7 @@ typedef struct {
+ static int pcmuio_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int pcmuio_detach(struct comedi_device * dev);
+ 
+-static comedi_driver driver = {
++static struct comedi_driver driver = {
+       driver_name:"pcmuio",
+       module:THIS_MODULE,
+       attach:pcmuio_attach,
+diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c
+index 5fc566f4aaa3..dde46b126312 100644
+--- a/drivers/staging/comedi/drivers/poc.c
++++ b/drivers/staging/comedi/drivers/poc.c
+@@ -103,7 +103,7 @@ static const struct boarddef_struct boards[] = {
+ #define n_boards (sizeof(boards)/sizeof(boards[0]))
+ #define this_board ((const struct boarddef_struct *)dev->board_ptr)
+ 
+-static comedi_driver driver_poc = {
++static struct comedi_driver driver_poc = {
+       driver_name:"poc",
+       module:THIS_MODULE,
+       attach:poc_attach,
+diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+index a3bfa6465b56..c30b1ccb2903 100644
+--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
++++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+@@ -199,7 +199,7 @@ static const comedi_lrange range_daqp_ao = { 1, {BIP_RANGE(5)} };
+ 
+ static int daqp_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int daqp_detach(struct comedi_device * dev);
+-static comedi_driver driver_daqp = {
++static struct comedi_driver driver_daqp = {
+       driver_name:"quatech_daqp_cs",
+       module:THIS_MODULE,
+       attach:daqp_attach,
+diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
+index 405c2040a881..c238f5b97d85 100644
+--- a/drivers/staging/comedi/drivers/rtd520.c
++++ b/drivers/staging/comedi/drivers/rtd520.c
+@@ -675,7 +675,7 @@ struct rtdPrivate {
+     readb (devpriv->lcfg+LCFG_DMACSR1)
+ 
+ /*
+- * The comedi_driver structure tells the Comedi core module
++ * The struct comedi_driver structure tells the Comedi core module
+  * which functions to call to configure/deconfigure (attac/detach)
+  * the board, and also about the kernel module that contains
+  * the device code.
+@@ -683,7 +683,7 @@ struct rtdPrivate {
+ static int rtd_attach(struct comedi_device *dev, comedi_devconfig *it);
+ static int rtd_detach(struct comedi_device *dev);
+ 
+-static comedi_driver rtd520Driver = {
++static struct comedi_driver rtd520Driver = {
+       driver_name: DRV_NAME,
+       module : THIS_MODULE,
+       attach : rtd_attach,
+diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c
+index 3525813b9bf3..0d2e9ff4f4f6 100644
+--- a/drivers/staging/comedi/drivers/rti800.c
++++ b/drivers/staging/comedi/drivers/rti800.c
+@@ -131,7 +131,7 @@ static const boardtype boardtypes[] = {
+ 
+ static int rti800_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int rti800_detach(struct comedi_device * dev);
+-static comedi_driver driver_rti800 = {
++static struct comedi_driver driver_rti800 = {
+       driver_name:"rti800",
+       module:THIS_MODULE,
+       attach:rti800_attach,
+diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c
+index 0985c858cb2f..0d2d1c310d03 100644
+--- a/drivers/staging/comedi/drivers/rti802.c
++++ b/drivers/staging/comedi/drivers/rti802.c
+@@ -49,7 +49,7 @@ Configuration Options:
+ 
+ static int rti802_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int rti802_detach(struct comedi_device * dev);
+-static comedi_driver driver_rti802 = {
++static struct comedi_driver driver_rti802 = {
+       driver_name:"rti802",
+       module:THIS_MODULE,
+       attach:rti802_attach,
+diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
+index 51ff5a7e5639..d3881498e164 100644
+--- a/drivers/staging/comedi/drivers/s526.c
++++ b/drivers/staging/comedi/drivers/s526.c
+@@ -210,14 +210,14 @@ typedef struct {
+ #define devpriv ((s526_private *)dev->private)
+ 
+ /*
+- * The comedi_driver structure tells the Comedi core module
++ * The struct comedi_driver structure tells the Comedi core module
+  * which functions to call to configure/deconfigure (attach/detach)
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+ static int s526_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int s526_detach(struct comedi_device * dev);
+-static comedi_driver driver_s526 = {
++static struct comedi_driver driver_s526 = {
+       driver_name:"s526",
+       module:THIS_MODULE,
+       attach:s526_attach,
+diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
+index 4bba963cd537..ac6424ca25da 100644
+--- a/drivers/staging/comedi/drivers/s626.c
++++ b/drivers/staging/comedi/drivers/s626.c
+@@ -121,7 +121,7 @@ MODULE_DEVICE_TABLE(pci, s626_pci_table);
+ static int s626_attach(struct comedi_device *dev, comedi_devconfig *it);
+ static int s626_detach(struct comedi_device *dev);
+ 
+-static comedi_driver driver_s626 = {
++static struct comedi_driver driver_s626 = {
+       driver_name:"s626",
+       module : THIS_MODULE,
+       attach : s626_attach,
+diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
+index c23a4322c1a8..7c056a328c0d 100644
+--- a/drivers/staging/comedi/drivers/serial2002.c
++++ b/drivers/staging/comedi/drivers/serial2002.c
+@@ -87,7 +87,7 @@ typedef struct {
+ 
+ static int serial2002_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int serial2002_detach(struct comedi_device * dev);
+-comedi_driver driver_serial2002 = {
++struct comedi_driver driver_serial2002 = {
+       driver_name:"serial2002",
+       module:THIS_MODULE,
+       attach:serial2002_attach,
+diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c
+index 13b14454f59a..5dda0cd6c990 100644
+--- a/drivers/staging/comedi/drivers/skel.c
++++ b/drivers/staging/comedi/drivers/skel.c
+@@ -44,7 +44,7 @@ Configuration Options:
+  * Devices: a full list of the boards that attempt to be supported by
+  *   the driver.  Format is "(manufacturer) board name [comedi name]",
+  *   where comedi_name is the name that is used to configure the board.
+- *   See the comment near board_name: in the comedi_driver structure
++ *   See the comment near board_name: in the struct comedi_driver structure
+  *   below.  If (manufacturer) or [comedi name] is missing, the previous
+  *   value is used.
+  * Author: you
+@@ -146,14 +146,14 @@ typedef struct {
+ #define devpriv ((skel_private *)dev->private)
+ 
+ /*
+- * The comedi_driver structure tells the Comedi core module
++ * The struct comedi_driver structure tells the Comedi core module
+  * which functions to call to configure/deconfigure (attach/detach)
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+ static int skel_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int skel_detach(struct comedi_device * dev);
+-static comedi_driver driver_skel = {
++static struct comedi_driver driver_skel = {
+       driver_name:"dummy",
+       module:THIS_MODULE,
+       attach:skel_attach,
+diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c
+index db31c2066aec..a5fda67f4a6a 100644
+--- a/drivers/staging/comedi/drivers/ssv_dnp.c
++++ b/drivers/staging/comedi/drivers/ssv_dnp.c
+@@ -80,7 +80,7 @@ typedef struct {
+ #define devpriv ((dnp_private *)dev->private)
+ 
+ /* ------------------------------------------------------------------------- */
+-/* The comedi_driver structure tells the Comedi core module which functions  */
++/* The struct comedi_driver structure tells the Comedi core module which functions  */
+ /* to call to configure/deconfigure (attach/detach) the board, and also      */
+ /* about the kernel module that contains the device code.                    */
+ /*                                                                           */
+@@ -90,7 +90,7 @@ typedef struct {
+ static int dnp_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int dnp_detach(struct comedi_device * dev);
+ 
+-static comedi_driver driver_dnp = {
++static struct comedi_driver driver_dnp = {
+       driver_name:"ssv_dnp",
+       module:THIS_MODULE,
+       attach:dnp_attach,
+diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c
+index 34c44718b522..bc5511d03ced 100644
+--- a/drivers/staging/comedi/drivers/unioxx5.c
++++ b/drivers/staging/comedi/drivers/unioxx5.c
+@@ -102,7 +102,7 @@ static int __unioxx5_analog_read(unioxx5_subd_priv * usp, unsigned int * data,
+ static int __unioxx5_define_chan_offset(int chan_num);
+ static void __unioxx5_analog_config(unioxx5_subd_priv * usp, int channel);
+ 
+-static comedi_driver unioxx5_driver = {
++static struct comedi_driver unioxx5_driver = {
+       driver_name:DRIVER_NAME,
+       module:THIS_MODULE,
+       attach:unioxx5_attach,
+diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
+index 41872a3a68b2..e3462c4a5a65 100644
+--- a/drivers/staging/comedi/drivers/usbdux.c
++++ b/drivers/staging/comedi/drivers/usbdux.c
+@@ -2903,7 +2903,7 @@ static int usbdux_detach(struct comedi_device *dev)
+ }
+ 
+ /* main driver struct */
+-static comedi_driver driver_usbdux = {
++static struct comedi_driver driver_usbdux = {
+       .driver_name =	"usbdux",
+       .module =		THIS_MODULE,
+       .attach =		usbdux_attach,
+diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c
+index e141484f11ae..54b49580505a 100644
+--- a/drivers/staging/comedi/drivers/usbduxfast.c
++++ b/drivers/staging/comedi/drivers/usbduxfast.c
+@@ -1856,7 +1856,7 @@ static int usbduxfast_detach(struct comedi_device *dev)
+ /*
+  * main driver struct
+  */
+-static comedi_driver driver_usbduxfast = {
++static struct comedi_driver driver_usbduxfast = {
+ 	.driver_name	= "usbduxfast",
+ 	.module		= THIS_MODULE,
+ 	.attach		= usbduxfast_attach,
+diff --git a/drivers/staging/comedi/proc.c b/drivers/staging/comedi/proc.c
+index bb208f852a00..36ae2cd92ad9 100644
+--- a/drivers/staging/comedi/proc.c
++++ b/drivers/staging/comedi/proc.c
+@@ -36,7 +36,7 @@
+ int comedi_read_procmem(char *buf, char **start, off_t offset, int len,
+ 	int *eof, void *data);
+ 
+-extern comedi_driver *comedi_drivers;
++extern struct comedi_driver *comedi_drivers;
+ 
+ int comedi_read_procmem(char *buf, char **start, off_t offset, int len,
+ 	int *eof, void *data)
+@@ -44,7 +44,7 @@ int comedi_read_procmem(char *buf, char **start, off_t offset, int len,
+ 	int i;
+ 	int devices_q = 0;
+ 	int l = 0;
+-	comedi_driver *driv;
++	struct comedi_driver *driv;
+ 
+ 	l += sprintf(buf + l,
+ 		"comedi version " COMEDI_RELEASE "\n"

commit d163679ceec20c50f9aee880fa76c0c1185244a8
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:05:20 2009 -0400
+
+    Staging: comedi: Remove comedi_async typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
+index eac18a742b22..d38addd01d4a 100644
+--- a/drivers/staging/comedi/comedi_fops.c
++++ b/drivers/staging/comedi/comedi_fops.c
+@@ -275,7 +275,7 @@ static int do_devconfig_ioctl(struct comedi_device *dev, comedi_devconfig *arg)
+ static int do_bufconfig_ioctl(struct comedi_device *dev, void *arg)
+ {
+ 	comedi_bufconfig bc;
+-	comedi_async *async;
++	struct comedi_async *async;
+ 	struct comedi_subdevice *s;
+ 	int ret = 0;
+ 
+@@ -558,7 +558,7 @@ static int do_bufinfo_ioctl(struct comedi_device *dev, void *arg)
+ {
+ 	comedi_bufinfo bi;
+ 	struct comedi_subdevice *s;
+-	comedi_async *async;
++	struct comedi_async *async;
+ 
+ 	if (copy_from_user(&bi, arg, sizeof(comedi_bufinfo)))
+ 		return -EFAULT;
+@@ -979,7 +979,7 @@ static int do_cmd_ioctl(struct comedi_device *dev, void *arg, void *file)
+ {
+ 	comedi_cmd user_cmd;
+ 	struct comedi_subdevice *s;
+-	comedi_async *async;
++	struct comedi_async *async;
+ 	int ret = 0;
+ 	unsigned int *chanlist_saver = NULL;
+ 
+@@ -1384,7 +1384,7 @@ static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ 
+ void comedi_unmap(struct vm_area_struct *area)
+ {
+-	comedi_async *async;
++	struct comedi_async *async;
+ 	struct comedi_device *dev;
+ 
+ 	async = area->vm_private_data;
+@@ -1405,7 +1405,7 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
+ 	struct comedi_device_file_info *dev_file_info =
+ 	    comedi_get_device_file_info(minor);
+ 	struct comedi_device *dev = dev_file_info->device;
+-	comedi_async *async = NULL;
++	struct comedi_async *async = NULL;
+ 	unsigned long start = vma->vm_start;
+ 	unsigned long size;
+ 	int n_pages;
+@@ -1524,7 +1524,7 @@ static ssize_t comedi_write(struct file *file, const char *buf, size_t nbytes,
+ 			    loff_t *offset)
+ {
+ 	struct comedi_subdevice *s;
+-	comedi_async *async;
++	struct comedi_async *async;
+ 	int n, m, count = 0, retval = 0;
+ 	DECLARE_WAITQUEUE(wait, current);
+ 	const unsigned minor = iminor(file->f_dentry->d_inode);
+@@ -1626,7 +1626,7 @@ static ssize_t comedi_read(struct file *file, char *buf, size_t nbytes,
+ 			   loff_t *offset)
+ {
+ 	struct comedi_subdevice *s;
+-	comedi_async *async;
++	struct comedi_async *async;
+ 	int n, m, count = 0, retval = 0;
+ 	DECLARE_WAITQUEUE(wait, current);
+ 	const unsigned minor = iminor(file->f_dentry->d_inode);
+@@ -1735,7 +1735,7 @@ static ssize_t comedi_read(struct file *file, char *buf, size_t nbytes,
+  */
+ void do_become_nonbusy(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 
+ 	comedi_set_subdevice_runflags(s, SRF_RUNNING, 0);
+ #ifdef CONFIG_COMEDI_RT
+@@ -2008,7 +2008,7 @@ void comedi_error(const struct comedi_device *dev, const char *s)
+ 
+ void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	unsigned runflags = 0;
+ 	unsigned runflags_mask = 0;
+ 
+diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
+index 4fba9e7d437e..1fdb093f9318 100644
+--- a/drivers/staging/comedi/comedidev.h
++++ b/drivers/staging/comedi/comedidev.h
+@@ -121,7 +121,6 @@
+ #define COMEDI_NUM_BOARD_MINORS 0x30
+ #define COMEDI_FIRST_SUBDEVICE_MINOR COMEDI_NUM_BOARD_MINORS
+ 
+-typedef struct comedi_async_struct comedi_async;
+ typedef struct comedi_driver_struct comedi_driver;
+ typedef struct comedi_lrange_struct comedi_lrange;
+ 
+@@ -139,7 +138,7 @@ struct comedi_subdevice {
+ 
+ 	void *private;
+ 
+-	comedi_async *async;
++	struct comedi_async *async;
+ 
+ 	void *lock;
+ 	void *busy;
+@@ -196,7 +195,7 @@ struct comedi_buf_page {
+ 	dma_addr_t dma_addr;
+ };
+ 
+-struct comedi_async_struct {
++struct comedi_async {
+ 	struct comedi_subdevice *subdevice;
+ 
+ 	void *prealloc_buf;	/* pre-allocated buffer */
+@@ -469,31 +468,31 @@ static inline void comedi_set_hw_dev(struct comedi_device *dev, struct device *h
+ 	}
+ }
+ 
+-int comedi_buf_put(comedi_async *async, short x);
+-int comedi_buf_get(comedi_async *async, short *x);
++int comedi_buf_put(struct comedi_async *async, short x);
++int comedi_buf_get(struct comedi_async *async, short *x);
+ 
+-unsigned int comedi_buf_write_n_available(comedi_async *async);
+-unsigned int comedi_buf_write_alloc(comedi_async *async, unsigned int nbytes);
+-unsigned int comedi_buf_write_alloc_strict(comedi_async *async,
++unsigned int comedi_buf_write_n_available(struct comedi_async *async);
++unsigned int comedi_buf_write_alloc(struct comedi_async *async, unsigned int nbytes);
++unsigned int comedi_buf_write_alloc_strict(struct comedi_async *async,
+ 	unsigned int nbytes);
+-unsigned comedi_buf_write_free(comedi_async *async, unsigned int nbytes);
+-unsigned comedi_buf_read_alloc(comedi_async *async, unsigned nbytes);
+-unsigned comedi_buf_read_free(comedi_async *async, unsigned int nbytes);
+-unsigned int comedi_buf_read_n_available(comedi_async *async);
+-void comedi_buf_memcpy_to(comedi_async *async, unsigned int offset,
++unsigned comedi_buf_write_free(struct comedi_async *async, unsigned int nbytes);
++unsigned comedi_buf_read_alloc(struct comedi_async *async, unsigned nbytes);
++unsigned comedi_buf_read_free(struct comedi_async *async, unsigned int nbytes);
++unsigned int comedi_buf_read_n_available(struct comedi_async *async);
++void comedi_buf_memcpy_to(struct comedi_async *async, unsigned int offset,
+ 	const void *source, unsigned int num_bytes);
+-void comedi_buf_memcpy_from(comedi_async *async, unsigned int offset,
++void comedi_buf_memcpy_from(struct comedi_async *async, unsigned int offset,
+ 	void *destination, unsigned int num_bytes);
+-static inline unsigned comedi_buf_write_n_allocated(comedi_async *async)
++static inline unsigned comedi_buf_write_n_allocated(struct comedi_async *async)
+ {
+ 	return async->buf_write_alloc_count - async->buf_write_count;
+ }
+-static inline unsigned comedi_buf_read_n_allocated(comedi_async *async)
++static inline unsigned comedi_buf_read_n_allocated(struct comedi_async *async)
+ {
+ 	return async->buf_read_alloc_count - async->buf_read_count;
+ }
+ 
+-void comedi_reset_async_buf(comedi_async *async);
++void comedi_reset_async_buf(struct comedi_async *async);
+ 
+ static inline void *comedi_aux_data(int options[], int n)
+ {
+diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
+index 32f3aca2d7f4..30e3beb6e97b 100644
+--- a/drivers/staging/comedi/drivers.c
++++ b/drivers/staging/comedi/drivers.c
+@@ -228,7 +228,7 @@ static int postconfig(struct comedi_device *dev)
+ {
+ 	int i;
+ 	struct comedi_subdevice *s;
+-	comedi_async *async = NULL;
++	struct comedi_async *async = NULL;
+ 	int ret;
+ 
+ 	for (i = 0; i < dev->n_subdevices; i++) {
+@@ -245,7 +245,7 @@ static int postconfig(struct comedi_device *dev)
+ 				SDF_CMD_WRITE)) == 0);
+ 			BUG_ON(!s->do_cmdtest);
+ 
+-			async = kzalloc(sizeof(comedi_async), GFP_KERNEL);
++			async = kzalloc(sizeof(struct comedi_async), GFP_KERNEL);
+ 			if (async == NULL) {
+ 				printk("failed to allocate async struct\n");
+ 				return -ENOMEM;
+@@ -415,7 +415,7 @@ static inline unsigned long kvirt_to_kva(unsigned long adr)
+ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned long new_size)
+ {
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 
+ 	/* Round up new_size to multiple of PAGE_SIZE */
+ 	new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
+@@ -536,7 +536,7 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
+ 
+ /* munging is applied to data by core as it passes between user
+  * and kernel space */
+-unsigned int comedi_buf_munge(comedi_async *async, unsigned int num_bytes)
++unsigned int comedi_buf_munge(struct comedi_async *async, unsigned int num_bytes)
+ {
+ 	struct comedi_subdevice *s = async->subdevice;
+ 	unsigned int count = 0;
+@@ -580,7 +580,7 @@ unsigned int comedi_buf_munge(comedi_async *async, unsigned int num_bytes)
+ 	return count;
+ }
+ 
+-unsigned int comedi_buf_write_n_available(comedi_async *async)
++unsigned int comedi_buf_write_n_available(struct comedi_async *async)
+ {
+ 	unsigned int free_end;
+ 	unsigned int nbytes;
+@@ -600,7 +600,7 @@ unsigned int comedi_buf_write_n_available(comedi_async *async)
+ }
+ 
+ /* allocates chunk for the writer from free buffer space */
+-unsigned int comedi_buf_write_alloc(comedi_async *async, unsigned int nbytes)
++unsigned int comedi_buf_write_alloc(struct comedi_async *async, unsigned int nbytes)
+ {
+ 	unsigned int free_end = async->buf_read_count + async->prealloc_bufsz;
+ 
+@@ -615,7 +615,7 @@ unsigned int comedi_buf_write_alloc(comedi_async *async, unsigned int nbytes)
+ }
+ 
+ /* allocates nothing unless it can completely fulfill the request */
+-unsigned int comedi_buf_write_alloc_strict(comedi_async *async,
++unsigned int comedi_buf_write_alloc_strict(struct comedi_async *async,
+ 	unsigned int nbytes)
+ {
+ 	unsigned int free_end = async->buf_read_count + async->prealloc_bufsz;
+@@ -631,7 +631,7 @@ unsigned int comedi_buf_write_alloc_strict(comedi_async *async,
+ }
+ 
+ /* transfers a chunk from writer to filled buffer space */
+-unsigned comedi_buf_write_free(comedi_async *async, unsigned int nbytes)
++unsigned comedi_buf_write_free(struct comedi_async *async, unsigned int nbytes)
+ {
+ 	if ((int)(async->buf_write_count + nbytes -
+ 			async->buf_write_alloc_count) > 0) {
+@@ -649,7 +649,7 @@ unsigned comedi_buf_write_free(comedi_async *async, unsigned int nbytes)
+ }
+ 
+ /* allocates a chunk for the reader from filled (and munged) buffer space */
+-unsigned comedi_buf_read_alloc(comedi_async *async, unsigned nbytes)
++unsigned comedi_buf_read_alloc(struct comedi_async *async, unsigned nbytes)
+ {
+ 	if ((int)(async->buf_read_alloc_count + nbytes - async->munge_count) >
+ 		0) {
+@@ -663,7 +663,7 @@ unsigned comedi_buf_read_alloc(comedi_async *async, unsigned nbytes)
+ }
+ 
+ /* transfers control of a chunk from reader to free buffer space */
+-unsigned comedi_buf_read_free(comedi_async *async, unsigned int nbytes)
++unsigned comedi_buf_read_free(struct comedi_async *async, unsigned int nbytes)
+ {
+ 	/*  barrier insures data has been read out of buffer before read count is incremented */
+ 	smp_mb();
+@@ -679,7 +679,7 @@ unsigned comedi_buf_read_free(comedi_async *async, unsigned int nbytes)
+ 	return nbytes;
+ }
+ 
+-void comedi_buf_memcpy_to(comedi_async *async, unsigned int offset,
++void comedi_buf_memcpy_to(struct comedi_async *async, unsigned int offset,
+ 	const void *data, unsigned int num_bytes)
+ {
+ 	unsigned int write_ptr = async->buf_write_ptr + offset;
+@@ -704,7 +704,7 @@ void comedi_buf_memcpy_to(comedi_async *async, unsigned int offset,
+ 	}
+ }
+ 
+-void comedi_buf_memcpy_from(comedi_async *async, unsigned int offset,
++void comedi_buf_memcpy_from(struct comedi_async *async, unsigned int offset,
+ 	void *dest, unsigned int nbytes)
+ {
+ 	void *src;
+@@ -730,7 +730,7 @@ void comedi_buf_memcpy_from(comedi_async *async, unsigned int offset,
+ 	}
+ }
+ 
+-unsigned int comedi_buf_read_n_available(comedi_async *async)
++unsigned int comedi_buf_read_n_available(struct comedi_async *async)
+ {
+ 	unsigned num_bytes;
+ 
+@@ -745,7 +745,7 @@ unsigned int comedi_buf_read_n_available(comedi_async *async)
+ 	return num_bytes;
+ }
+ 
+-int comedi_buf_get(comedi_async *async, short *x)
++int comedi_buf_get(struct comedi_async *async, short *x)
+ {
+ 	unsigned int n = comedi_buf_read_n_available(async);
+ 
+@@ -757,7 +757,7 @@ int comedi_buf_get(comedi_async *async, short *x)
+ 	return 1;
+ }
+ 
+-int comedi_buf_put(comedi_async *async, short x)
++int comedi_buf_put(struct comedi_async *async, short x)
+ {
+ 	unsigned int n = comedi_buf_write_alloc_strict(async, sizeof(short));
+ 
+@@ -770,7 +770,7 @@ int comedi_buf_put(comedi_async *async, short x)
+ 	return 1;
+ }
+ 
+-void comedi_reset_async_buf(comedi_async *async)
++void comedi_reset_async_buf(struct comedi_async *async)
+ {
+ 	async->buf_write_alloc_count = 0;
+ 	async->buf_write_count = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+index d8c495ddaae7..9af284314913 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+@@ -1630,14 +1630,15 @@ void v_APCI3120_Interrupt(int irq, void *d)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-/*int i_APCI3120_InterruptHandleEos(struct comedi_device *dev)
++/*
++ * int i_APCI3120_InterruptHandleEos(struct comedi_device *dev)
+ {
+        int n_chan,i;
+        short *data;
+        struct comedi_subdevice *s=dev->subdevices+0;
+-       comedi_async *async = s->async;
+-       data=async->data+async->buf_int_ptr;//new samples added from here onwards
+-       n_chan=devpriv->ui_AiNbrofChannels;
++       struct comedi_async *async = s->async;
++       data=async->data+async->buf_int_ptr;
++        n_chan=devpriv->ui_AiNbrofChannels;
+ 
+        for(i=0;iread_subdev;
+-	comedi_async *async;
++	struct comedi_async *async;
+ 	unsigned long irq_flags;
+ 	unsigned char intcsr;
+ 
+diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
+index 247b1eaaa17f..e575f7deb31d 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci224.c
++++ b/drivers/staging/comedi/drivers/amplc_pci224.c
+@@ -1185,7 +1185,7 @@ static void
+ pci224_ao_munge(struct comedi_device * dev, struct comedi_subdevice * s, void *data,
+ 	unsigned int num_bytes, unsigned int chan_index)
+ {
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	short *array = data;
+ 	unsigned int length = num_bytes / sizeof(*array);
+ 	unsigned int offset;
+diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
+index ee5f20320256..99ffbd2a961c 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci230.c
++++ b/drivers/staging/comedi/drivers/amplc_pci230.c
+@@ -1450,7 +1450,7 @@ static int pci230_ao_inttrig_scan_begin(struct comedi_device * dev,
+ 
+ static void pci230_ao_start(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 	unsigned long irqflags;
+ 
+@@ -2147,7 +2147,7 @@ static void pci230_ai_start(struct comedi_device * dev, struct comedi_subdevice
+ {
+ 	unsigned long irqflags;
+ 	unsigned short conv;
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 
+ 	set_bit(AI_CMD_STARTED, &devpriv->state);
+@@ -2300,7 +2300,7 @@ static int pci230_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s
+ 	unsigned char zgat;
+ 
+ 	/* Get the command. */
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 
+ 	/*
+@@ -2626,7 +2626,7 @@ static void pci230_handle_ao_nofifo(struct comedi_device * dev, struct comedi_su
+ {
+ 	short data;
+ 	int i, ret;
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 
+ 	if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0)) {
+@@ -2661,7 +2661,7 @@ static void pci230_handle_ao_nofifo(struct comedi_device * dev, struct comedi_su
+ /* Returns 0 if AO finished due to completion or error, 1 if still going. */
+ static int pci230_handle_ao_fifo(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 	unsigned int num_scans;
+ 	unsigned int room;
+@@ -2769,7 +2769,7 @@ static void pci230_handle_ai(struct comedi_device * dev, struct comedi_subdevice
+ 	unsigned int i;
+ 	unsigned int todo;
+ 	unsigned int fifoamount;
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	unsigned int scanlen = async->cmd.scan_end_arg;
+ 
+ 	/* Determine number of samples to read. */
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
+index aa431466053e..53fa8ee0fb7b 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas.c
+@@ -449,7 +449,7 @@ static comedi_driver driver_cb_pcidas = {
+       detach:cb_pcidas_detach,
+ };
+ 
+-static int cb_pcidas_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
++static int cb_pcidas_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ static int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+@@ -463,8 +463,9 @@ static int cb_pcidas_ai_cmd(struct comedi_device * dev, struct comedi_subdevice
+ static int cb_pcidas_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+ static int cb_pcidas_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+-static int cb_pcidas_ao_inttrig(struct comedi_device * dev, struct comedi_subdevice * subdev,
+-	unsigned int trig_num);
++static int cb_pcidas_ao_inttrig(struct comedi_device *dev,
++				struct comedi_subdevice *subdev,
++				unsigned int trig_num);
+ static int cb_pcidas_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+ static irqreturn_t cb_pcidas_interrupt(int irq, void *d PT_REGS_ARG);
+@@ -1164,7 +1165,7 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device * dev, struct comedi_subdev
+ 
+ static int cb_pcidas_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 	unsigned int bits;
+ 	unsigned long flags;
+@@ -1364,7 +1365,7 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device * dev, struct comedi_subdev
+ 
+ static int cb_pcidas_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 	unsigned int i;
+ 	unsigned long flags;
+@@ -1425,11 +1426,12 @@ static int cb_pcidas_ao_cmd(struct comedi_device * dev, struct comedi_subdevice
+ 	return 0;
+ }
+ 
+-static int cb_pcidas_ao_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
+-	unsigned int trig_num)
++static int cb_pcidas_ao_inttrig(struct comedi_device *dev,
++				struct comedi_subdevice *s,
++				unsigned int trig_num)
+ {
+ 	unsigned int num_bytes, num_points = thisboard->fifo_size;
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned long flags;
+ 
+@@ -1478,7 +1480,7 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+ 	struct comedi_subdevice *s = dev->read_subdev;
+-	comedi_async *async;
++	struct comedi_async *async;
+ 	int status, s5933_status;
+ 	int half_fifo = thisboard->fifo_size / 2;
+ 	unsigned int num_samples, i;
+@@ -1589,7 +1591,7 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d PT_REGS_ARG)
+ static void handle_ao_interrupt(struct comedi_device * dev, unsigned int status)
+ {
+ 	struct comedi_subdevice *s = dev->write_subdev;
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 	unsigned int half_fifo = thisboard->fifo_size / 2;
+ 	unsigned int num_points;
+@@ -1642,7 +1644,7 @@ static void handle_ao_interrupt(struct comedi_device * dev, unsigned int status)
+ 	comedi_event(dev, s);
+ }
+ 
+-// cancel analog input command
++/* cancel analog input command */
+ static int cb_pcidas_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+@@ -1661,8 +1663,9 @@ static int cb_pcidas_cancel(struct comedi_device * dev, struct comedi_subdevice
+ 	return 0;
+ }
+ 
+-// cancel analog output command
+-static int cb_pcidas_ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
++/* cancel analog output command */
++static int cb_pcidas_ao_cancel(struct comedi_device *dev,
++			       struct comedi_subdevice *s)
+ {
+ 	unsigned long flags;
+ 
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
+index f1e121110332..345eeb6241bf 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
+@@ -2681,7 +2681,7 @@ static inline void load_first_dma_descriptor(struct comedi_device * dev,
+ 
+ static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 	uint32_t bits;
+ 	unsigned int i;
+@@ -2800,7 +2800,7 @@ static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ static void pio_drain_ai_fifo_16(struct comedi_device * dev)
+ {
+ 	struct comedi_subdevice *s = dev->read_subdev;
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 	unsigned int i;
+ 	uint16_t prepost_bits;
+@@ -2867,7 +2867,7 @@ static void pio_drain_ai_fifo_16(struct comedi_device * dev)
+ static void pio_drain_ai_fifo_32(struct comedi_device * dev)
+ {
+ 	struct comedi_subdevice *s = dev->read_subdev;
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 	unsigned int i;
+ 	unsigned int max_transfer = 100000;
+@@ -2908,7 +2908,7 @@ static void pio_drain_ai_fifo(struct comedi_device * dev)
+ 
+ static void drain_dma_buffers(struct comedi_device * dev, unsigned int channel)
+ {
+-	comedi_async *async = dev->read_subdev->async;
++	struct comedi_async *async = dev->read_subdev->async;
+ 	uint32_t next_transfer_addr;
+ 	int j;
+ 	int num_samples = 0;
+@@ -2956,7 +2956,7 @@ void handle_ai_interrupt(struct comedi_device * dev, unsigned short status,
+ 	unsigned int plx_status)
+ {
+ 	struct comedi_subdevice *s = dev->read_subdev;
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 	uint8_t dma1_status;
+ 	unsigned long flags;
+@@ -3078,7 +3078,7 @@ static void handle_ao_interrupt(struct comedi_device * dev, unsigned short statu
+ 	unsigned int plx_status)
+ {
+ 	struct comedi_subdevice *s = dev->write_subdev;
+-	comedi_async *async;
++	struct comedi_async *async;
+ 	comedi_cmd *cmd;
+ 	uint8_t dma0_status;
+ 	unsigned long flags;
+diff --git a/drivers/staging/comedi/drivers/comedi_fc.c b/drivers/staging/comedi/drivers/comedi_fc.c
+index 8e7ec147285d..9fa4cdc84d44 100644
+--- a/drivers/staging/comedi/drivers/comedi_fc.c
++++ b/drivers/staging/comedi/drivers/comedi_fc.c
+@@ -31,7 +31,7 @@
+ static void increment_scan_progress(struct comedi_subdevice *subd,
+ 				    unsigned int num_bytes)
+ {
+-	comedi_async *async = subd->async;
++	struct comedi_async *async = subd->async;
+ 	unsigned int scan_length = cfc_bytes_per_scan(subd);
+ 
+ 	async->scan_progress += num_bytes;
+@@ -45,7 +45,7 @@ static void increment_scan_progress(struct comedi_subdevice *subd,
+ unsigned int cfc_write_array_to_buffer(struct comedi_subdevice *subd, void *data,
+ 				       unsigned int num_bytes)
+ {
+-	comedi_async *async = subd->async;
++	struct comedi_async *async = subd->async;
+ 	unsigned int retval;
+ 
+ 	if (num_bytes == 0)
+@@ -70,7 +70,7 @@ EXPORT_SYMBOL(cfc_write_array_to_buffer);
+ unsigned int cfc_read_array_from_buffer(struct comedi_subdevice *subd, void *data,
+ 					unsigned int num_bytes)
+ {
+-	comedi_async *async = subd->async;
++	struct comedi_async *async = subd->async;
+ 
+ 	if (num_bytes == 0)
+ 		return 0;
+diff --git a/drivers/staging/comedi/drivers/comedi_rt_timer.c b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+index 76a1cdcfcd1c..93a43bdf3bcf 100644
+--- a/drivers/staging/comedi/drivers/comedi_rt_timer.c
++++ b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+@@ -292,7 +292,7 @@ static void scan_task_func(comedi_rt_task_context_t d)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+ 	struct comedi_subdevice *s = dev->subdevices + 0;
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 	int i, ret;
+ 	unsigned long long n;
+@@ -580,7 +580,7 @@ static int timer_inttrig(struct comedi_device * dev, struct comedi_subdevice * s
+ 
+ static int timer_start_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 	RTIME now, delay, period;
+ 	int ret;
+diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c
+index 462d453eb88f..f8baf83c588c 100644
+--- a/drivers/staging/comedi/drivers/comedi_test.c
++++ b/drivers/staging/comedi/drivers/comedi_test.c
+@@ -144,7 +144,7 @@ static const comedi_lrange waveform_ai_ranges = {
+ static void waveform_ai_interrupt(unsigned long arg)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) arg;
+-	comedi_async *async = dev->read_subdev->async;
++	struct comedi_async *async = dev->read_subdev->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 	unsigned int i, j;
+ 	/* all times in microsec */
+diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
+index 94e59a5c6629..7e51137fcf5c 100644
+--- a/drivers/staging/comedi/drivers/das16.c
++++ b/drivers/staging/comedi/drivers/das16.c
+@@ -895,7 +895,7 @@ static int das16_cmd_test(struct comedi_device * dev, struct comedi_subdevice *
+ 
+ static int das16_cmd_exec(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 	unsigned int byte;
+ 	unsigned long flags;
+@@ -1201,7 +1201,7 @@ static void das16_interrupt(struct comedi_device * dev)
+ {
+ 	unsigned long dma_flags, spin_flags;
+ 	struct comedi_subdevice *s = dev->read_subdev;
+-	comedi_async *async;
++	struct comedi_async *async;
+ 	comedi_cmd *cmd;
+ 	int num_bytes, residue;
+ 	int buffer_index;
+diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
+index c337c803ec1e..48211a87961e 100644
+--- a/drivers/staging/comedi/drivers/das16m1.c
++++ b/drivers/staging/comedi/drivers/das16m1.c
+@@ -324,7 +324,7 @@ static int das16m1_cmd_test(struct comedi_device * dev, struct comedi_subdevice
+ 
+ static int das16m1_cmd_exec(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 	unsigned int byte, i;
+ 
+@@ -517,7 +517,7 @@ static void munge_sample_array(short * array, unsigned int num_elements)
+ static void das16m1_handler(struct comedi_device * dev, unsigned int status)
+ {
+ 	struct comedi_subdevice *s;
+-	comedi_async *async;
++	struct comedi_async *async;
+ 	comedi_cmd *cmd;
+ 	u16 num_samples;
+ 	u16 hw_counter;
+diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
+index 5a63a00d1a4c..47d92c70ca0a 100644
+--- a/drivers/staging/comedi/drivers/das1800.c
++++ b/drivers/staging/comedi/drivers/das1800.c
+@@ -912,7 +912,7 @@ static irqreturn_t das1800_interrupt(int irq, void *d PT_REGS_ARG)
+ static void das1800_ai_handler(struct comedi_device * dev)
+ {
+ 	struct comedi_subdevice *s = dev->subdevices + 0;	/* analog input subdevice */
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 	unsigned int status = inb(dev->iobase + DAS1800_STATUS);
+ 
+@@ -1493,7 +1493,7 @@ static int das1800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice
+ {
+ 	int ret;
+ 	int control_a, control_c;
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	comedi_cmd cmd = async->cmd;
+ 
+ 	if (!dev->irq) {
+diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
+index 7833e56b0124..92df82216f3e 100644
+--- a/drivers/staging/comedi/drivers/das800.c
++++ b/drivers/staging/comedi/drivers/das800.c
+@@ -349,7 +349,7 @@ static irqreturn_t das800_interrupt(int irq, void *d PT_REGS_ARG)
+ 	short dataPoint = 0;
+ 	struct comedi_device *dev = d;
+ 	struct comedi_subdevice *s = dev->read_subdev;	/* analog input subdevice */
+-	comedi_async *async;
++	struct comedi_async *async;
+ 	int status;
+ 	unsigned long irq_flags;
+ 	static const int max_loops = 128;	// half-fifo size for cio-das802/16
+@@ -714,7 +714,7 @@ static int das800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice
+ 	int startChan, endChan, scan, gain;
+ 	int conv_bits;
+ 	unsigned long irq_flags;
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 
+ 	if (!dev->irq) {
+ 		comedi_error(dev,
+diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
+index fb91fa1da839..aefee40710c1 100644
+--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
++++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
+@@ -838,7 +838,7 @@ static int di_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	uint32_t bits;
+ 	unsigned long flags;
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 
+ 	hpdi_writel(dev, RX_FIFO_RESET_BIT, BOARD_CONTROL_REG);
+@@ -897,7 +897,7 @@ static int hpdi_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 
+ static void drain_dma_buffers(struct comedi_device * dev, unsigned int channel)
+ {
+-	comedi_async *async = dev->read_subdev->async;
++	struct comedi_async *async = dev->read_subdev->async;
+ 	uint32_t next_transfer_addr;
+ 	int j;
+ 	int num_samples = 0;
+@@ -945,7 +945,7 @@ static irqreturn_t handle_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	struct comedi_device *dev = d;
+ 	struct comedi_subdevice *s = dev->read_subdev;
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	uint32_t hpdi_intr_status, hpdi_board_status;
+ 	uint32_t plx_status;
+ 	uint32_t plx_bits;
+diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c
+index e0e2d6c90ac3..ae9017744537 100644
+--- a/drivers/staging/comedi/drivers/mite.c
++++ b/drivers/staging/comedi/drivers/mite.c
+@@ -317,7 +317,7 @@ void mite_dma_arm(struct mite_channel *mite_chan)
+ 
+ /**************************************/
+ 
+-int mite_buf_change(struct mite_dma_descriptor_ring *ring, comedi_async * async)
++int mite_buf_change(struct mite_dma_descriptor_ring *ring, struct comedi_async * async)
+ {
+ 	unsigned int n_links;
+ 	int i;
+@@ -526,7 +526,7 @@ void mite_dma_disarm(struct mite_channel *mite_chan)
+ 	writel(chor, mite->mite_io_addr + MITE_CHOR(mite_chan->channel));
+ }
+ 
+-int mite_sync_input_dma(struct mite_channel *mite_chan, comedi_async * async)
++int mite_sync_input_dma(struct mite_channel *mite_chan, struct comedi_async * async)
+ {
+ 	int count;
+ 	unsigned int nbytes, old_alloc_count;
+@@ -561,7 +561,7 @@ int mite_sync_input_dma(struct mite_channel *mite_chan, comedi_async * async)
+ 	return 0;
+ }
+ 
+-int mite_sync_output_dma(struct mite_channel *mite_chan, comedi_async * async)
++int mite_sync_output_dma(struct mite_channel *mite_chan, struct comedi_async * async)
+ {
+ 	int count;
+ 	u32 nbytes_ub, nbytes_lb;
+diff --git a/drivers/staging/comedi/drivers/mite.h b/drivers/staging/comedi/drivers/mite.h
+index bca9f3af7adb..cdaf8a31688a 100644
+--- a/drivers/staging/comedi/drivers/mite.h
++++ b/drivers/staging/comedi/drivers/mite.h
+@@ -142,8 +142,8 @@ void mite_release_channel(struct mite_channel *mite_chan);
+ unsigned mite_dma_tcr(struct mite_channel *mite_chan);
+ void mite_dma_arm(struct mite_channel *mite_chan);
+ void mite_dma_disarm(struct mite_channel *mite_chan);
+-int mite_sync_input_dma(struct mite_channel *mite_chan, comedi_async * async);
+-int mite_sync_output_dma(struct mite_channel *mite_chan, comedi_async * async);
++int mite_sync_input_dma(struct mite_channel *mite_chan, struct comedi_async * async);
++int mite_sync_output_dma(struct mite_channel *mite_chan, struct comedi_async * async);
+ u32 mite_bytes_written_to_memory_lb(struct mite_channel *mite_chan);
+ u32 mite_bytes_written_to_memory_ub(struct mite_channel *mite_chan);
+ u32 mite_bytes_read_from_memory_lb(struct mite_channel *mite_chan);
+@@ -153,7 +153,7 @@ unsigned mite_get_status(struct mite_channel *mite_chan);
+ int mite_done(struct mite_channel *mite_chan);
+ 
+ #if 0
+-unsigned long mite_ll_from_kvmem(struct mite_struct *mite, comedi_async * async,
++unsigned long mite_ll_from_kvmem(struct mite_struct *mite, struct comedi_async * async,
+ 	int len);
+ void mite_setregs(struct mite_struct *mite, unsigned long ll_start, int chan,
+ 	int dir);
+@@ -162,7 +162,7 @@ void mite_setregs(struct mite_struct *mite, unsigned long ll_start, int chan,
+ void mite_prep_dma(struct mite_channel *mite_chan,
+ 	unsigned int num_device_bits, unsigned int num_memory_bits);
+ int mite_buf_change(struct mite_dma_descriptor_ring *ring,
+-	comedi_async *async);
++	struct comedi_async *async);
+ 
+ #ifdef DEBUG_MITE
+ void mite_print_chsr(unsigned int chsr);
+diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
+index 4ac5313ea43f..c15568d3cd46 100644
+--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
++++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
+@@ -214,7 +214,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d PT_REGS_ARG)
+ 	unsigned long flags;
+ 	struct comedi_device *dev = d;
+ 	struct comedi_subdevice *s = dev->read_subdev;
+-	comedi_async *async;
++	struct comedi_async *async;
+ 	comedi_cmd *cmd;
+ 	unsigned int max_points, num_points, residue, leftover;
+ 	short dpnt;
+@@ -617,7 +617,7 @@ static int a2150_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice
+ 
+ static int a2150_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 	unsigned long lock_flags;
+ 	unsigned int old_config_bits = devpriv->config_bits;
+diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
+index be528f6c3ab0..6ba97da42def 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc.c
++++ b/drivers/staging/comedi/drivers/ni_labpc.c
+@@ -1068,7 +1068,7 @@ static int labpc_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ 	int channel, range, aref;
+ 	unsigned long irq_flags;
+ 	int ret;
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 	enum transfer_type xfer;
+ 	unsigned long flags;
+@@ -1313,7 +1313,7 @@ static irqreturn_t labpc_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	struct comedi_device *dev = d;
+ 	struct comedi_subdevice *s = dev->read_subdev;
+-	comedi_async *async;
++	struct comedi_async *async;
+ 	comedi_cmd *cmd;
+ 
+ 	if (dev->attached == 0) {
+@@ -1397,7 +1397,7 @@ static int labpc_drain_fifo(struct comedi_device * dev)
+ {
+ 	unsigned int lsb, msb;
+ 	short data;
+-	comedi_async *async = dev->read_subdev->async;
++	struct comedi_async *async = dev->read_subdev->async;
+ 	const int timeout = 10000;
+ 	unsigned int i;
+ 
+@@ -1430,7 +1430,7 @@ static int labpc_drain_fifo(struct comedi_device * dev)
+ static void labpc_drain_dma(struct comedi_device * dev)
+ {
+ 	struct comedi_subdevice *s = dev->read_subdev;
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	int status;
+ 	unsigned long flags;
+ 	unsigned int max_points, num_points, residue, leftover;
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index 29698d995a19..8f3c959f6265 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -1206,7 +1206,7 @@ static void ni_mio_print_status_b(int status)
+ 
+ static void ni_ao_fifo_load(struct comedi_device * dev, struct comedi_subdevice * s, int n)
+ {
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 	int chan;
+ 	int i;
+@@ -1309,7 +1309,7 @@ static int ni_ao_prep_fifo(struct comedi_device * dev, struct comedi_subdevice *
+ 
+ static void ni_ai_fifo_read(struct comedi_device * dev, struct comedi_subdevice * s, int n)
+ {
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	int i;
+ 
+ 	if (boardtype.reg_type == ni_reg_611x) {
+@@ -1516,7 +1516,7 @@ static void get_last_sample_6143(struct comedi_device * dev)
+ static void ni_ai_munge(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	void *data, unsigned int num_bytes, unsigned int chan_index)
+ {
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	unsigned int i;
+ 	unsigned int length = num_bytes / bytes_per_sample(s);
+ 	short *array = data;
+@@ -2780,7 +2780,7 @@ static int ni_ai_config_analog_trig(struct comedi_device * dev, struct comedi_su
+ static void ni_ao_munge(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	void *data, unsigned int num_bytes, unsigned int chan_index)
+ {
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	unsigned int range;
+ 	unsigned int i;
+ 	unsigned int offset;
+diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
+index 79457ecbafbe..d75939bcca17 100644
+--- a/drivers/staging/comedi/drivers/ni_pcidio.c
++++ b/drivers/staging/comedi/drivers/ni_pcidio.c
+@@ -481,7 +481,7 @@ static irqreturn_t nidio_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	struct comedi_device *dev = d;
+ 	struct comedi_subdevice *s = dev->subdevices;
+-	comedi_async *async = s->async;
++	struct comedi_async *async = s->async;
+ 	struct mite_struct *mite = devpriv->mite;
+ 
+ 	//int i, j;
+diff --git a/drivers/staging/comedi/drivers/ni_tio.h b/drivers/staging/comedi/drivers/ni_tio.h
+index 97a925999ff9..e5dbd82826b0 100644
+--- a/drivers/staging/comedi/drivers/ni_tio.h
++++ b/drivers/staging/comedi/drivers/ni_tio.h
+@@ -145,7 +145,7 @@ extern int ni_tio_insn_config(struct ni_gpct *counter,
+ 	comedi_insn * insn, unsigned int * data);
+ extern int ni_tio_winsn(struct ni_gpct *counter,
+ 	comedi_insn * insn, unsigned int * data);
+-extern int ni_tio_cmd(struct ni_gpct *counter, comedi_async * async);
++extern int ni_tio_cmd(struct ni_gpct *counter, struct comedi_async *async);
+ extern int ni_tio_cmdtest(struct ni_gpct *counter, comedi_cmd * cmd);
+ extern int ni_tio_cancel(struct ni_gpct *counter);
+ extern void ni_tio_handle_interrupt(struct ni_gpct *counter,
+diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c
+index dffaafe9d5fa..2c3a21771875 100644
+--- a/drivers/staging/comedi/drivers/ni_tiocmd.c
++++ b/drivers/staging/comedi/drivers/ni_tiocmd.c
+@@ -121,7 +121,7 @@ static int ni_tio_input_inttrig(struct comedi_device * dev, struct comedi_subdev
+ 	return retval;
+ }
+ 
+-static int ni_tio_input_cmd(struct ni_gpct *counter, comedi_async * async)
++static int ni_tio_input_cmd(struct ni_gpct *counter, struct comedi_async *async)
+ {
+ 	struct ni_gpct_device *counter_dev = counter->counter_dev;
+ 	comedi_cmd *cmd = &async->cmd;
+@@ -169,7 +169,7 @@ static int ni_tio_input_cmd(struct ni_gpct *counter, comedi_async * async)
+ 	return retval;
+ }
+ 
+-static int ni_tio_output_cmd(struct ni_gpct *counter, comedi_async * async)
++static int ni_tio_output_cmd(struct ni_gpct *counter, struct comedi_async *async)
+ {
+ 	rt_printk("ni_tio: output commands not yet implemented.\n");
+ 	return -ENOTSUPP;
+@@ -181,7 +181,7 @@ static int ni_tio_output_cmd(struct ni_gpct *counter, comedi_async * async)
+ 	return ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE);
+ }
+ 
+-static int ni_tio_cmd_setup(struct ni_gpct *counter, comedi_async * async)
++static int ni_tio_cmd_setup(struct ni_gpct *counter, struct comedi_async *async)
+ {
+ 	comedi_cmd *cmd = &async->cmd;
+ 	int set_gate_source = 0;
+@@ -207,7 +207,7 @@ static int ni_tio_cmd_setup(struct ni_gpct *counter, comedi_async * async)
+ 	return retval;
+ }
+ 
+-int ni_tio_cmd(struct ni_gpct *counter, comedi_async * async)
++int ni_tio_cmd(struct ni_gpct *counter, struct comedi_async *async)
+ {
+ 	comedi_cmd *cmd = &async->cmd;
+ 	int retval = 0;
+diff --git a/drivers/staging/comedi/kcomedilib/get.c b/drivers/staging/comedi/kcomedilib/get.c
+index 8237716a20c6..8890fcb7c1c5 100644
+--- a/drivers/staging/comedi/kcomedilib/get.c
++++ b/drivers/staging/comedi/kcomedilib/get.c
+@@ -175,7 +175,7 @@ unsigned int comedi_get_buf_head_pos(void *d, unsigned int subdevice)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+ 	struct comedi_subdevice *s = dev->subdevices + subdevice;
+-	comedi_async *async;
++	struct comedi_async *async;
+ 
+ 	async = s->async;
+ 	if (async == NULL)
+@@ -188,7 +188,7 @@ int comedi_get_buffer_contents(void *d, unsigned int subdevice)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+ 	struct comedi_subdevice *s = dev->subdevices + subdevice;
+-	comedi_async *async;
++	struct comedi_async *async;
+ 	unsigned int num_bytes;
+ 
+ 	if (subdevice >= dev->n_subdevices)
+@@ -208,7 +208,7 @@ int comedi_set_user_int_count(void *d, unsigned int subdevice,
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+ 	struct comedi_subdevice *s = dev->subdevices + subdevice;
+-	comedi_async *async;
++	struct comedi_async *async;
+ 	int num_bytes;
+ 
+ 	async = s->async;
+@@ -229,7 +229,7 @@ int comedi_mark_buffer_read(void *d, unsigned int subdevice,
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+ 	struct comedi_subdevice *s = dev->subdevices + subdevice;
+-	comedi_async *async;
++	struct comedi_async *async;
+ 
+ 	if (subdevice >= dev->n_subdevices)
+ 		return -1;
+@@ -248,7 +248,7 @@ int comedi_mark_buffer_written(void *d, unsigned int subdevice,
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+ 	struct comedi_subdevice *s = dev->subdevices + subdevice;
+-	comedi_async *async;
++	struct comedi_async *async;
+ 	int bytes_written;
+ 
+ 	if (subdevice >= dev->n_subdevices)
+@@ -267,7 +267,7 @@ int comedi_get_buffer_size(void *d, unsigned int subdev)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+ 	struct comedi_subdevice *s = dev->subdevices + subdev;
+-	comedi_async *async;
++	struct comedi_async *async;
+ 
+ 	if (subdev >= dev->n_subdevices)
+ 		return -1;
+@@ -282,7 +282,7 @@ int comedi_get_buffer_offset(void *d, unsigned int subdevice)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+ 	struct comedi_subdevice *s = dev->subdevices + subdevice;
+-	comedi_async *async;
++	struct comedi_async *async;
+ 
+ 	if (subdevice >= dev->n_subdevices)
+ 		return -1;
+diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+index 928e93500bbf..31b749d4962a 100644
+--- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
++++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+@@ -125,7 +125,7 @@ int comedi_command(void *d, comedi_cmd *cmd)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+ 	struct comedi_subdevice *s;
+-	comedi_async *async;
++	struct comedi_async *async;
+ 	unsigned runflags;
+ 
+ 	if (cmd->subdev >= dev->n_subdevices)
+@@ -372,7 +372,7 @@ int comedi_unlock(void *d, unsigned int subdevice)
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+ 	struct comedi_subdevice *s;
+ 	unsigned long flags;
+-	comedi_async *async;
++	struct comedi_async *async;
+ 	int ret;
+ 
+ 	if (subdevice >= dev->n_subdevices)
+@@ -469,7 +469,7 @@ int comedi_register_callback(void *d, unsigned int subdevice,
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+ 	struct comedi_subdevice *s;
+-	comedi_async *async;
++	struct comedi_async *async;
+ 
+ 	if (subdevice >= dev->n_subdevices)
+ 		return -EINVAL;
+@@ -505,7 +505,7 @@ int comedi_poll(void *d, unsigned int subdevice)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+ 	struct comedi_subdevice *s = dev->subdevices;
+-	comedi_async *async;
++	struct comedi_async *async;
+ 
+ 	if (subdevice >= dev->n_subdevices)
+ 		return -EINVAL;

commit 34c43922e62708d45e9660eee4b4f1fb7b4bf2c7
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:05:14 2009 -0400
+
+    Staging: comedi: Remove comedi_subdevice typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
+index c8169e03693f..eac18a742b22 100644
+--- a/drivers/staging/comedi/comedi_fops.c
++++ b/drivers/staging/comedi/comedi_fops.c
+@@ -86,8 +86,8 @@ static int do_insnlist_ioctl(struct comedi_device *dev, void *arg, void *file);
+ static int do_insn_ioctl(struct comedi_device *dev, void *arg, void *file);
+ static int do_poll_ioctl(struct comedi_device *dev, unsigned int subd, void *file);
+ 
+-extern void do_become_nonbusy(struct comedi_device *dev, comedi_subdevice *s);
+-static int do_cancel(struct comedi_device *dev, comedi_subdevice *s);
++extern void do_become_nonbusy(struct comedi_device *dev, struct comedi_subdevice *s);
++static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
+ 
+ static int comedi_fasync(int fd, struct file *file, int on);
+ 
+@@ -276,7 +276,7 @@ static int do_bufconfig_ioctl(struct comedi_device *dev, void *arg)
+ {
+ 	comedi_bufconfig bc;
+ 	comedi_async *async;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int ret = 0;
+ 
+ 	if (copy_from_user(&bc, arg, sizeof(comedi_bufconfig)))
+@@ -367,9 +367,9 @@ static int do_devinfo_ioctl(struct comedi_device *dev, comedi_devinfo *arg,
+ 	const unsigned minor = iminor(file->f_dentry->d_inode);
+ 	struct comedi_device_file_info *dev_file_info =
+ 	    comedi_get_device_file_info(minor);
+-	comedi_subdevice *read_subdev =
++	struct comedi_subdevice *read_subdev =
+ 	    comedi_get_read_subdevice(dev_file_info);
+-	comedi_subdevice *write_subdev =
++	struct comedi_subdevice *write_subdev =
+ 	    comedi_get_write_subdevice(dev_file_info);
+ 
+ 	memset(&devinfo, 0, sizeof(devinfo));
+@@ -415,7 +415,7 @@ static int do_subdinfo_ioctl(struct comedi_device *dev, comedi_subdinfo *arg,
+ {
+ 	int ret, i;
+ 	comedi_subdinfo *tmp, *us;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	tmp = kcalloc(dev->n_subdevices, sizeof(comedi_subdinfo), GFP_KERNEL);
+ 	if (!tmp)
+@@ -492,7 +492,7 @@ static int do_subdinfo_ioctl(struct comedi_device *dev, comedi_subdinfo *arg,
+ */
+ static int do_chaninfo_ioctl(struct comedi_device *dev, comedi_chaninfo *arg)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	comedi_chaninfo it;
+ 
+ 	if (copy_from_user(&it, arg, sizeof(comedi_chaninfo)))
+@@ -557,7 +557,7 @@ static int do_chaninfo_ioctl(struct comedi_device *dev, comedi_chaninfo *arg)
+ static int do_bufinfo_ioctl(struct comedi_device *dev, void *arg)
+ {
+ 	comedi_bufinfo bi;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	comedi_async *async;
+ 
+ 	if (copy_from_user(&bi, arg, sizeof(comedi_bufinfo)))
+@@ -760,7 +760,7 @@ static int check_insn_config_length(comedi_insn *insn, unsigned int *data)
+ static int parse_insn(struct comedi_device *dev, comedi_insn *insn, unsigned int *data,
+ 		      void *file)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int ret = 0;
+ 	int i;
+ 
+@@ -978,7 +978,7 @@ static int do_insn_ioctl(struct comedi_device *dev, void *arg, void *file)
+ static int do_cmd_ioctl(struct comedi_device *dev, void *arg, void *file)
+ {
+ 	comedi_cmd user_cmd;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	comedi_async *async;
+ 	int ret = 0;
+ 	unsigned int *chanlist_saver = NULL;
+@@ -1132,7 +1132,7 @@ static int do_cmd_ioctl(struct comedi_device *dev, void *arg, void *file)
+ static int do_cmdtest_ioctl(struct comedi_device *dev, void *arg, void *file)
+ {
+ 	comedi_cmd user_cmd;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int ret = 0;
+ 	unsigned int *chanlist = NULL;
+ 	unsigned int *chanlist_saver = NULL;
+@@ -1231,7 +1231,7 @@ static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg, void *file
+ {
+ 	int ret = 0;
+ 	unsigned long flags;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	if (arg >= dev->n_subdevices)
+ 		return -EINVAL;
+@@ -1273,7 +1273,7 @@ static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg, void *file
+ */
+ static int do_unlock_ioctl(struct comedi_device *dev, unsigned int arg, void *file)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	if (arg >= dev->n_subdevices)
+ 		return -EINVAL;
+@@ -1313,7 +1313,7 @@ static int do_unlock_ioctl(struct comedi_device *dev, unsigned int arg, void *fi
+ */
+ static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg, void *file)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	if (arg >= dev->n_subdevices)
+ 		return -EINVAL;
+@@ -1349,7 +1349,7 @@ static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg, void *fi
+ */
+ static int do_poll_ioctl(struct comedi_device *dev, unsigned int arg, void *file)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	if (arg >= dev->n_subdevices)
+ 		return -EINVAL;
+@@ -1370,7 +1370,7 @@ static int do_poll_ioctl(struct comedi_device *dev, unsigned int arg, void *file
+ 	return -EINVAL;
+ }
+ 
+-static int do_cancel(struct comedi_device *dev, comedi_subdevice *s)
++static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	int ret = 0;
+ 
+@@ -1411,7 +1411,7 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
+ 	int n_pages;
+ 	int i;
+ 	int retval;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	mutex_lock(&dev->mutex);
+ 	if (!dev->attached) {
+@@ -1481,8 +1481,8 @@ static unsigned int comedi_poll(struct file *file, poll_table *wait)
+ 	struct comedi_device_file_info *dev_file_info =
+ 	    comedi_get_device_file_info(minor);
+ 	struct comedi_device *dev = dev_file_info->device;
+-	comedi_subdevice *read_subdev;
+-	comedi_subdevice *write_subdev;
++	struct comedi_subdevice *read_subdev;
++	struct comedi_subdevice *write_subdev;
+ 
+ 	mutex_lock(&dev->mutex);
+ 	if (!dev->attached) {
+@@ -1523,7 +1523,7 @@ static unsigned int comedi_poll(struct file *file, poll_table *wait)
+ static ssize_t comedi_write(struct file *file, const char *buf, size_t nbytes,
+ 			    loff_t *offset)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	comedi_async *async;
+ 	int n, m, count = 0, retval = 0;
+ 	DECLARE_WAITQUEUE(wait, current);
+@@ -1625,7 +1625,7 @@ static ssize_t comedi_write(struct file *file, const char *buf, size_t nbytes,
+ static ssize_t comedi_read(struct file *file, char *buf, size_t nbytes,
+ 			   loff_t *offset)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	comedi_async *async;
+ 	int n, m, count = 0, retval = 0;
+ 	DECLARE_WAITQUEUE(wait, current);
+@@ -1733,7 +1733,7 @@ static ssize_t comedi_read(struct file *file, char *buf, size_t nbytes,
+ /*
+    This function restores a subdevice to an idle state.
+  */
+-void do_become_nonbusy(struct comedi_device *dev, comedi_subdevice *s)
++void do_become_nonbusy(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	comedi_async *async = s->async;
+ 
+@@ -1833,7 +1833,7 @@ static int comedi_close(struct inode *inode, struct file *file)
+ 	struct comedi_device_file_info *dev_file_info =
+ 	    comedi_get_device_file_info(minor);
+ 	struct comedi_device *dev = dev_file_info->device;
+-	comedi_subdevice *s = NULL;
++	struct comedi_subdevice *s = NULL;
+ 	int i;
+ 
+ 	mutex_lock(&dev->mutex);
+@@ -2006,7 +2006,7 @@ void comedi_error(const struct comedi_device *dev, const char *s)
+ 		  s);
+ }
+ 
+-void comedi_event(struct comedi_device *dev, comedi_subdevice *s)
++void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	comedi_async *async = s->async;
+ 	unsigned runflags = 0;
+@@ -2067,7 +2067,7 @@ void comedi_event(struct comedi_device *dev, comedi_subdevice *s)
+ 	s->async->events = 0;
+ }
+ 
+-void comedi_set_subdevice_runflags(comedi_subdevice *s, unsigned mask,
++void comedi_set_subdevice_runflags(struct comedi_subdevice *s, unsigned mask,
+ 				   unsigned bits)
+ {
+ 	unsigned long flags;
+@@ -2078,7 +2078,7 @@ void comedi_set_subdevice_runflags(comedi_subdevice *s, unsigned mask,
+ 	comedi_spin_unlock_irqrestore(&s->spin_lock, flags);
+ }
+ 
+-unsigned comedi_get_subdevice_runflags(comedi_subdevice *s)
++unsigned comedi_get_subdevice_runflags(struct comedi_subdevice *s)
+ {
+ 	unsigned long flags;
+ 	unsigned runflags;
+@@ -2091,7 +2091,7 @@ unsigned comedi_get_subdevice_runflags(comedi_subdevice *s)
+ 
+ static int is_device_busy(struct comedi_device *dev)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int i;
+ 
+ 	if (!dev->attached)
+@@ -2193,7 +2193,7 @@ void comedi_free_board_minor(unsigned minor)
+ 	}
+ }
+ 
+-int comedi_alloc_subdevice_minor(struct comedi_device *dev, comedi_subdevice *s)
++int comedi_alloc_subdevice_minor(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	unsigned long flags;
+ 	struct comedi_device_file_info *info;
+@@ -2231,7 +2231,7 @@ int comedi_alloc_subdevice_minor(struct comedi_device *dev, comedi_subdevice *s)
+ 	return i;
+ }
+ 
+-void comedi_free_subdevice_minor(comedi_subdevice *s)
++void comedi_free_subdevice_minor(struct comedi_subdevice *s)
+ {
+ 	unsigned long flags;
+ 	struct comedi_device_file_info *info;
+diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
+index e0035f3e9287..4fba9e7d437e 100644
+--- a/drivers/staging/comedi/comedidev.h
++++ b/drivers/staging/comedi/comedidev.h
+@@ -121,7 +121,6 @@
+ #define COMEDI_NUM_BOARD_MINORS 0x30
+ #define COMEDI_FIRST_SUBDEVICE_MINOR COMEDI_NUM_BOARD_MINORS
+ 
+-typedef struct comedi_subdevice_struct comedi_subdevice;
+ typedef struct comedi_async_struct comedi_async;
+ typedef struct comedi_driver_struct comedi_driver;
+ typedef struct comedi_lrange_struct comedi_lrange;
+@@ -131,7 +130,7 @@ typedef struct device device_create_result_type;
+ #define COMEDI_DEVICE_CREATE(cs, parent, devt, drvdata, device, fmt...) \
+ 	device_create(cs, ((parent) ? (parent) : (device)), devt, drvdata, fmt)
+ 
+-struct comedi_subdevice_struct {
++struct comedi_subdevice {
+ 	struct comedi_device *device;
+ 	int type;
+ 	int n_chan;
+@@ -162,27 +161,27 @@ struct comedi_subdevice_struct {
+ 
+ 	unsigned int *chanlist;	/* driver-owned chanlist (not used) */
+ 
+-	int (*insn_read) (struct comedi_device *, comedi_subdevice *, comedi_insn *,
++	int (*insn_read) (struct comedi_device *, struct comedi_subdevice *, comedi_insn *,
+ 		unsigned int *);
+-	int (*insn_write) (struct comedi_device *, comedi_subdevice *, comedi_insn *,
++	int (*insn_write) (struct comedi_device *, struct comedi_subdevice *, comedi_insn *,
+ 		unsigned int *);
+-	int (*insn_bits) (struct comedi_device *, comedi_subdevice *, comedi_insn *,
++	int (*insn_bits) (struct comedi_device *, struct comedi_subdevice *, comedi_insn *,
+ 		unsigned int *);
+-	int (*insn_config) (struct comedi_device *, comedi_subdevice *, comedi_insn *,
++	int (*insn_config) (struct comedi_device *, struct comedi_subdevice *, comedi_insn *,
+ 		unsigned int *);
+ 
+-	int (*do_cmd) (struct comedi_device *, comedi_subdevice *);
+-	int (*do_cmdtest) (struct comedi_device *, comedi_subdevice *, comedi_cmd *);
+-	int (*poll) (struct comedi_device *, comedi_subdevice *);
+-	int (*cancel) (struct comedi_device *, comedi_subdevice *);
+-	/* int (*do_lock)(struct comedi_device *,comedi_subdevice *); */
+-	/* int (*do_unlock)(struct comedi_device *,comedi_subdevice *); */
++	int (*do_cmd) (struct comedi_device *, struct comedi_subdevice *);
++	int (*do_cmdtest) (struct comedi_device *, struct comedi_subdevice *, comedi_cmd *);
++	int (*poll) (struct comedi_device *, struct comedi_subdevice *);
++	int (*cancel) (struct comedi_device *, struct comedi_subdevice *);
++	/* int (*do_lock)(struct comedi_device *,struct comedi_subdevice *); */
++	/* int (*do_unlock)(struct comedi_device *,struct comedi_subdevice *); */
+ 
+ 	/* called when the buffer changes */
+-	int (*buf_change) (struct comedi_device *dev, comedi_subdevice *s,
++	int (*buf_change) (struct comedi_device *dev, struct comedi_subdevice *s,
+ 		unsigned long new_size);
+ 
+-	void (*munge) (struct comedi_device *dev, comedi_subdevice *s, void *data,
++	void (*munge) (struct comedi_device *dev, struct comedi_subdevice *s, void *data,
+ 		unsigned int num_bytes, unsigned int start_chan_index);
+ 	enum dma_data_direction async_dma_dir;
+ 
+@@ -198,7 +197,7 @@ struct comedi_buf_page {
+ };
+ 
+ struct comedi_async_struct {
+-	comedi_subdevice *subdevice;
++	struct comedi_subdevice *subdevice;
+ 
+ 	void *prealloc_buf;	/* pre-allocated buffer */
+ 	unsigned int prealloc_bufsz;	/* buffer size, in bytes */
+@@ -237,7 +236,7 @@ struct comedi_async_struct {
+ 	int (*cb_func) (unsigned int flags, void *);
+ 	void *cb_arg;
+ 
+-	int (*inttrig) (struct comedi_device *dev, comedi_subdevice *s,
++	int (*inttrig) (struct comedi_device *dev, struct comedi_subdevice *s,
+ 			unsigned int x);
+ };
+ 
+@@ -277,14 +276,14 @@ struct comedi_device {
+ 	int in_request_module;
+ 
+ 	int n_subdevices;
+-	comedi_subdevice *subdevices;
++	struct comedi_subdevice *subdevices;
+ 
+ 	/* dumb */
+ 	unsigned long iobase;
+ 	unsigned int irq;
+ 
+-	comedi_subdevice *read_subdev;
+-	comedi_subdevice *write_subdev;
++	struct comedi_subdevice *read_subdev;
++	struct comedi_subdevice *write_subdev;
+ 
+ 	struct fasync_struct *async_queue;
+ 
+@@ -294,8 +293,8 @@ struct comedi_device {
+ 
+ struct comedi_device_file_info {
+ 	struct comedi_device *device;
+-	comedi_subdevice *read_subdevice;
+-	comedi_subdevice *write_subdevice;
++	struct comedi_subdevice *read_subdevice;
++	struct comedi_subdevice *write_subdevice;
+ };
+ 
+ #ifdef CONFIG_COMEDI_DEBUG
+@@ -308,7 +307,7 @@ static const int comedi_debug;
+  * function prototypes
+  */
+ 
+-void comedi_event(struct comedi_device *dev, comedi_subdevice *s);
++void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s);
+ void comedi_error(const struct comedi_device *dev, const char *s);
+ 
+ /* we can expand the number of bits used to encode devices/subdevices into
+@@ -323,7 +322,7 @@ static const unsigned COMEDI_SUBDEVICE_MINOR_OFFSET = 1;
+ 
+ struct comedi_device_file_info *comedi_get_device_file_info(unsigned minor);
+ 
+-static inline comedi_subdevice *comedi_get_read_subdevice(
++static inline struct comedi_subdevice *comedi_get_read_subdevice(
+ 				const struct comedi_device_file_info *info)
+ {
+ 	if (info->read_subdevice)
+@@ -333,7 +332,7 @@ static inline comedi_subdevice *comedi_get_read_subdevice(
+ 	return info->device->read_subdev;
+ }
+ 
+-static inline comedi_subdevice *comedi_get_write_subdevice(
++static inline struct comedi_subdevice *comedi_get_write_subdevice(
+ 				const struct comedi_device_file_info *info)
+ {
+ 	if (info->write_subdevice)
+@@ -353,7 +352,7 @@ void cleanup_polling(void);
+ void start_polling(struct comedi_device *);
+ void stop_polling(struct comedi_device *);
+ 
+-int comedi_buf_alloc(struct comedi_device *dev, comedi_subdevice *s, unsigned long
++int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, unsigned long
+ 	new_size);
+ 
+ #ifdef CONFIG_PROC_FS
+@@ -383,11 +382,11 @@ enum subdevice_runflags {
+  */
+ 
+ int do_rangeinfo_ioctl(struct comedi_device *dev, comedi_rangeinfo *arg);
+-int check_chanlist(comedi_subdevice *s, int n, unsigned int *chanlist);
+-void comedi_set_subdevice_runflags(comedi_subdevice *s, unsigned mask,
++int check_chanlist(struct comedi_subdevice *s, int n, unsigned int *chanlist);
++void comedi_set_subdevice_runflags(struct comedi_subdevice *s, unsigned mask,
+ 	unsigned bits);
+-unsigned comedi_get_subdevice_runflags(comedi_subdevice *s);
+-int insn_inval(struct comedi_device *dev, comedi_subdevice *s,
++unsigned comedi_get_subdevice_runflags(struct comedi_subdevice *s);
++int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+ 
+ /* range stuff */
+@@ -428,7 +427,7 @@ static inline int alloc_subdevices(struct comedi_device *dev,
+ 
+ 	dev->n_subdevices = num_subdevices;
+ 	dev->subdevices =
+-		kcalloc(num_subdevices, sizeof(comedi_subdevice), GFP_KERNEL);
++		kcalloc(num_subdevices, sizeof(struct comedi_subdevice), GFP_KERNEL);
+ 	if (!dev->subdevices)
+ 		return -ENOMEM;
+ 	for (i = 0; i < num_subdevices; ++i) {
+@@ -448,7 +447,7 @@ static inline int alloc_private(struct comedi_device *dev, int size)
+ 	return 0;
+ }
+ 
+-static inline unsigned int bytes_per_sample(const comedi_subdevice *subd)
++static inline unsigned int bytes_per_sample(const struct comedi_subdevice *subd)
+ {
+ 	if (subd->subdev_flags & SDF_LSAMPL)
+ 		return sizeof(unsigned int);
+@@ -523,8 +522,8 @@ static inline void *comedi_aux_data(int options[], int n)
+ 
+ int comedi_alloc_board_minor(struct device *hardware_device);
+ void comedi_free_board_minor(unsigned minor);
+-int comedi_alloc_subdevice_minor(struct comedi_device *dev, comedi_subdevice *s);
+-void comedi_free_subdevice_minor(comedi_subdevice *s);
++int comedi_alloc_subdevice_minor(struct comedi_device *dev, struct comedi_subdevice *s);
++void comedi_free_subdevice_minor(struct comedi_subdevice *s);
+ int comedi_pci_auto_config(struct pci_dev *pcidev, const char *board_name);
+ void comedi_pci_auto_unconfig(struct pci_dev *pcidev);
+ struct usb_device;	/* forward declaration */
+diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
+index f0eb7341d9ab..32f3aca2d7f4 100644
+--- a/drivers/staging/comedi/drivers.c
++++ b/drivers/staging/comedi/drivers.c
+@@ -48,12 +48,12 @@
+ #include 
+ 
+ static int postconfig(struct comedi_device *dev);
+-static int insn_rw_emulate_bits(struct comedi_device *dev, comedi_subdevice *s,
++static int insn_rw_emulate_bits(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+ static void *comedi_recognize(comedi_driver * driv, const char *name);
+ static void comedi_report_boards(comedi_driver *driv);
+-static int poll_invalid(struct comedi_device *dev, comedi_subdevice *s);
+-int comedi_buf_alloc(struct comedi_device *dev, comedi_subdevice *s,
++static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s);
++int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned long new_size);
+ 
+ comedi_driver *comedi_drivers;
+@@ -66,7 +66,7 @@ int comedi_modprobe(int minor)
+ static void cleanup_device(struct comedi_device *dev)
+ {
+ 	int i;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	if (dev->subdevices) {
+ 		for (i = 0; i < dev->n_subdevices; i++) {
+@@ -227,7 +227,7 @@ int comedi_driver_unregister(comedi_driver *driver)
+ static int postconfig(struct comedi_device *dev)
+ {
+ 	int i;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	comedi_async *async = NULL;
+ 	int ret;
+ 
+@@ -331,18 +331,18 @@ void comedi_report_boards(comedi_driver *driv)
+ 		printk(" %s\n", driv->driver_name);
+ }
+ 
+-static int poll_invalid(struct comedi_device *dev, comedi_subdevice *s)
++static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	return -EINVAL;
+ }
+ 
+-int insn_inval(struct comedi_device *dev, comedi_subdevice *s,
++int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 	return -EINVAL;
+ }
+ 
+-static int insn_rw_emulate_bits(struct comedi_device *dev, comedi_subdevice *s,
++static int insn_rw_emulate_bits(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 	comedi_insn new_insn;
+@@ -412,7 +412,7 @@ static inline unsigned long kvirt_to_kva(unsigned long adr)
+ 	return kva;
+ }
+ 
+-int comedi_buf_alloc(struct comedi_device *dev, comedi_subdevice *s,
++int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned long new_size)
+ {
+ 	comedi_async *async = s->async;
+@@ -538,7 +538,7 @@ int comedi_buf_alloc(struct comedi_device *dev, comedi_subdevice *s,
+  * and kernel space */
+ unsigned int comedi_buf_munge(comedi_async *async, unsigned int num_bytes)
+ {
+-	comedi_subdevice *s = async->subdevice;
++	struct comedi_subdevice *s = async->subdevice;
+ 	unsigned int count = 0;
+ 	const unsigned num_sample_bytes = bytes_per_sample(s);
+ 
+diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c
+index 3355468266a2..e4920ae934ae 100644
+--- a/drivers/staging/comedi/drivers/8255.c
++++ b/drivers/staging/comedi/drivers/8255.c
+@@ -116,9 +116,9 @@ static comedi_driver driver_8255 = {
+ 
+ COMEDI_INITCLEANUP(driver_8255);
+ 
+-static void do_config(struct comedi_device *dev, comedi_subdevice * s);
++static void do_config(struct comedi_device *dev, struct comedi_subdevice * s);
+ 
+-void subdev_8255_interrupt(struct comedi_device *dev, comedi_subdevice * s)
++void subdev_8255_interrupt(struct comedi_device *dev, struct comedi_subdevice * s)
+ {
+ 	short d;
+ 
+@@ -143,7 +143,7 @@ static int subdev_8255_cb(int dir, int port, int data, unsigned long arg)
+ 	}
+ }
+ 
+-static int subdev_8255_insn(struct comedi_device *dev, comedi_subdevice * s,
++static int subdev_8255_insn(struct comedi_device *dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+@@ -168,7 +168,7 @@ static int subdev_8255_insn(struct comedi_device *dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int subdev_8255_insn_config(struct comedi_device *dev, comedi_subdevice * s,
++static int subdev_8255_insn_config(struct comedi_device *dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int mask;
+@@ -205,7 +205,7 @@ static int subdev_8255_insn_config(struct comedi_device *dev, comedi_subdevice *
+ 	return 1;
+ }
+ 
+-static void do_config(struct comedi_device *dev, comedi_subdevice * s)
++static void do_config(struct comedi_device *dev, struct comedi_subdevice * s)
+ {
+ 	int config;
+ 
+@@ -222,7 +222,7 @@ static void do_config(struct comedi_device *dev, comedi_subdevice * s)
+ 	CALLBACK_FUNC(1, _8255_CR, config, CALLBACK_ARG);
+ }
+ 
+-static int subdev_8255_cmdtest(struct comedi_device *dev, comedi_subdevice * s,
++static int subdev_8255_cmdtest(struct comedi_device *dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -297,21 +297,21 @@ static int subdev_8255_cmdtest(struct comedi_device *dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int subdev_8255_cmd(struct comedi_device *dev, comedi_subdevice * s)
++static int subdev_8255_cmd(struct comedi_device *dev, struct comedi_subdevice * s)
+ {
+ 	/* FIXME */
+ 
+ 	return 0;
+ }
+ 
+-static int subdev_8255_cancel(struct comedi_device *dev, comedi_subdevice * s)
++static int subdev_8255_cancel(struct comedi_device *dev, struct comedi_subdevice * s)
+ {
+ 	/* FIXME */
+ 
+ 	return 0;
+ }
+ 
+-int subdev_8255_init(struct comedi_device *dev, comedi_subdevice * s, int (*cb) (int,
++int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice * s, int (*cb) (int,
+ 		int, int, unsigned long), unsigned long arg)
+ {
+ 	s->type = COMEDI_SUBD_DIO;
+@@ -340,7 +340,7 @@ int subdev_8255_init(struct comedi_device *dev, comedi_subdevice * s, int (*cb)
+ 	return 0;
+ }
+ 
+-int subdev_8255_init_irq(struct comedi_device *dev, comedi_subdevice * s,
++int subdev_8255_init_irq(struct comedi_device *dev, struct comedi_subdevice * s,
+ 	int (*cb) (int, int, int, unsigned long), unsigned long arg)
+ {
+ 	int ret;
+@@ -358,7 +358,7 @@ int subdev_8255_init_irq(struct comedi_device *dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-void subdev_8255_cleanup(struct comedi_device *dev, comedi_subdevice * s)
++void subdev_8255_cleanup(struct comedi_device *dev, struct comedi_subdevice * s)
+ {
+ 	if (s->private) {
+ 		if (subdevpriv->have_irq) {
+@@ -420,7 +420,7 @@ static int dev_8255_detach(struct comedi_device *dev)
+ {
+ 	int i;
+ 	unsigned long iobase;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	printk("comedi%d: 8255: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/8255.h b/drivers/staging/comedi/drivers/8255.h
+index 6837cf83c10b..979311b99275 100644
+--- a/drivers/staging/comedi/drivers/8255.h
++++ b/drivers/staging/comedi/drivers/8255.h
+@@ -28,16 +28,16 @@
+ 
+ #if defined(CONFIG_COMEDI_8255) || defined(CONFIG_COMEDI_8255_MODULE)
+ 
+-int subdev_8255_init(struct comedi_device * dev, comedi_subdevice * s,
++int subdev_8255_init(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	int (*cb) (int, int, int, unsigned long), unsigned long arg);
+-int subdev_8255_init_irq(struct comedi_device * dev, comedi_subdevice * s,
++int subdev_8255_init_irq(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	int (*cb) (int, int, int, unsigned long), unsigned long arg);
+-void subdev_8255_cleanup(struct comedi_device * dev, comedi_subdevice * s);
+-void subdev_8255_interrupt(struct comedi_device * dev, comedi_subdevice * s);
++void subdev_8255_cleanup(struct comedi_device * dev, struct comedi_subdevice * s);
++void subdev_8255_interrupt(struct comedi_device * dev, struct comedi_subdevice * s);
+ 
+ #else
+ 
+-static inline int subdev_8255_init(struct comedi_device * dev, comedi_subdevice * s,
++static inline int subdev_8255_init(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	void *x, unsigned long y)
+ {
+ 	printk("8255 support not configured -- disabling subdevice\n");
+@@ -48,7 +48,7 @@ static inline int subdev_8255_init(struct comedi_device * dev, comedi_subdevice
+ }
+ 
+ static inline void subdev_8255_cleanup(struct comedi_device * dev,
+-	comedi_subdevice * s)
++	struct comedi_subdevice * s)
+ {
+ }
+ 
+diff --git a/drivers/staging/comedi/drivers/acl7225b.c b/drivers/staging/comedi/drivers/acl7225b.c
+index 4c6ad8ab5b61..f273a6f0094e 100644
+--- a/drivers/staging/comedi/drivers/acl7225b.c
++++ b/drivers/staging/comedi/drivers/acl7225b.c
+@@ -50,7 +50,7 @@ static comedi_driver driver_acl7225b = {
+ 
+ COMEDI_INITCLEANUP(driver_acl7225b);
+ 
+-static int acl7225b_do_insn(struct comedi_device *dev, comedi_subdevice * s,
++static int acl7225b_do_insn(struct comedi_device *dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -71,7 +71,7 @@ static int acl7225b_do_insn(struct comedi_device *dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int acl7225b_di_insn(struct comedi_device *dev, comedi_subdevice * s,
++static int acl7225b_di_insn(struct comedi_device *dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -85,7 +85,7 @@ static int acl7225b_di_insn(struct comedi_device *dev, comedi_subdevice * s,
+ 
+ static int acl7225b_attach(struct comedi_device *dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int iobase, iorange;
+ 
+ 	iobase = it->options[0];
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+index 73357d1196ce..d69b87a1691a 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+@@ -32,7 +32,7 @@
+ |                                BYTE_   b_InputClockLevel,                  |
+ |                                BYTE_   b_OutputLevel,                      |
+ |                                BYTE_   b_HardwareGateLevel)
+-INT i_InsnConfig_InitTimer(struct comedi_device *dev,comedi_subdevice *s,
++INT i_InsnConfig_InitTimer(struct comedi_device *dev,struct comedi_subdevice *s,
+ 	comedi_insn *insn,unsigned int *data)
+ |
+ +----------------------------------------------------------------------------+
+@@ -219,7 +219,7 @@ INT i_InsnConfig_InitTimer(struct comedi_device *dev,comedi_subdevice *s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, struct comedi_subdevice * s,
+ 				   comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -406,7 +406,7 @@ INT i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, comedi_subdevice
+ |                                BYTE_ b_ModulNbr,                           |
+ |                                BYTE_ b_TimerNbr,                           |
+ |                                BYTE_ b_InterruptEnable)
+-INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,comedi_subdevice *s,
++INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,struct comedi_subdevice *s,
+ 	comedi_insn *insn,unsigned int *data)                |
+ +----------------------------------------------------------------------------+
+ | Task              : Enable OR Disable the Timer (b_TimerNbr) from selected module     |
+@@ -449,7 +449,7 @@ i_ReturnValue=insn->n;
+ */
+ 
+ INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device * dev,
+-					   comedi_subdevice * s,
++					   struct comedi_subdevice * s,
+ 					   comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -561,7 +561,7 @@ INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device * dev,
+ |                                       (BYTE_     b_BoardHandle,            |
+ |                                        BYTE_     b_ModulNbr,               |
+ |                                        PULONG_ pul_TimerValueArray)
+-INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev,comedi_subdevice *s,
++INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev,struct comedi_subdevice *s,
+ 	comedi_insn *insn,unsigned int *data)        |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the all timer values from selected timer        |
+@@ -590,7 +590,7 @@ INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev,comedi_subdevice
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				     comedi_insn *insn, unsigned int *data)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -669,7 +669,7 @@ INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, comedi_subdevice
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     :INT i_APCI1710_InsnBitsTimer(struct comedi_device *dev,
+-comedi_subdevice *s,comedi_insn *insn,unsigned int *data)                   |
++struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ | Task              : Read write functions for Timer                                          |
+ +----------------------------------------------------------------------------+
+@@ -681,7 +681,7 @@ comedi_subdevice *s,comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnBitsTimer(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnBitsTimer(struct comedi_device * dev, struct comedi_subdevice * s,
+ 			     comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_BitsType;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
+index c17ac8ce251c..9785f925a1d4 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
+@@ -34,20 +34,20 @@
+ /*
+  * 82X54 TIMER INISIALISATION FUNCTION
+  */
+-INT i_APCI1710_InsnConfigInitTimer(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnConfigInitTimer(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,
+-					   comedi_subdevice *s,
++					   struct comedi_subdevice *s,
+ 					   comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * 82X54 READ FUNCTION
+  */
+-INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				     comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_InsnBitsTimer(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnBitsTimer(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			     comedi_insn *insn, unsigned int *data);
+ 
+ /*
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+index 75361fbaeefd..472e182a582a 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+@@ -131,7 +131,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -791,7 +791,7 @@ INT i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, comedi_subdevice
+ |                                                BYTE_ b_CycleMode,          |
+ |                                                BYTE_ b_InterruptEnable)
+ INT i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
+-comedi_subdevice *s,comedi_insn *insn,unsigned int *data)						 |
++struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)						 |
+ +----------------------------------------------------------------------------+
+ | Task              : Enable the chronometer from selected module            |
+ |                     (b_ModulNbr). You must calling the                     |
+@@ -841,7 +841,7 @@ comedi_subdevice *s,comedi_insn *insn,unsigned int *data)						 |
+ */
+ 
+ INT i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	BYTE b_ModulNbr, b_CycleMode, b_InterruptEnable, b_Action;
+@@ -1077,7 +1077,7 @@ INT i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     :INT	i_APCI1710_InsnReadChrono(struct comedi_device *dev,comedi_subdevice *s,
++| Function Name     :INT	i_APCI1710_InsnReadChrono(struct comedi_device *dev,struct comedi_subdevice *s,
+ comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  functions for Timer                                     |
+@@ -1090,7 +1090,7 @@ comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnReadChrono(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnReadChrono(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_ReadType;
+@@ -1757,7 +1757,7 @@ INT i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     : INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,comedi_subdevice *s,
++| Function Name     : INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,struct comedi_subdevice *s,
+ 	comedi_insn *insn,unsigned int *data)                    |
+ +----------------------------------------------------------------------------+
+ | Task              : Sets the output witch has been passed with the         |
+@@ -1877,7 +1877,7 @@ INT i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	BYTE b_ModulNbr, b_OutputChannel, b_InputChannel, b_IOType;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
+index ca4f5e117d5b..588f5735e24d 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
+@@ -35,18 +35,18 @@
+ /*
+  * CHRONOMETER INISIALISATION FUNCTION
+  */
+-INT i_APCI1710_InsnConfigInitChrono(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnConfigInitChrono(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				    comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
+-					    comedi_subdevice *s,
++					    struct comedi_subdevice *s,
+ 					    comedi_insn *insn,
+ 					    unsigned int *data);
+ 
+ /*
+  * CHRONOMETER READ FUNCTION
+  */
+-INT i_APCI1710_InsnReadChrono(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnReadChrono(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			      comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_GetChronoProgressStatus(struct comedi_device *dev,
+@@ -70,5 +70,5 @@ INT i_APCI1710_ConvertChronoValue(struct comedi_device *dev,
+  * CHRONOMETER DIGITAL INPUT OUTPUT FUNCTION
+  */
+ INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,
+-				       comedi_subdevice *s, comedi_insn *insn,
++				       struct comedi_subdevice *s, comedi_insn *insn,
+ 				       unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+index 586a897a633c..3b0c502de480 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+@@ -62,7 +62,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device *dev, |
+-|						comedi_subdevice *s,comedi_insn *insn,unsigned int *data)|
++|						struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)|
+ +----------------------------------------------------------------------------+
+ | Task              : Configure the digital I/O operating mode from selected |
+ |                     module  (b_ModulNbr). You must calling this function be|
+@@ -99,7 +99,7 @@ Activates and deactivates the digital output memory.
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_ModulNbr, b_ChannelAMode, b_ChannelBMode;
+@@ -294,7 +294,7 @@ INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device * dev, comedi_subdevice
+ //
+ //                                             PBYTE_  pb_ChannelStatus)
+ INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusReg;
+@@ -446,7 +446,7 @@ INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT i_APCI1710_InsnWriteDigitalIOChlOnOff(comedi_device
+-|*dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data)
++|*dev,struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)
+ 
+ +----------------------------------------------------------------------------+
+ | Task              : Sets or resets the output witch has been passed with the         |
+@@ -482,7 +482,7 @@ INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device * dev,
+ //                                       BYTE_ b_ModulNbr,
+ //                                       BYTE_ b_OutputChannel)
+ INT i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_WriteValue = 0;
+@@ -729,7 +729,7 @@ INT i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device * dev,
+ //                                       BYTE_ b_ModulNbr,
+ //                                       BYTE_ b_PortValue)
+ INT i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_WriteValue = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h
+index 846e9000651b..68a00d69e5f9 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h
+@@ -27,20 +27,20 @@
+ /*
+  * DIGITAL I/O INISIALISATION FUNCTION
+  */
+-INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * INPUT OUTPUT  FUNCTIONS
+  */
+ INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device *dev,
+-					 comedi_subdevice *s,
++					 struct comedi_subdevice *s,
+ 					 comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device *dev,
+-					  comedi_subdevice *s,
++					  struct comedi_subdevice *s,
+ 					  comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device *dev,
+-					  comedi_subdevice *s,
++					  struct comedi_subdevice *s,
+ 					  comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+index b8b4dedb0940..6939895bc401 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+@@ -61,7 +61,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| INT	i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev,comedi_subdevice *s,
++| INT	i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev,struct comedi_subdevice *s,
+ comedi_insn *insn,unsigned int *data)
+ 
+ +----------------------------------------------------------------------------+
+@@ -75,7 +75,7 @@ comedi_insn *insn,unsigned int *data)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnConfigINCCPT(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnConfigINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_ConfigType;
+@@ -2002,7 +2002,7 @@ INT i_APCI1710_InitFrequencyMeasurement(struct comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     :INT	i_APCI1710_InsnBitsINCCPT(struct comedi_device *dev,comedi_subdevice *s,
++| Function Name     :INT	i_APCI1710_InsnBitsINCCPT(struct comedi_device *dev,struct comedi_subdevice *s,
+ comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ | Task              : Set & Clear Functions for INC_CPT                                          |
+@@ -2015,7 +2015,7 @@ comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnBitsINCCPT(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnBitsINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_BitsType;
+@@ -2939,7 +2939,7 @@ INT i_APCI1710_SetDigitalChlOff(struct comedi_device * dev, BYTE b_ModulNbr)
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     :INT	i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev,comedi_subdevice *s,
++| Function Name     :INT	i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev,struct comedi_subdevice *s,
+ comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ | Task              : Enable Disable functions for INC_CPT                                       |
+@@ -2951,7 +2951,7 @@ comedi_insn *insn,unsigned int *data)                   |
+ | Return Value      :
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1710_InsnWriteINCCPT(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnWriteINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_WriteType;
+@@ -4037,7 +4037,7 @@ INT i_APCI1710_DisableFrequencyMeasurement(struct comedi_device * dev, BYTE b_Mo
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     :INT	i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev,comedi_subdevice *s,
++| Function Name     :INT	i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev,struct comedi_subdevice *s,
+ comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ | Task              : Read and Get functions for INC_CPT                                       |
+@@ -4049,7 +4049,7 @@ comedi_insn *insn,unsigned int *data)                   |
+ | Return Value      :
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1710_InsnReadINCCPT(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnReadINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_ReadType;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
+index a4189aeecaad..a4ffd8a1b15c 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
+@@ -132,16 +132,16 @@
+ #define APCI1710_INCCPT_DISABLEFREQUENCYMEASUREMENT		409
+ 
+ /************ Main Functions *************/
+-INT i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				comedi_insn *insn, unsigned int * data);
+ 
+-INT i_APCI1710_InsnBitsINCCPT(struct comedi_device *dev, comedi_subdevice * s,
++INT i_APCI1710_InsnBitsINCCPT(struct comedi_device *dev, struct comedi_subdevice * s,
+ 			      comedi_insn *insn, unsigned int * data);
+ 
+-INT i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev, comedi_subdevice * s,
++INT i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev, struct comedi_subdevice * s,
+ 			       comedi_insn *insn, unsigned int * data);
+ 
+-INT i_APCI1710_InsnReadINCCPT(struct comedi_device *dev, comedi_subdevice * s,
++INT i_APCI1710_InsnReadINCCPT(struct comedi_device *dev, struct comedi_subdevice * s,
+ 			      comedi_insn *insn, unsigned int * data);
+ 
+ /*********** Supplementary Functions********/
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+index e557e6c40cf6..6f654a39ff7f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+@@ -124,7 +124,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ */
+ 
+ INT i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_IntRegister;
+@@ -415,7 +415,7 @@ INT i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	BYTE b_ModulNbr;
+@@ -709,7 +709,7 @@ INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device * dev,
+    						 PBYTE_ pb_Status)
+ 						 */
+ INT i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusRegister;
+@@ -835,7 +835,7 @@ INT i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device * dev,
+ }
+ 
+ INT i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	data[0] = devpriv->s_InterruptParameters.
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h
+index 1dbdc39f96e0..bf84cb625ea7 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h
+@@ -22,11 +22,11 @@
+ #define APCI1710_PULSEENCODER_WRITE	1
+ 
+ INT i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device *dev,
+-					  comedi_subdevice *s,
++					  struct comedi_subdevice *s,
+ 					  comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device *dev,
+-						  comedi_subdevice *s,
++						  struct comedi_subdevice *s,
+ 						  comedi_insn *insn,
+ 						  unsigned int *data);
+ 
+@@ -34,7 +34,7 @@ INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device *dev,
+  * READ PULSE ENCODER FUNCTIONS
+  */
+ INT i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device *dev,
+-					     comedi_subdevice *s,
++					     struct comedi_subdevice *s,
+ 					     comedi_insn *insn,
+ 					     unsigned int *data);
+ 
+@@ -42,6 +42,6 @@ INT i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device *dev,
+  * WRITE PULSE ENCODER FUNCTIONS
+  */
+ INT i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device *dev,
+-					     comedi_subdevice *s,
++					     struct comedi_subdevice *s,
+ 					     comedi_insn *insn,
+ 					     unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+index 178d773563a1..11927b503f45 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+@@ -58,7 +58,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     :INT i_APCI1710_InsnConfigPWM(struct comedi_device *dev,
+-comedi_subdevice *s,comedi_insn *insn,unsigned int *data)                        |
++struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)                        |
+ +----------------------------------------------------------------------------+
+ | Task              : Pwm Init and Get Pwm Initialisation                    |
+ +----------------------------------------------------------------------------+
+@@ -70,7 +70,7 @@ comedi_subdevice *s,comedi_insn *insn,unsigned int *data)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnConfigPWM(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnConfigPWM(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_ConfigType;
+@@ -1671,7 +1671,7 @@ INT i_APCI1710_GetPWMInitialisation(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     :INT i_APCI1710_InsnWritePWM(struct comedi_device *dev,
+-comedi_subdevice *s,comedi_insn *insn,unsigned int *data)                        |
++struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)                        |
+ +----------------------------------------------------------------------------+
+ | Task              : Pwm Enable Disable and Set New Timing                  |
+ +----------------------------------------------------------------------------+
+@@ -1683,7 +1683,7 @@ comedi_subdevice *s,comedi_insn *insn,unsigned int *data)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnWritePWM(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnWritePWM(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_WriteType;
+@@ -3460,7 +3460,7 @@ INT i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnReadGetPWMStatus(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnReadGetPWMStatus(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -3562,7 +3562,7 @@ INT i_APCI1710_InsnReadGetPWMStatus(struct comedi_device * dev, comedi_subdevice
+ }
+ 
+ INT i_APCI1710_InsnBitsReadPWMInterrupt(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->s_InterruptParameters.
+ 		s_FIFOInterruptParameters[devpriv->
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
+index 0c10b1e8fab4..31a217842e4a 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
+@@ -26,7 +26,7 @@
+ #define APCI1710_PWM_ENABLE		1
+ #define APCI1710_PWM_NEWTIMING		2
+ 
+-INT i_APCI1710_InsnConfigPWM(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnConfigPWM(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			     comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InitPWM(struct comedi_device *dev,
+@@ -50,7 +50,7 @@ INT i_APCI1710_GetPWMInitialisation(struct comedi_device *dev,
+ 				    PBYTE pb_ExternGate,
+ 				    PBYTE pb_InterruptEnable, PBYTE pb_Enable);
+ 
+-INT i_APCI1710_InsnWritePWM(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnWritePWM(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			    comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_EnablePWM(struct comedi_device *dev,
+@@ -68,9 +68,9 @@ INT i_APCI1710_SetNewPWMTiming(struct comedi_device *dev,
+ 
+ INT i_APCI1710_DisablePWM(struct comedi_device *dev, BYTE b_ModulNbr, BYTE b_PWM);
+ 
+-INT i_APCI1710_InsnReadGetPWMStatus(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnReadGetPWMStatus(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				    comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnBitsReadPWMInterrupt(struct comedi_device *dev,
+-					comedi_subdevice *s,
++					struct comedi_subdevice *s,
+ 					comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+index de2b158698f6..e67a2236cb60 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+@@ -133,7 +133,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnConfigInitSSI(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnConfigInitSSI(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -362,7 +362,7 @@ INT i_APCI1710_InsnConfigInitSSI(struct comedi_device * dev, comedi_subdevice *
+ |                                BYTE_     b_SelectedSSI,                    |
+ |                                PULONG_ pul_Position,                       |
+ |                                PULONG_ pul_TurnCpt)
+- INT i_APCI1710_ReadSSIValue(struct comedi_device *dev,comedi_subdevice *s,
++ INT i_APCI1710_ReadSSIValue(struct comedi_device *dev,struct comedi_subdevice *s,
+ 	comedi_insn *insn,unsigned int *data)                       |
+ +----------------------------------------------------------------------------+
+ | Task              :
+@@ -400,7 +400,7 @@ pul_Position	=	(PULONG) &data[0];
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnReadSSIValue(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnReadSSIValue(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -735,7 +735,7 @@ INT i_APCI1710_InsnReadSSIValue(struct comedi_device * dev, comedi_subdevice * s
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h
+index 2a631b8163c4..3fc70532729f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h
+@@ -33,11 +33,11 @@
+ /*
+  * SSI INISIALISATION FUNCTION
+  */
+-INT i_APCI1710_InsnConfigInitSSI(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnConfigInitSSI(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_InsnReadSSIValue(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnReadSSIValue(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				    comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+index a9cad8066a54..97655db21458 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+@@ -131,7 +131,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ */
+ 
+ INT i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	ULONG ul_TimerValue = 0;
+@@ -988,7 +988,7 @@ INT i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_Status;
+@@ -1461,7 +1461,7 @@ INT i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_Status;
+@@ -1701,7 +1701,7 @@ INT i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_Status;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h
+index 80d100a9bc92..a2940f6d845f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h
+@@ -36,22 +36,22 @@
+  * TOR_COUNTER INISIALISATION FUNCTION
+  */
+ INT i_APCI1710_InsnConfigInitTorCounter(struct comedi_device *dev,
+-					comedi_subdevice *s,
++					struct comedi_subdevice *s,
+ 					comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device *dev,
+-						comedi_subdevice *s,
++						struct comedi_subdevice *s,
+ 						comedi_insn *insn,
+ 						unsigned int *data);
+ 
+ INT i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device *dev,
+-						   comedi_subdevice *s,
++						   struct comedi_subdevice *s,
+ 						   comedi_insn *insn,
+ 						   unsigned int *data);
+ /*
+  * TOR_COUNTER READ FUNCTION
+  */
+ INT i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device *dev,
+-							   comedi_subdevice *s,
++							   struct comedi_subdevice *s,
+ 							   comedi_insn *insn,
+ 							   unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+index 9932fc1fa55f..61c1526c43fa 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+@@ -100,7 +100,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnConfigInitTTLIO(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnConfigInitTTLIO(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -406,7 +406,7 @@ APCI1710_TTL_READCHANNEL
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -634,7 +634,7 @@ INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device * dev, comedi_subdevice *
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT i_APCI1710_InsnReadTTLIOAllPortValue(comedi_device
+-*dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data)              |
++*dev,struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)              |
+ +----------------------------------------------------------------------------+
+ | Task              : Read the status from all digital input ports           |
+ |                     (port A, port B and port C) from selected TTL          |
+@@ -656,7 +656,7 @@ INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device * dev, comedi_subdevice *
+ */
+ 
+ INT i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusReg;
+@@ -792,7 +792,7 @@ INT i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+ |                               (BYTE_           b_BoardHandle,              |
+ |                                BYTE_           b_ModulNbr,                 |
+ |                                BYTE_           b_OutputChannel)
+-INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,comedi_subdevice *s,
++INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,struct comedi_subdevice *s,
+ 	comedi_insn *insn,unsigned int *data)           |
+ +----------------------------------------------------------------------------+
+ | Task              : Sets or resets  the output witch has been passed with the         |
+@@ -826,7 +826,7 @@ INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,comedi_subdev
+ */
+ 
+ INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusReg = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h
+index d0bde4bb809a..fe168db93ae6 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h
+@@ -24,21 +24,21 @@
+ /*
+  * TTL INISIALISATION FUNCTION
+  */
+-INT i_APCI1710_InsnConfigInitTTLIO(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnConfigInitTTLIO(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * TTL INPUT FUNCTION
+  */
+-INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+ INT i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
+-					 comedi_subdevice *s,
++					 struct comedi_subdevice *s,
+ 					 comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * TTL OUTPUT FUNCTIONS
+  */
+ INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,
+-					 comedi_subdevice *s,
++					 struct comedi_subdevice *s,
+ 					 comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+index 1e091eca8019..49d6332d9db2 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+@@ -2561,7 +2561,7 @@ COMEDI_PCI_INITCLEANUP(driver_addi, addi_apci_tbl);
+ 
+ static int i_ADDI_Attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int ret, pages, i, n_subdevices;
+ 	DWORD dw_Dummy;
+ 	resource_size_t io_addr[5];
+@@ -3029,14 +3029,14 @@ static irqreturn_t v_ADDI_Interrupt(int irq, void *d PT_REGS_ARG)
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :                                                        |
+-|INT i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev,comedi_subdevice *s,
++|INT i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev,struct comedi_subdevice *s,
+ 							comedi_insn *insn,unsigned int *data)
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              : Read 256 words from EEPROM          				     |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  :(struct comedi_device *dev,comedi_subdevice *s,
++| Input Parameters  :(struct comedi_device *dev,struct comedi_subdevice *s,
+ 			comedi_insn *insn,unsigned int *data) 						 |
+ |                     														 |
+ |                                                 					         |
+@@ -3046,7 +3046,7 @@ static irqreturn_t v_ADDI_Interrupt(int irq, void *d PT_REGS_ARG)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-static int i_ADDIDATA_InsnReadEeprom(struct comedi_device * dev, comedi_subdevice * s,
++static int i_ADDIDATA_InsnReadEeprom(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	WORD w_Data;
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+index 9f3aa717b403..0df1287d14c8 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+@@ -118,103 +118,103 @@ typedef struct {
+ 
+ 	/* ANALOG INPUT */
+ 	int (*i_hwdrv_InsnConfigAnalogInput)(struct comedi_device *dev,
+-					     comedi_subdevice *s,
++					     struct comedi_subdevice *s,
+ 					     comedi_insn *insn,
+ 					     unsigned int *data);
+ 	int (*i_hwdrv_InsnReadAnalogInput)(struct comedi_device *dev,
+-					    comedi_subdevice *s,
++					    struct comedi_subdevice *s,
+ 					    comedi_insn *insn,
+ 					    unsigned int *data);
+ 	int (*i_hwdrv_InsnWriteAnalogInput)(struct comedi_device *dev,
+-					    comedi_subdevice *s,
++					    struct comedi_subdevice *s,
+ 					    comedi_insn *insn,
+ 					    unsigned int *data);
+ 	int (*i_hwdrv_InsnBitsAnalogInput)(struct comedi_device *dev,
+-					   comedi_subdevice *s,
++					   struct comedi_subdevice *s,
+ 					   comedi_insn *insn,
+ 					   unsigned int *data);
+ 	int (*i_hwdrv_CommandTestAnalogInput)(struct comedi_device *dev,
+-					      comedi_subdevice *s,
++					      struct comedi_subdevice *s,
+ 					      comedi_cmd *cmd);
+ 	int (*i_hwdrv_CommandAnalogInput)(struct comedi_device *dev,
+-					  comedi_subdevice *s);
++					  struct comedi_subdevice *s);
+ 	int (*i_hwdrv_CancelAnalogInput)(struct comedi_device *dev,
+-					 comedi_subdevice *s);
++					 struct comedi_subdevice *s);
+ 
+ 	/* Analog Output */
+ 	int (*i_hwdrv_InsnConfigAnalogOutput)(struct comedi_device *dev,
+-					      comedi_subdevice *s,
++					      struct comedi_subdevice *s,
+ 					      comedi_insn *insn,
+ 					      unsigned int *data);
+ 	int (*i_hwdrv_InsnWriteAnalogOutput)(struct comedi_device *dev,
+-					     comedi_subdevice *s,
++					     struct comedi_subdevice *s,
+ 					     comedi_insn *insn,
+ 					     unsigned int *data);
+ 	int (*i_hwdrv_InsnBitsAnalogOutput)(struct comedi_device *dev,
+-					    comedi_subdevice *s,
++					    struct comedi_subdevice *s,
+ 					    comedi_insn *insn,
+ 					    unsigned int *data);
+ 
+ 	/* Digital Input */
+ 	int (*i_hwdrv_InsnConfigDigitalInput) (struct comedi_device *dev,
+-					       comedi_subdevice *s,
++					       struct comedi_subdevice *s,
+ 					       comedi_insn *insn,
+ 					       unsigned int *data);
+ 	int (*i_hwdrv_InsnReadDigitalInput) (struct comedi_device *dev,
+-					     comedi_subdevice *s,
++					     struct comedi_subdevice *s,
+ 					     comedi_insn *insn,
+ 					     unsigned int *data);
+ 	int (*i_hwdrv_InsnWriteDigitalInput) (struct comedi_device *dev,
+-					      comedi_subdevice *s,
++					      struct comedi_subdevice *s,
+ 					      comedi_insn *insn,
+ 					      unsigned int *data);
+ 	int (*i_hwdrv_InsnBitsDigitalInput) (struct comedi_device *dev,
+-					     comedi_subdevice *s,
++					     struct comedi_subdevice *s,
+ 					     comedi_insn *insn,
+ 					     unsigned int *data);
+ 
+ 	/* Digital Output */
+ 	int (*i_hwdrv_InsnConfigDigitalOutput)(struct comedi_device *dev,
+-					       comedi_subdevice *s,
++					       struct comedi_subdevice *s,
+ 					       comedi_insn *insn,
+ 					       unsigned int *data);
+ 	int (*i_hwdrv_InsnWriteDigitalOutput)(struct comedi_device *dev,
+-					      comedi_subdevice *s,
++					      struct comedi_subdevice *s,
+ 					      comedi_insn *insn,
+ 					      unsigned int *data);
+ 	int (*i_hwdrv_InsnBitsDigitalOutput)(struct comedi_device *dev,
+-					     comedi_subdevice *s,
++					     struct comedi_subdevice *s,
+ 					     comedi_insn *insn,
+ 					     unsigned int *data);
+ 	int (*i_hwdrv_InsnReadDigitalOutput)(struct comedi_device *dev,
+-					     comedi_subdevice *s,
++					     struct comedi_subdevice *s,
+ 					     comedi_insn *insn,
+ 					     unsigned int *data);
+ 
+ 	/* TIMER */
+ 	int (*i_hwdrv_InsnConfigTimer)(struct comedi_device *dev,
+-				       comedi_subdevice *s,
++				       struct comedi_subdevice *s,
+ 				       comedi_insn *insn, unsigned int *data);
+ 	int (*i_hwdrv_InsnWriteTimer)(struct comedi_device *dev,
+-				      comedi_subdevice *s, comedi_insn *insn,
++				      struct comedi_subdevice *s, comedi_insn *insn,
+ 				      unsigned int *data);
+-	int (*i_hwdrv_InsnReadTimer)(struct comedi_device *dev, comedi_subdevice *s,
++	int (*i_hwdrv_InsnReadTimer)(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				     comedi_insn *insn, unsigned int *data);
+-	int (*i_hwdrv_InsnBitsTimer)(struct comedi_device *dev, comedi_subdevice *s,
++	int (*i_hwdrv_InsnBitsTimer)(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				     comedi_insn *insn, unsigned int *data);
+ 
+ 	/* TTL IO */
+ 	int (*i_hwdr_ConfigInitTTLIO)(struct comedi_device *dev,
+-				      comedi_subdevice *s, comedi_insn *insn,
++				      struct comedi_subdevice *s, comedi_insn *insn,
+ 				      unsigned int *data);
+-	int (*i_hwdr_ReadTTLIOBits)(struct comedi_device *dev, comedi_subdevice *s,
++	int (*i_hwdr_ReadTTLIOBits)(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				    comedi_insn *insn, unsigned int *data);
+ 	int (*i_hwdr_ReadTTLIOAllPortValue)(struct comedi_device *dev,
+-					    comedi_subdevice *s,
++					    struct comedi_subdevice *s,
+ 					    comedi_insn *insn,
+ 					    unsigned int *data);
+ 	int (*i_hwdr_WriteTTLIOChlOnOff)(struct comedi_device *dev,
+-					 comedi_subdevice *s,
++					 struct comedi_subdevice *s,
+ 					 comedi_insn *insn, unsigned int *data);
+ } boardtype;
+ 
+@@ -461,5 +461,5 @@ static int i_ADDI_Detach(struct comedi_device *dev);
+ static int i_ADDI_Reset(struct comedi_device *dev);
+ 
+ static irqreturn_t v_ADDI_Interrupt(int irq, void *d PT_REGS_ARG);
+-static int i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev, comedi_subdevice *s,
++static int i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				     comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+index 7d6a6e05cdbc..510323d7b7cb 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+@@ -58,7 +58,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ 
+ void i_ADDI_AttachPCI1710(struct comedi_device * dev)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int ret = 0;
+ 	int n_subdevices = 9;
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
+index 599c7c3b68f7..360e9da4c999 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
+@@ -58,7 +58,7 @@ INT i_Flag = 1;
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI035_ConfigTimerWatchdog                      |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Timer , Counter or Watchdog             |
+@@ -109,7 +109,7 @@ INT i_Flag = 1;
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI035_ConfigTimerWatchdog(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI035_ConfigTimerWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Status = 0;
+@@ -254,7 +254,7 @@ INT i_APCI035_ConfigTimerWatchdog(struct comedi_device * dev, comedi_subdevice *
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI035_StartStopWriteTimerWatchdog              |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Start / Stop The Selected Timer , or Watchdog  |
+@@ -279,7 +279,7 @@ INT i_APCI035_ConfigTimerWatchdog(struct comedi_device * dev, comedi_subdevice *
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Command = 0;
+ 	INT i_Count = 0;
+@@ -367,7 +367,7 @@ INT i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI035_ReadTimerWatchdog                        |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Selected Timer , Counter or Watchdog          |
+@@ -391,7 +391,7 @@ INT i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device * dev,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI035_ReadTimerWatchdog(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI035_ReadTimerWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Status = 0;	// Status register
+@@ -427,13 +427,13 @@ INT i_APCI035_ReadTimerWatchdog(struct comedi_device * dev, comedi_subdevice * s
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : INT i_APCI035_ConfigAnalogInput                        |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Analog Input Subdevice                  |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                     comedi_subdevice *s     : Subdevice Pointer            |
++|                     struct comedi_subdevice *s     : Subdevice Pointer            |
+ |                     comedi_insn *insn       : Insn Structure Pointer       |
+ |                     unsigned int *data          : Data Pointer contains        |
+ |                                          configuration parameters as below |
+@@ -447,7 +447,7 @@ INT i_APCI035_ReadTimerWatchdog(struct comedi_device * dev, comedi_subdevice * s
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI035_ConfigAnalogInput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI035_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	devpriv->tsk_Current = current;
+@@ -466,7 +466,7 @@ INT i_APCI035_ConfigAnalogInput(struct comedi_device * dev, comedi_subdevice * s
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI035_ReadAnalogInput                          |
+-|			          (struct comedi_device *dev,comedi_subdevice *s,       |
++|			          (struct comedi_device *dev,struct comedi_subdevice *s,       |
+ |                     comedi_insn *insn,unsigned int *data)                      |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel			         |
+@@ -484,7 +484,7 @@ INT i_APCI035_ConfigAnalogInput(struct comedi_device * dev, comedi_subdevice * s
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI035_ReadAnalogInput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI035_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_CommandRegister = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
+index c0330d8a3137..2f9af7b20b3e 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
+@@ -101,19 +101,19 @@ comedi_lrange range_apci035_ai = { 8, {
+ 
+ /* TIMER */
+ /* timer value is passed as u seconds */
+-INT i_APCI035_ConfigTimerWatchdog(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI035_ConfigTimerWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				  comedi_insn *insn, unsigned int *data);
+ INT i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device *dev,
+-					  comedi_subdevice *s,
++					  struct comedi_subdevice *s,
+ 					  comedi_insn *insn, unsigned int *data);
+-INT i_APCI035_ReadTimerWatchdog(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI035_ReadTimerWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				comedi_insn *insn, unsigned int *data);
+ 
+ /* Temperature Related Defines (Analog Input Subdevice) */
+ 
+-INT i_APCI035_ConfigAnalogInput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI035_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				comedi_insn *insn, unsigned int *data);
+-INT i_APCI035_ReadAnalogInput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI035_ReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			      comedi_insn *insn, unsigned int *data);
+ 
+ /* Interrupt */
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+index bdfe5e95eb61..d3f13eafb6f5 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+@@ -59,7 +59,7 @@ UINT ui_InterruptStatus = 0;
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1032_ConfigDigitalInput                      |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures the digital input Subdevice                 |
+@@ -84,7 +84,7 @@ UINT ui_InterruptStatus = 0;
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1032_ConfigDigitalInput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1032_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue;
+@@ -128,7 +128,7 @@ INT i_APCI1032_ConfigDigitalInput(struct comedi_device * dev, comedi_subdevice *
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1032_Read1DigitalInput                       |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the digital input                 |
+@@ -144,7 +144,7 @@ INT i_APCI1032_ConfigDigitalInput(struct comedi_device * dev, comedi_subdevice *
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1032_Read1DigitalInput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1032_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue = 0;
+@@ -166,7 +166,7 @@ INT i_APCI1032_Read1DigitalInput(struct comedi_device * dev, comedi_subdevice *
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1032_ReadMoreDigitalInput                    |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                     comedi_insn *insn,unsigned int *data)                      |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the Requested digital inputs      |
+@@ -183,7 +183,7 @@ INT i_APCI1032_Read1DigitalInput(struct comedi_device * dev, comedi_subdevice *
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1032_ReadMoreDigitalInput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1032_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_PortValue = data[0];
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
+index cb96ff1778c5..f24704f99f81 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
+@@ -47,13 +47,13 @@
+ //DI
+ // for di read
+ 
+-INT i_APCI1032_ConfigDigitalInput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1032_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				  comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1032_Read1DigitalInput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1032_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1032_ReadMoreDigitalInput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1032_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				    comedi_insn *insn, unsigned int *data);
+ 
+ // Interrupt functions.....
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+index 9a786c9060b6..9806199e0d16 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+@@ -61,7 +61,7 @@ int i_TimerCounter1Enabled = 0, i_TimerCounter2Enabled =
+ /*
+   +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_ConfigDigitalInputEvent                 |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : An event can be generated for each port.               |
+@@ -138,7 +138,7 @@ int i_TimerCounter1Enabled = 0, i_TimerCounter2Enabled =
+ */
+ 
+ INT i_APCI1500_ConfigDigitalInputEvent(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_PatternPolarity = 0, i_PatternTransition = 0, i_PatternMask = 0;
+ 	int i_MaxChannel = 0, i_Count = 0, i_EventMask = 0;
+@@ -500,7 +500,7 @@ INT i_APCI1500_ConfigDigitalInputEvent(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_StartStopInputEvent                     |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              :  Allows or disallows a port event                      |
+@@ -519,7 +519,7 @@ INT i_APCI1500_ConfigDigitalInputEvent(struct comedi_device * dev,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1500_StartStopInputEvent(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI1500_StartStopInputEvent(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_Event1InterruptStatus = 0, i_Event2InterruptStatus =
+@@ -768,7 +768,7 @@ int i_APCI1500_StartStopInputEvent(struct comedi_device * dev, comedi_subdevice
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_Initialisation                          |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the digital input                 |
+@@ -784,7 +784,7 @@ int i_APCI1500_StartStopInputEvent(struct comedi_device * dev, comedi_subdevice
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1500_Initialisation(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1500_Initialisation(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_DummyRead = 0;
+@@ -937,7 +937,7 @@ INT i_APCI1500_Initialisation(struct comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_ReadMoreDigitalInput                    |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                     comedi_insn *insn,unsigned int *data)                      |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the Requested digital inputs      |
+@@ -957,7 +957,7 @@ INT i_APCI1500_Initialisation(struct comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1500_ReadMoreDigitalInput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1500_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_PortValue = data[1];
+@@ -1015,7 +1015,7 @@ INT i_APCI1500_ReadMoreDigitalInput(struct comedi_device * dev, comedi_subdevice
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_ConfigDigitalOutputErrorInterrupt
+-                      (struct comedi_device *dev,comedi_subdevice *s comedi_insn
++                      (struct comedi_device *dev,struct comedi_subdevice *s comedi_insn
+                       *insn,unsigned int *data)                                  |
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+@@ -1025,7 +1025,7 @@ INT i_APCI1500_ReadMoreDigitalInput(struct comedi_device * dev, comedi_subdevice
+ | Input Parameters  : struct comedi_device *dev : Driver handle                     |
+ |                     unsigned int *data         : Data Pointer contains         |
+ |                                          configuration parameters as below |
+-|                      comedi_subdevice *s,   :pointer to subdevice structure
++|                      struct comedi_subdevice *s,   :pointer to subdevice structure
+                        comedi_insn *insn      :pointer to insn structure                                                                                                                |
+ |					  data[0]  :1:Memory on                          |
+ |					            0:Memory off                         |
+@@ -1041,7 +1041,7 @@ INT i_APCI1500_ReadMoreDigitalInput(struct comedi_device * dev, comedi_subdevice
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	devpriv->b_OutputMemoryStatus = data[0];
+ 	return insn->n;
+@@ -1050,7 +1050,7 @@ int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_WriteDigitalOutput                      |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes port value  To the selected port                |
+@@ -1067,7 +1067,7 @@ int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1500_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1500_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	static UINT ui_Temp = 0;
+@@ -1215,13 +1215,13 @@ INT i_APCI1500_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_ConfigCounterTimerWatchdog(comedi_device
+-                   *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data)|
++                   *dev,struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)|
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Watchdog                                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                     comedi_subdevice *s,   :pointer to subdevice structure
++|                     struct comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data         : Data Pointer to read status                                                       data[0]                : 2     APCI1500_1_8_KHZ
+ |                                              1     APCI1500_3_6_KHZ        |
+@@ -1262,7 +1262,7 @@ INT i_APCI1500_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ */
+ 
+ int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_TimerCounterMode, i_MasterConfiguration;
+ 
+@@ -1835,13 +1835,13 @@ int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_StartStopTriggerTimerCounterWatchdog      |
+-|				(struct comedi_device *dev,comedi_subdevice *s,
++|				(struct comedi_device *dev,struct comedi_subdevice *s,
+                          comedi_insn *insn,unsigned int *data);                  |
+ +----------------------------------------------------------------------------+
+ | Task              : Start / Stop or trigger the timer counter or Watchdog  |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev     : Driver handle                 |
+-|                     comedi_subdevice *s,   :pointer to subdevice structure
++|                     struct comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data         : Data Pointer to read status   |
+                       data[0]                : 0     Counter1/Timer1
+@@ -1861,7 +1861,7 @@ int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_CommandAndStatusValue;
+ 
+@@ -2160,13 +2160,13 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_ReadCounterTimerWatchdog                |
+-|			(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,
+                     unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Watchdog                                      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+-|                     comedi_subdevice *s,   :pointer to subdevice structure
++|                     struct comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+                       data[0]                : 0     Counter1/Timer1
+@@ -2183,7 +2183,7 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+ */
+ 
+ int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_CommandAndStatusValue;
+ 	switch (data[0]) {
+@@ -2351,13 +2351,13 @@ int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int  i_APCI1500_ReadInterruptMask                      |
+-|			(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,
+                     unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read the interrupt mask                                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+-|                     comedi_subdevice *s,   :pointer to subdevice structure
++|                     struct comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ 
+@@ -2370,7 +2370,7 @@ int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device * dev,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1500_ReadInterruptMask(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI1500_ReadInterruptMask(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = i_InterruptMask;
+@@ -2382,13 +2382,13 @@ int i_APCI1500_ReadInterruptMask(struct comedi_device * dev, comedi_subdevice *
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int  i_APCI1500_ConfigureInterrupt                     |
+-|			(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,
+                     unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures the interrupt registers                     |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+-|                     comedi_subdevice *s,   :pointer to subdevice structure
++|                     struct comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer                 |
+ 
+@@ -2401,7 +2401,7 @@ int i_APCI1500_ReadInterruptMask(struct comedi_device * dev, comedi_subdevice *
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1500_ConfigureInterrupt(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI1500_ConfigureInterrupt(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Status;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h
+index dc3f3ea78b0f..d824934370b1 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h
+@@ -116,50 +116,50 @@ enum {
+ };
+ 
+  /*----------DIGITAL INPUT----------------*/
+-static int i_APCI1500_Initialisation(struct comedi_device *dev, comedi_subdevice *s,
++static int i_APCI1500_Initialisation(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				     comedi_insn *insn, unsigned int *data);
+ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
+-					      comedi_subdevice *s,
++					      struct comedi_subdevice *s,
+ 					      comedi_insn *insn,
+ 					      unsigned int *data);
+ 
+ static int i_APCI1500_StartStopInputEvent(struct comedi_device *dev,
+-					  comedi_subdevice *s,
++					  struct comedi_subdevice *s,
+ 					  comedi_insn *insn, unsigned int *data);
+ static int i_APCI1500_ReadMoreDigitalInput(struct comedi_device *dev,
+-					   comedi_subdevice *s,
++					   struct comedi_subdevice *s,
+ 					   comedi_insn *insn, unsigned int *data);
+ 
+ /*----------	DIGITAL OUTPUT------------*/
+ static int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device *dev,
+-							comedi_subdevice *s,
++							struct comedi_subdevice *s,
+ 							comedi_insn *insn,
+ 							unsigned int *data);
+ static int i_APCI1500_WriteDigitalOutput(struct comedi_device *dev,
+-					 comedi_subdevice *s,
++					 struct comedi_subdevice *s,
+ 					 comedi_insn *insn, unsigned int *data);
+ 
+ /*----------TIMER----------------*/
+ static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
+-						 comedi_subdevice *s,
++						 struct comedi_subdevice *s,
+ 						 comedi_insn *insn,
+ 						 unsigned int *data);
+ static int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device *dev,
+-							   comedi_subdevice *s,
++							   struct comedi_subdevice *s,
+ 							   comedi_insn *insn,
+ 							   unsigned int *data);
+ static int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device *dev,
+-					       comedi_subdevice *s,
++					       struct comedi_subdevice *s,
+ 					       comedi_insn *insn,
+ 					       unsigned int *data);
+ static int i_APCI1500_ReadInterruptMask(struct comedi_device *dev,
+-					comedi_subdevice *s,
++					struct comedi_subdevice *s,
+ 					comedi_insn *insn, unsigned int *data);
+ 
+ /*----------INTERRUPT HANDLER------*/
+ static void v_APCI1500_Interrupt(int irq, void *d);
+ static int i_APCI1500_ConfigureInterrupt(struct comedi_device *dev,
+-					 comedi_subdevice *s,
++					 struct comedi_subdevice *s,
+ 					 comedi_insn *insn, unsigned int *data);
+ /*----------RESET---------------*/
+ static int i_APCI1500_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
+index 5ad419b9fa8e..21dde69dad03 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
+@@ -56,13 +56,13 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_Read1DigitalInput                       |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the digital input                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|		       comedi_subdevice *s,   :pointer to subdevice structure
++|		       struct comedi_subdevice *s,   :pointer to subdevice structure
+                        comedi_insn *insn      :pointer to insn structure     |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -73,7 +73,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1516_Read1DigitalInput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1516_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue = 0;
+@@ -96,13 +96,13 @@ INT i_APCI1516_Read1DigitalInput(struct comedi_device * dev, comedi_subdevice *
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_ReadMoreDigitalInput                    |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                     comedi_insn *insn,unsigned int *data)                      |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the Requested digital inputs      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                      comedi_subdevice *s,   :pointer to subdevice structure
++|                      struct comedi_subdevice *s,   :pointer to subdevice structure
+                        comedi_insn *insn      :pointer to insn structure     |
+ |                      unsigned int *data         : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -114,7 +114,7 @@ INT i_APCI1516_Read1DigitalInput(struct comedi_device * dev, comedi_subdevice *
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1516_ReadMoreDigitalInput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1516_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -149,7 +149,7 @@ INT i_APCI1516_ReadMoreDigitalInput(struct comedi_device * dev, comedi_subdevice
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_ConfigDigitalOutput (struct comedi_device *dev,
+-                    comedi_subdevice *s comedi_insn *insn,unsigned int *data)    |
++                    struct comedi_subdevice *s comedi_insn *insn,unsigned int *data)    |
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Digital Output Subdevice.               |
+@@ -157,7 +157,7 @@ INT i_APCI1516_ReadMoreDigitalInput(struct comedi_device * dev, comedi_subdevice
+ | Input Parameters  : struct comedi_device *dev : Driver handle                     |
+ |                     unsigned int *data         : Data Pointer contains         |
+ |                                          configuration parameters as below |
+-|                      comedi_subdevice *s,   :pointer to subdevice structure
++|                      struct comedi_subdevice *s,   :pointer to subdevice structure
+                        comedi_insn *insn      :pointer to insn structure                                                           |
+ |					  data[0]  :1:Memory on                          |
+ |					            0:Memory off                         |
+@@ -171,7 +171,7 @@ INT i_APCI1516_ReadMoreDigitalInput(struct comedi_device * dev, comedi_subdevice
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1516_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI1516_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	devpriv->b_OutputMemoryStatus = data[0];
+@@ -181,13 +181,13 @@ int i_APCI1516_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_WriteDigitalOutput                      |
+-|			(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,
+                      unsigned int *data)                                         |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes port value  To the selected port                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                     comedi_subdevice *s,   :pointer to subdevice structure
++|                     struct comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                    unsigned int *data           : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -199,7 +199,7 @@ int i_APCI1516_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1516_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1516_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp, ui_Temp1;
+@@ -341,13 +341,13 @@ INT i_APCI1516_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_ReadDigitalOutput                       |
+-|			(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,
+                     unsigned int *data) 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                     comedi_subdevice *s,   :pointer to subdevice structure
++|                     struct comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -359,7 +359,7 @@ INT i_APCI1516_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1516_ReadDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1516_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -401,13 +401,13 @@ INT i_APCI1516_ReadDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_ConfigWatchdog(struct comedi_device *dev,
+-                      comedi_subdevice *s,comedi_insn *insn,unsigned int *data)  |
++                      struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)  |
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Watchdog                                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+-|                     comedi_subdevice *s,   :pointer to subdevice structure
++|                     struct comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status                                                     |
+ +----------------------------------------------------------------------------+
+@@ -419,7 +419,7 @@ INT i_APCI1516_ReadDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1516_ConfigWatchdog(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI1516_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0] == 0) {
+@@ -447,13 +447,13 @@ int i_APCI1516_ConfigWatchdog(struct comedi_device * dev, comedi_subdevice * s,
+  /*
+     +----------------------------------------------------------------------------+
+     | Function   Name   : int i_APCI1516_StartStopWriteWatchdog                  |
+-    |                           (struct comedi_device *dev,comedi_subdevice *s,
++    |                           (struct comedi_device *dev,struct comedi_subdevice *s,
+     comedi_insn *insn,unsigned int *data);                      |
+     +----------------------------------------------------------------------------+
+     | Task              : Start / Stop The Watchdog                              |
+     +----------------------------------------------------------------------------+
+     | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-    |                     comedi_subdevice *s,   :pointer to subdevice structure
++    |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+     comedi_insn *insn      :pointer to insn structure      |
+     |                     unsigned int *data          : Data Pointer to read status  |
+     +----------------------------------------------------------------------------+
+@@ -465,7 +465,7 @@ int i_APCI1516_ConfigWatchdog(struct comedi_device * dev, comedi_subdevice * s,
+     +----------------------------------------------------------------------------+
+   */
+ 
+-int i_APCI1516_StartStopWriteWatchdog(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI1516_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+@@ -492,13 +492,13 @@ int i_APCI1516_StartStopWriteWatchdog(struct comedi_device * dev, comedi_subdevi
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_ReadWatchdog                            |
+-|			(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,
+                     unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Watchdog                                      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+-|                     comedi_subdevice *s,   :pointer to subdevice structure
++|                     struct comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -510,7 +510,7 @@ int i_APCI1516_StartStopWriteWatchdog(struct comedi_device * dev, comedi_subdevi
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1516_ReadWatchdog(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI1516_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = inw(devpriv->i_IobaseAddon + APCI1516_WATCHDOG_STATUS) & 0x1;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h
+index b166257775ce..8d857e7adc13 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h
+@@ -38,26 +38,26 @@
+ // Hardware Layer  functions for Apci1516
+ 
+ //Digital Input
+-INT i_APCI1516_ReadMoreDigitalInput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1516_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				    comedi_insn *insn, unsigned int *data);
+-INT i_APCI1516_Read1DigitalInput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1516_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+ 
+ //Digital Output
+-int i_APCI1516_ConfigDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI1516_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+-INT i_APCI1516_WriteDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1516_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				  comedi_insn *insn, unsigned int *data);
+-INT i_APCI1516_ReadDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1516_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+ // timer value is passed as u seconds
+-int i_APCI1516_ConfigWatchdog(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI1516_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			      comedi_insn *insn, unsigned int *data);
+-int i_APCI1516_StartStopWriteWatchdog(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI1516_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				      comedi_insn *insn, unsigned int *data);
+-int i_APCI1516_ReadWatchdog(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI1516_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			    comedi_insn *insn, unsigned int *data);
+ 
+ //reset
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+index 44b4965d8ecc..e45390f3f988 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+@@ -62,7 +62,7 @@ UINT ui_InterruptData, ui_Type;
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_ConfigDigitalInput                      |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures the digital input Subdevice                 |
+@@ -86,7 +86,7 @@ UINT ui_InterruptData, ui_Type;
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1564_ConfigDigitalInput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1564_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	devpriv->tsk_Current = current;
+@@ -131,7 +131,7 @@ INT i_APCI1564_ConfigDigitalInput(struct comedi_device * dev, comedi_subdevice *
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_Read1DigitalInput                       |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the digital input                 |
+@@ -147,7 +147,7 @@ INT i_APCI1564_ConfigDigitalInput(struct comedi_device * dev, comedi_subdevice *
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1564_Read1DigitalInput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1564_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue = 0;
+@@ -171,7 +171,7 @@ INT i_APCI1564_Read1DigitalInput(struct comedi_device * dev, comedi_subdevice *
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_ReadMoreDigitalInput                    |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                     comedi_insn *insn,unsigned int *data)                      |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the Requested digital inputs      |
+@@ -187,7 +187,7 @@ INT i_APCI1564_Read1DigitalInput(struct comedi_device * dev, comedi_subdevice *
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1564_ReadMoreDigitalInput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1564_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_PortValue = data[0];
+@@ -233,7 +233,7 @@ INT i_APCI1564_ReadMoreDigitalInput(struct comedi_device * dev, comedi_subdevice
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_ConfigDigitalOutput                     |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Digital Output Subdevice.               |
+@@ -255,7 +255,7 @@ INT i_APCI1564_ReadMoreDigitalInput(struct comedi_device * dev, comedi_subdevice
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1564_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1564_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command = 0;
+@@ -296,7 +296,7 @@ INT i_APCI1564_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_WriteDigitalOutput                      |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes port value  To the selected port                |
+@@ -312,7 +312,7 @@ INT i_APCI1564_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1564_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1564_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp, ui_Temp1;
+@@ -470,7 +470,7 @@ INT i_APCI1564_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_ReadDigitalOutput                       |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+@@ -486,7 +486,7 @@ INT i_APCI1564_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1564_ReadDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1564_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+@@ -537,7 +537,7 @@ INT i_APCI1564_ReadDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_ConfigTimerCounterWatchdog              |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Timer , Counter or Watchdog             |
+@@ -565,7 +565,7 @@ INT i_APCI1564_ReadDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0;
+ 	devpriv->tsk_Current = current;
+@@ -695,7 +695,7 @@ INT i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_StartStopWriteTimerCounterWatchdog      |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Start / Stop The Selected Timer , Counter or Watchdog  |
+@@ -719,7 +719,7 @@ INT i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0;
+ 	if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+@@ -795,7 +795,7 @@ INT i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_ReadTimerCounterWatchdog                |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Selected Timer , Counter or Watchdog          |
+@@ -814,7 +814,7 @@ INT i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0;
+ 
+@@ -878,7 +878,7 @@ INT i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   :  int i_APCI1564_ReadInterruptStatus                    |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              :Reads the interrupt status register                     |
+@@ -892,7 +892,7 @@ INT i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1564_ReadInterruptStatus(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI1564_ReadInterruptStatus(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	*data = ui_Type;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
+index 4b40da7879de..ff094f043caf 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
+@@ -82,34 +82,34 @@
+ 
+ //DI
+ // for di read
+-INT i_APCI1564_ConfigDigitalInput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1564_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				  comedi_insn *insn, unsigned int *data);
+-INT i_APCI1564_Read1DigitalInput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1564_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+-INT i_APCI1564_ReadMoreDigitalInput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1564_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				    comedi_insn *insn, unsigned int *data);
+ 
+ //DO
+-int i_APCI1564_ConfigDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI1564_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+-INT i_APCI1564_WriteDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1564_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				  comedi_insn *insn, unsigned int *data);
+-INT i_APCI1564_ReadDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1564_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+-int i_APCI1564_ReadInterruptStatus(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI1564_ReadInterruptStatus(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+ // timer value is passed as u seconds
+ INT i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev,
+-					  comedi_subdevice *s,
++					  struct comedi_subdevice *s,
+ 					  comedi_insn *insn, unsigned int *data);
+ int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
+-						  comedi_subdevice *s,
++						  struct comedi_subdevice *s,
+ 						  comedi_insn *insn,
+ 						  unsigned int *data);
+ int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device *dev,
+-					comedi_subdevice *s,
++					struct comedi_subdevice *s,
+ 					comedi_insn *insn, unsigned int *data);
+ 
+ // INTERRUPT
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
+index 74b0bd484bde..0cab42aa0bb8 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
+@@ -59,7 +59,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT   i_APCI16XX_InsnConfigInitTTLIO                   |
+ |                          (struct comedi_device    *dev,                           |
+-|                           comedi_subdevice *s,                             |
++|                           struct comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+@@ -91,7 +91,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ */
+ 
+ int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Command = 0;
+@@ -252,7 +252,7 @@ int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT     i_APCI16XX_InsnBitsReadTTLIO                   |
+ |                          (struct comedi_device    *dev,                           |
+-|                           comedi_subdevice *s,                             |
++|                           struct comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+@@ -284,7 +284,7 @@ int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ */
+ 
+ int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Command = 0;
+@@ -412,7 +412,7 @@ int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT i_APCI16XX_InsnReadTTLIOAllPortValue               |
+ |                          (struct comedi_device    *dev,                           |
+-|                           comedi_subdevice *s,                             |
++|                           struct comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+@@ -431,7 +431,7 @@ int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device * dev,
+ */
+ 
+ int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_Command = (BYTE) CR_AREF(insn->chanspec);
+ 	INT i_ReturnValue = insn->n;
+@@ -537,7 +537,7 @@ int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT     i_APCI16XX_InsnBitsWriteTTLIO                  |
+ |                          (struct comedi_device    *dev,                           |
+-|                           comedi_subdevice *s,                             |
++|                           struct comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+@@ -571,7 +571,7 @@ int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+ */
+ 
+ int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Command = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h
+index 9f8f2b752431..ae66bfeeefaf 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h
+@@ -63,7 +63,7 @@ static const comedi_lrange range_apci16xx_ttl = { 12,
+ */
+ 
+ int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device *dev,
+-				   comedi_subdevice *s, comedi_insn *insn,
++				   struct comedi_subdevice *s, comedi_insn *insn,
+ 				   unsigned int *data);
+ 
+ /*
+@@ -73,11 +73,11 @@ int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device *dev,
+ */
+ 
+ int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device *dev,
+-				 comedi_subdevice *s, comedi_insn *insn,
++				 struct comedi_subdevice *s, comedi_insn *insn,
+ 				 unsigned int *data);
+ 
+ int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
+-					 comedi_subdevice *s,
++					 struct comedi_subdevice *s,
+ 					 comedi_insn *insn, unsigned int *data);
+ 
+ /*
+@@ -87,7 +87,7 @@ int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
+ */
+ 
+ int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device *dev,
+-				  comedi_subdevice *s, comedi_insn *insn,
++				  struct comedi_subdevice *s, comedi_insn *insn,
+ 				  unsigned int *data);
+ 
+ int i_APCI16XX_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
+index dcb837dee3b1..6a692cf3fb13 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
+@@ -56,7 +56,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2016_ConfigDigitalOutput                     |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Digital Output Subdevice.               |
+@@ -75,7 +75,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI2016_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI2016_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if ((data[0] != 0) && (data[0] != 1)) {
+@@ -95,7 +95,7 @@ int i_APCI2016_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2016_WriteDigitalOutput                      |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes port value  To the selected port                |
+@@ -111,7 +111,7 @@ int i_APCI2016_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI2016_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI2016_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_NoOfChannel;
+@@ -250,7 +250,7 @@ int i_APCI2016_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2016_BitsDigitalOutput                       |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+@@ -266,7 +266,7 @@ int i_APCI2016_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI2016_BitsDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI2016_BitsDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+@@ -320,13 +320,13 @@ int i_APCI2016_BitsDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2016_ConfigWatchdog                          |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Watchdog                                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+-|                     comedi_subdevice *s,   :pointer to subdevice structure |
++|                     struct comedi_subdevice *s,   :pointer to subdevice structure |
+ |                     comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -337,7 +337,7 @@ int i_APCI2016_BitsDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI2016_ConfigWatchdog(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI2016_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -363,13 +363,13 @@ int i_APCI2016_ConfigWatchdog(struct comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2016_StartStopWriteWatchdog                  |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Start / Stop The Watchdog                              |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                     comedi_subdevice *s,   :pointer to subdevice structure |
++|                     struct comedi_subdevice *s,   :pointer to subdevice structure |
+ |                     comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -380,7 +380,7 @@ int i_APCI2016_ConfigWatchdog(struct comedi_device * dev, comedi_subdevice * s,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI2016_StartStopWriteWatchdog(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI2016_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -409,13 +409,13 @@ int i_APCI2016_StartStopWriteWatchdog(struct comedi_device * dev, comedi_subdevi
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2016_ReadWatchdog                            |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Watchdog                                      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                     comedi_subdevice *s,   :pointer to subdevice structure |
++|                     struct comedi_subdevice *s,   :pointer to subdevice structure |
+ |                     comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -427,7 +427,7 @@ int i_APCI2016_StartStopWriteWatchdog(struct comedi_device * dev, comedi_subdevi
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI2016_ReadWatchdog(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI2016_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	udelay(5);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
+index 765de4212ed0..ca98f6a51675 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
+@@ -40,25 +40,25 @@
+ // Hardware Layer  functions for Apci2016
+ 
+ //DO
+-int i_APCI2016_ConfigDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI2016_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+ 
+-int i_APCI2016_WriteDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI2016_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				  comedi_insn *insn, unsigned int *data);
+ 
+-int i_APCI2016_BitsDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI2016_BitsDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+ // timer value is passed as u seconds
+ 
+-int i_APCI2016_ConfigWatchdog(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI2016_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			      comedi_insn *insn, unsigned int *data);
+ 
+-int i_APCI2016_StartStopWriteWatchdog(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI2016_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				      comedi_insn *insn, unsigned int *data);
+ 
+-int i_APCI2016_ReadWatchdog(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI2016_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			    comedi_insn *insn, unsigned int *data);
+ 
+ // Interrupt functions.....
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
+index b536667398cf..067ee8679d3e 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
+@@ -57,7 +57,7 @@ UINT ui_InterruptData, ui_Type;
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2032_ConfigDigitalOutput                     |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Digital Output Subdevice.               |
+@@ -79,7 +79,7 @@ UINT ui_InterruptData, ui_Type;
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI2032_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI2032_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command = 0;
+@@ -117,7 +117,7 @@ int i_APCI2032_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2032_WriteDigitalOutput                      |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes port value  To the selected port                |
+@@ -134,7 +134,7 @@ int i_APCI2032_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI2032_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI2032_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp, ui_Temp1;
+@@ -296,7 +296,7 @@ INT i_APCI2032_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2032_ReadDigitalOutput                       |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+@@ -313,7 +313,7 @@ INT i_APCI2032_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI2032_ReadDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI2032_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+@@ -363,13 +363,13 @@ INT i_APCI2032_ReadDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : INT i_APCI2032_ConfigWatchdog(comedi_device
+-                   *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data)|
++                   *dev,struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)|
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Watchdog                                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                     comedi_subdevice *s,   :pointer to subdevice structure
++|                     struct comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status                                                                                                             |
+ +----------------------------------------------------------------------------+
+@@ -380,7 +380,7 @@ INT i_APCI2032_ReadDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI2032_ConfigWatchdog(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI2032_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0] == 0) {
+@@ -403,13 +403,13 @@ INT i_APCI2032_ConfigWatchdog(struct comedi_device * dev, comedi_subdevice * s,
+  /*
+     +----------------------------------------------------------------------------+
+     | Function   Name   : int i_APCI2032_StartStopWriteWatchdog                  |
+-    |                           (struct comedi_device *dev,comedi_subdevice *s,
++    |                           (struct comedi_device *dev,struct comedi_subdevice *s,
+     comedi_insn *insn,unsigned int *data);                      |
+     +----------------------------------------------------------------------------+
+     | Task              : Start / Stop The Watchdog                              |
+     +----------------------------------------------------------------------------+
+     | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-    |                     comedi_subdevice *s,   :pointer to subdevice structure
++    |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+     comedi_insn *insn      :pointer to insn structure      |
+     |                     unsigned int *data          : Data Pointer to read status  |
+     +----------------------------------------------------------------------------+
+@@ -421,7 +421,7 @@ INT i_APCI2032_ConfigWatchdog(struct comedi_device * dev, comedi_subdevice * s,
+     +----------------------------------------------------------------------------+
+   */
+ 
+-int i_APCI2032_StartStopWriteWatchdog(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI2032_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+@@ -448,13 +448,13 @@ int i_APCI2032_StartStopWriteWatchdog(struct comedi_device * dev, comedi_subdevi
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2032_ReadWatchdog                            |
+-|			(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,
+                     unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Watchdog                                      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+-|                     comedi_subdevice *s,   :pointer to subdevice structure
++|                     struct comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -466,7 +466,7 @@ int i_APCI2032_StartStopWriteWatchdog(struct comedi_device * dev, comedi_subdevi
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI2032_ReadWatchdog(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI2032_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -530,7 +530,7 @@ void v_APCI2032_Interrupt(int irq, void *d)
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   :  int i_APCI2032_ReadInterruptStatus                    |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              :Reads the interrupt status register                     |
+@@ -544,7 +544,7 @@ void v_APCI2032_Interrupt(int irq, void *d)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI2032_ReadInterruptStatus(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI2032_ReadInterruptStatus(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	*data = ui_Type;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h
+index 8ceefb07d503..3aab1d999315 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h
+@@ -55,22 +55,22 @@
+ // Hardware Layer  functions for Apci2032
+ 
+ //DO
+-int i_APCI2032_ConfigDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI2032_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+-INT i_APCI2032_WriteDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI2032_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				  comedi_insn *insn, unsigned int *data);
+-INT i_APCI2032_ReadDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI2032_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+-int i_APCI2032_ReadInterruptStatus(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI2032_ReadInterruptStatus(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+ // timer value is passed as u seconds
+-INT i_APCI2032_ConfigWatchdog(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI2032_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			      comedi_insn *insn, unsigned int *data);
+-int i_APCI2032_StartStopWriteWatchdog(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI2032_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				      comedi_insn *insn, unsigned int *data);
+-int i_APCI2032_ReadWatchdog(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI2032_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			    comedi_insn *insn, unsigned int *data);
+ 
+ // Interrupt functions.....
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
+index b297f6f96089..3f7dc9a67197 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
+@@ -56,13 +56,13 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_Read1DigitalInput                       |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the digital input                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|		       comedi_subdevice *s,   :pointer to subdevice structure
++|		       struct comedi_subdevice *s,   :pointer to subdevice structure
+                        comedi_insn *insn      :pointer to insn structure     |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -73,7 +73,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI2200_Read1DigitalInput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI2200_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue = 0;
+@@ -94,13 +94,13 @@ INT i_APCI2200_Read1DigitalInput(struct comedi_device * dev, comedi_subdevice *
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_ReadMoreDigitalInput                    |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                     comedi_insn *insn,unsigned int *data)                      |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the Requested digital inputs      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                      comedi_subdevice *s,   :pointer to subdevice structure
++|                      struct comedi_subdevice *s,   :pointer to subdevice structure
+                        comedi_insn *insn      :pointer to insn structure     |
+ |                      unsigned int *data         : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -112,7 +112,7 @@ INT i_APCI2200_Read1DigitalInput(struct comedi_device * dev, comedi_subdevice *
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI2200_ReadMoreDigitalInput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI2200_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -147,7 +147,7 @@ INT i_APCI2200_ReadMoreDigitalInput(struct comedi_device * dev, comedi_subdevice
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_ConfigDigitalOutput (struct comedi_device *dev,
+-                    comedi_subdevice *s comedi_insn *insn,unsigned int *data)    |
++                    struct comedi_subdevice *s comedi_insn *insn,unsigned int *data)    |
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Digital Output Subdevice.               |
+@@ -155,7 +155,7 @@ INT i_APCI2200_ReadMoreDigitalInput(struct comedi_device * dev, comedi_subdevice
+ | Input Parameters  : struct comedi_device *dev : Driver handle                     |
+ |                     unsigned int *data         : Data Pointer contains         |
+ |                                          configuration parameters as below |
+-|                      comedi_subdevice *s,   :pointer to subdevice structure
++|                      struct comedi_subdevice *s,   :pointer to subdevice structure
+                        comedi_insn *insn      :pointer to insn structure                                                           |
+ |					  data[0]  :1:Memory on                          |
+ |					            0:Memory off                         |
+@@ -169,7 +169,7 @@ INT i_APCI2200_ReadMoreDigitalInput(struct comedi_device * dev, comedi_subdevice
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI2200_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI2200_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	devpriv->b_OutputMemoryStatus = data[0];
+@@ -179,13 +179,13 @@ int i_APCI2200_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_WriteDigitalOutput                      |
+-|			(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,
+                      unsigned int *data)                                         |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes port value  To the selected port                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                     comedi_subdevice *s,   :pointer to subdevice structure
++|                     struct comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                    unsigned int *data           : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -197,7 +197,7 @@ int i_APCI2200_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI2200_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI2200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp, ui_Temp1;
+@@ -336,13 +336,13 @@ INT i_APCI2200_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_ReadDigitalOutput                       |
+-|			(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,
+                     unsigned int *data) 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                     comedi_subdevice *s,   :pointer to subdevice structure
++|                     struct comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -354,7 +354,7 @@ INT i_APCI2200_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI2200_ReadDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI2200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -400,13 +400,13 @@ INT i_APCI2200_ReadDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_ConfigWatchdog(struct comedi_device *dev,
+-                      comedi_subdevice *s,comedi_insn *insn,unsigned int *data)  |
++                      struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)  |
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Watchdog                                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+-|                     comedi_subdevice *s,   :pointer to subdevice structure
++|                     struct comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status                                                                                                             |
+ +----------------------------------------------------------------------------+
+@@ -418,7 +418,7 @@ INT i_APCI2200_ReadDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI2200_ConfigWatchdog(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI2200_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0] == 0) {
+@@ -446,13 +446,13 @@ int i_APCI2200_ConfigWatchdog(struct comedi_device * dev, comedi_subdevice * s,
+  /*
+     +----------------------------------------------------------------------------+
+     | Function   Name   : int i_APCI2200_StartStopWriteWatchdog                  |
+-    |                           (struct comedi_device *dev,comedi_subdevice *s,
++    |                           (struct comedi_device *dev,struct comedi_subdevice *s,
+     comedi_insn *insn,unsigned int *data);                      |
+     +----------------------------------------------------------------------------+
+     | Task              : Start / Stop The Watchdog                              |
+     +----------------------------------------------------------------------------+
+     | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-    |                     comedi_subdevice *s,   :pointer to subdevice structure
++    |                     struct comedi_subdevice *s,   :pointer to subdevice structure
+     comedi_insn *insn      :pointer to insn structure      |
+     |                     unsigned int *data          : Data Pointer to read status  |
+     +----------------------------------------------------------------------------+
+@@ -464,7 +464,7 @@ int i_APCI2200_ConfigWatchdog(struct comedi_device * dev, comedi_subdevice * s,
+     +----------------------------------------------------------------------------+
+   */
+ 
+-int i_APCI2200_StartStopWriteWatchdog(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI2200_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+@@ -491,13 +491,13 @@ int i_APCI2200_StartStopWriteWatchdog(struct comedi_device * dev, comedi_subdevi
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_ReadWatchdog                            |
+-|			(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,
+                     unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Watchdog                                      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+-|                     comedi_subdevice *s,   :pointer to subdevice structure
++|                     struct comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -509,7 +509,7 @@ int i_APCI2200_StartStopWriteWatchdog(struct comedi_device * dev, comedi_subdevi
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI2200_ReadWatchdog(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI2200_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] =
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h
+index ab1bb309767a..778bea21dd63 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h
+@@ -36,25 +36,25 @@
+ // Hardware Layer  functions for Apci2200
+ 
+ //Digital Input
+-INT i_APCI2200_ReadMoreDigitalInput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI2200_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				    comedi_insn *insn, unsigned int *data);
+-INT i_APCI2200_Read1DigitalInput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI2200_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+ 
+ //Digital Output
+-int i_APCI2200_ConfigDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI2200_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+-INT i_APCI2200_WriteDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI2200_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				  comedi_insn *insn, unsigned int *data);
+-INT i_APCI2200_ReadDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI2200_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+-int i_APCI2200_ConfigWatchdog(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI2200_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			      comedi_insn *insn, unsigned int *data);
+-int i_APCI2200_StartStopWriteWatchdog(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI2200_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				      comedi_insn *insn, unsigned int *data);
+-int i_APCI2200_ReadWatchdog(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI2200_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			    comedi_insn *insn, unsigned int *data);
+ 
+ //reset
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+index 6aaab8cf3c1a..d8c495ddaae7 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+@@ -58,14 +58,14 @@ static UINT ui_Temp = 0;
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnConfigAnalogInput(struct comedi_device *dev,|
+-|  comedi_subdevice *s,comedi_insn *insn,unsigned int *data)					 |
++|  struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)					 |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+ | Task              : Calls card specific function  					     |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev									 |
+-|                     comedi_subdevice *s									 |
++|                     struct comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+ |                     unsigned int *data      					         		 |
+ +----------------------------------------------------------------------------+
+@@ -74,7 +74,7 @@ static UINT ui_Temp = 0;
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_InsnConfigAnalogInput(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI3120_InsnConfigAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT i;
+@@ -125,7 +125,7 @@ int i_APCI3120_InsnConfigAnalogInput(struct comedi_device * dev, comedi_subdevic
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev,  |
+-|			comedi_subdevice *s,comedi_insn *insn, unsigned int *data)	 |
++|			struct comedi_subdevice *s,comedi_insn *insn, unsigned int *data)	 |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+ | Task              :  card specific function								 |
+@@ -136,7 +136,7 @@ int i_APCI3120_InsnConfigAnalogInput(struct comedi_device * dev, comedi_subdevic
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev									 |
+-|                     comedi_subdevice *s									 |
++|                     struct comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+ |                     unsigned int *data     									 |
+ +----------------------------------------------------------------------------+
+@@ -145,7 +145,7 @@ int i_APCI3120_InsnConfigAnalogInput(struct comedi_device * dev, comedi_subdevic
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	USHORT us_ConvertTiming, us_TmpValue, i;
+@@ -394,14 +394,14 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, comedi_subdevice
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev,|
+-| 											     comedi_subdevice *s)|
++| 											     struct comedi_subdevice *s)|
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              : Stops Cyclic acquisition  						     |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev									 |
+-|                     comedi_subdevice *s									 |
++|                     struct comedi_subdevice *s									 |
+ |                                                 					         |
+ +----------------------------------------------------------------------------+
+ | Return Value      :0              					                     |
+@@ -409,7 +409,7 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, comedi_subdevice
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_StopCyclicAcquisition(struct comedi_device * dev, comedi_subdevice * s)
++int i_APCI3120_StopCyclicAcquisition(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	// Disable A2P Fifo write and AMWEN signal
+ 	outw(0, devpriv->i_IobaseAddon + 4);
+@@ -460,7 +460,7 @@ int i_APCI3120_StopCyclicAcquisition(struct comedi_device * dev, comedi_subdevic
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev|
+-|			,comedi_subdevice *s,comedi_cmd *cmd)					 |
++|			,struct comedi_subdevice *s,comedi_cmd *cmd)					 |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              : Test validity for a command for cyclic anlog input     |
+@@ -468,7 +468,7 @@ int i_APCI3120_StopCyclicAcquisition(struct comedi_device * dev, comedi_subdevic
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev									 |
+-|                     comedi_subdevice *s									 |
++|                     struct comedi_subdevice *s									 |
+ |                     comedi_cmd *cmd              					         |
+ +----------------------------------------------------------------------------+
+ | Return Value      :0              					                     |
+@@ -476,7 +476,7 @@ int i_APCI3120_StopCyclicAcquisition(struct comedi_device * dev, comedi_subdevic
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_CommandTestAnalogInput(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI3120_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -617,7 +617,7 @@ int i_APCI3120_CommandTestAnalogInput(struct comedi_device * dev, comedi_subdevi
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     : int i_APCI3120_CommandAnalogInput(struct comedi_device *dev,  |
+-|												comedi_subdevice *s) |
++|												struct comedi_subdevice *s) |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              : Does asynchronous acquisition                          |
+@@ -625,7 +625,7 @@ int i_APCI3120_CommandTestAnalogInput(struct comedi_device * dev, comedi_subdevi
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev									 |
+-|                     comedi_subdevice *s									 |
++|                     struct comedi_subdevice *s									 |
+ |                     														 |
+ +----------------------------------------------------------------------------+
+ | Return Value      :              					                         |
+@@ -633,7 +633,7 @@ int i_APCI3120_CommandTestAnalogInput(struct comedi_device * dev, comedi_subdevi
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_CommandAnalogInput(struct comedi_device * dev, comedi_subdevice * s)
++int i_APCI3120_CommandAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 
+@@ -690,7 +690,7 @@ int i_APCI3120_CommandAnalogInput(struct comedi_device * dev, comedi_subdevice *
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :  int i_APCI3120_CyclicAnalogInput(int mode,            |
+-|		 	   struct comedi_device * dev,comedi_subdevice * s)			 |
++|		 	   struct comedi_device * dev,struct comedi_subdevice * s)			 |
+ +----------------------------------------------------------------------------+
+ | Task              : This is used for analog input cyclic acquisition       |
+ |			  Performs the command operations.                       |
+@@ -708,7 +708,7 @@ int i_APCI3120_CommandAnalogInput(struct comedi_device * dev, comedi_subdevice *
+ */
+ 
+ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+-	comedi_subdevice * s)
++	struct comedi_subdevice * s)
+ {
+ 	BYTE b_Tmp;
+ 	UINT ui_Tmp, ui_DelayTiming = 0, ui_TimerValue1 = 0, dmalen0 =
+@@ -1275,7 +1275,7 @@ int i_APCI3120_Reset(struct comedi_device * dev)
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     : int i_APCI3120_SetupChannelList(struct comedi_device * dev,   |
+-|                     comedi_subdevice * s, int n_chan,unsigned int *chanlist|
++|                     struct comedi_subdevice * s, int n_chan,unsigned int *chanlist|
+ |			  ,char check)											 |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+@@ -1286,7 +1286,7 @@ int i_APCI3120_Reset(struct comedi_device * dev)
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device * dev									 |
+-|                     comedi_subdevice * s									 |
++|                     struct comedi_subdevice * s									 |
+ |                     int n_chan                   					         |
+ 			  unsigned int *chanlist
+ 			  char check
+@@ -1296,7 +1296,7 @@ int i_APCI3120_Reset(struct comedi_device * dev)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_SetupChannelList(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI3120_SetupChannelList(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	int n_chan, unsigned int *chanlist, char check)
+ {
+ 	unsigned int i;		//, differencial=0, bipolar=0;
+@@ -1428,7 +1428,7 @@ void v_APCI3120_Interrupt(int irq, void *d)
+ 	USHORT us_TmpValue;
+ 	BYTE b_DummyRead;
+ 
+-	comedi_subdevice *s = dev->subdevices + 0;
++	struct comedi_subdevice *s = dev->subdevices + 0;
+ 	ui_Check = 1;
+ 
+ 	int_daq = inw(dev->iobase + APCI3120_RD_STATUS) & 0xf000;	// get IRQ reasons
+@@ -1634,7 +1634,7 @@ void v_APCI3120_Interrupt(int irq, void *d)
+ {
+        int n_chan,i;
+        short *data;
+-       comedi_subdevice *s=dev->subdevices+0;
++       struct comedi_subdevice *s=dev->subdevices+0;
+        comedi_async *async = s->async;
+        data=async->data+async->buf_int_ptr;//new samples added from here onwards
+        n_chan=devpriv->ui_AiNbrofChannels;
+@@ -1657,7 +1657,7 @@ void v_APCI3120_Interrupt(int irq, void *d)
+ int i_APCI3120_InterruptHandleEos(struct comedi_device * dev)
+ {
+ 	int n_chan, i;
+-	comedi_subdevice *s = dev->subdevices + 0;
++	struct comedi_subdevice *s = dev->subdevices + 0;
+ 	int err = 1;
+ 
+ 	n_chan = devpriv->ui_AiNbrofChannels;
+@@ -1699,7 +1699,7 @@ int i_APCI3120_InterruptHandleEos(struct comedi_device * dev)
+ void v_APCI3120_InterruptDma(int irq, void *d)
+ {
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s = dev->subdevices + 0;
++	struct comedi_subdevice *s = dev->subdevices + 0;
+ 	unsigned int next_dma_buf, samplesinbuf;
+ 	unsigned long low_word, high_word, var;
+ 
+@@ -1879,7 +1879,7 @@ void v_APCI3120_InterruptDma(int irq, void *d)
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device|
+-|*dev,comedi_subdevice *s,short *dma,short *data,int n)				     |
++|*dev,struct comedi_subdevice *s,short *dma,short *data,int n)				     |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              : This function copies the data from DMA buffer to the   |
+@@ -1887,7 +1887,7 @@ void v_APCI3120_InterruptDma(int irq, void *d)
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev									 |
+-|                     comedi_subdevice *s									 |
++|                     struct comedi_subdevice *s									 |
+ |                     short *dma											 |
+ |                     short *data,int n          					         |
+ +----------------------------------------------------------------------------+
+@@ -1896,7 +1896,7 @@ void v_APCI3120_InterruptDma(int irq, void *d)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-/*void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,comedi_subdevice *s,short *dma,short *data,int n)
++/*void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,struct comedi_subdevice *s,short *dma,short *data,int n)
+ {
+ 	int i,j,m;
+ 
+@@ -1926,7 +1926,7 @@ void v_APCI3120_InterruptDma(int irq, void *d)
+ }
+ */
+ void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device * dev,
+-	comedi_subdevice * s, short * dma_buffer, unsigned int num_samples)
++	struct comedi_subdevice * s, short * dma_buffer, unsigned int num_samples)
+ {
+ 	devpriv->ui_AiActualScan +=
+ 		(s->async->cur_chan + num_samples) / devpriv->ui_AiScanLength;
+@@ -1945,14 +1945,14 @@ void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnConfigTimer(struct comedi_device *dev,          |
+-|	comedi_subdevice *s,comedi_insn *insn,unsigned int *data) 			     |
++|	struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data) 			     |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              :Configure Timer 2  								     |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev									 |
+-|                     comedi_subdevice *s									 |
++|                     struct comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+ |                     unsigned int *data 										 |
+ |                     														 |
+@@ -1967,7 +1967,7 @@ void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_InsnConfigTimer(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI3120_InsnConfigTimer(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -2093,13 +2093,13 @@ int i_APCI3120_InsnConfigTimer(struct comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnWriteTimer(struct comedi_device *dev,           |
+-|                    comedi_subdevice *s, comedi_insn *insn,unsigned int *data)  |
++|                    struct comedi_subdevice *s, comedi_insn *insn,unsigned int *data)  |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+ | Task              :    To start and stop the timer		                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev									 |
+-|                     comedi_subdevice *s									 |
++|                     struct comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+ |                     unsigned int *data                                         |
+ |                                                                            |
+@@ -2118,7 +2118,7 @@ int i_APCI3120_InsnConfigTimer(struct comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_InsnWriteTimer(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI3120_InsnWriteTimer(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -2284,14 +2284,14 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     : int i_APCI3120_InsnReadTimer(struct comedi_device *dev,           |
+-|		comedi_subdevice *s,comedi_insn *insn, unsigned int *data) 		 |
++|		struct comedi_subdevice *s,comedi_insn *insn, unsigned int *data) 		 |
+ |                                        									 |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+ | Task              : read the Timer value 				                 	 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : 	struct comedi_device *dev									 |
+-|                     comedi_subdevice *s									 |
++|                     struct comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+ |                     unsigned int *data 										 |
+ |                     														 |
+@@ -2304,7 +2304,7 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device * dev, comedi_subdevice * s,
+ |                    													     |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI3120_InsnReadTimer(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI3120_InsnReadTimer(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_Tmp;
+@@ -2361,7 +2361,7 @@ int i_APCI3120_InsnReadTimer(struct comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev,     |
+-|			comedi_subdevice *s, comedi_insn *insn,unsigned int *data)   |
++|			struct comedi_subdevice *s, comedi_insn *insn,unsigned int *data)   |
+ |                                        									 |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+@@ -2369,7 +2369,7 @@ int i_APCI3120_InsnReadTimer(struct comedi_device * dev, comedi_subdevice * s,
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev									 |
+-|                     comedi_subdevice *s									 |
++|                     struct comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+ |                     unsigned int *data 										 |
+ +----------------------------------------------------------------------------+
+@@ -2378,8 +2378,10 @@ int i_APCI3120_InsnReadTimer(struct comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_InsnReadDigitalInput(struct comedi_device * dev, comedi_subdevice
+-	* s, comedi_insn * insn, unsigned int * data)
++int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev,
++				    struct comedi_subdevice *s,
++				    comedi_insn *insn,
++				    unsigned int *data)
+ {
+ 	UINT ui_Chan, ui_TmpValue;
+ 
+@@ -2404,7 +2406,7 @@ int i_APCI3120_InsnReadDigitalInput(struct comedi_device * dev, comedi_subdevice
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnBitsDigitalInput(struct comedi_device *dev, |
+-|comedi_subdevice *s, comedi_insn *insn,unsigned int *data)                      |
++|struct comedi_subdevice *s, comedi_insn *insn,unsigned int *data)                      |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              : Reads the value of the Digital input Port i.e.4channels|
+@@ -2412,7 +2414,7 @@ int i_APCI3120_InsnReadDigitalInput(struct comedi_device * dev, comedi_subdevice
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev									 |
+-|                     comedi_subdevice *s									 |
++|                     struct comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+ |                     unsigned int *data 										 |
+ +----------------------------------------------------------------------------+
+@@ -2420,7 +2422,7 @@ int i_APCI3120_InsnReadDigitalInput(struct comedi_device * dev, comedi_subdevice
+ |                    													     |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI3120_InsnBitsDigitalInput(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI3120_InsnBitsDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue;
+@@ -2443,14 +2445,14 @@ int i_APCI3120_InsnBitsDigitalInput(struct comedi_device * dev, comedi_subdevice
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device    |
+-| *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data)				 |
++| *dev,struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)				 |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+ | Task              :Configure the output memory ON or OFF				     |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :struct comedi_device *dev									 	 |
+-|                     comedi_subdevice *s									 |
++|                     struct comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+ |                     unsigned int *data 										 |
+ +----------------------------------------------------------------------------+
+@@ -2460,7 +2462,7 @@ int i_APCI3120_InsnBitsDigitalInput(struct comedi_device * dev, comedi_subdevice
+ */
+ 
+ int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	if ((data[0] != 0) && (data[0] != 1)) {
+@@ -2486,14 +2488,14 @@ int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device *dev,    |
+-|		comedi_subdevice *s, comedi_insn *insn,unsigned int *data) 		 |
++|		struct comedi_subdevice *s, comedi_insn *insn,unsigned int *data) 		 |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              : write diatal output port							     |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev									 |
+-|                     comedi_subdevice *s									 |
++|                     struct comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+ |                     unsigned int *data 										 |
+                       data[0]     Value to be written
+@@ -2505,8 +2507,10 @@ int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device * dev, comedi_subdevice
+-	* s, comedi_insn * insn, unsigned int * data)
++int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device * dev,
++				     struct comedi_subdevice *s,
++				     comedi_insn *insn,
++				     unsigned int *data)
+ {
+ 	if ((data[0] > this_board->i_DoMaxdata) || (data[0] < 0)) {
+ 
+@@ -2537,14 +2541,14 @@ int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device * dev, comedi_subdevic
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev,|
+-|comedi_subdevice *s,comedi_insn *insn,unsigned int *data) 			             |
++|struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data) 			             |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+ | Task              : Write digiatl output								     |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev								 	 |
+-|                     comedi_subdevice *s									 |
++|                     struct comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+ |                     unsigned int *data 										 |
+                       data[0]     Value to be written
+@@ -2556,8 +2560,10 @@ int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device * dev, comedi_subdevic
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device * dev, comedi_subdevice
+-	* s, comedi_insn * insn, unsigned int * data)
++int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev,
++				      struct comedi_subdevice *s,
++				      comedi_insn *insn,
++				      unsigned int *data)
+ {
+ 
+ 	UINT ui_Temp1;
+@@ -2618,14 +2624,14 @@ int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device * dev, comedi_subdevi
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev,|
+-|comedi_subdevice *s, comedi_insn *insn,unsigned int *data)			             |
++|struct comedi_subdevice *s, comedi_insn *insn,unsigned int *data)			             |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              : Write  analog output   							     |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev									 |
+-|                     comedi_subdevice *s									 |
++|                     struct comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+ |                     unsigned int *data  										 |
+ +----------------------------------------------------------------------------+
+@@ -2634,8 +2640,10 @@ int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device * dev, comedi_subdevi
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device * dev, comedi_subdevice
+-	* s, comedi_insn * insn, unsigned int * data)
++int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev,
++				     struct comedi_subdevice *s,
++				     comedi_insn *insn,
++				     unsigned int *data)
+ {
+ 	UINT ui_Range, ui_Channel;
+ 	USHORT us_TmpValue;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
+index ee346f6d0ba1..f5fdb6c4894f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
+@@ -178,19 +178,19 @@ typedef struct {
+ // Function Declaration For APCI-3120
+ 
+ // Internal functions
+-int i_APCI3120_SetupChannelList(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI3120_SetupChannelList(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				int n_chan, unsigned int *chanlist, char check);
+ int i_APCI3120_ExttrigEnable(struct comedi_device *dev);
+ int i_APCI3120_ExttrigDisable(struct comedi_device *dev);
+-int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev, comedi_subdevice *s);
++int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s);
+ int i_APCI3120_Reset(struct comedi_device *dev);
+ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device *dev,
+-				 comedi_subdevice *s);
++				 struct comedi_subdevice *s);
+ // Interrupt functions
+ void v_APCI3120_Interrupt(int irq, void *d);
+-//UPDATE-0.7.57->0.7.68 void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,comedi_subdevice *s,short *dma,short *data,int n);
++//UPDATE-0.7.57->0.7.68 void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,struct comedi_subdevice *s,short *dma,short *data,int n);
+ void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,
+-					   comedi_subdevice *s,
++					   struct comedi_subdevice *s,
+ 					   short *dma_buffer,
+ 					   unsigned int num_samples);
+ int i_APCI3120_InterruptHandleEos(struct comedi_device *dev);
+@@ -198,44 +198,44 @@ void v_APCI3120_InterruptDma(int irq, void *d);
+ 
+ // TIMER
+ 
+-int i_APCI3120_InsnConfigTimer(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI3120_InsnConfigTimer(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			       comedi_insn *insn, unsigned int *data);
+-int i_APCI3120_InsnWriteTimer(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI3120_InsnWriteTimer(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			      comedi_insn *insn, unsigned int *data);
+-int i_APCI3120_InsnReadTimer(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI3120_InsnReadTimer(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			     comedi_insn *insn, unsigned int *data);
+ 
+ //DI
+ // for di read
+ 
+-int i_APCI3120_InsnBitsDigitalInput(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI3120_InsnBitsDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				    comedi_insn *insn, unsigned int *data);
+-int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				    comedi_insn *insn, unsigned int *data);
+ 
+ //DO
+ //int i_APCI3120_WriteDigitalOutput(struct comedi_device *dev, BYTE data);
+ int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device *dev,
+-				       comedi_subdevice *s, comedi_insn *insn,
++				       struct comedi_subdevice *s, comedi_insn *insn,
+ 				       unsigned int *data);
+-int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				     comedi_insn *insn, unsigned int *data);
+-int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				      comedi_insn *insn, unsigned int *data);
+ 
+ //AO
+ //int i_APCI3120_Write1AnalogValue(struct comedi_device *dev,UINT ui_Range,UINT ui_Channel,UINT data );
+-int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				     comedi_insn *insn, unsigned int *data);
+ 
+ //AI HArdware layer
+ 
+-int i_APCI3120_InsnConfigAnalogInput(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI3120_InsnConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				     comedi_insn *insn, unsigned int *data);
+-int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+-int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				      comedi_cmd *cmd);
+-int i_APCI3120_CommandAnalogInput(struct comedi_device *dev, comedi_subdevice *s);
+-//int i_APCI3120_CancelAnalogInput(struct comedi_device *dev, comedi_subdevice *s);
+-int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev, comedi_subdevice *s);
++int i_APCI3120_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s);
++//int i_APCI3120_CancelAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s);
++int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+index f07e0b1cf8f8..2fdbd7d2ef13 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+@@ -530,7 +530,7 @@ INT i_APCI3200_GetChannelCalibrationValue(struct comedi_device * dev,
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadDigitalInput                       |
+-  |			  (struct comedi_device *dev,comedi_subdevice *s,               |
++  |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+   |                      comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              : Read  value  of the selected channel or port           |
+@@ -550,7 +550,7 @@ INT i_APCI3200_GetChannelCalibrationValue(struct comedi_device * dev,
+   +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI3200_ReadDigitalInput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI3200_ReadDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp = 0;
+@@ -592,7 +592,7 @@ INT i_APCI3200_ReadDigitalInput(struct comedi_device * dev, comedi_subdevice * s
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ConfigDigitalOutput                     |
+-  |			  (struct comedi_device *dev,comedi_subdevice *s,				 |
++  |			  (struct comedi_device *dev,struct comedi_subdevice *s,				 |
+   |                      comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              : Configures The Digital Output Subdevice.               |
+@@ -608,7 +608,7 @@ INT i_APCI3200_ReadDigitalInput(struct comedi_device * dev, comedi_subdevice * s
+   |																	 |
+   +----------------------------------------------------------------------------+
+ */
+-int i_APCI3200_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI3200_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -629,13 +629,13 @@ int i_APCI3200_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_WriteDigitalOutput                      |
+-  |			  (struct comedi_device *dev,comedi_subdevice *s,				 |
++  |			  (struct comedi_device *dev,struct comedi_subdevice *s,				 |
+   |                      comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              : writes To the digital Output Subdevice                 |
+   +----------------------------------------------------------------------------+
+   | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-  |                     comedi_subdevice *s     : Subdevice Pointer            |
++  |                     struct comedi_subdevice *s     : Subdevice Pointer            |
+   |                     comedi_insn *insn       : Insn Structure Pointer       |
+   |                     unsigned int *data          : Data Pointer contains        |
+   |                                          configuration parameters as below |
+@@ -653,7 +653,7 @@ int i_APCI3200_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3200_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI3200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp = 0, ui_Temp1 = 0;
+@@ -746,7 +746,7 @@ INT i_APCI3200_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadDigitalOutput                       |
+-  |			  (struct comedi_device *dev,comedi_subdevice *s,               |
++  |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+   |                      comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              : Read  value  of the selected channel or port           |
+@@ -766,7 +766,7 @@ INT i_APCI3200_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3200_ReadDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI3200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+@@ -807,13 +807,13 @@ INT i_APCI3200_ReadDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : INT i_APCI3200_ConfigAnalogInput                       |
+-  |			  (struct comedi_device *dev,comedi_subdevice *s,               |
++  |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+   |                      comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              : Configures The Analog Input Subdevice                  |
+   +----------------------------------------------------------------------------+
+   | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-  |                     comedi_subdevice *s     : Subdevice Pointer            |
++  |                     struct comedi_subdevice *s     : Subdevice Pointer            |
+   |                     comedi_insn *insn       : Insn Structure Pointer       |
+   |                     unsigned int *data          : Data Pointer contains        |
+   |                                          configuration parameters as below |
+@@ -874,7 +874,7 @@ INT i_APCI3200_ReadDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3200_ConfigAnalogInput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI3200_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -1334,7 +1334,7 @@ INT i_APCI3200_ConfigAnalogInput(struct comedi_device * dev, comedi_subdevice *
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadAnalogInput                         |
+-  |			          (struct comedi_device *dev,comedi_subdevice *s,       |
++  |			          (struct comedi_device *dev,struct comedi_subdevice *s,       |
+   |                     comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read  value  of the selected channel			         |
+@@ -1361,7 +1361,7 @@ INT i_APCI3200_ConfigAnalogInput(struct comedi_device * dev, comedi_subdevice *
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3200_ReadAnalogInput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI3200_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_DummyValue = 0;
+@@ -1633,7 +1633,7 @@ INT i_APCI3200_ReadAnalogInput(struct comedi_device * dev, comedi_subdevice * s,
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_Read1AnalogInputChannel                 |
+-  |			          (struct comedi_device *dev,comedi_subdevice *s,       |
++  |			          (struct comedi_device *dev,struct comedi_subdevice *s,       |
+   |                     comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read  value  of the selected channel			         |
+@@ -1652,7 +1652,7 @@ INT i_APCI3200_ReadAnalogInput(struct comedi_device * dev, comedi_subdevice * s,
+   +----------------------------------------------------------------------------+
+ */
+ INT i_APCI3200_Read1AnalogInputChannel(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_EOC = 0;
+ 	UINT ui_ChannelNo = 0;
+@@ -1759,7 +1759,7 @@ INT i_APCI3200_Read1AnalogInputChannel(struct comedi_device * dev,
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadCalibrationOffsetValue              |
+-  |			          (struct comedi_device *dev,comedi_subdevice *s,       |
++  |			          (struct comedi_device *dev,struct comedi_subdevice *s,       |
+   |                     comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read calibration offset  value  of the selected channel|
+@@ -1895,7 +1895,7 @@ int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device * dev, UINT * dat
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadCalibrationGainValue                |
+-  |			          (struct comedi_device *dev,comedi_subdevice *s,       |
++  |			          (struct comedi_device *dev,struct comedi_subdevice *s,       |
+   |                     comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read calibration gain  value  of the selected channel  |
+@@ -2030,7 +2030,7 @@ int i_APCI3200_ReadCalibrationGainValue(struct comedi_device * dev, UINT * data)
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadCJCValue                            |
+-  |			          (struct comedi_device *dev,comedi_subdevice *s,       |
++  |			          (struct comedi_device *dev,struct comedi_subdevice *s,       |
+   |                     comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read CJC  value  of the selected channel               |
+@@ -2150,7 +2150,7 @@ int i_APCI3200_ReadCJCValue(struct comedi_device * dev, unsigned int * data)
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadCJCCalOffset                        |
+-  |			          (struct comedi_device *dev,comedi_subdevice *s,       |
++  |			          (struct comedi_device *dev,struct comedi_subdevice *s,       |
+   |                     comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read CJC calibration offset  value  of the selected channel
+@@ -2265,7 +2265,7 @@ int i_APCI3200_ReadCJCCalOffset(struct comedi_device * dev, unsigned int * data)
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadCJCGainValue                        |
+-  |			          (struct comedi_device *dev,comedi_subdevice *s,       |
++  |			          (struct comedi_device *dev,struct comedi_subdevice *s,       |
+   |                     comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read CJC calibration gain value
+@@ -2375,13 +2375,13 @@ int i_APCI3200_ReadCJCCalGain(struct comedi_device * dev, unsigned int * data)
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_InsnBits_AnalogInput_Test               |
+-  |			  (struct comedi_device *dev,comedi_subdevice *s,               |
++  |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+   |                      comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              : Tests the Selected Anlog Input Channel                 |
+   +----------------------------------------------------------------------------+
+   | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-  |                     comedi_subdevice *s     : Subdevice Pointer            |
++  |                     struct comedi_subdevice *s     : Subdevice Pointer            |
+   |                     comedi_insn *insn       : Insn Structure Pointer       |
+   |                     unsigned int *data          : Data Pointer contains        |
+   |                                          configuration parameters as below |
+@@ -2405,7 +2405,7 @@ int i_APCI3200_ReadCJCCalGain(struct comedi_device * dev, unsigned int * data)
+ */
+ 
+ INT i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Configuration = 0;
+ 	INT i_Temp;		//,i_TimeUnit;
+@@ -2510,13 +2510,13 @@ INT i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device * dev,
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_InsnWriteReleaseAnalogInput             |
+-  |			  (struct comedi_device *dev,comedi_subdevice *s,               |
++  |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+   |                      comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              :  Resets the channels                                                      |
+   +----------------------------------------------------------------------------+
+   | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-  |                     comedi_subdevice *s     : Subdevice Pointer            |
++  |                     struct comedi_subdevice *s     : Subdevice Pointer            |
+   |                     comedi_insn *insn       : Insn Structure Pointer       |
+   |                     unsigned int *data          : Data Pointer
+   +----------------------------------------------------------------------------+
+@@ -2530,7 +2530,7 @@ INT i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device * dev,
+ */
+ 
+ INT i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	i_APCI3200_Reset(dev);
+ 	return insn->n;
+@@ -2539,7 +2539,7 @@ INT i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device * dev,
+ /*
+   +----------------------------------------------------------------------------+
+   | Function name     :int i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev|
+-  |			,comedi_subdevice *s,comedi_cmd *cmd)			         |
++  |			,struct comedi_subdevice *s,comedi_cmd *cmd)			         |
+   |                                        									 |
+   +----------------------------------------------------------------------------+
+   | Task              : Test validity for a command for cyclic anlog input     |
+@@ -2547,7 +2547,7 @@ INT i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device * dev,
+   |                     										                 |
+   +----------------------------------------------------------------------------+
+   | Input Parameters  : struct comedi_device *dev									 |
+-  |                     comedi_subdevice *s									 |
++  |                     struct comedi_subdevice *s									 |
+   |                     comedi_cmd *cmd              					         |
+   |                     										                 |
+   |
+@@ -2560,7 +2560,7 @@ INT i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device * dev,
+   +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3200_CommandTestAnalogInput(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI3200_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 
+@@ -2749,14 +2749,14 @@ int i_APCI3200_CommandTestAnalogInput(struct comedi_device * dev, comedi_subdevi
+ /*
+   +----------------------------------------------------------------------------+
+   | Function name     :int i_APCI3200_StopCyclicAcquisition(struct comedi_device *dev,|
+-  | 											     comedi_subdevice *s)|
++  | 											     struct comedi_subdevice *s)|
+   |                                        									 |
+   +----------------------------------------------------------------------------+
+   | Task              : Stop the  acquisition  						     |
+   |                     										                 |
+   +----------------------------------------------------------------------------+
+   | Input Parameters  : struct comedi_device *dev									 |
+-  |                     comedi_subdevice *s									 |
++  |                     struct comedi_subdevice *s									 |
+   |                                                 					         |
+   +----------------------------------------------------------------------------+
+   | Return Value      :0              					                     |
+@@ -2764,7 +2764,7 @@ int i_APCI3200_CommandTestAnalogInput(struct comedi_device * dev, comedi_subdevi
+   +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3200_StopCyclicAcquisition(struct comedi_device * dev, comedi_subdevice * s)
++int i_APCI3200_StopCyclicAcquisition(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	UINT ui_Configuration = 0;
+ 	//i_InterruptFlag=0;
+@@ -2797,7 +2797,7 @@ int i_APCI3200_StopCyclicAcquisition(struct comedi_device * dev, comedi_subdevic
+ /*
+   +----------------------------------------------------------------------------+
+   | Function name     : int i_APCI3200_CommandAnalogInput(struct comedi_device *dev,  |
+-  |												comedi_subdevice *s) |
++  |												struct comedi_subdevice *s) |
+   |                                        									 |
+   +----------------------------------------------------------------------------+
+   | Task              : Does asynchronous acquisition                          |
+@@ -2805,7 +2805,7 @@ int i_APCI3200_StopCyclicAcquisition(struct comedi_device * dev, comedi_subdevic
+   |                     										                 |
+   +----------------------------------------------------------------------------+
+   | Input Parameters  : struct comedi_device *dev									 |
+-  |                     comedi_subdevice *s									 |
++  |                     struct comedi_subdevice *s									 |
+   |                     														 |
+   |                     														 |
+   +----------------------------------------------------------------------------+
+@@ -2814,7 +2814,7 @@ int i_APCI3200_StopCyclicAcquisition(struct comedi_device * dev, comedi_subdevic
+   +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3200_CommandAnalogInput(struct comedi_device * dev, comedi_subdevice * s)
++int i_APCI3200_CommandAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	UINT ui_Configuration = 0;
+@@ -3502,7 +3502,7 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ int i_APCI3200_InterruptHandleEos(struct comedi_device * dev)
+ {
+ 	UINT ui_StatusRegister = 0;
+-	comedi_subdevice *s = dev->subdevices + 0;
++	struct comedi_subdevice *s = dev->subdevices + 0;
+ 
+ 	//BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+ 	//comedi_async *async = s->async;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+index fbb658eff531..528673939f17 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+@@ -154,22 +154,22 @@ typedef struct {
+ 
+ //AI
+ 
+-INT i_APCI3200_ConfigAnalogInput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI3200_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+-INT i_APCI3200_ReadAnalogInput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI3200_ReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			       comedi_insn *insn, unsigned int *data);
+ INT i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device *dev,
+-					   comedi_subdevice *s,
++					   struct comedi_subdevice *s,
+ 					   comedi_insn *insn, unsigned int *data);
+ INT i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device *dev,
+-					 comedi_subdevice *s,
++					 struct comedi_subdevice *s,
+ 					 comedi_insn *insn, unsigned int *data);
+-INT i_APCI3200_StopCyclicAcquisition(struct comedi_device *dev, comedi_subdevice *s);
++INT i_APCI3200_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s);
+ INT i_APCI3200_InterruptHandleEos(struct comedi_device *dev);
+-INT i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				      comedi_cmd *cmd);
+-INT i_APCI3200_CommandAnalogInput(struct comedi_device *dev, comedi_subdevice *s);
+-INT i_APCI3200_ReadDigitalInput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI3200_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s);
++INT i_APCI3200_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				comedi_insn *insn, unsigned int *data);
+ //Interrupt
+ void v_APCI3200_Interrupt(int irq, void *d);
+@@ -182,6 +182,6 @@ int i_APCI3200_ReadCJCValue(struct comedi_device *dev, unsigned int *data);
+ int i_APCI3200_ReadCalibrationGainValue(struct comedi_device *dev, UINT *data);
+ int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device *dev, UINT *data);
+ int i_APCI3200_Read1AnalogInputChannel(struct comedi_device *dev,
+-				       comedi_subdevice *s, comedi_insn *insn,
++				       struct comedi_subdevice *s, comedi_insn *insn,
+ 				       unsigned int *data);
+ int i_APCI3200_ReadCJCCalGain(struct comedi_device *dev, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
+index 352e630a603a..2e4c8ad54db2 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
+@@ -56,7 +56,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_ReadDigitalInput                    |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+@@ -73,7 +73,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI3501_ReadDigitalInput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI3501_ReadDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+@@ -99,7 +99,7 @@ INT i_APCI3501_ReadDigitalInput(struct comedi_device * dev, comedi_subdevice * s
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_ConfigDigitalOutput                     |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Digital Output Subdevice.               |
+@@ -121,7 +121,7 @@ INT i_APCI3501_ReadDigitalInput(struct comedi_device * dev, comedi_subdevice * s
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI3501_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
++int i_APCI3501_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -142,13 +142,13 @@ int i_APCI3501_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_WriteDigitalOutput                      |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : writes To the digital Output Subdevice                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                     comedi_subdevice *s     : Subdevice Pointer            |
++|                     struct comedi_subdevice *s     : Subdevice Pointer            |
+ |                     comedi_insn *insn       : Insn Structure Pointer       |
+ |                     unsigned int *data          : Data Pointer contains        |
+ |                                          configuration parameters as below |
+@@ -161,7 +161,7 @@ int i_APCI3501_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3501_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI3501_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp, ui_Temp1;
+@@ -232,7 +232,7 @@ INT i_APCI3501_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_ReadDigitalOutput                       |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+@@ -248,7 +248,7 @@ INT i_APCI3501_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3501_ReadDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI3501_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+@@ -275,13 +275,13 @@ INT i_APCI3501_ReadDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_ConfigAnalogOutput                      |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Analog Output Subdevice                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                     comedi_subdevice *s     : Subdevice Pointer            |
++|                     struct comedi_subdevice *s     : Subdevice Pointer            |
+ |                     comedi_insn *insn       : Insn Structure Pointer       |
+ |                     unsigned int *data          : Data Pointer contains        |
+ |                                          configuration parameters as below |
+@@ -298,7 +298,7 @@ INT i_APCI3501_ReadDigitalOutput(struct comedi_device * dev, comedi_subdevice *
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3501_ConfigAnalogOutput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI3501_ConfigAnalogOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	outl(data[0],
+@@ -316,13 +316,13 @@ INT i_APCI3501_ConfigAnalogOutput(struct comedi_device * dev, comedi_subdevice *
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_WriteAnalogOutput                       |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes To the Selected Anlog Output Channel            |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+-|                     comedi_subdevice *s     : Subdevice Pointer            |
++|                     struct comedi_subdevice *s     : Subdevice Pointer            |
+ |                     comedi_insn *insn       : Insn Structure Pointer       |
+ |                     unsigned int *data          : Data Pointer contains        |
+ |                                          configuration parameters as below |
+@@ -336,7 +336,7 @@ INT i_APCI3501_ConfigAnalogOutput(struct comedi_device * dev, comedi_subdevice *
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3501_WriteAnalogOutput(struct comedi_device * dev, comedi_subdevice * s,
++INT i_APCI3501_WriteAnalogOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0, ul_Channel_no, ul_Polarity, ul_DAC_Ready = 0;;
+@@ -386,7 +386,7 @@ INT i_APCI3501_WriteAnalogOutput(struct comedi_device * dev, comedi_subdevice *
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_ConfigTimerCounterWatchdog              |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Timer , Counter or Watchdog             |
+@@ -411,7 +411,7 @@ INT i_APCI3501_WriteAnalogOutput(struct comedi_device * dev, comedi_subdevice *
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0;
+ 	devpriv->tsk_Current = current;
+@@ -489,7 +489,7 @@ INT i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_StartStopWriteTimerCounterWatchdog      |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Start / Stop The Selected Timer , Counter or Watchdog  |
+@@ -512,7 +512,7 @@ INT i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ */
+ 
+ int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0;
+ 	int i_Temp;
+@@ -592,7 +592,7 @@ int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_ReadTimerCounterWatchdog                |
+-|			  (struct comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Selected Timer , Counter or Watchdog          |
+@@ -614,7 +614,7 @@ int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ */
+ 
+ int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
+index a7dd01e5e57a..3b47634bfb91 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
+@@ -55,37 +55,37 @@ comedi_lrange range_apci3501_ao = { 2, {
+ // Hardware Layer  functions for Apci3501
+ 
+ //AO
+-INT i_APCI3501_ConfigAnalogOutput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI3501_ConfigAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				  comedi_insn *insn, unsigned int *data);
+-INT i_APCI3501_WriteAnalogOutput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI3501_WriteAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+ 
+ //DI
+ // for di read
+-//INT i_APCI3501_ReadDigitalInput(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data);
++//INT i_APCI3501_ReadDigitalInput(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data);
+ 
+-INT i_APCI3501_ReadDigitalInput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI3501_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				comedi_insn *insn, unsigned int *data);
+ 
+ //DO
+-int i_APCI3501_ConfigDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
++int i_APCI3501_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+-INT i_APCI3501_WriteDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI3501_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				  comedi_insn *insn, unsigned int *data);
+-INT i_APCI3501_ReadDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
++INT i_APCI3501_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+ // timer value is passed as u seconds
+ INT i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device *dev,
+-					  comedi_subdevice *s,
++					  struct comedi_subdevice *s,
+ 					  comedi_insn *insn, unsigned int *data);
+ int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
+-						  comedi_subdevice *s,
++						  struct comedi_subdevice *s,
+ 						  comedi_insn *insn,
+ 						  unsigned int *data);
+ int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device *dev,
+-					comedi_subdevice *s,
++					struct comedi_subdevice *s,
+ 					comedi_insn *insn, unsigned int *data);
+ //Interrupt
+ void v_APCI3501_Interrupt(int irq, void *d);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+index 44ca298f75ba..ae11fb7af323 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+@@ -81,7 +81,7 @@ int i_APCI3XXX_TestConversionStarted(struct comedi_device * dev)
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT   i_APCI3XXX_AnalogInputConfigOperatingMode        |
+ |                          (struct comedi_device    *dev,                           |
+-|                           comedi_subdevice *s,                             |
++|                           struct comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+@@ -106,7 +106,7 @@ int i_APCI3XXX_TestConversionStarted(struct comedi_device * dev)
+ */
+ 
+ int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_TimeBase = 0;
+@@ -275,7 +275,7 @@ int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT   i_APCI3XXX_InsnConfigAnalogInput                 |
+ |                          (struct comedi_device    *dev,                           |
+-|                           comedi_subdevice *s,                             |
++|                           struct comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+@@ -296,7 +296,7 @@ int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnConfigAnalogInput(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 
+@@ -333,7 +333,7 @@ int i_APCI3XXX_InsnConfigAnalogInput(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT   i_APCI3XXX_InsnReadAnalogInput                   |
+ |                          (struct comedi_device    *dev,                           |
+-|                           comedi_subdevice *s,                             |
++|                           struct comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+@@ -356,7 +356,7 @@ int i_APCI3XXX_InsnConfigAnalogInput(struct comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Configuration = (BYTE) CR_RANGE(insn->chanspec);
+@@ -664,7 +664,7 @@ void v_APCI3XXX_Interrupt(int irq, void *d)
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT   i_APCI3XXX_InsnWriteAnalogOutput                 |
+ |                          (struct comedi_device    *dev,                           |
+-|                           comedi_subdevice *s,                             |
++|                           struct comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+@@ -685,7 +685,7 @@ void v_APCI3XXX_Interrupt(int irq, void *d)
+ */
+ 
+ int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_Range = (BYTE) CR_RANGE(insn->chanspec);
+ 	BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
+@@ -770,7 +770,7 @@ int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT   i_APCI3XXX_InsnConfigInitTTLIO                   |
+ |                          (struct comedi_device    *dev,                           |
+-|                           comedi_subdevice *s,                             |
++|                           struct comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+@@ -792,7 +792,7 @@ int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Command = 0;
+@@ -901,7 +901,7 @@ int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT     i_APCI3XXX_InsnBitsTTLIO                       |
+ |                          (struct comedi_device    *dev,                           |
+-|                           comedi_subdevice *s,                             |
++|                           struct comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+@@ -920,7 +920,7 @@ int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_ChannelCpt = 0;
+@@ -1058,7 +1058,7 @@ int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT i_APCI3XXX_InsnReadTTLIO                           |
+ |                          (struct comedi_device    *dev,                           |
+-|                           comedi_subdevice *s,                             |
++|                           struct comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+@@ -1075,7 +1075,7 @@ int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnReadTTLIO(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
+ 	INT i_ReturnValue = insn->n;
+@@ -1170,7 +1170,7 @@ int i_APCI3XXX_InsnReadTTLIO(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT     i_APCI3XXX_InsnWriteTTLIO                      |
+ |                          (struct comedi_device    *dev,                           |
+-|                           comedi_subdevice *s,                             |
++|                           struct comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+@@ -1188,7 +1188,7 @@ int i_APCI3XXX_InsnReadTTLIO(struct comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
+@@ -1282,7 +1282,7 @@ int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3XXX_InsnReadDigitalInput                     |
+ |                                          (struct comedi_device *dev,              |
+-|                                           comedi_subdevice *s,             |
++|                                           struct comedi_subdevice *s,             |
+ |                                           comedi_insn *insn,               |
+ |                                           unsigned int *data)                  |
+ +----------------------------------------------------------------------------+
+@@ -1299,7 +1299,7 @@ int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
+@@ -1341,7 +1341,7 @@ int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3XXX_InsnBitsDigitalInput                     |
+ |                                          (struct comedi_device *dev,              |
+-|                                           comedi_subdevice *s,             |
++|                                           struct comedi_subdevice *s,             |
+ |                                           comedi_insn *insn,               |
+ |                                           unsigned int *data)                  |
+ +----------------------------------------------------------------------------+
+@@ -1357,7 +1357,7 @@ int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI3XXX_InsnBitsDigitalInput(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	DWORD dw_Temp = 0;
+@@ -1392,7 +1392,7 @@ int i_APCI3XXX_InsnBitsDigitalInput(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3XXX_InsnBitsDigitalOutput                    |
+ |                                          (struct comedi_device *dev,              |
+-|                                           comedi_subdevice *s,             |
++|                                           struct comedi_subdevice *s,             |
+ |                                           comedi_insn *insn,               |
+ |                                           unsigned int *data)                  |
+ +----------------------------------------------------------------------------+
+@@ -1410,7 +1410,7 @@ int i_APCI3XXX_InsnBitsDigitalInput(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI3XXX_InsnBitsDigitalOutput(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_ChannelCpt = 0;
+@@ -1488,7 +1488,7 @@ int i_APCI3XXX_InsnBitsDigitalOutput(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3XXX_InsnWriteDigitalOutput                   |
+ |                                          (struct comedi_device *dev,              |
+-|                                           comedi_subdevice *s,             |
++|                                           struct comedi_subdevice *s,             |
+ |                                           comedi_insn *insn,               |
+ |                                           unsigned int *data)                  |
+ +----------------------------------------------------------------------------+
+@@ -1506,7 +1506,7 @@ int i_APCI3XXX_InsnBitsDigitalOutput(struct comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Channel = CR_CHAN(insn->chanspec);
+@@ -1564,7 +1564,7 @@ int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3XXX_InsnReadDigitalOutput                    |
+ |                                          (struct comedi_device *dev,              |
+-|                                           comedi_subdevice *s,             |
++|                                           struct comedi_subdevice *s,             |
+ |                                           comedi_insn *insn,               |
+ |                                           unsigned int *data)                  |
+ +----------------------------------------------------------------------------+
+@@ -1581,7 +1581,7 @@ int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnReadDigitalOutput(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Channel = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c
+index 20aa52943fad..9e1597caf21d 100644
+--- a/drivers/staging/comedi/drivers/adl_pci6208.c
++++ b/drivers/staging/comedi/drivers/adl_pci6208.c
+@@ -127,13 +127,13 @@ pci6208_pci_setup(struct pci_dev *pci_dev, unsigned long *io_base_ptr,
+ 	int dev_minor);
+ 
+ /*read/write functions*/
+-static int pci6208_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int pci6208_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int pci6208_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int pci6208_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-//static int pci6208_dio_insn_bits(struct comedi_device *dev,comedi_subdevice *s,
++//static int pci6208_dio_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s,
+ //      comedi_insn *insn,unsigned int *data);
+-//static int pci6208_dio_insn_config(struct comedi_device *dev,comedi_subdevice *s,
++//static int pci6208_dio_insn_config(struct comedi_device *dev,struct comedi_subdevice *s,
+ //      comedi_insn *insn,unsigned int *data);
+ 
+ /*
+@@ -144,7 +144,7 @@ static int pci6208_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+  */
+ static int pci6208_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int retval;
+ 	unsigned long io_base;
+ 
+@@ -219,7 +219,7 @@ static int pci6208_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int pci6208_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int pci6208_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i = 0, Data_Read;
+@@ -244,7 +244,7 @@ static int pci6208_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+-static int pci6208_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int pci6208_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -261,7 +261,7 @@ static int pci6208_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+  * useful to applications if you implement the insn_bits interface.
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+-//static int pci6208_dio_insn_bits(struct comedi_device *dev,comedi_subdevice *s,
++//static int pci6208_dio_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s,
+ //      comedi_insn *insn,unsigned int *data)
+ //{
+ //      if(insn->n!=2)return -EINVAL;
+@@ -285,7 +285,7 @@ static int pci6208_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ //      return 2;
+ //}
+ 
+-//static int pci6208_dio_insn_config(struct comedi_device *dev,comedi_subdevice *s,
++//static int pci6208_dio_insn_config(struct comedi_device *dev,struct comedi_subdevice *s,
+ //      comedi_insn *insn,unsigned int *data)
+ //{
+ //      int chan=CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/adl_pci7296.c b/drivers/staging/comedi/drivers/adl_pci7296.c
+index 9c9d3f47f503..f38aa06d3c4e 100644
+--- a/drivers/staging/comedi/drivers/adl_pci7296.c
++++ b/drivers/staging/comedi/drivers/adl_pci7296.c
+@@ -75,7 +75,7 @@ static comedi_driver driver_adl_pci7296 = {
+ static int adl_pci7296_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	struct pci_dev *pcidev;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int bus, slot;
+ 	int ret;
+ 
+diff --git a/drivers/staging/comedi/drivers/adl_pci7432.c b/drivers/staging/comedi/drivers/adl_pci7432.c
+index 75208720b175..a36be5e14f63 100644
+--- a/drivers/staging/comedi/drivers/adl_pci7432.c
++++ b/drivers/staging/comedi/drivers/adl_pci7432.c
+@@ -69,10 +69,10 @@ static comedi_driver driver_adl_pci7432 = {
+ 
+ /* Digital IO */
+ 
+-static int adl_pci7432_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int adl_pci7432_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int adl_pci7432_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int adl_pci7432_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ /*            */
+@@ -80,7 +80,7 @@ static int adl_pci7432_do_insn_bits(struct comedi_device * dev, comedi_subdevice
+ static int adl_pci7432_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	struct pci_dev *pcidev;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int bus, slot;
+ 
+ 	printk("comedi: attempt to attach...\n");
+@@ -164,7 +164,7 @@ static int adl_pci7432_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int adl_pci7432_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int adl_pci7432_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	printk("comedi: pci7432_do_insn_bits called\n");
+@@ -184,7 +184,7 @@ static int adl_pci7432_do_insn_bits(struct comedi_device * dev, comedi_subdevice
+ 	return 2;
+ }
+ 
+-static int adl_pci7432_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int adl_pci7432_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	printk("comedi: pci7432_di_insn_bits called\n");
+diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c
+index 4cb3dc2e13bd..cc95acf762f8 100644
+--- a/drivers/staging/comedi/drivers/adl_pci8164.c
++++ b/drivers/staging/comedi/drivers/adl_pci8164.c
+@@ -79,34 +79,34 @@ static comedi_driver driver_adl_pci8164 = {
+       detach:adl_pci8164_detach,
+ };
+ 
+-static int adl_pci8164_insn_read_msts(struct comedi_device * dev, comedi_subdevice * s,
++static int adl_pci8164_insn_read_msts(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int adl_pci8164_insn_read_ssts(struct comedi_device * dev, comedi_subdevice * s,
++static int adl_pci8164_insn_read_ssts(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int adl_pci8164_insn_read_buf0(struct comedi_device * dev, comedi_subdevice * s,
++static int adl_pci8164_insn_read_buf0(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int adl_pci8164_insn_read_buf1(struct comedi_device * dev, comedi_subdevice * s,
++static int adl_pci8164_insn_read_buf1(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int adl_pci8164_insn_write_cmd(struct comedi_device * dev, comedi_subdevice * s,
++static int adl_pci8164_insn_write_cmd(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int adl_pci8164_insn_write_otp(struct comedi_device * dev, comedi_subdevice * s,
++static int adl_pci8164_insn_write_otp(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ static int adl_pci8164_insn_write_buf0(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+ static int adl_pci8164_insn_write_buf1(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+ static int adl_pci8164_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	struct pci_dev *pcidev;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int bus, slot;
+ 
+ 	printk("comedi: attempt to attach...\n");
+@@ -208,7 +208,7 @@ static int adl_pci8164_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int adl_pci8164_insn_read_msts(struct comedi_device * dev, comedi_subdevice * s,
++static int adl_pci8164_insn_read_msts(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+@@ -245,7 +245,7 @@ static int adl_pci8164_insn_read_msts(struct comedi_device * dev, comedi_subdevi
+ 	return 2;
+ }
+ 
+-static int adl_pci8164_insn_read_ssts(struct comedi_device * dev, comedi_subdevice * s,
++static int adl_pci8164_insn_read_ssts(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+@@ -282,7 +282,7 @@ static int adl_pci8164_insn_read_ssts(struct comedi_device * dev, comedi_subdevi
+ 	return 2;
+ }
+ 
+-static int adl_pci8164_insn_read_buf0(struct comedi_device * dev, comedi_subdevice * s,
++static int adl_pci8164_insn_read_buf0(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+@@ -319,7 +319,7 @@ static int adl_pci8164_insn_read_buf0(struct comedi_device * dev, comedi_subdevi
+ 	return 2;
+ }
+ 
+-static int adl_pci8164_insn_read_buf1(struct comedi_device * dev, comedi_subdevice * s,
++static int adl_pci8164_insn_read_buf1(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+@@ -357,7 +357,7 @@ static int adl_pci8164_insn_read_buf1(struct comedi_device * dev, comedi_subdevi
+ 	return 2;
+ }
+ 
+-static int adl_pci8164_insn_write_cmd(struct comedi_device * dev, comedi_subdevice * s,
++static int adl_pci8164_insn_write_cmd(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int axis, axis_reg;
+@@ -395,7 +395,7 @@ static int adl_pci8164_insn_write_cmd(struct comedi_device * dev, comedi_subdevi
+ 	return 2;
+ }
+ 
+-static int adl_pci8164_insn_write_otp(struct comedi_device * dev, comedi_subdevice * s,
++static int adl_pci8164_insn_write_otp(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+@@ -434,7 +434,7 @@ static int adl_pci8164_insn_write_otp(struct comedi_device * dev, comedi_subdevi
+ }
+ 
+ static int adl_pci8164_insn_write_buf0(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+ 
+@@ -472,7 +472,7 @@ static int adl_pci8164_insn_write_buf0(struct comedi_device * dev,
+ }
+ 
+ static int adl_pci8164_insn_write_buf1(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+ 
+diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
+index 53eb696c06ad..587a94bf2244 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9111.c
++++ b/drivers/staging/comedi/drivers/adl_pci9111.c
+@@ -267,7 +267,7 @@ Configuration options:
+ 
+ static int pci9111_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int pci9111_detach(struct comedi_device * dev);
+-static void pci9111_ai_munge(struct comedi_device * dev, comedi_subdevice * s,
++static void pci9111_ai_munge(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	void *data, unsigned int num_bytes, unsigned int start_chan_index);
+ 
+ static const comedi_lrange pci9111_hr_ai_range = {
+@@ -527,7 +527,7 @@ static void pci9111_interrupt_source_set(struct comedi_device * dev,
+ 
+ #undef AI_DO_CMD_DEBUG
+ 
+-static int pci9111_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int pci9111_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	// Disable interrupts
+ 
+@@ -558,7 +558,7 @@ static int pci9111_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ 
+ static int
+ pci9111_ai_do_cmd_test(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_cmd * cmd)
++	struct comedi_subdevice * s, comedi_cmd * cmd)
+ {
+ 	int tmp;
+ 	int error = 0;
+@@ -758,7 +758,7 @@ pci9111_ai_do_cmd_test(struct comedi_device * dev,
+ // Analog input command
+ //
+ 
+-static int pci9111_ai_do_cmd(struct comedi_device * dev, comedi_subdevice * subdevice)
++static int pci9111_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * subdevice)
+ {
+ 	comedi_cmd *async_cmd = &subdevice->async->cmd;
+ 
+@@ -881,7 +881,7 @@ static int pci9111_ai_do_cmd(struct comedi_device * dev, comedi_subdevice * subd
+ 	return 0;
+ }
+ 
+-static void pci9111_ai_munge(struct comedi_device * dev, comedi_subdevice * s,
++static void pci9111_ai_munge(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	void *data, unsigned int num_bytes, unsigned int start_chan_index)
+ {
+ 	unsigned int i, num_samples = num_bytes / sizeof(short);
+@@ -912,7 +912,7 @@ static void pci9111_ai_munge(struct comedi_device * dev, comedi_subdevice * s,
+ static irqreturn_t pci9111_interrupt(int irq, void *p_device PT_REGS_ARG)
+ {
+ 	struct comedi_device *dev = p_device;
+-	comedi_subdevice *subdevice = dev->read_subdev;
++	struct comedi_subdevice *subdevice = dev->read_subdev;
+ 	comedi_async *async;
+ 	unsigned long irq_flags;
+ 	unsigned char intcsr;
+@@ -1072,7 +1072,7 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device PT_REGS_ARG)
+ #undef AI_INSN_DEBUG
+ 
+ static int pci9111_ai_insn_read(struct comedi_device * dev,
+-	comedi_subdevice * subdevice, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * subdevice, comedi_insn * insn, unsigned int * data)
+ {
+ 	int resolution =
+ 		((pci9111_board_struct *) dev->board_ptr)->ai_resolution;
+@@ -1132,7 +1132,7 @@ static int pci9111_ai_insn_read(struct comedi_device * dev,
+ 
+ static int
+ pci9111_ao_insn_write(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 
+@@ -1149,7 +1149,7 @@ pci9111_ao_insn_write(struct comedi_device * dev,
+ //
+ 
+ static int pci9111_ao_insn_read(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 
+@@ -1171,7 +1171,7 @@ static int pci9111_ao_insn_read(struct comedi_device * dev,
+ //
+ 
+ static int pci9111_di_insn_bits(struct comedi_device * dev,
+-	comedi_subdevice * subdevice, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * subdevice, comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bits;
+ 
+@@ -1186,7 +1186,7 @@ static int pci9111_di_insn_bits(struct comedi_device * dev,
+ //
+ 
+ static int pci9111_do_insn_bits(struct comedi_device * dev,
+-	comedi_subdevice * subdevice, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * subdevice, comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bits;
+ 
+@@ -1248,7 +1248,7 @@ static int pci9111_reset(struct comedi_device * dev)
+ 
+ static int pci9111_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *subdevice;
++	struct comedi_subdevice *subdevice;
+ 	unsigned long io_base, io_range, lcr_io_base, lcr_io_range;
+ 	struct pci_dev *pci_device;
+ 	int error, i;
+diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
+index c352e37d97ae..67e26a3c847c 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9118.c
++++ b/drivers/staging/comedi/drivers/adl_pci9118.c
+@@ -288,7 +288,7 @@ typedef struct {
+ 	unsigned char cnt0_users;	// bit field of 8254 CNT0 users (0-unused, 1-AO, 2-DI, 3-DO)
+ 	unsigned char exttrg_users;	// bit field of external trigger users (0-AI, 1-AO, 2-DI, 3-DO)
+ 	unsigned int cnt0_divisor;	// actual CNT0 divisor
+-	void (*int_ai_func) (struct comedi_device *, comedi_subdevice *, unsigned short, unsigned int, unsigned short);	// ptr to actual interrupt AI function
++	void (*int_ai_func) (struct comedi_device *, struct comedi_subdevice *, unsigned short, unsigned int, unsigned short);	// ptr to actual interrupt AI function
+ 	unsigned char ai16bits;	// =1 16 bit card
+ 	unsigned char usedma;	// =1 use DMA transfer and not INT
+ 	unsigned char useeoshandle;	// =1 change WAKE_EOS DMA transfer to fit on every second
+@@ -308,9 +308,9 @@ typedef struct {
+ ==============================================================================
+ */
+ 
+-static int check_channel_list(struct comedi_device * dev, comedi_subdevice * s,
++static int check_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	int n_chan, unsigned int *chanlist, int frontadd, int backadd);
+-static int setup_channel_list(struct comedi_device * dev, comedi_subdevice * s,
++static int setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	int n_chan, unsigned int *chanlist, int rot, int frontadd, int backadd,
+ 	int usedma, char eoshandle);
+ static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
+@@ -318,16 +318,16 @@ static void start_pacer(struct comedi_device * dev, int mode, unsigned int divis
+ static int pci9118_reset(struct comedi_device * dev);
+ static int pci9118_exttrg_add(struct comedi_device * dev, unsigned char source);
+ static int pci9118_exttrg_del(struct comedi_device * dev, unsigned char source);
+-static int pci9118_ai_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static int pci9118_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static void pci9118_calc_divisors(char mode, struct comedi_device * dev,
+-	comedi_subdevice * s, unsigned int *tim1, unsigned int *tim2,
++	struct comedi_subdevice * s, unsigned int *tim1, unsigned int *tim2,
+ 	unsigned int flags, int chans, unsigned int *div1, unsigned int *div2,
+ 	char usessh, unsigned int chnsshfront);
+ 
+ /*
+ ==============================================================================
+ */
+-static int pci9118_insn_read_ai(struct comedi_device * dev, comedi_subdevice * s,
++static int pci9118_insn_read_ai(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -377,7 +377,7 @@ static int pci9118_insn_read_ai(struct comedi_device * dev, comedi_subdevice * s
+ /*
+ ==============================================================================
+ */
+-static int pci9118_insn_write_ao(struct comedi_device * dev, comedi_subdevice * s,
++static int pci9118_insn_write_ao(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, chanreg, ch;
+@@ -400,7 +400,7 @@ static int pci9118_insn_write_ao(struct comedi_device * dev, comedi_subdevice *
+ /*
+ ==============================================================================
+ */
+-static int pci9118_insn_read_ao(struct comedi_device * dev, comedi_subdevice * s,
++static int pci9118_insn_read_ao(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, chan;
+@@ -415,7 +415,7 @@ static int pci9118_insn_read_ao(struct comedi_device * dev, comedi_subdevice * s
+ /*
+ ==============================================================================
+ */
+-static int pci9118_insn_bits_di(struct comedi_device * dev, comedi_subdevice * s,
++static int pci9118_insn_bits_di(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[1] = inl(dev->iobase + PCI9118_DI) & 0xf;
+@@ -426,7 +426,7 @@ static int pci9118_insn_bits_di(struct comedi_device * dev, comedi_subdevice * s
+ /*
+ ==============================================================================
+ */
+-static int pci9118_insn_bits_do(struct comedi_device * dev, comedi_subdevice * s,
++static int pci9118_insn_bits_do(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+@@ -457,7 +457,7 @@ static void interrupt_pci9118_ai_mode4_switch(struct comedi_device * dev)
+ }
+ 
+ static unsigned int defragment_dma_buffer(struct comedi_device * dev,
+-	comedi_subdevice * s, short * dma_buffer, unsigned int num_samples)
++	struct comedi_subdevice * s, short * dma_buffer, unsigned int num_samples)
+ {
+ 	unsigned int i = 0, j = 0;
+ 	unsigned int start_pos = devpriv->ai_add_front,
+@@ -481,7 +481,7 @@ static unsigned int defragment_dma_buffer(struct comedi_device * dev,
+ ==============================================================================
+ */
+ static unsigned int move_block_from_dma(struct comedi_device * dev,
+-	comedi_subdevice * s, short * dma_buffer, unsigned int num_samples)
++	struct comedi_subdevice * s, short * dma_buffer, unsigned int num_samples)
+ {
+ 	unsigned int num_bytes;
+ 
+@@ -502,7 +502,7 @@ static unsigned int move_block_from_dma(struct comedi_device * dev,
+ ==============================================================================
+ */
+ static char pci9118_decode_error_status(struct comedi_device * dev,
+-	comedi_subdevice * s, unsigned char m)
++	struct comedi_subdevice * s, unsigned char m)
+ {
+ 	if (m & 0x100) {
+ 		comedi_error(dev, "A/D FIFO Full status (Fatal Error!)");
+@@ -531,7 +531,7 @@ static char pci9118_decode_error_status(struct comedi_device * dev,
+ 	return 0;
+ }
+ 
+-static void pci9118_ai_munge(struct comedi_device * dev, comedi_subdevice * s,
++static void pci9118_ai_munge(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	void *data, unsigned int num_bytes, unsigned int start_chan_index)
+ {
+ 	unsigned int i, num_samples = num_bytes / sizeof(short);
+@@ -552,7 +552,7 @@ static void pci9118_ai_munge(struct comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+ */
+ static void interrupt_pci9118_ai_onesample(struct comedi_device * dev,
+-	comedi_subdevice * s, unsigned short int_adstat, unsigned int int_amcc,
++	struct comedi_subdevice * s, unsigned short int_adstat, unsigned int int_amcc,
+ 	unsigned short int_daq)
+ {
+ 	register short sampl;
+@@ -598,7 +598,7 @@ static void interrupt_pci9118_ai_onesample(struct comedi_device * dev,
+ /*
+ ==============================================================================
+ */
+-static void interrupt_pci9118_ai_dma(struct comedi_device * dev, comedi_subdevice * s,
++static void interrupt_pci9118_ai_dma(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned short int_adstat, unsigned int int_amcc,
+ 	unsigned short int_daq)
+ {
+@@ -727,7 +727,7 @@ static irqreturn_t interrupt_pci9118(int irq, void *d PT_REGS_ARG)
+ /*
+ ==============================================================================
+ */
+-static int pci9118_ai_inttrig(struct comedi_device * dev, comedi_subdevice * s,
++static int pci9118_ai_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int trignum)
+ {
+ 	if (trignum != devpriv->ai_inttrig_start)
+@@ -751,7 +751,7 @@ static int pci9118_ai_inttrig(struct comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pci9118_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int pci9118_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -1163,7 +1163,7 @@ static int Compute_and_setup_dma(struct comedi_device * dev)
+ /*
+ ==============================================================================
+ */
+-static int pci9118_ai_docmd_sampl(struct comedi_device * dev, comedi_subdevice * s)
++static int pci9118_ai_docmd_sampl(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_sampl(%d,) [%d]\n",
+ 		dev->minor, devpriv->ai_do);
+@@ -1216,7 +1216,7 @@ static int pci9118_ai_docmd_sampl(struct comedi_device * dev, comedi_subdevice *
+ /*
+ ==============================================================================
+ */
+-static int pci9118_ai_docmd_dma(struct comedi_device * dev, comedi_subdevice * s)
++static int pci9118_ai_docmd_dma(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_dma(%d,) [%d,%d]\n",
+ 		dev->minor, devpriv->ai_do, devpriv->usedma);
+@@ -1287,7 +1287,7 @@ static int pci9118_ai_docmd_dma(struct comedi_device * dev, comedi_subdevice * s
+ /*
+ ==============================================================================
+ */
+-static int pci9118_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int pci9118_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned int addchans = 0;
+@@ -1486,7 +1486,7 @@ static int pci9118_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ /*
+ ==============================================================================
+ */
+-static int check_channel_list(struct comedi_device * dev, comedi_subdevice * s,
++static int check_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	int n_chan, unsigned int *chanlist, int frontadd, int backadd)
+ {
+ 	unsigned int i, differencial = 0, bipolar = 0;
+@@ -1537,7 +1537,7 @@ static int check_channel_list(struct comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int setup_channel_list(struct comedi_device * dev, comedi_subdevice * s,
++static int setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	int n_chan, unsigned int *chanlist, int rot, int frontadd, int backadd,
+ 	int usedma, char useeos)
+ {
+@@ -1652,7 +1652,7 @@ static int setup_channel_list(struct comedi_device * dev, comedi_subdevice * s,
+   calculate 8254 divisors if they are used for dual timing
+ */
+ static void pci9118_calc_divisors(char mode, struct comedi_device * dev,
+-	comedi_subdevice * s, unsigned int *tim1, unsigned int *tim2,
++	struct comedi_subdevice * s, unsigned int *tim1, unsigned int *tim2,
+ 	unsigned int flags, int chans, unsigned int *div1, unsigned int *div2,
+ 	char usessh, unsigned int chnsshfront)
+ {
+@@ -1760,7 +1760,7 @@ static int pci9118_exttrg_del(struct comedi_device * dev, unsigned char source)
+ /*
+ ==============================================================================
+ */
+-static int pci9118_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int pci9118_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	if (devpriv->usedma)
+ 		outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS), devpriv->iobase_a + AMCC_OP_REG_MCSR);	// stop DMA
+@@ -1837,7 +1837,7 @@ static int pci9118_reset(struct comedi_device * dev)
+ */
+ static int pci9118_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int ret, pages, i;
+ 	unsigned short master;
+ 	unsigned int irq;
+diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c
+index 295b667a381a..99a7a0562082 100644
+--- a/drivers/staging/comedi/drivers/adq12b.c
++++ b/drivers/staging/comedi/drivers/adq12b.c
+@@ -174,9 +174,9 @@ static comedi_driver driver_adq12b={
+         num_names:      sizeof(adq12b_boards) / sizeof(adq12b_board),
+ };
+ 
+-static int adq12b_ai_rinsn(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data);
+-static int adq12b_di_insn_bits(struct comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,unsigned int *data);
+-static int adq12b_do_insn_bits(struct comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,unsigned int *data);
++static int adq12b_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data);
++static int adq12b_di_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, comedi_insn *insn,unsigned int *data);
++static int adq12b_do_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, comedi_insn *insn,unsigned int *data);
+ 
+ /*
+  * Attach is called by the Comedi core to configure the driver
+@@ -186,7 +186,7 @@ static int adq12b_do_insn_bits(struct comedi_device *dev,comedi_subdevice *s, co
+  */
+ static int adq12b_attach(struct comedi_device *dev,comedi_devconfig *it)
+ {
+-        comedi_subdevice *s;
++        struct comedi_subdevice *s;
+         unsigned long iobase;
+         int unipolar, differential;
+ 
+@@ -314,7 +314,7 @@ static int adq12b_detach(struct comedi_device *dev)
+  * mode.
+  */
+ 
+-static int adq12b_ai_rinsn(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data)
++static int adq12b_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data)
+ {
+         int n, i;
+         int range, channel;
+@@ -357,7 +357,7 @@ static int adq12b_ai_rinsn(struct comedi_device *dev,comedi_subdevice *s,comedi_
+ }
+ 
+ 
+-static int adq12b_di_insn_bits(struct comedi_device *dev,comedi_subdevice *s, 	comedi_insn *insn,unsigned int *data)
++static int adq12b_di_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, 	comedi_insn *insn,unsigned int *data)
+ {
+ 
+         /* only bits 0-4 have information about digital inputs */
+@@ -367,7 +367,7 @@ static int adq12b_di_insn_bits(struct comedi_device *dev,comedi_subdevice *s, 	c
+ }
+ 
+ 
+-static int adq12b_do_insn_bits(struct comedi_device *dev,comedi_subdevice *s, 	comedi_insn *insn,unsigned int *data)
++static int adq12b_do_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, 	comedi_insn *insn,unsigned int *data)
+ {
+         int channel;
+ 
+diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
+index 75d915310e01..e66c2560b2cd 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1710.c
++++ b/drivers/staging/comedi/drivers/adv_pci1710.c
+@@ -304,14 +304,14 @@ typedef struct {
+ ==============================================================================
+ */
+ 
+-static int check_channel_list(struct comedi_device * dev, comedi_subdevice * s,
++static int check_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int *chanlist, unsigned int n_chan);
+-static void setup_channel_list(struct comedi_device * dev, comedi_subdevice * s,
++static void setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int *chanlist, unsigned int n_chan, unsigned int seglen);
+ static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
+ 	unsigned int divisor2);
+ static int pci1710_reset(struct comedi_device * dev);
+-static int pci171x_ai_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static int pci171x_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ 
+ static const unsigned int muxonechan[] = { 0x0000, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, 0x0707,	// used for gain list programming
+ 	0x0808, 0x0909, 0x0a0a, 0x0b0b, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f,
+@@ -322,7 +322,7 @@ static const unsigned int muxonechan[] = { 0x0000, 0x0101, 0x0202, 0x0303, 0x040
+ /*
+ ==============================================================================
+ */
+-static int pci171x_insn_read_ai(struct comedi_device * dev, comedi_subdevice * s,
++static int pci171x_insn_read_ai(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, timeout;
+@@ -390,7 +390,7 @@ static int pci171x_insn_read_ai(struct comedi_device * dev, comedi_subdevice * s
+ /*
+ ==============================================================================
+ */
+-static int pci171x_insn_write_ao(struct comedi_device * dev, comedi_subdevice * s,
++static int pci171x_insn_write_ao(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, chan, range, ofs;
+@@ -421,7 +421,7 @@ static int pci171x_insn_write_ao(struct comedi_device * dev, comedi_subdevice *
+ /*
+ ==============================================================================
+ */
+-static int pci171x_insn_read_ao(struct comedi_device * dev, comedi_subdevice * s,
++static int pci171x_insn_read_ao(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, chan;
+@@ -436,7 +436,7 @@ static int pci171x_insn_read_ao(struct comedi_device * dev, comedi_subdevice * s
+ /*
+ ==============================================================================
+ */
+-static int pci171x_insn_bits_di(struct comedi_device * dev, comedi_subdevice * s,
++static int pci171x_insn_bits_di(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[1] = inw(dev->iobase + PCI171x_DI);
+@@ -447,7 +447,7 @@ static int pci171x_insn_bits_di(struct comedi_device * dev, comedi_subdevice * s
+ /*
+ ==============================================================================
+ */
+-static int pci171x_insn_bits_do(struct comedi_device * dev, comedi_subdevice * s,
++static int pci171x_insn_bits_do(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+@@ -463,7 +463,7 @@ static int pci171x_insn_bits_do(struct comedi_device * dev, comedi_subdevice * s
+ /*
+ ==============================================================================
+ */
+-static int pci171x_insn_counter_read(struct comedi_device * dev, comedi_subdevice * s,
++static int pci171x_insn_counter_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int msb, lsb, ccntrl;
+@@ -485,7 +485,7 @@ static int pci171x_insn_counter_read(struct comedi_device * dev, comedi_subdevic
+ /*
+ ==============================================================================
+ */
+-static int pci171x_insn_counter_write(struct comedi_device * dev, comedi_subdevice * s,
++static int pci171x_insn_counter_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	uint msb, lsb, ccntrl, status;
+@@ -513,7 +513,7 @@ static int pci171x_insn_counter_write(struct comedi_device * dev, comedi_subdevi
+ ==============================================================================
+ */
+ static int pci171x_insn_counter_config(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ #ifdef unused
+ 	/* This doesn't work like a normal Comedi counter config */
+@@ -548,7 +548,7 @@ static int pci171x_insn_counter_config(struct comedi_device * dev,
+ /*
+ ==============================================================================
+ */
+-static int pci1720_insn_write_ao(struct comedi_device * dev, comedi_subdevice * s,
++static int pci1720_insn_write_ao(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, rangereg, chan;
+@@ -577,7 +577,7 @@ static int pci1720_insn_write_ao(struct comedi_device * dev, comedi_subdevice *
+ static void interrupt_pci1710_every_sample(void *d)
+ {
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s = dev->subdevices + 0;
++	struct comedi_subdevice *s = dev->subdevices + 0;
+ 	int m;
+ #ifdef PCI171x_PARANOIDCHECK
+ 	short sampl;
+@@ -659,7 +659,7 @@ static void interrupt_pci1710_every_sample(void *d)
+ /*
+ ==============================================================================
+ */
+-static int move_block_from_fifo(struct comedi_device * dev, comedi_subdevice * s,
++static int move_block_from_fifo(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	int n, int turn)
+ {
+ 	int i, j;
+@@ -708,7 +708,7 @@ static int move_block_from_fifo(struct comedi_device * dev, comedi_subdevice * s
+ static void interrupt_pci1710_half_fifo(void *d)
+ {
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s = dev->subdevices + 0;
++	struct comedi_subdevice *s = dev->subdevices + 0;
+ 	int m, samplesinbuf;
+ 
+ 	DPRINTK("adv_pci1710 EDBG: BGN: interrupt_pci1710_half_fifo(...)\n");
+@@ -802,7 +802,7 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d PT_REGS_ARG)
+ ==============================================================================
+ */
+ static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device * dev,
+-	comedi_subdevice * s)
++	struct comedi_subdevice * s)
+ {
+ 	unsigned int divisor1, divisor2;
+ 	unsigned int seglen;
+@@ -900,7 +900,7 @@ static void pci171x_cmdtest_out(int e, comedi_cmd * cmd)
+ /*
+ ==============================================================================
+ */
+-static int pci171x_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int pci171x_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -1065,7 +1065,7 @@ static int pci171x_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pci171x_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int pci171x_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 
+@@ -1104,7 +1104,7 @@ static int pci171x_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+  If it's ok, then program scan/gain logic.
+  This works for all cards.
+ */
+-static int check_channel_list(struct comedi_device * dev, comedi_subdevice * s,
++static int check_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int *chanlist, unsigned int n_chan)
+ {
+ 	unsigned int chansegment[32];
+@@ -1163,7 +1163,7 @@ static int check_channel_list(struct comedi_device * dev, comedi_subdevice * s,
+ 	return seglen;
+ }
+ 
+-static void setup_channel_list(struct comedi_device * dev, comedi_subdevice * s,
++static void setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int *chanlist, unsigned int n_chan, unsigned int seglen)
+ {
+ 	unsigned int i, range, chanprog;
+@@ -1220,7 +1220,7 @@ static void start_pacer(struct comedi_device * dev, int mode, unsigned int divis
+ /*
+ ==============================================================================
+ */
+-static int pci171x_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int pci171x_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cancel(...)\n");
+ 
+@@ -1318,7 +1318,7 @@ static int pci1710_reset(struct comedi_device * dev)
+ */
+ static int pci1710_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int ret, subdev, n_subdevices;
+ 	unsigned int irq;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
+index e69c2e358139..8209e60c783c 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1723.c
++++ b/drivers/staging/comedi/drivers/adv_pci1723.c
+@@ -202,7 +202,7 @@ static int pci1723_reset(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int pci1723_insn_read_ao(struct comedi_device * dev, comedi_subdevice * s,
++static int pci1723_insn_read_ao(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, chan;
+@@ -218,7 +218,7 @@ static int pci1723_insn_read_ao(struct comedi_device * dev, comedi_subdevice * s
+ /*
+   analog data output;
+ */
+-static int pci1723_ao_write_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int pci1723_ao_write_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, chan;
+@@ -238,7 +238,7 @@ static int pci1723_ao_write_winsn(struct comedi_device * dev, comedi_subdevice *
+ /*
+   digital i/o config/query
+ */
+-static int pci1723_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int pci1723_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int mask;
+@@ -278,7 +278,7 @@ static int pci1723_dio_insn_config(struct comedi_device * dev, comedi_subdevice
+ /*
+   digital i/o bits read/write
+ */
+-static int pci1723_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int pci1723_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+@@ -296,7 +296,7 @@ static int pci1723_dio_insn_bits(struct comedi_device * dev, comedi_subdevice *
+  */
+ static int pci1723_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int ret, subdev, n_subdevices;
+ 	struct pci_dev *pcidev;
+ 	unsigned int iobase;
+diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
+index 18e778e398bf..e0e62ea57f7e 100644
+--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
++++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
+@@ -357,7 +357,7 @@ static pci_dio_private *pci_priv = NULL;	/* list of allocated cards */
+ /*
+ ==============================================================================
+ */
+-static int pci_dio_insn_bits_di_b(struct comedi_device * dev, comedi_subdevice * s,
++static int pci_dio_insn_bits_di_b(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	const diosubd_data *d = (const diosubd_data *)s->private;
+@@ -374,7 +374,7 @@ static int pci_dio_insn_bits_di_b(struct comedi_device * dev, comedi_subdevice *
+ /*
+ ==============================================================================
+ */
+-static int pci_dio_insn_bits_di_w(struct comedi_device * dev, comedi_subdevice * s,
++static int pci_dio_insn_bits_di_w(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	const diosubd_data *d = (const diosubd_data *)s->private;
+@@ -390,7 +390,7 @@ static int pci_dio_insn_bits_di_w(struct comedi_device * dev, comedi_subdevice *
+ /*
+ ==============================================================================
+ */
+-static int pci_dio_insn_bits_do_b(struct comedi_device * dev, comedi_subdevice * s,
++static int pci_dio_insn_bits_do_b(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	const diosubd_data *d = (const diosubd_data *)s->private;
+@@ -411,7 +411,7 @@ static int pci_dio_insn_bits_do_b(struct comedi_device * dev, comedi_subdevice *
+ /*
+ ==============================================================================
+ */
+-static int pci_dio_insn_bits_do_w(struct comedi_device * dev, comedi_subdevice * s,
++static int pci_dio_insn_bits_do_w(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	const diosubd_data *d = (const diosubd_data *)s->private;
+@@ -490,7 +490,7 @@ static int pci1760_mbxrequest(struct comedi_device * dev,
+ /*
+ ==============================================================================
+ */
+-static int pci1760_insn_bits_di(struct comedi_device * dev, comedi_subdevice * s,
++static int pci1760_insn_bits_di(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[1] = inb(dev->iobase + IMB3);
+@@ -501,7 +501,7 @@ static int pci1760_insn_bits_di(struct comedi_device * dev, comedi_subdevice * s
+ /*
+ ==============================================================================
+ */
+-static int pci1760_insn_bits_do(struct comedi_device * dev, comedi_subdevice * s,
++static int pci1760_insn_bits_do(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int ret;
+@@ -528,7 +528,7 @@ static int pci1760_insn_bits_do(struct comedi_device * dev, comedi_subdevice * s
+ /*
+ ==============================================================================
+ */
+-static int pci1760_insn_cnt_read(struct comedi_device * dev, comedi_subdevice * s,
++static int pci1760_insn_cnt_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int ret, n;
+@@ -552,7 +552,7 @@ static int pci1760_insn_cnt_read(struct comedi_device * dev, comedi_subdevice *
+ /*
+ ==============================================================================
+ */
+-static int pci1760_insn_cnt_write(struct comedi_device * dev, comedi_subdevice * s,
++static int pci1760_insn_cnt_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int ret;
+@@ -752,7 +752,7 @@ static int pci_dio_reset(struct comedi_device * dev)
+ */
+ static int pci1760_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int subdev = 0;
+ 
+ 	s = dev->subdevices + subdev;
+@@ -802,7 +802,7 @@ static int pci1760_attach(struct comedi_device * dev, comedi_devconfig * it)
+ /*
+ ==============================================================================
+ */
+-static int pci_dio_add_di(struct comedi_device * dev, comedi_subdevice * s,
++static int pci_dio_add_di(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	const diosubd_data * d, int subdev)
+ {
+ 	s->type = COMEDI_SUBD_DI;
+@@ -829,7 +829,7 @@ static int pci_dio_add_di(struct comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pci_dio_add_do(struct comedi_device * dev, comedi_subdevice * s,
++static int pci_dio_add_do(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	const diosubd_data * d, int subdev)
+ {
+ 	s->type = COMEDI_SUBD_DO;
+@@ -885,7 +885,7 @@ static int CheckAndAllocCard(struct comedi_device * dev, comedi_devconfig * it,
+ */
+ static int pci_dio_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int ret, subdev, n_subdevices, i, j;
+ 	unsigned long iobase;
+ 	struct pci_dev *pcidev;
+@@ -1014,7 +1014,7 @@ static int pci_dio_attach(struct comedi_device * dev, comedi_devconfig * it)
+ static int pci_dio_detach(struct comedi_device * dev)
+ {
+ 	int i, j;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int subdev;
+ 
+ 	if (dev->private) {
+diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c
+index 37d13d68089e..5b62ec9608a8 100644
+--- a/drivers/staging/comedi/drivers/aio_aio12_8.c
++++ b/drivers/staging/comedi/drivers/aio_aio12_8.c
+@@ -88,7 +88,7 @@ typedef struct {
+ 
+ #define devpriv	((aio12_8_private *) dev->private)
+ 
+-static int aio_aio12_8_ai_read(struct comedi_device * dev, comedi_subdevice * s,
++static int aio_aio12_8_ai_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -122,7 +122,7 @@ static int aio_aio12_8_ai_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int aio_aio12_8_ao_read(struct comedi_device * dev, comedi_subdevice * s,
++static int aio_aio12_8_ao_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -133,7 +133,7 @@ static int aio_aio12_8_ao_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	return insn->n;
+ }
+ 
+-static int aio_aio12_8_ao_write(struct comedi_device * dev, comedi_subdevice * s,
++static int aio_aio12_8_ao_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -164,7 +164,7 @@ static const comedi_lrange range_aio_aio12_8 = {
+ static int aio_aio12_8_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int iobase;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	iobase = it->options[0];
+ 	if (!request_region(iobase, 24, "aio_aio12_8")) {
+diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c
+index 88f8e188e0c9..0e3f8d5aa06c 100644
+--- a/drivers/staging/comedi/drivers/aio_iiro_16.c
++++ b/drivers/staging/comedi/drivers/aio_iiro_16.c
+@@ -82,15 +82,15 @@ static comedi_driver driver_aio_iiro_16 = {
+ };
+ 
+ static int aio_iiro_16_dio_insn_bits_read(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+ static int aio_iiro_16_dio_insn_bits_write(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+ static int aio_iiro_16_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int iobase;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	printk("comedi%d: aio_iiro_16: ", dev->minor);
+ 
+@@ -143,7 +143,7 @@ static int aio_iiro_16_detach(struct comedi_device * dev)
+ }
+ 
+ static int aio_iiro_16_dio_insn_bits_write(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -162,7 +162,7 @@ static int aio_iiro_16_dio_insn_bits_write(struct comedi_device * dev,
+ }
+ 
+ static int aio_iiro_16_dio_insn_bits_read(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
+index 642071a92971..f34e45028256 100644
+--- a/drivers/staging/comedi/drivers/amplc_dio200.c
++++ b/drivers/staging/comedi/drivers/amplc_dio200.c
+@@ -572,7 +572,7 @@ dio200_request_region(unsigned minor, unsigned long from, unsigned long extent)
+  * 'insn_bits' function for an 'INTERRUPT' subdevice.
+  */
+ static int
+-dio200_subdev_intr_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++dio200_subdev_intr_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	dio200_subdev_intr *subpriv = s->private;
+@@ -591,7 +591,7 @@ dio200_subdev_intr_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ /*
+  * Called to stop acquisition for an 'INTERRUPT' subdevice.
+  */
+-static void dio200_stop_intr(struct comedi_device * dev, comedi_subdevice * s)
++static void dio200_stop_intr(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	dio200_subdev_intr *subpriv = s->private;
+ 
+@@ -605,7 +605,7 @@ static void dio200_stop_intr(struct comedi_device * dev, comedi_subdevice * s)
+ /*
+  * Called to start acquisition for an 'INTERRUPT' subdevice.
+  */
+-static int dio200_start_intr(struct comedi_device * dev, comedi_subdevice * s)
++static int dio200_start_intr(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned int n;
+ 	unsigned isn_bits;
+@@ -641,7 +641,7 @@ static int dio200_start_intr(struct comedi_device * dev, comedi_subdevice * s)
+  * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
+  */
+ static int
+-dio200_inttrig_start_intr(struct comedi_device * dev, comedi_subdevice * s,
++dio200_inttrig_start_intr(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int trignum)
+ {
+ 	dio200_subdev_intr *subpriv;
+@@ -671,7 +671,7 @@ dio200_inttrig_start_intr(struct comedi_device * dev, comedi_subdevice * s,
+  * This is called from the interrupt service routine to handle a read
+  * scan on an 'INTERRUPT' subdevice.
+  */
+-static int dio200_handle_read_intr(struct comedi_device * dev, comedi_subdevice * s)
++static int dio200_handle_read_intr(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	dio200_subdev_intr *subpriv = s->private;
+ 	unsigned triggered;
+@@ -783,7 +783,7 @@ static int dio200_handle_read_intr(struct comedi_device * dev, comedi_subdevice
+ /*
+  * 'cancel' function for an 'INTERRUPT' subdevice.
+  */
+-static int dio200_subdev_intr_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int dio200_subdev_intr_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	dio200_subdev_intr *subpriv = s->private;
+ 	unsigned long flags;
+@@ -801,7 +801,7 @@ static int dio200_subdev_intr_cancel(struct comedi_device * dev, comedi_subdevic
+  * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
+  */
+ static int
+-dio200_subdev_intr_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++dio200_subdev_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -907,7 +907,7 @@ dio200_subdev_intr_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ /*
+  * 'do_cmd' function for an 'INTERRUPT' subdevice.
+  */
+-static int dio200_subdev_intr_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int dio200_subdev_intr_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	dio200_subdev_intr *subpriv = s->private;
+@@ -953,7 +953,7 @@ static int dio200_subdev_intr_cmd(struct comedi_device * dev, comedi_subdevice *
+  * This function initializes an 'INTERRUPT' subdevice.
+  */
+ static int
+-dio200_subdev_intr_init(struct comedi_device * dev, comedi_subdevice * s,
++dio200_subdev_intr_init(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned long iobase, unsigned valid_isns, int has_int_sce)
+ {
+ 	dio200_subdev_intr *subpriv;
+@@ -998,7 +998,7 @@ dio200_subdev_intr_init(struct comedi_device * dev, comedi_subdevice * s,
+  * This function cleans up an 'INTERRUPT' subdevice.
+  */
+ static void
+-dio200_subdev_intr_cleanup(struct comedi_device * dev, comedi_subdevice * s)
++dio200_subdev_intr_cleanup(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	dio200_subdev_intr *subpriv = s->private;
+ 
+@@ -1033,7 +1033,7 @@ static irqreturn_t dio200_interrupt(int irq, void *d PT_REGS_ARG)
+  * Handle 'insn_read' for an '8254' counter subdevice.
+  */
+ static int
+-dio200_subdev_8254_read(struct comedi_device * dev, comedi_subdevice * s,
++dio200_subdev_8254_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	dio200_subdev_8254 *subpriv = s->private;
+@@ -1048,7 +1048,7 @@ dio200_subdev_8254_read(struct comedi_device * dev, comedi_subdevice * s,
+  * Handle 'insn_write' for an '8254' counter subdevice.
+  */
+ static int
+-dio200_subdev_8254_write(struct comedi_device * dev, comedi_subdevice * s,
++dio200_subdev_8254_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	dio200_subdev_8254 *subpriv = s->private;
+@@ -1142,7 +1142,7 @@ dio200_get_clock_src(dio200_subdev_8254 * subpriv, unsigned int counter_number,
+  * Handle 'insn_config' for an '8254' counter subdevice.
+  */
+ static int
+-dio200_subdev_8254_config(struct comedi_device * dev, comedi_subdevice * s,
++dio200_subdev_8254_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	dio200_subdev_8254 *subpriv = s->private;
+@@ -1194,7 +1194,7 @@ dio200_subdev_8254_config(struct comedi_device * dev, comedi_subdevice * s,
+  * offset is the offset to the 8254 chip.
+  */
+ static int
+-dio200_subdev_8254_init(struct comedi_device * dev, comedi_subdevice * s,
++dio200_subdev_8254_init(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned long iobase, unsigned offset, int has_clk_gat_sce)
+ {
+ 	dio200_subdev_8254 *subpriv;
+@@ -1247,7 +1247,7 @@ dio200_subdev_8254_init(struct comedi_device * dev, comedi_subdevice * s,
+  * This function cleans up an '8254' counter subdevice.
+  */
+ static void
+-dio200_subdev_8254_cleanup(struct comedi_device * dev, comedi_subdevice * s)
++dio200_subdev_8254_cleanup(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	dio200_subdev_intr *subpriv = s->private;
+ 
+@@ -1264,7 +1264,7 @@ dio200_subdev_8254_cleanup(struct comedi_device * dev, comedi_subdevice * s)
+  */
+ static int dio200_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned long iobase = 0;
+ 	unsigned int irq = 0;
+ #ifdef CONFIG_COMEDI_PCI
+@@ -1443,7 +1443,7 @@ static int dio200_detach(struct comedi_device * dev)
+ 	if (dev->subdevices) {
+ 		layout = thislayout;
+ 		for (n = 0; n < dev->n_subdevices; n++) {
+-			comedi_subdevice *s = &dev->subdevices[n];
++			struct comedi_subdevice *s = &dev->subdevices[n];
+ 			switch (layout->sdtype[n]) {
+ 			case sd_8254:
+ 				dio200_subdev_8254_cleanup(dev, s);
+diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
+index adbd79421d4d..ba91debae962 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc236.c
++++ b/drivers/staging/comedi/drivers/amplc_pc236.c
+@@ -188,12 +188,12 @@ static int pc236_request_region(unsigned minor, unsigned long from,
+ static void pc236_intr_disable(struct comedi_device * dev);
+ static void pc236_intr_enable(struct comedi_device * dev);
+ static int pc236_intr_check(struct comedi_device * dev);
+-static int pc236_intr_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int pc236_intr_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int pc236_intr_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int pc236_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int pc236_intr_cmd(struct comedi_device * dev, comedi_subdevice * s);
+-static int pc236_intr_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static int pc236_intr_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
++static int pc236_intr_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static irqreturn_t pc236_interrupt(int irq, void *d PT_REGS_ARG);
+ 
+ /*
+@@ -266,7 +266,7 @@ pc236_find_pci(struct comedi_device * dev, int bus, int slot,
+  */
+ static int pc236_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned long iobase = 0;
+ 	unsigned int irq = 0;
+ #ifdef CONFIG_COMEDI_PCI
+@@ -528,7 +528,7 @@ static int pc236_intr_check(struct comedi_device * dev)
+  * Input from subdevice 1.
+  * Copied from the comedi_parport driver.
+  */
+-static int pc236_intr_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int pc236_intr_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[1] = 0;
+@@ -539,7 +539,7 @@ static int pc236_intr_insn(struct comedi_device * dev, comedi_subdevice * s,
+  * Subdevice 1 command test.
+  * Copied from the comedi_parport driver.
+  */
+-static int pc236_intr_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int pc236_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -617,7 +617,7 @@ static int pc236_intr_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ /*
+  * Subdevice 1 command.
+  */
+-static int pc236_intr_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int pc236_intr_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	pc236_intr_enable(dev);
+ 
+@@ -627,7 +627,7 @@ static int pc236_intr_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ /*
+  * Subdevice 1 cancel command.
+  */
+-static int pc236_intr_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int pc236_intr_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	pc236_intr_disable(dev);
+ 
+@@ -641,7 +641,7 @@ static int pc236_intr_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ static irqreturn_t pc236_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s = dev->subdevices + 1;
++	struct comedi_subdevice *s = dev->subdevices + 1;
+ 	int handled;
+ 
+ 	handled = pc236_intr_check(dev);
+diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
+index 5f4c7e28102b..43bd5324be4a 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc263.c
++++ b/drivers/staging/comedi/drivers/amplc_pc263.c
+@@ -146,9 +146,9 @@ static comedi_driver driver_amplc_pc263 = {
+ 
+ static int pc263_request_region(unsigned minor, unsigned long from,
+ 	unsigned long extent);
+-static int pc263_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int pc263_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int pc263_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int pc263_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ /*
+@@ -221,7 +221,7 @@ pc263_find_pci(struct comedi_device * dev, int bus, int slot,
+  */
+ static int pc263_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned long iobase = 0;
+ #ifdef CONFIG_COMEDI_PCI
+ 	struct pci_dev *pci_dev = NULL;
+@@ -387,7 +387,7 @@ static int pc263_request_region(unsigned minor, unsigned long from,
+  * useful to applications if you implement the insn_bits interface.
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+-static int pc263_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int pc263_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -412,7 +412,7 @@ static int pc263_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int pc263_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int pc263_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 1)
+diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
+index afb110a868e2..247b1eaaa17f 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci224.c
++++ b/drivers/staging/comedi/drivers/amplc_pci224.c
+@@ -477,7 +477,7 @@ pci224_ao_set_data(struct comedi_device * dev, int chan, int range, unsigned int
+  * 'insn_write' function for AO subdevice.
+  */
+ static int
+-pci224_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
++pci224_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -504,7 +504,7 @@ pci224_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+  * command.
+  */
+ static int
+-pci224_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++pci224_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -532,7 +532,7 @@ pci224_cascade_ns_to_timer(int osc_base, unsigned int *d1, unsigned int *d2,
+ /*
+  * Kills a command running on the AO subdevice.
+  */
+-static void pci224_ao_stop(struct comedi_device * dev, comedi_subdevice * s)
++static void pci224_ao_stop(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+ 
+@@ -572,7 +572,7 @@ static void pci224_ao_stop(struct comedi_device * dev, comedi_subdevice * s)
+ /*
+  * Handles start of acquisition for the AO subdevice.
+  */
+-static void pci224_ao_start(struct comedi_device * dev, comedi_subdevice * s)
++static void pci224_ao_start(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned long flags;
+@@ -599,7 +599,7 @@ static void pci224_ao_start(struct comedi_device * dev, comedi_subdevice * s)
+ /*
+  * Handles interrupts from the DAC FIFO.
+  */
+-static void pci224_ao_handle_fifo(struct comedi_device * dev, comedi_subdevice * s)
++static void pci224_ao_handle_fifo(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned int num_scans;
+@@ -728,7 +728,7 @@ static void pci224_ao_handle_fifo(struct comedi_device * dev, comedi_subdevice *
+  * Internal trigger function to start acquisition on AO subdevice.
+  */
+ static int
+-pci224_ao_inttrig_start(struct comedi_device * dev, comedi_subdevice * s,
++pci224_ao_inttrig_start(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int trignum)
+ {
+ 	if (trignum != 0)
+@@ -748,7 +748,7 @@ pci224_ao_inttrig_start(struct comedi_device * dev, comedi_subdevice * s,
+  * 'do_cmdtest' function for AO subdevice.
+  */
+ static int
+-pci224_ao_cmdtest(struct comedi_device * dev, comedi_subdevice * s, comedi_cmd * cmd)
++pci224_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	unsigned int tmp;
+@@ -1015,7 +1015,7 @@ pci224_ao_cmdtest(struct comedi_device * dev, comedi_subdevice * s, comedi_cmd *
+ /*
+  * 'do_cmd' function for AO subdevice.
+  */
+-static int pci224_ao_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int pci224_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	int range;
+@@ -1172,7 +1172,7 @@ static int pci224_ao_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ /*
+  * 'cancel' function for AO subdevice.
+  */
+-static int pci224_ao_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int pci224_ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	pci224_ao_stop(dev, s);
+ 	return 0;
+@@ -1182,7 +1182,7 @@ static int pci224_ao_cancel(struct comedi_device * dev, comedi_subdevice * s)
+  * 'munge' data for AO command.
+  */
+ static void
+-pci224_ao_munge(struct comedi_device * dev, comedi_subdevice * s, void *data,
++pci224_ao_munge(struct comedi_device * dev, struct comedi_subdevice * s, void *data,
+ 	unsigned int num_bytes, unsigned int chan_index)
+ {
+ 	comedi_async *async = s->async;
+@@ -1215,7 +1215,7 @@ pci224_ao_munge(struct comedi_device * dev, comedi_subdevice * s, void *data,
+ static irqreturn_t pci224_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s = &dev->subdevices[0];
++	struct comedi_subdevice *s = &dev->subdevices[0];
+ 	comedi_cmd *cmd;
+ 	unsigned char intstat, valid_intstat;
+ 	unsigned char curenab;
+@@ -1325,7 +1325,7 @@ pci224_find_pci(struct comedi_device * dev, int bus, int slot,
+  */
+ static int pci224_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	struct pci_dev *pci_dev;
+ 	unsigned int irq;
+ 	int bus = 0, slot = 0;
+@@ -1511,7 +1511,7 @@ static int pci224_detach(struct comedi_device * dev)
+ 		comedi_free_irq(dev->irq, dev);
+ 	}
+ 	if (dev->subdevices) {
+-		comedi_subdevice *s;
++		struct comedi_subdevice *s;
+ 
+ 		s = dev->subdevices + 0;
+ 		/* AO subdevice */
+diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
+index c66a840085f7..ee5f20320256 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci230.c
++++ b/drivers/staging/comedi/drivers/amplc_pci230.c
+@@ -615,30 +615,30 @@ static comedi_driver driver_amplc_pci230 = {
+ 
+ COMEDI_PCI_INITCLEANUP(driver_amplc_pci230, pci230_pci_table);
+ 
+-static int pci230_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int pci230_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int pci230_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int pci230_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int pci230_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int pci230_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ static void pci230_ct_setup_ns_mode(struct comedi_device * dev, unsigned int ct,
+ 	unsigned int mode, uint64_t ns, unsigned int round);
+ static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round);
+ static void pci230_cancel_ct(struct comedi_device * dev, unsigned int ct);
+ static irqreturn_t pci230_interrupt(int irq, void *d PT_REGS_ARG);
+-static int pci230_ao_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int pci230_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int pci230_ao_cmd(struct comedi_device * dev, comedi_subdevice * s);
+-static int pci230_ao_cancel(struct comedi_device * dev, comedi_subdevice * s);
+-static void pci230_ao_stop(struct comedi_device * dev, comedi_subdevice * s);
+-static void pci230_handle_ao_nofifo(struct comedi_device * dev, comedi_subdevice * s);
+-static int pci230_handle_ao_fifo(struct comedi_device * dev, comedi_subdevice * s);
+-static int pci230_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int pci230_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
++static int pci230_ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
++static void pci230_ao_stop(struct comedi_device * dev, struct comedi_subdevice * s);
++static void pci230_handle_ao_nofifo(struct comedi_device * dev, struct comedi_subdevice * s);
++static int pci230_handle_ao_fifo(struct comedi_device * dev, struct comedi_subdevice * s);
++static int pci230_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int pci230_ai_cmd(struct comedi_device * dev, comedi_subdevice * s);
+-static int pci230_ai_cancel(struct comedi_device * dev, comedi_subdevice * s);
+-static void pci230_ai_stop(struct comedi_device * dev, comedi_subdevice * s);
+-static void pci230_handle_ai(struct comedi_device * dev, comedi_subdevice * s);
++static int pci230_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
++static int pci230_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
++static void pci230_ai_stop(struct comedi_device * dev, struct comedi_subdevice * s);
++static void pci230_handle_ai(struct comedi_device * dev, struct comedi_subdevice * s);
+ 
+ static short pci230_ai_read(struct comedi_device * dev)
+ {
+@@ -704,7 +704,7 @@ static inline void pci230_ao_write_fifo(struct comedi_device * dev, short datum,
+  */
+ static int pci230_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned long iobase1, iobase2;
+ 	/* PCI230's I/O spaces 1 and 2 respectively. */
+ 	struct pci_dev *pci_dev;
+@@ -1058,7 +1058,7 @@ static inline void put_all_resources(struct comedi_device * dev, unsigned char o
+ /*
+  *  COMEDI_SUBD_AI instruction;
+  */
+-static int pci230_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int pci230_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int n, i;
+@@ -1163,7 +1163,7 @@ static int pci230_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ /*
+  *  COMEDI_SUBD_AO instructions;
+  */
+-static int pci230_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int pci230_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -1191,7 +1191,7 @@ static int pci230_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+-static int pci230_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int pci230_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -1203,7 +1203,7 @@ static int pci230_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int pci230_ao_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int pci230_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -1417,7 +1417,7 @@ static int pci230_ao_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int pci230_ao_inttrig_scan_begin(struct comedi_device * dev,
+-	comedi_subdevice * s, unsigned int trig_num)
++	struct comedi_subdevice * s, unsigned int trig_num)
+ {
+ 	unsigned long irqflags;
+ 
+@@ -1448,7 +1448,7 @@ static int pci230_ao_inttrig_scan_begin(struct comedi_device * dev,
+ 	return 1;
+ }
+ 
+-static void pci230_ao_start(struct comedi_device * dev, comedi_subdevice * s)
++static void pci230_ao_start(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+@@ -1536,7 +1536,7 @@ static void pci230_ao_start(struct comedi_device * dev, comedi_subdevice * s)
+ 	}
+ }
+ 
+-static int pci230_ao_inttrig_start(struct comedi_device * dev, comedi_subdevice * s,
++static int pci230_ao_inttrig_start(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int trig_num)
+ {
+ 	if (trig_num != 0)
+@@ -1548,7 +1548,7 @@ static int pci230_ao_inttrig_start(struct comedi_device * dev, comedi_subdevice
+ 	return 1;
+ }
+ 
+-static int pci230_ao_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int pci230_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned short daccon;
+ 	unsigned int range;
+@@ -1648,7 +1648,7 @@ static int pci230_ai_check_scan_period(comedi_cmd * cmd)
+ 	return !err;
+ }
+ 
+-static int pci230_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int pci230_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -2035,7 +2035,7 @@ static int pci230_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static void pci230_ai_update_fifo_trigger_level(struct comedi_device * dev,
+-	comedi_subdevice * s)
++	struct comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned int scanlen = cmd->scan_end_arg;
+@@ -2078,7 +2078,7 @@ static void pci230_ai_update_fifo_trigger_level(struct comedi_device * dev,
+ 	}
+ }
+ 
+-static int pci230_ai_inttrig_convert(struct comedi_device * dev, comedi_subdevice * s,
++static int pci230_ai_inttrig_convert(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int trig_num)
+ {
+ 	unsigned long irqflags;
+@@ -2122,7 +2122,7 @@ static int pci230_ai_inttrig_convert(struct comedi_device * dev, comedi_subdevic
+ }
+ 
+ static int pci230_ai_inttrig_scan_begin(struct comedi_device * dev,
+-	comedi_subdevice * s, unsigned int trig_num)
++	struct comedi_subdevice * s, unsigned int trig_num)
+ {
+ 	unsigned long irqflags;
+ 	unsigned char zgat;
+@@ -2143,7 +2143,7 @@ static int pci230_ai_inttrig_scan_begin(struct comedi_device * dev,
+ 	return 1;
+ }
+ 
+-static void pci230_ai_start(struct comedi_device * dev, comedi_subdevice * s)
++static void pci230_ai_start(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned long irqflags;
+ 	unsigned short conv;
+@@ -2280,7 +2280,7 @@ static void pci230_ai_start(struct comedi_device * dev, comedi_subdevice * s)
+ 	}
+ }
+ 
+-static int pci230_ai_inttrig_start(struct comedi_device * dev, comedi_subdevice * s,
++static int pci230_ai_inttrig_start(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int trig_num)
+ {
+ 	if (trig_num != 0)
+@@ -2292,7 +2292,7 @@ static int pci230_ai_inttrig_start(struct comedi_device * dev, comedi_subdevice
+ 	return 1;
+ }
+ 
+-static int pci230_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int pci230_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned int i, chan, range, diff;
+ 	unsigned int res_mask;
+@@ -2563,7 +2563,7 @@ static irqreturn_t pci230_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	unsigned char status_int, valid_status_int;
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned long irqflags;
+ 
+ 	/* Read interrupt status/enable register. */
+@@ -2622,7 +2622,7 @@ static irqreturn_t pci230_interrupt(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static void pci230_handle_ao_nofifo(struct comedi_device * dev, comedi_subdevice * s)
++static void pci230_handle_ao_nofifo(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	short data;
+ 	int i, ret;
+@@ -2659,7 +2659,7 @@ static void pci230_handle_ao_nofifo(struct comedi_device * dev, comedi_subdevice
+ 
+ /* Loads DAC FIFO (if using it) from buffer. */
+ /* Returns 0 if AO finished due to completion or error, 1 if still going. */
+-static int pci230_handle_ao_fifo(struct comedi_device * dev, comedi_subdevice * s)
++static int pci230_handle_ao_fifo(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+@@ -2762,7 +2762,7 @@ static int pci230_handle_ao_fifo(struct comedi_device * dev, comedi_subdevice *
+ 	return running;
+ }
+ 
+-static void pci230_handle_ai(struct comedi_device * dev, comedi_subdevice * s)
++static void pci230_handle_ai(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned int events = 0;
+ 	unsigned int status_fifo;
+@@ -2861,7 +2861,7 @@ static void pci230_handle_ai(struct comedi_device * dev, comedi_subdevice * s)
+ 	}
+ }
+ 
+-static void pci230_ao_stop(struct comedi_device * dev, comedi_subdevice * s)
++static void pci230_ao_stop(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned long irqflags;
+ 	unsigned char intsrc;
+@@ -2916,13 +2916,13 @@ static void pci230_ao_stop(struct comedi_device * dev, comedi_subdevice * s)
+ 	put_all_resources(dev, OWNER_AOCMD);
+ }
+ 
+-static int pci230_ao_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int pci230_ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	pci230_ao_stop(dev, s);
+ 	return 0;
+ }
+ 
+-static void pci230_ai_stop(struct comedi_device * dev, comedi_subdevice * s)
++static void pci230_ai_stop(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned long irqflags;
+ 	comedi_cmd *cmd;
+@@ -2970,7 +2970,7 @@ static void pci230_ai_stop(struct comedi_device * dev, comedi_subdevice * s)
+ 	put_all_resources(dev, OWNER_AICMD);
+ }
+ 
+-static int pci230_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int pci230_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	pci230_ai_stop(dev, s);
+ 	return 0;
+diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c
+index bf8562b3023f..afe3550fe8f1 100644
+--- a/drivers/staging/comedi/drivers/c6xdigio.c
++++ b/drivers/staging/comedi/drivers/c6xdigio.c
+@@ -339,14 +339,14 @@ static void C6X_encResetAll(unsigned long baseAddr)
+ }
+ 
+ static int c6xdigio_pwmo_insn_read(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	printk("c6xdigio_pwmo_insn_read %x\n", insn->n);
+ 	return insn->n;
+ }
+ 
+ static int c6xdigio_pwmo_insn_write(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -360,7 +360,7 @@ static int c6xdigio_pwmo_insn_write(struct comedi_device * dev,
+ }
+ 
+ //static int c6xdigio_ei_init_insn_read(struct comedi_device *dev,
+-//                                 comedi_subdevice *s,
++//                                 struct comedi_subdevice *s,
+ //                                 comedi_insn *insn,
+ //                                 unsigned int *data)
+ //{
+@@ -369,7 +369,7 @@ static int c6xdigio_pwmo_insn_write(struct comedi_device * dev,
+ //}
+ 
+ //static int c6xdigio_ei_init_insn_write(struct comedi_device *dev,
+-//                                 comedi_subdevice *s,
++//                                 struct comedi_subdevice *s,
+ //                                 comedi_insn *insn,
+ //                                 unsigned int *data)
+ //{
+@@ -382,7 +382,7 @@ static int c6xdigio_pwmo_insn_write(struct comedi_device * dev,
+ //}
+ 
+ static int c6xdigio_ei_insn_read(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	//  printk("c6xdigio_ei__insn_read %x\n", insn->n);
+ 	int n;
+@@ -433,7 +433,7 @@ static int c6xdigio_attach(struct comedi_device * dev, comedi_devconfig * it)
+ 	int result = 0;
+ 	unsigned long iobase;
+ 	unsigned int irq;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	iobase = it->options[0];
+ 	printk("comedi%d: c6xdigio: 0x%04lx\n", dev->minor, iobase);
+diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
+index b45a1771bd0d..ad01884479c0 100644
+--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
++++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
+@@ -109,22 +109,22 @@ static const comedi_lrange das16cs_ai_range = { 4, {
+ };
+ 
+ static irqreturn_t das16cs_interrupt(int irq, void *d PT_REGS_ARG);
+-static int das16cs_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int das16cs_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das16cs_ai_cmd(struct comedi_device * dev, comedi_subdevice * s);
+-static int das16cs_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int das16cs_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
++static int das16cs_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int das16cs_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int das16cs_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das16cs_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int das16cs_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das16cs_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int das16cs_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das16cs_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int das16cs_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das16cs_timer_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int das16cs_timer_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das16cs_timer_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int das16cs_timer_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ static int get_prodid(struct comedi_device * dev, struct pcmcia_device *link)
+@@ -168,7 +168,7 @@ static const das16cs_board *das16cs_probe(struct comedi_device * dev,
+ static int das16cs_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	struct pcmcia_device *link;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int ret;
+ 	int i;
+ 
+@@ -286,7 +286,7 @@ static irqreturn_t das16cs_interrupt(int irq, void *d PT_REGS_ARG)
+  * "instructions" read/write data in "one-shot" or "software-triggered"
+  * mode.
+  */
+-static int das16cs_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int das16cs_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -328,12 +328,12 @@ static int das16cs_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int das16cs_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int das16cs_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	return -EINVAL;
+ }
+ 
+-static int das16cs_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int das16cs_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -489,7 +489,7 @@ static int das16cs_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int das16cs_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int das16cs_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -535,7 +535,7 @@ static int das16cs_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+-static int das16cs_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int das16cs_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -552,7 +552,7 @@ static int das16cs_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+  * useful to applications if you implement the insn_bits interface.
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+-static int das16cs_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int das16cs_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -572,7 +572,7 @@ static int das16cs_dio_insn_bits(struct comedi_device * dev, comedi_subdevice *
+ 	return 2;
+ }
+ 
+-static int das16cs_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int das16cs_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -610,13 +610,13 @@ static int das16cs_dio_insn_config(struct comedi_device * dev, comedi_subdevice
+ 	return insn->n;
+ }
+ 
+-static int das16cs_timer_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int das16cs_timer_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	return -EINVAL;
+ }
+ 
+-static int das16cs_timer_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int das16cs_timer_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
+index 7a3564e51244..aa431466053e 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas.c
+@@ -449,46 +449,46 @@ static comedi_driver driver_cb_pcidas = {
+       detach:cb_pcidas_detach,
+ };
+ 
+-static int cb_pcidas_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidas_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ai_config_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int cb_pcidas_ao_nofifo_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidas_ao_nofifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int cb_pcidas_ao_fifo_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidas_ao_fifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int cb_pcidas_ao_readback_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidas_ao_readback_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int cb_pcidas_ai_cmd(struct comedi_device * dev, comedi_subdevice * s);
+-static int cb_pcidas_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidas_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
++static int cb_pcidas_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int cb_pcidas_ao_cmd(struct comedi_device * dev, comedi_subdevice * s);
+-static int cb_pcidas_ao_inttrig(struct comedi_device * dev, comedi_subdevice * subdev,
++static int cb_pcidas_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
++static int cb_pcidas_ao_inttrig(struct comedi_device * dev, struct comedi_subdevice * subdev,
+ 	unsigned int trig_num);
+-static int cb_pcidas_ao_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidas_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+ static irqreturn_t cb_pcidas_interrupt(int irq, void *d PT_REGS_ARG);
+ static void handle_ao_interrupt(struct comedi_device * dev, unsigned int status);
+-static int cb_pcidas_cancel(struct comedi_device * dev, comedi_subdevice * s);
+-static int cb_pcidas_ao_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static int cb_pcidas_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
++static int cb_pcidas_ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static void cb_pcidas_load_counters(struct comedi_device * dev, unsigned int *ns,
+ 	int round_flags);
+-static int eeprom_read_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int caldac_read_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int caldac_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int caldac_write_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int caldac_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int trimpot_read_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int trimpot_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ static int cb_pcidas_trimpot_write(struct comedi_device * dev, unsigned int channel,
+ 	unsigned int value);
+-static int trimpot_write_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int trimpot_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dac08_read_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int dac08_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ static int dac08_write(struct comedi_device * dev, unsigned int value);
+-static int dac08_write_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int dac08_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ static int caldac_8800_write(struct comedi_device * dev, unsigned int address,
+ 	uint8_t value);
+@@ -509,7 +509,7 @@ static inline unsigned int cal_enable_bits(struct comedi_device * dev)
+  */
+ static int cb_pcidas_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	struct pci_dev *pcidev;
+ 	int index;
+ 	int i;
+@@ -752,7 +752,7 @@ static int cb_pcidas_detach(struct comedi_device * dev)
+  * "instructions" read/write data in "one-shot" or "software-triggered"
+  * mode.
+  */
+-static int cb_pcidas_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidas_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i;
+@@ -819,7 +819,7 @@ static int ai_config_calibration_source(struct comedi_device * dev, unsigned int
+ 	return 2;
+ }
+ 
+-static int ai_config_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int id = data[0];
+@@ -836,7 +836,7 @@ static int ai_config_insn(struct comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ // analog output insn for pcidas-1000 and 1200 series
+-static int cb_pcidas_ao_nofifo_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidas_ao_nofifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel;
+@@ -861,7 +861,7 @@ static int cb_pcidas_ao_nofifo_winsn(struct comedi_device * dev, comedi_subdevic
+ }
+ 
+ // analog output insn for pcidas-1602 series
+-static int cb_pcidas_ao_fifo_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidas_ao_fifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel;
+@@ -892,7 +892,7 @@ static int cb_pcidas_ao_fifo_winsn(struct comedi_device * dev, comedi_subdevice
+ 
+ // analog output readback insn
+ // XXX loses track of analog output value back after an analog ouput command is executed
+-static int cb_pcidas_ao_readback_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidas_ao_readback_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)];
+@@ -900,7 +900,7 @@ static int cb_pcidas_ao_readback_insn(struct comedi_device * dev, comedi_subdevi
+ 	return 1;
+ }
+ 
+-static int eeprom_read_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	uint8_t nvram_data;
+@@ -915,7 +915,7 @@ static int eeprom_read_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int caldac_write_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int caldac_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	const unsigned int channel = CR_CHAN(insn->chanspec);
+@@ -923,7 +923,7 @@ static int caldac_write_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return caldac_8800_write(dev, channel, data[0]);
+ }
+ 
+-static int caldac_read_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int caldac_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->caldac_value[CR_CHAN(insn->chanspec)];
+@@ -952,13 +952,13 @@ static int dac08_write(struct comedi_device * dev, unsigned int value)
+ 	return 1;
+ }
+ 
+-static int dac08_write_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int dac08_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	return dac08_write(dev, data[0]);
+ }
+ 
+-static int dac08_read_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int dac08_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->dac08_value;
+@@ -989,7 +989,7 @@ static int cb_pcidas_trimpot_write(struct comedi_device * dev,
+ 	return 1;
+ }
+ 
+-static int trimpot_write_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int trimpot_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int channel = CR_CHAN(insn->chanspec);
+@@ -997,7 +997,7 @@ static int trimpot_write_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return cb_pcidas_trimpot_write(dev, channel, data[0]);
+ }
+ 
+-static int trimpot_read_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int trimpot_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int channel = CR_CHAN(insn->chanspec);
+@@ -1007,7 +1007,7 @@ static int trimpot_read_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int cb_pcidas_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidas_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -1162,7 +1162,7 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s
+ 	return 0;
+ }
+ 
+-static int cb_pcidas_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int cb_pcidas_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+@@ -1249,7 +1249,7 @@ static int cb_pcidas_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int cb_pcidas_ao_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidas_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -1362,7 +1362,7 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device * dev, comedi_subdevice * s
+ 	return 0;
+ }
+ 
+-static int cb_pcidas_ao_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int cb_pcidas_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+@@ -1425,7 +1425,7 @@ static int cb_pcidas_ao_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int cb_pcidas_ao_inttrig(struct comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidas_ao_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int trig_num)
+ {
+ 	unsigned int num_bytes, num_points = thisboard->fifo_size;
+@@ -1477,7 +1477,7 @@ static int cb_pcidas_ao_inttrig(struct comedi_device * dev, comedi_subdevice * s
+ static irqreturn_t cb_pcidas_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s = dev->read_subdev;
++	struct comedi_subdevice *s = dev->read_subdev;
+ 	comedi_async *async;
+ 	int status, s5933_status;
+ 	int half_fifo = thisboard->fifo_size / 2;
+@@ -1588,7 +1588,7 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d PT_REGS_ARG)
+ 
+ static void handle_ao_interrupt(struct comedi_device * dev, unsigned int status)
+ {
+-	comedi_subdevice *s = dev->write_subdev;
++	struct comedi_subdevice *s = dev->write_subdev;
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 	unsigned int half_fifo = thisboard->fifo_size / 2;
+@@ -1643,7 +1643,7 @@ static void handle_ao_interrupt(struct comedi_device * dev, unsigned int status)
+ }
+ 
+ // cancel analog input command
+-static int cb_pcidas_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int cb_pcidas_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+ 
+@@ -1662,7 +1662,7 @@ static int cb_pcidas_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ // cancel analog output command
+-static int cb_pcidas_ao_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int cb_pcidas_ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+ 
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
+index 4095381f201e..f1e121110332 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
+@@ -1134,46 +1134,46 @@ static comedi_driver driver_cb_pcidas = {
+       detach:detach,
+ };
+ 
+-static int ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ai_config_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ao_readback_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int ao_readback_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ai_cmd(struct comedi_device * dev, comedi_subdevice * s);
+-static int ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
++static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int ao_cmd(struct comedi_device * dev, comedi_subdevice * s);
+-static int ao_inttrig(struct comedi_device * dev, comedi_subdevice * subdev,
++static int ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
++static int ao_inttrig(struct comedi_device * dev, struct comedi_subdevice * subdev,
+ 	unsigned int trig_num);
+-static int ao_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+ static irqreturn_t handle_interrupt(int irq, void *d PT_REGS_ARG);
+-static int ai_cancel(struct comedi_device * dev, comedi_subdevice * s);
+-static int ao_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static int ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
++static int ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int dio_callback(int dir, int port, int data, unsigned long arg);
+ static int dio_callback_4020(int dir, int port, int data, unsigned long arg);
+-static int di_rbits(struct comedi_device * dev, comedi_subdevice * s,
++static int di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int do_wbits(struct comedi_device * dev, comedi_subdevice * s,
++static int do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dio_60xx_config_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int dio_60xx_config_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dio_60xx_wbits(struct comedi_device * dev, comedi_subdevice * s,
++static int dio_60xx_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int calib_read_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int calib_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int calib_write_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int calib_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ad8402_read_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int ad8402_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ static void ad8402_write(struct comedi_device * dev, unsigned int channel,
+ 	unsigned int value);
+-static int ad8402_write_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int ad8402_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int eeprom_read_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ static void check_adc_timing(struct comedi_device * dev, comedi_cmd * cmd);
+ static unsigned int get_divisor(unsigned int ns, unsigned int flags);
+@@ -1365,7 +1365,7 @@ static void init_plx9080(struct comedi_device * dev)
+  */
+ static int setup_subdevices(struct comedi_device * dev)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	void *dio_8255_iobase;
+ 	int i;
+ 
+@@ -1881,7 +1881,7 @@ static int detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bits = 0, n, i;
+@@ -2106,7 +2106,7 @@ static int ai_config_master_clock(struct comedi_device * dev, unsigned int * dat
+ 	return -EINVAL;
+ }
+ 
+-static int ai_config_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int id = data[0];
+@@ -2128,7 +2128,7 @@ static int ai_config_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return -EINVAL;
+ }
+ 
+-static int ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -2679,7 +2679,7 @@ static inline void load_first_dma_descriptor(struct comedi_device * dev,
+ 	}
+ }
+ 
+-static int ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+@@ -2799,7 +2799,7 @@ static int ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ // read num_samples from 16 bit wide ai fifo
+ static void pio_drain_ai_fifo_16(struct comedi_device * dev)
+ {
+-	comedi_subdevice *s = dev->read_subdev;
++	struct comedi_subdevice *s = dev->read_subdev;
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 	unsigned int i;
+@@ -2866,7 +2866,7 @@ static void pio_drain_ai_fifo_16(struct comedi_device * dev)
+  */
+ static void pio_drain_ai_fifo_32(struct comedi_device * dev)
+ {
+-	comedi_subdevice *s = dev->read_subdev;
++	struct comedi_subdevice *s = dev->read_subdev;
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 	unsigned int i;
+@@ -2955,7 +2955,7 @@ static void drain_dma_buffers(struct comedi_device * dev, unsigned int channel)
+ void handle_ai_interrupt(struct comedi_device * dev, unsigned short status,
+ 	unsigned int plx_status)
+ {
+-	comedi_subdevice *s = dev->read_subdev;
++	struct comedi_subdevice *s = dev->read_subdev;
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 	uint8_t dma1_status;
+@@ -3077,7 +3077,7 @@ static void restart_ao_dma(struct comedi_device * dev)
+ static void handle_ao_interrupt(struct comedi_device * dev, unsigned short status,
+ 	unsigned int plx_status)
+ {
+-	comedi_subdevice *s = dev->write_subdev;
++	struct comedi_subdevice *s = dev->write_subdev;
+ 	comedi_async *async;
+ 	comedi_cmd *cmd;
+ 	uint8_t dma0_status;
+@@ -3174,7 +3174,7 @@ void abort_dma(struct comedi_device * dev, unsigned int channel)
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ }
+ 
+-static int ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+ 
+@@ -3194,7 +3194,7 @@ static int ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -3224,7 +3224,7 @@ static int ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int ao_readback_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int ao_readback_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = priv(dev)->ao_value[CR_CHAN(insn->chanspec)];
+@@ -3413,7 +3413,7 @@ static inline int external_ai_queue_in_use(struct comedi_device * dev)
+ 	return 1;
+ }
+ 
+-static int ao_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 
+@@ -3438,7 +3438,7 @@ static int ao_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ao_inttrig(struct comedi_device * dev, comedi_subdevice * s,
++static int ao_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int trig_num)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+@@ -3461,7 +3461,7 @@ static int ao_inttrig(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int ao_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -3577,7 +3577,7 @@ static int ao_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int ao_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	writew(0x0, priv(dev)->main_iobase + DAC_CONTROL0_REG);
+ 	abort_dma(dev, 0);
+@@ -3605,7 +3605,7 @@ static int dio_callback_4020(int dir, int port, int data, unsigned long iobase)
+ 	}
+ }
+ 
+-static int di_rbits(struct comedi_device * dev, comedi_subdevice * s,
++static int di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bits;
+@@ -3618,7 +3618,7 @@ static int di_rbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int do_wbits(struct comedi_device * dev, comedi_subdevice * s,
++static int do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] &= 0xf;
+@@ -3634,7 +3634,7 @@ static int do_wbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int dio_60xx_config_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int dio_60xx_config_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int mask;
+@@ -3661,7 +3661,7 @@ static int dio_60xx_config_insn(struct comedi_device * dev, comedi_subdevice * s
+ 	return 1;
+ }
+ 
+-static int dio_60xx_wbits(struct comedi_device * dev, comedi_subdevice * s,
++static int dio_60xx_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+@@ -3694,7 +3694,7 @@ static void caldac_write(struct comedi_device * dev, unsigned int channel,
+ 	}
+ }
+ 
+-static int calib_write_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int calib_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel = CR_CHAN(insn->chanspec);
+@@ -3709,7 +3709,7 @@ static int calib_write_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int calib_read_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int calib_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int channel = CR_CHAN(insn->chanspec);
+@@ -3750,7 +3750,7 @@ static void ad8402_write(struct comedi_device * dev, unsigned int channel,
+ }
+ 
+ /* for pci-das6402/16, channel 0 is analog input gain and channel 1 is offset */
+-static int ad8402_write_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int ad8402_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel = CR_CHAN(insn->chanspec);
+@@ -3767,7 +3767,7 @@ static int ad8402_write_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int ad8402_read_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int ad8402_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int channel = CR_CHAN(insn->chanspec);
+@@ -3839,7 +3839,7 @@ static uint16_t read_eeprom(struct comedi_device * dev, uint8_t address)
+ 	return value;
+ }
+ 
+-static int eeprom_read_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = read_eeprom(dev, CR_CHAN(insn->chanspec));
+diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
+index d433780d5b50..474ffedc6daa 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidda.c
++++ b/drivers/staging/comedi/drivers/cb_pcidda.c
+@@ -234,11 +234,11 @@ typedef struct {
+ 
+ static int cb_pcidda_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int cb_pcidda_detach(struct comedi_device * dev);
+-//static int cb_pcidda_ai_rinsn(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data);
+-static int cb_pcidda_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++//static int cb_pcidda_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data);
++static int cb_pcidda_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-//static int cb_pcidda_ai_cmd(struct comedi_device *dev,comedi_subdevice *s);
+-//static int cb_pcidda_ai_cmdtest(struct comedi_device *dev,comedi_subdevice *s, comedi_cmd *cmd);
++//static int cb_pcidda_ai_cmd(struct comedi_device *dev,struct comedi_subdevice *s);
++//static int cb_pcidda_ai_cmdtest(struct comedi_device *dev,struct comedi_subdevice *s, comedi_cmd *cmd);
+ //static int cb_pcidda_ns_to_timer(unsigned int *ns,int round);
+ static unsigned int cb_pcidda_serial_in(struct comedi_device * dev);
+ static void cb_pcidda_serial_out(struct comedi_device * dev, unsigned int value,
+@@ -267,7 +267,7 @@ static comedi_driver driver_cb_pcidda = {
+  */
+ static int cb_pcidda_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	struct pci_dev *pcidev;
+ 	int index;
+ 
+@@ -413,7 +413,7 @@ static int cb_pcidda_detach(struct comedi_device * dev)
+  * I will program this later... ;-)
+  */
+ #if 0
+-static int cb_pcidda_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int cb_pcidda_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	printk("cb_pcidda_ai_cmd\n");
+ 	printk("subdev: %d\n", cmd->subdev);
+@@ -432,7 +432,7 @@ static int cb_pcidda_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ #endif
+ 
+ #if 0
+-static int cb_pcidda_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidda_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -598,7 +598,7 @@ static int cb_pcidda_ns_to_timer(unsigned int *ns, int round)
+ }
+ #endif
+ 
+-static int cb_pcidda_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidda_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int command;
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
+index 09be4e19522e..435bb39e8e46 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
+@@ -184,11 +184,11 @@ static comedi_driver driver_cb_pcimdas = {
+       detach:cb_pcimdas_detach,
+ };
+ 
+-static int cb_pcimdas_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int cb_pcimdas_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int cb_pcimdas_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int cb_pcimdas_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int cb_pcimdas_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int cb_pcimdas_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ /*
+@@ -199,7 +199,7 @@ static int cb_pcimdas_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+  */
+ static int cb_pcimdas_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	struct pci_dev *pcidev;
+ 	int index;
+ 	//int i;
+@@ -372,7 +372,7 @@ static int cb_pcimdas_detach(struct comedi_device * dev)
+  * "instructions" read/write data in "one-shot" or "software-triggered"
+  * mode.
+  */
+-static int cb_pcimdas_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int cb_pcimdas_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i;
+@@ -437,7 +437,7 @@ static int cb_pcimdas_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int cb_pcimdas_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int cb_pcimdas_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -465,7 +465,7 @@ static int cb_pcimdas_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+-static int cb_pcimdas_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int cb_pcimdas_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
+index eb583bfd648c..2b953c2e1959 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
+@@ -197,9 +197,9 @@ MODULE_DESCRIPTION("Comedi low-level driver for the Computerboards PCIM-DDA "
+ MODULE_LICENSE("GPL");
+ COMEDI_PCI_INITCLEANUP_NOMODULE(cb_pcimdda_driver, pci_table);
+ 
+-static int ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ /*---------------------------------------------------------------------------
+@@ -240,7 +240,7 @@ static int probe(struct comedi_device * dev, const comedi_devconfig * it);
+  */
+ static int attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int err;
+ 
+ /*
+@@ -352,7 +352,7 @@ static int detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -391,7 +391,7 @@ static int ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+    all AO channels update simultaneously.  This is useful for some control
+    applications, I would imagine.
+ */
+-static int ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c
+index 7d842a2bb5e0..aa6892254f39 100644
+--- a/drivers/staging/comedi/drivers/comedi_bond.c
++++ b/drivers/staging/comedi/drivers/comedi_bond.c
+@@ -213,9 +213,9 @@ static comedi_driver driver_bonding = {
+       .num_names =	sizeof(bondingBoards) / sizeof(struct BondingBoard),
+ };
+ 
+-static int bonding_dio_insn_bits(struct comedi_device *dev, comedi_subdevice *s,
++static int bonding_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+-static int bonding_dio_insn_config(struct comedi_device *dev, comedi_subdevice *s,
++static int bonding_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+ 
+ /*
+@@ -226,7 +226,7 @@ static int bonding_dio_insn_config(struct comedi_device *dev, comedi_subdevice *
+  */
+ static int bonding_attach(struct comedi_device *dev, comedi_devconfig *it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	LOG_MSG("comedi%d\n", dev->minor);
+ 
+@@ -293,7 +293,7 @@ static int bonding_detach(struct comedi_device *dev)
+  * useful to applications if you implement the insn_bits interface.
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+-static int bonding_dio_insn_bits(struct comedi_device *dev, comedi_subdevice *s,
++static int bonding_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data)
+ {
+ #define LSAMPL_BITS (sizeof(unsigned int)*8)
+@@ -340,7 +340,7 @@ static int bonding_dio_insn_bits(struct comedi_device *dev, comedi_subdevice *s,
+ 	return insn->n;
+ }
+ 
+-static int bonding_dio_insn_config(struct comedi_device *dev, comedi_subdevice *s,
++static int bonding_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec), ret, io_bits = s->io_bits;
+diff --git a/drivers/staging/comedi/drivers/comedi_fc.c b/drivers/staging/comedi/drivers/comedi_fc.c
+index 842b250a7c65..8e7ec147285d 100644
+--- a/drivers/staging/comedi/drivers/comedi_fc.c
++++ b/drivers/staging/comedi/drivers/comedi_fc.c
+@@ -28,7 +28,7 @@
+ 
+ #include "comedi_fc.h"
+ 
+-static void increment_scan_progress(comedi_subdevice *subd,
++static void increment_scan_progress(struct comedi_subdevice *subd,
+ 				    unsigned int num_bytes)
+ {
+ 	comedi_async *async = subd->async;
+@@ -42,7 +42,7 @@ static void increment_scan_progress(comedi_subdevice *subd,
+ }
+ 
+ /* Writes an array of data points to comedi's buffer */
+-unsigned int cfc_write_array_to_buffer(comedi_subdevice *subd, void *data,
++unsigned int cfc_write_array_to_buffer(struct comedi_subdevice *subd, void *data,
+ 				       unsigned int num_bytes)
+ {
+ 	comedi_async *async = subd->async;
+@@ -67,7 +67,7 @@ unsigned int cfc_write_array_to_buffer(comedi_subdevice *subd, void *data,
+ }
+ EXPORT_SYMBOL(cfc_write_array_to_buffer);
+ 
+-unsigned int cfc_read_array_from_buffer(comedi_subdevice *subd, void *data,
++unsigned int cfc_read_array_from_buffer(struct comedi_subdevice *subd, void *data,
+ 					unsigned int num_bytes)
+ {
+ 	comedi_async *async = subd->async;
+@@ -85,7 +85,7 @@ unsigned int cfc_read_array_from_buffer(comedi_subdevice *subd, void *data,
+ }
+ EXPORT_SYMBOL(cfc_read_array_from_buffer);
+ 
+-unsigned int cfc_handle_events(struct comedi_device *dev, comedi_subdevice *subd)
++unsigned int cfc_handle_events(struct comedi_device *dev, struct comedi_subdevice *subd)
+ {
+ 	unsigned int events = subd->async->events;
+ 
+diff --git a/drivers/staging/comedi/drivers/comedi_fc.h b/drivers/staging/comedi/drivers/comedi_fc.h
+index 4f251cd509e6..494ae3f2aff6 100644
+--- a/drivers/staging/comedi/drivers/comedi_fc.h
++++ b/drivers/staging/comedi/drivers/comedi_fc.h
+@@ -30,30 +30,30 @@
+ #include "../comedidev.h"
+ 
+ /* Writes an array of data points to comedi's buffer */
+-extern unsigned int cfc_write_array_to_buffer(comedi_subdevice *subd,
++extern unsigned int cfc_write_array_to_buffer(struct comedi_subdevice *subd,
+ 					      void *data,
+ 					      unsigned int num_bytes);
+ 
+-static inline unsigned int cfc_write_to_buffer(comedi_subdevice *subd,
++static inline unsigned int cfc_write_to_buffer(struct comedi_subdevice *subd,
+ 					       short data)
+ {
+ 	return cfc_write_array_to_buffer(subd, &data, sizeof(data));
+ };
+ 
+-static inline unsigned int cfc_write_long_to_buffer(comedi_subdevice *subd,
++static inline unsigned int cfc_write_long_to_buffer(struct comedi_subdevice *subd,
+ 						    unsigned int data)
+ {
+ 	return cfc_write_array_to_buffer(subd, &data, sizeof(data));
+ };
+ 
+-extern unsigned int cfc_read_array_from_buffer(comedi_subdevice *subd,
++extern unsigned int cfc_read_array_from_buffer(struct comedi_subdevice *subd,
+ 					       void *data,
+ 					       unsigned int num_bytes);
+ 
+ extern unsigned int cfc_handle_events(struct comedi_device *dev,
+-				      comedi_subdevice *subd);
++				      struct comedi_subdevice *subd);
+ 
+-static inline unsigned int cfc_bytes_per_scan(comedi_subdevice *subd)
++static inline unsigned int cfc_bytes_per_scan(struct comedi_subdevice *subd)
+ {
+ 	int num_samples;
+ 	int bits_per_sample;
+diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c
+index b432d50df4d4..50790b651cef 100644
+--- a/drivers/staging/comedi/drivers/comedi_parport.c
++++ b/drivers/staging/comedi/drivers/comedi_parport.c
+@@ -108,7 +108,7 @@ struct parport_private {
+ };
+ #define devpriv ((struct parport_private *)(dev->private))
+ 
+-static int parport_insn_a(struct comedi_device *dev, comedi_subdevice *s,
++static int parport_insn_a(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			  comedi_insn *insn, unsigned int *data)
+ {
+ 	if (data[0]) {
+@@ -123,7 +123,7 @@ static int parport_insn_a(struct comedi_device *dev, comedi_subdevice *s,
+ 	return 2;
+ }
+ 
+-static int parport_insn_config_a(struct comedi_device *dev, comedi_subdevice *s,
++static int parport_insn_config_a(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data)
+ {
+ 	if (data[0]) {
+@@ -138,7 +138,7 @@ static int parport_insn_config_a(struct comedi_device *dev, comedi_subdevice *s,
+ 	return 1;
+ }
+ 
+-static int parport_insn_b(struct comedi_device *dev, comedi_subdevice *s,
++static int parport_insn_b(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			  comedi_insn *insn, unsigned int *data)
+ {
+ 	if (data[0]) {
+@@ -151,7 +151,7 @@ static int parport_insn_b(struct comedi_device *dev, comedi_subdevice *s,
+ 	return 2;
+ }
+ 
+-static int parport_insn_c(struct comedi_device *dev, comedi_subdevice *s,
++static int parport_insn_c(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			  comedi_insn *insn, unsigned int *data)
+ {
+ 	data[0] &= 0x0f;
+@@ -167,7 +167,7 @@ static int parport_insn_c(struct comedi_device *dev, comedi_subdevice *s,
+ 	return 2;
+ }
+ 
+-static int parport_intr_insn(struct comedi_device *dev, comedi_subdevice *s,
++static int parport_intr_insn(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			     comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n < 1)
+@@ -177,7 +177,7 @@ static int parport_intr_insn(struct comedi_device *dev, comedi_subdevice *s,
+ 	return 2;
+ }
+ 
+-static int parport_intr_cmdtest(struct comedi_device *dev, comedi_subdevice *s,
++static int parport_intr_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				comedi_cmd *cmd)
+ {
+ 	int err = 0;
+@@ -252,7 +252,7 @@ static int parport_intr_cmdtest(struct comedi_device *dev, comedi_subdevice *s,
+ 	return 0;
+ }
+ 
+-static int parport_intr_cmd(struct comedi_device *dev, comedi_subdevice *s)
++static int parport_intr_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	devpriv->c_data |= 0x10;
+ 	outb(devpriv->c_data, dev->iobase + PARPORT_C);
+@@ -262,7 +262,7 @@ static int parport_intr_cmd(struct comedi_device *dev, comedi_subdevice *s)
+ 	return 0;
+ }
+ 
+-static int parport_intr_cancel(struct comedi_device *dev, comedi_subdevice *s)
++static int parport_intr_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	printk(KERN_DEBUG "parport_intr_cancel()\n");
+ 
+@@ -277,7 +277,7 @@ static int parport_intr_cancel(struct comedi_device *dev, comedi_subdevice *s)
+ static irqreturn_t parport_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s = dev->subdevices + 3;
++	struct comedi_subdevice *s = dev->subdevices + 3;
+ 
+ 	if (!devpriv->enable_irq) {
+ 		printk(KERN_ERR "comedi_parport: bogus irq, ignored\n");
+@@ -296,7 +296,7 @@ static int parport_attach(struct comedi_device *dev, comedi_devconfig *it)
+ 	int ret;
+ 	unsigned int irq;
+ 	unsigned long iobase;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	iobase = it->options[0];
+ 	printk(KERN_INFO "comedi%d: parport: 0x%04lx ", dev->minor, iobase);
+diff --git a/drivers/staging/comedi/drivers/comedi_rt_timer.c b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+index 202b04b2e394..76a1cdcfcd1c 100644
+--- a/drivers/staging/comedi/drivers/comedi_rt_timer.c
++++ b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+@@ -124,9 +124,9 @@ static inline RTIME nano2count(long long ns)
+ 
+ static int timer_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int timer_detach(struct comedi_device * dev);
+-static int timer_inttrig(struct comedi_device * dev, comedi_subdevice * s,
++static int timer_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int trig_num);
+-static int timer_start_cmd(struct comedi_device * dev, comedi_subdevice * s);
++static int timer_start_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ 
+ static comedi_driver driver_timer = {
+       module:THIS_MODULE,
+@@ -162,7 +162,7 @@ typedef struct {
+ } timer_private;
+ #define devpriv ((timer_private *)dev->private)
+ 
+-static int timer_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int timer_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	devpriv->stop = 1;
+ 
+@@ -209,7 +209,7 @@ inline static int check_conversion_timing(struct comedi_device * dev,
+ static int timer_data_read(struct comedi_device * dev, comedi_cmd * cmd,
+ 	unsigned int index)
+ {
+-	comedi_subdevice *s = dev->read_subdev;
++	struct comedi_subdevice *s = dev->read_subdev;
+ 	int ret;
+ 	unsigned int data;
+ 
+@@ -234,7 +234,7 @@ static int timer_data_read(struct comedi_device * dev, comedi_cmd * cmd,
+ static int timer_data_write(struct comedi_device * dev, comedi_cmd * cmd,
+ 	unsigned int index)
+ {
+-	comedi_subdevice *s = dev->write_subdev;
++	struct comedi_subdevice *s = dev->write_subdev;
+ 	unsigned int num_bytes;
+ 	short data;
+ 	unsigned int long_data;
+@@ -269,7 +269,7 @@ static int timer_data_write(struct comedi_device * dev, comedi_cmd * cmd,
+ static int timer_dio_read(struct comedi_device * dev, comedi_cmd * cmd,
+ 	unsigned int index)
+ {
+-	comedi_subdevice *s = dev->read_subdev;
++	struct comedi_subdevice *s = dev->read_subdev;
+ 	int ret;
+ 	unsigned int data;
+ 
+@@ -291,7 +291,7 @@ static int timer_dio_read(struct comedi_device * dev, comedi_cmd * cmd,
+ static void scan_task_func(comedi_rt_task_context_t d)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s = dev->subdevices + 0;
++	struct comedi_subdevice *s = dev->subdevices + 0;
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 	int i, ret;
+@@ -361,7 +361,7 @@ static void scan_task_func(comedi_rt_task_context_t d)
+ static void timer_task_func(comedi_rt_task_context_t d)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s = dev->subdevices + 0;
++	struct comedi_subdevice *s = dev->subdevices + 0;
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	int ret;
+ 	unsigned long long n;
+@@ -396,7 +396,7 @@ static void timer_task_func(comedi_rt_task_context_t d)
+ 	}
+ }
+ 
+-static int timer_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int timer_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	comedi_insn xinsn = *insn;
+@@ -444,7 +444,7 @@ static int cmdtest_helper(comedi_cmd * cmd,
+ 	return err;
+ }
+ 
+-static int timer_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int timer_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -516,7 +516,7 @@ static int timer_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int timer_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int timer_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	int ret;
+ 	comedi_cmd *cmd = &s->async->cmd;
+@@ -567,7 +567,7 @@ static int timer_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int timer_inttrig(struct comedi_device * dev, comedi_subdevice * s,
++static int timer_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int trig_num)
+ {
+ 	if (trig_num != 0)
+@@ -578,7 +578,7 @@ static int timer_inttrig(struct comedi_device * dev, comedi_subdevice * s,
+ 	return timer_start_cmd(dev, s);
+ }
+ 
+-static int timer_start_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int timer_start_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+@@ -610,7 +610,7 @@ static int timer_start_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ static int timer_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int ret;
+-	comedi_subdevice *s, *emul_s;
++	struct comedi_subdevice *s, *emul_s;
+ 	struct comedi_device *emul_dev;
+ 	/* These should probably be devconfig options[] */
+ 	const int timer_priority = 4;
+diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c
+index 70aeb6088e1b..462d453eb88f 100644
+--- a/drivers/staging/comedi/drivers/comedi_test.c
++++ b/drivers/staging/comedi/drivers/comedi_test.c
+@@ -107,13 +107,13 @@ static comedi_driver driver_waveform = {
+ 
+ COMEDI_INITCLEANUP(driver_waveform);
+ 
+-static int waveform_ai_cmdtest(struct comedi_device *dev, comedi_subdevice *s,
++static int waveform_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			       comedi_cmd *cmd);
+-static int waveform_ai_cmd(struct comedi_device *dev, comedi_subdevice *s);
+-static int waveform_ai_cancel(struct comedi_device *dev, comedi_subdevice *s);
+-static int waveform_ai_insn_read(struct comedi_device *dev, comedi_subdevice *s,
++static int waveform_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
++static int waveform_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
++static int waveform_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+-static int waveform_ao_insn_write(struct comedi_device *dev, comedi_subdevice *s,
++static int waveform_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				  comedi_insn *insn, unsigned int *data);
+ static short fake_sawtooth(struct comedi_device *dev, unsigned int range,
+ 			     unsigned long current_time);
+@@ -194,7 +194,7 @@ static void waveform_ai_interrupt(unsigned long arg)
+ 
+ static int waveform_attach(struct comedi_device *dev, comedi_devconfig *it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int amplitude = it->options[0];
+ 	int period = it->options[1];
+ 	int i;
+@@ -269,7 +269,7 @@ static int waveform_detach(struct comedi_device *dev)
+ 	return 0;
+ }
+ 
+-static int waveform_ai_cmdtest(struct comedi_device *dev, comedi_subdevice *s,
++static int waveform_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			       comedi_cmd *cmd)
+ {
+ 	int err = 0;
+@@ -397,7 +397,7 @@ static int waveform_ai_cmdtest(struct comedi_device *dev, comedi_subdevice *s,
+ 	return 0;
+ }
+ 
+-static int waveform_ai_cmd(struct comedi_device *dev, comedi_subdevice *s)
++static int waveform_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 
+@@ -429,7 +429,7 @@ static int waveform_ai_cmd(struct comedi_device *dev, comedi_subdevice *s)
+ 	return 0;
+ }
+ 
+-static int waveform_ai_cancel(struct comedi_device *dev, comedi_subdevice *s)
++static int waveform_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	devpriv->timer_running = 0;
+ 	del_timer(&devpriv->timer);
+@@ -439,7 +439,7 @@ static int waveform_ai_cancel(struct comedi_device *dev, comedi_subdevice *s)
+ static short fake_sawtooth(struct comedi_device *dev, unsigned int range_index,
+ 			     unsigned long current_time)
+ {
+-	comedi_subdevice *s = dev->read_subdev;
++	struct comedi_subdevice *s = dev->read_subdev;
+ 	unsigned int offset = s->maxdata / 2;
+ 	u64 value;
+ 	const comedi_krange *krange = &s->range_table->range[range_index];
+@@ -460,7 +460,7 @@ static short fake_sawtooth(struct comedi_device *dev, unsigned int range_index,
+ static short fake_squarewave(struct comedi_device *dev, unsigned int range_index,
+ 			       unsigned long current_time)
+ {
+-	comedi_subdevice *s = dev->read_subdev;
++	struct comedi_subdevice *s = dev->read_subdev;
+ 	unsigned int offset = s->maxdata / 2;
+ 	u64 value;
+ 	const comedi_krange *krange = &s->range_table->range[range_index];
+@@ -504,7 +504,7 @@ static short fake_waveform(struct comedi_device *dev, unsigned int channel,
+ 	return fake_flatline(dev, range, current_time);
+ }
+ 
+-static int waveform_ai_insn_read(struct comedi_device *dev, comedi_subdevice *s,
++static int waveform_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, chan = CR_CHAN(insn->chanspec);
+@@ -515,7 +515,7 @@ static int waveform_ai_insn_read(struct comedi_device *dev, comedi_subdevice *s,
+ 	return insn->n;
+ }
+ 
+-static int waveform_ao_insn_write(struct comedi_device *dev, comedi_subdevice *s,
++static int waveform_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				  comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
+index 845f97e81280..0b96859cc3bf 100644
+--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
++++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
+@@ -85,13 +85,13 @@ static comedi_driver driver_contec = {
+ };
+ 
+ /* Classic digital IO */
+-static int contec_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int contec_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int contec_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int contec_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ #if 0
+-static int contec_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int contec_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+ 
+ static int contec_ns_to_timer(unsigned int *ns, int round);
+@@ -100,7 +100,7 @@ static int contec_ns_to_timer(unsigned int *ns, int round);
+ static int contec_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	struct pci_dev *pcidev;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	printk("comedi%d: contec: ", dev->minor);
+ 
+@@ -179,7 +179,7 @@ static int contec_detach(struct comedi_device * dev)
+ }
+ 
+ #if 0
+-static int contec_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int contec_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	printk("contec_cmdtest called\n");
+@@ -192,7 +192,7 @@ static int contec_ns_to_timer(unsigned int *ns, int round)
+ }
+ #endif
+ 
+-static int contec_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int contec_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -212,7 +212,7 @@ static int contec_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int contec_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int contec_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
+index 21bf5d3131b7..9ef655eec40b 100644
+--- a/drivers/staging/comedi/drivers/daqboard2000.c
++++ b/drivers/staging/comedi/drivers/daqboard2000.c
+@@ -393,7 +393,7 @@ static void setup_sampling(struct comedi_device * dev, int chan, int gain)
+ 	writeAcqScanListEntry(dev, word3);
+ }
+ 
+-static int daqboard2000_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int daqboard2000_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -450,7 +450,7 @@ static int daqboard2000_ai_insn_read(struct comedi_device * dev, comedi_subdevic
+ 	return i;
+ }
+ 
+-static int daqboard2000_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int daqboard2000_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -463,7 +463,7 @@ static int daqboard2000_ao_insn_read(struct comedi_device * dev, comedi_subdevic
+ 	return i;
+ }
+ 
+-static int daqboard2000_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
++static int daqboard2000_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -720,7 +720,7 @@ static int daqboard2000_8255_cb(int dir, int port, int data,
+ static int daqboard2000_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int result = 0;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	struct pci_dev *card = NULL;
+ 	void *aux_data;
+ 	unsigned int aux_len;
+diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
+index 1614a2070aff..a0029dc7e389 100644
+--- a/drivers/staging/comedi/drivers/das08.c
++++ b/drivers/staging/comedi/drivers/das08.c
+@@ -154,19 +154,19 @@ driver.
+ 
+ /* gainlist same as _pgx_ below */
+ 
+-static int das08_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int das08_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das08_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
++static int das08_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das08_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
++static int das08_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das08jr_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
++static int das08jr_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das08jr_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
++static int das08jr_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das08jr_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int das08jr_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das08ao_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int das08ao_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ static void i8254_set_mode_low(unsigned int base, int channel,
+ 	unsigned int mode);
+@@ -512,7 +512,7 @@ MODULE_DEVICE_TABLE(pci, das08_pci_table);
+ 
+ #define TIMEOUT 100000
+ 
+-static int das08_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int das08_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+@@ -579,7 +579,7 @@ static int das08_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int das08_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
++static int das08_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = 0;
+@@ -588,7 +588,7 @@ static int das08_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int das08_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
++static int das08_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int wbits;
+@@ -611,7 +611,7 @@ static int das08_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int das08jr_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
++static int das08jr_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = 0;
+@@ -620,7 +620,7 @@ static int das08jr_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int das08jr_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
++static int das08jr_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	// null bits we are going to set
+@@ -634,7 +634,7 @@ static int das08jr_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int das08jr_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int das08jr_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -668,7 +668,7 @@ static int das08jr_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+  * a different method to force an update.
+  *
+  */
+-static int das08ao_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int das08ao_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -782,7 +782,7 @@ static unsigned int i8254_read_status(struct i8254_struct *st, int channel)
+ 	return i8254_read_status_low(st->iobase, chan);
+ }
+ 
+-static int das08_counter_read(struct comedi_device * dev, comedi_subdevice * s,
++static int das08_counter_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = insn->chanspec;
+@@ -794,7 +794,7 @@ static int das08_counter_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int das08_counter_write(struct comedi_device * dev, comedi_subdevice * s,
++static int das08_counter_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = insn->chanspec;
+@@ -805,7 +805,7 @@ static int das08_counter_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int das08_counter_config(struct comedi_device * dev, comedi_subdevice * s,
++static int das08_counter_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = insn->chanspec;
+@@ -842,7 +842,7 @@ static comedi_driver driver_das08 = {
+ 
+ int das08_common_attach(struct comedi_device * dev, unsigned long iobase)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int ret;
+ 
+ 	// allocate ioports for non-pcmcia, non-pci boards
+diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
+index 07f8856c2c39..94e59a5c6629 100644
+--- a/drivers/staging/comedi/drivers/das16.c
++++ b/drivers/staging/comedi/drivers/das16.c
+@@ -326,20 +326,20 @@ struct munge_info {
+ 	unsigned have_byte:1;
+ };
+ 
+-static int das16_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int das16_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das16_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
++static int das16_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das16_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
++static int das16_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das16_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int das16_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int das16_cmd_test(struct comedi_device * dev, comedi_subdevice * s,
++static int das16_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int das16_cmd_exec(struct comedi_device * dev, comedi_subdevice * s);
+-static int das16_cancel(struct comedi_device * dev, comedi_subdevice * s);
+-static void das16_ai_munge(struct comedi_device * dev, comedi_subdevice * s,
++static int das16_cmd_exec(struct comedi_device * dev, struct comedi_subdevice * s);
++static int das16_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
++static void das16_ai_munge(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	void *array, unsigned int num_bytes, unsigned int start_chan_index);
+ 
+ static void das16_reset(struct comedi_device * dev);
+@@ -742,7 +742,7 @@ struct das16_private_struct {
+ #define devpriv ((struct das16_private_struct *)(dev->private))
+ #define thisboard ((struct das16_board_struct *)(dev->board_ptr))
+ 
+-static int das16_cmd_test(struct comedi_device * dev, comedi_subdevice * s,
++static int das16_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0, tmp;
+@@ -893,7 +893,7 @@ static int das16_cmd_test(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int das16_cmd_exec(struct comedi_device * dev, comedi_subdevice * s)
++static int das16_cmd_exec(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+@@ -996,7 +996,7 @@ static int das16_cmd_exec(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int das16_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int das16_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+ 
+@@ -1031,7 +1031,7 @@ static void das16_reset(struct comedi_device * dev)
+ 	outb(0, dev->iobase + DAS16_CNTR_CONTROL);
+ }
+ 
+-static int das16_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int das16_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+@@ -1079,7 +1079,7 @@ static int das16_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int das16_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
++static int das16_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bits;
+@@ -1091,7 +1091,7 @@ static int das16_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int das16_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
++static int das16_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int wbits;
+@@ -1111,7 +1111,7 @@ static int das16_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int das16_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int das16_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -1200,7 +1200,7 @@ static int disable_dma_on_even(struct comedi_device * dev)
+ static void das16_interrupt(struct comedi_device * dev)
+ {
+ 	unsigned long dma_flags, spin_flags;
+-	comedi_subdevice *s = dev->read_subdev;
++	struct comedi_subdevice *s = dev->read_subdev;
+ 	comedi_async *async;
+ 	comedi_cmd *cmd;
+ 	int num_bytes, residue;
+@@ -1368,7 +1368,7 @@ static int das1600_mode_detect(struct comedi_device * dev)
+ 
+ static int das16_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int ret;
+ 	unsigned int irq;
+ 	unsigned long iobase;
+@@ -1715,7 +1715,7 @@ static unsigned int das16_suggest_transfer_size(struct comedi_device * dev,
+ 	return size;
+ }
+ 
+-static void das16_ai_munge(struct comedi_device * dev, comedi_subdevice * s,
++static void das16_ai_munge(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	void *array, unsigned int num_bytes, unsigned int start_chan_index)
+ {
+ 	unsigned int i, num_samples = num_bytes / sizeof(short);
+diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
+index f646eb16d0c9..c337c803ec1e 100644
+--- a/drivers/staging/comedi/drivers/das16m1.c
++++ b/drivers/staging/comedi/drivers/das16m1.c
+@@ -131,19 +131,19 @@ static const comedi_lrange range_das16m1 = { 9,
+ 		}
+ };
+ 
+-static int das16m1_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
++static int das16m1_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das16m1_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
++static int das16m1_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das16m1_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int das16m1_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int das16m1_cmd_test(struct comedi_device * dev, comedi_subdevice * s,
++static int das16m1_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int das16m1_cmd_exec(struct comedi_device * dev, comedi_subdevice * s);
+-static int das16m1_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static int das16m1_cmd_exec(struct comedi_device * dev, struct comedi_subdevice * s);
++static int das16m1_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ 
+-static int das16m1_poll(struct comedi_device * dev, comedi_subdevice * s);
++static int das16m1_poll(struct comedi_device * dev, struct comedi_subdevice * s);
+ static irqreturn_t das16m1_interrupt(int irq, void *d PT_REGS_ARG);
+ static void das16m1_handler(struct comedi_device * dev, unsigned int status);
+ 
+@@ -200,7 +200,7 @@ static inline short munge_sample(short data)
+ 	return (data >> 4) & 0xfff;
+ }
+ 
+-static int das16m1_cmd_test(struct comedi_device * dev, comedi_subdevice * s,
++static int das16m1_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	unsigned int err = 0, tmp, i;
+@@ -322,7 +322,7 @@ static int das16m1_cmd_test(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int das16m1_cmd_exec(struct comedi_device * dev, comedi_subdevice * s)
++static int das16m1_cmd_exec(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+@@ -385,7 +385,7 @@ static int das16m1_cmd_exec(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int das16m1_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int das16m1_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	devpriv->control_state &= ~INTE & ~PACER_MASK;
+ 	outb(devpriv->control_state, dev->iobase + DAS16M1_INTR_CONTROL);
+@@ -393,7 +393,7 @@ static int das16m1_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int das16m1_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int das16m1_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+@@ -430,7 +430,7 @@ static int das16m1_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int das16m1_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
++static int das16m1_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bits;
+@@ -442,7 +442,7 @@ static int das16m1_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int das16m1_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
++static int das16m1_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int wbits;
+@@ -462,7 +462,7 @@ static int das16m1_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int das16m1_poll(struct comedi_device * dev, comedi_subdevice * s)
++static int das16m1_poll(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+ 	unsigned int status;
+@@ -516,7 +516,7 @@ static void munge_sample_array(short * array, unsigned int num_elements)
+ 
+ static void das16m1_handler(struct comedi_device * dev, unsigned int status)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	comedi_async *async;
+ 	comedi_cmd *cmd;
+ 	u16 num_samples;
+@@ -637,7 +637,7 @@ static int das16m1_irq_bits(unsigned int irq)
+ 
+ static int das16m1_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int ret;
+ 	unsigned int irq;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
+index 9fb800fbfc15..5a63a00d1a4c 100644
+--- a/drivers/staging/comedi/drivers/das1800.c
++++ b/drivers/staging/comedi/drivers/das1800.c
+@@ -183,29 +183,29 @@ enum {
+ static int das1800_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int das1800_detach(struct comedi_device * dev);
+ static int das1800_probe(struct comedi_device * dev);
+-static int das1800_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static int das1800_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static irqreturn_t das1800_interrupt(int irq, void *d PT_REGS_ARG);
+-static int das1800_ai_poll(struct comedi_device * dev, comedi_subdevice * s);
++static int das1800_ai_poll(struct comedi_device * dev, struct comedi_subdevice * s);
+ static void das1800_ai_handler(struct comedi_device * dev);
+-static void das1800_handle_dma(struct comedi_device * dev, comedi_subdevice * s,
++static void das1800_handle_dma(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int status);
+-static void das1800_flush_dma(struct comedi_device * dev, comedi_subdevice * s);
+-static void das1800_flush_dma_channel(struct comedi_device * dev, comedi_subdevice * s,
++static void das1800_flush_dma(struct comedi_device * dev, struct comedi_subdevice * s);
++static void das1800_flush_dma_channel(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int channel, uint16_t * buffer);
+ static void das1800_handle_fifo_half_full(struct comedi_device * dev,
+-	comedi_subdevice * s);
++	struct comedi_subdevice * s);
+ static void das1800_handle_fifo_not_empty(struct comedi_device * dev,
+-	comedi_subdevice * s);
+-static int das1800_ai_do_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++	struct comedi_subdevice * s);
++static int das1800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int das1800_ai_do_cmd(struct comedi_device * dev, comedi_subdevice * s);
+-static int das1800_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int das1800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
++static int das1800_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das1800_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int das1800_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das1800_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
++static int das1800_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das1800_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
++static int das1800_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ static int das1800_set_frequency(struct comedi_device * dev);
+@@ -592,7 +592,7 @@ static int das1800_init_dma(struct comedi_device * dev, unsigned int dma0,
+ 
+ static int das1800_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned long iobase = it->options[0];
+ 	unsigned int irq = it->options[1];
+ 	unsigned int dma0 = it->options[2];
+@@ -867,7 +867,7 @@ static int das1800_probe(struct comedi_device * dev)
+ 	return -1;
+ }
+ 
+-static int das1800_ai_poll(struct comedi_device * dev, comedi_subdevice * s)
++static int das1800_ai_poll(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+ 
+@@ -911,7 +911,7 @@ static irqreturn_t das1800_interrupt(int irq, void *d PT_REGS_ARG)
+ // the guts of the interrupt handler, that is shared with das1800_ai_poll
+ static void das1800_ai_handler(struct comedi_device * dev)
+ {
+-	comedi_subdevice *s = dev->subdevices + 0;	/* analog input subdevice */
++	struct comedi_subdevice *s = dev->subdevices + 0;	/* analog input subdevice */
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 	unsigned int status = inb(dev->iobase + DAS1800_STATUS);
+@@ -962,7 +962,7 @@ static void das1800_ai_handler(struct comedi_device * dev)
+ 	return;
+ }
+ 
+-static void das1800_handle_dma(struct comedi_device * dev, comedi_subdevice * s,
++static void das1800_handle_dma(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int status)
+ {
+ 	unsigned long flags;
+@@ -1023,7 +1023,7 @@ static void munge_data(struct comedi_device * dev, uint16_t * array,
+ 
+ /* Utility function used by das1800_flush_dma() and das1800_handle_dma().
+  * Assumes dma lock is held */
+-static void das1800_flush_dma_channel(struct comedi_device * dev, comedi_subdevice * s,
++static void das1800_flush_dma_channel(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int channel, uint16_t * buffer)
+ {
+ 	unsigned int num_bytes, num_samples;
+@@ -1053,7 +1053,7 @@ static void das1800_flush_dma_channel(struct comedi_device * dev, comedi_subdevi
+ 
+ /* flushes remaining data from board when external trigger has stopped aquisition
+  * and we are using dma transfers */
+-static void das1800_flush_dma(struct comedi_device * dev, comedi_subdevice * s)
++static void das1800_flush_dma(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+ 	const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
+@@ -1084,7 +1084,7 @@ static void das1800_flush_dma(struct comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ static void das1800_handle_fifo_half_full(struct comedi_device * dev,
+-	comedi_subdevice * s)
++	struct comedi_subdevice * s)
+ {
+ 	int numPoints = 0;	/* number of points to read */
+ 	comedi_cmd *cmd = &s->async->cmd;
+@@ -1103,7 +1103,7 @@ static void das1800_handle_fifo_half_full(struct comedi_device * dev,
+ }
+ 
+ static void das1800_handle_fifo_not_empty(struct comedi_device * dev,
+-	comedi_subdevice * s)
++	struct comedi_subdevice * s)
+ {
+ 	short dpnt;
+ 	int unipolar;
+@@ -1126,7 +1126,7 @@ static void das1800_handle_fifo_not_empty(struct comedi_device * dev,
+ 	return;
+ }
+ 
+-static int das1800_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int das1800_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	outb(0x0, dev->iobase + DAS1800_STATUS);	/* disable conversions */
+ 	outb(0x0, dev->iobase + DAS1800_CONTROL_B);	/* disable interrupts and dma */
+@@ -1139,7 +1139,7 @@ static int das1800_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ /* test analog input cmd */
+-static int das1800_ai_do_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int das1800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -1489,7 +1489,7 @@ static void program_chanlist(struct comedi_device * dev, comedi_cmd cmd)
+ }
+ 
+ // analog input do_cmd
+-static int das1800_ai_do_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int das1800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	int ret;
+ 	int control_a, control_c;
+@@ -1552,7 +1552,7 @@ static int das1800_ai_do_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ /* read analog input */
+-static int das1800_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int das1800_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+@@ -1612,7 +1612,7 @@ static int das1800_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ /* writes to an analog output channel */
+-static int das1800_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int das1800_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -1641,7 +1641,7 @@ static int das1800_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ /* reads from digital input channels */
+-static int das1800_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
++static int das1800_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -1652,7 +1652,7 @@ static int das1800_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ /* writes to digital output channels */
+-static int das1800_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
++static int das1800_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int wbits;
+diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c
+index e78d9eb0eb7a..6c0a28cb712c 100644
+--- a/drivers/staging/comedi/drivers/das6402.c
++++ b/drivers/staging/comedi/drivers/das6402.c
+@@ -116,7 +116,7 @@ typedef struct {
+ } das6402_private;
+ #define devpriv ((das6402_private *)dev->private)
+ 
+-static void das6402_ai_fifo_dregs(struct comedi_device * dev, comedi_subdevice * s);
++static void das6402_ai_fifo_dregs(struct comedi_device * dev, struct comedi_subdevice * s);
+ 
+ static void das6402_setcounter(struct comedi_device * dev)
+ {
+@@ -154,7 +154,7 @@ static void das6402_setcounter(struct comedi_device * dev)
+ static irqreturn_t intr_handler(int irq, void *d PT_REGS_ARG)
+ {
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s = dev->subdevices;
++	struct comedi_subdevice *s = dev->subdevices;
+ 
+ 	if (!dev->attached || devpriv->das6402_ignoreirq) {
+ 		printk("das6402: BUG: spurious interrupt\n");
+@@ -195,7 +195,7 @@ static void das6402_ai_fifo_read(struct comedi_device * dev, short * data, int n
+ }
+ #endif
+ 
+-static void das6402_ai_fifo_dregs(struct comedi_device * dev, comedi_subdevice * s)
++static void das6402_ai_fifo_dregs(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	while (1) {
+ 		if (!(inb(dev->iobase + 8) & 0x01))
+@@ -204,7 +204,7 @@ static void das6402_ai_fifo_dregs(struct comedi_device * dev, comedi_subdevice *
+ 	}
+ }
+ 
+-static int das6402_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int das6402_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	/*
+ 	 *  This function should reset the board from whatever condition it
+@@ -226,7 +226,7 @@ static int das6402_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ #ifdef unused
+-static int das6402_ai_mode2(struct comedi_device * dev, comedi_subdevice * s,
++static int das6402_ai_mode2(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_trig * it)
+ {
+ 	devpriv->das6402_ignoreirq = 1;
+@@ -304,7 +304,7 @@ static int das6402_attach(struct comedi_device * dev, comedi_devconfig * it)
+ 	unsigned int irq;
+ 	unsigned long iobase;
+ 	int ret;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	dev->board_name = "das6402";
+ 
+diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
+index 73068309ae9c..7833e56b0124 100644
+--- a/drivers/staging/comedi/drivers/das800.c
++++ b/drivers/staging/comedi/drivers/das800.c
+@@ -244,7 +244,7 @@ typedef struct {
+ 
+ static int das800_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int das800_detach(struct comedi_device * dev);
+-static int das800_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static int das800_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ 
+ static comedi_driver driver_das800 = {
+       driver_name:"das800",
+@@ -259,14 +259,14 @@ static comedi_driver driver_das800 = {
+ static irqreturn_t das800_interrupt(int irq, void *d PT_REGS_ARG);
+ static void enable_das800(struct comedi_device * dev);
+ static void disable_das800(struct comedi_device * dev);
+-static int das800_ai_do_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int das800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int das800_ai_do_cmd(struct comedi_device * dev, comedi_subdevice * s);
+-static int das800_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int das800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
++static int das800_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das800_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
++static int das800_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das800_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
++static int das800_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ static int das800_probe(struct comedi_device * dev);
+ static int das800_set_frequency(struct comedi_device * dev);
+@@ -348,7 +348,7 @@ static irqreturn_t das800_interrupt(int irq, void *d PT_REGS_ARG)
+ 	short i;		/* loop index */
+ 	short dataPoint = 0;
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s = dev->read_subdev;	/* analog input subdevice */
++	struct comedi_subdevice *s = dev->read_subdev;	/* analog input subdevice */
+ 	comedi_async *async;
+ 	int status;
+ 	unsigned long irq_flags;
+@@ -443,7 +443,7 @@ static irqreturn_t das800_interrupt(int irq, void *d PT_REGS_ARG)
+ 
+ static int das800_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned long iobase = it->options[0];
+ 	unsigned int irq = it->options[1];
+ 	unsigned long irq_flags;
+@@ -551,7 +551,7 @@ static int das800_detach(struct comedi_device * dev)
+ 	return 0;
+ };
+ 
+-static int das800_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int das800_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	devpriv->forever = 0;
+ 	devpriv->count = 0;
+@@ -584,7 +584,7 @@ static void disable_das800(struct comedi_device * dev)
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags);
+ }
+ 
+-static int das800_ai_do_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int das800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -709,7 +709,7 @@ static int das800_ai_do_cmdtest(struct comedi_device * dev, comedi_subdevice * s
+ 	return 0;
+ }
+ 
+-static int das800_ai_do_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int das800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	int startChan, endChan, scan, gain;
+ 	int conv_bits;
+@@ -788,7 +788,7 @@ static int das800_ai_do_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int das800_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int das800_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+@@ -842,7 +842,7 @@ static int das800_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int das800_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
++static int das800_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bits;
+@@ -855,7 +855,7 @@ static int das800_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int das800_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
++static int das800_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int wbits;
+diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
+index 678eb970a034..d710dd652053 100644
+--- a/drivers/staging/comedi/drivers/dmm32at.c
++++ b/drivers/staging/comedi/drivers/dmm32at.c
+@@ -289,20 +289,20 @@ static comedi_driver driver_dmm32at = {
+ };
+ 
+ /* prototypes for driver functions below */
+-static int dmm32at_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int dmm32at_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dmm32at_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int dmm32at_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dmm32at_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int dmm32at_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dmm32at_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int dmm32at_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dmm32at_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int dmm32at_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dmm32at_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int dmm32at_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int dmm32at_ai_cmd(struct comedi_device * dev, comedi_subdevice * s);
+-static int dmm32at_ai_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static int dmm32at_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
++static int dmm32at_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int dmm32at_ns_to_timer(unsigned int *ns, int round);
+ static irqreturn_t dmm32at_isr(int irq, void *d PT_REGS_ARG);
+ void dmm32at_setaitimer(struct comedi_device * dev, unsigned int nansec);
+@@ -316,7 +316,7 @@ void dmm32at_setaitimer(struct comedi_device * dev, unsigned int nansec);
+ static int dmm32at_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int ret;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned char aihi, ailo, fifostat, aistat, intstat, airback;
+ 	unsigned long iobase;
+ 	unsigned int irq;
+@@ -497,7 +497,7 @@ static int dmm32at_detach(struct comedi_device * dev)
+  * mode.
+  */
+ 
+-static int dmm32at_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int dmm32at_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i;
+@@ -568,7 +568,7 @@ static int dmm32at_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int dmm32at_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int dmm32at_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -752,7 +752,7 @@ static int dmm32at_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int dmm32at_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int dmm32at_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	int i, range;
+@@ -822,7 +822,7 @@ static int dmm32at_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ 
+ }
+ 
+-static int dmm32at_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int dmm32at_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	devpriv->ai_scans_left = 1;
+ 	return 0;
+@@ -844,7 +844,7 @@ static irqreturn_t dmm32at_isr(int irq, void *d PT_REGS_ARG)
+ 	intstat = dmm_inb(dev, DMM32AT_INTCLOCK);
+ 
+ 	if (intstat & DMM32AT_ADINT) {
+-		comedi_subdevice *s = dev->read_subdev;
++		struct comedi_subdevice *s = dev->read_subdev;
+ 		comedi_cmd *cmd = &s->async->cmd;
+ 
+ 		for (i = 0; i < cmd->chanlist_len; i++) {
+@@ -893,7 +893,7 @@ static int dmm32at_ns_to_timer(unsigned int *ns, int round)
+ 	return *ns;
+ }
+ 
+-static int dmm32at_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int dmm32at_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -936,7 +936,7 @@ static int dmm32at_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+-static int dmm32at_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int dmm32at_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -953,7 +953,7 @@ static int dmm32at_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+  * useful to applications if you implement the insn_bits interface.
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+-static int dmm32at_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int dmm32at_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned char diobits;
+@@ -1006,7 +1006,7 @@ static int dmm32at_dio_insn_bits(struct comedi_device * dev, comedi_subdevice *
+ 	return 2;
+ }
+ 
+-static int dmm32at_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int dmm32at_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned char chanbit;
+diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c
+index 364102436d6e..1f6e4bfa8cd2 100644
+--- a/drivers/staging/comedi/drivers/dt2801.c
++++ b/drivers/staging/comedi/drivers/dt2801.c
+@@ -224,15 +224,15 @@ typedef struct {
+ } dt2801_private;
+ #define devpriv ((dt2801_private *)dev->private)
+ 
+-static int dt2801_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int dt2801_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dt2801_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int dt2801_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dt2801_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
++static int dt2801_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dt2801_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int dt2801_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dt2801_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int dt2801_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ /* These are the low-level routines:
+@@ -480,7 +480,7 @@ static const comedi_lrange *ai_range_lkup(int type, int opt)
+ */
+ static int dt2801_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+ 	int board_code, type;
+ 	int ret = 0;
+@@ -605,7 +605,7 @@ static int dt2801_error(struct comedi_device * dev, int stat)
+ 	return -EIO;
+ }
+ 
+-static int dt2801_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int dt2801_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int d;
+@@ -627,7 +627,7 @@ static int dt2801_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int dt2801_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int dt2801_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->ao_readback[CR_CHAN(insn->chanspec)];
+@@ -635,7 +635,7 @@ static int dt2801_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int dt2801_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
++static int dt2801_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	dt2801_writecmd(dev, DT_C_WRITE_DAIM);
+@@ -647,7 +647,7 @@ static int dt2801_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s
+ 	return 1;
+ }
+ 
+-static int dt2801_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int dt2801_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int which = 0;
+@@ -671,7 +671,7 @@ static int dt2801_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s
+ 	return 2;
+ }
+ 
+-static int dt2801_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int dt2801_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int which = 0;
+diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c
+index 76c084ca081b..ca2e83f3630f 100644
+--- a/drivers/staging/comedi/drivers/dt2811.c
++++ b/drivers/staging/comedi/drivers/dt2811.c
+@@ -226,15 +226,15 @@ static comedi_driver driver_dt2811 = {
+ 
+ COMEDI_INITCLEANUP(driver_dt2811);
+ 
+-static int dt2811_ai_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int dt2811_ai_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dt2811_ao_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int dt2811_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dt2811_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int dt2811_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dt2811_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int dt2811_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dt2811_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int dt2811_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ enum { card_2811_pgh, card_2811_pgl };
+@@ -314,7 +314,7 @@ static int dt2811_attach(struct comedi_device * dev, comedi_devconfig * it)
+ 	//unsigned long irqs;
+ 	//long flags;
+ 	int ret;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+ 
+ 	iobase = it->options[0];
+@@ -490,7 +490,7 @@ static int dt2811_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int dt2811_ai_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int dt2811_ai_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -541,7 +541,7 @@ int dt2811_adtrig(kdev_t minor, comedi_adtrig * adtrig)
+ }
+ #endif
+ 
+-static int dt2811_ao_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int dt2811_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -559,7 +559,7 @@ static int dt2811_ao_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int dt2811_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int dt2811_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -574,7 +574,7 @@ static int dt2811_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int dt2811_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int dt2811_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -585,7 +585,7 @@ static int dt2811_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int dt2811_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int dt2811_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c
+index 40430b5df69a..f886d1c376ed 100644
+--- a/drivers/staging/comedi/drivers/dt2814.c
++++ b/drivers/staging/comedi/drivers/dt2814.c
+@@ -81,7 +81,7 @@ typedef struct {
+ #define DT2814_TIMEOUT 10
+ #define DT2814_MAX_SPEED 100000	/* Arbitrary 10 khz limit */
+ 
+-static int dt2814_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int dt2814_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i, hi, lo;
+@@ -132,7 +132,7 @@ static int dt2814_ns_to_timer(unsigned int *ns, unsigned int flags)
+ 	return i;
+ }
+ 
+-static int dt2814_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int dt2814_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -224,7 +224,7 @@ static int dt2814_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int dt2814_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int dt2814_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	int chan;
+@@ -247,7 +247,7 @@ static int dt2814_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int i, irq;
+ 	int ret;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+ 
+ 	iobase = it->options[0];
+@@ -345,7 +345,7 @@ static irqreturn_t dt2814_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	int lo, hi;
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int data;
+ 
+ 	if (!dev->attached) {
+diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c
+index 892fe38d55e6..75b89430be8c 100644
+--- a/drivers/staging/comedi/drivers/dt2815.c
++++ b/drivers/staging/comedi/drivers/dt2815.c
+@@ -106,7 +106,7 @@ static int dt2815_wait_for_status(struct comedi_device * dev, int status)
+ 	return status;
+ }
+ 
+-static int dt2815_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int dt2815_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -119,7 +119,7 @@ static int dt2815_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int dt2815_ao_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int dt2815_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -179,7 +179,7 @@ static int dt2815_ao_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 
+ static int dt2815_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int i;
+ 	const comedi_lrange *current_range_type, *voltage_range_type;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c
+index 41aa03d40cdd..5e012856a58e 100644
+--- a/drivers/staging/comedi/drivers/dt2817.c
++++ b/drivers/staging/comedi/drivers/dt2817.c
+@@ -58,7 +58,7 @@ static comedi_driver driver_dt2817 = {
+ 
+ COMEDI_INITCLEANUP(driver_dt2817);
+ 
+-static int dt2817_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int dt2817_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int mask;
+@@ -96,7 +96,7 @@ static int dt2817_dio_insn_config(struct comedi_device * dev, comedi_subdevice *
+ 	return 1;
+ }
+ 
+-static int dt2817_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int dt2817_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int changed;
+@@ -134,7 +134,7 @@ static int dt2817_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s
+ static int dt2817_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int ret;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+ 
+ 	iobase = it->options[0];
+diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
+index 2c4557faac4a..5da648d2399b 100644
+--- a/drivers/staging/comedi/drivers/dt282x.c
++++ b/drivers/staging/comedi/drivers/dt282x.c
+@@ -411,8 +411,8 @@ COMEDI_INITCLEANUP(driver_dt282x);
+ static void free_resources(struct comedi_device * dev);
+ static int prep_ai_dma(struct comedi_device * dev, int chan, int size);
+ static int prep_ao_dma(struct comedi_device * dev, int chan, int size);
+-static int dt282x_ai_cancel(struct comedi_device * dev, comedi_subdevice * s);
+-static int dt282x_ao_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static int dt282x_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
++static int dt282x_ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int dt282x_ns_to_timer(int *nanosec, int round_mode);
+ static void dt282x_disable_dma(struct comedi_device * dev);
+ 
+@@ -445,7 +445,7 @@ static void dt282x_ao_dma_interrupt(struct comedi_device * dev)
+ 	void *ptr;
+ 	int size;
+ 	int i;
+-	comedi_subdevice *s = dev->subdevices + 1;
++	struct comedi_subdevice *s = dev->subdevices + 1;
+ 
+ 	update_supcsr(DT2821_CLRDMADNE);
+ 
+@@ -478,7 +478,7 @@ static void dt282x_ai_dma_interrupt(struct comedi_device * dev)
+ 	int size;
+ 	int i;
+ 	int ret;
+-	comedi_subdevice *s = dev->subdevices;
++	struct comedi_subdevice *s = dev->subdevices;
+ 
+ 	update_supcsr(DT2821_CLRDMADNE);
+ 
+@@ -580,8 +580,8 @@ static int prep_ao_dma(struct comedi_device * dev, int dma_index, int n)
+ static irqreturn_t dt282x_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s;
+-	comedi_subdevice *s_ao;
++	struct comedi_subdevice *s;
++	struct comedi_subdevice *s_ao;
+ 	unsigned int supcsr, adcsr, dacsr;
+ 	int handled = 0;
+ 
+@@ -674,7 +674,7 @@ static void dt282x_load_changain(struct comedi_device * dev, int n,
+  *      - preload multiplexer
+  *      - trigger conversion and wait for it to finish
+  */
+-static int dt282x_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int dt282x_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -706,7 +706,7 @@ static int dt282x_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int dt282x_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int dt282x_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -818,7 +818,7 @@ static int dt282x_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int dt282x_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int dt282x_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	int timer;
+@@ -887,7 +887,7 @@ static void dt282x_disable_dma(struct comedi_device * dev)
+ 	}
+ }
+ 
+-static int dt282x_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int dt282x_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	dt282x_disable_dma(dev);
+ 
+@@ -937,7 +937,7 @@ static int dt282x_ns_to_timer(int *nanosec, int round_mode)
+  *      offset binary if necessary, loads the data into the DAC
+  *      data register, and performs the conversion.
+  */
+-static int dt282x_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int dt282x_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->ao[CR_CHAN(insn->chanspec)];
+@@ -945,7 +945,7 @@ static int dt282x_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int dt282x_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
++static int dt282x_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	short d;
+@@ -978,7 +978,7 @@ static int dt282x_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s
+ 	return 1;
+ }
+ 
+-static int dt282x_ao_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int dt282x_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -1069,7 +1069,7 @@ static int dt282x_ao_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 
+ }
+ 
+-static int dt282x_ao_inttrig(struct comedi_device * dev, comedi_subdevice * s,
++static int dt282x_ao_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int x)
+ {
+ 	int size;
+@@ -1099,7 +1099,7 @@ static int dt282x_ao_inttrig(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int dt282x_ao_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int dt282x_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	int timer;
+ 	comedi_cmd *cmd = &s->async->cmd;
+@@ -1132,7 +1132,7 @@ static int dt282x_ao_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int dt282x_ao_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int dt282x_ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	dt282x_disable_dma(dev);
+ 
+@@ -1145,7 +1145,7 @@ static int dt282x_ao_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int dt282x_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int dt282x_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+@@ -1159,7 +1159,7 @@ static int dt282x_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s
+ 	return 2;
+ }
+ 
+-static int dt282x_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int dt282x_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int mask;
+@@ -1244,7 +1244,7 @@ static int dt282x_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int i, irq;
+ 	int ret;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+ 
+ 	dev->board_name = this_board->name;
+diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
+index 0b015a0d8203..add9b11fa157 100644
+--- a/drivers/staging/comedi/drivers/dt3000.c
++++ b/drivers/staging/comedi/drivers/dt3000.c
+@@ -282,10 +282,10 @@ static comedi_driver driver_dt3000 = {
+ 
+ COMEDI_PCI_INITCLEANUP(driver_dt3000, dt3k_pci_table);
+ 
+-static void dt3k_ai_empty_fifo(struct comedi_device * dev, comedi_subdevice * s);
++static void dt3k_ai_empty_fifo(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *arg,
+ 	unsigned int round_mode);
+-static int dt3k_ai_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static int dt3k_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ #ifdef DEBUG
+ static void debug_intr_flags(unsigned int flags);
+ #endif
+@@ -346,7 +346,7 @@ static int debug_n_ints = 0;
+ static irqreturn_t dt3k_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned int status;
+ 
+ 	if (!dev->attached) {
+@@ -396,7 +396,7 @@ static void debug_intr_flags(unsigned int flags)
+ }
+ #endif
+ 
+-static void dt3k_ai_empty_fifo(struct comedi_device * dev, comedi_subdevice * s)
++static void dt3k_ai_empty_fifo(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	int front;
+ 	int rear;
+@@ -425,7 +425,7 @@ static void dt3k_ai_empty_fifo(struct comedi_device * dev, comedi_subdevice * s)
+ 	writew(rear, devpriv->io_addr + DPR_AD_Buf_Rear);
+ }
+ 
+-static int dt3k_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int dt3k_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -587,7 +587,7 @@ static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
+ 	return (prescale << 16) | (divider);
+ }
+ 
+-static int dt3k_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int dt3k_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	int i;
+@@ -655,7 +655,7 @@ static int dt3k_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int dt3k_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int dt3k_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	int ret;
+ 
+@@ -667,7 +667,7 @@ static int dt3k_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int dt3k_ai_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int dt3k_ai_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -685,7 +685,7 @@ static int dt3k_ai_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int dt3k_ao_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int dt3k_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -700,7 +700,7 @@ static int dt3k_ao_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int dt3k_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int dt3k_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -729,7 +729,7 @@ static void dt3k_dio_config(struct comedi_device * dev, int bits)
+ 	dt3k_send_cmd(dev, CMD_CONFIG);
+ }
+ 
+-static int dt3k_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int dt3k_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int mask;
+@@ -760,7 +760,7 @@ static int dt3k_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s
+ 	return insn->n;
+ }
+ 
+-static int dt3k_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int dt3k_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -776,7 +776,7 @@ static int dt3k_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int dt3k_mem_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int dt3k_mem_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int addr = CR_CHAN(insn->chanspec);
+@@ -799,7 +799,7 @@ static int dt_pci_probe(struct comedi_device * dev, int bus, int slot);
+ 
+ static int dt3000_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int bus, slot;
+ 	int ret = 0;
+ 
+diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c
+index 068ef2f79e5a..3dd357336fa7 100644
+--- a/drivers/staging/comedi/drivers/dt9812.c
++++ b/drivers/staging/comedi/drivers/dt9812.c
+@@ -897,7 +897,7 @@ static void dt9812_comedi_open(struct comedi_device *dev)
+ 	down(&devpriv->slot->mutex);
+ 	if (devpriv->slot->usb) {
+ 		/* We have an attached device, fill in current range info */
+-		comedi_subdevice *s;
++		struct comedi_subdevice *s;
+ 
+ 		s = &dev->subdevices[0];
+ 		s->n_chan = 8;
+@@ -940,7 +940,7 @@ static void dt9812_comedi_open(struct comedi_device *dev)
+ 	up(&devpriv->slot->mutex);
+ }
+ 
+-static int dt9812_di_rinsn(struct comedi_device *dev, comedi_subdevice *s,
++static int dt9812_di_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			   comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+@@ -952,7 +952,7 @@ static int dt9812_di_rinsn(struct comedi_device *dev, comedi_subdevice *s,
+ 	return n;
+ }
+ 
+-static int dt9812_do_winsn(struct comedi_device *dev, comedi_subdevice *s,
++static int dt9812_do_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			   comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+@@ -970,7 +970,7 @@ static int dt9812_do_winsn(struct comedi_device *dev, comedi_subdevice *s,
+ 	return n;
+ }
+ 
+-static int dt9812_ai_rinsn(struct comedi_device *dev, comedi_subdevice *s,
++static int dt9812_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			   comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+@@ -985,7 +985,7 @@ static int dt9812_ai_rinsn(struct comedi_device *dev, comedi_subdevice *s,
+ 	return n;
+ }
+ 
+-static int dt9812_ao_rinsn(struct comedi_device *dev, comedi_subdevice *s,
++static int dt9812_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			   comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+@@ -999,7 +999,7 @@ static int dt9812_ao_rinsn(struct comedi_device *dev, comedi_subdevice *s,
+ 	return n;
+ }
+ 
+-static int dt9812_ao_winsn(struct comedi_device *dev, comedi_subdevice *s,
++static int dt9812_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			   comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+@@ -1012,7 +1012,7 @@ static int dt9812_ao_winsn(struct comedi_device *dev, comedi_subdevice *s,
+ static int dt9812_attach(struct comedi_device *dev, comedi_devconfig *it)
+ {
+ 	int i;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	dev->board_name = "dt9812";
+ 
+diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c
+index 20bd47318439..54f2c2a6c51c 100644
+--- a/drivers/staging/comedi/drivers/fl512.c
++++ b/drivers/staging/comedi/drivers/fl512.c
+@@ -53,17 +53,17 @@ static comedi_driver driver_fl512 = {
+ COMEDI_INITCLEANUP(driver_fl512);
+ 
+ static int fl512_ai_insn(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ static int fl512_ao_insn(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ static int fl512_ao_insn_readback(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+ /*
+  * fl512_ai_insn : this is the analog input function
+  */
+ static int fl512_ai_insn(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	unsigned int lo_byte, hi_byte;
+@@ -88,7 +88,7 @@ static int fl512_ai_insn(struct comedi_device * dev,
+  * fl512_ao_insn : used to write to a DA port n times
+  */
+ static int fl512_ao_insn(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);	/* get chan to write */
+@@ -109,7 +109,7 @@ static int fl512_ao_insn(struct comedi_device * dev,
+  * DA port
+  */
+ static int fl512_ao_insn_readback(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -127,7 +127,7 @@ static int fl512_ao_insn_readback(struct comedi_device * dev,
+ static int fl512_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	unsigned long iobase;
+-	comedi_subdevice *s;	/* pointer to the subdevice:
++	struct comedi_subdevice *s;	/* pointer to the subdevice:
+ 				   Analog in, Analog out, ( not made ->and Digital IO) */
+ 
+ 	iobase = it->options[0];
+diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
+index 5048255b4a3f..fb91fa1da839 100644
+--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
++++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
+@@ -55,10 +55,10 @@ support could be added to this driver.
+ static int hpdi_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int hpdi_detach(struct comedi_device * dev);
+ void abort_dma(struct comedi_device * dev, unsigned int channel);
+-static int hpdi_cmd(struct comedi_device * dev, comedi_subdevice * s);
+-static int hpdi_cmd_test(struct comedi_device * dev, comedi_subdevice * s,
++static int hpdi_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
++static int hpdi_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int hpdi_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static int hpdi_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static irqreturn_t handle_interrupt(int irq, void *d PT_REGS_ARG);
+ static int dio_config_block_size(struct comedi_device * dev, unsigned int * data);
+ 
+@@ -336,7 +336,7 @@ static comedi_driver driver_hpdi = {
+ 
+ COMEDI_PCI_INITCLEANUP(driver_hpdi, hpdi_pci_table);
+ 
+-static int dio_config_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int dio_config_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+@@ -437,7 +437,7 @@ static void init_plx9080(struct comedi_device * dev)
+  */
+ static int setup_subdevices(struct comedi_device * dev)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	if (alloc_subdevices(dev, 1) < 0)
+ 		return -ENOMEM;
+@@ -718,7 +718,7 @@ static int dio_config_block_size(struct comedi_device * dev, unsigned int * data
+ 	return 2;
+ }
+ 
+-static int di_cmd_test(struct comedi_device * dev, comedi_subdevice * s,
++static int di_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -818,7 +818,7 @@ static int di_cmd_test(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int hpdi_cmd_test(struct comedi_device * dev, comedi_subdevice * s,
++static int hpdi_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	if (priv(dev)->dio_config_output) {
+@@ -834,7 +834,7 @@ static inline void hpdi_writel(struct comedi_device * dev, uint32_t bits,
+ 		priv(dev)->hpdi_iobase + offset);
+ }
+ 
+-static int di_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int di_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	uint32_t bits;
+ 	unsigned long flags;
+@@ -887,7 +887,7 @@ static int di_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int hpdi_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int hpdi_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	if (priv(dev)->dio_config_output) {
+ 		return -EINVAL;
+@@ -944,7 +944,7 @@ static void drain_dma_buffers(struct comedi_device * dev, unsigned int channel)
+ static irqreturn_t handle_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s = dev->read_subdev;
++	struct comedi_subdevice *s = dev->read_subdev;
+ 	comedi_async *async = s->async;
+ 	uint32_t hpdi_intr_status, hpdi_board_status;
+ 	uint32_t plx_status;
+@@ -1044,7 +1044,7 @@ void abort_dma(struct comedi_device * dev, unsigned int channel)
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ }
+ 
+-static int hpdi_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int hpdi_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	hpdi_writel(dev, 0, BOARD_CONTROL_REG);
+ 
+diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
+index 04152148a106..ee17c6ce838c 100644
+--- a/drivers/staging/comedi/drivers/icp_multi.c
++++ b/drivers/staging/comedi/drivers/icp_multi.c
+@@ -214,10 +214,10 @@ struct icp_multi_private {
+ */
+ 
+ #if 0
+-static int check_channel_list(struct comedi_device *dev, comedi_subdevice *s,
++static int check_channel_list(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int *chanlist, unsigned int n_chan);
+ #endif
+-static void setup_channel_list(struct comedi_device *dev, comedi_subdevice *s,
++static void setup_channel_list(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int *chanlist, unsigned int n_chan);
+ static int icp_multi_reset(struct comedi_device *dev);
+ 
+@@ -237,7 +237,7 @@ static int icp_multi_reset(struct comedi_device *dev);
+ 
+ 	Parameters:
+ 		struct comedi_device *dev	Pointer to current device structure
+-		comedi_subdevice *s	Pointer to current subdevice structure
++		struct comedi_subdevice *s	Pointer to current subdevice structure
+ 		comedi_insn *insn	Pointer to current comedi instruction
+ 		unsigned int *data		Pointer to analogue input data
+ 
+@@ -245,7 +245,7 @@ static int icp_multi_reset(struct comedi_device *dev);
+ 
+ ==============================================================================
+ */
+-static int icp_multi_insn_read_ai(struct comedi_device *dev, comedi_subdevice *s,
++static int icp_multi_insn_read_ai(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, timeout;
+@@ -356,7 +356,7 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev, comedi_subdevice *s
+ 
+ 	Parameters:
+ 		struct comedi_device *dev	Pointer to current device structure
+-		comedi_subdevice *s	Pointer to current subdevice structure
++		struct comedi_subdevice *s	Pointer to current subdevice structure
+ 		comedi_insn *insn	Pointer to current comedi instruction
+ 		unsigned int *data		Pointer to analogue output data
+ 
+@@ -364,7 +364,7 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev, comedi_subdevice *s
+ 
+ ==============================================================================
+ */
+-static int icp_multi_insn_write_ao(struct comedi_device *dev, comedi_subdevice *s,
++static int icp_multi_insn_write_ao(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, chan, range, timeout;
+@@ -464,7 +464,7 @@ static int icp_multi_insn_write_ao(struct comedi_device *dev, comedi_subdevice *
+ 
+ 	Parameters:
+ 		struct comedi_device *dev	Pointer to current device structure
+-		comedi_subdevice *s	Pointer to current subdevice structure
++		struct comedi_subdevice *s	Pointer to current subdevice structure
+ 		comedi_insn *insn	Pointer to current comedi instruction
+ 		unsigned int *data		Pointer to analogue output data
+ 
+@@ -472,7 +472,7 @@ static int icp_multi_insn_write_ao(struct comedi_device *dev, comedi_subdevice *
+ 
+ ==============================================================================
+ */
+-static int icp_multi_insn_read_ao(struct comedi_device *dev, comedi_subdevice *s,
++static int icp_multi_insn_read_ao(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, chan;
+@@ -497,7 +497,7 @@ static int icp_multi_insn_read_ao(struct comedi_device *dev, comedi_subdevice *s
+ 
+ 	Parameters:
+ 		struct comedi_device *dev	Pointer to current device structure
+-		comedi_subdevice *s	Pointer to current subdevice structure
++		struct comedi_subdevice *s	Pointer to current subdevice structure
+ 		comedi_insn *insn	Pointer to current comedi instruction
+ 		unsigned int *data		Pointer to analogue output data
+ 
+@@ -505,7 +505,7 @@ static int icp_multi_insn_read_ao(struct comedi_device *dev, comedi_subdevice *s
+ 
+ ==============================================================================
+ */
+-static int icp_multi_insn_bits_di(struct comedi_device *dev, comedi_subdevice *s,
++static int icp_multi_insn_bits_di(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 	data[1] = readw(devpriv->io_addr + ICP_MULTI_DI);
+@@ -523,7 +523,7 @@ static int icp_multi_insn_bits_di(struct comedi_device *dev, comedi_subdevice *s
+ 
+ 	Parameters:
+ 		struct comedi_device *dev	Pointer to current device structure
+-		comedi_subdevice *s	Pointer to current subdevice structure
++		struct comedi_subdevice *s	Pointer to current subdevice structure
+ 		comedi_insn *insn	Pointer to current comedi instruction
+ 		unsigned int *data		Pointer to analogue output data
+ 
+@@ -531,7 +531,7 @@ static int icp_multi_insn_bits_di(struct comedi_device *dev, comedi_subdevice *s
+ 
+ ==============================================================================
+ */
+-static int icp_multi_insn_bits_do(struct comedi_device *dev, comedi_subdevice *s,
++static int icp_multi_insn_bits_do(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ #ifdef ICP_MULTI_EXTDEBUG
+@@ -565,7 +565,7 @@ static int icp_multi_insn_bits_do(struct comedi_device *dev, comedi_subdevice *s
+ 
+ 	Parameters:
+ 		struct comedi_device *dev	Pointer to current device structure
+-		comedi_subdevice *s	Pointer to current subdevice structure
++		struct comedi_subdevice *s	Pointer to current subdevice structure
+ 		comedi_insn *insn	Pointer to current comedi instruction
+ 		unsigned int *data		Pointer to counter data
+ 
+@@ -573,7 +573,7 @@ static int icp_multi_insn_bits_do(struct comedi_device *dev, comedi_subdevice *s
+ 
+ ==============================================================================
+ */
+-static int icp_multi_insn_read_ctr(struct comedi_device *dev, comedi_subdevice *s,
++static int icp_multi_insn_read_ctr(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 	return 0;
+@@ -589,7 +589,7 @@ static int icp_multi_insn_read_ctr(struct comedi_device *dev, comedi_subdevice *
+ 
+ 	Parameters:
+ 		struct comedi_device *dev	Pointer to current device structure
+-		comedi_subdevice *s	Pointer to current subdevice structure
++		struct comedi_subdevice *s	Pointer to current subdevice structure
+ 		comedi_insn *insn	Pointer to current comedi instruction
+ 		unsigned int *data		Pointer to counter data
+ 
+@@ -597,7 +597,7 @@ static int icp_multi_insn_read_ctr(struct comedi_device *dev, comedi_subdevice *
+ 
+ ==============================================================================
+ */
+-static int icp_multi_insn_write_ctr(struct comedi_device *dev, comedi_subdevice *s,
++static int icp_multi_insn_write_ctr(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 	return 0;
+@@ -680,7 +680,7 @@ static irqreturn_t interrupt_service_icp_multi(int irq, void *d PT_REGS_ARG)
+ 
+ 	Parameters:
+ 		struct comedi_device *dev	Pointer to current sevice structure
+-		comedi_subdevice *s	Pointer to current subdevice structure
++		struct comedi_subdevice *s	Pointer to current subdevice structure
+ 		unsigned int *chanlist	Pointer to packed channel list
+ 		unsigned int n_chan	Number of channels to scan
+ 
+@@ -689,7 +689,7 @@ static irqreturn_t interrupt_service_icp_multi(int irq, void *d PT_REGS_ARG)
+ 
+ ==============================================================================
+ */
+-static int check_channel_list(struct comedi_device *dev, comedi_subdevice *s,
++static int check_channel_list(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int *chanlist, unsigned int n_chan)
+ {
+ 	unsigned int i;
+@@ -735,7 +735,7 @@ static int check_channel_list(struct comedi_device *dev, comedi_subdevice *s,
+ 
+ 	Parameters:
+ 		struct comedi_device *dev	Pointer to current sevice structure
+-		comedi_subdevice *s	Pointer to current subdevice structure
++		struct comedi_subdevice *s	Pointer to current subdevice structure
+ 		unsigned int *chanlist	Pointer to packed channel list
+ 		unsigned int n_chan	Number of channels to scan
+ 
+@@ -743,7 +743,7 @@ static int check_channel_list(struct comedi_device *dev, comedi_subdevice *s,
+ 
+ ==============================================================================
+ */
+-static void setup_channel_list(struct comedi_device *dev, comedi_subdevice *s,
++static void setup_channel_list(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int *chanlist, unsigned int n_chan)
+ {
+ 	unsigned int i, range, chanprog;
+@@ -872,7 +872,7 @@ static int icp_multi_reset(struct comedi_device *dev)
+ */
+ static int icp_multi_attach(struct comedi_device *dev, comedi_devconfig *it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int ret, subdev, n_subdevices;
+ 	unsigned int irq;
+ 	struct pcilst_struct *card = NULL;
+diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c
+index 3e7ca4e6b8af..df21bf255d02 100644
+--- a/drivers/staging/comedi/drivers/ii_pci20kc.c
++++ b/drivers/staging/comedi/drivers/ii_pci20kc.c
+@@ -166,11 +166,11 @@ static comedi_driver driver_pci20xxx = {
+       detach:pci20xxx_detach,
+ };
+ 
+-static int pci20006_init(struct comedi_device * dev, comedi_subdevice * s,
++static int pci20006_init(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	int opt0, int opt1);
+-static int pci20341_init(struct comedi_device * dev, comedi_subdevice * s,
++static int pci20341_init(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	int opt0, int opt1);
+-static int pci20xxx_dio_init(struct comedi_device * dev, comedi_subdevice * s);
++static int pci20xxx_dio_init(struct comedi_device * dev, struct comedi_subdevice * s);
+ 
+ /*
+   options[0]	Board base address
+@@ -204,7 +204,7 @@ static int pci20xxx_attach(struct comedi_device * dev, comedi_devconfig * it)
+ 	unsigned char i;
+ 	int ret;
+ 	int id;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	pci20xxx_subdev_private *sdp;
+ 
+ 	if ((ret = alloc_subdevices(dev, 1 + PCI20000_MODULES)) < 0)
+@@ -270,9 +270,9 @@ static int pci20xxx_detach(struct comedi_device * dev)
+ 
+ /* pci20006m */
+ 
+-static int pci20006_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int pci20006_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int pci20006_insn_write(struct comedi_device * dev, comedi_subdevice * s,
++static int pci20006_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ static const comedi_lrange *pci20006_range_list[] = {
+@@ -281,7 +281,7 @@ static const comedi_lrange *pci20006_range_list[] = {
+ 	&range_bipolar5,
+ };
+ 
+-static int pci20006_init(struct comedi_device * dev, comedi_subdevice * s,
++static int pci20006_init(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	int opt0, int opt1)
+ {
+ 	pci20xxx_subdev_private *sdp = s->private;
+@@ -306,7 +306,7 @@ static int pci20006_init(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int pci20006_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int pci20006_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	pci20xxx_subdev_private *sdp = s->private;
+@@ -316,7 +316,7 @@ static int pci20006_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int pci20006_insn_write(struct comedi_device * dev, comedi_subdevice * s,
++static int pci20006_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	pci20xxx_subdev_private *sdp = s->private;
+@@ -349,7 +349,7 @@ static int pci20006_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+ 
+ /* PCI20341M */
+ 
+-static int pci20341_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int pci20341_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ static const int pci20341_timebase[] = { 0x00, 0x00, 0x00, 0x04 };
+@@ -366,7 +366,7 @@ static const comedi_lrange *const pci20341_ranges[] = {
+ 	&range_bipolar0_025,
+ };
+ 
+-static int pci20341_init(struct comedi_device * dev, comedi_subdevice * s,
++static int pci20341_init(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	int opt0, int opt1)
+ {
+ 	pci20xxx_subdev_private *sdp = s->private;
+@@ -397,7 +397,7 @@ static int pci20341_init(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int pci20341_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int pci20341_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	pci20xxx_subdev_private *sdp = s->private;
+@@ -443,14 +443,14 @@ static int pci20341_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 
+ /* native DIO */
+ 
+-static void pci20xxx_dio_config(struct comedi_device * dev, comedi_subdevice * s);
+-static int pci20xxx_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static void pci20xxx_dio_config(struct comedi_device * dev, struct comedi_subdevice * s);
++static int pci20xxx_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int pci20xxx_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int pci20xxx_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ /* initialize pci20xxx_private */
+-static int pci20xxx_dio_init(struct comedi_device * dev, comedi_subdevice * s)
++static int pci20xxx_dio_init(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 
+ 	s->type = COMEDI_SUBD_DIO;
+@@ -469,7 +469,7 @@ static int pci20xxx_dio_init(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int pci20xxx_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int pci20xxx_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int mask, bits;
+@@ -494,7 +494,7 @@ static int pci20xxx_dio_insn_config(struct comedi_device * dev, comedi_subdevice
+ 	return 1;
+ }
+ 
+-static int pci20xxx_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int pci20xxx_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int mask = data[0];
+@@ -524,7 +524,7 @@ static int pci20xxx_dio_insn_bits(struct comedi_device * dev, comedi_subdevice *
+ 	return 2;
+ }
+ 
+-static void pci20xxx_dio_config(struct comedi_device * dev, comedi_subdevice * s)
++static void pci20xxx_dio_config(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned char control_01;
+ 	unsigned char control_23;
+@@ -580,7 +580,7 @@ static void pci20xxx_dio_config(struct comedi_device * dev, comedi_subdevice * s
+ }
+ 
+ #if 0
+-static void pci20xxx_do(struct comedi_device * dev, comedi_subdevice * s)
++static void pci20xxx_do(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	/* XXX if the channel is configured for input, does this
+ 	   do bad things? */
+@@ -593,7 +593,7 @@ static void pci20xxx_do(struct comedi_device * dev, comedi_subdevice * s)
+ 	writeb((s->state >> 24) & 0xff, devpriv->ioaddr + PCI20000_DIO_3);
+ }
+ 
+-static unsigned int pci20xxx_di(struct comedi_device * dev, comedi_subdevice * s)
++static unsigned int pci20xxx_di(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	/* XXX same note as above */
+ 	unsigned int bits;
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
+index 0a077486315c..44b5c4ff3648 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -269,7 +269,7 @@ static six_axis_t get_max_full_scales(volatile jr3_channel_t * channel)
+ 	return result;
+ }
+ 
+-static int jr3_pci_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int jr3_pci_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int result;
+@@ -523,7 +523,7 @@ static int jr3_download_firmware(struct comedi_device * dev, const u8 * data,
+ 	return result;
+ }
+ 
+-static poll_delay_t jr3_pci_poll_subdevice(comedi_subdevice * s)
++static poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice * s)
+ {
+ 	poll_delay_t result = poll_delay_min_max(1000, 2000);
+ 	jr3_pci_subdev_private *p = s->private;
+diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c
+index d9b8a83343d9..08f09ac19d70 100644
+--- a/drivers/staging/comedi/drivers/ke_counter.c
++++ b/drivers/staging/comedi/drivers/ke_counter.c
+@@ -100,7 +100,7 @@ COMEDI_PCI_INITCLEANUP(cnt_driver, cnt_pci_table);
+ /* This should be used only for resetting the counters; maybe it is better
+    to make a special command 'reset'. */
+ static int cnt_winsn(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+@@ -120,7 +120,7 @@ static int cnt_winsn(struct comedi_device * dev,
+ /*-- counter read -----------------------------------------------------------*/
+ 
+ static int cnt_rinsn(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned char a0, a1, a2, a3, a4;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -146,7 +146,7 @@ static int cnt_rinsn(struct comedi_device * dev,
+ 
+ static int cnt_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *subdevice;
++	struct comedi_subdevice *subdevice;
+ 	struct pci_dev *pci_device;
+ 	cnt_board_struct *board;
+ 	unsigned long io_base;
+diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
+index a03661ce34b5..17de86a3988c 100644
+--- a/drivers/staging/comedi/drivers/me4000.c
++++ b/drivers/staging/comedi/drivers/me4000.c
+@@ -141,10 +141,10 @@ static int xilinx_download(struct comedi_device *dev);
+ static int reset_board(struct comedi_device *dev);
+ 
+ static int me4000_dio_insn_bits(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
++	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
+ 
+ static int me4000_dio_insn_config(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
++	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
+ 
+ static int cnt_reset(struct comedi_device *dev, unsigned int channel);
+ 
+@@ -152,49 +152,49 @@ static int cnt_config(struct comedi_device *dev,
+ 	unsigned int channel, unsigned int mode);
+ 
+ static int me4000_cnt_insn_config(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
++	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
+ 
+ static int me4000_cnt_insn_write(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
++	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
+ 
+ static int me4000_cnt_insn_read(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
++	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
+ 
+ static int me4000_ai_insn_read(struct comedi_device *dev,
+-	comedi_subdevice *subdevice, comedi_insn *insn, unsigned int *data);
++	struct comedi_subdevice *subdevice, comedi_insn *insn, unsigned int *data);
+ 
+-static int me4000_ai_cancel(struct comedi_device *dev, comedi_subdevice *s);
++static int me4000_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
+ 
+ static int ai_check_chanlist(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_cmd *cmd);
++	struct comedi_subdevice *s, comedi_cmd *cmd);
+ 
+ static int ai_round_cmd_args(struct comedi_device *dev,
+-	comedi_subdevice *s,
++	struct comedi_subdevice *s,
+ 	comedi_cmd *cmd,
+ 	unsigned int *init_ticks,
+ 	unsigned int *scan_ticks, unsigned int *chan_ticks);
+ 
+ static int ai_prepare(struct comedi_device *dev,
+-	comedi_subdevice *s,
++	struct comedi_subdevice *s,
+ 	comedi_cmd *cmd,
+ 	unsigned int init_ticks,
+ 	unsigned int scan_ticks, unsigned int chan_ticks);
+ 
+ static int ai_write_chanlist(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_cmd *cmd);
++	struct comedi_subdevice *s, comedi_cmd *cmd);
+ 
+ static irqreturn_t me4000_ai_isr(int irq, void *dev_id PT_REGS_ARG);
+ 
+ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_cmd *cmd);
++	struct comedi_subdevice *s, comedi_cmd *cmd);
+ 
+-static int me4000_ai_do_cmd(struct comedi_device *dev, comedi_subdevice *s);
++static int me4000_ai_do_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
+ 
+ static int me4000_ao_insn_write(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
++	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
+ 
+ static int me4000_ao_insn_read(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
++	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
+ 
+ /*-----------------------------------------------------------------------------
+   Meilhaus inline functions
+@@ -249,7 +249,7 @@ static const comedi_lrange me4000_ao_range = {
+ 
+ static int me4000_attach(struct comedi_device *dev, comedi_devconfig *it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int result;
+ 
+ 	CALL_PDEBUG("In me4000_attach()\n");
+@@ -914,7 +914,7 @@ static int me4000_detach(struct comedi_device *dev)
+   ===========================================================================*/
+ 
+ static int me4000_ai_insn_read(struct comedi_device *dev,
+-	comedi_subdevice *subdevice, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *subdevice, comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -1037,7 +1037,7 @@ static int me4000_ai_insn_read(struct comedi_device *dev,
+ 	return 1;
+ }
+ 
+-static int me4000_ai_cancel(struct comedi_device *dev, comedi_subdevice *s)
++static int me4000_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	unsigned long tmp;
+ 
+@@ -1055,7 +1055,7 @@ static int me4000_ai_cancel(struct comedi_device *dev, comedi_subdevice *s)
+ }
+ 
+ static int ai_check_chanlist(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_cmd *cmd)
++	struct comedi_subdevice *s, comedi_cmd *cmd)
+ {
+ 	int aref;
+ 	int i;
+@@ -1136,7 +1136,7 @@ static int ai_check_chanlist(struct comedi_device *dev,
+ }
+ 
+ static int ai_round_cmd_args(struct comedi_device *dev,
+-	comedi_subdevice *s,
++	struct comedi_subdevice *s,
+ 	comedi_cmd *cmd,
+ 	unsigned int *init_ticks,
+ 	unsigned int *scan_ticks, unsigned int *chan_ticks)
+@@ -1223,7 +1223,7 @@ static void ai_write_timer(struct comedi_device *dev,
+ }
+ 
+ static int ai_prepare(struct comedi_device *dev,
+-	comedi_subdevice *s,
++	struct comedi_subdevice *s,
+ 	comedi_cmd *cmd,
+ 	unsigned int init_ticks,
+ 	unsigned int scan_ticks, unsigned int chan_ticks)
+@@ -1292,7 +1292,7 @@ static int ai_prepare(struct comedi_device *dev,
+ }
+ 
+ static int ai_write_chanlist(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_cmd *cmd)
++	struct comedi_subdevice *s, comedi_cmd *cmd)
+ {
+ 	unsigned int entry;
+ 	unsigned int chan;
+@@ -1331,7 +1331,7 @@ static int ai_write_chanlist(struct comedi_device *dev,
+ 	return 0;
+ }
+ 
+-static int me4000_ai_do_cmd(struct comedi_device *dev, comedi_subdevice *s)
++static int me4000_ai_do_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	int err;
+ 	unsigned int init_ticks = 0;
+@@ -1376,7 +1376,7 @@ static int me4000_ai_do_cmd(struct comedi_device *dev, comedi_subdevice *s)
+  * So I tried to adopt this scheme.
+  */
+ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_cmd *cmd)
++	struct comedi_subdevice *s, comedi_cmd *cmd)
+ {
+ 
+ 	unsigned int init_ticks;
+@@ -1744,7 +1744,7 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id PT_REGS_ARG)
+ {
+ 	unsigned int tmp;
+ 	struct comedi_device *dev = dev_id;
+-	comedi_subdevice *s = dev->subdevices;
++	struct comedi_subdevice *s = dev->subdevices;
+ 	me4000_ai_context_t *ai_context = &info->ai_context;
+ 	int i;
+ 	int c = 0;
+@@ -1904,7 +1904,7 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id PT_REGS_ARG)
+   ===========================================================================*/
+ 
+ static int me4000_ao_insn_write(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -1962,7 +1962,7 @@ static int me4000_ao_insn_write(struct comedi_device *dev,
+ }
+ 
+ static int me4000_ao_insn_read(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+@@ -1983,7 +1983,7 @@ static int me4000_ao_insn_read(struct comedi_device *dev,
+   ===========================================================================*/
+ 
+ static int me4000_dio_insn_bits(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	CALL_PDEBUG("In me4000_dio_insn_bits()\n");
+@@ -2034,7 +2034,7 @@ static int me4000_dio_insn_bits(struct comedi_device *dev,
+ }
+ 
+ static int me4000_dio_insn_config(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned long tmp;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -2216,7 +2216,7 @@ static int cnt_config(struct comedi_device *dev, unsigned int channel,
+ }
+ 
+ static int me4000_cnt_insn_config(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	int err;
+@@ -2259,7 +2259,7 @@ static int me4000_cnt_insn_config(struct comedi_device *dev,
+ }
+ 
+ static int me4000_cnt_insn_read(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	unsigned short tmp;
+@@ -2306,7 +2306,7 @@ static int me4000_cnt_insn_read(struct comedi_device *dev,
+ }
+ 
+ static int me4000_cnt_insn_write(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	unsigned short tmp;
+diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c
+index 5e48eaaf5f28..084b903d0cd6 100644
+--- a/drivers/staging/comedi/drivers/me_daq.c
++++ b/drivers/staging/comedi/drivers/me_daq.c
+@@ -290,7 +290,7 @@ static inline void sleep(unsigned sec)
+  *
+  * ------------------------------------------------------------------
+  */
+-static int me_dio_insn_config(struct comedi_device *dev, comedi_subdevice *s,
++static int me_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			      comedi_insn *insn, unsigned int *data)
+ {
+ 	int bits;
+@@ -326,7 +326,7 @@ static int me_dio_insn_config(struct comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ /* Digital instant input/outputs */
+-static int me_dio_insn_bits(struct comedi_device *dev, comedi_subdevice *s,
++static int me_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			    comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int mask = data[0];
+@@ -362,7 +362,7 @@ static int me_dio_insn_bits(struct comedi_device *dev, comedi_subdevice *s,
+  */
+ 
+ /* Analog instant input */
+-static int me_ai_insn_read(struct comedi_device *dev, comedi_subdevice *subdevice,
++static int me_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *subdevice,
+ 			   comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned short value;
+@@ -436,7 +436,7 @@ static int me_ai_insn_read(struct comedi_device *dev, comedi_subdevice *subdevic
+  */
+ 
+ /* Cancel analog input autoscan */
+-static int me_ai_cancel(struct comedi_device *dev, comedi_subdevice *s)
++static int me_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	/* disable interrupts */
+ 
+@@ -448,14 +448,14 @@ static int me_ai_cancel(struct comedi_device *dev, comedi_subdevice *s)
+ }
+ 
+ /* Test analog input command */
+-static int me_ai_do_cmd_test(struct comedi_device *dev, comedi_subdevice *s,
++static int me_ai_do_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			     comedi_cmd *cmd)
+ {
+ 	return 0;
+ }
+ 
+ /* Analog input command */
+-static int me_ai_do_cmd(struct comedi_device *dev, comedi_subdevice *subdevice)
++static int me_ai_do_cmd(struct comedi_device *dev, struct comedi_subdevice *subdevice)
+ {
+ 	return 0;
+ }
+@@ -469,7 +469,7 @@ static int me_ai_do_cmd(struct comedi_device *dev, comedi_subdevice *subdevice)
+  */
+ 
+ /* Analog instant output */
+-static int me_ao_insn_write(struct comedi_device *dev, comedi_subdevice *s,
++static int me_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			    comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan;
+@@ -519,7 +519,7 @@ static int me_ao_insn_write(struct comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ /* Analog output readback */
+-static int me_ao_insn_read(struct comedi_device *dev, comedi_subdevice *s,
++static int me_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			   comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+@@ -634,7 +634,7 @@ static int me_reset(struct comedi_device *dev)
+ static int me_attach(struct comedi_device *dev, comedi_devconfig *it)
+ {
+ 	struct pci_dev *pci_device;
+-	comedi_subdevice *subdevice;
++	struct comedi_subdevice *subdevice;
+ 	struct me_board *board;
+ 	resource_size_t plx_regbase_tmp;
+ 	unsigned long plx_regbase_size_tmp;
+diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c
+index 6bbcdde62ad3..2a30dda24bc4 100644
+--- a/drivers/staging/comedi/drivers/mpc624.c
++++ b/drivers/staging/comedi/drivers/mpc624.c
+@@ -155,12 +155,12 @@ static comedi_driver driver_mpc624 = {
+ };
+ 
+ //----------------------------------------------------------------------------
+-static int mpc624_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int mpc624_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ //----------------------------------------------------------------------------
+ static int mpc624_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+ 
+ 	iobase = it->options[0];
+@@ -268,7 +268,7 @@ static int mpc624_detach(struct comedi_device * dev)
+ // Timeout 200ms
+ #define TIMEOUT 200
+ 
+-static int mpc624_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int mpc624_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i;
+diff --git a/drivers/staging/comedi/drivers/mpc8260cpm.c b/drivers/staging/comedi/drivers/mpc8260cpm.c
+index f1f14514ff27..40057a0b8f97 100644
+--- a/drivers/staging/comedi/drivers/mpc8260cpm.c
++++ b/drivers/staging/comedi/drivers/mpc8260cpm.c
+@@ -55,14 +55,14 @@ static comedi_driver driver_mpc8260cpm = {
+ 
+ COMEDI_INITCLEANUP(driver_mpc8260cpm);
+ 
+-static int mpc8260cpm_dio_config(struct comedi_device * dev, comedi_subdevice * s,
++static int mpc8260cpm_dio_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int mpc8260cpm_dio_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int mpc8260cpm_dio_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ static int mpc8260cpm_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int i;
+ 
+ 	printk("comedi%d: mpc8260cpm: ", dev->minor);
+@@ -112,7 +112,7 @@ static unsigned long *cpm_pdat(int port)
+ 	}
+ }
+ 
+-static int mpc8260cpm_dio_config(struct comedi_device * dev, comedi_subdevice * s,
++static int mpc8260cpm_dio_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -155,7 +155,7 @@ static int mpc8260cpm_dio_config(struct comedi_device * dev, comedi_subdevice *
+ 	return 1;
+ }
+ 
+-static int mpc8260cpm_dio_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int mpc8260cpm_dio_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int port;
+diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c
+index 477185b33d72..151d6d4bdde4 100644
+--- a/drivers/staging/comedi/drivers/multiq3.c
++++ b/drivers/staging/comedi/drivers/multiq3.c
+@@ -98,7 +98,7 @@ struct multiq3_private {
+ };
+ #define devpriv ((struct multiq3_private *)dev->private)
+ 
+-static int multiq3_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int multiq3_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+@@ -134,7 +134,7 @@ static int multiq3_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s
+ 	return n;
+ }
+ 
+-static int multiq3_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int multiq3_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -147,7 +147,7 @@ static int multiq3_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s
+ 	return i;
+ }
+ 
+-static int multiq3_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
++static int multiq3_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -165,7 +165,7 @@ static int multiq3_ao_insn_write(struct comedi_device * dev, comedi_subdevice *
+ 	return i;
+ }
+ 
+-static int multiq3_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int multiq3_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -176,7 +176,7 @@ static int multiq3_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s
+ 	return 2;
+ }
+ 
+-static int multiq3_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int multiq3_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -191,7 +191,7 @@ static int multiq3_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s
+ 	return 2;
+ }
+ 
+-static int multiq3_encoder_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int multiq3_encoder_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -240,7 +240,7 @@ static int multiq3_attach(struct comedi_device * dev, comedi_devconfig * it)
+ 	int result = 0;
+ 	unsigned long iobase;
+ 	unsigned int irq;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	iobase = it->options[0];
+ 	printk("comedi%d: multiq3: 0x%04lx ", dev->minor, iobase);
+diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
+index bb9af22fbc44..453588813293 100644
+--- a/drivers/staging/comedi/drivers/ni_6527.c
++++ b/drivers/staging/comedi/drivers/ni_6527.c
+@@ -119,7 +119,7 @@ typedef struct {
+ 
+ static int ni6527_find_device(struct comedi_device * dev, int bus, int slot);
+ 
+-static int ni6527_di_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int ni6527_di_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -167,7 +167,7 @@ static int ni6527_di_insn_config(struct comedi_device * dev, comedi_subdevice *
+ 	return 2;
+ }
+ 
+-static int ni6527_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int ni6527_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -180,7 +180,7 @@ static int ni6527_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int ni6527_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int ni6527_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -212,7 +212,7 @@ static int ni6527_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ static irqreturn_t ni6527_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s = dev->subdevices + 2;
++	struct comedi_subdevice *s = dev->subdevices + 2;
+ 	unsigned int status;
+ 
+ 	status = readb(devpriv->mite->daq_io_addr + Change_Status);
+@@ -230,7 +230,7 @@ static irqreturn_t ni6527_interrupt(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int ni6527_intr_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int ni6527_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -306,7 +306,7 @@ static int ni6527_intr_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int ni6527_intr_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int ni6527_intr_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	//comedi_cmd *cmd = &s->async->cmd;
+ 
+@@ -319,14 +319,14 @@ static int ni6527_intr_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ni6527_intr_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int ni6527_intr_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	writeb(0x00, devpriv->mite->daq_io_addr + Master_Interrupt_Control);
+ 
+ 	return 0;
+ }
+ 
+-static int ni6527_intr_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int ni6527_intr_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n < 1)
+@@ -336,7 +336,7 @@ static int ni6527_intr_insn_bits(struct comedi_device * dev, comedi_subdevice *
+ 	return 2;
+ }
+ 
+-static int ni6527_intr_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int ni6527_intr_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n < 1)
+@@ -363,7 +363,7 @@ static int ni6527_intr_insn_config(struct comedi_device * dev, comedi_subdevice
+ 
+ static int ni6527_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int ret;
+ 
+ 	printk("comedi%d: ni6527:", dev->minor);
+diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
+index 347925b4963b..c12dcb6cae60 100644
+--- a/drivers/staging/comedi/drivers/ni_65xx.c
++++ b/drivers/staging/comedi/drivers/ni_65xx.c
+@@ -295,7 +295,7 @@ static inline ni_65xx_private *private(struct comedi_device * dev)
+ typedef struct {
+ 	unsigned base_port;
+ } ni_65xx_subdevice_private;
+-static inline ni_65xx_subdevice_private *sprivate(comedi_subdevice * subdev)
++static inline ni_65xx_subdevice_private *sprivate(struct comedi_subdevice * subdev)
+ {
+ 	return subdev->private;
+ }
+@@ -310,7 +310,7 @@ static ni_65xx_subdevice_private *ni_65xx_alloc_subdevice_private(void)
+ 
+ static int ni_65xx_find_device(struct comedi_device * dev, int bus, int slot);
+ 
+-static int ni_65xx_config_filter(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_65xx_config_filter(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	const unsigned chan = CR_CHAN(insn->chanspec);
+@@ -349,7 +349,7 @@ static int ni_65xx_config_filter(struct comedi_device * dev, comedi_subdevice *
+ 	return 2;
+ }
+ 
+-static int ni_65xx_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_65xx_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned port;
+@@ -388,7 +388,7 @@ static int ni_65xx_dio_insn_config(struct comedi_device * dev, comedi_subdevice
+ 	return -EINVAL;
+ }
+ 
+-static int ni_65xx_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_65xx_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned base_bitfield_channel;
+@@ -453,7 +453,7 @@ static int ni_65xx_dio_insn_bits(struct comedi_device * dev, comedi_subdevice *
+ static irqreturn_t ni_65xx_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s = dev->subdevices + 2;
++	struct comedi_subdevice *s = dev->subdevices + 2;
+ 	unsigned int status;
+ 
+ 	status = readb(private(dev)->mite->daq_io_addr + Change_Status);
+@@ -471,7 +471,7 @@ static irqreturn_t ni_65xx_interrupt(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int ni_65xx_intr_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_65xx_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -547,7 +547,7 @@ static int ni_65xx_intr_cmdtest(struct comedi_device * dev, comedi_subdevice * s
+ 	return 0;
+ }
+ 
+-static int ni_65xx_intr_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int ni_65xx_intr_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	//comedi_cmd *cmd = &s->async->cmd;
+ 
+@@ -560,7 +560,7 @@ static int ni_65xx_intr_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ni_65xx_intr_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int ni_65xx_intr_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	writeb(0x00,
+ 		private(dev)->mite->daq_io_addr + Master_Interrupt_Control);
+@@ -568,7 +568,7 @@ static int ni_65xx_intr_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ni_65xx_intr_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_65xx_intr_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n < 1)
+@@ -578,7 +578,7 @@ static int ni_65xx_intr_insn_bits(struct comedi_device * dev, comedi_subdevice *
+ 	return 2;
+ }
+ 
+-static int ni_65xx_intr_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_65xx_intr_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n < 1)
+@@ -617,7 +617,7 @@ static int ni_65xx_intr_insn_config(struct comedi_device * dev, comedi_subdevice
+ 
+ static int ni_65xx_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned i;
+ 	int ret;
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
+index 531709724b75..3304472d0a76 100644
+--- a/drivers/staging/comedi/drivers/ni_660x.c
++++ b/drivers/staging/comedi/drivers/ni_660x.c
+@@ -465,17 +465,17 @@ static int ni_660x_set_pfi_routing(struct comedi_device * dev, unsigned chan,
+ 
+ /* Possible instructions for a GPCT */
+ static int ni_660x_GPCT_rinsn(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ static int ni_660x_GPCT_insn_config(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ static int ni_660x_GPCT_winsn(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+ /* Possible instructions for Digital IO */
+ static int ni_660x_dio_insn_config(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ static int ni_660x_dio_insn_bits(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+ static inline unsigned ni_660x_num_counters(struct comedi_device * dev)
+ {
+@@ -843,7 +843,7 @@ void ni_660x_release_mite_channel(struct comedi_device * dev, struct ni_gpct *co
+ 	comedi_spin_unlock_irqrestore(&private(dev)->mite_channel_lock, flags);
+ }
+ 
+-static int ni_660x_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int ni_660x_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	int retval;
+ 
+@@ -862,7 +862,7 @@ static int ni_660x_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ 	return retval;
+ }
+ 
+-static int ni_660x_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_660x_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	struct ni_gpct *counter = subdev_to_counter(s);
+@@ -870,7 +870,7 @@ static int ni_660x_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	return ni_tio_cmdtest(counter, cmd);
+ }
+ 
+-static int ni_660x_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int ni_660x_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	struct ni_gpct *counter = subdev_to_counter(s);
+ 	int retval;
+@@ -894,7 +894,7 @@ static void set_tio_counterswap(struct comedi_device * dev, int chipset)
+ }
+ 
+ static void ni_660x_handle_gpct_interrupt(struct comedi_device * dev,
+-	comedi_subdevice * s)
++	struct comedi_subdevice * s)
+ {
+ 	ni_tio_handle_interrupt(subdev_to_counter(s), s);
+ 	if (s->async->events) {
+@@ -910,7 +910,7 @@ static void ni_660x_handle_gpct_interrupt(struct comedi_device * dev,
+ static irqreturn_t ni_660x_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned i;
+ 
+ 	if (dev->attached == 0)
+@@ -923,7 +923,7 @@ static irqreturn_t ni_660x_interrupt(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int ni_660x_buf_change(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_660x_buf_change(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned long new_size)
+ {
+ 	int ret;
+@@ -982,7 +982,7 @@ static void ni_660x_free_mite_rings(struct comedi_device * dev)
+ 
+ static int ni_660x_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int ret;
+ 	unsigned i;
+ 	unsigned global_interrupt_config_bits;
+@@ -1120,7 +1120,7 @@ static int ni_660x_detach(struct comedi_device * dev)
+ }
+ 
+ static int
+-ni_660x_GPCT_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++ni_660x_GPCT_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	return ni_tio_rinsn(subdev_to_counter(s), insn, data);
+@@ -1147,14 +1147,14 @@ static void init_tio_chip(struct comedi_device * dev, int chipset)
+ }
+ 
+ static int
+-ni_660x_GPCT_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++ni_660x_GPCT_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	return ni_tio_insn_config(subdev_to_counter(s), insn, data);
+ }
+ 
+ static int ni_660x_GPCT_winsn(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	return ni_tio_winsn(subdev_to_counter(s), insn, data);
+ }
+@@ -1187,7 +1187,7 @@ static int ni_660x_find_device(struct comedi_device * dev, int bus, int slot)
+ }
+ 
+ static int ni_660x_dio_insn_bits(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned base_bitfield_channel = CR_CHAN(insn->chanspec);
+ 
+@@ -1280,7 +1280,7 @@ static void ni660x_config_filter(struct comedi_device * dev, unsigned pfi_channe
+ }
+ 
+ static int ni_660x_dio_insn_config(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
+index 4c0cc433312a..0bcbfd1cd5ba 100644
+--- a/drivers/staging/comedi/drivers/ni_670x.c
++++ b/drivers/staging/comedi/drivers/ni_670x.c
+@@ -124,18 +124,18 @@ static comedi_lrange range_0_20mA = { 1, {RANGE_mA(0, 20)} };
+ 
+ static int ni_670x_find_device(struct comedi_device * dev, int bus, int slot);
+ 
+-static int ni_670x_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_670x_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_670x_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_670x_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_670x_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_670x_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_670x_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_670x_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ static int ni_670x_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int ret;
+ 	int i;
+ 
+@@ -218,7 +218,7 @@ static int ni_670x_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int ni_670x_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_670x_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -244,7 +244,7 @@ static int ni_670x_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int ni_670x_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_670x_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -256,7 +256,7 @@ static int ni_670x_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int ni_670x_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_670x_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -278,7 +278,7 @@ static int ni_670x_dio_insn_bits(struct comedi_device * dev, comedi_subdevice *
+ 	return 2;
+ }
+ 
+-static int ni_670x_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_670x_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
+index bf16e1273825..4ac5313ea43f 100644
+--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
++++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
+@@ -169,7 +169,7 @@ typedef struct {
+ 
+ static int a2150_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int a2150_detach(struct comedi_device * dev);
+-static int a2150_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static int a2150_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ 
+ static comedi_driver driver_a2150 = {
+       driver_name:"ni_at_a2150",
+@@ -179,10 +179,10 @@ static comedi_driver driver_a2150 = {
+ };
+ 
+ static irqreturn_t a2150_interrupt(int irq, void *d PT_REGS_ARG);
+-static int a2150_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int a2150_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int a2150_ai_cmd(struct comedi_device * dev, comedi_subdevice * s);
+-static int a2150_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int a2150_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
++static int a2150_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ static int a2150_get_timing(struct comedi_device * dev, unsigned int *period,
+ 	int flags);
+@@ -213,7 +213,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d PT_REGS_ARG)
+ 	int status;
+ 	unsigned long flags;
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s = dev->read_subdev;
++	struct comedi_subdevice *s = dev->read_subdev;
+ 	comedi_async *async;
+ 	comedi_cmd *cmd;
+ 	unsigned int max_points, num_points, residue, leftover;
+@@ -324,7 +324,7 @@ static int a2150_probe(struct comedi_device * dev)
+ 
+ static int a2150_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned long iobase = it->options[0];
+ 	unsigned int irq = it->options[1];
+ 	unsigned int dma = it->options[2];
+@@ -470,7 +470,7 @@ static int a2150_detach(struct comedi_device * dev)
+ 	return 0;
+ };
+ 
+-static int a2150_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int a2150_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	// disable dma on card
+ 	devpriv->irq_dma_bits &= ~DMA_INTR_EN_BIT & ~DMA_EN_BIT;
+@@ -485,7 +485,7 @@ static int a2150_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int a2150_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int a2150_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -615,7 +615,7 @@ static int a2150_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int a2150_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int a2150_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+@@ -726,7 +726,7 @@ static int a2150_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int a2150_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int a2150_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int i, n;
+diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c
+index 6a8d9a5b7bf7..e5083a2111c3 100644
+--- a/drivers/staging/comedi/drivers/ni_at_ao.c
++++ b/drivers/staging/comedi/drivers/ni_at_ao.c
+@@ -194,22 +194,22 @@ COMEDI_INITCLEANUP(driver_atao);
+ 
+ static void atao_reset(struct comedi_device * dev);
+ 
+-static int atao_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int atao_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int atao_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int atao_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int atao_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int atao_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int atao_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int atao_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int atao_calib_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int atao_calib_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int atao_calib_insn_write(struct comedi_device * dev, comedi_subdevice * s,
++static int atao_calib_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ static int atao_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+ 	int ao_unipolar;
+ 
+@@ -320,7 +320,7 @@ static void atao_reset(struct comedi_device * dev)
+ 	outw(devpriv->cfg1, dev->iobase + ATAO_CFG1);
+ }
+ 
+-static int atao_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int atao_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -344,7 +344,7 @@ static int atao_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int atao_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int atao_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -356,7 +356,7 @@ static int atao_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int atao_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int atao_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -373,7 +373,7 @@ static int atao_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int atao_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int atao_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -418,7 +418,7 @@ static int atao_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s
+  * DACs.  It is not explicitly stated in the manual how to access
+  * the caldacs, but we can guess.
+  */
+-static int atao_calib_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int atao_calib_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -428,7 +428,7 @@ static int atao_calib_insn_read(struct comedi_device * dev, comedi_subdevice * s
+ 	return insn->n;
+ }
+ 
+-static int atao_calib_insn_write(struct comedi_device * dev, comedi_subdevice * s,
++static int atao_calib_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bitstring, bit;
+diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
+index 62be3d9ec484..9c59c51863fe 100644
+--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
++++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
+@@ -126,10 +126,10 @@ static const atmio16_board_t atmio16_boards[] = {
+ static int atmio16d_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int atmio16d_detach(struct comedi_device * dev);
+ static irqreturn_t atmio16d_interrupt(int irq, void *d PT_REGS_ARG);
+-static int atmio16d_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int atmio16d_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int atmio16d_ai_cmd(struct comedi_device * dev, comedi_subdevice * s);
+-static int atmio16d_ai_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static int atmio16d_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
++static int atmio16d_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static void reset_counters(struct comedi_device * dev);
+ static void reset_atmio16d(struct comedi_device * dev);
+ 
+@@ -258,7 +258,7 @@ static void reset_atmio16d(struct comedi_device * dev)
+ static irqreturn_t atmio16d_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s = dev->subdevices + 0;
++	struct comedi_subdevice *s = dev->subdevices + 0;
+ 
+ //      printk("atmio16d_interrupt!\n");
+ 
+@@ -268,7 +268,7 @@ static irqreturn_t atmio16d_interrupt(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int atmio16d_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int atmio16d_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0, tmp;
+@@ -369,7 +369,7 @@ static int atmio16d_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int atmio16d_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int atmio16d_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned int timer, base_clock;
+@@ -517,7 +517,7 @@ static int atmio16d_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ /* This will cancel a running acquisition operation */
+-static int atmio16d_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int atmio16d_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	reset_atmio16d(dev);
+ 
+@@ -525,7 +525,7 @@ static int atmio16d_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ /* Mode 0 is used to get a single conversion on demand */
+-static int atmio16d_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int atmio16d_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, t;
+@@ -584,7 +584,7 @@ static int atmio16d_ai_insn_read(struct comedi_device * dev, comedi_subdevice *
+ 	return i;
+ }
+ 
+-static int atmio16d_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int atmio16d_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -599,7 +599,7 @@ static int atmio16d_ao_insn_read(struct comedi_device * dev, comedi_subdevice *
+ 	return i;
+ }
+ 
+-static int atmio16d_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
++static int atmio16d_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -634,7 +634,7 @@ static int atmio16d_ao_insn_write(struct comedi_device * dev, comedi_subdevice *
+ 	return i;
+ }
+ 
+-static int atmio16d_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int atmio16d_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -650,7 +650,7 @@ static int atmio16d_dio_insn_bits(struct comedi_device * dev, comedi_subdevice *
+ 	return 2;
+ }
+ 
+-static int atmio16d_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int atmio16d_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -710,7 +710,7 @@ static int atmio16d_attach(struct comedi_device * dev, comedi_devconfig * it)
+ 	unsigned long iobase;
+ 	int ret;
+ 
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	/* make sure the address range is free and allocate it */
+ 	iobase = it->options[0];
+diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
+index a83d0308a67a..8a0a5fa50eee 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_700.c
++++ b/drivers/staging/comedi/drivers/ni_daq_700.c
+@@ -126,9 +126,9 @@ struct subdev_700_struct {
+ #define CALLBACK_FUNC	(((struct subdev_700_struct *)s->private)->cb_func)
+ #define subdevpriv	((struct subdev_700_struct *)s->private)
+ 
+-static void do_config(struct comedi_device * dev, comedi_subdevice * s);
++static void do_config(struct comedi_device * dev, struct comedi_subdevice * s);
+ 
+-void subdev_700_interrupt(struct comedi_device * dev, comedi_subdevice * s)
++void subdev_700_interrupt(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	short d;
+ 
+@@ -153,7 +153,7 @@ static int subdev_700_cb(int dir, int port, int data, unsigned long arg)
+ 	}
+ }
+ 
+-static int subdev_700_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int subdev_700_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+@@ -171,7 +171,7 @@ static int subdev_700_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int subdev_700_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int subdev_700_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -194,12 +194,12 @@ static int subdev_700_insn_config(struct comedi_device * dev, comedi_subdevice *
+ 	return 1;
+ }
+ 
+-static void do_config(struct comedi_device * dev, comedi_subdevice * s)
++static void do_config(struct comedi_device * dev, struct comedi_subdevice * s)
+ {				/* use powerup defaults */
+ 	return;
+ }
+ 
+-static int subdev_700_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int subdev_700_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -274,21 +274,21 @@ static int subdev_700_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int subdev_700_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int subdev_700_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	/* FIXME */
+ 
+ 	return 0;
+ }
+ 
+-static int subdev_700_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int subdev_700_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	/* FIXME */
+ 
+ 	return 0;
+ }
+ 
+-int subdev_700_init(struct comedi_device * dev, comedi_subdevice * s, int (*cb) (int,
++int subdev_700_init(struct comedi_device * dev, struct comedi_subdevice * s, int (*cb) (int,
+ 		int, int, unsigned long), unsigned long arg)
+ {
+ 	s->type = COMEDI_SUBD_DIO;
+@@ -317,7 +317,7 @@ int subdev_700_init(struct comedi_device * dev, comedi_subdevice * s, int (*cb)
+ 	return 0;
+ }
+ 
+-int subdev_700_init_irq(struct comedi_device * dev, comedi_subdevice * s,
++int subdev_700_init_irq(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	int (*cb) (int, int, int, unsigned long), unsigned long arg)
+ {
+ 	int ret;
+@@ -335,7 +335,7 @@ int subdev_700_init_irq(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-void subdev_700_cleanup(struct comedi_device * dev, comedi_subdevice * s)
++void subdev_700_cleanup(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	if (s->private) {
+ 		if (subdevpriv->have_irq) {
+@@ -352,7 +352,7 @@ EXPORT_SYMBOL(subdev_700_interrupt);
+ 
+ static int dio700_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned long iobase = 0;
+ #ifdef incomplete
+ 	unsigned int irq = 0;
+diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
+index 98b20304b339..f2c73a4af068 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
++++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
+@@ -109,7 +109,7 @@ static comedi_driver driver_dio24 = {
+ 
+ static int dio24_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned long iobase = 0;
+ #ifdef incomplete
+ 	unsigned int irq = 0;
+diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
+index 53a7783793e3..be528f6c3ab0 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc.c
++++ b/drivers/staging/comedi/drivers/ni_labpc.c
+@@ -164,28 +164,28 @@ NI manuals:
+ #define COUNTER_B_BASE_REG	0x18
+ 
+ static int labpc_attach(struct comedi_device * dev, comedi_devconfig * it);
+-static int labpc_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static int labpc_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static irqreturn_t labpc_interrupt(int irq, void *d PT_REGS_ARG);
+ static int labpc_drain_fifo(struct comedi_device * dev);
+ static void labpc_drain_dma(struct comedi_device * dev);
+ static void handle_isa_dma(struct comedi_device * dev);
+ static void labpc_drain_dregs(struct comedi_device * dev);
+-static int labpc_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int labpc_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int labpc_ai_cmd(struct comedi_device * dev, comedi_subdevice * s);
+-static int labpc_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int labpc_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
++static int labpc_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int labpc_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int labpc_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int labpc_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int labpc_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int labpc_calib_read_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int labpc_calib_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int labpc_calib_write_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int labpc_calib_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int labpc_eeprom_read_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int labpc_eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int labpc_eeprom_write_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int labpc_eeprom_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ static unsigned int labpc_suggest_transfer_size(comedi_cmd cmd);
+ static void labpc_adc_timing(struct comedi_device * dev, comedi_cmd * cmd);
+@@ -462,7 +462,7 @@ static inline int labpc_counter_load(struct comedi_device * dev,
+ int labpc_common_attach(struct comedi_device * dev, unsigned long iobase,
+ 	unsigned int irq, unsigned int dma_chan)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int i;
+ 	unsigned long dma_flags, isr_flags;
+ 	short lsb, msb;
+@@ -755,7 +755,7 @@ static void labpc_clear_adc_fifo(const struct comedi_device * dev)
+ 	devpriv->read_byte(dev->iobase + ADC_FIFO_REG);
+ }
+ 
+-static int labpc_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int labpc_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+ 
+@@ -926,7 +926,7 @@ static void labpc_set_ai_scan_period(comedi_cmd * cmd, unsigned int ns)
+ 	cmd->scan_begin_arg = ns;
+ }
+ 
+-static int labpc_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int labpc_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -1063,7 +1063,7 @@ static int labpc_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int labpc_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int labpc_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	int channel, range, aref;
+ 	unsigned long irq_flags;
+@@ -1312,7 +1312,7 @@ static int labpc_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ static irqreturn_t labpc_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s = dev->read_subdev;
++	struct comedi_subdevice *s = dev->read_subdev;
+ 	comedi_async *async;
+ 	comedi_cmd *cmd;
+ 
+@@ -1429,7 +1429,7 @@ static int labpc_drain_fifo(struct comedi_device * dev)
+ 
+ static void labpc_drain_dma(struct comedi_device * dev)
+ {
+-	comedi_subdevice *s = dev->read_subdev;
++	struct comedi_subdevice *s = dev->read_subdev;
+ 	comedi_async *async = s->async;
+ 	int status;
+ 	unsigned long flags;
+@@ -1500,7 +1500,7 @@ static void labpc_drain_dregs(struct comedi_device * dev)
+ 	labpc_drain_fifo(dev);
+ }
+ 
+-static int labpc_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int labpc_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+@@ -1586,7 +1586,7 @@ static int labpc_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ // analog output insn
+-static int labpc_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int labpc_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel, range;
+@@ -1627,7 +1627,7 @@ static int labpc_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ // analog output readback insn
+-static int labpc_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int labpc_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)];
+@@ -1635,7 +1635,7 @@ static int labpc_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int labpc_calib_read_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int labpc_calib_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->caldac[CR_CHAN(insn->chanspec)];
+@@ -1643,7 +1643,7 @@ static int labpc_calib_read_insn(struct comedi_device * dev, comedi_subdevice *
+ 	return 1;
+ }
+ 
+-static int labpc_calib_write_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int labpc_calib_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel = CR_CHAN(insn->chanspec);
+@@ -1652,7 +1652,7 @@ static int labpc_calib_write_insn(struct comedi_device * dev, comedi_subdevice *
+ 	return 1;
+ }
+ 
+-static int labpc_eeprom_read_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int labpc_eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->eeprom_data[CR_CHAN(insn->chanspec)];
+@@ -1660,7 +1660,7 @@ static int labpc_eeprom_read_insn(struct comedi_device * dev, comedi_subdevice *
+ 	return 1;
+ }
+ 
+-static int labpc_eeprom_write_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int labpc_eeprom_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index f702cc9064ba..29698d995a19 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -193,48 +193,48 @@ static const comedi_lrange *const ni_range_lkup[] = {
+ 	[ai_gain_6143] = &range_ni_S_ai_6143
+ };
+ 
+-static int ni_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_cdio_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_cdio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int ni_cdio_cmd(struct comedi_device * dev, comedi_subdevice * s);
+-static int ni_cdio_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static int ni_cdio_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
++static int ni_cdio_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static void handle_cdio_interrupt(struct comedi_device * dev);
+-static int ni_cdo_inttrig(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_cdo_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int trignum);
+ 
+-static int ni_serial_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_serial_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_serial_hw_readwrite8(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_serial_hw_readwrite8(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned char data_out, unsigned char *data_in);
+-static int ni_serial_sw_readwrite8(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_serial_sw_readwrite8(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned char data_out, unsigned char *data_in);
+ 
+-static int ni_calib_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_calib_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_calib_insn_write(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_calib_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int ni_eeprom_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_eeprom_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ static int ni_m_series_eeprom_insn_read(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+-static int ni_pfi_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_pfi_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_pfi_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_pfi_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ static unsigned ni_old_get_pfi_routing(struct comedi_device * dev, unsigned chan);
+ 
+ static void ni_rtsi_init(struct comedi_device * dev);
+-static int ni_rtsi_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_rtsi_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_rtsi_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_rtsi_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static void caldac_setup(struct comedi_device * dev, comedi_subdevice * s);
++static void caldac_setup(struct comedi_device * dev, struct comedi_subdevice * s);
+ static int ni_read_eeprom(struct comedi_device * dev, int addr);
+ 
+ #ifdef DEBUG_STATUS_A
+@@ -248,41 +248,41 @@ static void ni_mio_print_status_b(int status);
+ #define ni_mio_print_status_b(a)
+ #endif
+ 
+-static int ni_ai_reset(struct comedi_device * dev, comedi_subdevice * s);
++static int ni_ai_reset(struct comedi_device * dev, struct comedi_subdevice * s);
+ #ifndef PCIDMA
+ static void ni_handle_fifo_half_full(struct comedi_device * dev);
+-static int ni_ao_fifo_half_empty(struct comedi_device * dev, comedi_subdevice * s);
++static int ni_ao_fifo_half_empty(struct comedi_device * dev, struct comedi_subdevice * s);
+ #endif
+ static void ni_handle_fifo_dregs(struct comedi_device * dev);
+-static int ni_ai_inttrig(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_ai_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int trignum);
+ static void ni_load_channelgain_list(struct comedi_device * dev, unsigned int n_chan,
+ 	unsigned int *list);
+ static void shutdown_ai_command(struct comedi_device * dev);
+ 
+-static int ni_ao_inttrig(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_ao_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int trignum);
+ 
+-static int ni_ao_reset(struct comedi_device * dev, comedi_subdevice * s);
++static int ni_ao_reset(struct comedi_device * dev, struct comedi_subdevice * s);
+ 
+ static int ni_8255_callback(int dir, int port, int data, unsigned long arg);
+ 
+-static int ni_gpct_insn_write(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_gpct_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_gpct_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_gpct_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_gpct_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_gpct_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_gpct_cmd(struct comedi_device * dev, comedi_subdevice * s);
+-static int ni_gpct_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_gpct_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
++static int ni_gpct_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int ni_gpct_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static int ni_gpct_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static void handle_gpct_interrupt(struct comedi_device * dev,
+ 	unsigned short counter_index);
+ 
+ static int init_cs5529(struct comedi_device * dev);
+ static int cs5529_do_conversion(struct comedi_device * dev, unsigned short *data);
+-static int cs5529_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int cs5529_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ #ifdef NI_CS5529_DEBUG
+ static unsigned int cs5529_config_read(struct comedi_device * dev,
+@@ -291,9 +291,9 @@ static unsigned int cs5529_config_read(struct comedi_device * dev,
+ static void cs5529_config_write(struct comedi_device * dev, unsigned int value,
+ 	unsigned int reg_select_bits);
+ 
+-static int ni_m_series_pwm_config(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_m_series_pwm_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_6143_pwm_config(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_6143_pwm_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ static int ni_set_master_clock(struct comedi_device * dev, unsigned source,
+@@ -825,7 +825,7 @@ static irqreturn_t ni_E_interrupt(int irq, void *d PT_REGS_ARG)
+ #ifdef PCIDMA
+ static void ni_sync_ai_dma(struct comedi_device * dev)
+ {
+-	comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
++	struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ 	unsigned long flags;
+ 
+ 	comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
+@@ -836,7 +836,7 @@ static void ni_sync_ai_dma(struct comedi_device * dev)
+ 
+ static void mite_handle_b_linkc(struct mite_struct *mite, struct comedi_device * dev)
+ {
+-	comedi_subdevice *s = dev->subdevices + NI_AO_SUBDEV;
++	struct comedi_subdevice *s = dev->subdevices + NI_AO_SUBDEV;
+ 	unsigned long flags;
+ 
+ 	comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
+@@ -868,7 +868,7 @@ static int ni_ao_wait_for_dma_load(struct comedi_device * dev)
+ }
+ 
+ #endif //PCIDMA
+-static void ni_handle_eos(struct comedi_device * dev, comedi_subdevice * s)
++static void ni_handle_eos(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	if (devpriv->aimode == AIMODE_SCAN) {
+ #ifdef PCIDMA
+@@ -894,7 +894,7 @@ static void ni_handle_eos(struct comedi_device * dev, comedi_subdevice * s)
+ 
+ static void shutdown_ai_command(struct comedi_device * dev)
+ {
+-	comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
++	struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ 
+ #ifdef PCIDMA
+ 	ni_ai_drain_dma(dev);
+@@ -906,7 +906,7 @@ static void shutdown_ai_command(struct comedi_device * dev)
+ 	s->async->events |= COMEDI_CB_EOA;
+ }
+ 
+-static void ni_event(struct comedi_device * dev, comedi_subdevice * s)
++static void ni_event(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	if (s->async->
+ 		events & (COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW | COMEDI_CB_EOA))
+@@ -936,7 +936,7 @@ static void handle_gpct_interrupt(struct comedi_device * dev,
+ 	unsigned short counter_index)
+ {
+ #ifdef PCIDMA
+-	comedi_subdevice *s = dev->subdevices + NI_GPCT_SUBDEV(counter_index);
++	struct comedi_subdevice *s = dev->subdevices + NI_GPCT_SUBDEV(counter_index);
+ 
+ 	ni_tio_handle_interrupt(&devpriv->counter_dev->counters[counter_index],
+ 		s);
+@@ -969,7 +969,7 @@ static void ack_a_interrupt(struct comedi_device * dev, unsigned short a_status)
+ static void handle_a_interrupt(struct comedi_device * dev, unsigned short status,
+ 	unsigned ai_mite_status)
+ {
+-	comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
++	struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ 
+ 	//67xx boards don't have ai subdevice, but their gpct0 might generate an a interrupt
+ 	if (s->type == COMEDI_SUBD_UNUSED)
+@@ -1101,7 +1101,7 @@ static void ack_b_interrupt(struct comedi_device * dev, unsigned short b_status)
+ static void handle_b_interrupt(struct comedi_device * dev, unsigned short b_status,
+ 	unsigned ao_mite_status)
+ {
+-	comedi_subdevice *s = dev->subdevices + NI_AO_SUBDEV;
++	struct comedi_subdevice *s = dev->subdevices + NI_AO_SUBDEV;
+ 	//unsigned short ack=0;
+ #ifdef DEBUG_INTERRUPT
+ 	rt_printk("ni_mio_common: interrupt: b_status=%04x m1_status=%08x\n",
+@@ -1204,7 +1204,7 @@ static void ni_mio_print_status_b(int status)
+ 
+ #ifndef PCIDMA
+ 
+-static void ni_ao_fifo_load(struct comedi_device * dev, comedi_subdevice * s, int n)
++static void ni_ao_fifo_load(struct comedi_device * dev, struct comedi_subdevice * s, int n)
+ {
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+@@ -1263,7 +1263,7 @@ static void ni_ao_fifo_load(struct comedi_device * dev, comedi_subdevice * s, in
+  *  RT code, as RT code might purposely be running close to the
+  *  metal.  Needs to be fixed eventually.
+  */
+-static int ni_ao_fifo_half_empty(struct comedi_device * dev, comedi_subdevice * s)
++static int ni_ao_fifo_half_empty(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	int n;
+ 
+@@ -1284,7 +1284,7 @@ static int ni_ao_fifo_half_empty(struct comedi_device * dev, comedi_subdevice *
+ 	return 1;
+ }
+ 
+-static int ni_ao_prep_fifo(struct comedi_device * dev, comedi_subdevice * s)
++static int ni_ao_prep_fifo(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	int n;
+ 
+@@ -1307,7 +1307,7 @@ static int ni_ao_prep_fifo(struct comedi_device * dev, comedi_subdevice * s)
+ 	return n;
+ }
+ 
+-static void ni_ai_fifo_read(struct comedi_device * dev, comedi_subdevice * s, int n)
++static void ni_ai_fifo_read(struct comedi_device * dev, struct comedi_subdevice * s, int n)
+ {
+ 	comedi_async *async = s->async;
+ 	int i;
+@@ -1367,7 +1367,7 @@ static void ni_ai_fifo_read(struct comedi_device * dev, comedi_subdevice * s, in
+ static void ni_handle_fifo_half_full(struct comedi_device * dev)
+ {
+ 	int n;
+-	comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
++	struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ 
+ 	n = boardtype.ai_fifo_depth / 2;
+ 
+@@ -1416,7 +1416,7 @@ static int ni_ai_drain_dma(struct comedi_device * dev)
+ */
+ static void ni_handle_fifo_dregs(struct comedi_device * dev)
+ {
+-	comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
++	struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ 	short data[2];
+ 	u32 dl;
+ 	short fifo_empty;
+@@ -1478,7 +1478,7 @@ static void ni_handle_fifo_dregs(struct comedi_device * dev)
+ 
+ static void get_last_sample_611x(struct comedi_device * dev)
+ {
+-	comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
++	struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ 	short data;
+ 	u32 dl;
+ 
+@@ -1495,7 +1495,7 @@ static void get_last_sample_611x(struct comedi_device * dev)
+ 
+ static void get_last_sample_6143(struct comedi_device * dev)
+ {
+-	comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
++	struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ 	short data;
+ 	u32 dl;
+ 
+@@ -1513,7 +1513,7 @@ static void get_last_sample_6143(struct comedi_device * dev)
+ 	}
+ }
+ 
+-static void ni_ai_munge(struct comedi_device * dev, comedi_subdevice * s,
++static void ni_ai_munge(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	void *data, unsigned int num_bytes, unsigned int chan_index)
+ {
+ 	comedi_async *async = s->async;
+@@ -1541,7 +1541,7 @@ static void ni_ai_munge(struct comedi_device * dev, comedi_subdevice * s,
+ 
+ static int ni_ai_setup_MITE_dma(struct comedi_device * dev)
+ {
+-	comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
++	struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ 	int retval;
+ 	unsigned long flags;
+ 
+@@ -1581,7 +1581,7 @@ static int ni_ai_setup_MITE_dma(struct comedi_device * dev)
+ 
+ static int ni_ao_setup_MITE_dma(struct comedi_device * dev)
+ {
+-	comedi_subdevice *s = dev->subdevices + NI_AO_SUBDEV;
++	struct comedi_subdevice *s = dev->subdevices + NI_AO_SUBDEV;
+ 	int retval;
+ 	unsigned long flags;
+ 
+@@ -1617,7 +1617,7 @@ static int ni_ao_setup_MITE_dma(struct comedi_device * dev)
+    this is pretty harsh for a cancel, but it works...
+  */
+ 
+-static int ni_ai_reset(struct comedi_device * dev, comedi_subdevice * s)
++static int ni_ai_reset(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	ni_release_ai_mite_channel(dev);
+ 	/* ai configuration */
+@@ -1698,7 +1698,7 @@ static int ni_ai_reset(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ni_ai_poll(struct comedi_device * dev, comedi_subdevice * s)
++static int ni_ai_poll(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned long flags = 0;
+ 	int count;
+@@ -1718,7 +1718,7 @@ static int ni_ai_poll(struct comedi_device * dev, comedi_subdevice * s)
+ 	return count;
+ }
+ 
+-static int ni_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+@@ -2095,7 +2095,7 @@ static unsigned ni_min_ai_scan_period_ns(struct comedi_device * dev,
+ 	return boardtype.ai_speed * num_channels;
+ }
+ 
+-static int ni_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -2308,7 +2308,7 @@ static int ni_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int ni_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int ni_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	const comedi_cmd *cmd = &s->async->cmd;
+ 	int timer;
+@@ -2612,7 +2612,7 @@ static int ni_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ni_ai_inttrig(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_ai_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int trignum)
+ {
+ 	if (trignum != 0)
+@@ -2625,10 +2625,10 @@ static int ni_ai_inttrig(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int ni_ai_config_analog_trig(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_ai_config_analog_trig(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int ni_ai_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_ai_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n < 1)
+@@ -2679,7 +2679,7 @@ static int ni_ai_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	return -EINVAL;
+ }
+ 
+-static int ni_ai_config_analog_trig(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_ai_config_analog_trig(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int a, b, modebits;
+@@ -2777,7 +2777,7 @@ static int ni_ai_config_analog_trig(struct comedi_device * dev, comedi_subdevice
+ }
+ 
+ /* munge data from unsigned to 2's complement for analog output bipolar modes */
+-static void ni_ao_munge(struct comedi_device * dev, comedi_subdevice * s,
++static void ni_ao_munge(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	void *data, unsigned int num_bytes, unsigned int chan_index)
+ {
+ 	comedi_async *async = s->async;
+@@ -2801,7 +2801,7 @@ static void ni_ao_munge(struct comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int ni_m_series_ao_config_chanlist(struct comedi_device * dev,
+-	comedi_subdevice * s, unsigned int chanspec[], unsigned int n_chans,
++	struct comedi_subdevice * s, unsigned int chanspec[], unsigned int n_chans,
+ 	int timed)
+ {
+ 	unsigned int range;
+@@ -2869,7 +2869,7 @@ static int ni_m_series_ao_config_chanlist(struct comedi_device * dev,
+ 	return invert;
+ }
+ 
+-static int ni_old_ao_config_chanlist(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_old_ao_config_chanlist(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int chanspec[], unsigned int n_chans)
+ {
+ 	unsigned int range;
+@@ -2912,7 +2912,7 @@ static int ni_old_ao_config_chanlist(struct comedi_device * dev, comedi_subdevic
+ 	return invert;
+ }
+ 
+-static int ni_ao_config_chanlist(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_ao_config_chanlist(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int chanspec[], unsigned int n_chans, int timed)
+ {
+ 	if (boardtype.reg_type & ni_reg_m_series_mask)
+@@ -2921,7 +2921,7 @@ static int ni_ao_config_chanlist(struct comedi_device * dev, comedi_subdevice *
+ 	else
+ 		return ni_old_ao_config_chanlist(dev, s, chanspec, n_chans);
+ }
+-static int ni_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->ao[CR_CHAN(insn->chanspec)];
+@@ -2929,7 +2929,7 @@ static int ni_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int ni_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int chan = CR_CHAN(insn->chanspec);
+@@ -2948,7 +2948,7 @@ static int ni_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int ni_ao_insn_write_671x(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_ao_insn_write_671x(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int chan = CR_CHAN(insn->chanspec);
+@@ -2965,7 +2965,7 @@ static int ni_ao_insn_write_671x(struct comedi_device * dev, comedi_subdevice *
+ 	return 1;
+ }
+ 
+-static int ni_ao_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_ao_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+@@ -2991,7 +2991,7 @@ static int ni_ao_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	return -EINVAL;
+ }
+ 
+-static int ni_ao_inttrig(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_ao_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int trignum)
+ {
+ 	int ret;
+@@ -3062,7 +3062,7 @@ static int ni_ao_inttrig(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int ni_ao_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int ni_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	const comedi_cmd *cmd = &s->async->cmd;
+ 	int bits;
+@@ -3261,7 +3261,7 @@ static int ni_ao_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ni_ao_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -3384,7 +3384,7 @@ static int ni_ao_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int ni_ao_reset(struct comedi_device * dev, comedi_subdevice * s)
++static int ni_ao_reset(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	//devpriv->ao0p=0x0000;
+ 	//ni_writew(devpriv->ao0p,AO_Configuration);
+@@ -3436,7 +3436,7 @@ static int ni_ao_reset(struct comedi_device * dev, comedi_subdevice * s)
+ 
+ // digital io
+ 
+-static int ni_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ #ifdef DEBUG_DIO
+@@ -3468,7 +3468,7 @@ static int ni_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int ni_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ #ifdef DEBUG_DIO
+@@ -3496,7 +3496,7 @@ static int ni_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int ni_m_series_dio_insn_config(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ #ifdef DEBUG_DIO
+ 	rt_printk("ni_m_series_dio_insn_config() chan=%d io=%d\n",
+@@ -3525,7 +3525,7 @@ static int ni_m_series_dio_insn_config(struct comedi_device * dev,
+ 	return 1;
+ }
+ 
+-static int ni_m_series_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_m_series_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ #ifdef DEBUG_DIO
+@@ -3544,7 +3544,7 @@ static int ni_m_series_dio_insn_bits(struct comedi_device * dev, comedi_subdevic
+ 	return 2;
+ }
+ 
+-static int ni_cdio_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_cdio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -3653,7 +3653,7 @@ static int ni_cdio_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int ni_cdio_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int ni_cdio_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	const comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned cdo_mode_bits = CDO_FIFO_Mode_Bit | CDO_Halt_On_Error_Bit;
+@@ -3690,7 +3690,7 @@ static int ni_cdio_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ni_cdo_inttrig(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_cdo_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int trignum)
+ {
+ #ifdef PCIDMA
+@@ -3736,7 +3736,7 @@ static int ni_cdo_inttrig(struct comedi_device * dev, comedi_subdevice * s,
+ 	return retval;
+ }
+ 
+-static int ni_cdio_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int ni_cdio_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	ni_writel(CDO_Disarm_Bit | CDO_Error_Interrupt_Enable_Clear_Bit |
+ 		CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit |
+@@ -3752,7 +3752,7 @@ static int ni_cdio_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ static void handle_cdio_interrupt(struct comedi_device * dev)
+ {
+ 	unsigned cdio_status;
+-	comedi_subdevice *s = dev->subdevices + NI_DIO_SUBDEV;
++	struct comedi_subdevice *s = dev->subdevices + NI_DIO_SUBDEV;
+ #ifdef PCIDMA
+ 	unsigned long flags;
+ #endif
+@@ -3790,7 +3790,7 @@ static void handle_cdio_interrupt(struct comedi_device * dev)
+ 	ni_event(dev, s);
+ }
+ 
+-static int ni_serial_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_serial_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int err = insn->n;
+@@ -3884,7 +3884,7 @@ static int ni_serial_insn_config(struct comedi_device * dev, comedi_subdevice *
+ 
+ }
+ 
+-static int ni_serial_hw_readwrite8(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_serial_hw_readwrite8(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned char data_out, unsigned char *data_in)
+ {
+ 	unsigned int status1;
+@@ -3940,7 +3940,7 @@ static int ni_serial_hw_readwrite8(struct comedi_device * dev, comedi_subdevice
+ 	return err;
+ }
+ 
+-static int ni_serial_sw_readwrite8(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_serial_sw_readwrite8(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned char data_out, unsigned char *data_in)
+ {
+ 	unsigned char mask, input = 0;
+@@ -4004,7 +4004,7 @@ static void mio_common_detach(struct comedi_device * dev)
+ 		subdev_8255_cleanup(dev, dev->subdevices + NI_8255_DIO_SUBDEV);
+ }
+ 
+-static void init_ao_67xx(struct comedi_device * dev, comedi_subdevice * s)
++static void init_ao_67xx(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	int i;
+ 
+@@ -4209,14 +4209,14 @@ static unsigned ni_gpct_read_register(struct ni_gpct *counter,
+ }
+ 
+ static int ni_freq_out_insn_read(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->clock_and_fout & FOUT_Divider_mask;
+ 	return 1;
+ }
+ 
+ static int ni_freq_out_insn_write(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	devpriv->clock_and_fout &= ~FOUT_Enable;
+ 	devpriv->stc_writew(dev, devpriv->clock_and_fout,
+@@ -4258,7 +4258,7 @@ static void ni_get_freq_out_clock(struct comedi_device * dev, unsigned int * clo
+ 	}
+ }
+ 
+-static int ni_freq_out_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_freq_out_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+@@ -4291,7 +4291,7 @@ static int ni_alloc_private(struct comedi_device * dev)
+ 
+ static int ni_E_init(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned j;
+ 	enum ni_gpct_variant counter_variant;
+ 
+@@ -4623,7 +4623,7 @@ static int ni_8255_callback(int dir, int port, int data, unsigned long arg)
+ 	presents the EEPROM as a subdevice
+ */
+ 
+-static int ni_eeprom_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_eeprom_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = ni_read_eeprom(dev, CR_CHAN(insn->chanspec));
+@@ -4660,7 +4660,7 @@ static int ni_read_eeprom(struct comedi_device * dev, int addr)
+ }
+ 
+ static int ni_m_series_eeprom_insn_read(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->eeprom_buffer[CR_CHAN(insn->chanspec)];
+ 
+@@ -4674,7 +4674,7 @@ static int ni_get_pwm_config(struct comedi_device * dev, unsigned int * data)
+ 	return 3;
+ }
+ 
+-static int ni_m_series_pwm_config(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_m_series_pwm_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned up_count, down_count;
+@@ -4739,7 +4739,7 @@ static int ni_m_series_pwm_config(struct comedi_device * dev, comedi_subdevice *
+ 	return 0;
+ }
+ 
+-static int ni_6143_pwm_config(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_6143_pwm_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned up_count, down_count;
+@@ -4806,7 +4806,7 @@ static void ni_write_caldac(struct comedi_device * dev, int addr, int val);
+ /*
+ 	calibration subdevice
+ */
+-static int ni_calib_insn_write(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_calib_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	ni_write_caldac(dev, CR_CHAN(insn->chanspec), data[0]);
+@@ -4814,7 +4814,7 @@ static int ni_calib_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int ni_calib_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_calib_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->caldacs[CR_CHAN(insn->chanspec)];
+@@ -4845,7 +4845,7 @@ static struct caldac_struct caldacs[] = {
+ 	[ad8804_debug] = {16, 8, pack_ad8804},
+ };
+ 
+-static void caldac_setup(struct comedi_device * dev, comedi_subdevice * s)
++static void caldac_setup(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	int i, j;
+ 	int n_dacs;
+@@ -5070,28 +5070,28 @@ static void GPCT_Reset(struct comedi_device * dev, int chan)
+ 
+ #endif
+ 
+-static int ni_gpct_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_gpct_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	struct ni_gpct *counter = s->private;
+ 	return ni_tio_insn_config(counter, insn, data);
+ }
+ 
+-static int ni_gpct_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_gpct_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	struct ni_gpct *counter = s->private;
+ 	return ni_tio_rinsn(counter, insn, data);
+ }
+ 
+-static int ni_gpct_insn_write(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_gpct_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	struct ni_gpct *counter = s->private;
+ 	return ni_tio_winsn(counter, insn, data);
+ }
+ 
+-static int ni_gpct_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int ni_gpct_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	int retval;
+ #ifdef PCIDMA
+@@ -5114,7 +5114,7 @@ static int ni_gpct_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ 	return retval;
+ }
+ 
+-static int ni_gpct_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_gpct_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ #ifdef PCIDMA
+@@ -5126,7 +5126,7 @@ static int ni_gpct_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ #endif
+ }
+ 
+-static int ni_gpct_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int ni_gpct_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ #ifdef PCIDMA
+ 	struct ni_gpct *counter = s->private;
+@@ -5253,7 +5253,7 @@ static int ni_config_filter(struct comedi_device * dev, unsigned pfi_channel,
+ 	return 0;
+ }
+ 
+-static int ni_pfi_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_pfi_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if ((boardtype.reg_type & ni_reg_m_series_mask) == 0) {
+@@ -5268,7 +5268,7 @@ static int ni_pfi_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int ni_pfi_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_pfi_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int chan;
+@@ -5345,7 +5345,7 @@ static void ni_rtsi_init(struct comedi_device * dev)
+ //      devpriv->stc_writew(dev, 0x0000, RTSI_Board_Register);
+ }
+ 
+-static int ni_rtsi_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_rtsi_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -5626,7 +5626,7 @@ static unsigned ni_get_rtsi_routing(struct comedi_device * dev, unsigned chan)
+ 	}
+ }
+ 
+-static int ni_rtsi_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_rtsi_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int chan = CR_CHAN(insn->chanspec);
+@@ -5805,7 +5805,7 @@ static int cs5529_do_conversion(struct comedi_device * dev, unsigned short *data
+ 	return 0;
+ }
+ 
+-static int cs5529_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int cs5529_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, retval;
+diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
+index b236d88e4e4e..79457ecbafbe 100644
+--- a/drivers/staging/comedi/drivers/ni_pcidio.c
++++ b/drivers/staging/comedi/drivers/ni_pcidio.c
+@@ -289,7 +289,7 @@ enum FPGA_Control_Bits {
+ 
+ static int nidio_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int nidio_detach(struct comedi_device * dev);
+-static int ni_pcidio_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static int ni_pcidio_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ 
+ static comedi_driver driver_pcidio = {
+       driver_name:"ni_pcidio",
+@@ -399,14 +399,14 @@ typedef struct {
+ } nidio96_private;
+ #define devpriv ((nidio96_private *)dev->private)
+ 
+-static int ni_pcidio_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_pcidio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int ni_pcidio_cmd(struct comedi_device * dev, comedi_subdevice * s);
+-static int ni_pcidio_inttrig(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_pcidio_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
++static int ni_pcidio_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int trignum);
+ static int nidio_find_device(struct comedi_device * dev, int bus, int slot);
+ static int ni_pcidio_ns_to_timer(int *nanosec, int round_mode);
+-static int setup_mite_dma(struct comedi_device * dev, comedi_subdevice * s);
++static int setup_mite_dma(struct comedi_device * dev, struct comedi_subdevice * s);
+ 
+ #ifdef DEBUG_FLAGS
+ static void ni_pcidio_print_flags(unsigned int flags);
+@@ -467,7 +467,7 @@ static int nidio96_8255_cb(int dir, int port, int data, unsigned long iobase)
+ 	}
+ }
+ 
+-void ni_pcidio_event(struct comedi_device * dev, comedi_subdevice * s)
++void ni_pcidio_event(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	if (s->async->
+ 		events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW))
+@@ -480,7 +480,7 @@ void ni_pcidio_event(struct comedi_device * dev, comedi_subdevice * s)
+ static irqreturn_t nidio_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s = dev->subdevices;
++	struct comedi_subdevice *s = dev->subdevices;
+ 	comedi_async *async = s->async;
+ 	struct mite_struct *mite = devpriv->mite;
+ 
+@@ -702,7 +702,7 @@ static void debug_int(struct comedi_device * dev)
+ }
+ #endif
+ 
+-static int ni_pcidio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_pcidio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 1)
+@@ -729,7 +729,7 @@ static int ni_pcidio_insn_config(struct comedi_device * dev, comedi_subdevice *
+ 	return 1;
+ }
+ 
+-static int ni_pcidio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_pcidio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -744,7 +744,7 @@ static int ni_pcidio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int ni_pcidio_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_pcidio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -876,7 +876,7 @@ static int ni_pcidio_ns_to_timer(int *nanosec, int round_mode)
+ 	return divider;
+ }
+ 
+-static int ni_pcidio_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int ni_pcidio_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 
+@@ -986,7 +986,7 @@ static int ni_pcidio_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int setup_mite_dma(struct comedi_device * dev, comedi_subdevice * s)
++static int setup_mite_dma(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	int retval;
+ 
+@@ -1002,7 +1002,7 @@ static int setup_mite_dma(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ni_pcidio_inttrig(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_pcidio_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int trignum)
+ {
+ 	if (trignum != 0)
+@@ -1014,7 +1014,7 @@ static int ni_pcidio_inttrig(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int ni_pcidio_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int ni_pcidio_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	writeb(0x00,
+ 		devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control);
+@@ -1023,7 +1023,7 @@ static int ni_pcidio_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ni_pcidio_change(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_pcidio_change(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned long new_size)
+ {
+ 	int ret;
+@@ -1151,7 +1151,7 @@ static int pci_6534_upload_firmware(struct comedi_device * dev, int options[])
+ 
+ static int nidio_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int i;
+ 	int ret;
+ 	int n_subdevices;
+diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
+index cca0383fc775..105dab0758f1 100644
+--- a/drivers/staging/comedi/drivers/ni_pcimio.c
++++ b/drivers/staging/comedi/drivers/ni_pcimio.c
+@@ -1529,15 +1529,15 @@ static uint32_t m_series_stc_readl(struct comedi_device * dev, int reg)
+ #include "ni_mio_common.c"
+ 
+ static int pcimio_find_device(struct comedi_device * dev, int bus, int slot);
+-static int pcimio_ai_change(struct comedi_device * dev, comedi_subdevice * s,
++static int pcimio_ai_change(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned long new_size);
+-static int pcimio_ao_change(struct comedi_device * dev, comedi_subdevice * s,
++static int pcimio_ao_change(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned long new_size);
+-static int pcimio_gpct0_change(struct comedi_device * dev, comedi_subdevice * s,
++static int pcimio_gpct0_change(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned long new_size);
+-static int pcimio_gpct1_change(struct comedi_device * dev, comedi_subdevice * s,
++static int pcimio_gpct1_change(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned long new_size);
+-static int pcimio_dio_change(struct comedi_device * dev, comedi_subdevice * s,
++static int pcimio_dio_change(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned long new_size);
+ 
+ static void m_series_init_eeprom_buffer(struct comedi_device * dev)
+@@ -1727,7 +1727,7 @@ static int pcimio_find_device(struct comedi_device * dev, int bus, int slot)
+ 	return -EIO;
+ }
+ 
+-static int pcimio_ai_change(struct comedi_device * dev, comedi_subdevice * s,
++static int pcimio_ai_change(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned long new_size)
+ {
+ 	int ret;
+@@ -1739,7 +1739,7 @@ static int pcimio_ai_change(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int pcimio_ao_change(struct comedi_device * dev, comedi_subdevice * s,
++static int pcimio_ao_change(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned long new_size)
+ {
+ 	int ret;
+@@ -1751,7 +1751,7 @@ static int pcimio_ao_change(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int pcimio_gpct0_change(struct comedi_device * dev, comedi_subdevice * s,
++static int pcimio_gpct0_change(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned long new_size)
+ {
+ 	int ret;
+@@ -1763,7 +1763,7 @@ static int pcimio_gpct0_change(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int pcimio_gpct1_change(struct comedi_device * dev, comedi_subdevice * s,
++static int pcimio_gpct1_change(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned long new_size)
+ {
+ 	int ret;
+@@ -1775,7 +1775,7 @@ static int pcimio_gpct1_change(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int pcimio_dio_change(struct comedi_device * dev, comedi_subdevice * s,
++static int pcimio_dio_change(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned long new_size)
+ {
+ 	int ret;
+diff --git a/drivers/staging/comedi/drivers/ni_tio.h b/drivers/staging/comedi/drivers/ni_tio.h
+index eb611e1fb34b..97a925999ff9 100644
+--- a/drivers/staging/comedi/drivers/ni_tio.h
++++ b/drivers/staging/comedi/drivers/ni_tio.h
+@@ -149,13 +149,13 @@ extern int ni_tio_cmd(struct ni_gpct *counter, comedi_async * async);
+ extern int ni_tio_cmdtest(struct ni_gpct *counter, comedi_cmd * cmd);
+ extern int ni_tio_cancel(struct ni_gpct *counter);
+ extern void ni_tio_handle_interrupt(struct ni_gpct *counter,
+-	comedi_subdevice * s);
++	struct comedi_subdevice * s);
+ extern void ni_tio_set_mite_channel(struct ni_gpct *counter,
+ 	struct mite_channel *mite_chan);
+ extern void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter,
+ 	int *gate_error, int *tc_error, int *perm_stale_data, int *stale_data);
+ 
+-static inline struct ni_gpct *subdev_to_counter(comedi_subdevice * s)
++static inline struct ni_gpct *subdev_to_counter(struct comedi_subdevice * s)
+ {
+ 	return s->private;
+ }
+diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c
+index e28bc754f672..dffaafe9d5fa 100644
+--- a/drivers/staging/comedi/drivers/ni_tiocmd.c
++++ b/drivers/staging/comedi/drivers/ni_tiocmd.c
+@@ -96,7 +96,7 @@ static void ni_tio_configure_dma(struct ni_gpct *counter, short enable,
+ 	}
+ }
+ 
+-static int ni_tio_input_inttrig(struct comedi_device * dev, comedi_subdevice * s,
++static int ni_tio_input_inttrig(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int trignum)
+ {
+ 	unsigned long flags;
+@@ -447,7 +447,7 @@ void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter, int *gate_error,
+ 	}
+ }
+ 
+-void ni_tio_handle_interrupt(struct ni_gpct *counter, comedi_subdevice * s)
++void ni_tio_handle_interrupt(struct ni_gpct *counter, struct comedi_subdevice * s)
+ {
+ 	unsigned gpct_mite_status;
+ 	unsigned long flags;
+diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c
+index 6542b6fd06f2..4261fcc85adf 100644
+--- a/drivers/staging/comedi/drivers/pcl711.c
++++ b/drivers/staging/comedi/drivers/pcl711.c
+@@ -186,7 +186,7 @@ static irqreturn_t pcl711_interrupt(int irq, void *d PT_REGS_ARG)
+ 	int lo, hi;
+ 	int data;
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s = dev->subdevices + 0;
++	struct comedi_subdevice *s = dev->subdevices + 0;
+ 
+ 	if (!dev->attached) {
+ 		comedi_error(dev, "spurious interrupt");
+@@ -240,7 +240,7 @@ static void pcl711_set_changain(struct comedi_device * dev, int chan)
+ 	}
+ }
+ 
+-static int pcl711_ai_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl711_ai_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+@@ -279,7 +279,7 @@ static int pcl711_ai_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int pcl711_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl711_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int tmp;
+@@ -381,7 +381,7 @@ static int pcl711_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int pcl711_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int pcl711_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	int timer1, timer2;
+ 	comedi_cmd *cmd = &s->async->cmd;
+@@ -427,7 +427,7 @@ static int pcl711_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ /*
+    analog output
+ */
+-static int pcl711_ao_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl711_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -445,7 +445,7 @@ static int pcl711_ao_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int pcl711_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl711_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -460,7 +460,7 @@ static int pcl711_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ /* Digital port read - Untested on 8112 */
+-static int pcl711_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl711_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -473,7 +473,7 @@ static int pcl711_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ /* Digital port write - Untested on 8112 */
+-static int pcl711_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl711_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -513,7 +513,7 @@ static int pcl711_attach(struct comedi_device * dev, comedi_devconfig * it)
+ 	int ret;
+ 	unsigned long iobase;
+ 	unsigned int irq;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	/* claim our I/O space */
+ 
+diff --git a/drivers/staging/comedi/drivers/pcl725.c b/drivers/staging/comedi/drivers/pcl725.c
+index afe51b7f4ef1..a2ea3e154bb2 100644
+--- a/drivers/staging/comedi/drivers/pcl725.c
++++ b/drivers/staging/comedi/drivers/pcl725.c
+@@ -31,7 +31,7 @@ static comedi_driver driver_pcl725 = {
+ 
+ COMEDI_INITCLEANUP(driver_pcl725);
+ 
+-static int pcl725_do_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl725_do_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -48,7 +48,7 @@ static int pcl725_do_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int pcl725_di_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl725_di_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -61,7 +61,7 @@ static int pcl725_di_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 
+ static int pcl725_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+ 
+ 	iobase = it->options[0];
+diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c
+index 373c1a7f2368..23e98550c58b 100644
+--- a/drivers/staging/comedi/drivers/pcl726.c
++++ b/drivers/staging/comedi/drivers/pcl726.c
+@@ -168,7 +168,7 @@ typedef struct {
+ } pcl726_private;
+ #define devpriv ((pcl726_private *)dev->private)
+ 
+-static int pcl726_ao_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl726_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int hi, lo;
+@@ -193,7 +193,7 @@ static int pcl726_ao_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int pcl726_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl726_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -205,7 +205,7 @@ static int pcl726_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int pcl726_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl726_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -217,7 +217,7 @@ static int pcl726_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int pcl726_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl726_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -239,7 +239,7 @@ static int pcl726_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 
+ static int pcl726_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+ 	unsigned int iorange;
+ 	int ret, i;
+diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c
+index 63f38738c47a..974f96cfcf45 100644
+--- a/drivers/staging/comedi/drivers/pcl730.c
++++ b/drivers/staging/comedi/drivers/pcl730.c
+@@ -55,7 +55,7 @@ static comedi_driver driver_pcl730 = {
+ 
+ COMEDI_INITCLEANUP(driver_pcl730);
+ 
+-static int pcl730_do_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl730_do_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -77,7 +77,7 @@ static int pcl730_do_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int pcl730_di_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl730_di_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -91,7 +91,7 @@ static int pcl730_di_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 
+ static int pcl730_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+ 	unsigned int iorange;
+ 
+diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
+index 0c8e03d66594..b678dd6dd73f 100644
+--- a/drivers/staging/comedi/drivers/pcl812.c
++++ b/drivers/staging/comedi/drivers/pcl812.c
+@@ -427,13 +427,13 @@ typedef struct {
+ */
+ static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
+ 	unsigned int divisor2);
+-static void setup_range_channel(struct comedi_device * dev, comedi_subdevice * s,
++static void setup_range_channel(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int rangechan, char wait);
+-static int pcl812_ai_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static int pcl812_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ /*
+ ==============================================================================
+ */
+-static int pcl812_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl812_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -467,7 +467,7 @@ static int pcl812_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int acl8216_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int acl8216_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -503,7 +503,7 @@ static int acl8216_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s
+ /*
+ ==============================================================================
+ */
+-static int pcl812_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl812_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -523,7 +523,7 @@ static int pcl812_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s
+ /*
+ ==============================================================================
+ */
+-static int pcl812_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl812_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -539,7 +539,7 @@ static int pcl812_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pcl812_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl812_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -554,7 +554,7 @@ static int pcl812_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pcl812_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl812_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -591,7 +591,7 @@ static void pcl812_cmdtest_out(int e, comedi_cmd * cmd)
+ /*
+ ==============================================================================
+ */
+-static int pcl812_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl812_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -770,7 +770,7 @@ static int pcl812_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pcl812_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int pcl812_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned int divisor1 = 0, divisor2 = 0, i, dma_flags, bytes;
+ 	comedi_cmd *cmd = &s->async->cmd;
+@@ -923,7 +923,7 @@ static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d)
+ 	char err = 1;
+ 	unsigned int mask, timeout;
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s = dev->subdevices + 0;
++	struct comedi_subdevice *s = dev->subdevices + 0;
+ 
+ 	s->async->events = 0;
+ 
+@@ -980,7 +980,7 @@ static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d)
+ /*
+ ==============================================================================
+ */
+-static void transfer_from_dma_buf(struct comedi_device * dev, comedi_subdevice * s,
++static void transfer_from_dma_buf(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	short * ptr, unsigned int bufptr, unsigned int len)
+ {
+ 	unsigned int i;
+@@ -1009,7 +1009,7 @@ static void transfer_from_dma_buf(struct comedi_device * dev, comedi_subdevice *
+ static irqreturn_t interrupt_pcl812_ai_dma(int irq, void *d)
+ {
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s = dev->subdevices + 0;
++	struct comedi_subdevice *s = dev->subdevices + 0;
+ 	unsigned long dma_flags;
+ 	int len, bufptr;
+ 	short *ptr;
+@@ -1075,7 +1075,7 @@ static irqreturn_t interrupt_pcl812(int irq, void *d PT_REGS_ARG)
+ /*
+ ==============================================================================
+ */
+-static int pcl812_ai_poll(struct comedi_device * dev, comedi_subdevice * s)
++static int pcl812_ai_poll(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+ 	unsigned int top1, top2, i;
+@@ -1119,7 +1119,7 @@ static int pcl812_ai_poll(struct comedi_device * dev, comedi_subdevice * s)
+ /*
+ ==============================================================================
+ */
+-static void setup_range_channel(struct comedi_device * dev, comedi_subdevice * s,
++static void setup_range_channel(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int rangechan, char wait)
+ {
+ 	unsigned char chan_reg = CR_CHAN(rangechan);	// normal board
+@@ -1200,7 +1200,7 @@ static void free_resources(struct comedi_device * dev)
+ /*
+ ==============================================================================
+ */
+-static int pcl812_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int pcl812_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ #ifdef PCL812_EXTDEBUG
+ 	rt_printk("pcl812 EDBG: BGN: pcl812_ai_cancel(...)\n");
+@@ -1269,7 +1269,7 @@ static int pcl812_attach(struct comedi_device * dev, comedi_devconfig * it)
+ 	unsigned int irq;
+ 	unsigned int dma;
+ 	unsigned long pages;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int n_subdevices;
+ 
+ 	iobase = it->options[0];
+diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
+index 5d8509f45a08..f1282c68d7ef 100644
+--- a/drivers/staging/comedi/drivers/pcl816.c
++++ b/drivers/staging/comedi/drivers/pcl816.c
+@@ -193,13 +193,13 @@ typedef struct {
+ #endif
+ 	int irq_was_now_closed;	// when IRQ finish, there's stored int816_mode for last interrupt
+ 	int int816_mode;	// who now uses IRQ - 1=AI1 int, 2=AI1 dma, 3=AI3 int, 4AI3 dma
+-	comedi_subdevice *last_int_sub;	// ptr to subdevice which now finish
++	struct comedi_subdevice *last_int_sub;	// ptr to subdevice which now finish
+ 	int ai_act_scan;	// how many scans we finished
+ 	unsigned int ai_act_chanlist[16];	// MUX setting for actual AI operations
+ 	unsigned int ai_act_chanlist_len;	// how long is actual MUX list
+ 	unsigned int ai_act_chanlist_pos;	// actual position in MUX list
+ 	unsigned int ai_poll_ptr;	// how many sampes transfer poll
+-	comedi_subdevice *sub_ai;	// ptr to AI subdevice
++	struct comedi_subdevice *sub_ai;	// ptr to AI subdevice
+ #ifdef unused
+ 	struct timer_list rtc_irq_timer;	// timer for RTC sanity check
+ 	unsigned long rtc_freq;	// RTC int freq
+@@ -210,23 +210,23 @@ typedef struct {
+ ==============================================================================
+ */
+ static int check_and_setup_channel_list(struct comedi_device * dev,
+-	comedi_subdevice * s, unsigned int *chanlist, int chanlen);
+-static int pcl816_ai_cancel(struct comedi_device * dev, comedi_subdevice * s);
++	struct comedi_subdevice * s, unsigned int *chanlist, int chanlen);
++static int pcl816_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
+ 	unsigned int divisor2);
+ #ifdef unused
+ static int set_rtc_irq_bit(unsigned char bit);
+ #endif
+ 
+-static int pcl816_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl816_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int pcl816_ai_cmd(struct comedi_device * dev, comedi_subdevice * s);
++static int pcl816_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
+ 
+ /*
+ ==============================================================================
+    ANALOG INPUT MODE0, 816 cards, slow version
+ */
+-static int pcl816_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl816_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -281,7 +281,7 @@ static int pcl816_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ static irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d)
+ {
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s = dev->subdevices + 0;
++	struct comedi_subdevice *s = dev->subdevices + 0;
+ 	int low, hi;
+ 	int timeout = 50;	/* wait max 50us */
+ 
+@@ -330,7 +330,7 @@ static irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d)
+ ==============================================================================
+    analog input dma mode 1 & 3, 816 cards
+ */
+-static void transfer_from_dma_buf(struct comedi_device * dev, comedi_subdevice * s,
++static void transfer_from_dma_buf(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	short * ptr, unsigned int bufptr, unsigned int len)
+ {
+ 	int i;
+@@ -362,7 +362,7 @@ static void transfer_from_dma_buf(struct comedi_device * dev, comedi_subdevice *
+ static irqreturn_t interrupt_pcl816_ai_mode13_dma(int irq, void *d)
+ {
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s = dev->subdevices + 0;
++	struct comedi_subdevice *s = dev->subdevices + 0;
+ 	int len, bufptr, this_dma_buf;
+ 	unsigned long dma_flags;
+ 	short *ptr;
+@@ -458,7 +458,7 @@ static void pcl816_cmdtest_out(int e, comedi_cmd * cmd)
+ /*
+ ==============================================================================
+ */
+-static int pcl816_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl816_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -593,7 +593,7 @@ static int pcl816_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int pcl816_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int pcl816_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned int divisor1 = 0, divisor2 = 0, dma_flags, bytes, dmairq;
+ 	comedi_cmd *cmd = &s->async->cmd;
+@@ -698,7 +698,7 @@ static int pcl816_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int pcl816_ai_poll(struct comedi_device * dev, comedi_subdevice * s)
++static int pcl816_ai_poll(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+ 	unsigned int top1, top2, i;
+@@ -741,7 +741,7 @@ static int pcl816_ai_poll(struct comedi_device * dev, comedi_subdevice * s)
+ ==============================================================================
+  cancel any mode 1-4 AI
+ */
+-static int pcl816_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int pcl816_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ //  DEBUG(rt_printk("pcl816_ai_cancel()\n");)
+ 
+@@ -861,7 +861,7 @@ start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
+  If it's ok, then program scan/gain logic
+ */
+ static int
+-check_and_setup_channel_list(struct comedi_device * dev, comedi_subdevice * s,
++check_and_setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int *chanlist, int chanlen)
+ {
+ 	unsigned int chansegment[16];
+@@ -1018,7 +1018,7 @@ static int pcl816_attach(struct comedi_device * dev, comedi_devconfig * it)
+ 	unsigned int irq, dma;
+ 	unsigned long pages;
+ 	//int i;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	/* claim our I/O space */
+ 	iobase = it->options[0];
+diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
+index 156788916b50..d202022c1be6 100644
+--- a/drivers/staging/comedi/drivers/pcl818.c
++++ b/drivers/staging/comedi/drivers/pcl818.c
+@@ -339,7 +339,7 @@ typedef struct {
+ 	int irq_blocked;	// 1=IRQ now uses any subdev
+ 	int irq_was_now_closed;	// when IRQ finish, there's stored int818_mode for last interrupt
+ 	int ai_mode;		// who now uses IRQ - 1=AI1 int, 2=AI1 dma, 3=AI3 int, 4AI3 dma
+-	comedi_subdevice *last_int_sub;	// ptr to subdevice which now finish
++	struct comedi_subdevice *last_int_sub;	// ptr to subdevice which now finish
+ 	int ai_act_scan;	// how many scans we finished
+ 	int ai_act_chan;	// actual position in actual scan
+ 	unsigned int act_chanlist[16];	// MUX setting for actual AI operations
+@@ -353,7 +353,7 @@ typedef struct {
+ 	short *ai_data;	// data buffer
+ 	unsigned int ai_timer1;	// timers
+ 	unsigned int ai_timer2;
+-	comedi_subdevice *sub_ai;	// ptr to AI subdevice
++	struct comedi_subdevice *sub_ai;	// ptr to AI subdevice
+ 	unsigned char usefifo;	// 1=use fifo
+ 	unsigned int ao_readback[2];
+ } pcl818_private;
+@@ -368,12 +368,12 @@ static const unsigned int muxonechan[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0
+ /*
+ ==============================================================================
+ */
+-static void setup_channel_list(struct comedi_device * dev, comedi_subdevice * s,
++static void setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int *chanlist, unsigned int n_chan, unsigned int seglen);
+-static int check_channel_list(struct comedi_device * dev, comedi_subdevice * s,
++static int check_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int *chanlist, unsigned int n_chan);
+ 
+-static int pcl818_ai_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static int pcl818_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
+ static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
+ 	unsigned int divisor2);
+ 
+@@ -387,7 +387,7 @@ static int rtc_setfreq_irq(int freq);
+ ==============================================================================
+    ANALOG INPUT MODE0, 818 cards, slow version
+ */
+-static int pcl818_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl818_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -434,7 +434,7 @@ static int pcl818_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+    ANALOG OUTPUT MODE0, 818 cards
+    only one sample per call is supported
+ */
+-static int pcl818_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl818_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -447,7 +447,7 @@ static int pcl818_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int pcl818_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl818_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -470,7 +470,7 @@ static int pcl818_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s
+ 
+    only one sample per call is supported
+ */
+-static int pcl818_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl818_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -488,7 +488,7 @@ static int pcl818_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 
+    only one sample per call is supported
+ */
+-static int pcl818_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl818_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -513,7 +513,7 @@ static int pcl818_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d)
+ {
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s = dev->subdevices + 0;
++	struct comedi_subdevice *s = dev->subdevices + 0;
+ 	int low;
+ 	int timeout = 50;	/* wait max 50us */
+ 
+@@ -566,7 +566,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d)
+ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
+ {
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s = dev->subdevices + 0;
++	struct comedi_subdevice *s = dev->subdevices + 0;
+ 	int i, len, bufptr;
+ 	unsigned long flags;
+ 	short *ptr;
+@@ -641,7 +641,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
+ static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d)
+ {
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s = dev->subdevices + 0;
++	struct comedi_subdevice *s = dev->subdevices + 0;
+ 	unsigned long tmp;
+ 	unsigned int top1, top2, i, bufptr;
+ 	long ofs_dats;
+@@ -739,7 +739,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d)
+ static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
+ {
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s = dev->subdevices + 0;
++	struct comedi_subdevice *s = dev->subdevices + 0;
+ 	int i, len, lo;
+ 
+ 	outb(0, dev->iobase + PCL818_FI_INTCLR);	// clear fifo int request
+@@ -849,7 +849,7 @@ static irqreturn_t interrupt_pcl818(int irq, void *d PT_REGS_ARG)
+ 				   because the card doesn't seem to like being reprogrammed
+ 				   while a DMA transfer is in progress
+ 				 */
+-				comedi_subdevice *s = dev->subdevices + 0;
++				struct comedi_subdevice *s = dev->subdevices + 0;
+ 				devpriv->ai_mode = devpriv->irq_was_now_closed;
+ 				devpriv->irq_was_now_closed = 0;
+ 				devpriv->neverending_ai = 0;
+@@ -871,7 +871,7 @@ static irqreturn_t interrupt_pcl818(int irq, void *d PT_REGS_ARG)
+    ANALOG INPUT MODE 1 or 3 DMA , 818 cards
+ */
+ static void pcl818_ai_mode13dma_int(int mode, struct comedi_device * dev,
+-	comedi_subdevice * s)
++	struct comedi_subdevice * s)
+ {
+ 	unsigned int flags;
+ 	unsigned int bytes;
+@@ -912,7 +912,7 @@ static void pcl818_ai_mode13dma_int(int mode, struct comedi_device * dev,
+    ANALOG INPUT MODE 1 or 3 DMA rtc, 818 cards
+ */
+ static void pcl818_ai_mode13dma_rtc(int mode, struct comedi_device * dev,
+-	comedi_subdevice * s)
++	struct comedi_subdevice * s)
+ {
+ 	unsigned int flags;
+ 	short *pole;
+@@ -953,7 +953,7 @@ static void pcl818_ai_mode13dma_rtc(int mode, struct comedi_device * dev,
+    ANALOG INPUT MODE 1 or 3, 818 cards
+ */
+ static int pcl818_ai_cmd_mode(int mode, struct comedi_device * dev,
+-	comedi_subdevice * s)
++	struct comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	int divisor1, divisor2;
+@@ -1063,7 +1063,7 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device * dev,
+    ANALOG OUTPUT MODE 1 or 3, 818 cards
+ */
+ #ifdef PCL818_MODE13_AO
+-static int pcl818_ao_mode13(int mode, struct comedi_device * dev, comedi_subdevice * s,
++static int pcl818_ao_mode13(int mode, struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_trig * it)
+ {
+ 	int divisor1, divisor2;
+@@ -1116,7 +1116,7 @@ static int pcl818_ao_mode13(int mode, struct comedi_device * dev, comedi_subdevi
+ ==============================================================================
+    ANALOG OUTPUT MODE 1, 818 cards
+ */
+-static int pcl818_ao_mode1(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl818_ao_mode1(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_trig * it)
+ {
+ 	return pcl818_ao_mode13(1, dev, s, it);
+@@ -1126,7 +1126,7 @@ static int pcl818_ao_mode1(struct comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+    ANALOG OUTPUT MODE 3, 818 cards
+ */
+-static int pcl818_ao_mode3(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl818_ao_mode3(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_trig * it)
+ {
+ 	return pcl818_ao_mode13(3, dev, s, it);
+@@ -1158,7 +1158,7 @@ static void start_pacer(struct comedi_device * dev, int mode, unsigned int divis
+  Check if channel list from user is builded correctly
+  If it's ok, then program scan/gain logic
+ */
+-static int check_channel_list(struct comedi_device * dev, comedi_subdevice * s,
++static int check_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int *chanlist, unsigned int n_chan)
+ {
+ 	unsigned int chansegment[16];
+@@ -1214,7 +1214,7 @@ static int check_channel_list(struct comedi_device * dev, comedi_subdevice * s,
+ 	return seglen;
+ }
+ 
+-static void setup_channel_list(struct comedi_device * dev, comedi_subdevice * s,
++static void setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int *chanlist, unsigned int n_chan, unsigned int seglen)
+ {
+ 	int i;
+@@ -1251,7 +1251,7 @@ static int check_single_ended(unsigned int port)
+ /*
+ ==============================================================================
+ */
+-static int ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -1396,7 +1396,7 @@ static int ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	int retval;
+@@ -1435,7 +1435,7 @@ static int ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ ==============================================================================
+  cancel any mode 1-4 AI
+ */
+-static int pcl818_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int pcl818_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	if (devpriv->irq_blocked > 0) {
+ 		rt_printk("pcl818_ai_cancel()\n");
+@@ -1681,7 +1681,7 @@ static int pcl818_attach(struct comedi_device * dev, comedi_devconfig * it)
+ 	unsigned long iobase;
+ 	unsigned int irq, dma;
+ 	unsigned long pages;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	if ((ret = alloc_private(dev, sizeof(pcl818_private))) < 0)
+ 		return ret;	/* Can't alloc mem */
+diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c
+index aa4ecddcf2a1..dedf92c6a149 100644
+--- a/drivers/staging/comedi/drivers/pcm3724.c
++++ b/drivers/staging/comedi/drivers/pcm3724.c
+@@ -115,7 +115,7 @@ static int subdev_8255_cb(int dir, int port, int data, unsigned long arg)
+ 	}
+ }
+ 
+-static int compute_buffer(int config, int devno, comedi_subdevice * s)
++static int compute_buffer(int config, int devno, struct comedi_subdevice * s)
+ {
+ 	/* 1 in io_bits indicates output */
+ 	if (s->io_bits & 0x0000ff) {
+@@ -142,7 +142,7 @@ static int compute_buffer(int config, int devno, comedi_subdevice * s)
+ 	return config;
+ }
+ 
+-static void do_3724_config(struct comedi_device * dev, comedi_subdevice * s,
++static void do_3724_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	int chanspec)
+ {
+ 	int config;
+@@ -176,7 +176,7 @@ static void do_3724_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	outb(config, port_8255_cfg);
+ }
+ 
+-static void enable_chan(struct comedi_device * dev, comedi_subdevice * s, int chanspec)
++static void enable_chan(struct comedi_device * dev, struct comedi_subdevice * s, int chanspec)
+ {
+ 	unsigned int mask;
+ 	int gatecfg;
+@@ -214,7 +214,7 @@ static void enable_chan(struct comedi_device * dev, comedi_subdevice * s, int ch
+ }
+ 
+ /* overriding the 8255 insn config */
+-static int subdev_3724_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int subdev_3724_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int mask;
+diff --git a/drivers/staging/comedi/drivers/pcm3730.c b/drivers/staging/comedi/drivers/pcm3730.c
+index c7d275f1fcbb..e89b3c7ea550 100644
+--- a/drivers/staging/comedi/drivers/pcm3730.c
++++ b/drivers/staging/comedi/drivers/pcm3730.c
+@@ -39,7 +39,7 @@ static comedi_driver driver_pcm3730 = {
+ 
+ COMEDI_INITCLEANUP(driver_pcm3730);
+ 
+-static int pcm3730_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int pcm3730_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -54,7 +54,7 @@ static int pcm3730_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s
+ 	return 2;
+ }
+ 
+-static int pcm3730_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int pcm3730_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -65,7 +65,7 @@ static int pcm3730_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s
+ 
+ static int pcm3730_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+ 
+ 	iobase = it->options[0];
+diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c
+index 08fe79ab59f3..5cb0e59cb216 100644
+--- a/drivers/staging/comedi/drivers/pcmad.c
++++ b/drivers/staging/comedi/drivers/pcmad.c
+@@ -92,7 +92,7 @@ COMEDI_INITCLEANUP(driver_pcmad);
+ 
+ #define TIMEOUT	100
+ 
+-static int pcmad_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int pcmad_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -129,7 +129,7 @@ static int pcmad_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ static int pcmad_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int ret;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+ 
+ 	iobase = it->options[0];
+diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c
+index 6a3a22ed726f..32cfc35daee2 100644
+--- a/drivers/staging/comedi/drivers/pcmda12.c
++++ b/drivers/staging/comedi/drivers/pcmda12.c
+@@ -138,9 +138,9 @@ static comedi_driver driver = {
+       num_names:sizeof(pcmda12_boards) / sizeof(pcmda12_board),
+ };
+ 
+-static int ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ /*
+@@ -151,7 +151,7 @@ static int ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+  */
+ static int pcmda12_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+ 
+ 	iobase = it->options[0];
+@@ -239,7 +239,7 @@ static void zero_chans(struct comedi_device * dev)
+ 	inb(LSB_PORT(0));	/* update chans. */
+ }
+ 
+-static int ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -281,7 +281,7 @@ static int ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+    DAC outputs, which makes all AO channels update simultaneously.
+    This is useful for some control applications, I would imagine.
+ */
+-static int ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
+index 77f62cddddb3..6af8637880c0 100644
+--- a/drivers/staging/comedi/drivers/pcmmio.c
++++ b/drivers/staging/comedi/drivers/pcmmio.c
+@@ -139,14 +139,14 @@ Configuration Options:
+ #define PAGE_ENAB 2
+ #define PAGE_INT_ID 3
+ 
+-typedef int (*comedi_insn_fn_t) (struct comedi_device *, comedi_subdevice *,
++typedef int (*comedi_insn_fn_t) (struct comedi_device *, struct comedi_subdevice *,
+ 	comedi_insn *, unsigned int *);
+ 
+-static int ai_rinsn(struct comedi_device *, comedi_subdevice *, comedi_insn *,
++static int ai_rinsn(struct comedi_device *, struct comedi_subdevice *, comedi_insn *,
+ 	unsigned int *);
+-static int ao_rinsn(struct comedi_device *, comedi_subdevice *, comedi_insn *,
++static int ao_rinsn(struct comedi_device *, struct comedi_subdevice *, comedi_insn *,
+ 	unsigned int *);
+-static int ao_winsn(struct comedi_device *, comedi_subdevice *, comedi_insn *,
++static int ao_winsn(struct comedi_device *, struct comedi_subdevice *, comedi_insn *,
+ 	unsigned int *);
+ 
+ /*
+@@ -295,16 +295,16 @@ static comedi_driver driver = {
+       num_names:sizeof(pcmmio_boards) / sizeof(pcmmio_board),
+ };
+ 
+-static int pcmmio_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int pcmmio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int pcmmio_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int pcmmio_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ static irqreturn_t interrupt_pcmmio(int irq, void *d PT_REGS_ARG);
+-static void pcmmio_stop_intr(struct comedi_device *, comedi_subdevice *);
+-static int pcmmio_cancel(struct comedi_device * dev, comedi_subdevice * s);
+-static int pcmmio_cmd(struct comedi_device * dev, comedi_subdevice * s);
+-static int pcmmio_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static void pcmmio_stop_intr(struct comedi_device *, struct comedi_subdevice *);
++static int pcmmio_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
++static int pcmmio_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
++static int pcmmio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+ 
+ /* some helper functions to deal with specifics of this device's registers */
+@@ -323,7 +323,7 @@ static void unlock_port(struct comedi_device * dev, int asic, int port);
+  */
+ static int pcmmio_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int sdev_no, chans_left, n_dio_subdevs, n_subdevs, port, asic,
+ 		thisasic_chanct = 0;
+ 	unsigned long iobase;
+@@ -550,7 +550,7 @@ static int pcmmio_detach(struct comedi_device * dev)
+  * useful to applications if you implement the insn_bits interface.
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+-static int pcmmio_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int pcmmio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int byte_no;
+@@ -624,7 +624,7 @@ static int pcmmio_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s
+  * configured by a special insn_config instruction.  chanspec
+  * contains the channel to be changed, and data[0] contains the
+  * value COMEDI_INPUT or COMEDI_OUTPUT. */
+-static int pcmmio_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int pcmmio_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec), byte_no = chan / 8, bit_no =
+@@ -815,7 +815,7 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d PT_REGS_ARG)
+ 				spinlock, flags);
+ 
+ 			if (triggered) {
+-				comedi_subdevice *s;
++				struct comedi_subdevice *s;
+ 				/* TODO here: dispatch io lines to subdevs with commands.. */
+ 				printk("PCMMIO DEBUG: got edge detect interrupt %d asic %d which_chans: %06x\n", irq, asic, triggered);
+ 				for (s = dev->subdevices + 2;
+@@ -917,7 +917,7 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static void pcmmio_stop_intr(struct comedi_device * dev, comedi_subdevice * s)
++static void pcmmio_stop_intr(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	int nports, firstport, asic, port;
+ 
+@@ -936,7 +936,7 @@ static void pcmmio_stop_intr(struct comedi_device * dev, comedi_subdevice * s)
+ 	}
+ }
+ 
+-static int pcmmio_start_intr(struct comedi_device * dev, comedi_subdevice * s)
++static int pcmmio_start_intr(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	if (!subpriv->dio.intr.continuous && subpriv->dio.intr.stop_count == 0) {
+ 		/* An empty acquisition! */
+@@ -995,7 +995,7 @@ static int pcmmio_start_intr(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int pcmmio_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int pcmmio_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+ 
+@@ -1011,7 +1011,7 @@ static int pcmmio_cancel(struct comedi_device * dev, comedi_subdevice * s)
+  * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
+  */
+ static int
+-pcmmio_inttrig_start_intr(struct comedi_device * dev, comedi_subdevice * s,
++pcmmio_inttrig_start_intr(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int trignum)
+ {
+ 	unsigned long flags;
+@@ -1037,7 +1037,7 @@ pcmmio_inttrig_start_intr(struct comedi_device * dev, comedi_subdevice * s,
+ /*
+  * 'do_cmd' function for an 'INTERRUPT' subdevice.
+  */
+-static int pcmmio_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int pcmmio_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned long flags;
+@@ -1082,7 +1082,7 @@ static int pcmmio_cmd(struct comedi_device * dev, comedi_subdevice * s)
+  * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
+  */
+ static int
+-pcmmio_cmdtest(struct comedi_device * dev, comedi_subdevice * s, comedi_cmd * cmd)
++pcmmio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	unsigned int tmp;
+@@ -1194,7 +1194,7 @@ static int adc_wait_ready(unsigned long iobase)
+ }
+ 
+ /* All this is for AI and AO */
+-static int ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -1258,7 +1258,7 @@ static int ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -1288,7 +1288,7 @@ static int wait_dac_ready(unsigned long iobase)
+ 	return 1;
+ }
+ 
+-static int ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
+index d2af7082c1e8..6dc42eb047d3 100644
+--- a/drivers/staging/comedi/drivers/pcmuio.c
++++ b/drivers/staging/comedi/drivers/pcmuio.c
+@@ -253,16 +253,16 @@ static comedi_driver driver = {
+       num_names:sizeof(pcmuio_boards) / sizeof(pcmuio_board),
+ };
+ 
+-static int pcmuio_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int pcmuio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int pcmuio_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int pcmuio_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ static irqreturn_t interrupt_pcmuio(int irq, void *d PT_REGS_ARG);
+-static void pcmuio_stop_intr(struct comedi_device *, comedi_subdevice *);
+-static int pcmuio_cancel(struct comedi_device * dev, comedi_subdevice * s);
+-static int pcmuio_cmd(struct comedi_device * dev, comedi_subdevice * s);
+-static int pcmuio_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static void pcmuio_stop_intr(struct comedi_device *, struct comedi_subdevice *);
++static int pcmuio_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
++static int pcmuio_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
++static int pcmuio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+ 
+ /* some helper functions to deal with specifics of this device's registers */
+@@ -281,7 +281,7 @@ static void unlock_port(struct comedi_device * dev, int asic, int port);
+  */
+ static int pcmuio_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int sdev_no, chans_left, n_subdevs, port, asic, thisasic_chanct = 0;
+ 	unsigned long iobase;
+ 	unsigned int irq[MAX_ASICS];
+@@ -474,7 +474,7 @@ static int pcmuio_detach(struct comedi_device * dev)
+  * useful to applications if you implement the insn_bits interface.
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+-static int pcmuio_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int pcmuio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int byte_no;
+@@ -548,7 +548,7 @@ static int pcmuio_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s
+  * configured by a special insn_config instruction.  chanspec
+  * contains the channel to be changed, and data[0] contains the
+  * value COMEDI_INPUT or COMEDI_OUTPUT. */
+-static int pcmuio_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int pcmuio_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec), byte_no = chan / 8, bit_no =
+@@ -738,7 +738,7 @@ static irqreturn_t interrupt_pcmuio(int irq, void *d PT_REGS_ARG)
+ 				spinlock, flags);
+ 
+ 			if (triggered) {
+-				comedi_subdevice *s;
++				struct comedi_subdevice *s;
+ 				/* TODO here: dispatch io lines to subdevs with commands.. */
+ 				printk("PCMUIO DEBUG: got edge detect interrupt %d asic %d which_chans: %06x\n", irq, asic, triggered);
+ 				for (s = dev->subdevices;
+@@ -837,7 +837,7 @@ static irqreturn_t interrupt_pcmuio(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static void pcmuio_stop_intr(struct comedi_device * dev, comedi_subdevice * s)
++static void pcmuio_stop_intr(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	int nports, firstport, asic, port;
+ 
+@@ -856,7 +856,7 @@ static void pcmuio_stop_intr(struct comedi_device * dev, comedi_subdevice * s)
+ 	}
+ }
+ 
+-static int pcmuio_start_intr(struct comedi_device * dev, comedi_subdevice * s)
++static int pcmuio_start_intr(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	if (!subpriv->intr.continuous && subpriv->intr.stop_count == 0) {
+ 		/* An empty acquisition! */
+@@ -905,7 +905,7 @@ static int pcmuio_start_intr(struct comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int pcmuio_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int pcmuio_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+ 
+@@ -921,7 +921,7 @@ static int pcmuio_cancel(struct comedi_device * dev, comedi_subdevice * s)
+  * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
+  */
+ static int
+-pcmuio_inttrig_start_intr(struct comedi_device * dev, comedi_subdevice * s,
++pcmuio_inttrig_start_intr(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	unsigned int trignum)
+ {
+ 	unsigned long flags;
+@@ -947,7 +947,7 @@ pcmuio_inttrig_start_intr(struct comedi_device * dev, comedi_subdevice * s,
+ /*
+  * 'do_cmd' function for an 'INTERRUPT' subdevice.
+  */
+-static int pcmuio_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int pcmuio_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned long flags;
+@@ -992,7 +992,7 @@ static int pcmuio_cmd(struct comedi_device * dev, comedi_subdevice * s)
+  * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
+  */
+ static int
+-pcmuio_cmdtest(struct comedi_device * dev, comedi_subdevice * s, comedi_cmd * cmd)
++pcmuio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	unsigned int tmp;
+diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c
+index 9cd1472a9120..5fc566f4aaa3 100644
+--- a/drivers/staging/comedi/drivers/poc.c
++++ b/drivers/staging/comedi/drivers/poc.c
+@@ -43,14 +43,14 @@ Configuration options:
+ 
+ static int poc_attach(struct comedi_device * dev, comedi_devconfig * it);
+ static int poc_detach(struct comedi_device * dev);
+-static int readback_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int readback_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int dac02_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int dac02_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int pcl733_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl733_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int pcl734_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl734_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ struct boarddef_struct {
+@@ -60,11 +60,11 @@ struct boarddef_struct {
+ 	int type;
+ 	int n_chan;
+ 	int n_bits;
+-	int (*winsn) (struct comedi_device *, comedi_subdevice *, comedi_insn *,
++	int (*winsn) (struct comedi_device *, struct comedi_subdevice *, comedi_insn *,
+ 		unsigned int *);
+-	int (*rinsn) (struct comedi_device *, comedi_subdevice *, comedi_insn *,
++	int (*rinsn) (struct comedi_device *, struct comedi_subdevice *, comedi_insn *,
+ 		unsigned int *);
+-	int (*insnbits) (struct comedi_device *, comedi_subdevice *, comedi_insn *,
++	int (*insnbits) (struct comedi_device *, struct comedi_subdevice *, comedi_insn *,
+ 		unsigned int *);
+ 	const comedi_lrange *range;
+ };
+@@ -115,7 +115,7 @@ static comedi_driver driver_poc = {
+ 
+ static int poc_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned long iobase;
+ 	unsigned int iosize;
+ 
+@@ -170,7 +170,7 @@ static int poc_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int readback_insn(struct comedi_device * dev, comedi_subdevice * s,
++static int readback_insn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan;
+@@ -185,7 +185,7 @@ static int readback_insn(struct comedi_device * dev, comedi_subdevice * s,
+ #define DAC02_LSB(a)	(2 * a)
+ #define DAC02_MSB(a)	(2 * a + 1)
+ 
+-static int dac02_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int dac02_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int temp;
+@@ -208,7 +208,7 @@ static int dac02_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int pcl733_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl733_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -222,7 +222,7 @@ static int pcl733_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int pcl734_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int pcl734_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+index cc6a6daa1f9a..a3bfa6465b56 100644
+--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
++++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+@@ -87,7 +87,7 @@ typedef struct local_info_t {
+ 	struct semaphore eos;
+ 
+ 	struct comedi_device *dev;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int count;
+ } local_info_t;
+ 
+@@ -234,7 +234,7 @@ static void hex_dump(char *str, void *ptr, int len)
+ 
+ /* Cancel a running acquisition */
+ 
+-static int daqp_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
++static int daqp_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	local_info_t *local = (local_info_t *) s->private;
+ 
+@@ -266,7 +266,7 @@ static void daqp_interrupt(int irq, void *dev_id PT_REGS_ARG)
+ {
+ 	local_info_t *local = (local_info_t *) dev_id;
+ 	struct comedi_device *dev;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int loop_limit = 10000;
+ 	int status;
+ 
+@@ -361,7 +361,7 @@ static void daqp_interrupt(int irq, void *dev_id PT_REGS_ARG)
+ 
+ /* One-shot analog data acquisition routine */
+ 
+-static int daqp_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int daqp_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	local_info_t *local = (local_info_t *) s->private;
+@@ -467,7 +467,7 @@ static int daqp_ns_to_timer(unsigned int *ns, int round)
+  * the command passes.
+  */
+ 
+-static int daqp_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int daqp_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -593,7 +593,7 @@ static int daqp_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int daqp_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
++static int daqp_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
+ {
+ 	local_info_t *local = (local_info_t *) s->private;
+ 	comedi_cmd *cmd = &s->async->cmd;
+@@ -793,7 +793,7 @@ static int daqp_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ 
+ /* Single-shot analog output routine */
+ 
+-static int daqp_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
++static int daqp_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	local_info_t *local = (local_info_t *) s->private;
+@@ -820,7 +820,7 @@ static int daqp_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+ 
+ /* Digital input routine */
+ 
+-static int daqp_di_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int daqp_di_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	local_info_t *local = (local_info_t *) s->private;
+@@ -836,7 +836,7 @@ static int daqp_di_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 
+ /* Digital output routine */
+ 
+-static int daqp_do_insn_write(struct comedi_device * dev, comedi_subdevice * s,
++static int daqp_do_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	local_info_t *local = (local_info_t *) s->private;
+@@ -862,7 +862,7 @@ static int daqp_attach(struct comedi_device * dev, comedi_devconfig * it)
+ 	local_info_t *local = dev_table[it->options[0]];
+ 	tuple_t tuple;
+ 	int i;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	if (it->options[0] < 0 || it->options[0] >= MAX_DEV || !local) {
+ 		printk("comedi%d: No such daqp device %d\n",
+diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
+index f4b1fc6fa488..405c2040a881 100644
+--- a/drivers/staging/comedi/drivers/rtd520.c
++++ b/drivers/staging/comedi/drivers/rtd520.c
+@@ -690,21 +690,21 @@ static comedi_driver rtd520Driver = {
+       detach : rtd_detach,
+ };
+ 
+-static int rtd_ai_rinsn(struct comedi_device *dev, comedi_subdevice *s,
++static int rtd_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+-static int rtd_ao_winsn(struct comedi_device *dev, comedi_subdevice *s,
++static int rtd_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+-static int rtd_ao_rinsn(struct comedi_device *dev, comedi_subdevice *s,
++static int rtd_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+-static int rtd_dio_insn_bits(struct comedi_device *dev, comedi_subdevice *s,
++static int rtd_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+-static int rtd_dio_insn_config(struct comedi_device *dev, comedi_subdevice *s,
++static int rtd_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+-static int rtd_ai_cmdtest(struct comedi_device *dev, comedi_subdevice *s,
++static int rtd_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_cmd *cmd);
+-static int rtd_ai_cmd(struct comedi_device *dev, comedi_subdevice *s);
+-static int rtd_ai_cancel(struct comedi_device *dev, comedi_subdevice *s);
+-/* static int rtd_ai_poll (struct comedi_device *dev,comedi_subdevice *s); */
++static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
++static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
++/* static int rtd_ai_poll (struct comedi_device *dev,struct comedi_subdevice *s); */
+ static int rtd_ns_to_timer(unsigned int *ns, int roundMode);
+ static irqreturn_t rtd_interrupt(int irq, void *d PT_REGS_ARG);
+ static int rtd520_probe_fifo_depth(struct comedi_device *dev);
+@@ -717,7 +717,7 @@ static int rtd520_probe_fifo_depth(struct comedi_device *dev);
+  */
+ static int rtd_attach(struct comedi_device *dev, comedi_devconfig *it)
+ {				/* board name and options flags */
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	struct pci_dev *pcidev;
+ 	int ret;
+ 	resource_size_t physLas0;	/* configuation */
+@@ -1255,7 +1255,7 @@ static int rtd520_probe_fifo_depth(struct comedi_device *dev)
+   select, delay, then read.
+  */
+ static int rtd_ai_rinsn(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, ii;
+ 	int stat;
+@@ -1307,7 +1307,7 @@ static int rtd_ai_rinsn(struct comedi_device *dev,
+ 
+   The manual claims that we can do a lword read, but it doesn't work here.
+ */
+-static int ai_read_n(struct comedi_device *dev, comedi_subdevice *s, int count)
++static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s, int count)
+ {
+ 	int ii;
+ 
+@@ -1346,7 +1346,7 @@ static int ai_read_n(struct comedi_device *dev, comedi_subdevice *s, int count)
+ /*
+   unknown amout of data is waiting in fifo.
+ */
+-static int ai_read_dregs(struct comedi_device *dev, comedi_subdevice *s)
++static int ai_read_dregs(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	while (RtdFifoStatus(dev) & FS_ADC_NOT_EMPTY) {	/* 1 -> not empty */
+ 		short sample;
+@@ -1434,7 +1434,7 @@ void abort_dma(struct comedi_device *dev, unsigned int channel)
+   Process what is in the DMA transfer buffer and pass to comedi
+   Note: this is not re-entrant
+ */
+-static int ai_process_dma(struct comedi_device *dev, comedi_subdevice *s)
++static int ai_process_dma(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	int ii, n;
+ 	s16 *dp;
+@@ -1500,7 +1500,7 @@ static irqreturn_t rtd_interrupt(int irq,	/* interrupt number (ignored) */
+ 	struct comedi_device *dev = d;	/* must be called "dev" for devpriv */
+ 	u16 status;
+ 	u16 fifoStatus;
+-	comedi_subdevice *s = dev->subdevices + 0;	/* analog in subdevice */
++	struct comedi_subdevice *s = dev->subdevices + 0;	/* analog in subdevice */
+ 
+ 	if (!dev->attached) {
+ 		return IRQ_NONE;
+@@ -1648,7 +1648,7 @@ static irqreturn_t rtd_interrupt(int irq,	/* interrupt number (ignored) */
+ /*
+   return the number of samples available
+ */
+-static int rtd_ai_poll(struct comedi_device *dev, comedi_subdevice *s)
++static int rtd_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	/* TODO: This needs to mask interrupts, read_dregs, and then re-enable */
+ 	/* Not sure what to do if DMA is active */
+@@ -1666,7 +1666,7 @@ static int rtd_ai_poll(struct comedi_device *dev, comedi_subdevice *s)
+ */
+ 
+ static int rtd_ai_cmdtest(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_cmd *cmd)
++	struct comedi_subdevice *s, comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -1870,7 +1870,7 @@ static int rtd_ai_cmdtest(struct comedi_device *dev,
+   This is usually done by an interrupt handler.
+   Userland gets to the data using read calls.
+ */
+-static int rtd_ai_cmd(struct comedi_device *dev, comedi_subdevice *s)
++static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	int timer;
+@@ -2067,7 +2067,7 @@ static int rtd_ai_cmd(struct comedi_device *dev, comedi_subdevice *s)
+ /*
+   Stop a running data aquisition.
+ */
+-static int rtd_ai_cancel(struct comedi_device *dev, comedi_subdevice *s)
++static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	u16 status;
+ 
+@@ -2136,7 +2136,7 @@ static int rtd_ns_to_timer(unsigned int *ns, int round_mode)
+   Output one (or more) analog values to a single port as fast as possible.
+ */
+ static int rtd_ao_winsn(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -2191,7 +2191,7 @@ static int rtd_ao_winsn(struct comedi_device *dev,
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+ static int rtd_ao_rinsn(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -2214,7 +2214,7 @@ static int rtd_ao_rinsn(struct comedi_device *dev,
+  * comedi core can convert between insn_bits and insn_read/write
+  */
+ static int rtd_dio_insn_bits(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -2241,7 +2241,7 @@ static int rtd_dio_insn_bits(struct comedi_device *dev,
+   Configure one bit on a IO port as Input or Output (hence the name :-).
+ */
+ static int rtd_dio_insn_config(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c
+index 8ec384528181..3525813b9bf3 100644
+--- a/drivers/staging/comedi/drivers/rti800.c
++++ b/drivers/staging/comedi/drivers/rti800.c
+@@ -178,7 +178,7 @@ static irqreturn_t rti800_interrupt(int irq, void *dev PT_REGS_ARG)
+ // settling delay times in usec for different gains
+ static const int gaindelay[] = { 10, 20, 40, 80 };
+ 
+-static int rti800_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int rti800_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, t;
+@@ -231,7 +231,7 @@ static int rti800_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int rti800_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int rti800_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -243,7 +243,7 @@ static int rti800_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int rti800_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
++static int rti800_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -263,7 +263,7 @@ static int rti800_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s
+ 	return i;
+ }
+ 
+-static int rti800_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int rti800_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -272,7 +272,7 @@ static int rti800_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int rti800_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int rti800_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -312,7 +312,7 @@ static int rti800_attach(struct comedi_device * dev, comedi_devconfig * it)
+ 	unsigned int irq;
+ 	unsigned long iobase;
+ 	int ret;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	iobase = it->options[0];
+ 	printk("comedi%d: rti800: 0x%04lx ", dev->minor, iobase);
+diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c
+index 843fce9056c8..0985c858cb2f 100644
+--- a/drivers/staging/comedi/drivers/rti802.c
++++ b/drivers/staging/comedi/drivers/rti802.c
+@@ -68,7 +68,7 @@ typedef struct {
+ 
+ #define devpriv ((rti802_private *)dev->private)
+ 
+-static int rti802_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
++static int rti802_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -79,7 +79,7 @@ static int rti802_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int rti802_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
++static int rti802_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, d;
+@@ -98,7 +98,7 @@ static int rti802_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s
+ 
+ static int rti802_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int i;
+ 	unsigned long iobase;
+ 
+diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
+index 7e066a0263cc..51ff5a7e5639 100644
+--- a/drivers/staging/comedi/drivers/s526.c
++++ b/drivers/staging/comedi/drivers/s526.c
+@@ -245,23 +245,23 @@ static comedi_driver driver_s526 = {
+       num_names:sizeof(s526_boards) / sizeof(s526_board),
+ };
+ 
+-static int s526_gpct_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int s526_gpct_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int s526_gpct_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int s526_gpct_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int s526_gpct_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int s526_gpct_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int s526_ai_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int s526_ai_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int s526_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int s526_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int s526_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int s526_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int s526_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int s526_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int s526_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int s526_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int s526_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int s526_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ /*
+@@ -272,7 +272,7 @@ static int s526_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s
+  */
+ static int s526_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int iobase;
+ 	int i, n;
+ //      short value;
+@@ -476,7 +476,7 @@ static int s526_detach(struct comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int s526_gpct_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int s526_gpct_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;			// counts the Data
+@@ -500,7 +500,7 @@ static int s526_gpct_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int s526_gpct_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int s526_gpct_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int subdev_channel = CR_CHAN(insn->chanspec);	// Unpack chanspec
+@@ -725,7 +725,7 @@ static int s526_gpct_insn_config(struct comedi_device * dev, comedi_subdevice *
+ 	return insn->n;
+ }
+ 
+-static int s526_gpct_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int s526_gpct_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int subdev_channel = CR_CHAN(insn->chanspec);	// Unpack chanspec
+@@ -784,7 +784,7 @@ static int s526_gpct_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ #define ISR_ADC_DONE 0x4
+-static int s526_ai_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int s526_ai_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int result = -EINVAL;
+@@ -817,7 +817,7 @@ static int s526_ai_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+  * "instructions" read/write data in "one-shot" or "software-triggered"
+  * mode.
+  */
+-static int s526_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int s526_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i;
+@@ -867,7 +867,7 @@ static int s526_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int s526_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int s526_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -896,7 +896,7 @@ static int s526_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+-static int s526_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int s526_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -913,7 +913,7 @@ static int s526_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+  * useful to applications if you implement the insn_bits interface.
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+-static int s526_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int s526_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -938,7 +938,7 @@ static int s526_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int s526_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int s526_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
+index 7a9e4544f00a..4bba963cd537 100644
+--- a/drivers/staging/comedi/drivers/s626.c
++++ b/drivers/staging/comedi/drivers/s626.c
+@@ -222,40 +222,40 @@ static struct dio_private *dio_private_word[]={
+ COMEDI_PCI_INITCLEANUP_NOMODULE(driver_s626, s626_pci_table);
+ 
+ /* ioctl routines */
+-static int s626_ai_insn_config(struct comedi_device *dev, comedi_subdevice *s,
++static int s626_ai_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+-/* static int s626_ai_rinsn(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data); */
+-static int s626_ai_insn_read(struct comedi_device *dev, comedi_subdevice *s,
++/* static int s626_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data); */
++static int s626_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+-static int s626_ai_cmd(struct comedi_device *dev, comedi_subdevice *s);
+-static int s626_ai_cmdtest(struct comedi_device *dev, comedi_subdevice *s,
++static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
++static int s626_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_cmd *cmd);
+-static int s626_ai_cancel(struct comedi_device *dev, comedi_subdevice *s);
+-static int s626_ao_winsn(struct comedi_device *dev, comedi_subdevice *s,
++static int s626_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
++static int s626_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+-static int s626_ao_rinsn(struct comedi_device *dev, comedi_subdevice *s,
++static int s626_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+-static int s626_dio_insn_bits(struct comedi_device *dev, comedi_subdevice *s,
++static int s626_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+-static int s626_dio_insn_config(struct comedi_device *dev, comedi_subdevice *s,
++static int s626_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+ static int s626_dio_set_irq(struct comedi_device *dev, unsigned int chan);
+ static int s626_dio_reset_irq(struct comedi_device *dev, unsigned int gruop,
+ 	unsigned int mask);
+ static int s626_dio_clear_irq(struct comedi_device *dev);
+-static int s626_enc_insn_config(struct comedi_device *dev, comedi_subdevice *s,
++static int s626_enc_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+-static int s626_enc_insn_read(struct comedi_device *dev, comedi_subdevice *s,
++static int s626_enc_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+-static int s626_enc_insn_write(struct comedi_device *dev, comedi_subdevice *s,
++static int s626_enc_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+ static int s626_ns_to_timer(int *nanosec, int round_mode);
+ static int s626_ai_load_polllist(uint8_t *ppl, comedi_cmd *cmd);
+-static int s626_ai_inttrig(struct comedi_device *dev, comedi_subdevice *s,
++static int s626_ai_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int trignum);
+ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG);
+ static unsigned int s626_ai_reg_to_uint(int data);
+-/* static unsigned int s626_uint_to_reg(comedi_subdevice *s, int data); */
++/* static unsigned int s626_uint_to_reg(struct comedi_subdevice *s, int data); */
+ 
+ /* end ioctl routines */
+ 
+@@ -497,7 +497,7 @@ static int s626_attach(struct comedi_device *dev, comedi_devconfig *it)
+ 	int ret;
+ 	resource_size_t resourceStart;
+ 	dma_addr_t appdma;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	struct pci_dev *pdev;
+ 
+ 	if (alloc_private(dev, sizeof(struct s626_private)) < 0)
+@@ -964,14 +964,14 @@ static unsigned int s626_ai_reg_to_uint(int data)
+ 	return tempdata;
+ }
+ 
+-/* static unsigned int s626_uint_to_reg(comedi_subdevice *s, int data){ */
++/* static unsigned int s626_uint_to_reg(struct comedi_subdevice *s, int data){ */
+ /*   return 0; */
+ /* } */
+ 
+ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG)
+ {
+ 	struct comedi_device *dev = d;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	comedi_cmd *cmd;
+ 	struct enc_private *k;
+ 	unsigned long flags;
+@@ -1503,14 +1503,14 @@ void ResetADC(struct comedi_device *dev, uint8_t *ppl)
+ }
+ 
+ /* TO COMPLETE, IF NECESSARY */
+-static int s626_ai_insn_config(struct comedi_device *dev, comedi_subdevice *s,
++static int s626_ai_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	return -EINVAL;
+ }
+ 
+-/* static int s626_ai_rinsn(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data) */
++/* static int s626_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,comedi_insn *insn,unsigned int *data) */
+ /* { */
+ /*   register uint8_t	i; */
+ /*   register int32_t	*readaddr; */
+@@ -1540,7 +1540,7 @@ static int s626_ai_insn_config(struct comedi_device *dev, comedi_subdevice *s,
+ /*   return i; */
+ /* } */
+ 
+-static int s626_ai_insn_read(struct comedi_device *dev, comedi_subdevice *s,
++static int s626_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 	uint16_t chan = CR_CHAN(insn->chanspec);
+@@ -1654,7 +1654,7 @@ static int s626_ai_load_polllist(uint8_t *ppl, comedi_cmd *cmd)
+ 	return n;
+ }
+ 
+-static int s626_ai_inttrig(struct comedi_device *dev, comedi_subdevice *s,
++static int s626_ai_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	unsigned int trignum)
+ {
+ 	if (trignum != 0)
+@@ -1673,7 +1673,7 @@ static int s626_ai_inttrig(struct comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ /*  TO COMPLETE  */
+-static int s626_ai_cmd(struct comedi_device *dev, comedi_subdevice *s)
++static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 
+ 	uint8_t ppl[16];
+@@ -1819,7 +1819,7 @@ static int s626_ai_cmd(struct comedi_device *dev, comedi_subdevice *s)
+ 	return 0;
+ }
+ 
+-static int s626_ai_cmdtest(struct comedi_device *dev, comedi_subdevice *s,
++static int s626_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_cmd *cmd)
+ {
+ 	int err = 0;
+@@ -2004,7 +2004,7 @@ static int s626_ai_cmdtest(struct comedi_device *dev, comedi_subdevice *s,
+ 	return 0;
+ }
+ 
+-static int s626_ai_cancel(struct comedi_device *dev, comedi_subdevice *s)
++static int s626_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	/*  Stop RPS program in case it is currently running. */
+ 	MC_DISABLE(P_MC1, MC1_ERPS1);
+@@ -2045,7 +2045,7 @@ static int s626_ns_to_timer(int *nanosec, int round_mode)
+ 	return divider - 1;
+ }
+ 
+-static int s626_ao_winsn(struct comedi_device *dev, comedi_subdevice *s,
++static int s626_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 
+@@ -2064,7 +2064,7 @@ static int s626_ao_winsn(struct comedi_device *dev, comedi_subdevice *s,
+ 	return i;
+ }
+ 
+-static int s626_ao_rinsn(struct comedi_device *dev, comedi_subdevice *s,
++static int s626_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+@@ -2084,7 +2084,7 @@ static int s626_ao_rinsn(struct comedi_device *dev, comedi_subdevice *s,
+ static void s626_dio_init(struct comedi_device *dev)
+ {
+ 	uint16_t group;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	/*  Prepare to treat writes to WRCapSel as capture disables. */
+ 	DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP);
+@@ -2110,7 +2110,7 @@ static void s626_dio_init(struct comedi_device *dev)
+  * This allows packed reading/writing of the DIO channels.  The comedi
+  * core can convert between insn_bits and insn_read/write */
+ 
+-static int s626_dio_insn_bits(struct comedi_device *dev, comedi_subdevice *s,
++static int s626_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 
+@@ -2146,7 +2146,7 @@ static int s626_dio_insn_bits(struct comedi_device *dev, comedi_subdevice *s,
+ 	return 2;
+ }
+ 
+-static int s626_dio_insn_config(struct comedi_device *dev, comedi_subdevice *s,
++static int s626_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 
+@@ -2251,7 +2251,7 @@ static int s626_dio_clear_irq(struct comedi_device *dev)
+ /* Now this function initializes the value of the counter (data[0])
+    and set the subdevice. To complete with trigger and interrupt
+    configuration */
+-static int s626_enc_insn_config(struct comedi_device *dev, comedi_subdevice *s,
++static int s626_enc_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 	uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) |	/*  Preload upon */
+@@ -2281,7 +2281,7 @@ static int s626_enc_insn_config(struct comedi_device *dev, comedi_subdevice *s,
+ 	return insn->n;
+ }
+ 
+-static int s626_enc_insn_read(struct comedi_device *dev, comedi_subdevice *s,
++static int s626_enc_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 
+@@ -2299,7 +2299,7 @@ static int s626_enc_insn_read(struct comedi_device *dev, comedi_subdevice *s,
+ 	return n;
+ }
+ 
+-static int s626_enc_insn_write(struct comedi_device *dev, comedi_subdevice *s,
++static int s626_enc_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 
+diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
+index d63b657ec0d5..c23a4322c1a8 100644
+--- a/drivers/staging/comedi/drivers/serial2002.c
++++ b/drivers/staging/comedi/drivers/serial2002.c
+@@ -97,15 +97,15 @@ comedi_driver driver_serial2002 = {
+       num_names:sizeof(serial2002_boards) / sizeof(serial2002_board),
+ };
+ 
+-static int serial2002_di_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int serial2002_di_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int serial2002_do_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int serial2002_do_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int serial2002_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int serial2002_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int serial2002_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int serial2002_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int serial2002_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int serial2002_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ struct serial_data {
+@@ -597,7 +597,7 @@ static void serial_2002_open(struct comedi_device * dev)
+ 				break;
+ 			}
+ 			if (c) {
+-				comedi_subdevice *s;
++				struct comedi_subdevice *s;
+ 				const comedi_lrange **range_table_list = NULL;
+ 				unsigned int *maxdata_list;
+ 				int j, chan;
+@@ -660,7 +660,7 @@ static void serial_2002_close(struct comedi_device * dev)
+ 	}
+ }
+ 
+-static int serial2002_di_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int serial2002_di_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -682,7 +682,7 @@ static int serial2002_di_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int serial2002_do_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int serial2002_do_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -700,7 +700,7 @@ static int serial2002_do_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int serial2002_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int serial2002_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -722,7 +722,7 @@ static int serial2002_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int serial2002_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int serial2002_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -741,7 +741,7 @@ static int serial2002_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int serial2002_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int serial2002_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -754,7 +754,7 @@ static int serial2002_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int serial2002_ei_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int serial2002_ei_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -778,7 +778,7 @@ static int serial2002_ei_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 
+ static int serial2002_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	printk("comedi%d: serial2002: ", dev->minor);
+ 	dev->board_name = thisboard->name;
+@@ -845,7 +845,7 @@ static int serial2002_attach(struct comedi_device * dev, comedi_devconfig * it)
+ 
+ static int serial2002_detach(struct comedi_device * dev)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int i;
+ 
+ 	printk("comedi%d: serial2002: remove\n", dev->minor);
+diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c
+index 8252349e3af9..13b14454f59a 100644
+--- a/drivers/staging/comedi/drivers/skel.c
++++ b/drivers/staging/comedi/drivers/skel.c
+@@ -181,17 +181,17 @@ static comedi_driver driver_skel = {
+       num_names:sizeof(skel_boards) / sizeof(skel_board),
+ };
+ 
+-static int skel_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int skel_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int skel_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int skel_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int skel_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int skel_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int skel_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int skel_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int skel_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int skel_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int skel_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int skel_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+ static int skel_ns_to_timer(unsigned int *ns, int round);
+ 
+@@ -203,7 +203,7 @@ static int skel_ns_to_timer(unsigned int *ns, int round);
+  */
+ static int skel_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	printk("comedi%d: skel: ", dev->minor);
+ 
+@@ -298,7 +298,7 @@ static int skel_detach(struct comedi_device * dev)
+  * "instructions" read/write data in "one-shot" or "software-triggered"
+  * mode.
+  */
+-static int skel_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int skel_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i;
+@@ -346,7 +346,7 @@ static int skel_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int skel_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
++static int skel_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -515,7 +515,7 @@ static int skel_ns_to_timer(unsigned int *ns, int round)
+ 	return *ns;
+ }
+ 
+-static int skel_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
++static int skel_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -536,7 +536,7 @@ static int skel_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+-static int skel_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
++static int skel_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -553,7 +553,7 @@ static int skel_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+  * useful to applications if you implement the insn_bits interface.
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+-static int skel_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
++static int skel_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -578,7 +578,7 @@ static int skel_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int skel_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
++static int skel_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c
+index 2cb08849a6bb..db31c2066aec 100644
+--- a/drivers/staging/comedi/drivers/ssv_dnp.c
++++ b/drivers/staging/comedi/drivers/ssv_dnp.c
+@@ -104,10 +104,10 @@ static comedi_driver driver_dnp = {
+ COMEDI_INITCLEANUP(driver_dnp);
+ 
+ static int dnp_dio_insn_bits(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+ static int dnp_dio_insn_config(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+ /* ------------------------------------------------------------------------- */
+ /* Attach is called by comedi core to configure the driver for a particular  */
+@@ -118,7 +118,7 @@ static int dnp_dio_insn_config(struct comedi_device * dev,
+ static int dnp_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	printk("comedi%d: dnp: ", dev->minor);
+ 
+@@ -201,7 +201,7 @@ static int dnp_detach(struct comedi_device * dev)
+ /* ------------------------------------------------------------------------- */
+ 
+ static int dnp_dio_insn_bits(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	if (insn->n != 2)
+@@ -251,7 +251,7 @@ static int dnp_dio_insn_bits(struct comedi_device * dev,
+ /* ------------------------------------------------------------------------- */
+ 
+ static int dnp_dio_insn_config(struct comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
++	struct comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	u8 register_buffer;
+diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c
+index 90947cf1dbc4..34c44718b522 100644
+--- a/drivers/staging/comedi/drivers/unioxx5.c
++++ b/drivers/staging/comedi/drivers/unioxx5.c
+@@ -81,14 +81,14 @@ typedef struct unioxx5_subd_priv {
+ } unioxx5_subd_priv;
+ 
+ static int unioxx5_attach(struct comedi_device * dev, comedi_devconfig * it);
+-static int unioxx5_subdev_write(struct comedi_device * dev, comedi_subdevice * subdev,
++static int unioxx5_subdev_write(struct comedi_device * dev, struct comedi_subdevice * subdev,
+ 	comedi_insn * insn, unsigned int * data);
+-static int unioxx5_subdev_read(struct comedi_device * dev, comedi_subdevice * subdev,
++static int unioxx5_subdev_read(struct comedi_device * dev, struct comedi_subdevice * subdev,
+ 	comedi_insn * insn, unsigned int * data);
+-static int unioxx5_insn_config(struct comedi_device * dev, comedi_subdevice * subdev,
++static int unioxx5_insn_config(struct comedi_device * dev, struct comedi_subdevice * subdev,
+ 	comedi_insn * insn, unsigned int * data);
+ static int unioxx5_detach(struct comedi_device * dev);
+-static int __unioxx5_subdev_init(comedi_subdevice * subdev, int subdev_iobase,
++static int __unioxx5_subdev_init(struct comedi_subdevice * subdev, int subdev_iobase,
+ 	int minor);
+ static int __unioxx5_digital_write(unioxx5_subd_priv * usp, unsigned int * data,
+ 	int channel, int minor);
+@@ -156,7 +156,7 @@ static int unioxx5_attach(struct comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int unioxx5_subdev_read(struct comedi_device * dev, comedi_subdevice * subdev,
++static int unioxx5_subdev_read(struct comedi_device * dev, struct comedi_subdevice * subdev,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unioxx5_subd_priv *usp = subdev->private;
+@@ -176,7 +176,7 @@ static int unioxx5_subdev_read(struct comedi_device * dev, comedi_subdevice * su
+ 	return 1;
+ }
+ 
+-static int unioxx5_subdev_write(struct comedi_device * dev, comedi_subdevice * subdev,
++static int unioxx5_subdev_write(struct comedi_device * dev, struct comedi_subdevice * subdev,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unioxx5_subd_priv *usp = subdev->private;
+@@ -197,7 +197,7 @@ static int unioxx5_subdev_write(struct comedi_device * dev, comedi_subdevice * s
+ }
+ 
+ /* for digital modules only */
+-static int unioxx5_insn_config(struct comedi_device * dev, comedi_subdevice * subdev,
++static int unioxx5_insn_config(struct comedi_device * dev, struct comedi_subdevice * subdev,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel_offset, flags, channel = CR_CHAN(insn->chanspec), type;
+@@ -250,7 +250,7 @@ static int unioxx5_insn_config(struct comedi_device * dev, comedi_subdevice * su
+ static int unioxx5_detach(struct comedi_device * dev)
+ {
+ 	int i;
+-	comedi_subdevice *subdev;
++	struct comedi_subdevice *subdev;
+ 	unioxx5_subd_priv *usp;
+ 
+ 	for (i = 0; i < dev->n_subdevices; i++) {
+@@ -264,7 +264,7 @@ static int unioxx5_detach(struct comedi_device * dev)
+ }
+ 
+ /* initializing subdevice with given address */
+-static int __unioxx5_subdev_init(comedi_subdevice * subdev, int subdev_iobase,
++static int __unioxx5_subdev_init(struct comedi_subdevice * subdev, int subdev_iobase,
+ 	int minor)
+ {
+ 	unioxx5_subd_priv *usp;
+diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
+index c433076c0e47..41872a3a68b2 100644
+--- a/drivers/staging/comedi/drivers/usbdux.c
++++ b/drivers/staging/comedi/drivers/usbdux.c
+@@ -363,7 +363,7 @@ static int usbdux_ai_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
+  * This will cancel a running acquisition operation.
+  * This is called by comedi but never from inside the driver.
+  */
+-static int usbdux_ai_cancel(struct comedi_device *dev, comedi_subdevice *s)
++static int usbdux_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct usbduxsub *this_usbduxsub;
+ 	int res = 0;
+@@ -393,7 +393,7 @@ static void usbduxsub_ai_IsocIrq(struct urb *urb)
+ 	int i, err, n;
+ 	struct usbduxsub *this_usbduxsub;
+ 	struct comedi_device *this_comedidev;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	/* the context variable points to the subdevice */
+ 	this_comedidev = urb->context;
+@@ -561,7 +561,7 @@ static int usbdux_ao_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
+ }
+ 
+ /* force unlink, is called by comedi */
+-static int usbdux_ao_cancel(struct comedi_device *dev, comedi_subdevice *s)
++static int usbdux_ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+ 	int res = 0;
+@@ -587,7 +587,7 @@ static void usbduxsub_ao_IsocIrq(struct urb *urb)
+ 	int8_t *datap;
+ 	struct usbduxsub *this_usbduxsub;
+ 	struct comedi_device *this_comedidev;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	/* the context variable points to the subdevice */
+ 	this_comedidev = urb->context;
+@@ -896,7 +896,7 @@ static int usbduxsub_submit_OutURBs(struct usbduxsub *usbduxsub)
+ 	return 0;
+ }
+ 
+-static int usbdux_ai_cmdtest(struct comedi_device *dev, comedi_subdevice *s,
++static int usbdux_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			     comedi_cmd *cmd)
+ {
+ 	int err = 0, tmp, i;
+@@ -1116,7 +1116,7 @@ static int receive_dux_commands(struct usbduxsub *this_usbduxsub, int command)
+ 	return -EFAULT;
+ }
+ 
+-static int usbdux_ai_inttrig(struct comedi_device *dev, comedi_subdevice *s,
++static int usbdux_ai_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			     unsigned int trignum)
+ {
+ 	int ret;
+@@ -1160,7 +1160,7 @@ static int usbdux_ai_inttrig(struct comedi_device *dev, comedi_subdevice *s,
+ 	return 1;
+ }
+ 
+-static int usbdux_ai_cmd(struct comedi_device *dev, comedi_subdevice *s)
++static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned int chan, range;
+@@ -1276,7 +1276,7 @@ static int usbdux_ai_cmd(struct comedi_device *dev, comedi_subdevice *s)
+ }
+ 
+ /* Mode 0 is used to get a single conversion on demand */
+-static int usbdux_ai_insn_read(struct comedi_device *dev, comedi_subdevice *s,
++static int usbdux_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			       comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+@@ -1337,7 +1337,7 @@ static int usbdux_ai_insn_read(struct comedi_device *dev, comedi_subdevice *s,
+ /************************************/
+ /* analog out */
+ 
+-static int usbdux_ao_insn_read(struct comedi_device *dev, comedi_subdevice *s,
++static int usbdux_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			       comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+@@ -1359,7 +1359,7 @@ static int usbdux_ao_insn_read(struct comedi_device *dev, comedi_subdevice *s,
+ 	return i;
+ }
+ 
+-static int usbdux_ao_insn_write(struct comedi_device *dev, comedi_subdevice *s,
++static int usbdux_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, err;
+@@ -1409,7 +1409,7 @@ static int usbdux_ao_insn_write(struct comedi_device *dev, comedi_subdevice *s,
+ 	return i;
+ }
+ 
+-static int usbdux_ao_inttrig(struct comedi_device *dev, comedi_subdevice *s,
++static int usbdux_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			     unsigned int trignum)
+ {
+ 	int ret;
+@@ -1450,7 +1450,7 @@ static int usbdux_ao_inttrig(struct comedi_device *dev, comedi_subdevice *s,
+ 	return 1;
+ }
+ 
+-static int usbdux_ao_cmdtest(struct comedi_device *dev, comedi_subdevice *s,
++static int usbdux_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			     comedi_cmd *cmd)
+ {
+ 	int err = 0, tmp;
+@@ -1589,7 +1589,7 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev, comedi_subdevice *s,
+ 	return 0;
+ }
+ 
+-static int usbdux_ao_cmd(struct comedi_device *dev, comedi_subdevice *s)
++static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned int chan, gain;
+@@ -1697,7 +1697,7 @@ static int usbdux_ao_cmd(struct comedi_device *dev, comedi_subdevice *s)
+ 	return 0;
+ }
+ 
+-static int usbdux_dio_insn_config(struct comedi_device *dev, comedi_subdevice *s,
++static int usbdux_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				  comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -1728,7 +1728,7 @@ static int usbdux_dio_insn_config(struct comedi_device *dev, comedi_subdevice *s
+ 	return insn->n;
+ }
+ 
+-static int usbdux_dio_insn_bits(struct comedi_device *dev, comedi_subdevice *s,
++static int usbdux_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				comedi_insn *insn, unsigned int *data)
+ {
+ 
+@@ -1775,7 +1775,7 @@ static int usbdux_dio_insn_bits(struct comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ /* reads the 4 counters, only two are used just now */
+-static int usbdux_counter_read(struct comedi_device *dev, comedi_subdevice *s,
++static int usbdux_counter_read(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			       comedi_insn *insn, unsigned int *data)
+ {
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+@@ -1809,7 +1809,7 @@ static int usbdux_counter_read(struct comedi_device *dev, comedi_subdevice *s,
+ 	return 1;
+ }
+ 
+-static int usbdux_counter_write(struct comedi_device *dev, comedi_subdevice *s,
++static int usbdux_counter_write(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				comedi_insn *insn, unsigned int *data)
+ {
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+@@ -1839,7 +1839,7 @@ static int usbdux_counter_write(struct comedi_device *dev, comedi_subdevice *s,
+ 	return 1;
+ }
+ 
+-static int usbdux_counter_config(struct comedi_device *dev, comedi_subdevice *s,
++static int usbdux_counter_config(struct comedi_device *dev, struct comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data)
+ {
+ 	/* nothing to do so far */
+@@ -1883,7 +1883,7 @@ static int usbdux_pwm_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
+ }
+ 
+ /* force unlink - is called by comedi */
+-static int usbdux_pwm_cancel(struct comedi_device *dev, comedi_subdevice *s)
++static int usbdux_pwm_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+ 	int res = 0;
+@@ -1906,7 +1906,7 @@ static void usbduxsub_pwm_irq(struct urb *urb)
+ 	int ret;
+ 	struct usbduxsub *this_usbduxsub;
+ 	struct comedi_device *this_comedidev;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	/* printk(KERN_DEBUG "PWM: IRQ\n"); */
+ 
+@@ -1996,7 +1996,7 @@ static int usbduxsub_submit_PwmURBs(struct usbduxsub *usbduxsub)
+ 	return 0;
+ }
+ 
+-static int usbdux_pwm_period(struct comedi_device *dev, comedi_subdevice *s,
++static int usbdux_pwm_period(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			     unsigned int period)
+ {
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+@@ -2024,7 +2024,7 @@ static int usbdux_pwm_period(struct comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ /* is called from insn so there's no need to do all the sanity checks */
+-static int usbdux_pwm_start(struct comedi_device *dev, comedi_subdevice *s)
++static int usbdux_pwm_start(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	int ret, i;
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+@@ -2056,7 +2056,7 @@ static int usbdux_pwm_start(struct comedi_device *dev, comedi_subdevice *s)
+ }
+ 
+ /* generates the bit pattern for PWM with the optional sign bit */
+-static int usbdux_pwm_pattern(struct comedi_device *dev, comedi_subdevice *s,
++static int usbdux_pwm_pattern(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			      int channel, unsigned int value, unsigned int sign)
+ {
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+@@ -2097,7 +2097,7 @@ static int usbdux_pwm_pattern(struct comedi_device *dev, comedi_subdevice *s,
+ 	return 1;
+ }
+ 
+-static int usbdux_pwm_write(struct comedi_device *dev, comedi_subdevice *s,
++static int usbdux_pwm_write(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			    comedi_insn *insn, unsigned int *data)
+ {
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+@@ -2122,7 +2122,7 @@ static int usbdux_pwm_write(struct comedi_device *dev, comedi_subdevice *s,
+ 				  data[0], 0);
+ }
+ 
+-static int usbdux_pwm_read(struct comedi_device *x1, comedi_subdevice *x2,
++static int usbdux_pwm_read(struct comedi_device *x1, struct comedi_subdevice *x2,
+ 			   comedi_insn *x3, unsigned int *x4)
+ {
+ 	/* not needed */
+@@ -2130,7 +2130,7 @@ static int usbdux_pwm_read(struct comedi_device *x1, comedi_subdevice *x2,
+ };
+ 
+ /* switches on/off PWM */
+-static int usbdux_pwm_config(struct comedi_device *dev, comedi_subdevice *s,
++static int usbdux_pwm_config(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			     comedi_insn *insn, unsigned int *data)
+ {
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+@@ -2710,7 +2710,7 @@ static int usbdux_attach(struct comedi_device *dev, comedi_devconfig *it)
+ 	int i;
+ 	struct usbduxsub *udev;
+ 
+-	comedi_subdevice *s = NULL;
++	struct comedi_subdevice *s = NULL;
+ 	dev->private = NULL;
+ 
+ 	down(&start_stop_sem);
+diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c
+index ff4a546a157a..e141484f11ae 100644
+--- a/drivers/staging/comedi/drivers/usbduxfast.c
++++ b/drivers/staging/comedi/drivers/usbduxfast.c
+@@ -284,7 +284,7 @@ static int usbduxfast_ai_stop(struct usbduxfastsub_s *udfs,
+  * This will cancel a running acquisition operation.
+  * This is called by comedi but never from inside the driver.
+  */
+-static int usbduxfast_ai_cancel(struct comedi_device *dev, comedi_subdevice *s)
++static int usbduxfast_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	struct usbduxfastsub_s *udfs;
+ 	int ret;
+@@ -319,7 +319,7 @@ static void usbduxfastsub_ai_Irq(struct urb *urb PT_REGS_ARG)
+ 	int n, err;
+ 	struct usbduxfastsub_s *udfs;
+ 	struct comedi_device *this_comedidev;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	uint16_t *p;
+ 
+ 	/* sanity checks - is the urb there? */
+@@ -578,7 +578,7 @@ int usbduxfastsub_submit_InURBs(struct usbduxfastsub_s *udfs)
+ }
+ 
+ static int usbduxfast_ai_cmdtest(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_cmd *cmd)
++	struct comedi_subdevice *s, comedi_cmd *cmd)
+ {
+ 	int err = 0, stop_mask = 0;
+ 	long int steps, tmp;
+@@ -720,7 +720,7 @@ static int usbduxfast_ai_cmdtest(struct comedi_device *dev,
+ }
+ 
+ static int usbduxfast_ai_inttrig(struct comedi_device *dev,
+-	comedi_subdevice *s, unsigned int trignum)
++	struct comedi_subdevice *s, unsigned int trignum)
+ {
+ 	int ret;
+ 	struct usbduxfastsub_s *udfs = dev->private;
+@@ -771,7 +771,7 @@ static int usbduxfast_ai_inttrig(struct comedi_device *dev,
+ #define OUTBASE	(1+0x10)
+ #define LOGBASE	(1+0x18)
+ 
+-static int usbduxfast_ai_cmd(struct comedi_device *dev, comedi_subdevice *s)
++static int usbduxfast_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned int chan, gain, rngmask = 0xff;
+@@ -1231,7 +1231,7 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev, comedi_subdevice *s)
+  * Mode 0 is used to get a single conversion on demand.
+  */
+ static int usbduxfast_ai_insn_read(struct comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
++	struct comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, j, n, actual_length;
+ 	int chan, range, rngmask;
+@@ -1720,7 +1720,7 @@ static int usbduxfast_attach(struct comedi_device *dev, comedi_devconfig *it)
+ 	int ret;
+ 	int index;
+ 	int i;
+-	comedi_subdevice *s = NULL;
++	struct comedi_subdevice *s = NULL;
+ 	dev->private = NULL;
+ 
+ 	down(&start_stop_sem);
+diff --git a/drivers/staging/comedi/kcomedilib/get.c b/drivers/staging/comedi/kcomedilib/get.c
+index 257cf8c25564..8237716a20c6 100644
+--- a/drivers/staging/comedi/kcomedilib/get.c
++++ b/drivers/staging/comedi/kcomedilib/get.c
+@@ -55,7 +55,7 @@ const char *comedi_get_board_name(void * d)
+ int comedi_get_subdevice_type(void *d, unsigned int subdevice)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s = dev->subdevices + subdevice;
++	struct comedi_subdevice *s = dev->subdevices + subdevice;
+ 
+ 	return s->type;
+ }
+@@ -63,7 +63,7 @@ int comedi_get_subdevice_type(void *d, unsigned int subdevice)
+ unsigned int comedi_get_subdevice_flags(void *d, unsigned int subdevice)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s = dev->subdevices + subdevice;
++	struct comedi_subdevice *s = dev->subdevices + subdevice;
+ 
+ 	return s->subdev_flags;
+ }
+@@ -85,7 +85,7 @@ int comedi_find_subdevice_by_type(void *d, int type, unsigned int subd)
+ int comedi_get_n_channels(void *d, unsigned int subdevice)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s = dev->subdevices + subdevice;
++	struct comedi_subdevice *s = dev->subdevices + subdevice;
+ 
+ 	return s->n_chan;
+ }
+@@ -93,7 +93,7 @@ int comedi_get_n_channels(void *d, unsigned int subdevice)
+ int comedi_get_len_chanlist(void *d, unsigned int subdevice)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s = dev->subdevices + subdevice;
++	struct comedi_subdevice *s = dev->subdevices + subdevice;
+ 
+ 	return s->len_chanlist;
+ }
+@@ -102,7 +102,7 @@ unsigned int comedi_get_maxdata(void *d, unsigned int subdevice,
+ 	unsigned int chan)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s = dev->subdevices + subdevice;
++	struct comedi_subdevice *s = dev->subdevices + subdevice;
+ 
+ 	if (s->maxdata_list)
+ 		return s->maxdata_list[chan];
+@@ -115,7 +115,7 @@ int comedi_get_rangetype(void *d, unsigned int subdevice,
+ 	unsigned int chan)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s = dev->subdevices + subdevice;
++	struct comedi_subdevice *s = dev->subdevices + subdevice;
+ 	int ret;
+ 
+ 	if (s->range_table_list) {
+@@ -133,7 +133,7 @@ int comedi_get_rangetype(void *d, unsigned int subdevice,
+ int comedi_get_n_ranges(void *d, unsigned int subdevice, unsigned int chan)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s = dev->subdevices + subdevice;
++	struct comedi_subdevice *s = dev->subdevices + subdevice;
+ 	int ret;
+ 
+ 	if (s->range_table_list) {
+@@ -152,7 +152,7 @@ int comedi_get_krange(void *d, unsigned int subdevice, unsigned int chan,
+ 	unsigned int range, comedi_krange *krange)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s = dev->subdevices + subdevice;
++	struct comedi_subdevice *s = dev->subdevices + subdevice;
+ 	const comedi_lrange *lr;
+ 
+ 	if (s->range_table_list) {
+@@ -174,7 +174,7 @@ int comedi_get_krange(void *d, unsigned int subdevice, unsigned int chan,
+ unsigned int comedi_get_buf_head_pos(void *d, unsigned int subdevice)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s = dev->subdevices + subdevice;
++	struct comedi_subdevice *s = dev->subdevices + subdevice;
+ 	comedi_async *async;
+ 
+ 	async = s->async;
+@@ -187,7 +187,7 @@ unsigned int comedi_get_buf_head_pos(void *d, unsigned int subdevice)
+ int comedi_get_buffer_contents(void *d, unsigned int subdevice)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s = dev->subdevices + subdevice;
++	struct comedi_subdevice *s = dev->subdevices + subdevice;
+ 	comedi_async *async;
+ 	unsigned int num_bytes;
+ 
+@@ -207,7 +207,7 @@ int comedi_set_user_int_count(void *d, unsigned int subdevice,
+ 	unsigned int buf_user_count)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s = dev->subdevices + subdevice;
++	struct comedi_subdevice *s = dev->subdevices + subdevice;
+ 	comedi_async *async;
+ 	int num_bytes;
+ 
+@@ -228,7 +228,7 @@ int comedi_mark_buffer_read(void *d, unsigned int subdevice,
+ 	unsigned int num_bytes)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s = dev->subdevices + subdevice;
++	struct comedi_subdevice *s = dev->subdevices + subdevice;
+ 	comedi_async *async;
+ 
+ 	if (subdevice >= dev->n_subdevices)
+@@ -247,7 +247,7 @@ int comedi_mark_buffer_written(void *d, unsigned int subdevice,
+ 	unsigned int num_bytes)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s = dev->subdevices + subdevice;
++	struct comedi_subdevice *s = dev->subdevices + subdevice;
+ 	comedi_async *async;
+ 	int bytes_written;
+ 
+@@ -266,7 +266,7 @@ int comedi_mark_buffer_written(void *d, unsigned int subdevice,
+ int comedi_get_buffer_size(void *d, unsigned int subdev)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s = dev->subdevices + subdev;
++	struct comedi_subdevice *s = dev->subdevices + subdev;
+ 	comedi_async *async;
+ 
+ 	if (subdev >= dev->n_subdevices)
+@@ -281,7 +281,7 @@ int comedi_get_buffer_size(void *d, unsigned int subdev)
+ int comedi_get_buffer_offset(void *d, unsigned int subdevice)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s = dev->subdevices + subdevice;
++	struct comedi_subdevice *s = dev->subdevices + subdevice;
+ 	comedi_async *async;
+ 
+ 	if (subdevice >= dev->n_subdevices)
+diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+index 98ddbb61ac01..928e93500bbf 100644
+--- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
++++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+@@ -124,7 +124,7 @@ int comedi_fileno(void *d)
+ int comedi_command(void *d, comedi_cmd *cmd)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	comedi_async *async;
+ 	unsigned runflags;
+ 
+@@ -164,7 +164,7 @@ int comedi_command(void *d, comedi_cmd *cmd)
+ int comedi_command_test(void *d, comedi_cmd *cmd)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	if (cmd->subdev >= dev->n_subdevices)
+ 		return -ENODEV;
+@@ -186,7 +186,7 @@ int comedi_command_test(void *d, comedi_cmd *cmd)
+ int comedi_do_insn(void *d, comedi_insn *insn)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int ret = 0;
+ 
+ 	if (insn->insn & INSN_MASK_SPECIAL) {
+@@ -327,7 +327,7 @@ int comedi_do_insn(void *d, comedi_insn *insn)
+ int comedi_lock(void *d, unsigned int subdevice)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned long flags;
+ 	int ret = 0;
+ 
+@@ -370,7 +370,7 @@ int comedi_lock(void *d, unsigned int subdevice)
+ int comedi_unlock(void *d, unsigned int subdevice)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	unsigned long flags;
+ 	comedi_async *async;
+ 	int ret;
+@@ -422,7 +422,7 @@ int comedi_unlock(void *d, unsigned int subdevice)
+ int comedi_cancel(void *d, unsigned int subdevice)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	int ret = 0;
+ 
+ 	if (subdevice >= dev->n_subdevices)
+@@ -468,7 +468,7 @@ int comedi_register_callback(void *d, unsigned int subdevice,
+ 	unsigned int mask, int (*cb) (unsigned int, void *), void *arg)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 	comedi_async *async;
+ 
+ 	if (subdevice >= dev->n_subdevices)
+@@ -504,7 +504,7 @@ int comedi_register_callback(void *d, unsigned int subdevice,
+ int comedi_poll(void *d, unsigned int subdevice)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s = dev->subdevices;
++	struct comedi_subdevice *s = dev->subdevices;
+ 	comedi_async *async;
+ 
+ 	if (subdevice >= dev->n_subdevices)
+@@ -531,7 +531,7 @@ int comedi_poll(void *d, unsigned int subdevice)
+ int comedi_map(void *d, unsigned int subdevice, void *ptr)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	if (subdevice >= dev->n_subdevices)
+ 		return -EINVAL;
+@@ -553,7 +553,7 @@ int comedi_map(void *d, unsigned int subdevice, void *ptr)
+ int comedi_unmap(void *d, unsigned int subdevice)
+ {
+ 	struct comedi_device *dev = (struct comedi_device *) d;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	if (subdevice >= dev->n_subdevices)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/range.c b/drivers/staging/comedi/range.c
+index 7e069fd2ba5c..98f53df35573 100644
+--- a/drivers/staging/comedi/range.c
++++ b/drivers/staging/comedi/range.c
+@@ -49,7 +49,7 @@ int do_rangeinfo_ioctl(struct comedi_device *dev, comedi_rangeinfo *arg)
+ 	comedi_rangeinfo it;
+ 	int subd, chan;
+ 	const comedi_lrange *lr;
+-	comedi_subdevice *s;
++	struct comedi_subdevice *s;
+ 
+ 	if (copy_from_user(&it, arg, sizeof(comedi_rangeinfo)))
+ 		return -EFAULT;
+@@ -84,7 +84,7 @@ int do_rangeinfo_ioctl(struct comedi_device *dev, comedi_rangeinfo *arg)
+ 	return 0;
+ }
+ 
+-static int aref_invalid(comedi_subdevice *s, unsigned int chanspec)
++static int aref_invalid(struct comedi_subdevice *s, unsigned int chanspec)
+ {
+ 	unsigned int aref;
+ 
+@@ -120,7 +120,7 @@ static int aref_invalid(comedi_subdevice *s, unsigned int chanspec)
+    This function checks each element in a channel/gain list to make
+    make sure it is valid.
+ */
+-int check_chanlist(comedi_subdevice *s, int n, unsigned int *chanlist)
++int check_chanlist(struct comedi_subdevice *s, int n, unsigned int *chanlist)
+ {
+ 	int i;
+ 	int chan;

commit 71b5f4f11971dea972832ad63a994c7e5b45db6b
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:05:08 2009 -0400
+
+    Staging: comedi: Remove comedi_device typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
+index 82bb66994e17..c8169e03693f 100644
+--- a/drivers/staging/comedi/comedi_fops.c
++++ b/drivers/staging/comedi/comedi_fops.c
+@@ -69,29 +69,29 @@ static DEFINE_SPINLOCK(comedi_file_info_table_lock);
+ static struct comedi_device_file_info
+     *comedi_file_info_table[COMEDI_NUM_MINORS];
+ 
+-static int do_devconfig_ioctl(comedi_device *dev, comedi_devconfig *arg);
+-static int do_bufconfig_ioctl(comedi_device *dev, void *arg);
+-static int do_devinfo_ioctl(comedi_device *dev, comedi_devinfo *arg,
++static int do_devconfig_ioctl(struct comedi_device *dev, comedi_devconfig *arg);
++static int do_bufconfig_ioctl(struct comedi_device *dev, void *arg);
++static int do_devinfo_ioctl(struct comedi_device *dev, comedi_devinfo *arg,
+ 			    struct file *file);
+-static int do_subdinfo_ioctl(comedi_device *dev, comedi_subdinfo *arg,
++static int do_subdinfo_ioctl(struct comedi_device *dev, comedi_subdinfo *arg,
+ 			     void *file);
+-static int do_chaninfo_ioctl(comedi_device *dev, comedi_chaninfo *arg);
+-static int do_bufinfo_ioctl(comedi_device *dev, void *arg);
+-static int do_cmd_ioctl(comedi_device *dev, void *arg, void *file);
+-static int do_lock_ioctl(comedi_device *dev, unsigned int arg, void *file);
+-static int do_unlock_ioctl(comedi_device *dev, unsigned int arg, void *file);
+-static int do_cancel_ioctl(comedi_device *dev, unsigned int arg, void *file);
+-static int do_cmdtest_ioctl(comedi_device *dev, void *arg, void *file);
+-static int do_insnlist_ioctl(comedi_device *dev, void *arg, void *file);
+-static int do_insn_ioctl(comedi_device *dev, void *arg, void *file);
+-static int do_poll_ioctl(comedi_device *dev, unsigned int subd, void *file);
+-
+-extern void do_become_nonbusy(comedi_device *dev, comedi_subdevice *s);
+-static int do_cancel(comedi_device *dev, comedi_subdevice *s);
++static int do_chaninfo_ioctl(struct comedi_device *dev, comedi_chaninfo *arg);
++static int do_bufinfo_ioctl(struct comedi_device *dev, void *arg);
++static int do_cmd_ioctl(struct comedi_device *dev, void *arg, void *file);
++static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg, void *file);
++static int do_unlock_ioctl(struct comedi_device *dev, unsigned int arg, void *file);
++static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg, void *file);
++static int do_cmdtest_ioctl(struct comedi_device *dev, void *arg, void *file);
++static int do_insnlist_ioctl(struct comedi_device *dev, void *arg, void *file);
++static int do_insn_ioctl(struct comedi_device *dev, void *arg, void *file);
++static int do_poll_ioctl(struct comedi_device *dev, unsigned int subd, void *file);
++
++extern void do_become_nonbusy(struct comedi_device *dev, comedi_subdevice *s);
++static int do_cancel(struct comedi_device *dev, comedi_subdevice *s);
+ 
+ static int comedi_fasync(int fd, struct file *file, int on);
+ 
+-static int is_device_busy(comedi_device *dev);
++static int is_device_busy(struct comedi_device *dev);
+ 
+ #ifdef HAVE_UNLOCKED_IOCTL
+ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
+@@ -104,7 +104,7 @@ static int comedi_ioctl(struct inode *inode, struct file *file,
+ 	const unsigned minor = iminor(file->f_dentry->d_inode);
+ 	struct comedi_device_file_info *dev_file_info =
+ 	    comedi_get_device_file_info(minor);
+-	comedi_device *dev;
++	struct comedi_device *dev;
+ 	int rc;
+ 
+ 	if (dev_file_info == NULL || dev_file_info->device == NULL)
+@@ -192,7 +192,7 @@ static int comedi_ioctl(struct inode *inode, struct file *file,
+ 	writes:
+ 		none
+ */
+-static int do_devconfig_ioctl(comedi_device *dev, comedi_devconfig *arg)
++static int do_devconfig_ioctl(struct comedi_device *dev, comedi_devconfig *arg)
+ {
+ 	comedi_devconfig it;
+ 	int ret;
+@@ -272,7 +272,7 @@ static int do_devconfig_ioctl(comedi_device *dev, comedi_devconfig *arg)
+ 		modified bufconfig at arg
+ 
+ */
+-static int do_bufconfig_ioctl(comedi_device *dev, void *arg)
++static int do_bufconfig_ioctl(struct comedi_device *dev, void *arg)
+ {
+ 	comedi_bufconfig bc;
+ 	comedi_async *async;
+@@ -360,7 +360,7 @@ static int do_bufconfig_ioctl(comedi_device *dev, void *arg)
+ 		devinfo structure
+ 
+ */
+-static int do_devinfo_ioctl(comedi_device *dev, comedi_devinfo *arg,
++static int do_devinfo_ioctl(struct comedi_device *dev, comedi_devinfo *arg,
+ 			    struct file *file)
+ {
+ 	comedi_devinfo devinfo;
+@@ -410,7 +410,7 @@ static int do_devinfo_ioctl(comedi_device *dev, comedi_devinfo *arg,
+ 		array of subdevice info structures at arg
+ 
+ */
+-static int do_subdinfo_ioctl(comedi_device *dev, comedi_subdinfo *arg,
++static int do_subdinfo_ioctl(struct comedi_device *dev, comedi_subdinfo *arg,
+ 			     void *file)
+ {
+ 	int ret, i;
+@@ -490,7 +490,7 @@ static int do_subdinfo_ioctl(comedi_device *dev, comedi_subdinfo *arg,
+ 		arrays at elements of chaninfo structure
+ 
+ */
+-static int do_chaninfo_ioctl(comedi_device *dev, comedi_chaninfo *arg)
++static int do_chaninfo_ioctl(struct comedi_device *dev, comedi_chaninfo *arg)
+ {
+ 	comedi_subdevice *s;
+ 	comedi_chaninfo it;
+@@ -554,7 +554,7 @@ static int do_chaninfo_ioctl(comedi_device *dev, comedi_chaninfo *arg)
+     modified bufinfo at arg
+ 
+   */
+-static int do_bufinfo_ioctl(comedi_device *dev, void *arg)
++static int do_bufinfo_ioctl(struct comedi_device *dev, void *arg)
+ {
+ 	comedi_bufinfo bi;
+ 	comedi_subdevice *s;
+@@ -607,7 +607,7 @@ static int do_bufinfo_ioctl(comedi_device *dev, void *arg)
+ 	return 0;
+ }
+ 
+-static int parse_insn(comedi_device *dev, comedi_insn *insn, unsigned int *data,
++static int parse_insn(struct comedi_device *dev, comedi_insn *insn, unsigned int *data,
+ 		      void *file);
+ /*
+  * 	COMEDI_INSNLIST
+@@ -626,7 +626,7 @@ static int parse_insn(comedi_device *dev, comedi_insn *insn, unsigned int *data,
+  */
+ /* arbitrary limits */
+ #define MAX_SAMPLES 256
+-static int do_insnlist_ioctl(comedi_device *dev, void *arg, void *file)
++static int do_insnlist_ioctl(struct comedi_device *dev, void *arg, void *file)
+ {
+ 	comedi_insnlist insnlist;
+ 	comedi_insn *insns = NULL;
+@@ -757,7 +757,7 @@ static int check_insn_config_length(comedi_insn *insn, unsigned int *data)
+ 	return -EINVAL;
+ }
+ 
+-static int parse_insn(comedi_device *dev, comedi_insn *insn, unsigned int *data,
++static int parse_insn(struct comedi_device *dev, comedi_insn *insn, unsigned int *data,
+ 		      void *file)
+ {
+ 	comedi_subdevice *s;
+@@ -917,7 +917,7 @@ static int parse_insn(comedi_device *dev, comedi_insn *insn, unsigned int *data,
+  * 	writes:
+  * 		data (for reads)
+  */
+-static int do_insn_ioctl(comedi_device *dev, void *arg, void *file)
++static int do_insn_ioctl(struct comedi_device *dev, void *arg, void *file)
+ {
+ 	comedi_insn insn;
+ 	unsigned int *data = NULL;
+@@ -975,7 +975,7 @@ static int do_insn_ioctl(comedi_device *dev, void *arg, void *file)
+ 		modified cmd structure at arg
+ 
+ */
+-static int do_cmd_ioctl(comedi_device *dev, void *arg, void *file)
++static int do_cmd_ioctl(struct comedi_device *dev, void *arg, void *file)
+ {
+ 	comedi_cmd user_cmd;
+ 	comedi_subdevice *s;
+@@ -1129,7 +1129,7 @@ static int do_cmd_ioctl(comedi_device *dev, void *arg, void *file)
+ 		modified cmd structure at arg
+ 
+ */
+-static int do_cmdtest_ioctl(comedi_device *dev, void *arg, void *file)
++static int do_cmdtest_ioctl(struct comedi_device *dev, void *arg, void *file)
+ {
+ 	comedi_cmd user_cmd;
+ 	comedi_subdevice *s;
+@@ -1227,7 +1227,7 @@ static int do_cmdtest_ioctl(comedi_device *dev, void *arg, void *file)
+ 
+ */
+ 
+-static int do_lock_ioctl(comedi_device *dev, unsigned int arg, void *file)
++static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg, void *file)
+ {
+ 	int ret = 0;
+ 	unsigned long flags;
+@@ -1271,7 +1271,7 @@ static int do_lock_ioctl(comedi_device *dev, unsigned int arg, void *file)
+ 	This function isn't protected by the semaphore, since
+ 	we already own the lock.
+ */
+-static int do_unlock_ioctl(comedi_device *dev, unsigned int arg, void *file)
++static int do_unlock_ioctl(struct comedi_device *dev, unsigned int arg, void *file)
+ {
+ 	comedi_subdevice *s;
+ 
+@@ -1311,7 +1311,7 @@ static int do_unlock_ioctl(comedi_device *dev, unsigned int arg, void *file)
+ 		nothing
+ 
+ */
+-static int do_cancel_ioctl(comedi_device *dev, unsigned int arg, void *file)
++static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg, void *file)
+ {
+ 	comedi_subdevice *s;
+ 
+@@ -1347,7 +1347,7 @@ static int do_cancel_ioctl(comedi_device *dev, unsigned int arg, void *file)
+ 		nothing
+ 
+ */
+-static int do_poll_ioctl(comedi_device *dev, unsigned int arg, void *file)
++static int do_poll_ioctl(struct comedi_device *dev, unsigned int arg, void *file)
+ {
+ 	comedi_subdevice *s;
+ 
+@@ -1370,7 +1370,7 @@ static int do_poll_ioctl(comedi_device *dev, unsigned int arg, void *file)
+ 	return -EINVAL;
+ }
+ 
+-static int do_cancel(comedi_device *dev, comedi_subdevice *s)
++static int do_cancel(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 	int ret = 0;
+ 
+@@ -1385,7 +1385,7 @@ static int do_cancel(comedi_device *dev, comedi_subdevice *s)
+ void comedi_unmap(struct vm_area_struct *area)
+ {
+ 	comedi_async *async;
+-	comedi_device *dev;
++	struct comedi_device *dev;
+ 
+ 	async = area->vm_private_data;
+ 	dev = async->subdevice->device;
+@@ -1404,7 +1404,7 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
+ 	const unsigned minor = iminor(file->f_dentry->d_inode);
+ 	struct comedi_device_file_info *dev_file_info =
+ 	    comedi_get_device_file_info(minor);
+-	comedi_device *dev = dev_file_info->device;
++	struct comedi_device *dev = dev_file_info->device;
+ 	comedi_async *async = NULL;
+ 	unsigned long start = vma->vm_start;
+ 	unsigned long size;
+@@ -1480,7 +1480,7 @@ static unsigned int comedi_poll(struct file *file, poll_table *wait)
+ 	const unsigned minor = iminor(file->f_dentry->d_inode);
+ 	struct comedi_device_file_info *dev_file_info =
+ 	    comedi_get_device_file_info(minor);
+-	comedi_device *dev = dev_file_info->device;
++	struct comedi_device *dev = dev_file_info->device;
+ 	comedi_subdevice *read_subdev;
+ 	comedi_subdevice *write_subdev;
+ 
+@@ -1530,7 +1530,7 @@ static ssize_t comedi_write(struct file *file, const char *buf, size_t nbytes,
+ 	const unsigned minor = iminor(file->f_dentry->d_inode);
+ 	struct comedi_device_file_info *dev_file_info =
+ 	    comedi_get_device_file_info(minor);
+-	comedi_device *dev = dev_file_info->device;
++	struct comedi_device *dev = dev_file_info->device;
+ 
+ 	if (!dev->attached) {
+ 		DPRINTK("no driver configured on comedi%i\n", dev->minor);
+@@ -1632,7 +1632,7 @@ static ssize_t comedi_read(struct file *file, char *buf, size_t nbytes,
+ 	const unsigned minor = iminor(file->f_dentry->d_inode);
+ 	struct comedi_device_file_info *dev_file_info =
+ 	    comedi_get_device_file_info(minor);
+-	comedi_device *dev = dev_file_info->device;
++	struct comedi_device *dev = dev_file_info->device;
+ 
+ 	if (!dev->attached) {
+ 		DPRINTK("no driver configured on comedi%i\n", dev->minor);
+@@ -1733,7 +1733,7 @@ static ssize_t comedi_read(struct file *file, char *buf, size_t nbytes,
+ /*
+    This function restores a subdevice to an idle state.
+  */
+-void do_become_nonbusy(comedi_device *dev, comedi_subdevice *s)
++void do_become_nonbusy(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 	comedi_async *async = s->async;
+ 
+@@ -1760,7 +1760,7 @@ static int comedi_open(struct inode *inode, struct file *file)
+ 	const unsigned minor = iminor(inode);
+ 	struct comedi_device_file_info *dev_file_info =
+ 	    comedi_get_device_file_info(minor);
+-	comedi_device *dev = dev_file_info ? dev_file_info->device : NULL;
++	struct comedi_device *dev = dev_file_info ? dev_file_info->device : NULL;
+ 
+ 	if (dev == NULL) {
+ 		DPRINTK("invalid minor number\n");
+@@ -1832,7 +1832,7 @@ static int comedi_close(struct inode *inode, struct file *file)
+ 	const unsigned minor = iminor(inode);
+ 	struct comedi_device_file_info *dev_file_info =
+ 	    comedi_get_device_file_info(minor);
+-	comedi_device *dev = dev_file_info->device;
++	struct comedi_device *dev = dev_file_info->device;
+ 	comedi_subdevice *s = NULL;
+ 	int i;
+ 
+@@ -1871,7 +1871,7 @@ static int comedi_fasync(int fd, struct file *file, int on)
+ 	struct comedi_device_file_info *dev_file_info =
+ 	    comedi_get_device_file_info(minor);
+ 
+-	comedi_device *dev = dev_file_info->device;
++	struct comedi_device *dev = dev_file_info->device;
+ 
+ 	return fasync_helper(fd, file, on, &dev->async_queue);
+ }
+@@ -2000,13 +2000,13 @@ static void __exit comedi_cleanup(void)
+ module_init(comedi_init);
+ module_exit(comedi_cleanup);
+ 
+-void comedi_error(const comedi_device *dev, const char *s)
++void comedi_error(const struct comedi_device *dev, const char *s)
+ {
+ 	rt_printk("comedi%d: %s: %s\n", dev->minor, dev->driver->driver_name,
+ 		  s);
+ }
+ 
+-void comedi_event(comedi_device *dev, comedi_subdevice *s)
++void comedi_event(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 	comedi_async *async = s->async;
+ 	unsigned runflags = 0;
+@@ -2089,7 +2089,7 @@ unsigned comedi_get_subdevice_runflags(comedi_subdevice *s)
+ 	return runflags;
+ }
+ 
+-static int is_device_busy(comedi_device *dev)
++static int is_device_busy(struct comedi_device *dev)
+ {
+ 	comedi_subdevice *s;
+ 	int i;
+@@ -2108,15 +2108,15 @@ static int is_device_busy(comedi_device *dev)
+ 	return 0;
+ }
+ 
+-void comedi_device_init(comedi_device *dev)
++void comedi_device_init(struct comedi_device *dev)
+ {
+-	memset(dev, 0, sizeof(comedi_device));
++	memset(dev, 0, sizeof(struct comedi_device));
+ 	spin_lock_init(&dev->spinlock);
+ 	mutex_init(&dev->mutex);
+ 	dev->minor = -1;
+ }
+ 
+-void comedi_device_cleanup(comedi_device *dev)
++void comedi_device_cleanup(struct comedi_device *dev)
+ {
+ 	if (dev == NULL)
+ 		return;
+@@ -2136,7 +2136,7 @@ int comedi_alloc_board_minor(struct device *hardware_device)
+ 	info = kzalloc(sizeof(struct comedi_device_file_info), GFP_KERNEL);
+ 	if (info == NULL)
+ 		return -ENOMEM;
+-	info->device = kzalloc(sizeof(comedi_device), GFP_KERNEL);
++	info->device = kzalloc(sizeof(struct comedi_device), GFP_KERNEL);
+ 	if (info->device == NULL) {
+ 		kfree(info);
+ 		return -ENOMEM;
+@@ -2180,7 +2180,7 @@ void comedi_free_board_minor(unsigned minor)
+ 	comedi_spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
+ 
+ 	if (info) {
+-		comedi_device *dev = info->device;
++		struct comedi_device *dev = info->device;
+ 		if (dev) {
+ 			if (dev->class_dev) {
+ 				device_destroy(comedi_class,
+@@ -2193,7 +2193,7 @@ void comedi_free_board_minor(unsigned minor)
+ 	}
+ }
+ 
+-int comedi_alloc_subdevice_minor(comedi_device *dev, comedi_subdevice *s)
++int comedi_alloc_subdevice_minor(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 	unsigned long flags;
+ 	struct comedi_device_file_info *info;
+diff --git a/drivers/staging/comedi/comedi_rt.h b/drivers/staging/comedi/comedi_rt.h
+index baeaa495b0a7..169ca963312a 100644
+--- a/drivers/staging/comedi/comedi_rt.h
++++ b/drivers/staging/comedi/comedi_rt.h
+@@ -58,12 +58,12 @@
+ 
+ int comedi_request_irq(unsigned int irq, irqreturn_t(*handler) (int,
+ 		void *PT_REGS_ARG), unsigned long flags, const char *device,
+-		comedi_device *dev_id);
+-void comedi_free_irq(unsigned int irq, comedi_device *dev_id);
++		struct comedi_device *dev_id);
++void comedi_free_irq(unsigned int irq, struct comedi_device *dev_id);
+ void comedi_rt_init(void);
+ void comedi_rt_cleanup(void);
+-int comedi_switch_to_rt(comedi_device *dev);
+-void comedi_switch_to_non_rt(comedi_device *dev);
++int comedi_switch_to_rt(struct comedi_device *dev);
++void comedi_switch_to_non_rt(struct comedi_device *dev);
+ void comedi_rt_pend_wakeup(wait_queue_head_t *q);
+ extern int rt_pend_call(void (*func) (int arg1, void *arg2), int arg1,
+ 	void *arg2);
+diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
+index 372a1ba808d6..e0035f3e9287 100644
+--- a/drivers/staging/comedi/comedidev.h
++++ b/drivers/staging/comedi/comedidev.h
+@@ -121,7 +121,6 @@
+ #define COMEDI_NUM_BOARD_MINORS 0x30
+ #define COMEDI_FIRST_SUBDEVICE_MINOR COMEDI_NUM_BOARD_MINORS
+ 
+-typedef struct comedi_device_struct comedi_device;
+ typedef struct comedi_subdevice_struct comedi_subdevice;
+ typedef struct comedi_async_struct comedi_async;
+ typedef struct comedi_driver_struct comedi_driver;
+@@ -133,7 +132,7 @@ typedef struct device device_create_result_type;
+ 	device_create(cs, ((parent) ? (parent) : (device)), devt, drvdata, fmt)
+ 
+ struct comedi_subdevice_struct {
+-	comedi_device *device;
++	struct comedi_device *device;
+ 	int type;
+ 	int n_chan;
+ 	volatile int subdev_flags;
+@@ -163,27 +162,27 @@ struct comedi_subdevice_struct {
+ 
+ 	unsigned int *chanlist;	/* driver-owned chanlist (not used) */
+ 
+-	int (*insn_read) (comedi_device *, comedi_subdevice *, comedi_insn *,
++	int (*insn_read) (struct comedi_device *, comedi_subdevice *, comedi_insn *,
+ 		unsigned int *);
+-	int (*insn_write) (comedi_device *, comedi_subdevice *, comedi_insn *,
++	int (*insn_write) (struct comedi_device *, comedi_subdevice *, comedi_insn *,
+ 		unsigned int *);
+-	int (*insn_bits) (comedi_device *, comedi_subdevice *, comedi_insn *,
++	int (*insn_bits) (struct comedi_device *, comedi_subdevice *, comedi_insn *,
+ 		unsigned int *);
+-	int (*insn_config) (comedi_device *, comedi_subdevice *, comedi_insn *,
++	int (*insn_config) (struct comedi_device *, comedi_subdevice *, comedi_insn *,
+ 		unsigned int *);
+ 
+-	int (*do_cmd) (comedi_device *, comedi_subdevice *);
+-	int (*do_cmdtest) (comedi_device *, comedi_subdevice *, comedi_cmd *);
+-	int (*poll) (comedi_device *, comedi_subdevice *);
+-	int (*cancel) (comedi_device *, comedi_subdevice *);
+-	/* int (*do_lock)(comedi_device *,comedi_subdevice *); */
+-	/* int (*do_unlock)(comedi_device *,comedi_subdevice *); */
++	int (*do_cmd) (struct comedi_device *, comedi_subdevice *);
++	int (*do_cmdtest) (struct comedi_device *, comedi_subdevice *, comedi_cmd *);
++	int (*poll) (struct comedi_device *, comedi_subdevice *);
++	int (*cancel) (struct comedi_device *, comedi_subdevice *);
++	/* int (*do_lock)(struct comedi_device *,comedi_subdevice *); */
++	/* int (*do_unlock)(struct comedi_device *,comedi_subdevice *); */
+ 
+ 	/* called when the buffer changes */
+-	int (*buf_change) (comedi_device *dev, comedi_subdevice *s,
++	int (*buf_change) (struct comedi_device *dev, comedi_subdevice *s,
+ 		unsigned long new_size);
+ 
+-	void (*munge) (comedi_device *dev, comedi_subdevice *s, void *data,
++	void (*munge) (struct comedi_device *dev, comedi_subdevice *s, void *data,
+ 		unsigned int num_bytes, unsigned int start_chan_index);
+ 	enum dma_data_direction async_dma_dir;
+ 
+@@ -238,7 +237,7 @@ struct comedi_async_struct {
+ 	int (*cb_func) (unsigned int flags, void *);
+ 	void *cb_arg;
+ 
+-	int (*inttrig) (comedi_device *dev, comedi_subdevice *s,
++	int (*inttrig) (struct comedi_device *dev, comedi_subdevice *s,
+ 			unsigned int x);
+ };
+ 
+@@ -247,8 +246,8 @@ struct comedi_driver_struct {
+ 
+ 	const char *driver_name;
+ 	struct module *module;
+-	int (*attach) (comedi_device *, comedi_devconfig *);
+-	int (*detach) (comedi_device *);
++	int (*attach) (struct comedi_device *, comedi_devconfig *);
++	int (*detach) (struct comedi_device *);
+ 
+ 	/* number of elements in board_name and board_id arrays */
+ 	unsigned int num_names;
+@@ -257,7 +256,7 @@ struct comedi_driver_struct {
+ 	int offset;
+ };
+ 
+-struct comedi_device_struct {
++struct comedi_device {
+ 	int use_count;
+ 	comedi_driver *driver;
+ 	void *private;
+@@ -289,12 +288,12 @@ struct comedi_device_struct {
+ 
+ 	struct fasync_struct *async_queue;
+ 
+-	void (*open) (comedi_device *dev);
+-	void (*close) (comedi_device *dev);
++	void (*open) (struct comedi_device *dev);
++	void (*close) (struct comedi_device *dev);
+ };
+ 
+ struct comedi_device_file_info {
+-	comedi_device *device;
++	struct comedi_device *device;
+ 	comedi_subdevice *read_subdevice;
+ 	comedi_subdevice *write_subdevice;
+ };
+@@ -309,8 +308,8 @@ static const int comedi_debug;
+  * function prototypes
+  */
+ 
+-void comedi_event(comedi_device *dev, comedi_subdevice *s);
+-void comedi_error(const comedi_device *dev, const char *s);
++void comedi_event(struct comedi_device *dev, comedi_subdevice *s);
++void comedi_error(const struct comedi_device *dev, const char *s);
+ 
+ /* we can expand the number of bits used to encode devices/subdevices into
+  the minor number soon, after more distros support > 8 bit minor numbers
+@@ -344,17 +343,17 @@ static inline comedi_subdevice *comedi_get_write_subdevice(
+ 	return info->device->write_subdev;
+ }
+ 
+-void comedi_device_detach(comedi_device *dev);
+-int comedi_device_attach(comedi_device *dev, comedi_devconfig *it);
++void comedi_device_detach(struct comedi_device *dev);
++int comedi_device_attach(struct comedi_device *dev, comedi_devconfig *it);
+ int comedi_driver_register(comedi_driver *);
+ int comedi_driver_unregister(comedi_driver *);
+ 
+ void init_polling(void);
+ void cleanup_polling(void);
+-void start_polling(comedi_device *);
+-void stop_polling(comedi_device *);
++void start_polling(struct comedi_device *);
++void stop_polling(struct comedi_device *);
+ 
+-int comedi_buf_alloc(comedi_device *dev, comedi_subdevice *s, unsigned long
++int comedi_buf_alloc(struct comedi_device *dev, comedi_subdevice *s, unsigned long
+ 	new_size);
+ 
+ #ifdef CONFIG_PROC_FS
+@@ -383,12 +382,12 @@ enum subdevice_runflags {
+    various internal comedi functions
+  */
+ 
+-int do_rangeinfo_ioctl(comedi_device *dev, comedi_rangeinfo *arg);
++int do_rangeinfo_ioctl(struct comedi_device *dev, comedi_rangeinfo *arg);
+ int check_chanlist(comedi_subdevice *s, int n, unsigned int *chanlist);
+ void comedi_set_subdevice_runflags(comedi_subdevice *s, unsigned mask,
+ 	unsigned bits);
+ unsigned comedi_get_subdevice_runflags(comedi_subdevice *s);
+-int insn_inval(comedi_device *dev, comedi_subdevice *s,
++int insn_inval(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+ 
+ /* range stuff */
+@@ -422,7 +421,7 @@ struct comedi_lrange_struct {
+ 
+ /* some silly little inline functions */
+ 
+-static inline int alloc_subdevices(comedi_device *dev,
++static inline int alloc_subdevices(struct comedi_device *dev,
+ 				   unsigned int num_subdevices)
+ {
+ 	unsigned i;
+@@ -441,7 +440,7 @@ static inline int alloc_subdevices(comedi_device *dev,
+ 	return 0;
+ }
+ 
+-static inline int alloc_private(comedi_device *dev, int size)
++static inline int alloc_private(struct comedi_device *dev, int size)
+ {
+ 	dev->private = kzalloc(size, GFP_KERNEL);
+ 	if (!dev->private)
+@@ -459,7 +458,7 @@ static inline unsigned int bytes_per_sample(const comedi_subdevice *subd)
+ 
+ /* must be used in attach to set dev->hw_dev if you wish to dma directly
+ into comedi's buffer */
+-static inline void comedi_set_hw_dev(comedi_device *dev, struct device *hw_dev)
++static inline void comedi_set_hw_dev(struct comedi_device *dev, struct device *hw_dev)
+ {
+ 	if (dev->hw_dev)
+ 		put_device(dev->hw_dev);
+@@ -524,7 +523,7 @@ static inline void *comedi_aux_data(int options[], int n)
+ 
+ int comedi_alloc_board_minor(struct device *hardware_device);
+ void comedi_free_board_minor(unsigned minor);
+-int comedi_alloc_subdevice_minor(comedi_device *dev, comedi_subdevice *s);
++int comedi_alloc_subdevice_minor(struct comedi_device *dev, comedi_subdevice *s);
+ void comedi_free_subdevice_minor(comedi_subdevice *s);
+ int comedi_pci_auto_config(struct pci_dev *pcidev, const char *board_name);
+ void comedi_pci_auto_unconfig(struct pci_dev *pcidev);
+diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
+index 49834ebfcb19..f0eb7341d9ab 100644
+--- a/drivers/staging/comedi/drivers.c
++++ b/drivers/staging/comedi/drivers.c
+@@ -47,13 +47,13 @@
+ #include 
+ #include 
+ 
+-static int postconfig(comedi_device *dev);
+-static int insn_rw_emulate_bits(comedi_device *dev, comedi_subdevice *s,
++static int postconfig(struct comedi_device *dev);
++static int insn_rw_emulate_bits(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+ static void *comedi_recognize(comedi_driver * driv, const char *name);
+ static void comedi_report_boards(comedi_driver *driv);
+-static int poll_invalid(comedi_device *dev, comedi_subdevice *s);
+-int comedi_buf_alloc(comedi_device *dev, comedi_subdevice *s,
++static int poll_invalid(struct comedi_device *dev, comedi_subdevice *s);
++int comedi_buf_alloc(struct comedi_device *dev, comedi_subdevice *s,
+ 	unsigned long new_size);
+ 
+ comedi_driver *comedi_drivers;
+@@ -63,7 +63,7 @@ int comedi_modprobe(int minor)
+ 	return -EINVAL;
+ }
+ 
+-static void cleanup_device(comedi_device *dev)
++static void cleanup_device(struct comedi_device *dev)
+ {
+ 	int i;
+ 	comedi_subdevice *s;
+@@ -95,7 +95,7 @@ static void cleanup_device(comedi_device *dev)
+ 	comedi_set_hw_dev(dev, NULL);
+ }
+ 
+-static void __comedi_device_detach(comedi_device *dev)
++static void __comedi_device_detach(struct comedi_device *dev)
+ {
+ 	dev->attached = 0;
+ 	if (dev->driver) {
+@@ -106,14 +106,14 @@ static void __comedi_device_detach(comedi_device *dev)
+ 	cleanup_device(dev);
+ }
+ 
+-void comedi_device_detach(comedi_device *dev)
++void comedi_device_detach(struct comedi_device *dev)
+ {
+ 	if (!dev->attached)
+ 		return;
+ 	__comedi_device_detach(dev);
+ }
+ 
+-int comedi_device_attach(comedi_device *dev, comedi_devconfig *it)
++int comedi_device_attach(struct comedi_device *dev, comedi_devconfig *it)
+ {
+ 	comedi_driver *driv;
+ 	int ret;
+@@ -196,7 +196,7 @@ int comedi_driver_unregister(comedi_driver *driver)
+ 	/* check for devices using this driver */
+ 	for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) {
+ 		struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(i);
+-		comedi_device *dev;
++		struct comedi_device *dev;
+ 
+ 		if(dev_file_info == NULL) continue;
+ 		dev = dev_file_info->device;
+@@ -224,7 +224,7 @@ int comedi_driver_unregister(comedi_driver *driver)
+ 	return -EINVAL;
+ }
+ 
+-static int postconfig(comedi_device *dev)
++static int postconfig(struct comedi_device *dev)
+ {
+ 	int i;
+ 	comedi_subdevice *s;
+@@ -331,18 +331,18 @@ void comedi_report_boards(comedi_driver *driv)
+ 		printk(" %s\n", driv->driver_name);
+ }
+ 
+-static int poll_invalid(comedi_device *dev, comedi_subdevice *s)
++static int poll_invalid(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 	return -EINVAL;
+ }
+ 
+-int insn_inval(comedi_device *dev, comedi_subdevice *s,
++int insn_inval(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 	return -EINVAL;
+ }
+ 
+-static int insn_rw_emulate_bits(comedi_device *dev, comedi_subdevice *s,
++static int insn_rw_emulate_bits(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 	comedi_insn new_insn;
+@@ -412,7 +412,7 @@ static inline unsigned long kvirt_to_kva(unsigned long adr)
+ 	return kva;
+ }
+ 
+-int comedi_buf_alloc(comedi_device *dev, comedi_subdevice *s,
++int comedi_buf_alloc(struct comedi_device *dev, comedi_subdevice *s,
+ 	unsigned long new_size)
+ {
+ 	comedi_async *async = s->async;
+diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c
+index b90bd1275f99..3355468266a2 100644
+--- a/drivers/staging/comedi/drivers/8255.c
++++ b/drivers/staging/comedi/drivers/8255.c
+@@ -105,8 +105,8 @@ struct subdev_8255_struct {
+ #define CALLBACK_FUNC	(((struct subdev_8255_struct *)s->private)->cb_func)
+ #define subdevpriv	((struct subdev_8255_struct *)s->private)
+ 
+-static int dev_8255_attach(comedi_device * dev, comedi_devconfig * it);
+-static int dev_8255_detach(comedi_device * dev);
++static int dev_8255_attach(struct comedi_device *dev, comedi_devconfig * it);
++static int dev_8255_detach(struct comedi_device *dev);
+ static comedi_driver driver_8255 = {
+       driver_name:"8255",
+       module:THIS_MODULE,
+@@ -116,9 +116,9 @@ static comedi_driver driver_8255 = {
+ 
+ COMEDI_INITCLEANUP(driver_8255);
+ 
+-static void do_config(comedi_device * dev, comedi_subdevice * s);
++static void do_config(struct comedi_device *dev, comedi_subdevice * s);
+ 
+-void subdev_8255_interrupt(comedi_device * dev, comedi_subdevice * s)
++void subdev_8255_interrupt(struct comedi_device *dev, comedi_subdevice * s)
+ {
+ 	short d;
+ 
+@@ -143,7 +143,7 @@ static int subdev_8255_cb(int dir, int port, int data, unsigned long arg)
+ 	}
+ }
+ 
+-static int subdev_8255_insn(comedi_device * dev, comedi_subdevice * s,
++static int subdev_8255_insn(struct comedi_device *dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+@@ -168,7 +168,7 @@ static int subdev_8255_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int subdev_8255_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int subdev_8255_insn_config(struct comedi_device *dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int mask;
+@@ -205,7 +205,7 @@ static int subdev_8255_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static void do_config(comedi_device * dev, comedi_subdevice * s)
++static void do_config(struct comedi_device *dev, comedi_subdevice * s)
+ {
+ 	int config;
+ 
+@@ -222,7 +222,7 @@ static void do_config(comedi_device * dev, comedi_subdevice * s)
+ 	CALLBACK_FUNC(1, _8255_CR, config, CALLBACK_ARG);
+ }
+ 
+-static int subdev_8255_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int subdev_8255_cmdtest(struct comedi_device *dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -297,21 +297,21 @@ static int subdev_8255_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int subdev_8255_cmd(comedi_device * dev, comedi_subdevice * s)
++static int subdev_8255_cmd(struct comedi_device *dev, comedi_subdevice * s)
+ {
+ 	/* FIXME */
+ 
+ 	return 0;
+ }
+ 
+-static int subdev_8255_cancel(comedi_device * dev, comedi_subdevice * s)
++static int subdev_8255_cancel(struct comedi_device *dev, comedi_subdevice * s)
+ {
+ 	/* FIXME */
+ 
+ 	return 0;
+ }
+ 
+-int subdev_8255_init(comedi_device * dev, comedi_subdevice * s, int (*cb) (int,
++int subdev_8255_init(struct comedi_device *dev, comedi_subdevice * s, int (*cb) (int,
+ 		int, int, unsigned long), unsigned long arg)
+ {
+ 	s->type = COMEDI_SUBD_DIO;
+@@ -340,7 +340,7 @@ int subdev_8255_init(comedi_device * dev, comedi_subdevice * s, int (*cb) (int,
+ 	return 0;
+ }
+ 
+-int subdev_8255_init_irq(comedi_device * dev, comedi_subdevice * s,
++int subdev_8255_init_irq(struct comedi_device *dev, comedi_subdevice * s,
+ 	int (*cb) (int, int, int, unsigned long), unsigned long arg)
+ {
+ 	int ret;
+@@ -358,7 +358,7 @@ int subdev_8255_init_irq(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-void subdev_8255_cleanup(comedi_device * dev, comedi_subdevice * s)
++void subdev_8255_cleanup(struct comedi_device *dev, comedi_subdevice * s)
+ {
+ 	if (s->private) {
+ 		if (subdevpriv->have_irq) {
+@@ -374,7 +374,7 @@ void subdev_8255_cleanup(comedi_device * dev, comedi_subdevice * s)
+ 
+  */
+ 
+-static int dev_8255_attach(comedi_device * dev, comedi_devconfig * it)
++static int dev_8255_attach(struct comedi_device *dev, comedi_devconfig * it)
+ {
+ 	int ret;
+ 	unsigned long iobase;
+@@ -416,7 +416,7 @@ static int dev_8255_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int dev_8255_detach(comedi_device * dev)
++static int dev_8255_detach(struct comedi_device *dev)
+ {
+ 	int i;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/8255.h b/drivers/staging/comedi/drivers/8255.h
+index 69a2a72595c6..6837cf83c10b 100644
+--- a/drivers/staging/comedi/drivers/8255.h
++++ b/drivers/staging/comedi/drivers/8255.h
+@@ -28,16 +28,16 @@
+ 
+ #if defined(CONFIG_COMEDI_8255) || defined(CONFIG_COMEDI_8255_MODULE)
+ 
+-int subdev_8255_init(comedi_device * dev, comedi_subdevice * s,
++int subdev_8255_init(struct comedi_device * dev, comedi_subdevice * s,
+ 	int (*cb) (int, int, int, unsigned long), unsigned long arg);
+-int subdev_8255_init_irq(comedi_device * dev, comedi_subdevice * s,
++int subdev_8255_init_irq(struct comedi_device * dev, comedi_subdevice * s,
+ 	int (*cb) (int, int, int, unsigned long), unsigned long arg);
+-void subdev_8255_cleanup(comedi_device * dev, comedi_subdevice * s);
+-void subdev_8255_interrupt(comedi_device * dev, comedi_subdevice * s);
++void subdev_8255_cleanup(struct comedi_device * dev, comedi_subdevice * s);
++void subdev_8255_interrupt(struct comedi_device * dev, comedi_subdevice * s);
+ 
+ #else
+ 
+-static inline int subdev_8255_init(comedi_device * dev, comedi_subdevice * s,
++static inline int subdev_8255_init(struct comedi_device * dev, comedi_subdevice * s,
+ 	void *x, unsigned long y)
+ {
+ 	printk("8255 support not configured -- disabling subdevice\n");
+@@ -47,7 +47,7 @@ static inline int subdev_8255_init(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static inline void subdev_8255_cleanup(comedi_device * dev,
++static inline void subdev_8255_cleanup(struct comedi_device * dev,
+ 	comedi_subdevice * s)
+ {
+ }
+diff --git a/drivers/staging/comedi/drivers/acl7225b.c b/drivers/staging/comedi/drivers/acl7225b.c
+index aeaf30dea300..4c6ad8ab5b61 100644
+--- a/drivers/staging/comedi/drivers/acl7225b.c
++++ b/drivers/staging/comedi/drivers/acl7225b.c
+@@ -22,8 +22,8 @@ Devices: [Adlink] ACL-7225b (acl7225b), [ICP] P16R16DIO (p16r16dio)
+ #define ACL7225_DI_LO  2	/* Digital input low byte (DI0-DI7) */
+ #define ACL7225_DI_HI  3	/* Digital input high byte (DI8-DI15) */
+ 
+-static int acl7225b_attach(comedi_device * dev, comedi_devconfig * it);
+-static int acl7225b_detach(comedi_device * dev);
++static int acl7225b_attach(struct comedi_device *dev, comedi_devconfig * it);
++static int acl7225b_detach(struct comedi_device *dev);
+ 
+ typedef struct {
+ 	const char *name;	// driver name
+@@ -50,7 +50,7 @@ static comedi_driver driver_acl7225b = {
+ 
+ COMEDI_INITCLEANUP(driver_acl7225b);
+ 
+-static int acl7225b_do_insn(comedi_device * dev, comedi_subdevice * s,
++static int acl7225b_do_insn(struct comedi_device *dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -71,7 +71,7 @@ static int acl7225b_do_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int acl7225b_di_insn(comedi_device * dev, comedi_subdevice * s,
++static int acl7225b_di_insn(struct comedi_device *dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -83,7 +83,7 @@ static int acl7225b_di_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int acl7225b_attach(comedi_device * dev, comedi_devconfig * it)
++static int acl7225b_attach(struct comedi_device *dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	int iobase, iorange;
+@@ -138,7 +138,7 @@ static int acl7225b_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int acl7225b_detach(comedi_device * dev)
++static int acl7225b_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: acl7225b: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+index 20450ba03504..73357d1196ce 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+@@ -32,7 +32,7 @@
+ |                                BYTE_   b_InputClockLevel,                  |
+ |                                BYTE_   b_OutputLevel,                      |
+ |                                BYTE_   b_HardwareGateLevel)
+-INT i_InsnConfig_InitTimer(comedi_device *dev,comedi_subdevice *s,
++INT i_InsnConfig_InitTimer(struct comedi_device *dev,comedi_subdevice *s,
+ 	comedi_insn *insn,unsigned int *data)
+ |
+ +----------------------------------------------------------------------------+
+@@ -219,7 +219,7 @@ INT i_InsnConfig_InitTimer(comedi_device *dev,comedi_subdevice *s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnConfigInitTimer(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, comedi_subdevice * s,
+ 				   comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -406,7 +406,7 @@ INT i_APCI1710_InsnConfigInitTimer(comedi_device * dev, comedi_subdevice * s,
+ |                                BYTE_ b_ModulNbr,                           |
+ |                                BYTE_ b_TimerNbr,                           |
+ |                                BYTE_ b_InterruptEnable)
+-INT i_APCI1710_InsnWriteEnableDisableTimer(comedi_device *dev,comedi_subdevice *s,
++INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,comedi_subdevice *s,
+ 	comedi_insn *insn,unsigned int *data)                |
+ +----------------------------------------------------------------------------+
+ | Task              : Enable OR Disable the Timer (b_TimerNbr) from selected module     |
+@@ -448,7 +448,7 @@ i_ReturnValue=insn->n;
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnWriteEnableDisableTimer(comedi_device * dev,
++INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device * dev,
+ 					   comedi_subdevice * s,
+ 					   comedi_insn * insn, unsigned int * data)
+ {
+@@ -561,7 +561,7 @@ INT i_APCI1710_InsnWriteEnableDisableTimer(comedi_device * dev,
+ |                                       (BYTE_     b_BoardHandle,            |
+ |                                        BYTE_     b_ModulNbr,               |
+ |                                        PULONG_ pul_TimerValueArray)
+-INT i_APCI1710_InsnReadAllTimerValue(comedi_device *dev,comedi_subdevice *s,
++INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev,comedi_subdevice *s,
+ 	comedi_insn *insn,unsigned int *data)        |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the all timer values from selected timer        |
+@@ -590,7 +590,7 @@ INT i_APCI1710_InsnReadAllTimerValue(comedi_device *dev,comedi_subdevice *s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnReadAllTimerValue(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, comedi_subdevice *s,
+ 				     comedi_insn *insn, unsigned int *data)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -668,7 +668,7 @@ INT i_APCI1710_InsnReadAllTimerValue(comedi_device *dev, comedi_subdevice *s,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     :INT i_APCI1710_InsnBitsTimer(comedi_device *dev,
++| Function Name     :INT i_APCI1710_InsnBitsTimer(struct comedi_device *dev,
+ comedi_subdevice *s,comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ | Task              : Read write functions for Timer                                          |
+@@ -681,7 +681,7 @@ comedi_subdevice *s,comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnBitsTimer(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnBitsTimer(struct comedi_device * dev, comedi_subdevice * s,
+ 			     comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_BitsType;
+@@ -760,7 +760,7 @@ INT i_APCI1710_InsnBitsTimer(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_ReadTimerValue(comedi_device * dev,
++INT i_APCI1710_ReadTimerValue(struct comedi_device * dev,
+ 			      BYTE b_ModulNbr, BYTE b_TimerNbr,
+ 			      PULONG pul_TimerValue)
+ {
+@@ -848,7 +848,7 @@ INT i_APCI1710_ReadTimerValue(comedi_device * dev,
+ 	   +----------------------------------------------------------------------------+
+ 	 */
+ 
+-INT i_APCI1710_GetTimerOutputLevel(comedi_device * dev,
++INT i_APCI1710_GetTimerOutputLevel(struct comedi_device * dev,
+ 				   BYTE b_ModulNbr, BYTE b_TimerNbr,
+ 				   PBYTE pb_OutputLevel)
+ {
+@@ -927,7 +927,7 @@ INT i_APCI1710_GetTimerOutputLevel(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_GetTimerProgressStatus(comedi_device *dev,
++INT i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
+ 				      BYTE b_ModulNbr, BYTE b_TimerNbr,
+ 				      PBYTE pb_TimerStatus)
+ {
+@@ -1006,7 +1006,7 @@ INT i_APCI1710_GetTimerProgressStatus(comedi_device *dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_WriteTimerValue(comedi_device * dev,
++INT i_APCI1710_WriteTimerValue(struct comedi_device * dev,
+ 			       BYTE b_ModulNbr, BYTE b_TimerNbr,
+ 			       ULONG ul_WriteValue)
+ {
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
+index 80ee66233ec6..c17ac8ce251c 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
+@@ -34,40 +34,40 @@
+ /*
+  * 82X54 TIMER INISIALISATION FUNCTION
+  */
+-INT i_APCI1710_InsnConfigInitTimer(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnConfigInitTimer(struct comedi_device *dev, comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_InsnWriteEnableDisableTimer(comedi_device *dev,
++INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,
+ 					   comedi_subdevice *s,
+ 					   comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * 82X54 READ FUNCTION
+  */
+-INT i_APCI1710_InsnReadAllTimerValue(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, comedi_subdevice *s,
+ 				     comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_InsnBitsTimer(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnBitsTimer(struct comedi_device *dev, comedi_subdevice *s,
+ 			     comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * 82X54 READ & WRITE FUNCTION
+  */
+-INT i_APCI1710_ReadTimerValue(comedi_device *dev,
++INT i_APCI1710_ReadTimerValue(struct comedi_device *dev,
+ 			      BYTE b_ModulNbr, BYTE b_TimerNbr,
+ 			      PULONG pul_TimerValue);
+ 
+-INT i_APCI1710_GetTimerOutputLevel(comedi_device *dev,
++INT i_APCI1710_GetTimerOutputLevel(struct comedi_device *dev,
+ 				   BYTE b_ModulNbr, BYTE b_TimerNbr,
+ 				   PBYTE pb_OutputLevel);
+ 
+-INT i_APCI1710_GetTimerProgressStatus(comedi_device *dev,
++INT i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
+ 				      BYTE b_ModulNbr, BYTE b_TimerNbr,
+ 				      PBYTE pb_TimerStatus);
+ 
+ /*
+  * 82X54 WRITE FUNCTION
+  */
+-INT i_APCI1710_WriteTimerValue(comedi_device *dev,
++INT i_APCI1710_WriteTimerValue(struct comedi_device *dev,
+ 			       BYTE b_ModulNbr, BYTE b_TimerNbr,
+ 			       ULONG ul_WriteValue);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+index 25242871d470..75361fbaeefd 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+@@ -131,7 +131,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnConfigInitChrono(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -790,7 +790,7 @@ INT i_APCI1710_InsnConfigInitChrono(comedi_device * dev, comedi_subdevice * s,
+ |                                                BYTE_ b_ModulNbr,           |
+ |                                                BYTE_ b_CycleMode,          |
+ |                                                BYTE_ b_InterruptEnable)
+-INT i_APCI1710_InsnWriteEnableDisableChrono(comedi_device *dev,
++INT i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
+ comedi_subdevice *s,comedi_insn *insn,unsigned int *data)						 |
+ +----------------------------------------------------------------------------+
+ | Task              : Enable the chronometer from selected module            |
+@@ -840,7 +840,7 @@ comedi_subdevice *s,comedi_insn *insn,unsigned int *data)						 |
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnWriteEnableDisableChrono(comedi_device * dev,
++INT i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -1077,7 +1077,7 @@ INT i_APCI1710_InsnWriteEnableDisableChrono(comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     :INT	i_APCI1710_InsnReadChrono(comedi_device *dev,comedi_subdevice *s,
++| Function Name     :INT	i_APCI1710_InsnReadChrono(struct comedi_device *dev,comedi_subdevice *s,
+ comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  functions for Timer                                     |
+@@ -1090,7 +1090,7 @@ comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnReadChrono(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnReadChrono(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_ReadType;
+@@ -1194,7 +1194,7 @@ INT i_APCI1710_InsnReadChrono(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_GetChronoProgressStatus(comedi_device * dev,
++INT i_APCI1710_GetChronoProgressStatus(struct comedi_device * dev,
+ 	BYTE b_ModulNbr, PBYTE pb_ChronoStatus)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -1355,7 +1355,7 @@ INT i_APCI1710_GetChronoProgressStatus(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_ReadChronoValue(comedi_device * dev,
++INT i_APCI1710_ReadChronoValue(struct comedi_device * dev,
+ 	BYTE b_ModulNbr,
+ 	UINT ui_TimeOut, PBYTE pb_ChronoStatus, PULONG pul_ChronoValue)
+ {
+@@ -1619,7 +1619,7 @@ INT i_APCI1710_ReadChronoValue(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_ConvertChronoValue(comedi_device * dev,
++INT i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
+ 	BYTE b_ModulNbr,
+ 	ULONG ul_ChronoValue,
+ 	PULONG pul_Hour,
+@@ -1757,7 +1757,7 @@ INT i_APCI1710_ConvertChronoValue(comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     : INT i_APCI1710_InsnBitsChronoDigitalIO(comedi_device *dev,comedi_subdevice *s,
++| Function Name     : INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,comedi_subdevice *s,
+ 	comedi_insn *insn,unsigned int *data)                    |
+ +----------------------------------------------------------------------------+
+ | Task              : Sets the output witch has been passed with the         |
+@@ -1876,7 +1876,7 @@ INT i_APCI1710_ConvertChronoValue(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnBitsChronoDigitalIO(comedi_device * dev,
++INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
+index 9f6d0f003de4..ca4f5e117d5b 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
+@@ -35,10 +35,10 @@
+ /*
+  * CHRONOMETER INISIALISATION FUNCTION
+  */
+-INT i_APCI1710_InsnConfigInitChrono(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnConfigInitChrono(struct comedi_device *dev, comedi_subdevice *s,
+ 				    comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_InsnWriteEnableDisableChrono(comedi_device *dev,
++INT i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
+ 					    comedi_subdevice *s,
+ 					    comedi_insn *insn,
+ 					    unsigned int *data);
+@@ -46,18 +46,18 @@ INT i_APCI1710_InsnWriteEnableDisableChrono(comedi_device *dev,
+ /*
+  * CHRONOMETER READ FUNCTION
+  */
+-INT i_APCI1710_InsnReadChrono(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnReadChrono(struct comedi_device *dev, comedi_subdevice *s,
+ 			      comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_GetChronoProgressStatus(comedi_device *dev,
++INT i_APCI1710_GetChronoProgressStatus(struct comedi_device *dev,
+ 				       BYTE b_ModulNbr, PBYTE pb_ChronoStatus);
+ 
+-INT i_APCI1710_ReadChronoValue(comedi_device *dev,
++INT i_APCI1710_ReadChronoValue(struct comedi_device *dev,
+ 			       BYTE b_ModulNbr,
+ 			       UINT ui_TimeOut, PBYTE pb_ChronoStatus,
+ 			       PULONG pul_ChronoValue);
+ 
+-INT i_APCI1710_ConvertChronoValue(comedi_device *dev,
++INT i_APCI1710_ConvertChronoValue(struct comedi_device *dev,
+ 				  BYTE b_ModulNbr,
+ 				  ULONG ul_ChronoValue,
+ 				  PULONG pul_Hour,
+@@ -69,6 +69,6 @@ INT i_APCI1710_ConvertChronoValue(comedi_device *dev,
+ /*
+  * CHRONOMETER DIGITAL INPUT OUTPUT FUNCTION
+  */
+-INT i_APCI1710_InsnBitsChronoDigitalIO(comedi_device *dev,
++INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,
+ 				       comedi_subdevice *s, comedi_insn *insn,
+ 				       unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+index 87dba6a83d83..586a897a633c 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+@@ -61,7 +61,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     : INT i_APCI1710_InsnConfigDigitalIO(comedi_device *dev, |
++| Function Name     : INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device *dev, |
+ |						comedi_subdevice *s,comedi_insn *insn,unsigned int *data)|
+ +----------------------------------------------------------------------------+
+ | Task              : Configure the digital I/O operating mode from selected |
+@@ -99,7 +99,7 @@ Activates and deactivates the digital output memory.
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnConfigDigitalIO(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_ModulNbr, b_ChannelAMode, b_ChannelBMode;
+@@ -247,7 +247,7 @@ INT i_APCI1710_InsnConfigDigitalIO(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ 
+-|INT i_APCI1710_InsnReadDigitalIOChlValue(comedi_device *dev,comedi_subdevice
++|INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device *dev,comedi_subdevice
+ *s,	comedi_insn *insn,unsigned int *data)
+ 
+ +----------------------------------------------------------------------------+
+@@ -293,7 +293,7 @@ INT i_APCI1710_InsnConfigDigitalIO(comedi_device * dev, comedi_subdevice * s,
+ //                                             BYTE_    b_InputChannel,
+ //
+ //                                             PBYTE_  pb_ChannelStatus)
+-INT i_APCI1710_InsnReadDigitalIOChlValue(comedi_device * dev,
++INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -481,7 +481,7 @@ INT i_APCI1710_InsnReadDigitalIOChlValue(comedi_device * dev,
+ //_INT_   i_APCI1710_SetDigitalIOChlOn    (BYTE_ b_BoardHandle,
+ //                                       BYTE_ b_ModulNbr,
+ //                                       BYTE_ b_OutputChannel)
+-INT i_APCI1710_InsnWriteDigitalIOChlOnOff(comedi_device * dev,
++INT i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -676,7 +676,7 @@ INT i_APCI1710_InsnWriteDigitalIOChlOnOff(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ 
+-|INT i_APCI1710_InsnBitsDigitalIOPortOnOff(comedi_device *dev,comedi_subdevice
++|INT i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device *dev,comedi_subdevice
+ 	*s,	comedi_insn *insn,unsigned int *data)
+ +----------------------------------------------------------------------------+
+ | Task              : write:
+@@ -728,7 +728,7 @@ INT i_APCI1710_InsnWriteDigitalIOChlOnOff(comedi_device * dev,
+ //_INT_   i_APCI1710_SetDigitalIOPortOn   (BYTE_ b_BoardHandle,
+ //                                       BYTE_ b_ModulNbr,
+ //                                       BYTE_ b_PortValue)
+-INT i_APCI1710_InsnBitsDigitalIOPortOnOff(comedi_device * dev,
++INT i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h
+index 76dbf0840889..846e9000651b 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h
+@@ -27,20 +27,20 @@
+ /*
+  * DIGITAL I/O INISIALISATION FUNCTION
+  */
+-INT i_APCI1710_InsnConfigDigitalIO(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device *dev, comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * INPUT OUTPUT  FUNCTIONS
+  */
+-INT i_APCI1710_InsnReadDigitalIOChlValue(comedi_device *dev,
++INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device *dev,
+ 					 comedi_subdevice *s,
+ 					 comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_InsnWriteDigitalIOChlOnOff(comedi_device *dev,
++INT i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device *dev,
+ 					  comedi_subdevice *s,
+ 					  comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_InsnBitsDigitalIOPortOnOff(comedi_device *dev,
++INT i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device *dev,
+ 					  comedi_subdevice *s,
+ 					  comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+index 5ad6abff41a5..b8b4dedb0940 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+@@ -61,7 +61,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| INT	i_APCI1710_InsnConfigINCCPT(comedi_device *dev,comedi_subdevice *s,
++| INT	i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev,comedi_subdevice *s,
+ comedi_insn *insn,unsigned int *data)
+ 
+ +----------------------------------------------------------------------------+
+@@ -75,7 +75,7 @@ comedi_insn *insn,unsigned int *data)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnConfigINCCPT(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnConfigINCCPT(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_ConfigType;
+@@ -299,7 +299,7 @@ INT i_APCI1710_InsnConfigINCCPT(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InitCounter(comedi_device * dev,
++INT i_APCI1710_InitCounter(struct comedi_device * dev,
+ 	BYTE b_ModulNbr,
+ 	BYTE b_CounterRange,
+ 	BYTE b_FirstCounterModus,
+@@ -545,7 +545,7 @@ INT i_APCI1710_InitCounter(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_CounterAutoTest(comedi_device * dev, PBYTE pb_TestStatus)
++INT i_APCI1710_CounterAutoTest(struct comedi_device * dev, PBYTE pb_TestStatus)
+ {
+ 	BYTE b_ModulCpt = 0;
+ 	INT i_ReturnValue = 0;
+@@ -708,7 +708,7 @@ INT i_APCI1710_CounterAutoTest(comedi_device * dev, PBYTE pb_TestStatus)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InitIndex(comedi_device * dev,
++INT i_APCI1710_InitIndex(struct comedi_device * dev,
+ 	BYTE b_ModulNbr,
+ 	BYTE b_ReferenceAction,
+ 	BYTE b_IndexOperation, BYTE b_AutoMode, BYTE b_InterruptEnable)
+@@ -1152,7 +1152,7 @@ INT i_APCI1710_InitIndex(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InitReference(comedi_device * dev,
++INT i_APCI1710_InitReference(struct comedi_device * dev,
+ 	BYTE b_ModulNbr, BYTE b_ReferenceLevel)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -1277,7 +1277,7 @@ INT i_APCI1710_InitReference(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InitExternalStrobe(comedi_device * dev,
++INT i_APCI1710_InitExternalStrobe(struct comedi_device * dev,
+ 	BYTE b_ModulNbr, BYTE b_ExternalStrobe, BYTE b_ExternalStrobeLevel)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -1391,7 +1391,7 @@ INT i_APCI1710_InitExternalStrobe(comedi_device * dev,
+ 	   +----------------------------------------------------------------------------+
+ 	 */
+ 
+-INT i_APCI1710_InitCompareLogic(comedi_device * dev,
++INT i_APCI1710_InitCompareLogic(struct comedi_device * dev,
+ 	BYTE b_ModulNbr, UINT ui_CompareValue)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -1487,7 +1487,7 @@ INT i_APCI1710_InitCompareLogic(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InitFrequencyMeasurement(comedi_device * dev,
++INT i_APCI1710_InitFrequencyMeasurement(struct comedi_device * dev,
+ 	BYTE b_ModulNbr,
+ 	BYTE b_PCIInputClock,
+ 	BYTE b_TimingUnity,
+@@ -2002,7 +2002,7 @@ INT i_APCI1710_InitFrequencyMeasurement(comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     :INT	i_APCI1710_InsnBitsINCCPT(comedi_device *dev,comedi_subdevice *s,
++| Function Name     :INT	i_APCI1710_InsnBitsINCCPT(struct comedi_device *dev,comedi_subdevice *s,
+ comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ | Task              : Set & Clear Functions for INC_CPT                                          |
+@@ -2015,7 +2015,7 @@ comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnBitsINCCPT(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnBitsINCCPT(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_BitsType;
+@@ -2091,7 +2091,7 @@ INT i_APCI1710_InsnBitsINCCPT(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_ClearCounterValue(comedi_device * dev, BYTE b_ModulNbr)
++INT i_APCI1710_ClearCounterValue(struct comedi_device * dev, BYTE b_ModulNbr)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -2151,7 +2151,7 @@ INT i_APCI1710_ClearCounterValue(comedi_device * dev, BYTE b_ModulNbr)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_ClearAllCounterValue(comedi_device * dev)
++INT i_APCI1710_ClearAllCounterValue(struct comedi_device * dev)
+ {
+ 	BYTE b_ModulCpt = 0;
+ 	INT i_ReturnValue = 0;
+@@ -2297,7 +2297,7 @@ INT i_APCI1710_ClearAllCounterValue(comedi_device * dev)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_SetInputFilter(comedi_device * dev,
++INT i_APCI1710_SetInputFilter(struct comedi_device * dev,
+ 	BYTE b_ModulNbr, BYTE b_PCIInputClock, BYTE b_Filter)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -2561,7 +2561,7 @@ INT i_APCI1710_SetInputFilter(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_LatchCounter(comedi_device * dev,
++INT i_APCI1710_LatchCounter(struct comedi_device * dev,
+ 	BYTE b_ModulNbr, BYTE b_LatchReg)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -2658,7 +2658,7 @@ INT i_APCI1710_LatchCounter(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_SetIndexAndReferenceSource(comedi_device * dev,
++INT i_APCI1710_SetIndexAndReferenceSource(struct comedi_device * dev,
+ 	BYTE b_ModulNbr, BYTE b_SourceSelection)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -2795,7 +2795,7 @@ INT i_APCI1710_SetIndexAndReferenceSource(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_SetDigitalChlOn(comedi_device * dev, BYTE b_ModulNbr)
++INT i_APCI1710_SetDigitalChlOn(struct comedi_device * dev, BYTE b_ModulNbr)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -2875,7 +2875,7 @@ INT i_APCI1710_SetDigitalChlOn(comedi_device * dev, BYTE b_ModulNbr)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_SetDigitalChlOff(comedi_device * dev, BYTE b_ModulNbr)
++INT i_APCI1710_SetDigitalChlOff(struct comedi_device * dev, BYTE b_ModulNbr)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -2939,7 +2939,7 @@ INT i_APCI1710_SetDigitalChlOff(comedi_device * dev, BYTE b_ModulNbr)
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     :INT	i_APCI1710_InsnWriteINCCPT(comedi_device *dev,comedi_subdevice *s,
++| Function Name     :INT	i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev,comedi_subdevice *s,
+ comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ | Task              : Enable Disable functions for INC_CPT                                       |
+@@ -2951,7 +2951,7 @@ comedi_insn *insn,unsigned int *data)                   |
+ | Return Value      :
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1710_InsnWriteINCCPT(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnWriteINCCPT(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_WriteType;
+@@ -3047,7 +3047,7 @@ INT i_APCI1710_InsnWriteINCCPT(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_EnableLatchInterrupt(comedi_device * dev, BYTE b_ModulNbr)
++INT i_APCI1710_EnableLatchInterrupt(struct comedi_device * dev, BYTE b_ModulNbr)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -3133,7 +3133,7 @@ INT i_APCI1710_EnableLatchInterrupt(comedi_device * dev, BYTE b_ModulNbr)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_DisableLatchInterrupt(comedi_device * dev, BYTE b_ModulNbr)
++INT i_APCI1710_DisableLatchInterrupt(struct comedi_device * dev, BYTE b_ModulNbr)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -3231,7 +3231,7 @@ INT i_APCI1710_DisableLatchInterrupt(comedi_device * dev, BYTE b_ModulNbr)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_Write16BitCounterValue(comedi_device * dev,
++INT i_APCI1710_Write16BitCounterValue(struct comedi_device * dev,
+ 	BYTE b_ModulNbr, BYTE b_SelectedCounter, UINT ui_WriteValue)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -3316,7 +3316,7 @@ INT i_APCI1710_Write16BitCounterValue(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_Write32BitCounterValue(comedi_device * dev,
++INT i_APCI1710_Write32BitCounterValue(struct comedi_device * dev,
+ 	BYTE b_ModulNbr, ULONG ul_WriteValue)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -3383,7 +3383,7 @@ INT i_APCI1710_Write32BitCounterValue(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_EnableIndex(comedi_device * dev, BYTE b_ModulNbr)
++INT i_APCI1710_EnableIndex(struct comedi_device * dev, BYTE b_ModulNbr)
+ {
+ 	INT i_ReturnValue = 0;
+ 	ULONG ul_InterruptLatchReg;
+@@ -3481,7 +3481,7 @@ INT i_APCI1710_EnableIndex(comedi_device * dev, BYTE b_ModulNbr)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_DisableIndex(comedi_device * dev, BYTE b_ModulNbr)
++INT i_APCI1710_DisableIndex(struct comedi_device * dev, BYTE b_ModulNbr)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -3580,7 +3580,7 @@ INT i_APCI1710_DisableIndex(comedi_device * dev, BYTE b_ModulNbr)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_EnableCompareLogic(comedi_device * dev, BYTE b_ModulNbr)
++INT i_APCI1710_EnableCompareLogic(struct comedi_device * dev, BYTE b_ModulNbr)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -3680,7 +3680,7 @@ INT i_APCI1710_EnableCompareLogic(comedi_device * dev, BYTE b_ModulNbr)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_DisableCompareLogic(comedi_device * dev, BYTE b_ModulNbr)
++INT i_APCI1710_DisableCompareLogic(struct comedi_device * dev, BYTE b_ModulNbr)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -3789,7 +3789,7 @@ INT i_APCI1710_DisableCompareLogic(comedi_device * dev, BYTE b_ModulNbr)
+ 	   +----------------------------------------------------------------------------+
+ 	 */
+ 
+-INT i_APCI1710_EnableFrequencyMeasurement(comedi_device * dev,
++INT i_APCI1710_EnableFrequencyMeasurement(struct comedi_device * dev,
+ 	BYTE b_ModulNbr, BYTE b_InterruptEnable)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -3936,7 +3936,7 @@ INT i_APCI1710_EnableFrequencyMeasurement(comedi_device * dev,
+ 	   +----------------------------------------------------------------------------+
+ 	 */
+ 
+-INT i_APCI1710_DisableFrequencyMeasurement(comedi_device * dev, BYTE b_ModulNbr)
++INT i_APCI1710_DisableFrequencyMeasurement(struct comedi_device * dev, BYTE b_ModulNbr)
+ {
+ 	INT i_ReturnValue = 0;
+ 
+@@ -4037,7 +4037,7 @@ INT i_APCI1710_DisableFrequencyMeasurement(comedi_device * dev, BYTE b_ModulNbr)
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     :INT	i_APCI1710_InsnWriteINCCPT(comedi_device *dev,comedi_subdevice *s,
++| Function Name     :INT	i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev,comedi_subdevice *s,
+ comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ | Task              : Read and Get functions for INC_CPT                                       |
+@@ -4049,7 +4049,7 @@ comedi_insn *insn,unsigned int *data)                   |
+ | Return Value      :
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1710_InsnReadINCCPT(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnReadINCCPT(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_ReadType;
+@@ -4193,7 +4193,7 @@ INT i_APCI1710_InsnReadINCCPT(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_ReadLatchRegisterStatus(comedi_device * dev,
++INT i_APCI1710_ReadLatchRegisterStatus(struct comedi_device * dev,
+ 	BYTE b_ModulNbr, BYTE b_LatchReg, PBYTE pb_LatchStatus)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -4280,7 +4280,7 @@ INT i_APCI1710_ReadLatchRegisterStatus(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_ReadLatchRegisterValue(comedi_device * dev,
++INT i_APCI1710_ReadLatchRegisterValue(struct comedi_device * dev,
+ 	BYTE b_ModulNbr, BYTE b_LatchReg, PULONG pul_LatchValue)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -4364,7 +4364,7 @@ INT i_APCI1710_ReadLatchRegisterValue(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_Read16BitCounterValue(comedi_device * dev,
++INT i_APCI1710_Read16BitCounterValue(struct comedi_device * dev,
+ 	BYTE b_ModulNbr, BYTE b_SelectedCounter, PUINT pui_CounterValue)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -4459,7 +4459,7 @@ INT i_APCI1710_Read16BitCounterValue(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_Read32BitCounterValue(comedi_device * dev,
++INT i_APCI1710_Read32BitCounterValue(struct comedi_device * dev,
+ 	BYTE b_ModulNbr, PULONG pul_CounterValue)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -4535,7 +4535,7 @@ INT i_APCI1710_Read32BitCounterValue(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_GetIndexStatus(comedi_device * dev,
++INT i_APCI1710_GetIndexStatus(struct comedi_device * dev,
+ 	BYTE b_ModulNbr, PBYTE pb_IndexStatus)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -4619,7 +4619,7 @@ INT i_APCI1710_GetIndexStatus(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_GetReferenceStatus(comedi_device * dev,
++INT i_APCI1710_GetReferenceStatus(struct comedi_device * dev,
+ 	BYTE b_ModulNbr, PBYTE pb_ReferenceStatus)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -4703,7 +4703,7 @@ INT i_APCI1710_GetReferenceStatus(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_GetUASStatus(comedi_device * dev,
++INT i_APCI1710_GetUASStatus(struct comedi_device * dev,
+ 	BYTE b_ModulNbr, PBYTE pb_UASStatus)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -4771,7 +4771,7 @@ INT i_APCI1710_GetUASStatus(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_GetCBStatus(comedi_device * dev,
++INT i_APCI1710_GetCBStatus(struct comedi_device * dev,
+ 	BYTE b_ModulNbr, PBYTE pb_CBStatus)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -4853,7 +4853,7 @@ INT i_APCI1710_GetCBStatus(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_Get16BitCBStatus(comedi_device * dev,
++INT i_APCI1710_Get16BitCBStatus(struct comedi_device * dev,
+ 	BYTE b_ModulNbr, PBYTE pb_CBStatusCounter0, PBYTE pb_CBStatusCounter1)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -4966,7 +4966,7 @@ INT i_APCI1710_Get16BitCBStatus(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_GetUDStatus(comedi_device * dev,
++INT i_APCI1710_GetUDStatus(struct comedi_device * dev,
+ 	BYTE b_ModulNbr, PBYTE pb_UDStatus)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -5040,7 +5040,7 @@ INT i_APCI1710_GetUDStatus(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_GetInterruptUDLatchedStatus(comedi_device * dev,
++INT i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device * dev,
+ 	BYTE b_ModulNbr, PBYTE pb_UDStatus)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -5145,7 +5145,7 @@ INT i_APCI1710_GetInterruptUDLatchedStatus(comedi_device * dev,
+ 	   +----------------------------------------------------------------------------+
+ 	 */
+ 
+-INT i_APCI1710_ReadFrequencyMeasurement(comedi_device * dev,
++INT i_APCI1710_ReadFrequencyMeasurement(struct comedi_device * dev,
+ 	BYTE b_ModulNbr,
+ 	PBYTE pb_Status, PBYTE pb_UDStatus, PULONG pul_ReadValue)
+ {
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
+index 8abcaa4a971c..a4189aeecaad 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
+@@ -132,22 +132,22 @@
+ #define APCI1710_INCCPT_DISABLEFREQUENCYMEASUREMENT		409
+ 
+ /************ Main Functions *************/
+-INT i_APCI1710_InsnConfigINCCPT(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev, comedi_subdevice *s,
+ 				comedi_insn *insn, unsigned int * data);
+ 
+-INT i_APCI1710_InsnBitsINCCPT(comedi_device *dev, comedi_subdevice * s,
++INT i_APCI1710_InsnBitsINCCPT(struct comedi_device *dev, comedi_subdevice * s,
+ 			      comedi_insn *insn, unsigned int * data);
+ 
+-INT i_APCI1710_InsnWriteINCCPT(comedi_device *dev, comedi_subdevice * s,
++INT i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev, comedi_subdevice * s,
+ 			       comedi_insn *insn, unsigned int * data);
+ 
+-INT i_APCI1710_InsnReadINCCPT(comedi_device *dev, comedi_subdevice * s,
++INT i_APCI1710_InsnReadINCCPT(struct comedi_device *dev, comedi_subdevice * s,
+ 			      comedi_insn *insn, unsigned int * data);
+ 
+ /*********** Supplementary Functions********/
+ 
+ /* INSN CONFIG */
+-INT i_APCI1710_InitCounter(comedi_device *dev,
++INT i_APCI1710_InitCounter(struct comedi_device *dev,
+ 			   BYTE b_ModulNbr,
+ 			   BYTE b_CounterRange,
+ 			   BYTE b_FirstCounterModus,
+@@ -155,25 +155,25 @@ INT i_APCI1710_InitCounter(comedi_device *dev,
+ 			   BYTE b_SecondCounterModus,
+ 			   BYTE b_SecondCounterOption);
+ 
+-INT i_APCI1710_CounterAutoTest(comedi_device *dev, PBYTE pb_TestStatus);
++INT i_APCI1710_CounterAutoTest(struct comedi_device *dev, PBYTE pb_TestStatus);
+ 
+-INT i_APCI1710_InitIndex(comedi_device *dev,
++INT i_APCI1710_InitIndex(struct comedi_device *dev,
+ 			 BYTE b_ModulNbr,
+ 			 BYTE b_ReferenceAction,
+ 			 BYTE b_IndexOperation, BYTE b_AutoMode,
+ 			 BYTE b_InterruptEnable);
+ 
+-INT i_APCI1710_InitReference(comedi_device *dev,
++INT i_APCI1710_InitReference(struct comedi_device *dev,
+ 			     BYTE b_ModulNbr, BYTE b_ReferenceLevel);
+ 
+-INT i_APCI1710_InitExternalStrobe(comedi_device *dev,
++INT i_APCI1710_InitExternalStrobe(struct comedi_device *dev,
+ 				  BYTE b_ModulNbr, BYTE b_ExternalStrobe,
+ 				  BYTE b_ExternalStrobeLevel);
+ 
+-INT i_APCI1710_InitCompareLogic(comedi_device *dev,
++INT i_APCI1710_InitCompareLogic(struct comedi_device *dev,
+ 				BYTE b_ModulNbr, UINT ui_CompareValue);
+ 
+-INT i_APCI1710_InitFrequencyMeasurement(comedi_device *dev,
++INT i_APCI1710_InitFrequencyMeasurement(struct comedi_device *dev,
+ 					BYTE b_ModulNbr,
+ 					BYTE b_PCIInputClock,
+ 					BYTE b_TimingUnity,
+@@ -181,91 +181,91 @@ INT i_APCI1710_InitFrequencyMeasurement(comedi_device *dev,
+ 					PULONG pul_RealTimingInterval);
+ 
+ /* INSN BITS */
+-INT i_APCI1710_ClearCounterValue(comedi_device *dev, BYTE b_ModulNbr);
++INT i_APCI1710_ClearCounterValue(struct comedi_device *dev, BYTE b_ModulNbr);
+ 
+-INT i_APCI1710_ClearAllCounterValue(comedi_device *dev);
++INT i_APCI1710_ClearAllCounterValue(struct comedi_device *dev);
+ 
+-INT i_APCI1710_SetInputFilter(comedi_device *dev,
++INT i_APCI1710_SetInputFilter(struct comedi_device *dev,
+ 			      BYTE b_ModulNbr, BYTE b_PCIInputClock,
+ 			      BYTE b_Filter);
+ 
+-INT i_APCI1710_LatchCounter(comedi_device *dev,
++INT i_APCI1710_LatchCounter(struct comedi_device *dev,
+ 			    BYTE b_ModulNbr, BYTE b_LatchReg);
+ 
+-INT i_APCI1710_SetIndexAndReferenceSource(comedi_device *dev,
++INT i_APCI1710_SetIndexAndReferenceSource(struct comedi_device *dev,
+ 					  BYTE b_ModulNbr,
+ 					  BYTE b_SourceSelection);
+ 
+-INT i_APCI1710_SetDigitalChlOn(comedi_device *dev, BYTE b_ModulNbr);
++INT i_APCI1710_SetDigitalChlOn(struct comedi_device *dev, BYTE b_ModulNbr);
+ 
+-INT i_APCI1710_SetDigitalChlOff(comedi_device *dev, BYTE b_ModulNbr);
++INT i_APCI1710_SetDigitalChlOff(struct comedi_device *dev, BYTE b_ModulNbr);
+ 
+ /* INSN WRITE */
+-INT i_APCI1710_EnableLatchInterrupt(comedi_device *dev, BYTE b_ModulNbr);
++INT i_APCI1710_EnableLatchInterrupt(struct comedi_device *dev, BYTE b_ModulNbr);
+ 
+-INT i_APCI1710_DisableLatchInterrupt(comedi_device *dev, BYTE b_ModulNbr);
++INT i_APCI1710_DisableLatchInterrupt(struct comedi_device *dev, BYTE b_ModulNbr);
+ 
+-INT i_APCI1710_Write16BitCounterValue(comedi_device *dev,
++INT i_APCI1710_Write16BitCounterValue(struct comedi_device *dev,
+ 				      BYTE b_ModulNbr, BYTE b_SelectedCounter,
+ 				      UINT ui_WriteValue);
+ 
+-INT i_APCI1710_Write32BitCounterValue(comedi_device *dev,
++INT i_APCI1710_Write32BitCounterValue(struct comedi_device *dev,
+ 				      BYTE b_ModulNbr, ULONG ul_WriteValue);
+ 
+-INT i_APCI1710_EnableIndex(comedi_device *dev, BYTE b_ModulNbr);
++INT i_APCI1710_EnableIndex(struct comedi_device *dev, BYTE b_ModulNbr);
+ 
+-INT i_APCI1710_DisableIndex(comedi_device *dev, BYTE b_ModulNbr);
++INT i_APCI1710_DisableIndex(struct comedi_device *dev, BYTE b_ModulNbr);
+ 
+-INT i_APCI1710_EnableCompareLogic(comedi_device *dev, BYTE b_ModulNbr);
++INT i_APCI1710_EnableCompareLogic(struct comedi_device *dev, BYTE b_ModulNbr);
+ 
+-INT i_APCI1710_DisableCompareLogic(comedi_device *dev, BYTE b_ModulNbr);
++INT i_APCI1710_DisableCompareLogic(struct comedi_device *dev, BYTE b_ModulNbr);
+ 
+-INT i_APCI1710_EnableFrequencyMeasurement(comedi_device *dev,
++INT i_APCI1710_EnableFrequencyMeasurement(struct comedi_device *dev,
+ 					  BYTE b_ModulNbr,
+ 					  BYTE b_InterruptEnable);
+ 
+-INT i_APCI1710_DisableFrequencyMeasurement(comedi_device *dev,
++INT i_APCI1710_DisableFrequencyMeasurement(struct comedi_device *dev,
+ 					   BYTE b_ModulNbr);
+ 
+ /* INSN READ */
+-INT i_APCI1710_ReadLatchRegisterStatus(comedi_device *dev,
++INT i_APCI1710_ReadLatchRegisterStatus(struct comedi_device *dev,
+ 				       BYTE b_ModulNbr, BYTE b_LatchReg,
+ 				       PBYTE pb_LatchStatus);
+ 
+-INT i_APCI1710_ReadLatchRegisterValue(comedi_device *dev,
++INT i_APCI1710_ReadLatchRegisterValue(struct comedi_device *dev,
+ 				      BYTE b_ModulNbr, BYTE b_LatchReg,
+ 				      PULONG pul_LatchValue);
+ 
+-INT i_APCI1710_Read16BitCounterValue(comedi_device *dev,
++INT i_APCI1710_Read16BitCounterValue(struct comedi_device *dev,
+ 				     BYTE b_ModulNbr, BYTE b_SelectedCounter,
+ 				     PUINT pui_CounterValue);
+ 
+-INT i_APCI1710_Read32BitCounterValue(comedi_device *dev,
++INT i_APCI1710_Read32BitCounterValue(struct comedi_device *dev,
+ 				     BYTE b_ModulNbr, PULONG pul_CounterValue);
+ 
+-INT i_APCI1710_GetIndexStatus(comedi_device *dev,
++INT i_APCI1710_GetIndexStatus(struct comedi_device *dev,
+ 			      BYTE b_ModulNbr, PBYTE pb_IndexStatus);
+ 
+-INT i_APCI1710_GetReferenceStatus(comedi_device *dev,
++INT i_APCI1710_GetReferenceStatus(struct comedi_device *dev,
+ 				  BYTE b_ModulNbr, PBYTE pb_ReferenceStatus);
+ 
+-INT i_APCI1710_GetUASStatus(comedi_device *dev,
++INT i_APCI1710_GetUASStatus(struct comedi_device *dev,
+ 			    BYTE b_ModulNbr, PBYTE pb_UASStatus);
+ 
+-INT i_APCI1710_GetCBStatus(comedi_device *dev,
++INT i_APCI1710_GetCBStatus(struct comedi_device *dev,
+ 			   BYTE b_ModulNbr, PBYTE pb_CBStatus);
+ 
+-INT i_APCI1710_Get16BitCBStatus(comedi_device *dev,
++INT i_APCI1710_Get16BitCBStatus(struct comedi_device *dev,
+ 				BYTE b_ModulNbr, PBYTE pb_CBStatusCounter0,
+ 				PBYTE pb_CBStatusCounter1);
+ 
+-INT i_APCI1710_GetUDStatus(comedi_device *dev,
++INT i_APCI1710_GetUDStatus(struct comedi_device *dev,
+ 			   BYTE b_ModulNbr, PBYTE pb_UDStatus);
+ 
+-INT i_APCI1710_GetInterruptUDLatchedStatus(comedi_device *dev,
++INT i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device *dev,
+ 					   BYTE b_ModulNbr, PBYTE pb_UDStatus);
+ 
+-INT i_APCI1710_ReadFrequencyMeasurement(comedi_device *dev,
++INT i_APCI1710_ReadFrequencyMeasurement(struct comedi_device *dev,
+ 					BYTE b_ModulNbr,
+ 					PBYTE pb_Status, PBYTE pb_UDStatus,
+ 					PULONG pul_ReadValue);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+index d6101c9a998a..e557e6c40cf6 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+@@ -123,7 +123,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnConfigInitPulseEncoder(comedi_device * dev,
++INT i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -414,7 +414,7 @@ INT i_APCI1710_InsnConfigInitPulseEncoder(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(comedi_device * dev,
++INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -708,7 +708,7 @@ INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(comedi_device * dev,
+ 
+    						 PBYTE_ pb_Status)
+ 						 */
+-INT i_APCI1710_InsnBitsReadWritePulseEncoder(comedi_device * dev,
++INT i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -834,7 +834,7 @@ INT i_APCI1710_InsnBitsReadWritePulseEncoder(comedi_device * dev,
+ 	return (i_ReturnValue);
+ }
+ 
+-INT i_APCI1710_InsnReadInterruptPulseEncoder(comedi_device * dev,
++INT i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h
+index c901a317fc61..1dbdc39f96e0 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h
+@@ -21,11 +21,11 @@
+ #define APCI1710_PULSEENCODER_READ	0
+ #define APCI1710_PULSEENCODER_WRITE	1
+ 
+-INT i_APCI1710_InsnConfigInitPulseEncoder(comedi_device *dev,
++INT i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device *dev,
+ 					  comedi_subdevice *s,
+ 					  comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(comedi_device *dev,
++INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device *dev,
+ 						  comedi_subdevice *s,
+ 						  comedi_insn *insn,
+ 						  unsigned int *data);
+@@ -33,7 +33,7 @@ INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(comedi_device *dev,
+ /*
+  * READ PULSE ENCODER FUNCTIONS
+  */
+-INT i_APCI1710_InsnReadInterruptPulseEncoder(comedi_device *dev,
++INT i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device *dev,
+ 					     comedi_subdevice *s,
+ 					     comedi_insn *insn,
+ 					     unsigned int *data);
+@@ -41,7 +41,7 @@ INT i_APCI1710_InsnReadInterruptPulseEncoder(comedi_device *dev,
+ /*
+  * WRITE PULSE ENCODER FUNCTIONS
+  */
+-INT i_APCI1710_InsnBitsReadWritePulseEncoder(comedi_device *dev,
++INT i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device *dev,
+ 					     comedi_subdevice *s,
+ 					     comedi_insn *insn,
+ 					     unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+index 9a2dd408f38f..178d773563a1 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+@@ -57,7 +57,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     :INT i_APCI1710_InsnConfigPWM(comedi_device *dev,
++| Function Name     :INT i_APCI1710_InsnConfigPWM(struct comedi_device *dev,
+ comedi_subdevice *s,comedi_insn *insn,unsigned int *data)                        |
+ +----------------------------------------------------------------------------+
+ | Task              : Pwm Init and Get Pwm Initialisation                    |
+@@ -70,7 +70,7 @@ comedi_subdevice *s,comedi_insn *insn,unsigned int *data)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnConfigPWM(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnConfigPWM(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_ConfigType;
+@@ -179,7 +179,7 @@ INT i_APCI1710_InsnConfigPWM(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InitPWM(comedi_device * dev,
++INT i_APCI1710_InitPWM(struct comedi_device * dev,
+ 	BYTE b_ModulNbr,
+ 	BYTE b_PWM,
+ 	BYTE b_ClockSelection,
+@@ -1534,7 +1534,7 @@ INT i_APCI1710_InitPWM(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_GetPWMInitialisation(comedi_device * dev,
++INT i_APCI1710_GetPWMInitialisation(struct comedi_device * dev,
+ 	BYTE b_ModulNbr,
+ 	BYTE b_PWM,
+ 	PBYTE pb_TimingUnit,
+@@ -1670,7 +1670,7 @@ INT i_APCI1710_GetPWMInitialisation(comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function Name     :INT i_APCI1710_InsnWritePWM(comedi_device *dev,
++| Function Name     :INT i_APCI1710_InsnWritePWM(struct comedi_device *dev,
+ comedi_subdevice *s,comedi_insn *insn,unsigned int *data)                        |
+ +----------------------------------------------------------------------------+
+ | Task              : Pwm Enable Disable and Set New Timing                  |
+@@ -1683,7 +1683,7 @@ comedi_subdevice *s,comedi_insn *insn,unsigned int *data)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnWritePWM(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnWritePWM(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_WriteType;
+@@ -1806,7 +1806,7 @@ INT i_APCI1710_InsnWritePWM(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_EnablePWM(comedi_device * dev,
++INT i_APCI1710_EnablePWM(struct comedi_device * dev,
+ 	BYTE b_ModulNbr,
+ 	BYTE b_PWM,
+ 	BYTE b_StartLevel,
+@@ -2062,7 +2062,7 @@ INT i_APCI1710_EnablePWM(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_DisablePWM(comedi_device * dev, BYTE b_ModulNbr, BYTE b_PWM)
++INT i_APCI1710_DisablePWM(struct comedi_device * dev, BYTE b_ModulNbr, BYTE b_PWM)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_Status;
+@@ -2189,7 +2189,7 @@ INT i_APCI1710_DisablePWM(comedi_device * dev, BYTE b_ModulNbr, BYTE b_PWM)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_SetNewPWMTiming(comedi_device * dev,
++INT i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ 	BYTE b_ModulNbr,
+ 	BYTE b_PWM, BYTE b_TimingUnit, ULONG ul_LowTiming, ULONG ul_HighTiming)
+ {
+@@ -3460,7 +3460,7 @@ INT i_APCI1710_SetNewPWMTiming(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnReadGetPWMStatus(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnReadGetPWMStatus(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -3561,7 +3561,7 @@ INT i_APCI1710_InsnReadGetPWMStatus(comedi_device * dev, comedi_subdevice * s,
+ 	return (i_ReturnValue);
+ }
+ 
+-INT i_APCI1710_InsnBitsReadPWMInterrupt(comedi_device * dev,
++INT i_APCI1710_InsnBitsReadPWMInterrupt(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->s_InterruptParameters.
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
+index 1f40d00b10e6..0c10b1e8fab4 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
+@@ -26,10 +26,10 @@
+ #define APCI1710_PWM_ENABLE		1
+ #define APCI1710_PWM_NEWTIMING		2
+ 
+-INT i_APCI1710_InsnConfigPWM(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnConfigPWM(struct comedi_device *dev, comedi_subdevice *s,
+ 			     comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_InitPWM(comedi_device *dev,
++INT i_APCI1710_InitPWM(struct comedi_device *dev,
+ 		       BYTE b_ModulNbr,
+ 		       BYTE b_PWM,
+ 		       BYTE b_ClockSelection,
+@@ -38,7 +38,7 @@ INT i_APCI1710_InitPWM(comedi_device *dev,
+ 		       ULONG ul_HighTiming,
+ 		       PULONG pul_RealLowTiming, PULONG pul_RealHighTiming);
+ 
+-INT i_APCI1710_GetPWMInitialisation(comedi_device *dev,
++INT i_APCI1710_GetPWMInitialisation(struct comedi_device *dev,
+ 				    BYTE b_ModulNbr,
+ 				    BYTE b_PWM,
+ 				    PBYTE pb_TimingUnit,
+@@ -50,10 +50,10 @@ INT i_APCI1710_GetPWMInitialisation(comedi_device *dev,
+ 				    PBYTE pb_ExternGate,
+ 				    PBYTE pb_InterruptEnable, PBYTE pb_Enable);
+ 
+-INT i_APCI1710_InsnWritePWM(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnWritePWM(struct comedi_device *dev, comedi_subdevice *s,
+ 			    comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_EnablePWM(comedi_device *dev,
++INT i_APCI1710_EnablePWM(struct comedi_device *dev,
+ 			 BYTE b_ModulNbr,
+ 			 BYTE b_PWM,
+ 			 BYTE b_StartLevel,
+@@ -61,16 +61,16 @@ INT i_APCI1710_EnablePWM(comedi_device *dev,
+ 			 BYTE b_StopLevel, BYTE b_ExternGate,
+ 			 BYTE b_InterruptEnable);
+ 
+-INT i_APCI1710_SetNewPWMTiming(comedi_device *dev,
++INT i_APCI1710_SetNewPWMTiming(struct comedi_device *dev,
+ 			       BYTE b_ModulNbr,
+ 			       BYTE b_PWM, BYTE b_TimingUnit,
+ 			       ULONG ul_LowTiming, ULONG ul_HighTiming);
+ 
+-INT i_APCI1710_DisablePWM(comedi_device *dev, BYTE b_ModulNbr, BYTE b_PWM);
++INT i_APCI1710_DisablePWM(struct comedi_device *dev, BYTE b_ModulNbr, BYTE b_PWM);
+ 
+-INT i_APCI1710_InsnReadGetPWMStatus(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnReadGetPWMStatus(struct comedi_device *dev, comedi_subdevice *s,
+ 				    comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_InsnBitsReadPWMInterrupt(comedi_device *dev,
++INT i_APCI1710_InsnBitsReadPWMInterrupt(struct comedi_device *dev,
+ 					comedi_subdevice *s,
+ 					comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+index 650b5752e61a..de2b158698f6 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+@@ -133,7 +133,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnConfigInitSSI(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnConfigInitSSI(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -362,7 +362,7 @@ INT i_APCI1710_InsnConfigInitSSI(comedi_device * dev, comedi_subdevice * s,
+ |                                BYTE_     b_SelectedSSI,                    |
+ |                                PULONG_ pul_Position,                       |
+ |                                PULONG_ pul_TurnCpt)
+- INT i_APCI1710_ReadSSIValue(comedi_device *dev,comedi_subdevice *s,
++ INT i_APCI1710_ReadSSIValue(struct comedi_device *dev,comedi_subdevice *s,
+ 	comedi_insn *insn,unsigned int *data)                       |
+ +----------------------------------------------------------------------------+
+ | Task              :
+@@ -400,7 +400,7 @@ pul_Position	=	(PULONG) &data[0];
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnReadSSIValue(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnReadSSIValue(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -735,7 +735,7 @@ INT i_APCI1710_InsnReadSSIValue(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnBitsSSIDigitalIO(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h
+index a0ad47d2f7a8..2a631b8163c4 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h
+@@ -33,11 +33,11 @@
+ /*
+  * SSI INISIALISATION FUNCTION
+  */
+-INT i_APCI1710_InsnConfigInitSSI(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnConfigInitSSI(struct comedi_device *dev, comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_InsnReadSSIValue(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnReadSSIValue(struct comedi_device *dev, comedi_subdevice *s,
+ 				comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_InsnBitsSSIDigitalIO(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev, comedi_subdevice *s,
+ 				    comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+index 09d5a2fadee6..a9cad8066a54 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+@@ -130,7 +130,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnConfigInitTorCounter(comedi_device * dev,
++INT i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -987,7 +987,7 @@ INT i_APCI1710_InsnConfigInitTorCounter(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnWriteEnableDisableTorCounter(comedi_device * dev,
++INT i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -1460,7 +1460,7 @@ INT i_APCI1710_InsnWriteEnableDisableTorCounter(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnReadGetTorCounterInitialisation(comedi_device * dev,
++INT i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -1700,7 +1700,7 @@ INT i_APCI1710_InsnReadGetTorCounterInitialisation(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(comedi_device * dev,
++INT i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h
+index a4807de42441..80d100a9bc92 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h
+@@ -35,23 +35,23 @@
+ /*
+  * TOR_COUNTER INISIALISATION FUNCTION
+  */
+-INT i_APCI1710_InsnConfigInitTorCounter(comedi_device *dev,
++INT i_APCI1710_InsnConfigInitTorCounter(struct comedi_device *dev,
+ 					comedi_subdevice *s,
+ 					comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1710_InsnWriteEnableDisableTorCounter(comedi_device *dev,
++INT i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device *dev,
+ 						comedi_subdevice *s,
+ 						comedi_insn *insn,
+ 						unsigned int *data);
+ 
+-INT i_APCI1710_InsnReadGetTorCounterInitialisation(comedi_device *dev,
++INT i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device *dev,
+ 						   comedi_subdevice *s,
+ 						   comedi_insn *insn,
+ 						   unsigned int *data);
+ /*
+  * TOR_COUNTER READ FUNCTION
+  */
+-INT i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(comedi_device *dev,
++INT i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device *dev,
+ 							   comedi_subdevice *s,
+ 							   comedi_insn *insn,
+ 							   unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+index 0a40f46442e9..9932fc1fa55f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+@@ -100,7 +100,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnConfigInitTTLIO(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnConfigInitTTLIO(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -406,7 +406,7 @@ APCI1710_TTL_READCHANNEL
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnBitsReadTTLIO(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -655,7 +655,7 @@ INT i_APCI1710_InsnBitsReadTTLIO(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnReadTTLIOAllPortValue(comedi_device * dev,
++INT i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+@@ -792,7 +792,7 @@ INT i_APCI1710_InsnReadTTLIOAllPortValue(comedi_device * dev,
+ |                               (BYTE_           b_BoardHandle,              |
+ |                                BYTE_           b_ModulNbr,                 |
+ |                                BYTE_           b_OutputChannel)
+-INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(comedi_device *dev,comedi_subdevice *s,
++INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,comedi_subdevice *s,
+ 	comedi_insn *insn,unsigned int *data)           |
+ +----------------------------------------------------------------------------+
+ | Task              : Sets or resets  the output witch has been passed with the         |
+@@ -825,7 +825,7 @@ INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(comedi_device *dev,comedi_subdevice *s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(comedi_device * dev,
++INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h
+index 8993ac642736..d0bde4bb809a 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h
+@@ -24,21 +24,21 @@
+ /*
+  * TTL INISIALISATION FUNCTION
+  */
+-INT i_APCI1710_InsnConfigInitTTLIO(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnConfigInitTTLIO(struct comedi_device *dev, comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * TTL INPUT FUNCTION
+  */
+-INT i_APCI1710_InsnBitsReadTTLIO(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device *dev, comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+-INT i_APCI1710_InsnReadTTLIOAllPortValue(comedi_device *dev,
++INT i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
+ 					 comedi_subdevice *s,
+ 					 comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * TTL OUTPUT FUNCTIONS
+  */
+-INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(comedi_device *dev,
++INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,
+ 					 comedi_subdevice *s,
+ 					 comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+index 4cd552568ac3..1e091eca8019 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+@@ -2541,7 +2541,7 @@ COMEDI_PCI_INITCLEANUP(driver_addi, addi_apci_tbl);
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function name     :static int i_ADDI_Attach(comedi_device *dev,            |
++| Function name     :static int i_ADDI_Attach(struct comedi_device *dev,            |
+ |										comedi_devconfig *it)        |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+@@ -2550,7 +2550,7 @@ COMEDI_PCI_INITCLEANUP(driver_addi, addi_apci_tbl);
+ |  			 This function does all the initializations and memory   |
+ |			 allocation of data structures for the driver.	         |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  :comedi_device *dev										 |
++| Input Parameters  :struct comedi_device *dev										 |
+ |                    comedi_devconfig *it									 |
+ |                                                 					         |
+ +----------------------------------------------------------------------------+
+@@ -2559,7 +2559,7 @@ COMEDI_PCI_INITCLEANUP(driver_addi, addi_apci_tbl);
+ +----------------------------------------------------------------------------+
+ */
+ 
+-static int i_ADDI_Attach(comedi_device * dev, comedi_devconfig * it)
++static int i_ADDI_Attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	int ret, pages, i, n_subdevices;
+@@ -2909,7 +2909,7 @@ static int i_ADDI_Attach(comedi_device * dev, comedi_devconfig * it)
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function name     : static int i_ADDI_Detach(comedi_device *dev)           |
++| Function name     : static int i_ADDI_Detach(struct comedi_device *dev)           |
+ |                                        									 |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+@@ -2917,7 +2917,7 @@ static int i_ADDI_Attach(comedi_device * dev, comedi_devconfig * it)
+ |			  Free the DMA buffers, unregister irq.				     |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev									 |
++| Input Parameters  : struct comedi_device *dev									 |
+ |                     														 |
+ |                                                 					         |
+ +----------------------------------------------------------------------------+
+@@ -2926,7 +2926,7 @@ static int i_ADDI_Attach(comedi_device * dev, comedi_devconfig * it)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-static int i_ADDI_Detach(comedi_device * dev)
++static int i_ADDI_Detach(struct comedi_device * dev)
+ {
+ 
+ 	if (dev->private) {
+@@ -2976,14 +2976,14 @@ static int i_ADDI_Detach(comedi_device * dev)
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function name     : static int i_ADDI_Reset(comedi_device *dev)			 |
++| Function name     : static int i_ADDI_Reset(struct comedi_device *dev)			 |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              : Disables all interrupts, Resets digital output to low, |
+ |				Set all analog output to low						 |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev									 |
++| Input Parameters  : struct comedi_device *dev									 |
+ |                     														 |
+ |                                                 					         |
+ +----------------------------------------------------------------------------+
+@@ -2992,7 +2992,7 @@ static int i_ADDI_Detach(comedi_device * dev)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-static int i_ADDI_Reset(comedi_device * dev)
++static int i_ADDI_Reset(struct comedi_device * dev)
+ {
+ 
+ 	this_board->i_hwdrv_Reset(dev);
+@@ -3020,7 +3020,7 @@ static int i_ADDI_Reset(comedi_device * dev)
+ 
+ static irqreturn_t v_ADDI_Interrupt(int irq, void *d PT_REGS_ARG)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	this_board->v_hwdrv_Interrupt(irq, d);
+ 	return IRQ_RETVAL(1);
+ }
+@@ -3029,14 +3029,14 @@ static irqreturn_t v_ADDI_Interrupt(int irq, void *d PT_REGS_ARG)
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :                                                        |
+-|INT i_ADDIDATA_InsnReadEeprom(comedi_device *dev,comedi_subdevice *s,
++|INT i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev,comedi_subdevice *s,
+ 							comedi_insn *insn,unsigned int *data)
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              : Read 256 words from EEPROM          				     |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  :(comedi_device *dev,comedi_subdevice *s,
++| Input Parameters  :(struct comedi_device *dev,comedi_subdevice *s,
+ 			comedi_insn *insn,unsigned int *data) 						 |
+ |                     														 |
+ |                                                 					         |
+@@ -3046,7 +3046,7 @@ static irqreturn_t v_ADDI_Interrupt(int irq, void *d PT_REGS_ARG)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-static int i_ADDIDATA_InsnReadEeprom(comedi_device * dev, comedi_subdevice * s,
++static int i_ADDIDATA_InsnReadEeprom(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	WORD w_Data;
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+index ca7c5cb4dac6..9f3aa717b403 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+@@ -112,108 +112,108 @@ typedef struct {
+ 
+ 	/* interrupt and reset */
+ 	void (*v_hwdrv_Interrupt)(int irq, void *d);
+-	int (*i_hwdrv_Reset)(comedi_device *dev);
++	int (*i_hwdrv_Reset)(struct comedi_device *dev);
+ 
+ 	/* Subdevice functions */
+ 
+ 	/* ANALOG INPUT */
+-	int (*i_hwdrv_InsnConfigAnalogInput)(comedi_device *dev,
++	int (*i_hwdrv_InsnConfigAnalogInput)(struct comedi_device *dev,
+ 					     comedi_subdevice *s,
+ 					     comedi_insn *insn,
+ 					     unsigned int *data);
+-	int (*i_hwdrv_InsnReadAnalogInput)(comedi_device *dev,
++	int (*i_hwdrv_InsnReadAnalogInput)(struct comedi_device *dev,
+ 					    comedi_subdevice *s,
+ 					    comedi_insn *insn,
+ 					    unsigned int *data);
+-	int (*i_hwdrv_InsnWriteAnalogInput)(comedi_device *dev,
++	int (*i_hwdrv_InsnWriteAnalogInput)(struct comedi_device *dev,
+ 					    comedi_subdevice *s,
+ 					    comedi_insn *insn,
+ 					    unsigned int *data);
+-	int (*i_hwdrv_InsnBitsAnalogInput)(comedi_device *dev,
++	int (*i_hwdrv_InsnBitsAnalogInput)(struct comedi_device *dev,
+ 					   comedi_subdevice *s,
+ 					   comedi_insn *insn,
+ 					   unsigned int *data);
+-	int (*i_hwdrv_CommandTestAnalogInput)(comedi_device *dev,
++	int (*i_hwdrv_CommandTestAnalogInput)(struct comedi_device *dev,
+ 					      comedi_subdevice *s,
+ 					      comedi_cmd *cmd);
+-	int (*i_hwdrv_CommandAnalogInput)(comedi_device *dev,
++	int (*i_hwdrv_CommandAnalogInput)(struct comedi_device *dev,
+ 					  comedi_subdevice *s);
+-	int (*i_hwdrv_CancelAnalogInput)(comedi_device *dev,
++	int (*i_hwdrv_CancelAnalogInput)(struct comedi_device *dev,
+ 					 comedi_subdevice *s);
+ 
+ 	/* Analog Output */
+-	int (*i_hwdrv_InsnConfigAnalogOutput)(comedi_device *dev,
++	int (*i_hwdrv_InsnConfigAnalogOutput)(struct comedi_device *dev,
+ 					      comedi_subdevice *s,
+ 					      comedi_insn *insn,
+ 					      unsigned int *data);
+-	int (*i_hwdrv_InsnWriteAnalogOutput)(comedi_device *dev,
++	int (*i_hwdrv_InsnWriteAnalogOutput)(struct comedi_device *dev,
+ 					     comedi_subdevice *s,
+ 					     comedi_insn *insn,
+ 					     unsigned int *data);
+-	int (*i_hwdrv_InsnBitsAnalogOutput)(comedi_device *dev,
++	int (*i_hwdrv_InsnBitsAnalogOutput)(struct comedi_device *dev,
+ 					    comedi_subdevice *s,
+ 					    comedi_insn *insn,
+ 					    unsigned int *data);
+ 
+ 	/* Digital Input */
+-	int (*i_hwdrv_InsnConfigDigitalInput) (comedi_device *dev,
++	int (*i_hwdrv_InsnConfigDigitalInput) (struct comedi_device *dev,
+ 					       comedi_subdevice *s,
+ 					       comedi_insn *insn,
+ 					       unsigned int *data);
+-	int (*i_hwdrv_InsnReadDigitalInput) (comedi_device *dev,
++	int (*i_hwdrv_InsnReadDigitalInput) (struct comedi_device *dev,
+ 					     comedi_subdevice *s,
+ 					     comedi_insn *insn,
+ 					     unsigned int *data);
+-	int (*i_hwdrv_InsnWriteDigitalInput) (comedi_device *dev,
++	int (*i_hwdrv_InsnWriteDigitalInput) (struct comedi_device *dev,
+ 					      comedi_subdevice *s,
+ 					      comedi_insn *insn,
+ 					      unsigned int *data);
+-	int (*i_hwdrv_InsnBitsDigitalInput) (comedi_device *dev,
++	int (*i_hwdrv_InsnBitsDigitalInput) (struct comedi_device *dev,
+ 					     comedi_subdevice *s,
+ 					     comedi_insn *insn,
+ 					     unsigned int *data);
+ 
+ 	/* Digital Output */
+-	int (*i_hwdrv_InsnConfigDigitalOutput)(comedi_device *dev,
++	int (*i_hwdrv_InsnConfigDigitalOutput)(struct comedi_device *dev,
+ 					       comedi_subdevice *s,
+ 					       comedi_insn *insn,
+ 					       unsigned int *data);
+-	int (*i_hwdrv_InsnWriteDigitalOutput)(comedi_device *dev,
++	int (*i_hwdrv_InsnWriteDigitalOutput)(struct comedi_device *dev,
+ 					      comedi_subdevice *s,
+ 					      comedi_insn *insn,
+ 					      unsigned int *data);
+-	int (*i_hwdrv_InsnBitsDigitalOutput)(comedi_device *dev,
++	int (*i_hwdrv_InsnBitsDigitalOutput)(struct comedi_device *dev,
+ 					     comedi_subdevice *s,
+ 					     comedi_insn *insn,
+ 					     unsigned int *data);
+-	int (*i_hwdrv_InsnReadDigitalOutput)(comedi_device *dev,
++	int (*i_hwdrv_InsnReadDigitalOutput)(struct comedi_device *dev,
+ 					     comedi_subdevice *s,
+ 					     comedi_insn *insn,
+ 					     unsigned int *data);
+ 
+ 	/* TIMER */
+-	int (*i_hwdrv_InsnConfigTimer)(comedi_device *dev,
++	int (*i_hwdrv_InsnConfigTimer)(struct comedi_device *dev,
+ 				       comedi_subdevice *s,
+ 				       comedi_insn *insn, unsigned int *data);
+-	int (*i_hwdrv_InsnWriteTimer)(comedi_device *dev,
++	int (*i_hwdrv_InsnWriteTimer)(struct comedi_device *dev,
+ 				      comedi_subdevice *s, comedi_insn *insn,
+ 				      unsigned int *data);
+-	int (*i_hwdrv_InsnReadTimer)(comedi_device *dev, comedi_subdevice *s,
++	int (*i_hwdrv_InsnReadTimer)(struct comedi_device *dev, comedi_subdevice *s,
+ 				     comedi_insn *insn, unsigned int *data);
+-	int (*i_hwdrv_InsnBitsTimer)(comedi_device *dev, comedi_subdevice *s,
++	int (*i_hwdrv_InsnBitsTimer)(struct comedi_device *dev, comedi_subdevice *s,
+ 				     comedi_insn *insn, unsigned int *data);
+ 
+ 	/* TTL IO */
+-	int (*i_hwdr_ConfigInitTTLIO)(comedi_device *dev,
++	int (*i_hwdr_ConfigInitTTLIO)(struct comedi_device *dev,
+ 				      comedi_subdevice *s, comedi_insn *insn,
+ 				      unsigned int *data);
+-	int (*i_hwdr_ReadTTLIOBits)(comedi_device *dev, comedi_subdevice *s,
++	int (*i_hwdr_ReadTTLIOBits)(struct comedi_device *dev, comedi_subdevice *s,
+ 				    comedi_insn *insn, unsigned int *data);
+-	int (*i_hwdr_ReadTTLIOAllPortValue)(comedi_device *dev,
++	int (*i_hwdr_ReadTTLIOAllPortValue)(struct comedi_device *dev,
+ 					    comedi_subdevice *s,
+ 					    comedi_insn *insn,
+ 					    unsigned int *data);
+-	int (*i_hwdr_WriteTTLIOChlOnOff)(comedi_device *dev,
++	int (*i_hwdr_WriteTTLIOChlOnOff)(struct comedi_device *dev,
+ 					 comedi_subdevice *s,
+ 					 comedi_insn *insn, unsigned int *data);
+ } boardtype;
+@@ -456,10 +456,10 @@ typedef struct {
+ static unsigned short pci_list_builded;	/* set to 1 when list of card is known */
+ 
+ /* Function declarations */
+-static int i_ADDI_Attach(comedi_device *dev, comedi_devconfig *it);
+-static int i_ADDI_Detach(comedi_device *dev);
+-static int i_ADDI_Reset(comedi_device *dev);
++static int i_ADDI_Attach(struct comedi_device *dev, comedi_devconfig *it);
++static int i_ADDI_Detach(struct comedi_device *dev);
++static int i_ADDI_Reset(struct comedi_device *dev);
+ 
+ static irqreturn_t v_ADDI_Interrupt(int irq, void *d PT_REGS_ARG);
+-static int i_ADDIDATA_InsnReadEeprom(comedi_device *dev, comedi_subdevice *s,
++static int i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev, comedi_subdevice *s,
+ 				     comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+index b8fa5c9071a6..bf83af20f489 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+@@ -121,7 +121,7 @@ typedef struct {
+ 		/*****************************************/
+ 
+ INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress,
+-	PCHAR pc_PCIChipInformation, comedi_device * dev);
++	PCHAR pc_PCIChipInformation, struct comedi_device *dev);
+ 
+ INT i_EepromReadDigitalInputHeader(WORD w_PCIBoardEepromAddress,
+ 	PCHAR pc_PCIChipInformation, WORD w_Address,
+@@ -787,7 +787,7 @@ VOID v_EepromCs76Read(DWORD dw_Address, WORD w_offset, PWORD pw_Value)
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name  : INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress,  |
+-|				PCHAR 	pc_PCIChipInformation,comedi_device *dev)    |
++|				PCHAR 	pc_PCIChipInformation,struct comedi_device *dev)    |
+ +----------------------------------------------------------------------------+
+ | Task              : Read from eeprom Main Header                           |
+ +----------------------------------------------------------------------------+
+@@ -795,7 +795,7 @@ VOID v_EepromCs76Read(DWORD dw_Address, WORD w_offset, PWORD pw_Value)
+ |																	 |
+ |		      PCHAR pc_PCIChipInformation  : PCI Chip Type.          |
+ |																	 |
+-|			  comedi_device *dev		   : comedi device structure |
++|			  struct comedi_device *dev		   : comedi device structure |
+ |											 pointer				 |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+@@ -805,7 +805,7 @@ VOID v_EepromCs76Read(DWORD dw_Address, WORD w_offset, PWORD pw_Value)
+ */
+ 
+ INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress,
+-	PCHAR pc_PCIChipInformation, comedi_device * dev)
++	PCHAR pc_PCIChipInformation, struct comedi_device *dev)
+ {
+ 	WORD w_Temp, i, w_Count = 0;
+ 	UINT ui_Temp;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+index e18d085bbd6b..7d6a6e05cdbc 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+@@ -56,7 +56,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ #include "APCI1710_Pwm.c"
+ #include "APCI1710_INCCPT.c"
+ 
+-void i_ADDI_AttachPCI1710(comedi_device * dev)
++void i_ADDI_AttachPCI1710(struct comedi_device * dev)
+ {
+ 	comedi_subdevice *s;
+ 	int ret = 0;
+@@ -195,11 +195,11 @@ void i_ADDI_AttachPCI1710(comedi_device * dev)
+ 	s->insn_bits = i_APCI1710_InsnBitsINCCPT;
+ }
+ 
+-int i_APCI1710_Reset(comedi_device * dev);
++int i_APCI1710_Reset(struct comedi_device * dev);
+ VOID v_APCI1710_Interrupt(int irq, void *d);
+ //for 1710
+ 
+-int i_APCI1710_Reset(comedi_device * dev)
++int i_APCI1710_Reset(struct comedi_device * dev)
+ {
+ 	int ret;
+ 	DWORD dw_Dummy;
+@@ -249,7 +249,7 @@ int i_APCI1710_Reset(comedi_device * dev)
+ 
+ VOID v_APCI1710_Interrupt(int irq, void *d)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	BYTE b_ModuleCpt = 0;
+ 	BYTE b_InterruptFlag = 0;
+ 	BYTE b_PWMCpt = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
+index 4a4356550a6c..599c7c3b68f7 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
+@@ -58,12 +58,12 @@ INT i_Flag = 1;
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI035_ConfigTimerWatchdog                      |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Timer , Counter or Watchdog             |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev : Driver handle                     |
++| Input Parameters  : struct comedi_device *dev : Driver handle                     |
+ |                     UINT *data         : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |                                                                            |
+@@ -109,7 +109,7 @@ INT i_Flag = 1;
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI035_ConfigTimerWatchdog(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI035_ConfigTimerWatchdog(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Status = 0;
+@@ -254,12 +254,12 @@ INT i_APCI035_ConfigTimerWatchdog(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI035_StartStopWriteTimerWatchdog              |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Start / Stop The Selected Timer , or Watchdog  |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev : Driver handle                     |
++| Input Parameters  : struct comedi_device *dev : Driver handle                     |
+ |                     UINT *data         : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |					                                                 |
+@@ -278,7 +278,7 @@ INT i_APCI035_ConfigTimerWatchdog(comedi_device * dev, comedi_subdevice * s,
+ |					                                                 |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI035_StartStopWriteTimerWatchdog(comedi_device * dev,
++INT i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Command = 0;
+@@ -367,12 +367,12 @@ INT i_APCI035_StartStopWriteTimerWatchdog(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI035_ReadTimerWatchdog                        |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Selected Timer , Counter or Watchdog          |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev : Driver handle                     |
++| Input Parameters  : struct comedi_device *dev : Driver handle                     |
+ |                     UINT *data         : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |                                                                            |
+@@ -391,7 +391,7 @@ INT i_APCI035_StartStopWriteTimerWatchdog(comedi_device * dev,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI035_ReadTimerWatchdog(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI035_ReadTimerWatchdog(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Status = 0;	// Status register
+@@ -427,12 +427,12 @@ INT i_APCI035_ReadTimerWatchdog(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : INT i_APCI035_ConfigAnalogInput                        |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Analog Input Subdevice                  |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     comedi_subdevice *s     : Subdevice Pointer            |
+ |                     comedi_insn *insn       : Insn Structure Pointer       |
+ |                     unsigned int *data          : Data Pointer contains        |
+@@ -447,7 +447,7 @@ INT i_APCI035_ReadTimerWatchdog(comedi_device * dev, comedi_subdevice * s,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI035_ConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI035_ConfigAnalogInput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	devpriv->tsk_Current = current;
+@@ -466,12 +466,12 @@ INT i_APCI035_ConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI035_ReadAnalogInput                          |
+-|			          (comedi_device *dev,comedi_subdevice *s,       |
++|			          (struct comedi_device *dev,comedi_subdevice *s,       |
+ |                     comedi_insn *insn,unsigned int *data)                      |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel			         |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     UINT ui_NoOfChannels    : No Of Channels To read       |
+ |                     UINT *data              : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -484,7 +484,7 @@ INT i_APCI035_ConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI035_ReadAnalogInput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI035_ReadAnalogInput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_CommandRegister = 0;
+@@ -506,7 +506,7 @@ INT i_APCI035_ReadAnalogInput(comedi_device * dev, comedi_subdevice * s,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function   Name   :  int i_APCI035_Reset(comedi_device *dev)			     |
++| Function   Name   :  int i_APCI035_Reset(struct comedi_device *dev)			     |
+ |					                                                         |
+ +----------------------------------------------------------------------------+
+ | Task              :Resets the registers of the card                        |
+@@ -519,7 +519,7 @@ INT i_APCI035_ReadAnalogInput(comedi_device * dev, comedi_subdevice * s,
+ |			                                                                 |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI035_Reset(comedi_device * dev)
++INT i_APCI035_Reset(struct comedi_device * dev)
+ {
+ 	INT i_Count = 0;
+ 	for (i_Count = 1; i_Count <= 4; i_Count++) {
+@@ -550,7 +550,7 @@ INT i_APCI035_Reset(comedi_device * dev)
+ */
+ static void v_APCI035_Interrupt(int irq, void *d)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	UINT ui_StatusRegister1 = 0;
+ 	UINT ui_StatusRegister2 = 0;
+ 	UINT ui_ReadCommand = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
+index 0e4ec157ad3a..c0330d8a3137 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
+@@ -101,23 +101,23 @@ comedi_lrange range_apci035_ai = { 8, {
+ 
+ /* TIMER */
+ /* timer value is passed as u seconds */
+-INT i_APCI035_ConfigTimerWatchdog(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI035_ConfigTimerWatchdog(struct comedi_device *dev, comedi_subdevice *s,
+ 				  comedi_insn *insn, unsigned int *data);
+-INT i_APCI035_StartStopWriteTimerWatchdog(comedi_device *dev,
++INT i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device *dev,
+ 					  comedi_subdevice *s,
+ 					  comedi_insn *insn, unsigned int *data);
+-INT i_APCI035_ReadTimerWatchdog(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI035_ReadTimerWatchdog(struct comedi_device *dev, comedi_subdevice *s,
+ 				comedi_insn *insn, unsigned int *data);
+ 
+ /* Temperature Related Defines (Analog Input Subdevice) */
+ 
+-INT i_APCI035_ConfigAnalogInput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI035_ConfigAnalogInput(struct comedi_device *dev, comedi_subdevice *s,
+ 				comedi_insn *insn, unsigned int *data);
+-INT i_APCI035_ReadAnalogInput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI035_ReadAnalogInput(struct comedi_device *dev, comedi_subdevice *s,
+ 			      comedi_insn *insn, unsigned int *data);
+ 
+ /* Interrupt */
+ static void v_APCI035_Interrupt(int irq, void *d);
+ 
+ /* Reset functions */
+-INT i_APCI035_Reset(comedi_device *dev);
++INT i_APCI035_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+index 5f65d1d4baab..bdfe5e95eb61 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+@@ -59,12 +59,12 @@ UINT ui_InterruptStatus = 0;
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1032_ConfigDigitalInput                      |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures the digital input Subdevice                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev : Driver handle                     |
++| Input Parameters  : struct comedi_device *dev : Driver handle                     |
+ |                     unsigned int *data         : Data Pointer contains         |
+ |                                          configuration parameters as below |
+ |                                                                            |
+@@ -84,7 +84,7 @@ UINT ui_InterruptStatus = 0;
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1032_ConfigDigitalInput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1032_ConfigDigitalInput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue;
+@@ -128,12 +128,12 @@ INT i_APCI1032_ConfigDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1032_Read1DigitalInput                       |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the digital input                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |		              UINT ui_Channel : Channel number to read       |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -144,7 +144,7 @@ INT i_APCI1032_ConfigDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1032_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1032_Read1DigitalInput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue = 0;
+@@ -166,12 +166,12 @@ INT i_APCI1032_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1032_ReadMoreDigitalInput                    |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                     comedi_insn *insn,unsigned int *data)                      |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the Requested digital inputs      |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     UINT ui_NoOfChannels    : No Of Channels To be Read    |
+ |                      UINT *data             : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -183,7 +183,7 @@ INT i_APCI1032_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1032_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1032_ReadMoreDigitalInput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_PortValue = data[0];
+@@ -245,7 +245,7 @@ INT i_APCI1032_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ */
+ static VOID v_APCI1032_Interrupt(int irq, void *d)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 
+ 	UINT ui_Temp;
+ 	//disable the interrupt
+@@ -262,11 +262,11 @@ static VOID v_APCI1032_Interrupt(int irq, void *d)
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function   Name   : int i_APCI1032_Reset(comedi_device *dev)               |                                                       |
++| Function   Name   : int i_APCI1032_Reset(struct comedi_device *dev)               |                                                       |
+ +----------------------------------------------------------------------------+
+ | Task              :resets all the registers                                |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev
++| Input Parameters  : struct comedi_device *dev
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -275,7 +275,7 @@ static VOID v_APCI1032_Interrupt(int irq, void *d)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1032_Reset(comedi_device * dev)
++INT i_APCI1032_Reset(struct comedi_device * dev)
+ {
+ 	outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);	//disable the interrupts
+ 	inl(devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_STATUS);	//Reset the interrupt status register
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
+index 51abd4f073de..cb96ff1778c5 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
+@@ -47,17 +47,17 @@
+ //DI
+ // for di read
+ 
+-INT i_APCI1032_ConfigDigitalInput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1032_ConfigDigitalInput(struct comedi_device *dev, comedi_subdevice *s,
+ 				  comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1032_Read1DigitalInput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1032_Read1DigitalInput(struct comedi_device *dev, comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+ 
+-INT i_APCI1032_ReadMoreDigitalInput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1032_ReadMoreDigitalInput(struct comedi_device *dev, comedi_subdevice *s,
+ 				    comedi_insn *insn, unsigned int *data);
+ 
+ // Interrupt functions.....
+ 
+ static VOID v_APCI1032_Interrupt(int irq, void *d);
+ //Reset
+-INT i_APCI1032_Reset(comedi_device *dev);
++INT i_APCI1032_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+index 33885c55be9d..9a786c9060b6 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+@@ -61,7 +61,7 @@ int i_TimerCounter1Enabled = 0, i_TimerCounter2Enabled =
+ /*
+   +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_ConfigDigitalInputEvent                 |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : An event can be generated for each port.               |
+@@ -70,7 +70,7 @@ int i_TimerCounter1Enabled = 0, i_TimerCounter2Enabled =
+ |                     (port 2). An interrupt is generated when one or both   |
+ |                     events have occurred                                   |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev : Driver handle                     |
++| Input Parameters  : struct comedi_device *dev : Driver handle                     |
+ |                     unsigned int *data     : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |                                                                            |
+@@ -137,7 +137,7 @@ int i_TimerCounter1Enabled = 0, i_TimerCounter2Enabled =
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1500_ConfigDigitalInputEvent(comedi_device * dev,
++INT i_APCI1500_ConfigDigitalInputEvent(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_PatternPolarity = 0, i_PatternTransition = 0, i_PatternMask = 0;
+@@ -500,12 +500,12 @@ INT i_APCI1500_ConfigDigitalInputEvent(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_StartStopInputEvent                     |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              :  Allows or disallows a port event                      |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |		              UINT ui_Channel : Channel number to read       |
+ |                     unsigned int *data          : Data Pointer to read status  |
+                       data[0]                 :0 Start input event
+@@ -519,7 +519,7 @@ INT i_APCI1500_ConfigDigitalInputEvent(comedi_device * dev,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1500_StartStopInputEvent(comedi_device * dev, comedi_subdevice * s,
++int i_APCI1500_StartStopInputEvent(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_Event1InterruptStatus = 0, i_Event2InterruptStatus =
+@@ -768,12 +768,12 @@ int i_APCI1500_StartStopInputEvent(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_Initialisation                          |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the digital input                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |		              UINT ui_Channel : Channel number to read       |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -784,7 +784,7 @@ int i_APCI1500_StartStopInputEvent(comedi_device * dev, comedi_subdevice * s,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1500_Initialisation(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1500_Initialisation(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_DummyRead = 0;
+@@ -937,12 +937,12 @@ INT i_APCI1500_Initialisation(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_ReadMoreDigitalInput                    |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                     comedi_insn *insn,unsigned int *data)                      |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the Requested digital inputs      |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     UINT ui_NoOfChannels    : No Of Channels To be Read    |
+ |                      UINT *data             : Data Pointer
+                       data[0]                 : 0 Read a single channel
+@@ -957,7 +957,7 @@ INT i_APCI1500_Initialisation(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1500_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1500_ReadMoreDigitalInput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_PortValue = data[1];
+@@ -1015,14 +1015,14 @@ INT i_APCI1500_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_ConfigDigitalOutputErrorInterrupt
+-                      (comedi_device *dev,comedi_subdevice *s comedi_insn
++                      (struct comedi_device *dev,comedi_subdevice *s comedi_insn
+                       *insn,unsigned int *data)                                  |
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures the digital output memory and the digital
+                       output error interrupt                                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev : Driver handle                     |
++| Input Parameters  : struct comedi_device *dev : Driver handle                     |
+ |                     unsigned int *data         : Data Pointer contains         |
+ |                                          configuration parameters as below |
+ |                      comedi_subdevice *s,   :pointer to subdevice structure
+@@ -1040,7 +1040,7 @@ INT i_APCI1500_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1500_ConfigDigitalOutputErrorInterrupt(comedi_device * dev,
++int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	devpriv->b_OutputMemoryStatus = data[0];
+@@ -1050,12 +1050,12 @@ int i_APCI1500_ConfigDigitalOutputErrorInterrupt(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_WriteDigitalOutput                      |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes port value  To the selected port                |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     UINT ui_NoOfChannels    : No Of Channels To Write      |
+ |                     UINT *data              : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -1067,7 +1067,7 @@ int i_APCI1500_ConfigDigitalOutputErrorInterrupt(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1500_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1500_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	static UINT ui_Temp = 0;
+@@ -1220,7 +1220,7 @@ INT i_APCI1500_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Watchdog                                |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data         : Data Pointer to read status                                                       data[0]                : 2     APCI1500_1_8_KHZ
+@@ -1261,7 +1261,7 @@ INT i_APCI1500_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1500_ConfigCounterTimerWatchdog(comedi_device * dev,
++int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_TimerCounterMode, i_MasterConfiguration;
+@@ -1835,12 +1835,12 @@ int i_APCI1500_ConfigCounterTimerWatchdog(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_StartStopTriggerTimerCounterWatchdog      |
+-|				(comedi_device *dev,comedi_subdevice *s,
++|				(struct comedi_device *dev,comedi_subdevice *s,
+                          comedi_insn *insn,unsigned int *data);                  |
+ +----------------------------------------------------------------------------+
+ | Task              : Start / Stop or trigger the timer counter or Watchdog  |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev     : Driver handle                 |
++| Input Parameters  : struct comedi_device *dev     : Driver handle                 |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data         : Data Pointer to read status   |
+@@ -1860,7 +1860,7 @@ int i_APCI1500_ConfigCounterTimerWatchdog(comedi_device * dev,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1500_StartStopTriggerTimerCounterWatchdog(comedi_device * dev,
++int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_CommandAndStatusValue;
+@@ -2160,12 +2160,12 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_ReadCounterTimerWatchdog                |
+-|			(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+                     unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Watchdog                                      |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  :   comedi_device *dev      : Driver handle              |
++| Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+@@ -2182,7 +2182,7 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1500_ReadCounterTimerWatchdog(comedi_device * dev,
++int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_CommandAndStatusValue;
+@@ -2351,12 +2351,12 @@ int i_APCI1500_ReadCounterTimerWatchdog(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int  i_APCI1500_ReadInterruptMask                      |
+-|			(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+                     unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read the interrupt mask                                |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  :   comedi_device *dev      : Driver handle              |
++| Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+@@ -2370,7 +2370,7 @@ int i_APCI1500_ReadCounterTimerWatchdog(comedi_device * dev,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1500_ReadInterruptMask(comedi_device * dev, comedi_subdevice * s,
++int i_APCI1500_ReadInterruptMask(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = i_InterruptMask;
+@@ -2382,12 +2382,12 @@ int i_APCI1500_ReadInterruptMask(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int  i_APCI1500_ConfigureInterrupt                     |
+-|			(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+                     unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures the interrupt registers                     |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  :   comedi_device *dev      : Driver handle              |
++| Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer                 |
+@@ -2401,7 +2401,7 @@ int i_APCI1500_ReadInterruptMask(comedi_device * dev, comedi_subdevice * s,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1500_ConfigureInterrupt(comedi_device * dev, comedi_subdevice * s,
++int i_APCI1500_ConfigureInterrupt(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Status;
+@@ -2579,7 +2579,7 @@ int i_APCI1500_ConfigureInterrupt(comedi_device * dev, comedi_subdevice * s,
+ static VOID v_APCI1500_Interrupt(int irq, void *d)
+ {
+ 
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	UINT ui_InterruptStatus = 0;
+ 	int i_RegValue = 0;
+ 	i_InterruptMask = 0;
+@@ -2809,11 +2809,11 @@ static VOID v_APCI1500_Interrupt(int irq, void *d)
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function   Name   : int i_APCI1500_Reset(comedi_device *dev)               |                                                       |
++| Function   Name   : int i_APCI1500_Reset(struct comedi_device *dev)               |                                                       |
+ +----------------------------------------------------------------------------+
+ | Task              :resets all the registers                                |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev
++| Input Parameters  : struct comedi_device *dev
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -2822,7 +2822,7 @@ static VOID v_APCI1500_Interrupt(int irq, void *d)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1500_Reset(comedi_device * dev)
++INT i_APCI1500_Reset(struct comedi_device * dev)
+ {
+ 	int i_DummyRead = 0;
+ 	i_TimerCounter1Init = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h
+index f1519e70cfbc..dc3f3ea78b0f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h
+@@ -116,50 +116,50 @@ enum {
+ };
+ 
+  /*----------DIGITAL INPUT----------------*/
+-static int i_APCI1500_Initialisation(comedi_device *dev, comedi_subdevice *s,
++static int i_APCI1500_Initialisation(struct comedi_device *dev, comedi_subdevice *s,
+ 				     comedi_insn *insn, unsigned int *data);
+-static int i_APCI1500_ConfigDigitalInputEvent(comedi_device *dev,
++static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
+ 					      comedi_subdevice *s,
+ 					      comedi_insn *insn,
+ 					      unsigned int *data);
+ 
+-static int i_APCI1500_StartStopInputEvent(comedi_device *dev,
++static int i_APCI1500_StartStopInputEvent(struct comedi_device *dev,
+ 					  comedi_subdevice *s,
+ 					  comedi_insn *insn, unsigned int *data);
+-static int i_APCI1500_ReadMoreDigitalInput(comedi_device *dev,
++static int i_APCI1500_ReadMoreDigitalInput(struct comedi_device *dev,
+ 					   comedi_subdevice *s,
+ 					   comedi_insn *insn, unsigned int *data);
+ 
+ /*----------	DIGITAL OUTPUT------------*/
+-static int i_APCI1500_ConfigDigitalOutputErrorInterrupt(comedi_device *dev,
++static int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device *dev,
+ 							comedi_subdevice *s,
+ 							comedi_insn *insn,
+ 							unsigned int *data);
+-static int i_APCI1500_WriteDigitalOutput(comedi_device *dev,
++static int i_APCI1500_WriteDigitalOutput(struct comedi_device *dev,
+ 					 comedi_subdevice *s,
+ 					 comedi_insn *insn, unsigned int *data);
+ 
+ /*----------TIMER----------------*/
+-static int i_APCI1500_ConfigCounterTimerWatchdog(comedi_device *dev,
++static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
+ 						 comedi_subdevice *s,
+ 						 comedi_insn *insn,
+ 						 unsigned int *data);
+-static int i_APCI1500_StartStopTriggerTimerCounterWatchdog(comedi_device *dev,
++static int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device *dev,
+ 							   comedi_subdevice *s,
+ 							   comedi_insn *insn,
+ 							   unsigned int *data);
+-static int i_APCI1500_ReadCounterTimerWatchdog(comedi_device *dev,
++static int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device *dev,
+ 					       comedi_subdevice *s,
+ 					       comedi_insn *insn,
+ 					       unsigned int *data);
+-static int i_APCI1500_ReadInterruptMask(comedi_device *dev,
++static int i_APCI1500_ReadInterruptMask(struct comedi_device *dev,
+ 					comedi_subdevice *s,
+ 					comedi_insn *insn, unsigned int *data);
+ 
+ /*----------INTERRUPT HANDLER------*/
+ static void v_APCI1500_Interrupt(int irq, void *d);
+-static int i_APCI1500_ConfigureInterrupt(comedi_device *dev,
++static int i_APCI1500_ConfigureInterrupt(struct comedi_device *dev,
+ 					 comedi_subdevice *s,
+ 					 comedi_insn *insn, unsigned int *data);
+ /*----------RESET---------------*/
+-static int i_APCI1500_Reset(comedi_device *dev);
++static int i_APCI1500_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
+index 5be566eda898..5ad419b9fa8e 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
+@@ -56,12 +56,12 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_Read1DigitalInput                       |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the digital input                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |		       comedi_subdevice *s,   :pointer to subdevice structure
+                        comedi_insn *insn      :pointer to insn structure     |
+ |                     unsigned int *data          : Data Pointer to read status  |
+@@ -73,7 +73,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1516_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1516_Read1DigitalInput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue = 0;
+@@ -96,12 +96,12 @@ INT i_APCI1516_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_ReadMoreDigitalInput                    |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                     comedi_insn *insn,unsigned int *data)                      |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the Requested digital inputs      |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                      comedi_subdevice *s,   :pointer to subdevice structure
+                        comedi_insn *insn      :pointer to insn structure     |
+ |                      unsigned int *data         : Data Pointer to read status  |
+@@ -114,7 +114,7 @@ INT i_APCI1516_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1516_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1516_ReadMoreDigitalInput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -148,13 +148,13 @@ INT i_APCI1516_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function   Name   : int i_APCI1516_ConfigDigitalOutput (comedi_device *dev,
++| Function   Name   : int i_APCI1516_ConfigDigitalOutput (struct comedi_device *dev,
+                     comedi_subdevice *s comedi_insn *insn,unsigned int *data)    |
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Digital Output Subdevice.               |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev : Driver handle                     |
++| Input Parameters  : struct comedi_device *dev : Driver handle                     |
+ |                     unsigned int *data         : Data Pointer contains         |
+ |                                          configuration parameters as below |
+ |                      comedi_subdevice *s,   :pointer to subdevice structure
+@@ -171,7 +171,7 @@ INT i_APCI1516_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI1516_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
++int i_APCI1516_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	devpriv->b_OutputMemoryStatus = data[0];
+@@ -181,12 +181,12 @@ int i_APCI1516_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_WriteDigitalOutput                      |
+-|			(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+                      unsigned int *data)                                         |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes port value  To the selected port                |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                    unsigned int *data           : Data Pointer to read status  |
+@@ -199,7 +199,7 @@ int i_APCI1516_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1516_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1516_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp, ui_Temp1;
+@@ -341,12 +341,12 @@ INT i_APCI1516_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_ReadDigitalOutput                       |
+-|			(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+                     unsigned int *data) 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+@@ -359,7 +359,7 @@ INT i_APCI1516_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1516_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1516_ReadDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -400,13 +400,13 @@ INT i_APCI1516_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function   Name   : int i_APCI1516_ConfigWatchdog(comedi_device *dev,
++| Function   Name   : int i_APCI1516_ConfigWatchdog(struct comedi_device *dev,
+                       comedi_subdevice *s,comedi_insn *insn,unsigned int *data)  |
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Watchdog                                |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  :   comedi_device *dev      : Driver handle              |
++| Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status                                                     |
+@@ -419,7 +419,7 @@ INT i_APCI1516_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1516_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
++int i_APCI1516_ConfigWatchdog(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0] == 0) {
+@@ -447,12 +447,12 @@ int i_APCI1516_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+  /*
+     +----------------------------------------------------------------------------+
+     | Function   Name   : int i_APCI1516_StartStopWriteWatchdog                  |
+-    |                           (comedi_device *dev,comedi_subdevice *s,
++    |                           (struct comedi_device *dev,comedi_subdevice *s,
+     comedi_insn *insn,unsigned int *data);                      |
+     +----------------------------------------------------------------------------+
+     | Task              : Start / Stop The Watchdog                              |
+     +----------------------------------------------------------------------------+
+-    | Input Parameters  : comedi_device *dev      : Driver handle                |
++    | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+     |                     comedi_subdevice *s,   :pointer to subdevice structure
+     comedi_insn *insn      :pointer to insn structure      |
+     |                     unsigned int *data          : Data Pointer to read status  |
+@@ -465,7 +465,7 @@ int i_APCI1516_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+     +----------------------------------------------------------------------------+
+   */
+ 
+-int i_APCI1516_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
++int i_APCI1516_StartStopWriteWatchdog(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+@@ -492,12 +492,12 @@ int i_APCI1516_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_ReadWatchdog                            |
+-|			(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+                     unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Watchdog                                      |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  :   comedi_device *dev      : Driver handle              |
++| Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+@@ -510,7 +510,7 @@ int i_APCI1516_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1516_ReadWatchdog(comedi_device * dev, comedi_subdevice * s,
++int i_APCI1516_ReadWatchdog(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = inw(devpriv->i_IobaseAddon + APCI1516_WATCHDOG_STATUS) & 0x1;
+@@ -519,11 +519,11 @@ int i_APCI1516_ReadWatchdog(comedi_device * dev, comedi_subdevice * s,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function   Name   : int i_APCI1516_Reset(comedi_device *dev)               |                                                                                                          |
++| Function   Name   : int i_APCI1516_Reset(struct comedi_device *dev)               |                                                                                                          |
+ +----------------------------------------------------------------------------+
+ | Task              :resets all the registers                                |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev
++| Input Parameters  : struct comedi_device *dev
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -532,7 +532,7 @@ int i_APCI1516_ReadWatchdog(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1516_Reset(comedi_device * dev)
++INT i_APCI1516_Reset(struct comedi_device * dev)
+ {
+ 	outw(0x0, devpriv->iobase + APCI1516_DIGITAL_OP);	//RESETS THE DIGITAL OUTPUTS
+ 	outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_ENABLEDISABLE);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h
+index 176e4785819e..b166257775ce 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h
+@@ -38,27 +38,27 @@
+ // Hardware Layer  functions for Apci1516
+ 
+ //Digital Input
+-INT i_APCI1516_ReadMoreDigitalInput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1516_ReadMoreDigitalInput(struct comedi_device *dev, comedi_subdevice *s,
+ 				    comedi_insn *insn, unsigned int *data);
+-INT i_APCI1516_Read1DigitalInput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1516_Read1DigitalInput(struct comedi_device *dev, comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+ 
+ //Digital Output
+-int i_APCI1516_ConfigDigitalOutput(comedi_device *dev, comedi_subdevice *s,
++int i_APCI1516_ConfigDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+-INT i_APCI1516_WriteDigitalOutput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1516_WriteDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
+ 				  comedi_insn *insn, unsigned int *data);
+-INT i_APCI1516_ReadDigitalOutput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1516_ReadDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+ // timer value is passed as u seconds
+-int i_APCI1516_ConfigWatchdog(comedi_device *dev, comedi_subdevice *s,
++int i_APCI1516_ConfigWatchdog(struct comedi_device *dev, comedi_subdevice *s,
+ 			      comedi_insn *insn, unsigned int *data);
+-int i_APCI1516_StartStopWriteWatchdog(comedi_device *dev, comedi_subdevice *s,
++int i_APCI1516_StartStopWriteWatchdog(struct comedi_device *dev, comedi_subdevice *s,
+ 				      comedi_insn *insn, unsigned int *data);
+-int i_APCI1516_ReadWatchdog(comedi_device *dev, comedi_subdevice *s,
++int i_APCI1516_ReadWatchdog(struct comedi_device *dev, comedi_subdevice *s,
+ 			    comedi_insn *insn, unsigned int *data);
+ 
+ //reset
+-INT i_APCI1516_Reset(comedi_device *dev);
++INT i_APCI1516_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+index cb7510930626..44b4965d8ecc 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+@@ -62,12 +62,12 @@ UINT ui_InterruptData, ui_Type;
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_ConfigDigitalInput                      |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures the digital input Subdevice                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev : Driver handle                     |
++| Input Parameters  : struct comedi_device *dev : Driver handle                     |
+ |                     unsigned int *data         : Data Pointer contains         |
+ |                                          configuration parameters as below |
+ |                                                                            |
+@@ -86,7 +86,7 @@ UINT ui_InterruptData, ui_Type;
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1564_ConfigDigitalInput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1564_ConfigDigitalInput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	devpriv->tsk_Current = current;
+@@ -131,12 +131,12 @@ INT i_APCI1564_ConfigDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_Read1DigitalInput                       |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the digital input                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |		              UINT ui_Channel : Channel number to read       |
+ |                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -147,7 +147,7 @@ INT i_APCI1564_ConfigDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1564_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1564_Read1DigitalInput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue = 0;
+@@ -171,12 +171,12 @@ INT i_APCI1564_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_ReadMoreDigitalInput                    |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                     comedi_insn *insn,unsigned int *data)                      |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the Requested digital inputs      |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     UINT ui_NoOfChannels    : No Of Channels To be Read    |
+ |                      UINT *data             : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -187,7 +187,7 @@ INT i_APCI1564_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1564_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1564_ReadMoreDigitalInput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_PortValue = data[0];
+@@ -233,12 +233,12 @@ INT i_APCI1564_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_ConfigDigitalOutput                     |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Digital Output Subdevice.               |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev : Driver handle                     |
++| Input Parameters  : struct comedi_device *dev : Driver handle                     |
+ |                     UINT *data         : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |                                                                            |
+@@ -255,7 +255,7 @@ INT i_APCI1564_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1564_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1564_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command = 0;
+@@ -296,12 +296,12 @@ INT i_APCI1564_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_WriteDigitalOutput                      |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes port value  To the selected port                |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     UINT ui_NoOfChannels    : No Of Channels To Write      |
+ |                     UINT *data              : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -312,7 +312,7 @@ INT i_APCI1564_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1564_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1564_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp, ui_Temp1;
+@@ -470,12 +470,12 @@ INT i_APCI1564_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_ReadDigitalOutput                       |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     UINT ui_NoOfChannels    : No Of Channels To read       |
+ |                     UINT *data              : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -486,7 +486,7 @@ INT i_APCI1564_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1564_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI1564_ReadDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+@@ -537,12 +537,12 @@ INT i_APCI1564_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_ConfigTimerCounterWatchdog              |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Timer , Counter or Watchdog             |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev : Driver handle                     |
++| Input Parameters  : struct comedi_device *dev : Driver handle                     |
+ |                     UINT *data         : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |                                                                            |
+@@ -564,7 +564,7 @@ INT i_APCI1564_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1564_ConfigTimerCounterWatchdog(comedi_device * dev,
++INT i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0;
+@@ -695,12 +695,12 @@ INT i_APCI1564_ConfigTimerCounterWatchdog(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_StartStopWriteTimerCounterWatchdog      |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Start / Stop The Selected Timer , Counter or Watchdog  |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev : Driver handle                     |
++| Input Parameters  : struct comedi_device *dev : Driver handle                     |
+ |                     UINT *data         : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |                                                                            |
+@@ -718,7 +718,7 @@ INT i_APCI1564_ConfigTimerCounterWatchdog(comedi_device * dev,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1564_StartStopWriteTimerCounterWatchdog(comedi_device * dev,
++INT i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0;
+@@ -795,12 +795,12 @@ INT i_APCI1564_StartStopWriteTimerCounterWatchdog(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_ReadTimerCounterWatchdog                |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Selected Timer , Counter or Watchdog          |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev : Driver handle                     |
++| Input Parameters  : struct comedi_device *dev : Driver handle                     |
+ |                     UINT *data         : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |                                                                            |
+@@ -813,7 +813,7 @@ INT i_APCI1564_StartStopWriteTimerCounterWatchdog(comedi_device * dev,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI1564_ReadTimerCounterWatchdog(comedi_device * dev,
++INT i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0;
+@@ -878,7 +878,7 @@ INT i_APCI1564_ReadTimerCounterWatchdog(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   :  int i_APCI1564_ReadInterruptStatus                    |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              :Reads the interrupt status register                     |
+@@ -892,7 +892,7 @@ INT i_APCI1564_ReadTimerCounterWatchdog(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI1564_ReadInterruptStatus(comedi_device * dev, comedi_subdevice * s,
++int i_APCI1564_ReadInterruptStatus(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	*data = ui_Type;
+@@ -918,7 +918,7 @@ int i_APCI1564_ReadInterruptStatus(comedi_device * dev, comedi_subdevice * s,
+ */
+ static VOID v_APCI1564_Interrupt(int irq, void *d)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	UINT ui_DO, ui_DI;
+ 	UINT ui_Timer;
+ 	UINT ui_C1, ui_C2, ui_C3, ui_C4;
+@@ -1068,11 +1068,11 @@ static VOID v_APCI1564_Interrupt(int irq, void *d)
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function   Name   : int i_APCI1564_Reset(comedi_device *dev)               |                                                       |
++| Function   Name   : int i_APCI1564_Reset(struct comedi_device *dev)               |                                                       |
+ +----------------------------------------------------------------------------+
+ | Task              :resets all the registers                                |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev
++| Input Parameters  : struct comedi_device *dev
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -1081,7 +1081,7 @@ static VOID v_APCI1564_Interrupt(int irq, void *d)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI1564_Reset(comedi_device * dev)
++INT i_APCI1564_Reset(struct comedi_device * dev)
+ {
+ 	outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_IRQ);	//disable the interrupts
+ 	inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_STATUS);	//Reset the interrupt status register
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
+index 914231f2edb6..4b40da7879de 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
+@@ -82,33 +82,33 @@
+ 
+ //DI
+ // for di read
+-INT i_APCI1564_ConfigDigitalInput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1564_ConfigDigitalInput(struct comedi_device *dev, comedi_subdevice *s,
+ 				  comedi_insn *insn, unsigned int *data);
+-INT i_APCI1564_Read1DigitalInput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1564_Read1DigitalInput(struct comedi_device *dev, comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+-INT i_APCI1564_ReadMoreDigitalInput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1564_ReadMoreDigitalInput(struct comedi_device *dev, comedi_subdevice *s,
+ 				    comedi_insn *insn, unsigned int *data);
+ 
+ //DO
+-int i_APCI1564_ConfigDigitalOutput(comedi_device *dev, comedi_subdevice *s,
++int i_APCI1564_ConfigDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+-INT i_APCI1564_WriteDigitalOutput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1564_WriteDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
+ 				  comedi_insn *insn, unsigned int *data);
+-INT i_APCI1564_ReadDigitalOutput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI1564_ReadDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+-int i_APCI1564_ReadInterruptStatus(comedi_device *dev, comedi_subdevice *s,
++int i_APCI1564_ReadInterruptStatus(struct comedi_device *dev, comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+ // timer value is passed as u seconds
+-INT i_APCI1564_ConfigTimerCounterWatchdog(comedi_device *dev,
++INT i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev,
+ 					  comedi_subdevice *s,
+ 					  comedi_insn *insn, unsigned int *data);
+-int i_APCI1564_StartStopWriteTimerCounterWatchdog(comedi_device *dev,
++int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
+ 						  comedi_subdevice *s,
+ 						  comedi_insn *insn,
+ 						  unsigned int *data);
+-int i_APCI1564_ReadTimerCounterWatchdog(comedi_device *dev,
++int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device *dev,
+ 					comedi_subdevice *s,
+ 					comedi_insn *insn, unsigned int *data);
+ 
+@@ -116,4 +116,4 @@ int i_APCI1564_ReadTimerCounterWatchdog(comedi_device *dev,
+ static VOID v_APCI1564_Interrupt(int irq, void *d);
+ 
+ // RESET
+-INT i_APCI1564_Reset(comedi_device *dev);
++INT i_APCI1564_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
+index 0955fdf31cd1..74b0bd484bde 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
+@@ -58,7 +58,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT   i_APCI16XX_InsnConfigInitTTLIO                   |
+-|                          (comedi_device    *dev,                           |
++|                          (struct comedi_device    *dev,                           |
+ |                           comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+@@ -90,7 +90,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI16XX_InsnConfigInitTTLIO(comedi_device * dev,
++int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+@@ -251,7 +251,7 @@ int i_APCI16XX_InsnConfigInitTTLIO(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT     i_APCI16XX_InsnBitsReadTTLIO                   |
+-|                          (comedi_device    *dev,                           |
++|                          (struct comedi_device    *dev,                           |
+ |                           comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+@@ -283,7 +283,7 @@ int i_APCI16XX_InsnConfigInitTTLIO(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI16XX_InsnBitsReadTTLIO(comedi_device * dev,
++int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+@@ -411,7 +411,7 @@ int i_APCI16XX_InsnBitsReadTTLIO(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT i_APCI16XX_InsnReadTTLIOAllPortValue               |
+-|                          (comedi_device    *dev,                           |
++|                          (struct comedi_device    *dev,                           |
+ |                           comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+@@ -430,7 +430,7 @@ int i_APCI16XX_InsnBitsReadTTLIO(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI16XX_InsnReadTTLIOAllPortValue(comedi_device * dev,
++int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_Command = (BYTE) CR_AREF(insn->chanspec);
+@@ -536,7 +536,7 @@ int i_APCI16XX_InsnReadTTLIOAllPortValue(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT     i_APCI16XX_InsnBitsWriteTTLIO                  |
+-|                          (comedi_device    *dev,                           |
++|                          (struct comedi_device    *dev,                           |
+ |                           comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+@@ -570,7 +570,7 @@ int i_APCI16XX_InsnReadTTLIOAllPortValue(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI16XX_InsnBitsWriteTTLIO(comedi_device * dev,
++int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+@@ -763,10 +763,10 @@ int i_APCI16XX_InsnBitsWriteTTLIO(comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function   Name   : int i_APCI2200_Reset(comedi_device *dev)               |                                                         +----------------------------------------------------------------------------+
++| Function   Name   : int i_APCI2200_Reset(struct comedi_device *dev)               |                                                         +----------------------------------------------------------------------------+
+ | Task              :resets all the registers                                |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev                                     |
++| Input Parameters  : struct comedi_device *dev                                     |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+ +----------------------------------------------------------------------------+
+@@ -774,7 +774,7 @@ int i_APCI16XX_InsnBitsWriteTTLIO(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI16XX_Reset(comedi_device * dev)
++int i_APCI16XX_Reset(struct comedi_device * dev)
+ {
+ 	return 0;
+ }
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h
+index 6e8d09407807..9f8f2b752431 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h
+@@ -62,7 +62,7 @@ static const comedi_lrange range_apci16xx_ttl = { 12,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI16XX_InsnConfigInitTTLIO(comedi_device *dev,
++int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device *dev,
+ 				   comedi_subdevice *s, comedi_insn *insn,
+ 				   unsigned int *data);
+ 
+@@ -72,11 +72,11 @@ int i_APCI16XX_InsnConfigInitTTLIO(comedi_device *dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI16XX_InsnBitsReadTTLIO(comedi_device *dev,
++int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device *dev,
+ 				 comedi_subdevice *s, comedi_insn *insn,
+ 				 unsigned int *data);
+ 
+-int i_APCI16XX_InsnReadTTLIOAllPortValue(comedi_device *dev,
++int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
+ 					 comedi_subdevice *s,
+ 					 comedi_insn *insn, unsigned int *data);
+ 
+@@ -86,9 +86,9 @@ int i_APCI16XX_InsnReadTTLIOAllPortValue(comedi_device *dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI16XX_InsnBitsWriteTTLIO(comedi_device *dev,
++int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device *dev,
+ 				  comedi_subdevice *s, comedi_insn *insn,
+ 				  unsigned int *data);
+ 
+-int i_APCI16XX_Reset(comedi_device *dev);
++int i_APCI16XX_Reset(struct comedi_device *dev);
+ #endif
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
+index fd4ae6abbb3f..dcb837dee3b1 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
+@@ -56,12 +56,12 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2016_ConfigDigitalOutput                     |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Digital Output Subdevice.               |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev : Driver handle                     |
++| Input Parameters  : struct comedi_device *dev : Driver handle                     |
+ |                     UINT *data         : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |                                                                            |
+@@ -75,7 +75,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI2016_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
++int i_APCI2016_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if ((data[0] != 0) && (data[0] != 1)) {
+@@ -95,12 +95,12 @@ int i_APCI2016_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2016_WriteDigitalOutput                      |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes port value  To the selected port                |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     UINT ui_NoOfChannels    : No Of Channels To Write      |
+ |                     UINT *data              : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -111,7 +111,7 @@ int i_APCI2016_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI2016_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
++int i_APCI2016_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_NoOfChannel;
+@@ -250,12 +250,12 @@ int i_APCI2016_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2016_BitsDigitalOutput                       |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     UINT ui_NoOfChannels    : No Of Channels To read       |
+ |                     UINT *data              : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -266,7 +266,7 @@ int i_APCI2016_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI2016_BitsDigitalOutput(comedi_device * dev, comedi_subdevice * s,
++int i_APCI2016_BitsDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+@@ -320,12 +320,12 @@ int i_APCI2016_BitsDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2016_ConfigWatchdog                          |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Watchdog                                |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  :   comedi_device *dev      : Driver handle              |
++| Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure |
+ |                     comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+@@ -337,7 +337,7 @@ int i_APCI2016_BitsDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI2016_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
++int i_APCI2016_ConfigWatchdog(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -363,12 +363,12 @@ int i_APCI2016_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2016_StartStopWriteWatchdog                  |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Start / Stop The Watchdog                              |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure |
+ |                     comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+@@ -380,7 +380,7 @@ int i_APCI2016_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI2016_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
++int i_APCI2016_StartStopWriteWatchdog(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -409,12 +409,12 @@ int i_APCI2016_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2016_ReadWatchdog                            |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Watchdog                                      |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure |
+ |                     comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+@@ -427,7 +427,7 @@ int i_APCI2016_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI2016_ReadWatchdog(comedi_device * dev, comedi_subdevice * s,
++int i_APCI2016_ReadWatchdog(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	udelay(5);
+@@ -437,11 +437,11 @@ int i_APCI2016_ReadWatchdog(comedi_device * dev, comedi_subdevice * s,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function   Name   : int i_APCI2016_Reset(comedi_device *dev)               |                                                       |
++| Function   Name   : int i_APCI2016_Reset(struct comedi_device *dev)               |                                                       |
+ +----------------------------------------------------------------------------+
+ | Task              :resets all the registers                                |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev
++| Input Parameters  : struct comedi_device *dev
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -450,7 +450,7 @@ int i_APCI2016_ReadWatchdog(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI2016_Reset(comedi_device * dev)
++INT i_APCI2016_Reset(struct comedi_device * dev)
+ {
+ 	outw(0x0, devpriv->iobase + APCI2016_DIGITAL_OP);	// Resets the digital output channels
+ 	outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_ENABLEDISABLE);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
+index 3ca52e9eca5a..765de4212ed0 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
+@@ -40,25 +40,25 @@
+ // Hardware Layer  functions for Apci2016
+ 
+ //DO
+-int i_APCI2016_ConfigDigitalOutput(comedi_device *dev, comedi_subdevice *s,
++int i_APCI2016_ConfigDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+ 
+-int i_APCI2016_WriteDigitalOutput(comedi_device *dev, comedi_subdevice *s,
++int i_APCI2016_WriteDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
+ 				  comedi_insn *insn, unsigned int *data);
+ 
+-int i_APCI2016_BitsDigitalOutput(comedi_device *dev, comedi_subdevice *s,
++int i_APCI2016_BitsDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+ // timer value is passed as u seconds
+ 
+-int i_APCI2016_ConfigWatchdog(comedi_device *dev, comedi_subdevice *s,
++int i_APCI2016_ConfigWatchdog(struct comedi_device *dev, comedi_subdevice *s,
+ 			      comedi_insn *insn, unsigned int *data);
+ 
+-int i_APCI2016_StartStopWriteWatchdog(comedi_device *dev, comedi_subdevice *s,
++int i_APCI2016_StartStopWriteWatchdog(struct comedi_device *dev, comedi_subdevice *s,
+ 				      comedi_insn *insn, unsigned int *data);
+ 
+-int i_APCI2016_ReadWatchdog(comedi_device *dev, comedi_subdevice *s,
++int i_APCI2016_ReadWatchdog(struct comedi_device *dev, comedi_subdevice *s,
+ 			    comedi_insn *insn, unsigned int *data);
+ 
+ // Interrupt functions.....
+@@ -67,4 +67,4 @@ int i_APCI2016_ReadWatchdog(comedi_device *dev, comedi_subdevice *s,
+ 
+  //VOID v_APCI2016_Interrupt(int irq, void *d);
+ // RESET
+-INT i_APCI2016_Reset(comedi_device *dev);
++INT i_APCI2016_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
+index 4345dda7f99d..b536667398cf 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
+@@ -57,12 +57,12 @@ UINT ui_InterruptData, ui_Type;
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2032_ConfigDigitalOutput                     |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Digital Output Subdevice.               |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev : Driver handle                     |
++| Input Parameters  : struct comedi_device *dev : Driver handle                     |
+ |                     UINT *data         : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |                                                                            |
+@@ -79,7 +79,7 @@ UINT ui_InterruptData, ui_Type;
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI2032_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
++int i_APCI2032_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command = 0;
+@@ -117,12 +117,12 @@ int i_APCI2032_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2032_WriteDigitalOutput                      |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes port value  To the selected port                |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     UINT ui_NoOfChannels    : No Of Channels To Write      |
+ |                     UINT *data              : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -134,7 +134,7 @@ int i_APCI2032_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI2032_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI2032_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp, ui_Temp1;
+@@ -296,12 +296,12 @@ INT i_APCI2032_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2032_ReadDigitalOutput                       |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     UINT ui_NoOfChannels    : No Of Channels To read       |
+ |                     UINT *data              : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -313,7 +313,7 @@ INT i_APCI2032_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI2032_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI2032_ReadDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+@@ -368,7 +368,7 @@ INT i_APCI2032_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Watchdog                                |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status                                                                                                             |
+@@ -380,7 +380,7 @@ INT i_APCI2032_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI2032_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI2032_ConfigWatchdog(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0] == 0) {
+@@ -403,12 +403,12 @@ INT i_APCI2032_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+  /*
+     +----------------------------------------------------------------------------+
+     | Function   Name   : int i_APCI2032_StartStopWriteWatchdog                  |
+-    |                           (comedi_device *dev,comedi_subdevice *s,
++    |                           (struct comedi_device *dev,comedi_subdevice *s,
+     comedi_insn *insn,unsigned int *data);                      |
+     +----------------------------------------------------------------------------+
+     | Task              : Start / Stop The Watchdog                              |
+     +----------------------------------------------------------------------------+
+-    | Input Parameters  : comedi_device *dev      : Driver handle                |
++    | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+     |                     comedi_subdevice *s,   :pointer to subdevice structure
+     comedi_insn *insn      :pointer to insn structure      |
+     |                     unsigned int *data          : Data Pointer to read status  |
+@@ -421,7 +421,7 @@ INT i_APCI2032_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+     +----------------------------------------------------------------------------+
+   */
+ 
+-int i_APCI2032_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
++int i_APCI2032_StartStopWriteWatchdog(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+@@ -448,12 +448,12 @@ int i_APCI2032_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2032_ReadWatchdog                            |
+-|			(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+                     unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Watchdog                                      |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  :   comedi_device *dev      : Driver handle              |
++| Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+@@ -466,7 +466,7 @@ int i_APCI2032_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI2032_ReadWatchdog(comedi_device * dev, comedi_subdevice * s,
++int i_APCI2032_ReadWatchdog(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -495,7 +495,7 @@ int i_APCI2032_ReadWatchdog(comedi_device * dev, comedi_subdevice * s,
+ */
+ void v_APCI2032_Interrupt(int irq, void *d)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	unsigned int ui_DO;
+ 
+ 	ui_DO = inl(devpriv->iobase + APCI2032_DIGITAL_OP_IRQ) & 0x1;	//Check if VCC OR CC interrupt has occured.
+@@ -530,7 +530,7 @@ void v_APCI2032_Interrupt(int irq, void *d)
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   :  int i_APCI2032_ReadInterruptStatus                    |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              :Reads the interrupt status register                     |
+@@ -544,7 +544,7 @@ void v_APCI2032_Interrupt(int irq, void *d)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI2032_ReadInterruptStatus(comedi_device * dev, comedi_subdevice * s,
++int i_APCI2032_ReadInterruptStatus(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	*data = ui_Type;
+@@ -553,7 +553,7 @@ int i_APCI2032_ReadInterruptStatus(comedi_device * dev, comedi_subdevice * s,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function   Name   :  int i_APCI2032_Reset(comedi_device *dev)			     |
++| Function   Name   :  int i_APCI2032_Reset(struct comedi_device *dev)			     |
+ |					                                                 |
+ +----------------------------------------------------------------------------+
+ | Task              :Resets the registers of the card                        |
+@@ -567,7 +567,7 @@ int i_APCI2032_ReadInterruptStatus(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI2032_Reset(comedi_device * dev)
++int i_APCI2032_Reset(struct comedi_device * dev)
+ {
+ 	devpriv->b_DigitalOutputRegister = 0;
+ 	ui_Type = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h
+index 7d858af87979..8ceefb07d503 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h
+@@ -55,22 +55,22 @@
+ // Hardware Layer  functions for Apci2032
+ 
+ //DO
+-int i_APCI2032_ConfigDigitalOutput(comedi_device *dev, comedi_subdevice *s,
++int i_APCI2032_ConfigDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+-INT i_APCI2032_WriteDigitalOutput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI2032_WriteDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
+ 				  comedi_insn *insn, unsigned int *data);
+-INT i_APCI2032_ReadDigitalOutput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI2032_ReadDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+-int i_APCI2032_ReadInterruptStatus(comedi_device *dev, comedi_subdevice *s,
++int i_APCI2032_ReadInterruptStatus(struct comedi_device *dev, comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+ // timer value is passed as u seconds
+-INT i_APCI2032_ConfigWatchdog(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI2032_ConfigWatchdog(struct comedi_device *dev, comedi_subdevice *s,
+ 			      comedi_insn *insn, unsigned int *data);
+-int i_APCI2032_StartStopWriteWatchdog(comedi_device *dev, comedi_subdevice *s,
++int i_APCI2032_StartStopWriteWatchdog(struct comedi_device *dev, comedi_subdevice *s,
+ 				      comedi_insn *insn, unsigned int *data);
+-int i_APCI2032_ReadWatchdog(comedi_device *dev, comedi_subdevice *s,
++int i_APCI2032_ReadWatchdog(struct comedi_device *dev, comedi_subdevice *s,
+ 			    comedi_insn *insn, unsigned int *data);
+ 
+ // Interrupt functions.....
+@@ -78,4 +78,4 @@ int i_APCI2032_ReadWatchdog(comedi_device *dev, comedi_subdevice *s,
+ void v_APCI2032_Interrupt(int irq, void *d);
+ 
+ //Reset functions
+-int i_APCI2032_Reset(comedi_device *dev);
++int i_APCI2032_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
+index d61dfd1d1eab..b297f6f96089 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
+@@ -56,12 +56,12 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_Read1DigitalInput                       |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the digital input                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |		       comedi_subdevice *s,   :pointer to subdevice structure
+                        comedi_insn *insn      :pointer to insn structure     |
+ |                     unsigned int *data          : Data Pointer to read status  |
+@@ -73,7 +73,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI2200_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI2200_Read1DigitalInput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue = 0;
+@@ -94,12 +94,12 @@ INT i_APCI2200_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_ReadMoreDigitalInput                    |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                     comedi_insn *insn,unsigned int *data)                      |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the Requested digital inputs      |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                      comedi_subdevice *s,   :pointer to subdevice structure
+                        comedi_insn *insn      :pointer to insn structure     |
+ |                      unsigned int *data         : Data Pointer to read status  |
+@@ -112,7 +112,7 @@ INT i_APCI2200_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI2200_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI2200_ReadMoreDigitalInput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -146,13 +146,13 @@ INT i_APCI2200_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function   Name   : int i_APCI2200_ConfigDigitalOutput (comedi_device *dev,
++| Function   Name   : int i_APCI2200_ConfigDigitalOutput (struct comedi_device *dev,
+                     comedi_subdevice *s comedi_insn *insn,unsigned int *data)    |
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Digital Output Subdevice.               |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev : Driver handle                     |
++| Input Parameters  : struct comedi_device *dev : Driver handle                     |
+ |                     unsigned int *data         : Data Pointer contains         |
+ |                                          configuration parameters as below |
+ |                      comedi_subdevice *s,   :pointer to subdevice structure
+@@ -169,7 +169,7 @@ INT i_APCI2200_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI2200_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
++int i_APCI2200_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	devpriv->b_OutputMemoryStatus = data[0];
+@@ -179,12 +179,12 @@ int i_APCI2200_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_WriteDigitalOutput                      |
+-|			(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+                      unsigned int *data)                                         |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes port value  To the selected port                |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                    unsigned int *data           : Data Pointer to read status  |
+@@ -197,7 +197,7 @@ int i_APCI2200_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI2200_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI2200_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp, ui_Temp1;
+@@ -336,12 +336,12 @@ INT i_APCI2200_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_ReadDigitalOutput                       |
+-|			(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+                     unsigned int *data) 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+@@ -354,7 +354,7 @@ INT i_APCI2200_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI2200_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI2200_ReadDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -399,13 +399,13 @@ INT i_APCI2200_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function   Name   : int i_APCI2200_ConfigWatchdog(comedi_device *dev,
++| Function   Name   : int i_APCI2200_ConfigWatchdog(struct comedi_device *dev,
+                       comedi_subdevice *s,comedi_insn *insn,unsigned int *data)  |
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Watchdog                                |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  :   comedi_device *dev      : Driver handle              |
++| Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status                                                                                                             |
+@@ -418,7 +418,7 @@ INT i_APCI2200_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI2200_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
++int i_APCI2200_ConfigWatchdog(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0] == 0) {
+@@ -446,12 +446,12 @@ int i_APCI2200_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+  /*
+     +----------------------------------------------------------------------------+
+     | Function   Name   : int i_APCI2200_StartStopWriteWatchdog                  |
+-    |                           (comedi_device *dev,comedi_subdevice *s,
++    |                           (struct comedi_device *dev,comedi_subdevice *s,
+     comedi_insn *insn,unsigned int *data);                      |
+     +----------------------------------------------------------------------------+
+     | Task              : Start / Stop The Watchdog                              |
+     +----------------------------------------------------------------------------+
+-    | Input Parameters  : comedi_device *dev      : Driver handle                |
++    | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+     |                     comedi_subdevice *s,   :pointer to subdevice structure
+     comedi_insn *insn      :pointer to insn structure      |
+     |                     unsigned int *data          : Data Pointer to read status  |
+@@ -464,7 +464,7 @@ int i_APCI2200_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+     +----------------------------------------------------------------------------+
+   */
+ 
+-int i_APCI2200_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
++int i_APCI2200_StartStopWriteWatchdog(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+@@ -491,12 +491,12 @@ int i_APCI2200_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_ReadWatchdog                            |
+-|			(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
++|			(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+                     unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Watchdog                                      |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  :   comedi_device *dev      : Driver handle              |
++| Input Parameters  :   struct comedi_device *dev      : Driver handle              |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+ |                     unsigned int *data          : Data Pointer to read status  |
+@@ -509,7 +509,7 @@ int i_APCI2200_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI2200_ReadWatchdog(comedi_device * dev, comedi_subdevice * s,
++int i_APCI2200_ReadWatchdog(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] =
+@@ -520,11 +520,11 @@ int i_APCI2200_ReadWatchdog(comedi_device * dev, comedi_subdevice * s,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function   Name   : int i_APCI2200_Reset(comedi_device *dev)               |                                                                                                          |
++| Function   Name   : int i_APCI2200_Reset(struct comedi_device *dev)               |                                                                                                          |
+ +----------------------------------------------------------------------------+
+ | Task              :resets all the registers                                |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev
++| Input Parameters  : struct comedi_device *dev
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -533,7 +533,7 @@ int i_APCI2200_ReadWatchdog(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI2200_Reset(comedi_device * dev)
++INT i_APCI2200_Reset(struct comedi_device * dev)
+ {
+ 	outw(0x0, devpriv->iobase + APCI2200_DIGITAL_OP);	//RESETS THE DIGITAL OUTPUTS
+ 	outw(0x0,
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h
+index 59fc451e71c7..ab1bb309767a 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h
+@@ -36,26 +36,26 @@
+ // Hardware Layer  functions for Apci2200
+ 
+ //Digital Input
+-INT i_APCI2200_ReadMoreDigitalInput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI2200_ReadMoreDigitalInput(struct comedi_device *dev, comedi_subdevice *s,
+ 				    comedi_insn *insn, unsigned int *data);
+-INT i_APCI2200_Read1DigitalInput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI2200_Read1DigitalInput(struct comedi_device *dev, comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+ 
+ //Digital Output
+-int i_APCI2200_ConfigDigitalOutput(comedi_device *dev, comedi_subdevice *s,
++int i_APCI2200_ConfigDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+-INT i_APCI2200_WriteDigitalOutput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI2200_WriteDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
+ 				  comedi_insn *insn, unsigned int *data);
+-INT i_APCI2200_ReadDigitalOutput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI2200_ReadDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+-int i_APCI2200_ConfigWatchdog(comedi_device *dev, comedi_subdevice *s,
++int i_APCI2200_ConfigWatchdog(struct comedi_device *dev, comedi_subdevice *s,
+ 			      comedi_insn *insn, unsigned int *data);
+-int i_APCI2200_StartStopWriteWatchdog(comedi_device *dev, comedi_subdevice *s,
++int i_APCI2200_StartStopWriteWatchdog(struct comedi_device *dev, comedi_subdevice *s,
+ 				      comedi_insn *insn, unsigned int *data);
+-int i_APCI2200_ReadWatchdog(comedi_device *dev, comedi_subdevice *s,
++int i_APCI2200_ReadWatchdog(struct comedi_device *dev, comedi_subdevice *s,
+ 			    comedi_insn *insn, unsigned int *data);
+ 
+ //reset
+-INT i_APCI2200_Reset(comedi_device *dev);
++INT i_APCI2200_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+index 45445e675f72..6aaab8cf3c1a 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+@@ -57,14 +57,14 @@ static UINT ui_Temp = 0;
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function name     :int i_APCI3120_InsnConfigAnalogInput(comedi_device *dev,|
++| Function name     :int i_APCI3120_InsnConfigAnalogInput(struct comedi_device *dev,|
+ |  comedi_subdevice *s,comedi_insn *insn,unsigned int *data)					 |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+ | Task              : Calls card specific function  					     |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev									 |
++| Input Parameters  : struct comedi_device *dev									 |
+ |                     comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+ |                     unsigned int *data      					         		 |
+@@ -74,7 +74,7 @@ static UINT ui_Temp = 0;
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_InsnConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
++int i_APCI3120_InsnConfigAnalogInput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT i;
+@@ -124,7 +124,7 @@ int i_APCI3120_InsnConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function name     :int i_APCI3120_InsnReadAnalogInput(comedi_device *dev,  |
++| Function name     :int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev,  |
+ |			comedi_subdevice *s,comedi_insn *insn, unsigned int *data)	 |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+@@ -135,7 +135,7 @@ int i_APCI3120_InsnConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
+ |			  time 10 microsec.					      				 |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev									 |
++| Input Parameters  : struct comedi_device *dev									 |
+ |                     comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+ |                     unsigned int *data     									 |
+@@ -145,7 +145,7 @@ int i_APCI3120_InsnConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_InsnReadAnalogInput(comedi_device * dev, comedi_subdevice * s,
++int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	USHORT us_ConvertTiming, us_TmpValue, i;
+@@ -393,14 +393,14 @@ int i_APCI3120_InsnReadAnalogInput(comedi_device * dev, comedi_subdevice * s,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function name     :int i_APCI3120_StopCyclicAcquisition(comedi_device *dev,|
++| Function name     :int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev,|
+ | 											     comedi_subdevice *s)|
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              : Stops Cyclic acquisition  						     |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev									 |
++| Input Parameters  : struct comedi_device *dev									 |
+ |                     comedi_subdevice *s									 |
+ |                                                 					         |
+ +----------------------------------------------------------------------------+
+@@ -409,7 +409,7 @@ int i_APCI3120_InsnReadAnalogInput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_StopCyclicAcquisition(comedi_device * dev, comedi_subdevice * s)
++int i_APCI3120_StopCyclicAcquisition(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	// Disable A2P Fifo write and AMWEN signal
+ 	outw(0, devpriv->i_IobaseAddon + 4);
+@@ -459,7 +459,7 @@ int i_APCI3120_StopCyclicAcquisition(comedi_device * dev, comedi_subdevice * s)
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function name     :int i_APCI3120_CommandTestAnalogInput(comedi_device *dev|
++| Function name     :int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev|
+ |			,comedi_subdevice *s,comedi_cmd *cmd)					 |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+@@ -467,7 +467,7 @@ int i_APCI3120_StopCyclicAcquisition(comedi_device * dev, comedi_subdevice * s)
+ |                       acquisition  						     			 |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev									 |
++| Input Parameters  : struct comedi_device *dev									 |
+ |                     comedi_subdevice *s									 |
+ |                     comedi_cmd *cmd              					         |
+ +----------------------------------------------------------------------------+
+@@ -476,7 +476,7 @@ int i_APCI3120_StopCyclicAcquisition(comedi_device * dev, comedi_subdevice * s)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_CommandTestAnalogInput(comedi_device * dev, comedi_subdevice * s,
++int i_APCI3120_CommandTestAnalogInput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -616,7 +616,7 @@ int i_APCI3120_CommandTestAnalogInput(comedi_device * dev, comedi_subdevice * s,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function name     : int i_APCI3120_CommandAnalogInput(comedi_device *dev,  |
++| Function name     : int i_APCI3120_CommandAnalogInput(struct comedi_device *dev,  |
+ |												comedi_subdevice *s) |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+@@ -624,7 +624,7 @@ int i_APCI3120_CommandTestAnalogInput(comedi_device * dev, comedi_subdevice * s,
+ |                     Determines the mode 1 or 2.						     |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev									 |
++| Input Parameters  : struct comedi_device *dev									 |
+ |                     comedi_subdevice *s									 |
+ |                     														 |
+ +----------------------------------------------------------------------------+
+@@ -633,7 +633,7 @@ int i_APCI3120_CommandTestAnalogInput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_CommandAnalogInput(comedi_device * dev, comedi_subdevice * s)
++int i_APCI3120_CommandAnalogInput(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 
+@@ -690,7 +690,7 @@ int i_APCI3120_CommandAnalogInput(comedi_device * dev, comedi_subdevice * s)
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :  int i_APCI3120_CyclicAnalogInput(int mode,            |
+-|		 	   comedi_device * dev,comedi_subdevice * s)			 |
++|		 	   struct comedi_device * dev,comedi_subdevice * s)			 |
+ +----------------------------------------------------------------------------+
+ | Task              : This is used for analog input cyclic acquisition       |
+ |			  Performs the command operations.                       |
+@@ -707,7 +707,7 @@ int i_APCI3120_CommandAnalogInput(comedi_device * dev, comedi_subdevice * s)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_CyclicAnalogInput(int mode, comedi_device * dev,
++int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ 	comedi_subdevice * s)
+ {
+ 	BYTE b_Tmp;
+@@ -1202,14 +1202,14 @@ int i_APCI3120_CyclicAnalogInput(int mode, comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function name     : int i_APCI3120_Reset(comedi_device *dev)               |
++| Function name     : int i_APCI3120_Reset(struct comedi_device *dev)               |
+ |                                        									 |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+ | Task              : Hardware reset function   						     |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : 	comedi_device *dev									 |
++| Input Parameters  : 	struct comedi_device *dev									 |
+ |                     														 |
+ |                                                 					         |
+ +----------------------------------------------------------------------------+
+@@ -1218,7 +1218,7 @@ int i_APCI3120_CyclicAnalogInput(int mode, comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_Reset(comedi_device * dev)
++int i_APCI3120_Reset(struct comedi_device * dev)
+ {
+ 	unsigned int i;
+ 	unsigned short us_TmpValue;
+@@ -1274,7 +1274,7 @@ int i_APCI3120_Reset(comedi_device * dev)
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function name     : int i_APCI3120_SetupChannelList(comedi_device * dev,   |
++| Function name     : int i_APCI3120_SetupChannelList(struct comedi_device * dev,   |
+ |                     comedi_subdevice * s, int n_chan,unsigned int *chanlist|
+ |			  ,char check)											 |
+ |                                            						         |
+@@ -1285,7 +1285,7 @@ int i_APCI3120_Reset(comedi_device * dev)
+ |list is ok or not.												     		 |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device * dev									 |
++| Input Parameters  : struct comedi_device * dev									 |
+ |                     comedi_subdevice * s									 |
+ |                     int n_chan                   					         |
+ 			  unsigned int *chanlist
+@@ -1296,7 +1296,7 @@ int i_APCI3120_Reset(comedi_device * dev)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_SetupChannelList(comedi_device * dev, comedi_subdevice * s,
++int i_APCI3120_SetupChannelList(struct comedi_device * dev, comedi_subdevice * s,
+ 	int n_chan, unsigned int *chanlist, char check)
+ {
+ 	unsigned int i;		//, differencial=0, bipolar=0;
+@@ -1344,14 +1344,14 @@ int i_APCI3120_SetupChannelList(comedi_device * dev, comedi_subdevice * s,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function name     :	int i_APCI3120_ExttrigEnable(comedi_device * dev)    |
++| Function name     :	int i_APCI3120_ExttrigEnable(struct comedi_device * dev)    |
+ |                                        									 |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+ | Task              : 	Enable the external trigger						     |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : 	comedi_device * dev									 |
++| Input Parameters  : 	struct comedi_device * dev									 |
+ |                     														 |
+ |                                                 					         |
+ +----------------------------------------------------------------------------+
+@@ -1360,7 +1360,7 @@ int i_APCI3120_SetupChannelList(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_ExttrigEnable(comedi_device * dev)
++int i_APCI3120_ExttrigEnable(struct comedi_device * dev)
+ {
+ 
+ 	devpriv->us_OutputRegister |= APCI3120_ENABLE_EXT_TRIGGER;
+@@ -1370,13 +1370,13 @@ int i_APCI3120_ExttrigEnable(comedi_device * dev)
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function name     : 	int i_APCI3120_ExttrigDisable(comedi_device * dev)   |
++| Function name     : 	int i_APCI3120_ExttrigDisable(struct comedi_device * dev)   |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              : 	Disables the external trigger					     |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : 	comedi_device * dev									 |
++| Input Parameters  : 	struct comedi_device * dev									 |
+ |                     														 |
+ |                                                 					         |
+ +----------------------------------------------------------------------------+
+@@ -1385,7 +1385,7 @@ int i_APCI3120_ExttrigEnable(comedi_device * dev)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_ExttrigDisable(comedi_device * dev)
++int i_APCI3120_ExttrigDisable(struct comedi_device * dev)
+ {
+ 	devpriv->us_OutputRegister &= ~APCI3120_ENABLE_EXT_TRIGGER;
+ 	outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
+@@ -1421,7 +1421,7 @@ int i_APCI3120_ExttrigDisable(comedi_device * dev)
+ 
+ void v_APCI3120_Interrupt(int irq, void *d)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	USHORT int_daq;
+ 
+ 	unsigned int int_amcc, ui_Check, i;
+@@ -1612,7 +1612,7 @@ void v_APCI3120_Interrupt(int irq, void *d)
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function name     :int i_APCI3120_InterruptHandleEos(comedi_device *dev)   |
++| Function name     :int i_APCI3120_InterruptHandleEos(struct comedi_device *dev)   |
+ |                                        									 |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+@@ -1621,7 +1621,7 @@ void v_APCI3120_Interrupt(int irq, void *d)
+ |				to Comedi buffer.		 							 |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev									 |
++| Input Parameters  : struct comedi_device *dev									 |
+ |                     														 |
+ |                                                 					         |
+ +----------------------------------------------------------------------------+
+@@ -1630,7 +1630,7 @@ void v_APCI3120_Interrupt(int irq, void *d)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-/*int i_APCI3120_InterruptHandleEos(comedi_device *dev)
++/*int i_APCI3120_InterruptHandleEos(struct comedi_device *dev)
+ {
+        int n_chan,i;
+        short *data;
+@@ -1654,7 +1654,7 @@ void v_APCI3120_Interrupt(int irq, void *d)
+          }
+  	return 0;
+ }*/
+-int i_APCI3120_InterruptHandleEos(comedi_device * dev)
++int i_APCI3120_InterruptHandleEos(struct comedi_device * dev)
+ {
+ 	int n_chan, i;
+ 	comedi_subdevice *s = dev->subdevices + 0;
+@@ -1698,7 +1698,7 @@ int i_APCI3120_InterruptHandleEos(comedi_device * dev)
+ 
+ void v_APCI3120_InterruptDma(int irq, void *d)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s = dev->subdevices + 0;
+ 	unsigned int next_dma_buf, samplesinbuf;
+ 	unsigned long low_word, high_word, var;
+@@ -1886,7 +1886,7 @@ void v_APCI3120_InterruptDma(int irq, void *d)
+ |				 Comedi buffer  									 |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev									 |
++| Input Parameters  : struct comedi_device *dev									 |
+ |                     comedi_subdevice *s									 |
+ |                     short *dma											 |
+ |                     short *data,int n          					         |
+@@ -1896,7 +1896,7 @@ void v_APCI3120_InterruptDma(int irq, void *d)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-/*void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device *dev,comedi_subdevice *s,short *dma,short *data,int n)
++/*void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,comedi_subdevice *s,short *dma,short *data,int n)
+ {
+ 	int i,j,m;
+ 
+@@ -1925,7 +1925,7 @@ void v_APCI3120_InterruptDma(int irq, void *d)
+ 
+ }
+ */
+-void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device * dev,
++void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device * dev,
+ 	comedi_subdevice * s, short * dma_buffer, unsigned int num_samples)
+ {
+ 	devpriv->ui_AiActualScan +=
+@@ -1944,14 +1944,14 @@ void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function name     :int i_APCI3120_InsnConfigTimer(comedi_device *dev,          |
++| Function name     :int i_APCI3120_InsnConfigTimer(struct comedi_device *dev,          |
+ |	comedi_subdevice *s,comedi_insn *insn,unsigned int *data) 			     |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              :Configure Timer 2  								     |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev									 |
++| Input Parameters  : struct comedi_device *dev									 |
+ |                     comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+ |                     unsigned int *data 										 |
+@@ -1967,7 +1967,7 @@ void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_InsnConfigTimer(comedi_device * dev, comedi_subdevice * s,
++int i_APCI3120_InsnConfigTimer(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -2092,13 +2092,13 @@ int i_APCI3120_InsnConfigTimer(comedi_device * dev, comedi_subdevice * s,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function name     :int i_APCI3120_InsnWriteTimer(comedi_device *dev,           |
++| Function name     :int i_APCI3120_InsnWriteTimer(struct comedi_device *dev,           |
+ |                    comedi_subdevice *s, comedi_insn *insn,unsigned int *data)  |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+ | Task              :    To start and stop the timer		                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev									 |
++| Input Parameters  : struct comedi_device *dev									 |
+ |                     comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+ |                     unsigned int *data                                         |
+@@ -2118,7 +2118,7 @@ int i_APCI3120_InsnConfigTimer(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_InsnWriteTimer(comedi_device * dev, comedi_subdevice * s,
++int i_APCI3120_InsnWriteTimer(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -2283,14 +2283,14 @@ int i_APCI3120_InsnWriteTimer(comedi_device * dev, comedi_subdevice * s,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function name     : int i_APCI3120_InsnReadTimer(comedi_device *dev,           |
++| Function name     : int i_APCI3120_InsnReadTimer(struct comedi_device *dev,           |
+ |		comedi_subdevice *s,comedi_insn *insn, unsigned int *data) 		 |
+ |                                        									 |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+ | Task              : read the Timer value 				                 	 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : 	comedi_device *dev									 |
++| Input Parameters  : 	struct comedi_device *dev									 |
+ |                     comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+ |                     unsigned int *data 										 |
+@@ -2304,7 +2304,7 @@ int i_APCI3120_InsnWriteTimer(comedi_device * dev, comedi_subdevice * s,
+ |                    													     |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI3120_InsnReadTimer(comedi_device * dev, comedi_subdevice * s,
++int i_APCI3120_InsnReadTimer(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_Tmp;
+@@ -2360,7 +2360,7 @@ int i_APCI3120_InsnReadTimer(comedi_device * dev, comedi_subdevice * s,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function name     :int i_APCI3120_InsnReadDigitalInput(comedi_device *dev,     |
++| Function name     :int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev,     |
+ |			comedi_subdevice *s, comedi_insn *insn,unsigned int *data)   |
+ |                                        									 |
+ |                                            						         |
+@@ -2368,7 +2368,7 @@ int i_APCI3120_InsnReadTimer(comedi_device * dev, comedi_subdevice * s,
+ | Task              : Reads the value of the specified  Digital input channel|
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev									 |
++| Input Parameters  : struct comedi_device *dev									 |
+ |                     comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+ |                     unsigned int *data 										 |
+@@ -2378,7 +2378,7 @@ int i_APCI3120_InsnReadTimer(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_InsnReadDigitalInput(comedi_device * dev, comedi_subdevice
++int i_APCI3120_InsnReadDigitalInput(struct comedi_device * dev, comedi_subdevice
+ 	* s, comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Chan, ui_TmpValue;
+@@ -2403,7 +2403,7 @@ int i_APCI3120_InsnReadDigitalInput(comedi_device * dev, comedi_subdevice
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function name     :int i_APCI3120_InsnBitsDigitalInput(comedi_device *dev, |
++| Function name     :int i_APCI3120_InsnBitsDigitalInput(struct comedi_device *dev, |
+ |comedi_subdevice *s, comedi_insn *insn,unsigned int *data)                      |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+@@ -2411,7 +2411,7 @@ int i_APCI3120_InsnReadDigitalInput(comedi_device * dev, comedi_subdevice
+ |   value is returned in data[0]											 |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev									 |
++| Input Parameters  : struct comedi_device *dev									 |
+ |                     comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+ |                     unsigned int *data 										 |
+@@ -2420,7 +2420,7 @@ int i_APCI3120_InsnReadDigitalInput(comedi_device * dev, comedi_subdevice
+ |                    													     |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI3120_InsnBitsDigitalInput(comedi_device * dev, comedi_subdevice * s,
++int i_APCI3120_InsnBitsDigitalInput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue;
+@@ -2442,14 +2442,14 @@ int i_APCI3120_InsnBitsDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ */
+ /*
+ +----------------------------------------------------------------------------+
+-| Function name     :int i_APCI3120_InsnConfigDigitalOutput(comedi_device    |
++| Function name     :int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device    |
+ | *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data)				 |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+ | Task              :Configure the output memory ON or OFF				     |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  :comedi_device *dev									 	 |
++| Input Parameters  :struct comedi_device *dev									 	 |
+ |                     comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+ |                     unsigned int *data 										 |
+@@ -2459,7 +2459,7 @@ int i_APCI3120_InsnBitsDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_InsnConfigDigitalOutput(comedi_device * dev,
++int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -2485,14 +2485,14 @@ int i_APCI3120_InsnConfigDigitalOutput(comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function name     :int i_APCI3120_InsnBitsDigitalOutput(comedi_device *dev,    |
++| Function name     :int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device *dev,    |
+ |		comedi_subdevice *s, comedi_insn *insn,unsigned int *data) 		 |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              : write diatal output port							     |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev									 |
++| Input Parameters  : struct comedi_device *dev									 |
+ |                     comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+ |                     unsigned int *data 										 |
+@@ -2505,7 +2505,7 @@ int i_APCI3120_InsnConfigDigitalOutput(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_InsnBitsDigitalOutput(comedi_device * dev, comedi_subdevice
++int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device * dev, comedi_subdevice
+ 	* s, comedi_insn * insn, unsigned int * data)
+ {
+ 	if ((data[0] > this_board->i_DoMaxdata) || (data[0] < 0)) {
+@@ -2536,14 +2536,14 @@ int i_APCI3120_InsnBitsDigitalOutput(comedi_device * dev, comedi_subdevice
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function name     :int i_APCI3120_InsnWriteDigitalOutput(comedi_device *dev,|
++| Function name     :int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev,|
+ |comedi_subdevice *s,comedi_insn *insn,unsigned int *data) 			             |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+ | Task              : Write digiatl output								     |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev								 	 |
++| Input Parameters  : struct comedi_device *dev								 	 |
+ |                     comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+ |                     unsigned int *data 										 |
+@@ -2556,7 +2556,7 @@ int i_APCI3120_InsnBitsDigitalOutput(comedi_device * dev, comedi_subdevice
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_InsnWriteDigitalOutput(comedi_device * dev, comedi_subdevice
++int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device * dev, comedi_subdevice
+ 	* s, comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -2617,14 +2617,14 @@ int i_APCI3120_InsnWriteDigitalOutput(comedi_device * dev, comedi_subdevice
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function name     :int i_APCI3120_InsnWriteAnalogOutput(comedi_device *dev,|
++| Function name     :int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev,|
+ |comedi_subdevice *s, comedi_insn *insn,unsigned int *data)			             |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              : Write  analog output   							     |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev									 |
++| Input Parameters  : struct comedi_device *dev									 |
+ |                     comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+ |                     unsigned int *data  										 |
+@@ -2634,7 +2634,7 @@ int i_APCI3120_InsnWriteDigitalOutput(comedi_device * dev, comedi_subdevice
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3120_InsnWriteAnalogOutput(comedi_device * dev, comedi_subdevice
++int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device * dev, comedi_subdevice
+ 	* s, comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Range, ui_Channel;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
+index 591061743c74..ee346f6d0ba1 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
+@@ -178,64 +178,64 @@ typedef struct {
+ // Function Declaration For APCI-3120
+ 
+ // Internal functions
+-int i_APCI3120_SetupChannelList(comedi_device *dev, comedi_subdevice *s,
++int i_APCI3120_SetupChannelList(struct comedi_device *dev, comedi_subdevice *s,
+ 				int n_chan, unsigned int *chanlist, char check);
+-int i_APCI3120_ExttrigEnable(comedi_device *dev);
+-int i_APCI3120_ExttrigDisable(comedi_device *dev);
+-int i_APCI3120_StopCyclicAcquisition(comedi_device *dev, comedi_subdevice *s);
+-int i_APCI3120_Reset(comedi_device *dev);
+-int i_APCI3120_CyclicAnalogInput(int mode, comedi_device *dev,
++int i_APCI3120_ExttrigEnable(struct comedi_device *dev);
++int i_APCI3120_ExttrigDisable(struct comedi_device *dev);
++int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev, comedi_subdevice *s);
++int i_APCI3120_Reset(struct comedi_device *dev);
++int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device *dev,
+ 				 comedi_subdevice *s);
+ // Interrupt functions
+ void v_APCI3120_Interrupt(int irq, void *d);
+-//UPDATE-0.7.57->0.7.68 void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device *dev,comedi_subdevice *s,short *dma,short *data,int n);
+-void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device *dev,
++//UPDATE-0.7.57->0.7.68 void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,comedi_subdevice *s,short *dma,short *data,int n);
++void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,
+ 					   comedi_subdevice *s,
+ 					   short *dma_buffer,
+ 					   unsigned int num_samples);
+-int i_APCI3120_InterruptHandleEos(comedi_device *dev);
++int i_APCI3120_InterruptHandleEos(struct comedi_device *dev);
+ void v_APCI3120_InterruptDma(int irq, void *d);
+ 
+ // TIMER
+ 
+-int i_APCI3120_InsnConfigTimer(comedi_device *dev, comedi_subdevice *s,
++int i_APCI3120_InsnConfigTimer(struct comedi_device *dev, comedi_subdevice *s,
+ 			       comedi_insn *insn, unsigned int *data);
+-int i_APCI3120_InsnWriteTimer(comedi_device *dev, comedi_subdevice *s,
++int i_APCI3120_InsnWriteTimer(struct comedi_device *dev, comedi_subdevice *s,
+ 			      comedi_insn *insn, unsigned int *data);
+-int i_APCI3120_InsnReadTimer(comedi_device *dev, comedi_subdevice *s,
++int i_APCI3120_InsnReadTimer(struct comedi_device *dev, comedi_subdevice *s,
+ 			     comedi_insn *insn, unsigned int *data);
+ 
+ //DI
+ // for di read
+ 
+-int i_APCI3120_InsnBitsDigitalInput(comedi_device *dev, comedi_subdevice *s,
++int i_APCI3120_InsnBitsDigitalInput(struct comedi_device *dev, comedi_subdevice *s,
+ 				    comedi_insn *insn, unsigned int *data);
+-int i_APCI3120_InsnReadDigitalInput(comedi_device *dev, comedi_subdevice *s,
++int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev, comedi_subdevice *s,
+ 				    comedi_insn *insn, unsigned int *data);
+ 
+ //DO
+-//int i_APCI3120_WriteDigitalOutput(comedi_device *dev, BYTE data);
+-int i_APCI3120_InsnConfigDigitalOutput(comedi_device *dev,
++//int i_APCI3120_WriteDigitalOutput(struct comedi_device *dev, BYTE data);
++int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device *dev,
+ 				       comedi_subdevice *s, comedi_insn *insn,
+ 				       unsigned int *data);
+-int i_APCI3120_InsnBitsDigitalOutput(comedi_device *dev, comedi_subdevice *s,
++int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
+ 				     comedi_insn *insn, unsigned int *data);
+-int i_APCI3120_InsnWriteDigitalOutput(comedi_device *dev, comedi_subdevice *s,
++int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
+ 				      comedi_insn *insn, unsigned int *data);
+ 
+ //AO
+-//int i_APCI3120_Write1AnalogValue(comedi_device *dev,UINT ui_Range,UINT ui_Channel,UINT data );
+-int i_APCI3120_InsnWriteAnalogOutput(comedi_device *dev, comedi_subdevice *s,
++//int i_APCI3120_Write1AnalogValue(struct comedi_device *dev,UINT ui_Range,UINT ui_Channel,UINT data );
++int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev, comedi_subdevice *s,
+ 				     comedi_insn *insn, unsigned int *data);
+ 
+ //AI HArdware layer
+ 
+-int i_APCI3120_InsnConfigAnalogInput(comedi_device *dev, comedi_subdevice *s,
++int i_APCI3120_InsnConfigAnalogInput(struct comedi_device *dev, comedi_subdevice *s,
+ 				     comedi_insn *insn, unsigned int *data);
+-int i_APCI3120_InsnReadAnalogInput(comedi_device *dev, comedi_subdevice *s,
++int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev, comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+-int i_APCI3120_CommandTestAnalogInput(comedi_device *dev, comedi_subdevice *s,
++int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev, comedi_subdevice *s,
+ 				      comedi_cmd *cmd);
+-int i_APCI3120_CommandAnalogInput(comedi_device *dev, comedi_subdevice *s);
+-//int i_APCI3120_CancelAnalogInput(comedi_device *dev, comedi_subdevice *s);
+-int i_APCI3120_StopCyclicAcquisition(comedi_device *dev, comedi_subdevice *s);
++int i_APCI3120_CommandAnalogInput(struct comedi_device *dev, comedi_subdevice *s);
++//int i_APCI3120_CancelAnalogInput(struct comedi_device *dev, comedi_subdevice *s);
++int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev, comedi_subdevice *s);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+index 83868d8f1c5f..f07e0b1cf8f8 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+@@ -453,7 +453,7 @@ VOID v_GetAPCI3200EepromCalibrationValue(DWORD dw_PCIBoardEepromAddress,
+ 	}
+ }
+ 
+-INT i_APCI3200_GetChannelCalibrationValue(comedi_device * dev,
++INT i_APCI3200_GetChannelCalibrationValue(struct comedi_device * dev,
+ 	unsigned int ui_Channel_num, unsigned int * CJCCurrentSource,
+ 	unsigned int * ChannelCurrentSource, unsigned int * ChannelGainFactor)
+ {
+@@ -530,12 +530,12 @@ INT i_APCI3200_GetChannelCalibrationValue(comedi_device * dev,
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadDigitalInput                       |
+-  |			  (comedi_device *dev,comedi_subdevice *s,               |
++  |			  (struct comedi_device *dev,comedi_subdevice *s,               |
+   |                      comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              : Read  value  of the selected channel or port           |
+   +----------------------------------------------------------------------------+
+-  | Input Parameters  : comedi_device *dev      : Driver handle                |
++  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+   |                     UINT ui_NoOfChannels    : No Of Channels To read  for Port
+   Channel Numberfor single channel
+   |                     UINT data[0]            : 0: Read single channel
+@@ -550,7 +550,7 @@ INT i_APCI3200_GetChannelCalibrationValue(comedi_device * dev,
+   +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI3200_ReadDigitalInput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI3200_ReadDigitalInput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp = 0;
+@@ -592,12 +592,12 @@ INT i_APCI3200_ReadDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ConfigDigitalOutput                     |
+-  |			  (comedi_device *dev,comedi_subdevice *s,				 |
++  |			  (struct comedi_device *dev,comedi_subdevice *s,				 |
+   |                      comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              : Configures The Digital Output Subdevice.               |
+   +----------------------------------------------------------------------------+
+-  | Input Parameters  : comedi_device *dev : Driver handle                     |
++  | Input Parameters  : struct comedi_device *dev : Driver handle                     |
+   |			  data[0]  :1  Memory enable
+   0  Memory Disable
+   +----------------------------------------------------------------------------+
+@@ -608,7 +608,7 @@ INT i_APCI3200_ReadDigitalInput(comedi_device * dev, comedi_subdevice * s,
+   |																	 |
+   +----------------------------------------------------------------------------+
+ */
+-int i_APCI3200_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
++int i_APCI3200_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -629,12 +629,12 @@ int i_APCI3200_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_WriteDigitalOutput                      |
+-  |			  (comedi_device *dev,comedi_subdevice *s,				 |
++  |			  (struct comedi_device *dev,comedi_subdevice *s,				 |
+   |                      comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              : writes To the digital Output Subdevice                 |
+   +----------------------------------------------------------------------------+
+-  | Input Parameters  : comedi_device *dev      : Driver handle                |
++  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+   |                     comedi_subdevice *s     : Subdevice Pointer            |
+   |                     comedi_insn *insn       : Insn Structure Pointer       |
+   |                     unsigned int *data          : Data Pointer contains        |
+@@ -653,7 +653,7 @@ int i_APCI3200_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3200_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI3200_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp = 0, ui_Temp1 = 0;
+@@ -746,12 +746,12 @@ INT i_APCI3200_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadDigitalOutput                       |
+-  |			  (comedi_device *dev,comedi_subdevice *s,               |
++  |			  (struct comedi_device *dev,comedi_subdevice *s,               |
+   |                      comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              : Read  value  of the selected channel or port           |
+   +----------------------------------------------------------------------------+
+-  | Input Parameters  : comedi_device *dev      : Driver handle                |
++  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+   |                     UINT ui_NoOfChannels    : No Of Channels To read       |
+   |                     UINT *data              : Data Pointer to read status  |
+   data[0]                 :0 read single channel
+@@ -766,7 +766,7 @@ INT i_APCI3200_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3200_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI3200_ReadDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+@@ -807,12 +807,12 @@ INT i_APCI3200_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : INT i_APCI3200_ConfigAnalogInput                       |
+-  |			  (comedi_device *dev,comedi_subdevice *s,               |
++  |			  (struct comedi_device *dev,comedi_subdevice *s,               |
+   |                      comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              : Configures The Analog Input Subdevice                  |
+   +----------------------------------------------------------------------------+
+-  | Input Parameters  : comedi_device *dev      : Driver handle                |
++  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+   |                     comedi_subdevice *s     : Subdevice Pointer            |
+   |                     comedi_insn *insn       : Insn Structure Pointer       |
+   |                     unsigned int *data          : Data Pointer contains        |
+@@ -874,7 +874,7 @@ INT i_APCI3200_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3200_ConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI3200_ConfigAnalogInput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -1334,12 +1334,12 @@ INT i_APCI3200_ConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadAnalogInput                         |
+-  |			          (comedi_device *dev,comedi_subdevice *s,       |
++  |			          (struct comedi_device *dev,comedi_subdevice *s,       |
+   |                     comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read  value  of the selected channel			         |
+   +----------------------------------------------------------------------------+
+-  | Input Parameters  : comedi_device *dev      : Driver handle                |
++  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+   |                     UINT ui_NoOfChannels    : No Of Channels To read       |
+   |                     UINT *data              : Data Pointer to read status  |
+   +----------------------------------------------------------------------------+
+@@ -1361,7 +1361,7 @@ INT i_APCI3200_ConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3200_ReadAnalogInput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI3200_ReadAnalogInput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_DummyValue = 0;
+@@ -1633,12 +1633,12 @@ INT i_APCI3200_ReadAnalogInput(comedi_device * dev, comedi_subdevice * s,
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_Read1AnalogInputChannel                 |
+-  |			          (comedi_device *dev,comedi_subdevice *s,       |
++  |			          (struct comedi_device *dev,comedi_subdevice *s,       |
+   |                     comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read  value  of the selected channel			         |
+   +----------------------------------------------------------------------------+
+-  | Input Parameters  : comedi_device *dev      : Driver handle                |
++  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+   |                     UINT ui_NoOfChannel    : Channel No to read            |
+   |                     UINT *data              : Data Pointer to read status  |
+   +----------------------------------------------------------------------------+
+@@ -1651,7 +1651,7 @@ INT i_APCI3200_ReadAnalogInput(comedi_device * dev, comedi_subdevice * s,
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3200_Read1AnalogInputChannel(comedi_device * dev,
++INT i_APCI3200_Read1AnalogInputChannel(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_EOC = 0;
+@@ -1759,12 +1759,12 @@ INT i_APCI3200_Read1AnalogInputChannel(comedi_device * dev,
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadCalibrationOffsetValue              |
+-  |			          (comedi_device *dev,comedi_subdevice *s,       |
++  |			          (struct comedi_device *dev,comedi_subdevice *s,       |
+   |                     comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read calibration offset  value  of the selected channel|
+   +----------------------------------------------------------------------------+
+-  | Input Parameters  : comedi_device *dev      : Driver handle                |
++  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+   |                     UINT *data              : Data Pointer to read status  |
+   +----------------------------------------------------------------------------+
+   | Output Parameters :	--													 |
+@@ -1776,7 +1776,7 @@ INT i_APCI3200_Read1AnalogInputChannel(comedi_device * dev,
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-int i_APCI3200_ReadCalibrationOffsetValue(comedi_device * dev, UINT * data)
++int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device * dev, UINT * data)
+ {
+ 	UINT ui_Temp = 0, ui_EOC = 0;
+ 	UINT ui_CommandRegister = 0;
+@@ -1895,12 +1895,12 @@ int i_APCI3200_ReadCalibrationOffsetValue(comedi_device * dev, UINT * data)
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadCalibrationGainValue                |
+-  |			          (comedi_device *dev,comedi_subdevice *s,       |
++  |			          (struct comedi_device *dev,comedi_subdevice *s,       |
+   |                     comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read calibration gain  value  of the selected channel  |
+   +----------------------------------------------------------------------------+
+-  | Input Parameters  : comedi_device *dev      : Driver handle                |
++  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+   |                     UINT *data              : Data Pointer to read status  |
+   +----------------------------------------------------------------------------+
+   | Output Parameters :	--													 |
+@@ -1912,7 +1912,7 @@ int i_APCI3200_ReadCalibrationOffsetValue(comedi_device * dev, UINT * data)
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-int i_APCI3200_ReadCalibrationGainValue(comedi_device * dev, UINT * data)
++int i_APCI3200_ReadCalibrationGainValue(struct comedi_device * dev, UINT * data)
+ {
+ 	UINT ui_EOC = 0;
+ 	INT ui_CommandRegister = 0;
+@@ -2030,12 +2030,12 @@ int i_APCI3200_ReadCalibrationGainValue(comedi_device * dev, UINT * data)
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadCJCValue                            |
+-  |			          (comedi_device *dev,comedi_subdevice *s,       |
++  |			          (struct comedi_device *dev,comedi_subdevice *s,       |
+   |                     comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read CJC  value  of the selected channel               |
+   +----------------------------------------------------------------------------+
+-  | Input Parameters  : comedi_device *dev      : Driver handle                |
++  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+   |                     UINT *data              : Data Pointer to read status  |
+   +----------------------------------------------------------------------------+
+   | Output Parameters :	--													 |
+@@ -2048,7 +2048,7 @@ int i_APCI3200_ReadCalibrationGainValue(comedi_device * dev, UINT * data)
+   +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3200_ReadCJCValue(comedi_device * dev, unsigned int * data)
++int i_APCI3200_ReadCJCValue(struct comedi_device * dev, unsigned int * data)
+ {
+ 	UINT ui_EOC = 0;
+ 	INT ui_CommandRegister = 0;
+@@ -2150,12 +2150,12 @@ int i_APCI3200_ReadCJCValue(comedi_device * dev, unsigned int * data)
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadCJCCalOffset                        |
+-  |			          (comedi_device *dev,comedi_subdevice *s,       |
++  |			          (struct comedi_device *dev,comedi_subdevice *s,       |
+   |                     comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read CJC calibration offset  value  of the selected channel
+   +----------------------------------------------------------------------------+
+-  | Input Parameters  : comedi_device *dev      : Driver handle                |
++  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+   |                     UINT *data              : Data Pointer to read status  |
+   +----------------------------------------------------------------------------+
+   | Output Parameters :	--													 |
+@@ -2167,7 +2167,7 @@ int i_APCI3200_ReadCJCValue(comedi_device * dev, unsigned int * data)
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-int i_APCI3200_ReadCJCCalOffset(comedi_device * dev, unsigned int * data)
++int i_APCI3200_ReadCJCCalOffset(struct comedi_device * dev, unsigned int * data)
+ {
+ 	UINT ui_EOC = 0;
+ 	INT ui_CommandRegister = 0;
+@@ -2265,12 +2265,12 @@ int i_APCI3200_ReadCJCCalOffset(comedi_device * dev, unsigned int * data)
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadCJCGainValue                        |
+-  |			          (comedi_device *dev,comedi_subdevice *s,       |
++  |			          (struct comedi_device *dev,comedi_subdevice *s,       |
+   |                     comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read CJC calibration gain value
+   +----------------------------------------------------------------------------+
+-  | Input Parameters  : comedi_device *dev      : Driver handle                |
++  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+   |                     UINT ui_NoOfChannels    : No Of Channels To read       |
+   |                     UINT *data              : Data Pointer to read status  |
+   +----------------------------------------------------------------------------+
+@@ -2283,7 +2283,7 @@ int i_APCI3200_ReadCJCCalOffset(comedi_device * dev, unsigned int * data)
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-int i_APCI3200_ReadCJCCalGain(comedi_device * dev, unsigned int * data)
++int i_APCI3200_ReadCJCCalGain(struct comedi_device * dev, unsigned int * data)
+ {
+ 	UINT ui_EOC = 0;
+ 	INT ui_CommandRegister = 0;
+@@ -2375,12 +2375,12 @@ int i_APCI3200_ReadCJCCalGain(comedi_device * dev, unsigned int * data)
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_InsnBits_AnalogInput_Test               |
+-  |			  (comedi_device *dev,comedi_subdevice *s,               |
++  |			  (struct comedi_device *dev,comedi_subdevice *s,               |
+   |                      comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              : Tests the Selected Anlog Input Channel                 |
+   +----------------------------------------------------------------------------+
+-  | Input Parameters  : comedi_device *dev      : Driver handle                |
++  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+   |                     comedi_subdevice *s     : Subdevice Pointer            |
+   |                     comedi_insn *insn       : Insn Structure Pointer       |
+   |                     unsigned int *data          : Data Pointer contains        |
+@@ -2404,7 +2404,7 @@ int i_APCI3200_ReadCJCCalGain(comedi_device * dev, unsigned int * data)
+   +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI3200_InsnBits_AnalogInput_Test(comedi_device * dev,
++INT i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Configuration = 0;
+@@ -2510,12 +2510,12 @@ INT i_APCI3200_InsnBits_AnalogInput_Test(comedi_device * dev,
+ /*
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_InsnWriteReleaseAnalogInput             |
+-  |			  (comedi_device *dev,comedi_subdevice *s,               |
++  |			  (struct comedi_device *dev,comedi_subdevice *s,               |
+   |                      comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              :  Resets the channels                                                      |
+   +----------------------------------------------------------------------------+
+-  | Input Parameters  : comedi_device *dev      : Driver handle                |
++  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+   |                     comedi_subdevice *s     : Subdevice Pointer            |
+   |                     comedi_insn *insn       : Insn Structure Pointer       |
+   |                     unsigned int *data          : Data Pointer
+@@ -2529,7 +2529,7 @@ INT i_APCI3200_InsnBits_AnalogInput_Test(comedi_device * dev,
+   +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI3200_InsnWriteReleaseAnalogInput(comedi_device * dev,
++INT i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	i_APCI3200_Reset(dev);
+@@ -2538,7 +2538,7 @@ INT i_APCI3200_InsnWriteReleaseAnalogInput(comedi_device * dev,
+ 
+ /*
+   +----------------------------------------------------------------------------+
+-  | Function name     :int i_APCI3200_CommandTestAnalogInput(comedi_device *dev|
++  | Function name     :int i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev|
+   |			,comedi_subdevice *s,comedi_cmd *cmd)			         |
+   |                                        									 |
+   +----------------------------------------------------------------------------+
+@@ -2546,7 +2546,7 @@ INT i_APCI3200_InsnWriteReleaseAnalogInput(comedi_device * dev,
+   |                       acquisition  						     			 |
+   |                     										                 |
+   +----------------------------------------------------------------------------+
+-  | Input Parameters  : comedi_device *dev									 |
++  | Input Parameters  : struct comedi_device *dev									 |
+   |                     comedi_subdevice *s									 |
+   |                     comedi_cmd *cmd              					         |
+   |                     										                 |
+@@ -2560,7 +2560,7 @@ INT i_APCI3200_InsnWriteReleaseAnalogInput(comedi_device * dev,
+   +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3200_CommandTestAnalogInput(comedi_device * dev, comedi_subdevice * s,
++int i_APCI3200_CommandTestAnalogInput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 
+@@ -2748,14 +2748,14 @@ int i_APCI3200_CommandTestAnalogInput(comedi_device * dev, comedi_subdevice * s,
+ 
+ /*
+   +----------------------------------------------------------------------------+
+-  | Function name     :int i_APCI3200_StopCyclicAcquisition(comedi_device *dev,|
++  | Function name     :int i_APCI3200_StopCyclicAcquisition(struct comedi_device *dev,|
+   | 											     comedi_subdevice *s)|
+   |                                        									 |
+   +----------------------------------------------------------------------------+
+   | Task              : Stop the  acquisition  						     |
+   |                     										                 |
+   +----------------------------------------------------------------------------+
+-  | Input Parameters  : comedi_device *dev									 |
++  | Input Parameters  : struct comedi_device *dev									 |
+   |                     comedi_subdevice *s									 |
+   |                                                 					         |
+   +----------------------------------------------------------------------------+
+@@ -2764,7 +2764,7 @@ int i_APCI3200_CommandTestAnalogInput(comedi_device * dev, comedi_subdevice * s,
+   +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3200_StopCyclicAcquisition(comedi_device * dev, comedi_subdevice * s)
++int i_APCI3200_StopCyclicAcquisition(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	UINT ui_Configuration = 0;
+ 	//i_InterruptFlag=0;
+@@ -2796,7 +2796,7 @@ int i_APCI3200_StopCyclicAcquisition(comedi_device * dev, comedi_subdevice * s)
+ 
+ /*
+   +----------------------------------------------------------------------------+
+-  | Function name     : int i_APCI3200_CommandAnalogInput(comedi_device *dev,  |
++  | Function name     : int i_APCI3200_CommandAnalogInput(struct comedi_device *dev,  |
+   |												comedi_subdevice *s) |
+   |                                        									 |
+   +----------------------------------------------------------------------------+
+@@ -2804,7 +2804,7 @@ int i_APCI3200_StopCyclicAcquisition(comedi_device * dev, comedi_subdevice * s)
+   |                     Determines the mode 1 or 2.						     |
+   |                     										                 |
+   +----------------------------------------------------------------------------+
+-  | Input Parameters  : comedi_device *dev									 |
++  | Input Parameters  : struct comedi_device *dev									 |
+   |                     comedi_subdevice *s									 |
+   |                     														 |
+   |                     														 |
+@@ -2814,7 +2814,7 @@ int i_APCI3200_StopCyclicAcquisition(comedi_device * dev, comedi_subdevice * s)
+   +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3200_CommandAnalogInput(comedi_device * dev, comedi_subdevice * s)
++int i_APCI3200_CommandAnalogInput(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	UINT ui_Configuration = 0;
+@@ -2987,7 +2987,7 @@ int i_APCI3200_CommandAnalogInput(comedi_device * dev, comedi_subdevice * s)
+ 
+ /*
+   +----------------------------------------------------------------------------+
+-  | Function   Name   :  int i_APCI3200_Reset(comedi_device *dev)			     |
++  | Function   Name   :  int i_APCI3200_Reset(struct comedi_device *dev)			     |
+   |							                                         |
+   +----------------------------------------------------------------------------+
+   | Task              :Resets the registers of the card                        |
+@@ -3001,7 +3001,7 @@ int i_APCI3200_CommandAnalogInput(comedi_device * dev, comedi_subdevice * s)
+   +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3200_Reset(comedi_device * dev)
++int i_APCI3200_Reset(struct comedi_device * dev)
+ {
+ 	INT i_Temp;
+ 	DWORD dw_Dummy;
+@@ -3059,7 +3059,7 @@ int i_APCI3200_Reset(comedi_device * dev)
+ */
+ void v_APCI3200_Interrupt(int irq, void *d)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	UINT ui_StatusRegister = 0;
+ 	UINT ui_ChannelNumber = 0;
+ 	INT i_CalibrationFlag = 0;
+@@ -3482,7 +3482,7 @@ void v_APCI3200_Interrupt(int irq, void *d)
+ 
+ /*
+   +----------------------------------------------------------------------------+
+-  | Function name     :int i_APCI3200_InterruptHandleEos(comedi_device *dev)   |
++  | Function name     :int i_APCI3200_InterruptHandleEos(struct comedi_device *dev)   |
+   |                                        									 |
+   |                                            						         |
+   +----------------------------------------------------------------------------+
+@@ -3491,7 +3491,7 @@ void v_APCI3200_Interrupt(int irq, void *d)
+   |				to Comedi buffer.		 							 |
+   |                     										                 |
+   +----------------------------------------------------------------------------+
+-  | Input Parameters  : comedi_device *dev									 |
++  | Input Parameters  : struct comedi_device *dev									 |
+   |                     														 |
+   |                                                 					         |
+   +----------------------------------------------------------------------------+
+@@ -3499,7 +3499,7 @@ void v_APCI3200_Interrupt(int irq, void *d)
+   |                    													     |
+   +----------------------------------------------------------------------------+
+ */
+-int i_APCI3200_InterruptHandleEos(comedi_device * dev)
++int i_APCI3200_InterruptHandleEos(struct comedi_device * dev)
+ {
+ 	UINT ui_StatusRegister = 0;
+ 	comedi_subdevice *s = dev->subdevices + 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+index 09445d5f673e..fbb658eff531 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+@@ -154,34 +154,34 @@ typedef struct {
+ 
+ //AI
+ 
+-INT i_APCI3200_ConfigAnalogInput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI3200_ConfigAnalogInput(struct comedi_device *dev, comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+-INT i_APCI3200_ReadAnalogInput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI3200_ReadAnalogInput(struct comedi_device *dev, comedi_subdevice *s,
+ 			       comedi_insn *insn, unsigned int *data);
+-INT i_APCI3200_InsnWriteReleaseAnalogInput(comedi_device *dev,
++INT i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device *dev,
+ 					   comedi_subdevice *s,
+ 					   comedi_insn *insn, unsigned int *data);
+-INT i_APCI3200_InsnBits_AnalogInput_Test(comedi_device *dev,
++INT i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device *dev,
+ 					 comedi_subdevice *s,
+ 					 comedi_insn *insn, unsigned int *data);
+-INT i_APCI3200_StopCyclicAcquisition(comedi_device *dev, comedi_subdevice *s);
+-INT i_APCI3200_InterruptHandleEos(comedi_device *dev);
+-INT i_APCI3200_CommandTestAnalogInput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI3200_StopCyclicAcquisition(struct comedi_device *dev, comedi_subdevice *s);
++INT i_APCI3200_InterruptHandleEos(struct comedi_device *dev);
++INT i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev, comedi_subdevice *s,
+ 				      comedi_cmd *cmd);
+-INT i_APCI3200_CommandAnalogInput(comedi_device *dev, comedi_subdevice *s);
+-INT i_APCI3200_ReadDigitalInput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI3200_CommandAnalogInput(struct comedi_device *dev, comedi_subdevice *s);
++INT i_APCI3200_ReadDigitalInput(struct comedi_device *dev, comedi_subdevice *s,
+ 				comedi_insn *insn, unsigned int *data);
+ //Interrupt
+ void v_APCI3200_Interrupt(int irq, void *d);
+-int i_APCI3200_InterruptHandleEos(comedi_device *dev);
++int i_APCI3200_InterruptHandleEos(struct comedi_device *dev);
+ //Reset functions
+-INT i_APCI3200_Reset(comedi_device *dev);
++INT i_APCI3200_Reset(struct comedi_device *dev);
+ 
+-int i_APCI3200_ReadCJCCalOffset(comedi_device *dev, unsigned int *data);
+-int i_APCI3200_ReadCJCValue(comedi_device *dev, unsigned int *data);
+-int i_APCI3200_ReadCalibrationGainValue(comedi_device *dev, UINT *data);
+-int i_APCI3200_ReadCalibrationOffsetValue(comedi_device *dev, UINT *data);
+-int i_APCI3200_Read1AnalogInputChannel(comedi_device *dev,
++int i_APCI3200_ReadCJCCalOffset(struct comedi_device *dev, unsigned int *data);
++int i_APCI3200_ReadCJCValue(struct comedi_device *dev, unsigned int *data);
++int i_APCI3200_ReadCalibrationGainValue(struct comedi_device *dev, UINT *data);
++int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device *dev, UINT *data);
++int i_APCI3200_Read1AnalogInputChannel(struct comedi_device *dev,
+ 				       comedi_subdevice *s, comedi_insn *insn,
+ 				       unsigned int *data);
+-int i_APCI3200_ReadCJCCalGain(comedi_device *dev, unsigned int *data);
++int i_APCI3200_ReadCJCCalGain(struct comedi_device *dev, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
+index 8f5bc0132a62..352e630a603a 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
+@@ -56,12 +56,12 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_ReadDigitalInput                    |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     UINT ui_NoOfChannels    : No Of Channels To read       |
+ |                     UINT *data              : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -73,7 +73,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ 
+-INT i_APCI3501_ReadDigitalInput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI3501_ReadDigitalInput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+@@ -99,12 +99,12 @@ INT i_APCI3501_ReadDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_ConfigDigitalOutput                     |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Digital Output Subdevice.               |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev : Driver handle                     |
++| Input Parameters  : struct comedi_device *dev : Driver handle                     |
+ |                     UINT *data         : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |                                                                            |
+@@ -121,7 +121,7 @@ INT i_APCI3501_ReadDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI3501_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
++int i_APCI3501_ConfigDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -142,12 +142,12 @@ int i_APCI3501_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_WriteDigitalOutput                      |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : writes To the digital Output Subdevice                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     comedi_subdevice *s     : Subdevice Pointer            |
+ |                     comedi_insn *insn       : Insn Structure Pointer       |
+ |                     unsigned int *data          : Data Pointer contains        |
+@@ -161,7 +161,7 @@ int i_APCI3501_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3501_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI3501_WriteDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp, ui_Temp1;
+@@ -232,12 +232,12 @@ INT i_APCI3501_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_ReadDigitalOutput                       |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     UINT ui_NoOfChannels    : No Of Channels To read       |
+ |                     UINT *data              : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+@@ -248,7 +248,7 @@ INT i_APCI3501_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3501_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI3501_ReadDigitalOutput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+@@ -275,12 +275,12 @@ INT i_APCI3501_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_ConfigAnalogOutput                      |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Analog Output Subdevice                 |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     comedi_subdevice *s     : Subdevice Pointer            |
+ |                     comedi_insn *insn       : Insn Structure Pointer       |
+ |                     unsigned int *data          : Data Pointer contains        |
+@@ -298,7 +298,7 @@ INT i_APCI3501_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3501_ConfigAnalogOutput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI3501_ConfigAnalogOutput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	outl(data[0],
+@@ -316,12 +316,12 @@ INT i_APCI3501_ConfigAnalogOutput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_WriteAnalogOutput                       |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes To the Selected Anlog Output Channel            |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev      : Driver handle                |
++| Input Parameters  : struct comedi_device *dev      : Driver handle                |
+ |                     comedi_subdevice *s     : Subdevice Pointer            |
+ |                     comedi_insn *insn       : Insn Structure Pointer       |
+ |                     unsigned int *data          : Data Pointer contains        |
+@@ -336,7 +336,7 @@ INT i_APCI3501_ConfigAnalogOutput(comedi_device * dev, comedi_subdevice * s,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3501_WriteAnalogOutput(comedi_device * dev, comedi_subdevice * s,
++INT i_APCI3501_WriteAnalogOutput(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0, ul_Channel_no, ul_Polarity, ul_DAC_Ready = 0;;
+@@ -386,12 +386,12 @@ INT i_APCI3501_WriteAnalogOutput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_ConfigTimerCounterWatchdog              |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Timer , Counter or Watchdog             |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev : Driver handle                     |
++| Input Parameters  : struct comedi_device *dev : Driver handle                     |
+ |                     UINT *data         : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |                                                                            |
+@@ -410,7 +410,7 @@ INT i_APCI3501_WriteAnalogOutput(comedi_device * dev, comedi_subdevice * s,
+ |			                                                         |
+ +----------------------------------------------------------------------------+
+ */
+-INT i_APCI3501_ConfigTimerCounterWatchdog(comedi_device * dev,
++INT i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0;
+@@ -489,12 +489,12 @@ INT i_APCI3501_ConfigTimerCounterWatchdog(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_StartStopWriteTimerCounterWatchdog      |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Start / Stop The Selected Timer , Counter or Watchdog  |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev : Driver handle                     |
++| Input Parameters  : struct comedi_device *dev : Driver handle                     |
+ |                     UINT *data         : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |                                                                            |
+@@ -511,7 +511,7 @@ INT i_APCI3501_ConfigTimerCounterWatchdog(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3501_StartStopWriteTimerCounterWatchdog(comedi_device * dev,
++int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0;
+@@ -592,12 +592,12 @@ int i_APCI3501_StartStopWriteTimerCounterWatchdog(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_ReadTimerCounterWatchdog                |
+-|			  (comedi_device *dev,comedi_subdevice *s,               |
++|			  (struct comedi_device *dev,comedi_subdevice *s,               |
+ |                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Selected Timer , Counter or Watchdog          |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev : Driver handle                     |
++| Input Parameters  : struct comedi_device *dev : Driver handle                     |
+ |                     UINT *data         : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |                                                                            |
+@@ -613,7 +613,7 @@ int i_APCI3501_StartStopWriteTimerCounterWatchdog(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3501_ReadTimerCounterWatchdog(comedi_device * dev,
++int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -640,7 +640,7 @@ int i_APCI3501_ReadTimerCounterWatchdog(comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function   Name   :  int i_APCI3501_Reset(comedi_device *dev)			     |
++| Function   Name   :  int i_APCI3501_Reset(struct comedi_device *dev)			     |
+ |					                                                 |
+ +----------------------------------------------------------------------------+
+ | Task              :Resets the registers of the card                        |
+@@ -654,7 +654,7 @@ int i_APCI3501_ReadTimerCounterWatchdog(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3501_Reset(comedi_device * dev)
++int i_APCI3501_Reset(struct comedi_device * dev)
+ {
+ 	int i_Count = 0, i_temp = 0;
+ 	ULONG ul_Command1 = 0, ul_Polarity, ul_DAC_Ready = 0;
+@@ -708,7 +708,7 @@ int i_APCI3501_Reset(comedi_device * dev)
+ void v_APCI3501_Interrupt(int irq, void *d)
+ {
+ 	int i_temp;
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	unsigned int ui_Timer_AOWatchdog;
+ 	unsigned long ul_Command1;
+ 	// Disable Interrupt
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
+index aeb7f032884f..a7dd01e5e57a 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
+@@ -55,40 +55,40 @@ comedi_lrange range_apci3501_ao = { 2, {
+ // Hardware Layer  functions for Apci3501
+ 
+ //AO
+-INT i_APCI3501_ConfigAnalogOutput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI3501_ConfigAnalogOutput(struct comedi_device *dev, comedi_subdevice *s,
+ 				  comedi_insn *insn, unsigned int *data);
+-INT i_APCI3501_WriteAnalogOutput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI3501_WriteAnalogOutput(struct comedi_device *dev, comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+ 
+ //DI
+ // for di read
+-//INT i_APCI3501_ReadDigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data);
++//INT i_APCI3501_ReadDigitalInput(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data);
+ 
+-INT i_APCI3501_ReadDigitalInput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI3501_ReadDigitalInput(struct comedi_device *dev, comedi_subdevice *s,
+ 				comedi_insn *insn, unsigned int *data);
+ 
+ //DO
+-int i_APCI3501_ConfigDigitalOutput(comedi_device *dev, comedi_subdevice *s,
++int i_APCI3501_ConfigDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+-INT i_APCI3501_WriteDigitalOutput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI3501_WriteDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
+ 				  comedi_insn *insn, unsigned int *data);
+-INT i_APCI3501_ReadDigitalOutput(comedi_device *dev, comedi_subdevice *s,
++INT i_APCI3501_ReadDigitalOutput(struct comedi_device *dev, comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+ // timer value is passed as u seconds
+-INT i_APCI3501_ConfigTimerCounterWatchdog(comedi_device *dev,
++INT i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device *dev,
+ 					  comedi_subdevice *s,
+ 					  comedi_insn *insn, unsigned int *data);
+-int i_APCI3501_StartStopWriteTimerCounterWatchdog(comedi_device *dev,
++int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
+ 						  comedi_subdevice *s,
+ 						  comedi_insn *insn,
+ 						  unsigned int *data);
+-int i_APCI3501_ReadTimerCounterWatchdog(comedi_device *dev,
++int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device *dev,
+ 					comedi_subdevice *s,
+ 					comedi_insn *insn, unsigned int *data);
+ //Interrupt
+ void v_APCI3501_Interrupt(int irq, void *d);
+ 
+ //Reset functions
+-int i_APCI3501_Reset(comedi_device *dev);
++int i_APCI3501_Reset(struct comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+index 7a78c99405b2..44ca298f75ba 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+@@ -55,7 +55,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT   i_APCI3XXX_TestConversionStarted                 |
+-|                          (comedi_device    *dev)                           |
++|                          (struct comedi_device    *dev)                           |
+ +----------------------------------------------------------------------------+
+ | Task                Test if any conversion started                         |
+ +----------------------------------------------------------------------------+
+@@ -68,7 +68,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3XXX_TestConversionStarted(comedi_device * dev)
++int i_APCI3XXX_TestConversionStarted(struct comedi_device * dev)
+ {
+ 	if ((readl((void *)(devpriv->dw_AiBase + 8)) & 0x80000UL) == 0x80000UL) {
+ 		return (1);
+@@ -80,7 +80,7 @@ int i_APCI3XXX_TestConversionStarted(comedi_device * dev)
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT   i_APCI3XXX_AnalogInputConfigOperatingMode        |
+-|                          (comedi_device    *dev,                           |
++|                          (struct comedi_device    *dev,                           |
+ |                           comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+@@ -105,7 +105,7 @@ int i_APCI3XXX_TestConversionStarted(comedi_device * dev)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3XXX_AnalogInputConfigOperatingMode(comedi_device * dev,
++int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+@@ -274,7 +274,7 @@ int i_APCI3XXX_AnalogInputConfigOperatingMode(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT   i_APCI3XXX_InsnConfigAnalogInput                 |
+-|                          (comedi_device    *dev,                           |
++|                          (struct comedi_device    *dev,                           |
+ |                           comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+@@ -295,7 +295,7 @@ int i_APCI3XXX_AnalogInputConfigOperatingMode(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3XXX_InsnConfigAnalogInput(comedi_device * dev,
++int i_APCI3XXX_InsnConfigAnalogInput(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+@@ -332,7 +332,7 @@ int i_APCI3XXX_InsnConfigAnalogInput(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT   i_APCI3XXX_InsnReadAnalogInput                   |
+-|                          (comedi_device    *dev,                           |
++|                          (struct comedi_device    *dev,                           |
+ |                           comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+@@ -355,7 +355,7 @@ int i_APCI3XXX_InsnConfigAnalogInput(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3XXX_InsnReadAnalogInput(comedi_device * dev,
++int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+@@ -606,7 +606,7 @@ int i_APCI3XXX_InsnReadAnalogInput(comedi_device * dev,
+ 
+ void v_APCI3XXX_Interrupt(int irq, void *d)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	BYTE b_CopyCpt = 0;
+ 	DWORD dw_Status = 0;
+ 
+@@ -663,7 +663,7 @@ void v_APCI3XXX_Interrupt(int irq, void *d)
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT   i_APCI3XXX_InsnWriteAnalogOutput                 |
+-|                          (comedi_device    *dev,                           |
++|                          (struct comedi_device    *dev,                           |
+ |                           comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+@@ -684,7 +684,7 @@ void v_APCI3XXX_Interrupt(int irq, void *d)
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3XXX_InsnWriteAnalogOutput(comedi_device * dev,
++int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_Range = (BYTE) CR_RANGE(insn->chanspec);
+@@ -769,7 +769,7 @@ int i_APCI3XXX_InsnWriteAnalogOutput(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT   i_APCI3XXX_InsnConfigInitTTLIO                   |
+-|                          (comedi_device    *dev,                           |
++|                          (struct comedi_device    *dev,                           |
+ |                           comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+@@ -791,7 +791,7 @@ int i_APCI3XXX_InsnWriteAnalogOutput(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3XXX_InsnConfigInitTTLIO(comedi_device * dev,
++int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+@@ -900,7 +900,7 @@ int i_APCI3XXX_InsnConfigInitTTLIO(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT     i_APCI3XXX_InsnBitsTTLIO                       |
+-|                          (comedi_device    *dev,                           |
++|                          (struct comedi_device    *dev,                           |
+ |                           comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+@@ -919,7 +919,7 @@ int i_APCI3XXX_InsnConfigInitTTLIO(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3XXX_InsnBitsTTLIO(comedi_device * dev,
++int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+@@ -1057,7 +1057,7 @@ int i_APCI3XXX_InsnBitsTTLIO(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT i_APCI3XXX_InsnReadTTLIO                           |
+-|                          (comedi_device    *dev,                           |
++|                          (struct comedi_device    *dev,                           |
+ |                           comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+@@ -1074,7 +1074,7 @@ int i_APCI3XXX_InsnBitsTTLIO(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3XXX_InsnReadTTLIO(comedi_device * dev,
++int i_APCI3XXX_InsnReadTTLIO(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
+@@ -1169,7 +1169,7 @@ int i_APCI3XXX_InsnReadTTLIO(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT     i_APCI3XXX_InsnWriteTTLIO                      |
+-|                          (comedi_device    *dev,                           |
++|                          (struct comedi_device    *dev,                           |
+ |                           comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+ |                           unsigned int         *data)                          |
+@@ -1187,7 +1187,7 @@ int i_APCI3XXX_InsnReadTTLIO(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3XXX_InsnWriteTTLIO(comedi_device * dev,
++int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+@@ -1281,7 +1281,7 @@ int i_APCI3XXX_InsnWriteTTLIO(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3XXX_InsnReadDigitalInput                     |
+-|                                          (comedi_device *dev,              |
++|                                          (struct comedi_device *dev,              |
+ |                                           comedi_subdevice *s,             |
+ |                                           comedi_insn *insn,               |
+ |                                           unsigned int *data)                  |
+@@ -1298,7 +1298,7 @@ int i_APCI3XXX_InsnWriteTTLIO(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3XXX_InsnReadDigitalInput(comedi_device * dev,
++int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+@@ -1340,7 +1340,7 @@ int i_APCI3XXX_InsnReadDigitalInput(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3XXX_InsnBitsDigitalInput                     |
+-|                                          (comedi_device *dev,              |
++|                                          (struct comedi_device *dev,              |
+ |                                           comedi_subdevice *s,             |
+ |                                           comedi_insn *insn,               |
+ |                                           unsigned int *data)                  |
+@@ -1356,7 +1356,7 @@ int i_APCI3XXX_InsnReadDigitalInput(comedi_device * dev,
+ |                    -101 : Data size error                                  |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI3XXX_InsnBitsDigitalInput(comedi_device * dev,
++int i_APCI3XXX_InsnBitsDigitalInput(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+@@ -1391,7 +1391,7 @@ int i_APCI3XXX_InsnBitsDigitalInput(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3XXX_InsnBitsDigitalOutput                    |
+-|                                          (comedi_device *dev,              |
++|                                          (struct comedi_device *dev,              |
+ |                                           comedi_subdevice *s,             |
+ |                                           comedi_insn *insn,               |
+ |                                           unsigned int *data)                  |
+@@ -1409,7 +1409,7 @@ int i_APCI3XXX_InsnBitsDigitalInput(comedi_device * dev,
+ |                    -101 : Data size error                                  |
+ +----------------------------------------------------------------------------+
+ */
+-int i_APCI3XXX_InsnBitsDigitalOutput(comedi_device * dev,
++int i_APCI3XXX_InsnBitsDigitalOutput(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+@@ -1487,7 +1487,7 @@ int i_APCI3XXX_InsnBitsDigitalOutput(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3XXX_InsnWriteDigitalOutput                   |
+-|                                          (comedi_device *dev,              |
++|                                          (struct comedi_device *dev,              |
+ |                                           comedi_subdevice *s,             |
+ |                                           comedi_insn *insn,               |
+ |                                           unsigned int *data)                  |
+@@ -1505,7 +1505,7 @@ int i_APCI3XXX_InsnBitsDigitalOutput(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3XXX_InsnWriteDigitalOutput(comedi_device * dev,
++int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+@@ -1563,7 +1563,7 @@ int i_APCI3XXX_InsnWriteDigitalOutput(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3XXX_InsnReadDigitalOutput                    |
+-|                                          (comedi_device *dev,              |
++|                                          (struct comedi_device *dev,              |
+ |                                           comedi_subdevice *s,             |
+ |                                           comedi_insn *insn,               |
+ |                                           unsigned int *data)                  |
+@@ -1580,7 +1580,7 @@ int i_APCI3XXX_InsnWriteDigitalOutput(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3XXX_InsnReadDigitalOutput(comedi_device * dev,
++int i_APCI3XXX_InsnReadDigitalOutput(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+@@ -1627,10 +1627,10 @@ int i_APCI3XXX_InsnReadDigitalOutput(comedi_device * dev,
+ 
+ /*
+ +----------------------------------------------------------------------------+
+-| Function   Name   : int i_APCI3XXX_Reset(comedi_device *dev)               |                                                         +----------------------------------------------------------------------------+
++| Function   Name   : int i_APCI3XXX_Reset(struct comedi_device *dev)               |                                                         +----------------------------------------------------------------------------+
+ | Task              :resets all the registers                                |
+ +----------------------------------------------------------------------------+
+-| Input Parameters  : comedi_device *dev                                     |
++| Input Parameters  : struct comedi_device *dev                                     |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -                                                      |
+ +----------------------------------------------------------------------------+
+@@ -1638,7 +1638,7 @@ int i_APCI3XXX_InsnReadDigitalOutput(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3XXX_Reset(comedi_device * dev)
++int i_APCI3XXX_Reset(struct comedi_device * dev)
+ {
+ 	unsigned char b_Cpt = 0;
+ 
+diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c
+index 65fe959fc53b..20aa52943fad 100644
+--- a/drivers/staging/comedi/drivers/adl_pci6208.c
++++ b/drivers/staging/comedi/drivers/adl_pci6208.c
+@@ -106,8 +106,8 @@ typedef struct {
+ 
+ #define devpriv ((pci6208_private *)dev->private)
+ 
+-static int pci6208_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pci6208_detach(comedi_device * dev);
++static int pci6208_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pci6208_detach(struct comedi_device * dev);
+ 
+ #define pci6208_board_nbr \
+ 	(sizeof(pci6208_boards) / sizeof(pci6208_board))
+@@ -121,19 +121,19 @@ static comedi_driver driver_pci6208 = {
+ 
+ COMEDI_PCI_INITCLEANUP(driver_pci6208, pci6208_pci_table);
+ 
+-static int pci6208_find_device(comedi_device * dev, int bus, int slot);
++static int pci6208_find_device(struct comedi_device * dev, int bus, int slot);
+ static int
+ pci6208_pci_setup(struct pci_dev *pci_dev, unsigned long *io_base_ptr,
+ 	int dev_minor);
+ 
+ /*read/write functions*/
+-static int pci6208_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int pci6208_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int pci6208_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int pci6208_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-//static int pci6208_dio_insn_bits(comedi_device *dev,comedi_subdevice *s,
++//static int pci6208_dio_insn_bits(struct comedi_device *dev,comedi_subdevice *s,
+ //      comedi_insn *insn,unsigned int *data);
+-//static int pci6208_dio_insn_config(comedi_device *dev,comedi_subdevice *s,
++//static int pci6208_dio_insn_config(struct comedi_device *dev,comedi_subdevice *s,
+ //      comedi_insn *insn,unsigned int *data);
+ 
+ /*
+@@ -142,7 +142,7 @@ static int pci6208_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pci6208_attach(comedi_device * dev, comedi_devconfig * it)
++static int pci6208_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	int retval;
+@@ -205,7 +205,7 @@ static int pci6208_attach(comedi_device * dev, comedi_devconfig * it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int pci6208_detach(comedi_device * dev)
++static int pci6208_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: pci6208: remove\n", dev->minor);
+ 
+@@ -219,7 +219,7 @@ static int pci6208_detach(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int pci6208_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int pci6208_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i = 0, Data_Read;
+@@ -244,7 +244,7 @@ static int pci6208_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ 
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+-static int pci6208_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int pci6208_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -261,7 +261,7 @@ static int pci6208_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+  * useful to applications if you implement the insn_bits interface.
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+-//static int pci6208_dio_insn_bits(comedi_device *dev,comedi_subdevice *s,
++//static int pci6208_dio_insn_bits(struct comedi_device *dev,comedi_subdevice *s,
+ //      comedi_insn *insn,unsigned int *data)
+ //{
+ //      if(insn->n!=2)return -EINVAL;
+@@ -285,7 +285,7 @@ static int pci6208_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+ //      return 2;
+ //}
+ 
+-//static int pci6208_dio_insn_config(comedi_device *dev,comedi_subdevice *s,
++//static int pci6208_dio_insn_config(struct comedi_device *dev,comedi_subdevice *s,
+ //      comedi_insn *insn,unsigned int *data)
+ //{
+ //      int chan=CR_CHAN(insn->chanspec);
+@@ -305,7 +305,7 @@ static int pci6208_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+ //      return 1;
+ //}
+ 
+-static int pci6208_find_device(comedi_device * dev, int bus, int slot)
++static int pci6208_find_device(struct comedi_device * dev, int bus, int slot)
+ {
+ 	struct pci_dev *pci_dev;
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/adl_pci7296.c b/drivers/staging/comedi/drivers/adl_pci7296.c
+index ddd3e2d8848a..9c9d3f47f503 100644
+--- a/drivers/staging/comedi/drivers/adl_pci7296.c
++++ b/drivers/staging/comedi/drivers/adl_pci7296.c
+@@ -63,8 +63,8 @@ typedef struct {
+ 
+ #define devpriv ((adl_pci7296_private *)dev->private)
+ 
+-static int adl_pci7296_attach(comedi_device * dev, comedi_devconfig * it);
+-static int adl_pci7296_detach(comedi_device * dev);
++static int adl_pci7296_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int adl_pci7296_detach(struct comedi_device * dev);
+ static comedi_driver driver_adl_pci7296 = {
+       driver_name:"adl_pci7296",
+       module:THIS_MODULE,
+@@ -72,7 +72,7 @@ static comedi_driver driver_adl_pci7296 = {
+       detach:adl_pci7296_detach,
+ };
+ 
+-static int adl_pci7296_attach(comedi_device * dev, comedi_devconfig * it)
++static int adl_pci7296_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	struct pci_dev *pcidev;
+ 	comedi_subdevice *s;
+@@ -148,7 +148,7 @@ static int adl_pci7296_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return -EIO;
+ }
+ 
+-static int adl_pci7296_detach(comedi_device * dev)
++static int adl_pci7296_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: pci7432: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/adl_pci7432.c b/drivers/staging/comedi/drivers/adl_pci7432.c
+index 4e54d08d2e37..75208720b175 100644
+--- a/drivers/staging/comedi/drivers/adl_pci7432.c
++++ b/drivers/staging/comedi/drivers/adl_pci7432.c
+@@ -58,8 +58,8 @@ typedef struct {
+ 
+ #define devpriv ((adl_pci7432_private *)dev->private)
+ 
+-static int adl_pci7432_attach(comedi_device * dev, comedi_devconfig * it);
+-static int adl_pci7432_detach(comedi_device * dev);
++static int adl_pci7432_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int adl_pci7432_detach(struct comedi_device * dev);
+ static comedi_driver driver_adl_pci7432 = {
+       driver_name:"adl_pci7432",
+       module:THIS_MODULE,
+@@ -69,15 +69,15 @@ static comedi_driver driver_adl_pci7432 = {
+ 
+ /* Digital IO */
+ 
+-static int adl_pci7432_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int adl_pci7432_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int adl_pci7432_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int adl_pci7432_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ /*            */
+ 
+-static int adl_pci7432_attach(comedi_device * dev, comedi_devconfig * it)
++static int adl_pci7432_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	struct pci_dev *pcidev;
+ 	comedi_subdevice *s;
+@@ -150,7 +150,7 @@ static int adl_pci7432_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return -EIO;
+ }
+ 
+-static int adl_pci7432_detach(comedi_device * dev)
++static int adl_pci7432_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: pci7432: remove\n", dev->minor);
+ 
+@@ -164,7 +164,7 @@ static int adl_pci7432_detach(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int adl_pci7432_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int adl_pci7432_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	printk("comedi: pci7432_do_insn_bits called\n");
+@@ -184,7 +184,7 @@ static int adl_pci7432_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int adl_pci7432_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int adl_pci7432_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	printk("comedi: pci7432_di_insn_bits called\n");
+diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c
+index 9d5c9875a06b..4cb3dc2e13bd 100644
+--- a/drivers/staging/comedi/drivers/adl_pci8164.c
++++ b/drivers/staging/comedi/drivers/adl_pci8164.c
+@@ -70,8 +70,8 @@ typedef struct {
+ 
+ #define devpriv ((adl_pci8164_private *)dev->private)
+ 
+-static int adl_pci8164_attach(comedi_device * dev, comedi_devconfig * it);
+-static int adl_pci8164_detach(comedi_device * dev);
++static int adl_pci8164_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int adl_pci8164_detach(struct comedi_device * dev);
+ static comedi_driver driver_adl_pci8164 = {
+       driver_name:"adl_pci8164",
+       module:THIS_MODULE,
+@@ -79,31 +79,31 @@ static comedi_driver driver_adl_pci8164 = {
+       detach:adl_pci8164_detach,
+ };
+ 
+-static int adl_pci8164_insn_read_msts(comedi_device * dev, comedi_subdevice * s,
++static int adl_pci8164_insn_read_msts(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int adl_pci8164_insn_read_ssts(comedi_device * dev, comedi_subdevice * s,
++static int adl_pci8164_insn_read_ssts(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int adl_pci8164_insn_read_buf0(comedi_device * dev, comedi_subdevice * s,
++static int adl_pci8164_insn_read_buf0(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int adl_pci8164_insn_read_buf1(comedi_device * dev, comedi_subdevice * s,
++static int adl_pci8164_insn_read_buf1(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int adl_pci8164_insn_write_cmd(comedi_device * dev, comedi_subdevice * s,
++static int adl_pci8164_insn_write_cmd(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int adl_pci8164_insn_write_otp(comedi_device * dev, comedi_subdevice * s,
++static int adl_pci8164_insn_write_otp(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int adl_pci8164_insn_write_buf0(comedi_device * dev,
++static int adl_pci8164_insn_write_buf0(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+-static int adl_pci8164_insn_write_buf1(comedi_device * dev,
++static int adl_pci8164_insn_write_buf1(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+-static int adl_pci8164_attach(comedi_device * dev, comedi_devconfig * it)
++static int adl_pci8164_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	struct pci_dev *pcidev;
+ 	comedi_subdevice *s;
+@@ -194,7 +194,7 @@ static int adl_pci8164_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return -EIO;
+ }
+ 
+-static int adl_pci8164_detach(comedi_device * dev)
++static int adl_pci8164_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: pci8164: remove\n", dev->minor);
+ 
+@@ -208,7 +208,7 @@ static int adl_pci8164_detach(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int adl_pci8164_insn_read_msts(comedi_device * dev, comedi_subdevice * s,
++static int adl_pci8164_insn_read_msts(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+@@ -245,7 +245,7 @@ static int adl_pci8164_insn_read_msts(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int adl_pci8164_insn_read_ssts(comedi_device * dev, comedi_subdevice * s,
++static int adl_pci8164_insn_read_ssts(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+@@ -282,7 +282,7 @@ static int adl_pci8164_insn_read_ssts(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int adl_pci8164_insn_read_buf0(comedi_device * dev, comedi_subdevice * s,
++static int adl_pci8164_insn_read_buf0(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+@@ -319,7 +319,7 @@ static int adl_pci8164_insn_read_buf0(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int adl_pci8164_insn_read_buf1(comedi_device * dev, comedi_subdevice * s,
++static int adl_pci8164_insn_read_buf1(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+@@ -357,7 +357,7 @@ static int adl_pci8164_insn_read_buf1(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int adl_pci8164_insn_write_cmd(comedi_device * dev, comedi_subdevice * s,
++static int adl_pci8164_insn_write_cmd(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int axis, axis_reg;
+@@ -395,7 +395,7 @@ static int adl_pci8164_insn_write_cmd(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int adl_pci8164_insn_write_otp(comedi_device * dev, comedi_subdevice * s,
++static int adl_pci8164_insn_write_otp(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+@@ -433,7 +433,7 @@ static int adl_pci8164_insn_write_otp(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int adl_pci8164_insn_write_buf0(comedi_device * dev,
++static int adl_pci8164_insn_write_buf0(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+@@ -471,7 +471,7 @@ static int adl_pci8164_insn_write_buf0(comedi_device * dev,
+ 	return 2;
+ }
+ 
+-static int adl_pci8164_insn_write_buf1(comedi_device * dev,
++static int adl_pci8164_insn_write_buf1(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
+index 1b9e9740a4c7..53eb696c06ad 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9111.c
++++ b/drivers/staging/comedi/drivers/adl_pci9111.c
+@@ -265,9 +265,9 @@ Configuration options:
+ // Function prototypes
+ //
+ 
+-static int pci9111_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pci9111_detach(comedi_device * dev);
+-static void pci9111_ai_munge(comedi_device * dev, comedi_subdevice * s,
++static int pci9111_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pci9111_detach(struct comedi_device * dev);
++static void pci9111_ai_munge(struct comedi_device * dev, comedi_subdevice * s,
+ 	void *data, unsigned int num_bytes, unsigned int start_chan_index);
+ 
+ static const comedi_lrange pci9111_hr_ai_range = {
+@@ -415,7 +415,7 @@ static void plx9050_interrupt_control(unsigned long io_base,
+ // 8254 timer
+ //
+ 
+-static void pci9111_timer_set(comedi_device * dev)
++static void pci9111_timer_set(struct comedi_device * dev)
+ {
+ 	pci9111_8254_control_set(PCI9111_8254_COUNTER_0 |
+ 		PCI9111_8254_READ_LOAD_LSB_MSB |
+@@ -441,7 +441,7 @@ typedef enum {
+ 	external
+ } pci9111_trigger_sources;
+ 
+-static void pci9111_trigger_source_set(comedi_device * dev,
++static void pci9111_trigger_source_set(struct comedi_device * dev,
+ 	pci9111_trigger_sources source)
+ {
+ 	int flags;
+@@ -465,7 +465,7 @@ static void pci9111_trigger_source_set(comedi_device * dev,
+ 	pci9111_trigger_and_autoscan_set(flags);
+ }
+ 
+-static void pci9111_pretrigger_set(comedi_device * dev, bool pretrigger)
++static void pci9111_pretrigger_set(struct comedi_device * dev, bool pretrigger)
+ {
+ 	int flags;
+ 
+@@ -477,7 +477,7 @@ static void pci9111_pretrigger_set(comedi_device * dev, bool pretrigger)
+ 	pci9111_trigger_and_autoscan_set(flags);
+ }
+ 
+-static void pci9111_autoscan_set(comedi_device * dev, bool autoscan)
++static void pci9111_autoscan_set(struct comedi_device * dev, bool autoscan)
+ {
+ 	int flags;
+ 
+@@ -499,7 +499,7 @@ typedef enum {
+ 	irq_on_external_trigger
+ } pci9111_ISC1_sources;
+ 
+-static void pci9111_interrupt_source_set(comedi_device * dev,
++static void pci9111_interrupt_source_set(struct comedi_device * dev,
+ 	pci9111_ISC0_sources irq_0_source, pci9111_ISC1_sources irq_1_source)
+ {
+ 	int flags;
+@@ -527,7 +527,7 @@ static void pci9111_interrupt_source_set(comedi_device * dev,
+ 
+ #undef AI_DO_CMD_DEBUG
+ 
+-static int pci9111_ai_cancel(comedi_device * dev, comedi_subdevice * s)
++static int pci9111_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	// Disable interrupts
+ 
+@@ -557,7 +557,7 @@ static int pci9111_ai_cancel(comedi_device * dev, comedi_subdevice * s)
+   if (!src || tmp != src) error++
+ 
+ static int
+-pci9111_ai_do_cmd_test(comedi_device * dev,
++pci9111_ai_do_cmd_test(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_cmd * cmd)
+ {
+ 	int tmp;
+@@ -758,7 +758,7 @@ pci9111_ai_do_cmd_test(comedi_device * dev,
+ // Analog input command
+ //
+ 
+-static int pci9111_ai_do_cmd(comedi_device * dev, comedi_subdevice * subdevice)
++static int pci9111_ai_do_cmd(struct comedi_device * dev, comedi_subdevice * subdevice)
+ {
+ 	comedi_cmd *async_cmd = &subdevice->async->cmd;
+ 
+@@ -881,7 +881,7 @@ static int pci9111_ai_do_cmd(comedi_device * dev, comedi_subdevice * subdevice)
+ 	return 0;
+ }
+ 
+-static void pci9111_ai_munge(comedi_device * dev, comedi_subdevice * s,
++static void pci9111_ai_munge(struct comedi_device * dev, comedi_subdevice * s,
+ 	void *data, unsigned int num_bytes, unsigned int start_chan_index)
+ {
+ 	unsigned int i, num_samples = num_bytes / sizeof(short);
+@@ -911,7 +911,7 @@ static void pci9111_ai_munge(comedi_device * dev, comedi_subdevice * s,
+ 
+ static irqreturn_t pci9111_interrupt(int irq, void *p_device PT_REGS_ARG)
+ {
+-	comedi_device *dev = p_device;
++	struct comedi_device *dev = p_device;
+ 	comedi_subdevice *subdevice = dev->read_subdev;
+ 	comedi_async *async;
+ 	unsigned long irq_flags;
+@@ -1071,7 +1071,7 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device PT_REGS_ARG)
+ 
+ #undef AI_INSN_DEBUG
+ 
+-static int pci9111_ai_insn_read(comedi_device * dev,
++static int pci9111_ai_insn_read(struct comedi_device * dev,
+ 	comedi_subdevice * subdevice, comedi_insn * insn, unsigned int * data)
+ {
+ 	int resolution =
+@@ -1131,7 +1131,7 @@ static int pci9111_ai_insn_read(comedi_device * dev,
+ //
+ 
+ static int
+-pci9111_ao_insn_write(comedi_device * dev,
++pci9111_ao_insn_write(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -1148,7 +1148,7 @@ pci9111_ao_insn_write(comedi_device * dev,
+ // Analog output readback
+ //
+ 
+-static int pci9111_ao_insn_read(comedi_device * dev,
++static int pci9111_ao_insn_read(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -1170,7 +1170,7 @@ static int pci9111_ao_insn_read(comedi_device * dev,
+ // Digital inputs
+ //
+ 
+-static int pci9111_di_insn_bits(comedi_device * dev,
++static int pci9111_di_insn_bits(struct comedi_device * dev,
+ 	comedi_subdevice * subdevice, comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bits;
+@@ -1185,7 +1185,7 @@ static int pci9111_di_insn_bits(comedi_device * dev,
+ // Digital outputs
+ //
+ 
+-static int pci9111_do_insn_bits(comedi_device * dev,
++static int pci9111_do_insn_bits(struct comedi_device * dev,
+ 	comedi_subdevice * subdevice, comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bits;
+@@ -1218,7 +1218,7 @@ static int pci9111_do_insn_bits(comedi_device * dev,
+ // Reset device
+ //
+ 
+-static int pci9111_reset(comedi_device * dev)
++static int pci9111_reset(struct comedi_device * dev)
+ {
+ 	// Set trigger source to software
+ 
+@@ -1246,7 +1246,7 @@ static int pci9111_reset(comedi_device * dev)
+ //      - Declare device driver capability
+ //
+ 
+-static int pci9111_attach(comedi_device * dev, comedi_devconfig * it)
++static int pci9111_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *subdevice;
+ 	unsigned long io_base, io_range, lcr_io_base, lcr_io_range;
+@@ -1420,7 +1420,7 @@ static int pci9111_attach(comedi_device * dev, comedi_devconfig * it)
+ // Detach
+ //
+ 
+-static int pci9111_detach(comedi_device * dev)
++static int pci9111_detach(struct comedi_device * dev)
+ {
+ 	// Reset device
+ 
+diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
+index 9dc30b282973..c352e37d97ae 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9118.c
++++ b/drivers/staging/comedi/drivers/adl_pci9118.c
+@@ -178,8 +178,8 @@ static const comedi_lrange range_pci9118hg = { 8, {
+ 
+ #define PCI9118_BIPOLAR_RANGES	4	/* used for test on mixture of BIP/UNI ranges */
+ 
+-static int pci9118_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pci9118_detach(comedi_device * dev);
++static int pci9118_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pci9118_detach(struct comedi_device * dev);
+ 
+ typedef struct {
+ 	const char *name;	// board name
+@@ -288,7 +288,7 @@ typedef struct {
+ 	unsigned char cnt0_users;	// bit field of 8254 CNT0 users (0-unused, 1-AO, 2-DI, 3-DO)
+ 	unsigned char exttrg_users;	// bit field of external trigger users (0-AI, 1-AO, 2-DI, 3-DO)
+ 	unsigned int cnt0_divisor;	// actual CNT0 divisor
+-	void (*int_ai_func) (comedi_device *, comedi_subdevice *, unsigned short, unsigned int, unsigned short);	// ptr to actual interrupt AI function
++	void (*int_ai_func) (struct comedi_device *, comedi_subdevice *, unsigned short, unsigned int, unsigned short);	// ptr to actual interrupt AI function
+ 	unsigned char ai16bits;	// =1 16 bit card
+ 	unsigned char usedma;	// =1 use DMA transfer and not INT
+ 	unsigned char useeoshandle;	// =1 change WAKE_EOS DMA transfer to fit on every second
+@@ -308,18 +308,18 @@ typedef struct {
+ ==============================================================================
+ */
+ 
+-static int check_channel_list(comedi_device * dev, comedi_subdevice * s,
++static int check_channel_list(struct comedi_device * dev, comedi_subdevice * s,
+ 	int n_chan, unsigned int *chanlist, int frontadd, int backadd);
+-static int setup_channel_list(comedi_device * dev, comedi_subdevice * s,
++static int setup_channel_list(struct comedi_device * dev, comedi_subdevice * s,
+ 	int n_chan, unsigned int *chanlist, int rot, int frontadd, int backadd,
+ 	int usedma, char eoshandle);
+-static void start_pacer(comedi_device * dev, int mode, unsigned int divisor1,
++static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
+ 	unsigned int divisor2);
+-static int pci9118_reset(comedi_device * dev);
+-static int pci9118_exttrg_add(comedi_device * dev, unsigned char source);
+-static int pci9118_exttrg_del(comedi_device * dev, unsigned char source);
+-static int pci9118_ai_cancel(comedi_device * dev, comedi_subdevice * s);
+-static void pci9118_calc_divisors(char mode, comedi_device * dev,
++static int pci9118_reset(struct comedi_device * dev);
++static int pci9118_exttrg_add(struct comedi_device * dev, unsigned char source);
++static int pci9118_exttrg_del(struct comedi_device * dev, unsigned char source);
++static int pci9118_ai_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static void pci9118_calc_divisors(char mode, struct comedi_device * dev,
+ 	comedi_subdevice * s, unsigned int *tim1, unsigned int *tim2,
+ 	unsigned int flags, int chans, unsigned int *div1, unsigned int *div2,
+ 	char usessh, unsigned int chnsshfront);
+@@ -327,7 +327,7 @@ static void pci9118_calc_divisors(char mode, comedi_device * dev,
+ /*
+ ==============================================================================
+ */
+-static int pci9118_insn_read_ai(comedi_device * dev, comedi_subdevice * s,
++static int pci9118_insn_read_ai(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -377,7 +377,7 @@ static int pci9118_insn_read_ai(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pci9118_insn_write_ao(comedi_device * dev, comedi_subdevice * s,
++static int pci9118_insn_write_ao(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, chanreg, ch;
+@@ -400,7 +400,7 @@ static int pci9118_insn_write_ao(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pci9118_insn_read_ao(comedi_device * dev, comedi_subdevice * s,
++static int pci9118_insn_read_ao(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, chan;
+@@ -415,7 +415,7 @@ static int pci9118_insn_read_ao(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pci9118_insn_bits_di(comedi_device * dev, comedi_subdevice * s,
++static int pci9118_insn_bits_di(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[1] = inl(dev->iobase + PCI9118_DI) & 0xf;
+@@ -426,7 +426,7 @@ static int pci9118_insn_bits_di(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pci9118_insn_bits_do(comedi_device * dev, comedi_subdevice * s,
++static int pci9118_insn_bits_do(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+@@ -442,7 +442,7 @@ static int pci9118_insn_bits_do(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static void interrupt_pci9118_ai_mode4_switch(comedi_device * dev)
++static void interrupt_pci9118_ai_mode4_switch(struct comedi_device * dev)
+ {
+ 	devpriv->AdFunctionReg =
+ 		AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM;
+@@ -456,7 +456,7 @@ static void interrupt_pci9118_ai_mode4_switch(comedi_device * dev)
+ 	outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
+ }
+ 
+-static unsigned int defragment_dma_buffer(comedi_device * dev,
++static unsigned int defragment_dma_buffer(struct comedi_device * dev,
+ 	comedi_subdevice * s, short * dma_buffer, unsigned int num_samples)
+ {
+ 	unsigned int i = 0, j = 0;
+@@ -480,7 +480,7 @@ static unsigned int defragment_dma_buffer(comedi_device * dev,
+ /*
+ ==============================================================================
+ */
+-static unsigned int move_block_from_dma(comedi_device * dev,
++static unsigned int move_block_from_dma(struct comedi_device * dev,
+ 	comedi_subdevice * s, short * dma_buffer, unsigned int num_samples)
+ {
+ 	unsigned int num_bytes;
+@@ -501,7 +501,7 @@ static unsigned int move_block_from_dma(comedi_device * dev,
+ /*
+ ==============================================================================
+ */
+-static char pci9118_decode_error_status(comedi_device * dev,
++static char pci9118_decode_error_status(struct comedi_device * dev,
+ 	comedi_subdevice * s, unsigned char m)
+ {
+ 	if (m & 0x100) {
+@@ -531,7 +531,7 @@ static char pci9118_decode_error_status(comedi_device * dev,
+ 	return 0;
+ }
+ 
+-static void pci9118_ai_munge(comedi_device * dev, comedi_subdevice * s,
++static void pci9118_ai_munge(struct comedi_device * dev, comedi_subdevice * s,
+ 	void *data, unsigned int num_bytes, unsigned int start_chan_index)
+ {
+ 	unsigned int i, num_samples = num_bytes / sizeof(short);
+@@ -551,7 +551,7 @@ static void pci9118_ai_munge(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static void interrupt_pci9118_ai_onesample(comedi_device * dev,
++static void interrupt_pci9118_ai_onesample(struct comedi_device * dev,
+ 	comedi_subdevice * s, unsigned short int_adstat, unsigned int int_amcc,
+ 	unsigned short int_daq)
+ {
+@@ -598,7 +598,7 @@ static void interrupt_pci9118_ai_onesample(comedi_device * dev,
+ /*
+ ==============================================================================
+ */
+-static void interrupt_pci9118_ai_dma(comedi_device * dev, comedi_subdevice * s,
++static void interrupt_pci9118_ai_dma(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned short int_adstat, unsigned int int_amcc,
+ 	unsigned short int_daq)
+ {
+@@ -676,7 +676,7 @@ static void interrupt_pci9118_ai_dma(comedi_device * dev, comedi_subdevice * s,
+ */
+ static irqreturn_t interrupt_pci9118(int irq, void *d PT_REGS_ARG)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	unsigned int int_daq = 0, int_amcc, int_adstat;
+ 
+ 	if (!dev->attached)
+@@ -727,7 +727,7 @@ static irqreturn_t interrupt_pci9118(int irq, void *d PT_REGS_ARG)
+ /*
+ ==============================================================================
+ */
+-static int pci9118_ai_inttrig(comedi_device * dev, comedi_subdevice * s,
++static int pci9118_ai_inttrig(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int trignum)
+ {
+ 	if (trignum != devpriv->ai_inttrig_start)
+@@ -751,7 +751,7 @@ static int pci9118_ai_inttrig(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pci9118_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int pci9118_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -1009,7 +1009,7 @@ static int pci9118_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int Compute_and_setup_dma(comedi_device * dev)
++static int Compute_and_setup_dma(struct comedi_device * dev)
+ {
+ 	unsigned int dmalen0, dmalen1, i;
+ 
+@@ -1163,7 +1163,7 @@ static int Compute_and_setup_dma(comedi_device * dev)
+ /*
+ ==============================================================================
+ */
+-static int pci9118_ai_docmd_sampl(comedi_device * dev, comedi_subdevice * s)
++static int pci9118_ai_docmd_sampl(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_sampl(%d,) [%d]\n",
+ 		dev->minor, devpriv->ai_do);
+@@ -1216,7 +1216,7 @@ static int pci9118_ai_docmd_sampl(comedi_device * dev, comedi_subdevice * s)
+ /*
+ ==============================================================================
+ */
+-static int pci9118_ai_docmd_dma(comedi_device * dev, comedi_subdevice * s)
++static int pci9118_ai_docmd_dma(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_dma(%d,) [%d,%d]\n",
+ 		dev->minor, devpriv->ai_do, devpriv->usedma);
+@@ -1287,7 +1287,7 @@ static int pci9118_ai_docmd_dma(comedi_device * dev, comedi_subdevice * s)
+ /*
+ ==============================================================================
+ */
+-static int pci9118_ai_cmd(comedi_device * dev, comedi_subdevice * s)
++static int pci9118_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned int addchans = 0;
+@@ -1486,7 +1486,7 @@ static int pci9118_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ /*
+ ==============================================================================
+ */
+-static int check_channel_list(comedi_device * dev, comedi_subdevice * s,
++static int check_channel_list(struct comedi_device * dev, comedi_subdevice * s,
+ 	int n_chan, unsigned int *chanlist, int frontadd, int backadd)
+ {
+ 	unsigned int i, differencial = 0, bipolar = 0;
+@@ -1537,7 +1537,7 @@ static int check_channel_list(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int setup_channel_list(comedi_device * dev, comedi_subdevice * s,
++static int setup_channel_list(struct comedi_device * dev, comedi_subdevice * s,
+ 	int n_chan, unsigned int *chanlist, int rot, int frontadd, int backadd,
+ 	int usedma, char useeos)
+ {
+@@ -1651,7 +1651,7 @@ static int setup_channel_list(comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+   calculate 8254 divisors if they are used for dual timing
+ */
+-static void pci9118_calc_divisors(char mode, comedi_device * dev,
++static void pci9118_calc_divisors(char mode, struct comedi_device * dev,
+ 	comedi_subdevice * s, unsigned int *tim1, unsigned int *tim2,
+ 	unsigned int flags, int chans, unsigned int *div1, unsigned int *div2,
+ 	char usessh, unsigned int chnsshfront)
+@@ -1710,7 +1710,7 @@ static void pci9118_calc_divisors(char mode, comedi_device * dev,
+ /*
+ ==============================================================================
+ */
+-static void start_pacer(comedi_device * dev, int mode, unsigned int divisor1,
++static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
+ 	unsigned int divisor2)
+ {
+ 	outl(0x74, dev->iobase + PCI9118_CNTCTRL);
+@@ -1729,7 +1729,7 @@ static void start_pacer(comedi_device * dev, int mode, unsigned int divisor1,
+ /*
+ ==============================================================================
+ */
+-static int pci9118_exttrg_add(comedi_device * dev, unsigned char source)
++static int pci9118_exttrg_add(struct comedi_device * dev, unsigned char source)
+ {
+ 	if (source > 3)
+ 		return -1;	// incorrect source
+@@ -1743,7 +1743,7 @@ static int pci9118_exttrg_add(comedi_device * dev, unsigned char source)
+ /*
+ ==============================================================================
+ */
+-static int pci9118_exttrg_del(comedi_device * dev, unsigned char source)
++static int pci9118_exttrg_del(struct comedi_device * dev, unsigned char source)
+ {
+ 	if (source > 3)
+ 		return -1;	// incorrect source
+@@ -1760,7 +1760,7 @@ static int pci9118_exttrg_del(comedi_device * dev, unsigned char source)
+ /*
+ ==============================================================================
+ */
+-static int pci9118_ai_cancel(comedi_device * dev, comedi_subdevice * s)
++static int pci9118_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	if (devpriv->usedma)
+ 		outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS), devpriv->iobase_a + AMCC_OP_REG_MCSR);	// stop DMA
+@@ -1795,7 +1795,7 @@ static int pci9118_ai_cancel(comedi_device * dev, comedi_subdevice * s)
+ /*
+ ==============================================================================
+ */
+-static int pci9118_reset(comedi_device * dev)
++static int pci9118_reset(struct comedi_device * dev)
+ {
+ 	devpriv->IntControlReg = 0;
+ 	devpriv->exttrg_users = 0;
+@@ -1835,7 +1835,7 @@ static int pci9118_reset(comedi_device * dev)
+ /*
+ ==============================================================================
+ */
+-static int pci9118_attach(comedi_device * dev, comedi_devconfig * it)
++static int pci9118_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	int ret, pages, i;
+@@ -2071,7 +2071,7 @@ static int pci9118_attach(comedi_device * dev, comedi_devconfig * it)
+ /*
+ ==============================================================================
+ */
+-static int pci9118_detach(comedi_device * dev)
++static int pci9118_detach(struct comedi_device * dev)
+ {
+ 	if (dev->private) {
+ 		if (devpriv->valid)
+diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c
+index f32e55921b5f..295b667a381a 100644
+--- a/drivers/staging/comedi/drivers/adq12b.c
++++ b/drivers/staging/comedi/drivers/adq12b.c
+@@ -162,8 +162,8 @@ typedef struct{
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int adq12b_attach(comedi_device *dev,comedi_devconfig *it);
+-static int adq12b_detach(comedi_device *dev);
++static int adq12b_attach(struct comedi_device *dev,comedi_devconfig *it);
++static int adq12b_detach(struct comedi_device *dev);
+ static comedi_driver driver_adq12b={
+         driver_name:    "adq12b",
+         module:         THIS_MODULE,
+@@ -174,9 +174,9 @@ static comedi_driver driver_adq12b={
+         num_names:      sizeof(adq12b_boards) / sizeof(adq12b_board),
+ };
+ 
+-static int adq12b_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data);
+-static int adq12b_di_insn_bits(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,unsigned int *data);
+-static int adq12b_do_insn_bits(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,unsigned int *data);
++static int adq12b_ai_rinsn(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data);
++static int adq12b_di_insn_bits(struct comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,unsigned int *data);
++static int adq12b_do_insn_bits(struct comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,unsigned int *data);
+ 
+ /*
+  * Attach is called by the Comedi core to configure the driver
+@@ -184,7 +184,7 @@ static int adq12b_do_insn_bits(comedi_device *dev,comedi_subdevice *s, comedi_in
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int adq12b_attach(comedi_device *dev,comedi_devconfig *it)
++static int adq12b_attach(struct comedi_device *dev,comedi_devconfig *it)
+ {
+         comedi_subdevice *s;
+         unsigned long iobase;
+@@ -297,7 +297,7 @@ static int adq12b_attach(comedi_device *dev,comedi_devconfig *it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int adq12b_detach(comedi_device *dev)
++static int adq12b_detach(struct comedi_device *dev)
+ {
+         if (dev->iobase)
+           release_region(dev->iobase, ADQ12B_SIZE);
+@@ -314,7 +314,7 @@ static int adq12b_detach(comedi_device *dev)
+  * mode.
+  */
+ 
+-static int adq12b_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data)
++static int adq12b_ai_rinsn(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data)
+ {
+         int n, i;
+         int range, channel;
+@@ -357,7 +357,7 @@ static int adq12b_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *i
+ }
+ 
+ 
+-static int adq12b_di_insn_bits(comedi_device *dev,comedi_subdevice *s, 	comedi_insn *insn,unsigned int *data)
++static int adq12b_di_insn_bits(struct comedi_device *dev,comedi_subdevice *s, 	comedi_insn *insn,unsigned int *data)
+ {
+ 
+         /* only bits 0-4 have information about digital inputs */
+@@ -367,7 +367,7 @@ static int adq12b_di_insn_bits(comedi_device *dev,comedi_subdevice *s, 	comedi_i
+ }
+ 
+ 
+-static int adq12b_do_insn_bits(comedi_device *dev,comedi_subdevice *s, 	comedi_insn *insn,unsigned int *data)
++static int adq12b_do_insn_bits(struct comedi_device *dev,comedi_subdevice *s, 	comedi_insn *insn,unsigned int *data)
+ {
+         int channel;
+ 
+diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
+index e482e602ba9e..75d915310e01 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1710.c
++++ b/drivers/staging/comedi/drivers/adv_pci1710.c
+@@ -182,8 +182,8 @@ static const comedi_lrange range_pci171x_da = { 2, {
+ 	}
+ };
+ 
+-static int pci1710_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pci1710_detach(comedi_device * dev);
++static int pci1710_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pci1710_detach(struct comedi_device * dev);
+ 
+ typedef struct {
+ 	const char *name;	// board name
+@@ -304,14 +304,14 @@ typedef struct {
+ ==============================================================================
+ */
+ 
+-static int check_channel_list(comedi_device * dev, comedi_subdevice * s,
++static int check_channel_list(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int *chanlist, unsigned int n_chan);
+-static void setup_channel_list(comedi_device * dev, comedi_subdevice * s,
++static void setup_channel_list(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int *chanlist, unsigned int n_chan, unsigned int seglen);
+-static void start_pacer(comedi_device * dev, int mode, unsigned int divisor1,
++static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
+ 	unsigned int divisor2);
+-static int pci1710_reset(comedi_device * dev);
+-static int pci171x_ai_cancel(comedi_device * dev, comedi_subdevice * s);
++static int pci1710_reset(struct comedi_device * dev);
++static int pci171x_ai_cancel(struct comedi_device * dev, comedi_subdevice * s);
+ 
+ static const unsigned int muxonechan[] = { 0x0000, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, 0x0707,	// used for gain list programming
+ 	0x0808, 0x0909, 0x0a0a, 0x0b0b, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f,
+@@ -322,7 +322,7 @@ static const unsigned int muxonechan[] = { 0x0000, 0x0101, 0x0202, 0x0303, 0x040
+ /*
+ ==============================================================================
+ */
+-static int pci171x_insn_read_ai(comedi_device * dev, comedi_subdevice * s,
++static int pci171x_insn_read_ai(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, timeout;
+@@ -390,7 +390,7 @@ static int pci171x_insn_read_ai(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pci171x_insn_write_ao(comedi_device * dev, comedi_subdevice * s,
++static int pci171x_insn_write_ao(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, chan, range, ofs;
+@@ -421,7 +421,7 @@ static int pci171x_insn_write_ao(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pci171x_insn_read_ao(comedi_device * dev, comedi_subdevice * s,
++static int pci171x_insn_read_ao(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, chan;
+@@ -436,7 +436,7 @@ static int pci171x_insn_read_ao(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pci171x_insn_bits_di(comedi_device * dev, comedi_subdevice * s,
++static int pci171x_insn_bits_di(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[1] = inw(dev->iobase + PCI171x_DI);
+@@ -447,7 +447,7 @@ static int pci171x_insn_bits_di(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pci171x_insn_bits_do(comedi_device * dev, comedi_subdevice * s,
++static int pci171x_insn_bits_do(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+@@ -463,7 +463,7 @@ static int pci171x_insn_bits_do(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pci171x_insn_counter_read(comedi_device * dev, comedi_subdevice * s,
++static int pci171x_insn_counter_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int msb, lsb, ccntrl;
+@@ -485,7 +485,7 @@ static int pci171x_insn_counter_read(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pci171x_insn_counter_write(comedi_device * dev, comedi_subdevice * s,
++static int pci171x_insn_counter_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	uint msb, lsb, ccntrl, status;
+@@ -512,7 +512,7 @@ static int pci171x_insn_counter_write(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pci171x_insn_counter_config(comedi_device * dev,
++static int pci171x_insn_counter_config(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ #ifdef unused
+@@ -548,7 +548,7 @@ static int pci171x_insn_counter_config(comedi_device * dev,
+ /*
+ ==============================================================================
+ */
+-static int pci1720_insn_write_ao(comedi_device * dev, comedi_subdevice * s,
++static int pci1720_insn_write_ao(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, rangereg, chan;
+@@ -576,7 +576,7 @@ static int pci1720_insn_write_ao(comedi_device * dev, comedi_subdevice * s,
+ */
+ static void interrupt_pci1710_every_sample(void *d)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s = dev->subdevices + 0;
+ 	int m;
+ #ifdef PCI171x_PARANOIDCHECK
+@@ -659,7 +659,7 @@ static void interrupt_pci1710_every_sample(void *d)
+ /*
+ ==============================================================================
+ */
+-static int move_block_from_fifo(comedi_device * dev, comedi_subdevice * s,
++static int move_block_from_fifo(struct comedi_device * dev, comedi_subdevice * s,
+ 	int n, int turn)
+ {
+ 	int i, j;
+@@ -707,7 +707,7 @@ static int move_block_from_fifo(comedi_device * dev, comedi_subdevice * s,
+ */
+ static void interrupt_pci1710_half_fifo(void *d)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s = dev->subdevices + 0;
+ 	int m, samplesinbuf;
+ 
+@@ -762,7 +762,7 @@ static void interrupt_pci1710_half_fifo(void *d)
+ */
+ static irqreturn_t interrupt_service_pci1710(int irq, void *d PT_REGS_ARG)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 
+ 	DPRINTK("adv_pci1710 EDBG: BGN: interrupt_service_pci1710(%d,...)\n",
+ 		irq);
+@@ -801,7 +801,7 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d PT_REGS_ARG)
+ /*
+ ==============================================================================
+ */
+-static int pci171x_ai_docmd_and_mode(int mode, comedi_device * dev,
++static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device * dev,
+ 	comedi_subdevice * s)
+ {
+ 	unsigned int divisor1, divisor2;
+@@ -900,7 +900,7 @@ static void pci171x_cmdtest_out(int e, comedi_cmd * cmd)
+ /*
+ ==============================================================================
+ */
+-static int pci171x_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int pci171x_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -1065,7 +1065,7 @@ static int pci171x_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pci171x_ai_cmd(comedi_device * dev, comedi_subdevice * s)
++static int pci171x_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 
+@@ -1104,7 +1104,7 @@ static int pci171x_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+  If it's ok, then program scan/gain logic.
+  This works for all cards.
+ */
+-static int check_channel_list(comedi_device * dev, comedi_subdevice * s,
++static int check_channel_list(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int *chanlist, unsigned int n_chan)
+ {
+ 	unsigned int chansegment[32];
+@@ -1163,7 +1163,7 @@ static int check_channel_list(comedi_device * dev, comedi_subdevice * s,
+ 	return seglen;
+ }
+ 
+-static void setup_channel_list(comedi_device * dev, comedi_subdevice * s,
++static void setup_channel_list(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int *chanlist, unsigned int n_chan, unsigned int seglen)
+ {
+ 	unsigned int i, range, chanprog;
+@@ -1200,7 +1200,7 @@ static void setup_channel_list(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static void start_pacer(comedi_device * dev, int mode, unsigned int divisor1,
++static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
+ 	unsigned int divisor2)
+ {
+ 	DPRINTK("adv_pci1710 EDBG: BGN: start_pacer(%d,%u,%u)\n", mode,
+@@ -1220,7 +1220,7 @@ static void start_pacer(comedi_device * dev, int mode, unsigned int divisor1,
+ /*
+ ==============================================================================
+ */
+-static int pci171x_ai_cancel(comedi_device * dev, comedi_subdevice * s)
++static int pci171x_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cancel(...)\n");
+ 
+@@ -1249,7 +1249,7 @@ static int pci171x_ai_cancel(comedi_device * dev, comedi_subdevice * s)
+ /*
+ ==============================================================================
+ */
+-static int pci171x_reset(comedi_device * dev)
++static int pci171x_reset(struct comedi_device * dev)
+ {
+ 	DPRINTK("adv_pci1710 EDBG: BGN: pci171x_reset(...)\n");
+ 	outw(0x30, dev->iobase + PCI171x_CNTCTRL);
+@@ -1279,7 +1279,7 @@ static int pci171x_reset(comedi_device * dev)
+ /*
+ ==============================================================================
+ */
+-static int pci1720_reset(comedi_device * dev)
++static int pci1720_reset(struct comedi_device * dev)
+ {
+ 	DPRINTK("adv_pci1710 EDBG: BGN: pci1720_reset(...)\n");
+ 	outb(Syncont_SC0, dev->iobase + PCI1720_SYNCONT);	// set synchronous output mode
+@@ -1301,7 +1301,7 @@ static int pci1720_reset(comedi_device * dev)
+ /*
+ ==============================================================================
+ */
+-static int pci1710_reset(comedi_device * dev)
++static int pci1710_reset(struct comedi_device * dev)
+ {
+ 	DPRINTK("adv_pci1710 EDBG: BGN: pci1710_reset(...)\n");
+ 	switch (this_board->cardtype) {
+@@ -1316,7 +1316,7 @@ static int pci1710_reset(comedi_device * dev)
+ /*
+ ==============================================================================
+ */
+-static int pci1710_attach(comedi_device * dev, comedi_devconfig * it)
++static int pci1710_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	int ret, subdev, n_subdevices;
+@@ -1540,7 +1540,7 @@ static int pci1710_attach(comedi_device * dev, comedi_devconfig * it)
+ /*
+ ==============================================================================
+ */
+-static int pci1710_detach(comedi_device * dev)
++static int pci1710_detach(struct comedi_device * dev)
+ {
+ 
+ 	if (dev->private) {
+diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
+index 46b70942ac85..e69c2e358139 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1723.c
++++ b/drivers/staging/comedi/drivers/adv_pci1723.c
+@@ -143,8 +143,8 @@ MODULE_DEVICE_TABLE(pci, pci1723_pci_table);
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pci1723_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pci1723_detach(comedi_device * dev);
++static int pci1723_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pci1723_detach(struct comedi_device * dev);
+ 
+ #define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+ 
+@@ -175,7 +175,7 @@ typedef struct {
+ /*
+  *   the pci1723 card reset;
+  */
+-static int pci1723_reset(comedi_device * dev)
++static int pci1723_reset(struct comedi_device * dev)
+ {
+ 	int i;
+ 	DPRINTK("adv_pci1723 EDBG: BGN: pci1723_reset(...)\n");
+@@ -202,7 +202,7 @@ static int pci1723_reset(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int pci1723_insn_read_ao(comedi_device * dev, comedi_subdevice * s,
++static int pci1723_insn_read_ao(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, chan;
+@@ -218,7 +218,7 @@ static int pci1723_insn_read_ao(comedi_device * dev, comedi_subdevice * s,
+ /*
+   analog data output;
+ */
+-static int pci1723_ao_write_winsn(comedi_device * dev, comedi_subdevice * s,
++static int pci1723_ao_write_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, chan;
+@@ -238,7 +238,7 @@ static int pci1723_ao_write_winsn(comedi_device * dev, comedi_subdevice * s,
+ /*
+   digital i/o config/query
+ */
+-static int pci1723_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int pci1723_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int mask;
+@@ -278,7 +278,7 @@ static int pci1723_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+ /*
+   digital i/o bits read/write
+ */
+-static int pci1723_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int pci1723_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+@@ -294,7 +294,7 @@ static int pci1723_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+  * Attach is called by the Comedi core to configure the driver
+  * for a pci1723 board.
+  */
+-static int pci1723_attach(comedi_device * dev, comedi_devconfig * it)
++static int pci1723_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	int ret, subdev, n_subdevices;
+@@ -439,7 +439,7 @@ static int pci1723_attach(comedi_device * dev, comedi_devconfig * it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int pci1723_detach(comedi_device * dev)
++static int pci1723_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: pci1723: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
+index 25ddbc86fb33..18e778e398bf 100644
+--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
++++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
+@@ -183,8 +183,8 @@ typedef enum {
+ 
+ #define OMBCMD_RETRY	0x03	/* 3 times try request before error */
+ 
+-static int pci_dio_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pci_dio_detach(comedi_device * dev);
++static int pci_dio_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pci_dio_detach(struct comedi_device * dev);
+ 
+ typedef struct {
+ 	int chans;		// num of chans
+@@ -357,7 +357,7 @@ static pci_dio_private *pci_priv = NULL;	/* list of allocated cards */
+ /*
+ ==============================================================================
+ */
+-static int pci_dio_insn_bits_di_b(comedi_device * dev, comedi_subdevice * s,
++static int pci_dio_insn_bits_di_b(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	const diosubd_data *d = (const diosubd_data *)s->private;
+@@ -374,7 +374,7 @@ static int pci_dio_insn_bits_di_b(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pci_dio_insn_bits_di_w(comedi_device * dev, comedi_subdevice * s,
++static int pci_dio_insn_bits_di_w(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	const diosubd_data *d = (const diosubd_data *)s->private;
+@@ -390,7 +390,7 @@ static int pci_dio_insn_bits_di_w(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pci_dio_insn_bits_do_b(comedi_device * dev, comedi_subdevice * s,
++static int pci_dio_insn_bits_do_b(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	const diosubd_data *d = (const diosubd_data *)s->private;
+@@ -411,7 +411,7 @@ static int pci_dio_insn_bits_do_b(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pci_dio_insn_bits_do_w(comedi_device * dev, comedi_subdevice * s,
++static int pci_dio_insn_bits_do_w(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	const diosubd_data *d = (const diosubd_data *)s->private;
+@@ -432,7 +432,7 @@ static int pci_dio_insn_bits_do_w(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pci1760_unchecked_mbxrequest(comedi_device * dev,
++static int pci1760_unchecked_mbxrequest(struct comedi_device * dev,
+ 	unsigned char *omb, unsigned char *imb, int repeats)
+ {
+ 	int cnt, tout, ok = 0;
+@@ -460,7 +460,7 @@ static int pci1760_unchecked_mbxrequest(comedi_device * dev,
+ 	return -ETIME;
+ }
+ 
+-static int pci1760_clear_imb2(comedi_device * dev)
++static int pci1760_clear_imb2(struct comedi_device * dev)
+ {
+ 	unsigned char omb[4] = { 0x0, 0x0, CMD_ClearIMB2, 0x0 };
+ 	unsigned char imb[4];
+@@ -470,7 +470,7 @@ static int pci1760_clear_imb2(comedi_device * dev)
+ 	return pci1760_unchecked_mbxrequest(dev, omb, imb, OMBCMD_RETRY);
+ }
+ 
+-static int pci1760_mbxrequest(comedi_device * dev,
++static int pci1760_mbxrequest(struct comedi_device * dev,
+ 	unsigned char *omb, unsigned char *imb)
+ {
+ 	if (omb[2] == CMD_ClearIMB2) {
+@@ -490,7 +490,7 @@ static int pci1760_mbxrequest(comedi_device * dev,
+ /*
+ ==============================================================================
+ */
+-static int pci1760_insn_bits_di(comedi_device * dev, comedi_subdevice * s,
++static int pci1760_insn_bits_di(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[1] = inb(dev->iobase + IMB3);
+@@ -501,7 +501,7 @@ static int pci1760_insn_bits_di(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pci1760_insn_bits_do(comedi_device * dev, comedi_subdevice * s,
++static int pci1760_insn_bits_do(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int ret;
+@@ -528,7 +528,7 @@ static int pci1760_insn_bits_do(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pci1760_insn_cnt_read(comedi_device * dev, comedi_subdevice * s,
++static int pci1760_insn_cnt_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int ret, n;
+@@ -552,7 +552,7 @@ static int pci1760_insn_cnt_read(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pci1760_insn_cnt_write(comedi_device * dev, comedi_subdevice * s,
++static int pci1760_insn_cnt_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int ret;
+@@ -590,7 +590,7 @@ static int pci1760_insn_cnt_write(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pci1760_reset(comedi_device * dev)
++static int pci1760_reset(struct comedi_device * dev)
+ {
+ 	int i;
+ 	unsigned char omb[4] = { 0x00, 0x00, 0x00, 0x00 };
+@@ -667,7 +667,7 @@ static int pci1760_reset(comedi_device * dev)
+ /*
+ ==============================================================================
+ */
+-static int pci_dio_reset(comedi_device * dev)
++static int pci_dio_reset(struct comedi_device * dev)
+ {
+ 	DPRINTK("adv_pci_dio EDBG: BGN: pci171x_reset(...)\n");
+ 
+@@ -750,7 +750,7 @@ static int pci_dio_reset(comedi_device * dev)
+ /*
+ ==============================================================================
+ */
+-static int pci1760_attach(comedi_device * dev, comedi_devconfig * it)
++static int pci1760_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	int subdev = 0;
+@@ -802,7 +802,7 @@ static int pci1760_attach(comedi_device * dev, comedi_devconfig * it)
+ /*
+ ==============================================================================
+ */
+-static int pci_dio_add_di(comedi_device * dev, comedi_subdevice * s,
++static int pci_dio_add_di(struct comedi_device * dev, comedi_subdevice * s,
+ 	const diosubd_data * d, int subdev)
+ {
+ 	s->type = COMEDI_SUBD_DI;
+@@ -829,7 +829,7 @@ static int pci_dio_add_di(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pci_dio_add_do(comedi_device * dev, comedi_subdevice * s,
++static int pci_dio_add_do(struct comedi_device * dev, comedi_subdevice * s,
+ 	const diosubd_data * d, int subdev)
+ {
+ 	s->type = COMEDI_SUBD_DO;
+@@ -857,7 +857,7 @@ static int pci_dio_add_do(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int CheckAndAllocCard(comedi_device * dev, comedi_devconfig * it,
++static int CheckAndAllocCard(struct comedi_device * dev, comedi_devconfig * it,
+ 	struct pci_dev *pcidev)
+ {
+ 	pci_dio_private *pr, *prev;
+@@ -883,7 +883,7 @@ static int CheckAndAllocCard(comedi_device * dev, comedi_devconfig * it,
+ /*
+ ==============================================================================
+ */
+-static int pci_dio_attach(comedi_device * dev, comedi_devconfig * it)
++static int pci_dio_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	int ret, subdev, n_subdevices, i, j;
+@@ -1011,7 +1011,7 @@ static int pci_dio_attach(comedi_device * dev, comedi_devconfig * it)
+ /*
+ ==============================================================================
+ */
+-static int pci_dio_detach(comedi_device * dev)
++static int pci_dio_detach(struct comedi_device * dev)
+ {
+ 	int i, j;
+ 	comedi_subdevice *s;
+diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c
+index 3a326f6e3205..37d13d68089e 100644
+--- a/drivers/staging/comedi/drivers/aio_aio12_8.c
++++ b/drivers/staging/comedi/drivers/aio_aio12_8.c
+@@ -88,7 +88,7 @@ typedef struct {
+ 
+ #define devpriv	((aio12_8_private *) dev->private)
+ 
+-static int aio_aio12_8_ai_read(comedi_device * dev, comedi_subdevice * s,
++static int aio_aio12_8_ai_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -122,7 +122,7 @@ static int aio_aio12_8_ai_read(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int aio_aio12_8_ao_read(comedi_device * dev, comedi_subdevice * s,
++static int aio_aio12_8_ao_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -133,7 +133,7 @@ static int aio_aio12_8_ao_read(comedi_device * dev, comedi_subdevice * s,
+ 	return insn->n;
+ }
+ 
+-static int aio_aio12_8_ao_write(comedi_device * dev, comedi_subdevice * s,
++static int aio_aio12_8_ao_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -161,7 +161,7 @@ static const comedi_lrange range_aio_aio12_8 = {
+ 		}
+ };
+ 
+-static int aio_aio12_8_attach(comedi_device * dev, comedi_devconfig * it)
++static int aio_aio12_8_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int iobase;
+ 	comedi_subdevice *s;
+@@ -205,7 +205,7 @@ static int aio_aio12_8_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int aio_aio12_8_detach(comedi_device * dev)
++static int aio_aio12_8_detach(struct comedi_device * dev)
+ {
+ 	subdev_8255_cleanup(dev, &dev->subdevices[2]);
+ 	if (dev->iobase)
+diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c
+index 2da86744bc00..88f8e188e0c9 100644
+--- a/drivers/staging/comedi/drivers/aio_iiro_16.c
++++ b/drivers/staging/comedi/drivers/aio_iiro_16.c
+@@ -67,9 +67,9 @@ typedef struct {
+ 
+ #define	devpriv	((aio_iiro_16_private *) dev->private)
+ 
+-static int aio_iiro_16_attach(comedi_device * dev, comedi_devconfig * it);
++static int aio_iiro_16_attach(struct comedi_device * dev, comedi_devconfig * it);
+ 
+-static int aio_iiro_16_detach(comedi_device * dev);
++static int aio_iiro_16_detach(struct comedi_device * dev);
+ 
+ static comedi_driver driver_aio_iiro_16 = {
+       driver_name:"aio_iiro_16",
+@@ -81,13 +81,13 @@ static comedi_driver driver_aio_iiro_16 = {
+       num_names:sizeof(aio_iiro_16_boards) / sizeof(aio_iiro_16_board),
+ };
+ 
+-static int aio_iiro_16_dio_insn_bits_read(comedi_device * dev,
++static int aio_iiro_16_dio_insn_bits_read(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+-static int aio_iiro_16_dio_insn_bits_write(comedi_device * dev,
++static int aio_iiro_16_dio_insn_bits_write(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+-static int aio_iiro_16_attach(comedi_device * dev, comedi_devconfig * it)
++static int aio_iiro_16_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int iobase;
+ 	comedi_subdevice *s;
+@@ -132,7 +132,7 @@ static int aio_iiro_16_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 1;
+ }
+ 
+-static int aio_iiro_16_detach(comedi_device * dev)
++static int aio_iiro_16_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: aio_iiro_16: remove\n", dev->minor);
+ 
+@@ -142,7 +142,7 @@ static int aio_iiro_16_detach(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int aio_iiro_16_dio_insn_bits_write(comedi_device * dev,
++static int aio_iiro_16_dio_insn_bits_write(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -161,7 +161,7 @@ static int aio_iiro_16_dio_insn_bits_write(comedi_device * dev,
+ 	return 2;
+ }
+ 
+-static int aio_iiro_16_dio_insn_bits_read(comedi_device * dev,
++static int aio_iiro_16_dio_insn_bits_read(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
+index 8c8e58f71ec6..642071a92971 100644
+--- a/drivers/staging/comedi/drivers/amplc_dio200.c
++++ b/drivers/staging/comedi/drivers/amplc_dio200.c
+@@ -436,7 +436,7 @@ MODULE_DEVICE_TABLE(pci, dio200_pci_table);
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+-   feel free to suggest moving the variable to the comedi_device struct.  */
++   feel free to suggest moving the variable to the struct comedi_device struct.  */
+ typedef struct {
+ #ifdef CONFIG_COMEDI_PCI
+ 	struct pci_dev *pci_dev;	/* PCI device */
+@@ -473,8 +473,8 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int dio200_attach(comedi_device * dev, comedi_devconfig * it);
+-static int dio200_detach(comedi_device * dev);
++static int dio200_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int dio200_detach(struct comedi_device * dev);
+ static comedi_driver driver_amplc_dio200 = {
+       driver_name:DIO200_DRIVER_NAME,
+       module:THIS_MODULE,
+@@ -497,7 +497,7 @@ COMEDI_INITCLEANUP(driver_amplc_dio200);
+  */
+ #ifdef CONFIG_COMEDI_PCI
+ static int
+-dio200_find_pci(comedi_device * dev, int bus, int slot,
++dio200_find_pci(struct comedi_device * dev, int bus, int slot,
+ 	struct pci_dev **pci_dev_p)
+ {
+ 	struct pci_dev *pci_dev = NULL;
+@@ -572,7 +572,7 @@ dio200_request_region(unsigned minor, unsigned long from, unsigned long extent)
+  * 'insn_bits' function for an 'INTERRUPT' subdevice.
+  */
+ static int
+-dio200_subdev_intr_insn_bits(comedi_device * dev, comedi_subdevice * s,
++dio200_subdev_intr_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	dio200_subdev_intr *subpriv = s->private;
+@@ -591,7 +591,7 @@ dio200_subdev_intr_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ /*
+  * Called to stop acquisition for an 'INTERRUPT' subdevice.
+  */
+-static void dio200_stop_intr(comedi_device * dev, comedi_subdevice * s)
++static void dio200_stop_intr(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	dio200_subdev_intr *subpriv = s->private;
+ 
+@@ -605,7 +605,7 @@ static void dio200_stop_intr(comedi_device * dev, comedi_subdevice * s)
+ /*
+  * Called to start acquisition for an 'INTERRUPT' subdevice.
+  */
+-static int dio200_start_intr(comedi_device * dev, comedi_subdevice * s)
++static int dio200_start_intr(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	unsigned int n;
+ 	unsigned isn_bits;
+@@ -641,7 +641,7 @@ static int dio200_start_intr(comedi_device * dev, comedi_subdevice * s)
+  * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
+  */
+ static int
+-dio200_inttrig_start_intr(comedi_device * dev, comedi_subdevice * s,
++dio200_inttrig_start_intr(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int trignum)
+ {
+ 	dio200_subdev_intr *subpriv;
+@@ -671,7 +671,7 @@ dio200_inttrig_start_intr(comedi_device * dev, comedi_subdevice * s,
+  * This is called from the interrupt service routine to handle a read
+  * scan on an 'INTERRUPT' subdevice.
+  */
+-static int dio200_handle_read_intr(comedi_device * dev, comedi_subdevice * s)
++static int dio200_handle_read_intr(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	dio200_subdev_intr *subpriv = s->private;
+ 	unsigned triggered;
+@@ -783,7 +783,7 @@ static int dio200_handle_read_intr(comedi_device * dev, comedi_subdevice * s)
+ /*
+  * 'cancel' function for an 'INTERRUPT' subdevice.
+  */
+-static int dio200_subdev_intr_cancel(comedi_device * dev, comedi_subdevice * s)
++static int dio200_subdev_intr_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	dio200_subdev_intr *subpriv = s->private;
+ 	unsigned long flags;
+@@ -801,7 +801,7 @@ static int dio200_subdev_intr_cancel(comedi_device * dev, comedi_subdevice * s)
+  * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
+  */
+ static int
+-dio200_subdev_intr_cmdtest(comedi_device * dev, comedi_subdevice * s,
++dio200_subdev_intr_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -907,7 +907,7 @@ dio200_subdev_intr_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ /*
+  * 'do_cmd' function for an 'INTERRUPT' subdevice.
+  */
+-static int dio200_subdev_intr_cmd(comedi_device * dev, comedi_subdevice * s)
++static int dio200_subdev_intr_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	dio200_subdev_intr *subpriv = s->private;
+@@ -953,7 +953,7 @@ static int dio200_subdev_intr_cmd(comedi_device * dev, comedi_subdevice * s)
+  * This function initializes an 'INTERRUPT' subdevice.
+  */
+ static int
+-dio200_subdev_intr_init(comedi_device * dev, comedi_subdevice * s,
++dio200_subdev_intr_init(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned long iobase, unsigned valid_isns, int has_int_sce)
+ {
+ 	dio200_subdev_intr *subpriv;
+@@ -998,7 +998,7 @@ dio200_subdev_intr_init(comedi_device * dev, comedi_subdevice * s,
+  * This function cleans up an 'INTERRUPT' subdevice.
+  */
+ static void
+-dio200_subdev_intr_cleanup(comedi_device * dev, comedi_subdevice * s)
++dio200_subdev_intr_cleanup(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	dio200_subdev_intr *subpriv = s->private;
+ 
+@@ -1012,7 +1012,7 @@ dio200_subdev_intr_cleanup(comedi_device * dev, comedi_subdevice * s)
+  */
+ static irqreturn_t dio200_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	int handled;
+ 
+ 	if (!dev->attached) {
+@@ -1033,7 +1033,7 @@ static irqreturn_t dio200_interrupt(int irq, void *d PT_REGS_ARG)
+  * Handle 'insn_read' for an '8254' counter subdevice.
+  */
+ static int
+-dio200_subdev_8254_read(comedi_device * dev, comedi_subdevice * s,
++dio200_subdev_8254_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	dio200_subdev_8254 *subpriv = s->private;
+@@ -1048,7 +1048,7 @@ dio200_subdev_8254_read(comedi_device * dev, comedi_subdevice * s,
+  * Handle 'insn_write' for an '8254' counter subdevice.
+  */
+ static int
+-dio200_subdev_8254_write(comedi_device * dev, comedi_subdevice * s,
++dio200_subdev_8254_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	dio200_subdev_8254 *subpriv = s->private;
+@@ -1142,7 +1142,7 @@ dio200_get_clock_src(dio200_subdev_8254 * subpriv, unsigned int counter_number,
+  * Handle 'insn_config' for an '8254' counter subdevice.
+  */
+ static int
+-dio200_subdev_8254_config(comedi_device * dev, comedi_subdevice * s,
++dio200_subdev_8254_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	dio200_subdev_8254 *subpriv = s->private;
+@@ -1194,7 +1194,7 @@ dio200_subdev_8254_config(comedi_device * dev, comedi_subdevice * s,
+  * offset is the offset to the 8254 chip.
+  */
+ static int
+-dio200_subdev_8254_init(comedi_device * dev, comedi_subdevice * s,
++dio200_subdev_8254_init(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned long iobase, unsigned offset, int has_clk_gat_sce)
+ {
+ 	dio200_subdev_8254 *subpriv;
+@@ -1247,7 +1247,7 @@ dio200_subdev_8254_init(comedi_device * dev, comedi_subdevice * s,
+  * This function cleans up an '8254' counter subdevice.
+  */
+ static void
+-dio200_subdev_8254_cleanup(comedi_device * dev, comedi_subdevice * s)
++dio200_subdev_8254_cleanup(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	dio200_subdev_intr *subpriv = s->private;
+ 
+@@ -1262,7 +1262,7 @@ dio200_subdev_8254_cleanup(comedi_device * dev, comedi_subdevice * s)
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int dio200_attach(comedi_device * dev, comedi_devconfig * it)
++static int dio200_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	unsigned long iobase = 0;
+@@ -1429,7 +1429,7 @@ static int dio200_attach(comedi_device * dev, comedi_devconfig * it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int dio200_detach(comedi_device * dev)
++static int dio200_detach(struct comedi_device * dev)
+ {
+ 	const dio200_layout *layout;
+ 	unsigned n;
+diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
+index 8d3fb69176ca..adbd79421d4d 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc236.c
++++ b/drivers/staging/comedi/drivers/amplc_pc236.c
+@@ -147,7 +147,7 @@ MODULE_DEVICE_TABLE(pci, pc236_pci_table);
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+-   feel free to suggest moving the variable to the comedi_device struct.  */
++   feel free to suggest moving the variable to the struct comedi_device struct.  */
+ typedef struct {
+ #ifdef CONFIG_COMEDI_PCI
+ 	/* PCI device */
+@@ -165,8 +165,8 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pc236_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pc236_detach(comedi_device * dev);
++static int pc236_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pc236_detach(struct comedi_device * dev);
+ static comedi_driver driver_amplc_pc236 = {
+       driver_name:PC236_DRIVER_NAME,
+       module:THIS_MODULE,
+@@ -185,15 +185,15 @@ COMEDI_INITCLEANUP(driver_amplc_pc236);
+ 
+ static int pc236_request_region(unsigned minor, unsigned long from,
+ 	unsigned long extent);
+-static void pc236_intr_disable(comedi_device * dev);
+-static void pc236_intr_enable(comedi_device * dev);
+-static int pc236_intr_check(comedi_device * dev);
+-static int pc236_intr_insn(comedi_device * dev, comedi_subdevice * s,
++static void pc236_intr_disable(struct comedi_device * dev);
++static void pc236_intr_enable(struct comedi_device * dev);
++static int pc236_intr_check(struct comedi_device * dev);
++static int pc236_intr_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int pc236_intr_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int pc236_intr_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int pc236_intr_cmd(comedi_device * dev, comedi_subdevice * s);
+-static int pc236_intr_cancel(comedi_device * dev, comedi_subdevice * s);
++static int pc236_intr_cmd(struct comedi_device * dev, comedi_subdevice * s);
++static int pc236_intr_cancel(struct comedi_device * dev, comedi_subdevice * s);
+ static irqreturn_t pc236_interrupt(int irq, void *d PT_REGS_ARG);
+ 
+ /*
+@@ -202,7 +202,7 @@ static irqreturn_t pc236_interrupt(int irq, void *d PT_REGS_ARG);
+  */
+ #ifdef CONFIG_COMEDI_PCI
+ static int
+-pc236_find_pci(comedi_device * dev, int bus, int slot,
++pc236_find_pci(struct comedi_device * dev, int bus, int slot,
+ 	struct pci_dev **pci_dev_p)
+ {
+ 	struct pci_dev *pci_dev = NULL;
+@@ -264,7 +264,7 @@ pc236_find_pci(comedi_device * dev, int bus, int slot,
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pc236_attach(comedi_device * dev, comedi_devconfig * it)
++static int pc236_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	unsigned long iobase = 0;
+@@ -405,7 +405,7 @@ static int pc236_attach(comedi_device * dev, comedi_devconfig * it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int pc236_detach(comedi_device * dev)
++static int pc236_detach(struct comedi_device * dev)
+ {
+ 	printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
+ 		PC236_DRIVER_NAME);
+@@ -459,7 +459,7 @@ static int pc236_request_region(unsigned minor, unsigned long from,
+  * configured on subdevice 1) and to physically disable the interrupt
+  * (not possible on the PC36AT, except by removing the IRQ jumper!).
+  */
+-static void pc236_intr_disable(comedi_device * dev)
++static void pc236_intr_disable(struct comedi_device * dev)
+ {
+ 	unsigned long flags;
+ 
+@@ -477,7 +477,7 @@ static void pc236_intr_disable(comedi_device * dev)
+  * configured on subdevice 1) and to physically enable the interrupt
+  * (not possible on the PC36AT, except by (re)connecting the IRQ jumper!).
+  */
+-static void pc236_intr_enable(comedi_device * dev)
++static void pc236_intr_enable(struct comedi_device * dev)
+ {
+ 	unsigned long flags;
+ 
+@@ -497,7 +497,7 @@ static void pc236_intr_enable(comedi_device * dev)
+  * interrupt.
+  * Returns 0 if the interrupt should be ignored.
+  */
+-static int pc236_intr_check(comedi_device * dev)
++static int pc236_intr_check(struct comedi_device * dev)
+ {
+ 	int retval = 0;
+ 	unsigned long flags;
+@@ -528,7 +528,7 @@ static int pc236_intr_check(comedi_device * dev)
+  * Input from subdevice 1.
+  * Copied from the comedi_parport driver.
+  */
+-static int pc236_intr_insn(comedi_device * dev, comedi_subdevice * s,
++static int pc236_intr_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[1] = 0;
+@@ -539,7 +539,7 @@ static int pc236_intr_insn(comedi_device * dev, comedi_subdevice * s,
+  * Subdevice 1 command test.
+  * Copied from the comedi_parport driver.
+  */
+-static int pc236_intr_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int pc236_intr_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -617,7 +617,7 @@ static int pc236_intr_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ /*
+  * Subdevice 1 command.
+  */
+-static int pc236_intr_cmd(comedi_device * dev, comedi_subdevice * s)
++static int pc236_intr_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	pc236_intr_enable(dev);
+ 
+@@ -627,7 +627,7 @@ static int pc236_intr_cmd(comedi_device * dev, comedi_subdevice * s)
+ /*
+  * Subdevice 1 cancel command.
+  */
+-static int pc236_intr_cancel(comedi_device * dev, comedi_subdevice * s)
++static int pc236_intr_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	pc236_intr_disable(dev);
+ 
+@@ -640,7 +640,7 @@ static int pc236_intr_cancel(comedi_device * dev, comedi_subdevice * s)
+  */
+ static irqreturn_t pc236_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s = dev->subdevices + 1;
+ 	int handled;
+ 
+diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
+index 4c23b018ce5e..5f4c7e28102b 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc263.c
++++ b/drivers/staging/comedi/drivers/amplc_pc263.c
+@@ -116,7 +116,7 @@ MODULE_DEVICE_TABLE(pci, pc263_pci_table);
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+-   feel free to suggest moving the variable to the comedi_device struct.  */
++   feel free to suggest moving the variable to the struct comedi_device struct.  */
+ #ifdef CONFIG_COMEDI_PCI
+ typedef struct {
+ 	/* PCI device. */
+@@ -132,8 +132,8 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pc263_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pc263_detach(comedi_device * dev);
++static int pc263_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pc263_detach(struct comedi_device * dev);
+ static comedi_driver driver_amplc_pc263 = {
+       driver_name:PC263_DRIVER_NAME,
+       module:THIS_MODULE,
+@@ -146,9 +146,9 @@ static comedi_driver driver_amplc_pc263 = {
+ 
+ static int pc263_request_region(unsigned minor, unsigned long from,
+ 	unsigned long extent);
+-static int pc263_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int pc263_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int pc263_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int pc263_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ /*
+@@ -157,7 +157,7 @@ static int pc263_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+  */
+ #ifdef CONFIG_COMEDI_PCI
+ static int
+-pc263_find_pci(comedi_device * dev, int bus, int slot,
++pc263_find_pci(struct comedi_device * dev, int bus, int slot,
+ 	struct pci_dev **pci_dev_p)
+ {
+ 	struct pci_dev *pci_dev = NULL;
+@@ -219,7 +219,7 @@ pc263_find_pci(comedi_device * dev, int bus, int slot,
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pc263_attach(comedi_device * dev, comedi_devconfig * it)
++static int pc263_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	unsigned long iobase = 0;
+@@ -337,7 +337,7 @@ static int pc263_attach(comedi_device * dev, comedi_devconfig * it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int pc263_detach(comedi_device * dev)
++static int pc263_detach(struct comedi_device * dev)
+ {
+ 	printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
+ 		PC263_DRIVER_NAME);
+@@ -387,7 +387,7 @@ static int pc263_request_region(unsigned minor, unsigned long from,
+  * useful to applications if you implement the insn_bits interface.
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+-static int pc263_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int pc263_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -412,7 +412,7 @@ static int pc263_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int pc263_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int pc263_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 1)
+diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
+index b936ccf9bb4d..afb110a868e2 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci224.c
++++ b/drivers/staging/comedi/drivers/amplc_pci224.c
+@@ -397,7 +397,7 @@ MODULE_DEVICE_TABLE(pci, pci224_pci_table);
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+-   feel free to suggest moving the variable to the comedi_device struct.  */
++   feel free to suggest moving the variable to the struct comedi_device struct.  */
+ typedef struct {
+ 	struct pci_dev *pci_dev;	/* PCI device */
+ 	const unsigned short *hwrange;
+@@ -426,8 +426,8 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pci224_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pci224_detach(comedi_device * dev);
++static int pci224_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pci224_detach(struct comedi_device * dev);
+ static comedi_driver driver_amplc_pci224 = {
+       driver_name:DRIVER_NAME,
+       module:THIS_MODULE,
+@@ -444,7 +444,7 @@ COMEDI_PCI_INITCLEANUP(driver_amplc_pci224, pci224_pci_table);
+  * Called from the 'insn_write' function to perform a single write.
+  */
+ static void
+-pci224_ao_set_data(comedi_device * dev, int chan, int range, unsigned int data)
++pci224_ao_set_data(struct comedi_device * dev, int chan, int range, unsigned int data)
+ {
+ 	unsigned short mangled;
+ 
+@@ -477,7 +477,7 @@ pci224_ao_set_data(comedi_device * dev, int chan, int range, unsigned int data)
+  * 'insn_write' function for AO subdevice.
+  */
+ static int
+-pci224_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
++pci224_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -504,7 +504,7 @@ pci224_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+  * command.
+  */
+ static int
+-pci224_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
++pci224_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -532,7 +532,7 @@ pci224_cascade_ns_to_timer(int osc_base, unsigned int *d1, unsigned int *d2,
+ /*
+  * Kills a command running on the AO subdevice.
+  */
+-static void pci224_ao_stop(comedi_device * dev, comedi_subdevice * s)
++static void pci224_ao_stop(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+ 
+@@ -572,7 +572,7 @@ static void pci224_ao_stop(comedi_device * dev, comedi_subdevice * s)
+ /*
+  * Handles start of acquisition for the AO subdevice.
+  */
+-static void pci224_ao_start(comedi_device * dev, comedi_subdevice * s)
++static void pci224_ao_start(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned long flags;
+@@ -599,7 +599,7 @@ static void pci224_ao_start(comedi_device * dev, comedi_subdevice * s)
+ /*
+  * Handles interrupts from the DAC FIFO.
+  */
+-static void pci224_ao_handle_fifo(comedi_device * dev, comedi_subdevice * s)
++static void pci224_ao_handle_fifo(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned int num_scans;
+@@ -728,7 +728,7 @@ static void pci224_ao_handle_fifo(comedi_device * dev, comedi_subdevice * s)
+  * Internal trigger function to start acquisition on AO subdevice.
+  */
+ static int
+-pci224_ao_inttrig_start(comedi_device * dev, comedi_subdevice * s,
++pci224_ao_inttrig_start(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int trignum)
+ {
+ 	if (trignum != 0)
+@@ -748,7 +748,7 @@ pci224_ao_inttrig_start(comedi_device * dev, comedi_subdevice * s,
+  * 'do_cmdtest' function for AO subdevice.
+  */
+ static int
+-pci224_ao_cmdtest(comedi_device * dev, comedi_subdevice * s, comedi_cmd * cmd)
++pci224_ao_cmdtest(struct comedi_device * dev, comedi_subdevice * s, comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	unsigned int tmp;
+@@ -1015,7 +1015,7 @@ pci224_ao_cmdtest(comedi_device * dev, comedi_subdevice * s, comedi_cmd * cmd)
+ /*
+  * 'do_cmd' function for AO subdevice.
+  */
+-static int pci224_ao_cmd(comedi_device * dev, comedi_subdevice * s)
++static int pci224_ao_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	int range;
+@@ -1172,7 +1172,7 @@ static int pci224_ao_cmd(comedi_device * dev, comedi_subdevice * s)
+ /*
+  * 'cancel' function for AO subdevice.
+  */
+-static int pci224_ao_cancel(comedi_device * dev, comedi_subdevice * s)
++static int pci224_ao_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	pci224_ao_stop(dev, s);
+ 	return 0;
+@@ -1182,7 +1182,7 @@ static int pci224_ao_cancel(comedi_device * dev, comedi_subdevice * s)
+  * 'munge' data for AO command.
+  */
+ static void
+-pci224_ao_munge(comedi_device * dev, comedi_subdevice * s, void *data,
++pci224_ao_munge(struct comedi_device * dev, comedi_subdevice * s, void *data,
+ 	unsigned int num_bytes, unsigned int chan_index)
+ {
+ 	comedi_async *async = s->async;
+@@ -1214,7 +1214,7 @@ pci224_ao_munge(comedi_device * dev, comedi_subdevice * s, void *data,
+  */
+ static irqreturn_t pci224_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s = &dev->subdevices[0];
+ 	comedi_cmd *cmd;
+ 	unsigned char intstat, valid_intstat;
+@@ -1264,7 +1264,7 @@ static irqreturn_t pci224_interrupt(int irq, void *d PT_REGS_ARG)
+  * bus and slot.
+  */
+ static int
+-pci224_find_pci(comedi_device * dev, int bus, int slot,
++pci224_find_pci(struct comedi_device * dev, int bus, int slot,
+ 	struct pci_dev **pci_dev_p)
+ {
+ 	struct pci_dev *pci_dev = NULL;
+@@ -1323,7 +1323,7 @@ pci224_find_pci(comedi_device * dev, int bus, int slot,
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pci224_attach(comedi_device * dev, comedi_devconfig * it)
++static int pci224_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	struct pci_dev *pci_dev;
+@@ -1503,7 +1503,7 @@ static int pci224_attach(comedi_device * dev, comedi_devconfig * it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int pci224_detach(comedi_device * dev)
++static int pci224_detach(struct comedi_device * dev)
+ {
+ 	printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor, DRIVER_NAME);
+ 
+diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
+index 4463e9803e08..c66a840085f7 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci230.c
++++ b/drivers/staging/comedi/drivers/amplc_pci230.c
+@@ -515,7 +515,7 @@ MODULE_DEVICE_TABLE(pci, pci230_pci_table);
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+-   feel free to suggest moving the variable to the comedi_device struct.  */
++   feel free to suggest moving the variable to the struct comedi_device struct.  */
+ struct pci230_private {
+ 	struct pci_dev *pci_dev;
+ 	spinlock_t isr_spinlock;	/* Interrupt spin lock */
+@@ -601,8 +601,8 @@ static const unsigned char pci230_ao_bipolar[2] = { 0, 1 };
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pci230_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pci230_detach(comedi_device * dev);
++static int pci230_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pci230_detach(struct comedi_device * dev);
+ static comedi_driver driver_amplc_pci230 = {
+       driver_name:"amplc_pci230",
+       module:THIS_MODULE,
+@@ -615,32 +615,32 @@ static comedi_driver driver_amplc_pci230 = {
+ 
+ COMEDI_PCI_INITCLEANUP(driver_amplc_pci230, pci230_pci_table);
+ 
+-static int pci230_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int pci230_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int pci230_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int pci230_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int pci230_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int pci230_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static void pci230_ct_setup_ns_mode(comedi_device * dev, unsigned int ct,
++static void pci230_ct_setup_ns_mode(struct comedi_device * dev, unsigned int ct,
+ 	unsigned int mode, uint64_t ns, unsigned int round);
+ static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round);
+-static void pci230_cancel_ct(comedi_device * dev, unsigned int ct);
++static void pci230_cancel_ct(struct comedi_device * dev, unsigned int ct);
+ static irqreturn_t pci230_interrupt(int irq, void *d PT_REGS_ARG);
+-static int pci230_ao_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int pci230_ao_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int pci230_ao_cmd(comedi_device * dev, comedi_subdevice * s);
+-static int pci230_ao_cancel(comedi_device * dev, comedi_subdevice * s);
+-static void pci230_ao_stop(comedi_device * dev, comedi_subdevice * s);
+-static void pci230_handle_ao_nofifo(comedi_device * dev, comedi_subdevice * s);
+-static int pci230_handle_ao_fifo(comedi_device * dev, comedi_subdevice * s);
+-static int pci230_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int pci230_ao_cmd(struct comedi_device * dev, comedi_subdevice * s);
++static int pci230_ao_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static void pci230_ao_stop(struct comedi_device * dev, comedi_subdevice * s);
++static void pci230_handle_ao_nofifo(struct comedi_device * dev, comedi_subdevice * s);
++static int pci230_handle_ao_fifo(struct comedi_device * dev, comedi_subdevice * s);
++static int pci230_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int pci230_ai_cmd(comedi_device * dev, comedi_subdevice * s);
+-static int pci230_ai_cancel(comedi_device * dev, comedi_subdevice * s);
+-static void pci230_ai_stop(comedi_device * dev, comedi_subdevice * s);
+-static void pci230_handle_ai(comedi_device * dev, comedi_subdevice * s);
++static int pci230_ai_cmd(struct comedi_device * dev, comedi_subdevice * s);
++static int pci230_ai_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static void pci230_ai_stop(struct comedi_device * dev, comedi_subdevice * s);
++static void pci230_handle_ai(struct comedi_device * dev, comedi_subdevice * s);
+ 
+-static short pci230_ai_read(comedi_device * dev)
++static short pci230_ai_read(struct comedi_device * dev)
+ {
+ 	/* Read sample. */
+ 	short data = (short) inw(dev->iobase + PCI230_ADCDATA);
+@@ -658,7 +658,7 @@ static short pci230_ai_read(comedi_device * dev)
+ 	return data;
+ }
+ 
+-static inline unsigned short pci230_ao_mangle_datum(comedi_device * dev,
++static inline unsigned short pci230_ao_mangle_datum(struct comedi_device * dev,
+ 	short datum)
+ {
+ 	/* If a bipolar range was specified, mangle it (straight binary->twos
+@@ -674,7 +674,7 @@ static inline unsigned short pci230_ao_mangle_datum(comedi_device * dev,
+ 	return (unsigned short)datum;
+ }
+ 
+-static inline void pci230_ao_write_nofifo(comedi_device * dev, short datum,
++static inline void pci230_ao_write_nofifo(struct comedi_device * dev, short datum,
+ 	unsigned int chan)
+ {
+ 	/* Store unmangled datum to be read back later. */
+@@ -685,7 +685,7 @@ static inline void pci230_ao_write_nofifo(comedi_device * dev, short datum,
+ 			? PCI230_DACOUT1 : PCI230_DACOUT2));
+ }
+ 
+-static inline void pci230_ao_write_fifo(comedi_device * dev, short datum,
++static inline void pci230_ao_write_fifo(struct comedi_device * dev, short datum,
+ 	unsigned int chan)
+ {
+ 	/* Store unmangled datum to be read back later. */
+@@ -702,7 +702,7 @@ static inline void pci230_ao_write_fifo(comedi_device * dev, short datum,
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pci230_attach(comedi_device * dev, comedi_devconfig * it)
++static int pci230_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	unsigned long iobase1, iobase2;
+@@ -959,7 +959,7 @@ static int pci230_attach(comedi_device * dev, comedi_devconfig * it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int pci230_detach(comedi_device * dev)
++static int pci230_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: amplc_pci230: remove\n", dev->minor);
+ 
+@@ -982,7 +982,7 @@ static int pci230_detach(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int get_resources(comedi_device * dev, unsigned int res_mask,
++static int get_resources(struct comedi_device * dev, unsigned int res_mask,
+ 	unsigned char owner)
+ {
+ 	int ok;
+@@ -1018,13 +1018,13 @@ static int get_resources(comedi_device * dev, unsigned int res_mask,
+ 	return ok;
+ }
+ 
+-static inline int get_one_resource(comedi_device * dev, unsigned int resource,
++static inline int get_one_resource(struct comedi_device * dev, unsigned int resource,
+ 	unsigned char owner)
+ {
+ 	return get_resources(dev, (1U << resource), owner);
+ }
+ 
+-static void put_resources(comedi_device * dev, unsigned int res_mask,
++static void put_resources(struct comedi_device * dev, unsigned int res_mask,
+ 	unsigned char owner)
+ {
+ 	unsigned int i;
+@@ -1044,13 +1044,13 @@ static void put_resources(comedi_device * dev, unsigned int res_mask,
+ 	comedi_spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags);
+ }
+ 
+-static inline void put_one_resource(comedi_device * dev, unsigned int resource,
++static inline void put_one_resource(struct comedi_device * dev, unsigned int resource,
+ 	unsigned char owner)
+ {
+ 	put_resources(dev, (1U << resource), owner);
+ }
+ 
+-static inline void put_all_resources(comedi_device * dev, unsigned char owner)
++static inline void put_all_resources(struct comedi_device * dev, unsigned char owner)
+ {
+ 	put_resources(dev, (1U << NUM_RESOURCES) - 1, owner);
+ }
+@@ -1058,7 +1058,7 @@ static inline void put_all_resources(comedi_device * dev, unsigned char owner)
+ /*
+  *  COMEDI_SUBD_AI instruction;
+  */
+-static int pci230_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int pci230_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int n, i;
+@@ -1163,7 +1163,7 @@ static int pci230_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ /*
+  *  COMEDI_SUBD_AO instructions;
+  */
+-static int pci230_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int pci230_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -1191,7 +1191,7 @@ static int pci230_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ 
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+-static int pci230_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int pci230_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -1203,7 +1203,7 @@ static int pci230_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int pci230_ao_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int pci230_ao_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -1416,7 +1416,7 @@ static int pci230_ao_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int pci230_ao_inttrig_scan_begin(comedi_device * dev,
++static int pci230_ao_inttrig_scan_begin(struct comedi_device * dev,
+ 	comedi_subdevice * s, unsigned int trig_num)
+ {
+ 	unsigned long irqflags;
+@@ -1448,7 +1448,7 @@ static int pci230_ao_inttrig_scan_begin(comedi_device * dev,
+ 	return 1;
+ }
+ 
+-static void pci230_ao_start(comedi_device * dev, comedi_subdevice * s)
++static void pci230_ao_start(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+@@ -1536,7 +1536,7 @@ static void pci230_ao_start(comedi_device * dev, comedi_subdevice * s)
+ 	}
+ }
+ 
+-static int pci230_ao_inttrig_start(comedi_device * dev, comedi_subdevice * s,
++static int pci230_ao_inttrig_start(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int trig_num)
+ {
+ 	if (trig_num != 0)
+@@ -1548,7 +1548,7 @@ static int pci230_ao_inttrig_start(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int pci230_ao_cmd(comedi_device * dev, comedi_subdevice * s)
++static int pci230_ao_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	unsigned short daccon;
+ 	unsigned int range;
+@@ -1648,7 +1648,7 @@ static int pci230_ai_check_scan_period(comedi_cmd * cmd)
+ 	return !err;
+ }
+ 
+-static int pci230_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int pci230_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -2034,7 +2034,7 @@ static int pci230_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static void pci230_ai_update_fifo_trigger_level(comedi_device * dev,
++static void pci230_ai_update_fifo_trigger_level(struct comedi_device * dev,
+ 	comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+@@ -2078,7 +2078,7 @@ static void pci230_ai_update_fifo_trigger_level(comedi_device * dev,
+ 	}
+ }
+ 
+-static int pci230_ai_inttrig_convert(comedi_device * dev, comedi_subdevice * s,
++static int pci230_ai_inttrig_convert(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int trig_num)
+ {
+ 	unsigned long irqflags;
+@@ -2121,7 +2121,7 @@ static int pci230_ai_inttrig_convert(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int pci230_ai_inttrig_scan_begin(comedi_device * dev,
++static int pci230_ai_inttrig_scan_begin(struct comedi_device * dev,
+ 	comedi_subdevice * s, unsigned int trig_num)
+ {
+ 	unsigned long irqflags;
+@@ -2143,7 +2143,7 @@ static int pci230_ai_inttrig_scan_begin(comedi_device * dev,
+ 	return 1;
+ }
+ 
+-static void pci230_ai_start(comedi_device * dev, comedi_subdevice * s)
++static void pci230_ai_start(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	unsigned long irqflags;
+ 	unsigned short conv;
+@@ -2280,7 +2280,7 @@ static void pci230_ai_start(comedi_device * dev, comedi_subdevice * s)
+ 	}
+ }
+ 
+-static int pci230_ai_inttrig_start(comedi_device * dev, comedi_subdevice * s,
++static int pci230_ai_inttrig_start(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int trig_num)
+ {
+ 	if (trig_num != 0)
+@@ -2292,7 +2292,7 @@ static int pci230_ai_inttrig_start(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int pci230_ai_cmd(comedi_device * dev, comedi_subdevice * s)
++static int pci230_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	unsigned int i, chan, range, diff;
+ 	unsigned int res_mask;
+@@ -2532,7 +2532,7 @@ static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round)
+ 	return;
+ }
+ 
+-static void pci230_ct_setup_ns_mode(comedi_device * dev, unsigned int ct,
++static void pci230_ct_setup_ns_mode(struct comedi_device * dev, unsigned int ct,
+ 	unsigned int mode, uint64_t ns, unsigned int round)
+ {
+ 	unsigned int clk_src;
+@@ -2551,7 +2551,7 @@ static void pci230_ct_setup_ns_mode(comedi_device * dev, unsigned int ct,
+ 	i8254_write(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, count);
+ }
+ 
+-static void pci230_cancel_ct(comedi_device * dev, unsigned int ct)
++static void pci230_cancel_ct(struct comedi_device * dev, unsigned int ct)
+ {
+ 	i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct,
+ 		I8254_MODE1);
+@@ -2562,7 +2562,7 @@ static void pci230_cancel_ct(comedi_device * dev, unsigned int ct)
+ static irqreturn_t pci230_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	unsigned char status_int, valid_status_int;
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s;
+ 	unsigned long irqflags;
+ 
+@@ -2622,7 +2622,7 @@ static irqreturn_t pci230_interrupt(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static void pci230_handle_ao_nofifo(comedi_device * dev, comedi_subdevice * s)
++static void pci230_handle_ao_nofifo(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	short data;
+ 	int i, ret;
+@@ -2659,7 +2659,7 @@ static void pci230_handle_ao_nofifo(comedi_device * dev, comedi_subdevice * s)
+ 
+ /* Loads DAC FIFO (if using it) from buffer. */
+ /* Returns 0 if AO finished due to completion or error, 1 if still going. */
+-static int pci230_handle_ao_fifo(comedi_device * dev, comedi_subdevice * s)
++static int pci230_handle_ao_fifo(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+@@ -2762,7 +2762,7 @@ static int pci230_handle_ao_fifo(comedi_device * dev, comedi_subdevice * s)
+ 	return running;
+ }
+ 
+-static void pci230_handle_ai(comedi_device * dev, comedi_subdevice * s)
++static void pci230_handle_ai(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	unsigned int events = 0;
+ 	unsigned int status_fifo;
+@@ -2861,7 +2861,7 @@ static void pci230_handle_ai(comedi_device * dev, comedi_subdevice * s)
+ 	}
+ }
+ 
+-static void pci230_ao_stop(comedi_device * dev, comedi_subdevice * s)
++static void pci230_ao_stop(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	unsigned long irqflags;
+ 	unsigned char intsrc;
+@@ -2916,13 +2916,13 @@ static void pci230_ao_stop(comedi_device * dev, comedi_subdevice * s)
+ 	put_all_resources(dev, OWNER_AOCMD);
+ }
+ 
+-static int pci230_ao_cancel(comedi_device * dev, comedi_subdevice * s)
++static int pci230_ao_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	pci230_ao_stop(dev, s);
+ 	return 0;
+ }
+ 
+-static void pci230_ai_stop(comedi_device * dev, comedi_subdevice * s)
++static void pci230_ai_stop(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	unsigned long irqflags;
+ 	comedi_cmd *cmd;
+@@ -2970,7 +2970,7 @@ static void pci230_ai_stop(comedi_device * dev, comedi_subdevice * s)
+ 	put_all_resources(dev, OWNER_AICMD);
+ }
+ 
+-static int pci230_ai_cancel(comedi_device * dev, comedi_subdevice * s)
++static int pci230_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	pci230_ai_stop(dev, s);
+ 	return 0;
+diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c
+index 5837770ac5b2..bf8562b3023f 100644
+--- a/drivers/staging/comedi/drivers/c6xdigio.c
++++ b/drivers/staging/comedi/drivers/c6xdigio.c
+@@ -97,8 +97,8 @@ union encvaluetype {
+ 
+ #define C6XDIGIO_TIME_OUT 20
+ 
+-static int c6xdigio_attach(comedi_device * dev, comedi_devconfig * it);
+-static int c6xdigio_detach(comedi_device * dev);
++static int c6xdigio_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int c6xdigio_detach(struct comedi_device * dev);
+ comedi_driver driver_c6xdigio = {
+       driver_name:"c6xdigio",
+       module:THIS_MODULE,
+@@ -338,14 +338,14 @@ static void C6X_encResetAll(unsigned long baseAddr)
+ 	}
+ }
+ 
+-static int c6xdigio_pwmo_insn_read(comedi_device * dev,
++static int c6xdigio_pwmo_insn_read(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	printk("c6xdigio_pwmo_insn_read %x\n", insn->n);
+ 	return insn->n;
+ }
+ 
+-static int c6xdigio_pwmo_insn_write(comedi_device * dev,
++static int c6xdigio_pwmo_insn_write(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -359,7 +359,7 @@ static int c6xdigio_pwmo_insn_write(comedi_device * dev,
+ 	return i;
+ }
+ 
+-//static int c6xdigio_ei_init_insn_read(comedi_device *dev,
++//static int c6xdigio_ei_init_insn_read(struct comedi_device *dev,
+ //                                 comedi_subdevice *s,
+ //                                 comedi_insn *insn,
+ //                                 unsigned int *data)
+@@ -368,7 +368,7 @@ static int c6xdigio_pwmo_insn_write(comedi_device * dev,
+ //  return insn->n;
+ //}
+ 
+-//static int c6xdigio_ei_init_insn_write(comedi_device *dev,
++//static int c6xdigio_ei_init_insn_write(struct comedi_device *dev,
+ //                                 comedi_subdevice *s,
+ //                                 comedi_insn *insn,
+ //                                 unsigned int *data)
+@@ -381,7 +381,7 @@ static int c6xdigio_pwmo_insn_write(comedi_device * dev,
+ //  return insn->n;
+ //}
+ 
+-static int c6xdigio_ei_insn_read(comedi_device * dev,
++static int c6xdigio_ei_insn_read(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	//  printk("c6xdigio_ei__insn_read %x\n", insn->n);
+@@ -395,7 +395,7 @@ static int c6xdigio_ei_insn_read(comedi_device * dev,
+ 	return n;
+ }
+ 
+-static void board_init(comedi_device * dev)
++static void board_init(struct comedi_device * dev)
+ {
+ 
+ 	//printk("Inside board_init\n");
+@@ -405,7 +405,7 @@ static void board_init(comedi_device * dev)
+ 
+ }
+ 
+-//static void board_halt(comedi_device *dev) {
++//static void board_halt(struct comedi_device *dev) {
+ //  C6X_pwmInit(dev->iobase);
+ //}
+ 
+@@ -428,7 +428,7 @@ static struct pnp_driver c6xdigio_pnp_driver = {
+ 	.id_table = c6xdigio_pnp_tbl,
+ };
+ 
+-static int c6xdigio_attach(comedi_device * dev, comedi_devconfig * it)
++static int c6xdigio_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int result = 0;
+ 	unsigned long iobase;
+@@ -497,7 +497,7 @@ static int c6xdigio_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int c6xdigio_detach(comedi_device * dev)
++static int c6xdigio_detach(struct comedi_device * dev)
+ {
+ //  board_halt(dev);  // may not need this
+ 
+diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
+index 827954971c1a..b45a1771bd0d 100644
+--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
++++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
+@@ -89,8 +89,8 @@ typedef struct {
+ } das16cs_private;
+ #define devpriv ((das16cs_private *)dev->private)
+ 
+-static int das16cs_attach(comedi_device * dev, comedi_devconfig * it);
+-static int das16cs_detach(comedi_device * dev);
++static int das16cs_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int das16cs_detach(struct comedi_device * dev);
+ static comedi_driver driver_das16cs = {
+       driver_name:"cb_das16_cs",
+       module:THIS_MODULE,
+@@ -109,25 +109,25 @@ static const comedi_lrange das16cs_ai_range = { 4, {
+ };
+ 
+ static irqreturn_t das16cs_interrupt(int irq, void *d PT_REGS_ARG);
+-static int das16cs_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int das16cs_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das16cs_ai_cmd(comedi_device * dev, comedi_subdevice * s);
+-static int das16cs_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int das16cs_ai_cmd(struct comedi_device * dev, comedi_subdevice * s);
++static int das16cs_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int das16cs_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int das16cs_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das16cs_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int das16cs_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das16cs_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int das16cs_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das16cs_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int das16cs_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das16cs_timer_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int das16cs_timer_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das16cs_timer_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int das16cs_timer_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int get_prodid(comedi_device * dev, struct pcmcia_device *link)
++static int get_prodid(struct comedi_device * dev, struct pcmcia_device *link)
+ {
+ 	tuple_t tuple;
+ 	u_short buf[128];
+@@ -146,7 +146,7 @@ static int get_prodid(comedi_device * dev, struct pcmcia_device *link)
+ 	return prodid;
+ }
+ 
+-static const das16cs_board *das16cs_probe(comedi_device * dev,
++static const das16cs_board *das16cs_probe(struct comedi_device * dev,
+ 	struct pcmcia_device *link)
+ {
+ 	int id;
+@@ -165,7 +165,7 @@ static const das16cs_board *das16cs_probe(comedi_device * dev,
+ 	return NULL;
+ }
+ 
+-static int das16cs_attach(comedi_device * dev, comedi_devconfig * it)
++static int das16cs_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	struct pcmcia_device *link;
+ 	comedi_subdevice *s;
+@@ -265,7 +265,7 @@ static int das16cs_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 1;
+ }
+ 
+-static int das16cs_detach(comedi_device * dev)
++static int das16cs_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: das16cs: remove\n", dev->minor);
+ 
+@@ -278,7 +278,7 @@ static int das16cs_detach(comedi_device * dev)
+ 
+ static irqreturn_t das16cs_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+-	//comedi_device *dev = d;
++	//struct comedi_device *dev = d;
+ 	return IRQ_HANDLED;
+ }
+ 
+@@ -286,7 +286,7 @@ static irqreturn_t das16cs_interrupt(int irq, void *d PT_REGS_ARG)
+  * "instructions" read/write data in "one-shot" or "software-triggered"
+  * mode.
+  */
+-static int das16cs_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int das16cs_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -328,12 +328,12 @@ static int das16cs_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int das16cs_ai_cmd(comedi_device * dev, comedi_subdevice * s)
++static int das16cs_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	return -EINVAL;
+ }
+ 
+-static int das16cs_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int das16cs_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -489,7 +489,7 @@ static int das16cs_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int das16cs_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int das16cs_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -535,7 +535,7 @@ static int das16cs_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ 
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+-static int das16cs_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int das16cs_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -552,7 +552,7 @@ static int das16cs_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+  * useful to applications if you implement the insn_bits interface.
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+-static int das16cs_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int das16cs_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -572,7 +572,7 @@ static int das16cs_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int das16cs_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int das16cs_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -610,13 +610,13 @@ static int das16cs_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 	return insn->n;
+ }
+ 
+-static int das16cs_timer_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int das16cs_timer_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	return -EINVAL;
+ }
+ 
+-static int das16cs_timer_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int das16cs_timer_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
+index c98fb6de3d41..7a3564e51244 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas.c
+@@ -398,7 +398,7 @@ MODULE_DEVICE_TABLE(pci, cb_pcidas_pci_table);
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+-   feel free to suggest moving the variable to the comedi_device struct.  */
++   feel free to suggest moving the variable to the struct comedi_device struct.  */
+ typedef struct {
+ 	/* would be useful for a PCI device */
+ 	struct pci_dev *pci_dev;
+@@ -440,8 +440,8 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int cb_pcidas_attach(comedi_device * dev, comedi_devconfig * it);
+-static int cb_pcidas_detach(comedi_device * dev);
++static int cb_pcidas_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int cb_pcidas_detach(struct comedi_device * dev);
+ static comedi_driver driver_cb_pcidas = {
+       driver_name:"cb_pcidas",
+       module:THIS_MODULE,
+@@ -449,56 +449,56 @@ static comedi_driver driver_cb_pcidas = {
+       detach:cb_pcidas_detach,
+ };
+ 
+-static int cb_pcidas_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidas_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ai_config_insn(comedi_device * dev, comedi_subdevice * s,
++static int ai_config_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int cb_pcidas_ao_nofifo_winsn(comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidas_ao_nofifo_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int cb_pcidas_ao_fifo_winsn(comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidas_ao_fifo_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int cb_pcidas_ao_readback_insn(comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidas_ao_readback_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int cb_pcidas_ai_cmd(comedi_device * dev, comedi_subdevice * s);
+-static int cb_pcidas_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidas_ai_cmd(struct comedi_device * dev, comedi_subdevice * s);
++static int cb_pcidas_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int cb_pcidas_ao_cmd(comedi_device * dev, comedi_subdevice * s);
+-static int cb_pcidas_ao_inttrig(comedi_device * dev, comedi_subdevice * subdev,
++static int cb_pcidas_ao_cmd(struct comedi_device * dev, comedi_subdevice * s);
++static int cb_pcidas_ao_inttrig(struct comedi_device * dev, comedi_subdevice * subdev,
+ 	unsigned int trig_num);
+-static int cb_pcidas_ao_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidas_ao_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+ static irqreturn_t cb_pcidas_interrupt(int irq, void *d PT_REGS_ARG);
+-static void handle_ao_interrupt(comedi_device * dev, unsigned int status);
+-static int cb_pcidas_cancel(comedi_device * dev, comedi_subdevice * s);
+-static int cb_pcidas_ao_cancel(comedi_device * dev, comedi_subdevice * s);
+-static void cb_pcidas_load_counters(comedi_device * dev, unsigned int *ns,
++static void handle_ao_interrupt(struct comedi_device * dev, unsigned int status);
++static int cb_pcidas_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static int cb_pcidas_ao_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static void cb_pcidas_load_counters(struct comedi_device * dev, unsigned int *ns,
+ 	int round_flags);
+-static int eeprom_read_insn(comedi_device * dev, comedi_subdevice * s,
++static int eeprom_read_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int caldac_read_insn(comedi_device * dev, comedi_subdevice * s,
++static int caldac_read_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int caldac_write_insn(comedi_device * dev, comedi_subdevice * s,
++static int caldac_write_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int trimpot_read_insn(comedi_device * dev, comedi_subdevice * s,
++static int trimpot_read_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int cb_pcidas_trimpot_write(comedi_device * dev, unsigned int channel,
++static int cb_pcidas_trimpot_write(struct comedi_device * dev, unsigned int channel,
+ 	unsigned int value);
+-static int trimpot_write_insn(comedi_device * dev, comedi_subdevice * s,
++static int trimpot_write_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dac08_read_insn(comedi_device * dev, comedi_subdevice * s,
++static int dac08_read_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dac08_write(comedi_device * dev, unsigned int value);
+-static int dac08_write_insn(comedi_device * dev, comedi_subdevice * s,
++static int dac08_write(struct comedi_device * dev, unsigned int value);
++static int dac08_write_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int caldac_8800_write(comedi_device * dev, unsigned int address,
++static int caldac_8800_write(struct comedi_device * dev, unsigned int address,
+ 	uint8_t value);
+-static int trimpot_7376_write(comedi_device * dev, uint8_t value);
+-static int trimpot_8402_write(comedi_device * dev, unsigned int channel,
++static int trimpot_7376_write(struct comedi_device * dev, uint8_t value);
++static int trimpot_8402_write(struct comedi_device * dev, unsigned int channel,
+ 	uint8_t value);
+-static int nvram_read(comedi_device * dev, unsigned int address,
++static int nvram_read(struct comedi_device * dev, unsigned int address,
+ 	uint8_t * data);
+ 
+-static inline unsigned int cal_enable_bits(comedi_device * dev)
++static inline unsigned int cal_enable_bits(struct comedi_device * dev)
+ {
+ 	return CAL_EN_BIT | CAL_SRC_BITS(devpriv->calibration_source);
+ }
+@@ -507,7 +507,7 @@ static inline unsigned int cal_enable_bits(comedi_device * dev)
+  * Attach is called by the Comedi core to configure the driver
+  * for a particular board.
+  */
+-static int cb_pcidas_attach(comedi_device * dev, comedi_devconfig * it)
++static int cb_pcidas_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	struct pci_dev *pcidev;
+@@ -718,7 +718,7 @@ static int cb_pcidas_attach(comedi_device * dev, comedi_devconfig * it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int cb_pcidas_detach(comedi_device * dev)
++static int cb_pcidas_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: cb_pcidas: remove\n", dev->minor);
+ 
+@@ -752,7 +752,7 @@ static int cb_pcidas_detach(comedi_device * dev)
+  * "instructions" read/write data in "one-shot" or "software-triggered"
+  * mode.
+  */
+-static int cb_pcidas_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidas_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i;
+@@ -804,7 +804,7 @@ static int cb_pcidas_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int ai_config_calibration_source(comedi_device * dev, unsigned int * data)
++static int ai_config_calibration_source(struct comedi_device * dev, unsigned int * data)
+ {
+ 	static const int num_calibration_sources = 8;
+ 	unsigned int source = data[1];
+@@ -819,7 +819,7 @@ static int ai_config_calibration_source(comedi_device * dev, unsigned int * data
+ 	return 2;
+ }
+ 
+-static int ai_config_insn(comedi_device * dev, comedi_subdevice * s,
++static int ai_config_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int id = data[0];
+@@ -836,7 +836,7 @@ static int ai_config_insn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ // analog output insn for pcidas-1000 and 1200 series
+-static int cb_pcidas_ao_nofifo_winsn(comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidas_ao_nofifo_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel;
+@@ -861,7 +861,7 @@ static int cb_pcidas_ao_nofifo_winsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ // analog output insn for pcidas-1602 series
+-static int cb_pcidas_ao_fifo_winsn(comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidas_ao_fifo_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel;
+@@ -892,7 +892,7 @@ static int cb_pcidas_ao_fifo_winsn(comedi_device * dev, comedi_subdevice * s,
+ 
+ // analog output readback insn
+ // XXX loses track of analog output value back after an analog ouput command is executed
+-static int cb_pcidas_ao_readback_insn(comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidas_ao_readback_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)];
+@@ -900,7 +900,7 @@ static int cb_pcidas_ao_readback_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int eeprom_read_insn(comedi_device * dev, comedi_subdevice * s,
++static int eeprom_read_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	uint8_t nvram_data;
+@@ -915,7 +915,7 @@ static int eeprom_read_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int caldac_write_insn(comedi_device * dev, comedi_subdevice * s,
++static int caldac_write_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	const unsigned int channel = CR_CHAN(insn->chanspec);
+@@ -923,7 +923,7 @@ static int caldac_write_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return caldac_8800_write(dev, channel, data[0]);
+ }
+ 
+-static int caldac_read_insn(comedi_device * dev, comedi_subdevice * s,
++static int caldac_read_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->caldac_value[CR_CHAN(insn->chanspec)];
+@@ -932,7 +932,7 @@ static int caldac_read_insn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ /* 1602/16 pregain offset */
+-static int dac08_write(comedi_device * dev, unsigned int value)
++static int dac08_write(struct comedi_device * dev, unsigned int value)
+ {
+ 	if (devpriv->dac08_value == value)
+ 		return 1;
+@@ -952,13 +952,13 @@ static int dac08_write(comedi_device * dev, unsigned int value)
+ 	return 1;
+ }
+ 
+-static int dac08_write_insn(comedi_device * dev, comedi_subdevice * s,
++static int dac08_write_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	return dac08_write(dev, data[0]);
+ }
+ 
+-static int dac08_read_insn(comedi_device * dev, comedi_subdevice * s,
++static int dac08_read_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->dac08_value;
+@@ -966,7 +966,7 @@ static int dac08_read_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int cb_pcidas_trimpot_write(comedi_device * dev,
++static int cb_pcidas_trimpot_write(struct comedi_device * dev,
+ 	unsigned int channel, unsigned int value)
+ {
+ 	if (devpriv->trimpot_value[channel] == value)
+@@ -989,7 +989,7 @@ static int cb_pcidas_trimpot_write(comedi_device * dev,
+ 	return 1;
+ }
+ 
+-static int trimpot_write_insn(comedi_device * dev, comedi_subdevice * s,
++static int trimpot_write_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int channel = CR_CHAN(insn->chanspec);
+@@ -997,7 +997,7 @@ static int trimpot_write_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return cb_pcidas_trimpot_write(dev, channel, data[0]);
+ }
+ 
+-static int trimpot_read_insn(comedi_device * dev, comedi_subdevice * s,
++static int trimpot_read_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int channel = CR_CHAN(insn->chanspec);
+@@ -1007,7 +1007,7 @@ static int trimpot_read_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int cb_pcidas_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidas_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -1162,7 +1162,7 @@ static int cb_pcidas_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int cb_pcidas_ai_cmd(comedi_device * dev, comedi_subdevice * s)
++static int cb_pcidas_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+@@ -1249,7 +1249,7 @@ static int cb_pcidas_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int cb_pcidas_ao_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidas_ao_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -1362,7 +1362,7 @@ static int cb_pcidas_ao_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int cb_pcidas_ao_cmd(comedi_device * dev, comedi_subdevice * s)
++static int cb_pcidas_ao_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+@@ -1425,7 +1425,7 @@ static int cb_pcidas_ao_cmd(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int cb_pcidas_ao_inttrig(comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidas_ao_inttrig(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int trig_num)
+ {
+ 	unsigned int num_bytes, num_points = thisboard->fifo_size;
+@@ -1476,7 +1476,7 @@ static int cb_pcidas_ao_inttrig(comedi_device * dev, comedi_subdevice * s,
+ 
+ static irqreturn_t cb_pcidas_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s = dev->read_subdev;
+ 	comedi_async *async;
+ 	int status, s5933_status;
+@@ -1586,7 +1586,7 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static void handle_ao_interrupt(comedi_device * dev, unsigned int status)
++static void handle_ao_interrupt(struct comedi_device * dev, unsigned int status)
+ {
+ 	comedi_subdevice *s = dev->write_subdev;
+ 	comedi_async *async = s->async;
+@@ -1643,7 +1643,7 @@ static void handle_ao_interrupt(comedi_device * dev, unsigned int status)
+ }
+ 
+ // cancel analog input command
+-static int cb_pcidas_cancel(comedi_device * dev, comedi_subdevice * s)
++static int cb_pcidas_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+ 
+@@ -1662,7 +1662,7 @@ static int cb_pcidas_cancel(comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ // cancel analog output command
+-static int cb_pcidas_ao_cancel(comedi_device * dev, comedi_subdevice * s)
++static int cb_pcidas_ao_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+ 
+@@ -1679,7 +1679,7 @@ static int cb_pcidas_ao_cancel(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static void cb_pcidas_load_counters(comedi_device * dev, unsigned int *ns,
++static void cb_pcidas_load_counters(struct comedi_device * dev, unsigned int *ns,
+ 	int rounding_flags)
+ {
+ 	i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1),
+@@ -1692,7 +1692,7 @@ static void cb_pcidas_load_counters(comedi_device * dev, unsigned int *ns,
+ 		devpriv->divisor2, 2);
+ }
+ 
+-static void write_calibration_bitstream(comedi_device * dev,
++static void write_calibration_bitstream(struct comedi_device * dev,
+ 	unsigned int register_bits, unsigned int bitstream,
+ 	unsigned int bitstream_length)
+ {
+@@ -1709,7 +1709,7 @@ static void write_calibration_bitstream(comedi_device * dev,
+ 	}
+ }
+ 
+-static int caldac_8800_write(comedi_device * dev, unsigned int address,
++static int caldac_8800_write(struct comedi_device * dev, unsigned int address,
+ 	uint8_t value)
+ {
+ 	static const int num_caldac_channels = 8;
+@@ -1739,7 +1739,7 @@ static int caldac_8800_write(comedi_device * dev, unsigned int address,
+ 	return 1;
+ }
+ 
+-static int trimpot_7376_write(comedi_device * dev, uint8_t value)
++static int trimpot_7376_write(struct comedi_device * dev, uint8_t value)
+ {
+ 	static const int bitstream_length = 7;
+ 	unsigned int bitstream = value & 0x7f;
+@@ -1762,7 +1762,7 @@ static int trimpot_7376_write(comedi_device * dev, uint8_t value)
+ /* For 1602/16 only
+  * ch 0 : adc gain
+  * ch 1 : adc postgain offset */
+-static int trimpot_8402_write(comedi_device * dev, unsigned int channel,
++static int trimpot_8402_write(struct comedi_device * dev, unsigned int channel,
+ 	uint8_t value)
+ {
+ 	static const int bitstream_length = 10;
+@@ -1798,7 +1798,7 @@ static int wait_for_nvram_ready(unsigned long s5933_base_addr)
+ 	return -1;
+ }
+ 
+-static int nvram_read(comedi_device * dev, unsigned int address, uint8_t * data)
++static int nvram_read(struct comedi_device * dev, unsigned int address, uint8_t * data)
+ {
+ 	unsigned long iobase = devpriv->s5933_config;
+ 
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
+index 4b1afce04d92..4095381f201e 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
+@@ -1044,12 +1044,12 @@ static DEFINE_PCI_DEVICE_TABLE(pcidas64_pci_table) = {
+ 
+ MODULE_DEVICE_TABLE(pci, pcidas64_pci_table);
+ 
+-static inline pcidas64_board *board(const comedi_device * dev)
++static inline pcidas64_board *board(const struct comedi_device * dev)
+ {
+ 	return (pcidas64_board *) dev->board_ptr;
+ }
+ 
+-static inline unsigned short se_diff_bit_6xxx(comedi_device * dev,
++static inline unsigned short se_diff_bit_6xxx(struct comedi_device * dev,
+ 	int use_differential)
+ {
+ 	if ((board(dev)->layout == LAYOUT_64XX && !use_differential) ||
+@@ -1114,7 +1114,7 @@ typedef struct {
+ /* inline function that makes it easier to
+  * access the private structure.
+  */
+-static inline pcidas64_private *priv(comedi_device * dev)
++static inline pcidas64_private *priv(struct comedi_device * dev)
+ {
+ 	return dev->private;
+ }
+@@ -1125,8 +1125,8 @@ static inline pcidas64_private *priv(comedi_device * dev)
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int attach(comedi_device * dev, comedi_devconfig * it);
+-static int detach(comedi_device * dev);
++static int attach(struct comedi_device * dev, comedi_devconfig * it);
++static int detach(struct comedi_device * dev);
+ static comedi_driver driver_cb_pcidas = {
+       driver_name:"cb_pcidas64",
+       module:THIS_MODULE,
+@@ -1134,73 +1134,73 @@ static comedi_driver driver_cb_pcidas = {
+       detach:detach,
+ };
+ 
+-static int ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ai_config_insn(comedi_device * dev, comedi_subdevice * s,
++static int ai_config_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ao_readback_insn(comedi_device * dev, comedi_subdevice * s,
++static int ao_readback_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ai_cmd(comedi_device * dev, comedi_subdevice * s);
+-static int ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int ai_cmd(struct comedi_device * dev, comedi_subdevice * s);
++static int ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int ao_cmd(comedi_device * dev, comedi_subdevice * s);
+-static int ao_inttrig(comedi_device * dev, comedi_subdevice * subdev,
++static int ao_cmd(struct comedi_device * dev, comedi_subdevice * s);
++static int ao_inttrig(struct comedi_device * dev, comedi_subdevice * subdev,
+ 	unsigned int trig_num);
+-static int ao_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int ao_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+ static irqreturn_t handle_interrupt(int irq, void *d PT_REGS_ARG);
+-static int ai_cancel(comedi_device * dev, comedi_subdevice * s);
+-static int ao_cancel(comedi_device * dev, comedi_subdevice * s);
++static int ai_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static int ao_cancel(struct comedi_device * dev, comedi_subdevice * s);
+ static int dio_callback(int dir, int port, int data, unsigned long arg);
+ static int dio_callback_4020(int dir, int port, int data, unsigned long arg);
+-static int di_rbits(comedi_device * dev, comedi_subdevice * s,
++static int di_rbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int do_wbits(comedi_device * dev, comedi_subdevice * s,
++static int do_wbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dio_60xx_config_insn(comedi_device * dev, comedi_subdevice * s,
++static int dio_60xx_config_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dio_60xx_wbits(comedi_device * dev, comedi_subdevice * s,
++static int dio_60xx_wbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int calib_read_insn(comedi_device * dev, comedi_subdevice * s,
++static int calib_read_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int calib_write_insn(comedi_device * dev, comedi_subdevice * s,
++static int calib_write_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ad8402_read_insn(comedi_device * dev, comedi_subdevice * s,
++static int ad8402_read_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static void ad8402_write(comedi_device * dev, unsigned int channel,
++static void ad8402_write(struct comedi_device * dev, unsigned int channel,
+ 	unsigned int value);
+-static int ad8402_write_insn(comedi_device * dev, comedi_subdevice * s,
++static int ad8402_write_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int eeprom_read_insn(comedi_device * dev, comedi_subdevice * s,
++static int eeprom_read_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static void check_adc_timing(comedi_device * dev, comedi_cmd * cmd);
++static void check_adc_timing(struct comedi_device * dev, comedi_cmd * cmd);
+ static unsigned int get_divisor(unsigned int ns, unsigned int flags);
+-static void i2c_write(comedi_device * dev, unsigned int address,
++static void i2c_write(struct comedi_device * dev, unsigned int address,
+ 	const uint8_t * data, unsigned int length);
+-static void caldac_write(comedi_device * dev, unsigned int channel,
++static void caldac_write(struct comedi_device * dev, unsigned int channel,
+ 	unsigned int value);
+-static int caldac_8800_write(comedi_device * dev, unsigned int address,
++static int caldac_8800_write(struct comedi_device * dev, unsigned int address,
+ 	uint8_t value);
+-//static int dac_1590_write(comedi_device *dev, unsigned int dac_a, unsigned int dac_b);
+-static int caldac_i2c_write(comedi_device * dev, unsigned int caldac_channel,
++//static int dac_1590_write(struct comedi_device *dev, unsigned int dac_a, unsigned int dac_b);
++static int caldac_i2c_write(struct comedi_device * dev, unsigned int caldac_channel,
+ 	unsigned int value);
+-static void abort_dma(comedi_device * dev, unsigned int channel);
+-static void disable_plx_interrupts(comedi_device * dev);
+-static int set_ai_fifo_size(comedi_device * dev, unsigned int num_samples);
+-static unsigned int ai_fifo_size(comedi_device * dev);
+-static int set_ai_fifo_segment_length(comedi_device * dev,
++static void abort_dma(struct comedi_device * dev, unsigned int channel);
++static void disable_plx_interrupts(struct comedi_device * dev);
++static int set_ai_fifo_size(struct comedi_device * dev, unsigned int num_samples);
++static unsigned int ai_fifo_size(struct comedi_device * dev);
++static int set_ai_fifo_segment_length(struct comedi_device * dev,
+ 	unsigned int num_entries);
+-static void disable_ai_pacing(comedi_device * dev);
+-static void disable_ai_interrupts(comedi_device * dev);
+-static void enable_ai_interrupts(comedi_device * dev, const comedi_cmd * cmd);
++static void disable_ai_pacing(struct comedi_device * dev);
++static void disable_ai_interrupts(struct comedi_device * dev);
++static void enable_ai_interrupts(struct comedi_device * dev, const comedi_cmd * cmd);
+ static unsigned int get_ao_divisor(unsigned int ns, unsigned int flags);
+-static void load_ao_dma(comedi_device * dev, const comedi_cmd * cmd);
++static void load_ao_dma(struct comedi_device * dev, const comedi_cmd * cmd);
+ 
+ COMEDI_PCI_INITCLEANUP(driver_cb_pcidas, pcidas64_pci_table);
+ 
+-static unsigned int ai_range_bits_6xxx(const comedi_device * dev,
++static unsigned int ai_range_bits_6xxx(const struct comedi_device * dev,
+ 	unsigned int range_index)
+ {
+ 	const comedi_krange *range =
+@@ -1244,7 +1244,7 @@ static unsigned int ai_range_bits_6xxx(const comedi_device * dev,
+ 	return bits;
+ }
+ 
+-static unsigned int hw_revision(const comedi_device * dev,
++static unsigned int hw_revision(const struct comedi_device * dev,
+ 	uint16_t hw_status_bits)
+ {
+ 	if (board(dev)->layout == LAYOUT_4020)
+@@ -1253,7 +1253,7 @@ static unsigned int hw_revision(const comedi_device * dev,
+ 	return (hw_status_bits >> 12) & 0xf;
+ }
+ 
+-static void set_dac_range_bits(comedi_device * dev, volatile uint16_t * bits,
++static void set_dac_range_bits(struct comedi_device * dev, volatile uint16_t * bits,
+ 	unsigned int channel, unsigned int range)
+ {
+ 	unsigned int code = board(dev)->ao_range_code[range];
+@@ -1273,7 +1273,7 @@ static inline int ao_cmd_is_supported(const pcidas64_board * board)
+ }
+ 
+ // initialize plx9080 chip
+-static void init_plx9080(comedi_device * dev)
++static void init_plx9080(struct comedi_device * dev)
+ {
+ 	uint32_t bits;
+ 	void *plx_iobase = priv(dev)->plx9080_iobase;
+@@ -1363,7 +1363,7 @@ static void init_plx9080(comedi_device * dev)
+ 
+ /* Allocate and initialize the subdevice structures.
+  */
+-static int setup_subdevices(comedi_device * dev)
++static int setup_subdevices(struct comedi_device * dev)
+ {
+ 	comedi_subdevice *s;
+ 	void *dio_8255_iobase;
+@@ -1526,14 +1526,14 @@ static int setup_subdevices(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static void disable_plx_interrupts(comedi_device * dev)
++static void disable_plx_interrupts(struct comedi_device * dev)
+ {
+ 	priv(dev)->plx_intcsr_bits = 0;
+ 	writel(priv(dev)->plx_intcsr_bits,
+ 		priv(dev)->plx9080_iobase + PLX_INTRCS_REG);
+ }
+ 
+-static void init_stc_registers(comedi_device * dev)
++static void init_stc_registers(struct comedi_device * dev)
+ {
+ 	uint16_t bits;
+ 	unsigned long flags;
+@@ -1575,7 +1575,7 @@ static void init_stc_registers(comedi_device * dev)
+ 	disable_ai_pacing(dev);
+ };
+ 
+-int alloc_and_init_dma_members(comedi_device * dev)
++int alloc_and_init_dma_members(struct comedi_device * dev)
+ {
+ 	int i;
+ 
+@@ -1661,7 +1661,7 @@ int alloc_and_init_dma_members(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static inline void warn_external_queue(comedi_device * dev)
++static inline void warn_external_queue(struct comedi_device * dev)
+ {
+ 	comedi_error(dev,
+ 		"AO command and AI external channel queue cannot be used simultaneously.");
+@@ -1673,7 +1673,7 @@ static inline void warn_external_queue(comedi_device * dev)
+  * Attach is called by the Comedi core to configure the driver
+  * for a particular board.
+  */
+-static int attach(comedi_device * dev, comedi_devconfig * it)
++static int attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	struct pci_dev *pcidev;
+ 	int index;
+@@ -1821,7 +1821,7 @@ static int attach(comedi_device * dev, comedi_devconfig * it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int detach(comedi_device * dev)
++static int detach(struct comedi_device * dev)
+ {
+ 	unsigned int i;
+ 
+@@ -1881,7 +1881,7 @@ static int detach(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bits = 0, n, i;
+@@ -2018,7 +2018,7 @@ static int ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int ai_config_calibration_source(comedi_device * dev, unsigned int * data)
++static int ai_config_calibration_source(struct comedi_device * dev, unsigned int * data)
+ {
+ 	unsigned int source = data[1];
+ 	int num_calibration_sources;
+@@ -2038,7 +2038,7 @@ static int ai_config_calibration_source(comedi_device * dev, unsigned int * data
+ 	return 2;
+ }
+ 
+-static int ai_config_block_size(comedi_device * dev, unsigned int * data)
++static int ai_config_block_size(struct comedi_device * dev, unsigned int * data)
+ {
+ 	int fifo_size;
+ 	const hw_fifo_info_t *const fifo = board(dev)->ai_fifo;
+@@ -2065,7 +2065,7 @@ static int ai_config_block_size(comedi_device * dev, unsigned int * data)
+ 	return 2;
+ }
+ 
+-static int ai_config_master_clock_4020(comedi_device * dev, unsigned int * data)
++static int ai_config_master_clock_4020(struct comedi_device * dev, unsigned int * data)
+ {
+ 	unsigned int divisor = data[4];
+ 	int retval = 0;
+@@ -2091,7 +2091,7 @@ static int ai_config_master_clock_4020(comedi_device * dev, unsigned int * data)
+ }
+ 
+ // XXX could add support for 60xx series
+-static int ai_config_master_clock(comedi_device * dev, unsigned int * data)
++static int ai_config_master_clock(struct comedi_device * dev, unsigned int * data)
+ {
+ 
+ 	switch (board(dev)->layout) {
+@@ -2106,7 +2106,7 @@ static int ai_config_master_clock(comedi_device * dev, unsigned int * data)
+ 	return -EINVAL;
+ }
+ 
+-static int ai_config_insn(comedi_device * dev, comedi_subdevice * s,
++static int ai_config_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int id = data[0];
+@@ -2128,7 +2128,7 @@ static int ai_config_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return -EINVAL;
+ }
+ 
+-static int ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -2324,7 +2324,7 @@ static int use_hw_sample_counter(comedi_cmd * cmd)
+ 		return 0;
+ }
+ 
+-static void setup_sample_counters(comedi_device * dev, comedi_cmd * cmd)
++static void setup_sample_counters(struct comedi_device * dev, comedi_cmd * cmd)
+ {
+ 	if (cmd->stop_src == TRIG_COUNT) {
+ 		// set software count
+@@ -2341,7 +2341,7 @@ static void setup_sample_counters(comedi_device * dev, comedi_cmd * cmd)
+ 	}
+ }
+ 
+-static inline unsigned int dma_transfer_size(comedi_device * dev)
++static inline unsigned int dma_transfer_size(struct comedi_device * dev)
+ {
+ 	unsigned int num_samples;
+ 
+@@ -2354,7 +2354,7 @@ static inline unsigned int dma_transfer_size(comedi_device * dev)
+ 	return num_samples;
+ }
+ 
+-static void disable_ai_pacing(comedi_device * dev)
++static void disable_ai_pacing(struct comedi_device * dev)
+ {
+ 	unsigned long flags;
+ 
+@@ -2371,7 +2371,7 @@ static void disable_ai_pacing(comedi_device * dev)
+ 		priv(dev)->main_iobase + ADC_CONTROL0_REG);
+ }
+ 
+-static void disable_ai_interrupts(comedi_device * dev)
++static void disable_ai_interrupts(struct comedi_device * dev)
+ {
+ 	unsigned long flags;
+ 
+@@ -2387,7 +2387,7 @@ static void disable_ai_interrupts(comedi_device * dev)
+ 	DEBUG_PRINT("intr enable bits 0x%x\n", priv(dev)->intr_enable_bits);
+ }
+ 
+-static void enable_ai_interrupts(comedi_device * dev, const comedi_cmd * cmd)
++static void enable_ai_interrupts(struct comedi_device * dev, const comedi_cmd * cmd)
+ {
+ 	uint32_t bits;
+ 	unsigned long flags;
+@@ -2408,14 +2408,14 @@ static void enable_ai_interrupts(comedi_device * dev, const comedi_cmd * cmd)
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ }
+ 
+-static uint32_t ai_convert_counter_6xxx(const comedi_device * dev,
++static uint32_t ai_convert_counter_6xxx(const struct comedi_device * dev,
+ 	const comedi_cmd * cmd)
+ {
+ 	// supposed to load counter with desired divisor minus 3
+ 	return cmd->convert_arg / TIMER_BASE - 3;
+ }
+ 
+-static uint32_t ai_scan_counter_6xxx(comedi_device * dev, comedi_cmd * cmd)
++static uint32_t ai_scan_counter_6xxx(struct comedi_device * dev, comedi_cmd * cmd)
+ {
+ 	uint32_t count;
+ 	// figure out how long we need to delay at end of scan
+@@ -2435,7 +2435,7 @@ static uint32_t ai_scan_counter_6xxx(comedi_device * dev, comedi_cmd * cmd)
+ 	return count - 3;
+ }
+ 
+-static uint32_t ai_convert_counter_4020(comedi_device * dev, comedi_cmd * cmd)
++static uint32_t ai_convert_counter_4020(struct comedi_device * dev, comedi_cmd * cmd)
+ {
+ 	unsigned int divisor;
+ 
+@@ -2456,7 +2456,7 @@ static uint32_t ai_convert_counter_4020(comedi_device * dev, comedi_cmd * cmd)
+ 	return divisor - 2;
+ }
+ 
+-static void select_master_clock_4020(comedi_device * dev,
++static void select_master_clock_4020(struct comedi_device * dev,
+ 	const comedi_cmd * cmd)
+ {
+ 	// select internal/external master clock
+@@ -2475,7 +2475,7 @@ static void select_master_clock_4020(comedi_device * dev,
+ 		priv(dev)->main_iobase + HW_CONFIG_REG);
+ }
+ 
+-static void select_master_clock(comedi_device * dev, const comedi_cmd * cmd)
++static void select_master_clock(struct comedi_device * dev, const comedi_cmd * cmd)
+ {
+ 	switch (board(dev)->layout) {
+ 	case LAYOUT_4020:
+@@ -2486,7 +2486,7 @@ static void select_master_clock(comedi_device * dev, const comedi_cmd * cmd)
+ 	}
+ }
+ 
+-static inline void dma_start_sync(comedi_device * dev, unsigned int channel)
++static inline void dma_start_sync(struct comedi_device * dev, unsigned int channel)
+ {
+ 	unsigned long flags;
+ 
+@@ -2503,7 +2503,7 @@ static inline void dma_start_sync(comedi_device * dev, unsigned int channel)
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ }
+ 
+-static void set_ai_pacing(comedi_device * dev, comedi_cmd * cmd)
++static void set_ai_pacing(struct comedi_device * dev, comedi_cmd * cmd)
+ {
+ 	uint32_t convert_counter = 0, scan_counter = 0;
+ 
+@@ -2550,7 +2550,7 @@ static int use_internal_queue_6xxx(const comedi_cmd * cmd)
+ 	return 1;
+ }
+ 
+-static int setup_channel_queue(comedi_device * dev, const comedi_cmd * cmd)
++static int setup_channel_queue(struct comedi_device * dev, const comedi_cmd * cmd)
+ {
+ 	unsigned short bits;
+ 	int i;
+@@ -2652,7 +2652,7 @@ static int setup_channel_queue(comedi_device * dev, const comedi_cmd * cmd)
+ 	return 0;
+ }
+ 
+-static inline void load_first_dma_descriptor(comedi_device * dev,
++static inline void load_first_dma_descriptor(struct comedi_device * dev,
+ 	unsigned int dma_channel, unsigned int descriptor_bits)
+ {
+ 	/* The transfer size, pci address, and local address registers
+@@ -2679,7 +2679,7 @@ static inline void load_first_dma_descriptor(comedi_device * dev,
+ 	}
+ }
+ 
+-static int ai_cmd(comedi_device * dev, comedi_subdevice * s)
++static int ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+@@ -2797,7 +2797,7 @@ static int ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ // read num_samples from 16 bit wide ai fifo
+-static void pio_drain_ai_fifo_16(comedi_device * dev)
++static void pio_drain_ai_fifo_16(struct comedi_device * dev)
+ {
+ 	comedi_subdevice *s = dev->read_subdev;
+ 	comedi_async *async = s->async;
+@@ -2864,7 +2864,7 @@ static void pio_drain_ai_fifo_16(comedi_device * dev)
+  * dma transfers (it only supports the use of pio for draining the last remaining
+  * points from the fifo when a data aquisition operation has completed).
+  */
+-static void pio_drain_ai_fifo_32(comedi_device * dev)
++static void pio_drain_ai_fifo_32(struct comedi_device * dev)
+ {
+ 	comedi_subdevice *s = dev->read_subdev;
+ 	comedi_async *async = s->async;
+@@ -2898,7 +2898,7 @@ static void pio_drain_ai_fifo_32(comedi_device * dev)
+ }
+ 
+ // empty fifo
+-static void pio_drain_ai_fifo(comedi_device * dev)
++static void pio_drain_ai_fifo(struct comedi_device * dev)
+ {
+ 	if (board(dev)->layout == LAYOUT_4020) {
+ 		pio_drain_ai_fifo_32(dev);
+@@ -2906,7 +2906,7 @@ static void pio_drain_ai_fifo(comedi_device * dev)
+ 		pio_drain_ai_fifo_16(dev);
+ }
+ 
+-static void drain_dma_buffers(comedi_device * dev, unsigned int channel)
++static void drain_dma_buffers(struct comedi_device * dev, unsigned int channel)
+ {
+ 	comedi_async *async = dev->read_subdev->async;
+ 	uint32_t next_transfer_addr;
+@@ -2952,7 +2952,7 @@ static void drain_dma_buffers(comedi_device * dev, unsigned int channel)
+ 	 * unused buffer) */
+ }
+ 
+-void handle_ai_interrupt(comedi_device * dev, unsigned short status,
++void handle_ai_interrupt(struct comedi_device * dev, unsigned short status,
+ 	unsigned int plx_status)
+ {
+ 	comedi_subdevice *s = dev->read_subdev;
+@@ -3006,7 +3006,7 @@ void handle_ai_interrupt(comedi_device * dev, unsigned short status,
+ 	cfc_handle_events(dev, s);
+ }
+ 
+-static inline unsigned int prev_ao_dma_index(comedi_device * dev)
++static inline unsigned int prev_ao_dma_index(struct comedi_device * dev)
+ {
+ 	unsigned int buffer_index;
+ 
+@@ -3017,7 +3017,7 @@ static inline unsigned int prev_ao_dma_index(comedi_device * dev)
+ 	return buffer_index;
+ }
+ 
+-static int last_ao_dma_load_completed(comedi_device * dev)
++static int last_ao_dma_load_completed(struct comedi_device * dev)
+ {
+ 	unsigned int buffer_index;
+ 	unsigned int transfer_address;
+@@ -3036,7 +3036,7 @@ static int last_ao_dma_load_completed(comedi_device * dev)
+ 	return 1;
+ }
+ 
+-static int ao_stopped_by_error(comedi_device * dev, const comedi_cmd * cmd)
++static int ao_stopped_by_error(struct comedi_device * dev, const comedi_cmd * cmd)
+ {
+ 	if (cmd->stop_src == TRIG_NONE)
+ 		return 1;
+@@ -3049,7 +3049,7 @@ static int ao_stopped_by_error(comedi_device * dev, const comedi_cmd * cmd)
+ 	return 0;
+ }
+ 
+-static inline int ao_dma_needs_restart(comedi_device * dev,
++static inline int ao_dma_needs_restart(struct comedi_device * dev,
+ 	unsigned short dma_status)
+ {
+ 	if ((dma_status & PLX_DMA_DONE_BIT) == 0 ||
+@@ -3061,7 +3061,7 @@ static inline int ao_dma_needs_restart(comedi_device * dev,
+ 	return 1;
+ }
+ 
+-static void restart_ao_dma(comedi_device * dev)
++static void restart_ao_dma(struct comedi_device * dev)
+ {
+ 	unsigned int dma_desc_bits;
+ 
+@@ -3074,7 +3074,7 @@ static void restart_ao_dma(comedi_device * dev)
+ 	dma_start_sync(dev, 0);
+ }
+ 
+-static void handle_ao_interrupt(comedi_device * dev, unsigned short status,
++static void handle_ao_interrupt(struct comedi_device * dev, unsigned short status,
+ 	unsigned int plx_status)
+ {
+ 	comedi_subdevice *s = dev->write_subdev;
+@@ -3128,7 +3128,7 @@ static void handle_ao_interrupt(comedi_device * dev, unsigned short status,
+ 
+ static irqreturn_t handle_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	unsigned short status;
+ 	uint32_t plx_status;
+ 	uint32_t plx_bits;
+@@ -3162,7 +3162,7 @@ static irqreturn_t handle_interrupt(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-void abort_dma(comedi_device * dev, unsigned int channel)
++void abort_dma(struct comedi_device * dev, unsigned int channel)
+ {
+ 	unsigned long flags;
+ 
+@@ -3174,7 +3174,7 @@ void abort_dma(comedi_device * dev, unsigned int channel)
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ }
+ 
+-static int ai_cancel(comedi_device * dev, comedi_subdevice * s)
++static int ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+ 
+@@ -3194,7 +3194,7 @@ static int ai_cancel(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -3224,7 +3224,7 @@ static int ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int ao_readback_insn(comedi_device * dev, comedi_subdevice * s,
++static int ao_readback_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = priv(dev)->ao_value[CR_CHAN(insn->chanspec)];
+@@ -3232,7 +3232,7 @@ static int ao_readback_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static void set_dac_control0_reg(comedi_device * dev, const comedi_cmd * cmd)
++static void set_dac_control0_reg(struct comedi_device * dev, const comedi_cmd * cmd)
+ {
+ 	unsigned int bits = DAC_ENABLE_BIT | WAVEFORM_GATE_LEVEL_BIT |
+ 		WAVEFORM_GATE_ENABLE_BIT | WAVEFORM_GATE_SELECT_BIT;
+@@ -3252,7 +3252,7 @@ static void set_dac_control0_reg(comedi_device * dev, const comedi_cmd * cmd)
+ 	writew(bits, priv(dev)->main_iobase + DAC_CONTROL0_REG);
+ }
+ 
+-static void set_dac_control1_reg(comedi_device * dev, const comedi_cmd * cmd)
++static void set_dac_control1_reg(struct comedi_device * dev, const comedi_cmd * cmd)
+ {
+ 	int i;
+ 
+@@ -3269,7 +3269,7 @@ static void set_dac_control1_reg(comedi_device * dev, const comedi_cmd * cmd)
+ 		priv(dev)->main_iobase + DAC_CONTROL1_REG);
+ }
+ 
+-static void set_dac_select_reg(comedi_device * dev, const comedi_cmd * cmd)
++static void set_dac_select_reg(struct comedi_device * dev, const comedi_cmd * cmd)
+ {
+ 	uint16_t bits;
+ 	unsigned int first_channel, last_channel;
+@@ -3284,7 +3284,7 @@ static void set_dac_select_reg(comedi_device * dev, const comedi_cmd * cmd)
+ 	writew(bits, priv(dev)->main_iobase + DAC_SELECT_REG);
+ }
+ 
+-static void set_dac_interval_regs(comedi_device * dev, const comedi_cmd * cmd)
++static void set_dac_interval_regs(struct comedi_device * dev, const comedi_cmd * cmd)
+ {
+ 	unsigned int divisor;
+ 
+@@ -3302,7 +3302,7 @@ static void set_dac_interval_regs(comedi_device * dev, const comedi_cmd * cmd)
+ 		priv(dev)->main_iobase + DAC_SAMPLE_INTERVAL_UPPER_REG);
+ }
+ 
+-static unsigned int load_ao_dma_buffer(comedi_device * dev,
++static unsigned int load_ao_dma_buffer(struct comedi_device * dev,
+ 	const comedi_cmd * cmd)
+ {
+ 	unsigned int num_bytes, buffer_index, prev_buffer_index;
+@@ -3346,7 +3346,7 @@ static unsigned int load_ao_dma_buffer(comedi_device * dev,
+ 	return num_bytes;
+ }
+ 
+-static void load_ao_dma(comedi_device * dev, const comedi_cmd * cmd)
++static void load_ao_dma(struct comedi_device * dev, const comedi_cmd * cmd)
+ {
+ 	unsigned int num_bytes;
+ 	unsigned int next_transfer_addr;
+@@ -3368,7 +3368,7 @@ static void load_ao_dma(comedi_device * dev, const comedi_cmd * cmd)
+ 	} while (num_bytes >= DMA_BUFFER_SIZE);
+ }
+ 
+-static int prep_ao_dma(comedi_device * dev, const comedi_cmd * cmd)
++static int prep_ao_dma(struct comedi_device * dev, const comedi_cmd * cmd)
+ {
+ 	unsigned int num_bytes;
+ 	int i;
+@@ -3402,7 +3402,7 @@ static int prep_ao_dma(comedi_device * dev, const comedi_cmd * cmd)
+ 	return 0;
+ }
+ 
+-static inline int external_ai_queue_in_use(comedi_device * dev)
++static inline int external_ai_queue_in_use(struct comedi_device * dev)
+ {
+ 	if (dev->read_subdev->busy)
+ 		return 0;
+@@ -3413,7 +3413,7 @@ static inline int external_ai_queue_in_use(comedi_device * dev)
+ 	return 1;
+ }
+ 
+-static int ao_cmd(comedi_device * dev, comedi_subdevice * s)
++static int ao_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 
+@@ -3438,7 +3438,7 @@ static int ao_cmd(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ao_inttrig(comedi_device * dev, comedi_subdevice * s,
++static int ao_inttrig(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int trig_num)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+@@ -3461,7 +3461,7 @@ static int ao_inttrig(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int ao_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int ao_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -3577,7 +3577,7 @@ static int ao_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int ao_cancel(comedi_device * dev, comedi_subdevice * s)
++static int ao_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	writew(0x0, priv(dev)->main_iobase + DAC_CONTROL0_REG);
+ 	abort_dma(dev, 0);
+@@ -3605,7 +3605,7 @@ static int dio_callback_4020(int dir, int port, int data, unsigned long iobase)
+ 	}
+ }
+ 
+-static int di_rbits(comedi_device * dev, comedi_subdevice * s,
++static int di_rbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bits;
+@@ -3618,7 +3618,7 @@ static int di_rbits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int do_wbits(comedi_device * dev, comedi_subdevice * s,
++static int do_wbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] &= 0xf;
+@@ -3634,7 +3634,7 @@ static int do_wbits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int dio_60xx_config_insn(comedi_device * dev, comedi_subdevice * s,
++static int dio_60xx_config_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int mask;
+@@ -3661,7 +3661,7 @@ static int dio_60xx_config_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int dio_60xx_wbits(comedi_device * dev, comedi_subdevice * s,
++static int dio_60xx_wbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+@@ -3676,7 +3676,7 @@ static int dio_60xx_wbits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static void caldac_write(comedi_device * dev, unsigned int channel,
++static void caldac_write(struct comedi_device * dev, unsigned int channel,
+ 	unsigned int value)
+ {
+ 	priv(dev)->caldac_state[channel] = value;
+@@ -3694,7 +3694,7 @@ static void caldac_write(comedi_device * dev, unsigned int channel,
+ 	}
+ }
+ 
+-static int calib_write_insn(comedi_device * dev, comedi_subdevice * s,
++static int calib_write_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel = CR_CHAN(insn->chanspec);
+@@ -3709,7 +3709,7 @@ static int calib_write_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int calib_read_insn(comedi_device * dev, comedi_subdevice * s,
++static int calib_read_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int channel = CR_CHAN(insn->chanspec);
+@@ -3719,7 +3719,7 @@ static int calib_read_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static void ad8402_write(comedi_device * dev, unsigned int channel,
++static void ad8402_write(struct comedi_device * dev, unsigned int channel,
+ 	unsigned int value)
+ {
+ 	static const int bitstream_length = 10;
+@@ -3750,7 +3750,7 @@ static void ad8402_write(comedi_device * dev, unsigned int channel,
+ }
+ 
+ /* for pci-das6402/16, channel 0 is analog input gain and channel 1 is offset */
+-static int ad8402_write_insn(comedi_device * dev, comedi_subdevice * s,
++static int ad8402_write_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel = CR_CHAN(insn->chanspec);
+@@ -3767,7 +3767,7 @@ static int ad8402_write_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int ad8402_read_insn(comedi_device * dev, comedi_subdevice * s,
++static int ad8402_read_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int channel = CR_CHAN(insn->chanspec);
+@@ -3777,7 +3777,7 @@ static int ad8402_read_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static uint16_t read_eeprom(comedi_device * dev, uint8_t address)
++static uint16_t read_eeprom(struct comedi_device * dev, uint8_t address)
+ {
+ 	static const int bitstream_length = 11;
+ 	static const int read_command = 0x6;
+@@ -3839,7 +3839,7 @@ static uint16_t read_eeprom(comedi_device * dev, uint8_t address)
+ 	return value;
+ }
+ 
+-static int eeprom_read_insn(comedi_device * dev, comedi_subdevice * s,
++static int eeprom_read_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = read_eeprom(dev, CR_CHAN(insn->chanspec));
+@@ -3851,7 +3851,7 @@ static int eeprom_read_insn(comedi_device * dev, comedi_subdevice * s,
+  * sets cmd members appropriately.
+  * adc paces conversions from master clock by dividing by (x + 3) where x is 24 bit number
+  */
+-static void check_adc_timing(comedi_device * dev, comedi_cmd * cmd)
++static void check_adc_timing(struct comedi_device * dev, comedi_cmd * cmd)
+ {
+ 	unsigned int convert_divisor = 0, scan_divisor;
+ 	static const int min_convert_divisor = 3;
+@@ -3925,7 +3925,7 @@ static unsigned int get_ao_divisor(unsigned int ns, unsigned int flags)
+ }
+ 
+ // adjusts the size of hardware fifo (which determines block size for dma xfers)
+-static int set_ai_fifo_size(comedi_device * dev, unsigned int num_samples)
++static int set_ai_fifo_size(struct comedi_device * dev, unsigned int num_samples)
+ {
+ 	unsigned int num_fifo_entries;
+ 	int retval;
+@@ -3946,14 +3946,14 @@ static int set_ai_fifo_size(comedi_device * dev, unsigned int num_samples)
+ }
+ 
+ // query length of fifo
+-static unsigned int ai_fifo_size(comedi_device * dev)
++static unsigned int ai_fifo_size(struct comedi_device * dev)
+ {
+ 	return priv(dev)->ai_fifo_segment_length *
+ 		board(dev)->ai_fifo->num_segments *
+ 		board(dev)->ai_fifo->sample_packing_ratio;
+ }
+ 
+-static int set_ai_fifo_segment_length(comedi_device * dev,
++static int set_ai_fifo_segment_length(struct comedi_device * dev,
+ 	unsigned int num_entries)
+ {
+ 	static const int increment_size = 0x100;
+@@ -4004,7 +4004,7 @@ static int set_ai_fifo_segment_length(comedi_device * dev,
+  * address 7 == dac channel 1 fine offset
+ */
+ 
+-static int caldac_8800_write(comedi_device * dev, unsigned int address,
++static int caldac_8800_write(struct comedi_device * dev, unsigned int address,
+ 	uint8_t value)
+ {
+ 	static const int num_caldac_channels = 8;
+@@ -4036,7 +4036,7 @@ static int caldac_8800_write(comedi_device * dev, unsigned int address,
+ }
+ 
+ // 4020 caldacs
+-static int caldac_i2c_write(comedi_device * dev, unsigned int caldac_channel,
++static int caldac_i2c_write(struct comedi_device * dev, unsigned int caldac_channel,
+ 	unsigned int value)
+ {
+ 	uint8_t serial_bytes[3];
+@@ -4101,7 +4101,7 @@ static const int i2c_high_comedi_udelay = 1000;
+ static const int i2c_low_comedi_udelay = 10;
+ 
+ // set i2c data line high or low
+-static void i2c_set_sda(comedi_device * dev, int state)
++static void i2c_set_sda(struct comedi_device * dev, int state)
+ {
+ 	static const int data_bit = CTL_EE_W;
+ 	void *plx_control_addr = priv(dev)->plx9080_iobase + PLX_CONTROL_REG;
+@@ -4120,7 +4120,7 @@ static void i2c_set_sda(comedi_device * dev, int state)
+ }
+ 
+ // set i2c clock line high or low
+-static void i2c_set_scl(comedi_device * dev, int state)
++static void i2c_set_scl(struct comedi_device * dev, int state)
+ {
+ 	static const int clock_bit = CTL_USERO;
+ 	void *plx_control_addr = priv(dev)->plx9080_iobase + PLX_CONTROL_REG;
+@@ -4138,7 +4138,7 @@ static void i2c_set_scl(comedi_device * dev, int state)
+ 	}
+ }
+ 
+-static void i2c_write_byte(comedi_device * dev, uint8_t byte)
++static void i2c_write_byte(struct comedi_device * dev, uint8_t byte)
+ {
+ 	uint8_t bit;
+ 	unsigned int num_bits = 8;
+@@ -4156,7 +4156,7 @@ static void i2c_write_byte(comedi_device * dev, uint8_t byte)
+ }
+ 
+ // we can't really read the lines, so fake it
+-static int i2c_read_ack(comedi_device * dev)
++static int i2c_read_ack(struct comedi_device * dev)
+ {
+ 	i2c_set_scl(dev, 0);
+ 	i2c_set_sda(dev, 1);
+@@ -4166,7 +4166,7 @@ static int i2c_read_ack(comedi_device * dev)
+ }
+ 
+ // send start bit
+-static void i2c_start(comedi_device * dev)
++static void i2c_start(struct comedi_device * dev)
+ {
+ 	i2c_set_scl(dev, 1);
+ 	i2c_set_sda(dev, 1);
+@@ -4174,7 +4174,7 @@ static void i2c_start(comedi_device * dev)
+ }
+ 
+ // send stop bit
+-static void i2c_stop(comedi_device * dev)
++static void i2c_stop(struct comedi_device * dev)
+ {
+ 	i2c_set_scl(dev, 0);
+ 	i2c_set_sda(dev, 0);
+@@ -4182,7 +4182,7 @@ static void i2c_stop(comedi_device * dev)
+ 	i2c_set_sda(dev, 1);
+ }
+ 
+-static void i2c_write(comedi_device * dev, unsigned int address,
++static void i2c_write(struct comedi_device * dev, unsigned int address,
+ 	const uint8_t * data, unsigned int length)
+ {
+ 	unsigned int i;
+diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
+index f245eb1c1631..d433780d5b50 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidda.c
++++ b/drivers/staging/comedi/drivers/cb_pcidda.c
+@@ -210,7 +210,7 @@ MODULE_DEVICE_TABLE(pci, cb_pcidda_pci_table);
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+-   feel free to suggest moving the variable to the comedi_device struct.  */
++   feel free to suggest moving the variable to the struct comedi_device struct.  */
+ typedef struct {
+ 	int data;
+ 
+@@ -232,20 +232,20 @@ typedef struct {
+  */
+ #define devpriv ((cb_pcidda_private *)dev->private)
+ 
+-static int cb_pcidda_attach(comedi_device * dev, comedi_devconfig * it);
+-static int cb_pcidda_detach(comedi_device * dev);
+-//static int cb_pcidda_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data);
+-static int cb_pcidda_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidda_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int cb_pcidda_detach(struct comedi_device * dev);
++//static int cb_pcidda_ai_rinsn(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data);
++static int cb_pcidda_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-//static int cb_pcidda_ai_cmd(comedi_device *dev,comedi_subdevice *s);
+-//static int cb_pcidda_ai_cmdtest(comedi_device *dev,comedi_subdevice *s, comedi_cmd *cmd);
++//static int cb_pcidda_ai_cmd(struct comedi_device *dev,comedi_subdevice *s);
++//static int cb_pcidda_ai_cmdtest(struct comedi_device *dev,comedi_subdevice *s, comedi_cmd *cmd);
+ //static int cb_pcidda_ns_to_timer(unsigned int *ns,int round);
+-static unsigned int cb_pcidda_serial_in(comedi_device * dev);
+-static void cb_pcidda_serial_out(comedi_device * dev, unsigned int value,
++static unsigned int cb_pcidda_serial_in(struct comedi_device * dev);
++static void cb_pcidda_serial_out(struct comedi_device * dev, unsigned int value,
+ 	unsigned int num_bits);
+-static unsigned int cb_pcidda_read_eeprom(comedi_device * dev,
++static unsigned int cb_pcidda_read_eeprom(struct comedi_device * dev,
+ 	unsigned int address);
+-static void cb_pcidda_calibrate(comedi_device * dev, unsigned int channel,
++static void cb_pcidda_calibrate(struct comedi_device * dev, unsigned int channel,
+ 	unsigned int range);
+ 
+ /*
+@@ -265,7 +265,7 @@ static comedi_driver driver_cb_pcidda = {
+  * Attach is called by the Comedi core to configure the driver
+  * for a particular board.
+  */
+-static int cb_pcidda_attach(comedi_device * dev, comedi_devconfig * it)
++static int cb_pcidda_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	struct pci_dev *pcidev;
+@@ -385,7 +385,7 @@ static int cb_pcidda_attach(comedi_device * dev, comedi_devconfig * it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int cb_pcidda_detach(comedi_device * dev)
++static int cb_pcidda_detach(struct comedi_device * dev)
+ {
+ /*
+  * Deallocate the I/O ports.
+@@ -413,7 +413,7 @@ static int cb_pcidda_detach(comedi_device * dev)
+  * I will program this later... ;-)
+  */
+ #if 0
+-static int cb_pcidda_ai_cmd(comedi_device * dev, comedi_subdevice * s)
++static int cb_pcidda_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	printk("cb_pcidda_ai_cmd\n");
+ 	printk("subdev: %d\n", cmd->subdev);
+@@ -432,7 +432,7 @@ static int cb_pcidda_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ #endif
+ 
+ #if 0
+-static int cb_pcidda_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidda_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -598,7 +598,7 @@ static int cb_pcidda_ns_to_timer(unsigned int *ns, int round)
+ }
+ #endif
+ 
+-static int cb_pcidda_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int cb_pcidda_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int command;
+@@ -648,7 +648,7 @@ static int cb_pcidda_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ // lowlevel read from eeprom
+-static unsigned int cb_pcidda_serial_in(comedi_device * dev)
++static unsigned int cb_pcidda_serial_in(struct comedi_device * dev)
+ {
+ 	unsigned int value = 0;
+ 	int i;
+@@ -665,7 +665,7 @@ static unsigned int cb_pcidda_serial_in(comedi_device * dev)
+ }
+ 
+ // lowlevel write to eeprom/dac
+-static void cb_pcidda_serial_out(comedi_device * dev, unsigned int value,
++static void cb_pcidda_serial_out(struct comedi_device * dev, unsigned int value,
+ 	unsigned int num_bits)
+ {
+ 	int i;
+@@ -681,7 +681,7 @@ static void cb_pcidda_serial_out(comedi_device * dev, unsigned int value,
+ }
+ 
+ // reads a 16 bit value from board's eeprom
+-static unsigned int cb_pcidda_read_eeprom(comedi_device * dev,
++static unsigned int cb_pcidda_read_eeprom(struct comedi_device * dev,
+ 	unsigned int address)
+ {
+ 	unsigned int i;
+@@ -715,7 +715,7 @@ static unsigned int cb_pcidda_read_eeprom(comedi_device * dev,
+ }
+ 
+ // writes to 8 bit calibration dacs
+-static void cb_pcidda_write_caldac(comedi_device * dev, unsigned int caldac,
++static void cb_pcidda_write_caldac(struct comedi_device * dev, unsigned int caldac,
+ 	unsigned int channel, unsigned int value)
+ {
+ 	unsigned int cal2_bits;
+@@ -801,7 +801,7 @@ static unsigned int eeprom_fine_byte(unsigned int word)
+ }
+ 
+ // set caldacs to eeprom values for given channel and range
+-static void cb_pcidda_calibrate(comedi_device * dev, unsigned int channel,
++static void cb_pcidda_calibrate(struct comedi_device * dev, unsigned int channel,
+ 	unsigned int range)
+ {
+ 	unsigned int coarse_offset, fine_offset, coarse_gain, fine_gain;
+diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c
+index e5bc34746e38..7f749bd61b58 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidio.c
++++ b/drivers/staging/comedi/drivers/cb_pcidio.c
+@@ -102,7 +102,7 @@ MODULE_DEVICE_TABLE(pci, pcidio_pci_table);
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+-   feel free to suggest moving the variable to the comedi_device struct.  */
++   feel free to suggest moving the variable to the struct comedi_device struct.  */
+ typedef struct {
+ 	int data;		// curently unused
+ 
+@@ -127,8 +127,8 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pcidio_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pcidio_detach(comedi_device * dev);
++static int pcidio_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcidio_detach(struct comedi_device * dev);
+ static comedi_driver driver_cb_pcidio = {
+       driver_name:"cb_pcidio",
+       module:THIS_MODULE,
+@@ -166,7 +166,7 @@ static comedi_driver driver_cb_pcidio = {
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pcidio_attach(comedi_device * dev, comedi_devconfig * it)
++static int pcidio_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	struct pci_dev *pcidev = NULL;
+ 	int index;
+@@ -267,7 +267,7 @@ static int pcidio_attach(comedi_device * dev, comedi_devconfig * it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int pcidio_detach(comedi_device * dev)
++static int pcidio_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: cb_pcidio: remove\n", dev->minor);
+ 	if (devpriv) {
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
+index 1223635a4422..09be4e19522e 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
+@@ -138,7 +138,7 @@ MODULE_DEVICE_TABLE(pci, cb_pcimdas_pci_table);
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+-   feel free to suggest moving the variable to the comedi_device struct.  */
++   feel free to suggest moving the variable to the struct comedi_device struct.  */
+ typedef struct {
+ 	int data;
+ 
+@@ -175,8 +175,8 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int cb_pcimdas_attach(comedi_device * dev, comedi_devconfig * it);
+-static int cb_pcimdas_detach(comedi_device * dev);
++static int cb_pcimdas_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int cb_pcimdas_detach(struct comedi_device * dev);
+ static comedi_driver driver_cb_pcimdas = {
+       driver_name:"cb_pcimdas",
+       module:THIS_MODULE,
+@@ -184,11 +184,11 @@ static comedi_driver driver_cb_pcimdas = {
+       detach:cb_pcimdas_detach,
+ };
+ 
+-static int cb_pcimdas_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int cb_pcimdas_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int cb_pcimdas_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int cb_pcimdas_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int cb_pcimdas_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int cb_pcimdas_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ /*
+@@ -197,7 +197,7 @@ static int cb_pcimdas_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int cb_pcimdas_attach(comedi_device * dev, comedi_devconfig * it)
++static int cb_pcimdas_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	struct pci_dev *pcidev;
+@@ -342,7 +342,7 @@ static int cb_pcimdas_attach(comedi_device * dev, comedi_devconfig * it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int cb_pcimdas_detach(comedi_device * dev)
++static int cb_pcimdas_detach(struct comedi_device * dev)
+ {
+ #ifdef CBPCIMDAS_DEBUG
+ 	if (devpriv) {
+@@ -372,7 +372,7 @@ static int cb_pcimdas_detach(comedi_device * dev)
+  * "instructions" read/write data in "one-shot" or "software-triggered"
+  * mode.
+  */
+-static int cb_pcimdas_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int cb_pcimdas_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i;
+@@ -437,7 +437,7 @@ static int cb_pcimdas_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int cb_pcimdas_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int cb_pcimdas_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -465,7 +465,7 @@ static int cb_pcimdas_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ 
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+-static int cb_pcimdas_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int cb_pcimdas_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
+index ac21056aa787..eb583bfd648c 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
+@@ -154,7 +154,7 @@ MODULE_DEVICE_TABLE(pci, pci_table);
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+-   feel free to suggest moving the variable to the comedi_device struct.  */
++   feel free to suggest moving the variable to the struct comedi_device struct.  */
+ typedef struct {
+ 	unsigned long registers;	/* set by probe */
+ 	unsigned long dio_registers;
+@@ -181,8 +181,8 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int attach(comedi_device * dev, comedi_devconfig * it);
+-static int detach(comedi_device * dev);
++static int attach(struct comedi_device * dev, comedi_devconfig * it);
++static int detach(struct comedi_device * dev);
+ static comedi_driver cb_pcimdda_driver = {
+       driver_name:"cb_pcimdda",
+       module:THIS_MODULE,
+@@ -197,9 +197,9 @@ MODULE_DESCRIPTION("Comedi low-level driver for the Computerboards PCIM-DDA "
+ MODULE_LICENSE("GPL");
+ COMEDI_PCI_INITCLEANUP_NOMODULE(cb_pcimdda_driver, pci_table);
+ 
+-static int ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ /*---------------------------------------------------------------------------
+@@ -226,7 +226,7 @@ static inline unsigned int figure_out_maxdata(int bits)
+  *
+  *  Otherwise, returns a -errno on error
+  */
+-static int probe(comedi_device * dev, const comedi_devconfig * it);
++static int probe(struct comedi_device * dev, const comedi_devconfig * it);
+ 
+ /*---------------------------------------------------------------------------
+   FUNCTION DEFINITIONS
+@@ -238,7 +238,7 @@ static int probe(comedi_device * dev, const comedi_devconfig * it);
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int attach(comedi_device * dev, comedi_devconfig * it)
++static int attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	int err;
+@@ -326,7 +326,7 @@ static int attach(comedi_device * dev, comedi_devconfig * it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int detach(comedi_device * dev)
++static int detach(struct comedi_device * dev)
+ {
+ 	if (devpriv) {
+ 
+@@ -352,7 +352,7 @@ static int detach(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -391,7 +391,7 @@ static int ao_winsn(comedi_device * dev, comedi_subdevice * s,
+    all AO channels update simultaneously.  This is useful for some control
+    applications, I would imagine.
+ */
+-static int ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -425,7 +425,7 @@ static int ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+  *
+  *  Otherwise, returns a -errno on error
+  */
+-static int probe(comedi_device * dev, const comedi_devconfig * it)
++static int probe(struct comedi_device * dev, const comedi_devconfig * it)
+ {
+ 	struct pci_dev *pcidev;
+ 	int index;
+diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c
+index 7868ddd6fe25..7d842a2bb5e0 100644
+--- a/drivers/staging/comedi/drivers/comedi_bond.c
++++ b/drivers/staging/comedi/drivers/comedi_bond.c
+@@ -154,7 +154,7 @@ struct BondedDevice {
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+-   feel free to suggest moving the variable to the comedi_device struct.  */
++   feel free to suggest moving the variable to the struct comedi_device struct.  */
+ struct Private {
+ # define MAX_BOARD_NAME 256
+ 	char name[MAX_BOARD_NAME];
+@@ -176,11 +176,11 @@ struct Private {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int bonding_attach(comedi_device *dev, comedi_devconfig *it);
+-static int bonding_detach(comedi_device *dev);
++static int bonding_attach(struct comedi_device *dev, comedi_devconfig *it);
++static int bonding_detach(struct comedi_device *dev);
+ /** Build Private array of all devices.. */
+-static int doDevConfig(comedi_device *dev, comedi_devconfig *it);
+-static void doDevUnconfig(comedi_device *dev);
++static int doDevConfig(struct comedi_device *dev, comedi_devconfig *it);
++static void doDevUnconfig(struct comedi_device *dev);
+ /* Ugly implementation of realloc that always copies memory around -- I'm lazy,
+  * what can I say?  I like to do wasteful memcopies.. :) */
+ static void *Realloc(const void *ptr, size_t len, size_t old_len);
+@@ -213,9 +213,9 @@ static comedi_driver driver_bonding = {
+       .num_names =	sizeof(bondingBoards) / sizeof(struct BondingBoard),
+ };
+ 
+-static int bonding_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
++static int bonding_dio_insn_bits(struct comedi_device *dev, comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+-static int bonding_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
++static int bonding_dio_insn_config(struct comedi_device *dev, comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data);
+ 
+ /*
+@@ -224,7 +224,7 @@ static int bonding_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int bonding_attach(comedi_device *dev, comedi_devconfig *it)
++static int bonding_attach(struct comedi_device *dev, comedi_devconfig *it)
+ {
+ 	comedi_subdevice *s;
+ 
+@@ -281,7 +281,7 @@ static int bonding_attach(comedi_device *dev, comedi_devconfig *it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int bonding_detach(comedi_device *dev)
++static int bonding_detach(struct comedi_device *dev)
+ {
+ 	LOG_MSG("comedi%d: remove\n", dev->minor);
+ 	doDevUnconfig(dev);
+@@ -293,7 +293,7 @@ static int bonding_detach(comedi_device *dev)
+  * useful to applications if you implement the insn_bits interface.
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+-static int bonding_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
++static int bonding_dio_insn_bits(struct comedi_device *dev, comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data)
+ {
+ #define LSAMPL_BITS (sizeof(unsigned int)*8)
+@@ -340,7 +340,7 @@ static int bonding_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
+ 	return insn->n;
+ }
+ 
+-static int bonding_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
++static int bonding_dio_insn_config(struct comedi_device *dev, comedi_subdevice *s,
+ 				   comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec), ret, io_bits = s->io_bits;
+@@ -394,7 +394,7 @@ static void *Realloc(const void *oldmem, size_t newlen, size_t oldlen)
+ 	return newmem;
+ }
+ 
+-static int doDevConfig(comedi_device *dev, comedi_devconfig *it)
++static int doDevConfig(struct comedi_device *dev, comedi_devconfig *it)
+ {
+ 	int i;
+ 	void *devs_opened[COMEDI_NUM_BOARD_MINORS];
+@@ -497,7 +497,7 @@ static int doDevConfig(comedi_device *dev, comedi_devconfig *it)
+ 	return 1;
+ }
+ 
+-static void doDevUnconfig(comedi_device *dev)
++static void doDevUnconfig(struct comedi_device *dev)
+ {
+ 	unsigned long devs_closed = 0;
+ 
+diff --git a/drivers/staging/comedi/drivers/comedi_fc.c b/drivers/staging/comedi/drivers/comedi_fc.c
+index cd74dbe5417d..842b250a7c65 100644
+--- a/drivers/staging/comedi/drivers/comedi_fc.c
++++ b/drivers/staging/comedi/drivers/comedi_fc.c
+@@ -85,7 +85,7 @@ unsigned int cfc_read_array_from_buffer(comedi_subdevice *subd, void *data,
+ }
+ EXPORT_SYMBOL(cfc_read_array_from_buffer);
+ 
+-unsigned int cfc_handle_events(comedi_device *dev, comedi_subdevice *subd)
++unsigned int cfc_handle_events(struct comedi_device *dev, comedi_subdevice *subd)
+ {
+ 	unsigned int events = subd->async->events;
+ 
+diff --git a/drivers/staging/comedi/drivers/comedi_fc.h b/drivers/staging/comedi/drivers/comedi_fc.h
+index bbb70d66eee9..4f251cd509e6 100644
+--- a/drivers/staging/comedi/drivers/comedi_fc.h
++++ b/drivers/staging/comedi/drivers/comedi_fc.h
+@@ -50,7 +50,7 @@ extern unsigned int cfc_read_array_from_buffer(comedi_subdevice *subd,
+ 					       void *data,
+ 					       unsigned int num_bytes);
+ 
+-extern unsigned int cfc_handle_events(comedi_device *dev,
++extern unsigned int cfc_handle_events(struct comedi_device *dev,
+ 				      comedi_subdevice *subd);
+ 
+ static inline unsigned int cfc_bytes_per_scan(comedi_subdevice *subd)
+diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c
+index 87c4c20694e0..b432d50df4d4 100644
+--- a/drivers/staging/comedi/drivers/comedi_parport.c
++++ b/drivers/staging/comedi/drivers/comedi_parport.c
+@@ -90,8 +90,8 @@ pin, which can be used to wake up tasks.
+ #define PARPORT_B 1
+ #define PARPORT_C 2
+ 
+-static int parport_attach(comedi_device *dev, comedi_devconfig *it);
+-static int parport_detach(comedi_device *dev);
++static int parport_attach(struct comedi_device *dev, comedi_devconfig *it);
++static int parport_detach(struct comedi_device *dev);
+ static comedi_driver driver_parport = {
+       .driver_name =	"comedi_parport",
+       .module =		THIS_MODULE,
+@@ -108,7 +108,7 @@ struct parport_private {
+ };
+ #define devpriv ((struct parport_private *)(dev->private))
+ 
+-static int parport_insn_a(comedi_device *dev, comedi_subdevice *s,
++static int parport_insn_a(struct comedi_device *dev, comedi_subdevice *s,
+ 			  comedi_insn *insn, unsigned int *data)
+ {
+ 	if (data[0]) {
+@@ -123,7 +123,7 @@ static int parport_insn_a(comedi_device *dev, comedi_subdevice *s,
+ 	return 2;
+ }
+ 
+-static int parport_insn_config_a(comedi_device *dev, comedi_subdevice *s,
++static int parport_insn_config_a(struct comedi_device *dev, comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data)
+ {
+ 	if (data[0]) {
+@@ -138,7 +138,7 @@ static int parport_insn_config_a(comedi_device *dev, comedi_subdevice *s,
+ 	return 1;
+ }
+ 
+-static int parport_insn_b(comedi_device *dev, comedi_subdevice *s,
++static int parport_insn_b(struct comedi_device *dev, comedi_subdevice *s,
+ 			  comedi_insn *insn, unsigned int *data)
+ {
+ 	if (data[0]) {
+@@ -151,7 +151,7 @@ static int parport_insn_b(comedi_device *dev, comedi_subdevice *s,
+ 	return 2;
+ }
+ 
+-static int parport_insn_c(comedi_device *dev, comedi_subdevice *s,
++static int parport_insn_c(struct comedi_device *dev, comedi_subdevice *s,
+ 			  comedi_insn *insn, unsigned int *data)
+ {
+ 	data[0] &= 0x0f;
+@@ -167,7 +167,7 @@ static int parport_insn_c(comedi_device *dev, comedi_subdevice *s,
+ 	return 2;
+ }
+ 
+-static int parport_intr_insn(comedi_device *dev, comedi_subdevice *s,
++static int parport_intr_insn(struct comedi_device *dev, comedi_subdevice *s,
+ 			     comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n < 1)
+@@ -177,7 +177,7 @@ static int parport_intr_insn(comedi_device *dev, comedi_subdevice *s,
+ 	return 2;
+ }
+ 
+-static int parport_intr_cmdtest(comedi_device *dev, comedi_subdevice *s,
++static int parport_intr_cmdtest(struct comedi_device *dev, comedi_subdevice *s,
+ 				comedi_cmd *cmd)
+ {
+ 	int err = 0;
+@@ -252,7 +252,7 @@ static int parport_intr_cmdtest(comedi_device *dev, comedi_subdevice *s,
+ 	return 0;
+ }
+ 
+-static int parport_intr_cmd(comedi_device *dev, comedi_subdevice *s)
++static int parport_intr_cmd(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 	devpriv->c_data |= 0x10;
+ 	outb(devpriv->c_data, dev->iobase + PARPORT_C);
+@@ -262,7 +262,7 @@ static int parport_intr_cmd(comedi_device *dev, comedi_subdevice *s)
+ 	return 0;
+ }
+ 
+-static int parport_intr_cancel(comedi_device *dev, comedi_subdevice *s)
++static int parport_intr_cancel(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 	printk(KERN_DEBUG "parport_intr_cancel()\n");
+ 
+@@ -276,7 +276,7 @@ static int parport_intr_cancel(comedi_device *dev, comedi_subdevice *s)
+ 
+ static irqreturn_t parport_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s = dev->subdevices + 3;
+ 
+ 	if (!devpriv->enable_irq) {
+@@ -291,7 +291,7 @@ static irqreturn_t parport_interrupt(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int parport_attach(comedi_device *dev, comedi_devconfig *it)
++static int parport_attach(struct comedi_device *dev, comedi_devconfig *it)
+ {
+ 	int ret;
+ 	unsigned int irq;
+@@ -376,7 +376,7 @@ static int parport_attach(comedi_device *dev, comedi_devconfig *it)
+ 	return 1;
+ }
+ 
+-static int parport_detach(comedi_device *dev)
++static int parport_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: parport: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/comedi_rt_timer.c b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+index ec081c4180c6..202b04b2e394 100644
+--- a/drivers/staging/comedi/drivers/comedi_rt_timer.c
++++ b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+@@ -122,11 +122,11 @@ static inline RTIME nano2count(long long ns)
+  * task period because analog input tends to be slow. */
+ #define SPEED_LIMIT 100000	/* in nanoseconds */
+ 
+-static int timer_attach(comedi_device * dev, comedi_devconfig * it);
+-static int timer_detach(comedi_device * dev);
+-static int timer_inttrig(comedi_device * dev, comedi_subdevice * s,
++static int timer_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int timer_detach(struct comedi_device * dev);
++static int timer_inttrig(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int trig_num);
+-static int timer_start_cmd(comedi_device * dev, comedi_subdevice * s);
++static int timer_start_cmd(struct comedi_device * dev, comedi_subdevice * s);
+ 
+ static comedi_driver driver_timer = {
+       module:THIS_MODULE,
+@@ -145,7 +145,7 @@ typedef struct {
+ 	RT_TASK *scan_task;	// rt task that controls conversion timing in a scan
+ 	/* io_function can point to either an input or output function
+ 	 * depending on what kind of subdevice we are emulating for */
+-	int (*io_function) (comedi_device * dev, comedi_cmd * cmd,
++	int (*io_function) (struct comedi_device * dev, comedi_cmd * cmd,
+ 		unsigned int index);
+ 	// RTIME has units of 1 = 838 nanoseconds
+ 	// time at which first scan started, used to check scan timing
+@@ -162,7 +162,7 @@ typedef struct {
+ } timer_private;
+ #define devpriv ((timer_private *)dev->private)
+ 
+-static int timer_cancel(comedi_device * dev, comedi_subdevice * s)
++static int timer_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	devpriv->stop = 1;
+ 
+@@ -170,7 +170,7 @@ static int timer_cancel(comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ // checks for scan timing error
+-inline static int check_scan_timing(comedi_device * dev,
++inline static int check_scan_timing(struct comedi_device * dev,
+ 	unsigned long long scan)
+ {
+ 	RTIME now, timing_error;
+@@ -187,7 +187,7 @@ inline static int check_scan_timing(comedi_device * dev,
+ }
+ 
+ // checks for conversion timing error
+-inline static int check_conversion_timing(comedi_device * dev,
++inline static int check_conversion_timing(struct comedi_device * dev,
+ 	RTIME scan_start, unsigned int conversion)
+ {
+ 	RTIME now, timing_error;
+@@ -206,7 +206,7 @@ inline static int check_conversion_timing(comedi_device * dev,
+ }
+ 
+ // devpriv->io_function for an input subdevice
+-static int timer_data_read(comedi_device * dev, comedi_cmd * cmd,
++static int timer_data_read(struct comedi_device * dev, comedi_cmd * cmd,
+ 	unsigned int index)
+ {
+ 	comedi_subdevice *s = dev->read_subdev;
+@@ -231,7 +231,7 @@ static int timer_data_read(comedi_device * dev, comedi_cmd * cmd,
+ }
+ 
+ // devpriv->io_function for an output subdevice
+-static int timer_data_write(comedi_device * dev, comedi_cmd * cmd,
++static int timer_data_write(struct comedi_device * dev, comedi_cmd * cmd,
+ 	unsigned int index)
+ {
+ 	comedi_subdevice *s = dev->write_subdev;
+@@ -266,7 +266,7 @@ static int timer_data_write(comedi_device * dev, comedi_cmd * cmd,
+ }
+ 
+ // devpriv->io_function for DIO subdevices
+-static int timer_dio_read(comedi_device * dev, comedi_cmd * cmd,
++static int timer_dio_read(struct comedi_device * dev, comedi_cmd * cmd,
+ 	unsigned int index)
+ {
+ 	comedi_subdevice *s = dev->read_subdev;
+@@ -290,7 +290,7 @@ static int timer_dio_read(comedi_device * dev, comedi_cmd * cmd,
+ // performs scans
+ static void scan_task_func(comedi_rt_task_context_t d)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + 0;
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+@@ -360,7 +360,7 @@ static void scan_task_func(comedi_rt_task_context_t d)
+ 
+ static void timer_task_func(comedi_rt_task_context_t d)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + 0;
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	int ret;
+@@ -396,7 +396,7 @@ static void timer_task_func(comedi_rt_task_context_t d)
+ 	}
+ }
+ 
+-static int timer_insn(comedi_device * dev, comedi_subdevice * s,
++static int timer_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	comedi_insn xinsn = *insn;
+@@ -444,7 +444,7 @@ static int cmdtest_helper(comedi_cmd * cmd,
+ 	return err;
+ }
+ 
+-static int timer_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int timer_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -516,7 +516,7 @@ static int timer_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int timer_cmd(comedi_device * dev, comedi_subdevice * s)
++static int timer_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	int ret;
+ 	comedi_cmd *cmd = &s->async->cmd;
+@@ -567,7 +567,7 @@ static int timer_cmd(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int timer_inttrig(comedi_device * dev, comedi_subdevice * s,
++static int timer_inttrig(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int trig_num)
+ {
+ 	if (trig_num != 0)
+@@ -578,7 +578,7 @@ static int timer_inttrig(comedi_device * dev, comedi_subdevice * s,
+ 	return timer_start_cmd(dev, s);
+ }
+ 
+-static int timer_start_cmd(comedi_device * dev, comedi_subdevice * s)
++static int timer_start_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+@@ -607,11 +607,11 @@ static int timer_start_cmd(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int timer_attach(comedi_device * dev, comedi_devconfig * it)
++static int timer_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int ret;
+ 	comedi_subdevice *s, *emul_s;
+-	comedi_device *emul_dev;
++	struct comedi_device *emul_dev;
+ 	/* These should probably be devconfig options[] */
+ 	const int timer_priority = 4;
+ 	const int scan_priority = timer_priority + 1;
+@@ -706,7 +706,7 @@ static int timer_attach(comedi_device * dev, comedi_devconfig * it)
+ }
+ 
+ // free allocated resources
+-static int timer_detach(comedi_device * dev)
++static int timer_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: timer: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c
+index f65ee2b52042..70aeb6088e1b 100644
+--- a/drivers/staging/comedi/drivers/comedi_test.c
++++ b/drivers/staging/comedi/drivers/comedi_test.c
+@@ -93,8 +93,8 @@ struct waveform_private {
+ };
+ #define devpriv ((struct waveform_private *)dev->private)
+ 
+-static int waveform_attach(comedi_device *dev, comedi_devconfig *it);
+-static int waveform_detach(comedi_device *dev);
++static int waveform_attach(struct comedi_device *dev, comedi_devconfig *it);
++static int waveform_detach(struct comedi_device *dev);
+ static comedi_driver driver_waveform = {
+       .driver_name =	"comedi_test",
+       .module =		THIS_MODULE,
+@@ -107,21 +107,21 @@ static comedi_driver driver_waveform = {
+ 
+ COMEDI_INITCLEANUP(driver_waveform);
+ 
+-static int waveform_ai_cmdtest(comedi_device *dev, comedi_subdevice *s,
++static int waveform_ai_cmdtest(struct comedi_device *dev, comedi_subdevice *s,
+ 			       comedi_cmd *cmd);
+-static int waveform_ai_cmd(comedi_device *dev, comedi_subdevice *s);
+-static int waveform_ai_cancel(comedi_device *dev, comedi_subdevice *s);
+-static int waveform_ai_insn_read(comedi_device *dev, comedi_subdevice *s,
++static int waveform_ai_cmd(struct comedi_device *dev, comedi_subdevice *s);
++static int waveform_ai_cancel(struct comedi_device *dev, comedi_subdevice *s);
++static int waveform_ai_insn_read(struct comedi_device *dev, comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data);
+-static int waveform_ao_insn_write(comedi_device *dev, comedi_subdevice *s,
++static int waveform_ao_insn_write(struct comedi_device *dev, comedi_subdevice *s,
+ 				  comedi_insn *insn, unsigned int *data);
+-static short fake_sawtooth(comedi_device *dev, unsigned int range,
++static short fake_sawtooth(struct comedi_device *dev, unsigned int range,
+ 			     unsigned long current_time);
+-static short fake_squarewave(comedi_device *dev, unsigned int range,
++static short fake_squarewave(struct comedi_device *dev, unsigned int range,
+ 			       unsigned long current_time);
+-static short fake_flatline(comedi_device *dev, unsigned int range,
++static short fake_flatline(struct comedi_device *dev, unsigned int range,
+ 			     unsigned long current_time);
+-static short fake_waveform(comedi_device *dev, unsigned int channel,
++static short fake_waveform(struct comedi_device *dev, unsigned int channel,
+ 			     unsigned int range, unsigned long current_time);
+ 
+ /* 1000 nanosec in a microsec */
+@@ -143,7 +143,7 @@ static const comedi_lrange waveform_ai_ranges = {
+ */
+ static void waveform_ai_interrupt(unsigned long arg)
+ {
+-	comedi_device *dev = (comedi_device *) arg;
++	struct comedi_device *dev = (struct comedi_device *) arg;
+ 	comedi_async *async = dev->read_subdev->async;
+ 	comedi_cmd *cmd = &async->cmd;
+ 	unsigned int i, j;
+@@ -192,7 +192,7 @@ static void waveform_ai_interrupt(unsigned long arg)
+ 	comedi_event(dev, dev->read_subdev);
+ }
+ 
+-static int waveform_attach(comedi_device *dev, comedi_devconfig *it)
++static int waveform_attach(struct comedi_device *dev, comedi_devconfig *it)
+ {
+ 	comedi_subdevice *s;
+ 	int amplitude = it->options[0];
+@@ -259,7 +259,7 @@ static int waveform_attach(comedi_device *dev, comedi_devconfig *it)
+ 	return 1;
+ }
+ 
+-static int waveform_detach(comedi_device *dev)
++static int waveform_detach(struct comedi_device *dev)
+ {
+ 	printk("comedi%d: comedi_test: remove\n", dev->minor);
+ 
+@@ -269,7 +269,7 @@ static int waveform_detach(comedi_device *dev)
+ 	return 0;
+ }
+ 
+-static int waveform_ai_cmdtest(comedi_device *dev, comedi_subdevice *s,
++static int waveform_ai_cmdtest(struct comedi_device *dev, comedi_subdevice *s,
+ 			       comedi_cmd *cmd)
+ {
+ 	int err = 0;
+@@ -397,7 +397,7 @@ static int waveform_ai_cmdtest(comedi_device *dev, comedi_subdevice *s,
+ 	return 0;
+ }
+ 
+-static int waveform_ai_cmd(comedi_device *dev, comedi_subdevice *s)
++static int waveform_ai_cmd(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 
+@@ -429,14 +429,14 @@ static int waveform_ai_cmd(comedi_device *dev, comedi_subdevice *s)
+ 	return 0;
+ }
+ 
+-static int waveform_ai_cancel(comedi_device *dev, comedi_subdevice *s)
++static int waveform_ai_cancel(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 	devpriv->timer_running = 0;
+ 	del_timer(&devpriv->timer);
+ 	return 0;
+ }
+ 
+-static short fake_sawtooth(comedi_device *dev, unsigned int range_index,
++static short fake_sawtooth(struct comedi_device *dev, unsigned int range_index,
+ 			     unsigned long current_time)
+ {
+ 	comedi_subdevice *s = dev->read_subdev;
+@@ -457,7 +457,7 @@ static short fake_sawtooth(comedi_device *dev, unsigned int range_index,
+ 
+ 	return offset + value;
+ }
+-static short fake_squarewave(comedi_device *dev, unsigned int range_index,
++static short fake_squarewave(struct comedi_device *dev, unsigned int range_index,
+ 			       unsigned long current_time)
+ {
+ 	comedi_subdevice *s = dev->read_subdev;
+@@ -476,14 +476,14 @@ static short fake_squarewave(comedi_device *dev, unsigned int range_index,
+ 	return offset + value;
+ }
+ 
+-static short fake_flatline(comedi_device *dev, unsigned int range_index,
++static short fake_flatline(struct comedi_device *dev, unsigned int range_index,
+ 			     unsigned long current_time)
+ {
+ 	return dev->read_subdev->maxdata / 2;
+ }
+ 
+ /* generates a different waveform depending on what channel is read */
+-static short fake_waveform(comedi_device *dev, unsigned int channel,
++static short fake_waveform(struct comedi_device *dev, unsigned int channel,
+ 			     unsigned int range, unsigned long current_time)
+ {
+ 	enum {
+@@ -504,7 +504,7 @@ static short fake_waveform(comedi_device *dev, unsigned int channel,
+ 	return fake_flatline(dev, range, current_time);
+ }
+ 
+-static int waveform_ai_insn_read(comedi_device *dev, comedi_subdevice *s,
++static int waveform_ai_insn_read(struct comedi_device *dev, comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, chan = CR_CHAN(insn->chanspec);
+@@ -515,7 +515,7 @@ static int waveform_ai_insn_read(comedi_device *dev, comedi_subdevice *s,
+ 	return insn->n;
+ }
+ 
+-static int waveform_ao_insn_write(comedi_device *dev, comedi_subdevice *s,
++static int waveform_ao_insn_write(struct comedi_device *dev, comedi_subdevice *s,
+ 				  comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
+index 3049eb26674b..845f97e81280 100644
+--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
++++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
+@@ -75,8 +75,8 @@ typedef struct {
+ 
+ #define devpriv ((contec_private *)dev->private)
+ 
+-static int contec_attach(comedi_device * dev, comedi_devconfig * it);
+-static int contec_detach(comedi_device * dev);
++static int contec_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int contec_detach(struct comedi_device * dev);
+ static comedi_driver driver_contec = {
+       driver_name:"contec_pci_dio",
+       module:THIS_MODULE,
+@@ -85,19 +85,19 @@ static comedi_driver driver_contec = {
+ };
+ 
+ /* Classic digital IO */
+-static int contec_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int contec_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int contec_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int contec_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ #if 0
+-static int contec_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int contec_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+ 
+ static int contec_ns_to_timer(unsigned int *ns, int round);
+ #endif
+ 
+-static int contec_attach(comedi_device * dev, comedi_devconfig * it)
++static int contec_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	struct pci_dev *pcidev;
+ 	comedi_subdevice *s;
+@@ -164,7 +164,7 @@ static int contec_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return -EIO;
+ }
+ 
+-static int contec_detach(comedi_device * dev)
++static int contec_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: contec: remove\n", dev->minor);
+ 
+@@ -179,7 +179,7 @@ static int contec_detach(comedi_device * dev)
+ }
+ 
+ #if 0
+-static int contec_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int contec_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	printk("contec_cmdtest called\n");
+@@ -192,7 +192,7 @@ static int contec_ns_to_timer(unsigned int *ns, int round)
+ }
+ #endif
+ 
+-static int contec_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int contec_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -212,7 +212,7 @@ static int contec_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int contec_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int contec_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
+index 86cab4295d9e..21bf5d3131b7 100644
+--- a/drivers/staging/comedi/drivers/daqboard2000.c
++++ b/drivers/staging/comedi/drivers/daqboard2000.c
+@@ -296,8 +296,8 @@ typedef struct daqboard2000_hw {
+ #define DAQBOARD2000_PosRefDacSelect             0x0100
+ #define DAQBOARD2000_NegRefDacSelect             0x0000
+ 
+-static int daqboard2000_attach(comedi_device * dev, comedi_devconfig * it);
+-static int daqboard2000_detach(comedi_device * dev);
++static int daqboard2000_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int daqboard2000_detach(struct comedi_device * dev);
+ 
+ static comedi_driver driver_daqboard2000 = {
+       driver_name:"daqboard2000",
+@@ -338,7 +338,7 @@ typedef struct {
+ 
+ #define devpriv ((daqboard2000_private*)dev->private)
+ 
+-static void writeAcqScanListEntry(comedi_device * dev, u16 entry)
++static void writeAcqScanListEntry(struct comedi_device * dev, u16 entry)
+ {
+ 	daqboard2000_hw *fpga = devpriv->daq;
+ 
+@@ -348,7 +348,7 @@ static void writeAcqScanListEntry(comedi_device * dev, u16 entry)
+ 	fpga->acqScanListFIFO = (entry >> 8) & 0x00ff;
+ }
+ 
+-static void setup_sampling(comedi_device * dev, int chan, int gain)
++static void setup_sampling(struct comedi_device * dev, int chan, int gain)
+ {
+ 	u16 word0, word1, word2, word3;
+ 
+@@ -393,7 +393,7 @@ static void setup_sampling(comedi_device * dev, int chan, int gain)
+ 	writeAcqScanListEntry(dev, word3);
+ }
+ 
+-static int daqboard2000_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int daqboard2000_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -450,7 +450,7 @@ static int daqboard2000_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int daqboard2000_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int daqboard2000_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -463,7 +463,7 @@ static int daqboard2000_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int daqboard2000_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
++static int daqboard2000_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -494,7 +494,7 @@ static int daqboard2000_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static void daqboard2000_resetLocalBus(comedi_device * dev)
++static void daqboard2000_resetLocalBus(struct comedi_device * dev)
+ {
+ 	printk("daqboard2000_resetLocalBus\n");
+ 	writel(DAQBOARD2000_SECRLocalBusHi, devpriv->plx + 0x6c);
+@@ -503,7 +503,7 @@ static void daqboard2000_resetLocalBus(comedi_device * dev)
+ 	comedi_udelay(10000);
+ }
+ 
+-static void daqboard2000_reloadPLX(comedi_device * dev)
++static void daqboard2000_reloadPLX(struct comedi_device * dev)
+ {
+ 	printk("daqboard2000_reloadPLX\n");
+ 	writel(DAQBOARD2000_SECRReloadLo, devpriv->plx + 0x6c);
+@@ -514,7 +514,7 @@ static void daqboard2000_reloadPLX(comedi_device * dev)
+ 	comedi_udelay(10000);
+ }
+ 
+-static void daqboard2000_pulseProgPin(comedi_device * dev)
++static void daqboard2000_pulseProgPin(struct comedi_device * dev)
+ {
+ 	printk("daqboard2000_pulseProgPin 1\n");
+ 	writel(DAQBOARD2000_SECRProgPinHi, devpriv->plx + 0x6c);
+@@ -523,7 +523,7 @@ static void daqboard2000_pulseProgPin(comedi_device * dev)
+ 	comedi_udelay(10000);	/* Not in the original code, but I like symmetry... */
+ }
+ 
+-static int daqboard2000_pollCPLD(comedi_device * dev, int mask)
++static int daqboard2000_pollCPLD(struct comedi_device * dev, int mask)
+ {
+ 	int result = 0;
+ 	int i;
+@@ -542,7 +542,7 @@ static int daqboard2000_pollCPLD(comedi_device * dev, int mask)
+ 	return result;
+ }
+ 
+-static int daqboard2000_writeCPLD(comedi_device * dev, int data)
++static int daqboard2000_writeCPLD(struct comedi_device * dev, int data)
+ {
+ 	int result = 0;
+ 
+@@ -555,7 +555,7 @@ static int daqboard2000_writeCPLD(comedi_device * dev, int data)
+ 	return result;
+ }
+ 
+-static int initialize_daqboard2000(comedi_device * dev,
++static int initialize_daqboard2000(struct comedi_device * dev,
+ 	unsigned char *cpld_array, int len)
+ {
+ 	int result = -EIO;
+@@ -613,12 +613,12 @@ static int initialize_daqboard2000(comedi_device * dev,
+ 	return result;
+ }
+ 
+-static void daqboard2000_adcStopDmaTransfer(comedi_device * dev)
++static void daqboard2000_adcStopDmaTransfer(struct comedi_device * dev)
+ {
+ /*  printk("Implement: daqboard2000_adcStopDmaTransfer\n");*/
+ }
+ 
+-static void daqboard2000_adcDisarm(comedi_device * dev)
++static void daqboard2000_adcDisarm(struct comedi_device * dev)
+ {
+ 	daqboard2000_hw *fpga = devpriv->daq;
+ 
+@@ -640,7 +640,7 @@ static void daqboard2000_adcDisarm(comedi_device * dev)
+ 	daqboard2000_adcStopDmaTransfer(dev);
+ }
+ 
+-static void daqboard2000_activateReferenceDacs(comedi_device * dev)
++static void daqboard2000_activateReferenceDacs(struct comedi_device * dev)
+ {
+ 	daqboard2000_hw *fpga = devpriv->daq;
+ 	int timeout;
+@@ -666,22 +666,22 @@ static void daqboard2000_activateReferenceDacs(comedi_device * dev)
+ /*  printk("DAQBOARD2000_NegRefDacSelect %d\n", timeout);*/
+ }
+ 
+-static void daqboard2000_initializeCtrs(comedi_device * dev)
++static void daqboard2000_initializeCtrs(struct comedi_device * dev)
+ {
+ /*  printk("Implement: daqboard2000_initializeCtrs\n");*/
+ }
+ 
+-static void daqboard2000_initializeTmrs(comedi_device * dev)
++static void daqboard2000_initializeTmrs(struct comedi_device * dev)
+ {
+ /*  printk("Implement: daqboard2000_initializeTmrs\n");*/
+ }
+ 
+-static void daqboard2000_dacDisarm(comedi_device * dev)
++static void daqboard2000_dacDisarm(struct comedi_device * dev)
+ {
+ /*  printk("Implement: daqboard2000_dacDisarm\n");*/
+ }
+ 
+-static void daqboard2000_initializeAdc(comedi_device * dev)
++static void daqboard2000_initializeAdc(struct comedi_device * dev)
+ {
+ 	daqboard2000_adcDisarm(dev);
+ 	daqboard2000_activateReferenceDacs(dev);
+@@ -689,7 +689,7 @@ static void daqboard2000_initializeAdc(comedi_device * dev)
+ 	daqboard2000_initializeTmrs(dev);
+ }
+ 
+-static void daqboard2000_initializeDac(comedi_device * dev)
++static void daqboard2000_initializeDac(struct comedi_device * dev)
+ {
+ 	daqboard2000_dacDisarm(dev);
+ }
+@@ -717,7 +717,7 @@ static int daqboard2000_8255_cb(int dir, int port, int data,
+ 	return result;
+ }
+ 
+-static int daqboard2000_attach(comedi_device * dev, comedi_devconfig * it)
++static int daqboard2000_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int result = 0;
+ 	comedi_subdevice *s;
+@@ -849,7 +849,7 @@ static int daqboard2000_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return result;
+ }
+ 
+-static int daqboard2000_detach(comedi_device * dev)
++static int daqboard2000_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: daqboard2000: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
+index 8d4903dc03d6..1614a2070aff 100644
+--- a/drivers/staging/comedi/drivers/das08.c
++++ b/drivers/staging/comedi/drivers/das08.c
+@@ -154,19 +154,19 @@ driver.
+ 
+ /* gainlist same as _pgx_ below */
+ 
+-static int das08_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int das08_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das08_di_rbits(comedi_device * dev, comedi_subdevice * s,
++static int das08_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das08_do_wbits(comedi_device * dev, comedi_subdevice * s,
++static int das08_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das08jr_di_rbits(comedi_device * dev, comedi_subdevice * s,
++static int das08jr_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das08jr_do_wbits(comedi_device * dev, comedi_subdevice * s,
++static int das08jr_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das08jr_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int das08jr_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das08ao_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int das08ao_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ static void i8254_set_mode_low(unsigned int base, int channel,
+ 	unsigned int mode);
+@@ -512,7 +512,7 @@ MODULE_DEVICE_TABLE(pci, das08_pci_table);
+ 
+ #define TIMEOUT 100000
+ 
+-static int das08_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int das08_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+@@ -579,7 +579,7 @@ static int das08_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int das08_di_rbits(comedi_device * dev, comedi_subdevice * s,
++static int das08_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = 0;
+@@ -588,7 +588,7 @@ static int das08_di_rbits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int das08_do_wbits(comedi_device * dev, comedi_subdevice * s,
++static int das08_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int wbits;
+@@ -611,7 +611,7 @@ static int das08_do_wbits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int das08jr_di_rbits(comedi_device * dev, comedi_subdevice * s,
++static int das08jr_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = 0;
+@@ -620,7 +620,7 @@ static int das08jr_di_rbits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int das08jr_do_wbits(comedi_device * dev, comedi_subdevice * s,
++static int das08jr_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	// null bits we are going to set
+@@ -634,7 +634,7 @@ static int das08jr_do_wbits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int das08jr_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int das08jr_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -668,7 +668,7 @@ static int das08jr_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+  * a different method to force an update.
+  *
+  */
+-static int das08ao_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int das08ao_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -782,7 +782,7 @@ static unsigned int i8254_read_status(struct i8254_struct *st, int channel)
+ 	return i8254_read_status_low(st->iobase, chan);
+ }
+ 
+-static int das08_counter_read(comedi_device * dev, comedi_subdevice * s,
++static int das08_counter_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = insn->chanspec;
+@@ -794,7 +794,7 @@ static int das08_counter_read(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int das08_counter_write(comedi_device * dev, comedi_subdevice * s,
++static int das08_counter_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = insn->chanspec;
+@@ -805,7 +805,7 @@ static int das08_counter_write(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int das08_counter_config(comedi_device * dev, comedi_subdevice * s,
++static int das08_counter_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = insn->chanspec;
+@@ -827,7 +827,7 @@ static int das08_counter_config(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int das08_attach(comedi_device * dev, comedi_devconfig * it);
++static int das08_attach(struct comedi_device * dev, comedi_devconfig * it);
+ 
+ static comedi_driver driver_das08 = {
+       driver_name: DRV_NAME,
+@@ -840,7 +840,7 @@ static comedi_driver driver_das08 = {
+       offset:sizeof(struct das08_board_struct),
+ };
+ 
+-int das08_common_attach(comedi_device * dev, unsigned long iobase)
++int das08_common_attach(struct comedi_device * dev, unsigned long iobase)
+ {
+ 	comedi_subdevice *s;
+ 	int ret;
+@@ -952,7 +952,7 @@ int das08_common_attach(comedi_device * dev, unsigned long iobase)
+ 	return 0;
+ }
+ 
+-static int das08_attach(comedi_device * dev, comedi_devconfig * it)
++static int das08_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int ret;
+ 	unsigned long iobase;
+@@ -1028,7 +1028,7 @@ static int das08_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return das08_common_attach(dev, iobase);
+ }
+ 
+-int das08_common_detach(comedi_device * dev)
++int das08_common_detach(struct comedi_device * dev)
+ {
+ 	printk(KERN_INFO "comedi%d: das08: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/das08.h b/drivers/staging/comedi/drivers/das08.h
+index 6342fbaf7bf0..9f82527ec834 100644
+--- a/drivers/staging/comedi/drivers/das08.h
++++ b/drivers/staging/comedi/drivers/das08.h
+@@ -72,7 +72,7 @@ struct das08_private_struct {
+ #define NUM_DAS08_CS_BOARDS 2
+ extern struct das08_board_struct das08_cs_boards[NUM_DAS08_CS_BOARDS];
+ 
+-int das08_common_attach(comedi_device * dev, unsigned long iobase);
+-int das08_common_detach(comedi_device * dev);
++int das08_common_attach(struct comedi_device * dev, unsigned long iobase);
++int das08_common_detach(struct comedi_device * dev);
+ 
+ #endif /* _DAS08_H */
+diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
+index d5390e630878..0e56f1d762de 100644
+--- a/drivers/staging/comedi/drivers/das08_cs.c
++++ b/drivers/staging/comedi/drivers/das08_cs.c
+@@ -56,7 +56,7 @@ static struct pcmcia_device *cur_dev = NULL;
+ 
+ #define thisboard ((const struct das08_board_struct *)dev->board_ptr)
+ 
+-static int das08_cs_attach(comedi_device * dev, comedi_devconfig * it);
++static int das08_cs_attach(struct comedi_device * dev, comedi_devconfig * it);
+ 
+ static comedi_driver driver_das08_cs = {
+       driver_name:"das08_cs",
+@@ -69,7 +69,7 @@ static comedi_driver driver_das08_cs = {
+       offset:sizeof(struct das08_board_struct),
+ };
+ 
+-static int das08_cs_attach(comedi_device * dev, comedi_devconfig * it)
++static int das08_cs_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int ret;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
+index dd28385fc12f..07f8856c2c39 100644
+--- a/drivers/staging/comedi/drivers/das16.c
++++ b/drivers/staging/comedi/drivers/das16.c
+@@ -326,34 +326,34 @@ struct munge_info {
+ 	unsigned have_byte:1;
+ };
+ 
+-static int das16_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int das16_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das16_do_wbits(comedi_device * dev, comedi_subdevice * s,
++static int das16_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das16_di_rbits(comedi_device * dev, comedi_subdevice * s,
++static int das16_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das16_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int das16_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int das16_cmd_test(comedi_device * dev, comedi_subdevice * s,
++static int das16_cmd_test(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int das16_cmd_exec(comedi_device * dev, comedi_subdevice * s);
+-static int das16_cancel(comedi_device * dev, comedi_subdevice * s);
+-static void das16_ai_munge(comedi_device * dev, comedi_subdevice * s,
++static int das16_cmd_exec(struct comedi_device * dev, comedi_subdevice * s);
++static int das16_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static void das16_ai_munge(struct comedi_device * dev, comedi_subdevice * s,
+ 	void *array, unsigned int num_bytes, unsigned int start_chan_index);
+ 
+-static void das16_reset(comedi_device * dev);
++static void das16_reset(struct comedi_device * dev);
+ static irqreturn_t das16_dma_interrupt(int irq, void *d PT_REGS_ARG);
+ static void das16_timer_interrupt(unsigned long arg);
+-static void das16_interrupt(comedi_device * dev);
++static void das16_interrupt(struct comedi_device * dev);
+ 
+-static unsigned int das16_set_pacer(comedi_device * dev, unsigned int ns,
++static unsigned int das16_set_pacer(struct comedi_device * dev, unsigned int ns,
+ 	int flags);
+-static int das1600_mode_detect(comedi_device * dev);
+-static unsigned int das16_suggest_transfer_size(comedi_device * dev,
++static int das1600_mode_detect(struct comedi_device * dev);
++static unsigned int das16_suggest_transfer_size(struct comedi_device * dev,
+ 	comedi_cmd cmd);
+ 
+-static void reg_dump(comedi_device * dev);
++static void reg_dump(struct comedi_device * dev);
+ 
+ typedef struct das16_board_struct {
+ 	const char *name;
+@@ -698,8 +698,8 @@ static const struct das16_board_struct das16_boards[] = {
+ 
+ #define n_das16_boards ((sizeof(das16_boards))/(sizeof(das16_board)))
+ 
+-static int das16_attach(comedi_device * dev, comedi_devconfig * it);
+-static int das16_detach(comedi_device * dev);
++static int das16_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int das16_detach(struct comedi_device * dev);
+ static comedi_driver driver_das16 = {
+       driver_name:"das16",
+       module:THIS_MODULE,
+@@ -742,7 +742,7 @@ struct das16_private_struct {
+ #define devpriv ((struct das16_private_struct *)(dev->private))
+ #define thisboard ((struct das16_board_struct *)(dev->board_ptr))
+ 
+-static int das16_cmd_test(comedi_device * dev, comedi_subdevice * s,
++static int das16_cmd_test(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0, tmp;
+@@ -893,7 +893,7 @@ static int das16_cmd_test(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int das16_cmd_exec(comedi_device * dev, comedi_subdevice * s)
++static int das16_cmd_exec(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+@@ -996,7 +996,7 @@ static int das16_cmd_exec(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int das16_cancel(comedi_device * dev, comedi_subdevice * s)
++static int das16_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+ 
+@@ -1023,7 +1023,7 @@ static int das16_cancel(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static void das16_reset(comedi_device * dev)
++static void das16_reset(struct comedi_device * dev)
+ {
+ 	outb(0, dev->iobase + DAS16_STATUS);
+ 	outb(0, dev->iobase + DAS16_CONTROL);
+@@ -1031,7 +1031,7 @@ static void das16_reset(comedi_device * dev)
+ 	outb(0, dev->iobase + DAS16_CNTR_CONTROL);
+ }
+ 
+-static int das16_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int das16_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+@@ -1079,7 +1079,7 @@ static int das16_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int das16_di_rbits(comedi_device * dev, comedi_subdevice * s,
++static int das16_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bits;
+@@ -1091,7 +1091,7 @@ static int das16_di_rbits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int das16_do_wbits(comedi_device * dev, comedi_subdevice * s,
++static int das16_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int wbits;
+@@ -1111,7 +1111,7 @@ static int das16_do_wbits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int das16_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int das16_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -1138,7 +1138,7 @@ static int das16_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ static irqreturn_t das16_dma_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	int status;
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 
+ 	status = inb(dev->iobase + DAS16_STATUS);
+ 
+@@ -1155,7 +1155,7 @@ static irqreturn_t das16_dma_interrupt(int irq, void *d PT_REGS_ARG)
+ 
+ static void das16_timer_interrupt(unsigned long arg)
+ {
+-	comedi_device *dev = (comedi_device *) arg;
++	struct comedi_device *dev = (struct comedi_device *) arg;
+ 
+ 	das16_interrupt(dev);
+ 
+@@ -1169,7 +1169,7 @@ static void das16_timer_interrupt(unsigned long arg)
+ 	an even transfer count after disabling dma
+ 	channel.
+ */
+-static int disable_dma_on_even(comedi_device * dev)
++static int disable_dma_on_even(struct comedi_device * dev)
+ {
+ 	int residue;
+ 	int i;
+@@ -1197,7 +1197,7 @@ static int disable_dma_on_even(comedi_device * dev)
+ 	return residue;
+ }
+ 
+-static void das16_interrupt(comedi_device * dev)
++static void das16_interrupt(struct comedi_device * dev)
+ {
+ 	unsigned long dma_flags, spin_flags;
+ 	comedi_subdevice *s = dev->read_subdev;
+@@ -1273,7 +1273,7 @@ static void das16_interrupt(comedi_device * dev)
+ 	cfc_handle_events(dev, s);
+ }
+ 
+-static unsigned int das16_set_pacer(comedi_device * dev, unsigned int ns,
++static unsigned int das16_set_pacer(struct comedi_device * dev, unsigned int ns,
+ 	int rounding_flags)
+ {
+ 	i8253_cascade_ns_to_timer_2div(devpriv->clockbase, &(devpriv->divisor1),
+@@ -1286,7 +1286,7 @@ static unsigned int das16_set_pacer(comedi_device * dev, unsigned int ns,
+ 	return ns;
+ }
+ 
+-static void reg_dump(comedi_device * dev)
++static void reg_dump(struct comedi_device * dev)
+ {
+ 	DEBUG_PRINT("********DAS1600 REGISTER DUMP********\n");
+ 	DEBUG_PRINT("DAS16_MUX: %x\n", inb(dev->iobase + DAS16_MUX));
+@@ -1304,7 +1304,7 @@ static void reg_dump(comedi_device * dev)
+ 		inb(dev->iobase + DAS1600_STATUS_B));
+ }
+ 
+-static int das16_probe(comedi_device * dev, comedi_devconfig * it)
++static int das16_probe(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int status;
+ 	int diobits;
+@@ -1338,7 +1338,7 @@ static int das16_probe(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int das1600_mode_detect(comedi_device * dev)
++static int das1600_mode_detect(struct comedi_device * dev)
+ {
+ 	int status = 0;
+ 
+@@ -1366,7 +1366,7 @@ static int das1600_mode_detect(comedi_device * dev)
+  *   3  Clock speed (in MHz)
+  */
+ 
+-static int das16_attach(comedi_device * dev, comedi_devconfig * it)
++static int das16_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	int ret;
+@@ -1630,7 +1630,7 @@ static int das16_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int das16_detach(comedi_device * dev)
++static int das16_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: das16: remove\n", dev->minor);
+ 
+@@ -1674,7 +1674,7 @@ static int das16_detach(comedi_device * dev)
+ COMEDI_INITCLEANUP(driver_das16);
+ 
+ // utility function that suggests a dma transfer size in bytes
+-static unsigned int das16_suggest_transfer_size(comedi_device * dev,
++static unsigned int das16_suggest_transfer_size(struct comedi_device * dev,
+ 	comedi_cmd cmd)
+ {
+ 	unsigned int size;
+@@ -1715,7 +1715,7 @@ static unsigned int das16_suggest_transfer_size(comedi_device * dev,
+ 	return size;
+ }
+ 
+-static void das16_ai_munge(comedi_device * dev, comedi_subdevice * s,
++static void das16_ai_munge(struct comedi_device * dev, comedi_subdevice * s,
+ 	void *array, unsigned int num_bytes, unsigned int start_chan_index)
+ {
+ 	unsigned int i, num_samples = num_bytes / sizeof(short);
+diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
+index addccba3c6e8..f646eb16d0c9 100644
+--- a/drivers/staging/comedi/drivers/das16m1.c
++++ b/drivers/staging/comedi/drivers/das16m1.c
+@@ -131,23 +131,23 @@ static const comedi_lrange range_das16m1 = { 9,
+ 		}
+ };
+ 
+-static int das16m1_do_wbits(comedi_device * dev, comedi_subdevice * s,
++static int das16m1_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das16m1_di_rbits(comedi_device * dev, comedi_subdevice * s,
++static int das16m1_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das16m1_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int das16m1_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int das16m1_cmd_test(comedi_device * dev, comedi_subdevice * s,
++static int das16m1_cmd_test(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int das16m1_cmd_exec(comedi_device * dev, comedi_subdevice * s);
+-static int das16m1_cancel(comedi_device * dev, comedi_subdevice * s);
++static int das16m1_cmd_exec(struct comedi_device * dev, comedi_subdevice * s);
++static int das16m1_cancel(struct comedi_device * dev, comedi_subdevice * s);
+ 
+-static int das16m1_poll(comedi_device * dev, comedi_subdevice * s);
++static int das16m1_poll(struct comedi_device * dev, comedi_subdevice * s);
+ static irqreturn_t das16m1_interrupt(int irq, void *d PT_REGS_ARG);
+-static void das16m1_handler(comedi_device * dev, unsigned int status);
++static void das16m1_handler(struct comedi_device * dev, unsigned int status);
+ 
+-static unsigned int das16m1_set_pacer(comedi_device * dev, unsigned int ns,
++static unsigned int das16m1_set_pacer(struct comedi_device * dev, unsigned int ns,
+ 	int round_flag);
+ 
+ static int das16m1_irq_bits(unsigned int irq);
+@@ -166,8 +166,8 @@ static const das16m1_board das16m1_boards[] = {
+ 
+ #define das16m1_num_boards ((sizeof(das16m1_boards)) / (sizeof(das16m1_boards[0])))
+ 
+-static int das16m1_attach(comedi_device * dev, comedi_devconfig * it);
+-static int das16m1_detach(comedi_device * dev);
++static int das16m1_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int das16m1_detach(struct comedi_device * dev);
+ static comedi_driver driver_das16m1 = {
+       driver_name:"das16m1",
+       module:THIS_MODULE,
+@@ -200,7 +200,7 @@ static inline short munge_sample(short data)
+ 	return (data >> 4) & 0xfff;
+ }
+ 
+-static int das16m1_cmd_test(comedi_device * dev, comedi_subdevice * s,
++static int das16m1_cmd_test(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	unsigned int err = 0, tmp, i;
+@@ -322,7 +322,7 @@ static int das16m1_cmd_test(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int das16m1_cmd_exec(comedi_device * dev, comedi_subdevice * s)
++static int das16m1_cmd_exec(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+@@ -385,7 +385,7 @@ static int das16m1_cmd_exec(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int das16m1_cancel(comedi_device * dev, comedi_subdevice * s)
++static int das16m1_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	devpriv->control_state &= ~INTE & ~PACER_MASK;
+ 	outb(devpriv->control_state, dev->iobase + DAS16M1_INTR_CONTROL);
+@@ -393,7 +393,7 @@ static int das16m1_cancel(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int das16m1_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int das16m1_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+@@ -430,7 +430,7 @@ static int das16m1_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int das16m1_di_rbits(comedi_device * dev, comedi_subdevice * s,
++static int das16m1_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bits;
+@@ -442,7 +442,7 @@ static int das16m1_di_rbits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int das16m1_do_wbits(comedi_device * dev, comedi_subdevice * s,
++static int das16m1_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int wbits;
+@@ -462,7 +462,7 @@ static int das16m1_do_wbits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int das16m1_poll(comedi_device * dev, comedi_subdevice * s)
++static int das16m1_poll(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+ 	unsigned int status;
+@@ -479,7 +479,7 @@ static int das16m1_poll(comedi_device * dev, comedi_subdevice * s)
+ static irqreturn_t das16m1_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	int status;
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 
+ 	if (dev->attached == 0) {
+ 		comedi_error(dev, "premature interrupt");
+@@ -514,7 +514,7 @@ static void munge_sample_array(short * array, unsigned int num_elements)
+ 	}
+ }
+ 
+-static void das16m1_handler(comedi_device * dev, unsigned int status)
++static void das16m1_handler(struct comedi_device * dev, unsigned int status)
+ {
+ 	comedi_subdevice *s;
+ 	comedi_async *async;
+@@ -578,7 +578,7 @@ static void das16m1_handler(comedi_device * dev, unsigned int status)
+ /* This function takes a time in nanoseconds and sets the     *
+  * 2 pacer clocks to the closest frequency possible. It also  *
+  * returns the actual sampling period.                        */
+-static unsigned int das16m1_set_pacer(comedi_device * dev, unsigned int ns,
++static unsigned int das16m1_set_pacer(struct comedi_device * dev, unsigned int ns,
+ 	int rounding_flags)
+ {
+ 	i8253_cascade_ns_to_timer_2div(DAS16M1_XTAL, &(devpriv->divisor1),
+@@ -635,7 +635,7 @@ static int das16m1_irq_bits(unsigned int irq)
+  *   1  IRQ
+  */
+ 
+-static int das16m1_attach(comedi_device * dev, comedi_devconfig * it)
++static int das16m1_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	int ret;
+@@ -744,7 +744,7 @@ static int das16m1_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int das16m1_detach(comedi_device * dev)
++static int das16m1_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: das16m1: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
+index f66cf17bbbcd..9fb800fbfc15 100644
+--- a/drivers/staging/comedi/drivers/das1800.c
++++ b/drivers/staging/comedi/drivers/das1800.c
+@@ -180,35 +180,35 @@ enum {
+ 	das1802hr, das1802hr_da, das1801hc, das1802hc, das1801ao, das1802ao
+ };
+ 
+-static int das1800_attach(comedi_device * dev, comedi_devconfig * it);
+-static int das1800_detach(comedi_device * dev);
+-static int das1800_probe(comedi_device * dev);
+-static int das1800_cancel(comedi_device * dev, comedi_subdevice * s);
++static int das1800_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int das1800_detach(struct comedi_device * dev);
++static int das1800_probe(struct comedi_device * dev);
++static int das1800_cancel(struct comedi_device * dev, comedi_subdevice * s);
+ static irqreturn_t das1800_interrupt(int irq, void *d PT_REGS_ARG);
+-static int das1800_ai_poll(comedi_device * dev, comedi_subdevice * s);
+-static void das1800_ai_handler(comedi_device * dev);
+-static void das1800_handle_dma(comedi_device * dev, comedi_subdevice * s,
++static int das1800_ai_poll(struct comedi_device * dev, comedi_subdevice * s);
++static void das1800_ai_handler(struct comedi_device * dev);
++static void das1800_handle_dma(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int status);
+-static void das1800_flush_dma(comedi_device * dev, comedi_subdevice * s);
+-static void das1800_flush_dma_channel(comedi_device * dev, comedi_subdevice * s,
++static void das1800_flush_dma(struct comedi_device * dev, comedi_subdevice * s);
++static void das1800_flush_dma_channel(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int channel, uint16_t * buffer);
+-static void das1800_handle_fifo_half_full(comedi_device * dev,
++static void das1800_handle_fifo_half_full(struct comedi_device * dev,
+ 	comedi_subdevice * s);
+-static void das1800_handle_fifo_not_empty(comedi_device * dev,
++static void das1800_handle_fifo_not_empty(struct comedi_device * dev,
+ 	comedi_subdevice * s);
+-static int das1800_ai_do_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int das1800_ai_do_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int das1800_ai_do_cmd(comedi_device * dev, comedi_subdevice * s);
+-static int das1800_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int das1800_ai_do_cmd(struct comedi_device * dev, comedi_subdevice * s);
++static int das1800_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das1800_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int das1800_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das1800_di_rbits(comedi_device * dev, comedi_subdevice * s,
++static int das1800_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das1800_do_wbits(comedi_device * dev, comedi_subdevice * s,
++static int das1800_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int das1800_set_frequency(comedi_device * dev);
++static int das1800_set_frequency(struct comedi_device * dev);
+ static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode);
+ static unsigned int suggest_transfer_size(comedi_cmd * cmd);
+ 
+@@ -520,7 +520,7 @@ static comedi_driver driver_das1800 = {
+  */
+ COMEDI_INITCLEANUP(driver_das1800);
+ 
+-static int das1800_init_dma(comedi_device * dev, unsigned int dma0,
++static int das1800_init_dma(struct comedi_device * dev, unsigned int dma0,
+ 	unsigned int dma1)
+ {
+ 	unsigned long flags;
+@@ -590,7 +590,7 @@ static int das1800_init_dma(comedi_device * dev, unsigned int dma0,
+ 	return 0;
+ }
+ 
+-static int das1800_attach(comedi_device * dev, comedi_devconfig * it)
++static int das1800_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	unsigned long iobase = it->options[0];
+@@ -765,7 +765,7 @@ static int das1800_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ };
+ 
+-static int das1800_detach(comedi_device * dev)
++static int das1800_detach(struct comedi_device * dev)
+ {
+ 	/* only free stuff if it has been allocated by _attach */
+ 	if (dev->iobase)
+@@ -793,7 +793,7 @@ static int das1800_detach(comedi_device * dev)
+ 
+ /* probes and checks das-1800 series board type
+  */
+-static int das1800_probe(comedi_device * dev)
++static int das1800_probe(struct comedi_device * dev)
+ {
+ 	int id;
+ 	int board;
+@@ -867,7 +867,7 @@ static int das1800_probe(comedi_device * dev)
+ 	return -1;
+ }
+ 
+-static int das1800_ai_poll(comedi_device * dev, comedi_subdevice * s)
++static int das1800_ai_poll(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+ 
+@@ -881,7 +881,7 @@ static int das1800_ai_poll(comedi_device * dev, comedi_subdevice * s)
+ 
+ static irqreturn_t das1800_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	unsigned int status;
+ 
+ 	if (dev->attached == 0) {
+@@ -909,7 +909,7 @@ static irqreturn_t das1800_interrupt(int irq, void *d PT_REGS_ARG)
+ }
+ 
+ // the guts of the interrupt handler, that is shared with das1800_ai_poll
+-static void das1800_ai_handler(comedi_device * dev)
++static void das1800_ai_handler(struct comedi_device * dev)
+ {
+ 	comedi_subdevice *s = dev->subdevices + 0;	/* analog input subdevice */
+ 	comedi_async *async = s->async;
+@@ -962,7 +962,7 @@ static void das1800_ai_handler(comedi_device * dev)
+ 	return;
+ }
+ 
+-static void das1800_handle_dma(comedi_device * dev, comedi_subdevice * s,
++static void das1800_handle_dma(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int status)
+ {
+ 	unsigned long flags;
+@@ -997,14 +997,14 @@ static void das1800_handle_dma(comedi_device * dev, comedi_subdevice * s,
+ 	return;
+ }
+ 
+-static inline uint16_t munge_bipolar_sample(const comedi_device * dev,
++static inline uint16_t munge_bipolar_sample(const struct comedi_device * dev,
+ 	uint16_t sample)
+ {
+ 	sample += 1 << (thisboard->resolution - 1);
+ 	return sample;
+ }
+ 
+-static void munge_data(comedi_device * dev, uint16_t * array,
++static void munge_data(struct comedi_device * dev, uint16_t * array,
+ 	unsigned int num_elements)
+ {
+ 	unsigned int i;
+@@ -1023,7 +1023,7 @@ static void munge_data(comedi_device * dev, uint16_t * array,
+ 
+ /* Utility function used by das1800_flush_dma() and das1800_handle_dma().
+  * Assumes dma lock is held */
+-static void das1800_flush_dma_channel(comedi_device * dev, comedi_subdevice * s,
++static void das1800_flush_dma_channel(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int channel, uint16_t * buffer)
+ {
+ 	unsigned int num_bytes, num_samples;
+@@ -1053,7 +1053,7 @@ static void das1800_flush_dma_channel(comedi_device * dev, comedi_subdevice * s,
+ 
+ /* flushes remaining data from board when external trigger has stopped aquisition
+  * and we are using dma transfers */
+-static void das1800_flush_dma(comedi_device * dev, comedi_subdevice * s)
++static void das1800_flush_dma(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+ 	const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
+@@ -1083,7 +1083,7 @@ static void das1800_flush_dma(comedi_device * dev, comedi_subdevice * s)
+ 	return;
+ }
+ 
+-static void das1800_handle_fifo_half_full(comedi_device * dev,
++static void das1800_handle_fifo_half_full(struct comedi_device * dev,
+ 	comedi_subdevice * s)
+ {
+ 	int numPoints = 0;	/* number of points to read */
+@@ -1102,7 +1102,7 @@ static void das1800_handle_fifo_half_full(comedi_device * dev,
+ 	return;
+ }
+ 
+-static void das1800_handle_fifo_not_empty(comedi_device * dev,
++static void das1800_handle_fifo_not_empty(struct comedi_device * dev,
+ 	comedi_subdevice * s)
+ {
+ 	short dpnt;
+@@ -1126,7 +1126,7 @@ static void das1800_handle_fifo_not_empty(comedi_device * dev,
+ 	return;
+ }
+ 
+-static int das1800_cancel(comedi_device * dev, comedi_subdevice * s)
++static int das1800_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	outb(0x0, dev->iobase + DAS1800_STATUS);	/* disable conversions */
+ 	outb(0x0, dev->iobase + DAS1800_CONTROL_B);	/* disable interrupts and dma */
+@@ -1139,7 +1139,7 @@ static int das1800_cancel(comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ /* test analog input cmd */
+-static int das1800_ai_do_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int das1800_ai_do_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -1385,7 +1385,7 @@ static int control_c_bits(comedi_cmd cmd)
+ }
+ 
+ // sets up counters
+-static int setup_counters(comedi_device * dev, comedi_cmd cmd)
++static int setup_counters(struct comedi_device * dev, comedi_cmd cmd)
+ {
+ 	// setup cascaded counters for conversion/scan frequency
+ 	switch (cmd.scan_begin_src) {
+@@ -1424,7 +1424,7 @@ static int setup_counters(comedi_device * dev, comedi_cmd cmd)
+ }
+ 
+ // sets up dma
+-static void setup_dma(comedi_device * dev, comedi_cmd cmd)
++static void setup_dma(struct comedi_device * dev, comedi_cmd cmd)
+ {
+ 	unsigned long lock_flags;
+ 	const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
+@@ -1462,7 +1462,7 @@ static void setup_dma(comedi_device * dev, comedi_cmd cmd)
+ }
+ 
+ // programs channel/gain list into card
+-static void program_chanlist(comedi_device * dev, comedi_cmd cmd)
++static void program_chanlist(struct comedi_device * dev, comedi_cmd cmd)
+ {
+ 	int i, n, chan_range;
+ 	unsigned long irq_flags;
+@@ -1489,7 +1489,7 @@ static void program_chanlist(comedi_device * dev, comedi_cmd cmd)
+ }
+ 
+ // analog input do_cmd
+-static int das1800_ai_do_cmd(comedi_device * dev, comedi_subdevice * s)
++static int das1800_ai_do_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	int ret;
+ 	int control_a, control_c;
+@@ -1552,7 +1552,7 @@ static int das1800_ai_do_cmd(comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ /* read analog input */
+-static int das1800_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int das1800_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+@@ -1612,7 +1612,7 @@ static int das1800_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ /* writes to an analog output channel */
+-static int das1800_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int das1800_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -1641,7 +1641,7 @@ static int das1800_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ /* reads from digital input channels */
+-static int das1800_di_rbits(comedi_device * dev, comedi_subdevice * s,
++static int das1800_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -1652,7 +1652,7 @@ static int das1800_di_rbits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ /* writes to digital output channels */
+-static int das1800_do_wbits(comedi_device * dev, comedi_subdevice * s,
++static int das1800_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int wbits;
+@@ -1672,7 +1672,7 @@ static int das1800_do_wbits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ /* loads counters with divisor1, divisor2 from private structure */
+-static int das1800_set_frequency(comedi_device * dev)
++static int das1800_set_frequency(struct comedi_device * dev)
+ {
+ 	int err = 0;
+ 
+diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c
+index 85959c09679f..e78d9eb0eb7a 100644
+--- a/drivers/staging/comedi/drivers/das6402.c
++++ b/drivers/staging/comedi/drivers/das6402.c
+@@ -98,8 +98,8 @@ This driver has suffered bitrot.
+ #define	C2 0x80
+ #define	RWLH 0x30
+ 
+-static int das6402_attach(comedi_device * dev, comedi_devconfig * it);
+-static int das6402_detach(comedi_device * dev);
++static int das6402_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int das6402_detach(struct comedi_device * dev);
+ static comedi_driver driver_das6402 = {
+       driver_name:"das6402",
+       module:THIS_MODULE,
+@@ -116,9 +116,9 @@ typedef struct {
+ } das6402_private;
+ #define devpriv ((das6402_private *)dev->private)
+ 
+-static void das6402_ai_fifo_dregs(comedi_device * dev, comedi_subdevice * s);
++static void das6402_ai_fifo_dregs(struct comedi_device * dev, comedi_subdevice * s);
+ 
+-static void das6402_setcounter(comedi_device * dev)
++static void das6402_setcounter(struct comedi_device * dev)
+ {
+ 	BYTE p;
+ 	unsigned short ctrlwrd;
+@@ -153,7 +153,7 @@ static void das6402_setcounter(comedi_device * dev)
+ 
+ static irqreturn_t intr_handler(int irq, void *d PT_REGS_ARG)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s = dev->subdevices;
+ 
+ 	if (!dev->attached || devpriv->das6402_ignoreirq) {
+@@ -186,7 +186,7 @@ static irqreturn_t intr_handler(int irq, void *d PT_REGS_ARG)
+ }
+ 
+ #if 0
+-static void das6402_ai_fifo_read(comedi_device * dev, short * data, int n)
++static void das6402_ai_fifo_read(struct comedi_device * dev, short * data, int n)
+ {
+ 	int i;
+ 
+@@ -195,7 +195,7 @@ static void das6402_ai_fifo_read(comedi_device * dev, short * data, int n)
+ }
+ #endif
+ 
+-static void das6402_ai_fifo_dregs(comedi_device * dev, comedi_subdevice * s)
++static void das6402_ai_fifo_dregs(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	while (1) {
+ 		if (!(inb(dev->iobase + 8) & 0x01))
+@@ -204,7 +204,7 @@ static void das6402_ai_fifo_dregs(comedi_device * dev, comedi_subdevice * s)
+ 	}
+ }
+ 
+-static int das6402_ai_cancel(comedi_device * dev, comedi_subdevice * s)
++static int das6402_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	/*
+ 	 *  This function should reset the board from whatever condition it
+@@ -226,7 +226,7 @@ static int das6402_ai_cancel(comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ #ifdef unused
+-static int das6402_ai_mode2(comedi_device * dev, comedi_subdevice * s,
++static int das6402_ai_mode2(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_trig * it)
+ {
+ 	devpriv->das6402_ignoreirq = 1;
+@@ -249,7 +249,7 @@ static int das6402_ai_mode2(comedi_device * dev, comedi_subdevice * s,
+ }
+ #endif
+ 
+-static int board_init(comedi_device * dev)
++static int board_init(struct comedi_device * dev)
+ {
+ 	BYTE b;
+ 
+@@ -289,7 +289,7 @@ static int board_init(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int das6402_detach(comedi_device * dev)
++static int das6402_detach(struct comedi_device * dev)
+ {
+ 	if (dev->irq)
+ 		comedi_free_irq(dev->irq, dev);
+@@ -299,7 +299,7 @@ static int das6402_detach(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int das6402_attach(comedi_device * dev, comedi_devconfig * it)
++static int das6402_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	unsigned int irq;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
+index 7e658dbfa07a..73068309ae9c 100644
+--- a/drivers/staging/comedi/drivers/das800.c
++++ b/drivers/staging/comedi/drivers/das800.c
+@@ -242,9 +242,9 @@ typedef struct {
+ 
+ #define devpriv ((das800_private *)dev->private)
+ 
+-static int das800_attach(comedi_device * dev, comedi_devconfig * it);
+-static int das800_detach(comedi_device * dev);
+-static int das800_cancel(comedi_device * dev, comedi_subdevice * s);
++static int das800_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int das800_detach(struct comedi_device * dev);
++static int das800_cancel(struct comedi_device * dev, comedi_subdevice * s);
+ 
+ static comedi_driver driver_das800 = {
+       driver_name:"das800",
+@@ -257,22 +257,22 @@ static comedi_driver driver_das800 = {
+ };
+ 
+ static irqreturn_t das800_interrupt(int irq, void *d PT_REGS_ARG);
+-static void enable_das800(comedi_device * dev);
+-static void disable_das800(comedi_device * dev);
+-static int das800_ai_do_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static void enable_das800(struct comedi_device * dev);
++static void disable_das800(struct comedi_device * dev);
++static int das800_ai_do_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int das800_ai_do_cmd(comedi_device * dev, comedi_subdevice * s);
+-static int das800_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int das800_ai_do_cmd(struct comedi_device * dev, comedi_subdevice * s);
++static int das800_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das800_di_rbits(comedi_device * dev, comedi_subdevice * s,
++static int das800_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das800_do_wbits(comedi_device * dev, comedi_subdevice * s,
++static int das800_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int das800_probe(comedi_device * dev);
+-static int das800_set_frequency(comedi_device * dev);
++static int das800_probe(struct comedi_device * dev);
++static int das800_set_frequency(struct comedi_device * dev);
+ 
+ /* checks and probes das-800 series board type */
+-static int das800_probe(comedi_device * dev)
++static int das800_probe(struct comedi_device * dev)
+ {
+ 	int id_bits;
+ 	unsigned long irq_flags;
+@@ -347,7 +347,7 @@ static irqreturn_t das800_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	short i;		/* loop index */
+ 	short dataPoint = 0;
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s = dev->read_subdev;	/* analog input subdevice */
+ 	comedi_async *async;
+ 	int status;
+@@ -441,7 +441,7 @@ static irqreturn_t das800_interrupt(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int das800_attach(comedi_device * dev, comedi_devconfig * it)
++static int das800_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	unsigned long iobase = it->options[0];
+@@ -539,7 +539,7 @@ static int das800_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ };
+ 
+-static int das800_detach(comedi_device * dev)
++static int das800_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: das800: remove\n", dev->minor);
+ 
+@@ -551,7 +551,7 @@ static int das800_detach(comedi_device * dev)
+ 	return 0;
+ };
+ 
+-static int das800_cancel(comedi_device * dev, comedi_subdevice * s)
++static int das800_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	devpriv->forever = 0;
+ 	devpriv->count = 0;
+@@ -560,7 +560,7 @@ static int das800_cancel(comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ /* enable_das800 makes the card start taking hardware triggered conversions */
+-static void enable_das800(comedi_device * dev)
++static void enable_das800(struct comedi_device * dev)
+ {
+ 	unsigned long irq_flags;
+ 	comedi_spin_lock_irqsave(&dev->spinlock, irq_flags);
+@@ -575,7 +575,7 @@ static void enable_das800(comedi_device * dev)
+ }
+ 
+ /* disable_das800 stops hardware triggered conversions */
+-static void disable_das800(comedi_device * dev)
++static void disable_das800(struct comedi_device * dev)
+ {
+ 	unsigned long irq_flags;
+ 	comedi_spin_lock_irqsave(&dev->spinlock, irq_flags);
+@@ -584,7 +584,7 @@ static void disable_das800(comedi_device * dev)
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags);
+ }
+ 
+-static int das800_ai_do_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int das800_ai_do_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -709,7 +709,7 @@ static int das800_ai_do_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int das800_ai_do_cmd(comedi_device * dev, comedi_subdevice * s)
++static int das800_ai_do_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	int startChan, endChan, scan, gain;
+ 	int conv_bits;
+@@ -788,7 +788,7 @@ static int das800_ai_do_cmd(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int das800_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int das800_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+@@ -842,7 +842,7 @@ static int das800_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int das800_di_rbits(comedi_device * dev, comedi_subdevice * s,
++static int das800_di_rbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bits;
+@@ -855,7 +855,7 @@ static int das800_di_rbits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int das800_do_wbits(comedi_device * dev, comedi_subdevice * s,
++static int das800_do_wbits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int wbits;
+@@ -879,7 +879,7 @@ static int das800_do_wbits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ /* loads counters with divisor1, divisor2 from private structure */
+-static int das800_set_frequency(comedi_device * dev)
++static int das800_set_frequency(struct comedi_device * dev)
+ {
+ 	int err = 0;
+ 
+diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
+index c63af0c556b4..678eb970a034 100644
+--- a/drivers/staging/comedi/drivers/dmm32at.c
++++ b/drivers/staging/comedi/drivers/dmm32at.c
+@@ -232,7 +232,7 @@ static const dmm32at_board dmm32at_boards[] = {
+ 
+ /* this structure is for data unique to this hardware driver.  If
+  * several hardware drivers keep similar information in this structure,
+- * feel free to suggest moving the variable to the comedi_device struct.
++ * feel free to suggest moving the variable to the struct comedi_device struct.
+  */
+ typedef struct {
+ 
+@@ -258,8 +258,8 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int dmm32at_attach(comedi_device * dev, comedi_devconfig * it);
+-static int dmm32at_detach(comedi_device * dev);
++static int dmm32at_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int dmm32at_detach(struct comedi_device * dev);
+ static comedi_driver driver_dmm32at = {
+       driver_name:"dmm32at",
+       module:THIS_MODULE,
+@@ -289,23 +289,23 @@ static comedi_driver driver_dmm32at = {
+ };
+ 
+ /* prototypes for driver functions below */
+-static int dmm32at_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int dmm32at_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dmm32at_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int dmm32at_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dmm32at_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int dmm32at_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dmm32at_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int dmm32at_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dmm32at_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int dmm32at_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dmm32at_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int dmm32at_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int dmm32at_ai_cmd(comedi_device * dev, comedi_subdevice * s);
+-static int dmm32at_ai_cancel(comedi_device * dev, comedi_subdevice * s);
++static int dmm32at_ai_cmd(struct comedi_device * dev, comedi_subdevice * s);
++static int dmm32at_ai_cancel(struct comedi_device * dev, comedi_subdevice * s);
+ static int dmm32at_ns_to_timer(unsigned int *ns, int round);
+ static irqreturn_t dmm32at_isr(int irq, void *d PT_REGS_ARG);
+-void dmm32at_setaitimer(comedi_device * dev, unsigned int nansec);
++void dmm32at_setaitimer(struct comedi_device * dev, unsigned int nansec);
+ 
+ /*
+  * Attach is called by the Comedi core to configure the driver
+@@ -313,7 +313,7 @@ void dmm32at_setaitimer(comedi_device * dev, unsigned int nansec);
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int dmm32at_attach(comedi_device * dev, comedi_devconfig * it)
++static int dmm32at_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int ret;
+ 	comedi_subdevice *s;
+@@ -481,7 +481,7 @@ static int dmm32at_attach(comedi_device * dev, comedi_devconfig * it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int dmm32at_detach(comedi_device * dev)
++static int dmm32at_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: dmm32at: remove\n", dev->minor);
+ 	if (dev->irq)
+@@ -497,7 +497,7 @@ static int dmm32at_detach(comedi_device * dev)
+  * mode.
+  */
+ 
+-static int dmm32at_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int dmm32at_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i;
+@@ -568,7 +568,7 @@ static int dmm32at_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int dmm32at_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int dmm32at_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -752,7 +752,7 @@ static int dmm32at_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int dmm32at_ai_cmd(comedi_device * dev, comedi_subdevice * s)
++static int dmm32at_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	int i, range;
+@@ -822,7 +822,7 @@ static int dmm32at_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ 
+ }
+ 
+-static int dmm32at_ai_cancel(comedi_device * dev, comedi_subdevice * s)
++static int dmm32at_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	devpriv->ai_scans_left = 1;
+ 	return 0;
+@@ -834,7 +834,7 @@ static irqreturn_t dmm32at_isr(int irq, void *d PT_REGS_ARG)
+ 	unsigned int samp;
+ 	unsigned short msb, lsb;
+ 	int i;
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 
+ 	if (!dev->attached) {
+ 		comedi_error(dev, "spurious interrupt");
+@@ -893,7 +893,7 @@ static int dmm32at_ns_to_timer(unsigned int *ns, int round)
+ 	return *ns;
+ }
+ 
+-static int dmm32at_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int dmm32at_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -936,7 +936,7 @@ static int dmm32at_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ 
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+-static int dmm32at_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int dmm32at_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -953,7 +953,7 @@ static int dmm32at_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+  * useful to applications if you implement the insn_bits interface.
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+-static int dmm32at_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int dmm32at_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned char diobits;
+@@ -1006,7 +1006,7 @@ static int dmm32at_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int dmm32at_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int dmm32at_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned char chanbit;
+@@ -1043,7 +1043,7 @@ static int dmm32at_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-void dmm32at_setaitimer(comedi_device * dev, unsigned int nansec)
++void dmm32at_setaitimer(struct comedi_device * dev, unsigned int nansec)
+ {
+ 	unsigned char lo1, lo2, hi2;
+ 	unsigned short both2;
+diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c
+index 4ee1199920e1..364102436d6e 100644
+--- a/drivers/staging/comedi/drivers/dt2801.c
++++ b/drivers/staging/comedi/drivers/dt2801.c
+@@ -88,8 +88,8 @@ Configuration options:
+ #define DT2801_STATUS		1
+ #define DT2801_CMD		1
+ 
+-static int dt2801_attach(comedi_device * dev, comedi_devconfig * it);
+-static int dt2801_detach(comedi_device * dev);
++static int dt2801_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int dt2801_detach(struct comedi_device * dev);
+ static comedi_driver driver_dt2801 = {
+       driver_name:"dt2801",
+       module:THIS_MODULE,
+@@ -224,15 +224,15 @@ typedef struct {
+ } dt2801_private;
+ #define devpriv ((dt2801_private *)dev->private)
+ 
+-static int dt2801_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int dt2801_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dt2801_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int dt2801_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dt2801_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
++static int dt2801_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dt2801_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int dt2801_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dt2801_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int dt2801_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ /* These are the low-level routines:
+@@ -244,7 +244,7 @@ static int dt2801_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+ /* Only checks DataOutReady-flag, not the Ready-flag as it is done
+    in the examples of the manual. I don't see why this should be
+    necessary. */
+-static int dt2801_readdata(comedi_device * dev, int *data)
++static int dt2801_readdata(struct comedi_device * dev, int *data)
+ {
+ 	int stat = 0;
+ 	int timeout = DT2801_TIMEOUT;
+@@ -263,7 +263,7 @@ static int dt2801_readdata(comedi_device * dev, int *data)
+ 	return -ETIME;
+ }
+ 
+-static int dt2801_readdata2(comedi_device * dev, int *data)
++static int dt2801_readdata2(struct comedi_device * dev, int *data)
+ {
+ 	int lb, hb;
+ 	int ret;
+@@ -279,7 +279,7 @@ static int dt2801_readdata2(comedi_device * dev, int *data)
+ 	return 0;
+ }
+ 
+-static int dt2801_writedata(comedi_device * dev, unsigned int data)
++static int dt2801_writedata(struct comedi_device * dev, unsigned int data)
+ {
+ 	int stat = 0;
+ 	int timeout = DT2801_TIMEOUT;
+@@ -305,7 +305,7 @@ static int dt2801_writedata(comedi_device * dev, unsigned int data)
+ 	return -ETIME;
+ }
+ 
+-static int dt2801_writedata2(comedi_device * dev, unsigned int data)
++static int dt2801_writedata2(struct comedi_device * dev, unsigned int data)
+ {
+ 	int ret;
+ 
+@@ -319,7 +319,7 @@ static int dt2801_writedata2(comedi_device * dev, unsigned int data)
+ 	return 0;
+ }
+ 
+-static int dt2801_wait_for_ready(comedi_device * dev)
++static int dt2801_wait_for_ready(struct comedi_device * dev)
+ {
+ 	int timeout = DT2801_TIMEOUT;
+ 	int stat;
+@@ -342,7 +342,7 @@ static int dt2801_wait_for_ready(comedi_device * dev)
+ 	return -ETIME;
+ }
+ 
+-static int dt2801_writecmd(comedi_device * dev, int command)
++static int dt2801_writecmd(struct comedi_device * dev, int command)
+ {
+ 	int stat;
+ 
+@@ -360,7 +360,7 @@ static int dt2801_writecmd(comedi_device * dev, int command)
+ 	return 0;
+ }
+ 
+-static int dt2801_reset(comedi_device * dev)
++static int dt2801_reset(struct comedi_device * dev)
+ {
+ 	int board_code = 0;
+ 	unsigned int stat;
+@@ -417,7 +417,7 @@ static int dt2801_reset(comedi_device * dev)
+ 	return board_code;
+ }
+ 
+-static int probe_number_of_ai_chans(comedi_device * dev)
++static int probe_number_of_ai_chans(struct comedi_device * dev)
+ {
+ 	int n_chans;
+ 	int stat;
+@@ -478,7 +478,7 @@ static const comedi_lrange *ai_range_lkup(int type, int opt)
+ 	[4] - dac0 range 0=[-10,10], 1=[-5,5], 2=[-2.5,2.5] 3=[0,10], 4=[0,5]
+ 	[5] - dac1 range 0=[-10,10], 1=[-5,5], 2=[-2.5,2.5] 3=[0,10], 4=[0,5]
+ */
+-static int dt2801_attach(comedi_device * dev, comedi_devconfig * it)
++static int dt2801_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	unsigned long iobase;
+@@ -579,7 +579,7 @@ static int dt2801_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return ret;
+ }
+ 
+-static int dt2801_detach(comedi_device * dev)
++static int dt2801_detach(struct comedi_device * dev)
+ {
+ 	if (dev->iobase)
+ 		release_region(dev->iobase, DT2801_IOSIZE);
+@@ -587,7 +587,7 @@ static int dt2801_detach(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int dt2801_error(comedi_device * dev, int stat)
++static int dt2801_error(struct comedi_device * dev, int stat)
+ {
+ 	if (stat < 0) {
+ 		if (stat == -ETIME) {
+@@ -605,7 +605,7 @@ static int dt2801_error(comedi_device * dev, int stat)
+ 	return -EIO;
+ }
+ 
+-static int dt2801_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int dt2801_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int d;
+@@ -627,7 +627,7 @@ static int dt2801_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int dt2801_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int dt2801_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->ao_readback[CR_CHAN(insn->chanspec)];
+@@ -635,7 +635,7 @@ static int dt2801_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int dt2801_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
++static int dt2801_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	dt2801_writecmd(dev, DT_C_WRITE_DAIM);
+@@ -647,7 +647,7 @@ static int dt2801_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int dt2801_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int dt2801_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int which = 0;
+@@ -671,7 +671,7 @@ static int dt2801_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int dt2801_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int dt2801_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int which = 0;
+diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c
+index ce7cf31f2fc9..76c084ca081b 100644
+--- a/drivers/staging/comedi/drivers/dt2811.c
++++ b/drivers/staging/comedi/drivers/dt2811.c
+@@ -212,8 +212,8 @@ static const boardtype boardtypes[] = {
+ 
+ #define this_board ((const boardtype *)dev->board_ptr)
+ 
+-static int dt2811_attach(comedi_device * dev, comedi_devconfig * it);
+-static int dt2811_detach(comedi_device * dev);
++static int dt2811_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int dt2811_detach(struct comedi_device * dev);
+ static comedi_driver driver_dt2811 = {
+       driver_name:"dt2811",
+       module:THIS_MODULE,
+@@ -226,15 +226,15 @@ static comedi_driver driver_dt2811 = {
+ 
+ COMEDI_INITCLEANUP(driver_dt2811);
+ 
+-static int dt2811_ai_insn(comedi_device * dev, comedi_subdevice * s,
++static int dt2811_ai_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dt2811_ao_insn(comedi_device * dev, comedi_subdevice * s,
++static int dt2811_ao_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dt2811_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int dt2811_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dt2811_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int dt2811_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int dt2811_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int dt2811_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ enum { card_2811_pgh, card_2811_pgl };
+@@ -266,7 +266,7 @@ static irqreturn_t dt2811_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	int lo, hi;
+ 	int data;
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 
+ 	if (!dev->attached) {
+ 		comedi_error(dev, "spurious interrupt");
+@@ -308,7 +308,7 @@ static irqreturn_t dt2811_interrupt(int irq, void *d PT_REGS_ARG)
+                  2 == unipolar 5V  (0V -- +5V)
+ */
+ 
+-static int dt2811_attach(comedi_device * dev, comedi_devconfig * it)
++static int dt2811_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	//int i, irq;
+ 	//unsigned long irqs;
+@@ -476,7 +476,7 @@ static int dt2811_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int dt2811_detach(comedi_device * dev)
++static int dt2811_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: dt2811: remove\n", dev->minor);
+ 
+@@ -490,7 +490,7 @@ static int dt2811_detach(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int dt2811_ai_insn(comedi_device * dev, comedi_subdevice * s,
++static int dt2811_ai_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -519,7 +519,7 @@ static int dt2811_ai_insn(comedi_device * dev, comedi_subdevice * s,
+  * replaced, so I'll let it stay. */
+ int dt2811_adtrig(kdev_t minor, comedi_adtrig * adtrig)
+ {
+-	comedi_device *dev = comedi_devices + minor;
++	struct comedi_device *dev = comedi_devices + minor;
+ 
+ 	if (adtrig->n < 1)
+ 		return 0;
+@@ -541,7 +541,7 @@ int dt2811_adtrig(kdev_t minor, comedi_adtrig * adtrig)
+ }
+ #endif
+ 
+-static int dt2811_ao_insn(comedi_device * dev, comedi_subdevice * s,
++static int dt2811_ao_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -559,7 +559,7 @@ static int dt2811_ao_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int dt2811_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int dt2811_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -574,7 +574,7 @@ static int dt2811_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int dt2811_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int dt2811_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -585,7 +585,7 @@ static int dt2811_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int dt2811_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int dt2811_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c
+index bc96bf63e027..40430b5df69a 100644
+--- a/drivers/staging/comedi/drivers/dt2814.c
++++ b/drivers/staging/comedi/drivers/dt2814.c
+@@ -59,8 +59,8 @@ addition, the clock does not seem to be very accurate.
+ #define DT2814_ENB 0x10
+ #define DT2814_CHANMASK 0x0f
+ 
+-static int dt2814_attach(comedi_device * dev, comedi_devconfig * it);
+-static int dt2814_detach(comedi_device * dev);
++static int dt2814_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int dt2814_detach(struct comedi_device * dev);
+ static comedi_driver driver_dt2814 = {
+       driver_name:"dt2814",
+       module:THIS_MODULE,
+@@ -81,7 +81,7 @@ typedef struct {
+ #define DT2814_TIMEOUT 10
+ #define DT2814_MAX_SPEED 100000	/* Arbitrary 10 khz limit */
+ 
+-static int dt2814_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int dt2814_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i, hi, lo;
+@@ -132,7 +132,7 @@ static int dt2814_ns_to_timer(unsigned int *ns, unsigned int flags)
+ 	return i;
+ }
+ 
+-static int dt2814_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int dt2814_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -224,7 +224,7 @@ static int dt2814_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int dt2814_ai_cmd(comedi_device * dev, comedi_subdevice * s)
++static int dt2814_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	int chan;
+@@ -243,7 +243,7 @@ static int dt2814_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ 
+ }
+ 
+-static int dt2814_attach(comedi_device * dev, comedi_devconfig * it)
++static int dt2814_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int i, irq;
+ 	int ret;
+@@ -327,7 +327,7 @@ static int dt2814_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int dt2814_detach(comedi_device * dev)
++static int dt2814_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: dt2814: remove\n", dev->minor);
+ 
+@@ -344,7 +344,7 @@ static int dt2814_detach(comedi_device * dev)
+ static irqreturn_t dt2814_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	int lo, hi;
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s;
+ 	int data;
+ 
+diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c
+index 98a64a74c82b..892fe38d55e6 100644
+--- a/drivers/staging/comedi/drivers/dt2815.c
++++ b/drivers/staging/comedi/drivers/dt2815.c
+@@ -75,8 +75,8 @@ static const comedi_lrange range_dt2815_ao_20_current = { 1, {
+ #define DT2815_DATA 0
+ #define DT2815_STATUS 1
+ 
+-static int dt2815_attach(comedi_device * dev, comedi_devconfig * it);
+-static int dt2815_detach(comedi_device * dev);
++static int dt2815_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int dt2815_detach(struct comedi_device * dev);
+ static comedi_driver driver_dt2815 = {
+       driver_name:"dt2815",
+       module:THIS_MODULE,
+@@ -86,7 +86,7 @@ static comedi_driver driver_dt2815 = {
+ 
+ COMEDI_INITCLEANUP(driver_dt2815);
+ 
+-static void dt2815_free_resources(comedi_device * dev);
++static void dt2815_free_resources(struct comedi_device * dev);
+ 
+ typedef struct {
+ 	const comedi_lrange *range_type_list[8];
+@@ -95,7 +95,7 @@ typedef struct {
+ 
+ #define devpriv ((dt2815_private *)dev->private)
+ 
+-static int dt2815_wait_for_status(comedi_device * dev, int status)
++static int dt2815_wait_for_status(struct comedi_device * dev, int status)
+ {
+ 	int i;
+ 
+@@ -106,7 +106,7 @@ static int dt2815_wait_for_status(comedi_device * dev, int status)
+ 	return status;
+ }
+ 
+-static int dt2815_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int dt2815_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -119,7 +119,7 @@ static int dt2815_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int dt2815_ao_insn(comedi_device * dev, comedi_subdevice * s,
++static int dt2815_ao_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -177,7 +177,7 @@ static int dt2815_ao_insn(comedi_device * dev, comedi_subdevice * s,
+                  1 == current
+  */
+ 
+-static int dt2815_attach(comedi_device * dev, comedi_devconfig * it)
++static int dt2815_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	int i;
+@@ -246,13 +246,13 @@ static int dt2815_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static void dt2815_free_resources(comedi_device * dev)
++static void dt2815_free_resources(struct comedi_device * dev)
+ {
+ 	if (dev->iobase)
+ 		release_region(dev->iobase, DT2815_SIZE);
+ }
+ 
+-static int dt2815_detach(comedi_device * dev)
++static int dt2815_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: dt2815: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c
+index 77c28e7b2a11..41aa03d40cdd 100644
+--- a/drivers/staging/comedi/drivers/dt2817.c
++++ b/drivers/staging/comedi/drivers/dt2817.c
+@@ -47,8 +47,8 @@ Configuration options:
+ #define DT2817_CR 0
+ #define DT2817_DATA 1
+ 
+-static int dt2817_attach(comedi_device * dev, comedi_devconfig * it);
+-static int dt2817_detach(comedi_device * dev);
++static int dt2817_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int dt2817_detach(struct comedi_device * dev);
+ static comedi_driver driver_dt2817 = {
+       driver_name:"dt2817",
+       module:THIS_MODULE,
+@@ -58,7 +58,7 @@ static comedi_driver driver_dt2817 = {
+ 
+ COMEDI_INITCLEANUP(driver_dt2817);
+ 
+-static int dt2817_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int dt2817_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int mask;
+@@ -96,7 +96,7 @@ static int dt2817_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int dt2817_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int dt2817_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int changed;
+@@ -131,7 +131,7 @@ static int dt2817_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int dt2817_attach(comedi_device * dev, comedi_devconfig * it)
++static int dt2817_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int ret;
+ 	comedi_subdevice *s;
+@@ -167,7 +167,7 @@ static int dt2817_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int dt2817_detach(comedi_device * dev)
++static int dt2817_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: dt2817: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
+index 5cdd577475da..2c4557faac4a 100644
+--- a/drivers/staging/comedi/drivers/dt282x.c
++++ b/drivers/staging/comedi/drivers/dt282x.c
+@@ -394,8 +394,8 @@ typedef struct {
+ 		if(_i){b}				\
+ 	}while(0)
+ 
+-static int dt282x_attach(comedi_device * dev, comedi_devconfig * it);
+-static int dt282x_detach(comedi_device * dev);
++static int dt282x_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int dt282x_detach(struct comedi_device * dev);
+ static comedi_driver driver_dt282x = {
+       driver_name:"dt282x",
+       module:THIS_MODULE,
+@@ -408,17 +408,17 @@ static comedi_driver driver_dt282x = {
+ 
+ COMEDI_INITCLEANUP(driver_dt282x);
+ 
+-static void free_resources(comedi_device * dev);
+-static int prep_ai_dma(comedi_device * dev, int chan, int size);
+-static int prep_ao_dma(comedi_device * dev, int chan, int size);
+-static int dt282x_ai_cancel(comedi_device * dev, comedi_subdevice * s);
+-static int dt282x_ao_cancel(comedi_device * dev, comedi_subdevice * s);
++static void free_resources(struct comedi_device * dev);
++static int prep_ai_dma(struct comedi_device * dev, int chan, int size);
++static int prep_ao_dma(struct comedi_device * dev, int chan, int size);
++static int dt282x_ai_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static int dt282x_ao_cancel(struct comedi_device * dev, comedi_subdevice * s);
+ static int dt282x_ns_to_timer(int *nanosec, int round_mode);
+-static void dt282x_disable_dma(comedi_device * dev);
++static void dt282x_disable_dma(struct comedi_device * dev);
+ 
+-static int dt282x_grab_dma(comedi_device * dev, int dma1, int dma2);
++static int dt282x_grab_dma(struct comedi_device * dev, int dma1, int dma2);
+ 
+-static void dt282x_munge(comedi_device * dev, short * buf,
++static void dt282x_munge(struct comedi_device * dev, short * buf,
+ 	unsigned int nbytes)
+ {
+ 	unsigned int i;
+@@ -440,7 +440,7 @@ static void dt282x_munge(comedi_device * dev, short * buf,
+ 	}
+ }
+ 
+-static void dt282x_ao_dma_interrupt(comedi_device * dev)
++static void dt282x_ao_dma_interrupt(struct comedi_device * dev)
+ {
+ 	void *ptr;
+ 	int size;
+@@ -472,7 +472,7 @@ static void dt282x_ao_dma_interrupt(comedi_device * dev)
+ 	return;
+ }
+ 
+-static void dt282x_ai_dma_interrupt(comedi_device * dev)
++static void dt282x_ai_dma_interrupt(struct comedi_device * dev)
+ {
+ 	void *ptr;
+ 	int size;
+@@ -524,7 +524,7 @@ static void dt282x_ai_dma_interrupt(comedi_device * dev)
+ 	prep_ai_dma(dev, i, 0);
+ }
+ 
+-static int prep_ai_dma(comedi_device * dev, int dma_index, int n)
++static int prep_ai_dma(struct comedi_device * dev, int dma_index, int n)
+ {
+ 	int dma_chan;
+ 	unsigned long dma_ptr;
+@@ -555,7 +555,7 @@ static int prep_ai_dma(comedi_device * dev, int dma_index, int n)
+ 	return n;
+ }
+ 
+-static int prep_ao_dma(comedi_device * dev, int dma_index, int n)
++static int prep_ao_dma(struct comedi_device * dev, int dma_index, int n)
+ {
+ 	int dma_chan;
+ 	unsigned long dma_ptr;
+@@ -579,7 +579,7 @@ static int prep_ao_dma(comedi_device * dev, int dma_index, int n)
+ 
+ static irqreturn_t dt282x_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s;
+ 	comedi_subdevice *s_ao;
+ 	unsigned int supcsr, adcsr, dacsr;
+@@ -653,7 +653,7 @@ static irqreturn_t dt282x_interrupt(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_RETVAL(handled);
+ }
+ 
+-static void dt282x_load_changain(comedi_device * dev, int n,
++static void dt282x_load_changain(struct comedi_device * dev, int n,
+ 	unsigned int *chanlist)
+ {
+ 	unsigned int i;
+@@ -674,7 +674,7 @@ static void dt282x_load_changain(comedi_device * dev, int n,
+  *      - preload multiplexer
+  *      - trigger conversion and wait for it to finish
+  */
+-static int dt282x_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int dt282x_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -706,7 +706,7 @@ static int dt282x_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int dt282x_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int dt282x_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -818,7 +818,7 @@ static int dt282x_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int dt282x_ai_cmd(comedi_device * dev, comedi_subdevice * s)
++static int dt282x_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	int timer;
+@@ -879,7 +879,7 @@ static int dt282x_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static void dt282x_disable_dma(comedi_device * dev)
++static void dt282x_disable_dma(struct comedi_device * dev)
+ {
+ 	if (devpriv->usedma) {
+ 		disable_dma(devpriv->dma[0].chan);
+@@ -887,7 +887,7 @@ static void dt282x_disable_dma(comedi_device * dev)
+ 	}
+ }
+ 
+-static int dt282x_ai_cancel(comedi_device * dev, comedi_subdevice * s)
++static int dt282x_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	dt282x_disable_dma(dev);
+ 
+@@ -937,7 +937,7 @@ static int dt282x_ns_to_timer(int *nanosec, int round_mode)
+  *      offset binary if necessary, loads the data into the DAC
+  *      data register, and performs the conversion.
+  */
+-static int dt282x_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int dt282x_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->ao[CR_CHAN(insn->chanspec)];
+@@ -945,7 +945,7 @@ static int dt282x_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int dt282x_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
++static int dt282x_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	short d;
+@@ -978,7 +978,7 @@ static int dt282x_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int dt282x_ao_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int dt282x_ao_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -1069,7 +1069,7 @@ static int dt282x_ao_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 
+ }
+ 
+-static int dt282x_ao_inttrig(comedi_device * dev, comedi_subdevice * s,
++static int dt282x_ao_inttrig(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int x)
+ {
+ 	int size;
+@@ -1099,7 +1099,7 @@ static int dt282x_ao_inttrig(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int dt282x_ao_cmd(comedi_device * dev, comedi_subdevice * s)
++static int dt282x_ao_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	int timer;
+ 	comedi_cmd *cmd = &s->async->cmd;
+@@ -1132,7 +1132,7 @@ static int dt282x_ao_cmd(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int dt282x_ao_cancel(comedi_device * dev, comedi_subdevice * s)
++static int dt282x_ao_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	dt282x_disable_dma(dev);
+ 
+@@ -1145,7 +1145,7 @@ static int dt282x_ao_cancel(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int dt282x_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int dt282x_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+@@ -1159,7 +1159,7 @@ static int dt282x_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int dt282x_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int dt282x_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int mask;
+@@ -1240,7 +1240,7 @@ enum { opt_iobase = 0, opt_irq, opt_dma1, opt_dma2,	/* i/o base, irq, dma channe
+    9	ao0 0=±10 V, 1=0-10 V, 2=±5 V, 3=0-5 V, 4=±2.5 V
+    10	ao1 0=±10 V, 1=0-10 V, 2=±5 V, 3=0-5 V, 4=±2.5 V
+  */
+-static int dt282x_attach(comedi_device * dev, comedi_devconfig * it)
++static int dt282x_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int i, irq;
+ 	int ret;
+@@ -1396,7 +1396,7 @@ static int dt282x_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static void free_resources(comedi_device * dev)
++static void free_resources(struct comedi_device * dev)
+ {
+ 	if (dev->irq) {
+ 		comedi_free_irq(dev->irq, dev);
+@@ -1415,7 +1415,7 @@ static void free_resources(comedi_device * dev)
+ 	}
+ }
+ 
+-static int dt282x_detach(comedi_device * dev)
++static int dt282x_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: dt282x: remove\n", dev->minor);
+ 
+@@ -1424,7 +1424,7 @@ static int dt282x_detach(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int dt282x_grab_dma(comedi_device * dev, int dma1, int dma2)
++static int dt282x_grab_dma(struct comedi_device * dev, int dma1, int dma2)
+ {
+ 	int ret;
+ 
+diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
+index b1af0e74cc73..0b015a0d8203 100644
+--- a/drivers/staging/comedi/drivers/dt3000.c
++++ b/drivers/staging/comedi/drivers/dt3000.c
+@@ -271,8 +271,8 @@ typedef struct {
+ } dt3k_private;
+ #define devpriv ((dt3k_private *)dev->private)
+ 
+-static int dt3000_attach(comedi_device * dev, comedi_devconfig * it);
+-static int dt3000_detach(comedi_device * dev);
++static int dt3000_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int dt3000_detach(struct comedi_device * dev);
+ static comedi_driver driver_dt3000 = {
+       driver_name:"dt3000",
+       module:THIS_MODULE,
+@@ -282,17 +282,17 @@ static comedi_driver driver_dt3000 = {
+ 
+ COMEDI_PCI_INITCLEANUP(driver_dt3000, dt3k_pci_table);
+ 
+-static void dt3k_ai_empty_fifo(comedi_device * dev, comedi_subdevice * s);
++static void dt3k_ai_empty_fifo(struct comedi_device * dev, comedi_subdevice * s);
+ static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *arg,
+ 	unsigned int round_mode);
+-static int dt3k_ai_cancel(comedi_device * dev, comedi_subdevice * s);
++static int dt3k_ai_cancel(struct comedi_device * dev, comedi_subdevice * s);
+ #ifdef DEBUG
+ static void debug_intr_flags(unsigned int flags);
+ #endif
+ 
+ #define TIMEOUT 100
+ 
+-static int dt3k_send_cmd(comedi_device * dev, unsigned int cmd)
++static int dt3k_send_cmd(struct comedi_device * dev, unsigned int cmd)
+ {
+ 	int i;
+ 	unsigned int status = 0;
+@@ -314,7 +314,7 @@ static int dt3k_send_cmd(comedi_device * dev, unsigned int cmd)
+ 	return -ETIME;
+ }
+ 
+-static unsigned int dt3k_readsingle(comedi_device * dev, unsigned int subsys,
++static unsigned int dt3k_readsingle(struct comedi_device * dev, unsigned int subsys,
+ 	unsigned int chan, unsigned int gain)
+ {
+ 	writew(subsys, devpriv->io_addr + DPR_SubSys);
+@@ -327,7 +327,7 @@ static unsigned int dt3k_readsingle(comedi_device * dev, unsigned int subsys,
+ 	return readw(devpriv->io_addr + DPR_Params(2));
+ }
+ 
+-static void dt3k_writesingle(comedi_device * dev, unsigned int subsys,
++static void dt3k_writesingle(struct comedi_device * dev, unsigned int subsys,
+ 	unsigned int chan, unsigned int data)
+ {
+ 	writew(subsys, devpriv->io_addr + DPR_SubSys);
+@@ -345,7 +345,7 @@ static int debug_n_ints = 0;
+ // What's this debug_n_ints stuff? Obviously needs some work...
+ static irqreturn_t dt3k_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s;
+ 	unsigned int status;
+ 
+@@ -396,7 +396,7 @@ static void debug_intr_flags(unsigned int flags)
+ }
+ #endif
+ 
+-static void dt3k_ai_empty_fifo(comedi_device * dev, comedi_subdevice * s)
++static void dt3k_ai_empty_fifo(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	int front;
+ 	int rear;
+@@ -425,7 +425,7 @@ static void dt3k_ai_empty_fifo(comedi_device * dev, comedi_subdevice * s)
+ 	writew(rear, devpriv->io_addr + DPR_AD_Buf_Rear);
+ }
+ 
+-static int dt3k_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int dt3k_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -587,7 +587,7 @@ static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
+ 	return (prescale << 16) | (divider);
+ }
+ 
+-static int dt3k_ai_cmd(comedi_device * dev, comedi_subdevice * s)
++static int dt3k_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	int i;
+@@ -655,7 +655,7 @@ static int dt3k_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int dt3k_ai_cancel(comedi_device * dev, comedi_subdevice * s)
++static int dt3k_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	int ret;
+ 
+@@ -667,7 +667,7 @@ static int dt3k_ai_cancel(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int dt3k_ai_insn(comedi_device * dev, comedi_subdevice * s,
++static int dt3k_ai_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -685,7 +685,7 @@ static int dt3k_ai_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int dt3k_ao_insn(comedi_device * dev, comedi_subdevice * s,
++static int dt3k_ao_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -700,7 +700,7 @@ static int dt3k_ao_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int dt3k_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int dt3k_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -714,7 +714,7 @@ static int dt3k_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static void dt3k_dio_config(comedi_device * dev, int bits)
++static void dt3k_dio_config(struct comedi_device * dev, int bits)
+ {
+ 	/* XXX */
+ 	writew(SUBS_DOUT, devpriv->io_addr + DPR_SubSys);
+@@ -729,7 +729,7 @@ static void dt3k_dio_config(comedi_device * dev, int bits)
+ 	dt3k_send_cmd(dev, CMD_CONFIG);
+ }
+ 
+-static int dt3k_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int dt3k_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int mask;
+@@ -760,7 +760,7 @@ static int dt3k_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 	return insn->n;
+ }
+ 
+-static int dt3k_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int dt3k_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -776,7 +776,7 @@ static int dt3k_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int dt3k_mem_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int dt3k_mem_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int addr = CR_CHAN(insn->chanspec);
+@@ -795,9 +795,9 @@ static int dt3k_mem_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int dt_pci_probe(comedi_device * dev, int bus, int slot);
++static int dt_pci_probe(struct comedi_device * dev, int bus, int slot);
+ 
+-static int dt3000_attach(comedi_device * dev, comedi_devconfig * it)
++static int dt3000_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	int bus, slot;
+@@ -886,7 +886,7 @@ static int dt3000_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int dt3000_detach(comedi_device * dev)
++static int dt3000_detach(struct comedi_device * dev)
+ {
+ 	if (dev->irq)
+ 		comedi_free_irq(dev->irq, dev);
+@@ -907,9 +907,9 @@ static int dt3000_detach(comedi_device * dev)
+ }
+ 
+ static struct pci_dev *dt_pci_find_device(struct pci_dev *from, int *board);
+-static int setup_pci(comedi_device * dev);
++static int setup_pci(struct comedi_device * dev);
+ 
+-static int dt_pci_probe(comedi_device * dev, int bus, int slot)
++static int dt_pci_probe(struct comedi_device * dev, int bus, int slot)
+ {
+ 	int board;
+ 	int ret;
+@@ -937,7 +937,7 @@ static int dt_pci_probe(comedi_device * dev, int bus, int slot)
+ 	return 1;
+ }
+ 
+-static int setup_pci(comedi_device * dev)
++static int setup_pci(struct comedi_device * dev)
+ {
+ 	resource_size_t addr;
+ 	int ret;
+diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c
+index bbb5a146a7ee..068ef2f79e5a 100644
+--- a/drivers/staging/comedi/drivers/dt9812.c
++++ b/drivers/staging/comedi/drivers/dt9812.c
+@@ -892,7 +892,7 @@ static struct usb_driver dt9812_usb_driver = {
+  * Comedi functions
+  */
+ 
+-static void dt9812_comedi_open(comedi_device *dev)
++static void dt9812_comedi_open(struct comedi_device *dev)
+ {
+ 	down(&devpriv->slot->mutex);
+ 	if (devpriv->slot->usb) {
+@@ -940,7 +940,7 @@ static void dt9812_comedi_open(comedi_device *dev)
+ 	up(&devpriv->slot->mutex);
+ }
+ 
+-static int dt9812_di_rinsn(comedi_device *dev, comedi_subdevice *s,
++static int dt9812_di_rinsn(struct comedi_device *dev, comedi_subdevice *s,
+ 			   comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+@@ -952,7 +952,7 @@ static int dt9812_di_rinsn(comedi_device *dev, comedi_subdevice *s,
+ 	return n;
+ }
+ 
+-static int dt9812_do_winsn(comedi_device *dev, comedi_subdevice *s,
++static int dt9812_do_winsn(struct comedi_device *dev, comedi_subdevice *s,
+ 			   comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+@@ -970,7 +970,7 @@ static int dt9812_do_winsn(comedi_device *dev, comedi_subdevice *s,
+ 	return n;
+ }
+ 
+-static int dt9812_ai_rinsn(comedi_device *dev, comedi_subdevice *s,
++static int dt9812_ai_rinsn(struct comedi_device *dev, comedi_subdevice *s,
+ 			   comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+@@ -985,7 +985,7 @@ static int dt9812_ai_rinsn(comedi_device *dev, comedi_subdevice *s,
+ 	return n;
+ }
+ 
+-static int dt9812_ao_rinsn(comedi_device *dev, comedi_subdevice *s,
++static int dt9812_ao_rinsn(struct comedi_device *dev, comedi_subdevice *s,
+ 			   comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+@@ -999,7 +999,7 @@ static int dt9812_ao_rinsn(comedi_device *dev, comedi_subdevice *s,
+ 	return n;
+ }
+ 
+-static int dt9812_ao_winsn(comedi_device *dev, comedi_subdevice *s,
++static int dt9812_ao_winsn(struct comedi_device *dev, comedi_subdevice *s,
+ 			   comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+@@ -1009,7 +1009,7 @@ static int dt9812_ao_winsn(comedi_device *dev, comedi_subdevice *s,
+ 	return n;
+ }
+ 
+-static int dt9812_attach(comedi_device *dev, comedi_devconfig *it)
++static int dt9812_attach(struct comedi_device *dev, comedi_devconfig *it)
+ {
+ 	int i;
+ 	comedi_subdevice *s;
+@@ -1103,7 +1103,7 @@ static int dt9812_attach(comedi_device *dev, comedi_devconfig *it)
+ 	return 0;
+ }
+ 
+-static int dt9812_detach(comedi_device *dev)
++static int dt9812_detach(struct comedi_device *dev)
+ {
+ 	return 0;
+ }
+diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c
+index 26709987278c..20bd47318439 100644
+--- a/drivers/staging/comedi/drivers/fl512.c
++++ b/drivers/staging/comedi/drivers/fl512.c
+@@ -40,8 +40,8 @@ static const comedi_lrange range_fl512 = { 4, {
+ 	}
+ };
+ 
+-static int fl512_attach(comedi_device * dev, comedi_devconfig * it);
+-static int fl512_detach(comedi_device * dev);
++static int fl512_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int fl512_detach(struct comedi_device * dev);
+ 
+ static comedi_driver driver_fl512 = {
+       driver_name:"fl512",
+@@ -52,17 +52,17 @@ static comedi_driver driver_fl512 = {
+ 
+ COMEDI_INITCLEANUP(driver_fl512);
+ 
+-static int fl512_ai_insn(comedi_device * dev,
++static int fl512_ai_insn(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+-static int fl512_ao_insn(comedi_device * dev,
++static int fl512_ao_insn(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+-static int fl512_ao_insn_readback(comedi_device * dev,
++static int fl512_ao_insn_readback(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+ /*
+  * fl512_ai_insn : this is the analog input function
+  */
+-static int fl512_ai_insn(comedi_device * dev,
++static int fl512_ai_insn(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -87,7 +87,7 @@ static int fl512_ai_insn(comedi_device * dev,
+ /*
+  * fl512_ao_insn : used to write to a DA port n times
+  */
+-static int fl512_ao_insn(comedi_device * dev,
++static int fl512_ao_insn(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -108,7 +108,7 @@ static int fl512_ao_insn(comedi_device * dev,
+  * fl512_ao_insn_readback : used to read previous values written to
+  * DA port
+  */
+-static int fl512_ao_insn_readback(comedi_device * dev,
++static int fl512_ao_insn_readback(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -124,7 +124,7 @@ static int fl512_ao_insn_readback(comedi_device * dev,
+ /*
+  * start attach
+  */
+-static int fl512_attach(comedi_device * dev, comedi_devconfig * it)
++static int fl512_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	unsigned long iobase;
+ 	comedi_subdevice *s;	/* pointer to the subdevice:
+@@ -175,7 +175,7 @@ static int fl512_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 1;
+ }
+ 
+-static int fl512_detach(comedi_device * dev)
++static int fl512_detach(struct comedi_device * dev)
+ {
+ 	if (dev->iobase)
+ 		release_region(dev->iobase, FL512_SIZE);
+diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
+index 07ed2380aa9a..5048255b4a3f 100644
+--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
++++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
+@@ -52,15 +52,15 @@ support could be added to this driver.
+ #include "plx9080.h"
+ #include "comedi_fc.h"
+ 
+-static int hpdi_attach(comedi_device * dev, comedi_devconfig * it);
+-static int hpdi_detach(comedi_device * dev);
+-void abort_dma(comedi_device * dev, unsigned int channel);
+-static int hpdi_cmd(comedi_device * dev, comedi_subdevice * s);
+-static int hpdi_cmd_test(comedi_device * dev, comedi_subdevice * s,
++static int hpdi_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int hpdi_detach(struct comedi_device * dev);
++void abort_dma(struct comedi_device * dev, unsigned int channel);
++static int hpdi_cmd(struct comedi_device * dev, comedi_subdevice * s);
++static int hpdi_cmd_test(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int hpdi_cancel(comedi_device * dev, comedi_subdevice * s);
++static int hpdi_cancel(struct comedi_device * dev, comedi_subdevice * s);
+ static irqreturn_t handle_interrupt(int irq, void *d PT_REGS_ARG);
+-static int dio_config_block_size(comedi_device * dev, unsigned int * data);
++static int dio_config_block_size(struct comedi_device * dev, unsigned int * data);
+ 
+ #undef HPDI_DEBUG		// disable debugging messages
+ //#define HPDI_DEBUG    // enable debugging code
+@@ -294,7 +294,7 @@ static DEFINE_PCI_DEVICE_TABLE(hpdi_pci_table) = {
+ 
+ MODULE_DEVICE_TABLE(pci, hpdi_pci_table);
+ 
+-static inline hpdi_board *board(const comedi_device * dev)
++static inline hpdi_board *board(const struct comedi_device * dev)
+ {
+ 	return (hpdi_board *) dev->board_ptr;
+ }
+@@ -322,7 +322,7 @@ typedef struct {
+ 	unsigned dio_config_output:1;
+ } hpdi_private;
+ 
+-static inline hpdi_private *priv(comedi_device * dev)
++static inline hpdi_private *priv(struct comedi_device * dev)
+ {
+ 	return dev->private;
+ }
+@@ -336,7 +336,7 @@ static comedi_driver driver_hpdi = {
+ 
+ COMEDI_PCI_INITCLEANUP(driver_hpdi, hpdi_pci_table);
+ 
+-static int dio_config_insn(comedi_device * dev, comedi_subdevice * s,
++static int dio_config_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+@@ -364,13 +364,13 @@ static int dio_config_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return -EINVAL;
+ }
+ 
+-static void disable_plx_interrupts(comedi_device * dev)
++static void disable_plx_interrupts(struct comedi_device * dev)
+ {
+ 	writel(0, priv(dev)->plx9080_iobase + PLX_INTRCS_REG);
+ }
+ 
+ // initialize plx9080 chip
+-static void init_plx9080(comedi_device * dev)
++static void init_plx9080(struct comedi_device * dev)
+ {
+ 	uint32_t bits;
+ 	void *plx_iobase = priv(dev)->plx9080_iobase;
+@@ -435,7 +435,7 @@ static void init_plx9080(comedi_device * dev)
+ 
+ /* Allocate and initialize the subdevice structures.
+  */
+-static int setup_subdevices(comedi_device * dev)
++static int setup_subdevices(struct comedi_device * dev)
+ {
+ 	comedi_subdevice *s;
+ 
+@@ -461,7 +461,7 @@ static int setup_subdevices(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int init_hpdi(comedi_device * dev)
++static int init_hpdi(struct comedi_device * dev)
+ {
+ 	uint32_t plx_intcsr_bits;
+ 
+@@ -490,7 +490,7 @@ static int init_hpdi(comedi_device * dev)
+ }
+ 
+ // setup dma descriptors so a link completes every 'transfer_size' bytes
+-static int setup_dma_descriptors(comedi_device * dev,
++static int setup_dma_descriptors(struct comedi_device * dev,
+ 	unsigned int transfer_size)
+ {
+ 	unsigned int buffer_index, buffer_offset;
+@@ -552,7 +552,7 @@ static int setup_dma_descriptors(comedi_device * dev,
+ 	return transfer_size;
+ }
+ 
+-static int hpdi_attach(comedi_device * dev, comedi_devconfig * it)
++static int hpdi_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	struct pci_dev *pcidev;
+ 	int i;
+@@ -661,7 +661,7 @@ static int hpdi_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return init_hpdi(dev);
+ }
+ 
+-static int hpdi_detach(comedi_device * dev)
++static int hpdi_detach(struct comedi_device * dev)
+ {
+ 	unsigned int i;
+ 
+@@ -702,7 +702,7 @@ static int hpdi_detach(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int dio_config_block_size(comedi_device * dev, unsigned int * data)
++static int dio_config_block_size(struct comedi_device * dev, unsigned int * data)
+ {
+ 	unsigned int requested_block_size;
+ 	int retval;
+@@ -718,7 +718,7 @@ static int dio_config_block_size(comedi_device * dev, unsigned int * data)
+ 	return 2;
+ }
+ 
+-static int di_cmd_test(comedi_device * dev, comedi_subdevice * s,
++static int di_cmd_test(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -818,7 +818,7 @@ static int di_cmd_test(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int hpdi_cmd_test(comedi_device * dev, comedi_subdevice * s,
++static int hpdi_cmd_test(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	if (priv(dev)->dio_config_output) {
+@@ -827,14 +827,14 @@ static int hpdi_cmd_test(comedi_device * dev, comedi_subdevice * s,
+ 		return di_cmd_test(dev, s, cmd);
+ }
+ 
+-static inline void hpdi_writel(comedi_device * dev, uint32_t bits,
++static inline void hpdi_writel(struct comedi_device * dev, uint32_t bits,
+ 	unsigned int offset)
+ {
+ 	writel(bits | priv(dev)->bits[offset / sizeof(uint32_t)],
+ 		priv(dev)->hpdi_iobase + offset);
+ }
+ 
+-static int di_cmd(comedi_device * dev, comedi_subdevice * s)
++static int di_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	uint32_t bits;
+ 	unsigned long flags;
+@@ -887,7 +887,7 @@ static int di_cmd(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int hpdi_cmd(comedi_device * dev, comedi_subdevice * s)
++static int hpdi_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	if (priv(dev)->dio_config_output) {
+ 		return -EINVAL;
+@@ -895,7 +895,7 @@ static int hpdi_cmd(comedi_device * dev, comedi_subdevice * s)
+ 		return di_cmd(dev, s);
+ }
+ 
+-static void drain_dma_buffers(comedi_device * dev, unsigned int channel)
++static void drain_dma_buffers(struct comedi_device * dev, unsigned int channel)
+ {
+ 	comedi_async *async = dev->read_subdev->async;
+ 	uint32_t next_transfer_addr;
+@@ -943,7 +943,7 @@ static void drain_dma_buffers(comedi_device * dev, unsigned int channel)
+ 
+ static irqreturn_t handle_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s = dev->read_subdev;
+ 	comedi_async *async = s->async;
+ 	uint32_t hpdi_intr_status, hpdi_board_status;
+@@ -1032,7 +1032,7 @@ static irqreturn_t handle_interrupt(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-void abort_dma(comedi_device * dev, unsigned int channel)
++void abort_dma(struct comedi_device * dev, unsigned int channel)
+ {
+ 	unsigned long flags;
+ 
+@@ -1044,7 +1044,7 @@ void abort_dma(comedi_device * dev, unsigned int channel)
+ 	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ }
+ 
+-static int hpdi_cancel(comedi_device * dev, comedi_subdevice * s)
++static int hpdi_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	hpdi_writel(dev, 0, BOARD_CONTROL_REG);
+ 
+diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
+index 1d27e90213cd..04152148a106 100644
+--- a/drivers/staging/comedi/drivers/icp_multi.c
++++ b/drivers/staging/comedi/drivers/icp_multi.c
+@@ -123,8 +123,8 @@ static const char range_codes_analog[] = { 0x00, 0x20, 0x10, 0x30 };
+ 	Forward declarations
+ ==============================================================================
+ */
+-static int icp_multi_attach(comedi_device *dev, comedi_devconfig *it);
+-static int icp_multi_detach(comedi_device *dev);
++static int icp_multi_attach(struct comedi_device *dev, comedi_devconfig *it);
++static int icp_multi_detach(struct comedi_device *dev);
+ 
+ /*
+ ==============================================================================
+@@ -214,12 +214,12 @@ struct icp_multi_private {
+ */
+ 
+ #if 0
+-static int check_channel_list(comedi_device *dev, comedi_subdevice *s,
++static int check_channel_list(struct comedi_device *dev, comedi_subdevice *s,
+ 	unsigned int *chanlist, unsigned int n_chan);
+ #endif
+-static void setup_channel_list(comedi_device *dev, comedi_subdevice *s,
++static void setup_channel_list(struct comedi_device *dev, comedi_subdevice *s,
+ 	unsigned int *chanlist, unsigned int n_chan);
+-static int icp_multi_reset(comedi_device *dev);
++static int icp_multi_reset(struct comedi_device *dev);
+ 
+ /*
+ ==============================================================================
+@@ -236,7 +236,7 @@ static int icp_multi_reset(comedi_device *dev);
+ 		This function reads a single analogue input.
+ 
+ 	Parameters:
+-		comedi_device *dev	Pointer to current device structure
++		struct comedi_device *dev	Pointer to current device structure
+ 		comedi_subdevice *s	Pointer to current subdevice structure
+ 		comedi_insn *insn	Pointer to current comedi instruction
+ 		unsigned int *data		Pointer to analogue input data
+@@ -245,7 +245,7 @@ static int icp_multi_reset(comedi_device *dev);
+ 
+ ==============================================================================
+ */
+-static int icp_multi_insn_read_ai(comedi_device *dev, comedi_subdevice *s,
++static int icp_multi_insn_read_ai(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, timeout;
+@@ -355,7 +355,7 @@ static int icp_multi_insn_read_ai(comedi_device *dev, comedi_subdevice *s,
+ 		This function writes a single analogue output.
+ 
+ 	Parameters:
+-		comedi_device *dev	Pointer to current device structure
++		struct comedi_device *dev	Pointer to current device structure
+ 		comedi_subdevice *s	Pointer to current subdevice structure
+ 		comedi_insn *insn	Pointer to current comedi instruction
+ 		unsigned int *data		Pointer to analogue output data
+@@ -364,7 +364,7 @@ static int icp_multi_insn_read_ai(comedi_device *dev, comedi_subdevice *s,
+ 
+ ==============================================================================
+ */
+-static int icp_multi_insn_write_ao(comedi_device *dev, comedi_subdevice *s,
++static int icp_multi_insn_write_ao(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, chan, range, timeout;
+@@ -463,7 +463,7 @@ static int icp_multi_insn_write_ao(comedi_device *dev, comedi_subdevice *s,
+ 		This function reads a single analogue output.
+ 
+ 	Parameters:
+-		comedi_device *dev	Pointer to current device structure
++		struct comedi_device *dev	Pointer to current device structure
+ 		comedi_subdevice *s	Pointer to current subdevice structure
+ 		comedi_insn *insn	Pointer to current comedi instruction
+ 		unsigned int *data		Pointer to analogue output data
+@@ -472,7 +472,7 @@ static int icp_multi_insn_write_ao(comedi_device *dev, comedi_subdevice *s,
+ 
+ ==============================================================================
+ */
+-static int icp_multi_insn_read_ao(comedi_device *dev, comedi_subdevice *s,
++static int icp_multi_insn_read_ao(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, chan;
+@@ -496,7 +496,7 @@ static int icp_multi_insn_read_ao(comedi_device *dev, comedi_subdevice *s,
+ 		This function reads the digital inputs.
+ 
+ 	Parameters:
+-		comedi_device *dev	Pointer to current device structure
++		struct comedi_device *dev	Pointer to current device structure
+ 		comedi_subdevice *s	Pointer to current subdevice structure
+ 		comedi_insn *insn	Pointer to current comedi instruction
+ 		unsigned int *data		Pointer to analogue output data
+@@ -505,7 +505,7 @@ static int icp_multi_insn_read_ao(comedi_device *dev, comedi_subdevice *s,
+ 
+ ==============================================================================
+ */
+-static int icp_multi_insn_bits_di(comedi_device *dev, comedi_subdevice *s,
++static int icp_multi_insn_bits_di(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 	data[1] = readw(devpriv->io_addr + ICP_MULTI_DI);
+@@ -522,7 +522,7 @@ static int icp_multi_insn_bits_di(comedi_device *dev, comedi_subdevice *s,
+ 		This function writes the appropriate digital outputs.
+ 
+ 	Parameters:
+-		comedi_device *dev	Pointer to current device structure
++		struct comedi_device *dev	Pointer to current device structure
+ 		comedi_subdevice *s	Pointer to current subdevice structure
+ 		comedi_insn *insn	Pointer to current comedi instruction
+ 		unsigned int *data		Pointer to analogue output data
+@@ -531,7 +531,7 @@ static int icp_multi_insn_bits_di(comedi_device *dev, comedi_subdevice *s,
+ 
+ ==============================================================================
+ */
+-static int icp_multi_insn_bits_do(comedi_device *dev, comedi_subdevice *s,
++static int icp_multi_insn_bits_do(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ #ifdef ICP_MULTI_EXTDEBUG
+@@ -564,7 +564,7 @@ static int icp_multi_insn_bits_do(comedi_device *dev, comedi_subdevice *s,
+ 		This function reads the specified counter.
+ 
+ 	Parameters:
+-		comedi_device *dev	Pointer to current device structure
++		struct comedi_device *dev	Pointer to current device structure
+ 		comedi_subdevice *s	Pointer to current subdevice structure
+ 		comedi_insn *insn	Pointer to current comedi instruction
+ 		unsigned int *data		Pointer to counter data
+@@ -573,7 +573,7 @@ static int icp_multi_insn_bits_do(comedi_device *dev, comedi_subdevice *s,
+ 
+ ==============================================================================
+ */
+-static int icp_multi_insn_read_ctr(comedi_device *dev, comedi_subdevice *s,
++static int icp_multi_insn_read_ctr(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 	return 0;
+@@ -588,7 +588,7 @@ static int icp_multi_insn_read_ctr(comedi_device *dev, comedi_subdevice *s,
+ 		This function write to the specified counter.
+ 
+ 	Parameters:
+-		comedi_device *dev	Pointer to current device structure
++		struct comedi_device *dev	Pointer to current device structure
+ 		comedi_subdevice *s	Pointer to current subdevice structure
+ 		comedi_insn *insn	Pointer to current comedi instruction
+ 		unsigned int *data		Pointer to counter data
+@@ -597,7 +597,7 @@ static int icp_multi_insn_read_ctr(comedi_device *dev, comedi_subdevice *s,
+ 
+ ==============================================================================
+ */
+-static int icp_multi_insn_write_ctr(comedi_device *dev, comedi_subdevice *s,
++static int icp_multi_insn_write_ctr(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 	return 0;
+@@ -620,7 +620,7 @@ static int icp_multi_insn_write_ctr(comedi_device *dev, comedi_subdevice *s,
+ */
+ static irqreturn_t interrupt_service_icp_multi(int irq, void *d PT_REGS_ARG)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	int int_no;
+ 
+ #ifdef ICP_MULTI_EXTDEBUG
+@@ -679,7 +679,7 @@ static irqreturn_t interrupt_service_icp_multi(int irq, void *d PT_REGS_ARG)
+ 		is built correctly
+ 
+ 	Parameters:
+-		comedi_device *dev	Pointer to current sevice structure
++		struct comedi_device *dev	Pointer to current sevice structure
+ 		comedi_subdevice *s	Pointer to current subdevice structure
+ 		unsigned int *chanlist	Pointer to packed channel list
+ 		unsigned int n_chan	Number of channels to scan
+@@ -689,7 +689,7 @@ static irqreturn_t interrupt_service_icp_multi(int irq, void *d PT_REGS_ARG)
+ 
+ ==============================================================================
+ */
+-static int check_channel_list(comedi_device *dev, comedi_subdevice *s,
++static int check_channel_list(struct comedi_device *dev, comedi_subdevice *s,
+ 	unsigned int *chanlist, unsigned int n_chan)
+ {
+ 	unsigned int i;
+@@ -734,7 +734,7 @@ static int check_channel_list(comedi_device *dev, comedi_subdevice *s,
+ 		Status register.
+ 
+ 	Parameters:
+-		comedi_device *dev	Pointer to current sevice structure
++		struct comedi_device *dev	Pointer to current sevice structure
+ 		comedi_subdevice *s	Pointer to current subdevice structure
+ 		unsigned int *chanlist	Pointer to packed channel list
+ 		unsigned int n_chan	Number of channels to scan
+@@ -743,7 +743,7 @@ static int check_channel_list(comedi_device *dev, comedi_subdevice *s,
+ 
+ ==============================================================================
+ */
+-static void setup_channel_list(comedi_device *dev, comedi_subdevice *s,
++static void setup_channel_list(struct comedi_device *dev, comedi_subdevice *s,
+ 	unsigned int *chanlist, unsigned int n_chan)
+ {
+ 	unsigned int i, range, chanprog;
+@@ -806,13 +806,13 @@ static void setup_channel_list(comedi_device *dev, comedi_subdevice *s,
+ 		This function resets the icp multi device to a 'safe' state
+ 
+ 	Parameters:
+-		comedi_device *dev	Pointer to current sevice structure
++		struct comedi_device *dev	Pointer to current sevice structure
+ 
+ 	Returns:int	0 = success
+ 
+ ==============================================================================
+ */
+-static int icp_multi_reset(comedi_device *dev)
++static int icp_multi_reset(struct comedi_device *dev)
+ {
+ 	unsigned int i;
+ 
+@@ -863,14 +863,14 @@ static int icp_multi_reset(comedi_device *dev)
+ 		device.
+ 
+ 	Parameters:
+-		comedi_device *dev	Pointer to current device structure
++		struct comedi_device *dev	Pointer to current device structure
+ 		comedi_devconfig *it	Pointer to current device configuration
+ 
+ 	Returns:int	0 = success
+ 
+ ==============================================================================
+ */
+-static int icp_multi_attach(comedi_device *dev, comedi_devconfig *it)
++static int icp_multi_attach(struct comedi_device *dev, comedi_devconfig *it)
+ {
+ 	comedi_subdevice *s;
+ 	int ret, subdev, n_subdevices;
+@@ -1058,13 +1058,13 @@ static int icp_multi_attach(comedi_device *dev, comedi_devconfig *it)
+ 		device.
+ 
+ 	Parameters:
+-		comedi_device *dev	Pointer to current device structure
++		struct comedi_device *dev	Pointer to current device structure
+ 
+ 	Returns:int	0 = success
+ 
+ ==============================================================================
+ */
+-static int icp_multi_detach(comedi_device *dev)
++static int icp_multi_detach(struct comedi_device *dev)
+ {
+ 
+ 	if (dev->private)
+diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c
+index eb3dde50d75c..3e7ca4e6b8af 100644
+--- a/drivers/staging/comedi/drivers/ii_pci20kc.c
++++ b/drivers/staging/comedi/drivers/ii_pci20kc.c
+@@ -156,8 +156,8 @@ typedef struct {
+ #define devpriv ((pci20xxx_private *)dev->private)
+ #define CHAN (CR_CHAN(it->chanlist[0]))
+ 
+-static int pci20xxx_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pci20xxx_detach(comedi_device * dev);
++static int pci20xxx_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pci20xxx_detach(struct comedi_device * dev);
+ 
+ static comedi_driver driver_pci20xxx = {
+       driver_name:"ii_pci20kc",
+@@ -166,11 +166,11 @@ static comedi_driver driver_pci20xxx = {
+       detach:pci20xxx_detach,
+ };
+ 
+-static int pci20006_init(comedi_device * dev, comedi_subdevice * s,
++static int pci20006_init(struct comedi_device * dev, comedi_subdevice * s,
+ 	int opt0, int opt1);
+-static int pci20341_init(comedi_device * dev, comedi_subdevice * s,
++static int pci20341_init(struct comedi_device * dev, comedi_subdevice * s,
+ 	int opt0, int opt1);
+-static int pci20xxx_dio_init(comedi_device * dev, comedi_subdevice * s);
++static int pci20xxx_dio_init(struct comedi_device * dev, comedi_subdevice * s);
+ 
+ /*
+   options[0]	Board base address
+@@ -199,7 +199,7 @@ static int pci20xxx_dio_init(comedi_device * dev, comedi_subdevice * s);
+ 		1 == unipolar 10V  (0V -- +10V)
+ 		2 == bipolar 5V  (-5V -- +5V)
+ */
+-static int pci20xxx_attach(comedi_device * dev, comedi_devconfig * it)
++static int pci20xxx_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	unsigned char i;
+ 	int ret;
+@@ -261,7 +261,7 @@ static int pci20xxx_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 1;
+ }
+ 
+-static int pci20xxx_detach(comedi_device * dev)
++static int pci20xxx_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: pci20xxx: remove\n", dev->minor);
+ 
+@@ -270,9 +270,9 @@ static int pci20xxx_detach(comedi_device * dev)
+ 
+ /* pci20006m */
+ 
+-static int pci20006_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int pci20006_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int pci20006_insn_write(comedi_device * dev, comedi_subdevice * s,
++static int pci20006_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ static const comedi_lrange *pci20006_range_list[] = {
+@@ -281,7 +281,7 @@ static const comedi_lrange *pci20006_range_list[] = {
+ 	&range_bipolar5,
+ };
+ 
+-static int pci20006_init(comedi_device * dev, comedi_subdevice * s,
++static int pci20006_init(struct comedi_device * dev, comedi_subdevice * s,
+ 	int opt0, int opt1)
+ {
+ 	pci20xxx_subdev_private *sdp = s->private;
+@@ -306,7 +306,7 @@ static int pci20006_init(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int pci20006_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int pci20006_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	pci20xxx_subdev_private *sdp = s->private;
+@@ -316,7 +316,7 @@ static int pci20006_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int pci20006_insn_write(comedi_device * dev, comedi_subdevice * s,
++static int pci20006_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	pci20xxx_subdev_private *sdp = s->private;
+@@ -349,7 +349,7 @@ static int pci20006_insn_write(comedi_device * dev, comedi_subdevice * s,
+ 
+ /* PCI20341M */
+ 
+-static int pci20341_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int pci20341_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ static const int pci20341_timebase[] = { 0x00, 0x00, 0x00, 0x04 };
+@@ -366,7 +366,7 @@ static const comedi_lrange *const pci20341_ranges[] = {
+ 	&range_bipolar0_025,
+ };
+ 
+-static int pci20341_init(comedi_device * dev, comedi_subdevice * s,
++static int pci20341_init(struct comedi_device * dev, comedi_subdevice * s,
+ 	int opt0, int opt1)
+ {
+ 	pci20xxx_subdev_private *sdp = s->private;
+@@ -397,7 +397,7 @@ static int pci20341_init(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int pci20341_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int pci20341_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	pci20xxx_subdev_private *sdp = s->private;
+@@ -443,14 +443,14 @@ static int pci20341_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 
+ /* native DIO */
+ 
+-static void pci20xxx_dio_config(comedi_device * dev, comedi_subdevice * s);
+-static int pci20xxx_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static void pci20xxx_dio_config(struct comedi_device * dev, comedi_subdevice * s);
++static int pci20xxx_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int pci20xxx_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int pci20xxx_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ /* initialize pci20xxx_private */
+-static int pci20xxx_dio_init(comedi_device * dev, comedi_subdevice * s)
++static int pci20xxx_dio_init(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 
+ 	s->type = COMEDI_SUBD_DIO;
+@@ -469,7 +469,7 @@ static int pci20xxx_dio_init(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int pci20xxx_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int pci20xxx_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int mask, bits;
+@@ -494,7 +494,7 @@ static int pci20xxx_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int pci20xxx_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int pci20xxx_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int mask = data[0];
+@@ -524,7 +524,7 @@ static int pci20xxx_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static void pci20xxx_dio_config(comedi_device * dev, comedi_subdevice * s)
++static void pci20xxx_dio_config(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	unsigned char control_01;
+ 	unsigned char control_23;
+@@ -580,7 +580,7 @@ static void pci20xxx_dio_config(comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ #if 0
+-static void pci20xxx_do(comedi_device * dev, comedi_subdevice * s)
++static void pci20xxx_do(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	/* XXX if the channel is configured for input, does this
+ 	   do bad things? */
+@@ -593,7 +593,7 @@ static void pci20xxx_do(comedi_device * dev, comedi_subdevice * s)
+ 	writeb((s->state >> 24) & 0xff, devpriv->ioaddr + PCI20000_DIO_3);
+ }
+ 
+-static unsigned int pci20xxx_di(comedi_device * dev, comedi_subdevice * s)
++static unsigned int pci20xxx_di(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	/* XXX same note as above */
+ 	unsigned int bits;
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
+index ae3e2a125abf..0a077486315c 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -60,10 +60,10 @@ static struct device comedi_fw_device = {
+ 	.release = comedi_fw_release
+ };
+ 
+-typedef int comedi_firmware_callback(comedi_device * dev,
++typedef int comedi_firmware_callback(struct comedi_device * dev,
+ 	const u8 * data, size_t size);
+ 
+-static int comedi_load_firmware(comedi_device * dev,
++static int comedi_load_firmware(struct comedi_device * dev,
+ 	char *name, comedi_firmware_callback cb)
+ {
+ 	int result = 0;
+@@ -103,8 +103,8 @@ static int comedi_load_firmware(comedi_device * dev,
+ #define PCI_DEVICE_ID_JR3_3_CHANNEL 0x3113
+ #define PCI_DEVICE_ID_JR3_4_CHANNEL 0x3114
+ 
+-static int jr3_pci_attach(comedi_device * dev, comedi_devconfig * it);
+-static int jr3_pci_detach(comedi_device * dev);
++static int jr3_pci_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int jr3_pci_detach(struct comedi_device * dev);
+ 
+ static comedi_driver driver_jr3_pci = {
+       driver_name:"jr3_pci",
+@@ -269,7 +269,7 @@ static six_axis_t get_max_full_scales(volatile jr3_channel_t * channel)
+ 	return result;
+ }
+ 
+-static int jr3_pci_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int jr3_pci_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int result;
+@@ -385,7 +385,7 @@ static int jr3_pci_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return result;
+ }
+ 
+-static void jr3_pci_open(comedi_device * dev)
++static void jr3_pci_open(struct comedi_device * dev)
+ {
+ 	int i;
+ 	jr3_pci_dev_private *devpriv = dev->private;
+@@ -424,7 +424,7 @@ int read_idm_word(const u8 * data, size_t size, int *pos, unsigned int *val)
+ 	return result;
+ }
+ 
+-static int jr3_download_firmware(comedi_device * dev, const u8 * data,
++static int jr3_download_firmware(struct comedi_device * dev, const u8 * data,
+ 	size_t size)
+ {
+ 	/*
+@@ -737,7 +737,7 @@ static poll_delay_t jr3_pci_poll_subdevice(comedi_subdevice * s)
+ static void jr3_pci_poll_dev(unsigned long data)
+ {
+ 	unsigned long flags;
+-	comedi_device *dev = (comedi_device *) data;
++	struct comedi_device *dev = (struct comedi_device *) data;
+ 	jr3_pci_dev_private *devpriv = dev->private;
+ 	unsigned long now;
+ 	int delay;
+@@ -770,7 +770,7 @@ static void jr3_pci_poll_dev(unsigned long data)
+ 	add_timer(&devpriv->timer);
+ }
+ 
+-static int jr3_pci_attach(comedi_device * dev, comedi_devconfig * it)
++static int jr3_pci_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int result = 0;
+ 	struct pci_dev *card = NULL;
+@@ -940,7 +940,7 @@ static int jr3_pci_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return result;
+ }
+ 
+-static int jr3_pci_detach(comedi_device * dev)
++static int jr3_pci_detach(struct comedi_device * dev)
+ {
+ 	int i;
+ 	jr3_pci_dev_private *devpriv = dev->private;
+diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c
+index 834625c546db..d9b8a83343d9 100644
+--- a/drivers/staging/comedi/drivers/ke_counter.c
++++ b/drivers/staging/comedi/drivers/ke_counter.c
+@@ -48,8 +48,8 @@ Kolter Electronic PCI Counter Card.
+ 
+ /*-- function prototypes ----------------------------------------------------*/
+ 
+-static int cnt_attach(comedi_device * dev, comedi_devconfig * it);
+-static int cnt_detach(comedi_device * dev);
++static int cnt_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int cnt_detach(struct comedi_device * dev);
+ 
+ static DEFINE_PCI_DEVICE_TABLE(cnt_pci_table) = {
+ 	{PCI_VENDOR_ID_KOLTER, CNT_CARD_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+@@ -99,7 +99,7 @@ COMEDI_PCI_INITCLEANUP(cnt_driver, cnt_pci_table);
+ 
+ /* This should be used only for resetting the counters; maybe it is better
+    to make a special command 'reset'. */
+-static int cnt_winsn(comedi_device * dev,
++static int cnt_winsn(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -119,7 +119,7 @@ static int cnt_winsn(comedi_device * dev,
+ 
+ /*-- counter read -----------------------------------------------------------*/
+ 
+-static int cnt_rinsn(comedi_device * dev,
++static int cnt_rinsn(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned char a0, a1, a2, a3, a4;
+@@ -144,7 +144,7 @@ static int cnt_rinsn(comedi_device * dev,
+ 
+ /*-- attach -----------------------------------------------------------------*/
+ 
+-static int cnt_attach(comedi_device * dev, comedi_devconfig * it)
++static int cnt_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *subdevice;
+ 	struct pci_dev *pci_device;
+@@ -237,7 +237,7 @@ static int cnt_attach(comedi_device * dev, comedi_devconfig * it)
+ 
+ /*-- detach -----------------------------------------------------------------*/
+ 
+-static int cnt_detach(comedi_device * dev)
++static int cnt_detach(struct comedi_device * dev)
+ {
+ 	if (devpriv && devpriv->pcidev) {
+ 		if (dev->iobase) {
+diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
+index 7aad3e53624a..a03661ce34b5 100644
+--- a/drivers/staging/comedi/drivers/me4000.c
++++ b/drivers/staging/comedi/drivers/me4000.c
+@@ -118,8 +118,8 @@ static const me4000_board_t me4000_boards[] = {
+ /*-----------------------------------------------------------------------------
+   Comedi function prototypes
+   ---------------------------------------------------------------------------*/
+-static int me4000_attach(comedi_device *dev, comedi_devconfig *it);
+-static int me4000_detach(comedi_device *dev);
++static int me4000_attach(struct comedi_device *dev, comedi_devconfig *it);
++static int me4000_detach(struct comedi_device *dev);
+ static comedi_driver driver_me4000 = {
+       driver_name:"me4000",
+       module : THIS_MODULE,
+@@ -130,91 +130,91 @@ static comedi_driver driver_me4000 = {
+ /*-----------------------------------------------------------------------------
+   Meilhaus function prototypes
+   ---------------------------------------------------------------------------*/
+-static int me4000_probe(comedi_device *dev, comedi_devconfig *it);
+-static int get_registers(comedi_device *dev, struct pci_dev *pci_dev_p);
+-static int init_board_info(comedi_device *dev, struct pci_dev *pci_dev_p);
+-static int init_ao_context(comedi_device *dev);
+-static int init_ai_context(comedi_device *dev);
+-static int init_dio_context(comedi_device *dev);
+-static int init_cnt_context(comedi_device *dev);
+-static int xilinx_download(comedi_device *dev);
+-static int reset_board(comedi_device *dev);
+-
+-static int me4000_dio_insn_bits(comedi_device *dev,
++static int me4000_probe(struct comedi_device *dev, comedi_devconfig *it);
++static int get_registers(struct comedi_device *dev, struct pci_dev *pci_dev_p);
++static int init_board_info(struct comedi_device *dev, struct pci_dev *pci_dev_p);
++static int init_ao_context(struct comedi_device *dev);
++static int init_ai_context(struct comedi_device *dev);
++static int init_dio_context(struct comedi_device *dev);
++static int init_cnt_context(struct comedi_device *dev);
++static int xilinx_download(struct comedi_device *dev);
++static int reset_board(struct comedi_device *dev);
++
++static int me4000_dio_insn_bits(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
+ 
+-static int me4000_dio_insn_config(comedi_device *dev,
++static int me4000_dio_insn_config(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
+ 
+-static int cnt_reset(comedi_device *dev, unsigned int channel);
++static int cnt_reset(struct comedi_device *dev, unsigned int channel);
+ 
+-static int cnt_config(comedi_device *dev,
++static int cnt_config(struct comedi_device *dev,
+ 	unsigned int channel, unsigned int mode);
+ 
+-static int me4000_cnt_insn_config(comedi_device *dev,
++static int me4000_cnt_insn_config(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
+ 
+-static int me4000_cnt_insn_write(comedi_device *dev,
++static int me4000_cnt_insn_write(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
+ 
+-static int me4000_cnt_insn_read(comedi_device *dev,
++static int me4000_cnt_insn_read(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
+ 
+-static int me4000_ai_insn_read(comedi_device *dev,
++static int me4000_ai_insn_read(struct comedi_device *dev,
+ 	comedi_subdevice *subdevice, comedi_insn *insn, unsigned int *data);
+ 
+-static int me4000_ai_cancel(comedi_device *dev, comedi_subdevice *s);
++static int me4000_ai_cancel(struct comedi_device *dev, comedi_subdevice *s);
+ 
+-static int ai_check_chanlist(comedi_device *dev,
++static int ai_check_chanlist(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_cmd *cmd);
+ 
+-static int ai_round_cmd_args(comedi_device *dev,
++static int ai_round_cmd_args(struct comedi_device *dev,
+ 	comedi_subdevice *s,
+ 	comedi_cmd *cmd,
+ 	unsigned int *init_ticks,
+ 	unsigned int *scan_ticks, unsigned int *chan_ticks);
+ 
+-static int ai_prepare(comedi_device *dev,
++static int ai_prepare(struct comedi_device *dev,
+ 	comedi_subdevice *s,
+ 	comedi_cmd *cmd,
+ 	unsigned int init_ticks,
+ 	unsigned int scan_ticks, unsigned int chan_ticks);
+ 
+-static int ai_write_chanlist(comedi_device *dev,
++static int ai_write_chanlist(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_cmd *cmd);
+ 
+ static irqreturn_t me4000_ai_isr(int irq, void *dev_id PT_REGS_ARG);
+ 
+-static int me4000_ai_do_cmd_test(comedi_device *dev,
++static int me4000_ai_do_cmd_test(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_cmd *cmd);
+ 
+-static int me4000_ai_do_cmd(comedi_device *dev, comedi_subdevice *s);
++static int me4000_ai_do_cmd(struct comedi_device *dev, comedi_subdevice *s);
+ 
+-static int me4000_ao_insn_write(comedi_device *dev,
++static int me4000_ao_insn_write(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
+ 
+-static int me4000_ao_insn_read(comedi_device *dev,
++static int me4000_ao_insn_read(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
+ 
+ /*-----------------------------------------------------------------------------
+   Meilhaus inline functions
+   ---------------------------------------------------------------------------*/
+ 
+-static inline void me4000_outb(comedi_device *dev, unsigned char value,
++static inline void me4000_outb(struct comedi_device *dev, unsigned char value,
+ 	unsigned long port)
+ {
+ 	PORT_PDEBUG("--> 0x%02X port 0x%04lX\n", value, port);
+ 	outb(value, port);
+ }
+ 
+-static inline void me4000_outl(comedi_device *dev, unsigned long value,
++static inline void me4000_outl(struct comedi_device *dev, unsigned long value,
+ 	unsigned long port)
+ {
+ 	PORT_PDEBUG("--> 0x%08lX port 0x%04lX\n", value, port);
+ 	outl(value, port);
+ }
+ 
+-static inline unsigned long me4000_inl(comedi_device *dev, unsigned long port)
++static inline unsigned long me4000_inl(struct comedi_device *dev, unsigned long port)
+ {
+ 	unsigned long value;
+ 	value = inl(port);
+@@ -222,7 +222,7 @@ static inline unsigned long me4000_inl(comedi_device *dev, unsigned long port)
+ 	return value;
+ }
+ 
+-static inline unsigned char me4000_inb(comedi_device *dev, unsigned long port)
++static inline unsigned char me4000_inb(struct comedi_device *dev, unsigned long port)
+ {
+ 	unsigned char value;
+ 	value = inb(port);
+@@ -247,7 +247,7 @@ static const comedi_lrange me4000_ao_range = {
+ 		}
+ };
+ 
+-static int me4000_attach(comedi_device *dev, comedi_devconfig *it)
++static int me4000_attach(struct comedi_device *dev, comedi_devconfig *it)
+ {
+ 	comedi_subdevice *s;
+ 	int result;
+@@ -369,7 +369,7 @@ static int me4000_attach(comedi_device *dev, comedi_devconfig *it)
+ 	return 0;
+ }
+ 
+-static int me4000_probe(comedi_device *dev, comedi_devconfig *it)
++static int me4000_probe(struct comedi_device *dev, comedi_devconfig *it)
+ {
+ 	struct pci_dev *pci_device;
+ 	int result, i;
+@@ -512,7 +512,7 @@ static int me4000_probe(comedi_device *dev, comedi_devconfig *it)
+ 	return 0;
+ }
+ 
+-static int get_registers(comedi_device *dev, struct pci_dev *pci_dev_p)
++static int get_registers(struct comedi_device *dev, struct pci_dev *pci_dev_p)
+ {
+ 
+ 	CALL_PDEBUG("In get_registers()\n");
+@@ -564,7 +564,7 @@ static int get_registers(comedi_device *dev, struct pci_dev *pci_dev_p)
+ 	return 0;
+ }
+ 
+-static int init_board_info(comedi_device *dev, struct pci_dev *pci_dev_p)
++static int init_board_info(struct comedi_device *dev, struct pci_dev *pci_dev_p)
+ {
+ 	int result;
+ 
+@@ -596,7 +596,7 @@ static int init_board_info(comedi_device *dev, struct pci_dev *pci_dev_p)
+ 	return 0;
+ }
+ 
+-static int init_ao_context(comedi_device *dev)
++static int init_ao_context(struct comedi_device *dev)
+ {
+ 	int i;
+ 
+@@ -679,7 +679,7 @@ static int init_ao_context(comedi_device *dev)
+ 	return 0;
+ }
+ 
+-static int init_ai_context(comedi_device *dev)
++static int init_ai_context(struct comedi_device *dev)
+ {
+ 
+ 	CALL_PDEBUG("In init_ai_context()\n");
+@@ -713,7 +713,7 @@ static int init_ai_context(comedi_device *dev)
+ 	return 0;
+ }
+ 
+-static int init_dio_context(comedi_device *dev)
++static int init_dio_context(struct comedi_device *dev)
+ {
+ 
+ 	CALL_PDEBUG("In init_dio_context()\n");
+@@ -732,7 +732,7 @@ static int init_dio_context(comedi_device *dev)
+ 	return 0;
+ }
+ 
+-static int init_cnt_context(comedi_device *dev)
++static int init_cnt_context(struct comedi_device *dev)
+ {
+ 
+ 	CALL_PDEBUG("In init_cnt_context()\n");
+@@ -753,7 +753,7 @@ static int init_cnt_context(comedi_device *dev)
+ extern unsigned char *xilinx_firm;
+ #endif
+ 
+-static int xilinx_download(comedi_device *dev)
++static int xilinx_download(struct comedi_device *dev)
+ {
+ 	u32 value = 0;
+ 	wait_queue_head_t queue;
+@@ -835,7 +835,7 @@ static int xilinx_download(comedi_device *dev)
+ 	return 0;
+ }
+ 
+-static int reset_board(comedi_device *dev)
++static int reset_board(struct comedi_device *dev)
+ {
+ 	unsigned long icr;
+ 
+@@ -893,7 +893,7 @@ static int reset_board(comedi_device *dev)
+ 	return 0;
+ }
+ 
+-static int me4000_detach(comedi_device *dev)
++static int me4000_detach(struct comedi_device *dev)
+ {
+ 	CALL_PDEBUG("In me4000_detach()\n");
+ 
+@@ -913,7 +913,7 @@ static int me4000_detach(comedi_device *dev)
+   Analog input section
+   ===========================================================================*/
+ 
+-static int me4000_ai_insn_read(comedi_device *dev,
++static int me4000_ai_insn_read(struct comedi_device *dev,
+ 	comedi_subdevice *subdevice, comedi_insn *insn, unsigned int *data)
+ {
+ 
+@@ -1037,7 +1037,7 @@ static int me4000_ai_insn_read(comedi_device *dev,
+ 	return 1;
+ }
+ 
+-static int me4000_ai_cancel(comedi_device *dev, comedi_subdevice *s)
++static int me4000_ai_cancel(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 	unsigned long tmp;
+ 
+@@ -1054,7 +1054,7 @@ static int me4000_ai_cancel(comedi_device *dev, comedi_subdevice *s)
+ 	return 0;
+ }
+ 
+-static int ai_check_chanlist(comedi_device *dev,
++static int ai_check_chanlist(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_cmd *cmd)
+ {
+ 	int aref;
+@@ -1135,7 +1135,7 @@ static int ai_check_chanlist(comedi_device *dev,
+ 	return 0;
+ }
+ 
+-static int ai_round_cmd_args(comedi_device *dev,
++static int ai_round_cmd_args(struct comedi_device *dev,
+ 	comedi_subdevice *s,
+ 	comedi_cmd *cmd,
+ 	unsigned int *init_ticks,
+@@ -1201,7 +1201,7 @@ static int ai_round_cmd_args(comedi_device *dev,
+ 	return 0;
+ }
+ 
+-static void ai_write_timer(comedi_device *dev,
++static void ai_write_timer(struct comedi_device *dev,
+ 	unsigned int init_ticks,
+ 	unsigned int scan_ticks, unsigned int chan_ticks)
+ {
+@@ -1222,7 +1222,7 @@ static void ai_write_timer(comedi_device *dev,
+ 	me4000_outl(dev, chan_ticks - 1, info->ai_context.chan_timer_reg);
+ }
+ 
+-static int ai_prepare(comedi_device *dev,
++static int ai_prepare(struct comedi_device *dev,
+ 	comedi_subdevice *s,
+ 	comedi_cmd *cmd,
+ 	unsigned int init_ticks,
+@@ -1291,7 +1291,7 @@ static int ai_prepare(comedi_device *dev,
+ 	return 0;
+ }
+ 
+-static int ai_write_chanlist(comedi_device *dev,
++static int ai_write_chanlist(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_cmd *cmd)
+ {
+ 	unsigned int entry;
+@@ -1331,7 +1331,7 @@ static int ai_write_chanlist(comedi_device *dev,
+ 	return 0;
+ }
+ 
+-static int me4000_ai_do_cmd(comedi_device *dev, comedi_subdevice *s)
++static int me4000_ai_do_cmd(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 	int err;
+ 	unsigned int init_ticks = 0;
+@@ -1375,7 +1375,7 @@ static int me4000_ai_do_cmd(comedi_device *dev, comedi_subdevice *s)
+  * - invalid chanlist
+  * So I tried to adopt this scheme.
+  */
+-static int me4000_ai_do_cmd_test(comedi_device *dev,
++static int me4000_ai_do_cmd_test(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_cmd *cmd)
+ {
+ 
+@@ -1743,7 +1743,7 @@ static int me4000_ai_do_cmd_test(comedi_device *dev,
+ static irqreturn_t me4000_ai_isr(int irq, void *dev_id PT_REGS_ARG)
+ {
+ 	unsigned int tmp;
+-	comedi_device *dev = dev_id;
++	struct comedi_device *dev = dev_id;
+ 	comedi_subdevice *s = dev->subdevices;
+ 	me4000_ai_context_t *ai_context = &info->ai_context;
+ 	int i;
+@@ -1903,7 +1903,7 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id PT_REGS_ARG)
+   Analog output section
+   ===========================================================================*/
+ 
+-static int me4000_ao_insn_write(comedi_device *dev,
++static int me4000_ao_insn_write(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 
+@@ -1961,7 +1961,7 @@ static int me4000_ao_insn_write(comedi_device *dev,
+ 	return 1;
+ }
+ 
+-static int me4000_ao_insn_read(comedi_device *dev,
++static int me4000_ao_insn_read(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -1982,7 +1982,7 @@ static int me4000_ao_insn_read(comedi_device *dev,
+   Digital I/O section
+   ===========================================================================*/
+ 
+-static int me4000_dio_insn_bits(comedi_device *dev,
++static int me4000_dio_insn_bits(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 
+@@ -2033,7 +2033,7 @@ static int me4000_dio_insn_bits(comedi_device *dev,
+ 	return 2;
+ }
+ 
+-static int me4000_dio_insn_config(comedi_device *dev,
++static int me4000_dio_insn_config(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned long tmp;
+@@ -2127,7 +2127,7 @@ static int me4000_dio_insn_config(comedi_device *dev,
+   Counter section
+   ===========================================================================*/
+ 
+-static int cnt_reset(comedi_device *dev, unsigned int channel)
++static int cnt_reset(struct comedi_device *dev, unsigned int channel)
+ {
+ 
+ 	CALL_PDEBUG("In cnt_reset()\n");
+@@ -2158,7 +2158,7 @@ static int cnt_reset(comedi_device *dev, unsigned int channel)
+ 	return 0;
+ }
+ 
+-static int cnt_config(comedi_device *dev, unsigned int channel,
++static int cnt_config(struct comedi_device *dev, unsigned int channel,
+ 	unsigned int mode)
+ {
+ 	int tmp = 0;
+@@ -2215,7 +2215,7 @@ static int cnt_config(comedi_device *dev, unsigned int channel,
+ 	return 0;
+ }
+ 
+-static int me4000_cnt_insn_config(comedi_device *dev,
++static int me4000_cnt_insn_config(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 
+@@ -2258,7 +2258,7 @@ static int me4000_cnt_insn_config(comedi_device *dev,
+ 	return 2;
+ }
+ 
+-static int me4000_cnt_insn_read(comedi_device *dev,
++static int me4000_cnt_insn_read(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 
+@@ -2305,7 +2305,7 @@ static int me4000_cnt_insn_read(comedi_device *dev,
+ 	return 1;
+ }
+ 
+-static int me4000_cnt_insn_write(comedi_device *dev,
++static int me4000_cnt_insn_write(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 
+diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c
+index 877920e35e1b..5e48eaaf5f28 100644
+--- a/drivers/staging/comedi/drivers/me_daq.c
++++ b/drivers/staging/comedi/drivers/me_daq.c
+@@ -144,8 +144,8 @@ from http://www.comedi.org
+ #define ME_COUNTER_VALUE_B		0x0022	/* R | - */
+ 
+ /* Function prototypes */
+-static int me_attach(comedi_device *dev, comedi_devconfig *it);
+-static int me_detach(comedi_device *dev);
++static int me_attach(struct comedi_device *dev, comedi_devconfig *it);
++static int me_detach(struct comedi_device *dev);
+ 
+ static const comedi_lrange me2000_ai_range = {
+ 	8,
+@@ -290,7 +290,7 @@ static inline void sleep(unsigned sec)
+  *
+  * ------------------------------------------------------------------
+  */
+-static int me_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
++static int me_dio_insn_config(struct comedi_device *dev, comedi_subdevice *s,
+ 			      comedi_insn *insn, unsigned int *data)
+ {
+ 	int bits;
+@@ -326,7 +326,7 @@ static int me_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ /* Digital instant input/outputs */
+-static int me_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
++static int me_dio_insn_bits(struct comedi_device *dev, comedi_subdevice *s,
+ 			    comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int mask = data[0];
+@@ -362,7 +362,7 @@ static int me_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
+  */
+ 
+ /* Analog instant input */
+-static int me_ai_insn_read(comedi_device *dev, comedi_subdevice *subdevice,
++static int me_ai_insn_read(struct comedi_device *dev, comedi_subdevice *subdevice,
+ 			   comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned short value;
+@@ -436,7 +436,7 @@ static int me_ai_insn_read(comedi_device *dev, comedi_subdevice *subdevice,
+  */
+ 
+ /* Cancel analog input autoscan */
+-static int me_ai_cancel(comedi_device *dev, comedi_subdevice *s)
++static int me_ai_cancel(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 	/* disable interrupts */
+ 
+@@ -448,14 +448,14 @@ static int me_ai_cancel(comedi_device *dev, comedi_subdevice *s)
+ }
+ 
+ /* Test analog input command */
+-static int me_ai_do_cmd_test(comedi_device *dev, comedi_subdevice *s,
++static int me_ai_do_cmd_test(struct comedi_device *dev, comedi_subdevice *s,
+ 			     comedi_cmd *cmd)
+ {
+ 	return 0;
+ }
+ 
+ /* Analog input command */
+-static int me_ai_do_cmd(comedi_device *dev, comedi_subdevice *subdevice)
++static int me_ai_do_cmd(struct comedi_device *dev, comedi_subdevice *subdevice)
+ {
+ 	return 0;
+ }
+@@ -469,7 +469,7 @@ static int me_ai_do_cmd(comedi_device *dev, comedi_subdevice *subdevice)
+  */
+ 
+ /* Analog instant output */
+-static int me_ao_insn_write(comedi_device *dev, comedi_subdevice *s,
++static int me_ao_insn_write(struct comedi_device *dev, comedi_subdevice *s,
+ 			    comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan;
+@@ -519,7 +519,7 @@ static int me_ao_insn_write(comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ /* Analog output readback */
+-static int me_ao_insn_read(comedi_device *dev, comedi_subdevice *s,
++static int me_ao_insn_read(struct comedi_device *dev, comedi_subdevice *s,
+ 			   comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+@@ -541,7 +541,7 @@ static int me_ao_insn_read(comedi_device *dev, comedi_subdevice *s,
+  */
+ 
+ /* Xilinx firmware download for card: ME-2600i */
+-static int me2600_xilinx_download(comedi_device *dev,
++static int me2600_xilinx_download(struct comedi_device *dev,
+ 				  unsigned char *me2600_firmware,
+ 				  unsigned int length)
+ {
+@@ -609,7 +609,7 @@ static int me2600_xilinx_download(comedi_device *dev,
+ }
+ 
+ /* Reset device */
+-static int me_reset(comedi_device *dev)
++static int me_reset(struct comedi_device *dev)
+ {
+ 	/* Reset board */
+ 	writew(0x00, dev_private->me_regbase + ME_CONTROL_1);
+@@ -631,7 +631,7 @@ static int me_reset(comedi_device *dev)
+  * - Register PCI device
+  * - Declare device driver capability
+  */
+-static int me_attach(comedi_device *dev, comedi_devconfig *it)
++static int me_attach(struct comedi_device *dev, comedi_devconfig *it)
+ {
+ 	struct pci_dev *pci_device;
+ 	comedi_subdevice *subdevice;
+@@ -825,7 +825,7 @@ static int me_attach(comedi_device *dev, comedi_devconfig *it)
+ }
+ 
+ /* Detach */
+-static int me_detach(comedi_device *dev)
++static int me_detach(struct comedi_device *dev)
+ {
+ 	if (dev_private) {
+ 		if (dev_private->me_regbase) {
+diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c
+index a4be0721d69f..6bbcdde62ad3 100644
+--- a/drivers/staging/comedi/drivers/mpc624.c
++++ b/drivers/staging/comedi/drivers/mpc624.c
+@@ -144,8 +144,8 @@ static const comedi_lrange range_mpc624_bipolar10 = {
+ };
+ 
+ //----------------------------------------------------------------------------
+-static int mpc624_attach(comedi_device * dev, comedi_devconfig * it);
+-static int mpc624_detach(comedi_device * dev);
++static int mpc624_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int mpc624_detach(struct comedi_device * dev);
+ //----------------------------------------------------------------------------
+ static comedi_driver driver_mpc624 = {
+       driver_name:"mpc624",
+@@ -155,10 +155,10 @@ static comedi_driver driver_mpc624 = {
+ };
+ 
+ //----------------------------------------------------------------------------
+-static int mpc624_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int mpc624_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ //----------------------------------------------------------------------------
+-static int mpc624_attach(comedi_device * dev, comedi_devconfig * it)
++static int mpc624_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	unsigned long iobase;
+@@ -255,7 +255,7 @@ static int mpc624_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 1;
+ }
+ 
+-static int mpc624_detach(comedi_device * dev)
++static int mpc624_detach(struct comedi_device * dev)
+ {
+ 	rt_printk("comedi%d: mpc624: remove\n", dev->minor);
+ 
+@@ -268,7 +268,7 @@ static int mpc624_detach(comedi_device * dev)
+ // Timeout 200ms
+ #define TIMEOUT 200
+ 
+-static int mpc624_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int mpc624_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i;
+diff --git a/drivers/staging/comedi/drivers/mpc8260cpm.c b/drivers/staging/comedi/drivers/mpc8260cpm.c
+index b3a64bbbf0c3..f1f14514ff27 100644
+--- a/drivers/staging/comedi/drivers/mpc8260cpm.c
++++ b/drivers/staging/comedi/drivers/mpc8260cpm.c
+@@ -44,8 +44,8 @@ typedef struct {
+ } mpc8260cpm_private;
+ #define devpriv ((mpc8260cpm_private *)dev->private)
+ 
+-static int mpc8260cpm_attach(comedi_device * dev, comedi_devconfig * it);
+-static int mpc8260cpm_detach(comedi_device * dev);
++static int mpc8260cpm_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int mpc8260cpm_detach(struct comedi_device * dev);
+ static comedi_driver driver_mpc8260cpm = {
+       driver_name:"mpc8260cpm",
+       module:THIS_MODULE,
+@@ -55,12 +55,12 @@ static comedi_driver driver_mpc8260cpm = {
+ 
+ COMEDI_INITCLEANUP(driver_mpc8260cpm);
+ 
+-static int mpc8260cpm_dio_config(comedi_device * dev, comedi_subdevice * s,
++static int mpc8260cpm_dio_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int mpc8260cpm_dio_bits(comedi_device * dev, comedi_subdevice * s,
++static int mpc8260cpm_dio_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int mpc8260cpm_attach(comedi_device * dev, comedi_devconfig * it)
++static int mpc8260cpm_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	int i;
+@@ -91,7 +91,7 @@ static int mpc8260cpm_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 1;
+ }
+ 
+-static int mpc8260cpm_detach(comedi_device * dev)
++static int mpc8260cpm_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: mpc8260cpm: remove\n", dev->minor);
+ 
+@@ -112,7 +112,7 @@ static unsigned long *cpm_pdat(int port)
+ 	}
+ }
+ 
+-static int mpc8260cpm_dio_config(comedi_device * dev, comedi_subdevice * s,
++static int mpc8260cpm_dio_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -155,7 +155,7 @@ static int mpc8260cpm_dio_config(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int mpc8260cpm_dio_bits(comedi_device * dev, comedi_subdevice * s,
++static int mpc8260cpm_dio_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int port;
+diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c
+index dd9648d68a88..477185b33d72 100644
+--- a/drivers/staging/comedi/drivers/multiq3.c
++++ b/drivers/staging/comedi/drivers/multiq3.c
+@@ -82,8 +82,8 @@ Devices: [Quanser Consulting] MultiQ-3 (multiq3)
+ 
+ #define MULTIQ3_TIMEOUT 30
+ 
+-static int multiq3_attach(comedi_device * dev, comedi_devconfig * it);
+-static int multiq3_detach(comedi_device * dev);
++static int multiq3_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int multiq3_detach(struct comedi_device * dev);
+ static comedi_driver driver_multiq3 = {
+       driver_name:"multiq3",
+       module:THIS_MODULE,
+@@ -98,7 +98,7 @@ struct multiq3_private {
+ };
+ #define devpriv ((struct multiq3_private *)dev->private)
+ 
+-static int multiq3_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int multiq3_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+@@ -134,7 +134,7 @@ static int multiq3_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int multiq3_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int multiq3_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -147,7 +147,7 @@ static int multiq3_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int multiq3_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
++static int multiq3_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -165,7 +165,7 @@ static int multiq3_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int multiq3_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int multiq3_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -176,7 +176,7 @@ static int multiq3_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int multiq3_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int multiq3_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -191,7 +191,7 @@ static int multiq3_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int multiq3_encoder_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int multiq3_encoder_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -212,7 +212,7 @@ static int multiq3_encoder_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static void encoder_reset(comedi_device * dev)
++static void encoder_reset(struct comedi_device * dev)
+ {
+ 	int chan;
+ 	for (chan = 0; chan < dev->subdevices[4].n_chan; chan++) {
+@@ -235,7 +235,7 @@ static void encoder_reset(comedi_device * dev)
+    options[2] - number of encoder chips installed
+  */
+ 
+-static int multiq3_attach(comedi_device * dev, comedi_devconfig * it)
++static int multiq3_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int result = 0;
+ 	unsigned long iobase;
+@@ -318,7 +318,7 @@ static int multiq3_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int multiq3_detach(comedi_device * dev)
++static int multiq3_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: multiq3: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
+index 17c33a591fd1..bb9af22fbc44 100644
+--- a/drivers/staging/comedi/drivers/ni_6527.c
++++ b/drivers/staging/comedi/drivers/ni_6527.c
+@@ -75,8 +75,8 @@ Updated: Sat, 25 Jan 2003 13:24:40 -0800
+ #define Rising_Edge_Detection_Enable(x)		(0x018+(x))
+ #define Falling_Edge_Detection_Enable(x)	(0x020+(x))
+ 
+-static int ni6527_attach(comedi_device * dev, comedi_devconfig * it);
+-static int ni6527_detach(comedi_device * dev);
++static int ni6527_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int ni6527_detach(struct comedi_device * dev);
+ static comedi_driver driver_ni6527 = {
+       driver_name:"ni6527",
+       module:THIS_MODULE,
+@@ -117,9 +117,9 @@ typedef struct {
+ } ni6527_private;
+ #define devpriv ((ni6527_private *)dev->private)
+ 
+-static int ni6527_find_device(comedi_device * dev, int bus, int slot);
++static int ni6527_find_device(struct comedi_device * dev, int bus, int slot);
+ 
+-static int ni6527_di_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int ni6527_di_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -167,7 +167,7 @@ static int ni6527_di_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int ni6527_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int ni6527_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -180,7 +180,7 @@ static int ni6527_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int ni6527_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int ni6527_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -211,7 +211,7 @@ static int ni6527_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 
+ static irqreturn_t ni6527_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s = dev->subdevices + 2;
+ 	unsigned int status;
+ 
+@@ -230,7 +230,7 @@ static irqreturn_t ni6527_interrupt(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int ni6527_intr_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int ni6527_intr_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -306,7 +306,7 @@ static int ni6527_intr_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int ni6527_intr_cmd(comedi_device * dev, comedi_subdevice * s)
++static int ni6527_intr_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	//comedi_cmd *cmd = &s->async->cmd;
+ 
+@@ -319,14 +319,14 @@ static int ni6527_intr_cmd(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ni6527_intr_cancel(comedi_device * dev, comedi_subdevice * s)
++static int ni6527_intr_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	writeb(0x00, devpriv->mite->daq_io_addr + Master_Interrupt_Control);
+ 
+ 	return 0;
+ }
+ 
+-static int ni6527_intr_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int ni6527_intr_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n < 1)
+@@ -336,7 +336,7 @@ static int ni6527_intr_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int ni6527_intr_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int ni6527_intr_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n < 1)
+@@ -361,7 +361,7 @@ static int ni6527_intr_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int ni6527_attach(comedi_device * dev, comedi_devconfig * it)
++static int ni6527_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	int ret;
+@@ -439,7 +439,7 @@ static int ni6527_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int ni6527_detach(comedi_device * dev)
++static int ni6527_detach(struct comedi_device * dev)
+ {
+ 	if (devpriv && devpriv->mite && devpriv->mite->daq_io_addr) {
+ 		writeb(0x00,
+@@ -457,7 +457,7 @@ static int ni6527_detach(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int ni6527_find_device(comedi_device * dev, int bus, int slot)
++static int ni6527_find_device(struct comedi_device * dev, int bus, int slot)
+ {
+ 	struct mite_struct *mite;
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
+index cc5ada875359..347925b4963b 100644
+--- a/drivers/staging/comedi/drivers/ni_65xx.c
++++ b/drivers/staging/comedi/drivers/ni_65xx.c
+@@ -102,8 +102,8 @@ static inline unsigned Filter_Enable(unsigned port)
+ #define OverflowIntEnable		0x02
+ #define EdgeIntEnable			0x01
+ 
+-static int ni_65xx_attach(comedi_device * dev, comedi_devconfig * it);
+-static int ni_65xx_detach(comedi_device * dev);
++static int ni_65xx_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int ni_65xx_detach(struct comedi_device * dev);
+ static comedi_driver driver_ni_65xx = {
+       driver_name:"ni_65xx",
+       module:THIS_MODULE,
+@@ -239,7 +239,7 @@ static const ni_65xx_board ni_65xx_boards[] = {
+ };
+ 
+ #define n_ni_65xx_boards (sizeof(ni_65xx_boards)/sizeof(ni_65xx_boards[0]))
+-static inline const ni_65xx_board *board(comedi_device * dev)
++static inline const ni_65xx_board *board(struct comedi_device * dev)
+ {
+ 	return dev->board_ptr;
+ }
+@@ -287,7 +287,7 @@ typedef struct {
+ 	unsigned short output_bits[NI_65XX_MAX_NUM_PORTS];
+ 	unsigned short dio_direction[NI_65XX_MAX_NUM_PORTS];
+ } ni_65xx_private;
+-static inline ni_65xx_private *private(comedi_device * dev)
++static inline ni_65xx_private *private(struct comedi_device * dev)
+ {
+ 	return dev->private;
+ }
+@@ -308,9 +308,9 @@ static ni_65xx_subdevice_private *ni_65xx_alloc_subdevice_private(void)
+ 	return subdev_private;
+ }
+ 
+-static int ni_65xx_find_device(comedi_device * dev, int bus, int slot);
++static int ni_65xx_find_device(struct comedi_device * dev, int bus, int slot);
+ 
+-static int ni_65xx_config_filter(comedi_device * dev, comedi_subdevice * s,
++static int ni_65xx_config_filter(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	const unsigned chan = CR_CHAN(insn->chanspec);
+@@ -349,7 +349,7 @@ static int ni_65xx_config_filter(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int ni_65xx_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int ni_65xx_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned port;
+@@ -388,7 +388,7 @@ static int ni_65xx_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 	return -EINVAL;
+ }
+ 
+-static int ni_65xx_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int ni_65xx_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned base_bitfield_channel;
+@@ -452,7 +452,7 @@ static int ni_65xx_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 
+ static irqreturn_t ni_65xx_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s = dev->subdevices + 2;
+ 	unsigned int status;
+ 
+@@ -471,7 +471,7 @@ static irqreturn_t ni_65xx_interrupt(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int ni_65xx_intr_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int ni_65xx_intr_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -547,7 +547,7 @@ static int ni_65xx_intr_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int ni_65xx_intr_cmd(comedi_device * dev, comedi_subdevice * s)
++static int ni_65xx_intr_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	//comedi_cmd *cmd = &s->async->cmd;
+ 
+@@ -560,7 +560,7 @@ static int ni_65xx_intr_cmd(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ni_65xx_intr_cancel(comedi_device * dev, comedi_subdevice * s)
++static int ni_65xx_intr_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	writeb(0x00,
+ 		private(dev)->mite->daq_io_addr + Master_Interrupt_Control);
+@@ -568,7 +568,7 @@ static int ni_65xx_intr_cancel(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ni_65xx_intr_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int ni_65xx_intr_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n < 1)
+@@ -578,7 +578,7 @@ static int ni_65xx_intr_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int ni_65xx_intr_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int ni_65xx_intr_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n < 1)
+@@ -615,7 +615,7 @@ static int ni_65xx_intr_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int ni_65xx_attach(comedi_device * dev, comedi_devconfig * it)
++static int ni_65xx_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	unsigned i;
+@@ -748,7 +748,7 @@ static int ni_65xx_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int ni_65xx_detach(comedi_device * dev)
++static int ni_65xx_detach(struct comedi_device * dev)
+ {
+ 	if (private(dev) && private(dev)->mite
+ 		&& private(dev)->mite->daq_io_addr) {
+@@ -776,7 +776,7 @@ static int ni_65xx_detach(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int ni_65xx_find_device(comedi_device * dev, int bus, int slot)
++static int ni_65xx_find_device(struct comedi_device * dev, int bus, int slot)
+ {
+ 	struct mite_struct *mite;
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
+index 896e2ea4b04d..531709724b75 100644
+--- a/drivers/staging/comedi/drivers/ni_660x.c
++++ b/drivers/staging/comedi/drivers/ni_660x.c
+@@ -431,23 +431,23 @@ typedef struct {
+ 	unsigned short pfi_output_selects[NUM_PFI_CHANNELS];
+ } ni_660x_private;
+ 
+-static inline ni_660x_private *private(comedi_device * dev)
++static inline ni_660x_private *private(struct comedi_device * dev)
+ {
+ 	return dev->private;
+ }
+ 
+ /* initialized in ni_660x_find_device() */
+-static inline const ni_660x_board *board(comedi_device * dev)
++static inline const ni_660x_board *board(struct comedi_device * dev)
+ {
+ 	return dev->board_ptr;
+ }
+ 
+ #define n_ni_660x_boards (sizeof(ni_660x_boards)/sizeof(ni_660x_boards[0]))
+ 
+-static int ni_660x_attach(comedi_device * dev, comedi_devconfig * it);
+-static int ni_660x_detach(comedi_device * dev);
+-static void init_tio_chip(comedi_device * dev, int chipset);
+-static void ni_660x_select_pfi_output(comedi_device * dev, unsigned pfi_channel,
++static int ni_660x_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int ni_660x_detach(struct comedi_device * dev);
++static void init_tio_chip(struct comedi_device * dev, int chipset);
++static void ni_660x_select_pfi_output(struct comedi_device * dev, unsigned pfi_channel,
+ 	unsigned output_select);
+ 
+ static comedi_driver driver_ni_660x = {
+@@ -459,25 +459,25 @@ static comedi_driver driver_ni_660x = {
+ 
+ COMEDI_PCI_INITCLEANUP(driver_ni_660x, ni_660x_pci_table);
+ 
+-static int ni_660x_find_device(comedi_device * dev, int bus, int slot);
+-static int ni_660x_set_pfi_routing(comedi_device * dev, unsigned chan,
++static int ni_660x_find_device(struct comedi_device * dev, int bus, int slot);
++static int ni_660x_set_pfi_routing(struct comedi_device * dev, unsigned chan,
+ 	unsigned source);
+ 
+ /* Possible instructions for a GPCT */
+-static int ni_660x_GPCT_rinsn(comedi_device * dev,
++static int ni_660x_GPCT_rinsn(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+-static int ni_660x_GPCT_insn_config(comedi_device * dev,
++static int ni_660x_GPCT_insn_config(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+-static int ni_660x_GPCT_winsn(comedi_device * dev,
++static int ni_660x_GPCT_winsn(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+ /* Possible instructions for Digital IO */
+-static int ni_660x_dio_insn_config(comedi_device * dev,
++static int ni_660x_dio_insn_config(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+-static int ni_660x_dio_insn_bits(comedi_device * dev,
++static int ni_660x_dio_insn_bits(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+-static inline unsigned ni_660x_num_counters(comedi_device * dev)
++static inline unsigned ni_660x_num_counters(struct comedi_device * dev)
+ {
+ 	return board(dev)->n_chips * counters_per_chip;
+ }
+@@ -700,7 +700,7 @@ static NI_660x_Register ni_gpct_to_660x_register(enum ni_gpct_register reg)
+ 	return ni_660x_register;
+ }
+ 
+-static inline void ni_660x_write_register(comedi_device * dev,
++static inline void ni_660x_write_register(struct comedi_device * dev,
+ 	unsigned chip_index, unsigned bits, NI_660x_Register reg)
+ {
+ 	void *const write_address =
+@@ -722,7 +722,7 @@ static inline void ni_660x_write_register(comedi_device * dev,
+ 	}
+ }
+ 
+-static inline unsigned ni_660x_read_register(comedi_device * dev,
++static inline unsigned ni_660x_read_register(struct comedi_device * dev,
+ 	unsigned chip_index, NI_660x_Register reg)
+ {
+ 	void *const read_address =
+@@ -748,7 +748,7 @@ static inline unsigned ni_660x_read_register(comedi_device * dev,
+ static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits,
+ 	enum ni_gpct_register reg)
+ {
+-	comedi_device *dev = counter->counter_dev->dev;
++	struct comedi_device *dev = counter->counter_dev->dev;
+ 	NI_660x_Register ni_660x_register = ni_gpct_to_660x_register(reg);
+ 	ni_660x_write_register(dev, counter->chip_index, bits,
+ 		ni_660x_register);
+@@ -757,7 +757,7 @@ static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits,
+ static unsigned ni_gpct_read_register(struct ni_gpct *counter,
+ 	enum ni_gpct_register reg)
+ {
+-	comedi_device *dev = counter->counter_dev->dev;
++	struct comedi_device *dev = counter->counter_dev->dev;
+ 	NI_660x_Register ni_660x_register = ni_gpct_to_660x_register(reg);
+ 	return ni_660x_read_register(dev, counter->chip_index,
+ 		ni_660x_register);
+@@ -769,7 +769,7 @@ static inline struct mite_dma_descriptor_ring *mite_ring(ni_660x_private * priv,
+ 	return priv->mite_rings[counter->chip_index][counter->counter_index];
+ }
+ 
+-static inline void ni_660x_set_dma_channel(comedi_device * dev,
++static inline void ni_660x_set_dma_channel(struct comedi_device * dev,
+ 	unsigned mite_channel, struct ni_gpct *counter)
+ {
+ 	unsigned long flags;
+@@ -787,7 +787,7 @@ static inline void ni_660x_set_dma_channel(comedi_device * dev,
+ 	comedi_spin_unlock_irqrestore(&private(dev)->soft_reg_copy_lock, flags);
+ }
+ 
+-static inline void ni_660x_unset_dma_channel(comedi_device * dev,
++static inline void ni_660x_unset_dma_channel(struct comedi_device * dev,
+ 	unsigned mite_channel, struct ni_gpct *counter)
+ {
+ 	unsigned long flags;
+@@ -803,7 +803,7 @@ static inline void ni_660x_unset_dma_channel(comedi_device * dev,
+ 	comedi_spin_unlock_irqrestore(&private(dev)->soft_reg_copy_lock, flags);
+ }
+ 
+-static int ni_660x_request_mite_channel(comedi_device * dev,
++static int ni_660x_request_mite_channel(struct comedi_device * dev,
+ 	struct ni_gpct *counter, enum comedi_io_direction direction)
+ {
+ 	unsigned long flags;
+@@ -828,7 +828,7 @@ static int ni_660x_request_mite_channel(comedi_device * dev,
+ 	return 0;
+ }
+ 
+-void ni_660x_release_mite_channel(comedi_device * dev, struct ni_gpct *counter)
++void ni_660x_release_mite_channel(struct comedi_device * dev, struct ni_gpct *counter)
+ {
+ 	unsigned long flags;
+ 
+@@ -843,7 +843,7 @@ void ni_660x_release_mite_channel(comedi_device * dev, struct ni_gpct *counter)
+ 	comedi_spin_unlock_irqrestore(&private(dev)->mite_channel_lock, flags);
+ }
+ 
+-static int ni_660x_cmd(comedi_device * dev, comedi_subdevice * s)
++static int ni_660x_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	int retval;
+ 
+@@ -862,7 +862,7 @@ static int ni_660x_cmd(comedi_device * dev, comedi_subdevice * s)
+ 	return retval;
+ }
+ 
+-static int ni_660x_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int ni_660x_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	struct ni_gpct *counter = subdev_to_counter(s);
+@@ -870,7 +870,7 @@ static int ni_660x_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	return ni_tio_cmdtest(counter, cmd);
+ }
+ 
+-static int ni_660x_cancel(comedi_device * dev, comedi_subdevice * s)
++static int ni_660x_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	struct ni_gpct *counter = subdev_to_counter(s);
+ 	int retval;
+@@ -880,7 +880,7 @@ static int ni_660x_cancel(comedi_device * dev, comedi_subdevice * s)
+ 	return retval;
+ }
+ 
+-static void set_tio_counterswap(comedi_device * dev, int chipset)
++static void set_tio_counterswap(struct comedi_device * dev, int chipset)
+ {
+ 	/* See P. 3.5 of the Register-Level Programming manual.  The
+ 	   CounterSwap bit has to be set on the second chip, otherwise
+@@ -893,7 +893,7 @@ static void set_tio_counterswap(comedi_device * dev, int chipset)
+ 		ni_660x_write_register(dev, chipset, 0, ClockConfigRegister);
+ }
+ 
+-static void ni_660x_handle_gpct_interrupt(comedi_device * dev,
++static void ni_660x_handle_gpct_interrupt(struct comedi_device * dev,
+ 	comedi_subdevice * s)
+ {
+ 	ni_tio_handle_interrupt(subdev_to_counter(s), s);
+@@ -909,7 +909,7 @@ static void ni_660x_handle_gpct_interrupt(comedi_device * dev,
+ 
+ static irqreturn_t ni_660x_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s;
+ 	unsigned i;
+ 
+@@ -923,7 +923,7 @@ static irqreturn_t ni_660x_interrupt(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int ni_660x_buf_change(comedi_device * dev, comedi_subdevice * s,
++static int ni_660x_buf_change(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned long new_size)
+ {
+ 	int ret;
+@@ -936,7 +936,7 @@ static int ni_660x_buf_change(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int ni_660x_allocate_private(comedi_device * dev)
++static int ni_660x_allocate_private(struct comedi_device * dev)
+ {
+ 	int retval;
+ 	unsigned i;
+@@ -951,7 +951,7 @@ static int ni_660x_allocate_private(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int ni_660x_alloc_mite_rings(comedi_device * dev)
++static int ni_660x_alloc_mite_rings(struct comedi_device * dev)
+ {
+ 	unsigned i;
+ 	unsigned j;
+@@ -968,7 +968,7 @@ static int ni_660x_alloc_mite_rings(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static void ni_660x_free_mite_rings(comedi_device * dev)
++static void ni_660x_free_mite_rings(struct comedi_device * dev)
+ {
+ 	unsigned i;
+ 	unsigned j;
+@@ -980,7 +980,7 @@ static void ni_660x_free_mite_rings(comedi_device * dev)
+ 	}
+ }
+ 
+-static int ni_660x_attach(comedi_device * dev, comedi_devconfig * it)
++static int ni_660x_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	int ret;
+@@ -1100,7 +1100,7 @@ static int ni_660x_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int ni_660x_detach(comedi_device * dev)
++static int ni_660x_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: ni_660x: remove\n", dev->minor);
+ 
+@@ -1120,13 +1120,13 @@ static int ni_660x_detach(comedi_device * dev)
+ }
+ 
+ static int
+-ni_660x_GPCT_rinsn(comedi_device * dev, comedi_subdevice * s,
++ni_660x_GPCT_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	return ni_tio_rinsn(subdev_to_counter(s), insn, data);
+ }
+ 
+-static void init_tio_chip(comedi_device * dev, int chipset)
++static void init_tio_chip(struct comedi_device * dev, int chipset)
+ {
+ 	unsigned i;
+ 
+@@ -1147,19 +1147,19 @@ static void init_tio_chip(comedi_device * dev, int chipset)
+ }
+ 
+ static int
+-ni_660x_GPCT_insn_config(comedi_device * dev, comedi_subdevice * s,
++ni_660x_GPCT_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	return ni_tio_insn_config(subdev_to_counter(s), insn, data);
+ }
+ 
+-static int ni_660x_GPCT_winsn(comedi_device * dev,
++static int ni_660x_GPCT_winsn(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	return ni_tio_winsn(subdev_to_counter(s), insn, data);
+ }
+ 
+-static int ni_660x_find_device(comedi_device * dev, int bus, int slot)
++static int ni_660x_find_device(struct comedi_device * dev, int bus, int slot)
+ {
+ 	struct mite_struct *mite;
+ 	int i;
+@@ -1186,7 +1186,7 @@ static int ni_660x_find_device(comedi_device * dev, int bus, int slot)
+ 	return -EIO;
+ }
+ 
+-static int ni_660x_dio_insn_bits(comedi_device * dev,
++static int ni_660x_dio_insn_bits(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned base_bitfield_channel = CR_CHAN(insn->chanspec);
+@@ -1206,7 +1206,7 @@ static int ni_660x_dio_insn_bits(comedi_device * dev,
+ 	return 2;
+ }
+ 
+-static void ni_660x_select_pfi_output(comedi_device * dev, unsigned pfi_channel,
++static void ni_660x_select_pfi_output(struct comedi_device * dev, unsigned pfi_channel,
+ 	unsigned output_select)
+ {
+ 	static const unsigned counter_4_7_first_pfi = 8;
+@@ -1241,7 +1241,7 @@ static void ni_660x_select_pfi_output(comedi_device * dev, unsigned pfi_channel,
+ 	ni_660x_write_register(dev, active_chipset, active_bits, IOConfigReg(pfi_channel));
+ }
+ 
+-static int ni_660x_set_pfi_routing(comedi_device * dev, unsigned chan,
++static int ni_660x_set_pfi_routing(struct comedi_device * dev, unsigned chan,
+ 	unsigned source)
+ {
+ 	if (source > num_pfi_output_selects)
+@@ -1264,13 +1264,13 @@ static int ni_660x_set_pfi_routing(comedi_device * dev, unsigned chan,
+ 	return 0;
+ }
+ 
+-static unsigned ni_660x_get_pfi_routing(comedi_device * dev, unsigned chan)
++static unsigned ni_660x_get_pfi_routing(struct comedi_device * dev, unsigned chan)
+ {
+ 	BUG_ON(chan >= NUM_PFI_CHANNELS);
+ 	return private(dev)->pfi_output_selects[chan];
+ }
+ 
+-static void ni660x_config_filter(comedi_device * dev, unsigned pfi_channel,
++static void ni660x_config_filter(struct comedi_device * dev, unsigned pfi_channel,
+ 	enum ni_gpct_filter_select filter)
+ {
+ 	unsigned bits = ni_660x_read_register(dev, 0, IOConfigReg(pfi_channel));
+@@ -1279,7 +1279,7 @@ static void ni660x_config_filter(comedi_device * dev, unsigned pfi_channel,
+ 	ni_660x_write_register(dev, 0, bits, IOConfigReg(pfi_channel));
+ }
+ 
+-static int ni_660x_dio_insn_config(comedi_device * dev,
++static int ni_660x_dio_insn_config(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
+index 5e1cb2abe870..4c0cc433312a 100644
+--- a/drivers/staging/comedi/drivers/ni_670x.c
++++ b/drivers/staging/comedi/drivers/ni_670x.c
+@@ -108,8 +108,8 @@ typedef struct {
+ #define devpriv ((ni_670x_private *)dev->private)
+ #define n_ni_670x_boards (sizeof(ni_670x_boards)/sizeof(ni_670x_boards[0]))
+ 
+-static int ni_670x_attach(comedi_device * dev, comedi_devconfig * it);
+-static int ni_670x_detach(comedi_device * dev);
++static int ni_670x_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int ni_670x_detach(struct comedi_device * dev);
+ 
+ static comedi_driver driver_ni_670x = {
+       driver_name:"ni_670x",
+@@ -122,18 +122,18 @@ COMEDI_PCI_INITCLEANUP(driver_ni_670x, ni_670x_pci_table);
+ 
+ static comedi_lrange range_0_20mA = { 1, {RANGE_mA(0, 20)} };
+ 
+-static int ni_670x_find_device(comedi_device * dev, int bus, int slot);
++static int ni_670x_find_device(struct comedi_device * dev, int bus, int slot);
+ 
+-static int ni_670x_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int ni_670x_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_670x_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int ni_670x_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_670x_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int ni_670x_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_670x_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int ni_670x_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int ni_670x_attach(comedi_device * dev, comedi_devconfig * it)
++static int ni_670x_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	int ret;
+@@ -202,7 +202,7 @@ static int ni_670x_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 1;
+ }
+ 
+-static int ni_670x_detach(comedi_device * dev)
++static int ni_670x_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: ni_670x: remove\n", dev->minor);
+ 
+@@ -218,7 +218,7 @@ static int ni_670x_detach(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int ni_670x_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int ni_670x_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -244,7 +244,7 @@ static int ni_670x_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int ni_670x_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int ni_670x_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -256,7 +256,7 @@ static int ni_670x_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int ni_670x_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int ni_670x_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -278,7 +278,7 @@ static int ni_670x_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int ni_670x_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int ni_670x_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -305,7 +305,7 @@ static int ni_670x_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 	return insn->n;
+ }
+ 
+-static int ni_670x_find_device(comedi_device * dev, int bus, int slot)
++static int ni_670x_find_device(struct comedi_device * dev, int bus, int slot)
+ {
+ 	struct mite_struct *mite;
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
+index 2d7f5528b402..bf16e1273825 100644
+--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
++++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
+@@ -167,9 +167,9 @@ typedef struct {
+ 
+ #define devpriv ((a2150_private *)dev->private)
+ 
+-static int a2150_attach(comedi_device * dev, comedi_devconfig * it);
+-static int a2150_detach(comedi_device * dev);
+-static int a2150_cancel(comedi_device * dev, comedi_subdevice * s);
++static int a2150_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int a2150_detach(struct comedi_device * dev);
++static int a2150_cancel(struct comedi_device * dev, comedi_subdevice * s);
+ 
+ static comedi_driver driver_a2150 = {
+       driver_name:"ni_at_a2150",
+@@ -179,15 +179,15 @@ static comedi_driver driver_a2150 = {
+ };
+ 
+ static irqreturn_t a2150_interrupt(int irq, void *d PT_REGS_ARG);
+-static int a2150_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int a2150_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int a2150_ai_cmd(comedi_device * dev, comedi_subdevice * s);
+-static int a2150_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int a2150_ai_cmd(struct comedi_device * dev, comedi_subdevice * s);
++static int a2150_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int a2150_get_timing(comedi_device * dev, unsigned int *period,
++static int a2150_get_timing(struct comedi_device * dev, unsigned int *period,
+ 	int flags);
+-static int a2150_probe(comedi_device * dev);
+-static int a2150_set_chanlist(comedi_device * dev, unsigned int start_channel,
++static int a2150_probe(struct comedi_device * dev);
++static int a2150_set_chanlist(struct comedi_device * dev, unsigned int start_channel,
+ 	unsigned int num_channels);
+ /*
+  * A convenient macro that defines init_module() and cleanup_module(),
+@@ -197,7 +197,7 @@ COMEDI_INITCLEANUP(driver_a2150);
+ 
+ #ifdef A2150_DEBUG
+ 
+-static void ni_dump_regs(comedi_device * dev)
++static void ni_dump_regs(struct comedi_device * dev)
+ {
+ 	rt_printk("config bits 0x%x\n", devpriv->config_bits);
+ 	rt_printk("irq dma bits 0x%x\n", devpriv->irq_dma_bits);
+@@ -212,7 +212,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d PT_REGS_ARG)
+ 	int i;
+ 	int status;
+ 	unsigned long flags;
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s = dev->read_subdev;
+ 	comedi_async *async;
+ 	comedi_cmd *cmd;
+@@ -316,13 +316,13 @@ static irqreturn_t a2150_interrupt(int irq, void *d PT_REGS_ARG)
+ }
+ 
+ // probes board type, returns offset
+-static int a2150_probe(comedi_device * dev)
++static int a2150_probe(struct comedi_device * dev)
+ {
+ 	int status = inw(dev->iobase + STATUS_REG);
+ 	return ID_BITS(status);
+ }
+ 
+-static int a2150_attach(comedi_device * dev, comedi_devconfig * it)
++static int a2150_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	unsigned long iobase = it->options[0];
+@@ -447,7 +447,7 @@ static int a2150_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ };
+ 
+-static int a2150_detach(comedi_device * dev)
++static int a2150_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: %s: remove\n", dev->minor, driver_a2150.driver_name);
+ 
+@@ -470,7 +470,7 @@ static int a2150_detach(comedi_device * dev)
+ 	return 0;
+ };
+ 
+-static int a2150_cancel(comedi_device * dev, comedi_subdevice * s)
++static int a2150_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	// disable dma on card
+ 	devpriv->irq_dma_bits &= ~DMA_INTR_EN_BIT & ~DMA_EN_BIT;
+@@ -485,7 +485,7 @@ static int a2150_cancel(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int a2150_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int a2150_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -615,7 +615,7 @@ static int a2150_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int a2150_ai_cmd(comedi_device * dev, comedi_subdevice * s)
++static int a2150_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+@@ -726,7 +726,7 @@ static int a2150_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int a2150_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int a2150_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int i, n;
+@@ -800,7 +800,7 @@ static int a2150_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 
+ /* sets bits in devpriv->clock_bits to nearest approximation of requested period,
+  * adjusts requested period to actual timing. */
+-static int a2150_get_timing(comedi_device * dev, unsigned int *period,
++static int a2150_get_timing(struct comedi_device * dev, unsigned int *period,
+ 	int flags)
+ {
+ 	int lub, glb, temp;
+@@ -874,7 +874,7 @@ static int a2150_get_timing(comedi_device * dev, unsigned int *period,
+ 	return 0;
+ }
+ 
+-static int a2150_set_chanlist(comedi_device * dev, unsigned int start_channel,
++static int a2150_set_chanlist(struct comedi_device * dev, unsigned int start_channel,
+ 	unsigned int num_channels)
+ {
+ 	if (start_channel + num_channels > 4)
+diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c
+index fd259813bf54..6a8d9a5b7bf7 100644
+--- a/drivers/staging/comedi/drivers/ni_at_ao.c
++++ b/drivers/staging/comedi/drivers/ni_at_ao.c
+@@ -178,8 +178,8 @@ typedef struct {
+ } atao_private;
+ #define devpriv ((atao_private *)dev->private)
+ 
+-static int atao_attach(comedi_device * dev, comedi_devconfig * it);
+-static int atao_detach(comedi_device * dev);
++static int atao_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int atao_detach(struct comedi_device * dev);
+ static comedi_driver driver_atao = {
+       driver_name:"ni_at_ao",
+       module:THIS_MODULE,
+@@ -192,22 +192,22 @@ static comedi_driver driver_atao = {
+ 
+ COMEDI_INITCLEANUP(driver_atao);
+ 
+-static void atao_reset(comedi_device * dev);
++static void atao_reset(struct comedi_device * dev);
+ 
+-static int atao_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int atao_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int atao_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int atao_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int atao_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int atao_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int atao_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int atao_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int atao_calib_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int atao_calib_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int atao_calib_insn_write(comedi_device * dev, comedi_subdevice * s,
++static int atao_calib_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int atao_attach(comedi_device * dev, comedi_devconfig * it)
++static int atao_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	unsigned long iobase;
+@@ -280,7 +280,7 @@ static int atao_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int atao_detach(comedi_device * dev)
++static int atao_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: atao: remove\n", dev->minor);
+ 
+@@ -290,7 +290,7 @@ static int atao_detach(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static void atao_reset(comedi_device * dev)
++static void atao_reset(struct comedi_device * dev)
+ {
+ 	/* This is the reset sequence described in the manual */
+ 
+@@ -320,7 +320,7 @@ static void atao_reset(comedi_device * dev)
+ 	outw(devpriv->cfg1, dev->iobase + ATAO_CFG1);
+ }
+ 
+-static int atao_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int atao_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -344,7 +344,7 @@ static int atao_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int atao_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int atao_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -356,7 +356,7 @@ static int atao_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int atao_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int atao_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -373,7 +373,7 @@ static int atao_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int atao_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int atao_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -418,7 +418,7 @@ static int atao_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+  * DACs.  It is not explicitly stated in the manual how to access
+  * the caldacs, but we can guess.
+  */
+-static int atao_calib_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int atao_calib_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -428,7 +428,7 @@ static int atao_calib_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return insn->n;
+ }
+ 
+-static int atao_calib_insn_write(comedi_device * dev, comedi_subdevice * s,
++static int atao_calib_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bitstring, bit;
+diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c
+index 4c8fe52db30c..0e30050b91e6 100644
+--- a/drivers/staging/comedi/drivers/ni_atmio.c
++++ b/drivers/staging/comedi/drivers/ni_atmio.c
+@@ -296,7 +296,7 @@ typedef struct {
+  * read/written directly in the I/O space of the board.  The
+  * AT-MIO devices map the low 8 STC registers to iobase+addr*2. */
+ 
+-static void ni_atmio_win_out(comedi_device * dev, uint16_t data, int addr)
++static void ni_atmio_win_out(struct comedi_device * dev, uint16_t data, int addr)
+ {
+ 	unsigned long flags;
+ 
+@@ -310,7 +310,7 @@ static void ni_atmio_win_out(comedi_device * dev, uint16_t data, int addr)
+ 	comedi_spin_unlock_irqrestore(&devpriv->window_lock, flags);
+ }
+ 
+-static uint16_t ni_atmio_win_in(comedi_device * dev, int addr)
++static uint16_t ni_atmio_win_in(struct comedi_device * dev, int addr)
+ {
+ 	unsigned long flags;
+ 	uint16_t ret;
+@@ -338,8 +338,8 @@ static struct pnp_device_id device_ids[] = {
+ 
+ MODULE_DEVICE_TABLE(pnp, device_ids);
+ 
+-static int ni_atmio_attach(comedi_device * dev, comedi_devconfig * it);
+-static int ni_atmio_detach(comedi_device * dev);
++static int ni_atmio_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int ni_atmio_detach(struct comedi_device * dev);
+ static comedi_driver driver_atmio = {
+       driver_name:"ni_atmio",
+       module:THIS_MODULE,
+@@ -351,10 +351,10 @@ COMEDI_INITCLEANUP(driver_atmio);
+ 
+ #include "ni_mio_common.c"
+ 
+-static int ni_getboardtype(comedi_device * dev);
++static int ni_getboardtype(struct comedi_device * dev);
+ 
+ /* clean up allocated resources */
+-static int ni_atmio_detach(comedi_device * dev)
++static int ni_atmio_detach(struct comedi_device * dev)
+ {
+ 	mio_common_detach(dev);
+ 
+@@ -404,7 +404,7 @@ static int ni_isapnp_find_board(struct pnp_dev **dev)
+ 	return 0;
+ }
+ 
+-static int ni_atmio_attach(comedi_device * dev, comedi_devconfig * it)
++static int ni_atmio_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	struct pnp_dev *isapnp_dev;
+ 	int ret;
+@@ -492,7 +492,7 @@ static int ni_atmio_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int ni_getboardtype(comedi_device * dev)
++static int ni_getboardtype(struct comedi_device * dev)
+ {
+ 	int device_id = ni_read_eeprom(dev, 511);
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
+index 11581dce981f..62be3d9ec484 100644
+--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
++++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
+@@ -123,15 +123,15 @@ static const atmio16_board_t atmio16_boards[] = {
+ #define boardtype ((const atmio16_board_t *)dev->board_ptr)
+ 
+ /* function prototypes */
+-static int atmio16d_attach(comedi_device * dev, comedi_devconfig * it);
+-static int atmio16d_detach(comedi_device * dev);
++static int atmio16d_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int atmio16d_detach(struct comedi_device * dev);
+ static irqreturn_t atmio16d_interrupt(int irq, void *d PT_REGS_ARG);
+-static int atmio16d_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int atmio16d_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int atmio16d_ai_cmd(comedi_device * dev, comedi_subdevice * s);
+-static int atmio16d_ai_cancel(comedi_device * dev, comedi_subdevice * s);
+-static void reset_counters(comedi_device * dev);
+-static void reset_atmio16d(comedi_device * dev);
++static int atmio16d_ai_cmd(struct comedi_device * dev, comedi_subdevice * s);
++static int atmio16d_ai_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static void reset_counters(struct comedi_device * dev);
++static void reset_atmio16d(struct comedi_device * dev);
+ 
+ /* main driver struct */
+ static comedi_driver driver_atmio16d = {
+@@ -185,7 +185,7 @@ typedef struct {
+ 	unsigned int com_reg_2_state;	/* current state of command register 2 */
+ } atmio16d_private;
+ 
+-static void reset_counters(comedi_device * dev)
++static void reset_counters(struct comedi_device * dev)
+ {
+ 	/* Counter 2 */
+ 	outw(0xFFC2, dev->iobase + AM9513A_COM_REG);
+@@ -223,7 +223,7 @@ static void reset_counters(comedi_device * dev)
+ 	outw(0, dev->iobase + AD_CLEAR_REG);
+ }
+ 
+-static void reset_atmio16d(comedi_device * dev)
++static void reset_atmio16d(struct comedi_device * dev)
+ {
+ 	int i;
+ 
+@@ -257,7 +257,7 @@ static void reset_atmio16d(comedi_device * dev)
+ 
+ static irqreturn_t atmio16d_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s = dev->subdevices + 0;
+ 
+ //      printk("atmio16d_interrupt!\n");
+@@ -268,7 +268,7 @@ static irqreturn_t atmio16d_interrupt(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int atmio16d_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int atmio16d_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0, tmp;
+@@ -369,7 +369,7 @@ static int atmio16d_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int atmio16d_ai_cmd(comedi_device * dev, comedi_subdevice * s)
++static int atmio16d_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned int timer, base_clock;
+@@ -517,7 +517,7 @@ static int atmio16d_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ /* This will cancel a running acquisition operation */
+-static int atmio16d_ai_cancel(comedi_device * dev, comedi_subdevice * s)
++static int atmio16d_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	reset_atmio16d(dev);
+ 
+@@ -525,7 +525,7 @@ static int atmio16d_ai_cancel(comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ /* Mode 0 is used to get a single conversion on demand */
+-static int atmio16d_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int atmio16d_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, t;
+@@ -584,7 +584,7 @@ static int atmio16d_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int atmio16d_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int atmio16d_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -599,7 +599,7 @@ static int atmio16d_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int atmio16d_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
++static int atmio16d_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -634,7 +634,7 @@ static int atmio16d_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int atmio16d_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int atmio16d_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -650,7 +650,7 @@ static int atmio16d_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int atmio16d_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int atmio16d_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -704,7 +704,7 @@ static int atmio16d_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+    options[12] - dac1 coding
+  */
+ 
+-static int atmio16d_attach(comedi_device * dev, comedi_devconfig * it)
++static int atmio16d_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	unsigned int irq;
+ 	unsigned long iobase;
+@@ -839,7 +839,7 @@ static int atmio16d_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int atmio16d_detach(comedi_device * dev)
++static int atmio16d_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: atmio16d: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
+index 9193f16ad14f..a83d0308a67a 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_700.c
++++ b/drivers/staging/comedi/drivers/ni_daq_700.c
+@@ -55,8 +55,8 @@ static struct pcmcia_device *pcmcia_cur_dev = NULL;
+ 
+ #define DIO700_SIZE 8		// size of io region used by board
+ 
+-static int dio700_attach(comedi_device * dev, comedi_devconfig * it);
+-static int dio700_detach(comedi_device * dev);
++static int dio700_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int dio700_detach(struct comedi_device * dev);
+ 
+ enum dio700_bustype { pcmcia_bustype };
+ 
+@@ -126,9 +126,9 @@ struct subdev_700_struct {
+ #define CALLBACK_FUNC	(((struct subdev_700_struct *)s->private)->cb_func)
+ #define subdevpriv	((struct subdev_700_struct *)s->private)
+ 
+-static void do_config(comedi_device * dev, comedi_subdevice * s);
++static void do_config(struct comedi_device * dev, comedi_subdevice * s);
+ 
+-void subdev_700_interrupt(comedi_device * dev, comedi_subdevice * s)
++void subdev_700_interrupt(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	short d;
+ 
+@@ -153,7 +153,7 @@ static int subdev_700_cb(int dir, int port, int data, unsigned long arg)
+ 	}
+ }
+ 
+-static int subdev_700_insn(comedi_device * dev, comedi_subdevice * s,
++static int subdev_700_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+@@ -171,7 +171,7 @@ static int subdev_700_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int subdev_700_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int subdev_700_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -194,12 +194,12 @@ static int subdev_700_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static void do_config(comedi_device * dev, comedi_subdevice * s)
++static void do_config(struct comedi_device * dev, comedi_subdevice * s)
+ {				/* use powerup defaults */
+ 	return;
+ }
+ 
+-static int subdev_700_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int subdev_700_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -274,21 +274,21 @@ static int subdev_700_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int subdev_700_cmd(comedi_device * dev, comedi_subdevice * s)
++static int subdev_700_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	/* FIXME */
+ 
+ 	return 0;
+ }
+ 
+-static int subdev_700_cancel(comedi_device * dev, comedi_subdevice * s)
++static int subdev_700_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	/* FIXME */
+ 
+ 	return 0;
+ }
+ 
+-int subdev_700_init(comedi_device * dev, comedi_subdevice * s, int (*cb) (int,
++int subdev_700_init(struct comedi_device * dev, comedi_subdevice * s, int (*cb) (int,
+ 		int, int, unsigned long), unsigned long arg)
+ {
+ 	s->type = COMEDI_SUBD_DIO;
+@@ -317,7 +317,7 @@ int subdev_700_init(comedi_device * dev, comedi_subdevice * s, int (*cb) (int,
+ 	return 0;
+ }
+ 
+-int subdev_700_init_irq(comedi_device * dev, comedi_subdevice * s,
++int subdev_700_init_irq(struct comedi_device * dev, comedi_subdevice * s,
+ 	int (*cb) (int, int, int, unsigned long), unsigned long arg)
+ {
+ 	int ret;
+@@ -335,7 +335,7 @@ int subdev_700_init_irq(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-void subdev_700_cleanup(comedi_device * dev, comedi_subdevice * s)
++void subdev_700_cleanup(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	if (s->private) {
+ 		if (subdevpriv->have_irq) {
+@@ -350,7 +350,7 @@ EXPORT_SYMBOL(subdev_700_init_irq);
+ EXPORT_SYMBOL(subdev_700_cleanup);
+ EXPORT_SYMBOL(subdev_700_interrupt);
+ 
+-static int dio700_attach(comedi_device * dev, comedi_devconfig * it)
++static int dio700_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	unsigned long iobase = 0;
+@@ -413,7 +413,7 @@ static int dio700_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ };
+ 
+-static int dio700_detach(comedi_device * dev)
++static int dio700_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: ni_daq_700: cs-remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
+index 477d65ab09f7..98b20304b339 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
++++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
+@@ -56,8 +56,8 @@ static struct pcmcia_device *pcmcia_cur_dev = NULL;
+ 
+ #define DIO24_SIZE 4		// size of io region used by board
+ 
+-static int dio24_attach(comedi_device * dev, comedi_devconfig * it);
+-static int dio24_detach(comedi_device * dev);
++static int dio24_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int dio24_detach(struct comedi_device * dev);
+ 
+ enum dio24_bustype { pcmcia_bustype };
+ 
+@@ -107,7 +107,7 @@ static comedi_driver driver_dio24 = {
+       offset:sizeof(dio24_board),
+ };
+ 
+-static int dio24_attach(comedi_device * dev, comedi_devconfig * it)
++static int dio24_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	unsigned long iobase = 0;
+@@ -170,7 +170,7 @@ static int dio24_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ };
+ 
+-static int dio24_detach(comedi_device * dev)
++static int dio24_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: ni_daq_dio24: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
+index a7688f1670aa..53a7783793e3 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc.c
++++ b/drivers/staging/comedi/drivers/ni_labpc.c
+@@ -163,46 +163,46 @@ NI manuals:
+ #define   INIT_A1_BITS	0x70	// put hardware conversion counter output in harmless state (a1 mode 0)
+ #define COUNTER_B_BASE_REG	0x18
+ 
+-static int labpc_attach(comedi_device * dev, comedi_devconfig * it);
+-static int labpc_cancel(comedi_device * dev, comedi_subdevice * s);
++static int labpc_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int labpc_cancel(struct comedi_device * dev, comedi_subdevice * s);
+ static irqreturn_t labpc_interrupt(int irq, void *d PT_REGS_ARG);
+-static int labpc_drain_fifo(comedi_device * dev);
+-static void labpc_drain_dma(comedi_device * dev);
+-static void handle_isa_dma(comedi_device * dev);
+-static void labpc_drain_dregs(comedi_device * dev);
+-static int labpc_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int labpc_drain_fifo(struct comedi_device * dev);
++static void labpc_drain_dma(struct comedi_device * dev);
++static void handle_isa_dma(struct comedi_device * dev);
++static void labpc_drain_dregs(struct comedi_device * dev);
++static int labpc_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int labpc_ai_cmd(comedi_device * dev, comedi_subdevice * s);
+-static int labpc_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int labpc_ai_cmd(struct comedi_device * dev, comedi_subdevice * s);
++static int labpc_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int labpc_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int labpc_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int labpc_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int labpc_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int labpc_calib_read_insn(comedi_device * dev, comedi_subdevice * s,
++static int labpc_calib_read_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int labpc_calib_write_insn(comedi_device * dev, comedi_subdevice * s,
++static int labpc_calib_write_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int labpc_eeprom_read_insn(comedi_device * dev, comedi_subdevice * s,
++static int labpc_eeprom_read_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int labpc_eeprom_write_insn(comedi_device * dev, comedi_subdevice * s,
++static int labpc_eeprom_write_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ static unsigned int labpc_suggest_transfer_size(comedi_cmd cmd);
+-static void labpc_adc_timing(comedi_device * dev, comedi_cmd * cmd);
++static void labpc_adc_timing(struct comedi_device * dev, comedi_cmd * cmd);
+ #ifdef CONFIG_COMEDI_PCI
+-static int labpc_find_device(comedi_device *dev, int bus, int slot);
++static int labpc_find_device(struct comedi_device *dev, int bus, int slot);
+ #endif
+ static int labpc_dio_mem_callback(int dir, int port, int data,
+ 	unsigned long arg);
+-static void labpc_serial_out(comedi_device * dev, unsigned int value,
++static void labpc_serial_out(struct comedi_device * dev, unsigned int value,
+ 	unsigned int num_bits);
+-static unsigned int labpc_serial_in(comedi_device * dev);
+-static unsigned int labpc_eeprom_read(comedi_device * dev,
++static unsigned int labpc_serial_in(struct comedi_device * dev);
++static unsigned int labpc_eeprom_read(struct comedi_device * dev,
+ 	unsigned int address);
+-static unsigned int labpc_eeprom_read_status(comedi_device * dev);
+-static unsigned int labpc_eeprom_write(comedi_device * dev,
++static unsigned int labpc_eeprom_read_status(struct comedi_device * dev);
++static unsigned int labpc_eeprom_write(struct comedi_device * dev,
+ 	unsigned int address, unsigned int value);
+-static void write_caldac(comedi_device * dev, unsigned int channel,
++static void write_caldac(struct comedi_device * dev, unsigned int channel,
+ 	unsigned int value);
+ 
+ enum scan_mode {
+@@ -448,7 +448,7 @@ static DEFINE_PCI_DEVICE_TABLE(labpc_pci_table) = {
+ MODULE_DEVICE_TABLE(pci, labpc_pci_table);
+ #endif /* CONFIG_COMEDI_PCI */
+ 
+-static inline int labpc_counter_load(comedi_device * dev,
++static inline int labpc_counter_load(struct comedi_device * dev,
+ 	unsigned long base_address, unsigned int counter_number,
+ 	unsigned int count, unsigned int mode)
+ {
+@@ -459,7 +459,7 @@ static inline int labpc_counter_load(comedi_device * dev,
+ 		return i8254_load(base_address, 0, counter_number, count, mode);
+ }
+ 
+-int labpc_common_attach(comedi_device * dev, unsigned long iobase,
++int labpc_common_attach(struct comedi_device * dev, unsigned long iobase,
+ 	unsigned int irq, unsigned int dma_chan)
+ {
+ 	comedi_subdevice *s;
+@@ -643,7 +643,7 @@ int labpc_common_attach(comedi_device * dev, unsigned long iobase,
+ 	return 0;
+ }
+ 
+-static int labpc_attach(comedi_device * dev, comedi_devconfig * it)
++static int labpc_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	unsigned long iobase = 0;
+ 	unsigned int irq = 0;
+@@ -694,7 +694,7 @@ static int labpc_attach(comedi_device * dev, comedi_devconfig * it)
+ 
+ // adapted from ni_pcimio for finding mite based boards (pc-1200)
+ #ifdef CONFIG_COMEDI_PCI
+-static int labpc_find_device(comedi_device *dev, int bus, int slot)
++static int labpc_find_device(struct comedi_device *dev, int bus, int slot)
+ {
+ 	struct mite_struct *mite;
+ 	int i;
+@@ -724,7 +724,7 @@ static int labpc_find_device(comedi_device *dev, int bus, int slot)
+ }
+ #endif
+ 
+-int labpc_common_detach(comedi_device * dev)
++int labpc_common_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: ni_labpc: detach\n", dev->minor);
+ 
+@@ -748,14 +748,14 @@ int labpc_common_detach(comedi_device * dev)
+ 	return 0;
+ };
+ 
+-static void labpc_clear_adc_fifo(const comedi_device * dev)
++static void labpc_clear_adc_fifo(const struct comedi_device * dev)
+ {
+ 	devpriv->write_byte(0x1, dev->iobase + ADC_CLEAR_REG);
+ 	devpriv->read_byte(dev->iobase + ADC_FIFO_REG);
+ 	devpriv->read_byte(dev->iobase + ADC_FIFO_REG);
+ }
+ 
+-static int labpc_cancel(comedi_device * dev, comedi_subdevice * s)
++static int labpc_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+ 
+@@ -793,7 +793,7 @@ static enum scan_mode labpc_ai_scan_mode(const comedi_cmd * cmd)
+ 	return 0;
+ }
+ 
+-static int labpc_ai_chanlist_invalid(const comedi_device * dev,
++static int labpc_ai_chanlist_invalid(const struct comedi_device * dev,
+ 	const comedi_cmd * cmd)
+ {
+ 	int mode, channel, range, aref, i;
+@@ -926,7 +926,7 @@ static void labpc_set_ai_scan_period(comedi_cmd * cmd, unsigned int ns)
+ 	cmd->scan_begin_arg = ns;
+ }
+ 
+-static int labpc_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int labpc_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -1063,7 +1063,7 @@ static int labpc_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int labpc_ai_cmd(comedi_device * dev, comedi_subdevice * s)
++static int labpc_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	int channel, range, aref;
+ 	unsigned long irq_flags;
+@@ -1311,7 +1311,7 @@ static int labpc_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ /* interrupt service routine */
+ static irqreturn_t labpc_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s = dev->read_subdev;
+ 	comedi_async *async;
+ 	comedi_cmd *cmd;
+@@ -1393,7 +1393,7 @@ static irqreturn_t labpc_interrupt(int irq, void *d PT_REGS_ARG)
+ }
+ 
+ // read all available samples from ai fifo
+-static int labpc_drain_fifo(comedi_device * dev)
++static int labpc_drain_fifo(struct comedi_device * dev)
+ {
+ 	unsigned int lsb, msb;
+ 	short data;
+@@ -1427,7 +1427,7 @@ static int labpc_drain_fifo(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static void labpc_drain_dma(comedi_device * dev)
++static void labpc_drain_dma(struct comedi_device * dev)
+ {
+ 	comedi_subdevice *s = dev->read_subdev;
+ 	comedi_async *async = s->async;
+@@ -1480,7 +1480,7 @@ static void labpc_drain_dma(comedi_device * dev)
+ 	async->events |= COMEDI_CB_BLOCK;
+ }
+ 
+-static void handle_isa_dma(comedi_device * dev)
++static void handle_isa_dma(struct comedi_device * dev)
+ {
+ 	labpc_drain_dma(dev);
+ 
+@@ -1492,7 +1492,7 @@ static void handle_isa_dma(comedi_device * dev)
+ 
+ /* makes sure all data aquired by board is transfered to comedi (used
+  * when aquisition is terminated by stop_src == TRIG_EXT). */
+-static void labpc_drain_dregs(comedi_device * dev)
++static void labpc_drain_dregs(struct comedi_device * dev)
+ {
+ 	if (devpriv->current_transfer == isa_dma_transfer)
+ 		labpc_drain_dma(dev);
+@@ -1500,7 +1500,7 @@ static void labpc_drain_dregs(comedi_device * dev)
+ 	labpc_drain_fifo(dev);
+ }
+ 
+-static int labpc_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int labpc_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+@@ -1586,7 +1586,7 @@ static int labpc_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ // analog output insn
+-static int labpc_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int labpc_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel, range;
+@@ -1627,7 +1627,7 @@ static int labpc_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ // analog output readback insn
+-static int labpc_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int labpc_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)];
+@@ -1635,7 +1635,7 @@ static int labpc_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int labpc_calib_read_insn(comedi_device * dev, comedi_subdevice * s,
++static int labpc_calib_read_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->caldac[CR_CHAN(insn->chanspec)];
+@@ -1643,7 +1643,7 @@ static int labpc_calib_read_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int labpc_calib_write_insn(comedi_device * dev, comedi_subdevice * s,
++static int labpc_calib_write_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel = CR_CHAN(insn->chanspec);
+@@ -1652,7 +1652,7 @@ static int labpc_calib_write_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int labpc_eeprom_read_insn(comedi_device * dev, comedi_subdevice * s,
++static int labpc_eeprom_read_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->eeprom_data[CR_CHAN(insn->chanspec)];
+@@ -1660,7 +1660,7 @@ static int labpc_eeprom_read_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int labpc_eeprom_write_insn(comedi_device * dev, comedi_subdevice * s,
++static int labpc_eeprom_write_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel = CR_CHAN(insn->chanspec);
+@@ -1704,7 +1704,7 @@ static unsigned int labpc_suggest_transfer_size(comedi_cmd cmd)
+ }
+ 
+ // figures out what counter values to use based on command
+-static void labpc_adc_timing(comedi_device * dev, comedi_cmd * cmd)
++static void labpc_adc_timing(struct comedi_device * dev, comedi_cmd * cmd)
+ {
+ 	const int max_counter_value = 0x10000;	// max value for 16 bit counter in mode 2
+ 	const int min_counter_value = 2;	// min value for 16 bit counter in mode 2
+@@ -1796,7 +1796,7 @@ static int labpc_dio_mem_callback(int dir, int port, int data,
+ }
+ 
+ // lowlevel write to eeprom/dac
+-static void labpc_serial_out(comedi_device * dev, unsigned int value,
++static void labpc_serial_out(struct comedi_device * dev, unsigned int value,
+ 	unsigned int value_width)
+ {
+ 	int i;
+@@ -1821,7 +1821,7 @@ static void labpc_serial_out(comedi_device * dev, unsigned int value,
+ }
+ 
+ // lowlevel read from eeprom
+-static unsigned int labpc_serial_in(comedi_device * dev)
++static unsigned int labpc_serial_in(struct comedi_device * dev)
+ {
+ 	unsigned int value = 0;
+ 	int i;
+@@ -1850,7 +1850,7 @@ static unsigned int labpc_serial_in(comedi_device * dev)
+ 	return value;
+ }
+ 
+-static unsigned int labpc_eeprom_read(comedi_device * dev, unsigned int address)
++static unsigned int labpc_eeprom_read(struct comedi_device * dev, unsigned int address)
+ {
+ 	unsigned int value;
+ 	const int read_instruction = 0x3;	// bits to tell eeprom to expect a read
+@@ -1879,7 +1879,7 @@ static unsigned int labpc_eeprom_read(comedi_device * dev, unsigned int address)
+ 	return value;
+ }
+ 
+-static unsigned int labpc_eeprom_write(comedi_device * dev,
++static unsigned int labpc_eeprom_write(struct comedi_device * dev,
+ 	unsigned int address, unsigned int value)
+ {
+ 	const int write_enable_instruction = 0x6;
+@@ -1937,7 +1937,7 @@ static unsigned int labpc_eeprom_write(comedi_device * dev,
+ 	return 0;
+ }
+ 
+-static unsigned int labpc_eeprom_read_status(comedi_device * dev)
++static unsigned int labpc_eeprom_read_status(struct comedi_device * dev)
+ {
+ 	unsigned int value;
+ 	const int read_status_instruction = 0x5;
+@@ -1965,7 +1965,7 @@ static unsigned int labpc_eeprom_read_status(comedi_device * dev)
+ }
+ 
+ // writes to 8 bit calibration dacs
+-static void write_caldac(comedi_device * dev, unsigned int channel,
++static void write_caldac(struct comedi_device * dev, unsigned int channel,
+ 	unsigned int value)
+ {
+ 	if (value == devpriv->caldac[channel])
+diff --git a/drivers/staging/comedi/drivers/ni_labpc.h b/drivers/staging/comedi/drivers/ni_labpc.h
+index 8264fb19288d..d80f05eae52f 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc.h
++++ b/drivers/staging/comedi/drivers/ni_labpc.h
+@@ -74,9 +74,9 @@ typedef struct {
+ 	void (*write_byte) (unsigned int byte, unsigned long address);
+ } labpc_private;
+ 
+-int labpc_common_attach(comedi_device * dev, unsigned long iobase,
++int labpc_common_attach(struct comedi_device * dev, unsigned long iobase,
+ 	unsigned int irq, unsigned int dma);
+-int labpc_common_detach(comedi_device * dev);
++int labpc_common_detach(struct comedi_device * dev);
+ 
+ extern const int labpc_1200_is_unipolar[];
+ extern const int labpc_1200_ai_gain_bits[];
+diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
+index e9098ce6f9dd..f41d39b75df9 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
++++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
+@@ -79,7 +79,7 @@ NI manuals:
+ 
+ static struct pcmcia_device *pcmcia_cur_dev = NULL;
+ 
+-static int labpc_attach(comedi_device * dev, comedi_devconfig * it);
++static int labpc_attach(struct comedi_device * dev, comedi_devconfig * it);
+ 
+ static const labpc_board labpc_cs_boards[] = {
+ 	{
+@@ -126,7 +126,7 @@ static comedi_driver driver_labpc_cs = {
+ 	.offset = sizeof(labpc_board),
+ };
+ 
+-static int labpc_attach(comedi_device * dev, comedi_devconfig * it)
++static int labpc_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	unsigned long iobase = 0;
+ 	unsigned int irq = 0;
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index bb2c378cf68a..f702cc9064ba 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -193,49 +193,49 @@ static const comedi_lrange *const ni_range_lkup[] = {
+ 	[ai_gain_6143] = &range_ni_S_ai_6143
+ };
+ 
+-static int ni_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int ni_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int ni_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_cdio_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int ni_cdio_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int ni_cdio_cmd(comedi_device * dev, comedi_subdevice * s);
+-static int ni_cdio_cancel(comedi_device * dev, comedi_subdevice * s);
+-static void handle_cdio_interrupt(comedi_device * dev);
+-static int ni_cdo_inttrig(comedi_device * dev, comedi_subdevice * s,
++static int ni_cdio_cmd(struct comedi_device * dev, comedi_subdevice * s);
++static int ni_cdio_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static void handle_cdio_interrupt(struct comedi_device * dev);
++static int ni_cdo_inttrig(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int trignum);
+ 
+-static int ni_serial_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int ni_serial_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_serial_hw_readwrite8(comedi_device * dev, comedi_subdevice * s,
++static int ni_serial_hw_readwrite8(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned char data_out, unsigned char *data_in);
+-static int ni_serial_sw_readwrite8(comedi_device * dev, comedi_subdevice * s,
++static int ni_serial_sw_readwrite8(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned char data_out, unsigned char *data_in);
+ 
+-static int ni_calib_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int ni_calib_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_calib_insn_write(comedi_device * dev, comedi_subdevice * s,
++static int ni_calib_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int ni_eeprom_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int ni_eeprom_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_m_series_eeprom_insn_read(comedi_device * dev,
++static int ni_m_series_eeprom_insn_read(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+-static int ni_pfi_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int ni_pfi_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_pfi_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int ni_pfi_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static unsigned ni_old_get_pfi_routing(comedi_device * dev, unsigned chan);
++static unsigned ni_old_get_pfi_routing(struct comedi_device * dev, unsigned chan);
+ 
+-static void ni_rtsi_init(comedi_device * dev);
+-static int ni_rtsi_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static void ni_rtsi_init(struct comedi_device * dev);
++static int ni_rtsi_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_rtsi_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int ni_rtsi_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static void caldac_setup(comedi_device * dev, comedi_subdevice * s);
+-static int ni_read_eeprom(comedi_device * dev, int addr);
++static void caldac_setup(struct comedi_device * dev, comedi_subdevice * s);
++static int ni_read_eeprom(struct comedi_device * dev, int addr);
+ 
+ #ifdef DEBUG_STATUS_A
+ static void ni_mio_print_status_a(int status);
+@@ -248,58 +248,58 @@ static void ni_mio_print_status_b(int status);
+ #define ni_mio_print_status_b(a)
+ #endif
+ 
+-static int ni_ai_reset(comedi_device * dev, comedi_subdevice * s);
++static int ni_ai_reset(struct comedi_device * dev, comedi_subdevice * s);
+ #ifndef PCIDMA
+-static void ni_handle_fifo_half_full(comedi_device * dev);
+-static int ni_ao_fifo_half_empty(comedi_device * dev, comedi_subdevice * s);
++static void ni_handle_fifo_half_full(struct comedi_device * dev);
++static int ni_ao_fifo_half_empty(struct comedi_device * dev, comedi_subdevice * s);
+ #endif
+-static void ni_handle_fifo_dregs(comedi_device * dev);
+-static int ni_ai_inttrig(comedi_device * dev, comedi_subdevice * s,
++static void ni_handle_fifo_dregs(struct comedi_device * dev);
++static int ni_ai_inttrig(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int trignum);
+-static void ni_load_channelgain_list(comedi_device * dev, unsigned int n_chan,
++static void ni_load_channelgain_list(struct comedi_device * dev, unsigned int n_chan,
+ 	unsigned int *list);
+-static void shutdown_ai_command(comedi_device * dev);
++static void shutdown_ai_command(struct comedi_device * dev);
+ 
+-static int ni_ao_inttrig(comedi_device * dev, comedi_subdevice * s,
++static int ni_ao_inttrig(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int trignum);
+ 
+-static int ni_ao_reset(comedi_device * dev, comedi_subdevice * s);
++static int ni_ao_reset(struct comedi_device * dev, comedi_subdevice * s);
+ 
+ static int ni_8255_callback(int dir, int port, int data, unsigned long arg);
+ 
+-static int ni_gpct_insn_write(comedi_device * dev, comedi_subdevice * s,
++static int ni_gpct_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_gpct_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int ni_gpct_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_gpct_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int ni_gpct_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_gpct_cmd(comedi_device * dev, comedi_subdevice * s);
+-static int ni_gpct_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int ni_gpct_cmd(struct comedi_device * dev, comedi_subdevice * s);
++static int ni_gpct_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int ni_gpct_cancel(comedi_device * dev, comedi_subdevice * s);
+-static void handle_gpct_interrupt(comedi_device * dev,
++static int ni_gpct_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static void handle_gpct_interrupt(struct comedi_device * dev,
+ 	unsigned short counter_index);
+ 
+-static int init_cs5529(comedi_device * dev);
+-static int cs5529_do_conversion(comedi_device * dev, unsigned short *data);
+-static int cs5529_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int init_cs5529(struct comedi_device * dev);
++static int cs5529_do_conversion(struct comedi_device * dev, unsigned short *data);
++static int cs5529_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ #ifdef NI_CS5529_DEBUG
+-static unsigned int cs5529_config_read(comedi_device * dev,
++static unsigned int cs5529_config_read(struct comedi_device * dev,
+ 	unsigned int reg_select_bits);
+ #endif
+-static void cs5529_config_write(comedi_device * dev, unsigned int value,
++static void cs5529_config_write(struct comedi_device * dev, unsigned int value,
+ 	unsigned int reg_select_bits);
+ 
+-static int ni_m_series_pwm_config(comedi_device * dev, comedi_subdevice * s,
++static int ni_m_series_pwm_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ni_6143_pwm_config(comedi_device * dev, comedi_subdevice * s,
++static int ni_6143_pwm_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int ni_set_master_clock(comedi_device * dev, unsigned source,
++static int ni_set_master_clock(struct comedi_device * dev, unsigned source,
+ 	unsigned period_ns);
+-static void ack_a_interrupt(comedi_device * dev, unsigned short a_status);
+-static void ack_b_interrupt(comedi_device * dev, unsigned short b_status);
++static void ack_a_interrupt(struct comedi_device * dev, unsigned short a_status);
++static void ack_b_interrupt(struct comedi_device * dev, unsigned short b_status);
+ 
+ enum aimodes {
+ 	AIMODE_NONE = 0,
+@@ -353,14 +353,14 @@ enum timebase_nanoseconds {
+ 
+ static const int num_adc_stages_611x = 3;
+ 
+-static void handle_a_interrupt(comedi_device * dev, unsigned short status,
++static void handle_a_interrupt(struct comedi_device * dev, unsigned short status,
+ 	unsigned ai_mite_status);
+-static void handle_b_interrupt(comedi_device * dev, unsigned short status,
++static void handle_b_interrupt(struct comedi_device * dev, unsigned short status,
+ 	unsigned ao_mite_status);
+-static void get_last_sample_611x(comedi_device * dev);
+-static void get_last_sample_6143(comedi_device * dev);
++static void get_last_sample_611x(struct comedi_device * dev);
++static void get_last_sample_6143(struct comedi_device * dev);
+ 
+-static inline void ni_set_bitfield(comedi_device * dev, int reg,
++static inline void ni_set_bitfield(struct comedi_device * dev, int reg,
+ 	unsigned bit_mask, unsigned bit_values)
+ {
+ 	unsigned long flags;
+@@ -406,12 +406,12 @@ static inline void ni_set_bitfield(comedi_device * dev, int reg,
+ }
+ 
+ #ifdef PCIDMA
+-static int ni_ai_drain_dma(comedi_device * dev);
++static int ni_ai_drain_dma(struct comedi_device * dev);
+ 
+ /* DMA channel setup */
+ 
+ // negative channel means no channel
+-static inline void ni_set_ai_dma_channel(comedi_device * dev, int channel)
++static inline void ni_set_ai_dma_channel(struct comedi_device * dev, int channel)
+ {
+ 	unsigned bitfield;
+ 
+@@ -426,7 +426,7 @@ static inline void ni_set_ai_dma_channel(comedi_device * dev, int channel)
+ }
+ 
+ // negative channel means no channel
+-static inline void ni_set_ao_dma_channel(comedi_device * dev, int channel)
++static inline void ni_set_ao_dma_channel(struct comedi_device * dev, int channel)
+ {
+ 	unsigned bitfield;
+ 
+@@ -441,7 +441,7 @@ static inline void ni_set_ao_dma_channel(comedi_device * dev, int channel)
+ }
+ 
+ // negative mite_channel means no channel
+-static inline void ni_set_gpct_dma_channel(comedi_device * dev,
++static inline void ni_set_gpct_dma_channel(struct comedi_device * dev,
+ 	unsigned gpct_index, int mite_channel)
+ {
+ 	unsigned bitfield;
+@@ -456,7 +456,7 @@ static inline void ni_set_gpct_dma_channel(comedi_device * dev,
+ }
+ 
+ // negative mite_channel means no channel
+-static inline void ni_set_cdo_dma_channel(comedi_device * dev, int mite_channel)
++static inline void ni_set_cdo_dma_channel(struct comedi_device * dev, int mite_channel)
+ {
+ 	unsigned long flags;
+ 
+@@ -475,7 +475,7 @@ static inline void ni_set_cdo_dma_channel(comedi_device * dev, int mite_channel)
+ 	comedi_spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags);
+ }
+ 
+-static int ni_request_ai_mite_channel(comedi_device * dev)
++static int ni_request_ai_mite_channel(struct comedi_device * dev)
+ {
+ 	unsigned long flags;
+ 
+@@ -496,7 +496,7 @@ static int ni_request_ai_mite_channel(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int ni_request_ao_mite_channel(comedi_device * dev)
++static int ni_request_ao_mite_channel(struct comedi_device * dev)
+ {
+ 	unsigned long flags;
+ 
+@@ -517,7 +517,7 @@ static int ni_request_ao_mite_channel(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int ni_request_gpct_mite_channel(comedi_device * dev,
++static int ni_request_gpct_mite_channel(struct comedi_device * dev,
+ 	unsigned gpct_index, enum comedi_io_direction direction)
+ {
+ 	unsigned long flags;
+@@ -546,7 +546,7 @@ static int ni_request_gpct_mite_channel(comedi_device * dev,
+ 
+ #endif // PCIDMA
+ 
+-static int ni_request_cdo_mite_channel(comedi_device * dev)
++static int ni_request_cdo_mite_channel(struct comedi_device * dev)
+ {
+ #ifdef PCIDMA
+ 	unsigned long flags;
+@@ -569,7 +569,7 @@ static int ni_request_cdo_mite_channel(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static void ni_release_ai_mite_channel(comedi_device * dev)
++static void ni_release_ai_mite_channel(struct comedi_device * dev)
+ {
+ #ifdef PCIDMA
+ 	unsigned long flags;
+@@ -584,7 +584,7 @@ static void ni_release_ai_mite_channel(comedi_device * dev)
+ #endif // PCIDMA
+ }
+ 
+-static void ni_release_ao_mite_channel(comedi_device * dev)
++static void ni_release_ao_mite_channel(struct comedi_device * dev)
+ {
+ #ifdef PCIDMA
+ 	unsigned long flags;
+@@ -599,7 +599,7 @@ static void ni_release_ao_mite_channel(comedi_device * dev)
+ #endif // PCIDMA
+ }
+ 
+-void ni_release_gpct_mite_channel(comedi_device * dev, unsigned gpct_index)
++void ni_release_gpct_mite_channel(struct comedi_device * dev, unsigned gpct_index)
+ {
+ #ifdef PCIDMA
+ 	unsigned long flags;
+@@ -619,7 +619,7 @@ void ni_release_gpct_mite_channel(comedi_device * dev, unsigned gpct_index)
+ #endif // PCIDMA
+ }
+ 
+-static void ni_release_cdo_mite_channel(comedi_device * dev)
++static void ni_release_cdo_mite_channel(struct comedi_device * dev)
+ {
+ #ifdef PCIDMA
+ 	unsigned long flags;
+@@ -636,7 +636,7 @@ static void ni_release_cdo_mite_channel(comedi_device * dev)
+ 
+ // e-series boards use the second irq signals to generate dma requests for their counters
+ #ifdef PCIDMA
+-static void ni_e_series_enable_second_irq(comedi_device * dev,
++static void ni_e_series_enable_second_irq(struct comedi_device * dev,
+ 	unsigned gpct_index, short enable)
+ {
+ 	if (boardtype.reg_type & ni_reg_m_series_mask)
+@@ -667,7 +667,7 @@ static void ni_e_series_enable_second_irq(comedi_device * dev,
+ }
+ #endif // PCIDMA
+ 
+-static void ni_clear_ai_fifo(comedi_device * dev)
++static void ni_clear_ai_fifo(struct comedi_device * dev)
+ {
+ 	if (boardtype.reg_type == ni_reg_6143) {
+ 		// Flush the 6143 data FIFO
+@@ -693,13 +693,13 @@ static void ni_clear_ai_fifo(comedi_device * dev)
+ 	}
+ }
+ 
+-static void win_out2(comedi_device * dev, uint32_t data, int reg)
++static void win_out2(struct comedi_device * dev, uint32_t data, int reg)
+ {
+ 	devpriv->stc_writew(dev, data >> 16, reg);
+ 	devpriv->stc_writew(dev, data & 0xffff, reg + 1);
+ }
+ 
+-static uint32_t win_in2(comedi_device * dev, int reg)
++static uint32_t win_in2(struct comedi_device * dev, int reg)
+ {
+ 	uint32_t bits;
+ 	bits = devpriv->stc_readw(dev, reg) << 16;
+@@ -708,7 +708,7 @@ static uint32_t win_in2(comedi_device * dev, int reg)
+ }
+ 
+ #define ao_win_out(data,addr) ni_ao_win_outw(dev,data,addr)
+-static inline void ni_ao_win_outw(comedi_device * dev, uint16_t data, int addr)
++static inline void ni_ao_win_outw(struct comedi_device * dev, uint16_t data, int addr)
+ {
+ 	unsigned long flags;
+ 
+@@ -718,7 +718,7 @@ static inline void ni_ao_win_outw(comedi_device * dev, uint16_t data, int addr)
+ 	comedi_spin_unlock_irqrestore(&devpriv->window_lock, flags);
+ }
+ 
+-static inline void ni_ao_win_outl(comedi_device * dev, uint32_t data, int addr)
++static inline void ni_ao_win_outl(struct comedi_device * dev, uint32_t data, int addr)
+ {
+ 	unsigned long flags;
+ 
+@@ -728,7 +728,7 @@ static inline void ni_ao_win_outl(comedi_device * dev, uint32_t data, int addr)
+ 	comedi_spin_unlock_irqrestore(&devpriv->window_lock, flags);
+ }
+ 
+-static inline unsigned short ni_ao_win_inw(comedi_device * dev, int addr)
++static inline unsigned short ni_ao_win_inw(struct comedi_device * dev, int addr)
+ {
+ 	unsigned long flags;
+ 	unsigned short data;
+@@ -750,7 +750,7 @@ static inline unsigned short ni_ao_win_inw(comedi_device * dev, int addr)
+ *
+ * value should only be 1 or 0.
+ */
+-static inline void ni_set_bits(comedi_device * dev, int reg, unsigned bits,
++static inline void ni_set_bits(struct comedi_device * dev, int reg, unsigned bits,
+ 	unsigned value)
+ {
+ 	unsigned bit_values;
+@@ -764,7 +764,7 @@ static inline void ni_set_bits(comedi_device * dev, int reg, unsigned bits,
+ 
+ static irqreturn_t ni_E_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	unsigned short a_status;
+ 	unsigned short b_status;
+ 	unsigned int ai_mite_status = 0;
+@@ -823,7 +823,7 @@ static irqreturn_t ni_E_interrupt(int irq, void *d PT_REGS_ARG)
+ }
+ 
+ #ifdef PCIDMA
+-static void ni_sync_ai_dma(comedi_device * dev)
++static void ni_sync_ai_dma(struct comedi_device * dev)
+ {
+ 	comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ 	unsigned long flags;
+@@ -834,7 +834,7 @@ static void ni_sync_ai_dma(comedi_device * dev)
+ 	comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
+ }
+ 
+-static void mite_handle_b_linkc(struct mite_struct *mite, comedi_device * dev)
++static void mite_handle_b_linkc(struct mite_struct *mite, struct comedi_device * dev)
+ {
+ 	comedi_subdevice *s = dev->subdevices + NI_AO_SUBDEV;
+ 	unsigned long flags;
+@@ -846,7 +846,7 @@ static void mite_handle_b_linkc(struct mite_struct *mite, comedi_device * dev)
+ 	comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
+ }
+ 
+-static int ni_ao_wait_for_dma_load(comedi_device * dev)
++static int ni_ao_wait_for_dma_load(struct comedi_device * dev)
+ {
+ 	static const int timeout = 10000;
+ 	int i;
+@@ -868,7 +868,7 @@ static int ni_ao_wait_for_dma_load(comedi_device * dev)
+ }
+ 
+ #endif //PCIDMA
+-static void ni_handle_eos(comedi_device * dev, comedi_subdevice * s)
++static void ni_handle_eos(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	if (devpriv->aimode == AIMODE_SCAN) {
+ #ifdef PCIDMA
+@@ -892,7 +892,7 @@ static void ni_handle_eos(comedi_device * dev, comedi_subdevice * s)
+ 	}
+ }
+ 
+-static void shutdown_ai_command(comedi_device * dev)
++static void shutdown_ai_command(struct comedi_device * dev)
+ {
+ 	comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ 
+@@ -906,7 +906,7 @@ static void shutdown_ai_command(comedi_device * dev)
+ 	s->async->events |= COMEDI_CB_EOA;
+ }
+ 
+-static void ni_event(comedi_device * dev, comedi_subdevice * s)
++static void ni_event(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	if (s->async->
+ 		events & (COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW | COMEDI_CB_EOA))
+@@ -932,7 +932,7 @@ static void ni_event(comedi_device * dev, comedi_subdevice * s)
+ 	comedi_event(dev, s);
+ }
+ 
+-static void handle_gpct_interrupt(comedi_device * dev,
++static void handle_gpct_interrupt(struct comedi_device * dev,
+ 	unsigned short counter_index)
+ {
+ #ifdef PCIDMA
+@@ -945,7 +945,7 @@ static void handle_gpct_interrupt(comedi_device * dev,
+ #endif
+ }
+ 
+-static void ack_a_interrupt(comedi_device * dev, unsigned short a_status)
++static void ack_a_interrupt(struct comedi_device * dev, unsigned short a_status)
+ {
+ 	unsigned short ack = 0;
+ 
+@@ -966,7 +966,7 @@ static void ack_a_interrupt(comedi_device * dev, unsigned short a_status)
+ 		devpriv->stc_writew(dev, ack, Interrupt_A_Ack_Register);
+ }
+ 
+-static void handle_a_interrupt(comedi_device * dev, unsigned short status,
++static void handle_a_interrupt(struct comedi_device * dev, unsigned short status,
+ 	unsigned ai_mite_status)
+ {
+ 	comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+@@ -1070,7 +1070,7 @@ static void handle_a_interrupt(comedi_device * dev, unsigned short status,
+ #endif
+ }
+ 
+-static void ack_b_interrupt(comedi_device * dev, unsigned short b_status)
++static void ack_b_interrupt(struct comedi_device * dev, unsigned short b_status)
+ {
+ 	unsigned short ack = 0;
+ 	if (b_status & AO_BC_TC_St) {
+@@ -1098,7 +1098,7 @@ static void ack_b_interrupt(comedi_device * dev, unsigned short b_status)
+ 		devpriv->stc_writew(dev, ack, Interrupt_B_Ack_Register);
+ }
+ 
+-static void handle_b_interrupt(comedi_device * dev, unsigned short b_status,
++static void handle_b_interrupt(struct comedi_device * dev, unsigned short b_status,
+ 	unsigned ao_mite_status)
+ {
+ 	comedi_subdevice *s = dev->subdevices + NI_AO_SUBDEV;
+@@ -1204,7 +1204,7 @@ static void ni_mio_print_status_b(int status)
+ 
+ #ifndef PCIDMA
+ 
+-static void ni_ao_fifo_load(comedi_device * dev, comedi_subdevice * s, int n)
++static void ni_ao_fifo_load(struct comedi_device * dev, comedi_subdevice * s, int n)
+ {
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+@@ -1263,7 +1263,7 @@ static void ni_ao_fifo_load(comedi_device * dev, comedi_subdevice * s, int n)
+  *  RT code, as RT code might purposely be running close to the
+  *  metal.  Needs to be fixed eventually.
+  */
+-static int ni_ao_fifo_half_empty(comedi_device * dev, comedi_subdevice * s)
++static int ni_ao_fifo_half_empty(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	int n;
+ 
+@@ -1284,7 +1284,7 @@ static int ni_ao_fifo_half_empty(comedi_device * dev, comedi_subdevice * s)
+ 	return 1;
+ }
+ 
+-static int ni_ao_prep_fifo(comedi_device * dev, comedi_subdevice * s)
++static int ni_ao_prep_fifo(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	int n;
+ 
+@@ -1307,7 +1307,7 @@ static int ni_ao_prep_fifo(comedi_device * dev, comedi_subdevice * s)
+ 	return n;
+ }
+ 
+-static void ni_ai_fifo_read(comedi_device * dev, comedi_subdevice * s, int n)
++static void ni_ai_fifo_read(struct comedi_device * dev, comedi_subdevice * s, int n)
+ {
+ 	comedi_async *async = s->async;
+ 	int i;
+@@ -1364,7 +1364,7 @@ static void ni_ai_fifo_read(comedi_device * dev, comedi_subdevice * s, int n)
+ 	}
+ }
+ 
+-static void ni_handle_fifo_half_full(comedi_device * dev)
++static void ni_handle_fifo_half_full(struct comedi_device * dev)
+ {
+ 	int n;
+ 	comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+@@ -1376,7 +1376,7 @@ static void ni_handle_fifo_half_full(comedi_device * dev)
+ #endif
+ 
+ #ifdef PCIDMA
+-static int ni_ai_drain_dma(comedi_device * dev)
++static int ni_ai_drain_dma(struct comedi_device * dev)
+ {
+ 	int i;
+ 	static const int timeout = 10000;
+@@ -1414,7 +1414,7 @@ static int ni_ai_drain_dma(comedi_device * dev)
+ /*
+    Empties the AI fifo
+ */
+-static void ni_handle_fifo_dregs(comedi_device * dev)
++static void ni_handle_fifo_dregs(struct comedi_device * dev)
+ {
+ 	comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ 	short data[2];
+@@ -1476,7 +1476,7 @@ static void ni_handle_fifo_dregs(comedi_device * dev)
+ 	}
+ }
+ 
+-static void get_last_sample_611x(comedi_device * dev)
++static void get_last_sample_611x(struct comedi_device * dev)
+ {
+ 	comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ 	short data;
+@@ -1493,7 +1493,7 @@ static void get_last_sample_611x(comedi_device * dev)
+ 	}
+ }
+ 
+-static void get_last_sample_6143(comedi_device * dev)
++static void get_last_sample_6143(struct comedi_device * dev)
+ {
+ 	comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ 	short data;
+@@ -1513,7 +1513,7 @@ static void get_last_sample_6143(comedi_device * dev)
+ 	}
+ }
+ 
+-static void ni_ai_munge(comedi_device * dev, comedi_subdevice * s,
++static void ni_ai_munge(struct comedi_device * dev, comedi_subdevice * s,
+ 	void *data, unsigned int num_bytes, unsigned int chan_index)
+ {
+ 	comedi_async *async = s->async;
+@@ -1539,7 +1539,7 @@ static void ni_ai_munge(comedi_device * dev, comedi_subdevice * s,
+ 
+ #ifdef PCIDMA
+ 
+-static int ni_ai_setup_MITE_dma(comedi_device * dev)
++static int ni_ai_setup_MITE_dma(struct comedi_device * dev)
+ {
+ 	comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+ 	int retval;
+@@ -1579,7 +1579,7 @@ static int ni_ai_setup_MITE_dma(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int ni_ao_setup_MITE_dma(comedi_device * dev)
++static int ni_ao_setup_MITE_dma(struct comedi_device * dev)
+ {
+ 	comedi_subdevice *s = dev->subdevices + NI_AO_SUBDEV;
+ 	int retval;
+@@ -1617,7 +1617,7 @@ static int ni_ao_setup_MITE_dma(comedi_device * dev)
+    this is pretty harsh for a cancel, but it works...
+  */
+ 
+-static int ni_ai_reset(comedi_device * dev, comedi_subdevice * s)
++static int ni_ai_reset(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	ni_release_ai_mite_channel(dev);
+ 	/* ai configuration */
+@@ -1698,7 +1698,7 @@ static int ni_ai_reset(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ni_ai_poll(comedi_device * dev, comedi_subdevice * s)
++static int ni_ai_poll(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	unsigned long flags = 0;
+ 	int count;
+@@ -1718,7 +1718,7 @@ static int ni_ai_poll(comedi_device * dev, comedi_subdevice * s)
+ 	return count;
+ }
+ 
+-static int ni_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int ni_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+@@ -1814,7 +1814,7 @@ static int ni_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return insn->n;
+ }
+ 
+-void ni_prime_channelgain_list(comedi_device * dev)
++void ni_prime_channelgain_list(struct comedi_device * dev)
+ {
+ 	int i;
+ 	devpriv->stc_writew(dev, AI_CONVERT_Pulse, AI_Command_1_Register);
+@@ -1830,7 +1830,7 @@ void ni_prime_channelgain_list(comedi_device * dev)
+ 	rt_printk("ni_mio_common: timeout loading channel/gain list\n");
+ }
+ 
+-static void ni_m_series_load_channelgain_list(comedi_device * dev,
++static void ni_m_series_load_channelgain_list(struct comedi_device * dev,
+ 	unsigned int n_chan, unsigned int *list)
+ {
+ 	unsigned int chan, range, aref;
+@@ -1935,7 +1935,7 @@ static void ni_m_series_load_channelgain_list(comedi_device * dev,
+  *   bits 0-2: channel
+  *       valid channels are 0-3
+  */
+-static void ni_load_channelgain_list(comedi_device * dev, unsigned int n_chan,
++static void ni_load_channelgain_list(struct comedi_device * dev, unsigned int n_chan,
+ 	unsigned int *list)
+ {
+ 	unsigned int chan, range, aref;
+@@ -2055,7 +2055,7 @@ static void ni_load_channelgain_list(comedi_device * dev, unsigned int n_chan,
+ 	}
+ }
+ 
+-static int ni_ns_to_timer(const comedi_device * dev, unsigned nanosec,
++static int ni_ns_to_timer(const struct comedi_device * dev, unsigned nanosec,
+ 	int round_mode)
+ {
+ 	int divider;
+@@ -2074,12 +2074,12 @@ static int ni_ns_to_timer(const comedi_device * dev, unsigned nanosec,
+ 	return divider - 1;
+ }
+ 
+-static unsigned ni_timer_to_ns(const comedi_device * dev, int timer)
++static unsigned ni_timer_to_ns(const struct comedi_device * dev, int timer)
+ {
+ 	return devpriv->clock_ns * (timer + 1);
+ }
+ 
+-static unsigned ni_min_ai_scan_period_ns(comedi_device * dev,
++static unsigned ni_min_ai_scan_period_ns(struct comedi_device * dev,
+ 	unsigned num_channels)
+ {
+ 	switch (boardtype.reg_type) {
+@@ -2095,7 +2095,7 @@ static unsigned ni_min_ai_scan_period_ns(comedi_device * dev,
+ 	return boardtype.ai_speed * num_channels;
+ }
+ 
+-static int ni_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int ni_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -2308,7 +2308,7 @@ static int ni_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int ni_ai_cmd(comedi_device * dev, comedi_subdevice * s)
++static int ni_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	const comedi_cmd *cmd = &s->async->cmd;
+ 	int timer;
+@@ -2612,7 +2612,7 @@ static int ni_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ni_ai_inttrig(comedi_device * dev, comedi_subdevice * s,
++static int ni_ai_inttrig(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int trignum)
+ {
+ 	if (trignum != 0)
+@@ -2625,10 +2625,10 @@ static int ni_ai_inttrig(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int ni_ai_config_analog_trig(comedi_device * dev, comedi_subdevice * s,
++static int ni_ai_config_analog_trig(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int ni_ai_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int ni_ai_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n < 1)
+@@ -2679,7 +2679,7 @@ static int ni_ai_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 	return -EINVAL;
+ }
+ 
+-static int ni_ai_config_analog_trig(comedi_device * dev, comedi_subdevice * s,
++static int ni_ai_config_analog_trig(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int a, b, modebits;
+@@ -2777,7 +2777,7 @@ static int ni_ai_config_analog_trig(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ /* munge data from unsigned to 2's complement for analog output bipolar modes */
+-static void ni_ao_munge(comedi_device * dev, comedi_subdevice * s,
++static void ni_ao_munge(struct comedi_device * dev, comedi_subdevice * s,
+ 	void *data, unsigned int num_bytes, unsigned int chan_index)
+ {
+ 	comedi_async *async = s->async;
+@@ -2800,7 +2800,7 @@ static void ni_ao_munge(comedi_device * dev, comedi_subdevice * s,
+ 	}
+ }
+ 
+-static int ni_m_series_ao_config_chanlist(comedi_device * dev,
++static int ni_m_series_ao_config_chanlist(struct comedi_device * dev,
+ 	comedi_subdevice * s, unsigned int chanspec[], unsigned int n_chans,
+ 	int timed)
+ {
+@@ -2869,7 +2869,7 @@ static int ni_m_series_ao_config_chanlist(comedi_device * dev,
+ 	return invert;
+ }
+ 
+-static int ni_old_ao_config_chanlist(comedi_device * dev, comedi_subdevice * s,
++static int ni_old_ao_config_chanlist(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int chanspec[], unsigned int n_chans)
+ {
+ 	unsigned int range;
+@@ -2912,7 +2912,7 @@ static int ni_old_ao_config_chanlist(comedi_device * dev, comedi_subdevice * s,
+ 	return invert;
+ }
+ 
+-static int ni_ao_config_chanlist(comedi_device * dev, comedi_subdevice * s,
++static int ni_ao_config_chanlist(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int chanspec[], unsigned int n_chans, int timed)
+ {
+ 	if (boardtype.reg_type & ni_reg_m_series_mask)
+@@ -2921,7 +2921,7 @@ static int ni_ao_config_chanlist(comedi_device * dev, comedi_subdevice * s,
+ 	else
+ 		return ni_old_ao_config_chanlist(dev, s, chanspec, n_chans);
+ }
+-static int ni_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int ni_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->ao[CR_CHAN(insn->chanspec)];
+@@ -2929,7 +2929,7 @@ static int ni_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int ni_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
++static int ni_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int chan = CR_CHAN(insn->chanspec);
+@@ -2948,7 +2948,7 @@ static int ni_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int ni_ao_insn_write_671x(comedi_device * dev, comedi_subdevice * s,
++static int ni_ao_insn_write_671x(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int chan = CR_CHAN(insn->chanspec);
+@@ -2965,7 +2965,7 @@ static int ni_ao_insn_write_671x(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int ni_ao_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int ni_ao_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+@@ -2991,7 +2991,7 @@ static int ni_ao_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 	return -EINVAL;
+ }
+ 
+-static int ni_ao_inttrig(comedi_device * dev, comedi_subdevice * s,
++static int ni_ao_inttrig(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int trignum)
+ {
+ 	int ret;
+@@ -3062,7 +3062,7 @@ static int ni_ao_inttrig(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int ni_ao_cmd(comedi_device * dev, comedi_subdevice * s)
++static int ni_ao_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	const comedi_cmd *cmd = &s->async->cmd;
+ 	int bits;
+@@ -3261,7 +3261,7 @@ static int ni_ao_cmd(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ni_ao_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int ni_ao_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -3384,7 +3384,7 @@ static int ni_ao_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int ni_ao_reset(comedi_device * dev, comedi_subdevice * s)
++static int ni_ao_reset(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	//devpriv->ao0p=0x0000;
+ 	//ni_writew(devpriv->ao0p,AO_Configuration);
+@@ -3436,7 +3436,7 @@ static int ni_ao_reset(comedi_device * dev, comedi_subdevice * s)
+ 
+ // digital io
+ 
+-static int ni_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int ni_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ #ifdef DEBUG_DIO
+@@ -3468,7 +3468,7 @@ static int ni_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int ni_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int ni_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ #ifdef DEBUG_DIO
+@@ -3495,7 +3495,7 @@ static int ni_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int ni_m_series_dio_insn_config(comedi_device * dev,
++static int ni_m_series_dio_insn_config(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ #ifdef DEBUG_DIO
+@@ -3525,7 +3525,7 @@ static int ni_m_series_dio_insn_config(comedi_device * dev,
+ 	return 1;
+ }
+ 
+-static int ni_m_series_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int ni_m_series_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ #ifdef DEBUG_DIO
+@@ -3544,7 +3544,7 @@ static int ni_m_series_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int ni_cdio_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int ni_cdio_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -3653,7 +3653,7 @@ static int ni_cdio_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int ni_cdio_cmd(comedi_device * dev, comedi_subdevice * s)
++static int ni_cdio_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	const comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned cdo_mode_bits = CDO_FIFO_Mode_Bit | CDO_Halt_On_Error_Bit;
+@@ -3690,7 +3690,7 @@ static int ni_cdio_cmd(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ni_cdo_inttrig(comedi_device * dev, comedi_subdevice * s,
++static int ni_cdo_inttrig(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int trignum)
+ {
+ #ifdef PCIDMA
+@@ -3736,7 +3736,7 @@ static int ni_cdo_inttrig(comedi_device * dev, comedi_subdevice * s,
+ 	return retval;
+ }
+ 
+-static int ni_cdio_cancel(comedi_device * dev, comedi_subdevice * s)
++static int ni_cdio_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	ni_writel(CDO_Disarm_Bit | CDO_Error_Interrupt_Enable_Clear_Bit |
+ 		CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit |
+@@ -3749,7 +3749,7 @@ static int ni_cdio_cancel(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static void handle_cdio_interrupt(comedi_device * dev)
++static void handle_cdio_interrupt(struct comedi_device * dev)
+ {
+ 	unsigned cdio_status;
+ 	comedi_subdevice *s = dev->subdevices + NI_DIO_SUBDEV;
+@@ -3790,7 +3790,7 @@ static void handle_cdio_interrupt(comedi_device * dev)
+ 	ni_event(dev, s);
+ }
+ 
+-static int ni_serial_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int ni_serial_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int err = insn->n;
+@@ -3884,7 +3884,7 @@ static int ni_serial_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 
+ }
+ 
+-static int ni_serial_hw_readwrite8(comedi_device * dev, comedi_subdevice * s,
++static int ni_serial_hw_readwrite8(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned char data_out, unsigned char *data_in)
+ {
+ 	unsigned int status1;
+@@ -3940,7 +3940,7 @@ static int ni_serial_hw_readwrite8(comedi_device * dev, comedi_subdevice * s,
+ 	return err;
+ }
+ 
+-static int ni_serial_sw_readwrite8(comedi_device * dev, comedi_subdevice * s,
++static int ni_serial_sw_readwrite8(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned char data_out, unsigned char *data_in)
+ {
+ 	unsigned char mask, input = 0;
+@@ -3993,7 +3993,7 @@ static int ni_serial_sw_readwrite8(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static void mio_common_detach(comedi_device * dev)
++static void mio_common_detach(struct comedi_device * dev)
+ {
+ 	if (dev->private) {
+ 		if (devpriv->counter_dev) {
+@@ -4004,7 +4004,7 @@ static void mio_common_detach(comedi_device * dev)
+ 		subdev_8255_cleanup(dev, dev->subdevices + NI_8255_DIO_SUBDEV);
+ }
+ 
+-static void init_ao_67xx(comedi_device * dev, comedi_subdevice * s)
++static void init_ao_67xx(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	int i;
+ 
+@@ -4111,7 +4111,7 @@ static unsigned ni_gpct_to_stc_register(enum ni_gpct_register reg)
+ static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits,
+ 	enum ni_gpct_register reg)
+ {
+-	comedi_device *dev = counter->counter_dev->dev;
++	struct comedi_device *dev = counter->counter_dev->dev;
+ 	unsigned stc_register;
+ 	/* bits in the join reset register which are relevant to counters */
+ 	static const unsigned gpct_joint_reset_mask = G0_Reset | G1_Reset;
+@@ -4179,7 +4179,7 @@ static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits,
+ static unsigned ni_gpct_read_register(struct ni_gpct *counter,
+ 	enum ni_gpct_register reg)
+ {
+-	comedi_device *dev = counter->counter_dev->dev;
++	struct comedi_device *dev = counter->counter_dev->dev;
+ 	unsigned stc_register;
+ 	switch (reg) {
+ 		/* m-series only registers */
+@@ -4208,14 +4208,14 @@ static unsigned ni_gpct_read_register(struct ni_gpct *counter,
+ 	return 0;
+ }
+ 
+-static int ni_freq_out_insn_read(comedi_device * dev,
++static int ni_freq_out_insn_read(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->clock_and_fout & FOUT_Divider_mask;
+ 	return 1;
+ }
+ 
+-static int ni_freq_out_insn_write(comedi_device * dev,
++static int ni_freq_out_insn_write(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	devpriv->clock_and_fout &= ~FOUT_Enable;
+@@ -4229,7 +4229,7 @@ static int ni_freq_out_insn_write(comedi_device * dev,
+ 	return insn->n;
+ }
+ 
+-static int ni_set_freq_out_clock(comedi_device * dev, unsigned int clock_source)
++static int ni_set_freq_out_clock(struct comedi_device * dev, unsigned int clock_source)
+ {
+ 	switch (clock_source) {
+ 	case NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC:
+@@ -4246,7 +4246,7 @@ static int ni_set_freq_out_clock(comedi_device * dev, unsigned int clock_source)
+ 	return 3;
+ }
+ 
+-static void ni_get_freq_out_clock(comedi_device * dev, unsigned int * clock_source,
++static void ni_get_freq_out_clock(struct comedi_device * dev, unsigned int * clock_source,
+ 	unsigned int * clock_period_ns)
+ {
+ 	if (devpriv->clock_and_fout & FOUT_Timebase_Select) {
+@@ -4258,7 +4258,7 @@ static void ni_get_freq_out_clock(comedi_device * dev, unsigned int * clock_sour
+ 	}
+ }
+ 
+-static int ni_freq_out_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int ni_freq_out_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+@@ -4274,7 +4274,7 @@ static int ni_freq_out_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 	return -EINVAL;
+ }
+ 
+-static int ni_alloc_private(comedi_device * dev)
++static int ni_alloc_private(struct comedi_device * dev)
+ {
+ 	int ret;
+ 
+@@ -4289,7 +4289,7 @@ static int ni_alloc_private(comedi_device * dev)
+ 	return 0;
+ };
+ 
+-static int ni_E_init(comedi_device * dev, comedi_devconfig * it)
++static int ni_E_init(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	unsigned j;
+@@ -4609,7 +4609,7 @@ static int ni_E_init(comedi_device * dev, comedi_devconfig * it)
+ 
+ static int ni_8255_callback(int dir, int port, int data, unsigned long arg)
+ {
+-	comedi_device *dev = (comedi_device *) arg;
++	struct comedi_device *dev = (struct comedi_device *) arg;
+ 
+ 	if (dir) {
+ 		ni_writeb(data, Port_A + 2 * port);
+@@ -4623,7 +4623,7 @@ static int ni_8255_callback(int dir, int port, int data, unsigned long arg)
+ 	presents the EEPROM as a subdevice
+ */
+ 
+-static int ni_eeprom_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int ni_eeprom_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = ni_read_eeprom(dev, CR_CHAN(insn->chanspec));
+@@ -4635,7 +4635,7 @@ static int ni_eeprom_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	reads bytes out of eeprom
+ */
+ 
+-static int ni_read_eeprom(comedi_device * dev, int addr)
++static int ni_read_eeprom(struct comedi_device * dev, int addr)
+ {
+ 	int bit;
+ 	int bitstring;
+@@ -4659,7 +4659,7 @@ static int ni_read_eeprom(comedi_device * dev, int addr)
+ 	return bitstring;
+ }
+ 
+-static int ni_m_series_eeprom_insn_read(comedi_device * dev,
++static int ni_m_series_eeprom_insn_read(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->eeprom_buffer[CR_CHAN(insn->chanspec)];
+@@ -4667,14 +4667,14 @@ static int ni_m_series_eeprom_insn_read(comedi_device * dev,
+ 	return 1;
+ }
+ 
+-static int ni_get_pwm_config(comedi_device * dev, unsigned int * data)
++static int ni_get_pwm_config(struct comedi_device * dev, unsigned int * data)
+ {
+ 	data[1] = devpriv->pwm_up_count * devpriv->clock_ns;
+ 	data[2] = devpriv->pwm_down_count * devpriv->clock_ns;
+ 	return 3;
+ }
+ 
+-static int ni_m_series_pwm_config(comedi_device * dev, comedi_subdevice * s,
++static int ni_m_series_pwm_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned up_count, down_count;
+@@ -4739,7 +4739,7 @@ static int ni_m_series_pwm_config(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int ni_6143_pwm_config(comedi_device * dev, comedi_subdevice * s,
++static int ni_6143_pwm_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned up_count, down_count;
+@@ -4802,11 +4802,11 @@ static int ni_6143_pwm_config(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static void ni_write_caldac(comedi_device * dev, int addr, int val);
++static void ni_write_caldac(struct comedi_device * dev, int addr, int val);
+ /*
+ 	calibration subdevice
+ */
+-static int ni_calib_insn_write(comedi_device * dev, comedi_subdevice * s,
++static int ni_calib_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	ni_write_caldac(dev, CR_CHAN(insn->chanspec), data[0]);
+@@ -4814,7 +4814,7 @@ static int ni_calib_insn_write(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int ni_calib_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int ni_calib_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->caldacs[CR_CHAN(insn->chanspec)];
+@@ -4845,7 +4845,7 @@ static struct caldac_struct caldacs[] = {
+ 	[ad8804_debug] = {16, 8, pack_ad8804},
+ };
+ 
+-static void caldac_setup(comedi_device * dev, comedi_subdevice * s)
++static void caldac_setup(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	int i, j;
+ 	int n_dacs;
+@@ -4898,7 +4898,7 @@ static void caldac_setup(comedi_device * dev, comedi_subdevice * s)
+ 	}
+ }
+ 
+-static void ni_write_caldac(comedi_device * dev, int addr, int val)
++static void ni_write_caldac(struct comedi_device * dev, int addr, int val)
+ {
+ 	unsigned int loadbit = 0, bits = 0, bit, bitstring = 0;
+ 	int i;
+@@ -4985,7 +4985,7 @@ static int pack_ad8842(int addr, int val, int *bitstring)
+ /*
+  *	Read the GPCTs current value.
+  */
+-static int GPCT_G_Watch(comedi_device * dev, int chan)
++static int GPCT_G_Watch(struct comedi_device * dev, int chan)
+ {
+ 	unsigned int hi1, hi2, lo;
+ 
+@@ -5008,7 +5008,7 @@ static int GPCT_G_Watch(comedi_device * dev, int chan)
+ 	return (hi1 << 16) | lo;
+ }
+ 
+-static void GPCT_Reset(comedi_device * dev, int chan)
++static void GPCT_Reset(struct comedi_device * dev, int chan)
+ {
+ 	int temp_ack_reg = 0;
+ 
+@@ -5070,28 +5070,28 @@ static void GPCT_Reset(comedi_device * dev, int chan)
+ 
+ #endif
+ 
+-static int ni_gpct_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int ni_gpct_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	struct ni_gpct *counter = s->private;
+ 	return ni_tio_insn_config(counter, insn, data);
+ }
+ 
+-static int ni_gpct_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int ni_gpct_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	struct ni_gpct *counter = s->private;
+ 	return ni_tio_rinsn(counter, insn, data);
+ }
+ 
+-static int ni_gpct_insn_write(comedi_device * dev, comedi_subdevice * s,
++static int ni_gpct_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	struct ni_gpct *counter = s->private;
+ 	return ni_tio_winsn(counter, insn, data);
+ }
+ 
+-static int ni_gpct_cmd(comedi_device * dev, comedi_subdevice * s)
++static int ni_gpct_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	int retval;
+ #ifdef PCIDMA
+@@ -5114,7 +5114,7 @@ static int ni_gpct_cmd(comedi_device * dev, comedi_subdevice * s)
+ 	return retval;
+ }
+ 
+-static int ni_gpct_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int ni_gpct_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ #ifdef PCIDMA
+@@ -5126,7 +5126,7 @@ static int ni_gpct_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ #endif
+ }
+ 
+-static int ni_gpct_cancel(comedi_device * dev, comedi_subdevice * s)
++static int ni_gpct_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ #ifdef PCIDMA
+ 	struct ni_gpct *counter = s->private;
+@@ -5147,7 +5147,7 @@ static int ni_gpct_cancel(comedi_device * dev, comedi_subdevice * s)
+  *
+  */
+ 
+-static int ni_m_series_set_pfi_routing(comedi_device * dev, unsigned chan,
++static int ni_m_series_set_pfi_routing(struct comedi_device * dev, unsigned chan,
+ 	unsigned source)
+ {
+ 	unsigned pfi_reg_index;
+@@ -5165,7 +5165,7 @@ static int ni_m_series_set_pfi_routing(comedi_device * dev, unsigned chan,
+ 	return 2;
+ }
+ 
+-static int ni_old_set_pfi_routing(comedi_device * dev, unsigned chan,
++static int ni_old_set_pfi_routing(struct comedi_device * dev, unsigned chan,
+ 	unsigned source)
+ {
+ 	// pre-m-series boards have fixed signals on pfi pins
+@@ -5174,7 +5174,7 @@ static int ni_old_set_pfi_routing(comedi_device * dev, unsigned chan,
+ 	return 2;
+ }
+ 
+-static int ni_set_pfi_routing(comedi_device * dev, unsigned chan,
++static int ni_set_pfi_routing(struct comedi_device * dev, unsigned chan,
+ 	unsigned source)
+ {
+ 	if (boardtype.reg_type & ni_reg_m_series_mask)
+@@ -5183,14 +5183,14 @@ static int ni_set_pfi_routing(comedi_device * dev, unsigned chan,
+ 		return ni_old_set_pfi_routing(dev, chan, source);
+ }
+ 
+-static unsigned ni_m_series_get_pfi_routing(comedi_device * dev, unsigned chan)
++static unsigned ni_m_series_get_pfi_routing(struct comedi_device * dev, unsigned chan)
+ {
+ 	const unsigned array_offset = chan / 3;
+ 	return MSeries_PFI_Output_Select_Source(chan,
+ 		devpriv->pfi_output_select_reg[array_offset]);
+ }
+ 
+-static unsigned ni_old_get_pfi_routing(comedi_device * dev, unsigned chan)
++static unsigned ni_old_get_pfi_routing(struct comedi_device * dev, unsigned chan)
+ {
+ 	// pre-m-series boards have fixed signals on pfi pins
+ 	switch (chan) {
+@@ -5231,7 +5231,7 @@ static unsigned ni_old_get_pfi_routing(comedi_device * dev, unsigned chan)
+ 	return 0;
+ }
+ 
+-static unsigned ni_get_pfi_routing(comedi_device * dev, unsigned chan)
++static unsigned ni_get_pfi_routing(struct comedi_device * dev, unsigned chan)
+ {
+ 	if (boardtype.reg_type & ni_reg_m_series_mask)
+ 		return ni_m_series_get_pfi_routing(dev, chan);
+@@ -5239,7 +5239,7 @@ static unsigned ni_get_pfi_routing(comedi_device * dev, unsigned chan)
+ 		return ni_old_get_pfi_routing(dev, chan);
+ }
+ 
+-static int ni_config_filter(comedi_device * dev, unsigned pfi_channel,
++static int ni_config_filter(struct comedi_device * dev, unsigned pfi_channel,
+ 	enum ni_pfi_filter_select filter)
+ {
+ 	unsigned bits;
+@@ -5253,7 +5253,7 @@ static int ni_config_filter(comedi_device * dev, unsigned pfi_channel,
+ 	return 0;
+ }
+ 
+-static int ni_pfi_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int ni_pfi_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if ((boardtype.reg_type & ni_reg_m_series_mask) == 0) {
+@@ -5268,7 +5268,7 @@ static int ni_pfi_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int ni_pfi_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int ni_pfi_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int chan;
+@@ -5312,7 +5312,7 @@ static int ni_pfi_insn_config(comedi_device * dev, comedi_subdevice * s,
+  *  NI RTSI Bus Functions
+  *
+  */
+-static void ni_rtsi_init(comedi_device * dev)
++static void ni_rtsi_init(struct comedi_device * dev)
+ {
+ 	// Initialises the RTSI bus signal switch to a default state
+ 
+@@ -5345,7 +5345,7 @@ static void ni_rtsi_init(comedi_device * dev)
+ //      devpriv->stc_writew(dev, 0x0000, RTSI_Board_Register);
+ }
+ 
+-static int ni_rtsi_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int ni_rtsi_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -5401,7 +5401,7 @@ static int ni_mseries_get_pll_parameters(unsigned reference_period_ns,
+ 	return 0;
+ }
+ 
+-static inline unsigned num_configurable_rtsi_channels(comedi_device * dev)
++static inline unsigned num_configurable_rtsi_channels(struct comedi_device * dev)
+ {
+ 	if (boardtype.reg_type & ni_reg_m_series_mask)
+ 		return 8;
+@@ -5409,7 +5409,7 @@ static inline unsigned num_configurable_rtsi_channels(comedi_device * dev)
+ 		return 7;
+ }
+ 
+-static int ni_mseries_set_pll_master_clock(comedi_device * dev, unsigned source,
++static int ni_mseries_set_pll_master_clock(struct comedi_device * dev, unsigned source,
+ 	unsigned period_ns)
+ {
+ 	static const unsigned min_period_ns = 50;
+@@ -5504,7 +5504,7 @@ static int ni_mseries_set_pll_master_clock(comedi_device * dev, unsigned source,
+ 	return 3;
+ }
+ 
+-static int ni_set_master_clock(comedi_device * dev, unsigned source,
++static int ni_set_master_clock(struct comedi_device * dev, unsigned source,
+ 	unsigned period_ns)
+ {
+ 	if (source == NI_MIO_INTERNAL_CLOCK) {
+@@ -5548,7 +5548,7 @@ static int ni_set_master_clock(comedi_device * dev, unsigned source,
+ 	return 3;
+ }
+ 
+-static int ni_valid_rtsi_output_source(comedi_device * dev, unsigned chan,
++static int ni_valid_rtsi_output_source(struct comedi_device * dev, unsigned chan,
+ 	unsigned source)
+ {
+ 	if (chan >= num_configurable_rtsi_channels(dev)) {
+@@ -5589,7 +5589,7 @@ static int ni_valid_rtsi_output_source(comedi_device * dev, unsigned chan,
+ 	}
+ }
+ 
+-static int ni_set_rtsi_routing(comedi_device * dev, unsigned chan,
++static int ni_set_rtsi_routing(struct comedi_device * dev, unsigned chan,
+ 	unsigned source)
+ {
+ 	if (ni_valid_rtsi_output_source(dev, chan, source) == 0)
+@@ -5610,7 +5610,7 @@ static int ni_set_rtsi_routing(comedi_device * dev, unsigned chan,
+ 	return 2;
+ }
+ 
+-static unsigned ni_get_rtsi_routing(comedi_device * dev, unsigned chan)
++static unsigned ni_get_rtsi_routing(struct comedi_device * dev, unsigned chan)
+ {
+ 	if (chan < 4) {
+ 		return RTSI_Trig_Output_Source(chan,
+@@ -5626,7 +5626,7 @@ static unsigned ni_get_rtsi_routing(comedi_device * dev, unsigned chan)
+ 	}
+ }
+ 
+-static int ni_rtsi_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int ni_rtsi_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int chan = CR_CHAN(insn->chanspec);
+@@ -5698,7 +5698,7 @@ static int ni_rtsi_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int cs5529_wait_for_idle(comedi_device * dev)
++static int cs5529_wait_for_idle(struct comedi_device * dev)
+ {
+ 	unsigned short status;
+ 	const int timeout = HZ;
+@@ -5722,7 +5722,7 @@ static int cs5529_wait_for_idle(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static void cs5529_command(comedi_device * dev, unsigned short value)
++static void cs5529_command(struct comedi_device * dev, unsigned short value)
+ {
+ 	static const int timeout = 100;
+ 	int i;
+@@ -5744,7 +5744,7 @@ static void cs5529_command(comedi_device * dev, unsigned short value)
+ }
+ 
+ /* write to cs5529 register */
+-static void cs5529_config_write(comedi_device * dev, unsigned int value,
++static void cs5529_config_write(struct comedi_device * dev, unsigned int value,
+ 	unsigned int reg_select_bits)
+ {
+ 	ni_ao_win_outw(dev, ((value >> 16) & 0xff),
+@@ -5759,7 +5759,7 @@ static void cs5529_config_write(comedi_device * dev, unsigned int value,
+ 
+ #ifdef NI_CS5529_DEBUG
+ /* read from cs5529 register */
+-static unsigned int cs5529_config_read(comedi_device * dev,
++static unsigned int cs5529_config_read(struct comedi_device * dev,
+ 	unsigned int reg_select_bits)
+ {
+ 	unsigned int value;
+@@ -5775,7 +5775,7 @@ static unsigned int cs5529_config_read(comedi_device * dev,
+ }
+ #endif
+ 
+-static int cs5529_do_conversion(comedi_device * dev, unsigned short *data)
++static int cs5529_do_conversion(struct comedi_device * dev, unsigned short *data)
+ {
+ 	int retval;
+ 	unsigned short status;
+@@ -5805,7 +5805,7 @@ static int cs5529_do_conversion(comedi_device * dev, unsigned short *data)
+ 	return 0;
+ }
+ 
+-static int cs5529_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int cs5529_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, retval;
+@@ -5831,7 +5831,7 @@ static int cs5529_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return insn->n;
+ }
+ 
+-static int init_cs5529(comedi_device * dev)
++static int init_cs5529(struct comedi_device * dev)
+ {
+ 	unsigned int config_bits =
+ 		CSCFG_PORT_MODE | CSCFG_WORD_RATE_2180_CYCLES;
+diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c
+index 258613fafa3a..4891bc2805f8 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_cs.c
++++ b/drivers/staging/comedi/drivers/ni_mio_cs.c
+@@ -194,7 +194,7 @@ typedef struct {
+  * read/written directly in the I/O space of the board.  The
+  * DAQCard devices map the low 8 STC registers to iobase+addr*2. */
+ 
+-static void mio_cs_win_out(comedi_device * dev, uint16_t data, int addr)
++static void mio_cs_win_out(struct comedi_device * dev, uint16_t data, int addr)
+ {
+ 	unsigned long flags;
+ 
+@@ -208,7 +208,7 @@ static void mio_cs_win_out(comedi_device * dev, uint16_t data, int addr)
+ 	comedi_spin_unlock_irqrestore(&devpriv->window_lock, flags);
+ }
+ 
+-static uint16_t mio_cs_win_in(comedi_device * dev, int addr)
++static uint16_t mio_cs_win_in(struct comedi_device * dev, int addr)
+ {
+ 	unsigned long flags;
+ 	uint16_t ret;
+@@ -225,8 +225,8 @@ static uint16_t mio_cs_win_in(comedi_device * dev, int addr)
+ 	return ret;
+ }
+ 
+-static int mio_cs_attach(comedi_device * dev, comedi_devconfig * it);
+-static int mio_cs_detach(comedi_device * dev);
++static int mio_cs_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int mio_cs_detach(struct comedi_device * dev);
+ static comedi_driver driver_ni_mio_cs = {
+       driver_name:"ni_mio_cs",
+       module:THIS_MODULE,
+@@ -236,11 +236,11 @@ static comedi_driver driver_ni_mio_cs = {
+ 
+ #include "ni_mio_common.c"
+ 
+-static int ni_getboardtype(comedi_device * dev, struct pcmcia_device *link);
++static int ni_getboardtype(struct comedi_device * dev, struct pcmcia_device *link);
+ 
+ /* clean up allocated resources */
+ /* called when driver is removed */
+-static int mio_cs_detach(comedi_device * dev)
++static int mio_cs_detach(struct comedi_device * dev)
+ {
+ 	mio_common_detach(dev);
+ 
+@@ -401,7 +401,7 @@ static void mio_cs_config(struct pcmcia_device *link)
+ 	link->dev_node = &dev_node;
+ }
+ 
+-static int mio_cs_attach(comedi_device * dev, comedi_devconfig * it)
++static int mio_cs_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	struct pcmcia_device *link;
+ 	unsigned int irq;
+@@ -466,7 +466,7 @@ static int mio_cs_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int get_prodid(comedi_device * dev, struct pcmcia_device *link)
++static int get_prodid(struct comedi_device * dev, struct pcmcia_device *link)
+ {
+ 	tuple_t tuple;
+ 	u_short buf[128];
+@@ -485,7 +485,7 @@ static int get_prodid(comedi_device * dev, struct pcmcia_device *link)
+ 	return prodid;
+ }
+ 
+-static int ni_getboardtype(comedi_device * dev, struct pcmcia_device *link)
++static int ni_getboardtype(struct comedi_device * dev, struct pcmcia_device *link)
+ {
+ 	int id;
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
+index 289d7b921513..b236d88e4e4e 100644
+--- a/drivers/staging/comedi/drivers/ni_pcidio.c
++++ b/drivers/staging/comedi/drivers/ni_pcidio.c
+@@ -287,9 +287,9 @@ enum FPGA_Control_Bits {
+ #define IntEn (TransferReady|CountExpired|Waited|PrimaryTC|SecondaryTC)
+ #endif
+ 
+-static int nidio_attach(comedi_device * dev, comedi_devconfig * it);
+-static int nidio_detach(comedi_device * dev);
+-static int ni_pcidio_cancel(comedi_device * dev, comedi_subdevice * s);
++static int nidio_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int nidio_detach(struct comedi_device * dev);
++static int ni_pcidio_cancel(struct comedi_device * dev, comedi_subdevice * s);
+ 
+ static comedi_driver driver_pcidio = {
+       driver_name:"ni_pcidio",
+@@ -399,14 +399,14 @@ typedef struct {
+ } nidio96_private;
+ #define devpriv ((nidio96_private *)dev->private)
+ 
+-static int ni_pcidio_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int ni_pcidio_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int ni_pcidio_cmd(comedi_device * dev, comedi_subdevice * s);
+-static int ni_pcidio_inttrig(comedi_device * dev, comedi_subdevice * s,
++static int ni_pcidio_cmd(struct comedi_device * dev, comedi_subdevice * s);
++static int ni_pcidio_inttrig(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int trignum);
+-static int nidio_find_device(comedi_device * dev, int bus, int slot);
++static int nidio_find_device(struct comedi_device * dev, int bus, int slot);
+ static int ni_pcidio_ns_to_timer(int *nanosec, int round_mode);
+-static int setup_mite_dma(comedi_device * dev, comedi_subdevice * s);
++static int setup_mite_dma(struct comedi_device * dev, comedi_subdevice * s);
+ 
+ #ifdef DEBUG_FLAGS
+ static void ni_pcidio_print_flags(unsigned int flags);
+@@ -416,7 +416,7 @@ static void ni_pcidio_print_status(unsigned int status);
+ #define ni_pcidio_print_status(x)
+ #endif
+ 
+-static int ni_pcidio_request_di_mite_channel(comedi_device * dev)
++static int ni_pcidio_request_di_mite_channel(struct comedi_device * dev)
+ {
+ 	unsigned long flags;
+ 
+@@ -439,7 +439,7 @@ static int ni_pcidio_request_di_mite_channel(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static void ni_pcidio_release_di_mite_channel(comedi_device * dev)
++static void ni_pcidio_release_di_mite_channel(struct comedi_device * dev)
+ {
+ 	unsigned long flags;
+ 
+@@ -467,7 +467,7 @@ static int nidio96_8255_cb(int dir, int port, int data, unsigned long iobase)
+ 	}
+ }
+ 
+-void ni_pcidio_event(comedi_device * dev, comedi_subdevice * s)
++void ni_pcidio_event(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	if (s->async->
+ 		events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW))
+@@ -479,7 +479,7 @@ void ni_pcidio_event(comedi_device * dev, comedi_subdevice * s)
+ 
+ static irqreturn_t nidio_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s = dev->subdevices;
+ 	comedi_async *async = s->async;
+ 	struct mite_struct *mite = devpriv->mite;
+@@ -673,7 +673,7 @@ static void ni_pcidio_print_status(unsigned int flags)
+ #endif
+ 
+ #ifdef unused
+-static void debug_int(comedi_device * dev)
++static void debug_int(struct comedi_device * dev)
+ {
+ 	int a, b;
+ 	static int n_int = 0;
+@@ -702,7 +702,7 @@ static void debug_int(comedi_device * dev)
+ }
+ #endif
+ 
+-static int ni_pcidio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int ni_pcidio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 1)
+@@ -729,7 +729,7 @@ static int ni_pcidio_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int ni_pcidio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int ni_pcidio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -744,7 +744,7 @@ static int ni_pcidio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int ni_pcidio_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int ni_pcidio_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -876,7 +876,7 @@ static int ni_pcidio_ns_to_timer(int *nanosec, int round_mode)
+ 	return divider;
+ }
+ 
+-static int ni_pcidio_cmd(comedi_device * dev, comedi_subdevice * s)
++static int ni_pcidio_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 
+@@ -986,7 +986,7 @@ static int ni_pcidio_cmd(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int setup_mite_dma(comedi_device * dev, comedi_subdevice * s)
++static int setup_mite_dma(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	int retval;
+ 
+@@ -1002,7 +1002,7 @@ static int setup_mite_dma(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ni_pcidio_inttrig(comedi_device * dev, comedi_subdevice * s,
++static int ni_pcidio_inttrig(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int trignum)
+ {
+ 	if (trignum != 0)
+@@ -1014,7 +1014,7 @@ static int ni_pcidio_inttrig(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int ni_pcidio_cancel(comedi_device * dev, comedi_subdevice * s)
++static int ni_pcidio_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	writeb(0x00,
+ 		devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control);
+@@ -1023,7 +1023,7 @@ static int ni_pcidio_cancel(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ni_pcidio_change(comedi_device * dev, comedi_subdevice * s,
++static int ni_pcidio_change(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned long new_size)
+ {
+ 	int ret;
+@@ -1037,7 +1037,7 @@ static int ni_pcidio_change(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int pci_6534_load_fpga(comedi_device * dev, int fpga_index, u8 * data,
++static int pci_6534_load_fpga(struct comedi_device * dev, int fpga_index, u8 * data,
+ 	int data_len)
+ {
+ 	static const int timeout = 1000;
+@@ -1090,12 +1090,12 @@ static int pci_6534_load_fpga(comedi_device * dev, int fpga_index, u8 * data,
+ 	return 0;
+ }
+ 
+-static int pci_6534_reset_fpga(comedi_device * dev, int fpga_index)
++static int pci_6534_reset_fpga(struct comedi_device * dev, int fpga_index)
+ {
+ 	return pci_6534_load_fpga(dev, fpga_index, NULL, 0);
+ }
+ 
+-static int pci_6534_reset_fpgas(comedi_device * dev)
++static int pci_6534_reset_fpgas(struct comedi_device * dev)
+ {
+ 	int ret;
+ 	int i;
+@@ -1109,7 +1109,7 @@ static int pci_6534_reset_fpgas(comedi_device * dev)
+ 	return ret;
+ }
+ 
+-static void pci_6534_init_main_fpga(comedi_device * dev)
++static void pci_6534_init_main_fpga(struct comedi_device * dev)
+ {
+ 	writel(0, devpriv->mite->daq_io_addr + FPGA_Control1_Register);
+ 	writel(0, devpriv->mite->daq_io_addr + FPGA_Control2_Register);
+@@ -1119,7 +1119,7 @@ static void pci_6534_init_main_fpga(comedi_device * dev)
+ 	writel(0, devpriv->mite->daq_io_addr + FPGA_SCBMS_Counter_Register);
+ }
+ 
+-static int pci_6534_upload_firmware(comedi_device * dev, int options[])
++static int pci_6534_upload_firmware(struct comedi_device * dev, int options[])
+ {
+ 	int ret;
+ 	void *main_fpga_data, *scarab_a_data, *scarab_b_data;
+@@ -1149,7 +1149,7 @@ static int pci_6534_upload_firmware(comedi_device * dev, int options[])
+ 	return 0;
+ }
+ 
+-static int nidio_attach(comedi_device * dev, comedi_devconfig * it)
++static int nidio_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	int i;
+@@ -1246,7 +1246,7 @@ static int nidio_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int nidio_detach(comedi_device * dev)
++static int nidio_detach(struct comedi_device * dev)
+ {
+ 	int i;
+ 
+@@ -1270,7 +1270,7 @@ static int nidio_detach(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int nidio_find_device(comedi_device * dev, int bus, int slot)
++static int nidio_find_device(struct comedi_device * dev, int bus, int slot)
+ {
+ 	struct mite_struct *mite;
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
+index 8d83fb41c3b2..cca0383fc775 100644
+--- a/drivers/staging/comedi/drivers/ni_pcimio.c
++++ b/drivers/staging/comedi/drivers/ni_pcimio.c
+@@ -1207,8 +1207,8 @@ static const ni_board ni_boards[] = {
+ 
+ #define n_pcimio_boards ((sizeof(ni_boards)/sizeof(ni_boards[0])))
+ 
+-static int pcimio_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pcimio_detach(comedi_device * dev);
++static int pcimio_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcimio_detach(struct comedi_device * dev);
+ static comedi_driver driver_pcimio = {
+ 	driver_name: DRV_NAME,
+ 	module:THIS_MODULE,
+@@ -1241,7 +1241,7 @@ NI_PRIVATE_COMMON} ni_private;
+ /* However, the 611x boards still aren't working, so I'm disabling
+  * non-windowed STC access temporarily */
+ 
+-static void e_series_win_out(comedi_device * dev, uint16_t data, int reg)
++static void e_series_win_out(struct comedi_device * dev, uint16_t data, int reg)
+ {
+ 	unsigned long flags;
+ 
+@@ -1251,7 +1251,7 @@ static void e_series_win_out(comedi_device * dev, uint16_t data, int reg)
+ 	comedi_spin_unlock_irqrestore(&devpriv->window_lock, flags);
+ }
+ 
+-static uint16_t e_series_win_in(comedi_device * dev, int reg)
++static uint16_t e_series_win_in(struct comedi_device * dev, int reg)
+ {
+ 	unsigned long flags;
+ 	uint16_t ret;
+@@ -1264,7 +1264,7 @@ static uint16_t e_series_win_in(comedi_device * dev, int reg)
+ 	return ret;
+ }
+ 
+-static void m_series_stc_writew(comedi_device * dev, uint16_t data, int reg)
++static void m_series_stc_writew(struct comedi_device * dev, uint16_t data, int reg)
+ {
+ 	unsigned offset;
+ 	switch (reg) {
+@@ -1419,7 +1419,7 @@ static void m_series_stc_writew(comedi_device * dev, uint16_t data, int reg)
+ 	ni_writew(data, offset);
+ }
+ 
+-static uint16_t m_series_stc_readw(comedi_device * dev, int reg)
++static uint16_t m_series_stc_readw(struct comedi_device * dev, int reg)
+ {
+ 	unsigned offset;
+ 	switch (reg) {
+@@ -1454,7 +1454,7 @@ static uint16_t m_series_stc_readw(comedi_device * dev, int reg)
+ 	return ni_readw(offset);
+ }
+ 
+-static void m_series_stc_writel(comedi_device * dev, uint32_t data, int reg)
++static void m_series_stc_writel(struct comedi_device * dev, uint32_t data, int reg)
+ {
+ 	unsigned offset;
+ 	switch (reg) {
+@@ -1495,7 +1495,7 @@ static void m_series_stc_writel(comedi_device * dev, uint32_t data, int reg)
+ 	ni_writel(data, offset);
+ }
+ 
+-static uint32_t m_series_stc_readl(comedi_device * dev, int reg)
++static uint32_t m_series_stc_readl(struct comedi_device * dev, int reg)
+ {
+ 	unsigned offset;
+ 	switch (reg) {
+@@ -1528,19 +1528,19 @@ static uint32_t m_series_stc_readl(comedi_device * dev, int reg)
+ 
+ #include "ni_mio_common.c"
+ 
+-static int pcimio_find_device(comedi_device * dev, int bus, int slot);
+-static int pcimio_ai_change(comedi_device * dev, comedi_subdevice * s,
++static int pcimio_find_device(struct comedi_device * dev, int bus, int slot);
++static int pcimio_ai_change(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned long new_size);
+-static int pcimio_ao_change(comedi_device * dev, comedi_subdevice * s,
++static int pcimio_ao_change(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned long new_size);
+-static int pcimio_gpct0_change(comedi_device * dev, comedi_subdevice * s,
++static int pcimio_gpct0_change(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned long new_size);
+-static int pcimio_gpct1_change(comedi_device * dev, comedi_subdevice * s,
++static int pcimio_gpct1_change(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned long new_size);
+-static int pcimio_dio_change(comedi_device * dev, comedi_subdevice * s,
++static int pcimio_dio_change(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned long new_size);
+ 
+-static void m_series_init_eeprom_buffer(comedi_device * dev)
++static void m_series_init_eeprom_buffer(struct comedi_device * dev)
+ {
+ 	static const int Start_Cal_EEPROM = 0x400;
+ 	static const unsigned window_size = 10;
+@@ -1577,7 +1577,7 @@ static void m_series_init_eeprom_buffer(comedi_device * dev)
+ 	writel(0x0, devpriv->mite->mite_io_addr + 0x30);
+ }
+ 
+-static void init_6143(comedi_device * dev)
++static void init_6143(struct comedi_device * dev)
+ {
+ 	// Disable interrupts
+ 	devpriv->stc_writew(dev, 0, Interrupt_Control_Register);
+@@ -1597,7 +1597,7 @@ static void init_6143(comedi_device * dev)
+ }
+ 
+ /* cleans up allocated resources */
+-static int pcimio_detach(comedi_device * dev)
++static int pcimio_detach(struct comedi_device * dev)
+ {
+ 	mio_common_detach(dev);
+ 	if (dev->irq) {
+@@ -1616,7 +1616,7 @@ static int pcimio_detach(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int pcimio_attach(comedi_device * dev, comedi_devconfig * it)
++static int pcimio_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int ret;
+ 
+@@ -1699,7 +1699,7 @@ static int pcimio_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return ret;
+ }
+ 
+-static int pcimio_find_device(comedi_device * dev, int bus, int slot)
++static int pcimio_find_device(struct comedi_device * dev, int bus, int slot)
+ {
+ 	struct mite_struct *mite;
+ 	int i;
+@@ -1727,7 +1727,7 @@ static int pcimio_find_device(comedi_device * dev, int bus, int slot)
+ 	return -EIO;
+ }
+ 
+-static int pcimio_ai_change(comedi_device * dev, comedi_subdevice * s,
++static int pcimio_ai_change(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned long new_size)
+ {
+ 	int ret;
+@@ -1739,7 +1739,7 @@ static int pcimio_ai_change(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int pcimio_ao_change(comedi_device * dev, comedi_subdevice * s,
++static int pcimio_ao_change(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned long new_size)
+ {
+ 	int ret;
+@@ -1751,7 +1751,7 @@ static int pcimio_ao_change(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int pcimio_gpct0_change(comedi_device * dev, comedi_subdevice * s,
++static int pcimio_gpct0_change(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned long new_size)
+ {
+ 	int ret;
+@@ -1763,7 +1763,7 @@ static int pcimio_gpct0_change(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int pcimio_gpct1_change(comedi_device * dev, comedi_subdevice * s,
++static int pcimio_gpct1_change(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned long new_size)
+ {
+ 	int ret;
+@@ -1775,7 +1775,7 @@ static int pcimio_gpct1_change(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int pcimio_dio_change(comedi_device * dev, comedi_subdevice * s,
++static int pcimio_dio_change(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned long new_size)
+ {
+ 	int ret;
+diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h
+index d76ef024131d..2c0929147585 100644
+--- a/drivers/staging/comedi/drivers/ni_stc.h
++++ b/drivers/staging/comedi/drivers/ni_stc.h
+@@ -1411,10 +1411,10 @@ typedef struct ni_board_struct {
+ #define NUM_GPCT 2
+ 
+ #define NI_PRIVATE_COMMON					\
+-	uint16_t (*stc_readw)(comedi_device *dev, int register);	\
+-	uint32_t (*stc_readl)(comedi_device *dev, int register);	\
+-	void (*stc_writew)(comedi_device *dev, uint16_t value, int register);	\
+-	void (*stc_writel)(comedi_device *dev, uint32_t value, int register);	\
++	uint16_t (*stc_readw)(struct comedi_device *dev, int register);	\
++	uint32_t (*stc_readl)(struct comedi_device *dev, int register);	\
++	void (*stc_writew)(struct comedi_device *dev, uint16_t value, int register);	\
++	void (*stc_writel)(struct comedi_device *dev, uint32_t value, int register);	\
+ 	\
+ 	unsigned short dio_output;				\
+ 	unsigned short dio_control;				\
+diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c
+index efa9cf5546f5..f5385b903d41 100644
+--- a/drivers/staging/comedi/drivers/ni_tio.c
++++ b/drivers/staging/comedi/drivers/ni_tio.c
+@@ -278,7 +278,7 @@ static void __exit ni_tio_cleanup_module(void)
+ 
+ module_exit(ni_tio_cleanup_module);
+ 
+-struct ni_gpct_device *ni_gpct_device_construct(comedi_device * dev,
++struct ni_gpct_device *ni_gpct_device_construct(struct comedi_device * dev,
+ 	void (*write_register) (struct ni_gpct * counter, unsigned bits,
+ 		enum ni_gpct_register reg),
+ 	unsigned (*read_register) (struct ni_gpct * counter,
+diff --git a/drivers/staging/comedi/drivers/ni_tio.h b/drivers/staging/comedi/drivers/ni_tio.h
+index 39f85ec8485b..eb611e1fb34b 100644
+--- a/drivers/staging/comedi/drivers/ni_tio.h
++++ b/drivers/staging/comedi/drivers/ni_tio.h
+@@ -119,7 +119,7 @@ struct ni_gpct {
+ };
+ 
+ struct ni_gpct_device {
+-	comedi_device *dev;
++	struct comedi_device *dev;
+ 	void (*write_register) (struct ni_gpct * counter, unsigned bits,
+ 		enum ni_gpct_register reg);
+ 	unsigned (*read_register) (struct ni_gpct * counter,
+@@ -131,7 +131,7 @@ struct ni_gpct_device {
+ 	spinlock_t regs_lock;
+ };
+ 
+-extern struct ni_gpct_device *ni_gpct_device_construct(comedi_device * dev,
++extern struct ni_gpct_device *ni_gpct_device_construct(struct comedi_device * dev,
+ 	void (*write_register) (struct ni_gpct * counter, unsigned bits,
+ 		enum ni_gpct_register reg),
+ 	unsigned (*read_register) (struct ni_gpct * counter,
+diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c
+index e4cc5c59f0c5..e28bc754f672 100644
+--- a/drivers/staging/comedi/drivers/ni_tiocmd.c
++++ b/drivers/staging/comedi/drivers/ni_tiocmd.c
+@@ -96,7 +96,7 @@ static void ni_tio_configure_dma(struct ni_gpct *counter, short enable,
+ 	}
+ }
+ 
+-static int ni_tio_input_inttrig(comedi_device * dev, comedi_subdevice * s,
++static int ni_tio_input_inttrig(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int trignum)
+ {
+ 	unsigned long flags;
+diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c
+index d54e55fe963f..6542b6fd06f2 100644
+--- a/drivers/staging/comedi/drivers/pcl711.c
++++ b/drivers/staging/comedi/drivers/pcl711.c
+@@ -154,8 +154,8 @@ static const boardtype boardtypes[] = {
+ #define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+ #define this_board ((const boardtype *)dev->board_ptr)
+ 
+-static int pcl711_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pcl711_detach(comedi_device * dev);
++static int pcl711_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcl711_detach(struct comedi_device * dev);
+ static comedi_driver driver_pcl711 = {
+       driver_name:"pcl711",
+       module:THIS_MODULE,
+@@ -185,7 +185,7 @@ static irqreturn_t pcl711_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	int lo, hi;
+ 	int data;
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s = dev->subdevices + 0;
+ 
+ 	if (!dev->attached) {
+@@ -213,7 +213,7 @@ static irqreturn_t pcl711_interrupt(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static void pcl711_set_changain(comedi_device * dev, int chan)
++static void pcl711_set_changain(struct comedi_device * dev, int chan)
+ {
+ 	int chan_register;
+ 
+@@ -240,7 +240,7 @@ static void pcl711_set_changain(comedi_device * dev, int chan)
+ 	}
+ }
+ 
+-static int pcl711_ai_insn(comedi_device * dev, comedi_subdevice * s,
++static int pcl711_ai_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+@@ -279,7 +279,7 @@ static int pcl711_ai_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int pcl711_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int pcl711_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int tmp;
+@@ -381,7 +381,7 @@ static int pcl711_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int pcl711_ai_cmd(comedi_device * dev, comedi_subdevice * s)
++static int pcl711_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	int timer1, timer2;
+ 	comedi_cmd *cmd = &s->async->cmd;
+@@ -427,7 +427,7 @@ static int pcl711_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ /*
+    analog output
+ */
+-static int pcl711_ao_insn(comedi_device * dev, comedi_subdevice * s,
++static int pcl711_ao_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -445,7 +445,7 @@ static int pcl711_ao_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int pcl711_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int pcl711_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -460,7 +460,7 @@ static int pcl711_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ /* Digital port read - Untested on 8112 */
+-static int pcl711_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int pcl711_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -473,7 +473,7 @@ static int pcl711_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ /* Digital port write - Untested on 8112 */
+-static int pcl711_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int pcl711_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -494,7 +494,7 @@ static int pcl711_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ /*  Free any resources that we have claimed  */
+-static int pcl711_detach(comedi_device * dev)
++static int pcl711_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: pcl711: remove\n", dev->minor);
+ 
+@@ -508,7 +508,7 @@ static int pcl711_detach(comedi_device * dev)
+ }
+ 
+ /*  Initialization */
+-static int pcl711_attach(comedi_device * dev, comedi_devconfig * it)
++static int pcl711_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int ret;
+ 	unsigned long iobase;
+diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c
+index 047bebbb4a07..a65bcfb1043b 100644
+--- a/drivers/staging/comedi/drivers/pcl724.c
++++ b/drivers/staging/comedi/drivers/pcl724.c
+@@ -56,8 +56,8 @@ See the source for configuration details.
+ 
+ // #define PCL724_IRQ   1  /* no IRQ support now */
+ 
+-static int pcl724_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pcl724_detach(comedi_device * dev);
++static int pcl724_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcl724_detach(struct comedi_device * dev);
+ 
+ typedef struct {
+ 	const char *name;	// board name
+@@ -122,7 +122,7 @@ static int subdev_8255mapped_cb(int dir, int port, int data,
+ 	}
+ }
+ 
+-static int pcl724_attach(comedi_device * dev, comedi_devconfig * it)
++static int pcl724_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	unsigned long iobase;
+ 	unsigned int iorange;
+@@ -198,7 +198,7 @@ static int pcl724_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int pcl724_detach(comedi_device * dev)
++static int pcl724_detach(struct comedi_device * dev)
+ {
+ 	int i;
+ 
+diff --git a/drivers/staging/comedi/drivers/pcl725.c b/drivers/staging/comedi/drivers/pcl725.c
+index a252defade5b..afe51b7f4ef1 100644
+--- a/drivers/staging/comedi/drivers/pcl725.c
++++ b/drivers/staging/comedi/drivers/pcl725.c
+@@ -20,8 +20,8 @@ Devices: [Advantech] PCL-725 (pcl725)
+ #define PCL725_DO 0
+ #define PCL725_DI 1
+ 
+-static int pcl725_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pcl725_detach(comedi_device * dev);
++static int pcl725_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcl725_detach(struct comedi_device * dev);
+ static comedi_driver driver_pcl725 = {
+       driver_name:"pcl725",
+       module:THIS_MODULE,
+@@ -31,7 +31,7 @@ static comedi_driver driver_pcl725 = {
+ 
+ COMEDI_INITCLEANUP(driver_pcl725);
+ 
+-static int pcl725_do_insn(comedi_device * dev, comedi_subdevice * s,
++static int pcl725_do_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -48,7 +48,7 @@ static int pcl725_do_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int pcl725_di_insn(comedi_device * dev, comedi_subdevice * s,
++static int pcl725_di_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -59,7 +59,7 @@ static int pcl725_di_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int pcl725_attach(comedi_device * dev, comedi_devconfig * it)
++static int pcl725_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	unsigned long iobase;
+@@ -100,7 +100,7 @@ static int pcl725_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int pcl725_detach(comedi_device * dev)
++static int pcl725_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: pcl725: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c
+index 61097184e3cc..373c1a7f2368 100644
+--- a/drivers/staging/comedi/drivers/pcl726.c
++++ b/drivers/staging/comedi/drivers/pcl726.c
+@@ -111,8 +111,8 @@ static const comedi_lrange *const rangelist_728[] = {
+ 	&range_4_20mA, &range_0_20mA
+ };
+ 
+-static int pcl726_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pcl726_detach(comedi_device * dev);
++static int pcl726_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcl726_detach(struct comedi_device * dev);
+ 
+ typedef struct {
+ 	const char *name;	// driver name
+@@ -168,7 +168,7 @@ typedef struct {
+ } pcl726_private;
+ #define devpriv ((pcl726_private *)dev->private)
+ 
+-static int pcl726_ao_insn(comedi_device * dev, comedi_subdevice * s,
++static int pcl726_ao_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int hi, lo;
+@@ -193,7 +193,7 @@ static int pcl726_ao_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int pcl726_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int pcl726_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -205,7 +205,7 @@ static int pcl726_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int pcl726_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int pcl726_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -217,7 +217,7 @@ static int pcl726_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int pcl726_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int pcl726_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -237,7 +237,7 @@ static int pcl726_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int pcl726_attach(comedi_device * dev, comedi_devconfig * it)
++static int pcl726_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	unsigned long iobase;
+@@ -356,7 +356,7 @@ static int pcl726_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int pcl726_detach(comedi_device * dev)
++static int pcl726_detach(struct comedi_device * dev)
+ {
+ //      printk("comedi%d: pcl726: remove\n",dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c
+index a33ff0850c48..63f38738c47a 100644
+--- a/drivers/staging/comedi/drivers/pcl730.c
++++ b/drivers/staging/comedi/drivers/pcl730.c
+@@ -26,8 +26,8 @@ The ACL-7130 card have an 8254 timer/counter not supported by this driver.
+ #define PCL730_DIO_LO	2	/* TTL Digital I/O low byte (D0-D7) */
+ #define PCL730_DIO_HI	3	/* TTL Digital I/O high byte (D8-D15) */
+ 
+-static int pcl730_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pcl730_detach(comedi_device * dev);
++static int pcl730_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcl730_detach(struct comedi_device * dev);
+ 
+ typedef struct {
+ 	const char *name;	// board name
+@@ -55,7 +55,7 @@ static comedi_driver driver_pcl730 = {
+ 
+ COMEDI_INITCLEANUP(driver_pcl730);
+ 
+-static int pcl730_do_insn(comedi_device * dev, comedi_subdevice * s,
++static int pcl730_do_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -77,7 +77,7 @@ static int pcl730_do_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int pcl730_di_insn(comedi_device * dev, comedi_subdevice * s,
++static int pcl730_di_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -89,7 +89,7 @@ static int pcl730_di_insn(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int pcl730_attach(comedi_device * dev, comedi_devconfig * it)
++static int pcl730_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	unsigned long iobase;
+@@ -155,7 +155,7 @@ static int pcl730_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int pcl730_detach(comedi_device * dev)
++static int pcl730_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: pcl730: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
+index b3d24cb588a0..0c8e03d66594 100644
+--- a/drivers/staging/comedi/drivers/pcl812.c
++++ b/drivers/staging/comedi/drivers/pcl812.c
+@@ -292,8 +292,8 @@ static const comedi_lrange range_a821pgh_ai = { 4, {
+ 	}
+ };
+ 
+-static int pcl812_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pcl812_detach(comedi_device * dev);
++static int pcl812_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcl812_detach(struct comedi_device * dev);
+ 
+ typedef struct {
+ 	const char *name;	// board name
+@@ -425,15 +425,15 @@ typedef struct {
+ /*
+ ==============================================================================
+ */
+-static void start_pacer(comedi_device * dev, int mode, unsigned int divisor1,
++static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
+ 	unsigned int divisor2);
+-static void setup_range_channel(comedi_device * dev, comedi_subdevice * s,
++static void setup_range_channel(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int rangechan, char wait);
+-static int pcl812_ai_cancel(comedi_device * dev, comedi_subdevice * s);
++static int pcl812_ai_cancel(struct comedi_device * dev, comedi_subdevice * s);
+ /*
+ ==============================================================================
+ */
+-static int pcl812_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int pcl812_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -467,7 +467,7 @@ static int pcl812_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int acl8216_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int acl8216_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -503,7 +503,7 @@ static int acl8216_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pcl812_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
++static int pcl812_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -523,7 +523,7 @@ static int pcl812_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pcl812_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int pcl812_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -539,7 +539,7 @@ static int pcl812_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pcl812_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int pcl812_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -554,7 +554,7 @@ static int pcl812_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pcl812_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int pcl812_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -591,7 +591,7 @@ static void pcl812_cmdtest_out(int e, comedi_cmd * cmd)
+ /*
+ ==============================================================================
+ */
+-static int pcl812_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int pcl812_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -770,7 +770,7 @@ static int pcl812_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int pcl812_ai_cmd(comedi_device * dev, comedi_subdevice * s)
++static int pcl812_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	unsigned int divisor1 = 0, divisor2 = 0, i, dma_flags, bytes;
+ 	comedi_cmd *cmd = &s->async->cmd;
+@@ -922,7 +922,7 @@ static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d)
+ {
+ 	char err = 1;
+ 	unsigned int mask, timeout;
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s = dev->subdevices + 0;
+ 
+ 	s->async->events = 0;
+@@ -980,7 +980,7 @@ static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d)
+ /*
+ ==============================================================================
+ */
+-static void transfer_from_dma_buf(comedi_device * dev, comedi_subdevice * s,
++static void transfer_from_dma_buf(struct comedi_device * dev, comedi_subdevice * s,
+ 	short * ptr, unsigned int bufptr, unsigned int len)
+ {
+ 	unsigned int i;
+@@ -1008,7 +1008,7 @@ static void transfer_from_dma_buf(comedi_device * dev, comedi_subdevice * s,
+ */
+ static irqreturn_t interrupt_pcl812_ai_dma(int irq, void *d)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s = dev->subdevices + 0;
+ 	unsigned long dma_flags;
+ 	int len, bufptr;
+@@ -1059,7 +1059,7 @@ static irqreturn_t interrupt_pcl812_ai_dma(int irq, void *d)
+ */
+ static irqreturn_t interrupt_pcl812(int irq, void *d PT_REGS_ARG)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 
+ 	if (!dev->attached) {
+ 		comedi_error(dev, "spurious interrupt");
+@@ -1075,7 +1075,7 @@ static irqreturn_t interrupt_pcl812(int irq, void *d PT_REGS_ARG)
+ /*
+ ==============================================================================
+ */
+-static int pcl812_ai_poll(comedi_device * dev, comedi_subdevice * s)
++static int pcl812_ai_poll(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+ 	unsigned int top1, top2, i;
+@@ -1119,7 +1119,7 @@ static int pcl812_ai_poll(comedi_device * dev, comedi_subdevice * s)
+ /*
+ ==============================================================================
+ */
+-static void setup_range_channel(comedi_device * dev, comedi_subdevice * s,
++static void setup_range_channel(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int rangechan, char wait)
+ {
+ 	unsigned char chan_reg = CR_CHAN(rangechan);	// normal board
+@@ -1155,7 +1155,7 @@ static void setup_range_channel(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static void start_pacer(comedi_device * dev, int mode, unsigned int divisor1,
++static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
+ 	unsigned int divisor2)
+ {
+ #ifdef PCL812_EXTDEBUG
+@@ -1180,7 +1180,7 @@ static void start_pacer(comedi_device * dev, int mode, unsigned int divisor1,
+ /*
+ ==============================================================================
+ */
+-static void free_resources(comedi_device * dev)
++static void free_resources(struct comedi_device * dev)
+ {
+ 
+ 	if (dev->private) {
+@@ -1200,7 +1200,7 @@ static void free_resources(comedi_device * dev)
+ /*
+ ==============================================================================
+ */
+-static int pcl812_ai_cancel(comedi_device * dev, comedi_subdevice * s)
++static int pcl812_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ #ifdef PCL812_EXTDEBUG
+ 	rt_printk("pcl812 EDBG: BGN: pcl812_ai_cancel(...)\n");
+@@ -1220,7 +1220,7 @@ static int pcl812_ai_cancel(comedi_device * dev, comedi_subdevice * s)
+ /*
+ ==============================================================================
+ */
+-static void pcl812_reset(comedi_device * dev)
++static void pcl812_reset(struct comedi_device * dev)
+ {
+ #ifdef PCL812_EXTDEBUG
+ 	rt_printk("pcl812 EDBG: BGN: pcl812_reset(...)\n");
+@@ -1262,7 +1262,7 @@ static void pcl812_reset(comedi_device * dev)
+ /*
+ ==============================================================================
+ */
+-static int pcl812_attach(comedi_device * dev, comedi_devconfig * it)
++static int pcl812_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int ret, subdev;
+ 	unsigned long iobase;
+@@ -1590,7 +1590,7 @@ static int pcl812_attach(comedi_device * dev, comedi_devconfig * it)
+ /*
+ ==============================================================================
+  */
+-static int pcl812_detach(comedi_device * dev)
++static int pcl812_detach(struct comedi_device * dev)
+ {
+ 
+ #ifdef PCL812_EXTDEBUG
+diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
+index cb795736300d..5d8509f45a08 100644
+--- a/drivers/staging/comedi/drivers/pcl816.c
++++ b/drivers/staging/comedi/drivers/pcl816.c
+@@ -146,8 +146,8 @@ static const boardtype boardtypes[] = {
+ #define devpriv ((pcl816_private *)dev->private)
+ #define this_board ((const boardtype *)dev->board_ptr)
+ 
+-static int pcl816_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pcl816_detach(comedi_device * dev);
++static int pcl816_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcl816_detach(struct comedi_device * dev);
+ 
+ #ifdef unused
+ static int RTC_lock = 0;	/* RTC lock */
+@@ -209,24 +209,24 @@ typedef struct {
+ /*
+ ==============================================================================
+ */
+-static int check_and_setup_channel_list(comedi_device * dev,
++static int check_and_setup_channel_list(struct comedi_device * dev,
+ 	comedi_subdevice * s, unsigned int *chanlist, int chanlen);
+-static int pcl816_ai_cancel(comedi_device * dev, comedi_subdevice * s);
+-static void start_pacer(comedi_device * dev, int mode, unsigned int divisor1,
++static int pcl816_ai_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
+ 	unsigned int divisor2);
+ #ifdef unused
+ static int set_rtc_irq_bit(unsigned char bit);
+ #endif
+ 
+-static int pcl816_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int pcl816_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+-static int pcl816_ai_cmd(comedi_device * dev, comedi_subdevice * s);
++static int pcl816_ai_cmd(struct comedi_device * dev, comedi_subdevice * s);
+ 
+ /*
+ ==============================================================================
+    ANALOG INPUT MODE0, 816 cards, slow version
+ */
+-static int pcl816_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int pcl816_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -280,7 +280,7 @@ static int pcl816_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+ */
+ static irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s = dev->subdevices + 0;
+ 	int low, hi;
+ 	int timeout = 50;	/* wait max 50us */
+@@ -330,7 +330,7 @@ static irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d)
+ ==============================================================================
+    analog input dma mode 1 & 3, 816 cards
+ */
+-static void transfer_from_dma_buf(comedi_device * dev, comedi_subdevice * s,
++static void transfer_from_dma_buf(struct comedi_device * dev, comedi_subdevice * s,
+ 	short * ptr, unsigned int bufptr, unsigned int len)
+ {
+ 	int i;
+@@ -361,7 +361,7 @@ static void transfer_from_dma_buf(comedi_device * dev, comedi_subdevice * s,
+ 
+ static irqreturn_t interrupt_pcl816_ai_mode13_dma(int irq, void *d)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s = dev->subdevices + 0;
+ 	int len, bufptr, this_dma_buf;
+ 	unsigned long dma_flags;
+@@ -407,7 +407,7 @@ static irqreturn_t interrupt_pcl816_ai_mode13_dma(int irq, void *d)
+ */
+ static irqreturn_t interrupt_pcl816(int irq, void *d PT_REGS_ARG)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	DPRINTK("");
+ 
+ 	if (!dev->attached) {
+@@ -458,7 +458,7 @@ static void pcl816_cmdtest_out(int e, comedi_cmd * cmd)
+ /*
+ ==============================================================================
+ */
+-static int pcl816_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int pcl816_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -593,7 +593,7 @@ static int pcl816_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int pcl816_ai_cmd(comedi_device * dev, comedi_subdevice * s)
++static int pcl816_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	unsigned int divisor1 = 0, divisor2 = 0, dma_flags, bytes, dmairq;
+ 	comedi_cmd *cmd = &s->async->cmd;
+@@ -698,7 +698,7 @@ static int pcl816_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int pcl816_ai_poll(comedi_device * dev, comedi_subdevice * s)
++static int pcl816_ai_poll(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+ 	unsigned int top1, top2, i;
+@@ -741,7 +741,7 @@ static int pcl816_ai_poll(comedi_device * dev, comedi_subdevice * s)
+ ==============================================================================
+  cancel any mode 1-4 AI
+ */
+-static int pcl816_ai_cancel(comedi_device * dev, comedi_subdevice * s)
++static int pcl816_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ //  DEBUG(rt_printk("pcl816_ai_cancel()\n");)
+ 
+@@ -809,7 +809,7 @@ static int pcl816_check(unsigned long iobase)
+ ==============================================================================
+  reset whole PCL-816 cards
+ */
+-static void pcl816_reset(comedi_device * dev)
++static void pcl816_reset(struct comedi_device * dev)
+ {
+ //  outb (0, dev->iobase + PCL818_DA_LO);       // DAC=0V
+ //  outb (0, dev->iobase + PCL818_DA_HI);
+@@ -831,7 +831,7 @@ static void pcl816_reset(comedi_device * dev)
+  Start/stop pacer onboard pacer
+ */
+ static void
+-start_pacer(comedi_device * dev, int mode, unsigned int divisor1,
++start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
+ 	unsigned int divisor2)
+ {
+ 	outb(0x32, dev->iobase + PCL816_CTRCTL);
+@@ -861,7 +861,7 @@ start_pacer(comedi_device * dev, int mode, unsigned int divisor1,
+  If it's ok, then program scan/gain logic
+ */
+ static int
+-check_and_setup_channel_list(comedi_device * dev, comedi_subdevice * s,
++check_and_setup_channel_list(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int *chanlist, int chanlen)
+ {
+ 	unsigned int chansegment[16];
+@@ -975,7 +975,7 @@ static int set_rtc_irq_bit(unsigned char bit)
+ ==============================================================================
+   Free any resources that we have claimed
+ */
+-static void free_resources(comedi_device * dev)
++static void free_resources(struct comedi_device * dev)
+ {
+ 	//rt_printk("free_resource()\n");
+ 	if (dev->private) {
+@@ -1011,7 +1011,7 @@ static void free_resources(comedi_device * dev)
+    Initialization
+ 
+ */
+-static int pcl816_attach(comedi_device * dev, comedi_devconfig * it)
++static int pcl816_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int ret;
+ 	unsigned long iobase;
+@@ -1234,7 +1234,7 @@ case COMEDI_SUBD_DO:
+ ==============================================================================
+   Removes device
+  */
+-static int pcl816_detach(comedi_device * dev)
++static int pcl816_detach(struct comedi_device * dev)
+ {
+ 	DEBUG(rt_printk("comedi%d: pcl816: remove\n", dev->minor);
+ 		)
+diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
+index 5425c196bed1..156788916b50 100644
+--- a/drivers/staging/comedi/drivers/pcl818.c
++++ b/drivers/staging/comedi/drivers/pcl818.c
+@@ -244,8 +244,8 @@ static const comedi_lrange range718_bipolar0_5 = { 1, {BIP_RANGE(0.5),} };
+ static const comedi_lrange range718_unipolar2 = { 1, {UNI_RANGE(2),} };
+ static const comedi_lrange range718_unipolar1 = { 1, {BIP_RANGE(1),} };
+ 
+-static int pcl818_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pcl818_detach(comedi_device * dev);
++static int pcl818_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcl818_detach(struct comedi_device * dev);
+ 
+ #ifdef unused
+ static int RTC_lock = 0;	/* RTC lock */
+@@ -368,13 +368,13 @@ static const unsigned int muxonechan[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0
+ /*
+ ==============================================================================
+ */
+-static void setup_channel_list(comedi_device * dev, comedi_subdevice * s,
++static void setup_channel_list(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int *chanlist, unsigned int n_chan, unsigned int seglen);
+-static int check_channel_list(comedi_device * dev, comedi_subdevice * s,
++static int check_channel_list(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int *chanlist, unsigned int n_chan);
+ 
+-static int pcl818_ai_cancel(comedi_device * dev, comedi_subdevice * s);
+-static void start_pacer(comedi_device * dev, int mode, unsigned int divisor1,
++static int pcl818_ai_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
+ 	unsigned int divisor2);
+ 
+ #ifdef unused
+@@ -387,7 +387,7 @@ static int rtc_setfreq_irq(int freq);
+ ==============================================================================
+    ANALOG INPUT MODE0, 818 cards, slow version
+ */
+-static int pcl818_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int pcl818_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -434,7 +434,7 @@ static int pcl818_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+    ANALOG OUTPUT MODE0, 818 cards
+    only one sample per call is supported
+ */
+-static int pcl818_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int pcl818_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -447,7 +447,7 @@ static int pcl818_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int pcl818_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
++static int pcl818_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -470,7 +470,7 @@ static int pcl818_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+ 
+    only one sample per call is supported
+ */
+-static int pcl818_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int pcl818_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -488,7 +488,7 @@ static int pcl818_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 
+    only one sample per call is supported
+ */
+-static int pcl818_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int pcl818_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -512,7 +512,7 @@ static int pcl818_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ */
+ static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s = dev->subdevices + 0;
+ 	int low;
+ 	int timeout = 50;	/* wait max 50us */
+@@ -565,7 +565,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d)
+ */
+ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s = dev->subdevices + 0;
+ 	int i, len, bufptr;
+ 	unsigned long flags;
+@@ -640,7 +640,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
+ */
+ static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s = dev->subdevices + 0;
+ 	unsigned long tmp;
+ 	unsigned int top1, top2, i, bufptr;
+@@ -738,7 +738,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d)
+ */
+ static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s = dev->subdevices + 0;
+ 	int i, len, lo;
+ 
+@@ -808,7 +808,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
+ */
+ static irqreturn_t interrupt_pcl818(int irq, void *d PT_REGS_ARG)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 
+ 	if (!dev->attached) {
+ 		comedi_error(dev, "premature interrupt");
+@@ -870,7 +870,7 @@ static irqreturn_t interrupt_pcl818(int irq, void *d PT_REGS_ARG)
+ ==============================================================================
+    ANALOG INPUT MODE 1 or 3 DMA , 818 cards
+ */
+-static void pcl818_ai_mode13dma_int(int mode, comedi_device * dev,
++static void pcl818_ai_mode13dma_int(int mode, struct comedi_device * dev,
+ 	comedi_subdevice * s)
+ {
+ 	unsigned int flags;
+@@ -911,7 +911,7 @@ static void pcl818_ai_mode13dma_int(int mode, comedi_device * dev,
+ ==============================================================================
+    ANALOG INPUT MODE 1 or 3 DMA rtc, 818 cards
+ */
+-static void pcl818_ai_mode13dma_rtc(int mode, comedi_device * dev,
++static void pcl818_ai_mode13dma_rtc(int mode, struct comedi_device * dev,
+ 	comedi_subdevice * s)
+ {
+ 	unsigned int flags;
+@@ -952,7 +952,7 @@ static void pcl818_ai_mode13dma_rtc(int mode, comedi_device * dev,
+ ==============================================================================
+    ANALOG INPUT MODE 1 or 3, 818 cards
+ */
+-static int pcl818_ai_cmd_mode(int mode, comedi_device * dev,
++static int pcl818_ai_cmd_mode(int mode, struct comedi_device * dev,
+ 	comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+@@ -1063,7 +1063,7 @@ static int pcl818_ai_cmd_mode(int mode, comedi_device * dev,
+    ANALOG OUTPUT MODE 1 or 3, 818 cards
+ */
+ #ifdef PCL818_MODE13_AO
+-static int pcl818_ao_mode13(int mode, comedi_device * dev, comedi_subdevice * s,
++static int pcl818_ao_mode13(int mode, struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_trig * it)
+ {
+ 	int divisor1, divisor2;
+@@ -1116,7 +1116,7 @@ static int pcl818_ao_mode13(int mode, comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+    ANALOG OUTPUT MODE 1, 818 cards
+ */
+-static int pcl818_ao_mode1(comedi_device * dev, comedi_subdevice * s,
++static int pcl818_ao_mode1(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_trig * it)
+ {
+ 	return pcl818_ao_mode13(1, dev, s, it);
+@@ -1126,7 +1126,7 @@ static int pcl818_ao_mode1(comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+    ANALOG OUTPUT MODE 3, 818 cards
+ */
+-static int pcl818_ao_mode3(comedi_device * dev, comedi_subdevice * s,
++static int pcl818_ao_mode3(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_trig * it)
+ {
+ 	return pcl818_ao_mode13(3, dev, s, it);
+@@ -1138,7 +1138,7 @@ static int pcl818_ao_mode3(comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+  Start/stop pacer onboard pacer
+ */
+-static void start_pacer(comedi_device * dev, int mode, unsigned int divisor1,
++static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
+ 	unsigned int divisor2)
+ {
+ 	outb(0xb4, dev->iobase + PCL818_CTRCTL);
+@@ -1158,7 +1158,7 @@ static void start_pacer(comedi_device * dev, int mode, unsigned int divisor1,
+  Check if channel list from user is builded correctly
+  If it's ok, then program scan/gain logic
+ */
+-static int check_channel_list(comedi_device * dev, comedi_subdevice * s,
++static int check_channel_list(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int *chanlist, unsigned int n_chan)
+ {
+ 	unsigned int chansegment[16];
+@@ -1214,7 +1214,7 @@ static int check_channel_list(comedi_device * dev, comedi_subdevice * s,
+ 	return seglen;
+ }
+ 
+-static void setup_channel_list(comedi_device * dev, comedi_subdevice * s,
++static void setup_channel_list(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int *chanlist, unsigned int n_chan, unsigned int seglen)
+ {
+ 	int i;
+@@ -1251,7 +1251,7 @@ static int check_single_ended(unsigned int port)
+ /*
+ ==============================================================================
+ */
+-static int ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -1396,7 +1396,7 @@ static int ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ /*
+ ==============================================================================
+ */
+-static int ai_cmd(comedi_device * dev, comedi_subdevice * s)
++static int ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	int retval;
+@@ -1435,7 +1435,7 @@ static int ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ ==============================================================================
+  cancel any mode 1-4 AI
+ */
+-static int pcl818_ai_cancel(comedi_device * dev, comedi_subdevice * s)
++static int pcl818_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	if (devpriv->irq_blocked > 0) {
+ 		rt_printk("pcl818_ai_cancel()\n");
+@@ -1516,7 +1516,7 @@ static int pcl818_check(unsigned long iobase)
+ ==============================================================================
+  reset whole PCL-818 cards
+ */
+-static void pcl818_reset(comedi_device * dev)
++static void pcl818_reset(struct comedi_device * dev)
+ {
+ 	if (devpriv->usefifo) {	// FIFO shutdown
+ 		outb(0, dev->iobase + PCL818_FI_INTCLR);
+@@ -1586,7 +1586,7 @@ static int set_rtc_irq_bit(unsigned char bit)
+ */
+ static void rtc_dropped_irq(unsigned long data)
+ {
+-	comedi_device *dev = (void *)data;
++	struct comedi_device *dev = (void *)data;
+ 	unsigned long flags, tmp;
+ 
+ 	switch (devpriv->int818_mode) {
+@@ -1637,7 +1637,7 @@ static int rtc_setfreq_irq(int freq)
+ ==============================================================================
+   Free any resources that we have claimed
+ */
+-static void free_resources(comedi_device * dev)
++static void free_resources(struct comedi_device * dev)
+ {
+ 	//rt_printk("free_resource()\n");
+ 	if (dev->private) {
+@@ -1675,7 +1675,7 @@ static void free_resources(comedi_device * dev)
+    Initialization
+ 
+ */
+-static int pcl818_attach(comedi_device * dev, comedi_devconfig * it)
++static int pcl818_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int ret;
+ 	unsigned long iobase;
+@@ -1976,7 +1976,7 @@ static int pcl818_attach(comedi_device * dev, comedi_devconfig * it)
+ ==============================================================================
+   Removes device
+  */
+-static int pcl818_detach(comedi_device * dev)
++static int pcl818_detach(struct comedi_device * dev)
+ {
+ 	//  rt_printk("comedi%d: pcl818: remove\n", dev->minor);
+ 	free_resources(dev);
+diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c
+index c4458442d5be..aa4ecddcf2a1 100644
+--- a/drivers/staging/comedi/drivers/pcm3724.c
++++ b/drivers/staging/comedi/drivers/pcm3724.c
+@@ -62,8 +62,8 @@ Copy/pasted/hacked from pcm724.c
+ #define CR_A_MODE(a)	((a)<<5)
+ #define CR_CW		0x80
+ 
+-static int pcm3724_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pcm3724_detach(comedi_device * dev);
++static int pcm3724_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcm3724_detach(struct comedi_device * dev);
+ 
+ typedef struct {
+ 	const char *name;	// driver name
+@@ -142,7 +142,7 @@ static int compute_buffer(int config, int devno, comedi_subdevice * s)
+ 	return config;
+ }
+ 
+-static void do_3724_config(comedi_device * dev, comedi_subdevice * s,
++static void do_3724_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	int chanspec)
+ {
+ 	int config;
+@@ -176,7 +176,7 @@ static void do_3724_config(comedi_device * dev, comedi_subdevice * s,
+ 	outb(config, port_8255_cfg);
+ }
+ 
+-static void enable_chan(comedi_device * dev, comedi_subdevice * s, int chanspec)
++static void enable_chan(struct comedi_device * dev, comedi_subdevice * s, int chanspec)
+ {
+ 	unsigned int mask;
+ 	int gatecfg;
+@@ -214,7 +214,7 @@ static void enable_chan(comedi_device * dev, comedi_subdevice * s, int chanspec)
+ }
+ 
+ /* overriding the 8255 insn config */
+-static int subdev_3724_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int subdev_3724_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int mask;
+@@ -251,7 +251,7 @@ static int subdev_3724_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int pcm3724_attach(comedi_device * dev, comedi_devconfig * it)
++static int pcm3724_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	unsigned long iobase;
+ 	unsigned int iorange;
+@@ -289,7 +289,7 @@ static int pcm3724_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int pcm3724_detach(comedi_device * dev)
++static int pcm3724_detach(struct comedi_device * dev)
+ {
+ 	int i;
+ 
+diff --git a/drivers/staging/comedi/drivers/pcm3730.c b/drivers/staging/comedi/drivers/pcm3730.c
+index 1283be635ef8..c7d275f1fcbb 100644
+--- a/drivers/staging/comedi/drivers/pcm3730.c
++++ b/drivers/staging/comedi/drivers/pcm3730.c
+@@ -28,8 +28,8 @@ Configuration options:
+ #define PCM3730_DIB 2
+ #define PCM3730_DIC 3
+ 
+-static int pcm3730_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pcm3730_detach(comedi_device * dev);
++static int pcm3730_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcm3730_detach(struct comedi_device * dev);
+ static comedi_driver driver_pcm3730 = {
+       driver_name:"pcm3730",
+       module:THIS_MODULE,
+@@ -39,7 +39,7 @@ static comedi_driver driver_pcm3730 = {
+ 
+ COMEDI_INITCLEANUP(driver_pcm3730);
+ 
+-static int pcm3730_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int pcm3730_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -54,7 +54,7 @@ static int pcm3730_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int pcm3730_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int pcm3730_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -63,7 +63,7 @@ static int pcm3730_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int pcm3730_attach(comedi_device * dev, comedi_devconfig * it)
++static int pcm3730_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	unsigned long iobase;
+@@ -141,7 +141,7 @@ static int pcm3730_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int pcm3730_detach(comedi_device * dev)
++static int pcm3730_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: pcm3730: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c
+index 1a371da6f828..08fe79ab59f3 100644
+--- a/drivers/staging/comedi/drivers/pcmad.c
++++ b/drivers/staging/comedi/drivers/pcmad.c
+@@ -76,8 +76,8 @@ struct pcmad_priv_struct {
+ };
+ #define devpriv ((struct pcmad_priv_struct *)dev->private)
+ 
+-static int pcmad_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pcmad_detach(comedi_device * dev);
++static int pcmad_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcmad_detach(struct comedi_device * dev);
+ static comedi_driver driver_pcmad = {
+       driver_name:"pcmad",
+       module:THIS_MODULE,
+@@ -92,7 +92,7 @@ COMEDI_INITCLEANUP(driver_pcmad);
+ 
+ #define TIMEOUT	100
+ 
+-static int pcmad_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int pcmad_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -126,7 +126,7 @@ static int pcmad_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+  * 2	0=single ended 1=differential
+  * 3	0=straight binary 1=two's comp
+  */
+-static int pcmad_attach(comedi_device * dev, comedi_devconfig * it)
++static int pcmad_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int ret;
+ 	comedi_subdevice *s;
+@@ -159,7 +159,7 @@ static int pcmad_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int pcmad_detach(comedi_device * dev)
++static int pcmad_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: pcmad: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c
+index c8963cdf5a5f..6a3a22ed726f 100644
+--- a/drivers/staging/comedi/drivers/pcmda12.c
++++ b/drivers/staging/comedi/drivers/pcmda12.c
+@@ -105,10 +105,10 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pcmda12_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pcmda12_detach(comedi_device * dev);
++static int pcmda12_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcmda12_detach(struct comedi_device * dev);
+ 
+-static void zero_chans(comedi_device * dev);
++static void zero_chans(struct comedi_device * dev);
+ 
+ static comedi_driver driver = {
+       driver_name:"pcmda12",
+@@ -138,9 +138,9 @@ static comedi_driver driver = {
+       num_names:sizeof(pcmda12_boards) / sizeof(pcmda12_board),
+ };
+ 
+-static int ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ /*
+@@ -149,7 +149,7 @@ static int ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pcmda12_attach(comedi_device * dev, comedi_devconfig * it)
++static int pcmda12_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	unsigned long iobase;
+@@ -218,7 +218,7 @@ static int pcmda12_attach(comedi_device * dev, comedi_devconfig * it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int pcmda12_detach(comedi_device * dev)
++static int pcmda12_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: %s: remove\n", dev->minor, driver.driver_name);
+ 	if (dev->iobase)
+@@ -226,7 +226,7 @@ static int pcmda12_detach(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static void zero_chans(comedi_device * dev)
++static void zero_chans(struct comedi_device * dev)
+ {				/* sets up an
+ 				   ASIC chip to defaults */
+ 	int i;
+@@ -239,7 +239,7 @@ static void zero_chans(comedi_device * dev)
+ 	inb(LSB_PORT(0));	/* update chans. */
+ }
+ 
+-static int ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -281,7 +281,7 @@ static int ao_winsn(comedi_device * dev, comedi_subdevice * s,
+    DAC outputs, which makes all AO channels update simultaneously.
+    This is useful for some control applications, I would imagine.
+ */
+-static int ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
+index 739959cd2cfd..77f62cddddb3 100644
+--- a/drivers/staging/comedi/drivers/pcmmio.c
++++ b/drivers/staging/comedi/drivers/pcmmio.c
+@@ -139,14 +139,14 @@ Configuration Options:
+ #define PAGE_ENAB 2
+ #define PAGE_INT_ID 3
+ 
+-typedef int (*comedi_insn_fn_t) (comedi_device *, comedi_subdevice *,
++typedef int (*comedi_insn_fn_t) (struct comedi_device *, comedi_subdevice *,
+ 	comedi_insn *, unsigned int *);
+ 
+-static int ai_rinsn(comedi_device *, comedi_subdevice *, comedi_insn *,
++static int ai_rinsn(struct comedi_device *, comedi_subdevice *, comedi_insn *,
+ 	unsigned int *);
+-static int ao_rinsn(comedi_device *, comedi_subdevice *, comedi_insn *,
++static int ao_rinsn(struct comedi_device *, comedi_subdevice *, comedi_insn *,
+ 	unsigned int *);
+-static int ao_winsn(comedi_device *, comedi_subdevice *, comedi_insn *,
++static int ao_winsn(struct comedi_device *, comedi_subdevice *, comedi_insn *,
+ 	unsigned int *);
+ 
+ /*
+@@ -237,7 +237,7 @@ typedef struct {
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+-   feel free to suggest moving the variable to the comedi_device struct.  */
++   feel free to suggest moving the variable to the struct comedi_device struct.  */
+ typedef struct {
+ 	/* stuff for DIO */
+ 	struct {
+@@ -264,8 +264,8 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pcmmio_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pcmmio_detach(comedi_device * dev);
++static int pcmmio_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcmmio_detach(struct comedi_device * dev);
+ 
+ static comedi_driver driver = {
+       driver_name:"pcmmio",
+@@ -295,24 +295,24 @@ static comedi_driver driver = {
+       num_names:sizeof(pcmmio_boards) / sizeof(pcmmio_board),
+ };
+ 
+-static int pcmmio_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int pcmmio_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int pcmmio_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int pcmmio_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ static irqreturn_t interrupt_pcmmio(int irq, void *d PT_REGS_ARG);
+-static void pcmmio_stop_intr(comedi_device *, comedi_subdevice *);
+-static int pcmmio_cancel(comedi_device * dev, comedi_subdevice * s);
+-static int pcmmio_cmd(comedi_device * dev, comedi_subdevice * s);
+-static int pcmmio_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static void pcmmio_stop_intr(struct comedi_device *, comedi_subdevice *);
++static int pcmmio_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static int pcmmio_cmd(struct comedi_device * dev, comedi_subdevice * s);
++static int pcmmio_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+ 
+ /* some helper functions to deal with specifics of this device's registers */
+-static void init_asics(comedi_device * dev);	/* sets up/clears ASIC chips to defaults */
+-static void switch_page(comedi_device * dev, int asic, int page);
++static void init_asics(struct comedi_device * dev);	/* sets up/clears ASIC chips to defaults */
++static void switch_page(struct comedi_device * dev, int asic, int page);
+ #ifdef notused
+-static void lock_port(comedi_device * dev, int asic, int port);
+-static void unlock_port(comedi_device * dev, int asic, int port);
++static void lock_port(struct comedi_device * dev, int asic, int port);
++static void unlock_port(struct comedi_device * dev, int asic, int port);
+ #endif
+ 
+ /*
+@@ -321,7 +321,7 @@ static void unlock_port(comedi_device * dev, int asic, int port);
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pcmmio_attach(comedi_device * dev, comedi_devconfig * it)
++static int pcmmio_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	int sdev_no, chans_left, n_dio_subdevs, n_subdevs, port, asic,
+@@ -526,7 +526,7 @@ static int pcmmio_attach(comedi_device * dev, comedi_devconfig * it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int pcmmio_detach(comedi_device * dev)
++static int pcmmio_detach(struct comedi_device * dev)
+ {
+ 	int i;
+ 
+@@ -550,7 +550,7 @@ static int pcmmio_detach(comedi_device * dev)
+  * useful to applications if you implement the insn_bits interface.
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+-static int pcmmio_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int pcmmio_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int byte_no;
+@@ -624,7 +624,7 @@ static int pcmmio_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+  * configured by a special insn_config instruction.  chanspec
+  * contains the channel to be changed, and data[0] contains the
+  * value COMEDI_INPUT or COMEDI_OUTPUT. */
+-static int pcmmio_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int pcmmio_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec), byte_no = chan / 8, bit_no =
+@@ -685,7 +685,7 @@ static int pcmmio_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 	return insn->n;
+ }
+ 
+-static void init_asics(comedi_device * dev)
++static void init_asics(struct comedi_device * dev)
+ {				/* sets up an
+ 				   ASIC chip to defaults */
+ 	int asic;
+@@ -722,7 +722,7 @@ static void init_asics(comedi_device * dev)
+ 	}
+ }
+ 
+-static void switch_page(comedi_device * dev, int asic, int page)
++static void switch_page(struct comedi_device * dev, int asic, int page)
+ {
+ 	if (asic < 0 || asic >= thisboard->dio_num_asics)
+ 		return;		/* paranoia */
+@@ -738,7 +738,7 @@ static void switch_page(comedi_device * dev, int asic, int page)
+ }
+ 
+ #ifdef notused
+-static void lock_port(comedi_device * dev, int asic, int port)
++static void lock_port(struct comedi_device * dev, int asic, int port)
+ {
+ 	if (asic < 0 || asic >= thisboard->dio_num_asics)
+ 		return;		/* paranoia */
+@@ -752,7 +752,7 @@ static void lock_port(comedi_device * dev, int asic, int port)
+ 	return;
+ }
+ 
+-static void unlock_port(comedi_device * dev, int asic, int port)
++static void unlock_port(struct comedi_device * dev, int asic, int port)
+ {
+ 	if (asic < 0 || asic >= thisboard->dio_num_asics)
+ 		return;		/* paranoia */
+@@ -768,7 +768,7 @@ static void unlock_port(comedi_device * dev, int asic, int port)
+ static irqreturn_t interrupt_pcmmio(int irq, void *d PT_REGS_ARG)
+ {
+ 	int asic, got1 = 0;
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 
+ 	for (asic = 0; asic < MAX_ASICS; ++asic) {
+ 		if (irq == devpriv->asics[asic].irq) {
+@@ -917,7 +917,7 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static void pcmmio_stop_intr(comedi_device * dev, comedi_subdevice * s)
++static void pcmmio_stop_intr(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	int nports, firstport, asic, port;
+ 
+@@ -936,7 +936,7 @@ static void pcmmio_stop_intr(comedi_device * dev, comedi_subdevice * s)
+ 	}
+ }
+ 
+-static int pcmmio_start_intr(comedi_device * dev, comedi_subdevice * s)
++static int pcmmio_start_intr(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	if (!subpriv->dio.intr.continuous && subpriv->dio.intr.stop_count == 0) {
+ 		/* An empty acquisition! */
+@@ -995,7 +995,7 @@ static int pcmmio_start_intr(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int pcmmio_cancel(comedi_device * dev, comedi_subdevice * s)
++static int pcmmio_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+ 
+@@ -1011,7 +1011,7 @@ static int pcmmio_cancel(comedi_device * dev, comedi_subdevice * s)
+  * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
+  */
+ static int
+-pcmmio_inttrig_start_intr(comedi_device * dev, comedi_subdevice * s,
++pcmmio_inttrig_start_intr(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int trignum)
+ {
+ 	unsigned long flags;
+@@ -1037,7 +1037,7 @@ pcmmio_inttrig_start_intr(comedi_device * dev, comedi_subdevice * s,
+ /*
+  * 'do_cmd' function for an 'INTERRUPT' subdevice.
+  */
+-static int pcmmio_cmd(comedi_device * dev, comedi_subdevice * s)
++static int pcmmio_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned long flags;
+@@ -1082,7 +1082,7 @@ static int pcmmio_cmd(comedi_device * dev, comedi_subdevice * s)
+  * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
+  */
+ static int
+-pcmmio_cmdtest(comedi_device * dev, comedi_subdevice * s, comedi_cmd * cmd)
++pcmmio_cmdtest(struct comedi_device * dev, comedi_subdevice * s, comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	unsigned int tmp;
+@@ -1194,7 +1194,7 @@ static int adc_wait_ready(unsigned long iobase)
+ }
+ 
+ /* All this is for AI and AO */
+-static int ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -1258,7 +1258,7 @@ static int ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -1288,7 +1288,7 @@ static int wait_dac_ready(unsigned long iobase)
+ 	return 1;
+ }
+ 
+-static int ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
+index f40f91987e30..d2af7082c1e8 100644
+--- a/drivers/staging/comedi/drivers/pcmuio.c
++++ b/drivers/staging/comedi/drivers/pcmuio.c
+@@ -196,7 +196,7 @@ typedef struct {
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+-   feel free to suggest moving the variable to the comedi_device struct.  */
++   feel free to suggest moving the variable to the struct comedi_device struct.  */
+ typedef struct {
+ 	struct {
+ 		unsigned char pagelock;	/* current page and lock */
+@@ -222,8 +222,8 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int pcmuio_attach(comedi_device * dev, comedi_devconfig * it);
+-static int pcmuio_detach(comedi_device * dev);
++static int pcmuio_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int pcmuio_detach(struct comedi_device * dev);
+ 
+ static comedi_driver driver = {
+       driver_name:"pcmuio",
+@@ -253,24 +253,24 @@ static comedi_driver driver = {
+       num_names:sizeof(pcmuio_boards) / sizeof(pcmuio_board),
+ };
+ 
+-static int pcmuio_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int pcmuio_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int pcmuio_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int pcmuio_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ static irqreturn_t interrupt_pcmuio(int irq, void *d PT_REGS_ARG);
+-static void pcmuio_stop_intr(comedi_device *, comedi_subdevice *);
+-static int pcmuio_cancel(comedi_device * dev, comedi_subdevice * s);
+-static int pcmuio_cmd(comedi_device * dev, comedi_subdevice * s);
+-static int pcmuio_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static void pcmuio_stop_intr(struct comedi_device *, comedi_subdevice *);
++static int pcmuio_cancel(struct comedi_device * dev, comedi_subdevice * s);
++static int pcmuio_cmd(struct comedi_device * dev, comedi_subdevice * s);
++static int pcmuio_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+ 
+ /* some helper functions to deal with specifics of this device's registers */
+-static void init_asics(comedi_device * dev);	/* sets up/clears ASIC chips to defaults */
+-static void switch_page(comedi_device * dev, int asic, int page);
++static void init_asics(struct comedi_device * dev);	/* sets up/clears ASIC chips to defaults */
++static void switch_page(struct comedi_device * dev, int asic, int page);
+ #ifdef notused
+-static void lock_port(comedi_device * dev, int asic, int port);
+-static void unlock_port(comedi_device * dev, int asic, int port);
++static void lock_port(struct comedi_device * dev, int asic, int port);
++static void unlock_port(struct comedi_device * dev, int asic, int port);
+ #endif
+ 
+ /*
+@@ -279,7 +279,7 @@ static void unlock_port(comedi_device * dev, int asic, int port);
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int pcmuio_attach(comedi_device * dev, comedi_devconfig * it)
++static int pcmuio_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	int sdev_no, chans_left, n_subdevs, port, asic, thisasic_chanct = 0;
+@@ -450,7 +450,7 @@ static int pcmuio_attach(comedi_device * dev, comedi_devconfig * it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int pcmuio_detach(comedi_device * dev)
++static int pcmuio_detach(struct comedi_device * dev)
+ {
+ 	int i;
+ 
+@@ -474,7 +474,7 @@ static int pcmuio_detach(comedi_device * dev)
+  * useful to applications if you implement the insn_bits interface.
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+-static int pcmuio_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int pcmuio_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int byte_no;
+@@ -548,7 +548,7 @@ static int pcmuio_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+  * configured by a special insn_config instruction.  chanspec
+  * contains the channel to be changed, and data[0] contains the
+  * value COMEDI_INPUT or COMEDI_OUTPUT. */
+-static int pcmuio_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int pcmuio_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec), byte_no = chan / 8, bit_no =
+@@ -609,7 +609,7 @@ static int pcmuio_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 	return insn->n;
+ }
+ 
+-static void init_asics(comedi_device * dev)
++static void init_asics(struct comedi_device * dev)
+ {				/* sets up an
+ 				   ASIC chip to defaults */
+ 	int asic;
+@@ -646,7 +646,7 @@ static void init_asics(comedi_device * dev)
+ 	}
+ }
+ 
+-static void switch_page(comedi_device * dev, int asic, int page)
++static void switch_page(struct comedi_device * dev, int asic, int page)
+ {
+ 	if (asic < 0 || asic >= thisboard->num_asics)
+ 		return;		/* paranoia */
+@@ -662,7 +662,7 @@ static void switch_page(comedi_device * dev, int asic, int page)
+ }
+ 
+ #ifdef notused
+-static void lock_port(comedi_device * dev, int asic, int port)
++static void lock_port(struct comedi_device * dev, int asic, int port)
+ {
+ 	if (asic < 0 || asic >= thisboard->num_asics)
+ 		return;		/* paranoia */
+@@ -675,7 +675,7 @@ static void lock_port(comedi_device * dev, int asic, int port)
+ 		dev->iobase + ASIC_IOSIZE * asic + REG_PAGELOCK);
+ }
+ 
+-static void unlock_port(comedi_device * dev, int asic, int port)
++static void unlock_port(struct comedi_device * dev, int asic, int port)
+ {
+ 	if (asic < 0 || asic >= thisboard->num_asics)
+ 		return;		/* paranoia */
+@@ -691,7 +691,7 @@ static void unlock_port(comedi_device * dev, int asic, int port)
+ static irqreturn_t interrupt_pcmuio(int irq, void *d PT_REGS_ARG)
+ {
+ 	int asic, got1 = 0;
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 
+ 	for (asic = 0; asic < MAX_ASICS; ++asic) {
+ 		if (irq == devpriv->asics[asic].irq) {
+@@ -837,7 +837,7 @@ static irqreturn_t interrupt_pcmuio(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static void pcmuio_stop_intr(comedi_device * dev, comedi_subdevice * s)
++static void pcmuio_stop_intr(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	int nports, firstport, asic, port;
+ 
+@@ -856,7 +856,7 @@ static void pcmuio_stop_intr(comedi_device * dev, comedi_subdevice * s)
+ 	}
+ }
+ 
+-static int pcmuio_start_intr(comedi_device * dev, comedi_subdevice * s)
++static int pcmuio_start_intr(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	if (!subpriv->intr.continuous && subpriv->intr.stop_count == 0) {
+ 		/* An empty acquisition! */
+@@ -905,7 +905,7 @@ static int pcmuio_start_intr(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int pcmuio_cancel(comedi_device * dev, comedi_subdevice * s)
++static int pcmuio_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	unsigned long flags;
+ 
+@@ -921,7 +921,7 @@ static int pcmuio_cancel(comedi_device * dev, comedi_subdevice * s)
+  * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
+  */
+ static int
+-pcmuio_inttrig_start_intr(comedi_device * dev, comedi_subdevice * s,
++pcmuio_inttrig_start_intr(struct comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int trignum)
+ {
+ 	unsigned long flags;
+@@ -947,7 +947,7 @@ pcmuio_inttrig_start_intr(comedi_device * dev, comedi_subdevice * s,
+ /*
+  * 'do_cmd' function for an 'INTERRUPT' subdevice.
+  */
+-static int pcmuio_cmd(comedi_device * dev, comedi_subdevice * s)
++static int pcmuio_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned long flags;
+@@ -992,7 +992,7 @@ static int pcmuio_cmd(comedi_device * dev, comedi_subdevice * s)
+  * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
+  */
+ static int
+-pcmuio_cmdtest(comedi_device * dev, comedi_subdevice * s, comedi_cmd * cmd)
++pcmuio_cmdtest(struct comedi_device * dev, comedi_subdevice * s, comedi_cmd * cmd)
+ {
+ 	int err = 0;
+ 	unsigned int tmp;
+diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c
+index d9147d18882d..9cd1472a9120 100644
+--- a/drivers/staging/comedi/drivers/poc.c
++++ b/drivers/staging/comedi/drivers/poc.c
+@@ -41,30 +41,30 @@ Configuration options:
+ 
+ #include 
+ 
+-static int poc_attach(comedi_device * dev, comedi_devconfig * it);
+-static int poc_detach(comedi_device * dev);
+-static int readback_insn(comedi_device * dev, comedi_subdevice * s,
++static int poc_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int poc_detach(struct comedi_device * dev);
++static int readback_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+-static int dac02_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int dac02_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int pcl733_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int pcl733_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int pcl734_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int pcl734_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ struct boarddef_struct {
+ 	const char *name;
+ 	unsigned int iosize;
+-	int (*setup) (comedi_device *);
++	int (*setup) (struct comedi_device *);
+ 	int type;
+ 	int n_chan;
+ 	int n_bits;
+-	int (*winsn) (comedi_device *, comedi_subdevice *, comedi_insn *,
++	int (*winsn) (struct comedi_device *, comedi_subdevice *, comedi_insn *,
+ 		unsigned int *);
+-	int (*rinsn) (comedi_device *, comedi_subdevice *, comedi_insn *,
++	int (*rinsn) (struct comedi_device *, comedi_subdevice *, comedi_insn *,
+ 		unsigned int *);
+-	int (*insnbits) (comedi_device *, comedi_subdevice *, comedi_insn *,
++	int (*insnbits) (struct comedi_device *, comedi_subdevice *, comedi_insn *,
+ 		unsigned int *);
+ 	const comedi_lrange *range;
+ };
+@@ -113,7 +113,7 @@ static comedi_driver driver_poc = {
+       offset:sizeof(boards[0]),
+ };
+ 
+-static int poc_attach(comedi_device * dev, comedi_devconfig * it)
++static int poc_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	unsigned long iobase;
+@@ -159,7 +159,7 @@ static int poc_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int poc_detach(comedi_device * dev)
++static int poc_detach(struct comedi_device * dev)
+ {
+ 	/* only free stuff if it has been allocated by _attach */
+ 	if (dev->iobase)
+@@ -170,7 +170,7 @@ static int poc_detach(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int readback_insn(comedi_device * dev, comedi_subdevice * s,
++static int readback_insn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan;
+@@ -185,7 +185,7 @@ static int readback_insn(comedi_device * dev, comedi_subdevice * s,
+ #define DAC02_LSB(a)	(2 * a)
+ #define DAC02_MSB(a)	(2 * a + 1)
+ 
+-static int dac02_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int dac02_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int temp;
+@@ -208,7 +208,7 @@ static int dac02_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int pcl733_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int pcl733_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -222,7 +222,7 @@ static int pcl733_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int pcl734_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int pcl734_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+index ac34c5183c0c..cc6a6daa1f9a 100644
+--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
++++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+@@ -86,7 +86,7 @@ typedef struct local_info_t {
+ 
+ 	struct semaphore eos;
+ 
+-	comedi_device *dev;
++	struct comedi_device *dev;
+ 	comedi_subdevice *s;
+ 	int count;
+ } local_info_t;
+@@ -197,8 +197,8 @@ static const comedi_lrange range_daqp_ao = { 1, {BIP_RANGE(5)} };
+ 
+ /* comedi interface code */
+ 
+-static int daqp_attach(comedi_device * dev, comedi_devconfig * it);
+-static int daqp_detach(comedi_device * dev);
++static int daqp_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int daqp_detach(struct comedi_device * dev);
+ static comedi_driver driver_daqp = {
+       driver_name:"quatech_daqp_cs",
+       module:THIS_MODULE,
+@@ -208,7 +208,7 @@ static comedi_driver driver_daqp = {
+ 
+ #ifdef DAQP_DEBUG
+ 
+-static void daqp_dump(comedi_device * dev)
++static void daqp_dump(struct comedi_device * dev)
+ {
+ 	printk("DAQP: status %02x; aux status %02x\n",
+ 		inb(dev->iobase + DAQP_STATUS), inb(dev->iobase + DAQP_AUX));
+@@ -234,7 +234,7 @@ static void hex_dump(char *str, void *ptr, int len)
+ 
+ /* Cancel a running acquisition */
+ 
+-static int daqp_ai_cancel(comedi_device * dev, comedi_subdevice * s)
++static int daqp_ai_cancel(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	local_info_t *local = (local_info_t *) s->private;
+ 
+@@ -265,7 +265,7 @@ static int daqp_ai_cancel(comedi_device * dev, comedi_subdevice * s)
+ static void daqp_interrupt(int irq, void *dev_id PT_REGS_ARG)
+ {
+ 	local_info_t *local = (local_info_t *) dev_id;
+-	comedi_device *dev;
++	struct comedi_device *dev;
+ 	comedi_subdevice *s;
+ 	int loop_limit = 10000;
+ 	int status;
+@@ -284,7 +284,7 @@ static void daqp_interrupt(int irq, void *dev_id PT_REGS_ARG)
+ 
+ 	if (!dev->attached) {
+ 		printk(KERN_WARNING
+-			"daqp_interrupt(): comedi_device not yet attached.\n");
++			"daqp_interrupt(): struct comedi_device not yet attached.\n");
+ 		return;
+ 	}
+ 
+@@ -361,7 +361,7 @@ static void daqp_interrupt(int irq, void *dev_id PT_REGS_ARG)
+ 
+ /* One-shot analog data acquisition routine */
+ 
+-static int daqp_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int daqp_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	local_info_t *local = (local_info_t *) s->private;
+@@ -467,7 +467,7 @@ static int daqp_ns_to_timer(unsigned int *ns, int round)
+  * the command passes.
+  */
+ 
+-static int daqp_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int daqp_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -593,7 +593,7 @@ static int daqp_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int daqp_ai_cmd(comedi_device * dev, comedi_subdevice * s)
++static int daqp_ai_cmd(struct comedi_device * dev, comedi_subdevice * s)
+ {
+ 	local_info_t *local = (local_info_t *) s->private;
+ 	comedi_cmd *cmd = &s->async->cmd;
+@@ -793,7 +793,7 @@ static int daqp_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ 
+ /* Single-shot analog output routine */
+ 
+-static int daqp_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
++static int daqp_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	local_info_t *local = (local_info_t *) s->private;
+@@ -820,7 +820,7 @@ static int daqp_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+ 
+ /* Digital input routine */
+ 
+-static int daqp_di_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int daqp_di_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	local_info_t *local = (local_info_t *) s->private;
+@@ -836,7 +836,7 @@ static int daqp_di_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 
+ /* Digital output routine */
+ 
+-static int daqp_do_insn_write(comedi_device * dev, comedi_subdevice * s,
++static int daqp_do_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	local_info_t *local = (local_info_t *) s->private;
+@@ -856,7 +856,7 @@ static int daqp_do_insn_write(comedi_device * dev, comedi_subdevice * s,
+  * when it is inserted.
+  */
+ 
+-static int daqp_attach(comedi_device * dev, comedi_devconfig * it)
++static int daqp_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int ret;
+ 	local_info_t *local = dev_table[it->options[0]];
+@@ -962,7 +962,7 @@ static int daqp_attach(comedi_device * dev, comedi_devconfig * it)
+  * card is removed, daqp_cs_detach() is called by the pcmcia subsystem.
+  */
+ 
+-static int daqp_detach(comedi_device * dev)
++static int daqp_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: detaching daqp\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
+index 571fa54c4d38..f4b1fc6fa488 100644
+--- a/drivers/staging/comedi/drivers/rtd520.c
++++ b/drivers/staging/comedi/drivers/rtd520.c
+@@ -680,8 +680,8 @@ struct rtdPrivate {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int rtd_attach(comedi_device *dev, comedi_devconfig *it);
+-static int rtd_detach(comedi_device *dev);
++static int rtd_attach(struct comedi_device *dev, comedi_devconfig *it);
++static int rtd_detach(struct comedi_device *dev);
+ 
+ static comedi_driver rtd520Driver = {
+       driver_name: DRV_NAME,
+@@ -690,24 +690,24 @@ static comedi_driver rtd520Driver = {
+       detach : rtd_detach,
+ };
+ 
+-static int rtd_ai_rinsn(comedi_device *dev, comedi_subdevice *s,
++static int rtd_ai_rinsn(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+-static int rtd_ao_winsn(comedi_device *dev, comedi_subdevice *s,
++static int rtd_ao_winsn(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+-static int rtd_ao_rinsn(comedi_device *dev, comedi_subdevice *s,
++static int rtd_ao_rinsn(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+-static int rtd_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
++static int rtd_dio_insn_bits(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+-static int rtd_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
++static int rtd_dio_insn_config(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+-static int rtd_ai_cmdtest(comedi_device *dev, comedi_subdevice *s,
++static int rtd_ai_cmdtest(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_cmd *cmd);
+-static int rtd_ai_cmd(comedi_device *dev, comedi_subdevice *s);
+-static int rtd_ai_cancel(comedi_device *dev, comedi_subdevice *s);
+-/* static int rtd_ai_poll (comedi_device *dev,comedi_subdevice *s); */
++static int rtd_ai_cmd(struct comedi_device *dev, comedi_subdevice *s);
++static int rtd_ai_cancel(struct comedi_device *dev, comedi_subdevice *s);
++/* static int rtd_ai_poll (struct comedi_device *dev,comedi_subdevice *s); */
+ static int rtd_ns_to_timer(unsigned int *ns, int roundMode);
+ static irqreturn_t rtd_interrupt(int irq, void *d PT_REGS_ARG);
+-static int rtd520_probe_fifo_depth(comedi_device *dev);
++static int rtd520_probe_fifo_depth(struct comedi_device *dev);
+ 
+ /*
+  * Attach is called by the Comedi core to configure the driver
+@@ -715,7 +715,7 @@ static int rtd520_probe_fifo_depth(comedi_device *dev);
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int rtd_attach(comedi_device *dev, comedi_devconfig *it)
++static int rtd_attach(struct comedi_device *dev, comedi_devconfig *it)
+ {				/* board name and options flags */
+ 	comedi_subdevice *s;
+ 	struct pci_dev *pcidev;
+@@ -1060,7 +1060,7 @@ static int rtd_attach(comedi_device *dev, comedi_devconfig *it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int rtd_detach(comedi_device *dev)
++static int rtd_detach(struct comedi_device *dev)
+ {
+ #ifdef USE_DMA
+ 	int index;
+@@ -1140,7 +1140,7 @@ static int rtd_detach(comedi_device *dev)
+ /*
+   Convert a single comedi channel-gain entry to a RTD520 table entry
+ */
+-static unsigned short rtdConvertChanGain(comedi_device *dev,
++static unsigned short rtdConvertChanGain(struct comedi_device *dev,
+ 	unsigned int comediChan, int chanIndex)
+ {				/* index in channel list */
+ 	unsigned int chan, range, aref;
+@@ -1190,7 +1190,7 @@ static unsigned short rtdConvertChanGain(comedi_device *dev,
+ /*
+   Setup the channel-gain table from a comedi list
+ */
+-static void rtd_load_channelgain_list(comedi_device *dev,
++static void rtd_load_channelgain_list(struct comedi_device *dev,
+ 	unsigned int n_chan, unsigned int *list)
+ {
+ 	if (n_chan > 1) {	/* setup channel gain table */
+@@ -1209,7 +1209,7 @@ static void rtd_load_channelgain_list(comedi_device *dev,
+ 
+ /* determine fifo size by doing adc conversions until the fifo half
+ empty status flag clears */
+-static int rtd520_probe_fifo_depth(comedi_device *dev)
++static int rtd520_probe_fifo_depth(struct comedi_device *dev)
+ {
+ 	unsigned int chanspec = CR_PACK(0, 0, AREF_GROUND);
+ 	unsigned i;
+@@ -1254,7 +1254,7 @@ static int rtd520_probe_fifo_depth(comedi_device *dev)
+   Note, we don't do any settling delays.  Use a instruction list to
+   select, delay, then read.
+  */
+-static int rtd_ai_rinsn(comedi_device *dev,
++static int rtd_ai_rinsn(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, ii;
+@@ -1307,7 +1307,7 @@ static int rtd_ai_rinsn(comedi_device *dev,
+ 
+   The manual claims that we can do a lword read, but it doesn't work here.
+ */
+-static int ai_read_n(comedi_device *dev, comedi_subdevice *s, int count)
++static int ai_read_n(struct comedi_device *dev, comedi_subdevice *s, int count)
+ {
+ 	int ii;
+ 
+@@ -1346,7 +1346,7 @@ static int ai_read_n(comedi_device *dev, comedi_subdevice *s, int count)
+ /*
+   unknown amout of data is waiting in fifo.
+ */
+-static int ai_read_dregs(comedi_device *dev, comedi_subdevice *s)
++static int ai_read_dregs(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 	while (RtdFifoStatus(dev) & FS_ADC_NOT_EMPTY) {	/* 1 -> not empty */
+ 		short sample;
+@@ -1375,7 +1375,7 @@ static int ai_read_dregs(comedi_device *dev, comedi_subdevice *s)
+ /*
+   Terminate a DMA transfer and wait for everything to quiet down
+ */
+-void abort_dma(comedi_device *dev, unsigned int channel)
++void abort_dma(struct comedi_device *dev, unsigned int channel)
+ {				/* DMA channel 0, 1 */
+ 	unsigned long dma_cs_addr;	/* the control/status register */
+ 	uint8_t status;
+@@ -1434,7 +1434,7 @@ void abort_dma(comedi_device *dev, unsigned int channel)
+   Process what is in the DMA transfer buffer and pass to comedi
+   Note: this is not re-entrant
+ */
+-static int ai_process_dma(comedi_device *dev, comedi_subdevice *s)
++static int ai_process_dma(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 	int ii, n;
+ 	s16 *dp;
+@@ -1497,7 +1497,7 @@ static irqreturn_t rtd_interrupt(int irq,	/* interrupt number (ignored) */
+ 	void *d			/* our data */
+ 	PT_REGS_ARG)
+ {				/* cpu context (ignored) */
+-	comedi_device *dev = d;	/* must be called "dev" for devpriv */
++	struct comedi_device *dev = d;	/* must be called "dev" for devpriv */
+ 	u16 status;
+ 	u16 fifoStatus;
+ 	comedi_subdevice *s = dev->subdevices + 0;	/* analog in subdevice */
+@@ -1648,7 +1648,7 @@ static irqreturn_t rtd_interrupt(int irq,	/* interrupt number (ignored) */
+ /*
+   return the number of samples available
+ */
+-static int rtd_ai_poll(comedi_device *dev, comedi_subdevice *s)
++static int rtd_ai_poll(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 	/* TODO: This needs to mask interrupts, read_dregs, and then re-enable */
+ 	/* Not sure what to do if DMA is active */
+@@ -1665,7 +1665,7 @@ static int rtd_ai_poll(comedi_device *dev, comedi_subdevice *s)
+   the command passes.
+ */
+ 
+-static int rtd_ai_cmdtest(comedi_device *dev,
++static int rtd_ai_cmdtest(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_cmd *cmd)
+ {
+ 	int err = 0;
+@@ -1870,7 +1870,7 @@ static int rtd_ai_cmdtest(comedi_device *dev,
+   This is usually done by an interrupt handler.
+   Userland gets to the data using read calls.
+ */
+-static int rtd_ai_cmd(comedi_device *dev, comedi_subdevice *s)
++static int rtd_ai_cmd(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	int timer;
+@@ -2067,7 +2067,7 @@ static int rtd_ai_cmd(comedi_device *dev, comedi_subdevice *s)
+ /*
+   Stop a running data aquisition.
+ */
+-static int rtd_ai_cancel(comedi_device *dev, comedi_subdevice *s)
++static int rtd_ai_cancel(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 	u16 status;
+ 
+@@ -2135,7 +2135,7 @@ static int rtd_ns_to_timer(unsigned int *ns, int round_mode)
+ /*
+   Output one (or more) analog values to a single port as fast as possible.
+ */
+-static int rtd_ao_winsn(comedi_device *dev,
++static int rtd_ao_winsn(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+@@ -2190,7 +2190,7 @@ static int rtd_ao_winsn(comedi_device *dev,
+ 
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+-static int rtd_ao_rinsn(comedi_device *dev,
++static int rtd_ao_rinsn(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+@@ -2213,7 +2213,7 @@ static int rtd_ao_rinsn(comedi_device *dev,
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write
+  */
+-static int rtd_dio_insn_bits(comedi_device *dev,
++static int rtd_dio_insn_bits(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+@@ -2240,7 +2240,7 @@ static int rtd_dio_insn_bits(comedi_device *dev,
+ /*
+   Configure one bit on a IO port as Input or Output (hence the name :-).
+ */
+-static int rtd_dio_insn_config(comedi_device *dev,
++static int rtd_dio_insn_config(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c
+index 0cefcb39db7c..8ec384528181 100644
+--- a/drivers/staging/comedi/drivers/rti800.c
++++ b/drivers/staging/comedi/drivers/rti800.c
+@@ -129,8 +129,8 @@ static const boardtype boardtypes[] = {
+ 
+ #define this_board ((const boardtype *)dev->board_ptr)
+ 
+-static int rti800_attach(comedi_device * dev, comedi_devconfig * it);
+-static int rti800_detach(comedi_device * dev);
++static int rti800_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int rti800_detach(struct comedi_device * dev);
+ static comedi_driver driver_rti800 = {
+       driver_name:"rti800",
+       module:THIS_MODULE,
+@@ -178,7 +178,7 @@ static irqreturn_t rti800_interrupt(int irq, void *dev PT_REGS_ARG)
+ // settling delay times in usec for different gains
+ static const int gaindelay[] = { 10, 20, 40, 80 };
+ 
+-static int rti800_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int rti800_ai_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, t;
+@@ -231,7 +231,7 @@ static int rti800_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int rti800_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int rti800_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -243,7 +243,7 @@ static int rti800_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int rti800_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
++static int rti800_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -263,7 +263,7 @@ static int rti800_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int rti800_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int rti800_di_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -272,7 +272,7 @@ static int rti800_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int rti800_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int rti800_do_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -307,7 +307,7 @@ static int rti800_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+    options[8] - dac1 coding
+  */
+ 
+-static int rti800_attach(comedi_device * dev, comedi_devconfig * it)
++static int rti800_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	unsigned int irq;
+ 	unsigned long iobase;
+@@ -442,7 +442,7 @@ static int rti800_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int rti800_detach(comedi_device * dev)
++static int rti800_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: rti800: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c
+index 058a4c066205..843fce9056c8 100644
+--- a/drivers/staging/comedi/drivers/rti802.c
++++ b/drivers/staging/comedi/drivers/rti802.c
+@@ -47,8 +47,8 @@ Configuration Options:
+ #define RTI802_DATALOW 1
+ #define RTI802_DATAHIGH 2
+ 
+-static int rti802_attach(comedi_device * dev, comedi_devconfig * it);
+-static int rti802_detach(comedi_device * dev);
++static int rti802_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int rti802_detach(struct comedi_device * dev);
+ static comedi_driver driver_rti802 = {
+       driver_name:"rti802",
+       module:THIS_MODULE,
+@@ -68,7 +68,7 @@ typedef struct {
+ 
+ #define devpriv ((rti802_private *)dev->private)
+ 
+-static int rti802_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
++static int rti802_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -79,7 +79,7 @@ static int rti802_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int rti802_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
++static int rti802_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, d;
+@@ -96,7 +96,7 @@ static int rti802_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int rti802_attach(comedi_device * dev, comedi_devconfig * it)
++static int rti802_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	int i;
+@@ -140,7 +140,7 @@ static int rti802_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int rti802_detach(comedi_device * dev)
++static int rti802_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: rti802: remove\n", dev->minor);
+ 
+diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
+index c9bd985f9932..7e066a0263cc 100644
+--- a/drivers/staging/comedi/drivers/s526.c
++++ b/drivers/staging/comedi/drivers/s526.c
+@@ -190,7 +190,7 @@ static const s526_board s526_boards[] = {
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+-   feel free to suggest moving the variable to the comedi_device struct.  */
++   feel free to suggest moving the variable to the struct comedi_device struct.  */
+ typedef struct {
+ 	int data;
+ 
+@@ -215,8 +215,8 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int s526_attach(comedi_device * dev, comedi_devconfig * it);
+-static int s526_detach(comedi_device * dev);
++static int s526_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int s526_detach(struct comedi_device * dev);
+ static comedi_driver driver_s526 = {
+       driver_name:"s526",
+       module:THIS_MODULE,
+@@ -245,23 +245,23 @@ static comedi_driver driver_s526 = {
+       num_names:sizeof(s526_boards) / sizeof(s526_board),
+ };
+ 
+-static int s526_gpct_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int s526_gpct_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int s526_gpct_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int s526_gpct_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int s526_gpct_winsn(comedi_device * dev, comedi_subdevice * s,
++static int s526_gpct_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int s526_ai_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int s526_ai_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int s526_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int s526_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int s526_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int s526_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int s526_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int s526_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int s526_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int s526_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int s526_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int s526_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ /*
+@@ -270,7 +270,7 @@ static int s526_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int s526_attach(comedi_device * dev, comedi_devconfig * it)
++static int s526_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 	int iobase;
+@@ -466,7 +466,7 @@ static int s526_attach(comedi_device * dev, comedi_devconfig * it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int s526_detach(comedi_device * dev)
++static int s526_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: s526: remove\n", dev->minor);
+ 
+@@ -476,7 +476,7 @@ static int s526_detach(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int s526_gpct_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int s526_gpct_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;			// counts the Data
+@@ -500,7 +500,7 @@ static int s526_gpct_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int s526_gpct_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int s526_gpct_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int subdev_channel = CR_CHAN(insn->chanspec);	// Unpack chanspec
+@@ -725,7 +725,7 @@ static int s526_gpct_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 	return insn->n;
+ }
+ 
+-static int s526_gpct_winsn(comedi_device * dev, comedi_subdevice * s,
++static int s526_gpct_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int subdev_channel = CR_CHAN(insn->chanspec);	// Unpack chanspec
+@@ -784,7 +784,7 @@ static int s526_gpct_winsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ #define ISR_ADC_DONE 0x4
+-static int s526_ai_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int s526_ai_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int result = -EINVAL;
+@@ -817,7 +817,7 @@ static int s526_ai_insn_config(comedi_device * dev, comedi_subdevice * s,
+  * "instructions" read/write data in "one-shot" or "software-triggered"
+  * mode.
+  */
+-static int s526_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int s526_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i;
+@@ -867,7 +867,7 @@ static int s526_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int s526_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int s526_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -896,7 +896,7 @@ static int s526_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ 
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+-static int s526_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int s526_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -913,7 +913,7 @@ static int s526_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+  * useful to applications if you implement the insn_bits interface.
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+-static int s526_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int s526_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -938,7 +938,7 @@ static int s526_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int s526_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int s526_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
+index a4f4de69da76..7a9e4544f00a 100644
+--- a/drivers/staging/comedi/drivers/s626.c
++++ b/drivers/staging/comedi/drivers/s626.c
+@@ -118,8 +118,8 @@ static DEFINE_PCI_DEVICE_TABLE(s626_pci_table) = {
+ 
+ MODULE_DEVICE_TABLE(pci, s626_pci_table);
+ 
+-static int s626_attach(comedi_device *dev, comedi_devconfig *it);
+-static int s626_detach(comedi_device *dev);
++static int s626_attach(struct comedi_device *dev, comedi_devconfig *it);
++static int s626_detach(struct comedi_device *dev);
+ 
+ static comedi_driver driver_s626 = {
+       driver_name:"s626",
+@@ -222,36 +222,36 @@ static struct dio_private *dio_private_word[]={
+ COMEDI_PCI_INITCLEANUP_NOMODULE(driver_s626, s626_pci_table);
+ 
+ /* ioctl routines */
+-static int s626_ai_insn_config(comedi_device *dev, comedi_subdevice *s,
++static int s626_ai_insn_config(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+-/* static int s626_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data); */
+-static int s626_ai_insn_read(comedi_device *dev, comedi_subdevice *s,
++/* static int s626_ai_rinsn(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data); */
++static int s626_ai_insn_read(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+-static int s626_ai_cmd(comedi_device *dev, comedi_subdevice *s);
+-static int s626_ai_cmdtest(comedi_device *dev, comedi_subdevice *s,
++static int s626_ai_cmd(struct comedi_device *dev, comedi_subdevice *s);
++static int s626_ai_cmdtest(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_cmd *cmd);
+-static int s626_ai_cancel(comedi_device *dev, comedi_subdevice *s);
+-static int s626_ao_winsn(comedi_device *dev, comedi_subdevice *s,
++static int s626_ai_cancel(struct comedi_device *dev, comedi_subdevice *s);
++static int s626_ao_winsn(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+-static int s626_ao_rinsn(comedi_device *dev, comedi_subdevice *s,
++static int s626_ao_rinsn(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+-static int s626_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
++static int s626_dio_insn_bits(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+-static int s626_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
++static int s626_dio_insn_config(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+-static int s626_dio_set_irq(comedi_device *dev, unsigned int chan);
+-static int s626_dio_reset_irq(comedi_device *dev, unsigned int gruop,
++static int s626_dio_set_irq(struct comedi_device *dev, unsigned int chan);
++static int s626_dio_reset_irq(struct comedi_device *dev, unsigned int gruop,
+ 	unsigned int mask);
+-static int s626_dio_clear_irq(comedi_device *dev);
+-static int s626_enc_insn_config(comedi_device *dev, comedi_subdevice *s,
++static int s626_dio_clear_irq(struct comedi_device *dev);
++static int s626_enc_insn_config(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+-static int s626_enc_insn_read(comedi_device *dev, comedi_subdevice *s,
++static int s626_enc_insn_read(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+-static int s626_enc_insn_write(comedi_device *dev, comedi_subdevice *s,
++static int s626_enc_insn_write(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data);
+ static int s626_ns_to_timer(int *nanosec, int round_mode);
+ static int s626_ai_load_polllist(uint8_t *ppl, comedi_cmd *cmd);
+-static int s626_ai_inttrig(comedi_device *dev, comedi_subdevice *s,
++static int s626_ai_inttrig(struct comedi_device *dev, comedi_subdevice *s,
+ 	unsigned int trignum);
+ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG);
+ static unsigned int s626_ai_reg_to_uint(int data);
+@@ -260,36 +260,36 @@ static unsigned int s626_ai_reg_to_uint(int data);
+ /* end ioctl routines */
+ 
+ /* internal routines */
+-static void s626_dio_init(comedi_device *dev);
+-static void ResetADC(comedi_device *dev, uint8_t *ppl);
+-static void LoadTrimDACs(comedi_device *dev);
+-static void WriteTrimDAC(comedi_device *dev, uint8_t LogicalChan,
++static void s626_dio_init(struct comedi_device *dev);
++static void ResetADC(struct comedi_device *dev, uint8_t *ppl);
++static void LoadTrimDACs(struct comedi_device *dev);
++static void WriteTrimDAC(struct comedi_device *dev, uint8_t LogicalChan,
+ 	uint8_t DacData);
+-static uint8_t I2Cread(comedi_device *dev, uint8_t addr);
+-static uint32_t I2Chandshake(comedi_device *dev, uint32_t val);
+-static void SetDAC(comedi_device *dev, uint16_t chan, short dacdata);
+-static void SendDAC(comedi_device *dev, uint32_t val);
+-static void WriteMISC2(comedi_device *dev, uint16_t NewImage);
+-static void DEBItransfer(comedi_device *dev);
+-static uint16_t DEBIread(comedi_device *dev, uint16_t addr);
+-static void DEBIwrite(comedi_device *dev, uint16_t addr, uint16_t wdata);
+-static void DEBIreplace(comedi_device *dev, uint16_t addr, uint16_t mask,
++static uint8_t I2Cread(struct comedi_device *dev, uint8_t addr);
++static uint32_t I2Chandshake(struct comedi_device *dev, uint32_t val);
++static void SetDAC(struct comedi_device *dev, uint16_t chan, short dacdata);
++static void SendDAC(struct comedi_device *dev, uint32_t val);
++static void WriteMISC2(struct comedi_device *dev, uint16_t NewImage);
++static void DEBItransfer(struct comedi_device *dev);
++static uint16_t DEBIread(struct comedi_device *dev, uint16_t addr);
++static void DEBIwrite(struct comedi_device *dev, uint16_t addr, uint16_t wdata);
++static void DEBIreplace(struct comedi_device *dev, uint16_t addr, uint16_t mask,
+ 	uint16_t wdata);
+-static void CloseDMAB(comedi_device *dev, DMABUF *pdma, size_t bsize);
++static void CloseDMAB(struct comedi_device *dev, DMABUF *pdma, size_t bsize);
+ 
+ /*  COUNTER OBJECT ------------------------------------------------ */
+ struct enc_private {
+ 	/*  Pointers to functions that differ for A and B counters: */
+-	uint16_t(*GetEnable) (comedi_device *dev, struct enc_private *);	/* Return clock enable. */
+-	uint16_t(*GetIntSrc) (comedi_device *dev, struct enc_private *);	/* Return interrupt source. */
+-	uint16_t(*GetLoadTrig) (comedi_device *dev, struct enc_private *);	/* Return preload trigger source. */
+-	uint16_t(*GetMode) (comedi_device *dev, struct enc_private *);	/* Return standardized operating mode. */
+-	void (*PulseIndex) (comedi_device *dev, struct enc_private *);	/* Generate soft index strobe. */
+-	void (*SetEnable) (comedi_device *dev, struct enc_private *, uint16_t enab);	/* Program clock enable. */
+-	void (*SetIntSrc) (comedi_device *dev, struct enc_private *, uint16_t IntSource);	/* Program interrupt source. */
+-	void (*SetLoadTrig) (comedi_device *dev, struct enc_private *, uint16_t Trig);	/* Program preload trigger source. */
+-	void (*SetMode) (comedi_device *dev, struct enc_private *, uint16_t Setup, uint16_t DisableIntSrc);	/* Program standardized operating mode. */
+-	void (*ResetCapFlags) (comedi_device *dev, struct enc_private *);	/* Reset event capture flags. */
++	uint16_t(*GetEnable) (struct comedi_device *dev, struct enc_private *);	/* Return clock enable. */
++	uint16_t(*GetIntSrc) (struct comedi_device *dev, struct enc_private *);	/* Return interrupt source. */
++	uint16_t(*GetLoadTrig) (struct comedi_device *dev, struct enc_private *);	/* Return preload trigger source. */
++	uint16_t(*GetMode) (struct comedi_device *dev, struct enc_private *);	/* Return standardized operating mode. */
++	void (*PulseIndex) (struct comedi_device *dev, struct enc_private *);	/* Generate soft index strobe. */
++	void (*SetEnable) (struct comedi_device *dev, struct enc_private *, uint16_t enab);	/* Program clock enable. */
++	void (*SetIntSrc) (struct comedi_device *dev, struct enc_private *, uint16_t IntSource);	/* Program interrupt source. */
++	void (*SetLoadTrig) (struct comedi_device *dev, struct enc_private *, uint16_t Trig);	/* Program preload trigger source. */
++	void (*SetMode) (struct comedi_device *dev, struct enc_private *, uint16_t Setup, uint16_t DisableIntSrc);	/* Program standardized operating mode. */
++	void (*ResetCapFlags) (struct comedi_device *dev, struct enc_private *);	/* Reset event capture flags. */
+ 
+ 	uint16_t MyCRA;		/*    Address of CRA register. */
+ 	uint16_t MyCRB;		/*    Address of CRB register. */
+@@ -301,45 +301,45 @@ struct enc_private {
+ #define encpriv ((struct enc_private *)(dev->subdevices+5)->private)
+ 
+ /* counters routines */
+-static void s626_timer_load(comedi_device *dev, struct enc_private *k, int tick);
+-static uint32_t ReadLatch(comedi_device *dev, struct enc_private *k);
+-static void ResetCapFlags_A(comedi_device *dev, struct enc_private *k);
+-static void ResetCapFlags_B(comedi_device *dev, struct enc_private *k);
+-static uint16_t GetMode_A(comedi_device *dev, struct enc_private *k);
+-static uint16_t GetMode_B(comedi_device *dev, struct enc_private *k);
+-static void SetMode_A(comedi_device *dev, struct enc_private *k, uint16_t Setup,
++static void s626_timer_load(struct comedi_device *dev, struct enc_private *k, int tick);
++static uint32_t ReadLatch(struct comedi_device *dev, struct enc_private *k);
++static void ResetCapFlags_A(struct comedi_device *dev, struct enc_private *k);
++static void ResetCapFlags_B(struct comedi_device *dev, struct enc_private *k);
++static uint16_t GetMode_A(struct comedi_device *dev, struct enc_private *k);
++static uint16_t GetMode_B(struct comedi_device *dev, struct enc_private *k);
++static void SetMode_A(struct comedi_device *dev, struct enc_private *k, uint16_t Setup,
+ 	uint16_t DisableIntSrc);
+-static void SetMode_B(comedi_device *dev, struct enc_private *k, uint16_t Setup,
++static void SetMode_B(struct comedi_device *dev, struct enc_private *k, uint16_t Setup,
+ 	uint16_t DisableIntSrc);
+-static void SetEnable_A(comedi_device *dev, struct enc_private *k, uint16_t enab);
+-static void SetEnable_B(comedi_device *dev, struct enc_private *k, uint16_t enab);
+-static uint16_t GetEnable_A(comedi_device *dev, struct enc_private *k);
+-static uint16_t GetEnable_B(comedi_device *dev, struct enc_private *k);
+-static void SetLatchSource(comedi_device *dev, struct enc_private *k,
++static void SetEnable_A(struct comedi_device *dev, struct enc_private *k, uint16_t enab);
++static void SetEnable_B(struct comedi_device *dev, struct enc_private *k, uint16_t enab);
++static uint16_t GetEnable_A(struct comedi_device *dev, struct enc_private *k);
++static uint16_t GetEnable_B(struct comedi_device *dev, struct enc_private *k);
++static void SetLatchSource(struct comedi_device *dev, struct enc_private *k,
+ 	uint16_t value);
+-/* static uint16_t GetLatchSource(comedi_device *dev, struct enc_private *k ); */
+-static void SetLoadTrig_A(comedi_device *dev, struct enc_private *k, uint16_t Trig);
+-static void SetLoadTrig_B(comedi_device *dev, struct enc_private *k, uint16_t Trig);
+-static uint16_t GetLoadTrig_A(comedi_device *dev, struct enc_private *k);
+-static uint16_t GetLoadTrig_B(comedi_device *dev, struct enc_private *k);
+-static void SetIntSrc_B(comedi_device *dev, struct enc_private *k,
++/* static uint16_t GetLatchSource(struct comedi_device *dev, struct enc_private *k ); */
++static void SetLoadTrig_A(struct comedi_device *dev, struct enc_private *k, uint16_t Trig);
++static void SetLoadTrig_B(struct comedi_device *dev, struct enc_private *k, uint16_t Trig);
++static uint16_t GetLoadTrig_A(struct comedi_device *dev, struct enc_private *k);
++static uint16_t GetLoadTrig_B(struct comedi_device *dev, struct enc_private *k);
++static void SetIntSrc_B(struct comedi_device *dev, struct enc_private *k,
+ 	uint16_t IntSource);
+-static void SetIntSrc_A(comedi_device *dev, struct enc_private *k,
++static void SetIntSrc_A(struct comedi_device *dev, struct enc_private *k,
+ 	uint16_t IntSource);
+-static uint16_t GetIntSrc_A(comedi_device *dev, struct enc_private *k);
+-static uint16_t GetIntSrc_B(comedi_device *dev, struct enc_private *k);
+-/* static void SetClkMult(comedi_device *dev, struct enc_private *k, uint16_t value ) ; */
+-/* static uint16_t GetClkMult(comedi_device *dev, struct enc_private *k ) ; */
+-/* static void SetIndexPol(comedi_device *dev, struct enc_private *k, uint16_t value ); */
+-/* static uint16_t GetClkPol(comedi_device *dev, struct enc_private *k ) ; */
+-/* static void SetIndexSrc( comedi_device *dev,struct enc_private *k, uint16_t value );  */
+-/* static uint16_t GetClkSrc( comedi_device *dev,struct enc_private *k );  */
+-/* static void SetIndexSrc( comedi_device *dev,struct enc_private *k, uint16_t value );  */
+-/* static uint16_t GetIndexSrc( comedi_device *dev,struct enc_private *k );  */
+-static void PulseIndex_A(comedi_device *dev, struct enc_private *k);
+-static void PulseIndex_B(comedi_device *dev, struct enc_private *k);
+-static void Preload(comedi_device *dev, struct enc_private *k, uint32_t value);
+-static void CountersInit(comedi_device *dev);
++static uint16_t GetIntSrc_A(struct comedi_device *dev, struct enc_private *k);
++static uint16_t GetIntSrc_B(struct comedi_device *dev, struct enc_private *k);
++/* static void SetClkMult(struct comedi_device *dev, struct enc_private *k, uint16_t value ) ; */
++/* static uint16_t GetClkMult(struct comedi_device *dev, struct enc_private *k ) ; */
++/* static void SetIndexPol(struct comedi_device *dev, struct enc_private *k, uint16_t value ); */
++/* static uint16_t GetClkPol(struct comedi_device *dev, struct enc_private *k ) ; */
++/* static void SetIndexSrc( struct comedi_device *dev,struct enc_private *k, uint16_t value );  */
++/* static uint16_t GetClkSrc( struct comedi_device *dev,struct enc_private *k );  */
++/* static void SetIndexSrc( struct comedi_device *dev,struct enc_private *k, uint16_t value );  */
++/* static uint16_t GetIndexSrc( struct comedi_device *dev,struct enc_private *k );  */
++static void PulseIndex_A(struct comedi_device *dev, struct enc_private *k);
++static void PulseIndex_B(struct comedi_device *dev, struct enc_private *k);
++static void Preload(struct comedi_device *dev, struct enc_private *k, uint32_t value);
++static void CountersInit(struct comedi_device *dev);
+ /* end internal routines */
+ 
+ /*  Counter objects constructor. */
+@@ -485,7 +485,7 @@ static const comedi_lrange s626_range_table = { 2, {
+ 	}
+ };
+ 
+-static int s626_attach(comedi_device *dev, comedi_devconfig *it)
++static int s626_attach(struct comedi_device *dev, comedi_devconfig *it)
+ {
+ /*   uint8_t	PollList; */
+ /*   uint16_t	AdcData; */
+@@ -970,7 +970,7 @@ static unsigned int s626_ai_reg_to_uint(int data)
+ 
+ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG)
+ {
+-	comedi_device *dev = d;
++	struct comedi_device *dev = d;
+ 	comedi_subdevice *s;
+ 	comedi_cmd *cmd;
+ 	struct enc_private *k;
+@@ -1268,7 +1268,7 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int s626_detach(comedi_device *dev)
++static int s626_detach(struct comedi_device *dev)
+ {
+ 	if (devpriv) {
+ 		/* stop ai_command */
+@@ -1311,7 +1311,7 @@ static int s626_detach(comedi_device *dev)
+ /*
+  * this functions build the RPS program for hardware driven acquistion
+  */
+-void ResetADC(comedi_device *dev, uint8_t *ppl)
++void ResetADC(struct comedi_device *dev, uint8_t *ppl)
+ {
+ 	register uint32_t *pRPS;
+ 	uint32_t JmpAdrs;
+@@ -1503,14 +1503,14 @@ void ResetADC(comedi_device *dev, uint8_t *ppl)
+ }
+ 
+ /* TO COMPLETE, IF NECESSARY */
+-static int s626_ai_insn_config(comedi_device *dev, comedi_subdevice *s,
++static int s626_ai_insn_config(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	return -EINVAL;
+ }
+ 
+-/* static int s626_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data) */
++/* static int s626_ai_rinsn(struct comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data) */
+ /* { */
+ /*   register uint8_t	i; */
+ /*   register int32_t	*readaddr; */
+@@ -1540,7 +1540,7 @@ static int s626_ai_insn_config(comedi_device *dev, comedi_subdevice *s,
+ /*   return i; */
+ /* } */
+ 
+-static int s626_ai_insn_read(comedi_device *dev, comedi_subdevice *s,
++static int s626_ai_insn_read(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 	uint16_t chan = CR_CHAN(insn->chanspec);
+@@ -1654,7 +1654,7 @@ static int s626_ai_load_polllist(uint8_t *ppl, comedi_cmd *cmd)
+ 	return n;
+ }
+ 
+-static int s626_ai_inttrig(comedi_device *dev, comedi_subdevice *s,
++static int s626_ai_inttrig(struct comedi_device *dev, comedi_subdevice *s,
+ 	unsigned int trignum)
+ {
+ 	if (trignum != 0)
+@@ -1673,7 +1673,7 @@ static int s626_ai_inttrig(comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ /*  TO COMPLETE  */
+-static int s626_ai_cmd(comedi_device *dev, comedi_subdevice *s)
++static int s626_ai_cmd(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 
+ 	uint8_t ppl[16];
+@@ -1819,7 +1819,7 @@ static int s626_ai_cmd(comedi_device *dev, comedi_subdevice *s)
+ 	return 0;
+ }
+ 
+-static int s626_ai_cmdtest(comedi_device *dev, comedi_subdevice *s,
++static int s626_ai_cmdtest(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_cmd *cmd)
+ {
+ 	int err = 0;
+@@ -2004,7 +2004,7 @@ static int s626_ai_cmdtest(comedi_device *dev, comedi_subdevice *s,
+ 	return 0;
+ }
+ 
+-static int s626_ai_cancel(comedi_device *dev, comedi_subdevice *s)
++static int s626_ai_cancel(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 	/*  Stop RPS program in case it is currently running. */
+ 	MC_DISABLE(P_MC1, MC1_ERPS1);
+@@ -2045,7 +2045,7 @@ static int s626_ns_to_timer(int *nanosec, int round_mode)
+ 	return divider - 1;
+ }
+ 
+-static int s626_ao_winsn(comedi_device *dev, comedi_subdevice *s,
++static int s626_ao_winsn(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 
+@@ -2064,7 +2064,7 @@ static int s626_ao_winsn(comedi_device *dev, comedi_subdevice *s,
+ 	return i;
+ }
+ 
+-static int s626_ao_rinsn(comedi_device *dev, comedi_subdevice *s,
++static int s626_ao_rinsn(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+@@ -2081,7 +2081,7 @@ static int s626_ao_rinsn(comedi_device *dev, comedi_subdevice *s,
+  * ports A, B and C, respectively.
+  */
+ 
+-static void s626_dio_init(comedi_device *dev)
++static void s626_dio_init(struct comedi_device *dev)
+ {
+ 	uint16_t group;
+ 	comedi_subdevice *s;
+@@ -2110,7 +2110,7 @@ static void s626_dio_init(comedi_device *dev)
+  * This allows packed reading/writing of the DIO channels.  The comedi
+  * core can convert between insn_bits and insn_read/write */
+ 
+-static int s626_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
++static int s626_dio_insn_bits(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 
+@@ -2146,7 +2146,7 @@ static int s626_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
+ 	return 2;
+ }
+ 
+-static int s626_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
++static int s626_dio_insn_config(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 
+@@ -2173,7 +2173,7 @@ static int s626_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
+ 	return 1;
+ }
+ 
+-static int s626_dio_set_irq(comedi_device *dev, unsigned int chan)
++static int s626_dio_set_irq(struct comedi_device *dev, unsigned int chan)
+ {
+ 	unsigned int group;
+ 	unsigned int bitmask;
+@@ -2215,7 +2215,7 @@ static int s626_dio_set_irq(comedi_device *dev, unsigned int chan)
+ 	return 0;
+ }
+ 
+-static int s626_dio_reset_irq(comedi_device *dev, unsigned int group,
++static int s626_dio_reset_irq(struct comedi_device *dev, unsigned int group,
+ 	unsigned int mask)
+ {
+ 	DEBUG("s626_dio_reset_irq: disable  interrupt on dio channel %d group %d\n", mask, group);
+@@ -2231,7 +2231,7 @@ static int s626_dio_reset_irq(comedi_device *dev, unsigned int group,
+ 	return 0;
+ }
+ 
+-static int s626_dio_clear_irq(comedi_device *dev)
++static int s626_dio_clear_irq(struct comedi_device *dev)
+ {
+ 	unsigned int group;
+ 
+@@ -2251,7 +2251,7 @@ static int s626_dio_clear_irq(comedi_device *dev)
+ /* Now this function initializes the value of the counter (data[0])
+    and set the subdevice. To complete with trigger and interrupt
+    configuration */
+-static int s626_enc_insn_config(comedi_device *dev, comedi_subdevice *s,
++static int s626_enc_insn_config(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 	uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) |	/*  Preload upon */
+@@ -2281,7 +2281,7 @@ static int s626_enc_insn_config(comedi_device *dev, comedi_subdevice *s,
+ 	return insn->n;
+ }
+ 
+-static int s626_enc_insn_read(comedi_device *dev, comedi_subdevice *s,
++static int s626_enc_insn_read(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 
+@@ -2299,7 +2299,7 @@ static int s626_enc_insn_read(comedi_device *dev, comedi_subdevice *s,
+ 	return n;
+ }
+ 
+-static int s626_enc_insn_write(comedi_device *dev, comedi_subdevice *s,
++static int s626_enc_insn_write(struct comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, unsigned int *data)
+ {
+ 
+@@ -2322,7 +2322,7 @@ static int s626_enc_insn_write(comedi_device *dev, comedi_subdevice *s,
+ 	return 1;
+ }
+ 
+-static void s626_timer_load(comedi_device *dev, struct enc_private *k, int tick)
++static void s626_timer_load(struct comedi_device *dev, struct enc_private *k, int tick)
+ {
+ 	uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) |	/*  Preload upon */
+ 		/*  index. */
+@@ -2368,7 +2368,7 @@ static uint8_t trimchan[] = { 10, 9, 8, 3, 2, 7, 6, 1, 0, 5, 4 };
+ static uint8_t trimadrs[] =
+ 	{ 0x40, 0x41, 0x42, 0x50, 0x51, 0x52, 0x53, 0x60, 0x61, 0x62, 0x63 };
+ 
+-static void LoadTrimDACs(comedi_device *dev)
++static void LoadTrimDACs(struct comedi_device *dev)
+ {
+ 	register uint8_t i;
+ 
+@@ -2377,7 +2377,7 @@ static void LoadTrimDACs(comedi_device *dev)
+ 		WriteTrimDAC(dev, i, I2Cread(dev, trimadrs[i]));
+ }
+ 
+-static void WriteTrimDAC(comedi_device *dev, uint8_t LogicalChan,
++static void WriteTrimDAC(struct comedi_device *dev, uint8_t LogicalChan,
+ 	uint8_t DacData)
+ {
+ 	uint32_t chan;
+@@ -2418,7 +2418,7 @@ static void WriteTrimDAC(comedi_device *dev, uint8_t LogicalChan,
+ /* **************  EEPROM ACCESS FUNCTIONS  ************** */
+ /*  Read uint8_t from EEPROM. */
+ 
+-static uint8_t I2Cread(comedi_device *dev, uint8_t addr)
++static uint8_t I2Cread(struct comedi_device *dev, uint8_t addr)
+ {
+ 	uint8_t rtnval;
+ 
+@@ -2451,7 +2451,7 @@ static uint8_t I2Cread(comedi_device *dev, uint8_t addr)
+ 	return rtnval;
+ }
+ 
+-static uint32_t I2Chandshake(comedi_device *dev, uint32_t val)
++static uint32_t I2Chandshake(struct comedi_device *dev, uint32_t val)
+ {
+ 	/*  Write I2C command to I2C Transfer Control shadow register. */
+ 	WR7146(P_I2CCTRL, val);
+@@ -2474,7 +2474,7 @@ static uint32_t I2Chandshake(comedi_device *dev, uint32_t val)
+ 
+ /*  Private helper function: Write setpoint to an application DAC channel. */
+ 
+-static void SetDAC(comedi_device *dev, uint16_t chan, short dacdata)
++static void SetDAC(struct comedi_device *dev, uint16_t chan, short dacdata)
+ {
+ 	register uint16_t signmask;
+ 	register uint32_t WSImage;
+@@ -2535,7 +2535,7 @@ static void SetDAC(comedi_device *dev, uint16_t chan, short dacdata)
+  * Dacpol contains valid target image.
+  */
+ 
+-static void SendDAC(comedi_device *dev, uint32_t val)
++static void SendDAC(struct comedi_device *dev, uint32_t val)
+ {
+ 
+ 	/* START THE SERIAL CLOCK RUNNING ------------- */
+@@ -2655,7 +2655,7 @@ static void SendDAC(comedi_device *dev, uint32_t val)
+ 		;
+ }
+ 
+-static void WriteMISC2(comedi_device *dev, uint16_t NewImage)
++static void WriteMISC2(struct comedi_device *dev, uint16_t NewImage)
+ {
+ 	DEBIwrite(dev, LP_MISC1, MISC1_WENABLE);	/*  enab writes to */
+ 	/*  MISC2 register. */
+@@ -2665,7 +2665,7 @@ static void WriteMISC2(comedi_device *dev, uint16_t NewImage)
+ 
+ /*  Initialize the DEBI interface for all transfers. */
+ 
+-static uint16_t DEBIread(comedi_device *dev, uint16_t addr)
++static uint16_t DEBIread(struct comedi_device *dev, uint16_t addr)
+ {
+ 	uint16_t retval;
+ 
+@@ -2684,7 +2684,7 @@ static uint16_t DEBIread(comedi_device *dev, uint16_t addr)
+ 
+ /*  Execute a DEBI transfer.  This must be called from within a */
+ /*  critical section. */
+-static void DEBItransfer(comedi_device *dev)
++static void DEBItransfer(struct comedi_device *dev)
+ {
+ 	/*  Initiate upload of shadow RAM to DEBI control register. */
+ 	MC_ENABLE(P_MC2, MC2_UPLD_DEBI);
+@@ -2700,7 +2700,7 @@ static void DEBItransfer(comedi_device *dev)
+ }
+ 
+ /*  Write a value to a gate array register. */
+-static void DEBIwrite(comedi_device *dev, uint16_t addr, uint16_t wdata)
++static void DEBIwrite(struct comedi_device *dev, uint16_t addr, uint16_t wdata)
+ {
+ 
+ 	/*  Set up DEBI control register value in shadow RAM. */
+@@ -2715,7 +2715,7 @@ static void DEBIwrite(comedi_device *dev, uint16_t addr, uint16_t wdata)
+  * specifies bits that are to be preserved, wdata is new value to be
+  * or'd with the masked original.
+  */
+-static void DEBIreplace(comedi_device *dev, uint16_t addr, uint16_t mask,
++static void DEBIreplace(struct comedi_device *dev, uint16_t addr, uint16_t mask,
+ 	uint16_t wdata)
+ {
+ 
+@@ -2733,7 +2733,7 @@ static void DEBIreplace(comedi_device *dev, uint16_t addr, uint16_t mask,
+ 	DEBItransfer(dev);	/*  Execute the DEBI Write transfer. */
+ }
+ 
+-static void CloseDMAB(comedi_device *dev, DMABUF *pdma, size_t bsize)
++static void CloseDMAB(struct comedi_device *dev, DMABUF *pdma, size_t bsize)
+ {
+ 	void *vbptr;
+ 	dma_addr_t vpptr;
+@@ -2768,7 +2768,7 @@ static void CloseDMAB(comedi_device *dev, DMABUF *pdma, size_t bsize)
+ 
+ /*  Read a counter's output latch. */
+ 
+-static uint32_t ReadLatch(comedi_device *dev, struct enc_private *k)
++static uint32_t ReadLatch(struct comedi_device *dev, struct enc_private *k)
+ {
+ 	register uint32_t value;
+ 	/* DEBUG FIXME DEBUG("ReadLatch: Read Latch enter\n"); */
+@@ -2787,13 +2787,13 @@ static uint32_t ReadLatch(comedi_device *dev, struct enc_private *k)
+ 
+ /*  Reset a counter's index and overflow event capture flags. */
+ 
+-static void ResetCapFlags_A(comedi_device *dev, struct enc_private *k)
++static void ResetCapFlags_A(struct comedi_device *dev, struct enc_private *k)
+ {
+ 	DEBIreplace(dev, k->MyCRB, (uint16_t) (~CRBMSK_INTCTRL),
+ 		CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A);
+ }
+ 
+-static void ResetCapFlags_B(comedi_device *dev, struct enc_private *k)
++static void ResetCapFlags_B(struct comedi_device *dev, struct enc_private *k)
+ {
+ 	DEBIreplace(dev, k->MyCRB, (uint16_t) (~CRBMSK_INTCTRL),
+ 		CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B);
+@@ -2802,7 +2802,7 @@ static void ResetCapFlags_B(comedi_device *dev, struct enc_private *k)
+ /*  Return counter setup in a format (COUNTER_SETUP) that is consistent */
+ /*  for both A and B counters. */
+ 
+-static uint16_t GetMode_A(comedi_device *dev, struct enc_private *k)
++static uint16_t GetMode_A(struct comedi_device *dev, struct enc_private *k)
+ {
+ 	register uint16_t cra;
+ 	register uint16_t crb;
+@@ -2840,7 +2840,7 @@ static uint16_t GetMode_A(comedi_device *dev, struct enc_private *k)
+ 	return setup;
+ }
+ 
+-static uint16_t GetMode_B(comedi_device *dev, struct enc_private *k)
++static uint16_t GetMode_B(struct comedi_device *dev, struct enc_private *k)
+ {
+ 	register uint16_t cra;
+ 	register uint16_t crb;
+@@ -2886,7 +2886,7 @@ static uint16_t GetMode_B(comedi_device *dev, struct enc_private *k)
+  * ClkPol, ClkEnab, IndexSrc, IndexPol, LoadSrc.
+  */
+ 
+-static void SetMode_A(comedi_device *dev, struct enc_private *k, uint16_t Setup,
++static void SetMode_A(struct comedi_device *dev, struct enc_private *k, uint16_t Setup,
+ 	uint16_t DisableIntSrc)
+ {
+ 	register uint16_t cra;
+@@ -2944,7 +2944,7 @@ static void SetMode_A(comedi_device *dev, struct enc_private *k, uint16_t Setup,
+ 		(uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_A)), crb);
+ }
+ 
+-static void SetMode_B(comedi_device *dev, struct enc_private *k, uint16_t Setup,
++static void SetMode_B(struct comedi_device *dev, struct enc_private *k, uint16_t Setup,
+ 	uint16_t DisableIntSrc)
+ {
+ 	register uint16_t cra;
+@@ -3008,7 +3008,7 @@ static void SetMode_B(comedi_device *dev, struct enc_private *k, uint16_t Setup,
+ 
+ /*  Return/set a counter's enable.  enab: 0=always enabled, 1=enabled by index. */
+ 
+-static void SetEnable_A(comedi_device *dev, struct enc_private *k, uint16_t enab)
++static void SetEnable_A(struct comedi_device *dev, struct enc_private *k, uint16_t enab)
+ {
+ 	DEBUG("SetEnable_A: SetEnable_A enter 3541\n");
+ 	DEBIreplace(dev, k->MyCRB,
+@@ -3016,19 +3016,19 @@ static void SetEnable_A(comedi_device *dev, struct enc_private *k, uint16_t enab
+ 		(uint16_t) (enab << CRBBIT_CLKENAB_A));
+ }
+ 
+-static void SetEnable_B(comedi_device *dev, struct enc_private *k, uint16_t enab)
++static void SetEnable_B(struct comedi_device *dev, struct enc_private *k, uint16_t enab)
+ {
+ 	DEBIreplace(dev, k->MyCRB,
+ 		(uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_B)),
+ 		(uint16_t) (enab << CRBBIT_CLKENAB_B));
+ }
+ 
+-static uint16_t GetEnable_A(comedi_device *dev, struct enc_private *k)
++static uint16_t GetEnable_A(struct comedi_device *dev, struct enc_private *k)
+ {
+ 	return (DEBIread(dev, k->MyCRB) >> CRBBIT_CLKENAB_A) & 1;
+ }
+ 
+-static uint16_t GetEnable_B(comedi_device *dev, struct enc_private *k)
++static uint16_t GetEnable_B(struct comedi_device *dev, struct enc_private *k)
+ {
+ 	return (DEBIread(dev, k->MyCRB) >> CRBBIT_CLKENAB_B) & 1;
+ }
+@@ -3038,7 +3038,7 @@ static uint16_t GetEnable_B(comedi_device *dev, struct enc_private *k)
+  * latches B.
+  */
+ 
+-static void SetLatchSource(comedi_device *dev, struct enc_private *k, uint16_t value)
++static void SetLatchSource(struct comedi_device *dev, struct enc_private *k, uint16_t value)
+ {
+ 	DEBUG("SetLatchSource: SetLatchSource enter 3550 \n");
+ 	DEBIreplace(dev, k->MyCRB,
+@@ -3049,7 +3049,7 @@ static void SetLatchSource(comedi_device *dev, struct enc_private *k, uint16_t v
+ }
+ 
+ /*
+- * static uint16_t GetLatchSource(comedi_device *dev, struct enc_private *k )
++ * static uint16_t GetLatchSource(struct comedi_device *dev, struct enc_private *k )
+  * {
+  * 	return ( DEBIread( dev, k->MyCRB) >> CRBBIT_LATCHSRC ) & 3;
+  * }
+@@ -3061,25 +3061,25 @@ static void SetLatchSource(comedi_device *dev, struct enc_private *k, uint16_t v
+  * 2=OverflowA (B counters only), 3=disabled.
+  */
+ 
+-static void SetLoadTrig_A(comedi_device *dev, struct enc_private *k, uint16_t Trig)
++static void SetLoadTrig_A(struct comedi_device *dev, struct enc_private *k, uint16_t Trig)
+ {
+ 	DEBIreplace(dev, k->MyCRA, (uint16_t) (~CRAMSK_LOADSRC_A),
+ 		(uint16_t) (Trig << CRABIT_LOADSRC_A));
+ }
+ 
+-static void SetLoadTrig_B(comedi_device *dev, struct enc_private *k, uint16_t Trig)
++static void SetLoadTrig_B(struct comedi_device *dev, struct enc_private *k, uint16_t Trig)
+ {
+ 	DEBIreplace(dev, k->MyCRB,
+ 		(uint16_t) (~(CRBMSK_LOADSRC_B | CRBMSK_INTCTRL)),
+ 		(uint16_t) (Trig << CRBBIT_LOADSRC_B));
+ }
+ 
+-static uint16_t GetLoadTrig_A(comedi_device *dev, struct enc_private *k)
++static uint16_t GetLoadTrig_A(struct comedi_device *dev, struct enc_private *k)
+ {
+ 	return (DEBIread(dev, k->MyCRA) >> CRABIT_LOADSRC_A) & 3;
+ }
+ 
+-static uint16_t GetLoadTrig_B(comedi_device *dev, struct enc_private *k)
++static uint16_t GetLoadTrig_B(struct comedi_device *dev, struct enc_private *k)
+ {
+ 	return (DEBIread(dev, k->MyCRB) >> CRBBIT_LOADSRC_B) & 3;
+ }
+@@ -3089,7 +3089,7 @@ static uint16_t GetLoadTrig_B(comedi_device *dev, struct enc_private *k)
+  * 2=IndexOnly, 3=IndexAndOverflow.
+  */
+ 
+-static void SetIntSrc_A(comedi_device *dev, struct enc_private *k,
++static void SetIntSrc_A(struct comedi_device *dev, struct enc_private *k,
+ 	uint16_t IntSource)
+ {
+ 	/*  Reset any pending counter overflow or index captures. */
+@@ -3106,7 +3106,7 @@ static void SetIntSrc_A(comedi_device *dev, struct enc_private *k,
+ 		MyEventBits[IntSource];
+ }
+ 
+-static void SetIntSrc_B(comedi_device *dev, struct enc_private *k,
++static void SetIntSrc_B(struct comedi_device *dev, struct enc_private *k,
+ 	uint16_t IntSource)
+ {
+ 	uint16_t crb;
+@@ -3129,80 +3129,80 @@ static void SetIntSrc_B(comedi_device *dev, struct enc_private *k,
+ 		MyEventBits[IntSource];
+ }
+ 
+-static uint16_t GetIntSrc_A(comedi_device *dev, struct enc_private *k)
++static uint16_t GetIntSrc_A(struct comedi_device *dev, struct enc_private *k)
+ {
+ 	return (DEBIread(dev, k->MyCRA) >> CRABIT_INTSRC_A) & 3;
+ }
+ 
+-static uint16_t GetIntSrc_B(comedi_device *dev, struct enc_private *k)
++static uint16_t GetIntSrc_B(struct comedi_device *dev, struct enc_private *k)
+ {
+ 	return (DEBIread(dev, k->MyCRB) >> CRBBIT_INTSRC_B) & 3;
+ }
+ 
+ /*  Return/set the clock multiplier. */
+ 
+-/* static void SetClkMult(comedi_device *dev, struct enc_private *k, uint16_t value )  */
++/* static void SetClkMult(struct comedi_device *dev, struct enc_private *k, uint16_t value )  */
+ /* { */
+ /*   k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKMULT ) | ( value << STDBIT_CLKMULT ) ), FALSE ); */
+ /* } */
+ 
+-/* static uint16_t GetClkMult(comedi_device *dev, struct enc_private *k )  */
++/* static uint16_t GetClkMult(struct comedi_device *dev, struct enc_private *k )  */
+ /* { */
+ /*   return ( k->GetMode(dev, k ) >> STDBIT_CLKMULT ) & 3; */
+ /* } */
+ 
+ /* Return/set the clock polarity. */
+ 
+-/* static void SetClkPol( comedi_device *dev,struct enc_private *k, uint16_t value )  */
++/* static void SetClkPol( struct comedi_device *dev,struct enc_private *k, uint16_t value )  */
+ /* { */
+ /*   k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKPOL ) | ( value << STDBIT_CLKPOL ) ), FALSE ); */
+ /* } */
+ 
+-/* static uint16_t GetClkPol(comedi_device *dev, struct enc_private *k )  */
++/* static uint16_t GetClkPol(struct comedi_device *dev, struct enc_private *k )  */
+ /* { */
+ /*   return ( k->GetMode(dev, k ) >> STDBIT_CLKPOL ) & 1; */
+ /* } */
+ 
+ /* Return/set the clock source.  */
+ 
+-/* static void SetClkSrc( comedi_device *dev,struct enc_private *k, uint16_t value )  */
++/* static void SetClkSrc( struct comedi_device *dev,struct enc_private *k, uint16_t value )  */
+ /* { */
+ /*   k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKSRC ) | ( value << STDBIT_CLKSRC ) ), FALSE ); */
+ /* } */
+ 
+-/* static uint16_t GetClkSrc( comedi_device *dev,struct enc_private *k )  */
++/* static uint16_t GetClkSrc( struct comedi_device *dev,struct enc_private *k )  */
+ /* { */
+ /*   return ( k->GetMode(dev, k ) >> STDBIT_CLKSRC ) & 3; */
+ /* } */
+ 
+ /* Return/set the index polarity. */
+ 
+-/* static void SetIndexPol(comedi_device *dev, struct enc_private *k, uint16_t value )  */
++/* static void SetIndexPol(struct comedi_device *dev, struct enc_private *k, uint16_t value )  */
+ /* { */
+ /*   k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_INDXPOL ) | ( (value != 0) << STDBIT_INDXPOL ) ), FALSE ); */
+ /* } */
+ 
+-/* static uint16_t GetIndexPol(comedi_device *dev, struct enc_private *k )  */
++/* static uint16_t GetIndexPol(struct comedi_device *dev, struct enc_private *k )  */
+ /* { */
+ /*   return ( k->GetMode(dev, k ) >> STDBIT_INDXPOL ) & 1; */
+ /* } */
+ 
+ /*  Return/set the index source. */
+ 
+-/* static void SetIndexSrc(comedi_device *dev, struct enc_private *k, uint16_t value )  */
++/* static void SetIndexSrc(struct comedi_device *dev, struct enc_private *k, uint16_t value )  */
+ /* { */
+ /*   DEBUG("SetIndexSrc: set index src enter 3700\n"); */
+ /*   k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_INDXSRC ) | ( (value != 0) << STDBIT_INDXSRC ) ), FALSE ); */
+ /* } */
+ 
+-/* static uint16_t GetIndexSrc(comedi_device *dev, struct enc_private *k )  */
++/* static uint16_t GetIndexSrc(struct comedi_device *dev, struct enc_private *k )  */
+ /* { */
+ /*   return ( k->GetMode(dev, k ) >> STDBIT_INDXSRC ) & 1; */
+ /* } */
+ 
+ /*  Generate an index pulse. */
+ 
+-static void PulseIndex_A(comedi_device *dev, struct enc_private *k)
++static void PulseIndex_A(struct comedi_device *dev, struct enc_private *k)
+ {
+ 	register uint16_t cra;
+ 
+@@ -3214,7 +3214,7 @@ static void PulseIndex_A(comedi_device *dev, struct enc_private *k)
+ 	DEBIwrite(dev, k->MyCRA, cra);
+ }
+ 
+-static void PulseIndex_B(comedi_device *dev, struct enc_private *k)
++static void PulseIndex_B(struct comedi_device *dev, struct enc_private *k)
+ {
+ 	register uint16_t crb;
+ 
+@@ -3225,7 +3225,7 @@ static void PulseIndex_B(comedi_device *dev, struct enc_private *k)
+ 
+ /*  Write value into counter preload register. */
+ 
+-static void Preload(comedi_device *dev, struct enc_private *k, uint32_t value)
++static void Preload(struct comedi_device *dev, struct enc_private *k, uint32_t value)
+ {
+ 	DEBUG("Preload: preload enter\n");
+ 	DEBIwrite(dev, (uint16_t) (k->MyLatchLsw), (uint16_t) value);	/*  Write value to preload register. */
+@@ -3234,7 +3234,7 @@ static void Preload(comedi_device *dev, struct enc_private *k, uint32_t value)
+ 		(uint16_t) (value >> 16));
+ }
+ 
+-static void CountersInit(comedi_device *dev)
++static void CountersInit(struct comedi_device *dev)
+ {
+ 	int chan;
+ 	struct enc_private *k;
+diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
+index 65bbf5cb0e9f..d63b657ec0d5 100644
+--- a/drivers/staging/comedi/drivers/serial2002.c
++++ b/drivers/staging/comedi/drivers/serial2002.c
+@@ -85,8 +85,8 @@ typedef struct {
+  */
+ #define devpriv ((serial2002_private *)dev->private)
+ 
+-static int serial2002_attach(comedi_device * dev, comedi_devconfig * it);
+-static int serial2002_detach(comedi_device * dev);
++static int serial2002_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int serial2002_detach(struct comedi_device * dev);
+ comedi_driver driver_serial2002 = {
+       driver_name:"serial2002",
+       module:THIS_MODULE,
+@@ -97,15 +97,15 @@ comedi_driver driver_serial2002 = {
+       num_names:sizeof(serial2002_boards) / sizeof(serial2002_board),
+ };
+ 
+-static int serial2002_di_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int serial2002_di_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int serial2002_do_winsn(comedi_device * dev, comedi_subdevice * s,
++static int serial2002_do_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int serial2002_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int serial2002_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int serial2002_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int serial2002_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int serial2002_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int serial2002_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+ 
+ struct serial_data {
+@@ -389,7 +389,7 @@ static void serial_write(struct file *f, struct serial_data data)
+ 	}
+ }
+ 
+-static void serial_2002_open(comedi_device * dev)
++static void serial_2002_open(struct comedi_device * dev)
+ {
+ 	char port[20];
+ 
+@@ -653,14 +653,14 @@ static void serial_2002_open(comedi_device * dev)
+ 	}
+ }
+ 
+-static void serial_2002_close(comedi_device * dev)
++static void serial_2002_close(struct comedi_device * dev)
+ {
+ 	if (!IS_ERR(devpriv->tty) && (devpriv->tty != 0)) {
+ 		filp_close(devpriv->tty, 0);
+ 	}
+ }
+ 
+-static int serial2002_di_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int serial2002_di_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -682,7 +682,7 @@ static int serial2002_di_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int serial2002_do_winsn(comedi_device * dev, comedi_subdevice * s,
++static int serial2002_do_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -700,7 +700,7 @@ static int serial2002_do_winsn(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int serial2002_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int serial2002_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -722,7 +722,7 @@ static int serial2002_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int serial2002_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int serial2002_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -741,7 +741,7 @@ static int serial2002_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int serial2002_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int serial2002_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -754,7 +754,7 @@ static int serial2002_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int serial2002_ei_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int serial2002_ei_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+@@ -776,7 +776,7 @@ static int serial2002_ei_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int serial2002_attach(comedi_device * dev, comedi_devconfig * it)
++static int serial2002_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 
+@@ -843,7 +843,7 @@ static int serial2002_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 1;
+ }
+ 
+-static int serial2002_detach(comedi_device * dev)
++static int serial2002_detach(struct comedi_device * dev)
+ {
+ 	comedi_subdevice *s;
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c
+index 7a2e0ce409ed..8252349e3af9 100644
+--- a/drivers/staging/comedi/drivers/skel.c
++++ b/drivers/staging/comedi/drivers/skel.c
+@@ -129,7 +129,7 @@ MODULE_DEVICE_TABLE(pci, skel_pci_table);
+ 
+ /* this structure is for data unique to this hardware driver.  If
+    several hardware drivers keep similar information in this structure,
+-   feel free to suggest moving the variable to the comedi_device struct.  */
++   feel free to suggest moving the variable to the struct comedi_device struct.  */
+ typedef struct {
+ 	int data;
+ 
+@@ -151,8 +151,8 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int skel_attach(comedi_device * dev, comedi_devconfig * it);
+-static int skel_detach(comedi_device * dev);
++static int skel_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int skel_detach(struct comedi_device * dev);
+ static comedi_driver driver_skel = {
+       driver_name:"dummy",
+       module:THIS_MODULE,
+@@ -181,17 +181,17 @@ static comedi_driver driver_skel = {
+       num_names:sizeof(skel_boards) / sizeof(skel_board),
+ };
+ 
+-static int skel_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int skel_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int skel_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int skel_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int skel_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int skel_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int skel_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int skel_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int skel_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int skel_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data);
+-static int skel_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int skel_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+ static int skel_ns_to_timer(unsigned int *ns, int round);
+ 
+@@ -201,7 +201,7 @@ static int skel_ns_to_timer(unsigned int *ns, int round);
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int skel_attach(comedi_device * dev, comedi_devconfig * it)
++static int skel_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	comedi_subdevice *s;
+ 
+@@ -287,7 +287,7 @@ static int skel_attach(comedi_device * dev, comedi_devconfig * it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int skel_detach(comedi_device * dev)
++static int skel_detach(struct comedi_device * dev)
+ {
+ 	printk("comedi%d: skel: remove\n", dev->minor);
+ 
+@@ -298,7 +298,7 @@ static int skel_detach(comedi_device * dev)
+  * "instructions" read/write data in "one-shot" or "software-triggered"
+  * mode.
+  */
+-static int skel_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int skel_ai_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i;
+@@ -346,7 +346,7 @@ static int skel_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int skel_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
++static int skel_ai_cmdtest(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd)
+ {
+ 	int err = 0;
+@@ -515,7 +515,7 @@ static int skel_ns_to_timer(unsigned int *ns, int round)
+ 	return *ns;
+ }
+ 
+-static int skel_ao_winsn(comedi_device * dev, comedi_subdevice * s,
++static int skel_ao_winsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -536,7 +536,7 @@ static int skel_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ 
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+-static int skel_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
++static int skel_ao_rinsn(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+@@ -553,7 +553,7 @@ static int skel_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+  * useful to applications if you implement the insn_bits interface.
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+-static int skel_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
++static int skel_dio_insn_bits(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+@@ -578,7 +578,7 @@ static int skel_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int skel_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
++static int skel_dio_insn_config(struct comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c
+index f2465a2bf8e5..2cb08849a6bb 100644
+--- a/drivers/staging/comedi/drivers/ssv_dnp.c
++++ b/drivers/staging/comedi/drivers/ssv_dnp.c
+@@ -87,8 +87,8 @@ typedef struct {
+ /* In the following section we define the API of this driver.                */
+ /* ------------------------------------------------------------------------- */
+ 
+-static int dnp_attach(comedi_device * dev, comedi_devconfig * it);
+-static int dnp_detach(comedi_device * dev);
++static int dnp_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int dnp_detach(struct comedi_device * dev);
+ 
+ static comedi_driver driver_dnp = {
+       driver_name:"ssv_dnp",
+@@ -103,10 +103,10 @@ static comedi_driver driver_dnp = {
+ 
+ COMEDI_INITCLEANUP(driver_dnp);
+ 
+-static int dnp_dio_insn_bits(comedi_device * dev,
++static int dnp_dio_insn_bits(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+-static int dnp_dio_insn_config(comedi_device * dev,
++static int dnp_dio_insn_config(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+ /* ------------------------------------------------------------------------- */
+@@ -115,7 +115,7 @@ static int dnp_dio_insn_config(comedi_device * dev,
+ /* dev->board_ptr contains that address.                                     */
+ /* ------------------------------------------------------------------------- */
+ 
+-static int dnp_attach(comedi_device * dev, comedi_devconfig * it)
++static int dnp_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 
+ 	comedi_subdevice *s;
+@@ -176,7 +176,7 @@ static int dnp_attach(comedi_device * dev, comedi_devconfig * it)
+ /* deallocated automatically by the core.                                    */
+ /* ------------------------------------------------------------------------- */
+ 
+-static int dnp_detach(comedi_device * dev)
++static int dnp_detach(struct comedi_device * dev)
+ {
+ 
+ 	/* configure all ports as input (default)                                  */
+@@ -200,7 +200,7 @@ static int dnp_detach(comedi_device * dev)
+ /* are able to use these instructions as well.                               */
+ /* ------------------------------------------------------------------------- */
+ 
+-static int dnp_dio_insn_bits(comedi_device * dev,
++static int dnp_dio_insn_bits(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 
+@@ -250,7 +250,7 @@ static int dnp_dio_insn_bits(comedi_device * dev,
+ /* COMEDI_INPUT or COMEDI_OUTPUT.                                            */
+ /* ------------------------------------------------------------------------- */
+ 
+-static int dnp_dio_insn_config(comedi_device * dev,
++static int dnp_dio_insn_config(struct comedi_device * dev,
+ 	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 
+diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c
+index 8df437af9dcc..90947cf1dbc4 100644
+--- a/drivers/staging/comedi/drivers/unioxx5.c
++++ b/drivers/staging/comedi/drivers/unioxx5.c
+@@ -80,14 +80,14 @@ typedef struct unioxx5_subd_priv {
+ 	unsigned char usp_prev_cn_val[3];	/* previous channel value */
+ } unioxx5_subd_priv;
+ 
+-static int unioxx5_attach(comedi_device * dev, comedi_devconfig * it);
+-static int unioxx5_subdev_write(comedi_device * dev, comedi_subdevice * subdev,
++static int unioxx5_attach(struct comedi_device * dev, comedi_devconfig * it);
++static int unioxx5_subdev_write(struct comedi_device * dev, comedi_subdevice * subdev,
+ 	comedi_insn * insn, unsigned int * data);
+-static int unioxx5_subdev_read(comedi_device * dev, comedi_subdevice * subdev,
++static int unioxx5_subdev_read(struct comedi_device * dev, comedi_subdevice * subdev,
+ 	comedi_insn * insn, unsigned int * data);
+-static int unioxx5_insn_config(comedi_device * dev, comedi_subdevice * subdev,
++static int unioxx5_insn_config(struct comedi_device * dev, comedi_subdevice * subdev,
+ 	comedi_insn * insn, unsigned int * data);
+-static int unioxx5_detach(comedi_device * dev);
++static int unioxx5_detach(struct comedi_device * dev);
+ static int __unioxx5_subdev_init(comedi_subdevice * subdev, int subdev_iobase,
+ 	int minor);
+ static int __unioxx5_digital_write(unioxx5_subd_priv * usp, unsigned int * data,
+@@ -111,7 +111,7 @@ static comedi_driver unioxx5_driver = {
+ 
+ COMEDI_INITCLEANUP(unioxx5_driver);
+ 
+-static int unioxx5_attach(comedi_device * dev, comedi_devconfig * it)
++static int unioxx5_attach(struct comedi_device * dev, comedi_devconfig * it)
+ {
+ 	int iobase, i, n_subd;
+ 	int id, num, ba;
+@@ -156,7 +156,7 @@ static int unioxx5_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int unioxx5_subdev_read(comedi_device * dev, comedi_subdevice * subdev,
++static int unioxx5_subdev_read(struct comedi_device * dev, comedi_subdevice * subdev,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unioxx5_subd_priv *usp = subdev->private;
+@@ -176,7 +176,7 @@ static int unioxx5_subdev_read(comedi_device * dev, comedi_subdevice * subdev,
+ 	return 1;
+ }
+ 
+-static int unioxx5_subdev_write(comedi_device * dev, comedi_subdevice * subdev,
++static int unioxx5_subdev_write(struct comedi_device * dev, comedi_subdevice * subdev,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	unioxx5_subd_priv *usp = subdev->private;
+@@ -197,7 +197,7 @@ static int unioxx5_subdev_write(comedi_device * dev, comedi_subdevice * subdev,
+ }
+ 
+ /* for digital modules only */
+-static int unioxx5_insn_config(comedi_device * dev, comedi_subdevice * subdev,
++static int unioxx5_insn_config(struct comedi_device * dev, comedi_subdevice * subdev,
+ 	comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel_offset, flags, channel = CR_CHAN(insn->chanspec), type;
+@@ -247,7 +247,7 @@ static int unioxx5_insn_config(comedi_device * dev, comedi_subdevice * subdev,
+ 	return 0;
+ }
+ 
+-static int unioxx5_detach(comedi_device * dev)
++static int unioxx5_detach(struct comedi_device * dev)
+ {
+ 	int i;
+ 	comedi_subdevice *subdev;
+diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
+index 68566295443a..c433076c0e47 100644
+--- a/drivers/staging/comedi/drivers/usbdux.c
++++ b/drivers/staging/comedi/drivers/usbdux.c
+@@ -269,7 +269,7 @@ struct usbduxsub {
+ 	/* interface structure in 2.6 */
+ 	struct usb_interface *interface;
+ 	/* comedi device for the interrupt context */
+-	comedi_device *comedidev;
++	struct comedi_device *comedidev;
+ 	/* is it USB_SPEED_HIGH or not? */
+ 	short int high_speed;
+ 	/* asynchronous command is running */
+@@ -363,7 +363,7 @@ static int usbdux_ai_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
+  * This will cancel a running acquisition operation.
+  * This is called by comedi but never from inside the driver.
+  */
+-static int usbdux_ai_cancel(comedi_device *dev, comedi_subdevice *s)
++static int usbdux_ai_cancel(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 	struct usbduxsub *this_usbduxsub;
+ 	int res = 0;
+@@ -392,7 +392,7 @@ static void usbduxsub_ai_IsocIrq(struct urb *urb)
+ {
+ 	int i, err, n;
+ 	struct usbduxsub *this_usbduxsub;
+-	comedi_device *this_comedidev;
++	struct comedi_device *this_comedidev;
+ 	comedi_subdevice *s;
+ 
+ 	/* the context variable points to the subdevice */
+@@ -561,7 +561,7 @@ static int usbdux_ao_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
+ }
+ 
+ /* force unlink, is called by comedi */
+-static int usbdux_ao_cancel(comedi_device *dev, comedi_subdevice *s)
++static int usbdux_ao_cancel(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+ 	int res = 0;
+@@ -586,7 +586,7 @@ static void usbduxsub_ao_IsocIrq(struct urb *urb)
+ 	int i, ret;
+ 	int8_t *datap;
+ 	struct usbduxsub *this_usbduxsub;
+-	comedi_device *this_comedidev;
++	struct comedi_device *this_comedidev;
+ 	comedi_subdevice *s;
+ 
+ 	/* the context variable points to the subdevice */
+@@ -896,7 +896,7 @@ static int usbduxsub_submit_OutURBs(struct usbduxsub *usbduxsub)
+ 	return 0;
+ }
+ 
+-static int usbdux_ai_cmdtest(comedi_device *dev, comedi_subdevice *s,
++static int usbdux_ai_cmdtest(struct comedi_device *dev, comedi_subdevice *s,
+ 			     comedi_cmd *cmd)
+ {
+ 	int err = 0, tmp, i;
+@@ -1116,7 +1116,7 @@ static int receive_dux_commands(struct usbduxsub *this_usbduxsub, int command)
+ 	return -EFAULT;
+ }
+ 
+-static int usbdux_ai_inttrig(comedi_device *dev, comedi_subdevice *s,
++static int usbdux_ai_inttrig(struct comedi_device *dev, comedi_subdevice *s,
+ 			     unsigned int trignum)
+ {
+ 	int ret;
+@@ -1160,7 +1160,7 @@ static int usbdux_ai_inttrig(comedi_device *dev, comedi_subdevice *s,
+ 	return 1;
+ }
+ 
+-static int usbdux_ai_cmd(comedi_device *dev, comedi_subdevice *s)
++static int usbdux_ai_cmd(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned int chan, range;
+@@ -1276,7 +1276,7 @@ static int usbdux_ai_cmd(comedi_device *dev, comedi_subdevice *s)
+ }
+ 
+ /* Mode 0 is used to get a single conversion on demand */
+-static int usbdux_ai_insn_read(comedi_device *dev, comedi_subdevice *s,
++static int usbdux_ai_insn_read(struct comedi_device *dev, comedi_subdevice *s,
+ 			       comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+@@ -1337,7 +1337,7 @@ static int usbdux_ai_insn_read(comedi_device *dev, comedi_subdevice *s,
+ /************************************/
+ /* analog out */
+ 
+-static int usbdux_ao_insn_read(comedi_device *dev, comedi_subdevice *s,
++static int usbdux_ao_insn_read(struct comedi_device *dev, comedi_subdevice *s,
+ 			       comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+@@ -1359,7 +1359,7 @@ static int usbdux_ao_insn_read(comedi_device *dev, comedi_subdevice *s,
+ 	return i;
+ }
+ 
+-static int usbdux_ao_insn_write(comedi_device *dev, comedi_subdevice *s,
++static int usbdux_ao_insn_write(struct comedi_device *dev, comedi_subdevice *s,
+ 				comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, err;
+@@ -1409,7 +1409,7 @@ static int usbdux_ao_insn_write(comedi_device *dev, comedi_subdevice *s,
+ 	return i;
+ }
+ 
+-static int usbdux_ao_inttrig(comedi_device *dev, comedi_subdevice *s,
++static int usbdux_ao_inttrig(struct comedi_device *dev, comedi_subdevice *s,
+ 			     unsigned int trignum)
+ {
+ 	int ret;
+@@ -1450,7 +1450,7 @@ static int usbdux_ao_inttrig(comedi_device *dev, comedi_subdevice *s,
+ 	return 1;
+ }
+ 
+-static int usbdux_ao_cmdtest(comedi_device *dev, comedi_subdevice *s,
++static int usbdux_ao_cmdtest(struct comedi_device *dev, comedi_subdevice *s,
+ 			     comedi_cmd *cmd)
+ {
+ 	int err = 0, tmp;
+@@ -1589,7 +1589,7 @@ static int usbdux_ao_cmdtest(comedi_device *dev, comedi_subdevice *s,
+ 	return 0;
+ }
+ 
+-static int usbdux_ao_cmd(comedi_device *dev, comedi_subdevice *s)
++static int usbdux_ao_cmd(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned int chan, gain;
+@@ -1697,7 +1697,7 @@ static int usbdux_ao_cmd(comedi_device *dev, comedi_subdevice *s)
+ 	return 0;
+ }
+ 
+-static int usbdux_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
++static int usbdux_dio_insn_config(struct comedi_device *dev, comedi_subdevice *s,
+ 				  comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -1728,7 +1728,7 @@ static int usbdux_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
+ 	return insn->n;
+ }
+ 
+-static int usbdux_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
++static int usbdux_dio_insn_bits(struct comedi_device *dev, comedi_subdevice *s,
+ 				comedi_insn *insn, unsigned int *data)
+ {
+ 
+@@ -1775,7 +1775,7 @@ static int usbdux_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ /* reads the 4 counters, only two are used just now */
+-static int usbdux_counter_read(comedi_device *dev, comedi_subdevice *s,
++static int usbdux_counter_read(struct comedi_device *dev, comedi_subdevice *s,
+ 			       comedi_insn *insn, unsigned int *data)
+ {
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+@@ -1809,7 +1809,7 @@ static int usbdux_counter_read(comedi_device *dev, comedi_subdevice *s,
+ 	return 1;
+ }
+ 
+-static int usbdux_counter_write(comedi_device *dev, comedi_subdevice *s,
++static int usbdux_counter_write(struct comedi_device *dev, comedi_subdevice *s,
+ 				comedi_insn *insn, unsigned int *data)
+ {
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+@@ -1839,7 +1839,7 @@ static int usbdux_counter_write(comedi_device *dev, comedi_subdevice *s,
+ 	return 1;
+ }
+ 
+-static int usbdux_counter_config(comedi_device *dev, comedi_subdevice *s,
++static int usbdux_counter_config(struct comedi_device *dev, comedi_subdevice *s,
+ 				 comedi_insn *insn, unsigned int *data)
+ {
+ 	/* nothing to do so far */
+@@ -1883,7 +1883,7 @@ static int usbdux_pwm_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
+ }
+ 
+ /* force unlink - is called by comedi */
+-static int usbdux_pwm_cancel(comedi_device *dev, comedi_subdevice *s)
++static int usbdux_pwm_cancel(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+ 	int res = 0;
+@@ -1905,7 +1905,7 @@ static void usbduxsub_pwm_irq(struct urb *urb)
+ {
+ 	int ret;
+ 	struct usbduxsub *this_usbduxsub;
+-	comedi_device *this_comedidev;
++	struct comedi_device *this_comedidev;
+ 	comedi_subdevice *s;
+ 
+ 	/* printk(KERN_DEBUG "PWM: IRQ\n"); */
+@@ -1996,7 +1996,7 @@ static int usbduxsub_submit_PwmURBs(struct usbduxsub *usbduxsub)
+ 	return 0;
+ }
+ 
+-static int usbdux_pwm_period(comedi_device *dev, comedi_subdevice *s,
++static int usbdux_pwm_period(struct comedi_device *dev, comedi_subdevice *s,
+ 			     unsigned int period)
+ {
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+@@ -2024,7 +2024,7 @@ static int usbdux_pwm_period(comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ /* is called from insn so there's no need to do all the sanity checks */
+-static int usbdux_pwm_start(comedi_device *dev, comedi_subdevice *s)
++static int usbdux_pwm_start(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 	int ret, i;
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+@@ -2056,7 +2056,7 @@ static int usbdux_pwm_start(comedi_device *dev, comedi_subdevice *s)
+ }
+ 
+ /* generates the bit pattern for PWM with the optional sign bit */
+-static int usbdux_pwm_pattern(comedi_device *dev, comedi_subdevice *s,
++static int usbdux_pwm_pattern(struct comedi_device *dev, comedi_subdevice *s,
+ 			      int channel, unsigned int value, unsigned int sign)
+ {
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+@@ -2097,7 +2097,7 @@ static int usbdux_pwm_pattern(comedi_device *dev, comedi_subdevice *s,
+ 	return 1;
+ }
+ 
+-static int usbdux_pwm_write(comedi_device *dev, comedi_subdevice *s,
++static int usbdux_pwm_write(struct comedi_device *dev, comedi_subdevice *s,
+ 			    comedi_insn *insn, unsigned int *data)
+ {
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+@@ -2122,7 +2122,7 @@ static int usbdux_pwm_write(comedi_device *dev, comedi_subdevice *s,
+ 				  data[0], 0);
+ }
+ 
+-static int usbdux_pwm_read(comedi_device *x1, comedi_subdevice *x2,
++static int usbdux_pwm_read(struct comedi_device *x1, comedi_subdevice *x2,
+ 			   comedi_insn *x3, unsigned int *x4)
+ {
+ 	/* not needed */
+@@ -2130,7 +2130,7 @@ static int usbdux_pwm_read(comedi_device *x1, comedi_subdevice *x2,
+ };
+ 
+ /* switches on/off PWM */
+-static int usbdux_pwm_config(comedi_device *dev, comedi_subdevice *s,
++static int usbdux_pwm_config(struct comedi_device *dev, comedi_subdevice *s,
+ 			     comedi_insn *insn, unsigned int *data)
+ {
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+@@ -2703,7 +2703,7 @@ static void usbduxsub_disconnect(struct usb_interface *intf)
+ }
+ 
+ /* is called when comedi-config is called */
+-static int usbdux_attach(comedi_device *dev, comedi_devconfig *it)
++static int usbdux_attach(struct comedi_device *dev, comedi_devconfig *it)
+ {
+ 	int ret;
+ 	int index;
+@@ -2870,7 +2870,7 @@ static int usbdux_attach(comedi_device *dev, comedi_devconfig *it)
+ 	return 0;
+ }
+ 
+-static int usbdux_detach(comedi_device *dev)
++static int usbdux_detach(struct comedi_device *dev)
+ {
+ 	struct usbduxsub *usbduxsub_tmp;
+ 
+diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c
+index aa21914318c8..ff4a546a157a 100644
+--- a/drivers/staging/comedi/drivers/usbduxfast.c
++++ b/drivers/staging/comedi/drivers/usbduxfast.c
+@@ -179,7 +179,7 @@ struct usbduxfastsub_s {
+ 	int16_t *insnBuffer;		/* input buffer for single insn */
+ 	int ifnum;			/* interface number */
+ 	struct usb_interface *interface;	/* interface structure */
+-	comedi_device *comedidev;	/* comedi device for the interrupt
++	struct comedi_device *comedidev;	/* comedi device for the interrupt
+ 					   context */
+ 	short int ai_cmd_running;	/* asynchronous command is running */
+ 	short int ai_continous;		/* continous aquisition */
+@@ -284,7 +284,7 @@ static int usbduxfast_ai_stop(struct usbduxfastsub_s *udfs,
+  * This will cancel a running acquisition operation.
+  * This is called by comedi but never from inside the driver.
+  */
+-static int usbduxfast_ai_cancel(comedi_device *dev, comedi_subdevice *s)
++static int usbduxfast_ai_cancel(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 	struct usbduxfastsub_s *udfs;
+ 	int ret;
+@@ -318,7 +318,7 @@ static void usbduxfastsub_ai_Irq(struct urb *urb PT_REGS_ARG)
+ {
+ 	int n, err;
+ 	struct usbduxfastsub_s *udfs;
+-	comedi_device *this_comedidev;
++	struct comedi_device *this_comedidev;
+ 	comedi_subdevice *s;
+ 	uint16_t *p;
+ 
+@@ -577,7 +577,7 @@ int usbduxfastsub_submit_InURBs(struct usbduxfastsub_s *udfs)
+ 	return 0;
+ }
+ 
+-static int usbduxfast_ai_cmdtest(comedi_device *dev,
++static int usbduxfast_ai_cmdtest(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_cmd *cmd)
+ {
+ 	int err = 0, stop_mask = 0;
+@@ -719,7 +719,7 @@ static int usbduxfast_ai_cmdtest(comedi_device *dev,
+ 
+ }
+ 
+-static int usbduxfast_ai_inttrig(comedi_device *dev,
++static int usbduxfast_ai_inttrig(struct comedi_device *dev,
+ 	comedi_subdevice *s, unsigned int trignum)
+ {
+ 	int ret;
+@@ -771,7 +771,7 @@ static int usbduxfast_ai_inttrig(comedi_device *dev,
+ #define OUTBASE	(1+0x10)
+ #define LOGBASE	(1+0x18)
+ 
+-static int usbduxfast_ai_cmd(comedi_device *dev, comedi_subdevice *s)
++static int usbduxfast_ai_cmd(struct comedi_device *dev, comedi_subdevice *s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned int chan, gain, rngmask = 0xff;
+@@ -1230,7 +1230,7 @@ static int usbduxfast_ai_cmd(comedi_device *dev, comedi_subdevice *s)
+ /*
+  * Mode 0 is used to get a single conversion on demand.
+  */
+-static int usbduxfast_ai_insn_read(comedi_device *dev,
++static int usbduxfast_ai_insn_read(struct comedi_device *dev,
+ 	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, j, n, actual_length;
+@@ -1715,7 +1715,7 @@ static void usbduxfastsub_disconnect(struct usb_interface *intf)
+ /*
+  * is called when comedi-config is called
+  */
+-static int usbduxfast_attach(comedi_device *dev, comedi_devconfig *it)
++static int usbduxfast_attach(struct comedi_device *dev, comedi_devconfig *it)
+ {
+ 	int ret;
+ 	int index;
+@@ -1813,7 +1813,7 @@ static int usbduxfast_attach(comedi_device *dev, comedi_devconfig *it)
+ 	return 0;
+ }
+ 
+-static int usbduxfast_detach(comedi_device *dev)
++static int usbduxfast_detach(struct comedi_device *dev)
+ {
+ 	struct usbduxfastsub_s *udfs;
+ 
+diff --git a/drivers/staging/comedi/kcomedilib/get.c b/drivers/staging/comedi/kcomedilib/get.c
+index 4bb32593a79d..257cf8c25564 100644
+--- a/drivers/staging/comedi/kcomedilib/get.c
++++ b/drivers/staging/comedi/kcomedilib/get.c
+@@ -28,7 +28,7 @@
+ 
+ int comedi_get_n_subdevices(void *d)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 
+ 	return dev->n_subdevices;
+ }
+@@ -40,21 +40,21 @@ int comedi_get_version_code(void *d)
+ 
+ const char *comedi_get_driver_name(void * d)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 
+ 	return dev->driver->driver_name;
+ }
+ 
+ const char *comedi_get_board_name(void * d)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 
+ 	return dev->board_name;
+ }
+ 
+ int comedi_get_subdevice_type(void *d, unsigned int subdevice)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+ 
+ 	return s->type;
+@@ -62,7 +62,7 @@ int comedi_get_subdevice_type(void *d, unsigned int subdevice)
+ 
+ unsigned int comedi_get_subdevice_flags(void *d, unsigned int subdevice)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+ 
+ 	return s->subdev_flags;
+@@ -70,7 +70,7 @@ unsigned int comedi_get_subdevice_flags(void *d, unsigned int subdevice)
+ 
+ int comedi_find_subdevice_by_type(void *d, int type, unsigned int subd)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 
+ 	if (subd > dev->n_subdevices)
+ 		return -ENODEV;
+@@ -84,7 +84,7 @@ int comedi_find_subdevice_by_type(void *d, int type, unsigned int subd)
+ 
+ int comedi_get_n_channels(void *d, unsigned int subdevice)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+ 
+ 	return s->n_chan;
+@@ -92,7 +92,7 @@ int comedi_get_n_channels(void *d, unsigned int subdevice)
+ 
+ int comedi_get_len_chanlist(void *d, unsigned int subdevice)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+ 
+ 	return s->len_chanlist;
+@@ -101,7 +101,7 @@ int comedi_get_len_chanlist(void *d, unsigned int subdevice)
+ unsigned int comedi_get_maxdata(void *d, unsigned int subdevice,
+ 	unsigned int chan)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+ 
+ 	if (s->maxdata_list)
+@@ -114,7 +114,7 @@ unsigned int comedi_get_maxdata(void *d, unsigned int subdevice,
+ int comedi_get_rangetype(void *d, unsigned int subdevice,
+ 	unsigned int chan)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+ 	int ret;
+ 
+@@ -132,7 +132,7 @@ int comedi_get_rangetype(void *d, unsigned int subdevice,
+ 
+ int comedi_get_n_ranges(void *d, unsigned int subdevice, unsigned int chan)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+ 	int ret;
+ 
+@@ -151,7 +151,7 @@ int comedi_get_n_ranges(void *d, unsigned int subdevice, unsigned int chan)
+ int comedi_get_krange(void *d, unsigned int subdevice, unsigned int chan,
+ 	unsigned int range, comedi_krange *krange)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+ 	const comedi_lrange *lr;
+ 
+@@ -173,7 +173,7 @@ int comedi_get_krange(void *d, unsigned int subdevice, unsigned int chan,
+ */
+ unsigned int comedi_get_buf_head_pos(void *d, unsigned int subdevice)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+ 	comedi_async *async;
+ 
+@@ -186,7 +186,7 @@ unsigned int comedi_get_buf_head_pos(void *d, unsigned int subdevice)
+ 
+ int comedi_get_buffer_contents(void *d, unsigned int subdevice)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+ 	comedi_async *async;
+ 	unsigned int num_bytes;
+@@ -206,7 +206,7 @@ int comedi_get_buffer_contents(void *d, unsigned int subdevice)
+ int comedi_set_user_int_count(void *d, unsigned int subdevice,
+ 	unsigned int buf_user_count)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+ 	comedi_async *async;
+ 	int num_bytes;
+@@ -227,7 +227,7 @@ int comedi_set_user_int_count(void *d, unsigned int subdevice,
+ int comedi_mark_buffer_read(void *d, unsigned int subdevice,
+ 	unsigned int num_bytes)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+ 	comedi_async *async;
+ 
+@@ -246,7 +246,7 @@ int comedi_mark_buffer_read(void *d, unsigned int subdevice,
+ int comedi_mark_buffer_written(void *d, unsigned int subdevice,
+ 	unsigned int num_bytes)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+ 	comedi_async *async;
+ 	int bytes_written;
+@@ -265,7 +265,7 @@ int comedi_mark_buffer_written(void *d, unsigned int subdevice,
+ 
+ int comedi_get_buffer_size(void *d, unsigned int subdev)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdev;
+ 	comedi_async *async;
+ 
+@@ -280,7 +280,7 @@ int comedi_get_buffer_size(void *d, unsigned int subdev)
+ 
+ int comedi_get_buffer_offset(void *d, unsigned int subdevice)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+ 	comedi_async *async;
+ 
+diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+index 0320a0ce74e9..98ddbb61ac01 100644
+--- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
++++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+@@ -45,7 +45,7 @@ MODULE_LICENSE("GPL");
+ void *comedi_open(const char *filename)
+ {
+ 	struct comedi_device_file_info *dev_file_info;
+-	comedi_device *dev;
++	struct comedi_device *dev;
+ 	unsigned int minor;
+ 
+ 	if (strncmp(filename, "/dev/comedi", 11) != 0)
+@@ -73,7 +73,7 @@ void *comedi_open(const char *filename)
+ void *comedi_open_old(unsigned int minor)
+ {
+ 	struct comedi_device_file_info *dev_file_info;
+-	comedi_device *dev;
++	struct comedi_device *dev;
+ 
+ 	if (minor >= COMEDI_NUM_MINORS)
+ 		return NULL;
+@@ -91,7 +91,7 @@ void *comedi_open_old(unsigned int minor)
+ 
+ int comedi_close(void *d)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 
+ 	module_put(dev->driver->module);
+ 
+@@ -115,7 +115,7 @@ char *comedi_strerror(int err)
+ 
+ int comedi_fileno(void *d)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 
+ 	/* return something random */
+ 	return dev->minor;
+@@ -123,7 +123,7 @@ int comedi_fileno(void *d)
+ 
+ int comedi_command(void *d, comedi_cmd *cmd)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s;
+ 	comedi_async *async;
+ 	unsigned runflags;
+@@ -163,7 +163,7 @@ int comedi_command(void *d, comedi_cmd *cmd)
+ 
+ int comedi_command_test(void *d, comedi_cmd *cmd)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s;
+ 
+ 	if (cmd->subdev >= dev->n_subdevices)
+@@ -185,7 +185,7 @@ int comedi_command_test(void *d, comedi_cmd *cmd)
+  */
+ int comedi_do_insn(void *d, comedi_insn *insn)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s;
+ 	int ret = 0;
+ 
+@@ -326,7 +326,7 @@ int comedi_do_insn(void *d, comedi_insn *insn)
+ */
+ int comedi_lock(void *d, unsigned int subdevice)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s;
+ 	unsigned long flags;
+ 	int ret = 0;
+@@ -369,7 +369,7 @@ int comedi_lock(void *d, unsigned int subdevice)
+ */
+ int comedi_unlock(void *d, unsigned int subdevice)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s;
+ 	unsigned long flags;
+ 	comedi_async *async;
+@@ -421,7 +421,7 @@ int comedi_unlock(void *d, unsigned int subdevice)
+ */
+ int comedi_cancel(void *d, unsigned int subdevice)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s;
+ 	int ret = 0;
+ 
+@@ -467,7 +467,7 @@ int comedi_cancel(void *d, unsigned int subdevice)
+ int comedi_register_callback(void *d, unsigned int subdevice,
+ 	unsigned int mask, int (*cb) (unsigned int, void *), void *arg)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s;
+ 	comedi_async *async;
+ 
+@@ -503,7 +503,7 @@ int comedi_register_callback(void *d, unsigned int subdevice,
+ 
+ int comedi_poll(void *d, unsigned int subdevice)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices;
+ 	comedi_async *async;
+ 
+@@ -530,7 +530,7 @@ int comedi_poll(void *d, unsigned int subdevice)
+ /* WARNING: not portable */
+ int comedi_map(void *d, unsigned int subdevice, void *ptr)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s;
+ 
+ 	if (subdevice >= dev->n_subdevices)
+@@ -552,7 +552,7 @@ int comedi_map(void *d, unsigned int subdevice, void *ptr)
+ /* WARNING: not portable */
+ int comedi_unmap(void *d, unsigned int subdevice)
+ {
+-	comedi_device *dev = (comedi_device *) d;
++	struct comedi_device *dev = (struct comedi_device *) d;
+ 	comedi_subdevice *s;
+ 
+ 	if (subdevice >= dev->n_subdevices)
+diff --git a/drivers/staging/comedi/proc.c b/drivers/staging/comedi/proc.c
+index 6a1efa86ae97..bb208f852a00 100644
+--- a/drivers/staging/comedi/proc.c
++++ b/drivers/staging/comedi/proc.c
+@@ -53,7 +53,7 @@ int comedi_read_procmem(char *buf, char **start, off_t offset, int len,
+ 
+ 	for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) {
+ 		struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(i);
+-		comedi_device *dev;
++		struct comedi_device *dev;
+ 
+ 		if (dev_file_info == NULL)
+ 			continue;
+diff --git a/drivers/staging/comedi/range.c b/drivers/staging/comedi/range.c
+index e54be6182eea..7e069fd2ba5c 100644
+--- a/drivers/staging/comedi/range.c
++++ b/drivers/staging/comedi/range.c
+@@ -44,7 +44,7 @@ const comedi_lrange range_unknown = { 1, {{0, 1000000, UNIT_none}} };
+ 	writes:
+ 		n comedi_krange structures to rangeinfo->range_ptr
+ */
+-int do_rangeinfo_ioctl(comedi_device *dev, comedi_rangeinfo *arg)
++int do_rangeinfo_ioctl(struct comedi_device *dev, comedi_rangeinfo *arg)
+ {
+ 	comedi_rangeinfo it;
+ 	int subd, chan;
+diff --git a/drivers/staging/comedi/rt.c b/drivers/staging/comedi/rt.c
+index fa99d6942b45..e9f5777595ab 100644
+--- a/drivers/staging/comedi/rt.c
++++ b/drivers/staging/comedi/rt.c
+@@ -57,7 +57,7 @@ struct comedi_irq_struct {
+ 	 irqreturn_t(*handler) (int irq, void *dev_id PT_REGS_ARG);
+ 	unsigned long flags;
+ 	const char *device;
+-	comedi_device *dev_id;
++	struct comedi_device *dev_id;
+ };
+ 
+ static int comedi_rt_get_irq(struct comedi_irq_struct *it);
+@@ -67,7 +67,7 @@ static struct comedi_irq_struct *comedi_irqs[NR_IRQS];
+ 
+ int comedi_request_irq(unsigned irq, irqreturn_t(*handler) (int,
+ 		void *PT_REGS_ARG), unsigned long flags, const char *device,
+-	comedi_device *dev_id)
++	struct comedi_device *dev_id)
+ {
+ 	struct comedi_irq_struct *it;
+ 	int ret;
+@@ -102,7 +102,7 @@ int comedi_request_irq(unsigned irq, irqreturn_t(*handler) (int,
+ 	return 0;
+ }
+ 
+-void comedi_free_irq(unsigned int irq, comedi_device *dev_id)
++void comedi_free_irq(unsigned int irq, struct comedi_device *dev_id)
+ {
+ 	struct comedi_irq_struct *it;
+ 
+@@ -121,7 +121,7 @@ void comedi_free_irq(unsigned int irq, comedi_device *dev_id)
+ 	comedi_irqs[irq] = NULL;
+ }
+ 
+-int comedi_switch_to_rt(comedi_device *dev)
++int comedi_switch_to_rt(struct comedi_device *dev)
+ {
+ 	struct comedi_irq_struct *it;
+ 	unsigned long flags;
+@@ -145,7 +145,7 @@ int comedi_switch_to_rt(comedi_device *dev)
+ 	return 0;
+ }
+ 
+-void comedi_switch_to_non_rt(comedi_device *dev)
++void comedi_switch_to_non_rt(struct comedi_device *dev)
+ {
+ 	struct comedi_irq_struct *it;
+ 	unsigned long flags;

commit 790c55415aa31f4c732729f94d2c3a54f7d3bfc2
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:05:02 2009 -0400
+
+    Staging: comedi: Remove lsampl_t and sampl_t typedefs
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
+index 14b376c8e800..665dbc7de003 100644
+--- a/drivers/staging/comedi/comedi.h
++++ b/drivers/staging/comedi/comedi.h
+@@ -57,9 +57,6 @@ extern "C" {
+ /* max length of device and driver names */
+ #define COMEDI_NAMELEN 20
+ 
+-	typedef unsigned int lsampl_t;
+-	typedef unsigned short sampl_t;
+-
+ /* packs and unpacks a channel/range number */
+ 
+ #define CR_PACK(chan, rng, aref)		((((aref)&0x3)<<24) | (((rng)&0xff)<<16) | (chan))
+@@ -332,7 +329,7 @@ struct comedi_trig_struct {
+ 	unsigned int flags;
+ 	unsigned int n_chan;	/* number of channels */
+ 	unsigned int *chanlist;	/* channel/range list */
+-	sampl_t *data;	/* data list, size depends on subd flags */
++	short *data;	/* data list, size depends on subd flags */
+ 	unsigned int n;	/* number of scans */
+ 	unsigned int trigsrc;
+ 	unsigned int trigvar;
+@@ -344,7 +341,7 @@ struct comedi_trig_struct {
+ struct comedi_insn_struct {
+ 	unsigned int insn;
+ 	unsigned int n;
+-	lsampl_t *data;
++	unsigned int *data;
+ 	unsigned int subdev;
+ 	unsigned int chanspec;
+ 	unsigned int unused[3];
+@@ -377,13 +374,13 @@ struct comedi_cmd_struct {
+ 	unsigned int *chanlist;	/* channel/range list */
+ 	unsigned int chanlist_len;
+ 
+-	sampl_t *data;	/* data list, size depends on subd flags */
++	short *data;	/* data list, size depends on subd flags */
+ 	unsigned int data_len;
+ };
+ 
+ struct comedi_chaninfo_struct {
+ 	unsigned int subdev;
+-	lsampl_t *maxdata_list;
++	unsigned int *maxdata_list;
+ 	unsigned int *flaglist;
+ 	unsigned int *rangelist;
+ 	unsigned int unused[4];
+@@ -407,7 +404,7 @@ struct comedi_subdinfo_struct {
+ 	unsigned int subd_flags;
+ 	unsigned int timer_type;
+ 	unsigned int len_chanlist;
+-	lsampl_t maxdata;
++	unsigned int maxdata;
+ 	unsigned int flags;	/* channel flags */
+ 	unsigned int range_type;	/* lookup in kernel */
+ 	unsigned int settling_time_0;
+diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c
+index 600060ed73dd..ef3caa9d0e02 100644
+--- a/drivers/staging/comedi/comedi_compat32.c
++++ b/drivers/staging/comedi/comedi_compat32.c
+@@ -50,7 +50,7 @@
+ 
+ struct comedi32_chaninfo_struct {
+ 	unsigned int subdev;
+-	compat_uptr_t maxdata_list;	/* 32-bit 'lsampl_t *' */
++	compat_uptr_t maxdata_list;	/* 32-bit 'unsigned int *' */
+ 	compat_uptr_t flaglist;		/* 32-bit 'unsigned int *' */
+ 	compat_uptr_t rangelist;	/* 32-bit 'unsigned int *' */
+ 	unsigned int unused[4];
+@@ -76,14 +76,14 @@ struct comedi32_cmd_struct {
+ 	unsigned int stop_arg;
+ 	compat_uptr_t chanlist;		/* 32-bit 'unsigned int *' */
+ 	unsigned int chanlist_len;
+-	compat_uptr_t data;		/* 32-bit 'sampl_t *' */
++	compat_uptr_t data;		/* 32-bit 'short *' */
+ 	unsigned int data_len;
+ };
+ 
+ struct comedi32_insn_struct {
+ 	unsigned int insn;
+ 	unsigned int n;
+-	compat_uptr_t data;		/* 32-bit 'lsampl_t *' */
++	compat_uptr_t data;		/* 32-bit 'unsigned int *' */
+ 	unsigned int subdev;
+ 	unsigned int chanspec;
+ 	unsigned int unused[3];
+diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
+index fa5ef2ee4eda..82bb66994e17 100644
+--- a/drivers/staging/comedi/comedi_fops.c
++++ b/drivers/staging/comedi/comedi_fops.c
+@@ -506,7 +506,7 @@ static int do_chaninfo_ioctl(comedi_device *dev, comedi_chaninfo *arg)
+ 		if (s->maxdata || !s->maxdata_list)
+ 			return -EINVAL;
+ 		if (copy_to_user(it.maxdata_list, s->maxdata_list,
+-				 s->n_chan * sizeof(lsampl_t)))
++				 s->n_chan * sizeof(unsigned int)))
+ 			return -EFAULT;
+ 	}
+ 
+@@ -607,7 +607,7 @@ static int do_bufinfo_ioctl(comedi_device *dev, void *arg)
+ 	return 0;
+ }
+ 
+-static int parse_insn(comedi_device *dev, comedi_insn *insn, lsampl_t *data,
++static int parse_insn(comedi_device *dev, comedi_insn *insn, unsigned int *data,
+ 		      void *file);
+ /*
+  * 	COMEDI_INSNLIST
+@@ -630,14 +630,14 @@ static int do_insnlist_ioctl(comedi_device *dev, void *arg, void *file)
+ {
+ 	comedi_insnlist insnlist;
+ 	comedi_insn *insns = NULL;
+-	lsampl_t *data = NULL;
++	unsigned int *data = NULL;
+ 	int i = 0;
+ 	int ret = 0;
+ 
+ 	if (copy_from_user(&insnlist, arg, sizeof(comedi_insnlist)))
+ 		return -EFAULT;
+ 
+-	data = kmalloc(sizeof(lsampl_t) * MAX_SAMPLES, GFP_KERNEL);
++	data = kmalloc(sizeof(unsigned int) * MAX_SAMPLES, GFP_KERNEL);
+ 	if (!data) {
+ 		DPRINTK("kmalloc failed\n");
+ 		ret = -ENOMEM;
+@@ -666,7 +666,7 @@ static int do_insnlist_ioctl(comedi_device *dev, void *arg, void *file)
+ 		}
+ 		if (insns[i].insn & INSN_MASK_WRITE) {
+ 			if (copy_from_user(data, insns[i].data,
+-					   insns[i].n * sizeof(lsampl_t))) {
++					   insns[i].n * sizeof(unsigned int))) {
+ 				DPRINTK("copy_from_user failed\n");
+ 				ret = -EFAULT;
+ 				goto error;
+@@ -677,7 +677,7 @@ static int do_insnlist_ioctl(comedi_device *dev, void *arg, void *file)
+ 			goto error;
+ 		if (insns[i].insn & INSN_MASK_READ) {
+ 			if (copy_to_user(insns[i].data, data,
+-					 insns[i].n * sizeof(lsampl_t))) {
++					 insns[i].n * sizeof(unsigned int))) {
+ 				DPRINTK("copy_to_user failed\n");
+ 				ret = -EFAULT;
+ 				goto error;
+@@ -696,7 +696,7 @@ static int do_insnlist_ioctl(comedi_device *dev, void *arg, void *file)
+ 	return i;
+ }
+ 
+-static int check_insn_config_length(comedi_insn *insn, lsampl_t *data)
++static int check_insn_config_length(comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n < 1)
+ 		return -EINVAL;
+@@ -757,7 +757,7 @@ static int check_insn_config_length(comedi_insn *insn, lsampl_t *data)
+ 	return -EINVAL;
+ }
+ 
+-static int parse_insn(comedi_device *dev, comedi_insn *insn, lsampl_t *data,
++static int parse_insn(comedi_device *dev, comedi_insn *insn, unsigned int *data,
+ 		      void *file)
+ {
+ 	comedi_subdevice *s;
+@@ -825,7 +825,7 @@ static int parse_insn(comedi_device *dev, comedi_insn *insn, lsampl_t *data,
+ 		}
+ 	} else {
+ 		/* a subdevice instruction */
+-		lsampl_t maxdata;
++		unsigned int maxdata;
+ 
+ 		if (insn->subdev >= dev->n_subdevices) {
+ 			DPRINTK("subdevice %d out of range\n", insn->subdev);
+@@ -920,10 +920,10 @@ static int parse_insn(comedi_device *dev, comedi_insn *insn, lsampl_t *data,
+ static int do_insn_ioctl(comedi_device *dev, void *arg, void *file)
+ {
+ 	comedi_insn insn;
+-	lsampl_t *data = NULL;
++	unsigned int *data = NULL;
+ 	int ret = 0;
+ 
+-	data = kmalloc(sizeof(lsampl_t) * MAX_SAMPLES, GFP_KERNEL);
++	data = kmalloc(sizeof(unsigned int) * MAX_SAMPLES, GFP_KERNEL);
+ 	if (!data) {
+ 		ret = -ENOMEM;
+ 		goto error;
+@@ -938,7 +938,7 @@ static int do_insn_ioctl(comedi_device *dev, void *arg, void *file)
+ 	if (insn.n > MAX_SAMPLES)
+ 		insn.n = MAX_SAMPLES;
+ 	if (insn.insn & INSN_MASK_WRITE) {
+-		if (copy_from_user(data, insn.data, insn.n * sizeof(lsampl_t))) {
++		if (copy_from_user(data, insn.data, insn.n * sizeof(unsigned int))) {
+ 			ret = -EFAULT;
+ 			goto error;
+ 		}
+@@ -947,7 +947,7 @@ static int do_insn_ioctl(comedi_device *dev, void *arg, void *file)
+ 	if (ret < 0)
+ 		goto error;
+ 	if (insn.insn & INSN_MASK_READ) {
+-		if (copy_to_user(insn.data, data, insn.n * sizeof(lsampl_t))) {
++		if (copy_to_user(insn.data, data, insn.n * sizeof(unsigned int))) {
+ 			ret = -EFAULT;
+ 			goto error;
+ 		}
+diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
+index d4750e503aad..372a1ba808d6 100644
+--- a/drivers/staging/comedi/comedidev.h
++++ b/drivers/staging/comedi/comedidev.h
+@@ -150,8 +150,8 @@ struct comedi_subdevice_struct {
+ 
+ 	int io_bits;
+ 
+-	lsampl_t maxdata;	/* if maxdata==0, use list */
+-	const lsampl_t *maxdata_list;	/* list is channel specific */
++	unsigned int maxdata;	/* if maxdata==0, use list */
++	const unsigned int *maxdata_list;	/* list is channel specific */
+ 
+ 	unsigned int flags;
+ 	const unsigned int *flaglist;
+@@ -164,13 +164,13 @@ struct comedi_subdevice_struct {
+ 	unsigned int *chanlist;	/* driver-owned chanlist (not used) */
+ 
+ 	int (*insn_read) (comedi_device *, comedi_subdevice *, comedi_insn *,
+-		lsampl_t *);
++		unsigned int *);
+ 	int (*insn_write) (comedi_device *, comedi_subdevice *, comedi_insn *,
+-		lsampl_t *);
++		unsigned int *);
+ 	int (*insn_bits) (comedi_device *, comedi_subdevice *, comedi_insn *,
+-		lsampl_t *);
++		unsigned int *);
+ 	int (*insn_config) (comedi_device *, comedi_subdevice *, comedi_insn *,
+-		lsampl_t *);
++		unsigned int *);
+ 
+ 	int (*do_cmd) (comedi_device *, comedi_subdevice *);
+ 	int (*do_cmdtest) (comedi_device *, comedi_subdevice *, comedi_cmd *);
+@@ -389,7 +389,7 @@ void comedi_set_subdevice_runflags(comedi_subdevice *s, unsigned mask,
+ 	unsigned bits);
+ unsigned comedi_get_subdevice_runflags(comedi_subdevice *s);
+ int insn_inval(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data);
++	comedi_insn *insn, unsigned int *data);
+ 
+ /* range stuff */
+ 
+@@ -452,9 +452,9 @@ static inline int alloc_private(comedi_device *dev, int size)
+ static inline unsigned int bytes_per_sample(const comedi_subdevice *subd)
+ {
+ 	if (subd->subdev_flags & SDF_LSAMPL)
+-		return sizeof(lsampl_t);
++		return sizeof(unsigned int);
+ 	else
+-		return sizeof(sampl_t);
++		return sizeof(short);
+ }
+ 
+ /* must be used in attach to set dev->hw_dev if you wish to dma directly
+@@ -471,8 +471,8 @@ static inline void comedi_set_hw_dev(comedi_device *dev, struct device *hw_dev)
+ 	}
+ }
+ 
+-int comedi_buf_put(comedi_async *async, sampl_t x);
+-int comedi_buf_get(comedi_async *async, sampl_t *x);
++int comedi_buf_put(comedi_async *async, short x);
++int comedi_buf_get(comedi_async *async, short *x);
+ 
+ unsigned int comedi_buf_write_n_available(comedi_async *async);
+ unsigned int comedi_buf_write_alloc(comedi_async *async, unsigned int nbytes);
+diff --git a/drivers/staging/comedi/comedilib.h b/drivers/staging/comedi/comedilib.h
+index ab42893562f9..b4192e486aa5 100644
+--- a/drivers/staging/comedi/comedilib.h
++++ b/drivers/staging/comedi/comedilib.h
+@@ -65,14 +65,14 @@ int comedi_command_test(void *dev, comedi_cmd *cmd);
+ int comedi_trigger(void *dev, unsigned int subdev, comedi_trig *it);
+ int __comedi_trigger(void *dev, unsigned int subdev, comedi_trig *it);
+ int comedi_data_write(void *dev, unsigned int subdev, unsigned int chan,
+-	unsigned int range, unsigned int aref, lsampl_t data);
++	unsigned int range, unsigned int aref, unsigned int data);
+ int comedi_data_read(void *dev, unsigned int subdev, unsigned int chan,
+-	unsigned int range, unsigned int aref, lsampl_t *data);
++	unsigned int range, unsigned int aref, unsigned int *data);
+ int comedi_data_read_hint(void *dev, unsigned int subdev,
+ 	unsigned int chan, unsigned int range, unsigned int aref);
+ int comedi_data_read_delayed(void *dev, unsigned int subdev,
+ 	unsigned int chan, unsigned int range, unsigned int aref,
+-	lsampl_t *data, unsigned int nano_sec);
++	unsigned int *data, unsigned int nano_sec);
+ int comedi_dio_config(void *dev, unsigned int subdev, unsigned int chan,
+ 	unsigned int io);
+ int comedi_dio_read(void *dev, unsigned int subdev, unsigned int chan,
+@@ -88,7 +88,7 @@ const char *comedi_get_board_name(void *dev);
+ int comedi_get_subdevice_type(void *dev, unsigned int subdevice);
+ int comedi_find_subdevice_by_type(void *dev, int type, unsigned int subd);
+ int comedi_get_n_channels(void *dev, unsigned int subdevice);
+-lsampl_t comedi_get_maxdata(void *dev, unsigned int subdevice, unsigned
++unsigned int comedi_get_maxdata(void *dev, unsigned int subdevice, unsigned
+ 	int chan);
+ int comedi_get_n_ranges(void *dev, unsigned int subdevice, unsigned int
+ 	chan);
+@@ -142,9 +142,9 @@ int comedi_command_test(unsigned int minor, comedi_cmd *cmd);
+ int comedi_trigger(unsigned int minor, unsigned int subdev, comedi_trig *it);
+ int __comedi_trigger(unsigned int minor, unsigned int subdev, comedi_trig *it);
+ int comedi_data_write(unsigned int dev, unsigned int subdev, unsigned int chan,
+-	unsigned int range, unsigned int aref, lsampl_t data);
++	unsigned int range, unsigned int aref, unsigned int data);
+ int comedi_data_read(unsigned int dev, unsigned int subdev, unsigned int chan,
+-	unsigned int range, unsigned int aref, lsampl_t *data);
++	unsigned int range, unsigned int aref, unsigned int *data);
+ int comedi_dio_config(unsigned int dev, unsigned int subdev, unsigned int chan,
+ 	unsigned int io);
+ int comedi_dio_read(unsigned int dev, unsigned int subdev, unsigned int chan,
+@@ -161,7 +161,7 @@ int comedi_get_subdevice_type(unsigned int minor, unsigned int subdevice);
+ int comedi_find_subdevice_by_type(unsigned int minor, int type,
+ 	unsigned int subd);
+ int comedi_get_n_channels(unsigned int minor, unsigned int subdevice);
+-lsampl_t comedi_get_maxdata(unsigned int minor, unsigned int subdevice, unsigned
++unsigned int comedi_get_maxdata(unsigned int minor, unsigned int subdevice, unsigned
+ 	int chan);
+ int comedi_get_n_ranges(unsigned int minor, unsigned int subdevice, unsigned int
+ 	chan);
+diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
+index 07456c0709dc..49834ebfcb19 100644
+--- a/drivers/staging/comedi/drivers.c
++++ b/drivers/staging/comedi/drivers.c
+@@ -49,7 +49,7 @@
+ 
+ static int postconfig(comedi_device *dev);
+ static int insn_rw_emulate_bits(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data);
++	comedi_insn *insn, unsigned int *data);
+ static void *comedi_recognize(comedi_driver * driv, const char *name);
+ static void comedi_report_boards(comedi_driver *driv);
+ static int poll_invalid(comedi_device *dev, comedi_subdevice *s);
+@@ -337,13 +337,13 @@ static int poll_invalid(comedi_device *dev, comedi_subdevice *s)
+ }
+ 
+ int insn_inval(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data)
++	comedi_insn *insn, unsigned int *data)
+ {
+ 	return -EINVAL;
+ }
+ 
+ static int insn_rw_emulate_bits(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data)
++	comedi_insn *insn, unsigned int *data)
+ {
+ 	comedi_insn new_insn;
+ 	int ret;
+@@ -352,7 +352,7 @@ static int insn_rw_emulate_bits(comedi_device *dev, comedi_subdevice *s,
+ 	unsigned chan = CR_CHAN(insn->chanspec);
+ 	const unsigned base_bitfield_channel =
+ 		(chan < channels_per_bitfield) ? 0 : chan;
+-	lsampl_t new_data[2];
++	unsigned int new_data[2];
+ 	memset(new_data, 0, sizeof(new_data));
+ 	memset(&new_insn, 0, sizeof(new_insn));
+ 	new_insn.insn = INSN_BITS;
+@@ -745,28 +745,28 @@ unsigned int comedi_buf_read_n_available(comedi_async *async)
+ 	return num_bytes;
+ }
+ 
+-int comedi_buf_get(comedi_async *async, sampl_t *x)
++int comedi_buf_get(comedi_async *async, short *x)
+ {
+ 	unsigned int n = comedi_buf_read_n_available(async);
+ 
+-	if (n < sizeof(sampl_t))
++	if (n < sizeof(short))
+ 		return 0;
+-	comedi_buf_read_alloc(async, sizeof(sampl_t));
+-	*x = *(sampl_t *) (async->prealloc_buf + async->buf_read_ptr);
+-	comedi_buf_read_free(async, sizeof(sampl_t));
++	comedi_buf_read_alloc(async, sizeof(short));
++	*x = *(short *) (async->prealloc_buf + async->buf_read_ptr);
++	comedi_buf_read_free(async, sizeof(short));
+ 	return 1;
+ }
+ 
+-int comedi_buf_put(comedi_async *async, sampl_t x)
++int comedi_buf_put(comedi_async *async, short x)
+ {
+-	unsigned int n = comedi_buf_write_alloc_strict(async, sizeof(sampl_t));
++	unsigned int n = comedi_buf_write_alloc_strict(async, sizeof(short));
+ 
+-	if (n < sizeof(sampl_t)) {
++	if (n < sizeof(short)) {
+ 		async->events |= COMEDI_CB_ERROR;
+ 		return 0;
+ 	}
+-	*(sampl_t *) (async->prealloc_buf + async->buf_write_ptr) = x;
+-	comedi_buf_write_free(async, sizeof(sampl_t));
++	*(short *) (async->prealloc_buf + async->buf_write_ptr) = x;
++	comedi_buf_write_free(async, sizeof(short));
+ 	return 1;
+ }
+ 
+diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c
+index 4a471849181f..b90bd1275f99 100644
+--- a/drivers/staging/comedi/drivers/8255.c
++++ b/drivers/staging/comedi/drivers/8255.c
+@@ -120,7 +120,7 @@ static void do_config(comedi_device * dev, comedi_subdevice * s);
+ 
+ void subdev_8255_interrupt(comedi_device * dev, comedi_subdevice * s)
+ {
+-	sampl_t d;
++	short d;
+ 
+ 	d = CALLBACK_FUNC(0, _8255_DATA, 0, CALLBACK_ARG);
+ 	d |= (CALLBACK_FUNC(0, _8255_DATA + 1, 0, CALLBACK_ARG) << 8);
+@@ -144,7 +144,7 @@ static int subdev_8255_cb(int dir, int port, int data, unsigned long arg)
+ }
+ 
+ static int subdev_8255_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+ 		s->state &= ~data[0];
+@@ -169,7 +169,7 @@ static int subdev_8255_insn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int subdev_8255_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int mask;
+ 	unsigned int bits;
+diff --git a/drivers/staging/comedi/drivers/acl7225b.c b/drivers/staging/comedi/drivers/acl7225b.c
+index 10dd20ca6b36..aeaf30dea300 100644
+--- a/drivers/staging/comedi/drivers/acl7225b.c
++++ b/drivers/staging/comedi/drivers/acl7225b.c
+@@ -51,7 +51,7 @@ static comedi_driver driver_acl7225b = {
+ COMEDI_INITCLEANUP(driver_acl7225b);
+ 
+ static int acl7225b_do_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -72,7 +72,7 @@ static int acl7225b_do_insn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int acl7225b_di_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+index 20db5b2a84bd..20450ba03504 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+@@ -33,7 +33,7 @@
+ |                                BYTE_   b_OutputLevel,                      |
+ |                                BYTE_   b_HardwareGateLevel)
+ INT i_InsnConfig_InitTimer(comedi_device *dev,comedi_subdevice *s,
+-	comedi_insn *insn,lsampl_t *data)
++	comedi_insn *insn,unsigned int *data)
+ |
+ +----------------------------------------------------------------------------+
+ | Task              : Configure the Timer (b_TimerNbr) operating mode        |
+@@ -220,7 +220,7 @@ INT i_InsnConfig_InitTimer(comedi_device *dev,comedi_subdevice *s,
+ */
+ 
+ INT i_APCI1710_InsnConfigInitTimer(comedi_device * dev, comedi_subdevice * s,
+-				   comedi_insn * insn, lsampl_t * data)
++				   comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	INT i_ReturnValue = 0;
+@@ -407,7 +407,7 @@ INT i_APCI1710_InsnConfigInitTimer(comedi_device * dev, comedi_subdevice * s,
+ |                                BYTE_ b_TimerNbr,                           |
+ |                                BYTE_ b_InterruptEnable)
+ INT i_APCI1710_InsnWriteEnableDisableTimer(comedi_device *dev,comedi_subdevice *s,
+-	comedi_insn *insn,lsampl_t *data)                |
++	comedi_insn *insn,unsigned int *data)                |
+ +----------------------------------------------------------------------------+
+ | Task              : Enable OR Disable the Timer (b_TimerNbr) from selected module     |
+ |                     (b_ModulNbr). You must calling the                     |
+@@ -450,7 +450,7 @@ i_ReturnValue=insn->n;
+ 
+ INT i_APCI1710_InsnWriteEnableDisableTimer(comedi_device * dev,
+ 					   comedi_subdevice * s,
+-					   comedi_insn * insn, lsampl_t * data)
++					   comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_DummyRead;
+@@ -562,7 +562,7 @@ INT i_APCI1710_InsnWriteEnableDisableTimer(comedi_device * dev,
+ |                                        BYTE_     b_ModulNbr,               |
+ |                                        PULONG_ pul_TimerValueArray)
+ INT i_APCI1710_InsnReadAllTimerValue(comedi_device *dev,comedi_subdevice *s,
+-	comedi_insn *insn,lsampl_t *data)        |
++	comedi_insn *insn,unsigned int *data)        |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the all timer values from selected timer        |
+ |                     module (b_ModulNbr).                                   |
+@@ -591,7 +591,7 @@ INT i_APCI1710_InsnReadAllTimerValue(comedi_device *dev,comedi_subdevice *s,
+ */
+ 
+ INT i_APCI1710_InsnReadAllTimerValue(comedi_device *dev, comedi_subdevice *s,
+-				     comedi_insn *insn, lsampl_t *data)
++				     comedi_insn *insn, unsigned int *data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	BYTE b_ModulNbr, b_ReadType;
+@@ -669,7 +669,7 @@ INT i_APCI1710_InsnReadAllTimerValue(comedi_device *dev, comedi_subdevice *s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     :INT i_APCI1710_InsnBitsTimer(comedi_device *dev,
+-comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)                   |
++comedi_subdevice *s,comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ | Task              : Read write functions for Timer                                          |
+ +----------------------------------------------------------------------------+
+@@ -682,7 +682,7 @@ comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)                   |
+ */
+ 
+ INT i_APCI1710_InsnBitsTimer(comedi_device * dev, comedi_subdevice * s,
+-			     comedi_insn * insn, lsampl_t * data)
++			     comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_BitsType;
+ 	INT i_ReturnValue = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
+index 33ef9113878b..80ee66233ec6 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
+@@ -35,20 +35,20 @@
+  * 82X54 TIMER INISIALISATION FUNCTION
+  */
+ INT i_APCI1710_InsnConfigInitTimer(comedi_device *dev, comedi_subdevice *s,
+-				   comedi_insn *insn, lsampl_t *data);
++				   comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnWriteEnableDisableTimer(comedi_device *dev,
+ 					   comedi_subdevice *s,
+-					   comedi_insn *insn, lsampl_t *data);
++					   comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * 82X54 READ FUNCTION
+  */
+ INT i_APCI1710_InsnReadAllTimerValue(comedi_device *dev, comedi_subdevice *s,
+-				     comedi_insn *insn, lsampl_t *data);
++				     comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnBitsTimer(comedi_device *dev, comedi_subdevice *s,
+-			     comedi_insn *insn, lsampl_t *data);
++			     comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * 82X54 READ & WRITE FUNCTION
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+index 01100ff01ed4..25242871d470 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+@@ -132,7 +132,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ */
+ 
+ INT i_APCI1710_InsnConfigInitChrono(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	ULONG ul_TimerValue = 0;
+@@ -791,7 +791,7 @@ INT i_APCI1710_InsnConfigInitChrono(comedi_device * dev, comedi_subdevice * s,
+ |                                                BYTE_ b_CycleMode,          |
+ |                                                BYTE_ b_InterruptEnable)
+ INT i_APCI1710_InsnWriteEnableDisableChrono(comedi_device *dev,
+-comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)						 |
++comedi_subdevice *s,comedi_insn *insn,unsigned int *data)						 |
+ +----------------------------------------------------------------------------+
+ | Task              : Enable the chronometer from selected module            |
+ |                     (b_ModulNbr). You must calling the                     |
+@@ -841,7 +841,7 @@ comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)						 |
+ */
+ 
+ INT i_APCI1710_InsnWriteEnableDisableChrono(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	BYTE b_ModulNbr, b_CycleMode, b_InterruptEnable, b_Action;
+@@ -1078,7 +1078,7 @@ INT i_APCI1710_InsnWriteEnableDisableChrono(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     :INT	i_APCI1710_InsnReadChrono(comedi_device *dev,comedi_subdevice *s,
+-comedi_insn *insn,lsampl_t *data)                   |
++comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  functions for Timer                                     |
+ +----------------------------------------------------------------------------+
+@@ -1091,7 +1091,7 @@ comedi_insn *insn,lsampl_t *data)                   |
+ */
+ 
+ INT i_APCI1710_InsnReadChrono(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_ReadType;
+ 	INT i_ReturnValue = insn->n;
+@@ -1758,7 +1758,7 @@ INT i_APCI1710_ConvertChronoValue(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT i_APCI1710_InsnBitsChronoDigitalIO(comedi_device *dev,comedi_subdevice *s,
+-	comedi_insn *insn,lsampl_t *data)                    |
++	comedi_insn *insn,unsigned int *data)                    |
+ +----------------------------------------------------------------------------+
+ | Task              : Sets the output witch has been passed with the         |
+ |                     parameter b_Channel. Setting an output means setting an|
+@@ -1877,7 +1877,7 @@ INT i_APCI1710_ConvertChronoValue(comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_InsnBitsChronoDigitalIO(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	BYTE b_ModulNbr, b_OutputChannel, b_InputChannel, b_IOType;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
+index 0dc67e87ed0f..9f6d0f003de4 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
+@@ -36,18 +36,18 @@
+  * CHRONOMETER INISIALISATION FUNCTION
+  */
+ INT i_APCI1710_InsnConfigInitChrono(comedi_device *dev, comedi_subdevice *s,
+-				    comedi_insn *insn, lsampl_t *data);
++				    comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnWriteEnableDisableChrono(comedi_device *dev,
+ 					    comedi_subdevice *s,
+ 					    comedi_insn *insn,
+-					    lsampl_t *data);
++					    unsigned int *data);
+ 
+ /*
+  * CHRONOMETER READ FUNCTION
+  */
+ INT i_APCI1710_InsnReadChrono(comedi_device *dev, comedi_subdevice *s,
+-			      comedi_insn *insn, lsampl_t *data);
++			      comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_GetChronoProgressStatus(comedi_device *dev,
+ 				       BYTE b_ModulNbr, PBYTE pb_ChronoStatus);
+@@ -71,4 +71,4 @@ INT i_APCI1710_ConvertChronoValue(comedi_device *dev,
+  */
+ INT i_APCI1710_InsnBitsChronoDigitalIO(comedi_device *dev,
+ 				       comedi_subdevice *s, comedi_insn *insn,
+-				       lsampl_t *data);
++				       unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+index 531822c10847..87dba6a83d83 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+@@ -62,7 +62,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT i_APCI1710_InsnConfigDigitalIO(comedi_device *dev, |
+-|						comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)|
++|						comedi_subdevice *s,comedi_insn *insn,unsigned int *data)|
+ +----------------------------------------------------------------------------+
+ | Task              : Configure the digital I/O operating mode from selected |
+ |                     module  (b_ModulNbr). You must calling this function be|
+@@ -100,7 +100,7 @@ Activates and deactivates the digital output memory.
+ */
+ 
+ INT i_APCI1710_InsnConfigDigitalIO(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_ModulNbr, b_ChannelAMode, b_ChannelBMode;
+ 	BYTE b_MemoryOnOff, b_ConfigType;
+@@ -248,7 +248,7 @@ INT i_APCI1710_InsnConfigDigitalIO(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ 
+ |INT i_APCI1710_InsnReadDigitalIOChlValue(comedi_device *dev,comedi_subdevice
+-*s,	comedi_insn *insn,lsampl_t *data)
++*s,	comedi_insn *insn,unsigned int *data)
+ 
+ +----------------------------------------------------------------------------+
+ | Task              : Read the status from selected digital I/O digital input|
+@@ -294,7 +294,7 @@ INT i_APCI1710_InsnConfigDigitalIO(comedi_device * dev, comedi_subdevice * s,
+ //
+ //                                             PBYTE_  pb_ChannelStatus)
+ INT i_APCI1710_InsnReadDigitalIOChlValue(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusReg;
+@@ -446,7 +446,7 @@ INT i_APCI1710_InsnReadDigitalIOChlValue(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT i_APCI1710_InsnWriteDigitalIOChlOnOff(comedi_device
+-|*dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
++|*dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data)
+ 
+ +----------------------------------------------------------------------------+
+ | Task              : Sets or resets the output witch has been passed with the         |
+@@ -482,7 +482,7 @@ INT i_APCI1710_InsnReadDigitalIOChlValue(comedi_device * dev,
+ //                                       BYTE_ b_ModulNbr,
+ //                                       BYTE_ b_OutputChannel)
+ INT i_APCI1710_InsnWriteDigitalIOChlOnOff(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_WriteValue = 0;
+@@ -677,7 +677,7 @@ INT i_APCI1710_InsnWriteDigitalIOChlOnOff(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ 
+ |INT i_APCI1710_InsnBitsDigitalIOPortOnOff(comedi_device *dev,comedi_subdevice
+-	*s,	comedi_insn *insn,lsampl_t *data)
++	*s,	comedi_insn *insn,unsigned int *data)
+ +----------------------------------------------------------------------------+
+ | Task              : write:
+ 					  Sets or resets one or several outputs from port.                 |
+@@ -729,7 +729,7 @@ INT i_APCI1710_InsnWriteDigitalIOChlOnOff(comedi_device * dev,
+ //                                       BYTE_ b_ModulNbr,
+ //                                       BYTE_ b_PortValue)
+ INT i_APCI1710_InsnBitsDigitalIOPortOnOff(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_WriteValue = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h
+index 2f1cf869999c..76dbf0840889 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h
+@@ -28,19 +28,19 @@
+  * DIGITAL I/O INISIALISATION FUNCTION
+  */
+ INT i_APCI1710_InsnConfigDigitalIO(comedi_device *dev, comedi_subdevice *s,
+-				   comedi_insn *insn, lsampl_t *data);
++				   comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * INPUT OUTPUT  FUNCTIONS
+  */
+ INT i_APCI1710_InsnReadDigitalIOChlValue(comedi_device *dev,
+ 					 comedi_subdevice *s,
+-					 comedi_insn *insn, lsampl_t *data);
++					 comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnWriteDigitalIOChlOnOff(comedi_device *dev,
+ 					  comedi_subdevice *s,
+-					  comedi_insn *insn, lsampl_t *data);
++					  comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnBitsDigitalIOPortOnOff(comedi_device *dev,
+ 					  comedi_subdevice *s,
+-					  comedi_insn *insn, lsampl_t *data);
++					  comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+index ddffb069d5c2..5ad6abff41a5 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+@@ -62,7 +62,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*
+ +----------------------------------------------------------------------------+
+ | INT	i_APCI1710_InsnConfigINCCPT(comedi_device *dev,comedi_subdevice *s,
+-comedi_insn *insn,lsampl_t *data)
++comedi_insn *insn,unsigned int *data)
+ 
+ +----------------------------------------------------------------------------+
+ | Task              : Configuration function for INC_CPT                             |
+@@ -76,7 +76,7 @@ comedi_insn *insn,lsampl_t *data)
+ */
+ 
+ INT i_APCI1710_InsnConfigINCCPT(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_ConfigType;
+ 	INT i_ReturnValue = 0;
+@@ -2003,7 +2003,7 @@ INT i_APCI1710_InitFrequencyMeasurement(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     :INT	i_APCI1710_InsnBitsINCCPT(comedi_device *dev,comedi_subdevice *s,
+-comedi_insn *insn,lsampl_t *data)                   |
++comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ | Task              : Set & Clear Functions for INC_CPT                                          |
+ +----------------------------------------------------------------------------+
+@@ -2016,7 +2016,7 @@ comedi_insn *insn,lsampl_t *data)                   |
+ */
+ 
+ INT i_APCI1710_InsnBitsINCCPT(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_BitsType;
+ 	INT i_ReturnValue = 0;
+@@ -2940,7 +2940,7 @@ INT i_APCI1710_SetDigitalChlOff(comedi_device * dev, BYTE b_ModulNbr)
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     :INT	i_APCI1710_InsnWriteINCCPT(comedi_device *dev,comedi_subdevice *s,
+-comedi_insn *insn,lsampl_t *data)                   |
++comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ | Task              : Enable Disable functions for INC_CPT                                       |
+ +----------------------------------------------------------------------------+
+@@ -2952,7 +2952,7 @@ comedi_insn *insn,lsampl_t *data)                   |
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1710_InsnWriteINCCPT(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_WriteType;
+ 	INT i_ReturnValue = 0;
+@@ -4038,7 +4038,7 @@ INT i_APCI1710_DisableFrequencyMeasurement(comedi_device * dev, BYTE b_ModulNbr)
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     :INT	i_APCI1710_InsnWriteINCCPT(comedi_device *dev,comedi_subdevice *s,
+-comedi_insn *insn,lsampl_t *data)                   |
++comedi_insn *insn,unsigned int *data)                   |
+ +----------------------------------------------------------------------------+
+ | Task              : Read and Get functions for INC_CPT                                       |
+ +----------------------------------------------------------------------------+
+@@ -4050,7 +4050,7 @@ comedi_insn *insn,lsampl_t *data)                   |
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1710_InsnReadINCCPT(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_ReadType;
+ 	INT i_ReturnValue = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
+index 140f4d25c3b3..8abcaa4a971c 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
+@@ -133,16 +133,16 @@
+ 
+ /************ Main Functions *************/
+ INT i_APCI1710_InsnConfigINCCPT(comedi_device *dev, comedi_subdevice *s,
+-				comedi_insn *insn, lsampl_t * data);
++				comedi_insn *insn, unsigned int * data);
+ 
+ INT i_APCI1710_InsnBitsINCCPT(comedi_device *dev, comedi_subdevice * s,
+-			      comedi_insn *insn, lsampl_t * data);
++			      comedi_insn *insn, unsigned int * data);
+ 
+ INT i_APCI1710_InsnWriteINCCPT(comedi_device *dev, comedi_subdevice * s,
+-			       comedi_insn *insn, lsampl_t * data);
++			       comedi_insn *insn, unsigned int * data);
+ 
+ INT i_APCI1710_InsnReadINCCPT(comedi_device *dev, comedi_subdevice * s,
+-			      comedi_insn *insn, lsampl_t * data);
++			      comedi_insn *insn, unsigned int * data);
+ 
+ /*********** Supplementary Functions********/
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+index 90b8dc9df5bd..d6101c9a998a 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+@@ -124,7 +124,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ */
+ 
+ INT i_APCI1710_InsnConfigInitPulseEncoder(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_IntRegister;
+@@ -415,7 +415,7 @@ INT i_APCI1710_InsnConfigInitPulseEncoder(comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	BYTE b_ModulNbr;
+@@ -709,7 +709,7 @@ INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(comedi_device * dev,
+    						 PBYTE_ pb_Status)
+ 						 */
+ INT i_APCI1710_InsnBitsReadWritePulseEncoder(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusRegister;
+@@ -835,7 +835,7 @@ INT i_APCI1710_InsnBitsReadWritePulseEncoder(comedi_device * dev,
+ }
+ 
+ INT i_APCI1710_InsnReadInterruptPulseEncoder(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	data[0] = devpriv->s_InterruptParameters.
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h
+index 1cfa9c978f83..c901a317fc61 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h
+@@ -23,12 +23,12 @@
+ 
+ INT i_APCI1710_InsnConfigInitPulseEncoder(comedi_device *dev,
+ 					  comedi_subdevice *s,
+-					  comedi_insn *insn, lsampl_t *data);
++					  comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(comedi_device *dev,
+ 						  comedi_subdevice *s,
+ 						  comedi_insn *insn,
+-						  lsampl_t *data);
++						  unsigned int *data);
+ 
+ /*
+  * READ PULSE ENCODER FUNCTIONS
+@@ -36,7 +36,7 @@ INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(comedi_device *dev,
+ INT i_APCI1710_InsnReadInterruptPulseEncoder(comedi_device *dev,
+ 					     comedi_subdevice *s,
+ 					     comedi_insn *insn,
+-					     lsampl_t *data);
++					     unsigned int *data);
+ 
+ /*
+  * WRITE PULSE ENCODER FUNCTIONS
+@@ -44,4 +44,4 @@ INT i_APCI1710_InsnReadInterruptPulseEncoder(comedi_device *dev,
+ INT i_APCI1710_InsnBitsReadWritePulseEncoder(comedi_device *dev,
+ 					     comedi_subdevice *s,
+ 					     comedi_insn *insn,
+-					     lsampl_t *data);
++					     unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+index a3b44b978da5..9a2dd408f38f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+@@ -58,7 +58,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     :INT i_APCI1710_InsnConfigPWM(comedi_device *dev,
+-comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)                        |
++comedi_subdevice *s,comedi_insn *insn,unsigned int *data)                        |
+ +----------------------------------------------------------------------------+
+ | Task              : Pwm Init and Get Pwm Initialisation                    |
+ +----------------------------------------------------------------------------+
+@@ -71,7 +71,7 @@ comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)                        |
+ */
+ 
+ INT i_APCI1710_InsnConfigPWM(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_ConfigType;
+ 	INT i_ReturnValue = 0;
+@@ -1671,7 +1671,7 @@ INT i_APCI1710_GetPWMInitialisation(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     :INT i_APCI1710_InsnWritePWM(comedi_device *dev,
+-comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)                        |
++comedi_subdevice *s,comedi_insn *insn,unsigned int *data)                        |
+ +----------------------------------------------------------------------------+
+ | Task              : Pwm Enable Disable and Set New Timing                  |
+ +----------------------------------------------------------------------------+
+@@ -1684,7 +1684,7 @@ comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)                        |
+ */
+ 
+ INT i_APCI1710_InsnWritePWM(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_WriteType;
+ 	INT i_ReturnValue = 0;
+@@ -3461,7 +3461,7 @@ INT i_APCI1710_SetNewPWMTiming(comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_InsnReadGetPWMStatus(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_Status;
+@@ -3562,7 +3562,7 @@ INT i_APCI1710_InsnReadGetPWMStatus(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ INT i_APCI1710_InsnBitsReadPWMInterrupt(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->s_InterruptParameters.
+ 		s_FIFOInterruptParameters[devpriv->
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
+index 3eeef3e85181..1f40d00b10e6 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
+@@ -27,7 +27,7 @@
+ #define APCI1710_PWM_NEWTIMING		2
+ 
+ INT i_APCI1710_InsnConfigPWM(comedi_device *dev, comedi_subdevice *s,
+-			     comedi_insn *insn, lsampl_t *data);
++			     comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InitPWM(comedi_device *dev,
+ 		       BYTE b_ModulNbr,
+@@ -51,7 +51,7 @@ INT i_APCI1710_GetPWMInitialisation(comedi_device *dev,
+ 				    PBYTE pb_InterruptEnable, PBYTE pb_Enable);
+ 
+ INT i_APCI1710_InsnWritePWM(comedi_device *dev, comedi_subdevice *s,
+-			    comedi_insn *insn, lsampl_t *data);
++			    comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_EnablePWM(comedi_device *dev,
+ 			 BYTE b_ModulNbr,
+@@ -69,8 +69,8 @@ INT i_APCI1710_SetNewPWMTiming(comedi_device *dev,
+ INT i_APCI1710_DisablePWM(comedi_device *dev, BYTE b_ModulNbr, BYTE b_PWM);
+ 
+ INT i_APCI1710_InsnReadGetPWMStatus(comedi_device *dev, comedi_subdevice *s,
+-				    comedi_insn *insn, lsampl_t *data);
++				    comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnBitsReadPWMInterrupt(comedi_device *dev,
+ 					comedi_subdevice *s,
+-					comedi_insn *insn, lsampl_t *data);
++					comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+index 497233618c45..650b5752e61a 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+@@ -134,7 +134,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ */
+ 
+ INT i_APCI1710_InsnConfigInitSSI(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	UINT ui_TimerValue;
+@@ -363,7 +363,7 @@ INT i_APCI1710_InsnConfigInitSSI(comedi_device * dev, comedi_subdevice * s,
+ |                                PULONG_ pul_Position,                       |
+ |                                PULONG_ pul_TurnCpt)
+  INT i_APCI1710_ReadSSIValue(comedi_device *dev,comedi_subdevice *s,
+-	comedi_insn *insn,lsampl_t *data)                       |
++	comedi_insn *insn,unsigned int *data)                       |
+ +----------------------------------------------------------------------------+
+ | Task              :
+ 
+@@ -401,7 +401,7 @@ pul_Position	=	(PULONG) &data[0];
+ */
+ 
+ INT i_APCI1710_InsnReadSSIValue(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	BYTE b_Cpt;
+@@ -736,7 +736,7 @@ INT i_APCI1710_InsnReadSSIValue(comedi_device * dev, comedi_subdevice * s,
+ */
+ 
+ INT i_APCI1710_InsnBitsSSIDigitalIO(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusReg;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h
+index 260fc52a2495..a0ad47d2f7a8 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h
+@@ -34,10 +34,10 @@
+  * SSI INISIALISATION FUNCTION
+  */
+ INT i_APCI1710_InsnConfigInitSSI(comedi_device *dev, comedi_subdevice *s,
+-				 comedi_insn *insn, lsampl_t *data);
++				 comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnReadSSIValue(comedi_device *dev, comedi_subdevice *s,
+-				comedi_insn *insn, lsampl_t *data);
++				comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnBitsSSIDigitalIO(comedi_device *dev, comedi_subdevice *s,
+-				    comedi_insn *insn, lsampl_t *data);
++				    comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+index aa45d0a37270..09d5a2fadee6 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+@@ -131,7 +131,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ */
+ 
+ INT i_APCI1710_InsnConfigInitTorCounter(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	ULONG ul_TimerValue = 0;
+@@ -988,7 +988,7 @@ INT i_APCI1710_InsnConfigInitTorCounter(comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_InsnWriteEnableDisableTorCounter(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_Status;
+@@ -1461,7 +1461,7 @@ INT i_APCI1710_InsnWriteEnableDisableTorCounter(comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_InsnReadGetTorCounterInitialisation(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_Status;
+@@ -1701,7 +1701,7 @@ INT i_APCI1710_InsnReadGetTorCounterInitialisation(comedi_device * dev,
+ */
+ 
+ INT i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_Status;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h
+index 49e024280486..a4807de42441 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h
+@@ -37,21 +37,21 @@
+  */
+ INT i_APCI1710_InsnConfigInitTorCounter(comedi_device *dev,
+ 					comedi_subdevice *s,
+-					comedi_insn *insn, lsampl_t *data);
++					comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1710_InsnWriteEnableDisableTorCounter(comedi_device *dev,
+ 						comedi_subdevice *s,
+ 						comedi_insn *insn,
+-						lsampl_t *data);
++						unsigned int *data);
+ 
+ INT i_APCI1710_InsnReadGetTorCounterInitialisation(comedi_device *dev,
+ 						   comedi_subdevice *s,
+ 						   comedi_insn *insn,
+-						   lsampl_t *data);
++						   unsigned int *data);
+ /*
+  * TOR_COUNTER READ FUNCTION
+  */
+ INT i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(comedi_device *dev,
+ 							   comedi_subdevice *s,
+ 							   comedi_insn *insn,
+-							   lsampl_t *data);
++							   unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+index cd781796b633..0a40f46442e9 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+@@ -101,7 +101,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ */
+ 
+ INT i_APCI1710_InsnConfigInitTTLIO(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	BYTE b_ModulNbr;
+@@ -407,7 +407,7 @@ APCI1710_TTL_READCHANNEL
+ */
+ 
+ INT i_APCI1710_InsnBitsReadTTLIO(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusReg;
+@@ -634,7 +634,7 @@ INT i_APCI1710_InsnBitsReadTTLIO(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name     : INT i_APCI1710_InsnReadTTLIOAllPortValue(comedi_device
+-*dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)              |
++*dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data)              |
+ +----------------------------------------------------------------------------+
+ | Task              : Read the status from all digital input ports           |
+ |                     (port A, port B and port C) from selected TTL          |
+@@ -656,7 +656,7 @@ INT i_APCI1710_InsnBitsReadTTLIO(comedi_device * dev, comedi_subdevice * s,
+ */
+ 
+ INT i_APCI1710_InsnReadTTLIOAllPortValue(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusReg;
+@@ -793,7 +793,7 @@ INT i_APCI1710_InsnReadTTLIOAllPortValue(comedi_device * dev,
+ |                                BYTE_           b_ModulNbr,                 |
+ |                                BYTE_           b_OutputChannel)
+ INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(comedi_device *dev,comedi_subdevice *s,
+-	comedi_insn *insn,lsampl_t *data)           |
++	comedi_insn *insn,unsigned int *data)           |
+ +----------------------------------------------------------------------------+
+ | Task              : Sets or resets  the output witch has been passed with the         |
+ |                     parameter b_Channel. Setting an output means setting   |
+@@ -826,7 +826,7 @@ INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(comedi_device *dev,comedi_subdevice *s,
+ */
+ 
+ INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = 0;
+ 	DWORD dw_StatusReg = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h
+index 6870cf071b71..8993ac642736 100644
+--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h
++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h
+@@ -25,20 +25,20 @@
+  * TTL INISIALISATION FUNCTION
+  */
+ INT i_APCI1710_InsnConfigInitTTLIO(comedi_device *dev, comedi_subdevice *s,
+-				   comedi_insn *insn, lsampl_t *data);
++				   comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * TTL INPUT FUNCTION
+  */
+ INT i_APCI1710_InsnBitsReadTTLIO(comedi_device *dev, comedi_subdevice *s,
+-				 comedi_insn *insn, lsampl_t *data);
++				 comedi_insn *insn, unsigned int *data);
+ INT i_APCI1710_InsnReadTTLIOAllPortValue(comedi_device *dev,
+ 					 comedi_subdevice *s,
+-					 comedi_insn *insn, lsampl_t *data);
++					 comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * TTL OUTPUT FUNCTIONS
+  */
+ INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(comedi_device *dev,
+ 					 comedi_subdevice *s,
+-					 comedi_insn *insn, lsampl_t *data);
++					 comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+index 63c93debb92e..4cd552568ac3 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
+@@ -3030,14 +3030,14 @@ static irqreturn_t v_ADDI_Interrupt(int irq, void *d PT_REGS_ARG)
+ +----------------------------------------------------------------------------+
+ | Function name     :                                                        |
+ |INT i_ADDIDATA_InsnReadEeprom(comedi_device *dev,comedi_subdevice *s,
+-							comedi_insn *insn,lsampl_t *data)
++							comedi_insn *insn,unsigned int *data)
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              : Read 256 words from EEPROM          				     |
+ |                     										                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :(comedi_device *dev,comedi_subdevice *s,
+-			comedi_insn *insn,lsampl_t *data) 						 |
++			comedi_insn *insn,unsigned int *data) 						 |
+ |                     														 |
+ |                                                 					         |
+ +----------------------------------------------------------------------------+
+@@ -3047,7 +3047,7 @@ static irqreturn_t v_ADDI_Interrupt(int irq, void *d PT_REGS_ARG)
+ */
+ 
+ static int i_ADDIDATA_InsnReadEeprom(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	WORD w_Data;
+ 	WORD w_Address;
+diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+index 7bf997976b7f..ca7c5cb4dac6 100644
+--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
++++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
+@@ -120,19 +120,19 @@ typedef struct {
+ 	int (*i_hwdrv_InsnConfigAnalogInput)(comedi_device *dev,
+ 					     comedi_subdevice *s,
+ 					     comedi_insn *insn,
+-					     lsampl_t *data);
++					     unsigned int *data);
+ 	int (*i_hwdrv_InsnReadAnalogInput)(comedi_device *dev,
+ 					    comedi_subdevice *s,
+ 					    comedi_insn *insn,
+-					    lsampl_t *data);
++					    unsigned int *data);
+ 	int (*i_hwdrv_InsnWriteAnalogInput)(comedi_device *dev,
+ 					    comedi_subdevice *s,
+ 					    comedi_insn *insn,
+-					    lsampl_t *data);
++					    unsigned int *data);
+ 	int (*i_hwdrv_InsnBitsAnalogInput)(comedi_device *dev,
+ 					   comedi_subdevice *s,
+ 					   comedi_insn *insn,
+-					   lsampl_t *data);
++					   unsigned int *data);
+ 	int (*i_hwdrv_CommandTestAnalogInput)(comedi_device *dev,
+ 					      comedi_subdevice *s,
+ 					      comedi_cmd *cmd);
+@@ -145,77 +145,77 @@ typedef struct {
+ 	int (*i_hwdrv_InsnConfigAnalogOutput)(comedi_device *dev,
+ 					      comedi_subdevice *s,
+ 					      comedi_insn *insn,
+-					      lsampl_t *data);
++					      unsigned int *data);
+ 	int (*i_hwdrv_InsnWriteAnalogOutput)(comedi_device *dev,
+ 					     comedi_subdevice *s,
+ 					     comedi_insn *insn,
+-					     lsampl_t *data);
++					     unsigned int *data);
+ 	int (*i_hwdrv_InsnBitsAnalogOutput)(comedi_device *dev,
+ 					    comedi_subdevice *s,
+ 					    comedi_insn *insn,
+-					    lsampl_t *data);
++					    unsigned int *data);
+ 
+ 	/* Digital Input */
+ 	int (*i_hwdrv_InsnConfigDigitalInput) (comedi_device *dev,
+ 					       comedi_subdevice *s,
+ 					       comedi_insn *insn,
+-					       lsampl_t *data);
++					       unsigned int *data);
+ 	int (*i_hwdrv_InsnReadDigitalInput) (comedi_device *dev,
+ 					     comedi_subdevice *s,
+ 					     comedi_insn *insn,
+-					     lsampl_t *data);
++					     unsigned int *data);
+ 	int (*i_hwdrv_InsnWriteDigitalInput) (comedi_device *dev,
+ 					      comedi_subdevice *s,
+ 					      comedi_insn *insn,
+-					      lsampl_t *data);
++					      unsigned int *data);
+ 	int (*i_hwdrv_InsnBitsDigitalInput) (comedi_device *dev,
+ 					     comedi_subdevice *s,
+ 					     comedi_insn *insn,
+-					     lsampl_t *data);
++					     unsigned int *data);
+ 
+ 	/* Digital Output */
+ 	int (*i_hwdrv_InsnConfigDigitalOutput)(comedi_device *dev,
+ 					       comedi_subdevice *s,
+ 					       comedi_insn *insn,
+-					       lsampl_t *data);
++					       unsigned int *data);
+ 	int (*i_hwdrv_InsnWriteDigitalOutput)(comedi_device *dev,
+ 					      comedi_subdevice *s,
+ 					      comedi_insn *insn,
+-					      lsampl_t *data);
++					      unsigned int *data);
+ 	int (*i_hwdrv_InsnBitsDigitalOutput)(comedi_device *dev,
+ 					     comedi_subdevice *s,
+ 					     comedi_insn *insn,
+-					     lsampl_t *data);
++					     unsigned int *data);
+ 	int (*i_hwdrv_InsnReadDigitalOutput)(comedi_device *dev,
+ 					     comedi_subdevice *s,
+ 					     comedi_insn *insn,
+-					     lsampl_t *data);
++					     unsigned int *data);
+ 
+ 	/* TIMER */
+ 	int (*i_hwdrv_InsnConfigTimer)(comedi_device *dev,
+ 				       comedi_subdevice *s,
+-				       comedi_insn *insn, lsampl_t *data);
++				       comedi_insn *insn, unsigned int *data);
+ 	int (*i_hwdrv_InsnWriteTimer)(comedi_device *dev,
+ 				      comedi_subdevice *s, comedi_insn *insn,
+-				      lsampl_t *data);
++				      unsigned int *data);
+ 	int (*i_hwdrv_InsnReadTimer)(comedi_device *dev, comedi_subdevice *s,
+-				     comedi_insn *insn, lsampl_t *data);
++				     comedi_insn *insn, unsigned int *data);
+ 	int (*i_hwdrv_InsnBitsTimer)(comedi_device *dev, comedi_subdevice *s,
+-				     comedi_insn *insn, lsampl_t *data);
++				     comedi_insn *insn, unsigned int *data);
+ 
+ 	/* TTL IO */
+ 	int (*i_hwdr_ConfigInitTTLIO)(comedi_device *dev,
+ 				      comedi_subdevice *s, comedi_insn *insn,
+-				      lsampl_t *data);
++				      unsigned int *data);
+ 	int (*i_hwdr_ReadTTLIOBits)(comedi_device *dev, comedi_subdevice *s,
+-				    comedi_insn *insn, lsampl_t *data);
++				    comedi_insn *insn, unsigned int *data);
+ 	int (*i_hwdr_ReadTTLIOAllPortValue)(comedi_device *dev,
+ 					    comedi_subdevice *s,
+ 					    comedi_insn *insn,
+-					    lsampl_t *data);
++					    unsigned int *data);
+ 	int (*i_hwdr_WriteTTLIOChlOnOff)(comedi_device *dev,
+ 					 comedi_subdevice *s,
+-					 comedi_insn *insn, lsampl_t *data);
++					 comedi_insn *insn, unsigned int *data);
+ } boardtype;
+ 
+ //MODULE INFO STRUCTURE
+@@ -388,14 +388,14 @@ typedef struct {
+ 	UINT ui_AiTimer1;	//Timer constant for Timer1
+ 	UINT ui_AiFlags;
+ 	UINT ui_AiDataLength;
+-	sampl_t *AiData;	// Pointer to sample data
++	short *AiData;	// Pointer to sample data
+ 	UINT ui_AiNbrofScans;	// number of scans to do
+ 	USHORT us_UseDma;	// To use Dma or not
+ 	BYTE b_DmaDoubleBuffer;	// we can use double buffering
+ 	UINT ui_DmaActualBuffer;	// which buffer is used now
+ 	//*UPDATE-0.7.57->0.7.68
+ 	//ULONG               ul_DmaBufferVirtual[2];// pointers to begin of DMA buffer
+-	sampl_t *ul_DmaBufferVirtual[2];	// pointers to begin of DMA buffer
++	short *ul_DmaBufferVirtual[2];	// pointers to begin of DMA buffer
+ 	ULONG ul_DmaBufferHw[2];	// hw address of DMA buff
+ 	UINT ui_DmaBufferSize[2];	// size of dma buffer in bytes
+ 	UINT ui_DmaBufferUsesize[2];	// which size we may now used for transfer
+@@ -462,4 +462,4 @@ static int i_ADDI_Reset(comedi_device *dev);
+ 
+ static irqreturn_t v_ADDI_Interrupt(int irq, void *d PT_REGS_ARG);
+ static int i_ADDIDATA_InsnReadEeprom(comedi_device *dev, comedi_subdevice *s,
+-				     comedi_insn *insn, lsampl_t *data);
++				     comedi_insn *insn, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
+index f10ea4b25f19..4a4356550a6c 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
+@@ -59,7 +59,7 @@ INT i_Flag = 1;
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI035_ConfigTimerWatchdog                      |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Timer , Counter or Watchdog             |
+ +----------------------------------------------------------------------------+
+@@ -110,7 +110,7 @@ INT i_Flag = 1;
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI035_ConfigTimerWatchdog(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Status = 0;
+ 	UINT ui_Command = 0;
+@@ -255,7 +255,7 @@ INT i_APCI035_ConfigTimerWatchdog(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI035_StartStopWriteTimerWatchdog              |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Start / Stop The Selected Timer , or Watchdog  |
+ +----------------------------------------------------------------------------+
+@@ -279,7 +279,7 @@ INT i_APCI035_ConfigTimerWatchdog(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI035_StartStopWriteTimerWatchdog(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Command = 0;
+ 	INT i_Count = 0;
+@@ -368,7 +368,7 @@ INT i_APCI035_StartStopWriteTimerWatchdog(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI035_ReadTimerWatchdog                        |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Selected Timer , Counter or Watchdog          |
+ +----------------------------------------------------------------------------+
+@@ -392,7 +392,7 @@ INT i_APCI035_StartStopWriteTimerWatchdog(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI035_ReadTimerWatchdog(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Status = 0;	// Status register
+ 	i_WatchdogNbr = insn->unused[0];
+@@ -428,14 +428,14 @@ INT i_APCI035_ReadTimerWatchdog(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : INT i_APCI035_ConfigAnalogInput                        |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Analog Input Subdevice                  |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : comedi_device *dev      : Driver handle                |
+ |                     comedi_subdevice *s     : Subdevice Pointer            |
+ |                     comedi_insn *insn       : Insn Structure Pointer       |
+-|                     lsampl_t *data          : Data Pointer contains        |
++|                     unsigned int *data          : Data Pointer contains        |
+ |                                          configuration parameters as below |
+ |                     data[0]                  : Warning delay value
+ |                                                                            |
+@@ -448,7 +448,7 @@ INT i_APCI035_ReadTimerWatchdog(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI035_ConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	devpriv->tsk_Current = current;
+ 	outl(0x200 | 0, devpriv->iobase + 128 + 0x4);
+@@ -467,7 +467,7 @@ INT i_APCI035_ConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI035_ReadAnalogInput                          |
+ |			          (comedi_device *dev,comedi_subdevice *s,       |
+-|                     comedi_insn *insn,lsampl_t *data)                      |
++|                     comedi_insn *insn,unsigned int *data)                      |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel			         |
+ +----------------------------------------------------------------------------+
+@@ -485,7 +485,7 @@ INT i_APCI035_ConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI035_ReadAnalogInput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_CommandRegister = 0;
+ /******************/
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
+index 8ae0af6fdd09..0e4ec157ad3a 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
+@@ -102,19 +102,19 @@ comedi_lrange range_apci035_ai = { 8, {
+ /* TIMER */
+ /* timer value is passed as u seconds */
+ INT i_APCI035_ConfigTimerWatchdog(comedi_device *dev, comedi_subdevice *s,
+-				  comedi_insn *insn, lsampl_t *data);
++				  comedi_insn *insn, unsigned int *data);
+ INT i_APCI035_StartStopWriteTimerWatchdog(comedi_device *dev,
+ 					  comedi_subdevice *s,
+-					  comedi_insn *insn, lsampl_t *data);
++					  comedi_insn *insn, unsigned int *data);
+ INT i_APCI035_ReadTimerWatchdog(comedi_device *dev, comedi_subdevice *s,
+-				comedi_insn *insn, lsampl_t *data);
++				comedi_insn *insn, unsigned int *data);
+ 
+ /* Temperature Related Defines (Analog Input Subdevice) */
+ 
+ INT i_APCI035_ConfigAnalogInput(comedi_device *dev, comedi_subdevice *s,
+-				comedi_insn *insn, lsampl_t *data);
++				comedi_insn *insn, unsigned int *data);
+ INT i_APCI035_ReadAnalogInput(comedi_device *dev, comedi_subdevice *s,
+-			      comedi_insn *insn, lsampl_t *data);
++			      comedi_insn *insn, unsigned int *data);
+ 
+ /* Interrupt */
+ static void v_APCI035_Interrupt(int irq, void *d);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+index b9fa99723f90..5f65d1d4baab 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+@@ -60,12 +60,12 @@ UINT ui_InterruptStatus = 0;
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1032_ConfigDigitalInput                      |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures the digital input Subdevice                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : comedi_device *dev : Driver handle                     |
+-|                     lsampl_t *data         : Data Pointer contains         |
++|                     unsigned int *data         : Data Pointer contains         |
+ |                                          configuration parameters as below |
+ |                                                                            |
+ |			  data[0]            : 1 Enable  Digital Input Interrupt |
+@@ -85,7 +85,7 @@ UINT ui_InterruptStatus = 0;
+ */
+ 
+ INT i_APCI1032_ConfigDigitalInput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue;
+ 
+@@ -129,13 +129,13 @@ INT i_APCI1032_ConfigDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1032_Read1DigitalInput                       |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the digital input                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : comedi_device *dev      : Driver handle                |
+ |		              UINT ui_Channel : Channel number to read       |
+-|                     lsampl_t *data          : Data Pointer to read status  |
++|                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -145,7 +145,7 @@ INT i_APCI1032_ConfigDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1032_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue = 0;
+ 	UINT ui_Channel;
+@@ -167,7 +167,7 @@ INT i_APCI1032_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1032_ReadMoreDigitalInput                    |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                     comedi_insn *insn,lsampl_t *data)                      |
++|                     comedi_insn *insn,unsigned int *data)                      |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the Requested digital inputs      |
+ +----------------------------------------------------------------------------+
+@@ -184,7 +184,7 @@ INT i_APCI1032_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+ */
+ 
+ INT i_APCI1032_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_PortValue = data[0];
+ 	UINT ui_Mask = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
+index c47a95731c98..51abd4f073de 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
+@@ -48,13 +48,13 @@
+ // for di read
+ 
+ INT i_APCI1032_ConfigDigitalInput(comedi_device *dev, comedi_subdevice *s,
+-				  comedi_insn *insn, lsampl_t *data);
++				  comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1032_Read1DigitalInput(comedi_device *dev, comedi_subdevice *s,
+-				 comedi_insn *insn, lsampl_t *data);
++				 comedi_insn *insn, unsigned int *data);
+ 
+ INT i_APCI1032_ReadMoreDigitalInput(comedi_device *dev, comedi_subdevice *s,
+-				    comedi_insn *insn, lsampl_t *data);
++				    comedi_insn *insn, unsigned int *data);
+ 
+ // Interrupt functions.....
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+index ff7284d787b5..33885c55be9d 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+@@ -62,7 +62,7 @@ int i_TimerCounter1Enabled = 0, i_TimerCounter2Enabled =
+   +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_ConfigDigitalInputEvent                 |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : An event can be generated for each port.               |
+ |                     The first event is related to the first 8 channels     |
+@@ -71,7 +71,7 @@ int i_TimerCounter1Enabled = 0, i_TimerCounter2Enabled =
+ |                     events have occurred                                   |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : comedi_device *dev : Driver handle                     |
+-|                     lsampl_t *data     : Data Pointer contains             |
++|                     unsigned int *data     : Data Pointer contains             |
+ |                                          configuration parameters as below |
+ |                                                                            |
+ |			  data[0]            :Number of the input port on        |
+@@ -138,7 +138,7 @@ int i_TimerCounter1Enabled = 0, i_TimerCounter2Enabled =
+ */
+ 
+ INT i_APCI1500_ConfigDigitalInputEvent(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_PatternPolarity = 0, i_PatternTransition = 0, i_PatternMask = 0;
+ 	int i_MaxChannel = 0, i_Count = 0, i_EventMask = 0;
+@@ -501,13 +501,13 @@ INT i_APCI1500_ConfigDigitalInputEvent(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_StartStopInputEvent                     |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              :  Allows or disallows a port event                      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : comedi_device *dev      : Driver handle                |
+ |		              UINT ui_Channel : Channel number to read       |
+-|                     lsampl_t *data          : Data Pointer to read status  |
++|                     unsigned int *data          : Data Pointer to read status  |
+                       data[0]                 :0 Start input event
+                                                1 Stop input event
+                       data[1]                 :No of port (1 or 2)
+@@ -520,7 +520,7 @@ INT i_APCI1500_ConfigDigitalInputEvent(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI1500_StartStopInputEvent(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_Event1InterruptStatus = 0, i_Event2InterruptStatus =
+ 		0, i_RegValue;
+@@ -769,13 +769,13 @@ int i_APCI1500_StartStopInputEvent(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_Initialisation                          |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the digital input                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : comedi_device *dev      : Driver handle                |
+ |		              UINT ui_Channel : Channel number to read       |
+-|                     lsampl_t *data          : Data Pointer to read status  |
++|                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -785,7 +785,7 @@ int i_APCI1500_StartStopInputEvent(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1500_Initialisation(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_DummyRead = 0;
+     /******************/
+@@ -938,7 +938,7 @@ INT i_APCI1500_Initialisation(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_ReadMoreDigitalInput                    |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                     comedi_insn *insn,lsampl_t *data)                      |
++|                     comedi_insn *insn,unsigned int *data)                      |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the Requested digital inputs      |
+ +----------------------------------------------------------------------------+
+@@ -958,7 +958,7 @@ INT i_APCI1500_Initialisation(comedi_device * dev, comedi_subdevice * s,
+ */
+ 
+ INT i_APCI1500_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_PortValue = data[1];
+ 	UINT ui_Mask = 0;
+@@ -1016,14 +1016,14 @@ INT i_APCI1500_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_ConfigDigitalOutputErrorInterrupt
+                       (comedi_device *dev,comedi_subdevice *s comedi_insn
+-                      *insn,lsampl_t *data)                                  |
++                      *insn,unsigned int *data)                                  |
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures the digital output memory and the digital
+                       output error interrupt                                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : comedi_device *dev : Driver handle                     |
+-|                     lsampl_t *data         : Data Pointer contains         |
++|                     unsigned int *data         : Data Pointer contains         |
+ |                                          configuration parameters as below |
+ |                      comedi_subdevice *s,   :pointer to subdevice structure
+                        comedi_insn *insn      :pointer to insn structure                                                                                                                |
+@@ -1041,7 +1041,7 @@ INT i_APCI1500_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI1500_ConfigDigitalOutputErrorInterrupt(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	devpriv->b_OutputMemoryStatus = data[0];
+ 	return insn->n;
+@@ -1051,7 +1051,7 @@ int i_APCI1500_ConfigDigitalOutputErrorInterrupt(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_WriteDigitalOutput                      |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes port value  To the selected port                |
+ +----------------------------------------------------------------------------+
+@@ -1068,7 +1068,7 @@ int i_APCI1500_ConfigDigitalOutputErrorInterrupt(comedi_device * dev,
+ */
+ 
+ INT i_APCI1500_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	static UINT ui_Temp = 0;
+ 	UINT ui_Temp1;
+@@ -1215,7 +1215,7 @@ INT i_APCI1500_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_ConfigCounterTimerWatchdog(comedi_device
+-                   *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)|
++                   *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data)|
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Watchdog                                |
+@@ -1223,7 +1223,7 @@ INT i_APCI1500_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ | Input Parameters  : comedi_device *dev      : Driver handle                |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+-|                     lsampl_t *data         : Data Pointer to read status                                                       data[0]                : 2     APCI1500_1_8_KHZ
++|                     unsigned int *data         : Data Pointer to read status                                                       data[0]                : 2     APCI1500_1_8_KHZ
+ |                                              1     APCI1500_3_6_KHZ        |
+ |                                              0     APCI1500_115_KHZ
+                       data[1]                : 0     Counter1/Timer1
+@@ -1262,7 +1262,7 @@ INT i_APCI1500_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ */
+ 
+ int i_APCI1500_ConfigCounterTimerWatchdog(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_TimerCounterMode, i_MasterConfiguration;
+ 
+@@ -1836,14 +1836,14 @@ int i_APCI1500_ConfigCounterTimerWatchdog(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_StartStopTriggerTimerCounterWatchdog      |
+ |				(comedi_device *dev,comedi_subdevice *s,
+-                         comedi_insn *insn,lsampl_t *data);                  |
++                         comedi_insn *insn,unsigned int *data);                  |
+ +----------------------------------------------------------------------------+
+ | Task              : Start / Stop or trigger the timer counter or Watchdog  |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : comedi_device *dev     : Driver handle                 |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+-|                     lsampl_t *data         : Data Pointer to read status   |
++|                     unsigned int *data         : Data Pointer to read status   |
+                       data[0]                : 0     Counter1/Timer1
+                                                1     Counter2/Timer2
+                                                2     Counter3/Watchdog
+@@ -1861,7 +1861,7 @@ int i_APCI1500_ConfigCounterTimerWatchdog(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_CommandAndStatusValue;
+ 
+@@ -2161,14 +2161,14 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1500_ReadCounterTimerWatchdog                |
+ |			(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+-                    lsampl_t *data); 	                                     |
++                    unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Watchdog                                      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   comedi_device *dev      : Driver handle              |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+-|                     lsampl_t *data          : Data Pointer to read status  |
++|                     unsigned int *data          : Data Pointer to read status  |
+                       data[0]                : 0     Counter1/Timer1
+                                                1     Counter2/Timer2
+                                                2     Counter3/Watchdog
+@@ -2183,7 +2183,7 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(comedi_device * dev,
+ */
+ 
+ int i_APCI1500_ReadCounterTimerWatchdog(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int i_CommandAndStatusValue;
+ 	switch (data[0]) {
+@@ -2352,14 +2352,14 @@ int i_APCI1500_ReadCounterTimerWatchdog(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int  i_APCI1500_ReadInterruptMask                      |
+ |			(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+-                    lsampl_t *data); 	                                     |
++                    unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read the interrupt mask                                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   comedi_device *dev      : Driver handle              |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+-|                     lsampl_t *data          : Data Pointer to read status  |
++|                     unsigned int *data          : Data Pointer to read status  |
+ 
+ 
+ +----------------------------------------------------------------------------+
+@@ -2371,7 +2371,7 @@ int i_APCI1500_ReadCounterTimerWatchdog(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI1500_ReadInterruptMask(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = i_InterruptMask;
+ 	data[1] = i_InputChannel;
+@@ -2383,14 +2383,14 @@ int i_APCI1500_ReadInterruptMask(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int  i_APCI1500_ConfigureInterrupt                     |
+ |			(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+-                    lsampl_t *data); 	                                     |
++                    unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures the interrupt registers                     |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   comedi_device *dev      : Driver handle              |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+-|                     lsampl_t *data          : Data Pointer                 |
++|                     unsigned int *data          : Data Pointer                 |
+ 
+ 
+ +----------------------------------------------------------------------------+
+@@ -2402,7 +2402,7 @@ int i_APCI1500_ReadInterruptMask(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI1500_ConfigureInterrupt(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Status;
+ 	int i_RegValue;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h
+index a0d924a8e6ba..f1519e70cfbc 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h
+@@ -117,49 +117,49 @@ enum {
+ 
+  /*----------DIGITAL INPUT----------------*/
+ static int i_APCI1500_Initialisation(comedi_device *dev, comedi_subdevice *s,
+-				     comedi_insn *insn, lsampl_t *data);
++				     comedi_insn *insn, unsigned int *data);
+ static int i_APCI1500_ConfigDigitalInputEvent(comedi_device *dev,
+ 					      comedi_subdevice *s,
+ 					      comedi_insn *insn,
+-					      lsampl_t *data);
++					      unsigned int *data);
+ 
+ static int i_APCI1500_StartStopInputEvent(comedi_device *dev,
+ 					  comedi_subdevice *s,
+-					  comedi_insn *insn, lsampl_t *data);
++					  comedi_insn *insn, unsigned int *data);
+ static int i_APCI1500_ReadMoreDigitalInput(comedi_device *dev,
+ 					   comedi_subdevice *s,
+-					   comedi_insn *insn, lsampl_t *data);
++					   comedi_insn *insn, unsigned int *data);
+ 
+ /*----------	DIGITAL OUTPUT------------*/
+ static int i_APCI1500_ConfigDigitalOutputErrorInterrupt(comedi_device *dev,
+ 							comedi_subdevice *s,
+ 							comedi_insn *insn,
+-							lsampl_t *data);
++							unsigned int *data);
+ static int i_APCI1500_WriteDigitalOutput(comedi_device *dev,
+ 					 comedi_subdevice *s,
+-					 comedi_insn *insn, lsampl_t *data);
++					 comedi_insn *insn, unsigned int *data);
+ 
+ /*----------TIMER----------------*/
+ static int i_APCI1500_ConfigCounterTimerWatchdog(comedi_device *dev,
+ 						 comedi_subdevice *s,
+ 						 comedi_insn *insn,
+-						 lsampl_t *data);
++						 unsigned int *data);
+ static int i_APCI1500_StartStopTriggerTimerCounterWatchdog(comedi_device *dev,
+ 							   comedi_subdevice *s,
+ 							   comedi_insn *insn,
+-							   lsampl_t *data);
++							   unsigned int *data);
+ static int i_APCI1500_ReadCounterTimerWatchdog(comedi_device *dev,
+ 					       comedi_subdevice *s,
+ 					       comedi_insn *insn,
+-					       lsampl_t *data);
++					       unsigned int *data);
+ static int i_APCI1500_ReadInterruptMask(comedi_device *dev,
+ 					comedi_subdevice *s,
+-					comedi_insn *insn, lsampl_t *data);
++					comedi_insn *insn, unsigned int *data);
+ 
+ /*----------INTERRUPT HANDLER------*/
+ static void v_APCI1500_Interrupt(int irq, void *d);
+ static int i_APCI1500_ConfigureInterrupt(comedi_device *dev,
+ 					 comedi_subdevice *s,
+-					 comedi_insn *insn, lsampl_t *data);
++					 comedi_insn *insn, unsigned int *data);
+ /*----------RESET---------------*/
+ static int i_APCI1500_Reset(comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
+index 57e53f4d3735..5be566eda898 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
+@@ -57,14 +57,14 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_Read1DigitalInput                       |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the digital input                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : comedi_device *dev      : Driver handle                |
+ |		       comedi_subdevice *s,   :pointer to subdevice structure
+                        comedi_insn *insn      :pointer to insn structure     |
+-|                     lsampl_t *data          : Data Pointer to read status  |
++|                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -74,7 +74,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1516_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue = 0;
+ 	UINT ui_Channel;
+@@ -97,14 +97,14 @@ INT i_APCI1516_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_ReadMoreDigitalInput                    |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                     comedi_insn *insn,lsampl_t *data)                      |
++|                     comedi_insn *insn,unsigned int *data)                      |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the Requested digital inputs      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : comedi_device *dev      : Driver handle                |
+ |                      comedi_subdevice *s,   :pointer to subdevice structure
+                        comedi_insn *insn      :pointer to insn structure     |
+-|                      lsampl_t *data         : Data Pointer to read status  |
++|                      unsigned int *data         : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -115,7 +115,7 @@ INT i_APCI1516_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+ */
+ 
+ INT i_APCI1516_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	UINT ui_PortValue = data[0];
+@@ -149,13 +149,13 @@ INT i_APCI1516_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_ConfigDigitalOutput (comedi_device *dev,
+-                    comedi_subdevice *s comedi_insn *insn,lsampl_t *data)    |
++                    comedi_subdevice *s comedi_insn *insn,unsigned int *data)    |
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Digital Output Subdevice.               |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : comedi_device *dev : Driver handle                     |
+-|                     lsampl_t *data         : Data Pointer contains         |
++|                     unsigned int *data         : Data Pointer contains         |
+ |                                          configuration parameters as below |
+ |                      comedi_subdevice *s,   :pointer to subdevice structure
+                        comedi_insn *insn      :pointer to insn structure                                                           |
+@@ -172,7 +172,7 @@ INT i_APCI1516_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI1516_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	devpriv->b_OutputMemoryStatus = data[0];
+ 	return insn->n;
+@@ -182,14 +182,14 @@ int i_APCI1516_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_WriteDigitalOutput                      |
+ |			(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+-                     lsampl_t *data)                                         |
++                     unsigned int *data)                                         |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes port value  To the selected port                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : comedi_device *dev      : Driver handle                |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+-|                    lsampl_t *data           : Data Pointer to read status  |
++|                    unsigned int *data           : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -200,7 +200,7 @@ int i_APCI1516_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ */
+ 
+ INT i_APCI1516_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp, ui_Temp1;
+ 	UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
+@@ -342,14 +342,14 @@ INT i_APCI1516_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_ReadDigitalOutput                       |
+ |			(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+-                    lsampl_t *data) 	                                     |
++                    unsigned int *data) 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : comedi_device *dev      : Driver handle                |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+-|                     lsampl_t *data          : Data Pointer to read status  |
++|                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -360,7 +360,7 @@ INT i_APCI1516_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ */
+ 
+ INT i_APCI1516_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	UINT ui_Temp;
+@@ -401,7 +401,7 @@ INT i_APCI1516_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_ConfigWatchdog(comedi_device *dev,
+-                      comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)  |
++                      comedi_subdevice *s,comedi_insn *insn,unsigned int *data)  |
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Watchdog                                |
+@@ -409,7 +409,7 @@ INT i_APCI1516_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ | Input Parameters  :   comedi_device *dev      : Driver handle              |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+-|                     lsampl_t *data          : Data Pointer to read status                                                     |
++|                     unsigned int *data          : Data Pointer to read status                                                     |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -420,7 +420,7 @@ INT i_APCI1516_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ */
+ 
+ int i_APCI1516_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0] == 0) {
+ 		//Disable the watchdog
+@@ -448,14 +448,14 @@ int i_APCI1516_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+     +----------------------------------------------------------------------------+
+     | Function   Name   : int i_APCI1516_StartStopWriteWatchdog                  |
+     |                           (comedi_device *dev,comedi_subdevice *s,
+-    comedi_insn *insn,lsampl_t *data);                      |
++    comedi_insn *insn,unsigned int *data);                      |
+     +----------------------------------------------------------------------------+
+     | Task              : Start / Stop The Watchdog                              |
+     +----------------------------------------------------------------------------+
+     | Input Parameters  : comedi_device *dev      : Driver handle                |
+     |                     comedi_subdevice *s,   :pointer to subdevice structure
+     comedi_insn *insn      :pointer to insn structure      |
+-    |                     lsampl_t *data          : Data Pointer to read status  |
++    |                     unsigned int *data          : Data Pointer to read status  |
+     +----------------------------------------------------------------------------+
+     | Output Parameters :       --                                                                                                       |
+     +----------------------------------------------------------------------------+
+@@ -466,7 +466,7 @@ int i_APCI1516_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+   */
+ 
+ int i_APCI1516_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+ 	case 0:		//stop the watchdog
+@@ -493,14 +493,14 @@ int i_APCI1516_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1516_ReadWatchdog                            |
+ |			(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+-                    lsampl_t *data); 	                                     |
++                    unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Watchdog                                      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   comedi_device *dev      : Driver handle              |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+-|                     lsampl_t *data          : Data Pointer to read status  |
++|                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -511,7 +511,7 @@ int i_APCI1516_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+ */
+ 
+ int i_APCI1516_ReadWatchdog(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = inw(devpriv->i_IobaseAddon + APCI1516_WATCHDOG_STATUS) & 0x1;
+ 	return insn->n;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h
+index c07598d61e74..176e4785819e 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h
+@@ -39,26 +39,26 @@
+ 
+ //Digital Input
+ INT i_APCI1516_ReadMoreDigitalInput(comedi_device *dev, comedi_subdevice *s,
+-				    comedi_insn *insn, lsampl_t *data);
++				    comedi_insn *insn, unsigned int *data);
+ INT i_APCI1516_Read1DigitalInput(comedi_device *dev, comedi_subdevice *s,
+-				 comedi_insn *insn, lsampl_t *data);
++				 comedi_insn *insn, unsigned int *data);
+ 
+ //Digital Output
+ int i_APCI1516_ConfigDigitalOutput(comedi_device *dev, comedi_subdevice *s,
+-				   comedi_insn *insn, lsampl_t *data);
++				   comedi_insn *insn, unsigned int *data);
+ INT i_APCI1516_WriteDigitalOutput(comedi_device *dev, comedi_subdevice *s,
+-				  comedi_insn *insn, lsampl_t *data);
++				  comedi_insn *insn, unsigned int *data);
+ INT i_APCI1516_ReadDigitalOutput(comedi_device *dev, comedi_subdevice *s,
+-				 comedi_insn *insn, lsampl_t *data);
++				 comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+ // timer value is passed as u seconds
+ int i_APCI1516_ConfigWatchdog(comedi_device *dev, comedi_subdevice *s,
+-			      comedi_insn *insn, lsampl_t *data);
++			      comedi_insn *insn, unsigned int *data);
+ int i_APCI1516_StartStopWriteWatchdog(comedi_device *dev, comedi_subdevice *s,
+-				      comedi_insn *insn, lsampl_t *data);
++				      comedi_insn *insn, unsigned int *data);
+ int i_APCI1516_ReadWatchdog(comedi_device *dev, comedi_subdevice *s,
+-			    comedi_insn *insn, lsampl_t *data);
++			    comedi_insn *insn, unsigned int *data);
+ 
+ //reset
+ INT i_APCI1516_Reset(comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+index f92253455374..cb7510930626 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+@@ -63,12 +63,12 @@ UINT ui_InterruptData, ui_Type;
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_ConfigDigitalInput                      |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures the digital input Subdevice                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : comedi_device *dev : Driver handle                     |
+-|                     lsampl_t *data         : Data Pointer contains         |
++|                     unsigned int *data         : Data Pointer contains         |
+ |                                          configuration parameters as below |
+ |                                                                            |
+ |			  data[0]            : 1 Enable  Digital Input Interrupt |
+@@ -87,7 +87,7 @@ UINT ui_InterruptData, ui_Type;
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1564_ConfigDigitalInput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	devpriv->tsk_Current = current;
+    /*******************************/
+@@ -132,13 +132,13 @@ INT i_APCI1564_ConfigDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_Read1DigitalInput                       |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the digital input                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : comedi_device *dev      : Driver handle                |
+ |		              UINT ui_Channel : Channel number to read       |
+-|                     lsampl_t *data          : Data Pointer to read status  |
++|                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -148,7 +148,7 @@ INT i_APCI1564_ConfigDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1564_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue = 0;
+ 	UINT ui_Channel;
+@@ -172,7 +172,7 @@ INT i_APCI1564_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_ReadMoreDigitalInput                    |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                     comedi_insn *insn,lsampl_t *data)                      |
++|                     comedi_insn *insn,unsigned int *data)                      |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the Requested digital inputs      |
+ +----------------------------------------------------------------------------+
+@@ -188,7 +188,7 @@ INT i_APCI1564_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1564_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_PortValue = data[0];
+ 	UINT ui_Mask = 0;
+@@ -234,7 +234,7 @@ INT i_APCI1564_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_ConfigDigitalOutput                     |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Digital Output Subdevice.               |
+ +----------------------------------------------------------------------------+
+@@ -256,7 +256,7 @@ INT i_APCI1564_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1564_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command = 0;
+ 
+@@ -297,7 +297,7 @@ INT i_APCI1564_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_WriteDigitalOutput                      |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes port value  To the selected port                |
+ +----------------------------------------------------------------------------+
+@@ -313,7 +313,7 @@ INT i_APCI1564_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1564_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp, ui_Temp1;
+ 	UINT ui_NoOfChannel;
+@@ -471,7 +471,7 @@ INT i_APCI1564_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_ReadDigitalOutput                       |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+@@ -487,7 +487,7 @@ INT i_APCI1564_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1564_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+ 	UINT ui_NoOfChannel;
+@@ -538,7 +538,7 @@ INT i_APCI1564_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_ConfigTimerCounterWatchdog              |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Timer , Counter or Watchdog             |
+ +----------------------------------------------------------------------------+
+@@ -565,7 +565,7 @@ INT i_APCI1564_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1564_ConfigTimerCounterWatchdog(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0;
+ 	devpriv->tsk_Current = current;
+@@ -696,7 +696,7 @@ INT i_APCI1564_ConfigTimerCounterWatchdog(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_StartStopWriteTimerCounterWatchdog      |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Start / Stop The Selected Timer , Counter or Watchdog  |
+ +----------------------------------------------------------------------------+
+@@ -719,7 +719,7 @@ INT i_APCI1564_ConfigTimerCounterWatchdog(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1564_StartStopWriteTimerCounterWatchdog(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0;
+ 	if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+@@ -796,7 +796,7 @@ INT i_APCI1564_StartStopWriteTimerCounterWatchdog(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI1564_ReadTimerCounterWatchdog                |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Selected Timer , Counter or Watchdog          |
+ +----------------------------------------------------------------------------+
+@@ -814,7 +814,7 @@ INT i_APCI1564_StartStopWriteTimerCounterWatchdog(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI1564_ReadTimerCounterWatchdog(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0;
+ 
+@@ -879,7 +879,7 @@ INT i_APCI1564_ReadTimerCounterWatchdog(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function   Name   :  int i_APCI1564_ReadInterruptStatus                    |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              :Reads the interrupt status register                     |
+ +----------------------------------------------------------------------------+
+@@ -893,7 +893,7 @@ INT i_APCI1564_ReadTimerCounterWatchdog(comedi_device * dev,
+ */
+ 
+ int i_APCI1564_ReadInterruptStatus(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	*data = ui_Type;
+ 	return insn->n;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
+index 2244686c0092..914231f2edb6 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
+@@ -83,34 +83,34 @@
+ //DI
+ // for di read
+ INT i_APCI1564_ConfigDigitalInput(comedi_device *dev, comedi_subdevice *s,
+-				  comedi_insn *insn, lsampl_t *data);
++				  comedi_insn *insn, unsigned int *data);
+ INT i_APCI1564_Read1DigitalInput(comedi_device *dev, comedi_subdevice *s,
+-				 comedi_insn *insn, lsampl_t *data);
++				 comedi_insn *insn, unsigned int *data);
+ INT i_APCI1564_ReadMoreDigitalInput(comedi_device *dev, comedi_subdevice *s,
+-				    comedi_insn *insn, lsampl_t *data);
++				    comedi_insn *insn, unsigned int *data);
+ 
+ //DO
+ int i_APCI1564_ConfigDigitalOutput(comedi_device *dev, comedi_subdevice *s,
+-				   comedi_insn *insn, lsampl_t *data);
++				   comedi_insn *insn, unsigned int *data);
+ INT i_APCI1564_WriteDigitalOutput(comedi_device *dev, comedi_subdevice *s,
+-				  comedi_insn *insn, lsampl_t *data);
++				  comedi_insn *insn, unsigned int *data);
+ INT i_APCI1564_ReadDigitalOutput(comedi_device *dev, comedi_subdevice *s,
+-				 comedi_insn *insn, lsampl_t *data);
++				 comedi_insn *insn, unsigned int *data);
+ int i_APCI1564_ReadInterruptStatus(comedi_device *dev, comedi_subdevice *s,
+-				   comedi_insn *insn, lsampl_t *data);
++				   comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+ // timer value is passed as u seconds
+ INT i_APCI1564_ConfigTimerCounterWatchdog(comedi_device *dev,
+ 					  comedi_subdevice *s,
+-					  comedi_insn *insn, lsampl_t *data);
++					  comedi_insn *insn, unsigned int *data);
+ int i_APCI1564_StartStopWriteTimerCounterWatchdog(comedi_device *dev,
+ 						  comedi_subdevice *s,
+ 						  comedi_insn *insn,
+-						  lsampl_t *data);
++						  unsigned int *data);
+ int i_APCI1564_ReadTimerCounterWatchdog(comedi_device *dev,
+ 					comedi_subdevice *s,
+-					comedi_insn *insn, lsampl_t *data);
++					comedi_insn *insn, unsigned int *data);
+ 
+ // INTERRUPT
+ static VOID v_APCI1564_Interrupt(int irq, void *d);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
+index f505d9052ce2..0955fdf31cd1 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
+@@ -61,7 +61,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ |                          (comedi_device    *dev,                           |
+ |                           comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+-|                           lsampl_t         *data)                          |
++|                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+ | Task           APCI16XX_TTL_INIT (using defaults)   :                      |
+ |                Configure the TTL I/O operating mode from all ports         |
+@@ -91,7 +91,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ */
+ 
+ int i_APCI16XX_InsnConfigInitTTLIO(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Command = 0;
+@@ -254,7 +254,7 @@ int i_APCI16XX_InsnConfigInitTTLIO(comedi_device * dev,
+ |                          (comedi_device    *dev,                           |
+ |                           comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+-|                           lsampl_t         *data)                          |
++|                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+ | Task              : Read the status from selected TTL digital input        |
+ |                     (b_InputChannel)                                       |
+@@ -284,7 +284,7 @@ int i_APCI16XX_InsnConfigInitTTLIO(comedi_device * dev,
+ */
+ 
+ int i_APCI16XX_InsnBitsReadTTLIO(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Command = 0;
+@@ -414,7 +414,7 @@ int i_APCI16XX_InsnBitsReadTTLIO(comedi_device * dev,
+ |                          (comedi_device    *dev,                           |
+ |                           comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+-|                           lsampl_t         *data)                          |
++|                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+ | Task              : Read the status from all digital input ports           |
+ +----------------------------------------------------------------------------+
+@@ -431,13 +431,13 @@ int i_APCI16XX_InsnBitsReadTTLIO(comedi_device * dev,
+ */
+ 
+ int i_APCI16XX_InsnReadTTLIOAllPortValue(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_Command = (BYTE) CR_AREF(insn->chanspec);
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Cpt = 0;
+ 	BYTE b_NumberOfPort = 0;
+-	lsampl_t *pls_ReadData = data;
++	unsigned int *pls_ReadData = data;
+ 
+ 	/********************/
+ 	/* Test the command */
+@@ -539,7 +539,7 @@ int i_APCI16XX_InsnReadTTLIOAllPortValue(comedi_device * dev,
+ |                          (comedi_device    *dev,                           |
+ |                           comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+-|                           lsampl_t         *data)                          |
++|                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+ | Task              : Set the state from selected TTL digital output         |
+ |                     (b_OutputChannel)                                      |
+@@ -571,7 +571,7 @@ int i_APCI16XX_InsnReadTTLIOAllPortValue(comedi_device * dev,
+ */
+ 
+ int i_APCI16XX_InsnBitsWriteTTLIO(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Command = 0;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h
+index ff2e411e207d..6e8d09407807 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h
+@@ -64,7 +64,7 @@ static const comedi_lrange range_apci16xx_ttl = { 12,
+ 
+ int i_APCI16XX_InsnConfigInitTTLIO(comedi_device *dev,
+ 				   comedi_subdevice *s, comedi_insn *insn,
+-				   lsampl_t *data);
++				   unsigned int *data);
+ 
+ /*
+ +----------------------------------------------------------------------------+
+@@ -74,11 +74,11 @@ int i_APCI16XX_InsnConfigInitTTLIO(comedi_device *dev,
+ 
+ int i_APCI16XX_InsnBitsReadTTLIO(comedi_device *dev,
+ 				 comedi_subdevice *s, comedi_insn *insn,
+-				 lsampl_t *data);
++				 unsigned int *data);
+ 
+ int i_APCI16XX_InsnReadTTLIOAllPortValue(comedi_device *dev,
+ 					 comedi_subdevice *s,
+-					 comedi_insn *insn, lsampl_t *data);
++					 comedi_insn *insn, unsigned int *data);
+ 
+ /*
+ +----------------------------------------------------------------------------+
+@@ -88,7 +88,7 @@ int i_APCI16XX_InsnReadTTLIOAllPortValue(comedi_device *dev,
+ 
+ int i_APCI16XX_InsnBitsWriteTTLIO(comedi_device *dev,
+ 				  comedi_subdevice *s, comedi_insn *insn,
+-				  lsampl_t *data);
++				  unsigned int *data);
+ 
+ int i_APCI16XX_Reset(comedi_device *dev);
+ #endif
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
+index 7fad966d4721..fd4ae6abbb3f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
+@@ -57,7 +57,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2016_ConfigDigitalOutput                     |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Digital Output Subdevice.               |
+ +----------------------------------------------------------------------------+
+@@ -76,7 +76,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI2016_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if ((data[0] != 0) && (data[0] != 1)) {
+ 		comedi_error(dev,
+@@ -96,7 +96,7 @@ int i_APCI2016_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2016_WriteDigitalOutput                      |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes port value  To the selected port                |
+ +----------------------------------------------------------------------------+
+@@ -112,7 +112,7 @@ int i_APCI2016_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI2016_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_NoOfChannel;
+ 	UINT ui_Temp, ui_Temp1;
+@@ -251,7 +251,7 @@ int i_APCI2016_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2016_BitsDigitalOutput                       |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+@@ -267,7 +267,7 @@ int i_APCI2016_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI2016_BitsDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+ 	UINT ui_NoOfChannel;
+@@ -321,14 +321,14 @@ int i_APCI2016_BitsDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2016_ConfigWatchdog                          |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Watchdog                                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   comedi_device *dev      : Driver handle              |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure |
+ |                     comedi_insn *insn      :pointer to insn structure      |
+-|                     lsampl_t *data          : Data Pointer to read status  |
++|                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -338,7 +338,7 @@ int i_APCI2016_BitsDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI2016_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	if (data[0] == 0) {
+@@ -364,14 +364,14 @@ int i_APCI2016_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2016_StartStopWriteWatchdog                  |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Start / Stop The Watchdog                              |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : comedi_device *dev      : Driver handle                |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure |
+ |                     comedi_insn *insn      :pointer to insn structure      |
+-|                     lsampl_t *data          : Data Pointer to read status  |
++|                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -381,7 +381,7 @@ int i_APCI2016_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI2016_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	switch (data[0]) {
+@@ -410,14 +410,14 @@ int i_APCI2016_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2016_ReadWatchdog                            |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Watchdog                                      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : comedi_device *dev      : Driver handle                |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure |
+ |                     comedi_insn *insn      :pointer to insn structure      |
+-|                     lsampl_t *data          : Data Pointer to read status  |
++|                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -428,7 +428,7 @@ int i_APCI2016_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+ */
+ 
+ int i_APCI2016_ReadWatchdog(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	udelay(5);
+ 	data[0] = inw(devpriv->i_IobaseAddon + APCI2016_WATCHDOG_STATUS) & 0x1;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
+index 0dadbddcc5fc..3ca52e9eca5a 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
+@@ -41,25 +41,25 @@
+ 
+ //DO
+ int i_APCI2016_ConfigDigitalOutput(comedi_device *dev, comedi_subdevice *s,
+-				   comedi_insn *insn, lsampl_t *data);
++				   comedi_insn *insn, unsigned int *data);
+ 
+ int i_APCI2016_WriteDigitalOutput(comedi_device *dev, comedi_subdevice *s,
+-				  comedi_insn *insn, lsampl_t *data);
++				  comedi_insn *insn, unsigned int *data);
+ 
+ int i_APCI2016_BitsDigitalOutput(comedi_device *dev, comedi_subdevice *s,
+-				 comedi_insn *insn, lsampl_t *data);
++				 comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+ // timer value is passed as u seconds
+ 
+ int i_APCI2016_ConfigWatchdog(comedi_device *dev, comedi_subdevice *s,
+-			      comedi_insn *insn, lsampl_t *data);
++			      comedi_insn *insn, unsigned int *data);
+ 
+ int i_APCI2016_StartStopWriteWatchdog(comedi_device *dev, comedi_subdevice *s,
+-				      comedi_insn *insn, lsampl_t *data);
++				      comedi_insn *insn, unsigned int *data);
+ 
+ int i_APCI2016_ReadWatchdog(comedi_device *dev, comedi_subdevice *s,
+-			    comedi_insn *insn, lsampl_t *data);
++			    comedi_insn *insn, unsigned int *data);
+ 
+ // Interrupt functions.....
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
+index 117193c6916e..4345dda7f99d 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
+@@ -58,7 +58,7 @@ UINT ui_InterruptData, ui_Type;
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2032_ConfigDigitalOutput                     |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Digital Output Subdevice.               |
+ +----------------------------------------------------------------------------+
+@@ -80,7 +80,7 @@ UINT ui_InterruptData, ui_Type;
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI2032_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command = 0;
+ 	devpriv->tsk_Current = current;
+@@ -118,7 +118,7 @@ int i_APCI2032_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2032_WriteDigitalOutput                      |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes port value  To the selected port                |
+ +----------------------------------------------------------------------------+
+@@ -135,7 +135,7 @@ int i_APCI2032_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ */
+ 
+ INT i_APCI2032_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp, ui_Temp1;
+ 	UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
+@@ -297,7 +297,7 @@ INT i_APCI2032_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2032_ReadDigitalOutput                       |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+@@ -314,7 +314,7 @@ INT i_APCI2032_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ */
+ 
+ INT i_APCI2032_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+ 	UINT ui_NoOfChannel;
+@@ -363,7 +363,7 @@ INT i_APCI2032_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : INT i_APCI2032_ConfigWatchdog(comedi_device
+-                   *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)|
++                   *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data)|
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Watchdog                                |
+@@ -371,7 +371,7 @@ INT i_APCI2032_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ | Input Parameters  : comedi_device *dev      : Driver handle                |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+-|                     lsampl_t *data          : Data Pointer to read status                                                                                                             |
++|                     unsigned int *data          : Data Pointer to read status                                                                                                             |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -381,7 +381,7 @@ INT i_APCI2032_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI2032_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0] == 0) {
+ 		//Disable the watchdog
+@@ -404,14 +404,14 @@ INT i_APCI2032_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+     +----------------------------------------------------------------------------+
+     | Function   Name   : int i_APCI2032_StartStopWriteWatchdog                  |
+     |                           (comedi_device *dev,comedi_subdevice *s,
+-    comedi_insn *insn,lsampl_t *data);                      |
++    comedi_insn *insn,unsigned int *data);                      |
+     +----------------------------------------------------------------------------+
+     | Task              : Start / Stop The Watchdog                              |
+     +----------------------------------------------------------------------------+
+     | Input Parameters  : comedi_device *dev      : Driver handle                |
+     |                     comedi_subdevice *s,   :pointer to subdevice structure
+     comedi_insn *insn      :pointer to insn structure      |
+-    |                     lsampl_t *data          : Data Pointer to read status  |
++    |                     unsigned int *data          : Data Pointer to read status  |
+     +----------------------------------------------------------------------------+
+     | Output Parameters :       --                                                                                                       |
+     +----------------------------------------------------------------------------+
+@@ -422,7 +422,7 @@ INT i_APCI2032_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+   */
+ 
+ int i_APCI2032_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+ 	case 0:		//stop the watchdog
+@@ -449,14 +449,14 @@ int i_APCI2032_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2032_ReadWatchdog                            |
+ |			(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+-                    lsampl_t *data); 	                                     |
++                    unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Watchdog                                      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   comedi_device *dev      : Driver handle              |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+-|                     lsampl_t *data          : Data Pointer to read status  |
++|                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -467,7 +467,7 @@ int i_APCI2032_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+ */
+ 
+ int i_APCI2032_ReadWatchdog(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	data[0] =
+@@ -531,7 +531,7 @@ void v_APCI2032_Interrupt(int irq, void *d)
+ +----------------------------------------------------------------------------+
+ | Function   Name   :  int i_APCI2032_ReadInterruptStatus                    |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              :Reads the interrupt status register                     |
+ +----------------------------------------------------------------------------+
+@@ -545,7 +545,7 @@ void v_APCI2032_Interrupt(int irq, void *d)
+ */
+ 
+ int i_APCI2032_ReadInterruptStatus(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	*data = ui_Type;
+ 	return insn->n;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h
+index c6d45ce1549d..7d858af87979 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h
+@@ -56,22 +56,22 @@
+ 
+ //DO
+ int i_APCI2032_ConfigDigitalOutput(comedi_device *dev, comedi_subdevice *s,
+-				   comedi_insn *insn, lsampl_t *data);
++				   comedi_insn *insn, unsigned int *data);
+ INT i_APCI2032_WriteDigitalOutput(comedi_device *dev, comedi_subdevice *s,
+-				  comedi_insn *insn, lsampl_t *data);
++				  comedi_insn *insn, unsigned int *data);
+ INT i_APCI2032_ReadDigitalOutput(comedi_device *dev, comedi_subdevice *s,
+-				 comedi_insn *insn, lsampl_t *data);
++				 comedi_insn *insn, unsigned int *data);
+ int i_APCI2032_ReadInterruptStatus(comedi_device *dev, comedi_subdevice *s,
+-				   comedi_insn *insn, lsampl_t *data);
++				   comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+ // timer value is passed as u seconds
+ INT i_APCI2032_ConfigWatchdog(comedi_device *dev, comedi_subdevice *s,
+-			      comedi_insn *insn, lsampl_t *data);
++			      comedi_insn *insn, unsigned int *data);
+ int i_APCI2032_StartStopWriteWatchdog(comedi_device *dev, comedi_subdevice *s,
+-				      comedi_insn *insn, lsampl_t *data);
++				      comedi_insn *insn, unsigned int *data);
+ int i_APCI2032_ReadWatchdog(comedi_device *dev, comedi_subdevice *s,
+-			    comedi_insn *insn, lsampl_t *data);
++			    comedi_insn *insn, unsigned int *data);
+ 
+ // Interrupt functions.....
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
+index 9e81f4390fe9..d61dfd1d1eab 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
+@@ -57,14 +57,14 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_Read1DigitalInput                       |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the digital input                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : comedi_device *dev      : Driver handle                |
+ |		       comedi_subdevice *s,   :pointer to subdevice structure
+                        comedi_insn *insn      :pointer to insn structure     |
+-|                     lsampl_t *data          : Data Pointer to read status  |
++|                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -74,7 +74,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI2200_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue = 0;
+ 	UINT ui_Channel;
+@@ -95,14 +95,14 @@ INT i_APCI2200_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_ReadMoreDigitalInput                    |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                     comedi_insn *insn,lsampl_t *data)                      |
++|                     comedi_insn *insn,unsigned int *data)                      |
+ +----------------------------------------------------------------------------+
+ | Task              : Return the status of the Requested digital inputs      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : comedi_device *dev      : Driver handle                |
+ |                      comedi_subdevice *s,   :pointer to subdevice structure
+                        comedi_insn *insn      :pointer to insn structure     |
+-|                      lsampl_t *data         : Data Pointer to read status  |
++|                      unsigned int *data         : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -113,7 +113,7 @@ INT i_APCI2200_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+ */
+ 
+ INT i_APCI2200_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	UINT ui_PortValue = data[0];
+@@ -147,13 +147,13 @@ INT i_APCI2200_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_ConfigDigitalOutput (comedi_device *dev,
+-                    comedi_subdevice *s comedi_insn *insn,lsampl_t *data)    |
++                    comedi_subdevice *s comedi_insn *insn,unsigned int *data)    |
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Digital Output Subdevice.               |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : comedi_device *dev : Driver handle                     |
+-|                     lsampl_t *data         : Data Pointer contains         |
++|                     unsigned int *data         : Data Pointer contains         |
+ |                                          configuration parameters as below |
+ |                      comedi_subdevice *s,   :pointer to subdevice structure
+                        comedi_insn *insn      :pointer to insn structure                                                           |
+@@ -170,7 +170,7 @@ INT i_APCI2200_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI2200_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	devpriv->b_OutputMemoryStatus = data[0];
+ 	return insn->n;
+@@ -180,14 +180,14 @@ int i_APCI2200_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_WriteDigitalOutput                      |
+ |			(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+-                     lsampl_t *data)                                         |
++                     unsigned int *data)                                         |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes port value  To the selected port                |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : comedi_device *dev      : Driver handle                |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+-|                    lsampl_t *data           : Data Pointer to read status  |
++|                    unsigned int *data           : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -198,7 +198,7 @@ int i_APCI2200_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ */
+ 
+ INT i_APCI2200_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp, ui_Temp1;
+ 	UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
+@@ -337,14 +337,14 @@ INT i_APCI2200_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_ReadDigitalOutput                       |
+ |			(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+-                    lsampl_t *data) 	                                     |
++                    unsigned int *data) 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : comedi_device *dev      : Driver handle                |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+-|                     lsampl_t *data          : Data Pointer to read status  |
++|                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -355,7 +355,7 @@ INT i_APCI2200_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ */
+ 
+ INT i_APCI2200_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	UINT ui_Temp;
+@@ -400,7 +400,7 @@ INT i_APCI2200_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_ConfigWatchdog(comedi_device *dev,
+-                      comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)  |
++                      comedi_subdevice *s,comedi_insn *insn,unsigned int *data)  |
+ |				                                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Watchdog                                |
+@@ -408,7 +408,7 @@ INT i_APCI2200_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ | Input Parameters  :   comedi_device *dev      : Driver handle              |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+-|                     lsampl_t *data          : Data Pointer to read status                                                                                                             |
++|                     unsigned int *data          : Data Pointer to read status                                                                                                             |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -419,7 +419,7 @@ INT i_APCI2200_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ */
+ 
+ int i_APCI2200_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0] == 0) {
+ 		//Disable the watchdog
+@@ -447,14 +447,14 @@ int i_APCI2200_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+     +----------------------------------------------------------------------------+
+     | Function   Name   : int i_APCI2200_StartStopWriteWatchdog                  |
+     |                           (comedi_device *dev,comedi_subdevice *s,
+-    comedi_insn *insn,lsampl_t *data);                      |
++    comedi_insn *insn,unsigned int *data);                      |
+     +----------------------------------------------------------------------------+
+     | Task              : Start / Stop The Watchdog                              |
+     +----------------------------------------------------------------------------+
+     | Input Parameters  : comedi_device *dev      : Driver handle                |
+     |                     comedi_subdevice *s,   :pointer to subdevice structure
+     comedi_insn *insn      :pointer to insn structure      |
+-    |                     lsampl_t *data          : Data Pointer to read status  |
++    |                     unsigned int *data          : Data Pointer to read status  |
+     +----------------------------------------------------------------------------+
+     | Output Parameters :       --                                                                                                       |
+     +----------------------------------------------------------------------------+
+@@ -465,7 +465,7 @@ int i_APCI2200_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+   */
+ 
+ int i_APCI2200_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+ 	case 0:		//stop the watchdog
+@@ -492,14 +492,14 @@ int i_APCI2200_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI2200_ReadWatchdog                            |
+ |			(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+-                    lsampl_t *data); 	                                     |
++                    unsigned int *data); 	                                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Watchdog                                      |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  :   comedi_device *dev      : Driver handle              |
+ |                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure      |
+-|                     lsampl_t *data          : Data Pointer to read status  |
++|                     unsigned int *data          : Data Pointer to read status  |
+ +----------------------------------------------------------------------------+
+ | Output Parameters :	--													 |
+ +----------------------------------------------------------------------------+
+@@ -510,7 +510,7 @@ int i_APCI2200_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+ */
+ 
+ int i_APCI2200_ReadWatchdog(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] =
+ 		inw(devpriv->iobase + APCI2200_WATCHDOG +
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h
+index 4de1ca104d45..59fc451e71c7 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h
+@@ -37,25 +37,25 @@
+ 
+ //Digital Input
+ INT i_APCI2200_ReadMoreDigitalInput(comedi_device *dev, comedi_subdevice *s,
+-				    comedi_insn *insn, lsampl_t *data);
++				    comedi_insn *insn, unsigned int *data);
+ INT i_APCI2200_Read1DigitalInput(comedi_device *dev, comedi_subdevice *s,
+-				 comedi_insn *insn, lsampl_t *data);
++				 comedi_insn *insn, unsigned int *data);
+ 
+ //Digital Output
+ int i_APCI2200_ConfigDigitalOutput(comedi_device *dev, comedi_subdevice *s,
+-				   comedi_insn *insn, lsampl_t *data);
++				   comedi_insn *insn, unsigned int *data);
+ INT i_APCI2200_WriteDigitalOutput(comedi_device *dev, comedi_subdevice *s,
+-				  comedi_insn *insn, lsampl_t *data);
++				  comedi_insn *insn, unsigned int *data);
+ INT i_APCI2200_ReadDigitalOutput(comedi_device *dev, comedi_subdevice *s,
+-				 comedi_insn *insn, lsampl_t *data);
++				 comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+ int i_APCI2200_ConfigWatchdog(comedi_device *dev, comedi_subdevice *s,
+-			      comedi_insn *insn, lsampl_t *data);
++			      comedi_insn *insn, unsigned int *data);
+ int i_APCI2200_StartStopWriteWatchdog(comedi_device *dev, comedi_subdevice *s,
+-				      comedi_insn *insn, lsampl_t *data);
++				      comedi_insn *insn, unsigned int *data);
+ int i_APCI2200_ReadWatchdog(comedi_device *dev, comedi_subdevice *s,
+-			    comedi_insn *insn, lsampl_t *data);
++			    comedi_insn *insn, unsigned int *data);
+ 
+ //reset
+ INT i_APCI2200_Reset(comedi_device *dev);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+index 32b7f241985e..45445e675f72 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+@@ -58,7 +58,7 @@ static UINT ui_Temp = 0;
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnConfigAnalogInput(comedi_device *dev,|
+-|  comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)					 |
++|  comedi_subdevice *s,comedi_insn *insn,unsigned int *data)					 |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+ | Task              : Calls card specific function  					     |
+@@ -67,7 +67,7 @@ static UINT ui_Temp = 0;
+ | Input Parameters  : comedi_device *dev									 |
+ |                     comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+-|                     lsampl_t *data      					         		 |
++|                     unsigned int *data      					         		 |
+ +----------------------------------------------------------------------------+
+ | Return Value      :              					                         |
+ |                    													     |
+@@ -75,7 +75,7 @@ static UINT ui_Temp = 0;
+ */
+ 
+ int i_APCI3120_InsnConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT i;
+ 
+@@ -125,7 +125,7 @@ int i_APCI3120_InsnConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnReadAnalogInput(comedi_device *dev,  |
+-|			comedi_subdevice *s,comedi_insn *insn, lsampl_t *data)	 |
++|			comedi_subdevice *s,comedi_insn *insn, unsigned int *data)	 |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+ | Task              :  card specific function								 |
+@@ -138,7 +138,7 @@ int i_APCI3120_InsnConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
+ | Input Parameters  : comedi_device *dev									 |
+ |                     comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+-|                     lsampl_t *data     									 |
++|                     unsigned int *data     									 |
+ +----------------------------------------------------------------------------+
+ | Return Value      :              					                         |
+ |                    													     |
+@@ -146,7 +146,7 @@ int i_APCI3120_InsnConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
+ */
+ 
+ int i_APCI3120_InsnReadAnalogInput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	USHORT us_ConvertTiming, us_TmpValue, i;
+ 	BYTE b_Tmp;
+@@ -1633,7 +1633,7 @@ void v_APCI3120_Interrupt(int irq, void *d)
+ /*int i_APCI3120_InterruptHandleEos(comedi_device *dev)
+ {
+        int n_chan,i;
+-       sampl_t *data;
++       short *data;
+        comedi_subdevice *s=dev->subdevices+0;
+        comedi_async *async = s->async;
+        data=async->data+async->buf_int_ptr;//new samples added from here onwards
+@@ -1643,8 +1643,8 @@ void v_APCI3120_Interrupt(int irq, void *d)
+          {
+            data[i]=inw(dev->iobase+0);
+          }
+-       async->buf_int_count+=n_chan*sizeof(sampl_t);
+-       async->buf_int_ptr+=n_chan*sizeof(sampl_t);
++       async->buf_int_count+=n_chan*sizeof(short);
++       async->buf_int_ptr+=n_chan*sizeof(short);
+        comedi_eos(dev,s);
+        if (s->async->buf_int_ptr>=s->async->data_len) //  for buffer rool over
+ 		         {
+@@ -1771,16 +1771,16 @@ void v_APCI3120_InterruptDma(int irq, void *d)
+ 
+ 	}
+ /*UPDATE-0.7.57->0.7.68
+-	ptr=(sampl_t *)devpriv->ul_DmaBufferVirtual[devpriv->ui_DmaActualBuffer];
++	ptr=(short *)devpriv->ul_DmaBufferVirtual[devpriv->ui_DmaActualBuffer];
+ 
+ 
+ 	// if there is not enough space left in the buffer to copy all data contained in the DMABufferVirtual
+-	if(s->async->buf_int_ptr+samplesinbuf*sizeof(sampl_t)>=devpriv->ui_AiDataLength)
++	if(s->async->buf_int_ptr+samplesinbuf*sizeof(short)>=devpriv->ui_AiDataLength)
+ 	{
+-		m=(devpriv->ui_AiDataLength-s->async->buf_int_ptr)/sizeof(sampl_t);
++		m=(devpriv->ui_AiDataLength-s->async->buf_int_ptr)/sizeof(short);
+ 		v_APCI3120_InterruptDmaMoveBlock16bit(dev,s,(void *)ptr,((void *)(devpriv->AiData))+s->async->buf_int_ptr,m);
+-		s->async->buf_int_count+=m*sizeof(sampl_t);
+-		ptr+=m*sizeof(sampl_t);
++		s->async->buf_int_count+=m*sizeof(short);
++		ptr+=m*sizeof(short);
+                 samplesinbuf-=m;
+ 		s->async->buf_int_ptr=0;
+ 		comedi_eobuf(dev,s);
+@@ -1790,8 +1790,8 @@ void v_APCI3120_InterruptDma(int irq, void *d)
+ 	{
+ 	        v_APCI3120_InterruptDmaMoveBlock16bit(dev,s,(void *)ptr,((void *)(devpriv->AiData))+s->async->buf_int_ptr,samplesinbuf);
+ 
+-		s->async->buf_int_count+=samplesinbuf*sizeof(sampl_t);
+-		s->async->buf_int_ptr+=samplesinbuf*sizeof(sampl_t);
++		s->async->buf_int_count+=samplesinbuf*sizeof(short);
++		s->async->buf_int_ptr+=samplesinbuf*sizeof(short);
+ 		if (!(devpriv->ui_AiFlags & TRIG_WAKE_EOS))
+ 		{
+ 			comedi_bufcheck(dev,s);
+@@ -1879,7 +1879,7 @@ void v_APCI3120_InterruptDma(int irq, void *d)
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device|
+-|*dev,comedi_subdevice *s,sampl_t *dma,sampl_t *data,int n)				     |
++|*dev,comedi_subdevice *s,short *dma,short *data,int n)				     |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              : This function copies the data from DMA buffer to the   |
+@@ -1888,15 +1888,15 @@ void v_APCI3120_InterruptDma(int irq, void *d)
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : comedi_device *dev									 |
+ |                     comedi_subdevice *s									 |
+-|                     sampl_t *dma											 |
+-|                     sampl_t *data,int n          					         |
++|                     short *dma											 |
++|                     short *data,int n          					         |
+ +----------------------------------------------------------------------------+
+ | Return Value      : void         					                         |
+ |                    													     |
+ +----------------------------------------------------------------------------+
+ */
+ 
+-/*void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device *dev,comedi_subdevice *s,sampl_t *dma,sampl_t *data,int n)
++/*void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device *dev,comedi_subdevice *s,short *dma,short *data,int n)
+ {
+ 	int i,j,m;
+ 
+@@ -1926,14 +1926,14 @@ void v_APCI3120_InterruptDma(int irq, void *d)
+ }
+ */
+ void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device * dev,
+-	comedi_subdevice * s, sampl_t * dma_buffer, unsigned int num_samples)
++	comedi_subdevice * s, short * dma_buffer, unsigned int num_samples)
+ {
+ 	devpriv->ui_AiActualScan +=
+ 		(s->async->cur_chan + num_samples) / devpriv->ui_AiScanLength;
+ 	s->async->cur_chan += num_samples;
+ 	s->async->cur_chan %= devpriv->ui_AiScanLength;
+ 
+-	cfc_write_array_to_buffer(s, dma_buffer, num_samples * sizeof(sampl_t));
++	cfc_write_array_to_buffer(s, dma_buffer, num_samples * sizeof(short));
+ }
+ 
+ /*
+@@ -1945,7 +1945,7 @@ void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnConfigTimer(comedi_device *dev,          |
+-|	comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) 			     |
++|	comedi_subdevice *s,comedi_insn *insn,unsigned int *data) 			     |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              :Configure Timer 2  								     |
+@@ -1954,7 +1954,7 @@ void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device * dev,
+ | Input Parameters  : comedi_device *dev									 |
+ |                     comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+-|                     lsampl_t *data 										 |
++|                     unsigned int *data 										 |
+ |                     														 |
+ |                      data[0]= TIMER  configure as timer                    |
+ |              				 = WATCHDOG configure as watchdog				 |
+@@ -1968,7 +1968,7 @@ void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device * dev,
+ */
+ 
+ int i_APCI3120_InsnConfigTimer(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	UINT ui_Timervalue2;
+@@ -2093,7 +2093,7 @@ int i_APCI3120_InsnConfigTimer(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnWriteTimer(comedi_device *dev,           |
+-|                    comedi_subdevice *s, comedi_insn *insn,lsampl_t *data)  |
++|                    comedi_subdevice *s, comedi_insn *insn,unsigned int *data)  |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+ | Task              :    To start and stop the timer		                 |
+@@ -2101,7 +2101,7 @@ int i_APCI3120_InsnConfigTimer(comedi_device * dev, comedi_subdevice * s,
+ | Input Parameters  : comedi_device *dev									 |
+ |                     comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+-|                     lsampl_t *data                                         |
++|                     unsigned int *data                                         |
+ |                                                                            |
+ |				data[0] = 1 (start)                                  |
+ |				data[0] = 0 (stop )                                  |
+@@ -2119,7 +2119,7 @@ int i_APCI3120_InsnConfigTimer(comedi_device * dev, comedi_subdevice * s,
+ */
+ 
+ int i_APCI3120_InsnWriteTimer(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	UINT ui_Timervalue2 = 0;
+@@ -2284,7 +2284,7 @@ int i_APCI3120_InsnWriteTimer(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     : int i_APCI3120_InsnReadTimer(comedi_device *dev,           |
+-|		comedi_subdevice *s,comedi_insn *insn, lsampl_t *data) 		 |
++|		comedi_subdevice *s,comedi_insn *insn, unsigned int *data) 		 |
+ |                                        									 |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+@@ -2293,7 +2293,7 @@ int i_APCI3120_InsnWriteTimer(comedi_device * dev, comedi_subdevice * s,
+ | Input Parameters  : 	comedi_device *dev									 |
+ |                     comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+-|                     lsampl_t *data 										 |
++|                     unsigned int *data 										 |
+ |                     														 |
+ +----------------------------------------------------------------------------+
+ | Return Value      :   													 |
+@@ -2305,7 +2305,7 @@ int i_APCI3120_InsnWriteTimer(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI3120_InsnReadTimer(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_Tmp;
+ 	USHORT us_TmpValue, us_TmpValue_2, us_StatusValue;
+@@ -2361,7 +2361,7 @@ int i_APCI3120_InsnReadTimer(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnReadDigitalInput(comedi_device *dev,     |
+-|			comedi_subdevice *s, comedi_insn *insn,lsampl_t *data)   |
++|			comedi_subdevice *s, comedi_insn *insn,unsigned int *data)   |
+ |                                        									 |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+@@ -2371,7 +2371,7 @@ int i_APCI3120_InsnReadTimer(comedi_device * dev, comedi_subdevice * s,
+ | Input Parameters  : comedi_device *dev									 |
+ |                     comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+-|                     lsampl_t *data 										 |
++|                     unsigned int *data 										 |
+ +----------------------------------------------------------------------------+
+ | Return Value      :              					                         |
+ |                    													     |
+@@ -2379,7 +2379,7 @@ int i_APCI3120_InsnReadTimer(comedi_device * dev, comedi_subdevice * s,
+ */
+ 
+ int i_APCI3120_InsnReadDigitalInput(comedi_device * dev, comedi_subdevice
+-	* s, comedi_insn * insn, lsampl_t * data)
++	* s, comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Chan, ui_TmpValue;
+ 
+@@ -2404,7 +2404,7 @@ int i_APCI3120_InsnReadDigitalInput(comedi_device * dev, comedi_subdevice
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnBitsDigitalInput(comedi_device *dev, |
+-|comedi_subdevice *s, comedi_insn *insn,lsampl_t *data)                      |
++|comedi_subdevice *s, comedi_insn *insn,unsigned int *data)                      |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              : Reads the value of the Digital input Port i.e.4channels|
+@@ -2414,14 +2414,14 @@ int i_APCI3120_InsnReadDigitalInput(comedi_device * dev, comedi_subdevice
+ | Input Parameters  : comedi_device *dev									 |
+ |                     comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+-|                     lsampl_t *data 										 |
++|                     unsigned int *data 										 |
+ +----------------------------------------------------------------------------+
+ | Return Value      :              					                         |
+ |                    													     |
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI3120_InsnBitsDigitalInput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_TmpValue;
+ 	ui_TmpValue = (UINT) inw(devpriv->iobase + APCI3120_RD_STATUS);
+@@ -2443,7 +2443,7 @@ int i_APCI3120_InsnBitsDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnConfigDigitalOutput(comedi_device    |
+-| *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)				 |
++| *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data)				 |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+ | Task              :Configure the output memory ON or OFF				     |
+@@ -2452,7 +2452,7 @@ int i_APCI3120_InsnBitsDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ | Input Parameters  :comedi_device *dev									 	 |
+ |                     comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+-|                     lsampl_t *data 										 |
++|                     unsigned int *data 										 |
+ +----------------------------------------------------------------------------+
+ | Return Value      :              					                         |
+ |                    													     |
+@@ -2460,7 +2460,7 @@ int i_APCI3120_InsnBitsDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ */
+ 
+ int i_APCI3120_InsnConfigDigitalOutput(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	if ((data[0] != 0) && (data[0] != 1)) {
+@@ -2486,7 +2486,7 @@ int i_APCI3120_InsnConfigDigitalOutput(comedi_device * dev,
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnBitsDigitalOutput(comedi_device *dev,    |
+-|		comedi_subdevice *s, comedi_insn *insn,lsampl_t *data) 		 |
++|		comedi_subdevice *s, comedi_insn *insn,unsigned int *data) 		 |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              : write diatal output port							     |
+@@ -2495,7 +2495,7 @@ int i_APCI3120_InsnConfigDigitalOutput(comedi_device * dev,
+ | Input Parameters  : comedi_device *dev									 |
+ |                     comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+-|                     lsampl_t *data 										 |
++|                     unsigned int *data 										 |
+                       data[0]     Value to be written
+                       data[1]    :1 Set digital o/p ON
+                       data[1]     2 Set digital o/p OFF with memory ON
+@@ -2506,7 +2506,7 @@ int i_APCI3120_InsnConfigDigitalOutput(comedi_device * dev,
+ */
+ 
+ int i_APCI3120_InsnBitsDigitalOutput(comedi_device * dev, comedi_subdevice
+-	* s, comedi_insn * insn, lsampl_t * data)
++	* s, comedi_insn * insn, unsigned int * data)
+ {
+ 	if ((data[0] > this_board->i_DoMaxdata) || (data[0] < 0)) {
+ 
+@@ -2537,7 +2537,7 @@ int i_APCI3120_InsnBitsDigitalOutput(comedi_device * dev, comedi_subdevice
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnWriteDigitalOutput(comedi_device *dev,|
+-|comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) 			             |
++|comedi_subdevice *s,comedi_insn *insn,unsigned int *data) 			             |
+ |                                            						         |
+ +----------------------------------------------------------------------------+
+ | Task              : Write digiatl output								     |
+@@ -2546,7 +2546,7 @@ int i_APCI3120_InsnBitsDigitalOutput(comedi_device * dev, comedi_subdevice
+ | Input Parameters  : comedi_device *dev								 	 |
+ |                     comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+-|                     lsampl_t *data 										 |
++|                     unsigned int *data 										 |
+                       data[0]     Value to be written
+                       data[1]    :1 Set digital o/p ON
+                       data[1]     2 Set digital o/p OFF with memory ON
+@@ -2557,7 +2557,7 @@ int i_APCI3120_InsnBitsDigitalOutput(comedi_device * dev, comedi_subdevice
+ */
+ 
+ int i_APCI3120_InsnWriteDigitalOutput(comedi_device * dev, comedi_subdevice
+-	* s, comedi_insn * insn, lsampl_t * data)
++	* s, comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	UINT ui_Temp1;
+@@ -2618,7 +2618,7 @@ int i_APCI3120_InsnWriteDigitalOutput(comedi_device * dev, comedi_subdevice
+ /*
+ +----------------------------------------------------------------------------+
+ | Function name     :int i_APCI3120_InsnWriteAnalogOutput(comedi_device *dev,|
+-|comedi_subdevice *s, comedi_insn *insn,lsampl_t *data)			             |
++|comedi_subdevice *s, comedi_insn *insn,unsigned int *data)			             |
+ |                                        									 |
+ +----------------------------------------------------------------------------+
+ | Task              : Write  analog output   							     |
+@@ -2627,7 +2627,7 @@ int i_APCI3120_InsnWriteDigitalOutput(comedi_device * dev, comedi_subdevice
+ | Input Parameters  : comedi_device *dev									 |
+ |                     comedi_subdevice *s									 |
+ |                     comedi_insn *insn                                      |
+-|                     lsampl_t *data  										 |
++|                     unsigned int *data  										 |
+ +----------------------------------------------------------------------------+
+ | Return Value      :              					                         |
+ |                    													     |
+@@ -2635,7 +2635,7 @@ int i_APCI3120_InsnWriteDigitalOutput(comedi_device * dev, comedi_subdevice
+ */
+ 
+ int i_APCI3120_InsnWriteAnalogOutput(comedi_device * dev, comedi_subdevice
+-	* s, comedi_insn * insn, lsampl_t * data)
++	* s, comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Range, ui_Channel;
+ 	USHORT us_TmpValue;
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
+index 2c20f90b0b9e..591061743c74 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
+@@ -188,10 +188,10 @@ int i_APCI3120_CyclicAnalogInput(int mode, comedi_device *dev,
+ 				 comedi_subdevice *s);
+ // Interrupt functions
+ void v_APCI3120_Interrupt(int irq, void *d);
+-//UPDATE-0.7.57->0.7.68 void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device *dev,comedi_subdevice *s,sampl_t *dma,sampl_t *data,int n);
++//UPDATE-0.7.57->0.7.68 void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device *dev,comedi_subdevice *s,short *dma,short *data,int n);
+ void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device *dev,
+ 					   comedi_subdevice *s,
+-					   sampl_t *dma_buffer,
++					   short *dma_buffer,
+ 					   unsigned int num_samples);
+ int i_APCI3120_InterruptHandleEos(comedi_device *dev);
+ void v_APCI3120_InterruptDma(int irq, void *d);
+@@ -199,41 +199,41 @@ void v_APCI3120_InterruptDma(int irq, void *d);
+ // TIMER
+ 
+ int i_APCI3120_InsnConfigTimer(comedi_device *dev, comedi_subdevice *s,
+-			       comedi_insn *insn, lsampl_t *data);
++			       comedi_insn *insn, unsigned int *data);
+ int i_APCI3120_InsnWriteTimer(comedi_device *dev, comedi_subdevice *s,
+-			      comedi_insn *insn, lsampl_t *data);
++			      comedi_insn *insn, unsigned int *data);
+ int i_APCI3120_InsnReadTimer(comedi_device *dev, comedi_subdevice *s,
+-			     comedi_insn *insn, lsampl_t *data);
++			     comedi_insn *insn, unsigned int *data);
+ 
+ //DI
+ // for di read
+ 
+ int i_APCI3120_InsnBitsDigitalInput(comedi_device *dev, comedi_subdevice *s,
+-				    comedi_insn *insn, lsampl_t *data);
++				    comedi_insn *insn, unsigned int *data);
+ int i_APCI3120_InsnReadDigitalInput(comedi_device *dev, comedi_subdevice *s,
+-				    comedi_insn *insn, lsampl_t *data);
++				    comedi_insn *insn, unsigned int *data);
+ 
+ //DO
+ //int i_APCI3120_WriteDigitalOutput(comedi_device *dev, BYTE data);
+ int i_APCI3120_InsnConfigDigitalOutput(comedi_device *dev,
+ 				       comedi_subdevice *s, comedi_insn *insn,
+-				       lsampl_t *data);
++				       unsigned int *data);
+ int i_APCI3120_InsnBitsDigitalOutput(comedi_device *dev, comedi_subdevice *s,
+-				     comedi_insn *insn, lsampl_t *data);
++				     comedi_insn *insn, unsigned int *data);
+ int i_APCI3120_InsnWriteDigitalOutput(comedi_device *dev, comedi_subdevice *s,
+-				      comedi_insn *insn, lsampl_t *data);
++				      comedi_insn *insn, unsigned int *data);
+ 
+ //AO
+ //int i_APCI3120_Write1AnalogValue(comedi_device *dev,UINT ui_Range,UINT ui_Channel,UINT data );
+ int i_APCI3120_InsnWriteAnalogOutput(comedi_device *dev, comedi_subdevice *s,
+-				     comedi_insn *insn, lsampl_t *data);
++				     comedi_insn *insn, unsigned int *data);
+ 
+ //AI HArdware layer
+ 
+ int i_APCI3120_InsnConfigAnalogInput(comedi_device *dev, comedi_subdevice *s,
+-				     comedi_insn *insn, lsampl_t *data);
++				     comedi_insn *insn, unsigned int *data);
+ int i_APCI3120_InsnReadAnalogInput(comedi_device *dev, comedi_subdevice *s,
+-				   comedi_insn *insn, lsampl_t *data);
++				   comedi_insn *insn, unsigned int *data);
+ int i_APCI3120_CommandTestAnalogInput(comedi_device *dev, comedi_subdevice *s,
+ 				      comedi_cmd *cmd);
+ int i_APCI3120_CommandAnalogInput(comedi_device *dev, comedi_subdevice *s);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+index 8a507da1489b..83868d8f1c5f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+@@ -454,8 +454,8 @@ VOID v_GetAPCI3200EepromCalibrationValue(DWORD dw_PCIBoardEepromAddress,
+ }
+ 
+ INT i_APCI3200_GetChannelCalibrationValue(comedi_device * dev,
+-	unsigned int ui_Channel_num, lsampl_t * CJCCurrentSource,
+-	lsampl_t * ChannelCurrentSource, lsampl_t * ChannelGainFactor)
++	unsigned int ui_Channel_num, unsigned int * CJCCurrentSource,
++	unsigned int * ChannelCurrentSource, unsigned int * ChannelGainFactor)
+ {
+ 	int i_DiffChannel = 0;
+ 	int i_Module = 0;
+@@ -531,7 +531,7 @@ INT i_APCI3200_GetChannelCalibrationValue(comedi_device * dev,
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadDigitalInput                       |
+   |			  (comedi_device *dev,comedi_subdevice *s,               |
+-  |                      comedi_insn *insn,lsampl_t *data)                     |
++  |                      comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              : Read  value  of the selected channel or port           |
+   +----------------------------------------------------------------------------+
+@@ -551,7 +551,7 @@ INT i_APCI3200_GetChannelCalibrationValue(comedi_device * dev,
+ */
+ 
+ INT i_APCI3200_ReadDigitalInput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp = 0;
+ 	UINT ui_NoOfChannel = 0;
+@@ -593,7 +593,7 @@ INT i_APCI3200_ReadDigitalInput(comedi_device * dev, comedi_subdevice * s,
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ConfigDigitalOutput                     |
+   |			  (comedi_device *dev,comedi_subdevice *s,				 |
+-  |                      comedi_insn *insn,lsampl_t *data)                     |
++  |                      comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              : Configures The Digital Output Subdevice.               |
+   +----------------------------------------------------------------------------+
+@@ -609,7 +609,7 @@ INT i_APCI3200_ReadDigitalInput(comedi_device * dev, comedi_subdevice * s,
+   +----------------------------------------------------------------------------+
+ */
+ int i_APCI3200_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	if ((data[0] != 0) && (data[0] != 1)) {
+@@ -630,14 +630,14 @@ int i_APCI3200_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_WriteDigitalOutput                      |
+   |			  (comedi_device *dev,comedi_subdevice *s,				 |
+-  |                      comedi_insn *insn,lsampl_t *data)                     |
++  |                      comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              : writes To the digital Output Subdevice                 |
+   +----------------------------------------------------------------------------+
+   | Input Parameters  : comedi_device *dev      : Driver handle                |
+   |                     comedi_subdevice *s     : Subdevice Pointer            |
+   |                     comedi_insn *insn       : Insn Structure Pointer       |
+-  |                     lsampl_t *data          : Data Pointer contains        |
++  |                     unsigned int *data          : Data Pointer contains        |
+   |                                          configuration parameters as below |
+   |                     data[0]             :Value to output
+   data[1]             : 0 o/p single channel
+@@ -654,7 +654,7 @@ int i_APCI3200_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+   +----------------------------------------------------------------------------+
+ */
+ INT i_APCI3200_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp = 0, ui_Temp1 = 0;
+ 	UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
+@@ -747,7 +747,7 @@ INT i_APCI3200_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadDigitalOutput                       |
+   |			  (comedi_device *dev,comedi_subdevice *s,               |
+-  |                      comedi_insn *insn,lsampl_t *data)                     |
++  |                      comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              : Read  value  of the selected channel or port           |
+   +----------------------------------------------------------------------------+
+@@ -767,7 +767,7 @@ INT i_APCI3200_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+   +----------------------------------------------------------------------------+
+ */
+ INT i_APCI3200_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+ 	UINT ui_NoOfChannel;
+@@ -808,14 +808,14 @@ INT i_APCI3200_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+   +----------------------------------------------------------------------------+
+   | Function   Name   : INT i_APCI3200_ConfigAnalogInput                       |
+   |			  (comedi_device *dev,comedi_subdevice *s,               |
+-  |                      comedi_insn *insn,lsampl_t *data)                     |
++  |                      comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              : Configures The Analog Input Subdevice                  |
+   +----------------------------------------------------------------------------+
+   | Input Parameters  : comedi_device *dev      : Driver handle                |
+   |                     comedi_subdevice *s     : Subdevice Pointer            |
+   |                     comedi_insn *insn       : Insn Structure Pointer       |
+-  |                     lsampl_t *data          : Data Pointer contains        |
++  |                     unsigned int *data          : Data Pointer contains        |
+   |                                          configuration parameters as below |
+   |                                                                            |
+   |					data[0]
+@@ -875,7 +875,7 @@ INT i_APCI3200_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+   +----------------------------------------------------------------------------+
+ */
+ INT i_APCI3200_ConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	UINT ul_Config = 0, ul_Temp = 0;
+@@ -1028,7 +1028,7 @@ INT i_APCI3200_ConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
+ 	//END JK 06.07.04: Management of sevrals boards
+ 
+ 	//Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+-	memset(s_BoardInfos[dev->minor].ui_ScanValueArray, 0, (7 + 12) * sizeof(lsampl_t));	// 7 is the maximal number of channels
++	memset(s_BoardInfos[dev->minor].ui_ScanValueArray, 0, (7 + 12) * sizeof(unsigned int));	// 7 is the maximal number of channels
+ 	//End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+ 
+ 	//BEGIN JK 02.07.04 : This while can't be do, it block the process when using severals boards
+@@ -1335,7 +1335,7 @@ INT i_APCI3200_ConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadAnalogInput                         |
+   |			          (comedi_device *dev,comedi_subdevice *s,       |
+-  |                     comedi_insn *insn,lsampl_t *data)                      |
++  |                     comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read  value  of the selected channel			         |
+   +----------------------------------------------------------------------------+
+@@ -1362,7 +1362,7 @@ INT i_APCI3200_ConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
+   +----------------------------------------------------------------------------+
+ */
+ INT i_APCI3200_ReadAnalogInput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_DummyValue = 0;
+ 	int i_ConvertCJCCalibration;
+@@ -1634,7 +1634,7 @@ INT i_APCI3200_ReadAnalogInput(comedi_device * dev, comedi_subdevice * s,
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_Read1AnalogInputChannel                 |
+   |			          (comedi_device *dev,comedi_subdevice *s,       |
+-  |                     comedi_insn *insn,lsampl_t *data)                      |
++  |                     comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read  value  of the selected channel			         |
+   +----------------------------------------------------------------------------+
+@@ -1652,7 +1652,7 @@ INT i_APCI3200_ReadAnalogInput(comedi_device * dev, comedi_subdevice * s,
+   +----------------------------------------------------------------------------+
+ */
+ INT i_APCI3200_Read1AnalogInputChannel(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_EOC = 0;
+ 	UINT ui_ChannelNo = 0;
+@@ -1760,7 +1760,7 @@ INT i_APCI3200_Read1AnalogInputChannel(comedi_device * dev,
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadCalibrationOffsetValue              |
+   |			          (comedi_device *dev,comedi_subdevice *s,       |
+-  |                     comedi_insn *insn,lsampl_t *data)                      |
++  |                     comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read calibration offset  value  of the selected channel|
+   +----------------------------------------------------------------------------+
+@@ -1896,7 +1896,7 @@ int i_APCI3200_ReadCalibrationOffsetValue(comedi_device * dev, UINT * data)
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadCalibrationGainValue                |
+   |			          (comedi_device *dev,comedi_subdevice *s,       |
+-  |                     comedi_insn *insn,lsampl_t *data)                      |
++  |                     comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read calibration gain  value  of the selected channel  |
+   +----------------------------------------------------------------------------+
+@@ -2031,7 +2031,7 @@ int i_APCI3200_ReadCalibrationGainValue(comedi_device * dev, UINT * data)
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadCJCValue                            |
+   |			          (comedi_device *dev,comedi_subdevice *s,       |
+-  |                     comedi_insn *insn,lsampl_t *data)                      |
++  |                     comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read CJC  value  of the selected channel               |
+   +----------------------------------------------------------------------------+
+@@ -2048,7 +2048,7 @@ int i_APCI3200_ReadCalibrationGainValue(comedi_device * dev, UINT * data)
+   +----------------------------------------------------------------------------+
+ */
+ 
+-int i_APCI3200_ReadCJCValue(comedi_device * dev, lsampl_t * data)
++int i_APCI3200_ReadCJCValue(comedi_device * dev, unsigned int * data)
+ {
+ 	UINT ui_EOC = 0;
+ 	INT ui_CommandRegister = 0;
+@@ -2151,7 +2151,7 @@ int i_APCI3200_ReadCJCValue(comedi_device * dev, lsampl_t * data)
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadCJCCalOffset                        |
+   |			          (comedi_device *dev,comedi_subdevice *s,       |
+-  |                     comedi_insn *insn,lsampl_t *data)                      |
++  |                     comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read CJC calibration offset  value  of the selected channel
+   +----------------------------------------------------------------------------+
+@@ -2167,7 +2167,7 @@ int i_APCI3200_ReadCJCValue(comedi_device * dev, lsampl_t * data)
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-int i_APCI3200_ReadCJCCalOffset(comedi_device * dev, lsampl_t * data)
++int i_APCI3200_ReadCJCCalOffset(comedi_device * dev, unsigned int * data)
+ {
+ 	UINT ui_EOC = 0;
+ 	INT ui_CommandRegister = 0;
+@@ -2266,7 +2266,7 @@ int i_APCI3200_ReadCJCCalOffset(comedi_device * dev, lsampl_t * data)
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_ReadCJCGainValue                        |
+   |			          (comedi_device *dev,comedi_subdevice *s,       |
+-  |                     comedi_insn *insn,lsampl_t *data)                      |
++  |                     comedi_insn *insn,unsigned int *data)                      |
+   +----------------------------------------------------------------------------+
+   | Task              : Read CJC calibration gain value
+   +----------------------------------------------------------------------------+
+@@ -2283,7 +2283,7 @@ int i_APCI3200_ReadCJCCalOffset(comedi_device * dev, lsampl_t * data)
+   |			                                                         |
+   +----------------------------------------------------------------------------+
+ */
+-int i_APCI3200_ReadCJCCalGain(comedi_device * dev, lsampl_t * data)
++int i_APCI3200_ReadCJCCalGain(comedi_device * dev, unsigned int * data)
+ {
+ 	UINT ui_EOC = 0;
+ 	INT ui_CommandRegister = 0;
+@@ -2376,14 +2376,14 @@ int i_APCI3200_ReadCJCCalGain(comedi_device * dev, lsampl_t * data)
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_InsnBits_AnalogInput_Test               |
+   |			  (comedi_device *dev,comedi_subdevice *s,               |
+-  |                      comedi_insn *insn,lsampl_t *data)                     |
++  |                      comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              : Tests the Selected Anlog Input Channel                 |
+   +----------------------------------------------------------------------------+
+   | Input Parameters  : comedi_device *dev      : Driver handle                |
+   |                     comedi_subdevice *s     : Subdevice Pointer            |
+   |                     comedi_insn *insn       : Insn Structure Pointer       |
+-  |                     lsampl_t *data          : Data Pointer contains        |
++  |                     unsigned int *data          : Data Pointer contains        |
+   |                                          configuration parameters as below |
+   |
+   |
+@@ -2405,7 +2405,7 @@ int i_APCI3200_ReadCJCCalGain(comedi_device * dev, lsampl_t * data)
+ */
+ 
+ INT i_APCI3200_InsnBits_AnalogInput_Test(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Configuration = 0;
+ 	INT i_Temp;		//,i_TimeUnit;
+@@ -2511,14 +2511,14 @@ INT i_APCI3200_InsnBits_AnalogInput_Test(comedi_device * dev,
+   +----------------------------------------------------------------------------+
+   | Function   Name   : int i_APCI3200_InsnWriteReleaseAnalogInput             |
+   |			  (comedi_device *dev,comedi_subdevice *s,               |
+-  |                      comedi_insn *insn,lsampl_t *data)                     |
++  |                      comedi_insn *insn,unsigned int *data)                     |
+   +----------------------------------------------------------------------------+
+   | Task              :  Resets the channels                                                      |
+   +----------------------------------------------------------------------------+
+   | Input Parameters  : comedi_device *dev      : Driver handle                |
+   |                     comedi_subdevice *s     : Subdevice Pointer            |
+   |                     comedi_insn *insn       : Insn Structure Pointer       |
+-  |                     lsampl_t *data          : Data Pointer
++  |                     unsigned int *data          : Data Pointer
+   +----------------------------------------------------------------------------+
+   | Output Parameters :	--													 |
+ 
+@@ -2530,7 +2530,7 @@ INT i_APCI3200_InsnBits_AnalogInput_Test(comedi_device * dev,
+ */
+ 
+ INT i_APCI3200_InsnWriteReleaseAnalogInput(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	i_APCI3200_Reset(dev);
+ 	return insn->n;
+@@ -3601,23 +3601,23 @@ int i_APCI3200_InterruptHandleEos(comedi_device * dev)
+ 			s->async->events |= COMEDI_CB_EOS;
+ 
+ 			// Test if enougth memory is available and allocate it for 7 values
+-			//n = comedi_buf_write_alloc(s->async, 7*sizeof(lsampl_t));
++			//n = comedi_buf_write_alloc(s->async, 7*sizeof(unsigned int));
+ 			n = comedi_buf_write_alloc(s->async,
+-				(7 + 12) * sizeof(lsampl_t));
++				(7 + 12) * sizeof(unsigned int));
+ 
+ 			// If not enougth memory available, event is set to Comedi Buffer Errror
+-			if (n > ((7 + 12) * sizeof(lsampl_t))) {
++			if (n > ((7 + 12) * sizeof(unsigned int))) {
+ 				printk("\ncomedi_buf_write_alloc n = %i", n);
+ 				s->async->events |= COMEDI_CB_ERROR;
+ 			}
+ 			// Write all 7 scan values in the comedi buffer
+ 			comedi_buf_memcpy_to(s->async, 0,
+-				(lsampl_t *) s_BoardInfos[dev->minor].
+-				ui_ScanValueArray, (7 + 12) * sizeof(lsampl_t));
++				(unsigned int *) s_BoardInfos[dev->minor].
++				ui_ScanValueArray, (7 + 12) * sizeof(unsigned int));
+ 
+ 			// Update comedi buffer pinters indexes
+ 			comedi_buf_write_free(s->async,
+-				(7 + 12) * sizeof(lsampl_t));
++				(7 + 12) * sizeof(unsigned int));
+ 
+ 			// Send events
+ 			comedi_event(dev, s);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+index 314b3c5e2a5a..09445d5f673e 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+@@ -139,7 +139,7 @@ typedef struct {
+ 	UINT ui_InterruptChannelValue[144];	//Buffer
+ 	BYTE b_StructInitialized;
+ 	//Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+-	lsampl_t ui_ScanValueArray[7 + 12];	// 7 is the maximal number of channels
++	unsigned int ui_ScanValueArray[7 + 12];	// 7 is the maximal number of channels
+ 	//End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+ 
+ 	//Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+@@ -155,33 +155,33 @@ typedef struct {
+ //AI
+ 
+ INT i_APCI3200_ConfigAnalogInput(comedi_device *dev, comedi_subdevice *s,
+-				 comedi_insn *insn, lsampl_t *data);
++				 comedi_insn *insn, unsigned int *data);
+ INT i_APCI3200_ReadAnalogInput(comedi_device *dev, comedi_subdevice *s,
+-			       comedi_insn *insn, lsampl_t *data);
++			       comedi_insn *insn, unsigned int *data);
+ INT i_APCI3200_InsnWriteReleaseAnalogInput(comedi_device *dev,
+ 					   comedi_subdevice *s,
+-					   comedi_insn *insn, lsampl_t *data);
++					   comedi_insn *insn, unsigned int *data);
+ INT i_APCI3200_InsnBits_AnalogInput_Test(comedi_device *dev,
+ 					 comedi_subdevice *s,
+-					 comedi_insn *insn, lsampl_t *data);
++					 comedi_insn *insn, unsigned int *data);
+ INT i_APCI3200_StopCyclicAcquisition(comedi_device *dev, comedi_subdevice *s);
+ INT i_APCI3200_InterruptHandleEos(comedi_device *dev);
+ INT i_APCI3200_CommandTestAnalogInput(comedi_device *dev, comedi_subdevice *s,
+ 				      comedi_cmd *cmd);
+ INT i_APCI3200_CommandAnalogInput(comedi_device *dev, comedi_subdevice *s);
+ INT i_APCI3200_ReadDigitalInput(comedi_device *dev, comedi_subdevice *s,
+-				comedi_insn *insn, lsampl_t *data);
++				comedi_insn *insn, unsigned int *data);
+ //Interrupt
+ void v_APCI3200_Interrupt(int irq, void *d);
+ int i_APCI3200_InterruptHandleEos(comedi_device *dev);
+ //Reset functions
+ INT i_APCI3200_Reset(comedi_device *dev);
+ 
+-int i_APCI3200_ReadCJCCalOffset(comedi_device *dev, lsampl_t *data);
+-int i_APCI3200_ReadCJCValue(comedi_device *dev, lsampl_t *data);
++int i_APCI3200_ReadCJCCalOffset(comedi_device *dev, unsigned int *data);
++int i_APCI3200_ReadCJCValue(comedi_device *dev, unsigned int *data);
+ int i_APCI3200_ReadCalibrationGainValue(comedi_device *dev, UINT *data);
+ int i_APCI3200_ReadCalibrationOffsetValue(comedi_device *dev, UINT *data);
+ int i_APCI3200_Read1AnalogInputChannel(comedi_device *dev,
+ 				       comedi_subdevice *s, comedi_insn *insn,
+-				       lsampl_t *data);
+-int i_APCI3200_ReadCJCCalGain(comedi_device *dev, lsampl_t *data);
++				       unsigned int *data);
++int i_APCI3200_ReadCJCCalGain(comedi_device *dev, unsigned int *data);
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
+index 9ecd9baa947f..8f5bc0132a62 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
+@@ -57,7 +57,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_ReadDigitalInput                    |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+@@ -74,7 +74,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
+ */
+ 
+ INT i_APCI3501_ReadDigitalInput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+ 	UINT ui_NoOfChannel;
+@@ -100,7 +100,7 @@ INT i_APCI3501_ReadDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_ConfigDigitalOutput                     |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Digital Output Subdevice.               |
+ +----------------------------------------------------------------------------+
+@@ -122,7 +122,7 @@ INT i_APCI3501_ReadDigitalInput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI3501_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	if ((data[0] != 0) && (data[0] != 1)) {
+@@ -143,14 +143,14 @@ int i_APCI3501_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_WriteDigitalOutput                      |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : writes To the digital Output Subdevice                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : comedi_device *dev      : Driver handle                |
+ |                     comedi_subdevice *s     : Subdevice Pointer            |
+ |                     comedi_insn *insn       : Insn Structure Pointer       |
+-|                     lsampl_t *data          : Data Pointer contains        |
++|                     unsigned int *data          : Data Pointer contains        |
+ |                                          configuration parameters as below |
+ |                                                                            |
+ +----------------------------------------------------------------------------+
+@@ -162,7 +162,7 @@ int i_APCI3501_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI3501_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp, ui_Temp1;
+ 	UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);	// get the channel
+@@ -233,7 +233,7 @@ INT i_APCI3501_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_ReadDigitalOutput                       |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read  value  of the selected channel or port           |
+ +----------------------------------------------------------------------------+
+@@ -249,7 +249,7 @@ INT i_APCI3501_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI3501_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	UINT ui_Temp;
+ 	UINT ui_NoOfChannel;
+@@ -276,14 +276,14 @@ INT i_APCI3501_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_ConfigAnalogOutput                      |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Analog Output Subdevice                 |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : comedi_device *dev      : Driver handle                |
+ |                     comedi_subdevice *s     : Subdevice Pointer            |
+ |                     comedi_insn *insn       : Insn Structure Pointer       |
+-|                     lsampl_t *data          : Data Pointer contains        |
++|                     unsigned int *data          : Data Pointer contains        |
+ |                                          configuration parameters as below |
+ |                                                                            |
+ |					data[0]            : Voltage Mode                |
+@@ -299,7 +299,7 @@ INT i_APCI3501_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI3501_ConfigAnalogOutput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	outl(data[0],
+ 		devpriv->iobase + APCI3501_ANALOG_OUTPUT +
+@@ -317,14 +317,14 @@ INT i_APCI3501_ConfigAnalogOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_WriteAnalogOutput                       |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Writes To the Selected Anlog Output Channel            |
+ +----------------------------------------------------------------------------+
+ | Input Parameters  : comedi_device *dev      : Driver handle                |
+ |                     comedi_subdevice *s     : Subdevice Pointer            |
+ |                     comedi_insn *insn       : Insn Structure Pointer       |
+-|                     lsampl_t *data          : Data Pointer contains        |
++|                     unsigned int *data          : Data Pointer contains        |
+ |                                          configuration parameters as below |
+ |                                                                            |
+ |                                                                            |
+@@ -337,7 +337,7 @@ INT i_APCI3501_ConfigAnalogOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI3501_WriteAnalogOutput(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0, ul_Channel_no, ul_Polarity, ul_DAC_Ready = 0;;
+ 
+@@ -387,7 +387,7 @@ INT i_APCI3501_WriteAnalogOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_ConfigTimerCounterWatchdog              |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Configures The Timer , Counter or Watchdog             |
+ +----------------------------------------------------------------------------+
+@@ -411,7 +411,7 @@ INT i_APCI3501_WriteAnalogOutput(comedi_device * dev, comedi_subdevice * s,
+ +----------------------------------------------------------------------------+
+ */
+ INT i_APCI3501_ConfigTimerCounterWatchdog(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0;
+ 	devpriv->tsk_Current = current;
+@@ -490,7 +490,7 @@ INT i_APCI3501_ConfigTimerCounterWatchdog(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_StartStopWriteTimerCounterWatchdog      |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Start / Stop The Selected Timer , Counter or Watchdog  |
+ +----------------------------------------------------------------------------+
+@@ -512,7 +512,7 @@ INT i_APCI3501_ConfigTimerCounterWatchdog(comedi_device * dev,
+ */
+ 
+ int i_APCI3501_StartStopWriteTimerCounterWatchdog(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	ULONG ul_Command1 = 0;
+ 	int i_Temp;
+@@ -593,7 +593,7 @@ int i_APCI3501_StartStopWriteTimerCounterWatchdog(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ | Function   Name   : int i_APCI3501_ReadTimerCounterWatchdog                |
+ |			  (comedi_device *dev,comedi_subdevice *s,               |
+-|                      comedi_insn *insn,lsampl_t *data)                     |
++|                      comedi_insn *insn,unsigned int *data)                     |
+ +----------------------------------------------------------------------------+
+ | Task              : Read The Selected Timer , Counter or Watchdog          |
+ +----------------------------------------------------------------------------+
+@@ -614,7 +614,7 @@ int i_APCI3501_StartStopWriteTimerCounterWatchdog(comedi_device * dev,
+ */
+ 
+ int i_APCI3501_ReadTimerCounterWatchdog(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
+index 03b7d2e4956f..aeb7f032884f 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
+@@ -56,37 +56,37 @@ comedi_lrange range_apci3501_ao = { 2, {
+ 
+ //AO
+ INT i_APCI3501_ConfigAnalogOutput(comedi_device *dev, comedi_subdevice *s,
+-				  comedi_insn *insn, lsampl_t *data);
++				  comedi_insn *insn, unsigned int *data);
+ INT i_APCI3501_WriteAnalogOutput(comedi_device *dev, comedi_subdevice *s,
+-				 comedi_insn *insn, lsampl_t *data);
++				 comedi_insn *insn, unsigned int *data);
+ 
+ //DI
+ // for di read
+-//INT i_APCI3501_ReadDigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
++//INT i_APCI3501_ReadDigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data);
+ 
+ INT i_APCI3501_ReadDigitalInput(comedi_device *dev, comedi_subdevice *s,
+-				comedi_insn *insn, lsampl_t *data);
++				comedi_insn *insn, unsigned int *data);
+ 
+ //DO
+ int i_APCI3501_ConfigDigitalOutput(comedi_device *dev, comedi_subdevice *s,
+-				   comedi_insn *insn, lsampl_t *data);
++				   comedi_insn *insn, unsigned int *data);
+ INT i_APCI3501_WriteDigitalOutput(comedi_device *dev, comedi_subdevice *s,
+-				  comedi_insn *insn, lsampl_t *data);
++				  comedi_insn *insn, unsigned int *data);
+ INT i_APCI3501_ReadDigitalOutput(comedi_device *dev, comedi_subdevice *s,
+-				 comedi_insn *insn, lsampl_t *data);
++				 comedi_insn *insn, unsigned int *data);
+ 
+ // TIMER
+ // timer value is passed as u seconds
+ INT i_APCI3501_ConfigTimerCounterWatchdog(comedi_device *dev,
+ 					  comedi_subdevice *s,
+-					  comedi_insn *insn, lsampl_t *data);
++					  comedi_insn *insn, unsigned int *data);
+ int i_APCI3501_StartStopWriteTimerCounterWatchdog(comedi_device *dev,
+ 						  comedi_subdevice *s,
+ 						  comedi_insn *insn,
+-						  lsampl_t *data);
++						  unsigned int *data);
+ int i_APCI3501_ReadTimerCounterWatchdog(comedi_device *dev,
+ 					comedi_subdevice *s,
+-					comedi_insn *insn, lsampl_t *data);
++					comedi_insn *insn, unsigned int *data);
+ //Interrupt
+ void v_APCI3501_Interrupt(int irq, void *d);
+ 
+diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+index a4f411dfb02f..7a78c99405b2 100644
+--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+@@ -83,7 +83,7 @@ int i_APCI3XXX_TestConversionStarted(comedi_device * dev)
+ |                          (comedi_device    *dev,                           |
+ |                           comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+-|                           lsampl_t         *data)                          |
++|                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+ | Task           Converting mode and convert time selection                  |
+ +----------------------------------------------------------------------------+
+@@ -106,7 +106,7 @@ int i_APCI3XXX_TestConversionStarted(comedi_device * dev)
+ */
+ 
+ int i_APCI3XXX_AnalogInputConfigOperatingMode(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_TimeBase = 0;
+@@ -277,7 +277,7 @@ int i_APCI3XXX_AnalogInputConfigOperatingMode(comedi_device * dev,
+ |                          (comedi_device    *dev,                           |
+ |                           comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+-|                           lsampl_t         *data)                          |
++|                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+ | Task           Converting mode and convert time selection                  |
+ +----------------------------------------------------------------------------+
+@@ -296,7 +296,7 @@ int i_APCI3XXX_AnalogInputConfigOperatingMode(comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnConfigAnalogInput(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 
+@@ -335,7 +335,7 @@ int i_APCI3XXX_InsnConfigAnalogInput(comedi_device * dev,
+ |                          (comedi_device    *dev,                           |
+ |                           comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+-|                           lsampl_t         *data)                          |
++|                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+ | Task                Read 1 analog input                                    |
+ +----------------------------------------------------------------------------+
+@@ -356,7 +356,7 @@ int i_APCI3XXX_InsnConfigAnalogInput(comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnReadAnalogInput(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Configuration = (BYTE) CR_RANGE(insn->chanspec);
+@@ -544,7 +544,7 @@ int i_APCI3XXX_InsnReadAnalogInput(comedi_device * dev,
+ 
+ 							data[dw_AcquisitionCpt]
+ 								=
+-								(lsampl_t)
++								(unsigned int)
+ 								readl((void
+ 									*)
+ 								(devpriv->
+@@ -666,7 +666,7 @@ void v_APCI3XXX_Interrupt(int irq, void *d)
+ |                          (comedi_device    *dev,                           |
+ |                           comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+-|                           lsampl_t         *data)                          |
++|                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+ | Task                Read 1 analog input                                    |
+ +----------------------------------------------------------------------------+
+@@ -685,7 +685,7 @@ void v_APCI3XXX_Interrupt(int irq, void *d)
+ */
+ 
+ int i_APCI3XXX_InsnWriteAnalogOutput(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_Range = (BYTE) CR_RANGE(insn->chanspec);
+ 	BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
+@@ -772,7 +772,7 @@ int i_APCI3XXX_InsnWriteAnalogOutput(comedi_device * dev,
+ |                          (comedi_device    *dev,                           |
+ |                           comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+-|                           lsampl_t         *data)                          |
++|                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+ | Task           You must calling this function be                           |
+ |                for you call any other function witch access of TTL.        |
+@@ -792,7 +792,7 @@ int i_APCI3XXX_InsnWriteAnalogOutput(comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnConfigInitTTLIO(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Command = 0;
+@@ -903,7 +903,7 @@ int i_APCI3XXX_InsnConfigInitTTLIO(comedi_device * dev,
+ |                          (comedi_device    *dev,                           |
+ |                           comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+-|                           lsampl_t         *data)                          |
++|                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+ | Task              : Write the selected output mask and read the status from|
+ |                     all TTL channles                                       |
+@@ -920,7 +920,7 @@ int i_APCI3XXX_InsnConfigInitTTLIO(comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnBitsTTLIO(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_ChannelCpt = 0;
+@@ -1060,7 +1060,7 @@ int i_APCI3XXX_InsnBitsTTLIO(comedi_device * dev,
+ |                          (comedi_device    *dev,                           |
+ |                           comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+-|                           lsampl_t         *data)                          |
++|                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+ | Task              : Read the status from selected channel                  |
+ +----------------------------------------------------------------------------+
+@@ -1075,11 +1075,11 @@ int i_APCI3XXX_InsnBitsTTLIO(comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnReadTTLIO(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
+ 	INT i_ReturnValue = insn->n;
+-	lsampl_t *pls_ReadData = data;
++	unsigned int *pls_ReadData = data;
+ 
+ 	/************************/
+ 	/* Test the buffer size */
+@@ -1172,7 +1172,7 @@ int i_APCI3XXX_InsnReadTTLIO(comedi_device * dev,
+ |                          (comedi_device    *dev,                           |
+ |                           comedi_subdevice *s,                             |
+ |                           comedi_insn      *insn,                          |
+-|                           lsampl_t         *data)                          |
++|                           unsigned int         *data)                          |
+ +----------------------------------------------------------------------------+
+ | Task              : Set the state from TTL output channel                  |
+ +----------------------------------------------------------------------------+
+@@ -1188,7 +1188,7 @@ int i_APCI3XXX_InsnReadTTLIO(comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnWriteTTLIO(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
+@@ -1284,7 +1284,7 @@ int i_APCI3XXX_InsnWriteTTLIO(comedi_device * dev,
+ |                                          (comedi_device *dev,              |
+ |                                           comedi_subdevice *s,             |
+ |                                           comedi_insn *insn,               |
+-|                                           lsampl_t *data)                  |
++|                                           unsigned int *data)                  |
+ +----------------------------------------------------------------------------+
+ | Task              : Reads the value of the specified Digital input channel |
+ +----------------------------------------------------------------------------+
+@@ -1299,7 +1299,7 @@ int i_APCI3XXX_InsnWriteTTLIO(comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnReadDigitalInput(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
+@@ -1343,7 +1343,7 @@ int i_APCI3XXX_InsnReadDigitalInput(comedi_device * dev,
+ |                                          (comedi_device *dev,              |
+ |                                           comedi_subdevice *s,             |
+ |                                           comedi_insn *insn,               |
+-|                                           lsampl_t *data)                  |
++|                                           unsigned int *data)                  |
+ +----------------------------------------------------------------------------+
+ | Task              : Reads the value of the Digital input Port i.e.4channels|
+ +----------------------------------------------------------------------------+
+@@ -1357,7 +1357,7 @@ int i_APCI3XXX_InsnReadDigitalInput(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI3XXX_InsnBitsDigitalInput(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	DWORD dw_Temp = 0;
+@@ -1394,7 +1394,7 @@ int i_APCI3XXX_InsnBitsDigitalInput(comedi_device * dev,
+ |                                          (comedi_device *dev,              |
+ |                                           comedi_subdevice *s,             |
+ |                                           comedi_insn *insn,               |
+-|                                           lsampl_t *data)                  |
++|                                           unsigned int *data)                  |
+ +----------------------------------------------------------------------------+
+ | Task              : Write the selected output mask and read the status from|
+ |                     all digital output channles                            |
+@@ -1410,7 +1410,7 @@ int i_APCI3XXX_InsnBitsDigitalInput(comedi_device * dev,
+ +----------------------------------------------------------------------------+
+ */
+ int i_APCI3XXX_InsnBitsDigitalOutput(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_ChannelCpt = 0;
+@@ -1490,7 +1490,7 @@ int i_APCI3XXX_InsnBitsDigitalOutput(comedi_device * dev,
+ |                                          (comedi_device *dev,              |
+ |                                           comedi_subdevice *s,             |
+ |                                           comedi_insn *insn,               |
+-|                                           lsampl_t *data)                  |
++|                                           unsigned int *data)                  |
+ +----------------------------------------------------------------------------+
+ | Task              : Set the state from digital output channel              |
+ +----------------------------------------------------------------------------+
+@@ -1506,7 +1506,7 @@ int i_APCI3XXX_InsnBitsDigitalOutput(comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnWriteDigitalOutput(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Channel = CR_CHAN(insn->chanspec);
+@@ -1566,7 +1566,7 @@ int i_APCI3XXX_InsnWriteDigitalOutput(comedi_device * dev,
+ |                                          (comedi_device *dev,              |
+ |                                           comedi_subdevice *s,             |
+ |                                           comedi_insn *insn,               |
+-|                                           lsampl_t *data)                  |
++|                                           unsigned int *data)                  |
+ +----------------------------------------------------------------------------+
+ | Task              : Read the state from digital output channel             |
+ +----------------------------------------------------------------------------+
+@@ -1581,7 +1581,7 @@ int i_APCI3XXX_InsnWriteDigitalOutput(comedi_device * dev,
+ */
+ 
+ int i_APCI3XXX_InsnReadDigitalOutput(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	INT i_ReturnValue = insn->n;
+ 	BYTE b_Channel = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c
+index 0740ae697506..65fe959fc53b 100644
+--- a/drivers/staging/comedi/drivers/adl_pci6208.c
++++ b/drivers/staging/comedi/drivers/adl_pci6208.c
+@@ -101,7 +101,7 @@ MODULE_DEVICE_TABLE(pci, pci6208_pci_table);
+ typedef struct {
+ 	int data;
+ 	struct pci_dev *pci_dev;	/* for a PCI device */
+-	lsampl_t ao_readback[2];	/* Used for AO readback */
++	unsigned int ao_readback[2];	/* Used for AO readback */
+ } pci6208_private;
+ 
+ #define devpriv ((pci6208_private *)dev->private)
+@@ -128,13 +128,13 @@ pci6208_pci_setup(struct pci_dev *pci_dev, unsigned long *io_base_ptr,
+ 
+ /*read/write functions*/
+ static int pci6208_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int pci6208_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ //static int pci6208_dio_insn_bits(comedi_device *dev,comedi_subdevice *s,
+-//      comedi_insn *insn,lsampl_t *data);
++//      comedi_insn *insn,unsigned int *data);
+ //static int pci6208_dio_insn_config(comedi_device *dev,comedi_subdevice *s,
+-//      comedi_insn *insn,lsampl_t *data);
++//      comedi_insn *insn,unsigned int *data);
+ 
+ /*
+  * Attach is called by the Comedi core to configure the driver
+@@ -220,7 +220,7 @@ static int pci6208_detach(comedi_device * dev)
+ }
+ 
+ static int pci6208_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i = 0, Data_Read;
+ 	unsigned short chan = CR_CHAN(insn->chanspec);
+@@ -245,7 +245,7 @@ static int pci6208_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+ static int pci6208_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -262,7 +262,7 @@ static int pci6208_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+ //static int pci6208_dio_insn_bits(comedi_device *dev,comedi_subdevice *s,
+-//      comedi_insn *insn,lsampl_t *data)
++//      comedi_insn *insn,unsigned int *data)
+ //{
+ //      if(insn->n!=2)return -EINVAL;
+ 
+@@ -286,7 +286,7 @@ static int pci6208_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+ //}
+ 
+ //static int pci6208_dio_insn_config(comedi_device *dev,comedi_subdevice *s,
+-//      comedi_insn *insn,lsampl_t *data)
++//      comedi_insn *insn,unsigned int *data)
+ //{
+ //      int chan=CR_CHAN(insn->chanspec);
+ 
+diff --git a/drivers/staging/comedi/drivers/adl_pci7432.c b/drivers/staging/comedi/drivers/adl_pci7432.c
+index caeb5048f20d..4e54d08d2e37 100644
+--- a/drivers/staging/comedi/drivers/adl_pci7432.c
++++ b/drivers/staging/comedi/drivers/adl_pci7432.c
+@@ -70,10 +70,10 @@ static comedi_driver driver_adl_pci7432 = {
+ /* Digital IO */
+ 
+ static int adl_pci7432_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ static int adl_pci7432_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ /*            */
+ 
+@@ -165,7 +165,7 @@ static int adl_pci7432_detach(comedi_device * dev)
+ }
+ 
+ static int adl_pci7432_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	printk("comedi: pci7432_do_insn_bits called\n");
+ 	printk("comedi: data0: %8x data1: %8x\n", data[0], data[1]);
+@@ -185,7 +185,7 @@ static int adl_pci7432_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int adl_pci7432_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	printk("comedi: pci7432_di_insn_bits called\n");
+ 	printk("comedi: data0: %8x data1: %8x\n", data[0], data[1]);
+diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c
+index 3b13da2be418..9d5c9875a06b 100644
+--- a/drivers/staging/comedi/drivers/adl_pci8164.c
++++ b/drivers/staging/comedi/drivers/adl_pci8164.c
+@@ -80,28 +80,28 @@ static comedi_driver driver_adl_pci8164 = {
+ };
+ 
+ static int adl_pci8164_insn_read_msts(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ static int adl_pci8164_insn_read_ssts(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ static int adl_pci8164_insn_read_buf0(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ static int adl_pci8164_insn_read_buf1(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ static int adl_pci8164_insn_write_cmd(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ static int adl_pci8164_insn_write_otp(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ static int adl_pci8164_insn_write_buf0(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+ static int adl_pci8164_insn_write_buf1(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+ static int adl_pci8164_attach(comedi_device * dev, comedi_devconfig * it)
+ {
+@@ -209,7 +209,7 @@ static int adl_pci8164_detach(comedi_device * dev)
+ }
+ 
+ static int adl_pci8164_insn_read_msts(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+ 	char *axisname;
+@@ -246,7 +246,7 @@ static int adl_pci8164_insn_read_msts(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int adl_pci8164_insn_read_ssts(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+ 	char *axisname;
+@@ -283,7 +283,7 @@ static int adl_pci8164_insn_read_ssts(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int adl_pci8164_insn_read_buf0(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+ 	char *axisname;
+@@ -320,7 +320,7 @@ static int adl_pci8164_insn_read_buf0(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int adl_pci8164_insn_read_buf1(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+ 
+@@ -358,7 +358,7 @@ static int adl_pci8164_insn_read_buf1(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int adl_pci8164_insn_write_cmd(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int axis, axis_reg;
+ 
+@@ -396,7 +396,7 @@ static int adl_pci8164_insn_write_cmd(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int adl_pci8164_insn_write_otp(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+ 
+@@ -434,7 +434,7 @@ static int adl_pci8164_insn_write_otp(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int adl_pci8164_insn_write_buf0(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+ 
+@@ -472,7 +472,7 @@ static int adl_pci8164_insn_write_buf0(comedi_device * dev,
+ }
+ 
+ static int adl_pci8164_insn_write_buf1(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int axis, axis_reg;
+ 
+diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
+index c8ba2b728831..1b9e9740a4c7 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9111.c
++++ b/drivers/staging/comedi/drivers/adl_pci9111.c
+@@ -361,7 +361,7 @@ typedef struct {
+ 
+ 	int is_valid;		// Is device valid
+ 
+-	sampl_t ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE];
++	short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE];
+ } pci9111_private_data_struct;
+ 
+ #define dev_private 	((pci9111_private_data_struct *)dev->private)
+@@ -884,8 +884,8 @@ static int pci9111_ai_do_cmd(comedi_device * dev, comedi_subdevice * subdevice)
+ static void pci9111_ai_munge(comedi_device * dev, comedi_subdevice * s,
+ 	void *data, unsigned int num_bytes, unsigned int start_chan_index)
+ {
+-	unsigned int i, num_samples = num_bytes / sizeof(sampl_t);
+-	sampl_t *array = data;
++	unsigned int i, num_samples = num_bytes / sizeof(short);
++	short *array = data;
+ 	int resolution =
+ 		((pci9111_board_struct *) dev->board_ptr)->ai_resolution;
+ 
+@@ -983,7 +983,7 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device PT_REGS_ARG)
+ 				bytes_written =
+ 					cfc_write_array_to_buffer(subdevice,
+ 					dev_private->ai_bounce_buffer,
+-					num_samples * sizeof(sampl_t));
++					num_samples * sizeof(short));
+ 			} else {
+ 				int position = 0;
+ 				int to_read;
+@@ -1010,7 +1010,7 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device PT_REGS_ARG)
+ 							ai_bounce_buffer +
+ 							position,
+ 							to_read *
+-							sizeof(sampl_t));
++							sizeof(short));
+ 					} else {
+ 						to_read =
+ 							dev_private->
+@@ -1024,7 +1024,7 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device PT_REGS_ARG)
+ 								position;
+ 
+ 						bytes_written +=
+-							sizeof(sampl_t) *
++							sizeof(short) *
+ 							to_read;
+ 					}
+ 
+@@ -1038,7 +1038,7 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device PT_REGS_ARG)
+ 			}
+ 
+ 			dev_private->stop_counter -=
+-				bytes_written / sizeof(sampl_t);
++				bytes_written / sizeof(short);
+ 		}
+ 	}
+ 
+@@ -1072,7 +1072,7 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device PT_REGS_ARG)
+ #undef AI_INSN_DEBUG
+ 
+ static int pci9111_ai_insn_read(comedi_device * dev,
+-	comedi_subdevice * subdevice, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * subdevice, comedi_insn * insn, unsigned int * data)
+ {
+ 	int resolution =
+ 		((pci9111_board_struct *) dev->board_ptr)->ai_resolution;
+@@ -1132,7 +1132,7 @@ static int pci9111_ai_insn_read(comedi_device * dev,
+ 
+ static int
+ pci9111_ao_insn_write(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 
+@@ -1149,7 +1149,7 @@ pci9111_ao_insn_write(comedi_device * dev,
+ //
+ 
+ static int pci9111_ao_insn_read(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 
+@@ -1171,9 +1171,9 @@ static int pci9111_ao_insn_read(comedi_device * dev,
+ //
+ 
+ static int pci9111_di_insn_bits(comedi_device * dev,
+-	comedi_subdevice * subdevice, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * subdevice, comedi_insn * insn, unsigned int * data)
+ {
+-	lsampl_t bits;
++	unsigned int bits;
+ 
+ 	bits = pci9111_di_get_bits();
+ 	data[1] = bits;
+@@ -1186,9 +1186,9 @@ static int pci9111_di_insn_bits(comedi_device * dev,
+ //
+ 
+ static int pci9111_do_insn_bits(comedi_device * dev,
+-	comedi_subdevice * subdevice, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * subdevice, comedi_insn * insn, unsigned int * data)
+ {
+-	lsampl_t bits;
++	unsigned int bits;
+ 
+ 	// Only set bits that have been masked
+ 	// data[0] = mask
+diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
+index 5149c748fe8f..9dc30b282973 100644
+--- a/drivers/staging/comedi/drivers/adl_pci9118.c
++++ b/drivers/staging/comedi/drivers/adl_pci9118.c
+@@ -272,12 +272,12 @@ typedef struct {
+ 	char ai12_startstop;	// measure can start/stop on external trigger
+ 	unsigned int ai_divisor1, ai_divisor2;	// divisors for start of measure on external start
+ 	unsigned int ai_data_len;
+-	sampl_t *ai_data;
+-	sampl_t ao_data[2];	// data output buffer
++	short *ai_data;
++	short ao_data[2];	// data output buffer
+ 	unsigned int ai_scans;	// number of scans to do
+ 	char dma_doublebuf;	// we can use double buffring
+ 	unsigned int dma_actbuf;	// which buffer is used now
+-	sampl_t *dmabuf_virt[2];	// pointers to begin of DMA buffer
++	short *dmabuf_virt[2];	// pointers to begin of DMA buffer
+ 	unsigned long dmabuf_hw[2];	// hw address of DMA buff
+ 	unsigned int dmabuf_size[2];	// size of dma buffer in bytes
+ 	unsigned int dmabuf_use_size[2];	// which size we may now used for transfer
+@@ -328,7 +328,7 @@ static void pci9118_calc_divisors(char mode, comedi_device * dev,
+ ==============================================================================
+ */
+ static int pci9118_insn_read_ai(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	int n, timeout;
+@@ -378,7 +378,7 @@ static int pci9118_insn_read_ai(comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+ */
+ static int pci9118_insn_write_ao(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, chanreg, ch;
+ 
+@@ -401,7 +401,7 @@ static int pci9118_insn_write_ao(comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+ */
+ static int pci9118_insn_read_ao(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, chan;
+ 
+@@ -416,7 +416,7 @@ static int pci9118_insn_read_ao(comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+ */
+ static int pci9118_insn_bits_di(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[1] = inl(dev->iobase + PCI9118_DI) & 0xf;
+ 
+@@ -427,7 +427,7 @@ static int pci9118_insn_bits_di(comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+ */
+ static int pci9118_insn_bits_do(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+ 		s->state &= ~data[0];
+@@ -457,7 +457,7 @@ static void interrupt_pci9118_ai_mode4_switch(comedi_device * dev)
+ }
+ 
+ static unsigned int defragment_dma_buffer(comedi_device * dev,
+-	comedi_subdevice * s, sampl_t * dma_buffer, unsigned int num_samples)
++	comedi_subdevice * s, short * dma_buffer, unsigned int num_samples)
+ {
+ 	unsigned int i = 0, j = 0;
+ 	unsigned int start_pos = devpriv->ai_add_front,
+@@ -481,7 +481,7 @@ static unsigned int defragment_dma_buffer(comedi_device * dev,
+ ==============================================================================
+ */
+ static unsigned int move_block_from_dma(comedi_device * dev,
+-	comedi_subdevice * s, sampl_t * dma_buffer, unsigned int num_samples)
++	comedi_subdevice * s, short * dma_buffer, unsigned int num_samples)
+ {
+ 	unsigned int num_bytes;
+ 
+@@ -492,8 +492,8 @@ static unsigned int move_block_from_dma(comedi_device * dev,
+ 	s->async->cur_chan %= devpriv->ai_n_scanlen;
+ 	num_bytes =
+ 		cfc_write_array_to_buffer(s, dma_buffer,
+-		num_samples * sizeof(sampl_t));
+-	if (num_bytes < num_samples * sizeof(sampl_t))
++		num_samples * sizeof(short));
++	if (num_bytes < num_samples * sizeof(short))
+ 		return -1;
+ 	return 0;
+ }
+@@ -534,8 +534,8 @@ static char pci9118_decode_error_status(comedi_device * dev,
+ static void pci9118_ai_munge(comedi_device * dev, comedi_subdevice * s,
+ 	void *data, unsigned int num_bytes, unsigned int start_chan_index)
+ {
+-	unsigned int i, num_samples = num_bytes / sizeof(sampl_t);
+-	sampl_t *array = data;
++	unsigned int i, num_samples = num_bytes / sizeof(short);
++	short *array = data;
+ 
+ 	for (i = 0; i < num_samples; i++) {
+ 		if (devpriv->usedma)
+@@ -555,7 +555,7 @@ static void interrupt_pci9118_ai_onesample(comedi_device * dev,
+ 	comedi_subdevice * s, unsigned short int_adstat, unsigned int int_amcc,
+ 	unsigned short int_daq)
+ {
+-	register sampl_t sampl;
++	register short sampl;
+ 
+ 	s->async->events = 0;
+ 
+@@ -1131,10 +1131,10 @@ static int Compute_and_setup_dma(comedi_device * dev)
+ 	if (devpriv->ai_n_scanlen < this_board->half_fifo_size) {
+ 		devpriv->dmabuf_panic_size[0] =
+ 			(this_board->half_fifo_size / devpriv->ai_n_scanlen +
+-			1) * devpriv->ai_n_scanlen * sizeof(sampl_t);
++			1) * devpriv->ai_n_scanlen * sizeof(short);
+ 		devpriv->dmabuf_panic_size[1] =
+ 			(this_board->half_fifo_size / devpriv->ai_n_scanlen +
+-			1) * devpriv->ai_n_scanlen * sizeof(sampl_t);
++			1) * devpriv->ai_n_scanlen * sizeof(short);
+ 	} else {
+ 		devpriv->dmabuf_panic_size[0] =
+ 			(devpriv->ai_n_scanlen << 1) % devpriv->dmabuf_size[0];
+@@ -1940,7 +1940,7 @@ static int pci9118_attach(comedi_device * dev, comedi_devconfig * it)
+ 		devpriv->dma_doublebuf = 0;
+ 		for (i = 0; i < 2; i++) {
+ 			for (pages = 4; pages >= 0; pages--)
+-				if ((devpriv->dmabuf_virt[i] = (sampl_t *)
++				if ((devpriv->dmabuf_virt[i] = (short *)
+ 						__get_free_pages(GFP_KERNEL,
+ 							pages)))
+ 					break;
+diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c
+index 8f233b60b69a..f32e55921b5f 100644
+--- a/drivers/staging/comedi/drivers/adq12b.c
++++ b/drivers/staging/comedi/drivers/adq12b.c
+@@ -151,7 +151,7 @@ typedef struct{
+         int differential;      /* option 3 of comedi_config */
+         int last_channel;
+         int last_range;
+-        lsampl_t digital_state;
++        unsigned int digital_state;
+  }adq12b_private;
+ 
+ #define devpriv ((adq12b_private *)dev->private)
+@@ -174,9 +174,9 @@ static comedi_driver driver_adq12b={
+         num_names:      sizeof(adq12b_boards) / sizeof(adq12b_board),
+ };
+ 
+-static int adq12b_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
+-static int adq12b_di_insn_bits(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data);
+-static int adq12b_do_insn_bits(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data);
++static int adq12b_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data);
++static int adq12b_di_insn_bits(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,unsigned int *data);
++static int adq12b_do_insn_bits(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,unsigned int *data);
+ 
+ /*
+  * Attach is called by the Comedi core to configure the driver
+@@ -314,7 +314,7 @@ static int adq12b_detach(comedi_device *dev)
+  * mode.
+  */
+ 
+-static int adq12b_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
++static int adq12b_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data)
+ {
+         int n, i;
+         int range, channel;
+@@ -357,7 +357,7 @@ static int adq12b_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *i
+ }
+ 
+ 
+-static int adq12b_di_insn_bits(comedi_device *dev,comedi_subdevice *s, 	comedi_insn *insn,lsampl_t *data)
++static int adq12b_di_insn_bits(comedi_device *dev,comedi_subdevice *s, 	comedi_insn *insn,unsigned int *data)
+ {
+ 
+         /* only bits 0-4 have information about digital inputs */
+@@ -367,7 +367,7 @@ static int adq12b_di_insn_bits(comedi_device *dev,comedi_subdevice *s, 	comedi_i
+ }
+ 
+ 
+-static int adq12b_do_insn_bits(comedi_device *dev,comedi_subdevice *s, 	comedi_insn *insn,lsampl_t *data)
++static int adq12b_do_insn_bits(comedi_device *dev,comedi_subdevice *s, 	comedi_insn *insn,unsigned int *data)
+ {
+         int channel;
+ 
+diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
+index edfcfd51ad6c..e482e602ba9e 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1710.c
++++ b/drivers/staging/comedi/drivers/adv_pci1710.c
+@@ -290,10 +290,10 @@ typedef struct {
+ 	unsigned int *ai_chanlist;	// actaul chanlist
+ 	unsigned int ai_flags;	// flaglist
+ 	unsigned int ai_data_len;	// len of data buffer
+-	sampl_t *ai_data;	// data buffer
++	short *ai_data;	// data buffer
+ 	unsigned int ai_timer1;	// timers
+ 	unsigned int ai_timer2;
+-	sampl_t ao_data[4];	// data output buffer
++	short ao_data[4];	// data output buffer
+ 	unsigned int cnt0_write_wait;	// after a write, wait for update of the internal state
+ } pci1710_private;
+ 
+@@ -323,7 +323,7 @@ static const unsigned int muxonechan[] = { 0x0000, 0x0101, 0x0202, 0x0303, 0x040
+ ==============================================================================
+ */
+ static int pci171x_insn_read_ai(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, timeout;
+ #ifdef PCI171x_PARANOIDCHECK
+@@ -391,7 +391,7 @@ static int pci171x_insn_read_ai(comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+ */
+ static int pci171x_insn_write_ao(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, chan, range, ofs;
+ 
+@@ -422,7 +422,7 @@ static int pci171x_insn_write_ao(comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+ */
+ static int pci171x_insn_read_ao(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, chan;
+ 
+@@ -437,7 +437,7 @@ static int pci171x_insn_read_ao(comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+ */
+ static int pci171x_insn_bits_di(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[1] = inw(dev->iobase + PCI171x_DI);
+ 
+@@ -448,7 +448,7 @@ static int pci171x_insn_bits_di(comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+ */
+ static int pci171x_insn_bits_do(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+ 		s->state &= ~data[0];
+@@ -464,7 +464,7 @@ static int pci171x_insn_bits_do(comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+ */
+ static int pci171x_insn_counter_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int msb, lsb, ccntrl;
+ 	int i;
+@@ -486,7 +486,7 @@ static int pci171x_insn_counter_read(comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+ */
+ static int pci171x_insn_counter_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	uint msb, lsb, ccntrl, status;
+ 
+@@ -513,7 +513,7 @@ static int pci171x_insn_counter_write(comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+ */
+ static int pci171x_insn_counter_config(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ #ifdef unused
+ 	/* This doesn't work like a normal Comedi counter config */
+@@ -549,7 +549,7 @@ static int pci171x_insn_counter_config(comedi_device * dev,
+ ==============================================================================
+ */
+ static int pci1720_insn_write_ao(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, rangereg, chan;
+ 
+@@ -580,7 +580,7 @@ static void interrupt_pci1710_every_sample(void *d)
+ 	comedi_subdevice *s = dev->subdevices + 0;
+ 	int m;
+ #ifdef PCI171x_PARANOIDCHECK
+-	sampl_t sampl;
++	short sampl;
+ #endif
+ 
+ 	DPRINTK("adv_pci1710 EDBG: BGN: interrupt_pci1710_every_sample(...)\n");
+@@ -732,8 +732,8 @@ static void interrupt_pci1710_half_fifo(void *d)
+ 	}
+ 
+ 	samplesinbuf = this_board->fifo_half_size;
+-	if (samplesinbuf * sizeof(sampl_t) >= devpriv->ai_data_len) {
+-		m = devpriv->ai_data_len / sizeof(sampl_t);
++	if (samplesinbuf * sizeof(short) >= devpriv->ai_data_len) {
++		m = devpriv->ai_data_len / sizeof(short);
+ 		if (move_block_from_fifo(dev, s, m, 0))
+ 			return;
+ 		samplesinbuf -= m;
+diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
+index 3cc573db4c7c..46b70942ac85 100644
+--- a/drivers/staging/comedi/drivers/adv_pci1723.c
++++ b/drivers/staging/comedi/drivers/adv_pci1723.c
+@@ -162,7 +162,7 @@ typedef struct {
+ 	struct pci_dev *pcidev;
+ 	unsigned char da_range[8];	// D/A output range for each channel
+ 
+-	sampl_t ao_data[8];	// data output buffer
++	short ao_data[8];	// data output buffer
+ } pci1723_private;
+ 
+ /*the following macro to make it easy to
+@@ -203,7 +203,7 @@ static int pci1723_reset(comedi_device * dev)
+ }
+ 
+ static int pci1723_insn_read_ao(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, chan;
+ 
+@@ -219,7 +219,7 @@ static int pci1723_insn_read_ao(comedi_device * dev, comedi_subdevice * s,
+   analog data output;
+ */
+ static int pci1723_ao_write_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, chan;
+ 	chan = CR_CHAN(insn->chanspec);
+@@ -239,7 +239,7 @@ static int pci1723_ao_write_winsn(comedi_device * dev, comedi_subdevice * s,
+   digital i/o config/query
+ */
+ static int pci1723_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int mask;
+ 	unsigned int bits;
+@@ -279,7 +279,7 @@ static int pci1723_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+   digital i/o bits read/write
+ */
+ static int pci1723_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+ 		s->state &= ~data[0];
+diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
+index 06f373098d7d..25ddbc86fb33 100644
+--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
++++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
+@@ -358,7 +358,7 @@ static pci_dio_private *pci_priv = NULL;	/* list of allocated cards */
+ ==============================================================================
+ */
+ static int pci_dio_insn_bits_di_b(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	const diosubd_data *d = (const diosubd_data *)s->private;
+ 	int i;
+@@ -375,7 +375,7 @@ static int pci_dio_insn_bits_di_b(comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+ */
+ static int pci_dio_insn_bits_di_w(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	const diosubd_data *d = (const diosubd_data *)s->private;
+ 	int i;
+@@ -391,7 +391,7 @@ static int pci_dio_insn_bits_di_w(comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+ */
+ static int pci_dio_insn_bits_do_b(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	const diosubd_data *d = (const diosubd_data *)s->private;
+ 	int i;
+@@ -412,7 +412,7 @@ static int pci_dio_insn_bits_do_b(comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+ */
+ static int pci_dio_insn_bits_do_w(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	const diosubd_data *d = (const diosubd_data *)s->private;
+ 	int i;
+@@ -491,7 +491,7 @@ static int pci1760_mbxrequest(comedi_device * dev,
+ ==============================================================================
+ */
+ static int pci1760_insn_bits_di(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[1] = inb(dev->iobase + IMB3);
+ 
+@@ -502,7 +502,7 @@ static int pci1760_insn_bits_di(comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+ */
+ static int pci1760_insn_bits_do(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int ret;
+ 	unsigned char omb[4] = {
+@@ -529,7 +529,7 @@ static int pci1760_insn_bits_do(comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+ */
+ static int pci1760_insn_cnt_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int ret, n;
+ 	unsigned char omb[4] = {
+@@ -553,7 +553,7 @@ static int pci1760_insn_cnt_read(comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+ */
+ static int pci1760_insn_cnt_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int ret;
+ 	unsigned char chan = CR_CHAN(insn->chanspec) & 0x07;
+diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c
+index 227f446db790..3a326f6e3205 100644
+--- a/drivers/staging/comedi/drivers/aio_aio12_8.c
++++ b/drivers/staging/comedi/drivers/aio_aio12_8.c
+@@ -83,13 +83,13 @@ static const board_type board_types[] = {
+ #define	thisboard	((const board_type *) dev->board_ptr)
+ 
+ typedef struct {
+-	lsampl_t ao_readback[4];
++	unsigned int ao_readback[4];
+ } aio12_8_private;
+ 
+ #define devpriv	((aio12_8_private *) dev->private)
+ 
+ static int aio_aio12_8_ai_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	unsigned char control =
+@@ -123,7 +123,7 @@ static int aio_aio12_8_ai_read(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int aio_aio12_8_ao_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int val = devpriv->ao_readback[CR_CHAN(insn->chanspec)];
+@@ -134,7 +134,7 @@ static int aio_aio12_8_ao_read(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int aio_aio12_8_ao_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c
+index f7958e380ca5..2da86744bc00 100644
+--- a/drivers/staging/comedi/drivers/aio_iiro_16.c
++++ b/drivers/staging/comedi/drivers/aio_iiro_16.c
+@@ -62,7 +62,7 @@ static const aio_iiro_16_board aio_iiro_16_boards[] = {
+ typedef struct {
+ 	int data;
+ 	struct pci_dev *pci_dev;
+-	lsampl_t ao_readback[2];
++	unsigned int ao_readback[2];
+ } aio_iiro_16_private;
+ 
+ #define	devpriv	((aio_iiro_16_private *) dev->private)
+@@ -82,10 +82,10 @@ static comedi_driver driver_aio_iiro_16 = {
+ };
+ 
+ static int aio_iiro_16_dio_insn_bits_read(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+ static int aio_iiro_16_dio_insn_bits_write(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+ static int aio_iiro_16_attach(comedi_device * dev, comedi_devconfig * it)
+ {
+@@ -143,7 +143,7 @@ static int aio_iiro_16_detach(comedi_device * dev)
+ }
+ 
+ static int aio_iiro_16_dio_insn_bits_write(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -162,7 +162,7 @@ static int aio_iiro_16_dio_insn_bits_write(comedi_device * dev,
+ }
+ 
+ static int aio_iiro_16_dio_insn_bits_read(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
+index 2f5f94050180..8c8e58f71ec6 100644
+--- a/drivers/staging/comedi/drivers/amplc_dio200.c
++++ b/drivers/staging/comedi/drivers/amplc_dio200.c
+@@ -201,7 +201,7 @@ to be enabled.  All channels will be sampled together (convert_src ==
+ TRIG_NOW).  The scan begins a short time after the hardware interrupt
+ occurs, subject to interrupt latencies (scan_begin_src == TRIG_EXT,
+ scan_begin_arg == 0).  The value read from the interrupt status register
+-is packed into a sampl_t value, one bit per requested channel, in the
++is packed into a short value, one bit per requested channel, in the
+ order they appear in the channel list.
+ */
+ 
+@@ -573,7 +573,7 @@ dio200_request_region(unsigned minor, unsigned long from, unsigned long extent)
+  */
+ static int
+ dio200_subdev_intr_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	dio200_subdev_intr *subpriv = s->private;
+ 
+@@ -732,7 +732,7 @@ static int dio200_handle_read_intr(comedi_device * dev, comedi_subdevice * s)
+ 			 */
+ 			if (triggered & subpriv->enabled_isns) {
+ 				/* Collect scan data. */
+-				sampl_t val;
++				short val;
+ 				unsigned int n, ch, len;
+ 
+ 				val = 0;
+@@ -1034,7 +1034,7 @@ static irqreturn_t dio200_interrupt(int irq, void *d PT_REGS_ARG)
+  */
+ static int
+ dio200_subdev_8254_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	dio200_subdev_8254 *subpriv = s->private;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -1049,7 +1049,7 @@ dio200_subdev_8254_read(comedi_device * dev, comedi_subdevice * s,
+  */
+ static int
+ dio200_subdev_8254_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	dio200_subdev_8254 *subpriv = s->private;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -1124,7 +1124,7 @@ dio200_set_clock_src(dio200_subdev_8254 * subpriv, unsigned int counter_number,
+  */
+ static int
+ dio200_get_clock_src(dio200_subdev_8254 * subpriv, unsigned int counter_number,
+-	lsampl_t * period_ns)
++	unsigned int * period_ns)
+ {
+ 	unsigned clock_src;
+ 
+@@ -1143,7 +1143,7 @@ dio200_get_clock_src(dio200_subdev_8254 * subpriv, unsigned int counter_number,
+  */
+ static int
+ dio200_subdev_8254_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	dio200_subdev_8254 *subpriv = s->private;
+ 	int ret;
+diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
+index 1ee3664e99b5..8d3fb69176ca 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc236.c
++++ b/drivers/staging/comedi/drivers/amplc_pc236.c
+@@ -189,7 +189,7 @@ static void pc236_intr_disable(comedi_device * dev);
+ static void pc236_intr_enable(comedi_device * dev);
+ static int pc236_intr_check(comedi_device * dev);
+ static int pc236_intr_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int pc236_intr_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+ static int pc236_intr_cmd(comedi_device * dev, comedi_subdevice * s);
+@@ -529,7 +529,7 @@ static int pc236_intr_check(comedi_device * dev)
+  * Copied from the comedi_parport driver.
+  */
+ static int pc236_intr_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[1] = 0;
+ 	return 2;
+diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
+index 868d35d82ee1..4c23b018ce5e 100644
+--- a/drivers/staging/comedi/drivers/amplc_pc263.c
++++ b/drivers/staging/comedi/drivers/amplc_pc263.c
+@@ -147,9 +147,9 @@ static comedi_driver driver_amplc_pc263 = {
+ static int pc263_request_region(unsigned minor, unsigned long from,
+ 	unsigned long extent);
+ static int pc263_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int pc263_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ /*
+  * This function looks for a PCI device matching the requested board name,
+@@ -388,7 +388,7 @@ static int pc263_request_region(unsigned minor, unsigned long from,
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+ static int pc263_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -413,7 +413,7 @@ static int pc263_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int pc263_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 1)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
+index b821a0bb3b53..b936ccf9bb4d 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci224.c
++++ b/drivers/staging/comedi/drivers/amplc_pci224.c
+@@ -404,8 +404,8 @@ typedef struct {
+ 	unsigned long iobase1;
+ 	unsigned long state;
+ 	spinlock_t ao_spinlock;
+-	lsampl_t *ao_readback;
+-	sampl_t *ao_scan_vals;
++	unsigned int *ao_readback;
++	short *ao_scan_vals;
+ 	unsigned char *ao_scan_order;
+ 	int intr_cpuid;
+ 	short intr_running;
+@@ -444,7 +444,7 @@ COMEDI_PCI_INITCLEANUP(driver_amplc_pci224, pci224_pci_table);
+  * Called from the 'insn_write' function to perform a single write.
+  */
+ static void
+-pci224_ao_set_data(comedi_device * dev, int chan, int range, lsampl_t data)
++pci224_ao_set_data(comedi_device * dev, int chan, int range, unsigned int data)
+ {
+ 	unsigned short mangled;
+ 
+@@ -478,7 +478,7 @@ pci224_ao_set_data(comedi_device * dev, int chan, int range, lsampl_t data)
+  */
+ static int
+ pci224_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan, range;
+@@ -505,7 +505,7 @@ pci224_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+  */
+ static int
+ pci224_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan;
+@@ -609,10 +609,10 @@ static void pci224_ao_handle_fifo(comedi_device * dev, comedi_subdevice * s)
+ 	unsigned int bytes_per_scan;
+ 
+ 	if (cmd->chanlist_len) {
+-		bytes_per_scan = cmd->chanlist_len * sizeof(sampl_t);
++		bytes_per_scan = cmd->chanlist_len * sizeof(short);
+ 	} else {
+ 		/* Shouldn't get here! */
+-		bytes_per_scan = sizeof(sampl_t);
++		bytes_per_scan = sizeof(short);
+ 	}
+ 	/* Determine number of scans available in buffer. */
+ 	num_scans = comedi_buf_read_n_available(s->async) / bytes_per_scan;
+@@ -1186,7 +1186,7 @@ pci224_ao_munge(comedi_device * dev, comedi_subdevice * s, void *data,
+ 	unsigned int num_bytes, unsigned int chan_index)
+ {
+ 	comedi_async *async = s->async;
+-	sampl_t *array = data;
++	short *array = data;
+ 	unsigned int length = num_bytes / sizeof(*array);
+ 	unsigned int offset;
+ 	unsigned int shift;
+diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
+index 39482742401e..4463e9803e08 100644
+--- a/drivers/staging/comedi/drivers/amplc_pci230.c
++++ b/drivers/staging/comedi/drivers/amplc_pci230.c
+@@ -524,7 +524,7 @@ struct pci230_private {
+ 	spinlock_t ao_stop_spinlock;	/* Spin lock for stopping AO command */
+ 	unsigned long state;	/* State flags */
+ 	unsigned long iobase1;	/* PCI230's I/O space 1 */
+-	lsampl_t ao_readback[2];	/* Used for AO readback */
++	unsigned int ao_readback[2];	/* Used for AO readback */
+ 	unsigned int ai_scan_count;	/* Number of analogue input scans
+ 					 * remaining.  */
+ 	unsigned int ai_scan_pos;	/* Current position within analogue
+@@ -616,11 +616,11 @@ static comedi_driver driver_amplc_pci230 = {
+ COMEDI_PCI_INITCLEANUP(driver_amplc_pci230, pci230_pci_table);
+ 
+ static int pci230_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int pci230_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int pci230_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static void pci230_ct_setup_ns_mode(comedi_device * dev, unsigned int ct,
+ 	unsigned int mode, uint64_t ns, unsigned int round);
+ static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round);
+@@ -640,10 +640,10 @@ static int pci230_ai_cancel(comedi_device * dev, comedi_subdevice * s);
+ static void pci230_ai_stop(comedi_device * dev, comedi_subdevice * s);
+ static void pci230_handle_ai(comedi_device * dev, comedi_subdevice * s);
+ 
+-static sampl_t pci230_ai_read(comedi_device * dev)
++static short pci230_ai_read(comedi_device * dev)
+ {
+ 	/* Read sample. */
+-	sampl_t data = (sampl_t) inw(dev->iobase + PCI230_ADCDATA);
++	short data = (short) inw(dev->iobase + PCI230_ADCDATA);
+ 
+ 	/* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower
+ 	 * four bits reserved for expansion). */
+@@ -659,7 +659,7 @@ static sampl_t pci230_ai_read(comedi_device * dev)
+ }
+ 
+ static inline unsigned short pci230_ao_mangle_datum(comedi_device * dev,
+-	sampl_t datum)
++	short datum)
+ {
+ 	/* If a bipolar range was specified, mangle it (straight binary->twos
+ 	 * complement). */
+@@ -674,7 +674,7 @@ static inline unsigned short pci230_ao_mangle_datum(comedi_device * dev,
+ 	return (unsigned short)datum;
+ }
+ 
+-static inline void pci230_ao_write_nofifo(comedi_device * dev, sampl_t datum,
++static inline void pci230_ao_write_nofifo(comedi_device * dev, short datum,
+ 	unsigned int chan)
+ {
+ 	/* Store unmangled datum to be read back later. */
+@@ -685,7 +685,7 @@ static inline void pci230_ao_write_nofifo(comedi_device * dev, sampl_t datum,
+ 			? PCI230_DACOUT1 : PCI230_DACOUT2));
+ }
+ 
+-static inline void pci230_ao_write_fifo(comedi_device * dev, sampl_t datum,
++static inline void pci230_ao_write_fifo(comedi_device * dev, short datum,
+ 	unsigned int chan)
+ {
+ 	/* Store unmangled datum to be read back later. */
+@@ -1059,7 +1059,7 @@ static inline void put_all_resources(comedi_device * dev, unsigned char owner)
+  *  COMEDI_SUBD_AI instruction;
+  */
+ static int pci230_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int n, i;
+ 	unsigned int chan, range, aref;
+@@ -1164,7 +1164,7 @@ static int pci230_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+  *  COMEDI_SUBD_AO instructions;
+  */
+ static int pci230_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan, range;
+@@ -1192,7 +1192,7 @@ static int pci230_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+ static int pci230_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -2624,7 +2624,7 @@ static irqreturn_t pci230_interrupt(int irq, void *d PT_REGS_ARG)
+ 
+ static void pci230_handle_ao_nofifo(comedi_device * dev, comedi_subdevice * s)
+ {
+-	sampl_t data;
++	short data;
+ 	int i, ret;
+ 	comedi_async *async = s->async;
+ 	comedi_cmd *cmd = &async->cmd;
+@@ -2675,7 +2675,7 @@ static int pci230_handle_ao_fifo(comedi_device * dev, comedi_subdevice * s)
+ 	dacstat = inw(dev->iobase + PCI230_DACCON);
+ 
+ 	/* Determine number of scans available in buffer. */
+-	bytes_per_scan = cmd->chanlist_len * sizeof(sampl_t);
++	bytes_per_scan = cmd->chanlist_len * sizeof(short);
+ 	num_scans = comedi_buf_read_n_available(async) / bytes_per_scan;
+ 	if (!devpriv->ao_continuous) {
+ 		/* Fixed number of scans. */
+@@ -2722,7 +2722,7 @@ static int pci230_handle_ao_fifo(comedi_device * dev, comedi_subdevice * s)
+ 		/* Process scans. */
+ 		for (n = 0; n < num_scans; n++) {
+ 			for (i = 0; i < cmd->chanlist_len; i++) {
+-				sampl_t datum;
++				short datum;
+ 
+ 				comedi_buf_get(async, &datum);
+ 				pci230_ao_write_fifo(dev, datum,
+diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c
+index 1bf1375cb2c7..5837770ac5b2 100644
+--- a/drivers/staging/comedi/drivers/c6xdigio.c
++++ b/drivers/staging/comedi/drivers/c6xdigio.c
+@@ -339,14 +339,14 @@ static void C6X_encResetAll(unsigned long baseAddr)
+ }
+ 
+ static int c6xdigio_pwmo_insn_read(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	printk("c6xdigio_pwmo_insn_read %x\n", insn->n);
+ 	return insn->n;
+ }
+ 
+ static int c6xdigio_pwmo_insn_write(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -362,7 +362,7 @@ static int c6xdigio_pwmo_insn_write(comedi_device * dev,
+ //static int c6xdigio_ei_init_insn_read(comedi_device *dev,
+ //                                 comedi_subdevice *s,
+ //                                 comedi_insn *insn,
+-//                                 lsampl_t *data)
++//                                 unsigned int *data)
+ //{
+ //  printk("c6xdigio_ei_init_insn_read %x\n", insn->n);
+ //  return insn->n;
+@@ -371,7 +371,7 @@ static int c6xdigio_pwmo_insn_write(comedi_device * dev,
+ //static int c6xdigio_ei_init_insn_write(comedi_device *dev,
+ //                                 comedi_subdevice *s,
+ //                                 comedi_insn *insn,
+-//                                 lsampl_t *data)
++//                                 unsigned int *data)
+ //{
+ //  int i;
+ //  int chan = CR_CHAN(insn->chanspec);
+@@ -382,7 +382,7 @@ static int c6xdigio_pwmo_insn_write(comedi_device * dev,
+ //}
+ 
+ static int c6xdigio_ei_insn_read(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	//  printk("c6xdigio_ei__insn_read %x\n", insn->n);
+ 	int n;
+diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
+index d6cc0a1d0d95..827954971c1a 100644
+--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
++++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
+@@ -83,7 +83,7 @@ static const das16cs_board das16cs_boards[] = {
+ typedef struct {
+ 	struct pcmcia_device *link;
+ 
+-	lsampl_t ao_readback[2];
++	unsigned int ao_readback[2];
+ 	unsigned short status1;
+ 	unsigned short status2;
+ } das16cs_private;
+@@ -110,22 +110,22 @@ static const comedi_lrange das16cs_ai_range = { 4, {
+ 
+ static irqreturn_t das16cs_interrupt(int irq, void *d PT_REGS_ARG);
+ static int das16cs_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int das16cs_ai_cmd(comedi_device * dev, comedi_subdevice * s);
+ static int das16cs_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+ static int das16cs_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int das16cs_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int das16cs_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int das16cs_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int das16cs_timer_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int das16cs_timer_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ static int get_prodid(comedi_device * dev, struct pcmcia_device *link)
+ {
+@@ -287,7 +287,7 @@ static irqreturn_t das16cs_interrupt(int irq, void *d PT_REGS_ARG)
+  * mode.
+  */
+ static int das16cs_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int to;
+@@ -490,7 +490,7 @@ static int das16cs_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int das16cs_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -536,7 +536,7 @@ static int das16cs_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+ static int das16cs_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -553,7 +553,7 @@ static int das16cs_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+ static int das16cs_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -573,7 +573,7 @@ static int das16cs_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int das16cs_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	int bits;
+@@ -611,13 +611,13 @@ static int das16cs_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int das16cs_timer_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	return -EINVAL;
+ }
+ 
+ static int das16cs_timer_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	return -EINVAL;
+ }
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
+index 63c8a802f599..c98fb6de3d41 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas.c
+@@ -415,8 +415,8 @@ typedef struct {
+ 	volatile unsigned int adc_fifo_bits;	// bits to write to interupt/adcfifo register
+ 	volatile unsigned int s5933_intcsr_bits;	// bits to write to amcc s5933 interrupt control/status register
+ 	volatile unsigned int ao_control_bits;	// bits to write to ao control and status register
+-	sampl_t ai_buffer[AI_BUFFER_SIZE];
+-	sampl_t ao_buffer[AO_BUFFER_SIZE];
++	short ai_buffer[AI_BUFFER_SIZE];
++	short ao_buffer[AO_BUFFER_SIZE];
+ 	// divisors of master clock for analog output pacing
+ 	unsigned int ao_divisor1;
+ 	unsigned int ao_divisor2;
+@@ -450,15 +450,15 @@ static comedi_driver driver_cb_pcidas = {
+ };
+ 
+ static int cb_pcidas_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int ai_config_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int cb_pcidas_ao_nofifo_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int cb_pcidas_ao_fifo_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int cb_pcidas_ao_readback_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int cb_pcidas_ai_cmd(comedi_device * dev, comedi_subdevice * s);
+ static int cb_pcidas_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+@@ -474,22 +474,22 @@ static int cb_pcidas_ao_cancel(comedi_device * dev, comedi_subdevice * s);
+ static void cb_pcidas_load_counters(comedi_device * dev, unsigned int *ns,
+ 	int round_flags);
+ static int eeprom_read_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int caldac_read_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int caldac_write_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int trimpot_read_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int cb_pcidas_trimpot_write(comedi_device * dev, unsigned int channel,
+-	lsampl_t value);
++	unsigned int value);
+ static int trimpot_write_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int dac08_read_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
+-static int dac08_write(comedi_device * dev, lsampl_t value);
++	comedi_insn * insn, unsigned int * data);
++static int dac08_write(comedi_device * dev, unsigned int value);
+ static int dac08_write_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int caldac_8800_write(comedi_device * dev, unsigned int address,
+ 	uint8_t value);
+ static int trimpot_7376_write(comedi_device * dev, uint8_t value);
+@@ -753,7 +753,7 @@ static int cb_pcidas_detach(comedi_device * dev)
+  * mode.
+  */
+ static int cb_pcidas_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i;
+ 	unsigned int bits;
+@@ -804,10 +804,10 @@ static int cb_pcidas_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int ai_config_calibration_source(comedi_device * dev, lsampl_t * data)
++static int ai_config_calibration_source(comedi_device * dev, unsigned int * data)
+ {
+ 	static const int num_calibration_sources = 8;
+-	lsampl_t source = data[1];
++	unsigned int source = data[1];
+ 
+ 	if (source >= num_calibration_sources) {
+ 		printk("invalid calibration source: %i\n", source);
+@@ -820,7 +820,7 @@ static int ai_config_calibration_source(comedi_device * dev, lsampl_t * data)
+ }
+ 
+ static int ai_config_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int id = data[0];
+ 
+@@ -837,7 +837,7 @@ static int ai_config_insn(comedi_device * dev, comedi_subdevice * s,
+ 
+ // analog output insn for pcidas-1000 and 1200 series
+ static int cb_pcidas_ao_nofifo_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel;
+ 	unsigned long flags;
+@@ -862,7 +862,7 @@ static int cb_pcidas_ao_nofifo_winsn(comedi_device * dev, comedi_subdevice * s,
+ 
+ // analog output insn for pcidas-1602 series
+ static int cb_pcidas_ao_fifo_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel;
+ 	unsigned long flags;
+@@ -893,7 +893,7 @@ static int cb_pcidas_ao_fifo_winsn(comedi_device * dev, comedi_subdevice * s,
+ // analog output readback insn
+ // XXX loses track of analog output value back after an analog ouput command is executed
+ static int cb_pcidas_ao_readback_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)];
+ 
+@@ -901,7 +901,7 @@ static int cb_pcidas_ao_readback_insn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int eeprom_read_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	uint8_t nvram_data;
+ 	int retval;
+@@ -916,7 +916,7 @@ static int eeprom_read_insn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int caldac_write_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	const unsigned int channel = CR_CHAN(insn->chanspec);
+ 
+@@ -924,7 +924,7 @@ static int caldac_write_insn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int caldac_read_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->caldac_value[CR_CHAN(insn->chanspec)];
+ 
+@@ -932,7 +932,7 @@ static int caldac_read_insn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ /* 1602/16 pregain offset */
+-static int dac08_write(comedi_device * dev, lsampl_t value)
++static int dac08_write(comedi_device * dev, unsigned int value)
+ {
+ 	if (devpriv->dac08_value == value)
+ 		return 1;
+@@ -953,13 +953,13 @@ static int dac08_write(comedi_device * dev, lsampl_t value)
+ }
+ 
+ static int dac08_write_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	return dac08_write(dev, data[0]);
+ }
+ 
+ static int dac08_read_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->dac08_value;
+ 
+@@ -967,7 +967,7 @@ static int dac08_read_insn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int cb_pcidas_trimpot_write(comedi_device * dev,
+-	unsigned int channel, lsampl_t value)
++	unsigned int channel, unsigned int value)
+ {
+ 	if (devpriv->trimpot_value[channel] == value)
+ 		return 1;
+@@ -990,7 +990,7 @@ static int cb_pcidas_trimpot_write(comedi_device * dev,
+ }
+ 
+ static int trimpot_write_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int channel = CR_CHAN(insn->chanspec);
+ 
+@@ -998,7 +998,7 @@ static int trimpot_write_insn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int trimpot_read_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int channel = CR_CHAN(insn->chanspec);
+ 
+@@ -1441,8 +1441,8 @@ static int cb_pcidas_ao_inttrig(comedi_device * dev, comedi_subdevice * s,
+ 		num_points = devpriv->ao_count;
+ 
+ 	num_bytes = cfc_read_array_from_buffer(s, devpriv->ao_buffer,
+-		num_points * sizeof(sampl_t));
+-	num_points = num_bytes / sizeof(sampl_t);
++		num_points * sizeof(short));
++	num_points = num_bytes / sizeof(short);
+ 
+ 	if (cmd->stop_src == TRIG_COUNT) {
+ 		devpriv->ao_count -= num_points;
+@@ -1530,7 +1530,7 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d PT_REGS_ARG)
+ 		insw(devpriv->adc_fifo + ADCDATA, devpriv->ai_buffer,
+ 			num_samples);
+ 		cfc_write_array_to_buffer(s, devpriv->ai_buffer,
+-			num_samples * sizeof(sampl_t));
++			num_samples * sizeof(short));
+ 		devpriv->count -= num_samples;
+ 		if (async->cmd.stop_src == TRIG_COUNT && devpriv->count == 0) {
+ 			async->events |= COMEDI_CB_EOA;
+@@ -1623,8 +1623,8 @@ static void handle_ao_interrupt(comedi_device * dev, unsigned int status)
+ 			num_points = devpriv->ao_count;
+ 		num_bytes =
+ 			cfc_read_array_from_buffer(s, devpriv->ao_buffer,
+-			num_points * sizeof(sampl_t));
+-		num_points = num_bytes / sizeof(sampl_t);
++			num_points * sizeof(short));
++		num_points = num_bytes / sizeof(short);
+ 
+ 		if (async->cmd.stop_src == TRIG_COUNT) {
+ 			devpriv->ao_count -= num_points;
+diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
+index 9f056aa44f5d..4b1afce04d92 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
++++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
+@@ -1108,7 +1108,7 @@ typedef struct {
+ 	volatile short ai_cmd_running;
+ 	unsigned int ai_fifo_segment_length;
+ 	struct ext_clock_info ext_clock;
+-	sampl_t ao_bounce_buffer[DAC_FIFO_SIZE];
++	short ao_bounce_buffer[DAC_FIFO_SIZE];
+ } pcidas64_private;
+ 
+ /* inline function that makes it easier to
+@@ -1135,13 +1135,13 @@ static comedi_driver driver_cb_pcidas = {
+ };
+ 
+ static int ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int ai_config_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int ao_readback_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int ai_cmd(comedi_device * dev, comedi_subdevice * s);
+ static int ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+@@ -1156,25 +1156,25 @@ static int ao_cancel(comedi_device * dev, comedi_subdevice * s);
+ static int dio_callback(int dir, int port, int data, unsigned long arg);
+ static int dio_callback_4020(int dir, int port, int data, unsigned long arg);
+ static int di_rbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int do_wbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int dio_60xx_config_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int dio_60xx_wbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int calib_read_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int calib_write_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int ad8402_read_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static void ad8402_write(comedi_device * dev, unsigned int channel,
+ 	unsigned int value);
+ static int ad8402_write_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int eeprom_read_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static void check_adc_timing(comedi_device * dev, comedi_cmd * cmd);
+ static unsigned int get_divisor(unsigned int ns, unsigned int flags);
+ static void i2c_write(comedi_device * dev, unsigned int address,
+@@ -1882,7 +1882,7 @@ static int detach(comedi_device * dev)
+ }
+ 
+ static int ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bits = 0, n, i;
+ 	unsigned int channel, range, aref;
+@@ -2018,9 +2018,9 @@ static int ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int ai_config_calibration_source(comedi_device * dev, lsampl_t * data)
++static int ai_config_calibration_source(comedi_device * dev, unsigned int * data)
+ {
+-	lsampl_t source = data[1];
++	unsigned int source = data[1];
+ 	int num_calibration_sources;
+ 
+ 	if (board(dev)->layout == LAYOUT_60XX)
+@@ -2038,7 +2038,7 @@ static int ai_config_calibration_source(comedi_device * dev, lsampl_t * data)
+ 	return 2;
+ }
+ 
+-static int ai_config_block_size(comedi_device * dev, lsampl_t * data)
++static int ai_config_block_size(comedi_device * dev, unsigned int * data)
+ {
+ 	int fifo_size;
+ 	const hw_fifo_info_t *const fifo = board(dev)->ai_fifo;
+@@ -2065,7 +2065,7 @@ static int ai_config_block_size(comedi_device * dev, lsampl_t * data)
+ 	return 2;
+ }
+ 
+-static int ai_config_master_clock_4020(comedi_device * dev, lsampl_t * data)
++static int ai_config_master_clock_4020(comedi_device * dev, unsigned int * data)
+ {
+ 	unsigned int divisor = data[4];
+ 	int retval = 0;
+@@ -2091,7 +2091,7 @@ static int ai_config_master_clock_4020(comedi_device * dev, lsampl_t * data)
+ }
+ 
+ // XXX could add support for 60xx series
+-static int ai_config_master_clock(comedi_device * dev, lsampl_t * data)
++static int ai_config_master_clock(comedi_device * dev, unsigned int * data)
+ {
+ 
+ 	switch (board(dev)->layout) {
+@@ -2107,7 +2107,7 @@ static int ai_config_master_clock(comedi_device * dev, lsampl_t * data)
+ }
+ 
+ static int ai_config_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int id = data[0];
+ 
+@@ -3195,7 +3195,7 @@ static int ai_cancel(comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ static int ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	int range = CR_RANGE(insn->chanspec);
+@@ -3225,7 +3225,7 @@ static int ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int ao_readback_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = priv(dev)->ao_value[CR_CHAN(insn->chanspec)];
+ 
+@@ -3606,9 +3606,9 @@ static int dio_callback_4020(int dir, int port, int data, unsigned long iobase)
+ }
+ 
+ static int di_rbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+-	lsampl_t bits;
++	unsigned int bits;
+ 
+ 	bits = readb(priv(dev)->dio_counter_iobase + DI_REG);
+ 	bits &= 0xf;
+@@ -3619,7 +3619,7 @@ static int di_rbits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int do_wbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] &= 0xf;
+ 	// zero bits we are going to change
+@@ -3635,7 +3635,7 @@ static int do_wbits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int dio_60xx_config_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int mask;
+ 
+@@ -3662,7 +3662,7 @@ static int dio_60xx_config_insn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int dio_60xx_wbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+ 		s->state &= ~data[0];
+@@ -3695,7 +3695,7 @@ static void caldac_write(comedi_device * dev, unsigned int channel,
+ }
+ 
+ static int calib_write_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel = CR_CHAN(insn->chanspec);
+ 
+@@ -3710,7 +3710,7 @@ static int calib_write_insn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int calib_read_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int channel = CR_CHAN(insn->chanspec);
+ 
+@@ -3751,7 +3751,7 @@ static void ad8402_write(comedi_device * dev, unsigned int channel,
+ 
+ /* for pci-das6402/16, channel 0 is analog input gain and channel 1 is offset */
+ static int ad8402_write_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel = CR_CHAN(insn->chanspec);
+ 
+@@ -3768,7 +3768,7 @@ static int ad8402_write_insn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int ad8402_read_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int channel = CR_CHAN(insn->chanspec);
+ 
+@@ -3840,7 +3840,7 @@ static uint16_t read_eeprom(comedi_device * dev, uint8_t address)
+ }
+ 
+ static int eeprom_read_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = read_eeprom(dev, CR_CHAN(insn->chanspec));
+ 
+diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
+index c5c156b4cade..f245eb1c1631 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidda.c
++++ b/drivers/staging/comedi/drivers/cb_pcidda.c
+@@ -234,9 +234,9 @@ typedef struct {
+ 
+ static int cb_pcidda_attach(comedi_device * dev, comedi_devconfig * it);
+ static int cb_pcidda_detach(comedi_device * dev);
+-//static int cb_pcidda_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
++//static int cb_pcidda_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data);
+ static int cb_pcidda_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ //static int cb_pcidda_ai_cmd(comedi_device *dev,comedi_subdevice *s);
+ //static int cb_pcidda_ai_cmdtest(comedi_device *dev,comedi_subdevice *s, comedi_cmd *cmd);
+ //static int cb_pcidda_ns_to_timer(unsigned int *ns,int round);
+@@ -599,7 +599,7 @@ static int cb_pcidda_ns_to_timer(unsigned int *ns, int round)
+ #endif
+ 
+ static int cb_pcidda_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int command;
+ 	unsigned int channel, range;
+diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c
+index d6d8bf1c6f22..e5bc34746e38 100644
+--- a/drivers/staging/comedi/drivers/cb_pcidio.c
++++ b/drivers/staging/comedi/drivers/cb_pcidio.c
+@@ -110,7 +110,7 @@ typedef struct {
+ 	struct pci_dev *pci_dev;
+ 
+ 	/* used for DO readback, curently unused */
+-	lsampl_t do_readback[4];	/* up to 4 lsampl_t suffice to hold 96 bits for PCI-DIO96 */
++	unsigned int do_readback[4];	/* up to 4 unsigned int suffice to hold 96 bits for PCI-DIO96 */
+ 
+ 	unsigned long dio_reg_base;	// address of port A of the first 8255 chip on board
+ } pcidio_private;
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
+index b95b3b157424..1223635a4422 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
+@@ -153,7 +153,7 @@ typedef struct {
+ 	unsigned long BADR4;
+ 
+ 	/* Used for AO readback */
+-	lsampl_t ao_readback[2];
++	unsigned int ao_readback[2];
+ 
+ 	// Used for DIO
+ 	unsigned short int port_a;	// copy of BADR4+0
+@@ -185,11 +185,11 @@ static comedi_driver driver_cb_pcimdas = {
+ };
+ 
+ static int cb_pcimdas_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int cb_pcimdas_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int cb_pcimdas_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ /*
+  * Attach is called by the Comedi core to configure the driver
+@@ -373,7 +373,7 @@ static int cb_pcimdas_detach(comedi_device * dev)
+  * mode.
+  */
+ static int cb_pcimdas_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i;
+ 	unsigned int d;
+@@ -438,7 +438,7 @@ static int cb_pcimdas_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int cb_pcimdas_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -466,7 +466,7 @@ static int cb_pcimdas_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+ static int cb_pcimdas_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
+index 2c7fd68c0d20..ac21056aa787 100644
+--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
++++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
+@@ -165,7 +165,7 @@ typedef struct {
+ 
+ #define MAX_AO_READBACK_CHANNELS 6
+ 	/* Used for AO readback */
+-	lsampl_t ao_readback[MAX_AO_READBACK_CHANNELS];
++	unsigned int ao_readback[MAX_AO_READBACK_CHANNELS];
+ 
+ } private;
+ 
+@@ -198,18 +198,18 @@ MODULE_LICENSE("GPL");
+ COMEDI_PCI_INITCLEANUP_NOMODULE(cb_pcimdda_driver, pci_table);
+ 
+ static int ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ /*---------------------------------------------------------------------------
+   HELPER FUNCTION DECLARATIONS
+ -----------------------------------------------------------------------------*/
+ 
+ /* returns a maxdata value for a given n_bits */
+-static inline lsampl_t figure_out_maxdata(int bits)
++static inline unsigned int figure_out_maxdata(int bits)
+ {
+-	return (((lsampl_t) 1 << bits) - 1);
++	return (((unsigned int) 1 << bits) - 1);
+ }
+ 
+ /*
+@@ -353,7 +353,7 @@ static int detach(comedi_device * dev)
+ }
+ 
+ static int ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -392,7 +392,7 @@ static int ao_winsn(comedi_device * dev, comedi_subdevice * s,
+    applications, I would imagine.
+ */
+ static int ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -400,7 +400,7 @@ static int ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 	for (i = 0; i < insn->n; i++) {
+ 		inw(devpriv->registers + chan * 2);
+ 		/* should I set data[i] to the result of the actual read on the register
+-		   or the cached lsampl_t in devpriv->ao_readback[]? */
++		   or the cached unsigned int in devpriv->ao_readback[]? */
+ 		data[i] = devpriv->ao_readback[chan];
+ 	}
+ 
+diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c
+index 09e288904f9e..7868ddd6fe25 100644
+--- a/drivers/staging/comedi/drivers/comedi_bond.c
++++ b/drivers/staging/comedi/drivers/comedi_bond.c
+@@ -214,9 +214,9 @@ static comedi_driver driver_bonding = {
+ };
+ 
+ static int bonding_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
+-				 comedi_insn *insn, lsampl_t *data);
++				 comedi_insn *insn, unsigned int *data);
+ static int bonding_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
+-				   comedi_insn *insn, lsampl_t *data);
++				   comedi_insn *insn, unsigned int *data);
+ 
+ /*
+  * Attach is called by the Comedi core to configure the driver
+@@ -294,9 +294,9 @@ static int bonding_detach(comedi_device *dev)
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+ static int bonding_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
+-				 comedi_insn *insn, lsampl_t *data)
++				 comedi_insn *insn, unsigned int *data)
+ {
+-#define LSAMPL_BITS (sizeof(lsampl_t)*8)
++#define LSAMPL_BITS (sizeof(unsigned int)*8)
+ 	unsigned nchans = LSAMPL_BITS, num_done = 0, i;
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -312,12 +312,12 @@ static int bonding_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
+ 		   to this subdevice.. need to shift them to zero position of
+ 		   course. */
+ 		/* Bits corresponding to this subdev. */
+-		lsampl_t subdevMask = ((1 << bdev->nchans) - 1);
+-		lsampl_t writeMask, dataBits;
++		unsigned int subdevMask = ((1 << bdev->nchans) - 1);
++		unsigned int writeMask, dataBits;
+ 
+ 		/* Argh, we have >= LSAMPL_BITS chans.. take all bits */
+ 		if (bdev->nchans >= LSAMPL_BITS)
+-			subdevMask = (lsampl_t) (-1);
++			subdevMask = (unsigned int) (-1);
+ 
+ 		writeMask = (data[0] >> num_done) & subdevMask;
+ 		dataBits = (data[1] >> num_done) & subdevMask;
+@@ -341,7 +341,7 @@ static int bonding_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ static int bonding_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
+-				   comedi_insn *insn, lsampl_t *data)
++				   comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec), ret, io_bits = s->io_bits;
+ 	unsigned int io;
+diff --git a/drivers/staging/comedi/drivers/comedi_fc.h b/drivers/staging/comedi/drivers/comedi_fc.h
+index 6952fe20f273..bbb70d66eee9 100644
+--- a/drivers/staging/comedi/drivers/comedi_fc.h
++++ b/drivers/staging/comedi/drivers/comedi_fc.h
+@@ -35,13 +35,13 @@ extern unsigned int cfc_write_array_to_buffer(comedi_subdevice *subd,
+ 					      unsigned int num_bytes);
+ 
+ static inline unsigned int cfc_write_to_buffer(comedi_subdevice *subd,
+-					       sampl_t data)
++					       short data)
+ {
+ 	return cfc_write_array_to_buffer(subd, &data, sizeof(data));
+ };
+ 
+ static inline unsigned int cfc_write_long_to_buffer(comedi_subdevice *subd,
+-						    lsampl_t data)
++						    unsigned int data)
+ {
+ 	return cfc_write_array_to_buffer(subd, &data, sizeof(data));
+ };
+diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c
+index ba838fffa29e..87c4c20694e0 100644
+--- a/drivers/staging/comedi/drivers/comedi_parport.c
++++ b/drivers/staging/comedi/drivers/comedi_parport.c
+@@ -109,7 +109,7 @@ struct parport_private {
+ #define devpriv ((struct parport_private *)(dev->private))
+ 
+ static int parport_insn_a(comedi_device *dev, comedi_subdevice *s,
+-			  comedi_insn *insn, lsampl_t *data)
++			  comedi_insn *insn, unsigned int *data)
+ {
+ 	if (data[0]) {
+ 		devpriv->a_data &= ~data[0];
+@@ -124,7 +124,7 @@ static int parport_insn_a(comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ static int parport_insn_config_a(comedi_device *dev, comedi_subdevice *s,
+-				 comedi_insn *insn, lsampl_t *data)
++				 comedi_insn *insn, unsigned int *data)
+ {
+ 	if (data[0]) {
+ 		s->io_bits = 0xff;
+@@ -139,7 +139,7 @@ static int parport_insn_config_a(comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ static int parport_insn_b(comedi_device *dev, comedi_subdevice *s,
+-			  comedi_insn *insn, lsampl_t *data)
++			  comedi_insn *insn, unsigned int *data)
+ {
+ 	if (data[0]) {
+ 		/* should writes be ignored? */
+@@ -152,7 +152,7 @@ static int parport_insn_b(comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ static int parport_insn_c(comedi_device *dev, comedi_subdevice *s,
+-			  comedi_insn *insn, lsampl_t *data)
++			  comedi_insn *insn, unsigned int *data)
+ {
+ 	data[0] &= 0x0f;
+ 	if (data[0]) {
+@@ -168,7 +168,7 @@ static int parport_insn_c(comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ static int parport_intr_insn(comedi_device *dev, comedi_subdevice *s,
+-			     comedi_insn *insn, lsampl_t *data)
++			     comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n < 1)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/comedi_rt_timer.c b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+index 878160eae080..ec081c4180c6 100644
+--- a/drivers/staging/comedi/drivers/comedi_rt_timer.c
++++ b/drivers/staging/comedi/drivers/comedi_rt_timer.c
+@@ -211,7 +211,7 @@ static int timer_data_read(comedi_device * dev, comedi_cmd * cmd,
+ {
+ 	comedi_subdevice *s = dev->read_subdev;
+ 	int ret;
+-	lsampl_t data;
++	unsigned int data;
+ 
+ 	ret = comedi_data_read(devpriv->device, devpriv->subd,
+ 		CR_CHAN(cmd->chanlist[index]),
+@@ -236,8 +236,8 @@ static int timer_data_write(comedi_device * dev, comedi_cmd * cmd,
+ {
+ 	comedi_subdevice *s = dev->write_subdev;
+ 	unsigned int num_bytes;
+-	sampl_t data;
+-	lsampl_t long_data;
++	short data;
++	unsigned int long_data;
+ 	int ret;
+ 
+ 	if (s->flags & SDF_LSAMPL) {
+@@ -271,7 +271,7 @@ static int timer_dio_read(comedi_device * dev, comedi_cmd * cmd,
+ {
+ 	comedi_subdevice *s = dev->read_subdev;
+ 	int ret;
+-	lsampl_t data;
++	unsigned int data;
+ 
+ 	ret = comedi_dio_bitfield(devpriv->device, devpriv->subd, 0, &data);
+ 	if (ret < 0) {
+@@ -397,7 +397,7 @@ static void timer_task_func(comedi_rt_task_context_t d)
+ }
+ 
+ static int timer_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	comedi_insn xinsn = *insn;
+ 
+diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c
+index 4b4c37d07482..f65ee2b52042 100644
+--- a/drivers/staging/comedi/drivers/comedi_test.c
++++ b/drivers/staging/comedi/drivers/comedi_test.c
+@@ -89,7 +89,7 @@ struct waveform_private {
+ 	unsigned int scan_period;	/* scan period in usec */
+ 	unsigned int convert_period;	/* conversion period in usec */
+ 	unsigned timer_running:1;
+-	lsampl_t ao_loopbacks[N_CHANS];
++	unsigned int ao_loopbacks[N_CHANS];
+ };
+ #define devpriv ((struct waveform_private *)dev->private)
+ 
+@@ -112,16 +112,16 @@ static int waveform_ai_cmdtest(comedi_device *dev, comedi_subdevice *s,
+ static int waveform_ai_cmd(comedi_device *dev, comedi_subdevice *s);
+ static int waveform_ai_cancel(comedi_device *dev, comedi_subdevice *s);
+ static int waveform_ai_insn_read(comedi_device *dev, comedi_subdevice *s,
+-				 comedi_insn *insn, lsampl_t *data);
++				 comedi_insn *insn, unsigned int *data);
+ static int waveform_ao_insn_write(comedi_device *dev, comedi_subdevice *s,
+-				  comedi_insn *insn, lsampl_t *data);
+-static sampl_t fake_sawtooth(comedi_device *dev, unsigned int range,
++				  comedi_insn *insn, unsigned int *data);
++static short fake_sawtooth(comedi_device *dev, unsigned int range,
+ 			     unsigned long current_time);
+-static sampl_t fake_squarewave(comedi_device *dev, unsigned int range,
++static short fake_squarewave(comedi_device *dev, unsigned int range,
+ 			       unsigned long current_time);
+-static sampl_t fake_flatline(comedi_device *dev, unsigned int range,
++static short fake_flatline(comedi_device *dev, unsigned int range,
+ 			     unsigned long current_time);
+-static sampl_t fake_waveform(comedi_device *dev, unsigned int channel,
++static short fake_waveform(comedi_device *dev, unsigned int channel,
+ 			     unsigned int range, unsigned long current_time);
+ 
+ /* 1000 nanosec in a microsec */
+@@ -436,7 +436,7 @@ static int waveform_ai_cancel(comedi_device *dev, comedi_subdevice *s)
+ 	return 0;
+ }
+ 
+-static sampl_t fake_sawtooth(comedi_device *dev, unsigned int range_index,
++static short fake_sawtooth(comedi_device *dev, unsigned int range_index,
+ 			     unsigned long current_time)
+ {
+ 	comedi_subdevice *s = dev->read_subdev;
+@@ -457,7 +457,7 @@ static sampl_t fake_sawtooth(comedi_device *dev, unsigned int range_index,
+ 
+ 	return offset + value;
+ }
+-static sampl_t fake_squarewave(comedi_device *dev, unsigned int range_index,
++static short fake_squarewave(comedi_device *dev, unsigned int range_index,
+ 			       unsigned long current_time)
+ {
+ 	comedi_subdevice *s = dev->read_subdev;
+@@ -476,14 +476,14 @@ static sampl_t fake_squarewave(comedi_device *dev, unsigned int range_index,
+ 	return offset + value;
+ }
+ 
+-static sampl_t fake_flatline(comedi_device *dev, unsigned int range_index,
++static short fake_flatline(comedi_device *dev, unsigned int range_index,
+ 			     unsigned long current_time)
+ {
+ 	return dev->read_subdev->maxdata / 2;
+ }
+ 
+ /* generates a different waveform depending on what channel is read */
+-static sampl_t fake_waveform(comedi_device *dev, unsigned int channel,
++static short fake_waveform(comedi_device *dev, unsigned int channel,
+ 			     unsigned int range, unsigned long current_time)
+ {
+ 	enum {
+@@ -505,7 +505,7 @@ static sampl_t fake_waveform(comedi_device *dev, unsigned int channel,
+ }
+ 
+ static int waveform_ai_insn_read(comedi_device *dev, comedi_subdevice *s,
+-				 comedi_insn *insn, lsampl_t *data)
++				 comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, chan = CR_CHAN(insn->chanspec);
+ 
+@@ -516,7 +516,7 @@ static int waveform_ai_insn_read(comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ static int waveform_ao_insn_write(comedi_device *dev, comedi_subdevice *s,
+-				  comedi_insn *insn, lsampl_t *data)
++				  comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, chan = CR_CHAN(insn->chanspec);
+ 
+diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
+index fa89ce021b5d..3049eb26674b 100644
+--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
++++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
+@@ -86,9 +86,9 @@ static comedi_driver driver_contec = {
+ 
+ /* Classic digital IO */
+ static int contec_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int contec_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ #if 0
+ static int contec_cmdtest(comedi_device * dev, comedi_subdevice * s,
+@@ -193,7 +193,7 @@ static int contec_ns_to_timer(unsigned int *ns, int round)
+ #endif
+ 
+ static int contec_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	printk("contec_do_insn_bits called\n");
+@@ -213,7 +213,7 @@ static int contec_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int contec_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	rt_printk("contec_di_insn_bits called\n");
+diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
+index 04c490fd459f..86cab4295d9e 100644
+--- a/drivers/staging/comedi/drivers/daqboard2000.c
++++ b/drivers/staging/comedi/drivers/daqboard2000.c
+@@ -333,7 +333,7 @@ typedef struct {
+ 	void *daq;
+ 	void *plx;
+ 	int got_regions;
+-	lsampl_t ao_readback[2];
++	unsigned int ao_readback[2];
+ } daqboard2000_private;
+ 
+ #define devpriv ((daqboard2000_private*)dev->private)
+@@ -394,7 +394,7 @@ static void setup_sampling(comedi_device * dev, int chan, int gain)
+ }
+ 
+ static int daqboard2000_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	daqboard2000_hw *fpga = devpriv->daq;
+@@ -451,7 +451,7 @@ static int daqboard2000_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int daqboard2000_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -464,7 +464,7 @@ static int daqboard2000_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int daqboard2000_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
+index 30c2c1292db2..8d4903dc03d6 100644
+--- a/drivers/staging/comedi/drivers/das08.c
++++ b/drivers/staging/comedi/drivers/das08.c
+@@ -155,19 +155,19 @@ driver.
+ /* gainlist same as _pgx_ below */
+ 
+ static int das08_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int das08_di_rbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int das08_do_wbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int das08jr_di_rbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int das08jr_do_wbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int das08jr_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int das08ao_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static void i8254_set_mode_low(unsigned int base, int channel,
+ 	unsigned int mode);
+ 
+@@ -513,7 +513,7 @@ MODULE_DEVICE_TABLE(pci, das08_pci_table);
+ #define TIMEOUT 100000
+ 
+ static int das08_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+ 	int chan;
+@@ -580,7 +580,7 @@ static int das08_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int das08_di_rbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = 0;
+ 	data[1] = DAS08_IP(inb(dev->iobase + DAS08_STATUS));
+@@ -589,7 +589,7 @@ static int das08_di_rbits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int das08_do_wbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int wbits;
+ 
+@@ -612,7 +612,7 @@ static int das08_do_wbits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int das08jr_di_rbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = 0;
+ 	data[1] = inb(dev->iobase + DAS08JR_DIO);
+@@ -621,7 +621,7 @@ static int das08jr_di_rbits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int das08jr_do_wbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	// null bits we are going to set
+ 	devpriv->do_bits &= ~data[0];
+@@ -635,7 +635,7 @@ static int das08jr_do_wbits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int das08jr_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int lsb, msb;
+@@ -669,7 +669,7 @@ static int das08jr_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+  *
+  */
+ static int das08ao_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int lsb, msb;
+@@ -783,7 +783,7 @@ static unsigned int i8254_read_status(struct i8254_struct *st, int channel)
+ }
+ 
+ static int das08_counter_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = insn->chanspec;
+ 
+@@ -795,7 +795,7 @@ static int das08_counter_read(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int das08_counter_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = insn->chanspec;
+ 
+@@ -806,7 +806,7 @@ static int das08_counter_write(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int das08_counter_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = insn->chanspec;
+ 
+diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
+index 42a81b832a9b..dd28385fc12f 100644
+--- a/drivers/staging/comedi/drivers/das16.c
++++ b/drivers/staging/comedi/drivers/das16.c
+@@ -327,13 +327,13 @@ struct munge_info {
+ };
+ 
+ static int das16_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int das16_do_wbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int das16_di_rbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int das16_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ static int das16_cmd_test(comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+@@ -1032,7 +1032,7 @@ static void das16_reset(comedi_device * dev)
+ }
+ 
+ static int das16_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+ 	int range;
+@@ -1080,9 +1080,9 @@ static int das16_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int das16_di_rbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+-	lsampl_t bits;
++	unsigned int bits;
+ 
+ 	bits = inb(dev->iobase + DAS16_DIO) & 0xf;
+ 	data[1] = bits;
+@@ -1092,9 +1092,9 @@ static int das16_di_rbits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int das16_do_wbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+-	lsampl_t wbits;
++	unsigned int wbits;
+ 
+ 	// only set bits that have been masked
+ 	data[0] &= 0xf;
+@@ -1112,7 +1112,7 @@ static int das16_do_wbits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int das16_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int lsb, msb;
+@@ -1718,8 +1718,8 @@ static unsigned int das16_suggest_transfer_size(comedi_device * dev,
+ static void das16_ai_munge(comedi_device * dev, comedi_subdevice * s,
+ 	void *array, unsigned int num_bytes, unsigned int start_chan_index)
+ {
+-	unsigned int i, num_samples = num_bytes / sizeof(sampl_t);
+-	sampl_t *data = array;
++	unsigned int i, num_samples = num_bytes / sizeof(short);
++	short *data = array;
+ 
+ 	for (i = 0; i < num_samples; i++) {
+ 		data[i] = le16_to_cpu(data[i]);
+diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
+index 904402ae507b..addccba3c6e8 100644
+--- a/drivers/staging/comedi/drivers/das16m1.c
++++ b/drivers/staging/comedi/drivers/das16m1.c
+@@ -132,11 +132,11 @@ static const comedi_lrange range_das16m1 = { 9,
+ };
+ 
+ static int das16m1_do_wbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int das16m1_di_rbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int das16m1_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ static int das16m1_cmd_test(comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+@@ -185,7 +185,7 @@ struct das16m1_private_struct {
+ 	 * needed to keep track of whether new count has been loaded into
+ 	 * counter yet (loaded by first sample conversion) */
+ 	u16 initial_hw_count;
+-	sampl_t ai_buffer[FIFO_SIZE];
++	short ai_buffer[FIFO_SIZE];
+ 	unsigned int do_bits;	// saves status of digital output bits
+ 	unsigned int divisor1;	// divides master clock to obtain conversion speed
+ 	unsigned int divisor2;	// divides master clock to obtain conversion speed
+@@ -195,7 +195,7 @@ struct das16m1_private_struct {
+ 
+ COMEDI_INITCLEANUP(driver_das16m1);
+ 
+-static inline sampl_t munge_sample(sampl_t data)
++static inline short munge_sample(short data)
+ {
+ 	return (data >> 4) & 0xfff;
+ }
+@@ -394,7 +394,7 @@ static int das16m1_cancel(comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ static int das16m1_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+ 	int byte;
+@@ -431,9 +431,9 @@ static int das16m1_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int das16m1_di_rbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+-	lsampl_t bits;
++	unsigned int bits;
+ 
+ 	bits = inb(dev->iobase + DAS16M1_DIO) & 0xf;
+ 	data[1] = bits;
+@@ -443,9 +443,9 @@ static int das16m1_di_rbits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int das16m1_do_wbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+-	lsampl_t wbits;
++	unsigned int wbits;
+ 
+ 	// only set bits that have been masked
+ 	data[0] &= 0xf;
+@@ -505,7 +505,7 @@ static irqreturn_t das16m1_interrupt(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static void munge_sample_array(sampl_t * array, unsigned int num_elements)
++static void munge_sample_array(short * array, unsigned int num_elements)
+ {
+ 	unsigned int i;
+ 
+@@ -553,7 +553,7 @@ static void das16m1_handler(comedi_device * dev, unsigned int status)
+ 	insw(dev->iobase, devpriv->ai_buffer, num_samples);
+ 	munge_sample_array(devpriv->ai_buffer, num_samples);
+ 	cfc_write_array_to_buffer(s, devpriv->ai_buffer,
+-		num_samples * sizeof(sampl_t));
++		num_samples * sizeof(short));
+ 	devpriv->adc_count += num_samples;
+ 
+ 	if (cmd->stop_src == TRIG_COUNT) {
+diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
+index 9c106965a429..f66cf17bbbcd 100644
+--- a/drivers/staging/comedi/drivers/das1800.c
++++ b/drivers/staging/comedi/drivers/das1800.c
+@@ -200,13 +200,13 @@ static int das1800_ai_do_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+ static int das1800_ai_do_cmd(comedi_device * dev, comedi_subdevice * s);
+ static int das1800_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int das1800_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int das1800_di_rbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int das1800_do_wbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ static int das1800_set_frequency(comedi_device * dev);
+ static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode);
+@@ -1037,7 +1037,7 @@ static void das1800_flush_dma_channel(comedi_device * dev, comedi_subdevice * s,
+ 
+ 	// figure out how many points to read
+ 	num_bytes = devpriv->dma_transfer_size - get_dma_residue(channel);
+-	num_samples = num_bytes / sizeof(sampl_t);
++	num_samples = num_bytes / sizeof(short);
+ 
+ 	/* if we only need some of the points */
+ 	if (cmd->stop_src == TRIG_COUNT && devpriv->count < num_samples)
+@@ -1105,7 +1105,7 @@ static void das1800_handle_fifo_half_full(comedi_device * dev,
+ static void das1800_handle_fifo_not_empty(comedi_device * dev,
+ 	comedi_subdevice * s)
+ {
+-	sampl_t dpnt;
++	short dpnt;
+ 	int unipolar;
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 
+@@ -1553,7 +1553,7 @@ static int das1800_ai_do_cmd(comedi_device * dev, comedi_subdevice * s)
+ 
+ /* read analog input */
+ static int das1800_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+ 	int chan, range, aref, chan_range;
+@@ -1613,7 +1613,7 @@ static int das1800_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 
+ /* writes to an analog output channel */
+ static int das1800_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ //      int range = CR_RANGE(insn->chanspec);
+@@ -1642,7 +1642,7 @@ static int das1800_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ 
+ /* reads from digital input channels */
+ static int das1800_di_rbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	data[1] = inb(dev->iobase + DAS1800_DIGITAL) & 0xf;
+@@ -1653,9 +1653,9 @@ static int das1800_di_rbits(comedi_device * dev, comedi_subdevice * s,
+ 
+ /* writes to digital output channels */
+ static int das1800_do_wbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+-	lsampl_t wbits;
++	unsigned int wbits;
+ 
+ 	// only set bits that have been masked
+ 	data[0] &= (1 << s->n_chan) - 1;
+diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c
+index e87a16e3a89f..85959c09679f 100644
+--- a/drivers/staging/comedi/drivers/das6402.c
++++ b/drivers/staging/comedi/drivers/das6402.c
+@@ -186,7 +186,7 @@ static irqreturn_t intr_handler(int irq, void *d PT_REGS_ARG)
+ }
+ 
+ #if 0
+-static void das6402_ai_fifo_read(comedi_device * dev, sampl_t * data, int n)
++static void das6402_ai_fifo_read(comedi_device * dev, short * data, int n)
+ {
+ 	int i;
+ 
+@@ -238,7 +238,7 @@ static int das6402_ai_mode2(comedi_device * dev, comedi_subdevice * s,
+ 	outw_p(SCANL, dev->iobase + 2);	/* resets the card fifo */
+ 	outb_p(IRQ | CONVSRC | BURSTEN | INTE, dev->iobase + 9);
+ 
+-	devpriv->ai_bytes_to_read = it->n * sizeof(sampl_t);
++	devpriv->ai_bytes_to_read = it->n * sizeof(short);
+ 
+ 	/* um... ignoreirq is a nasty race condition */
+ 	devpriv->das6402_ignoreirq = 0;
+diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
+index d0ec47e6b70e..7e658dbfa07a 100644
+--- a/drivers/staging/comedi/drivers/das800.c
++++ b/drivers/staging/comedi/drivers/das800.c
+@@ -263,11 +263,11 @@ static int das800_ai_do_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+ static int das800_ai_do_cmd(comedi_device * dev, comedi_subdevice * s);
+ static int das800_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int das800_di_rbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int das800_do_wbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int das800_probe(comedi_device * dev);
+ static int das800_set_frequency(comedi_device * dev);
+ 
+@@ -346,7 +346,7 @@ COMEDI_INITCLEANUP(driver_das800);
+ static irqreturn_t das800_interrupt(int irq, void *d PT_REGS_ARG)
+ {
+ 	short i;		/* loop index */
+-	sampl_t dataPoint = 0;
++	short dataPoint = 0;
+ 	comedi_device *dev = d;
+ 	comedi_subdevice *s = dev->read_subdev;	/* analog input subdevice */
+ 	comedi_async *async;
+@@ -789,7 +789,7 @@ static int das800_ai_do_cmd(comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ static int das800_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+ 	int chan;
+@@ -843,9 +843,9 @@ static int das800_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int das800_di_rbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+-	lsampl_t bits;
++	unsigned int bits;
+ 
+ 	bits = inb(dev->iobase + DAS800_STATUS) >> 4;
+ 	bits &= 0x7;
+@@ -856,7 +856,7 @@ static int das800_di_rbits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int das800_do_wbits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int wbits;
+ 	unsigned long irq_flags;
+diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
+index 0605caf4e305..c63af0c556b4 100644
+--- a/drivers/staging/comedi/drivers/dmm32at.c
++++ b/drivers/staging/comedi/drivers/dmm32at.c
+@@ -241,7 +241,7 @@ typedef struct {
+ 	unsigned int ai_scans_left;
+ 
+ 	/* Used for AO readback */
+-	lsampl_t ao_readback[4];
++	unsigned int ao_readback[4];
+ 	unsigned char dio_config;
+ 
+ } dmm32at_private;
+@@ -290,15 +290,15 @@ static comedi_driver driver_dmm32at = {
+ 
+ /* prototypes for driver functions below */
+ static int dmm32at_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int dmm32at_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int dmm32at_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int dmm32at_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int dmm32at_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int dmm32at_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+ static int dmm32at_ai_cmd(comedi_device * dev, comedi_subdevice * s);
+@@ -498,7 +498,7 @@ static int dmm32at_detach(comedi_device * dev)
+  */
+ 
+ static int dmm32at_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i;
+ 	unsigned int d;
+@@ -894,7 +894,7 @@ static int dmm32at_ns_to_timer(unsigned int *ns, int round)
+ }
+ 
+ static int dmm32at_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -937,7 +937,7 @@ static int dmm32at_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+ static int dmm32at_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -954,7 +954,7 @@ static int dmm32at_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+ static int dmm32at_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned char diobits;
+ 
+@@ -1007,7 +1007,7 @@ static int dmm32at_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int dmm32at_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned char chanbit;
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c
+index 73aaf7911a9d..4ee1199920e1 100644
+--- a/drivers/staging/comedi/drivers/dt2801.c
++++ b/drivers/staging/comedi/drivers/dt2801.c
+@@ -220,20 +220,20 @@ static const boardtype_t boardtypes[] = {
+ 
+ typedef struct {
+ 	const comedi_lrange *dac_range_types[2];
+-	lsampl_t ao_readback[2];
++	unsigned int ao_readback[2];
+ } dt2801_private;
+ #define devpriv ((dt2801_private *)dev->private)
+ 
+ static int dt2801_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int dt2801_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int dt2801_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int dt2801_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int dt2801_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ /* These are the low-level routines:
+    writecommand: write a command to the board
+@@ -606,7 +606,7 @@ static int dt2801_error(comedi_device * dev, int stat)
+ }
+ 
+ static int dt2801_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int d;
+ 	int stat;
+@@ -628,7 +628,7 @@ static int dt2801_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int dt2801_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->ao_readback[CR_CHAN(insn->chanspec)];
+ 
+@@ -636,7 +636,7 @@ static int dt2801_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int dt2801_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	dt2801_writecmd(dev, DT_C_WRITE_DAIM);
+ 	dt2801_writedata(dev, CR_CHAN(insn->chanspec));
+@@ -648,7 +648,7 @@ static int dt2801_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int dt2801_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int which = 0;
+ 
+@@ -672,7 +672,7 @@ static int dt2801_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int dt2801_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int which = 0;
+ 
+diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c
+index 99cd98067ca4..ce7cf31f2fc9 100644
+--- a/drivers/staging/comedi/drivers/dt2811.c
++++ b/drivers/staging/comedi/drivers/dt2811.c
+@@ -227,15 +227,15 @@ static comedi_driver driver_dt2811 = {
+ COMEDI_INITCLEANUP(driver_dt2811);
+ 
+ static int dt2811_ai_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int dt2811_ao_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int dt2811_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int dt2811_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int dt2811_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ enum { card_2811_pgh, card_2811_pgl };
+ typedef struct {
+@@ -248,7 +248,7 @@ typedef struct {
+ 		dac_bipolar_5, dac_bipolar_2_5, dac_unipolar_5
+ 	} dac_range[2];
+ 	const comedi_lrange *range_type_list[2];
+-	lsampl_t ao_readback[2];
++	unsigned int ao_readback[2];
+ } dt2811_private;
+ 
+ #define devpriv ((dt2811_private *)dev->private)
+@@ -491,7 +491,7 @@ static int dt2811_detach(comedi_device * dev)
+ }
+ 
+ static int dt2811_ai_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	int timeout = DT2811_TIMEOUT;
+@@ -542,7 +542,7 @@ int dt2811_adtrig(kdev_t minor, comedi_adtrig * adtrig)
+ #endif
+ 
+ static int dt2811_ao_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan;
+@@ -560,7 +560,7 @@ static int dt2811_ao_insn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int dt2811_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan;
+@@ -575,7 +575,7 @@ static int dt2811_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int dt2811_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -586,7 +586,7 @@ static int dt2811_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int dt2811_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c
+index bf432877ab26..bc96bf63e027 100644
+--- a/drivers/staging/comedi/drivers/dt2814.c
++++ b/drivers/staging/comedi/drivers/dt2814.c
+@@ -82,7 +82,7 @@ typedef struct {
+ #define DT2814_MAX_SPEED 100000	/* Arbitrary 10 khz limit */
+ 
+ static int dt2814_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i, hi, lo;
+ 	int chan;
+diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c
+index 7c0462d6cce1..98a64a74c82b 100644
+--- a/drivers/staging/comedi/drivers/dt2815.c
++++ b/drivers/staging/comedi/drivers/dt2815.c
+@@ -90,7 +90,7 @@ static void dt2815_free_resources(comedi_device * dev);
+ 
+ typedef struct {
+ 	const comedi_lrange *range_type_list[8];
+-	lsampl_t ao_readback[8];
++	unsigned int ao_readback[8];
+ } dt2815_private;
+ 
+ #define devpriv ((dt2815_private *)dev->private)
+@@ -107,7 +107,7 @@ static int dt2815_wait_for_status(comedi_device * dev, int status)
+ }
+ 
+ static int dt2815_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -120,7 +120,7 @@ static int dt2815_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int dt2815_ao_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c
+index d7a5285ccf9f..77c28e7b2a11 100644
+--- a/drivers/staging/comedi/drivers/dt2817.c
++++ b/drivers/staging/comedi/drivers/dt2817.c
+@@ -59,7 +59,7 @@ static comedi_driver driver_dt2817 = {
+ COMEDI_INITCLEANUP(driver_dt2817);
+ 
+ static int dt2817_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int mask;
+ 	int chan;
+@@ -97,7 +97,7 @@ static int dt2817_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int dt2817_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int changed;
+ 
+diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
+index 28eadea2a424..5cdd577475da 100644
+--- a/drivers/staging/comedi/drivers/dt282x.c
++++ b/drivers/staging/comedi/drivers/dt282x.c
+@@ -347,7 +347,7 @@ typedef struct {
+ 
+ 	const comedi_lrange *darangelist[2];
+ 
+-	sampl_t ao[2];
++	short ao[2];
+ 
+ 	volatile int dacsr;	/* software copies of registers */
+ 	volatile int adcsr;
+@@ -418,7 +418,7 @@ static void dt282x_disable_dma(comedi_device * dev);
+ 
+ static int dt282x_grab_dma(comedi_device * dev, int dma1, int dma2);
+ 
+-static void dt282x_munge(comedi_device * dev, sampl_t * buf,
++static void dt282x_munge(comedi_device * dev, short * buf,
+ 	unsigned int nbytes)
+ {
+ 	unsigned int i;
+@@ -626,9 +626,9 @@ static irqreturn_t dt282x_interrupt(int irq, void *d PT_REGS_ARG)
+ #if 0
+ 	if (adcsr & DT2821_ADDONE) {
+ 		int ret;
+-		sampl_t data;
++		short data;
+ 
+-		data = (sampl_t) inw(dev->iobase + DT2821_ADDAT);
++		data = (short) inw(dev->iobase + DT2821_ADDAT);
+ 		data &= (1 << boardtype.adbits) - 1;
+ 		if (devpriv->ad_2scomp) {
+ 			data ^= 1 << (boardtype.adbits - 1);
+@@ -675,7 +675,7 @@ static void dt282x_load_changain(comedi_device * dev, int n,
+  *      - trigger conversion and wait for it to finish
+  */
+ static int dt282x_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 
+@@ -938,7 +938,7 @@ static int dt282x_ns_to_timer(int *nanosec, int round_mode)
+  *      data register, and performs the conversion.
+  */
+ static int dt282x_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->ao[CR_CHAN(insn->chanspec)];
+ 
+@@ -946,9 +946,9 @@ static int dt282x_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int dt282x_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+-	sampl_t d;
++	short d;
+ 	unsigned int chan;
+ 
+ 	chan = CR_CHAN(insn->chanspec);
+@@ -1146,7 +1146,7 @@ static int dt282x_ao_cancel(comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ static int dt282x_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+ 		s->state &= ~data[0];
+@@ -1160,7 +1160,7 @@ static int dt282x_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int dt282x_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int mask;
+ 
+diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
+index 5266cae98880..b1af0e74cc73 100644
+--- a/drivers/staging/comedi/drivers/dt3000.c
++++ b/drivers/staging/comedi/drivers/dt3000.c
+@@ -265,7 +265,7 @@ typedef struct {
+ 	resource_size_t phys_addr;
+ 	void *io_addr;
+ 	unsigned int lock;
+-	lsampl_t ao_readback[2];
++	unsigned int ao_readback[2];
+ 	unsigned int ai_front;
+ 	unsigned int ai_rear;
+ } dt3k_private;
+@@ -402,7 +402,7 @@ static void dt3k_ai_empty_fifo(comedi_device * dev, comedi_subdevice * s)
+ 	int rear;
+ 	int count;
+ 	int i;
+-	sampl_t data;
++	short data;
+ 
+ 	front = readw(devpriv->io_addr + DPR_AD_Buf_Front);
+ 	count = front - devpriv->ai_front;
+@@ -668,7 +668,7 @@ static int dt3k_ai_cancel(comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ static int dt3k_ai_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	unsigned int chan, gain, aref;
+@@ -686,7 +686,7 @@ static int dt3k_ai_insn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int dt3k_ao_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	unsigned int chan;
+@@ -701,7 +701,7 @@ static int dt3k_ao_insn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int dt3k_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	unsigned int chan;
+@@ -730,7 +730,7 @@ static void dt3k_dio_config(comedi_device * dev, int bits)
+ }
+ 
+ static int dt3k_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int mask;
+ 
+@@ -761,7 +761,7 @@ static int dt3k_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int dt3k_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -777,7 +777,7 @@ static int dt3k_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int dt3k_mem_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int addr = CR_CHAN(insn->chanspec);
+ 	int i;
+diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c
+index f2d2173d7219..bbb5a146a7ee 100644
+--- a/drivers/staging/comedi/drivers/dt9812.c
++++ b/drivers/staging/comedi/drivers/dt9812.c
+@@ -941,7 +941,7 @@ static void dt9812_comedi_open(comedi_device *dev)
+ }
+ 
+ static int dt9812_di_rinsn(comedi_device *dev, comedi_subdevice *s,
+-			   comedi_insn *insn, lsampl_t *data)
++			   comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	u8 bits = 0;
+@@ -953,7 +953,7 @@ static int dt9812_di_rinsn(comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ static int dt9812_do_winsn(comedi_device *dev, comedi_subdevice *s,
+-			   comedi_insn *insn, lsampl_t *data)
++			   comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	u8 bits = 0;
+@@ -971,7 +971,7 @@ static int dt9812_do_winsn(comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ static int dt9812_ai_rinsn(comedi_device *dev, comedi_subdevice *s,
+-			   comedi_insn *insn, lsampl_t *data)
++			   comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 
+@@ -986,7 +986,7 @@ static int dt9812_ai_rinsn(comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ static int dt9812_ao_rinsn(comedi_device *dev, comedi_subdevice *s,
+-			   comedi_insn *insn, lsampl_t *data)
++			   comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 	u16 value;
+@@ -1000,7 +1000,7 @@ static int dt9812_ao_rinsn(comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ static int dt9812_ao_winsn(comedi_device *dev, comedi_subdevice *s,
+-			   comedi_insn *insn, lsampl_t *data)
++			   comedi_insn *insn, unsigned int *data)
+ {
+ 	int n;
+ 
+diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c
+index 81c47304d204..26709987278c 100644
+--- a/drivers/staging/comedi/drivers/fl512.c
++++ b/drivers/staging/comedi/drivers/fl512.c
+@@ -25,7 +25,7 @@ Configuration options:
+ 
+ #define FL512_SIZE 16		/* the size of the used memory */
+ typedef struct {
+-	sampl_t ao_readback[2];
++	short ao_readback[2];
+ } fl512_private;
+ #define devpriv ((fl512_private *) dev->private)
+ 
+@@ -53,17 +53,17 @@ static comedi_driver driver_fl512 = {
+ COMEDI_INITCLEANUP(driver_fl512);
+ 
+ static int fl512_ai_insn(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ static int fl512_ao_insn(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ static int fl512_ao_insn_readback(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+ /*
+  * fl512_ai_insn : this is the analog input function
+  */
+ static int fl512_ai_insn(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	unsigned int lo_byte, hi_byte;
+@@ -88,7 +88,7 @@ static int fl512_ai_insn(comedi_device * dev,
+  * fl512_ao_insn : used to write to a DA port n times
+  */
+ static int fl512_ao_insn(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);	/* get chan to write */
+@@ -109,7 +109,7 @@ static int fl512_ao_insn(comedi_device * dev,
+  * DA port
+  */
+ static int fl512_ao_insn_readback(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
+index 8d753e4ce7b6..07ed2380aa9a 100644
+--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
++++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
+@@ -60,7 +60,7 @@ static int hpdi_cmd_test(comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+ static int hpdi_cancel(comedi_device * dev, comedi_subdevice * s);
+ static irqreturn_t handle_interrupt(int irq, void *d PT_REGS_ARG);
+-static int dio_config_block_size(comedi_device * dev, lsampl_t * data);
++static int dio_config_block_size(comedi_device * dev, unsigned int * data);
+ 
+ #undef HPDI_DEBUG		// disable debugging messages
+ //#define HPDI_DEBUG    // enable debugging code
+@@ -337,7 +337,7 @@ static comedi_driver driver_hpdi = {
+ COMEDI_PCI_INITCLEANUP(driver_hpdi, hpdi_pci_table);
+ 
+ static int dio_config_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+ 	case INSN_CONFIG_DIO_OUTPUT:
+@@ -702,7 +702,7 @@ static int hpdi_detach(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int dio_config_block_size(comedi_device * dev, lsampl_t * data)
++static int dio_config_block_size(comedi_device * dev, unsigned int * data)
+ {
+ 	unsigned int requested_block_size;
+ 	int retval;
+diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
+index 41ce5ec058fa..1d27e90213cd 100644
+--- a/drivers/staging/comedi/drivers/icp_multi.c
++++ b/drivers/staging/comedi/drivers/icp_multi.c
+@@ -198,9 +198,9 @@ struct icp_multi_private {
+ 	unsigned char act_chanlist_len;	/*  len of scanlist */
+ 	unsigned char act_chanlist_pos;	/*  actual position in MUX list */
+ 	unsigned int *ai_chanlist;	/*  actaul chanlist */
+-	sampl_t *ai_data;	/*  data buffer */
+-	sampl_t ao_data[4];	/*  data output buffer */
+-	sampl_t di_data;	/*  Digital input data */
++	short *ai_data;	/*  data buffer */
++	short ao_data[4];	/*  data output buffer */
++	short di_data;	/*  Digital input data */
+ 	unsigned int do_data;	/*  Remember digital output data */
+ };
+ 
+@@ -239,14 +239,14 @@ static int icp_multi_reset(comedi_device *dev);
+ 		comedi_device *dev	Pointer to current device structure
+ 		comedi_subdevice *s	Pointer to current subdevice structure
+ 		comedi_insn *insn	Pointer to current comedi instruction
+-		lsampl_t *data		Pointer to analogue input data
++		unsigned int *data		Pointer to analogue input data
+ 
+ 	Returns:int			Nmuber of instructions executed
+ 
+ ==============================================================================
+ */
+ static int icp_multi_insn_read_ai(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data)
++	comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, timeout;
+ 
+@@ -358,14 +358,14 @@ static int icp_multi_insn_read_ai(comedi_device *dev, comedi_subdevice *s,
+ 		comedi_device *dev	Pointer to current device structure
+ 		comedi_subdevice *s	Pointer to current subdevice structure
+ 		comedi_insn *insn	Pointer to current comedi instruction
+-		lsampl_t *data		Pointer to analogue output data
++		unsigned int *data		Pointer to analogue output data
+ 
+ 	Returns:int			Nmuber of instructions executed
+ 
+ ==============================================================================
+ */
+ static int icp_multi_insn_write_ao(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data)
++	comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, chan, range, timeout;
+ 
+@@ -466,14 +466,14 @@ static int icp_multi_insn_write_ao(comedi_device *dev, comedi_subdevice *s,
+ 		comedi_device *dev	Pointer to current device structure
+ 		comedi_subdevice *s	Pointer to current subdevice structure
+ 		comedi_insn *insn	Pointer to current comedi instruction
+-		lsampl_t *data		Pointer to analogue output data
++		unsigned int *data		Pointer to analogue output data
+ 
+ 	Returns:int			Nmuber of instructions executed
+ 
+ ==============================================================================
+ */
+ static int icp_multi_insn_read_ao(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data)
++	comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, chan;
+ 
+@@ -499,14 +499,14 @@ static int icp_multi_insn_read_ao(comedi_device *dev, comedi_subdevice *s,
+ 		comedi_device *dev	Pointer to current device structure
+ 		comedi_subdevice *s	Pointer to current subdevice structure
+ 		comedi_insn *insn	Pointer to current comedi instruction
+-		lsampl_t *data		Pointer to analogue output data
++		unsigned int *data		Pointer to analogue output data
+ 
+ 	Returns:int			Nmuber of instructions executed
+ 
+ ==============================================================================
+ */
+ static int icp_multi_insn_bits_di(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data)
++	comedi_insn *insn, unsigned int *data)
+ {
+ 	data[1] = readw(devpriv->io_addr + ICP_MULTI_DI);
+ 
+@@ -525,14 +525,14 @@ static int icp_multi_insn_bits_di(comedi_device *dev, comedi_subdevice *s,
+ 		comedi_device *dev	Pointer to current device structure
+ 		comedi_subdevice *s	Pointer to current subdevice structure
+ 		comedi_insn *insn	Pointer to current comedi instruction
+-		lsampl_t *data		Pointer to analogue output data
++		unsigned int *data		Pointer to analogue output data
+ 
+ 	Returns:int			Nmuber of instructions executed
+ 
+ ==============================================================================
+ */
+ static int icp_multi_insn_bits_do(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data)
++	comedi_insn *insn, unsigned int *data)
+ {
+ #ifdef ICP_MULTI_EXTDEBUG
+ 	printk("icp multi EDBG: BGN: icp_multi_insn_bits_do(...)\n");
+@@ -567,14 +567,14 @@ static int icp_multi_insn_bits_do(comedi_device *dev, comedi_subdevice *s,
+ 		comedi_device *dev	Pointer to current device structure
+ 		comedi_subdevice *s	Pointer to current subdevice structure
+ 		comedi_insn *insn	Pointer to current comedi instruction
+-		lsampl_t *data		Pointer to counter data
++		unsigned int *data		Pointer to counter data
+ 
+ 	Returns:int			Nmuber of instructions executed
+ 
+ ==============================================================================
+ */
+ static int icp_multi_insn_read_ctr(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data)
++	comedi_insn *insn, unsigned int *data)
+ {
+ 	return 0;
+ }
+@@ -591,14 +591,14 @@ static int icp_multi_insn_read_ctr(comedi_device *dev, comedi_subdevice *s,
+ 		comedi_device *dev	Pointer to current device structure
+ 		comedi_subdevice *s	Pointer to current subdevice structure
+ 		comedi_insn *insn	Pointer to current comedi instruction
+-		lsampl_t *data		Pointer to counter data
++		unsigned int *data		Pointer to counter data
+ 
+ 	Returns:int			Nmuber of instructions executed
+ 
+ ==============================================================================
+ */
+ static int icp_multi_insn_write_ctr(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data)
++	comedi_insn *insn, unsigned int *data)
+ {
+ 	return 0;
+ }
+diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c
+index ef7c580453c0..eb3dde50d75c 100644
+--- a/drivers/staging/comedi/drivers/ii_pci20kc.c
++++ b/drivers/staging/comedi/drivers/ii_pci20kc.c
+@@ -138,7 +138,7 @@ typedef union {
+ 	struct {
+ 		void *iobase;
+ 		const comedi_lrange *ao_range_list[2];	/* range of channels of ao module */
+-		lsampl_t last_data[2];
++		unsigned int last_data[2];
+ 	} pci20006;
+ 	struct {
+ 		void *iobase;
+@@ -271,9 +271,9 @@ static int pci20xxx_detach(comedi_device * dev)
+ /* pci20006m */
+ 
+ static int pci20006_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int pci20006_insn_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ static const comedi_lrange *pci20006_range_list[] = {
+ 	&range_bipolar10,
+@@ -307,7 +307,7 @@ static int pci20006_init(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int pci20006_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	pci20xxx_subdev_private *sdp = s->private;
+ 
+@@ -317,7 +317,7 @@ static int pci20006_insn_read(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int pci20006_insn_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	pci20xxx_subdev_private *sdp = s->private;
+ 	int hi, lo;
+@@ -350,7 +350,7 @@ static int pci20006_insn_write(comedi_device * dev, comedi_subdevice * s,
+ /* PCI20341M */
+ 
+ static int pci20341_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ static const int pci20341_timebase[] = { 0x00, 0x00, 0x00, 0x04 };
+ static const int pci20341_settling_time[] = { 0x58, 0x58, 0x93, 0x99 };
+@@ -398,7 +398,7 @@ static int pci20341_init(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int pci20341_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	pci20xxx_subdev_private *sdp = s->private;
+ 	unsigned int i = 0, j = 0;
+@@ -435,7 +435,7 @@ static int pci20341_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 		lo = readb(sdp->iobase + PCI20341_LDATA);
+ 		hi = readb(sdp->iobase + PCI20341_LDATA + 1);
+ 		boarddata = lo + 0x100 * hi;
+-		data[i] = (sampl_t) ((boarddata + 0x8000) & 0xffff);	/* board-data -> comedi-data */
++		data[i] = (short) ((boarddata + 0x8000) & 0xffff);	/* board-data -> comedi-data */
+ 	}
+ 
+ 	return i;
+@@ -445,9 +445,9 @@ static int pci20341_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 
+ static void pci20xxx_dio_config(comedi_device * dev, comedi_subdevice * s);
+ static int pci20xxx_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int pci20xxx_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ /* initialize pci20xxx_private */
+ static int pci20xxx_dio_init(comedi_device * dev, comedi_subdevice * s)
+@@ -470,7 +470,7 @@ static int pci20xxx_dio_init(comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ static int pci20xxx_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int mask, bits;
+ 
+@@ -495,7 +495,7 @@ static int pci20xxx_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int pci20xxx_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int mask = data[0];
+ 
+diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
+index 3ba05d9c7176..ae3e2a125abf 100644
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -159,7 +159,7 @@ typedef struct {
+ 		comedi_krange range;
+ 	} range[9];
+ 	const comedi_lrange *range_table_list[8 * 7 + 2];
+-	lsampl_t maxdata_list[8 * 7 + 2];
++	unsigned int maxdata_list[8 * 7 + 2];
+ 	u16 errors;
+ 	int retries;
+ } jr3_pci_subdev_private;
+@@ -270,7 +270,7 @@ static six_axis_t get_max_full_scales(volatile jr3_channel_t * channel)
+ }
+ 
+ static int jr3_pci_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int result;
+ 	jr3_pci_subdev_private *p;
+diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c
+index 585788833ccd..834625c546db 100644
+--- a/drivers/staging/comedi/drivers/ke_counter.c
++++ b/drivers/staging/comedi/drivers/ke_counter.c
+@@ -100,7 +100,7 @@ COMEDI_PCI_INITCLEANUP(cnt_driver, cnt_pci_table);
+ /* This should be used only for resetting the counters; maybe it is better
+    to make a special command 'reset'. */
+ static int cnt_winsn(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+@@ -120,7 +120,7 @@ static int cnt_winsn(comedi_device * dev,
+ /*-- counter read -----------------------------------------------------------*/
+ 
+ static int cnt_rinsn(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned char a0, a1, a2, a3, a4;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -136,7 +136,7 @@ static int cnt_rinsn(comedi_device * dev,
+ 	if (a4 > 0)
+ 		result = result - s->maxdata;
+ 
+-	*data = (lsampl_t) result;
++	*data = (unsigned int) result;
+ 
+ 	/* return the number of samples read */
+ 	return 1;
+diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
+index 5f6e77cceb69..7aad3e53624a 100644
+--- a/drivers/staging/comedi/drivers/me4000.c
++++ b/drivers/staging/comedi/drivers/me4000.c
+@@ -141,10 +141,10 @@ static int xilinx_download(comedi_device *dev);
+ static int reset_board(comedi_device *dev);
+ 
+ static int me4000_dio_insn_bits(comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);
++	comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
+ 
+ static int me4000_dio_insn_config(comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);
++	comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
+ 
+ static int cnt_reset(comedi_device *dev, unsigned int channel);
+ 
+@@ -152,16 +152,16 @@ static int cnt_config(comedi_device *dev,
+ 	unsigned int channel, unsigned int mode);
+ 
+ static int me4000_cnt_insn_config(comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);
++	comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
+ 
+ static int me4000_cnt_insn_write(comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);
++	comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
+ 
+ static int me4000_cnt_insn_read(comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);
++	comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
+ 
+ static int me4000_ai_insn_read(comedi_device *dev,
+-	comedi_subdevice *subdevice, comedi_insn *insn, lsampl_t *data);
++	comedi_subdevice *subdevice, comedi_insn *insn, unsigned int *data);
+ 
+ static int me4000_ai_cancel(comedi_device *dev, comedi_subdevice *s);
+ 
+@@ -191,10 +191,10 @@ static int me4000_ai_do_cmd_test(comedi_device *dev,
+ static int me4000_ai_do_cmd(comedi_device *dev, comedi_subdevice *s);
+ 
+ static int me4000_ao_insn_write(comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);
++	comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
+ 
+ static int me4000_ao_insn_read(comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);
++	comedi_subdevice *s, comedi_insn *insn, unsigned int *data);
+ 
+ /*-----------------------------------------------------------------------------
+   Meilhaus inline functions
+@@ -914,7 +914,7 @@ static int me4000_detach(comedi_device *dev)
+   ===========================================================================*/
+ 
+ static int me4000_ai_insn_read(comedi_device *dev,
+-	comedi_subdevice *subdevice, comedi_insn *insn, lsampl_t *data)
++	comedi_subdevice *subdevice, comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -1904,7 +1904,7 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id PT_REGS_ARG)
+   ===========================================================================*/
+ 
+ static int me4000_ao_insn_write(comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
++	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -1962,7 +1962,7 @@ static int me4000_ao_insn_write(comedi_device *dev,
+ }
+ 
+ static int me4000_ao_insn_read(comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
++	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+@@ -1983,7 +1983,7 @@ static int me4000_ao_insn_read(comedi_device *dev,
+   ===========================================================================*/
+ 
+ static int me4000_dio_insn_bits(comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
++	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	CALL_PDEBUG("In me4000_dio_insn_bits()\n");
+@@ -2034,7 +2034,7 @@ static int me4000_dio_insn_bits(comedi_device *dev,
+ }
+ 
+ static int me4000_dio_insn_config(comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
++	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned long tmp;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -2216,7 +2216,7 @@ static int cnt_config(comedi_device *dev, unsigned int channel,
+ }
+ 
+ static int me4000_cnt_insn_config(comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
++	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	int err;
+@@ -2259,7 +2259,7 @@ static int me4000_cnt_insn_config(comedi_device *dev,
+ }
+ 
+ static int me4000_cnt_insn_read(comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
++	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	unsigned short tmp;
+@@ -2306,7 +2306,7 @@ static int me4000_cnt_insn_read(comedi_device *dev,
+ }
+ 
+ static int me4000_cnt_insn_write(comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
++	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	unsigned short tmp;
+diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c
+index 6accec20a0f9..877920e35e1b 100644
+--- a/drivers/staging/comedi/drivers/me_daq.c
++++ b/drivers/staging/comedi/drivers/me_daq.c
+@@ -291,7 +291,7 @@ static inline void sleep(unsigned sec)
+  * ------------------------------------------------------------------
+  */
+ static int me_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
+-			      comedi_insn *insn, lsampl_t *data)
++			      comedi_insn *insn, unsigned int *data)
+ {
+ 	int bits;
+ 	int mask = 1 << CR_CHAN(insn->chanspec);
+@@ -327,7 +327,7 @@ static int me_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
+ 
+ /* Digital instant input/outputs */
+ static int me_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
+-			    comedi_insn *insn, lsampl_t *data)
++			    comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned int mask = data[0];
+ 	s->state &= ~mask;
+@@ -363,7 +363,7 @@ static int me_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
+ 
+ /* Analog instant input */
+ static int me_ai_insn_read(comedi_device *dev, comedi_subdevice *subdevice,
+-			   comedi_insn *insn, lsampl_t *data)
++			   comedi_insn *insn, unsigned int *data)
+ {
+ 	unsigned short value;
+ 	int chan = CR_CHAN((&insn->chanspec)[0]);
+@@ -470,7 +470,7 @@ static int me_ai_do_cmd(comedi_device *dev, comedi_subdevice *subdevice)
+ 
+ /* Analog instant output */
+ static int me_ao_insn_write(comedi_device *dev, comedi_subdevice *s,
+-			    comedi_insn *insn, lsampl_t *data)
++			    comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan;
+ 	int rang;
+@@ -520,7 +520,7 @@ static int me_ao_insn_write(comedi_device *dev, comedi_subdevice *s,
+ 
+ /* Analog output readback */
+ static int me_ao_insn_read(comedi_device *dev, comedi_subdevice *s,
+-			   comedi_insn *insn, lsampl_t *data)
++			   comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 
+diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c
+index c514d9999fb0..a4be0721d69f 100644
+--- a/drivers/staging/comedi/drivers/mpc624.c
++++ b/drivers/staging/comedi/drivers/mpc624.c
+@@ -156,7 +156,7 @@ static comedi_driver driver_mpc624 = {
+ 
+ //----------------------------------------------------------------------------
+ static int mpc624_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ //----------------------------------------------------------------------------
+ static int mpc624_attach(comedi_device * dev, comedi_devconfig * it)
+ {
+@@ -269,7 +269,7 @@ static int mpc624_detach(comedi_device * dev)
+ #define TIMEOUT 200
+ 
+ static int mpc624_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i;
+ 	unsigned long int data_in, data_out;
+diff --git a/drivers/staging/comedi/drivers/mpc8260cpm.c b/drivers/staging/comedi/drivers/mpc8260cpm.c
+index d8e6c43bdcdd..b3a64bbbf0c3 100644
+--- a/drivers/staging/comedi/drivers/mpc8260cpm.c
++++ b/drivers/staging/comedi/drivers/mpc8260cpm.c
+@@ -56,9 +56,9 @@ static comedi_driver driver_mpc8260cpm = {
+ COMEDI_INITCLEANUP(driver_mpc8260cpm);
+ 
+ static int mpc8260cpm_dio_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int mpc8260cpm_dio_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ static int mpc8260cpm_attach(comedi_device * dev, comedi_devconfig * it)
+ {
+@@ -113,7 +113,7 @@ static unsigned long *cpm_pdat(int port)
+ }
+ 
+ static int mpc8260cpm_dio_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	unsigned int d;
+@@ -156,7 +156,7 @@ static int mpc8260cpm_dio_config(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int mpc8260cpm_dio_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int port;
+ 	unsigned long *p;
+diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c
+index e827ae7ef9ba..dd9648d68a88 100644
+--- a/drivers/staging/comedi/drivers/multiq3.c
++++ b/drivers/staging/comedi/drivers/multiq3.c
+@@ -94,12 +94,12 @@ static comedi_driver driver_multiq3 = {
+ COMEDI_INITCLEANUP(driver_multiq3);
+ 
+ struct multiq3_private {
+-	lsampl_t ao_readback[2];
++	unsigned int ao_readback[2];
+ };
+ #define devpriv ((struct multiq3_private *)dev->private)
+ 
+ static int multiq3_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+ 	int chan;
+@@ -135,7 +135,7 @@ static int multiq3_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int multiq3_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -148,7 +148,7 @@ static int multiq3_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int multiq3_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -166,7 +166,7 @@ static int multiq3_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int multiq3_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -177,7 +177,7 @@ static int multiq3_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int multiq3_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -192,7 +192,7 @@ static int multiq3_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int multiq3_encoder_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
+index 1d152d173ab5..17c33a591fd1 100644
+--- a/drivers/staging/comedi/drivers/ni_6527.c
++++ b/drivers/staging/comedi/drivers/ni_6527.c
+@@ -120,7 +120,7 @@ typedef struct {
+ static int ni6527_find_device(comedi_device * dev, int bus, int slot);
+ 
+ static int ni6527_di_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	unsigned int interval;
+@@ -168,7 +168,7 @@ static int ni6527_di_insn_config(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int ni6527_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -181,7 +181,7 @@ static int ni6527_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int ni6527_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -327,7 +327,7 @@ static int ni6527_intr_cancel(comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ static int ni6527_intr_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n < 1)
+ 		return -EINVAL;
+@@ -337,7 +337,7 @@ static int ni6527_intr_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int ni6527_intr_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n < 1)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
+index 4029c1786d70..cc5ada875359 100644
+--- a/drivers/staging/comedi/drivers/ni_65xx.c
++++ b/drivers/staging/comedi/drivers/ni_65xx.c
+@@ -311,7 +311,7 @@ static ni_65xx_subdevice_private *ni_65xx_alloc_subdevice_private(void)
+ static int ni_65xx_find_device(comedi_device * dev, int bus, int slot);
+ 
+ static int ni_65xx_config_filter(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	const unsigned chan = CR_CHAN(insn->chanspec);
+ 	const unsigned port =
+@@ -350,7 +350,7 @@ static int ni_65xx_config_filter(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int ni_65xx_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned port;
+ 
+@@ -389,7 +389,7 @@ static int ni_65xx_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int ni_65xx_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned base_bitfield_channel;
+ 	const unsigned max_ports_per_bitfield = 5;
+@@ -569,7 +569,7 @@ static int ni_65xx_intr_cancel(comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ static int ni_65xx_intr_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n < 1)
+ 		return -EINVAL;
+@@ -579,7 +579,7 @@ static int ni_65xx_intr_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int ni_65xx_intr_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n < 1)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
+index e646e98f3082..896e2ea4b04d 100644
+--- a/drivers/staging/comedi/drivers/ni_660x.c
++++ b/drivers/staging/comedi/drivers/ni_660x.c
+@@ -465,17 +465,17 @@ static int ni_660x_set_pfi_routing(comedi_device * dev, unsigned chan,
+ 
+ /* Possible instructions for a GPCT */
+ static int ni_660x_GPCT_rinsn(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ static int ni_660x_GPCT_insn_config(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ static int ni_660x_GPCT_winsn(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+ /* Possible instructions for Digital IO */
+ static int ni_660x_dio_insn_config(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ static int ni_660x_dio_insn_bits(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+ static inline unsigned ni_660x_num_counters(comedi_device * dev)
+ {
+@@ -1121,7 +1121,7 @@ static int ni_660x_detach(comedi_device * dev)
+ 
+ static int
+ ni_660x_GPCT_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	return ni_tio_rinsn(subdev_to_counter(s), insn, data);
+ }
+@@ -1148,13 +1148,13 @@ static void init_tio_chip(comedi_device * dev, int chipset)
+ 
+ static int
+ ni_660x_GPCT_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	return ni_tio_insn_config(subdev_to_counter(s), insn, data);
+ }
+ 
+ static int ni_660x_GPCT_winsn(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	return ni_tio_winsn(subdev_to_counter(s), insn, data);
+ }
+@@ -1187,7 +1187,7 @@ static int ni_660x_find_device(comedi_device * dev, int bus, int slot)
+ }
+ 
+ static int ni_660x_dio_insn_bits(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned base_bitfield_channel = CR_CHAN(insn->chanspec);
+ 
+@@ -1280,7 +1280,7 @@ static void ni660x_config_filter(comedi_device * dev, unsigned pfi_channel,
+ }
+ 
+ static int ni_660x_dio_insn_config(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
+index f622e340e1a2..5e1cb2abe870 100644
+--- a/drivers/staging/comedi/drivers/ni_670x.c
++++ b/drivers/staging/comedi/drivers/ni_670x.c
+@@ -102,7 +102,7 @@ typedef struct {
+ 	struct mite_struct *mite;
+ 	int boardtype;
+ 	int dio;
+-	lsampl_t ao_readback[32];
++	unsigned int ao_readback[32];
+ } ni_670x_private;
+ 
+ #define devpriv ((ni_670x_private *)dev->private)
+@@ -125,13 +125,13 @@ static comedi_lrange range_0_20mA = { 1, {RANGE_mA(0, 20)} };
+ static int ni_670x_find_device(comedi_device * dev, int bus, int slot);
+ 
+ static int ni_670x_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int ni_670x_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int ni_670x_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int ni_670x_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ static int ni_670x_attach(comedi_device * dev, comedi_devconfig * it)
+ {
+@@ -219,7 +219,7 @@ static int ni_670x_detach(comedi_device * dev)
+ }
+ 
+ static int ni_670x_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -245,7 +245,7 @@ static int ni_670x_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int ni_670x_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -257,7 +257,7 @@ static int ni_670x_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int ni_670x_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -279,7 +279,7 @@ static int ni_670x_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int ni_670x_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
+index 462419b247b1..2d7f5528b402 100644
+--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
++++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
+@@ -183,7 +183,7 @@ static int a2150_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+ static int a2150_ai_cmd(comedi_device * dev, comedi_subdevice * s);
+ static int a2150_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int a2150_get_timing(comedi_device * dev, unsigned int *period,
+ 	int flags);
+ static int a2150_probe(comedi_device * dev);
+@@ -217,7 +217,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d PT_REGS_ARG)
+ 	comedi_async *async;
+ 	comedi_cmd *cmd;
+ 	unsigned int max_points, num_points, residue, leftover;
+-	sampl_t dpnt;
++	short dpnt;
+ 	static const int sample_size = sizeof(devpriv->dma_buffer[0]);
+ 
+ 	if (dev->attached == 0) {
+@@ -727,7 +727,7 @@ static int a2150_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ static int a2150_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int i, n;
+ 	static const int timeout = 100000;
+diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c
+index beb15ed9da3a..fd259813bf54 100644
+--- a/drivers/staging/comedi/drivers/ni_at_ao.c
++++ b/drivers/staging/comedi/drivers/ni_at_ao.c
+@@ -174,7 +174,7 @@ typedef struct {
+ 	unsigned short cfg3;
+ 
+ 	/* Used for AO readback */
+-	lsampl_t ao_readback[10];
++	unsigned int ao_readback[10];
+ } atao_private;
+ #define devpriv ((atao_private *)dev->private)
+ 
+@@ -195,17 +195,17 @@ COMEDI_INITCLEANUP(driver_atao);
+ static void atao_reset(comedi_device * dev);
+ 
+ static int atao_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int atao_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int atao_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int atao_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int atao_calib_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int atao_calib_insn_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ static int atao_attach(comedi_device * dev, comedi_devconfig * it)
+ {
+@@ -321,7 +321,7 @@ static void atao_reset(comedi_device * dev)
+ }
+ 
+ static int atao_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -345,7 +345,7 @@ static int atao_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int atao_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -357,7 +357,7 @@ static int atao_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int atao_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -374,7 +374,7 @@ static int atao_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int atao_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	unsigned int mask, bit;
+@@ -419,7 +419,7 @@ static int atao_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+  * the caldacs, but we can guess.
+  */
+ static int atao_calib_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	for (i = 0; i < insn->n; i++) {
+@@ -429,7 +429,7 @@ static int atao_calib_insn_read(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int atao_calib_insn_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int bitstring, bit;
+ 	unsigned int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
+index cdd9ee879c6c..11581dce981f 100644
+--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
++++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
+@@ -180,7 +180,7 @@ typedef struct {
+ 	enum { dac_internal, dac_external } dac0_reference, dac1_reference;
+ 	enum { dac_2comp, dac_straight } dac0_coding, dac1_coding;
+ 	const comedi_lrange *ao_range_type_list[2];
+-	lsampl_t ao_readback[2];
++	unsigned int ao_readback[2];
+ 	unsigned int com_reg_1_state;	/* current state of command register 1 */
+ 	unsigned int com_reg_2_state;	/* current state of command register 2 */
+ } atmio16d_private;
+@@ -526,7 +526,7 @@ static int atmio16d_ai_cancel(comedi_device * dev, comedi_subdevice * s)
+ 
+ /* Mode 0 is used to get a single conversion on demand */
+ static int atmio16d_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, t;
+ 	int chan;
+@@ -585,7 +585,7 @@ static int atmio16d_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int atmio16d_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ #ifdef DEBUG1
+@@ -600,7 +600,7 @@ static int atmio16d_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int atmio16d_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan;
+@@ -635,7 +635,7 @@ static int atmio16d_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int atmio16d_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -651,7 +651,7 @@ static int atmio16d_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int atmio16d_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int mask;
+diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
+index 7ea57a21e68d..9193f16ad14f 100644
+--- a/drivers/staging/comedi/drivers/ni_daq_700.c
++++ b/drivers/staging/comedi/drivers/ni_daq_700.c
+@@ -130,7 +130,7 @@ static void do_config(comedi_device * dev, comedi_subdevice * s);
+ 
+ void subdev_700_interrupt(comedi_device * dev, comedi_subdevice * s)
+ {
+-	sampl_t d;
++	short d;
+ 
+ 	d = CALLBACK_FUNC(0, _700_DATA, 0, CALLBACK_ARG);
+ 
+@@ -154,7 +154,7 @@ static int subdev_700_cb(int dir, int port, int data, unsigned long arg)
+ }
+ 
+ static int subdev_700_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (data[0]) {
+ 		s->state &= ~data[0];
+@@ -172,7 +172,7 @@ static int subdev_700_insn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int subdev_700_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	switch (data[0]) {
+diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
+index 9ea1953bae8f..a7688f1670aa 100644
+--- a/drivers/staging/comedi/drivers/ni_labpc.c
++++ b/drivers/staging/comedi/drivers/ni_labpc.c
+@@ -174,19 +174,19 @@ static int labpc_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+ static int labpc_ai_cmd(comedi_device * dev, comedi_subdevice * s);
+ static int labpc_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int labpc_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int labpc_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int labpc_calib_read_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int labpc_calib_write_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int labpc_eeprom_read_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int labpc_eeprom_write_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static unsigned int labpc_suggest_transfer_size(comedi_cmd cmd);
+ static void labpc_adc_timing(comedi_device * dev, comedi_cmd * cmd);
+ #ifdef CONFIG_COMEDI_PCI
+@@ -1396,7 +1396,7 @@ static irqreturn_t labpc_interrupt(int irq, void *d PT_REGS_ARG)
+ static int labpc_drain_fifo(comedi_device * dev)
+ {
+ 	unsigned int lsb, msb;
+-	sampl_t data;
++	short data;
+ 	comedi_async *async = dev->read_subdev->async;
+ 	const int timeout = 10000;
+ 	unsigned int i;
+@@ -1501,7 +1501,7 @@ static void labpc_drain_dregs(comedi_device * dev)
+ }
+ 
+ static int labpc_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+ 	int chan, range;
+@@ -1587,7 +1587,7 @@ static int labpc_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 
+ // analog output insn
+ static int labpc_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel, range;
+ 	unsigned long flags;
+@@ -1628,7 +1628,7 @@ static int labpc_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ 
+ // analog output readback insn
+ static int labpc_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)];
+ 
+@@ -1636,7 +1636,7 @@ static int labpc_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int labpc_calib_read_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->caldac[CR_CHAN(insn->chanspec)];
+ 
+@@ -1644,7 +1644,7 @@ static int labpc_calib_read_insn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int labpc_calib_write_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel = CR_CHAN(insn->chanspec);
+ 
+@@ -1653,7 +1653,7 @@ static int labpc_calib_write_insn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int labpc_eeprom_read_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->eeprom_data[CR_CHAN(insn->chanspec)];
+ 
+@@ -1661,7 +1661,7 @@ static int labpc_eeprom_read_insn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int labpc_eeprom_write_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel = CR_CHAN(insn->chanspec);
+ 	int ret;
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index 116a9e559659..bb2c378cf68a 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -194,9 +194,9 @@ static const comedi_lrange *const ni_range_lkup[] = {
+ };
+ 
+ static int ni_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int ni_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int ni_cdio_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+ static int ni_cdio_cmd(comedi_device * dev, comedi_subdevice * s);
+@@ -206,33 +206,33 @@ static int ni_cdo_inttrig(comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int trignum);
+ 
+ static int ni_serial_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int ni_serial_hw_readwrite8(comedi_device * dev, comedi_subdevice * s,
+ 	unsigned char data_out, unsigned char *data_in);
+ static int ni_serial_sw_readwrite8(comedi_device * dev, comedi_subdevice * s,
+ 	unsigned char data_out, unsigned char *data_in);
+ 
+ static int ni_calib_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int ni_calib_insn_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ static int ni_eeprom_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int ni_m_series_eeprom_insn_read(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+ static int ni_pfi_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int ni_pfi_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static unsigned ni_old_get_pfi_routing(comedi_device * dev, unsigned chan);
+ 
+ static void ni_rtsi_init(comedi_device * dev);
+ static int ni_rtsi_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int ni_rtsi_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ static void caldac_setup(comedi_device * dev, comedi_subdevice * s);
+ static int ni_read_eeprom(comedi_device * dev, int addr);
+@@ -268,11 +268,11 @@ static int ni_ao_reset(comedi_device * dev, comedi_subdevice * s);
+ static int ni_8255_callback(int dir, int port, int data, unsigned long arg);
+ 
+ static int ni_gpct_insn_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int ni_gpct_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int ni_gpct_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int ni_gpct_cmd(comedi_device * dev, comedi_subdevice * s);
+ static int ni_gpct_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+@@ -283,7 +283,7 @@ static void handle_gpct_interrupt(comedi_device * dev,
+ static int init_cs5529(comedi_device * dev);
+ static int cs5529_do_conversion(comedi_device * dev, unsigned short *data);
+ static int cs5529_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ #ifdef NI_CS5529_DEBUG
+ static unsigned int cs5529_config_read(comedi_device * dev,
+ 	unsigned int reg_select_bits);
+@@ -292,9 +292,9 @@ static void cs5529_config_write(comedi_device * dev, unsigned int value,
+ 	unsigned int reg_select_bits);
+ 
+ static int ni_m_series_pwm_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int ni_6143_pwm_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ static int ni_set_master_clock(comedi_device * dev, unsigned source,
+ 	unsigned period_ns);
+@@ -1210,7 +1210,7 @@ static void ni_ao_fifo_load(comedi_device * dev, comedi_subdevice * s, int n)
+ 	comedi_cmd *cmd = &async->cmd;
+ 	int chan;
+ 	int i;
+-	sampl_t d;
++	short d;
+ 	u32 packed_data;
+ 	int range;
+ 	int err = 1;
+@@ -1273,7 +1273,7 @@ static int ni_ao_fifo_half_empty(comedi_device * dev, comedi_subdevice * s)
+ 		return 0;
+ 	}
+ 
+-	n /= sizeof(sampl_t);
++	n /= sizeof(short);
+ 	if (n > boardtype.ao_fifo_depth / 2)
+ 		n = boardtype.ao_fifo_depth / 2;
+ 
+@@ -1298,7 +1298,7 @@ static int ni_ao_prep_fifo(comedi_device * dev, comedi_subdevice * s)
+ 	if (n == 0)
+ 		return 0;
+ 
+-	n /= sizeof(sampl_t);
++	n /= sizeof(short);
+ 	if (n > boardtype.ao_fifo_depth)
+ 		n = boardtype.ao_fifo_depth;
+ 
+@@ -1313,7 +1313,7 @@ static void ni_ai_fifo_read(comedi_device * dev, comedi_subdevice * s, int n)
+ 	int i;
+ 
+ 	if (boardtype.reg_type == ni_reg_611x) {
+-		sampl_t data[2];
++		short data[2];
+ 		u32 dl;
+ 
+ 		for (i = 0; i < n / 2; i++) {
+@@ -1330,7 +1330,7 @@ static void ni_ai_fifo_read(comedi_device * dev, comedi_subdevice * s, int n)
+ 			cfc_write_to_buffer(s, data[0]);
+ 		}
+ 	} else if (boardtype.reg_type == ni_reg_6143) {
+-		sampl_t data[2];
++		short data[2];
+ 		u32 dl;
+ 
+ 		// This just reads the FIFO assuming the data is present, no checks on the FIFO status are performed
+@@ -1417,7 +1417,7 @@ static int ni_ai_drain_dma(comedi_device * dev)
+ static void ni_handle_fifo_dregs(comedi_device * dev)
+ {
+ 	comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+-	sampl_t data[2];
++	short data[2];
+ 	u32 dl;
+ 	short fifo_empty;
+ 	int i;
+@@ -1479,7 +1479,7 @@ static void ni_handle_fifo_dregs(comedi_device * dev)
+ static void get_last_sample_611x(comedi_device * dev)
+ {
+ 	comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+-	sampl_t data;
++	short data;
+ 	u32 dl;
+ 
+ 	if (boardtype.reg_type != ni_reg_611x)
+@@ -1496,7 +1496,7 @@ static void get_last_sample_611x(comedi_device * dev)
+ static void get_last_sample_6143(comedi_device * dev)
+ {
+ 	comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
+-	sampl_t data;
++	short data;
+ 	u32 dl;
+ 
+ 	if (boardtype.reg_type != ni_reg_6143)
+@@ -1519,8 +1519,8 @@ static void ni_ai_munge(comedi_device * dev, comedi_subdevice * s,
+ 	comedi_async *async = s->async;
+ 	unsigned int i;
+ 	unsigned int length = num_bytes / bytes_per_sample(s);
+-	sampl_t *array = data;
+-	lsampl_t *larray = data;
++	short *array = data;
++	unsigned int *larray = data;
+ 	for (i = 0; i < length; i++) {
+ #ifdef PCIDMA
+ 		if (s->subdev_flags & SDF_LSAMPL)
+@@ -1719,7 +1719,7 @@ static int ni_ai_poll(comedi_device * dev, comedi_subdevice * s)
+ }
+ 
+ static int ni_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+ 	const unsigned int mask = (1 << boardtype.adbits) - 1;
+@@ -2626,10 +2626,10 @@ static int ni_ai_inttrig(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int ni_ai_config_analog_trig(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ static int ni_ai_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n < 1)
+ 		return -EINVAL;
+@@ -2680,7 +2680,7 @@ static int ni_ai_insn_config(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int ni_ai_config_analog_trig(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int a, b, modebits;
+ 	int err = 0;
+@@ -2784,8 +2784,8 @@ static void ni_ao_munge(comedi_device * dev, comedi_subdevice * s,
+ 	unsigned int range;
+ 	unsigned int i;
+ 	unsigned int offset;
+-	unsigned int length = num_bytes / sizeof(sampl_t);
+-	sampl_t *array = data;
++	unsigned int length = num_bytes / sizeof(short);
++	short *array = data;
+ 
+ 	offset = 1 << (boardtype.aobits - 1);
+ 	for (i = 0; i < length; i++) {
+@@ -2922,7 +2922,7 @@ static int ni_ao_config_chanlist(comedi_device * dev, comedi_subdevice * s,
+ 		return ni_old_ao_config_chanlist(dev, s, chanspec, n_chans);
+ }
+ static int ni_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->ao[CR_CHAN(insn->chanspec)];
+ 
+@@ -2930,7 +2930,7 @@ static int ni_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int ni_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int chan = CR_CHAN(insn->chanspec);
+ 	unsigned int invert;
+@@ -2949,7 +2949,7 @@ static int ni_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int ni_ao_insn_write_671x(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int chan = CR_CHAN(insn->chanspec);
+ 	unsigned int invert;
+@@ -2966,14 +2966,14 @@ static int ni_ao_insn_write_671x(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int ni_ao_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+ 	case INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE:
+ 		switch(data[1])
+ 		{
+ 		case COMEDI_OUTPUT:
+-			data[2] = 1 + boardtype.ao_fifo_depth * sizeof(sampl_t);
++			data[2] = 1 + boardtype.ao_fifo_depth * sizeof(short);
+ 			if(devpriv->mite) data[2] += devpriv->mite->fifo_size;
+ 			break;
+ 		case COMEDI_INPUT:
+@@ -3437,7 +3437,7 @@ static int ni_ao_reset(comedi_device * dev, comedi_subdevice * s)
+ // digital io
+ 
+ static int ni_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ #ifdef DEBUG_DIO
+ 	rt_printk("ni_dio_insn_config() chan=%d io=%d\n",
+@@ -3469,7 +3469,7 @@ static int ni_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int ni_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ #ifdef DEBUG_DIO
+ 	rt_printk("ni_dio_insn_bits() mask=0x%x bits=0x%x\n", data[0], data[1]);
+@@ -3496,7 +3496,7 @@ static int ni_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int ni_m_series_dio_insn_config(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ #ifdef DEBUG_DIO
+ 	rt_printk("ni_m_series_dio_insn_config() chan=%d io=%d\n",
+@@ -3526,7 +3526,7 @@ static int ni_m_series_dio_insn_config(comedi_device * dev,
+ }
+ 
+ static int ni_m_series_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ #ifdef DEBUG_DIO
+ 	rt_printk("ni_m_series_dio_insn_bits() mask=0x%x bits=0x%x\n", data[0],
+@@ -3791,7 +3791,7 @@ static void handle_cdio_interrupt(comedi_device * dev)
+ }
+ 
+ static int ni_serial_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int err = insn->n;
+ 	unsigned char byte_out, byte_in = 0;
+@@ -4209,14 +4209,14 @@ static unsigned ni_gpct_read_register(struct ni_gpct *counter,
+ }
+ 
+ static int ni_freq_out_insn_read(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->clock_and_fout & FOUT_Divider_mask;
+ 	return 1;
+ }
+ 
+ static int ni_freq_out_insn_write(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	devpriv->clock_and_fout &= ~FOUT_Enable;
+ 	devpriv->stc_writew(dev, devpriv->clock_and_fout,
+@@ -4229,7 +4229,7 @@ static int ni_freq_out_insn_write(comedi_device * dev,
+ 	return insn->n;
+ }
+ 
+-static int ni_set_freq_out_clock(comedi_device * dev, lsampl_t clock_source)
++static int ni_set_freq_out_clock(comedi_device * dev, unsigned int clock_source)
+ {
+ 	switch (clock_source) {
+ 	case NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC:
+@@ -4246,8 +4246,8 @@ static int ni_set_freq_out_clock(comedi_device * dev, lsampl_t clock_source)
+ 	return 3;
+ }
+ 
+-static void ni_get_freq_out_clock(comedi_device * dev, lsampl_t * clock_source,
+-	lsampl_t * clock_period_ns)
++static void ni_get_freq_out_clock(comedi_device * dev, unsigned int * clock_source,
++	unsigned int * clock_period_ns)
+ {
+ 	if (devpriv->clock_and_fout & FOUT_Timebase_Select) {
+ 		*clock_source = NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC;
+@@ -4259,7 +4259,7 @@ static void ni_get_freq_out_clock(comedi_device * dev, lsampl_t * clock_source,
+ }
+ 
+ static int ni_freq_out_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+ 	case INSN_CONFIG_SET_CLOCK_SRC:
+@@ -4624,7 +4624,7 @@ static int ni_8255_callback(int dir, int port, int data, unsigned long arg)
+ */
+ 
+ static int ni_eeprom_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = ni_read_eeprom(dev, CR_CHAN(insn->chanspec));
+ 
+@@ -4660,14 +4660,14 @@ static int ni_read_eeprom(comedi_device * dev, int addr)
+ }
+ 
+ static int ni_m_series_eeprom_insn_read(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->eeprom_buffer[CR_CHAN(insn->chanspec)];
+ 
+ 	return 1;
+ }
+ 
+-static int ni_get_pwm_config(comedi_device * dev, lsampl_t * data)
++static int ni_get_pwm_config(comedi_device * dev, unsigned int * data)
+ {
+ 	data[1] = devpriv->pwm_up_count * devpriv->clock_ns;
+ 	data[2] = devpriv->pwm_down_count * devpriv->clock_ns;
+@@ -4675,7 +4675,7 @@ static int ni_get_pwm_config(comedi_device * dev, lsampl_t * data)
+ }
+ 
+ static int ni_m_series_pwm_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned up_count, down_count;
+ 	switch (data[0]) {
+@@ -4740,7 +4740,7 @@ static int ni_m_series_pwm_config(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int ni_6143_pwm_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned up_count, down_count;
+ 	switch (data[0]) {
+@@ -4807,7 +4807,7 @@ static void ni_write_caldac(comedi_device * dev, int addr, int val);
+ 	calibration subdevice
+ */
+ static int ni_calib_insn_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	ni_write_caldac(dev, CR_CHAN(insn->chanspec), data[0]);
+ 
+@@ -4815,7 +4815,7 @@ static int ni_calib_insn_write(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int ni_calib_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	data[0] = devpriv->caldacs[CR_CHAN(insn->chanspec)];
+ 
+@@ -5071,21 +5071,21 @@ static void GPCT_Reset(comedi_device * dev, int chan)
+ #endif
+ 
+ static int ni_gpct_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	struct ni_gpct *counter = s->private;
+ 	return ni_tio_insn_config(counter, insn, data);
+ }
+ 
+ static int ni_gpct_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	struct ni_gpct *counter = s->private;
+ 	return ni_tio_rinsn(counter, insn, data);
+ }
+ 
+ static int ni_gpct_insn_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	struct ni_gpct *counter = s->private;
+ 	return ni_tio_winsn(counter, insn, data);
+@@ -5254,7 +5254,7 @@ static int ni_config_filter(comedi_device * dev, unsigned pfi_channel,
+ }
+ 
+ static int ni_pfi_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if ((boardtype.reg_type & ni_reg_m_series_mask) == 0) {
+ 		return -ENOTSUPP;
+@@ -5269,7 +5269,7 @@ static int ni_pfi_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int ni_pfi_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int chan;
+ 
+@@ -5346,7 +5346,7 @@ static void ni_rtsi_init(comedi_device * dev)
+ }
+ 
+ static int ni_rtsi_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -5627,7 +5627,7 @@ static unsigned ni_get_rtsi_routing(comedi_device * dev, unsigned chan)
+ }
+ 
+ static int ni_rtsi_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int chan = CR_CHAN(insn->chanspec);
+ 	switch (data[0]) {
+@@ -5806,7 +5806,7 @@ static int cs5529_do_conversion(comedi_device * dev, unsigned short *data)
+ }
+ 
+ static int cs5529_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, retval;
+ 	unsigned short sample;
+diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
+index a3e12212e427..289d7b921513 100644
+--- a/drivers/staging/comedi/drivers/ni_pcidio.c
++++ b/drivers/staging/comedi/drivers/ni_pcidio.c
+@@ -486,8 +486,8 @@ static irqreturn_t nidio_interrupt(int irq, void *d PT_REGS_ARG)
+ 
+ 	//int i, j;
+ 	long int AuxData = 0;
+-	sampl_t data1 = 0;
+-	sampl_t data2 = 0;
++	short data1 = 0;
++	short data2 = 0;
+ 	int flags;
+ 	int status;
+ 	int work = 0;
+@@ -703,7 +703,7 @@ static void debug_int(comedi_device * dev)
+ #endif
+ 
+ static int ni_pcidio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 1)
+ 		return -EINVAL;
+@@ -730,7 +730,7 @@ static int ni_pcidio_insn_config(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int ni_pcidio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h
+index 0c869ada3062..d76ef024131d 100644
+--- a/drivers/staging/comedi/drivers/ni_stc.h
++++ b/drivers/staging/comedi/drivers/ni_stc.h
+@@ -1482,7 +1482,7 @@ typedef struct ni_board_struct {
+ 	unsigned short pwm_up_count;	\
+ 	unsigned short pwm_down_count;	\
+ 	\
+-	sampl_t ai_fifo_buffer[0x2000];				\
++	short ai_fifo_buffer[0x2000];				\
+ 	uint8_t eeprom_buffer[M_SERIES_EEPROM_SIZE]; \
+ 	uint32_t serial_number; \
+ 	\
+diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c
+index f2fd095c4576..efa9cf5546f5 100644
+--- a/drivers/staging/comedi/drivers/ni_tio.c
++++ b/drivers/staging/comedi/drivers/ni_tio.c
+@@ -262,7 +262,7 @@ static inline unsigned NI_660x_RTSI_Second_Gate_Select(unsigned n)
+ 	return 0xb + n;
+ }
+ 
+-static const lsampl_t counter_status_mask =
++static const unsigned int counter_status_mask =
+ 	COMEDI_COUNTER_ARMED | COMEDI_COUNTER_COUNTING;
+ 
+ static int __init ni_tio_init_module(void)
+@@ -388,9 +388,9 @@ void ni_tio_init_counter(struct ni_gpct *counter)
+ 		NITIO_Gi_Interrupt_Enable_Reg(counter->counter_index), ~0, 0x0);
+ }
+ 
+-static lsampl_t ni_tio_counter_status(struct ni_gpct *counter)
++static unsigned int ni_tio_counter_status(struct ni_gpct *counter)
+ {
+-	lsampl_t status = 0;
++	unsigned int status = 0;
+ 	const unsigned bits = read_register(counter,
+ 		NITIO_Gxx_Status_Reg(counter->counter_index));
+ 	if (bits & Gi_Armed_Bit(counter->counter_index)) {
+@@ -564,7 +564,7 @@ int ni_tio_arm(struct ni_gpct *counter, int arm, unsigned start_trigger)
+ 	return 0;
+ }
+ 
+-static unsigned ni_660x_source_select_bits(lsampl_t clock_source)
++static unsigned ni_660x_source_select_bits(unsigned int clock_source)
+ {
+ 	unsigned ni_660x_clock;
+ 	unsigned i;
+@@ -618,7 +618,7 @@ static unsigned ni_660x_source_select_bits(lsampl_t clock_source)
+ 	return Gi_Source_Select_Bits(ni_660x_clock);
+ }
+ 
+-static unsigned ni_m_series_source_select_bits(lsampl_t clock_source)
++static unsigned ni_m_series_source_select_bits(unsigned int clock_source)
+ {
+ 	unsigned ni_m_series_clock;
+ 	unsigned i;
+@@ -679,7 +679,7 @@ static unsigned ni_m_series_source_select_bits(lsampl_t clock_source)
+ };
+ 
+ static void ni_tio_set_source_subselect(struct ni_gpct *counter,
+-	lsampl_t clock_source)
++	unsigned int clock_source)
+ {
+ 	struct ni_gpct_device *counter_dev = counter->counter_dev;
+ 	const unsigned second_gate_reg =
+@@ -708,7 +708,7 @@ static void ni_tio_set_source_subselect(struct ni_gpct *counter,
+ }
+ 
+ static int ni_tio_set_clock_src(struct ni_gpct *counter,
+-	lsampl_t clock_source, lsampl_t period_ns)
++	unsigned int clock_source, unsigned int period_ns)
+ {
+ 	struct ni_gpct_device *counter_dev = counter->counter_dev;
+ 	unsigned input_select_bits = 0;
+@@ -965,7 +965,7 @@ static uint64_t ni_tio_clock_period_ps(const struct ni_gpct *counter,
+ }
+ 
+ static void ni_tio_get_clock_src(struct ni_gpct *counter,
+-	lsampl_t * clock_source, lsampl_t * period_ns)
++	unsigned int * clock_source, unsigned int * period_ns)
+ {
+ 	static const unsigned pico_per_nano = 1000;
+ 	uint64_t temp64;
+@@ -976,7 +976,7 @@ static void ni_tio_get_clock_src(struct ni_gpct *counter,
+ }
+ 
+ static void ni_tio_set_first_gate_modifiers(struct ni_gpct *counter,
+-	lsampl_t gate_source)
++	unsigned int gate_source)
+ {
+ 	const unsigned mode_mask = Gi_Gate_Polarity_Bit | Gi_Gating_Mode_Mask;
+ 	unsigned mode_values = 0;
+@@ -993,7 +993,7 @@ static void ni_tio_set_first_gate_modifiers(struct ni_gpct *counter,
+ 		mode_mask, mode_values);
+ }
+ 
+-static int ni_660x_set_first_gate(struct ni_gpct *counter, lsampl_t gate_source)
++static int ni_660x_set_first_gate(struct ni_gpct *counter, unsigned int gate_source)
+ {
+ 	const unsigned selected_gate = CR_CHAN(gate_source);
+ 	/* bits of selected_gate that may be meaningful to input select register */
+@@ -1040,7 +1040,7 @@ static int ni_660x_set_first_gate(struct ni_gpct *counter, lsampl_t gate_source)
+ }
+ 
+ static int ni_m_series_set_first_gate(struct ni_gpct *counter,
+-	lsampl_t gate_source)
++	unsigned int gate_source)
+ {
+ 	const unsigned selected_gate = CR_CHAN(gate_source);
+ 	/* bits of selected_gate that may be meaningful to input select register */
+@@ -1089,7 +1089,7 @@ static int ni_m_series_set_first_gate(struct ni_gpct *counter,
+ }
+ 
+ static int ni_660x_set_second_gate(struct ni_gpct *counter,
+-	lsampl_t gate_source)
++	unsigned int gate_source)
+ {
+ 	struct ni_gpct_device *counter_dev = counter->counter_dev;
+ 	const unsigned second_gate_reg =
+@@ -1148,7 +1148,7 @@ static int ni_660x_set_second_gate(struct ni_gpct *counter,
+ }
+ 
+ static int ni_m_series_set_second_gate(struct ni_gpct *counter,
+-	lsampl_t gate_source)
++	unsigned int gate_source)
+ {
+ 	struct ni_gpct_device *counter_dev = counter->counter_dev;
+ 	const unsigned second_gate_reg =
+@@ -1176,7 +1176,7 @@ static int ni_m_series_set_second_gate(struct ni_gpct *counter,
+ }
+ 
+ int ni_tio_set_gate_src(struct ni_gpct *counter, unsigned gate_index,
+-	lsampl_t gate_source)
++	unsigned int gate_source)
+ {
+ 	struct ni_gpct_device *counter_dev = counter->counter_dev;
+ 	const unsigned second_gate_reg =
+@@ -1243,7 +1243,7 @@ int ni_tio_set_gate_src(struct ni_gpct *counter, unsigned gate_index,
+ }
+ 
+ static int ni_tio_set_other_src(struct ni_gpct *counter, unsigned index,
+-	lsampl_t source)
++	unsigned int source)
+ {
+ 	struct ni_gpct_device *counter_dev = counter->counter_dev;
+ 
+@@ -1442,7 +1442,7 @@ static unsigned ni_m_series_second_gate_to_generic_gate_source(unsigned
+ };
+ 
+ static int ni_tio_get_gate_src(struct ni_gpct *counter, unsigned gate_index,
+-	lsampl_t * gate_source)
++	unsigned int * gate_source)
+ {
+ 	struct ni_gpct_device *counter_dev = counter->counter_dev;
+ 	const unsigned mode_bits = ni_tio_get_soft_copy(counter,
+@@ -1534,7 +1534,7 @@ static int ni_tio_get_gate_src(struct ni_gpct *counter, unsigned gate_index,
+ }
+ 
+ int ni_tio_insn_config(struct ni_gpct *counter,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	switch (data[0]) {
+ 	case INSN_CONFIG_SET_COUNTER_MODE:
+@@ -1578,7 +1578,7 @@ int ni_tio_insn_config(struct ni_gpct *counter,
+ 	return -EINVAL;
+ }
+ 
+-int ni_tio_rinsn(struct ni_gpct *counter, comedi_insn * insn, lsampl_t * data)
++int ni_tio_rinsn(struct ni_gpct *counter, comedi_insn * insn, unsigned int * data)
+ {
+ 	struct ni_gpct_device *counter_dev = counter->counter_dev;
+ 	const unsigned channel = CR_CHAN(insn->chanspec);
+@@ -1642,7 +1642,7 @@ static unsigned ni_tio_next_load_register(struct ni_gpct *counter)
+ 	}
+ }
+ 
+-int ni_tio_winsn(struct ni_gpct *counter, comedi_insn * insn, lsampl_t * data)
++int ni_tio_winsn(struct ni_gpct *counter, comedi_insn * insn, unsigned int * data)
+ {
+ 	struct ni_gpct_device *counter_dev = counter->counter_dev;
+ 	const unsigned channel = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/ni_tio.h b/drivers/staging/comedi/drivers/ni_tio.h
+index 46c632977d68..39f85ec8485b 100644
+--- a/drivers/staging/comedi/drivers/ni_tio.h
++++ b/drivers/staging/comedi/drivers/ni_tio.h
+@@ -140,11 +140,11 @@ extern struct ni_gpct_device *ni_gpct_device_construct(comedi_device * dev,
+ extern void ni_gpct_device_destroy(struct ni_gpct_device *counter_dev);
+ extern void ni_tio_init_counter(struct ni_gpct *counter);
+ extern int ni_tio_rinsn(struct ni_gpct *counter,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ extern int ni_tio_insn_config(struct ni_gpct *counter,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ extern int ni_tio_winsn(struct ni_gpct *counter,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ extern int ni_tio_cmd(struct ni_gpct *counter, comedi_async * async);
+ extern int ni_tio_cmdtest(struct ni_gpct *counter, comedi_cmd * cmd);
+ extern int ni_tio_cancel(struct ni_gpct *counter);
+diff --git a/drivers/staging/comedi/drivers/ni_tio_internal.h b/drivers/staging/comedi/drivers/ni_tio_internal.h
+index e5aa578f6c4e..ac5b171cbe18 100644
+--- a/drivers/staging/comedi/drivers/ni_tio_internal.h
++++ b/drivers/staging/comedi/drivers/ni_tio_internal.h
+@@ -769,6 +769,6 @@ static inline unsigned ni_tio_get_soft_copy(const struct ni_gpct *counter,
+ 
+ int ni_tio_arm(struct ni_gpct *counter, int arm, unsigned start_trigger);
+ int ni_tio_set_gate_src(struct ni_gpct *counter, unsigned gate_index,
+-	lsampl_t gate_source);
++	unsigned int gate_source);
+ 
+ #endif /* _COMEDI_NI_TIO_INTERNAL_H */
+diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c
+index 15491745288b..d54e55fe963f 100644
+--- a/drivers/staging/comedi/drivers/pcl711.c
++++ b/drivers/staging/comedi/drivers/pcl711.c
+@@ -174,7 +174,7 @@ typedef struct {
+ 	int ntrig;
+ 	int aip[8];
+ 	int mode;
+-	lsampl_t ao_readback[2];
++	unsigned int ao_readback[2];
+ 	unsigned int divisor1;
+ 	unsigned int divisor2;
+ } pcl711_private;
+@@ -241,7 +241,7 @@ static void pcl711_set_changain(comedi_device * dev, int chan)
+ }
+ 
+ static int pcl711_ai_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, n;
+ 	int hi, lo;
+@@ -428,7 +428,7 @@ static int pcl711_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+    analog output
+ */
+ static int pcl711_ao_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -446,7 +446,7 @@ static int pcl711_ao_insn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int pcl711_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -461,7 +461,7 @@ static int pcl711_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 
+ /* Digital port read - Untested on 8112 */
+ static int pcl711_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -474,7 +474,7 @@ static int pcl711_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 
+ /* Digital port write - Untested on 8112 */
+ static int pcl711_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/pcl725.c b/drivers/staging/comedi/drivers/pcl725.c
+index b4e37098a6c3..a252defade5b 100644
+--- a/drivers/staging/comedi/drivers/pcl725.c
++++ b/drivers/staging/comedi/drivers/pcl725.c
+@@ -32,7 +32,7 @@ static comedi_driver driver_pcl725 = {
+ COMEDI_INITCLEANUP(driver_pcl725);
+ 
+ static int pcl725_do_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -49,7 +49,7 @@ static int pcl725_do_insn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int pcl725_di_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c
+index 48502660c077..61097184e3cc 100644
+--- a/drivers/staging/comedi/drivers/pcl726.c
++++ b/drivers/staging/comedi/drivers/pcl726.c
+@@ -164,12 +164,12 @@ COMEDI_INITCLEANUP(driver_pcl726);
+ typedef struct {
+ 	int bipolar[12];
+ 	const comedi_lrange *rangelist[12];
+-	lsampl_t ao_readback[12];
++	unsigned int ao_readback[12];
+ } pcl726_private;
+ #define devpriv ((pcl726_private *)dev->private)
+ 
+ static int pcl726_ao_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int hi, lo;
+ 	int n;
+@@ -194,7 +194,7 @@ static int pcl726_ao_insn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int pcl726_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	int n;
+@@ -206,7 +206,7 @@ static int pcl726_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int pcl726_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -218,7 +218,7 @@ static int pcl726_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int pcl726_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c
+index 290a32f508fa..a33ff0850c48 100644
+--- a/drivers/staging/comedi/drivers/pcl730.c
++++ b/drivers/staging/comedi/drivers/pcl730.c
+@@ -56,7 +56,7 @@ static comedi_driver driver_pcl730 = {
+ COMEDI_INITCLEANUP(driver_pcl730);
+ 
+ static int pcl730_do_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -78,7 +78,7 @@ static int pcl730_do_insn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int pcl730_di_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
+index 5554950632d0..b3d24cb588a0 100644
+--- a/drivers/staging/comedi/drivers/pcl812.c
++++ b/drivers/staging/comedi/drivers/pcl812.c
+@@ -406,7 +406,7 @@ typedef struct {
+ 	unsigned int ai_n_chan;	// how many channels is measured
+ 	unsigned int ai_flags;	// flaglist
+ 	unsigned int ai_data_len;	// len of data buffer
+-	sampl_t *ai_data;	// data buffer
++	short *ai_data;	// data buffer
+ 	unsigned int ai_is16b;	// =1 we have 16 bit card
+ 	unsigned long dmabuf[2];	// PTR to DMA buf
+ 	unsigned int dmapages[2];	// how many pages we have allocated
+@@ -417,7 +417,7 @@ typedef struct {
+ 	unsigned int dma_runs_to_end;	// how many times we must switch DMA buffers
+ 	unsigned int last_dma_run;	// how many bytes to transfer on last DMA buffer
+ 	unsigned int max_812_ai_mode0_rangewait;	// setling time for gain
+-	lsampl_t ao_readback[2];	// data for AO readback
++	unsigned int ao_readback[2];	// data for AO readback
+ } pcl812_private;
+ 
+ #define devpriv ((pcl812_private *)dev->private)
+@@ -434,7 +434,7 @@ static int pcl812_ai_cancel(comedi_device * dev, comedi_subdevice * s);
+ ==============================================================================
+ */
+ static int pcl812_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int timeout, hi;
+@@ -468,7 +468,7 @@ static int pcl812_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+ */
+ static int acl8216_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int timeout;
+@@ -504,7 +504,7 @@ static int acl8216_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+ */
+ static int pcl812_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	int i;
+@@ -524,7 +524,7 @@ static int pcl812_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+ */
+ static int pcl812_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	int i;
+@@ -540,7 +540,7 @@ static int pcl812_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+ */
+ static int pcl812_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -555,7 +555,7 @@ static int pcl812_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ ==============================================================================
+ */
+ static int pcl812_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -846,9 +846,9 @@ static int pcl812_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ 	if (devpriv->ai_dma) {
+ 		if (devpriv->ai_eos) {	// we use EOS, so adapt DMA buffer to one scan
+ 			devpriv->dmabytestomove[0] =
+-				devpriv->ai_n_chan * sizeof(sampl_t);
++				devpriv->ai_n_chan * sizeof(short);
+ 			devpriv->dmabytestomove[1] =
+-				devpriv->ai_n_chan * sizeof(sampl_t);
++				devpriv->ai_n_chan * sizeof(short);
+ 			devpriv->dma_runs_to_end = 1;
+ 		} else {
+ 			devpriv->dmabytestomove[0] = devpriv->hwdmasize[0];
+@@ -862,7 +862,7 @@ static int pcl812_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ 			if (devpriv->ai_neverending) {
+ 				devpriv->dma_runs_to_end = 1;
+ 			} else {
+-				bytes = devpriv->ai_n_chan * devpriv->ai_scans * sizeof(sampl_t);	// how many samples we must transfer?
++				bytes = devpriv->ai_n_chan * devpriv->ai_scans * sizeof(short);	// how many samples we must transfer?
+ 				devpriv->dma_runs_to_end = bytes / devpriv->dmabytestomove[0];	// how many DMA pages we must fill
+ 				devpriv->last_dma_run = bytes % devpriv->dmabytestomove[0];	//on last dma transfer must be moved
+ 				if (devpriv->dma_runs_to_end == 0)
+@@ -981,7 +981,7 @@ static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d)
+ ==============================================================================
+ */
+ static void transfer_from_dma_buf(comedi_device * dev, comedi_subdevice * s,
+-	sampl_t * ptr, unsigned int bufptr, unsigned int len)
++	short * ptr, unsigned int bufptr, unsigned int len)
+ {
+ 	unsigned int i;
+ 
+@@ -1012,12 +1012,12 @@ static irqreturn_t interrupt_pcl812_ai_dma(int irq, void *d)
+ 	comedi_subdevice *s = dev->subdevices + 0;
+ 	unsigned long dma_flags;
+ 	int len, bufptr;
+-	sampl_t *ptr;
++	short *ptr;
+ 
+ #ifdef PCL812_EXTDEBUG
+ 	rt_printk("pcl812 EDBG: BGN: interrupt_pcl812_ai_dma(...)\n");
+ #endif
+-	ptr = (sampl_t *) devpriv->dmabuf[devpriv->next_dma_buf];
++	ptr = (short *) devpriv->dmabuf[devpriv->next_dma_buf];
+ 	len = (devpriv->dmabytestomove[devpriv->next_dma_buf] >> 1) -
+ 		devpriv->ai_poll_ptr;
+ 
+diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
+index e361f9dc5246..cb795736300d 100644
+--- a/drivers/staging/comedi/drivers/pcl816.c
++++ b/drivers/staging/comedi/drivers/pcl816.c
+@@ -227,7 +227,7 @@ static int pcl816_ai_cmd(comedi_device * dev, comedi_subdevice * s);
+    ANALOG INPUT MODE0, 816 cards, slow version
+ */
+ static int pcl816_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int timeout;
+@@ -331,7 +331,7 @@ static irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d)
+    analog input dma mode 1 & 3, 816 cards
+ */
+ static void transfer_from_dma_buf(comedi_device * dev, comedi_subdevice * s,
+-	sampl_t * ptr, unsigned int bufptr, unsigned int len)
++	short * ptr, unsigned int bufptr, unsigned int len)
+ {
+ 	int i;
+ 
+@@ -365,7 +365,7 @@ static irqreturn_t interrupt_pcl816_ai_mode13_dma(int irq, void *d)
+ 	comedi_subdevice *s = dev->subdevices + 0;
+ 	int len, bufptr, this_dma_buf;
+ 	unsigned long dma_flags;
+-	sampl_t *ptr;
++	short *ptr;
+ 
+ 	disable_dma(devpriv->dma);
+ 	this_dma_buf = devpriv->next_dma_buf;
+@@ -391,7 +391,7 @@ static irqreturn_t interrupt_pcl816_ai_mode13_dma(int irq, void *d)
+ 	devpriv->dma_runs_to_end--;
+ 	outb(0, dev->iobase + PCL816_CLRINT);	/* clear INT request */
+ 
+-	ptr = (sampl_t *) devpriv->dmabuf[this_dma_buf];
++	ptr = (short *) devpriv->dmabuf[this_dma_buf];
+ 
+ 	len = (devpriv->hwdmasize[0] >> 1) - devpriv->ai_poll_ptr;
+ 	bufptr = devpriv->ai_poll_ptr;
+@@ -658,7 +658,7 @@ static int pcl816_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ 	if (devpriv->dma) {
+ 		bytes = devpriv->hwdmasize[0];
+ 		if (!devpriv->ai_neverending) {
+-			bytes = s->async->cmd.chanlist_len * s->async->cmd.chanlist_len * sizeof(sampl_t);	// how many
++			bytes = s->async->cmd.chanlist_len * s->async->cmd.chanlist_len * sizeof(short);	// how many
+ 			devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize[0];	// how many DMA pages we must fill
+ 			devpriv->last_dma_run = bytes % devpriv->hwdmasize[0];	//on last dma transfer must be moved
+ 			devpriv->dma_runs_to_end--;
+@@ -728,7 +728,7 @@ static int pcl816_ai_poll(comedi_device * dev, comedi_subdevice * s)
+ 	}
+ 
+ 	transfer_from_dma_buf(dev, s,
+-		(sampl_t *) devpriv->dmabuf[devpriv->next_dma_buf],
++		(short *) devpriv->dmabuf[devpriv->next_dma_buf],
+ 		devpriv->ai_poll_ptr, top2);
+ 
+ 	devpriv->ai_poll_ptr = top1;	// new buffer position
+diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
+index 9e648c3cc12e..5425c196bed1 100644
+--- a/drivers/staging/comedi/drivers/pcl818.c
++++ b/drivers/staging/comedi/drivers/pcl818.c
+@@ -350,12 +350,12 @@ typedef struct {
+ 	unsigned int *ai_chanlist;	// actaul chanlist
+ 	unsigned int ai_flags;	// flaglist
+ 	unsigned int ai_data_len;	// len of data buffer
+-	sampl_t *ai_data;	// data buffer
++	short *ai_data;	// data buffer
+ 	unsigned int ai_timer1;	// timers
+ 	unsigned int ai_timer2;
+ 	comedi_subdevice *sub_ai;	// ptr to AI subdevice
+ 	unsigned char usefifo;	// 1=use fifo
+-	lsampl_t ao_readback[2];
++	unsigned int ao_readback[2];
+ } pcl818_private;
+ 
+ static const unsigned int muxonechan[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,	// used for gain list programming
+@@ -388,7 +388,7 @@ static int rtc_setfreq_irq(int freq);
+    ANALOG INPUT MODE0, 818 cards, slow version
+ */
+ static int pcl818_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int timeout;
+@@ -435,7 +435,7 @@ static int pcl818_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+    only one sample per call is supported
+ */
+ static int pcl818_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -448,7 +448,7 @@ static int pcl818_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int pcl818_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -471,7 +471,7 @@ static int pcl818_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+    only one sample per call is supported
+ */
+ static int pcl818_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -489,7 +489,7 @@ static int pcl818_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+    only one sample per call is supported
+ */
+ static int pcl818_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -569,7 +569,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
+ 	comedi_subdevice *s = dev->subdevices + 0;
+ 	int i, len, bufptr;
+ 	unsigned long flags;
+-	sampl_t *ptr;
++	short *ptr;
+ 
+ 	disable_dma(devpriv->dma);
+ 	devpriv->next_dma_buf = 1 - devpriv->next_dma_buf;
+@@ -591,7 +591,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
+ 
+ 	devpriv->dma_runs_to_end--;
+ 	outb(0, dev->iobase + PCL818_CLRINT);	/* clear INT request */
+-	ptr = (sampl_t *) devpriv->dmabuf[1 - devpriv->next_dma_buf];
++	ptr = (short *) devpriv->dmabuf[1 - devpriv->next_dma_buf];
+ 
+ 	len = devpriv->hwdmasize[0] >> 1;
+ 	bufptr = 0;
+@@ -645,7 +645,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d)
+ 	unsigned long tmp;
+ 	unsigned int top1, top2, i, bufptr;
+ 	long ofs_dats;
+-	sampl_t *dmabuf = (sampl_t *) devpriv->dmabuf[0];
++	short *dmabuf = (short *) devpriv->dmabuf[0];
+ 
+ 	//outb(2,0x378);
+ 	switch (devpriv->ai_mode) {
+@@ -880,7 +880,7 @@ static void pcl818_ai_mode13dma_int(int mode, comedi_device * dev,
+ 	disable_dma(devpriv->dma);	// disable dma
+ 	bytes = devpriv->hwdmasize[0];
+ 	if (!devpriv->neverending_ai) {
+-		bytes = devpriv->ai_n_chan * devpriv->ai_scans * sizeof(sampl_t);	// how many
++		bytes = devpriv->ai_n_chan * devpriv->ai_scans * sizeof(short);	// how many
+ 		devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize[0];	// how many DMA pages we must fiil
+ 		devpriv->last_dma_run = bytes % devpriv->hwdmasize[0];	//on last dma transfer must be moved
+ 		devpriv->dma_runs_to_end--;
+@@ -915,7 +915,7 @@ static void pcl818_ai_mode13dma_rtc(int mode, comedi_device * dev,
+ 	comedi_subdevice * s)
+ {
+ 	unsigned int flags;
+-	sampl_t *pole;
++	short *pole;
+ 
+ 	set_dma_mode(devpriv->dma, DMA_MODE_READ | DMA_AUTOINIT);
+ 	flags = claim_dma_lock();
+@@ -925,7 +925,7 @@ static void pcl818_ai_mode13dma_rtc(int mode, comedi_device * dev,
+ 	release_dma_lock(flags);
+ 	enable_dma(devpriv->dma);
+ 	devpriv->last_top_dma = 0;	//devpriv->hwdmasize[0];
+-	pole = (sampl_t *) devpriv->dmabuf[0];
++	pole = (short *) devpriv->dmabuf[0];
+ 	devpriv->dmasamplsize = devpriv->hwdmasize[0] / 2;
+ 	pole[devpriv->dmasamplsize - 1] = MAGIC_DMA_WORD;
+ #ifdef unused
+diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c
+index 8e8015bc99f4..c4458442d5be 100644
+--- a/drivers/staging/comedi/drivers/pcm3724.c
++++ b/drivers/staging/comedi/drivers/pcm3724.c
+@@ -215,7 +215,7 @@ static void enable_chan(comedi_device * dev, comedi_subdevice * s, int chanspec)
+ 
+ /* overriding the 8255 insn config */
+ static int subdev_3724_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unsigned int mask;
+ 	unsigned int bits;
+diff --git a/drivers/staging/comedi/drivers/pcm3730.c b/drivers/staging/comedi/drivers/pcm3730.c
+index f633e0db9e8d..1283be635ef8 100644
+--- a/drivers/staging/comedi/drivers/pcm3730.c
++++ b/drivers/staging/comedi/drivers/pcm3730.c
+@@ -40,7 +40,7 @@ static comedi_driver driver_pcm3730 = {
+ COMEDI_INITCLEANUP(driver_pcm3730);
+ 
+ static int pcm3730_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -55,7 +55,7 @@ static int pcm3730_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int pcm3730_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c
+index 9fd6242d8133..1a371da6f828 100644
+--- a/drivers/staging/comedi/drivers/pcmad.c
++++ b/drivers/staging/comedi/drivers/pcmad.c
+@@ -93,7 +93,7 @@ COMEDI_INITCLEANUP(driver_pcmad);
+ #define TIMEOUT	100
+ 
+ static int pcmad_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan;
+diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c
+index 20357d7cbaaa..c8963cdf5a5f 100644
+--- a/drivers/staging/comedi/drivers/pcmda12.c
++++ b/drivers/staging/comedi/drivers/pcmda12.c
+@@ -93,7 +93,7 @@ static const pcmda12_board pcmda12_boards[] = {
+ #define thisboard ((const pcmda12_board *)dev->board_ptr)
+ 
+ typedef struct {
+-	lsampl_t ao_readback[CHANS];
++	unsigned int ao_readback[CHANS];
+ 	int simultaneous_xfer_mode;
+ } pcmda12_private;
+ 
+@@ -139,9 +139,9 @@ static comedi_driver driver = {
+ };
+ 
+ static int ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ /*
+  * Attach is called by the Comedi core to configure the driver
+@@ -240,7 +240,7 @@ static void zero_chans(comedi_device * dev)
+ }
+ 
+ static int ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -282,7 +282,7 @@ static int ao_winsn(comedi_device * dev, comedi_subdevice * s,
+    This is useful for some control applications, I would imagine.
+ */
+ static int ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
+index 5673b664ca20..739959cd2cfd 100644
+--- a/drivers/staging/comedi/drivers/pcmmio.c
++++ b/drivers/staging/comedi/drivers/pcmmio.c
+@@ -140,14 +140,14 @@ Configuration Options:
+ #define PAGE_INT_ID 3
+ 
+ typedef int (*comedi_insn_fn_t) (comedi_device *, comedi_subdevice *,
+-	comedi_insn *, lsampl_t *);
++	comedi_insn *, unsigned int *);
+ 
+ static int ai_rinsn(comedi_device *, comedi_subdevice *, comedi_insn *,
+-	lsampl_t *);
++	unsigned int *);
+ static int ao_rinsn(comedi_device *, comedi_subdevice *, comedi_insn *,
+-	lsampl_t *);
++	unsigned int *);
+ static int ao_winsn(comedi_device *, comedi_subdevice *, comedi_insn *,
+-	lsampl_t *);
++	unsigned int *);
+ 
+ /*
+  * Board descriptions for two imaginary boards.  Describing the
+@@ -230,7 +230,7 @@ typedef struct {
+ 			} intr;
+ 		} dio;
+ 		struct {
+-			lsampl_t shadow_samples[8];	/* the last lsampl_t data written */
++			unsigned int shadow_samples[8];	/* the last unsigned int data written */
+ 		} ao;
+ 	};
+ } pcmmio_subdev_private;
+@@ -296,9 +296,9 @@ static comedi_driver driver = {
+ };
+ 
+ static int pcmmio_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int pcmmio_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ static irqreturn_t interrupt_pcmmio(int irq, void *d PT_REGS_ARG);
+ static void pcmmio_stop_intr(comedi_device *, comedi_subdevice *);
+@@ -551,7 +551,7 @@ static int pcmmio_detach(comedi_device * dev)
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+ static int pcmmio_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int byte_no;
+ 	if (insn->n != 2)
+@@ -625,7 +625,7 @@ static int pcmmio_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+  * contains the channel to be changed, and data[0] contains the
+  * value COMEDI_INPUT or COMEDI_OUTPUT. */
+ static int pcmmio_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec), byte_no = chan / 8, bit_no =
+ 		chan % 8;
+@@ -842,7 +842,7 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d PT_REGS_ARG)
+ 							if (mytrig & subpriv->
+ 								dio.intr.
+ 								enabled_mask) {
+-								lsampl_t val =
++								unsigned int val =
+ 									0;
+ 								unsigned int n,
+ 									ch, len;
+@@ -859,10 +859,10 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d PT_REGS_ARG)
+ 									}
+ 								}
+ 								/* Write the scan to the buffer. */
+-								if (comedi_buf_put(s->async, ((sampl_t *) & val)[0])
++								if (comedi_buf_put(s->async, ((short *) & val)[0])
+ 									&&
+ 									comedi_buf_put
+-									(s->async, ((sampl_t *) & val)[1])) {
++									(s->async, ((short *) & val)[1])) {
+ 									s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS);
+ 								} else {
+ 									/* Overflow! Stop acquisition!! */
+@@ -1195,7 +1195,7 @@ static int adc_wait_ready(unsigned long iobase)
+ 
+ /* All this is for AI and AO */
+ static int ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	unsigned long iobase = subpriv->iobase;
+@@ -1218,7 +1218,7 @@ static int ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 			CR_AREF(insn->chanspec);
+ 		unsigned char command_byte = 0;
+ 		unsigned iooffset = 0;
+-		sampl_t sample, adc_adjust = 0;
++		short sample, adc_adjust = 0;
+ 
+ 		if (chan > 7)
+ 			chan -= 8, iooffset = 4;	/* use the second dword for channels > 7 */
+@@ -1259,7 +1259,7 @@ static int ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	for (n = 0; n < insn->n; n++) {
+@@ -1289,7 +1289,7 @@ static int wait_dac_ready(unsigned long iobase)
+ }
+ 
+ static int ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	unsigned iobase = subpriv->iobase, iooffset = 0;
+diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
+index 8458b054331c..f40f91987e30 100644
+--- a/drivers/staging/comedi/drivers/pcmuio.c
++++ b/drivers/staging/comedi/drivers/pcmuio.c
+@@ -254,9 +254,9 @@ static comedi_driver driver = {
+ };
+ 
+ static int pcmuio_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int pcmuio_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ static irqreturn_t interrupt_pcmuio(int irq, void *d PT_REGS_ARG);
+ static void pcmuio_stop_intr(comedi_device *, comedi_subdevice *);
+@@ -475,7 +475,7 @@ static int pcmuio_detach(comedi_device * dev)
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+ static int pcmuio_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int byte_no;
+ 	if (insn->n != 2)
+@@ -549,7 +549,7 @@ static int pcmuio_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+  * contains the channel to be changed, and data[0] contains the
+  * value COMEDI_INPUT or COMEDI_OUTPUT. */
+ static int pcmuio_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec), byte_no = chan / 8, bit_no =
+ 		chan % 8;
+@@ -764,7 +764,7 @@ static irqreturn_t interrupt_pcmuio(int irq, void *d PT_REGS_ARG)
+ 							if (mytrig & subpriv->
+ 								intr.
+ 								enabled_mask) {
+-								lsampl_t val =
++								unsigned int val =
+ 									0;
+ 								unsigned int n,
+ 									ch, len;
+@@ -781,10 +781,10 @@ static irqreturn_t interrupt_pcmuio(int irq, void *d PT_REGS_ARG)
+ 									}
+ 								}
+ 								/* Write the scan to the buffer. */
+-								if (comedi_buf_put(s->async, ((sampl_t *) & val)[0])
++								if (comedi_buf_put(s->async, ((short *) & val)[0])
+ 									&&
+ 									comedi_buf_put
+-									(s->async, ((sampl_t *) & val)[1])) {
++									(s->async, ((short *) & val)[1])) {
+ 									s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS);
+ 								} else {
+ 									/* Overflow! Stop acquisition!! */
+diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c
+index 19b143fd1dac..d9147d18882d 100644
+--- a/drivers/staging/comedi/drivers/poc.c
++++ b/drivers/staging/comedi/drivers/poc.c
+@@ -44,14 +44,14 @@ Configuration options:
+ static int poc_attach(comedi_device * dev, comedi_devconfig * it);
+ static int poc_detach(comedi_device * dev);
+ static int readback_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ static int dac02_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int pcl733_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int pcl734_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ struct boarddef_struct {
+ 	const char *name;
+@@ -61,11 +61,11 @@ struct boarddef_struct {
+ 	int n_chan;
+ 	int n_bits;
+ 	int (*winsn) (comedi_device *, comedi_subdevice *, comedi_insn *,
+-		lsampl_t *);
++		unsigned int *);
+ 	int (*rinsn) (comedi_device *, comedi_subdevice *, comedi_insn *,
+-		lsampl_t *);
++		unsigned int *);
+ 	int (*insnbits) (comedi_device *, comedi_subdevice *, comedi_insn *,
+-		lsampl_t *);
++		unsigned int *);
+ 	const comedi_lrange *range;
+ };
+ static const struct boarddef_struct boards[] = {
+@@ -140,7 +140,7 @@ static int poc_attach(comedi_device * dev, comedi_devconfig * it)
+ 
+ 	if (alloc_subdevices(dev, 1) < 0)
+ 		return -ENOMEM;
+-	if (alloc_private(dev, sizeof(lsampl_t) * this_board->n_chan) < 0)
++	if (alloc_private(dev, sizeof(unsigned int) * this_board->n_chan) < 0)
+ 		return -ENOMEM;
+ 
+ 	/* analog output subdevice */
+@@ -171,12 +171,12 @@ static int poc_detach(comedi_device * dev)
+ }
+ 
+ static int readback_insn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan;
+ 
+ 	chan = CR_CHAN(insn->chanspec);
+-	data[0] = ((lsampl_t *) dev->private)[chan];
++	data[0] = ((unsigned int *) dev->private)[chan];
+ 
+ 	return 1;
+ }
+@@ -186,14 +186,14 @@ static int readback_insn(comedi_device * dev, comedi_subdevice * s,
+ #define DAC02_MSB(a)	(2 * a + 1)
+ 
+ static int dac02_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int temp;
+ 	int chan;
+ 	int output;
+ 
+ 	chan = CR_CHAN(insn->chanspec);
+-	((lsampl_t *) dev->private)[chan] = data[0];
++	((unsigned int *) dev->private)[chan] = data[0];
+ 	output = data[0];
+ #ifdef wrong
+ 	// convert to complementary binary if range is bipolar
+@@ -209,7 +209,7 @@ static int dac02_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int pcl733_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -223,7 +223,7 @@ static int pcl733_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int pcl734_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+index 04fe5e397b55..ac34c5183c0c 100644
+--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
++++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+@@ -313,7 +313,7 @@ static void daqp_interrupt(int irq, void *dev_id PT_REGS_ARG)
+ 		while (!((status = inb(dev->iobase + DAQP_STATUS))
+ 				& DAQP_STATUS_FIFO_EMPTY)) {
+ 
+-			sampl_t data;
++			short data;
+ 
+ 			if (status & DAQP_STATUS_DATA_LOST) {
+ 				s->async->events |=
+@@ -362,7 +362,7 @@ static void daqp_interrupt(int irq, void *dev_id PT_REGS_ARG)
+ /* One-shot analog data acquisition routine */
+ 
+ static int daqp_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	local_info_t *local = (local_info_t *) s->private;
+ 	int i;
+@@ -794,7 +794,7 @@ static int daqp_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ /* Single-shot analog output routine */
+ 
+ static int daqp_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	local_info_t *local = (local_info_t *) s->private;
+ 	int d;
+@@ -821,7 +821,7 @@ static int daqp_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+ /* Digital input routine */
+ 
+ static int daqp_di_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	local_info_t *local = (local_info_t *) s->private;
+ 
+@@ -837,7 +837,7 @@ static int daqp_di_insn_read(comedi_device * dev, comedi_subdevice * s,
+ /* Digital output routine */
+ 
+ static int daqp_do_insn_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	local_info_t *local = (local_info_t *) s->private;
+ 
+diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
+index f2fa4faa24a8..571fa54c4d38 100644
+--- a/drivers/staging/comedi/drivers/rtd520.c
++++ b/drivers/staging/comedi/drivers/rtd520.c
+@@ -334,7 +334,7 @@ struct rtdPrivate {
+ 	unsigned char chanBipolar[RTD_MAX_CHANLIST / 8];	/* bit array */
+ 
+ 	/* read back data */
+-	lsampl_t aoValue[2];	/* Used for AO read back */
++	unsigned int aoValue[2];	/* Used for AO read back */
+ 
+ 	/* timer gate (when enabled) */
+ 	u8 utcGate[4];		/* 1 extra allows simple range check */
+@@ -691,15 +691,15 @@ static comedi_driver rtd520Driver = {
+ };
+ 
+ static int rtd_ai_rinsn(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data);
++	comedi_insn *insn, unsigned int *data);
+ static int rtd_ao_winsn(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data);
++	comedi_insn *insn, unsigned int *data);
+ static int rtd_ao_rinsn(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data);
++	comedi_insn *insn, unsigned int *data);
+ static int rtd_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data);
++	comedi_insn *insn, unsigned int *data);
+ static int rtd_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data);
++	comedi_insn *insn, unsigned int *data);
+ static int rtd_ai_cmdtest(comedi_device *dev, comedi_subdevice *s,
+ 	comedi_cmd *cmd);
+ static int rtd_ai_cmd(comedi_device *dev, comedi_subdevice *s);
+@@ -1211,7 +1211,7 @@ static void rtd_load_channelgain_list(comedi_device *dev,
+ empty status flag clears */
+ static int rtd520_probe_fifo_depth(comedi_device *dev)
+ {
+-	lsampl_t chanspec = CR_PACK(0, 0, AREF_GROUND);
++	unsigned int chanspec = CR_PACK(0, 0, AREF_GROUND);
+ 	unsigned i;
+ 	static const unsigned limit = 0x2000;
+ 	unsigned fifo_size = 0;
+@@ -1255,7 +1255,7 @@ static int rtd520_probe_fifo_depth(comedi_device *dev)
+   select, delay, then read.
+  */
+ static int rtd_ai_rinsn(comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
++	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 	int n, ii;
+ 	int stat;
+@@ -1312,7 +1312,7 @@ static int ai_read_n(comedi_device *dev, comedi_subdevice *s, int count)
+ 	int ii;
+ 
+ 	for (ii = 0; ii < count; ii++) {
+-		sampl_t sample;
++		short sample;
+ 		s16 d;
+ 
+ 		if (0 == devpriv->aiCount) {	/* done */
+@@ -1349,7 +1349,7 @@ static int ai_read_n(comedi_device *dev, comedi_subdevice *s, int count)
+ static int ai_read_dregs(comedi_device *dev, comedi_subdevice *s)
+ {
+ 	while (RtdFifoStatus(dev) & FS_ADC_NOT_EMPTY) {	/* 1 -> not empty */
+-		sampl_t sample;
++		short sample;
+ 		s16 d = RtdAdcFifoGet(dev);	/* get 2s comp value */
+ 
+ 		if (0 == devpriv->aiCount) {	/* done */
+@@ -1444,7 +1444,7 @@ static int ai_process_dma(comedi_device *dev, comedi_subdevice *s)
+ 
+ 	dp = devpriv->dma0Buff[devpriv->dma0Offset];
+ 	for (ii = 0; ii < devpriv->fifoLen / 2;) {	/* convert samples */
+-		sampl_t sample;
++		short sample;
+ 
+ 		if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) {
+ 			sample = (*dp >> 3) + 2048;	/* convert to comedi unsigned data */
+@@ -2136,7 +2136,7 @@ static int rtd_ns_to_timer(unsigned int *ns, int round_mode)
+   Output one (or more) analog values to a single port as fast as possible.
+ */
+ static int rtd_ao_winsn(comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
++	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -2191,7 +2191,7 @@ static int rtd_ao_winsn(comedi_device *dev,
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+ static int rtd_ao_rinsn(comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
++	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -2214,7 +2214,7 @@ static int rtd_ao_rinsn(comedi_device *dev,
+  * comedi core can convert between insn_bits and insn_read/write
+  */
+ static int rtd_dio_insn_bits(comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
++	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -2241,7 +2241,7 @@ static int rtd_dio_insn_bits(comedi_device *dev,
+   Configure one bit on a IO port as Input or Output (hence the name :-).
+ */
+ static int rtd_dio_insn_config(comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
++	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c
+index 35250b9ae448..0cefcb39db7c 100644
+--- a/drivers/staging/comedi/drivers/rti800.c
++++ b/drivers/staging/comedi/drivers/rti800.c
+@@ -162,7 +162,7 @@ typedef struct {
+ 		dac_2comp, dac_straight
+ 	} dac0_coding, dac1_coding;
+ 	const comedi_lrange *ao_range_type_list[2];
+-	lsampl_t ao_readback[2];
++	unsigned int ao_readback[2];
+ 	int muxgain_bits;
+ } rti800_private;
+ 
+@@ -179,7 +179,7 @@ static irqreturn_t rti800_interrupt(int irq, void *dev PT_REGS_ARG)
+ static const int gaindelay[] = { 10, 20, 40, 80 };
+ 
+ static int rti800_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, t;
+ 	int status;
+@@ -232,7 +232,7 @@ static int rti800_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int rti800_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -244,7 +244,7 @@ static int rti800_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int rti800_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 	int d;
+@@ -264,7 +264,7 @@ static int rti800_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int rti800_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -273,7 +273,7 @@ static int rti800_di_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int rti800_do_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c
+index 8ab968d0ffa4..058a4c066205 100644
+--- a/drivers/staging/comedi/drivers/rti802.c
++++ b/drivers/staging/comedi/drivers/rti802.c
+@@ -63,13 +63,13 @@ typedef struct {
+ 		dac_2comp, dac_straight
+ 	} dac_coding[8];
+ 	const comedi_lrange *range_type_list[8];
+-	lsampl_t ao_readback[8];
++	unsigned int ao_readback[8];
+ } rti802_private;
+ 
+ #define devpriv ((rti802_private *)dev->private)
+ 
+ static int rti802_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 
+@@ -80,7 +80,7 @@ static int rti802_ao_insn_read(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int rti802_ao_insn_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i, d;
+ 	int chan = CR_CHAN(insn->chanspec);
+diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
+index 20ac48e81514..c9bd985f9932 100644
+--- a/drivers/staging/comedi/drivers/s526.c
++++ b/drivers/staging/comedi/drivers/s526.c
+@@ -198,7 +198,7 @@ typedef struct {
+ 	struct pci_dev *pci_dev;
+ 
+ 	/* Used for AO readback */
+-	lsampl_t ao_readback[2];
++	unsigned int ao_readback[2];
+ 
+ 	s526_gpct_config_t s526_gpct_config[4];
+ 	unsigned short s526_ai_config;
+@@ -246,23 +246,23 @@ static comedi_driver driver_s526 = {
+ };
+ 
+ static int s526_gpct_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int s526_gpct_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int s526_gpct_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int s526_ai_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int s526_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int s526_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int s526_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int s526_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int s526_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ /*
+  * Attach is called by the Comedi core to configure the driver
+@@ -275,7 +275,7 @@ static int s526_attach(comedi_device * dev, comedi_devconfig * it)
+ 	comedi_subdevice *s;
+ 	int iobase;
+ 	int i, n;
+-//      sampl_t value;
++//      short value;
+ //      int subdev_channel = 0;
+ 
+ 	printk("comedi%d: s526: ", dev->minor);
+@@ -428,11 +428,11 @@ static int s526_attach(comedi_device * dev, comedi_devconfig * it)
+ 	printk("Read back mode reg=0x%04x\n", inw(ADDR_CHAN_REG(REG_C0M, n)));
+ 
+ 	// Load the pre-laod register high word
+-//                      value = (sampl_t) (0x55);
++//                      value = (short) (0x55);
+ //                      outw(value, ADDR_CHAN_REG(REG_C0H, n));
+ 
+ 	// Load the pre-laod register low word
+-//                      value = (sampl_t)(0xaa55);
++//                      value = (short)(0xaa55);
+ //                      outw(value, ADDR_CHAN_REG(REG_C0L, n));
+ 
+ 	// Write the Counter Control Register
+@@ -477,7 +477,7 @@ static int s526_detach(comedi_device * dev)
+ }
+ 
+ static int s526_gpct_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;			// counts the Data
+ 	int counter_channel = CR_CHAN(insn->chanspec);
+@@ -501,11 +501,11 @@ static int s526_gpct_rinsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int s526_gpct_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int subdev_channel = CR_CHAN(insn->chanspec);	// Unpack chanspec
+ 	int i;
+-	sampl_t value;
++	short value;
+ 
+ //        printk("s526: GPCT_INSN_CONFIG: Configuring Channel %d\n", subdev_channel);
+ 
+@@ -602,20 +602,20 @@ static int s526_gpct_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 			cmReg.reg.autoLoadResetRcap = 4;	// Auto load with INDEX^
+ 
+ 		// Set Counter Mode Register
+-		cmReg.value = (sampl_t) (insn->data[1] & 0xFFFF);
++		cmReg.value = (short) (insn->data[1] & 0xFFFF);
+ 		outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
+ 
+ 		// Load the pre-laod register high word
+-		value = (sampl_t) ((insn->data[2] >> 16) & 0xFFFF);
++		value = (short) ((insn->data[2] >> 16) & 0xFFFF);
+ 		outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
+ 
+ 		// Load the pre-laod register low word
+-		value = (sampl_t) (insn->data[2] & 0xFFFF);
++		value = (short) (insn->data[2] & 0xFFFF);
+ 		outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
+ 
+ 		// Write the Counter Control Register
+ 		if (insn->data[3] != 0) {
+-			value = (sampl_t) (insn->data[3] & 0xFFFF);
++			value = (short) (insn->data[3] & 0xFFFF);
+ 			outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel));
+ 		}
+ 		// Reset the counter if it is software preload
+@@ -639,34 +639,34 @@ static int s526_gpct_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 			SinglePulseGeneration;
+ 
+ 		// Set Counter Mode Register
+-		cmReg.value = (sampl_t) (insn->data[1] & 0xFFFF);
++		cmReg.value = (short) (insn->data[1] & 0xFFFF);
+ 		cmReg.reg.preloadRegSel = 0;	// PR0
+ 		outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
+ 
+ 		// Load the pre-laod register 0 high word
+-		value = (sampl_t) ((insn->data[2] >> 16) & 0xFFFF);
++		value = (short) ((insn->data[2] >> 16) & 0xFFFF);
+ 		outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
+ 
+ 		// Load the pre-laod register 0 low word
+-		value = (sampl_t) (insn->data[2] & 0xFFFF);
++		value = (short) (insn->data[2] & 0xFFFF);
+ 		outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
+ 
+ 		// Set Counter Mode Register
+-		cmReg.value = (sampl_t) (insn->data[1] & 0xFFFF);
++		cmReg.value = (short) (insn->data[1] & 0xFFFF);
+ 		cmReg.reg.preloadRegSel = 1;	// PR1
+ 		outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
+ 
+ 		// Load the pre-laod register 1 high word
+-		value = (sampl_t) ((insn->data[3] >> 16) & 0xFFFF);
++		value = (short) ((insn->data[3] >> 16) & 0xFFFF);
+ 		outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
+ 
+ 		// Load the pre-laod register 1 low word
+-		value = (sampl_t) (insn->data[3] & 0xFFFF);
++		value = (short) (insn->data[3] & 0xFFFF);
+ 		outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
+ 
+ 		// Write the Counter Control Register
+ 		if (insn->data[3] != 0) {
+-			value = (sampl_t) (insn->data[3] & 0xFFFF);
++			value = (short) (insn->data[3] & 0xFFFF);
+ 			outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel));
+ 		}
+ 		break;
+@@ -684,34 +684,34 @@ static int s526_gpct_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 			PulseTrainGeneration;
+ 
+ 		// Set Counter Mode Register
+-		cmReg.value = (sampl_t) (insn->data[1] & 0xFFFF);
++		cmReg.value = (short) (insn->data[1] & 0xFFFF);
+ 		cmReg.reg.preloadRegSel = 0;	// PR0
+ 		outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
+ 
+ 		// Load the pre-laod register 0 high word
+-		value = (sampl_t) ((insn->data[2] >> 16) & 0xFFFF);
++		value = (short) ((insn->data[2] >> 16) & 0xFFFF);
+ 		outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
+ 
+ 		// Load the pre-laod register 0 low word
+-		value = (sampl_t) (insn->data[2] & 0xFFFF);
++		value = (short) (insn->data[2] & 0xFFFF);
+ 		outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
+ 
+ 		// Set Counter Mode Register
+-		cmReg.value = (sampl_t) (insn->data[1] & 0xFFFF);
++		cmReg.value = (short) (insn->data[1] & 0xFFFF);
+ 		cmReg.reg.preloadRegSel = 1;	// PR1
+ 		outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
+ 
+ 		// Load the pre-laod register 1 high word
+-		value = (sampl_t) ((insn->data[3] >> 16) & 0xFFFF);
++		value = (short) ((insn->data[3] >> 16) & 0xFFFF);
+ 		outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
+ 
+ 		// Load the pre-laod register 1 low word
+-		value = (sampl_t) (insn->data[3] & 0xFFFF);
++		value = (short) (insn->data[3] & 0xFFFF);
+ 		outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
+ 
+ 		// Write the Counter Control Register
+ 		if (insn->data[3] != 0) {
+-			value = (sampl_t) (insn->data[3] & 0xFFFF);
++			value = (short) (insn->data[3] & 0xFFFF);
+ 			outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel));
+ 		}
+ 		break;
+@@ -726,10 +726,10 @@ static int s526_gpct_insn_config(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int s526_gpct_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int subdev_channel = CR_CHAN(insn->chanspec);	// Unpack chanspec
+-	sampl_t value;
++	short value;
+ 
+ 	printk("s526: GPCT_INSN_WRITE on channel %d\n", subdev_channel);
+ 	cmReg.value = inw(ADDR_CHAN_REG(REG_C0M, subdev_channel));
+@@ -769,9 +769,9 @@ static int s526_gpct_winsn(comedi_device * dev, comedi_subdevice * s,
+ 			return -EINVAL;
+ 		}
+ 
+-		value = (sampl_t) ((*data >> 16) & 0xFFFF);
++		value = (short) ((*data >> 16) & 0xFFFF);
+ 		outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
+-		value = (sampl_t) (*data & 0xFFFF);
++		value = (short) (*data & 0xFFFF);
+ 		outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
+ 		break;
+ 	default:		// Impossible
+@@ -785,7 +785,7 @@ static int s526_gpct_winsn(comedi_device * dev, comedi_subdevice * s,
+ 
+ #define ISR_ADC_DONE 0x4
+ static int s526_ai_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int result = -EINVAL;
+ 
+@@ -818,7 +818,7 @@ static int s526_ai_insn_config(comedi_device * dev, comedi_subdevice * s,
+  * mode.
+  */
+ static int s526_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -868,7 +868,7 @@ static int s526_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int s526_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -897,7 +897,7 @@ static int s526_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+ static int s526_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -914,7 +914,7 @@ static int s526_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+ static int s526_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -939,10 +939,10 @@ static int s526_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int s526_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+-	sampl_t value;
++	short value;
+ 
+ 	printk("S526 DIO insn_config\n");
+ 
+diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
+index 9323fa00fbb8..a4f4de69da76 100644
+--- a/drivers/staging/comedi/drivers/s626.c
++++ b/drivers/staging/comedi/drivers/s626.c
+@@ -157,7 +157,7 @@ struct s626_private {
+ 	uint32_t I2CAdrs;
+ 	/* I2C device address for onboard EEPROM (board rev dependent). */
+ 	/*   short         I2Cards; */
+-	lsampl_t ao_readback[S626_DAC_CHANNELS];
++	unsigned int ao_readback[S626_DAC_CHANNELS];
+ };
+ 
+ struct dio_private {
+@@ -223,39 +223,39 @@ COMEDI_PCI_INITCLEANUP_NOMODULE(driver_s626, s626_pci_table);
+ 
+ /* ioctl routines */
+ static int s626_ai_insn_config(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data);
+-/* static int s626_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); */
++	comedi_insn *insn, unsigned int *data);
++/* static int s626_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data); */
+ static int s626_ai_insn_read(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data);
++	comedi_insn *insn, unsigned int *data);
+ static int s626_ai_cmd(comedi_device *dev, comedi_subdevice *s);
+ static int s626_ai_cmdtest(comedi_device *dev, comedi_subdevice *s,
+ 	comedi_cmd *cmd);
+ static int s626_ai_cancel(comedi_device *dev, comedi_subdevice *s);
+ static int s626_ao_winsn(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data);
++	comedi_insn *insn, unsigned int *data);
+ static int s626_ao_rinsn(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data);
++	comedi_insn *insn, unsigned int *data);
+ static int s626_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data);
++	comedi_insn *insn, unsigned int *data);
+ static int s626_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data);
++	comedi_insn *insn, unsigned int *data);
+ static int s626_dio_set_irq(comedi_device *dev, unsigned int chan);
+ static int s626_dio_reset_irq(comedi_device *dev, unsigned int gruop,
+ 	unsigned int mask);
+ static int s626_dio_clear_irq(comedi_device *dev);
+ static int s626_enc_insn_config(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data);
++	comedi_insn *insn, unsigned int *data);
+ static int s626_enc_insn_read(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data);
++	comedi_insn *insn, unsigned int *data);
+ static int s626_enc_insn_write(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data);
++	comedi_insn *insn, unsigned int *data);
+ static int s626_ns_to_timer(int *nanosec, int round_mode);
+ static int s626_ai_load_polllist(uint8_t *ppl, comedi_cmd *cmd);
+ static int s626_ai_inttrig(comedi_device *dev, comedi_subdevice *s,
+ 	unsigned int trignum);
+ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG);
+-static lsampl_t s626_ai_reg_to_uint(int data);
+-/* static lsampl_t s626_uint_to_reg(comedi_subdevice *s, int data); */
++static unsigned int s626_ai_reg_to_uint(int data);
++/* static unsigned int s626_uint_to_reg(comedi_subdevice *s, int data); */
+ 
+ /* end ioctl routines */
+ 
+@@ -951,9 +951,9 @@ static int s626_attach(comedi_device *dev, comedi_devconfig *it)
+ 	return 1;
+ }
+ 
+-static lsampl_t s626_ai_reg_to_uint(int data)
++static unsigned int s626_ai_reg_to_uint(int data)
+ {
+-	lsampl_t tempdata;
++	unsigned int tempdata;
+ 
+ 	tempdata = (data >> 18);
+ 	if (tempdata & 0x2000)
+@@ -964,7 +964,7 @@ static lsampl_t s626_ai_reg_to_uint(int data)
+ 	return tempdata;
+ }
+ 
+-/* static lsampl_t s626_uint_to_reg(comedi_subdevice *s, int data){ */
++/* static unsigned int s626_uint_to_reg(comedi_subdevice *s, int data){ */
+ /*   return 0; */
+ /* } */
+ 
+@@ -978,7 +978,7 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG)
+ 	int32_t *readaddr;
+ 	uint32_t irqtype, irqstatus;
+ 	int i = 0;
+-	sampl_t tempdata;
++	short tempdata;
+ 	uint8_t group;
+ 	uint16_t irqbit;
+ 
+@@ -1504,13 +1504,13 @@ void ResetADC(comedi_device *dev, uint8_t *ppl)
+ 
+ /* TO COMPLETE, IF NECESSARY */
+ static int s626_ai_insn_config(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data)
++	comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	return -EINVAL;
+ }
+ 
+-/* static int s626_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) */
++/* static int s626_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,unsigned int *data) */
+ /* { */
+ /*   register uint8_t	i; */
+ /*   register int32_t	*readaddr; */
+@@ -1541,7 +1541,7 @@ static int s626_ai_insn_config(comedi_device *dev, comedi_subdevice *s,
+ /* } */
+ 
+ static int s626_ai_insn_read(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data)
++	comedi_insn *insn, unsigned int *data)
+ {
+ 	uint16_t chan = CR_CHAN(insn->chanspec);
+ 	uint16_t range = CR_RANGE(insn->chanspec);
+@@ -2046,7 +2046,7 @@ static int s626_ns_to_timer(int *nanosec, int round_mode)
+ }
+ 
+ static int s626_ao_winsn(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data)
++	comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	int i;
+@@ -2065,7 +2065,7 @@ static int s626_ao_winsn(comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ static int s626_ao_rinsn(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data)
++	comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 
+@@ -2111,7 +2111,7 @@ static void s626_dio_init(comedi_device *dev)
+  * core can convert between insn_bits and insn_read/write */
+ 
+ static int s626_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data)
++	comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	/* Length of data must be 2 (mask and new data, see below) */
+@@ -2147,7 +2147,7 @@ static int s626_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ static int s626_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data)
++	comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	switch (data[0]) {
+@@ -2252,7 +2252,7 @@ static int s626_dio_clear_irq(comedi_device *dev)
+    and set the subdevice. To complete with trigger and interrupt
+    configuration */
+ static int s626_enc_insn_config(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data)
++	comedi_insn *insn, unsigned int *data)
+ {
+ 	uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) |	/*  Preload upon */
+ 		/*  index. */
+@@ -2282,7 +2282,7 @@ static int s626_enc_insn_config(comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ static int s626_enc_insn_read(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data)
++	comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	int n;
+@@ -2300,7 +2300,7 @@ static int s626_enc_insn_read(comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ static int s626_enc_insn_write(comedi_device *dev, comedi_subdevice *s,
+-	comedi_insn *insn, lsampl_t *data)
++	comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	struct enc_private *k = &encpriv[CR_CHAN(insn->chanspec)];
+diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
+index 6436a3d71be7..65bbf5cb0e9f 100644
+--- a/drivers/staging/comedi/drivers/serial2002.c
++++ b/drivers/staging/comedi/drivers/serial2002.c
+@@ -70,7 +70,7 @@ typedef struct {
+ 	int port;		// /dev/ttyS
+ 	int speed;		// baudrate
+ 	struct file *tty;
+-	lsampl_t ao_readback[32];
++	unsigned int ao_readback[32];
+ 	unsigned char digital_in_mapping[32];
+ 	unsigned char digital_out_mapping[32];
+ 	unsigned char analog_in_mapping[32];
+@@ -98,15 +98,15 @@ comedi_driver driver_serial2002 = {
+ };
+ 
+ static int serial2002_di_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int serial2002_do_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int serial2002_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int serial2002_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int serial2002_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ 
+ struct serial_data {
+ 	enum { is_invalid, is_digital, is_channel } kind;
+@@ -614,7 +614,7 @@ static void serial_2002_open(comedi_device * dev)
+ 					kfree(s->maxdata_list);
+ 				}
+ 				s->maxdata_list = maxdata_list =
+-					kmalloc(sizeof(lsampl_t) * s->n_chan,
++					kmalloc(sizeof(unsigned int) * s->n_chan,
+ 					GFP_KERNEL);
+ 				if (s->range_table_list) {
+ 					kfree(s->range_table_list);
+@@ -661,7 +661,7 @@ static void serial_2002_close(comedi_device * dev)
+ }
+ 
+ static int serial2002_di_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan;
+@@ -683,7 +683,7 @@ static int serial2002_di_rinsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int serial2002_do_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan;
+@@ -701,7 +701,7 @@ static int serial2002_do_winsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int serial2002_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan;
+@@ -723,7 +723,7 @@ static int serial2002_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int serial2002_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan;
+@@ -742,7 +742,7 @@ static int serial2002_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int serial2002_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -755,7 +755,7 @@ static int serial2002_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int serial2002_ei_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n;
+ 	int chan;
+diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c
+index bb3d84ccc060..7a2e0ce409ed 100644
+--- a/drivers/staging/comedi/drivers/skel.c
++++ b/drivers/staging/comedi/drivers/skel.c
+@@ -137,7 +137,7 @@ typedef struct {
+ 	struct pci_dev *pci_dev;
+ 
+ 	/* Used for AO readback */
+-	lsampl_t ao_readback[2];
++	unsigned int ao_readback[2];
+ } skel_private;
+ /*
+  * most drivers define the following macro to make it easy to
+@@ -182,15 +182,15 @@ static comedi_driver driver_skel = {
+ };
+ 
+ static int skel_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int skel_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int skel_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int skel_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int skel_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int skel_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+ static int skel_ns_to_timer(unsigned int *ns, int round);
+@@ -299,7 +299,7 @@ static int skel_detach(comedi_device * dev)
+  * mode.
+  */
+ static int skel_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int n, i;
+ 	unsigned int d;
+@@ -516,7 +516,7 @@ static int skel_ns_to_timer(unsigned int *ns, int round)
+ }
+ 
+ static int skel_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -537,7 +537,7 @@ static int skel_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+ static int skel_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -554,7 +554,7 @@ static int skel_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write */
+ static int skel_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -579,7 +579,7 @@ static int skel_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ static int skel_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c
+index 242ec4eef313..f2465a2bf8e5 100644
+--- a/drivers/staging/comedi/drivers/ssv_dnp.c
++++ b/drivers/staging/comedi/drivers/ssv_dnp.c
+@@ -104,10 +104,10 @@ static comedi_driver driver_dnp = {
+ COMEDI_INITCLEANUP(driver_dnp);
+ 
+ static int dnp_dio_insn_bits(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+ static int dnp_dio_insn_config(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
+ 
+ /* ------------------------------------------------------------------------- */
+ /* Attach is called by comedi core to configure the driver for a particular  */
+@@ -201,7 +201,7 @@ static int dnp_detach(comedi_device * dev)
+ /* ------------------------------------------------------------------------- */
+ 
+ static int dnp_dio_insn_bits(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	if (insn->n != 2)
+@@ -251,7 +251,7 @@ static int dnp_dio_insn_bits(comedi_device * dev,
+ /* ------------------------------------------------------------------------- */
+ 
+ static int dnp_dio_insn_config(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
+ {
+ 
+ 	u8 register_buffer;
+diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c
+index 82850a53dcdf..8df437af9dcc 100644
+--- a/drivers/staging/comedi/drivers/unioxx5.c
++++ b/drivers/staging/comedi/drivers/unioxx5.c
+@@ -82,22 +82,22 @@ typedef struct unioxx5_subd_priv {
+ 
+ static int unioxx5_attach(comedi_device * dev, comedi_devconfig * it);
+ static int unioxx5_subdev_write(comedi_device * dev, comedi_subdevice * subdev,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int unioxx5_subdev_read(comedi_device * dev, comedi_subdevice * subdev,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int unioxx5_insn_config(comedi_device * dev, comedi_subdevice * subdev,
+-	comedi_insn * insn, lsampl_t * data);
++	comedi_insn * insn, unsigned int * data);
+ static int unioxx5_detach(comedi_device * dev);
+ static int __unioxx5_subdev_init(comedi_subdevice * subdev, int subdev_iobase,
+ 	int minor);
+-static int __unioxx5_digital_write(unioxx5_subd_priv * usp, lsampl_t * data,
++static int __unioxx5_digital_write(unioxx5_subd_priv * usp, unsigned int * data,
+ 	int channel, int minor);
+-static int __unioxx5_digital_read(unioxx5_subd_priv * usp, lsampl_t * data,
++static int __unioxx5_digital_read(unioxx5_subd_priv * usp, unsigned int * data,
+ 	int channel, int minor);
+ //static void __unioxx5_digital_config(unioxx5_subd_priv* usp, int mode);
+-static int __unioxx5_analog_write(unioxx5_subd_priv * usp, lsampl_t * data,
++static int __unioxx5_analog_write(unioxx5_subd_priv * usp, unsigned int * data,
+ 	int channel, int minor);
+-static int __unioxx5_analog_read(unioxx5_subd_priv * usp, lsampl_t * data,
++static int __unioxx5_analog_read(unioxx5_subd_priv * usp, unsigned int * data,
+ 	int channel, int minor);
+ static int __unioxx5_define_chan_offset(int chan_num);
+ static void __unioxx5_analog_config(unioxx5_subd_priv * usp, int channel);
+@@ -157,7 +157,7 @@ static int unioxx5_attach(comedi_device * dev, comedi_devconfig * it)
+ }
+ 
+ static int unioxx5_subdev_read(comedi_device * dev, comedi_subdevice * subdev,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unioxx5_subd_priv *usp = subdev->private;
+ 	int channel, type;
+@@ -177,7 +177,7 @@ static int unioxx5_subdev_read(comedi_device * dev, comedi_subdevice * subdev,
+ }
+ 
+ static int unioxx5_subdev_write(comedi_device * dev, comedi_subdevice * subdev,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	unioxx5_subd_priv *usp = subdev->private;
+ 	int channel, type;
+@@ -198,7 +198,7 @@ static int unioxx5_subdev_write(comedi_device * dev, comedi_subdevice * subdev,
+ 
+ /* for digital modules only */
+ static int unioxx5_insn_config(comedi_device * dev, comedi_subdevice * subdev,
+-	comedi_insn * insn, lsampl_t * data)
++	comedi_insn * insn, unsigned int * data)
+ {
+ 	int channel_offset, flags, channel = CR_CHAN(insn->chanspec), type;
+ 	unioxx5_subd_priv *usp = subdev->private;
+@@ -330,7 +330,7 @@ static int __unioxx5_subdev_init(comedi_subdevice * subdev, int subdev_iobase,
+ 	return 0;
+ }
+ 
+-static int __unioxx5_digital_write(unioxx5_subd_priv * usp, lsampl_t * data,
++static int __unioxx5_digital_write(unioxx5_subd_priv * usp, unsigned int * data,
+ 	int channel, int minor)
+ {
+ 	int channel_offset, val;
+@@ -357,7 +357,7 @@ static int __unioxx5_digital_write(unioxx5_subd_priv * usp, lsampl_t * data,
+ }
+ 
+ /* function for digital reading */
+-static int __unioxx5_digital_read(unioxx5_subd_priv * usp, lsampl_t * data,
++static int __unioxx5_digital_read(unioxx5_subd_priv * usp, unsigned int * data,
+ 	int channel, int minor)
+ {
+ 	int channel_offset, mask = 1 << (channel & 0x07);
+@@ -396,7 +396,7 @@ static void __unioxx5_digital_config(unioxx5_subd_priv * usp, int mode)
+ }
+ #endif
+ 
+-static int __unioxx5_analog_write(unioxx5_subd_priv * usp, lsampl_t * data,
++static int __unioxx5_analog_write(unioxx5_subd_priv * usp, unsigned int * data,
+ 	int channel, int minor)
+ {
+ 	int module, i;
+@@ -431,7 +431,7 @@ static int __unioxx5_analog_write(unioxx5_subd_priv * usp, lsampl_t * data,
+ 	return 1;
+ }
+ 
+-static int __unioxx5_analog_read(unioxx5_subd_priv * usp, lsampl_t * data,
++static int __unioxx5_analog_read(unioxx5_subd_priv * usp, unsigned int * data,
+ 	int channel, int minor)
+ {
+ 	int module_no, read_ch;
+diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
+index 0e02e646dad6..68566295443a 100644
+--- a/drivers/staging/comedi/drivers/usbdux.c
++++ b/drivers/staging/comedi/drivers/usbdux.c
+@@ -253,7 +253,7 @@ struct usbduxsub {
+ 	/* pwm-transfer handling */
+ 	struct urb *urbPwm;
+ 	/* PWM period */
+-	lsampl_t pwmPeriod;
++	unsigned int pwmPeriod;
+ 	/* PWM internal delay for the GPIF in the FX2 */
+ 	int8_t pwmDelay;
+ 	/* size of the PWM buffer which holds the bit pattern */
+@@ -656,7 +656,7 @@ static void usbduxsub_ao_IsocIrq(struct urb *urb)
+ 		((uint8_t *) (urb->transfer_buffer))[0] =
+ 			s->async->cmd.chanlist_len;
+ 		for (i = 0; i < s->async->cmd.chanlist_len; i++) {
+-			sampl_t temp;
++			short temp;
+ 			if (i >= NUMOUTCHANNELS)
+ 				break;
+ 
+@@ -1277,10 +1277,10 @@ static int usbdux_ai_cmd(comedi_device *dev, comedi_subdevice *s)
+ 
+ /* Mode 0 is used to get a single conversion on demand */
+ static int usbdux_ai_insn_read(comedi_device *dev, comedi_subdevice *s,
+-			       comedi_insn *insn, lsampl_t *data)
++			       comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+-	lsampl_t one = 0;
++	unsigned int one = 0;
+ 	int chan, range;
+ 	int err;
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+@@ -1338,7 +1338,7 @@ static int usbdux_ai_insn_read(comedi_device *dev, comedi_subdevice *s,
+ /* analog out */
+ 
+ static int usbdux_ao_insn_read(comedi_device *dev, comedi_subdevice *s,
+-			       comedi_insn *insn, lsampl_t *data)
++			       comedi_insn *insn, unsigned int *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -1360,7 +1360,7 @@ static int usbdux_ao_insn_read(comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ static int usbdux_ao_insn_write(comedi_device *dev, comedi_subdevice *s,
+-				comedi_insn *insn, lsampl_t *data)
++				comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, err;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -1698,7 +1698,7 @@ static int usbdux_ao_cmd(comedi_device *dev, comedi_subdevice *s)
+ }
+ 
+ static int usbdux_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
+-				  comedi_insn *insn, lsampl_t *data)
++				  comedi_insn *insn, unsigned int *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+@@ -1729,7 +1729,7 @@ static int usbdux_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ static int usbdux_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
+-				comedi_insn *insn, lsampl_t *data)
++				comedi_insn *insn, unsigned int *data)
+ {
+ 
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+@@ -1776,7 +1776,7 @@ static int usbdux_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
+ 
+ /* reads the 4 counters, only two are used just now */
+ static int usbdux_counter_read(comedi_device *dev, comedi_subdevice *s,
+-			       comedi_insn *insn, lsampl_t *data)
++			       comedi_insn *insn, unsigned int *data)
+ {
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+ 	int chan = insn->chanspec;
+@@ -1810,7 +1810,7 @@ static int usbdux_counter_read(comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ static int usbdux_counter_write(comedi_device *dev, comedi_subdevice *s,
+-				comedi_insn *insn, lsampl_t *data)
++				comedi_insn *insn, unsigned int *data)
+ {
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+ 	int err;
+@@ -1840,7 +1840,7 @@ static int usbdux_counter_write(comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ static int usbdux_counter_config(comedi_device *dev, comedi_subdevice *s,
+-				 comedi_insn *insn, lsampl_t *data)
++				 comedi_insn *insn, unsigned int *data)
+ {
+ 	/* nothing to do so far */
+ 	return 2;
+@@ -1997,7 +1997,7 @@ static int usbduxsub_submit_PwmURBs(struct usbduxsub *usbduxsub)
+ }
+ 
+ static int usbdux_pwm_period(comedi_device *dev, comedi_subdevice *s,
+-			     lsampl_t period)
++			     unsigned int period)
+ {
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+ 	int fx2delay = 255;
+@@ -2057,7 +2057,7 @@ static int usbdux_pwm_start(comedi_device *dev, comedi_subdevice *s)
+ 
+ /* generates the bit pattern for PWM with the optional sign bit */
+ static int usbdux_pwm_pattern(comedi_device *dev, comedi_subdevice *s,
+-			      int channel, lsampl_t value, lsampl_t sign)
++			      int channel, unsigned int value, unsigned int sign)
+ {
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+ 	int i, szbuf;
+@@ -2098,7 +2098,7 @@ static int usbdux_pwm_pattern(comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ static int usbdux_pwm_write(comedi_device *dev, comedi_subdevice *s,
+-			    comedi_insn *insn, lsampl_t *data)
++			    comedi_insn *insn, unsigned int *data)
+ {
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+ 
+@@ -2123,7 +2123,7 @@ static int usbdux_pwm_write(comedi_device *dev, comedi_subdevice *s,
+ }
+ 
+ static int usbdux_pwm_read(comedi_device *x1, comedi_subdevice *x2,
+-			   comedi_insn *x3, lsampl_t *x4)
++			   comedi_insn *x3, unsigned int *x4)
+ {
+ 	/* not needed */
+ 	return -EINVAL;
+@@ -2131,7 +2131,7 @@ static int usbdux_pwm_read(comedi_device *x1, comedi_subdevice *x2,
+ 
+ /* switches on/off PWM */
+ static int usbdux_pwm_config(comedi_device *dev, comedi_subdevice *s,
+-			     comedi_insn *insn, lsampl_t *data)
++			     comedi_insn *insn, unsigned int *data)
+ {
+ 	struct usbduxsub *this_usbduxsub = dev->private;
+ 	switch (data[0]) {
+diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c
+index 95b5807bcd41..aa21914318c8 100644
+--- a/drivers/staging/comedi/drivers/usbduxfast.c
++++ b/drivers/staging/comedi/drivers/usbduxfast.c
+@@ -1231,7 +1231,7 @@ static int usbduxfast_ai_cmd(comedi_device *dev, comedi_subdevice *s)
+  * Mode 0 is used to get a single conversion on demand.
+  */
+ static int usbduxfast_ai_insn_read(comedi_device *dev,
+-	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
++	comedi_subdevice *s, comedi_insn *insn, unsigned int *data)
+ {
+ 	int i, j, n, actual_length;
+ 	int chan, range, rngmask;
+diff --git a/drivers/staging/comedi/kcomedilib/data.c b/drivers/staging/comedi/kcomedilib/data.c
+index f63a506dd8ab..53f20476e99b 100644
+--- a/drivers/staging/comedi/kcomedilib/data.c
++++ b/drivers/staging/comedi/kcomedilib/data.c
+@@ -28,7 +28,7 @@
+ #include 
+ 
+ int comedi_data_write(void *dev, unsigned int subdev, unsigned int chan,
+-	unsigned int range, unsigned int aref, lsampl_t data)
++	unsigned int range, unsigned int aref, unsigned int data)
+ {
+ 	comedi_insn insn;
+ 
+@@ -43,7 +43,7 @@ int comedi_data_write(void *dev, unsigned int subdev, unsigned int chan,
+ }
+ 
+ int comedi_data_read(void *dev, unsigned int subdev, unsigned int chan,
+-	unsigned int range, unsigned int aref, lsampl_t *data)
++	unsigned int range, unsigned int aref, unsigned int *data)
+ {
+ 	comedi_insn insn;
+ 
+@@ -61,7 +61,7 @@ int comedi_data_read_hint(void *dev, unsigned int subdev,
+ 	unsigned int chan, unsigned int range, unsigned int aref)
+ {
+ 	comedi_insn insn;
+-	lsampl_t dummy_data;
++	unsigned int dummy_data;
+ 
+ 	memset(&insn, 0, sizeof(insn));
+ 	insn.insn = INSN_READ;
+@@ -75,7 +75,7 @@ int comedi_data_read_hint(void *dev, unsigned int subdev,
+ 
+ int comedi_data_read_delayed(void *dev, unsigned int subdev,
+ 	unsigned int chan, unsigned int range, unsigned int aref,
+-	lsampl_t *data, unsigned int nano_sec)
++	unsigned int *data, unsigned int nano_sec)
+ {
+ 	int retval;
+ 
+diff --git a/drivers/staging/comedi/kcomedilib/dio.c b/drivers/staging/comedi/kcomedilib/dio.c
+index 78e63c84072d..1a76ef57537c 100644
+--- a/drivers/staging/comedi/kcomedilib/dio.c
++++ b/drivers/staging/comedi/kcomedilib/dio.c
+@@ -75,7 +75,7 @@ int comedi_dio_bitfield(void *dev, unsigned int subdev, unsigned int mask,
+ 	unsigned int *bits)
+ {
+ 	comedi_insn insn;
+-	lsampl_t data[2];
++	unsigned int data[2];
+ 	int ret;
+ 
+ 	memset(&insn, 0, sizeof(insn));
+diff --git a/drivers/staging/comedi/kcomedilib/get.c b/drivers/staging/comedi/kcomedilib/get.c
+index 5a69d8cf1567..4bb32593a79d 100644
+--- a/drivers/staging/comedi/kcomedilib/get.c
++++ b/drivers/staging/comedi/kcomedilib/get.c
+@@ -98,7 +98,7 @@ int comedi_get_len_chanlist(void *d, unsigned int subdevice)
+ 	return s->len_chanlist;
+ }
+ 
+-lsampl_t comedi_get_maxdata(void *d, unsigned int subdevice,
++unsigned int comedi_get_maxdata(void *d, unsigned int subdevice,
+ 	unsigned int chan)
+ {
+ 	comedi_device *dev = (comedi_device *) d;

commit 0b3fb27fa7b4bf811c31ee66453cda0a6d94aa6c
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:04:56 2009 -0400
+
+    Staging: comedi: Remove comedi_t typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedilib.h b/drivers/staging/comedi/comedilib.h
+index fc5fc015726b..ab42893562f9 100644
+--- a/drivers/staging/comedi/comedilib.h
++++ b/drivers/staging/comedi/comedilib.h
+@@ -36,18 +36,16 @@
+ 
+ #ifndef KCOMEDILIB_DEPRECATED
+ 
+-typedef void comedi_t;
+-
+ /* these functions may not be called at real-time priority */
+ 
+-comedi_t *comedi_open(const char *path);
+-int comedi_close(comedi_t *dev);
++void *comedi_open(const char *path);
++int comedi_close(void *dev);
+ 
+ /* these functions may be called at any priority, but may fail at
+    real-time priority */
+ 
+-int comedi_lock(comedi_t *dev, unsigned int subdev);
+-int comedi_unlock(comedi_t *dev, unsigned int subdev);
++int comedi_lock(void *dev, unsigned int subdev);
++int comedi_unlock(void *dev, unsigned int subdev);
+ 
+ /* these functions may be called at any priority, but you must hold
+    the lock for the subdevice */
+@@ -56,68 +54,68 @@ int comedi_loglevel(int loglevel);
+ void comedi_perror(const char *s);
+ char *comedi_strerror(int errnum);
+ int comedi_errno(void);
+-int comedi_fileno(comedi_t *dev);
++int comedi_fileno(void *dev);
+ 
+-int comedi_cancel(comedi_t *dev, unsigned int subdev);
+-int comedi_register_callback(comedi_t *dev, unsigned int subdev,
++int comedi_cancel(void *dev, unsigned int subdev);
++int comedi_register_callback(void *dev, unsigned int subdev,
+ 	unsigned int mask, int (*cb) (unsigned int, void *), void *arg);
+ 
+-int comedi_command(comedi_t *dev, comedi_cmd *cmd);
+-int comedi_command_test(comedi_t *dev, comedi_cmd *cmd);
+-int comedi_trigger(comedi_t *dev, unsigned int subdev, comedi_trig *it);
+-int __comedi_trigger(comedi_t *dev, unsigned int subdev, comedi_trig *it);
+-int comedi_data_write(comedi_t *dev, unsigned int subdev, unsigned int chan,
++int comedi_command(void *dev, comedi_cmd *cmd);
++int comedi_command_test(void *dev, comedi_cmd *cmd);
++int comedi_trigger(void *dev, unsigned int subdev, comedi_trig *it);
++int __comedi_trigger(void *dev, unsigned int subdev, comedi_trig *it);
++int comedi_data_write(void *dev, unsigned int subdev, unsigned int chan,
+ 	unsigned int range, unsigned int aref, lsampl_t data);
+-int comedi_data_read(comedi_t *dev, unsigned int subdev, unsigned int chan,
++int comedi_data_read(void *dev, unsigned int subdev, unsigned int chan,
+ 	unsigned int range, unsigned int aref, lsampl_t *data);
+-int comedi_data_read_hint(comedi_t *dev, unsigned int subdev,
++int comedi_data_read_hint(void *dev, unsigned int subdev,
+ 	unsigned int chan, unsigned int range, unsigned int aref);
+-int comedi_data_read_delayed(comedi_t *dev, unsigned int subdev,
++int comedi_data_read_delayed(void *dev, unsigned int subdev,
+ 	unsigned int chan, unsigned int range, unsigned int aref,
+ 	lsampl_t *data, unsigned int nano_sec);
+-int comedi_dio_config(comedi_t *dev, unsigned int subdev, unsigned int chan,
++int comedi_dio_config(void *dev, unsigned int subdev, unsigned int chan,
+ 	unsigned int io);
+-int comedi_dio_read(comedi_t *dev, unsigned int subdev, unsigned int chan,
++int comedi_dio_read(void *dev, unsigned int subdev, unsigned int chan,
+ 	unsigned int *val);
+-int comedi_dio_write(comedi_t *dev, unsigned int subdev, unsigned int chan,
++int comedi_dio_write(void *dev, unsigned int subdev, unsigned int chan,
+ 	unsigned int val);
+-int comedi_dio_bitfield(comedi_t *dev, unsigned int subdev, unsigned int mask,
++int comedi_dio_bitfield(void *dev, unsigned int subdev, unsigned int mask,
+ 	unsigned int *bits);
+-int comedi_get_n_subdevices(comedi_t *dev);
+-int comedi_get_version_code(comedi_t *dev);
+-const char *comedi_get_driver_name(comedi_t *dev);
+-const char *comedi_get_board_name(comedi_t *dev);
+-int comedi_get_subdevice_type(comedi_t *dev, unsigned int subdevice);
+-int comedi_find_subdevice_by_type(comedi_t *dev, int type, unsigned int subd);
+-int comedi_get_n_channels(comedi_t *dev, unsigned int subdevice);
+-lsampl_t comedi_get_maxdata(comedi_t *dev, unsigned int subdevice, unsigned
++int comedi_get_n_subdevices(void *dev);
++int comedi_get_version_code(void *dev);
++const char *comedi_get_driver_name(void *dev);
++const char *comedi_get_board_name(void *dev);
++int comedi_get_subdevice_type(void *dev, unsigned int subdevice);
++int comedi_find_subdevice_by_type(void *dev, int type, unsigned int subd);
++int comedi_get_n_channels(void *dev, unsigned int subdevice);
++lsampl_t comedi_get_maxdata(void *dev, unsigned int subdevice, unsigned
+ 	int chan);
+-int comedi_get_n_ranges(comedi_t *dev, unsigned int subdevice, unsigned int
++int comedi_get_n_ranges(void *dev, unsigned int subdevice, unsigned int
+ 	chan);
+-int comedi_do_insn(comedi_t *dev, comedi_insn *insn);
+-int comedi_poll(comedi_t *dev, unsigned int subdev);
++int comedi_do_insn(void *dev, comedi_insn *insn);
++int comedi_poll(void *dev, unsigned int subdev);
+ 
+ /* DEPRECATED functions */
+-int comedi_get_rangetype(comedi_t *dev, unsigned int subdevice,
++int comedi_get_rangetype(void *dev, unsigned int subdevice,
+ 	unsigned int chan);
+ 
+ /* ALPHA functions */
+-unsigned int comedi_get_subdevice_flags(comedi_t *dev, unsigned int subdevice);
+-int comedi_get_len_chanlist(comedi_t *dev, unsigned int subdevice);
+-int comedi_get_krange(comedi_t *dev, unsigned int subdevice, unsigned int
++unsigned int comedi_get_subdevice_flags(void *dev, unsigned int subdevice);
++int comedi_get_len_chanlist(void *dev, unsigned int subdevice);
++int comedi_get_krange(void *dev, unsigned int subdevice, unsigned int
+ 	chan, unsigned int range, comedi_krange *krange);
+-unsigned int comedi_get_buf_head_pos(comedi_t *dev, unsigned int subdevice);
+-int comedi_set_user_int_count(comedi_t *dev, unsigned int subdevice,
++unsigned int comedi_get_buf_head_pos(void *dev, unsigned int subdevice);
++int comedi_set_user_int_count(void *dev, unsigned int subdevice,
+ 	unsigned int buf_user_count);
+-int comedi_map(comedi_t *dev, unsigned int subdev, void *ptr);
+-int comedi_unmap(comedi_t *dev, unsigned int subdev);
+-int comedi_get_buffer_size(comedi_t *dev, unsigned int subdev);
+-int comedi_mark_buffer_read(comedi_t *dev, unsigned int subdevice,
++int comedi_map(void *dev, unsigned int subdev, void *ptr);
++int comedi_unmap(void *dev, unsigned int subdev);
++int comedi_get_buffer_size(void *dev, unsigned int subdev);
++int comedi_mark_buffer_read(void *dev, unsigned int subdevice,
+ 	unsigned int num_bytes);
+-int comedi_mark_buffer_written(comedi_t *d, unsigned int subdevice,
++int comedi_mark_buffer_written(void *d, unsigned int subdevice,
+ 	unsigned int num_bytes);
+-int comedi_get_buffer_contents(comedi_t *dev, unsigned int subdevice);
+-int comedi_get_buffer_offset(comedi_t *dev, unsigned int subdevice);
++int comedi_get_buffer_contents(void *dev, unsigned int subdevice);
++int comedi_get_buffer_offset(void *dev, unsigned int subdevice);
+ 
+ #else
+ 
+diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c
+index 9e5496f4f1ae..09e288904f9e 100644
+--- a/drivers/staging/comedi/drivers/comedi_bond.c
++++ b/drivers/staging/comedi/drivers/comedi_bond.c
+@@ -142,7 +142,7 @@ static const struct BondingBoard bondingBoards[] = {
+ #define thisboard ((const struct BondingBoard *)dev->board_ptr)
+ 
+ struct BondedDevice {
+-	comedi_t *dev;
++	void *dev;
+ 	unsigned minor;
+ 	unsigned subdev;
+ 	unsigned subdev_type;
+@@ -397,7 +397,7 @@ static void *Realloc(const void *oldmem, size_t newlen, size_t oldlen)
+ static int doDevConfig(comedi_device *dev, comedi_devconfig *it)
+ {
+ 	int i;
+-	comedi_t *devs_opened[COMEDI_NUM_BOARD_MINORS];
++	void *devs_opened[COMEDI_NUM_BOARD_MINORS];
+ 
+ 	memset(devs_opened, 0, sizeof(devs_opened));
+ 	devpriv->name[0] = 0;;
+@@ -406,7 +406,7 @@ static int doDevConfig(comedi_device *dev, comedi_devconfig *it)
+ 	for (i = 0; i < COMEDI_NDEVCONFOPTS && (!i || it->options[i]); ++i) {
+ 		char file[] = "/dev/comediXXXXXX";
+ 		int minor = it->options[i];
+-		comedi_t *d;
++		void *d;
+ 		int sdev = -1, nchans, tmp;
+ 		struct BondedDevice *bdev = NULL;
+ 
+diff --git a/drivers/staging/comedi/kcomedilib/data.c b/drivers/staging/comedi/kcomedilib/data.c
+index 4f1a41d50861..f63a506dd8ab 100644
+--- a/drivers/staging/comedi/kcomedilib/data.c
++++ b/drivers/staging/comedi/kcomedilib/data.c
+@@ -27,7 +27,7 @@
+ 
+ #include 
+ 
+-int comedi_data_write(comedi_t *dev, unsigned int subdev, unsigned int chan,
++int comedi_data_write(void *dev, unsigned int subdev, unsigned int chan,
+ 	unsigned int range, unsigned int aref, lsampl_t data)
+ {
+ 	comedi_insn insn;
+@@ -42,7 +42,7 @@ int comedi_data_write(comedi_t *dev, unsigned int subdev, unsigned int chan,
+ 	return comedi_do_insn(dev, &insn);
+ }
+ 
+-int comedi_data_read(comedi_t *dev, unsigned int subdev, unsigned int chan,
++int comedi_data_read(void *dev, unsigned int subdev, unsigned int chan,
+ 	unsigned int range, unsigned int aref, lsampl_t *data)
+ {
+ 	comedi_insn insn;
+@@ -57,7 +57,7 @@ int comedi_data_read(comedi_t *dev, unsigned int subdev, unsigned int chan,
+ 	return comedi_do_insn(dev, &insn);
+ }
+ 
+-int comedi_data_read_hint(comedi_t *dev, unsigned int subdev,
++int comedi_data_read_hint(void *dev, unsigned int subdev,
+ 	unsigned int chan, unsigned int range, unsigned int aref)
+ {
+ 	comedi_insn insn;
+@@ -73,7 +73,7 @@ int comedi_data_read_hint(comedi_t *dev, unsigned int subdev,
+ 	return comedi_do_insn(dev, &insn);
+ }
+ 
+-int comedi_data_read_delayed(comedi_t *dev, unsigned int subdev,
++int comedi_data_read_delayed(void *dev, unsigned int subdev,
+ 	unsigned int chan, unsigned int range, unsigned int aref,
+ 	lsampl_t *data, unsigned int nano_sec)
+ {
+diff --git a/drivers/staging/comedi/kcomedilib/dio.c b/drivers/staging/comedi/kcomedilib/dio.c
+index 823052776e93..78e63c84072d 100644
+--- a/drivers/staging/comedi/kcomedilib/dio.c
++++ b/drivers/staging/comedi/kcomedilib/dio.c
+@@ -26,7 +26,7 @@
+ 
+ #include 
+ 
+-int comedi_dio_config(comedi_t *dev, unsigned int subdev, unsigned int chan,
++int comedi_dio_config(void *dev, unsigned int subdev, unsigned int chan,
+ 	unsigned int io)
+ {
+ 	comedi_insn insn;
+@@ -41,7 +41,7 @@ int comedi_dio_config(comedi_t *dev, unsigned int subdev, unsigned int chan,
+ 	return comedi_do_insn(dev, &insn);
+ }
+ 
+-int comedi_dio_read(comedi_t *dev, unsigned int subdev, unsigned int chan,
++int comedi_dio_read(void *dev, unsigned int subdev, unsigned int chan,
+ 	unsigned int *val)
+ {
+ 	comedi_insn insn;
+@@ -56,7 +56,7 @@ int comedi_dio_read(comedi_t *dev, unsigned int subdev, unsigned int chan,
+ 	return comedi_do_insn(dev, &insn);
+ }
+ 
+-int comedi_dio_write(comedi_t *dev, unsigned int subdev, unsigned int chan,
++int comedi_dio_write(void *dev, unsigned int subdev, unsigned int chan,
+ 	unsigned int val)
+ {
+ 	comedi_insn insn;
+@@ -71,7 +71,7 @@ int comedi_dio_write(comedi_t *dev, unsigned int subdev, unsigned int chan,
+ 	return comedi_do_insn(dev, &insn);
+ }
+ 
+-int comedi_dio_bitfield(comedi_t *dev, unsigned int subdev, unsigned int mask,
++int comedi_dio_bitfield(void *dev, unsigned int subdev, unsigned int mask,
+ 	unsigned int *bits)
+ {
+ 	comedi_insn insn;
+diff --git a/drivers/staging/comedi/kcomedilib/get.c b/drivers/staging/comedi/kcomedilib/get.c
+index 36778b30f396..5a69d8cf1567 100644
+--- a/drivers/staging/comedi/kcomedilib/get.c
++++ b/drivers/staging/comedi/kcomedilib/get.c
+@@ -26,33 +26,33 @@
+ #include "../comedilib.h"
+ #include "../comedidev.h"
+ 
+-int comedi_get_n_subdevices(comedi_t *d)
++int comedi_get_n_subdevices(void *d)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 
+ 	return dev->n_subdevices;
+ }
+ 
+-int comedi_get_version_code(comedi_t *d)
++int comedi_get_version_code(void *d)
+ {
+ 	return COMEDI_VERSION_CODE;
+ }
+ 
+-const char *comedi_get_driver_name(comedi_t * d)
++const char *comedi_get_driver_name(void * d)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 
+ 	return dev->driver->driver_name;
+ }
+ 
+-const char *comedi_get_board_name(comedi_t * d)
++const char *comedi_get_board_name(void * d)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 
+ 	return dev->board_name;
+ }
+ 
+-int comedi_get_subdevice_type(comedi_t *d, unsigned int subdevice)
++int comedi_get_subdevice_type(void *d, unsigned int subdevice)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+@@ -60,7 +60,7 @@ int comedi_get_subdevice_type(comedi_t *d, unsigned int subdevice)
+ 	return s->type;
+ }
+ 
+-unsigned int comedi_get_subdevice_flags(comedi_t *d, unsigned int subdevice)
++unsigned int comedi_get_subdevice_flags(void *d, unsigned int subdevice)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+@@ -68,7 +68,7 @@ unsigned int comedi_get_subdevice_flags(comedi_t *d, unsigned int subdevice)
+ 	return s->subdev_flags;
+ }
+ 
+-int comedi_find_subdevice_by_type(comedi_t *d, int type, unsigned int subd)
++int comedi_find_subdevice_by_type(void *d, int type, unsigned int subd)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 
+@@ -82,7 +82,7 @@ int comedi_find_subdevice_by_type(comedi_t *d, int type, unsigned int subd)
+ 	return -1;
+ }
+ 
+-int comedi_get_n_channels(comedi_t *d, unsigned int subdevice)
++int comedi_get_n_channels(void *d, unsigned int subdevice)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+@@ -90,7 +90,7 @@ int comedi_get_n_channels(comedi_t *d, unsigned int subdevice)
+ 	return s->n_chan;
+ }
+ 
+-int comedi_get_len_chanlist(comedi_t *d, unsigned int subdevice)
++int comedi_get_len_chanlist(void *d, unsigned int subdevice)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+@@ -98,7 +98,7 @@ int comedi_get_len_chanlist(comedi_t *d, unsigned int subdevice)
+ 	return s->len_chanlist;
+ }
+ 
+-lsampl_t comedi_get_maxdata(comedi_t *d, unsigned int subdevice,
++lsampl_t comedi_get_maxdata(void *d, unsigned int subdevice,
+ 	unsigned int chan)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+@@ -111,7 +111,7 @@ lsampl_t comedi_get_maxdata(comedi_t *d, unsigned int subdevice,
+ }
+ 
+ #ifdef KCOMEDILIB_DEPRECATED
+-int comedi_get_rangetype(comedi_t *d, unsigned int subdevice,
++int comedi_get_rangetype(void *d, unsigned int subdevice,
+ 	unsigned int chan)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+@@ -130,7 +130,7 @@ int comedi_get_rangetype(comedi_t *d, unsigned int subdevice,
+ }
+ #endif
+ 
+-int comedi_get_n_ranges(comedi_t *d, unsigned int subdevice, unsigned int chan)
++int comedi_get_n_ranges(void *d, unsigned int subdevice, unsigned int chan)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+@@ -148,7 +148,7 @@ int comedi_get_n_ranges(comedi_t *d, unsigned int subdevice, unsigned int chan)
+ /*
+  * ALPHA (non-portable)
+ */
+-int comedi_get_krange(comedi_t *d, unsigned int subdevice, unsigned int chan,
++int comedi_get_krange(void *d, unsigned int subdevice, unsigned int chan,
+ 	unsigned int range, comedi_krange *krange)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+@@ -171,7 +171,7 @@ int comedi_get_krange(comedi_t *d, unsigned int subdevice, unsigned int chan,
+ /*
+  * ALPHA (may be renamed)
+ */
+-unsigned int comedi_get_buf_head_pos(comedi_t *d, unsigned int subdevice)
++unsigned int comedi_get_buf_head_pos(void *d, unsigned int subdevice)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+@@ -184,7 +184,7 @@ unsigned int comedi_get_buf_head_pos(comedi_t *d, unsigned int subdevice)
+ 	return async->buf_write_count;
+ }
+ 
+-int comedi_get_buffer_contents(comedi_t *d, unsigned int subdevice)
++int comedi_get_buffer_contents(void *d, unsigned int subdevice)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+@@ -203,7 +203,7 @@ int comedi_get_buffer_contents(comedi_t *d, unsigned int subdevice)
+ /*
+  * ALPHA
+ */
+-int comedi_set_user_int_count(comedi_t *d, unsigned int subdevice,
++int comedi_set_user_int_count(void *d, unsigned int subdevice,
+ 	unsigned int buf_user_count)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+@@ -224,7 +224,7 @@ int comedi_set_user_int_count(comedi_t *d, unsigned int subdevice,
+ 	return 0;
+ }
+ 
+-int comedi_mark_buffer_read(comedi_t *d, unsigned int subdevice,
++int comedi_mark_buffer_read(void *d, unsigned int subdevice,
+ 	unsigned int num_bytes)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+@@ -243,7 +243,7 @@ int comedi_mark_buffer_read(comedi_t *d, unsigned int subdevice,
+ 	return 0;
+ }
+ 
+-int comedi_mark_buffer_written(comedi_t *d, unsigned int subdevice,
++int comedi_mark_buffer_written(void *d, unsigned int subdevice,
+ 	unsigned int num_bytes)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+@@ -263,7 +263,7 @@ int comedi_mark_buffer_written(comedi_t *d, unsigned int subdevice,
+ 	return 0;
+ }
+ 
+-int comedi_get_buffer_size(comedi_t *d, unsigned int subdev)
++int comedi_get_buffer_size(void *d, unsigned int subdev)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdev;
+@@ -278,7 +278,7 @@ int comedi_get_buffer_size(comedi_t *d, unsigned int subdev)
+ 	return async->prealloc_bufsz;
+ }
+ 
+-int comedi_get_buffer_offset(comedi_t *d, unsigned int subdevice)
++int comedi_get_buffer_offset(void *d, unsigned int subdevice)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+index 7818e391dcab..0320a0ce74e9 100644
+--- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
++++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+@@ -42,7 +42,7 @@ MODULE_AUTHOR("David Schleef ");
+ MODULE_DESCRIPTION("Comedi kernel library");
+ MODULE_LICENSE("GPL");
+ 
+-comedi_t *comedi_open(const char *filename)
++void *comedi_open(const char *filename)
+ {
+ 	struct comedi_device_file_info *dev_file_info;
+ 	comedi_device *dev;
+@@ -67,10 +67,10 @@ comedi_t *comedi_open(const char *filename)
+ 	if (!try_module_get(dev->driver->module))
+ 		return NULL;
+ 
+-	return (comedi_t *) dev;
++	return (void *) dev;
+ }
+ 
+-comedi_t *comedi_open_old(unsigned int minor)
++void *comedi_open_old(unsigned int minor)
+ {
+ 	struct comedi_device_file_info *dev_file_info;
+ 	comedi_device *dev;
+@@ -86,10 +86,10 @@ comedi_t *comedi_open_old(unsigned int minor)
+ 	if (dev == NULL || !dev->attached)
+ 		return NULL;
+ 
+-	return (comedi_t *) dev;
++	return (void *) dev;
+ }
+ 
+-int comedi_close(comedi_t *d)
++int comedi_close(void *d)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 
+@@ -113,7 +113,7 @@ char *comedi_strerror(int err)
+ 	return "unknown error";
+ }
+ 
+-int comedi_fileno(comedi_t *d)
++int comedi_fileno(void *d)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 
+@@ -121,7 +121,7 @@ int comedi_fileno(comedi_t *d)
+ 	return dev->minor;
+ }
+ 
+-int comedi_command(comedi_t *d, comedi_cmd *cmd)
++int comedi_command(void *d, comedi_cmd *cmd)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s;
+@@ -161,7 +161,7 @@ int comedi_command(comedi_t *d, comedi_cmd *cmd)
+ 	return s->do_cmd(dev, s);
+ }
+ 
+-int comedi_command_test(comedi_t *d, comedi_cmd *cmd)
++int comedi_command_test(void *d, comedi_cmd *cmd)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s;
+@@ -183,7 +183,7 @@ int comedi_command_test(comedi_t *d, comedi_cmd *cmd)
+  *	COMEDI_INSN
+  *	perform an instruction
+  */
+-int comedi_do_insn(comedi_t *d, comedi_insn *insn)
++int comedi_do_insn(void *d, comedi_insn *insn)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s;
+@@ -324,7 +324,7 @@ int comedi_do_insn(comedi_t *d, comedi_insn *insn)
+ 	- lock while subdevice being programmed
+ 
+ */
+-int comedi_lock(comedi_t *d, unsigned int subdevice)
++int comedi_lock(void *d, unsigned int subdevice)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s;
+@@ -367,7 +367,7 @@ int comedi_lock(comedi_t *d, unsigned int subdevice)
+ 		none
+ 
+ */
+-int comedi_unlock(comedi_t *d, unsigned int subdevice)
++int comedi_unlock(void *d, unsigned int subdevice)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s;
+@@ -419,7 +419,7 @@ int comedi_unlock(comedi_t *d, unsigned int subdevice)
+ 		nothing
+ 
+ */
+-int comedi_cancel(comedi_t *d, unsigned int subdevice)
++int comedi_cancel(void *d, unsigned int subdevice)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s;
+@@ -464,7 +464,7 @@ int comedi_cancel(comedi_t *d, unsigned int subdevice)
+ /*
+    registration of callback functions
+  */
+-int comedi_register_callback(comedi_t *d, unsigned int subdevice,
++int comedi_register_callback(void *d, unsigned int subdevice,
+ 	unsigned int mask, int (*cb) (unsigned int, void *), void *arg)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+@@ -501,7 +501,7 @@ int comedi_register_callback(comedi_t *d, unsigned int subdevice,
+ 	return 0;
+ }
+ 
+-int comedi_poll(comedi_t *d, unsigned int subdevice)
++int comedi_poll(void *d, unsigned int subdevice)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices;
+@@ -528,7 +528,7 @@ int comedi_poll(comedi_t *d, unsigned int subdevice)
+ }
+ 
+ /* WARNING: not portable */
+-int comedi_map(comedi_t *d, unsigned int subdevice, void *ptr)
++int comedi_map(void *d, unsigned int subdevice, void *ptr)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s;
+@@ -550,7 +550,7 @@ int comedi_map(comedi_t *d, unsigned int subdevice, void *ptr)
+ }
+ 
+ /* WARNING: not portable */
+-int comedi_unmap(comedi_t *d, unsigned int subdevice)
++int comedi_unmap(void *d, unsigned int subdevice)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s;

commit 2e561b12e84a5363846669c5e0c070baf4d06a1a
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:04:50 2009 -0400
+
+    Staging: comedi: Remove V_FP_V typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/rt.c b/drivers/staging/comedi/rt.c
+index e6ec8b98a15d..fa99d6942b45 100644
+--- a/drivers/staging/comedi/rt.c
++++ b/drivers/staging/comedi/rt.c
+@@ -220,8 +220,7 @@ DECLARE_VOID_IRQ(21);
+ DECLARE_VOID_IRQ(22);
+ DECLARE_VOID_IRQ(23);
+ 
+-typedef void (*V_FP_V) (void);
+-static V_FP_V handle_void_irq_ptrs[] = {
++static void handle_void_irq_ptrs[] = {
+ 	handle_void_irq_0,
+ 	handle_void_irq_1,
+ 	handle_void_irq_2,

commit eb5e029ebacf37ccdcd25b804e005f7e69cd0a24
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:04:45 2009 -0400
+
+    Staging: comedi: Remove s626_board typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
+index d447f466d333..9323fa00fbb8 100644
+--- a/drivers/staging/comedi/drivers/s626.c
++++ b/drivers/staging/comedi/drivers/s626.c
+@@ -82,7 +82,7 @@ MODULE_AUTHOR("Gianluca Palli ");
+ MODULE_DESCRIPTION("Sensoray 626 Comedi driver module");
+ MODULE_LICENSE("GPL");
+ 
+-typedef struct s626_board_struct {
++struct s626_board {
+ 	const char *name;
+ 	int ai_chans;
+ 	int ai_bits;
+@@ -91,9 +91,9 @@ typedef struct s626_board_struct {
+ 	int dio_chans;
+ 	int dio_banks;
+ 	int enc_chans;
+-} s626_board;
++};
+ 
+-static const s626_board s626_boards[] = {
++static const struct s626_board s626_boards[] = {
+ 	{
+ 	      name:	"s626",
+ 	      ai_chans : S626_ADC_CHANNELS,
+@@ -106,7 +106,7 @@ static const s626_board s626_boards[] = {
+ 		}
+ };
+ 
+-#define thisboard ((const s626_board *)dev->board_ptr)
++#define thisboard ((const struct s626_board *)dev->board_ptr)
+ #define PCI_VENDOR_ID_S626 0x1131
+ #define PCI_DEVICE_ID_S626 0x7146
+ 
+@@ -128,7 +128,7 @@ static comedi_driver driver_s626 = {
+       detach : s626_detach,
+ };
+ 
+-typedef struct {
++struct s626_private {
+ 	struct pci_dev *pdev;
+ 	void *base_addr;
+ 	int got_regions;
+@@ -158,9 +158,9 @@ typedef struct {
+ 	/* I2C device address for onboard EEPROM (board rev dependent). */
+ 	/*   short         I2Cards; */
+ 	lsampl_t ao_readback[S626_DAC_CHANNELS];
+-} s626_private;
++};
+ 
+-typedef struct {
++struct dio_private {
+ 	uint16_t RDDIn;
+ 	uint16_t WRDOut;
+ 	uint16_t RDEdgSel;
+@@ -170,9 +170,9 @@ typedef struct {
+ 	uint16_t RDCapFlg;
+ 	uint16_t RDIntSel;
+ 	uint16_t WRIntSel;
+-} dio_private;
++};
+ 
+-static dio_private dio_private_A = {
++static struct dio_private dio_private_A = {
+       RDDIn:LP_RDDINA,
+       WRDOut : LP_WRDOUTA,
+       RDEdgSel : LP_RDEDGSELA,
+@@ -184,7 +184,7 @@ static dio_private dio_private_A = {
+       WRIntSel : LP_WRINTSELA,
+ };
+ 
+-static dio_private dio_private_B = {
++static struct dio_private dio_private_B = {
+       RDDIn:LP_RDDINB,
+       WRDOut : LP_WRDOUTB,
+       RDEdgSel : LP_RDEDGSELB,
+@@ -196,7 +196,7 @@ static dio_private dio_private_B = {
+       WRIntSel : LP_WRINTSELB,
+ };
+ 
+-static dio_private dio_private_C = {
++static struct dio_private dio_private_C = {
+       RDDIn:LP_RDDINC,
+       WRDOut : LP_WRDOUTC,
+       RDEdgSel : LP_RDEDGSELC,
+@@ -209,15 +209,15 @@ static dio_private dio_private_C = {
+ };
+ 
+ /* to group dio devices (48 bits mask and data are not allowed ???)
+-static dio_private *dio_private_word[]={
++static struct dio_private *dio_private_word[]={
+   &dio_private_A,
+   &dio_private_B,
+   &dio_private_C,
+ };
+ */
+ 
+-#define devpriv ((s626_private *)dev->private)
+-#define diopriv ((dio_private *)s->private)
++#define devpriv ((struct s626_private *)dev->private)
++#define diopriv ((struct dio_private *)s->private)
+ 
+ COMEDI_PCI_INITCLEANUP_NOMODULE(driver_s626, s626_pci_table);
+ 
+@@ -278,67 +278,67 @@ static void DEBIreplace(comedi_device *dev, uint16_t addr, uint16_t mask,
+ static void CloseDMAB(comedi_device *dev, DMABUF *pdma, size_t bsize);
+ 
+ /*  COUNTER OBJECT ------------------------------------------------ */
+-typedef struct enc_private_struct {
++struct enc_private {
+ 	/*  Pointers to functions that differ for A and B counters: */
+-	uint16_t(*GetEnable) (comedi_device *dev, struct enc_private_struct *);	/* Return clock enable. */
+-	uint16_t(*GetIntSrc) (comedi_device *dev, struct enc_private_struct *);	/* Return interrupt source. */
+-	uint16_t(*GetLoadTrig) (comedi_device *dev, struct enc_private_struct *);	/* Return preload trigger source. */
+-	uint16_t(*GetMode) (comedi_device *dev, struct enc_private_struct *);	/* Return standardized operating mode. */
+-	void (*PulseIndex) (comedi_device *dev, struct enc_private_struct *);	/* Generate soft index strobe. */
+-	void (*SetEnable) (comedi_device *dev, struct enc_private_struct *, uint16_t enab);	/* Program clock enable. */
+-	void (*SetIntSrc) (comedi_device *dev, struct enc_private_struct *, uint16_t IntSource);	/* Program interrupt source. */
+-	void (*SetLoadTrig) (comedi_device *dev, struct enc_private_struct *, uint16_t Trig);	/* Program preload trigger source. */
+-	void (*SetMode) (comedi_device *dev, struct enc_private_struct *, uint16_t Setup, uint16_t DisableIntSrc);	/* Program standardized operating mode. */
+-	void (*ResetCapFlags) (comedi_device *dev, struct enc_private_struct *);	/* Reset event capture flags. */
++	uint16_t(*GetEnable) (comedi_device *dev, struct enc_private *);	/* Return clock enable. */
++	uint16_t(*GetIntSrc) (comedi_device *dev, struct enc_private *);	/* Return interrupt source. */
++	uint16_t(*GetLoadTrig) (comedi_device *dev, struct enc_private *);	/* Return preload trigger source. */
++	uint16_t(*GetMode) (comedi_device *dev, struct enc_private *);	/* Return standardized operating mode. */
++	void (*PulseIndex) (comedi_device *dev, struct enc_private *);	/* Generate soft index strobe. */
++	void (*SetEnable) (comedi_device *dev, struct enc_private *, uint16_t enab);	/* Program clock enable. */
++	void (*SetIntSrc) (comedi_device *dev, struct enc_private *, uint16_t IntSource);	/* Program interrupt source. */
++	void (*SetLoadTrig) (comedi_device *dev, struct enc_private *, uint16_t Trig);	/* Program preload trigger source. */
++	void (*SetMode) (comedi_device *dev, struct enc_private *, uint16_t Setup, uint16_t DisableIntSrc);	/* Program standardized operating mode. */
++	void (*ResetCapFlags) (comedi_device *dev, struct enc_private *);	/* Reset event capture flags. */
+ 
+ 	uint16_t MyCRA;		/*    Address of CRA register. */
+ 	uint16_t MyCRB;		/*    Address of CRB register. */
+ 	uint16_t MyLatchLsw;	/*    Address of Latch least-significant-word */
+ 	/*    register. */
+ 	uint16_t MyEventBits[4];	/*    Bit translations for IntSrc -->RDMISC2. */
+-} enc_private;			/* counter object */
++};
+ 
+-#define encpriv ((enc_private *)(dev->subdevices+5)->private)
++#define encpriv ((struct enc_private *)(dev->subdevices+5)->private)
+ 
+ /* counters routines */
+-static void s626_timer_load(comedi_device *dev, enc_private *k, int tick);
+-static uint32_t ReadLatch(comedi_device *dev, enc_private *k);
+-static void ResetCapFlags_A(comedi_device *dev, enc_private *k);
+-static void ResetCapFlags_B(comedi_device *dev, enc_private *k);
+-static uint16_t GetMode_A(comedi_device *dev, enc_private *k);
+-static uint16_t GetMode_B(comedi_device *dev, enc_private *k);
+-static void SetMode_A(comedi_device *dev, enc_private *k, uint16_t Setup,
++static void s626_timer_load(comedi_device *dev, struct enc_private *k, int tick);
++static uint32_t ReadLatch(comedi_device *dev, struct enc_private *k);
++static void ResetCapFlags_A(comedi_device *dev, struct enc_private *k);
++static void ResetCapFlags_B(comedi_device *dev, struct enc_private *k);
++static uint16_t GetMode_A(comedi_device *dev, struct enc_private *k);
++static uint16_t GetMode_B(comedi_device *dev, struct enc_private *k);
++static void SetMode_A(comedi_device *dev, struct enc_private *k, uint16_t Setup,
+ 	uint16_t DisableIntSrc);
+-static void SetMode_B(comedi_device *dev, enc_private *k, uint16_t Setup,
++static void SetMode_B(comedi_device *dev, struct enc_private *k, uint16_t Setup,
+ 	uint16_t DisableIntSrc);
+-static void SetEnable_A(comedi_device *dev, enc_private *k, uint16_t enab);
+-static void SetEnable_B(comedi_device *dev, enc_private *k, uint16_t enab);
+-static uint16_t GetEnable_A(comedi_device *dev, enc_private *k);
+-static uint16_t GetEnable_B(comedi_device *dev, enc_private *k);
+-static void SetLatchSource(comedi_device *dev, enc_private *k,
++static void SetEnable_A(comedi_device *dev, struct enc_private *k, uint16_t enab);
++static void SetEnable_B(comedi_device *dev, struct enc_private *k, uint16_t enab);
++static uint16_t GetEnable_A(comedi_device *dev, struct enc_private *k);
++static uint16_t GetEnable_B(comedi_device *dev, struct enc_private *k);
++static void SetLatchSource(comedi_device *dev, struct enc_private *k,
+ 	uint16_t value);
+-/* static uint16_t GetLatchSource(comedi_device *dev, enc_private *k ); */
+-static void SetLoadTrig_A(comedi_device *dev, enc_private *k, uint16_t Trig);
+-static void SetLoadTrig_B(comedi_device *dev, enc_private *k, uint16_t Trig);
+-static uint16_t GetLoadTrig_A(comedi_device *dev, enc_private *k);
+-static uint16_t GetLoadTrig_B(comedi_device *dev, enc_private *k);
+-static void SetIntSrc_B(comedi_device *dev, enc_private *k,
++/* static uint16_t GetLatchSource(comedi_device *dev, struct enc_private *k ); */
++static void SetLoadTrig_A(comedi_device *dev, struct enc_private *k, uint16_t Trig);
++static void SetLoadTrig_B(comedi_device *dev, struct enc_private *k, uint16_t Trig);
++static uint16_t GetLoadTrig_A(comedi_device *dev, struct enc_private *k);
++static uint16_t GetLoadTrig_B(comedi_device *dev, struct enc_private *k);
++static void SetIntSrc_B(comedi_device *dev, struct enc_private *k,
+ 	uint16_t IntSource);
+-static void SetIntSrc_A(comedi_device *dev, enc_private *k,
++static void SetIntSrc_A(comedi_device *dev, struct enc_private *k,
+ 	uint16_t IntSource);
+-static uint16_t GetIntSrc_A(comedi_device *dev, enc_private *k);
+-static uint16_t GetIntSrc_B(comedi_device *dev, enc_private *k);
+-/* static void SetClkMult(comedi_device *dev, enc_private *k, uint16_t value ) ; */
+-/* static uint16_t GetClkMult(comedi_device *dev, enc_private *k ) ; */
+-/* static void SetIndexPol(comedi_device *dev, enc_private *k, uint16_t value ); */
+-/* static uint16_t GetClkPol(comedi_device *dev, enc_private *k ) ; */
+-/* static void SetIndexSrc( comedi_device *dev,enc_private *k, uint16_t value );  */
+-/* static uint16_t GetClkSrc( comedi_device *dev,enc_private *k );  */
+-/* static void SetIndexSrc( comedi_device *dev,enc_private *k, uint16_t value );  */
+-/* static uint16_t GetIndexSrc( comedi_device *dev,enc_private *k );  */
+-static void PulseIndex_A(comedi_device *dev, enc_private *k);
+-static void PulseIndex_B(comedi_device *dev, enc_private *k);
+-static void Preload(comedi_device *dev, enc_private *k, uint32_t value);
++static uint16_t GetIntSrc_A(comedi_device *dev, struct enc_private *k);
++static uint16_t GetIntSrc_B(comedi_device *dev, struct enc_private *k);
++/* static void SetClkMult(comedi_device *dev, struct enc_private *k, uint16_t value ) ; */
++/* static uint16_t GetClkMult(comedi_device *dev, struct enc_private *k ) ; */
++/* static void SetIndexPol(comedi_device *dev, struct enc_private *k, uint16_t value ); */
++/* static uint16_t GetClkPol(comedi_device *dev, struct enc_private *k ) ; */
++/* static void SetIndexSrc( comedi_device *dev,struct enc_private *k, uint16_t value );  */
++/* static uint16_t GetClkSrc( comedi_device *dev,struct enc_private *k );  */
++/* static void SetIndexSrc( comedi_device *dev,struct enc_private *k, uint16_t value );  */
++/* static uint16_t GetIndexSrc( comedi_device *dev,struct enc_private *k );  */
++static void PulseIndex_A(comedi_device *dev, struct enc_private *k);
++static void PulseIndex_B(comedi_device *dev, struct enc_private *k);
++static void Preload(comedi_device *dev, struct enc_private *k, uint32_t value);
+ static void CountersInit(comedi_device *dev);
+ /* end internal routines */
+ 
+@@ -352,8 +352,8 @@ static void CountersInit(comedi_device *dev);
+ /*  Translation table to map IntSrc into equivalent RDMISC2 event flag  bits. */
+ /* static const uint16_t EventBits[][4] = { EVBITS(0), EVBITS(1), EVBITS(2), EVBITS(3), EVBITS(4), EVBITS(5) }; */
+ 
+-/* enc_private; */
+-static enc_private enc_private_data[] = {
++/* struct enc_private; */
++static struct enc_private enc_private_data[] = {
+ 	{
+ 	      GetEnable:GetEnable_A,
+ 	      GetIntSrc : GetIntSrc_A,
+@@ -500,7 +500,7 @@ static int s626_attach(comedi_device *dev, comedi_devconfig *it)
+ 	comedi_subdevice *s;
+ 	struct pci_dev *pdev;
+ 
+-	if (alloc_private(dev, sizeof(s626_private)) < 0)
++	if (alloc_private(dev, sizeof(struct s626_private)) < 0)
+ 		return -ENOMEM;
+ 
+ 	for (pdev = pci_get_device(PCI_VENDOR_ID_S626, PCI_DEVICE_ID_S626,
+@@ -973,7 +973,7 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG)
+ 	comedi_device *dev = d;
+ 	comedi_subdevice *s;
+ 	comedi_cmd *cmd;
+-	enc_private *k;
++	struct enc_private *k;
+ 	unsigned long flags;
+ 	int32_t *readaddr;
+ 	uint32_t irqtype, irqstatus;
+@@ -1078,7 +1078,7 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG)
+ 			irqbit = 0;
+ 			/* read interrupt type */
+ 			irqbit = DEBIread(dev,
+-				((dio_private *) (dev->subdevices + 2 +
++				((struct dio_private *) (dev->subdevices + 2 +
+ 						group)->private)->RDCapFlg);
+ 
+ 			/* check if interrupt is generated from dio channels */
+@@ -1678,7 +1678,7 @@ static int s626_ai_cmd(comedi_device *dev, comedi_subdevice *s)
+ 
+ 	uint8_t ppl[16];
+ 	comedi_cmd *cmd = &s->async->cmd;
+-	enc_private *k;
++	struct enc_private *k;
+ 	int tick;
+ 
+ 	DEBUG("s626_ai_cmd: entering command function\n");
+@@ -2187,18 +2187,18 @@ static int s626_dio_set_irq(comedi_device *dev, unsigned int chan)
+ 
+ 	/* set channel to capture positive edge */
+ 	status = DEBIread(dev,
+-		((dio_private *) (dev->subdevices + 2 +
++		((struct dio_private *) (dev->subdevices + 2 +
+ 				group)->private)->RDEdgSel);
+ 	DEBIwrite(dev,
+-		((dio_private *) (dev->subdevices + 2 +
++		((struct dio_private *) (dev->subdevices + 2 +
+ 				group)->private)->WREdgSel, bitmask | status);
+ 
+ 	/* enable interrupt on selected channel */
+ 	status = DEBIread(dev,
+-		((dio_private *) (dev->subdevices + 2 +
++		((struct dio_private *) (dev->subdevices + 2 +
+ 				group)->private)->RDIntSel);
+ 	DEBIwrite(dev,
+-		((dio_private *) (dev->subdevices + 2 +
++		((struct dio_private *) (dev->subdevices + 2 +
+ 				group)->private)->WRIntSel, bitmask | status);
+ 
+ 	/* enable edge capture write command */
+@@ -2206,10 +2206,10 @@ static int s626_dio_set_irq(comedi_device *dev, unsigned int chan)
+ 
+ 	/* enable edge capture on selected channel */
+ 	status = DEBIread(dev,
+-		((dio_private *) (dev->subdevices + 2 +
++		((struct dio_private *) (dev->subdevices + 2 +
+ 				group)->private)->RDCapSel);
+ 	DEBIwrite(dev,
+-		((dio_private *) (dev->subdevices + 2 +
++		((struct dio_private *) (dev->subdevices + 2 +
+ 				group)->private)->WRCapSel, bitmask | status);
+ 
+ 	return 0;
+@@ -2225,7 +2225,7 @@ static int s626_dio_reset_irq(comedi_device *dev, unsigned int group,
+ 
+ 	/* enable edge capture on selected channel */
+ 	DEBIwrite(dev,
+-		((dio_private *) (dev->subdevices + 2 +
++		((struct dio_private *) (dev->subdevices + 2 +
+ 				group)->private)->WRCapSel, mask);
+ 
+ 	return 0;
+@@ -2241,7 +2241,7 @@ static int s626_dio_clear_irq(comedi_device *dev)
+ 	for (group = 0; group < S626_DIO_BANKS; group++) {
+ 		/* clear pending events and interrupt */
+ 		DEBIwrite(dev,
+-			((dio_private *) (dev->subdevices + 2 +
++			((struct dio_private *) (dev->subdevices + 2 +
+ 					group)->private)->WRCapSel, 0xffff);
+ 	}
+ 
+@@ -2266,7 +2266,7 @@ static int s626_enc_insn_config(comedi_device *dev, comedi_subdevice *s,
+ 	/*  uint32_t Preloadvalue;              //Counter initial value */
+ 	uint16_t valueSrclatch = LATCHSRC_AB_READ;
+ 	uint16_t enab = CLKENAB_ALWAYS;
+-	enc_private *k = &encpriv[CR_CHAN(insn->chanspec)];
++	struct enc_private *k = &encpriv[CR_CHAN(insn->chanspec)];
+ 
+ 	DEBUG("s626_enc_insn_config: encoder config\n");
+ 
+@@ -2286,7 +2286,7 @@ static int s626_enc_insn_read(comedi_device *dev, comedi_subdevice *s,
+ {
+ 
+ 	int n;
+-	enc_private *k = &encpriv[CR_CHAN(insn->chanspec)];
++	struct enc_private *k = &encpriv[CR_CHAN(insn->chanspec)];
+ 
+ 	DEBUG("s626_enc_insn_read: encoder read channel %d \n",
+ 		CR_CHAN(insn->chanspec));
+@@ -2303,7 +2303,7 @@ static int s626_enc_insn_write(comedi_device *dev, comedi_subdevice *s,
+ 	comedi_insn *insn, lsampl_t *data)
+ {
+ 
+-	enc_private *k = &encpriv[CR_CHAN(insn->chanspec)];
++	struct enc_private *k = &encpriv[CR_CHAN(insn->chanspec)];
+ 
+ 	DEBUG("s626_enc_insn_write: encoder write channel %d \n",
+ 		CR_CHAN(insn->chanspec));
+@@ -2322,7 +2322,7 @@ static int s626_enc_insn_write(comedi_device *dev, comedi_subdevice *s,
+ 	return 1;
+ }
+ 
+-static void s626_timer_load(comedi_device *dev, enc_private *k, int tick)
++static void s626_timer_load(comedi_device *dev, struct enc_private *k, int tick)
+ {
+ 	uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) |	/*  Preload upon */
+ 		/*  index. */
+@@ -2768,7 +2768,7 @@ static void CloseDMAB(comedi_device *dev, DMABUF *pdma, size_t bsize)
+ 
+ /*  Read a counter's output latch. */
+ 
+-static uint32_t ReadLatch(comedi_device *dev, enc_private *k)
++static uint32_t ReadLatch(comedi_device *dev, struct enc_private *k)
+ {
+ 	register uint32_t value;
+ 	/* DEBUG FIXME DEBUG("ReadLatch: Read Latch enter\n"); */
+@@ -2787,13 +2787,13 @@ static uint32_t ReadLatch(comedi_device *dev, enc_private *k)
+ 
+ /*  Reset a counter's index and overflow event capture flags. */
+ 
+-static void ResetCapFlags_A(comedi_device *dev, enc_private *k)
++static void ResetCapFlags_A(comedi_device *dev, struct enc_private *k)
+ {
+ 	DEBIreplace(dev, k->MyCRB, (uint16_t) (~CRBMSK_INTCTRL),
+ 		CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A);
+ }
+ 
+-static void ResetCapFlags_B(comedi_device *dev, enc_private *k)
++static void ResetCapFlags_B(comedi_device *dev, struct enc_private *k)
+ {
+ 	DEBIreplace(dev, k->MyCRB, (uint16_t) (~CRBMSK_INTCTRL),
+ 		CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B);
+@@ -2802,7 +2802,7 @@ static void ResetCapFlags_B(comedi_device *dev, enc_private *k)
+ /*  Return counter setup in a format (COUNTER_SETUP) that is consistent */
+ /*  for both A and B counters. */
+ 
+-static uint16_t GetMode_A(comedi_device *dev, enc_private *k)
++static uint16_t GetMode_A(comedi_device *dev, struct enc_private *k)
+ {
+ 	register uint16_t cra;
+ 	register uint16_t crb;
+@@ -2840,7 +2840,7 @@ static uint16_t GetMode_A(comedi_device *dev, enc_private *k)
+ 	return setup;
+ }
+ 
+-static uint16_t GetMode_B(comedi_device *dev, enc_private *k)
++static uint16_t GetMode_B(comedi_device *dev, struct enc_private *k)
+ {
+ 	register uint16_t cra;
+ 	register uint16_t crb;
+@@ -2886,7 +2886,7 @@ static uint16_t GetMode_B(comedi_device *dev, enc_private *k)
+  * ClkPol, ClkEnab, IndexSrc, IndexPol, LoadSrc.
+  */
+ 
+-static void SetMode_A(comedi_device *dev, enc_private *k, uint16_t Setup,
++static void SetMode_A(comedi_device *dev, struct enc_private *k, uint16_t Setup,
+ 	uint16_t DisableIntSrc)
+ {
+ 	register uint16_t cra;
+@@ -2944,7 +2944,7 @@ static void SetMode_A(comedi_device *dev, enc_private *k, uint16_t Setup,
+ 		(uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_A)), crb);
+ }
+ 
+-static void SetMode_B(comedi_device *dev, enc_private *k, uint16_t Setup,
++static void SetMode_B(comedi_device *dev, struct enc_private *k, uint16_t Setup,
+ 	uint16_t DisableIntSrc)
+ {
+ 	register uint16_t cra;
+@@ -3008,7 +3008,7 @@ static void SetMode_B(comedi_device *dev, enc_private *k, uint16_t Setup,
+ 
+ /*  Return/set a counter's enable.  enab: 0=always enabled, 1=enabled by index. */
+ 
+-static void SetEnable_A(comedi_device *dev, enc_private *k, uint16_t enab)
++static void SetEnable_A(comedi_device *dev, struct enc_private *k, uint16_t enab)
+ {
+ 	DEBUG("SetEnable_A: SetEnable_A enter 3541\n");
+ 	DEBIreplace(dev, k->MyCRB,
+@@ -3016,19 +3016,19 @@ static void SetEnable_A(comedi_device *dev, enc_private *k, uint16_t enab)
+ 		(uint16_t) (enab << CRBBIT_CLKENAB_A));
+ }
+ 
+-static void SetEnable_B(comedi_device *dev, enc_private *k, uint16_t enab)
++static void SetEnable_B(comedi_device *dev, struct enc_private *k, uint16_t enab)
+ {
+ 	DEBIreplace(dev, k->MyCRB,
+ 		(uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_B)),
+ 		(uint16_t) (enab << CRBBIT_CLKENAB_B));
+ }
+ 
+-static uint16_t GetEnable_A(comedi_device *dev, enc_private *k)
++static uint16_t GetEnable_A(comedi_device *dev, struct enc_private *k)
+ {
+ 	return (DEBIread(dev, k->MyCRB) >> CRBBIT_CLKENAB_A) & 1;
+ }
+ 
+-static uint16_t GetEnable_B(comedi_device *dev, enc_private *k)
++static uint16_t GetEnable_B(comedi_device *dev, struct enc_private *k)
+ {
+ 	return (DEBIread(dev, k->MyCRB) >> CRBBIT_CLKENAB_B) & 1;
+ }
+@@ -3038,7 +3038,7 @@ static uint16_t GetEnable_B(comedi_device *dev, enc_private *k)
+  * latches B.
+  */
+ 
+-static void SetLatchSource(comedi_device *dev, enc_private *k, uint16_t value)
++static void SetLatchSource(comedi_device *dev, struct enc_private *k, uint16_t value)
+ {
+ 	DEBUG("SetLatchSource: SetLatchSource enter 3550 \n");
+ 	DEBIreplace(dev, k->MyCRB,
+@@ -3049,7 +3049,7 @@ static void SetLatchSource(comedi_device *dev, enc_private *k, uint16_t value)
+ }
+ 
+ /*
+- * static uint16_t GetLatchSource(comedi_device *dev, enc_private *k )
++ * static uint16_t GetLatchSource(comedi_device *dev, struct enc_private *k )
+  * {
+  * 	return ( DEBIread( dev, k->MyCRB) >> CRBBIT_LATCHSRC ) & 3;
+  * }
+@@ -3061,25 +3061,25 @@ static void SetLatchSource(comedi_device *dev, enc_private *k, uint16_t value)
+  * 2=OverflowA (B counters only), 3=disabled.
+  */
+ 
+-static void SetLoadTrig_A(comedi_device *dev, enc_private *k, uint16_t Trig)
++static void SetLoadTrig_A(comedi_device *dev, struct enc_private *k, uint16_t Trig)
+ {
+ 	DEBIreplace(dev, k->MyCRA, (uint16_t) (~CRAMSK_LOADSRC_A),
+ 		(uint16_t) (Trig << CRABIT_LOADSRC_A));
+ }
+ 
+-static void SetLoadTrig_B(comedi_device *dev, enc_private *k, uint16_t Trig)
++static void SetLoadTrig_B(comedi_device *dev, struct enc_private *k, uint16_t Trig)
+ {
+ 	DEBIreplace(dev, k->MyCRB,
+ 		(uint16_t) (~(CRBMSK_LOADSRC_B | CRBMSK_INTCTRL)),
+ 		(uint16_t) (Trig << CRBBIT_LOADSRC_B));
+ }
+ 
+-static uint16_t GetLoadTrig_A(comedi_device *dev, enc_private *k)
++static uint16_t GetLoadTrig_A(comedi_device *dev, struct enc_private *k)
+ {
+ 	return (DEBIread(dev, k->MyCRA) >> CRABIT_LOADSRC_A) & 3;
+ }
+ 
+-static uint16_t GetLoadTrig_B(comedi_device *dev, enc_private *k)
++static uint16_t GetLoadTrig_B(comedi_device *dev, struct enc_private *k)
+ {
+ 	return (DEBIread(dev, k->MyCRB) >> CRBBIT_LOADSRC_B) & 3;
+ }
+@@ -3089,7 +3089,7 @@ static uint16_t GetLoadTrig_B(comedi_device *dev, enc_private *k)
+  * 2=IndexOnly, 3=IndexAndOverflow.
+  */
+ 
+-static void SetIntSrc_A(comedi_device *dev, enc_private *k,
++static void SetIntSrc_A(comedi_device *dev, struct enc_private *k,
+ 	uint16_t IntSource)
+ {
+ 	/*  Reset any pending counter overflow or index captures. */
+@@ -3106,7 +3106,7 @@ static void SetIntSrc_A(comedi_device *dev, enc_private *k,
+ 		MyEventBits[IntSource];
+ }
+ 
+-static void SetIntSrc_B(comedi_device *dev, enc_private *k,
++static void SetIntSrc_B(comedi_device *dev, struct enc_private *k,
+ 	uint16_t IntSource)
+ {
+ 	uint16_t crb;
+@@ -3129,80 +3129,80 @@ static void SetIntSrc_B(comedi_device *dev, enc_private *k,
+ 		MyEventBits[IntSource];
+ }
+ 
+-static uint16_t GetIntSrc_A(comedi_device *dev, enc_private *k)
++static uint16_t GetIntSrc_A(comedi_device *dev, struct enc_private *k)
+ {
+ 	return (DEBIread(dev, k->MyCRA) >> CRABIT_INTSRC_A) & 3;
+ }
+ 
+-static uint16_t GetIntSrc_B(comedi_device *dev, enc_private *k)
++static uint16_t GetIntSrc_B(comedi_device *dev, struct enc_private *k)
+ {
+ 	return (DEBIread(dev, k->MyCRB) >> CRBBIT_INTSRC_B) & 3;
+ }
+ 
+ /*  Return/set the clock multiplier. */
+ 
+-/* static void SetClkMult(comedi_device *dev, enc_private *k, uint16_t value )  */
++/* static void SetClkMult(comedi_device *dev, struct enc_private *k, uint16_t value )  */
+ /* { */
+ /*   k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKMULT ) | ( value << STDBIT_CLKMULT ) ), FALSE ); */
+ /* } */
+ 
+-/* static uint16_t GetClkMult(comedi_device *dev, enc_private *k )  */
++/* static uint16_t GetClkMult(comedi_device *dev, struct enc_private *k )  */
+ /* { */
+ /*   return ( k->GetMode(dev, k ) >> STDBIT_CLKMULT ) & 3; */
+ /* } */
+ 
+ /* Return/set the clock polarity. */
+ 
+-/* static void SetClkPol( comedi_device *dev,enc_private *k, uint16_t value )  */
++/* static void SetClkPol( comedi_device *dev,struct enc_private *k, uint16_t value )  */
+ /* { */
+ /*   k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKPOL ) | ( value << STDBIT_CLKPOL ) ), FALSE ); */
+ /* } */
+ 
+-/* static uint16_t GetClkPol(comedi_device *dev, enc_private *k )  */
++/* static uint16_t GetClkPol(comedi_device *dev, struct enc_private *k )  */
+ /* { */
+ /*   return ( k->GetMode(dev, k ) >> STDBIT_CLKPOL ) & 1; */
+ /* } */
+ 
+ /* Return/set the clock source.  */
+ 
+-/* static void SetClkSrc( comedi_device *dev,enc_private *k, uint16_t value )  */
++/* static void SetClkSrc( comedi_device *dev,struct enc_private *k, uint16_t value )  */
+ /* { */
+ /*   k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKSRC ) | ( value << STDBIT_CLKSRC ) ), FALSE ); */
+ /* } */
+ 
+-/* static uint16_t GetClkSrc( comedi_device *dev,enc_private *k )  */
++/* static uint16_t GetClkSrc( comedi_device *dev,struct enc_private *k )  */
+ /* { */
+ /*   return ( k->GetMode(dev, k ) >> STDBIT_CLKSRC ) & 3; */
+ /* } */
+ 
+ /* Return/set the index polarity. */
+ 
+-/* static void SetIndexPol(comedi_device *dev, enc_private *k, uint16_t value )  */
++/* static void SetIndexPol(comedi_device *dev, struct enc_private *k, uint16_t value )  */
+ /* { */
+ /*   k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_INDXPOL ) | ( (value != 0) << STDBIT_INDXPOL ) ), FALSE ); */
+ /* } */
+ 
+-/* static uint16_t GetIndexPol(comedi_device *dev, enc_private *k )  */
++/* static uint16_t GetIndexPol(comedi_device *dev, struct enc_private *k )  */
+ /* { */
+ /*   return ( k->GetMode(dev, k ) >> STDBIT_INDXPOL ) & 1; */
+ /* } */
+ 
+ /*  Return/set the index source. */
+ 
+-/* static void SetIndexSrc(comedi_device *dev, enc_private *k, uint16_t value )  */
++/* static void SetIndexSrc(comedi_device *dev, struct enc_private *k, uint16_t value )  */
+ /* { */
+ /*   DEBUG("SetIndexSrc: set index src enter 3700\n"); */
+ /*   k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_INDXSRC ) | ( (value != 0) << STDBIT_INDXSRC ) ), FALSE ); */
+ /* } */
+ 
+-/* static uint16_t GetIndexSrc(comedi_device *dev, enc_private *k )  */
++/* static uint16_t GetIndexSrc(comedi_device *dev, struct enc_private *k )  */
+ /* { */
+ /*   return ( k->GetMode(dev, k ) >> STDBIT_INDXSRC ) & 1; */
+ /* } */
+ 
+ /*  Generate an index pulse. */
+ 
+-static void PulseIndex_A(comedi_device *dev, enc_private *k)
++static void PulseIndex_A(comedi_device *dev, struct enc_private *k)
+ {
+ 	register uint16_t cra;
+ 
+@@ -3214,7 +3214,7 @@ static void PulseIndex_A(comedi_device *dev, enc_private *k)
+ 	DEBIwrite(dev, k->MyCRA, cra);
+ }
+ 
+-static void PulseIndex_B(comedi_device *dev, enc_private *k)
++static void PulseIndex_B(comedi_device *dev, struct enc_private *k)
+ {
+ 	register uint16_t crb;
+ 
+@@ -3225,7 +3225,7 @@ static void PulseIndex_B(comedi_device *dev, enc_private *k)
+ 
+ /*  Write value into counter preload register. */
+ 
+-static void Preload(comedi_device *dev, enc_private *k, uint32_t value)
++static void Preload(comedi_device *dev, struct enc_private *k, uint32_t value)
+ {
+ 	DEBUG("Preload: preload enter\n");
+ 	DEBIwrite(dev, (uint16_t) (k->MyLatchLsw), (uint16_t) value);	/*  Write value to preload register. */
+@@ -3237,7 +3237,7 @@ static void Preload(comedi_device *dev, enc_private *k, uint32_t value)
+ static void CountersInit(comedi_device *dev)
+ {
+ 	int chan;
+-	enc_private *k;
++	struct enc_private *k;
+ 	uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) |	/*  Preload upon */
+ 		/*  index. */
+ 		(INDXSRC_SOFT << BF_INDXSRC) |	/*  Disable hardware index. */

commit d80235ce8474396ec25a64b6c70e9bd8919f5cd4
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:04:40 2009 -0400
+
+    Staging: comedi: Remove rtdBoard typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
+index 95e4af27bd8d..f2fa4faa24a8 100644
+--- a/drivers/staging/comedi/drivers/rtd520.c
++++ b/drivers/staging/comedi/drivers/rtd520.c
+@@ -266,7 +266,7 @@ static const comedi_lrange rtd_ao_range = { 4, {
+ /*
+   Board descriptions
+  */
+-typedef struct rtdBoard_struct {
++struct rtdBoard {
+ 	const char *name;	/* must be first */
+ 	int device_id;
+ 	int aiChans;
+@@ -274,9 +274,9 @@ typedef struct rtdBoard_struct {
+ 	int aiMaxGain;
+ 	int range10Start;	/* start of +-10V range */
+ 	int rangeUniStart;	/* start of +10V range */
+-} rtdBoard;
++};
+ 
+-static const rtdBoard rtd520Boards[] = {
++static const struct rtdBoard rtd520Boards[] = {
+ 	{
+ 	      name:	"DM7520",
+ 	      device_id : 0x7520,
+@@ -308,13 +308,13 @@ MODULE_DEVICE_TABLE(pci, rtd520_pci_table);
+ /*
+  * Useful for shorthand access to the particular board structure
+  */
+-#define thisboard ((const rtdBoard *)dev->board_ptr)
++#define thisboard ((const struct rtdBoard *)dev->board_ptr)
+ 
+ /*
+    This structure is for data unique to this hardware driver.
+    This is also unique for each board in the system.
+ */
+-typedef struct {
++struct rtdPrivate {
+ 	/* memory mapped board structures */
+ 	void *las0;
+ 	void *las1;
+@@ -358,7 +358,7 @@ typedef struct {
+ 	u8 dma1Control;
+ #endif				/* USE_DMA */
+ 	unsigned fifoLen;
+-} rtdPrivate;
++};
+ 
+ /* bit defines for "flags" */
+ #define SEND_EOS	0x01	/* send End Of Scan events */
+@@ -377,7 +377,7 @@ typedef struct {
+  * most drivers define the following macro to make it easy to
+  * access the private structure.
+  */
+-#define devpriv ((rtdPrivate *)dev->private)
++#define devpriv ((struct rtdPrivate *)dev->private)
+ 
+ /* Macros to access registers */
+ 
+@@ -739,7 +739,7 @@ static int rtd_attach(comedi_device *dev, comedi_devconfig *it)
+ 	 * Allocate the private structure area.  alloc_private() is a
+ 	 * convenient macro defined in comedidev.h.
+ 	 */
+-	if (alloc_private(dev, sizeof(rtdPrivate)) < 0)
++	if (alloc_private(dev, sizeof(struct rtdPrivate)) < 0)
+ 		return -ENOMEM;
+ 
+ 	/*

commit 52bfe6c8e8746591e276de2594b8c98a51222d49
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:04:34 2009 -0400
+
+    Staging: comedi: Remove boardtype typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
+index d9ff56874483..41ce5ec058fa 100644
+--- a/drivers/staging/comedi/drivers/icp_multi.c
++++ b/drivers/staging/comedi/drivers/icp_multi.c
+@@ -133,7 +133,7 @@ static int icp_multi_detach(comedi_device *dev);
+ */
+ static unsigned short pci_list_builded = 0;	/*>0 list of card is known */
+ 
+-typedef struct {
++struct boardtype {
+ 	const char *name;	/*  driver name */
+ 	int device_id;
+ 	int iorange;		/*  I/O range len */
+@@ -150,9 +150,9 @@ typedef struct {
+ 	const comedi_lrange *rangelist_ai;	/*  rangelist for A/D */
+ 	const char *rangecode;	/*  range codes for programming */
+ 	const comedi_lrange *rangelist_ao;	/*  rangelist for D/A */
+-} boardtype;
++};
+ 
+-static const boardtype boardtypes[] = {
++static const struct boardtype boardtypes[] = {
+ 	{"icp_multi",		/*  Driver name */
+ 			DEVICE_ID,	/*  PCI device ID */
+ 			IORANGE_ICP_MULTI,	/*  I/O range length */
+@@ -171,7 +171,7 @@ static const boardtype boardtypes[] = {
+ 		&range_analog},	/*  Rangelist for D/A */
+ };
+ 
+-#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
++#define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype))
+ 
+ static comedi_driver driver_icp_multi = {
+       driver_name:"icp_multi",
+@@ -180,12 +180,12 @@ static comedi_driver driver_icp_multi = {
+       detach : icp_multi_detach,
+       num_names : n_boardtypes,
+       board_name : &boardtypes[0].name,
+-      offset : sizeof(boardtype),
++      offset : sizeof(struct boardtype),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_icp_multi);
+ 
+-typedef struct {
++struct icp_multi_private {
+ 	struct pcilst_struct *card;	/*  pointer to card */
+ 	char valid;		/*  card is usable */
+ 	void *io_addr;		/*  Pointer to mapped io address */
+@@ -202,10 +202,10 @@ typedef struct {
+ 	sampl_t ao_data[4];	/*  data output buffer */
+ 	sampl_t di_data;	/*  Digital input data */
+ 	unsigned int do_data;	/*  Remember digital output data */
+-} icp_multi_private;
++};
+ 
+-#define devpriv ((icp_multi_private *)dev->private)
+-#define this_board ((const boardtype *)dev->board_ptr)
++#define devpriv ((struct icp_multi_private *)dev->private)
++#define this_board ((const struct boardtype *)dev->board_ptr)
+ 
+ /*
+ ==============================================================================
+@@ -882,7 +882,7 @@ static int icp_multi_attach(comedi_device *dev, comedi_devconfig *it)
+ 	printk("icp_multi EDBG: BGN: icp_multi_attach(...)\n");
+ 
+ 	/*  Alocate private data storage space */
+-	ret = alloc_private(dev, sizeof(icp_multi_private));
++	ret = alloc_private(dev, sizeof(struct icp_multi_private));
+ 	if (ret < 0)
+ 		return ret;
+ 

commit bf8db92eb3c52ccc3c28ee8d382750a7d4dc758d
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:04:29 2009 -0400
+
+    Staging: comedi: Remove comedi32_chaninfo_struct typedef
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c
+index 7f5a86903c6f..600060ed73dd 100644
+--- a/drivers/staging/comedi/comedi_compat32.c
++++ b/drivers/staging/comedi/comedi_compat32.c
+@@ -38,30 +38,30 @@
+ #endif
+ 
+ #define COMEDI32_CHANINFO _IOR(CIO, 3, comedi32_chaninfo)
+-#define COMEDI32_RANGEINFO _IOR(CIO, 8, comedi32_rangeinfo)
++#define COMEDI32_RANGEINFO _IOR(CIO, 8, (struct comedi32_rangeinfo_struct))
+ /* N.B. COMEDI32_CMD and COMEDI_CMD ought to use _IOWR, not _IOR.
+  * It's too late to change it now, but it only affects the command number. */
+-#define COMEDI32_CMD _IOR(CIO, 9, comedi32_cmd)
++#define COMEDI32_CMD _IOR(CIO, 9, (struct comedi32_cmd_struct))
+ /* N.B. COMEDI32_CMDTEST and COMEDI_CMDTEST ought to use _IOWR, not _IOR.
+  * It's too late to change it now, but it only affects the command number. */
+-#define COMEDI32_CMDTEST _IOR(CIO, 10, comedi32_cmd)
+-#define COMEDI32_INSNLIST _IOR(CIO, 11, comedi32_insnlist)
+-#define COMEDI32_INSN _IOR(CIO, 12, comedi32_insn)
++#define COMEDI32_CMDTEST _IOR(CIO, 10, (struct comedi32_cmd_struct))
++#define COMEDI32_INSNLIST _IOR(CIO, 11, (struct comedi32_insnlist_struct))
++#define COMEDI32_INSN _IOR(CIO, 12, (struct comedi32_insn_struct))
+ 
+-typedef struct comedi32_chaninfo_struct {
++struct comedi32_chaninfo_struct {
+ 	unsigned int subdev;
+ 	compat_uptr_t maxdata_list;	/* 32-bit 'lsampl_t *' */
+ 	compat_uptr_t flaglist;		/* 32-bit 'unsigned int *' */
+ 	compat_uptr_t rangelist;	/* 32-bit 'unsigned int *' */
+ 	unsigned int unused[4];
+-} comedi32_chaninfo;
++};
+ 
+-typedef struct comedi32_rangeinfo_struct {
++struct comedi32_rangeinfo_struct {
+ 	unsigned int range_type;
+ 	compat_uptr_t range_ptr;	/* 32-bit 'void *' */
+-} comedi32_rangeinfo;
++};
+ 
+-typedef struct comedi32_cmd_struct {
++struct comedi32_cmd_struct {
+ 	unsigned int subdev;
+ 	unsigned int flags;
+ 	unsigned int start_src;
+@@ -78,21 +78,21 @@ typedef struct comedi32_cmd_struct {
+ 	unsigned int chanlist_len;
+ 	compat_uptr_t data;		/* 32-bit 'sampl_t *' */
+ 	unsigned int data_len;
+-} comedi32_cmd;
++};
+ 
+-typedef struct comedi32_insn_struct {
++struct comedi32_insn_struct {
+ 	unsigned int insn;
+ 	unsigned int n;
+ 	compat_uptr_t data;		/* 32-bit 'lsampl_t *' */
+ 	unsigned int subdev;
+ 	unsigned int chanspec;
+ 	unsigned int unused[3];
+-} comedi32_insn;
++};
+ 
+-typedef struct comedi32_insnlist_struct {
++struct comedi32_insnlist_struct {
+ 	unsigned int n_insns;
+ 	compat_uptr_t insns;		/* 32-bit 'comedi_insn *' */
+-} comedi32_insnlist;
++};
+ 
+ /* Handle translated ioctl. */
+ static int translated_ioctl(struct file *file, unsigned int cmd,
+@@ -123,8 +123,8 @@ static int translated_ioctl(struct file *file, unsigned int cmd,
+ /* Handle 32-bit COMEDI_CHANINFO ioctl. */
+ static int compat_chaninfo(struct file *file, unsigned long arg)
+ {
+-	comedi_chaninfo __user *chaninfo;
+-	comedi32_chaninfo __user *chaninfo32;
++	struct comedi_chaninfo_struct __user *chaninfo;
++	struct comedi32_chaninfo_struct __user *chaninfo32;
+ 	int err;
+ 	union {
+ 		unsigned int uint;
+@@ -159,7 +159,7 @@ static int compat_chaninfo(struct file *file, unsigned long arg)
+ static int compat_rangeinfo(struct file *file, unsigned long arg)
+ {
+ 	comedi_rangeinfo __user *rangeinfo;
+-	comedi32_rangeinfo __user *rangeinfo32;
++	struct comedi32_rangeinfo_struct __user *rangeinfo32;
+ 	int err;
+ 	union {
+ 		unsigned int uint;
+@@ -189,7 +189,7 @@ static int compat_rangeinfo(struct file *file, unsigned long arg)
+ 
+ /* Copy 32-bit cmd structure to native cmd structure. */
+ static int get_compat_cmd(comedi_cmd __user *cmd,
+-		comedi32_cmd __user *cmd32)
++		struct comedi32_cmd_struct __user *cmd32)
+ {
+ 	int err;
+ 	union {
+@@ -239,7 +239,7 @@ static int get_compat_cmd(comedi_cmd __user *cmd,
+ }
+ 
+ /* Copy native cmd structure to 32-bit cmd structure. */
+-static int put_compat_cmd(comedi32_cmd __user *cmd32, comedi_cmd __user *cmd)
++static int put_compat_cmd(struct comedi32_cmd_struct __user *cmd32, comedi_cmd __user *cmd)
+ {
+ 	int err;
+ 	unsigned int temp;
+@@ -290,7 +290,7 @@ static int put_compat_cmd(comedi32_cmd __user *cmd32, comedi_cmd __user *cmd)
+ static int compat_cmd(struct file *file, unsigned long arg)
+ {
+ 	comedi_cmd __user *cmd;
+-	comedi32_cmd __user *cmd32;
++	struct comedi32_cmd_struct __user *cmd32;
+ 	int rc;
+ 
+ 	cmd32 = compat_ptr(arg);
+@@ -307,7 +307,7 @@ static int compat_cmd(struct file *file, unsigned long arg)
+ static int compat_cmdtest(struct file *file, unsigned long arg)
+ {
+ 	comedi_cmd __user *cmd;
+-	comedi32_cmd __user *cmd32;
++	struct comedi32_cmd_struct __user *cmd32;
+ 	int rc, err;
+ 
+ 	cmd32 = compat_ptr(arg);
+@@ -330,7 +330,7 @@ static int compat_cmdtest(struct file *file, unsigned long arg)
+ 
+ /* Copy 32-bit insn structure to native insn structure. */
+ static int get_compat_insn(comedi_insn __user *insn,
+-		comedi32_insn __user *insn32)
++		struct comedi32_insn_struct __user *insn32)
+ {
+ 	int err;
+ 	union {
+@@ -364,8 +364,8 @@ static int compat_insnlist(struct file *file, unsigned long arg)
+ 		comedi_insnlist insnlist;
+ 		comedi_insn insn[1];
+ 	} __user *s;
+-	comedi32_insnlist __user *insnlist32;
+-	comedi32_insn __user *insn32;
++	struct comedi32_insnlist_struct __user *insnlist32;
++	struct comedi32_insn_struct __user *insn32;
+ 	compat_uptr_t uptr;
+ 	unsigned int n_insns, n;
+ 	int err, rc;
+@@ -411,7 +411,7 @@ static int compat_insnlist(struct file *file, unsigned long arg)
+ static int compat_insn(struct file *file, unsigned long arg)
+ {
+ 	comedi_insn __user *insn;
+-	comedi32_insn __user *insn32;
++	struct comedi32_insn_struct __user *insn32;
+ 	int rc;
+ 
+ 	insn32 = compat_ptr(arg);

commit 82675f3547ba2a0732beabd9bb4393535f74408c
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:04:23 2009 -0400
+
+    Staging: comedi: Remove curly braces where they are not needed
+    
+    Changes as suggested by checkpatch.pl.
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c
+index 98e570a2cb3e..7f5a86903c6f 100644
+--- a/drivers/staging/comedi/comedi_compat32.c
++++ b/drivers/staging/comedi/comedi_compat32.c
+@@ -98,15 +98,14 @@ typedef struct comedi32_insnlist_struct {
+ static int translated_ioctl(struct file *file, unsigned int cmd,
+ 		unsigned long arg)
+ {
+-	if (!file->f_op) {
++	if (!file->f_op)
+ 		return -ENOTTY;
+-	}
++
+ #ifdef HAVE_UNLOCKED_IOCTL
+ 	if (file->f_op->unlocked_ioctl) {
+ 		int rc = (int)(*file->f_op->unlocked_ioctl)(file, cmd, arg);
+-		if (rc == -ENOIOCTLCMD) {
++		if (rc == -ENOIOCTLCMD)
+ 			rc = -ENOTTY;
+-		}
+ 		return rc;
+ 	}
+ #endif
+@@ -150,9 +149,8 @@ static int compat_chaninfo(struct file *file, unsigned long arg)
+ 	err |= __put_user(compat_ptr(temp.uptr), &chaninfo->flaglist);
+ 	err |= __get_user(temp.uptr, &chaninfo32->rangelist);
+ 	err |= __put_user(compat_ptr(temp.uptr), &chaninfo->rangelist);
+-	if (err) {
++	if (err)
+ 		return -EFAULT;
+-	}
+ 
+ 	return translated_ioctl(file, COMEDI_CHANINFO, (unsigned long)chaninfo);
+ }
+@@ -182,9 +180,8 @@ static int compat_rangeinfo(struct file *file, unsigned long arg)
+ 	err |= __put_user(temp.uint, &rangeinfo->range_type);
+ 	err |= __get_user(temp.uptr, &rangeinfo32->range_ptr);
+ 	err |= __put_user(compat_ptr(temp.uptr), &rangeinfo->range_ptr);
+-	if (err) {
++	if (err)
+ 		return -EFAULT;
+-	}
+ 
+ 	return translated_ioctl(file, COMEDI_RANGEINFO,
+ 			(unsigned long)rangeinfo);
+@@ -300,9 +297,8 @@ static int compat_cmd(struct file *file, unsigned long arg)
+ 	cmd = compat_alloc_user_space(sizeof(*cmd));
+ 
+ 	rc = get_compat_cmd(cmd, cmd32);
+-	if (rc) {
++	if (rc)
+ 		return rc;
+-	}
+ 
+ 	return translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd);
+ }
+@@ -318,19 +314,17 @@ static int compat_cmdtest(struct file *file, unsigned long arg)
+ 	cmd = compat_alloc_user_space(sizeof(*cmd));
+ 
+ 	rc = get_compat_cmd(cmd, cmd32);
+-	if (rc) {
++	if (rc)
+ 		return rc;
+-	}
+ 
+ 	rc = translated_ioctl(file, COMEDI_CMDTEST, (unsigned long)cmd);
+-	if (rc < 0) {
++	if (rc < 0)
+ 		return rc;
+-	}
+ 
+ 	err = put_compat_cmd(cmd32, cmd);
+-	if (err) {
++	if (err)
+ 		rc = err;
+-	}
++
+ 	return rc;
+ }
+ 
+@@ -347,9 +341,9 @@ static int get_compat_insn(comedi_insn __user *insn,
+ 	/* Copy insn structure.  Ignore the unused members. */
+ 	err = 0;
+ 	if (!access_ok(VERIFY_READ, insn32, sizeof(*insn32))
+-			|| !access_ok(VERIFY_WRITE, insn, sizeof(*insn))) {
++			|| !access_ok(VERIFY_WRITE, insn, sizeof(*insn)))
+ 		return -EFAULT;
+-	}
++
+ 	err |= __get_user(temp.uint, &insn32->insn);
+ 	err |= __put_user(temp.uint, &insn->insn);
+ 	err |= __get_user(temp.uint, &insn32->n);
+@@ -386,9 +380,8 @@ static int compat_insnlist(struct file *file, unsigned long arg)
+ 	err |= __get_user(n_insns, &insnlist32->n_insns);
+ 	err |= __get_user(uptr, &insnlist32->insns);
+ 	insn32 = compat_ptr(uptr);
+-	if (err) {
++	if (err)
+ 		return -EFAULT;
+-	}
+ 
+ 	/* Allocate user memory to copy insnlist and insns into. */
+ 	s = compat_alloc_user_space(offsetof(struct combined_insnlist,
+@@ -400,16 +393,14 @@ static int compat_insnlist(struct file *file, unsigned long arg)
+ 	}
+ 	err |= __put_user(n_insns, &s->insnlist.n_insns);
+ 	err |= __put_user(&s->insn[0], &s->insnlist.insns);
+-	if (err) {
++	if (err)
+ 		return -EFAULT;
+-	}
+ 
+ 	/* Copy insn structures. */
+ 	for (n = 0; n < n_insns; n++) {
+ 		rc = get_compat_insn(&s->insn[n], &insn32[n]);
+-		if (rc) {
++		if (rc)
+ 			return rc;
+-		}
+ 	}
+ 
+ 	return translated_ioctl(file, COMEDI_INSNLIST,
+@@ -427,9 +418,8 @@ static int compat_insn(struct file *file, unsigned long arg)
+ 	insn = compat_alloc_user_space(sizeof(*insn));
+ 
+ 	rc = get_compat_insn(insn, insn32);
+-	if (rc) {
++	if (rc)
+ 		return rc;
+-	}
+ 
+ 	return translated_ioctl(file, COMEDI_INSN, (unsigned long)insn);
+ }
+@@ -512,14 +502,14 @@ static int mapped_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg,
+ 	int rc;
+ 
+ 	/* Make sure we are dealing with a Comedi device. */
+-	if (imajor(file->f_dentry->d_inode) != COMEDI_MAJOR) {
++	if (imajor(file->f_dentry->d_inode) != COMEDI_MAJOR)
+ 		return -ENOTTY;
+-	}
++
+ 	rc = raw_ioctl(file, cmd, arg);
+ 	/* Do not return -ENOIOCTLCMD. */
+-	if (rc == -ENOIOCTLCMD) {
++	if (rc == -ENOIOCTLCMD)
+ 		rc = -ENOTTY;
+-	}
++
+ 	return rc;
+ }
+ 
+diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
+index 9603d9e24d30..d9ff56874483 100644
+--- a/drivers/staging/comedi/drivers/icp_multi.c
++++ b/drivers/staging/comedi/drivers/icp_multi.c
+@@ -1080,9 +1080,8 @@ static int icp_multi_detach(comedi_device *dev)
+ 	if (dev->private && devpriv->card)
+ 		pci_card_free(devpriv->card);
+ 
+-	if (--pci_list_builded == 0) {
++	if (--pci_list_builded == 0)
+ 		pci_card_list_cleanup(PCI_VENDOR_ID_ICP);
+-	}
+ 
+ 	return 0;
+ }
+diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
+index c1f10b89a831..5f6e77cceb69 100644
+--- a/drivers/staging/comedi/drivers/me4000.c
++++ b/drivers/staging/comedi/drivers/me4000.c
+@@ -378,9 +378,9 @@ static int me4000_probe(comedi_device *dev, comedi_devconfig *it)
+ 	CALL_PDEBUG("In me4000_probe()\n");
+ 
+ 	/* Allocate private memory */
+-	if (alloc_private(dev, sizeof(me4000_info_t)) < 0) {
++	if (alloc_private(dev, sizeof(me4000_info_t)) < 0)
+ 		return -ENOMEM;
+-	}
++
+ 	/*
+ 	 * Probe the device to determine what device in the series it is.
+ 	 */
+@@ -576,15 +576,13 @@ static int init_board_info(comedi_device *dev, struct pci_dev *pci_dev_p)
+ 
+ 	/* Get the serial number */
+ 	result = pci_read_config_dword(pci_dev_p, 0x2C, &info->serial_no);
+-	if (result != PCIBIOS_SUCCESSFUL) {
++	if (result != PCIBIOS_SUCCESSFUL)
+ 		return result;
+-	}
+ 
+ 	/* Get the hardware revision */
+ 	result = pci_read_config_byte(pci_dev_p, 0x08, &info->hw_revision);
+-	if (result != PCIBIOS_SUCCESSFUL) {
++	if (result != PCIBIOS_SUCCESSFUL)
+ 		return result;
+-	}
+ 
+ 	/* Get the vendor id */
+ 	info->vendor_id = pci_dev_p->vendor;
+@@ -902,9 +900,8 @@ static int me4000_detach(comedi_device *dev)
+ 	if (info) {
+ 		if (info->pci_dev_p) {
+ 			reset_board(dev);
+-			if (info->plx_regbase) {
++			if (info->plx_regbase)
+ 				comedi_pci_disable(info->pci_dev_p);
+-			}
+ 			pci_dev_put(info->pci_dev_p);
+ 		}
+ 	}
+@@ -1163,9 +1160,8 @@ static int ai_round_cmd_args(comedi_device *dev,
+ 		rest = (cmd->start_arg * 33) % 1000;
+ 
+ 		if (cmd->flags & TRIG_ROUND_NEAREST) {
+-			if (rest > 33) {
++			if (rest > 33)
+ 				(*init_ticks)++;
+-			}
+ 		} else if (cmd->flags & TRIG_ROUND_UP) {
+ 			if (rest)
+ 				(*init_ticks)++;
+@@ -1177,9 +1173,8 @@ static int ai_round_cmd_args(comedi_device *dev,
+ 		rest = (cmd->scan_begin_arg * 33) % 1000;
+ 
+ 		if (cmd->flags & TRIG_ROUND_NEAREST) {
+-			if (rest > 33) {
++			if (rest > 33)
+ 				(*scan_ticks)++;
+-			}
+ 		} else if (cmd->flags & TRIG_ROUND_UP) {
+ 			if (rest)
+ 				(*scan_ticks)++;
+@@ -1191,9 +1186,8 @@ static int ai_round_cmd_args(comedi_device *dev,
+ 		rest = (cmd->convert_arg * 33) % 1000;
+ 
+ 		if (cmd->flags & TRIG_ROUND_NEAREST) {
+-			if (rest > 33) {
++			if (rest > 33)
+ 				(*chan_ticks)++;
+-			}
+ 		} else if (cmd->flags & TRIG_ROUND_UP) {
+ 			if (rest)
+ 				(*chan_ticks)++;
+@@ -1503,9 +1497,8 @@ static int me4000_ai_do_cmd_test(comedi_device *dev,
+ 		cmd->stop_src = TRIG_NONE;
+ 		err++;
+ 	}
+-	if (err) {
++	if (err)
+ 		return 1;
+-	}
+ 
+ 	/*
+ 	 * Stage 2. Check for trigger source conflicts.
+@@ -1553,9 +1546,8 @@ static int me4000_ai_do_cmd_test(comedi_device *dev,
+ 		cmd->scan_end_src = TRIG_NONE;
+ 		err++;
+ 	}
+-	if (err) {
++	if (err)
+ 		return 2;
+-	}
+ 
+ 	/*
+ 	 * Stage 3. Check if arguments are generally valid.
+@@ -1588,9 +1580,9 @@ static int me4000_ai_do_cmd_test(comedi_device *dev,
+ 		cmd->convert_arg = 2000;
+ 		err++;
+ 	}
+-	if (err) {
++
++	if (err)
+ 		return 3;
+-	}
+ 
+ 	/*
+ 	 * Stage 4. Check for argument conflicts.
+@@ -1735,9 +1727,9 @@ static int me4000_ai_do_cmd_test(comedi_device *dev,
+ 			err++;
+ 		}
+ 	}
+-	if (err) {
++
++	if (err)
+ 		return 4;
+-	}
+ 
+ 	/*
+ 	 * Stage 5. Check the channel list.
+@@ -1997,9 +1989,9 @@ static int me4000_dio_insn_bits(comedi_device *dev,
+ 	CALL_PDEBUG("In me4000_dio_insn_bits()\n");
+ 
+ 	/* Length of data must be 2 (mask and new data, see below) */
+-	if (insn->n == 0) {
++	if (insn->n == 0)
+ 		return 0;
+-	}
++
+ 	if (insn->n != 2) {
+ 		printk("comedi%d: me4000: me4000_dio_insn_bits(): Invalid instruction length\n", dev->minor);
+ 		return -EINVAL;
+@@ -2274,9 +2266,9 @@ static int me4000_cnt_insn_read(comedi_device *dev,
+ 
+ 	CALL_PDEBUG("In me4000_cnt_insn_read()\n");
+ 
+-	if (insn->n == 0) {
++	if (insn->n == 0)
+ 		return 0;
+-	}
++
+ 	if (insn->n > 1) {
+ 		printk(KERN_ERR
+ 			"comedi%d: me4000: me4000_cnt_insn_read(): Invalid instruction length %d\n",
+diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c
+index c7fe073f27b7..e0e2d6c90ac3 100644
+--- a/drivers/staging/comedi/drivers/mite.c
++++ b/drivers/staging/comedi/drivers/mite.c
+@@ -331,9 +331,9 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring, comedi_async * async)
+ 	ring->descriptors_dma_addr = 0;
+ 	ring->n_links = 0;
+ 
+-	if (async->prealloc_bufsz == 0) {
++	if (async->prealloc_bufsz == 0)
+ 		return 0;
+-	}
++
+ 	n_links = async->prealloc_bufsz >> PAGE_SHIFT;
+ 
+ 	MDPRINTK("ring->hw_dev=%p, n_links=0x%04x\n", ring->hw_dev, n_links);
+@@ -395,9 +395,9 @@ void mite_prep_dma(struct mite_channel *mite_chan,
+ 		   on e-series boards.  */
+ 		chcr |= CHCR_BYTE_SWAP_DEVICE | CHCR_BYTE_SWAP_MEMORY;
+ 	}
+-	if (mite_chan->dir == COMEDI_INPUT) {
++	if (mite_chan->dir == COMEDI_INPUT)
+ 		chcr |= CHCR_DEV_TO_MEM;
+-	}
++
+ 	writel(chcr, mite->mite_io_addr + MITE_CHCR(mite_chan->channel));
+ 
+ 	/* to/from memory */
+@@ -547,9 +547,9 @@ int mite_sync_input_dma(struct mite_channel *mite_chan, comedi_async * async)
+ 	count = nbytes - async->buf_write_count;
+ 	/* it's possible count will be negative due to
+ 	 * conservative value returned by mite_bytes_written_to_memory_lb */
+-	if (count <= 0) {
++	if (count <= 0)
+ 		return 0;
+-	}
++
+ 	comedi_buf_write_free(async, count);
+ 
+ 	async->scan_progress += count;
+@@ -586,9 +586,9 @@ int mite_sync_output_dma(struct mite_channel *mite_chan, comedi_async * async)
+ 		return -1;
+ 	}
+ 	count = nbytes_lb - async->buf_read_count;
+-	if (count <= 0) {
++	if (count <= 0)
+ 		return 0;
+-	}
++
+ 	if (count) {
+ 		comedi_buf_read_free(async, count);
+ 		async->events |= COMEDI_CB_BLOCK;
+@@ -753,9 +753,8 @@ static void mite_decode(char **bit_str, unsigned int bits)
+ 	int i;
+ 
+ 	for (i = 31; i >= 0; i--) {
+-		if (bits & (1 << i)) {
++		if (bits & (1 << i))
+ 			printk(" %s", bit_str[i]);
+-		}
+ 	}
+ 	printk("\n");
+ }
+diff --git a/drivers/staging/comedi/drivers/plx9080.h b/drivers/staging/comedi/drivers/plx9080.h
+index e53d3d429d7f..9231ba802030 100644
+--- a/drivers/staging/comedi/drivers/plx9080.h
++++ b/drivers/staging/comedi/drivers/plx9080.h
+@@ -394,9 +394,9 @@ static inline int plx9080_abort_dma(void *iobase, unsigned int channel)
+ 
+ 	/*  abort dma transfer if necessary */
+ 	dma_status = readb(dma_cs_addr);
+-	if ((dma_status & PLX_DMA_EN_BIT) == 0) {
++	if ((dma_status & PLX_DMA_EN_BIT) == 0)
+ 		return 0;
+-	}
++
+ 	/*  wait to make sure done bit is zero */
+ 	for (i = 0; (dma_status & PLX_DMA_DONE_BIT) && i < timeout; i++) {
+ 		comedi_udelay(1);
+diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
+index 22b1e72a9f71..d447f466d333 100644
+--- a/drivers/staging/comedi/drivers/s626.c
++++ b/drivers/staging/comedi/drivers/s626.c
+@@ -1290,18 +1290,15 @@ static int s626_detach(comedi_device *dev)
+ 			CloseDMAB(dev, &devpriv->ANABuf, DMABUF_SIZE);
+ 		}
+ 
+-		if (dev->irq) {
++		if (dev->irq)
+ 			comedi_free_irq(dev->irq, dev);
+-		}
+ 
+-		if (devpriv->base_addr) {
++		if (devpriv->base_addr)
+ 			iounmap(devpriv->base_addr);
+-		}
+ 
+ 		if (devpriv->pdev) {
+-			if (devpriv->got_regions) {
++			if (devpriv->got_regions)
+ 				comedi_pci_disable(devpriv->pdev);
+-			}
+ 			pci_dev_put(devpriv->pdev);
+ 		}
+ 	}
+@@ -2072,9 +2069,8 @@ static int s626_ao_rinsn(comedi_device *dev, comedi_subdevice *s,
+ {
+ 	int i;
+ 
+-	for (i = 0; i < insn->n; i++) {
++	for (i = 0; i < insn->n; i++)
+ 		data[i] = devpriv->ao_readback[CR_CHAN(insn->chanspec)];
+-	}
+ 
+ 	return i;
+ }
+@@ -2119,9 +2115,9 @@ static int s626_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
+ {
+ 
+ 	/* Length of data must be 2 (mask and new data, see below) */
+-	if (insn->n == 0) {
++	if (insn->n == 0)
+ 		return 0;
+-	}
++
+ 	if (insn->n != 2) {
+ 		printk("comedi%d: s626: s626_dio_insn_bits(): Invalid instruction length\n", dev->minor);
+ 		return -EINVAL;
+diff --git a/drivers/staging/comedi/kcomedilib/get.c b/drivers/staging/comedi/kcomedilib/get.c
+index 781733787e96..36778b30f396 100644
+--- a/drivers/staging/comedi/kcomedilib/get.c
++++ b/drivers/staging/comedi/kcomedilib/get.c
+@@ -160,9 +160,9 @@ int comedi_get_krange(comedi_t *d, unsigned int subdevice, unsigned int chan,
+ 	} else {
+ 		lr = s->range_table;
+ 	}
+-	if (range >= lr->length) {
++	if (range >= lr->length)
+ 		return -EINVAL;
+-	}
++
+ 	memcpy(krange, lr->range + range, sizeof(comedi_krange));
+ 
+ 	return 0;
+diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+index 94a5067f6bd5..7818e391dcab 100644
+--- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
++++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+@@ -331,9 +331,9 @@ int comedi_lock(comedi_t *d, unsigned int subdevice)
+ 	unsigned long flags;
+ 	int ret = 0;
+ 
+-	if (subdevice >= dev->n_subdevices) {
++	if (subdevice >= dev->n_subdevices)
+ 		return -EINVAL;
+-	}
++
+ 	s = dev->subdevices + subdevice;
+ 
+ 	comedi_spin_lock_irqsave(&s->spin_lock, flags);
+@@ -375,9 +375,9 @@ int comedi_unlock(comedi_t *d, unsigned int subdevice)
+ 	comedi_async *async;
+ 	int ret;
+ 
+-	if (subdevice >= dev->n_subdevices) {
++	if (subdevice >= dev->n_subdevices)
+ 		return -EINVAL;
+-	}
++
+ 	s = dev->subdevices + subdevice;
+ 
+ 	async = s->async;
+@@ -425,9 +425,9 @@ int comedi_cancel(comedi_t *d, unsigned int subdevice)
+ 	comedi_subdevice *s;
+ 	int ret = 0;
+ 
+-	if (subdevice >= dev->n_subdevices) {
++	if (subdevice >= dev->n_subdevices)
+ 		return -EINVAL;
+-	}
++
+ 	s = dev->subdevices + subdevice;
+ 
+ 	if (s->lock && s->lock != d)
+@@ -450,9 +450,9 @@ int comedi_cancel(comedi_t *d, unsigned int subdevice)
+ 		return ret;
+ 
+ #ifdef CONFIG_COMEDI_RT
+-	if (comedi_get_subdevice_runflags(s) & SRF_RT) {
++	if (comedi_get_subdevice_runflags(s) & SRF_RT)
+ 		comedi_switch_to_non_rt(dev);
+-	}
++
+ #endif
+ 	comedi_set_subdevice_runflags(s, SRF_RUNNING | SRF_RT, 0);
+ 	s->async->inttrig = NULL;
+@@ -471,9 +471,9 @@ int comedi_register_callback(comedi_t *d, unsigned int subdevice,
+ 	comedi_subdevice *s;
+ 	comedi_async *async;
+ 
+-	if (subdevice >= dev->n_subdevices) {
++	if (subdevice >= dev->n_subdevices)
+ 		return -EINVAL;
+-	}
++
+ 	s = dev->subdevices + subdevice;
+ 
+ 	async = s->async;
+@@ -507,9 +507,9 @@ int comedi_poll(comedi_t *d, unsigned int subdevice)
+ 	comedi_subdevice *s = dev->subdevices;
+ 	comedi_async *async;
+ 
+-	if (subdevice >= dev->n_subdevices) {
++	if (subdevice >= dev->n_subdevices)
+ 		return -EINVAL;
+-	}
++
+ 	s = dev->subdevices + subdevice;
+ 
+ 	async = s->async;
+@@ -533,17 +533,16 @@ int comedi_map(comedi_t *d, unsigned int subdevice, void *ptr)
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s;
+ 
+-	if (subdevice >= dev->n_subdevices) {
++	if (subdevice >= dev->n_subdevices)
+ 		return -EINVAL;
+-	}
++
+ 	s = dev->subdevices + subdevice;
+ 
+ 	if (!s->async)
+ 		return -EINVAL;
+ 
+-	if (ptr) {
++	if (ptr)
+ 		*((void **)ptr) = s->async->prealloc_buf;
+-	}
+ 
+ 	/* XXX no reference counting */
+ 
+@@ -556,9 +555,9 @@ int comedi_unmap(comedi_t *d, unsigned int subdevice)
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s;
+ 
+-	if (subdevice >= dev->n_subdevices) {
++	if (subdevice >= dev->n_subdevices)
+ 		return -EINVAL;
+-	}
++
+ 	s = dev->subdevices + subdevice;
+ 
+ 	if (!s->async)
+diff --git a/drivers/staging/comedi/proc.c b/drivers/staging/comedi/proc.c
+index 3f61828294fd..6a1efa86ae97 100644
+--- a/drivers/staging/comedi/proc.c
++++ b/drivers/staging/comedi/proc.c
+@@ -67,9 +67,8 @@ int comedi_read_procmem(char *buf, char **start, off_t offset, int len,
+ 				dev->board_name, dev->n_subdevices);
+ 		}
+ 	}
+-	if (!devices_q) {
++	if (!devices_q)
+ 		l += sprintf(buf + l, "no devices\n");
+-	}
+ 
+ 	for (driv = comedi_drivers; driv; driv = driv->next) {
+ 		l += sprintf(buf + l, "%s:\n", driv->driver_name);
+@@ -78,9 +77,8 @@ int comedi_read_procmem(char *buf, char **start, off_t offset, int len,
+ 				*(char **)((char *)driv->board_name +
+ 					i * driv->offset));
+ 		}
+-		if (!driv->num_names) {
++		if (!driv->num_names)
+ 			l += sprintf(buf + l, " %s\n", driv->driver_name);
+-		}
+ 	}
+ 
+ 	return l;
+diff --git a/drivers/staging/comedi/range.c b/drivers/staging/comedi/range.c
+index b8eb4ec41854..e54be6182eea 100644
+--- a/drivers/staging/comedi/range.c
++++ b/drivers/staging/comedi/range.c
+@@ -135,9 +135,8 @@ int check_chanlist(comedi_subdevice *s, int n, unsigned int *chanlist)
+ 					i, chanlist[i], s->n_chan,
+ 					s->range_table->length);
+ #if 0
+-				for (i = 0; i < n; i++) {
++				for (i = 0; i < n; i++)
+ 					printk("[%d]=0x%08x\n", i, chanlist[i]);
+-				}
+ #endif
+ 				return -EINVAL;
+ 			}
+diff --git a/drivers/staging/comedi/rt.c b/drivers/staging/comedi/rt.c
+index f4b851252541..e6ec8b98a15d 100644
+--- a/drivers/staging/comedi/rt.c
++++ b/drivers/staging/comedi/rt.c
+@@ -84,9 +84,9 @@ int comedi_request_irq(unsigned irq, irqreturn_t(*handler) (int,
+ 				("comedi: cannot get unshared interrupt, will not use RT interrupts.\n");
+ 			ret = request_irq(irq, handler, flags, device, dev_id);
+ 		}
+-		if (ret < 0) {
++		if (ret < 0)
+ 			return ret;
+-		}
++
+ 	} else {
+ 		it = kzalloc(sizeof(struct comedi_irq_struct), GFP_KERNEL);
+ 		if (!it)

commit dedd1325f1d53e2a2604457c4b3af9e62dde5001
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:04:18 2009 -0400
+
+    Staging: comedi: Remove checks for NULL before calling kfree()
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
+index a252081b6a08..07456c0709dc 100644
+--- a/drivers/staging/comedi/drivers.c
++++ b/drivers/staging/comedi/drivers.c
+@@ -81,10 +81,8 @@ static void cleanup_device(comedi_device *dev)
+ 		dev->subdevices = NULL;
+ 		dev->n_subdevices = 0;
+ 	}
+-	if (dev->private) {
+-		kfree(dev->private);
+-		dev->private = NULL;
+-	}
++	kfree(dev->private);
++	dev->private = NULL;
+ 	dev->driver = 0;
+ 	dev->board_name = NULL;
+ 	dev->board_ptr = NULL;

commit 51b713a684d403bd672b3e4cac55db43dc5cca2d
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:04:12 2009 -0400
+
+    Staging: comedi: Misc code cleanups for checkpatch
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
+index 8a3a1786c152..d4750e503aad 100644
+--- a/drivers/staging/comedi/comedidev.h
++++ b/drivers/staging/comedi/comedidev.h
+@@ -53,9 +53,9 @@
+ 
+ #define COMEDI_INITCLEANUP_NOMODULE(x)					\
+ 	static int __init x ## _init_module(void)			\
+-		{return comedi_driver_register(&(x));}			\
++		{return comedi_driver_register(&(x)); }			\
+ 	static void __exit x ## _cleanup_module(void)			\
+-		{comedi_driver_unregister(&(x));} 			\
++		{comedi_driver_unregister(&(x)); } 			\
+ 	module_init(x ## _init_module);					\
+ 	module_exit(x ## _cleanup_module);					\
+ 
+diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
+index d474cb2cb7e5..9603d9e24d30 100644
+--- a/drivers/staging/comedi/drivers/icp_multi.c
++++ b/drivers/staging/comedi/drivers/icp_multi.c
+@@ -179,7 +179,7 @@ static comedi_driver driver_icp_multi = {
+       attach : icp_multi_attach,
+       detach : icp_multi_detach,
+       num_names : n_boardtypes,
+-      board_name:&boardtypes[0].name,
++      board_name : &boardtypes[0].name,
+       offset : sizeof(boardtype),
+ };
+ 
+@@ -947,7 +947,7 @@ static int icp_multi_attach(comedi_device *dev, comedi_devconfig *it)
+ 		n_subdevices++;
+ 
+ 	ret = alloc_subdevices(dev, n_subdevices);
+-	if ( ret < 0 )
++	if (ret < 0)
+ 		return ret;
+ 
+ 	icp_multi_reset(dev);
+diff --git a/drivers/staging/comedi/drivers/icp_multi.h b/drivers/staging/comedi/drivers/icp_multi.h
+index 0796056a07a4..21d84766fea8 100644
+--- a/drivers/staging/comedi/drivers/icp_multi.h
++++ b/drivers/staging/comedi/drivers/icp_multi.h
+@@ -246,7 +246,7 @@ static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id,
+ 
+ 	if ((pci_bus < 1) & (pci_slot < 1)) {	/* use autodetection */
+ 
+-		card = find_free_pci_card_by_device(vendor_id,device_id);
++		card = find_free_pci_card_by_device(vendor_id, device_id);
+ 		if (card == NULL) {
+ 			rt_printk(" - Unused card not found in system!\n");
+ 			return NULL;
+@@ -268,7 +268,7 @@ static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id,
+ 	}
+ 
+ 	err = pci_card_alloc(card);
+-	if ( err != 0) {
++	if (err != 0) {
+ 		if (err > 0)
+ 			rt_printk(" - Can't allocate card!\n");
+ 		/* else: error already printed. */
+diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c
+index c82aeff8ff58..c7fe073f27b7 100644
+--- a/drivers/staging/comedi/drivers/mite.c
++++ b/drivers/staging/comedi/drivers/mite.c
+@@ -63,7 +63,7 @@
+ 
+ MODULE_LICENSE("GPL");
+ 
+-struct mite_struct *mite_devices = NULL;
++struct mite_struct *mite_devices;
+ 
+ #define TOP_OF_PAGE(x) ((x)|(~(PAGE_MASK)))
+ 
+diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
+index 578b731ae500..95e4af27bd8d 100644
+--- a/drivers/staging/comedi/drivers/rtd520.c
++++ b/drivers/staging/comedi/drivers/rtd520.c
+@@ -2155,7 +2155,7 @@ static int rtd_ao_winsn(comedi_device *dev,
+ 		/* VERIFY: comedi range and offset conversions */
+ 
+ 		if ((range > 1)	/* bipolar */
+-			&&(data[i] < 2048)) {
++			&& (data[i] < 2048)) {
+ 			/* offset and sign extend */
+ 			val = (((int)data[i]) - 2048) << 3;
+ 		} else {	/* unipolor */
+diff --git a/drivers/staging/comedi/rt.c b/drivers/staging/comedi/rt.c
+index ba9c70ecd044..f4b851252541 100644
+--- a/drivers/staging/comedi/rt.c
++++ b/drivers/staging/comedi/rt.c
+@@ -180,7 +180,7 @@ void comedi_rt_pend_wakeup(wait_queue_head_t *q)
+ 
+ #ifndef HAVE_RT_REQUEST_IRQ_WITH_ARG
+ #define DECLARE_VOID_IRQ(irq) \
+-static void handle_void_irq_ ## irq (void){ handle_void_irq(irq);}
++static void handle_void_irq_ ## irq (void){ handle_void_irq(irq); }
+ 
+ static void handle_void_irq(int irq)
+ {

commit a87e4f5a4a7be43e610399ebcbb09ba3da021094
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:04:07 2009 -0400
+
+    Staging: comedi: Add spaces around colons as requested by checkpatch
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
+index ff6118e8ad4a..22b1e72a9f71 100644
+--- a/drivers/staging/comedi/drivers/s626.c
++++ b/drivers/staging/comedi/drivers/s626.c
+@@ -358,15 +358,15 @@ static enc_private enc_private_data[] = {
+ 	      GetEnable:GetEnable_A,
+ 	      GetIntSrc : GetIntSrc_A,
+ 	      GetLoadTrig : GetLoadTrig_A,
+-	      GetMode:	GetMode_A,
++	      GetMode :	GetMode_A,
+ 	      PulseIndex : PulseIndex_A,
+ 	      SetEnable : SetEnable_A,
+ 	      SetIntSrc : SetIntSrc_A,
+ 	      SetLoadTrig : SetLoadTrig_A,
+-	      SetMode:	SetMode_A,
++	      SetMode :	SetMode_A,
+ 	      ResetCapFlags : ResetCapFlags_A,
+-	      MyCRA:	LP_CR0A,
+-	      MyCRB:	LP_CR0B,
++	      MyCRA :	LP_CR0A,
++	      MyCRB :	LP_CR0B,
+ 	      MyLatchLsw : LP_CNTR0ALSW,
+ 	      MyEventBits : EVBITS(0),
+ 		},
+@@ -374,15 +374,15 @@ static enc_private enc_private_data[] = {
+ 	      GetEnable:GetEnable_A,
+ 	      GetIntSrc : GetIntSrc_A,
+ 	      GetLoadTrig : GetLoadTrig_A,
+-	      GetMode:	GetMode_A,
++	      GetMode :	GetMode_A,
+ 	      PulseIndex : PulseIndex_A,
+ 	      SetEnable : SetEnable_A,
+ 	      SetIntSrc : SetIntSrc_A,
+ 	      SetLoadTrig : SetLoadTrig_A,
+-	      SetMode:	SetMode_A,
++	      SetMode :	SetMode_A,
+ 	      ResetCapFlags : ResetCapFlags_A,
+-	      MyCRA:	LP_CR1A,
+-	      MyCRB:	LP_CR1B,
++	      MyCRA :	LP_CR1A,
++	      MyCRB :	LP_CR1B,
+ 	      MyLatchLsw : LP_CNTR1ALSW,
+ 	      MyEventBits : EVBITS(1),
+ 		},
+@@ -390,15 +390,15 @@ static enc_private enc_private_data[] = {
+ 	      GetEnable:GetEnable_A,
+ 	      GetIntSrc : GetIntSrc_A,
+ 	      GetLoadTrig : GetLoadTrig_A,
+-	      GetMode:	GetMode_A,
++	      GetMode :	GetMode_A,
+ 	      PulseIndex : PulseIndex_A,
+ 	      SetEnable : SetEnable_A,
+ 	      SetIntSrc : SetIntSrc_A,
+ 	      SetLoadTrig : SetLoadTrig_A,
+-	      SetMode:	SetMode_A,
++	      SetMode :	SetMode_A,
+ 	      ResetCapFlags : ResetCapFlags_A,
+-	      MyCRA:	LP_CR2A,
+-	      MyCRB:	LP_CR2B,
++	      MyCRA :	LP_CR2A,
++	      MyCRB :	LP_CR2B,
+ 	      MyLatchLsw : LP_CNTR2ALSW,
+ 	      MyEventBits : EVBITS(2),
+ 		},
+@@ -406,15 +406,15 @@ static enc_private enc_private_data[] = {
+ 	      GetEnable:GetEnable_B,
+ 	      GetIntSrc : GetIntSrc_B,
+ 	      GetLoadTrig : GetLoadTrig_B,
+-	      GetMode:	GetMode_B,
++	      GetMode :	GetMode_B,
+ 	      PulseIndex : PulseIndex_B,
+ 	      SetEnable : SetEnable_B,
+ 	      SetIntSrc : SetIntSrc_B,
+ 	      SetLoadTrig : SetLoadTrig_B,
+-	      SetMode:	SetMode_B,
++	      SetMode :	SetMode_B,
+ 	      ResetCapFlags : ResetCapFlags_B,
+-	      MyCRA:	LP_CR0A,
+-	      MyCRB:	LP_CR0B,
++	      MyCRA :	LP_CR0A,
++	      MyCRB :	LP_CR0B,
+ 	      MyLatchLsw : LP_CNTR0BLSW,
+ 	      MyEventBits : EVBITS(3),
+ 		},
+@@ -422,15 +422,15 @@ static enc_private enc_private_data[] = {
+ 	      GetEnable:GetEnable_B,
+ 	      GetIntSrc : GetIntSrc_B,
+ 	      GetLoadTrig : GetLoadTrig_B,
+-	      GetMode:	GetMode_B,
++	      GetMode :	GetMode_B,
+ 	      PulseIndex : PulseIndex_B,
+ 	      SetEnable : SetEnable_B,
+ 	      SetIntSrc : SetIntSrc_B,
+ 	      SetLoadTrig : SetLoadTrig_B,
+-	      SetMode:	SetMode_B,
++	      SetMode :	SetMode_B,
+ 	      ResetCapFlags : ResetCapFlags_B,
+-	      MyCRA:	LP_CR1A,
+-	      MyCRB:	LP_CR1B,
++	      MyCRA :	LP_CR1A,
++	      MyCRB :	LP_CR1B,
+ 	      MyLatchLsw : LP_CNTR1BLSW,
+ 	      MyEventBits : EVBITS(4),
+ 		},
+@@ -438,15 +438,15 @@ static enc_private enc_private_data[] = {
+ 	      GetEnable:GetEnable_B,
+ 	      GetIntSrc : GetIntSrc_B,
+ 	      GetLoadTrig : GetLoadTrig_B,
+-	      GetMode:	GetMode_B,
++	      GetMode :	GetMode_B,
+ 	      PulseIndex : PulseIndex_B,
+ 	      SetEnable : SetEnable_B,
+ 	      SetIntSrc : SetIntSrc_B,
+ 	      SetLoadTrig : SetLoadTrig_B,
+-	      SetMode:	SetMode_B,
++	      SetMode :	SetMode_B,
+ 	      ResetCapFlags : ResetCapFlags_B,
+-	      MyCRA:	LP_CR2A,
+-	      MyCRB:	LP_CR2B,
++	      MyCRA :	LP_CR2A,
++	      MyCRB :	LP_CR2B,
+ 	      MyLatchLsw : LP_CNTR2BLSW,
+ 	      MyEventBits : EVBITS(5),
+ 		},

commit f10fe5742ba6ad6a2219cbe774e1b9d3db0ef23d
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:04:02 2009 -0400
+
+    Staging: comedi: Fix cases of open curly on wrong line
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
+index 26cc41073b0b..ff6118e8ad4a 100644
+--- a/drivers/staging/comedi/drivers/s626.c
++++ b/drivers/staging/comedi/drivers/s626.c
+@@ -2431,8 +2431,7 @@ static uint8_t I2Cread(comedi_device *dev, uint8_t addr)
+ 			 /* Byte2 = I2C command: write to I2C EEPROM  device. */
+ 			| I2C_B1(I2C_ATTRSTOP, addr)
+ 			 /* Byte1 = EEPROM internal target address. */
+-			| I2C_B0(I2C_ATTRNOP, 0)))	/*  Byte0 = Not sent. */
+-	{
++			| I2C_B0(I2C_ATTRNOP, 0))) {	/*  Byte0 = Not sent. */
+ 		/*  Abort function and declare error if handshake failed. */
+ 		DEBUG("I2Cread: error handshake I2Cread  a\n");
+ 		return 0;
+@@ -2445,9 +2444,8 @@ static uint8_t I2Cread(comedi_device *dev, uint8_t addr)
+ 			| I2C_B1(I2C_ATTRSTOP, 0)	/*  Byte1 receives */
+ 			/*  uint8_t from */
+ 			/*  EEPROM. */
+-			| I2C_B0(I2C_ATTRNOP, 0)))	/*  Byte0 = Not */
+-		/*  sent. */
+-	{
++			| I2C_B0(I2C_ATTRNOP, 0))) {	/*  Byte0 = Not  sent. */
++
+ 		/*  Abort function and declare error if handshake failed. */
+ 		DEBUG("I2Cread: error handshake I2Cread b\n");
+ 		return 0;

commit c7427409cd071a34c4a13c5c24531b7a10334e31
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:03:56 2009 -0400
+
+    Staging: comedi: Move trailing statements to next line as requested by checkpatch
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
+index 9110ae3c7fec..26cc41073b0b 100644
+--- a/drivers/staging/comedi/drivers/s626.c
++++ b/drivers/staging/comedi/drivers/s626.c
+@@ -749,7 +749,8 @@ static int s626_attach(comedi_device *dev, comedi_devconfig *it)
+ 		/*  Write I2C control: abort any I2C activity. */
+ 		MC_ENABLE(P_MC2, MC2_UPLD_IIC);
+ 		/*  Invoke command  upload */
+-		while ((RR7146(P_MC2) & MC2_UPLD_IIC) == 0);
++		while ((RR7146(P_MC2) & MC2_UPLD_IIC) == 0)
++			;
+ 		/*  and wait for upload to complete. */
+ 
+ 		/* Per SAA7146 data sheet, write to STATUS reg twice to
+@@ -758,7 +759,8 @@ static int s626_attach(comedi_device *dev, comedi_devconfig *it)
+ 			WR7146(P_I2CSTAT, I2C_CLKSEL);
+ 			/*  Write I2C control: reset  error flags. */
+ 			MC_ENABLE(P_MC2, MC2_UPLD_IIC);	/*  Invoke command upload */
+-			while (!MC_TEST(P_MC2, MC2_UPLD_IIC));
++			while (!MC_TEST(P_MC2, MC2_UPLD_IIC))
++				;
+ 			/* and wait for upload to complete. */
+ 		}
+ 
+@@ -1592,7 +1594,8 @@ static int s626_ai_insn_read(comedi_device *dev, comedi_subdevice *s,
+ 		/*  shift into FB BUFFER 1 register. */
+ 
+ 		/*  Wait for ADC done. */
+-		while (!(RR7146(P_PSR) & PSR_GPIO2)) ;
++		while (!(RR7146(P_PSR) & PSR_GPIO2))
++			;
+ 
+ 		/*  Fetch ADC data. */
+ 		if (n != 0)
+@@ -1624,7 +1627,8 @@ static int s626_ai_insn_read(comedi_device *dev, comedi_subdevice *s,
+ 	/*  Wait for the data to arrive in FB BUFFER 1 register. */
+ 
+ 	/*  Wait for ADC done. */
+-	while (!(RR7146(P_PSR) & PSR_GPIO2)) ;
++	while (!(RR7146(P_PSR) & PSR_GPIO2))
++		;
+ 
+ 	/*  Fetch ADC data from audio interface's input shift register. */
+ 
+@@ -2462,10 +2466,12 @@ static uint32_t I2Chandshake(comedi_device *dev, uint32_t val)
+ 	/*  upload confirmation. */
+ 
+ 	MC_ENABLE(P_MC2, MC2_UPLD_IIC);
+-	while (!MC_TEST(P_MC2, MC2_UPLD_IIC)) ;
++	while (!MC_TEST(P_MC2, MC2_UPLD_IIC))
++		;
+ 
+ 	/*  Wait until I2C bus transfer is finished or an error occurs. */
+-	while ((RR7146(P_I2CCTRL) & (I2C_BUSY | I2C_ERR)) == I2C_BUSY) ;
++	while ((RR7146(P_I2CCTRL) & (I2C_BUSY | I2C_ERR)) == I2C_BUSY)
++		;
+ 
+ 	/*  Return non-zero if I2C error occured. */
+ 	return RR7146(P_I2CCTRL) & I2C_ERR;
+@@ -2579,7 +2585,8 @@ static void SendDAC(comedi_device *dev, uint32_t val)
+ 	 * Done by polling the DMAC enable flag; this flag is automatically
+ 	 * cleared when the transfer has finished.
+ 	 */
+-	while ((RR7146(P_MC1) & MC1_A2OUT) != 0) ;
++	while ((RR7146(P_MC1) & MC1_A2OUT) != 0)
++		;
+ 
+ 	/* START THE OUTPUT STREAM TO THE TARGET DAC -------------------- */
+ 
+@@ -2596,7 +2603,8 @@ static void SendDAC(comedi_device *dev, uint32_t val)
+ 	 * finished transferring the DAC's data DWORD from the output FIFO
+ 	 * to the output buffer register.
+ 	 */
+-	while ((RR7146(P_SSR) & SSR_AF2_OUT) == 0) ;
++	while ((RR7146(P_SSR) & SSR_AF2_OUT) == 0)
++		;
+ 
+ 	/* Set up to trap execution at slot 0 when the TSL sequencer cycles
+ 	 * back to slot 0 after executing the EOS in slot 5.  Also,
+@@ -2632,7 +2640,8 @@ static void SendDAC(comedi_device *dev, uint32_t val)
+ 		 * from 0xFF to 0x00, which slot 0 causes to happen by shifting
+ 		 * out/in on SD2 the 0x00 that is always referenced by slot 5.
+ 		 */
+-		 while ((RR7146(P_FB_BUFFER2) & 0xFF000000) != 0) ;
++		 while ((RR7146(P_FB_BUFFER2) & 0xFF000000) != 0)
++			;
+ 	}
+ 	/* Either (1) we were too late setting the slot 0 trap; the TSL
+ 	 * sequencer restarted slot 0 before we could set the EOS trap flag,
+@@ -2648,7 +2657,8 @@ static void SendDAC(comedi_device *dev, uint32_t val)
+ 	 * the next DAC write.  This is detected when FB_BUFFER2 MSB changes
+ 	 * from 0x00 to 0xFF.
+ 	 */
+-	while ((RR7146(P_FB_BUFFER2) & 0xFF000000) == 0) ;
++	while ((RR7146(P_FB_BUFFER2) & 0xFF000000) == 0)
++		;
+ }
+ 
+ static void WriteMISC2(comedi_device *dev, uint16_t NewImage)
+@@ -2687,10 +2697,12 @@ static void DEBItransfer(comedi_device *dev)
+ 
+ 	/*  Wait for completion of upload from shadow RAM to DEBI control */
+ 	/*  register. */
+-	while (!MC_TEST(P_MC2, MC2_UPLD_DEBI)) ;
++	while (!MC_TEST(P_MC2, MC2_UPLD_DEBI))
++		;
+ 
+ 	/*  Wait until DEBI transfer is done. */
+-	while (RR7146(P_PSR) & PSR_DEBI_S) ;
++	while (RR7146(P_PSR) & PSR_DEBI_S)
++		;
+ }
+ 
+ /*  Write a value to a gate array register. */
+diff --git a/drivers/staging/comedi/proc.c b/drivers/staging/comedi/proc.c
+index 100877362577..3f61828294fd 100644
+--- a/drivers/staging/comedi/proc.c
++++ b/drivers/staging/comedi/proc.c
+@@ -55,7 +55,8 @@ int comedi_read_procmem(char *buf, char **start, off_t offset, int len,
+ 		struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(i);
+ 		comedi_device *dev;
+ 
+-		if (dev_file_info == NULL) continue;
++		if (dev_file_info == NULL)
++			continue;
+ 		dev = dev_file_info->device;
+ 
+ 		if (dev->attached) {

commit 197c82bf25b9e379cb5646561be1a727ab9e84a7
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:03:51 2009 -0400
+
+    Staging: comedi: Remove instances of assignments in conditionals
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
+index aefd1c16ab2b..d474cb2cb7e5 100644
+--- a/drivers/staging/comedi/drivers/icp_multi.c
++++ b/drivers/staging/comedi/drivers/icp_multi.c
+@@ -882,7 +882,8 @@ static int icp_multi_attach(comedi_device *dev, comedi_devconfig *it)
+ 	printk("icp_multi EDBG: BGN: icp_multi_attach(...)\n");
+ 
+ 	/*  Alocate private data storage space */
+-	if ((ret = alloc_private(dev, sizeof(icp_multi_private))) < 0)
++	ret = alloc_private(dev, sizeof(icp_multi_private));
++	if (ret < 0)
+ 		return ret;
+ 
+ 	/*  Initialise list of PCI cards in system, if not already done so */
+@@ -899,9 +900,11 @@ static int icp_multi_attach(comedi_device *dev, comedi_devconfig *it)
+ 	printk("Anne's comedi%d: icp_multi: board=%s", dev->minor,
+ 		this_board->name);
+ 
+-	if ((card = select_and_alloc_pci_card(PCI_VENDOR_ID_ICP,
+-				this_board->device_id, it->options[0],
+-				it->options[1])) == NULL)
++	card = select_and_alloc_pci_card(PCI_VENDOR_ID_ICP,
++					 this_board->device_id, it->options[0],
++					 it->options[1]);
++
++	if (card == NULL)
+ 		return -EIO;
+ 
+ 	devpriv->card = card;
+@@ -943,9 +946,9 @@ static int icp_multi_attach(comedi_device *dev, comedi_devconfig *it)
+ 	if (this_board->n_ctrs)
+ 		n_subdevices++;
+ 
+-	if ((ret = alloc_subdevices(dev, n_subdevices)) < 0) {
++	ret = alloc_subdevices(dev, n_subdevices);
++	if ( ret < 0 )
+ 		return ret;
+-	}
+ 
+ 	icp_multi_reset(dev);
+ 
+diff --git a/drivers/staging/comedi/drivers/icp_multi.h b/drivers/staging/comedi/drivers/icp_multi.h
+index c0abc1062b8d..0796056a07a4 100644
+--- a/drivers/staging/comedi/drivers/icp_multi.h
++++ b/drivers/staging/comedi/drivers/icp_multi.h
+@@ -245,8 +245,9 @@ static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id,
+ 	int err;
+ 
+ 	if ((pci_bus < 1) & (pci_slot < 1)) {	/* use autodetection */
+-		if ((card = find_free_pci_card_by_device(vendor_id,
+-					device_id)) == NULL) {
++
++		card = find_free_pci_card_by_device(vendor_id,device_id);
++		if (card == NULL) {
+ 			rt_printk(" - Unused card not found in system!\n");
+ 			return NULL;
+ 		}
+@@ -266,7 +267,8 @@ static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id,
+ 		}
+ 	}
+ 
+-	if ((err = pci_card_alloc(card)) != 0) {
++	err = pci_card_alloc(card);
++	if ( err != 0) {
+ 		if (err > 0)
+ 			rt_printk(" - Can't allocate card!\n");
+ 		/* else: error already printed. */
+diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
+index 08e3dde67f8c..578b731ae500 100644
+--- a/drivers/staging/comedi/drivers/rtd520.c
++++ b/drivers/staging/comedi/drivers/rtd520.c
+@@ -779,7 +779,8 @@ static int rtd_attach(comedi_device *dev, comedi_devconfig *it)
+ 	devpriv->pci_dev = pcidev;
+ 	dev->board_name = thisboard->name;
+ 
+-	if ((ret = comedi_pci_enable(pcidev, DRV_NAME)) < 0) {
++	ret = comedi_pci_enable(pcidev, DRV_NAME);
++	if (ret < 0) {
+ 		printk("Failed to enable PCI device and request regions.\n");
+ 		return ret;
+ 	}
+@@ -918,8 +919,10 @@ static int rtd_attach(comedi_device *dev, comedi_devconfig *it)
+ 	/* TODO: set user out source ??? */
+ 
+ 	/* check if our interrupt is available and get it */
+-	if ((ret = comedi_request_irq(devpriv->pci_dev->irq, rtd_interrupt,
+-				IRQF_SHARED, DRV_NAME, dev)) < 0) {
++	ret = comedi_request_irq(devpriv->pci_dev->irq, rtd_interrupt,
++				 IRQF_SHARED, DRV_NAME, dev);
++
++	if (ret < 0) {
+ 		printk("Could not get interrupt! (%u)\n",
+ 			devpriv->pci_dev->irq);
+ 		return ret;
+diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
+index 71309d3e1227..9110ae3c7fec 100644
+--- a/drivers/staging/comedi/drivers/s626.c
++++ b/drivers/staging/comedi/drivers/s626.c
+@@ -525,7 +525,8 @@ static int s626_attach(comedi_device *dev, comedi_devconfig *it)
+ 		return -ENODEV;
+ 	}
+ 
+-	if ((result = comedi_pci_enable(pdev, "s626")) < 0) {
++	result = comedi_pci_enable(pdev, "s626");
++	if (result < 0) {
+ 		printk("s626_attach: comedi_pci_enable fails\n");
+ 		return -ENODEV;
+ 	}
+@@ -552,9 +553,10 @@ static int s626_attach(comedi_device *dev, comedi_devconfig *it)
+ 		/* adc buffer allocation */
+ 		devpriv->allocatedBuf = 0;
+ 
+-		if ((devpriv->ANABuf.LogicalBase =
+-				pci_alloc_consistent(devpriv->pdev, DMABUF_SIZE,
+-					&appdma)) == NULL) {
++		devpriv->ANABuf.LogicalBase =
++			pci_alloc_consistent(devpriv->pdev, DMABUF_SIZE, &appdma);
++
++		if (devpriv->ANABuf.LogicalBase == NULL) {
+ 			printk("s626_attach: DMA Memory mapping error\n");
+ 			return -ENOMEM;
+ 		}
+@@ -565,9 +567,10 @@ static int s626_attach(comedi_device *dev, comedi_devconfig *it)
+ 
+ 		devpriv->allocatedBuf++;
+ 
+-		if ((devpriv->RPSBuf.LogicalBase =
+-				pci_alloc_consistent(devpriv->pdev, DMABUF_SIZE,
+-					&appdma)) == NULL) {
++		devpriv->RPSBuf.LogicalBase =
++			pci_alloc_consistent(devpriv->pdev, DMABUF_SIZE,  &appdma);
++
++		if (devpriv->RPSBuf.LogicalBase == NULL) {
+ 			printk("s626_attach: DMA Memory mapping error\n");
+ 			return -ENOMEM;
+ 		}
+@@ -593,8 +596,10 @@ static int s626_attach(comedi_device *dev, comedi_devconfig *it)
+ 	if (dev->irq == 0) {
+ 		printk(" unknown irq (bad)\n");
+ 	} else {
+-		if ((ret = comedi_request_irq(dev->irq, s626_irq_handler,
+-					IRQF_SHARED, "s626", dev)) < 0) {
++		ret = comedi_request_irq(dev->irq, s626_irq_handler,
++					 IRQF_SHARED, "s626", dev);
++
++		if (ret < 0) {
+ 			printk(" irq not available\n");
+ 			dev->irq = 0;
+ 		}
+diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+index 7133f2f2607c..94a5067f6bd5 100644
+--- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
++++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+@@ -256,7 +256,8 @@ int comedi_do_insn(comedi_t *d, comedi_insn *insn)
+ 
+ 		/* XXX check lock */
+ 
+-		if ((ret = check_chanlist(s, 1, &insn->chanspec)) < 0) {
++		ret = check_chanlist(s, 1, &insn->chanspec);
++		if (ret < 0) {
+ 			rt_printk("bad chanspec\n");
+ 			ret = -EINVAL;
+ 			goto error;
+@@ -443,7 +444,9 @@ int comedi_cancel(comedi_t *d, unsigned int subdevice)
+ 	if (!s->cancel || !s->async)
+ 		return -EINVAL;
+ 
+-	if ((ret = s->cancel(dev, s)))
++	ret = s->cancel(dev, s);
++
++	if (ret)
+ 		return ret;
+ 
+ #ifdef CONFIG_COMEDI_RT

commit 6a98d36e87a0b38d711d580b5fc9dbba17f68dfc
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:03:45 2009 -0400
+
+    Staging: comedi: Add spaces around parens as requested by checkpatch.pl
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/mite.h b/drivers/staging/comedi/drivers/mite.h
+index 37f397b340c5..bca9f3af7adb 100644
+--- a/drivers/staging/comedi/drivers/mite.h
++++ b/drivers/staging/comedi/drivers/mite.h
+@@ -33,7 +33,7 @@
+ #define PCIMIO_COMPAT
+ 
+ #ifdef DEBUG_MITE
+-#define MDPRINTK(format, args...)	printk(format , ## args )
++#define MDPRINTK(format, args...)	printk(format , ## args)
+ #else
+ #define MDPRINTK(format, args...)
+ #endif
+diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
+index a3763ade9c96..71309d3e1227 100644
+--- a/drivers/staging/comedi/drivers/s626.c
++++ b/drivers/staging/comedi/drivers/s626.c
+@@ -345,8 +345,8 @@ static void CountersInit(comedi_device *dev);
+ /*  Counter objects constructor. */
+ 
+ /*  Counter overflow/index event flag masks for RDMISC2. */
+-#define INDXMASK(C)		( 1 << ( ( (C) > 2 ) ? ( (C) * 2 - 1 ) : ( (C) * 2 +  4 ) ) )
+-#define OVERMASK(C)		( 1 << ( ( (C) > 2 ) ? ( (C) * 2 + 5 ) : ( (C) * 2 + 10 ) ) )
++#define INDXMASK(C)		(1 << (((C) > 2) ? ((C) * 2 - 1) : ((C) * 2 +  4)))
++#define OVERMASK(C)		(1 << (((C) > 2) ? ((C) * 2 + 5) : ((C) * 2 + 10)))
+ #define EVBITS(C)		{ 0, OVERMASK(C), INDXMASK(C), OVERMASK(C) | INDXMASK(C) }
+ 
+ /*  Translation table to map IntSrc into equivalent RDMISC2 event flag  bits. */
+@@ -454,11 +454,11 @@ static enc_private enc_private_data[] = {
+ 
+ /*  enab/disable a function or test status bit(s) that are accessed */
+ /*  through Main Control Registers 1 or 2. */
+-#define MC_ENABLE( REGADRS, CTRLWORD )	writel(  ( (uint32_t)( CTRLWORD ) << 16 ) | (uint32_t)( CTRLWORD ), devpriv->base_addr+( REGADRS ) )
++#define MC_ENABLE(REGADRS, CTRLWORD)	writel(((uint32_t)(CTRLWORD) << 16) | (uint32_t)(CTRLWORD), devpriv->base_addr+(REGADRS))
+ 
+-#define MC_DISABLE( REGADRS, CTRLWORD )	writel(  (uint32_t)( CTRLWORD ) << 16 , devpriv->base_addr+( REGADRS ) )
++#define MC_DISABLE(REGADRS, CTRLWORD)	writel((uint32_t)(CTRLWORD) << 16 , devpriv->base_addr+(REGADRS))
+ 
+-#define MC_TEST( REGADRS, CTRLWORD )	( ( readl(devpriv->base_addr+( REGADRS )) & CTRLWORD ) != 0 )
++#define MC_TEST(REGADRS, CTRLWORD)	((readl(devpriv->base_addr+(REGADRS)) & CTRLWORD) != 0)
+ 
+ /* #define WR7146(REGARDS,CTRLWORD)
+     writel(CTRLWORD,(uint32_t)(devpriv->base_addr+(REGARDS))) */
+@@ -468,16 +468,16 @@ static enc_private enc_private_data[] = {
+     readl((uint32_t)(devpriv->base_addr+(REGARDS))) */
+ #define RR7146(REGARDS)		readl(devpriv->base_addr+(REGARDS))
+ 
+-#define BUGFIX_STREG(REGADRS)   ( REGADRS - 4 )
++#define BUGFIX_STREG(REGADRS)   (REGADRS - 4)
+ 
+ /*  Write a time slot control record to TSL2. */
+-#define VECTPORT( VECTNUM )		(P_TSL2 + ( (VECTNUM) << 2 ))
+-#define SETVECT( VECTNUM, VECTVAL )	WR7146(VECTPORT( VECTNUM ), (VECTVAL))
++#define VECTPORT(VECTNUM)		(P_TSL2 + ((VECTNUM) << 2))
++#define SETVECT(VECTNUM, VECTVAL)	WR7146(VECTPORT(VECTNUM), (VECTVAL))
+ 
+ /*  Code macros used for constructing I2C command bytes. */
+-#define I2C_B2(ATTR, VAL)	( ( (ATTR) << 6 ) | ( (VAL) << 24 ) )
+-#define I2C_B1(ATTR, VAL)	( ( (ATTR) << 4 ) | ( (VAL) << 16 ) )
+-#define I2C_B0(ATTR, VAL)	( ( (ATTR) << 2 ) | ( (VAL) <<  8 ) )
++#define I2C_B2(ATTR, VAL)	(((ATTR) << 6) | ((VAL) << 24))
++#define I2C_B1(ATTR, VAL)	(((ATTR) << 4) | ((VAL) << 16))
++#define I2C_B0(ATTR, VAL)	(((ATTR) << 2) | ((VAL) <<  8))
+ 
+ static const comedi_lrange s626_range_table = { 2, {
+ 			RANGE(-5, 5),
+@@ -2353,7 +2353,7 @@ static void s626_timer_load(comedi_device *dev, enc_private *k, int tick)
+ /* ***********  DAC FUNCTIONS *********** */
+ 
+ /*  Slot 0 base settings. */
+-#define VECT0	( XSD2 | RSD3 | SIB_A2 )
++#define VECT0	(XSD2 | RSD3 | SIB_A2)
+ /*  Slot 0 always shifts in  0xFF and store it to  FB_BUFFER2. */
+ 
+ /*  TrimDac LogicalChan-to-PhysicalChan mapping table. */
+diff --git a/drivers/staging/comedi/drivers/s626.h b/drivers/staging/comedi/drivers/s626.h
+index c158110aa47c..c48957be2e1c 100644
+--- a/drivers/staging/comedi/drivers/s626.h
++++ b/drivers/staging/comedi/drivers/s626.h
+@@ -173,7 +173,7 @@
+ 
+ /*  RPS clock parameters. */
+ #define RPSCLK_SCALAR		8	/*  This is apparent ratio of PCI/RPS clks (undocumented!!). */
+-#define RPSCLK_PER_US		( 33 / RPSCLK_SCALAR )	/*  Number of RPS clocks in one microsecond. */
++#define RPSCLK_PER_US		(33 / RPSCLK_SCALAR)	/*  Number of RPS clocks in one microsecond. */
+ 
+ /*  Event counter source addresses. */
+ #define SBA_RPS_A0		0x27	/*  Time of RPS0 busy, in PCI clocks. */
+@@ -377,14 +377,14 @@
+ 
+ #if PLATFORM == INTEL		/* Base ACON1 config: always run A1 based
+ 				 * on TSL1. */
+-#define ACON1_BASE		( WS_MODES | A1_RUN )
++#define ACON1_BASE		(WS_MODES | A1_RUN)
+ #elif PLATFORM == MOTOROLA
+-#define ACON1_BASE		( WS_MODES | A1_RUN | A1_SWAP | A2_SWAP )
++#define ACON1_BASE		(WS_MODES | A1_RUN | A1_SWAP | A2_SWAP)
+ #endif
+ 
+ #define ACON1_ADCSTART		ACON1_BASE	/* Start ADC: run A1
+ 						 *  based on TSL1. */
+-#define ACON1_DACSTART		( ACON1_BASE | A2_RUN )
++#define ACON1_DACSTART		(ACON1_BASE | A2_RUN)
+ /* Start transmit to DAC: run A2 based on TSL2. */
+ #define ACON1_DACSTOP		ACON1_BASE	/*  Halt A2. */
+ 
+@@ -398,7 +398,7 @@
+ #define ACON2_XORMASK		0x000C0000	/*  XOR mask for ACON2 */
+ 						/*  active-low bits. */
+ 
+-#define ACON2_INIT		( ACON2_XORMASK ^ ( A1_CLKSRC_BCLK1 | A2_CLKSRC_X2 | INVERT_BCLK2 | BCLK2_OE ) )
++#define ACON2_INIT		(ACON2_XORMASK ^ (A1_CLKSRC_BCLK1 | A2_CLKSRC_X2 | INVERT_BCLK2 | BCLK2_OE))
+ 
+ /*  Bit masks for timeslot records. */
+ #define WS1		     	0x40000000	/*  WS output to assert. */
+@@ -452,7 +452,7 @@
+ /*  I2C manifest constants. */
+ 
+ /*  Max retries to wait for EEPROM write. */
+-#define I2C_RETRIES		( I2C_WRTIME * I2C_BITRATE / 9.0 )
++#define I2C_RETRIES		(I2C_WRTIME * I2C_BITRATE / 9.0)
+ #define I2C_ERR			0x0002	/*  I2C control/status */
+ 						/*  flag ERROR. */
+ #define I2C_BUSY		0x0001	/*  I2C control/status */
+@@ -464,15 +464,15 @@
+ #define I2C_ATTRNOP		0x0	/*  I2C attribute NOP. */
+ 
+ /*  I2C read command  | EEPROM address. */
+-#define I2CR			( devpriv->I2CAdrs | 1 )
++#define I2CR			(devpriv->I2CAdrs | 1)
+ 
+ /*  I2C write command | EEPROM address. */
+-#define I2CW			( devpriv->I2CAdrs )
++#define I2CW			(devpriv->I2CAdrs)
+ 
+ /*  Code macros used for constructing I2C command bytes. */
+-#define I2C_B2(ATTR, VAL)	( ( (ATTR) << 6 ) | ( (VAL) << 24 ) )
+-#define I2C_B1(ATTR, VAL)	( ( (ATTR) << 4 ) | ( (VAL) << 16 ) )
+-#define I2C_B0(ATTR, VAL)	( ( (ATTR) << 2 ) | ( (VAL) <<  8 ) )
++#define I2C_B2(ATTR, VAL)	(((ATTR) << 6) | ((VAL) << 24))
++#define I2C_B1(ATTR, VAL)	(((ATTR) << 4) | ((VAL) << 16))
++#define I2C_B0(ATTR, VAL)	(((ATTR) << 2) | ((VAL) <<  8))
+ 
+ /* oldest */
+ #define P_DEBICFGq              0x007C	/*  DEBI configuration. */
+@@ -490,16 +490,16 @@
+ #define DEBI_PAGE_DISABLEQ	0x00000000	/*  paging disable */
+ 
+ /*  DEBI command constants. */
+-#define DEBI_CMD_SIZE16		( 2 << 17 )	/*  Transfer size is */
++#define DEBI_CMD_SIZE16		(2 << 17)	/*  Transfer size is */
+ 						/*  always 2 bytes. */
+ #define DEBI_CMD_READ		0x00010000	/*  Read operation. */
+ #define DEBI_CMD_WRITE		0x00000000	/*  Write operation. */
+ 
+ /*  Read immediate 2 bytes. */
+-#define DEBI_CMD_RDWORD		( DEBI_CMD_READ  | DEBI_CMD_SIZE16 )
++#define DEBI_CMD_RDWORD		(DEBI_CMD_READ  | DEBI_CMD_SIZE16)
+ 
+ /*  Write immediate 2 bytes. */
+-#define DEBI_CMD_WRWORD		( DEBI_CMD_WRITE | DEBI_CMD_SIZE16 )
++#define DEBI_CMD_WRWORD		(DEBI_CMD_WRITE | DEBI_CMD_SIZE16)
+ 
+ /*  DEBI configuration constants. */
+ #define DEBI_CFG_XIRQ_EN	0x80000000	/*  enab external */
+@@ -681,29 +681,29 @@
+ 
+ /*  Bit field masks for CRA and CRB. */
+ 
+-#define CRAMSK_INDXSRC_B	( (uint16_t)( 3 << CRABIT_INDXSRC_B) )
+-#define CRAMSK_CLKSRC_B		( (uint16_t)( 3 << CRABIT_CLKSRC_B) )
+-#define CRAMSK_INDXPOL_A	( (uint16_t)( 1 << CRABIT_INDXPOL_A) )
+-#define CRAMSK_LOADSRC_A	( (uint16_t)( 3 << CRABIT_LOADSRC_A) )
+-#define CRAMSK_CLKMULT_A	( (uint16_t)( 3 << CRABIT_CLKMULT_A) )
+-#define CRAMSK_INTSRC_A		( (uint16_t)( 3 << CRABIT_INTSRC_A) )
+-#define CRAMSK_CLKPOL_A		( (uint16_t)( 3 << CRABIT_CLKPOL_A) )
+-#define CRAMSK_INDXSRC_A	( (uint16_t)( 3 << CRABIT_INDXSRC_A) )
+-#define CRAMSK_CLKSRC_A		( (uint16_t)( 3 << CRABIT_CLKSRC_A) )
+-
+-#define CRBMSK_INTRESETCMD	( (uint16_t)( 1 << CRBBIT_INTRESETCMD) )
+-#define CRBMSK_INTRESET_B	( (uint16_t)( 1 << CRBBIT_INTRESET_B) )
+-#define CRBMSK_INTRESET_A	( (uint16_t)( 1 << CRBBIT_INTRESET_A) )
+-#define CRBMSK_CLKENAB_A	( (uint16_t)( 1 << CRBBIT_CLKENAB_A) )
+-#define CRBMSK_INTSRC_B		( (uint16_t)( 3 << CRBBIT_INTSRC_B) )
+-#define CRBMSK_LATCHSRC		( (uint16_t)( 3 << CRBBIT_LATCHSRC) )
+-#define CRBMSK_LOADSRC_B	( (uint16_t)( 3 << CRBBIT_LOADSRC_B) )
+-#define CRBMSK_CLKMULT_B	( (uint16_t)( 3 << CRBBIT_CLKMULT_B) )
+-#define CRBMSK_CLKENAB_B	( (uint16_t)( 1 << CRBBIT_CLKENAB_B) )
+-#define CRBMSK_INDXPOL_B	( (uint16_t)( 1 << CRBBIT_INDXPOL_B) )
+-#define CRBMSK_CLKPOL_B		( (uint16_t)( 1 << CRBBIT_CLKPOL_B) )
+-
+-#define CRBMSK_INTCTRL		( CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A | CRBMSK_INTRESET_B )	/*  Interrupt reset control bits. */
++#define CRAMSK_INDXSRC_B	((uint16_t)(3 << CRABIT_INDXSRC_B))
++#define CRAMSK_CLKSRC_B		((uint16_t)(3 << CRABIT_CLKSRC_B))
++#define CRAMSK_INDXPOL_A	((uint16_t)(1 << CRABIT_INDXPOL_A))
++#define CRAMSK_LOADSRC_A	((uint16_t)(3 << CRABIT_LOADSRC_A))
++#define CRAMSK_CLKMULT_A	((uint16_t)(3 << CRABIT_CLKMULT_A))
++#define CRAMSK_INTSRC_A		((uint16_t)(3 << CRABIT_INTSRC_A))
++#define CRAMSK_CLKPOL_A		((uint16_t)(3 << CRABIT_CLKPOL_A))
++#define CRAMSK_INDXSRC_A	((uint16_t)(3 << CRABIT_INDXSRC_A))
++#define CRAMSK_CLKSRC_A		((uint16_t)(3 << CRABIT_CLKSRC_A))
++
++#define CRBMSK_INTRESETCMD	((uint16_t)(1 << CRBBIT_INTRESETCMD))
++#define CRBMSK_INTRESET_B	((uint16_t)(1 << CRBBIT_INTRESET_B))
++#define CRBMSK_INTRESET_A	((uint16_t)(1 << CRBBIT_INTRESET_A))
++#define CRBMSK_CLKENAB_A	((uint16_t)(1 << CRBBIT_CLKENAB_A))
++#define CRBMSK_INTSRC_B		((uint16_t)(3 << CRBBIT_INTSRC_B))
++#define CRBMSK_LATCHSRC		((uint16_t)(3 << CRBBIT_LATCHSRC))
++#define CRBMSK_LOADSRC_B	((uint16_t)(3 << CRBBIT_LOADSRC_B))
++#define CRBMSK_CLKMULT_B	((uint16_t)(3 << CRBBIT_CLKMULT_B))
++#define CRBMSK_CLKENAB_B	((uint16_t)(1 << CRBBIT_CLKENAB_B))
++#define CRBMSK_INDXPOL_B	((uint16_t)(1 << CRBBIT_INDXPOL_B))
++#define CRBMSK_CLKPOL_B		((uint16_t)(1 << CRBBIT_CLKPOL_B))
++
++#define CRBMSK_INTCTRL		(CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A | CRBMSK_INTRESET_B)	/*  Interrupt reset control bits. */
+ 
+ /*  Bit field positions for standardized SETUP structure. */
+ 
+@@ -719,15 +719,15 @@
+ 
+ /*  Bit field masks for standardized SETUP structure. */
+ 
+-#define STDMSK_INTSRC		( (uint16_t)( 3 << STDBIT_INTSRC   ) )
+-#define STDMSK_LATCHSRC		( (uint16_t)( 3 << STDBIT_LATCHSRC ) )
+-#define STDMSK_LOADSRC		( (uint16_t)( 3 << STDBIT_LOADSRC  ) )
+-#define STDMSK_INDXSRC		( (uint16_t)( 1 << STDBIT_INDXSRC  ) )
+-#define STDMSK_INDXPOL		( (uint16_t)( 1 << STDBIT_INDXPOL  ) )
+-#define STDMSK_CLKSRC		( (uint16_t)( 3 << STDBIT_CLKSRC   ) )
+-#define STDMSK_CLKPOL		( (uint16_t)( 1 << STDBIT_CLKPOL   ) )
+-#define STDMSK_CLKMULT		( (uint16_t)( 3 << STDBIT_CLKMULT  ) )
+-#define STDMSK_CLKENAB		( (uint16_t)( 1 << STDBIT_CLKENAB  ) )
++#define STDMSK_INTSRC		((uint16_t)(3 << STDBIT_INTSRC))
++#define STDMSK_LATCHSRC		((uint16_t)(3 << STDBIT_LATCHSRC))
++#define STDMSK_LOADSRC		((uint16_t)(3 << STDBIT_LOADSRC))
++#define STDMSK_INDXSRC		((uint16_t)(1 << STDBIT_INDXSRC))
++#define STDMSK_INDXPOL		((uint16_t)(1 << STDBIT_INDXPOL))
++#define STDMSK_CLKSRC		((uint16_t)(3 << STDBIT_CLKSRC))
++#define STDMSK_CLKPOL		((uint16_t)(1 << STDBIT_CLKPOL))
++#define STDMSK_CLKMULT		((uint16_t)(3 << STDBIT_CLKMULT))
++#define STDMSK_CLKENAB		((uint16_t)(1 << STDBIT_CLKENAB))
+ 
+ 
+ /* typedef struct indexCounter */
+diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+index e758e4e8c91b..7133f2f2607c 100644
+--- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
++++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+@@ -57,11 +57,11 @@ comedi_t *comedi_open(const char *filename)
+ 		return NULL;
+ 
+ 	dev_file_info = comedi_get_device_file_info(minor);
+-	if(dev_file_info == NULL)
++	if (dev_file_info == NULL)
+ 		return NULL;
+ 	dev = dev_file_info->device;
+ 
+-	if(dev == NULL || !dev->attached)
++	if (dev == NULL || !dev->attached)
+ 		return NULL;
+ 
+ 	if (!try_module_get(dev->driver->module))
+@@ -79,11 +79,11 @@ comedi_t *comedi_open_old(unsigned int minor)
+ 		return NULL;
+ 
+ 	dev_file_info = comedi_get_device_file_info(minor);
+-	if(dev_file_info == NULL)
++	if (dev_file_info == NULL)
+ 		return NULL;
+ 	dev = dev_file_info->device;
+ 
+-	if(dev == NULL || !dev->attached)
++	if (dev == NULL || !dev->attached)
+ 		return NULL;
+ 
+ 	return (comedi_t *) dev;
+diff --git a/drivers/staging/comedi/proc.c b/drivers/staging/comedi/proc.c
+index 031004ebc6ec..100877362577 100644
+--- a/drivers/staging/comedi/proc.c
++++ b/drivers/staging/comedi/proc.c
+@@ -55,7 +55,7 @@ int comedi_read_procmem(char *buf, char **start, off_t offset, int len,
+ 		struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(i);
+ 		comedi_device *dev;
+ 
+-		if(dev_file_info == NULL) continue;
++		if (dev_file_info == NULL) continue;
+ 		dev = dev_file_info->device;
+ 
+ 		if (dev->attached) {

commit f7266a48a10d76ff512d5eb44aa18364ee203da4
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:03:40 2009 -0400
+
+    Staging: comedi: Add spaces around colons as needed
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
+index ef8f783ba4e4..aefd1c16ab2b 100644
+--- a/drivers/staging/comedi/drivers/icp_multi.c
++++ b/drivers/staging/comedi/drivers/icp_multi.c
+@@ -175,12 +175,12 @@ static const boardtype boardtypes[] = {
+ 
+ static comedi_driver driver_icp_multi = {
+       driver_name:"icp_multi",
+-      module:THIS_MODULE,
+-      attach:icp_multi_attach,
+-      detach:icp_multi_detach,
+-      num_names:n_boardtypes,
++      module : THIS_MODULE,
++      attach : icp_multi_attach,
++      detach : icp_multi_detach,
++      num_names : n_boardtypes,
+       board_name:&boardtypes[0].name,
+-      offset:sizeof(boardtype),
++      offset : sizeof(boardtype),
+ };
+ 
+ COMEDI_INITCLEANUP(driver_icp_multi);
+diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
+index 3aafedecf7ed..c1f10b89a831 100644
+--- a/drivers/staging/comedi/drivers/me4000.c
++++ b/drivers/staging/comedi/drivers/me4000.c
+@@ -122,9 +122,9 @@ static int me4000_attach(comedi_device *dev, comedi_devconfig *it);
+ static int me4000_detach(comedi_device *dev);
+ static comedi_driver driver_me4000 = {
+       driver_name:"me4000",
+-      module:THIS_MODULE,
+-      attach:me4000_attach,
+-      detach:me4000_detach,
++      module : THIS_MODULE,
++      attach : me4000_attach,
++      detach : me4000_detach,
+ };
+ 
+ /*-----------------------------------------------------------------------------
+diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
+index 326dd2f1b840..08e3dde67f8c 100644
+--- a/drivers/staging/comedi/drivers/rtd520.c
++++ b/drivers/staging/comedi/drivers/rtd520.c
+@@ -279,7 +279,7 @@ typedef struct rtdBoard_struct {
+ static const rtdBoard rtd520Boards[] = {
+ 	{
+ 	      name:	"DM7520",
+-	      device_id:0x7520,
++	      device_id : 0x7520,
+ 	      aiChans:	16,
+ 	      aiBits:	12,
+ 	      aiMaxGain:32,
+@@ -288,7 +288,7 @@ static const rtdBoard rtd520Boards[] = {
+ 		},
+ 	{
+ 	      name:	"PCI4520",
+-	      device_id:0x4520,
++	      device_id : 0x4520,
+ 	      aiChans:	16,
+ 	      aiBits:	12,
+ 	      aiMaxGain:128,
+@@ -685,9 +685,9 @@ static int rtd_detach(comedi_device *dev);
+ 
+ static comedi_driver rtd520Driver = {
+       driver_name: DRV_NAME,
+-      module:THIS_MODULE,
+-      attach:rtd_attach,
+-      detach:rtd_detach,
++      module : THIS_MODULE,
++      attach : rtd_attach,
++      detach : rtd_detach,
+ };
+ 
+ static int rtd_ai_rinsn(comedi_device *dev, comedi_subdevice *s,
+diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
+index 0c1f5297fe2f..a3763ade9c96 100644
+--- a/drivers/staging/comedi/drivers/s626.c
++++ b/drivers/staging/comedi/drivers/s626.c
+@@ -96,13 +96,13 @@ typedef struct s626_board_struct {
+ static const s626_board s626_boards[] = {
+ 	{
+ 	      name:	"s626",
+-	      ai_chans:S626_ADC_CHANNELS,
++	      ai_chans : S626_ADC_CHANNELS,
+ 	      ai_bits:	14,
+-	      ao_chans:S626_DAC_CHANNELS,
++	      ao_chans : S626_DAC_CHANNELS,
+ 	      ao_bits:	13,
+-	      dio_chans:S626_DIO_CHANNELS,
+-	      dio_banks:S626_DIO_BANKS,
+-	      enc_chans:S626_ENCODER_CHANNELS,
++	      dio_chans : S626_DIO_CHANNELS,
++	      dio_banks : S626_DIO_BANKS,
++	      enc_chans : S626_ENCODER_CHANNELS,
+ 		}
+ };
+ 
+@@ -123,9 +123,9 @@ static int s626_detach(comedi_device *dev);
+ 
+ static comedi_driver driver_s626 = {
+       driver_name:"s626",
+-      module:THIS_MODULE,
+-      attach:s626_attach,
+-      detach:s626_detach,
++      module : THIS_MODULE,
++      attach : s626_attach,
++      detach : s626_detach,
+ };
+ 
+ typedef struct {
+@@ -174,38 +174,38 @@ typedef struct {
+ 
+ static dio_private dio_private_A = {
+       RDDIn:LP_RDDINA,
+-      WRDOut:LP_WRDOUTA,
+-      RDEdgSel:LP_RDEDGSELA,
+-      WREdgSel:LP_WREDGSELA,
+-      RDCapSel:LP_RDCAPSELA,
+-      WRCapSel:LP_WRCAPSELA,
+-      RDCapFlg:LP_RDCAPFLGA,
+-      RDIntSel:LP_RDINTSELA,
+-      WRIntSel:LP_WRINTSELA,
++      WRDOut : LP_WRDOUTA,
++      RDEdgSel : LP_RDEDGSELA,
++      WREdgSel : LP_WREDGSELA,
++      RDCapSel : LP_RDCAPSELA,
++      WRCapSel : LP_WRCAPSELA,
++      RDCapFlg : LP_RDCAPFLGA,
++      RDIntSel : LP_RDINTSELA,
++      WRIntSel : LP_WRINTSELA,
+ };
+ 
+ static dio_private dio_private_B = {
+       RDDIn:LP_RDDINB,
+-      WRDOut:LP_WRDOUTB,
+-      RDEdgSel:LP_RDEDGSELB,
+-      WREdgSel:LP_WREDGSELB,
+-      RDCapSel:LP_RDCAPSELB,
+-      WRCapSel:LP_WRCAPSELB,
+-      RDCapFlg:LP_RDCAPFLGB,
+-      RDIntSel:LP_RDINTSELB,
+-      WRIntSel:LP_WRINTSELB,
++      WRDOut : LP_WRDOUTB,
++      RDEdgSel : LP_RDEDGSELB,
++      WREdgSel : LP_WREDGSELB,
++      RDCapSel : LP_RDCAPSELB,
++      WRCapSel : LP_WRCAPSELB,
++      RDCapFlg : LP_RDCAPFLGB,
++      RDIntSel : LP_RDINTSELB,
++      WRIntSel : LP_WRINTSELB,
+ };
+ 
+ static dio_private dio_private_C = {
+       RDDIn:LP_RDDINC,
+-      WRDOut:LP_WRDOUTC,
+-      RDEdgSel:LP_RDEDGSELC,
+-      WREdgSel:LP_WREDGSELC,
+-      RDCapSel:LP_RDCAPSELC,
+-      WRCapSel:LP_WRCAPSELC,
+-      RDCapFlg:LP_RDCAPFLGC,
+-      RDIntSel:LP_RDINTSELC,
+-      WRIntSel:LP_WRINTSELC,
++      WRDOut : LP_WRDOUTC,
++      RDEdgSel : LP_RDEDGSELC,
++      WREdgSel : LP_WREDGSELC,
++      RDCapSel : LP_RDCAPSELC,
++      WRCapSel : LP_WRCAPSELC,
++      RDCapFlg : LP_RDCAPFLGC,
++      RDIntSel : LP_RDINTSELC,
++      WRIntSel : LP_WRINTSELC,
+ };
+ 
+ /* to group dio devices (48 bits mask and data are not allowed ???)
+@@ -356,99 +356,99 @@ static void CountersInit(comedi_device *dev);
+ static enc_private enc_private_data[] = {
+ 	{
+ 	      GetEnable:GetEnable_A,
+-	      GetIntSrc:GetIntSrc_A,
+-	      GetLoadTrig:GetLoadTrig_A,
++	      GetIntSrc : GetIntSrc_A,
++	      GetLoadTrig : GetLoadTrig_A,
+ 	      GetMode:	GetMode_A,
+-	      PulseIndex:PulseIndex_A,
+-	      SetEnable:SetEnable_A,
+-	      SetIntSrc:SetIntSrc_A,
+-	      SetLoadTrig:SetLoadTrig_A,
++	      PulseIndex : PulseIndex_A,
++	      SetEnable : SetEnable_A,
++	      SetIntSrc : SetIntSrc_A,
++	      SetLoadTrig : SetLoadTrig_A,
+ 	      SetMode:	SetMode_A,
+-	      ResetCapFlags:ResetCapFlags_A,
++	      ResetCapFlags : ResetCapFlags_A,
+ 	      MyCRA:	LP_CR0A,
+ 	      MyCRB:	LP_CR0B,
+-	      MyLatchLsw:LP_CNTR0ALSW,
+-	      MyEventBits:EVBITS(0),
++	      MyLatchLsw : LP_CNTR0ALSW,
++	      MyEventBits : EVBITS(0),
+ 		},
+ 	{
+ 	      GetEnable:GetEnable_A,
+-	      GetIntSrc:GetIntSrc_A,
+-	      GetLoadTrig:GetLoadTrig_A,
++	      GetIntSrc : GetIntSrc_A,
++	      GetLoadTrig : GetLoadTrig_A,
+ 	      GetMode:	GetMode_A,
+-	      PulseIndex:PulseIndex_A,
+-	      SetEnable:SetEnable_A,
+-	      SetIntSrc:SetIntSrc_A,
+-	      SetLoadTrig:SetLoadTrig_A,
++	      PulseIndex : PulseIndex_A,
++	      SetEnable : SetEnable_A,
++	      SetIntSrc : SetIntSrc_A,
++	      SetLoadTrig : SetLoadTrig_A,
+ 	      SetMode:	SetMode_A,
+-	      ResetCapFlags:ResetCapFlags_A,
++	      ResetCapFlags : ResetCapFlags_A,
+ 	      MyCRA:	LP_CR1A,
+ 	      MyCRB:	LP_CR1B,
+-	      MyLatchLsw:LP_CNTR1ALSW,
+-	      MyEventBits:EVBITS(1),
++	      MyLatchLsw : LP_CNTR1ALSW,
++	      MyEventBits : EVBITS(1),
+ 		},
+ 	{
+ 	      GetEnable:GetEnable_A,
+-	      GetIntSrc:GetIntSrc_A,
+-	      GetLoadTrig:GetLoadTrig_A,
++	      GetIntSrc : GetIntSrc_A,
++	      GetLoadTrig : GetLoadTrig_A,
+ 	      GetMode:	GetMode_A,
+-	      PulseIndex:PulseIndex_A,
+-	      SetEnable:SetEnable_A,
+-	      SetIntSrc:SetIntSrc_A,
+-	      SetLoadTrig:SetLoadTrig_A,
++	      PulseIndex : PulseIndex_A,
++	      SetEnable : SetEnable_A,
++	      SetIntSrc : SetIntSrc_A,
++	      SetLoadTrig : SetLoadTrig_A,
+ 	      SetMode:	SetMode_A,
+-	      ResetCapFlags:ResetCapFlags_A,
++	      ResetCapFlags : ResetCapFlags_A,
+ 	      MyCRA:	LP_CR2A,
+ 	      MyCRB:	LP_CR2B,
+-	      MyLatchLsw:LP_CNTR2ALSW,
+-	      MyEventBits:EVBITS(2),
++	      MyLatchLsw : LP_CNTR2ALSW,
++	      MyEventBits : EVBITS(2),
+ 		},
+ 	{
+ 	      GetEnable:GetEnable_B,
+-	      GetIntSrc:GetIntSrc_B,
+-	      GetLoadTrig:GetLoadTrig_B,
++	      GetIntSrc : GetIntSrc_B,
++	      GetLoadTrig : GetLoadTrig_B,
+ 	      GetMode:	GetMode_B,
+-	      PulseIndex:PulseIndex_B,
+-	      SetEnable:SetEnable_B,
+-	      SetIntSrc:SetIntSrc_B,
+-	      SetLoadTrig:SetLoadTrig_B,
++	      PulseIndex : PulseIndex_B,
++	      SetEnable : SetEnable_B,
++	      SetIntSrc : SetIntSrc_B,
++	      SetLoadTrig : SetLoadTrig_B,
+ 	      SetMode:	SetMode_B,
+-	      ResetCapFlags:ResetCapFlags_B,
++	      ResetCapFlags : ResetCapFlags_B,
+ 	      MyCRA:	LP_CR0A,
+ 	      MyCRB:	LP_CR0B,
+-	      MyLatchLsw:LP_CNTR0BLSW,
+-	      MyEventBits:EVBITS(3),
++	      MyLatchLsw : LP_CNTR0BLSW,
++	      MyEventBits : EVBITS(3),
+ 		},
+ 	{
+ 	      GetEnable:GetEnable_B,
+-	      GetIntSrc:GetIntSrc_B,
+-	      GetLoadTrig:GetLoadTrig_B,
++	      GetIntSrc : GetIntSrc_B,
++	      GetLoadTrig : GetLoadTrig_B,
+ 	      GetMode:	GetMode_B,
+-	      PulseIndex:PulseIndex_B,
+-	      SetEnable:SetEnable_B,
+-	      SetIntSrc:SetIntSrc_B,
+-	      SetLoadTrig:SetLoadTrig_B,
++	      PulseIndex : PulseIndex_B,
++	      SetEnable : SetEnable_B,
++	      SetIntSrc : SetIntSrc_B,
++	      SetLoadTrig : SetLoadTrig_B,
+ 	      SetMode:	SetMode_B,
+-	      ResetCapFlags:ResetCapFlags_B,
++	      ResetCapFlags : ResetCapFlags_B,
+ 	      MyCRA:	LP_CR1A,
+ 	      MyCRB:	LP_CR1B,
+-	      MyLatchLsw:LP_CNTR1BLSW,
+-	      MyEventBits:EVBITS(4),
++	      MyLatchLsw : LP_CNTR1BLSW,
++	      MyEventBits : EVBITS(4),
+ 		},
+ 	{
+ 	      GetEnable:GetEnable_B,
+-	      GetIntSrc:GetIntSrc_B,
+-	      GetLoadTrig:GetLoadTrig_B,
++	      GetIntSrc : GetIntSrc_B,
++	      GetLoadTrig : GetLoadTrig_B,
+ 	      GetMode:	GetMode_B,
+-	      PulseIndex:PulseIndex_B,
+-	      SetEnable:SetEnable_B,
+-	      SetIntSrc:SetIntSrc_B,
+-	      SetLoadTrig:SetLoadTrig_B,
++	      PulseIndex : PulseIndex_B,
++	      SetEnable : SetEnable_B,
++	      SetIntSrc : SetIntSrc_B,
++	      SetLoadTrig : SetLoadTrig_B,
+ 	      SetMode:	SetMode_B,
+-	      ResetCapFlags:ResetCapFlags_B,
++	      ResetCapFlags : ResetCapFlags_B,
+ 	      MyCRA:	LP_CR2A,
+ 	      MyCRB:	LP_CR2B,
+-	      MyLatchLsw:LP_CNTR2BLSW,
+-	      MyEventBits:EVBITS(5),
++	      MyLatchLsw : LP_CNTR2BLSW,
++	      MyEventBits : EVBITS(5),
+ 		},
+ };
+ 

commit 8086fff871940e6a348a733a303f39c086e4b3c5
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:03:35 2009 -0400
+
+    Staging: comedi: Add spaces after commas where suggested by checkpatch.pl
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c
+index 7d0116bcb9ff..98e570a2cb3e 100644
+--- a/drivers/staging/comedi/comedi_compat32.c
++++ b/drivers/staging/comedi/comedi_compat32.c
+@@ -37,16 +37,16 @@
+ #include 	/* for (un)register_ioctl32_conversion */
+ #endif
+ 
+-#define COMEDI32_CHANINFO _IOR(CIO,3,comedi32_chaninfo)
+-#define COMEDI32_RANGEINFO _IOR(CIO,8,comedi32_rangeinfo)
++#define COMEDI32_CHANINFO _IOR(CIO, 3, comedi32_chaninfo)
++#define COMEDI32_RANGEINFO _IOR(CIO, 8, comedi32_rangeinfo)
+ /* N.B. COMEDI32_CMD and COMEDI_CMD ought to use _IOWR, not _IOR.
+  * It's too late to change it now, but it only affects the command number. */
+-#define COMEDI32_CMD _IOR(CIO,9,comedi32_cmd)
++#define COMEDI32_CMD _IOR(CIO, 9, comedi32_cmd)
+ /* N.B. COMEDI32_CMDTEST and COMEDI_CMDTEST ought to use _IOWR, not _IOR.
+  * It's too late to change it now, but it only affects the command number. */
+-#define COMEDI32_CMDTEST _IOR(CIO,10,comedi32_cmd)
+-#define COMEDI32_INSNLIST _IOR(CIO,11,comedi32_insnlist)
+-#define COMEDI32_INSN _IOR(CIO,12,comedi32_insn)
++#define COMEDI32_CMDTEST _IOR(CIO, 10, comedi32_cmd)
++#define COMEDI32_INSNLIST _IOR(CIO, 11, comedi32_insnlist)
++#define COMEDI32_INSN _IOR(CIO, 12, comedi32_insn)
+ 
+ typedef struct comedi32_chaninfo_struct {
+ 	unsigned int subdev;
+diff --git a/drivers/staging/comedi/drivers/mite.h b/drivers/staging/comedi/drivers/mite.h
+index 2b2df8b4e360..37f397b340c5 100644
+--- a/drivers/staging/comedi/drivers/mite.h
++++ b/drivers/staging/comedi/drivers/mite.h
+@@ -33,9 +33,9 @@
+ #define PCIMIO_COMPAT
+ 
+ #ifdef DEBUG_MITE
+-#define MDPRINTK(format,args...)	printk(format , ## args )
++#define MDPRINTK(format, args...)	printk(format , ## args )
+ #else
+-#define MDPRINTK(format,args...)
++#define MDPRINTK(format, args...)
+ #endif
+ 
+ #define MAX_MITE_DMA_CHANNELS 8
+diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
+index 4d8c68104530..326dd2f1b840 100644
+--- a/drivers/staging/comedi/drivers/rtd520.c
++++ b/drivers/staging/comedi/drivers/rtd520.c
+@@ -366,11 +366,11 @@ typedef struct {
+ #define DMA1_ACTIVE	0x04	/* DMA1 is active */
+ 
+ /* Macros for accessing channel list bit array */
+-#define CHAN_ARRAY_TEST(array,index) \
++#define CHAN_ARRAY_TEST(array, index) \
+ 	(((array)[(index)/8] >> ((index) & 0x7)) & 0x1)
+-#define CHAN_ARRAY_SET(array,index) \
++#define CHAN_ARRAY_SET(array, index) \
+ 	(((array)[(index)/8] |= 1 << ((index) & 0x7)))
+-#define CHAN_ARRAY_CLEAR(array,index) \
++#define CHAN_ARRAY_CLEAR(array, index) \
+ 	(((array)[(index)/8] &= ~(1 << ((index) & 0x7))))
+ 
+ /*
+@@ -394,15 +394,15 @@ typedef struct {
+     writel (0, devpriv->las0+LAS0_CGT_CLEAR)
+ 
+ /* Reset channel gain table read and write pointers */
+-#define RtdEnableCGT(dev,v) \
++#define RtdEnableCGT(dev, v) \
+     writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_CGT_ENABLE)
+ 
+ /* Write channel gain table entry */
+-#define RtdWriteCGTable(dev,v) \
++#define RtdWriteCGTable(dev, v) \
+     writel (v, devpriv->las0+LAS0_CGT_WRITE)
+ 
+ /* Write Channel Gain Latch */
+-#define RtdWriteCGLatch(dev,v) \
++#define RtdWriteCGLatch(dev, v) \
+     writel (v, devpriv->las0+LAS0_CGL_WRITE)
+ 
+ /* Reset ADC FIFO */
+@@ -410,39 +410,39 @@ typedef struct {
+     writel (0, devpriv->las0+LAS0_ADC_FIFO_CLEAR)
+ 
+ /* Set ADC start conversion source select (write only) */
+-#define RtdAdcConversionSource(dev,v) \
++#define RtdAdcConversionSource(dev, v) \
+     writel (v, devpriv->las0+LAS0_ADC_CONVERSION)
+ 
+ /* Set burst start source select (write only) */
+-#define RtdBurstStartSource(dev,v) \
++#define RtdBurstStartSource(dev, v) \
+     writel (v, devpriv->las0+LAS0_BURST_START)
+ 
+ /* Set Pacer start source select (write only) */
+-#define RtdPacerStartSource(dev,v) \
++#define RtdPacerStartSource(dev, v) \
+     writel (v, devpriv->las0+LAS0_PACER_START)
+ 
+ /* Set Pacer stop source select (write only) */
+-#define RtdPacerStopSource(dev,v) \
++#define RtdPacerStopSource(dev, v) \
+     writel (v, devpriv->las0+LAS0_PACER_STOP)
+ 
+ /* Set Pacer clock source select (write only) 0=external 1=internal */
+-#define RtdPacerClockSource(dev,v) \
++#define RtdPacerClockSource(dev, v) \
+     writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_PACER_SELECT)
+ 
+ /* Set sample counter source select (write only) */
+-#define RtdAdcSampleCounterSource(dev,v) \
++#define RtdAdcSampleCounterSource(dev, v) \
+     writel (v, devpriv->las0+LAS0_ADC_SCNT_SRC)
+ 
+ /* Set Pacer trigger mode select (write only) 0=single cycle, 1=repeat */
+-#define RtdPacerTriggerMode(dev,v) \
++#define RtdPacerTriggerMode(dev, v) \
+     writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_PACER_REPEAT)
+ 
+ /* Set About counter stop enable (write only) */
+-#define RtdAboutStopEnable(dev,v) \
++#define RtdAboutStopEnable(dev, v) \
+     writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_ACNT_STOP_ENABLE)
+ 
+ /* Set external trigger polarity (write only) 0=positive edge, 1=negative */
+-#define RtdTriggerPolarity(dev,v) \
++#define RtdTriggerPolarity(dev, v) \
+     writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_ETRG_POLARITY)
+ 
+ /* Start single ADC conversion */
+@@ -473,15 +473,15 @@ typedef struct {
+     readw (devpriv->las0+LAS0_IT)
+ 
+ /* Interrupt mask */
+-#define RtdInterruptMask(dev,v) \
+-    writew ((devpriv->intMask = (v)),devpriv->las0+LAS0_IT)
++#define RtdInterruptMask(dev, v) \
++    writew ((devpriv->intMask = (v)), devpriv->las0+LAS0_IT)
+ 
+ /* Interrupt status clear (only bits set in mask) */
+ #define RtdInterruptClear(dev) \
+     readw (devpriv->las0+LAS0_CLEAR)
+ 
+ /* Interrupt clear mask */
+-#define RtdInterruptClearMask(dev,v) \
++#define RtdInterruptClearMask(dev, v) \
+     writew ((devpriv->intClearMask = (v)), devpriv->las0+LAS0_CLEAR)
+ 
+ /* Interrupt overrun status */
+@@ -495,92 +495,92 @@ typedef struct {
+ /* Pacer counter, 24bit */
+ #define RtdPacerCount(dev) \
+     readl (devpriv->las0+LAS0_PCLK)
+-#define RtdPacerCounter(dev,v) \
+-    writel ((v) & 0xffffff,devpriv->las0+LAS0_PCLK)
++#define RtdPacerCounter(dev, v) \
++    writel ((v) & 0xffffff, devpriv->las0+LAS0_PCLK)
+ 
+ /* Burst counter, 10bit */
+ #define RtdBurstCount(dev) \
+     readl (devpriv->las0+LAS0_BCLK)
+-#define RtdBurstCounter(dev,v) \
+-    writel ((v) & 0x3ff,devpriv->las0+LAS0_BCLK)
++#define RtdBurstCounter(dev, v) \
++    writel ((v) & 0x3ff, devpriv->las0+LAS0_BCLK)
+ 
+ /* Delay counter, 16bit */
+ #define RtdDelayCount(dev) \
+     readl (devpriv->las0+LAS0_DCLK)
+-#define RtdDelayCounter(dev,v) \
++#define RtdDelayCounter(dev, v) \
+     writel ((v) & 0xffff, devpriv->las0+LAS0_DCLK)
+ 
+ /* About counter, 16bit */
+ #define RtdAboutCount(dev) \
+     readl (devpriv->las0+LAS0_ACNT)
+-#define RtdAboutCounter(dev,v) \
++#define RtdAboutCounter(dev, v) \
+     writel ((v) & 0xffff, devpriv->las0+LAS0_ACNT)
+ 
+ /* ADC sample counter, 10bit */
+ #define RtdAdcSampleCount(dev) \
+     readl (devpriv->las0+LAS0_ADC_SCNT)
+-#define RtdAdcSampleCounter(dev,v) \
++#define RtdAdcSampleCounter(dev, v) \
+     writel ((v) & 0x3ff, devpriv->las0+LAS0_ADC_SCNT)
+ 
+ /* User Timer/Counter (8254) */
+-#define RtdUtcCounterGet(dev,n) \
++#define RtdUtcCounterGet(dev, n) \
+     readb (devpriv->las0 \
+         + ((n <= 0) ? LAS0_UTC0 : ((1 == n) ? LAS0_UTC1 : LAS0_UTC2)))
+ 
+-#define RtdUtcCounterPut(dev,n,v) \
++#define RtdUtcCounterPut(dev, n, v) \
+     writeb ((v) & 0xff, devpriv->las0 \
+         + ((n <= 0) ? LAS0_UTC0 : ((1 == n) ? LAS0_UTC1 : LAS0_UTC2)))
+ 
+ /* Set UTC (8254) control byte  */
+-#define RtdUtcCtrlPut(dev,n,v) \
++#define RtdUtcCtrlPut(dev, n, v) \
+     writeb (devpriv->utcCtrl[(n) & 3] = (((n) & 3) << 6) | ((v) & 0x3f), \
+       devpriv->las0 + LAS0_UTC_CTRL)
+ 
+ /* Set UTCn clock source (write only) */
+-#define RtdUtcClockSource(dev,n,v) \
++#define RtdUtcClockSource(dev, n, v) \
+     writew (v, devpriv->las0 \
+         + ((n <= 0) ? LAS0_UTC0_CLOCK : \
+            ((1 == n) ? LAS0_UTC1_CLOCK : LAS0_UTC2_CLOCK)))
+ 
+ /* Set UTCn gate source (write only) */
+-#define RtdUtcGateSource(dev,n,v) \
++#define RtdUtcGateSource(dev, n, v) \
+     writew (v, devpriv->las0 \
+         + ((n <= 0) ? LAS0_UTC0_GATE : \
+            ((1 == n) ? LAS0_UTC1_GATE : LAS0_UTC2_GATE)))
+ 
+ /* User output N source select (write only) */
+-#define RtdUsrOutSource(dev,n,v) \
+-    writel (v,devpriv->las0+((n <= 0) ? LAS0_UOUT0_SELECT : LAS0_UOUT1_SELECT))
++#define RtdUsrOutSource(dev, n, v) \
++    writel (v, devpriv->las0+((n <= 0) ? LAS0_UOUT0_SELECT : LAS0_UOUT1_SELECT))
+ 
+ /* Digital IO */
+ #define RtdDio0Read(dev) \
+     (readw (devpriv->las0+LAS0_DIO0) & 0xff)
+-#define RtdDio0Write(dev,v) \
++#define RtdDio0Write(dev, v) \
+     writew ((v) & 0xff, devpriv->las0+LAS0_DIO0)
+ 
+ #define RtdDio1Read(dev) \
+     (readw (devpriv->las0+LAS0_DIO1) & 0xff)
+-#define RtdDio1Write(dev,v) \
++#define RtdDio1Write(dev, v) \
+     writew ((v) & 0xff, devpriv->las0+LAS0_DIO1)
+ 
+ #define RtdDioStatusRead(dev) \
+     (readw (devpriv->las0+LAS0_DIO_STATUS) & 0xff)
+-#define RtdDioStatusWrite(dev,v) \
++#define RtdDioStatusWrite(dev, v) \
+     writew ((devpriv->dioStatus = (v)), devpriv->las0+LAS0_DIO_STATUS)
+ 
+ #define RtdDio0CtrlRead(dev) \
+     (readw (devpriv->las0+LAS0_DIO0_CTRL) & 0xff)
+-#define RtdDio0CtrlWrite(dev,v) \
++#define RtdDio0CtrlWrite(dev, v) \
+     writew ((v) & 0xff, devpriv->las0+LAS0_DIO0_CTRL)
+ 
+ /* Digital to Analog converter */
+ /* Write one data value (sign + 12bit + marker bits) */
+ /* Note: matches what DMA would put.  Actual value << 3 */
+-#define RtdDacFifoPut(dev,n,v) \
++#define RtdDacFifoPut(dev, n, v) \
+     writew ((v), devpriv->las1 +(((n) == 0) ? LAS1_DAC1_FIFO : LAS1_DAC2_FIFO))
+ 
+ /* Start single DAC conversion */
+-#define RtdDacUpdate(dev,n) \
++#define RtdDacUpdate(dev, n) \
+     writew (0, devpriv->las0 +(((n) == 0) ? LAS0_DAC1 : LAS0_DAC2))
+ 
+ /* Start single DAC conversion on both DACs */
+@@ -588,20 +588,20 @@ typedef struct {
+     writew (0, devpriv->las0+LAS0_DAC)
+ 
+ /* Set DAC output type and range */
+-#define RtdDacRange(dev,n,v) \
++#define RtdDacRange(dev, n, v) \
+     writew ((v) & 7, devpriv->las0 \
+ 	+(((n) == 0) ? LAS0_DAC1_CTRL : LAS0_DAC2_CTRL))
+ 
+ /* Reset DAC FIFO */
+-#define RtdDacClearFifo(dev,n) \
++#define RtdDacClearFifo(dev, n) \
+     writel (0, devpriv->las0+(((n) == 0) ? LAS0_DAC1_RESET : LAS0_DAC2_RESET))
+ 
+ /* Set source for DMA 0 (write only, shadow?) */
+-#define RtdDma0Source(dev,n) \
++#define RtdDma0Source(dev, n) \
+     writel ((n) & 0xf, devpriv->las0+LAS0_DMA0_SRC)
+ 
+ /* Set source for DMA 1 (write only, shadow?) */
+-#define RtdDma1Source(dev,n) \
++#define RtdDma1Source(dev, n) \
+     writel ((n) & 0xf, devpriv->las0+LAS0_DMA1_SRC)
+ 
+ /* Reset board state for DMA 0 */
+@@ -615,51 +615,51 @@ typedef struct {
+ /* PLX9080 interrupt mask and status */
+ #define RtdPlxInterruptRead(dev) \
+     readl (devpriv->lcfg+LCFG_ITCSR)
+-#define RtdPlxInterruptWrite(dev,v) \
++#define RtdPlxInterruptWrite(dev, v) \
+     writel (v, devpriv->lcfg+LCFG_ITCSR)
+ 
+ /* Set  mode for DMA 0 */
+-#define RtdDma0Mode(dev,m) \
++#define RtdDma0Mode(dev, m) \
+     writel ((m), devpriv->lcfg+LCFG_DMAMODE0)
+ 
+ /* Set PCI address for DMA 0 */
+-#define RtdDma0PciAddr(dev,a) \
++#define RtdDma0PciAddr(dev, a) \
+     writel ((a), devpriv->lcfg+LCFG_DMAPADR0)
+ 
+ /* Set local address for DMA 0 */
+-#define RtdDma0LocalAddr(dev,a) \
++#define RtdDma0LocalAddr(dev, a) \
+     writel ((a), devpriv->lcfg+LCFG_DMALADR0)
+ 
+ /* Set byte count for DMA 0 */
+-#define RtdDma0Count(dev,c) \
++#define RtdDma0Count(dev, c) \
+     writel ((c), devpriv->lcfg+LCFG_DMASIZ0)
+ 
+ /* Set next descriptor for DMA 0 */
+-#define RtdDma0Next(dev,a) \
++#define RtdDma0Next(dev, a) \
+     writel ((a), devpriv->lcfg+LCFG_DMADPR0)
+ 
+ /* Set  mode for DMA 1 */
+-#define RtdDma1Mode(dev,m) \
++#define RtdDma1Mode(dev, m) \
+     writel ((m), devpriv->lcfg+LCFG_DMAMODE1)
+ 
+ /* Set PCI address for DMA 1 */
+-#define RtdDma1PciAddr(dev,a) \
++#define RtdDma1PciAddr(dev, a) \
+     writel ((a), devpriv->lcfg+LCFG_DMAADR1)
+ 
+ /* Set local address for DMA 1 */
+-#define RtdDma1LocalAddr(dev,a) \
++#define RtdDma1LocalAddr(dev, a) \
+     writel ((a), devpriv->lcfg+LCFG_DMALADR1)
+ 
+ /* Set byte count for DMA 1 */
+-#define RtdDma1Count(dev,c) \
++#define RtdDma1Count(dev, c) \
+     writel ((c), devpriv->lcfg+LCFG_DMASIZ1)
+ 
+ /* Set next descriptor for DMA 1 */
+-#define RtdDma1Next(dev,a) \
++#define RtdDma1Next(dev, a) \
+     writel ((a), devpriv->lcfg+LCFG_DMADPR1)
+ 
+ /* Set control for DMA 0 (write only, shadow?) */
+-#define RtdDma0Control(dev,n) \
++#define RtdDma0Control(dev, n) \
+     writeb (devpriv->dma0Control = (n), devpriv->lcfg+LCFG_DMACSR0)
+ 
+ /* Get status for DMA 0 */
+@@ -667,7 +667,7 @@ typedef struct {
+     readb (devpriv->lcfg+LCFG_DMACSR0)
+ 
+ /* Set control for DMA 1 (write only, shadow?) */
+-#define RtdDma1Control(dev,n) \
++#define RtdDma1Control(dev, n) \
+     writeb (devpriv->dma1Control = (n), devpriv->lcfg+LCFG_DMACSR1)
+ 
+ /* Get status for DMA 1 */
+diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
+index 41f3736efa3b..0c1f5297fe2f 100644
+--- a/drivers/staging/comedi/drivers/s626.c
++++ b/drivers/staging/comedi/drivers/s626.c
+@@ -454,7 +454,7 @@ static enc_private enc_private_data[] = {
+ 
+ /*  enab/disable a function or test status bit(s) that are accessed */
+ /*  through Main Control Registers 1 or 2. */
+-#define MC_ENABLE( REGADRS, CTRLWORD )	writel(  ( (uint32_t)( CTRLWORD ) << 16 ) | (uint32_t)( CTRLWORD ),devpriv->base_addr+( REGADRS ) )
++#define MC_ENABLE( REGADRS, CTRLWORD )	writel(  ( (uint32_t)( CTRLWORD ) << 16 ) | (uint32_t)( CTRLWORD ), devpriv->base_addr+( REGADRS ) )
+ 
+ #define MC_DISABLE( REGADRS, CTRLWORD )	writel(  (uint32_t)( CTRLWORD ) << 16 , devpriv->base_addr+( REGADRS ) )
+ 
+@@ -462,7 +462,7 @@ static enc_private enc_private_data[] = {
+ 
+ /* #define WR7146(REGARDS,CTRLWORD)
+     writel(CTRLWORD,(uint32_t)(devpriv->base_addr+(REGARDS))) */
+-#define WR7146(REGARDS,CTRLWORD) writel(CTRLWORD,devpriv->base_addr+(REGARDS))
++#define WR7146(REGARDS, CTRLWORD) writel(CTRLWORD, devpriv->base_addr+(REGARDS))
+ 
+ /* #define RR7146(REGARDS)
+     readl((uint32_t)(devpriv->base_addr+(REGARDS))) */
+@@ -475,9 +475,9 @@ static enc_private enc_private_data[] = {
+ #define SETVECT( VECTNUM, VECTVAL )	WR7146(VECTPORT( VECTNUM ), (VECTVAL))
+ 
+ /*  Code macros used for constructing I2C command bytes. */
+-#define I2C_B2(ATTR,VAL)	( ( (ATTR) << 6 ) | ( (VAL) << 24 ) )
+-#define I2C_B1(ATTR,VAL)	( ( (ATTR) << 4 ) | ( (VAL) << 16 ) )
+-#define I2C_B0(ATTR,VAL)	( ( (ATTR) << 2 ) | ( (VAL) <<  8 ) )
++#define I2C_B2(ATTR, VAL)	( ( (ATTR) << 6 ) | ( (VAL) << 24 ) )
++#define I2C_B1(ATTR, VAL)	( ( (ATTR) << 4 ) | ( (VAL) << 16 ) )
++#define I2C_B0(ATTR, VAL)	( ( (ATTR) << 2 ) | ( (VAL) <<  8 ) )
+ 
+ static const comedi_lrange s626_range_table = { 2, {
+ 			RANGE(-5, 5),
+diff --git a/drivers/staging/comedi/drivers/s626.h b/drivers/staging/comedi/drivers/s626.h
+index 7a88bb35b50b..c158110aa47c 100644
+--- a/drivers/staging/comedi/drivers/s626.h
++++ b/drivers/staging/comedi/drivers/s626.h
+@@ -470,9 +470,9 @@
+ #define I2CW			( devpriv->I2CAdrs )
+ 
+ /*  Code macros used for constructing I2C command bytes. */
+-#define I2C_B2(ATTR,VAL)	( ( (ATTR) << 6 ) | ( (VAL) << 24 ) )
+-#define I2C_B1(ATTR,VAL)	( ( (ATTR) << 4 ) | ( (VAL) << 16 ) )
+-#define I2C_B0(ATTR,VAL)	( ( (ATTR) << 2 ) | ( (VAL) <<  8 ) )
++#define I2C_B2(ATTR, VAL)	( ( (ATTR) << 6 ) | ( (VAL) << 24 ) )
++#define I2C_B1(ATTR, VAL)	( ( (ATTR) << 4 ) | ( (VAL) << 16 ) )
++#define I2C_B0(ATTR, VAL)	( ( (ATTR) << 2 ) | ( (VAL) <<  8 ) )
+ 
+ /* oldest */
+ #define P_DEBICFGq              0x007C	/*  DEBI configuration. */

commit e473e9120b0a2d7252aca1ed9db5adadee36c0fa
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:03:29 2009 -0400
+
+    Staging: comedi: Change "foo * bar" to "foo *bar"
+    
+    Removes checkpatch.pl errors
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
+index 48e54042f8b3..a252081b6a08 100644
+--- a/drivers/staging/comedi/drivers.c
++++ b/drivers/staging/comedi/drivers.c
+@@ -47,13 +47,13 @@
+ #include 
+ #include 
+ 
+-static int postconfig(comedi_device * dev);
+-static int insn_rw_emulate_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++static int postconfig(comedi_device *dev);
++static int insn_rw_emulate_bits(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data);
+ static void *comedi_recognize(comedi_driver * driv, const char *name);
+-static void comedi_report_boards(comedi_driver * driv);
+-static int poll_invalid(comedi_device * dev, comedi_subdevice * s);
+-int comedi_buf_alloc(comedi_device * dev, comedi_subdevice * s,
++static void comedi_report_boards(comedi_driver *driv);
++static int poll_invalid(comedi_device *dev, comedi_subdevice *s);
++int comedi_buf_alloc(comedi_device *dev, comedi_subdevice *s,
+ 	unsigned long new_size);
+ 
+ comedi_driver *comedi_drivers;
+@@ -63,7 +63,7 @@ int comedi_modprobe(int minor)
+ 	return -EINVAL;
+ }
+ 
+-static void cleanup_device(comedi_device * dev)
++static void cleanup_device(comedi_device *dev)
+ {
+ 	int i;
+ 	comedi_subdevice *s;
+@@ -97,7 +97,7 @@ static void cleanup_device(comedi_device * dev)
+ 	comedi_set_hw_dev(dev, NULL);
+ }
+ 
+-static void __comedi_device_detach(comedi_device * dev)
++static void __comedi_device_detach(comedi_device *dev)
+ {
+ 	dev->attached = 0;
+ 	if (dev->driver) {
+@@ -108,14 +108,14 @@ static void __comedi_device_detach(comedi_device * dev)
+ 	cleanup_device(dev);
+ }
+ 
+-void comedi_device_detach(comedi_device * dev)
++void comedi_device_detach(comedi_device *dev)
+ {
+ 	if (!dev->attached)
+ 		return;
+ 	__comedi_device_detach(dev);
+ }
+ 
+-int comedi_device_attach(comedi_device * dev, comedi_devconfig * it)
++int comedi_device_attach(comedi_device *dev, comedi_devconfig *it)
+ {
+ 	comedi_driver *driv;
+ 	int ret;
+@@ -182,7 +182,7 @@ int comedi_device_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-int comedi_driver_register(comedi_driver * driver)
++int comedi_driver_register(comedi_driver *driver)
+ {
+ 	driver->next = comedi_drivers;
+ 	comedi_drivers = driver;
+@@ -190,7 +190,7 @@ int comedi_driver_register(comedi_driver * driver)
+ 	return 0;
+ }
+ 
+-int comedi_driver_unregister(comedi_driver * driver)
++int comedi_driver_unregister(comedi_driver *driver)
+ {
+ 	comedi_driver *prev;
+ 	int i;
+@@ -226,7 +226,7 @@ int comedi_driver_unregister(comedi_driver * driver)
+ 	return -EINVAL;
+ }
+ 
+-static int postconfig(comedi_device * dev)
++static int postconfig(comedi_device *dev)
+ {
+ 	int i;
+ 	comedi_subdevice *s;
+@@ -315,7 +315,7 @@ void *comedi_recognize(comedi_driver * driv, const char *name)
+ 	return NULL;
+ }
+ 
+-void comedi_report_boards(comedi_driver * driv)
++void comedi_report_boards(comedi_driver *driv)
+ {
+ 	unsigned int i;
+ 	const char *const *name_ptr;
+@@ -333,19 +333,19 @@ void comedi_report_boards(comedi_driver * driv)
+ 		printk(" %s\n", driv->driver_name);
+ }
+ 
+-static int poll_invalid(comedi_device * dev, comedi_subdevice * s)
++static int poll_invalid(comedi_device *dev, comedi_subdevice *s)
+ {
+ 	return -EINVAL;
+ }
+ 
+-int insn_inval(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++int insn_inval(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data)
+ {
+ 	return -EINVAL;
+ }
+ 
+-static int insn_rw_emulate_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++static int insn_rw_emulate_bits(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data)
+ {
+ 	comedi_insn new_insn;
+ 	int ret;
+@@ -381,7 +381,7 @@ static int insn_rw_emulate_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static inline unsigned long uvirt_to_kva(pgd_t * pgd, unsigned long adr)
++static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
+ {
+ 	unsigned long ret = 0UL;
+ 	pmd_t *pmd;
+@@ -414,7 +414,7 @@ static inline unsigned long kvirt_to_kva(unsigned long adr)
+ 	return kva;
+ }
+ 
+-int comedi_buf_alloc(comedi_device * dev, comedi_subdevice * s,
++int comedi_buf_alloc(comedi_device *dev, comedi_subdevice *s,
+ 	unsigned long new_size)
+ {
+ 	comedi_async *async = s->async;
+@@ -538,7 +538,7 @@ int comedi_buf_alloc(comedi_device * dev, comedi_subdevice * s,
+ 
+ /* munging is applied to data by core as it passes between user
+  * and kernel space */
+-unsigned int comedi_buf_munge(comedi_async * async, unsigned int num_bytes)
++unsigned int comedi_buf_munge(comedi_async *async, unsigned int num_bytes)
+ {
+ 	comedi_subdevice *s = async->subdevice;
+ 	unsigned int count = 0;
+@@ -582,7 +582,7 @@ unsigned int comedi_buf_munge(comedi_async * async, unsigned int num_bytes)
+ 	return count;
+ }
+ 
+-unsigned int comedi_buf_write_n_available(comedi_async * async)
++unsigned int comedi_buf_write_n_available(comedi_async *async)
+ {
+ 	unsigned int free_end;
+ 	unsigned int nbytes;
+@@ -602,7 +602,7 @@ unsigned int comedi_buf_write_n_available(comedi_async * async)
+ }
+ 
+ /* allocates chunk for the writer from free buffer space */
+-unsigned int comedi_buf_write_alloc(comedi_async * async, unsigned int nbytes)
++unsigned int comedi_buf_write_alloc(comedi_async *async, unsigned int nbytes)
+ {
+ 	unsigned int free_end = async->buf_read_count + async->prealloc_bufsz;
+ 
+@@ -617,7 +617,7 @@ unsigned int comedi_buf_write_alloc(comedi_async * async, unsigned int nbytes)
+ }
+ 
+ /* allocates nothing unless it can completely fulfill the request */
+-unsigned int comedi_buf_write_alloc_strict(comedi_async * async,
++unsigned int comedi_buf_write_alloc_strict(comedi_async *async,
+ 	unsigned int nbytes)
+ {
+ 	unsigned int free_end = async->buf_read_count + async->prealloc_bufsz;
+@@ -633,7 +633,7 @@ unsigned int comedi_buf_write_alloc_strict(comedi_async * async,
+ }
+ 
+ /* transfers a chunk from writer to filled buffer space */
+-unsigned comedi_buf_write_free(comedi_async * async, unsigned int nbytes)
++unsigned comedi_buf_write_free(comedi_async *async, unsigned int nbytes)
+ {
+ 	if ((int)(async->buf_write_count + nbytes -
+ 			async->buf_write_alloc_count) > 0) {
+@@ -651,7 +651,7 @@ unsigned comedi_buf_write_free(comedi_async * async, unsigned int nbytes)
+ }
+ 
+ /* allocates a chunk for the reader from filled (and munged) buffer space */
+-unsigned comedi_buf_read_alloc(comedi_async * async, unsigned nbytes)
++unsigned comedi_buf_read_alloc(comedi_async *async, unsigned nbytes)
+ {
+ 	if ((int)(async->buf_read_alloc_count + nbytes - async->munge_count) >
+ 		0) {
+@@ -665,7 +665,7 @@ unsigned comedi_buf_read_alloc(comedi_async * async, unsigned nbytes)
+ }
+ 
+ /* transfers control of a chunk from reader to free buffer space */
+-unsigned comedi_buf_read_free(comedi_async * async, unsigned int nbytes)
++unsigned comedi_buf_read_free(comedi_async *async, unsigned int nbytes)
+ {
+ 	/*  barrier insures data has been read out of buffer before read count is incremented */
+ 	smp_mb();
+@@ -681,7 +681,7 @@ unsigned comedi_buf_read_free(comedi_async * async, unsigned int nbytes)
+ 	return nbytes;
+ }
+ 
+-void comedi_buf_memcpy_to(comedi_async * async, unsigned int offset,
++void comedi_buf_memcpy_to(comedi_async *async, unsigned int offset,
+ 	const void *data, unsigned int num_bytes)
+ {
+ 	unsigned int write_ptr = async->buf_write_ptr + offset;
+@@ -706,7 +706,7 @@ void comedi_buf_memcpy_to(comedi_async * async, unsigned int offset,
+ 	}
+ }
+ 
+-void comedi_buf_memcpy_from(comedi_async * async, unsigned int offset,
++void comedi_buf_memcpy_from(comedi_async *async, unsigned int offset,
+ 	void *dest, unsigned int nbytes)
+ {
+ 	void *src;
+@@ -732,7 +732,7 @@ void comedi_buf_memcpy_from(comedi_async * async, unsigned int offset,
+ 	}
+ }
+ 
+-unsigned int comedi_buf_read_n_available(comedi_async * async)
++unsigned int comedi_buf_read_n_available(comedi_async *async)
+ {
+ 	unsigned num_bytes;
+ 
+@@ -747,7 +747,7 @@ unsigned int comedi_buf_read_n_available(comedi_async * async)
+ 	return num_bytes;
+ }
+ 
+-int comedi_buf_get(comedi_async * async, sampl_t * x)
++int comedi_buf_get(comedi_async *async, sampl_t *x)
+ {
+ 	unsigned int n = comedi_buf_read_n_available(async);
+ 
+@@ -759,7 +759,7 @@ int comedi_buf_get(comedi_async * async, sampl_t * x)
+ 	return 1;
+ }
+ 
+-int comedi_buf_put(comedi_async * async, sampl_t x)
++int comedi_buf_put(comedi_async *async, sampl_t x)
+ {
+ 	unsigned int n = comedi_buf_write_alloc_strict(async, sizeof(sampl_t));
+ 
+@@ -772,7 +772,7 @@ int comedi_buf_put(comedi_async * async, sampl_t x)
+ 	return 1;
+ }
+ 
+-void comedi_reset_async_buf(comedi_async * async)
++void comedi_reset_async_buf(comedi_async *async)
+ {
+ 	async->buf_write_alloc_count = 0;
+ 	async->buf_write_count = 0;
+diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
+index 143a5f95b31f..ef8f783ba4e4 100644
+--- a/drivers/staging/comedi/drivers/icp_multi.c
++++ b/drivers/staging/comedi/drivers/icp_multi.c
+@@ -123,8 +123,8 @@ static const char range_codes_analog[] = { 0x00, 0x20, 0x10, 0x30 };
+ 	Forward declarations
+ ==============================================================================
+ */
+-static int icp_multi_attach(comedi_device * dev, comedi_devconfig * it);
+-static int icp_multi_detach(comedi_device * dev);
++static int icp_multi_attach(comedi_device *dev, comedi_devconfig *it);
++static int icp_multi_detach(comedi_device *dev);
+ 
+ /*
+ ==============================================================================
+@@ -214,12 +214,12 @@ typedef struct {
+ */
+ 
+ #if 0
+-static int check_channel_list(comedi_device * dev, comedi_subdevice * s,
++static int check_channel_list(comedi_device *dev, comedi_subdevice *s,
+ 	unsigned int *chanlist, unsigned int n_chan);
+ #endif
+-static void setup_channel_list(comedi_device * dev, comedi_subdevice * s,
++static void setup_channel_list(comedi_device *dev, comedi_subdevice *s,
+ 	unsigned int *chanlist, unsigned int n_chan);
+-static int icp_multi_reset(comedi_device * dev);
++static int icp_multi_reset(comedi_device *dev);
+ 
+ /*
+ ==============================================================================
+@@ -245,8 +245,8 @@ static int icp_multi_reset(comedi_device * dev);
+ 
+ ==============================================================================
+ */
+-static int icp_multi_insn_read_ai(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++static int icp_multi_insn_read_ai(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data)
+ {
+ 	int n, timeout;
+ 
+@@ -364,8 +364,8 @@ static int icp_multi_insn_read_ai(comedi_device * dev, comedi_subdevice * s,
+ 
+ ==============================================================================
+ */
+-static int icp_multi_insn_write_ao(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++static int icp_multi_insn_write_ao(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data)
+ {
+ 	int n, chan, range, timeout;
+ 
+@@ -472,8 +472,8 @@ static int icp_multi_insn_write_ao(comedi_device * dev, comedi_subdevice * s,
+ 
+ ==============================================================================
+ */
+-static int icp_multi_insn_read_ao(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++static int icp_multi_insn_read_ao(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data)
+ {
+ 	int n, chan;
+ 
+@@ -505,8 +505,8 @@ static int icp_multi_insn_read_ao(comedi_device * dev, comedi_subdevice * s,
+ 
+ ==============================================================================
+ */
+-static int icp_multi_insn_bits_di(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++static int icp_multi_insn_bits_di(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data)
+ {
+ 	data[1] = readw(devpriv->io_addr + ICP_MULTI_DI);
+ 
+@@ -531,8 +531,8 @@ static int icp_multi_insn_bits_di(comedi_device * dev, comedi_subdevice * s,
+ 
+ ==============================================================================
+ */
+-static int icp_multi_insn_bits_do(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++static int icp_multi_insn_bits_do(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data)
+ {
+ #ifdef ICP_MULTI_EXTDEBUG
+ 	printk("icp multi EDBG: BGN: icp_multi_insn_bits_do(...)\n");
+@@ -573,8 +573,8 @@ static int icp_multi_insn_bits_do(comedi_device * dev, comedi_subdevice * s,
+ 
+ ==============================================================================
+ */
+-static int icp_multi_insn_read_ctr(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++static int icp_multi_insn_read_ctr(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data)
+ {
+ 	return 0;
+ }
+@@ -597,8 +597,8 @@ static int icp_multi_insn_read_ctr(comedi_device * dev, comedi_subdevice * s,
+ 
+ ==============================================================================
+ */
+-static int icp_multi_insn_write_ctr(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++static int icp_multi_insn_write_ctr(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data)
+ {
+ 	return 0;
+ }
+@@ -689,7 +689,7 @@ static irqreturn_t interrupt_service_icp_multi(int irq, void *d PT_REGS_ARG)
+ 
+ ==============================================================================
+ */
+-static int check_channel_list(comedi_device * dev, comedi_subdevice * s,
++static int check_channel_list(comedi_device *dev, comedi_subdevice *s,
+ 	unsigned int *chanlist, unsigned int n_chan)
+ {
+ 	unsigned int i;
+@@ -743,7 +743,7 @@ static int check_channel_list(comedi_device * dev, comedi_subdevice * s,
+ 
+ ==============================================================================
+ */
+-static void setup_channel_list(comedi_device * dev, comedi_subdevice * s,
++static void setup_channel_list(comedi_device *dev, comedi_subdevice *s,
+ 	unsigned int *chanlist, unsigned int n_chan)
+ {
+ 	unsigned int i, range, chanprog;
+@@ -812,7 +812,7 @@ static void setup_channel_list(comedi_device * dev, comedi_subdevice * s,
+ 
+ ==============================================================================
+ */
+-static int icp_multi_reset(comedi_device * dev)
++static int icp_multi_reset(comedi_device *dev)
+ {
+ 	unsigned int i;
+ 
+@@ -870,7 +870,7 @@ static int icp_multi_reset(comedi_device * dev)
+ 
+ ==============================================================================
+ */
+-static int icp_multi_attach(comedi_device * dev, comedi_devconfig * it)
++static int icp_multi_attach(comedi_device *dev, comedi_devconfig *it)
+ {
+ 	comedi_subdevice *s;
+ 	int ret, subdev, n_subdevices;
+@@ -1061,7 +1061,7 @@ static int icp_multi_attach(comedi_device * dev, comedi_devconfig * it)
+ 
+ ==============================================================================
+ */
+-static int icp_multi_detach(comedi_device * dev)
++static int icp_multi_detach(comedi_device *dev)
+ {
+ 
+ 	if (dev->private)
+diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
+index 2608c8713c90..3aafedecf7ed 100644
+--- a/drivers/staging/comedi/drivers/me4000.c
++++ b/drivers/staging/comedi/drivers/me4000.c
+@@ -118,8 +118,8 @@ static const me4000_board_t me4000_boards[] = {
+ /*-----------------------------------------------------------------------------
+   Comedi function prototypes
+   ---------------------------------------------------------------------------*/
+-static int me4000_attach(comedi_device * dev, comedi_devconfig * it);
+-static int me4000_detach(comedi_device * dev);
++static int me4000_attach(comedi_device *dev, comedi_devconfig *it);
++static int me4000_detach(comedi_device *dev);
+ static comedi_driver driver_me4000 = {
+       driver_name:"me4000",
+       module:THIS_MODULE,
+@@ -130,91 +130,91 @@ static comedi_driver driver_me4000 = {
+ /*-----------------------------------------------------------------------------
+   Meilhaus function prototypes
+   ---------------------------------------------------------------------------*/
+-static int me4000_probe(comedi_device * dev, comedi_devconfig * it);
+-static int get_registers(comedi_device * dev, struct pci_dev *pci_dev_p);
+-static int init_board_info(comedi_device * dev, struct pci_dev *pci_dev_p);
+-static int init_ao_context(comedi_device * dev);
+-static int init_ai_context(comedi_device * dev);
+-static int init_dio_context(comedi_device * dev);
+-static int init_cnt_context(comedi_device * dev);
+-static int xilinx_download(comedi_device * dev);
+-static int reset_board(comedi_device * dev);
++static int me4000_probe(comedi_device *dev, comedi_devconfig *it);
++static int get_registers(comedi_device *dev, struct pci_dev *pci_dev_p);
++static int init_board_info(comedi_device *dev, struct pci_dev *pci_dev_p);
++static int init_ao_context(comedi_device *dev);
++static int init_ai_context(comedi_device *dev);
++static int init_dio_context(comedi_device *dev);
++static int init_cnt_context(comedi_device *dev);
++static int xilinx_download(comedi_device *dev);
++static int reset_board(comedi_device *dev);
+ 
+-static int me4000_dio_insn_bits(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
++static int me4000_dio_insn_bits(comedi_device *dev,
++	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);
+ 
+-static int me4000_dio_insn_config(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
++static int me4000_dio_insn_config(comedi_device *dev,
++	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);
+ 
+-static int cnt_reset(comedi_device * dev, unsigned int channel);
++static int cnt_reset(comedi_device *dev, unsigned int channel);
+ 
+-static int cnt_config(comedi_device * dev,
++static int cnt_config(comedi_device *dev,
+ 	unsigned int channel, unsigned int mode);
+ 
+-static int me4000_cnt_insn_config(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
++static int me4000_cnt_insn_config(comedi_device *dev,
++	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);
+ 
+-static int me4000_cnt_insn_write(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
++static int me4000_cnt_insn_write(comedi_device *dev,
++	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);
+ 
+-static int me4000_cnt_insn_read(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
++static int me4000_cnt_insn_read(comedi_device *dev,
++	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);
+ 
+-static int me4000_ai_insn_read(comedi_device * dev,
+-	comedi_subdevice * subdevice, comedi_insn * insn, lsampl_t * data);
++static int me4000_ai_insn_read(comedi_device *dev,
++	comedi_subdevice *subdevice, comedi_insn *insn, lsampl_t *data);
+ 
+-static int me4000_ai_cancel(comedi_device * dev, comedi_subdevice * s);
++static int me4000_ai_cancel(comedi_device *dev, comedi_subdevice *s);
+ 
+-static int ai_check_chanlist(comedi_device * dev,
+-	comedi_subdevice * s, comedi_cmd * cmd);
++static int ai_check_chanlist(comedi_device *dev,
++	comedi_subdevice *s, comedi_cmd *cmd);
+ 
+-static int ai_round_cmd_args(comedi_device * dev,
+-	comedi_subdevice * s,
+-	comedi_cmd * cmd,
++static int ai_round_cmd_args(comedi_device *dev,
++	comedi_subdevice *s,
++	comedi_cmd *cmd,
+ 	unsigned int *init_ticks,
+ 	unsigned int *scan_ticks, unsigned int *chan_ticks);
+ 
+-static int ai_prepare(comedi_device * dev,
+-	comedi_subdevice * s,
+-	comedi_cmd * cmd,
++static int ai_prepare(comedi_device *dev,
++	comedi_subdevice *s,
++	comedi_cmd *cmd,
+ 	unsigned int init_ticks,
+ 	unsigned int scan_ticks, unsigned int chan_ticks);
+ 
+-static int ai_write_chanlist(comedi_device * dev,
+-	comedi_subdevice * s, comedi_cmd * cmd);
++static int ai_write_chanlist(comedi_device *dev,
++	comedi_subdevice *s, comedi_cmd *cmd);
+ 
+ static irqreturn_t me4000_ai_isr(int irq, void *dev_id PT_REGS_ARG);
+ 
+-static int me4000_ai_do_cmd_test(comedi_device * dev,
+-	comedi_subdevice * s, comedi_cmd * cmd);
++static int me4000_ai_do_cmd_test(comedi_device *dev,
++	comedi_subdevice *s, comedi_cmd *cmd);
+ 
+-static int me4000_ai_do_cmd(comedi_device * dev, comedi_subdevice * s);
++static int me4000_ai_do_cmd(comedi_device *dev, comedi_subdevice *s);
+ 
+-static int me4000_ao_insn_write(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
++static int me4000_ao_insn_write(comedi_device *dev,
++	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);
+ 
+-static int me4000_ao_insn_read(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
++static int me4000_ao_insn_read(comedi_device *dev,
++	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);
+ 
+ /*-----------------------------------------------------------------------------
+   Meilhaus inline functions
+   ---------------------------------------------------------------------------*/
+ 
+-static inline void me4000_outb(comedi_device * dev, unsigned char value,
++static inline void me4000_outb(comedi_device *dev, unsigned char value,
+ 	unsigned long port)
+ {
+ 	PORT_PDEBUG("--> 0x%02X port 0x%04lX\n", value, port);
+ 	outb(value, port);
+ }
+ 
+-static inline void me4000_outl(comedi_device * dev, unsigned long value,
++static inline void me4000_outl(comedi_device *dev, unsigned long value,
+ 	unsigned long port)
+ {
+ 	PORT_PDEBUG("--> 0x%08lX port 0x%04lX\n", value, port);
+ 	outl(value, port);
+ }
+ 
+-static inline unsigned long me4000_inl(comedi_device * dev, unsigned long port)
++static inline unsigned long me4000_inl(comedi_device *dev, unsigned long port)
+ {
+ 	unsigned long value;
+ 	value = inl(port);
+@@ -222,7 +222,7 @@ static inline unsigned long me4000_inl(comedi_device * dev, unsigned long port)
+ 	return value;
+ }
+ 
+-static inline unsigned char me4000_inb(comedi_device * dev, unsigned long port)
++static inline unsigned char me4000_inb(comedi_device *dev, unsigned long port)
+ {
+ 	unsigned char value;
+ 	value = inb(port);
+@@ -247,7 +247,7 @@ static const comedi_lrange me4000_ao_range = {
+ 		}
+ };
+ 
+-static int me4000_attach(comedi_device * dev, comedi_devconfig * it)
++static int me4000_attach(comedi_device *dev, comedi_devconfig *it)
+ {
+ 	comedi_subdevice *s;
+ 	int result;
+@@ -369,7 +369,7 @@ static int me4000_attach(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int me4000_probe(comedi_device * dev, comedi_devconfig * it)
++static int me4000_probe(comedi_device *dev, comedi_devconfig *it)
+ {
+ 	struct pci_dev *pci_device;
+ 	int result, i;
+@@ -512,7 +512,7 @@ static int me4000_probe(comedi_device * dev, comedi_devconfig * it)
+ 	return 0;
+ }
+ 
+-static int get_registers(comedi_device * dev, struct pci_dev *pci_dev_p)
++static int get_registers(comedi_device *dev, struct pci_dev *pci_dev_p)
+ {
+ 
+ 	CALL_PDEBUG("In get_registers()\n");
+@@ -564,7 +564,7 @@ static int get_registers(comedi_device * dev, struct pci_dev *pci_dev_p)
+ 	return 0;
+ }
+ 
+-static int init_board_info(comedi_device * dev, struct pci_dev *pci_dev_p)
++static int init_board_info(comedi_device *dev, struct pci_dev *pci_dev_p)
+ {
+ 	int result;
+ 
+@@ -598,7 +598,7 @@ static int init_board_info(comedi_device * dev, struct pci_dev *pci_dev_p)
+ 	return 0;
+ }
+ 
+-static int init_ao_context(comedi_device * dev)
++static int init_ao_context(comedi_device *dev)
+ {
+ 	int i;
+ 
+@@ -681,7 +681,7 @@ static int init_ao_context(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int init_ai_context(comedi_device * dev)
++static int init_ai_context(comedi_device *dev)
+ {
+ 
+ 	CALL_PDEBUG("In init_ai_context()\n");
+@@ -715,7 +715,7 @@ static int init_ai_context(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int init_dio_context(comedi_device * dev)
++static int init_dio_context(comedi_device *dev)
+ {
+ 
+ 	CALL_PDEBUG("In init_dio_context()\n");
+@@ -734,7 +734,7 @@ static int init_dio_context(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int init_cnt_context(comedi_device * dev)
++static int init_cnt_context(comedi_device *dev)
+ {
+ 
+ 	CALL_PDEBUG("In init_cnt_context()\n");
+@@ -755,7 +755,7 @@ static int init_cnt_context(comedi_device * dev)
+ extern unsigned char *xilinx_firm;
+ #endif
+ 
+-static int xilinx_download(comedi_device * dev)
++static int xilinx_download(comedi_device *dev)
+ {
+ 	u32 value = 0;
+ 	wait_queue_head_t queue;
+@@ -837,7 +837,7 @@ static int xilinx_download(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int reset_board(comedi_device * dev)
++static int reset_board(comedi_device *dev)
+ {
+ 	unsigned long icr;
+ 
+@@ -895,7 +895,7 @@ static int reset_board(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-static int me4000_detach(comedi_device * dev)
++static int me4000_detach(comedi_device *dev)
+ {
+ 	CALL_PDEBUG("In me4000_detach()\n");
+ 
+@@ -916,8 +916,8 @@ static int me4000_detach(comedi_device * dev)
+   Analog input section
+   ===========================================================================*/
+ 
+-static int me4000_ai_insn_read(comedi_device * dev,
+-	comedi_subdevice * subdevice, comedi_insn * insn, lsampl_t * data)
++static int me4000_ai_insn_read(comedi_device *dev,
++	comedi_subdevice *subdevice, comedi_insn *insn, lsampl_t *data)
+ {
+ 
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -1040,7 +1040,7 @@ static int me4000_ai_insn_read(comedi_device * dev,
+ 	return 1;
+ }
+ 
+-static int me4000_ai_cancel(comedi_device * dev, comedi_subdevice * s)
++static int me4000_ai_cancel(comedi_device *dev, comedi_subdevice *s)
+ {
+ 	unsigned long tmp;
+ 
+@@ -1057,8 +1057,8 @@ static int me4000_ai_cancel(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int ai_check_chanlist(comedi_device * dev,
+-	comedi_subdevice * s, comedi_cmd * cmd)
++static int ai_check_chanlist(comedi_device *dev,
++	comedi_subdevice *s, comedi_cmd *cmd)
+ {
+ 	int aref;
+ 	int i;
+@@ -1138,9 +1138,9 @@ static int ai_check_chanlist(comedi_device * dev,
+ 	return 0;
+ }
+ 
+-static int ai_round_cmd_args(comedi_device * dev,
+-	comedi_subdevice * s,
+-	comedi_cmd * cmd,
++static int ai_round_cmd_args(comedi_device *dev,
++	comedi_subdevice *s,
++	comedi_cmd *cmd,
+ 	unsigned int *init_ticks,
+ 	unsigned int *scan_ticks, unsigned int *chan_ticks)
+ {
+@@ -1207,7 +1207,7 @@ static int ai_round_cmd_args(comedi_device * dev,
+ 	return 0;
+ }
+ 
+-static void ai_write_timer(comedi_device * dev,
++static void ai_write_timer(comedi_device *dev,
+ 	unsigned int init_ticks,
+ 	unsigned int scan_ticks, unsigned int chan_ticks)
+ {
+@@ -1228,9 +1228,9 @@ static void ai_write_timer(comedi_device * dev,
+ 	me4000_outl(dev, chan_ticks - 1, info->ai_context.chan_timer_reg);
+ }
+ 
+-static int ai_prepare(comedi_device * dev,
+-	comedi_subdevice * s,
+-	comedi_cmd * cmd,
++static int ai_prepare(comedi_device *dev,
++	comedi_subdevice *s,
++	comedi_cmd *cmd,
+ 	unsigned int init_ticks,
+ 	unsigned int scan_ticks, unsigned int chan_ticks)
+ {
+@@ -1297,8 +1297,8 @@ static int ai_prepare(comedi_device * dev,
+ 	return 0;
+ }
+ 
+-static int ai_write_chanlist(comedi_device * dev,
+-	comedi_subdevice * s, comedi_cmd * cmd)
++static int ai_write_chanlist(comedi_device *dev,
++	comedi_subdevice *s, comedi_cmd *cmd)
+ {
+ 	unsigned int entry;
+ 	unsigned int chan;
+@@ -1337,7 +1337,7 @@ static int ai_write_chanlist(comedi_device * dev,
+ 	return 0;
+ }
+ 
+-static int me4000_ai_do_cmd(comedi_device * dev, comedi_subdevice * s)
++static int me4000_ai_do_cmd(comedi_device *dev, comedi_subdevice *s)
+ {
+ 	int err;
+ 	unsigned int init_ticks = 0;
+@@ -1381,8 +1381,8 @@ static int me4000_ai_do_cmd(comedi_device * dev, comedi_subdevice * s)
+  * - invalid chanlist
+  * So I tried to adopt this scheme.
+  */
+-static int me4000_ai_do_cmd_test(comedi_device * dev,
+-	comedi_subdevice * s, comedi_cmd * cmd)
++static int me4000_ai_do_cmd_test(comedi_device *dev,
++	comedi_subdevice *s, comedi_cmd *cmd)
+ {
+ 
+ 	unsigned int init_ticks;
+@@ -1911,8 +1911,8 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id PT_REGS_ARG)
+   Analog output section
+   ===========================================================================*/
+ 
+-static int me4000_ao_insn_write(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++static int me4000_ao_insn_write(comedi_device *dev,
++	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
+ {
+ 
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -1969,8 +1969,8 @@ static int me4000_ao_insn_write(comedi_device * dev,
+ 	return 1;
+ }
+ 
+-static int me4000_ao_insn_read(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++static int me4000_ao_insn_read(comedi_device *dev,
++	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+@@ -1990,8 +1990,8 @@ static int me4000_ao_insn_read(comedi_device * dev,
+   Digital I/O section
+   ===========================================================================*/
+ 
+-static int me4000_dio_insn_bits(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++static int me4000_dio_insn_bits(comedi_device *dev,
++	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
+ {
+ 
+ 	CALL_PDEBUG("In me4000_dio_insn_bits()\n");
+@@ -2041,8 +2041,8 @@ static int me4000_dio_insn_bits(comedi_device * dev,
+ 	return 2;
+ }
+ 
+-static int me4000_dio_insn_config(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++static int me4000_dio_insn_config(comedi_device *dev,
++	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
+ {
+ 	unsigned long tmp;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -2135,7 +2135,7 @@ static int me4000_dio_insn_config(comedi_device * dev,
+   Counter section
+   ===========================================================================*/
+ 
+-static int cnt_reset(comedi_device * dev, unsigned int channel)
++static int cnt_reset(comedi_device *dev, unsigned int channel)
+ {
+ 
+ 	CALL_PDEBUG("In cnt_reset()\n");
+@@ -2166,7 +2166,7 @@ static int cnt_reset(comedi_device * dev, unsigned int channel)
+ 	return 0;
+ }
+ 
+-static int cnt_config(comedi_device * dev, unsigned int channel,
++static int cnt_config(comedi_device *dev, unsigned int channel,
+ 	unsigned int mode)
+ {
+ 	int tmp = 0;
+@@ -2223,8 +2223,8 @@ static int cnt_config(comedi_device * dev, unsigned int channel,
+ 	return 0;
+ }
+ 
+-static int me4000_cnt_insn_config(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++static int me4000_cnt_insn_config(comedi_device *dev,
++	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
+ {
+ 
+ 	int err;
+@@ -2266,8 +2266,8 @@ static int me4000_cnt_insn_config(comedi_device * dev,
+ 	return 2;
+ }
+ 
+-static int me4000_cnt_insn_read(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++static int me4000_cnt_insn_read(comedi_device *dev,
++	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
+ {
+ 
+ 	unsigned short tmp;
+@@ -2313,8 +2313,8 @@ static int me4000_cnt_insn_read(comedi_device * dev,
+ 	return 1;
+ }
+ 
+-static int me4000_cnt_insn_write(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++static int me4000_cnt_insn_write(comedi_device *dev,
++	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
+ {
+ 
+ 	unsigned short tmp;
+diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c
+index 354ed8ddaffd..c82aeff8ff58 100644
+--- a/drivers/staging/comedi/drivers/mite.c
++++ b/drivers/staging/comedi/drivers/mite.c
+@@ -103,7 +103,7 @@ static void dump_chip_signature(u32 csigr_bits)
+ 	printk("mite: num channels = %i, write post fifo depth = %i, wins = %i, iowins = %i\n", mite_csigr_dmac(csigr_bits), mite_csigr_wpdep(csigr_bits), mite_csigr_wins(csigr_bits), mite_csigr_iowins(csigr_bits));
+ }
+ 
+-unsigned mite_fifo_size(struct mite_struct * mite, unsigned channel)
++unsigned mite_fifo_size(struct mite_struct *mite, unsigned channel)
+ {
+ 	unsigned fcr_bits = readl(mite->mite_io_addr +
+ 		MITE_FCR(channel));
+@@ -459,7 +459,7 @@ u32 mite_device_bytes_transferred(struct mite_channel *mite_chan)
+ 	return readl(mite->mite_io_addr + MITE_DAR(mite_chan->channel));
+ }
+ 
+-u32 mite_bytes_in_transit(struct mite_channel * mite_chan)
++u32 mite_bytes_in_transit(struct mite_channel *mite_chan)
+ {
+ 	struct mite_struct *mite = mite_chan->mite;
+ 	return readl(mite->mite_io_addr +
+@@ -467,7 +467,7 @@ u32 mite_bytes_in_transit(struct mite_channel * mite_chan)
+ }
+ 
+ /*  returns lower bound for number of bytes transferred from device to memory */
+-u32 mite_bytes_written_to_memory_lb(struct mite_channel * mite_chan)
++u32 mite_bytes_written_to_memory_lb(struct mite_channel *mite_chan)
+ {
+ 	u32 device_byte_count;
+ 
+@@ -476,7 +476,7 @@ u32 mite_bytes_written_to_memory_lb(struct mite_channel * mite_chan)
+ }
+ 
+ /*  returns upper bound for number of bytes transferred from device to memory */
+-u32 mite_bytes_written_to_memory_ub(struct mite_channel * mite_chan)
++u32 mite_bytes_written_to_memory_ub(struct mite_channel *mite_chan)
+ {
+ 	u32 in_transit_count;
+ 
+@@ -485,7 +485,7 @@ u32 mite_bytes_written_to_memory_ub(struct mite_channel * mite_chan)
+ }
+ 
+ /*  returns lower bound for number of bytes read from memory for transfer to device */
+-u32 mite_bytes_read_from_memory_lb(struct mite_channel * mite_chan)
++u32 mite_bytes_read_from_memory_lb(struct mite_channel *mite_chan)
+ {
+ 	u32 device_byte_count;
+ 
+@@ -494,7 +494,7 @@ u32 mite_bytes_read_from_memory_lb(struct mite_channel * mite_chan)
+ }
+ 
+ /*  returns upper bound for number of bytes read from memory for transfer to device */
+-u32 mite_bytes_read_from_memory_ub(struct mite_channel * mite_chan)
++u32 mite_bytes_read_from_memory_ub(struct mite_channel *mite_chan)
+ {
+ 	u32 in_transit_count;
+ 
+diff --git a/drivers/staging/comedi/drivers/mite.h b/drivers/staging/comedi/drivers/mite.h
+index 26c04c82293c..2b2df8b4e360 100644
+--- a/drivers/staging/comedi/drivers/mite.h
++++ b/drivers/staging/comedi/drivers/mite.h
+@@ -162,7 +162,7 @@ void mite_setregs(struct mite_struct *mite, unsigned long ll_start, int chan,
+ void mite_prep_dma(struct mite_channel *mite_chan,
+ 	unsigned int num_device_bits, unsigned int num_memory_bits);
+ int mite_buf_change(struct mite_dma_descriptor_ring *ring,
+-	comedi_async * async);
++	comedi_async *async);
+ 
+ #ifdef DEBUG_MITE
+ void mite_print_chsr(unsigned int chsr);
+diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
+index e9379b80d227..4d8c68104530 100644
+--- a/drivers/staging/comedi/drivers/rtd520.c
++++ b/drivers/staging/comedi/drivers/rtd520.c
+@@ -680,8 +680,8 @@ typedef struct {
+  * the board, and also about the kernel module that contains
+  * the device code.
+  */
+-static int rtd_attach(comedi_device * dev, comedi_devconfig * it);
+-static int rtd_detach(comedi_device * dev);
++static int rtd_attach(comedi_device *dev, comedi_devconfig *it);
++static int rtd_detach(comedi_device *dev);
+ 
+ static comedi_driver rtd520Driver = {
+       driver_name: DRV_NAME,
+@@ -690,20 +690,20 @@ static comedi_driver rtd520Driver = {
+       detach:rtd_detach,
+ };
+ 
+-static int rtd_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
+-static int rtd_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
+-static int rtd_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
+-static int rtd_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
+-static int rtd_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
+-static int rtd_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+-	comedi_cmd * cmd);
+-static int rtd_ai_cmd(comedi_device * dev, comedi_subdevice * s);
+-static int rtd_ai_cancel(comedi_device * dev, comedi_subdevice * s);
++static int rtd_ai_rinsn(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data);
++static int rtd_ao_winsn(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data);
++static int rtd_ao_rinsn(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data);
++static int rtd_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data);
++static int rtd_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data);
++static int rtd_ai_cmdtest(comedi_device *dev, comedi_subdevice *s,
++	comedi_cmd *cmd);
++static int rtd_ai_cmd(comedi_device *dev, comedi_subdevice *s);
++static int rtd_ai_cancel(comedi_device *dev, comedi_subdevice *s);
+ /* static int rtd_ai_poll (comedi_device *dev,comedi_subdevice *s); */
+ static int rtd_ns_to_timer(unsigned int *ns, int roundMode);
+ static irqreturn_t rtd_interrupt(int irq, void *d PT_REGS_ARG);
+@@ -715,7 +715,7 @@ static int rtd520_probe_fifo_depth(comedi_device *dev);
+  * in the driver structure, dev->board_ptr contains that
+  * address.
+  */
+-static int rtd_attach(comedi_device * dev, comedi_devconfig * it)
++static int rtd_attach(comedi_device *dev, comedi_devconfig *it)
+ {				/* board name and options flags */
+ 	comedi_subdevice *s;
+ 	struct pci_dev *pcidev;
+@@ -1057,7 +1057,7 @@ static int rtd_attach(comedi_device * dev, comedi_devconfig * it)
+  * allocated by _attach().  dev->private and dev->subdevices are
+  * deallocated automatically by the core.
+  */
+-static int rtd_detach(comedi_device * dev)
++static int rtd_detach(comedi_device *dev)
+ {
+ #ifdef USE_DMA
+ 	int index;
+@@ -1137,7 +1137,7 @@ static int rtd_detach(comedi_device * dev)
+ /*
+   Convert a single comedi channel-gain entry to a RTD520 table entry
+ */
+-static unsigned short rtdConvertChanGain(comedi_device * dev,
++static unsigned short rtdConvertChanGain(comedi_device *dev,
+ 	unsigned int comediChan, int chanIndex)
+ {				/* index in channel list */
+ 	unsigned int chan, range, aref;
+@@ -1187,7 +1187,7 @@ static unsigned short rtdConvertChanGain(comedi_device * dev,
+ /*
+   Setup the channel-gain table from a comedi list
+ */
+-static void rtd_load_channelgain_list(comedi_device * dev,
++static void rtd_load_channelgain_list(comedi_device *dev,
+ 	unsigned int n_chan, unsigned int *list)
+ {
+ 	if (n_chan > 1) {	/* setup channel gain table */
+@@ -1251,8 +1251,8 @@ static int rtd520_probe_fifo_depth(comedi_device *dev)
+   Note, we don't do any settling delays.  Use a instruction list to
+   select, delay, then read.
+  */
+-static int rtd_ai_rinsn(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++static int rtd_ai_rinsn(comedi_device *dev,
++	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
+ {
+ 	int n, ii;
+ 	int stat;
+@@ -1304,7 +1304,7 @@ static int rtd_ai_rinsn(comedi_device * dev,
+ 
+   The manual claims that we can do a lword read, but it doesn't work here.
+ */
+-static int ai_read_n(comedi_device * dev, comedi_subdevice * s, int count)
++static int ai_read_n(comedi_device *dev, comedi_subdevice *s, int count)
+ {
+ 	int ii;
+ 
+@@ -1343,7 +1343,7 @@ static int ai_read_n(comedi_device * dev, comedi_subdevice * s, int count)
+ /*
+   unknown amout of data is waiting in fifo.
+ */
+-static int ai_read_dregs(comedi_device * dev, comedi_subdevice * s)
++static int ai_read_dregs(comedi_device *dev, comedi_subdevice *s)
+ {
+ 	while (RtdFifoStatus(dev) & FS_ADC_NOT_EMPTY) {	/* 1 -> not empty */
+ 		sampl_t sample;
+@@ -1372,7 +1372,7 @@ static int ai_read_dregs(comedi_device * dev, comedi_subdevice * s)
+ /*
+   Terminate a DMA transfer and wait for everything to quiet down
+ */
+-void abort_dma(comedi_device * dev, unsigned int channel)
++void abort_dma(comedi_device *dev, unsigned int channel)
+ {				/* DMA channel 0, 1 */
+ 	unsigned long dma_cs_addr;	/* the control/status register */
+ 	uint8_t status;
+@@ -1431,7 +1431,7 @@ void abort_dma(comedi_device * dev, unsigned int channel)
+   Process what is in the DMA transfer buffer and pass to comedi
+   Note: this is not re-entrant
+ */
+-static int ai_process_dma(comedi_device * dev, comedi_subdevice * s)
++static int ai_process_dma(comedi_device *dev, comedi_subdevice *s)
+ {
+ 	int ii, n;
+ 	s16 *dp;
+@@ -1645,7 +1645,7 @@ static irqreturn_t rtd_interrupt(int irq,	/* interrupt number (ignored) */
+ /*
+   return the number of samples available
+ */
+-static int rtd_ai_poll(comedi_device * dev, comedi_subdevice * s)
++static int rtd_ai_poll(comedi_device *dev, comedi_subdevice *s)
+ {
+ 	/* TODO: This needs to mask interrupts, read_dregs, and then re-enable */
+ 	/* Not sure what to do if DMA is active */
+@@ -1662,8 +1662,8 @@ static int rtd_ai_poll(comedi_device * dev, comedi_subdevice * s)
+   the command passes.
+ */
+ 
+-static int rtd_ai_cmdtest(comedi_device * dev,
+-	comedi_subdevice * s, comedi_cmd * cmd)
++static int rtd_ai_cmdtest(comedi_device *dev,
++	comedi_subdevice *s, comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -1867,7 +1867,7 @@ static int rtd_ai_cmdtest(comedi_device * dev,
+   This is usually done by an interrupt handler.
+   Userland gets to the data using read calls.
+ */
+-static int rtd_ai_cmd(comedi_device * dev, comedi_subdevice * s)
++static int rtd_ai_cmd(comedi_device *dev, comedi_subdevice *s)
+ {
+ 	comedi_cmd *cmd = &s->async->cmd;
+ 	int timer;
+@@ -2064,7 +2064,7 @@ static int rtd_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ /*
+   Stop a running data aquisition.
+ */
+-static int rtd_ai_cancel(comedi_device * dev, comedi_subdevice * s)
++static int rtd_ai_cancel(comedi_device *dev, comedi_subdevice *s)
+ {
+ 	u16 status;
+ 
+@@ -2132,8 +2132,8 @@ static int rtd_ns_to_timer(unsigned int *ns, int round_mode)
+ /*
+   Output one (or more) analog values to a single port as fast as possible.
+ */
+-static int rtd_ao_winsn(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++static int rtd_ao_winsn(comedi_device *dev,
++	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -2187,8 +2187,8 @@ static int rtd_ao_winsn(comedi_device * dev,
+ 
+ /* AO subdevices should have a read insn as well as a write insn.
+  * Usually this means copying a value stored in devpriv. */
+-static int rtd_ao_rinsn(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++static int rtd_ao_rinsn(comedi_device *dev,
++	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
+ {
+ 	int i;
+ 	int chan = CR_CHAN(insn->chanspec);
+@@ -2210,8 +2210,8 @@ static int rtd_ao_rinsn(comedi_device * dev,
+  * This allows packed reading/writing of the DIO channels.  The
+  * comedi core can convert between insn_bits and insn_read/write
+  */
+-static int rtd_dio_insn_bits(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++static int rtd_dio_insn_bits(comedi_device *dev,
++	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
+ {
+ 	if (insn->n != 2)
+ 		return -EINVAL;
+@@ -2237,8 +2237,8 @@ static int rtd_dio_insn_bits(comedi_device * dev,
+ /*
+   Configure one bit on a IO port as Input or Output (hence the name :-).
+ */
+-static int rtd_dio_insn_config(comedi_device * dev,
+-	comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
++static int rtd_dio_insn_config(comedi_device *dev,
++	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
+ {
+ 	int chan = CR_CHAN(insn->chanspec);
+ 
+diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
+index 24577a9a16b1..41f3736efa3b 100644
+--- a/drivers/staging/comedi/drivers/s626.c
++++ b/drivers/staging/comedi/drivers/s626.c
+@@ -118,8 +118,8 @@ static DEFINE_PCI_DEVICE_TABLE(s626_pci_table) = {
+ 
+ MODULE_DEVICE_TABLE(pci, s626_pci_table);
+ 
+-static int s626_attach(comedi_device * dev, comedi_devconfig * it);
+-static int s626_detach(comedi_device * dev);
++static int s626_attach(comedi_device *dev, comedi_devconfig *it);
++static int s626_detach(comedi_device *dev);
+ 
+ static comedi_driver driver_s626 = {
+       driver_name:"s626",
+@@ -222,36 +222,36 @@ static dio_private *dio_private_word[]={
+ COMEDI_PCI_INITCLEANUP_NOMODULE(driver_s626, s626_pci_table);
+ 
+ /* ioctl routines */
+-static int s626_ai_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++static int s626_ai_insn_config(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data);
+ /* static int s626_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); */
+-static int s626_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
+-static int s626_ai_cmd(comedi_device * dev, comedi_subdevice * s);
+-static int s626_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+-	comedi_cmd * cmd);
+-static int s626_ai_cancel(comedi_device * dev, comedi_subdevice * s);
+-static int s626_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
+-static int s626_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
+-static int s626_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
+-static int s626_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
+-static int s626_dio_set_irq(comedi_device * dev, unsigned int chan);
+-static int s626_dio_reset_irq(comedi_device * dev, unsigned int gruop,
++static int s626_ai_insn_read(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data);
++static int s626_ai_cmd(comedi_device *dev, comedi_subdevice *s);
++static int s626_ai_cmdtest(comedi_device *dev, comedi_subdevice *s,
++	comedi_cmd *cmd);
++static int s626_ai_cancel(comedi_device *dev, comedi_subdevice *s);
++static int s626_ao_winsn(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data);
++static int s626_ao_rinsn(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data);
++static int s626_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data);
++static int s626_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data);
++static int s626_dio_set_irq(comedi_device *dev, unsigned int chan);
++static int s626_dio_reset_irq(comedi_device *dev, unsigned int gruop,
+ 	unsigned int mask);
+-static int s626_dio_clear_irq(comedi_device * dev);
+-static int s626_enc_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
+-static int s626_enc_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
+-static int s626_enc_insn_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data);
++static int s626_dio_clear_irq(comedi_device *dev);
++static int s626_enc_insn_config(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data);
++static int s626_enc_insn_read(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data);
++static int s626_enc_insn_write(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data);
+ static int s626_ns_to_timer(int *nanosec, int round_mode);
+-static int s626_ai_load_polllist(uint8_t * ppl, comedi_cmd * cmd);
+-static int s626_ai_inttrig(comedi_device * dev, comedi_subdevice * s,
++static int s626_ai_load_polllist(uint8_t *ppl, comedi_cmd *cmd);
++static int s626_ai_inttrig(comedi_device *dev, comedi_subdevice *s,
+ 	unsigned int trignum);
+ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG);
+ static lsampl_t s626_ai_reg_to_uint(int data);
+@@ -260,36 +260,36 @@ static lsampl_t s626_ai_reg_to_uint(int data);
+ /* end ioctl routines */
+ 
+ /* internal routines */
+-static void s626_dio_init(comedi_device * dev);
+-static void ResetADC(comedi_device * dev, uint8_t * ppl);
+-static void LoadTrimDACs(comedi_device * dev);
+-static void WriteTrimDAC(comedi_device * dev, uint8_t LogicalChan,
++static void s626_dio_init(comedi_device *dev);
++static void ResetADC(comedi_device *dev, uint8_t *ppl);
++static void LoadTrimDACs(comedi_device *dev);
++static void WriteTrimDAC(comedi_device *dev, uint8_t LogicalChan,
+ 	uint8_t DacData);
+-static uint8_t I2Cread(comedi_device * dev, uint8_t addr);
+-static uint32_t I2Chandshake(comedi_device * dev, uint32_t val);
+-static void SetDAC(comedi_device * dev, uint16_t chan, short dacdata);
+-static void SendDAC(comedi_device * dev, uint32_t val);
+-static void WriteMISC2(comedi_device * dev, uint16_t NewImage);
+-static void DEBItransfer(comedi_device * dev);
+-static uint16_t DEBIread(comedi_device * dev, uint16_t addr);
+-static void DEBIwrite(comedi_device * dev, uint16_t addr, uint16_t wdata);
+-static void DEBIreplace(comedi_device * dev, uint16_t addr, uint16_t mask,
++static uint8_t I2Cread(comedi_device *dev, uint8_t addr);
++static uint32_t I2Chandshake(comedi_device *dev, uint32_t val);
++static void SetDAC(comedi_device *dev, uint16_t chan, short dacdata);
++static void SendDAC(comedi_device *dev, uint32_t val);
++static void WriteMISC2(comedi_device *dev, uint16_t NewImage);
++static void DEBItransfer(comedi_device *dev);
++static uint16_t DEBIread(comedi_device *dev, uint16_t addr);
++static void DEBIwrite(comedi_device *dev, uint16_t addr, uint16_t wdata);
++static void DEBIreplace(comedi_device *dev, uint16_t addr, uint16_t mask,
+ 	uint16_t wdata);
+-static void CloseDMAB(comedi_device * dev, DMABUF * pdma, size_t bsize);
++static void CloseDMAB(comedi_device *dev, DMABUF *pdma, size_t bsize);
+ 
+ /*  COUNTER OBJECT ------------------------------------------------ */
+ typedef struct enc_private_struct {
+ 	/*  Pointers to functions that differ for A and B counters: */
+-	uint16_t(*GetEnable) (comedi_device * dev, struct enc_private_struct *);	/* Return clock enable. */
+-	uint16_t(*GetIntSrc) (comedi_device * dev, struct enc_private_struct *);	/* Return interrupt source. */
+-	uint16_t(*GetLoadTrig) (comedi_device * dev, struct enc_private_struct *);	/* Return preload trigger source. */
+-	uint16_t(*GetMode) (comedi_device * dev, struct enc_private_struct *);	/* Return standardized operating mode. */
+-	void (*PulseIndex) (comedi_device * dev, struct enc_private_struct *);	/* Generate soft index strobe. */
+-	void (*SetEnable) (comedi_device * dev, struct enc_private_struct *, uint16_t enab);	/* Program clock enable. */
+-	void (*SetIntSrc) (comedi_device * dev, struct enc_private_struct *, uint16_t IntSource);	/* Program interrupt source. */
+-	void (*SetLoadTrig) (comedi_device * dev, struct enc_private_struct *, uint16_t Trig);	/* Program preload trigger source. */
+-	void (*SetMode) (comedi_device * dev, struct enc_private_struct *, uint16_t Setup, uint16_t DisableIntSrc);	/* Program standardized operating mode. */
+-	void (*ResetCapFlags) (comedi_device * dev, struct enc_private_struct *);	/* Reset event capture flags. */
++	uint16_t(*GetEnable) (comedi_device *dev, struct enc_private_struct *);	/* Return clock enable. */
++	uint16_t(*GetIntSrc) (comedi_device *dev, struct enc_private_struct *);	/* Return interrupt source. */
++	uint16_t(*GetLoadTrig) (comedi_device *dev, struct enc_private_struct *);	/* Return preload trigger source. */
++	uint16_t(*GetMode) (comedi_device *dev, struct enc_private_struct *);	/* Return standardized operating mode. */
++	void (*PulseIndex) (comedi_device *dev, struct enc_private_struct *);	/* Generate soft index strobe. */
++	void (*SetEnable) (comedi_device *dev, struct enc_private_struct *, uint16_t enab);	/* Program clock enable. */
++	void (*SetIntSrc) (comedi_device *dev, struct enc_private_struct *, uint16_t IntSource);	/* Program interrupt source. */
++	void (*SetLoadTrig) (comedi_device *dev, struct enc_private_struct *, uint16_t Trig);	/* Program preload trigger source. */
++	void (*SetMode) (comedi_device *dev, struct enc_private_struct *, uint16_t Setup, uint16_t DisableIntSrc);	/* Program standardized operating mode. */
++	void (*ResetCapFlags) (comedi_device *dev, struct enc_private_struct *);	/* Reset event capture flags. */
+ 
+ 	uint16_t MyCRA;		/*    Address of CRA register. */
+ 	uint16_t MyCRB;		/*    Address of CRB register. */
+@@ -301,33 +301,33 @@ typedef struct enc_private_struct {
+ #define encpriv ((enc_private *)(dev->subdevices+5)->private)
+ 
+ /* counters routines */
+-static void s626_timer_load(comedi_device * dev, enc_private * k, int tick);
+-static uint32_t ReadLatch(comedi_device * dev, enc_private * k);
+-static void ResetCapFlags_A(comedi_device * dev, enc_private * k);
+-static void ResetCapFlags_B(comedi_device * dev, enc_private * k);
+-static uint16_t GetMode_A(comedi_device * dev, enc_private * k);
+-static uint16_t GetMode_B(comedi_device * dev, enc_private * k);
+-static void SetMode_A(comedi_device * dev, enc_private * k, uint16_t Setup,
++static void s626_timer_load(comedi_device *dev, enc_private *k, int tick);
++static uint32_t ReadLatch(comedi_device *dev, enc_private *k);
++static void ResetCapFlags_A(comedi_device *dev, enc_private *k);
++static void ResetCapFlags_B(comedi_device *dev, enc_private *k);
++static uint16_t GetMode_A(comedi_device *dev, enc_private *k);
++static uint16_t GetMode_B(comedi_device *dev, enc_private *k);
++static void SetMode_A(comedi_device *dev, enc_private *k, uint16_t Setup,
+ 	uint16_t DisableIntSrc);
+-static void SetMode_B(comedi_device * dev, enc_private * k, uint16_t Setup,
++static void SetMode_B(comedi_device *dev, enc_private *k, uint16_t Setup,
+ 	uint16_t DisableIntSrc);
+-static void SetEnable_A(comedi_device * dev, enc_private * k, uint16_t enab);
+-static void SetEnable_B(comedi_device * dev, enc_private * k, uint16_t enab);
+-static uint16_t GetEnable_A(comedi_device * dev, enc_private * k);
+-static uint16_t GetEnable_B(comedi_device * dev, enc_private * k);
+-static void SetLatchSource(comedi_device * dev, enc_private * k,
++static void SetEnable_A(comedi_device *dev, enc_private *k, uint16_t enab);
++static void SetEnable_B(comedi_device *dev, enc_private *k, uint16_t enab);
++static uint16_t GetEnable_A(comedi_device *dev, enc_private *k);
++static uint16_t GetEnable_B(comedi_device *dev, enc_private *k);
++static void SetLatchSource(comedi_device *dev, enc_private *k,
+ 	uint16_t value);
+ /* static uint16_t GetLatchSource(comedi_device *dev, enc_private *k ); */
+-static void SetLoadTrig_A(comedi_device * dev, enc_private * k, uint16_t Trig);
+-static void SetLoadTrig_B(comedi_device * dev, enc_private * k, uint16_t Trig);
+-static uint16_t GetLoadTrig_A(comedi_device * dev, enc_private * k);
+-static uint16_t GetLoadTrig_B(comedi_device * dev, enc_private * k);
+-static void SetIntSrc_B(comedi_device * dev, enc_private * k,
++static void SetLoadTrig_A(comedi_device *dev, enc_private *k, uint16_t Trig);
++static void SetLoadTrig_B(comedi_device *dev, enc_private *k, uint16_t Trig);
++static uint16_t GetLoadTrig_A(comedi_device *dev, enc_private *k);
++static uint16_t GetLoadTrig_B(comedi_device *dev, enc_private *k);
++static void SetIntSrc_B(comedi_device *dev, enc_private *k,
+ 	uint16_t IntSource);
+-static void SetIntSrc_A(comedi_device * dev, enc_private * k,
++static void SetIntSrc_A(comedi_device *dev, enc_private *k,
+ 	uint16_t IntSource);
+-static uint16_t GetIntSrc_A(comedi_device * dev, enc_private * k);
+-static uint16_t GetIntSrc_B(comedi_device * dev, enc_private * k);
++static uint16_t GetIntSrc_A(comedi_device *dev, enc_private *k);
++static uint16_t GetIntSrc_B(comedi_device *dev, enc_private *k);
+ /* static void SetClkMult(comedi_device *dev, enc_private *k, uint16_t value ) ; */
+ /* static uint16_t GetClkMult(comedi_device *dev, enc_private *k ) ; */
+ /* static void SetIndexPol(comedi_device *dev, enc_private *k, uint16_t value ); */
+@@ -336,10 +336,10 @@ static uint16_t GetIntSrc_B(comedi_device * dev, enc_private * k);
+ /* static uint16_t GetClkSrc( comedi_device *dev,enc_private *k );  */
+ /* static void SetIndexSrc( comedi_device *dev,enc_private *k, uint16_t value );  */
+ /* static uint16_t GetIndexSrc( comedi_device *dev,enc_private *k );  */
+-static void PulseIndex_A(comedi_device * dev, enc_private * k);
+-static void PulseIndex_B(comedi_device * dev, enc_private * k);
+-static void Preload(comedi_device * dev, enc_private * k, uint32_t value);
+-static void CountersInit(comedi_device * dev);
++static void PulseIndex_A(comedi_device *dev, enc_private *k);
++static void PulseIndex_B(comedi_device *dev, enc_private *k);
++static void Preload(comedi_device *dev, enc_private *k, uint32_t value);
++static void CountersInit(comedi_device *dev);
+ /* end internal routines */
+ 
+ /*  Counter objects constructor. */
+@@ -485,7 +485,7 @@ static const comedi_lrange s626_range_table = { 2, {
+ 	}
+ };
+ 
+-static int s626_attach(comedi_device * dev, comedi_devconfig * it)
++static int s626_attach(comedi_device *dev, comedi_devconfig *it)
+ {
+ /*   uint8_t	PollList; */
+ /*   uint16_t	AdcData; */
+@@ -1261,7 +1261,7 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int s626_detach(comedi_device * dev)
++static int s626_detach(comedi_device *dev)
+ {
+ 	if (devpriv) {
+ 		/* stop ai_command */
+@@ -1307,7 +1307,7 @@ static int s626_detach(comedi_device * dev)
+ /*
+  * this functions build the RPS program for hardware driven acquistion
+  */
+-void ResetADC(comedi_device * dev, uint8_t * ppl)
++void ResetADC(comedi_device *dev, uint8_t *ppl)
+ {
+ 	register uint32_t *pRPS;
+ 	uint32_t JmpAdrs;
+@@ -1499,8 +1499,8 @@ void ResetADC(comedi_device * dev, uint8_t * ppl)
+ }
+ 
+ /* TO COMPLETE, IF NECESSARY */
+-static int s626_ai_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++static int s626_ai_insn_config(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data)
+ {
+ 
+ 	return -EINVAL;
+@@ -1536,8 +1536,8 @@ static int s626_ai_insn_config(comedi_device * dev, comedi_subdevice * s,
+ /*   return i; */
+ /* } */
+ 
+-static int s626_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++static int s626_ai_insn_read(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data)
+ {
+ 	uint16_t chan = CR_CHAN(insn->chanspec);
+ 	uint16_t range = CR_RANGE(insn->chanspec);
+@@ -1632,7 +1632,7 @@ static int s626_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int s626_ai_load_polllist(uint8_t * ppl, comedi_cmd * cmd)
++static int s626_ai_load_polllist(uint8_t *ppl, comedi_cmd *cmd)
+ {
+ 
+ 	int n;
+@@ -1648,7 +1648,7 @@ static int s626_ai_load_polllist(uint8_t * ppl, comedi_cmd * cmd)
+ 	return n;
+ }
+ 
+-static int s626_ai_inttrig(comedi_device * dev, comedi_subdevice * s,
++static int s626_ai_inttrig(comedi_device *dev, comedi_subdevice *s,
+ 	unsigned int trignum)
+ {
+ 	if (trignum != 0)
+@@ -1667,7 +1667,7 @@ static int s626_ai_inttrig(comedi_device * dev, comedi_subdevice * s,
+ }
+ 
+ /*  TO COMPLETE  */
+-static int s626_ai_cmd(comedi_device * dev, comedi_subdevice * s)
++static int s626_ai_cmd(comedi_device *dev, comedi_subdevice *s)
+ {
+ 
+ 	uint8_t ppl[16];
+@@ -1813,8 +1813,8 @@ static int s626_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ 	return 0;
+ }
+ 
+-static int s626_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+-	comedi_cmd * cmd)
++static int s626_ai_cmdtest(comedi_device *dev, comedi_subdevice *s,
++	comedi_cmd *cmd)
+ {
+ 	int err = 0;
+ 	int tmp;
+@@ -1998,7 +1998,7 @@ static int s626_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	return 0;
+ }
+ 
+-static int s626_ai_cancel(comedi_device * dev, comedi_subdevice * s)
++static int s626_ai_cancel(comedi_device *dev, comedi_subdevice *s)
+ {
+ 	/*  Stop RPS program in case it is currently running. */
+ 	MC_DISABLE(P_MC1, MC1_ERPS1);
+@@ -2039,8 +2039,8 @@ static int s626_ns_to_timer(int *nanosec, int round_mode)
+ 	return divider - 1;
+ }
+ 
+-static int s626_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++static int s626_ao_winsn(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data)
+ {
+ 
+ 	int i;
+@@ -2058,8 +2058,8 @@ static int s626_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-static int s626_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++static int s626_ao_rinsn(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data)
+ {
+ 	int i;
+ 
+@@ -2076,7 +2076,7 @@ static int s626_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+  * ports A, B and C, respectively.
+  */
+ 
+-static void s626_dio_init(comedi_device * dev)
++static void s626_dio_init(comedi_device *dev)
+ {
+ 	uint16_t group;
+ 	comedi_subdevice *s;
+@@ -2105,8 +2105,8 @@ static void s626_dio_init(comedi_device * dev)
+  * This allows packed reading/writing of the DIO channels.  The comedi
+  * core can convert between insn_bits and insn_read/write */
+ 
+-static int s626_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++static int s626_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data)
+ {
+ 
+ 	/* Length of data must be 2 (mask and new data, see below) */
+@@ -2141,8 +2141,8 @@ static int s626_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ 	return 2;
+ }
+ 
+-static int s626_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++static int s626_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data)
+ {
+ 
+ 	switch (data[0]) {
+@@ -2168,7 +2168,7 @@ static int s626_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static int s626_dio_set_irq(comedi_device * dev, unsigned int chan)
++static int s626_dio_set_irq(comedi_device *dev, unsigned int chan)
+ {
+ 	unsigned int group;
+ 	unsigned int bitmask;
+@@ -2210,7 +2210,7 @@ static int s626_dio_set_irq(comedi_device * dev, unsigned int chan)
+ 	return 0;
+ }
+ 
+-static int s626_dio_reset_irq(comedi_device * dev, unsigned int group,
++static int s626_dio_reset_irq(comedi_device *dev, unsigned int group,
+ 	unsigned int mask)
+ {
+ 	DEBUG("s626_dio_reset_irq: disable  interrupt on dio channel %d group %d\n", mask, group);
+@@ -2226,7 +2226,7 @@ static int s626_dio_reset_irq(comedi_device * dev, unsigned int group,
+ 	return 0;
+ }
+ 
+-static int s626_dio_clear_irq(comedi_device * dev)
++static int s626_dio_clear_irq(comedi_device *dev)
+ {
+ 	unsigned int group;
+ 
+@@ -2246,8 +2246,8 @@ static int s626_dio_clear_irq(comedi_device * dev)
+ /* Now this function initializes the value of the counter (data[0])
+    and set the subdevice. To complete with trigger and interrupt
+    configuration */
+-static int s626_enc_insn_config(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++static int s626_enc_insn_config(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data)
+ {
+ 	uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) |	/*  Preload upon */
+ 		/*  index. */
+@@ -2276,8 +2276,8 @@ static int s626_enc_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 	return insn->n;
+ }
+ 
+-static int s626_enc_insn_read(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++static int s626_enc_insn_read(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data)
+ {
+ 
+ 	int n;
+@@ -2294,8 +2294,8 @@ static int s626_enc_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	return n;
+ }
+ 
+-static int s626_enc_insn_write(comedi_device * dev, comedi_subdevice * s,
+-	comedi_insn * insn, lsampl_t * data)
++static int s626_enc_insn_write(comedi_device *dev, comedi_subdevice *s,
++	comedi_insn *insn, lsampl_t *data)
+ {
+ 
+ 	enc_private *k = &encpriv[CR_CHAN(insn->chanspec)];
+@@ -2317,7 +2317,7 @@ static int s626_enc_insn_write(comedi_device * dev, comedi_subdevice * s,
+ 	return 1;
+ }
+ 
+-static void s626_timer_load(comedi_device * dev, enc_private * k, int tick)
++static void s626_timer_load(comedi_device *dev, enc_private *k, int tick)
+ {
+ 	uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) |	/*  Preload upon */
+ 		/*  index. */
+@@ -2363,7 +2363,7 @@ static uint8_t trimchan[] = { 10, 9, 8, 3, 2, 7, 6, 1, 0, 5, 4 };
+ static uint8_t trimadrs[] =
+ 	{ 0x40, 0x41, 0x42, 0x50, 0x51, 0x52, 0x53, 0x60, 0x61, 0x62, 0x63 };
+ 
+-static void LoadTrimDACs(comedi_device * dev)
++static void LoadTrimDACs(comedi_device *dev)
+ {
+ 	register uint8_t i;
+ 
+@@ -2372,7 +2372,7 @@ static void LoadTrimDACs(comedi_device * dev)
+ 		WriteTrimDAC(dev, i, I2Cread(dev, trimadrs[i]));
+ }
+ 
+-static void WriteTrimDAC(comedi_device * dev, uint8_t LogicalChan,
++static void WriteTrimDAC(comedi_device *dev, uint8_t LogicalChan,
+ 	uint8_t DacData)
+ {
+ 	uint32_t chan;
+@@ -2413,7 +2413,7 @@ static void WriteTrimDAC(comedi_device * dev, uint8_t LogicalChan,
+ /* **************  EEPROM ACCESS FUNCTIONS  ************** */
+ /*  Read uint8_t from EEPROM. */
+ 
+-static uint8_t I2Cread(comedi_device * dev, uint8_t addr)
++static uint8_t I2Cread(comedi_device *dev, uint8_t addr)
+ {
+ 	uint8_t rtnval;
+ 
+@@ -2448,7 +2448,7 @@ static uint8_t I2Cread(comedi_device * dev, uint8_t addr)
+ 	return rtnval;
+ }
+ 
+-static uint32_t I2Chandshake(comedi_device * dev, uint32_t val)
++static uint32_t I2Chandshake(comedi_device *dev, uint32_t val)
+ {
+ 	/*  Write I2C command to I2C Transfer Control shadow register. */
+ 	WR7146(P_I2CCTRL, val);
+@@ -2469,7 +2469,7 @@ static uint32_t I2Chandshake(comedi_device * dev, uint32_t val)
+ 
+ /*  Private helper function: Write setpoint to an application DAC channel. */
+ 
+-static void SetDAC(comedi_device * dev, uint16_t chan, short dacdata)
++static void SetDAC(comedi_device *dev, uint16_t chan, short dacdata)
+ {
+ 	register uint16_t signmask;
+ 	register uint32_t WSImage;
+@@ -2530,7 +2530,7 @@ static void SetDAC(comedi_device * dev, uint16_t chan, short dacdata)
+  * Dacpol contains valid target image.
+  */
+ 
+-static void SendDAC(comedi_device * dev, uint32_t val)
++static void SendDAC(comedi_device *dev, uint32_t val)
+ {
+ 
+ 	/* START THE SERIAL CLOCK RUNNING ------------- */
+@@ -2646,7 +2646,7 @@ static void SendDAC(comedi_device * dev, uint32_t val)
+ 	while ((RR7146(P_FB_BUFFER2) & 0xFF000000) == 0) ;
+ }
+ 
+-static void WriteMISC2(comedi_device * dev, uint16_t NewImage)
++static void WriteMISC2(comedi_device *dev, uint16_t NewImage)
+ {
+ 	DEBIwrite(dev, LP_MISC1, MISC1_WENABLE);	/*  enab writes to */
+ 	/*  MISC2 register. */
+@@ -2656,7 +2656,7 @@ static void WriteMISC2(comedi_device * dev, uint16_t NewImage)
+ 
+ /*  Initialize the DEBI interface for all transfers. */
+ 
+-static uint16_t DEBIread(comedi_device * dev, uint16_t addr)
++static uint16_t DEBIread(comedi_device *dev, uint16_t addr)
+ {
+ 	uint16_t retval;
+ 
+@@ -2675,7 +2675,7 @@ static uint16_t DEBIread(comedi_device * dev, uint16_t addr)
+ 
+ /*  Execute a DEBI transfer.  This must be called from within a */
+ /*  critical section. */
+-static void DEBItransfer(comedi_device * dev)
++static void DEBItransfer(comedi_device *dev)
+ {
+ 	/*  Initiate upload of shadow RAM to DEBI control register. */
+ 	MC_ENABLE(P_MC2, MC2_UPLD_DEBI);
+@@ -2689,7 +2689,7 @@ static void DEBItransfer(comedi_device * dev)
+ }
+ 
+ /*  Write a value to a gate array register. */
+-static void DEBIwrite(comedi_device * dev, uint16_t addr, uint16_t wdata)
++static void DEBIwrite(comedi_device *dev, uint16_t addr, uint16_t wdata)
+ {
+ 
+ 	/*  Set up DEBI control register value in shadow RAM. */
+@@ -2704,7 +2704,7 @@ static void DEBIwrite(comedi_device * dev, uint16_t addr, uint16_t wdata)
+  * specifies bits that are to be preserved, wdata is new value to be
+  * or'd with the masked original.
+  */
+-static void DEBIreplace(comedi_device * dev, uint16_t addr, uint16_t mask,
++static void DEBIreplace(comedi_device *dev, uint16_t addr, uint16_t mask,
+ 	uint16_t wdata)
+ {
+ 
+@@ -2722,7 +2722,7 @@ static void DEBIreplace(comedi_device * dev, uint16_t addr, uint16_t mask,
+ 	DEBItransfer(dev);	/*  Execute the DEBI Write transfer. */
+ }
+ 
+-static void CloseDMAB(comedi_device * dev, DMABUF * pdma, size_t bsize)
++static void CloseDMAB(comedi_device *dev, DMABUF *pdma, size_t bsize)
+ {
+ 	void *vbptr;
+ 	dma_addr_t vpptr;
+@@ -2757,7 +2757,7 @@ static void CloseDMAB(comedi_device * dev, DMABUF * pdma, size_t bsize)
+ 
+ /*  Read a counter's output latch. */
+ 
+-static uint32_t ReadLatch(comedi_device * dev, enc_private * k)
++static uint32_t ReadLatch(comedi_device *dev, enc_private *k)
+ {
+ 	register uint32_t value;
+ 	/* DEBUG FIXME DEBUG("ReadLatch: Read Latch enter\n"); */
+@@ -2776,13 +2776,13 @@ static uint32_t ReadLatch(comedi_device * dev, enc_private * k)
+ 
+ /*  Reset a counter's index and overflow event capture flags. */
+ 
+-static void ResetCapFlags_A(comedi_device * dev, enc_private * k)
++static void ResetCapFlags_A(comedi_device *dev, enc_private *k)
+ {
+ 	DEBIreplace(dev, k->MyCRB, (uint16_t) (~CRBMSK_INTCTRL),
+ 		CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A);
+ }
+ 
+-static void ResetCapFlags_B(comedi_device * dev, enc_private * k)
++static void ResetCapFlags_B(comedi_device *dev, enc_private *k)
+ {
+ 	DEBIreplace(dev, k->MyCRB, (uint16_t) (~CRBMSK_INTCTRL),
+ 		CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B);
+@@ -2791,7 +2791,7 @@ static void ResetCapFlags_B(comedi_device * dev, enc_private * k)
+ /*  Return counter setup in a format (COUNTER_SETUP) that is consistent */
+ /*  for both A and B counters. */
+ 
+-static uint16_t GetMode_A(comedi_device * dev, enc_private * k)
++static uint16_t GetMode_A(comedi_device *dev, enc_private *k)
+ {
+ 	register uint16_t cra;
+ 	register uint16_t crb;
+@@ -2829,7 +2829,7 @@ static uint16_t GetMode_A(comedi_device * dev, enc_private * k)
+ 	return setup;
+ }
+ 
+-static uint16_t GetMode_B(comedi_device * dev, enc_private * k)
++static uint16_t GetMode_B(comedi_device *dev, enc_private *k)
+ {
+ 	register uint16_t cra;
+ 	register uint16_t crb;
+@@ -2875,7 +2875,7 @@ static uint16_t GetMode_B(comedi_device * dev, enc_private * k)
+  * ClkPol, ClkEnab, IndexSrc, IndexPol, LoadSrc.
+  */
+ 
+-static void SetMode_A(comedi_device * dev, enc_private * k, uint16_t Setup,
++static void SetMode_A(comedi_device *dev, enc_private *k, uint16_t Setup,
+ 	uint16_t DisableIntSrc)
+ {
+ 	register uint16_t cra;
+@@ -2933,7 +2933,7 @@ static void SetMode_A(comedi_device * dev, enc_private * k, uint16_t Setup,
+ 		(uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_A)), crb);
+ }
+ 
+-static void SetMode_B(comedi_device * dev, enc_private * k, uint16_t Setup,
++static void SetMode_B(comedi_device *dev, enc_private *k, uint16_t Setup,
+ 	uint16_t DisableIntSrc)
+ {
+ 	register uint16_t cra;
+@@ -2997,7 +2997,7 @@ static void SetMode_B(comedi_device * dev, enc_private * k, uint16_t Setup,
+ 
+ /*  Return/set a counter's enable.  enab: 0=always enabled, 1=enabled by index. */
+ 
+-static void SetEnable_A(comedi_device * dev, enc_private * k, uint16_t enab)
++static void SetEnable_A(comedi_device *dev, enc_private *k, uint16_t enab)
+ {
+ 	DEBUG("SetEnable_A: SetEnable_A enter 3541\n");
+ 	DEBIreplace(dev, k->MyCRB,
+@@ -3005,19 +3005,19 @@ static void SetEnable_A(comedi_device * dev, enc_private * k, uint16_t enab)
+ 		(uint16_t) (enab << CRBBIT_CLKENAB_A));
+ }
+ 
+-static void SetEnable_B(comedi_device * dev, enc_private * k, uint16_t enab)
++static void SetEnable_B(comedi_device *dev, enc_private *k, uint16_t enab)
+ {
+ 	DEBIreplace(dev, k->MyCRB,
+ 		(uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_B)),
+ 		(uint16_t) (enab << CRBBIT_CLKENAB_B));
+ }
+ 
+-static uint16_t GetEnable_A(comedi_device * dev, enc_private * k)
++static uint16_t GetEnable_A(comedi_device *dev, enc_private *k)
+ {
+ 	return (DEBIread(dev, k->MyCRB) >> CRBBIT_CLKENAB_A) & 1;
+ }
+ 
+-static uint16_t GetEnable_B(comedi_device * dev, enc_private * k)
++static uint16_t GetEnable_B(comedi_device *dev, enc_private *k)
+ {
+ 	return (DEBIread(dev, k->MyCRB) >> CRBBIT_CLKENAB_B) & 1;
+ }
+@@ -3027,7 +3027,7 @@ static uint16_t GetEnable_B(comedi_device * dev, enc_private * k)
+  * latches B.
+  */
+ 
+-static void SetLatchSource(comedi_device * dev, enc_private * k, uint16_t value)
++static void SetLatchSource(comedi_device *dev, enc_private *k, uint16_t value)
+ {
+ 	DEBUG("SetLatchSource: SetLatchSource enter 3550 \n");
+ 	DEBIreplace(dev, k->MyCRB,
+@@ -3050,25 +3050,25 @@ static void SetLatchSource(comedi_device * dev, enc_private * k, uint16_t value)
+  * 2=OverflowA (B counters only), 3=disabled.
+  */
+ 
+-static void SetLoadTrig_A(comedi_device * dev, enc_private * k, uint16_t Trig)
++static void SetLoadTrig_A(comedi_device *dev, enc_private *k, uint16_t Trig)
+ {
+ 	DEBIreplace(dev, k->MyCRA, (uint16_t) (~CRAMSK_LOADSRC_A),
+ 		(uint16_t) (Trig << CRABIT_LOADSRC_A));
+ }
+ 
+-static void SetLoadTrig_B(comedi_device * dev, enc_private * k, uint16_t Trig)
++static void SetLoadTrig_B(comedi_device *dev, enc_private *k, uint16_t Trig)
+ {
+ 	DEBIreplace(dev, k->MyCRB,
+ 		(uint16_t) (~(CRBMSK_LOADSRC_B | CRBMSK_INTCTRL)),
+ 		(uint16_t) (Trig << CRBBIT_LOADSRC_B));
+ }
+ 
+-static uint16_t GetLoadTrig_A(comedi_device * dev, enc_private * k)
++static uint16_t GetLoadTrig_A(comedi_device *dev, enc_private *k)
+ {
+ 	return (DEBIread(dev, k->MyCRA) >> CRABIT_LOADSRC_A) & 3;
+ }
+ 
+-static uint16_t GetLoadTrig_B(comedi_device * dev, enc_private * k)
++static uint16_t GetLoadTrig_B(comedi_device *dev, enc_private *k)
+ {
+ 	return (DEBIread(dev, k->MyCRB) >> CRBBIT_LOADSRC_B) & 3;
+ }
+@@ -3078,7 +3078,7 @@ static uint16_t GetLoadTrig_B(comedi_device * dev, enc_private * k)
+  * 2=IndexOnly, 3=IndexAndOverflow.
+  */
+ 
+-static void SetIntSrc_A(comedi_device * dev, enc_private * k,
++static void SetIntSrc_A(comedi_device *dev, enc_private *k,
+ 	uint16_t IntSource)
+ {
+ 	/*  Reset any pending counter overflow or index captures. */
+@@ -3095,7 +3095,7 @@ static void SetIntSrc_A(comedi_device * dev, enc_private * k,
+ 		MyEventBits[IntSource];
+ }
+ 
+-static void SetIntSrc_B(comedi_device * dev, enc_private * k,
++static void SetIntSrc_B(comedi_device *dev, enc_private *k,
+ 	uint16_t IntSource)
+ {
+ 	uint16_t crb;
+@@ -3118,12 +3118,12 @@ static void SetIntSrc_B(comedi_device * dev, enc_private * k,
+ 		MyEventBits[IntSource];
+ }
+ 
+-static uint16_t GetIntSrc_A(comedi_device * dev, enc_private * k)
++static uint16_t GetIntSrc_A(comedi_device *dev, enc_private *k)
+ {
+ 	return (DEBIread(dev, k->MyCRA) >> CRABIT_INTSRC_A) & 3;
+ }
+ 
+-static uint16_t GetIntSrc_B(comedi_device * dev, enc_private * k)
++static uint16_t GetIntSrc_B(comedi_device *dev, enc_private *k)
+ {
+ 	return (DEBIread(dev, k->MyCRB) >> CRBBIT_INTSRC_B) & 3;
+ }
+@@ -3191,7 +3191,7 @@ static uint16_t GetIntSrc_B(comedi_device * dev, enc_private * k)
+ 
+ /*  Generate an index pulse. */
+ 
+-static void PulseIndex_A(comedi_device * dev, enc_private * k)
++static void PulseIndex_A(comedi_device *dev, enc_private *k)
+ {
+ 	register uint16_t cra;
+ 
+@@ -3203,7 +3203,7 @@ static void PulseIndex_A(comedi_device * dev, enc_private * k)
+ 	DEBIwrite(dev, k->MyCRA, cra);
+ }
+ 
+-static void PulseIndex_B(comedi_device * dev, enc_private * k)
++static void PulseIndex_B(comedi_device *dev, enc_private *k)
+ {
+ 	register uint16_t crb;
+ 
+@@ -3214,7 +3214,7 @@ static void PulseIndex_B(comedi_device * dev, enc_private * k)
+ 
+ /*  Write value into counter preload register. */
+ 
+-static void Preload(comedi_device * dev, enc_private * k, uint32_t value)
++static void Preload(comedi_device *dev, enc_private *k, uint32_t value)
+ {
+ 	DEBUG("Preload: preload enter\n");
+ 	DEBIwrite(dev, (uint16_t) (k->MyLatchLsw), (uint16_t) value);	/*  Write value to preload register. */
+@@ -3223,7 +3223,7 @@ static void Preload(comedi_device * dev, enc_private * k, uint32_t value)
+ 		(uint16_t) (value >> 16));
+ }
+ 
+-static void CountersInit(comedi_device * dev)
++static void CountersInit(comedi_device *dev)
+ {
+ 	int chan;
+ 	enc_private *k;
+diff --git a/drivers/staging/comedi/kcomedilib/data.c b/drivers/staging/comedi/kcomedilib/data.c
+index 79aec2041150..4f1a41d50861 100644
+--- a/drivers/staging/comedi/kcomedilib/data.c
++++ b/drivers/staging/comedi/kcomedilib/data.c
+@@ -27,7 +27,7 @@
+ 
+ #include 
+ 
+-int comedi_data_write(comedi_t * dev, unsigned int subdev, unsigned int chan,
++int comedi_data_write(comedi_t *dev, unsigned int subdev, unsigned int chan,
+ 	unsigned int range, unsigned int aref, lsampl_t data)
+ {
+ 	comedi_insn insn;
+@@ -42,8 +42,8 @@ int comedi_data_write(comedi_t * dev, unsigned int subdev, unsigned int chan,
+ 	return comedi_do_insn(dev, &insn);
+ }
+ 
+-int comedi_data_read(comedi_t * dev, unsigned int subdev, unsigned int chan,
+-	unsigned int range, unsigned int aref, lsampl_t * data)
++int comedi_data_read(comedi_t *dev, unsigned int subdev, unsigned int chan,
++	unsigned int range, unsigned int aref, lsampl_t *data)
+ {
+ 	comedi_insn insn;
+ 
+@@ -57,7 +57,7 @@ int comedi_data_read(comedi_t * dev, unsigned int subdev, unsigned int chan,
+ 	return comedi_do_insn(dev, &insn);
+ }
+ 
+-int comedi_data_read_hint(comedi_t * dev, unsigned int subdev,
++int comedi_data_read_hint(comedi_t *dev, unsigned int subdev,
+ 	unsigned int chan, unsigned int range, unsigned int aref)
+ {
+ 	comedi_insn insn;
+@@ -73,9 +73,9 @@ int comedi_data_read_hint(comedi_t * dev, unsigned int subdev,
+ 	return comedi_do_insn(dev, &insn);
+ }
+ 
+-int comedi_data_read_delayed(comedi_t * dev, unsigned int subdev,
++int comedi_data_read_delayed(comedi_t *dev, unsigned int subdev,
+ 	unsigned int chan, unsigned int range, unsigned int aref,
+-	lsampl_t * data, unsigned int nano_sec)
++	lsampl_t *data, unsigned int nano_sec)
+ {
+ 	int retval;
+ 
+diff --git a/drivers/staging/comedi/kcomedilib/dio.c b/drivers/staging/comedi/kcomedilib/dio.c
+index a9f488aed369..823052776e93 100644
+--- a/drivers/staging/comedi/kcomedilib/dio.c
++++ b/drivers/staging/comedi/kcomedilib/dio.c
+@@ -26,7 +26,7 @@
+ 
+ #include 
+ 
+-int comedi_dio_config(comedi_t * dev, unsigned int subdev, unsigned int chan,
++int comedi_dio_config(comedi_t *dev, unsigned int subdev, unsigned int chan,
+ 	unsigned int io)
+ {
+ 	comedi_insn insn;
+@@ -41,7 +41,7 @@ int comedi_dio_config(comedi_t * dev, unsigned int subdev, unsigned int chan,
+ 	return comedi_do_insn(dev, &insn);
+ }
+ 
+-int comedi_dio_read(comedi_t * dev, unsigned int subdev, unsigned int chan,
++int comedi_dio_read(comedi_t *dev, unsigned int subdev, unsigned int chan,
+ 	unsigned int *val)
+ {
+ 	comedi_insn insn;
+@@ -56,7 +56,7 @@ int comedi_dio_read(comedi_t * dev, unsigned int subdev, unsigned int chan,
+ 	return comedi_do_insn(dev, &insn);
+ }
+ 
+-int comedi_dio_write(comedi_t * dev, unsigned int subdev, unsigned int chan,
++int comedi_dio_write(comedi_t *dev, unsigned int subdev, unsigned int chan,
+ 	unsigned int val)
+ {
+ 	comedi_insn insn;
+@@ -71,7 +71,7 @@ int comedi_dio_write(comedi_t * dev, unsigned int subdev, unsigned int chan,
+ 	return comedi_do_insn(dev, &insn);
+ }
+ 
+-int comedi_dio_bitfield(comedi_t * dev, unsigned int subdev, unsigned int mask,
++int comedi_dio_bitfield(comedi_t *dev, unsigned int subdev, unsigned int mask,
+ 	unsigned int *bits)
+ {
+ 	comedi_insn insn;
+diff --git a/drivers/staging/comedi/kcomedilib/get.c b/drivers/staging/comedi/kcomedilib/get.c
+index 2004ad4480c0..781733787e96 100644
+--- a/drivers/staging/comedi/kcomedilib/get.c
++++ b/drivers/staging/comedi/kcomedilib/get.c
+@@ -26,14 +26,14 @@
+ #include "../comedilib.h"
+ #include "../comedidev.h"
+ 
+-int comedi_get_n_subdevices(comedi_t * d)
++int comedi_get_n_subdevices(comedi_t *d)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 
+ 	return dev->n_subdevices;
+ }
+ 
+-int comedi_get_version_code(comedi_t * d)
++int comedi_get_version_code(comedi_t *d)
+ {
+ 	return COMEDI_VERSION_CODE;
+ }
+@@ -52,7 +52,7 @@ const char *comedi_get_board_name(comedi_t * d)
+ 	return dev->board_name;
+ }
+ 
+-int comedi_get_subdevice_type(comedi_t * d, unsigned int subdevice)
++int comedi_get_subdevice_type(comedi_t *d, unsigned int subdevice)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+@@ -60,7 +60,7 @@ int comedi_get_subdevice_type(comedi_t * d, unsigned int subdevice)
+ 	return s->type;
+ }
+ 
+-unsigned int comedi_get_subdevice_flags(comedi_t * d, unsigned int subdevice)
++unsigned int comedi_get_subdevice_flags(comedi_t *d, unsigned int subdevice)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+@@ -68,7 +68,7 @@ unsigned int comedi_get_subdevice_flags(comedi_t * d, unsigned int subdevice)
+ 	return s->subdev_flags;
+ }
+ 
+-int comedi_find_subdevice_by_type(comedi_t * d, int type, unsigned int subd)
++int comedi_find_subdevice_by_type(comedi_t *d, int type, unsigned int subd)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 
+@@ -82,7 +82,7 @@ int comedi_find_subdevice_by_type(comedi_t * d, int type, unsigned int subd)
+ 	return -1;
+ }
+ 
+-int comedi_get_n_channels(comedi_t * d, unsigned int subdevice)
++int comedi_get_n_channels(comedi_t *d, unsigned int subdevice)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+@@ -90,7 +90,7 @@ int comedi_get_n_channels(comedi_t * d, unsigned int subdevice)
+ 	return s->n_chan;
+ }
+ 
+-int comedi_get_len_chanlist(comedi_t * d, unsigned int subdevice)
++int comedi_get_len_chanlist(comedi_t *d, unsigned int subdevice)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+@@ -98,7 +98,7 @@ int comedi_get_len_chanlist(comedi_t * d, unsigned int subdevice)
+ 	return s->len_chanlist;
+ }
+ 
+-lsampl_t comedi_get_maxdata(comedi_t * d, unsigned int subdevice,
++lsampl_t comedi_get_maxdata(comedi_t *d, unsigned int subdevice,
+ 	unsigned int chan)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+@@ -111,7 +111,7 @@ lsampl_t comedi_get_maxdata(comedi_t * d, unsigned int subdevice,
+ }
+ 
+ #ifdef KCOMEDILIB_DEPRECATED
+-int comedi_get_rangetype(comedi_t * d, unsigned int subdevice,
++int comedi_get_rangetype(comedi_t *d, unsigned int subdevice,
+ 	unsigned int chan)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+@@ -130,7 +130,7 @@ int comedi_get_rangetype(comedi_t * d, unsigned int subdevice,
+ }
+ #endif
+ 
+-int comedi_get_n_ranges(comedi_t * d, unsigned int subdevice, unsigned int chan)
++int comedi_get_n_ranges(comedi_t *d, unsigned int subdevice, unsigned int chan)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+@@ -148,8 +148,8 @@ int comedi_get_n_ranges(comedi_t * d, unsigned int subdevice, unsigned int chan)
+ /*
+  * ALPHA (non-portable)
+ */
+-int comedi_get_krange(comedi_t * d, unsigned int subdevice, unsigned int chan,
+-	unsigned int range, comedi_krange * krange)
++int comedi_get_krange(comedi_t *d, unsigned int subdevice, unsigned int chan,
++	unsigned int range, comedi_krange *krange)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+@@ -171,7 +171,7 @@ int comedi_get_krange(comedi_t * d, unsigned int subdevice, unsigned int chan,
+ /*
+  * ALPHA (may be renamed)
+ */
+-unsigned int comedi_get_buf_head_pos(comedi_t * d, unsigned int subdevice)
++unsigned int comedi_get_buf_head_pos(comedi_t *d, unsigned int subdevice)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+@@ -184,7 +184,7 @@ unsigned int comedi_get_buf_head_pos(comedi_t * d, unsigned int subdevice)
+ 	return async->buf_write_count;
+ }
+ 
+-int comedi_get_buffer_contents(comedi_t * d, unsigned int subdevice)
++int comedi_get_buffer_contents(comedi_t *d, unsigned int subdevice)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+@@ -203,7 +203,7 @@ int comedi_get_buffer_contents(comedi_t * d, unsigned int subdevice)
+ /*
+  * ALPHA
+ */
+-int comedi_set_user_int_count(comedi_t * d, unsigned int subdevice,
++int comedi_set_user_int_count(comedi_t *d, unsigned int subdevice,
+ 	unsigned int buf_user_count)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+@@ -224,7 +224,7 @@ int comedi_set_user_int_count(comedi_t * d, unsigned int subdevice,
+ 	return 0;
+ }
+ 
+-int comedi_mark_buffer_read(comedi_t * d, unsigned int subdevice,
++int comedi_mark_buffer_read(comedi_t *d, unsigned int subdevice,
+ 	unsigned int num_bytes)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+@@ -243,7 +243,7 @@ int comedi_mark_buffer_read(comedi_t * d, unsigned int subdevice,
+ 	return 0;
+ }
+ 
+-int comedi_mark_buffer_written(comedi_t * d, unsigned int subdevice,
++int comedi_mark_buffer_written(comedi_t *d, unsigned int subdevice,
+ 	unsigned int num_bytes)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+@@ -263,7 +263,7 @@ int comedi_mark_buffer_written(comedi_t * d, unsigned int subdevice,
+ 	return 0;
+ }
+ 
+-int comedi_get_buffer_size(comedi_t * d, unsigned int subdev)
++int comedi_get_buffer_size(comedi_t *d, unsigned int subdev)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdev;
+@@ -278,7 +278,7 @@ int comedi_get_buffer_size(comedi_t * d, unsigned int subdev)
+ 	return async->prealloc_bufsz;
+ }
+ 
+-int comedi_get_buffer_offset(comedi_t * d, unsigned int subdevice)
++int comedi_get_buffer_offset(comedi_t *d, unsigned int subdevice)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices + subdevice;
+diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+index 510fbdcec493..e758e4e8c91b 100644
+--- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
++++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+@@ -89,7 +89,7 @@ comedi_t *comedi_open_old(unsigned int minor)
+ 	return (comedi_t *) dev;
+ }
+ 
+-int comedi_close(comedi_t * d)
++int comedi_close(comedi_t *d)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 
+@@ -113,7 +113,7 @@ char *comedi_strerror(int err)
+ 	return "unknown error";
+ }
+ 
+-int comedi_fileno(comedi_t * d)
++int comedi_fileno(comedi_t *d)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 
+@@ -121,7 +121,7 @@ int comedi_fileno(comedi_t * d)
+ 	return dev->minor;
+ }
+ 
+-int comedi_command(comedi_t * d, comedi_cmd * cmd)
++int comedi_command(comedi_t *d, comedi_cmd *cmd)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s;
+@@ -161,7 +161,7 @@ int comedi_command(comedi_t * d, comedi_cmd * cmd)
+ 	return s->do_cmd(dev, s);
+ }
+ 
+-int comedi_command_test(comedi_t * d, comedi_cmd * cmd)
++int comedi_command_test(comedi_t *d, comedi_cmd *cmd)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s;
+@@ -183,7 +183,7 @@ int comedi_command_test(comedi_t * d, comedi_cmd * cmd)
+  *	COMEDI_INSN
+  *	perform an instruction
+  */
+-int comedi_do_insn(comedi_t * d, comedi_insn * insn)
++int comedi_do_insn(comedi_t *d, comedi_insn *insn)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s;
+@@ -323,7 +323,7 @@ int comedi_do_insn(comedi_t * d, comedi_insn * insn)
+ 	- lock while subdevice being programmed
+ 
+ */
+-int comedi_lock(comedi_t * d, unsigned int subdevice)
++int comedi_lock(comedi_t *d, unsigned int subdevice)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s;
+@@ -366,7 +366,7 @@ int comedi_lock(comedi_t * d, unsigned int subdevice)
+ 		none
+ 
+ */
+-int comedi_unlock(comedi_t * d, unsigned int subdevice)
++int comedi_unlock(comedi_t *d, unsigned int subdevice)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s;
+@@ -418,7 +418,7 @@ int comedi_unlock(comedi_t * d, unsigned int subdevice)
+ 		nothing
+ 
+ */
+-int comedi_cancel(comedi_t * d, unsigned int subdevice)
++int comedi_cancel(comedi_t *d, unsigned int subdevice)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s;
+@@ -461,7 +461,7 @@ int comedi_cancel(comedi_t * d, unsigned int subdevice)
+ /*
+    registration of callback functions
+  */
+-int comedi_register_callback(comedi_t * d, unsigned int subdevice,
++int comedi_register_callback(comedi_t *d, unsigned int subdevice,
+ 	unsigned int mask, int (*cb) (unsigned int, void *), void *arg)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+@@ -498,7 +498,7 @@ int comedi_register_callback(comedi_t * d, unsigned int subdevice,
+ 	return 0;
+ }
+ 
+-int comedi_poll(comedi_t * d, unsigned int subdevice)
++int comedi_poll(comedi_t *d, unsigned int subdevice)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s = dev->subdevices;
+@@ -525,7 +525,7 @@ int comedi_poll(comedi_t * d, unsigned int subdevice)
+ }
+ 
+ /* WARNING: not portable */
+-int comedi_map(comedi_t * d, unsigned int subdevice, void *ptr)
++int comedi_map(comedi_t *d, unsigned int subdevice, void *ptr)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s;
+@@ -548,7 +548,7 @@ int comedi_map(comedi_t * d, unsigned int subdevice, void *ptr)
+ }
+ 
+ /* WARNING: not portable */
+-int comedi_unmap(comedi_t * d, unsigned int subdevice)
++int comedi_unmap(comedi_t *d, unsigned int subdevice)
+ {
+ 	comedi_device *dev = (comedi_device *) d;
+ 	comedi_subdevice *s;
+diff --git a/drivers/staging/comedi/range.c b/drivers/staging/comedi/range.c
+index 2934fb3162cd..b8eb4ec41854 100644
+--- a/drivers/staging/comedi/range.c
++++ b/drivers/staging/comedi/range.c
+@@ -44,7 +44,7 @@ const comedi_lrange range_unknown = { 1, {{0, 1000000, UNIT_none}} };
+ 	writes:
+ 		n comedi_krange structures to rangeinfo->range_ptr
+ */
+-int do_rangeinfo_ioctl(comedi_device * dev, comedi_rangeinfo * arg)
++int do_rangeinfo_ioctl(comedi_device *dev, comedi_rangeinfo *arg)
+ {
+ 	comedi_rangeinfo it;
+ 	int subd, chan;
+@@ -84,7 +84,7 @@ int do_rangeinfo_ioctl(comedi_device * dev, comedi_rangeinfo * arg)
+ 	return 0;
+ }
+ 
+-static int aref_invalid(comedi_subdevice * s, unsigned int chanspec)
++static int aref_invalid(comedi_subdevice *s, unsigned int chanspec)
+ {
+ 	unsigned int aref;
+ 
+@@ -120,7 +120,7 @@ static int aref_invalid(comedi_subdevice * s, unsigned int chanspec)
+    This function checks each element in a channel/gain list to make
+    make sure it is valid.
+ */
+-int check_chanlist(comedi_subdevice * s, int n, unsigned int *chanlist)
++int check_chanlist(comedi_subdevice *s, int n, unsigned int *chanlist)
+ {
+ 	int i;
+ 	int chan;
+diff --git a/drivers/staging/comedi/rt.c b/drivers/staging/comedi/rt.c
+index 2546c64dab00..ba9c70ecd044 100644
+--- a/drivers/staging/comedi/rt.c
++++ b/drivers/staging/comedi/rt.c
+@@ -67,7 +67,7 @@ static struct comedi_irq_struct *comedi_irqs[NR_IRQS];
+ 
+ int comedi_request_irq(unsigned irq, irqreturn_t(*handler) (int,
+ 		void *PT_REGS_ARG), unsigned long flags, const char *device,
+-	comedi_device * dev_id)
++	comedi_device *dev_id)
+ {
+ 	struct comedi_irq_struct *it;
+ 	int ret;
+@@ -102,7 +102,7 @@ int comedi_request_irq(unsigned irq, irqreturn_t(*handler) (int,
+ 	return 0;
+ }
+ 
+-void comedi_free_irq(unsigned int irq, comedi_device * dev_id)
++void comedi_free_irq(unsigned int irq, comedi_device *dev_id)
+ {
+ 	struct comedi_irq_struct *it;
+ 
+@@ -121,7 +121,7 @@ void comedi_free_irq(unsigned int irq, comedi_device * dev_id)
+ 	comedi_irqs[irq] = NULL;
+ }
+ 
+-int comedi_switch_to_rt(comedi_device * dev)
++int comedi_switch_to_rt(comedi_device *dev)
+ {
+ 	struct comedi_irq_struct *it;
+ 	unsigned long flags;
+@@ -145,7 +145,7 @@ int comedi_switch_to_rt(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-void comedi_switch_to_non_rt(comedi_device * dev)
++void comedi_switch_to_non_rt(comedi_device *dev)
+ {
+ 	struct comedi_irq_struct *it;
+ 	unsigned long flags;
+@@ -170,7 +170,7 @@ void wake_up_int_handler(int arg1, void *arg2)
+ 	wake_up_interruptible((wait_queue_head_t *) arg2);
+ }
+ 
+-void comedi_rt_pend_wakeup(wait_queue_head_t * q)
++void comedi_rt_pend_wakeup(wait_queue_head_t *q)
+ {
+ 	rt_pend_call(wake_up_int_handler, 0, q);
+ }

commit b6c777571b8d387d3add91170826f32a379e4313
+Author: Bill Pemberton 
+Date:   Mon Mar 16 22:03:24 2009 -0400
+
+    Staging: comedi: Convert C99 style comments to traditional style comments
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi_ksyms.c b/drivers/staging/comedi/comedi_ksyms.c
+index 7d0db3bb680f..6e6fb979ef54 100644
+--- a/drivers/staging/comedi/comedi_ksyms.c
++++ b/drivers/staging/comedi/comedi_ksyms.c
+@@ -31,12 +31,12 @@
+ /* for drivers */
+ EXPORT_SYMBOL(comedi_driver_register);
+ EXPORT_SYMBOL(comedi_driver_unregister);
+-//EXPORT_SYMBOL(comedi_bufcheck);
+-//EXPORT_SYMBOL(comedi_done);
+-//EXPORT_SYMBOL(comedi_error_done);
++/* EXPORT_SYMBOL(comedi_bufcheck); */
++/* EXPORT_SYMBOL(comedi_done); */
++/* EXPORT_SYMBOL(comedi_error_done); */
+ EXPORT_SYMBOL(comedi_error);
+-//EXPORT_SYMBOL(comedi_eobuf);
+-//EXPORT_SYMBOL(comedi_eos);
++/* EXPORT_SYMBOL(comedi_eobuf); */
++/* EXPORT_SYMBOL(comedi_eos); */
+ EXPORT_SYMBOL(comedi_event);
+ EXPORT_SYMBOL(comedi_get_subdevice_runflags);
+ EXPORT_SYMBOL(comedi_set_subdevice_runflags);
+diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
+index e14aef2a197a..48e54042f8b3 100644
+--- a/drivers/staging/comedi/drivers.c
++++ b/drivers/staging/comedi/drivers.c
+@@ -140,7 +140,7 @@ int comedi_device_attach(comedi_device * dev, comedi_devconfig * it)
+ 				continue;
+ 			}
+ 		}
+-		//initialize dev->driver here so comedi_error() can be called from attach
++		/* initialize dev->driver here so comedi_error() can be called from attach */
+ 		dev->driver = driv;
+ 		ret = driv->attach(dev, it);
+ 		if (ret < 0) {
+@@ -151,8 +151,8 @@ int comedi_device_attach(comedi_device * dev, comedi_devconfig * it)
+ 		goto attached;
+ 	}
+ 
+-	// recognize has failed if we get here
+-	// report valid board names before returning error
++	/*  recognize has failed if we get here */
++	/*  report valid board names before returning error */
+ 	for (driv = comedi_drivers; driv; driv = driv->next) {
+ 		if (!try_module_get(driv->module)) {
+ 			printk("comedi: failed to increment module count\n");
+@@ -299,7 +299,7 @@ static int postconfig(comedi_device * dev)
+ 	return 0;
+ }
+ 
+-// generic recognize function for drivers that register their supported board names
++/*  generic recognize function for drivers that register their supported board names */
+ void *comedi_recognize(comedi_driver * driv, const char *name)
+ {
+ 	unsigned i;
+@@ -426,7 +426,7 @@ int comedi_buf_alloc(comedi_device * dev, comedi_subdevice * s,
+ 	if (async->prealloc_buf && async->prealloc_bufsz == new_size) {
+ 		return 0;
+ 	}
+-	// deallocate old buffer
++	/*  deallocate old buffer */
+ 	if (async->prealloc_buf) {
+ 		vunmap(async->prealloc_buf);
+ 		async->prealloc_buf = NULL;
+@@ -455,7 +455,7 @@ int comedi_buf_alloc(comedi_device * dev, comedi_subdevice * s,
+ 		async->buf_page_list = NULL;
+ 		async->n_buf_pages = 0;
+ 	}
+-	// allocate new buffer
++	/*  allocate new buffer */
+ 	if (new_size) {
+ 		unsigned i = 0;
+ 		unsigned n_pages = new_size >> PAGE_SHIFT;
+@@ -568,7 +568,7 @@ unsigned int comedi_buf_munge(comedi_async * async, unsigned int num_bytes)
+ 		s->munge(s->device, s, async->prealloc_buf + async->munge_ptr,
+ 			block_size, async->munge_chan);
+ 
+-		smp_wmb();	//barrier insures data is munged in buffer before munge_count is incremented
++		smp_wmb();	/* barrier insures data is munged in buffer before munge_count is incremented */
+ 
+ 		async->munge_chan += block_size / num_sample_bytes;
+ 		async->munge_chan %= async->cmd.chanlist_len;
+@@ -667,7 +667,7 @@ unsigned comedi_buf_read_alloc(comedi_async * async, unsigned nbytes)
+ /* transfers control of a chunk from reader to free buffer space */
+ unsigned comedi_buf_read_free(comedi_async * async, unsigned int nbytes)
+ {
+-	// barrier insures data has been read out of buffer before read count is incremented
++	/*  barrier insures data has been read out of buffer before read count is incremented */
+ 	smp_mb();
+ 	if ((int)(async->buf_read_count + nbytes -
+ 			async->buf_read_alloc_count) > 0) {
+@@ -852,9 +852,9 @@ int comedi_pci_auto_config(struct pci_dev *pcidev, const char *board_name)
+ {
+ 	int options[2];
+ 
+-	// pci bus
++	/*  pci bus */
+ 	options[0] = pcidev->bus->number;
+-	// pci slot
++	/*  pci slot */
+ 	options[1] = PCI_SLOT(pcidev->devfn);
+ 
+ 	return comedi_auto_config(&pcidev->dev, board_name, options, sizeof(options) / sizeof(options[0]));
+diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
+index 59144d7cb0bc..143a5f95b31f 100644
+--- a/drivers/staging/comedi/drivers/icp_multi.c
++++ b/drivers/staging/comedi/drivers/icp_multi.c
+@@ -61,7 +61,7 @@ There are 4 x 12-bit Analogue Outputs.  Ranges : 5V, 10V, +/-5V, +/-10V
+ 
+ #define ICP_MULTI_EXTDEBUG
+ 
+-// Hardware types of the cards
++/*  Hardware types of the cards */
+ #define TYPE_ICP_MULTI	0
+ 
+ #define IORANGE_ICP_MULTI 	32
+@@ -81,20 +81,20 @@ There are 4 x 12-bit Analogue Outputs.  Ranges : 5V, 10V, +/-5V, +/-10V
+ 
+ #define ICP_MULTI_SIZE		0x20	/* 32 bytes */
+ 
+-// Define bits from ADC command/status register
++/*  Define bits from ADC command/status register */
+ #define	ADC_ST		0x0001	/* Start ADC */
+ #define	ADC_BSY		0x0001	/* ADC busy */
+ #define ADC_BI		0x0010	/* Bipolar input range 1 = bipolar */
+ #define ADC_RA		0x0020	/* Input range 0 = 5V, 1 = 10V */
+ #define	ADC_DI		0x0040	/* Differential input mode 1 = differential */
+ 
+-// Define bits from DAC command/status register
++/*  Define bits from DAC command/status register */
+ #define	DAC_ST		0x0001	/* Start DAC */
+ #define DAC_BSY		0x0001	/* DAC busy */
+ #define	DAC_BI		0x0010	/* Bipolar input range 1 = bipolar */
+ #define	DAC_RA		0x0020	/* Input range 0 = 5V, 1 = 10V */
+ 
+-// Define bits from interrupt enable/status registers
++/*  Define bits from interrupt enable/status registers */
+ #define	ADC_READY	0x0001	/* A/d conversion ready interrupt */
+ #define	DAC_READY	0x0002	/* D/a conversion ready interrupt */
+ #define	DOUT_ERROR	0x0004	/* Digital output error interrupt */
+@@ -104,10 +104,10 @@ There are 4 x 12-bit Analogue Outputs.  Ranges : 5V, 10V, +/-5V, +/-10V
+ #define	CIE2		0x0040	/* Counter 2 overrun interrupt */
+ #define	CIE3		0x0080	/* Counter 3 overrun interrupt */
+ 
+-// Useful definitions
+-#define	Status_IRQ	0x00ff	// All interrupts
++/*  Useful definitions */
++#define	Status_IRQ	0x00ff	/*  All interrupts */
+ 
+-// Define analogue range
++/*  Define analogue range */
+ static const comedi_lrange range_analog = { 4, {
+ 			UNI_RANGE(5),
+ 			UNI_RANGE(10),
+@@ -134,41 +134,41 @@ static int icp_multi_detach(comedi_device * dev);
+ static unsigned short pci_list_builded = 0;	/*>0 list of card is known */
+ 
+ typedef struct {
+-	const char *name;	// driver name
++	const char *name;	/*  driver name */
+ 	int device_id;
+-	int iorange;		// I/O range len
+-	char have_irq;		// 1=card support IRQ
+-	char cardtype;		// 0=ICP Multi
+-	int n_aichan;		// num of A/D chans
+-	int n_aichand;		// num of A/D chans in diff mode
+-	int n_aochan;		// num of D/A chans
+-	int n_dichan;		// num of DI chans
+-	int n_dochan;		// num of DO chans
+-	int n_ctrs;		// num of counters
+-	int ai_maxdata;		// resolution of A/D
+-	int ao_maxdata;		// resolution of D/A
+-	const comedi_lrange *rangelist_ai;	// rangelist for A/D
+-	const char *rangecode;	// range codes for programming
+-	const comedi_lrange *rangelist_ao;	// rangelist for D/A
++	int iorange;		/*  I/O range len */
++	char have_irq;		/*  1=card support IRQ */
++	char cardtype;		/*  0=ICP Multi */
++	int n_aichan;		/*  num of A/D chans */
++	int n_aichand;		/*  num of A/D chans in diff mode */
++	int n_aochan;		/*  num of D/A chans */
++	int n_dichan;		/*  num of DI chans */
++	int n_dochan;		/*  num of DO chans */
++	int n_ctrs;		/*  num of counters */
++	int ai_maxdata;		/*  resolution of A/D */
++	int ao_maxdata;		/*  resolution of D/A */
++	const comedi_lrange *rangelist_ai;	/*  rangelist for A/D */
++	const char *rangecode;	/*  range codes for programming */
++	const comedi_lrange *rangelist_ao;	/*  rangelist for D/A */
+ } boardtype;
+ 
+ static const boardtype boardtypes[] = {
+-	{"icp_multi",		// Driver name
+-			DEVICE_ID,	// PCI device ID
+-			IORANGE_ICP_MULTI,	// I/O range length
+-			1,	// 1=Card supports interrupts
+-			TYPE_ICP_MULTI,	// Card type = ICP MULTI
+-			16,	// Num of A/D channels
+-			8,	// Num of A/D channels in diff mode
+-			4,	// Num of D/A channels
+-			16,	// Num of digital inputs
+-			8,	// Num of digital outputs
+-			4,	// Num of counters
+-			0x0fff,	// Resolution of A/D
+-			0x0fff,	// Resolution of D/A
+-			&range_analog,	// Rangelist for A/D
+-			range_codes_analog,	// Range codes for programming
+-		&range_analog},	// Rangelist for D/A
++	{"icp_multi",		/*  Driver name */
++			DEVICE_ID,	/*  PCI device ID */
++			IORANGE_ICP_MULTI,	/*  I/O range length */
++			1,	/*  1=Card supports interrupts */
++			TYPE_ICP_MULTI,	/*  Card type = ICP MULTI */
++			16,	/*  Num of A/D channels */
++			8,	/*  Num of A/D channels in diff mode */
++			4,	/*  Num of D/A channels */
++			16,	/*  Num of digital inputs */
++			8,	/*  Num of digital outputs */
++			4,	/*  Num of counters */
++			0x0fff,	/*  Resolution of A/D */
++			0x0fff,	/*  Resolution of D/A */
++			&range_analog,	/*  Rangelist for A/D */
++			range_codes_analog,	/*  Range codes for programming */
++		&range_analog},	/*  Rangelist for D/A */
+ };
+ 
+ #define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+@@ -186,22 +186,22 @@ static comedi_driver driver_icp_multi = {
+ COMEDI_INITCLEANUP(driver_icp_multi);
+ 
+ typedef struct {
+-	struct pcilst_struct *card;	// pointer to card
+-	char valid;		// card is usable
+-	void *io_addr;		// Pointer to mapped io address
+-	resource_size_t phys_iobase;	// Physical io address
+-	unsigned int AdcCmdStatus;	// ADC Command/Status register
+-	unsigned int DacCmdStatus;	// DAC Command/Status register
+-	unsigned int IntEnable;	// Interrupt Enable register
+-	unsigned int IntStatus;	// Interrupt Status register
+-	unsigned int act_chanlist[32];	// list of scaned channel
+-	unsigned char act_chanlist_len;	// len of scanlist
+-	unsigned char act_chanlist_pos;	// actual position in MUX list
+-	unsigned int *ai_chanlist;	// actaul chanlist
+-	sampl_t *ai_data;	// data buffer
+-	sampl_t ao_data[4];	// data output buffer
+-	sampl_t di_data;	// Digital input data
+-	unsigned int do_data;	// Remember digital output data
++	struct pcilst_struct *card;	/*  pointer to card */
++	char valid;		/*  card is usable */
++	void *io_addr;		/*  Pointer to mapped io address */
++	resource_size_t phys_iobase;	/*  Physical io address */
++	unsigned int AdcCmdStatus;	/*  ADC Command/Status register */
++	unsigned int DacCmdStatus;	/*  DAC Command/Status register */
++	unsigned int IntEnable;	/*  Interrupt Enable register */
++	unsigned int IntStatus;	/*  Interrupt Status register */
++	unsigned int act_chanlist[32];	/*  list of scaned channel */
++	unsigned char act_chanlist_len;	/*  len of scanlist */
++	unsigned char act_chanlist_pos;	/*  actual position in MUX list */
++	unsigned int *ai_chanlist;	/*  actaul chanlist */
++	sampl_t *ai_data;	/*  data buffer */
++	sampl_t ao_data[4];	/*  data output buffer */
++	sampl_t di_data;	/*  Digital input data */
++	unsigned int do_data;	/*  Remember digital output data */
+ } icp_multi_private;
+ 
+ #define devpriv ((icp_multi_private *)dev->private)
+@@ -253,15 +253,15 @@ static int icp_multi_insn_read_ai(comedi_device * dev, comedi_subdevice * s,
+ #ifdef ICP_MULTI_EXTDEBUG
+ 	printk("icp multi EDBG: BGN: icp_multi_insn_read_ai(...)\n");
+ #endif
+-	// Disable A/D conversion ready interrupt
++	/*  Disable A/D conversion ready interrupt */
+ 	devpriv->IntEnable &= ~ADC_READY;
+ 	writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN);
+ 
+-	// Clear interrupt status
++	/*  Clear interrupt status */
+ 	devpriv->IntStatus |= ADC_READY;
+ 	writew(devpriv->IntStatus, devpriv->io_addr + ICP_MULTI_INT_STAT);
+ 
+-	// Set up appropriate channel, mode and range data, for specified channel
++	/*  Set up appropriate channel, mode and range data, for specified channel */
+ 	setup_channel_list(dev, s, &insn->chanspec, 1);
+ 
+ #ifdef ICP_MULTI_EXTDEBUG
+@@ -271,7 +271,7 @@ static int icp_multi_insn_read_ai(comedi_device * dev, comedi_subdevice * s,
+ #endif
+ 
+ 	for (n = 0; n < insn->n; n++) {
+-		// Set start ADC bit
++		/*  Set start ADC bit */
+ 		devpriv->AdcCmdStatus |= ADC_ST;
+ 		writew(devpriv->AdcCmdStatus,
+ 			devpriv->io_addr + ICP_MULTI_ADC_CSR);
+@@ -289,7 +289,7 @@ static int icp_multi_insn_read_ai(comedi_device * dev, comedi_subdevice * s,
+ 			readw(devpriv->io_addr + ICP_MULTI_ADC_CSR));
+ #endif
+ 
+-		// Wait for conversion to complete, or get fed up waiting
++		/*  Wait for conversion to complete, or get fed up waiting */
+ 		timeout = 100;
+ 		while (timeout--) {
+ 			if (!(readw(devpriv->io_addr +
+@@ -307,19 +307,19 @@ static int icp_multi_insn_read_ai(comedi_device * dev, comedi_subdevice * s,
+ 			comedi_udelay(1);
+ 		}
+ 
+-		// If we reach here, a timeout has occurred
++		/*  If we reach here, a timeout has occurred */
+ 		comedi_error(dev, "A/D insn timeout");
+ 
+-		// Disable interrupt
++		/*  Disable interrupt */
+ 		devpriv->IntEnable &= ~ADC_READY;
+ 		writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN);
+ 
+-		// Clear interrupt status
++		/*  Clear interrupt status */
+ 		devpriv->IntStatus |= ADC_READY;
+ 		writew(devpriv->IntStatus,
+ 			devpriv->io_addr + ICP_MULTI_INT_STAT);
+ 
+-		// Clear data received
++		/*  Clear data received */
+ 		data[n] = 0;
+ 
+ #ifdef ICP_MULTI_EXTDEBUG
+@@ -332,11 +332,11 @@ static int icp_multi_insn_read_ai(comedi_device * dev, comedi_subdevice * s,
+ 			(readw(devpriv->io_addr + ICP_MULTI_AI) >> 4) & 0x0fff;
+ 	}
+ 
+-	// Disable interrupt
++	/*  Disable interrupt */
+ 	devpriv->IntEnable &= ~ADC_READY;
+ 	writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN);
+ 
+-	// Clear interrupt status
++	/*  Clear interrupt status */
+ 	devpriv->IntStatus |= ADC_READY;
+ 	writew(devpriv->IntStatus, devpriv->io_addr + ICP_MULTI_INT_STAT);
+ 
+@@ -372,23 +372,23 @@ static int icp_multi_insn_write_ao(comedi_device * dev, comedi_subdevice * s,
+ #ifdef ICP_MULTI_EXTDEBUG
+ 	printk("icp multi EDBG: BGN: icp_multi_insn_write_ao(...)\n");
+ #endif
+-	// Disable D/A conversion ready interrupt
++	/*  Disable D/A conversion ready interrupt */
+ 	devpriv->IntEnable &= ~DAC_READY;
+ 	writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN);
+ 
+-	// Clear interrupt status
++	/*  Clear interrupt status */
+ 	devpriv->IntStatus |= DAC_READY;
+ 	writew(devpriv->IntStatus, devpriv->io_addr + ICP_MULTI_INT_STAT);
+ 
+-	// Get channel number and range
++	/*  Get channel number and range */
+ 	chan = CR_CHAN(insn->chanspec);
+ 	range = CR_RANGE(insn->chanspec);
+ 
+-	// Set up range and channel data
+-	// Bit 4 = 1 : Bipolar
+-	// Bit 5 = 0 : 5V
+-	// Bit 5 = 1 : 10V
+-	// Bits 8-9 : Channel number
++	/*  Set up range and channel data */
++	/*  Bit 4 = 1 : Bipolar */
++	/*  Bit 5 = 0 : 5V */
++	/*  Bit 5 = 1 : 10V */
++	/*  Bits 8-9 : Channel number */
+ 	devpriv->DacCmdStatus &= 0xfccf;
+ 	devpriv->DacCmdStatus |= this_board->rangecode[range];
+ 	devpriv->DacCmdStatus |= (chan << 8);
+@@ -396,7 +396,7 @@ static int icp_multi_insn_write_ao(comedi_device * dev, comedi_subdevice * s,
+ 	writew(devpriv->DacCmdStatus, devpriv->io_addr + ICP_MULTI_DAC_CSR);
+ 
+ 	for (n = 0; n < insn->n; n++) {
+-		// Wait for analogue output data register to be ready for new data, or get fed up waiting
++		/*  Wait for analogue output data register to be ready for new data, or get fed up waiting */
+ 		timeout = 100;
+ 		while (timeout--) {
+ 			if (!(readw(devpriv->io_addr +
+@@ -414,19 +414,19 @@ static int icp_multi_insn_write_ao(comedi_device * dev, comedi_subdevice * s,
+ 			comedi_udelay(1);
+ 		}
+ 
+-		// If we reach here, a timeout has occurred
++		/*  If we reach here, a timeout has occurred */
+ 		comedi_error(dev, "D/A insn timeout");
+ 
+-		// Disable interrupt
++		/*  Disable interrupt */
+ 		devpriv->IntEnable &= ~DAC_READY;
+ 		writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN);
+ 
+-		// Clear interrupt status
++		/*  Clear interrupt status */
+ 		devpriv->IntStatus |= DAC_READY;
+ 		writew(devpriv->IntStatus,
+ 			devpriv->io_addr + ICP_MULTI_INT_STAT);
+ 
+-		// Clear data received
++		/*  Clear data received */
+ 		devpriv->ao_data[chan] = 0;
+ 
+ #ifdef ICP_MULTI_EXTDEBUG
+@@ -435,16 +435,16 @@ static int icp_multi_insn_write_ao(comedi_device * dev, comedi_subdevice * s,
+ 		return -ETIME;
+ 
+ 	      dac_ready:
+-		// Write data to analogue output data register
++		/*  Write data to analogue output data register */
+ 		writew(data[n], devpriv->io_addr + ICP_MULTI_AO);
+ 
+-		// Set DAC_ST bit to write the data to selected channel
++		/*  Set DAC_ST bit to write the data to selected channel */
+ 		devpriv->DacCmdStatus |= DAC_ST;
+ 		writew(devpriv->DacCmdStatus,
+ 			devpriv->io_addr + ICP_MULTI_DAC_CSR);
+ 		devpriv->DacCmdStatus &= ~DAC_ST;
+ 
+-		// Save analogue output data
++		/*  Save analogue output data */
+ 		devpriv->ao_data[chan] = data[n];
+ 	}
+ 
+@@ -477,10 +477,10 @@ static int icp_multi_insn_read_ao(comedi_device * dev, comedi_subdevice * s,
+ {
+ 	int n, chan;
+ 
+-	// Get channel number
++	/*  Get channel number */
+ 	chan = CR_CHAN(insn->chanspec);
+ 
+-	// Read analogue outputs
++	/*  Read analogue outputs */
+ 	for (n = 0; n < insn->n; n++)
+ 		data[n] = devpriv->ao_data[chan];
+ 
+@@ -628,10 +628,10 @@ static irqreturn_t interrupt_service_icp_multi(int irq, void *d PT_REGS_ARG)
+ 		irq);
+ #endif
+ 
+-	// Is this interrupt from our board?
++	/*  Is this interrupt from our board? */
+ 	int_no = readw(devpriv->io_addr + ICP_MULTI_INT_STAT) & Status_IRQ;
+ 	if (!int_no)
+-		// No, exit
++		/*  No, exit */
+ 		return IRQ_NONE;
+ 
+ #ifdef ICP_MULTI_EXTDEBUG
+@@ -639,7 +639,7 @@ static irqreturn_t interrupt_service_icp_multi(int irq, void *d PT_REGS_ARG)
+ 		readw(devpriv->io_addr + ICP_MULTI_INT_STAT));
+ #endif
+ 
+-	// Determine which interrupt is active & handle it
++	/*  Determine which interrupt is active & handle it */
+ 	switch (int_no) {
+ 	case ADC_READY:
+ 		break;
+@@ -697,14 +697,14 @@ static int check_channel_list(comedi_device * dev, comedi_subdevice * s,
+ #ifdef ICP_MULTI_EXTDEBUG
+ 	printk("icp multi EDBG:  check_channel_list(...,%d)\n", n_chan);
+ #endif
+-	// Check that we at least have one channel to check
++	/*  Check that we at least have one channel to check */
+ 	if (n_chan < 1) {
+ 		comedi_error(dev, "range/channel list is empty!");
+ 		return 0;
+ 	}
+-	// Check all channels
++	/*  Check all channels */
+ 	for (i = 0; i < n_chan; i++) {
+-		// Check that channel number is < maximum
++		/*  Check that channel number is < maximum */
+ 		if (CR_AREF(chanlist[i]) == AREF_DIFF) {
+ 			if (CR_CHAN(chanlist[i]) > this_board->n_aichand) {
+ 				comedi_error(dev,
+@@ -756,10 +756,10 @@ static void setup_channel_list(comedi_device * dev, comedi_subdevice * s,
+ 	devpriv->act_chanlist_pos = 0;
+ 
+ 	for (i = 0; i < n_chan; i++) {
+-		// Get channel
++		/*  Get channel */
+ 		chanprog = CR_CHAN(chanlist[i]);
+ 
+-		// Determine if it is a differential channel (Bit 15  = 1)
++		/*  Determine if it is a differential channel (Bit 15  = 1) */
+ 		if (CR_AREF(chanlist[i]) == AREF_DIFF) {
+ 			diff = 1;
+ 			chanprog &= 0x0007;
+@@ -768,21 +768,21 @@ static void setup_channel_list(comedi_device * dev, comedi_subdevice * s,
+ 			chanprog &= 0x000f;
+ 		}
+ 
+-		// Clear channel, range and input mode bits in A/D command/status register
++		/*  Clear channel, range and input mode bits in A/D command/status register */
+ 		devpriv->AdcCmdStatus &= 0xf00f;
+ 
+-		// Set channel number and differential mode status bit
++		/*  Set channel number and differential mode status bit */
+ 		if (diff) {
+-			// Set channel number, bits 9-11 & mode, bit 6
++			/*  Set channel number, bits 9-11 & mode, bit 6 */
+ 			devpriv->AdcCmdStatus |= (chanprog << 9);
+ 			devpriv->AdcCmdStatus |= ADC_DI;
+ 		} else
+-			// Set channel number, bits 8-11
++			/*  Set channel number, bits 8-11 */
+ 			devpriv->AdcCmdStatus |= (chanprog << 8);
+ 
+-		// Get range for current channel
++		/*  Get range for current channel */
+ 		range = this_board->rangecode[CR_RANGE(chanlist[i])];
+-		// Set range. bits 4-5
++		/*  Set range. bits 4-5 */
+ 		devpriv->AdcCmdStatus |= range;
+ 
+ 		/* Output channel, range, mode to ICP Multi */
+@@ -819,32 +819,32 @@ static int icp_multi_reset(comedi_device * dev)
+ #ifdef ICP_MULTI_EXTDEBUG
+ 	printk("icp_multi EDBG: BGN: icp_multi_reset(...)\n");
+ #endif
+-	// Clear INT enables and requests
++	/*  Clear INT enables and requests */
+ 	writew(0, devpriv->io_addr + ICP_MULTI_INT_EN);
+ 	writew(0x00ff, devpriv->io_addr + ICP_MULTI_INT_STAT);
+ 
+ 	if (this_board->n_aochan)
+-		// Set DACs to 0..5V range and 0V output
++		/*  Set DACs to 0..5V range and 0V output */
+ 		for (i = 0; i < this_board->n_aochan; i++) {
+ 			devpriv->DacCmdStatus &= 0xfcce;
+ 
+-			// Set channel number
++			/*  Set channel number */
+ 			devpriv->DacCmdStatus |= (i << 8);
+ 
+-			// Output 0V
++			/*  Output 0V */
+ 			writew(0, devpriv->io_addr + ICP_MULTI_AO);
+ 
+-			// Set start conversion bit
++			/*  Set start conversion bit */
+ 			devpriv->DacCmdStatus |= DAC_ST;
+ 
+-			// Output to command / status register
++			/*  Output to command / status register */
+ 			writew(devpriv->DacCmdStatus,
+ 				devpriv->io_addr + ICP_MULTI_DAC_CSR);
+ 
+-			// Delay to allow DAC time to recover
++			/*  Delay to allow DAC time to recover */
+ 			comedi_udelay(1);
+ 		}
+-	// Digital outputs to 0
++	/*  Digital outputs to 0 */
+ 	writew(0, devpriv->io_addr + ICP_MULTI_DO);
+ 
+ #ifdef ICP_MULTI_EXTDEBUG
+@@ -881,11 +881,11 @@ static int icp_multi_attach(comedi_device * dev, comedi_devconfig * it)
+ 
+ 	printk("icp_multi EDBG: BGN: icp_multi_attach(...)\n");
+ 
+-	// Alocate private data storage space
++	/*  Alocate private data storage space */
+ 	if ((ret = alloc_private(dev, sizeof(icp_multi_private))) < 0)
+ 		return ret;
+ 
+-	// Initialise list of PCI cards in system, if not already done so
++	/*  Initialise list of PCI cards in system, if not already done so */
+ 	if (pci_list_builded++ == 0) {
+ 		pci_card_list_init(PCI_VENDOR_ID_ICP,
+ #ifdef ICP_MULTI_EXTDEBUG
+diff --git a/drivers/staging/comedi/drivers/icp_multi.h b/drivers/staging/comedi/drivers/icp_multi.h
+index 6df4a8d15ff2..c0abc1062b8d 100644
+--- a/drivers/staging/comedi/drivers/icp_multi.h
++++ b/drivers/staging/comedi/drivers/icp_multi.h
+@@ -28,7 +28,8 @@ struct pcilst_struct {
+ 	unsigned int irq;
+ };
+ 
+-struct pcilst_struct *inova_devices;	// ptr to root list of all Inova devices
++struct pcilst_struct *inova_devices;
++/* ptr to root list of all Inova devices */
+ 
+ /****************************************************************************/
+ 
+@@ -150,14 +151,14 @@ static int find_free_pci_card_by_position(unsigned short vendor_id,
+ 			&& (inova->pci_slot == pci_slot)) {
+ 			if (!(inova->used)) {
+ 				*card = inova;
+-				return 0;	// ok, card is found
++				return 0;	/* ok, card is found */
+ 			} else {
+-				return 2;	// card exist but is used
++				return 2;	/* card exist but is used */
+ 			}
+ 		}
+ 	}
+ 
+-	return 1;		// no card found
++	return 1;		/* no card found */
+ }
+ 
+ /****************************************************************************/
+@@ -243,7 +244,7 @@ static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id,
+ 	struct pcilst_struct *card;
+ 	int err;
+ 
+-	if ((pci_bus < 1) & (pci_slot < 1)) {	// use autodetection
++	if ((pci_bus < 1) & (pci_slot < 1)) {	/* use autodetection */
+ 		if ((card = find_free_pci_card_by_device(vendor_id,
+ 					device_id)) == NULL) {
+ 			rt_printk(" - Unused card not found in system!\n");
+diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
+index cc29315ecad4..2608c8713c90 100644
+--- a/drivers/staging/comedi/drivers/me4000.c
++++ b/drivers/staging/comedi/drivers/me4000.c
+@@ -277,7 +277,7 @@ static int me4000_attach(comedi_device * dev, comedi_devconfig * it)
+ 		s->subdev_flags =
+ 			SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
+ 		s->n_chan = thisboard->ai.count;
+-		s->maxdata = 0xFFFF;	// 16 bit ADC
++		s->maxdata = 0xFFFF;	/*  16 bit ADC */
+ 		s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT;
+ 		s->range_table = &me4000_ai_range;
+ 		s->insn_read = me4000_ai_insn_read;
+@@ -312,7 +312,7 @@ static int me4000_attach(comedi_device * dev, comedi_devconfig * it)
+ 		s->type = COMEDI_SUBD_AO;
+ 		s->subdev_flags = SDF_WRITEABLE | SDF_COMMON | SDF_GROUND;
+ 		s->n_chan = thisboard->ao.count;
+-		s->maxdata = 0xFFFF;	// 16 bit DAC
++		s->maxdata = 0xFFFF;	/*  16 bit DAC */
+ 		s->range_table = &me4000_ao_range;
+ 		s->insn_write = me4000_ao_insn_write;
+ 		s->insn_read = me4000_ao_insn_read;
+@@ -358,7 +358,7 @@ static int me4000_attach(comedi_device * dev, comedi_devconfig * it)
+ 		s->type = COMEDI_SUBD_COUNTER;
+ 		s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ 		s->n_chan = thisboard->cnt.count;
+-		s->maxdata = 0xFFFF;	// 16 bit counters
++		s->maxdata = 0xFFFF;	/*  16 bit counters */
+ 		s->insn_read = me4000_cnt_insn_read;
+ 		s->insn_write = me4000_cnt_insn_write;
+ 		s->insn_config = me4000_cnt_insn_config;
+@@ -571,8 +571,8 @@ static int init_board_info(comedi_device * dev, struct pci_dev *pci_dev_p)
+ 	CALL_PDEBUG("In init_board_info()\n");
+ 
+ 	/* Init spin locks */
+-	//spin_lock_init(&info->preload_lock);
+-	//spin_lock_init(&info->ai_ctrl_lock);
++	/* spin_lock_init(&info->preload_lock); */
++	/* spin_lock_init(&info->ai_ctrl_lock); */
+ 
+ 	/* Get the serial number */
+ 	result = pci_read_config_dword(pci_dev_p, 0x2C, &info->serial_no);
+@@ -605,7 +605,7 @@ static int init_ao_context(comedi_device * dev)
+ 	CALL_PDEBUG("In init_ao_context()\n");
+ 
+ 	for (i = 0; i < thisboard->ao.count; i++) {
+-		//spin_lock_init(&info->ao_context[i].use_lock);
++		/* spin_lock_init(&info->ao_context[i].use_lock); */
+ 		info->ao_context[i].irq = info->irq;
+ 
+ 		switch (i) {
+@@ -1604,21 +1604,21 @@ static int me4000_ai_do_cmd_test(comedi_device * dev,
+ 			printk(KERN_ERR
+ 				"comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
+ 				dev->minor);
+-			cmd->start_arg = 2000;	// 66 ticks at least
++			cmd->start_arg = 2000;	/*  66 ticks at least */
+ 			err++;
+ 		}
+ 		if (chan_ticks < ME4000_AI_MIN_TICKS) {
+ 			printk(KERN_ERR
+ 				"comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n",
+ 				dev->minor);
+-			cmd->convert_arg = 2000;	// 66 ticks at least
++			cmd->convert_arg = 2000;	/*  66 ticks at least */
+ 			err++;
+ 		}
+ 		if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
+ 			printk(KERN_ERR
+ 				"comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan end arg\n",
+ 				dev->minor);
+-			cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;	// At least one tick more
++			cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;	/*  At least one tick more */
+ 			err++;
+ 		}
+ 	} else if (cmd->start_src == TRIG_NOW &&
+@@ -1630,14 +1630,14 @@ static int me4000_ai_do_cmd_test(comedi_device * dev,
+ 			printk(KERN_ERR
+ 				"comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
+ 				dev->minor);
+-			cmd->start_arg = 2000;	// 66 ticks at least
++			cmd->start_arg = 2000;	/*  66 ticks at least */
+ 			err++;
+ 		}
+ 		if (chan_ticks < ME4000_AI_MIN_TICKS) {
+ 			printk(KERN_ERR
+ 				"comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n",
+ 				dev->minor);
+-			cmd->convert_arg = 2000;	// 66 ticks at least
++			cmd->convert_arg = 2000;	/*  66 ticks at least */
+ 			err++;
+ 		}
+ 	} else if (cmd->start_src == TRIG_EXT &&
+@@ -1649,21 +1649,21 @@ static int me4000_ai_do_cmd_test(comedi_device * dev,
+ 			printk(KERN_ERR
+ 				"comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
+ 				dev->minor);
+-			cmd->start_arg = 2000;	// 66 ticks at least
++			cmd->start_arg = 2000;	/*  66 ticks at least */
+ 			err++;
+ 		}
+ 		if (chan_ticks < ME4000_AI_MIN_TICKS) {
+ 			printk(KERN_ERR
+ 				"comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n",
+ 				dev->minor);
+-			cmd->convert_arg = 2000;	// 66 ticks at least
++			cmd->convert_arg = 2000;	/*  66 ticks at least */
+ 			err++;
+ 		}
+ 		if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
+ 			printk(KERN_ERR
+ 				"comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan end arg\n",
+ 				dev->minor);
+-			cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;	// At least one tick more
++			cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;	/*  At least one tick more */
+ 			err++;
+ 		}
+ 	} else if (cmd->start_src == TRIG_EXT &&
+@@ -1675,14 +1675,14 @@ static int me4000_ai_do_cmd_test(comedi_device * dev,
+ 			printk(KERN_ERR
+ 				"comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
+ 				dev->minor);
+-			cmd->start_arg = 2000;	// 66 ticks at least
++			cmd->start_arg = 2000;	/*  66 ticks at least */
+ 			err++;
+ 		}
+ 		if (chan_ticks < ME4000_AI_MIN_TICKS) {
+ 			printk(KERN_ERR
+ 				"comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n",
+ 				dev->minor);
+-			cmd->convert_arg = 2000;	// 66 ticks at least
++			cmd->convert_arg = 2000;	/*  66 ticks at least */
+ 			err++;
+ 		}
+ 	} else if (cmd->start_src == TRIG_EXT &&
+@@ -1694,14 +1694,14 @@ static int me4000_ai_do_cmd_test(comedi_device * dev,
+ 			printk(KERN_ERR
+ 				"comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
+ 				dev->minor);
+-			cmd->start_arg = 2000;	// 66 ticks at least
++			cmd->start_arg = 2000;	/*  66 ticks at least */
+ 			err++;
+ 		}
+ 		if (chan_ticks < ME4000_AI_MIN_TICKS) {
+ 			printk(KERN_ERR
+ 				"comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n",
+ 				dev->minor);
+-			cmd->convert_arg = 2000;	// 66 ticks at least
++			cmd->convert_arg = 2000;	/*  66 ticks at least */
+ 			err++;
+ 		}
+ 	} else if (cmd->start_src == TRIG_EXT &&
+@@ -1713,7 +1713,7 @@ static int me4000_ai_do_cmd_test(comedi_device * dev,
+ 			printk(KERN_ERR
+ 				"comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
+ 				dev->minor);
+-			cmd->start_arg = 2000;	// 66 ticks at least
++			cmd->start_arg = 2000;	/*  66 ticks at least */
+ 			err++;
+ 		}
+ 	}
+diff --git a/drivers/staging/comedi/drivers/me4000.h b/drivers/staging/comedi/drivers/me4000.h
+index f12b8873ec3c..37af3a80263a 100644
+--- a/drivers/staging/comedi/drivers/me4000.h
++++ b/drivers/staging/comedi/drivers/me4000.h
+@@ -28,37 +28,37 @@
+   Debug section
+   ===========================================================================*/
+ 
+-#undef ME4000_CALL_DEBUG	// Debug function entry and exit
+-#undef ME4000_PORT_DEBUG	// Debug port access
+-#undef ME4000_ISR_DEBUG		// Debug the interrupt service routine
+-#undef ME4000_DEBUG		// General purpose debug masseges
++#undef ME4000_CALL_DEBUG	/*  Debug function entry and exit */
++#undef ME4000_PORT_DEBUG	/*  Debug port access */
++#undef ME4000_ISR_DEBUG		/*  Debug the interrupt service routine */
++#undef ME4000_DEBUG		/*  General purpose debug masseges */
+ 
+ #ifdef ME4000_CALL_DEBUG
+ #undef CALL_PDEBUG
+ #define CALL_PDEBUG(fmt, args...) printk(KERN_DEBUG"comedi%d: me4000: " fmt, dev->minor, ##args)
+ #else
+-# define CALL_PDEBUG(fmt, args...)	// no debugging, do nothing
++# define CALL_PDEBUG(fmt, args...)	/*  no debugging, do nothing */
+ #endif
+ 
+ #ifdef ME4000_PORT_DEBUG
+ #undef PORT_PDEBUG
+ #define PORT_PDEBUG(fmt, args...) printk(KERN_DEBUG"comedi%d: me4000: " fmt, dev->minor,  ##args)
+ #else
+-#define PORT_PDEBUG(fmt, args...)	// no debugging, do nothing
++#define PORT_PDEBUG(fmt, args...)	/*  no debugging, do nothing */
+ #endif
+ 
+ #ifdef ME4000_ISR_DEBUG
+ #undef ISR_PDEBUG
+ #define ISR_PDEBUG(fmt, args...) printk(KERN_DEBUG"comedi%d: me4000: " fmt, dev->minor,  ##args)
+ #else
+-#define ISR_PDEBUG(fmt, args...)	// no debugging, do nothing
++#define ISR_PDEBUG(fmt, args...)	/*  no debugging, do nothing */
+ #endif
+ 
+ #ifdef ME4000_DEBUG
+ #undef PDEBUG
+ #define PDEBUG(fmt, args...) printk(KERN_DEBUG"comedi%d: me4000: " fmt, dev->minor,  ##args)
+ #else
+-#define PDEBUG(fmt, args...)	// no debugging, do nothing
++#define PDEBUG(fmt, args...)	/*  no debugging, do nothing */
+ #endif
+ 
+ /*=============================================================================
+@@ -67,78 +67,78 @@
+ 
+ #define PCI_VENDOR_ID_MEILHAUS 0x1402
+ 
+-#define PCI_DEVICE_ID_MEILHAUS_ME4650	0x4650	// Low Cost version
++#define PCI_DEVICE_ID_MEILHAUS_ME4650	0x4650	/*  Low Cost version */
+ 
+-#define PCI_DEVICE_ID_MEILHAUS_ME4660	0x4660	// Standard version
+-#define PCI_DEVICE_ID_MEILHAUS_ME4660I	0x4661	// Isolated version
+-#define PCI_DEVICE_ID_MEILHAUS_ME4660S	0x4662	// Standard version with Sample and Hold
+-#define PCI_DEVICE_ID_MEILHAUS_ME4660IS	0x4663	// Isolated version with Sample and Hold
++#define PCI_DEVICE_ID_MEILHAUS_ME4660	0x4660	/*  Standard version */
++#define PCI_DEVICE_ID_MEILHAUS_ME4660I	0x4661	/*  Isolated version */
++#define PCI_DEVICE_ID_MEILHAUS_ME4660S	0x4662	/*  Standard version with Sample and Hold */
++#define PCI_DEVICE_ID_MEILHAUS_ME4660IS	0x4663	/*  Isolated version with Sample and Hold */
+ 
+-#define PCI_DEVICE_ID_MEILHAUS_ME4670	0x4670	// Standard version
+-#define PCI_DEVICE_ID_MEILHAUS_ME4670I	0x4671	// Isolated version
+-#define PCI_DEVICE_ID_MEILHAUS_ME4670S	0x4672	// Standard version with Sample and Hold
+-#define PCI_DEVICE_ID_MEILHAUS_ME4670IS	0x4673	// Isolated version with Sample and Hold
++#define PCI_DEVICE_ID_MEILHAUS_ME4670	0x4670	/*  Standard version */
++#define PCI_DEVICE_ID_MEILHAUS_ME4670I	0x4671	/*  Isolated version */
++#define PCI_DEVICE_ID_MEILHAUS_ME4670S	0x4672	/*  Standard version with Sample and Hold */
++#define PCI_DEVICE_ID_MEILHAUS_ME4670IS	0x4673	/*  Isolated version with Sample and Hold */
+ 
+-#define PCI_DEVICE_ID_MEILHAUS_ME4680	0x4680	// Standard version
+-#define PCI_DEVICE_ID_MEILHAUS_ME4680I	0x4681	// Isolated version
+-#define PCI_DEVICE_ID_MEILHAUS_ME4680S	0x4682	// Standard version with Sample and Hold
+-#define PCI_DEVICE_ID_MEILHAUS_ME4680IS	0x4683	// Isolated version with Sample and Hold
++#define PCI_DEVICE_ID_MEILHAUS_ME4680	0x4680	/*  Standard version */
++#define PCI_DEVICE_ID_MEILHAUS_ME4680I	0x4681	/*  Isolated version */
++#define PCI_DEVICE_ID_MEILHAUS_ME4680S	0x4682	/*  Standard version with Sample and Hold */
++#define PCI_DEVICE_ID_MEILHAUS_ME4680IS	0x4683	/*  Isolated version with Sample and Hold */
+ 
+ /*=============================================================================
+   ME-4000 base register offsets
+   ===========================================================================*/
+ 
+-#define ME4000_AO_00_CTRL_REG			0x00	// R/W
+-#define ME4000_AO_00_STATUS_REG			0x04	// R/_
+-#define ME4000_AO_00_FIFO_REG			0x08	// _/W
+-#define ME4000_AO_00_SINGLE_REG			0x0C	// R/W
+-#define ME4000_AO_00_TIMER_REG			0x10	// _/W
+-
+-#define ME4000_AO_01_CTRL_REG			0x18	// R/W
+-#define ME4000_AO_01_STATUS_REG			0x1C	// R/_
+-#define ME4000_AO_01_FIFO_REG			0x20	// _/W
+-#define ME4000_AO_01_SINGLE_REG			0x24	// R/W
+-#define ME4000_AO_01_TIMER_REG			0x28	// _/W
+-
+-#define ME4000_AO_02_CTRL_REG			0x30	// R/W
+-#define ME4000_AO_02_STATUS_REG			0x34	// R/_
+-#define ME4000_AO_02_FIFO_REG			0x38	// _/W
+-#define ME4000_AO_02_SINGLE_REG			0x3C	// R/W
+-#define ME4000_AO_02_TIMER_REG			0x40	// _/W
+-
+-#define ME4000_AO_03_CTRL_REG			0x48	// R/W
+-#define ME4000_AO_03_STATUS_REG			0x4C	// R/_
+-#define ME4000_AO_03_FIFO_REG			0x50	// _/W
+-#define ME4000_AO_03_SINGLE_REG			0x54	// R/W
+-#define ME4000_AO_03_TIMER_REG			0x58	// _/W
+-
+-#define ME4000_AI_CTRL_REG			0x74	// _/W
+-#define ME4000_AI_STATUS_REG			0x74	// R/_
+-#define ME4000_AI_CHANNEL_LIST_REG		0x78	// _/W
+-#define ME4000_AI_DATA_REG			0x7C	// R/_
+-#define ME4000_AI_CHAN_TIMER_REG		0x80	// _/W
+-#define ME4000_AI_CHAN_PRE_TIMER_REG		0x84	// _/W
+-#define ME4000_AI_SCAN_TIMER_LOW_REG		0x88	// _/W
+-#define ME4000_AI_SCAN_TIMER_HIGH_REG		0x8C	// _/W
+-#define ME4000_AI_SCAN_PRE_TIMER_LOW_REG	0x90	// _/W
+-#define ME4000_AI_SCAN_PRE_TIMER_HIGH_REG	0x94	// _/W
+-#define ME4000_AI_START_REG			0x98	// R/_
+-
+-#define ME4000_IRQ_STATUS_REG			0x9C	// R/_
+-
+-#define ME4000_DIO_PORT_0_REG			0xA0	// R/W
+-#define ME4000_DIO_PORT_1_REG			0xA4	// R/W
+-#define ME4000_DIO_PORT_2_REG			0xA8	// R/W
+-#define ME4000_DIO_PORT_3_REG			0xAC	// R/W
+-#define ME4000_DIO_DIR_REG			0xB0	// R/W
+-
+-#define ME4000_AO_LOADSETREG_XX			0xB4	// R/W
+-
+-#define ME4000_DIO_CTRL_REG			0xB8	// R/W
+-
+-#define ME4000_AO_DEMUX_ADJUST_REG		0xBC	// -/W
+-
+-#define ME4000_AI_SAMPLE_COUNTER_REG		0xC0	// _/W
++#define ME4000_AO_00_CTRL_REG			0x00	/*  R/W */
++#define ME4000_AO_00_STATUS_REG			0x04	/*  R/_ */
++#define ME4000_AO_00_FIFO_REG			0x08	/*  _/W */
++#define ME4000_AO_00_SINGLE_REG			0x0C	/*  R/W */
++#define ME4000_AO_00_TIMER_REG			0x10	/*  _/W */
++
++#define ME4000_AO_01_CTRL_REG			0x18	/*  R/W */
++#define ME4000_AO_01_STATUS_REG			0x1C	/*  R/_ */
++#define ME4000_AO_01_FIFO_REG			0x20	/*  _/W */
++#define ME4000_AO_01_SINGLE_REG			0x24	/*  R/W */
++#define ME4000_AO_01_TIMER_REG			0x28	/*  _/W */
++
++#define ME4000_AO_02_CTRL_REG			0x30	/*  R/W */
++#define ME4000_AO_02_STATUS_REG			0x34	/*  R/_ */
++#define ME4000_AO_02_FIFO_REG			0x38	/*  _/W */
++#define ME4000_AO_02_SINGLE_REG			0x3C	/*  R/W */
++#define ME4000_AO_02_TIMER_REG			0x40	/*  _/W */
++
++#define ME4000_AO_03_CTRL_REG			0x48	/*  R/W */
++#define ME4000_AO_03_STATUS_REG			0x4C	/*  R/_ */
++#define ME4000_AO_03_FIFO_REG			0x50	/*  _/W */
++#define ME4000_AO_03_SINGLE_REG			0x54	/*  R/W */
++#define ME4000_AO_03_TIMER_REG			0x58	/*  _/W */
++
++#define ME4000_AI_CTRL_REG			0x74	/*  _/W */
++#define ME4000_AI_STATUS_REG			0x74	/*  R/_ */
++#define ME4000_AI_CHANNEL_LIST_REG		0x78	/*  _/W */
++#define ME4000_AI_DATA_REG			0x7C	/*  R/_ */
++#define ME4000_AI_CHAN_TIMER_REG		0x80	/*  _/W */
++#define ME4000_AI_CHAN_PRE_TIMER_REG		0x84	/*  _/W */
++#define ME4000_AI_SCAN_TIMER_LOW_REG		0x88	/*  _/W */
++#define ME4000_AI_SCAN_TIMER_HIGH_REG		0x8C	/*  _/W */
++#define ME4000_AI_SCAN_PRE_TIMER_LOW_REG	0x90	/*  _/W */
++#define ME4000_AI_SCAN_PRE_TIMER_HIGH_REG	0x94	/*  _/W */
++#define ME4000_AI_START_REG			0x98	/*  R/_ */
++
++#define ME4000_IRQ_STATUS_REG			0x9C	/*  R/_ */
++
++#define ME4000_DIO_PORT_0_REG			0xA0	/*  R/W */
++#define ME4000_DIO_PORT_1_REG			0xA4	/*  R/W */
++#define ME4000_DIO_PORT_2_REG			0xA8	/*  R/W */
++#define ME4000_DIO_PORT_3_REG			0xAC	/*  R/W */
++#define ME4000_DIO_DIR_REG			0xB0	/*  R/W */
++
++#define ME4000_AO_LOADSETREG_XX			0xB4	/*  R/W */
++
++#define ME4000_DIO_CTRL_REG			0xB8	/*  R/W */
++
++#define ME4000_AO_DEMUX_ADJUST_REG		0xBC	/*  -/W */
++
++#define ME4000_AI_SAMPLE_COUNTER_REG		0xC0	/*  _/W */
+ 
+ /*=============================================================================
+   Value to adjust Demux
+@@ -159,21 +159,21 @@
+   PLX base register offsets
+   ===========================================================================*/
+ 
+-#define PLX_INTCSR	0x4C	// Interrupt control and status register
+-#define PLX_ICR		0x50	// Initialization control register
++#define PLX_INTCSR	0x4C	/*  Interrupt control and status register */
++#define PLX_ICR		0x50	/*  Initialization control register */
+ 
+ /*=============================================================================
+   Bits for the PLX_ICSR register
+   ===========================================================================*/
+ 
+-#define PLX_INTCSR_LOCAL_INT1_EN             0x01	// If set, local interrupt 1 is enabled (r/w)
+-#define PLX_INTCSR_LOCAL_INT1_POL            0x02	// If set, local interrupt 1 polarity is active high (r/w)
+-#define PLX_INTCSR_LOCAL_INT1_STATE          0x04	// If set, local interrupt 1 is active (r/_)
+-#define PLX_INTCSR_LOCAL_INT2_EN             0x08	// If set, local interrupt 2 is enabled (r/w)
+-#define PLX_INTCSR_LOCAL_INT2_POL            0x10	// If set, local interrupt 2 polarity is active high (r/w)
+-#define PLX_INTCSR_LOCAL_INT2_STATE          0x20	// If set, local interrupt 2 is active  (r/_)
+-#define PLX_INTCSR_PCI_INT_EN                0x40	// If set, PCI interrupt is enabled (r/w)
+-#define PLX_INTCSR_SOFT_INT                  0x80	// If set, a software interrupt is generated (r/w)
++#define PLX_INTCSR_LOCAL_INT1_EN             0x01	/*  If set, local interrupt 1 is enabled (r/w) */
++#define PLX_INTCSR_LOCAL_INT1_POL            0x02	/*  If set, local interrupt 1 polarity is active high (r/w) */
++#define PLX_INTCSR_LOCAL_INT1_STATE          0x04	/*  If set, local interrupt 1 is active (r/_) */
++#define PLX_INTCSR_LOCAL_INT2_EN             0x08	/*  If set, local interrupt 2 is enabled (r/w) */
++#define PLX_INTCSR_LOCAL_INT2_POL            0x10	/*  If set, local interrupt 2 polarity is active high (r/w) */
++#define PLX_INTCSR_LOCAL_INT2_STATE          0x20	/*  If set, local interrupt 2 is active  (r/_) */
++#define PLX_INTCSR_PCI_INT_EN                0x40	/*  If set, PCI interrupt is enabled (r/w) */
++#define PLX_INTCSR_SOFT_INT                  0x80	/*  If set, a software interrupt is generated (r/w) */
+ 
+ /*=============================================================================
+   Bits for the PLX_ICR register
+@@ -331,7 +331,7 @@ typedef struct me4000_board {
+ typedef struct me4000_ao_context {
+ 	int irq;
+ 
+-	unsigned long mirror;	// Store the last written value
++	unsigned long mirror;	/*  Store the last written value */
+ 
+ 	unsigned long ctrl_reg;
+ 	unsigned long status_reg;
+@@ -377,29 +377,29 @@ typedef struct me4000_cnt_context {
+ } me4000_cnt_context_t;
+ 
+ typedef struct me4000_info {
+-	unsigned long plx_regbase;	// PLX configuration space base address
+-	unsigned long me4000_regbase;	// Base address of the ME4000
+-	unsigned long timer_regbase;	// Base address of the timer circuit
+-	unsigned long program_regbase;	// Base address to set the program pin for the xilinx
++	unsigned long plx_regbase;	/*  PLX configuration space base address */
++	unsigned long me4000_regbase;	/*  Base address of the ME4000 */
++	unsigned long timer_regbase;	/*  Base address of the timer circuit */
++	unsigned long program_regbase;	/*  Base address to set the program pin for the xilinx */
+ 
+-	unsigned long plx_regbase_size;	// PLX register set space
+-	unsigned long me4000_regbase_size;	// ME4000 register set space
+-	unsigned long timer_regbase_size;	// Timer circuit register set space
+-	unsigned long program_regbase_size;	// Size of program base address of the ME4000
++	unsigned long plx_regbase_size;	/*  PLX register set space */
++	unsigned long me4000_regbase_size;	/*  ME4000 register set space */
++	unsigned long timer_regbase_size;	/*  Timer circuit register set space */
++	unsigned long program_regbase_size;	/*  Size of program base address of the ME4000 */
+ 
+-	unsigned int serial_no;	// Serial number of the board
+-	unsigned char hw_revision;	// Hardware revision of the board
+-	unsigned short vendor_id;	// Meilhaus vendor id
+-	unsigned short device_id;	// Device id
++	unsigned int serial_no;	/*  Serial number of the board */
++	unsigned char hw_revision;	/*  Hardware revision of the board */
++	unsigned short vendor_id;	/*  Meilhaus vendor id */
++	unsigned short device_id;	/*  Device id */
+ 
+-	struct pci_dev *pci_dev_p;	// General PCI information
++	struct pci_dev *pci_dev_p;	/*  General PCI information */
+ 
+-	unsigned int irq;	// IRQ assigned from the PCI BIOS
++	unsigned int irq;	/*  IRQ assigned from the PCI BIOS */
+ 
+-	struct me4000_ai_context ai_context;	// Analog input  specific context
+-	struct me4000_ao_context ao_context[4];	// Vector with analog output specific context
+-	struct me4000_dio_context dio_context;	// Digital I/O specific context
+-	struct me4000_cnt_context cnt_context;	// Counter specific context
++	struct me4000_ai_context ai_context;	/*  Analog input  specific context */
++	struct me4000_ao_context ao_context[4];	/*  Vector with analog output specific context */
++	struct me4000_dio_context dio_context;	/*  Digital I/O specific context */
++	struct me4000_cnt_context cnt_context;	/*  Counter specific context */
+ } me4000_info_t;
+ 
+ #define info	((me4000_info_t *)dev->private)
+@@ -412,7 +412,7 @@ typedef struct me4000_info {
+ #define ME4000_AI_FIFO_COUNT			2048
+ 
+ #define ME4000_AI_MIN_TICKS			66
+-#define ME4000_AI_MIN_SAMPLE_TIME		2000	// Minimum sample time [ns]
++#define ME4000_AI_MIN_SAMPLE_TIME		2000	/*  Minimum sample time [ns] */
+ #define ME4000_AI_BASE_FREQUENCY		(unsigned int) 33E6
+ 
+ /* Channel list defines and masks */
+@@ -436,11 +436,11 @@ typedef struct me4000_info {
+ #define ME4000_CNT_COUNTER_1  0x40
+ #define ME4000_CNT_COUNTER_2  0x80
+ 
+-#define ME4000_CNT_MODE_0     0x00	// Change state if zero crossing
+-#define ME4000_CNT_MODE_1     0x02	// Retriggerable One-Shot
+-#define ME4000_CNT_MODE_2     0x04	// Asymmetrical divider
+-#define ME4000_CNT_MODE_3     0x06	// Symmetrical divider
+-#define ME4000_CNT_MODE_4     0x08	// Counter start by software trigger
+-#define ME4000_CNT_MODE_5     0x0A	// Counter start by hardware trigger
++#define ME4000_CNT_MODE_0     0x00	/*  Change state if zero crossing */
++#define ME4000_CNT_MODE_1     0x02	/*  Retriggerable One-Shot */
++#define ME4000_CNT_MODE_2     0x04	/*  Asymmetrical divider */
++#define ME4000_CNT_MODE_3     0x06	/*  Symmetrical divider */
++#define ME4000_CNT_MODE_4     0x08	/*  Counter start by software trigger */
++#define ME4000_CNT_MODE_5     0x0A	/*  Counter start by hardware trigger */
+ 
+ #endif
+diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c
+index 9cc527424d04..354ed8ddaffd 100644
+--- a/drivers/staging/comedi/drivers/mite.c
++++ b/drivers/staging/comedi/drivers/mite.c
+@@ -47,7 +47,7 @@
+ 
+ */
+ 
+-//#define USE_KMALLOC
++/* #define USE_KMALLOC */
+ 
+ #include "mite.h"
+ 
+@@ -139,7 +139,7 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1)
+ 	addr = pci_resource_start(mite->pcidev, 1);
+ 	mite->daq_phys_addr = addr;
+ 	length = pci_resource_len(mite->pcidev, 1);
+-	// In case of a 660x board, DAQ size is 8k instead of 4k (see as shown by lspci output)
++	/*  In case of a 660x board, DAQ size is 8k instead of 4k (see as shown by lspci output) */
+ 	mite->daq_io_addr = ioremap(mite->daq_phys_addr, length);
+ 	if (!mite->daq_io_addr) {
+ 		printk("failed to remap daq io memory address\n");
+@@ -212,7 +212,7 @@ void mite_cleanup(void)
+ 
+ void mite_unsetup(struct mite_struct *mite)
+ {
+-	//unsigned long offset, start, length;
++	/* unsigned long offset, start, length; */
+ 
+ 	if (!mite)
+ 		return;
+@@ -257,7 +257,7 @@ struct mite_channel *mite_request_channel_in_range(struct mite_struct *mite,
+ 	unsigned long flags;
+ 	struct mite_channel *channel = NULL;
+ 
+-	// spin lock so mite_release_channel can be called safely from interrupts
++	/*  spin lock so mite_release_channel can be called safely from interrupts */
+ 	comedi_spin_lock_irqsave(&mite->lock, flags);
+ 	for (i = min_channel; i <= max_channel; ++i) {
+ 		if (mite->channel_allocated[i] == 0) {
+@@ -276,7 +276,7 @@ void mite_release_channel(struct mite_channel *mite_chan)
+ 	struct mite_struct *mite = mite_chan->mite;
+ 	unsigned long flags;
+ 
+-	// spin lock to prevent races with mite_request_channel
++	/*  spin lock to prevent races with mite_request_channel */
+ 	comedi_spin_lock_irqsave(&mite->lock, flags);
+ 	if (mite->channel_allocated[mite_chan->channel]) {
+ 		mite_dma_disarm(mite_chan);
+@@ -312,7 +312,7 @@ void mite_dma_arm(struct mite_channel *mite_chan)
+ 	writel(chor, mite->mite_io_addr + MITE_CHOR(mite_chan->channel));
+ 	mmiowb();
+ 	comedi_spin_unlock_irqrestore(&mite->lock, flags);
+-//      mite_dma_tcr(mite, channel);
++/*       mite_dma_tcr(mite, channel); */
+ }
+ 
+ /**************************************/
+@@ -466,7 +466,7 @@ u32 mite_bytes_in_transit(struct mite_channel * mite_chan)
+ 		MITE_FCR(mite_chan->channel)) & 0x000000FF;
+ }
+ 
+-// returns lower bound for number of bytes transferred from device to memory
++/*  returns lower bound for number of bytes transferred from device to memory */
+ u32 mite_bytes_written_to_memory_lb(struct mite_channel * mite_chan)
+ {
+ 	u32 device_byte_count;
+@@ -475,7 +475,7 @@ u32 mite_bytes_written_to_memory_lb(struct mite_channel * mite_chan)
+ 	return device_byte_count - mite_bytes_in_transit(mite_chan);
+ }
+ 
+-// returns upper bound for number of bytes transferred from device to memory
++/*  returns upper bound for number of bytes transferred from device to memory */
+ u32 mite_bytes_written_to_memory_ub(struct mite_channel * mite_chan)
+ {
+ 	u32 in_transit_count;
+@@ -484,7 +484,7 @@ u32 mite_bytes_written_to_memory_ub(struct mite_channel * mite_chan)
+ 	return mite_device_bytes_transferred(mite_chan) - in_transit_count;
+ }
+ 
+-// returns lower bound for number of bytes read from memory for transfer to device
++/*  returns lower bound for number of bytes read from memory for transfer to device */
+ u32 mite_bytes_read_from_memory_lb(struct mite_channel * mite_chan)
+ {
+ 	u32 device_byte_count;
+@@ -493,7 +493,7 @@ u32 mite_bytes_read_from_memory_lb(struct mite_channel * mite_chan)
+ 	return device_byte_count + mite_bytes_in_transit(mite_chan);
+ }
+ 
+-// returns upper bound for number of bytes read from memory for transfer to device
++/*  returns upper bound for number of bytes read from memory for transfer to device */
+ u32 mite_bytes_read_from_memory_ub(struct mite_channel * mite_chan)
+ {
+ 	u32 in_transit_count;
+@@ -533,7 +533,7 @@ int mite_sync_input_dma(struct mite_channel *mite_chan, comedi_async * async)
+ 	const unsigned bytes_per_scan = cfc_bytes_per_scan(async->subdevice);
+ 
+ 	old_alloc_count = async->buf_write_alloc_count;
+-	// write alloc as much as we can
++	/*  write alloc as much as we can */
+ 	comedi_buf_write_alloc(async, async->prealloc_bufsz);
+ 
+ 	nbytes = mite_bytes_written_to_memory_lb(mite_chan);
+@@ -570,7 +570,7 @@ int mite_sync_output_dma(struct mite_channel *mite_chan, comedi_async * async)
+ 		async->cmd.stop_arg * cfc_bytes_per_scan(async->subdevice);
+ 
+ 	old_alloc_count = async->buf_read_alloc_count;
+-	// read alloc as much as we can
++	/*  read alloc as much as we can */
+ 	comedi_buf_read_alloc(async, async->prealloc_bufsz);
+ 	nbytes_lb = mite_bytes_read_from_memory_lb(mite_chan);
+ 	if (async->cmd.stop_src == TRIG_COUNT &&
+diff --git a/drivers/staging/comedi/drivers/mite.h b/drivers/staging/comedi/drivers/mite.h
+index b84eafa6ff2b..26c04c82293c 100644
+--- a/drivers/staging/comedi/drivers/mite.h
++++ b/drivers/staging/comedi/drivers/mite.h
+@@ -29,7 +29,7 @@
+ 
+ #define PCI_VENDOR_ID_NATINST		0x1093
+ 
+-// #define DEBUG_MITE
++/*  #define DEBUG_MITE */
+ #define PCIMIO_COMPAT
+ 
+ #ifdef DEBUG_MITE
+@@ -179,83 +179,83 @@ enum mite_registers {
+ 	   written and read back.  The bits 0x1f always read as 1.
+ 	   The rest always read as zero. */
+ 	MITE_UNKNOWN_DMA_BURST_REG = 0x28,
+-	MITE_IODWBSR = 0xc0,	//IO Device Window Base Size Register
+-	MITE_IODWBSR_1 = 0xc4,	// IO Device Window Base Size Register 1
++	MITE_IODWBSR = 0xc0,	/* IO Device Window Base Size Register */
++	MITE_IODWBSR_1 = 0xc4,	/*  IO Device Window Base Size Register 1 */
+ 	MITE_IODWCR_1 = 0xf4,
+ 	MITE_PCI_CONFIG_OFFSET = 0x300,
+-	MITE_CSIGR = 0x460	//chip signature
++	MITE_CSIGR = 0x460	/* chip signature */
+ };
+-static inline int MITE_CHOR(int channel)	// channel operation
++static inline int MITE_CHOR(int channel)	/*  channel operation */
+ {
+ 	return CHAN_OFFSET(channel) + 0x0;
+ };
+-static inline int MITE_CHCR(int channel)	// channel control
++static inline int MITE_CHCR(int channel)	/*  channel control */
+ {
+ 	return CHAN_OFFSET(channel) + 0x4;
+ };
+-static inline int MITE_TCR(int channel)	// transfer count
++static inline int MITE_TCR(int channel)	/*  transfer count */
+ {
+ 	return CHAN_OFFSET(channel) + 0x8;
+ };
+-static inline int MITE_MCR(int channel)	// memory configuration
++static inline int MITE_MCR(int channel)	/*  memory configuration */
+ {
+ 	return CHAN_OFFSET(channel) + 0xc;
+ };
+-static inline int MITE_MAR(int channel)	// memory address
++static inline int MITE_MAR(int channel)	/*  memory address */
+ {
+ 	return CHAN_OFFSET(channel) + 0x10;
+ };
+-static inline int MITE_DCR(int channel)	// device configuration
++static inline int MITE_DCR(int channel)	/*  device configuration */
+ {
+ 	return CHAN_OFFSET(channel) + 0x14;
+ };
+-static inline int MITE_DAR(int channel)	// device address
++static inline int MITE_DAR(int channel)	/*  device address */
+ {
+ 	return CHAN_OFFSET(channel) + 0x18;
+ };
+-static inline int MITE_LKCR(int channel)	// link configuration
++static inline int MITE_LKCR(int channel)	/*  link configuration */
+ {
+ 	return CHAN_OFFSET(channel) + 0x1c;
+ };
+-static inline int MITE_LKAR(int channel)	// link address
++static inline int MITE_LKAR(int channel)	/*  link address */
+ {
+ 	return CHAN_OFFSET(channel) + 0x20;
+ };
+-static inline int MITE_LLKAR(int channel)	// see mite section of tnt5002 manual
++static inline int MITE_LLKAR(int channel)	/*  see mite section of tnt5002 manual */
+ {
+ 	return CHAN_OFFSET(channel) + 0x24;
+ };
+-static inline int MITE_BAR(int channel)	// base address
++static inline int MITE_BAR(int channel)	/*  base address */
+ {
+ 	return CHAN_OFFSET(channel) + 0x28;
+ };
+-static inline int MITE_BCR(int channel)	// base count
++static inline int MITE_BCR(int channel)	/*  base count */
+ {
+ 	return CHAN_OFFSET(channel) + 0x2c;
+ };
+-static inline int MITE_SAR(int channel)	// ? address
++static inline int MITE_SAR(int channel)	/*  ? address */
+ {
+ 	return CHAN_OFFSET(channel) + 0x30;
+ };
+-static inline int MITE_WSCR(int channel)	// ?
++static inline int MITE_WSCR(int channel)	/*  ? */
+ {
+ 	return CHAN_OFFSET(channel) + 0x34;
+ };
+-static inline int MITE_WSER(int channel)	// ?
++static inline int MITE_WSER(int channel)	/*  ? */
+ {
+ 	return CHAN_OFFSET(channel) + 0x38;
+ };
+-static inline int MITE_CHSR(int channel)	// channel status
++static inline int MITE_CHSR(int channel)	/*  channel status */
+ {
+ 	return CHAN_OFFSET(channel) + 0x3c;
+ };
+-static inline int MITE_FCR(int channel)	// fifo count
++static inline int MITE_FCR(int channel)	/*  fifo count */
+ {
+ 	return CHAN_OFFSET(channel) + 0x40;
+ };
+ 
+ enum MITE_IODWBSR_bits {
+-	WENAB = 0x80,		// window enable
++	WENAB = 0x80,		/*  window enable */
+ };
+ 
+ static inline unsigned MITE_IODWBSR_1_WSIZE_bits(unsigned size)
+@@ -276,23 +276,23 @@ static inline int mite_csigr_version(u32 csigr_bits)
+ 	return csigr_bits & 0xf;
+ };
+ static inline int mite_csigr_type(u32 csigr_bits)
+-{				// original mite = 0, minimite = 1
++{				/*  original mite = 0, minimite = 1 */
+ 	return (csigr_bits >> 4) & 0xf;
+ };
+ static inline int mite_csigr_mmode(u32 csigr_bits)
+-{				// mite mode, minimite = 1
++{				/*  mite mode, minimite = 1 */
+ 	return (csigr_bits >> 8) & 0x3;
+ };
+ static inline int mite_csigr_imode(u32 csigr_bits)
+-{				// cpu port interface mode, pci = 0x3
++{				/*  cpu port interface mode, pci = 0x3 */
+ 	return (csigr_bits >> 12) & 0x3;
+ };
+ static inline int mite_csigr_dmac(u32 csigr_bits)
+-{				// number of dma channels
++{				/*  number of dma channels */
+ 	return (csigr_bits >> 16) & 0xf;
+ };
+ static inline int mite_csigr_wpdep(u32 csigr_bits)
+-{				// write post fifo depth
++{				/*  write post fifo depth */
+ 	unsigned int wpdep_bits = (csigr_bits >> 20) & 0x7;
+ 	if (wpdep_bits == 0)
+ 		return 0;
+@@ -304,7 +304,7 @@ static inline int mite_csigr_wins(u32 csigr_bits)
+ 	return (csigr_bits >> 24) & 0x1f;
+ };
+ static inline int mite_csigr_iowins(u32 csigr_bits)
+-{				// number of io windows
++{				/*  number of io windows */
+ 	return (csigr_bits >> 29) & 0x7;
+ };
+ 
+diff --git a/drivers/staging/comedi/drivers/plx9080.h b/drivers/staging/comedi/drivers/plx9080.h
+index a5a1a6808c5d..e53d3d429d7f 100644
+--- a/drivers/staging/comedi/drivers/plx9080.h
++++ b/drivers/staging/comedi/drivers/plx9080.h
+@@ -27,7 +27,7 @@
+ #ifndef __COMEDI_PLX9080_H
+ #define __COMEDI_PLX9080_H
+ 
+-// descriptor block used for chained dma transfers
++/*  descriptor block used for chained dma transfers */
+ struct plx_dma_desc {
+ 	volatile uint32_t pci_start_addr;
+ 	volatile uint32_t local_start_addr;
+@@ -52,14 +52,14 @@ struct plx_dma_desc {
+ #define  LRNG_ANY32        0x00000000	/* Locate anywhere in 32 bit */
+ #define  LRNG_LT1MB        0x00000002	/* Locate in 1st meg */
+ #define  LRNG_ANY64        0x00000004	/* Locate anywhere in 64 bit */
+-#define  LRNG_MEM_MASK     0xfffffff0	// bits that specify range for memory io
+-#define  LRNG_IO_MASK     0xfffffffa	// bits that specify range for normal io
++#define  LRNG_MEM_MASK     0xfffffff0	/*  bits that specify range for memory io */
++#define  LRNG_IO_MASK     0xfffffffa	/*  bits that specify range for normal io */
+ 
+ #define PLX_LAS0MAP_REG         0x0004	/* L, Local Addr Space 0 Remap Register */
+ #define PLX_LAS1MAP_REG         0x00f4	/* L, Local Addr Space 1 Remap Register */
+ #define  LMAP_EN           0x00000001	/* Enable slave decode */
+-#define  LMAP_MEM_MASK     0xfffffff0	// bits that specify decode for memory io
+-#define  LMAP_IO_MASK     0xfffffffa	// bits that specify decode bits for normal io
++#define  LMAP_MEM_MASK     0xfffffff0	/*  bits that specify decode for memory io */
++#define  LMAP_IO_MASK     0xfffffffa	/*  bits that specify decode bits for normal io */
+ 
+ /* Mode/Arbitration Register.
+ */
+@@ -169,7 +169,7 @@ enum bigend_bits {
+ #define  ICS_AERR          0x00000001	/* Assert LSERR on ABORT */
+ #define  ICS_PERR          0x00000002	/* Assert LSERR on Parity Error */
+ #define  ICS_SERR          0x00000004	/* Generate PCI SERR# */
+-#define  ICS_MBIE          0x00000008	// mailbox interrupt enable
++#define  ICS_MBIE          0x00000008	/*  mailbox interrupt enable */
+ #define  ICS_PIE           0x00000100	/* PCI Interrupt Enable */
+ #define  ICS_PDIE          0x00000200	/* PCI Doorbell Interrupt Enable */
+ #define  ICS_PAIE          0x00000400	/* PCI Abort Interrupt Enable */
+@@ -190,7 +190,7 @@ enum bigend_bits {
+ #define  ICS_TA_DMA0       0x02000000	/* Target Abort - DMA #0 */
+ #define  ICS_TA_DMA1       0x04000000	/* Target Abort - DMA #1 */
+ #define  ICS_TA_RA         0x08000000	/* Target Abort - Retry Timeout */
+-#define  ICS_MBIA(x)       (0x10000000 << ((x) & 0x3))	// mailbox x is active
++#define  ICS_MBIA(x)       (0x10000000 << ((x) & 0x3))	/*  mailbox x is active */
+ 
+ #define PLX_CONTROL_REG        0x006C	/* L, EEPROM Cntl & PCI Cmd Codes */
+ #define  CTL_RDMA          0x0000000E	/* DMA Read Command */
+@@ -208,51 +208,51 @@ enum bigend_bits {
+ #define  CTL_RESET         0x40000000	/* !! Adapter Reset !! */
+ #define  CTL_READY         0x80000000	/* Local Init Done */
+ 
+-#define PLX_ID_REG	0x70	// hard-coded plx vendor and device ids
++#define PLX_ID_REG	0x70	/*  hard-coded plx vendor and device ids */
+ 
+-#define PLX_REVISION_REG	0x74	// silicon revision
++#define PLX_REVISION_REG	0x74	/*  silicon revision */
+ 
+-#define PLX_DMA0_MODE_REG	0x80	// dma channel 0 mode register
+-#define PLX_DMA1_MODE_REG	0x94	// dma channel 0 mode register
++#define PLX_DMA0_MODE_REG	0x80	/*  dma channel 0 mode register */
++#define PLX_DMA1_MODE_REG	0x94	/*  dma channel 0 mode register */
+ #define  PLX_LOCAL_BUS_16_WIDE_BITS	0x1
+ #define  PLX_LOCAL_BUS_32_WIDE_BITS	0x3
+ #define  PLX_LOCAL_BUS_WIDTH_MASK	0x3
+-#define  PLX_DMA_EN_READYIN_BIT	0x40	// enable ready in input
+-#define  PLX_EN_BTERM_BIT	0x80	// enable BTERM# input
+-#define  PLX_DMA_LOCAL_BURST_EN_BIT	0x100	// enable local burst mode
+-#define  PLX_EN_CHAIN_BIT	0x200	// enables chaining
+-#define  PLX_EN_DMA_DONE_INTR_BIT	0x400	// enables interrupt on dma done
+-#define  PLX_LOCAL_ADDR_CONST_BIT	0x800	// hold local address constant (don't increment)
+-#define  PLX_DEMAND_MODE_BIT	0x1000	// enables demand-mode for dma transfer
++#define  PLX_DMA_EN_READYIN_BIT	0x40	/*  enable ready in input */
++#define  PLX_EN_BTERM_BIT	0x80	/*  enable BTERM# input */
++#define  PLX_DMA_LOCAL_BURST_EN_BIT	0x100	/*  enable local burst mode */
++#define  PLX_EN_CHAIN_BIT	0x200	/*  enables chaining */
++#define  PLX_EN_DMA_DONE_INTR_BIT	0x400	/*  enables interrupt on dma done */
++#define  PLX_LOCAL_ADDR_CONST_BIT	0x800	/*  hold local address constant (don't increment) */
++#define  PLX_DEMAND_MODE_BIT	0x1000	/*  enables demand-mode for dma transfer */
+ #define  PLX_EOT_ENABLE_BIT	0x4000
+ #define  PLX_STOP_MODE_BIT 0x8000
+-#define  PLX_DMA_INTR_PCI_BIT	0x20000	// routes dma interrupt to pci bus (instead of local bus)
++#define  PLX_DMA_INTR_PCI_BIT	0x20000	/*  routes dma interrupt to pci bus (instead of local bus) */
+ 
+-#define PLX_DMA0_PCI_ADDRESS_REG	0x84	// pci address that dma transfers start at
++#define PLX_DMA0_PCI_ADDRESS_REG	0x84	/*  pci address that dma transfers start at */
+ #define PLX_DMA1_PCI_ADDRESS_REG	0x98
+ 
+-#define PLX_DMA0_LOCAL_ADDRESS_REG	0x88	// local address that dma transfers start at
++#define PLX_DMA0_LOCAL_ADDRESS_REG	0x88	/*  local address that dma transfers start at */
+ #define PLX_DMA1_LOCAL_ADDRESS_REG	0x9c
+ 
+-#define PLX_DMA0_TRANSFER_SIZE_REG	0x8c	// number of bytes to transfer (first 23 bits)
++#define PLX_DMA0_TRANSFER_SIZE_REG	0x8c	/*  number of bytes to transfer (first 23 bits) */
+ #define PLX_DMA1_TRANSFER_SIZE_REG	0xa0
+ 
+-#define PLX_DMA0_DESCRIPTOR_REG	0x90	// descriptor pointer register
++#define PLX_DMA0_DESCRIPTOR_REG	0x90	/*  descriptor pointer register */
+ #define PLX_DMA1_DESCRIPTOR_REG	0xa4
+-#define  PLX_DESC_IN_PCI_BIT	0x1	// descriptor is located in pci space (not local space)
+-#define  PLX_END_OF_CHAIN_BIT	0x2	// end of chain bit
+-#define  PLX_INTR_TERM_COUNT	0x4	// interrupt when this descriptor's transfer is finished
+-#define  PLX_XFER_LOCAL_TO_PCI 0x8	// transfer from local to pci bus (not pci to local)
++#define  PLX_DESC_IN_PCI_BIT	0x1	/*  descriptor is located in pci space (not local space) */
++#define  PLX_END_OF_CHAIN_BIT	0x2	/*  end of chain bit */
++#define  PLX_INTR_TERM_COUNT	0x4	/*  interrupt when this descriptor's transfer is finished */
++#define  PLX_XFER_LOCAL_TO_PCI 0x8	/*  transfer from local to pci bus (not pci to local) */
+ 
+-#define PLX_DMA0_CS_REG	0xa8	// command status register
++#define PLX_DMA0_CS_REG	0xa8	/*  command status register */
+ #define PLX_DMA1_CS_REG	0xa9
+-#define  PLX_DMA_EN_BIT	0x1	// enable dma channel
+-#define  PLX_DMA_START_BIT	0x2	// start dma transfer
+-#define  PLX_DMA_ABORT_BIT	0x4	// abort dma transfer
+-#define  PLX_CLEAR_DMA_INTR_BIT	0x8	// clear dma interrupt
+-#define  PLX_DMA_DONE_BIT	0x10	// transfer done status bit
++#define  PLX_DMA_EN_BIT	0x1	/*  enable dma channel */
++#define  PLX_DMA_START_BIT	0x2	/*  start dma transfer */
++#define  PLX_DMA_ABORT_BIT	0x4	/*  abort dma transfer */
++#define  PLX_CLEAR_DMA_INTR_BIT	0x8	/*  clear dma interrupt */
++#define  PLX_DMA_DONE_BIT	0x10	/*  transfer done status bit */
+ 
+-#define PLX_DMA0_THRESHOLD_REG	0xb0	// command status register
++#define PLX_DMA0_THRESHOLD_REG	0xb0	/*  command status register */
+ 
+ /*
+  * Accesses near the end of memory can cause the PLX chip
+@@ -392,12 +392,12 @@ static inline int plx9080_abort_dma(void *iobase, unsigned int channel)
+ 	else
+ 		dma_cs_addr = iobase + PLX_DMA0_CS_REG;
+ 
+-	// abort dma transfer if necessary
++	/*  abort dma transfer if necessary */
+ 	dma_status = readb(dma_cs_addr);
+ 	if ((dma_status & PLX_DMA_EN_BIT) == 0) {
+ 		return 0;
+ 	}
+-	// wait to make sure done bit is zero
++	/*  wait to make sure done bit is zero */
+ 	for (i = 0; (dma_status & PLX_DMA_DONE_BIT) && i < timeout; i++) {
+ 		comedi_udelay(1);
+ 		dma_status = readb(dma_cs_addr);
+@@ -408,9 +408,9 @@ static inline int plx9080_abort_dma(void *iobase, unsigned int channel)
+ 			channel);
+ 		return -ETIMEDOUT;
+ 	}
+-	// disable and abort channel
++	/*  disable and abort channel */
+ 	writeb(PLX_DMA_ABORT_BIT, dma_cs_addr);
+-	// wait for dma done bit
++	/*  wait for dma done bit */
+ 	dma_status = readb(dma_cs_addr);
+ 	for (i = 0; (dma_status & PLX_DMA_DONE_BIT) == 0 && i < timeout; i++) {
+ 		comedi_udelay(1);
+diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
+index 6c7d54321f88..e9379b80d227 100644
+--- a/drivers/staging/comedi/drivers/rtd520.c
++++ b/drivers/staging/comedi/drivers/rtd520.c
+@@ -704,7 +704,7 @@ static int rtd_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 	comedi_cmd * cmd);
+ static int rtd_ai_cmd(comedi_device * dev, comedi_subdevice * s);
+ static int rtd_ai_cancel(comedi_device * dev, comedi_subdevice * s);
+-//static int rtd_ai_poll (comedi_device *dev,comedi_subdevice *s);
++/* static int rtd_ai_poll (comedi_device *dev,comedi_subdevice *s); */
+ static int rtd_ns_to_timer(unsigned int *ns, int roundMode);
+ static irqreturn_t rtd_interrupt(int irq, void *d PT_REGS_ARG);
+ static int rtd520_probe_fifo_depth(comedi_device *dev);
+@@ -866,7 +866,7 @@ static int rtd_attach(comedi_device * dev, comedi_devconfig * it)
+ 	s->do_cmd = rtd_ai_cmd;
+ 	s->do_cmdtest = rtd_ai_cmdtest;
+ 	s->cancel = rtd_ai_cancel;
+-	/*s->poll = rtd_ai_poll; *//* not ready yet */
++	/* s->poll = rtd_ai_poll; */ /* not ready yet */
+ 
+ 	s = dev->subdevices + 1;
+ 	/* analog output subdevice */
+@@ -1005,7 +1005,7 @@ static int rtd_attach(comedi_device * dev, comedi_devconfig * it)
+ 
+ #if 0
+ 	/* hit an error, clean up memory and return ret */
+-//rtd_attach_die_error:
++/* rtd_attach_die_error: */
+ #ifdef USE_DMA
+ 	for (index = 0; index < DMA_CHAIN_COUNT; index++) {
+ 		if (NULL != devpriv->dma0Buff[index]) {	/* free buffer memory */
+@@ -1377,15 +1377,15 @@ void abort_dma(comedi_device * dev, unsigned int channel)
+ 	unsigned long dma_cs_addr;	/* the control/status register */
+ 	uint8_t status;
+ 	unsigned int ii;
+-	//unsigned long flags;
++	/* unsigned long flags; */
+ 
+ 	dma_cs_addr = (unsigned long)devpriv->lcfg
+ 		+ ((channel == 0) ? LCFG_DMACSR0 : LCFG_DMACSR1);
+ 
+-	// spinlock for plx dma control/status reg
+-	//comedi_spin_lock_irqsave( &dev->spinlock, flags );
++	/*  spinlock for plx dma control/status reg */
++	/* comedi_spin_lock_irqsave( &dev->spinlock, flags ); */
+ 
+-	// abort dma transfer if necessary
++	/*  abort dma transfer if necessary */
+ 	status = readb(dma_cs_addr);
+ 	if ((status & PLX_DMA_EN_BIT) == 0) {	/* not enabled (Error?) */
+ 		DPRINTK("rtd520: AbortDma on non-active channel %d (0x%x)\n",
+@@ -1410,7 +1410,7 @@ void abort_dma(comedi_device * dev, unsigned int channel)
+ 	/* set abort bit for channel */
+ 	writeb(PLX_DMA_ABORT_BIT, dma_cs_addr);
+ 
+-	// wait for dma done bit to be set
++	/*  wait for dma done bit to be set */
+ 	status = readb(dma_cs_addr);
+ 	for (ii = 0;
+ 		(status & PLX_DMA_DONE_BIT) == 0 && ii < RTD_DMA_TIMEOUT;
+@@ -1424,7 +1424,7 @@ void abort_dma(comedi_device * dev, unsigned int channel)
+ 	}
+ 
+       abortDmaExit:
+-	//comedi_spin_unlock_irqrestore( &dev->spinlock, flags );
++	/* comedi_spin_unlock_irqrestore( &dev->spinlock, flags ); */
+ }
+ 
+ /*
+diff --git a/drivers/staging/comedi/drivers/rtd520.h b/drivers/staging/comedi/drivers/rtd520.h
+index 0eb50b8e605e..a3ec2599c4b8 100644
+--- a/drivers/staging/comedi/drivers/rtd520.h
++++ b/drivers/staging/comedi/drivers/rtd520.h
+@@ -29,366 +29,366 @@
+   LAS0 Runtime Area
+   Local Address Space 0 Offset		Read Function	Write Function
+ */
+-#define LAS0_SPARE_00    0x0000	// -                               -
+-#define LAS0_SPARE_04    0x0004	// -                               -
+-#define LAS0_USER_IO     0x0008	// Read User Inputs                Write User Outputs
+-#define LAS0_SPARE_0C    0x000C	// -                               -
+-#define LAS0_ADC         0x0010	// Read FIFO Status                Software A/D Start
+-#define LAS0_DAC1        0x0014	// -                               Software D/A1 Update
+-#define LAS0_DAC2        0x0018	// -                               Software D/A2 Update
+-#define LAS0_SPARE_1C    0x001C	// -                               -
+-#define LAS0_SPARE_20    0x0020	// -                               -
+-#define LAS0_DAC         0x0024	// -                               Software Simultaneous D/A1 and D/A2 Update
+-#define LAS0_PACER       0x0028	// Software Pacer Start            Software Pacer Stop
+-#define LAS0_TIMER       0x002C	// Read Timer Counters Status      HDIN Software Trigger
+-#define LAS0_IT          0x0030	// Read Interrupt Status           Write Interrupt Enable Mask Register
+-#define LAS0_CLEAR       0x0034	// Clear ITs set by Clear Mask     Set Interrupt Clear Mask
+-#define LAS0_OVERRUN     0x0038	// Read pending interrupts         Clear Overrun Register
+-#define LAS0_SPARE_3C    0x003C	// -                               -
++#define LAS0_SPARE_00    0x0000	/*  -                               - */
++#define LAS0_SPARE_04    0x0004	/*  -                               - */
++#define LAS0_USER_IO     0x0008	/*  Read User Inputs                Write User Outputs */
++#define LAS0_SPARE_0C    0x000C	/*  -                               - */
++#define LAS0_ADC         0x0010	/*  Read FIFO Status                Software A/D Start */
++#define LAS0_DAC1        0x0014	/*  -                               Software D/A1 Update */
++#define LAS0_DAC2        0x0018	/*  -                               Software D/A2 Update */
++#define LAS0_SPARE_1C    0x001C	/*  -                               - */
++#define LAS0_SPARE_20    0x0020	/*  -                               - */
++#define LAS0_DAC         0x0024	/*  -                               Software Simultaneous D/A1 and D/A2 Update */
++#define LAS0_PACER       0x0028	/*  Software Pacer Start            Software Pacer Stop */
++#define LAS0_TIMER       0x002C	/*  Read Timer Counters Status      HDIN Software Trigger */
++#define LAS0_IT          0x0030	/*  Read Interrupt Status           Write Interrupt Enable Mask Register */
++#define LAS0_CLEAR       0x0034	/*  Clear ITs set by Clear Mask     Set Interrupt Clear Mask */
++#define LAS0_OVERRUN     0x0038	/*  Read pending interrupts         Clear Overrun Register */
++#define LAS0_SPARE_3C    0x003C	/*  -                               - */
+ 
+ /*
+   LAS0 Runtime Area Timer/Counter,Dig.IO
+   Name			Local Address			Function
+ */
+-#define LAS0_PCLK        0x0040	// Pacer Clock value (24bit)             Pacer Clock load (24bit)
+-#define LAS0_BCLK        0x0044	// Burst Clock value (10bit)             Burst Clock load (10bit)
+-#define LAS0_ADC_SCNT    0x0048	// A/D Sample counter value (10bit)      A/D Sample counter load (10bit)
+-#define LAS0_DAC1_UCNT   0x004C	// D/A1 Update counter value (10 bit)    D/A1 Update counter load (10bit)
+-#define LAS0_DAC2_UCNT   0x0050	// D/A2 Update counter value (10 bit)    D/A2 Update counter load (10bit)
+-#define LAS0_DCNT        0x0054	// Delay counter value (16 bit)          Delay counter load (16bit)
+-#define LAS0_ACNT        0x0058	// About counter value (16 bit)          About counter load (16bit)
+-#define LAS0_DAC_CLK     0x005C	// DAC clock value (16bit)               DAC clock load (16bit)
+-#define LAS0_UTC0        0x0060	// 8254 TC Counter 0 User TC 0 value     Load count in TC Counter 0
+-#define LAS0_UTC1        0x0064	// 8254 TC Counter 1 User TC 1 value     Load count in TC Counter 1
+-#define LAS0_UTC2        0x0068	// 8254 TC Counter 2 User TC 2 value     Load count in TC Counter 2
+-#define LAS0_UTC_CTRL    0x006C	// 8254 TC Control Word                  Program counter mode for TC
+-#define LAS0_DIO0        0x0070	// Digital I/O Port 0 Read Port          Digital I/O Port 0 Write Port
+-#define LAS0_DIO1        0x0074	// Digital I/O Port 1 Read Port          Digital I/O Port 1 Write Port
+-#define LAS0_DIO0_CTRL   0x0078	// Clear digital IRQ status flag/read    Clear digital chip/program Port 0
+-#define LAS0_DIO_STATUS  0x007C	// Read Digital I/O Status word          Program digital control register &
++#define LAS0_PCLK        0x0040	/*  Pacer Clock value (24bit)             Pacer Clock load (24bit) */
++#define LAS0_BCLK        0x0044	/*  Burst Clock value (10bit)             Burst Clock load (10bit) */
++#define LAS0_ADC_SCNT    0x0048	/*  A/D Sample counter value (10bit)      A/D Sample counter load (10bit) */
++#define LAS0_DAC1_UCNT   0x004C	/*  D/A1 Update counter value (10 bit)    D/A1 Update counter load (10bit) */
++#define LAS0_DAC2_UCNT   0x0050	/*  D/A2 Update counter value (10 bit)    D/A2 Update counter load (10bit) */
++#define LAS0_DCNT        0x0054	/*  Delay counter value (16 bit)          Delay counter load (16bit) */
++#define LAS0_ACNT        0x0058	/*  About counter value (16 bit)          About counter load (16bit) */
++#define LAS0_DAC_CLK     0x005C	/*  DAC clock value (16bit)               DAC clock load (16bit) */
++#define LAS0_UTC0        0x0060	/*  8254 TC Counter 0 User TC 0 value     Load count in TC Counter 0 */
++#define LAS0_UTC1        0x0064	/*  8254 TC Counter 1 User TC 1 value     Load count in TC Counter 1 */
++#define LAS0_UTC2        0x0068	/*  8254 TC Counter 2 User TC 2 value     Load count in TC Counter 2 */
++#define LAS0_UTC_CTRL    0x006C	/*  8254 TC Control Word                  Program counter mode for TC */
++#define LAS0_DIO0        0x0070	/*  Digital I/O Port 0 Read Port          Digital I/O Port 0 Write Port */
++#define LAS0_DIO1        0x0074	/*  Digital I/O Port 1 Read Port          Digital I/O Port 1 Write Port */
++#define LAS0_DIO0_CTRL   0x0078	/*  Clear digital IRQ status flag/read    Clear digital chip/program Port 0 */
++#define LAS0_DIO_STATUS  0x007C	/*  Read Digital I/O Status word          Program digital control register & */
+ 
+ /*
+   LAS0 Setup Area
+   Name			Local Address			Function
+ */
+-#define LAS0_BOARD_RESET        0x0100	// Board reset
+-#define LAS0_DMA0_SRC           0x0104	// DMA 0 Sources select
+-#define LAS0_DMA1_SRC           0x0108	// DMA 1 Sources select
+-#define LAS0_ADC_CONVERSION     0x010C	// A/D Conversion Signal select
+-#define LAS0_BURST_START        0x0110	// Burst Clock Start Trigger select
+-#define LAS0_PACER_START        0x0114	// Pacer Clock Start Trigger select
+-#define LAS0_PACER_STOP         0x0118	// Pacer Clock Stop Trigger select
+-#define LAS0_ACNT_STOP_ENABLE   0x011C	// About Counter Stop Enable
+-#define LAS0_PACER_REPEAT       0x0120	// Pacer Start Trigger Mode select
+-#define LAS0_DIN_START          0x0124	// High Speed Digital Input Sampling Signal select
+-#define LAS0_DIN_FIFO_CLEAR     0x0128	// Digital Input FIFO Clear
+-#define LAS0_ADC_FIFO_CLEAR     0x012C	// A/D FIFO Clear
+-#define LAS0_CGT_WRITE          0x0130	// Channel Gain Table Write
+-#define LAS0_CGL_WRITE          0x0134	// Channel Gain Latch Write
+-#define LAS0_CG_DATA            0x0138	// Digital Table Write
+-#define LAS0_CGT_ENABLE		0x013C	// Channel Gain Table Enable
+-#define LAS0_CG_ENABLE          0x0140	// Digital Table Enable
+-#define LAS0_CGT_PAUSE          0x0144	// Table Pause Enable
+-#define LAS0_CGT_RESET          0x0148	// Reset Channel Gain Table
+-#define LAS0_CGT_CLEAR          0x014C	// Clear Channel Gain Table
+-#define LAS0_DAC1_CTRL          0x0150	// D/A1 output type/range
+-#define LAS0_DAC1_SRC           0x0154	// D/A1 update source
+-#define LAS0_DAC1_CYCLE         0x0158	// D/A1 cycle mode
+-#define LAS0_DAC1_RESET         0x015C	// D/A1 FIFO reset
+-#define LAS0_DAC1_FIFO_CLEAR    0x0160	// D/A1 FIFO clear
+-#define LAS0_DAC2_CTRL          0x0164	// D/A2 output type/range
+-#define LAS0_DAC2_SRC           0x0168	// D/A2 update source
+-#define LAS0_DAC2_CYCLE         0x016C	// D/A2 cycle mode
+-#define LAS0_DAC2_RESET         0x0170	// D/A2 FIFO reset
+-#define LAS0_DAC2_FIFO_CLEAR    0x0174	// D/A2 FIFO clear
+-#define LAS0_ADC_SCNT_SRC       0x0178	// A/D Sample Counter Source select
+-#define LAS0_PACER_SELECT       0x0180	// Pacer Clock select
+-#define LAS0_SBUS0_SRC          0x0184	// SyncBus 0 Source select
+-#define LAS0_SBUS0_ENABLE       0x0188	// SyncBus 0 enable
+-#define LAS0_SBUS1_SRC          0x018C	// SyncBus 1 Source select
+-#define LAS0_SBUS1_ENABLE       0x0190	// SyncBus 1 enable
+-#define LAS0_SBUS2_SRC          0x0198	// SyncBus 2 Source select
+-#define LAS0_SBUS2_ENABLE       0x019C	// SyncBus 2 enable
+-#define LAS0_ETRG_POLARITY      0x01A4	// External Trigger polarity select
+-#define LAS0_EINT_POLARITY      0x01A8	// External Interrupt polarity select
+-#define LAS0_UTC0_CLOCK         0x01AC	// UTC0 Clock select
+-#define LAS0_UTC0_GATE          0x01B0	// UTC0 Gate select
+-#define LAS0_UTC1_CLOCK         0x01B4	// UTC1 Clock select
+-#define LAS0_UTC1_GATE          0x01B8	// UTC1 Gate select
+-#define LAS0_UTC2_CLOCK         0x01BC	// UTC2 Clock select
+-#define LAS0_UTC2_GATE          0x01C0	// UTC2 Gate select
+-#define LAS0_UOUT0_SELECT       0x01C4	// User Output 0 source select
+-#define LAS0_UOUT1_SELECT       0x01C8	// User Output 1 source select
+-#define LAS0_DMA0_RESET         0x01CC	// DMA0 Request state machine reset
+-#define LAS0_DMA1_RESET         0x01D0	// DMA1 Request state machine reset
++#define LAS0_BOARD_RESET        0x0100	/*  Board reset */
++#define LAS0_DMA0_SRC           0x0104	/*  DMA 0 Sources select */
++#define LAS0_DMA1_SRC           0x0108	/*  DMA 1 Sources select */
++#define LAS0_ADC_CONVERSION     0x010C	/*  A/D Conversion Signal select */
++#define LAS0_BURST_START        0x0110	/*  Burst Clock Start Trigger select */
++#define LAS0_PACER_START        0x0114	/*  Pacer Clock Start Trigger select */
++#define LAS0_PACER_STOP         0x0118	/*  Pacer Clock Stop Trigger select */
++#define LAS0_ACNT_STOP_ENABLE   0x011C	/*  About Counter Stop Enable */
++#define LAS0_PACER_REPEAT       0x0120	/*  Pacer Start Trigger Mode select */
++#define LAS0_DIN_START          0x0124	/*  High Speed Digital Input Sampling Signal select */
++#define LAS0_DIN_FIFO_CLEAR     0x0128	/*  Digital Input FIFO Clear */
++#define LAS0_ADC_FIFO_CLEAR     0x012C	/*  A/D FIFO Clear */
++#define LAS0_CGT_WRITE          0x0130	/*  Channel Gain Table Write */
++#define LAS0_CGL_WRITE          0x0134	/*  Channel Gain Latch Write */
++#define LAS0_CG_DATA            0x0138	/*  Digital Table Write */
++#define LAS0_CGT_ENABLE		0x013C	/*  Channel Gain Table Enable */
++#define LAS0_CG_ENABLE          0x0140	/*  Digital Table Enable */
++#define LAS0_CGT_PAUSE          0x0144	/*  Table Pause Enable */
++#define LAS0_CGT_RESET          0x0148	/*  Reset Channel Gain Table */
++#define LAS0_CGT_CLEAR          0x014C	/*  Clear Channel Gain Table */
++#define LAS0_DAC1_CTRL          0x0150	/*  D/A1 output type/range */
++#define LAS0_DAC1_SRC           0x0154	/*  D/A1 update source */
++#define LAS0_DAC1_CYCLE         0x0158	/*  D/A1 cycle mode */
++#define LAS0_DAC1_RESET         0x015C	/*  D/A1 FIFO reset */
++#define LAS0_DAC1_FIFO_CLEAR    0x0160	/*  D/A1 FIFO clear */
++#define LAS0_DAC2_CTRL          0x0164	/*  D/A2 output type/range */
++#define LAS0_DAC2_SRC           0x0168	/*  D/A2 update source */
++#define LAS0_DAC2_CYCLE         0x016C	/*  D/A2 cycle mode */
++#define LAS0_DAC2_RESET         0x0170	/*  D/A2 FIFO reset */
++#define LAS0_DAC2_FIFO_CLEAR    0x0174	/*  D/A2 FIFO clear */
++#define LAS0_ADC_SCNT_SRC       0x0178	/*  A/D Sample Counter Source select */
++#define LAS0_PACER_SELECT       0x0180	/*  Pacer Clock select */
++#define LAS0_SBUS0_SRC          0x0184	/*  SyncBus 0 Source select */
++#define LAS0_SBUS0_ENABLE       0x0188	/*  SyncBus 0 enable */
++#define LAS0_SBUS1_SRC          0x018C	/*  SyncBus 1 Source select */
++#define LAS0_SBUS1_ENABLE       0x0190	/*  SyncBus 1 enable */
++#define LAS0_SBUS2_SRC          0x0198	/*  SyncBus 2 Source select */
++#define LAS0_SBUS2_ENABLE       0x019C	/*  SyncBus 2 enable */
++#define LAS0_ETRG_POLARITY      0x01A4	/*  External Trigger polarity select */
++#define LAS0_EINT_POLARITY      0x01A8	/*  External Interrupt polarity select */
++#define LAS0_UTC0_CLOCK         0x01AC	/*  UTC0 Clock select */
++#define LAS0_UTC0_GATE          0x01B0	/*  UTC0 Gate select */
++#define LAS0_UTC1_CLOCK         0x01B4	/*  UTC1 Clock select */
++#define LAS0_UTC1_GATE          0x01B8	/*  UTC1 Gate select */
++#define LAS0_UTC2_CLOCK         0x01BC	/*  UTC2 Clock select */
++#define LAS0_UTC2_GATE          0x01C0	/*  UTC2 Gate select */
++#define LAS0_UOUT0_SELECT       0x01C4	/*  User Output 0 source select */
++#define LAS0_UOUT1_SELECT       0x01C8	/*  User Output 1 source select */
++#define LAS0_DMA0_RESET         0x01CC	/*  DMA0 Request state machine reset */
++#define LAS0_DMA1_RESET         0x01D0	/*  DMA1 Request state machine reset */
+ 
+ /*
+   LAS1
+   Name			Local Address			Function
+ */
+-#define LAS1_ADC_FIFO            0x0000	// Read A/D FIFO (16bit) -
+-#define LAS1_HDIO_FIFO           0x0004	// Read High Speed Digital Input FIFO (16bit) -
+-#define LAS1_DAC1_FIFO           0x0008	// - Write D/A1 FIFO (16bit)
+-#define LAS1_DAC2_FIFO           0x000C	// - Write D/A2 FIFO (16bit)
++#define LAS1_ADC_FIFO            0x0000	/*  Read A/D FIFO (16bit) - */
++#define LAS1_HDIO_FIFO           0x0004	/*  Read High Speed Digital Input FIFO (16bit) - */
++#define LAS1_DAC1_FIFO           0x0008	/*  - Write D/A1 FIFO (16bit) */
++#define LAS1_DAC2_FIFO           0x000C	/*  - Write D/A2 FIFO (16bit) */
+ 
+ /*
+   LCFG: PLX 9080 local config & runtime registers
+   Name			Local Address			Function
+ */
+-#define LCFG_ITCSR              0x0068	// INTCSR, Interrupt Control/Status Register
+-#define LCFG_DMAMODE0           0x0080	// DMA Channel 0 Mode Register
+-#define LCFG_DMAPADR0           0x0084	// DMA Channel 0 PCI Address Register
+-#define LCFG_DMALADR0           0x0088	// DMA Channel 0 Local Address Reg
+-#define LCFG_DMASIZ0            0x008C	// DMA Channel 0 Transfer Size (Bytes) Register
+-#define LCFG_DMADPR0            0x0090	// DMA Channel 0 Descriptor Pointer Register
+-#define LCFG_DMAMODE1           0x0094	// DMA Channel 1 Mode Register
+-#define LCFG_DMAPADR1           0x0098	// DMA Channel 1 PCI Address Register
+-#define LCFG_DMALADR1           0x009C	// DMA Channel 1 Local Address Register
+-#define LCFG_DMASIZ1            0x00A0	// DMA Channel 1 Transfer Size (Bytes) Register
+-#define LCFG_DMADPR1            0x00A4	// DMA Channel 1 Descriptor Pointer Register
+-#define LCFG_DMACSR0            0x00A8	// DMA Channel 0 Command/Status Register
+-#define LCFG_DMACSR1            0x00A9	// DMA Channel 0 Command/Status Register
+-#define LCFG_DMAARB             0x00AC	// DMA Arbitration Register
+-#define LCFG_DMATHR             0x00B0	// DMA Threshold Register
++#define LCFG_ITCSR              0x0068	/*  INTCSR, Interrupt Control/Status Register */
++#define LCFG_DMAMODE0           0x0080	/*  DMA Channel 0 Mode Register */
++#define LCFG_DMAPADR0           0x0084	/*  DMA Channel 0 PCI Address Register */
++#define LCFG_DMALADR0           0x0088	/*  DMA Channel 0 Local Address Reg */
++#define LCFG_DMASIZ0            0x008C	/*  DMA Channel 0 Transfer Size (Bytes) Register */
++#define LCFG_DMADPR0            0x0090	/*  DMA Channel 0 Descriptor Pointer Register */
++#define LCFG_DMAMODE1           0x0094	/*  DMA Channel 1 Mode Register */
++#define LCFG_DMAPADR1           0x0098	/*  DMA Channel 1 PCI Address Register */
++#define LCFG_DMALADR1           0x009C	/*  DMA Channel 1 Local Address Register */
++#define LCFG_DMASIZ1            0x00A0	/*  DMA Channel 1 Transfer Size (Bytes) Register */
++#define LCFG_DMADPR1            0x00A4	/*  DMA Channel 1 Descriptor Pointer Register */
++#define LCFG_DMACSR0            0x00A8	/*  DMA Channel 0 Command/Status Register */
++#define LCFG_DMACSR1            0x00A9	/*  DMA Channel 0 Command/Status Register */
++#define LCFG_DMAARB             0x00AC	/*  DMA Arbitration Register */
++#define LCFG_DMATHR             0x00B0	/*  DMA Threshold Register */
+ 
+ /*======================================================================
+   Resister bit definitions
+ ======================================================================*/
+ 
+-// FIFO Status Word Bits (RtdFifoStatus)
+-#define FS_DAC1_NOT_EMPTY    0x0001	// D0  - DAC1 FIFO not empty
+-#define FS_DAC1_HEMPTY   0x0002	// D1  - DAC1 FIFO half empty
+-#define FS_DAC1_NOT_FULL     0x0004	// D2  - DAC1 FIFO not full
+-#define FS_DAC2_NOT_EMPTY    0x0010	// D4  - DAC2 FIFO not empty
+-#define FS_DAC2_HEMPTY   0x0020	// D5  - DAC2 FIFO half empty
+-#define FS_DAC2_NOT_FULL     0x0040	// D6  - DAC2 FIFO not full
+-#define FS_ADC_NOT_EMPTY     0x0100	// D8  - ADC FIFO not empty
+-#define FS_ADC_HEMPTY    0x0200	// D9  - ADC FIFO half empty
+-#define FS_ADC_NOT_FULL      0x0400	// D10 - ADC FIFO not full
+-#define FS_DIN_NOT_EMPTY     0x1000	// D12 - DIN FIFO not empty
+-#define FS_DIN_HEMPTY    0x2000	// D13 - DIN FIFO half empty
+-#define FS_DIN_NOT_FULL      0x4000	// D14 - DIN FIFO not full
+-
+-// Timer Status Word Bits (GetTimerStatus)
++/*  FIFO Status Word Bits (RtdFifoStatus) */
++#define FS_DAC1_NOT_EMPTY    0x0001	/*  D0  - DAC1 FIFO not empty */
++#define FS_DAC1_HEMPTY   0x0002	/*  D1  - DAC1 FIFO half empty */
++#define FS_DAC1_NOT_FULL     0x0004	/*  D2  - DAC1 FIFO not full */
++#define FS_DAC2_NOT_EMPTY    0x0010	/*  D4  - DAC2 FIFO not empty */
++#define FS_DAC2_HEMPTY   0x0020	/*  D5  - DAC2 FIFO half empty */
++#define FS_DAC2_NOT_FULL     0x0040	/*  D6  - DAC2 FIFO not full */
++#define FS_ADC_NOT_EMPTY     0x0100	/*  D8  - ADC FIFO not empty */
++#define FS_ADC_HEMPTY    0x0200	/*  D9  - ADC FIFO half empty */
++#define FS_ADC_NOT_FULL      0x0400	/*  D10 - ADC FIFO not full */
++#define FS_DIN_NOT_EMPTY     0x1000	/*  D12 - DIN FIFO not empty */
++#define FS_DIN_HEMPTY    0x2000	/*  D13 - DIN FIFO half empty */
++#define FS_DIN_NOT_FULL      0x4000	/*  D14 - DIN FIFO not full */
++
++/*  Timer Status Word Bits (GetTimerStatus) */
+ #define TS_PCLK_GATE   0x0001
+-// D0 - Pacer Clock Gate [0 - gated, 1 - enabled]
++/*  D0 - Pacer Clock Gate [0 - gated, 1 - enabled] */
+ #define TS_BCLK_GATE   0x0002
+-// D1 - Burst Clock Gate [0 - disabled, 1 - running]
++/*  D1 - Burst Clock Gate [0 - disabled, 1 - running] */
+ #define TS_DCNT_GATE   0x0004
+-// D2 - Pacer Clock Delayed Start Trigger [0 - delay over, 1 - delay in
+-// progress]
++/*  D2 - Pacer Clock Delayed Start Trigger [0 - delay over, 1 - delay in */
++/*  progress] */
+ #define TS_ACNT_GATE   0x0008
+-// D3 - Pacer Clock About Trigger [0 - completed, 1 - in progress]
++/*  D3 - Pacer Clock About Trigger [0 - completed, 1 - in progress] */
+ #define TS_PCLK_RUN    0x0010
+-// D4 - Pacer Clock Shutdown Flag [0 - Pacer Clock cannot be start
+-// triggered only by Software Pacer Start Command, 1 - Pacer Clock can
+-// be start triggered]
+-
+-// External Trigger polarity select
+-// External Interrupt polarity select
+-#define POL_POSITIVE         0x0	// positive edge
+-#define POL_NEGATIVE         0x1	// negative edge
+-
+-// User Output Signal select (SetUout0Source, SetUout1Source)
+-#define UOUT_ADC                0x0	// A/D Conversion Signal
+-#define UOUT_DAC1               0x1	// D/A1 Update
+-#define UOUT_DAC2               0x2	// D/A2 Update
+-#define UOUT_SOFTWARE           0x3	// Software Programmable
+-
+-// Pacer clock select (SetPacerSource)
+-#define PCLK_INTERNAL           1	// Internal Pacer Clock
+-#define PCLK_EXTERNAL           0	// External Pacer Clock
+-
+-// A/D Sample Counter Sources (SetAdcntSource, SetupSampleCounter)
+-#define ADC_SCNT_CGT_RESET         0x0	// needs restart with StartPacer
++/*  D4 - Pacer Clock Shutdown Flag [0 - Pacer Clock cannot be start */
++/*  triggered only by Software Pacer Start Command, 1 - Pacer Clock can */
++/*  be start triggered] */
++
++/*  External Trigger polarity select */
++/*  External Interrupt polarity select */
++#define POL_POSITIVE         0x0	/*  positive edge */
++#define POL_NEGATIVE         0x1	/*  negative edge */
++
++/*  User Output Signal select (SetUout0Source, SetUout1Source) */
++#define UOUT_ADC                0x0	/*  A/D Conversion Signal */
++#define UOUT_DAC1               0x1	/*  D/A1 Update */
++#define UOUT_DAC2               0x2	/*  D/A2 Update */
++#define UOUT_SOFTWARE           0x3	/*  Software Programmable */
++
++/*  Pacer clock select (SetPacerSource) */
++#define PCLK_INTERNAL           1	/*  Internal Pacer Clock */
++#define PCLK_EXTERNAL           0	/*  External Pacer Clock */
++
++/*  A/D Sample Counter Sources (SetAdcntSource, SetupSampleCounter) */
++#define ADC_SCNT_CGT_RESET         0x0	/*  needs restart with StartPacer */
+ #define ADC_SCNT_FIFO_WRITE        0x1
+ 
+-// A/D Conversion Signal Select (for SetConversionSelect)
+-#define ADC_START_SOFTWARE         0x0	// Software A/D Start
+-#define ADC_START_PCLK             0x1	// Pacer Clock (Ext. Int. see Func.509)
+-#define ADC_START_BCLK             0x2	// Burst Clock
+-#define ADC_START_DIGITAL_IT       0x3	// Digital Interrupt
+-#define ADC_START_DAC1_MARKER1     0x4	// D/A 1 Data Marker 1
+-#define ADC_START_DAC2_MARKER1     0x5	// D/A 2 Data Marker 1
+-#define ADC_START_SBUS0            0x6	// SyncBus 0
+-#define ADC_START_SBUS1            0x7	// SyncBus 1
+-#define ADC_START_SBUS2            0x8	// SyncBus 2
+-
+-// Burst Clock start trigger select (SetBurstStart)
+-#define BCLK_START_SOFTWARE        0x0	// Software A/D Start (StartBurst)
+-#define BCLK_START_PCLK            0x1	// Pacer Clock
+-#define BCLK_START_ETRIG           0x2	// External Trigger
+-#define BCLK_START_DIGITAL_IT      0x3	// Digital Interrupt
+-#define BCLK_START_SBUS0           0x4	// SyncBus 0
+-#define BCLK_START_SBUS1           0x5	// SyncBus 1
+-#define BCLK_START_SBUS2           0x6	// SyncBus 2
+-
+-// Pacer Clock start trigger select (SetPacerStart)
+-#define PCLK_START_SOFTWARE        0x0	// Software Pacer Start (StartPacer)
+-#define PCLK_START_ETRIG           0x1	// External trigger
+-#define PCLK_START_DIGITAL_IT      0x2	// Digital interrupt
+-#define PCLK_START_UTC2            0x3	// User TC 2 out
+-#define PCLK_START_SBUS0           0x4	// SyncBus 0
+-#define PCLK_START_SBUS1           0x5	// SyncBus 1
+-#define PCLK_START_SBUS2           0x6	// SyncBus 2
+-#define PCLK_START_D_SOFTWARE      0x8	// Delayed Software Pacer Start
+-#define PCLK_START_D_ETRIG         0x9	// Delayed external trigger
+-#define PCLK_START_D_DIGITAL_IT    0xA	// Delayed digital interrupt
+-#define PCLK_START_D_UTC2          0xB	// Delayed User TC 2 out
+-#define PCLK_START_D_SBUS0         0xC	// Delayed SyncBus 0
+-#define PCLK_START_D_SBUS1         0xD	// Delayed SyncBus 1
+-#define PCLK_START_D_SBUS2         0xE	// Delayed SyncBus 2
+-#define PCLK_START_ETRIG_GATED     0xF	// External Trigger Gated controlled mode
+-
+-// Pacer Clock Stop Trigger select (SetPacerStop)
+-#define PCLK_STOP_SOFTWARE         0x0	// Software Pacer Stop (StopPacer)
+-#define PCLK_STOP_ETRIG            0x1	// External Trigger
+-#define PCLK_STOP_DIGITAL_IT       0x2	// Digital Interrupt
+-#define PCLK_STOP_ACNT             0x3	// About Counter
+-#define PCLK_STOP_UTC2             0x4	// User TC2 out
+-#define PCLK_STOP_SBUS0            0x5	// SyncBus 0
+-#define PCLK_STOP_SBUS1            0x6	// SyncBus 1
+-#define PCLK_STOP_SBUS2            0x7	// SyncBus 2
+-#define PCLK_STOP_A_SOFTWARE       0x8	// About Software Pacer Stop
+-#define PCLK_STOP_A_ETRIG          0x9	// About External Trigger
+-#define PCLK_STOP_A_DIGITAL_IT     0xA	// About Digital Interrupt
+-#define PCLK_STOP_A_UTC2           0xC	// About User TC2 out
+-#define PCLK_STOP_A_SBUS0          0xD	// About SyncBus 0
+-#define PCLK_STOP_A_SBUS1          0xE	// About SyncBus 1
+-#define PCLK_STOP_A_SBUS2          0xF	// About SyncBus 2
+-
+-// About Counter Stop Enable
+-#define ACNT_STOP                  0x0	// stop enable
+-#define ACNT_NO_STOP               0x1	// stop disabled
+-
+-// DAC update source (SetDAC1Start & SetDAC2Start)
+-#define DAC_START_SOFTWARE         0x0	// Software Update
+-#define DAC_START_CGT              0x1	// CGT controlled Update
+-#define DAC_START_DAC_CLK          0x2	// D/A Clock
+-#define DAC_START_EPCLK            0x3	// External Pacer Clock
+-#define DAC_START_SBUS0            0x4	// SyncBus 0
+-#define DAC_START_SBUS1            0x5	// SyncBus 1
+-#define DAC_START_SBUS2            0x6	// SyncBus 2
+-
+-// DAC Cycle Mode (SetDAC1Cycle, SetDAC2Cycle, SetupDAC)
+-#define DAC_CYCLE_SINGLE           0x0	// not cycle
+-#define DAC_CYCLE_MULTI            0x1	// cycle
+-
+-// 8254 Operation Modes (Set8254Mode, SetupTimerCounter)
+-#define M8254_EVENT_COUNTER        0	// Event Counter
+-#define M8254_HW_ONE_SHOT          1	// Hardware-Retriggerable One-Shot
+-#define M8254_RATE_GENERATOR       2	// Rate Generator
+-#define M8254_SQUARE_WAVE          3	// Square Wave Mode
+-#define M8254_SW_STROBE            4	// Software Triggered Strobe
+-#define M8254_HW_STROBE            5	// Hardware Triggered Strobe (Retriggerable)
+-
+-// User Timer/Counter 0 Clock Select (SetUtc0Clock)
+-#define CUTC0_8MHZ                 0x0	// 8MHz
+-#define CUTC0_EXT_TC_CLOCK1        0x1	// Ext. TC Clock 1
+-#define CUTC0_EXT_TC_CLOCK2        0x2	// Ext. TC Clock 2
+-#define CUTC0_EXT_PCLK             0x3	// Ext. Pacer Clock
+-
+-// User Timer/Counter 1 Clock Select (SetUtc1Clock)
+-#define CUTC1_8MHZ                 0x0	// 8MHz
+-#define CUTC1_EXT_TC_CLOCK1        0x1	// Ext. TC Clock 1
+-#define CUTC1_EXT_TC_CLOCK2        0x2	// Ext. TC Clock 2
+-#define CUTC1_EXT_PCLK             0x3	// Ext. Pacer Clock
+-#define CUTC1_UTC0_OUT             0x4	// User Timer/Counter 0 out
+-#define CUTC1_DIN_SIGNAL           0x5	// High-Speed Digital Input   Sampling signal
+-
+-// User Timer/Counter 2 Clock Select (SetUtc2Clock)
+-#define CUTC2_8MHZ                 0x0	// 8MHz
+-#define CUTC2_EXT_TC_CLOCK1        0x1	// Ext. TC Clock 1
+-#define CUTC2_EXT_TC_CLOCK2        0x2	// Ext. TC Clock 2
+-#define CUTC2_EXT_PCLK             0x3	// Ext. Pacer Clock
+-#define CUTC2_UTC1_OUT             0x4	// User Timer/Counter 1 out
+-
+-// User Timer/Counter 0 Gate Select (SetUtc0Gate)
+-#define GUTC0_NOT_GATED            0x0	// Not gated
+-#define GUTC0_GATED                0x1	// Gated
+-#define GUTC0_EXT_TC_GATE1         0x2	// Ext. TC Gate 1
+-#define GUTC0_EXT_TC_GATE2         0x3	// Ext. TC Gate 2
+-
+-// User Timer/Counter 1 Gate Select (SetUtc1Gate)
+-#define GUTC1_NOT_GATED            0x0	// Not gated
+-#define GUTC1_GATED                0x1	// Gated
+-#define GUTC1_EXT_TC_GATE1         0x2	// Ext. TC Gate 1
+-#define GUTC1_EXT_TC_GATE2         0x3	// Ext. TC Gate 2
+-#define GUTC1_UTC0_OUT             0x4	// User Timer/Counter 0 out
+-
+-// User Timer/Counter 2 Gate Select (SetUtc2Gate)
+-#define GUTC2_NOT_GATED            0x0	// Not gated
+-#define GUTC2_GATED                0x1	// Gated
+-#define GUTC2_EXT_TC_GATE1         0x2	// Ext. TC Gate 1
+-#define GUTC2_EXT_TC_GATE2         0x3	// Ext. TC Gate 2
+-#define GUTC2_UTC1_OUT             0x4	// User Timer/Counter 1 out
+-
+-// Interrupt Source Masks (SetITMask, ClearITMask, GetITStatus)
+-#define IRQM_ADC_FIFO_WRITE        0x0001	// ADC FIFO Write
+-#define IRQM_CGT_RESET             0x0002	// Reset CGT
+-#define IRQM_CGT_PAUSE             0x0008	// Pause CGT
+-#define IRQM_ADC_ABOUT_CNT         0x0010	// About Counter out
+-#define IRQM_ADC_DELAY_CNT         0x0020	// Delay Counter out
+-#define IRQM_ADC_SAMPLE_CNT	   0x0040	// ADC Sample Counter
+-#define IRQM_DAC1_UCNT             0x0080	// DAC1 Update Counter
+-#define IRQM_DAC2_UCNT             0x0100	// DAC2 Update Counter
+-#define IRQM_UTC1                  0x0200	// User TC1 out
+-#define IRQM_UTC1_INV              0x0400	// User TC1 out, inverted
+-#define IRQM_UTC2                  0x0800	// User TC2 out
+-#define IRQM_DIGITAL_IT            0x1000	// Digital Interrupt
+-#define IRQM_EXTERNAL_IT           0x2000	// External Interrupt
+-#define IRQM_ETRIG_RISING          0x4000	// External Trigger rising-edge
+-#define IRQM_ETRIG_FALLING         0x8000	// External Trigger falling-edge
+-
+-// DMA Request Sources (LAS0)
+-#define DMAS_DISABLED              0x0	// DMA Disabled
+-#define DMAS_ADC_SCNT              0x1	// ADC Sample Counter
+-#define DMAS_DAC1_UCNT             0x2	// D/A1 Update Counter
+-#define DMAS_DAC2_UCNT             0x3	// D/A2 Update Counter
+-#define DMAS_UTC1                  0x4	// User TC1 out
+-#define DMAS_ADFIFO_HALF_FULL      0x8	// A/D FIFO half full
+-#define DMAS_DAC1_FIFO_HALF_EMPTY  0x9	// D/A1 FIFO half empty
+-#define DMAS_DAC2_FIFO_HALF_EMPTY  0xA	// D/A2 FIFO half empty
+-
+-// DMA Local Addresses   (0x40000000+LAS1 offset)
+-#define DMALADDR_ADC       0x40000000	// A/D FIFO
+-#define DMALADDR_HDIN      0x40000004	// High Speed Digital Input FIFO
+-#define DMALADDR_DAC1      0x40000008	// D/A1 FIFO
+-#define DMALADDR_DAC2      0x4000000C	// D/A2 FIFO
+-
+-// Port 0 compare modes (SetDIO0CompareMode)
+-#define DIO_MODE_EVENT     0	// Event Mode
+-#define DIO_MODE_MATCH     1	// Match Mode
+-
+-// Digital Table Enable (Port 1 disable)
+-#define DTBL_DISABLE       0	// Enable Digital Table
+-#define DTBL_ENABLE        1	// Disable Digital Table
+-
+-// Sampling Signal for High Speed Digital Input (SetHdinStart)
+-#define HDIN_SOFTWARE      0x0	// Software Trigger
+-#define HDIN_ADC           0x1	// A/D Conversion Signal
+-#define HDIN_UTC0          0x2	// User TC out 0
+-#define HDIN_UTC1          0x3	// User TC out 1
+-#define HDIN_UTC2          0x4	// User TC out 2
+-#define HDIN_EPCLK         0x5	// External Pacer Clock
+-#define HDIN_ETRG          0x6	// External Trigger
+-
+-// Channel Gain Table / Channel Gain Latch
+-#define CSC_LATCH          0	// Channel Gain Latch mode
+-#define CSC_CGT            1	// Channel Gain Table mode
+-
+-// Channel Gain Table Pause Enable
+-#define CGT_PAUSE_DISABLE  0	// Channel Gain Table Pause Disable
+-#define CGT_PAUSE_ENABLE   1	// Channel Gain Table Pause Enable
+-
+-// DAC output type/range (p63)
+-#define AOUT_UNIP5         0	// 0..+5 Volt
+-#define AOUT_UNIP10        1	// 0..+10 Volt
+-#define AOUT_BIP5          2	// -5..+5 Volt
+-#define AOUT_BIP10         3	// -10..+10 Volt
+-
+-// Ghannel Gain Table field definitions (p61)
+-// Gain
++/*  A/D Conversion Signal Select (for SetConversionSelect) */
++#define ADC_START_SOFTWARE         0x0	/*  Software A/D Start */
++#define ADC_START_PCLK             0x1	/*  Pacer Clock (Ext. Int. see Func.509) */
++#define ADC_START_BCLK             0x2	/*  Burst Clock */
++#define ADC_START_DIGITAL_IT       0x3	/*  Digital Interrupt */
++#define ADC_START_DAC1_MARKER1     0x4	/*  D/A 1 Data Marker 1 */
++#define ADC_START_DAC2_MARKER1     0x5	/*  D/A 2 Data Marker 1 */
++#define ADC_START_SBUS0            0x6	/*  SyncBus 0 */
++#define ADC_START_SBUS1            0x7	/*  SyncBus 1 */
++#define ADC_START_SBUS2            0x8	/*  SyncBus 2 */
++
++/*  Burst Clock start trigger select (SetBurstStart) */
++#define BCLK_START_SOFTWARE        0x0	/*  Software A/D Start (StartBurst) */
++#define BCLK_START_PCLK            0x1	/*  Pacer Clock */
++#define BCLK_START_ETRIG           0x2	/*  External Trigger */
++#define BCLK_START_DIGITAL_IT      0x3	/*  Digital Interrupt */
++#define BCLK_START_SBUS0           0x4	/*  SyncBus 0 */
++#define BCLK_START_SBUS1           0x5	/*  SyncBus 1 */
++#define BCLK_START_SBUS2           0x6	/*  SyncBus 2 */
++
++/*  Pacer Clock start trigger select (SetPacerStart) */
++#define PCLK_START_SOFTWARE        0x0	/*  Software Pacer Start (StartPacer) */
++#define PCLK_START_ETRIG           0x1	/*  External trigger */
++#define PCLK_START_DIGITAL_IT      0x2	/*  Digital interrupt */
++#define PCLK_START_UTC2            0x3	/*  User TC 2 out */
++#define PCLK_START_SBUS0           0x4	/*  SyncBus 0 */
++#define PCLK_START_SBUS1           0x5	/*  SyncBus 1 */
++#define PCLK_START_SBUS2           0x6	/*  SyncBus 2 */
++#define PCLK_START_D_SOFTWARE      0x8	/*  Delayed Software Pacer Start */
++#define PCLK_START_D_ETRIG         0x9	/*  Delayed external trigger */
++#define PCLK_START_D_DIGITAL_IT    0xA	/*  Delayed digital interrupt */
++#define PCLK_START_D_UTC2          0xB	/*  Delayed User TC 2 out */
++#define PCLK_START_D_SBUS0         0xC	/*  Delayed SyncBus 0 */
++#define PCLK_START_D_SBUS1         0xD	/*  Delayed SyncBus 1 */
++#define PCLK_START_D_SBUS2         0xE	/*  Delayed SyncBus 2 */
++#define PCLK_START_ETRIG_GATED     0xF	/*  External Trigger Gated controlled mode */
++
++/*  Pacer Clock Stop Trigger select (SetPacerStop) */
++#define PCLK_STOP_SOFTWARE         0x0	/*  Software Pacer Stop (StopPacer) */
++#define PCLK_STOP_ETRIG            0x1	/*  External Trigger */
++#define PCLK_STOP_DIGITAL_IT       0x2	/*  Digital Interrupt */
++#define PCLK_STOP_ACNT             0x3	/*  About Counter */
++#define PCLK_STOP_UTC2             0x4	/*  User TC2 out */
++#define PCLK_STOP_SBUS0            0x5	/*  SyncBus 0 */
++#define PCLK_STOP_SBUS1            0x6	/*  SyncBus 1 */
++#define PCLK_STOP_SBUS2            0x7	/*  SyncBus 2 */
++#define PCLK_STOP_A_SOFTWARE       0x8	/*  About Software Pacer Stop */
++#define PCLK_STOP_A_ETRIG          0x9	/*  About External Trigger */
++#define PCLK_STOP_A_DIGITAL_IT     0xA	/*  About Digital Interrupt */
++#define PCLK_STOP_A_UTC2           0xC	/*  About User TC2 out */
++#define PCLK_STOP_A_SBUS0          0xD	/*  About SyncBus 0 */
++#define PCLK_STOP_A_SBUS1          0xE	/*  About SyncBus 1 */
++#define PCLK_STOP_A_SBUS2          0xF	/*  About SyncBus 2 */
++
++/*  About Counter Stop Enable */
++#define ACNT_STOP                  0x0	/*  stop enable */
++#define ACNT_NO_STOP               0x1	/*  stop disabled */
++
++/*  DAC update source (SetDAC1Start & SetDAC2Start) */
++#define DAC_START_SOFTWARE         0x0	/*  Software Update */
++#define DAC_START_CGT              0x1	/*  CGT controlled Update */
++#define DAC_START_DAC_CLK          0x2	/*  D/A Clock */
++#define DAC_START_EPCLK            0x3	/*  External Pacer Clock */
++#define DAC_START_SBUS0            0x4	/*  SyncBus 0 */
++#define DAC_START_SBUS1            0x5	/*  SyncBus 1 */
++#define DAC_START_SBUS2            0x6	/*  SyncBus 2 */
++
++/*  DAC Cycle Mode (SetDAC1Cycle, SetDAC2Cycle, SetupDAC) */
++#define DAC_CYCLE_SINGLE           0x0	/*  not cycle */
++#define DAC_CYCLE_MULTI            0x1	/*  cycle */
++
++/*  8254 Operation Modes (Set8254Mode, SetupTimerCounter) */
++#define M8254_EVENT_COUNTER        0	/*  Event Counter */
++#define M8254_HW_ONE_SHOT          1	/*  Hardware-Retriggerable One-Shot */
++#define M8254_RATE_GENERATOR       2	/*  Rate Generator */
++#define M8254_SQUARE_WAVE          3	/*  Square Wave Mode */
++#define M8254_SW_STROBE            4	/*  Software Triggered Strobe */
++#define M8254_HW_STROBE            5	/*  Hardware Triggered Strobe (Retriggerable) */
++
++/*  User Timer/Counter 0 Clock Select (SetUtc0Clock) */
++#define CUTC0_8MHZ                 0x0	/*  8MHz */
++#define CUTC0_EXT_TC_CLOCK1        0x1	/*  Ext. TC Clock 1 */
++#define CUTC0_EXT_TC_CLOCK2        0x2	/*  Ext. TC Clock 2 */
++#define CUTC0_EXT_PCLK             0x3	/*  Ext. Pacer Clock */
++
++/*  User Timer/Counter 1 Clock Select (SetUtc1Clock) */
++#define CUTC1_8MHZ                 0x0	/*  8MHz */
++#define CUTC1_EXT_TC_CLOCK1        0x1	/*  Ext. TC Clock 1 */
++#define CUTC1_EXT_TC_CLOCK2        0x2	/*  Ext. TC Clock 2 */
++#define CUTC1_EXT_PCLK             0x3	/*  Ext. Pacer Clock */
++#define CUTC1_UTC0_OUT             0x4	/*  User Timer/Counter 0 out */
++#define CUTC1_DIN_SIGNAL           0x5	/*  High-Speed Digital Input   Sampling signal */
++
++/*  User Timer/Counter 2 Clock Select (SetUtc2Clock) */
++#define CUTC2_8MHZ                 0x0	/*  8MHz */
++#define CUTC2_EXT_TC_CLOCK1        0x1	/*  Ext. TC Clock 1 */
++#define CUTC2_EXT_TC_CLOCK2        0x2	/*  Ext. TC Clock 2 */
++#define CUTC2_EXT_PCLK             0x3	/*  Ext. Pacer Clock */
++#define CUTC2_UTC1_OUT             0x4	/*  User Timer/Counter 1 out */
++
++/*  User Timer/Counter 0 Gate Select (SetUtc0Gate) */
++#define GUTC0_NOT_GATED            0x0	/*  Not gated */
++#define GUTC0_GATED                0x1	/*  Gated */
++#define GUTC0_EXT_TC_GATE1         0x2	/*  Ext. TC Gate 1 */
++#define GUTC0_EXT_TC_GATE2         0x3	/*  Ext. TC Gate 2 */
++
++/*  User Timer/Counter 1 Gate Select (SetUtc1Gate) */
++#define GUTC1_NOT_GATED            0x0	/*  Not gated */
++#define GUTC1_GATED                0x1	/*  Gated */
++#define GUTC1_EXT_TC_GATE1         0x2	/*  Ext. TC Gate 1 */
++#define GUTC1_EXT_TC_GATE2         0x3	/*  Ext. TC Gate 2 */
++#define GUTC1_UTC0_OUT             0x4	/*  User Timer/Counter 0 out */
++
++/*  User Timer/Counter 2 Gate Select (SetUtc2Gate) */
++#define GUTC2_NOT_GATED            0x0	/*  Not gated */
++#define GUTC2_GATED                0x1	/*  Gated */
++#define GUTC2_EXT_TC_GATE1         0x2	/*  Ext. TC Gate 1 */
++#define GUTC2_EXT_TC_GATE2         0x3	/*  Ext. TC Gate 2 */
++#define GUTC2_UTC1_OUT             0x4	/*  User Timer/Counter 1 out */
++
++/*  Interrupt Source Masks (SetITMask, ClearITMask, GetITStatus) */
++#define IRQM_ADC_FIFO_WRITE        0x0001	/*  ADC FIFO Write */
++#define IRQM_CGT_RESET             0x0002	/*  Reset CGT */
++#define IRQM_CGT_PAUSE             0x0008	/*  Pause CGT */
++#define IRQM_ADC_ABOUT_CNT         0x0010	/*  About Counter out */
++#define IRQM_ADC_DELAY_CNT         0x0020	/*  Delay Counter out */
++#define IRQM_ADC_SAMPLE_CNT	   0x0040	/*  ADC Sample Counter */
++#define IRQM_DAC1_UCNT             0x0080	/*  DAC1 Update Counter */
++#define IRQM_DAC2_UCNT             0x0100	/*  DAC2 Update Counter */
++#define IRQM_UTC1                  0x0200	/*  User TC1 out */
++#define IRQM_UTC1_INV              0x0400	/*  User TC1 out, inverted */
++#define IRQM_UTC2                  0x0800	/*  User TC2 out */
++#define IRQM_DIGITAL_IT            0x1000	/*  Digital Interrupt */
++#define IRQM_EXTERNAL_IT           0x2000	/*  External Interrupt */
++#define IRQM_ETRIG_RISING          0x4000	/*  External Trigger rising-edge */
++#define IRQM_ETRIG_FALLING         0x8000	/*  External Trigger falling-edge */
++
++/*  DMA Request Sources (LAS0) */
++#define DMAS_DISABLED              0x0	/*  DMA Disabled */
++#define DMAS_ADC_SCNT              0x1	/*  ADC Sample Counter */
++#define DMAS_DAC1_UCNT             0x2	/*  D/A1 Update Counter */
++#define DMAS_DAC2_UCNT             0x3	/*  D/A2 Update Counter */
++#define DMAS_UTC1                  0x4	/*  User TC1 out */
++#define DMAS_ADFIFO_HALF_FULL      0x8	/*  A/D FIFO half full */
++#define DMAS_DAC1_FIFO_HALF_EMPTY  0x9	/*  D/A1 FIFO half empty */
++#define DMAS_DAC2_FIFO_HALF_EMPTY  0xA	/*  D/A2 FIFO half empty */
++
++/*  DMA Local Addresses   (0x40000000+LAS1 offset) */
++#define DMALADDR_ADC       0x40000000	/*  A/D FIFO */
++#define DMALADDR_HDIN      0x40000004	/*  High Speed Digital Input FIFO */
++#define DMALADDR_DAC1      0x40000008	/*  D/A1 FIFO */
++#define DMALADDR_DAC2      0x4000000C	/*  D/A2 FIFO */
++
++/*  Port 0 compare modes (SetDIO0CompareMode) */
++#define DIO_MODE_EVENT     0	/*  Event Mode */
++#define DIO_MODE_MATCH     1	/*  Match Mode */
++
++/*  Digital Table Enable (Port 1 disable) */
++#define DTBL_DISABLE       0	/*  Enable Digital Table */
++#define DTBL_ENABLE        1	/*  Disable Digital Table */
++
++/*  Sampling Signal for High Speed Digital Input (SetHdinStart) */
++#define HDIN_SOFTWARE      0x0	/*  Software Trigger */
++#define HDIN_ADC           0x1	/*  A/D Conversion Signal */
++#define HDIN_UTC0          0x2	/*  User TC out 0 */
++#define HDIN_UTC1          0x3	/*  User TC out 1 */
++#define HDIN_UTC2          0x4	/*  User TC out 2 */
++#define HDIN_EPCLK         0x5	/*  External Pacer Clock */
++#define HDIN_ETRG          0x6	/*  External Trigger */
++
++/*  Channel Gain Table / Channel Gain Latch */
++#define CSC_LATCH          0	/*  Channel Gain Latch mode */
++#define CSC_CGT            1	/*  Channel Gain Table mode */
++
++/*  Channel Gain Table Pause Enable */
++#define CGT_PAUSE_DISABLE  0	/*  Channel Gain Table Pause Disable */
++#define CGT_PAUSE_ENABLE   1	/*  Channel Gain Table Pause Enable */
++
++/*  DAC output type/range (p63) */
++#define AOUT_UNIP5         0	/*  0..+5 Volt */
++#define AOUT_UNIP10        1	/*  0..+10 Volt */
++#define AOUT_BIP5          2	/*  -5..+5 Volt */
++#define AOUT_BIP10         3	/*  -10..+10 Volt */
++
++/*  Ghannel Gain Table field definitions (p61) */
++/*  Gain */
+ #define GAIN1              0
+ #define GAIN2              1
+ #define GAIN4              2
+@@ -398,15 +398,15 @@
+ #define GAIN64             6
+ #define GAIN128            7
+ 
+-// Input range/polarity
+-#define AIN_BIP5           0	// -5..+5 Volt
+-#define AIN_BIP10          1	// -10..+10 Volt
+-#define AIN_UNIP10         2	// 0..+10 Volt
++/*  Input range/polarity */
++#define AIN_BIP5           0	/*  -5..+5 Volt */
++#define AIN_BIP10          1	/*  -10..+10 Volt */
++#define AIN_UNIP10         2	/*  0..+10 Volt */
+ 
+-// non referenced single ended select bit
+-#define NRSE_AGND          0	// AGND referenced SE input
+-#define NRSE_AINS          1	// AIN SENSE referenced SE input
++/*  non referenced single ended select bit */
++#define NRSE_AGND          0	/*  AGND referenced SE input */
++#define NRSE_AINS          1	/*  AIN SENSE referenced SE input */
+ 
+-// single ended vs differential
+-#define GND_SE		0	// Single-Ended
+-#define GND_DIFF	1	// Differential
++/*  single ended vs differential */
++#define GND_SE		0	/*  Single-Ended */
++#define GND_DIFF	1	/*  Differential */
+diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
+index 469ee8c474c9..24577a9a16b1 100644
+--- a/drivers/staging/comedi/drivers/s626.c
++++ b/drivers/staging/comedi/drivers/s626.c
+@@ -133,38 +133,30 @@ typedef struct {
+ 	void *base_addr;
+ 	int got_regions;
+ 	short allocatedBuf;
+-	uint8_t ai_cmd_running;	// ai_cmd is running
+-	uint8_t ai_continous;	// continous aquisition
+-	int ai_sample_count;	// number of samples to aquire
+-	unsigned int ai_sample_timer;	// time between samples in
+-	// units of the timer
+-	int ai_convert_count;	// conversion counter
+-	unsigned int ai_convert_timer;	// time between conversion in
+-	// units of the timer
+-	uint16_t CounterIntEnabs;	//Counter interrupt enable
+-	//mask for MISC2 register.
+-	uint8_t AdcItems;	//Number of items in ADC poll
+-	//list.
+-	DMABUF RPSBuf;		//DMA buffer used to hold ADC
+-	//(RPS1) program.
+-	DMABUF ANABuf;		//DMA buffer used to receive
+-	//ADC data and hold DAC data.
+-	uint32_t *pDacWBuf;	//Pointer to logical adrs of
+-	//DMA buffer used to hold DAC
+-	//data.
+-	uint16_t Dacpol;	//Image of DAC polarity
+-	//register.
+-	uint8_t TrimSetpoint[12];	//Images of TrimDAC setpoints.
+-	//registers.
+-	uint16_t ChargeEnabled;	//Image of MISC2 Battery
+-	//Charge Enabled (0 or
+-	//WRMISC2_CHARGE_ENABLE).
+-	uint16_t WDInterval;	//Image of MISC2 watchdog
+-	//interval control bits.
+-	uint32_t I2CAdrs;	//I2C device address for
+-	//onboard EEPROM (board rev
+-	//dependent).
+-	//  short         I2Cards;
++	uint8_t ai_cmd_running;	/*  ai_cmd is running */
++	uint8_t ai_continous;	/*  continous aquisition */
++	int ai_sample_count;	/*  number of samples to aquire */
++	unsigned int ai_sample_timer;
++	/*  time between samples in  units of the timer */
++	int ai_convert_count;	/*  conversion counter */
++	unsigned int ai_convert_timer;
++	/*  time between conversion in  units of the timer */
++	uint16_t CounterIntEnabs;
++	/* Counter interrupt enable  mask for MISC2 register. */
++	uint8_t AdcItems;	/* Number of items in ADC poll  list. */
++	DMABUF RPSBuf;		/* DMA buffer used to hold ADC (RPS1) program. */
++	DMABUF ANABuf;
++	/* DMA buffer used to receive ADC data and hold DAC data. */
++	uint32_t *pDacWBuf;
++	/* Pointer to logical adrs of DMA buffer used to hold DAC  data. */
++	uint16_t Dacpol;	/* Image of DAC polarity register. */
++	uint8_t TrimSetpoint[12];	/* Images of TrimDAC setpoints */
++	uint16_t ChargeEnabled;	/* Image of MISC2 Battery */
++	/* Charge Enabled (0 or WRMISC2_CHARGE_ENABLE). */
++	uint16_t WDInterval;	/* Image of MISC2 watchdog interval control bits. */
++	uint32_t I2CAdrs;
++	/* I2C device address for onboard EEPROM (board rev dependent). */
++	/*   short         I2Cards; */
+ 	lsampl_t ao_readback[S626_DAC_CHANNELS];
+ } s626_private;
+ 
+@@ -229,7 +221,7 @@ static dio_private *dio_private_word[]={
+ 
+ COMEDI_PCI_INITCLEANUP_NOMODULE(driver_s626, s626_pci_table);
+ 
+-//ioctl routines
++/* ioctl routines */
+ static int s626_ai_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, lsampl_t * data);
+ /* static int s626_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); */
+@@ -265,9 +257,9 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG);
+ static lsampl_t s626_ai_reg_to_uint(int data);
+ /* static lsampl_t s626_uint_to_reg(comedi_subdevice *s, int data); */
+ 
+-//end ioctl routines
++/* end ioctl routines */
+ 
+-//internal routines
++/* internal routines */
+ static void s626_dio_init(comedi_device * dev);
+ static void ResetADC(comedi_device * dev, uint8_t * ppl);
+ static void LoadTrimDACs(comedi_device * dev);
+@@ -285,30 +277,30 @@ static void DEBIreplace(comedi_device * dev, uint16_t addr, uint16_t mask,
+ 	uint16_t wdata);
+ static void CloseDMAB(comedi_device * dev, DMABUF * pdma, size_t bsize);
+ 
+-// COUNTER OBJECT ------------------------------------------------
++/*  COUNTER OBJECT ------------------------------------------------ */
+ typedef struct enc_private_struct {
+-	// Pointers to functions that differ for A and B counters:
+-	uint16_t(*GetEnable) (comedi_device * dev, struct enc_private_struct *);	//Return clock enable.
+-	uint16_t(*GetIntSrc) (comedi_device * dev, struct enc_private_struct *);	//Return interrupt source.
+-	uint16_t(*GetLoadTrig) (comedi_device * dev, struct enc_private_struct *);	//Return preload trigger source.
+-	uint16_t(*GetMode) (comedi_device * dev, struct enc_private_struct *);	//Return standardized operating mode.
+-	void (*PulseIndex) (comedi_device * dev, struct enc_private_struct *);	//Generate soft index strobe.
+-	void (*SetEnable) (comedi_device * dev, struct enc_private_struct *, uint16_t enab);	//Program clock enable.
+-	void (*SetIntSrc) (comedi_device * dev, struct enc_private_struct *, uint16_t IntSource);	//Program interrupt source.
+-	void (*SetLoadTrig) (comedi_device * dev, struct enc_private_struct *, uint16_t Trig);	//Program preload trigger source.
+-	void (*SetMode) (comedi_device * dev, struct enc_private_struct *, uint16_t Setup, uint16_t DisableIntSrc);	//Program standardized operating mode.
+-	void (*ResetCapFlags) (comedi_device * dev, struct enc_private_struct *);	//Reset event capture flags.
+-
+-	uint16_t MyCRA;		//   Address of CRA register.
+-	uint16_t MyCRB;		//   Address of CRB register.
+-	uint16_t MyLatchLsw;	//   Address of Latch least-significant-word
+-	//   register.
+-	uint16_t MyEventBits[4];	//   Bit translations for IntSrc -->RDMISC2.
+-} enc_private;			//counter object
++	/*  Pointers to functions that differ for A and B counters: */
++	uint16_t(*GetEnable) (comedi_device * dev, struct enc_private_struct *);	/* Return clock enable. */
++	uint16_t(*GetIntSrc) (comedi_device * dev, struct enc_private_struct *);	/* Return interrupt source. */
++	uint16_t(*GetLoadTrig) (comedi_device * dev, struct enc_private_struct *);	/* Return preload trigger source. */
++	uint16_t(*GetMode) (comedi_device * dev, struct enc_private_struct *);	/* Return standardized operating mode. */
++	void (*PulseIndex) (comedi_device * dev, struct enc_private_struct *);	/* Generate soft index strobe. */
++	void (*SetEnable) (comedi_device * dev, struct enc_private_struct *, uint16_t enab);	/* Program clock enable. */
++	void (*SetIntSrc) (comedi_device * dev, struct enc_private_struct *, uint16_t IntSource);	/* Program interrupt source. */
++	void (*SetLoadTrig) (comedi_device * dev, struct enc_private_struct *, uint16_t Trig);	/* Program preload trigger source. */
++	void (*SetMode) (comedi_device * dev, struct enc_private_struct *, uint16_t Setup, uint16_t DisableIntSrc);	/* Program standardized operating mode. */
++	void (*ResetCapFlags) (comedi_device * dev, struct enc_private_struct *);	/* Reset event capture flags. */
++
++	uint16_t MyCRA;		/*    Address of CRA register. */
++	uint16_t MyCRB;		/*    Address of CRB register. */
++	uint16_t MyLatchLsw;	/*    Address of Latch least-significant-word */
++	/*    register. */
++	uint16_t MyEventBits[4];	/*    Bit translations for IntSrc -->RDMISC2. */
++} enc_private;			/* counter object */
+ 
+ #define encpriv ((enc_private *)(dev->subdevices+5)->private)
+ 
+-//counters routines
++/* counters routines */
+ static void s626_timer_load(comedi_device * dev, enc_private * k, int tick);
+ static uint32_t ReadLatch(comedi_device * dev, enc_private * k);
+ static void ResetCapFlags_A(comedi_device * dev, enc_private * k);
+@@ -348,19 +340,17 @@ static void PulseIndex_A(comedi_device * dev, enc_private * k);
+ static void PulseIndex_B(comedi_device * dev, enc_private * k);
+ static void Preload(comedi_device * dev, enc_private * k, uint32_t value);
+ static void CountersInit(comedi_device * dev);
+-//end internal routines
++/* end internal routines */
+ 
+-/////////////////////////////////////////////////////////////////////////
+-// Counter objects constructor.
++/*  Counter objects constructor. */
+ 
+-// Counter overflow/index event flag masks for RDMISC2.
++/*  Counter overflow/index event flag masks for RDMISC2. */
+ #define INDXMASK(C)		( 1 << ( ( (C) > 2 ) ? ( (C) * 2 - 1 ) : ( (C) * 2 +  4 ) ) )
+ #define OVERMASK(C)		( 1 << ( ( (C) > 2 ) ? ( (C) * 2 + 5 ) : ( (C) * 2 + 10 ) ) )
+ #define EVBITS(C)		{ 0, OVERMASK(C), INDXMASK(C), OVERMASK(C) | INDXMASK(C) }
+ 
+-// Translation table to map IntSrc into equivalent RDMISC2 event flag
+-// bits.
+-//static const uint16_t EventBits[][4] = { EVBITS(0), EVBITS(1), EVBITS(2), EVBITS(3), EVBITS(4), EVBITS(5) };
++/*  Translation table to map IntSrc into equivalent RDMISC2 event flag  bits. */
++/* static const uint16_t EventBits[][4] = { EVBITS(0), EVBITS(1), EVBITS(2), EVBITS(3), EVBITS(4), EVBITS(5) }; */
+ 
+ /* enc_private; */
+ static enc_private enc_private_data[] = {
+@@ -462,8 +452,8 @@ static enc_private enc_private_data[] = {
+ 		},
+ };
+ 
+-// enab/disable a function or test status bit(s) that are accessed
+-// through Main Control Registers 1 or 2.
++/*  enab/disable a function or test status bit(s) that are accessed */
++/*  through Main Control Registers 1 or 2. */
+ #define MC_ENABLE( REGADRS, CTRLWORD )	writel(  ( (uint32_t)( CTRLWORD ) << 16 ) | (uint32_t)( CTRLWORD ),devpriv->base_addr+( REGADRS ) )
+ 
+ #define MC_DISABLE( REGADRS, CTRLWORD )	writel(  (uint32_t)( CTRLWORD ) << 16 , devpriv->base_addr+( REGADRS ) )
+@@ -480,11 +470,11 @@ static enc_private enc_private_data[] = {
+ 
+ #define BUGFIX_STREG(REGADRS)   ( REGADRS - 4 )
+ 
+-// Write a time slot control record to TSL2.
++/*  Write a time slot control record to TSL2. */
+ #define VECTPORT( VECTNUM )		(P_TSL2 + ( (VECTNUM) << 2 ))
+ #define SETVECT( VECTNUM, VECTVAL )	WR7146(VECTPORT( VECTNUM ), (VECTVAL))
+ 
+-// Code macros used for constructing I2C command bytes.
++/*  Code macros used for constructing I2C command bytes. */
+ #define I2C_B2(ATTR,VAL)	( ( (ATTR) << 6 ) | ( (VAL) << 24 ) )
+ #define I2C_B1(ATTR,VAL)	( ( (ATTR) << 4 ) | ( (VAL) << 16 ) )
+ #define I2C_B0(ATTR,VAL)	( ( (ATTR) << 2 ) | ( (VAL) <<  8 ) )
+@@ -550,16 +540,16 @@ static int s626_attach(comedi_device * dev, comedi_devconfig * it)
+ 	}
+ 
+ 	if (devpriv->base_addr) {
+-		//disable master interrupt
++		/* disable master interrupt */
+ 		writel(0, devpriv->base_addr + P_IER);
+ 
+-		//soft reset
++		/* soft reset */
+ 		writel(MC1_SOFT_RESET, devpriv->base_addr + P_MC1);
+ 
+-		//DMA FIXME DMA//
++		/* DMA FIXME DMA// */
+ 		DEBUG("s626_attach: DMA ALLOCATION\n");
+ 
+-		//adc buffer allocation
++		/* adc buffer allocation */
+ 		devpriv->allocatedBuf = 0;
+ 
+ 		if ((devpriv->ANABuf.LogicalBase =
+@@ -599,7 +589,7 @@ static int s626_attach(comedi_device * dev, comedi_devconfig * it)
+ 	dev->iobase = (unsigned long)devpriv->base_addr;
+ 	dev->irq = devpriv->pdev->irq;
+ 
+-	//set up interrupt handler
++	/* set up interrupt handler */
+ 	if (dev->irq == 0) {
+ 		printk(" unknown irq (bad)\n");
+ 	} else {
+@@ -689,119 +679,119 @@ static int s626_attach(comedi_device * dev, comedi_devconfig * it)
+ 	s->maxdata = 0xffffff;
+ 	s->range_table = &range_unknown;
+ 
+-	//stop ai_command
++	/* stop ai_command */
+ 	devpriv->ai_cmd_running = 0;
+ 
+ 	if (devpriv->base_addr && (devpriv->allocatedBuf == 2)) {
+ 		dma_addr_t pPhysBuf;
+ 		uint16_t chan;
+ 
+-		// enab DEBI and audio pins, enable I2C interface.
++		/*  enab DEBI and audio pins, enable I2C interface. */
+ 		MC_ENABLE(P_MC1, MC1_DEBI | MC1_AUDIO | MC1_I2C);
+-		// Configure DEBI operating mode.
+-		WR7146(P_DEBICFG, DEBI_CFG_SLAVE16	// Local bus is 16
+-			// bits wide.
+-			| (DEBI_TOUT << DEBI_CFG_TOUT_BIT)	// Declare DEBI
+-			// transfer timeout
+-			// interval.
+-			| DEBI_SWAP	// Set up byte lane
+-			// steering.
+-			| DEBI_CFG_INTEL);	// Intel-compatible
+-		// local bus (DEBI
+-		// never times out).
++		/*  Configure DEBI operating mode. */
++		WR7146(P_DEBICFG, DEBI_CFG_SLAVE16	/*  Local bus is 16 */
++			/*  bits wide. */
++			| (DEBI_TOUT << DEBI_CFG_TOUT_BIT)	/*  Declare DEBI */
++			/*  transfer timeout */
++			/*  interval. */
++			| DEBI_SWAP	/*  Set up byte lane */
++			/*  steering. */
++			| DEBI_CFG_INTEL);	/*  Intel-compatible */
++		/*  local bus (DEBI */
++		/*  never times out). */
+ 		DEBUG("s626_attach: %d debi init -- %d\n",
+ 			DEBI_CFG_SLAVE16 | (DEBI_TOUT << DEBI_CFG_TOUT_BIT) |
+ 			DEBI_SWAP | DEBI_CFG_INTEL,
+ 			DEBI_CFG_INTEL | DEBI_CFG_TOQ | DEBI_CFG_INCQ |
+ 			DEBI_CFG_16Q);
+ 
+-		//DEBI INIT S626 WR7146( P_DEBICFG, DEBI_CFG_INTEL | DEBI_CFG_TOQ
+-		//| DEBI_CFG_INCQ| DEBI_CFG_16Q); //end
++		/* DEBI INIT S626 WR7146( P_DEBICFG, DEBI_CFG_INTEL | DEBI_CFG_TOQ */
++		/* | DEBI_CFG_INCQ| DEBI_CFG_16Q); //end */
+ 
+-		// Paging is disabled.
+-		WR7146(P_DEBIPAGE, DEBI_PAGE_DISABLE);	// Disable MMU paging.
++		/*  Paging is disabled. */
++		WR7146(P_DEBIPAGE, DEBI_PAGE_DISABLE);	/*  Disable MMU paging. */
+ 
+-		// Init GPIO so that ADC Start* is negated.
++		/*  Init GPIO so that ADC Start* is negated. */
+ 		WR7146(P_GPIO, GPIO_BASE | GPIO1_HI);
+ 
+-		//IsBoardRevA is a boolean that indicates whether the board is
+-		//RevA.
+-
+-		// VERSION 2.01 CHANGE: REV A & B BOARDS NOW SUPPORTED BY DYNAMIC
+-		// EEPROM ADDRESS SELECTION.  Initialize the I2C interface, which
+-		// is used to access the onboard serial EEPROM.  The EEPROM's I2C
+-		// DeviceAddress is hardwired to a value that is dependent on the
+-		// 626 board revision.  On all board revisions, the EEPROM stores
+-		// TrimDAC calibration constants for analog I/O.  On RevB and
+-		// higher boards, the DeviceAddress is hardwired to 0 to enable
+-		// the EEPROM to also store the PCI SubVendorID and SubDeviceID;
+-		// this is the address at which the SAA7146 expects a
+-		// configuration EEPROM to reside.  On RevA boards, the EEPROM
+-		// device address, which is hardwired to 4, prevents the SAA7146
+-		// from retrieving PCI sub-IDs, so the SAA7146 uses its built-in
+-		// default values, instead.
+-
+-		//    devpriv->I2Cards= IsBoardRevA ? 0xA8 : 0xA0; // Set I2C EEPROM
+-		// DeviceType (0xA0)
+-		// and DeviceAddress<<1.
+-
+-		devpriv->I2CAdrs = 0xA0;	// I2C device address for onboard
+-		// eeprom(revb)
+-
+-		// Issue an I2C ABORT command to halt any I2C operation in
+-		//progress and reset BUSY flag.
+-		WR7146(P_I2CSTAT, I2C_CLKSEL | I2C_ABORT);	// Write I2C control:
+-		// abort any I2C
+-		// activity.
+-		MC_ENABLE(P_MC2, MC2_UPLD_IIC);	// Invoke command
+-		// upload
+-		while ((RR7146(P_MC2) & MC2_UPLD_IIC) == 0) ;	// and wait for
+-		// upload to
+-		// complete.
+-
+-		// Per SAA7146 data sheet, write to STATUS reg twice to reset all
+-		// I2C error flags.
++    /* IsBoardRevA is a boolean that indicates whether the board is RevA.
++     *
++     * VERSION 2.01 CHANGE: REV A & B BOARDS NOW SUPPORTED BY DYNAMIC
++     * EEPROM ADDRESS SELECTION.  Initialize the I2C interface, which
++     * is used to access the onboard serial EEPROM.  The EEPROM's I2C
++     * DeviceAddress is hardwired to a value that is dependent on the
++     * 626 board revision.  On all board revisions, the EEPROM stores
++     * TrimDAC calibration constants for analog I/O.  On RevB and
++     * higher boards, the DeviceAddress is hardwired to 0 to enable
++     * the EEPROM to also store the PCI SubVendorID and SubDeviceID;
++     * this is the address at which the SAA7146 expects a
++     * configuration EEPROM to reside.  On RevA boards, the EEPROM
++     * device address, which is hardwired to 4, prevents the SAA7146
++     * from retrieving PCI sub-IDs, so the SAA7146 uses its built-in
++     * default values, instead.
++     */
++
++		/*     devpriv->I2Cards= IsBoardRevA ? 0xA8 : 0xA0; // Set I2C EEPROM */
++		/*  DeviceType (0xA0) */
++		/*  and DeviceAddress<<1. */
++
++		devpriv->I2CAdrs = 0xA0;	/*  I2C device address for onboard */
++		/*  eeprom(revb) */
++
++		/*  Issue an I2C ABORT command to halt any I2C operation in */
++		/* progress and reset BUSY flag. */
++		WR7146(P_I2CSTAT, I2C_CLKSEL | I2C_ABORT);
++		/*  Write I2C control: abort any I2C activity. */
++		MC_ENABLE(P_MC2, MC2_UPLD_IIC);
++		/*  Invoke command  upload */
++		while ((RR7146(P_MC2) & MC2_UPLD_IIC) == 0);
++		/*  and wait for upload to complete. */
++
++		/* Per SAA7146 data sheet, write to STATUS reg twice to
++		 * reset all  I2C error flags. */
+ 		for (i = 0; i < 2; i++) {
+-			WR7146(P_I2CSTAT, I2C_CLKSEL);	// Write I2C control: reset
+-			// error flags.
+-			MC_ENABLE(P_MC2, MC2_UPLD_IIC);	// Invoke command upload
+-			while (!MC_TEST(P_MC2, MC2_UPLD_IIC)) ;	//   and wait for
+-			//   upload to
+-			//   complete.
++			WR7146(P_I2CSTAT, I2C_CLKSEL);
++			/*  Write I2C control: reset  error flags. */
++			MC_ENABLE(P_MC2, MC2_UPLD_IIC);	/*  Invoke command upload */
++			while (!MC_TEST(P_MC2, MC2_UPLD_IIC));
++			/* and wait for upload to complete. */
+ 		}
+ 
+-		// Init audio interface functional attributes: set DAC/ADC serial
+-		// clock rates, invert DAC serial clock so that DAC data setup
+-		// times are satisfied, enable DAC serial clock out.
++		/* Init audio interface functional attributes: set DAC/ADC
++		 * serial clock rates, invert DAC serial clock so that
++		 * DAC data setup times are satisfied, enable DAC serial
++		 * clock out.
++		 */
++
+ 		WR7146(P_ACON2, ACON2_INIT);
+ 
+-		// Set up TSL1 slot list, which is used to control the
+-		// accumulation of ADC data: RSD1 = shift data in on SD1.  SIB_A1
+-		// = store data uint8_t at next available location in FB BUFFER1
+-		// register.
+-		WR7146(P_TSL1, RSD1 | SIB_A1);	// Fetch ADC high data
+-		// uint8_t.
+-		WR7146(P_TSL1 + 4, RSD1 | SIB_A1 | EOS);	// Fetch ADC low data
+-		// uint8_t; end of
+-		// TSL1.
+-
+-		// enab TSL1 slot list so that it executes all the time.
++		/* Set up TSL1 slot list, which is used to control the
++		 * accumulation of ADC data: RSD1 = shift data in on SD1.
++		 * SIB_A1  = store data uint8_t at next available location in
++		 * FB BUFFER1  register. */
++		WR7146(P_TSL1, RSD1 | SIB_A1);
++		/*  Fetch ADC high data uint8_t. */
++		WR7146(P_TSL1 + 4, RSD1 | SIB_A1 | EOS);
++		/*  Fetch ADC low data uint8_t; end of TSL1. */
++
++		/*  enab TSL1 slot list so that it executes all the time. */
+ 		WR7146(P_ACON1, ACON1_ADCSTART);
+ 
+-		// Initialize RPS registers used for ADC.
++		/*  Initialize RPS registers used for ADC. */
+ 
+-		//Physical start of RPS program.
++		/* Physical start of RPS program. */
+ 		WR7146(P_RPSADDR1, (uint32_t) devpriv->RPSBuf.PhysicalBase);
+ 
+-		WR7146(P_RPSPAGE1, 0);	// RPS program performs no
+-		// explicit mem writes.
+-		WR7146(P_RPS1_TOUT, 0);	// Disable RPS timeouts.
++		WR7146(P_RPSPAGE1, 0);
++		/*  RPS program performs no explicit mem writes. */
++		WR7146(P_RPS1_TOUT, 0);	/*  Disable RPS timeouts. */
+ 
+-		// SAA7146 BUG WORKAROUND.  Initialize SAA7146 ADC interface to a
+-		// known state by invoking ADCs until FB BUFFER 1 register shows
+-		// that it is correctly receiving ADC data.  This is necessary
+-		// because the SAA7146 ADC interface does not start up in a
+-		// defined state after a PCI reset.
++		/* SAA7146 BUG WORKAROUND.  Initialize SAA7146 ADC interface
++		 * to a known state by invoking ADCs until FB BUFFER 1
++		 * register shows that it is correctly receiving ADC data.
++		 * This is necessary because the SAA7146 ADC interface does
++		 * not start up in a defined state after a PCI reset.
++		 */
+ 
+ /*     PollList = EOPL;			// Create a simple polling */
+ /* 					// list for analog input */
+@@ -829,115 +819,123 @@ static int s626_attach(comedi_device * dev, comedi_devconfig * it)
+ /* 	  break; */
+ /*       } */
+ 
+-		// end initADC
++		/*  end initADC */
+ 
+-		// init the DAC interface
++		/*  init the DAC interface */
+ 
+-		// Init Audio2's output DMAC attributes: burst length = 1 DWORD,
+-		// threshold = 1 DWORD.
++		/* Init Audio2's output DMAC attributes: burst length = 1
++		 * DWORD,  threshold = 1 DWORD.
++		 */
+ 		WR7146(P_PCI_BT_A, 0);
+ 
+-		// Init Audio2's output DMA physical addresses.  The protection
+-		// address is set to 1 DWORD past the base address so that a
+-		// single DWORD will be transferred each time a DMA transfer is
+-		// enabled.
++		/* Init Audio2's output DMA physical addresses.  The protection
++		 * address is set to 1 DWORD past the base address so that a
++		 * single DWORD will be transferred each time a DMA transfer is
++		 * enabled. */
+ 
+ 		pPhysBuf =
+ 			devpriv->ANABuf.PhysicalBase +
+ 			(DAC_WDMABUF_OS * sizeof(uint32_t));
+ 
+-		WR7146(P_BASEA2_OUT, (uint32_t) pPhysBuf);	// Buffer base adrs.
+-		WR7146(P_PROTA2_OUT, (uint32_t) (pPhysBuf + sizeof(uint32_t)));	// Protection address.
++		WR7146(P_BASEA2_OUT, (uint32_t) pPhysBuf);	/*  Buffer base adrs. */
++		WR7146(P_PROTA2_OUT, (uint32_t) (pPhysBuf + sizeof(uint32_t)));	/*  Protection address. */
+ 
+-		// Cache Audio2's output DMA buffer logical address.  This is
+-		// where DAC data is buffered for A2 output DMA transfers.
++		/* Cache Audio2's output DMA buffer logical address.  This is
++		 * where DAC data is buffered for A2 output DMA transfers. */
+ 		devpriv->pDacWBuf =
+ 			(uint32_t *) devpriv->ANABuf.LogicalBase +
+ 			DAC_WDMABUF_OS;
+ 
+-		// Audio2's output channels does not use paging.  The protection
+-		// violation handling bit is set so that the DMAC will
+-		// automatically halt and its PCI address pointer will be reset
+-		// when the protection address is reached.
++		/* Audio2's output channels does not use paging.  The protection
++		 * violation handling bit is set so that the DMAC will
++		 * automatically halt and its PCI address pointer will be reset
++		 * when the protection address is reached. */
++
+ 		WR7146(P_PAGEA2_OUT, 8);
+ 
+-		// Initialize time slot list 2 (TSL2), which is used to control
+-		// the clock generation for and serialization of data to be sent
+-		// to the DAC devices.  Slot 0 is a NOP that is used to trap TSL
+-		// execution; this permits other slots to be safely modified
+-		// without first turning off the TSL sequencer (which is
+-		// apparently impossible to do).  Also, SD3 (which is driven by a
+-		// pull-up resistor) is shifted in and stored to the MSB of
+-		// FB_BUFFER2 to be used as evidence that the slot sequence has
+-		// not yet finished executing.
+-		SETVECT(0, XSD2 | RSD3 | SIB_A2 | EOS);	// Slot 0: Trap TSL
+-		// execution, shift 0xFF
+-		// into FB_BUFFER2.
+-
+-		// Initialize slot 1, which is constant.  Slot 1 causes a DWORD to
+-		// be transferred from audio channel 2's output FIFO to the FIFO's
+-		// output buffer so that it can be serialized and sent to the DAC
+-		// during subsequent slots.  All remaining slots are dynamically
+-		// populated as required by the target DAC device.
+-		SETVECT(1, LF_A2);	// Slot 1: Fetch DWORD from Audio2's
+-		// output FIFO.
+-
+-		// Start DAC's audio interface (TSL2) running.
++		/* Initialize time slot list 2 (TSL2), which is used to control
++		 * the clock generation for and serialization of data to be sent
++		 * to the DAC devices.  Slot 0 is a NOP that is used to trap TSL
++		 * execution; this permits other slots to be safely modified
++		 * without first turning off the TSL sequencer (which is
++		 * apparently impossible to do).  Also, SD3 (which is driven by a
++		 * pull-up resistor) is shifted in and stored to the MSB of
++		 * FB_BUFFER2 to be used as evidence that the slot sequence has
++		 * not yet finished executing.
++		 */
++
++		SETVECT(0, XSD2 | RSD3 | SIB_A2 | EOS);
++		/*  Slot 0: Trap TSL execution, shift 0xFF into FB_BUFFER2. */
++
++		/* Initialize slot 1, which is constant.  Slot 1 causes a
++		 * DWORD to be transferred from audio channel 2's output FIFO
++		 * to the FIFO's output buffer so that it can be serialized
++		 * and sent to the DAC during subsequent slots.  All remaining
++		 * slots are dynamically populated as required by the target
++		 * DAC device.
++		 */
++		SETVECT(1, LF_A2);
++		/*  Slot 1: Fetch DWORD from Audio2's output FIFO. */
++
++		/*  Start DAC's audio interface (TSL2) running. */
+ 		WR7146(P_ACON1, ACON1_DACSTART);
+ 
+-		////////////////////////////////////////////////////////
+-
+-		// end init DAC interface
++		/* end init DAC interface */
+ 
+-		// Init Trim DACs to calibrated values.  Do it twice because the
+-		// SAA7146 audio channel does not always reset properly and
+-		// sometimes causes the first few TrimDAC writes to malfunction.
++		/* Init Trim DACs to calibrated values.  Do it twice because the
++		 * SAA7146 audio channel does not always reset properly and
++		 * sometimes causes the first few TrimDAC writes to malfunction.
++		 */
+ 
+ 		LoadTrimDACs(dev);
+-		LoadTrimDACs(dev);	// Insurance.
++		LoadTrimDACs(dev);	/*  Insurance. */
+ 
+-		//////////////////////////////////////////////////////////////////
+-		// Manually init all gate array hardware in case this is a soft
+-		// reset (we have no way of determining whether this is a warm or
+-		// cold start).  This is necessary because the gate array will
+-		// reset only in response to a PCI hard reset; there is no soft
+-		// reset function.
++		/* Manually init all gate array hardware in case this is a soft
++		 * reset (we have no way of determining whether this is a warm
++		 * or cold start).  This is necessary because the gate array will
++		 * reset only in response to a PCI hard reset; there is no soft
++		 * reset function. */
+ 
+-		// Init all DAC outputs to 0V and init all DAC setpoint and
+-		// polarity images.
++		/* Init all DAC outputs to 0V and init all DAC setpoint and
++		 * polarity images.
++		 */
+ 		for (chan = 0; chan < S626_DAC_CHANNELS; chan++)
+ 			SetDAC(dev, chan, 0);
+ 
+-		// Init image of WRMISC2 Battery Charger Enabled control bit.
+-		// This image is used when the state of the charger control bit,
+-		// which has no direct hardware readback mechanism, is queried.
++		/* Init image of WRMISC2 Battery Charger Enabled control bit.
++		 * This image is used when the state of the charger control bit,
++		 * which has no direct hardware readback mechanism, is queried.
++		 */
+ 		devpriv->ChargeEnabled = 0;
+ 
+-		// Init image of watchdog timer interval in WRMISC2.  This image
+-		// maintains the value of the control bits of MISC2 are
+-		// continuously reset to zero as long as the WD timer is disabled.
++		/* Init image of watchdog timer interval in WRMISC2.  This image
++		 * maintains the value of the control bits of MISC2 are
++		 * continuously reset to zero as long as the WD timer is disabled.
++		 */
+ 		devpriv->WDInterval = 0;
+ 
+-		// Init Counter Interrupt enab mask for RDMISC2.  This mask is
+-		// applied against MISC2 when testing to determine which timer
+-		// events are requesting interrupt service.
++		/* Init Counter Interrupt enab mask for RDMISC2.  This mask is
++		 * applied against MISC2 when testing to determine which timer
++		 * events are requesting interrupt service.
++		 */
+ 		devpriv->CounterIntEnabs = 0;
+ 
+-		// Init counters.
++		/*  Init counters. */
+ 		CountersInit(dev);
+ 
+-		// Without modifying the state of the Battery Backup enab, disable
+-		// the watchdog timer, set DIO channels 0-5 to operate in the
+-		// standard DIO (vs. counter overflow) mode, disable the battery
+-		// charger, and reset the watchdog interval selector to zero.
++		/* Without modifying the state of the Battery Backup enab, disable
++		 * the watchdog timer, set DIO channels 0-5 to operate in the
++		 * standard DIO (vs. counter overflow) mode, disable the battery
++		 * charger, and reset the watchdog interval selector to zero.
++		 */
+ 		WriteMISC2(dev, (uint16_t) (DEBIread(dev,
+ 					LP_RDMISC2) & MISC2_BATT_ENABLE));
+ 
+-		// Initialize the digital I/O subsystem.
++		/*  Initialize the digital I/O subsystem. */
+ 		s626_dio_init(dev);
+ 
+-		//enable interrupt test
+-		// writel(IRQ_GPIO3 | IRQ_RPS1,devpriv->base_addr+P_IER);
++		/* enable interrupt test */
++		/*  writel(IRQ_GPIO3 | IRQ_RPS1,devpriv->base_addr+P_IER); */
+ 	}
+ 
+ 	DEBUG("s626_attach: comedi%d s626 attached %04x\n", dev->minor,
+@@ -981,47 +979,48 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG)
+ 
+ 	if (dev->attached == 0)
+ 		return IRQ_NONE;
+-	// lock to avoid race with comedi_poll
++	/*  lock to avoid race with comedi_poll */
+ 	comedi_spin_lock_irqsave(&dev->spinlock, flags);
+ 
+-	//save interrupt enable register state
++	/* save interrupt enable register state */
+ 	irqstatus = readl(devpriv->base_addr + P_IER);
+ 
+-	//read interrupt type
++	/* read interrupt type */
+ 	irqtype = readl(devpriv->base_addr + P_ISR);
+ 
+-	//disable master interrupt
++	/* disable master interrupt */
+ 	writel(0, devpriv->base_addr + P_IER);
+ 
+-	//clear interrupt
++	/* clear interrupt */
+ 	writel(irqtype, devpriv->base_addr + P_ISR);
+ 
+-	//do somethings
++	/* do somethings */
+ 	DEBUG("s626_irq_handler: interrupt type %d\n", irqtype);
+ 
+ 	switch (irqtype) {
+-	case IRQ_RPS1:		// end_of_scan occurs
++	case IRQ_RPS1:		/*  end_of_scan occurs */
+ 
+ 		DEBUG("s626_irq_handler: RPS1 irq detected\n");
+ 
+-		// manage ai subdevice
++		/*  manage ai subdevice */
+ 		s = dev->subdevices;
+ 		cmd = &(s->async->cmd);
+ 
+-		// Init ptr to DMA buffer that holds new ADC data.  We skip the
+-		// first uint16_t in the buffer because it contains junk data from
+-		// the final ADC of the previous poll list scan.
++		/* Init ptr to DMA buffer that holds new ADC data.  We skip the
++		 * first uint16_t in the buffer because it contains junk data from
++		 * the final ADC of the previous poll list scan.
++		 */
+ 		readaddr = (int32_t *) devpriv->ANABuf.LogicalBase + 1;
+ 
+-		// get the data and hand it over to comedi
++		/*  get the data and hand it over to comedi */
+ 		for (i = 0; i < (s->async->cmd.chanlist_len); i++) {
+-			// Convert ADC data to 16-bit integer values and copy to application
+-			// buffer.
++			/*  Convert ADC data to 16-bit integer values and copy to application */
++			/*  buffer. */
+ 			tempdata = s626_ai_reg_to_uint((int)*readaddr);
+ 			readaddr++;
+ 
+-			//put data into read buffer
+-			// comedi_buf_put(s->async, tempdata);
++			/* put data into read buffer */
++			/*  comedi_buf_put(s->async, tempdata); */
+ 			if (cfc_write_to_buffer(s, tempdata) == 0)
+ 				printk("s626_irq_handler: cfc_write_to_buffer error!\n");
+ 
+@@ -1029,7 +1028,7 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG)
+ 				i, tempdata);
+ 		}
+ 
+-		//end of scan occurs
++		/* end of scan occurs */
+ 		s->async->events |= COMEDI_CB_EOS;
+ 
+ 		if (!(devpriv->ai_continous))
+@@ -1037,13 +1036,13 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG)
+ 		if (devpriv->ai_sample_count <= 0) {
+ 			devpriv->ai_cmd_running = 0;
+ 
+-			// Stop RPS program.
++			/*  Stop RPS program. */
+ 			MC_DISABLE(P_MC1, MC1_ERPS1);
+ 
+-			//send end of acquisition
++			/* send end of acquisition */
+ 			s->async->events |= COMEDI_CB_EOA;
+ 
+-			//disable master interrupt
++			/* disable master interrupt */
+ 			irqstatus = 0;
+ 		}
+ 
+@@ -1054,40 +1053,40 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG)
+ 
+ 			DEBUG("s626_irq_handler: External trigger is set!!!\n");
+ 		}
+-		// tell comedi that data is there
++		/*  tell comedi that data is there */
+ 		DEBUG("s626_irq_handler: events %d\n", s->async->events);
+ 		comedi_event(dev, s);
+ 		break;
+-	case IRQ_GPIO3:	//check dio and conter interrupt
++	case IRQ_GPIO3:	/* check dio and conter interrupt */
+ 
+ 		DEBUG("s626_irq_handler: GPIO3 irq detected\n");
+ 
+-		// manage ai subdevice
++		/*  manage ai subdevice */
+ 		s = dev->subdevices;
+ 		cmd = &(s->async->cmd);
+ 
+-		//s626_dio_clear_irq(dev);
++		/* s626_dio_clear_irq(dev); */
+ 
+ 		for (group = 0; group < S626_DIO_BANKS; group++) {
+ 			irqbit = 0;
+-			//read interrupt type
++			/* read interrupt type */
+ 			irqbit = DEBIread(dev,
+ 				((dio_private *) (dev->subdevices + 2 +
+ 						group)->private)->RDCapFlg);
+ 
+-			//check if interrupt is generated from dio channels
++			/* check if interrupt is generated from dio channels */
+ 			if (irqbit) {
+ 				s626_dio_reset_irq(dev, group, irqbit);
+ 				DEBUG("s626_irq_handler: check interrupt on dio group %d %d\n", group, i);
+ 				if (devpriv->ai_cmd_running) {
+-					//check if interrupt is an ai acquisition start trigger
++					/* check if interrupt is an ai acquisition start trigger */
+ 					if ((irqbit >> (cmd->start_arg -
+ 								(16 * group)))
+ 						== 1
+ 						&& cmd->start_src == TRIG_EXT) {
+ 						DEBUG("s626_irq_handler: Edge capture interrupt recieved from channel %d\n", cmd->start_arg);
+ 
+-						// Start executing the RPS program.
++						/*  Start executing the RPS program. */
+ 						MC_ENABLE(P_MC1, MC1_ERPS1);
+ 
+ 						DEBUG("s626_irq_handler: aquisition start triggered!!!\n");
+@@ -1110,7 +1109,7 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG)
+ 						TRIG_EXT) {
+ 						DEBUG("s626_irq_handler: Edge capture interrupt recieved from channel %d\n", cmd->scan_begin_arg);
+ 
+-						// Trigger ADC scan loop start by setting RPS Signal 0.
++						/*  Trigger ADC scan loop start by setting RPS Signal 0. */
+ 						MC_ENABLE(P_MC2, MC2_ADC_RPS);
+ 
+ 						DEBUG("s626_irq_handler: scan triggered!!! %d\n", devpriv->ai_sample_count);
+@@ -1151,7 +1150,7 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG)
+ 						TRIG_EXT) {
+ 						DEBUG("s626_irq_handler: Edge capture interrupt recieved from channel %d\n", cmd->convert_arg);
+ 
+-						// Trigger ADC scan loop start by setting RPS Signal 0.
++						/*  Trigger ADC scan loop start by setting RPS Signal 0. */
+ 						MC_ENABLE(P_MC2, MC2_ADC_RPS);
+ 
+ 						DEBUG("s626_irq_handler: adc convert triggered!!!\n");
+@@ -1175,10 +1174,10 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG)
+ 			}
+ 		}
+ 
+-		//read interrupt type
++		/* read interrupt type */
+ 		irqbit = DEBIread(dev, LP_RDMISC2);
+ 
+-		//check interrupt on counters
++		/* check interrupt on counters */
+ 		DEBUG("s626_irq_handler: check counters interrupt %d\n",
+ 			irqbit);
+ 
+@@ -1186,35 +1185,35 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG)
+ 			DEBUG("s626_irq_handler: interrupt on counter 1A overflow\n");
+ 			k = &encpriv[0];
+ 
+-			//clear interrupt capture flag
++			/* clear interrupt capture flag */
+ 			k->ResetCapFlags(dev, k);
+ 		}
+ 		if (irqbit & IRQ_COINT2A) {
+ 			DEBUG("s626_irq_handler: interrupt on counter 2A overflow\n");
+ 			k = &encpriv[1];
+ 
+-			//clear interrupt capture flag
++			/* clear interrupt capture flag */
+ 			k->ResetCapFlags(dev, k);
+ 		}
+ 		if (irqbit & IRQ_COINT3A) {
+ 			DEBUG("s626_irq_handler: interrupt on counter 3A overflow\n");
+ 			k = &encpriv[2];
+ 
+-			//clear interrupt capture flag
++			/* clear interrupt capture flag */
+ 			k->ResetCapFlags(dev, k);
+ 		}
+ 		if (irqbit & IRQ_COINT1B) {
+ 			DEBUG("s626_irq_handler: interrupt on counter 1B overflow\n");
+ 			k = &encpriv[3];
+ 
+-			//clear interrupt capture flag
++			/* clear interrupt capture flag */
+ 			k->ResetCapFlags(dev, k);
+ 		}
+ 		if (irqbit & IRQ_COINT2B) {
+ 			DEBUG("s626_irq_handler: interrupt on counter 2B overflow\n");
+ 			k = &encpriv[4];
+ 
+-			//clear interrupt capture flag
++			/* clear interrupt capture flag */
+ 			k->ResetCapFlags(dev, k);
+ 
+ 			if (devpriv->ai_convert_count > 0) {
+@@ -1225,7 +1224,7 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG)
+ 				if (cmd->convert_src == TRIG_TIMER) {
+ 					DEBUG("s626_irq_handler: conver timer trigger!!! %d\n", devpriv->ai_convert_count);
+ 
+-					// Trigger ADC scan loop start by setting RPS Signal 0.
++					/*  Trigger ADC scan loop start by setting RPS Signal 0. */
+ 					MC_ENABLE(P_MC2, MC2_ADC_RPS);
+ 				}
+ 			}
+@@ -1234,13 +1233,13 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG)
+ 			DEBUG("s626_irq_handler: interrupt on counter 3B overflow\n");
+ 			k = &encpriv[5];
+ 
+-			//clear interrupt capture flag
++			/* clear interrupt capture flag */
+ 			k->ResetCapFlags(dev, k);
+ 
+ 			if (cmd->scan_begin_src == TRIG_TIMER) {
+ 				DEBUG("s626_irq_handler: scan timer trigger!!!\n");
+ 
+-				// Trigger ADC scan loop start by setting RPS Signal 0.
++				/*  Trigger ADC scan loop start by setting RPS Signal 0. */
+ 				MC_ENABLE(P_MC2, MC2_ADC_RPS);
+ 			}
+ 
+@@ -1253,7 +1252,7 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG)
+ 		}
+ 	}
+ 
+-	//enable interrupt
++	/* enable interrupt */
+ 	writel(irqstatus, devpriv->base_addr + P_IER);
+ 
+ 	DEBUG("s626_irq_handler: exit interrupt service routine.\n");
+@@ -1265,18 +1264,18 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG)
+ static int s626_detach(comedi_device * dev)
+ {
+ 	if (devpriv) {
+-		//stop ai_command
++		/* stop ai_command */
+ 		devpriv->ai_cmd_running = 0;
+ 
+ 		if (devpriv->base_addr) {
+-			//interrupt mask
+-			WR7146(P_IER, 0);	// Disable master interrupt.
+-			WR7146(P_ISR, IRQ_GPIO3 | IRQ_RPS1);	// Clear board's IRQ status flag.
++			/* interrupt mask */
++			WR7146(P_IER, 0);	/*  Disable master interrupt. */
++			WR7146(P_ISR, IRQ_GPIO3 | IRQ_RPS1);	/*  Clear board's IRQ status flag. */
+ 
+-			// Disable the watchdog timer and battery charger.
++			/*  Disable the watchdog timer and battery charger. */
+ 			WriteMISC2(dev, 0);
+ 
+-			// Close all interfaces on 7146 device.
++			/*  Close all interfaces on 7146 device. */
+ 			WR7146(P_MC1, MC1_SHUTDOWN);
+ 			WR7146(P_ACON1, ACON1_BASE);
+ 
+@@ -1317,174 +1316,186 @@ void ResetADC(comedi_device * dev, uint8_t * ppl)
+ 	uint32_t LocalPPL;
+ 	comedi_cmd *cmd = &(dev->subdevices->async->cmd);
+ 
+-	// Stop RPS program in case it is currently running.
++	/*  Stop RPS program in case it is currently running. */
+ 	MC_DISABLE(P_MC1, MC1_ERPS1);
+ 
+-	// Set starting logical address to write RPS commands.
++	/*  Set starting logical address to write RPS commands. */
+ 	pRPS = (uint32_t *) devpriv->RPSBuf.LogicalBase;
+ 
+-	// Initialize RPS instruction pointer.
++	/*  Initialize RPS instruction pointer. */
+ 	WR7146(P_RPSADDR1, (uint32_t) devpriv->RPSBuf.PhysicalBase);
+ 
+-	// Construct RPS program in RPSBuf DMA buffer
++	/*  Construct RPS program in RPSBuf DMA buffer */
+ 
+ 	if (cmd != NULL && cmd->scan_begin_src != TRIG_FOLLOW) {
+ 		DEBUG("ResetADC: scan_begin pause inserted\n");
+-		// Wait for Start trigger.
++		/*  Wait for Start trigger. */
+ 		*pRPS++ = RPS_PAUSE | RPS_SIGADC;
+ 		*pRPS++ = RPS_CLRSIGNAL | RPS_SIGADC;
+ 	}
+-	// SAA7146 BUG WORKAROUND Do a dummy DEBI Write.  This is necessary
+-	// because the first RPS DEBI Write following a non-RPS DEBI write
+-	// seems to always fail.  If we don't do this dummy write, the ADC
+-	// gain might not be set to the value required for the first slot in
+-	// the poll list; the ADC gain would instead remain unchanged from
+-	// the previously programmed value.
+-	*pRPS++ = RPS_LDREG | (P_DEBICMD >> 2);	// Write DEBI Write command
+-	// and address to shadow RAM.
++
++	/* SAA7146 BUG WORKAROUND Do a dummy DEBI Write.  This is necessary
++	 * because the first RPS DEBI Write following a non-RPS DEBI write
++	 * seems to always fail.  If we don't do this dummy write, the ADC
++	 * gain might not be set to the value required for the first slot in
++	 * the poll list; the ADC gain would instead remain unchanged from
++	 * the previously programmed value.
++	 */
++	*pRPS++ = RPS_LDREG | (P_DEBICMD >> 2);
++	/* Write DEBI Write command and address to shadow RAM. */
++
+ 	*pRPS++ = DEBI_CMD_WRWORD | LP_GSEL;
+-	*pRPS++ = RPS_LDREG | (P_DEBIAD >> 2);	// Write DEBI immediate data
+-	// to shadow RAM:
+-	*pRPS++ = GSEL_BIPOLAR5V;	// arbitrary immediate data
+-	// value.
+-	*pRPS++ = RPS_CLRSIGNAL | RPS_DEBI;	// Reset "shadow RAM
+-	// uploaded" flag.
+-	*pRPS++ = RPS_UPLOAD | RPS_DEBI;	// Invoke shadow RAM upload.
+-	*pRPS++ = RPS_PAUSE | RPS_DEBI;	// Wait for shadow upload to finish.
+-
+-	// Digitize all slots in the poll list. This is implemented as a
+-	// for loop to limit the slot count to 16 in case the application
+-	// forgot to set the EOPL flag in the final slot.
++	*pRPS++ = RPS_LDREG | (P_DEBIAD >> 2);
++	/*  Write DEBI immediate data  to shadow RAM: */
++
++	*pRPS++ = GSEL_BIPOLAR5V;
++	/*  arbitrary immediate data  value. */
++
++	*pRPS++ = RPS_CLRSIGNAL | RPS_DEBI;
++	/*  Reset "shadow RAM  uploaded" flag. */
++	*pRPS++ = RPS_UPLOAD | RPS_DEBI;	/*  Invoke shadow RAM upload. */
++	*pRPS++ = RPS_PAUSE | RPS_DEBI;	/*  Wait for shadow upload to finish. */
++
++	/* Digitize all slots in the poll list. This is implemented as a
++	 * for loop to limit the slot count to 16 in case the application
++	 * forgot to set the EOPL flag in the final slot.
++	 */
+ 	for (devpriv->AdcItems = 0; devpriv->AdcItems < 16; devpriv->AdcItems++) {
+-		// Convert application's poll list item to private board class
+-		// format.  Each app poll list item is an uint8_t with form
+-		// (EOPL,x,x,RANGE,CHAN<3:0>), where RANGE code indicates 0 =
+-		// +-10V, 1 = +-5V, and EOPL = End of Poll List marker.
++	 /* Convert application's poll list item to private board class
++	  * format.  Each app poll list item is an uint8_t with form
++	  * (EOPL,x,x,RANGE,CHAN<3:0>), where RANGE code indicates 0 =
++	  * +-10V, 1 = +-5V, and EOPL = End of Poll List marker.
++	  */
+ 		LocalPPL =
+ 			(*ppl << 8) | (*ppl & 0x10 ? GSEL_BIPOLAR5V :
+ 			GSEL_BIPOLAR10V);
+ 
+-		// Switch ADC analog gain.
+-		*pRPS++ = RPS_LDREG | (P_DEBICMD >> 2);	// Write DEBI command
+-		// and address to
+-		// shadow RAM.
++		/*  Switch ADC analog gain. */
++		*pRPS++ = RPS_LDREG | (P_DEBICMD >> 2);	/*  Write DEBI command */
++		/*  and address to */
++		/*  shadow RAM. */
+ 		*pRPS++ = DEBI_CMD_WRWORD | LP_GSEL;
+-		*pRPS++ = RPS_LDREG | (P_DEBIAD >> 2);	// Write DEBI
+-		// immediate data to
+-		// shadow RAM.
++		*pRPS++ = RPS_LDREG | (P_DEBIAD >> 2);	/*  Write DEBI */
++		/*  immediate data to */
++		/*  shadow RAM. */
+ 		*pRPS++ = LocalPPL;
+-		*pRPS++ = RPS_CLRSIGNAL | RPS_DEBI;	// Reset "shadow RAM uploaded"
+-		// flag.
+-		*pRPS++ = RPS_UPLOAD | RPS_DEBI;	// Invoke shadow RAM upload.
+-		*pRPS++ = RPS_PAUSE | RPS_DEBI;	// Wait for shadow upload to
+-		// finish.
+-
+-		// Select ADC analog input channel.
+-		*pRPS++ = RPS_LDREG | (P_DEBICMD >> 2);	// Write DEBI command
+-		// and address to
+-		// shadow RAM.
++		*pRPS++ = RPS_CLRSIGNAL | RPS_DEBI;	/*  Reset "shadow RAM uploaded" */
++		/*  flag. */
++		*pRPS++ = RPS_UPLOAD | RPS_DEBI;	/*  Invoke shadow RAM upload. */
++		*pRPS++ = RPS_PAUSE | RPS_DEBI;	/*  Wait for shadow upload to */
++		/*  finish. */
++
++		/*  Select ADC analog input channel. */
++		*pRPS++ = RPS_LDREG | (P_DEBICMD >> 2);
++		/*  Write DEBI command and address to  shadow RAM. */
+ 		*pRPS++ = DEBI_CMD_WRWORD | LP_ISEL;
+-		*pRPS++ = RPS_LDREG | (P_DEBIAD >> 2);	// Write DEBI
+-		// immediate data to
+-		// shadow RAM.
++		*pRPS++ = RPS_LDREG | (P_DEBIAD >> 2);
++		/*  Write DEBI immediate data to shadow RAM. */
+ 		*pRPS++ = LocalPPL;
+-		*pRPS++ = RPS_CLRSIGNAL | RPS_DEBI;	// Reset "shadow RAM uploaded"
+-		// flag.
+-		*pRPS++ = RPS_UPLOAD | RPS_DEBI;	// Invoke shadow RAM upload.
+-		*pRPS++ = RPS_PAUSE | RPS_DEBI;	// Wait for shadow upload to
+-		// finish.
+-
+-		// Delay at least 10 microseconds for analog input settling.
+-		// Instead of padding with NOPs, we use RPS_JUMP instructions
+-		// here; this allows us to produce a longer delay than is
+-		// possible with NOPs because each RPS_JUMP flushes the RPS'
+-		// instruction prefetch pipeline.
++		*pRPS++ = RPS_CLRSIGNAL | RPS_DEBI;
++		/*  Reset "shadow RAM uploaded"  flag. */
++
++		*pRPS++ = RPS_UPLOAD | RPS_DEBI;
++		/*  Invoke shadow RAM upload. */
++
++		*pRPS++ = RPS_PAUSE | RPS_DEBI;
++		/*  Wait for shadow upload to finish. */
++
++		/* Delay at least 10 microseconds for analog input settling.
++		 * Instead of padding with NOPs, we use RPS_JUMP instructions
++		 * here; this allows us to produce a longer delay than is
++		 * possible with NOPs because each RPS_JUMP flushes the RPS'
++		 * instruction prefetch pipeline.
++		 */
+ 		JmpAdrs =
+ 			(uint32_t) devpriv->RPSBuf.PhysicalBase +
+ 			(uint32_t) ((unsigned long)pRPS -
+ 			(unsigned long)devpriv->RPSBuf.LogicalBase);
+ 		for (i = 0; i < (10 * RPSCLK_PER_US / 2); i++) {
+-			JmpAdrs += 8;	// Repeat to implement time delay:
+-			*pRPS++ = RPS_JUMP;	// Jump to next RPS instruction.
++			JmpAdrs += 8;	/*  Repeat to implement time delay: */
++			*pRPS++ = RPS_JUMP;	/*  Jump to next RPS instruction. */
+ 			*pRPS++ = JmpAdrs;
+ 		}
+ 
+ 		if (cmd != NULL && cmd->convert_src != TRIG_NOW) {
+ 			DEBUG("ResetADC: convert pause inserted\n");
+-			// Wait for Start trigger.
++			/*  Wait for Start trigger. */
+ 			*pRPS++ = RPS_PAUSE | RPS_SIGADC;
+ 			*pRPS++ = RPS_CLRSIGNAL | RPS_SIGADC;
+ 		}
+-		// Start ADC by pulsing GPIO1.
+-		*pRPS++ = RPS_LDREG | (P_GPIO >> 2);	// Begin ADC Start pulse.
++		/*  Start ADC by pulsing GPIO1. */
++		*pRPS++ = RPS_LDREG | (P_GPIO >> 2);	/*  Begin ADC Start pulse. */
+ 		*pRPS++ = GPIO_BASE | GPIO1_LO;
+ 		*pRPS++ = RPS_NOP;
+-		// VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE.
+-		*pRPS++ = RPS_LDREG | (P_GPIO >> 2);	// End ADC Start pulse.
++		/*  VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE. */
++		*pRPS++ = RPS_LDREG | (P_GPIO >> 2);	/*  End ADC Start pulse. */
+ 		*pRPS++ = GPIO_BASE | GPIO1_HI;
+ 
+-		// Wait for ADC to complete (GPIO2 is asserted high when ADC not
+-		// busy) and for data from previous conversion to shift into FB
+-		// BUFFER 1 register.
+-		*pRPS++ = RPS_PAUSE | RPS_GPIO2;	// Wait for ADC done.
++		/* Wait for ADC to complete (GPIO2 is asserted high when ADC not
++		 * busy) and for data from previous conversion to shift into FB
++		 * BUFFER 1 register.
++		 */
++		*pRPS++ = RPS_PAUSE | RPS_GPIO2;	/*  Wait for ADC done. */
+ 
+-		// Transfer ADC data from FB BUFFER 1 register to DMA buffer.
++		/*  Transfer ADC data from FB BUFFER 1 register to DMA buffer. */
+ 		*pRPS++ = RPS_STREG | (BUGFIX_STREG(P_FB_BUFFER1) >> 2);
+ 		*pRPS++ =
+ 			(uint32_t) devpriv->ANABuf.PhysicalBase +
+ 			(devpriv->AdcItems << 2);
+ 
+-		// If this slot's EndOfPollList flag is set, all channels have
+-		// now been processed.
++		/*  If this slot's EndOfPollList flag is set, all channels have */
++		/*  now been processed. */
+ 		if (*ppl++ & EOPL) {
+-			devpriv->AdcItems++;	// Adjust poll list item count.
+-			break;	// Exit poll list processing loop.
++			devpriv->AdcItems++;	/*  Adjust poll list item count. */
++			break;	/*  Exit poll list processing loop. */
+ 		}
+ 	}
+ 	DEBUG("ResetADC: ADC items %d \n", devpriv->AdcItems);
+ 
+-	// VERSION 2.01 CHANGE: DELAY CHANGED FROM 250NS to 2US.  Allow the
+-	// ADC to stabilize for 2 microseconds before starting the final
+-	// (dummy) conversion.  This delay is necessary to allow sufficient
+-	// time between last conversion finished and the start of the dummy
+-	// conversion.  Without this delay, the last conversion's data value
+-	// is sometimes set to the previous conversion's data value.
++	/* VERSION 2.01 CHANGE: DELAY CHANGED FROM 250NS to 2US.  Allow the
++	 * ADC to stabilize for 2 microseconds before starting the final
++	 * (dummy) conversion.  This delay is necessary to allow sufficient
++	 * time between last conversion finished and the start of the dummy
++	 * conversion.  Without this delay, the last conversion's data value
++	 * is sometimes set to the previous conversion's data value.
++	 */
+ 	for (n = 0; n < (2 * RPSCLK_PER_US); n++)
+ 		*pRPS++ = RPS_NOP;
+ 
+-	// Start a dummy conversion to cause the data from the last
+-	// conversion of interest to be shifted in.
+-	*pRPS++ = RPS_LDREG | (P_GPIO >> 2);	// Begin ADC Start pulse.
++	/* Start a dummy conversion to cause the data from the last
++	 * conversion of interest to be shifted in.
++	 */
++	*pRPS++ = RPS_LDREG | (P_GPIO >> 2);	/*  Begin ADC Start pulse. */
+ 	*pRPS++ = GPIO_BASE | GPIO1_LO;
+ 	*pRPS++ = RPS_NOP;
+-	// VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE.
+-	*pRPS++ = RPS_LDREG | (P_GPIO >> 2);	// End ADC Start pulse.
++	/* VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE. */
++	*pRPS++ = RPS_LDREG | (P_GPIO >> 2);	/*  End ADC Start pulse. */
+ 	*pRPS++ = GPIO_BASE | GPIO1_HI;
+ 
+-	// Wait for the data from the last conversion of interest to arrive
+-	// in FB BUFFER 1 register.
+-	*pRPS++ = RPS_PAUSE | RPS_GPIO2;	// Wait for ADC done.
++	/* Wait for the data from the last conversion of interest to arrive
++	 * in FB BUFFER 1 register.
++	 */
++	*pRPS++ = RPS_PAUSE | RPS_GPIO2;	/*  Wait for ADC done. */
+ 
+-	// Transfer final ADC data from FB BUFFER 1 register to DMA buffer.
+-	*pRPS++ = RPS_STREG | (BUGFIX_STREG(P_FB_BUFFER1) >> 2);	//
++	/*  Transfer final ADC data from FB BUFFER 1 register to DMA buffer. */
++	*pRPS++ = RPS_STREG | (BUGFIX_STREG(P_FB_BUFFER1) >> 2);	/*  */
+ 	*pRPS++ =
+ 		(uint32_t) devpriv->ANABuf.PhysicalBase +
+ 		(devpriv->AdcItems << 2);
+ 
+-	// Indicate ADC scan loop is finished.
+-	// *pRPS++= RPS_CLRSIGNAL | RPS_SIGADC ;  // Signal ReadADC() that scan is done.
++	/*  Indicate ADC scan loop is finished. */
++	/*  *pRPS++= RPS_CLRSIGNAL | RPS_SIGADC ;  // Signal ReadADC() that scan is done. */
+ 
+-	//invoke interrupt
++	/* invoke interrupt */
+ 	if (devpriv->ai_cmd_running == 1) {
+ 		DEBUG("ResetADC: insert irq in ADC RPS task\n");
+ 		*pRPS++ = RPS_IRQ;
+ 	}
+-	// Restart RPS program at its beginning.
+-	*pRPS++ = RPS_JUMP;	// Branch to start of RPS program.
++	/*  Restart RPS program at its beginning. */
++	*pRPS++ = RPS_JUMP;	/*  Branch to start of RPS program. */
+ 	*pRPS++ = (uint32_t) devpriv->RPSBuf.PhysicalBase;
+ 
+-	// End of RPS program build
+-	// ------------------------------------------------------------
++	/*  End of RPS program build */
+ }
+ 
+ /* TO COMPLETE, IF NECESSARY */
+@@ -1502,19 +1513,19 @@ static int s626_ai_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 
+ /*   DEBUG("as626_ai_rinsn: ai_rinsn enter \n");  */
+ 
+-/*   // Trigger ADC scan loop start by setting RPS Signal 0. */
++/*   Trigger ADC scan loop start by setting RPS Signal 0. */
+ /*   MC_ENABLE( P_MC2, MC2_ADC_RPS ); */
+ 
+-/*   // Wait until ADC scan loop is finished (RPS Signal 0 reset). */
++/*   Wait until ADC scan loop is finished (RPS Signal 0 reset). */
+ /*   while ( MC_TEST( P_MC2, MC2_ADC_RPS ) ); */
+ 
+-/*   // Init ptr to DMA buffer that holds new ADC data.  We skip the */
+-/*   // first uint16_t in the buffer because it contains junk data from */
+-/*   // the final ADC of the previous poll list scan. */
++/* Init ptr to DMA buffer that holds new ADC data.  We skip the
++ * first uint16_t in the buffer because it contains junk data from
++ * the final ADC of the previous poll list scan.
++ */
+ /*   readaddr = (uint32_t *)devpriv->ANABuf.LogicalBase + 1; */
+ 
+-/*   // Convert ADC data to 16-bit integer values and copy to application */
+-/*   // buffer.	 */
++/*  Convert ADC data to 16-bit integer values and copy to application buffer. */
+ /*   for ( i = 0; i < devpriv->AdcItems; i++ ) { */
+ /*     *data = s626_ai_reg_to_uint( *readaddr++ ); */
+ /*     DEBUG("s626_ai_rinsn: data %d \n",*data); */
+@@ -1534,86 +1545,85 @@ static int s626_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+ 	uint32_t GpioImage;
+ 	int n;
+ 
+-/*   //interrupt call test  */
+-/*   writel(IRQ_GPIO3,devpriv->base_addr+P_PSR); //Writing a logical 1 */
+-/* 					     //into any of the RPS_PSR */
+-/* 					     //bits causes the */
+-/* 					     //corresponding interrupt */
+-/* 					     //to be generated if */
+-/* 					     //enabled */
++ /* interrupt call test  */
++/*   writel(IRQ_GPIO3,devpriv->base_addr+P_PSR); */
++	/* Writing a logical 1 into any of the RPS_PSR bits causes the
++	 * corresponding interrupt to be generated if enabled
++	 */
+ 
+ 	DEBUG("s626_ai_insn_read: entering\n");
+ 
+-	// Convert application's ADC specification into form
+-	// appropriate for register programming.
++	/* Convert application's ADC specification into form
++	 *  appropriate for register programming.
++	 */
+ 	if (range == 0)
+ 		AdcSpec = (chan << 8) | (GSEL_BIPOLAR5V);
+ 	else
+ 		AdcSpec = (chan << 8) | (GSEL_BIPOLAR10V);
+ 
+-	// Switch ADC analog gain.
+-	DEBIwrite(dev, LP_GSEL, AdcSpec);	// Set gain.
++	/*  Switch ADC analog gain. */
++	DEBIwrite(dev, LP_GSEL, AdcSpec);	/*  Set gain. */
+ 
+-	// Select ADC analog input channel.
+-	DEBIwrite(dev, LP_ISEL, AdcSpec);	// Select channel.
++	/*  Select ADC analog input channel. */
++	DEBIwrite(dev, LP_ISEL, AdcSpec);	/*  Select channel. */
+ 
+ 	for (n = 0; n < insn->n; n++) {
+ 
+-		// Delay 10 microseconds for analog input settling.
++		/*  Delay 10 microseconds for analog input settling. */
+ 		comedi_udelay(10);
+ 
+-		// Start ADC by pulsing GPIO1 low.
++		/*  Start ADC by pulsing GPIO1 low. */
+ 		GpioImage = RR7146(P_GPIO);
+-		// Assert ADC Start command
++		/*  Assert ADC Start command */
+ 		WR7146(P_GPIO, GpioImage & ~GPIO1_HI);
+-		//   and stretch it out.
++		/*    and stretch it out. */
+ 		WR7146(P_GPIO, GpioImage & ~GPIO1_HI);
+ 		WR7146(P_GPIO, GpioImage & ~GPIO1_HI);
+-		// Negate ADC Start command.
++		/*  Negate ADC Start command. */
+ 		WR7146(P_GPIO, GpioImage | GPIO1_HI);
+ 
+-		// Wait for ADC to complete (GPIO2 is asserted high when
+-		// ADC not busy) and for data from previous conversion to
+-		// shift into FB BUFFER 1 register.
++		/*  Wait for ADC to complete (GPIO2 is asserted high when */
++		/*  ADC not busy) and for data from previous conversion to */
++		/*  shift into FB BUFFER 1 register. */
+ 
+-		// Wait for ADC done.
++		/*  Wait for ADC done. */
+ 		while (!(RR7146(P_PSR) & PSR_GPIO2)) ;
+ 
+-		// Fetch ADC data.
++		/*  Fetch ADC data. */
+ 		if (n != 0)
+ 			data[n - 1] = s626_ai_reg_to_uint(RR7146(P_FB_BUFFER1));
+ 
+-		// Allow the ADC to stabilize for 4 microseconds before
+-		// starting the next (final) conversion.  This delay is
+-		// necessary to allow sufficient time between last
+-		// conversion finished and the start of the next
+-		// conversion.  Without this delay, the last conversion's
+-		// data value is sometimes set to the previous
+-		// conversion's data value.
++		/* Allow the ADC to stabilize for 4 microseconds before
++		 * starting the next (final) conversion.  This delay is
++		 * necessary to allow sufficient time between last
++		 * conversion finished and the start of the next
++		 * conversion.  Without this delay, the last conversion's
++		 * data value is sometimes set to the previous
++		 * conversion's data value.
++		 */
+ 		comedi_udelay(4);
+ 	}
+ 
+-	// Start a dummy conversion to cause the data from the
+-	// previous conversion to be shifted in.
++	/* Start a dummy conversion to cause the data from the
++	 * previous conversion to be shifted in. */
+ 	GpioImage = RR7146(P_GPIO);
+ 
+-	//Assert ADC Start command
++	/* Assert ADC Start command */
+ 	WR7146(P_GPIO, GpioImage & ~GPIO1_HI);
+-	//   and stretch it out.
++	/*    and stretch it out. */
+ 	WR7146(P_GPIO, GpioImage & ~GPIO1_HI);
+ 	WR7146(P_GPIO, GpioImage & ~GPIO1_HI);
+-	// Negate ADC Start command.
++	/*  Negate ADC Start command. */
+ 	WR7146(P_GPIO, GpioImage | GPIO1_HI);
+ 
+-	// Wait for the data to arrive in FB BUFFER 1 register.
++	/*  Wait for the data to arrive in FB BUFFER 1 register. */
+ 
+-	// Wait for ADC done.
++	/*  Wait for ADC done. */
+ 	while (!(RR7146(P_PSR) & PSR_GPIO2)) ;
+ 
+-	// Fetch ADC data from audio interface's input shift
+-	// register.
++	/*  Fetch ADC data from audio interface's input shift register. */
+ 
+-	// Fetch ADC data.
++	/*  Fetch ADC data. */
+ 	if (n != 0)
+ 		data[n - 1] = s626_ai_reg_to_uint(RR7146(P_FB_BUFFER1));
+ 
+@@ -1646,7 +1656,7 @@ static int s626_ai_inttrig(comedi_device * dev, comedi_subdevice * s,
+ 
+ 	DEBUG("s626_ai_inttrig: trigger adc start...");
+ 
+-	// Start executing the RPS program.
++	/*  Start executing the RPS program. */
+ 	MC_ENABLE(P_MC1, MC1_ERPS1);
+ 
+ 	s->async->inttrig = NULL;
+@@ -1672,20 +1682,20 @@ static int s626_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ 			dev->minor);
+ 		return -EBUSY;
+ 	}
+-	//disable interrupt
++	/* disable interrupt */
+ 	writel(0, devpriv->base_addr + P_IER);
+ 
+-	//clear interrupt request
++	/* clear interrupt request */
+ 	writel(IRQ_RPS1 | IRQ_GPIO3, devpriv->base_addr + P_ISR);
+ 
+-	//clear any pending interrupt
++	/* clear any pending interrupt */
+ 	s626_dio_clear_irq(dev);
+-	//  s626_enc_clear_irq(dev);
++	/*   s626_enc_clear_irq(dev); */
+ 
+-	//reset ai_cmd_running flag
++	/* reset ai_cmd_running flag */
+ 	devpriv->ai_cmd_running = 0;
+ 
+-	// test if cmd is valid
++	/*  test if cmd is valid */
+ 	if (cmd == NULL) {
+ 		DEBUG("s626_ai_cmd: NULL command\n");
+ 		return -EINVAL;
+@@ -1707,12 +1717,12 @@ static int s626_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ 	case TRIG_FOLLOW:
+ 		break;
+ 	case TRIG_TIMER:
+-		// set a conter to generate adc trigger at scan_begin_arg interval
++		/*  set a conter to generate adc trigger at scan_begin_arg interval */
+ 		k = &encpriv[5];
+ 		tick = s626_ns_to_timer((int *)&cmd->scan_begin_arg,
+ 			cmd->flags & TRIG_ROUND_MASK);
+ 
+-		//load timer value and enable interrupt
++		/* load timer value and enable interrupt */
+ 		s626_timer_load(dev, k, tick);
+ 		k->SetEnable(dev, k, CLKENAB_ALWAYS);
+ 
+@@ -1721,7 +1731,7 @@ static int s626_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ 
+ 		break;
+ 	case TRIG_EXT:
+-		// set the digital line and interrupt for scan trigger
++		/*  set the digital line and interrupt for scan trigger */
+ 		if (cmd->start_src != TRIG_EXT)
+ 			s626_dio_set_irq(dev, cmd->scan_begin_arg);
+ 
+@@ -1734,19 +1744,19 @@ static int s626_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ 	case TRIG_NOW:
+ 		break;
+ 	case TRIG_TIMER:
+-		// set a conter to generate adc trigger at convert_arg interval
++		/*  set a conter to generate adc trigger at convert_arg interval */
+ 		k = &encpriv[4];
+ 		tick = s626_ns_to_timer((int *)&cmd->convert_arg,
+ 			cmd->flags & TRIG_ROUND_MASK);
+ 
+-		//load timer value and enable interrupt
++		/* load timer value and enable interrupt */
+ 		s626_timer_load(dev, k, tick);
+ 		k->SetEnable(dev, k, CLKENAB_INDEX);
+ 
+ 		DEBUG("s626_ai_cmd: convert trigger timer is set with value %d\n", tick);
+ 		break;
+ 	case TRIG_EXT:
+-		// set the digital line and interrupt for convert trigger
++		/*  set the digital line and interrupt for convert trigger */
+ 		if (cmd->scan_begin_src != TRIG_EXT
+ 			&& cmd->start_src == TRIG_EXT)
+ 			s626_dio_set_irq(dev, cmd->convert_arg);
+@@ -1758,12 +1768,12 @@ static int s626_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ 
+ 	switch (cmd->stop_src) {
+ 	case TRIG_COUNT:
+-		// data arrives as one packet
++		/*  data arrives as one packet */
+ 		devpriv->ai_sample_count = cmd->stop_arg;
+ 		devpriv->ai_continous = 0;
+ 		break;
+ 	case TRIG_NONE:
+-		// continous aquisition
++		/*  continous aquisition */
+ 		devpriv->ai_continous = 1;
+ 		devpriv->ai_sample_count = 0;
+ 		break;
+@@ -1773,17 +1783,17 @@ static int s626_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ 
+ 	switch (cmd->start_src) {
+ 	case TRIG_NOW:
+-		// Trigger ADC scan loop start by setting RPS Signal 0.
+-		// MC_ENABLE( P_MC2, MC2_ADC_RPS );
++		/*  Trigger ADC scan loop start by setting RPS Signal 0. */
++		/*  MC_ENABLE( P_MC2, MC2_ADC_RPS ); */
+ 
+-		// Start executing the RPS program.
++		/*  Start executing the RPS program. */
+ 		MC_ENABLE(P_MC1, MC1_ERPS1);
+ 
+ 		DEBUG("s626_ai_cmd: ADC triggered\n");
+ 		s->async->inttrig = NULL;
+ 		break;
+ 	case TRIG_EXT:
+-		//configure DIO channel for acquisition trigger
++		/* configure DIO channel for acquisition trigger */
+ 		s626_dio_set_irq(dev, cmd->start_arg);
+ 
+ 		DEBUG("s626_ai_cmd: External start trigger is set!!!\n");
+@@ -1795,7 +1805,7 @@ static int s626_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+ 		break;
+ 	}
+ 
+-	//enable interrupt
++	/* enable interrupt */
+ 	writel(IRQ_GPIO3 | IRQ_RPS1, devpriv->base_addr + P_IER);
+ 
+ 	DEBUG("s626_ai_cmd: command function terminated\n");
+@@ -1990,10 +2000,10 @@ static int s626_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ 
+ static int s626_ai_cancel(comedi_device * dev, comedi_subdevice * s)
+ {
+-	// Stop RPS program in case it is currently running.
++	/*  Stop RPS program in case it is currently running. */
+ 	MC_DISABLE(P_MC1, MC1_ERPS1);
+ 
+-	//disable master interrupt
++	/* disable master interrupt */
+ 	writel(0, devpriv->base_addr + P_IER);
+ 
+ 	devpriv->ai_cmd_running = 0;
+@@ -2010,7 +2020,7 @@ static int s626_ns_to_timer(int *nanosec, int round_mode)
+ {
+ 	int divider, base;
+ 
+-	base = 500;		//2MHz internal clock
++	base = 500;		/* 2MHz internal clock */
+ 
+ 	switch (round_mode) {
+ 	case TRIG_ROUND_NEAREST:
+@@ -2060,33 +2070,31 @@ static int s626_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+ 	return i;
+ }
+ 
+-/////////////////////////////////////////////////////////////////////
+-///////////////  DIGITAL I/O FUNCTIONS  /////////////////////////////
+-/////////////////////////////////////////////////////////////////////
+-// All DIO functions address a group of DIO channels by means of
+-// "group" argument.  group may be 0, 1 or 2, which correspond to DIO
+-// ports A, B and C, respectively.
+-/////////////////////////////////////////////////////////////////////
++/* *************** DIGITAL I/O FUNCTIONS ***************
++ * All DIO functions address a group of DIO channels by means of
++ * "group" argument.  group may be 0, 1 or 2, which correspond to DIO
++ * ports A, B and C, respectively.
++ */
+ 
+ static void s626_dio_init(comedi_device * dev)
+ {
+ 	uint16_t group;
+ 	comedi_subdevice *s;
+ 
+-	// Prepare to treat writes to WRCapSel as capture disables.
++	/*  Prepare to treat writes to WRCapSel as capture disables. */
+ 	DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP);
+ 
+-	// For each group of sixteen channels ...
++	/*  For each group of sixteen channels ... */
+ 	for (group = 0; group < S626_DIO_BANKS; group++) {
+ 		s = dev->subdevices + 2 + group;
+-		DEBIwrite(dev, diopriv->WRIntSel, 0);	// Disable all interrupts.
+-		DEBIwrite(dev, diopriv->WRCapSel, 0xFFFF);	// Disable all event
+-		// captures.
+-		DEBIwrite(dev, diopriv->WREdgSel, 0);	// Init all DIOs to
+-		// default edge
+-		// polarity.
+-		DEBIwrite(dev, diopriv->WRDOut, 0);	// Program all outputs
+-		// to inactive state.
++		DEBIwrite(dev, diopriv->WRIntSel, 0);	/*  Disable all interrupts. */
++		DEBIwrite(dev, diopriv->WRCapSel, 0xFFFF);	/*  Disable all event */
++		/*  captures. */
++		DEBIwrite(dev, diopriv->WREdgSel, 0);	/*  Init all DIOs to */
++		/*  default edge */
++		/*  polarity. */
++		DEBIwrite(dev, diopriv->WRDOut, 0);	/*  Program all outputs */
++		/*  to inactive state. */
+ 	}
+ 	DEBUG("s626_dio_init: DIO initialized \n");
+ }
+@@ -2166,13 +2174,13 @@ static int s626_dio_set_irq(comedi_device * dev, unsigned int chan)
+ 	unsigned int bitmask;
+ 	unsigned int status;
+ 
+-	//select dio bank
++	/* select dio bank */
+ 	group = chan / 16;
+ 	bitmask = 1 << (chan - (16 * group));
+ 	DEBUG("s626_dio_set_irq: enable interrupt on dio channel %d group %d\n",
+ 		chan - (16 * group), group);
+ 
+-	//set channel to capture positive edge
++	/* set channel to capture positive edge */
+ 	status = DEBIread(dev,
+ 		((dio_private *) (dev->subdevices + 2 +
+ 				group)->private)->RDEdgSel);
+@@ -2180,7 +2188,7 @@ static int s626_dio_set_irq(comedi_device * dev, unsigned int chan)
+ 		((dio_private *) (dev->subdevices + 2 +
+ 				group)->private)->WREdgSel, bitmask | status);
+ 
+-	//enable interrupt on selected channel
++	/* enable interrupt on selected channel */
+ 	status = DEBIread(dev,
+ 		((dio_private *) (dev->subdevices + 2 +
+ 				group)->private)->RDIntSel);
+@@ -2188,10 +2196,10 @@ static int s626_dio_set_irq(comedi_device * dev, unsigned int chan)
+ 		((dio_private *) (dev->subdevices + 2 +
+ 				group)->private)->WRIntSel, bitmask | status);
+ 
+-	//enable edge capture write command
++	/* enable edge capture write command */
+ 	DEBIwrite(dev, LP_MISC1, MISC1_EDCAP);
+ 
+-	//enable edge capture on selected channel
++	/* enable edge capture on selected channel */
+ 	status = DEBIread(dev,
+ 		((dio_private *) (dev->subdevices + 2 +
+ 				group)->private)->RDCapSel);
+@@ -2207,10 +2215,10 @@ static int s626_dio_reset_irq(comedi_device * dev, unsigned int group,
+ {
+ 	DEBUG("s626_dio_reset_irq: disable  interrupt on dio channel %d group %d\n", mask, group);
+ 
+-	//disable edge capture write command
++	/* disable edge capture write command */
+ 	DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP);
+ 
+-	//enable edge capture on selected channel
++	/* enable edge capture on selected channel */
+ 	DEBIwrite(dev,
+ 		((dio_private *) (dev->subdevices + 2 +
+ 				group)->private)->WRCapSel, mask);
+@@ -2222,11 +2230,11 @@ static int s626_dio_clear_irq(comedi_device * dev)
+ {
+ 	unsigned int group;
+ 
+-	//disable edge capture write command
++	/* disable edge capture write command */
+ 	DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP);
+ 
+ 	for (group = 0; group < S626_DIO_BANKS; group++) {
+-		//clear pending events and interrupt
++		/* clear pending events and interrupt */
+ 		DEBIwrite(dev,
+ 			((dio_private *) (dev->subdevices + 2 +
+ 					group)->private)->WRCapSel, 0xffff);
+@@ -2241,23 +2249,23 @@ static int s626_dio_clear_irq(comedi_device * dev)
+ static int s626_enc_insn_config(comedi_device * dev, comedi_subdevice * s,
+ 	comedi_insn * insn, lsampl_t * data)
+ {
+-	uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) |	// Preload upon
+-		// index.
+-		(INDXSRC_SOFT << BF_INDXSRC) |	// Disable hardware index.
+-		(CLKSRC_COUNTER << BF_CLKSRC) |	// Operating mode is Counter.
+-		(CLKPOL_POS << BF_CLKPOL) |	// Active high clock.
+-		//( CNTDIR_UP << BF_CLKPOL ) |      // Count direction is Down.
+-		(CLKMULT_1X << BF_CLKMULT) |	// Clock multiplier is 1x.
++	uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) |	/*  Preload upon */
++		/*  index. */
++		(INDXSRC_SOFT << BF_INDXSRC) |	/*  Disable hardware index. */
++		(CLKSRC_COUNTER << BF_CLKSRC) |	/*  Operating mode is Counter. */
++		(CLKPOL_POS << BF_CLKPOL) |	/*  Active high clock. */
++		/* ( CNTDIR_UP << BF_CLKPOL ) |      // Count direction is Down. */
++		(CLKMULT_1X << BF_CLKMULT) |	/*  Clock multiplier is 1x. */
+ 		(CLKENAB_INDEX << BF_CLKENAB);
+ 	/*   uint16_t DisableIntSrc=TRUE; */
+-	// uint32_t Preloadvalue;              //Counter initial value
++	/*  uint32_t Preloadvalue;              //Counter initial value */
+ 	uint16_t valueSrclatch = LATCHSRC_AB_READ;
+ 	uint16_t enab = CLKENAB_ALWAYS;
+ 	enc_private *k = &encpriv[CR_CHAN(insn->chanspec)];
+ 
+ 	DEBUG("s626_enc_insn_config: encoder config\n");
+ 
+-	//  (data==NULL) ? (Preloadvalue=0) : (Preloadvalue=data[0]);
++	/*   (data==NULL) ? (Preloadvalue=0) : (Preloadvalue=data[0]); */
+ 
+ 	k->SetMode(dev, k, Setup, TRUE);
+ 	Preload(dev, k, *(insn->data));
+@@ -2295,11 +2303,11 @@ static int s626_enc_insn_write(comedi_device * dev, comedi_subdevice * s,
+ 	DEBUG("s626_enc_insn_write: encoder write channel %d \n",
+ 		CR_CHAN(insn->chanspec));
+ 
+-	// Set the preload register
++	/*  Set the preload register */
+ 	Preload(dev, k, data[0]);
+ 
+-	// Software index pulse forces the preload register to load
+-	// into the counter
++	/*  Software index pulse forces the preload register to load */
++	/*  into the counter */
+ 	k->SetLoadTrig(dev, k, 0);
+ 	k->PulseIndex(dev, k);
+ 	k->SetLoadTrig(dev, k, 2);
+@@ -2311,50 +2319,47 @@ static int s626_enc_insn_write(comedi_device * dev, comedi_subdevice * s,
+ 
+ static void s626_timer_load(comedi_device * dev, enc_private * k, int tick)
+ {
+-	uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) |	// Preload upon
+-		// index.
+-		(INDXSRC_SOFT << BF_INDXSRC) |	// Disable hardware index.
+-		(CLKSRC_TIMER << BF_CLKSRC) |	// Operating mode is Timer.
+-		(CLKPOL_POS << BF_CLKPOL) |	// Active high clock.
+-		(CNTDIR_DOWN << BF_CLKPOL) |	// Count direction is Down.
+-		(CLKMULT_1X << BF_CLKMULT) |	// Clock multiplier is 1x.
++	uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) |	/*  Preload upon */
++		/*  index. */
++		(INDXSRC_SOFT << BF_INDXSRC) |	/*  Disable hardware index. */
++		(CLKSRC_TIMER << BF_CLKSRC) |	/*  Operating mode is Timer. */
++		(CLKPOL_POS << BF_CLKPOL) |	/*  Active high clock. */
++		(CNTDIR_DOWN << BF_CLKPOL) |	/*  Count direction is Down. */
++		(CLKMULT_1X << BF_CLKMULT) |	/*  Clock multiplier is 1x. */
+ 		(CLKENAB_INDEX << BF_CLKENAB);
+ 	uint16_t valueSrclatch = LATCHSRC_A_INDXA;
+-	//  uint16_t enab=CLKENAB_ALWAYS;
++	/*   uint16_t enab=CLKENAB_ALWAYS; */
+ 
+ 	k->SetMode(dev, k, Setup, FALSE);
+ 
+-	// Set the preload register
++	/*  Set the preload register */
+ 	Preload(dev, k, tick);
+ 
+-	// Software index pulse forces the preload register to load
+-	// into the counter
++	/*  Software index pulse forces the preload register to load */
++	/*  into the counter */
+ 	k->SetLoadTrig(dev, k, 0);
+ 	k->PulseIndex(dev, k);
+ 
+-	//set reload on counter overflow
++	/* set reload on counter overflow */
+ 	k->SetLoadTrig(dev, k, 1);
+ 
+-	//set interrupt on overflow
++	/* set interrupt on overflow */
+ 	k->SetIntSrc(dev, k, INTSRC_OVER);
+ 
+ 	SetLatchSource(dev, k, valueSrclatch);
+-	//  k->SetEnable(dev,k,(uint16_t)(enab != 0));
++	/*   k->SetEnable(dev,k,(uint16_t)(enab != 0)); */
+ }
+ 
+-///////////////////////////////////////////////////////////////////////
+-/////////////////////  DAC FUNCTIONS /////////////////////////////////
+-///////////////////////////////////////////////////////////////////////
++/* ***********  DAC FUNCTIONS *********** */
+ 
+-// Slot 0 base settings.
+-#define VECT0	( XSD2 | RSD3 | SIB_A2 )	// Slot 0 always shifts in
+-					 // 0xFF and store it to
+-					 // FB_BUFFER2.
++/*  Slot 0 base settings. */
++#define VECT0	( XSD2 | RSD3 | SIB_A2 )
++/*  Slot 0 always shifts in  0xFF and store it to  FB_BUFFER2. */
+ 
+-// TrimDac LogicalChan-to-PhysicalChan mapping table.
++/*  TrimDac LogicalChan-to-PhysicalChan mapping table. */
+ static uint8_t trimchan[] = { 10, 9, 8, 3, 2, 7, 6, 1, 0, 5, 4 };
+ 
+-// TrimDac LogicalChan-to-EepromAdrs mapping table.
++/*  TrimDac LogicalChan-to-EepromAdrs mapping table. */
+ static uint8_t trimadrs[] =
+ 	{ 0x40, 0x41, 0x42, 0x50, 0x51, 0x52, 0x53, 0x60, 0x61, 0x62, 0x63 };
+ 
+@@ -2362,7 +2367,7 @@ static void LoadTrimDACs(comedi_device * dev)
+ {
+ 	register uint8_t i;
+ 
+-	// Copy TrimDac setpoint values from EEPROM to TrimDacs.
++	/*  Copy TrimDac setpoint values from EEPROM to TrimDacs. */
+ 	for (i = 0; i < (sizeof(trimchan) / sizeof(trimchan[0])); i++)
+ 		WriteTrimDAC(dev, i, I2Cread(dev, trimadrs[i]));
+ }
+@@ -2372,112 +2377,105 @@ static void WriteTrimDAC(comedi_device * dev, uint8_t LogicalChan,
+ {
+ 	uint32_t chan;
+ 
+-	// Save the new setpoint in case the application needs to read it back later.
++	/*  Save the new setpoint in case the application needs to read it back later. */
+ 	devpriv->TrimSetpoint[LogicalChan] = (uint8_t) DacData;
+ 
+-	// Map logical channel number to physical channel number.
++	/*  Map logical channel number to physical channel number. */
+ 	chan = (uint32_t) trimchan[LogicalChan];
+ 
+-	// Set up TSL2 records for TrimDac write operation.  All slots shift
+-	// 0xFF in from pulled-up SD3 so that the end of the slot sequence
+-	// can be detected.
+-	SETVECT(2, XSD2 | XFIFO_1 | WS3);	// Slot 2: Send high uint8_t
+-	// to target TrimDac.
+-	SETVECT(3, XSD2 | XFIFO_0 | WS3);	// Slot 3: Send low uint8_t to
+-	// target TrimDac.
+-	SETVECT(4, XSD2 | XFIFO_3 | WS1);	// Slot 4: Send NOP high
+-	// uint8_t to DAC0 to keep
+-	// clock running.
+-	SETVECT(5, XSD2 | XFIFO_2 | WS1 | EOS);	// Slot 5: Send NOP low
+-	// uint8_t to DAC0.
+-
+-	// Construct and transmit target DAC's serial packet: ( 0000 AAAA
+-	// ),( DDDD DDDD ),( 0x00 ),( 0x00 ) where A<3:0> is the DAC
+-	// channel's address, and D<7:0> is the DAC setpoint.  Append a WORD
+-	// value (that writes a channel 0 NOP command to a non-existent main
+-	// DAC channel) that serves to keep the clock running after the
+-	// packet has been sent to the target DAC.
+-
+-	SendDAC(dev, ((uint32_t) chan << 8)	// Address the DAC channel
+-		// within the trimdac device.
+-		| (uint32_t) DacData);	// Include DAC setpoint data.
+-}
++	/* Set up TSL2 records for TrimDac write operation.  All slots shift
++	 * 0xFF in from pulled-up SD3 so that the end of the slot sequence
++	 * can be detected.
++	 */
++
++	SETVECT(2, XSD2 | XFIFO_1 | WS3);
++	/* Slot 2: Send high uint8_t to target TrimDac. */
++	SETVECT(3, XSD2 | XFIFO_0 | WS3);
++	/* Slot 3: Send low uint8_t to target TrimDac. */
++	SETVECT(4, XSD2 | XFIFO_3 | WS1);
++	/* Slot 4: Send NOP high uint8_t to DAC0 to keep clock running. */
++	SETVECT(5, XSD2 | XFIFO_2 | WS1 | EOS);
++	/* Slot 5: Send NOP low  uint8_t to DAC0. */
++
++	/* Construct and transmit target DAC's serial packet:
++	 * ( 0000 AAAA ), ( DDDD DDDD ),( 0x00 ),( 0x00 ) where A<3:0> is the
++	 * DAC channel's address, and D<7:0> is the DAC setpoint.  Append a
++	 * WORD value (that writes a channel 0 NOP command to a non-existent
++	 * main DAC channel) that serves to keep the clock running after the
++	 * packet has been sent to the target DAC.
++	 */
+ 
+-/////////////////////////////////////////////////////////////////////////
+-////////////////  EEPROM ACCESS FUNCTIONS  //////////////////////////////
+-/////////////////////////////////////////////////////////////////////////
++	/*  Address the DAC channel within the trimdac device. */
++	SendDAC(dev, ((uint32_t) chan << 8)
++		| (uint32_t) DacData);	/*  Include DAC setpoint data. */
++}
+ 
+-///////////////////////////////////////////
+-// Read uint8_t from EEPROM.
++/* **************  EEPROM ACCESS FUNCTIONS  ************** */
++/*  Read uint8_t from EEPROM. */
+ 
+ static uint8_t I2Cread(comedi_device * dev, uint8_t addr)
+ {
+ 	uint8_t rtnval;
+ 
+-	// Send EEPROM target address.
+-	if (I2Chandshake(dev, I2C_B2(I2C_ATTRSTART, I2CW)	// Byte2 = I2C
+-			// command:
+-			// write to
+-			// I2C EEPROM
+-			// device.
+-			| I2C_B1(I2C_ATTRSTOP, addr)	// Byte1 = EEPROM
+-			// internal target
+-			// address.
+-			| I2C_B0(I2C_ATTRNOP, 0)))	// Byte0 = Not
+-		// sent.
++	/*  Send EEPROM target address. */
++	if (I2Chandshake(dev, I2C_B2(I2C_ATTRSTART, I2CW)
++			 /* Byte2 = I2C command: write to I2C EEPROM  device. */
++			| I2C_B1(I2C_ATTRSTOP, addr)
++			 /* Byte1 = EEPROM internal target address. */
++			| I2C_B0(I2C_ATTRNOP, 0)))	/*  Byte0 = Not sent. */
+ 	{
+-		// Abort function and declare error if handshake failed.
++		/*  Abort function and declare error if handshake failed. */
+ 		DEBUG("I2Cread: error handshake I2Cread  a\n");
+ 		return 0;
+ 	}
+-	// Execute EEPROM read.
+-	if (I2Chandshake(dev, I2C_B2(I2C_ATTRSTART, I2CR)	// Byte2 = I2C
+-			// command: read
+-			// from I2C EEPROM
+-			// device.
+-			| I2C_B1(I2C_ATTRSTOP, 0)	// Byte1 receives
+-			// uint8_t from
+-			// EEPROM.
+-			| I2C_B0(I2C_ATTRNOP, 0)))	// Byte0 = Not
+-		// sent.
++	/*  Execute EEPROM read. */
++	if (I2Chandshake(dev, I2C_B2(I2C_ATTRSTART, I2CR)	/*  Byte2 = I2C */
++			/*  command: read */
++			/*  from I2C EEPROM */
++			/*  device. */
++			| I2C_B1(I2C_ATTRSTOP, 0)	/*  Byte1 receives */
++			/*  uint8_t from */
++			/*  EEPROM. */
++			| I2C_B0(I2C_ATTRNOP, 0)))	/*  Byte0 = Not */
++		/*  sent. */
+ 	{
+-		// Abort function and declare error if handshake failed.
++		/*  Abort function and declare error if handshake failed. */
+ 		DEBUG("I2Cread: error handshake I2Cread b\n");
+ 		return 0;
+ 	}
+-	// Return copy of EEPROM value.
++	/*  Return copy of EEPROM value. */
+ 	rtnval = (uint8_t) (RR7146(P_I2CCTRL) >> 16);
+ 	return rtnval;
+ }
+ 
+ static uint32_t I2Chandshake(comedi_device * dev, uint32_t val)
+ {
+-	// Write I2C command to I2C Transfer Control shadow register.
++	/*  Write I2C command to I2C Transfer Control shadow register. */
+ 	WR7146(P_I2CCTRL, val);
+ 
+-	// Upload I2C shadow registers into working registers and wait for
+-	// upload confirmation.
++	/*  Upload I2C shadow registers into working registers and wait for */
++	/*  upload confirmation. */
+ 
+ 	MC_ENABLE(P_MC2, MC2_UPLD_IIC);
+ 	while (!MC_TEST(P_MC2, MC2_UPLD_IIC)) ;
+ 
+-	// Wait until I2C bus transfer is finished or an error occurs.
++	/*  Wait until I2C bus transfer is finished or an error occurs. */
+ 	while ((RR7146(P_I2CCTRL) & (I2C_BUSY | I2C_ERR)) == I2C_BUSY) ;
+ 
+-	// Return non-zero if I2C error occured.
++	/*  Return non-zero if I2C error occured. */
+ 	return RR7146(P_I2CCTRL) & I2C_ERR;
+ 
+ }
+ 
+-// Private helper function: Write setpoint to an application DAC channel.
++/*  Private helper function: Write setpoint to an application DAC channel. */
+ 
+ static void SetDAC(comedi_device * dev, uint16_t chan, short dacdata)
+ {
+ 	register uint16_t signmask;
+ 	register uint32_t WSImage;
+ 
+-	// Adjust DAC data polarity and set up Polarity Control Register
+-	// image.
++	/*  Adjust DAC data polarity and set up Polarity Control Register */
++	/*  image. */
+ 	signmask = 1 << chan;
+ 	if (dacdata < 0) {
+ 		dacdata = -dacdata;
+@@ -2485,234 +2483,243 @@ static void SetDAC(comedi_device * dev, uint16_t chan, short dacdata)
+ 	} else
+ 		devpriv->Dacpol &= ~signmask;
+ 
+-	// Limit DAC setpoint value to valid range.
++	/*  Limit DAC setpoint value to valid range. */
+ 	if ((uint16_t) dacdata > 0x1FFF)
+ 		dacdata = 0x1FFF;
+ 
+-	// Set up TSL2 records (aka "vectors") for DAC update.  Vectors V2
+-	// and V3 transmit the setpoint to the target DAC.  V4 and V5 send
+-	// data to a non-existent TrimDac channel just to keep the clock
+-	// running after sending data to the target DAC.  This is necessary
+-	// to eliminate the clock glitch that would otherwise occur at the
+-	// end of the target DAC's serial data stream.  When the sequence
+-	// restarts at V0 (after executing V5), the gate array automatically
+-	// disables gating for the DAC clock and all DAC chip selects.
+-	WSImage = (chan & 2) ? WS1 : WS2;	// Choose DAC chip select to
+-	// be asserted.
+-	SETVECT(2, XSD2 | XFIFO_1 | WSImage);	// Slot 2: Transmit high
+-	// data byte to target DAC.
+-	SETVECT(3, XSD2 | XFIFO_0 | WSImage);	// Slot 3: Transmit low data
+-	// byte to target DAC.
+-	SETVECT(4, XSD2 | XFIFO_3 | WS3);	// Slot 4: Transmit to
+-	// non-existent TrimDac
+-	// channel to keep clock
+-	SETVECT(5, XSD2 | XFIFO_2 | WS3 | EOS);	// Slot 5: running after
+-	// writing target DAC's
+-	// low data byte.
+-
+-	// Construct and transmit target DAC's serial packet: ( A10D DDDD
+-	// ),( DDDD DDDD ),( 0x0F ),( 0x00 ) where A is chan<0>, and D<12:0>
+-	// is the DAC setpoint.  Append a WORD value (that writes to a
+-	// non-existent TrimDac channel) that serves to keep the clock
+-	// running after the packet has been sent to the target DAC.
+-	SendDAC(dev, 0x0F000000	//Continue clock after target DAC
+-		//data (write to non-existent
+-		//trimdac).
+-		| 0x00004000	// Address the two main dual-DAC
+-		// devices (TSL's chip select enables
+-		// target device).
+-		| ((uint32_t) (chan & 1) << 15)	// Address the DAC
+-		// channel within the
+-		// device.
+-		| (uint32_t) dacdata);	// Include DAC setpoint data.
++	/* Set up TSL2 records (aka "vectors") for DAC update.  Vectors V2
++	 * and V3 transmit the setpoint to the target DAC.  V4 and V5 send
++	 * data to a non-existent TrimDac channel just to keep the clock
++	 * running after sending data to the target DAC.  This is necessary
++	 * to eliminate the clock glitch that would otherwise occur at the
++	 * end of the target DAC's serial data stream.  When the sequence
++	 * restarts at V0 (after executing V5), the gate array automatically
++	 * disables gating for the DAC clock and all DAC chip selects.
++	 */
++
++	WSImage = (chan & 2) ? WS1 : WS2;
++	/* Choose DAC chip select to be asserted. */
++	SETVECT(2, XSD2 | XFIFO_1 | WSImage);
++	/* Slot 2: Transmit high data byte to target DAC. */
++	SETVECT(3, XSD2 | XFIFO_0 | WSImage);
++	/* Slot 3: Transmit low data byte to target DAC. */
++	SETVECT(4, XSD2 | XFIFO_3 | WS3);
++	/* Slot 4: Transmit to non-existent TrimDac channel to keep clock */
++	SETVECT(5, XSD2 | XFIFO_2 | WS3 | EOS);
++	/* Slot 5: running after writing target DAC's low data byte. */
++
++	/*  Construct and transmit target DAC's serial packet:
++	 * ( A10D DDDD ),( DDDD DDDD ),( 0x0F ),( 0x00 ) where A is chan<0>,
++	 * and D<12:0> is the DAC setpoint.  Append a WORD value (that writes
++	 * to a  non-existent TrimDac channel) that serves to keep the clock
++	 * running after the packet has been sent to the target DAC.
++	 */
++	SendDAC(dev, 0x0F000000
++		/* Continue clock after target DAC data (write to non-existent trimdac). */
++		| 0x00004000
++		/* Address the two main dual-DAC devices (TSL's chip select enables
++		 * target device). */
++		| ((uint32_t) (chan & 1) << 15)
++		/*  Address the DAC channel within the  device. */
++		| (uint32_t) dacdata);	/*  Include DAC setpoint data. */
+ 
+ }
+ 
+-////////////////////////////////////////////////////////
+-// Private helper function: Transmit serial data to DAC via Audio
+-// channel 2.  Assumes: (1) TSL2 slot records initialized, and (2)
+-// Dacpol contains valid target image.
++/* Private helper function: Transmit serial data to DAC via Audio
++ * channel 2.  Assumes: (1) TSL2 slot records initialized, and (2)
++ * Dacpol contains valid target image.
++ */
+ 
+ static void SendDAC(comedi_device * dev, uint32_t val)
+ {
+ 
+-	// START THE SERIAL CLOCK RUNNING -------------
++	/* START THE SERIAL CLOCK RUNNING ------------- */
+ 
+-	// Assert DAC polarity control and enable gating of DAC serial clock
+-	// and audio bit stream signals.  At this point in time we must be
+-	// assured of being in time slot 0.  If we are not in slot 0, the
+-	// serial clock and audio stream signals will be disabled; this is
+-	// because the following DEBIwrite statement (which enables signals
+-	// to be passed through the gate array) would execute before the
+-	// trailing edge of WS1/WS3 (which turns off the signals), thus
+-	// causing the signals to be inactive during the DAC write.
++	/* Assert DAC polarity control and enable gating of DAC serial clock
++	 * and audio bit stream signals.  At this point in time we must be
++	 * assured of being in time slot 0.  If we are not in slot 0, the
++	 * serial clock and audio stream signals will be disabled; this is
++	 * because the following DEBIwrite statement (which enables signals
++	 * to be passed through the gate array) would execute before the
++	 * trailing edge of WS1/WS3 (which turns off the signals), thus
++	 * causing the signals to be inactive during the DAC write.
++	 */
+ 	DEBIwrite(dev, LP_DACPOL, devpriv->Dacpol);
+ 
+-	// TRANSFER OUTPUT DWORD VALUE INTO A2'S OUTPUT FIFO ----------------
++	/* TRANSFER OUTPUT DWORD VALUE INTO A2'S OUTPUT FIFO ---------------- */
+ 
+-	// Copy DAC setpoint value to DAC's output DMA buffer.
++	/* Copy DAC setpoint value to DAC's output DMA buffer. */
+ 
+-	//WR7146( (uint32_t)devpriv->pDacWBuf, val );
++	/* WR7146( (uint32_t)devpriv->pDacWBuf, val ); */
+ 	*devpriv->pDacWBuf = val;
+ 
+-	// enab the output DMA transfer.  This will cause the DMAC to copy
+-	// the DAC's data value to A2's output FIFO.  The DMA transfer will
+-	// then immediately terminate because the protection address is
+-	// reached upon transfer of the first DWORD value.
++	/* enab the output DMA transfer.  This will cause the DMAC to copy
++	 * the DAC's data value to A2's output FIFO.  The DMA transfer will
++	 * then immediately terminate because the protection address is
++	 * reached upon transfer of the first DWORD value.
++	 */
+ 	MC_ENABLE(P_MC1, MC1_A2OUT);
+ 
+-	// While the DMA transfer is executing ...
++	/*  While the DMA transfer is executing ... */
+ 
+-	// Reset Audio2 output FIFO's underflow flag (along with any other
+-	// FIFO underflow/overflow flags).  When set, this flag will
+-	// indicate that we have emerged from slot 0.
++	/* Reset Audio2 output FIFO's underflow flag (along with any other
++	 * FIFO underflow/overflow flags).  When set, this flag will
++	 * indicate that we have emerged from slot 0.
++	 */
+ 	WR7146(P_ISR, ISR_AFOU);
+ 
+-	// Wait for the DMA transfer to finish so that there will be data
+-	// available in the FIFO when time slot 1 tries to transfer a DWORD
+-	// from the FIFO to the output buffer register.  We test for DMA
+-	// Done by polling the DMAC enable flag; this flag is automatically
+-	// cleared when the transfer has finished.
++	/* Wait for the DMA transfer to finish so that there will be data
++	 * available in the FIFO when time slot 1 tries to transfer a DWORD
++	 * from the FIFO to the output buffer register.  We test for DMA
++	 * Done by polling the DMAC enable flag; this flag is automatically
++	 * cleared when the transfer has finished.
++	 */
+ 	while ((RR7146(P_MC1) & MC1_A2OUT) != 0) ;
+ 
+-	// START THE OUTPUT STREAM TO THE TARGET DAC --------------------
++	/* START THE OUTPUT STREAM TO THE TARGET DAC -------------------- */
+ 
+-	// FIFO data is now available, so we enable execution of time slots
+-	// 1 and higher by clearing the EOS flag in slot 0.  Note that SD3
+-	// will be shifted in and stored in FB_BUFFER2 for end-of-slot-list
+-	// detection.
++	/* FIFO data is now available, so we enable execution of time slots
++	 * 1 and higher by clearing the EOS flag in slot 0.  Note that SD3
++	 * will be shifted in and stored in FB_BUFFER2 for end-of-slot-list
++	 * detection.
++	 */
+ 	SETVECT(0, XSD2 | RSD3 | SIB_A2);
+ 
+-	// Wait for slot 1 to execute to ensure that the Packet will be
+-	// transmitted.  This is detected by polling the Audio2 output FIFO
+-	// underflow flag, which will be set when slot 1 execution has
+-	// finished transferring the DAC's data DWORD from the output FIFO
+-	// to the output buffer register.
++	/* Wait for slot 1 to execute to ensure that the Packet will be
++	 * transmitted.  This is detected by polling the Audio2 output FIFO
++	 * underflow flag, which will be set when slot 1 execution has
++	 * finished transferring the DAC's data DWORD from the output FIFO
++	 * to the output buffer register.
++	 */
+ 	while ((RR7146(P_SSR) & SSR_AF2_OUT) == 0) ;
+ 
+-	// Set up to trap execution at slot 0 when the TSL sequencer cycles
+-	// back to slot 0 after executing the EOS in slot 5.  Also,
+-	// simultaneously shift out and in the 0x00 that is ALWAYS the value
+-	// stored in the last byte to be shifted out of the FIFO's DWORD
+-	// buffer register.
++	/* Set up to trap execution at slot 0 when the TSL sequencer cycles
++	 * back to slot 0 after executing the EOS in slot 5.  Also,
++	 * simultaneously shift out and in the 0x00 that is ALWAYS the value
++	 * stored in the last byte to be shifted out of the FIFO's DWORD
++	 * buffer register.
++	 */
+ 	SETVECT(0, XSD2 | XFIFO_2 | RSD2 | SIB_A2 | EOS);
+ 
+-	// WAIT FOR THE TRANSACTION TO FINISH -----------------------
+-
+-	// Wait for the TSL to finish executing all time slots before
+-	// exiting this function.  We must do this so that the next DAC
+-	// write doesn't start, thereby enabling clock/chip select signals:
+-	// 1. Before the TSL sequence cycles back to slot 0, which disables
+-	// the clock/cs signal gating and traps slot // list execution.  If
+-	// we have not yet finished slot 5 then the clock/cs signals are
+-	// still gated and we have // not finished transmitting the stream.
+-	// 2. While slots 2-5 are executing due to a late slot 0 trap.  In
+-	// this case, the slot sequence is currently // repeating, but with
+-	// clock/cs signals disabled.  We must wait for slot 0 to trap
+-	// execution before setting // up the next DAC setpoint DMA transfer
+-	// and enabling the clock/cs signals.  To detect the end of slot 5,
+-	// we test for the FB_BUFFER2 MSB contents to be equal to 0xFF.  If
+-	// the TSL has not yet finished executing slot 5 ...
++	/* WAIT FOR THE TRANSACTION TO FINISH ----------------------- */
++
++	/* Wait for the TSL to finish executing all time slots before
++	 * exiting this function.  We must do this so that the next DAC
++	 * write doesn't start, thereby enabling clock/chip select signals:
++	 *
++	 * 1. Before the TSL sequence cycles back to slot 0, which disables
++	 *    the clock/cs signal gating and traps slot // list execution.
++	 *    we have not yet finished slot 5 then the clock/cs signals are
++	 *    still gated and we have not finished transmitting the stream.
++	 *
++	 * 2. While slots 2-5 are executing due to a late slot 0 trap.  In
++	 *    this case, the slot sequence is currently repeating, but with
++	 *    clock/cs signals disabled.  We must wait for slot 0 to trap
++	 *    execution before setting up the next DAC setpoint DMA transfer
++	 *    and enabling the clock/cs signals.  To detect the end of slot 5,
++	 *    we test for the FB_BUFFER2 MSB contents to be equal to 0xFF.  If
++	 *    the TSL has not yet finished executing slot 5 ...
++	 */
+ 	if ((RR7146(P_FB_BUFFER2) & 0xFF000000) != 0) {
+-		// The trap was set on time and we are still executing somewhere
+-		// in slots 2-5, so we now wait for slot 0 to execute and trap
+-		// TSL execution.  This is detected when FB_BUFFER2 MSB changes
+-		// from 0xFF to 0x00, which slot 0 causes to happen by shifting
+-		// out/in on SD2 the 0x00 that is always referenced by slot 5.
+-		while ((RR7146(P_FB_BUFFER2) & 0xFF000000) != 0) ;
++		/* The trap was set on time and we are still executing somewhere
++		 * in slots 2-5, so we now wait for slot 0 to execute and trap
++		 * TSL execution.  This is detected when FB_BUFFER2 MSB changes
++		 * from 0xFF to 0x00, which slot 0 causes to happen by shifting
++		 * out/in on SD2 the 0x00 that is always referenced by slot 5.
++		 */
++		 while ((RR7146(P_FB_BUFFER2) & 0xFF000000) != 0) ;
+ 	}
+-	// Either (1) we were too late setting the slot 0 trap; the TSL
+-	// sequencer restarted slot 0 before we could set the EOS trap flag,
+-	// or (2) we were not late and execution is now trapped at slot 0.
+-	// In either case, we must now change slot 0 so that it will store
+-	// value 0xFF (instead of 0x00) to FB_BUFFER2 next time it executes.
+-	// In order to do this, we reprogram slot 0 so that it will shift in
+-	// SD3, which is driven only by a pull-up resistor.
++	/* Either (1) we were too late setting the slot 0 trap; the TSL
++	 * sequencer restarted slot 0 before we could set the EOS trap flag,
++	 * or (2) we were not late and execution is now trapped at slot 0.
++	 * In either case, we must now change slot 0 so that it will store
++	 * value 0xFF (instead of 0x00) to FB_BUFFER2 next time it executes.
++	 * In order to do this, we reprogram slot 0 so that it will shift in
++	 * SD3, which is driven only by a pull-up resistor.
++	 */
+ 	SETVECT(0, RSD3 | SIB_A2 | EOS);
+ 
+-	// Wait for slot 0 to execute, at which time the TSL is setup for
+-	// the next DAC write.  This is detected when FB_BUFFER2 MSB changes
+-	// from 0x00 to 0xFF.
++	/* Wait for slot 0 to execute, at which time the TSL is setup for
++	 * the next DAC write.  This is detected when FB_BUFFER2 MSB changes
++	 * from 0x00 to 0xFF.
++	 */
+ 	while ((RR7146(P_FB_BUFFER2) & 0xFF000000) == 0) ;
+ }
+ 
+ static void WriteMISC2(comedi_device * dev, uint16_t NewImage)
+ {
+-	DEBIwrite(dev, LP_MISC1, MISC1_WENABLE);	// enab writes to
+-	// MISC2 register.
+-	DEBIwrite(dev, LP_WRMISC2, NewImage);	// Write new image to MISC2.
+-	DEBIwrite(dev, LP_MISC1, MISC1_WDISABLE);	// Disable writes to MISC2.
++	DEBIwrite(dev, LP_MISC1, MISC1_WENABLE);	/*  enab writes to */
++	/*  MISC2 register. */
++	DEBIwrite(dev, LP_WRMISC2, NewImage);	/*  Write new image to MISC2. */
++	DEBIwrite(dev, LP_MISC1, MISC1_WDISABLE);	/*  Disable writes to MISC2. */
+ }
+ 
+-/////////////////////////////////////////////////////////////////////
+-// Initialize the DEBI interface for all transfers.
++/*  Initialize the DEBI interface for all transfers. */
+ 
+ static uint16_t DEBIread(comedi_device * dev, uint16_t addr)
+ {
+ 	uint16_t retval;
+ 
+-	// Set up DEBI control register value in shadow RAM.
++	/*  Set up DEBI control register value in shadow RAM. */
+ 	WR7146(P_DEBICMD, DEBI_CMD_RDWORD | addr);
+ 
+-	// Execute the DEBI transfer.
++	/*  Execute the DEBI transfer. */
+ 	DEBItransfer(dev);
+ 
+-	// Fetch target register value.
++	/*  Fetch target register value. */
+ 	retval = (uint16_t) RR7146(P_DEBIAD);
+ 
+-	// Return register value.
++	/*  Return register value. */
+ 	return retval;
+ }
+ 
+-// Execute a DEBI transfer.  This must be called from within a
+-// critical section.
++/*  Execute a DEBI transfer.  This must be called from within a */
++/*  critical section. */
+ static void DEBItransfer(comedi_device * dev)
+ {
+-	// Initiate upload of shadow RAM to DEBI control register.
++	/*  Initiate upload of shadow RAM to DEBI control register. */
+ 	MC_ENABLE(P_MC2, MC2_UPLD_DEBI);
+ 
+-	// Wait for completion of upload from shadow RAM to DEBI control
+-	// register.
++	/*  Wait for completion of upload from shadow RAM to DEBI control */
++	/*  register. */
+ 	while (!MC_TEST(P_MC2, MC2_UPLD_DEBI)) ;
+ 
+-	// Wait until DEBI transfer is done.
++	/*  Wait until DEBI transfer is done. */
+ 	while (RR7146(P_PSR) & PSR_DEBI_S) ;
+ }
+ 
+-// Write a value to a gate array register.
++/*  Write a value to a gate array register. */
+ static void DEBIwrite(comedi_device * dev, uint16_t addr, uint16_t wdata)
+ {
+ 
+-	// Set up DEBI control register value in shadow RAM.
++	/*  Set up DEBI control register value in shadow RAM. */
+ 	WR7146(P_DEBICMD, DEBI_CMD_WRWORD | addr);
+ 	WR7146(P_DEBIAD, wdata);
+ 
+-	// Execute the DEBI transfer.
++	/*  Execute the DEBI transfer. */
+ 	DEBItransfer(dev);
+ }
+ 
+-/////////////////////////////////////////////////////////////////////////////
+-// Replace the specified bits in a gate array register.  Imports: mask
+-// specifies bits that are to be preserved, wdata is new value to be
+-// or'd with the masked original.
++/* Replace the specified bits in a gate array register.  Imports: mask
++ * specifies bits that are to be preserved, wdata is new value to be
++ * or'd with the masked original.
++ */
+ static void DEBIreplace(comedi_device * dev, uint16_t addr, uint16_t mask,
+ 	uint16_t wdata)
+ {
+ 
+-	// Copy target gate array register into P_DEBIAD register.
+-	WR7146(P_DEBICMD, DEBI_CMD_RDWORD | addr);	// Set up DEBI control
+-	// reg value in shadow
+-	// RAM.
+-	DEBItransfer(dev);	// Execute the DEBI
+-	// Read transfer.
++	/*  Copy target gate array register into P_DEBIAD register. */
++	WR7146(P_DEBICMD, DEBI_CMD_RDWORD | addr);
++	/* Set up DEBI control reg value in shadow RAM. */
++	DEBItransfer(dev);	/*  Execute the DEBI Read transfer. */
+ 
+-	// Write back the modified image.
+-	WR7146(P_DEBICMD, DEBI_CMD_WRWORD | addr);	// Set up DEBI control
+-	// reg value in shadow
+-	// RAM.
++	/*  Write back the modified image. */
++	WR7146(P_DEBICMD, DEBI_CMD_WRWORD | addr);
++	/* Set up DEBI control reg value in shadow  RAM. */
+ 
+-	WR7146(P_DEBIAD, wdata | ((uint16_t) RR7146(P_DEBIAD) & mask));	// Modify the register image.
+-	DEBItransfer(dev);	// Execute the DEBI Write transfer.
++	WR7146(P_DEBIAD, wdata | ((uint16_t) RR7146(P_DEBIAD) & mask));
++	/* Modify the register image. */
++	DEBItransfer(dev);	/*  Execute the DEBI Write transfer. */
+ }
+ 
+ static void CloseDMAB(comedi_device * dev, DMABUF * pdma, size_t bsize)
+@@ -2723,7 +2730,7 @@ static void CloseDMAB(comedi_device * dev, DMABUF * pdma, size_t bsize)
+ 	DEBUG("CloseDMAB: Entering S626DRV_CloseDMAB():\n");
+ 	if (pdma == NULL)
+ 		return;
+-	//find the matching allocation from the board struct
++	/* find the matching allocation from the board struct */
+ 
+ 	vbptr = pdma->LogicalBase;
+ 	vpptr = pdma->PhysicalBase;
+@@ -2737,44 +2744,37 @@ static void CloseDMAB(comedi_device * dev, DMABUF * pdma, size_t bsize)
+ 	}
+ }
+ 
+-////////////////////////////////////////////////////////////////////////
+-/////////////////  COUNTER FUNCTIONS  //////////////////////////////////
+-////////////////////////////////////////////////////////////////////////
+-// All counter functions address a specific counter by means of the
+-// "Counter" argument, which is a logical counter number.  The Counter
+-// argument may have any of the following legal values: 0=0A, 1=1A,
+-// 2=2A, 3=0B, 4=1B, 5=2B.
+-////////////////////////////////////////////////////////////////////////
++/* ******  COUNTER FUNCTIONS  ******* */
++/* All counter functions address a specific counter by means of the
++ * "Counter" argument, which is a logical counter number.  The Counter
++ * argument may have any of the following legal values: 0=0A, 1=1A,
++ * 2=2A, 3=0B, 4=1B, 5=2B.
++ */
+ 
+-// Forward declarations for functions that are common to both A and B
+-// counters:
++/* Forward declarations for functions that are common to both A and B counters: */
+ 
+-/////////////////////////////////////////////////////////////////////
+-//////////////////// PRIVATE COUNTER FUNCTIONS  /////////////////////
+-/////////////////////////////////////////////////////////////////////
++/* ******  PRIVATE COUNTER FUNCTIONS ****** */
+ 
+-/////////////////////////////////////////////////////////////////
+-// Read a counter's output latch.
++/*  Read a counter's output latch. */
+ 
+ static uint32_t ReadLatch(comedi_device * dev, enc_private * k)
+ {
+ 	register uint32_t value;
+-	//DEBUG FIXME DEBUG("ReadLatch: Read Latch enter\n");
++	/* DEBUG FIXME DEBUG("ReadLatch: Read Latch enter\n"); */
+ 
+-	// Latch counts and fetch LSW of latched counts value.
++	/*  Latch counts and fetch LSW of latched counts value. */
+ 	value = (uint32_t) DEBIread(dev, k->MyLatchLsw);
+ 
+-	// Fetch MSW of latched counts and combine with LSW.
++	/*  Fetch MSW of latched counts and combine with LSW. */
+ 	value |= ((uint32_t) DEBIread(dev, k->MyLatchLsw + 2) << 16);
+ 
+-	// DEBUG FIXME DEBUG("ReadLatch: Read Latch exit\n");
++	/*  DEBUG FIXME DEBUG("ReadLatch: Read Latch exit\n"); */
+ 
+-	// Return latched counts.
++	/*  Return latched counts. */
+ 	return value;
+ }
+ 
+-///////////////////////////////////////////////////////////////////
+-// Reset a counter's index and overflow event capture flags.
++/*  Reset a counter's index and overflow event capture flags. */
+ 
+ static void ResetCapFlags_A(comedi_device * dev, enc_private * k)
+ {
+@@ -2788,9 +2788,8 @@ static void ResetCapFlags_B(comedi_device * dev, enc_private * k)
+ 		CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B);
+ }
+ 
+-/////////////////////////////////////////////////////////////////////////
+-// Return counter setup in a format (COUNTER_SETUP) that is consistent
+-// for both A and B counters.
++/*  Return counter setup in a format (COUNTER_SETUP) that is consistent */
++/*  for both A and B counters. */
+ 
+ static uint16_t GetMode_A(comedi_device * dev, enc_private * k)
+ {
+@@ -2798,35 +2797,35 @@ static uint16_t GetMode_A(comedi_device * dev, enc_private * k)
+ 	register uint16_t crb;
+ 	register uint16_t setup;
+ 
+-	// Fetch CRA and CRB register images.
++	/*  Fetch CRA and CRB register images. */
+ 	cra = DEBIread(dev, k->MyCRA);
+ 	crb = DEBIread(dev, k->MyCRB);
+ 
+-	// Populate the standardized counter setup bit fields.  Note:
+-	// IndexSrc is restricted to ENC_X or IndxPol.
+-	setup = ((cra & STDMSK_LOADSRC)	// LoadSrc  = LoadSrcA.
+-		| ((crb << (STDBIT_LATCHSRC - CRBBIT_LATCHSRC)) & STDMSK_LATCHSRC)	// LatchSrc = LatchSrcA.
+-		| ((cra << (STDBIT_INTSRC - CRABIT_INTSRC_A)) & STDMSK_INTSRC)	// IntSrc   = IntSrcA.
+-		| ((cra << (STDBIT_INDXSRC - (CRABIT_INDXSRC_A + 1))) & STDMSK_INDXSRC)	// IndxSrc  = IndxSrcA<1>.
+-		| ((cra >> (CRABIT_INDXPOL_A - STDBIT_INDXPOL)) & STDMSK_INDXPOL)	// IndxPol  = IndxPolA.
+-		| ((crb >> (CRBBIT_CLKENAB_A - STDBIT_CLKENAB)) & STDMSK_CLKENAB));	// ClkEnab  = ClkEnabA.
+-
+-	// Adjust mode-dependent parameters.
+-	if (cra & (2 << CRABIT_CLKSRC_A))	// If Timer mode (ClkSrcA<1> == 1):
+-		setup |= ((CLKSRC_TIMER << STDBIT_CLKSRC)	//   Indicate Timer mode.
+-			| ((cra << (STDBIT_CLKPOL - CRABIT_CLKSRC_A)) & STDMSK_CLKPOL)	//   Set ClkPol to indicate count direction (ClkSrcA<0>).
+-			| (MULT_X1 << STDBIT_CLKMULT));	//   ClkMult must be 1x in Timer mode.
+-
+-	else			// If Counter mode (ClkSrcA<1> == 0):
+-		setup |= ((CLKSRC_COUNTER << STDBIT_CLKSRC)	//   Indicate Counter mode.
+-			| ((cra >> (CRABIT_CLKPOL_A - STDBIT_CLKPOL)) & STDMSK_CLKPOL)	//   Pass through ClkPol.
+-			| (((cra & CRAMSK_CLKMULT_A) == (MULT_X0 << CRABIT_CLKMULT_A)) ?	//   Force ClkMult to 1x if not legal, else pass through.
++	/*  Populate the standardized counter setup bit fields.  Note: */
++	/*  IndexSrc is restricted to ENC_X or IndxPol. */
++	setup = ((cra & STDMSK_LOADSRC)	/*  LoadSrc  = LoadSrcA. */
++		| ((crb << (STDBIT_LATCHSRC - CRBBIT_LATCHSRC)) & STDMSK_LATCHSRC)	/*  LatchSrc = LatchSrcA. */
++		| ((cra << (STDBIT_INTSRC - CRABIT_INTSRC_A)) & STDMSK_INTSRC)	/*  IntSrc   = IntSrcA. */
++		| ((cra << (STDBIT_INDXSRC - (CRABIT_INDXSRC_A + 1))) & STDMSK_INDXSRC)	/*  IndxSrc  = IndxSrcA<1>. */
++		| ((cra >> (CRABIT_INDXPOL_A - STDBIT_INDXPOL)) & STDMSK_INDXPOL)	/*  IndxPol  = IndxPolA. */
++		| ((crb >> (CRBBIT_CLKENAB_A - STDBIT_CLKENAB)) & STDMSK_CLKENAB));	/*  ClkEnab  = ClkEnabA. */
++
++	/*  Adjust mode-dependent parameters. */
++	if (cra & (2 << CRABIT_CLKSRC_A))	/*  If Timer mode (ClkSrcA<1> == 1): */
++		setup |= ((CLKSRC_TIMER << STDBIT_CLKSRC)	/*    Indicate Timer mode. */
++			| ((cra << (STDBIT_CLKPOL - CRABIT_CLKSRC_A)) & STDMSK_CLKPOL)	/*    Set ClkPol to indicate count direction (ClkSrcA<0>). */
++			| (MULT_X1 << STDBIT_CLKMULT));	/*    ClkMult must be 1x in Timer mode. */
++
++	else			/*  If Counter mode (ClkSrcA<1> == 0): */
++		setup |= ((CLKSRC_COUNTER << STDBIT_CLKSRC)	/*    Indicate Counter mode. */
++			| ((cra >> (CRABIT_CLKPOL_A - STDBIT_CLKPOL)) & STDMSK_CLKPOL)	/*    Pass through ClkPol. */
++			| (((cra & CRAMSK_CLKMULT_A) == (MULT_X0 << CRABIT_CLKMULT_A)) ?	/*    Force ClkMult to 1x if not legal, else pass through. */
+ 				(MULT_X1 << STDBIT_CLKMULT) :
+ 				((cra >> (CRABIT_CLKMULT_A -
+ 							STDBIT_CLKMULT)) &
+ 					STDMSK_CLKMULT)));
+ 
+-	// Return adjusted counter setup.
++	/*  Return adjusted counter setup. */
+ 	return setup;
+ }
+ 
+@@ -2836,98 +2835,99 @@ static uint16_t GetMode_B(comedi_device * dev, enc_private * k)
+ 	register uint16_t crb;
+ 	register uint16_t setup;
+ 
+-	// Fetch CRA and CRB register images.
++	/*  Fetch CRA and CRB register images. */
+ 	cra = DEBIread(dev, k->MyCRA);
+ 	crb = DEBIread(dev, k->MyCRB);
+ 
+-	// Populate the standardized counter setup bit fields.  Note:
+-	// IndexSrc is restricted to ENC_X or IndxPol.
+-	setup = (((crb << (STDBIT_INTSRC - CRBBIT_INTSRC_B)) & STDMSK_INTSRC)	// IntSrc   = IntSrcB.
+-		| ((crb << (STDBIT_LATCHSRC - CRBBIT_LATCHSRC)) & STDMSK_LATCHSRC)	// LatchSrc = LatchSrcB.
+-		| ((crb << (STDBIT_LOADSRC - CRBBIT_LOADSRC_B)) & STDMSK_LOADSRC)	// LoadSrc  = LoadSrcB.
+-		| ((crb << (STDBIT_INDXPOL - CRBBIT_INDXPOL_B)) & STDMSK_INDXPOL)	// IndxPol  = IndxPolB.
+-		| ((crb >> (CRBBIT_CLKENAB_B - STDBIT_CLKENAB)) & STDMSK_CLKENAB)	// ClkEnab  = ClkEnabB.
+-		| ((cra >> ((CRABIT_INDXSRC_B + 1) - STDBIT_INDXSRC)) & STDMSK_INDXSRC));	// IndxSrc  = IndxSrcB<1>.
+-
+-	// Adjust mode-dependent parameters.
+-	if ((crb & CRBMSK_CLKMULT_B) == (MULT_X0 << CRBBIT_CLKMULT_B))	// If Extender mode (ClkMultB == MULT_X0):
+-		setup |= ((CLKSRC_EXTENDER << STDBIT_CLKSRC)	//   Indicate Extender mode.
+-			| (MULT_X1 << STDBIT_CLKMULT)	//   Indicate multiplier is 1x.
+-			| ((cra >> (CRABIT_CLKSRC_B - STDBIT_CLKPOL)) & STDMSK_CLKPOL));	//   Set ClkPol equal to Timer count direction (ClkSrcB<0>).
+-
+-	else if (cra & (2 << CRABIT_CLKSRC_B))	// If Timer mode (ClkSrcB<1> == 1):
+-		setup |= ((CLKSRC_TIMER << STDBIT_CLKSRC)	//   Indicate Timer mode.
+-			| (MULT_X1 << STDBIT_CLKMULT)	//   Indicate multiplier is 1x.
+-			| ((cra >> (CRABIT_CLKSRC_B - STDBIT_CLKPOL)) & STDMSK_CLKPOL));	//   Set ClkPol equal to Timer count direction (ClkSrcB<0>).
+-
+-	else			// If Counter mode (ClkSrcB<1> == 0):
+-		setup |= ((CLKSRC_COUNTER << STDBIT_CLKSRC)	//   Indicate Timer mode.
+-			| ((crb >> (CRBBIT_CLKMULT_B - STDBIT_CLKMULT)) & STDMSK_CLKMULT)	//   Clock multiplier is passed through.
+-			| ((crb << (STDBIT_CLKPOL - CRBBIT_CLKPOL_B)) & STDMSK_CLKPOL));	//   Clock polarity is passed through.
+-
+-	// Return adjusted counter setup.
++	/*  Populate the standardized counter setup bit fields.  Note: */
++	/*  IndexSrc is restricted to ENC_X or IndxPol. */
++	setup = (((crb << (STDBIT_INTSRC - CRBBIT_INTSRC_B)) & STDMSK_INTSRC)	/*  IntSrc   = IntSrcB. */
++		| ((crb << (STDBIT_LATCHSRC - CRBBIT_LATCHSRC)) & STDMSK_LATCHSRC)	/*  LatchSrc = LatchSrcB. */
++		| ((crb << (STDBIT_LOADSRC - CRBBIT_LOADSRC_B)) & STDMSK_LOADSRC)	/*  LoadSrc  = LoadSrcB. */
++		| ((crb << (STDBIT_INDXPOL - CRBBIT_INDXPOL_B)) & STDMSK_INDXPOL)	/*  IndxPol  = IndxPolB. */
++		| ((crb >> (CRBBIT_CLKENAB_B - STDBIT_CLKENAB)) & STDMSK_CLKENAB)	/*  ClkEnab  = ClkEnabB. */
++		| ((cra >> ((CRABIT_INDXSRC_B + 1) - STDBIT_INDXSRC)) & STDMSK_INDXSRC));	/*  IndxSrc  = IndxSrcB<1>. */
++
++	/*  Adjust mode-dependent parameters. */
++	if ((crb & CRBMSK_CLKMULT_B) == (MULT_X0 << CRBBIT_CLKMULT_B))	/*  If Extender mode (ClkMultB == MULT_X0): */
++		setup |= ((CLKSRC_EXTENDER << STDBIT_CLKSRC)	/*    Indicate Extender mode. */
++			| (MULT_X1 << STDBIT_CLKMULT)	/*    Indicate multiplier is 1x. */
++			| ((cra >> (CRABIT_CLKSRC_B - STDBIT_CLKPOL)) & STDMSK_CLKPOL));	/*    Set ClkPol equal to Timer count direction (ClkSrcB<0>). */
++
++	else if (cra & (2 << CRABIT_CLKSRC_B))	/*  If Timer mode (ClkSrcB<1> == 1): */
++		setup |= ((CLKSRC_TIMER << STDBIT_CLKSRC)	/*    Indicate Timer mode. */
++			| (MULT_X1 << STDBIT_CLKMULT)	/*    Indicate multiplier is 1x. */
++			| ((cra >> (CRABIT_CLKSRC_B - STDBIT_CLKPOL)) & STDMSK_CLKPOL));	/*    Set ClkPol equal to Timer count direction (ClkSrcB<0>). */
++
++	else			/*  If Counter mode (ClkSrcB<1> == 0): */
++		setup |= ((CLKSRC_COUNTER << STDBIT_CLKSRC)	/*    Indicate Timer mode. */
++			| ((crb >> (CRBBIT_CLKMULT_B - STDBIT_CLKMULT)) & STDMSK_CLKMULT)	/*    Clock multiplier is passed through. */
++			| ((crb << (STDBIT_CLKPOL - CRBBIT_CLKPOL_B)) & STDMSK_CLKPOL));	/*    Clock polarity is passed through. */
++
++	/*  Return adjusted counter setup. */
+ 	return setup;
+ }
+ 
+-/////////////////////////////////////////////////////////////////////////////////////////////
+-// Set the operating mode for the specified counter.  The setup
+-// parameter is treated as a COUNTER_SETUP data type.  The following
+-// parameters are programmable (all other parms are ignored): ClkMult,
+-// ClkPol, ClkEnab, IndexSrc, IndexPol, LoadSrc.
++/*
++ * Set the operating mode for the specified counter.  The setup
++ * parameter is treated as a COUNTER_SETUP data type.  The following
++ * parameters are programmable (all other parms are ignored): ClkMult,
++ * ClkPol, ClkEnab, IndexSrc, IndexPol, LoadSrc.
++ */
+ 
+ static void SetMode_A(comedi_device * dev, enc_private * k, uint16_t Setup,
+ 	uint16_t DisableIntSrc)
+ {
+ 	register uint16_t cra;
+ 	register uint16_t crb;
+-	register uint16_t setup = Setup;	// Cache the Standard Setup.
++	register uint16_t setup = Setup;	/*  Cache the Standard Setup. */
+ 
+-	// Initialize CRA and CRB images.
+-	cra = ((setup & CRAMSK_LOADSRC_A)	// Preload trigger is passed through.
+-		| ((setup & STDMSK_INDXSRC) >> (STDBIT_INDXSRC - (CRABIT_INDXSRC_A + 1))));	// IndexSrc is restricted to ENC_X or IndxPol.
++	/*  Initialize CRA and CRB images. */
++	cra = ((setup & CRAMSK_LOADSRC_A)	/*  Preload trigger is passed through. */
++		| ((setup & STDMSK_INDXSRC) >> (STDBIT_INDXSRC - (CRABIT_INDXSRC_A + 1))));	/*  IndexSrc is restricted to ENC_X or IndxPol. */
+ 
+-	crb = (CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A	// Reset any pending CounterA event captures.
+-		| ((setup & STDMSK_CLKENAB) << (CRBBIT_CLKENAB_A - STDBIT_CLKENAB)));	// Clock enable is passed through.
++	crb = (CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A	/*  Reset any pending CounterA event captures. */
++		| ((setup & STDMSK_CLKENAB) << (CRBBIT_CLKENAB_A - STDBIT_CLKENAB)));	/*  Clock enable is passed through. */
+ 
+-	// Force IntSrc to Disabled if DisableIntSrc is asserted.
++	/*  Force IntSrc to Disabled if DisableIntSrc is asserted. */
+ 	if (!DisableIntSrc)
+ 		cra |= ((setup & STDMSK_INTSRC) >> (STDBIT_INTSRC -
+ 				CRABIT_INTSRC_A));
+ 
+-	// Populate all mode-dependent attributes of CRA & CRB images.
++	/*  Populate all mode-dependent attributes of CRA & CRB images. */
+ 	switch ((setup & STDMSK_CLKSRC) >> STDBIT_CLKSRC) {
+-	case CLKSRC_EXTENDER:	// Extender Mode: Force to Timer mode
+-		// (Extender valid only for B counters).
+-
+-	case CLKSRC_TIMER:	// Timer Mode:
+-		cra |= ((2 << CRABIT_CLKSRC_A)	//   ClkSrcA<1> selects system clock
+-			| ((setup & STDMSK_CLKPOL) >> (STDBIT_CLKPOL - CRABIT_CLKSRC_A))	//     with count direction (ClkSrcA<0>) obtained from ClkPol.
+-			| (1 << CRABIT_CLKPOL_A)	//   ClkPolA behaves as always-on clock enable.
+-			| (MULT_X1 << CRABIT_CLKMULT_A));	//   ClkMult must be 1x.
++	case CLKSRC_EXTENDER:	/*  Extender Mode: Force to Timer mode */
++		/*  (Extender valid only for B counters). */
++
++	case CLKSRC_TIMER:	/*  Timer Mode: */
++		cra |= ((2 << CRABIT_CLKSRC_A)	/*    ClkSrcA<1> selects system clock */
++			| ((setup & STDMSK_CLKPOL) >> (STDBIT_CLKPOL - CRABIT_CLKSRC_A))	/*      with count direction (ClkSrcA<0>) obtained from ClkPol. */
++			| (1 << CRABIT_CLKPOL_A)	/*    ClkPolA behaves as always-on clock enable. */
++			| (MULT_X1 << CRABIT_CLKMULT_A));	/*    ClkMult must be 1x. */
+ 		break;
+ 
+-	default:		// Counter Mode:
+-		cra |= (CLKSRC_COUNTER	//   Select ENC_C and ENC_D as clock/direction inputs.
+-			| ((setup & STDMSK_CLKPOL) << (CRABIT_CLKPOL_A - STDBIT_CLKPOL))	//   Clock polarity is passed through.
+-			| (((setup & STDMSK_CLKMULT) == (MULT_X0 << STDBIT_CLKMULT)) ?	//   Force multiplier to x1 if not legal, otherwise pass through.
++	default:		/*  Counter Mode: */
++		cra |= (CLKSRC_COUNTER	/*    Select ENC_C and ENC_D as clock/direction inputs. */
++			| ((setup & STDMSK_CLKPOL) << (CRABIT_CLKPOL_A - STDBIT_CLKPOL))	/*    Clock polarity is passed through. */
++			| (((setup & STDMSK_CLKMULT) == (MULT_X0 << STDBIT_CLKMULT)) ?	/*    Force multiplier to x1 if not legal, otherwise pass through. */
+ 				(MULT_X1 << CRABIT_CLKMULT_A) :
+ 				((setup & STDMSK_CLKMULT) << (CRABIT_CLKMULT_A -
+ 						STDBIT_CLKMULT))));
+ 	}
+ 
+-	// Force positive index polarity if IndxSrc is software-driven only,
+-	// otherwise pass it through.
++	/*  Force positive index polarity if IndxSrc is software-driven only, */
++	/*  otherwise pass it through. */
+ 	if (~setup & STDMSK_INDXSRC)
+ 		cra |= ((setup & STDMSK_INDXPOL) << (CRABIT_INDXPOL_A -
+ 				STDBIT_INDXPOL));
+ 
+-	// If IntSrc has been forced to Disabled, update the MISC2 interrupt
+-	// enable mask to indicate the counter interrupt is disabled.
++	/*  If IntSrc has been forced to Disabled, update the MISC2 interrupt */
++	/*  enable mask to indicate the counter interrupt is disabled. */
+ 	if (DisableIntSrc)
+ 		devpriv->CounterIntEnabs &= ~k->MyEventBits[3];
+ 
+-	// While retaining CounterB and LatchSrc configurations, program the
+-	// new counter operating mode.
++	/*  While retaining CounterB and LatchSrc configurations, program the */
++	/*  new counter operating mode. */
+ 	DEBIreplace(dev, k->MyCRA, CRAMSK_INDXSRC_B | CRAMSK_CLKSRC_B, cra);
+ 	DEBIreplace(dev, k->MyCRB,
+ 		(uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_A)), crb);
+@@ -2938,65 +2938,64 @@ static void SetMode_B(comedi_device * dev, enc_private * k, uint16_t Setup,
+ {
+ 	register uint16_t cra;
+ 	register uint16_t crb;
+-	register uint16_t setup = Setup;	// Cache the Standard Setup.
++	register uint16_t setup = Setup;	/*  Cache the Standard Setup. */
+ 
+-	// Initialize CRA and CRB images.
+-	cra = ((setup & STDMSK_INDXSRC) << ((CRABIT_INDXSRC_B + 1) - STDBIT_INDXSRC));	// IndexSrc field is restricted to ENC_X or IndxPol.
++	/*  Initialize CRA and CRB images. */
++	cra = ((setup & STDMSK_INDXSRC) << ((CRABIT_INDXSRC_B + 1) - STDBIT_INDXSRC));	/*  IndexSrc field is restricted to ENC_X or IndxPol. */
+ 
+-	crb = (CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B	// Reset event captures and disable interrupts.
+-		| ((setup & STDMSK_CLKENAB) << (CRBBIT_CLKENAB_B - STDBIT_CLKENAB))	// Clock enable is passed through.
+-		| ((setup & STDMSK_LOADSRC) >> (STDBIT_LOADSRC - CRBBIT_LOADSRC_B)));	// Preload trigger source is passed through.
++	crb = (CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B	/*  Reset event captures and disable interrupts. */
++		| ((setup & STDMSK_CLKENAB) << (CRBBIT_CLKENAB_B - STDBIT_CLKENAB))	/*  Clock enable is passed through. */
++		| ((setup & STDMSK_LOADSRC) >> (STDBIT_LOADSRC - CRBBIT_LOADSRC_B)));	/*  Preload trigger source is passed through. */
+ 
+-	// Force IntSrc to Disabled if DisableIntSrc is asserted.
++	/*  Force IntSrc to Disabled if DisableIntSrc is asserted. */
+ 	if (!DisableIntSrc)
+ 		crb |= ((setup & STDMSK_INTSRC) >> (STDBIT_INTSRC -
+ 				CRBBIT_INTSRC_B));
+ 
+-	// Populate all mode-dependent attributes of CRA & CRB images.
++	/*  Populate all mode-dependent attributes of CRA & CRB images. */
+ 	switch ((setup & STDMSK_CLKSRC) >> STDBIT_CLKSRC) {
+-	case CLKSRC_TIMER:	// Timer Mode:
+-		cra |= ((2 << CRABIT_CLKSRC_B)	//   ClkSrcB<1> selects system clock
+-			| ((setup & STDMSK_CLKPOL) << (CRABIT_CLKSRC_B - STDBIT_CLKPOL)));	//     with direction (ClkSrcB<0>) obtained from ClkPol.
+-		crb |= ((1 << CRBBIT_CLKPOL_B)	//   ClkPolB behaves as always-on clock enable.
+-			| (MULT_X1 << CRBBIT_CLKMULT_B));	//   ClkMultB must be 1x.
++	case CLKSRC_TIMER:	/*  Timer Mode: */
++		cra |= ((2 << CRABIT_CLKSRC_B)	/*    ClkSrcB<1> selects system clock */
++			| ((setup & STDMSK_CLKPOL) << (CRABIT_CLKSRC_B - STDBIT_CLKPOL)));	/*      with direction (ClkSrcB<0>) obtained from ClkPol. */
++		crb |= ((1 << CRBBIT_CLKPOL_B)	/*    ClkPolB behaves as always-on clock enable. */
++			| (MULT_X1 << CRBBIT_CLKMULT_B));	/*    ClkMultB must be 1x. */
+ 		break;
+ 
+-	case CLKSRC_EXTENDER:	// Extender Mode:
+-		cra |= ((2 << CRABIT_CLKSRC_B)	//   ClkSrcB source is OverflowA (same as "timer")
+-			| ((setup & STDMSK_CLKPOL) << (CRABIT_CLKSRC_B - STDBIT_CLKPOL)));	//     with direction obtained from ClkPol.
+-		crb |= ((1 << CRBBIT_CLKPOL_B)	//   ClkPolB controls IndexB -- always set to active.
+-			| (MULT_X0 << CRBBIT_CLKMULT_B));	//   ClkMultB selects OverflowA as the clock source.
++	case CLKSRC_EXTENDER:	/*  Extender Mode: */
++		cra |= ((2 << CRABIT_CLKSRC_B)	/*    ClkSrcB source is OverflowA (same as "timer") */
++			| ((setup & STDMSK_CLKPOL) << (CRABIT_CLKSRC_B - STDBIT_CLKPOL)));	/*      with direction obtained from ClkPol. */
++		crb |= ((1 << CRBBIT_CLKPOL_B)	/*    ClkPolB controls IndexB -- always set to active. */
++			| (MULT_X0 << CRBBIT_CLKMULT_B));	/*    ClkMultB selects OverflowA as the clock source. */
+ 		break;
+ 
+-	default:		// Counter Mode:
+-		cra |= (CLKSRC_COUNTER << CRABIT_CLKSRC_B);	//   Select ENC_C and ENC_D as clock/direction inputs.
+-		crb |= (((setup & STDMSK_CLKPOL) >> (STDBIT_CLKPOL - CRBBIT_CLKPOL_B))	//   ClkPol is passed through.
+-			| (((setup & STDMSK_CLKMULT) == (MULT_X0 << STDBIT_CLKMULT)) ?	//   Force ClkMult to x1 if not legal, otherwise pass through.
++	default:		/*  Counter Mode: */
++		cra |= (CLKSRC_COUNTER << CRABIT_CLKSRC_B);	/*    Select ENC_C and ENC_D as clock/direction inputs. */
++		crb |= (((setup & STDMSK_CLKPOL) >> (STDBIT_CLKPOL - CRBBIT_CLKPOL_B))	/*    ClkPol is passed through. */
++			| (((setup & STDMSK_CLKMULT) == (MULT_X0 << STDBIT_CLKMULT)) ?	/*    Force ClkMult to x1 if not legal, otherwise pass through. */
+ 				(MULT_X1 << CRBBIT_CLKMULT_B) :
+ 				((setup & STDMSK_CLKMULT) << (CRBBIT_CLKMULT_B -
+ 						STDBIT_CLKMULT))));
+ 	}
+ 
+-	// Force positive index polarity if IndxSrc is software-driven only,
+-	// otherwise pass it through.
++	/*  Force positive index polarity if IndxSrc is software-driven only, */
++	/*  otherwise pass it through. */
+ 	if (~setup & STDMSK_INDXSRC)
+ 		crb |= ((setup & STDMSK_INDXPOL) >> (STDBIT_INDXPOL -
+ 				CRBBIT_INDXPOL_B));
+ 
+-	// If IntSrc has been forced to Disabled, update the MISC2 interrupt
+-	// enable mask to indicate the counter interrupt is disabled.
++	/*  If IntSrc has been forced to Disabled, update the MISC2 interrupt */
++	/*  enable mask to indicate the counter interrupt is disabled. */
+ 	if (DisableIntSrc)
+ 		devpriv->CounterIntEnabs &= ~k->MyEventBits[3];
+ 
+-	// While retaining CounterA and LatchSrc configurations, program the
+-	// new counter operating mode.
++	/*  While retaining CounterA and LatchSrc configurations, program the */
++	/*  new counter operating mode. */
+ 	DEBIreplace(dev, k->MyCRA,
+ 		(uint16_t) (~(CRAMSK_INDXSRC_B | CRAMSK_CLKSRC_B)), cra);
+ 	DEBIreplace(dev, k->MyCRB, CRBMSK_CLKENAB_A | CRBMSK_LATCHSRC, crb);
+ }
+ 
+-////////////////////////////////////////////////////////////////////////
+-// Return/set a counter's enable.  enab: 0=always enabled, 1=enabled by index.
++/*  Return/set a counter's enable.  enab: 0=always enabled, 1=enabled by index. */
+ 
+ static void SetEnable_A(comedi_device * dev, enc_private * k, uint16_t enab)
+ {
+@@ -3023,10 +3022,10 @@ static uint16_t GetEnable_B(comedi_device * dev, enc_private * k)
+ 	return (DEBIread(dev, k->MyCRB) >> CRBBIT_CLKENAB_B) & 1;
+ }
+ 
+-////////////////////////////////////////////////////////////////////////
+-// Return/set a counter pair's latch trigger source.  0: On read
+-// access, 1: A index latches A, 2: B index latches B, 3: A overflow
+-// latches B.
++/* Return/set a counter pair's latch trigger source.  0: On read
++ * access, 1: A index latches A, 2: B index latches B, 3: A overflow
++ * latches B.
++ */
+ 
+ static void SetLatchSource(comedi_device * dev, enc_private * k, uint16_t value)
+ {
+@@ -3038,15 +3037,18 @@ static void SetLatchSource(comedi_device * dev, enc_private * k, uint16_t value)
+ 	DEBUG("SetLatchSource: SetLatchSource exit \n");
+ }
+ 
+-/* static uint16_t GetLatchSource(comedi_device *dev, enc_private *k ) */
+-/* { */
+-/*   return ( DEBIread( dev, k->MyCRB) >> CRBBIT_LATCHSRC ) & 3; */
+-/* } */
++/*
++ * static uint16_t GetLatchSource(comedi_device *dev, enc_private *k )
++ * {
++ * 	return ( DEBIread( dev, k->MyCRB) >> CRBBIT_LATCHSRC ) & 3;
++ * }
++ */
+ 
+-/////////////////////////////////////////////////////////////////////////
+-// Return/set the event that will trigger transfer of the preload
+-// register into the counter.  0=ThisCntr_Index, 1=ThisCntr_Overflow,
+-// 2=OverflowA (B counters only), 3=disabled.
++/*
++ * Return/set the event that will trigger transfer of the preload
++ * register into the counter.  0=ThisCntr_Index, 1=ThisCntr_Overflow,
++ * 2=OverflowA (B counters only), 3=disabled.
++ */
+ 
+ static void SetLoadTrig_A(comedi_device * dev, enc_private * k, uint16_t Trig)
+ {
+@@ -3071,23 +3073,23 @@ static uint16_t GetLoadTrig_B(comedi_device * dev, enc_private * k)
+ 	return (DEBIread(dev, k->MyCRB) >> CRBBIT_LOADSRC_B) & 3;
+ }
+ 
+-////////////////////
+-// Return/set counter interrupt source and clear any captured
+-// index/overflow events.  IntSource: 0=Disabled, 1=OverflowOnly,
+-// 2=IndexOnly, 3=IndexAndOverflow.
++/* Return/set counter interrupt source and clear any captured
++ * index/overflow events.  IntSource: 0=Disabled, 1=OverflowOnly,
++ * 2=IndexOnly, 3=IndexAndOverflow.
++ */
+ 
+ static void SetIntSrc_A(comedi_device * dev, enc_private * k,
+ 	uint16_t IntSource)
+ {
+-	// Reset any pending counter overflow or index captures.
++	/*  Reset any pending counter overflow or index captures. */
+ 	DEBIreplace(dev, k->MyCRB, (uint16_t) (~CRBMSK_INTCTRL),
+ 		CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A);
+ 
+-	// Program counter interrupt source.
++	/*  Program counter interrupt source. */
+ 	DEBIreplace(dev, k->MyCRA, ~CRAMSK_INTSRC_A,
+ 		(uint16_t) (IntSource << CRABIT_INTSRC_A));
+ 
+-	// Update MISC2 interrupt enable mask.
++	/*  Update MISC2 interrupt enable mask. */
+ 	devpriv->CounterIntEnabs =
+ 		(devpriv->CounterIntEnabs & ~k->MyEventBits[3]) | k->
+ 		MyEventBits[IntSource];
+@@ -3098,19 +3100,19 @@ static void SetIntSrc_B(comedi_device * dev, enc_private * k,
+ {
+ 	uint16_t crb;
+ 
+-	// Cache writeable CRB register image.
++	/*  Cache writeable CRB register image. */
+ 	crb = DEBIread(dev, k->MyCRB) & ~CRBMSK_INTCTRL;
+ 
+-	// Reset any pending counter overflow or index captures.
++	/*  Reset any pending counter overflow or index captures. */
+ 	DEBIwrite(dev, k->MyCRB,
+ 		(uint16_t) (crb | CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B));
+ 
+-	// Program counter interrupt source.
++	/*  Program counter interrupt source. */
+ 	DEBIwrite(dev, k->MyCRB,
+ 		(uint16_t) ((crb & ~CRBMSK_INTSRC_B) | (IntSource <<
+ 				CRBBIT_INTSRC_B)));
+ 
+-	// Update MISC2 interrupt enable mask.
++	/*  Update MISC2 interrupt enable mask. */
+ 	devpriv->CounterIntEnabs =
+ 		(devpriv->CounterIntEnabs & ~k->MyEventBits[3]) | k->
+ 		MyEventBits[IntSource];
+@@ -3126,8 +3128,7 @@ static uint16_t GetIntSrc_B(comedi_device * dev, enc_private * k)
+ 	return (DEBIread(dev, k->MyCRB) >> CRBBIT_INTSRC_B) & 3;
+ }
+ 
+-/////////////////////////////////////////////////////////////////////////
+-// Return/set the clock multiplier.
++/*  Return/set the clock multiplier. */
+ 
+ /* static void SetClkMult(comedi_device *dev, enc_private *k, uint16_t value )  */
+ /* { */
+@@ -3139,8 +3140,7 @@ static uint16_t GetIntSrc_B(comedi_device * dev, enc_private * k)
+ /*   return ( k->GetMode(dev, k ) >> STDBIT_CLKMULT ) & 3; */
+ /* } */
+ 
+-/* ////////////////////////////////////////////////////////////////////////// */
+-/* // Return/set the clock polarity. */
++/* Return/set the clock polarity. */
+ 
+ /* static void SetClkPol( comedi_device *dev,enc_private *k, uint16_t value )  */
+ /* { */
+@@ -3152,8 +3152,7 @@ static uint16_t GetIntSrc_B(comedi_device * dev, enc_private * k)
+ /*   return ( k->GetMode(dev, k ) >> STDBIT_CLKPOL ) & 1; */
+ /* } */
+ 
+-/* /////////////////////////////////////////////////////////////////////// */
+-/* // Return/set the clock source. */
++/* Return/set the clock source.  */
+ 
+ /* static void SetClkSrc( comedi_device *dev,enc_private *k, uint16_t value )  */
+ /* { */
+@@ -3165,8 +3164,7 @@ static uint16_t GetIntSrc_B(comedi_device * dev, enc_private * k)
+ /*   return ( k->GetMode(dev, k ) >> STDBIT_CLKSRC ) & 3; */
+ /* } */
+ 
+-/* //////////////////////////////////////////////////////////////////////// */
+-/* // Return/set the index polarity. */
++/* Return/set the index polarity. */
+ 
+ /* static void SetIndexPol(comedi_device *dev, enc_private *k, uint16_t value )  */
+ /* { */
+@@ -3178,8 +3176,7 @@ static uint16_t GetIntSrc_B(comedi_device * dev, enc_private * k)
+ /*   return ( k->GetMode(dev, k ) >> STDBIT_INDXPOL ) & 1; */
+ /* } */
+ 
+-/* //////////////////////////////////////////////////////////////////////// */
+-/* // Return/set the index source. */
++/*  Return/set the index source. */
+ 
+ /* static void SetIndexSrc(comedi_device *dev, enc_private *k, uint16_t value )  */
+ /* { */
+@@ -3192,8 +3189,7 @@ static uint16_t GetIntSrc_B(comedi_device * dev, enc_private * k)
+ /*   return ( k->GetMode(dev, k ) >> STDBIT_INDXSRC ) & 1; */
+ /* } */
+ 
+-///////////////////////////////////////////////////////////////////
+-// Generate an index pulse.
++/*  Generate an index pulse. */
+ 
+ static void PulseIndex_A(comedi_device * dev, enc_private * k)
+ {
+@@ -3201,7 +3197,7 @@ static void PulseIndex_A(comedi_device * dev, enc_private * k)
+ 
+ 	DEBUG("PulseIndex_A: pulse index enter\n");
+ 
+-	cra = DEBIread(dev, k->MyCRA);	// Pulse index.
++	cra = DEBIread(dev, k->MyCRA);	/*  Pulse index. */
+ 	DEBIwrite(dev, k->MyCRA, (uint16_t) (cra ^ CRAMSK_INDXPOL_A));
+ 	DEBUG("PulseIndex_A: pulse index step1\n");
+ 	DEBIwrite(dev, k->MyCRA, cra);
+@@ -3211,18 +3207,17 @@ static void PulseIndex_B(comedi_device * dev, enc_private * k)
+ {
+ 	register uint16_t crb;
+ 
+-	crb = DEBIread(dev, k->MyCRB) & ~CRBMSK_INTCTRL;	// Pulse index.
++	crb = DEBIread(dev, k->MyCRB) & ~CRBMSK_INTCTRL;	/*  Pulse index. */
+ 	DEBIwrite(dev, k->MyCRB, (uint16_t) (crb ^ CRBMSK_INDXPOL_B));
+ 	DEBIwrite(dev, k->MyCRB, crb);
+ }
+ 
+-/////////////////////////////////////////////////////////
+-// Write value into counter preload register.
++/*  Write value into counter preload register. */
+ 
+ static void Preload(comedi_device * dev, enc_private * k, uint32_t value)
+ {
+ 	DEBUG("Preload: preload enter\n");
+-	DEBIwrite(dev, (uint16_t) (k->MyLatchLsw), (uint16_t) value);	// Write value to preload register.
++	DEBIwrite(dev, (uint16_t) (k->MyLatchLsw), (uint16_t) value);	/*  Write value to preload register. */
+ 	DEBUG("Preload: preload step 1\n");
+ 	DEBIwrite(dev, (uint16_t) (k->MyLatchLsw + 2),
+ 		(uint16_t) (value >> 16));
+@@ -3232,16 +3227,16 @@ static void CountersInit(comedi_device * dev)
+ {
+ 	int chan;
+ 	enc_private *k;
+-	uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) |	// Preload upon
+-		// index.
+-		(INDXSRC_SOFT << BF_INDXSRC) |	// Disable hardware index.
+-		(CLKSRC_COUNTER << BF_CLKSRC) |	// Operating mode is counter.
+-		(CLKPOL_POS << BF_CLKPOL) |	// Active high clock.
+-		(CNTDIR_UP << BF_CLKPOL) |	// Count direction is up.
+-		(CLKMULT_1X << BF_CLKMULT) |	// Clock multiplier is 1x.
+-		(CLKENAB_INDEX << BF_CLKENAB);	// Enabled by index
+-
+-	// Disable all counter interrupts and clear any captured counter events.
++	uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) |	/*  Preload upon */
++		/*  index. */
++		(INDXSRC_SOFT << BF_INDXSRC) |	/*  Disable hardware index. */
++		(CLKSRC_COUNTER << BF_CLKSRC) |	/*  Operating mode is counter. */
++		(CLKPOL_POS << BF_CLKPOL) |	/*  Active high clock. */
++		(CNTDIR_UP << BF_CLKPOL) |	/*  Count direction is up. */
++		(CLKMULT_1X << BF_CLKMULT) |	/*  Clock multiplier is 1x. */
++		(CLKENAB_INDEX << BF_CLKENAB);	/*  Enabled by index */
++
++	/*  Disable all counter interrupts and clear any captured counter events. */
+ 	for (chan = 0; chan < S626_ENCODER_CHANNELS; chan++) {
+ 		k = &encpriv[chan];
+ 		k->SetMode(dev, k, Setup, TRUE);
+diff --git a/drivers/staging/comedi/drivers/s626.h b/drivers/staging/comedi/drivers/s626.h
+index 11d8b1ceb0b8..7a88bb35b50b 100644
+--- a/drivers/staging/comedi/drivers/s626.h
++++ b/drivers/staging/comedi/drivers/s626.h
+@@ -51,15 +51,15 @@
+ 
+    Example code
+ 
+-   insn.insn=INSN_CONFIG;   //configuration instruction
+-   insn.n=1;                //number of operation (must be 1)
+-   insn.data=&initialvalue; //initial value loaded into encoder
+-                            //during configuration
+-   insn.subdev=5;           //encoder subdevice
+-   insn.chanspec=CR_PACK(encoder_channel,0,AREF_OTHER); //encoder_channel
+-                                                        //to configure
+-
+-   comedi_do_insn(cf,&insn); //executing configuration
++   insn.insn=INSN_CONFIG;   // configuration instruction
++   insn.n=1;                // number of operation (must be 1)
++   insn.data=&initialvalue; // initial value loaded into encoder
++                            // during configuration
++   insn.subdev=5;           // encoder subdevice
++   insn.chanspec=CR_PACK(encoder_channel,0,AREF_OTHER); // encoder_channel
++                                                        // to configure
++
++   comedi_do_insn(cf,&insn); // executing configuration
+ */
+ 
+ #ifdef _DEBUG_
+@@ -88,147 +88,136 @@
+ #define INLINE static __inline
+ #endif
+ 
+-/////////////////////////////////////////////////////
+ #include
+ 
+ #define S626_SIZE 0x0200
+ #define SIZEOF_ADDRESS_SPACE		0x0200
+-#define DMABUF_SIZE			4096	// 4k pages
++#define DMABUF_SIZE			4096	/*  4k pages */
+ 
+ #define S626_ADC_CHANNELS       16
+ #define S626_DAC_CHANNELS       4
+ #define S626_ENCODER_CHANNELS   6
+ #define S626_DIO_CHANNELS       48
+-#define S626_DIO_BANKS		3	// Number of DIO groups.
+-#define S626_DIO_EXTCHANS	40	// Number of
+-					// extended-capability
+-					// DIO channels.
++#define S626_DIO_BANKS		3	/*  Number of DIO groups. */
++#define S626_DIO_EXTCHANS	40	/*  Number of */
++					/*  extended-capability */
++					/*  DIO channels. */
+ 
+-#define NUM_TRIMDACS	12	// Number of valid TrimDAC channels.
++#define NUM_TRIMDACS	12	/*  Number of valid TrimDAC channels. */
+ 
+-// PCI bus interface types.
+-#define INTEL				1	// Intel bus type.
+-#define MOTOROLA			2	// Motorola bus type.
++/*  PCI bus interface types. */
++#define INTEL				1	/*  Intel bus type. */
++#define MOTOROLA			2	/*  Motorola bus type. */
+ 
+-//////////////////////////////////////////////////////////
++#define PLATFORM		INTEL	/*  *** SELECT PLATFORM TYPE *** */
+ 
+-//////////////////////////////////////////////////////////
+-#define PLATFORM		INTEL	// *** SELECT PLATFORM TYPE ***
+-//////////////////////////////////////////////////////////
++#define RANGE_5V                0x10	/*  +/-5V range */
++#define RANGE_10V               0x00	/*  +/-10V range */
+ 
+-#define RANGE_5V                0x10	// +/-5V range
+-#define RANGE_10V               0x00	// +/-10V range
++#define EOPL			0x80	/*  End of ADC poll list marker. */
++#define GSEL_BIPOLAR5V		0x00F0	/*  LP_GSEL setting for 5V bipolar range. */
++#define GSEL_BIPOLAR10V		0x00A0	/*  LP_GSEL setting for 10V bipolar range. */
+ 
+-#define EOPL			0x80	// End of ADC poll list marker.
+-#define GSEL_BIPOLAR5V		0x00F0	// LP_GSEL setting for 5V bipolar range.
+-#define GSEL_BIPOLAR10V		0x00A0	// LP_GSEL setting for 10V bipolar range.
++/*  Error codes that must be visible to this base class. */
++#define ERR_ILLEGAL_PARM	0x00010000	/*  Illegal function parameter value was specified. */
++#define ERR_I2C			0x00020000	/*  I2C error. */
++#define ERR_COUNTERSETUP	0x00200000	/*  Illegal setup specified for counter channel. */
++#define ERR_DEBI_TIMEOUT	0x00400000	/*  DEBI transfer timed out. */
+ 
+-// Error codes that must be visible to this base class.
+-#define ERR_ILLEGAL_PARM	0x00010000	// Illegal function parameter value was specified.
+-#define ERR_I2C			0x00020000	// I2C error.
+-#define ERR_COUNTERSETUP	0x00200000	// Illegal setup specified for counter channel.
+-#define ERR_DEBI_TIMEOUT	0x00400000	// DEBI transfer timed out.
++/*  Organization (physical order) and size (in DWORDs) of logical DMA buffers contained by ANA_DMABUF. */
++#define ADC_DMABUF_DWORDS	40	/*  ADC DMA buffer must hold 16 samples, plus pre/post garbage samples. */
++#define DAC_WDMABUF_DWORDS	1	/*  DAC output DMA buffer holds a single sample. */
+ 
+-// Organization (physical order) and size (in DWORDs) of logical DMA buffers contained by ANA_DMABUF.
+-#define ADC_DMABUF_DWORDS	40	// ADC DMA buffer must hold 16 samples, plus pre/post garbage samples.
+-#define DAC_WDMABUF_DWORDS	1	// DAC output DMA buffer holds a single sample.
++/*  All remaining space in 4KB DMA buffer is available for the RPS1 program. */
+ 
+-// All remaining space in 4KB DMA buffer is available for the RPS1 program.
+-
+-// Address offsets, in DWORDS, from base of DMA buffer.
++/*  Address offsets, in DWORDS, from base of DMA buffer. */
+ #define DAC_WDMABUF_OS		ADC_DMABUF_DWORDS
+ 
+-// Interrupt enab bit in ISR and IER.
+-#define IRQ_GPIO3		0x00000040	// IRQ enable for GPIO3.
++/*  Interrupt enab bit in ISR and IER. */
++#define IRQ_GPIO3		0x00000040  /*  IRQ enable for GPIO3. */
+ #define IRQ_RPS1                0x10000000
+-#define ISR_AFOU		0x00000800	// Audio fifo
+-						// under/overflow
+-						// detected.
+-#define IRQ_COINT1A             0x0400	// conter 1A overflow
+-						// interrupt mask
+-#define IRQ_COINT1B             0x0800	// conter 1B overflow
+-						// interrupt mask
+-#define IRQ_COINT2A             0x1000	// conter 2A overflow
+-						// interrupt mask
+-#define IRQ_COINT2B             0x2000	// conter 2B overflow
+-						// interrupt mask
+-#define IRQ_COINT3A             0x4000	// conter 3A overflow
+-						// interrupt mask
+-#define IRQ_COINT3B             0x8000	// conter 3B overflow
+-						// interrupt mask
+-
+-// RPS command codes.
+-#define RPS_CLRSIGNAL		0x00000000	// CLEAR SIGNAL
+-#define RPS_SETSIGNAL		0x10000000	// SET SIGNAL
+-#define RPS_NOP			0x00000000	// NOP
+-#define RPS_PAUSE		0x20000000	// PAUSE
+-#define RPS_UPLOAD		0x40000000	// UPLOAD
+-#define RPS_JUMP		0x80000000	// JUMP
+-#define RPS_LDREG		0x90000100	// LDREG (1 uint32_t only)
+-#define RPS_STREG		0xA0000100	// STREG (1 uint32_t only)
+-#define RPS_STOP		0x50000000	// STOP
+-#define RPS_IRQ                 0x60000000	// IRQ
+-
+-#define RPS_LOGICAL_OR		0x08000000	// Logical OR conditionals.
+-#define RPS_INVERT		0x04000000	// Test for negated semaphores.
+-#define RPS_DEBI		0x00000002	// DEBI done
+-
+-#define RPS_SIG0		0x00200000	// RPS semaphore 0 (used by ADC).
+-#define RPS_SIG1		0x00400000	// RPS semaphore 1 (used by DAC).
+-#define RPS_SIG2		0x00800000	// RPS semaphore 2 (not used).
+-#define RPS_GPIO2		0x00080000	// RPS GPIO2
+-#define RPS_GPIO3		0x00100000	// RPS GPIO3
+-
+-#define RPS_SIGADC		RPS_SIG0	// Trigger/status for ADC's RPS program.
+-#define RPS_SIGDAC		RPS_SIG1	// Trigger/status for DAC's RPS program.
+-
+-// RPS clock parameters.
+-#define RPSCLK_SCALAR		8	// This is apparent ratio of PCI/RPS clks (undocumented!!).
+-#define RPSCLK_PER_US		( 33 / RPSCLK_SCALAR )	// Number of RPS clocks in one microsecond.
+-
+-// Event counter source addresses.
+-#define SBA_RPS_A0		0x27	// Time of RPS0 busy, in PCI clocks.
+-
+-// GPIO constants.
+-#define GPIO_BASE		0x10004000	// GPIO 0,2,3 = inputs, GPIO3 = IRQ; GPIO1 = out.
+-#define GPIO1_LO		0x00000000	// GPIO1 set to LOW.
+-#define GPIO1_HI		0x00001000	// GPIO1 set to HIGH.
+-
+-// Primary Status Register (PSR) constants.
+-#define PSR_DEBI_E		0x00040000	// DEBI event flag.
+-#define PSR_DEBI_S		0x00080000	// DEBI status flag.
+-#define PSR_A2_IN		0x00008000	// Audio output DMA2 protection address reached.
+-#define PSR_AFOU		0x00000800	// Audio FIFO under/overflow detected.
+-#define PSR_GPIO2		0x00000020	// GPIO2 input pin: 0=AdcBusy, 1=AdcIdle.
+-#define PSR_EC0S		0x00000001	// Event counter 0 threshold reached.
+-
+-// Secondary Status Register (SSR) constants.
+-#define SSR_AF2_OUT		0x00000200	// Audio 2 output FIFO under/overflow detected.
+-
+-// Master Control Register 1 (MC1) constants.
+-#define MC1_SOFT_RESET		0x80000000	// Invoke 7146 soft reset.
+-#define MC1_SHUTDOWN		0x3FFF0000	// Shut down all MC1-controlled enables.
+-
+-#define MC1_ERPS1		0x2000	// enab/disable RPS task 1.
+-#define MC1_ERPS0		0x1000	// enab/disable RPS task 0.
+-#define MC1_DEBI		0x0800	// enab/disable DEBI pins.
+-#define MC1_AUDIO		0x0200	// enab/disable audio port pins.
+-#define MC1_I2C			0x0100	// enab/disable I2C interface.
+-#define MC1_A2OUT		0x0008	// enab/disable transfer on A2 out.
+-#define MC1_A2IN		0x0004	// enab/disable transfer on A2 in.
+-#define MC1_A1IN		0x0001	// enab/disable transfer on A1 in.
+-
+-// Master Control Register 2 (MC2) constants.
+-#define MC2_UPLD_DEBIq		0x00020002	// Upload DEBI registers.
+-#define MC2_UPLD_IICq		0x00010001	// Upload I2C registers.
+-#define MC2_RPSSIG2_ONq		0x20002000	// Assert RPS_SIG2.
+-#define MC2_RPSSIG1_ONq		0x10001000	// Assert RPS_SIG1.
+-#define MC2_RPSSIG0_ONq		0x08000800	// Assert RPS_SIG0.
+-#define MC2_UPLD_DEBI_MASKq	0x00000002	// Upload DEBI mask.
+-#define MC2_UPLD_IIC_MASKq	0x00000001	// Upload I2C mask.
+-#define MC2_RPSSIG2_MASKq	0x00002000	// RPS_SIG2 bit mask.
+-#define MC2_RPSSIG1_MASKq	0x00001000	// RPS_SIG1 bit mask.
+-#define MC2_RPSSIG0_MASKq	0x00000800	// RPS_SIG0 bit mask.
++#define ISR_AFOU		0x00000800
++/* Audio fifo under/overflow  detected. */
++
++#define IRQ_COINT1A             0x0400 /* conter 1A overflow interrupt mask */
++#define IRQ_COINT1B             0x0800 /* conter 1B overflow interrupt mask */
++#define IRQ_COINT2A             0x1000 /* conter 2A overflow interrupt mask */
++#define IRQ_COINT2B             0x2000 /* conter 2B overflow interrupt mask */
++#define IRQ_COINT3A             0x4000 /* conter 3A overflow interrupt mask */
++#define IRQ_COINT3B             0x8000 /* conter 3B overflow interrupt mask */
++
++/*  RPS command codes. */
++#define RPS_CLRSIGNAL		0x00000000	/*  CLEAR SIGNAL */
++#define RPS_SETSIGNAL		0x10000000	/*  SET SIGNAL */
++#define RPS_NOP			0x00000000	/*  NOP */
++#define RPS_PAUSE		0x20000000	/*  PAUSE */
++#define RPS_UPLOAD		0x40000000	/*  UPLOAD */
++#define RPS_JUMP		0x80000000	/*  JUMP */
++#define RPS_LDREG		0x90000100	/*  LDREG (1 uint32_t only) */
++#define RPS_STREG		0xA0000100	/*  STREG (1 uint32_t only) */
++#define RPS_STOP		0x50000000	/*  STOP */
++#define RPS_IRQ                 0x60000000	/*  IRQ */
++
++#define RPS_LOGICAL_OR		0x08000000	/*  Logical OR conditionals. */
++#define RPS_INVERT		0x04000000	/*  Test for negated semaphores. */
++#define RPS_DEBI		0x00000002	/*  DEBI done */
++
++#define RPS_SIG0		0x00200000	/*  RPS semaphore 0 (used by ADC). */
++#define RPS_SIG1		0x00400000	/*  RPS semaphore 1 (used by DAC). */
++#define RPS_SIG2		0x00800000	/*  RPS semaphore 2 (not used). */
++#define RPS_GPIO2		0x00080000	/*  RPS GPIO2 */
++#define RPS_GPIO3		0x00100000	/*  RPS GPIO3 */
++
++#define RPS_SIGADC		RPS_SIG0	/*  Trigger/status for ADC's RPS program. */
++#define RPS_SIGDAC		RPS_SIG1	/*  Trigger/status for DAC's RPS program. */
++
++/*  RPS clock parameters. */
++#define RPSCLK_SCALAR		8	/*  This is apparent ratio of PCI/RPS clks (undocumented!!). */
++#define RPSCLK_PER_US		( 33 / RPSCLK_SCALAR )	/*  Number of RPS clocks in one microsecond. */
++
++/*  Event counter source addresses. */
++#define SBA_RPS_A0		0x27	/*  Time of RPS0 busy, in PCI clocks. */
++
++/*  GPIO constants. */
++#define GPIO_BASE		0x10004000	/*  GPIO 0,2,3 = inputs, GPIO3 = IRQ; GPIO1 = out. */
++#define GPIO1_LO		0x00000000	/*  GPIO1 set to LOW. */
++#define GPIO1_HI		0x00001000	/*  GPIO1 set to HIGH. */
++
++/*  Primary Status Register (PSR) constants. */
++#define PSR_DEBI_E		0x00040000	/*  DEBI event flag. */
++#define PSR_DEBI_S		0x00080000	/*  DEBI status flag. */
++#define PSR_A2_IN		0x00008000	/*  Audio output DMA2 protection address reached. */
++#define PSR_AFOU		0x00000800	/*  Audio FIFO under/overflow detected. */
++#define PSR_GPIO2		0x00000020	/*  GPIO2 input pin: 0=AdcBusy, 1=AdcIdle. */
++#define PSR_EC0S		0x00000001	/*  Event counter 0 threshold reached. */
++
++/*  Secondary Status Register (SSR) constants. */
++#define SSR_AF2_OUT		0x00000200	/*  Audio 2 output FIFO under/overflow detected. */
++
++/*  Master Control Register 1 (MC1) constants. */
++#define MC1_SOFT_RESET		0x80000000	/*  Invoke 7146 soft reset. */
++#define MC1_SHUTDOWN		0x3FFF0000	/*  Shut down all MC1-controlled enables. */
++
++#define MC1_ERPS1		0x2000	/*  enab/disable RPS task 1. */
++#define MC1_ERPS0		0x1000	/*  enab/disable RPS task 0. */
++#define MC1_DEBI		0x0800	/*  enab/disable DEBI pins. */
++#define MC1_AUDIO		0x0200	/*  enab/disable audio port pins. */
++#define MC1_I2C			0x0100	/*  enab/disable I2C interface. */
++#define MC1_A2OUT		0x0008	/*  enab/disable transfer on A2 out. */
++#define MC1_A2IN		0x0004	/*  enab/disable transfer on A2 in. */
++#define MC1_A1IN		0x0001	/*  enab/disable transfer on A1 in. */
++
++/*  Master Control Register 2 (MC2) constants. */
++#define MC2_UPLD_DEBIq		0x00020002	/*  Upload DEBI registers. */
++#define MC2_UPLD_IICq		0x00010001	/*  Upload I2C registers. */
++#define MC2_RPSSIG2_ONq		0x20002000	/*  Assert RPS_SIG2. */
++#define MC2_RPSSIG1_ONq		0x10001000	/*  Assert RPS_SIG1. */
++#define MC2_RPSSIG0_ONq		0x08000800	/*  Assert RPS_SIG0. */
++#define MC2_UPLD_DEBI_MASKq	0x00000002	/*  Upload DEBI mask. */
++#define MC2_UPLD_IIC_MASKq	0x00000001	/*  Upload I2C mask. */
++#define MC2_RPSSIG2_MASKq	0x00002000	/*  RPS_SIG2 bit mask. */
++#define MC2_RPSSIG1_MASKq	0x00001000	/*  RPS_SIG1 bit mask. */
++#define MC2_RPSSIG0_MASKq	0x00000800	/*  RPS_SIG0 bit mask. */
+ 
+ #define MC2_DELAYTRIG_4USq	MC2_RPSSIG1_ON
+ #define MC2_DELAYBUSY_4USq	MC2_RPSSIG1_MASK
+@@ -236,469 +225,425 @@
+ #define	MC2_DELAYTRIG_6USq	MC2_RPSSIG2_ON
+ #define MC2_DELAYBUSY_6USq	MC2_RPSSIG2_MASK
+ 
+-#define MC2_UPLD_DEBI		0x0002	// Upload DEBI.
+-#define MC2_UPLD_IIC		0x0001	// Upload I2C.
+-#define MC2_RPSSIG2		0x2000	// RPS signal 2 (not used).
+-#define MC2_RPSSIG1		0x1000	// RPS signal 1 (DAC RPS busy).
+-#define MC2_RPSSIG0		0x0800	// RPS signal 0 (ADC RPS busy).
+-
+-#define MC2_ADC_RPS		MC2_RPSSIG0	// ADC RPS busy.
+-#define MC2_DAC_RPS		MC2_RPSSIG1	// DAC RPS busy.
+-
+-///////////////////oldies///////////
+-#define MC2_UPLD_DEBIQ		0x00020002	// Upload DEBI registers.
+-#define MC2_UPLD_IICQ		0x00010001	// Upload I2C registers.
+-////////////////////////////////////////
+-
+-// PCI BUS (SAA7146) REGISTER ADDRESS OFFSETS ////////////////////////
+-#define P_PCI_BT_A		0x004C	// Audio DMA
+-						// burst/threshold
+-						// control.
+-#define P_DEBICFG               0x007C	// DEBI configuration.
+-#define P_DEBICMD               0x0080	// DEBI command.
+-#define P_DEBIPAGE              0x0084	// DEBI page.
+-#define P_DEBIAD                0x0088	// DEBI target address.
+-#define P_I2CCTRL               0x008C	// I2C control.
+-#define P_I2CSTAT               0x0090	// I2C status.
+-#define P_BASEA2_IN		0x00AC	// Audio input 2 base
+-						// physical DMAbuf
+-						// address.
+-#define P_PROTA2_IN		0x00B0	// Audio input 2
+-						// physical DMAbuf
+-						// protection address.
+-#define P_PAGEA2_IN		0x00B4	// Audio input 2
+-						// paging attributes.
+-#define P_BASEA2_OUT		0x00B8	// Audio output 2 base
+-						// physical DMAbuf
+-						// address.
+-#define P_PROTA2_OUT		0x00BC	// Audio output 2
+-						// physical DMAbuf
+-						// protection address.
+-#define P_PAGEA2_OUT		0x00C0	// Audio output 2
+-						// paging attributes.
+-#define P_RPSPAGE0              0x00C4	// RPS0 page.
+-#define P_RPSPAGE1              0x00C8	// RPS1 page.
+-#define P_RPS0_TOUT		0x00D4	// RPS0 time-out.
+-#define P_RPS1_TOUT		0x00D8	// RPS1 time-out.
+-#define P_IER                   0x00DC	// Interrupt enable.
+-#define P_GPIO                  0x00E0	// General-purpose I/O.
+-#define P_EC1SSR		0x00E4	// Event counter set 1
+-						// source select.
+-#define P_ECT1R			0x00EC	// Event counter
+-						// threshold set 1.
+-#define P_ACON1                 0x00F4	// Audio control 1.
+-#define P_ACON2                 0x00F8	// Audio control 2.
+-#define P_MC1                   0x00FC	// Master control 1.
+-#define P_MC2                   0x0100	// Master control 2.
+-#define P_RPSADDR0              0x0104	// RPS0 instruction pointer.
+-#define P_RPSADDR1              0x0108	// RPS1 instruction pointer.
+-#define P_ISR                   0x010C	// Interrupt status.
+-#define P_PSR                   0x0110	// Primary status.
+-#define P_SSR                   0x0114	// Secondary status.
+-#define P_EC1R			0x0118	// Event counter set 1.
+-#define P_ADP4			0x0138	// Logical audio DMA
+-						// pointer of audio
+-						// input FIFO A2_IN.
+-#define P_FB_BUFFER1            0x0144	// Audio feedback buffer 1.
+-#define P_FB_BUFFER2            0x0148	// Audio feedback buffer 2.
+-#define P_TSL1                  0x0180	// Audio time slot list 1.
+-#define P_TSL2                  0x01C0	// Audio time slot list 2.
+-
+-// LOCAL BUS (GATE ARRAY) REGISTER ADDRESS OFFSETS /////////////////
+-// Analog I/O registers:
+-#define LP_DACPOL		0x0082	//  Write DAC polarity.
+-#define LP_GSEL			0x0084	//  Write ADC gain.
+-#define LP_ISEL			0x0086	//  Write ADC channel select.
+-// Digital I/O (write only):
+-#define LP_WRINTSELA		0x0042	//  Write A interrupt enable.
+-#define LP_WREDGSELA		0x0044	//  Write A edge selection.
+-#define LP_WRCAPSELA		0x0046	//  Write A capture enable.
+-#define LP_WRDOUTA		0x0048	//  Write A digital output.
+-#define LP_WRINTSELB		0x0052	//  Write B interrupt enable.
+-#define LP_WREDGSELB		0x0054	//  Write B edge selection.
+-#define LP_WRCAPSELB		0x0056	//  Write B capture enable.
+-#define LP_WRDOUTB		0x0058	//  Write B digital output.
+-#define LP_WRINTSELC		0x0062	//  Write C interrupt enable.
+-#define LP_WREDGSELC		0x0064	//  Write C edge selection.
+-#define LP_WRCAPSELC		0x0066	//  Write C capture enable.
+-#define LP_WRDOUTC		0x0068	//  Write C digital output.
+-
+-// Digital I/O (read only):
+-#define LP_RDDINA		0x0040	//  Read digital input.
+-#define LP_RDCAPFLGA		0x0048	//  Read edges captured.
+-#define LP_RDINTSELA		0x004A	//  Read interrupt
+-						//  enable register.
+-#define LP_RDEDGSELA		0x004C	//  Read edge
+-						//  selection
+-						//  register.
+-#define LP_RDCAPSELA		0x004E	//  Read capture
+-						//  enable register.
+-#define LP_RDDINB		0x0050	//  Read digital input.
+-#define LP_RDCAPFLGB		0x0058	//  Read edges captured.
+-#define LP_RDINTSELB		0x005A	//  Read interrupt
+-						//  enable register.
+-#define LP_RDEDGSELB		0x005C	//  Read edge
+-						//  selection
+-						//  register.
+-#define LP_RDCAPSELB		0x005E	//  Read capture
+-						//  enable register.
+-#define LP_RDDINC		0x0060	//  Read digital input.
+-#define LP_RDCAPFLGC		0x0068	//  Read edges captured.
+-#define LP_RDINTSELC		0x006A	//  Read interrupt
+-						//  enable register.
+-#define LP_RDEDGSELC		0x006C	//  Read edge
+-						//  selection
+-						//  register.
+-#define LP_RDCAPSELC		0x006E	//  Read capture
+-						//  enable register.
+-// Counter Registers (read/write):
+-#define LP_CR0A			0x0000	//  0A setup register.
+-#define LP_CR0B			0x0002	//  0B setup register.
+-#define LP_CR1A			0x0004	//  1A setup register.
+-#define LP_CR1B			0x0006	//  1B setup register.
+-#define LP_CR2A			0x0008	//  2A setup register.
+-#define LP_CR2B			0x000A	//  2B setup register.
+-// Counter PreLoad (write) and Latch (read) Registers:
+-#define	LP_CNTR0ALSW		0x000C	//  0A lsw.
+-#define	LP_CNTR0AMSW		0x000E	//  0A msw.
+-#define	LP_CNTR0BLSW		0x0010	//  0B lsw.
+-#define	LP_CNTR0BMSW		0x0012	//  0B msw.
+-#define	LP_CNTR1ALSW		0x0014	//  1A lsw.
+-#define	LP_CNTR1AMSW		0x0016	//  1A msw.
+-#define	LP_CNTR1BLSW		0x0018	//  1B lsw.
+-#define	LP_CNTR1BMSW		0x001A	//  1B msw.
+-#define	LP_CNTR2ALSW		0x001C	//  2A lsw.
+-#define	LP_CNTR2AMSW		0x001E	//  2A msw.
+-#define	LP_CNTR2BLSW		0x0020	//  2B lsw.
+-#define	LP_CNTR2BMSW		0x0022	//  2B msw.
+-// Miscellaneous Registers (read/write):
+-#define LP_MISC1		0x0088	//  Read/write Misc1.
+-#define LP_WRMISC2		0x0090	//  Write Misc2.
+-#define LP_RDMISC2		0x0082	//  Read Misc2.
+-
+-// Bit masks for MISC1 register that are the same for reads and writes.
+-#define MISC1_WENABLE		0x8000	// enab writes to
+-						// MISC2 (except Clear
+-						// Watchdog bit).
+-#define MISC1_WDISABLE		0x0000	// Disable writes to MISC2.
+-#define MISC1_EDCAP		0x1000	// enab edge capture
+-						// on DIO chans
+-						// specified by
+-						// LP_WRCAPSELx.
+-#define MISC1_NOEDCAP		0x0000	// Disable edge
+-						// capture on
+-						// specified DIO
+-						// chans.
+-
+-// Bit masks for MISC1 register reads.
+-#define RDMISC1_WDTIMEOUT	0x4000	// Watchdog timer timed out.
+-
+-// Bit masks for MISC2 register writes.
+-#define WRMISC2_WDCLEAR		0x8000	// Reset watchdog
+-						// timer to zero.
+-#define WRMISC2_CHARGE_ENABLE	0x4000	// enab battery
+-						// trickle charging.
+-
+-// Bit masks for MISC2 register that are the same for reads and writes.
+-#define MISC2_BATT_ENABLE	0x0008	// Backup battery enable.
+-#define MISC2_WDENABLE		0x0004	// Watchdog timer enable.
+-#define MISC2_WDPERIOD_MASK	0x0003	// Watchdog interval
+-						// select mask.
+-
+-// Bit masks for ACON1 register.
+-#define A2_RUN			0x40000000	// Run A2 based on TSL2.
+-#define A1_RUN			0x20000000	// Run A1 based on TSL1.
+-#define A1_SWAP			0x00200000	// Use big-endian for A1.
+-#define A2_SWAP			0x00100000	// Use big-endian for A2.
+-#define WS_MODES		0x00019999	// WS0 = TSL1 trigger
+-						// input, WS1-WS4 =
+-						// CS* outputs.
+-
+-#if PLATFORM == INTEL		// Base ACON1 config:
+-						// always run A1 based
+-						// on TSL1.
++#define MC2_UPLD_DEBI		0x0002	/*  Upload DEBI. */
++#define MC2_UPLD_IIC		0x0001	/*  Upload I2C. */
++#define MC2_RPSSIG2		0x2000	/*  RPS signal 2 (not used). */
++#define MC2_RPSSIG1		0x1000	/*  RPS signal 1 (DAC RPS busy). */
++#define MC2_RPSSIG0		0x0800	/*  RPS signal 0 (ADC RPS busy). */
++
++#define MC2_ADC_RPS		MC2_RPSSIG0	/*  ADC RPS busy. */
++#define MC2_DAC_RPS		MC2_RPSSIG1	/*  DAC RPS busy. */
++
++/* ***** oldies ***** */
++#define MC2_UPLD_DEBIQ		0x00020002	/*  Upload DEBI registers. */
++#define MC2_UPLD_IICQ		0x00010001	/*  Upload I2C registers. */
++
++/*  PCI BUS (SAA7146) REGISTER ADDRESS OFFSETS */
++#define P_PCI_BT_A		0x004C	/* Audio DMA burst/threshold control. */
++#define P_DEBICFG               0x007C	/* DEBI configuration. */
++#define P_DEBICMD               0x0080	/* DEBI command. */
++#define P_DEBIPAGE              0x0084	/* DEBI page. */
++#define P_DEBIAD                0x0088	/* DEBI target address. */
++#define P_I2CCTRL               0x008C	/* I2C control. */
++#define P_I2CSTAT               0x0090	/* I2C status. */
++#define P_BASEA2_IN		0x00AC	/* Audio input 2 base physical DMAbuf
++					 * address. */
++#define P_PROTA2_IN		0x00B0	/* Audio input 2 physical DMAbuf
++					 * protection address. */
++#define P_PAGEA2_IN		0x00B4	/* Audio input 2 paging attributes. */
++#define P_BASEA2_OUT		0x00B8	/* Audio output 2 base physical DMAbuf
++					 * address. */
++#define P_PROTA2_OUT		0x00BC	/* Audio output 2 physical DMAbuf
++					 * protection address. */
++#define P_PAGEA2_OUT		0x00C0	/* Audio output 2 paging attributes. */
++#define P_RPSPAGE0              0x00C4	/* RPS0 page. */
++#define P_RPSPAGE1              0x00C8	/* RPS1 page. */
++#define P_RPS0_TOUT		0x00D4	/* RPS0 time-out. */
++#define P_RPS1_TOUT		0x00D8	/* RPS1 time-out. */
++#define P_IER                   0x00DC	/* Interrupt enable. */
++#define P_GPIO                  0x00E0	/* General-purpose I/O. */
++#define P_EC1SSR		0x00E4	/* Event counter set 1 source select. */
++#define P_ECT1R			0x00EC	/* Event counter threshold set 1. */
++#define P_ACON1                 0x00F4	/* Audio control 1. */
++#define P_ACON2                 0x00F8	/* Audio control 2. */
++#define P_MC1                   0x00FC	/* Master control 1. */
++#define P_MC2                   0x0100	/* Master control 2. */
++#define P_RPSADDR0              0x0104	/* RPS0 instruction pointer. */
++#define P_RPSADDR1              0x0108	/* RPS1 instruction pointer. */
++#define P_ISR                   0x010C	/* Interrupt status. */
++#define P_PSR                   0x0110	/* Primary status. */
++#define P_SSR                   0x0114	/* Secondary status. */
++#define P_EC1R			0x0118	/* Event counter set 1. */
++#define P_ADP4			0x0138	/* Logical audio DMA pointer of audio
++					 * input FIFO A2_IN. */
++#define P_FB_BUFFER1            0x0144	/* Audio feedback buffer 1. */
++#define P_FB_BUFFER2            0x0148	/* Audio feedback buffer 2. */
++#define P_TSL1                  0x0180	/* Audio time slot list 1. */
++#define P_TSL2                  0x01C0	/* Audio time slot list 2. */
++
++/*  LOCAL BUS (GATE ARRAY) REGISTER ADDRESS OFFSETS */
++/*  Analog I/O registers: */
++#define LP_DACPOL		0x0082	/*   Write DAC polarity. */
++#define LP_GSEL			0x0084	/*   Write ADC gain. */
++#define LP_ISEL			0x0086	/*   Write ADC channel select. */
++/*  Digital I/O (write only): */
++#define LP_WRINTSELA		0x0042	/*   Write A interrupt enable. */
++#define LP_WREDGSELA		0x0044	/*   Write A edge selection. */
++#define LP_WRCAPSELA		0x0046	/*   Write A capture enable. */
++#define LP_WRDOUTA		0x0048	/*   Write A digital output. */
++#define LP_WRINTSELB		0x0052	/*   Write B interrupt enable. */
++#define LP_WREDGSELB		0x0054	/*   Write B edge selection. */
++#define LP_WRCAPSELB		0x0056	/*   Write B capture enable. */
++#define LP_WRDOUTB		0x0058	/*   Write B digital output. */
++#define LP_WRINTSELC		0x0062	/*   Write C interrupt enable. */
++#define LP_WREDGSELC		0x0064	/*   Write C edge selection. */
++#define LP_WRCAPSELC		0x0066	/*   Write C capture enable. */
++#define LP_WRDOUTC		0x0068	/*   Write C digital output. */
++
++/*  Digital I/O (read only): */
++#define LP_RDDINA		0x0040	/*   Read digital input. */
++#define LP_RDCAPFLGA		0x0048	/*   Read edges captured. */
++#define LP_RDINTSELA		0x004A	/*   Read interrupt enable register. */
++#define LP_RDEDGSELA		0x004C	/*   Read edge selection register. */
++#define LP_RDCAPSELA		0x004E	/*   Read capture enable register. */
++#define LP_RDDINB		0x0050	/*   Read digital input. */
++#define LP_RDCAPFLGB		0x0058	/*   Read edges captured. */
++#define LP_RDINTSELB		0x005A	/*   Read interrupt enable register. */
++#define LP_RDEDGSELB		0x005C	/*   Read edge selection register. */
++#define LP_RDCAPSELB		0x005E	/*   Read capture enable register. */
++#define LP_RDDINC		0x0060	/*   Read digital input. */
++#define LP_RDCAPFLGC		0x0068	/*   Read edges captured. */
++#define LP_RDINTSELC		0x006A	/*   Read interrupt enable register. */
++#define LP_RDEDGSELC		0x006C	/*   Read edge selection register. */
++#define LP_RDCAPSELC		0x006E	/*   Read capture enable register. */
++
++/*  Counter Registers (read/write): */
++#define LP_CR0A			0x0000	/*   0A setup register. */
++#define LP_CR0B			0x0002	/*   0B setup register. */
++#define LP_CR1A			0x0004	/*   1A setup register. */
++#define LP_CR1B			0x0006	/*   1B setup register. */
++#define LP_CR2A			0x0008	/*   2A setup register. */
++#define LP_CR2B			0x000A	/*   2B setup register. */
++
++/*  Counter PreLoad (write) and Latch (read) Registers: */
++#define	LP_CNTR0ALSW		0x000C	/*   0A lsw. */
++#define	LP_CNTR0AMSW		0x000E	/*   0A msw. */
++#define	LP_CNTR0BLSW		0x0010	/*   0B lsw. */
++#define	LP_CNTR0BMSW		0x0012	/*   0B msw. */
++#define	LP_CNTR1ALSW		0x0014	/*   1A lsw. */
++#define	LP_CNTR1AMSW		0x0016	/*   1A msw. */
++#define	LP_CNTR1BLSW		0x0018	/*   1B lsw. */
++#define	LP_CNTR1BMSW		0x001A	/*   1B msw. */
++#define	LP_CNTR2ALSW		0x001C	/*   2A lsw. */
++#define	LP_CNTR2AMSW		0x001E	/*   2A msw. */
++#define	LP_CNTR2BLSW		0x0020	/*   2B lsw. */
++#define	LP_CNTR2BMSW		0x0022	/*   2B msw. */
++
++/*  Miscellaneous Registers (read/write): */
++#define LP_MISC1		0x0088	/*   Read/write Misc1. */
++#define LP_WRMISC2		0x0090	/*   Write Misc2. */
++#define LP_RDMISC2		0x0082	/*   Read Misc2. */
++
++/*  Bit masks for MISC1 register that are the same for reads and writes. */
++#define MISC1_WENABLE		0x8000	/* enab writes to MISC2 (except Clear
++					 * Watchdog bit). */
++#define MISC1_WDISABLE		0x0000	/* Disable writes to MISC2. */
++#define MISC1_EDCAP		0x1000	/* enab edge capture on DIO chans
++					 * specified by  LP_WRCAPSELx. */
++#define MISC1_NOEDCAP		0x0000	/* Disable edge capture on specified
++					 * DIO chans. */
++
++/*  Bit masks for MISC1 register reads. */
++#define RDMISC1_WDTIMEOUT	0x4000	/*  Watchdog timer timed out. */
++
++/*  Bit masks for MISC2 register writes. */
++#define WRMISC2_WDCLEAR		0x8000	/*  Reset watchdog timer to zero. */
++#define WRMISC2_CHARGE_ENABLE	0x4000	/*  enab battery trickle charging. */
++
++/*  Bit masks for MISC2 register that are the same for reads and writes. */
++#define MISC2_BATT_ENABLE	0x0008	/*  Backup battery enable. */
++#define MISC2_WDENABLE		0x0004	/*  Watchdog timer enable. */
++#define MISC2_WDPERIOD_MASK	0x0003	/*  Watchdog interval */
++						/*  select mask. */
++
++/*  Bit masks for ACON1 register. */
++#define A2_RUN			0x40000000	/*  Run A2 based on TSL2. */
++#define A1_RUN			0x20000000	/*  Run A1 based on TSL1. */
++#define A1_SWAP			0x00200000	/*  Use big-endian for A1. */
++#define A2_SWAP			0x00100000	/*  Use big-endian for A2. */
++#define WS_MODES		0x00019999	/*  WS0 = TSL1 trigger */
++						/*  input, WS1-WS4 = */
++						/*  CS* outputs. */
++
++#if PLATFORM == INTEL		/* Base ACON1 config: always run A1 based
++				 * on TSL1. */
+ #define ACON1_BASE		( WS_MODES | A1_RUN )
+ #elif PLATFORM == MOTOROLA
+ #define ACON1_BASE		( WS_MODES | A1_RUN | A1_SWAP | A2_SWAP )
+ #endif
+ 
+-#define ACON1_ADCSTART		ACON1_BASE	// Start ADC: run A1
+-						// based on TSL1.
+-#define ACON1_DACSTART		( ACON1_BASE | A2_RUN )	// Start
+-							// transmit to
+-							// DAC: run A2
+-							// based on
+-							// TSL2.
+-#define ACON1_DACSTOP		ACON1_BASE	// Halt A2.
+-
+-// Bit masks for ACON2 register.
+-#define A1_CLKSRC_BCLK1		0x00000000	// A1 bit rate = BCLK1 (ADC).
+-#define A2_CLKSRC_X1		0x00800000	// A2 bit rate = ACLK/1 (DACs).
+-#define A2_CLKSRC_X2		0x00C00000	// A2 bit rate = ACLK/2 (DACs).
+-#define A2_CLKSRC_X4		0x01400000	// A2 bit rate = ACLK/4 (DACs).
+-#define INVERT_BCLK2		0x00100000	// Invert BCLK2 (DACs).
+-#define BCLK2_OE		0x00040000	// enab BCLK2 (DACs).
+-#define ACON2_XORMASK		0x000C0000	// XOR mask for ACON2
+-						// active-low bits.
++#define ACON1_ADCSTART		ACON1_BASE	/* Start ADC: run A1
++						 *  based on TSL1. */
++#define ACON1_DACSTART		( ACON1_BASE | A2_RUN )
++/* Start transmit to DAC: run A2 based on TSL2. */
++#define ACON1_DACSTOP		ACON1_BASE	/*  Halt A2. */
++
++/*  Bit masks for ACON2 register. */
++#define A1_CLKSRC_BCLK1		0x00000000	/*  A1 bit rate = BCLK1 (ADC). */
++#define A2_CLKSRC_X1		0x00800000	/*  A2 bit rate = ACLK/1 (DACs). */
++#define A2_CLKSRC_X2		0x00C00000	/*  A2 bit rate = ACLK/2 (DACs). */
++#define A2_CLKSRC_X4		0x01400000	/*  A2 bit rate = ACLK/4 (DACs). */
++#define INVERT_BCLK2		0x00100000	/*  Invert BCLK2 (DACs). */
++#define BCLK2_OE		0x00040000	/*  enab BCLK2 (DACs). */
++#define ACON2_XORMASK		0x000C0000	/*  XOR mask for ACON2 */
++						/*  active-low bits. */
+ 
+ #define ACON2_INIT		( ACON2_XORMASK ^ ( A1_CLKSRC_BCLK1 | A2_CLKSRC_X2 | INVERT_BCLK2 | BCLK2_OE ) )
+ 
+-// Bit masks for timeslot records.
+-#define WS1		     	0x40000000	// WS output to assert.
++/*  Bit masks for timeslot records. */
++#define WS1		     	0x40000000	/*  WS output to assert. */
+ #define WS2		     	0x20000000
+ #define WS3		     	0x10000000
+ #define WS4		     	0x08000000
+-#define RSD1			0x01000000	// Shift A1 data in on SD1.
+-#define SDW_A1			0x00800000	// Store rcv'd char at
+-						// next char slot of
+-						// DWORD1 buffer.
+-#define SIB_A1			0x00400000	// Store rcv'd char at
+-						// next char slot of
+-						// FB1 buffer.
+-#define SF_A1			0x00200000	// Write unsigned long
+-						// buffer to input
+-						// FIFO.
+-
+-//Select parallel-to-serial converter's data source:
+-#define XFIFO_0			0x00000000	//   Data fifo byte 0.
+-#define XFIFO_1			0x00000010	//   Data fifo byte 1.
+-#define XFIFO_2			0x00000020	//   Data fifo byte 2.
+-#define XFIFO_3			0x00000030	//   Data fifo byte 3.
+-#define XFB0			0x00000040	//   FB_BUFFER byte 0.
+-#define XFB1			0x00000050	//   FB_BUFFER byte 1.
+-#define XFB2			0x00000060	//   FB_BUFFER byte 2.
+-#define XFB3			0x00000070	//   FB_BUFFER byte 3.
+-#define SIB_A2			0x00000200	// Store next dword
+-						// from A2's input
+-						// shifter to FB2
+-						// buffer.
+-#define SF_A2			0x00000100	// Store next dword
+-						// from A2's input
+-						// shifter to its
+-						// input fifo.
+-#define LF_A2			0x00000080	// Load next dword
+-						// from A2's output
+-						// fifo into its
+-						// output dword
+-						// buffer.
+-#define XSD2			0x00000008	// Shift data out on SD2.
+-#define RSD3			0x00001800	// Shift data in on SD3.
+-#define RSD2			0x00001000	// Shift data in on SD2.
+-#define LOW_A2			0x00000002	// Drive last SD low
+-						// for 7 clks, then
+-						// tri-state.
+-#define EOS		     	0x00000001	// End of superframe.
+-
+-//////////////////////
+-
+-// I2C configuration constants.
+-#define I2C_CLKSEL		0x0400	// I2C bit rate =
+-						// PCIclk/480 = 68.75
+-						// KHz.
+-#define I2C_BITRATE		68.75	// I2C bus data bit
+-						// rate (determined by
+-						// I2C_CLKSEL) in KHz.
+-#define I2C_WRTIME		15.0	// Worst case time,in
+-						// msec, for EEPROM
+-						// internal write op.
+-
+-// I2C manifest constants.
+-
+-// Max retries to wait for EEPROM write.
++#define RSD1			0x01000000	/* Shift A1 data in on SD1. */
++#define SDW_A1			0x00800000	/* Store rcv'd char at next
++						 * char slot of DWORD1 buffer. */
++#define SIB_A1			0x00400000	/* Store rcv'd char at next
++						 * char slot of FB1 buffer. */
++#define SF_A1			0x00200000	/* Write unsigned long
++						 * buffer to input FIFO. */
++
++/* Select parallel-to-serial converter's data source: */
++#define XFIFO_0			0x00000000	/*    Data fifo byte 0. */
++#define XFIFO_1			0x00000010	/*    Data fifo byte 1. */
++#define XFIFO_2			0x00000020	/*    Data fifo byte 2. */
++#define XFIFO_3			0x00000030	/*    Data fifo byte 3. */
++#define XFB0			0x00000040	/*    FB_BUFFER byte 0. */
++#define XFB1			0x00000050	/*    FB_BUFFER byte 1. */
++#define XFB2			0x00000060	/*    FB_BUFFER byte 2. */
++#define XFB3			0x00000070	/*    FB_BUFFER byte 3. */
++#define SIB_A2			0x00000200	/* Store next dword from A2's
++						 * input shifter to FB2 buffer. */
++#define SF_A2			0x00000100	/* Store next dword from A2's
++						 * input shifter to its input
++						 * fifo. */
++#define LF_A2			0x00000080	/* Load next dword from A2's
++						 * output fifo into its
++						 * output dword buffer. */
++#define XSD2			0x00000008	/*  Shift data out on SD2. */
++#define RSD3			0x00001800	/*  Shift data in on SD3. */
++#define RSD2			0x00001000	/*  Shift data in on SD2. */
++#define LOW_A2			0x00000002	/*  Drive last SD low */
++						/*  for 7 clks, then */
++						/*  tri-state. */
++#define EOS		     	0x00000001	/*  End of superframe. */
++
++
++/*  I2C configuration constants. */
++#define I2C_CLKSEL		0x0400
++/* I2C bit rate = PCIclk/480 = 68.75 KHz. */
++
++#define I2C_BITRATE		68.75
++/* I2C bus data bit rate (determined by I2C_CLKSEL) in KHz. */
++
++#define I2C_WRTIME		15.0
++/* Worst case time, in msec, for EEPROM internal write op. */
++
++/*  I2C manifest constants. */
++
++/*  Max retries to wait for EEPROM write. */
+ #define I2C_RETRIES		( I2C_WRTIME * I2C_BITRATE / 9.0 )
+-#define I2C_ERR			0x0002	// I2C control/status
+-						// flag ERROR.
+-#define I2C_BUSY		0x0001	// I2C control/status
+-						// flag BUSY.
+-#define I2C_ABORT		0x0080	// I2C status flag ABORT.
+-#define I2C_ATTRSTART		0x3	// I2C attribute START.
+-#define I2C_ATTRCONT		0x2	// I2C attribute CONT.
+-#define I2C_ATTRSTOP		0x1	// I2C attribute STOP.
+-#define I2C_ATTRNOP		0x0	// I2C attribute NOP.
+-
+-// I2C read command  | EEPROM address.
++#define I2C_ERR			0x0002	/*  I2C control/status */
++						/*  flag ERROR. */
++#define I2C_BUSY		0x0001	/*  I2C control/status */
++						/*  flag BUSY. */
++#define I2C_ABORT		0x0080	/*  I2C status flag ABORT. */
++#define I2C_ATTRSTART		0x3	/*  I2C attribute START. */
++#define I2C_ATTRCONT		0x2	/*  I2C attribute CONT. */
++#define I2C_ATTRSTOP		0x1	/*  I2C attribute STOP. */
++#define I2C_ATTRNOP		0x0	/*  I2C attribute NOP. */
++
++/*  I2C read command  | EEPROM address. */
+ #define I2CR			( devpriv->I2CAdrs | 1 )
+ 
+-// I2C write command | EEPROM address.
++/*  I2C write command | EEPROM address. */
+ #define I2CW			( devpriv->I2CAdrs )
+ 
+-// Code macros used for constructing I2C command bytes.
++/*  Code macros used for constructing I2C command bytes. */
+ #define I2C_B2(ATTR,VAL)	( ( (ATTR) << 6 ) | ( (VAL) << 24 ) )
+ #define I2C_B1(ATTR,VAL)	( ( (ATTR) << 4 ) | ( (VAL) << 16 ) )
+ #define I2C_B0(ATTR,VAL)	( ( (ATTR) << 2 ) | ( (VAL) <<  8 ) )
+ 
+-////////////////////////////////////////////////////////
+-//oldest
+-#define P_DEBICFGq              0x007C	// DEBI configuration.
+-#define P_DEBICMDq              0x0080	// DEBI command.
+-#define P_DEBIPAGEq             0x0084	// DEBI page.
+-#define P_DEBIADq               0x0088	// DEBI target address.
+-
+-#define DEBI_CFG_TOQ		0x03C00000	// timeout (15 PCI cycles)
+-#define DEBI_CFG_FASTQ		0x10000000	// fast mode enable
+-#define DEBI_CFG_16Q		0x00080000	// 16-bit access enable
+-#define DEBI_CFG_INCQ		0x00040000	// enable address increment
+-#define DEBI_CFG_TIMEROFFQ	0x00010000	// disable timer
+-#define DEBI_CMD_RDQ		0x00050000	// read immediate 2 bytes
+-#define DEBI_CMD_WRQ		0x00040000	// write immediate 2 bytes
+-#define DEBI_PAGE_DISABLEQ	0x00000000	// paging disable
+-
+-///////////////////////////////////////////
+-// DEBI command constants.
+-#define DEBI_CMD_SIZE16		( 2 << 17 )	// Transfer size is
+-						// always 2 bytes.
+-#define DEBI_CMD_READ		0x00010000	// Read operation.
+-#define DEBI_CMD_WRITE		0x00000000	// Write operation.
+-
+-// Read immediate 2 bytes.
++/* oldest */
++#define P_DEBICFGq              0x007C	/*  DEBI configuration. */
++#define P_DEBICMDq              0x0080	/*  DEBI command. */
++#define P_DEBIPAGEq             0x0084	/*  DEBI page. */
++#define P_DEBIADq               0x0088	/*  DEBI target address. */
++
++#define DEBI_CFG_TOQ		0x03C00000	/*  timeout (15 PCI cycles) */
++#define DEBI_CFG_FASTQ		0x10000000	/*  fast mode enable */
++#define DEBI_CFG_16Q		0x00080000	/*  16-bit access enable */
++#define DEBI_CFG_INCQ		0x00040000	/*  enable address increment */
++#define DEBI_CFG_TIMEROFFQ	0x00010000	/*  disable timer */
++#define DEBI_CMD_RDQ		0x00050000	/*  read immediate 2 bytes */
++#define DEBI_CMD_WRQ		0x00040000	/*  write immediate 2 bytes */
++#define DEBI_PAGE_DISABLEQ	0x00000000	/*  paging disable */
++
++/*  DEBI command constants. */
++#define DEBI_CMD_SIZE16		( 2 << 17 )	/*  Transfer size is */
++						/*  always 2 bytes. */
++#define DEBI_CMD_READ		0x00010000	/*  Read operation. */
++#define DEBI_CMD_WRITE		0x00000000	/*  Write operation. */
++
++/*  Read immediate 2 bytes. */
+ #define DEBI_CMD_RDWORD		( DEBI_CMD_READ  | DEBI_CMD_SIZE16 )
+ 
+-// Write immediate 2 bytes.
++/*  Write immediate 2 bytes. */
+ #define DEBI_CMD_WRWORD		( DEBI_CMD_WRITE | DEBI_CMD_SIZE16 )
+ 
+-// DEBI configuration constants.
+-#define DEBI_CFG_XIRQ_EN	0x80000000	// enab external
+-						// interrupt on GPIO3.
+-#define DEBI_CFG_XRESUME	0x40000000	// Resume block
+-						// transfer when XIRQ
+-						// deasserted.
+-#define DEBI_CFG_FAST		0x10000000	// Fast mode enable.
+-
+-// 4-bit field that specifies DEBI timeout value in PCI clock cycles:
+-#define DEBI_CFG_TOUT_BIT	22	//   Finish DEBI cycle after
+-					//   this many clocks.
+-
+-// 2-bit field that specifies Endian byte lane steering:
+-#define DEBI_CFG_SWAP_NONE	0x00000000	//   Straight - don't
+-						//   swap any bytes
+-						//   (Intel).
+-#define DEBI_CFG_SWAP_2		0x00100000	//   2-byte swap (Motorola).
+-#define DEBI_CFG_SWAP_4		0x00200000	//   4-byte swap.
+-#define DEBI_CFG_16		0x00080000	// Slave is able to
+-						// serve 16-bit
+-						// cycles.
+-
+-#define DEBI_CFG_SLAVE16	0x00080000	// Slave is able to
+-						// serve 16-bit
+-						// cycles.
+-#define DEBI_CFG_INC		0x00040000	// enab address
+-						// increment for block
+-						// transfers.
+-#define DEBI_CFG_INTEL		0x00020000	// Intel style local bus.
+-#define DEBI_CFG_TIMEROFF	0x00010000	// Disable timer.
++/*  DEBI configuration constants. */
++#define DEBI_CFG_XIRQ_EN	0x80000000	/*  enab external */
++						/*  interrupt on GPIO3. */
++#define DEBI_CFG_XRESUME	0x40000000	/*  Resume block */
++						/*  transfer when XIRQ */
++						/*  deasserted. */
++#define DEBI_CFG_FAST		0x10000000	/*  Fast mode enable. */
++
++/*  4-bit field that specifies DEBI timeout value in PCI clock cycles: */
++#define DEBI_CFG_TOUT_BIT	22	/*    Finish DEBI cycle after */
++					/*    this many clocks. */
++
++/*  2-bit field that specifies Endian byte lane steering: */
++#define DEBI_CFG_SWAP_NONE	0x00000000	/*    Straight - don't */
++						/*    swap any bytes */
++						/*    (Intel). */
++#define DEBI_CFG_SWAP_2		0x00100000	/*    2-byte swap (Motorola). */
++#define DEBI_CFG_SWAP_4		0x00200000	/*    4-byte swap. */
++#define DEBI_CFG_16		0x00080000	/*  Slave is able to */
++						/*  serve 16-bit */
++						/*  cycles. */
++
++#define DEBI_CFG_SLAVE16	0x00080000	/*  Slave is able to */
++						/*  serve 16-bit */
++						/*  cycles. */
++#define DEBI_CFG_INC		0x00040000	/*  enab address */
++						/*  increment for block */
++						/*  transfers. */
++#define DEBI_CFG_INTEL		0x00020000	/*  Intel style local bus. */
++#define DEBI_CFG_TIMEROFF	0x00010000	/*  Disable timer. */
+ 
+ #if PLATFORM == INTEL
+ 
+-#define DEBI_TOUT		7	// Wait 7 PCI clocks
+-						// (212 ns) before
+-						// polling RDY.
++#define DEBI_TOUT		7	/*  Wait 7 PCI clocks */
++						/*  (212 ns) before */
++						/*  polling RDY. */
+ 
+-// Intel byte lane steering (pass through all byte lanes).
++/*  Intel byte lane steering (pass through all byte lanes). */
+ #define DEBI_SWAP		DEBI_CFG_SWAP_NONE
+ 
+ #elif PLATFORM == MOTOROLA
+ 
+-#define DEBI_TOUT		15	// Wait 15 PCI clocks (454 ns)
+-					// maximum before timing out.
+-#define DEBI_SWAP		DEBI_CFG_SWAP_2	// Motorola byte lane steering.
++#define DEBI_TOUT		15	/*  Wait 15 PCI clocks (454 ns) */
++					/*  maximum before timing out. */
++#define DEBI_SWAP		DEBI_CFG_SWAP_2	/*  Motorola byte lane steering. */
+ 
+ #endif
+ 
+-// DEBI page table constants.
+-#define DEBI_PAGE_DISABLE	0x00000000	// Paging disable.
+-
+-///////////////////EXTRA FROM OTHER SANSORAY  * .h////////
+-
+-// LoadSrc values:
+-#define LOADSRC_INDX		0	// Preload core in response to
+-					// Index.
+-#define LOADSRC_OVER		1	// Preload core in response to
+-					// Overflow.
+-#define LOADSRCB_OVERA		2	// Preload B core in response
+-					// to A Overflow.
+-#define LOADSRC_NONE		3	// Never preload core.
+-
+-// IntSrc values:
+-#define INTSRC_NONE 		0	// Interrupts disabled.
+-#define INTSRC_OVER 		1	// Interrupt on Overflow.
+-#define INTSRC_INDX 		2	// Interrupt on Index.
+-#define INTSRC_BOTH 		3	// Interrupt on Index or Overflow.
+-
+-// LatchSrc values:
+-#define LATCHSRC_AB_READ	0	// Latch on read.
+-#define LATCHSRC_A_INDXA	1	// Latch A on A Index.
+-#define LATCHSRC_B_INDXB	2	// Latch B on B Index.
+-#define LATCHSRC_B_OVERA	3	// Latch B on A Overflow.
+-
+-// IndxSrc values:
+-#define INDXSRC_HARD		0	// Hardware or software index.
+-#define INDXSRC_SOFT		1	// Software index only.
+-
+-// IndxPol values:
+-#define INDXPOL_POS 		0	// Index input is active high.
+-#define INDXPOL_NEG 		1	// Index input is active low.
+-
+-// ClkSrc values:
+-#define CLKSRC_COUNTER		0	// Counter mode.
+-#define CLKSRC_TIMER		2	// Timer mode.
+-#define CLKSRC_EXTENDER		3	// Extender mode.
+-
+-// ClkPol values:
+-#define CLKPOL_POS		0	// Counter/Extender clock is
+-					// active high.
+-#define CLKPOL_NEG		1	// Counter/Extender clock is
+-					// active low.
+-#define CNTDIR_UP		0	// Timer counts up.
+-#define CNTDIR_DOWN 		1	// Timer counts down.
+-
+-// ClkEnab values:
+-#define CLKENAB_ALWAYS		0	// Clock always enabled.
+-#define CLKENAB_INDEX		1	// Clock is enabled by index.
+-
+-// ClkMult values:
+-#define CLKMULT_4X 		0	// 4x clock multiplier.
+-#define CLKMULT_2X 		1	// 2x clock multiplier.
+-#define CLKMULT_1X 		2	// 1x clock multiplier.
+-
+-// Bit Field positions in COUNTER_SETUP structure:
+-#define BF_LOADSRC		9	// Preload trigger.
+-#define BF_INDXSRC		7	// Index source.
+-#define BF_INDXPOL		6	// Index polarity.
+-#define BF_CLKSRC		4	// Clock source.
+-#define BF_CLKPOL		3	// Clock polarity/count direction.
+-#define BF_CLKMULT		1	// Clock multiplier.
+-#define BF_CLKENAB		0	// Clock enable.
+-
+-// Enumerated counter operating modes specified by ClkSrc bit field in
+-// a COUNTER_SETUP.
+-
+-#define CLKSRC_COUNTER		0	// Counter: ENC_C clock, ENC_D
+-					// direction.
+-#define CLKSRC_TIMER		2	// Timer: SYS_C clock,
+-					// direction specified by
+-					// ClkPol.
+-#define CLKSRC_EXTENDER		3	// Extender: OVR_A clock,
+-					// ENC_D direction.
+-
+-// Enumerated counter clock multipliers.
+-
+-#define MULT_X0			0x0003	// Supports no multipliers;
+-					// fixed physical multiplier =
+-					// 3.
+-#define MULT_X1			0x0002	// Supports multiplier x1;
+-					// fixed physical multiplier =
+-					// 2.
+-#define MULT_X2			0x0001	// Supports multipliers x1,
+-					// x2; physical multipliers =
+-					// 1 or 2.
+-#define MULT_X4			0x0000	// Supports multipliers x1,
+-					// x2, x4; physical
+-					// multipliers = 0, 1 or 2.
+-
+-// Sanity-check limits for parameters.
+-
+-#define NUM_COUNTERS		6	// Maximum valid counter
+-					// logical channel number.
++/*  DEBI page table constants. */
++#define DEBI_PAGE_DISABLE	0x00000000	/*  Paging disable. */
++
++/* ******* EXTRA FROM OTHER SANSORAY  * .h  ******* */
++
++/*  LoadSrc values: */
++#define LOADSRC_INDX		0	/*  Preload core in response to */
++					/*  Index. */
++#define LOADSRC_OVER		1	/*  Preload core in response to */
++					/*  Overflow. */
++#define LOADSRCB_OVERA		2	/*  Preload B core in response */
++					/*  to A Overflow. */
++#define LOADSRC_NONE		3	/*  Never preload core. */
++
++/*  IntSrc values: */
++#define INTSRC_NONE 		0	/*  Interrupts disabled. */
++#define INTSRC_OVER 		1	/*  Interrupt on Overflow. */
++#define INTSRC_INDX 		2	/*  Interrupt on Index. */
++#define INTSRC_BOTH 		3	/*  Interrupt on Index or Overflow. */
++
++/*  LatchSrc values: */
++#define LATCHSRC_AB_READ	0	/*  Latch on read. */
++#define LATCHSRC_A_INDXA	1	/*  Latch A on A Index. */
++#define LATCHSRC_B_INDXB	2	/*  Latch B on B Index. */
++#define LATCHSRC_B_OVERA	3	/*  Latch B on A Overflow. */
++
++/*  IndxSrc values: */
++#define INDXSRC_HARD		0	/*  Hardware or software index. */
++#define INDXSRC_SOFT		1	/*  Software index only. */
++
++/*  IndxPol values: */
++#define INDXPOL_POS 		0	/*  Index input is active high. */
++#define INDXPOL_NEG 		1	/*  Index input is active low. */
++
++/*  ClkSrc values: */
++#define CLKSRC_COUNTER		0	/*  Counter mode. */
++#define CLKSRC_TIMER		2	/*  Timer mode. */
++#define CLKSRC_EXTENDER		3	/*  Extender mode. */
++
++/*  ClkPol values: */
++#define CLKPOL_POS		0	/*  Counter/Extender clock is */
++					/*  active high. */
++#define CLKPOL_NEG		1	/*  Counter/Extender clock is */
++					/*  active low. */
++#define CNTDIR_UP		0	/*  Timer counts up. */
++#define CNTDIR_DOWN 		1	/*  Timer counts down. */
++
++/*  ClkEnab values: */
++#define CLKENAB_ALWAYS		0	/*  Clock always enabled. */
++#define CLKENAB_INDEX		1	/*  Clock is enabled by index. */
++
++/*  ClkMult values: */
++#define CLKMULT_4X 		0	/*  4x clock multiplier. */
++#define CLKMULT_2X 		1	/*  2x clock multiplier. */
++#define CLKMULT_1X 		2	/*  1x clock multiplier. */
++
++/*  Bit Field positions in COUNTER_SETUP structure: */
++#define BF_LOADSRC		9	/*  Preload trigger. */
++#define BF_INDXSRC		7	/*  Index source. */
++#define BF_INDXPOL		6	/*  Index polarity. */
++#define BF_CLKSRC		4	/*  Clock source. */
++#define BF_CLKPOL		3	/*  Clock polarity/count direction. */
++#define BF_CLKMULT		1	/*  Clock multiplier. */
++#define BF_CLKENAB		0	/*  Clock enable. */
++
++/*  Enumerated counter operating modes specified by ClkSrc bit field in */
++/*  a COUNTER_SETUP. */
++
++#define CLKSRC_COUNTER		0	/*  Counter: ENC_C clock, ENC_D */
++					/*  direction. */
++#define CLKSRC_TIMER		2	/*  Timer: SYS_C clock, */
++					/*  direction specified by */
++					/*  ClkPol. */
++#define CLKSRC_EXTENDER		3	/*  Extender: OVR_A clock, */
++					/*  ENC_D direction. */
++
++/*  Enumerated counter clock multipliers. */
++
++#define MULT_X0			0x0003	/*  Supports no multipliers; */
++					/*  fixed physical multiplier = */
++					/*  3. */
++#define MULT_X1			0x0002	/*  Supports multiplier x1; */
++					/*  fixed physical multiplier = */
++					/*  2. */
++#define MULT_X2			0x0001	/*  Supports multipliers x1, */
++					/*  x2; physical multipliers = */
++					/*  1 or 2. */
++#define MULT_X4			0x0000	/*  Supports multipliers x1, */
++					/*  x2, x4; physical */
++					/*  multipliers = 0, 1 or 2. */
++
++/*  Sanity-check limits for parameters. */
++
++#define NUM_COUNTERS		6	/*  Maximum valid counter */
++					/*  logical channel number. */
+ #define NUM_INTSOURCES		4
+ #define NUM_LATCHSOURCES	4
+ #define NUM_CLKMULTS		4
+@@ -708,33 +653,33 @@
+ #define NUM_INDEXSOURCES	2
+ #define NUM_LOADTRIGS		4
+ 
+-// Bit field positions in CRA and CRB counter control registers.
+-
+-// Bit field positions in CRA:
+-#define CRABIT_INDXSRC_B	14	//   B index source.
+-#define CRABIT_CLKSRC_B		12	//   B clock source.
+-#define CRABIT_INDXPOL_A	11	//   A index polarity.
+-#define CRABIT_LOADSRC_A	 9	//   A preload trigger.
+-#define CRABIT_CLKMULT_A	 7	//   A clock multiplier.
+-#define CRABIT_INTSRC_A		 5	//   A interrupt source.
+-#define CRABIT_CLKPOL_A		 4	//   A clock polarity.
+-#define CRABIT_INDXSRC_A	 2	//   A index source.
+-#define CRABIT_CLKSRC_A		 0	//   A clock source.
+-
+-// Bit field positions in CRB:
+-#define CRBBIT_INTRESETCMD	15	//   Interrupt reset command.
+-#define CRBBIT_INTRESET_B	14	//   B interrupt reset enable.
+-#define CRBBIT_INTRESET_A	13	//   A interrupt reset enable.
+-#define CRBBIT_CLKENAB_A	12	//   A clock enable.
+-#define CRBBIT_INTSRC_B		10	//   B interrupt source.
+-#define CRBBIT_LATCHSRC		 8	//   A/B latch source.
+-#define CRBBIT_LOADSRC_B	 6	//   B preload trigger.
+-#define CRBBIT_CLKMULT_B	 3	//   B clock multiplier.
+-#define CRBBIT_CLKENAB_B	 2	//   B clock enable.
+-#define CRBBIT_INDXPOL_B	 1	//   B index polarity.
+-#define CRBBIT_CLKPOL_B		 0	//   B clock polarity.
+-
+-// Bit field masks for CRA and CRB.
++/*  Bit field positions in CRA and CRB counter control registers. */
++
++/*  Bit field positions in CRA: */
++#define CRABIT_INDXSRC_B	14	/*    B index source. */
++#define CRABIT_CLKSRC_B		12	/*    B clock source. */
++#define CRABIT_INDXPOL_A	11	/*    A index polarity. */
++#define CRABIT_LOADSRC_A	 9	/*    A preload trigger. */
++#define CRABIT_CLKMULT_A	 7	/*    A clock multiplier. */
++#define CRABIT_INTSRC_A		 5	/*    A interrupt source. */
++#define CRABIT_CLKPOL_A		 4	/*    A clock polarity. */
++#define CRABIT_INDXSRC_A	 2	/*    A index source. */
++#define CRABIT_CLKSRC_A		 0	/*    A clock source. */
++
++/*  Bit field positions in CRB: */
++#define CRBBIT_INTRESETCMD	15	/*    Interrupt reset command. */
++#define CRBBIT_INTRESET_B	14	/*    B interrupt reset enable. */
++#define CRBBIT_INTRESET_A	13	/*    A interrupt reset enable. */
++#define CRBBIT_CLKENAB_A	12	/*    A clock enable. */
++#define CRBBIT_INTSRC_B		10	/*    B interrupt source. */
++#define CRBBIT_LATCHSRC		 8	/*    A/B latch source. */
++#define CRBBIT_LOADSRC_B	 6	/*    B preload trigger. */
++#define CRBBIT_CLKMULT_B	 3	/*    B clock multiplier. */
++#define CRBBIT_CLKENAB_B	 2	/*    B clock enable. */
++#define CRBBIT_INDXPOL_B	 1	/*    B index polarity. */
++#define CRBBIT_CLKPOL_B		 0	/*    B clock polarity. */
++
++/*  Bit field masks for CRA and CRB. */
+ 
+ #define CRAMSK_INDXSRC_B	( (uint16_t)( 3 << CRABIT_INDXSRC_B) )
+ #define CRAMSK_CLKSRC_B		( (uint16_t)( 3 << CRABIT_CLKSRC_B) )
+@@ -758,9 +703,9 @@
+ #define CRBMSK_INDXPOL_B	( (uint16_t)( 1 << CRBBIT_INDXPOL_B) )
+ #define CRBMSK_CLKPOL_B		( (uint16_t)( 1 << CRBBIT_CLKPOL_B) )
+ 
+-#define CRBMSK_INTCTRL		( CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A | CRBMSK_INTRESET_B )	// Interrupt reset control bits.
++#define CRBMSK_INTCTRL		( CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A | CRBMSK_INTRESET_B )	/*  Interrupt reset control bits. */
+ 
+-// Bit field positions for standardized SETUP structure.
++/*  Bit field positions for standardized SETUP structure. */
+ 
+ #define STDBIT_INTSRC		13
+ #define STDBIT_LATCHSRC		11
+@@ -772,7 +717,7 @@
+ #define STDBIT_CLKMULT		 1
+ #define STDBIT_CLKENAB		 0
+ 
+-// Bit field masks for standardized SETUP structure.
++/*  Bit field masks for standardized SETUP structure. */
+ 
+ #define STDMSK_INTSRC		( (uint16_t)( 3 << STDBIT_INTSRC   ) )
+ #define STDMSK_LATCHSRC		( (uint16_t)( 3 << STDBIT_LATCHSRC ) )
+@@ -784,7 +729,6 @@
+ #define STDMSK_CLKMULT		( (uint16_t)( 3 << STDBIT_CLKMULT  ) )
+ #define STDMSK_CLKENAB		( (uint16_t)( 1 << STDBIT_CLKENAB  ) )
+ 
+-//////////////////////////////////////////////////////////
+ 
+ /* typedef struct indexCounter */
+ /* { */
+diff --git a/drivers/staging/comedi/pci_ids.h b/drivers/staging/comedi/pci_ids.h
+index c61ba90f9601..d979aa8e396b 100644
+--- a/drivers/staging/comedi/pci_ids.h
++++ b/drivers/staging/comedi/pci_ids.h
+@@ -28,4 +28,4 @@
+ #define PCI_DEVICE_ID_QUANCOM_GPIB	0x3302
+ #endif
+ 
+-#endif // __COMPAT_LINUX_PCI_IDS_H
++#endif /* __COMPAT_LINUX_PCI_IDS_H */
+diff --git a/drivers/staging/comedi/proc.c b/drivers/staging/comedi/proc.c
+index 5a2b72d87572..031004ebc6ec 100644
+--- a/drivers/staging/comedi/proc.c
++++ b/drivers/staging/comedi/proc.c
+@@ -31,7 +31,7 @@
+ #define __NO_VERSION__
+ #include "comedidev.h"
+ #include 
+-//#include 
++/* #include  */
+ 
+ int comedi_read_procmem(char *buf, char **start, off_t offset, int len,
+ 	int *eof, void *data);
+diff --git a/drivers/staging/comedi/range.c b/drivers/staging/comedi/range.c
+index 61dc3cd6a9fd..2934fb3162cd 100644
+--- a/drivers/staging/comedi/range.c
++++ b/drivers/staging/comedi/range.c
+@@ -88,7 +88,7 @@ static int aref_invalid(comedi_subdevice * s, unsigned int chanspec)
+ {
+ 	unsigned int aref;
+ 
+-	// disable reporting invalid arefs... maybe someday
++	/*  disable reporting invalid arefs... maybe someday */
+ 	return 0;
+ 
+ 	aref = CR_AREF(chanspec);
+diff --git a/drivers/staging/comedi/rt.c b/drivers/staging/comedi/rt.c
+index 385b81b94ac5..2546c64dab00 100644
+--- a/drivers/staging/comedi/rt.c
++++ b/drivers/staging/comedi/rt.c
+@@ -78,7 +78,7 @@ int comedi_request_irq(unsigned irq, irqreturn_t(*handler) (int,
+ 
+ 	ret = request_irq(irq, handler, unshared_flags, device, dev_id);
+ 	if (ret < 0) {
+-		// we failed, so fall back on allowing shared interrupt (which we won't ever make RT)
++		/*  we failed, so fall back on allowing shared interrupt (which we won't ever make RT) */
+ 		if (flags & IRQF_SHARED) {
+ 			rt_printk
+ 				("comedi: cannot get unshared interrupt, will not use RT interrupts.\n");
+@@ -192,7 +192,7 @@ static void handle_void_irq(int irq)
+ 		return;
+ 	}
+ 	it->handler(irq, it->dev_id PT_REGS_NULL);
+-	rt_enable_irq(irq);	//needed by rtai-adeos, seems like it shouldn't hurt earlier versions
++	rt_enable_irq(irq);	/* needed by rtai-adeos, seems like it shouldn't hurt earlier versions */
+ }
+ 
+ DECLARE_VOID_IRQ(0);
+@@ -402,11 +402,11 @@ static int comedi_rt_release_irq(struct comedi_irq_struct *it)
+ 
+ void comedi_rt_init(void)
+ {
+-	//rt_pend_tq_init();
++	/* rt_pend_tq_init(); */
+ }
+ 
+ void comedi_rt_cleanup(void)
+ {
+-	//rt_pend_tq_cleanup();
++	/* rt_pend_tq_cleanup(); */
+ }
+ #endif
+diff --git a/drivers/staging/comedi/rt_pend_tq.c b/drivers/staging/comedi/rt_pend_tq.c
+index 83ccf4da2952..f9dfd9d40cd3 100644
+--- a/drivers/staging/comedi/rt_pend_tq.c
++++ b/drivers/staging/comedi/rt_pend_tq.c
+@@ -3,7 +3,7 @@
+ #include 
+ #include 
+ #include 
+-#include "comedidev.h"	// for rt spinlocks
++#include "comedidev.h"	/* for rt spinlocks */
+ #include "rt_pend_tq.h"
+ #ifdef CONFIG_COMEDI_RTAI
+ #include 
+@@ -27,7 +27,7 @@ volatile static struct rt_pend_tq *volatile rt_pend_head = rt_pend_tq,
+ int rt_pend_tq_irq = 0;
+ DEFINE_SPINLOCK(rt_pend_tq_lock);
+ 
+-// WARNING: following code not checked against race conditions yet.
++/* WARNING: following code not checked against race conditions yet. */
+ #define INC_CIRCULAR_PTR(ptr,begin,size) do {if(++(ptr)>=(begin)+(size)) (ptr)=(begin); } while(0)
+ #define DEC_CIRCULAR_PTR(ptr,begin,size) do {if(--(ptr)<(begin)) (ptr)=(begin)+(size)-1; } while(0)
+ 
+@@ -42,7 +42,7 @@ int rt_pend_call(void (*func) (int arg1, void *arg2), int arg1, void *arg2)
+ 	comedi_spin_lock_irqsave(&rt_pend_tq_lock, flags);
+ 	INC_CIRCULAR_PTR(rt_pend_head, rt_pend_tq, RT_PEND_TQ_SIZE);
+ 	if (rt_pend_head == rt_pend_tail) {
+-		// overflow, we just refuse to take this request
++		/* overflow, we just refuse to take this request */
+ 		DEC_CIRCULAR_PTR(rt_pend_head, rt_pend_tq, RT_PEND_TQ_SIZE);
+ 		comedi_spin_unlock_irqrestore(&rt_pend_tq_lock, flags);
+ 		return -EAGAIN;

commit 6641445c3e05460c5164ab15a17fc4ee481ca213
+Author: Bill Pemberton 
+Date:   Thu Apr 29 10:04:56 2010 -0400
+
+    usb: u132-hcd.c: fix shadows sparse warning
+    
+    Signed-off-by: Bill Pemberton 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
+index fbd7adafd61c..11a97d93dff2 100644
+--- a/drivers/usb/host/u132-hcd.c
++++ b/drivers/usb/host/u132-hcd.c
+@@ -1446,7 +1446,7 @@ static void u132_hcd_endp_work_scheduler(struct work_struct *work)
+ 			return;
+ 		} else {
+ 			int retval;
+-			u8 address = u132->addr[endp->usb_addr].address;
++			address = u132->addr[endp->usb_addr].address;
+ 			struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
+ 				endp->queue_next];
+ 			endp->active = 1;
+@@ -3120,8 +3120,8 @@ static int __devinit u132_probe(struct platform_device *pdev)
+ 		ftdi_elan_gone_away(pdev);
+ 		return -ENOMEM;
+ 	} else {
+-		int retval = 0;
+ 		struct u132 *u132 = hcd_to_u132(hcd);
++		retval = 0;
+ 		hcd->rsrc_start = 0;
+ 		mutex_lock(&u132_module_lock);
+ 		list_add_tail(&u132->u132_list, &u132_static_list);

\ No newline at end of file diff --git a/detail/31.html b/detail/31.html new file mode 100644 index 0000000..d05cb99 --- /dev/null +++ b/detail/31.html @@ -0,0 +1,7598 @@ +

Patches contributed by Indiana University


commit 335ea564509045796dc07faa7333162a0b03f214
+Author: Joshua Walgenbach 
+Date:   Wed Oct 21 21:52:46 2015 -0400
+
+    staging: lustre: add in NID range management for libcfs
+    
+    This is a partial backport of the NID range management
+    added in for nodemap. We only backport the libcfs related
+    parts here.
+    
+    Signed-off-by: Joshua Walgenbach 
+    Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3527
+    Reviewed-on: http://review.whamcloud.com/8057
+    Reviewed-by: Andreas Dilger 
+    Reviewed-by: Andrew Perepechko 
+    Reviewed-by: John L. Hammond 
+    Reviewed-by: Ken Hornstein 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/lustre/include/linux/lnet/nidstr.h b/drivers/staging/lustre/include/linux/lnet/nidstr.h
+index 15363664eb86..4e7c9a5f9a9b 100644
+--- a/drivers/staging/lustre/include/linux/lnet/nidstr.h
++++ b/drivers/staging/lustre/include/linux/lnet/nidstr.h
+@@ -89,6 +89,9 @@ struct netstrfns {
+ 	int	(*nf_print_addrlist)(char *buffer, int count,
+ 				     struct list_head *list);
+ 	int	(*nf_match_addr)(__u32 addr, struct list_head *list);
++	bool	(*nf_is_contiguous)(struct list_head *nidlist);
++	void	(*nf_min_max)(struct list_head *nidlist, __u32 *min_nid,
++			      __u32 *max_nid);
+ };
+ 
+ #endif /* _LNET_NIDSTRINGS_H */
+diff --git a/drivers/staging/lustre/lnet/lnet/nidstrings.c b/drivers/staging/lustre/lnet/lnet/nidstrings.c
+index 1874dfebe33f..4402b80c8bf0 100644
+--- a/drivers/staging/lustre/lnet/lnet/nidstrings.c
++++ b/drivers/staging/lustre/lnet/lnet/nidstrings.c
+@@ -46,6 +46,8 @@
+ /* max value for numeric network address */
+ #define MAX_NUMERIC_VALUE 0xffffffff
+ 
++#define IPSTRING_LENGTH 16
++
+ /* CAVEAT VENDITOR! Keep the canonical string representation of nets/nids
+  * consistent in all conversion functions.  Some code fragments are copied
+  * around for the sake of clarity...
+@@ -456,6 +458,317 @@ int cfs_print_nidlist(char *buffer, int count, struct list_head *nidlist)
+ }
+ EXPORT_SYMBOL(cfs_print_nidlist);
+ 
++/**
++ * Determines minimum and maximum addresses for a single
++ * numeric address range
++ *
++ * \param	ar
++ * \param	min_nid
++ * \param	max_nid
++ */
++static void cfs_ip_ar_min_max(struct addrrange *ar, __u32 *min_nid,
++			      __u32 *max_nid)
++{
++	struct cfs_expr_list *el;
++	struct cfs_range_expr *re;
++	__u32 tmp_ip_addr = 0;
++	unsigned int min_ip[4] = {0};
++	unsigned int max_ip[4] = {0};
++	int re_count = 0;
++
++	list_for_each_entry(el, &ar->ar_numaddr_ranges, el_link) {
++		list_for_each_entry(re, &el->el_exprs, re_link) {
++			min_ip[re_count] = re->re_lo;
++			max_ip[re_count] = re->re_hi;
++			re_count++;
++		}
++	}
++
++	tmp_ip_addr = ((min_ip[0] << 24) | (min_ip[1] << 16) |
++		       (min_ip[2] << 8) | min_ip[3]);
++
++	if (min_nid != NULL)
++		*min_nid = tmp_ip_addr;
++
++	tmp_ip_addr = ((max_ip[0] << 24) | (max_ip[1] << 16) |
++		       (max_ip[2] << 8) | max_ip[3]);
++
++	if (max_nid != NULL)
++		*max_nid = tmp_ip_addr;
++}
++
++/**
++ * Determines minimum and maximum addresses for a single
++ * numeric address range
++ *
++ * \param	ar
++ * \param	min_nid
++ * \param	max_nid
++ */
++static void cfs_num_ar_min_max(struct addrrange *ar, __u32 *min_nid,
++			       __u32 *max_nid)
++{
++	struct cfs_expr_list *el;
++	struct cfs_range_expr *re;
++	unsigned int min_addr = 0;
++	unsigned int max_addr = 0;
++
++	list_for_each_entry(el, &ar->ar_numaddr_ranges, el_link) {
++		list_for_each_entry(re, &el->el_exprs, re_link) {
++			if (re->re_lo < min_addr || min_addr == 0)
++				min_addr = re->re_lo;
++			if (re->re_hi > max_addr)
++				max_addr = re->re_hi;
++		}
++	}
++
++	if (min_nid != NULL)
++		*min_nid = min_addr;
++	if (max_nid != NULL)
++		*max_nid = max_addr;
++}
++
++/**
++ * Determines whether an expression list in an nidrange contains exactly
++ * one contiguous address range. Calls the correct netstrfns for the LND
++ *
++ * \param	*nidlist
++ *
++ * \retval	true if contiguous
++ * \retval	false if not contiguous
++ */
++bool cfs_nidrange_is_contiguous(struct list_head *nidlist)
++{
++	struct nidrange *nr;
++	struct netstrfns *nf = NULL;
++	char *lndname = NULL;
++	int netnum = -1;
++
++	list_for_each_entry(nr, nidlist, nr_link) {
++		nf = nr->nr_netstrfns;
++		if (lndname == NULL)
++			lndname = nf->nf_name;
++		if (netnum == -1)
++			netnum = nr->nr_netnum;
++
++		if (strcmp(lndname, nf->nf_name) != 0 ||
++		    netnum != nr->nr_netnum)
++			return false;
++	}
++
++	if (nf == NULL)
++		return false;
++
++	if (!nf->nf_is_contiguous(nidlist))
++		return false;
++
++	return true;
++}
++EXPORT_SYMBOL(cfs_nidrange_is_contiguous);
++
++/**
++ * Determines whether an expression list in an num nidrange contains exactly
++ * one contiguous address range.
++ *
++ * \param	*nidlist
++ *
++ * \retval	true if contiguous
++ * \retval	false if not contiguous
++ */
++static bool cfs_num_is_contiguous(struct list_head *nidlist)
++{
++	struct nidrange *nr;
++	struct addrrange *ar;
++	struct cfs_expr_list *el;
++	struct cfs_range_expr *re;
++	int last_hi = 0;
++	__u32 last_end_nid = 0;
++	__u32 current_start_nid = 0;
++	__u32 current_end_nid = 0;
++
++	list_for_each_entry(nr, nidlist, nr_link) {
++		list_for_each_entry(ar, &nr->nr_addrranges, ar_link) {
++			cfs_num_ar_min_max(ar, ¤t_start_nid,
++					   ¤t_end_nid);
++			if (last_end_nid != 0 &&
++			    (current_start_nid - last_end_nid != 1))
++				return false;
++			last_end_nid = current_end_nid;
++			list_for_each_entry(el, &ar->ar_numaddr_ranges,
++					    el_link) {
++				list_for_each_entry(re, &el->el_exprs,
++						    re_link) {
++					if (re->re_stride > 1)
++						return false;
++					else if (last_hi != 0 &&
++						 re->re_hi - last_hi != 1)
++						return false;
++					last_hi = re->re_hi;
++				}
++			}
++		}
++	}
++
++	return true;
++}
++
++/**
++ * Determines whether an expression list in an ip nidrange contains exactly
++ * one contiguous address range.
++ *
++ * \param	*nidlist
++ *
++ * \retval	true if contiguous
++ * \retval	false if not contiguous
++ */
++static bool cfs_ip_is_contiguous(struct list_head *nidlist)
++{
++	struct nidrange *nr;
++	struct addrrange *ar;
++	struct cfs_expr_list *el;
++	struct cfs_range_expr *re;
++	int expr_count;
++	int last_hi = 255;
++	int last_diff = 0;
++	__u32 last_end_nid = 0;
++	__u32 current_start_nid = 0;
++	__u32 current_end_nid = 0;
++
++	list_for_each_entry(nr, nidlist, nr_link) {
++		list_for_each_entry(ar, &nr->nr_addrranges, ar_link) {
++			last_hi = 255;
++			last_diff = 0;
++			cfs_ip_ar_min_max(ar, ¤t_start_nid,
++					  ¤t_end_nid);
++			if (last_end_nid != 0 &&
++			    (current_start_nid - last_end_nid != 1))
++				return false;
++			last_end_nid = current_end_nid;
++			list_for_each_entry(el, &ar->ar_numaddr_ranges,
++					    el_link) {
++				expr_count = 0;
++				list_for_each_entry(re, &el->el_exprs,
++						    re_link) {
++					expr_count++;
++					if (re->re_stride > 1 ||
++					    (last_diff > 0 && last_hi != 255) ||
++					    (last_diff > 0 && last_hi == 255 &&
++					     re->re_lo > 0))
++						return false;
++					last_hi = re->re_hi;
++					last_diff = re->re_hi - re->re_lo;
++				}
++			}
++		}
++	}
++
++	return true;
++}
++
++/**
++ * Takes a linked list of nidrange expressions, determines the minimum
++ * and maximum nid and creates appropriate nid structures
++ *
++ * \param	*nidlist
++ * \param	*min_nid
++ * \param	*max_nid
++ */
++void cfs_nidrange_find_min_max(struct list_head *nidlist, char *min_nid,
++			       char *max_nid, size_t nidstr_length)
++{
++	struct nidrange *nr;
++	struct netstrfns *nf = NULL;
++	int netnum = -1;
++	__u32 min_addr;
++	__u32 max_addr;
++	char *lndname = NULL;
++	char min_addr_str[IPSTRING_LENGTH];
++	char max_addr_str[IPSTRING_LENGTH];
++
++	list_for_each_entry(nr, nidlist, nr_link) {
++		nf = nr->nr_netstrfns;
++		lndname = nf->nf_name;
++		if (netnum == -1)
++			netnum = nr->nr_netnum;
++
++		nf->nf_min_max(nidlist, &min_addr, &max_addr);
++	}
++	nf->nf_addr2str(min_addr, min_addr_str);
++	nf->nf_addr2str(max_addr, max_addr_str);
++
++	snprintf(min_nid, nidstr_length, "%s@%s%d", min_addr_str, lndname,
++		 netnum);
++	snprintf(max_nid, nidstr_length, "%s@%s%d", max_addr_str, lndname,
++		 netnum);
++}
++EXPORT_SYMBOL(cfs_nidrange_find_min_max);
++
++/**
++ * Determines the min and max NID values for num LNDs
++ *
++ * \param	*nidlist
++ * \param	*min_nid
++ * \param	*max_nid
++ */
++static void cfs_num_min_max(struct list_head *nidlist, __u32 *min_nid,
++			    __u32 *max_nid)
++{
++	struct nidrange	*nr;
++	struct addrrange *ar;
++	unsigned int tmp_min_addr = 0;
++	unsigned int tmp_max_addr = 0;
++	unsigned int min_addr = 0;
++	unsigned int max_addr = 0;
++
++	list_for_each_entry(nr, nidlist, nr_link) {
++		list_for_each_entry(ar, &nr->nr_addrranges, ar_link) {
++			cfs_num_ar_min_max(ar, &tmp_min_addr,
++					   &tmp_max_addr);
++			if (tmp_min_addr < min_addr || min_addr == 0)
++				min_addr = tmp_min_addr;
++			if (tmp_max_addr > max_addr)
++				max_addr = tmp_min_addr;
++		}
++	}
++	*max_nid = max_addr;
++	*min_nid = min_addr;
++}
++
++/**
++ * Takes an nidlist and determines the minimum and maximum
++ * ip addresses.
++ *
++ * \param	*nidlist
++ * \param	*min_nid
++ * \param	*max_nid
++ */
++static void cfs_ip_min_max(struct list_head *nidlist, __u32 *min_nid,
++			   __u32 *max_nid)
++{
++	struct nidrange *nr;
++	struct addrrange *ar;
++	__u32 tmp_min_ip_addr = 0;
++	__u32 tmp_max_ip_addr = 0;
++	__u32 min_ip_addr = 0;
++	__u32 max_ip_addr = 0;
++
++	list_for_each_entry(nr, nidlist, nr_link) {
++		list_for_each_entry(ar, &nr->nr_addrranges, ar_link) {
++			cfs_ip_ar_min_max(ar, &tmp_min_ip_addr,
++					  &tmp_max_ip_addr);
++			if (tmp_min_ip_addr < min_ip_addr || min_ip_addr == 0)
++				min_ip_addr = tmp_min_ip_addr;
++			if (tmp_max_ip_addr > max_ip_addr)
++				max_ip_addr = tmp_max_ip_addr;
++		}
++	}
++
++	if (min_nid != NULL)
++		*min_nid = min_ip_addr;
++	if (max_nid != NULL)
++		*max_nid = max_ip_addr;
++}
++
+ static int
+ libcfs_lo_str2addr(const char *str, int nob, __u32 *addr)
+ {
+@@ -665,7 +978,9 @@ static struct netstrfns  libcfs_netstrfns[] = {
+ 	 /* .nf_str2addr  */  libcfs_lo_str2addr,
+ 	 /* .nf_parse_addr*/  libcfs_num_parse,
+ 	 /* .nf_print_addrlist*/  libcfs_num_addr_range_print,
+-	 /* .nf_match_addr*/  libcfs_num_match},
++	 /* .nf_match_addr*/  libcfs_num_match,
++	 /* .nf_is_contiguous */  cfs_num_is_contiguous,
++	 /* .nf_min_max   */      cfs_num_min_max},
+ 	{/* .nf_type      */  SOCKLND,
+ 	 /* .nf_name      */  "tcp",
+ 	 /* .nf_modname   */  "ksocklnd",
+@@ -673,7 +988,9 @@ static struct netstrfns  libcfs_netstrfns[] = {
+ 	 /* .nf_str2addr  */  libcfs_ip_str2addr,
+ 	 /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
+ 	 /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
+-	 /* .nf_match_addr*/  cfs_ip_addr_match},
++	 /* .nf_match_addr*/  cfs_ip_addr_match,
++	 /* .nf_is_contiguous */  cfs_ip_is_contiguous,
++         /* .nf_min_max   */      cfs_ip_min_max},
+ 	{/* .nf_type      */  O2IBLND,
+ 	 /* .nf_name      */  "o2ib",
+ 	 /* .nf_modname   */  "ko2iblnd",
+@@ -681,7 +998,9 @@ static struct netstrfns  libcfs_netstrfns[] = {
+ 	 /* .nf_str2addr  */  libcfs_ip_str2addr,
+ 	 /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
+ 	 /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
+-	 /* .nf_match_addr*/  cfs_ip_addr_match},
++	 /* .nf_match_addr*/  cfs_ip_addr_match,
++	 /* .nf_is_contiguous */  cfs_ip_is_contiguous,
++         /* .nf_min_max   */      cfs_ip_min_max},
+ 	{/* .nf_type      */  CIBLND,
+ 	 /* .nf_name      */  "cib",
+ 	 /* .nf_modname   */  "kciblnd",
+@@ -689,7 +1008,9 @@ static struct netstrfns  libcfs_netstrfns[] = {
+ 	 /* .nf_str2addr  */  libcfs_ip_str2addr,
+ 	 /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
+ 	 /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
+-	 /* .nf_match_addr*/  cfs_ip_addr_match},
++	 /* .nf_match_addr*/  cfs_ip_addr_match,
++	 /* .nf_is_contiguous */  cfs_ip_is_contiguous,
++         /* .nf_min_max   */      cfs_ip_min_max},
+ 	{/* .nf_type      */  OPENIBLND,
+ 	 /* .nf_name      */  "openib",
+ 	 /* .nf_modname   */  "kopeniblnd",
+@@ -697,7 +1018,9 @@ static struct netstrfns  libcfs_netstrfns[] = {
+ 	 /* .nf_str2addr  */  libcfs_ip_str2addr,
+ 	 /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
+ 	 /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
+-	 /* .nf_match_addr*/  cfs_ip_addr_match},
++	 /* .nf_match_addr*/  cfs_ip_addr_match,
++	 /* .nf_is_contiguous */  cfs_ip_is_contiguous,
++         /* .nf_min_max   */      cfs_ip_min_max},
+ 	{/* .nf_type      */  IIBLND,
+ 	 /* .nf_name      */  "iib",
+ 	 /* .nf_modname   */  "kiiblnd",
+@@ -705,7 +1028,9 @@ static struct netstrfns  libcfs_netstrfns[] = {
+ 	 /* .nf_str2addr  */  libcfs_ip_str2addr,
+ 	 /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
+ 	 /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
+-	 /* .nf_match_addr*/  cfs_ip_addr_match},
++	 /* .nf_match_addr*/  cfs_ip_addr_match,
++	 /* .nf_is_contiguous */  cfs_ip_is_contiguous,
++         /* .nf_min_max   */      cfs_ip_min_max},
+ 	{/* .nf_type      */  VIBLND,
+ 	 /* .nf_name      */  "vib",
+ 	 /* .nf_modname   */  "kviblnd",
+@@ -713,7 +1038,9 @@ static struct netstrfns  libcfs_netstrfns[] = {
+ 	 /* .nf_str2addr  */  libcfs_ip_str2addr,
+ 	 /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
+ 	 /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
+-	 /* .nf_match_addr*/  cfs_ip_addr_match},
++	 /* .nf_match_addr*/  cfs_ip_addr_match,
++	 /* .nf_is_contiguous */  cfs_ip_is_contiguous,
++         /* .nf_min_max   */      cfs_ip_min_max},
+ 	{/* .nf_type      */  RALND,
+ 	 /* .nf_name      */  "ra",
+ 	 /* .nf_modname   */  "kralnd",
+@@ -721,7 +1048,9 @@ static struct netstrfns  libcfs_netstrfns[] = {
+ 	 /* .nf_str2addr  */  libcfs_ip_str2addr,
+ 	 /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
+ 	 /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
+-	 /* .nf_match_addr*/  cfs_ip_addr_match},
++	 /* .nf_match_addr*/  cfs_ip_addr_match,
++	 /* .nf_is_contiguous */  cfs_ip_is_contiguous,
++         /* .nf_min_max   */      cfs_ip_min_max},
+ 	{/* .nf_type      */  QSWLND,
+ 	 /* .nf_name      */  "elan",
+ 	 /* .nf_modname   */  "kqswlnd",
+@@ -729,7 +1058,9 @@ static struct netstrfns  libcfs_netstrfns[] = {
+ 	 /* .nf_str2addr  */  libcfs_num_str2addr,
+ 	 /* .nf_parse_addrlist*/  libcfs_num_parse,
+ 	 /* .nf_print_addrlist*/  libcfs_num_addr_range_print,
+-	 /* .nf_match_addr*/  libcfs_num_match},
++	 /* .nf_match_addr*/  libcfs_num_match,
++	 /* .nf_is_contiguous */  cfs_num_is_contiguous,
++	 /* .nf_min_max   */      cfs_num_min_max},
+ 	{/* .nf_type      */  GMLND,
+ 	 /* .nf_name      */  "gm",
+ 	 /* .nf_modname   */  "kgmlnd",
+@@ -737,7 +1068,9 @@ static struct netstrfns  libcfs_netstrfns[] = {
+ 	 /* .nf_str2addr  */  libcfs_num_str2addr,
+ 	 /* .nf_parse_addrlist*/  libcfs_num_parse,
+ 	 /* .nf_print_addrlist*/  libcfs_num_addr_range_print,
+-	 /* .nf_match_addr*/  libcfs_num_match},
++	 /* .nf_match_addr*/  libcfs_num_match,
++	 /* .nf_is_contiguous */  cfs_num_is_contiguous,
++	 /* .nf_min_max   */      cfs_num_min_max},
+ 	{/* .nf_type      */  MXLND,
+ 	 /* .nf_name      */  "mx",
+ 	 /* .nf_modname   */  "kmxlnd",
+@@ -745,7 +1078,9 @@ static struct netstrfns  libcfs_netstrfns[] = {
+ 	 /* .nf_str2addr  */  libcfs_ip_str2addr,
+ 	 /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
+ 	 /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
+-	 /* .nf_match_addr*/  cfs_ip_addr_match},
++	 /* .nf_match_addr*/  cfs_ip_addr_match,
++	 /* .nf_is_contiguous */  cfs_ip_is_contiguous,
++         /* .nf_min_max   */      cfs_ip_min_max},
+ 	{/* .nf_type      */  PTLLND,
+ 	 /* .nf_name      */  "ptl",
+ 	 /* .nf_modname   */  "kptllnd",
+@@ -753,7 +1088,9 @@ static struct netstrfns  libcfs_netstrfns[] = {
+ 	 /* .nf_str2addr  */  libcfs_num_str2addr,
+ 	 /* .nf_parse_addrlist*/  libcfs_num_parse,
+ 	 /* .nf_print_addrlist*/  libcfs_num_addr_range_print,
+-	 /* .nf_match_addr*/  libcfs_num_match},
++	 /* .nf_match_addr*/  libcfs_num_match,
++	 /* .nf_is_contiguous */  cfs_num_is_contiguous,
++	 /* .nf_min_max   */      cfs_num_min_max},
+ 	{/* .nf_type      */  GNILND,
+ 	 /* .nf_name      */  "gni",
+ 	 /* .nf_modname   */  "kgnilnd",
+@@ -761,7 +1098,9 @@ static struct netstrfns  libcfs_netstrfns[] = {
+ 	 /* .nf_str2addr  */  libcfs_num_str2addr,
+ 	 /* .nf_parse_addrlist*/  libcfs_num_parse,
+ 	 /* .nf_print_addrlist*/  libcfs_num_addr_range_print,
+-	 /* .nf_match_addr*/  libcfs_num_match},
++	 /* .nf_match_addr*/  libcfs_num_match,
++	 /* .nf_is_contiguous */  cfs_num_is_contiguous,
++	 /* .nf_min_max   */      cfs_num_min_max},
+ 	/* placeholder for net0 alias.  It MUST BE THE LAST ENTRY */
+ 	{/* .nf_type      */  -1},
+ };

commit d0bfef31f4d40888683e801dfd3f7448078d7e2b
+Author: Chris Hanna 
+Date:   Wed Jun 3 10:28:26 2015 -0400
+
+    staging: lustre: ptlrpc: clean up whitespace and align function params
+    
+    Minor changes to remove excessive whitespace and improve
+    readability of ptlrpc functions.
+    
+    Signed-off-by: Chris Hanna 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c
+index 347110e6e822..35ebe0f35bd1 100644
+--- a/drivers/staging/lustre/lustre/ptlrpc/client.c
++++ b/drivers/staging/lustre/lustre/ptlrpc/client.c
+@@ -57,8 +57,8 @@ void ptlrpc_init_client(int req_portal, int rep_portal, char *name,
+ 			struct ptlrpc_client *cl)
+ {
+ 	cl->cli_request_portal = req_portal;
+-	cl->cli_reply_portal   = rep_portal;
+-	cl->cli_name	   = name;
++	cl->cli_reply_portal = rep_portal;
++	cl->cli_name = name;
+ }
+ EXPORT_SYMBOL(ptlrpc_init_client);
+ 
+@@ -68,9 +68,9 @@ EXPORT_SYMBOL(ptlrpc_init_client);
+ struct ptlrpc_connection *ptlrpc_uuid_to_connection(struct obd_uuid *uuid)
+ {
+ 	struct ptlrpc_connection *c;
+-	lnet_nid_t		self;
+-	lnet_process_id_t	 peer;
+-	int		       err;
++	lnet_nid_t self;
++	lnet_process_id_t peer;
++	int err;
+ 
+ 	/* ptlrpc_uuid_to_peer() initializes its 2nd parameter
+ 	 * before accessing its values. */
+@@ -148,7 +148,7 @@ struct ptlrpc_bulk_desc *ptlrpc_prep_bulk_imp(struct ptlrpc_request *req,
+ 	desc->bd_import = class_import_get(imp);
+ 	desc->bd_req = req;
+ 
+-	desc->bd_cbid.cbid_fn  = client_bulk_callback;
++	desc->bd_cbid.cbid_fn = client_bulk_callback;
+ 	desc->bd_cbid.cbid_arg = desc;
+ 
+ 	/* This makes req own desc, and free it when she frees herself */
+@@ -343,8 +343,8 @@ static int unpack_reply(struct ptlrpc_request *req)
+ static int ptlrpc_at_recv_early_reply(struct ptlrpc_request *req)
+ {
+ 	struct ptlrpc_request *early_req;
+-	time_t		 olddl;
+-	int		    rc;
++	time_t olddl;
++	int rc;
+ 
+ 	req->rq_early = 0;
+ 	spin_unlock(&req->rq_lock);
+@@ -580,8 +580,8 @@ static int __ptlrpc_request_bufs_pack(struct ptlrpc_request *request,
+ 				      int count, __u32 *lengths, char **bufs,
+ 				      struct ptlrpc_cli_ctx *ctx)
+ {
+-	struct obd_import  *imp = request->rq_import;
+-	int		 rc;
++	struct obd_import *imp = request->rq_import;
++	int rc;
+ 
+ 	if (unlikely(ctx))
+ 		request->rq_cli_ctx = sptlrpc_cli_ctx_get(ctx);
+@@ -605,10 +605,10 @@ static int __ptlrpc_request_bufs_pack(struct ptlrpc_request *request,
+ 	request->rq_type = PTL_RPC_MSG_REQUEST;
+ 	request->rq_export = NULL;
+ 
+-	request->rq_req_cbid.cbid_fn  = request_out_callback;
++	request->rq_req_cbid.cbid_fn = request_out_callback;
+ 	request->rq_req_cbid.cbid_arg = request;
+ 
+-	request->rq_reply_cbid.cbid_fn  = reply_in_callback;
++	request->rq_reply_cbid.cbid_fn = reply_in_callback;
+ 	request->rq_reply_cbid.cbid_arg = request;
+ 
+ 	request->rq_reply_deadline = 0;
+@@ -761,8 +761,8 @@ EXPORT_SYMBOL(ptlrpc_request_alloc);
+  * initialize its buffer structure according to capsule template \a format.
+  */
+ struct ptlrpc_request *ptlrpc_request_alloc_pool(struct obd_import *imp,
+-					    struct ptlrpc_request_pool *pool,
+-					    const struct req_format *format)
++						 struct ptlrpc_request_pool *pool,
++						 const struct req_format *format)
+ {
+ 	return ptlrpc_request_alloc_internal(imp, pool, format);
+ }
+@@ -789,11 +789,11 @@ EXPORT_SYMBOL(ptlrpc_request_free);
+  * Returns allocated request or NULL on error.
+  */
+ struct ptlrpc_request *ptlrpc_request_alloc_pack(struct obd_import *imp,
+-						const struct req_format *format,
+-						__u32 version, int opcode)
++						 const struct req_format *format,
++						 __u32 version, int opcode)
+ {
+ 	struct ptlrpc_request *req = ptlrpc_request_alloc(imp, format);
+-	int		    rc;
++	int rc;
+ 
+ 	if (req) {
+ 		rc = ptlrpc_request_pack(req, version, opcode);
+@@ -820,7 +820,7 @@ ptlrpc_prep_req_pool(struct obd_import *imp,
+ 		     struct ptlrpc_request_pool *pool)
+ {
+ 	struct ptlrpc_request *request;
+-	int		    rc;
++	int rc;
+ 
+ 	request = __ptlrpc_request_alloc(imp, pool);
+ 	if (!request)
+@@ -868,9 +868,9 @@ struct ptlrpc_request_set *ptlrpc_prep_set(void)
+ 	INIT_LIST_HEAD(&set->set_new_requests);
+ 	INIT_LIST_HEAD(&set->set_cblist);
+ 	set->set_max_inflight = UINT_MAX;
+-	set->set_producer     = NULL;
++	set->set_producer = NULL;
+ 	set->set_producer_arg = NULL;
+-	set->set_rc	   = 0;
++	set->set_rc = 0;
+ 
+ 	return set;
+ }
+@@ -894,9 +894,9 @@ struct ptlrpc_request_set *ptlrpc_prep_fcset(int max, set_producer_func func,
+ 	if (!set)
+ 		return NULL;
+ 
+-	set->set_max_inflight  = max;
+-	set->set_producer      = func;
+-	set->set_producer_arg  = arg;
++	set->set_max_inflight = max;
++	set->set_producer = func;
++	set->set_producer_arg = arg;
+ 
+ 	return set;
+ }
+@@ -912,10 +912,10 @@ EXPORT_SYMBOL(ptlrpc_prep_fcset);
+  */
+ void ptlrpc_set_destroy(struct ptlrpc_request_set *set)
+ {
+-	struct list_head       *tmp;
+-	struct list_head       *next;
+-	int	       expected_phase;
+-	int	       n = 0;
++	struct list_head *tmp;
++	struct list_head *next;
++	int expected_phase;
++	int n = 0;
+ 
+ 	/* Requests on the set should either all be completed, or all be new */
+ 	expected_phase = (atomic_read(&set->set_remaining) == 0) ?
+@@ -1013,7 +1013,7 @@ EXPORT_SYMBOL(ptlrpc_set_add_req);
+  * Currently only used for ptlrpcd.
+  */
+ void ptlrpc_set_add_new_req(struct ptlrpcd_ctl *pc,
+-			   struct ptlrpc_request *req)
++			    struct ptlrpc_request *req)
+ {
+ 	struct ptlrpc_request_set *set = pc->pc_set;
+ 	int count, i;
+@@ -1400,7 +1400,7 @@ static int after_reply(struct ptlrpc_request *req)
+  */
+ static int ptlrpc_send_new_req(struct ptlrpc_request *req)
+ {
+-	struct obd_import     *imp = req->rq_import;
++	struct obd_import *imp = req->rq_import;
+ 	int rc;
+ 
+ 	LASSERT(req->rq_phase == RQ_PHASE_NEW);
+@@ -1669,7 +1669,7 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set)
+ 					continue;
+ 				}
+ 
+-				if (status != 0)  {
++				if (status != 0) {
+ 					req->rq_status = status;
+ 					ptlrpc_rqphase_move(req,
+ 						RQ_PHASE_INTERPRET);
+@@ -1969,8 +1969,8 @@ int ptlrpc_expire_one_request(struct ptlrpc_request *req, int async_unlink)
+ int ptlrpc_expired_set(void *data)
+ {
+ 	struct ptlrpc_request_set *set = data;
+-	struct list_head		*tmp;
+-	time_t		     now = get_seconds();
++	struct list_head *tmp;
++	time_t now = get_seconds();
+ 
+ 	LASSERT(set != NULL);
+ 
+@@ -2052,11 +2052,11 @@ EXPORT_SYMBOL(ptlrpc_interrupted_set);
+  */
+ int ptlrpc_set_next_timeout(struct ptlrpc_request_set *set)
+ {
+-	struct list_head	    *tmp;
+-	time_t		 now = get_seconds();
+-	int		    timeout = 0;
++	struct list_head *tmp;
++	time_t now = get_seconds();
++	int timeout = 0;
+ 	struct ptlrpc_request *req;
+-	int		    deadline;
++	int deadline;
+ 
+ 	list_for_each(tmp, &set->set_requests) {
+ 		req = list_entry(tmp, struct ptlrpc_request, rq_set_chain);
+@@ -2105,10 +2105,10 @@ EXPORT_SYMBOL(ptlrpc_set_next_timeout);
+  */
+ int ptlrpc_set_wait(struct ptlrpc_request_set *set)
+ {
+-	struct list_head	    *tmp;
++	struct list_head *tmp;
+ 	struct ptlrpc_request *req;
+-	struct l_wait_info     lwi;
+-	int		    rc, timeout;
++	struct l_wait_info lwi;
++	int rc, timeout;
+ 
+ 	if (set->set_producer)
+ 		(void)ptlrpc_set_producer(set);
+@@ -2353,8 +2353,8 @@ EXPORT_SYMBOL(ptlrpc_req_xid);
+  */
+ int ptlrpc_unregister_reply(struct ptlrpc_request *request, int async)
+ {
+-	int		rc;
+-	wait_queue_head_t       *wq;
++	int rc;
++	wait_queue_head_t *wq;
+ 	struct l_wait_info lwi;
+ 
+ 	/*
+@@ -2471,7 +2471,7 @@ void ptlrpc_free_committed(struct obd_import *imp)
+ {
+ 	struct ptlrpc_request *req, *saved;
+ 	struct ptlrpc_request *last_req = NULL; /* temporary fire escape */
+-	bool		       skip_committed_list = true;
++	bool skip_committed_list = true;
+ 
+ 	LASSERT(imp != NULL);
+ 	assert_spin_locked(&imp->imp_lock);
+@@ -3023,8 +3023,8 @@ EXPORT_SYMBOL(ptlrpc_sample_next_xid);
+  *    have delay before it really runs by ptlrpcd thread.
+  */
+ struct ptlrpc_work_async_args {
+-	int   (*cb)(const struct lu_env *, void *);
+-	void   *cbdata;
++	int (*cb)(const struct lu_env *, void *);
++	void *cbdata;
+ };
+ 
+ static void ptlrpcd_add_work_req(struct ptlrpc_request *req)
+@@ -3113,7 +3113,7 @@ void *ptlrpcd_alloc_work(struct obd_import *imp,
+ 
+ 	CLASSERT(sizeof(*args) <= sizeof(req->rq_async_args));
+ 	args = ptlrpc_req_async_args(req);
+-	args->cb     = cb;
++	args->cb = cb;
+ 	args->cbdata = cbdata;
+ 
+ 	return req;
+diff --git a/drivers/staging/lustre/lustre/ptlrpc/events.c b/drivers/staging/lustre/lustre/ptlrpc/events.c
+index 7f8644e01112..8cb1929fd31d 100644
+--- a/drivers/staging/lustre/lustre/ptlrpc/events.c
++++ b/drivers/staging/lustre/lustre/ptlrpc/events.c
+@@ -53,7 +53,7 @@ lnet_handle_eq_t   ptlrpc_eq_h;
+  */
+ void request_out_callback(lnet_event_t *ev)
+ {
+-	struct ptlrpc_cb_id   *cbid = ev->md.user_ptr;
++	struct ptlrpc_cb_id *cbid = ev->md.user_ptr;
+ 	struct ptlrpc_request *req = cbid->cbid_arg;
+ 
+ 	LASSERT(ev->type == LNET_EVENT_SEND ||
+@@ -86,7 +86,7 @@ void request_out_callback(lnet_event_t *ev)
+  */
+ void reply_in_callback(lnet_event_t *ev)
+ {
+-	struct ptlrpc_cb_id   *cbid = ev->md.user_ptr;
++	struct ptlrpc_cb_id *cbid = ev->md.user_ptr;
+ 	struct ptlrpc_request *req = cbid->cbid_arg;
+ 
+ 	DEBUG_REQ(D_NET, req, "type %d, status %d", ev->type, ev->status);
+@@ -172,9 +172,9 @@ void reply_in_callback(lnet_event_t *ev)
+  */
+ void client_bulk_callback(lnet_event_t *ev)
+ {
+-	struct ptlrpc_cb_id     *cbid = ev->md.user_ptr;
++	struct ptlrpc_cb_id *cbid = ev->md.user_ptr;
+ 	struct ptlrpc_bulk_desc *desc = cbid->cbid_arg;
+-	struct ptlrpc_request   *req;
++	struct ptlrpc_request *req;
+ 
+ 	LASSERT((desc->bd_type == BULK_PUT_SINK &&
+ 		 ev->type == LNET_EVENT_PUT) ||
+@@ -245,9 +245,9 @@ void client_bulk_callback(lnet_event_t *ev)
+ static void ptlrpc_req_add_history(struct ptlrpc_service_part *svcpt,
+ 				   struct ptlrpc_request *req)
+ {
+-	__u64	sec = req->rq_arrival_time.tv_sec;
+-	__u32	usec = req->rq_arrival_time.tv_usec >> 4; /* usec / 16 */
+-	__u64	new_seq;
++	__u64 sec = req->rq_arrival_time.tv_sec;
++	__u32 usec = req->rq_arrival_time.tv_usec >> 4; /* usec / 16 */
++	__u64 new_seq;
+ 
+ 	/* set sequence ID for request and add it to history list,
+ 	 * it must be called with hold svcpt::scp_lock */
+@@ -281,11 +281,11 @@ static void ptlrpc_req_add_history(struct ptlrpc_service_part *svcpt,
+  */
+ void request_in_callback(lnet_event_t *ev)
+ {
+-	struct ptlrpc_cb_id		  *cbid = ev->md.user_ptr;
++	struct ptlrpc_cb_id *cbid = ev->md.user_ptr;
+ 	struct ptlrpc_request_buffer_desc *rqbd = cbid->cbid_arg;
+-	struct ptlrpc_service_part	  *svcpt = rqbd->rqbd_svcpt;
+-	struct ptlrpc_service	     *service = svcpt->scp_service;
+-	struct ptlrpc_request	     *req;
++	struct ptlrpc_service_part *svcpt = rqbd->rqbd_svcpt;
++	struct ptlrpc_service *service = svcpt->scp_service;
++	struct ptlrpc_request *req;
+ 
+ 	LASSERT(ev->type == LNET_EVENT_PUT ||
+ 		ev->type == LNET_EVENT_UNLINK);
+@@ -380,7 +380,7 @@ void request_in_callback(lnet_event_t *ev)
+  */
+ void reply_out_callback(lnet_event_t *ev)
+ {
+-	struct ptlrpc_cb_id	  *cbid = ev->md.user_ptr;
++	struct ptlrpc_cb_id *cbid = ev->md.user_ptr;
+ 	struct ptlrpc_reply_state *rs = cbid->cbid_arg;
+ 	struct ptlrpc_service_part *svcpt = rs->rs_svcpt;
+ 
+@@ -433,17 +433,17 @@ static void ptlrpc_master_callback(lnet_event_t *ev)
+ }
+ 
+ int ptlrpc_uuid_to_peer(struct obd_uuid *uuid,
+-			 lnet_process_id_t *peer, lnet_nid_t *self)
++			lnet_process_id_t *peer, lnet_nid_t *self)
+ {
+-	int	       best_dist = 0;
+-	__u32	     best_order = 0;
+-	int	       count = 0;
+-	int	       rc = -ENOENT;
+-	int	       portals_compatibility;
+-	int	       dist;
+-	__u32	     order;
+-	lnet_nid_t	dst_nid;
+-	lnet_nid_t	src_nid;
++	int best_dist = 0;
++	__u32 best_order = 0;
++	int count = 0;
++	int rc = -ENOENT;
++	int portals_compatibility;
++	int dist;
++	__u32 order;
++	lnet_nid_t dst_nid;
++	lnet_nid_t src_nid;
+ 
+ 	portals_compatibility = LNetCtl(IOC_LIBCFS_PORTALS_COMPATIBILITY, NULL);
+ 
+@@ -487,10 +487,10 @@ int ptlrpc_uuid_to_peer(struct obd_uuid *uuid,
+ 
+ void ptlrpc_ni_fini(void)
+ {
+-	wait_queue_head_t	 waitq;
+-	struct l_wait_info  lwi;
+-	int		 rc;
+-	int		 retries;
++	wait_queue_head_t waitq;
++	struct l_wait_info lwi;
++	int rc;
++	int retries;
+ 
+ 	/* Wait for the event queue to become idle since there may still be
+ 	 * messages in flight with pending events (i.e. the fire-and-forget
+@@ -523,7 +523,7 @@ void ptlrpc_ni_fini(void)
+ 
+ lnet_pid_t ptl_get_pid(void)
+ {
+-	lnet_pid_t	pid;
++	lnet_pid_t pid;
+ 
+ 	pid = LUSTRE_SRV_LNET_PID;
+ 	return pid;
+@@ -531,8 +531,8 @@ lnet_pid_t ptl_get_pid(void)
+ 
+ int ptlrpc_ni_init(void)
+ {
+-	int	      rc;
+-	lnet_pid_t       pid;
++	int rc;
++	lnet_pid_t pid;
+ 
+ 	pid = ptl_get_pid();
+ 	CDEBUG(D_NET, "My pid is: %x\n", pid);
+@@ -563,7 +563,7 @@ int ptlrpc_ni_init(void)
+ 
+ int ptlrpc_init_portals(void)
+ {
+-	int   rc = ptlrpc_ni_init();
++	int rc = ptlrpc_ni_init();
+ 
+ 	if (rc != 0) {
+ 		CERROR("network initialisation failed\n");
+diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c
+index d5fc689c008b..c9b8481dd384 100644
+--- a/drivers/staging/lustre/lustre/ptlrpc/import.c
++++ b/drivers/staging/lustre/lustre/ptlrpc/import.c
+@@ -119,7 +119,7 @@ int ptlrpc_init_import(struct obd_import *imp)
+ 	spin_lock(&imp->imp_lock);
+ 
+ 	imp->imp_generation++;
+-	imp->imp_state =  LUSTRE_IMP_NEW;
++	imp->imp_state = LUSTRE_IMP_NEW;
+ 
+ 	spin_unlock(&imp->imp_lock);
+ 
+@@ -369,7 +369,7 @@ void ptlrpc_invalidate_import(struct obd_import *imp)
+ 						   imp_unregistering));
+ 			}
+ 			spin_unlock(&imp->imp_lock);
+-		  }
++		}
+ 	} while (rc != 0);
+ 
+ 	/*
+@@ -559,7 +559,7 @@ static int import_select_connection(struct obd_import *imp)
+ 		ptlrpc_connection_put(imp->imp_connection);
+ 	imp->imp_connection = ptlrpc_connection_addref(imp_conn->oic_conn);
+ 
+-	dlmexp =  class_conn2export(&imp->imp_dlm_handle);
++	dlmexp = class_conn2export(&imp->imp_dlm_handle);
+ 	LASSERT(dlmexp != NULL);
+ 	if (dlmexp->exp_connection)
+ 		ptlrpc_connection_put(dlmexp->exp_connection);
+@@ -1490,7 +1490,7 @@ int ptlrpc_disconnect_import(struct obd_import *imp, int noclose)
+ 					INITIAL_CONNECT_TIMEOUT);
+ 
+ 		IMPORT_SET_STATE(imp, LUSTRE_IMP_CONNECTING);
+-		req->rq_send_state =  LUSTRE_IMP_CONNECTING;
++		req->rq_send_state = LUSTRE_IMP_CONNECTING;
+ 		ptlrpc_request_set_replen(req);
+ 		rc = ptlrpc_queue_wait(req);
+ 		ptlrpc_req_finished(req);
+diff --git a/drivers/staging/lustre/lustre/ptlrpc/layout.c b/drivers/staging/lustre/lustre/ptlrpc/layout.c
+index a42335e26de9..d14c20008850 100644
+--- a/drivers/staging/lustre/lustre/ptlrpc/layout.c
++++ b/drivers/staging/lustre/lustre/ptlrpc/layout.c
+@@ -807,11 +807,11 @@ struct req_capsule;
+ /*
+  * Request fields.
+  */
+-#define DEFINE_MSGF(name, flags, size, swabber, dumper) {       \
+-	.rmf_name    = (name),				  \
+-	.rmf_flags   = (flags),				 \
+-	.rmf_size    = (size),				  \
+-	.rmf_swabber = (void (*)(void *))(swabber),	      \
++#define DEFINE_MSGF(name, flags, size, swabber, dumper) {	\
++	.rmf_name    = (name),					\
++	.rmf_flags   = (flags),					\
++	.rmf_size    = (size),					\
++	.rmf_swabber = (void (*)(void *))(swabber),		\
+ 	.rmf_dumper  = (void (*)(void *))(dumper)		\
+ }
+ 
+@@ -1164,25 +1164,25 @@ EXPORT_SYMBOL(RMF_SWAP_LAYOUTS);
+ 
+ struct req_format {
+ 	const char *rf_name;
+-	int	 rf_idx;
++	int rf_idx;
+ 	struct {
+-		int			  nr;
++		int nr;
+ 		const struct req_msg_field **d;
+ 	} rf_fields[RCL_NR];
+ };
+ 
+-#define DEFINE_REQ_FMT(name, client, client_nr, server, server_nr) {    \
+-	.rf_name   = name,					      \
+-	.rf_fields = {						  \
++#define DEFINE_REQ_FMT(name, client, client_nr, server, server_nr) {	\
++	.rf_name = name,						\
++	.rf_fields = {							\
+ 		[RCL_CLIENT] = {					\
+ 			.nr = client_nr,				\
+-			.d  = client				    \
+-		},						      \
++			.d = client					\
++		},							\
+ 		[RCL_SERVER] = {					\
+ 			.nr = server_nr,				\
+-			.d  = server				    \
+-		}						       \
+-	}							       \
++			.d = server					\
++		}							\
++	}								\
+ }
+ 
+ #define DEFINE_REQ_FMT0(name, client, server)				  \
+@@ -1769,10 +1769,10 @@ EXPORT_SYMBOL(req_capsule_set);
+  * field of a \a pill's \a rc_fmt's RMF's.
+  */
+ int req_capsule_filled_sizes(struct req_capsule *pill,
+-			   enum req_location loc)
++			     enum req_location loc)
+ {
+ 	const struct req_format *fmt = pill->rc_fmt;
+-	int		      i;
++	int i;
+ 
+ 	LASSERT(fmt != NULL);
+ 
+@@ -1806,8 +1806,8 @@ EXPORT_SYMBOL(req_capsule_filled_sizes);
+ int req_capsule_server_pack(struct req_capsule *pill)
+ {
+ 	const struct req_format *fmt;
+-	int		      count;
+-	int		      rc;
++	int count;
++	int rc;
+ 
+ 	LASSERT(pill->rc_loc == RCL_SERVER);
+ 	fmt = pill->rc_fmt;
+@@ -1857,11 +1857,11 @@ swabber_dumper_helper(struct req_capsule *pill,
+ 		      int offset,
+ 		      void *value, int len, int dump, void (*swabber)(void *))
+ {
+-	void    *p;
+-	int     i;
+-	int     n;
+-	int     do_swab;
+-	int     inout = loc == RCL_CLIENT;
++	void *p;
++	int i;
++	int n;
++	int do_swab;
++	int inout = loc == RCL_CLIENT;
+ 
+ 	swabber = swabber ?: field->rmf_swabber;
+ 
+@@ -1936,10 +1936,10 @@ static void *__req_capsule_get(struct req_capsule *pill,
+ 			       int dump)
+ {
+ 	const struct req_format *fmt;
+-	struct lustre_msg       *msg;
+-	void		    *value;
+-	int		      len;
+-	int		      offset;
++	struct lustre_msg *msg;
++	void *value;
++	int len;
++	int offset;
+ 
+ 	void *(*getter)(struct lustre_msg *m, int n, int minlen);
+ 
+@@ -2000,10 +2000,10 @@ static void *__req_capsule_get(struct req_capsule *pill,
+  */
+ static void __req_capsule_dump(struct req_capsule *pill, enum req_location loc)
+ {
+-	const struct    req_format *fmt;
+-	const struct    req_msg_field *field;
+-	int	     len;
+-	int	     i;
++	const struct req_format *fmt;
++	const struct req_msg_field *field;
++	int len;
++	int i;
+ 
+ 	fmt = pill->rc_fmt;
+ 
+@@ -2350,9 +2350,9 @@ void req_capsule_shrink(struct req_capsule *pill,
+ 			enum req_location loc)
+ {
+ 	const struct req_format *fmt;
+-	struct lustre_msg       *msg;
+-	int		      len;
+-	int		      offset;
++	struct lustre_msg *msg;
++	int len;
++	int offset;
+ 
+ 	fmt = pill->rc_fmt;
+ 	LASSERT(fmt != NULL);
+diff --git a/drivers/staging/lustre/lustre/ptlrpc/llog_client.c b/drivers/staging/lustre/lustre/ptlrpc/llog_client.c
+index e9baf5bbee3a..1c701e0a0bc7 100644
+--- a/drivers/staging/lustre/lustre/ptlrpc/llog_client.c
++++ b/drivers/staging/lustre/lustre/ptlrpc/llog_client.c
+@@ -49,29 +49,29 @@
+ #include "../include/lustre_net.h"
+ #include 
+ 
+-#define LLOG_CLIENT_ENTRY(ctxt, imp) do {			     \
+-	mutex_lock(&ctxt->loc_mutex);			     \
+-	if (ctxt->loc_imp) {					  \
+-		imp = class_import_get(ctxt->loc_imp);		\
+-	} else {						      \
+-		CERROR("ctxt->loc_imp == NULL for context idx %d."    \
+-		       "Unable to complete MDS/OSS recovery,"	 \
+-		       "but I'll try again next time.  Not fatal.\n", \
+-		       ctxt->loc_idx);				\
+-		imp = NULL;					   \
+-		mutex_unlock(&ctxt->loc_mutex);		   \
+-		return (-EINVAL);				     \
+-	}							     \
+-	mutex_unlock(&ctxt->loc_mutex);			   \
++#define LLOG_CLIENT_ENTRY(ctxt, imp) do {				\
++	mutex_lock(&ctxt->loc_mutex);					\
++	if (ctxt->loc_imp) {						\
++		imp = class_import_get(ctxt->loc_imp);			\
++	} else {							\
++		CERROR("ctxt->loc_imp == NULL for context idx %d."	\
++		       "Unable to complete MDS/OSS recovery,"		\
++		       "but I'll try again next time.  Not fatal.\n",	\
++		       ctxt->loc_idx);					\
++		imp = NULL;						\
++		mutex_unlock(&ctxt->loc_mutex);				\
++		return (-EINVAL);					\
++	}								\
++	mutex_unlock(&ctxt->loc_mutex);					\
+ } while (0)
+ 
+-#define LLOG_CLIENT_EXIT(ctxt, imp) do {			      \
+-	mutex_lock(&ctxt->loc_mutex);			     \
+-	if (ctxt->loc_imp != imp)				     \
+-		CWARN("loc_imp has changed from %p to %p\n",	  \
+-		       ctxt->loc_imp, imp);			   \
+-	class_import_put(imp);					\
+-	mutex_unlock(&ctxt->loc_mutex);			   \
++#define LLOG_CLIENT_EXIT(ctxt, imp) do {				\
++	mutex_lock(&ctxt->loc_mutex);					\
++	if (ctxt->loc_imp != imp)					\
++		CWARN("loc_imp has changed from %p to %p\n",		\
++		       ctxt->loc_imp, imp);				\
++	class_import_put(imp);						\
++	mutex_unlock(&ctxt->loc_mutex);					\
+ } while (0)
+ 
+ /* This is a callback from the llog_* functions.
+@@ -80,11 +80,11 @@ static int llog_client_open(const struct lu_env *env,
+ 			    struct llog_handle *lgh, struct llog_logid *logid,
+ 			    char *name, enum llog_open_param open_param)
+ {
+-	struct obd_import     *imp;
+-	struct llogd_body     *body;
+-	struct llog_ctxt      *ctxt = lgh->lgh_ctxt;
++	struct obd_import *imp;
++	struct llogd_body *body;
++	struct llog_ctxt *ctxt = lgh->lgh_ctxt;
+ 	struct ptlrpc_request *req = NULL;
+-	int		    rc;
++	int rc;
+ 
+ 	LLOG_CLIENT_ENTRY(ctxt, imp);
+ 
+@@ -145,10 +145,10 @@ static int llog_client_open(const struct lu_env *env,
+ static int llog_client_destroy(const struct lu_env *env,
+ 			       struct llog_handle *loghandle)
+ {
+-	struct obd_import     *imp;
++	struct obd_import *imp;
+ 	struct ptlrpc_request *req = NULL;
+-	struct llogd_body     *body;
+-	int		    rc;
++	struct llogd_body *body;
++	int rc;
+ 
+ 	LLOG_CLIENT_ENTRY(loghandle->lgh_ctxt, imp);
+ 	req = ptlrpc_request_alloc_pack(imp, &RQF_LLOG_ORIGIN_HANDLE_DESTROY,
+@@ -182,11 +182,11 @@ static int llog_client_next_block(const struct lu_env *env,
+ 				  int *cur_idx, int next_idx,
+ 				  __u64 *cur_offset, void *buf, int len)
+ {
+-	struct obd_import     *imp;
++	struct obd_import *imp;
+ 	struct ptlrpc_request *req = NULL;
+-	struct llogd_body     *body;
+-	void		  *ptr;
+-	int		    rc;
++	struct llogd_body *body;
++	void *ptr;
++	int rc;
+ 
+ 	LLOG_CLIENT_ENTRY(loghandle->lgh_ctxt, imp);
+ 	req = ptlrpc_request_alloc_pack(imp, &RQF_LLOG_ORIGIN_HANDLE_NEXT_BLOCK,
+@@ -240,11 +240,11 @@ static int llog_client_prev_block(const struct lu_env *env,
+ 				  struct llog_handle *loghandle,
+ 				  int prev_idx, void *buf, int len)
+ {
+-	struct obd_import     *imp;
++	struct obd_import *imp;
+ 	struct ptlrpc_request *req = NULL;
+-	struct llogd_body     *body;
+-	void		  *ptr;
+-	int		    rc;
++	struct llogd_body *body;
++	void *ptr;
++	int rc;
+ 
+ 	LLOG_CLIENT_ENTRY(loghandle->lgh_ctxt, imp);
+ 	req = ptlrpc_request_alloc_pack(imp, &RQF_LLOG_ORIGIN_HANDLE_PREV_BLOCK,
+@@ -292,12 +292,12 @@ static int llog_client_prev_block(const struct lu_env *env,
+ static int llog_client_read_header(const struct lu_env *env,
+ 				   struct llog_handle *handle)
+ {
+-	struct obd_import     *imp;
++	struct obd_import *imp;
+ 	struct ptlrpc_request *req = NULL;
+-	struct llogd_body     *body;
+-	struct llog_log_hdr   *hdr;
+-	struct llog_rec_hdr   *llh_hdr;
+-	int		    rc;
++	struct llogd_body *body;
++	struct llog_log_hdr *hdr;
++	struct llog_rec_hdr *llh_hdr;
++	int rc;
+ 
+ 	LLOG_CLIENT_ENTRY(handle->lgh_ctxt, imp);
+ 	req = ptlrpc_request_alloc_pack(imp, &RQF_LLOG_ORIGIN_HANDLE_READ_HEADER,
+diff --git a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c
+index 1362160983a9..c04ae50c2c29 100644
+--- a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c
++++ b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c
+@@ -261,8 +261,8 @@ ptlrpc_lprocfs_req_history_len_seq_show(struct seq_file *m, void *v)
+ {
+ 	struct ptlrpc_service *svc = m->private;
+ 	struct ptlrpc_service_part *svcpt;
+-	int	total = 0;
+-	int	i;
++	int total = 0;
++	int i;
+ 
+ 	ptlrpc_service_for_each_part(svcpt, i, svc)
+ 		total += svcpt->scp_hist_nrqbds;
+@@ -277,8 +277,8 @@ ptlrpc_lprocfs_req_history_max_seq_show(struct seq_file *m, void *n)
+ {
+ 	struct ptlrpc_service *svc = m->private;
+ 	struct ptlrpc_service_part *svcpt;
+-	int	total = 0;
+-	int	i;
++	int total = 0;
++	int i;
+ 
+ 	ptlrpc_service_for_each_part(svcpt, i, svc)
+ 		total += svc->srv_hist_nrqbds_cpt_max;
+@@ -289,13 +289,13 @@ ptlrpc_lprocfs_req_history_max_seq_show(struct seq_file *m, void *n)
+ 
+ static ssize_t
+ ptlrpc_lprocfs_req_history_max_seq_write(struct file *file,
+-					const char __user *buffer,
+-					size_t count, loff_t *off)
++					 const char __user *buffer,
++					 size_t count, loff_t *off)
+ {
+ 	struct ptlrpc_service *svc = ((struct seq_file *)file->private_data)->private;
+-	int			    bufpages;
+-	int			    val;
+-	int			    rc;
++	int bufpages;
++	int val;
++	int rc;
+ 
+ 	rc = lprocfs_write_helper(buffer, count, &val);
+ 	if (rc < 0)
+@@ -478,17 +478,17 @@ void nrs_policy_get_info_locked(struct ptlrpc_nrs_policy *policy,
+  */
+ static int ptlrpc_lprocfs_nrs_seq_show(struct seq_file *m, void *n)
+ {
+-	struct ptlrpc_service	       *svc = m->private;
+-	struct ptlrpc_service_part     *svcpt;
+-	struct ptlrpc_nrs	       *nrs;
+-	struct ptlrpc_nrs_policy       *policy;
+-	struct ptlrpc_nrs_pol_info     *infos;
+-	struct ptlrpc_nrs_pol_info	tmp;
+-	unsigned			num_pols;
+-	unsigned			pol_idx = 0;
+-	bool				hp = false;
+-	int				i;
+-	int				rc = 0;
++	struct ptlrpc_service *svc = m->private;
++	struct ptlrpc_service_part *svcpt;
++	struct ptlrpc_nrs *nrs;
++	struct ptlrpc_nrs_policy *policy;
++	struct ptlrpc_nrs_pol_info *infos;
++	struct ptlrpc_nrs_pol_info tmp;
++	unsigned num_pols;
++	unsigned pol_idx = 0;
++	bool hp = false;
++	int i;
++	int rc = 0;
+ 
+ 	/**
+ 	 * Serialize NRS core lprocfs operations with policy registration/
+@@ -638,15 +638,15 @@ static int ptlrpc_lprocfs_nrs_seq_show(struct seq_file *m, void *n)
+  * regular and high-priority (if the service has one) NRS head.
+  */
+ static ssize_t ptlrpc_lprocfs_nrs_seq_write(struct file *file,
+-					const char __user *buffer,
+-					size_t count, loff_t *off)
++					    const char __user *buffer,
++					    size_t count, loff_t *off)
+ {
+ 	struct ptlrpc_service *svc = ((struct seq_file *)file->private_data)->private;
+-	enum ptlrpc_nrs_queue_type	queue = PTLRPC_NRS_QUEUE_BOTH;
+-	char			       *cmd;
+-	char			       *cmd_copy = NULL;
+-	char			       *token;
+-	int				rc = 0;
++	enum ptlrpc_nrs_queue_type queue = PTLRPC_NRS_QUEUE_BOTH;
++	char *cmd;
++	char *cmd_copy = NULL;
++	char *token;
++	int rc = 0;
+ 
+ 	if (count >= LPROCFS_NRS_WR_MAX_CMD)
+ 		return -EINVAL;
+@@ -729,8 +729,8 @@ ptlrpc_lprocfs_svc_req_history_seek(struct ptlrpc_service_part *svcpt,
+ 				    struct ptlrpc_srh_iterator *srhi,
+ 				    __u64 seq)
+ {
+-	struct list_head		*e;
+-	struct ptlrpc_request	*req;
++	struct list_head *e;
++	struct ptlrpc_request *req;
+ 
+ 	if (srhi->srhi_req != NULL &&
+ 	    srhi->srhi_seq > svcpt->scp_hist_seq_culled &&
+@@ -860,12 +860,12 @@ static void *
+ ptlrpc_lprocfs_svc_req_history_next(struct seq_file *s,
+ 				    void *iter, loff_t *pos)
+ {
+-	struct ptlrpc_service		*svc = s->private;
+-	struct ptlrpc_srh_iterator	*srhi = iter;
+-	struct ptlrpc_service_part	*svcpt;
+-	__u64				seq;
+-	int				rc;
+-	int				i;
++	struct ptlrpc_service *svc = s->private;
++	struct ptlrpc_srh_iterator *srhi = iter;
++	struct ptlrpc_service_part *svcpt;
++	__u64 seq;
++	int rc;
++	int i;
+ 
+ 	for (i = srhi->srhi_idx; i < svc->srv_ncpts; i++) {
+ 		svcpt = svc->srv_parts[i];
+@@ -923,11 +923,11 @@ EXPORT_SYMBOL(target_print_req);
+ 
+ static int ptlrpc_lprocfs_svc_req_history_show(struct seq_file *s, void *iter)
+ {
+-	struct ptlrpc_service		*svc = s->private;
+-	struct ptlrpc_srh_iterator	*srhi = iter;
+-	struct ptlrpc_service_part	*svcpt;
+-	struct ptlrpc_request		*req;
+-	int				rc;
++	struct ptlrpc_service *svc = s->private;
++	struct ptlrpc_srh_iterator *srhi = iter;
++	struct ptlrpc_service_part *svcpt;
++	struct ptlrpc_request *req;
++	int rc;
+ 
+ 	LASSERT(srhi->srhi_idx < svc->srv_ncpts);
+ 
+@@ -972,8 +972,8 @@ ptlrpc_lprocfs_svc_req_history_open(struct inode *inode, struct file *file)
+ 		.next  = ptlrpc_lprocfs_svc_req_history_next,
+ 		.show  = ptlrpc_lprocfs_svc_req_history_show,
+ 	};
+-	struct seq_file       *seqf;
+-	int		    rc;
++	struct seq_file *seqf;
++	int rc;
+ 
+ 	rc = seq_open(file, &sops);
+ 	if (rc)
+@@ -987,13 +987,13 @@ ptlrpc_lprocfs_svc_req_history_open(struct inode *inode, struct file *file)
+ /* See also lprocfs_rd_timeouts */
+ static int ptlrpc_lprocfs_timeouts_seq_show(struct seq_file *m, void *n)
+ {
+-	struct ptlrpc_service		*svc = m->private;
+-	struct ptlrpc_service_part	*svcpt;
+-	struct dhms			ts;
+-	time_t				worstt;
+-	unsigned int			cur;
+-	unsigned int			worst;
+-	int				i;
++	struct ptlrpc_service *svc = m->private;
++	struct ptlrpc_service_part *svcpt;
++	struct dhms ts;
++	time_t worstt;
++	unsigned int cur;
++	unsigned int worst;
++	int i;
+ 
+ 	if (AT_OFF) {
+ 		seq_printf(m, "adaptive timeouts off, using obd_timeout %u\n",
+@@ -1215,8 +1215,8 @@ int lprocfs_wr_evict_client(struct file *file, const char __user *buffer,
+ 			    size_t count, loff_t *off)
+ {
+ 	struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
+-	char	      *kbuf;
+-	char	      *tmpbuf;
++	char *kbuf;
++	char *tmpbuf;
+ 
+ 	kbuf = kzalloc(BUFLEN, GFP_NOFS);
+ 	if (kbuf == NULL)
+@@ -1264,7 +1264,7 @@ int lprocfs_wr_ping(struct file *file, const char __user *buffer,
+ {
+ 	struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
+ 	struct ptlrpc_request *req;
+-	int		    rc;
++	int rc;
+ 
+ 	LPROCFS_CLIMP_CHECK(obd);
+ 	req = ptlrpc_prep_ping(obd->u.cli.cl_import);
+diff --git a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c
+index 2fa2585584a3..92c746b44462 100644
+--- a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c
++++ b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c
+@@ -52,17 +52,17 @@ static int ptl_send_buf(lnet_handle_md_t *mdh, void *base, int len,
+ 			struct ptlrpc_connection *conn, int portal, __u64 xid,
+ 			unsigned int offset)
+ {
+-	int	      rc;
+-	lnet_md_t	 md;
++	int rc;
++	lnet_md_t md;
+ 
+ 	LASSERT(portal != 0);
+ 	LASSERT(conn != NULL);
+ 	CDEBUG(D_INFO, "conn=%p id %s\n", conn, libcfs_id2str(conn->c_peer));
+-	md.start     = base;
+-	md.length    = len;
++	md.start = base;
++	md.length = len;
+ 	md.threshold = (ack == LNET_ACK_REQ) ? 2 : 1;
+-	md.options   = PTLRPC_MD_OPTIONS;
+-	md.user_ptr  = cbid;
++	md.options = PTLRPC_MD_OPTIONS;
++	md.user_ptr = cbid;
+ 	md.eq_handle = ptlrpc_eq_h;
+ 
+ 	if (unlikely(ack == LNET_ACK_REQ &&
+@@ -120,8 +120,8 @@ int ptlrpc_register_bulk(struct ptlrpc_request *req)
+ 	int posted_md;
+ 	int total_md;
+ 	__u64 xid;
+-	lnet_handle_me_t  me_h;
+-	lnet_md_t	 md;
++	lnet_handle_me_t me_h;
++	lnet_md_t md;
+ 
+ 	if (OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_BULK_GET_NET))
+ 		return 0;
+@@ -243,9 +243,9 @@ EXPORT_SYMBOL(ptlrpc_register_bulk);
+ int ptlrpc_unregister_bulk(struct ptlrpc_request *req, int async)
+ {
+ 	struct ptlrpc_bulk_desc *desc = req->rq_bulk;
+-	wait_queue_head_t	     *wq;
+-	struct l_wait_info       lwi;
+-	int		      rc;
++	wait_queue_head_t *wq;
++	struct l_wait_info lwi;
++	int rc;
+ 
+ 	LASSERT(!in_interrupt());     /* might sleep */
+ 
+@@ -301,8 +301,8 @@ EXPORT_SYMBOL(ptlrpc_unregister_bulk);
+ 
+ static void ptlrpc_at_set_reply(struct ptlrpc_request *req, int flags)
+ {
+-	struct ptlrpc_service_part	*svcpt = req->rq_rqbd->rqbd_svcpt;
+-	struct ptlrpc_service		*svc = svcpt->scp_service;
++	struct ptlrpc_service_part *svcpt = req->rq_rqbd->rqbd_svcpt;
++	struct ptlrpc_service *svc = svcpt->scp_service;
+ 	int service_time = max_t(int, get_seconds() -
+ 				 req->rq_arrival_time.tv_sec, 1);
+ 
+@@ -353,8 +353,8 @@ static void ptlrpc_at_set_reply(struct ptlrpc_request *req, int flags)
+ int ptlrpc_send_reply(struct ptlrpc_request *req, int flags)
+ {
+ 	struct ptlrpc_reply_state *rs = req->rq_reply_state;
+-	struct ptlrpc_connection  *conn;
+-	int			rc;
++	struct ptlrpc_connection *conn;
++	int rc;
+ 
+ 	/* We must already have a reply buffer (only ptlrpc_error() may be
+ 	 * called without one). The reply generated by sptlrpc layer (e.g.
+@@ -491,8 +491,8 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply)
+ 	int rc2;
+ 	int mpflag = 0;
+ 	struct ptlrpc_connection *connection;
+-	lnet_handle_me_t  reply_me_h;
+-	lnet_md_t	 reply_md;
++	lnet_handle_me_t reply_me_h;
++	lnet_md_t reply_md;
+ 	struct obd_device *obd = request->rq_import->imp_obd;
+ 
+ 	if (OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_DROP_RPC))
+@@ -594,15 +594,15 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply)
+ 	spin_unlock(&request->rq_lock);
+ 
+ 	if (!noreply) {
+-		reply_md.start     = request->rq_repbuf;
+-		reply_md.length    = request->rq_repbuf_len;
++		reply_md.start = request->rq_repbuf;
++		reply_md.length = request->rq_repbuf_len;
+ 		/* Allow multiple early replies */
+ 		reply_md.threshold = LNET_MD_THRESH_INF;
+ 		/* Manage remote for early replies */
+-		reply_md.options   = PTLRPC_MD_OPTIONS | LNET_MD_OP_PUT |
++		reply_md.options = PTLRPC_MD_OPTIONS | LNET_MD_OP_PUT |
+ 			LNET_MD_MANAGE_REMOTE |
+ 			LNET_MD_TRUNCATE; /* allow to make EOVERFLOW error */;
+-		reply_md.user_ptr  = &request->rq_reply_cbid;
++		reply_md.user_ptr = &request->rq_reply_cbid;
+ 		reply_md.eq_handle = ptlrpc_eq_h;
+ 
+ 		/* We must see the unlink callback to unset rq_reply_unlink,
+@@ -682,11 +682,11 @@ EXPORT_SYMBOL(ptl_send_rpc);
+  */
+ int ptlrpc_register_rqbd(struct ptlrpc_request_buffer_desc *rqbd)
+ {
+-	struct ptlrpc_service	  *service = rqbd->rqbd_svcpt->scp_service;
+-	static lnet_process_id_t  match_id = {LNET_NID_ANY, LNET_PID_ANY};
+-	int			  rc;
+-	lnet_md_t		 md;
+-	lnet_handle_me_t	  me_h;
++	struct ptlrpc_service *service = rqbd->rqbd_svcpt->scp_service;
++	static lnet_process_id_t match_id = {LNET_NID_ANY, LNET_PID_ANY};
++	int rc;
++	lnet_md_t md;
++	lnet_handle_me_t me_h;
+ 
+ 	CDEBUG(D_NET, "LNetMEAttach: portal %d\n",
+ 	       service->srv_req_portal);
+@@ -709,12 +709,12 @@ int ptlrpc_register_rqbd(struct ptlrpc_request_buffer_desc *rqbd)
+ 	LASSERT(rqbd->rqbd_refcount == 0);
+ 	rqbd->rqbd_refcount = 1;
+ 
+-	md.start     = rqbd->rqbd_buffer;
+-	md.length    = service->srv_buf_size;
+-	md.max_size  = service->srv_max_req_size;
++	md.start = rqbd->rqbd_buffer;
++	md.length = service->srv_buf_size;
++	md.max_size = service->srv_max_req_size;
+ 	md.threshold = LNET_MD_THRESH_INF;
+-	md.options   = PTLRPC_MD_OPTIONS | LNET_MD_OP_PUT | LNET_MD_MAX_SIZE;
+-	md.user_ptr  = &rqbd->rqbd_cbid;
++	md.options = PTLRPC_MD_OPTIONS | LNET_MD_OP_PUT | LNET_MD_MAX_SIZE;
++	md.user_ptr = &rqbd->rqbd_cbid;
+ 	md.eq_handle = ptlrpc_eq_h;
+ 
+ 	rc = LNetMDAttach(me_h, md, LNET_UNLINK, &rqbd->rqbd_md_h);
+diff --git a/drivers/staging/lustre/lustre/ptlrpc/nrs.c b/drivers/staging/lustre/lustre/ptlrpc/nrs.c
+index d38a1af8bfd7..9516acadb7a1 100644
+--- a/drivers/staging/lustre/lustre/ptlrpc/nrs.c
++++ b/drivers/staging/lustre/lustre/ptlrpc/nrs.c
+@@ -188,8 +188,8 @@ static void nrs_policy_stop_primary(struct ptlrpc_nrs *nrs)
+  */
+ static int nrs_policy_start_locked(struct ptlrpc_nrs_policy *policy)
+ {
+-	struct ptlrpc_nrs      *nrs = policy->pol_nrs;
+-	int			rc = 0;
++	struct ptlrpc_nrs *nrs = policy->pol_nrs;
++	int rc = 0;
+ 
+ 	/**
+ 	 * Don't allow multiple starting which is too complex, and has no real
+@@ -377,15 +377,15 @@ static void nrs_resource_put(struct ptlrpc_nrs_resource *res)
+  */
+ static
+ struct ptlrpc_nrs_resource *nrs_resource_get(struct ptlrpc_nrs_policy *policy,
+-					      struct ptlrpc_nrs_request *nrq,
+-					      bool moving_req)
++					     struct ptlrpc_nrs_request *nrq,
++					     bool moving_req)
+ {
+ 	/**
+ 	 * Set to NULL to traverse the resource hierarchy from the top.
+ 	 */
+ 	struct ptlrpc_nrs_resource *res = NULL;
+ 	struct ptlrpc_nrs_resource *tmp = NULL;
+-	int			    rc;
++	int rc;
+ 
+ 	while (1) {
+ 		rc = policy->pol_desc->pd_ops->op_res_get(policy, nrq, res,
+@@ -432,8 +432,8 @@ static void nrs_resource_get_safe(struct ptlrpc_nrs *nrs,
+ 				  struct ptlrpc_nrs_resource **resp,
+ 				  bool moving_req)
+ {
+-	struct ptlrpc_nrs_policy   *primary = NULL;
+-	struct ptlrpc_nrs_policy   *fallback = NULL;
++	struct ptlrpc_nrs_policy *primary = NULL;
++	struct ptlrpc_nrs_policy *fallback = NULL;
+ 
+ 	memset(resp, 0, sizeof(resp[0]) * NRS_RES_MAX);
+ 
+@@ -484,8 +484,8 @@ static void nrs_resource_get_safe(struct ptlrpc_nrs *nrs,
+ static void nrs_resource_put_safe(struct ptlrpc_nrs_resource **resp)
+ {
+ 	struct ptlrpc_nrs_policy *pols[NRS_RES_MAX];
+-	struct ptlrpc_nrs	 *nrs = NULL;
+-	int			  i;
++	struct ptlrpc_nrs *nrs = NULL;
++	int i;
+ 
+ 	for (i = 0; i < NRS_RES_MAX; i++) {
+ 		if (resp[i] != NULL) {
+@@ -530,7 +530,7 @@ static void nrs_resource_put_safe(struct ptlrpc_nrs_resource **resp)
+  */
+ static inline
+ struct ptlrpc_nrs_request *nrs_request_get(struct ptlrpc_nrs_policy *policy,
+-					    bool peek, bool force)
++					   bool peek, bool force)
+ {
+ 	struct ptlrpc_nrs_request *nrq;
+ 
+@@ -556,8 +556,8 @@ struct ptlrpc_nrs_request *nrs_request_get(struct ptlrpc_nrs_policy *policy,
+ static inline void nrs_request_enqueue(struct ptlrpc_nrs_request *nrq)
+ {
+ 	struct ptlrpc_nrs_policy *policy;
+-	int			  rc;
+-	int			  i;
++	int rc;
++	int i;
+ 
+ 	/**
+ 	 * Try in descending order, because the primary policy (if any) is
+@@ -628,8 +628,8 @@ static inline void nrs_request_stop(struct ptlrpc_nrs_request *nrq)
+ static int nrs_policy_ctl(struct ptlrpc_nrs *nrs, char *name,
+ 			  enum ptlrpc_nrs_ctl opc, void *arg)
+ {
+-	struct ptlrpc_nrs_policy       *policy;
+-	int				rc = 0;
++	struct ptlrpc_nrs_policy *policy;
++	int rc = 0;
+ 
+ 	spin_lock(&nrs->nrs_lock);
+ 
+@@ -733,10 +733,10 @@ static int nrs_policy_unregister(struct ptlrpc_nrs *nrs, char *name)
+ static int nrs_policy_register(struct ptlrpc_nrs *nrs,
+ 			       struct ptlrpc_nrs_pol_desc *desc)
+ {
+-	struct ptlrpc_nrs_policy       *policy;
+-	struct ptlrpc_nrs_policy       *tmp;
+-	struct ptlrpc_service_part     *svcpt = nrs->nrs_svcpt;
+-	int				rc;
++	struct ptlrpc_nrs_policy *policy;
++	struct ptlrpc_nrs_policy *tmp;
++	struct ptlrpc_service_part *svcpt = nrs->nrs_svcpt;
++	int rc;
+ 
+ 	LASSERT(svcpt != NULL);
+ 	LASSERT(desc->pd_ops != NULL);
+@@ -752,10 +752,10 @@ static int nrs_policy_register(struct ptlrpc_nrs *nrs,
+ 	if (policy == NULL)
+ 		return -ENOMEM;
+ 
+-	policy->pol_nrs     = nrs;
+-	policy->pol_desc    = desc;
+-	policy->pol_state   = NRS_POL_STATE_STOPPED;
+-	policy->pol_flags   = desc->pd_flags;
++	policy->pol_nrs = nrs;
++	policy->pol_desc = desc;
++	policy->pol_state = NRS_POL_STATE_STOPPED;
++	policy->pol_flags = desc->pd_flags;
+ 
+ 	INIT_LIST_HEAD(&policy->pol_list);
+ 	INIT_LIST_HEAD(&policy->pol_list_queued);
+@@ -804,7 +804,7 @@ static int nrs_policy_register(struct ptlrpc_nrs *nrs,
+  */
+ static void ptlrpc_nrs_req_add_nolock(struct ptlrpc_request *req)
+ {
+-	struct ptlrpc_nrs_policy       *policy;
++	struct ptlrpc_nrs_policy *policy;
+ 
+ 	LASSERT(req->rq_nrq.nr_initialized);
+ 	LASSERT(!req->rq_nrq.nr_enqueued);
+@@ -829,7 +829,7 @@ static void ptlrpc_nrs_req_add_nolock(struct ptlrpc_request *req)
+  */
+ static void ptlrpc_nrs_hpreq_add_nolock(struct ptlrpc_request *req)
+ {
+-	int	opc = lustre_msg_get_opc(req->rq_reqmsg);
++	int opc = lustre_msg_get_opc(req->rq_reqmsg);
+ 
+ 	spin_lock(&req->rq_lock);
+ 	req->rq_hp = 1;
+@@ -872,9 +872,9 @@ static int nrs_register_policies_locked(struct ptlrpc_nrs *nrs)
+ {
+ 	struct ptlrpc_nrs_pol_desc *desc;
+ 	/* for convenience */
+-	struct ptlrpc_service_part	 *svcpt = nrs->nrs_svcpt;
+-	struct ptlrpc_service		 *svc = svcpt->scp_service;
+-	int				  rc = -EINVAL;
++	struct ptlrpc_service_part *svcpt = nrs->nrs_svcpt;
++	struct ptlrpc_service *svc = svcpt->scp_service;
++	int rc = -EINVAL;
+ 
+ 	LASSERT(mutex_is_locked(&nrs_core.nrs_mutex));
+ 
+@@ -912,7 +912,7 @@ static int nrs_register_policies_locked(struct ptlrpc_nrs *nrs)
+ static int nrs_svcpt_setup_locked0(struct ptlrpc_nrs *nrs,
+ 				   struct ptlrpc_service_part *svcpt)
+ {
+-	enum ptlrpc_nrs_queue_type	queue;
++	enum ptlrpc_nrs_queue_type queue;
+ 
+ 	LASSERT(mutex_is_locked(&nrs_core.nrs_mutex));
+ 
+@@ -943,8 +943,8 @@ static int nrs_svcpt_setup_locked0(struct ptlrpc_nrs *nrs,
+  */
+ static int nrs_svcpt_setup_locked(struct ptlrpc_service_part *svcpt)
+ {
+-	struct ptlrpc_nrs	       *nrs;
+-	int				rc;
++	struct ptlrpc_nrs *nrs;
++	int rc;
+ 
+ 	LASSERT(mutex_is_locked(&nrs_core.nrs_mutex));
+ 
+@@ -988,11 +988,11 @@ static int nrs_svcpt_setup_locked(struct ptlrpc_service_part *svcpt)
+  */
+ static void nrs_svcpt_cleanup_locked(struct ptlrpc_service_part *svcpt)
+ {
+-	struct ptlrpc_nrs	       *nrs;
+-	struct ptlrpc_nrs_policy       *policy;
+-	struct ptlrpc_nrs_policy       *tmp;
+-	int				rc;
+-	bool				hp = false;
++	struct ptlrpc_nrs *nrs;
++	struct ptlrpc_nrs_policy *policy;
++	struct ptlrpc_nrs_policy *tmp;
++	int rc;
++	bool hp = false;
+ 
+ 	LASSERT(mutex_is_locked(&nrs_core.nrs_mutex));
+ 
+@@ -1028,7 +1028,7 @@ static void nrs_svcpt_cleanup_locked(struct ptlrpc_service_part *svcpt)
+  */
+ static struct ptlrpc_nrs_pol_desc *nrs_policy_find_desc_locked(const char *name)
+ {
+-	struct ptlrpc_nrs_pol_desc     *tmp;
++	struct ptlrpc_nrs_pol_desc *tmp;
+ 
+ 	list_for_each_entry(tmp, &nrs_core.nrs_policies, pd_list) {
+ 		if (strncmp(tmp->pd_name, name, NRS_POL_NAME_MAX) == 0)
+@@ -1051,11 +1051,11 @@ static struct ptlrpc_nrs_pol_desc *nrs_policy_find_desc_locked(const char *name)
+  */
+ static int nrs_policy_unregister_locked(struct ptlrpc_nrs_pol_desc *desc)
+ {
+-	struct ptlrpc_nrs	       *nrs;
+-	struct ptlrpc_service	       *svc;
+-	struct ptlrpc_service_part     *svcpt;
+-	int				i;
+-	int				rc = 0;
++	struct ptlrpc_nrs *nrs;
++	struct ptlrpc_service *svc;
++	struct ptlrpc_service_part *svcpt;
++	int i;
++	int rc = 0;
+ 
+ 	LASSERT(mutex_is_locked(&nrs_core.nrs_mutex));
+ 	LASSERT(mutex_is_locked(&ptlrpc_all_services_mutex));
+@@ -1115,9 +1115,9 @@ static int nrs_policy_unregister_locked(struct ptlrpc_nrs_pol_desc *desc)
+  */
+ int ptlrpc_nrs_policy_register(struct ptlrpc_nrs_pol_conf *conf)
+ {
+-	struct ptlrpc_service	       *svc;
+-	struct ptlrpc_nrs_pol_desc     *desc;
+-	int				rc = 0;
++	struct ptlrpc_service *svc;
++	struct ptlrpc_nrs_pol_desc *desc;
++	int rc = 0;
+ 
+ 	LASSERT(conf != NULL);
+ 	LASSERT(conf->nc_ops != NULL);
+@@ -1162,12 +1162,12 @@ int ptlrpc_nrs_policy_register(struct ptlrpc_nrs_pol_conf *conf)
+ 	}
+ 
+ 	strncpy(desc->pd_name, conf->nc_name, NRS_POL_NAME_MAX);
+-	desc->pd_ops		 = conf->nc_ops;
+-	desc->pd_compat		 = conf->nc_compat;
++	desc->pd_ops = conf->nc_ops;
++	desc->pd_compat = conf->nc_compat;
+ 	desc->pd_compat_svc_name = conf->nc_compat_svc_name;
+ 	if ((conf->nc_flags & PTLRPC_NRS_FL_REG_EXTERN) != 0)
+-		desc->pd_owner	 = conf->nc_owner;
+-	desc->pd_flags		 = conf->nc_flags;
++		desc->pd_owner = conf->nc_owner;
++	desc->pd_flags = conf->nc_flags;
+ 	atomic_set(&desc->pd_refs, 0);
+ 
+ 	/**
+@@ -1187,17 +1187,17 @@ int ptlrpc_nrs_policy_register(struct ptlrpc_nrs_pol_conf *conf)
+ 	mutex_lock(&ptlrpc_all_services_mutex);
+ 
+ 	list_for_each_entry(svc, &ptlrpc_all_services, srv_list) {
+-		struct ptlrpc_service_part     *svcpt;
+-		int				i;
+-		int				rc2;
++		struct ptlrpc_service_part *svcpt;
++		int i;
++		int rc2;
+ 
+ 		if (!nrs_policy_compatible(svc, desc) ||
+ 		    unlikely(svc->srv_is_stopping))
+ 			continue;
+ 
+ 		ptlrpc_service_for_each_part(svcpt, i, svc) {
+-			struct ptlrpc_nrs      *nrs;
+-			bool			hp = false;
++			struct ptlrpc_nrs *nrs;
++			bool hp = false;
+ again:
+ 			nrs = nrs_svcpt2nrs(svcpt, hp);
+ 			rc = nrs_policy_register(nrs, desc);
+@@ -1267,8 +1267,8 @@ EXPORT_SYMBOL(ptlrpc_nrs_policy_register);
+  */
+ int ptlrpc_nrs_policy_unregister(struct ptlrpc_nrs_pol_conf *conf)
+ {
+-	struct ptlrpc_nrs_pol_desc	*desc;
+-	int				 rc;
++	struct ptlrpc_nrs_pol_desc *desc;
++	int rc;
+ 
+ 	LASSERT(conf != NULL);
+ 
+@@ -1331,10 +1331,10 @@ EXPORT_SYMBOL(ptlrpc_nrs_policy_unregister);
+  */
+ int ptlrpc_service_nrs_setup(struct ptlrpc_service *svc)
+ {
+-	struct ptlrpc_service_part	       *svcpt;
+-	const struct ptlrpc_nrs_pol_desc       *desc;
+-	int					i;
+-	int					rc = 0;
++	struct ptlrpc_service_part *svcpt;
++	const struct ptlrpc_nrs_pol_desc *desc;
++	int i;
++	int rc = 0;
+ 
+ 	mutex_lock(&nrs_core.nrs_mutex);
+ 
+@@ -1376,9 +1376,9 @@ int ptlrpc_service_nrs_setup(struct ptlrpc_service *svc)
+  */
+ void ptlrpc_service_nrs_cleanup(struct ptlrpc_service *svc)
+ {
+-	struct ptlrpc_service_part	     *svcpt;
+-	const struct ptlrpc_nrs_pol_desc     *desc;
+-	int				      i;
++	struct ptlrpc_service_part *svcpt;
++	const struct ptlrpc_nrs_pol_desc *desc;
++	int i;
+ 
+ 	mutex_lock(&nrs_core.nrs_mutex);
+ 
+@@ -1417,7 +1417,7 @@ void ptlrpc_service_nrs_cleanup(struct ptlrpc_service *svc)
+ void ptlrpc_nrs_req_initialize(struct ptlrpc_service_part *svcpt,
+ 			       struct ptlrpc_request *req, bool hp)
+ {
+-	struct ptlrpc_nrs	*nrs = nrs_svcpt2nrs(svcpt, hp);
++	struct ptlrpc_nrs *nrs = nrs_svcpt2nrs(svcpt, hp);
+ 
+ 	memset(&req->rq_nrq, 0, sizeof(req->rq_nrq));
+ 	nrs_resource_get_safe(nrs, &req->rq_nrq, req->rq_nrq.nr_res_ptrs,
+@@ -1525,8 +1525,8 @@ struct ptlrpc_request *
+ ptlrpc_nrs_req_get_nolock0(struct ptlrpc_service_part *svcpt, bool hp,
+ 			   bool peek, bool force)
+ {
+-	struct ptlrpc_nrs	  *nrs = nrs_svcpt2nrs(svcpt, hp);
+-	struct ptlrpc_nrs_policy  *policy;
++	struct ptlrpc_nrs *nrs = nrs_svcpt2nrs(svcpt, hp);
++	struct ptlrpc_nrs_policy *policy;
+ 	struct ptlrpc_nrs_request *nrq;
+ 
+ 	/**
+@@ -1596,10 +1596,10 @@ bool ptlrpc_nrs_req_pending_nolock(struct ptlrpc_service_part *svcpt, bool hp)
+  */
+ void ptlrpc_nrs_req_hp_move(struct ptlrpc_request *req)
+ {
+-	struct ptlrpc_service_part	*svcpt = req->rq_rqbd->rqbd_svcpt;
+-	struct ptlrpc_nrs_request	*nrq = &req->rq_nrq;
+-	struct ptlrpc_nrs_resource	*res1[NRS_RES_MAX];
+-	struct ptlrpc_nrs_resource	*res2[NRS_RES_MAX];
++	struct ptlrpc_service_part *svcpt = req->rq_rqbd->rqbd_svcpt;
++	struct ptlrpc_nrs_request *nrq = &req->rq_nrq;
++	struct ptlrpc_nrs_resource *res1[NRS_RES_MAX];
++	struct ptlrpc_nrs_resource *res2[NRS_RES_MAX];
+ 
+ 	/**
+ 	 * Obtain the high-priority NRS head resources.
+@@ -1661,9 +1661,9 @@ int ptlrpc_nrs_policy_control(const struct ptlrpc_service *svc,
+ 			      enum ptlrpc_nrs_queue_type queue, char *name,
+ 			      enum ptlrpc_nrs_ctl opc, bool single, void *arg)
+ {
+-	struct ptlrpc_service_part     *svcpt;
+-	int				i;
+-	int				rc = 0;
++	struct ptlrpc_service_part *svcpt;
++	int i;
++	int rc = 0;
+ 
+ 	LASSERT(opc != PTLRPC_NRS_CTL_INVALID);
+ 
+@@ -1711,7 +1711,7 @@ extern struct ptlrpc_nrs_pol_conf nrs_conf_fifo;
+  */
+ int ptlrpc_nrs_init(void)
+ {
+-	int	rc;
++	int rc;
+ 
+ 	mutex_init(&nrs_core.nrs_mutex);
+ 	INIT_LIST_HEAD(&nrs_core.nrs_policies);
+diff --git a/drivers/staging/lustre/lustre/ptlrpc/nrs_fifo.c b/drivers/staging/lustre/lustre/ptlrpc/nrs_fifo.c
+index 6a61c85cfb11..8e21f0cdc8f8 100644
+--- a/drivers/staging/lustre/lustre/ptlrpc/nrs_fifo.c
++++ b/drivers/staging/lustre/lustre/ptlrpc/nrs_fifo.c
+@@ -160,9 +160,9 @@ static int nrs_fifo_res_get(struct ptlrpc_nrs_policy *policy,
+  */
+ static
+ struct ptlrpc_nrs_request *nrs_fifo_req_get(struct ptlrpc_nrs_policy *policy,
+-					     bool peek, bool force)
++					    bool peek, bool force)
+ {
+-	struct nrs_fifo_head	  *head = policy->pol_private;
++	struct nrs_fifo_head *head = policy->pol_private;
+ 	struct ptlrpc_nrs_request *nrq;
+ 
+ 	nrq = unlikely(list_empty(&head->fh_list)) ? NULL :
+diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c
+index b51af9bf37b7..2787bfd67165 100644
+--- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c
++++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c
+@@ -279,8 +279,8 @@ lustre_get_emerg_rs(struct ptlrpc_service_part *svcpt)
+ 
+ 	/* See if we have anything in a pool, and wait if nothing */
+ 	while (list_empty(&svcpt->scp_rep_idle)) {
+-		struct l_wait_info	lwi;
+-		int			rc;
++		struct l_wait_info lwi;
++		int rc;
+ 
+ 		spin_unlock(&svcpt->scp_rep_lock);
+ 		/* If we cannot get anything for some long time, we better
+@@ -321,7 +321,7 @@ int lustre_pack_reply_v2(struct ptlrpc_request *req, int count,
+ 			 __u32 *lens, char **bufs, int flags)
+ {
+ 	struct ptlrpc_reply_state *rs;
+-	int			msg_len, rc;
++	int msg_len, rc;
+ 
+ 	LASSERT(req->rq_reply_state == NULL);
+ 
+@@ -440,8 +440,8 @@ EXPORT_SYMBOL(lustre_msg_buf);
+ int lustre_shrink_msg_v2(struct lustre_msg_v2 *msg, int segment,
+ 			 unsigned int newlen, int move_data)
+ {
+-	char   *tail = NULL, *newpos;
+-	int     tail_len = 0, n;
++	char *tail = NULL, *newpos;
++	int tail_len = 0, n;
+ 
+ 	LASSERT(msg);
+ 	LASSERT(msg->lm_bufcount > segment);
+@@ -1577,8 +1577,8 @@ int do_set_info_async(struct obd_import *imp,
+ 		      struct ptlrpc_request_set *set)
+ {
+ 	struct ptlrpc_request *req;
+-	char		  *tmp;
+-	int		    rc;
++	char *tmp;
++	int rc;
+ 
+ 	req = ptlrpc_request_alloc(imp, &RQF_OBD_SET_INFO);
+ 	if (req == NULL)
+@@ -1688,7 +1688,7 @@ void lustre_swab_connect(struct obd_connect_data *ocd)
+ 	CLASSERT(offsetof(typeof(*ocd), paddingF) != 0);
+ }
+ 
+-void lustre_swab_obdo(struct obdo  *o)
++void lustre_swab_obdo(struct obdo *o)
+ {
+ 	__swab64s(&o->o_valid);
+ 	lustre_swab_ost_id(&o->o_oi);
+@@ -2179,7 +2179,7 @@ EXPORT_SYMBOL(lustre_swab_lov_user_md_objects);
+ 
+ void lustre_swab_ldlm_res_id(struct ldlm_res_id *id)
+ {
+-	int  i;
++	int i;
+ 
+ 	for (i = 0; i < RES_NAME_SIZE; i++)
+ 		__swab64s(&id->name[i]);
+diff --git a/drivers/staging/lustre/lustre/ptlrpc/pinger.c b/drivers/staging/lustre/lustre/ptlrpc/pinger.c
+index 9fc815676eb8..61e33be865b2 100644
+--- a/drivers/staging/lustre/lustre/ptlrpc/pinger.c
++++ b/drivers/staging/lustre/lustre/ptlrpc/pinger.c
+@@ -546,8 +546,8 @@ void ptlrpc_pinger_wake_up(void)
+ #define PET_TERMINATE 2
+ 
+ static int pet_refcount;
+-static int	       pet_state;
+-static wait_queue_head_t       pet_waitq;
++static int pet_state;
++static wait_queue_head_t pet_waitq;
+ static LIST_HEAD(pet_list);
+ static DEFINE_SPINLOCK(pet_lock);
+ 
+diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c
+index 5ba3e6ed5289..e591cff323ec 100644
+--- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c
++++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c
+@@ -68,9 +68,9 @@
+ #include "ptlrpc_internal.h"
+ 
+ struct ptlrpcd {
+-	int		pd_size;
+-	int		pd_index;
+-	int		pd_nthreads;
++	int pd_size;
++	int pd_index;
++	int pd_nthreads;
+ 	struct ptlrpcd_ctl pd_thread_rcv;
+ 	struct ptlrpcd_ctl pd_threads[0];
+ };
+diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec.c b/drivers/staging/lustre/lustre/ptlrpc/sec.c
+index bcfd0b0b6f93..8798fab31f77 100644
+--- a/drivers/staging/lustre/lustre/ptlrpc/sec.c
++++ b/drivers/staging/lustre/lustre/ptlrpc/sec.c
+@@ -113,10 +113,10 @@ static
+ struct ptlrpc_sec_policy *sptlrpc_wireflavor2policy(__u32 flavor)
+ {
+ 	static DEFINE_MUTEX(load_mutex);
+-	static atomic_t       loaded = ATOMIC_INIT(0);
++	static atomic_t loaded = ATOMIC_INIT(0);
+ 	struct ptlrpc_sec_policy *policy;
+-	__u16		     number = SPTLRPC_FLVR_POLICY(flavor);
+-	__u16		     flag = 0;
++	__u16 number = SPTLRPC_FLVR_POLICY(flavor);
++	__u16 flag = 0;
+ 
+ 	if (number >= SPTLRPC_POLICY_MAX)
+ 		return NULL;
+@@ -339,7 +339,7 @@ int sptlrpc_cli_ctx_display(struct ptlrpc_cli_ctx *ctx, char *buf, int bufsize)
+ 
+ static int import_sec_check_expire(struct obd_import *imp)
+ {
+-	int     adapt = 0;
++	int adapt = 0;
+ 
+ 	spin_lock(&imp->imp_lock);
+ 	if (imp->imp_sec_expire &&
+@@ -359,7 +359,7 @@ static int import_sec_check_expire(struct obd_import *imp)
+ static int import_sec_validate_get(struct obd_import *imp,
+ 				   struct ptlrpc_sec **sec)
+ {
+-	int     rc;
++	int rc;
+ 
+ 	if (unlikely(imp->imp_sec_expire)) {
+ 		rc = import_sec_check_expire(imp);
+@@ -447,10 +447,10 @@ int sptlrpc_req_ctx_switch(struct ptlrpc_request *req,
+ 			   struct ptlrpc_cli_ctx *oldctx,
+ 			   struct ptlrpc_cli_ctx *newctx)
+ {
+-	struct sptlrpc_flavor   old_flvr;
+-	char		   *reqmsg = NULL; /* to workaround old gcc */
+-	int		     reqmsg_size;
+-	int		     rc = 0;
++	struct sptlrpc_flavor old_flvr;
++	char *reqmsg = NULL; /* to workaround old gcc */
++	int reqmsg_size;
++	int rc = 0;
+ 
+ 	LASSERT(req->rq_reqmsg);
+ 	LASSERT(req->rq_reqlen);
+@@ -514,7 +514,7 @@ int sptlrpc_req_replace_dead_ctx(struct ptlrpc_request *req)
+ {
+ 	struct ptlrpc_cli_ctx *oldctx = req->rq_cli_ctx;
+ 	struct ptlrpc_cli_ctx *newctx;
+-	int		    rc;
++	int rc;
+ 
+ 	LASSERT(oldctx);
+ 
+@@ -629,10 +629,10 @@ void req_off_ctx_list(struct ptlrpc_request *req, struct ptlrpc_cli_ctx *ctx)
+  */
+ int sptlrpc_req_refresh_ctx(struct ptlrpc_request *req, long timeout)
+ {
+-	struct ptlrpc_cli_ctx  *ctx = req->rq_cli_ctx;
+-	struct ptlrpc_sec      *sec;
+-	struct l_wait_info      lwi;
+-	int		     rc;
++	struct ptlrpc_cli_ctx *ctx = req->rq_cli_ctx;
++	struct ptlrpc_sec *sec;
++	struct l_wait_info lwi;
++	int rc;
+ 
+ 	LASSERT(ctx);
+ 
+@@ -878,7 +878,7 @@ void sptlrpc_request_out_callback(struct ptlrpc_request *req)
+  */
+ int sptlrpc_import_check_ctx(struct obd_import *imp)
+ {
+-	struct ptlrpc_sec     *sec;
++	struct ptlrpc_sec *sec;
+ 	struct ptlrpc_cli_ctx *ctx;
+ 	struct ptlrpc_request *req = NULL;
+ 	int rc;
+@@ -974,7 +974,7 @@ int sptlrpc_cli_wrap_request(struct ptlrpc_request *req)
+ static int do_cli_unwrap_reply(struct ptlrpc_request *req)
+ {
+ 	struct ptlrpc_cli_ctx *ctx = req->rq_cli_ctx;
+-	int		    rc;
++	int rc;
+ 
+ 	LASSERT(ctx);
+ 	LASSERT(ctx->cc_sec);
+@@ -1082,10 +1082,10 @@ int sptlrpc_cli_unwrap_reply(struct ptlrpc_request *req)
+ int sptlrpc_cli_unwrap_early_reply(struct ptlrpc_request *req,
+ 				   struct ptlrpc_request **req_ret)
+ {
+-	struct ptlrpc_request  *early_req;
+-	char		   *early_buf;
+-	int		     early_bufsz, early_size;
+-	int		     rc;
++	struct ptlrpc_request *early_req;
++	char *early_buf;
++	int early_bufsz, early_size;
++	int rc;
+ 
+ 	early_req = ptlrpc_request_cache_alloc(GFP_NOFS);
+ 	if (early_req == NULL)
+@@ -1273,13 +1273,13 @@ EXPORT_SYMBOL(sptlrpc_sec_put);
+  */
+ static
+ struct ptlrpc_sec *sptlrpc_sec_create(struct obd_import *imp,
+-				       struct ptlrpc_svc_ctx *svc_ctx,
+-				       struct sptlrpc_flavor *sf,
+-				       enum lustre_sec_part sp)
++				      struct ptlrpc_svc_ctx *svc_ctx,
++				      struct sptlrpc_flavor *sf,
++				      enum lustre_sec_part sp)
+ {
+ 	struct ptlrpc_sec_policy *policy;
+-	struct ptlrpc_sec	*sec;
+-	char		      str[32];
++	struct ptlrpc_sec *sec;
++	char str[32];
+ 
+ 	if (svc_ctx) {
+ 		LASSERT(imp->imp_dlm_fake == 1);
+@@ -1369,7 +1369,7 @@ static void sptlrpc_import_sec_adapt_inplace(struct obd_import *imp,
+ 					     struct ptlrpc_sec *sec,
+ 					     struct sptlrpc_flavor *sf)
+ {
+-	char    str1[32], str2[32];
++	char str1[32], str2[32];
+ 
+ 	if (sec->ps_flvr.sf_flags != sf->sf_flags)
+ 		CDEBUG(D_SEC, "changing sec flags: %s -> %s\n",
+@@ -1394,12 +1394,12 @@ int sptlrpc_import_sec_adapt(struct obd_import *imp,
+ 			     struct ptlrpc_svc_ctx *svc_ctx,
+ 			     struct sptlrpc_flavor *flvr)
+ {
+-	struct ptlrpc_connection   *conn;
+-	struct sptlrpc_flavor       sf;
+-	struct ptlrpc_sec	  *sec, *newsec;
+-	enum lustre_sec_part	sp;
+-	char			str[24];
+-	int			 rc = 0;
++	struct ptlrpc_connection *conn;
++	struct sptlrpc_flavor sf;
++	struct ptlrpc_sec *sec, *newsec;
++	enum lustre_sec_part sp;
++	char str[24];
++	int rc = 0;
+ 
+ 	might_sleep();
+ 
+@@ -1436,7 +1436,7 @@ int sptlrpc_import_sec_adapt(struct obd_import *imp,
+ 
+ 	sec = sptlrpc_import_sec_ref(imp);
+ 	if (sec) {
+-		char    str2[24];
++		char str2[24];
+ 
+ 		if (flavor_equal(&sf, &sec->ps_flvr))
+ 			goto out;
+@@ -1585,8 +1585,8 @@ void sptlrpc_cli_free_reqbuf(struct ptlrpc_request *req)
+ void _sptlrpc_enlarge_msg_inplace(struct lustre_msg *msg,
+ 				  int segment, int newsize)
+ {
+-	void   *src, *dst;
+-	int     oldsize, oldmsg_size, movesize;
++	void *src, *dst;
++	int oldsize, oldmsg_size, movesize;
+ 
+ 	LASSERT(segment < msg->lm_bufcount);
+ 	LASSERT(msg->lm_buflens[segment] <= newsize);
+@@ -1635,9 +1635,9 @@ EXPORT_SYMBOL(_sptlrpc_enlarge_msg_inplace);
+ int sptlrpc_cli_enlarge_reqbuf(struct ptlrpc_request *req,
+ 			       int segment, int newsize)
+ {
+-	struct ptlrpc_cli_ctx    *ctx = req->rq_cli_ctx;
+-	struct ptlrpc_sec_cops   *cops;
+-	struct lustre_msg	*msg = req->rq_reqmsg;
++	struct ptlrpc_cli_ctx *ctx = req->rq_cli_ctx;
++	struct ptlrpc_sec_cops *cops;
++	struct lustre_msg *msg = req->rq_reqmsg;
+ 
+ 	LASSERT(ctx);
+ 	LASSERT(msg);
+@@ -1748,7 +1748,7 @@ static int flavor_allowed(struct sptlrpc_flavor *exp,
+ int sptlrpc_target_export_check(struct obd_export *exp,
+ 				struct ptlrpc_request *req)
+ {
+-	struct sptlrpc_flavor   flavor;
++	struct sptlrpc_flavor flavor;
+ 
+ 	if (exp == NULL)
+ 		return 0;
+@@ -1926,8 +1926,8 @@ EXPORT_SYMBOL(sptlrpc_target_export_check);
+ void sptlrpc_target_update_exp_flavor(struct obd_device *obd,
+ 				      struct sptlrpc_rule_set *rset)
+ {
+-	struct obd_export       *exp;
+-	struct sptlrpc_flavor    new_flvr;
++	struct obd_export *exp;
++	struct sptlrpc_flavor new_flvr;
+ 
+ 	LASSERT(obd);
+ 
+@@ -2019,8 +2019,8 @@ static int sptlrpc_svc_check_from(struct ptlrpc_request *req, int svc_rc)
+ int sptlrpc_svc_unwrap_request(struct ptlrpc_request *req)
+ {
+ 	struct ptlrpc_sec_policy *policy;
+-	struct lustre_msg	*msg = req->rq_reqbuf;
+-	int		       rc;
++	struct lustre_msg *msg = req->rq_reqbuf;
++	int rc;
+ 
+ 	LASSERT(msg);
+ 	LASSERT(req->rq_reqmsg == NULL);
+@@ -2231,8 +2231,8 @@ int sptlrpc_cli_unwrap_bulk_read(struct ptlrpc_request *req,
+ 				 struct ptlrpc_bulk_desc *desc,
+ 				 int nob)
+ {
+-	struct ptlrpc_cli_ctx  *ctx;
+-	int		     rc;
++	struct ptlrpc_cli_ctx *ctx;
++	int rc;
+ 
+ 	LASSERT(req->rq_bulk_read && !req->rq_bulk_write);
+ 
+@@ -2256,8 +2256,8 @@ EXPORT_SYMBOL(sptlrpc_cli_unwrap_bulk_read);
+ int sptlrpc_cli_unwrap_bulk_write(struct ptlrpc_request *req,
+ 				  struct ptlrpc_bulk_desc *desc)
+ {
+-	struct ptlrpc_cli_ctx  *ctx;
+-	int		     rc;
++	struct ptlrpc_cli_ctx *ctx;
++	int rc;
+ 
+ 	LASSERT(!req->rq_bulk_read && req->rq_bulk_write);
+ 
+@@ -2329,7 +2329,7 @@ EXPORT_SYMBOL(sptlrpc_pack_user_desc);
+ int sptlrpc_unpack_user_desc(struct lustre_msg *msg, int offset, int swabbed)
+ {
+ 	struct ptlrpc_user_desc *pud;
+-	int		      i;
++	int i;
+ 
+ 	pud = lustre_msg_buf(msg, offset, sizeof(*pud));
+ 	if (!pud)
+diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c
+index 97edc9174da3..ea35ca54e729 100644
+--- a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c
++++ b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c
+@@ -62,7 +62,7 @@
+ #define POINTERS_PER_PAGE	(PAGE_CACHE_SIZE / sizeof(void *))
+ #define PAGES_PER_POOL		(POINTERS_PER_PAGE)
+ 
+-#define IDLE_IDX_MAX	    (100)
++#define IDLE_IDX_MAX	 (100)
+ #define IDLE_IDX_WEIGHT	 (3)
+ 
+ #define CACHE_QUIESCENT_PERIOD  (20)
+@@ -173,8 +173,8 @@ int sptlrpc_proc_enc_pool_seq_show(struct seq_file *m, void *v)
+ 
+ static void enc_pools_release_free_pages(long npages)
+ {
+-	int     p_idx, g_idx;
+-	int     p_idx_max1, p_idx_max2;
++	int p_idx, g_idx;
++	int p_idx_max1, p_idx_max2;
+ 
+ 	LASSERT(npages > 0);
+ 	LASSERT(npages <= page_pools.epp_free_pages);
+@@ -284,7 +284,7 @@ int npages_to_npools(unsigned long npages)
+ static unsigned long enc_pools_cleanup(struct page ***pools, int npools)
+ {
+ 	unsigned long cleaned = 0;
+-	int	   i, j;
++	int i, j;
+ 
+ 	for (i = 0; i < npools; i++) {
+ 		if (pools[i]) {
+@@ -311,9 +311,9 @@ static unsigned long enc_pools_cleanup(struct page ***pools, int npools)
+  */
+ static void enc_pools_insert(struct page ***pools, int npools, int npages)
+ {
+-	int     freeslot;
+-	int     op_idx, np_idx, og_idx, ng_idx;
+-	int     cur_npools, end_npools;
++	int freeslot;
++	int op_idx, np_idx, og_idx, ng_idx;
++	int cur_npools, end_npools;
+ 
+ 	LASSERT(npages > 0);
+ 	LASSERT(page_pools.epp_total_pages+npages <= page_pools.epp_max_pages);
+@@ -393,9 +393,9 @@ static void enc_pools_insert(struct page ***pools, int npools, int npages)
+ static int enc_pools_add_pages(int npages)
+ {
+ 	static DEFINE_MUTEX(add_pages_mutex);
+-	struct page   ***pools;
+-	int	     npools, alloced = 0;
+-	int	     i, j, rc = -ENOMEM;
++	struct page ***pools;
++	int npools, alloced = 0;
++	int i, j, rc = -ENOMEM;
+ 
+ 	if (npages < PTLRPC_MAX_BRW_PAGES)
+ 		npages = PTLRPC_MAX_BRW_PAGES;
+@@ -494,12 +494,12 @@ static int enc_pools_should_grow(int page_needed, long now)
+  */
+ int sptlrpc_enc_pool_get_pages(struct ptlrpc_bulk_desc *desc)
+ {
+-	wait_queue_t  waitlink;
+-	unsigned long   this_idle = -1;
+-	unsigned long      tick = 0;
+-	long	    now;
+-	int	     p_idx, g_idx;
+-	int	     i;
++	wait_queue_t waitlink;
++	unsigned long this_idle = -1;
++	unsigned long tick = 0;
++	long now;
++	int p_idx, g_idx;
++	int i;
+ 
+ 	LASSERT(desc->bd_iov_count > 0);
+ 	LASSERT(desc->bd_iov_count <= page_pools.epp_max_pages);
+@@ -609,8 +609,8 @@ EXPORT_SYMBOL(sptlrpc_enc_pool_get_pages);
+ 
+ void sptlrpc_enc_pool_put_pages(struct ptlrpc_bulk_desc *desc)
+ {
+-	int     p_idx, g_idx;
+-	int     i;
++	int p_idx, g_idx;
++	int i;
+ 
+ 	if (desc->bd_enc_iov == NULL)
+ 		return;
+@@ -658,7 +658,7 @@ EXPORT_SYMBOL(sptlrpc_enc_pool_put_pages);
+  */
+ int sptlrpc_enc_pool_add_user(void)
+ {
+-	int     need_grow = 0;
++	int need_grow = 0;
+ 
+ 	spin_lock(&page_pools.epp_lock);
+ 	if (page_pools.epp_growing == 0 && page_pools.epp_total_pages == 0) {
+@@ -842,11 +842,11 @@ EXPORT_SYMBOL(bulk_sec_desc_unpack);
+ int sptlrpc_get_bulk_checksum(struct ptlrpc_bulk_desc *desc, __u8 alg,
+ 			      void *buf, int buflen)
+ {
+-	struct cfs_crypto_hash_desc	*hdesc;
+-	int				hashsize;
+-	char				hashbuf[64];
+-	unsigned int			bufsize;
+-	int				i, err;
++	struct cfs_crypto_hash_desc *hdesc;
++	int hashsize;
++	char hashbuf[64];
++	unsigned int bufsize;
++	int i, err;
+ 
+ 	LASSERT(alg > BULK_HASH_ALG_NULL && alg < BULK_HASH_ALG_MAX);
+ 	LASSERT(buflen >= 4);
+diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_config.c b/drivers/staging/lustre/lustre/ptlrpc/sec_config.c
+index 16dbf3fcfc84..31da43e8b3c6 100644
+--- a/drivers/staging/lustre/lustre/ptlrpc/sec_config.c
++++ b/drivers/staging/lustre/lustre/ptlrpc/sec_config.c
+@@ -94,8 +94,8 @@ EXPORT_SYMBOL(sptlrpc_target_sec_part);
+  */
+ int sptlrpc_parse_flavor(const char *str, struct sptlrpc_flavor *flvr)
+ {
+-	char	    buf[32];
+-	char	   *bulk, *alg;
++	char buf[32];
++	char *bulk, *alg;
+ 
+ 	memset(flvr, 0, sizeof(*flvr));
+ 
+@@ -182,8 +182,8 @@ static void sptlrpc_rule_init(struct sptlrpc_rule *rule)
+  */
+ int sptlrpc_parse_rule(char *param, struct sptlrpc_rule *rule)
+ {
+-	char	   *flavor, *dir;
+-	int	     rc;
++	char *flavor, *dir;
++	int rc;
+ 
+ 	sptlrpc_rule_init(rule);
+ 
+@@ -309,9 +309,9 @@ static inline int rule_match_net(struct sptlrpc_rule *r1,
+ int sptlrpc_rule_set_merge(struct sptlrpc_rule_set *rset,
+ 			   struct sptlrpc_rule *rule)
+ {
+-	struct sptlrpc_rule      *p = rset->srs_rules;
+-	int		       spec_dir, spec_net;
+-	int		       rc, n, match = 0;
++	struct sptlrpc_rule *p = rset->srs_rules;
++	int spec_dir, spec_net;
++	int rc, n, match = 0;
+ 
+ 	might_sleep();
+ 
+@@ -403,8 +403,8 @@ int sptlrpc_rule_set_choose(struct sptlrpc_rule_set *rset,
+ 			    lnet_nid_t nid,
+ 			    struct sptlrpc_flavor *sf)
+ {
+-	struct sptlrpc_rule    *r;
+-	int		     n;
++	struct sptlrpc_rule *r;
++	int n;
+ 
+ 	for (n = 0; n < rset->srs_nrule; n++) {
+ 		r = &rset->srs_rules[n];
+@@ -433,7 +433,7 @@ EXPORT_SYMBOL(sptlrpc_rule_set_choose);
+ void sptlrpc_rule_set_dump(struct sptlrpc_rule_set *rset)
+ {
+ 	struct sptlrpc_rule *r;
+-	int     n;
++	int n;
+ 
+ 	for (n = 0; n < rset->srs_nrule; n++) {
+ 		r = &rset->srs_rules[n];
+@@ -474,8 +474,8 @@ static inline int is_hex(char c)
+ 
+ static void target2fsname(const char *tgt, char *fsname, int buflen)
+ {
+-	const char     *ptr;
+-	int	     len;
++	const char *ptr;
++	int len;
+ 
+ 	ptr = strrchr(tgt, '-');
+ 	if (ptr) {
+@@ -583,8 +583,8 @@ static int sptlrpc_conf_merge_rule(struct sptlrpc_conf *conf,
+ 				   const char *target,
+ 				   struct sptlrpc_rule *rule)
+ {
+-	struct sptlrpc_conf_tgt  *conf_tgt;
+-	struct sptlrpc_rule_set  *rule_set;
++	struct sptlrpc_conf_tgt *conf_tgt;
++	struct sptlrpc_rule_set *rule_set;
+ 
+ 	/* fsname == target means general rules for the whole fs */
+ 	if (strcmp(conf->sc_fsname, target) == 0) {
+@@ -610,10 +610,10 @@ static int sptlrpc_conf_merge_rule(struct sptlrpc_conf *conf,
+ static int __sptlrpc_process_config(struct lustre_cfg *lcfg,
+ 				    struct sptlrpc_conf *conf)
+ {
+-	char		   *target, *param;
+-	char		    fsname[MTI_NAME_MAXLEN];
+-	struct sptlrpc_rule     rule;
+-	int		     rc;
++	char *target, *param;
++	char fsname[MTI_NAME_MAXLEN];
++	struct sptlrpc_rule rule;
++	int rc;
+ 
+ 	target = lustre_cfg_string(lcfg, 1);
+ 	if (target == NULL) {
+@@ -671,8 +671,8 @@ EXPORT_SYMBOL(sptlrpc_process_config);
+ 
+ static int logname2fsname(const char *logname, char *buf, int buflen)
+ {
+-	char   *ptr;
+-	int     len;
++	char *ptr;
++	int len;
+ 
+ 	ptr = strrchr(logname, '-');
+ 	if (ptr == NULL || strcmp(ptr, "-sptlrpc")) {
+@@ -690,7 +690,7 @@ static int logname2fsname(const char *logname, char *buf, int buflen)
+ void sptlrpc_conf_log_update_begin(const char *logname)
+ {
+ 	struct sptlrpc_conf *conf;
+-	char		 fsname[16];
++	char fsname[16];
+ 
+ 	if (logname2fsname(logname, fsname, sizeof(fsname)))
+ 		return;
+@@ -716,7 +716,7 @@ EXPORT_SYMBOL(sptlrpc_conf_log_update_begin);
+ void sptlrpc_conf_log_update_end(const char *logname)
+ {
+ 	struct sptlrpc_conf *conf;
+-	char		 fsname[16];
++	char fsname[16];
+ 
+ 	if (logname2fsname(logname, fsname, sizeof(fsname)))
+ 		return;
+@@ -741,7 +741,7 @@ EXPORT_SYMBOL(sptlrpc_conf_log_update_end);
+ 
+ void sptlrpc_conf_log_start(const char *logname)
+ {
+-	char		 fsname[16];
++	char fsname[16];
+ 
+ 	if (logname2fsname(logname, fsname, sizeof(fsname)))
+ 		return;
+@@ -755,7 +755,7 @@ EXPORT_SYMBOL(sptlrpc_conf_log_start);
+ void sptlrpc_conf_log_stop(const char *logname)
+ {
+ 	struct sptlrpc_conf *conf;
+-	char		 fsname[16];
++	char fsname[16];
+ 
+ 	if (logname2fsname(logname, fsname, sizeof(fsname)))
+ 		return;
+@@ -799,10 +799,10 @@ void sptlrpc_conf_choose_flavor(enum lustre_sec_part from,
+ 				lnet_nid_t nid,
+ 				struct sptlrpc_flavor *sf)
+ {
+-	struct sptlrpc_conf     *conf;
++	struct sptlrpc_conf *conf;
+ 	struct sptlrpc_conf_tgt *conf_tgt;
+-	char		     name[MTI_NAME_MAXLEN];
+-	int		      len, rc = 0;
++	char name[MTI_NAME_MAXLEN];
++	int len, rc = 0;
+ 
+ 	target2fsname(target->uuid, name, sizeof(name));
+ 
+@@ -858,7 +858,7 @@ EXPORT_SYMBOL(sptlrpc_target_choose_flavor);
+  */
+ void sptlrpc_conf_client_adapt(struct obd_device *obd)
+ {
+-	struct obd_import  *imp;
++	struct obd_import *imp;
+ 
+ 	LASSERT(strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) == 0 ||
+ 		strcmp(obd->obd_type->typ_name, LUSTRE_OSC_NAME) == 0);
+@@ -880,7 +880,7 @@ void sptlrpc_conf_client_adapt(struct obd_device *obd)
+ }
+ EXPORT_SYMBOL(sptlrpc_conf_client_adapt);
+ 
+-int  sptlrpc_conf_init(void)
++int sptlrpc_conf_init(void)
+ {
+ 	mutex_init(&sptlrpc_conf_lock);
+ 	return 0;
+@@ -888,7 +888,7 @@ int  sptlrpc_conf_init(void)
+ 
+ void sptlrpc_conf_fini(void)
+ {
+-	struct sptlrpc_conf  *conf, *conf_next;
++	struct sptlrpc_conf *conf, *conf_next;
+ 
+ 	mutex_lock(&sptlrpc_conf_lock);
+ 	list_for_each_entry_safe(conf, conf_next, &sptlrpc_confs, sc_list) {
+diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c b/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c
+index 81de68edb04e..cdad608bdb8d 100644
+--- a/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c
++++ b/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c
+@@ -164,7 +164,7 @@ static void sec_do_gc(struct ptlrpc_sec *sec)
+ static int sec_gc_main(void *arg)
+ {
+ 	struct ptlrpc_thread *thread = (struct ptlrpc_thread *) arg;
+-	struct l_wait_info    lwi;
++	struct l_wait_info lwi;
+ 
+ 	unshare_fs_struct();
+ 
+diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_lproc.c b/drivers/staging/lustre/lustre/ptlrpc/sec_lproc.c
+index 982512febf05..68fcac14b3ee 100644
+--- a/drivers/staging/lustre/lustre/ptlrpc/sec_lproc.c
++++ b/drivers/staging/lustre/lustre/ptlrpc/sec_lproc.c
+@@ -74,7 +74,7 @@ static int sptlrpc_info_lprocfs_seq_show(struct seq_file *seq, void *v)
+ 	struct obd_device *dev = seq->private;
+ 	struct client_obd *cli = &dev->u.cli;
+ 	struct ptlrpc_sec *sec = NULL;
+-	char	       str[32];
++	char str[32];
+ 
+ 	LASSERT(strcmp(dev->obd_type->typ_name, LUSTRE_OSC_NAME) == 0 ||
+ 		strcmp(dev->obd_type->typ_name, LUSTRE_MDC_NAME) == 0 ||
+@@ -134,7 +134,7 @@ LPROC_SEQ_FOPS_RO(sptlrpc_ctxs_lprocfs);
+ 
+ int sptlrpc_lprocfs_cliobd_attach(struct obd_device *dev)
+ {
+-	int     rc;
++	int rc;
+ 
+ 	if (strcmp(dev->obd_type->typ_name, LUSTRE_OSC_NAME) != 0 &&
+ 	    strcmp(dev->obd_type->typ_name, LUSTRE_MDC_NAME) != 0 &&
+diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_null.c b/drivers/staging/lustre/lustre/ptlrpc/sec_null.c
+index 4e132435b450..8c28b6b7ff02 100644
+--- a/drivers/staging/lustre/lustre/ptlrpc/sec_null.c
++++ b/drivers/staging/lustre/lustre/ptlrpc/sec_null.c
+@@ -92,7 +92,7 @@ int null_ctx_sign(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req)
+ static
+ int null_ctx_verify(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req)
+ {
+-	__u32   cksums, cksumc;
++	__u32 cksums, cksumc;
+ 
+ 	LASSERT(req->rq_repdata);
+ 
+@@ -226,9 +226,9 @@ int null_enlarge_reqbuf(struct ptlrpc_sec *sec,
+ 			struct ptlrpc_request *req,
+ 			int segment, int newsize)
+ {
+-	struct lustre_msg      *newbuf;
+-	struct lustre_msg      *oldbuf = req->rq_reqmsg;
+-	int		     oldsize, newmsg_size, alloc_size;
++	struct lustre_msg *newbuf;
++	struct lustre_msg *oldbuf = req->rq_reqmsg;
++	int oldsize, newmsg_size, alloc_size;
+ 
+ 	LASSERT(req->rq_reqbuf);
+ 	LASSERT(req->rq_reqbuf == req->rq_reqmsg);
+diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c b/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c
+index 65f3ab42829c..ed39970417d8 100644
+--- a/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c
++++ b/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c
+@@ -136,7 +136,7 @@ static int plain_verify_bulk_csum(struct ptlrpc_bulk_desc *desc,
+ 				  struct plain_bulk_token *tokenr)
+ {
+ 	struct plain_bulk_token tokenv;
+-	int		     rc;
++	int rc;
+ 
+ 	if (hash_alg == BULK_HASH_ALG_NULL)
+ 		return 0;
+@@ -154,8 +154,8 @@ static int plain_verify_bulk_csum(struct ptlrpc_bulk_desc *desc,
+ 
+ static void corrupt_bulk_data(struct ptlrpc_bulk_desc *desc)
+ {
+-	char	   *ptr;
+-	unsigned int    off, i;
++	char *ptr;
++	unsigned int off, i;
+ 
+ 	for (i = 0; i < desc->bd_iov_count; i++) {
+ 		if (desc->bd_iov[i].kiov_len == 0)
+@@ -190,7 +190,7 @@ int plain_ctx_validate(struct ptlrpc_cli_ctx *ctx)
+ static
+ int plain_ctx_sign(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req)
+ {
+-	struct lustre_msg   *msg = req->rq_reqbuf;
++	struct lustre_msg *msg = req->rq_reqbuf;
+ 	struct plain_header *phdr;
+ 
+ 	msg->lm_secflvr = req->rq_flvr.sf_rpc;
+@@ -214,10 +214,10 @@ int plain_ctx_sign(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req)
+ static
+ int plain_ctx_verify(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req)
+ {
+-	struct lustre_msg   *msg = req->rq_repdata;
++	struct lustre_msg *msg = req->rq_repdata;
+ 	struct plain_header *phdr;
+-	__u32		cksum;
+-	int		  swabbed;
++	__u32 cksum;
++	int swabbed;
+ 
+ 	if (msg->lm_bufcount != PLAIN_PACK_SEGMENTS) {
+ 		CERROR("unexpected reply buf count %u\n", msg->lm_bufcount);
+@@ -290,8 +290,8 @@ int plain_cli_wrap_bulk(struct ptlrpc_cli_ctx *ctx,
+ 			struct ptlrpc_bulk_desc *desc)
+ {
+ 	struct ptlrpc_bulk_sec_desc *bsd;
+-	struct plain_bulk_token     *token;
+-	int			  rc;
++	struct plain_bulk_token *token;
++	int rc;
+ 
+ 	LASSERT(req->rq_pack_bulk);
+ 	LASSERT(req->rq_reqbuf->lm_bufcount == PLAIN_PACK_SEGMENTS);
+@@ -333,9 +333,9 @@ int plain_cli_unwrap_bulk(struct ptlrpc_cli_ctx *ctx,
+ 			  struct ptlrpc_bulk_desc *desc)
+ {
+ 	struct ptlrpc_bulk_sec_desc *bsdv;
+-	struct plain_bulk_token     *tokenv;
+-	int			  rc;
+-	int			  i, nob;
++	struct plain_bulk_token *tokenv;
++	int rc;
++	int i, nob;
+ 
+ 	LASSERT(req->rq_pack_bulk);
+ 	LASSERT(req->rq_reqbuf->lm_bufcount == PLAIN_PACK_SEGMENTS);
+@@ -374,7 +374,7 @@ int plain_cli_unwrap_bulk(struct ptlrpc_cli_ctx *ctx,
+ static
+ struct ptlrpc_cli_ctx *plain_sec_install_ctx(struct plain_sec *plsec)
+ {
+-	struct ptlrpc_cli_ctx  *ctx, *ctx_new;
++	struct ptlrpc_cli_ctx *ctx, *ctx_new;
+ 
+ 	ctx_new = kzalloc(sizeof(*ctx_new), GFP_NOFS);
+ 
+@@ -413,7 +413,7 @@ struct ptlrpc_cli_ctx *plain_sec_install_ctx(struct plain_sec *plsec)
+ static
+ void plain_destroy_sec(struct ptlrpc_sec *sec)
+ {
+-	struct plain_sec       *plsec = sec2plsec(sec);
++	struct plain_sec *plsec = sec2plsec(sec);
+ 
+ 	LASSERT(sec->ps_policy == &plain_policy);
+ 	LASSERT(sec->ps_import);
+@@ -437,9 +437,9 @@ struct ptlrpc_sec *plain_create_sec(struct obd_import *imp,
+ 				    struct ptlrpc_svc_ctx *svc_ctx,
+ 				    struct sptlrpc_flavor *sf)
+ {
+-	struct plain_sec       *plsec;
+-	struct ptlrpc_sec      *sec;
+-	struct ptlrpc_cli_ctx  *ctx;
++	struct plain_sec *plsec;
++	struct ptlrpc_sec *sec;
++	struct ptlrpc_cli_ctx *ctx;
+ 
+ 	LASSERT(SPTLRPC_FLVR_POLICY(sf->sf_rpc) == SPTLRPC_POLICY_PLAIN);
+ 
+@@ -483,8 +483,8 @@ struct ptlrpc_cli_ctx *plain_lookup_ctx(struct ptlrpc_sec *sec,
+ 					struct vfs_cred *vcred,
+ 					int create, int remove_dead)
+ {
+-	struct plain_sec       *plsec = sec2plsec(sec);
+-	struct ptlrpc_cli_ctx  *ctx;
++	struct plain_sec *plsec = sec2plsec(sec);
++	struct ptlrpc_cli_ctx *ctx;
+ 
+ 	read_lock(&plsec->pls_lock);
+ 	ctx = plsec->pls_ctx;
+@@ -517,8 +517,8 @@ static
+ int plain_flush_ctx_cache(struct ptlrpc_sec *sec,
+ 			  uid_t uid, int grace, int force)
+ {
+-	struct plain_sec       *plsec = sec2plsec(sec);
+-	struct ptlrpc_cli_ctx  *ctx;
++	struct plain_sec *plsec = sec2plsec(sec);
++	struct ptlrpc_cli_ctx *ctx;
+ 
+ 	/* do nothing unless caller want to flush for 'all' */
+ 	if (uid != -1)
+@@ -540,7 +540,7 @@ int plain_alloc_reqbuf(struct ptlrpc_sec *sec,
+ 		       int msgsize)
+ {
+ 	__u32 buflens[PLAIN_PACK_SEGMENTS] = { 0, };
+-	int   alloc_len;
++	int alloc_len;
+ 
+ 	buflens[PLAIN_PACK_HDR_OFF] = sizeof(struct plain_header);
+ 	buflens[PLAIN_PACK_MSG_OFF] = msgsize;
+@@ -635,9 +635,9 @@ int plain_enlarge_reqbuf(struct ptlrpc_sec *sec,
+ 			 struct ptlrpc_request *req,
+ 			 int segment, int newsize)
+ {
+-	struct lustre_msg      *newbuf;
+-	int		     oldsize;
+-	int		     newmsg_size, newbuf_size;
++	struct lustre_msg *newbuf;
++	int oldsize;
++	int newmsg_size, newbuf_size;
+ 
+ 	LASSERT(req->rq_reqbuf);
+ 	LASSERT(req->rq_reqbuf_len >= req->rq_reqlen);
+@@ -709,9 +709,9 @@ static struct ptlrpc_svc_ctx plain_svc_ctx = {
+ static
+ int plain_accept(struct ptlrpc_request *req)
+ {
+-	struct lustre_msg   *msg = req->rq_reqbuf;
++	struct lustre_msg *msg = req->rq_reqbuf;
+ 	struct plain_header *phdr;
+-	int		  swabbed;
++	int swabbed;
+ 
+ 	LASSERT(SPTLRPC_FLVR_POLICY(req->rq_flvr.sf_rpc) ==
+ 		SPTLRPC_POLICY_PLAIN);
+@@ -780,9 +780,9 @@ int plain_accept(struct ptlrpc_request *req)
+ static
+ int plain_alloc_rs(struct ptlrpc_request *req, int msgsize)
+ {
+-	struct ptlrpc_reply_state   *rs;
+-	__u32			buflens[PLAIN_PACK_SEGMENTS] = { 0, };
+-	int			  rs_size = sizeof(*rs);
++	struct ptlrpc_reply_state *rs;
++	__u32 buflens[PLAIN_PACK_SEGMENTS] = { 0, };
++	int rs_size = sizeof(*rs);
+ 
+ 	LASSERT(msgsize % 8 == 0);
+ 
+@@ -833,9 +833,9 @@ static
+ int plain_authorize(struct ptlrpc_request *req)
+ {
+ 	struct ptlrpc_reply_state *rs = req->rq_reply_state;
+-	struct lustre_msg_v2      *msg = rs->rs_repbuf;
+-	struct plain_header       *phdr;
+-	int			len;
++	struct lustre_msg_v2 *msg = rs->rs_repbuf;
++	struct plain_header *phdr;
++	int len;
+ 
+ 	LASSERT(rs);
+ 	LASSERT(msg);
+@@ -880,10 +880,10 @@ static
+ int plain_svc_unwrap_bulk(struct ptlrpc_request *req,
+ 			  struct ptlrpc_bulk_desc *desc)
+ {
+-	struct ptlrpc_reply_state   *rs = req->rq_reply_state;
++	struct ptlrpc_reply_state *rs = req->rq_reply_state;
+ 	struct ptlrpc_bulk_sec_desc *bsdr, *bsdv;
+-	struct plain_bulk_token     *tokenr;
+-	int			  rc;
++	struct plain_bulk_token *tokenr;
++	int rc;
+ 
+ 	LASSERT(req->rq_bulk_write);
+ 	LASSERT(req->rq_pack_bulk);
+@@ -914,10 +914,10 @@ static
+ int plain_svc_wrap_bulk(struct ptlrpc_request *req,
+ 			struct ptlrpc_bulk_desc *desc)
+ {
+-	struct ptlrpc_reply_state   *rs = req->rq_reply_state;
++	struct ptlrpc_reply_state *rs = req->rq_reply_state;
+ 	struct ptlrpc_bulk_sec_desc *bsdr, *bsdv;
+-	struct plain_bulk_token     *tokenv;
+-	int			  rc;
++	struct plain_bulk_token *tokenv;
++	int rc;
+ 
+ 	LASSERT(req->rq_bulk_read);
+ 	LASSERT(req->rq_pack_bulk);
+diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c
+index 454d1a8640a5..25ccbcb1772f 100644
+--- a/drivers/staging/lustre/lustre/ptlrpc/service.c
++++ b/drivers/staging/lustre/lustre/ptlrpc/service.c
+@@ -72,7 +72,7 @@ struct mutex ptlrpc_all_services_mutex;
+ struct ptlrpc_request_buffer_desc *
+ ptlrpc_alloc_rqbd(struct ptlrpc_service_part *svcpt)
+ {
+-	struct ptlrpc_service		  *svc = svcpt->scp_service;
++	struct ptlrpc_service *svc = svcpt->scp_service;
+ 	struct ptlrpc_request_buffer_desc *rqbd;
+ 
+ 	rqbd = kzalloc_node(sizeof(*rqbd), GFP_NOFS,
+@@ -121,10 +121,10 @@ ptlrpc_free_rqbd(struct ptlrpc_request_buffer_desc *rqbd)
+ int
+ ptlrpc_grow_req_bufs(struct ptlrpc_service_part *svcpt, int post)
+ {
+-	struct ptlrpc_service		  *svc = svcpt->scp_service;
++	struct ptlrpc_service *svc = svcpt->scp_service;
+ 	struct ptlrpc_request_buffer_desc *rqbd;
+-	int				rc = 0;
+-	int				i;
++	int rc = 0;
++	int i;
+ 
+ 	if (svcpt->scp_rqbd_allocating)
+ 		goto try_post;
+@@ -186,7 +186,7 @@ ptlrpc_save_lock(struct ptlrpc_request *req,
+ 		 struct lustre_handle *lock, int mode, int no_ack)
+ {
+ 	struct ptlrpc_reply_state *rs = req->rq_reply_state;
+-	int			idx;
++	int idx;
+ 
+ 	LASSERT(rs != NULL);
+ 	LASSERT(rs->rs_nlocks < RS_MAX_LOCKS);
+@@ -275,8 +275,8 @@ static void rs_batch_init(struct rs_batch *b)
+ static struct ptlrpc_hr_thread *
+ ptlrpc_hr_select(struct ptlrpc_service_part *svcpt)
+ {
+-	struct ptlrpc_hr_partition	*hrp;
+-	unsigned int			rotor;
++	struct ptlrpc_hr_partition *hrp;
++	unsigned int rotor;
+ 
+ 	if (svcpt->scp_cpt >= 0 &&
+ 	    svcpt->scp_service->srv_cptable == ptlrpc_hr.hr_cpt_table) {
+@@ -431,8 +431,8 @@ static int
+ ptlrpc_server_post_idle_rqbds(struct ptlrpc_service_part *svcpt)
+ {
+ 	struct ptlrpc_request_buffer_desc *rqbd;
+-	int				  rc;
+-	int				  posted = 0;
++	int rc;
++	int posted = 0;
+ 
+ 	for (;;) {
+ 		spin_lock(&svcpt->scp_lock);
+@@ -489,11 +489,11 @@ static void
+ ptlrpc_server_nthreads_check(struct ptlrpc_service *svc,
+ 			     struct ptlrpc_service_conf *conf)
+ {
+-	struct ptlrpc_service_thr_conf	*tc = &conf->psc_thr;
+-	unsigned			init;
+-	unsigned			total;
+-	unsigned			nthrs;
+-	int				weight;
++	struct ptlrpc_service_thr_conf *tc = &conf->psc_thr;
++	unsigned init;
++	unsigned total;
++	unsigned nthrs;
++	int weight;
+ 
+ 	/*
+ 	 * Common code for estimating & validating threads number.
+@@ -517,7 +517,7 @@ ptlrpc_server_nthreads_check(struct ptlrpc_service *svc,
+ 		 * be up to 8 * nthrs_max */
+ 		total = min(tc->tc_nthrs_max * 8, tc->tc_nthrs_user);
+ 		nthrs = total / svc->srv_ncpts;
+-		init  = max(init, nthrs);
++		init = max(init, nthrs);
+ 		goto out;
+ 	}
+ 
+@@ -531,7 +531,7 @@ ptlrpc_server_nthreads_check(struct ptlrpc_service *svc,
+ 
+ 	nthrs = tc->tc_nthrs_base;
+ 	if (svc->srv_ncpts == 1) {
+-		int	i;
++		int i;
+ 
+ 		/* NB: Increase the base number if it's single partition
+ 		 * and total number of cores/HTs is larger or equal to 4.
+@@ -543,7 +543,7 @@ ptlrpc_server_nthreads_check(struct ptlrpc_service *svc,
+ 	}
+ 
+ 	if (tc->tc_thr_factor != 0) {
+-		int	  factor = tc->tc_thr_factor;
++		int factor = tc->tc_thr_factor;
+ 		const int fade = 4;
+ 
+ 		/*
+@@ -595,9 +595,9 @@ ptlrpc_service_part_init(struct ptlrpc_service *svc,
+ 			 struct ptlrpc_service_part *svcpt, int cpt)
+ {
+ 	struct ptlrpc_at_array	*array;
+-	int			size;
+-	int			index;
+-	int			rc;
++	int size;
++	int index;
++	int rc;
+ 
+ 	svcpt->scp_cpt = cpt;
+ 	INIT_LIST_HEAD(&svcpt->scp_threads);
+@@ -627,8 +627,8 @@ ptlrpc_service_part_init(struct ptlrpc_service *svc,
+ 	array = &svcpt->scp_at_array;
+ 
+ 	size = at_est2timeout(at_max);
+-	array->paa_size     = size;
+-	array->paa_count    = 0;
++	array->paa_size = size;
++	array->paa_count = 0;
+ 	array->paa_deadline = -1;
+ 
+ 	/* allocate memory for scp_at_array (ptlrpc_at_array) */
+@@ -683,15 +683,15 @@ ptlrpc_register_service(struct ptlrpc_service_conf *conf,
+ 			struct kset *parent,
+ 			struct dentry *debugfs_entry)
+ {
+-	struct ptlrpc_service_cpt_conf	*cconf = &conf->psc_cpt;
+-	struct ptlrpc_service		*service;
+-	struct ptlrpc_service_part	*svcpt;
+-	struct cfs_cpt_table		*cptable;
+-	__u32				*cpts = NULL;
+-	int				ncpts;
+-	int				cpt;
+-	int				rc;
+-	int				i;
++	struct ptlrpc_service_cpt_conf *cconf = &conf->psc_cpt;
++	struct ptlrpc_service *service;
++	struct ptlrpc_service_part *svcpt;
++	struct cfs_cpt_table *cptable;
++	__u32 *cpts = NULL;
++	int ncpts;
++	int cpt;
++	int rc;
++	int i;
+ 
+ 	LASSERT(conf->psc_buf.bc_nbufs > 0);
+ 	LASSERT(conf->psc_buf.bc_buf_size >=
+@@ -707,7 +707,7 @@ ptlrpc_register_service(struct ptlrpc_service_conf *conf,
+ 	} else {
+ 		ncpts = cfs_cpt_number(cptable);
+ 		if (cconf->cc_pattern != NULL) {
+-			struct cfs_expr_list	*el;
++			struct cfs_expr_list *el;
+ 
+ 			rc = cfs_expr_list_parse(cconf->cc_pattern,
+ 						 strlen(cconf->cc_pattern),
+@@ -737,9 +737,9 @@ ptlrpc_register_service(struct ptlrpc_service_conf *conf,
+ 		return ERR_PTR(-ENOMEM);
+ 	}
+ 
+-	service->srv_cptable		= cptable;
+-	service->srv_cpts		= cpts;
+-	service->srv_ncpts		= ncpts;
++	service->srv_cptable = cptable;
++	service->srv_cpts = cpts;
++	service->srv_ncpts = ncpts;
+ 
+ 	service->srv_cpt_bits = 0; /* it's zero already, easy to read... */
+ 	while ((1 << service->srv_cpt_bits) < cfs_cpt_number(cptable))
+@@ -747,18 +747,18 @@ ptlrpc_register_service(struct ptlrpc_service_conf *conf,
+ 
+ 	/* public members */
+ 	spin_lock_init(&service->srv_lock);
+-	service->srv_name		= conf->psc_name;
+-	service->srv_watchdog_factor	= conf->psc_watchdog_factor;
++	service->srv_name = conf->psc_name;
++	service->srv_watchdog_factor = conf->psc_watchdog_factor;
+ 	INIT_LIST_HEAD(&service->srv_list); /* for safety of cleanup */
+ 
+ 	/* buffer configuration */
+-	service->srv_nbuf_per_group	= test_req_buffer_pressure ?
++	service->srv_nbuf_per_group = test_req_buffer_pressure ?
+ 					  1 : conf->psc_buf.bc_nbufs;
+-	service->srv_max_req_size	= conf->psc_buf.bc_req_max_size +
++	service->srv_max_req_size = conf->psc_buf.bc_req_max_size +
+ 					  SPTLRPC_MAX_PAYLOAD;
+-	service->srv_buf_size		= conf->psc_buf.bc_buf_size;
+-	service->srv_rep_portal		= conf->psc_buf.bc_rep_portal;
+-	service->srv_req_portal		= conf->psc_buf.bc_req_portal;
++	service->srv_buf_size = conf->psc_buf.bc_buf_size;
++	service->srv_rep_portal	= conf->psc_buf.bc_rep_portal;
++	service->srv_req_portal	= conf->psc_buf.bc_req_portal;
+ 
+ 	/* Increase max reply size to next power of two */
+ 	service->srv_max_reply_size = 1;
+@@ -766,10 +766,10 @@ ptlrpc_register_service(struct ptlrpc_service_conf *conf,
+ 	       conf->psc_buf.bc_rep_max_size + SPTLRPC_MAX_PAYLOAD)
+ 		service->srv_max_reply_size <<= 1;
+ 
+-	service->srv_thread_name	= conf->psc_thr.tc_thr_name;
+-	service->srv_ctx_tags		= conf->psc_thr.tc_ctx_tags;
+-	service->srv_hpreq_ratio	= PTLRPC_SVC_HP_RATIO;
+-	service->srv_ops		= conf->psc_ops;
++	service->srv_thread_name = conf->psc_thr.tc_thr_name;
++	service->srv_ctx_tags = conf->psc_thr.tc_ctx_tags;
++	service->srv_hpreq_ratio = PTLRPC_SVC_HP_RATIO;
++	service->srv_ops = conf->psc_ops;
+ 
+ 	for (i = 0; i < ncpts; i++) {
+ 		if (!conf->psc_thr.tc_cpu_affinity)
+@@ -859,11 +859,11 @@ static void ptlrpc_server_free_request(struct ptlrpc_request *req)
+ void ptlrpc_server_drop_request(struct ptlrpc_request *req)
+ {
+ 	struct ptlrpc_request_buffer_desc *rqbd = req->rq_rqbd;
+-	struct ptlrpc_service_part	  *svcpt = rqbd->rqbd_svcpt;
+-	struct ptlrpc_service		  *svc = svcpt->scp_service;
+-	int				refcount;
+-	struct list_head			*tmp;
+-	struct list_head			*nxt;
++	struct ptlrpc_service_part *svcpt = rqbd->rqbd_svcpt;
++	struct ptlrpc_service *svc = svcpt->scp_service;
++	int refcount;
++	struct list_head *tmp;
++	struct list_head *nxt;
+ 
+ 	if (!atomic_dec_and_test(&req->rq_refcount))
+ 		return;
+@@ -1387,7 +1387,7 @@ static int ptlrpc_at_check_timed(struct ptlrpc_service_part *svcpt)
+ 	struct ptlrpc_at_array *array = &svcpt->scp_at_array;
+ 	struct ptlrpc_request *rq, *n;
+ 	struct list_head work_list;
+-	__u32  index, count;
++	__u32 index, count;
+ 	time_t deadline;
+ 	time_t now = get_seconds();
+ 	long delay;
+@@ -1732,10 +1732,10 @@ static int
+ ptlrpc_server_handle_req_in(struct ptlrpc_service_part *svcpt,
+ 			    struct ptlrpc_thread *thread)
+ {
+-	struct ptlrpc_service	*svc = svcpt->scp_service;
+-	struct ptlrpc_request	*req;
+-	__u32			deadline;
+-	int			rc;
++	struct ptlrpc_service *svc = svcpt->scp_service;
++	struct ptlrpc_request *req;
++	__u32 deadline;
++	int rc;
+ 
+ 	spin_lock(&svcpt->scp_lock);
+ 	if (list_empty(&svcpt->scp_req_incoming)) {
+@@ -1876,11 +1876,11 @@ ptlrpc_server_handle_request(struct ptlrpc_service_part *svcpt,
+ {
+ 	struct ptlrpc_service *svc = svcpt->scp_service;
+ 	struct ptlrpc_request *request;
+-	struct timeval	 work_start;
+-	struct timeval	 work_end;
+-	long		   timediff;
+-	int		    rc;
+-	int		    fail_opc = 0;
++	struct timeval work_start;
++	struct timeval work_end;
++	long timediff;
++	int rc;
++	int fail_opc = 0;
+ 
+ 	request = ptlrpc_server_request_get(svcpt, false);
+ 	if (request == NULL)
+@@ -2032,10 +2032,10 @@ static int
+ ptlrpc_handle_rs(struct ptlrpc_reply_state *rs)
+ {
+ 	struct ptlrpc_service_part *svcpt = rs->rs_svcpt;
+-	struct ptlrpc_service     *svc = svcpt->scp_service;
+-	struct obd_export	 *exp;
+-	int			nlocks;
+-	int			been_handled;
++	struct ptlrpc_service *svc = svcpt->scp_service;
++	struct obd_export *exp;
++	int nlocks;
++	int been_handled;
+ 
+ 	exp = rs->rs_export;
+ 
+@@ -2262,10 +2262,10 @@ ptlrpc_wait_event(struct ptlrpc_service_part *svcpt,
+  */
+ static int ptlrpc_main(void *arg)
+ {
+-	struct ptlrpc_thread		*thread = (struct ptlrpc_thread *)arg;
+-	struct ptlrpc_service_part	*svcpt = thread->t_svcpt;
+-	struct ptlrpc_service		*svc = svcpt->scp_service;
+-	struct ptlrpc_reply_state	*rs;
++	struct ptlrpc_thread *thread = (struct ptlrpc_thread *)arg;
++	struct ptlrpc_service_part *svcpt = thread->t_svcpt;
++	struct ptlrpc_service *svc = svcpt->scp_service;
++	struct ptlrpc_reply_state *rs;
+ 	struct group_info *ginfo = NULL;
+ 	struct lu_env *env;
+ 	int counter = 0, rc = 0;
+@@ -2464,11 +2464,11 @@ static int hrt_dont_sleep(struct ptlrpc_hr_thread *hrt,
+  */
+ static int ptlrpc_hr_main(void *arg)
+ {
+-	struct ptlrpc_hr_thread		*hrt = (struct ptlrpc_hr_thread *)arg;
+-	struct ptlrpc_hr_partition	*hrp = hrt->hrt_partition;
+-	LIST_HEAD			(replies);
+-	char				threadname[20];
+-	int				rc;
++	struct ptlrpc_hr_thread	*hrt = (struct ptlrpc_hr_thread *)arg;
++	struct ptlrpc_hr_partition *hrp = hrt->hrt_partition;
++	LIST_HEAD	(replies);
++	char threadname[20];
++	int rc;
+ 
+ 	snprintf(threadname, sizeof(threadname), "ptlrpc_hr%02d_%03d",
+ 		 hrp->hrp_cpt, hrt->hrt_id);
+@@ -2505,9 +2505,9 @@ static int ptlrpc_hr_main(void *arg)
+ 
+ static void ptlrpc_stop_hr_threads(void)
+ {
+-	struct ptlrpc_hr_partition	*hrp;
+-	int				i;
+-	int				j;
++	struct ptlrpc_hr_partition *hrp;
++	int i;
++	int j;
+ 
+ 	ptlrpc_hr.hr_stopping = 1;
+ 
+@@ -2529,12 +2529,12 @@ static void ptlrpc_stop_hr_threads(void)
+ 
+ static int ptlrpc_start_hr_threads(void)
+ {
+-	struct ptlrpc_hr_partition	*hrp;
+-	int				i;
+-	int				j;
++	struct ptlrpc_hr_partition *hrp;
++	int i;
++	int j;
+ 
+ 	cfs_percpt_for_each(hrp, i, ptlrpc_hr.hr_partitions) {
+-		int	rc = 0;
++		int rc = 0;
+ 
+ 		for (j = 0; j < hrp->hrp_nthrs; j++) {
+ 			struct	ptlrpc_hr_thread *hrt = &hrp->hrp_thrs[j];
+@@ -2561,9 +2561,9 @@ static int ptlrpc_start_hr_threads(void)
+ 
+ static void ptlrpc_svcpt_stop_threads(struct ptlrpc_service_part *svcpt)
+ {
+-	struct l_wait_info	lwi = { 0 };
+-	struct ptlrpc_thread	*thread;
+-	LIST_HEAD		(zombie);
++	struct l_wait_info lwi = { 0 };
++	struct ptlrpc_thread *thread;
++	LIST_HEAD	(zombie);
+ 
+ 	CDEBUG(D_INFO, "Stopping threads for service %s\n",
+ 	       svcpt->scp_service->srv_name);
+@@ -2612,7 +2612,7 @@ static void ptlrpc_svcpt_stop_threads(struct ptlrpc_service_part *svcpt)
+ void ptlrpc_stop_all_threads(struct ptlrpc_service *svc)
+ {
+ 	struct ptlrpc_service_part *svcpt;
+-	int			   i;
++	int i;
+ 
+ 	ptlrpc_service_for_each_part(svcpt, i, svc) {
+ 		if (svcpt->scp_service != NULL)
+@@ -2623,9 +2623,9 @@ EXPORT_SYMBOL(ptlrpc_stop_all_threads);
+ 
+ int ptlrpc_start_threads(struct ptlrpc_service *svc)
+ {
+-	int	rc = 0;
+-	int	i;
+-	int	j;
++	int rc = 0;
++	int i;
++	int j;
+ 
+ 	/* We require 2 threads min, see note in ptlrpc_server_handle_request */
+ 	LASSERT(svc->srv_nthrs_cpt_init >= PTLRPC_NTHRS_INIT);
+@@ -2654,10 +2654,10 @@ EXPORT_SYMBOL(ptlrpc_start_threads);
+ 
+ int ptlrpc_start_thread(struct ptlrpc_service_part *svcpt, int wait)
+ {
+-	struct l_wait_info	lwi = { 0 };
+-	struct ptlrpc_thread	*thread;
+-	struct ptlrpc_service	*svc;
+-	int			rc;
++	struct l_wait_info lwi = { 0 };
++	struct ptlrpc_thread *thread;
++	struct ptlrpc_service *svc;
++	int rc;
+ 
+ 	LASSERT(svcpt != NULL);
+ 
+@@ -2759,12 +2759,12 @@ int ptlrpc_start_thread(struct ptlrpc_service_part *svcpt, int wait)
+ 
+ int ptlrpc_hr_init(void)
+ {
+-	struct ptlrpc_hr_partition	*hrp;
+-	struct ptlrpc_hr_thread		*hrt;
+-	int				rc;
+-	int				i;
+-	int				j;
+-	int				weight;
++	struct ptlrpc_hr_partition *hrp;
++	struct ptlrpc_hr_thread	*hrt;
++	int rc;
++	int i;
++	int j;
++	int weight;
+ 
+ 	memset(&ptlrpc_hr, 0, sizeof(ptlrpc_hr));
+ 	ptlrpc_hr.hr_cpt_table = cfs_cpt_table;
+@@ -2817,8 +2817,8 @@ int ptlrpc_hr_init(void)
+ 
+ void ptlrpc_hr_fini(void)
+ {
+-	struct ptlrpc_hr_partition	*hrp;
+-	int				i;
++	struct ptlrpc_hr_partition *hrp;
++	int i;
+ 
+ 	if (ptlrpc_hr.hr_partitions == NULL)
+ 		return;
+@@ -2858,8 +2858,8 @@ static void ptlrpc_wait_replies(struct ptlrpc_service_part *svcpt)
+ static void
+ ptlrpc_service_del_atimer(struct ptlrpc_service *svc)
+ {
+-	struct ptlrpc_service_part	*svcpt;
+-	int				i;
++	struct ptlrpc_service_part *svcpt;
++	int i;
+ 
+ 	/* early disarm AT timer... */
+ 	ptlrpc_service_for_each_part(svcpt, i, svc) {
+@@ -2871,11 +2871,11 @@ ptlrpc_service_del_atimer(struct ptlrpc_service *svc)
+ static void
+ ptlrpc_service_unlink_rqbd(struct ptlrpc_service *svc)
+ {
+-	struct ptlrpc_service_part	  *svcpt;
++	struct ptlrpc_service_part *svcpt;
+ 	struct ptlrpc_request_buffer_desc *rqbd;
+-	struct l_wait_info		  lwi;
+-	int				  rc;
+-	int				  i;
++	struct l_wait_info lwi;
++	int rc;
++	int i;
+ 
+ 	/* All history will be culled when the next request buffer is
+ 	 * freed in ptlrpc_service_purge_all() */
+@@ -2927,11 +2927,11 @@ ptlrpc_service_unlink_rqbd(struct ptlrpc_service *svc)
+ static void
+ ptlrpc_service_purge_all(struct ptlrpc_service *svc)
+ {
+-	struct ptlrpc_service_part		*svcpt;
+-	struct ptlrpc_request_buffer_desc	*rqbd;
+-	struct ptlrpc_request			*req;
+-	struct ptlrpc_reply_state		*rs;
+-	int					i;
++	struct ptlrpc_service_part *svcpt;
++	struct ptlrpc_request_buffer_desc *rqbd;
++	struct ptlrpc_request *req;
++	struct ptlrpc_reply_state *rs;
++	int i;
+ 
+ 	ptlrpc_service_for_each_part(svcpt, i, svc) {
+ 		if (svcpt->scp_service == NULL)
+@@ -2995,9 +2995,9 @@ ptlrpc_service_purge_all(struct ptlrpc_service *svc)
+ static void
+ ptlrpc_service_free(struct ptlrpc_service *svc)
+ {
+-	struct ptlrpc_service_part	*svcpt;
+-	struct ptlrpc_at_array		*array;
+-	int				i;
++	struct ptlrpc_service_part *svcpt;
++	struct ptlrpc_at_array *array;
++	int i;
+ 
+ 	ptlrpc_service_for_each_part(svcpt, i, svc) {
+ 		if (svcpt->scp_service == NULL)
+@@ -3056,9 +3056,9 @@ EXPORT_SYMBOL(ptlrpc_unregister_service);
+  * to be shot, so it's intentionally non-aggressive. */
+ int ptlrpc_svcpt_health_check(struct ptlrpc_service_part *svcpt)
+ {
+-	struct ptlrpc_request		*request = NULL;
+-	struct timeval			right_now;
+-	long				timediff;
++	struct ptlrpc_request *request = NULL;
++	struct timeval right_now;
++	long timediff;
+ 
+ 	do_gettimeofday(&right_now);
+ 
+@@ -3090,8 +3090,8 @@ int ptlrpc_svcpt_health_check(struct ptlrpc_service_part *svcpt)
+ int
+ ptlrpc_service_health_check(struct ptlrpc_service *svc)
+ {
+-	struct ptlrpc_service_part	*svcpt;
+-	int				i;
++	struct ptlrpc_service_part *svcpt;
++	int i;
+ 
+ 	if (svc == NULL)
+ 		return 0;

commit 29ac6840d7c8b4ce60c9dcd0a55fce6a84d3bae0
+Author: Chris Hanna 
+Date:   Wed Jun 3 10:23:42 2015 -0400
+
+    staging: lustre: osc: clean up whitespace and align function parameters
+    
+    Minor changes to remove excessive whitespace and improve
+    readability of osc functions.
+    
+    Signed-off-by: Chris Hanna 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/lustre/lustre/osc/lproc_osc.c b/drivers/staging/lustre/lustre/osc/lproc_osc.c
+index 9dc84ba7aa55..ff6d2e2ffdab 100644
+--- a/drivers/staging/lustre/lustre/osc/lproc_osc.c
++++ b/drivers/staging/lustre/lustre/osc/lproc_osc.c
+@@ -417,8 +417,8 @@ static ssize_t osc_checksum_type_seq_write(struct file *file,
+ LPROC_SEQ_FOPS(osc_checksum_type);
+ 
+ static ssize_t resend_count_show(struct kobject *kobj,
+-			     struct attribute *attr,
+-			     char *buf)
++				 struct attribute *attr,
++				 char *buf)
+ {
+ 	struct obd_device *obd = container_of(kobj, struct obd_device,
+ 					      obd_kobj);
+@@ -427,9 +427,9 @@ static ssize_t resend_count_show(struct kobject *kobj,
+ }
+ 
+ static ssize_t resend_count_store(struct kobject *kobj,
+-			      struct attribute *attr,
+-			      const char *buffer,
+-			      size_t count)
++				  struct attribute *attr,
++				  const char *buffer,
++				  size_t count)
+ {
+ 	struct obd_device *obd = container_of(kobj, struct obd_device,
+ 					      obd_kobj);
+@@ -682,8 +682,8 @@ static int osc_rpc_stats_seq_show(struct seq_file *seq, void *v)
+ #undef pct
+ 
+ static ssize_t osc_rpc_stats_seq_write(struct file *file,
+-				const char __user *buf,
+-				size_t len, loff_t *off)
++				       const char __user *buf,
++				       size_t len, loff_t *off)
+ {
+ 	struct seq_file *seq = file->private_data;
+ 	struct obd_device *dev = seq->private;
+@@ -721,8 +721,8 @@ static int osc_stats_seq_show(struct seq_file *seq, void *v)
+ }
+ 
+ static ssize_t osc_stats_seq_write(struct file *file,
+-				const char __user *buf,
+-				size_t len, loff_t *off)
++				   const char __user *buf,
++				   size_t len, loff_t *off)
+ {
+ 	struct seq_file *seq = file->private_data;
+ 	struct obd_device *dev = seq->private;
+diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c
+index d44b3d4ffe4d..5592d32a1a95 100644
+--- a/drivers/staging/lustre/lustre/osc/osc_cache.c
++++ b/drivers/staging/lustre/lustre/osc/osc_cache.c
+@@ -112,8 +112,8 @@ static const char *oes_strings[] = {
+ 		/* ----- extent part 0 ----- */				      \
+ 		__ext, EXTPARA(__ext),					      \
+ 		/* ----- part 1 ----- */				      \
+-		atomic_read(&__ext->oe_refc),			      \
+-		atomic_read(&__ext->oe_users),			      \
++		atomic_read(&__ext->oe_refc),				      \
++		atomic_read(&__ext->oe_users),				      \
+ 		list_empty_marker(&__ext->oe_link),			      \
+ 		oes_strings[__ext->oe_state], ext_flags(__ext, __buf),	      \
+ 		__ext->oe_obj,						      \
+@@ -297,12 +297,12 @@ static int osc_extent_sanity_check0(struct osc_extent *ext,
+ #define sanity_check_nolock(ext) \
+ 	osc_extent_sanity_check0(ext, __func__, __LINE__)
+ 
+-#define sanity_check(ext) ({						   \
+-	int __res;							     \
++#define sanity_check(ext) ({						\
++	int __res;							\
+ 	osc_object_lock((ext)->oe_obj);					\
+-	__res = sanity_check_nolock(ext);				      \
+-	osc_object_unlock((ext)->oe_obj);				      \
+-	__res;								 \
++	__res = sanity_check_nolock(ext);				\
++	osc_object_unlock((ext)->oe_obj);				\
++	__res;								\
+ })
+ 
+ 
+@@ -411,7 +411,7 @@ static void osc_extent_put_trust(struct osc_extent *ext)
+ static struct osc_extent *osc_extent_search(struct osc_object *obj,
+ 					    pgoff_t index)
+ {
+-	struct rb_node    *n = obj->oo_root.rb_node;
++	struct rb_node *n = obj->oo_root.rb_node;
+ 	struct osc_extent *tmp, *p = NULL;
+ 
+ 	LASSERT(osc_object_is_locked(obj));
+@@ -447,8 +447,8 @@ static struct osc_extent *osc_extent_lookup(struct osc_object *obj,
+ /* caller must have held object lock. */
+ static void osc_extent_insert(struct osc_object *obj, struct osc_extent *ext)
+ {
+-	struct rb_node   **n      = &obj->oo_root.rb_node;
+-	struct rb_node    *parent = NULL;
++	struct rb_node **n = &obj->oo_root.rb_node;
++	struct rb_node *parent = NULL;
+ 	struct osc_extent *tmp;
+ 
+ 	LASSERT(ext->oe_intree == 0);
+@@ -544,19 +544,19 @@ static int osc_extent_merge(const struct lu_env *env, struct osc_extent *cur,
+ 	LASSERT(cur->oe_osclock == victim->oe_osclock);
+ 	ppc_bits = osc_cli(obj)->cl_chunkbits - PAGE_CACHE_SHIFT;
+ 	chunk_start = cur->oe_start >> ppc_bits;
+-	chunk_end   = cur->oe_end   >> ppc_bits;
+-	if (chunk_start   != (victim->oe_end >> ppc_bits) + 1 &&
++	chunk_end = cur->oe_end >> ppc_bits;
++	if (chunk_start != (victim->oe_end >> ppc_bits) + 1 &&
+ 	    chunk_end + 1 != victim->oe_start >> ppc_bits)
+ 		return -ERANGE;
+ 
+ 	OSC_EXTENT_DUMP(D_CACHE, victim, "will be merged by %p.\n", cur);
+ 
+-	cur->oe_start     = min(cur->oe_start, victim->oe_start);
+-	cur->oe_end       = max(cur->oe_end,   victim->oe_end);
+-	cur->oe_grants   += victim->oe_grants;
++	cur->oe_start = min(cur->oe_start, victim->oe_start);
++	cur->oe_end = max(cur->oe_end, victim->oe_end);
++	cur->oe_grants += victim->oe_grants;
+ 	cur->oe_nr_pages += victim->oe_nr_pages;
+ 	/* only the following bits are needed to merge */
+-	cur->oe_urgent   |= victim->oe_urgent;
++	cur->oe_urgent |= victim->oe_urgent;
+ 	cur->oe_memalloc |= victim->oe_memalloc;
+ 	list_splice_init(&victim->oe_pages, &cur->oe_pages);
+ 	list_del_init(&victim->oe_link);
+@@ -624,18 +624,18 @@ struct osc_extent *osc_extent_find(const struct lu_env *env,
+ 
+ {
+ 	struct client_obd *cli = osc_cli(obj);
+-	struct cl_lock    *lock;
++	struct cl_lock *lock;
+ 	struct osc_extent *cur;
+ 	struct osc_extent *ext;
+ 	struct osc_extent *conflict = NULL;
+ 	struct osc_extent *found = NULL;
+-	pgoff_t    chunk;
+-	pgoff_t    max_end;
+-	int	max_pages; /* max_pages_per_rpc */
+-	int	chunksize;
+-	int	ppc_bits; /* pages per chunk bits */
+-	int	chunk_mask;
+-	int	rc;
++	pgoff_t chunk;
++	pgoff_t max_end;
++	int max_pages; /* max_pages_per_rpc */
++	int chunksize;
++	int ppc_bits; /* pages per chunk bits */
++	int chunk_mask;
++	int rc;
+ 
+ 	cur = osc_extent_alloc(obj);
+ 	if (cur == NULL)
+@@ -646,10 +646,10 @@ struct osc_extent *osc_extent_find(const struct lu_env *env,
+ 	LASSERT(lock->cll_descr.cld_mode >= CLM_WRITE);
+ 
+ 	LASSERT(cli->cl_chunkbits >= PAGE_CACHE_SHIFT);
+-	ppc_bits   = cli->cl_chunkbits - PAGE_CACHE_SHIFT;
++	ppc_bits = cli->cl_chunkbits - PAGE_CACHE_SHIFT;
+ 	chunk_mask = ~((1 << ppc_bits) - 1);
+-	chunksize  = 1 << cli->cl_chunkbits;
+-	chunk      = index >> ppc_bits;
++	chunksize = 1 << cli->cl_chunkbits;
++	chunk = index >> ppc_bits;
+ 
+ 	/* align end to rpc edge, rpc size may not be a power 2 integer. */
+ 	max_pages = cli->cl_max_pages_per_rpc;
+@@ -659,15 +659,15 @@ struct osc_extent *osc_extent_find(const struct lu_env *env,
+ 
+ 	/* initialize new extent by parameters so far */
+ 	cur->oe_max_end = max_end;
+-	cur->oe_start   = index & chunk_mask;
+-	cur->oe_end     = ((index + ~chunk_mask + 1) & chunk_mask) - 1;
++	cur->oe_start = index & chunk_mask;
++	cur->oe_end = ((index + ~chunk_mask + 1) & chunk_mask) - 1;
+ 	if (cur->oe_start < lock->cll_descr.cld_start)
+ 		cur->oe_start = lock->cll_descr.cld_start;
+ 	if (cur->oe_end > max_end)
+ 		cur->oe_end = max_end;
+ 	cur->oe_osclock = lock;
+-	cur->oe_grants  = 0;
+-	cur->oe_mppr    = max_pages;
++	cur->oe_grants = 0;
++	cur->oe_mppr = max_pages;
+ 
+ 	/* grants has been allocated by caller */
+ 	LASSERTF(*grants >= chunksize + cli->cl_extent_tax,
+@@ -681,7 +681,7 @@ struct osc_extent *osc_extent_find(const struct lu_env *env,
+ 		ext = first_extent(obj);
+ 	while (ext != NULL) {
+ 		loff_t ext_chk_start = ext->oe_start >> ppc_bits;
+-		loff_t ext_chk_end   = ext->oe_end   >> ppc_bits;
++		loff_t ext_chk_end = ext->oe_end >> ppc_bits;
+ 
+ 		LASSERT(sanity_check_nolock(ext) == 0);
+ 		if (chunk > ext_chk_end + 1)
+@@ -755,14 +755,14 @@ struct osc_extent *osc_extent_find(const struct lu_env *env,
+ 			EASSERT((ext->oe_start & ~chunk_mask) == 0, ext);
+ 
+ 			/* pull ext's start back to cover cur */
+-			ext->oe_start   = cur->oe_start;
++			ext->oe_start = cur->oe_start;
+ 			ext->oe_grants += chunksize;
+ 			*grants -= chunksize;
+ 
+ 			found = osc_extent_hold(ext);
+ 		} else if (chunk == ext_chk_end + 1) {
+ 			/* rear merge */
+-			ext->oe_end     = cur->oe_end;
++			ext->oe_end = cur->oe_end;
+ 			ext->oe_grants += chunksize;
+ 			*grants -= chunksize;
+ 
+@@ -943,21 +943,21 @@ static int osc_extent_wait(const struct lu_env *env, struct osc_extent *ext,
+  * @size, then partial truncate happens.
+  */
+ static int osc_extent_truncate(struct osc_extent *ext, pgoff_t trunc_index,
+-				bool partial)
++			       bool partial)
+ {
+-	struct cl_env_nest     nest;
+-	struct lu_env	 *env;
+-	struct cl_io	  *io;
+-	struct osc_object     *obj = ext->oe_obj;
+-	struct client_obd     *cli = osc_cli(obj);
++	struct cl_env_nest nest;
++	struct lu_env *env;
++	struct cl_io *io;
++	struct osc_object *obj = ext->oe_obj;
++	struct client_obd *cli = osc_cli(obj);
+ 	struct osc_async_page *oap;
+ 	struct osc_async_page *tmp;
+-	int		    pages_in_chunk = 0;
+-	int		    ppc_bits    = cli->cl_chunkbits - PAGE_CACHE_SHIFT;
+-	__u64		  trunc_chunk = trunc_index >> ppc_bits;
+-	int		    grants   = 0;
+-	int		    nr_pages = 0;
+-	int		    rc       = 0;
++	int pages_in_chunk = 0;
++	int ppc_bits = cli->cl_chunkbits - PAGE_CACHE_SHIFT;
++	__u64 trunc_chunk = trunc_index >> ppc_bits;
++	int grants = 0;
++	int nr_pages = 0;
++	int rc = 0;
+ 
+ 	LASSERT(sanity_check(ext) == 0);
+ 	EASSERT(ext->oe_state == OES_TRUNC, ext);
+@@ -976,8 +976,8 @@ static int osc_extent_truncate(struct osc_extent *ext, pgoff_t trunc_index,
+ 	/* discard all pages with index greater then trunc_index */
+ 	list_for_each_entry_safe(oap, tmp, &ext->oe_pages,
+ 				     oap_pending_item) {
+-		struct cl_page  *sub  = oap2cl_page(oap);
+-		struct cl_page  *page = cl_page_top(sub);
++		struct cl_page *sub = oap2cl_page(oap);
++		struct cl_page *page = cl_page_top(sub);
+ 
+ 		LASSERT(list_empty(&oap->oap_rpc_item));
+ 
+@@ -1022,7 +1022,7 @@ static int osc_extent_truncate(struct osc_extent *ext, pgoff_t trunc_index,
+ 		grants = ext->oe_grants;
+ 		ext->oe_grants = 0;
+ 	} else { /* calculate how many grants we can free */
+-		int     chunks = (ext->oe_end >> ppc_bits) - trunc_chunk;
++		int chunks = (ext->oe_end >> ppc_bits) - trunc_chunk;
+ 		pgoff_t last_index;
+ 
+ 
+@@ -1038,10 +1038,10 @@ static int osc_extent_truncate(struct osc_extent *ext, pgoff_t trunc_index,
+ 		}
+ 
+ 		/* this is what we can free from this extent */
+-		grants	  = chunks << cli->cl_chunkbits;
++		grants = chunks << cli->cl_chunkbits;
+ 		ext->oe_grants -= grants;
+-		last_index      = ((trunc_chunk + 1) << ppc_bits) - 1;
+-		ext->oe_end     = min(last_index, ext->oe_max_end);
++		last_index = ((trunc_chunk + 1) << ppc_bits) - 1;
++		ext->oe_end = min(last_index, ext->oe_max_end);
+ 		LASSERT(ext->oe_end >= ext->oe_start);
+ 		LASSERT(ext->oe_grants > 0);
+ 	}
+@@ -1236,8 +1236,8 @@ static inline int osc_is_ready(struct osc_object *osc)
+ static int osc_make_ready(const struct lu_env *env, struct osc_async_page *oap,
+ 			  int cmd)
+ {
+-	struct osc_page *opg  = oap2osc_page(oap);
+-	struct cl_page  *page = cl_page_top(oap2cl_page(oap));
++	struct osc_page *opg = oap2osc_page(oap);
++	struct cl_page *page = cl_page_top(oap2cl_page(oap));
+ 	int result;
+ 
+ 	LASSERT(cmd == OBD_BRW_WRITE); /* no cached reads */
+@@ -1251,10 +1251,10 @@ static int osc_make_ready(const struct lu_env *env, struct osc_async_page *oap,
+ static int osc_refresh_count(const struct lu_env *env,
+ 			     struct osc_async_page *oap, int cmd)
+ {
+-	struct osc_page  *opg = oap2osc_page(oap);
+-	struct cl_page   *page = oap2cl_page(oap);
++	struct osc_page *opg = oap2osc_page(oap);
++	struct cl_page *page = oap2cl_page(oap);
+ 	struct cl_object *obj;
+-	struct cl_attr   *attr = &osc_env_info(env)->oti_attr;
++	struct cl_attr *attr = &osc_env_info(env)->oti_attr;
+ 
+ 	int result;
+ 	loff_t kms;
+@@ -1283,10 +1283,10 @@ static int osc_refresh_count(const struct lu_env *env,
+ static int osc_completion(const struct lu_env *env, struct osc_async_page *oap,
+ 			  int cmd, int rc)
+ {
+-	struct osc_page   *opg  = oap2osc_page(oap);
+-	struct cl_page    *page = cl_page_top(oap2cl_page(oap));
+-	struct osc_object *obj  = cl2osc(opg->ops_cl.cpl_obj);
+-	enum cl_req_type   crt;
++	struct osc_page *opg = oap2osc_page(oap);
++	struct cl_page *page = cl_page_top(oap2cl_page(oap));
++	struct osc_object *obj = cl2osc(opg->ops_cl.cpl_obj);
++	enum cl_req_type crt;
+ 	int srvlock;
+ 
+ 	cmd &= ~OBD_BRW_NOQUOTA;
+@@ -1318,7 +1318,7 @@ static int osc_completion(const struct lu_env *env, struct osc_async_page *oap,
+ 
+ 	/* statistic */
+ 	if (rc == 0 && srvlock) {
+-		struct lu_device *ld    = opg->ops_cl.cpl_obj->co_lu.lo_dev;
++		struct lu_device *ld = opg->ops_cl.cpl_obj->co_lu.lo_dev;
+ 		struct osc_stats *stats = &lu2osc_dev(ld)->od_stats;
+ 		int bytes = oap->oap_count;
+ 
+@@ -1396,7 +1396,7 @@ static int osc_reserve_grant(struct client_obd *cli, unsigned int bytes)
+ 	int rc = -EDQUOT;
+ 
+ 	if (cli->cl_avail_grant >= bytes) {
+-		cli->cl_avail_grant    -= bytes;
++		cli->cl_avail_grant -= bytes;
+ 		cli->cl_reserved_grant += bytes;
+ 		rc = 0;
+ 	}
+@@ -1527,7 +1527,7 @@ static int osc_enter_cache(const struct lu_env *env, struct client_obd *cli,
+ 			   struct osc_async_page *oap, int bytes)
+ {
+ 	struct osc_object *osc = oap->oap_obj;
+-	struct lov_oinfo  *loi = osc->oo_oinfo;
++	struct lov_oinfo *loi = osc->oo_oinfo;
+ 	struct osc_cache_waiter ocw;
+ 	struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL);
+ 	int rc = -EDQUOT;
+@@ -1782,7 +1782,7 @@ static void osc_ap_completion(const struct lu_env *env, struct client_obd *cli,
+ 			      struct osc_async_page *oap, int sent, int rc)
+ {
+ 	struct osc_object *osc = oap->oap_obj;
+-	struct lov_oinfo  *loi = osc->oo_oinfo;
++	struct lov_oinfo *loi = osc->oo_oinfo;
+ 	__u64 xid = 0;
+ 
+ 	if (oap->oap_request != NULL) {
+@@ -2049,7 +2049,7 @@ osc_send_read_rpc(const struct lu_env *env, struct client_obd *cli,
+ 
+ #define list_to_obj(list, item) ({					      \
+ 	struct list_head *__tmp = (list)->next;				      \
+-	list_del_init(__tmp);					      \
++	list_del_init(__tmp);						      \
+ 	list_entry(__tmp, struct osc_object, oo_##item);		      \
+ })
+ 
+@@ -2179,7 +2179,7 @@ static int osc_io_unplug0(const struct lu_env *env, struct client_obd *cli,
+ }
+ 
+ static int osc_io_unplug_async(const struct lu_env *env,
+-				struct client_obd *cli, struct osc_object *osc)
++			       struct client_obd *cli, struct osc_object *osc)
+ {
+ 	/* XXX: policy is no use actually. */
+ 	return osc_io_unplug0(env, cli, osc, PDL_POLICY_ROUND, 1);
+@@ -2194,7 +2194,7 @@ void osc_io_unplug(const struct lu_env *env, struct client_obd *cli,
+ int osc_prep_async_page(struct osc_object *osc, struct osc_page *ops,
+ 			struct page *page, loff_t offset)
+ {
+-	struct obd_export     *exp = osc_export(osc);
++	struct obd_export *exp = osc_export(osc);
+ 	struct osc_async_page *oap = &ops->ops_oap;
+ 
+ 	if (!page)
+@@ -2224,16 +2224,16 @@ int osc_queue_async_io(const struct lu_env *env, struct cl_io *io,
+ 		       struct osc_page *ops)
+ {
+ 	struct osc_io *oio = osc_env_io(env);
+-	struct osc_extent     *ext = NULL;
++	struct osc_extent *ext = NULL;
+ 	struct osc_async_page *oap = &ops->ops_oap;
+-	struct client_obd     *cli = oap->oap_cli;
+-	struct osc_object     *osc = oap->oap_obj;
++	struct client_obd *cli = oap->oap_cli;
++	struct osc_object *osc = oap->oap_obj;
+ 	pgoff_t index;
+-	int    grants = 0;
+-	int    brw_flags = OBD_BRW_ASYNC;
+-	int    cmd = OBD_BRW_WRITE;
+-	int    need_release = 0;
+-	int    rc = 0;
++	int grants = 0;
++	int brw_flags = OBD_BRW_ASYNC;
++	int cmd = OBD_BRW_WRITE;
++	int need_release = 0;
++	int rc = 0;
+ 
+ 	if (oap->oap_magic != OAP_MAGIC)
+ 		return -EINVAL;
+@@ -2256,7 +2256,7 @@ int osc_queue_async_io(const struct lu_env *env, struct cl_io *io,
+ 	/* check if the file's owner/group is over quota */
+ 	if (!(cmd & OBD_BRW_NOQUOTA)) {
+ 		struct cl_object *obj;
+-		struct cl_attr   *attr;
++		struct cl_attr *attr;
+ 		unsigned int qid[MAXQUOTAS];
+ 
+ 		obj = cl_object_top(&osc->oo_cl);
+@@ -2386,7 +2386,7 @@ int osc_teardown_async_page(const struct lu_env *env,
+ 			    struct osc_object *obj, struct osc_page *ops)
+ {
+ 	struct osc_async_page *oap = &ops->ops_oap;
+-	struct osc_extent     *ext = NULL;
++	struct osc_extent *ext = NULL;
+ 	int rc = 0;
+ 
+ 	LASSERT(oap->oap_magic == OAP_MAGIC);
+@@ -2425,10 +2425,10 @@ int osc_teardown_async_page(const struct lu_env *env,
+ int osc_flush_async_page(const struct lu_env *env, struct cl_io *io,
+ 			 struct osc_page *ops)
+ {
+-	struct osc_extent *ext   = NULL;
+-	struct osc_object *obj   = cl2osc(ops->ops_cl.cpl_obj);
+-	struct cl_page    *cp    = ops->ops_cl.cpl_page;
+-	pgoff_t	    index = cp->cp_index;
++	struct osc_extent *ext = NULL;
++	struct osc_object *obj = cl2osc(ops->ops_cl.cpl_obj);
++	struct cl_page *cp = ops->ops_cl.cpl_page;
++	pgoff_t	index = cp->cp_index;
+ 	struct osc_async_page *oap = &ops->ops_oap;
+ 	bool unplug = false;
+ 	int rc = 0;
+@@ -2507,14 +2507,14 @@ int osc_flush_async_page(const struct lu_env *env, struct cl_io *io,
+ int osc_cancel_async_page(const struct lu_env *env, struct osc_page *ops)
+ {
+ 	struct osc_async_page *oap = &ops->ops_oap;
+-	struct osc_object     *obj = oap->oap_obj;
+-	struct client_obd     *cli = osc_cli(obj);
+-	struct osc_extent     *ext;
+-	struct osc_extent     *found = NULL;
+-	struct list_head	    *plist;
++	struct osc_object *obj = oap->oap_obj;
++	struct client_obd *cli = osc_cli(obj);
++	struct osc_extent *ext;
++	struct osc_extent *found = NULL;
++	struct list_head *plist;
+ 	pgoff_t index = oap2cl_page(oap)->cp_index;
+-	int     rc = -EBUSY;
+-	int     cmd;
++	int rc = -EBUSY;
++	int cmd;
+ 
+ 	LASSERT(!oap->oap_interrupted);
+ 	oap->oap_interrupted = 1;
+@@ -2523,10 +2523,10 @@ int osc_cancel_async_page(const struct lu_env *env, struct osc_page *ops)
+ 	osc_object_lock(obj);
+ 	if (oap->oap_cmd & OBD_BRW_WRITE) {
+ 		plist = &obj->oo_urgent_exts;
+-		cmd   = OBD_BRW_WRITE;
++		cmd = OBD_BRW_WRITE;
+ 	} else {
+ 		plist = &obj->oo_reading_exts;
+-		cmd   = OBD_BRW_READ;
++		cmd = OBD_BRW_READ;
+ 	}
+ 	list_for_each_entry(ext, plist, oe_link) {
+ 		if (ext->oe_start <= index && ext->oe_end >= index) {
+@@ -2564,13 +2564,13 @@ int osc_cancel_async_page(const struct lu_env *env, struct osc_page *ops)
+ int osc_queue_sync_pages(const struct lu_env *env, struct osc_object *obj,
+ 			 struct list_head *list, int cmd, int brw_flags)
+ {
+-	struct client_obd     *cli = osc_cli(obj);
+-	struct osc_extent     *ext;
++	struct client_obd *cli = osc_cli(obj);
++	struct osc_extent *ext;
+ 	struct osc_async_page *oap, *tmp;
+-	int     page_count = 0;
+-	int     mppr       = cli->cl_max_pages_per_rpc;
+-	pgoff_t start      = CL_PAGE_EOF;
+-	pgoff_t end	= 0;
++	int page_count = 0;
++	int mppr = cli->cl_max_pages_per_rpc;
++	pgoff_t start = CL_PAGE_EOF;
++	pgoff_t end = 0;
+ 
+ 	list_for_each_entry(oap, list, oap_pending_item) {
+ 		struct cl_page *cp = oap2cl_page(oap);
+@@ -2785,7 +2785,7 @@ int osc_cache_wait_range(const struct lu_env *env, struct osc_object *obj,
+ {
+ 	struct osc_extent *ext;
+ 	pgoff_t index = start;
+-	int     result = 0;
++	int result = 0;
+ 
+ again:
+ 	osc_object_lock(obj);
+diff --git a/drivers/staging/lustre/lustre/osc/osc_dev.c b/drivers/staging/lustre/lustre/osc/osc_dev.c
+index ce5c3af1237b..9222c9f4faae 100644
+--- a/drivers/staging/lustre/lustre/osc/osc_dev.c
++++ b/drivers/staging/lustre/lustre/osc/osc_dev.c
+@@ -118,7 +118,7 @@ static struct lu_device *osc2lu_dev(struct osc_device *osc)
+  */
+ 
+ static void *osc_key_init(const struct lu_context *ctx,
+-			 struct lu_context_key *key)
++			  struct lu_context_key *key)
+ {
+ 	struct osc_thread_info *info;
+ 
+@@ -248,14 +248,14 @@ static const struct lu_device_type_operations osc_device_type_ops = {
+ 	.ldto_device_alloc = osc_device_alloc,
+ 	.ldto_device_free  = osc_device_free,
+ 
+-	.ldto_device_init    = osc_device_init,
+-	.ldto_device_fini    = osc_device_fini
++	.ldto_device_init = osc_device_init,
++	.ldto_device_fini = osc_device_fini
+ };
+ 
+ struct lu_device_type osc_device_type = {
+-	.ldt_tags     = LU_DEVICE_CL,
+-	.ldt_name     = LUSTRE_OSC_NAME,
+-	.ldt_ops      = &osc_device_type_ops,
++	.ldt_tags = LU_DEVICE_CL,
++	.ldt_name = LUSTRE_OSC_NAME,
++	.ldt_ops = &osc_device_type_ops,
+ 	.ldt_ctx_tags = LCT_CL_THREAD
+ };
+ 
+diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c
+index 3c7300b0651d..fa24e9ed1831 100644
+--- a/drivers/staging/lustre/lustre/osc/osc_io.c
++++ b/drivers/staging/lustre/lustre/osc/osc_io.c
+@@ -100,16 +100,16 @@ static int osc_io_submit(const struct lu_env *env,
+ 			 const struct cl_io_slice *ios,
+ 			 enum cl_req_type crt, struct cl_2queue *queue)
+ {
+-	struct cl_page    *page;
+-	struct cl_page    *tmp;
+-	struct client_obd *cli  = NULL;
+-	struct osc_object *osc  = NULL; /* to keep gcc happy */
+-	struct osc_page   *opg;
+-	struct cl_io      *io;
++	struct cl_page *page;
++	struct cl_page *tmp;
++	struct client_obd *cli = NULL;
++	struct osc_object *osc = NULL; /* to keep gcc happy */
++	struct osc_page *opg;
++	struct cl_io *io;
+ 	LIST_HEAD(list);
+ 
+-	struct cl_page_list *qin      = &queue->c2_qin;
+-	struct cl_page_list *qout     = &queue->c2_qout;
++	struct cl_page_list *qin = &queue->c2_qin;
++	struct cl_page_list *qout = &queue->c2_qout;
+ 	int queued = 0;
+ 	int result = 0;
+ 	int cmd;
+@@ -189,8 +189,8 @@ static int osc_io_submit(const struct lu_env *env,
+ static void osc_page_touch_at(const struct lu_env *env,
+ 			      struct cl_object *obj, pgoff_t idx, unsigned to)
+ {
+-	struct lov_oinfo  *loi  = cl2osc(obj)->oo_oinfo;
+-	struct cl_attr    *attr = &osc_env_info(env)->oti_attr;
++	struct lov_oinfo *loi = cl2osc(obj)->oo_oinfo;
++	struct cl_attr *attr = &osc_env_info(env)->oti_attr;
+ 	int valid;
+ 	__u64 kms;
+ 
+@@ -233,8 +233,8 @@ static void osc_page_touch_at(const struct lu_env *env,
+ static void osc_page_touch(const struct lu_env *env,
+ 			   struct osc_page *opage, unsigned to)
+ {
+-	struct cl_page    *page = opage->ops_cl.cpl_page;
+-	struct cl_object  *obj  = opage->ops_cl.cpl_obj;
++	struct cl_page *page = opage->ops_cl.cpl_page;
++	struct cl_object *obj = opage->ops_cl.cpl_obj;
+ 
+ 	osc_page_touch_at(env, obj, page->cp_index, to);
+ }
+@@ -260,7 +260,7 @@ static int osc_io_prepare_write(const struct lu_env *env,
+ {
+ 	struct osc_device *dev = lu2osc_dev(slice->cpl_obj->co_lu.lo_dev);
+ 	struct obd_import *imp = class_exp2cliimp(dev->od_exp);
+-	struct osc_io     *oio = cl2osc_io(env, ios);
++	struct osc_io *oio = cl2osc_io(env, ios);
+ 	int result = 0;
+ 
+ 	/*
+@@ -284,9 +284,9 @@ static int osc_io_commit_write(const struct lu_env *env,
+ 			       const struct cl_page_slice *slice,
+ 			       unsigned from, unsigned to)
+ {
+-	struct osc_io	 *oio = cl2osc_io(env, ios);
+-	struct osc_page       *opg = cl2osc_page(slice);
+-	struct osc_object     *obj = cl2osc(opg->ops_cl.cpl_obj);
++	struct osc_io *oio = cl2osc_io(env, ios);
++	struct osc_page *opg = cl2osc_page(slice);
++	struct osc_object *obj = cl2osc(opg->ops_cl.cpl_obj);
+ 	struct osc_async_page *oap = &opg->ops_oap;
+ 
+ 	LASSERT(to > 0);
+@@ -311,10 +311,10 @@ static int osc_io_commit_write(const struct lu_env *env,
+ static int osc_io_fault_start(const struct lu_env *env,
+ 			      const struct cl_io_slice *ios)
+ {
+-	struct cl_io       *io;
++	struct cl_io *io;
+ 	struct cl_fault_io *fio;
+ 
+-	io  = ios->cis_io;
++	io = ios->cis_io;
+ 	fio = &io->u.ci_fault;
+ 	CDEBUG(D_INFO, "%lu %d %d\n",
+ 	       fio->ft_index, fio->ft_writable, fio->ft_nob);
+@@ -375,11 +375,11 @@ static void osc_trunc_check(const struct lu_env *env, struct cl_io *io,
+ 			    struct osc_io *oio, __u64 size)
+ {
+ 	struct cl_object *clob;
+-	int     partial;
++	int partial;
+ 	pgoff_t start;
+ 
+-	clob    = oio->oi_cl.cis_obj;
+-	start   = cl_index(clob, size);
++	clob = oio->oi_cl.cis_obj;
++	start = cl_index(clob, size);
+ 	partial = cl_offset(clob, start) < size;
+ 
+ 	/*
+@@ -392,17 +392,17 @@ static void osc_trunc_check(const struct lu_env *env, struct cl_io *io,
+ static int osc_io_setattr_start(const struct lu_env *env,
+ 				const struct cl_io_slice *slice)
+ {
+-	struct cl_io	    *io     = slice->cis_io;
+-	struct osc_io	   *oio    = cl2osc_io(env, slice);
+-	struct cl_object	*obj    = slice->cis_obj;
+-	struct lov_oinfo	*loi    = cl2osc(obj)->oo_oinfo;
+-	struct cl_attr	  *attr   = &osc_env_info(env)->oti_attr;
+-	struct obdo	     *oa     = &oio->oi_oa;
++	struct cl_io *io = slice->cis_io;
++	struct osc_io *oio = cl2osc_io(env, slice);
++	struct cl_object *obj = slice->cis_obj;
++	struct lov_oinfo *loi = cl2osc(obj)->oo_oinfo;
++	struct cl_attr *attr = &osc_env_info(env)->oti_attr;
++	struct obdo *oa = &oio->oi_oa;
+ 	struct osc_async_cbargs *cbargs = &oio->oi_cbarg;
+-	__u64		    size   = io->u.ci_setattr.sa_attr.lvb_size;
+-	unsigned int	     ia_valid = io->u.ci_setattr.sa_valid;
+-	int		      result = 0;
+-	struct obd_info	  oinfo = { { { 0 } } };
++	__u64 size = io->u.ci_setattr.sa_attr.lvb_size;
++	unsigned int ia_valid = io->u.ci_setattr.sa_valid;
++	int result = 0;
++	struct obd_info oinfo = { { { 0 } } };
+ 
+ 	/* truncate cache dirty pages first */
+ 	if (cl_io_is_trunc(io))
+@@ -477,8 +477,8 @@ static int osc_io_setattr_start(const struct lu_env *env,
+ static void osc_io_setattr_end(const struct lu_env *env,
+ 			       const struct cl_io_slice *slice)
+ {
+-	struct cl_io     *io  = slice->cis_io;
+-	struct osc_io    *oio = cl2osc_io(env, slice);
++	struct cl_io *io = slice->cis_io;
++	struct osc_io *oio = cl2osc_io(env, slice);
+ 	struct cl_object *obj = slice->cis_obj;
+ 	struct osc_async_cbargs *cbargs = &oio->oi_cbarg;
+ 	int result = 0;
+@@ -512,8 +512,8 @@ static void osc_io_setattr_end(const struct lu_env *env,
+ static int osc_io_read_start(const struct lu_env *env,
+ 			     const struct cl_io_slice *slice)
+ {
+-	struct cl_object *obj   = slice->cis_obj;
+-	struct cl_attr   *attr  = &osc_env_info(env)->oti_attr;
++	struct cl_object *obj = slice->cis_obj;
++	struct cl_attr *attr = &osc_env_info(env)->oti_attr;
+ 	int rc = 0;
+ 
+ 	if (!slice->cis_io->ci_noatime) {
+@@ -528,8 +528,8 @@ static int osc_io_read_start(const struct lu_env *env,
+ static int osc_io_write_start(const struct lu_env *env,
+ 			      const struct cl_io_slice *slice)
+ {
+-	struct cl_object *obj   = slice->cis_obj;
+-	struct cl_attr   *attr  = &osc_env_info(env)->oti_attr;
++	struct cl_object *obj = slice->cis_obj;
++	struct cl_attr *attr = &osc_env_info(env)->oti_attr;
+ 	int rc = 0;
+ 
+ 	OBD_FAIL_TIMEOUT(OBD_FAIL_OSC_DELAY_SETTIME, 1);
+@@ -544,10 +544,10 @@ static int osc_io_write_start(const struct lu_env *env,
+ static int osc_fsync_ost(const struct lu_env *env, struct osc_object *obj,
+ 			 struct cl_fsync_io *fio)
+ {
+-	struct osc_io    *oio   = osc_env_io(env);
+-	struct obdo      *oa    = &oio->oi_oa;
+-	struct obd_info  *oinfo = &oio->oi_info;
+-	struct lov_oinfo *loi   = obj->oo_oinfo;
++	struct osc_io *oio = osc_env_io(env);
++	struct obdo *oa = &oio->oi_oa;
++	struct obd_info *oinfo = &oio->oi_info;
++	struct lov_oinfo *loi = obj->oo_oinfo;
+ 	struct osc_async_cbargs *cbargs = &oio->oi_cbarg;
+ 	int rc = 0;
+ 
+@@ -575,13 +575,13 @@ static int osc_fsync_ost(const struct lu_env *env, struct osc_object *obj,
+ static int osc_io_fsync_start(const struct lu_env *env,
+ 			      const struct cl_io_slice *slice)
+ {
+-	struct cl_io       *io  = slice->cis_io;
++	struct cl_io *io = slice->cis_io;
+ 	struct cl_fsync_io *fio = &io->u.ci_fsync;
+-	struct cl_object   *obj = slice->cis_obj;
+-	struct osc_object  *osc = cl2osc(obj);
+-	pgoff_t start  = cl_index(obj, fio->fi_start);
+-	pgoff_t end    = cl_index(obj, fio->fi_end);
+-	int     result = 0;
++	struct cl_object *obj = slice->cis_obj;
++	struct osc_object *osc = cl2osc(obj);
++	pgoff_t start = cl_index(obj, fio->fi_start);
++	pgoff_t end = cl_index(obj, fio->fi_end);
++	int result = 0;
+ 
+ 	if (fio->fi_end == OBD_OBJECT_EOF)
+ 		end = CL_PAGE_EOF;
+@@ -615,15 +615,15 @@ static void osc_io_fsync_end(const struct lu_env *env,
+ 			     const struct cl_io_slice *slice)
+ {
+ 	struct cl_fsync_io *fio = &slice->cis_io->u.ci_fsync;
+-	struct cl_object   *obj = slice->cis_obj;
++	struct cl_object *obj = slice->cis_obj;
+ 	pgoff_t start = cl_index(obj, fio->fi_start);
+-	pgoff_t end   = cl_index(obj, fio->fi_end);
++	pgoff_t end = cl_index(obj, fio->fi_end);
+ 	int result = 0;
+ 
+ 	if (fio->fi_mode == CL_FSYNC_LOCAL) {
+ 		result = osc_cache_wait_range(env, cl2osc(obj), start, end);
+ 	} else if (fio->fi_mode == CL_FSYNC_ALL) {
+-		struct osc_io	   *oio    = cl2osc_io(env, slice);
++		struct osc_io *oio = cl2osc_io(env, slice);
+ 		struct osc_async_cbargs *cbargs = &oio->oi_cbarg;
+ 
+ 		wait_for_completion(&cbargs->opc_sync);
+@@ -717,17 +717,17 @@ static void osc_req_attr_set(const struct lu_env *env,
+ 			     struct cl_req_attr *attr, u64 flags)
+ {
+ 	struct lov_oinfo *oinfo;
+-	struct cl_req    *clerq;
+-	struct cl_page   *apage; /* _some_ page in @clerq */
+-	struct cl_lock   *lock;  /* _some_ lock protecting @apage */
+-	struct osc_lock  *olck;
+-	struct osc_page  *opg;
+-	struct obdo      *oa;
+-	struct ost_lvb   *lvb;
+-
+-	oinfo	= cl2osc(obj)->oo_oinfo;
+-	lvb	= &oinfo->loi_lvb;
+-	oa	= attr->cra_oa;
++	struct cl_req *clerq;
++	struct cl_page *apage; /* _some_ page in @clerq */
++	struct cl_lock *lock;  /* _some_ lock protecting @apage */
++	struct osc_lock *olck;
++	struct osc_page *opg;
++	struct obdo *oa;
++	struct ost_lvb *lvb;
++
++	oinfo = cl2osc(obj)->oo_oinfo;
++	lvb = &oinfo->loi_lvb;
++	oa = attr->cra_oa;
+ 
+ 	if ((flags & OBD_MD_FLMTIME) != 0) {
+ 		oa->o_mtime = lvb->lvb_mtime;
+@@ -759,7 +759,7 @@ static void osc_req_attr_set(const struct lu_env *env,
+ 		lock = cl_lock_at_page(env, apage->cp_obj, apage, NULL, 1, 1);
+ 		if (lock == NULL) {
+ 			struct cl_object_header *head;
+-			struct cl_lock	  *scan;
++			struct cl_lock *scan;
+ 
+ 			head = cl_object_header(apage->cp_obj);
+ 			list_for_each_entry(scan, &head->coh_locks,
+diff --git a/drivers/staging/lustre/lustre/osc/osc_lock.c b/drivers/staging/lustre/lustre/osc/osc_lock.c
+index 350ad49550ab..06837f5f4e64 100644
+--- a/drivers/staging/lustre/lustre/osc/osc_lock.c
++++ b/drivers/staging/lustre/lustre/osc/osc_lock.c
+@@ -89,9 +89,9 @@ static struct ldlm_lock *osc_handle_ptr(struct lustre_handle *handle)
+  */
+ static int osc_lock_invariant(struct osc_lock *ols)
+ {
+-	struct ldlm_lock *lock	      = osc_handle_ptr(&ols->ols_handle);
+-	struct ldlm_lock *olock	      = ols->ols_lock;
+-	int		  handle_used = lustre_handle_is_used(&ols->ols_handle);
++	struct ldlm_lock *lock = osc_handle_ptr(&ols->ols_handle);
++	struct ldlm_lock *olock = ols->ols_lock;
++	int handle_used = lustre_handle_is_used(&ols->ols_handle);
+ 
+ 	if (ergo(osc_lock_is_lockless(ols),
+ 		 ols->ols_locklessable && ols->ols_lock == NULL))
+@@ -164,7 +164,7 @@ static void osc_lock_detach(const struct lu_env *env, struct osc_lock *olck)
+ 	lock_res_and_lock(dlmlock);
+ 	if (dlmlock->l_granted_mode == dlmlock->l_req_mode) {
+ 		struct cl_object *obj = olck->ols_cl.cls_obj;
+-		struct cl_attr *attr  = &osc_env_info(env)->oti_attr;
++		struct cl_attr *attr = &osc_env_info(env)->oti_attr;
+ 		__u64 old_kms;
+ 
+ 		cl_object_attr_lock(obj);
+@@ -237,7 +237,7 @@ static int osc_lock_unuse(const struct lu_env *env,
+ static void osc_lock_fini(const struct lu_env *env,
+ 			  struct cl_lock_slice *slice)
+ {
+-	struct osc_lock  *ols = cl2osc_lock(slice);
++	struct osc_lock *ols = cl2osc_lock(slice);
+ 
+ 	LINVRNT(osc_lock_invariant(ols));
+ 	/*
+@@ -337,25 +337,25 @@ static void osc_ast_data_put(const struct lu_env *env, struct osc_lock *olck)
+ static void osc_lock_lvb_update(const struct lu_env *env, struct osc_lock *olck,
+ 				int rc)
+ {
+-	struct ost_lvb    *lvb;
+-	struct cl_object  *obj;
+-	struct lov_oinfo  *oinfo;
+-	struct cl_attr    *attr;
+-	unsigned	   valid;
++	struct ost_lvb *lvb;
++	struct cl_object *obj;
++	struct lov_oinfo *oinfo;
++	struct cl_attr *attr;
++	unsigned valid;
+ 
+ 	if (!(olck->ols_flags & LDLM_FL_LVB_READY))
+ 		return;
+ 
+-	lvb   = &olck->ols_lvb;
+-	obj   = olck->ols_cl.cls_obj;
++	lvb = &olck->ols_lvb;
++	obj = olck->ols_cl.cls_obj;
+ 	oinfo = cl2osc(obj)->oo_oinfo;
+-	attr  = &osc_env_info(env)->oti_attr;
++	attr = &osc_env_info(env)->oti_attr;
+ 	valid = CAT_BLOCKS | CAT_ATIME | CAT_CTIME | CAT_MTIME | CAT_SIZE;
+ 	cl_lvb2attr(attr, lvb);
+ 
+ 	cl_object_attr_lock(obj);
+ 	if (rc == 0) {
+-		struct ldlm_lock  *dlmlock;
++		struct ldlm_lock *dlmlock;
+ 		__u64 size;
+ 
+ 		dlmlock = olck->ols_lock;
+@@ -401,23 +401,23 @@ static void osc_lock_lvb_update(const struct lu_env *env, struct osc_lock *olck,
+ static void osc_lock_granted(const struct lu_env *env, struct osc_lock *olck,
+ 			     struct ldlm_lock *dlmlock, int rc)
+ {
+-	struct ldlm_extent   *ext;
+-	struct cl_lock       *lock;
++	struct ldlm_extent *ext;
++	struct cl_lock *lock;
+ 	struct cl_lock_descr *descr;
+ 
+ 	LASSERT(dlmlock->l_granted_mode == dlmlock->l_req_mode);
+ 
+ 	if (olck->ols_state < OLS_GRANTED) {
+-		lock  = olck->ols_cl.cls_lock;
+-		ext   = &dlmlock->l_policy_data.l_extent;
++		lock = olck->ols_cl.cls_lock;
++		ext = &dlmlock->l_policy_data.l_extent;
+ 		descr = &osc_env_info(env)->oti_descr;
+ 		descr->cld_obj = lock->cll_descr.cld_obj;
+ 
+ 		/* XXX check that ->l_granted_mode is valid. */
+-		descr->cld_mode  = osc_ldlm2cl_lock(dlmlock->l_granted_mode);
++		descr->cld_mode = osc_ldlm2cl_lock(dlmlock->l_granted_mode);
+ 		descr->cld_start = cl_index(descr->cld_obj, ext->start);
+-		descr->cld_end   = cl_index(descr->cld_obj, ext->end);
+-		descr->cld_gid   = ext->gid;
++		descr->cld_end = cl_index(descr->cld_obj, ext->end);
++		descr->cld_gid = ext->gid;
+ 		/*
+ 		 * tell upper layers the extent of the lock that was actually
+ 		 * granted
+@@ -482,11 +482,11 @@ static void osc_lock_upcall0(const struct lu_env *env, struct osc_lock *olck)
+  */
+ static int osc_lock_upcall(void *cookie, int errcode)
+ {
+-	struct osc_lock	 *olck  = cookie;
+-	struct cl_lock_slice    *slice = &olck->ols_cl;
+-	struct cl_lock	  *lock  = slice->cls_lock;
+-	struct lu_env	   *env;
+-	struct cl_env_nest       nest;
++	struct osc_lock	*olck = cookie;
++	struct cl_lock_slice *slice = &olck->ols_cl;
++	struct cl_lock *lock = slice->cls_lock;
++	struct lu_env *env;
++	struct cl_env_nest nest;
+ 
+ 	env = cl_env_nested_get(&nest);
+ 	if (!IS_ERR(env)) {
+@@ -626,7 +626,7 @@ static int osc_dlm_blocking_ast0(const struct lu_env *env,
+ 				 void *data, int flag)
+ {
+ 	struct osc_lock *olck;
+-	struct cl_lock  *lock;
++	struct cl_lock *lock;
+ 	int result;
+ 	int cancel;
+ 
+@@ -733,9 +733,9 @@ static int osc_ldlm_blocking_ast(struct ldlm_lock *dlmlock,
+ 				 struct ldlm_lock_desc *new, void *data,
+ 				 int flag)
+ {
+-	struct lu_env     *env;
++	struct lu_env *env;
+ 	struct cl_env_nest nest;
+-	int		result;
++	int result;
+ 
+ 	/*
+ 	 * This can be called in the context of outer IO, e.g.,
+@@ -774,9 +774,9 @@ static int osc_ldlm_completion_ast(struct ldlm_lock *dlmlock,
+ 				   __u64 flags, void *data)
+ {
+ 	struct cl_env_nest nest;
+-	struct lu_env     *env;
+-	struct osc_lock   *olck;
+-	struct cl_lock    *lock;
++	struct lu_env *env;
++	struct osc_lock *olck;
++	struct cl_lock *lock;
+ 	int result;
+ 	int dlmrc;
+ 
+@@ -830,15 +830,15 @@ static int osc_ldlm_completion_ast(struct ldlm_lock *dlmlock,
+ 
+ static int osc_ldlm_glimpse_ast(struct ldlm_lock *dlmlock, void *data)
+ {
+-	struct ptlrpc_request  *req  = data;
++	struct ptlrpc_request *req = data;
+ 	struct osc_lock	*olck;
+-	struct cl_lock	 *lock;
+-	struct cl_object       *obj;
+-	struct cl_env_nest      nest;
+-	struct lu_env	  *env;
+-	struct ost_lvb	 *lvb;
+-	struct req_capsule     *cap;
+-	int		     result;
++	struct cl_lock *lock;
++	struct cl_object *obj;
++	struct cl_env_nest nest;
++	struct lu_env *env;
++	struct ost_lvb *lvb;
++	struct req_capsule *cap;
++	int result;
+ 
+ 	LASSERT(lustre_msg_get_opc(req->rq_reqmsg) == LDLM_GL_CALLBACK);
+ 
+@@ -916,11 +916,11 @@ static void osc_lock_build_einfo(const struct lu_env *env,
+ 		 */
+ 		mode = CLM_READ;
+ 
+-	einfo->ei_type   = LDLM_EXTENT;
+-	einfo->ei_mode   = osc_cl_lock2ldlm(mode);
+-	einfo->ei_cb_bl  = osc_ldlm_blocking_ast;
+-	einfo->ei_cb_cp  = osc_ldlm_completion_ast;
+-	einfo->ei_cb_gl  = osc_ldlm_glimpse_ast;
++	einfo->ei_type = LDLM_EXTENT;
++	einfo->ei_mode = osc_cl_lock2ldlm(mode);
++	einfo->ei_cb_bl = osc_ldlm_blocking_ast;
++	einfo->ei_cb_cp = osc_ldlm_completion_ast;
++	einfo->ei_cb_gl = osc_ldlm_glimpse_ast;
+ 	einfo->ei_cbdata = lock; /* value to be put into ->l_ast_data */
+ }
+ 
+@@ -948,9 +948,9 @@ static void osc_lock_to_lockless(const struct lu_env *env,
+ 		ols->ols_locklessable = 1;
+ 		slice->cls_ops = &osc_lock_lockless_ops;
+ 	} else {
+-		struct osc_io *oio     = osc_env_io(env);
+-		struct cl_io  *io      = oio->oi_cl.cis_io;
+-		struct cl_object *obj  = slice->cls_obj;
++		struct osc_io *oio = osc_env_io(env);
++		struct cl_io *io = oio->oi_cl.cis_io;
++		struct cl_object *obj = slice->cls_obj;
+ 		struct osc_object *oob = cl2osc(obj);
+ 		const struct osc_device *osd = lu2osc_dev(obj->co_lu.lo_dev);
+ 		struct obd_connect_data *ocd;
+@@ -1006,13 +1006,13 @@ static int osc_lock_compatible(const struct osc_lock *qing,
+ static int osc_lock_enqueue_wait(const struct lu_env *env,
+ 				 const struct osc_lock *olck)
+ {
+-	struct cl_lock	  *lock    = olck->ols_cl.cls_lock;
+-	struct cl_lock_descr    *descr   = &lock->cll_descr;
+-	struct cl_object_header *hdr     = cl_object_header(descr->cld_obj);
+-	struct cl_lock	  *scan;
+-	struct cl_lock	  *conflict = NULL;
+-	int lockless		     = osc_lock_is_lockless(olck);
+-	int rc			   = 0;
++	struct cl_lock *lock = olck->ols_cl.cls_lock;
++	struct cl_lock_descr *descr = &lock->cll_descr;
++	struct cl_object_header *hdr = cl_object_header(descr->cld_obj);
++	struct cl_lock *scan;
++	struct cl_lock *conflict = NULL;
++	int lockless = osc_lock_is_lockless(olck);
++	int rc = 0;
+ 
+ 	LASSERT(cl_lock_is_mutexed(lock));
+ 
+@@ -1102,8 +1102,8 @@ static int osc_lock_enqueue(const struct lu_env *env,
+ 			    const struct cl_lock_slice *slice,
+ 			    struct cl_io *unused, __u32 enqflags)
+ {
+-	struct osc_lock	  *ols     = cl2osc_lock(slice);
+-	struct cl_lock	   *lock    = ols->ols_cl.cls_lock;
++	struct osc_lock *ols = cl2osc_lock(slice);
++	struct cl_lock *lock = ols->ols_cl.cls_lock;
+ 	int result;
+ 
+ 	LASSERT(cl_lock_is_mutexed(lock));
+@@ -1116,10 +1116,10 @@ static int osc_lock_enqueue(const struct lu_env *env,
+ 	result = osc_lock_enqueue_wait(env, ols);
+ 	if (result == 0) {
+ 		if (!osc_lock_is_lockless(ols)) {
+-			struct osc_object	*obj = cl2osc(slice->cls_obj);
+-			struct osc_thread_info   *info = osc_env_info(env);
+-			struct ldlm_res_id       *resname = &info->oti_resname;
+-			ldlm_policy_data_t       *policy = &info->oti_policy;
++			struct osc_object *obj = cl2osc(slice->cls_obj);
++			struct osc_thread_info *info = osc_env_info(env);
++			struct ldlm_res_id *resname = &info->oti_resname;
++			ldlm_policy_data_t *policy = &info->oti_policy;
+ 			struct ldlm_enqueue_info *einfo = &ols->ols_einfo;
+ 
+ 			/* lock will be passed as upcall cookie,
+@@ -1164,7 +1164,7 @@ static int osc_lock_wait(const struct lu_env *env,
+ 			 const struct cl_lock_slice *slice)
+ {
+ 	struct osc_lock *olck = cl2osc_lock(slice);
+-	struct cl_lock  *lock = olck->ols_cl.cls_lock;
++	struct cl_lock *lock = olck->ols_cl.cls_lock;
+ 
+ 	LINVRNT(osc_lock_invariant(olck));
+ 
+@@ -1245,14 +1245,14 @@ static int osc_lock_use(const struct lu_env *env,
+ 
+ static int osc_lock_flush(struct osc_lock *ols, int discard)
+ {
+-	struct cl_lock       *lock  = ols->ols_cl.cls_lock;
+-	struct cl_env_nest    nest;
+-	struct lu_env	*env;
++	struct cl_lock *lock = ols->ols_cl.cls_lock;
++	struct cl_env_nest nest;
++	struct lu_env *env;
+ 	int result = 0;
+ 
+ 	env = cl_env_nested_get(&nest);
+ 	if (!IS_ERR(env)) {
+-		struct osc_object    *obj   = cl2osc(ols->ols_cl.cls_obj);
++		struct osc_object *obj = cl2osc(ols->ols_cl.cls_obj);
+ 		struct cl_lock_descr *descr = &lock->cll_descr;
+ 		int rc = 0;
+ 
+@@ -1298,11 +1298,11 @@ static int osc_lock_flush(struct osc_lock *ols, int discard)
+ static void osc_lock_cancel(const struct lu_env *env,
+ 			    const struct cl_lock_slice *slice)
+ {
+-	struct cl_lock   *lock    = slice->cls_lock;
+-	struct osc_lock  *olck    = cl2osc_lock(slice);
++	struct cl_lock *lock = slice->cls_lock;
++	struct osc_lock *olck = cl2osc_lock(slice);
+ 	struct ldlm_lock *dlmlock = olck->ols_lock;
+-	int	       result  = 0;
+-	int	       discard;
++	int result = 0;
++	int discard;
+ 
+ 	LASSERT(cl_lock_is_mutexed(lock));
+ 	LINVRNT(osc_lock_invariant(olck));
+@@ -1482,7 +1482,7 @@ static int osc_lock_lockless_unuse(const struct lu_env *env,
+ static void osc_lock_lockless_cancel(const struct lu_env *env,
+ 				     const struct cl_lock_slice *slice)
+ {
+-	struct osc_lock   *ols  = cl2osc_lock(slice);
++	struct osc_lock *ols = cl2osc_lock(slice);
+ 	int result;
+ 
+ 	result = osc_lock_flush(ols, 0);
+@@ -1496,7 +1496,7 @@ static int osc_lock_lockless_wait(const struct lu_env *env,
+ 				  const struct cl_lock_slice *slice)
+ {
+ 	struct osc_lock *olck = cl2osc_lock(slice);
+-	struct cl_lock  *lock = olck->ols_cl.cls_lock;
++	struct cl_lock *lock = olck->ols_cl.cls_lock;
+ 
+ 	LINVRNT(osc_lock_invariant(olck));
+ 	LASSERT(olck->ols_state >= OLS_UPCALL_RECEIVED);
+@@ -1512,7 +1512,7 @@ static void osc_lock_lockless_state(const struct lu_env *env,
+ 
+ 	LINVRNT(osc_lock_invariant(lock));
+ 	if (state == CLS_HELD) {
+-		struct osc_io *oio  = osc_env_io(env);
++		struct osc_io *oio = osc_env_io(env);
+ 
+ 		LASSERT(ergo(lock->ols_owner, lock->ols_owner == oio));
+ 		lock->ols_owner = oio;
+@@ -1591,7 +1591,7 @@ int osc_lock_init(const struct lu_env *env,
+ int osc_dlm_lock_pageref(struct ldlm_lock *dlm)
+ {
+ 	struct osc_lock *olock;
+-	int	      rc = 0;
++	int rc = 0;
+ 
+ 	spin_lock(&osc_ast_guard);
+ 	olock = dlm->l_ast_data;
+diff --git a/drivers/staging/lustre/lustre/osc/osc_object.c b/drivers/staging/lustre/lustre/osc/osc_object.c
+index 92c202f70395..c628a250ebd6 100644
+--- a/drivers/staging/lustre/lustre/osc/osc_object.c
++++ b/drivers/staging/lustre/lustre/osc/osc_object.c
+@@ -72,7 +72,7 @@ static struct osc_object *lu2osc(const struct lu_object *obj)
+ static int osc_object_init(const struct lu_env *env, struct lu_object *obj,
+ 			   const struct lu_object_conf *conf)
+ {
+-	struct osc_object	   *osc   = lu2osc(obj);
++	struct osc_object *osc = lu2osc(obj);
+ 	const struct cl_object_conf *cconf = lu2cl_conf(conf);
+ 	int i;
+ 
+@@ -136,9 +136,9 @@ int osc_lvb_print(const struct lu_env *env, void *cookie,
+ static int osc_object_print(const struct lu_env *env, void *cookie,
+ 			    lu_printer_t p, const struct lu_object *obj)
+ {
+-	struct osc_object   *osc   = lu2osc(obj);
+-	struct lov_oinfo    *oinfo = osc->oo_oinfo;
+-	struct osc_async_rc *ar    = &oinfo->loi_ar;
++	struct osc_object *osc = lu2osc(obj);
++	struct lov_oinfo *oinfo = osc->oo_oinfo;
++	struct osc_async_rc *ar = &oinfo->loi_ar;
+ 
+ 	(*p)(env, cookie, "id: " DOSTID " idx: %d gen: %d kms_valid: %u kms %llu rc: %d force_sync: %d min_xid: %llu ",
+ 	     POSTID(&oinfo->loi_oi), oinfo->loi_ost_idx,
+@@ -163,7 +163,7 @@ int osc_attr_set(const struct lu_env *env, struct cl_object *obj,
+ 		 const struct cl_attr *attr, unsigned valid)
+ {
+ 	struct lov_oinfo *oinfo = cl2osc(obj)->oo_oinfo;
+-	struct ost_lvb   *lvb   = &oinfo->loi_lvb;
++	struct ost_lvb *lvb = &oinfo->loi_lvb;
+ 
+ 	if (valid & CAT_SIZE)
+ 		lvb->lvb_size = attr->cat_size;
+@@ -188,7 +188,7 @@ static int osc_object_glimpse(const struct lu_env *env,
+ {
+ 	struct lov_oinfo *oinfo = cl2osc(obj)->oo_oinfo;
+ 
+-	lvb->lvb_size   = oinfo->loi_kms;
++	lvb->lvb_size = oinfo->loi_kms;
+ 	lvb->lvb_blocks = oinfo->loi_lvb.lvb_blocks;
+ 	return 0;
+ }
+@@ -208,9 +208,9 @@ void osc_object_clear_contended(struct osc_object *obj)
+ 
+ int osc_object_is_contended(struct osc_object *obj)
+ {
+-	struct osc_device *dev  = lu2osc_dev(obj->oo_cl.co_lu.lo_dev);
++	struct osc_device *dev = lu2osc_dev(obj->oo_cl.co_lu.lo_dev);
+ 	int osc_contention_time = dev->od_contention_time;
+-	unsigned long cur_time     = cfs_time_current();
++	unsigned long cur_time = cfs_time_current();
+ 	unsigned long retry_time;
+ 
+ 	if (OBD_FAIL_CHECK(OBD_FAIL_OSC_OBJECT_CONTENTION))
+@@ -255,7 +255,7 @@ struct lu_object *osc_object_alloc(const struct lu_env *env,
+ 				   struct lu_device *dev)
+ {
+ 	struct osc_object *osc;
+-	struct lu_object  *obj;
++	struct lu_object *obj;
+ 
+ 	OBD_SLAB_ALLOC_PTR_GFP(osc, osc_object_kmem, GFP_NOFS);
+ 	if (osc != NULL) {
+diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c
+index 76ba58b09c5d..43dfa73dd3a6 100644
+--- a/drivers/staging/lustre/lustre/osc/osc_page.c
++++ b/drivers/staging/lustre/lustre/osc/osc_page.c
+@@ -216,7 +216,7 @@ static int osc_page_cache_add(const struct lu_env *env,
+ 			      const struct cl_page_slice *slice,
+ 			      struct cl_io *io)
+ {
+-	struct osc_io   *oio = osc_env_io(env);
++	struct osc_io *oio = osc_env_io(env);
+ 	struct osc_page *opg = cl2osc_page(slice);
+ 	int result;
+ 
+@@ -247,7 +247,7 @@ void osc_index2policy(ldlm_policy_data_t *policy, const struct cl_object *obj,
+ {
+ 	memset(policy, 0, sizeof(*policy));
+ 	policy->l_extent.start = cl_offset(obj, start);
+-	policy->l_extent.end   = cl_offset(obj, end + 1) - 1;
++	policy->l_extent.end = cl_offset(obj, end + 1) - 1;
+ }
+ 
+ static int osc_page_addref_lock(const struct lu_env *env,
+@@ -255,7 +255,7 @@ static int osc_page_addref_lock(const struct lu_env *env,
+ 				struct cl_lock *lock)
+ {
+ 	struct osc_lock *olock;
+-	int	      rc;
++	int rc;
+ 
+ 	LASSERT(opg->ops_lock == NULL);
+ 
+@@ -274,7 +274,7 @@ static int osc_page_addref_lock(const struct lu_env *env,
+ static void osc_page_putref_lock(const struct lu_env *env,
+ 				 struct osc_page *opg)
+ {
+-	struct cl_lock  *lock = opg->ops_lock;
++	struct cl_lock *lock = opg->ops_lock;
+ 	struct osc_lock *olock;
+ 
+ 	LASSERT(lock != NULL);
+@@ -291,7 +291,7 @@ static int osc_page_is_under_lock(const struct lu_env *env,
+ 				  struct cl_io *unused)
+ {
+ 	struct cl_lock *lock;
+-	int	     result = -ENODATA;
++	int result = -ENODATA;
+ 
+ 	lock = cl_lock_at_page(env, slice->cpl_obj, slice->cpl_page,
+ 			       NULL, 1, 0);
+@@ -317,7 +317,7 @@ static void osc_page_completion_read(const struct lu_env *env,
+ 				     const struct cl_page_slice *slice,
+ 				     int ioret)
+ {
+-	struct osc_page   *opg = cl2osc_page(slice);
++	struct osc_page *opg = cl2osc_page(slice);
+ 	struct osc_object *obj = cl2osc(opg->ops_cl.cpl_obj);
+ 
+ 	if (likely(opg->ops_lock))
+@@ -329,7 +329,7 @@ static void osc_page_completion_write(const struct lu_env *env,
+ 				      const struct cl_page_slice *slice,
+ 				      int ioret)
+ {
+-	struct osc_page   *opg = cl2osc_page(slice);
++	struct osc_page *opg = cl2osc_page(slice);
+ 	struct osc_object *obj = cl2osc(slice->cpl_obj);
+ 
+ 	osc_lru_add(osc_cli(obj), opg);
+@@ -364,10 +364,10 @@ static int osc_page_print(const struct lu_env *env,
+ 			  const struct cl_page_slice *slice,
+ 			  void *cookie, lu_printer_t printer)
+ {
+-	struct osc_page       *opg = cl2osc_page(slice);
++	struct osc_page *opg = cl2osc_page(slice);
+ 	struct osc_async_page *oap = &opg->ops_oap;
+-	struct osc_object     *obj = cl2osc(slice->cpl_obj);
+-	struct client_obd     *cli = &osc_export(obj)->exp_obd->u.cli;
++	struct osc_object *obj = cl2osc(slice->cpl_obj);
++	struct client_obd *cli = &osc_export(obj)->exp_obd->u.cli;
+ 
+ 	return (*printer)(env, cookie, LUSTRE_OSC_NAME "-page@%p: 1< %#x %d %u %s %s > 2< %llu %u %u %#x %#x | %p %p %p > 3< %s %p %d %lu %d > 4< %d %d %d %lu %s | %s %s %s %s > 5< %s %s %s %s | %d %s | %d %s %s>\n",
+ 			  opg,
+@@ -408,7 +408,7 @@ static int osc_page_print(const struct lu_env *env,
+ static void osc_page_delete(const struct lu_env *env,
+ 			    const struct cl_page_slice *slice)
+ {
+-	struct osc_page   *opg = cl2osc_page(slice);
++	struct osc_page *opg = cl2osc_page(slice);
+ 	struct osc_object *obj = cl2osc(opg->ops_cl.cpl_obj);
+ 	int rc;
+ 
+@@ -437,13 +437,13 @@ static void osc_page_delete(const struct lu_env *env,
+ void osc_page_clip(const struct lu_env *env, const struct cl_page_slice *slice,
+ 		   int from, int to)
+ {
+-	struct osc_page       *opg = cl2osc_page(slice);
++	struct osc_page *opg = cl2osc_page(slice);
+ 	struct osc_async_page *oap = &opg->ops_oap;
+ 
+ 	LINVRNT(osc_page_protected(env, opg, CLM_READ, 0));
+ 
+ 	opg->ops_from = from;
+-	opg->ops_to   = to;
++	opg->ops_to = to;
+ 	spin_lock(&oap->oap_lock);
+ 	oap->oap_async_flags |= ASYNC_COUNT_STABLE;
+ 	spin_unlock(&oap->oap_lock);
+@@ -502,11 +502,11 @@ int osc_page_init(const struct lu_env *env, struct cl_object *obj,
+ 		struct cl_page *page, struct page *vmpage)
+ {
+ 	struct osc_object *osc = cl2osc(obj);
+-	struct osc_page   *opg = cl_object_page_slice(obj, page);
++	struct osc_page *opg = cl_object_page_slice(obj, page);
+ 	int result;
+ 
+ 	opg->ops_from = 0;
+-	opg->ops_to   = PAGE_CACHE_SIZE;
++	opg->ops_to = PAGE_CACHE_SIZE;
+ 
+ 	result = osc_prep_async_page(osc, opg, vmpage,
+ 					cl_offset(obj, page->cp_index));
+@@ -540,7 +540,7 @@ void osc_page_submit(const struct lu_env *env, struct osc_page *opg,
+ 		     enum cl_req_type crt, int brw_flags)
+ {
+ 	struct osc_async_page *oap = &opg->ops_oap;
+-	struct osc_object     *obj = oap->oap_obj;
++	struct osc_object *obj = oap->oap_obj;
+ 
+ 	LINVRNT(osc_page_protected(env, opg,
+ 				   crt == CRT_WRITE ? CLM_WRITE : CLM_READ, 1));
+@@ -550,9 +550,9 @@ void osc_page_submit(const struct lu_env *env, struct osc_page *opg,
+ 	LASSERT(oap->oap_async_flags & ASYNC_READY);
+ 	LASSERT(oap->oap_async_flags & ASYNC_COUNT_STABLE);
+ 
+-	oap->oap_cmd       = crt == CRT_WRITE ? OBD_BRW_WRITE : OBD_BRW_READ;
+-	oap->oap_page_off  = opg->ops_from;
+-	oap->oap_count     = opg->ops_to - opg->ops_from;
++	oap->oap_cmd = crt == CRT_WRITE ? OBD_BRW_WRITE : OBD_BRW_READ;
++	oap->oap_page_off = opg->ops_from;
++	oap->oap_count = opg->ops_to - opg->ops_from;
+ 	oap->oap_brw_flags = OBD_BRW_SYNC | brw_flags;
+ 
+ 	if (!client_is_remote(osc_export(obj)) &&
+diff --git a/drivers/staging/lustre/lustre/osc/osc_quota.c b/drivers/staging/lustre/lustre/osc/osc_quota.c
+index 6690f149a04c..2ff253f458f8 100644
+--- a/drivers/staging/lustre/lustre/osc/osc_quota.c
++++ b/drivers/staging/lustre/lustre/osc/osc_quota.c
+@@ -232,7 +232,7 @@ int osc_quota_setup(struct obd_device *obd)
+ 
+ int osc_quota_cleanup(struct obd_device *obd)
+ {
+-	struct client_obd     *cli = &obd->u.cli;
++	struct client_obd *cli = &obd->u.cli;
+ 	int type;
+ 
+ 	for (type = 0; type < MAXQUOTAS; type++)
+@@ -245,8 +245,8 @@ int osc_quotactl(struct obd_device *unused, struct obd_export *exp,
+ 		 struct obd_quotactl *oqctl)
+ {
+ 	struct ptlrpc_request *req;
+-	struct obd_quotactl   *oqc;
+-	int		    rc;
++	struct obd_quotactl *oqc;
++	int rc;
+ 
+ 	req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
+ 					&RQF_OST_QUOTACTL, LUSTRE_OST_VERSION,
+@@ -285,10 +285,10 @@ int osc_quotactl(struct obd_device *unused, struct obd_export *exp,
+ int osc_quotacheck(struct obd_device *unused, struct obd_export *exp,
+ 		   struct obd_quotactl *oqctl)
+ {
+-	struct client_obd       *cli = &exp->exp_obd->u.cli;
+-	struct ptlrpc_request   *req;
+-	struct obd_quotactl     *body;
+-	int		      rc;
++	struct client_obd *cli = &exp->exp_obd->u.cli;
++	struct ptlrpc_request *req;
++	struct obd_quotactl *body;
++	int rc;
+ 
+ 	req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
+ 					&RQF_OST_QUOTACHECK, LUSTRE_OST_VERSION,
+diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c
+index 6b6851ad3990..c174de9fb309 100644
+--- a/drivers/staging/lustre/lustre/osc/osc_request.c
++++ b/drivers/staging/lustre/lustre/osc/osc_request.c
+@@ -264,7 +264,7 @@ static int osc_getattr_async(struct obd_export *exp, struct obd_info *oinfo,
+ {
+ 	struct ptlrpc_request *req;
+ 	struct osc_async_args *aa;
+-	int		    rc;
++	int rc;
+ 
+ 	req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_GETATTR);
+ 	if (req == NULL)
+@@ -294,8 +294,8 @@ static int osc_getattr(const struct lu_env *env, struct obd_export *exp,
+ 		       struct obd_info *oinfo)
+ {
+ 	struct ptlrpc_request *req;
+-	struct ost_body       *body;
+-	int		    rc;
++	struct ost_body *body;
++	int rc;
+ 
+ 	req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_GETATTR);
+ 	if (req == NULL)
+@@ -338,8 +338,8 @@ static int osc_setattr(const struct lu_env *env, struct obd_export *exp,
+ 		       struct obd_info *oinfo, struct obd_trans_info *oti)
+ {
+ 	struct ptlrpc_request *req;
+-	struct ost_body       *body;
+-	int		    rc;
++	struct ost_body *body;
++	int rc;
+ 
+ 	LASSERT(oinfo->oi_oa->o_valid & OBD_MD_FLGROUP);
+ 
+@@ -403,9 +403,9 @@ int osc_setattr_async_base(struct obd_export *exp, struct obd_info *oinfo,
+ 			   obd_enqueue_update_f upcall, void *cookie,
+ 			   struct ptlrpc_request_set *rqset)
+ {
+-	struct ptlrpc_request   *req;
++	struct ptlrpc_request *req;
+ 	struct osc_setattr_args *sa;
+-	int		      rc;
++	int rc;
+ 
+ 	req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_SETATTR);
+ 	if (req == NULL)
+@@ -460,9 +460,9 @@ int osc_real_create(struct obd_export *exp, struct obdo *oa,
+ 		    struct lov_stripe_md **ea, struct obd_trans_info *oti)
+ {
+ 	struct ptlrpc_request *req;
+-	struct ost_body       *body;
+-	struct lov_stripe_md  *lsm;
+-	int		    rc;
++	struct ost_body *body;
++	struct lov_stripe_md *lsm;
++	int rc;
+ 
+ 	LASSERT(oa);
+ 	LASSERT(ea);
+@@ -548,10 +548,10 @@ int osc_punch_base(struct obd_export *exp, struct obd_info *oinfo,
+ 		   obd_enqueue_update_f upcall, void *cookie,
+ 		   struct ptlrpc_request_set *rqset)
+ {
+-	struct ptlrpc_request   *req;
++	struct ptlrpc_request *req;
+ 	struct osc_setattr_args *sa;
+-	struct ost_body	 *body;
+-	int		      rc;
++	struct ost_body *body;
++	int rc;
+ 
+ 	req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_PUNCH);
+ 	if (req == NULL)
+@@ -577,7 +577,7 @@ int osc_punch_base(struct obd_export *exp, struct obd_info *oinfo,
+ 	req->rq_interpret_reply = (ptlrpc_interpterer_t)osc_setattr_interpret;
+ 	CLASSERT (sizeof(*sa) <= sizeof(req->rq_async_args));
+ 	sa = ptlrpc_req_async_args(req);
+-	sa->sa_oa     = oinfo->oi_oa;
++	sa->sa_oa = oinfo->oi_oa;
+ 	sa->sa_upcall = upcall;
+ 	sa->sa_cookie = cookie;
+ 	if (rqset == PTLRPCD_SET)
+@@ -616,9 +616,9 @@ int osc_sync_base(struct obd_export *exp, struct obd_info *oinfo,
+ 		  struct ptlrpc_request_set *rqset)
+ {
+ 	struct ptlrpc_request *req;
+-	struct ost_body       *body;
++	struct ost_body *body;
+ 	struct osc_fsync_args *fa;
+-	int		    rc;
++	int rc;
+ 
+ 	req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_SYNC);
+ 	if (req == NULL)
+@@ -757,9 +757,9 @@ static int osc_destroy(const struct lu_env *env, struct obd_export *exp,
+ 		       struct obd_trans_info *oti, struct obd_export *md_export,
+ 		       void *capa)
+ {
+-	struct client_obd     *cli = &exp->exp_obd->u.cli;
++	struct client_obd *cli = &exp->exp_obd->u.cli;
+ 	struct ptlrpc_request *req;
+-	struct ost_body       *body;
++	struct ost_body *body;
+ 	LIST_HEAD(cancels);
+ 	int rc, count;
+ 
+@@ -947,7 +947,7 @@ static int osc_shrink_grant(struct client_obd *cli)
+ 
+ int osc_shrink_grant_to_target(struct client_obd *cli, __u64 target_bytes)
+ {
+-	int			rc = 0;
++	int rc = 0;
+ 	struct ost_body	*body;
+ 
+ 	client_obd_list_lock(&cli->cl_loi_list_lock);
+@@ -1131,8 +1131,8 @@ static int check_write_rcs(struct ptlrpc_request *req,
+ 			   int requested_nob, int niocount,
+ 			   u32 page_count, struct brw_page **pga)
+ {
+-	int     i;
+-	__u32   *remote_rcs;
++	int i;
++	__u32 *remote_rcs;
+ 
+ 	remote_rcs = req_capsule_server_sized_get(&req->rq_pill, &RMF_RCS,
+ 						  sizeof(*remote_rcs) *
+@@ -1182,15 +1182,15 @@ static inline int can_merge_pages(struct brw_page *p1, struct brw_page *p2)
+ }
+ 
+ static u32 osc_checksum_bulk(int nob, u32 pg_count,
+-				   struct brw_page **pga, int opc,
+-				   cksum_type_t cksum_type)
++			     struct brw_page **pga, int opc,
++			     cksum_type_t cksum_type)
+ {
+-	__u32				cksum;
+-	int				i = 0;
+-	struct cfs_crypto_hash_desc	*hdesc;
+-	unsigned int			bufsize;
+-	int				err;
+-	unsigned char			cfs_alg = cksum_obd2cfs(cksum_type);
++	__u32 cksum;
++	int i = 0;
++	struct cfs_crypto_hash_desc *hdesc;
++	unsigned int bufsize;
++	int err;
++	unsigned char cfs_alg = cksum_obd2cfs(cksum_type);
+ 
+ 	LASSERT(pg_count > 0);
+ 
+@@ -1250,14 +1250,14 @@ static int osc_brw_prep_request(int cmd, struct client_obd *cli,
+ 				struct obd_capa *ocapa, int reserve,
+ 				int resend)
+ {
+-	struct ptlrpc_request   *req;
++	struct ptlrpc_request *req;
+ 	struct ptlrpc_bulk_desc *desc;
+-	struct ost_body	 *body;
+-	struct obd_ioobj	*ioobj;
+-	struct niobuf_remote    *niobuf;
++	struct ost_body	*body;
++	struct obd_ioobj *ioobj;
++	struct niobuf_remote *niobuf;
+ 	int niocount, i, requested_nob, opc, rc;
+ 	struct osc_brw_async_args *aa;
+-	struct req_capsule      *pill;
++	struct req_capsule *pill;
+ 	struct brw_page *pg_prev;
+ 
+ 	if (OBD_FAIL_CHECK(OBD_FAIL_OSC_BRW_PREP_REQ))
+@@ -1359,8 +1359,8 @@ static int osc_brw_prep_request(int cmd, struct client_obd *cli,
+ 			niobuf->len += pg->count;
+ 		} else {
+ 			niobuf->offset = pg->off;
+-			niobuf->len    = pg->count;
+-			niobuf->flags  = pg->flag;
++			niobuf->len = pg->count;
++			niobuf->flags = pg->flag;
+ 		}
+ 		pg_prev = pg;
+ 	}
+@@ -1581,9 +1581,9 @@ static int osc_brw_fini_request(struct ptlrpc_request *req, int rc)
+ 
+ 	if (body->oa.o_valid & OBD_MD_FLCKSUM) {
+ 		static int cksum_counter;
+-		__u32      server_cksum = body->oa.o_cksum;
+-		char      *via;
+-		char      *router;
++		__u32 server_cksum = body->oa.o_cksum;
++		char *via;
++		char *router;
+ 		cksum_type_t cksum_type;
+ 
+ 		cksum_type = cksum_type_unpack(body->oa.o_valid &OBD_MD_FLFLAGS?
+@@ -1758,7 +1758,7 @@ static int brw_interpret(const struct lu_env *env,
+ 	struct osc_brw_async_args *aa = data;
+ 	struct osc_extent *ext;
+ 	struct osc_extent *tmp;
+-	struct cl_object  *obj = NULL;
++	struct cl_object *obj = NULL;
+ 	struct client_obd *cli = aa->aa_cli;
+ 
+ 	rc = osc_brw_fini_request(req, rc);
+@@ -1862,26 +1862,25 @@ static int brw_interpret(const struct lu_env *env,
+ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli,
+ 		  struct list_head *ext_list, int cmd, pdl_policy_t pol)
+ {
+-	struct ptlrpc_request		*req = NULL;
+-	struct osc_extent		*ext;
+-	struct brw_page			**pga = NULL;
+-	struct osc_brw_async_args	*aa = NULL;
+-	struct obdo			*oa = NULL;
+-	struct osc_async_page		*oap;
+-	struct osc_async_page		*tmp;
+-	struct cl_req			*clerq = NULL;
+-	enum cl_req_type		crt = (cmd & OBD_BRW_WRITE) ? CRT_WRITE :
+-								      CRT_READ;
+-	struct ldlm_lock		*lock = NULL;
+-	struct cl_req_attr		*crattr = NULL;
+-	u64				starting_offset = OBD_OBJECT_EOF;
+-	u64				ending_offset = 0;
+-	int				mpflag = 0;
+-	int				mem_tight = 0;
+-	int				page_count = 0;
+-	int				i;
+-	int				rc;
+-	struct ost_body			*body;
++	struct ptlrpc_request *req = NULL;
++	struct osc_extent *ext;
++	struct brw_page **pga = NULL;
++	struct osc_brw_async_args *aa = NULL;
++	struct obdo *oa = NULL;
++	struct osc_async_page *oap;
++	struct osc_async_page *tmp;
++	struct cl_req *clerq = NULL;
++	enum cl_req_type crt = (cmd & OBD_BRW_WRITE) ? CRT_WRITE : CRT_READ;
++	struct ldlm_lock *lock = NULL;
++	struct cl_req_attr *crattr = NULL;
++	u64 starting_offset = OBD_OBJECT_EOF;
++	u64 ending_offset = 0;
++	int mpflag = 0;
++	int mem_tight = 0;
++	int page_count = 0;
++	int i;
++	int rc;
++	struct ost_body *body;
+ 	LIST_HEAD(rpc_list);
+ 
+ 	LASSERT(!list_empty(ext_list));
+@@ -2480,10 +2479,10 @@ static int osc_statfs_async(struct obd_export *exp,
+ 			    struct obd_info *oinfo, __u64 max_age,
+ 			    struct ptlrpc_request_set *rqset)
+ {
+-	struct obd_device     *obd = class_exp2obd(exp);
++	struct obd_device *obd = class_exp2obd(exp);
+ 	struct ptlrpc_request *req;
+ 	struct osc_async_args *aa;
+-	int		    rc;
++	int rc;
+ 
+ 	/* We could possibly pass max_age in the request (as an absolute
+ 	 * timestamp or a "seconds.usec ago") so the target can avoid doing
+@@ -2522,10 +2521,10 @@ static int osc_statfs_async(struct obd_export *exp,
+ static int osc_statfs(const struct lu_env *env, struct obd_export *exp,
+ 		      struct obd_statfs *osfs, __u64 max_age, __u32 flags)
+ {
+-	struct obd_device     *obd = class_exp2obd(exp);
+-	struct obd_statfs     *msfs;
++	struct obd_device *obd = class_exp2obd(exp);
++	struct obd_statfs *msfs;
+ 	struct ptlrpc_request *req;
+-	struct obd_import     *imp = NULL;
++	struct obd_import *imp = NULL;
+ 	int rc;
+ 
+ 	/*Since the request might also come from lprocfs, so we need
+@@ -2749,9 +2748,9 @@ static int osc_get_info(const struct lu_env *env, struct obd_export *exp,
+ 		return 0;
+ 	} else if (KEY_IS(KEY_LAST_ID)) {
+ 		struct ptlrpc_request *req;
+-		u64		*reply;
+-		char		  *tmp;
+-		int		    rc;
++		u64 *reply;
++		char *tmp;
++		int rc;
+ 
+ 		req = ptlrpc_request_alloc(class_exp2cliimp(exp),
+ 					   &RQF_OST_GET_INFO_LAST_ID);
+@@ -2788,14 +2787,14 @@ static int osc_get_info(const struct lu_env *env, struct obd_export *exp,
+ 	} else if (KEY_IS(KEY_FIEMAP)) {
+ 		struct ll_fiemap_info_key *fm_key =
+ 				(struct ll_fiemap_info_key *)key;
+-		struct ldlm_res_id	 res_id;
+-		ldlm_policy_data_t	 policy;
+-		struct lustre_handle	 lockh;
+-		ldlm_mode_t		 mode = 0;
+-		struct ptlrpc_request	*req;
+-		struct ll_user_fiemap	*reply;
+-		char			*tmp;
+-		int			 rc;
++		struct ldlm_res_id res_id;
++		ldlm_policy_data_t policy;
++		struct lustre_handle lockh;
++		ldlm_mode_t mode = 0;
++		struct ptlrpc_request *req;
++		struct ll_user_fiemap *reply;
++		char *tmp;
++		int rc;
+ 
+ 		if (!(fm_key->fiemap.fm_flags & FIEMAP_FLAG_SYNC))
+ 			goto skip_locking;
+@@ -2881,10 +2880,10 @@ static int osc_set_info_async(const struct lu_env *env, struct obd_export *exp,
+ 			      void *val, struct ptlrpc_request_set *set)
+ {
+ 	struct ptlrpc_request *req;
+-	struct obd_device     *obd = exp->exp_obd;
+-	struct obd_import     *imp = class_exp2cliimp(exp);
+-	char		  *tmp;
+-	int		    rc;
++	struct obd_device *obd = exp->exp_obd;
++	struct obd_import *imp = class_exp2cliimp(exp);
++	char *tmp;
++	int rc;
+ 
+ 	OBD_FAIL_TIMEOUT(OBD_FAIL_OSC_SHUTDOWN, 10);
+ 
+@@ -3071,8 +3070,8 @@ static int osc_import_event(struct obd_device *obd,
+ 	}
+ 	case IMP_EVENT_INVALIDATE: {
+ 		struct ldlm_namespace *ns = obd->obd_namespace;
+-		struct lu_env	 *env;
+-		int		    refcheck;
++		struct lu_env *env;
++		int refcheck;
+ 
+ 		env = cl_env_get(&refcheck);
+ 		if (!IS_ERR(env)) {
+@@ -3159,9 +3158,9 @@ static int brw_queue_work(const struct lu_env *env, void *data)
+ int osc_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
+ {
+ 	struct lprocfs_static_vars lvars = { NULL };
+-	struct client_obd	  *cli = &obd->u.cli;
+-	void		       *handler;
+-	int			rc;
++	struct client_obd *cli = &obd->u.cli;
++	void *handler;
++	int rc;
+ 
+ 	rc = ptlrpcd_addref();
+ 	if (rc)

commit f4edeeb3937d5f9953b5722f1cca9573d5ffe8a0
+Author: Abhishek Kulkarni 
+Date:   Tue Sep 22 11:34:04 2009 -0500
+
+    9p: Update documentation to add fscache related bits
+    
+    Update the documentation to describe FS-Cache related
+    caching parameters. This patch also updates the pointers
+    to 9p-related papers and adds pointer to the Wiki.
+    
+    Signed-off-by: Abhishek Kulkarni 
+    Signed-off-by: Eric Van Hensbergen 
+
+diff --git a/Documentation/filesystems/9p.txt b/Documentation/filesystems/9p.txt
+index 6208f55c44c3..57e0b80a5274 100644
+--- a/Documentation/filesystems/9p.txt
++++ b/Documentation/filesystems/9p.txt
+@@ -18,11 +18,11 @@ the 9p client is available in the form of a USENIX paper:
+ 
+ Other applications are described in the following papers:
+ 	* XCPU & Clustering
+-		http://www.xcpu.org/xcpu-talk.pdf
++		http://xcpu.org/papers/xcpu-talk.pdf
+ 	* KVMFS: control file system for KVM
+-		http://www.xcpu.org/kvmfs.pdf
+-	* CellFS: A New ProgrammingModel for the Cell BE
+-		http://www.xcpu.org/cellfs-talk.pdf
++		http://xcpu.org/papers/kvmfs.pdf
++	* CellFS: A New Programming Model for the Cell BE
++		http://xcpu.org/papers/cellfs-talk.pdf
+ 	* PROSE I/O: Using 9p to enable Application Partitions
+ 		http://plan9.escet.urjc.es/iwp9/cready/PROSE_iwp9_2006.pdf
+ 
+@@ -48,6 +48,7 @@ OPTIONS
+                                 (see rfdno and wfdno)
+ 			virtio	- connect to the next virtio channel available
+ 				(from lguest or KVM with trans_virtio module)
++			rdma	- connect to a specified RDMA channel
+ 
+   uname=name	user name to attempt mount as on the remote server.  The
+   		server may override or ignore this value.  Certain user
+@@ -59,16 +60,22 @@ OPTIONS
+   cache=mode	specifies a caching policy.  By default, no caches are used.
+ 			loose = no attempts are made at consistency,
+                                 intended for exclusive, read-only mounts
++			fscache = use FS-Cache for a persistent, read-only
++				cache backend.
+ 
+   debug=n	specifies debug level.  The debug level is a bitmask.
+-  			0x01 = display verbose error messages
+-			0x02 = developer debug (DEBUG_CURRENT)
+-			0x04 = display 9p trace
+-			0x08 = display VFS trace
+-			0x10 = display Marshalling debug
+-			0x20 = display RPC debug
+-			0x40 = display transport debug
+-			0x80 = display allocation debug
++			0x01  = display verbose error messages
++			0x02  = developer debug (DEBUG_CURRENT)
++			0x04  = display 9p trace
++			0x08  = display VFS trace
++			0x10  = display Marshalling debug
++			0x20  = display RPC debug
++			0x40  = display transport debug
++			0x80  = display allocation debug
++			0x100 = display protocol message debug
++			0x200 = display Fid debug
++			0x400 = display packet debug
++			0x800 = display fscache tracing debug
+ 
+   rfdno=n	the file descriptor for reading with trans=fd
+ 
+@@ -100,6 +107,10 @@ OPTIONS
+ 			any   = v9fs does single attach and performs all
+ 				operations as one user
+ 
++  cachetag	cache tag to use the specified persistent cache.
++		cache tags for existing cache sessions can be listed at
++		/sys/fs/9p/caches. (applies only to cache=fscache)
++
+ RESOURCES
+ =========
+ 
+@@ -118,7 +129,7 @@ and export.
+ A Linux version of the 9p server is now maintained under the npfs project
+ on sourceforge (http://sourceforge.net/projects/npfs).  The currently
+ maintained version is the single-threaded version of the server (named spfs)
+-available from the same CVS repository.
++available from the same SVN repository.
+ 
+ There are user and developer mailing lists available through the v9fs project
+ on sourceforge (http://sourceforge.net/projects/v9fs).
+@@ -126,7 +137,8 @@ on sourceforge (http://sourceforge.net/projects/v9fs).
+ A stand-alone version of the module (which should build for any 2.6 kernel)
+ is available via (http://github.com/ericvh/9p-sac/tree/master)
+ 
+-News and other information is maintained on SWiK (http://swik.net/v9fs).
++News and other information is maintained on SWiK (http://swik.net/v9fs)
++and the Wiki (http://sf.net/apps/mediawiki/v9fs/index.php).
+ 
+ Bug reports may be issued through the kernel.org bugzilla 
+ (http://bugzilla.kernel.org)

commit 60e78d2c993e58d890596d951fff77d5965adcd6
+Author: Abhishek Kulkarni 
+Date:   Wed Sep 23 13:00:27 2009 -0500
+
+    9p: Add fscache support to 9p
+    
+    This patch adds a persistent, read-only caching facility for
+    9p clients using the FS-Cache caching backend.
+    
+    When the fscache facility is enabled, each inode is associated
+    with a corresponding vcookie which is an index into the FS-Cache
+    indexing tree. The FS-Cache indexing tree is indexed at 3 levels:
+    - session object associated with each mount.
+    - inode/vcookie
+    - actual data (pages)
+    
+    A cache tag is chosen randomly for each session. These tags can
+    be read off /sys/fs/9p/caches and can be passed as a mount-time
+    parameter to re-attach to the specified caching session.
+    
+    Signed-off-by: Abhishek Kulkarni 
+    Signed-off-by: Eric Van Hensbergen 
+
+diff --git a/fs/9p/Kconfig b/fs/9p/Kconfig
+index 74e0723e90bc..795233702a4e 100644
+--- a/fs/9p/Kconfig
++++ b/fs/9p/Kconfig
+@@ -8,3 +8,12 @@ config 9P_FS
+ 	  See  for more information.
+ 
+ 	  If unsure, say N.
++
++config 9P_FSCACHE
++	bool "Enable 9P client caching support (EXPERIMENTAL)"
++	depends on EXPERIMENTAL
++	depends on 9P_FS=m && FSCACHE || 9P_FS=y && FSCACHE=y
++	help
++	  Choose Y here to enable persistent, read-only local
++	  caching support for 9p clients using FS-Cache
++
+diff --git a/fs/9p/Makefile b/fs/9p/Makefile
+index bc7f0d1551e6..1a940ec7af61 100644
+--- a/fs/9p/Makefile
++++ b/fs/9p/Makefile
+@@ -8,5 +8,6 @@ obj-$(CONFIG_9P_FS) := 9p.o
+ 	vfs_dir.o \
+ 	vfs_dentry.o \
+ 	v9fs.o \
+-	fid.o \
++	fid.o
+ 
++9p-$(CONFIG_9P_FSCACHE) += cache.o
+diff --git a/fs/9p/cache.c b/fs/9p/cache.c
+new file mode 100644
+index 000000000000..51c94e26a346
+--- /dev/null
++++ b/fs/9p/cache.c
+@@ -0,0 +1,474 @@
++/*
++ * V9FS cache definitions.
++ *
++ *  Copyright (C) 2009 by Abhishek Kulkarni 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License version 2
++ *  as published by the Free Software Foundation.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to:
++ *  Free Software Foundation
++ *  51 Franklin Street, Fifth Floor
++ *  Boston, MA  02111-1301  USA
++ *
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include "v9fs.h"
++#include "cache.h"
++
++#define CACHETAG_LEN  11
++
++struct kmem_cache *vcookie_cache;
++
++struct fscache_netfs v9fs_cache_netfs = {
++	.name 		= "9p",
++	.version 	= 0,
++};
++
++static void init_once(void *foo)
++{
++	struct v9fs_cookie *vcookie = (struct v9fs_cookie *) foo;
++	vcookie->fscache = NULL;
++	vcookie->qid = NULL;
++	inode_init_once(&vcookie->inode);
++}
++
++/**
++ * v9fs_init_vcookiecache - initialize a cache for vcookies to maintain
++ *			    vcookie to inode mapping
++ *
++ * Returns 0 on success.
++ */
++
++static int v9fs_init_vcookiecache(void)
++{
++	vcookie_cache = kmem_cache_create("vcookie_cache",
++					  sizeof(struct v9fs_cookie),
++					  0, (SLAB_RECLAIM_ACCOUNT|
++					      SLAB_MEM_SPREAD),
++					  init_once);
++	if (!vcookie_cache)
++		return -ENOMEM;
++
++	return 0;
++}
++
++/**
++ * v9fs_destroy_vcookiecache - destroy the cache of vcookies
++ *
++ */
++
++static void v9fs_destroy_vcookiecache(void)
++{
++	kmem_cache_destroy(vcookie_cache);
++}
++
++int __v9fs_cache_register(void)
++{
++	int ret;
++	ret = v9fs_init_vcookiecache();
++	if (ret < 0)
++		return ret;
++
++	return fscache_register_netfs(&v9fs_cache_netfs);
++}
++
++void __v9fs_cache_unregister(void)
++{
++	v9fs_destroy_vcookiecache();
++	fscache_unregister_netfs(&v9fs_cache_netfs);
++}
++
++/**
++ * v9fs_random_cachetag - Generate a random tag to be associated
++ *			  with a new cache session.
++ *
++ * The value of jiffies is used for a fairly randomly cache tag.
++ */
++
++static
++int v9fs_random_cachetag(struct v9fs_session_info *v9ses)
++{
++	v9ses->cachetag = kmalloc(CACHETAG_LEN, GFP_KERNEL);
++	if (!v9ses->cachetag)
++		return -ENOMEM;
++
++	return scnprintf(v9ses->cachetag, CACHETAG_LEN, "%lu", jiffies);
++}
++
++static uint16_t v9fs_cache_session_get_key(const void *cookie_netfs_data,
++					   void *buffer, uint16_t bufmax)
++{
++	struct v9fs_session_info *v9ses;
++	uint16_t klen = 0;
++
++	v9ses = (struct v9fs_session_info *)cookie_netfs_data;
++	P9_DPRINTK(P9_DEBUG_FSC, "session %p buf %p size %u", v9ses,
++		   buffer, bufmax);
++
++	if (v9ses->cachetag)
++		klen = strlen(v9ses->cachetag);
++
++	if (klen > bufmax)
++		return 0;
++
++	memcpy(buffer, v9ses->cachetag, klen);
++	P9_DPRINTK(P9_DEBUG_FSC, "cache session tag %s", v9ses->cachetag);
++	return klen;
++}
++
++const struct fscache_cookie_def v9fs_cache_session_index_def = {
++	.name 		= "9P.session",
++	.type 		= FSCACHE_COOKIE_TYPE_INDEX,
++	.get_key 	= v9fs_cache_session_get_key,
++};
++
++void v9fs_cache_session_get_cookie(struct v9fs_session_info *v9ses)
++{
++	/* If no cache session tag was specified, we generate a random one. */
++	if (!v9ses->cachetag)
++		v9fs_random_cachetag(v9ses);
++
++	v9ses->fscache = fscache_acquire_cookie(v9fs_cache_netfs.primary_index,
++						&v9fs_cache_session_index_def,
++						v9ses);
++	P9_DPRINTK(P9_DEBUG_FSC, "session %p get cookie %p", v9ses,
++		   v9ses->fscache);
++}
++
++void v9fs_cache_session_put_cookie(struct v9fs_session_info *v9ses)
++{
++	P9_DPRINTK(P9_DEBUG_FSC, "session %p put cookie %p", v9ses,
++		   v9ses->fscache);
++	fscache_relinquish_cookie(v9ses->fscache, 0);
++	v9ses->fscache = NULL;
++}
++
++
++static uint16_t v9fs_cache_inode_get_key(const void *cookie_netfs_data,
++					 void *buffer, uint16_t bufmax)
++{
++	const struct v9fs_cookie *vcookie = cookie_netfs_data;
++	memcpy(buffer, &vcookie->qid->path, sizeof(vcookie->qid->path));
++
++	P9_DPRINTK(P9_DEBUG_FSC, "inode %p get key %llu", &vcookie->inode,
++		   vcookie->qid->path);
++	return sizeof(vcookie->qid->path);
++}
++
++static void v9fs_cache_inode_get_attr(const void *cookie_netfs_data,
++				      uint64_t *size)
++{
++	const struct v9fs_cookie *vcookie = cookie_netfs_data;
++	*size = i_size_read(&vcookie->inode);
++
++	P9_DPRINTK(P9_DEBUG_FSC, "inode %p get attr %llu", &vcookie->inode,
++		   *size);
++}
++
++static uint16_t v9fs_cache_inode_get_aux(const void *cookie_netfs_data,
++					 void *buffer, uint16_t buflen)
++{
++	const struct v9fs_cookie *vcookie = cookie_netfs_data;
++	memcpy(buffer, &vcookie->qid->version, sizeof(vcookie->qid->version));
++
++	P9_DPRINTK(P9_DEBUG_FSC, "inode %p get aux %u", &vcookie->inode,
++		   vcookie->qid->version);
++	return sizeof(vcookie->qid->version);
++}
++
++static enum
++fscache_checkaux v9fs_cache_inode_check_aux(void *cookie_netfs_data,
++					    const void *buffer,
++					    uint16_t buflen)
++{
++	const struct v9fs_cookie *vcookie = cookie_netfs_data;
++
++	if (buflen != sizeof(vcookie->qid->version))
++		return FSCACHE_CHECKAUX_OBSOLETE;
++
++	if (memcmp(buffer, &vcookie->qid->version,
++		   sizeof(vcookie->qid->version)))
++		return FSCACHE_CHECKAUX_OBSOLETE;
++
++	return FSCACHE_CHECKAUX_OKAY;
++}
++
++static void v9fs_cache_inode_now_uncached(void *cookie_netfs_data)
++{
++	struct v9fs_cookie *vcookie = cookie_netfs_data;
++	struct pagevec pvec;
++	pgoff_t first;
++	int loop, nr_pages;
++
++	pagevec_init(&pvec, 0);
++	first = 0;
++
++	for (;;) {
++		nr_pages = pagevec_lookup(&pvec, vcookie->inode.i_mapping,
++					  first,
++					  PAGEVEC_SIZE - pagevec_count(&pvec));
++		if (!nr_pages)
++			break;
++
++		for (loop = 0; loop < nr_pages; loop++)
++			ClearPageFsCache(pvec.pages[loop]);
++
++		first = pvec.pages[nr_pages - 1]->index + 1;
++
++		pvec.nr = nr_pages;
++		pagevec_release(&pvec);
++		cond_resched();
++	}
++}
++
++const struct fscache_cookie_def v9fs_cache_inode_index_def = {
++	.name		= "9p.inode",
++	.type		= FSCACHE_COOKIE_TYPE_DATAFILE,
++	.get_key	= v9fs_cache_inode_get_key,
++	.get_attr	= v9fs_cache_inode_get_attr,
++	.get_aux	= v9fs_cache_inode_get_aux,
++	.check_aux	= v9fs_cache_inode_check_aux,
++	.now_uncached	= v9fs_cache_inode_now_uncached,
++};
++
++void v9fs_cache_inode_get_cookie(struct inode *inode)
++{
++	struct v9fs_cookie *vcookie;
++	struct v9fs_session_info *v9ses;
++
++	if (!S_ISREG(inode->i_mode))
++		return;
++
++	vcookie = v9fs_inode2cookie(inode);
++	if (vcookie->fscache)
++		return;
++
++	v9ses = v9fs_inode2v9ses(inode);
++	vcookie->fscache = fscache_acquire_cookie(v9ses->fscache,
++						  &v9fs_cache_inode_index_def,
++						  vcookie);
++
++	P9_DPRINTK(P9_DEBUG_FSC, "inode %p get cookie %p", inode,
++		   vcookie->fscache);
++}
++
++void v9fs_cache_inode_put_cookie(struct inode *inode)
++{
++	struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode);
++
++	if (!vcookie->fscache)
++		return;
++	P9_DPRINTK(P9_DEBUG_FSC, "inode %p put cookie %p", inode,
++		   vcookie->fscache);
++
++	fscache_relinquish_cookie(vcookie->fscache, 0);
++	vcookie->fscache = NULL;
++}
++
++void v9fs_cache_inode_flush_cookie(struct inode *inode)
++{
++	struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode);
++
++	if (!vcookie->fscache)
++		return;
++	P9_DPRINTK(P9_DEBUG_FSC, "inode %p flush cookie %p", inode,
++		   vcookie->fscache);
++
++	fscache_relinquish_cookie(vcookie->fscache, 1);
++	vcookie->fscache = NULL;
++}
++
++void v9fs_cache_inode_set_cookie(struct inode *inode, struct file *filp)
++{
++	struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode);
++	struct p9_fid *fid;
++
++	if (!vcookie->fscache)
++		return;
++
++	spin_lock(&vcookie->lock);
++	fid = filp->private_data;
++	if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
++		v9fs_cache_inode_flush_cookie(inode);
++	else
++		v9fs_cache_inode_get_cookie(inode);
++
++	spin_unlock(&vcookie->lock);
++}
++
++void v9fs_cache_inode_reset_cookie(struct inode *inode)
++{
++	struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode);
++	struct v9fs_session_info *v9ses;
++	struct fscache_cookie *old;
++
++	if (!vcookie->fscache)
++		return;
++
++	old = vcookie->fscache;
++
++	spin_lock(&vcookie->lock);
++	fscache_relinquish_cookie(vcookie->fscache, 1);
++
++	v9ses = v9fs_inode2v9ses(inode);
++	vcookie->fscache = fscache_acquire_cookie(v9ses->fscache,
++						  &v9fs_cache_inode_index_def,
++						  vcookie);
++
++	P9_DPRINTK(P9_DEBUG_FSC, "inode %p revalidating cookie old %p new %p",
++		   inode, old, vcookie->fscache);
++
++	spin_unlock(&vcookie->lock);
++}
++
++int __v9fs_fscache_release_page(struct page *page, gfp_t gfp)
++{
++	struct inode *inode = page->mapping->host;
++	struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode);
++
++	BUG_ON(!vcookie->fscache);
++
++	if (PageFsCache(page)) {
++		if (fscache_check_page_write(vcookie->fscache, page)) {
++			if (!(gfp & __GFP_WAIT))
++				return 0;
++			fscache_wait_on_page_write(vcookie->fscache, page);
++		}
++
++		fscache_uncache_page(vcookie->fscache, page);
++		ClearPageFsCache(page);
++	}
++
++	return 1;
++}
++
++void __v9fs_fscache_invalidate_page(struct page *page)
++{
++	struct inode *inode = page->mapping->host;
++	struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode);
++
++	BUG_ON(!vcookie->fscache);
++
++	if (PageFsCache(page)) {
++		fscache_wait_on_page_write(vcookie->fscache, page);
++		BUG_ON(!PageLocked(page));
++		fscache_uncache_page(vcookie->fscache, page);
++		ClearPageFsCache(page);
++	}
++}
++
++static void v9fs_vfs_readpage_complete(struct page *page, void *data,
++				       int error)
++{
++	if (!error)
++		SetPageUptodate(page);
++
++	unlock_page(page);
++}
++
++/**
++ * __v9fs_readpage_from_fscache - read a page from cache
++ *
++ * Returns 0 if the pages are in cache and a BIO is submitted,
++ * 1 if the pages are not in cache and -error otherwise.
++ */
++
++int __v9fs_readpage_from_fscache(struct inode *inode, struct page *page)
++{
++	int ret;
++	const struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode);
++
++	P9_DPRINTK(P9_DEBUG_FSC, "inode %p page %p", inode, page);
++	if (!vcookie->fscache)
++		return -ENOBUFS;
++
++	ret = fscache_read_or_alloc_page(vcookie->fscache,
++					 page,
++					 v9fs_vfs_readpage_complete,
++					 NULL,
++					 GFP_KERNEL);
++	switch (ret) {
++	case -ENOBUFS:
++	case -ENODATA:
++		P9_DPRINTK(P9_DEBUG_FSC, "page/inode not in cache %d", ret);
++		return 1;
++	case 0:
++		P9_DPRINTK(P9_DEBUG_FSC, "BIO submitted");
++		return ret;
++	default:
++		P9_DPRINTK(P9_DEBUG_FSC, "ret %d", ret);
++		return ret;
++	}
++}
++
++/**
++ * __v9fs_readpages_from_fscache - read multiple pages from cache
++ *
++ * Returns 0 if the pages are in cache and a BIO is submitted,
++ * 1 if the pages are not in cache and -error otherwise.
++ */
++
++int __v9fs_readpages_from_fscache(struct inode *inode,
++				  struct address_space *mapping,
++				  struct list_head *pages,
++				  unsigned *nr_pages)
++{
++	int ret;
++	const struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode);
++
++	P9_DPRINTK(P9_DEBUG_FSC, "inode %p pages %u", inode, *nr_pages);
++	if (!vcookie->fscache)
++		return -ENOBUFS;
++
++	ret = fscache_read_or_alloc_pages(vcookie->fscache,
++					  mapping, pages, nr_pages,
++					  v9fs_vfs_readpage_complete,
++					  NULL,
++					  mapping_gfp_mask(mapping));
++	switch (ret) {
++	case -ENOBUFS:
++	case -ENODATA:
++		P9_DPRINTK(P9_DEBUG_FSC, "pages/inodes not in cache %d", ret);
++		return 1;
++	case 0:
++		BUG_ON(!list_empty(pages));
++		BUG_ON(*nr_pages != 0);
++		P9_DPRINTK(P9_DEBUG_FSC, "BIO submitted");
++		return ret;
++	default:
++		P9_DPRINTK(P9_DEBUG_FSC, "ret %d", ret);
++		return ret;
++	}
++}
++
++/**
++ * __v9fs_readpage_to_fscache - write a page to the cache
++ *
++ */
++
++void __v9fs_readpage_to_fscache(struct inode *inode, struct page *page)
++{
++	int ret;
++	const struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode);
++
++	P9_DPRINTK(P9_DEBUG_FSC, "inode %p page %p", inode, page);
++	ret = fscache_write_page(vcookie->fscache, page, GFP_KERNEL);
++	P9_DPRINTK(P9_DEBUG_FSC, "ret =  %d", ret);
++	if (ret != 0)
++		v9fs_uncache_page(inode, page);
++}
+diff --git a/fs/9p/cache.h b/fs/9p/cache.h
+new file mode 100644
+index 000000000000..a94192bfaee8
+--- /dev/null
++++ b/fs/9p/cache.h
+@@ -0,0 +1,176 @@
++/*
++ * V9FS cache definitions.
++ *
++ *  Copyright (C) 2009 by Abhishek Kulkarni 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License version 2
++ *  as published by the Free Software Foundation.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to:
++ *  Free Software Foundation
++ *  51 Franklin Street, Fifth Floor
++ *  Boston, MA  02111-1301  USA
++ *
++ */
++
++#ifndef _9P_CACHE_H
++#ifdef CONFIG_9P_FSCACHE
++#include 
++#include 
++
++extern struct kmem_cache *vcookie_cache;
++
++struct v9fs_cookie {
++	spinlock_t lock;
++	struct inode inode;
++	struct fscache_cookie *fscache;
++	struct p9_qid *qid;
++};
++
++static inline struct v9fs_cookie *v9fs_inode2cookie(const struct inode *inode)
++{
++	return container_of(inode, struct v9fs_cookie, inode);
++}
++
++extern struct fscache_netfs v9fs_cache_netfs;
++extern const struct fscache_cookie_def v9fs_cache_session_index_def;
++extern const struct fscache_cookie_def v9fs_cache_inode_index_def;
++
++extern void v9fs_cache_session_get_cookie(struct v9fs_session_info *v9ses);
++extern void v9fs_cache_session_put_cookie(struct v9fs_session_info *v9ses);
++
++extern void v9fs_cache_inode_get_cookie(struct inode *inode);
++extern void v9fs_cache_inode_put_cookie(struct inode *inode);
++extern void v9fs_cache_inode_flush_cookie(struct inode *inode);
++extern void v9fs_cache_inode_set_cookie(struct inode *inode, struct file *filp);
++extern void v9fs_cache_inode_reset_cookie(struct inode *inode);
++
++extern int __v9fs_cache_register(void);
++extern void __v9fs_cache_unregister(void);
++
++extern int __v9fs_fscache_release_page(struct page *page, gfp_t gfp);
++extern void __v9fs_fscache_invalidate_page(struct page *page);
++extern int __v9fs_readpage_from_fscache(struct inode *inode,
++					struct page *page);
++extern int __v9fs_readpages_from_fscache(struct inode *inode,
++					 struct address_space *mapping,
++					 struct list_head *pages,
++					 unsigned *nr_pages);
++extern void __v9fs_readpage_to_fscache(struct inode *inode, struct page *page);
++
++
++/**
++ * v9fs_cache_register - Register v9fs file system with the cache
++ */
++static inline int v9fs_cache_register(void)
++{
++	return __v9fs_cache_register();
++}
++
++/**
++ * v9fs_cache_unregister - Unregister v9fs from the cache
++ */
++static inline void v9fs_cache_unregister(void)
++{
++	__v9fs_cache_unregister();
++}
++
++static inline int v9fs_fscache_release_page(struct page *page,
++					    gfp_t gfp)
++{
++	return __v9fs_fscache_release_page(page, gfp);
++}
++
++static inline void v9fs_fscache_invalidate_page(struct page *page)
++{
++	__v9fs_fscache_invalidate_page(page);
++}
++
++static inline int v9fs_readpage_from_fscache(struct inode *inode,
++					     struct page *page)
++{
++	return __v9fs_readpage_from_fscache(inode, page);
++}
++
++static inline int v9fs_readpages_from_fscache(struct inode *inode,
++					      struct address_space *mapping,
++					      struct list_head *pages,
++					      unsigned *nr_pages)
++{
++	return __v9fs_readpages_from_fscache(inode, mapping, pages,
++					     nr_pages);
++}
++
++static inline void v9fs_readpage_to_fscache(struct inode *inode,
++					    struct page *page)
++{
++	if (PageFsCache(page))
++		__v9fs_readpage_to_fscache(inode, page);
++}
++
++static inline void v9fs_uncache_page(struct inode *inode, struct page *page)
++{
++	struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode);
++	fscache_uncache_page(vcookie->fscache, page);
++	BUG_ON(PageFsCache(page));
++}
++
++static inline void v9fs_vcookie_set_qid(struct inode *inode,
++					struct p9_qid *qid)
++{
++	struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode);
++	spin_lock(&vcookie->lock);
++	vcookie->qid = qid;
++	spin_unlock(&vcookie->lock);
++}
++
++#else /* CONFIG_9P_FSCACHE */
++
++static inline int v9fs_cache_register(void)
++{
++	return 1;
++}
++
++static inline void v9fs_cache_unregister(void) {}
++
++static inline int v9fs_fscache_release_page(struct page *page,
++					    gfp_t gfp) {
++	return 1;
++}
++
++static inline void v9fs_fscache_invalidate_page(struct page *page) {}
++
++static inline int v9fs_readpage_from_fscache(struct inode *inode,
++					     struct page *page)
++{
++	return -ENOBUFS;
++}
++
++static inline int v9fs_readpages_from_fscache(struct inode *inode,
++					      struct address_space *mapping,
++					      struct list_head *pages,
++					      unsigned *nr_pages)
++{
++	return -ENOBUFS;
++}
++
++static inline void v9fs_readpage_to_fscache(struct inode *inode,
++					    struct page *page)
++{}
++
++static inline void v9fs_uncache_page(struct inode *inode, struct page *page)
++{}
++
++static inline void v9fs_vcookie_set_qid(struct inode *inode,
++					struct p9_qid *qid)
++{}
++
++#endif /* CONFIG_9P_FSCACHE */
++#endif /* _9P_CACHE_H */
+diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
+index f7003cfac63d..cf62b05e296a 100644
+--- a/fs/9p/v9fs.c
++++ b/fs/9p/v9fs.c
+@@ -34,21 +34,25 @@
+ #include 
+ #include "v9fs.h"
+ #include "v9fs_vfs.h"
++#include "cache.h"
++
++static DEFINE_SPINLOCK(v9fs_sessionlist_lock);
++static LIST_HEAD(v9fs_sessionlist);
+ 
+ /*
+-  * Option Parsing (code inspired by NFS code)
+-  *  NOTE: each transport will parse its own options
+-  */
++ * Option Parsing (code inspired by NFS code)
++ *  NOTE: each transport will parse its own options
++ */
+ 
+ enum {
+ 	/* Options that take integer arguments */
+ 	Opt_debug, Opt_dfltuid, Opt_dfltgid, Opt_afid,
+ 	/* String options */
+-	Opt_uname, Opt_remotename, Opt_trans,
++	Opt_uname, Opt_remotename, Opt_trans, Opt_cache, Opt_cachetag,
+ 	/* Options that take no arguments */
+ 	Opt_nodevmap,
+ 	/* Cache options */
+-	Opt_cache_loose,
++	Opt_cache_loose, Opt_fscache,
+ 	/* Access options */
+ 	Opt_access,
+ 	/* Error token */
+@@ -63,8 +67,10 @@ static const match_table_t tokens = {
+ 	{Opt_uname, "uname=%s"},
+ 	{Opt_remotename, "aname=%s"},
+ 	{Opt_nodevmap, "nodevmap"},
+-	{Opt_cache_loose, "cache=loose"},
++	{Opt_cache, "cache=%s"},
+ 	{Opt_cache_loose, "loose"},
++	{Opt_fscache, "fscache"},
++	{Opt_cachetag, "cachetag=%s"},
+ 	{Opt_access, "access=%s"},
+ 	{Opt_err, NULL}
+ };
+@@ -89,16 +95,16 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
+ 	v9ses->afid = ~0;
+ 	v9ses->debug = 0;
+ 	v9ses->cache = 0;
++#ifdef CONFIG_9P_FSCACHE
++	v9ses->cachetag = NULL;
++#endif
+ 
+ 	if (!opts)
+ 		return 0;
+ 
+ 	options = kstrdup(opts, GFP_KERNEL);
+-	if (!options) {
+-		P9_DPRINTK(P9_DEBUG_ERROR,
+-			   "failed to allocate copy of option string\n");
+-		return -ENOMEM;
+-	}
++	if (!options)
++		goto fail_option_alloc;
+ 
+ 	while ((p = strsep(&options, ",")) != NULL) {
+ 		int token;
+@@ -143,16 +149,33 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
+ 		case Opt_cache_loose:
+ 			v9ses->cache = CACHE_LOOSE;
+ 			break;
++		case Opt_fscache:
++			v9ses->cache = CACHE_FSCACHE;
++			break;
++		case Opt_cachetag:
++#ifdef CONFIG_9P_FSCACHE
++			v9ses->cachetag = match_strdup(&args[0]);
++#endif
++			break;
++		case Opt_cache:
++			s = match_strdup(&args[0]);
++			if (!s)
++				goto fail_option_alloc;
++
++			if (strcmp(s, "loose") == 0)
++				v9ses->cache = CACHE_LOOSE;
++			else if (strcmp(s, "fscache") == 0)
++				v9ses->cache = CACHE_FSCACHE;
++			else
++				v9ses->cache = CACHE_NONE;
++			kfree(s);
++			break;
+ 
+ 		case Opt_access:
+ 			s = match_strdup(&args[0]);
+-			if (!s) {
+-				P9_DPRINTK(P9_DEBUG_ERROR,
+-					   "failed to allocate copy"
+-					   " of option argument\n");
+-				ret = -ENOMEM;
+-				break;
+-			}
++			if (!s)
++				goto fail_option_alloc;
++
+ 			v9ses->flags &= ~V9FS_ACCESS_MASK;
+ 			if (strcmp(s, "user") == 0)
+ 				v9ses->flags |= V9FS_ACCESS_USER;
+@@ -173,6 +196,11 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
+ 	}
+ 	kfree(options);
+ 	return ret;
++
++fail_option_alloc:
++	P9_DPRINTK(P9_DEBUG_ERROR,
++		   "failed to allocate copy of option argument\n");
++	return -ENOMEM;
+ }
+ 
+ /**
+@@ -200,6 +228,10 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
+ 		return ERR_PTR(-ENOMEM);
+ 	}
+ 
++	spin_lock(&v9fs_sessionlist_lock);
++	list_add(&v9ses->slist, &v9fs_sessionlist);
++	spin_unlock(&v9fs_sessionlist_lock);
++
+ 	v9ses->flags = V9FS_EXTENDED | V9FS_ACCESS_USER;
+ 	strcpy(v9ses->uname, V9FS_DEFUSER);
+ 	strcpy(v9ses->aname, V9FS_DEFANAME);
+@@ -249,6 +281,11 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
+ 	else
+ 		fid->uid = ~0;
+ 
++#ifdef CONFIG_9P_FSCACHE
++	/* register the session for caching */
++	v9fs_cache_session_get_cookie(v9ses);
++#endif
++
+ 	return fid;
+ 
+ error:
+@@ -268,8 +305,18 @@ void v9fs_session_close(struct v9fs_session_info *v9ses)
+ 		v9ses->clnt = NULL;
+ 	}
+ 
++#ifdef CONFIG_9P_FSCACHE
++	if (v9ses->fscache) {
++		v9fs_cache_session_put_cookie(v9ses);
++		kfree(v9ses->cachetag);
++	}
++#endif
+ 	__putname(v9ses->uname);
+ 	__putname(v9ses->aname);
++
++	spin_lock(&v9fs_sessionlist_lock);
++	list_del(&v9ses->slist);
++	spin_unlock(&v9fs_sessionlist_lock);
+ }
+ 
+ /**
+@@ -286,25 +333,132 @@ void v9fs_session_cancel(struct v9fs_session_info *v9ses) {
+ 
+ extern int v9fs_error_init(void);
+ 
++static struct kobject *v9fs_kobj;
++
++#ifdef CONFIG_9P_FSCACHE
+ /**
+- * v9fs_init - Initialize module
++ * caches_show - list caches associated with a session
++ *
++ * Returns the size of buffer written.
++ */
++
++static ssize_t caches_show(struct kobject *kobj,
++			   struct kobj_attribute *attr,
++			   char *buf)
++{
++	ssize_t n = 0, count = 0, limit = PAGE_SIZE;
++	struct v9fs_session_info *v9ses;
++
++	spin_lock(&v9fs_sessionlist_lock);
++	list_for_each_entry(v9ses, &v9fs_sessionlist, slist) {
++		if (v9ses->cachetag) {
++			n = snprintf(buf, limit, "%s\n", v9ses->cachetag);
++			if (n < 0) {
++				count = n;
++				break;
++			}
++
++			count += n;
++			limit -= n;
++		}
++	}
++
++	spin_unlock(&v9fs_sessionlist_lock);
++	return count;
++}
++
++static struct kobj_attribute v9fs_attr_cache = __ATTR_RO(caches);
++#endif /* CONFIG_9P_FSCACHE */
++
++static struct attribute *v9fs_attrs[] = {
++#ifdef CONFIG_9P_FSCACHE
++	&v9fs_attr_cache.attr,
++#endif
++	NULL,
++};
++
++static struct attribute_group v9fs_attr_group = {
++	.attrs = v9fs_attrs,
++};
++
++/**
++ * v9fs_sysfs_init - Initialize the v9fs sysfs interface
++ *
++ */
++
++static int v9fs_sysfs_init(void)
++{
++	v9fs_kobj = kobject_create_and_add("9p", fs_kobj);
++	if (!v9fs_kobj)
++		return -ENOMEM;
++
++	if (sysfs_create_group(v9fs_kobj, &v9fs_attr_group)) {
++		kobject_put(v9fs_kobj);
++		return -ENOMEM;
++	}
++
++	return 0;
++}
++
++/**
++ * v9fs_sysfs_cleanup - Unregister the v9fs sysfs interface
++ *
++ */
++
++static void v9fs_sysfs_cleanup(void)
++{
++	sysfs_remove_group(v9fs_kobj, &v9fs_attr_group);
++	kobject_put(v9fs_kobj);
++}
++
++/**
++ * init_v9fs - Initialize module
+  *
+  */
+ 
+ static int __init init_v9fs(void)
+ {
++	int err;
+ 	printk(KERN_INFO "Installing v9fs 9p2000 file system support\n");
+ 	/* TODO: Setup list of registered trasnport modules */
+-	return register_filesystem(&v9fs_fs_type);
++	err = register_filesystem(&v9fs_fs_type);
++	if (err < 0) {
++		printk(KERN_ERR "Failed to register filesystem\n");
++		return err;
++	}
++
++	err = v9fs_cache_register();
++	if (err < 0) {
++		printk(KERN_ERR "Failed to register v9fs for caching\n");
++		goto out_fs_unreg;
++	}
++
++	err = v9fs_sysfs_init();
++	if (err < 0) {
++		printk(KERN_ERR "Failed to register with sysfs\n");
++		goto out_sysfs_cleanup;
++	}
++
++	return 0;
++
++out_sysfs_cleanup:
++	v9fs_sysfs_cleanup();
++
++out_fs_unreg:
++	unregister_filesystem(&v9fs_fs_type);
++
++	return err;
+ }
+ 
+ /**
+- * v9fs_init - shutdown module
++ * exit_v9fs - shutdown module
+  *
+  */
+ 
+ static void __exit exit_v9fs(void)
+ {
++	v9fs_sysfs_cleanup();
++	v9fs_cache_unregister();
+ 	unregister_filesystem(&v9fs_fs_type);
+ }
+ 
+diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
+index 38762bf102a9..019f4ccb70c1 100644
+--- a/fs/9p/v9fs.h
++++ b/fs/9p/v9fs.h
+@@ -51,6 +51,7 @@ enum p9_session_flags {
+ enum p9_cache_modes {
+ 	CACHE_NONE,
+ 	CACHE_LOOSE,
++	CACHE_FSCACHE,
+ };
+ 
+ /**
+@@ -60,6 +61,8 @@ enum p9_cache_modes {
+  * @debug: debug level
+  * @afid: authentication handle
+  * @cache: cache mode of type &p9_cache_modes
++ * @cachetag: the tag of the cache associated with this session
++ * @fscache: session cookie associated with FS-Cache
+  * @options: copy of options string given by user
+  * @uname: string user name to mount hierarchy as
+  * @aname: mount specifier for remote hierarchy
+@@ -68,7 +71,7 @@ enum p9_cache_modes {
+  * @dfltgid: default numeric groupid to mount hierarchy as
+  * @uid: if %V9FS_ACCESS_SINGLE, the numeric uid which mounted the hierarchy
+  * @clnt: reference to 9P network client instantiated for this session
+- * @debugfs_dir: reference to debugfs_dir which can be used for add'l debug
++ * @slist: reference to list of registered 9p sessions
+  *
+  * This structure holds state for each session instance established during
+  * a sys_mount() .
+@@ -84,6 +87,10 @@ struct v9fs_session_info {
+ 	unsigned short debug;
+ 	unsigned int afid;
+ 	unsigned int cache;
++#ifdef CONFIG_9P_FSCACHE
++	char *cachetag;
++	struct fscache_cookie *fscache;
++#endif
+ 
+ 	char *uname;		/* user name to mount as */
+ 	char *aname;		/* name of remote hierarchy being mounted */
+@@ -92,11 +99,9 @@ struct v9fs_session_info {
+ 	unsigned int dfltgid;	/* default gid for legacy support */
+ 	u32 uid;		/* if ACCESS_SINGLE, the uid that has access */
+ 	struct p9_client *clnt;	/* 9p client */
+-	struct dentry *debugfs_dir;
++	struct list_head slist; /* list of sessions registered with v9fs */
+ };
+ 
+-extern struct dentry *v9fs_debugfs_root;
+-
+ struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *,
+ 									char *);
+ void v9fs_session_close(struct v9fs_session_info *v9ses);
+diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
+index f0c7de78e205..3a7560e35865 100644
+--- a/fs/9p/v9fs_vfs.h
++++ b/fs/9p/v9fs_vfs.h
+@@ -44,7 +44,13 @@ extern const struct file_operations v9fs_dir_operations;
+ extern const struct dentry_operations v9fs_dentry_operations;
+ extern const struct dentry_operations v9fs_cached_dentry_operations;
+ 
++#ifdef CONFIG_9P_FSCACHE
++struct inode *v9fs_alloc_inode(struct super_block *sb);
++void v9fs_destroy_inode(struct inode *inode);
++#endif
++
+ struct inode *v9fs_get_inode(struct super_block *sb, int mode);
++void v9fs_clear_inode(struct inode *inode);
+ ino_t v9fs_qid2ino(struct p9_qid *qid);
+ void v9fs_stat2inode(struct p9_wstat *, struct inode *, struct super_block *);
+ int v9fs_dir_release(struct inode *inode, struct file *filp);
+diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
+index 92828281a30b..90e38449f4b3 100644
+--- a/fs/9p/vfs_addr.c
++++ b/fs/9p/vfs_addr.c
+@@ -38,6 +38,7 @@
+ 
+ #include "v9fs.h"
+ #include "v9fs_vfs.h"
++#include "cache.h"
+ 
+ /**
+  * v9fs_vfs_readpage - read an entire page in from 9P
+@@ -52,18 +53,31 @@ static int v9fs_vfs_readpage(struct file *filp, struct page *page)
+ 	int retval;
+ 	loff_t offset;
+ 	char *buffer;
++	struct inode *inode;
+ 
++	inode = page->mapping->host;
+ 	P9_DPRINTK(P9_DEBUG_VFS, "\n");
++
++	BUG_ON(!PageLocked(page));
++
++	retval = v9fs_readpage_from_fscache(inode, page);
++	if (retval == 0)
++		return retval;
++
+ 	buffer = kmap(page);
+ 	offset = page_offset(page);
+ 
+ 	retval = v9fs_file_readn(filp, buffer, NULL, PAGE_CACHE_SIZE, offset);
+-	if (retval < 0)
++	if (retval < 0) {
++		v9fs_uncache_page(inode, page);
+ 		goto done;
++	}
+ 
+ 	memset(buffer + retval, 0, PAGE_CACHE_SIZE - retval);
+ 	flush_dcache_page(page);
+ 	SetPageUptodate(page);
++
++	v9fs_readpage_to_fscache(inode, page);
+ 	retval = 0;
+ 
+ done:
+@@ -72,6 +86,78 @@ static int v9fs_vfs_readpage(struct file *filp, struct page *page)
+ 	return retval;
+ }
+ 
++/**
++ * v9fs_vfs_readpages - read a set of pages from 9P
++ *
++ * @filp: file being read
++ * @mapping: the address space
++ * @pages: list of pages to read
++ * @nr_pages: count of pages to read
++ *
++ */
++
++static int v9fs_vfs_readpages(struct file *filp, struct address_space *mapping,
++			     struct list_head *pages, unsigned nr_pages)
++{
++	int ret = 0;
++	struct inode *inode;
++
++	inode = mapping->host;
++	P9_DPRINTK(P9_DEBUG_VFS, "inode: %p file: %p\n", inode, filp);
++
++	ret = v9fs_readpages_from_fscache(inode, mapping, pages, &nr_pages);
++	if (ret == 0)
++		return ret;
++
++	ret = read_cache_pages(mapping, pages, (void *)v9fs_vfs_readpage, filp);
++	P9_DPRINTK(P9_DEBUG_VFS, "  = %d\n", ret);
++	return ret;
++}
++
++/**
++ * v9fs_release_page - release the private state associated with a page
++ *
++ * Returns 1 if the page can be released, false otherwise.
++ */
++
++static int v9fs_release_page(struct page *page, gfp_t gfp)
++{
++	if (PagePrivate(page))
++		return 0;
++
++	return v9fs_fscache_release_page(page, gfp);
++}
++
++/**
++ * v9fs_invalidate_page - Invalidate a page completely or partially
++ *
++ * @page: structure to page
++ * @offset: offset in the page
++ */
++
++static void v9fs_invalidate_page(struct page *page, unsigned long offset)
++{
++	if (offset == 0)
++		v9fs_fscache_invalidate_page(page);
++}
++
++/**
++ * v9fs_launder_page - Writeback a dirty page
++ * Since the writes go directly to the server, we simply return a 0
++ * here to indicate success.
++ *
++ * Returns 0 on success.
++ */
++
++static int v9fs_launder_page(struct page *page)
++{
++	return 0;
++}
++
+ const struct address_space_operations v9fs_addr_operations = {
+       .readpage = v9fs_vfs_readpage,
++      .readpages = v9fs_vfs_readpages,
++      .releasepage = v9fs_release_page,
++      .invalidatepage = v9fs_invalidate_page,
++      .launder_page = v9fs_launder_page,
+ };
+diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
+index cafaa46434ba..3902bf43a088 100644
+--- a/fs/9p/vfs_file.c
++++ b/fs/9p/vfs_file.c
+@@ -41,6 +41,7 @@
+ #include "v9fs.h"
+ #include "v9fs_vfs.h"
+ #include "fid.h"
++#include "cache.h"
+ 
+ static const struct file_operations v9fs_cached_file_operations;
+ 
+@@ -86,6 +87,10 @@ int v9fs_file_open(struct inode *inode, struct file *file)
+ 		/* enable cached file options */
+ 		if(file->f_op == &v9fs_file_operations)
+ 			file->f_op = &v9fs_cached_file_operations;
++
++#ifdef CONFIG_9P_FSCACHE
++		v9fs_cache_inode_set_cookie(inode, file);
++#endif
+ 	}
+ 
+ 	return 0;
+@@ -238,8 +243,9 @@ v9fs_file_write(struct file *filp, const char __user * data,
+ 	if (total > 0) {
+ 		pg_start = origin >> PAGE_CACHE_SHIFT;
+ 		pg_end = (origin + total - 1) >> PAGE_CACHE_SHIFT;
+-		invalidate_inode_pages2_range(inode->i_mapping, pg_start,
+-								pg_end);
++		if (inode->i_mapping && inode->i_mapping->nrpages)
++			invalidate_inode_pages2_range(inode->i_mapping,
++						      pg_start, pg_end);
+ 		*offset += total;
+ 		i_size_write(inode, i_size_read(inode) + total);
+ 		inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9;
+diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
+index f3bfa87926bd..5947628aefef 100644
+--- a/fs/9p/vfs_inode.c
++++ b/fs/9p/vfs_inode.c
+@@ -40,6 +40,7 @@
+ #include "v9fs.h"
+ #include "v9fs_vfs.h"
+ #include "fid.h"
++#include "cache.h"
+ 
+ static const struct inode_operations v9fs_dir_inode_operations;
+ static const struct inode_operations v9fs_dir_inode_operations_ext;
+@@ -197,6 +198,39 @@ v9fs_blank_wstat(struct p9_wstat *wstat)
+ 	wstat->extension = NULL;
+ }
+ 
++#ifdef CONFIG_9P_FSCACHE
++/**
++ * v9fs_alloc_inode - helper function to allocate an inode
++ * This callback is executed before setting up the inode so that we
++ * can associate a vcookie with each inode.
++ *
++ */
++
++struct inode *v9fs_alloc_inode(struct super_block *sb)
++{
++	struct v9fs_cookie *vcookie;
++	vcookie = (struct v9fs_cookie *)kmem_cache_alloc(vcookie_cache,
++							 GFP_KERNEL);
++	if (!vcookie)
++		return NULL;
++
++	vcookie->fscache = NULL;
++	vcookie->qid = NULL;
++	spin_lock_init(&vcookie->lock);
++	return &vcookie->inode;
++}
++
++/**
++ * v9fs_destroy_inode - destroy an inode
++ *
++ */
++
++void v9fs_destroy_inode(struct inode *inode)
++{
++	kmem_cache_free(vcookie_cache, v9fs_inode2cookie(inode));
++}
++#endif
++
+ /**
+  * v9fs_get_inode - helper function to setup an inode
+  * @sb: superblock
+@@ -326,6 +360,21 @@ v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry)
+ }
+ */
+ 
++
++/**
++ * v9fs_clear_inode - release an inode
++ * @inode: inode to release
++ *
++ */
++void v9fs_clear_inode(struct inode *inode)
++{
++	filemap_fdatawrite(inode->i_mapping);
++
++#ifdef CONFIG_9P_FSCACHE
++	v9fs_cache_inode_put_cookie(inode);
++#endif
++}
++
+ /**
+  * v9fs_inode_from_fid - populate an inode by issuing a attribute request
+  * @v9ses: session information
+@@ -356,8 +405,14 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
+ 
+ 	v9fs_stat2inode(st, ret, sb);
+ 	ret->i_ino = v9fs_qid2ino(&st->qid);
++
++#ifdef CONFIG_9P_FSCACHE
++	v9fs_vcookie_set_qid(ret, &st->qid);
++	v9fs_cache_inode_get_cookie(ret);
++#endif
+ 	p9stat_free(st);
+ 	kfree(st);
++
+ 	return ret;
+ 
+ error:
+@@ -751,7 +806,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ 	P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry);
+ 	err = -EPERM;
+ 	v9ses = v9fs_inode2v9ses(dentry->d_inode);
+-	if (v9ses->cache == CACHE_LOOSE)
++	if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
+ 		return simple_getattr(mnt, dentry, stat);
+ 
+ 	fid = v9fs_fid_lookup(dentry);
+diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
+index 8961f1a8f668..14a86448572c 100644
+--- a/fs/9p/vfs_super.c
++++ b/fs/9p/vfs_super.c
+@@ -44,20 +44,8 @@
+ #include "v9fs_vfs.h"
+ #include "fid.h"
+ 
+-static void v9fs_clear_inode(struct inode *);
+ static const struct super_operations v9fs_super_ops;
+ 
+-/**
+- * v9fs_clear_inode - release an inode
+- * @inode: inode to release
+- *
+- */
+-
+-static void v9fs_clear_inode(struct inode *inode)
+-{
+-	filemap_fdatawrite(inode->i_mapping);
+-}
+-
+ /**
+  * v9fs_set_super - set the superblock
+  * @s: super block
+@@ -220,6 +208,10 @@ v9fs_umount_begin(struct super_block *sb)
+ }
+ 
+ static const struct super_operations v9fs_super_ops = {
++#ifdef CONFIG_9P_FSCACHE
++	.alloc_inode = v9fs_alloc_inode,
++	.destroy_inode = v9fs_destroy_inode,
++#endif
+ 	.statfs = simple_statfs,
+ 	.clear_inode = v9fs_clear_inode,
+ 	.show_options = generic_show_options,
+diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h
+index b77c1478c99f..a7fb54808a23 100644
+--- a/include/net/9p/9p.h
++++ b/include/net/9p/9p.h
+@@ -38,6 +38,8 @@
+  * @P9_DEBUG_SLABS: memory management tracing
+  * @P9_DEBUG_FCALL: verbose dump of protocol messages
+  * @P9_DEBUG_FID: fid allocation/deallocation tracking
++ * @P9_DEBUG_PKT: packet marshalling/unmarshalling
++ * @P9_DEBUG_FSC: FS-cache tracing
+  *
+  * These flags are passed at mount time to turn on various levels of
+  * verbosity and tracing which will be output to the system logs.
+@@ -54,6 +56,7 @@ enum p9_debug_flags {
+ 	P9_DEBUG_FCALL =	(1<<8),
+ 	P9_DEBUG_FID =		(1<<9),
+ 	P9_DEBUG_PKT =		(1<<10),
++	P9_DEBUG_FSC =		(1<<11),
+ };
+ 
+ #ifdef CONFIG_NET_9P_DEBUG

commit 637d020a02cd734bf27acfc56c6d942cddd9eb80
+Author: Abhishek Kulkarni 
+Date:   Tue Sep 22 11:34:05 2009 -0500
+
+    9p: Fix the incorrect update of inode size in v9fs_file_write()
+    
+    When using the cache=loose flags, the inode's size was not being
+    updated correctly on a remote write. Thus subsequent reads of
+    the whole file resulted in a truncated read. Fix it.
+    
+    Signed-off-by: Abhishek Kulkarni 
+    Signed-off-by: Eric Van Hensbergen 
+
+diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
+index de7690eec4d8..cafaa46434ba 100644
+--- a/fs/9p/vfs_file.c
++++ b/fs/9p/vfs_file.c
+@@ -32,6 +32,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -210,6 +211,7 @@ v9fs_file_write(struct file *filp, const char __user * data,
+ 	struct p9_client *clnt;
+ 	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	int origin = *offset;
++	unsigned long pg_start, pg_end;
+ 
+ 	P9_DPRINTK(P9_DEBUG_VFS, "data %p count %d offset %x\n", data,
+ 		(int)count, (int)*offset);
+@@ -225,7 +227,7 @@ v9fs_file_write(struct file *filp, const char __user * data,
+ 		if (count < rsize)
+ 			rsize = count;
+ 
+-		n = p9_client_write(fid, NULL, data+total, *offset+total,
++		n = p9_client_write(fid, NULL, data+total, origin+total,
+ 									rsize);
+ 		if (n <= 0)
+ 			break;
+@@ -234,13 +236,12 @@ v9fs_file_write(struct file *filp, const char __user * data,
+ 	} while (count > 0);
+ 
+ 	if (total > 0) {
+-		invalidate_inode_pages2_range(inode->i_mapping, origin,
+-								origin+total);
++		pg_start = origin >> PAGE_CACHE_SHIFT;
++		pg_end = (origin + total - 1) >> PAGE_CACHE_SHIFT;
++		invalidate_inode_pages2_range(inode->i_mapping, pg_start,
++								pg_end);
+ 		*offset += total;
+-	}
+-
+-	if (*offset > i_size_read(inode)) {
+-		i_size_write(inode, *offset);
++		i_size_write(inode, i_size_read(inode) + total);
+ 		inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9;
+ 	}
+ 

commit 7549ae3e81cc45908cbeee54a52b24f247fb0a2d
+Author: Abhishek Kulkarni 
+Date:   Tue Sep 22 11:34:05 2009 -0500
+
+    9p: Use the i_size_[read, write]() macros instead of using inode->i_size directly.
+    
+    Change all occurrence of inode->i_size with i_size_read() or i_size_write()
+    as appropriate.
+    
+    Signed-off-by: Abhishek Kulkarni 
+    Signed-off-by: Eric Van Hensbergen 
+
+diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
+index 68bf2af6c389..de7690eec4d8 100644
+--- a/fs/9p/vfs_file.c
++++ b/fs/9p/vfs_file.c
+@@ -72,7 +72,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
+ 			return err;
+ 		}
+ 		if (omode & P9_OTRUNC) {
+-			inode->i_size = 0;
++			i_size_write(inode, 0);
+ 			inode->i_blocks = 0;
+ 		}
+ 		if ((file->f_flags & O_APPEND) && (!v9fs_extended(v9ses)))
+@@ -239,9 +239,9 @@ v9fs_file_write(struct file *filp, const char __user * data,
+ 		*offset += total;
+ 	}
+ 
+-	if (*offset > inode->i_size) {
+-		inode->i_size = *offset;
+-		inode->i_blocks = (inode->i_size + 512 - 1) >> 9;
++	if (*offset > i_size_read(inode)) {
++		i_size_write(inode, *offset);
++		inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9;
+ 	}
+ 
+ 	if (n < 0)
+diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
+index 06a223d50a81..f3bfa87926bd 100644
+--- a/fs/9p/vfs_inode.c
++++ b/fs/9p/vfs_inode.c
+@@ -872,10 +872,10 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
+ 	} else
+ 		inode->i_rdev = 0;
+ 
+-	inode->i_size = stat->length;
++	i_size_write(inode, stat->length);
+ 
+ 	/* not real number of blocks, but 512 byte ones ... */
+-	inode->i_blocks = (inode->i_size + 512 - 1) >> 9;
++	inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9;
+ }
+ 
+ /**

commit 4b53e4b500779230aedd5355940aeaaed0b5353b
+Author: Abhishek Kulkarni 
+Date:   Mon Aug 17 16:42:28 2009 -0500
+
+    9p: remove unnecessary v9fses->options which duplicates the mount string
+    
+    The mount options string is saved in sb->s_options. This patch removes
+    the redundant duplicating of the mount options. Also, since we are not
+    displaying anything special in show options, we replace v9fs_show_options
+    with generic_show_options for now.
+    
+    Signed-off-by: Abhishek Kulkarni 
+    Signed-off-by: Eric Van Hensbergen 
+
+diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
+index 332b5ff02fec..f7003cfac63d 100644
+--- a/fs/9p/v9fs.c
++++ b/fs/9p/v9fs.c
+@@ -76,7 +76,7 @@ static const match_table_t tokens = {
+  * Return 0 upon success, -ERRNO upon failure.
+  */
+ 
+-static int v9fs_parse_options(struct v9fs_session_info *v9ses)
++static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
+ {
+ 	char *options;
+ 	substring_t args[MAX_OPT_ARGS];
+@@ -90,10 +90,10 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses)
+ 	v9ses->debug = 0;
+ 	v9ses->cache = 0;
+ 
+-	if (!v9ses->options)
++	if (!opts)
+ 		return 0;
+ 
+-	options = kstrdup(v9ses->options, GFP_KERNEL);
++	options = kstrdup(opts, GFP_KERNEL);
+ 	if (!options) {
+ 		P9_DPRINTK(P9_DEBUG_ERROR,
+ 			   "failed to allocate copy of option string\n");
+@@ -206,24 +206,14 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
+ 	v9ses->uid = ~0;
+ 	v9ses->dfltuid = V9FS_DEFUID;
+ 	v9ses->dfltgid = V9FS_DEFGID;
+-	if (data) {
+-		v9ses->options = kstrdup(data, GFP_KERNEL);
+-		if (!v9ses->options) {
+-			P9_DPRINTK(P9_DEBUG_ERROR,
+-			   "failed to allocate copy of option string\n");
+-			retval = -ENOMEM;
+-			goto error;
+-		}
+-	}
+ 
+-	rc = v9fs_parse_options(v9ses);
++	rc = v9fs_parse_options(v9ses, data);
+ 	if (rc < 0) {
+ 		retval = rc;
+ 		goto error;
+ 	}
+ 
+-	v9ses->clnt = p9_client_create(dev_name, v9ses->options);
+-
++	v9ses->clnt = p9_client_create(dev_name, data);
+ 	if (IS_ERR(v9ses->clnt)) {
+ 		retval = PTR_ERR(v9ses->clnt);
+ 		v9ses->clnt = NULL;
+@@ -280,7 +270,6 @@ void v9fs_session_close(struct v9fs_session_info *v9ses)
+ 
+ 	__putname(v9ses->uname);
+ 	__putname(v9ses->aname);
+-	kfree(v9ses->options);
+ }
+ 
+ /**
+diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
+index a7d567192998..38762bf102a9 100644
+--- a/fs/9p/v9fs.h
++++ b/fs/9p/v9fs.h
+@@ -85,7 +85,6 @@ struct v9fs_session_info {
+ 	unsigned int afid;
+ 	unsigned int cache;
+ 
+-	char *options;		/* copy of mount options */
+ 	char *uname;		/* user name to mount as */
+ 	char *aname;		/* name of remote hierarchy being mounted */
+ 	unsigned int maxdata;	/* max data for client interface */
+diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
+index 072dce094477..8961f1a8f668 100644
+--- a/fs/9p/vfs_super.c
++++ b/fs/9p/vfs_super.c
+@@ -81,7 +81,7 @@ static int v9fs_set_super(struct super_block *s, void *data)
+ 
+ static void
+ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
+-		int flags)
++		int flags, void *data)
+ {
+ 	sb->s_maxbytes = MAX_LFS_FILESIZE;
+ 	sb->s_blocksize_bits = fls(v9ses->maxdata - 1);
+@@ -91,6 +91,8 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
+ 
+ 	sb->s_flags = flags | MS_ACTIVE | MS_SYNCHRONOUS | MS_DIRSYNC |
+ 	    MS_NOATIME;
++
++	save_mount_options(sb, data);
+ }
+ 
+ /**
+@@ -139,7 +141,7 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
+ 		retval = PTR_ERR(sb);
+ 		goto free_stat;
+ 	}
+-	v9fs_fill_super(sb, v9ses, flags);
++	v9fs_fill_super(sb, v9ses, flags, data);
+ 
+ 	inode = v9fs_get_inode(sb, S_IFDIR | mode);
+ 	if (IS_ERR(inode)) {
+@@ -208,21 +210,6 @@ static void v9fs_kill_super(struct super_block *s)
+ 	P9_DPRINTK(P9_DEBUG_VFS, "exiting kill_super\n");
+ }
+ 
+-/**
+- * v9fs_show_options - Show mount options in /proc/mounts
+- * @m: seq_file to write to
+- * @mnt: mount descriptor
+- *
+- */
+-
+-static int v9fs_show_options(struct seq_file *m, struct vfsmount *mnt)
+-{
+-	struct v9fs_session_info *v9ses = mnt->mnt_sb->s_fs_info;
+-	if (v9ses->options != NULL)
+-		seq_printf(m, ",%s", v9ses->options);
+-	return 0;
+-}
+-
+ static void
+ v9fs_umount_begin(struct super_block *sb)
+ {
+@@ -235,7 +222,7 @@ v9fs_umount_begin(struct super_block *sb)
+ static const struct super_operations v9fs_super_ops = {
+ 	.statfs = simple_statfs,
+ 	.clear_inode = v9fs_clear_inode,
+-	.show_options = v9fs_show_options,
++	.show_options = generic_show_options,
+ 	.umount_begin = v9fs_umount_begin,
+ };
+ 

commit 0aad37ef3deed118d3816e1d1a600eb2ec9dcb87
+Author: Abhishek Kulkarni 
+Date:   Mon Aug 17 16:38:45 2009 -0500
+
+    net/9p: insulate the client against an invalid error code sent by a 9p server
+    
+    A looney tunes server sending an invalid error code (which is !IS_ERR_VALUE)
+    can result in a client oops. So fix it by adding a check and converting unknown
+    or invalid error codes to -ESERVERFAULT.
+    
+    Signed-off-by: Abhishek Kulkarni 
+    Signed-off-by: Eric Van Hensbergen 
+
+diff --git a/net/9p/client.c b/net/9p/client.c
+index 7bbd2d5ae8d3..5bf5f227dbe0 100644
+--- a/net/9p/client.c
++++ b/net/9p/client.c
+@@ -411,14 +411,9 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
+ 		if (c->dotu)
+ 			err = -ecode;
+ 
+-		if (!err) {
++		if (!err || !IS_ERR_VALUE(err))
+ 			err = p9_errstr2errno(ename, strlen(ename));
+ 
+-			/* string match failed */
+-			if (!err)
+-				err = -ESERVERFAULT;
+-		}
+-
+ 		P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename);
+ 
+ 		kfree(ename);
+diff --git a/net/9p/error.c b/net/9p/error.c
+index fdebe4314062..52518512a93e 100644
+--- a/net/9p/error.c
++++ b/net/9p/error.c
+@@ -239,7 +239,7 @@ int p9_errstr2errno(char *errstr, int len)
+ 		errstr[len] = 0;
+ 		printk(KERN_ERR "%s: server reported unknown error %s\n",
+ 			__func__, errstr);
+-		errno = 1;
++		errno = ESERVERFAULT;
+ 	}
+ 
+ 	return -errno;

commit 48559b4c30708ebdc849483da9fb83ee08c6c908
+Author: Abhishek Kulkarni 
+Date:   Mon Aug 17 16:32:18 2009 -0500
+
+    9p: Add missing cast for the error return value in v9fs_get_inode
+    
+    Cast the error return value (ENOMEM) in v9fs_get_inode() to its
+    correct type using ERR_PTR.
+    
+    Signed-off-by: Abhishek Kulkarni 
+    Signed-off-by: Eric Van Hensbergen 
+
+diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
+index fac30d21851f..06a223d50a81 100644
+--- a/fs/9p/vfs_inode.c
++++ b/fs/9p/vfs_inode.c
+@@ -215,7 +215,7 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
+ 	inode = new_inode(sb);
+ 	if (!inode) {
+ 		P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n");
+-		return -ENOMEM;
++		return ERR_PTR(-ENOMEM);
+ 	}
+ 
+ 	inode->i_mode = mode;

commit 4d3297ca5bf37ff5956f76fb352e009880aad62d
+Author: Abhishek Kulkarni 
+Date:   Sun Jul 19 13:41:51 2009 -0600
+
+    9p: Remove redundant inode uid/gid assignment
+    
+    Remove a redundant update of inode's i_uid and i_gid
+    after v9fs_get_inode() since the latter already sets up
+    a new inode and sets the proper uid and gid values.
+    
+    Signed-off-by: Abhishek Kulkarni 
+    Signed-off-by: Eric Van Hensbergen 
+
+diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
+index 2495af4ad9a6..072dce094477 100644
+--- a/fs/9p/vfs_super.c
++++ b/fs/9p/vfs_super.c
+@@ -113,8 +113,6 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
+ 	struct v9fs_session_info *v9ses = NULL;
+ 	struct p9_wstat *st = NULL;
+ 	int mode = S_IRWXUGO | S_ISVTX;
+-	uid_t uid = current_fsuid();
+-	gid_t gid = current_fsgid();
+ 	struct p9_fid *fid;
+ 	int retval = 0;
+ 
+@@ -149,9 +147,6 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
+ 		goto release_sb;
+ 	}
+ 
+-	inode->i_uid = uid;
+-	inode->i_gid = gid;
+-
+ 	root = d_alloc_root(inode);
+ 	if (!root) {
+ 		iput(inode);

commit 1b5ab3e86712b6be38ebbe0d821387c1d8f91d7c
+Author: Abhishek Kulkarni 
+Date:   Sun Jul 19 13:41:52 2009 -0600
+
+    9p: Fix possible regressions when ->get_sb fails.
+    
+    ->get_sb can fail causing some badness. this patch fixes
+       * clear sb->fs_s_info in kill_sb.
+       * deactivate_locked_super() calls kill_sb (v9fs_kill_super) which closes the
+         destroys the client, clunks all its fids and closes the v9fs session.
+         Attempting to do it twice will cause an oops.
+    
+    Signed-off-by: Abhishek Kulkarni 
+    Signed-off-by: Eric Van Hensbergen 
+
+diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
+index a9d7d08cfbe8..2495af4ad9a6 100644
+--- a/fs/9p/vfs_super.c
++++ b/fs/9p/vfs_super.c
+@@ -120,7 +120,6 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
+ 
+ 	P9_DPRINTK(P9_DEBUG_VFS, " \n");
+ 
+-	st = NULL;
+ 	v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL);
+ 	if (!v9ses)
+ 		return -ENOMEM;
+@@ -173,10 +172,8 @@ P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n");
+ 	simple_set_mnt(mnt, sb);
+ 	return 0;
+ 
+-release_sb:
+-	deactivate_locked_super(sb);
+-
+ free_stat:
++	p9stat_free(st);
+ 	kfree(st);
+ 
+ clunk_fid:
+@@ -185,7 +182,12 @@ P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n");
+ close_session:
+ 	v9fs_session_close(v9ses);
+ 	kfree(v9ses);
++	return retval;
+ 
++release_sb:
++	p9stat_free(st);
++	kfree(st);
++	deactivate_locked_super(sb);
+ 	return retval;
+ }
+ 
+@@ -207,6 +209,7 @@ static void v9fs_kill_super(struct super_block *s)
+ 
+ 	v9fs_session_close(v9ses);
+ 	kfree(v9ses);
++	s->s_fs_info = NULL;
+ 	P9_DPRINTK(P9_DEBUG_VFS, "exiting kill_super\n");
+ }
+ 

commit 4f4038328da5eb9cc237b51d3fe68138fd3fea14
+Author: Abhishek Kulkarni 
+Date:   Sun Jul 19 13:41:53 2009 -0600
+
+    9p: Fix v9fs show_options
+    
+    Add the delimiter ',' before the options when they are passed
+    and check if no option parameters are passed to prevent displaying
+    NULL in /proc/mounts.
+    
+    Signed-off-by: Abhishek Kulkarni 
+    Signed-off-by: Eric Van Hensbergen 
+
+diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
+index 38d695d66a0b..a9d7d08cfbe8 100644
+--- a/fs/9p/vfs_super.c
++++ b/fs/9p/vfs_super.c
+@@ -220,8 +220,8 @@ static void v9fs_kill_super(struct super_block *s)
+ static int v9fs_show_options(struct seq_file *m, struct vfsmount *mnt)
+ {
+ 	struct v9fs_session_info *v9ses = mnt->mnt_sb->s_fs_info;
+-
+-	seq_printf(m, "%s", v9ses->options);
++	if (v9ses->options != NULL)
++		seq_printf(m, ",%s", v9ses->options);
+ 	return 0;
+ }
+ 

commit 02bc35672b2fdf251e264adca5407792f63191e4
+Author: Abhishek Kulkarni 
+Date:   Sun Jul 19 13:41:54 2009 -0600
+
+    9p: Fix possible memleak in v9fs_inode_from fid.
+    
+    Add missing p9stat_free in v9fs_inode_from_fid to avoid
+    any possible leaks.
+    
+    Signed-off-by: Abhishek Kulkarni 
+    Signed-off-by: Eric Van Hensbergen 
+
+diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
+index f22668afd0d6..fac30d21851f 100644
+--- a/fs/9p/vfs_inode.c
++++ b/fs/9p/vfs_inode.c
+@@ -344,30 +344,25 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
+ 
+ 	ret = NULL;
+ 	st = p9_client_stat(fid);
+-	if (IS_ERR(st)) {
+-		err = PTR_ERR(st);
+-		st = NULL;
+-		goto error;
+-	}
++	if (IS_ERR(st))
++		return ERR_CAST(st);
+ 
+ 	umode = p9mode2unixmode(v9ses, st->mode);
+ 	ret = v9fs_get_inode(sb, umode);
+ 	if (IS_ERR(ret)) {
+ 		err = PTR_ERR(ret);
+-		ret = NULL;
+ 		goto error;
+ 	}
+ 
+ 	v9fs_stat2inode(st, ret, sb);
+ 	ret->i_ino = v9fs_qid2ino(&st->qid);
++	p9stat_free(st);
+ 	kfree(st);
+ 	return ret;
+ 
+ error:
++	p9stat_free(st);
+ 	kfree(st);
+-	if (ret)
+-		iput(ret);
+-
+ 	return ERR_PTR(err);
+ }
+ 

commit 0e15597ebfe00e28857185f46aba00f400480ffe
+Author: Abhishek Kulkarni 
+Date:   Sun Jul 19 13:41:55 2009 -0600
+
+    9p: minor comment fixes
+    
+    Fix the comments -- mostly the improper and/or missing descriptions
+    of function parameters.
+    
+    Signed-off-by: Abhishek Kulkarni 
+    Signed-off-by: Eric Van Hensbergen 
+
+diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
+index 0c8af1abf603..f22668afd0d6 100644
+--- a/fs/9p/vfs_inode.c
++++ b/fs/9p/vfs_inode.c
+@@ -171,7 +171,6 @@ int v9fs_uflags2omode(int uflags, int extended)
+ 
+ /**
+  * v9fs_blank_wstat - helper function to setup a 9P stat structure
+- * @v9ses: 9P session info (for determining extended mode)
+  * @wstat: structure to initialize
+  *
+  */
+@@ -410,9 +409,9 @@ v9fs_open_created(struct inode *inode, struct file *file)
+  * @v9ses: session information
+  * @dir: directory that dentry is being created in
+  * @dentry:  dentry that is being created
++ * @extension: 9p2000.u extension string to support devices, etc.
+  * @perm: create permissions
+  * @mode: open mode
+- * @extension: 9p2000.u extension string to support devices, etc.
+  *
+  */
+ static struct p9_fid *
+diff --git a/net/9p/client.c b/net/9p/client.c
+index 787ccddb85ea..7bbd2d5ae8d3 100644
+--- a/net/9p/client.c
++++ b/net/9p/client.c
+@@ -60,9 +60,9 @@ static struct p9_req_t *
+ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...);
+ 
+ /**
+- * v9fs_parse_options - parse mount options into session structure
+- * @options: options string passed from mount
+- * @v9ses: existing v9fs session information
++ * parse_options - parse mount options into client structure
++ * @opts: options string passed from mount
++ * @clnt: existing v9fs client information
+  *
+  * Return 0 upon success, -ERRNO upon failure
+  */
+@@ -232,7 +232,7 @@ EXPORT_SYMBOL(p9_tag_lookup);
+ 
+ /**
+  * p9_tag_init - setup tags structure and contents
+- * @tags: tags structure from the client struct
++ * @c:  v9fs client struct
+  *
+  * This initializes the tags structure for each client instance.
+  *
+@@ -258,7 +258,7 @@ static int p9_tag_init(struct p9_client *c)
+ 
+ /**
+  * p9_tag_cleanup - cleans up tags structure and reclaims resources
+- * @tags: tags structure from the client struct
++ * @c:  v9fs client struct
+  *
+  * This frees resources associated with the tags structure
+  *
+@@ -430,8 +430,8 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
+ 
+ /**
+  * p9_client_flush - flush (cancel) a request
+- * c: client state
+- * req: request to cancel
++ * @c: client state
++ * @oldreq: request to cancel
+  *
+  * This sents a flush for a particular requests and links
+  * the flush request to the original request.  The current
+diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
+index 8c2588e4edc0..8d934dd7fd54 100644
+--- a/net/9p/trans_fd.c
++++ b/net/9p/trans_fd.c
+@@ -119,8 +119,8 @@ struct p9_poll_wait {
+  * @wpos: write position for current frame
+  * @wsize: amount of data to write for current frame
+  * @wbuf: current write buffer
++ * @poll_pending_link: pending links to be polled per conn
+  * @poll_wait: array of wait_q's for various worker threads
+- * @poll_waddr: ????
+  * @pt: poll state
+  * @rq: current read work
+  * @wq: current write work
+@@ -700,9 +700,9 @@ static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req)
+ }
+ 
+ /**
+- * parse_options - parse mount options into session structure
+- * @options: options string passed from mount
+- * @opts: transport-specific structure to parse options into
++ * parse_opts - parse mount options into p9_fd_opts structure
++ * @params: options string passed from mount
++ * @opts: fd transport-specific structure to parse options into
+  *
+  * Returns 0 upon success, -ERRNO upon failure
+  */
+diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c
+index ac4990041ebb..65cb29db03f8 100644
+--- a/net/9p/trans_rdma.c
++++ b/net/9p/trans_rdma.c
+@@ -67,14 +67,15 @@
+  * @pd: Protection Domain pointer
+  * @qp: Queue Pair pointer
+  * @cq: Completion Queue pointer
++ * @dm_mr: DMA Memory Region pointer
+  * @lkey: The local access only memory region key
+  * @timeout: Number of uSecs to wait for connection management events
+  * @sq_depth: The depth of the Send Queue
+  * @sq_sem: Semaphore for the SQ
+  * @rq_depth: The depth of the Receive Queue.
++ * @rq_count: Count of requests in the Receive Queue.
+  * @addr: The remote peer's address
+  * @req_lock: Protects the active request list
+- * @send_wait: Wait list when the SQ fills up
+  * @cm_done: Completion event for connection management tracking
+  */
+ struct p9_trans_rdma {
+@@ -154,9 +155,9 @@ static match_table_t tokens = {
+ };
+ 
+ /**
+- * parse_options - parse mount options into session structure
+- * @options: options string passed from mount
+- * @opts: transport-specific structure to parse options into
++ * parse_opts - parse mount options into rdma options structure
++ * @params: options string passed from mount
++ * @opts: rdma transport-specific structure to parse options into
+  *
+  * Returns 0 upon success, -ERRNO upon failure
+  */
+diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
+index a49484e67e1d..9bf0b737aa51 100644
+--- a/net/9p/trans_virtio.c
++++ b/net/9p/trans_virtio.c
+@@ -57,11 +57,9 @@ static int chan_index;
+  * @initialized: whether the channel is initialized
+  * @inuse: whether the channel is in use
+  * @lock: protects multiple elements within this structure
++ * @client: client instance
+  * @vdev: virtio dev associated with this channel
+  * @vq: virtio queue associated with this channel
+- * @tagpool: accounting for tag ids (and request slots)
+- * @reqs: array of request slots
+- * @max_tag: current number of request_slots allocated
+  * @sg: scatter gather list which is used to pack a request (protected?)
+  *
+  * We keep all per-channel information in a structure.
+@@ -92,7 +90,7 @@ static unsigned int rest_of_page(void *data)
+ 
+ /**
+  * p9_virtio_close - reclaim resources of a channel
+- * @trans: transport state
++ * @client: client instance
+  *
+  * This reclaims a channel by freeing its resources and
+  * reseting its inuse flag.
+@@ -181,9 +179,8 @@ static int p9_virtio_cancel(struct p9_client *client, struct p9_req_t *req)
+ 
+ /**
+  * p9_virtio_request - issue a request
+- * @t: transport state
+- * @tc: &p9_fcall request to transmit
+- * @rc: &p9_fcall to put reponse into
++ * @client: client instance issuing the request
++ * @req: request to be issued
+  *
+  */
+ 

commit 2bb541157fe2602af7b9952096d0524f6f9c1e73
+Author: Abhishek Kulkarni 
+Date:   Sun Jul 19 13:41:56 2009 -0600
+
+    9p: Fix possible inode leak in v9fs_get_inode.
+    
+    Add a missing iput when cleaning up if v9fs_get_inode
+    fails after returning a valid inode.
+    
+    Signed-off-by: Abhishek Kulkarni 
+    Signed-off-by: Eric Van Hensbergen 
+
+diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
+index 1fa5f15eaddc..0c8af1abf603 100644
+--- a/fs/9p/vfs_inode.c
++++ b/fs/9p/vfs_inode.c
+@@ -207,65 +207,72 @@ v9fs_blank_wstat(struct p9_wstat *wstat)
+ 
+ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
+ {
++	int err;
+ 	struct inode *inode;
+ 	struct v9fs_session_info *v9ses = sb->s_fs_info;
+ 
+ 	P9_DPRINTK(P9_DEBUG_VFS, "super block: %p mode: %o\n", sb, mode);
+ 
+ 	inode = new_inode(sb);
+-	if (inode) {
+-		inode->i_mode = mode;
+-		inode->i_uid = current_fsuid();
+-		inode->i_gid = current_fsgid();
+-		inode->i_blocks = 0;
+-		inode->i_rdev = 0;
+-		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+-		inode->i_mapping->a_ops = &v9fs_addr_operations;
+-
+-		switch (mode & S_IFMT) {
+-		case S_IFIFO:
+-		case S_IFBLK:
+-		case S_IFCHR:
+-		case S_IFSOCK:
+-			if (!v9fs_extended(v9ses)) {
+-				P9_DPRINTK(P9_DEBUG_ERROR,
+-				      "special files without extended mode\n");
+-				return ERR_PTR(-EINVAL);
+-			}
+-			init_special_inode(inode, inode->i_mode,
+-					   inode->i_rdev);
+-			break;
+-		case S_IFREG:
+-			inode->i_op = &v9fs_file_inode_operations;
+-			inode->i_fop = &v9fs_file_operations;
+-			break;
+-		case S_IFLNK:
+-			if (!v9fs_extended(v9ses)) {
+-				P9_DPRINTK(P9_DEBUG_ERROR,
+-					"extended modes used w/o 9P2000.u\n");
+-				return ERR_PTR(-EINVAL);
+-			}
+-			inode->i_op = &v9fs_symlink_inode_operations;
+-			break;
+-		case S_IFDIR:
+-			inc_nlink(inode);
+-			if (v9fs_extended(v9ses))
+-				inode->i_op = &v9fs_dir_inode_operations_ext;
+-			else
+-				inode->i_op = &v9fs_dir_inode_operations;
+-			inode->i_fop = &v9fs_dir_operations;
+-			break;
+-		default:
++	if (!inode) {
++		P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n");
++		return -ENOMEM;
++	}
++
++	inode->i_mode = mode;
++	inode->i_uid = current_fsuid();
++	inode->i_gid = current_fsgid();
++	inode->i_blocks = 0;
++	inode->i_rdev = 0;
++	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
++	inode->i_mapping->a_ops = &v9fs_addr_operations;
++
++	switch (mode & S_IFMT) {
++	case S_IFIFO:
++	case S_IFBLK:
++	case S_IFCHR:
++	case S_IFSOCK:
++		if (!v9fs_extended(v9ses)) {
+ 			P9_DPRINTK(P9_DEBUG_ERROR,
+-				"BAD mode 0x%x S_IFMT 0x%x\n",
+-				mode, mode & S_IFMT);
+-			return ERR_PTR(-EINVAL);
++				   "special files without extended mode\n");
++			err = -EINVAL;
++			goto error;
+ 		}
+-	} else {
+-		P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n");
+-		return ERR_PTR(-ENOMEM);
++		init_special_inode(inode, inode->i_mode, inode->i_rdev);
++		break;
++	case S_IFREG:
++		inode->i_op = &v9fs_file_inode_operations;
++		inode->i_fop = &v9fs_file_operations;
++		break;
++	case S_IFLNK:
++		if (!v9fs_extended(v9ses)) {
++			P9_DPRINTK(P9_DEBUG_ERROR,
++				   "extended modes used w/o 9P2000.u\n");
++			err = -EINVAL;
++			goto error;
++		}
++		inode->i_op = &v9fs_symlink_inode_operations;
++		break;
++	case S_IFDIR:
++		inc_nlink(inode);
++		if (v9fs_extended(v9ses))
++			inode->i_op = &v9fs_dir_inode_operations_ext;
++		else
++			inode->i_op = &v9fs_dir_inode_operations;
++		inode->i_fop = &v9fs_dir_operations;
++		break;
++	default:
++		P9_DPRINTK(P9_DEBUG_ERROR, "BAD mode 0x%x S_IFMT 0x%x\n",
++			   mode, mode & S_IFMT);
++		err = -EINVAL;
++		goto error;
+ 	}
++
+ 	return inode;
++
++error:
++	iput(inode);
++	return ERR_PTR(err);
+ }
+ 
+ /*

commit 50fb6d2bd7062708892ae7147f30c3ee905b7a3d
+Author: Abhishek Kulkarni 
+Date:   Sun Jul 19 13:41:57 2009 -0600
+
+    9p: Check for error in return value of v9fs_fid_add
+    
+    Check if v9fs_fid_add was successful or not based on its
+    return value.
+    
+    Signed-off-by: Abhishek Kulkarni 
+    Signed-off-by: Eric Van Hensbergen 
+
+diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
+index 81f8bbf12f9f..1fa5f15eaddc 100644
+--- a/fs/9p/vfs_inode.c
++++ b/fs/9p/vfs_inode.c
+@@ -470,7 +470,10 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
+ 		dentry->d_op = &v9fs_dentry_operations;
+ 
+ 	d_instantiate(dentry, inode);
+-	v9fs_fid_add(dentry, fid);
++	err = v9fs_fid_add(dentry, fid);
++	if (err < 0)
++		goto error;
++
+ 	return ofid;
+ 
+ error:

commit 9c9ad6162e2aa1e528ed687ccab87fe681ebbef1
+Author: Abhishek Kulkarni 
+Date:   Tue Jul 14 13:26:52 2009 -0500
+
+    9p: Fix incorrect parameters to v9fs_file_readn.
+    
+    Fix v9fs_vfs_readpage. The offset and size parameters to v9fs_file_readn
+    were interchanged and hence passed incorrectly.
+    
+    Signed-off-by: Abhishek Kulkarni 
+    Signed-off-by: Eric Van Hensbergen 
+
+diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
+index 6fcb1e7095cf..92828281a30b 100644
+--- a/fs/9p/vfs_addr.c
++++ b/fs/9p/vfs_addr.c
+@@ -57,7 +57,7 @@ static int v9fs_vfs_readpage(struct file *filp, struct page *page)
+ 	buffer = kmap(page);
+ 	offset = page_offset(page);
+ 
+-	retval = v9fs_file_readn(filp, buffer, NULL, offset, PAGE_CACHE_SIZE);
++	retval = v9fs_file_readn(filp, buffer, NULL, PAGE_CACHE_SIZE, offset);
+ 	if (retval < 0)
+ 		goto done;
+ 

commit eedfe1c4289216af5a0a7f38e6b2c4d3f07c087f
+Author: Abhishek Kulkarni 
+Date:   Tue Jul 14 13:25:41 2009 -0500
+
+    9p: Possible regression in p9_client_stat
+    
+    Fix a possible regression with p9_client_stat where it can try to kfree
+    an ERR_PTR after an erroneous p9pdu_readf. Also remove an unnecessary data
+    buffer increment in p9_client_read.
+    
+    Signed-off-by: Abhishek Kulkarni 
+    Signed-off-by: Eric Van Hensbergen 
+
+diff --git a/net/9p/client.c b/net/9p/client.c
+index 783a41077403..787ccddb85ea 100644
+--- a/net/9p/client.c
++++ b/net/9p/client.c
+@@ -1098,7 +1098,6 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
+ 
+ 	if (data) {
+ 		memmove(data, dataptr, count);
+-		data += count;
+ 	}
+ 
+ 	if (udata) {
+@@ -1192,9 +1191,9 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid)
+ 
+ 	err = p9pdu_readf(req->rc, clnt->dotu, "wS", &ignored, ret);
+ 	if (err) {
+-		ret = ERR_PTR(err);
+ 		p9pdu_dump(1, req->rc);
+-		goto free_and_error;
++		p9_free_req(clnt, req);
++		goto error;
+ 	}
+ 
+ 	P9_DPRINTK(P9_DEBUG_9P,
+@@ -1211,8 +1210,6 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid)
+ 	p9_free_req(clnt, req);
+ 	return ret;
+ 
+-free_and_error:
+-	p9_free_req(clnt, req);
+ error:
+ 	kfree(ret);
+ 	return ERR_PTR(err);

commit a17d1720aa35623a9bef3707b36242706714bca5
+Author: Abhishek Kulkarni 
+Date:   Tue Jul 14 13:24:10 2009 -0500
+
+    9p: default 9p transport module fix
+    
+    The default 9p transport module is not chosen unless an option parameter (any)
+    is passed to mount, which thus returns a ENOPROTOSUPPORT. This fix moves the
+    check out of parse_opts into p9_client_create.
+    
+    Signed-off-by: Abhishek Kulkarni 
+    Signed-off-by: Eric Van Hensbergen 
+
+diff --git a/net/9p/client.c b/net/9p/client.c
+index dd43a8289b0d..783a41077403 100644
+--- a/net/9p/client.c
++++ b/net/9p/client.c
+@@ -117,9 +117,6 @@ static int parse_opts(char *opts, struct p9_client *clnt)
+ 		}
+ 	}
+ 
+-	if (!clnt->trans_mod)
+-		clnt->trans_mod = v9fs_get_default_trans();
+-
+ 	kfree(options);
+ 	return ret;
+ }
+@@ -689,6 +686,9 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
+ 	if (err < 0)
+ 		goto error;
+ 
++	if (!clnt->trans_mod)
++		clnt->trans_mod = v9fs_get_default_trans();
++
+ 	if (clnt->trans_mod == NULL) {
+ 		err = -EPROTONOSUPPORT;
+ 		P9_DPRINTK(P9_DEBUG_ERROR,

commit 15da4b1612d608a47e095439b3dd1d77ffe20e0c
+Author: Abhishek Kulkarni 
+Date:   Wed Jul 1 08:50:54 2009 +0000
+
+    net/9p: Fix crash due to bad mount parameters.
+    
+    It is not safe to use match_int without checking the token type returned
+    by match_token (especially when the token type returned is Opt_err and
+    args is empty). Fix it.
+    
+    Signed-off-by: Abhishek Kulkarni 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
+index a2a1814c7a8d..8c2588e4edc0 100644
+--- a/net/9p/trans_fd.c
++++ b/net/9p/trans_fd.c
+@@ -735,12 +735,14 @@ static int parse_opts(char *params, struct p9_fd_opts *opts)
+ 		if (!*p)
+ 			continue;
+ 		token = match_token(p, tokens, args);
+-		r = match_int(&args[0], &option);
+-		if (r < 0) {
+-			P9_DPRINTK(P9_DEBUG_ERROR,
+-			 "integer field, but no integer?\n");
+-			ret = r;
+-			continue;
++		if (token != Opt_err) {
++			r = match_int(&args[0], &option);
++			if (r < 0) {
++				P9_DPRINTK(P9_DEBUG_ERROR,
++				"integer field, but no integer?\n");
++				ret = r;
++				continue;
++			}
+ 		}
+ 		switch (token) {
+ 		case Opt_port:

\ No newline at end of file diff --git a/detail/32.html b/detail/32.html new file mode 100644 index 0000000..197d4fc --- /dev/null +++ b/detail/32.html @@ -0,0 +1,807 @@ +

Patches contributed by University of California, Berkeley


commit 922b0375fc93fb1a20c5617e37c389c26bbccb70
+Author: Albert Ou 
+Date:   Fri Sep 27 16:14:18 2019 -0700
+
+    riscv: Fix memblock reservation for device tree blob
+    
+    This fixes an error with how the FDT blob is reserved in memblock.
+    An incorrect physical address calculation exposed the FDT header to
+    unintended corruption, which typically manifested with of_fdt_raw_init()
+    faulting during late boot after fdt_totalsize() returned a wrong value.
+    Systems with smaller physical memory sizes more frequently trigger this
+    issue, as the kernel is more likely to allocate from the DMA32 zone
+    where bbl places the DTB after the kernel image.
+    
+    Commit 671f9a3e2e24 ("RISC-V: Setup initial page tables in two stages")
+    changed the mapping of the DTB to reside in the fixmap area.
+    Consequently, early_init_fdt_reserve_self() cannot be used anymore in
+    setup_bootmem() since it relies on __pa() to derive a physical address,
+    which does not work with dtb_early_va that is no longer a valid kernel
+    logical address.
+    
+    The reserved[0x1] region shows the effect of the pointer underflow
+    resulting from the __pa(initial_boot_params) offset subtraction:
+    
+    [    0.000000] MEMBLOCK configuration:
+    [    0.000000]  memory size = 0x000000001fe00000 reserved size = 0x0000000000a2e514
+    [    0.000000]  memory.cnt  = 0x1
+    [    0.000000]  memory[0x0]     [0x0000000080200000-0x000000009fffffff], 0x000000001fe00000 bytes flags: 0x0
+    [    0.000000]  reserved.cnt  = 0x2
+    [    0.000000]  reserved[0x0]   [0x0000000080200000-0x0000000080c2dfeb], 0x0000000000a2dfec bytes flags: 0x0
+    [    0.000000]  reserved[0x1]   [0xfffffff080100000-0xfffffff080100527], 0x0000000000000528 bytes flags: 0x0
+    
+    With the fix applied:
+    
+    [    0.000000] MEMBLOCK configuration:
+    [    0.000000]  memory size = 0x000000001fe00000 reserved size = 0x0000000000a2e514
+    [    0.000000]  memory.cnt  = 0x1
+    [    0.000000]  memory[0x0]     [0x0000000080200000-0x000000009fffffff], 0x000000001fe00000 bytes flags: 0x0
+    [    0.000000]  reserved.cnt  = 0x2
+    [    0.000000]  reserved[0x0]   [0x0000000080200000-0x0000000080c2dfeb], 0x0000000000a2dfec bytes flags: 0x0
+    [    0.000000]  reserved[0x1]   [0x0000000080e00000-0x0000000080e00527], 0x0000000000000528 bytes flags: 0x0
+    
+    Fixes: 671f9a3e2e24 ("RISC-V: Setup initial page tables in two stages")
+    Signed-off-by: Albert Ou 
+    Tested-by: Bin Meng 
+    Reviewed-by: Anup Patel 
+    Signed-off-by: Paul Walmsley 
+
+diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
+index f0ba71304b6e..83f7d12042fb 100644
+--- a/arch/riscv/mm/init.c
++++ b/arch/riscv/mm/init.c
+@@ -11,6 +11,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ #include 
+@@ -82,6 +83,8 @@ static void __init setup_initrd(void)
+ }
+ #endif /* CONFIG_BLK_DEV_INITRD */
+ 
++static phys_addr_t dtb_early_pa __initdata;
++
+ void __init setup_bootmem(void)
+ {
+ 	struct memblock_region *reg;
+@@ -117,7 +120,12 @@ void __init setup_bootmem(void)
+ 	setup_initrd();
+ #endif /* CONFIG_BLK_DEV_INITRD */
+ 
+-	early_init_fdt_reserve_self();
++	/*
++	 * Avoid using early_init_fdt_reserve_self() since __pa() does
++	 * not work for DTB pointers that are fixmap addresses
++	 */
++	memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va));
++
+ 	early_init_fdt_scan_reserved_mem();
+ 	memblock_allow_resize();
+ 	memblock_dump_all();
+@@ -393,6 +401,8 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
+ 
+ 	/* Save pointer to DTB for early FDT parsing */
+ 	dtb_early_va = (void *)fix_to_virt(FIX_FDT) + (dtb_pa & ~PAGE_MASK);
++	/* Save physical address for memblock reservation */
++	dtb_early_pa = dtb_pa;
+ }
+ 
+ static void __init setup_vm_final(void)

commit 28e84ab3abafb0f9c9573993626abe6ca3fa8eb1
+Author: Robert T. Johnson 
+Date:   Mon Jun 16 17:20:52 2008 -0700
+
+    atm: [he] limit queries to the device's register space
+    
+    From: "Robert T. Johnson" 
+    Signed-off-by: Chas Williams 
+
+diff --git a/drivers/atm/he.c b/drivers/atm/he.c
+index 320320e3dfb3..fc636a3429cf 100644
+--- a/drivers/atm/he.c
++++ b/drivers/atm/he.c
+@@ -2845,10 +2845,15 @@ he_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void __user *arg)
+ 			if (copy_from_user(®, arg,
+ 					   sizeof(struct he_ioctl_reg)))
+ 				return -EFAULT;
+-			
++
+ 			spin_lock_irqsave(&he_dev->global_lock, flags);
+ 			switch (reg.type) {
+ 				case HE_REGTYPE_PCI:
++					if (reg.addr < 0 || reg.addr >= HE_REGMAP_SIZE) {
++						err = -EINVAL;
++						break;
++					}
++
+ 					reg.val = he_readl(he_dev, reg.addr);
+ 					break;
+ 				case HE_REGTYPE_RCM:

commit 369693dc93533097c0ca7243affb4f3244c336e8
+Author: Paul Vojta 
+Date:   Wed Jul 8 23:57:46 2009 -0700
+
+    ALSA: hda - fix beep tone calculation for IDT/STAC codecs
+    
+    In the beep tone calculation for IDT/STAC codecs, lower numbers correspond
+    to higher frequencies and vice versa.  The current code has this backwards,
+    resulting in beep frequencies which are way too high (and sound bad on
+    tinny laptop speakers, resulting in complaints).
+    
+    [Also added hz <= 0 check by tiwai]
+    
+    Signed-off-by: Paul Vojta 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c
+index 29272f2e95a0..b0275a050870 100644
+--- a/sound/pci/hda/hda_beep.c
++++ b/sound/pci/hda/hda_beep.c
+@@ -50,19 +50,22 @@ static void snd_hda_generate_beep(struct work_struct *work)
+  * The tone frequency of beep generator on IDT/STAC codecs is
+  * defined from the 8bit tone parameter, in Hz,
+  *    freq = 48000 * (257 - tone) / 1024
+- * that is from 12kHz to 93.75kHz in step of 46.875 hz
++ * that is from 12kHz to 93.75Hz in steps of 46.875 Hz
+  */
+ static int beep_linear_tone(struct hda_beep *beep, int hz)
+ {
++	if (hz <= 0)
++		return 0;
+ 	hz *= 1000; /* fixed point */
+-	hz = hz - DIGBEEP_HZ_MIN;
++	hz = hz - DIGBEEP_HZ_MIN
++		+ DIGBEEP_HZ_STEP / 2; /* round to nearest step */
+ 	if (hz < 0)
+ 		hz = 0; /* turn off PC beep*/
+ 	else if (hz >= (DIGBEEP_HZ_MAX - DIGBEEP_HZ_MIN))
+-		hz = 0xff;
++		hz = 1; /* max frequency */
+ 	else {
+ 		hz /= DIGBEEP_HZ_STEP;
+-		hz++;
++		hz = 255 - hz;
+ 	}
+ 	return hz;
+ }

commit e2340465ec9587362a057524d3e2163377366771
+Author: Paul Vojta 
+Date:   Fri Jul 27 12:20:38 2007 +0200
+
+    [ALSA] Fix bugs in mode change/recalibration for opl3sa2 driver
+    
+    The mode change / recalibration doesn't work always with opl3sa2 devices,
+    e.g. the first time it's played back.  The patch fixes the problem.
+    
+    Signed-off-by: Paul Vojta 
+    Signed-off-by: Takashi Iwai 
+    Signed-off-by: Jaroslav Kysela 
+
+diff --git a/include/sound/cs4231.h b/include/sound/cs4231.h
+index ab51ce1ba9a5..b195a73c5685 100644
+--- a/include/sound/cs4231.h
++++ b/include/sound/cs4231.h
+@@ -210,7 +210,7 @@
+ #define CS4231_HW_CS4239	0x0404	/* CS4239 - Crystal Clear (tm) stereo enhancement */
+ /* compatible, but clones */
+ #define CS4231_HW_INTERWAVE     0x1000	/* InterWave chip */
+-#define CS4231_HW_OPL3SA2       0x1001	/* OPL3-SA2 chip */
++#define CS4231_HW_OPL3SA2       0x1101	/* OPL3-SA2 chip, similar to cs4231 */
+ 
+ /* defines for codec.hwshare */
+ #define CS4231_HWSHARE_IRQ	(1<<0)
+diff --git a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c
+index 914d77b61b0c..642bdaa703be 100644
+--- a/sound/isa/cs423x/cs4231_lib.c
++++ b/sound/isa/cs423x/cs4231_lib.c
+@@ -555,6 +555,8 @@ static void snd_cs4231_playback_format(struct snd_cs4231 *chip,
+ 			snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, chip->image[CS4231_PLAYBK_FORMAT] = pdfr);
+ 		}
+ 		spin_unlock_irqrestore(&chip->reg_lock, flags);
++		if (chip->hardware == CS4231_HW_OPL3SA2)
++			udelay(100);	/* this seems to help */
+ 		snd_cs4231_mce_down(chip);
+ 	}
+ 	snd_cs4231_calibrate_mute(chip, 0);
+diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
+index e70db32991d9..244a00296750 100644
+--- a/sound/isa/opl3sa2.c
++++ b/sound/isa/opl3sa2.c
+@@ -253,6 +253,7 @@ static int __devinit snd_opl3sa2_detect(struct snd_opl3sa2 *chip)
+ 		/* 0x03 - YM715B */
+ 		/* 0x04 - YM719 - OPL-SA4? */
+ 		/* 0x05 - OPL3-SA3 - Libretto 100 */
++		/* 0x07 - unknown - Neomagic MagicWave 3D */
+ 		break;
+ 	}
+ 	str[0] = chip->version + '0';

commit 4210861964145617cf27b2b9c45860bff3e8290c
+Author: Paul Vojta 
+Date:   Wed Jul 4 10:35:29 2007 +0200
+
+    [ALSA] nm256 - Add mention of opl3sa2 to a diagnostic message
+    
+    Adds mention of opl3sa2 driver to a diagnostic message for NeoMagic
+    nm256 driver.
+    
+    Signed-off-by: Paul Vojta 
+    Signed-off-by: Takashi Iwai 
+    Signed-off-by: Jaroslav Kysela 
+
+diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
+index 03b3a4792f73..c7621bd770a6 100644
+--- a/sound/pci/nm256/nm256.c
++++ b/sound/pci/nm256/nm256.c
+@@ -1533,7 +1533,8 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci,
+ 				printk(KERN_ERR "  force the driver to load by "
+ 				       "passing in the module parameter\n");
+ 				printk(KERN_ERR "    force_ac97=1\n");
+-				printk(KERN_ERR "  or try sb16 or cs423x drivers instead.\n");
++				printk(KERN_ERR "  or try sb16, opl3sa2, or "
++				       "cs423x drivers instead.\n");
+ 				err = -ENXIO;
+ 				goto __error;
+ 			}

commit 4700418cfc045296ee453342dc2fb142dc752aed
+Author: Paul Vojta 
+Date:   Wed Jul 4 10:34:22 2007 +0200
+
+    [ALSA] opl3sa2 - Add Neomagic MagicWave 3D ISA PnP ID
+    
+    Add Neomagic MagicWave 3D to list of supported devices for opl3sa2
+    driver.
+    
+    Signed-off-by: Paul Vojta 
+    Signed-off-by: Takashi Iwai 
+    Signed-off-by: Jaroslav Kysela 
+
+diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
+index 4f6800b43b0e..e70db32991d9 100644
+--- a/sound/isa/opl3sa2.c
++++ b/sound/isa/opl3sa2.c
+@@ -164,6 +164,8 @@ static struct pnp_card_device_id snd_opl3sa2_pnpids[] = {
+ 	{ .id = "YMH0801", .devs = { { "YMH0021" } } },
+ 	/* NeoMagic MagicWave 3DX */
+ 	{ .id = "NMX2200", .devs = { { "YMH2210" } } },
++	/* NeoMagic MagicWave 3D */
++	{ .id = "NMX2200", .devs = { { "NMX2210" } } },
+ 	/* --- */
+ 	{ .id = "" }	/* end */
+ };

commit dd2c565999e015004622425020a61593deb87a04
+Author: Adam Megacz 
+Date:   Fri Jan 5 16:36:17 2007 -0800
+
+    [PATCH] Add AFS_SUPER_MAGIC to magic.h
+    
+    Jeffrey Altman, one of the gatekeepers of OpenAFS (the open source project
+    which inherited the Transarc/IBM AFS codebase) has requested that the magic
+    number 0x5346414F (little endian 'OAFS') be allocated for the f_type field
+    of the fsinfo structure on Linux:
+    
+      https://lists.openafs.org/pipermail/openafs-info/2006-December/024829.html
+    
+    Add it to include/linux/magic.h, mostly as a way of publishing this number
+    and ensuring that no other filesystem accidentally uses it.
+    
+    Cc: Jeffrey Altman 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/magic.h b/include/linux/magic.h
+index 156c40fc664e..b78bbf42135a 100644
+--- a/include/linux/magic.h
++++ b/include/linux/magic.h
+@@ -3,6 +3,7 @@
+ 
+ #define ADFS_SUPER_MAGIC	0xadf5
+ #define AFFS_SUPER_MAGIC	0xadff
++#define AFS_SUPER_MAGIC                0x5346414F
+ #define AUTOFS_SUPER_MAGIC	0x0187
+ #define CODA_SUPER_MAGIC	0x73757245
+ #define EFS_SUPER_MAGIC		0x414A53

commit 99603966f5b44693901ea68cef2c1c21ce6a49c3
+Author: KAMBAROV, ZAUR 
+Date:   Fri Feb 3 03:04:49 2006 -0800
+
+    [PATCH] coverity: udf/balloc.c null deref fix
+    
+    It's doing
+    
+            if (obh)
+                    
+            else
+                    dereference obh
+    
+    So presumably `obh' is never null in there.
+    
+    This defect was found automatically by Coverity Prevent, a static analysis
+    tool.
+    
+    Signed-off-by: Zaur Kambarov 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c
+index 4fae57d9d115..201049ac8a96 100644
+--- a/fs/udf/balloc.c
++++ b/fs/udf/balloc.c
+@@ -579,10 +579,9 @@ static void udf_table_free_blocks(struct super_block * sb,
+ 			{
+ 				loffset = nextoffset;
+ 				aed->lengthAllocDescs = cpu_to_le32(adsize);
+-				if (obh)
+-					sptr = UDF_I_DATA(inode) + nextoffset -  udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode) - adsize;
+-				else
+-					sptr = obh->b_data + nextoffset - adsize;
++				sptr = UDF_I_DATA(inode) + nextoffset -
++					udf_file_entry_alloc_offset(inode) +
++					UDF_I_LENEATTR(inode) - adsize;
+ 				dptr = nbh->b_data + sizeof(struct allocExtDesc);
+ 				memcpy(dptr, sptr, adsize);
+ 				nextoffset = sizeof(struct allocExtDesc) + adsize;

commit b2134bcd2e1bf989e0566dd1b0e59a792722b671
+Author: KAMBAROV, ZAUR 
+Date:   Fri Jun 24 22:20:35 2005 -0700
+
+    [PATCH] USB: coverity: (desc->bitmap)[] overrun fix
+    
+    The length of the array desc->bitmap is 3, and not 4:
+    
+    Definitions involved:
+    
+    In drivers/usb/core/hcd.h
+    
+    464     #define bitmap  DeviceRemovable
+    
+    In drivers/usb/host/ohci-hub.c
+    
+    395             struct usb_hub_descriptor       *desc
+    
+    In drivers/usb/core/hub.h
+    
+    130     struct usb_hub_descriptor {
+    131             __u8  bDescLength;
+    132             __u8  bDescriptorType;
+    133             __u8  bNbrPorts;
+    134             __u16 wHubCharacteristics;
+    135             __u8  bPwrOn2PwrGood;
+    136             __u8  bHubContrCurrent;
+    137                     /* add 1 bit for hub status change; round to bytes */
+    138             __u8  DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8];
+    139             __u8  PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8];
+    140     } __attribute__ ((packed));
+    
+    In include/linux/usb.h
+    
+    306     #define USB_MAXCHILDREN         (16)
+    
+    This defect was found automatically by Coverity Prevent, a static analysis
+    tool.
+    
+    (akpm: this code should be shot.  Field `bitmap' doesn't exist in struct
+    usb_hub_descriptor.  And this .c file is #included in
+    drivers/usb/host/ohci-hcd.c, and someone somewhere #defines `bitmap' to
+    `DeviceRemovable'.
+    
+    >From a maintainability POV it would be better to memset the whole array
+    beforehand - I changed the patch to do that)
+    
+    Signed-off-by: Zaur Kambarov 
+    Cc: 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index e2fc4129dfc6..83ca4549a50e 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -419,10 +419,11 @@ ohci_hub_descriptor (
+ 
+ 	/* two bitmaps:  ports removable, and usb 1.0 legacy PortPwrCtrlMask */
+ 	rh = roothub_b (ohci);
++	memset(desc->bitmap, 0xff, sizeof(desc->bitmap));
+ 	desc->bitmap [0] = rh & RH_B_DR;
+ 	if (ports > 7) {
+ 		desc->bitmap [1] = (rh & RH_B_DR) >> 8;
+-		desc->bitmap [2] = desc->bitmap [3] = 0xff;
++		desc->bitmap [2] = 0xff;
+ 	} else
+ 		desc->bitmap [1] = 0xff;
+ }

commit 7e8d7e3c9e38dab8d28a8667faa4941842f64213
+Author: KAMBAROV, ZAUR 
+Date:   Thu Jul 7 17:57:07 2005 -0700
+
+    [PATCH] coverity: sunrpc/xprt task null check
+    
+    In __xprt_lock_write() we check to see if `task' is NULL, but in other places
+    we just go and dereference it.
+    
+    `task' shouldn't be NULL anyway, so remove this test.
+    
+    This defect was found automatically by Coverity Prevent, a static analysis
+    tool.
+    
+    Signed-off-by: Zaur Kambarov 
+    Acked-by: Trond Myklebust 
+    Cc: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
+index 269f217918a3..3c654e06b084 100644
+--- a/net/sunrpc/xprt.c
++++ b/net/sunrpc/xprt.c
+@@ -145,8 +145,6 @@ __xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
+ 	if (test_and_set_bit(XPRT_LOCKED, &xprt->sockstate)) {
+ 		if (task == xprt->snd_task)
+ 			return 1;
+-		if (task == NULL)
+-			return 0;
+ 		goto out_sleep;
+ 	}
+ 	if (xprt->nocong || __xprt_get_cong(xprt, task)) {

commit 7eaae2828dadae3abde7f77734c874d4b74b313a
+Author: KAMBAROV, ZAUR 
+Date:   Thu Jul 7 17:57:06 2005 -0700
+
+    [PATCH] coverity: fs/locks.c flp null check
+    
+    We're dereferencing `flp' and then we're testing it for NULLness.
+    
+    Either the compiler accidentally saved us or the existing null-pointer checdk
+    is redundant.
+    
+    This defect was found automatically by Coverity Prevent, a static analysis tool.
+    
+    Signed-off-by: Zaur Kambarov 
+    Cc: Matthew Wilcox 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/locks.c b/fs/locks.c
+index a0bc03495bd4..29fa5da6c117 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -1276,7 +1276,7 @@ int fcntl_getlease(struct file *filp)
+  */
+ static int __setlease(struct file *filp, long arg, struct file_lock **flp)
+ {
+-	struct file_lock *fl, **before, **my_before = NULL, *lease = *flp;
++	struct file_lock *fl, **before, **my_before = NULL, *lease;
+ 	struct dentry *dentry = filp->f_dentry;
+ 	struct inode *inode = dentry->d_inode;
+ 	int error, rdlease_count = 0, wrlease_count = 0;
+@@ -1287,6 +1287,8 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp)
+ 	if (!flp || !(*flp) || !(*flp)->fl_lmops || !(*flp)->fl_lmops->fl_break)
+ 		goto out;
+ 
++	lease = *flp;
++
+ 	error = -EAGAIN;
+ 	if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
+ 		goto out;

commit 8f96c95680bfe66ff00c91859d4c73edf539b854
+Author: KAMBAROV, ZAUR 
+Date:   Thu Jul 7 17:57:05 2005 -0700
+
+    [PATCH] coverity: fix fbsysfs null pointer check
+    
+    Correctly test for a null pointer before going and dereferencing it.
+    
+    This defect was found automatically by Coverity Prevent, a static analysis
+    tool.
+    
+    Signed-off-by: Zaur Kambarov 
+    Cc: 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
+index 7dfbf39b4ed3..ddc9443254d9 100644
+--- a/drivers/video/fbsysfs.c
++++ b/drivers/video/fbsysfs.c
+@@ -256,7 +256,7 @@ static ssize_t show_cmap(struct class_device *class_device, char *buf)
+ 	unsigned int offset = 0, i;
+ 
+ 	if (!fb_info->cmap.red || !fb_info->cmap.blue ||
+-	    fb_info->cmap.green || fb_info->cmap.transp)
++	    !fb_info->cmap.green || !fb_info->cmap.transp)
+ 		return -EINVAL;
+ 
+ 	for (i = 0; i < fb_info->cmap.len; i++) {

commit 69f63c5c34d0b34ee2cbf10c5ff7fcff0404879e
+Author: KAMBAROV, ZAUR 
+Date:   Tue Jun 28 20:45:12 2005 -0700
+
+    [PATCH] coverity: tty_ldisc_ref return null check
+    
+    We add a check of the return value of tty_ldisc_ref(), which
+    is checked 7 out of 8 times, e.g.:
+    
+    149             ld = tty_ldisc_ref(tty);
+    150             if (ld != NULL) {
+    151                     if (ld->set_termios)
+    152                             (ld->set_termios)(tty, &old_termios);
+    153                     tty_ldisc_deref(ld);
+    154             }
+    
+    This defect was found automatically by Coverity Prevent, a static analysis
+    tool.
+    
+    (akpm: presumably `ld' is never NULL.  Oh well)
+    
+    Signed-off-by: Zaur Kambarov 
+    Cc: Alan Cox 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
+index 58597993954f..f19cf9d7792d 100644
+--- a/drivers/char/tty_ioctl.c
++++ b/drivers/char/tty_ioctl.c
+@@ -476,11 +476,11 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
+ 			ld = tty_ldisc_ref(tty);
+ 			switch (arg) {
+ 			case TCIFLUSH:
+-				if (ld->flush_buffer)
++				if (ld && ld->flush_buffer)
+ 					ld->flush_buffer(tty);
+ 				break;
+ 			case TCIOFLUSH:
+-				if (ld->flush_buffer)
++				if (ld && ld->flush_buffer)
+ 					ld->flush_buffer(tty);
+ 				/* fall through */
+ 			case TCOFLUSH:

commit c7f1721ef284c6e8257c7471a02148db76105036
+Author: KAMBAROV, ZAUR 
+Date:   Tue Jun 28 20:45:11 2005 -0700
+
+    [PATCH] coverity: fs/ext3/super.c: match_int return check
+    
+    The return value of  "match_int" is  checked  27 out of 28 times
+    
+    In lib/parser.c
+    142     /**
+    143      * match_int: - scan a decimal representation of an integer from a substring_t
+    144      * @s: substring_t to be scanned
+    145      * @result: resulting integer on success
+    146      *
+    147      * Description: Attempts to parse the &substring_t @s as a decimal integer. On
+    148      * success, sets @result to the integer represented by the string and returns 0.
+    149      * Returns either -ENOMEM or -EINVAL on failure.
+    150      */
+    151     int match_int(substring_t *s, int *result)
+    152     {
+    153             return match_number(s, result, 0);
+    154     }
+    
+    Signed-off-by: Zaur Kambarov 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/ext3/super.c b/fs/ext3/super.c
+index b4b3e8a39131..a6d1779d7de4 100644
+--- a/fs/ext3/super.c
++++ b/fs/ext3/super.c
+@@ -944,7 +944,8 @@ static int parse_options (char * options, struct super_block *sb,
+ 					"for remount\n");
+ 				return 0;
+ 			}
+-			match_int(&args[0], &option);
++			if (match_int(&args[0], &option) != 0)
++				return 0;
+ 			*n_blocks_count = option;
+ 			break;
+ 		case Opt_nobh:

commit ec471dc484b8ca5352903ee28796b8b248313547
+Author: KAMBAROV, ZAUR 
+Date:   Tue Jun 28 20:45:10 2005 -0700
+
+    [PATCH] coverity: fs/udf/namei.c null check
+    
+    "dir" was dereferenced before null check
+    
+    Signed-off-by: Zaur Kambarov 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/udf/namei.c b/fs/udf/namei.c
+index 3f6dc7112bc6..4673157b262f 100644
+--- a/fs/udf/namei.c
++++ b/fs/udf/namei.c
+@@ -159,7 +159,7 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
+ 	char *nameptr;
+ 	uint8_t lfi;
+ 	uint16_t liu;
+-	loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
++	loff_t size;
+ 	kernel_lb_addr bloc, eloc;
+ 	uint32_t extoffset, elen, offset;
+ 	struct buffer_head *bh = NULL;
+@@ -167,6 +167,8 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
+ 	if (!dir)
+ 		return NULL;
+ 
++	size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
++
+ 	f_pos = (udf_ext0_offset(dir) >> 2);
+ 
+ 	fibh->soffset = fibh->eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;

commit 9c101fd439dab60d6eba76afb35fd2696f42c63d
+Author: KAMBAROV, ZAUR 
+Date:   Tue Jun 28 20:45:08 2005 -0700
+
+    [PATCH] coverity: ipmi_msghandler() channels array overrun fix
+    
+    We fix the check in 1084, which was
+    
+    1084                    if (addr->channel > IPMI_NUM_CHANNELS) {
+    1085                            spin_lock_irqsave(&intf->counter_lock, flags);
+    1086                            intf->sent_invalid_commands++;
+    1087                            spin_unlock_irqrestore(&intf->counter_lock, flags);
+    1088                            rv = -EINVAL;
+    1089                            goto out_err;
+    1090                    }
+    
+    addr->channel is used in
+    
+    1092                    if (intf->channels[addr->channel].medium
+    
+    Definitions involved:
+    
+    221             struct ipmi_channel channels[IPMI_MAX_CHANNELS];
+    
+    134     #define IPMI_MAX_CHANNELS       8
+    
+    In /linux-2.6.12-rc6/include/linux/ipmi.h
+    148     #define IPMI_NUM_CHANNELS 0x10
+    
+    Signed-off-by: Zaur Kambarov 
+    Cc: Corey Minyard 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
+index 1813d0d198f1..e16c13fe698d 100644
+--- a/drivers/char/ipmi/ipmi_msghandler.c
++++ b/drivers/char/ipmi/ipmi_msghandler.c
+@@ -1088,8 +1088,8 @@ static inline int i_ipmi_request(ipmi_user_t          user,
+ 		long                  seqid;
+ 		int                   broadcast = 0;
+ 
+-		if (addr->channel > IPMI_NUM_CHANNELS) {
+-			spin_lock_irqsave(&intf->counter_lock, flags);
++		if (addr->channel >= IPMI_MAX_CHANNELS) {
++		        spin_lock_irqsave(&intf->counter_lock, flags);
+ 			intf->sent_invalid_commands++;
+ 			spin_unlock_irqrestore(&intf->counter_lock, flags);
+ 			rv = -EINVAL;

commit a77e3362a224212d9d3b9e6fdec44df2eef6cf92
+Author: KAMBAROV, ZAUR 
+Date:   Tue Jun 28 20:45:06 2005 -0700
+
+    [PATCH] coverity: i386: scsi_lib buffer overrun fix
+    
+    The check in
+    
+    627             BUG_ON(index > SG_MEMPOOL_NR);
+    
+    with SG_MEMPOOL_NR defined in
+    
+    32      #define SG_MEMPOOL_NR           (sizeof(scsi_sg_pools)/sizeof(struct scsi_host_sg_pool))
+    
+    was not sufficient.
+    
+    sgp, set in
+    
+    629             sgp = scsi_sg_pools + index;
+    
+    is dereferenced in
+    
+    630             mempool_free(sgl, sgp->pool);
+    
+    Signed-off-by: Zaur Kambarov 
+    Cc: 
+    Cc: James Bottomley 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index 621dee8b8cb2..10506f9cd0c9 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -632,7 +632,7 @@ static void scsi_free_sgtable(struct scatterlist *sgl, int index)
+ {
+ 	struct scsi_host_sg_pool *sgp;
+ 
+-	BUG_ON(index > SG_MEMPOOL_NR);
++	BUG_ON(index >= SG_MEMPOOL_NR);
+ 
+ 	sgp = scsi_sg_pools + index;
+ 	mempool_free(sgl, sgp->pool);

commit a8f5034540195307362d071a8b387226b410469f
+Author: KAMBAROV, ZAUR 
+Date:   Tue Jun 28 20:45:06 2005 -0700
+
+    [PATCH] coverity: i386: build.c: negative return to unsigned fix
+    
+    Variable "c" was declared as an unsigned int, but used in:
+    
+    125             for (i=0 ; (c=read(fd, buf, sizeof(buf)))>0 ; i+=c )
+    126                     if (write(1, buf, c) != c)
+    127                             die("Write call failed");
+    
+    (akpm: read() can return -1.  If it does, we fill the disk up with garbage).
+    
+    Signed-off-by: Zaur Kambarov 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/i386/boot/tools/build.c b/arch/i386/boot/tools/build.c
+index 4a17956512e1..6835f6d47c31 100644
+--- a/arch/i386/boot/tools/build.c
++++ b/arch/i386/boot/tools/build.c
+@@ -70,7 +70,8 @@ void usage(void)
+ 
+ int main(int argc, char ** argv)
+ {
+-	unsigned int i, c, sz, setup_sectors;
++	unsigned int i, sz, setup_sectors;
++	int c;
+ 	u32 sys_size;
+ 	byte major_root, minor_root;
+ 	struct stat sb;

commit 589777eab7360894b7ca1c4ba9d252e03b51225b
+Author: Zaur Kambarov 
+Date:   Tue Jun 21 17:14:31 2005 -0700
+
+    [PATCH] coverity: idr_get_new_above_int() overrun fix
+    
+    This patch fixes overrun of array pa:
+    92              struct idr_layer *pa[MAX_LEVEL];
+    
+    in
+    
+    98              l = idp->layers;
+    99              pa[l--] = NULL;
+    
+    by passing idp->layers, set in
+    202             idp->layers = layers;
+    to function  sub_alloc in
+    203             v = sub_alloc(idp, ptr, &id);
+    
+    Signed-off-by: Zaur Kambarov 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/lib/idr.c b/lib/idr.c
+index 81fc430602ee..c5be889de449 100644
+--- a/lib/idr.c
++++ b/lib/idr.c
+@@ -175,7 +175,7 @@ static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)
+ 	 * Add a new layer to the top of the tree if the requested
+ 	 * id is larger than the currently allocated space.
+ 	 */
+-	while ((layers < MAX_LEVEL) && (id >= (1 << (layers*IDR_BITS)))) {
++	while ((layers < (MAX_LEVEL - 1)) && (id >= (1 << (layers*IDR_BITS)))) {
+ 		layers++;
+ 		if (!p->count)
+ 			continue;

commit 3a845099b20e81fb678521f034bbdcd69208da4e
+Author: Zaur Kambarov 
+Date:   Tue Jun 21 17:14:30 2005 -0700
+
+    [PATCH] coverity: ipmi: avoid overrun of ipmi_interfaces[]
+    
+    Fix overrun of static array "ipmi_interfaces" of size 4 at position 4 with
+    index variable "if_num".
+    
+    Definitions involved:
+    297     #define MAX_IPMI_INTERFACES 4
+    298     static ipmi_smi_t ipmi_interfaces[MAX_IPMI_INTERFACES];
+    
+    Signed-off-by: Zaur Kambarov 
+    Cc: Corey Minyard 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
+index d7fb452af7f9..0c81652eaba6 100644
+--- a/drivers/char/ipmi/ipmi_msghandler.c
++++ b/drivers/char/ipmi/ipmi_msghandler.c
+@@ -641,7 +641,7 @@ int ipmi_create_user(unsigned int          if_num,
+ 		return -ENOMEM;
+ 
+ 	down_read(&interfaces_sem);
+-	if ((if_num > MAX_IPMI_INTERFACES) || ipmi_interfaces[if_num] == NULL)
++	if ((if_num >= MAX_IPMI_INTERFACES) || ipmi_interfaces[if_num] == NULL)
+ 	{
+ 		rv = -EINVAL;
+ 		goto out_unlock;

\ No newline at end of file diff --git a/detail/33.html b/detail/33.html new file mode 100644 index 0000000..4046fc9 --- /dev/null +++ b/detail/33.html @@ -0,0 +1,669 @@ +

Patches contributed by University of California, Riverside


commit 68e8cc2a23b61862bf20ffc9b782a3fb49c65568
+Author: Yizhuo Zhai 
+Date:   Wed Feb 2 15:58:08 2022 -0800
+
+    fbdev: fbmem: Fix the implicit type casting
+    
+    In function do_fb_ioctl(), the "arg" is the type of unsigned long,
+    and in "case FBIOBLANK:" this argument is casted into an int before
+    passig to fb_blank(). In fb_blank(), the comparision
+    if (blank > FB_BLANK_POWERDOWN) would be bypass if the original
+    "arg" is a large number, which is possible because it comes from
+    the user input. Fix this by adding the check before the function
+    call.
+    
+    Reviewed-by: Guenter Roeck 
+    Reviewed-by: Sam Ravnborg 
+    Acked-by: Helge Deller 
+    Signed-off-by: Yizhuo Zhai 
+    Signed-off-by: Daniel Vetter 
+    Link: https://patchwork.freedesktop.org/patch/msgid/20220202235811.1621017-1-yzhai003@ucr.edu
+
+diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
+index 0fa7ede94fa6..13083ad8d751 100644
+--- a/drivers/video/fbdev/core/fbmem.c
++++ b/drivers/video/fbdev/core/fbmem.c
+@@ -1160,6 +1160,8 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
+ 		ret = fbcon_set_con2fb_map_ioctl(argp);
+ 		break;
+ 	case FBIOBLANK:
++		if (arg > FB_BLANK_POWERDOWN)
++			return -EINVAL;
+ 		console_lock();
+ 		lock_fb_info(info);
+ 		ret = fb_blank(info, arg);

commit 0726ed3065eeb910f9cea0c933bc021a848e00b3
+Author: Yizhuo Zhai 
+Date:   Fri Dec 17 20:22:23 2021 -0800
+
+    drm/amd/display: Fix the uninitialized variable in enable_stream_features()
+    
+    In function enable_stream_features(), the variable "old_downspread.raw"
+    could be uninitialized if core_link_read_dpcd() fails, however, it is
+    used in the later if statement, and further, core_link_write_dpcd()
+    may write random value, which is potentially unsafe.
+    
+    Fixes: 6016cd9dba0f ("drm/amd/display: add helper for enabling mst stream features")
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Yizhuo Zhai 
+    Signed-off-by: Alex Deucher 
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+index ee3c1c9eac4a..dc1380b6c5e0 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+@@ -1818,6 +1818,8 @@ static void enable_stream_features(struct pipe_ctx *pipe_ctx)
+ 		union down_spread_ctrl old_downspread;
+ 		union down_spread_ctrl new_downspread;
+ 
++		memset(&old_downspread, 0, sizeof(old_downspread));
++
+ 		core_link_read_dpcd(link, DP_DOWNSPREAD_CTRL,
+ 				&old_downspread.raw, sizeof(old_downspread));
+ 

commit 5ba9c067b5ed1ccfec58acae07c6582f16b9d44b
+Author: Yizhuo 
+Date:   Sun Jul 11 22:23:32 2021 +0200
+
+    media: staging: atomisp: fix the uninitialized use in gc2235_detect()
+    
+    Inside function gc2235_detect(), variable "low" could be uninitialized
+    if ov5693_read_reg() returns error, however, it affects the value of
+    variable "id". The "id" is used in the later if statement, which is
+    potentially unsafe.
+    
+    Link: https://lore.kernel.org/linux-media/20210711202334.27959-1-yzhai003@ucr.edu
+    Signed-off-by: Yizhuo 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c
+index 5e3670c4fc29..6c95f57a52e9 100644
+--- a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c
++++ b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c
+@@ -1714,6 +1714,8 @@ static int ov5693_detect(struct i2c_client *client)
+ 	}
+ 	ret = ov5693_read_reg(client, OV5693_8BIT,
+ 			      OV5693_SC_CMMN_CHIP_ID_L, &low);
++	if (ret)
++		return ret;
+ 	id = ((((u16)high) << 8) | (u16)low);
+ 
+ 	if (id != OV5693_ID) {

commit 0c980e3f5276ba2eb95c42919c5f1694e38ef86a
+Author: Yizhuo 
+Date:   Fri Jun 25 07:38:56 2021 +0200
+
+    media: atomisp: fix the uninitialized use and rename "retvalue"
+    
+    Inside function mt9m114_detect(), variable "retvalue" could
+    be uninitialized if mt9m114_read_reg() returns error, however, it
+    is used in the later if statement, which is potentially unsafe.
+    
+    The local variable "retvalue" is renamed to "model" to avoid
+    confusion.
+    
+    Link: https://lore.kernel.org/linux-media/20210625053858.3862-1-yzhai003@ucr.edu
+    Fixes: ad85094b293e ("Revert "media: staging: atomisp: Remove driver"")
+    Signed-off-by: Yizhuo 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c b/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c
+index 11196180a206..34bf92de2f29 100644
+--- a/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c
++++ b/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c
+@@ -1545,16 +1545,19 @@ static struct v4l2_ctrl_config mt9m114_controls[] = {
+ static int mt9m114_detect(struct mt9m114_device *dev, struct i2c_client *client)
+ {
+ 	struct i2c_adapter *adapter = client->adapter;
+-	u32 retvalue;
++	u32 model;
++	int ret;
+ 
+ 	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+ 		dev_err(&client->dev, "%s: i2c error", __func__);
+ 		return -ENODEV;
+ 	}
+-	mt9m114_read_reg(client, MISENSOR_16BIT, (u32)MT9M114_PID, &retvalue);
+-	dev->real_model_id = retvalue;
++	ret = mt9m114_read_reg(client, MISENSOR_16BIT, MT9M114_PID, &model);
++	if (ret)
++		return ret;
++	dev->real_model_id = model;
+ 
+-	if (retvalue != MT9M114_MOD_ID) {
++	if (model != MT9M114_MOD_ID) {
+ 		dev_err(&client->dev, "%s: failed: client->addr = %x\n",
+ 			__func__, client->addr);
+ 		return -ENODEV;

commit c275e5d349b0d2b1143607d28b9c7c14a8a0a9b4
+Author: Yizhuo 
+Date:   Fri Jun 25 07:38:56 2021 +0200
+
+    media: atomisp: fix the uninitialized use and rename "retvalue"
+    
+    Inside function mt9m114_detect(), variable "retvalue" could
+    be uninitialized if mt9m114_read_reg() returns error, however, it
+    is used in the later if statement, which is potentially unsafe.
+    
+    The local variable "retvalue" is renamed to "model" to avoid
+    confusion.
+    
+    Link: https://lore.kernel.org/linux-media/20210625053858.3862-1-yzhai003@ucr.edu
+    Fixes: ad85094 (media / atomisp: fix the uninitialized use of model ID)
+    Signed-off-by: Yizhuo 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c b/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c
+index 11196180a206..34bf92de2f29 100644
+--- a/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c
++++ b/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c
+@@ -1545,16 +1545,19 @@ static struct v4l2_ctrl_config mt9m114_controls[] = {
+ static int mt9m114_detect(struct mt9m114_device *dev, struct i2c_client *client)
+ {
+ 	struct i2c_adapter *adapter = client->adapter;
+-	u32 retvalue;
++	u32 model;
++	int ret;
+ 
+ 	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+ 		dev_err(&client->dev, "%s: i2c error", __func__);
+ 		return -ENODEV;
+ 	}
+-	mt9m114_read_reg(client, MISENSOR_16BIT, (u32)MT9M114_PID, &retvalue);
+-	dev->real_model_id = retvalue;
++	ret = mt9m114_read_reg(client, MISENSOR_16BIT, MT9M114_PID, &model);
++	if (ret)
++		return ret;
++	dev->real_model_id = model;
+ 
+-	if (retvalue != MT9M114_MOD_ID) {
++	if (model != MT9M114_MOD_ID) {
+ 		dev_err(&client->dev, "%s: failed: client->addr = %x\n",
+ 			__func__, client->addr);
+ 		return -ENODEV;

commit cac7100d4c51c04979dacdfe6c9a5e400d3f0a27
+Author: Yizhuo Zhai 
+Date:   Sat Jun 19 22:26:50 2021 -0700
+
+    Input: hideep - fix the uninitialized use in hideep_nvm_unlock()
+    
+    Inside function hideep_nvm_unlock(), variable "unmask_code" could
+    be uninitialized if hideep_pgm_r_reg() returns error, however, it
+    is used in the later if statement after an "and" operation, which
+    is potentially unsafe.
+    
+    Signed-off-by: Yizhuo 
+    Signed-off-by: Dmitry Torokhov 
+
+diff --git a/drivers/input/touchscreen/hideep.c b/drivers/input/touchscreen/hideep.c
+index ddad4a82a5e5..e9547ee29756 100644
+--- a/drivers/input/touchscreen/hideep.c
++++ b/drivers/input/touchscreen/hideep.c
+@@ -361,13 +361,16 @@ static int hideep_enter_pgm(struct hideep_ts *ts)
+ 	return -EIO;
+ }
+ 
+-static void hideep_nvm_unlock(struct hideep_ts *ts)
++static int hideep_nvm_unlock(struct hideep_ts *ts)
+ {
+ 	u32 unmask_code;
++	int error;
+ 
+ 	hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_SFR_RPAGE);
+-	hideep_pgm_r_reg(ts, 0x0000000C, &unmask_code);
++	error = hideep_pgm_r_reg(ts, 0x0000000C, &unmask_code);
+ 	hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_DEFAULT_PAGE);
++	if (error)
++		return error;
+ 
+ 	/* make it unprotected code */
+ 	unmask_code &= ~HIDEEP_PROT_MODE;
+@@ -384,6 +387,8 @@ static void hideep_nvm_unlock(struct hideep_ts *ts)
+ 	NVM_W_SFR(HIDEEP_NVM_MASK_OFS, ts->nvm_mask);
+ 	SET_FLASH_HWCONTROL();
+ 	hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_DEFAULT_PAGE);
++
++	return 0;
+ }
+ 
+ static int hideep_check_status(struct hideep_ts *ts)
+@@ -462,7 +467,9 @@ static int hideep_program_nvm(struct hideep_ts *ts,
+ 	u32 addr = 0;
+ 	int error;
+ 
+-	hideep_nvm_unlock(ts);
++       error = hideep_nvm_unlock(ts);
++       if (error)
++               return error;
+ 
+ 	while (ucode_len > 0) {
+ 		xfer_len = min_t(size_t, ucode_len, HIDEEP_NVM_PAGE_SIZE);

commit 31218df77e7f1b9b0a136990a500a7f980e6a573
+Author: Yizhuo 
+Date:   Thu Aug 29 21:43:59 2019 -0300
+
+    media: media/pci/ivtv: Variable vbi.type could be uninitialized if macro v4l2_subdev_call set __result an error code
+    
+    Inside function compress_sliced_buf(), variable vbi.type is
+    uninitialized if macro v4l2_subdev_call set __result an
+    error code. However, vbi.type is used in the if statement
+    without any check, which is potentially unsafe.
+    
+    Signed-off-by: Yizhuo 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/pci/ivtv/ivtv-vbi.c b/drivers/media/pci/ivtv/ivtv-vbi.c
+index 6d22c0107d33..80478b026d75 100644
+--- a/drivers/media/pci/ivtv/ivtv-vbi.c
++++ b/drivers/media/pci/ivtv/ivtv-vbi.c
+@@ -325,7 +325,7 @@ static u32 compress_raw_buf(struct ivtv *itv, u8 *buf, u32 size)
+ static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8 sav)
+ {
+ 	u32 line_size = itv->vbi.sliced_decoder_line_size;
+-	struct v4l2_decode_vbi_line vbi;
++	struct v4l2_decode_vbi_line vbi = {};
+ 	int i;
+ 	unsigned lines = 0;
+ 

commit 472b39c3d1bba0616eb0e9a8fa3ad0f56927c7d7
+Author: Yizhuo 
+Date:   Thu Oct 3 10:58:13 2019 -0700
+
+    regulator: max8907: Fix the usage of uninitialized variable in max8907_regulator_probe()
+    
+    Inside function max8907_regulator_probe(), variable val could
+    be uninitialized if regmap_read() fails. However, val is used
+    later in the if statement to decide the content written to
+    "pmic", which is potentially unsafe.
+    
+    Signed-off-by: Yizhuo 
+    Link: https://lore.kernel.org/r/20191003175813.16415-1-yzhai003@ucr.edu
+    Signed-off-by: Mark Brown 
+
+diff --git a/drivers/regulator/max8907-regulator.c b/drivers/regulator/max8907-regulator.c
+index 76152aaa330b..96dc0eea7659 100644
+--- a/drivers/regulator/max8907-regulator.c
++++ b/drivers/regulator/max8907-regulator.c
+@@ -296,7 +296,10 @@ static int max8907_regulator_probe(struct platform_device *pdev)
+ 	memcpy(pmic->desc, max8907_regulators, sizeof(pmic->desc));
+ 
+ 	/* Backwards compatibility with MAX8907B; SD1 uses different voltages */
+-	regmap_read(max8907->regmap_gen, MAX8907_REG_II2RR, &val);
++	ret = regmap_read(max8907->regmap_gen, MAX8907_REG_II2RR, &val);
++	if (ret)
++		return ret;
++
+ 	if ((val & MAX8907_II2RR_VERSION_MASK) ==
+ 	    MAX8907_II2RR_VERSION_REV_B) {
+ 		pmic->desc[MAX8907_SD1].min_uV = 637500;
+@@ -333,14 +336,20 @@ static int max8907_regulator_probe(struct platform_device *pdev)
+ 		}
+ 
+ 		if (pmic->desc[i].ops == &max8907_ldo_ops) {
+-			regmap_read(config.regmap, pmic->desc[i].enable_reg,
++			ret = regmap_read(config.regmap, pmic->desc[i].enable_reg,
+ 				    &val);
++			if (ret)
++				return ret;
++
+ 			if ((val & MAX8907_MASK_LDO_SEQ) !=
+ 			    MAX8907_MASK_LDO_SEQ)
+ 				pmic->desc[i].ops = &max8907_ldo_hwctl_ops;
+ 		} else if (pmic->desc[i].ops == &max8907_out5v_ops) {
+-			regmap_read(config.regmap, pmic->desc[i].enable_reg,
++			ret = regmap_read(config.regmap, pmic->desc[i].enable_reg,
+ 				    &val);
++			if (ret)
++				return ret;
++
+ 			if ((val & (MAX8907_MASK_OUT5V_VINEN |
+ 						MAX8907_MASK_OUT5V_ENSRC)) !=
+ 			    MAX8907_MASK_OUT5V_ENSRC)

commit 53de429f4e88f538f7a8ec2b18be8c0cd9b2c8e1
+Author: Yizhuo 
+Date:   Tue Oct 1 13:24:39 2019 -0700
+
+    net: hisilicon: Fix usage of uninitialized variable in function mdio_sc_cfg_reg_write()
+    
+    In function mdio_sc_cfg_reg_write(), variable "reg_value" could be
+    uninitialized if regmap_read() fails. However, "reg_value" is used
+    to decide the control flow later in the if statement, which is
+    potentially unsafe.
+    
+    Signed-off-by: Yizhuo 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/hisilicon/hns_mdio.c b/drivers/net/ethernet/hisilicon/hns_mdio.c
+index 3e863a71c513..7df5d7d211d4 100644
+--- a/drivers/net/ethernet/hisilicon/hns_mdio.c
++++ b/drivers/net/ethernet/hisilicon/hns_mdio.c
+@@ -148,11 +148,15 @@ static int mdio_sc_cfg_reg_write(struct hns_mdio_device *mdio_dev,
+ {
+ 	u32 time_cnt;
+ 	u32 reg_value;
++	int ret;
+ 
+ 	regmap_write(mdio_dev->subctrl_vbase, cfg_reg, set_val);
+ 
+ 	for (time_cnt = MDIO_TIMEOUT; time_cnt; time_cnt--) {
+-		regmap_read(mdio_dev->subctrl_vbase, st_reg, ®_value);
++		ret = regmap_read(mdio_dev->subctrl_vbase, st_reg, ®_value);
++		if (ret)
++			return ret;
++
+ 		reg_value &= st_msk;
+ 		if ((!!check_st) == (!!reg_value))
+ 			break;

commit 1252b283141f03c3dffd139292c862cae10e174d
+Author: Yizhuo 
+Date:   Sun Sep 29 10:09:57 2019 -0700
+
+    regulator: pfuze100-regulator: Variable "val" in pfuze100_regulator_probe() could be uninitialized
+    
+    In function pfuze100_regulator_probe(), variable "val" could be
+    initialized if regmap_read() fails. However, "val" is used to
+    decide the control flow later in the if statement, which is
+    potentially unsafe.
+    
+    Signed-off-by: Yizhuo 
+    Link: https://lore.kernel.org/r/20190929170957.14775-1-yzhai003@ucr.edu
+    Signed-off-by: Mark Brown 
+
+diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c
+index df5df1c495ad..689537927f6f 100644
+--- a/drivers/regulator/pfuze100-regulator.c
++++ b/drivers/regulator/pfuze100-regulator.c
+@@ -788,7 +788,13 @@ static int pfuze100_regulator_probe(struct i2c_client *client,
+ 
+ 		/* SW2~SW4 high bit check and modify the voltage value table */
+ 		if (i >= sw_check_start && i <= sw_check_end) {
+-			regmap_read(pfuze_chip->regmap, desc->vsel_reg, &val);
++			ret = regmap_read(pfuze_chip->regmap,
++						desc->vsel_reg, &val);
++			if (ret) {
++				dev_err(&client->dev, "Fails to read from the register.\n");
++				return ret;
++			}
++
+ 			if (val & sw_hi) {
+ 				if (pfuze_chip->chip_id == PFUZE3000 ||
+ 					pfuze_chip->chip_id == PFUZE3001) {

commit 09e7f2805c352dc38d13f663613663574a0584ad
+Author: Yizhuo 
+Date:   Mon Sep 2 12:52:49 2019 -0700
+
+    platform/x86: compal-laptop: Initialize "value" in ec_read_u8()
+    
+    In function ec_read_u8(), variable "value" could be uninitialized
+    if ec_read() fails. However, "value" is returned directly and used
+    in its callers. This is potentially unsafe.
+    
+    Signed-off-by: Yizhuo 
+    Signed-off-by: Andy Shevchenko 
+
+diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c
+index 09dfa6f48a1a..ab610376fdad 100644
+--- a/drivers/platform/x86/compal-laptop.c
++++ b/drivers/platform/x86/compal-laptop.c
+@@ -226,7 +226,7 @@ static const unsigned char pwm_lookup_table[256] = {
+ /* General access */
+ static u8 ec_read_u8(u8 addr)
+ {
+-	u8 value;
++	u8 value = 0;
+ 	ec_read(addr, &value);
+ 	return value;
+ }

commit e33b4325e60e146c2317a8b548cbd633239ff83b
+Author: Yizhuo 
+Date:   Fri Aug 30 19:00:48 2019 -0700
+
+    net: stmmac: dwmac-sun8i: Variable "val" in function sun8i_dwmac_set_syscon() could be uninitialized
+    
+    In function sun8i_dwmac_set_syscon(), local variable "val" could
+    be uninitialized if function regmap_field_read() returns -EINVAL.
+    However, it will be used directly in the if statement, which
+    is potentially unsafe.
+    
+    Signed-off-by: Yizhuo 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+index 4083019c547a..f97a4096f8fc 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+@@ -873,7 +873,12 @@ static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv)
+ 	int ret;
+ 	u32 reg, val;
+ 
+-	regmap_field_read(gmac->regmap_field, &val);
++	ret = regmap_field_read(gmac->regmap_field, &val);
++	if (ret) {
++		dev_err(priv->device, "Fail to read from regmap field.\n");
++		return ret;
++	}
++
+ 	reg = gmac->variant->default_syscon_value;
+ 	if (reg != val)
+ 		dev_warn(priv->device,

commit 0fb68ce02ae73626a61b8d03eab1625021057af5
+Author: Yizhuo 
+Date:   Mon Aug 26 20:55:28 2019 -0300
+
+    media: pvrusb2: qctrl.flag will be uninitlaized if cx2341x_ctrl_query() returns error code
+    
+    Inside function ctrl_cx2341x_getv4lflags(), qctrl.flag
+    will be uninitlaized if cx2341x_ctrl_query() returns -EINVAL.
+    However, it will be used in the later if statement, which is
+    potentially unsafe.
+    
+    Signed-off-by: Yizhuo 
+    Acked-by: Mike Isely 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
+index 2a946cff84b7..1cfb7cf64131 100644
+--- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
++++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
+@@ -784,7 +784,7 @@ static int ctrl_cx2341x_set(struct pvr2_ctrl *cptr,int m,int v)
+ 
+ static unsigned int ctrl_cx2341x_getv4lflags(struct pvr2_ctrl *cptr)
+ {
+-	struct v4l2_queryctrl qctrl;
++	struct v4l2_queryctrl qctrl = {};
+ 	struct pvr2_ctl_info *info;
+ 	qctrl.id = cptr->info->v4l_id;
+ 	cx2341x_ctrl_query(&cptr->hdw->enc_ctl_state,&qctrl);

commit 37d1e62b5bb3b1229d0c49f2ee45e67dc67274be
+Author: Yizhuo 
+Date:   Wed Jan 30 12:33:30 2019 -0500
+
+    media: ts2020: Variable "utmp" in function ts2020_set_tuner_rf() could be uninitialized
+    
+    In function ts2020_set_tuner_rf(), local variable "utmp" could
+    be uninitialized if function regmap_read() returns -EINVAL.
+    However, this value is used in if statement and written to
+    the register, which is potentially unsafe.
+    
+    Signed-off-by: Yizhuo 
+    Signed-off-by: Sean Young 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb-frontends/ts2020.c b/drivers/media/dvb-frontends/ts2020.c
+index e5cd2cd414f4..0af9b335be12 100644
+--- a/drivers/media/dvb-frontends/ts2020.c
++++ b/drivers/media/dvb-frontends/ts2020.c
+@@ -180,6 +180,9 @@ static int ts2020_set_tuner_rf(struct dvb_frontend *fe)
+ 	unsigned int utmp;
+ 
+ 	ret = regmap_read(dev->regmap, 0x3d, &utmp);
++	if (ret)
++		return ret;
++
+ 	utmp &= 0x7f;
+ 	if (utmp < 0x16)
+ 		utmp = 0xa1;

commit dc30e70391376ba3987aeb856ae6d9c0706534f1
+Author: Yizhuo 
+Date:   Fri Jan 25 22:32:20 2019 -0800
+
+    ARM: OMAP2+: Variable "reg" in function omap4_dsi_mux_pads() could be uninitialized
+    
+    In function omap4_dsi_mux_pads(), local variable "reg" could
+    be uninitialized if function regmap_read() returns -EINVAL.
+    However, it will be used directly in the later context, which
+    is potentially unsafe.
+    
+    Signed-off-by: Yizhuo 
+    Signed-off-by: Tony Lindgren 
+
+diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
+index f86b72d1d59e..1444b4b4bd9f 100644
+--- a/arch/arm/mach-omap2/display.c
++++ b/arch/arm/mach-omap2/display.c
+@@ -83,6 +83,7 @@ static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
+ 	u32 enable_mask, enable_shift;
+ 	u32 pipd_mask, pipd_shift;
+ 	u32 reg;
++	int ret;
+ 
+ 	if (dsi_id == 0) {
+ 		enable_mask = OMAP4_DSI1_LANEENABLE_MASK;
+@@ -98,7 +99,11 @@ static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
+ 		return -ENODEV;
+ 	}
+ 
+-	regmap_read(omap4_dsi_mux_syscon, OMAP4_DSIPHY_SYSCON_OFFSET, ®);
++	ret = regmap_read(omap4_dsi_mux_syscon,
++					  OMAP4_DSIPHY_SYSCON_OFFSET,
++					  ®);
++	if (ret)
++		return ret;
+ 
+ 	reg &= ~enable_mask;
+ 	reg &= ~pipd_mask;

commit e20bfeb0b7d808bc05e7c4cb1f492cd31d837da0
+Author: Yizhuo 
+Date:   Fri Jan 25 10:45:37 2019 -0800
+
+    ASoC: rt5651: Variable "ret" in function rt5651_i2c_probe() could be uninitialized
+    
+    In function rt5651_i2c_probe(), local variable "ret" could
+    be uninitialized if function regmap_read() returns -EINVAL.
+    However, this value is used in if statement. This is
+    potentially unsafe.
+    
+    Signed-off-by: Yizhuo 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
+index 75994297c896..29b2d60076b0 100644
+--- a/sound/soc/codecs/rt5651.c
++++ b/sound/soc/codecs/rt5651.c
+@@ -2181,6 +2181,7 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
+ {
+ 	struct rt5651_priv *rt5651;
+ 	int ret;
++	int err;
+ 
+ 	rt5651 = devm_kzalloc(&i2c->dev, sizeof(*rt5651),
+ 				GFP_KERNEL);
+@@ -2197,7 +2198,10 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
+ 		return ret;
+ 	}
+ 
+-	regmap_read(rt5651->regmap, RT5651_DEVICE_ID, &ret);
++	err = regmap_read(rt5651->regmap, RT5651_DEVICE_ID, &ret);
++	if (err)
++		return err;
++
+ 	if (ret != RT5651_DEVICE_ID_VALUE) {
+ 		dev_err(&i2c->dev,
+ 			"Device with ID register %#x is not rt5651\n", ret);

commit 4a8191aa9e057ea38279ef9e809265ba3966be40
+Author: Yizhuo 
+Date:   Mon Jan 7 12:12:32 2019 -0800
+
+    ASoC: rt274: Variable "buf" in function rt274_jack_detect() could be uninitialized
+    
+    In function rt274_jack_detect(), local variable "buf" could
+    be uninitialized if function regmap_read() returns -EINVAL.
+    However, it will be used to calculate "hp" and "mic" and
+    make their value unpredictable while those value are used
+    in the caller. This is potentially unsafe.
+    
+    Signed-off-by: Yizhuo 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/codecs/rt274.c b/sound/soc/codecs/rt274.c
+index 9e88f7b25d38..adf59039a3b6 100644
+--- a/sound/soc/codecs/rt274.c
++++ b/sound/soc/codecs/rt274.c
+@@ -353,6 +353,7 @@ static void rt274_index_sync(struct snd_soc_component *component)
+ static int rt274_jack_detect(struct rt274_priv *rt274, bool *hp, bool *mic)
+ {
+ 	unsigned int buf;
++	int ret;
+ 
+ 	*hp = false;
+ 	*mic = false;
+@@ -360,9 +361,15 @@ static int rt274_jack_detect(struct rt274_priv *rt274, bool *hp, bool *mic)
+ 	if (!rt274->component)
+ 		return -EINVAL;
+ 
+-	regmap_read(rt274->regmap, RT274_GET_HP_SENSE, &buf);
++	ret = regmap_read(rt274->regmap, RT274_GET_HP_SENSE, &buf);
++	if (ret)
++		return ret;
++
+ 	*hp = buf & 0x80000000;
+-	regmap_read(rt274->regmap, RT274_GET_MIC_SENSE, &buf);
++	ret = regmap_read(rt274->regmap, RT274_GET_MIC_SENSE, &buf);
++	if (ret)
++		return ret;
++
+ 	*mic = buf & 0x80000000;
+ 
+ 	pr_debug("*hp = %d *mic = %d\n", *hp, *mic);

commit 8c3590de0a378c2449fc1aec127cc693632458e4
+Author: Yizhuo 
+Date:   Thu Jan 3 13:59:12 2019 -0800
+
+    ASoC: Variable "val" in function rt274_i2c_probe() could be uninitialized
+    
+    Inside function rt274_i2c_probe(), if regmap_read() function
+    returns -EINVAL, then local variable "val" leaves uninitialized
+    but used in if statement. This is potentially unsafe.
+    
+    Signed-off-by: Yizhuo 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/codecs/rt274.c b/sound/soc/codecs/rt274.c
+index 0ef966d56bac..e2855ab9a2c6 100644
+--- a/sound/soc/codecs/rt274.c
++++ b/sound/soc/codecs/rt274.c
+@@ -1128,8 +1128,11 @@ static int rt274_i2c_probe(struct i2c_client *i2c,
+ 		return ret;
+ 	}
+ 
+-	regmap_read(rt274->regmap,
++	ret = regmap_read(rt274->regmap,
+ 		RT274_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &val);
++	if (ret)
++		return ret;
++
+ 	if (val != RT274_VENDOR_ID) {
+ 		dev_err(&i2c->dev,
+ 			"Device with ID register %#x is not rt274\n", val);

commit 4674686d6c8974eb4eebec894c398a0f6c506af3
+Author: yzhai003@ucr.edu 
+Date:   Fri Jun 1 11:30:14 2018 -0700
+
+    iommu/amd: Argument page_size could be uninitialized
+    
+    Argument "page_size" passing to function "fetch_pte" could be
+    uninitialized if the function returns NULL
+    
+    The caller "iommu_unmap_page" checks the return value but the page_size is
+    used outside the if block.
+    
+    Signed-off-by: yzhai003@ucr.edu 
+    Signed-off-by: Joerg Roedel 
+
+diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
+index 596b95c50051..e688169721b8 100644
+--- a/drivers/iommu/amd_iommu.c
++++ b/drivers/iommu/amd_iommu.c
+@@ -1404,6 +1404,8 @@ static u64 *fetch_pte(struct protection_domain *domain,
+ 	int level;
+ 	u64 *pte;
+ 
++	*page_size = 0;
++
+ 	if (address > PM_LEVEL_SIZE(domain->mode))
+ 		return NULL;
+ 

\ No newline at end of file diff --git a/detail/34.html b/detail/34.html new file mode 100644 index 0000000..f8a54be --- /dev/null +++ b/detail/34.html @@ -0,0 +1,1361 @@ +

Patches contributed by Rochester Institute of Technology


commit bd8d725078867cda250fe94b9c5a067b4a64ca74
+Author: Andrew Elble 
+Date:   Fri Oct 5 09:32:08 2018 -0400
+
+    nfsd: correctly decrement odstate refcount in error path
+    
+    alloc_init_deleg() both allocates an nfs4_delegation, and
+    bumps the refcount on odstate. So after this point, we need to
+    put_clnt_odstate() and nfs4_put_stid() to not leave the odstate
+    refcount inappropriately bumped.
+    
+    Signed-off-by: Andrew Elble 
+    Reviewed-by: Jeff Layton 
+    Cc: stable@vger.kernel.org
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 07a57d024f95..f093fbe47133 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -4398,7 +4398,7 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,
+ 
+ 	fl = nfs4_alloc_init_lease(dp, NFS4_OPEN_DELEGATE_READ);
+ 	if (!fl)
+-		goto out_stid;
++		goto out_clnt_odstate;
+ 
+ 	status = vfs_setlease(fp->fi_deleg_file, fl->fl_type, &fl, NULL);
+ 	if (fl)
+@@ -4423,7 +4423,6 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,
+ 	vfs_setlease(fp->fi_deleg_file, F_UNLCK, NULL, (void **)&dp);
+ out_clnt_odstate:
+ 	put_clnt_odstate(dp->dl_clnt_odstate);
+-out_stid:
+ 	nfs4_put_stid(&dp->dl_stid);
+ out_delegees:
+ 	put_deleg_file(fp);

commit 692ad280bff3e81721ab138b9455948ab5289acf
+Author: Andrew Elble 
+Date:   Wed Apr 18 17:04:37 2018 -0400
+
+    nfsd: fix error handling in nfs4_set_delegation()
+    
+    I noticed a memory corruption crash in nfsd in
+    4.17-rc1. This patch corrects the issue.
+    
+    Fix to return error if the delegation couldn't be hashed or there was
+    a recall in progress. Use the existing error path instead of
+    destroy_delegation() for readability.
+    
+    Signed-off-by: Andrew Elble 
+    Fixes: 353601e7d323c ("nfsd: create a separate lease for each delegation")
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index fc74d6f46bd5..3b40d1b57613 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -4378,8 +4378,11 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,
+ 	spin_unlock(&state_lock);
+ 
+ 	if (status)
+-		destroy_unhashed_deleg(dp);
++		goto out_unlock;
++
+ 	return dp;
++out_unlock:
++	vfs_setlease(fp->fi_deleg_file, F_UNLCK, NULL, (void **)&dp);
+ out_clnt_odstate:
+ 	put_clnt_odstate(dp->dl_clnt_odstate);
+ out_stid:

commit ae254dac721d44c0bfebe2795df87459e2e88219
+Author: Andrew Elble 
+Date:   Thu Nov 9 13:41:10 2017 -0500
+
+    nfsd: check for use of the closed special stateid
+    
+    Prevent the use of the closed (invalid) special stateid by clients.
+    
+    Signed-off-by: Andrew Elble 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index d0992d59f4e1..73451436c1c2 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -72,6 +72,7 @@ static u64 current_sessionid = 1;
+ #define ZERO_STATEID(stateid) (!memcmp((stateid), &zero_stateid, sizeof(stateid_t)))
+ #define ONE_STATEID(stateid)  (!memcmp((stateid), &one_stateid, sizeof(stateid_t)))
+ #define CURRENT_STATEID(stateid) (!memcmp((stateid), ¤tstateid, sizeof(stateid_t)))
++#define CLOSE_STATEID(stateid)  (!memcmp((stateid), &close_stateid, sizeof(stateid_t)))
+ 
+ /* forward declarations */
+ static bool check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner);
+@@ -4936,7 +4937,8 @@ static __be32 nfsd4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
+ 	struct nfs4_stid *s;
+ 	__be32 status = nfserr_bad_stateid;
+ 
+-	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
++	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid) ||
++		CLOSE_STATEID(stateid))
+ 		return status;
+ 	/* Client debugging aid. */
+ 	if (!same_clid(&stateid->si_opaque.so_clid, &cl->cl_clientid)) {
+@@ -4994,7 +4996,8 @@ nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate,
+ 	else if (typemask & NFS4_DELEG_STID)
+ 		typemask |= NFS4_REVOKED_DELEG_STID;
+ 
+-	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
++	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid) ||
++		CLOSE_STATEID(stateid))
+ 		return nfserr_bad_stateid;
+ 	status = lookup_clientid(&stateid->si_opaque.so_clid, cstate, nn);
+ 	if (status == nfserr_stale_clientid) {

commit 4f34bd0540d290d1fe1bc699550025623b2761ef
+Author: Andrew Elble 
+Date:   Wed Nov 8 17:29:51 2017 -0500
+
+    nfsd: fix locking validator warning on nfs4_ol_stateid->st_mutex class
+    
+    The use of the st_mutex has been confusing the validator. Use the
+    proper nested notation so as to not produce warnings.
+    
+    Signed-off-by: Andrew Elble 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index ecb803d7c966..98342d262771 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -86,6 +86,11 @@ static void nfs4_free_ol_stateid(struct nfs4_stid *stid);
+  */
+ static DEFINE_SPINLOCK(state_lock);
+ 
++enum nfsd4_st_mutex_lock_subclass {
++	OPEN_STATEID_MUTEX = 0,
++	LOCK_STATEID_MUTEX = 1,
++};
++
+ /*
+  * A waitqueue for all in-progress 4.0 CLOSE operations that are waiting for
+  * the refcount on the open stateid to drop.
+@@ -3600,7 +3605,7 @@ nfsd4_lock_ol_stateid(struct nfs4_ol_stateid *stp)
+ {
+ 	__be32 ret;
+ 
+-	mutex_lock(&stp->st_mutex);
++	mutex_lock_nested(&stp->st_mutex, LOCK_STATEID_MUTEX);
+ 	ret = nfsd4_verify_open_stid(&stp->st_stid);
+ 	if (ret != nfs_ok)
+ 		mutex_unlock(&stp->st_mutex);
+@@ -3664,7 +3669,7 @@ init_open_stateid(struct nfs4_file *fp, struct nfsd4_open *open)
+ 	stp = open->op_stp;
+ 	/* We are moving these outside of the spinlocks to avoid the warnings */
+ 	mutex_init(&stp->st_mutex);
+-	mutex_lock(&stp->st_mutex);
++	mutex_lock_nested(&stp->st_mutex, OPEN_STATEID_MUTEX);
+ 
+ retry:
+ 	spin_lock(&oo->oo_owner.so_client->cl_lock);
+@@ -5741,7 +5746,7 @@ init_lock_stateid(struct nfs4_ol_stateid *stp, struct nfs4_lockowner *lo,
+ 	struct nfs4_ol_stateid *retstp;
+ 
+ 	mutex_init(&stp->st_mutex);
+-	mutex_lock(&stp->st_mutex);
++	mutex_lock_nested(&stp->st_mutex, OPEN_STATEID_MUTEX);
+ retry:
+ 	spin_lock(&clp->cl_lock);
+ 	spin_lock(&fp->fi_lock);

commit 95da1b3a5aded124dd1bda1e3cdb876184813140
+Author: Andrew Elble 
+Date:   Fri Nov 3 14:06:31 2017 -0400
+
+    nfsd: deal with revoked delegations appropriately
+    
+    If a delegation has been revoked by the server, operations using that
+    delegation should error out with NFS4ERR_DELEG_REVOKED in the >4.1
+    case, and NFS4ERR_BAD_STATEID otherwise.
+    
+    The server needs NFSv4.1 clients to explicitly free revoked delegations.
+    If the server returns NFS4ERR_DELEG_REVOKED, the client will do that;
+    otherwise it may just forget about the delegation and be unable to
+    recover when it later sees SEQ4_STATUS_RECALLABLE_STATE_REVOKED set on a
+    SEQUENCE reply.  That can cause the Linux 4.1 client to loop in its
+    stage manager.
+    
+    Signed-off-by: Andrew Elble 
+    Reviewed-by: Trond Myklebust 
+    Cc: stable@vger.kernel.org
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index ecbc7b0dfa4d..b82817767b9d 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -4016,7 +4016,8 @@ static struct nfs4_delegation *find_deleg_stateid(struct nfs4_client *cl, statei
+ {
+ 	struct nfs4_stid *ret;
+ 
+-	ret = find_stateid_by_type(cl, s, NFS4_DELEG_STID);
++	ret = find_stateid_by_type(cl, s,
++				NFS4_DELEG_STID|NFS4_REVOKED_DELEG_STID);
+ 	if (!ret)
+ 		return NULL;
+ 	return delegstateid(ret);
+@@ -4039,6 +4040,12 @@ nfs4_check_deleg(struct nfs4_client *cl, struct nfsd4_open *open,
+ 	deleg = find_deleg_stateid(cl, &open->op_delegate_stateid);
+ 	if (deleg == NULL)
+ 		goto out;
++	if (deleg->dl_stid.sc_type == NFS4_REVOKED_DELEG_STID) {
++		nfs4_put_stid(&deleg->dl_stid);
++		if (cl->cl_minorversion)
++			status = nfserr_deleg_revoked;
++		goto out;
++	}
+ 	flags = share_access_to_flags(open->op_share_access);
+ 	status = nfs4_check_delegmode(deleg, flags);
+ 	if (status) {
+@@ -4908,6 +4915,16 @@ nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate,
+ 		     struct nfs4_stid **s, struct nfsd_net *nn)
+ {
+ 	__be32 status;
++	bool return_revoked = false;
++
++	/*
++	 *  only return revoked delegations if explicitly asked.
++	 *  otherwise we report revoked or bad_stateid status.
++	 */
++	if (typemask & NFS4_REVOKED_DELEG_STID)
++		return_revoked = true;
++	else if (typemask & NFS4_DELEG_STID)
++		typemask |= NFS4_REVOKED_DELEG_STID;
+ 
+ 	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
+ 		return nfserr_bad_stateid;
+@@ -4922,6 +4939,12 @@ nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate,
+ 	*s = find_stateid_by_type(cstate->clp, stateid, typemask);
+ 	if (!*s)
+ 		return nfserr_bad_stateid;
++	if (((*s)->sc_type == NFS4_REVOKED_DELEG_STID) && !return_revoked) {
++		nfs4_put_stid(*s);
++		if (cstate->minorversion)
++			return nfserr_deleg_revoked;
++		return nfserr_bad_stateid;
++	}
+ 	return nfs_ok;
+ }
+ 

commit ed94164398c935a42be7b129a478eb19c598b68a
+Author: Andrew Elble 
+Date:   Wed Jun 15 12:52:09 2016 -0400
+
+    nfsd: implement machine credential support for some operations
+    
+    This addresses the conundrum referenced in RFC5661 18.35.3,
+    and will allow clients to return state to the server using the
+    machine credentials.
+    
+    The biggest part of the problem is that we need to allow the client
+    to send a compound op with integrity/privacy on mounts that don't
+    have it enabled.
+    
+    Add server support for properly decoding and using spo_must_enforce
+    and spo_must_allow bits. Add support for machine credentials to be
+    used for CLOSE, OPEN_DOWNGRADE, LOCKU, DELEGRETURN,
+    and TEST/FREE STATEID.
+    Implement a check so as to not throw WRONGSEC errors when these
+    operations are used if integrity/privacy isn't turned on.
+    
+    Without this, Linux clients with credentials that expired while holding
+    delegations were getting stuck in an endless loop.
+    
+    Signed-off-by: Andrew Elble 
+    Reviewed-by: Jeff Layton 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
+index b4d84b579f20..79de2f38dd63 100644
+--- a/fs/nfsd/export.c
++++ b/fs/nfsd/export.c
+@@ -954,6 +954,16 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)
+ 		    rqstp->rq_cred.cr_flavor == RPC_AUTH_UNIX)
+ 			return 0;
+ 	}
++
++	/* If the compound op contains a spo_must_allowed op,
++	 * it will be sent with integrity/protection which
++	 * will have to be expressly allowed on mounts that
++	 * don't support it
++	 */
++
++	if (nfsd4_spo_must_allow(rqstp))
++		return 0;
++
+ 	return nfserr_wrongsec;
+ }
+ 
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index de1ff1d98bb1..b1159b3e9816 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -2335,6 +2335,45 @@ static struct nfsd4_operation nfsd4_ops[] = {
+ 	},
+ };
+ 
++/**
++ * nfsd4_spo_must_allow - Determine if the compound op contains an
++ * operation that is allowed to be sent with machine credentials
++ *
++ * @rqstp: a pointer to the struct svc_rqst
++ *
++ * Checks to see if the compound contains a spo_must_allow op
++ * and confirms that it was sent with the proper machine creds.
++ */
++
++bool nfsd4_spo_must_allow(struct svc_rqst *rqstp)
++{
++	struct nfsd4_compoundres *resp = rqstp->rq_resp;
++	struct nfsd4_compoundargs *argp = rqstp->rq_argp;
++	struct nfsd4_op *this = &argp->ops[resp->opcnt - 1];
++	struct nfsd4_compound_state *cstate = &resp->cstate;
++	struct nfs4_op_map *allow = &cstate->clp->cl_spo_must_allow;
++	u32 opiter;
++
++	if (!cstate->minorversion)
++		return false;
++
++	if (cstate->spo_must_allowed == true)
++		return true;
++
++	opiter = resp->opcnt;
++	while (opiter < argp->opcnt) {
++		this = &argp->ops[opiter++];
++		if (test_bit(this->opnum, allow->u.longs) &&
++			cstate->clp->cl_mach_cred &&
++			nfsd4_mach_creds_match(cstate->clp, rqstp)) {
++			cstate->spo_must_allowed = true;
++			return true;
++		}
++	}
++	cstate->spo_must_allowed = false;
++	return false;
++}
++
+ int nfsd4_max_reply(struct svc_rqst *rqstp, struct nfsd4_op *op)
+ {
+ 	struct nfsd4_operation *opdesc;
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index ef583507d276..ebfcebd5eab1 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2388,6 +2388,22 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
+ 
+ 	switch (exid->spa_how) {
+ 	case SP4_MACH_CRED:
++		exid->spo_must_enforce[0] = 0;
++		exid->spo_must_enforce[1] = (
++			1 << (OP_BIND_CONN_TO_SESSION - 32) |
++			1 << (OP_EXCHANGE_ID - 32) |
++			1 << (OP_CREATE_SESSION - 32) |
++			1 << (OP_DESTROY_SESSION - 32) |
++			1 << (OP_DESTROY_CLIENTID - 32));
++
++		exid->spo_must_allow[0] &= (1 << (OP_CLOSE) |
++					1 << (OP_OPEN_DOWNGRADE) |
++					1 << (OP_LOCKU) |
++					1 << (OP_DELEGRETURN));
++
++		exid->spo_must_allow[1] &= (
++					1 << (OP_TEST_STATEID - 32) |
++					1 << (OP_FREE_STATEID - 32));
+ 		if (!svc_rqst_integrity_protected(rqstp)) {
+ 			status = nfserr_inval;
+ 			goto out_nolock;
+@@ -2473,6 +2489,8 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
+ 			goto out;
+ 	}
+ 	new->cl_minorversion = cstate->minorversion;
++	new->cl_spo_must_allow.u.words[0] = exid->spo_must_allow[0];
++	new->cl_spo_must_allow.u.words[1] = exid->spo_must_allow[1];
+ 
+ 	gen_clid(new, nn);
+ 	add_to_unconfirmed(new);
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index 9df898ba648f..84ef94794496 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -1299,16 +1299,14 @@ nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp,
+ 		break;
+ 	case SP4_MACH_CRED:
+ 		/* spo_must_enforce */
+-		READ_BUF(4);
+-		dummy = be32_to_cpup(p++);
+-		READ_BUF(dummy * 4);
+-		p += dummy;
+-
++		status = nfsd4_decode_bitmap(argp,
++					exid->spo_must_enforce);
++		if (status)
++			goto out;
+ 		/* spo_must_allow */
+-		READ_BUF(4);
+-		dummy = be32_to_cpup(p++);
+-		READ_BUF(dummy * 4);
+-		p += dummy;
++		status = nfsd4_decode_bitmap(argp, exid->spo_must_allow);
++		if (status)
++			goto out;
+ 		break;
+ 	case SP4_SSV:
+ 		/* ssp_ops */
+@@ -3867,14 +3865,6 @@ nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_w
+ 	return nfserr;
+ }
+ 
+-static const u32 nfs4_minimal_spo_must_enforce[2] = {
+-	[1] = 1 << (OP_BIND_CONN_TO_SESSION - 32) |
+-	      1 << (OP_EXCHANGE_ID - 32) |
+-	      1 << (OP_CREATE_SESSION - 32) |
+-	      1 << (OP_DESTROY_SESSION - 32) |
+-	      1 << (OP_DESTROY_CLIENTID - 32)
+-};
+-
+ static __be32
+ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
+ 			 struct nfsd4_exchange_id *exid)
+@@ -3885,6 +3875,7 @@ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
+ 	char *server_scope;
+ 	int major_id_sz;
+ 	int server_scope_sz;
++	int status = 0;
+ 	uint64_t minor_id = 0;
+ 
+ 	if (nfserr)
+@@ -3913,18 +3904,20 @@ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
+ 	case SP4_NONE:
+ 		break;
+ 	case SP4_MACH_CRED:
+-		/* spo_must_enforce, spo_must_allow */
+-		p = xdr_reserve_space(xdr, 16);
+-		if (!p)
+-			return nfserr_resource;
+-
+ 		/* spo_must_enforce bitmap: */
+-		*p++ = cpu_to_be32(2);
+-		*p++ = cpu_to_be32(nfs4_minimal_spo_must_enforce[0]);
+-		*p++ = cpu_to_be32(nfs4_minimal_spo_must_enforce[1]);
+-		/* empty spo_must_allow bitmap: */
+-		*p++ = cpu_to_be32(0);
+-
++		status = nfsd4_encode_bitmap(xdr,
++					exid->spo_must_enforce[0],
++					exid->spo_must_enforce[1],
++					exid->spo_must_enforce[2]);
++		if (status)
++			goto out;
++		/* spo_must_allow bitmap: */
++		status = nfsd4_encode_bitmap(xdr,
++					exid->spo_must_allow[0],
++					exid->spo_must_allow[1],
++					exid->spo_must_allow[2]);
++		if (status)
++			goto out;
+ 		break;
+ 	default:
+ 		WARN_ON_ONCE(1);
+@@ -3951,6 +3944,8 @@ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
+ 	/* Implementation id */
+ 	*p++ = cpu_to_be32(0);	/* zero length nfs_impl_id4 array */
+ 	return 0;
++out:
++	return status;
+ }
+ 
+ static __be32
+diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
+index cf980523898b..9446849888d5 100644
+--- a/fs/nfsd/nfsd.h
++++ b/fs/nfsd/nfsd.h
+@@ -124,6 +124,7 @@ void nfs4_state_shutdown_net(struct net *net);
+ void nfs4_reset_lease(time_t leasetime);
+ int nfs4_reset_recoverydir(char *recdir);
+ char * nfs4_recoverydir(void);
++bool nfsd4_spo_must_allow(struct svc_rqst *rqstp);
+ #else
+ static inline int nfsd4_init_slabs(void) { return 0; }
+ static inline void nfsd4_free_slabs(void) { }
+@@ -134,6 +135,10 @@ static inline void nfs4_state_shutdown_net(struct net *net) { }
+ static inline void nfs4_reset_lease(time_t leasetime) { }
+ static inline int nfs4_reset_recoverydir(char *recdir) { return 0; }
+ static inline char * nfs4_recoverydir(void) {return NULL; }
++static inline bool nfsd4_spo_must_allow(struct svc_rqst *rqstp)
++{
++	return false;
++}
+ #endif
+ 
+ /*
+diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
+index 64053eadeb81..b95adf9a1595 100644
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -345,6 +345,7 @@ struct nfs4_client {
+ 	u32			cl_exchange_flags;
+ 	/* number of rpc's in progress over an associated session: */
+ 	atomic_t		cl_refcount;
++	struct nfs4_op_map      cl_spo_must_allow;
+ 
+ 	/* for nfs41 callbacks */
+ 	/* We currently support a single back channel with a single slot */
+diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
+index 74342a7c208a..beea0c5edc51 100644
+--- a/fs/nfsd/xdr4.h
++++ b/fs/nfsd/xdr4.h
+@@ -59,6 +59,7 @@ struct nfsd4_compound_state {
+ 	struct nfsd4_session	*session;
+ 	struct nfsd4_slot	*slot;
+ 	int			data_offset;
++	bool                    spo_must_allowed;
+ 	size_t			iovlen;
+ 	u32			minorversion;
+ 	__be32			status;
+@@ -403,6 +404,8 @@ struct nfsd4_exchange_id {
+ 	clientid_t	clientid;
+ 	u32		seqid;
+ 	int		spa_how;
++	u32             spo_must_enforce[3];
++	u32             spo_must_allow[3];
+ };
+ 
+ struct nfsd4_sequence {

commit dedeb13f9efb4439a37cf56317c8f25860dd667b
+Author: Andrew Elble 
+Date:   Wed Jun 15 12:52:08 2016 -0400
+
+    nfsd: allow mach_creds_match to be used more broadly
+    
+    Rename mach_creds_match() to nfsd4_mach_creds_match() and un-staticify
+    
+    Signed-off-by: Andrew Elble 
+    Reviewed-by: Jeff Layton 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 70d0b9b33031..ef583507d276 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1972,7 +1972,7 @@ static bool svc_rqst_integrity_protected(struct svc_rqst *rqstp)
+ 	       service == RPC_GSS_SVC_PRIVACY;
+ }
+ 
+-static bool mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp)
++bool nfsd4_mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp)
+ {
+ 	struct svc_cred *cr = &rqstp->rq_cred;
+ 
+@@ -2424,7 +2424,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
+ 				status = nfserr_inval;
+ 				goto out;
+ 			}
+-			if (!mach_creds_match(conf, rqstp)) {
++			if (!nfsd4_mach_creds_match(conf, rqstp)) {
+ 				status = nfserr_wrong_cred;
+ 				goto out;
+ 			}
+@@ -2676,7 +2676,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
+ 
+ 	if (conf) {
+ 		status = nfserr_wrong_cred;
+-		if (!mach_creds_match(conf, rqstp))
++		if (!nfsd4_mach_creds_match(conf, rqstp))
+ 			goto out_free_conn;
+ 		cs_slot = &conf->cl_cs_slot;
+ 		status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0);
+@@ -2692,7 +2692,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
+ 			goto out_free_conn;
+ 		}
+ 		status = nfserr_wrong_cred;
+-		if (!mach_creds_match(unconf, rqstp))
++		if (!nfsd4_mach_creds_match(unconf, rqstp))
+ 			goto out_free_conn;
+ 		cs_slot = &unconf->cl_cs_slot;
+ 		status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0);
+@@ -2801,7 +2801,7 @@ __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp,
+ 	if (!session)
+ 		goto out_no_session;
+ 	status = nfserr_wrong_cred;
+-	if (!mach_creds_match(session->se_client, rqstp))
++	if (!nfsd4_mach_creds_match(session->se_client, rqstp))
+ 		goto out;
+ 	status = nfsd4_map_bcts_dir(&bcts->dir);
+ 	if (status)
+@@ -2848,7 +2848,7 @@ nfsd4_destroy_session(struct svc_rqst *r,
+ 	if (!ses)
+ 		goto out_client_lock;
+ 	status = nfserr_wrong_cred;
+-	if (!mach_creds_match(ses->se_client, r))
++	if (!nfsd4_mach_creds_match(ses->se_client, r))
+ 		goto out_put_session;
+ 	status = mark_session_dead_locked(ses, 1 + ref_held_by_me);
+ 	if (status)
+@@ -3087,7 +3087,7 @@ nfsd4_destroy_clientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
+ 		status = nfserr_stale_clientid;
+ 		goto out;
+ 	}
+-	if (!mach_creds_match(clp, rqstp)) {
++	if (!nfsd4_mach_creds_match(clp, rqstp)) {
+ 		clp = NULL;
+ 		status = nfserr_wrong_cred;
+ 		goto out;
+diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
+index d9554813e58a..74342a7c208a 100644
+--- a/fs/nfsd/xdr4.h
++++ b/fs/nfsd/xdr4.h
+@@ -654,6 +654,8 @@ set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp)
+ 
+ }
+ 
++
++bool nfsd4_mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp);
+ int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *);
+ int nfs4svc_decode_compoundargs(struct svc_rqst *, __be32 *,
+ 		struct nfsd4_compoundargs *);

commit 1adf0c5a4451a100cd9253c1d6e3ca77f4a5a98b
+Author: Andrew Elble 
+Date:   Wed Jun 15 12:52:07 2016 -0400
+
+    nfs/nfsd: Move useful bitfield ops to a commonly accessible place
+    
+    So these may be used in nfsd as well
+    
+    Signed-off-by: Andrew Elble 
+    Reviewed-by: Jeff Layton 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
+index bfed6b367350..c6564ada9beb 100644
+--- a/include/linux/nfs4.h
++++ b/include/linux/nfs4.h
+@@ -643,4 +643,15 @@ enum pnfs_update_layout_reason {
+ 	PNFS_UPDATE_LAYOUT_SEND_LAYOUTGET,
+ };
+ 
++#define NFS4_OP_MAP_NUM_LONGS					\
++	DIV_ROUND_UP(LAST_NFS4_OP, 8 * sizeof(unsigned long))
++#define NFS4_OP_MAP_NUM_WORDS \
++	(NFS4_OP_MAP_NUM_LONGS * sizeof(unsigned long) / sizeof(u32))
++struct nfs4_op_map {
++	union {
++		unsigned long longs[NFS4_OP_MAP_NUM_LONGS];
++		u32 words[NFS4_OP_MAP_NUM_WORDS];
++	} u;
++};
++
+ #endif
+diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
+index c304a11b5b1a..e66abc2d1f88 100644
+--- a/include/linux/nfs_xdr.h
++++ b/include/linux/nfs_xdr.h
+@@ -1185,17 +1185,6 @@ struct pnfs_ds_commit_info {
+ 	struct pnfs_commit_bucket *buckets;
+ };
+ 
+-#define NFS4_OP_MAP_NUM_LONGS \
+-	DIV_ROUND_UP(LAST_NFS4_OP, 8 * sizeof(unsigned long))
+-#define NFS4_OP_MAP_NUM_WORDS \
+-	(NFS4_OP_MAP_NUM_LONGS * sizeof(unsigned long) / sizeof(u32))
+-struct nfs4_op_map {
+-	union {
+-		unsigned long longs[NFS4_OP_MAP_NUM_LONGS];
+-		u32 words[NFS4_OP_MAP_NUM_WORDS];
+-	} u;
+-};
+-
+ struct nfs41_state_protection {
+ 	u32 how;
+ 	struct nfs4_op_map enforce;

commit 99ade3c71b1e40e7174d6527709399a87f3d05e0
+Author: Andrew Elble 
+Date:   Wed Dec 2 09:39:51 2015 -0500
+
+    nfs: machine credential support for additional operations
+    
+    Allow LAYOUTRETURN and DELEGRETURN to use machine credentials if the
+    server supports it. Add request for OPEN_DOWNGRADE as the close path
+    also uses that.
+    
+    Signed-off-by: Andrew Elble 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index 18d862db15b6..a7d564a83665 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -5383,6 +5383,11 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
+ 	if (data == NULL)
+ 		return -ENOMEM;
+ 	nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1);
++
++	nfs4_state_protect(server->nfs_client,
++			NFS_SP4_MACH_CRED_CLEANUP,
++			&task_setup_data.rpc_client, &msg);
++
+ 	data->args.fhandle = &data->fh;
+ 	data->args.stateid = &data->stateid;
+ 	data->args.bitmask = server->cache_consistency_bitmask;
+@@ -6859,10 +6864,13 @@ static const struct nfs41_state_protection nfs4_sp4_mach_cred_request = {
+ 	},
+ 	.allow.u.words = {
+ 		[0] = 1 << (OP_CLOSE) |
++		      1 << (OP_OPEN_DOWNGRADE) |
+ 		      1 << (OP_LOCKU) |
++		      1 << (OP_DELEGRETURN) |
+ 		      1 << (OP_COMMIT),
+ 		[1] = 1 << (OP_SECINFO - 32) |
+ 		      1 << (OP_SECINFO_NO_NAME - 32) |
++		      1 << (OP_LAYOUTRETURN - 32) |
+ 		      1 << (OP_TEST_STATEID - 32) |
+ 		      1 << (OP_FREE_STATEID - 32) |
+ 		      1 << (OP_WRITE - 32)
+@@ -6927,11 +6935,19 @@ static int nfs4_sp4_select_mode(struct nfs_client *clp,
+ 		}
+ 
+ 		if (test_bit(OP_CLOSE, sp->allow.u.longs) &&
++		    test_bit(OP_OPEN_DOWNGRADE, sp->allow.u.longs) &&
++		    test_bit(OP_DELEGRETURN, sp->allow.u.longs) &&
+ 		    test_bit(OP_LOCKU, sp->allow.u.longs)) {
+ 			dfprintk(MOUNT, "  cleanup mode enabled\n");
+ 			set_bit(NFS_SP4_MACH_CRED_CLEANUP, &clp->cl_sp4_flags);
+ 		}
+ 
++		if (test_bit(OP_LAYOUTRETURN, sp->allow.u.longs)) {
++			dfprintk(MOUNT, "  pnfs cleanup mode enabled\n");
++			set_bit(NFS_SP4_MACH_CRED_PNFS_CLEANUP,
++				&clp->cl_sp4_flags);
++		}
++
+ 		if (test_bit(OP_SECINFO, sp->allow.u.longs) &&
+ 		    test_bit(OP_SECINFO_NO_NAME, sp->allow.u.longs)) {
+ 			dfprintk(MOUNT, "  secinfo mode enabled\n");
+@@ -8084,6 +8100,10 @@ int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp, bool sync)
+ 	};
+ 	int status = 0;
+ 
++	nfs4_state_protect(NFS_SERVER(lrp->args.inode)->nfs_client,
++			NFS_SP4_MACH_CRED_PNFS_CLEANUP,
++			&task_setup_data.rpc_client, &msg);
++
+ 	dprintk("--> %s\n", __func__);
+ 	if (!sync) {
+ 		lrp->inode = nfs_igrab_and_active(lrp->args.inode);
+diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
+index 2469ab0bb3a1..7fcc13c8cf1f 100644
+--- a/include/linux/nfs_fs_sb.h
++++ b/include/linux/nfs_fs_sb.h
+@@ -102,6 +102,7 @@ struct nfs_client {
+ #define NFS_SP4_MACH_CRED_STATEID  4	/* TEST_STATEID and FREE_STATEID */
+ #define NFS_SP4_MACH_CRED_WRITE    5	/* WRITE */
+ #define NFS_SP4_MACH_CRED_COMMIT   6	/* COMMIT */
++#define NFS_SP4_MACH_CRED_PNFS_CLEANUP  7 /* LAYOUTRETURN */
+ #endif /* CONFIG_NFS_V4 */
+ 
+ 	/* Our own IP address, as a null-terminated string.

commit 361cad3c89070aeb37560860ea8bfc092d545adc
+Author: Andrew Elble 
+Date:   Wed Dec 2 09:20:57 2015 -0500
+
+    nfs: Fix race in __update_open_stateid()
+    
+    We've seen this in a packet capture - I've intermixed what I
+    think was going on. The fix here is to grab the so_lock sooner.
+    
+    1964379 -> #1 open (for write) reply seqid=1
+    1964393 -> #2 open (for read) reply seqid=2
+    
+      __nfs4_close(), state->n_wronly--
+      nfs4_state_set_mode_locked(), changes state->state = [R]
+      state->flags is [RW]
+      state->state is [R], state->n_wronly == 0, state->n_rdonly == 1
+    
+    1964398 -> #3 open (for write) call -> because close is already running
+    1964399 -> downgrade (to read) call seqid=2 (close of #1)
+    1964402 -> #3 open (for write) reply seqid=3
+    
+     __update_open_stateid()
+       nfs_set_open_stateid_locked(), changes state->flags
+       state->flags is [RW]
+       state->state is [R], state->n_wronly == 0, state->n_rdonly == 1
+       new sequence number is exposed now via nfs4_stateid_copy()
+    
+       next step would be update_open_stateflags(), pending so_lock
+    
+    1964403 -> downgrade reply seqid=2, fails with OLD_STATEID (close of #1)
+    
+       nfs4_close_prepare() gets so_lock and recalcs flags -> send close
+    
+    1964405 -> downgrade (to read) call seqid=3 (close of #1 retry)
+    
+       __update_open_stateid() gets so_lock
+     * update_open_stateflags() updates state->n_wronly.
+       nfs4_state_set_mode_locked() updates state->state
+    
+       state->flags is [RW]
+       state->state is [RW], state->n_wronly == 1, state->n_rdonly == 1
+    
+     * should have suppressed the preceding nfs4_close_prepare() from
+       sending open_downgrade
+    
+    1964406 -> write call
+    1964408 -> downgrade (to read) reply seqid=4 (close of #1 retry)
+    
+       nfs_clear_open_stateid_locked()
+       state->flags is [R]
+       state->state is [RW], state->n_wronly == 1, state->n_rdonly == 1
+    
+    1964409 -> write reply (fails, openmode)
+    
+    Signed-off-by: Andrew Elble 
+    Cc: stable@vger,kernel.org
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index 89818036f035..2f1714fda666 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -1385,6 +1385,7 @@ static void __update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_s
+ 	 * Protect the call to nfs4_state_set_mode_locked and
+ 	 * serialise the stateid update
+ 	 */
++	spin_lock(&state->owner->so_lock);
+ 	write_seqlock(&state->seqlock);
+ 	if (deleg_stateid != NULL) {
+ 		nfs4_stateid_copy(&state->stateid, deleg_stateid);
+@@ -1393,7 +1394,6 @@ static void __update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_s
+ 	if (open_stateid != NULL)
+ 		nfs_set_open_stateid_locked(state, open_stateid, fmode);
+ 	write_sequnlock(&state->seqlock);
+-	spin_lock(&state->owner->so_lock);
+ 	update_open_stateflags(state, fmode);
+ 	spin_unlock(&state->owner->so_lock);
+ }

commit 52618df95d0820be7add339068d3c42799393c09
+Author: Andrew Elble 
+Date:   Wed Dec 2 09:19:43 2015 -0500
+
+    nfs: fix missing assignment in nfs4_sequence_done tracepoint
+    
+    status_flags not set
+    
+    Signed-off-by: Andrew Elble 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/nfs4trace.h b/fs/nfs/nfs4trace.h
+index 671cf68fe56b..4c1015462a81 100644
+--- a/fs/nfs/nfs4trace.h
++++ b/fs/nfs/nfs4trace.h
+@@ -321,6 +321,7 @@ TRACE_EVENT(nfs4_sequence_done,
+ 			__entry->highest_slotid = res->sr_highest_slotid;
+ 			__entry->target_highest_slotid =
+ 					res->sr_target_highest_slotid;
++			__entry->status_flags = res->sr_status_flags;
+ 			__entry->error = res->sr_status;
+ 		),
+ 		TP_printk(

commit 7fc0564e3a8d16df096f48c9c6425ba84d945c6e
+Author: Andrew Elble 
+Date:   Thu Nov 5 20:42:43 2015 -0500
+
+    nfsd: fix race with open / open upgrade stateids
+    
+    We observed multiple open stateids on the server for files that
+    seemingly should have been closed.
+    
+    nfsd4_process_open2() tests for the existence of a preexisting
+    stateid. If one is not found, the locks are dropped and a new
+    one is created. The problem is that init_open_stateid(), which
+    is also responsible for hashing the newly initialized stateid,
+    doesn't check to see if another open has raced in and created
+    a matching stateid. This fix is to enable init_open_stateid() to
+    return the matching stateid and have nfsd4_process_open2()
+    swap to that stateid and switch to the open upgrade path.
+    In testing this patch, coverage to the newly created
+    path indicates that the race was indeed happening.
+    
+    Signed-off-by: Andrew Elble 
+    Reviewed-by: Jeff Layton 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 6411c3421870..6b800b5b8fed 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -3392,6 +3392,27 @@ static const struct nfs4_stateowner_operations openowner_ops = {
+ 	.so_free =	nfs4_free_openowner,
+ };
+ 
++static struct nfs4_ol_stateid *
++nfsd4_find_existing_open(struct nfs4_file *fp, struct nfsd4_open *open)
++{
++	struct nfs4_ol_stateid *local, *ret = NULL;
++	struct nfs4_openowner *oo = open->op_openowner;
++
++	lockdep_assert_held(&fp->fi_lock);
++
++	list_for_each_entry(local, &fp->fi_stateids, st_perfile) {
++		/* ignore lock owners */
++		if (local->st_stateowner->so_is_open_owner == 0)
++			continue;
++		if (local->st_stateowner == &oo->oo_owner) {
++			ret = local;
++			atomic_inc(&ret->st_stid.sc_count);
++			break;
++		}
++	}
++	return ret;
++}
++
+ static struct nfs4_openowner *
+ alloc_init_open_stateowner(unsigned int strhashval, struct nfsd4_open *open,
+ 			   struct nfsd4_compound_state *cstate)
+@@ -3423,9 +3444,20 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfsd4_open *open,
+ 	return ret;
+ }
+ 
+-static void init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *open) {
++static struct nfs4_ol_stateid *
++init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp,
++		struct nfsd4_open *open)
++{
++
+ 	struct nfs4_openowner *oo = open->op_openowner;
++	struct nfs4_ol_stateid *retstp = NULL;
+ 
++	spin_lock(&oo->oo_owner.so_client->cl_lock);
++	spin_lock(&fp->fi_lock);
++
++	retstp = nfsd4_find_existing_open(fp, open);
++	if (retstp)
++		goto out_unlock;
+ 	atomic_inc(&stp->st_stid.sc_count);
+ 	stp->st_stid.sc_type = NFS4_OPEN_STID;
+ 	INIT_LIST_HEAD(&stp->st_locks);
+@@ -3436,12 +3468,13 @@ static void init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp,
+ 	stp->st_deny_bmap = 0;
+ 	stp->st_openstp = NULL;
+ 	init_rwsem(&stp->st_rwsem);
+-	spin_lock(&oo->oo_owner.so_client->cl_lock);
+ 	list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids);
+-	spin_lock(&fp->fi_lock);
+ 	list_add(&stp->st_perfile, &fp->fi_stateids);
++
++out_unlock:
+ 	spin_unlock(&fp->fi_lock);
+ 	spin_unlock(&oo->oo_owner.so_client->cl_lock);
++	return retstp;
+ }
+ 
+ /*
+@@ -3852,27 +3885,6 @@ nfs4_check_deleg(struct nfs4_client *cl, struct nfsd4_open *open,
+ 	return nfs_ok;
+ }
+ 
+-static struct nfs4_ol_stateid *
+-nfsd4_find_existing_open(struct nfs4_file *fp, struct nfsd4_open *open)
+-{
+-	struct nfs4_ol_stateid *local, *ret = NULL;
+-	struct nfs4_openowner *oo = open->op_openowner;
+-
+-	spin_lock(&fp->fi_lock);
+-	list_for_each_entry(local, &fp->fi_stateids, st_perfile) {
+-		/* ignore lock owners */
+-		if (local->st_stateowner->so_is_open_owner == 0)
+-			continue;
+-		if (local->st_stateowner == &oo->oo_owner) {
+-			ret = local;
+-			atomic_inc(&ret->st_stid.sc_count);
+-			break;
+-		}
+-	}
+-	spin_unlock(&fp->fi_lock);
+-	return ret;
+-}
+-
+ static inline int nfs4_access_to_access(u32 nfs4_access)
+ {
+ 	int flags = 0;
+@@ -4258,6 +4270,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
+ 	struct nfs4_client *cl = open->op_openowner->oo_owner.so_client;
+ 	struct nfs4_file *fp = NULL;
+ 	struct nfs4_ol_stateid *stp = NULL;
++	struct nfs4_ol_stateid *swapstp = NULL;
+ 	struct nfs4_delegation *dp = NULL;
+ 	__be32 status;
+ 
+@@ -4271,7 +4284,9 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
+ 		status = nfs4_check_deleg(cl, open, &dp);
+ 		if (status)
+ 			goto out;
++		spin_lock(&fp->fi_lock);
+ 		stp = nfsd4_find_existing_open(fp, open);
++		spin_unlock(&fp->fi_lock);
+ 	} else {
+ 		open->op_file = NULL;
+ 		status = nfserr_bad_stateid;
+@@ -4294,7 +4309,19 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
+ 	} else {
+ 		stp = open->op_stp;
+ 		open->op_stp = NULL;
+-		init_open_stateid(stp, fp, open);
++		swapstp = init_open_stateid(stp, fp, open);
++		if (swapstp) {
++			nfs4_put_stid(&stp->st_stid);
++			stp = swapstp;
++			down_read(&stp->st_rwsem);
++			status = nfs4_upgrade_open(rqstp, fp, current_fh,
++						stp, open);
++			if (status) {
++				up_read(&stp->st_rwsem);
++				goto out;
++			}
++			goto upgrade_out;
++		}
+ 		down_read(&stp->st_rwsem);
+ 		status = nfs4_get_vfs_file(rqstp, fp, current_fh, stp, open);
+ 		if (status) {
+@@ -4308,6 +4335,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
+ 		if (stp->st_clnt_odstate == open->op_odstate)
+ 			open->op_odstate = NULL;
+ 	}
++upgrade_out:
+ 	nfs4_inc_and_copy_stateid(&open->op_stateid, &stp->st_stid);
+ 	up_read(&stp->st_rwsem);
+ 

commit 34ed9872e745fa56f10e9bef2cf3d2336c6c8816
+Author: Andrew Elble 
+Date:   Thu Oct 15 12:07:28 2015 -0400
+
+    nfsd: eliminate sending duplicate and repeated delegations
+    
+    We've observed the nfsd server in a state where there are
+    multiple delegations on the same nfs4_file for the same client.
+    The nfs client does attempt to DELEGRETURN these when they are presented to
+    it - but apparently under some (unknown) circumstances the client does not
+    manage to return all of them. This leads to the eventual
+    attempt to CB_RECALL more than one delegation with the same nfs
+    filehandle to the same client. The first recall will succeed, but the
+    next recall will fail with NFS4ERR_BADHANDLE. This leads to the server
+    having delegations on cl_revoked that the client has no way to FREE
+    or DELEGRETURN, with resulting inability to recover. The state manager
+    on the server will continually assert SEQ4_STATUS_RECALLABLE_STATE_REVOKED,
+    and the state manager on the client will be looping unable to satisfy
+    the server.
+    
+    List discussion also reports a race between OPEN and DELEGRETURN that
+    will be avoided by only sending the delegation once to the
+    client. This is also logically in accordance with RFC5561 9.1.1 and 10.2.
+    
+    So, let's:
+    
+    1.) Not hand out duplicate delegations.
+    2.) Only send them to the client once.
+    
+    RFC 5561:
+    
+    9.1.1:
+    "Delegations and layouts, on the other hand, are not associated with a
+    specific owner but are associated with the client as a whole
+    (identified by a client ID)."
+    
+    10.2:
+    "...the stateid for a delegation is associated with a client ID and may be
+    used on behalf of all the open-owners for the given client.  A
+    delegation is made to the client as a whole and not to any specific
+    process or thread of control within it."
+    
+    Reported-by: Eric Meddaugh 
+    Cc: Trond Myklebust 
+    Cc: Olga Kornievskaia 
+    Signed-off-by: Andrew Elble 
+    Cc: stable@vger.kernel.org
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 0a697158a4ca..6411c3421870 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -778,16 +778,68 @@ void nfs4_unhash_stid(struct nfs4_stid *s)
+ 	s->sc_type = 0;
+ }
+ 
+-static void
++/**
++ * nfs4_get_existing_delegation - Discover if this delegation already exists
++ * @clp:     a pointer to the nfs4_client we're granting a delegation to
++ * @fp:      a pointer to the nfs4_file we're granting a delegation on
++ *
++ * Return:
++ *      On success: NULL if an existing delegation was not found.
++ *
++ *      On error: -EAGAIN if one was previously granted to this nfs4_client
++ *                 for this nfs4_file.
++ *
++ */
++
++static int
++nfs4_get_existing_delegation(struct nfs4_client *clp, struct nfs4_file *fp)
++{
++	struct nfs4_delegation *searchdp = NULL;
++	struct nfs4_client *searchclp = NULL;
++
++	lockdep_assert_held(&state_lock);
++	lockdep_assert_held(&fp->fi_lock);
++
++	list_for_each_entry(searchdp, &fp->fi_delegations, dl_perfile) {
++		searchclp = searchdp->dl_stid.sc_client;
++		if (clp == searchclp) {
++			return -EAGAIN;
++		}
++	}
++	return 0;
++}
++
++/**
++ * hash_delegation_locked - Add a delegation to the appropriate lists
++ * @dp:     a pointer to the nfs4_delegation we are adding.
++ * @fp:     a pointer to the nfs4_file we're granting a delegation on
++ *
++ * Return:
++ *      On success: NULL if the delegation was successfully hashed.
++ *
++ *      On error: -EAGAIN if one was previously granted to this
++ *                 nfs4_client for this nfs4_file. Delegation is not hashed.
++ *
++ */
++
++static int
+ hash_delegation_locked(struct nfs4_delegation *dp, struct nfs4_file *fp)
+ {
++	int status;
++	struct nfs4_client *clp = dp->dl_stid.sc_client;
++
+ 	lockdep_assert_held(&state_lock);
+ 	lockdep_assert_held(&fp->fi_lock);
+ 
++	status = nfs4_get_existing_delegation(clp, fp);
++	if (status)
++		return status;
++	++fp->fi_delegees;
+ 	atomic_inc(&dp->dl_stid.sc_count);
+ 	dp->dl_stid.sc_type = NFS4_DELEG_STID;
+ 	list_add(&dp->dl_perfile, &fp->fi_delegations);
+-	list_add(&dp->dl_perclnt, &dp->dl_stid.sc_client->cl_delegations);
++	list_add(&dp->dl_perclnt, &clp->cl_delegations);
++	return 0;
+ }
+ 
+ static bool
+@@ -3969,6 +4021,18 @@ static struct file_lock *nfs4_alloc_init_lease(struct nfs4_file *fp, int flag)
+ 	return fl;
+ }
+ 
++/**
++ * nfs4_setlease - Obtain a delegation by requesting lease from vfs layer
++ * @dp:   a pointer to the nfs4_delegation we're adding.
++ *
++ * Return:
++ *      On success: Return code will be 0 on success.
++ *
++ *      On error: -EAGAIN if there was an existing delegation.
++ *                 nonzero if there is an error in other cases.
++ *
++ */
++
+ static int nfs4_setlease(struct nfs4_delegation *dp)
+ {
+ 	struct nfs4_file *fp = dp->dl_stid.sc_file;
+@@ -4000,16 +4064,19 @@ static int nfs4_setlease(struct nfs4_delegation *dp)
+ 		goto out_unlock;
+ 	/* Race breaker */
+ 	if (fp->fi_deleg_file) {
+-		status = 0;
+-		++fp->fi_delegees;
+-		hash_delegation_locked(dp, fp);
++		status = hash_delegation_locked(dp, fp);
+ 		goto out_unlock;
+ 	}
+ 	fp->fi_deleg_file = filp;
+-	fp->fi_delegees = 1;
+-	hash_delegation_locked(dp, fp);
++	fp->fi_delegees = 0;
++	status = hash_delegation_locked(dp, fp);
+ 	spin_unlock(&fp->fi_lock);
+ 	spin_unlock(&state_lock);
++	if (status) {
++		/* Should never happen, this is a new fi_deleg_file  */
++		WARN_ON_ONCE(1);
++		goto out_fput;
++	}
+ 	return 0;
+ out_unlock:
+ 	spin_unlock(&fp->fi_lock);
+@@ -4029,6 +4096,15 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,
+ 	if (fp->fi_had_conflict)
+ 		return ERR_PTR(-EAGAIN);
+ 
++	spin_lock(&state_lock);
++	spin_lock(&fp->fi_lock);
++	status = nfs4_get_existing_delegation(clp, fp);
++	spin_unlock(&fp->fi_lock);
++	spin_unlock(&state_lock);
++
++	if (status)
++		return ERR_PTR(status);
++
+ 	dp = alloc_init_deleg(clp, fh, odstate);
+ 	if (!dp)
+ 		return ERR_PTR(-ENOMEM);
+@@ -4047,9 +4123,7 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,
+ 		status = -EAGAIN;
+ 		goto out_unlock;
+ 	}
+-	++fp->fi_delegees;
+-	hash_delegation_locked(dp, fp);
+-	status = 0;
++	status = hash_delegation_locked(dp, fp);
+ out_unlock:
+ 	spin_unlock(&fp->fi_lock);
+ 	spin_unlock(&state_lock);

commit a457974f1b9524a6e7d0a0be10df760e7802d32f
+Author: Andrew Elble 
+Date:   Mon Aug 31 12:06:41 2015 -0400
+
+    nfsd: deal with DELEGRETURN racing with CB_RECALL
+    
+    We have observed the server sending recalls for delegation stateids
+    that have already been successfully returned. Change
+    nfsd4_cb_recall_done() to return success if the client has returned
+    the delegation. While this does not completely eliminate the sending
+    of recalls for delegations that have already been returned, this
+    does prevent unnecessarily declaring the callback path to be down.
+    
+    Reported-by: Eric Meddaugh 
+    Signed-off-by: Andrew Elble 
+    Acked-by: Jeff Layton 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 08746ec1d44a..0f1d5691b795 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -3510,6 +3510,9 @@ static int nfsd4_cb_recall_done(struct nfsd4_callback *cb,
+ {
+ 	struct nfs4_delegation *dp = cb_to_delegation(cb);
+ 
++	if (dp->dl_stid.sc_type == NFS4_CLOSED_DELEG_STID)
++	        return 1;
++
+ 	switch (task->tk_status) {
+ 	case 0:
+ 		return 1;

commit c1b8940b42bb6487b10f2267a96b486276ce9ff7
+Author: Andrew Elble 
+Date:   Mon Feb 23 08:51:24 2015 -0500
+
+    NFS: fix BUG() crash in notify_change() with patch to chown_common()
+    
+    We have observed a BUG() crash in fs/attr.c:notify_change(). The crash
+    occurs during an rsync into a filesystem that is exported via NFS.
+    
+    1.) fs/attr.c:notify_change() modifies the caller's version of attr.
+    2.) 6de0ec00ba8d ("VFS: make notify_change pass ATTR_KILL_S*ID to
+        setattr operations") introduced a BUG() restriction such that "no
+        function will ever call notify_change() with both ATTR_MODE and
+        ATTR_KILL_S*ID set". Under some circumstances though, it will have
+        assisted in setting the caller's version of attr to this very
+        combination.
+    3.) 27ac0ffeac80 ("locks: break delegations on any attribute
+        modification") introduced code to handle breaking
+        delegations. This can result in notify_change() being re-called. attr
+        _must_ be explicitly reset to avoid triggering the BUG() established
+        in #2.
+    4.) The path that that triggers this is via fs/open.c:chmod_common().
+        The combination of attr flags set here and in the first call to
+        notify_change() along with a later failed break_deleg_wait()
+        results in notify_change() being called again via retry_deleg
+        without resetting attr.
+    
+    Solution is to move retry_deleg in chmod_common() a bit further up to
+    ensure attr is completely reset.
+    
+    There are other places where this seemingly could occur, such as
+    fs/utimes.c:utimes_common(), but the attr flags are not initially
+    set in such a way to trigger this.
+    
+    Fixes: 27ac0ffeac80 ("locks: break delegations on any attribute modification")
+    Reported-by: Eric Meddaugh 
+    Tested-by: Eric Meddaugh 
+    Signed-off-by: Andrew Elble 
+    Signed-off-by: Al Viro 
+
+diff --git a/fs/open.c b/fs/open.c
+index ebcc7df0c9b6..6a83c47d5904 100644
+--- a/fs/open.c
++++ b/fs/open.c
+@@ -570,6 +570,7 @@ static int chown_common(struct path *path, uid_t user, gid_t group)
+ 	uid = make_kuid(current_user_ns(), user);
+ 	gid = make_kgid(current_user_ns(), group);
+ 
++retry_deleg:
+ 	newattrs.ia_valid =  ATTR_CTIME;
+ 	if (user != (uid_t) -1) {
+ 		if (!uid_valid(uid))
+@@ -586,7 +587,6 @@ static int chown_common(struct path *path, uid_t user, gid_t group)
+ 	if (!S_ISDIR(inode->i_mode))
+ 		newattrs.ia_valid |=
+ 			ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
+-retry_deleg:
+ 	mutex_lock(&inode->i_mutex);
+ 	error = security_path_chown(path, uid, gid);
+ 	if (!error)

commit c876486be17aeefe0da569f3d111cbd8de6f675d
+Author: Andrew Elble 
+Date:   Wed Feb 25 17:46:27 2015 -0500
+
+    nfsd: fix clp->cl_revoked list deletion causing softlock in nfsd
+    
+    commit 2d4a532d385f ("nfsd: ensure that clp->cl_revoked list is
+    protected by clp->cl_lock") removed the use of the reaplist to
+    clean out clp->cl_revoked. It failed to change list_entry() to
+    walk clp->cl_revoked.next instead of reaplist.next
+    
+    Fixes: 2d4a532d385f ("nfsd: ensure that clp->cl_revoked list is protected by clp->cl_lock")
+    Cc: stable@vger.kernel.org
+    Reported-by: Eric Meddaugh 
+    Tested-by: Eric Meddaugh 
+    Signed-off-by: Andrew Elble 
+    Reviewed-by: Jeff Layton 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index f6b2a09f793f..d2f2c37dc2db 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1638,7 +1638,7 @@ __destroy_client(struct nfs4_client *clp)
+ 		nfs4_put_stid(&dp->dl_stid);
+ 	}
+ 	while (!list_empty(&clp->cl_revoked)) {
+-		dp = list_entry(reaplist.next, struct nfs4_delegation, dl_recall_lru);
++		dp = list_entry(clp->cl_revoked.next, struct nfs4_delegation, dl_recall_lru);
+ 		list_del_init(&dp->dl_recall_lru);
+ 		nfs4_put_stid(&dp->dl_stid);
+ 	}

commit 278702074ff77b1a3fa2061267997095959f5e2c
+Author: Andrew Elble 
+Date:   Mon Feb 9 12:53:04 2015 -0500
+
+    GFS2: Fix crash during ACL deletion in acl max entry check in gfs2_set_acl()
+    
+    Fixes: e01580bf9e ("gfs2: use generic posix ACL infrastructure")
+    Reported-by: Eric Meddaugh 
+    Tested-by: Eric Meddaugh 
+    Signed-off-by: Andrew Elble 
+    Signed-off-by: Steven Whitehouse 
+
+diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
+index 3088e2a38e30..7b3143064af1 100644
+--- a/fs/gfs2/acl.c
++++ b/fs/gfs2/acl.c
+@@ -73,7 +73,7 @@ int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
+ 
+ 	BUG_ON(name == NULL);
+ 
+-	if (acl->a_count > GFS2_ACL_MAX_ENTRIES(GFS2_SB(inode)))
++	if (acl && acl->a_count > GFS2_ACL_MAX_ENTRIES(GFS2_SB(inode)))
+ 		return -E2BIG;
+ 
+ 	if (type == ACL_TYPE_ACCESS) {

\ No newline at end of file diff --git a/detail/36.html b/detail/36.html new file mode 100644 index 0000000..b4afcfe --- /dev/null +++ b/detail/36.html @@ -0,0 +1,1621 @@ +

Patches contributed by City College of San Francisco


commit ba272e3bbeaee3b34ca6c616f7ad8d3c65f33f79
+Author: Katie Dunne 
+Date:   Mon Sep 18 15:52:40 2017 -0700
+
+    Staging: iio: meter: ade7759: update locking method for write frequency
+    
+    iio_dev->mlock is to be used only by the IIO core for protecting
+    device mode changes between INDIO_DIRECT and INDIO_BUFFER.
+    
+    This patch replaces the use of mlock with the already established
+    buf_lock mutex.
+    
+    Introducing an 'unlocked' spi_write_reg_16 function to be used by
+    ade7759_write_frequency avoids nested locks and maintains atomicity
+    between bus and device frequency changes.
+    
+    Based on the solution found in ade7754 patch here:
+    https://marc.info/?l=linux-iio&m=149086659008991&w=2
+    
+    Signed-off-by: Katie Dunne 
+    Signed-off-by: Jonathan Cameron 
+
+diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c
+index 7639e90d1c94..cd75f60aded3 100644
+--- a/drivers/staging/iio/meter/ade7759.c
++++ b/drivers/staging/iio/meter/ade7759.c
+@@ -60,7 +60,7 @@
+ /**
+  * struct ade7759_state - device instance specific data
+  * @us:			actual spi_device
+- * @buf_lock:		mutex to protect tx and rx
++ * @buf_lock:		mutex to protect tx and rx and write frequency
+  * @tx:			transmit buffer
+  * @rx:			receive buffer
+  **/
+@@ -89,19 +89,30 @@ static int ade7759_spi_write_reg_8(struct device *dev,
+ 	return ret;
+ }
+ 
+-static int ade7759_spi_write_reg_16(struct device *dev,
++/*Unlocked version of ade7759_spi_write_reg_16 function */
++static int __ade7759_spi_write_reg_16(struct device *dev,
+ 		u8 reg_address,
+ 		u16 value)
+ {
+-	int ret;
+ 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ 	struct ade7759_state *st = iio_priv(indio_dev);
+ 
+-	mutex_lock(&st->buf_lock);
+ 	st->tx[0] = ADE7759_WRITE_REG(reg_address);
+ 	st->tx[1] = (value >> 8) & 0xFF;
+ 	st->tx[2] = value & 0xFF;
+-	ret = spi_write(st->us, st->tx, 3);
++	return spi_write(st->us, st->tx, 3);
++}
++
++static int ade7759_spi_write_reg_16(struct device *dev,
++		u8 reg_address,
++		u16 value)
++{
++	int ret;
++	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
++	struct ade7759_state *st = iio_priv(indio_dev);
++
++	mutex_lock(&st->buf_lock);
++	ret = __ade7759_spi_write_reg_16(dev, reg_address, value);
+ 	mutex_unlock(&st->buf_lock);
+ 
+ 	return ret;
+@@ -429,7 +440,7 @@ static ssize_t ade7759_write_frequency(struct device *dev,
+ 	if (!val)
+ 		return -EINVAL;
+ 
+-	mutex_lock(&indio_dev->mlock);
++	mutex_lock(&st->buf_lock);
+ 
+ 	t = 27900 / val;
+ 	if (t > 0)
+@@ -447,10 +458,10 @@ static ssize_t ade7759_write_frequency(struct device *dev,
+ 	reg &= ~(3 << 13);
+ 	reg |= t << 13;
+ 
+-	ret = ade7759_spi_write_reg_16(dev, ADE7759_MODE, reg);
++	ret = __ade7759_spi_write_reg_16(dev, ADE7759_MODE, reg);
+ 
+ out:
+-	mutex_unlock(&indio_dev->mlock);
++	mutex_unlock(&st->buf_lock);
+ 
+ 	return ret ? ret : len;
+ }

commit dff1e0ef86cba81bf3d892036a28e8b889b7e72c
+Author: Katie Dunne 
+Date:   Mon Feb 20 13:53:07 2017 -0800
+
+    staging: vt6656: remove blank lines at opening and closing braces
+    
+    Removes unnecessary blank lines after opening and before closing braces.
+    These instances were found by checkpatch.pl.
+    
+    Signed-off-by: Katie Dunne 
+    Acked-by: Julia Lawall 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c
+index 9f6cc2ef08dd..b2fc17f1381b 100644
+--- a/drivers/staging/vt6656/wcmd.c
++++ b/drivers/staging/vt6656/wcmd.c
+@@ -45,7 +45,6 @@ static void vnt_cmd_timer_wait(struct vnt_private *priv, unsigned long msecs)
+ 
+ static int vnt_cmd_complete(struct vnt_private *priv)
+ {
+-
+ 	priv->command_state = WLAN_CMD_IDLE;
+ 	if (priv->free_cmd_queue == CMD_Q_SIZE) {
+ 		/* Command Queue Empty */
+@@ -165,7 +164,6 @@ void vnt_run_command(struct work_struct *work)
+ 
+ int vnt_schedule_command(struct vnt_private *priv, enum vnt_cmd command)
+ {
+-
+ 	if (priv->free_cmd_queue == 0)
+ 		return false;
+ 
+@@ -178,7 +176,6 @@ int vnt_schedule_command(struct vnt_private *priv, enum vnt_cmd command)
+ 		vnt_cmd_complete(priv);
+ 
+ 	return true;
+-
+ }
+ 
+ void vnt_reset_command_timer(struct vnt_private *priv)

commit 3efc66167007f4bd77d7690bf35ef1339b8bf374
+Author: Katie Dunne 
+Date:   Sun Feb 19 21:14:29 2017 -0800
+
+    staging: sm750fb: add spaces around operators
+    
+    Add spaces around operators -, *, ?:, >>, << to conform to kernel style.
+    These instances were found with checkpatch.pl
+    
+    Signed-off-by: Katie Dunne 
+    Acked-by: Julia Lawall 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/sm750fb/sm750_cursor.c b/drivers/staging/sm750fb/sm750_cursor.c
+index b1651b0d2034..dbc8bb1fa9c1 100644
+--- a/drivers/staging/sm750fb/sm750_cursor.c
++++ b/drivers/staging/sm750fb/sm750_cursor.c
+@@ -111,14 +111,14 @@ void sm750_hw_cursor_setData(struct lynx_cursor *cursor,
+ 		data = 0;
+ 
+ 		for (j = 0; j < 8; j++) {
+-			if (mask & (0x80>>j)) {
++			if (mask & (0x80 >> j)) {
+ 				if (rop == ROP_XOR)
+ 					opr = mask ^ color;
+ 				else
+ 					opr = mask & color;
+ 
+ 				/* 2 stands for forecolor and 1 for backcolor */
+-				data |= ((opr & (0x80>>j))?2:1)<<(j*2);
++				data |= ((opr & (0x80 >> j)) ? 2 : 1) << (j * 2);
+ 			}
+ 		}
+ 		iowrite16(data, pbuffer);
+@@ -165,13 +165,13 @@ void sm750_hw_cursor_setData2(struct lynx_cursor *cursor,
+ 		data = 0;
+ 
+ 		for (j = 0; j < 8; j++) {
+-			if (mask & (1<
commit 144634a6b42146834fb58ddd629545edd3e518db
+Author: Katie Dunne 
+Date:   Sun Feb 19 20:38:57 2017 -0800
+
+    staging: sm750fb: add curly braces to if-statements
+    
+    Add curly braces to if-statements for style compliance.
+    These cases are found by checkpatch.pl
+    
+    Signed-off-by: Katie Dunne 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c
+index e49f8845f923..332a3ef27ba8 100644
+--- a/drivers/staging/sm750fb/sm750.c
++++ b/drivers/staging/sm750fb/sm750.c
+@@ -954,23 +954,23 @@ static void sm750fb_setup(struct sm750_dev *sm750_dev, char *src)
+ 		dev_info(&sm750_dev->pdev->dev, "opt=%s\n", opt);
+ 		dev_info(&sm750_dev->pdev->dev, "src=%s\n", src);
+ 
+-		if (!strncmp(opt, "swap", strlen("swap")))
++		if (!strncmp(opt, "swap", strlen("swap"))) {
+ 			swap = 1;
+-		else if (!strncmp(opt, "nocrt", strlen("nocrt")))
++		} else if (!strncmp(opt, "nocrt", strlen("nocrt"))) {
+ 			sm750_dev->nocrt = 1;
+-		else if (!strncmp(opt, "36bit", strlen("36bit")))
++		} else if (!strncmp(opt, "36bit", strlen("36bit"))) {
+ 			sm750_dev->pnltype = sm750_doubleTFT;
+-		else if (!strncmp(opt, "18bit", strlen("18bit")))
++		} else if (!strncmp(opt, "18bit", strlen("18bit"))) {
+ 			sm750_dev->pnltype = sm750_dualTFT;
+-		else if (!strncmp(opt, "24bit", strlen("24bit")))
++		} else if (!strncmp(opt, "24bit", strlen("24bit"))) {
+ 			sm750_dev->pnltype = sm750_24TFT;
+-		else if (!strncmp(opt, "nohwc0", strlen("nohwc0")))
++		} else if (!strncmp(opt, "nohwc0", strlen("nohwc0"))) {
+ 			g_hwcursor &= ~0x1;
+-		else if (!strncmp(opt, "nohwc1", strlen("nohwc1")))
++		} else if (!strncmp(opt, "nohwc1", strlen("nohwc1"))) {
+ 			g_hwcursor &= ~0x2;
+-		else if (!strncmp(opt, "nohwc", strlen("nohwc")))
++		} else if (!strncmp(opt, "nohwc", strlen("nohwc"))) {
+ 			g_hwcursor = 0;
+-		else {
++		} else {
+ 			if (!g_fbmode[0]) {
+ 				g_fbmode[0] = opt;
+ 				dev_info(&sm750_dev->pdev->dev,
+@@ -1168,13 +1168,13 @@ static int __init lynxfb_setup(char *options)
+ 	 */
+ 	while ((opt = strsep(&options, ":")) != NULL) {
+ 		/* options that mean for any lynx chips are configured here */
+-		if (!strncmp(opt, "noaccel", strlen("noaccel")))
++		if (!strncmp(opt, "noaccel", strlen("noaccel"))) {
+ 			g_noaccel = 1;
+-		else if (!strncmp(opt, "nomtrr", strlen("nomtrr")))
++		} else if (!strncmp(opt, "nomtrr", strlen("nomtrr"))) {
+ 			g_nomtrr = 1;
+-		else if (!strncmp(opt, "dual", strlen("dual")))
++		} else if (!strncmp(opt, "dual", strlen("dual"))) {
+ 			g_dualview = 1;
+-		else {
++		} else {
+ 			strcat(tmp, opt);
+ 			tmp += strlen(opt);
+ 			if (options)

commit d680d24eacac3124fc0d6a2fab0eef0074f09efd
+Author: Katie Dunne 
+Date:   Sun Feb 19 18:30:00 2017 -0800
+
+    staging: ks7010: remove unecessary spaces after casts
+    
+    Remove spaces after casts found by checkpatch.pl. In some cases,
+    remove returns after casts and place them on a single line.
+    
+    Signed-off-by: Katie Dunne 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c
+index fab06f29ec8b..a533408cf0b9 100644
+--- a/drivers/staging/ks7010/ks_hostif.c
++++ b/drivers/staging/ks7010/ks_hostif.c
+@@ -379,9 +379,8 @@ void hostif_data_indication(struct ks_wlan_private *priv)
+ 				       (priv->rxp) + ((priv->rx_size) - 8), 8);
+ 				priv->rx_size = priv->rx_size - 8;
+ 				if (auth_type > 0 && auth_type < 4) {	/* auth_type check */
+-					MichaelMICFunction(&michel_mic, (uint8_t *) priv->wpa.key[auth_type - 1].rx_mic_key, (uint8_t *) priv->rxp, (int)priv->rx_size, (uint8_t) 0,	/* priority */
+-							   (uint8_t *)
+-							   michel_mic.Result);
++					MichaelMICFunction(&michel_mic, (uint8_t *)priv->wpa.key[auth_type - 1].rx_mic_key, (uint8_t *)priv->rxp, (int)priv->rx_size, (uint8_t)0,	/* priority */
++							   (uint8_t *)michel_mic.Result);
+ 				}
+ 				if (memcmp(michel_mic.Result, RecvMIC, 8)) {
+ 					now = jiffies;
+@@ -400,7 +399,7 @@ void hostif_data_indication(struct ks_wlan_private *priv)
+ 					} else if (mic_failure->failure == 1) {
+ 						mic_failure->failure = 2;
+ 						mic_failure->counter =
+-						    (uint16_t) ((now -
++						    (uint16_t)((now -
+ 								 mic_failure->
+ 								 last_failure_time)
+ 								/ HZ);
+@@ -1217,37 +1216,37 @@ int hostif_data_request(struct ks_wlan_private *priv, struct sk_buff *packet)
+ 		    && !(priv->wpa.key[1].key_len)
+ 		    && !(priv->wpa.key[2].key_len)
+ 		    && !(priv->wpa.key[3].key_len)) {
+-			pp->auth_type = cpu_to_le16((uint16_t) TYPE_AUTH);	/* no encryption */
++			pp->auth_type = cpu_to_le16((uint16_t)TYPE_AUTH);	/* no encryption */
+ 		} else {
+ 			if (priv->wpa.pairwise_suite == IW_AUTH_CIPHER_TKIP) {
+-				MichaelMICFunction(&michel_mic, (uint8_t *) priv->wpa.key[0].tx_mic_key, (uint8_t *) &pp->data[0], (int)packet_len, (uint8_t) 0,	/* priority */
+-						   (uint8_t *) michel_mic.
++				MichaelMICFunction(&michel_mic, (uint8_t *)priv->wpa.key[0].tx_mic_key, (uint8_t *)&pp->data[0], (int)packet_len, (uint8_t)0,	/* priority */
++						   (uint8_t *)michel_mic.
+ 						   Result);
+ 				memcpy(p, michel_mic.Result, 8);
+ 				length += 8;
+ 				packet_len += 8;
+ 				p += 8;
+ 				pp->auth_type =
+-				    cpu_to_le16((uint16_t) TYPE_DATA);
++				    cpu_to_le16((uint16_t)TYPE_DATA);
+ 
+ 			} else if (priv->wpa.pairwise_suite ==
+ 				   IW_AUTH_CIPHER_CCMP) {
+ 				pp->auth_type =
+-				    cpu_to_le16((uint16_t) TYPE_DATA);
++				    cpu_to_le16((uint16_t)TYPE_DATA);
+ 			}
+ 		}
+ 	} else {
+ 		if (eth_proto == ETHER_PROTOCOL_TYPE_EAP)
+-			pp->auth_type = cpu_to_le16((uint16_t) TYPE_AUTH);
++			pp->auth_type = cpu_to_le16((uint16_t)TYPE_AUTH);
+ 		else
+-			pp->auth_type = cpu_to_le16((uint16_t) TYPE_DATA);
++			pp->auth_type = cpu_to_le16((uint16_t)TYPE_DATA);
+ 	}
+ 
+ 	/* header value set */
+ 	pp->header.size =
+ 	    cpu_to_le16((uint16_t)
+ 			(sizeof(*pp) - sizeof(pp->header.size) + packet_len));
+-	pp->header.event = cpu_to_le16((uint16_t) HIF_DATA_REQ);
++	pp->header.event = cpu_to_le16((uint16_t)HIF_DATA_REQ);
+ 
+ 	/* tx request */
+ 	result =
+@@ -1291,9 +1290,9 @@ void hostif_mib_get_request(struct ks_wlan_private *priv,
+ 		return;
+ 	}
+ 	pp->header.size =
+-	    cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size)));
+-	pp->header.event = cpu_to_le16((uint16_t) HIF_MIB_GET_REQ);
+-	pp->mib_attribute = cpu_to_le32((uint32_t) mib_attribute);
++	    cpu_to_le16((uint16_t)(sizeof(*pp) - sizeof(pp->header.size)));
++	pp->header.event = cpu_to_le16((uint16_t)HIF_MIB_GET_REQ);
++	pp->mib_attribute = cpu_to_le32((uint32_t)mib_attribute);
+ 
+ 	/* send to device request */
+ 	ps_confirm_wait_inc(priv);
+@@ -1324,10 +1323,10 @@ void hostif_mib_set_request(struct ks_wlan_private *priv,
+ 	pp->header.size =
+ 	    cpu_to_le16((uint16_t)
+ 			(sizeof(*pp) - sizeof(pp->header.size) + size));
+-	pp->header.event = cpu_to_le16((uint16_t) HIF_MIB_SET_REQ);
+-	pp->mib_attribute = cpu_to_le32((uint32_t) mib_attribute);
+-	pp->mib_value.size = cpu_to_le16((uint16_t) size);
+-	pp->mib_value.type = cpu_to_le16((uint16_t) type);
++	pp->header.event = cpu_to_le16((uint16_t)HIF_MIB_SET_REQ);
++	pp->mib_attribute = cpu_to_le32((uint32_t)mib_attribute);
++	pp->mib_value.size = cpu_to_le16((uint16_t)size);
++	pp->mib_value.type = cpu_to_le16((uint16_t)type);
+ 	memcpy(&pp->mib_value.body, vp, size);
+ 
+ 	/* send to device request */
+@@ -1350,9 +1349,9 @@ void hostif_start_request(struct ks_wlan_private *priv, unsigned char mode)
+ 		return;
+ 	}
+ 	pp->header.size =
+-	    cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size)));
+-	pp->header.event = cpu_to_le16((uint16_t) HIF_START_REQ);
+-	pp->mode = cpu_to_le16((uint16_t) mode);
++	    cpu_to_le16((uint16_t)(sizeof(*pp) - sizeof(pp->header.size)));
++	pp->header.event = cpu_to_le16((uint16_t)HIF_START_REQ);
++	pp->mode = cpu_to_le16((uint16_t)mode);
+ 
+ 	/* send to device request */
+ 	ps_confirm_wait_inc(priv);
+@@ -1378,12 +1377,12 @@ void hostif_ps_adhoc_set_request(struct ks_wlan_private *priv)
+ 	}
+ 	memset(pp, 0, sizeof(*pp));
+ 	pp->header.size =
+-	    cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size)));
+-	pp->header.event = cpu_to_le16((uint16_t) HIF_PS_ADH_SET_REQ);
+-	pp->phy_type = cpu_to_le16((uint16_t) (priv->reg.phy_type));
+-	pp->cts_mode = cpu_to_le16((uint16_t) (priv->reg.cts_mode));
+-	pp->scan_type = cpu_to_le16((uint16_t) (priv->reg.scan_type));
+-	pp->channel = cpu_to_le16((uint16_t) (priv->reg.channel));
++	    cpu_to_le16((uint16_t)(sizeof(*pp) - sizeof(pp->header.size)));
++	pp->header.event = cpu_to_le16((uint16_t)HIF_PS_ADH_SET_REQ);
++	pp->phy_type = cpu_to_le16((uint16_t)(priv->reg.phy_type));
++	pp->cts_mode = cpu_to_le16((uint16_t)(priv->reg.cts_mode));
++	pp->scan_type = cpu_to_le16((uint16_t)(priv->reg.scan_type));
++	pp->channel = cpu_to_le16((uint16_t)(priv->reg.channel));
+ 	pp->rate_set.size = priv->reg.rate_set.size;
+ 	memcpy(&pp->rate_set.body[0], &priv->reg.rate_set.body[0],
+ 	       priv->reg.rate_set.size);
+@@ -1398,7 +1397,7 @@ void hostif_ps_adhoc_set_request(struct ks_wlan_private *priv)
+ 		capability |= BSS_CAP_SHORT_SLOT_TIME;	/* ShortSlotTime support */
+ 		capability &= ~(BSS_CAP_DSSS_OFDM);	/* DSSS OFDM */
+ 	}
+-	pp->capability = cpu_to_le16((uint16_t) capability);
++	pp->capability = cpu_to_le16((uint16_t)capability);
+ 
+ 	/* send to device request */
+ 	ps_confirm_wait_inc(priv);
+@@ -1420,11 +1419,11 @@ void hostif_infrastructure_set_request(struct ks_wlan_private *priv)
+ 		return;
+ 	}
+ 	pp->header.size =
+-	    cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size)));
+-	pp->header.event = cpu_to_le16((uint16_t) HIF_INFRA_SET_REQ);
+-	pp->phy_type = cpu_to_le16((uint16_t) (priv->reg.phy_type));
+-	pp->cts_mode = cpu_to_le16((uint16_t) (priv->reg.cts_mode));
+-	pp->scan_type = cpu_to_le16((uint16_t) (priv->reg.scan_type));
++	    cpu_to_le16((uint16_t)(sizeof(*pp) - sizeof(pp->header.size)));
++	pp->header.event = cpu_to_le16((uint16_t)HIF_INFRA_SET_REQ);
++	pp->phy_type = cpu_to_le16((uint16_t)(priv->reg.phy_type));
++	pp->cts_mode = cpu_to_le16((uint16_t)(priv->reg.cts_mode));
++	pp->scan_type = cpu_to_le16((uint16_t)(priv->reg.scan_type));
+ 
+ 	pp->rate_set.size = priv->reg.rate_set.size;
+ 	memcpy(&pp->rate_set.body[0], &priv->reg.rate_set.body[0],
+@@ -1442,10 +1441,10 @@ void hostif_infrastructure_set_request(struct ks_wlan_private *priv)
+ 		capability |= BSS_CAP_SHORT_SLOT_TIME;	/* ShortSlotTime support */
+ 		capability &= ~(BSS_CAP_DSSS_OFDM);	/* DSSS OFDM not support */
+ 	}
+-	pp->capability = cpu_to_le16((uint16_t) capability);
++	pp->capability = cpu_to_le16((uint16_t)capability);
+ 	pp->beacon_lost_count =
+-	    cpu_to_le16((uint16_t) (priv->reg.beacon_lost_count));
+-	pp->auth_type = cpu_to_le16((uint16_t) (priv->reg.authenticate_type));
++	    cpu_to_le16((uint16_t)(priv->reg.beacon_lost_count));
++	pp->auth_type = cpu_to_le16((uint16_t)(priv->reg.authenticate_type));
+ 
+ 	pp->channel_list.body[0] = 1;
+ 	pp->channel_list.body[1] = 8;
+@@ -1486,11 +1485,11 @@ static void hostif_infrastructure_set2_request(struct ks_wlan_private *priv)
+ 		return;
+ 	}
+ 	pp->header.size =
+-	    cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size)));
+-	pp->header.event = cpu_to_le16((uint16_t) HIF_INFRA_SET2_REQ);
+-	pp->phy_type = cpu_to_le16((uint16_t) (priv->reg.phy_type));
+-	pp->cts_mode = cpu_to_le16((uint16_t) (priv->reg.cts_mode));
+-	pp->scan_type = cpu_to_le16((uint16_t) (priv->reg.scan_type));
++	    cpu_to_le16((uint16_t)(sizeof(*pp) - sizeof(pp->header.size)));
++	pp->header.event = cpu_to_le16((uint16_t)HIF_INFRA_SET2_REQ);
++	pp->phy_type = cpu_to_le16((uint16_t)(priv->reg.phy_type));
++	pp->cts_mode = cpu_to_le16((uint16_t)(priv->reg.cts_mode));
++	pp->scan_type = cpu_to_le16((uint16_t)(priv->reg.scan_type));
+ 
+ 	pp->rate_set.size = priv->reg.rate_set.size;
+ 	memcpy(&pp->rate_set.body[0], &priv->reg.rate_set.body[0],
+@@ -1508,10 +1507,10 @@ static void hostif_infrastructure_set2_request(struct ks_wlan_private *priv)
+ 		capability |= BSS_CAP_SHORT_SLOT_TIME;	/* ShortSlotTime support */
+ 		capability &= ~(BSS_CAP_DSSS_OFDM);	/* DSSS OFDM not support */
+ 	}
+-	pp->capability = cpu_to_le16((uint16_t) capability);
++	pp->capability = cpu_to_le16((uint16_t)capability);
+ 	pp->beacon_lost_count =
+-	    cpu_to_le16((uint16_t) (priv->reg.beacon_lost_count));
+-	pp->auth_type = cpu_to_le16((uint16_t) (priv->reg.authenticate_type));
++	    cpu_to_le16((uint16_t)(priv->reg.beacon_lost_count));
++	pp->auth_type = cpu_to_le16((uint16_t)(priv->reg.authenticate_type));
+ 
+ 	pp->channel_list.body[0] = 1;
+ 	pp->channel_list.body[1] = 8;
+@@ -1556,12 +1555,12 @@ void hostif_adhoc_set_request(struct ks_wlan_private *priv)
+ 	}
+ 	memset(pp, 0, sizeof(*pp));
+ 	pp->header.size =
+-	    cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size)));
+-	pp->header.event = cpu_to_le16((uint16_t) HIF_ADH_SET_REQ);
+-	pp->phy_type = cpu_to_le16((uint16_t) (priv->reg.phy_type));
+-	pp->cts_mode = cpu_to_le16((uint16_t) (priv->reg.cts_mode));
+-	pp->scan_type = cpu_to_le16((uint16_t) (priv->reg.scan_type));
+-	pp->channel = cpu_to_le16((uint16_t) (priv->reg.channel));
++	    cpu_to_le16((uint16_t)(sizeof(*pp) - sizeof(pp->header.size)));
++	pp->header.event = cpu_to_le16((uint16_t)HIF_ADH_SET_REQ);
++	pp->phy_type = cpu_to_le16((uint16_t)(priv->reg.phy_type));
++	pp->cts_mode = cpu_to_le16((uint16_t)(priv->reg.cts_mode));
++	pp->scan_type = cpu_to_le16((uint16_t)(priv->reg.scan_type));
++	pp->channel = cpu_to_le16((uint16_t)(priv->reg.channel));
+ 	pp->rate_set.size = priv->reg.rate_set.size;
+ 	memcpy(&pp->rate_set.body[0], &priv->reg.rate_set.body[0],
+ 	       priv->reg.rate_set.size);
+@@ -1578,7 +1577,7 @@ void hostif_adhoc_set_request(struct ks_wlan_private *priv)
+ 		capability |= BSS_CAP_SHORT_SLOT_TIME;	/* ShortSlotTime support */
+ 		capability &= ~(BSS_CAP_DSSS_OFDM);	/* DSSS OFDM not support */
+ 	}
+-	pp->capability = cpu_to_le16((uint16_t) capability);
++	pp->capability = cpu_to_le16((uint16_t)capability);
+ 
+ 	/* send to device request */
+ 	ps_confirm_wait_inc(priv);
+@@ -1601,11 +1600,11 @@ void hostif_adhoc_set2_request(struct ks_wlan_private *priv)
+ 	}
+ 	memset(pp, 0, sizeof(*pp));
+ 	pp->header.size =
+-	    cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size)));
+-	pp->header.event = cpu_to_le16((uint16_t) HIF_ADH_SET_REQ);
+-	pp->phy_type = cpu_to_le16((uint16_t) (priv->reg.phy_type));
+-	pp->cts_mode = cpu_to_le16((uint16_t) (priv->reg.cts_mode));
+-	pp->scan_type = cpu_to_le16((uint16_t) (priv->reg.scan_type));
++	    cpu_to_le16((uint16_t)(sizeof(*pp) - sizeof(pp->header.size)));
++	pp->header.event = cpu_to_le16((uint16_t)HIF_ADH_SET_REQ);
++	pp->phy_type = cpu_to_le16((uint16_t)(priv->reg.phy_type));
++	pp->cts_mode = cpu_to_le16((uint16_t)(priv->reg.cts_mode));
++	pp->scan_type = cpu_to_le16((uint16_t)(priv->reg.scan_type));
+ 	pp->rate_set.size = priv->reg.rate_set.size;
+ 	memcpy(&pp->rate_set.body[0], &priv->reg.rate_set.body[0],
+ 	       priv->reg.rate_set.size);
+@@ -1622,7 +1621,7 @@ void hostif_adhoc_set2_request(struct ks_wlan_private *priv)
+ 		capability |= BSS_CAP_SHORT_SLOT_TIME;	/* ShortSlotTime support */
+ 		capability &= ~(BSS_CAP_DSSS_OFDM);	/* DSSS OFDM not support */
+ 	}
+-	pp->capability = cpu_to_le16((uint16_t) capability);
++	pp->capability = cpu_to_le16((uint16_t)capability);
+ 
+ 	pp->channel_list.body[0] = priv->reg.channel;
+ 	pp->channel_list.size = 1;
+@@ -1647,8 +1646,8 @@ void hostif_stop_request(struct ks_wlan_private *priv)
+ 		return;
+ 	}
+ 	pp->header.size =
+-	    cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size)));
+-	pp->header.event = cpu_to_le16((uint16_t) HIF_STOP_REQ);
++	    cpu_to_le16((uint16_t)(sizeof(*pp) - sizeof(pp->header.size)));
++	pp->header.event = cpu_to_le16((uint16_t)HIF_STOP_REQ);
+ 
+ 	/* send to device request */
+ 	ps_confirm_wait_inc(priv);
+@@ -1669,14 +1668,14 @@ void hostif_phy_information_request(struct ks_wlan_private *priv)
+ 		return;
+ 	}
+ 	pp->header.size =
+-	    cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size)));
+-	pp->header.event = cpu_to_le16((uint16_t) HIF_PHY_INFO_REQ);
++	    cpu_to_le16((uint16_t)(sizeof(*pp) - sizeof(pp->header.size)));
++	pp->header.event = cpu_to_le16((uint16_t)HIF_PHY_INFO_REQ);
+ 	if (priv->reg.phy_info_timer) {
+-		pp->type = cpu_to_le16((uint16_t) TIME_TYPE);
+-		pp->time = cpu_to_le16((uint16_t) (priv->reg.phy_info_timer));
++		pp->type = cpu_to_le16((uint16_t)TIME_TYPE);
++		pp->time = cpu_to_le16((uint16_t)(priv->reg.phy_info_timer));
+ 	} else {
+-		pp->type = cpu_to_le16((uint16_t) NORMAL_TYPE);
+-		pp->time = cpu_to_le16((uint16_t) 0);
++		pp->type = cpu_to_le16((uint16_t)NORMAL_TYPE);
++		pp->time = cpu_to_le16((uint16_t)0);
+ 	}
+ 
+ 	/* send to device request */
+@@ -1700,11 +1699,11 @@ void hostif_power_mngmt_request(struct ks_wlan_private *priv,
+ 		return;
+ 	}
+ 	pp->header.size =
+-	    cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size)));
+-	pp->header.event = cpu_to_le16((uint16_t) HIF_POWERMGT_REQ);
+-	pp->mode = cpu_to_le32((uint32_t) mode);
+-	pp->wake_up = cpu_to_le32((uint32_t) wake_up);
+-	pp->receiveDTIMs = cpu_to_le32((uint32_t) receiveDTIMs);
++	    cpu_to_le16((uint16_t)(sizeof(*pp) - sizeof(pp->header.size)));
++	pp->header.event = cpu_to_le16((uint16_t)HIF_POWERMGT_REQ);
++	pp->mode = cpu_to_le32((uint32_t)mode);
++	pp->wake_up = cpu_to_le32((uint32_t)wake_up);
++	pp->receiveDTIMs = cpu_to_le32((uint32_t)receiveDTIMs);
+ 
+ 	/* send to device request */
+ 	ps_confirm_wait_inc(priv);
+@@ -1726,9 +1725,8 @@ void hostif_sleep_request(struct ks_wlan_private *priv, unsigned long mode)
+ 			return;
+ 		}
+ 		pp->header.size =
+-		    cpu_to_le16((uint16_t)
+-				(sizeof(*pp) - sizeof(pp->header.size)));
+-		pp->header.event = cpu_to_le16((uint16_t) HIF_SLEEP_REQ);
++		    cpu_to_le16((uint16_t)(sizeof(*pp) - sizeof(pp->header.size)));
++		pp->header.event = cpu_to_le16((uint16_t)HIF_SLEEP_REQ);
+ 
+ 		/* send to device request */
+ 		ps_confirm_wait_inc(priv);
+@@ -1759,12 +1757,12 @@ void hostif_bss_scan_request(struct ks_wlan_private *priv,
+ 		return;
+ 	}
+ 	pp->header.size =
+-	    cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size)));
+-	pp->header.event = cpu_to_le16((uint16_t) HIF_SCAN_REQ);
++	    cpu_to_le16((uint16_t)(sizeof(*pp) - sizeof(pp->header.size)));
++	pp->header.event = cpu_to_le16((uint16_t)HIF_SCAN_REQ);
+ 	pp->scan_type = scan_type;
+ 
+-	pp->ch_time_min = cpu_to_le32((uint32_t) 110);	/* default value */
+-	pp->ch_time_max = cpu_to_le32((uint32_t) 130);	/* default value */
++	pp->ch_time_min = cpu_to_le32((uint32_t)110);	/* default value */
++	pp->ch_time_max = cpu_to_le32((uint32_t)130);	/* default value */
+ 	pp->channel_list.body[0] = 1;
+ 	pp->channel_list.body[1] = 8;
+ 	pp->channel_list.body[2] = 2;
+@@ -1815,10 +1813,10 @@ void hostif_mic_failure_request(struct ks_wlan_private *priv,
+ 		return;
+ 	}
+ 	pp->header.size =
+-	    cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size)));
+-	pp->header.event = cpu_to_le16((uint16_t) HIF_MIC_FAILURE_REQ);
+-	pp->failure_count = cpu_to_le16((uint16_t) failure_count);
+-	pp->timer = cpu_to_le16((uint16_t) timer);
++	    cpu_to_le16((uint16_t)(sizeof(*pp) - sizeof(pp->header.size)));
++	pp->header.event = cpu_to_le16((uint16_t)HIF_MIC_FAILURE_REQ);
++	pp->failure_count = cpu_to_le16((uint16_t)failure_count);
++	pp->timer = cpu_to_le16((uint16_t)timer);
+ 
+ 	/* send to device request */
+ 	ps_confirm_wait_inc(priv);
+@@ -1871,7 +1869,7 @@ void hostif_sme_set_wep(struct ks_wlan_private *priv, int type)
+ 
+ 	switch (type) {
+ 	case SME_WEP_INDEX_REQUEST:
+-		val = cpu_to_le32((uint32_t) (priv->reg.wep_index));
++		val = cpu_to_le32((uint32_t)(priv->reg.wep_index));
+ 		hostif_mib_set_request(priv, DOT11_WEP_DEFAULT_KEY_ID,
+ 				       sizeof(val), MIB_VALUE_TYPE_INT, &val);
+ 		break;
+@@ -1908,7 +1906,7 @@ void hostif_sme_set_wep(struct ks_wlan_private *priv, int type)
+ 					       &priv->reg.wep_key[3].val[0]);
+ 		break;
+ 	case SME_WEP_FLAG_REQUEST:
+-		val = cpu_to_le32((uint32_t) (priv->reg.privacy_invoked));
++		val = cpu_to_le32((uint32_t)(priv->reg.privacy_invoked));
+ 		hostif_mib_set_request(priv, DOT11_PRIVACY_INVOKED,
+ 				       sizeof(val), MIB_VALUE_TYPE_BOOL, &val);
+ 		break;
+@@ -1936,7 +1934,7 @@ void hostif_sme_set_rsn(struct ks_wlan_private *priv, int type)
+ 
+ 	switch (type) {
+ 	case SME_RSN_UCAST_REQUEST:
+-		wpa_suite.size = cpu_to_le16((uint16_t) 1);
++		wpa_suite.size = cpu_to_le16((uint16_t)1);
+ 		switch (priv->wpa.pairwise_suite) {
+ 		case IW_AUTH_CIPHER_NONE:
+ 			if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2)
+@@ -2034,7 +2032,7 @@ void hostif_sme_set_rsn(struct ks_wlan_private *priv, int type)
+ 				       &wpa_suite.suite[0][0]);
+ 		break;
+ 	case SME_RSN_AUTH_REQUEST:
+-		wpa_suite.size = cpu_to_le16((uint16_t) 1);
++		wpa_suite.size = cpu_to_le16((uint16_t)1);
+ 		switch (priv->wpa.key_mgmt_suite) {
+ 		case IW_AUTH_KEY_MGMT_802_1X:
+ 			if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2)
+@@ -2078,23 +2076,23 @@ void hostif_sme_set_rsn(struct ks_wlan_private *priv, int type)
+ 				       MIB_VALUE_TYPE_OSTRING, &wpa_suite);
+ 		break;
+ 	case SME_RSN_ENABLED_REQUEST:
+-		val = cpu_to_le32((uint32_t) (priv->wpa.rsn_enabled));
++		val = cpu_to_le32((uint32_t)(priv->wpa.rsn_enabled));
+ 		hostif_mib_set_request(priv, DOT11_RSN_ENABLED,
+ 				       sizeof(val), MIB_VALUE_TYPE_BOOL, &val);
+ 		break;
+ 	case SME_RSN_MODE_REQUEST:
+ 		if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) {
+ 			rsn_mode.rsn_mode =
+-			    cpu_to_le32((uint32_t) RSN_MODE_WPA2);
+-			rsn_mode.rsn_capability = cpu_to_le16((uint16_t) 0);
++			    cpu_to_le32((uint32_t)RSN_MODE_WPA2);
++			rsn_mode.rsn_capability = cpu_to_le16((uint16_t)0);
+ 		} else if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA) {
+ 			rsn_mode.rsn_mode =
+-			    cpu_to_le32((uint32_t) RSN_MODE_WPA);
+-			rsn_mode.rsn_capability = cpu_to_le16((uint16_t) 0);
++			    cpu_to_le32((uint32_t)RSN_MODE_WPA);
++			rsn_mode.rsn_capability = cpu_to_le16((uint16_t)0);
+ 		} else {
+ 			rsn_mode.rsn_mode =
+-			    cpu_to_le32((uint32_t) RSN_MODE_NONE);
+-			rsn_mode.rsn_capability = cpu_to_le16((uint16_t) 0);
++			    cpu_to_le32((uint32_t)RSN_MODE_NONE);
++			rsn_mode.rsn_capability = cpu_to_le16((uint16_t)0);
+ 		}
+ 		hostif_mib_set_request(priv, LOCAL_RSN_MODE, sizeof(rsn_mode),
+ 				       MIB_VALUE_TYPE_OSTRING, &rsn_mode);
+@@ -2187,7 +2185,7 @@ void hostif_sme_mode_setup(struct ks_wlan_private *priv)
+ 		break;
+ 	case MODE_INFRASTRUCTURE:
+ 		/* Infrastructure mode */
+-		if (!is_valid_ether_addr((u8 *) priv->reg.bssid)) {
++		if (!is_valid_ether_addr((u8 *)priv->reg.bssid)) {
+ 			hostif_infrastructure_set_request(priv);
+ 		} else {
+ 			hostif_infrastructure_set2_request(priv);
+@@ -2197,7 +2195,7 @@ void hostif_sme_mode_setup(struct ks_wlan_private *priv)
+ 		break;
+ 	case MODE_ADHOC:
+ 		/* IEEE802.11 Ad-Hoc mode */
+-		if (!is_valid_ether_addr((u8 *) priv->reg.bssid)) {
++		if (!is_valid_ether_addr((u8 *)priv->reg.bssid)) {
+ 			hostif_adhoc_set_request(priv);
+ 		} else {
+ 			hostif_adhoc_set2_request(priv);
+@@ -2227,13 +2225,13 @@ void hostif_sme_multicast_set(struct ks_wlan_private *priv)
+ 	memset(set_address, 0, NIC_MAX_MCAST_LIST * ETH_ALEN);
+ 
+ 	if (dev->flags & IFF_PROMISC) {
+-		filter_type = cpu_to_le32((uint32_t) MCAST_FILTER_PROMISC);
++		filter_type = cpu_to_le32((uint32_t)MCAST_FILTER_PROMISC);
+ 		hostif_mib_set_request(priv, LOCAL_MULTICAST_FILTER,
+ 				       sizeof(filter_type), MIB_VALUE_TYPE_BOOL,
+ 				       &filter_type);
+ 	} else if ((netdev_mc_count(dev) > NIC_MAX_MCAST_LIST)
+ 		   || (dev->flags & IFF_ALLMULTI)) {
+-		filter_type = cpu_to_le32((uint32_t) MCAST_FILTER_MCASTALL);
++		filter_type = cpu_to_le32((uint32_t)MCAST_FILTER_MCASTALL);
+ 		hostif_mib_set_request(priv, LOCAL_MULTICAST_FILTER,
+ 				       sizeof(filter_type), MIB_VALUE_TYPE_BOOL,
+ 				       &filter_type);
+@@ -2252,7 +2250,7 @@ void hostif_sme_multicast_set(struct ks_wlan_private *priv)
+ 					       &set_address[0]);
+ 		} else {
+ 			filter_type =
+-			    cpu_to_le32((uint32_t) MCAST_FILTER_MCAST);
++			    cpu_to_le32((uint32_t)MCAST_FILTER_MCAST);
+ 			priv->sme_i.sme_flag |= SME_MULTICAST;
+ 			hostif_mib_set_request(priv, LOCAL_MULTICAST_FILTER,
+ 					       sizeof(filter_type),
+@@ -2330,12 +2328,12 @@ void hostif_sme_set_key(struct ks_wlan_private *priv, int type)
+ 
+ 	switch (type) {
+ 	case SME_SET_FLAG:
+-		val = cpu_to_le32((uint32_t) (priv->reg.privacy_invoked));
++		val = cpu_to_le32((uint32_t)(priv->reg.privacy_invoked));
+ 		hostif_mib_set_request(priv, DOT11_PRIVACY_INVOKED,
+ 				       sizeof(val), MIB_VALUE_TYPE_BOOL, &val);
+ 		break;
+ 	case SME_SET_TXKEY:
+-		val = cpu_to_le32((uint32_t) (priv->wpa.txkey));
++		val = cpu_to_le32((uint32_t)(priv->wpa.txkey));
+ 		hostif_mib_set_request(priv, DOT11_WEP_DEFAULT_KEY_ID,
+ 				       sizeof(val), MIB_VALUE_TYPE_INT, &val);
+ 		break;
+@@ -2404,7 +2402,7 @@ void hostif_sme_set_pmksa(struct ks_wlan_private *priv)
+ 			i++;
+ 		}
+ 	}
+-	pmkcache.size = cpu_to_le16((uint16_t) (priv->pmklist.size));
++	pmkcache.size = cpu_to_le16((uint16_t)(priv->pmklist.size));
+ 	hostif_mib_set_request(priv, LOCAL_PMK,
+ 			       sizeof(priv->pmklist.size) + (ETH_ALEN +
+ 							     IW_PMKID_LEN) *
+@@ -2478,12 +2476,12 @@ void hostif_sme_execute(struct ks_wlan_private *priv, int event)
+ 		hostif_stop_request(priv);
+ 		break;
+ 	case SME_RTS_THRESHOLD_REQUEST:
+-		val = cpu_to_le32((uint32_t) (priv->reg.rts));
++		val = cpu_to_le32((uint32_t)(priv->reg.rts));
+ 		hostif_mib_set_request(priv, DOT11_RTS_THRESHOLD,
+ 				       sizeof(val), MIB_VALUE_TYPE_INT, &val);
+ 		break;
+ 	case SME_FRAGMENTATION_THRESHOLD_REQUEST:
+-		val = cpu_to_le32((uint32_t) (priv->reg.fragment));
++		val = cpu_to_le32((uint32_t)(priv->reg.fragment));
+ 		hostif_mib_set_request(priv, DOT11_FRAGMENTATION_THRESHOLD,
+ 				       sizeof(val), MIB_VALUE_TYPE_INT, &val);
+ 		break;
+@@ -2560,7 +2558,7 @@ void hostif_sme_execute(struct ks_wlan_private *priv, int event)
+ 		hostif_sme_sleep_set(priv);
+ 		break;
+ 	case SME_SET_REGION:
+-		val = cpu_to_le32((uint32_t) (priv->region));
++		val = cpu_to_le32((uint32_t)(priv->region));
+ 		hostif_mib_set_request(priv, LOCAL_REGION,
+ 				       sizeof(val), MIB_VALUE_TYPE_INT, &val);
+ 		break;

commit a8ba84626b1b33ff53c4adaff9b69304eb41877f
+Author: Katie Dunne 
+Date:   Mon Feb 20 12:24:40 2017 -0800
+
+    staging: xgifb: add braces around if-statements
+    
+    Add braces to instances of if-statements found by checkpatch.pl
+    to conform to kernel style.
+    
+    Signed-off-by: Katie Dunne 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
+index 68952358933c..69ed137337ce 100644
+--- a/drivers/staging/xgifb/XGI_main_26.c
++++ b/drivers/staging/xgifb/XGI_main_26.c
+@@ -1480,9 +1480,9 @@ static void XGIfb_detect_VB(struct xgifb_video_info *xgifb_info)
+ 
+ 	cr32 = xgifb_reg_get(XGICR, IND_XGI_SCRATCH_REG_CR32);
+ 
+-	if ((cr32 & SIS_CRT1) && !XGIfb_crt1off)
++	if ((cr32 & SIS_CRT1) && !XGIfb_crt1off) {
+ 		XGIfb_crt1off = 0;
+-	else {
++	} else {
+ 		if (cr32 & 0x5F)
+ 			XGIfb_crt1off = 1;
+ 		else
+@@ -1500,18 +1500,19 @@ static void XGIfb_detect_VB(struct xgifb_video_info *xgifb_info)
+ 			xgifb_info->display2 = XGIFB_DISP_NONE;
+ 	}
+ 
+-	if (XGIfb_tvplug != -1)
++	if (XGIfb_tvplug != -1) {
+ 		/* Override with option */
+ 		xgifb_info->TV_plug = XGIfb_tvplug;
+-	else if (cr32 & SIS_VB_HIVISION) {
++	} else if (cr32 & SIS_VB_HIVISION) {
+ 		xgifb_info->TV_type = TVMODE_HIVISION;
+ 		xgifb_info->TV_plug = TVPLUG_SVIDEO;
+-	} else if (cr32 & SIS_VB_SVIDEO)
++	} else if (cr32 & SIS_VB_SVIDEO) {
+ 		xgifb_info->TV_plug = TVPLUG_SVIDEO;
+-	else if (cr32 & SIS_VB_COMPOSITE)
++	} else if (cr32 & SIS_VB_COMPOSITE) {
+ 		xgifb_info->TV_plug = TVPLUG_COMPOSITE;
+-	else if (cr32 & SIS_VB_SCART)
++	} else if (cr32 & SIS_VB_SCART) {
+ 		xgifb_info->TV_plug = TVPLUG_SCART;
++	}
+ 
+ 	if (xgifb_info->TV_type == 0) {
+ 		temp = xgifb_reg_get(XGICR, 0x38);

commit 0f0c106aa95243c5e59f06fb447ed7ea89818be1
+Author: Katie Dunne 
+Date:   Fri Mar 3 07:38:37 2017 -0800
+
+    staging: iio: meter: ade7753: Clean up includes
+    
+    Alphabetize header files.
+    
+    Signed-off-by: Katie Dunne 
+    Signed-off-by: Jonathan Cameron 
+
+diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c
+index 063ff2789b71..dfd8b71d6a41 100644
+--- a/drivers/staging/iio/meter/ade7753.c
++++ b/drivers/staging/iio/meter/ade7753.c
+@@ -6,20 +6,19 @@
+  * Licensed under the GPL-2 or later.
+  */
+ 
+-#include 
+-#include 
+ #include 
+-#include 
+ #include 
++#include 
++#include 
+ #include 
+-#include 
+-#include 
+-#include 
+ #include 
+ #include 
+-
++#include 
++#include 
++#include 
+ #include 
+ #include 
++#include 
+ #include "meter.h"
+ 
+ #define ADE7753_WAVEFORM   0x01

commit 63a98d2511e2d2fb6fb305c0093ad8a066c43d08
+Author: Katie Dunne 
+Date:   Fri Mar 3 07:35:52 2017 -0800
+
+    staging: iio: meter: ade7753: Move header content to implementation file
+    
+    The contents of ade7753.h are only used in ade7753.c. Move the header
+    contents to the implementation file and delete the header file.
+    
+    Signed-off-by: Katie Dunne 
+    Signed-off-by: Jonathan Cameron 
+
+diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c
+index 671dc9971610..063ff2789b71 100644
+--- a/drivers/staging/iio/meter/ade7753.c
++++ b/drivers/staging/iio/meter/ade7753.c
+@@ -21,7 +21,74 @@
+ #include 
+ #include 
+ #include "meter.h"
+-#include "ade7753.h"
++
++#define ADE7753_WAVEFORM   0x01
++#define ADE7753_AENERGY    0x02
++#define ADE7753_RAENERGY   0x03
++#define ADE7753_LAENERGY   0x04
++#define ADE7753_VAENERGY   0x05
++#define ADE7753_RVAENERGY  0x06
++#define ADE7753_LVAENERGY  0x07
++#define ADE7753_LVARENERGY 0x08
++#define ADE7753_MODE       0x09
++#define ADE7753_IRQEN      0x0A
++#define ADE7753_STATUS     0x0B
++#define ADE7753_RSTSTATUS  0x0C
++#define ADE7753_CH1OS      0x0D
++#define ADE7753_CH2OS      0x0E
++#define ADE7753_GAIN       0x0F
++#define ADE7753_PHCAL      0x10
++#define ADE7753_APOS       0x11
++#define ADE7753_WGAIN      0x12
++#define ADE7753_WDIV       0x13
++#define ADE7753_CFNUM      0x14
++#define ADE7753_CFDEN      0x15
++#define ADE7753_IRMS       0x16
++#define ADE7753_VRMS       0x17
++#define ADE7753_IRMSOS     0x18
++#define ADE7753_VRMSOS     0x19
++#define ADE7753_VAGAIN     0x1A
++#define ADE7753_VADIV      0x1B
++#define ADE7753_LINECYC    0x1C
++#define ADE7753_ZXTOUT     0x1D
++#define ADE7753_SAGCYC     0x1E
++#define ADE7753_SAGLVL     0x1F
++#define ADE7753_IPKLVL     0x20
++#define ADE7753_VPKLVL     0x21
++#define ADE7753_IPEAK      0x22
++#define ADE7753_RSTIPEAK   0x23
++#define ADE7753_VPEAK      0x24
++#define ADE7753_RSTVPEAK   0x25
++#define ADE7753_TEMP       0x26
++#define ADE7753_PERIOD     0x27
++#define ADE7753_TMODE      0x3D
++#define ADE7753_CHKSUM     0x3E
++#define ADE7753_DIEREV     0x3F
++
++#define ADE7753_READ_REG(a)    a
++#define ADE7753_WRITE_REG(a) ((a) | 0x80)
++
++#define ADE7753_MAX_TX    4
++#define ADE7753_MAX_RX    4
++#define ADE7753_STARTUP_DELAY 1000
++
++#define ADE7753_SPI_SLOW    (u32)(300 * 1000)
++#define ADE7753_SPI_BURST   (u32)(1000 * 1000)
++#define ADE7753_SPI_FAST    (u32)(2000 * 1000)
++
++/**
++ * struct ade7753_state - device instance specific data
++ * @us:         actual spi_device
++ * @tx:         transmit buffer
++ * @rx:         receive buffer
++ * @buf_lock:       mutex to protect tx and rx
++ **/
++struct ade7753_state {
++	    struct spi_device   *us;
++		    struct mutex        buf_lock;
++			    u8          tx[ADE7753_MAX_TX] ____cacheline_aligned;
++				    u8          rx[ADE7753_MAX_RX];
++};
+ 
+ static int ade7753_spi_write_reg_8(struct device *dev,
+ 				   u8 reg_address,
+diff --git a/drivers/staging/iio/meter/ade7753.h b/drivers/staging/iio/meter/ade7753.h
+deleted file mode 100644
+index bfe749156bce..000000000000
+--- a/drivers/staging/iio/meter/ade7753.h
++++ /dev/null
+@@ -1,72 +0,0 @@
+-#ifndef _ADE7753_H
+-#define _ADE7753_H
+-
+-#define ADE7753_WAVEFORM   0x01
+-#define ADE7753_AENERGY    0x02
+-#define ADE7753_RAENERGY   0x03
+-#define ADE7753_LAENERGY   0x04
+-#define ADE7753_VAENERGY   0x05
+-#define ADE7753_RVAENERGY  0x06
+-#define ADE7753_LVAENERGY  0x07
+-#define ADE7753_LVARENERGY 0x08
+-#define ADE7753_MODE       0x09
+-#define ADE7753_IRQEN      0x0A
+-#define ADE7753_STATUS     0x0B
+-#define ADE7753_RSTSTATUS  0x0C
+-#define ADE7753_CH1OS      0x0D
+-#define ADE7753_CH2OS      0x0E
+-#define ADE7753_GAIN       0x0F
+-#define ADE7753_PHCAL      0x10
+-#define ADE7753_APOS       0x11
+-#define ADE7753_WGAIN      0x12
+-#define ADE7753_WDIV       0x13
+-#define ADE7753_CFNUM      0x14
+-#define ADE7753_CFDEN      0x15
+-#define ADE7753_IRMS       0x16
+-#define ADE7753_VRMS       0x17
+-#define ADE7753_IRMSOS     0x18
+-#define ADE7753_VRMSOS     0x19
+-#define ADE7753_VAGAIN     0x1A
+-#define ADE7753_VADIV      0x1B
+-#define ADE7753_LINECYC    0x1C
+-#define ADE7753_ZXTOUT     0x1D
+-#define ADE7753_SAGCYC     0x1E
+-#define ADE7753_SAGLVL     0x1F
+-#define ADE7753_IPKLVL     0x20
+-#define ADE7753_VPKLVL     0x21
+-#define ADE7753_IPEAK      0x22
+-#define ADE7753_RSTIPEAK   0x23
+-#define ADE7753_VPEAK      0x24
+-#define ADE7753_RSTVPEAK   0x25
+-#define ADE7753_TEMP       0x26
+-#define ADE7753_PERIOD     0x27
+-#define ADE7753_TMODE      0x3D
+-#define ADE7753_CHKSUM     0x3E
+-#define ADE7753_DIEREV     0x3F
+-
+-#define ADE7753_READ_REG(a)    a
+-#define ADE7753_WRITE_REG(a) ((a) | 0x80)
+-
+-#define ADE7753_MAX_TX    4
+-#define ADE7753_MAX_RX    4
+-#define ADE7753_STARTUP_DELAY 1000
+-
+-#define ADE7753_SPI_SLOW	(u32)(300 * 1000)
+-#define ADE7753_SPI_BURST	(u32)(1000 * 1000)
+-#define ADE7753_SPI_FAST	(u32)(2000 * 1000)
+-
+-/**
+- * struct ade7753_state - device instance specific data
+- * @us:			actual spi_device
+- * @tx:			transmit buffer
+- * @rx:			receive buffer
+- * @buf_lock:		mutex to protect tx and rx
+- **/
+-struct ade7753_state {
+-	struct spi_device	*us;
+-	struct mutex		buf_lock;
+-	u8			tx[ADE7753_MAX_TX] ____cacheline_aligned;
+-	u8			rx[ADE7753_MAX_RX];
+-};
+-
+-#endif

commit 3adc4aae0e597a7cdcb9ed3f99d0933bf9a4aaa6
+Author: Katie Dunne 
+Date:   Wed Sep 21 15:13:20 2016 -0700
+
+    staging: speakup: Remove unnecessary parentheses
+    
+    Issue found by checkpatch.
+    
+    Signed-off-by: Katie Dunne 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/speakup/synth.c b/drivers/staging/speakup/synth.c
+index 810a21408715..54b2f3918628 100644
+--- a/drivers/staging/speakup/synth.c
++++ b/drivers/staging/speakup/synth.c
+@@ -407,7 +407,7 @@ static int do_synth_init(struct spk_synth *in_synth)
+ 	if (!spk_quiet_boot)
+ 		synth_printf("%s found\n", synth->long_name);
+ 	if (synth->attributes.name
+-	&& sysfs_create_group(speakup_kobj, &(synth->attributes)) < 0)
++	&& sysfs_create_group(speakup_kobj, &synth->attributes) < 0)
+ 		return -ENOMEM;
+ 	synth_flags = synth->flags;
+ 	wake_up_interruptible_all(&speakup_event);
+@@ -429,7 +429,7 @@ void synth_release(void)
+ 	del_timer(&thread_timer);
+ 	spin_unlock_irqrestore(&speakup_info.spinlock, flags);
+ 	if (synth->attributes.name)
+-		sysfs_remove_group(speakup_kobj, &(synth->attributes));
++		sysfs_remove_group(speakup_kobj, &synth->attributes);
+ 	for (var = synth->vars; var->var_id != MAXVARS; var++)
+ 		speakup_unregister_var(var->var_id);
+ 	spk_stop_serial_interrupt();

commit a8886770dcf27082fe0fa64592e0054d02cea90d
+Author: Katie Dunne 
+Date:   Wed Sep 14 10:18:28 2016 -0700
+
+    staging: iio: ad5933: align arguments on new line with open parenthesis
+    
+    Issue found by checkpatch: "Alignment should match open parenthesis."
+    Multiple lines are also reduced to a single line where possible.
+    
+    Signed-off-by: Katie Dunne 
+    Signed-off-by: Jonathan Cameron 
+
+diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c
+index 24c348d2f5bb..5eecf1cb1028 100644
+--- a/drivers/staging/iio/impedance-analyzer/ad5933.c
++++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
+@@ -156,8 +156,7 @@ static const struct iio_chan_spec ad5933_channels[] = {
+ 	},
+ };
+ 
+-static int ad5933_i2c_write(struct i2c_client *client,
+-			      u8 reg, u8 len, u8 *data)
++static int ad5933_i2c_write(struct i2c_client *client, u8 reg, u8 len, u8 *data)
+ {
+ 	int ret;
+ 
+@@ -171,8 +170,7 @@ static int ad5933_i2c_write(struct i2c_client *client,
+ 	return 0;
+ }
+ 
+-static int ad5933_i2c_read(struct i2c_client *client,
+-			      u8 reg, u8 len, u8 *data)
++static int ad5933_i2c_read(struct i2c_client *client, u8 reg, u8 len, u8 *data)
+ {
+ 	int ret;
+ 
+@@ -269,7 +267,8 @@ static int ad5933_setup(struct ad5933_state *st)
+ 	dat = cpu_to_be16(st->settling_cycles);
+ 
+ 	ret = ad5933_i2c_write(st->client,
+-			AD5933_REG_SETTLING_CYCLES, 2, (u8 *)&dat);
++			       AD5933_REG_SETTLING_CYCLES,
++			       2, (u8 *)&dat);
+ 	if (ret < 0)
+ 		return ret;
+ 
+@@ -294,8 +293,8 @@ static void ad5933_calc_out_ranges(struct ad5933_state *st)
+  */
+ 
+ static ssize_t ad5933_show_frequency(struct device *dev,
+-					struct device_attribute *attr,
+-					char *buf)
++				     struct device_attribute *attr,
++				     char *buf)
+ {
+ 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ 	struct ad5933_state *st = iio_priv(indio_dev);
+@@ -322,9 +321,9 @@ static ssize_t ad5933_show_frequency(struct device *dev,
+ }
+ 
+ static ssize_t ad5933_store_frequency(struct device *dev,
+-					 struct device_attribute *attr,
+-					 const char *buf,
+-					 size_t len)
++				      struct device_attribute *attr,
++				      const char *buf,
++				      size_t len)
+ {
+ 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ 	struct ad5933_state *st = iio_priv(indio_dev);
+@@ -357,8 +356,8 @@ static IIO_DEVICE_ATTR(out_voltage0_freq_increment, S_IRUGO | S_IWUSR,
+ 			AD5933_REG_FREQ_INC);
+ 
+ static ssize_t ad5933_show(struct device *dev,
+-					struct device_attribute *attr,
+-					char *buf)
++			   struct device_attribute *attr,
++			   char *buf)
+ {
+ 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ 	struct ad5933_state *st = iio_priv(indio_dev);
+@@ -399,9 +398,9 @@ static ssize_t ad5933_show(struct device *dev,
+ }
+ 
+ static ssize_t ad5933_store(struct device *dev,
+-					 struct device_attribute *attr,
+-					 const char *buf,
+-					 size_t len)
++			    struct device_attribute *attr,
++			    const char *buf,
++			    size_t len)
+ {
+ 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ 	struct ad5933_state *st = iio_priv(indio_dev);
+@@ -451,7 +450,8 @@ static ssize_t ad5933_store(struct device *dev,
+ 
+ 		dat = cpu_to_be16(val);
+ 		ret = ad5933_i2c_write(st->client,
+-				AD5933_REG_SETTLING_CYCLES, 2, (u8 *)&dat);
++				       AD5933_REG_SETTLING_CYCLES,
++				       2, (u8 *)&dat);
+ 		break;
+ 	case AD5933_FREQ_POINTS:
+ 		val = clamp(val, (u16)0, (u16)511);
+@@ -545,8 +545,8 @@ static int ad5933_read_raw(struct iio_dev *indio_dev,
+ 			goto out;
+ 
+ 		ret = ad5933_i2c_read(st->client,
+-				AD5933_REG_TEMP_DATA, 2,
+-				(u8 *)&dat);
++				      AD5933_REG_TEMP_DATA,
++				      2, (u8 *)&dat);
+ 		if (ret < 0)
+ 			goto out;
+ 		mutex_unlock(&indio_dev->mlock);
+@@ -705,7 +705,7 @@ static void ad5933_work(struct work_struct *work)
+ }
+ 
+ static int ad5933_probe(struct i2c_client *client,
+-				   const struct i2c_device_id *id)
++			const struct i2c_device_id *id)
+ {
+ 	int ret, voltage_uv = 0;
+ 	struct ad5933_platform_data *pdata = dev_get_platdata(&client->dev);

commit 13d932f79cea6b59b9a18a54c2e776d88799654d
+Author: Katie Dunne 
+Date:   Thu Feb 26 18:42:36 2015 -0800
+
+    Staging: speakup: Remove 'extern' keywords from .h prototypes
+    
+    Addresses checkpatch.pl check:
+    CHECK: Extern prototypes should be avoided in .h files
+    
+    Removes the 'extern' keyword from function prototypes
+    
+    Signed-off-by: Katie Dunne 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/speakup/spk_priv.h b/drivers/staging/speakup/spk_priv.h
+index 637ba6760ec0..1ef3795b865d 100644
+--- a/drivers/staging/speakup/spk_priv.h
++++ b/drivers/staging/speakup/spk_priv.h
+@@ -44,34 +44,34 @@
+ 
+ #define KT_SPKUP 15
+ 
+-extern const struct old_serial_port *spk_serial_init(int index);
+-extern void spk_stop_serial_interrupt(void);
+-extern int spk_wait_for_xmitr(void);
+-extern unsigned char spk_serial_in(void);
+-extern unsigned char spk_serial_in_nowait(void);
+-extern int spk_serial_out(const char ch);
+-extern void spk_serial_release(void);
++const struct old_serial_port *spk_serial_init(int index);
++void spk_stop_serial_interrupt(void);
++int spk_wait_for_xmitr(void);
++unsigned char spk_serial_in(void);
++unsigned char spk_serial_in_nowait(void);
++int spk_serial_out(const char ch);
++void spk_serial_release(void);
+ 
+-extern char synth_buffer_getc(void);
+-extern char synth_buffer_peek(void);
+-extern int synth_buffer_empty(void);
+-extern struct var_t *spk_get_var(enum var_id_t var_id);
+-extern ssize_t spk_var_show(struct kobject *kobj, struct kobj_attribute *attr,
+-	char *buf);
+-extern ssize_t spk_var_store(struct kobject *kobj, struct kobj_attribute *attr,
+-	const char *buf, size_t count);
++char synth_buffer_getc(void);
++char synth_buffer_peek(void);
++int synth_buffer_empty(void);
++struct var_t *spk_get_var(enum var_id_t var_id);
++ssize_t spk_var_show(struct kobject *kobj, struct kobj_attribute *attr,
++		     char *buf);
++ssize_t spk_var_store(struct kobject *kobj, struct kobj_attribute *attr,
++		      const char *buf, size_t count);
+ 
+-extern int spk_serial_synth_probe(struct spk_synth *synth);
+-extern const char *spk_synth_immediate(struct spk_synth *synth, const char *buff);
+-extern void spk_do_catch_up(struct spk_synth *synth);
+-extern void spk_synth_flush(struct spk_synth *synth);
+-extern int spk_synth_is_alive_nop(struct spk_synth *synth);
+-extern int spk_synth_is_alive_restart(struct spk_synth *synth);
+-extern void synth_printf(const char *buf, ...);
+-extern int synth_request_region(u_long, u_long);
+-extern int synth_release_region(u_long, u_long);
+-extern int synth_add(struct spk_synth *in_synth);
+-extern void synth_remove(struct spk_synth *in_synth);
++int spk_serial_synth_probe(struct spk_synth *synth);
++const char *spk_synth_immediate(struct spk_synth *synth, const char *buff);
++void spk_do_catch_up(struct spk_synth *synth);
++void spk_synth_flush(struct spk_synth *synth);
++int spk_synth_is_alive_nop(struct spk_synth *synth);
++int spk_synth_is_alive_restart(struct spk_synth *synth);
++void synth_printf(const char *buf, ...);
++int synth_request_region(u_long, u_long);
++int synth_release_region(u_long, u_long);
++int synth_add(struct spk_synth *in_synth);
++void synth_remove(struct spk_synth *in_synth);
+ 
+ extern struct speakup_info_t speakup_info;
+ 

commit a6c6e298170e5fad9a759abf305eadcf5780b658
+Author: Katie Dunne 
+Date:   Wed Feb 25 07:40:37 2015 -0800
+
+    Staging: rtl8712: Remove unused macros
+    
+    Removes several macro definitions that are unused
+    Patch 2 will remove the same definitions in rtl8188eu/include/wifi.h
+    
+    Signed-off-by: Katie Dunne 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8712/wifi.h b/drivers/staging/rtl8712/wifi.h
+index 73d7cd280607..6b1e1fa59cbd 100644
+--- a/drivers/staging/rtl8712/wifi.h
++++ b/drivers/staging/rtl8712/wifi.h
+@@ -235,11 +235,6 @@ enum WIFI_REG_DOMAIN {
+ #define GetPrivacy(pbuf)	(((*(unsigned short *)(pbuf)) & \
+ 				le16_to_cpu(_PRIVACY_)) != 0)
+ 
+-#define ClearPrivacy(pbuf) ({ \
+-	*(unsigned short *)(pbuf) &= (~cpu_to_le16(_PRIVACY_)); \
+-})
+-
+-
+ #define GetOrder(pbuf)	(((*(unsigned short *)(pbuf)) & \
+ 			le16_to_cpu(_ORDER_)) != 0)
+ 
+@@ -270,16 +265,6 @@ enum WIFI_REG_DOMAIN {
+ #define GetFragNum(pbuf)	(cpu_to_le16(*(unsigned short *)((addr_t)\
+ 				(pbuf) + 22)) & 0x0f)
+ 
+-#define GetTupleCache(pbuf)	(cpu_to_le16(*(unsigned short *)\
+-				((addr_t)(pbuf) + 22)))
+-
+-#define SetFragNum(pbuf, num) ({ \
+-	*(unsigned short *)((addr_t)(pbuf) + 22) = \
+-	((*(unsigned short *)((addr_t)(pbuf) + 22)) & \
+-	le16_to_cpu(~(0x000f))) | \
+-	cpu_to_le16(0x0f & (num));     \
+-})
+-
+ #define SetSeqNum(pbuf, num) ({ \
+ 	*(unsigned short *)((addr_t)(pbuf) + 22) = \
+ 	((*(unsigned short *)((addr_t)(pbuf) + 22)) & \
+@@ -306,17 +291,9 @@ enum WIFI_REG_DOMAIN {
+ 
+ #define GetAMsdu(pbuf) (((le16_to_cpu(*(unsigned short *)pbuf)) >> 7) & 0x1)
+ 
+-#define SetAMsdu(pbuf, amsdu) ({ \
+-	*(unsigned short *)(pbuf) |= cpu_to_le16((amsdu & 1) << 7); \
+-})
+-
+ #define GetAid(pbuf)	(cpu_to_le16(*(unsigned short *)((addr_t)(pbuf) + 2)) \
+ 			& 0x3fff)
+ 
+-#define GetTid(pbuf)	(cpu_to_le16(*(unsigned short *)((addr_t)(pbuf) + \
+-			(((GetToDs(pbuf) << 1)|GetFrDs(pbuf)) == 3 ? \
+-			30 : 24))) & 0x000f)
+-
+ #define GetAddr1Ptr(pbuf)	((unsigned char *)((addr_t)(pbuf) + 4))
+ 
+ #define GetAddr2Ptr(pbuf)	((unsigned char *)((addr_t)(pbuf) + 10))

commit 0ed83e995e17f8ef5688a7a597943a9ef88362c3
+Author: Katie Dunne 
+Date:   Wed Feb 25 07:41:14 2015 -0800
+
+    Staging: rtl8188eu: Remove unused macros
+    
+    Removes macro definitions that are unused elsewhere
+    
+    Signed-off-by: Katie Dunne 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8188eu/include/wifi.h b/drivers/staging/rtl8188eu/include/wifi.h
+index 8dbdfafd52b5..a68b52208192 100644
+--- a/drivers/staging/rtl8188eu/include/wifi.h
++++ b/drivers/staging/rtl8188eu/include/wifi.h
+@@ -301,22 +301,12 @@ enum WIFI_REG_DOMAIN {
+ #define GetPrivacy(pbuf)					\
+ 	(((*(__le16 *)(pbuf)) & cpu_to_le16(_PRIVACY_)) != 0)
+ 
+-#define ClearPrivacy(pbuf)	\
+-	*(__le16 *)(pbuf) &= (~cpu_to_le16(_PRIVACY_))
+-
+-
+ #define GetOrder(pbuf)					\
+ 	(((*(__le16 *)(pbuf)) & cpu_to_le16(_ORDER_)) != 0)
+ 
+ #define GetFrameType(pbuf)				\
+ 	(le16_to_cpu(*(__le16 *)(pbuf)) & (BIT(3) | BIT(2)))
+ 
+-#define SetFrameType(pbuf, type)	\
+-	do {	\
+-		*(unsigned short *)(pbuf) &= __constant_cpu_to_le16(~(BIT(3) | BIT(2))); \
+-		*(unsigned short *)(pbuf) |= __constant_cpu_to_le16(type); \
+-	} while (0)
+-
+ #define GetFrameSubType(pbuf)	(le16_to_cpu(*(__le16 *)(pbuf)) & (BIT(7) |\
+ 	 BIT(6) | BIT(5) | BIT(4) | BIT(3) | BIT(2)))
+ 
+@@ -333,17 +323,6 @@ enum WIFI_REG_DOMAIN {
+ #define GetFragNum(pbuf)			\
+ 	(le16_to_cpu(*(__le16 *)((size_t)(pbuf) + 22)) & 0x0f)
+ 
+-#define GetTupleCache(pbuf)			\
+-	(cpu_to_le16(*(unsigned short *)((size_t)(pbuf) + 22)))
+-
+-#define SetFragNum(pbuf, num) \
+-	do {    \
+-		*(unsigned short *)((size_t)(pbuf) + 22) = \
+-			((*(unsigned short *)((size_t)(pbuf) + 22)) &	\
+-			le16_to_cpu(~(0x000f))) | \
+-			cpu_to_le16(0x0f & (num));     \
+-	} while (0)
+-
+ #define SetSeqNum(pbuf, num) \
+ 	do {    \
+ 		*(__le16 *)((size_t)(pbuf) + 22) = \
+@@ -370,15 +349,8 @@ enum WIFI_REG_DOMAIN {
+ 
+ #define GetAMsdu(pbuf) (((le16_to_cpu(*(__le16 *)pbuf)) >> 7) & 0x1)
+ 
+-#define SetAMsdu(pbuf, amsdu)	\
+-	*(__le16 *)(pbuf) |= cpu_to_le16((amsdu & 1) << 7)
+-
+ #define GetAid(pbuf)	(le16_to_cpu(*(__le16 *)((size_t)(pbuf) + 2)) & 0x3fff)
+ 
+-#define GetTid(pbuf)	(le16_to_cpu(*(__le16 *)((size_t)(pbuf) +	\
+-			(((GetToDs(pbuf)<<1) | GetFrDs(pbuf)) == 3 ?	\
+-			30 : 24))) & 0x000f)
+-
+ #define GetAddr1Ptr(pbuf)	((unsigned char *)((size_t)(pbuf) + 4))
+ 
+ #define GetAddr2Ptr(pbuf)	((unsigned char *)((size_t)(pbuf) + 10))

commit b4c2c314c140611f3f9c1496a60e55174ba96da7
+Author: Katie Dunne 
+Date:   Wed Feb 18 18:05:40 2015 -0800
+
+    Staging: media: mn88473: Match alignment with open parenthesis
+    
+    Fixes the checkpatch.pl Check:
+    CHECK: Alignment should match open parenthesis
+    
+    Increases readability by standardizing 7 argument indentations
+    
+    Signed-off-by: Katie Dunne 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/media/mn88473/mn88473.c b/drivers/staging/media/mn88473/mn88473.c
+index a333744b76b9..197e2d0871f4 100644
+--- a/drivers/staging/media/mn88473/mn88473.c
++++ b/drivers/staging/media/mn88473/mn88473.c
+@@ -17,7 +17,7 @@
+ #include "mn88473_priv.h"
+ 
+ static int mn88473_get_tune_settings(struct dvb_frontend *fe,
+-	struct dvb_frontend_tune_settings *s)
++				     struct dvb_frontend_tune_settings *s)
+ {
+ 	s->min_delay_ms = 1000;
+ 	return 0;
+@@ -33,10 +33,14 @@ static int mn88473_set_frontend(struct dvb_frontend *fe)
+ 	u8 delivery_system_val, if_val[3], bw_val[7];
+ 
+ 	dev_dbg(&client->dev,
+-			"delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%d stream_id=%d\n",
+-			c->delivery_system, c->modulation,
+-			c->frequency, c->bandwidth_hz, c->symbol_rate,
+-			c->inversion, c->stream_id);
++		"delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%d stream_id=%d\n",
++		c->delivery_system,
++		c->modulation,
++		c->frequency,
++		c->bandwidth_hz,
++		c->symbol_rate,
++		c->inversion,
++		c->stream_id);
+ 
+ 	if (!dev->warm) {
+ 		ret = -EAGAIN;
+@@ -112,7 +116,7 @@ static int mn88473_set_frontend(struct dvb_frontend *fe)
+ 		break;
+ 	default:
+ 		dev_err(&client->dev, "IF frequency %d not supported\n",
+-				if_frequency);
++			if_frequency);
+ 		ret = -EINVAL;
+ 		goto err;
+ 	}
+@@ -229,7 +233,7 @@ static int mn88473_init(struct dvb_frontend *fe)
+ 	}
+ 
+ 	dev_info(&client->dev, "downloading firmware from file '%s'\n",
+-			fw_file);
++		 fw_file);
+ 
+ 	ret = regmap_write(dev->regmap[0], 0xf5, 0x03);
+ 	if (ret)
+@@ -242,10 +246,10 @@ static int mn88473_init(struct dvb_frontend *fe)
+ 			len = (dev->i2c_wr_max - 1);
+ 
+ 		ret = regmap_bulk_write(dev->regmap[0], 0xf6,
+-				&fw->data[fw->size - remaining], len);
++					&fw->data[fw->size - remaining], len);
+ 		if (ret) {
+ 			dev_err(&client->dev, "firmware download failed=%d\n",
+-					ret);
++				ret);
+ 			goto err;
+ 		}
+ 	}
+@@ -325,7 +329,7 @@ static struct dvb_frontend_ops mn88473_ops = {
+ };
+ 
+ static int mn88473_probe(struct i2c_client *client,
+-		const struct i2c_device_id *id)
++			 const struct i2c_device_id *id)
+ {
+ 	struct mn88473_config *config = client->dev.platform_data;
+ 	struct mn88473_dev *dev;

commit 4d36302448dde607faac07f76d9da92654404981
+Author: Katie Dunne 
+Date:   Fri Feb 20 14:51:02 2015 -0800
+
+    Staging: vt6655: break lines over 80 characters
+    
+    Addresses checkpatch.pl warning:
+    WARNING: line over 80 characters
+    
+    Break 2 lines over 80 characters and align with opening parenthesis
+    
+    Signed-off-by: Katie Dunne 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/vt6655/srom.h b/drivers/staging/vt6655/srom.h
+index fc4b1799efff..531bf0069373 100644
+--- a/drivers/staging/vt6655/srom.h
++++ b/drivers/staging/vt6655/srom.h
+@@ -90,10 +90,12 @@
+ 
+ /*---------------------  Export Functions  --------------------------*/
+ 
+-unsigned char SROMbyReadEmbedded(void __iomem *dwIoBase, unsigned char byContntOffset);
++unsigned char SROMbyReadEmbedded(void __iomem *dwIoBase,
++				 unsigned char byContntOffset);
+ 
+ void SROMvReadAllContents(void __iomem *dwIoBase, unsigned char *pbyEepromRegs);
+ 
+-void SROMvReadEtherAddress(void __iomem *dwIoBase, unsigned char *pbyEtherAddress);
++void SROMvReadEtherAddress(void __iomem *dwIoBase,
++			   unsigned char *pbyEtherAddress);
+ 
+ #endif /* __EEPROM_H__*/

commit 0cc5a4f9d5d7389cc01ee676adbb45bcbd77228c
+Author: Katie Dunne 
+Date:   Thu Feb 19 15:43:12 2015 -0800
+
+    Staging: vt6655: Replace C99 comments with C89
+    
+    Addresses the checkpatch.pl error:
+    ERROR: Do not use C99 // comments
+    
+    Remove an unneeded comment line
+    Replace C99 comments with C89
+    Reduce multiple line comments to one line
+    Shorten comments over 80 line by removing blank space
+    
+    Signed-off-by: Katie Dunne 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/vt6655/srom.h b/drivers/staging/vt6655/srom.h
+index 7d3e3ef9f17f..fc4b1799efff 100644
+--- a/drivers/staging/vt6655/srom.h
++++ b/drivers/staging/vt6655/srom.h
+@@ -24,7 +24,6 @@
+  * Author: Jerry Chen
+  *
+  * Date: Jan 29, 2003
+- *
+  */
+ 
+ #ifndef __SROM_H__
+@@ -34,56 +33,50 @@
+ 
+ #define EEP_MAX_CONTEXT_SIZE    256
+ 
+-#define CB_EEPROM_READBYTE_WAIT 900     //us
++#define CB_EEPROM_READBYTE_WAIT 900     /* us */
+ 
+ #define W_MAX_I2CRETRY          0x0fff
+ 
+-//
+-// Contents in the EEPROM
+-//
+-#define EEP_OFS_PAR         0x00        // physical address
++/* Contents in the EEPROM */
++#define EEP_OFS_PAR         0x00        /* physical address */
+ #define EEP_OFS_ANTENNA     0x16
+ #define EEP_OFS_RADIOCTL    0x17
+-#define EEP_OFS_RFTYPE      0x1B        // for select RF
+-#define EEP_OFS_MINCHANNEL  0x1C        // Min Channel #
+-#define EEP_OFS_MAXCHANNEL  0x1D        // Max Channel #
+-#define EEP_OFS_SIGNATURE   0x1E        //
+-#define EEP_OFS_ZONETYPE    0x1F        //
+-#define EEP_OFS_RFTABLE     0x20        // RF POWER TABLE
++#define EEP_OFS_RFTYPE      0x1B        /* for select RF */
++#define EEP_OFS_MINCHANNEL  0x1C        /* Min Channel # */
++#define EEP_OFS_MAXCHANNEL  0x1D        /* Max Channel # */
++#define EEP_OFS_SIGNATURE   0x1E
++#define EEP_OFS_ZONETYPE    0x1F
++#define EEP_OFS_RFTABLE     0x20        /* RF POWER TABLE */
+ #define EEP_OFS_PWR_CCK     0x20
+ #define EEP_OFS_SETPT_CCK   0x21
+ #define EEP_OFS_PWR_OFDMG   0x23
+ #define EEP_OFS_SETPT_OFDMG 0x24
+-#define EEP_OFS_PWR_FORMULA_OST  0x26   //
++#define EEP_OFS_PWR_FORMULA_OST  0x26
+ #define EEP_OFS_MAJOR_VER 0x2E
+ #define EEP_OFS_MINOR_VER 0x2F
+ #define EEP_OFS_CCK_PWR_TBL     0x30
+ #define EEP_OFS_CCK_PWR_dBm     0x3F
+ #define EEP_OFS_OFDM_PWR_TBL    0x40
+ #define EEP_OFS_OFDM_PWR_dBm    0x4F
+-//{{ RobertYu: 20041124
++/*{{ RobertYu: 20041124 */
+ #define EEP_OFS_SETPT_OFDMA         0x4E
+ #define EEP_OFS_OFDMA_PWR_TBL       0x50
+-//}}
++/*}}*/
+ #define EEP_OFS_OFDMA_PWR_dBm       0xD2
+ 
+-//----------need to remove --------------------
+-#define EEP_OFS_BBTAB_LEN   0x70        // BB Table Length
+-#define EEP_OFS_BBTAB_ADR   0x71        // BB Table Offset
+-#define EEP_OFS_CHECKSUM    0xFF        // reserved area for baseband 28h ~ 78h
++/*----------need to remove --------------------*/
++#define EEP_OFS_BBTAB_LEN   0x70        /* BB Table Length */
++#define EEP_OFS_BBTAB_ADR   0x71        /* BB Table Offset */
++#define EEP_OFS_CHECKSUM    0xFF        /* reserved area for baseband 28h~78h */
+ 
+-#define EEP_I2C_DEV_ID      0x50        // EEPROM device address on the I2C bus
++#define EEP_I2C_DEV_ID      0x50        /* EEPROM device address on I2C bus */
+ 
+-//
+-// Bits in EEP_OFS_ANTENNA
+-//
++/* Bits in EEP_OFS_ANTENNA */
+ #define EEP_ANTENNA_MAIN    0x01
+ #define EEP_ANTENNA_AUX     0x02
+ #define EEP_ANTINV          0x04
+ 
+-//
+-// Bits in EEP_OFS_RADIOCTL
+-//
++/* Bits in EEP_OFS_RADIOCTL */
+ #define EEP_RADIOCTL_ENABLE 0x80
+ #define EEP_RADIOCTL_INV    0x01
+ 
+@@ -103,4 +96,4 @@ void SROMvReadAllContents(void __iomem *dwIoBase, unsigned char *pbyEepromRegs);
+ 
+ void SROMvReadEtherAddress(void __iomem *dwIoBase, unsigned char *pbyEtherAddress);
+ 
+-#endif // __EEPROM_H__
++#endif /* __EEPROM_H__*/

\ No newline at end of file diff --git a/detail/37.html b/detail/37.html new file mode 100644 index 0000000..db79a2d --- /dev/null +++ b/detail/37.html @@ -0,0 +1,1434 @@ +

Patches contributed by Unknown (rosedu.org)


commit 114ab993e1845a4152bc01d1075b1fb38e741df9
+Author: Calin Cruceru 
+Date:   Sat Feb 25 12:11:11 2017 +0200
+
+    ASoC: samsung: Remove extra blank lines
+    
+    This was reported by checkpatch.pl
+    
+    Signed-off-by: Calin Cruceru 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c
+index 3dd246fa0059..34deba461ae1 100644
+--- a/sound/soc/samsung/bells.c
++++ b/sound/soc/samsung/bells.c
+@@ -446,7 +446,6 @@ static struct snd_soc_card bells_cards[] = {
+ 	},
+ };
+ 
+-
+ static int bells_probe(struct platform_device *pdev)
+ {
+ 	int ret;
+diff --git a/sound/soc/samsung/i2s-regs.h b/sound/soc/samsung/i2s-regs.h
+index 9170c311d66e..fe6914005494 100644
+--- a/sound/soc/samsung/i2s-regs.h
++++ b/sound/soc/samsung/i2s-regs.h
+@@ -160,5 +160,3 @@
+ #define I2SSIZE_SHIFT		(16)
+ 
+ #endif /* __SND_SOC_SAMSUNG_I2S_REGS_H */
+-
+-
+diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
+index 52a47ed292a4..af3ba4d4ccc5 100644
+--- a/sound/soc/samsung/i2s.c
++++ b/sound/soc/samsung/i2s.c
+@@ -1242,7 +1242,6 @@ static int samsung_i2s_probe(struct platform_device *pdev)
+ 		i2s_dai_data = (struct samsung_i2s_dai_data *)
+ 				platform_get_device_id(pdev)->driver_data;
+ 
+-
+ 	pri_dai = i2s_alloc_dai(pdev, false);
+ 	if (!pri_dai) {
+ 		dev_err(&pdev->dev, "Unable to alloc I2S_pri\n");
+diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c
+index 644f186fd35c..8f42deaa184b 100644
+--- a/sound/soc/samsung/s3c-i2s-v2.c
++++ b/sound/soc/samsung/s3c-i2s-v2.c
+@@ -72,7 +72,6 @@ static inline void dbg_showcon(const char *fn, u32 con)
+ }
+ #endif
+ 
+-
+ /* Turn on or off the transmission path. */
+ static void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on)
+ {

commit 0e48a3e8f616026195416e5d61c6cf24f686c2d8
+Author: Alexandru Juncu 
+Date:   Wed Sep 4 11:41:34 2013 -0300
+
+    [media] dm1105: remove unneeded not-null test
+    
+    i2c_adap is a field of a struct and will always be allocated so
+    its address will never be null.
+    Suggested by coccinelle, manually verified.
+    
+    Signed-off-by: Alexandru Juncu 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/pci/dm1105/dm1105.c b/drivers/media/pci/dm1105/dm1105.c
+index e985e3b0f647..e60ac35fc10c 100644
+--- a/drivers/media/pci/dm1105/dm1105.c
++++ b/drivers/media/pci/dm1105/dm1105.c
+@@ -1201,8 +1201,7 @@ static void dm1105_remove(struct pci_dev *pdev)
+ 	dvb_dmxdev_release(&dev->dmxdev);
+ 	dvb_dmx_release(dvbdemux);
+ 	dvb_unregister_adapter(dvb_adapter);
+-	if (&dev->i2c_adap)
+-		i2c_del_adapter(&dev->i2c_adap);
++	i2c_del_adapter(&dev->i2c_adap);
+ 
+ 	dm1105_hw_exit(dev);
+ 	synchronize_irq(pdev->irq);

commit 907b7835799f741bf80e18b635555dc332ca9863
+Author: Laura Mihaela Vasilescu 
+Date:   Tue Oct 1 04:33:56 2013 -0700
+
+    igb: Add ethtool support to configure number of channels
+    
+    This patch adds the ethtool callbacks necessary to configure the
+    number of RSS queues.
+    
+    The maximum number of queues is in accordance with the datasheets.
+    
+    Signed-off-by: Laura Mihaela Vasilescu 
+    Tested-by: Aaron Brown 
+    Signed-off-by: Jeff Kirsher 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
+index cdaa2bcefc4c..5e9ed89403aa 100644
+--- a/drivers/net/ethernet/intel/igb/igb.h
++++ b/drivers/net/ethernet/intel/igb/igb.h
+@@ -487,6 +487,7 @@ int igb_up(struct igb_adapter *);
+ void igb_down(struct igb_adapter *);
+ void igb_reinit_locked(struct igb_adapter *);
+ void igb_reset(struct igb_adapter *);
++int igb_reinit_queues(struct igb_adapter *);
+ void igb_write_rss_indir_tbl(struct igb_adapter *);
+ int igb_set_spd_dplx(struct igb_adapter *, u32, u8);
+ int igb_setup_tx_resources(struct igb_ring *);
+diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
+index e4c77c041d37..c8f65e5e6d10 100644
+--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
++++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
+@@ -2874,6 +2874,88 @@ static int igb_set_rxfh_indir(struct net_device *netdev, const u32 *indir)
+ 	return 0;
+ }
+ 
++static unsigned int igb_max_channels(struct igb_adapter *adapter)
++{
++	struct e1000_hw *hw = &adapter->hw;
++	unsigned int max_combined = 0;
++
++	switch (hw->mac.type) {
++	case e1000_i211:
++		max_combined = IGB_MAX_RX_QUEUES_I211;
++		break;
++	case e1000_82575:
++	case e1000_i210:
++		max_combined = IGB_MAX_RX_QUEUES_82575;
++		break;
++	case e1000_i350:
++		if (!!adapter->vfs_allocated_count) {
++			max_combined = 1;
++			break;
++		}
++		/* fall through */
++	case e1000_82576:
++		if (!!adapter->vfs_allocated_count) {
++			max_combined = 2;
++			break;
++		}
++		/* fall through */
++	case e1000_82580:
++	case e1000_i354:
++	default:
++		max_combined = IGB_MAX_RX_QUEUES;
++		break;
++	}
++
++	return max_combined;
++}
++
++static void igb_get_channels(struct net_device *netdev,
++			     struct ethtool_channels *ch)
++{
++	struct igb_adapter *adapter = netdev_priv(netdev);
++
++	/* Report maximum channels */
++	ch->max_combined = igb_max_channels(adapter);
++
++	/* Report info for other vector */
++	if (adapter->msix_entries) {
++		ch->max_other = NON_Q_VECTORS;
++		ch->other_count = NON_Q_VECTORS;
++	}
++
++	ch->combined_count = adapter->rss_queues;
++}
++
++static int igb_set_channels(struct net_device *netdev,
++			    struct ethtool_channels *ch)
++{
++	struct igb_adapter *adapter = netdev_priv(netdev);
++	unsigned int count = ch->combined_count;
++
++	/* Verify they are not requesting separate vectors */
++	if (!count || ch->rx_count || ch->tx_count)
++		return -EINVAL;
++
++	/* Verify other_count is valid and has not been changed */
++	if (ch->other_count != NON_Q_VECTORS)
++		return -EINVAL;
++
++	/* Verify the number of channels doesn't exceed hw limits */
++	if (count > igb_max_channels(adapter))
++		return -EINVAL;
++
++	if (count != adapter->rss_queues) {
++		adapter->rss_queues = count;
++
++		/* Hardware has to reinitialize queues and interrupts to
++		 * match the new configuration.
++		 */
++		return igb_reinit_queues(adapter);
++	}
++
++	return 0;
++}
++
+ static const struct ethtool_ops igb_ethtool_ops = {
+ 	.get_settings		= igb_get_settings,
+ 	.set_settings		= igb_set_settings,
+@@ -2910,6 +2992,8 @@ static const struct ethtool_ops igb_ethtool_ops = {
+ 	.get_rxfh_indir_size	= igb_get_rxfh_indir_size,
+ 	.get_rxfh_indir		= igb_get_rxfh_indir,
+ 	.set_rxfh_indir		= igb_set_rxfh_indir,
++	.get_channels		= igb_get_channels,
++	.set_channels		= igb_set_channels,
+ 	.begin			= igb_ethtool_begin,
+ 	.complete		= igb_ethtool_complete,
+ };
+diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
+index 8cf44f2a8ccd..a56266eacc64 100644
+--- a/drivers/net/ethernet/intel/igb/igb_main.c
++++ b/drivers/net/ethernet/intel/igb/igb_main.c
+@@ -7838,4 +7838,26 @@ s32 igb_write_i2c_byte(struct e1000_hw *hw, u8 byte_offset,
+ 		return E1000_SUCCESS;
+ 
+ }
++
++int igb_reinit_queues(struct igb_adapter *adapter)
++{
++	struct net_device *netdev = adapter->netdev;
++	struct pci_dev *pdev = adapter->pdev;
++	int err = 0;
++
++	if (netif_running(netdev))
++		igb_close(netdev);
++
++	igb_clear_interrupt_scheme(adapter);
++
++	if (igb_init_interrupt_scheme(adapter, true)) {
++		dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
++		return -ENOMEM;
++	}
++
++	if (netif_running(netdev))
++		err = igb_open(netdev);
++
++	return err;
++}
+ /* igb_main.c */

commit 83eefabf9b596b8237cdcc385bff67f70d1e5a2d
+Author: Alexandru Juncu 
+Date:   Fri Jul 26 17:03:35 2013 +0300
+
+    MIPS:Netlogic: Remove redundant value in operation.
+    
+    Removed parameters checked twice in logical OR operation.
+    Suggested by coccinelle and manually verified.
+    
+    Signed-off-by: Alexandru Juncu 
+    Cc: jchandra@broadcom.com
+    Cc: linux-mips@linux-mips.org
+    Cc: linux-kernel@vger.kernel.org
+    Patchwork: https://patchwork.linux-mips.org/patch/5627/
+    Signed-off-by: Ralf Baechle 
+
+diff --git a/arch/mips/netlogic/xlp/usb-init.c b/arch/mips/netlogic/xlp/usb-init.c
+index ef3897ef0dc7..d5378ef3c0f7 100644
+--- a/arch/mips/netlogic/xlp/usb-init.c
++++ b/arch/mips/netlogic/xlp/usb-init.c
+@@ -75,8 +75,7 @@ static void nlm_usb_intr_en(int node, int port)
+ 	port_addr = nlm_get_usb_regbase(node, port);
+ 	val = nlm_read_usb_reg(port_addr, USB_INT_EN);
+ 	val = USB_CTRL_INTERRUPT_EN  | USB_OHCI_INTERRUPT_EN |
+-		USB_OHCI_INTERRUPT1_EN | USB_CTRL_INTERRUPT_EN	|
+-		USB_OHCI_INTERRUPT_EN | USB_OHCI_INTERRUPT2_EN;
++		USB_OHCI_INTERRUPT1_EN | USB_OHCI_INTERRUPT2_EN;
+ 	nlm_write_usb_reg(port_addr, USB_INT_EN, val);
+ }
+ 

commit ed12cc9a145132f5e59919570adff84b318f6010
+Author: Laura Mihaela Vasilescu 
+Date:   Wed Jul 31 20:19:54 2013 +0000
+
+    igb: Expose RSS indirection table for ethtool
+    
+    This patch adds the ethtool callbacks necessary to change the RETA
+    indirection table from userspace.
+    
+    In order to achieve this, we add the indirection table field (rss_indir_tbl)
+    in the board specific data structure (struct igb_adapter) to preserve the
+    values across hardware resets.
+    
+    The indirection table must be initialized with default values in the
+    following cases:
+            * at module init time
+            * when the number of RX queues changes.
+    For this reason we add a new field (rss_indir_tbl_init) in igb_adapter
+    that keeps track of the number of RX queues. Whenever the number of RX
+    queues changes, the rss_indir_tbl is modified and initialized with default
+    values. The rss_indir_tbl_init is updated accordingly.
+    
+    CC: Ben Hutchings 
+    Signed-off-by: Laura Mihaela Vasilescu 
+    Tested-by: Aaron Brown 
+    Signed-off-by: Jeff Kirsher 
+
+diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
+index 5a2659bf0c32..c1fae7aa0bd5 100644
+--- a/drivers/net/ethernet/intel/igb/igb.h
++++ b/drivers/net/ethernet/intel/igb/igb.h
+@@ -446,6 +446,8 @@ struct igb_adapter {
+ 	struct i2c_algo_bit_data i2c_algo;
+ 	struct i2c_adapter i2c_adap;
+ 	struct i2c_client *i2c_client;
++	u32 rss_indir_tbl_init;
++	u8 rss_indir_tbl[IGB_RETA_SIZE];
+ };
+ 
+ #define IGB_FLAG_HAS_MSI		(1 << 0)
+@@ -482,6 +484,7 @@ extern int igb_up(struct igb_adapter *);
+ extern void igb_down(struct igb_adapter *);
+ extern void igb_reinit_locked(struct igb_adapter *);
+ extern void igb_reset(struct igb_adapter *);
++extern void igb_write_rss_indir_tbl(struct igb_adapter *);
+ extern int igb_set_spd_dplx(struct igb_adapter *, u32, u8);
+ extern int igb_setup_tx_resources(struct igb_ring *);
+ extern int igb_setup_rx_resources(struct igb_ring *);
+diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
+index 03137e21551d..ce9b5a9e480c 100644
+--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
++++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
+@@ -2784,6 +2784,90 @@ static void igb_ethtool_complete(struct net_device *netdev)
+ 	pm_runtime_put(&adapter->pdev->dev);
+ }
+ 
++static u32 igb_get_rxfh_indir_size(struct net_device *netdev)
++{
++	return IGB_RETA_SIZE;
++}
++
++static int igb_get_rxfh_indir(struct net_device *netdev, u32 *indir)
++{
++	struct igb_adapter *adapter = netdev_priv(netdev);
++	int i;
++
++	for (i = 0; i < IGB_RETA_SIZE; i++)
++		indir[i] = adapter->rss_indir_tbl[i];
++
++	return 0;
++}
++
++void igb_write_rss_indir_tbl(struct igb_adapter *adapter)
++{
++	struct e1000_hw *hw = &adapter->hw;
++	u32 reg = E1000_RETA(0);
++	u32 shift = 0;
++	int i = 0;
++
++	switch (hw->mac.type) {
++	case e1000_82575:
++		shift = 6;
++		break;
++	case e1000_82576:
++		/* 82576 supports 2 RSS queues for SR-IOV */
++		if (adapter->vfs_allocated_count)
++			shift = 3;
++		break;
++	default:
++		break;
++	}
++
++	while (i < IGB_RETA_SIZE) {
++		u32 val = 0;
++		int j;
++
++		for (j = 3; j >= 0; j--) {
++			val <<= 8;
++			val |= adapter->rss_indir_tbl[i + j];
++		}
++
++		wr32(reg, val << shift);
++		reg += 4;
++		i += 4;
++	}
++}
++
++static int igb_set_rxfh_indir(struct net_device *netdev, const u32 *indir)
++{
++	struct igb_adapter *adapter = netdev_priv(netdev);
++	struct e1000_hw *hw = &adapter->hw;
++	int i;
++	u32 num_queues;
++
++	num_queues = adapter->rss_queues;
++
++	switch (hw->mac.type) {
++	case e1000_82576:
++		/* 82576 supports 2 RSS queues for SR-IOV */
++		if (adapter->vfs_allocated_count)
++			num_queues = 2;
++		break;
++	default:
++		break;
++	}
++
++	/* Verify user input. */
++	for (i = 0; i < IGB_RETA_SIZE; i++)
++		if (indir[i] >= num_queues)
++			return -EINVAL;
++
++
++	for (i = 0; i < IGB_RETA_SIZE; i++)
++		adapter->rss_indir_tbl[i] = indir[i];
++
++	igb_write_rss_indir_tbl(adapter);
++
++	return 0;
++}
++
+ static const struct ethtool_ops igb_ethtool_ops = {
+ 	.get_settings		= igb_get_settings,
+ 	.set_settings		= igb_set_settings,
+@@ -2817,6 +2901,9 @@ static const struct ethtool_ops igb_ethtool_ops = {
+ 	.set_eee		= igb_set_eee,
+ 	.get_module_info	= igb_get_module_info,
+ 	.get_module_eeprom	= igb_get_module_eeprom,
++	.get_rxfh_indir_size	= igb_get_rxfh_indir_size,
++	.get_rxfh_indir		= igb_get_rxfh_indir,
++	.set_rxfh_indir		= igb_set_rxfh_indir,
+ 	.begin			= igb_ethtool_begin,
+ 	.complete		= igb_ethtool_complete,
+ };
+diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
+index 1acd9c06026a..df33c4b8fa81 100644
+--- a/drivers/net/ethernet/intel/igb/igb_main.c
++++ b/drivers/net/ethernet/intel/igb/igb_main.c
+@@ -3126,7 +3126,7 @@ static void igb_setup_mrqc(struct igb_adapter *adapter)
+ {
+ 	struct e1000_hw *hw = &adapter->hw;
+ 	u32 mrqc, rxcsum;
+-	u32 j, num_rx_queues, shift = 0;
++	u32 j, num_rx_queues;
+ 	static const u32 rsskey[10] = { 0xDA565A6D, 0xC20E5B25, 0x3D256741,
+ 					0xB08FA343, 0xCB2BCAD0, 0xB4307BAE,
+ 					0xA32DCB77, 0x0CF23080, 0x3BB7426A,
+@@ -3139,35 +3139,21 @@ static void igb_setup_mrqc(struct igb_adapter *adapter)
+ 	num_rx_queues = adapter->rss_queues;
+ 
+ 	switch (hw->mac.type) {
+-	case e1000_82575:
+-		shift = 6;
+-		break;
+ 	case e1000_82576:
+ 		/* 82576 supports 2 RSS queues for SR-IOV */
+-		if (adapter->vfs_allocated_count) {
+-			shift = 3;
++		if (adapter->vfs_allocated_count)
+ 			num_rx_queues = 2;
+-		}
+ 		break;
+ 	default:
+ 		break;
+ 	}
+ 
+-	/* Populate the indirection table 4 entries at a time.  To do this
+-	 * we are generating the results for n and n+2 and then interleaving
+-	 * those with the results with n+1 and n+3.
+-	 */
+-	for (j = 0; j < IGB_RETA_SIZE / 4; j++) {
+-		/* first pass generates n and n+2 */
+-		u32 base = ((j * 0x00040004) + 0x00020000) * num_rx_queues;
+-		u32 reta = (base & 0x07800780) >> (7 - shift);
+-
+-		/* second pass generates n+1 and n+3 */
+-		base += 0x00010001 * num_rx_queues;
+-		reta |= (base & 0x07800780) << (1 + shift);
+-
+-		wr32(E1000_RETA(j), reta);
++	if (adapter->rss_indir_tbl_init != num_rx_queues) {
++		for (j = 0; j < IGB_RETA_SIZE; j++)
++			adapter->rss_indir_tbl[j] = (j * num_rx_queues) / IGB_RETA_SIZE;
++		adapter->rss_indir_tbl_init = num_rx_queues;
+ 	}
++	igb_write_rss_indir_tbl(adapter);
+ 
+ 	/* Disable raw packet checksumming so that RSS hash is placed in
+ 	 * descriptor on writeback.  No need to enable TCP/UDP/IP checksum

commit c342b39ea7ca0e46e093cdb346bf52b2b4e71b01
+Author: Laura Mihaela Vasilescu 
+Date:   Wed Jul 31 20:19:48 2013 +0000
+
+    igb: Add macro for size of RETA indirection table
+    
+    RETA indirection table is used to assign the received data to a CPU
+    in order to maintain an efficient distribution of network receive
+    processing across multiple CPUs.
+    
+    This patch removes the hard-coded value for the size of the indirection
+    table and defines a new macro.
+    
+    Signed-off-by: Laura Mihaela Vasilescu 
+    Tested-by: Aaron Brown 
+    Signed-off-by: Jeff Kirsher 
+
+diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
+index 15ea8dc9dad3..5a2659bf0c32 100644
+--- a/drivers/net/ethernet/intel/igb/igb.h
++++ b/drivers/net/ethernet/intel/igb/igb.h
+@@ -343,6 +343,8 @@ struct hwmon_buff {
+ 	};
+ #endif
+ 
++#define IGB_RETA_SIZE	128
++
+ /* board specific private data structure */
+ struct igb_adapter {
+ 	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
+diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
+index 7f6cf654b307..1acd9c06026a 100644
+--- a/drivers/net/ethernet/intel/igb/igb_main.c
++++ b/drivers/net/ethernet/intel/igb/igb_main.c
+@@ -3157,7 +3157,7 @@ static void igb_setup_mrqc(struct igb_adapter *adapter)
+ 	 * we are generating the results for n and n+2 and then interleaving
+ 	 * those with the results with n+1 and n+3.
+ 	 */
+-	for (j = 0; j < 32; j++) {
++	for (j = 0; j < IGB_RETA_SIZE / 4; j++) {
+ 		/* first pass generates n and n+2 */
+ 		u32 base = ((j * 0x00040004) + 0x00020000) * num_rx_queues;
+ 		u32 reta = (base & 0x07800780) >> (7 - shift);

commit e06922aa836f098c4893218a1c656ce7d73a3b6a
+Author: Alexandru Juncu 
+Date:   Sat Jul 27 11:14:39 2013 +0300
+
+    TTY: synclink: replace bitmasks add operation with OR operation.
+    
+    Found with coccinelle, manually fixed and verified.
+    
+    Signed-off-by: Alexandru Juncu 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c
+index 8eaf1ab8addb..e1ce141bad5e 100644
+--- a/drivers/tty/synclink.c
++++ b/drivers/tty/synclink.c
+@@ -577,22 +577,22 @@ struct mgsl_struct {
+ 
+ #define SICR_RXC_ACTIVE			BIT15
+ #define SICR_RXC_INACTIVE		BIT14
+-#define SICR_RXC			(BIT15+BIT14)
++#define SICR_RXC			(BIT15|BIT14)
+ #define SICR_TXC_ACTIVE			BIT13
+ #define SICR_TXC_INACTIVE		BIT12
+-#define SICR_TXC			(BIT13+BIT12)
++#define SICR_TXC			(BIT13|BIT12)
+ #define SICR_RI_ACTIVE			BIT11
+ #define SICR_RI_INACTIVE		BIT10
+-#define SICR_RI				(BIT11+BIT10)
++#define SICR_RI				(BIT11|BIT10)
+ #define SICR_DSR_ACTIVE			BIT9
+ #define SICR_DSR_INACTIVE		BIT8
+-#define SICR_DSR			(BIT9+BIT8)
++#define SICR_DSR			(BIT9|BIT8)
+ #define SICR_DCD_ACTIVE			BIT7
+ #define SICR_DCD_INACTIVE		BIT6
+-#define SICR_DCD			(BIT7+BIT6)
++#define SICR_DCD			(BIT7|BIT6)
+ #define SICR_CTS_ACTIVE			BIT5
+ #define SICR_CTS_INACTIVE		BIT4
+-#define SICR_CTS			(BIT5+BIT4)
++#define SICR_CTS			(BIT5|BIT4)
+ #define SICR_RCC_UNDERFLOW		BIT3
+ #define SICR_DPLL_NO_SYNC		BIT2
+ #define SICR_BRG1_ZERO			BIT1
+@@ -1161,7 +1161,7 @@ static void mgsl_isr_receive_status( struct mgsl_struct *info )
+ {
+ 	u16 status = usc_InReg( info, RCSR );
+ 
+-	if ( debug_level >= DEBUG_LEVEL_ISR )	
++	if ( debug_level >= DEBUG_LEVEL_ISR )
+ 		printk("%s(%d):mgsl_isr_receive_status status=%04X\n",
+ 			__FILE__,__LINE__,status);
+ 			
+@@ -1181,7 +1181,7 @@ static void mgsl_isr_receive_status( struct mgsl_struct *info )
+  			(usc_InReg(info, RICR) & ~RXSTATUS_ABORT_RECEIVED));
+  	}
+ 
+-	if (status & (RXSTATUS_EXITED_HUNT + RXSTATUS_IDLE_RECEIVED)) {
++	if (status & (RXSTATUS_EXITED_HUNT | RXSTATUS_IDLE_RECEIVED)) {
+ 		if (status & RXSTATUS_EXITED_HUNT)
+ 			info->icount.exithunt++;
+ 		if (status & RXSTATUS_IDLE_RECEIVED)
+@@ -1463,21 +1463,21 @@ static void mgsl_isr_receive_data( struct mgsl_struct *info )
+ 
+ 		/* get the status of the received byte */
+ 		status = usc_InReg(info, RCSR);
+-		if ( status & (RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR +
+-				RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) )
++		if ( status & (RXSTATUS_FRAMING_ERROR | RXSTATUS_PARITY_ERROR |
++				RXSTATUS_OVERRUN | RXSTATUS_BREAK_RECEIVED) )
+ 			usc_UnlatchRxstatusBits(info,RXSTATUS_ALL);
+ 		
+ 		icount->rx++;
+ 		
+ 		flag = 0;
+-		if ( status & (RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR +
+-				RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) ) {
+-			printk("rxerr=%04X\n",status);					
++		if ( status & (RXSTATUS_FRAMING_ERROR | RXSTATUS_PARITY_ERROR |
++				RXSTATUS_OVERRUN | RXSTATUS_BREAK_RECEIVED) ) {
++			printk("rxerr=%04X\n",status);
+ 			/* update error statistics */
+ 			if ( status & RXSTATUS_BREAK_RECEIVED ) {
+-				status &= ~(RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR);
++				status &= ~(RXSTATUS_FRAMING_ERROR | RXSTATUS_PARITY_ERROR);
+ 				icount->brk++;
+-			} else if (status & RXSTATUS_PARITY_ERROR) 
++			} else if (status & RXSTATUS_PARITY_ERROR)
+ 				icount->parity++;
+ 			else if (status & RXSTATUS_FRAMING_ERROR)
+ 				icount->frame++;
+@@ -1488,7 +1488,7 @@ static void mgsl_isr_receive_data( struct mgsl_struct *info )
+ 				icount->overrun++;
+ 			}
+ 
+-			/* discard char if tty control flags say so */					
++			/* discard char if tty control flags say so */
+ 			if (status & info->ignore_status_mask)
+ 				continue;
+ 				
+@@ -1545,8 +1545,8 @@ static void mgsl_isr_misc( struct mgsl_struct *info )
+ 		usc_EnableReceiver(info,DISABLE_UNCONDITIONAL);
+ 		usc_DmaCmd(info, DmaCmd_ResetRxChannel);
+ 		usc_UnlatchRxstatusBits(info, RXSTATUS_ALL);
+-		usc_ClearIrqPendingBits(info, RECEIVE_DATA + RECEIVE_STATUS);
+-		usc_DisableInterrupts(info, RECEIVE_DATA + RECEIVE_STATUS);
++		usc_ClearIrqPendingBits(info, RECEIVE_DATA | RECEIVE_STATUS);
++		usc_DisableInterrupts(info, RECEIVE_DATA | RECEIVE_STATUS);
+ 
+ 		/* schedule BH handler to restart receiver */
+ 		info->pending_bh |= BH_RECEIVE;
+@@ -1595,7 +1595,7 @@ static void mgsl_isr_receive_dma( struct mgsl_struct *info )
+ 	u16 status;
+ 	
+ 	/* clear interrupt pending and IUS bit for Rx DMA IRQ */
+-	usc_OutDmaReg( info, CDIR, BIT9+BIT1 );
++	usc_OutDmaReg( info, CDIR, BIT9 | BIT1 );
+ 
+ 	/* Read the receive DMA status to identify interrupt type. */
+ 	/* This also clears the status bits. */
+@@ -1639,7 +1639,7 @@ static void mgsl_isr_transmit_dma( struct mgsl_struct *info )
+ 	u16 status;
+ 
+ 	/* clear interrupt pending and IUS bit for Tx DMA IRQ */
+-	usc_OutDmaReg(info, CDIR, BIT8+BIT0 );
++	usc_OutDmaReg(info, CDIR, BIT8 | BIT0 );
+ 
+ 	/* Read the transmit DMA status to identify interrupt type. */
+ 	/* This also clears the status bits. */
+@@ -1832,8 +1832,8 @@ static void shutdown(struct mgsl_struct * info)
+ 	usc_DisableMasterIrqBit(info);
+ 	usc_stop_receiver(info);
+ 	usc_stop_transmitter(info);
+-	usc_DisableInterrupts(info,RECEIVE_DATA + RECEIVE_STATUS +
+-		TRANSMIT_DATA + TRANSMIT_STATUS + IO_PIN + MISC );
++	usc_DisableInterrupts(info,RECEIVE_DATA | RECEIVE_STATUS |
++		TRANSMIT_DATA | TRANSMIT_STATUS | IO_PIN | MISC );
+ 	usc_DisableDmaInterrupts(info,DICR_MASTER + DICR_TRANSMIT + DICR_RECEIVE);
+ 
+ 	/* Disable DMAEN (Port 7, Bit 14) */
+@@ -1886,7 +1886,7 @@ static void mgsl_program_hw(struct mgsl_struct *info)
+ 	info->ri_chkcount = 0;
+ 	info->dsr_chkcount = 0;
+ 
+-	usc_EnableStatusIrqs(info,SICR_CTS+SICR_DSR+SICR_DCD+SICR_RI);		
++	usc_EnableStatusIrqs(info,SICR_CTS+SICR_DSR+SICR_DCD+SICR_RI);
+ 	usc_EnableInterrupts(info, IO_PIN);
+ 	usc_get_serial_signals(info);
+ 		
+@@ -2773,7 +2773,7 @@ static int mgsl_wait_event(struct mgsl_struct * info, int __user * mask_ptr)
+ 		if (!waitqueue_active(&info->event_wait_q)) {
+ 			/* disable enable exit hunt mode/idle rcvd IRQs */
+ 			usc_OutReg(info, RICR, usc_InReg(info,RICR) &
+-				~(RXSTATUS_EXITED_HUNT + RXSTATUS_IDLE_RECEIVED));
++				~(RXSTATUS_EXITED_HUNT | RXSTATUS_IDLE_RECEIVED));
+ 		}
+ 		spin_unlock_irqrestore(&info->irq_spinlock,flags);
+ 	}
+@@ -3092,7 +3092,7 @@ static void mgsl_close(struct tty_struct *tty, struct file * filp)
+ 		printk("%s(%d):mgsl_close(%s) entry, count=%d\n",
+ 			 __FILE__,__LINE__, info->device_name, info->port.count);
+ 
+-	if (tty_port_close_start(&info->port, tty, filp) == 0)			 
++	if (tty_port_close_start(&info->port, tty, filp) == 0)
+ 		goto cleanup;
+ 
+ 	mutex_lock(&info->port.mutex);
+@@ -4297,7 +4297,7 @@ static struct mgsl_struct* mgsl_allocate_device(void)
+ 		spin_lock_init(&info->irq_spinlock);
+ 		spin_lock_init(&info->netlock);
+ 		memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS));
+-		info->idle_mode = HDLC_TXIDLE_FLAGS;		
++		info->idle_mode = HDLC_TXIDLE_FLAGS;
+ 		info->num_tx_dma_buffers = 1;
+ 		info->num_tx_holding_buffers = 0;
+ 	}
+@@ -4722,7 +4722,7 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info )
+ 		else if ( info->params.flags & HDLC_FLAG_UNDERRUN_FLAG )
+ 			RegValue |= BIT15;
+ 		else if ( info->params.flags & HDLC_FLAG_UNDERRUN_CRC )
+-			RegValue |= BIT15 + BIT14;
++			RegValue |= BIT15 | BIT14;
+ 		}
+ 
+ 		if ( info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE )
+@@ -4763,11 +4763,11 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info )
+ 	switch ( info->params.encoding ) {
+ 	case HDLC_ENCODING_NRZB:               RegValue |= BIT13; break;
+ 	case HDLC_ENCODING_NRZI_MARK:          RegValue |= BIT14; break;
+-	case HDLC_ENCODING_NRZI_SPACE:	       RegValue |= BIT14 + BIT13; break;
++	case HDLC_ENCODING_NRZI_SPACE:	       RegValue |= BIT14 | BIT13; break;
+ 	case HDLC_ENCODING_BIPHASE_MARK:       RegValue |= BIT15; break;
+-	case HDLC_ENCODING_BIPHASE_SPACE:      RegValue |= BIT15 + BIT13; break;
+-	case HDLC_ENCODING_BIPHASE_LEVEL:      RegValue |= BIT15 + BIT14; break;
+-	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT15 + BIT14 + BIT13; break;
++	case HDLC_ENCODING_BIPHASE_SPACE:      RegValue |= BIT15 | BIT13; break;
++	case HDLC_ENCODING_BIPHASE_LEVEL:      RegValue |= BIT15 | BIT14; break;
++	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT15 | BIT14 | BIT13; break;
+ 	}
+ 
+ 	if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_16_CCITT )
+@@ -4838,15 +4838,15 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info )
+ 	switch ( info->params.encoding ) {
+ 	case HDLC_ENCODING_NRZB:               RegValue |= BIT13; break;
+ 	case HDLC_ENCODING_NRZI_MARK:          RegValue |= BIT14; break;
+-	case HDLC_ENCODING_NRZI_SPACE:         RegValue |= BIT14 + BIT13; break;
++	case HDLC_ENCODING_NRZI_SPACE:         RegValue |= BIT14 | BIT13; break;
+ 	case HDLC_ENCODING_BIPHASE_MARK:       RegValue |= BIT15; break;
+-	case HDLC_ENCODING_BIPHASE_SPACE:      RegValue |= BIT15 + BIT13; break;
+-	case HDLC_ENCODING_BIPHASE_LEVEL:      RegValue |= BIT15 + BIT14; break;
+-	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT15 + BIT14 + BIT13; break;
++	case HDLC_ENCODING_BIPHASE_SPACE:      RegValue |= BIT15 | BIT13; break;
++	case HDLC_ENCODING_BIPHASE_LEVEL:      RegValue |= BIT15 | BIT14; break;
++	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT15 | BIT14 | BIT13; break;
+ 	}
+ 
+ 	if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_16_CCITT )
+-		RegValue |= BIT9 + BIT8;
++		RegValue |= BIT9 | BIT8;
+ 	else if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_32_CCITT )
+ 		RegValue |= ( BIT12 | BIT10 | BIT9 | BIT8);
+ 
+@@ -4957,7 +4957,7 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info )
+ 
+ 	RegValue = 0x0000;
+ 
+-	if ( info->params.flags & (HDLC_FLAG_RXC_DPLL + HDLC_FLAG_TXC_DPLL) ) {
++	if ( info->params.flags & (HDLC_FLAG_RXC_DPLL | HDLC_FLAG_TXC_DPLL) ) {
+ 		u32 XtalSpeed;
+ 		u32 DpllDivisor;
+ 		u16 Tc;
+@@ -5019,7 +5019,7 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info )
+ 		case HDLC_ENCODING_BIPHASE_MARK:
+ 		case HDLC_ENCODING_BIPHASE_SPACE: RegValue |= BIT9; break;
+ 		case HDLC_ENCODING_BIPHASE_LEVEL:
+-		case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT9 + BIT8; break;
++		case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT9 | BIT8; break;
+ 		}
+ 	}
+ 
+@@ -5056,8 +5056,8 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info )
+ 	/* enable Master Interrupt Enable bit (MIE) */
+ 	usc_EnableMasterIrqBit( info );
+ 
+-	usc_ClearIrqPendingBits( info, RECEIVE_STATUS + RECEIVE_DATA +
+-				TRANSMIT_STATUS + TRANSMIT_DATA + MISC);
++	usc_ClearIrqPendingBits( info, RECEIVE_STATUS | RECEIVE_DATA |
++				TRANSMIT_STATUS | TRANSMIT_DATA | MISC);
+ 
+ 	/* arm RCC underflow interrupt */
+ 	usc_OutReg(info, SICR, (u16)(usc_InReg(info,SICR) | BIT3));
+@@ -5175,14 +5175,14 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info )
+ 	switch ( info->params.preamble_length ) {
+ 	case HDLC_PREAMBLE_LENGTH_16BITS: RegValue |= BIT10; break;
+ 	case HDLC_PREAMBLE_LENGTH_32BITS: RegValue |= BIT11; break;
+-	case HDLC_PREAMBLE_LENGTH_64BITS: RegValue |= BIT11 + BIT10; break;
++	case HDLC_PREAMBLE_LENGTH_64BITS: RegValue |= BIT11 | BIT10; break;
+ 	}
+ 
+ 	switch ( info->params.preamble ) {
+-	case HDLC_PREAMBLE_PATTERN_FLAGS: RegValue |= BIT8 + BIT12; break;
++	case HDLC_PREAMBLE_PATTERN_FLAGS: RegValue |= BIT8 | BIT12; break;
+ 	case HDLC_PREAMBLE_PATTERN_ONES:  RegValue |= BIT8; break;
+ 	case HDLC_PREAMBLE_PATTERN_10:    RegValue |= BIT9; break;
+-	case HDLC_PREAMBLE_PATTERN_01:    RegValue |= BIT9 + BIT8; break;
++	case HDLC_PREAMBLE_PATTERN_01:    RegValue |= BIT9 | BIT8; break;
+ 	}
+ 
+ 	usc_OutReg( info, CCR, RegValue );
+@@ -5221,7 +5221,7 @@ static void usc_enable_loopback(struct mgsl_struct *info, int enable)
+ {
+ 	if (enable) {
+ 		/* blank external TXD output */
+-		usc_OutReg(info,IOCR,usc_InReg(info,IOCR) | (BIT7+BIT6));
++		usc_OutReg(info,IOCR,usc_InReg(info,IOCR) | (BIT7 | BIT6));
+ 	
+ 		/* Clock mode Control Register (CMCR)
+ 		 *
+@@ -5260,7 +5260,7 @@ static void usc_enable_loopback(struct mgsl_struct *info, int enable)
+ 		outw( 0x0300, info->io_base + CCAR );
+ 	} else {
+ 		/* enable external TXD output */
+-		usc_OutReg(info,IOCR,usc_InReg(info,IOCR) & ~(BIT7+BIT6));
++		usc_OutReg(info,IOCR,usc_InReg(info,IOCR) & ~(BIT7 | BIT6));
+ 	
+ 		/* clear Internal Data loopback mode */
+ 		info->loopback_bits = 0;
+@@ -5447,13 +5447,13 @@ static void usc_process_rxoverrun_sync( struct mgsl_struct *info )
+ 		usc_OutDmaReg( info, NRARU, (u16)(phys_addr >> 16) );
+ 
+ 		usc_UnlatchRxstatusBits( info, RXSTATUS_ALL );
+-		usc_ClearIrqPendingBits( info, RECEIVE_DATA + RECEIVE_STATUS );
++		usc_ClearIrqPendingBits( info, RECEIVE_DATA | RECEIVE_STATUS );
+ 		usc_EnableInterrupts( info, RECEIVE_STATUS );
+ 
+ 		/* 1. Arm End of Buffer (EOB) Receive DMA Interrupt (BIT2 of RDIAR) */
+ 		/* 2. Enable Receive DMA Interrupts (BIT1 of DICR) */
+ 
+-		usc_OutDmaReg( info, RDIAR, BIT3 + BIT2 );
++		usc_OutDmaReg( info, RDIAR, BIT3 | BIT2 );
+ 		usc_OutDmaReg( info, DICR, (u16)(usc_InDmaReg(info,DICR) | BIT1) );
+ 		usc_DmaCmd( info, DmaCmd_InitRxChannel );
+ 		if ( info->params.flags & HDLC_FLAG_AUTO_DCD )
+@@ -5488,8 +5488,8 @@ static void usc_stop_receiver( struct mgsl_struct *info )
+ 	usc_DmaCmd( info, DmaCmd_ResetRxChannel );
+ 
+ 	usc_UnlatchRxstatusBits( info, RXSTATUS_ALL );
+-	usc_ClearIrqPendingBits( info, RECEIVE_DATA + RECEIVE_STATUS );
+-	usc_DisableInterrupts( info, RECEIVE_DATA + RECEIVE_STATUS );
++	usc_ClearIrqPendingBits( info, RECEIVE_DATA | RECEIVE_STATUS );
++	usc_DisableInterrupts( info, RECEIVE_DATA | RECEIVE_STATUS );
+ 
+ 	usc_EnableReceiver(info,DISABLE_UNCONDITIONAL);
+ 
+@@ -5536,13 +5536,13 @@ static void usc_start_receiver( struct mgsl_struct *info )
+ 		usc_OutDmaReg( info, NRARU, (u16)(phys_addr >> 16) );
+ 
+ 		usc_UnlatchRxstatusBits( info, RXSTATUS_ALL );
+-		usc_ClearIrqPendingBits( info, RECEIVE_DATA + RECEIVE_STATUS );
++		usc_ClearIrqPendingBits( info, RECEIVE_DATA | RECEIVE_STATUS );
+ 		usc_EnableInterrupts( info, RECEIVE_STATUS );
+ 
+ 		/* 1. Arm End of Buffer (EOB) Receive DMA Interrupt (BIT2 of RDIAR) */
+ 		/* 2. Enable Receive DMA Interrupts (BIT1 of DICR) */
+ 
+-		usc_OutDmaReg( info, RDIAR, BIT3 + BIT2 );
++		usc_OutDmaReg( info, RDIAR, BIT3 | BIT2 );
+ 		usc_OutDmaReg( info, DICR, (u16)(usc_InDmaReg(info,DICR) | BIT1) );
+ 		usc_DmaCmd( info, DmaCmd_InitRxChannel );
+ 		if ( info->params.flags & HDLC_FLAG_AUTO_DCD )
+@@ -5551,7 +5551,7 @@ static void usc_start_receiver( struct mgsl_struct *info )
+ 			usc_EnableReceiver(info,ENABLE_UNCONDITIONAL);
+ 	} else {
+ 		usc_UnlatchRxstatusBits(info, RXSTATUS_ALL);
+-		usc_ClearIrqPendingBits(info, RECEIVE_DATA + RECEIVE_STATUS);
++		usc_ClearIrqPendingBits(info, RECEIVE_DATA | RECEIVE_STATUS);
+ 		usc_EnableInterrupts(info, RECEIVE_DATA);
+ 
+ 		usc_RTCmd( info, RTCmd_PurgeRxFifo );
+@@ -5925,7 +5925,7 @@ static void usc_set_async_mode( struct mgsl_struct *info )
+ 	RegValue = 0;
+ 
+ 	if ( info->params.data_bits != 8 )
+-		RegValue |= BIT4+BIT3+BIT2;
++		RegValue |= BIT4 | BIT3 | BIT2;
+ 
+ 	if ( info->params.parity != ASYNC_PARITY_NONE ) {
+ 		RegValue |= BIT5;
+@@ -5982,7 +5982,7 @@ static void usc_set_async_mode( struct mgsl_struct *info )
+ 	RegValue = 0;
+ 
+ 	if ( info->params.data_bits != 8 )
+-		RegValue |= BIT4+BIT3+BIT2;
++		RegValue |= BIT4 | BIT3 | BIT2;
+ 
+ 	if ( info->params.parity != ASYNC_PARITY_NONE ) {
+ 		RegValue |= BIT5;
+@@ -6129,7 +6129,7 @@ static void usc_loopback_frame( struct mgsl_struct *info )
+ 							
+ 	/* WAIT FOR RECEIVE COMPLETE */
+ 	for (i=0 ; i<1000 ; i++)
+-		if (usc_InReg( info, RCSR ) & (BIT8 + BIT4 + BIT3 + BIT1))
++		if (usc_InReg( info, RCSR ) & (BIT8 | BIT4 | BIT3 | BIT1))
+ 			break;
+ 
+ 	/* clear Internal Data loopback mode */
+@@ -6579,8 +6579,8 @@ static bool mgsl_get_rx_frame(struct mgsl_struct *info)
+ 	
+ 	status = info->rx_buffer_list[EndIndex].status;
+ 
+-	if ( status & (RXSTATUS_SHORT_FRAME + RXSTATUS_OVERRUN +
+-			RXSTATUS_CRC_ERROR + RXSTATUS_ABORT) ) {
++	if ( status & (RXSTATUS_SHORT_FRAME | RXSTATUS_OVERRUN |
++			RXSTATUS_CRC_ERROR | RXSTATUS_ABORT) ) {
+ 		if ( status & RXSTATUS_SHORT_FRAME )
+ 			info->icount.rxshort++;
+ 		else if ( status & RXSTATUS_ABORT )
+@@ -6762,8 +6762,8 @@ static bool mgsl_get_raw_rx_frame(struct mgsl_struct *info)
+ 
+ 		status = info->rx_buffer_list[CurrentIndex].status;
+ 
+-		if ( status & (RXSTATUS_SHORT_FRAME + RXSTATUS_OVERRUN +
+-				RXSTATUS_CRC_ERROR + RXSTATUS_ABORT) ) {
++		if ( status & (RXSTATUS_SHORT_FRAME | RXSTATUS_OVERRUN |
++				RXSTATUS_CRC_ERROR | RXSTATUS_ABORT) ) {
+ 			if ( status & RXSTATUS_SHORT_FRAME )
+ 				info->icount.rxshort++;
+ 			else if ( status & RXSTATUS_ABORT )
+@@ -6899,7 +6899,7 @@ static void mgsl_load_tx_dma_buffer(struct mgsl_struct *info,
+ 		/* set CMR:13 to start transmit when
+ 		 * next GoAhead (abort) is received
+ 		 */
+-	 	info->cmr_value |= BIT13;			  
++	 	info->cmr_value |= BIT13;
+ 	}
+ 		
+ 	/* begin loading the frame in the next available tx dma
+@@ -7278,7 +7278,7 @@ static bool mgsl_dma_test( struct mgsl_struct *info )
+ 		
+ 		spin_unlock_irqrestore(&info->irq_spinlock,flags);
+ 
+-						
++
+ 		/******************************/
+ 		/* WAIT FOR TRANSMIT COMPLETE */
+ 		/******************************/
+@@ -7292,7 +7292,7 @@ static bool mgsl_dma_test( struct mgsl_struct *info )
+ 		status = usc_InReg( info, TCSR );
+ 		spin_unlock_irqrestore(&info->irq_spinlock,flags);
+ 
+-		while ( !(status & (BIT6+BIT5+BIT4+BIT2+BIT1)) ) {
++		while ( !(status & (BIT6 | BIT5 | BIT4 | BIT2 | BIT1)) ) {
+ 			if (time_after(jiffies, EndTime)) {
+ 				rc = false;
+ 				break;
+@@ -7307,7 +7307,7 @@ static bool mgsl_dma_test( struct mgsl_struct *info )
+ 
+ 	if ( rc ){
+ 		/* CHECK FOR TRANSMIT ERRORS */
+-		if ( status & (BIT5 + BIT1) ) 
++		if ( status & (BIT5 | BIT1) )
+ 			rc = false;
+ 	}
+ 
+@@ -7333,7 +7333,7 @@ static bool mgsl_dma_test( struct mgsl_struct *info )
+ 		/* CHECK FOR RECEIVE ERRORS */
+ 		status = info->rx_buffer_list[0].status;
+ 
+-		if ( status & (BIT8 + BIT3 + BIT1) ) {
++		if ( status & (BIT8 | BIT3 | BIT1) ) {
+ 			/* receive error has occurred */
+ 			rc = false;
+ 		} else {
+@@ -7605,7 +7605,7 @@ static void usc_loopmode_send_done( struct mgsl_struct * info )
+ {
+  	info->loopmode_send_done_requested = false;
+  	/* clear CMR:13 to 0 to start echoing RxData to TxData */
+- 	info->cmr_value &= ~BIT13;			  
++ 	info->cmr_value &= ~BIT13;
+  	usc_OutReg(info, CMR, info->cmr_value);
+ }
+ 

commit ecda040ff3724f021a96491ecee88d48e968c153
+Author: Alexandru Juncu 
+Date:   Fri Jul 19 11:24:03 2013 +0300
+
+    pcmcia: synclink_cs: replace sum of bitmasks with OR operation.
+    
+    Suggested by coccinelle and manually verified.
+    
+    Signed-off-by: Alexandru Juncu 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
+index 5c5cc00ebb07..d39cca659a3f 100644
+--- a/drivers/char/pcmcia/synclink_cs.c
++++ b/drivers/char/pcmcia/synclink_cs.c
+@@ -1182,14 +1182,14 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id)
+ 		}
+ 		count++;
+ 
+-		if (gis & (BIT1 + BIT0)) {
++		if (gis & (BIT1 | BIT0)) {
+ 			isr = read_reg16(info, CHB + ISR);
+ 			if (isr & IRQ_DCD)
+ 				dcd_change(info, tty);
+ 			if (isr & IRQ_CTS)
+ 				cts_change(info, tty);
+ 		}
+-		if (gis & (BIT3 + BIT2))
++		if (gis & (BIT3 | BIT2))
+ 		{
+ 			isr = read_reg16(info, CHA + ISR);
+ 			if (isr & IRQ_TIMER) {
+@@ -1210,7 +1210,7 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id)
+ 			if (isr & IRQ_RXTIME) {
+ 				issue_command(info, CHA, CMD_RXFIFO_READ);
+ 			}
+-			if (isr & (IRQ_RXEOM + IRQ_RXFIFO)) {
++			if (isr & (IRQ_RXEOM | IRQ_RXFIFO)) {
+ 				if (info->params.mode == MGSL_MODE_HDLC)
+ 					rx_ready_hdlc(info, isr & IRQ_RXEOM);
+ 				else
+@@ -3031,11 +3031,11 @@ static void loopback_enable(MGSLPC_INFO *info)
+ 	unsigned char val;
+ 
+ 	/* CCR1:02..00  CM[2..0] Clock Mode = 111 (clock mode 7) */
+-	val = read_reg(info, CHA + CCR1) | (BIT2 + BIT1 + BIT0);
++	val = read_reg(info, CHA + CCR1) | (BIT2 | BIT1 | BIT0);
+ 	write_reg(info, CHA + CCR1, val);
+ 
+ 	/* CCR2:04 SSEL Clock source select, 1=submode b */
+-	val = read_reg(info, CHA + CCR2) | (BIT4 + BIT5);
++	val = read_reg(info, CHA + CCR2) | (BIT4 | BIT5);
+ 	write_reg(info, CHA + CCR2, val);
+ 
+ 	/* set LinkSpeed if available, otherwise default to 2Mbps */
+@@ -3125,10 +3125,10 @@ static void hdlc_mode(MGSLPC_INFO *info)
+ 		val |= BIT4;
+ 		break;		// FM0
+ 	case HDLC_ENCODING_BIPHASE_MARK:
+-		val |= BIT4 + BIT2;
++		val |= BIT4 | BIT2;
+ 		break;		// FM1
+ 	case HDLC_ENCODING_BIPHASE_LEVEL:
+-		val |= BIT4 + BIT3;
++		val |= BIT4 | BIT3;
+ 		break;		// Manchester
+ 	}
+ 	write_reg(info, CHA + CCR0, val);
+@@ -3185,7 +3185,7 @@ static void hdlc_mode(MGSLPC_INFO *info)
+ 	 */
+ 	val = 0x00;
+ 	if (info->params.crc_type == HDLC_CRC_NONE)
+-		val |= BIT2 + BIT1;
++		val |= BIT2 | BIT1;
+ 	if (info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE)
+ 		val |= BIT5;
+ 	switch (info->params.preamble_length)
+@@ -3197,7 +3197,7 @@ static void hdlc_mode(MGSLPC_INFO *info)
+ 		val |= BIT6;
+ 		break;
+ 	case HDLC_PREAMBLE_LENGTH_64BITS:
+-		val |= BIT7 + BIT6;
++		val |= BIT7 | BIT6;
+ 		break;
+ 	}
+ 	write_reg(info, CHA + CCR3, val);
+@@ -3264,8 +3264,8 @@ static void hdlc_mode(MGSLPC_INFO *info)
+ 		clear_reg_bits(info, CHA + PVR, BIT3);
+ 
+ 	irq_enable(info, CHA,
+-			 IRQ_RXEOM + IRQ_RXFIFO + IRQ_ALLSENT +
+-			 IRQ_UNDERRUN + IRQ_TXFIFO);
++			 IRQ_RXEOM | IRQ_RXFIFO | IRQ_ALLSENT |
++			 IRQ_UNDERRUN | IRQ_TXFIFO);
+ 	issue_command(info, CHA, CMD_TXRESET + CMD_RXRESET);
+ 	wait_command_complete(info, CHA);
+ 	read_reg16(info, CHA + ISR);	/* clear pending IRQs */
+@@ -3582,8 +3582,8 @@ static void async_mode(MGSLPC_INFO *info)
+ 	} else
+ 		clear_reg_bits(info, CHA + PVR, BIT3);
+ 	irq_enable(info, CHA,
+-			  IRQ_RXEOM + IRQ_RXFIFO + IRQ_BREAK_ON + IRQ_RXTIME +
+-			  IRQ_ALLSENT + IRQ_TXFIFO);
++			  IRQ_RXEOM | IRQ_RXFIFO | IRQ_BREAK_ON | IRQ_RXTIME |
++			  IRQ_ALLSENT | IRQ_TXFIFO);
+ 	issue_command(info, CHA, CMD_TXRESET + CMD_RXRESET);
+ 	wait_command_complete(info, CHA);
+ 	read_reg16(info, CHA + ISR);	/* clear pending IRQs */

commit ce01273fed085809458ca8ce078cc0c5145a3db4
+Author: Alexandru Juncu 
+Date:   Fri Jul 12 17:00:18 2013 +0300
+
+    matroxfb: replace kmalloc and memset with kzalloc.
+    
+    Signed-off-by: Alexandru Juncu 
+    Signed-off-by: Tomi Valkeinen 
+
+diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
+index 401a56e250bd..245652911650 100644
+--- a/drivers/video/matrox/matroxfb_base.c
++++ b/drivers/video/matrox/matroxfb_base.c
+@@ -2029,10 +2029,9 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm
+ 		return -1;
+ 	}
+ 
+-	minfo = kmalloc(sizeof(*minfo), GFP_KERNEL);
++	minfo = kzalloc(sizeof(*minfo), GFP_KERNEL);
+ 	if (!minfo)
+ 		return -1;
+-	memset(minfo, 0, sizeof(*minfo));
+ 
+ 	minfo->pcidev = pdev;
+ 	minfo->dead = 0;

commit 6e3d6774a7d59e33bebeb0ef66888bc7dbfed4c7
+Author: Alexandru Juncu 
+Date:   Thu Jul 18 14:36:48 2013 +0300
+
+    mISDN: replace sum of bitmasks with OR operation.
+    
+    Suggested by coccinelle and manually verified.
+    
+    Signed-off-by: Alexandru Juncu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
+index a7e4939787c9..7f910c76ca0a 100644
+--- a/drivers/isdn/hardware/mISDN/hfcpci.c
++++ b/drivers/isdn/hardware/mISDN/hfcpci.c
+@@ -1307,11 +1307,11 @@ mode_hfcpci(struct bchannel *bch, int bc, int protocol)
+ 		}
+ 		if (fifo2 & 2) {
+ 			hc->hw.fifo_en &= ~HFCPCI_FIFOEN_B2;
+-			hc->hw.int_m1 &= ~(HFCPCI_INTS_B2TRANS +
++			hc->hw.int_m1 &= ~(HFCPCI_INTS_B2TRANS |
+ 					   HFCPCI_INTS_B2REC);
+ 		} else {
+ 			hc->hw.fifo_en &= ~HFCPCI_FIFOEN_B1;
+-			hc->hw.int_m1 &= ~(HFCPCI_INTS_B1TRANS +
++			hc->hw.int_m1 &= ~(HFCPCI_INTS_B1TRANS |
+ 					   HFCPCI_INTS_B1REC);
+ 		}
+ #ifdef REVERSE_BITORDER
+@@ -1346,14 +1346,14 @@ mode_hfcpci(struct bchannel *bch, int bc, int protocol)
+ 		if (fifo2 & 2) {
+ 			hc->hw.fifo_en |= HFCPCI_FIFOEN_B2;
+ 			if (!tics)
+-				hc->hw.int_m1 |= (HFCPCI_INTS_B2TRANS +
++				hc->hw.int_m1 |= (HFCPCI_INTS_B2TRANS |
+ 						  HFCPCI_INTS_B2REC);
+ 			hc->hw.ctmt |= 2;
+ 			hc->hw.conn &= ~0x18;
+ 		} else {
+ 			hc->hw.fifo_en |= HFCPCI_FIFOEN_B1;
+ 			if (!tics)
+-				hc->hw.int_m1 |= (HFCPCI_INTS_B1TRANS +
++				hc->hw.int_m1 |= (HFCPCI_INTS_B1TRANS |
+ 						  HFCPCI_INTS_B1REC);
+ 			hc->hw.ctmt |= 1;
+ 			hc->hw.conn &= ~0x03;
+@@ -1375,14 +1375,14 @@ mode_hfcpci(struct bchannel *bch, int bc, int protocol)
+ 		if (fifo2 & 2) {
+ 			hc->hw.last_bfifo_cnt[1] = 0;
+ 			hc->hw.fifo_en |= HFCPCI_FIFOEN_B2;
+-			hc->hw.int_m1 |= (HFCPCI_INTS_B2TRANS +
++			hc->hw.int_m1 |= (HFCPCI_INTS_B2TRANS |
+ 					  HFCPCI_INTS_B2REC);
+ 			hc->hw.ctmt &= ~2;
+ 			hc->hw.conn &= ~0x18;
+ 		} else {
+ 			hc->hw.last_bfifo_cnt[0] = 0;
+ 			hc->hw.fifo_en |= HFCPCI_FIFOEN_B1;
+-			hc->hw.int_m1 |= (HFCPCI_INTS_B1TRANS +
++			hc->hw.int_m1 |= (HFCPCI_INTS_B1TRANS |
+ 					  HFCPCI_INTS_B1REC);
+ 			hc->hw.ctmt &= ~1;
+ 			hc->hw.conn &= ~0x03;

commit f1f996b66cc3908a8f5ffccc2ff41840e92f3b10
+Author: Laura Vasilescu 
+Date:   Mon Mar 19 15:41:15 2012 +0200
+
+    kcore: fix spelling in read_kcore() comment
+    
+    Signed-off-by: Laura Vasilescu 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
+index d245cb23dd72..e5e69aff6c69 100644
+--- a/fs/proc/kcore.c
++++ b/fs/proc/kcore.c
+@@ -513,7 +513,7 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
+ 
+ 				n = copy_to_user(buffer, (char *)start, tsz);
+ 				/*
+-				 * We cannot distingush between fault on source
++				 * We cannot distinguish between fault on source
+ 				 * and fault on destination. When this happens
+ 				 * we clear too and hope it will trigger the
+ 				 * EFAULT again.

commit 23b41168fc942a4a041325a04ecc1bd17d031a3e
+Author: Vlad Dogaru 
+Date:   Sat Feb 26 22:39:12 2011 +0000
+
+    netdevice: make initial group visible to userspace
+    
+    INIT_NETDEV_GROUP is needed by userspace, move it outside __KERNEL__
+    guards.
+    
+    Signed-off-by: Vlad Dogaru 
+    Signed-off-by: David S. Miller 
+
+diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
+index ffe56c16df8a..8be4056ad251 100644
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -75,9 +75,6 @@ struct wireless_dev;
+ #define NET_RX_SUCCESS		0	/* keep 'em coming, baby */
+ #define NET_RX_DROP		1	/* packet dropped */
+ 
+-/* Initial net device group. All devices belong to group 0 by default. */
+-#define INIT_NETDEV_GROUP	0
+-
+ /*
+  * Transmit return codes: transmit return codes originate from three different
+  * namespaces:
+@@ -141,6 +138,9 @@ static inline bool dev_xmit_complete(int rc)
+ 
+ #define MAX_ADDR_LEN	32		/* Largest hardware address length */
+ 
++/* Initial net device group. All devices belong to group 0 by default. */
++#define INIT_NETDEV_GROUP	0
++
+ #ifdef  __KERNEL__
+ /*
+  *	Compute the worst case header length according to the protocols

commit a512b92b3af4b03fc6834617a042dc85fbd4e34e
+Author: Vlad Dogaru 
+Date:   Mon Jan 24 03:37:29 2011 +0000
+
+    net: add sysfs entry for device group
+    
+    The group of a network device can be queried or changed from userspace
+    using sysfs.
+    
+    For example, considering sysfs mounted in /sys, one can change the group
+    that interface lo belongs to:
+            echo 1 > /sys/class/net/lo/group
+    
+    Signed-off-by: Vlad Dogaru 
+    Acked-by: Stephen Hemminger 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
+index 81367ccf3306..2e4a393dfc3b 100644
+--- a/net/core/net-sysfs.c
++++ b/net/core/net-sysfs.c
+@@ -295,6 +295,20 @@ static ssize_t show_ifalias(struct device *dev,
+ 	return ret;
+ }
+ 
++NETDEVICE_SHOW(group, fmt_dec);
++
++static int change_group(struct net_device *net, unsigned long new_group)
++{
++	dev_set_group(net, (int) new_group);
++	return 0;
++}
++
++static ssize_t store_group(struct device *dev, struct device_attribute *attr,
++			 const char *buf, size_t len)
++{
++	return netdev_store(dev, attr, buf, len, change_group);
++}
++
+ static struct device_attribute net_class_attributes[] = {
+ 	__ATTR(addr_assign_type, S_IRUGO, show_addr_assign_type, NULL),
+ 	__ATTR(addr_len, S_IRUGO, show_addr_len, NULL),
+@@ -316,6 +330,7 @@ static struct device_attribute net_class_attributes[] = {
+ 	__ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags),
+ 	__ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len,
+ 	       store_tx_queue_len),
++	__ATTR(group, S_IRUGO | S_IWUSR, show_group, store_group),
+ 	{}
+ };
+ 

commit e7ed828f10bd89a28f821ae7f20e691704d61923
+Author: Vlad Dogaru 
+Date:   Thu Jan 13 23:38:31 2011 +0000
+
+    netlink: support setting devgroup parameters
+    
+    If a rtnetlink request specifies a negative or zero ifindex and has no
+    interface name attribute, but has a group attribute, then the chenges
+    are made to all the interfaces belonging to the specified group.
+    
+    Signed-off-by: Vlad Dogaru 
+    Acked-by: Jamal Hadi Salim 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
+index 09062b07bf7f..a0b2eeb3b610 100644
+--- a/net/core/rtnetlink.c
++++ b/net/core/rtnetlink.c
+@@ -1558,6 +1558,24 @@ struct net_device *rtnl_create_link(struct net *src_net, struct net *net,
+ }
+ EXPORT_SYMBOL(rtnl_create_link);
+ 
++static int rtnl_group_changelink(struct net *net, int group,
++		struct ifinfomsg *ifm,
++		struct nlattr **tb)
++{
++	struct net_device *dev;
++	int err;
++
++	for_each_netdev(net, dev) {
++		if (dev->group == group) {
++			err = do_setlink(dev, ifm, tb, NULL, 0);
++			if (err < 0)
++				return err;
++		}
++	}
++
++	return 0;
++}
++
+ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+ 	struct net *net = sock_net(skb->sk);
+@@ -1585,10 +1603,16 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ 	ifm = nlmsg_data(nlh);
+ 	if (ifm->ifi_index > 0)
+ 		dev = __dev_get_by_index(net, ifm->ifi_index);
+-	else if (ifname[0])
+-		dev = __dev_get_by_name(net, ifname);
+-	else
+-		dev = NULL;
++	else {
++		if (ifname[0])
++			dev = __dev_get_by_name(net, ifname);
++		else if (tb[IFLA_GROUP])
++			return rtnl_group_changelink(net,
++					nla_get_u32(tb[IFLA_GROUP]),
++					ifm, tb);
++		else
++			dev = NULL;
++	}
+ 
+ 	err = validate_linkmsg(dev, tb);
+ 	if (err < 0)

commit cbda10fa97d72c7a1923be4426171aa90e8c6dab
+Author: Vlad Dogaru 
+Date:   Thu Jan 13 23:38:30 2011 +0000
+
+    net_device: add support for network device groups
+    
+    Net devices can now be grouped, enabling simpler manipulation from
+    userspace. This patch adds a group field to the net_device structure, as
+    well as rtnetlink support to query and modify it.
+    
+    Signed-off-by: Vlad Dogaru 
+    Acked-by: Jamal Hadi Salim 
+    Signed-off-by: David S. Miller 
+
+diff --git a/include/linux/if_link.h b/include/linux/if_link.h
+index 6485d2a89bec..f4a2e6b1b864 100644
+--- a/include/linux/if_link.h
++++ b/include/linux/if_link.h
+@@ -135,6 +135,7 @@ enum {
+ 	IFLA_VF_PORTS,
+ 	IFLA_PORT_SELF,
+ 	IFLA_AF_SPEC,
++	IFLA_GROUP,		/* Group the device belongs to */
+ 	__IFLA_MAX
+ };
+ 
+diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
+index d971346b0340..68a4627b74f5 100644
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -75,6 +75,9 @@ struct wireless_dev;
+ #define NET_RX_SUCCESS		0	/* keep 'em coming, baby */
+ #define NET_RX_DROP		1	/* packet dropped */
+ 
++/* Initial net device group. All devices belong to group 0 by default. */
++#define INIT_NETDEV_GROUP	0
++
+ /*
+  * Transmit return codes: transmit return codes originate from three different
+  * namespaces:
+@@ -1153,6 +1156,9 @@ struct net_device {
+ 
+ 	/* phy device may attach itself for hardware timestamping */
+ 	struct phy_device *phydev;
++
++	/* group the device belongs to */
++	int group;
+ };
+ #define to_net_dev(d) container_of(d, struct net_device, dev)
+ 
+@@ -1844,6 +1850,7 @@ extern int		dev_set_alias(struct net_device *, const char *, size_t);
+ extern int		dev_change_net_namespace(struct net_device *,
+ 						 struct net *, const char *);
+ extern int		dev_set_mtu(struct net_device *, int);
++extern void		dev_set_group(struct net_device *, int);
+ extern int		dev_set_mac_address(struct net_device *,
+ 					    struct sockaddr *);
+ extern int		dev_hard_start_xmit(struct sk_buff *skb,
+diff --git a/net/core/dev.c b/net/core/dev.c
+index 7741507429f4..2b85d4ae981f 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -4571,6 +4571,17 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
+ }
+ EXPORT_SYMBOL(dev_set_mtu);
+ 
++/**
++ *	dev_set_group - Change group this device belongs to
++ *	@dev: device
++ *	@new_group: group this device should belong to
++ */
++void dev_set_group(struct net_device *dev, int new_group)
++{
++	dev->group = new_group;
++}
++EXPORT_SYMBOL(dev_set_group);
++
+ /**
+  *	dev_set_mac_address - Change Media Access Control Address
+  *	@dev: device
+@@ -5678,6 +5689,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
+ 	dev->priv_flags = IFF_XMIT_DST_RELEASE;
+ 	setup(dev);
+ 	strcpy(dev->name, name);
++	dev->group = INIT_NETDEV_GROUP;
+ 	return dev;
+ 
+ free_pcpu:
+diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
+index a5f7535aab5b..09062b07bf7f 100644
+--- a/net/core/rtnetlink.c
++++ b/net/core/rtnetlink.c
+@@ -868,6 +868,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
+ 		   netif_running(dev) ? dev->operstate : IF_OPER_DOWN);
+ 	NLA_PUT_U8(skb, IFLA_LINKMODE, dev->link_mode);
+ 	NLA_PUT_U32(skb, IFLA_MTU, dev->mtu);
++	NLA_PUT_U32(skb, IFLA_GROUP, dev->group);
+ 
+ 	if (dev->ifindex != dev->iflink)
+ 		NLA_PUT_U32(skb, IFLA_LINK, dev->iflink);
+@@ -1265,6 +1266,11 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
+ 		modified = 1;
+ 	}
+ 
++	if (tb[IFLA_GROUP]) {
++		dev_set_group(dev, nla_get_u32(tb[IFLA_GROUP]));
++		modified = 1;
++	}
++
+ 	/*
+ 	 * Interface selected by interface index but interface
+ 	 * name provided implies that a name change has been

\ No newline at end of file diff --git a/detail/4.html b/detail/4.html new file mode 100644 index 0000000..e11f39f --- /dev/null +++ b/detail/4.html @@ -0,0 +1,91575 @@ +

Patches contributed by University of Michigan - Ann Arbor


commit 2285eb2f2429daadf9d57f08137b472139470aa9
+Author: Trevor Gross 
+Date:   Thu Aug 3 02:04:37 2023 -0400
+
+    docs: rust: clarify what 'rustup override' does
+    
+    The behavior of 'rustup override' is not very well known. Add a small
+    note about what it does, so users have a better understanding of how it
+    affects their system toolchain (i.e., it does not affect system
+    toolchain and only sets a directory-specific override).
+    
+    Signed-off-by: Trevor Gross 
+    Reviewed-by: Martin Rodriguez Reboredo 
+    Reviewed-by: Alice Ryhl 
+    Link: https://lore.kernel.org/r/20230803060437.12157-3-tmgross@umich.edu
+    [ Undid the `:` to `::` change. ]
+    Signed-off-by: Miguel Ojeda 
+
+diff --git a/Documentation/rust/quick-start.rst b/Documentation/rust/quick-start.rst
+index a0a47a6f216b..f382914f4191 100644
+--- a/Documentation/rust/quick-start.rst
++++ b/Documentation/rust/quick-start.rst
+@@ -38,7 +38,9 @@ and run::
+ 
+ 	rustup override set $(scripts/min-tool-version.sh rustc)
+ 
+-Otherwise, fetch a standalone installer from:
++This will configure your working directory to use the correct version of
++``rustc`` without affecting your default toolchain. If you are not using
++``rustup``, fetch a standalone installer from:
+ 
+ 	https://forge.rust-lang.org/infra/other-installation-methods.html#standalone
+ 

commit 8cb40124cf923d4627d2e29b84dbff72e41fa0ef
+Author: Trevor Gross 
+Date:   Thu Aug 3 02:04:36 2023 -0400
+
+    docs: rust: update instructions for obtaining 'core' source
+    
+    The source for Rust's 'core' library is needed to build the kernel with
+    Rust support. This sometimes needs to be obtained by hand when using a
+    standalone version of 'rustc' not managed by 'rustup'. Currently, the
+    documentation suggests cloning the 'rust' repository to obtain these
+    sources, but this is quite slow (on the order of a multiple minutes).
+    
+    Change this documentation to suggest using the source tarball instead.
+    The tarball includes only needed files (<5M) and is significantly faster
+    to download; this is more in line with what 'rustup' does.
+    
+    Also simplify wording of the relevant section.
+    
+    Link: https://github.com/Rust-for-Linux/linux/pull/1024
+    Signed-off-by: Trevor Gross 
+    Reviewed-by: Martin Rodriguez Reboredo 
+    Reviewed-by: Alice Ryhl 
+    Link: https://lore.kernel.org/r/20230803060437.12157-2-tmgross@umich.edu
+    Signed-off-by: Miguel Ojeda 
+
+diff --git a/Documentation/rust/quick-start.rst b/Documentation/rust/quick-start.rst
+index 1274cd74f767..a0a47a6f216b 100644
+--- a/Documentation/rust/quick-start.rst
++++ b/Documentation/rust/quick-start.rst
+@@ -56,16 +56,17 @@ If ``rustup`` is being used, run::
+ The components are installed per toolchain, thus upgrading the Rust compiler
+ version later on requires re-adding the component.
+ 
+-Otherwise, if a standalone installer is used, the Rust repository may be cloned
+-into the installation folder of the toolchain::
++Otherwise, if a standalone installer is used, the Rust source tree may be
++downloaded into the toolchain's installation folder::
+ 
+-	git clone --recurse-submodules \
+-		--branch $(scripts/min-tool-version.sh rustc) \
+-		https://github.com/rust-lang/rust \
+-		$(rustc --print sysroot)/lib/rustlib/src/rust
++	curl -L "https://static.rust-lang.org/dist/rust-src-$(scripts/min-tool-version.sh rustc).tar.gz" |
++		tar -xzf - -C "$(rustc --print sysroot)/lib" \
++		"rust-src-$(scripts/min-tool-version.sh rustc)/rust-src/lib/" \
++		--strip-components=3
+ 
+ In this case, upgrading the Rust compiler version later on requires manually
+-updating this clone.
++updating the source tree (this can be done by removing ``$(rustc --print
++sysroot)/lib/rustlib/src/rust`` then rerunning the above command).
+ 
+ 
+ libclang

commit f8bc1b2efa05183f10451b7618243a4278bf6b16
+Author: Spencer E. Olson 
+Date:   Tue Dec 4 12:07:50 2018 -0700
+
+    staging: comedi: change do_insn*_ioctl to allow more samples
+    
+    Changes do_insn*_ioctl functions to allow for data lengths for each
+    comedi_insn of up to 2^16.  This patch also changes these functions to only
+    allocate as much memory as is necessary for each comedi_insn, rather than
+    allocating a fixed-sized scratch space.
+    
+    In testing some user-space code for the new INSN_DEVICE_CONFIG_GET_ROUTES
+    facility with some newer hardware, I discovered that do_insn_ioctl and
+    do_insnlist_ioctl limited the amount of data that can be passed into the
+    kernel for insn's to a length of 256.  For some newer hardware, the number
+    of routes can be greater than 1000.  Working around the old limits (256)
+    would complicate the user-space/kernel interaction.
+    
+    The new upper limit is reasonable with current memory available and does
+    not otherwise impact the memory footprint for any current or otherwise
+    typical configuration.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
+index ceb6ba5dd57c..5d2fcbfe02af 100644
+--- a/drivers/staging/comedi/comedi_fops.c
++++ b/drivers/staging/comedi/comedi_fops.c
+@@ -1501,25 +1501,21 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn,
+  *	data (for reads) to insns[].data pointers
+  */
+ /* arbitrary limits */
+-#define MAX_SAMPLES 256
++#define MIN_SAMPLES 16
++#define MAX_SAMPLES 65536
+ static int do_insnlist_ioctl(struct comedi_device *dev,
+ 			     struct comedi_insnlist __user *arg, void *file)
+ {
+ 	struct comedi_insnlist insnlist;
+ 	struct comedi_insn *insns = NULL;
+ 	unsigned int *data = NULL;
++	unsigned int max_n_data_required = MIN_SAMPLES;
+ 	int i = 0;
+ 	int ret = 0;
+ 
+ 	if (copy_from_user(&insnlist, arg, sizeof(insnlist)))
+ 		return -EFAULT;
+ 
+-	data = kmalloc_array(MAX_SAMPLES, sizeof(unsigned int), GFP_KERNEL);
+-	if (!data) {
+-		ret = -ENOMEM;
+-		goto error;
+-	}
+-
+ 	insns = kcalloc(insnlist.n_insns, sizeof(*insns), GFP_KERNEL);
+ 	if (!insns) {
+ 		ret = -ENOMEM;
+@@ -1533,13 +1529,26 @@ static int do_insnlist_ioctl(struct comedi_device *dev,
+ 		goto error;
+ 	}
+ 
+-	for (i = 0; i < insnlist.n_insns; i++) {
++	/* Determine maximum memory needed for all instructions. */
++	for (i = 0; i < insnlist.n_insns; ++i) {
+ 		if (insns[i].n > MAX_SAMPLES) {
+ 			dev_dbg(dev->class_dev,
+ 				"number of samples too large\n");
+ 			ret = -EINVAL;
+ 			goto error;
+ 		}
++		max_n_data_required = max(max_n_data_required, insns[i].n);
++	}
++
++	/* Allocate scratch space for all instruction data. */
++	data = kmalloc_array(max_n_data_required, sizeof(unsigned int),
++			     GFP_KERNEL);
++	if (!data) {
++		ret = -ENOMEM;
++		goto error;
++	}
++
++	for (i = 0; i < insnlist.n_insns; ++i) {
+ 		if (insns[i].insn & INSN_MASK_WRITE) {
+ 			if (copy_from_user(data, insns[i].data,
+ 					   insns[i].n * sizeof(unsigned int))) {
+@@ -1593,22 +1602,27 @@ static int do_insn_ioctl(struct comedi_device *dev,
+ {
+ 	struct comedi_insn insn;
+ 	unsigned int *data = NULL;
++	unsigned int n_data = MIN_SAMPLES;
+ 	int ret = 0;
+ 
+-	data = kmalloc_array(MAX_SAMPLES, sizeof(unsigned int), GFP_KERNEL);
+-	if (!data) {
+-		ret = -ENOMEM;
+-		goto error;
+-	}
+-
+ 	if (copy_from_user(&insn, arg, sizeof(insn))) {
+-		ret = -EFAULT;
+-		goto error;
++		return -EFAULT;
+ 	}
+ 
++	n_data = max(n_data, insn.n);
++
+ 	/* This is where the behavior of insn and insnlist deviate. */
+-	if (insn.n > MAX_SAMPLES)
++	if (insn.n > MAX_SAMPLES) {
+ 		insn.n = MAX_SAMPLES;
++		n_data = MAX_SAMPLES;
++	}
++
++	data = kmalloc_array(n_data, sizeof(unsigned int), GFP_KERNEL);
++	if (!data) {
++		ret = -ENOMEM;
++		goto error;
++	}
++
+ 	if (insn.insn & INSN_MASK_WRITE) {
+ 		if (copy_from_user(data,
+ 				   insn.data,

commit 4dc2a3cd27856531cf92762fea2eb9468efe552f
+Author: Spencer E. Olson 
+Date:   Wed Oct 24 08:33:40 2018 -0600
+
+    staging: comedi: clarify/unify macros for NI macro-defined terminals
+    
+    Uses a single macro to define multiple macros that represent a series of
+    terminals for NI devices.  This patch also redefines NI_MAX_COUNTERS as the
+    maximum number of counters possible on NI devices (instead of the maximum
+    index of the counters).  This was a little confusing and caused a bug in
+    commit 347e244884c3b ("staging: comedi: tio: implement global tio/ctr routing")
+    when setting/reading registers for counter terminals.
+    
+    Fixes: 347e244884c3b ("staging: comedi: tio: implement global tio/ctr routing")
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
+index e90b17775284..09a940066c0e 100644
+--- a/drivers/staging/comedi/comedi.h
++++ b/drivers/staging/comedi/comedi.h
+@@ -1005,35 +1005,38 @@ enum i8254_mode {
+  * and INSN_DEVICE_CONFIG_GET_ROUTES.
+  */
+ #define NI_NAMES_BASE	0x8000u
++
++#define _TERM_N(base, n, x)	((base) + ((x) & ((n) - 1)))
++
+ /*
+  * not necessarily all allowed 64 PFIs are valid--certainly not for all devices
+  */
+-#define NI_PFI(x)	(NI_NAMES_BASE        + ((x) & 0x3f))
++#define NI_PFI(x)		_TERM_N(NI_NAMES_BASE, 64, x)
+ /* 8 trigger lines by standard, Some devices cannot talk to all eight. */
+-#define TRIGGER_LINE(x)	(NI_PFI(-1)       + 1 + ((x) & 0x7))
++#define TRIGGER_LINE(x)		_TERM_N(NI_PFI(-1) + 1, 8, x)
+ /* 4 RTSI shared MUXes to route signals to/from TRIGGER_LINES on NI hardware */
+-#define NI_RTSI_BRD(x)	(TRIGGER_LINE(-1) + 1 + ((x) & 0x3))
++#define NI_RTSI_BRD(x)		_TERM_N(TRIGGER_LINE(-1) + 1, 4, x)
+ 
+ /* *** Counter/timer names : 8 counters max *** */
+-#define NI_COUNTER_NAMES_BASE  (NI_RTSI_BRD(-1)  + 1)
+-#define NI_MAX_COUNTERS	       7
+-#define NI_CtrSource(x)	       (NI_COUNTER_NAMES_BASE + ((x) & NI_MAX_COUNTERS))
++#define NI_MAX_COUNTERS		8
++#define NI_COUNTER_NAMES_BASE	(NI_RTSI_BRD(-1)  + 1)
++#define NI_CtrSource(x)	      _TERM_N(NI_COUNTER_NAMES_BASE, NI_MAX_COUNTERS, x)
+ /* Gate, Aux, A,B,Z are all treated, at times as gates */
+-#define NI_GATES_NAMES_BASE    (NI_CtrSource(-1) + 1)
+-#define NI_CtrGate(x)	       (NI_GATES_NAMES_BASE   + ((x) & NI_MAX_COUNTERS))
+-#define NI_CtrAux(x)	       (NI_CtrGate(-1)   + 1  + ((x) & NI_MAX_COUNTERS))
+-#define NI_CtrA(x)	       (NI_CtrAux(-1)    + 1  + ((x) & NI_MAX_COUNTERS))
+-#define NI_CtrB(x)	       (NI_CtrA(-1)      + 1  + ((x) & NI_MAX_COUNTERS))
+-#define NI_CtrZ(x)	       (NI_CtrB(-1)      + 1  + ((x) & NI_MAX_COUNTERS))
+-#define NI_GATES_NAMES_MAX     NI_CtrZ(-1)
+-#define NI_CtrArmStartTrigger(x) (NI_CtrZ(-1)    + 1  + ((x) & NI_MAX_COUNTERS))
++#define NI_GATES_NAMES_BASE	(NI_CtrSource(-1) + 1)
++#define NI_CtrGate(x)		_TERM_N(NI_GATES_NAMES_BASE, NI_MAX_COUNTERS, x)
++#define NI_CtrAux(x)		_TERM_N(NI_CtrGate(-1)  + 1, NI_MAX_COUNTERS, x)
++#define NI_CtrA(x)		_TERM_N(NI_CtrAux(-1)   + 1, NI_MAX_COUNTERS, x)
++#define NI_CtrB(x)		_TERM_N(NI_CtrA(-1)     + 1, NI_MAX_COUNTERS, x)
++#define NI_CtrZ(x)		_TERM_N(NI_CtrB(-1)     + 1, NI_MAX_COUNTERS, x)
++#define NI_GATES_NAMES_MAX	NI_CtrZ(-1)
++#define NI_CtrArmStartTrigger(x) _TERM_N(NI_CtrZ(-1)    + 1, NI_MAX_COUNTERS, x)
+ #define NI_CtrInternalOutput(x) \
+-		     (NI_CtrArmStartTrigger(-1)  + 1  + ((x) & NI_MAX_COUNTERS))
++		      _TERM_N(NI_CtrArmStartTrigger(-1) + 1, NI_MAX_COUNTERS, x)
+ /** external pin(s) labeled conveniently as CtrOut. */
+-#define NI_CtrOut(x)  (NI_CtrInternalOutput(-1)  + 1  + ((x) & NI_MAX_COUNTERS))
++#define NI_CtrOut(x)   _TERM_N(NI_CtrInternalOutput(-1) + 1, NI_MAX_COUNTERS, x)
+ /** For Buffered sampling of ctr -- x series capability. */
+-#define NI_CtrSampleClock(x)	(NI_CtrOut(-1)   + 1  + ((x) & NI_MAX_COUNTERS))
+-#define NI_COUNTER_NAMES_MAX   NI_CtrSampleClock(-1)
++#define NI_CtrSampleClock(x)	_TERM_N(NI_CtrOut(-1)   + 1, NI_MAX_COUNTERS, x)
++#define NI_COUNTER_NAMES_MAX	NI_CtrSampleClock(-1)
+ 
+ enum ni_common_signal_names {
+ 	/* PXI_Star: this is a non-NI-specific signal */

commit 9a1ec4eb6f3722a65a267bb7d14c371d73f66c5b
+Author: Spencer E. Olson 
+Date:   Wed Oct 24 08:46:59 2018 -0600
+
+    staging: comedi: ni_mio_common: scale ao INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS
+    
+    Fixes implementation of INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS for
+    ni_mio devices.  The previous patch should have used the channel
+    information passed in to scale the result by the number of channels being
+    used.
+    
+    Fixes: 51fd36738383 ("staging: comedi: ni_mio_common: implement INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS")
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index 2d1e0325d04d..5edf59ac6706 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -2843,7 +2843,8 @@ static int ni_ao_insn_config(struct comedi_device *dev,
+ 		return ni_ao_arm(dev, s);
+ 	case INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS:
+ 		/* we don't care about actual channels */
+-		data[1] = board->ao_speed;
++		/* data[3] : chanlist_len */
++		data[1] = board->ao_speed * data[3];
+ 		data[2] = 0;
+ 		return 0;
+ 	default:

commit fa86c00799ee1fb851261a0ef904200ecd9c8215
+Author: Spencer E. Olson 
+Date:   Wed Oct 3 14:56:12 2018 -0600
+
+    staging: comedi: ni_660x: add device-global routing
+    
+    Provides the device-global routing interface for ni_660x devices.  Using
+    the device-global names in comedi_cmd structures for commands was already
+    supported through the ni_tio module.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
+index 59055f366138..e70a461e723f 100644
+--- a/drivers/staging/comedi/drivers/ni_660x.c
++++ b/drivers/staging/comedi/drivers/ni_660x.c
+@@ -568,6 +568,10 @@ static void ni_660x_select_pfi_output(struct comedi_device *dev,
+ 	unsigned int idle_chip = 0;
+ 	unsigned int bits;
+ 
++	if (chan >= NI_PFI(0))
++		/* allow new and old names of pfi channels to work. */
++		chan -= NI_PFI(0);
++
+ 	if (board->n_chips > 1) {
+ 		if (out_sel == NI_660X_PFI_OUTPUT_COUNTER &&
+ 		    chan >= 8 && chan <= 23) {
+@@ -603,6 +607,10 @@ static void ni_660x_set_pfi_direction(struct comedi_device *dev,
+ 	struct ni_660x_private *devpriv = dev->private;
+ 	u64 bit;
+ 
++	if (chan >= NI_PFI(0))
++		/* allow new and old names of pfi channels to work. */
++		chan -= NI_PFI(0);
++
+ 	bit = 1ULL << chan;
+ 
+ 	if (direction == COMEDI_OUTPUT) {
+@@ -622,6 +630,10 @@ static unsigned int ni_660x_get_pfi_direction(struct comedi_device *dev,
+ 	struct ni_660x_private *devpriv = dev->private;
+ 	u64 bit;
+ 
++	if (chan >= NI_PFI(0))
++		/* allow new and old names of pfi channels to work. */
++		chan -= NI_PFI(0);
++
+ 	bit = 1ULL << chan;
+ 
+ 	return (devpriv->io_dir & bit) ? COMEDI_OUTPUT : COMEDI_INPUT;
+@@ -632,6 +644,10 @@ static int ni_660x_set_pfi_routing(struct comedi_device *dev,
+ {
+ 	struct ni_660x_private *devpriv = dev->private;
+ 
++	if (chan >= NI_PFI(0))
++		/* allow new and old names of pfi channels to work. */
++		chan -= NI_PFI(0);
++
+ 	switch (source) {
+ 	case NI_660X_PFI_OUTPUT_COUNTER:
+ 		if (chan < 8)
+@@ -654,6 +670,10 @@ static int ni_660x_get_pfi_routing(struct comedi_device *dev, unsigned int chan)
+ {
+ 	struct ni_660x_private *devpriv = dev->private;
+ 
++	if (chan >= NI_PFI(0))
++		/* allow new and old names of pfi channels to work. */
++		chan -= NI_PFI(0);
++
+ 	return devpriv->io_cfg[chan];
+ }
+ 
+@@ -662,6 +682,10 @@ static void ni_660x_set_pfi_filter(struct comedi_device *dev,
+ {
+ 	unsigned int val;
+ 
++	if (chan >= NI_PFI(0))
++		/* allow new and old names of pfi channels to work. */
++		chan -= NI_PFI(0);
++
+ 	val = ni_660x_read(dev, 0, NI660X_IO_CFG(chan));
+ 	val &= ~NI660X_IO_CFG_IN_SEL_MASK(chan);
+ 	val |= NI660X_IO_CFG_IN_SEL(chan, value);
+@@ -710,6 +734,240 @@ static int ni_660x_dio_insn_config(struct comedi_device *dev,
+ 	return insn->n;
+ }
+ 
++static unsigned int _ni_get_valid_routes(struct comedi_device *dev,
++					 unsigned int n_pairs,
++					 unsigned int *pair_data)
++{
++	struct ni_660x_private *devpriv = dev->private;
++
++	return ni_get_valid_routes(&devpriv->routing_tables, n_pairs,
++				   pair_data);
++}
++
++/*
++ * Retrieves the current source of the output selector for the given
++ * destination.  If the terminal for the destination is not already configured
++ * as an output, this function returns -EINVAL as error.
++ *
++ * Return: The register value of the destination output selector;
++ *	   -EINVAL if terminal is not configured for output.
++ */
++static inline int get_output_select_source(int dest, struct comedi_device *dev)
++{
++	struct ni_660x_private *devpriv = dev->private;
++	int reg = -1;
++
++	if (channel_is_pfi(dest)) {
++		if (ni_660x_get_pfi_direction(dev, dest) == COMEDI_OUTPUT)
++			reg = ni_660x_get_pfi_routing(dev, dest);
++	} else if (channel_is_rtsi(dest)) {
++		dev_dbg(dev->class_dev,
++			"%s: unhandled rtsi destination (%d) queried\n",
++			__func__, dest);
++		/*
++		 * The following can be enabled when RTSI routing info is
++		 * determined (not currently documented):
++		 * if (ni_get_rtsi_direction(dev, dest) == COMEDI_OUTPUT) {
++		 *	reg = ni_get_rtsi_routing(dev, dest);
++
++		 *	if (reg == NI_RTSI_OUTPUT_RGOUT0) {
++		 *		dest = NI_RGOUT0; ** prepare for lookup below **
++		 *		reg = get_rgout0_reg(dev);
++		 *	} else if (reg >= NI_RTSI_OUTPUT_RTSI_BRD(0) &&
++		 *		   reg <= NI_RTSI_OUTPUT_RTSI_BRD(3)) {
++		 *		const int i = reg - NI_RTSI_OUTPUT_RTSI_BRD(0);
++
++		 *		dest = NI_RTSI_BRD(i); ** prepare for lookup **
++		 *		reg = get_ith_rtsi_brd_reg(i, dev);
++		 *	}
++		 * }
++		 */
++	} else if (channel_is_ctr(dest)) {
++		reg = ni_tio_get_routing(devpriv->counter_dev, dest);
++	} else {
++		dev_dbg(dev->class_dev,
++			"%s: unhandled destination (%d) queried\n",
++			__func__, dest);
++	}
++
++	if (reg >= 0)
++		return ni_find_route_source(CR_CHAN(reg), dest,
++					    &devpriv->routing_tables);
++	return -EINVAL;
++}
++
++/*
++ * Test a route:
++ *
++ * Return: -1 if not connectible;
++ *	    0 if connectible and not connected;
++ *	    1 if connectible and connected.
++ */
++static inline int test_route(unsigned int src, unsigned int dest,
++			     struct comedi_device *dev)
++{
++	struct ni_660x_private *devpriv = dev->private;
++	s8 reg = ni_route_to_register(CR_CHAN(src), dest,
++				      &devpriv->routing_tables);
++
++	if (reg < 0)
++		return -1;
++	if (get_output_select_source(dest, dev) != CR_CHAN(src))
++		return 0;
++	return 1;
++}
++
++/* Connect the actual route.  */
++static inline int connect_route(unsigned int src, unsigned int dest,
++				struct comedi_device *dev)
++{
++	struct ni_660x_private *devpriv = dev->private;
++	s8 reg = ni_route_to_register(CR_CHAN(src), dest,
++				      &devpriv->routing_tables);
++	s8 current_src;
++
++	if (reg < 0)
++		/* route is not valid */
++		return -EINVAL;
++
++	current_src = get_output_select_source(dest, dev);
++	if (current_src == CR_CHAN(src))
++		return -EALREADY;
++	if (current_src >= 0)
++		/* destination mux is already busy. complain, don't overwrite */
++		return -EBUSY;
++
++	/* The route is valid and available. Now connect... */
++	if (channel_is_pfi(CR_CHAN(dest))) {
++		/*
++		 * set routing and then direction so that the output does not
++		 * first get generated with the wrong pin
++		 */
++		ni_660x_set_pfi_routing(dev, dest, reg);
++		ni_660x_set_pfi_direction(dev, dest, COMEDI_OUTPUT);
++	} else if (channel_is_rtsi(CR_CHAN(dest))) {
++		dev_dbg(dev->class_dev, "%s: unhandled rtsi destination (%d)\n",
++			__func__, dest);
++		return -EINVAL;
++		/*
++		 * The following can be enabled when RTSI routing info is
++		 * determined (not currently documented):
++		 * if (reg == NI_RTSI_OUTPUT_RGOUT0) {
++		 *	int ret = incr_rgout0_src_use(src, dev);
++
++		 *	if (ret < 0)
++		 *		return ret;
++		 * } else if (ni_rtsi_route_requires_mux(reg)) {
++		 *	** Attempt to allocate and  route (src->brd) **
++		 *	int brd = incr_rtsi_brd_src_use(src, dev);
++
++		 *	if (brd < 0)
++		 *		return brd;
++
++		 *	** Now lookup the register value for (brd->dest) **
++		 *	reg = ni_lookup_route_register(brd, CR_CHAN(dest),
++		 *				       &devpriv->routing_tables);
++		 * }
++
++		 * ni_set_rtsi_direction(dev, dest, COMEDI_OUTPUT);
++		 * ni_set_rtsi_routing(dev, dest, reg);
++		 */
++	} else if (channel_is_ctr(CR_CHAN(dest))) {
++		/*
++		 * we are adding back the channel modifier info to set
++		 * invert/edge info passed by the user
++		 */
++		ni_tio_set_routing(devpriv->counter_dev, dest,
++				   reg | (src & ~CR_CHAN(-1)));
++	} else {
++		return -EINVAL;
++	}
++	return 0;
++}
++
++static inline int disconnect_route(unsigned int src, unsigned int dest,
++				   struct comedi_device *dev)
++{
++	struct ni_660x_private *devpriv = dev->private;
++	s8 reg = ni_route_to_register(CR_CHAN(src), CR_CHAN(dest),
++				      &devpriv->routing_tables);
++
++	if (reg < 0)
++		/* route is not valid */
++		return -EINVAL;
++	if (get_output_select_source(dest, dev) != CR_CHAN(src))
++		/* cannot disconnect something not connected */
++		return -EINVAL;
++
++	/* The route is valid and is connected.  Now disconnect... */
++	if (channel_is_pfi(CR_CHAN(dest))) {
++		unsigned int source = ((CR_CHAN(dest) - NI_PFI(0)) < 8)
++					? NI_660X_PFI_OUTPUT_DIO
++					: NI_660X_PFI_OUTPUT_COUNTER;
++
++		/* set the pfi to high impedance, and disconnect */
++		ni_660x_set_pfi_direction(dev, dest, COMEDI_INPUT);
++		ni_660x_set_pfi_routing(dev, dest, source);
++	} else if (channel_is_rtsi(CR_CHAN(dest))) {
++		dev_dbg(dev->class_dev, "%s: unhandled rtsi destination (%d)\n",
++			__func__, dest);
++		return -EINVAL;
++		/*
++		 * The following can be enabled when RTSI routing info is
++		 * determined (not currently documented):
++		 * if (reg == NI_RTSI_OUTPUT_RGOUT0) {
++		 *	int ret = decr_rgout0_src_use(src, dev);
++
++		 *	if (ret < 0)
++		 *		return ret;
++		 * } else if (ni_rtsi_route_requires_mux(reg)) {
++		 *	** find which RTSI_BRD line is source for rtsi pin **
++		 *	int brd = ni_find_route_source(
++		 *		ni_get_rtsi_routing(dev, dest), CR_CHAN(dest),
++		 *		&devpriv->routing_tables);
++
++		 *	if (brd < 0)
++		 *		return brd;
++
++		 *	** decrement/disconnect RTSI_BRD line from source **
++		 *	decr_rtsi_brd_src_use(src, brd, dev);
++		 * }
++
++		 * ** set rtsi output selector to default state **
++		 * reg = default_rtsi_routing[CR_CHAN(dest) - TRIGGER_LINE(0)];
++		 * ni_set_rtsi_direction(dev, dest, COMEDI_INPUT);
++		 * ni_set_rtsi_routing(dev, dest, reg);
++		 */
++	} else if (channel_is_ctr(CR_CHAN(dest))) {
++		ni_tio_unset_routing(devpriv->counter_dev, dest);
++	} else {
++		return -EINVAL;
++	}
++	return 0;
++}
++
++static int ni_global_insn_config(struct comedi_device *dev,
++				 struct comedi_insn *insn,
++				 unsigned int *data)
++{
++	switch (data[0]) {
++	case INSN_DEVICE_CONFIG_TEST_ROUTE:
++		data[0] = test_route(data[1], data[2], dev);
++		return 2;
++	case INSN_DEVICE_CONFIG_CONNECT_ROUTE:
++		return connect_route(data[1], data[2], dev);
++	case INSN_DEVICE_CONFIG_DISCONNECT_ROUTE:
++		return disconnect_route(data[1], data[2], dev);
++	/*
++	 * This case is already handled one level up.
++	 * case INSN_DEVICE_CONFIG_GET_ROUTES:
++	 */
++	default:
++		return -EINVAL;
++	}
++	return 1;
++}
++
+ static void ni_660x_init_tio_chips(struct comedi_device *dev,
+ 				   unsigned int n_chips)
+ {
+@@ -784,6 +1042,13 @@ static int ni_660x_auto_attach(struct comedi_device *dev,
+ 			 __func__, board->name);
+ 		dev_warn(dev->class_dev, "%s: High level NI signal names will not be available for this %s board.\n",
+ 			 __func__, board->name);
++	} else {
++		/*
++		 * only(?) assign insn_device_config if we have global names for
++		 * this device.
++		 */
++		dev->insn_device_config = ni_global_insn_config;
++		dev->get_valid_routes = _ni_get_valid_routes;
+ 	}
+ 
+ 	n_counters = board->n_chips * NI660X_COUNTERS_PER_CHIP;

commit a0c5e8460011506978c833d72496ce0147d82b2f
+Author: Spencer E. Olson 
+Date:   Wed Oct 3 14:56:11 2018 -0600
+
+    staging: comedi: ni_660x: clean up pfi routing
+    
+    Cleans up the pfi routing code to make it easier to follow, read, and also
+    to prepare to use this cleaned up code for enabling the device-global
+    routing interface for ni_660x devices.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
+index 0dfaf8ed093d..59055f366138 100644
+--- a/drivers/staging/comedi/drivers/ni_660x.c
++++ b/drivers/staging/comedi/drivers/ni_660x.c
+@@ -596,6 +596,37 @@ static void ni_660x_select_pfi_output(struct comedi_device *dev,
+ 	ni_660x_write(dev, active_chip, bits, NI660X_IO_CFG(chan));
+ }
+ 
++static void ni_660x_set_pfi_direction(struct comedi_device *dev,
++				      unsigned int chan,
++				      unsigned int direction)
++{
++	struct ni_660x_private *devpriv = dev->private;
++	u64 bit;
++
++	bit = 1ULL << chan;
++
++	if (direction == COMEDI_OUTPUT) {
++		devpriv->io_dir |= bit;
++		/* reset the output to currently assigned output value */
++		ni_660x_select_pfi_output(dev, chan, devpriv->io_cfg[chan]);
++	} else {
++		devpriv->io_dir &= ~bit;
++		/* set pin to high-z; do not change currently assigned route */
++		ni_660x_select_pfi_output(dev, chan, 0);
++	}
++}
++
++static unsigned int ni_660x_get_pfi_direction(struct comedi_device *dev,
++					      unsigned int chan)
++{
++	struct ni_660x_private *devpriv = dev->private;
++	u64 bit;
++
++	bit = 1ULL << chan;
++
++	return (devpriv->io_dir & bit) ? COMEDI_OUTPUT : COMEDI_INPUT;
++}
++
+ static int ni_660x_set_pfi_routing(struct comedi_device *dev,
+ 				   unsigned int chan, unsigned int source)
+ {
+@@ -614,36 +645,48 @@ static int ni_660x_set_pfi_routing(struct comedi_device *dev,
+ 	}
+ 
+ 	devpriv->io_cfg[chan] = source;
+-	if (devpriv->io_dir & (1ULL << chan))
++	if (ni_660x_get_pfi_direction(dev, chan) == COMEDI_OUTPUT)
+ 		ni_660x_select_pfi_output(dev, chan, devpriv->io_cfg[chan]);
+ 	return 0;
+ }
+ 
++static int ni_660x_get_pfi_routing(struct comedi_device *dev, unsigned int chan)
++{
++	struct ni_660x_private *devpriv = dev->private;
++
++	return devpriv->io_cfg[chan];
++}
++
++static void ni_660x_set_pfi_filter(struct comedi_device *dev,
++				   unsigned int chan, unsigned int value)
++{
++	unsigned int val;
++
++	val = ni_660x_read(dev, 0, NI660X_IO_CFG(chan));
++	val &= ~NI660X_IO_CFG_IN_SEL_MASK(chan);
++	val |= NI660X_IO_CFG_IN_SEL(chan, value);
++	ni_660x_write(dev, 0, val, NI660X_IO_CFG(chan));
++}
++
+ static int ni_660x_dio_insn_config(struct comedi_device *dev,
+ 				   struct comedi_subdevice *s,
+ 				   struct comedi_insn *insn,
+ 				   unsigned int *data)
+ {
+-	struct ni_660x_private *devpriv = dev->private;
+ 	unsigned int chan = CR_CHAN(insn->chanspec);
+-	u64 bit = 1ULL << chan;
+-	unsigned int val;
+ 	int ret;
+ 
+ 	switch (data[0]) {
+ 	case INSN_CONFIG_DIO_OUTPUT:
+-		devpriv->io_dir |= bit;
+-		ni_660x_select_pfi_output(dev, chan, devpriv->io_cfg[chan]);
++		ni_660x_set_pfi_direction(dev, chan, COMEDI_OUTPUT);
+ 		break;
+ 
+ 	case INSN_CONFIG_DIO_INPUT:
+-		devpriv->io_dir &= ~bit;
+-		ni_660x_select_pfi_output(dev, chan, 0);	/* high-z */
++		ni_660x_set_pfi_direction(dev, chan, COMEDI_INPUT);
+ 		break;
+ 
+ 	case INSN_CONFIG_DIO_QUERY:
+-		data[1] = (devpriv->io_dir & bit) ? COMEDI_OUTPUT
+-						  : COMEDI_INPUT;
++		data[1] = ni_660x_get_pfi_direction(dev, chan);
+ 		break;
+ 
+ 	case INSN_CONFIG_SET_ROUTING:
+@@ -653,14 +696,11 @@ static int ni_660x_dio_insn_config(struct comedi_device *dev,
+ 		break;
+ 
+ 	case INSN_CONFIG_GET_ROUTING:
+-		data[1] = devpriv->io_cfg[chan];
++		data[1] = ni_660x_get_pfi_routing(dev, chan);
+ 		break;
+ 
+ 	case INSN_CONFIG_FILTER:
+-		val = ni_660x_read(dev, 0, NI660X_IO_CFG(chan));
+-		val &= ~NI660X_IO_CFG_IN_SEL_MASK(chan);
+-		val |= NI660X_IO_CFG_IN_SEL(chan, data[1]);
+-		ni_660x_write(dev, 0, val, NI660X_IO_CFG(chan));
++		ni_660x_set_pfi_filter(dev, chan, data[1]);
+ 		break;
+ 
+ 	default:
+@@ -840,7 +880,7 @@ static int ni_660x_auto_attach(struct comedi_device *dev,
+ 					      : NI_660X_PFI_OUTPUT_COUNTER;
+ 
+ 		ni_660x_set_pfi_routing(dev, i, source);
+-		ni_660x_select_pfi_output(dev, i, 0);		/* high-z */
++		ni_660x_set_pfi_direction(dev, i, COMEDI_INPUT);/* high-z */
+ 	}
+ 
+ 	/* Counter subdevices (4 NI TIO General Purpose Counters per chip) */

commit 51c4ba6407ef9f5735bc6bf566211bb839892e4b
+Author: Spencer E. Olson 
+Date:   Wed Oct 3 14:56:10 2018 -0600
+
+    staging: comedi: ni_660x: Add NI PCI-6608 to list of supported devices
+    
+    Previously, only the PXI version of the NI-6608 board was supported.  This
+    change adds support for the PCI version as well.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
+index 498b2868c957..0dfaf8ed093d 100644
+--- a/drivers/staging/comedi/drivers/ni_660x.c
++++ b/drivers/staging/comedi/drivers/ni_660x.c
+@@ -7,7 +7,7 @@
+  * Driver: ni_660x
+  * Description: National Instruments 660x counter/timer boards
+  * Devices: [National Instruments] PCI-6601 (ni_660x), PCI-6602, PXI-6602,
+- *   PXI-6608, PCI-6624, PXI-6624
++ *   PCI-6608, PXI-6608, PCI-6624, PXI-6624
+  * Author: J.P. Mellor ,
+  *   Herman.Bruyninckx@mech.kuleuven.ac.be,
+  *   Wim.Meeussen@mech.kuleuven.ac.be,
+@@ -202,6 +202,7 @@ enum ni_660x_boardid {
+ 	BOARD_PCI6601,
+ 	BOARD_PCI6602,
+ 	BOARD_PXI6602,
++	BOARD_PCI6608,
+ 	BOARD_PXI6608,
+ 	BOARD_PCI6624,
+ 	BOARD_PXI6624
+@@ -225,6 +226,10 @@ static const struct ni_660x_board ni_660x_boards[] = {
+ 		.name		= "PXI-6602",
+ 		.n_chips	= 2,
+ 	},
++	[BOARD_PCI6608] = {
++		.name		= "PCI-6608",
++		.n_chips	= 2,
++	},
+ 	[BOARD_PXI6608] = {
+ 		.name		= "PXI-6608",
+ 		.n_chips	= 2,
+@@ -925,6 +930,7 @@ static const struct pci_device_id ni_660x_pci_table[] = {
+ 	{ PCI_VDEVICE(NI, 0x1310), BOARD_PCI6602 },
+ 	{ PCI_VDEVICE(NI, 0x1360), BOARD_PXI6602 },
+ 	{ PCI_VDEVICE(NI, 0x2c60), BOARD_PCI6601 },
++	{ PCI_VDEVICE(NI, 0x2db0), BOARD_PCI6608 },
+ 	{ PCI_VDEVICE(NI, 0x2cc0), BOARD_PXI6608 },
+ 	{ PCI_VDEVICE(NI, 0x1e30), BOARD_PCI6624 },
+ 	{ PCI_VDEVICE(NI, 0x1e40), BOARD_PXI6624 },

commit 713ebc593978e67d9e6d708f34fa6c66470be536
+Author: Spencer E. Olson 
+Date:   Wed Oct 3 14:56:09 2018 -0600
+
+    staging: comedi: ni_mio_common: create device-global access to tio
+    
+    Adds tio sub-devices of ni_mio_common supported hardware to the
+    implementation of test_route, connect_route, disconnect_route.  This change
+    delegates the actual functionality to the ni_tio module.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index addea2446197..2d1e0325d04d 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -5644,6 +5644,8 @@ static int get_output_select_source(int dest, struct comedi_device *dev)
+ 			/* there are only two g_out outputs. */
+ 			return -EINVAL;
+ 		reg = ni_get_gout_routing(dest, dev);
++	} else if (channel_is_ctr(dest)) {
++		reg = ni_tio_get_routing(devpriv->counter_dev, dest);
+ 	} else {
+ 		dev_dbg(dev->class_dev, "%s: unhandled destination (%d) queried\n",
+ 			__func__, dest);
+@@ -5732,6 +5734,13 @@ static int connect_route(unsigned int src, unsigned int dest,
+ 			return -EINVAL;
+ 		if (ni_set_gout_routing(src, dest, dev))
+ 			return -EINVAL;
++	} else if (channel_is_ctr(dest)) {
++		/*
++		 * we are adding back the channel modifier info to set
++		 * invert/edge info passed by the user
++		 */
++		ni_tio_set_routing(devpriv->counter_dev, dest,
++				   reg | (src & ~CR_CHAN(-1)));
+ 	} else {
+ 		return -EINVAL;
+ 	}
+@@ -5790,6 +5799,8 @@ static int disconnect_route(unsigned int src, unsigned int dest,
+ 			/* there are only two g_out outputs. */
+ 			return -EINVAL;
+ 		reg = ni_disable_gout_routing(dest, dev);
++	} else if (channel_is_ctr(dest)) {
++		ni_tio_unset_routing(devpriv->counter_dev, dest);
+ 	} else {
+ 		return -EINVAL;
+ 	}

commit 347e244884c3be1f5bce1d93730f0c32efabba99
+Author: Spencer E. Olson 
+Date:   Wed Oct 3 14:56:08 2018 -0600
+
+    staging: comedi: tio: implement global tio/ctr routing
+    
+    Adds ability to use device-global names in command args, in particular
+    cmd->start_arg (for NI_CtrArmStartTrigger), and cmd->scan_begin_arg or
+    cmd->convert_arg (either is used to specify NI_CtrGate, with preference
+    given to cmd->scan_begin_arg, if it is set).
+    
+    The actual arguments of cmd->start_arg are not fully checked against known
+    register values for the particular devices because these are not documented
+    or currently known.  This follows the precedence of prior versions of the
+    tio driver.  Should these become known, they should be annotated in the
+    route_values tables and the set of lines in ni_tio_cmdtest should be
+    uncommented to allow the tests to be made.
+    
+    This patch also adds interface functions that allow routes for particular
+    counter route destinations to be made/queried/unmade.  This allows overseer
+    modules to implement test_route, connect_route, and disconnect_route.  As a
+    part of these changes, various functions were cleaned up and clarified.
+    
+    These new interface functions allow direct writing/reading of register
+    values.  This is an example of exactly what the new device-global access
+    was intended to solve:  the old interface was not consistent with other
+    portions of the ni_* drivers--it did not allow full register values to be
+    given for various MUXes.  Instead, the old interface _did_ abstract away
+    some of the actual hardware from the underlying devices, but it was not
+    consistent with any other NI hardware.  Allowing the device-global
+    identifiers to be used, the new patch provides for consistency across all
+    ni_* drivers.  One final note:  these changes provide for backwards
+    compatibility by allowing the older values to still be used in through the
+    pre-existing kernel interfaces--though not in the new device-global
+    test/dis/connect/route interfaces.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
+index e521ed9d0887..498b2868c957 100644
+--- a/drivers/staging/comedi/drivers/ni_660x.c
++++ b/drivers/staging/comedi/drivers/ni_660x.c
+@@ -31,6 +31,7 @@
+ 
+ #include "mite.h"
+ #include "ni_tio.h"
++#include "ni_routes.h"
+ 
+ /* See Register-Level Programmer Manual page 3.1 */
+ enum ni_660x_register {
+@@ -259,6 +260,7 @@ struct ni_660x_private {
+ 	unsigned int dma_cfg[NI660X_MAX_CHIPS];
+ 	unsigned int io_cfg[NI660X_NUM_PFI_CHANNELS];
+ 	u64 io_dir;
++	struct ni_route_tables routing_tables;
+ };
+ 
+ static void ni_660x_write(struct comedi_device *dev, unsigned int chip,
+@@ -730,12 +732,23 @@ static int ni_660x_auto_attach(struct comedi_device *dev,
+ 
+ 	ni_660x_init_tio_chips(dev, board->n_chips);
+ 
++	/* prepare the device for globally-named routes. */
++	if (ni_assign_device_routes("ni_660x", board->name,
++				    &devpriv->routing_tables) < 0) {
++		dev_warn(dev->class_dev, "%s: %s device has no signal routing table.\n",
++			 __func__, board->name);
++		dev_warn(dev->class_dev, "%s: High level NI signal names will not be available for this %s board.\n",
++			 __func__, board->name);
++	}
++
+ 	n_counters = board->n_chips * NI660X_COUNTERS_PER_CHIP;
+ 	gpct_dev = ni_gpct_device_construct(dev,
+ 					    ni_660x_gpct_write,
+ 					    ni_660x_gpct_read,
+ 					    ni_gpct_variant_660x,
+-					    n_counters);
++					    n_counters,
++					    NI660X_COUNTERS_PER_CHIP,
++					    &devpriv->routing_tables);
+ 	if (!gpct_dev)
+ 		return -ENOMEM;
+ 	devpriv->counter_dev = gpct_dev;
+@@ -831,9 +844,6 @@ static int ni_660x_auto_attach(struct comedi_device *dev,
+ 		if (i < n_counters) {
+ 			struct ni_gpct *counter = &gpct_dev->counters[i];
+ 
+-			counter->chip_index = i / NI660X_COUNTERS_PER_CHIP;
+-			counter->counter_index = i % NI660X_COUNTERS_PER_CHIP;
+-
+ 			s->type		= COMEDI_SUBD_COUNTER;
+ 			s->subdev_flags	= SDF_READABLE | SDF_WRITABLE |
+ 					  SDF_LSAMPL | SDF_CMD_READ;
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index d0c403a9a226..addea2446197 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -6213,7 +6213,9 @@ static int ni_E_init(struct comedi_device *dev,
+ 					(devpriv->is_m_series)
+ 						? ni_gpct_variant_m_series
+ 						: ni_gpct_variant_e_series,
+-					NUM_GPCT);
++					NUM_GPCT,
++					NUM_GPCT,
++					&devpriv->routing_tables);
+ 	if (!devpriv->counter_dev)
+ 		return -ENOMEM;
+ 
+@@ -6222,8 +6224,6 @@ static int ni_E_init(struct comedi_device *dev,
+ 		struct ni_gpct *gpct = &devpriv->counter_dev->counters[i];
+ 
+ 		/* setup and initialize the counter */
+-		gpct->chip_index = 0;
+-		gpct->counter_index = i;
+ 		ni_tio_init_counter(gpct);
+ 
+ 		s = &dev->subdevices[NI_GPCT_SUBDEV(i)];
+diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c
+index ef919b21b7d9..838614ee64d6 100644
+--- a/drivers/staging/comedi/drivers/ni_tio.c
++++ b/drivers/staging/comedi/drivers/ni_tio.c
+@@ -818,10 +818,79 @@ static int ni_tio_get_clock_src(struct ni_gpct *counter,
+ 	return 0;
+ }
+ 
++static inline void ni_tio_set_gate_raw(struct ni_gpct *counter,
++				       unsigned int gate_source)
++{
++	ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(counter->counter_index),
++			GI_GATE_SEL_MASK, GI_GATE_SEL(gate_source));
++}
++
++static inline void ni_tio_set_gate2_raw(struct ni_gpct *counter,
++					unsigned int gate_source)
++{
++	ni_tio_set_bits(counter, NITIO_GATE2_REG(counter->counter_index),
++			GI_GATE2_SEL_MASK, GI_GATE2_SEL(gate_source));
++}
++
++/* Set the mode bits for gate. */
++static inline void ni_tio_set_gate_mode(struct ni_gpct *counter,
++					unsigned int src)
++{
++	unsigned int mode_bits = 0;
++
++	if (CR_CHAN(src) & NI_GPCT_DISABLED_GATE_SELECT) {
++		/*
++		 * Allowing bitwise comparison here to allow non-zero raw
++		 * register value to be used for channel when disabling.
++		 */
++		mode_bits = GI_GATING_DISABLED;
++	} else {
++		if (src & CR_INVERT)
++			mode_bits |= GI_GATE_POL_INVERT;
++		if (src & CR_EDGE)
++			mode_bits |= GI_RISING_EDGE_GATING;
++		else
++			mode_bits |= GI_LEVEL_GATING;
++	}
++	ni_tio_set_bits(counter, NITIO_MODE_REG(counter->counter_index),
++			GI_GATE_POL_INVERT | GI_GATING_MODE_MASK,
++			mode_bits);
++}
++
++/*
++ * Set the mode bits for gate2.
++ *
++ * Previously, the code this function represents did not actually write anything
++ * to the register.  Rather, writing to this register was reserved for the code
++ * ni ni_tio_set_gate2_raw.
++ */
++static inline void ni_tio_set_gate2_mode(struct ni_gpct *counter,
++					 unsigned int src)
++{
++	/*
++	 * The GI_GATE2_MODE bit was previously set in the code that also sets
++	 * the gate2 source.
++	 * We'll set mode bits _after_ source bits now, and thus, this function
++	 * will effectively enable the second gate after all bits are set.
++	 */
++	unsigned int mode_bits = GI_GATE2_MODE;
++
++	if (CR_CHAN(src) & NI_GPCT_DISABLED_GATE_SELECT)
++		/*
++		 * Allowing bitwise comparison here to allow non-zero raw
++		 * register value to be used for channel when disabling.
++		 */
++		mode_bits = GI_GATING_DISABLED;
++	if (src & CR_INVERT)
++		mode_bits |= GI_GATE2_POL_INVERT;
++
++	ni_tio_set_bits(counter, NITIO_GATE2_REG(counter->counter_index),
++			GI_GATE2_POL_INVERT | GI_GATE2_MODE, mode_bits);
++}
++
+ static int ni_660x_set_gate(struct ni_gpct *counter, unsigned int gate_source)
+ {
+ 	unsigned int chan = CR_CHAN(gate_source);
+-	unsigned int cidx = counter->counter_index;
+ 	unsigned int gate_sel;
+ 	unsigned int i;
+ 
+@@ -854,15 +923,13 @@ static int ni_660x_set_gate(struct ni_gpct *counter, unsigned int gate_source)
+ 			break;
+ 		return -EINVAL;
+ 	}
+-	ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx),
+-			GI_GATE_SEL_MASK, GI_GATE_SEL(gate_sel));
++	ni_tio_set_gate_raw(counter, gate_sel);
+ 	return 0;
+ }
+ 
+ static int ni_m_set_gate(struct ni_gpct *counter, unsigned int gate_source)
+ {
+ 	unsigned int chan = CR_CHAN(gate_source);
+-	unsigned int cidx = counter->counter_index;
+ 	unsigned int gate_sel;
+ 	unsigned int i;
+ 
+@@ -896,17 +963,13 @@ static int ni_m_set_gate(struct ni_gpct *counter, unsigned int gate_source)
+ 			break;
+ 		return -EINVAL;
+ 	}
+-	ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx),
+-			GI_GATE_SEL_MASK, GI_GATE_SEL(gate_sel));
++	ni_tio_set_gate_raw(counter, gate_sel);
+ 	return 0;
+ }
+ 
+ static int ni_660x_set_gate2(struct ni_gpct *counter, unsigned int gate_source)
+ {
+-	struct ni_gpct_device *counter_dev = counter->counter_dev;
+-	unsigned int cidx = counter->counter_index;
+ 	unsigned int chan = CR_CHAN(gate_source);
+-	unsigned int gate2_reg = NITIO_GATE2_REG(cidx);
+ 	unsigned int gate2_sel;
+ 	unsigned int i;
+ 
+@@ -940,94 +1003,102 @@ static int ni_660x_set_gate2(struct ni_gpct *counter, unsigned int gate_source)
+ 			break;
+ 		return -EINVAL;
+ 	}
+-	counter_dev->regs[gate2_reg] |= GI_GATE2_MODE;
+-	counter_dev->regs[gate2_reg] &= ~GI_GATE2_SEL_MASK;
+-	counter_dev->regs[gate2_reg] |= GI_GATE2_SEL(gate2_sel);
+-	ni_tio_write(counter, counter_dev->regs[gate2_reg], gate2_reg);
++	ni_tio_set_gate2_raw(counter, gate2_sel);
+ 	return 0;
+ }
+ 
+ static int ni_m_set_gate2(struct ni_gpct *counter, unsigned int gate_source)
+ {
+-	struct ni_gpct_device *counter_dev = counter->counter_dev;
+-	unsigned int cidx = counter->counter_index;
+-	unsigned int chan = CR_CHAN(gate_source);
+-	unsigned int gate2_reg = NITIO_GATE2_REG(cidx);
+-	unsigned int gate2_sel;
+-
+ 	/*
+ 	 * FIXME: We don't know what the m-series second gate codes are,
+ 	 * so we'll just pass the bits through for now.
+ 	 */
+-	switch (chan) {
+-	default:
+-		gate2_sel = chan & 0x1f;
++	ni_tio_set_gate2_raw(counter, gate_source);
++	return 0;
++}
++
++int ni_tio_set_gate_src_raw(struct ni_gpct *counter,
++			    unsigned int gate, unsigned int src)
++{
++	struct ni_gpct_device *counter_dev = counter->counter_dev;
++
++	switch (gate) {
++	case 0:
++		/* 1.  start by disabling gate */
++		ni_tio_set_gate_mode(counter, NI_GPCT_DISABLED_GATE_SELECT);
++		/* 2.  set the requested gate source */
++		ni_tio_set_gate_raw(counter, src);
++		/* 3.  reenable & set mode to starts things back up */
++		ni_tio_set_gate_mode(counter, src);
++		break;
++	case 1:
++		if (!ni_tio_has_gate2_registers(counter_dev))
++			return -EINVAL;
++
++		/* 1.  start by disabling gate */
++		ni_tio_set_gate2_mode(counter, NI_GPCT_DISABLED_GATE_SELECT);
++		/* 2.  set the requested gate source */
++		ni_tio_set_gate2_raw(counter, src);
++		/* 3.  reenable & set mode to starts things back up */
++		ni_tio_set_gate2_mode(counter, src);
+ 		break;
++	default:
++		return -EINVAL;
+ 	}
+-	counter_dev->regs[gate2_reg] |= GI_GATE2_MODE;
+-	counter_dev->regs[gate2_reg] &= ~GI_GATE2_SEL_MASK;
+-	counter_dev->regs[gate2_reg] |= GI_GATE2_SEL(gate2_sel);
+-	ni_tio_write(counter, counter_dev->regs[gate2_reg], gate2_reg);
+ 	return 0;
+ }
++EXPORT_SYMBOL_GPL(ni_tio_set_gate_src_raw);
+ 
+ int ni_tio_set_gate_src(struct ni_gpct *counter,
+ 			unsigned int gate, unsigned int src)
+ {
+ 	struct ni_gpct_device *counter_dev = counter->counter_dev;
+-	unsigned int cidx = counter->counter_index;
+-	unsigned int chan = CR_CHAN(src);
+-	unsigned int gate2_reg = NITIO_GATE2_REG(cidx);
+-	unsigned int mode = 0;
++	/*
++	 * mask off disable flag.  This high bit still passes CR_CHAN.
++	 * Doing this allows one to both set the gate as disabled, but also
++	 * change the route value of the gate.
++	 */
++	int chan = CR_CHAN(src) & (~NI_GPCT_DISABLED_GATE_SELECT);
++	int ret;
+ 
+ 	switch (gate) {
+ 	case 0:
+-		if (chan == NI_GPCT_DISABLED_GATE_SELECT) {
+-			ni_tio_set_bits(counter, NITIO_MODE_REG(cidx),
+-					GI_GATING_MODE_MASK,
+-					GI_GATING_DISABLED);
+-			return 0;
+-		}
+-		if (src & CR_INVERT)
+-			mode |= GI_GATE_POL_INVERT;
+-		if (src & CR_EDGE)
+-			mode |= GI_RISING_EDGE_GATING;
+-		else
+-			mode |= GI_LEVEL_GATING;
+-		ni_tio_set_bits(counter, NITIO_MODE_REG(cidx),
+-				GI_GATE_POL_INVERT | GI_GATING_MODE_MASK,
+-				mode);
++		/* 1.  start by disabling gate */
++		ni_tio_set_gate_mode(counter, NI_GPCT_DISABLED_GATE_SELECT);
++		/* 2.  set the requested gate source */
+ 		switch (counter_dev->variant) {
+ 		case ni_gpct_variant_e_series:
+ 		case ni_gpct_variant_m_series:
+-		default:
+-			return ni_m_set_gate(counter, src);
++			ret = ni_m_set_gate(counter, chan);
+ 		case ni_gpct_variant_660x:
+-			return ni_660x_set_gate(counter, src);
++			ret = ni_660x_set_gate(counter, chan);
++		default:
++			return -EINVAL;
+ 		}
++		if (ret)
++			return ret;
++		/* 3.  reenable & set mode to starts things back up */
++		ni_tio_set_gate_mode(counter, src);
+ 		break;
+ 	case 1:
+ 		if (!ni_tio_has_gate2_registers(counter_dev))
+ 			return -EINVAL;
+ 
+-		if (chan == NI_GPCT_DISABLED_GATE_SELECT) {
+-			counter_dev->regs[gate2_reg] &= ~GI_GATE2_MODE;
+-			ni_tio_write(counter, counter_dev->regs[gate2_reg],
+-				     gate2_reg);
+-			return 0;
+-		}
+-		if (src & CR_INVERT)
+-			counter_dev->regs[gate2_reg] |= GI_GATE2_POL_INVERT;
+-		else
+-			counter_dev->regs[gate2_reg] &= ~GI_GATE2_POL_INVERT;
++		/* 1.  start by disabling gate */
++		ni_tio_set_gate2_mode(counter, NI_GPCT_DISABLED_GATE_SELECT);
++		/* 2.  set the requested gate source */
+ 		switch (counter_dev->variant) {
+ 		case ni_gpct_variant_m_series:
+-			return ni_m_set_gate2(counter, src);
++			ret = ni_m_set_gate2(counter, chan);
+ 		case ni_gpct_variant_660x:
+-			return ni_660x_set_gate2(counter, src);
++			ret = ni_660x_set_gate2(counter, chan);
+ 		default:
+ 			return -EINVAL;
+ 		}
++		if (ret)
++			return ret;
++		/* 3.  reenable & set mode to starts things back up */
++		ni_tio_set_gate2_mode(counter, src);
+ 		break;
+ 	default:
+ 		return -EINVAL;
+@@ -1047,19 +1118,21 @@ static int ni_tio_set_other_src(struct ni_gpct *counter, unsigned int index,
+ 		return -EINVAL;
+ 
+ 	abz_reg = NITIO_ABZ_REG(cidx);
+-	switch (index) {
+-	case NI_GPCT_SOURCE_ENCODER_A:
++
++	/* allow for new device-global names */
++	if (index == NI_GPCT_SOURCE_ENCODER_A ||
++	    (index >= NI_CtrA(0) && index <= NI_CtrA(-1))) {
+ 		shift = 10;
+-		break;
+-	case NI_GPCT_SOURCE_ENCODER_B:
++	} else if (index == NI_GPCT_SOURCE_ENCODER_B ||
++	    (index >= NI_CtrB(0) && index <= NI_CtrB(-1))) {
+ 		shift = 5;
+-		break;
+-	case NI_GPCT_SOURCE_ENCODER_Z:
++	} else if (index == NI_GPCT_SOURCE_ENCODER_Z ||
++	    (index >= NI_CtrZ(0) && index <= NI_CtrZ(-1))) {
+ 		shift = 0;
+-		break;
+-	default:
++	} else {
+ 		return -EINVAL;
+ 	}
++
+ 	mask = 0x1f << shift;
+ 	if (source > 0x1f)
+ 		source = 0x1f;	/* Disable gate */
+@@ -1070,6 +1143,39 @@ static int ni_tio_set_other_src(struct ni_gpct *counter, unsigned int index,
+ 	return 0;
+ }
+ 
++static int ni_tio_get_other_src(struct ni_gpct *counter, unsigned int index,
++				unsigned int *source)
++{
++	struct ni_gpct_device *counter_dev = counter->counter_dev;
++	unsigned int cidx = counter->counter_index;
++	unsigned int abz_reg, shift, mask;
++
++	if (counter_dev->variant != ni_gpct_variant_m_series)
++		/* A,B,Z only valid for m-series */
++		return -EINVAL;
++
++	abz_reg = NITIO_ABZ_REG(cidx);
++
++	/* allow for new device-global names */
++	if (index == NI_GPCT_SOURCE_ENCODER_A ||
++	    (index >= NI_CtrA(0) && index <= NI_CtrA(-1))) {
++		shift = 10;
++	} else if (index == NI_GPCT_SOURCE_ENCODER_B ||
++	    (index >= NI_CtrB(0) && index <= NI_CtrB(-1))) {
++		shift = 5;
++	} else if (index == NI_GPCT_SOURCE_ENCODER_Z ||
++	    (index >= NI_CtrZ(0) && index <= NI_CtrZ(-1))) {
++		shift = 0;
++	} else {
++		return -EINVAL;
++	}
++
++	mask = 0x1f;
++
++	*source = (ni_tio_get_soft_copy(counter, abz_reg) >> shift) & mask;
++	return 0;
++}
++
+ static int ni_660x_gate_to_generic_gate(unsigned int gate, unsigned int *src)
+ {
+ 	unsigned int source;
+@@ -1112,7 +1218,7 @@ static int ni_660x_gate_to_generic_gate(unsigned int gate, unsigned int *src)
+ 	}
+ 	*src = source;
+ 	return 0;
+-};
++}
+ 
+ static int ni_m_gate_to_generic_gate(unsigned int gate, unsigned int *src)
+ {
+@@ -1165,7 +1271,7 @@ static int ni_m_gate_to_generic_gate(unsigned int gate, unsigned int *src)
+ 	}
+ 	*src = source;
+ 	return 0;
+-};
++}
+ 
+ static int ni_660x_gate2_to_generic_gate(unsigned int gate, unsigned int *src)
+ {
+@@ -1212,7 +1318,7 @@ static int ni_660x_gate2_to_generic_gate(unsigned int gate, unsigned int *src)
+ 	}
+ 	*src = source;
+ 	return 0;
+-};
++}
+ 
+ static int ni_m_gate2_to_generic_gate(unsigned int gate, unsigned int *src)
+ {
+@@ -1222,32 +1328,60 @@ static int ni_m_gate2_to_generic_gate(unsigned int gate, unsigned int *src)
+ 	 */
+ 	*src = gate;
+ 	return 0;
+-};
++}
++
++static inline unsigned int ni_tio_get_gate_mode(struct ni_gpct *counter)
++{
++	unsigned int mode = ni_tio_get_soft_copy(
++		counter, NITIO_MODE_REG(counter->counter_index));
++	unsigned int ret = 0;
++
++	if ((mode & GI_GATING_MODE_MASK) == GI_GATING_DISABLED)
++		ret |= NI_GPCT_DISABLED_GATE_SELECT;
++	if (mode & GI_GATE_POL_INVERT)
++		ret |= CR_INVERT;
++	if ((mode & GI_GATING_MODE_MASK) != GI_LEVEL_GATING)
++		ret |= CR_EDGE;
++
++	return ret;
++}
++
++static inline unsigned int ni_tio_get_gate2_mode(struct ni_gpct *counter)
++{
++	unsigned int mode = ni_tio_get_soft_copy(
++		counter, NITIO_GATE2_REG(counter->counter_index));
++	unsigned int ret = 0;
++
++	if (!(mode & GI_GATE2_MODE))
++		ret |= NI_GPCT_DISABLED_GATE_SELECT;
++	if (mode & GI_GATE2_POL_INVERT)
++		ret |= CR_INVERT;
++
++	return ret;
++}
++
++static inline unsigned int ni_tio_get_gate_val(struct ni_gpct *counter)
++{
++	return GI_BITS_TO_GATE(ni_tio_get_soft_copy(counter,
++		NITIO_INPUT_SEL_REG(counter->counter_index)));
++}
++
++static inline unsigned int ni_tio_get_gate2_val(struct ni_gpct *counter)
++{
++	return GI_BITS_TO_GATE2(ni_tio_get_soft_copy(counter,
++		NITIO_GATE2_REG(counter->counter_index)));
++}
+ 
+ static int ni_tio_get_gate_src(struct ni_gpct *counter, unsigned int gate_index,
+ 			       unsigned int *gate_source)
+ {
+-	struct ni_gpct_device *counter_dev = counter->counter_dev;
+-	unsigned int cidx = counter->counter_index;
+-	unsigned int mode;
+-	unsigned int reg;
+ 	unsigned int gate;
+ 	int ret;
+ 
+-	mode = ni_tio_get_soft_copy(counter, NITIO_MODE_REG(cidx));
+-	if (((mode & GI_GATING_MODE_MASK) == GI_GATING_DISABLED) ||
+-	    (gate_index == 1 &&
+-	     !(counter_dev->regs[NITIO_GATE2_REG(cidx)] & GI_GATE2_MODE))) {
+-		*gate_source = NI_GPCT_DISABLED_GATE_SELECT;
+-		return 0;
+-	}
+-
+ 	switch (gate_index) {
+ 	case 0:
+-		reg = NITIO_INPUT_SEL_REG(cidx);
+-		gate = GI_BITS_TO_GATE(ni_tio_get_soft_copy(counter, reg));
+-
+-		switch (counter_dev->variant) {
++		gate = ni_tio_get_gate_val(counter);
++		switch (counter->counter_dev->variant) {
+ 		case ni_gpct_variant_e_series:
+ 		case ni_gpct_variant_m_series:
+ 		default:
+@@ -1259,16 +1393,11 @@ static int ni_tio_get_gate_src(struct ni_gpct *counter, unsigned int gate_index,
+ 		}
+ 		if (ret)
+ 			return ret;
+-		if (mode & GI_GATE_POL_INVERT)
+-			*gate_source |= CR_INVERT;
+-		if ((mode & GI_GATING_MODE_MASK) != GI_LEVEL_GATING)
+-			*gate_source |= CR_EDGE;
++		*gate_source |= ni_tio_get_gate_mode(counter);
+ 		break;
+ 	case 1:
+-		reg = NITIO_GATE2_REG(cidx);
+-		gate = GI_BITS_TO_GATE2(counter_dev->regs[reg]);
+-
+-		switch (counter_dev->variant) {
++		gate = ni_tio_get_gate2_val(counter);
++		switch (counter->counter_dev->variant) {
+ 		case ni_gpct_variant_e_series:
+ 		case ni_gpct_variant_m_series:
+ 		default:
+@@ -1280,11 +1409,26 @@ static int ni_tio_get_gate_src(struct ni_gpct *counter, unsigned int gate_index,
+ 		}
+ 		if (ret)
+ 			return ret;
+-		if (counter_dev->regs[reg] & GI_GATE2_POL_INVERT)
+-			*gate_source |= CR_INVERT;
+-		/* second gate can't have edge/level mode set independently */
+-		if ((mode & GI_GATING_MODE_MASK) != GI_LEVEL_GATING)
+-			*gate_source |= CR_EDGE;
++		*gate_source |= ni_tio_get_gate2_mode(counter);
++		break;
++	default:
++		return -EINVAL;
++	}
++	return 0;
++}
++
++static int ni_tio_get_gate_src_raw(struct ni_gpct *counter,
++				   unsigned int gate_index,
++				   unsigned int *gate_source)
++{
++	switch (gate_index) {
++	case 0:
++		*gate_source = ni_tio_get_gate_mode(counter)
++			     | ni_tio_get_gate_val(counter);
++		break;
++	case 1:
++		*gate_source = ni_tio_get_gate2_mode(counter)
++			     | ni_tio_get_gate2_val(counter);
+ 		break;
+ 	default:
+ 		return -EINVAL;
+@@ -1347,6 +1491,107 @@ int ni_tio_insn_config(struct comedi_device *dev,
+ }
+ EXPORT_SYMBOL_GPL(ni_tio_insn_config);
+ 
++/**
++ * Retrieves the register value of the current source of the output selector for
++ * the given destination.
++ *
++ * If the terminal for the destination is not already configured as an output,
++ * this function returns -EINVAL as error.
++ *
++ * Return: the register value of the destination output selector;
++ *         -EINVAL if terminal is not configured for output.
++ */
++int ni_tio_get_routing(struct ni_gpct_device *counter_dev, unsigned int dest)
++{
++	/* we need to know the actual counter below... */
++	int ctr_index = (dest - NI_COUNTER_NAMES_BASE) % NI_MAX_COUNTERS;
++	struct ni_gpct *counter = &counter_dev->counters[ctr_index];
++	int ret = 1;
++	unsigned int reg;
++
++	if (dest >= NI_CtrA(0) && dest <= NI_CtrZ(-1)) {
++		ret = ni_tio_get_other_src(counter, dest, ®);
++	} else if (dest >= NI_CtrGate(0) && dest <= NI_CtrGate(-1)) {
++		ret = ni_tio_get_gate_src_raw(counter, 0, ®);
++	} else if (dest >= NI_CtrAux(0) && dest <= NI_CtrAux(-1)) {
++		ret = ni_tio_get_gate_src_raw(counter, 1, ®);
++	/*
++	 * This case is not possible through this interface.  A user must use
++	 * INSN_CONFIG_SET_CLOCK_SRC instead.
++	 * } else if (dest >= NI_CtrSource(0) && dest <= NI_CtrSource(-1)) {
++	 *	ret = ni_tio_set_clock_src(counter, ®, &period_ns);
++	 */
++	}
++
++	if (ret)
++		return -EINVAL;
++
++	return reg;
++}
++EXPORT_SYMBOL_GPL(ni_tio_get_routing);
++
++/**
++ * Sets the register value of the selector MUX for the given destination.
++ * @counter_dev:Pointer to general counter device.
++ * @destination:Device-global identifier of route destination.
++ * @register_value:
++ *		The first several bits of this value should store the desired
++ *		value to write to the register.  All other bits are for
++ *		transmitting information that modify the mode of the particular
++ *		destination/gate.  These mode bits might include a bitwise or of
++ *		CR_INVERT and CR_EDGE.  Note that the calling function should
++ *		have already validated the correctness of this value.
++ */
++int ni_tio_set_routing(struct ni_gpct_device *counter_dev, unsigned int dest,
++		       unsigned int reg)
++{
++	/* we need to know the actual counter below... */
++	int ctr_index = (dest - NI_COUNTER_NAMES_BASE) % NI_MAX_COUNTERS;
++	struct ni_gpct *counter = &counter_dev->counters[ctr_index];
++	int ret;
++
++	if (dest >= NI_CtrA(0) && dest <= NI_CtrZ(-1)) {
++		ret = ni_tio_set_other_src(counter, dest, reg);
++	} else if (dest >= NI_CtrGate(0) && dest <= NI_CtrGate(-1)) {
++		ret = ni_tio_set_gate_src_raw(counter, 0, reg);
++	} else if (dest >= NI_CtrAux(0) && dest <= NI_CtrAux(-1)) {
++		ret = ni_tio_set_gate_src_raw(counter, 1, reg);
++	/*
++	 * This case is not possible through this interface.  A user must use
++	 * INSN_CONFIG_SET_CLOCK_SRC instead.
++	 * } else if (dest >= NI_CtrSource(0) && dest <= NI_CtrSource(-1)) {
++	 *	ret = ni_tio_set_clock_src(counter, reg, period_ns);
++	 */
++	} else {
++		return -EINVAL;
++	}
++
++	return ret;
++}
++EXPORT_SYMBOL_GPL(ni_tio_set_routing);
++
++/**
++ * Sets the given destination MUX to its default value or disable it.
++ *
++ * Return: 0 if successful; -EINVAL if terminal is unknown.
++ */
++int ni_tio_unset_routing(struct ni_gpct_device *counter_dev, unsigned int dest)
++{
++	if (dest >= NI_GATES_NAMES_BASE && dest <= NI_GATES_NAMES_MAX)
++		/* Disable gate (via mode bits) and set to default 0-value */
++		return ni_tio_set_routing(counter_dev, dest,
++					  NI_GPCT_DISABLED_GATE_SELECT);
++	/*
++	 * This case is not possible through this interface.  A user must use
++	 * INSN_CONFIG_SET_CLOCK_SRC instead.
++	 * if (dest >= NI_CtrSource(0) && dest <= NI_CtrSource(-1))
++	 *	return ni_tio_set_clock_src(counter, reg, period_ns);
++	 */
++
++	return -EINVAL;
++}
++EXPORT_SYMBOL_GPL(ni_tio_unset_routing);
++
+ static unsigned int ni_tio_read_sw_save_reg(struct comedi_device *dev,
+ 					    struct comedi_subdevice *s)
+ {
+@@ -1504,13 +1749,15 @@ ni_gpct_device_construct(struct comedi_device *dev,
+ 			 unsigned int (*read)(struct ni_gpct *counter,
+ 					      enum ni_gpct_register reg),
+ 			 enum ni_gpct_variant variant,
+-			 unsigned int num_counters)
++			 unsigned int num_counters,
++			 unsigned int counters_per_chip,
++			 const struct ni_route_tables *routing_tables)
+ {
+ 	struct ni_gpct_device *counter_dev;
+ 	struct ni_gpct *counter;
+ 	unsigned int i;
+ 
+-	if (num_counters == 0)
++	if (num_counters == 0 || counters_per_chip == 0)
+ 		return NULL;
+ 
+ 	counter_dev = kzalloc(sizeof(*counter_dev), GFP_KERNEL);
+@@ -1521,6 +1768,7 @@ ni_gpct_device_construct(struct comedi_device *dev,
+ 	counter_dev->write = write;
+ 	counter_dev->read = read;
+ 	counter_dev->variant = variant;
++	counter_dev->routing_tables = routing_tables;
+ 
+ 	spin_lock_init(&counter_dev->regs_lock);
+ 
+@@ -1534,9 +1782,12 @@ ni_gpct_device_construct(struct comedi_device *dev,
+ 	for (i = 0; i < num_counters; ++i) {
+ 		counter = &counter_dev->counters[i];
+ 		counter->counter_dev = counter_dev;
++		counter->chip_index = i / counters_per_chip;
++		counter->counter_index = i % counters_per_chip;
+ 		spin_lock_init(&counter->lock);
+ 	}
+ 	counter_dev->num_counters = num_counters;
++	counter_dev->counters_per_chip = counters_per_chip;
+ 
+ 	return counter_dev;
+ }
+diff --git a/drivers/staging/comedi/drivers/ni_tio.h b/drivers/staging/comedi/drivers/ni_tio.h
+index 23221cead8ca..340d63c74467 100644
+--- a/drivers/staging/comedi/drivers/ni_tio.h
++++ b/drivers/staging/comedi/drivers/ni_tio.h
+@@ -107,8 +107,10 @@ struct ni_gpct_device {
+ 	enum ni_gpct_variant variant;
+ 	struct ni_gpct *counters;
+ 	unsigned int num_counters;
++	unsigned int counters_per_chip;
+ 	unsigned int regs[NITIO_NUM_REGS];
+ 	spinlock_t regs_lock;		/* protects 'regs' */
++	const struct ni_route_tables *routing_tables; /* link to routes */
+ };
+ 
+ struct ni_gpct_device *
+@@ -119,7 +121,9 @@ ni_gpct_device_construct(struct comedi_device *dev,
+ 			 unsigned int (*read)(struct ni_gpct *counter,
+ 					      enum ni_gpct_register),
+ 			 enum ni_gpct_variant,
+-			 unsigned int num_counters);
++			 unsigned int num_counters,
++			 unsigned int counters_per_chip,
++			 const struct ni_route_tables *routing_tables);
+ void ni_gpct_device_destroy(struct ni_gpct_device *counter_dev);
+ void ni_tio_init_counter(struct ni_gpct *counter);
+ int ni_tio_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
+@@ -138,4 +142,40 @@ void ni_tio_set_mite_channel(struct ni_gpct *counter,
+ 			     struct mite_channel *mite_chan);
+ void ni_tio_acknowledge(struct ni_gpct *counter);
+ 
++/*
++ * Retrieves the register value of the current source of the output selector for
++ * the given destination.
++ *
++ * If the terminal for the destination is not already configured as an output,
++ * this function returns -EINVAL as error.
++ *
++ * Return: the register value of the destination output selector;
++ *         -EINVAL if terminal is not configured for output.
++ */
++int ni_tio_get_routing(struct ni_gpct_device *counter_dev,
++		       unsigned int destination);
++
++/*
++ * Sets the register value of the selector MUX for the given destination.
++ * @counter_dev:Pointer to general counter device.
++ * @destination:Device-global identifier of route destination.
++ * @register_value:
++ *		The first several bits of this value should store the desired
++ *		value to write to the register.  All other bits are for
++ *		transmitting information that modify the mode of the particular
++ *		destination/gate.  These mode bits might include a bitwise or of
++ *		CR_INVERT and CR_EDGE.  Note that the calling function should
++ *		have already validated the correctness of this value.
++ */
++int ni_tio_set_routing(struct ni_gpct_device *counter_dev,
++		       unsigned int destination, unsigned int register_value);
++
++/*
++ * Sets the given destination MUX to its default value or disable it.
++ *
++ * Return: 0 if successful; -EINVAL if terminal is unknown.
++ */
++int ni_tio_unset_routing(struct ni_gpct_device *counter_dev,
++			 unsigned int destination);
++
+ #endif /* _COMEDI_NI_TIO_H */
+diff --git a/drivers/staging/comedi/drivers/ni_tio_internal.h b/drivers/staging/comedi/drivers/ni_tio_internal.h
+index f4d99d78208a..652a28990132 100644
+--- a/drivers/staging/comedi/drivers/ni_tio_internal.h
++++ b/drivers/staging/comedi/drivers/ni_tio_internal.h
+@@ -170,5 +170,7 @@ unsigned int ni_tio_get_soft_copy(const struct ni_gpct *counter,
+ int ni_tio_arm(struct ni_gpct *counter, bool arm, unsigned int start_trigger);
+ int ni_tio_set_gate_src(struct ni_gpct *counter, unsigned int gate,
+ 			unsigned int src);
++int ni_tio_set_gate_src_raw(struct ni_gpct *counter, unsigned int gate,
++			    unsigned int src);
+ 
+ #endif /* _COMEDI_NI_TIO_INTERNAL_H */
+diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c
+index 050bee0b9515..2a9f7e9821a7 100644
+--- a/drivers/staging/comedi/drivers/ni_tiocmd.c
++++ b/drivers/staging/comedi/drivers/ni_tiocmd.c
+@@ -33,6 +33,7 @@
+ #include 
+ #include "ni_tio_internal.h"
+ #include "mite.h"
++#include "ni_routes.h"
+ 
+ static void ni_tio_configure_dma(struct ni_gpct *counter,
+ 				 bool enable, bool read)
+@@ -100,6 +101,8 @@ static int ni_tio_input_cmd(struct comedi_subdevice *s)
+ {
+ 	struct ni_gpct *counter = s->private;
+ 	struct ni_gpct_device *counter_dev = counter->counter_dev;
++	const struct ni_route_tables *routing_tables =
++		counter_dev->routing_tables;
+ 	unsigned int cidx = counter->counter_index;
+ 	struct comedi_async *async = s->async;
+ 	struct comedi_cmd *cmd = &async->cmd;
+@@ -128,8 +131,19 @@ static int ni_tio_input_cmd(struct comedi_subdevice *s)
+ 
+ 		if (cmd->start_src == TRIG_NOW)
+ 			ret = ni_tio_arm(counter, true, NI_GPCT_ARM_IMMEDIATE);
+-		else if (cmd->start_src == TRIG_EXT)
+-			ret = ni_tio_arm(counter, true, cmd->start_arg);
++		else if (cmd->start_src == TRIG_EXT) {
++			int reg = CR_CHAN(cmd->start_arg);
++
++			if (reg >= NI_NAMES_BASE) {
++				/* using a device-global name. lookup reg */
++				reg = ni_get_reg_value(reg,
++						       NI_CtrArmStartTrigger(cidx),
++						       routing_tables);
++				/* mark this as a raw register value */
++				reg |= NI_GPCT_HW_ARM;
++			}
++			ret = ni_tio_arm(counter, true, reg);
++		}
+ 	}
+ 	return ret;
+ }
+@@ -148,6 +162,8 @@ static int ni_tio_cmd_setup(struct comedi_subdevice *s)
+ 	struct comedi_cmd *cmd = &s->async->cmd;
+ 	struct ni_gpct *counter = s->private;
+ 	unsigned int cidx = counter->counter_index;
++	const struct ni_route_tables *routing_tables =
++		counter->counter_dev->routing_tables;
+ 	int set_gate_source = 0;
+ 	unsigned int gate_source;
+ 	int retval = 0;
+@@ -159,8 +175,24 @@ static int ni_tio_cmd_setup(struct comedi_subdevice *s)
+ 		set_gate_source = 1;
+ 		gate_source = cmd->convert_arg;
+ 	}
+-	if (set_gate_source)
+-		retval = ni_tio_set_gate_src(counter, 0, gate_source);
++	if (set_gate_source) {
++		if (CR_CHAN(gate_source) >= NI_NAMES_BASE) {
++			/* Lookup and use the real register values */
++			int reg = ni_get_reg_value(CR_CHAN(gate_source),
++						   NI_CtrGate(cidx),
++						   routing_tables);
++			if (reg < 0)
++				return -EINVAL;
++			retval = ni_tio_set_gate_src_raw(counter, 0, reg);
++		} else {
++			/*
++			 * This function must be used separately since it does
++			 * not expect real register values and attempts to
++			 * convert these to real register values.
++			 */
++			retval = ni_tio_set_gate_src(counter, 0, gate_source);
++		}
++	}
+ 	if (cmd->flags & CMDF_WAKE_EOS) {
+ 		ni_tio_set_bits(counter, NITIO_INT_ENA_REG(cidx),
+ 				GI_GATE_INTERRUPT_ENABLE(cidx),
+@@ -203,6 +235,9 @@ int ni_tio_cmdtest(struct comedi_device *dev,
+ 		   struct comedi_cmd *cmd)
+ {
+ 	struct ni_gpct *counter = s->private;
++	unsigned int cidx = counter->counter_index;
++	const struct ni_route_tables *routing_tables =
++		counter->counter_dev->routing_tables;
+ 	int err = 0;
+ 	unsigned int sources;
+ 
+@@ -247,14 +282,37 @@ int ni_tio_cmdtest(struct comedi_device *dev,
+ 		break;
+ 	case TRIG_EXT:
+ 		/* start_arg is the start_trigger passed to ni_tio_arm() */
++		/*
++		 * This should be done, but we don't yet know the actual
++		 * register values.  These should be tested and then documented
++		 * in the ni_route_values/ni_*.csv files, with indication of
++		 * who/when/which/how these these were tested.
++		 * When at least a e/m/660x series have been tested, this code
++		 * should be uncommented:
++		 *
++		 * err |= ni_check_trigger_arg(CR_CHAN(cmd->start_arg),
++		 *			    NI_CtrArmStartTrigger(cidx),
++		 *			    routing_tables);
++		 */
+ 		break;
+ 	}
+ 
++	/*
++	 * It seems that convention is to allow either scan_begin_arg or
++	 * convert_arg to specify the Gate source, with scan_begin_arg taking
++	 * precedence.
++	 */
+ 	if (cmd->scan_begin_src != TRIG_EXT)
+ 		err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
++	else
++		err |= ni_check_trigger_arg(CR_CHAN(cmd->scan_begin_arg),
++					    NI_CtrGate(cidx), routing_tables);
+ 
+ 	if (cmd->convert_src != TRIG_EXT)
+ 		err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
++	else
++		err |= ni_check_trigger_arg(CR_CHAN(cmd->convert_arg),
++					    NI_CtrGate(cidx), routing_tables);
+ 
+ 	err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+ 					   cmd->chanlist_len);

commit 02d1c6e827073ebb65d9f92c169c024ae2d20ddc
+Author: Spencer E. Olson 
+Date:   Wed Oct 3 14:56:07 2018 -0600
+
+    staging: comedi: ni_mio_common: implement output selection of GPFO_{0, 1}
+    
+    Implement the ability to route various signals to NI_CtrOut(x) pin.  This
+    pin is also known as GPFO_{0,1} in the DAQ STC.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index d4c0fd07059b..d0c403a9a226 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -5532,6 +5532,77 @@ static void ni_rtsi_init(struct comedi_device *dev)
+ 	set_rgout0_reg(0, dev);
+ }
+ 
++/* Get route of GPFO_i/CtrOut pins */
++static inline int ni_get_gout_routing(unsigned int dest,
++				      struct comedi_device *dev)
++{
++	struct ni_private *devpriv = dev->private;
++	unsigned int reg = devpriv->an_trig_etc_reg;
++
++	switch (dest) {
++	case 0:
++		if (reg & NISTC_ATRIG_ETC_GPFO_0_ENA)
++			return NISTC_ATRIG_ETC_GPFO_0_SEL_TO_SRC(reg);
++		break;
++	case 1:
++		if (reg & NISTC_ATRIG_ETC_GPFO_1_ENA)
++			return NISTC_ATRIG_ETC_GPFO_1_SEL_TO_SRC(reg);
++		break;
++	}
++
++	return -EINVAL;
++}
++
++/* Set route of GPFO_i/CtrOut pins */
++static inline int ni_disable_gout_routing(unsigned int dest,
++					  struct comedi_device *dev)
++{
++	struct ni_private *devpriv = dev->private;
++
++	switch (dest) {
++	case 0:
++		devpriv->an_trig_etc_reg &= ~NISTC_ATRIG_ETC_GPFO_0_ENA;
++		break;
++	case 1:
++		devpriv->an_trig_etc_reg &= ~NISTC_ATRIG_ETC_GPFO_1_ENA;
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	ni_stc_writew(dev, devpriv->an_trig_etc_reg, NISTC_ATRIG_ETC_REG);
++	return 0;
++}
++
++/* Set route of GPFO_i/CtrOut pins */
++static inline int ni_set_gout_routing(unsigned int src, unsigned int dest,
++				      struct comedi_device *dev)
++{
++	struct ni_private *devpriv = dev->private;
++
++	switch (dest) {
++	case 0:
++		/* clear reg */
++		devpriv->an_trig_etc_reg &= ~NISTC_ATRIG_ETC_GPFO_0_SEL(-1);
++		/* set reg */
++		devpriv->an_trig_etc_reg |= NISTC_ATRIG_ETC_GPFO_0_ENA
++					 |  NISTC_ATRIG_ETC_GPFO_0_SEL(src);
++		break;
++	case 1:
++		/* clear reg */
++		devpriv->an_trig_etc_reg &= ~NISTC_ATRIG_ETC_GPFO_1_SEL;
++		src = src ? NISTC_ATRIG_ETC_GPFO_1_SEL : 0;
++		/* set reg */
++		devpriv->an_trig_etc_reg |= NISTC_ATRIG_ETC_GPFO_1_ENA | src;
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	ni_stc_writew(dev, devpriv->an_trig_etc_reg, NISTC_ATRIG_ETC_REG);
++	return 0;
++}
++
+ /*
+  * Retrieves the current source of the output selector for the given
+  * destination.  If the terminal for the destination is not already configured
+@@ -5563,6 +5634,16 @@ static int get_output_select_source(int dest, struct comedi_device *dev)
+ 				reg = get_ith_rtsi_brd_reg(i, dev);
+ 			}
+ 		}
++	} else if (dest >= NI_CtrOut(0) && dest <= NI_CtrOut(-1)) {
++		/*
++		 * not handled by ni_tio.  Only available for GPFO registers in
++		 * e/m series.
++		 */
++		dest -= NI_CtrOut(0);
++		if (dest > 1)
++			/* there are only two g_out outputs. */
++			return -EINVAL;
++		reg = ni_get_gout_routing(dest, dev);
+ 	} else {
+ 		dev_dbg(dev->class_dev, "%s: unhandled destination (%d) queried\n",
+ 			__func__, dest);
+@@ -5640,6 +5721,17 @@ static int connect_route(unsigned int src, unsigned int dest,
+ 
+ 		ni_set_rtsi_direction(dev, dest, COMEDI_OUTPUT);
+ 		ni_set_rtsi_routing(dev, dest, reg);
++	} else if (dest >= NI_CtrOut(0) && dest <= NI_CtrOut(-1)) {
++		/*
++		 * not handled by ni_tio.  Only available for GPFO registers in
++		 * e/m series.
++		 */
++		dest -= NI_CtrOut(0);
++		if (dest > 1)
++			/* there are only two g_out outputs. */
++			return -EINVAL;
++		if (ni_set_gout_routing(src, dest, dev))
++			return -EINVAL;
+ 	} else {
+ 		return -EINVAL;
+ 	}
+@@ -5688,6 +5780,16 @@ static int disconnect_route(unsigned int src, unsigned int dest,
+ 		reg = default_rtsi_routing[dest - TRIGGER_LINE(0)];
+ 		ni_set_rtsi_direction(dev, dest, COMEDI_INPUT);
+ 		ni_set_rtsi_routing(dev, dest, reg);
++	} else if (dest >= NI_CtrOut(0) && dest <= NI_CtrOut(-1)) {
++		/*
++		 * not handled by ni_tio.  Only available for GPFO registers in
++		 * e/m series.
++		 */
++		dest -= NI_CtrOut(0);
++		if (dest > 1)
++			/* there are only two g_out outputs. */
++			return -EINVAL;
++		reg = ni_disable_gout_routing(dest, dev);
+ 	} else {
+ 		return -EINVAL;
+ 	}
+@@ -6147,6 +6249,10 @@ static int ni_E_init(struct comedi_device *dev,
+ 		s->private	= gpct;
+ 	}
+ 
++	/* Initialize GPFO_{0,1} to produce output of counters */
++	ni_set_gout_routing(0, 0, dev); /* output of counter 0; DAQ STC, p338 */
++	ni_set_gout_routing(0, 1, dev); /* output of counter 1; DAQ STC, p338 */
++
+ 	/* Frequency output subdevice */
+ 	s = &dev->subdevices[NI_FREQ_OUT_SUBDEV];
+ 	s->type		= COMEDI_SUBD_COUNTER;
+diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h
+index 1867b64e23cf..6c023b40fb53 100644
+--- a/drivers/staging/comedi/drivers/ni_stc.h
++++ b/drivers/staging/comedi/drivers/ni_stc.h
+@@ -284,11 +284,15 @@
+ #define NISTC_ATRIG_ETC_REG		61
+ #define NISTC_ATRIG_ETC_GPFO_1_ENA	BIT(15)
+ #define NISTC_ATRIG_ETC_GPFO_0_ENA	BIT(14)
+-#define NISTC_ATRIG_ETC_GPFO_0_SEL(x)	(((x) & 0x3) << 11)
++#define NISTC_ATRIG_ETC_GPFO_0_SEL(x)	(((x) & 0x7) << 11)
++#define NISTC_ATRIG_ETC_GPFO_0_SEL_TO_SRC(x)	(((x) >> 11) & 0x7)
+ #define NISTC_ATRIG_ETC_GPFO_1_SEL	BIT(7)
++#define NISTC_ATRIG_ETC_GPFO_1_SEL_TO_SRC(x)	(((x) >> 7) & 0x1)
+ #define NISTC_ATRIG_ETC_DRV		BIT(4)
+ #define NISTC_ATRIG_ETC_ENA		BIT(3)
+ #define NISTC_ATRIG_ETC_MODE(x)		(((x) & 0x7) << 0)
++#define NISTC_GPFO_0_G_OUT		0 /* input to GPFO_0_SEL for Ctr0Out */
++#define NISTC_GPFO_1_G_OUT		0 /* input to GPFO_1_SEL for Ctr1Out */
+ 
+ #define NISTC_AI_START_STOP_REG		62
+ #define NISTC_AI_START_POLARITY		BIT(15)

commit d4961bb3d99f895fe8cf368b9765405a3f829198
+Author: Spencer E. Olson 
+Date:   Wed Oct 3 14:56:06 2018 -0600
+
+    staging: comedi: ni_mio_common: implement global pfi, rtsi routing
+    
+    Implement device-global config interface for ni_mio devices.  In
+    particular, this patch implements:
+    INSN_DEVICE_CONFIG_TEST_ROUTE,
+    INSN_DEVICE_CONFIG_CONNECT_ROUTE,
+    INSN_DEVICE_CONFIG_DISCONNECT_ROUTE,
+    INSN_DEVICE_CONFIG_GET_ROUTES
+    for the ni mio devices.  This means that the new abstracted signal/terminal
+    names can be used to define signal routing with regards to the PFI
+    terminals and RTSI trigger bus lines.
+    
+    This also adds ability to identify PFI and RTSI channels on the PFI and
+    RTSI subdevices using the new device-global names.  This does not change
+    the values that are set for channel output selections using the subdevice
+    interfaces--these still require direct register values.
+    
+    Annotates and updates tables of register values to reflect this new
+    implementation status.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index 31a567d593c9..d4c0fd07059b 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -351,7 +351,8 @@ static const struct mio_regmap m_series_stc_write_regmap[] = {
+ 	[NISTC_AO_PERSONAL_REG]		= { 0x19c, 2 },
+ 	[NISTC_RTSI_TRIGA_OUT_REG]	= { 0x19e, 2 },
+ 	[NISTC_RTSI_TRIGB_OUT_REG]	= { 0x1a0, 2 },
+-	[NISTC_RTSI_BOARD_REG]		= { 0, 0 }, /* Unknown */
++	/* doc for following line: mhddk/nimseries/ChipObjects/tMSeries.h */
++	[NISTC_RTSI_BOARD_REG]		= { 0x1a2, 2 },
+ 	[NISTC_CFG_MEM_CLR_REG]		= { 0x1a4, 2 },
+ 	[NISTC_ADC_FIFO_CLR_REG]	= { 0x1a6, 2 },
+ 	[NISTC_DAC_FIFO_CLR_REG]	= { 0x1a8, 2 },
+@@ -4590,24 +4591,33 @@ static unsigned int ni_get_pfi_routing(struct comedi_device *dev,
+ {
+ 	struct ni_private *devpriv = dev->private;
+ 
++	if (chan >= NI_PFI(0)) {
++		/* allow new and old names of pfi channels to work. */
++		chan -= NI_PFI(0);
++	}
+ 	return (devpriv->is_m_series)
+ 			? ni_m_series_get_pfi_routing(dev, chan)
+ 			: ni_old_get_pfi_routing(dev, chan);
+ }
+ 
++/* Sets the output mux for the specified PFI channel. */
+ static int ni_set_pfi_routing(struct comedi_device *dev,
+ 			      unsigned int chan, unsigned int source)
+ {
+ 	struct ni_private *devpriv = dev->private;
+ 
++	if (chan >= NI_PFI(0)) {
++		/* allow new and old names of pfi channels to work. */
++		chan -= NI_PFI(0);
++	}
+ 	return (devpriv->is_m_series)
+ 			? ni_m_series_set_pfi_routing(dev, chan, source)
+ 			: ni_old_set_pfi_routing(dev, chan, source);
+ }
+ 
+-static int ni_config_filter(struct comedi_device *dev,
+-			    unsigned int pfi_channel,
+-			    enum ni_pfi_filter_select filter)
++static int ni_config_pfi_filter(struct comedi_device *dev,
++				unsigned int chan,
++				enum ni_pfi_filter_select filter)
+ {
+ 	struct ni_private *devpriv = dev->private;
+ 	unsigned int bits;
+@@ -4615,19 +4625,46 @@ static int ni_config_filter(struct comedi_device *dev,
+ 	if (!devpriv->is_m_series)
+ 		return -ENOTSUPP;
+ 
++	if (chan >= NI_PFI(0)) {
++		/* allow new and old names of pfi channels to work. */
++		chan -= NI_PFI(0);
++	}
++
+ 	bits = ni_readl(dev, NI_M_PFI_FILTER_REG);
+-	bits &= ~NI_M_PFI_FILTER_SEL_MASK(pfi_channel);
+-	bits |= NI_M_PFI_FILTER_SEL(pfi_channel, filter);
++	bits &= ~NI_M_PFI_FILTER_SEL_MASK(chan);
++	bits |= NI_M_PFI_FILTER_SEL(chan, filter);
+ 	ni_writel(dev, bits, NI_M_PFI_FILTER_REG);
+ 	return 0;
+ }
+ 
++static void ni_set_pfi_direction(struct comedi_device *dev, int chan,
++				 unsigned int direction)
++{
++	if (chan >= NI_PFI(0)) {
++		/* allow new and old names of pfi channels to work. */
++		chan -= NI_PFI(0);
++	}
++	direction = (direction == COMEDI_OUTPUT) ? 1u : 0u;
++	ni_set_bits(dev, NISTC_IO_BIDIR_PIN_REG, 1 << chan, direction);
++}
++
++static int ni_get_pfi_direction(struct comedi_device *dev, int chan)
++{
++	struct ni_private *devpriv = dev->private;
++
++	if (chan >= NI_PFI(0)) {
++		/* allow new and old names of pfi channels to work. */
++		chan -= NI_PFI(0);
++	}
++	return devpriv->io_bidirection_pin_reg & (1 << chan) ?
++	       COMEDI_OUTPUT : COMEDI_INPUT;
++}
++
+ static int ni_pfi_insn_config(struct comedi_device *dev,
+ 			      struct comedi_subdevice *s,
+ 			      struct comedi_insn *insn,
+ 			      unsigned int *data)
+ {
+-	struct ni_private *devpriv = dev->private;
+ 	unsigned int chan;
+ 
+ 	if (insn->n < 1)
+@@ -4637,23 +4674,19 @@ static int ni_pfi_insn_config(struct comedi_device *dev,
+ 
+ 	switch (data[0]) {
+ 	case COMEDI_OUTPUT:
+-		ni_set_bits(dev, NISTC_IO_BIDIR_PIN_REG, 1 << chan, 1);
+-		break;
+ 	case COMEDI_INPUT:
+-		ni_set_bits(dev, NISTC_IO_BIDIR_PIN_REG, 1 << chan, 0);
++		ni_set_pfi_direction(dev, chan, data[0]);
+ 		break;
+ 	case INSN_CONFIG_DIO_QUERY:
+-		data[1] =
+-		    (devpriv->io_bidirection_pin_reg & (1 << chan)) ?
+-		    COMEDI_OUTPUT : COMEDI_INPUT;
+-		return 0;
++		data[1] = ni_get_pfi_direction(dev, chan);
++		break;
+ 	case INSN_CONFIG_SET_ROUTING:
+ 		return ni_set_pfi_routing(dev, chan, data[1]);
+ 	case INSN_CONFIG_GET_ROUTING:
+ 		data[1] = ni_get_pfi_routing(dev, chan);
+ 		break;
+ 	case INSN_CONFIG_FILTER:
+-		return ni_config_filter(dev, chan, data[1]);
++		return ni_config_pfi_filter(dev, chan, data[1]);
+ 	default:
+ 		return -EINVAL;
+ 	}
+@@ -5036,6 +5069,10 @@ static int ni_set_rtsi_routing(struct comedi_device *dev,
+ {
+ 	struct ni_private *devpriv = dev->private;
+ 
++	if (chan >= TRIGGER_LINE(0))
++		/* allow new and old names of rtsi channels to work. */
++		chan -= TRIGGER_LINE(0);
++
+ 	if (ni_valid_rtsi_output_source(dev, chan, src) == 0)
+ 		return -EINVAL;
+ 	if (chan < 4) {
+@@ -5064,6 +5101,10 @@ static unsigned int ni_get_rtsi_routing(struct comedi_device *dev,
+ {
+ 	struct ni_private *devpriv = dev->private;
+ 
++	if (chan >= TRIGGER_LINE(0))
++		/* allow new and old names of rtsi channels to work. */
++		chan -= TRIGGER_LINE(0);
++
+ 	if (chan < 4) {
+ 		return NISTC_RTSI_TRIG_TO_SRC(chan,
+ 					      devpriv->rtsi_trig_a_output_reg);
+@@ -5078,17 +5119,17 @@ static unsigned int ni_get_rtsi_routing(struct comedi_device *dev,
+ 	return -EINVAL;
+ }
+ 
+-static int ni_rtsi_insn_config(struct comedi_device *dev,
+-			       struct comedi_subdevice *s,
+-			       struct comedi_insn *insn,
+-			       unsigned int *data)
++static void ni_set_rtsi_direction(struct comedi_device *dev, int chan,
++				  unsigned int direction)
+ {
+ 	struct ni_private *devpriv = dev->private;
+-	unsigned int chan = CR_CHAN(insn->chanspec);
+ 	unsigned int max_chan = NISTC_RTSI_TRIG_NUM_CHAN(devpriv->is_m_series);
+ 
+-	switch (data[0]) {
+-	case INSN_CONFIG_DIO_OUTPUT:
++	if (chan >= TRIGGER_LINE(0))
++		/* allow new and old names of rtsi channels to work. */
++		chan -= TRIGGER_LINE(0);
++
++	if (direction == COMEDI_OUTPUT) {
+ 		if (chan < max_chan) {
+ 			devpriv->rtsi_trig_direction_reg |=
+ 			    NISTC_RTSI_TRIG_DIR(chan, devpriv->is_m_series);
+@@ -5096,10 +5137,7 @@ static int ni_rtsi_insn_config(struct comedi_device *dev,
+ 			devpriv->rtsi_trig_direction_reg |=
+ 			    NISTC_RTSI_TRIG_DRV_CLK;
+ 		}
+-		ni_stc_writew(dev, devpriv->rtsi_trig_direction_reg,
+-			      NISTC_RTSI_TRIG_DIR_REG);
+-		break;
+-	case INSN_CONFIG_DIO_INPUT:
++	} else {
+ 		if (chan < max_chan) {
+ 			devpriv->rtsi_trig_direction_reg &=
+ 			    ~NISTC_RTSI_TRIG_DIR(chan, devpriv->is_m_series);
+@@ -5107,23 +5145,53 @@ static int ni_rtsi_insn_config(struct comedi_device *dev,
+ 			devpriv->rtsi_trig_direction_reg &=
+ 			    ~NISTC_RTSI_TRIG_DRV_CLK;
+ 		}
+-		ni_stc_writew(dev, devpriv->rtsi_trig_direction_reg,
+-			      NISTC_RTSI_TRIG_DIR_REG);
++	}
++	ni_stc_writew(dev, devpriv->rtsi_trig_direction_reg,
++		      NISTC_RTSI_TRIG_DIR_REG);
++}
++
++static int ni_get_rtsi_direction(struct comedi_device *dev, int chan)
++{
++	struct ni_private *devpriv = dev->private;
++	unsigned int max_chan = NISTC_RTSI_TRIG_NUM_CHAN(devpriv->is_m_series);
++
++	if (chan >= TRIGGER_LINE(0))
++		/* allow new and old names of rtsi channels to work. */
++		chan -= TRIGGER_LINE(0);
++
++	if (chan < max_chan) {
++		return (devpriv->rtsi_trig_direction_reg &
++			NISTC_RTSI_TRIG_DIR(chan, devpriv->is_m_series))
++			   ? COMEDI_OUTPUT : COMEDI_INPUT;
++	} else if (chan == NISTC_RTSI_TRIG_OLD_CLK_CHAN) {
++		return (devpriv->rtsi_trig_direction_reg &
++			NISTC_RTSI_TRIG_DRV_CLK)
++			   ? COMEDI_OUTPUT : COMEDI_INPUT;
++	}
++	return -EINVAL;
++}
++
++static int ni_rtsi_insn_config(struct comedi_device *dev,
++			       struct comedi_subdevice *s,
++			       struct comedi_insn *insn,
++			       unsigned int *data)
++{
++	struct ni_private *devpriv = dev->private;
++	unsigned int chan = CR_CHAN(insn->chanspec);
++
++	switch (data[0]) {
++	case COMEDI_OUTPUT:
++	case COMEDI_INPUT:
++		ni_set_rtsi_direction(dev, chan, data[0]);
+ 		break;
+-	case INSN_CONFIG_DIO_QUERY:
+-		if (chan < max_chan) {
+-			data[1] =
+-			    (devpriv->rtsi_trig_direction_reg &
+-			     NISTC_RTSI_TRIG_DIR(chan, devpriv->is_m_series))
+-				? INSN_CONFIG_DIO_OUTPUT
+-				: INSN_CONFIG_DIO_INPUT;
+-		} else if (chan == NISTC_RTSI_TRIG_OLD_CLK_CHAN) {
+-			data[1] = (devpriv->rtsi_trig_direction_reg &
+-				   NISTC_RTSI_TRIG_DRV_CLK)
+-				  ? INSN_CONFIG_DIO_OUTPUT
+-				  : INSN_CONFIG_DIO_INPUT;
+-		}
++	case INSN_CONFIG_DIO_QUERY: {
++		int ret = ni_get_rtsi_direction(dev, chan);
++
++		if (ret < 0)
++			return ret;
++		data[1] = ret;
+ 		return 2;
++	}
+ 	case INSN_CONFIG_SET_CLOCK_SRC:
+ 		return ni_set_master_clock(dev, data[1], data[2]);
+ 	case INSN_CONFIG_GET_CLOCK_SRC:
+@@ -5132,9 +5200,14 @@ static int ni_rtsi_insn_config(struct comedi_device *dev,
+ 		return 3;
+ 	case INSN_CONFIG_SET_ROUTING:
+ 		return ni_set_rtsi_routing(dev, chan, data[1]);
+-	case INSN_CONFIG_GET_ROUTING:
+-		data[1] = ni_get_rtsi_routing(dev, chan);
++	case INSN_CONFIG_GET_ROUTING: {
++		int ret = ni_get_rtsi_routing(dev, chan);
++
++		if (ret < 0)
++			return ret;
++		data[1] = ret;
+ 		return 2;
++	}
+ 	default:
+ 		return -EINVAL;
+ 	}
+@@ -5151,9 +5224,275 @@ static int ni_rtsi_insn_bits(struct comedi_device *dev,
+ 	return insn->n;
+ }
+ 
++/*
++ * Default routing for RTSI trigger lines.
++ *
++ * These values are used here in the init function, as well as in the
++ * disconnect_route function, after a RTSI route has been disconnected.
++ */
++static const int default_rtsi_routing[] = {
++	[0] = NI_RTSI_OUTPUT_ADR_START1,
++	[1] = NI_RTSI_OUTPUT_ADR_START2,
++	[2] = NI_RTSI_OUTPUT_SCLKG,
++	[3] = NI_RTSI_OUTPUT_DACUPDN,
++	[4] = NI_RTSI_OUTPUT_DA_START1,
++	[5] = NI_RTSI_OUTPUT_G_SRC0,
++	[6] = NI_RTSI_OUTPUT_G_GATE0,
++	[7] = NI_RTSI_OUTPUT_RTSI_OSC,
++};
++
++/*
++ * Route signals through RGOUT0 terminal.
++ * @reg: raw register value of RGOUT0 bits (only bit0 is important).
++ * @dev: comedi device handle.
++ */
++static void set_rgout0_reg(int reg, struct comedi_device *dev)
++{
++	struct ni_private *devpriv = dev->private;
++
++	if (devpriv->is_m_series) {
++		devpriv->rtsi_trig_direction_reg &=
++			~NISTC_RTSI_TRIG_DIR_SUB_SEL1;
++		devpriv->rtsi_trig_direction_reg |=
++			(reg << NISTC_RTSI_TRIG_DIR_SUB_SEL1_SHIFT) &
++			NISTC_RTSI_TRIG_DIR_SUB_SEL1;
++		ni_stc_writew(dev, devpriv->rtsi_trig_direction_reg,
++			      NISTC_RTSI_TRIG_DIR_REG);
++	} else {
++		devpriv->rtsi_trig_b_output_reg &= ~NISTC_RTSI_TRIGB_SUB_SEL1;
++		devpriv->rtsi_trig_b_output_reg |=
++			(reg << NISTC_RTSI_TRIGB_SUB_SEL1_SHIFT) &
++			NISTC_RTSI_TRIGB_SUB_SEL1;
++		ni_stc_writew(dev, devpriv->rtsi_trig_b_output_reg,
++			      NISTC_RTSI_TRIGB_OUT_REG);
++	}
++}
++
++static int get_rgout0_reg(struct comedi_device *dev)
++{
++	struct ni_private *devpriv = dev->private;
++	int reg;
++
++	if (devpriv->is_m_series)
++		reg = (devpriv->rtsi_trig_direction_reg &
++		       NISTC_RTSI_TRIG_DIR_SUB_SEL1)
++		    >> NISTC_RTSI_TRIG_DIR_SUB_SEL1_SHIFT;
++	else
++		reg = (devpriv->rtsi_trig_b_output_reg &
++		       NISTC_RTSI_TRIGB_SUB_SEL1)
++		    >> NISTC_RTSI_TRIGB_SUB_SEL1_SHIFT;
++	return reg;
++}
++
++static inline int get_rgout0_src(struct comedi_device *dev)
++{
++	struct ni_private *devpriv = dev->private;
++	int reg = get_rgout0_reg(dev);
++
++	return ni_find_route_source(reg, NI_RGOUT0, &devpriv->routing_tables);
++}
++
++/*
++ * Route signals through RGOUT0 terminal and increment the RGOUT0 use for this
++ * particular route.
++ * @src: device-global signal name
++ * @dev: comedi device handle
++ *
++ * Return: -EINVAL if the source is not valid to route to RGOUT0;
++ *	   -EBUSY if the RGOUT0 is already used;
++ *	   0 if successful.
++ */
++static int incr_rgout0_src_use(int src, struct comedi_device *dev)
++{
++	struct ni_private *devpriv = dev->private;
++	s8 reg = ni_lookup_route_register(CR_CHAN(src), NI_RGOUT0,
++					  &devpriv->routing_tables);
++
++	if (reg < 0)
++		return -EINVAL;
++
++	if (devpriv->rgout0_usage > 0 && get_rgout0_reg(dev) != reg)
++		return -EBUSY;
++
++	++devpriv->rgout0_usage;
++	set_rgout0_reg(reg, dev);
++	return 0;
++}
++
++/*
++ * Unroute signals through RGOUT0 terminal and deccrement the RGOUT0 use for
++ * this particular source.  This function does not actually unroute anything
++ * with respect to RGOUT0.  It does, on the other hand, decrement the usage
++ * counter for the current src->RGOUT0 mapping.
++ *
++ * Return: -EINVAL if the source is not already routed to RGOUT0 (or usage is
++ *	already at zero); 0 if successful.
++ */
++static int decr_rgout0_src_use(int src, struct comedi_device *dev)
++{
++	struct ni_private *devpriv = dev->private;
++	s8 reg = ni_lookup_route_register(CR_CHAN(src), NI_RGOUT0,
++					  &devpriv->routing_tables);
++
++	if (devpriv->rgout0_usage > 0 && get_rgout0_reg(dev) == reg) {
++		--devpriv->rgout0_usage;
++		if (!devpriv->rgout0_usage)
++			set_rgout0_reg(0, dev); /* ok default? */
++		return 0;
++	}
++	return -EINVAL;
++}
++
++/*
++ * Route signals through given NI_RTSI_BRD mux.
++ * @i: index of mux to route
++ * @reg: raw register value of RTSI_BRD bits
++ * @dev: comedi device handle
++ */
++static void set_ith_rtsi_brd_reg(int i, int reg, struct comedi_device *dev)
++{
++	struct ni_private *devpriv = dev->private;
++	int reg_i_sz = 3; /* value for e-series */
++	int reg_i_mask;
++	int reg_i_shift;
++
++	if (devpriv->is_m_series)
++		reg_i_sz = 4;
++	reg_i_mask = ~((~0) << reg_i_sz);
++	reg_i_shift = i * reg_i_sz;
++
++	/* clear out the current reg_i for ith brd */
++	devpriv->rtsi_shared_mux_reg &= ~(reg_i_mask       << reg_i_shift);
++	/* (softcopy) write the new reg_i for ith brd */
++	devpriv->rtsi_shared_mux_reg |= (reg & reg_i_mask) << reg_i_shift;
++	/* (hardcopy) write the new reg_i for ith brd */
++	ni_stc_writew(dev, devpriv->rtsi_shared_mux_reg, NISTC_RTSI_BOARD_REG);
++}
++
++static int get_ith_rtsi_brd_reg(int i, struct comedi_device *dev)
++{
++	struct ni_private *devpriv = dev->private;
++	int reg_i_sz = 3; /* value for e-series */
++	int reg_i_mask;
++	int reg_i_shift;
++
++	if (devpriv->is_m_series)
++		reg_i_sz = 4;
++	reg_i_mask = ~((~0) << reg_i_sz);
++	reg_i_shift = i * reg_i_sz;
++
++	return (devpriv->rtsi_shared_mux_reg >> reg_i_shift) & reg_i_mask;
++}
++
++static inline int get_rtsi_brd_src(int brd, struct comedi_device *dev)
++{
++	struct ni_private *devpriv = dev->private;
++	int brd_index = brd;
++	int reg;
++
++	if (brd >= NI_RTSI_BRD(0))
++		brd_index = brd - NI_RTSI_BRD(0);
++	else
++		brd = NI_RTSI_BRD(brd);
++	/*
++	 * And now:
++	 * brd : device-global name
++	 * brd_index : index number of RTSI_BRD mux
++	 */
++
++	reg = get_ith_rtsi_brd_reg(brd_index, dev);
++
++	return ni_find_route_source(reg, brd, &devpriv->routing_tables);
++}
++
++/*
++ * Route signals through NI_RTSI_BRD mux and increment the use counter for this
++ * particular route.
++ *
++ * Return: -EINVAL if the source is not valid to route to NI_RTSI_BRD(i);
++ *	   -EBUSY if all NI_RTSI_BRD muxes are already used;
++ *	   NI_RTSI_BRD(i) of allocated ith mux if successful.
++ */
++static int incr_rtsi_brd_src_use(int src, struct comedi_device *dev)
++{
++	struct ni_private *devpriv = dev->private;
++	int first_available = -1;
++	int err = -EINVAL;
++	s8 reg;
++	int i;
++
++	/* first look for a mux that is already configured to provide src */
++	for (i = 0; i < NUM_RTSI_SHARED_MUXS; ++i) {
++		reg = ni_lookup_route_register(CR_CHAN(src), NI_RTSI_BRD(i),
++					       &devpriv->routing_tables);
++
++		if (reg < 0)
++			continue; /* invalid route */
++
++		if (!devpriv->rtsi_shared_mux_usage[i]) {
++			if (first_available < 0)
++				/* found the first unused, but usable mux */
++				first_available = i;
++		} else {
++			/*
++			 * we've seen at least one possible route, so change the
++			 * final error to -EBUSY in case there are no muxes
++			 * available.
++			 */
++			err = -EBUSY;
++
++			if (get_ith_rtsi_brd_reg(i, dev) == reg) {
++				/*
++				 * we've found a mux that is already being used
++				 * to provide the requested signal.  Reuse it.
++				 */
++				goto success;
++			}
++		}
++	}
++
++	if (first_available < 0)
++		return err;
++
++	/* we did not find a mux to reuse, but there is at least one usable */
++	i = first_available;
++
++success:
++	++devpriv->rtsi_shared_mux_usage[i];
++	set_ith_rtsi_brd_reg(i, reg, dev);
++	return NI_RTSI_BRD(i);
++}
++
++/*
++ * Unroute signals through NI_RTSI_BRD mux and decrement the user counter for
++ * this particular route.
++ *
++ * Return: -EINVAL if the source is not already routed to rtsi_brd(i) (or usage
++ *	is already at zero); 0 if successful.
++ */
++static int decr_rtsi_brd_src_use(int src, int rtsi_brd,
++				 struct comedi_device *dev)
++{
++	struct ni_private *devpriv = dev->private;
++	s8 reg = ni_lookup_route_register(CR_CHAN(src), rtsi_brd,
++					  &devpriv->routing_tables);
++	const int i = rtsi_brd - NI_RTSI_BRD(0);
++
++	if (devpriv->rtsi_shared_mux_usage[i] > 0 &&
++	    get_ith_rtsi_brd_reg(i, dev) == reg) {
++		--devpriv->rtsi_shared_mux_usage[i];
++		if (!devpriv->rtsi_shared_mux_usage[i])
++			set_ith_rtsi_brd_reg(i, 0, dev); /* ok default? */
++		return 0;
++	}
++
++	return -EINVAL;
++}
++
+ static void ni_rtsi_init(struct comedi_device *dev)
+ {
+ 	struct ni_private *devpriv = dev->private;
++	int i;
+ 
+ 	/*  Initialises the RTSI bus signal switch to a default state */
+ 
+@@ -5166,28 +5505,215 @@ static void ni_rtsi_init(struct comedi_device *dev)
+ 	/*  Set clock mode to internal */
+ 	if (ni_set_master_clock(dev, NI_MIO_INTERNAL_CLOCK, 0) < 0)
+ 		dev_err(dev->class_dev, "ni_set_master_clock failed, bug?\n");
+-	/*  default internal lines routing to RTSI bus lines */
+-	devpriv->rtsi_trig_a_output_reg =
+-	    NISTC_RTSI_TRIG(0, NI_RTSI_OUTPUT_ADR_START1) |
+-	    NISTC_RTSI_TRIG(1, NI_RTSI_OUTPUT_ADR_START2) |
+-	    NISTC_RTSI_TRIG(2, NI_RTSI_OUTPUT_SCLKG) |
+-	    NISTC_RTSI_TRIG(3, NI_RTSI_OUTPUT_DACUPDN);
+-	ni_stc_writew(dev, devpriv->rtsi_trig_a_output_reg,
+-		      NISTC_RTSI_TRIGA_OUT_REG);
+-	devpriv->rtsi_trig_b_output_reg =
+-	    NISTC_RTSI_TRIG(4, NI_RTSI_OUTPUT_DA_START1) |
+-	    NISTC_RTSI_TRIG(5, NI_RTSI_OUTPUT_G_SRC0) |
+-	    NISTC_RTSI_TRIG(6, NI_RTSI_OUTPUT_G_GATE0);
+-	if (devpriv->is_m_series)
+-		devpriv->rtsi_trig_b_output_reg |=
+-		    NISTC_RTSI_TRIG(7, NI_RTSI_OUTPUT_RTSI_OSC);
+-	ni_stc_writew(dev, devpriv->rtsi_trig_b_output_reg,
+-		      NISTC_RTSI_TRIGB_OUT_REG);
++
++	/* default internal lines routing to RTSI bus lines */
++	for (i = 0; i < 8; ++i) {
++		ni_set_rtsi_direction(dev, i, COMEDI_INPUT);
++		ni_set_rtsi_routing(dev, i, default_rtsi_routing[i]);
++	}
+ 
+ 	/*
+-	 * Sets the source and direction of the 4 on board lines
+-	 * ni_stc_writew(dev, 0, NISTC_RTSI_BOARD_REG);
++	 * Sets the source and direction of the 4 on board lines.
++	 * This configures all board lines to be:
++	 * for e-series:
++	 *   1) inputs (not sure what "output" would mean)
++	 *   2) copying TRIGGER_LINE(0) (or RTSI0) output
++	 * for m-series:
++	 *   copying NI_PFI(0) output
+ 	 */
++	devpriv->rtsi_shared_mux_reg = 0;
++	for (i = 0; i < 4; ++i)
++		set_ith_rtsi_brd_reg(i, 0, dev);
++	memset(devpriv->rtsi_shared_mux_usage, 0,
++	       sizeof(devpriv->rtsi_shared_mux_usage));
++
++	/* initialize rgout0 pin as unused. */
++	devpriv->rgout0_usage = 0;
++	set_rgout0_reg(0, dev);
++}
++
++/*
++ * Retrieves the current source of the output selector for the given
++ * destination.  If the terminal for the destination is not already configured
++ * as an output, this function returns -EINVAL as error.
++ *
++ * Return: the register value of the destination output selector;
++ *	   -EINVAL if terminal is not configured for output.
++ */
++static int get_output_select_source(int dest, struct comedi_device *dev)
++{
++	struct ni_private *devpriv = dev->private;
++	int reg = -1;
++
++	if (channel_is_pfi(dest)) {
++		if (ni_get_pfi_direction(dev, dest) == COMEDI_OUTPUT)
++			reg = ni_get_pfi_routing(dev, dest);
++	} else if (channel_is_rtsi(dest)) {
++		if (ni_get_rtsi_direction(dev, dest) == COMEDI_OUTPUT) {
++			reg = ni_get_rtsi_routing(dev, dest);
++
++			if (reg == NI_RTSI_OUTPUT_RGOUT0) {
++				dest = NI_RGOUT0; /* prepare for lookup below */
++				reg = get_rgout0_reg(dev);
++			} else if (reg >= NI_RTSI_OUTPUT_RTSI_BRD(0) &&
++				   reg <= NI_RTSI_OUTPUT_RTSI_BRD(3)) {
++				const int i = reg - NI_RTSI_OUTPUT_RTSI_BRD(0);
++
++				dest = NI_RTSI_BRD(i); /* prepare for lookup */
++				reg = get_ith_rtsi_brd_reg(i, dev);
++			}
++		}
++	} else {
++		dev_dbg(dev->class_dev, "%s: unhandled destination (%d) queried\n",
++			__func__, dest);
++	}
++
++	if (reg >= 0)
++		return ni_find_route_source(CR_CHAN(reg), dest,
++					    &devpriv->routing_tables);
++	return -EINVAL;
++}
++
++/*
++ * Test a route:
++ *
++ * Return: -1 if not connectible;
++ *	    0 if connectible and not connected;
++ *	    1 if connectible and connected.
++ */
++static int test_route(unsigned int src, unsigned int dest,
++		      struct comedi_device *dev)
++{
++	struct ni_private *devpriv = dev->private;
++	s8 reg = ni_route_to_register(CR_CHAN(src), dest,
++				      &devpriv->routing_tables);
++
++	if (reg < 0)
++		return -1;
++	if (get_output_select_source(dest, dev) != CR_CHAN(src))
++		return 0;
++	return 1;
++}
++
++/* Connect the actual route.  */
++static int connect_route(unsigned int src, unsigned int dest,
++			 struct comedi_device *dev)
++{
++	struct ni_private *devpriv = dev->private;
++	s8 reg = ni_route_to_register(CR_CHAN(src), dest,
++				      &devpriv->routing_tables);
++	s8 current_src;
++
++	if (reg < 0)
++		/* route is not valid */
++		return -EINVAL;
++
++	current_src = get_output_select_source(dest, dev);
++	if (current_src == CR_CHAN(src))
++		return -EALREADY;
++	if (current_src >= 0)
++		/* destination mux is already busy. complain, don't overwrite */
++		return -EBUSY;
++
++	/* The route is valid and available. Now connect... */
++	if (channel_is_pfi(dest)) {
++		/* set routing source, then open output */
++		ni_set_pfi_routing(dev, dest, reg);
++		ni_set_pfi_direction(dev, dest, COMEDI_OUTPUT);
++	} else if (channel_is_rtsi(dest)) {
++		if (reg == NI_RTSI_OUTPUT_RGOUT0) {
++			int ret = incr_rgout0_src_use(src, dev);
++
++			if (ret < 0)
++				return ret;
++		} else if (ni_rtsi_route_requires_mux(reg)) {
++			/* Attempt to allocate and  route (src->brd) */
++			int brd = incr_rtsi_brd_src_use(src, dev);
++
++			if (brd < 0)
++				return brd;
++
++			/* Now lookup the register value for (brd->dest) */
++			reg = ni_lookup_route_register(
++				brd, dest, &devpriv->routing_tables);
++		}
++
++		ni_set_rtsi_direction(dev, dest, COMEDI_OUTPUT);
++		ni_set_rtsi_routing(dev, dest, reg);
++	} else {
++		return -EINVAL;
++	}
++	return 0;
++}
++
++static int disconnect_route(unsigned int src, unsigned int dest,
++			    struct comedi_device *dev)
++{
++	struct ni_private *devpriv = dev->private;
++	s8 reg = ni_route_to_register(CR_CHAN(src), dest,
++				      &devpriv->routing_tables);
++
++	if (reg < 0)
++		/* route is not valid */
++		return -EINVAL;
++	if (get_output_select_source(dest, dev) != src)
++		/* cannot disconnect something not connected */
++		return -EINVAL;
++
++	/* The route is valid and is connected.  Now disconnect... */
++	if (channel_is_pfi(dest)) {
++		/* set the pfi to high impedance, and disconnect */
++		ni_set_pfi_direction(dev, dest, COMEDI_INPUT);
++		ni_set_pfi_routing(dev, dest, NI_PFI_OUTPUT_PFI_DEFAULT);
++	} else if (channel_is_rtsi(dest)) {
++		if (reg == NI_RTSI_OUTPUT_RGOUT0) {
++			int ret = decr_rgout0_src_use(src, dev);
++
++			if (ret < 0)
++				return ret;
++		} else if (ni_rtsi_route_requires_mux(reg)) {
++			/* find which RTSI_BRD line is source for rtsi pin */
++			int brd = ni_find_route_source(
++				ni_get_rtsi_routing(dev, dest), dest,
++				&devpriv->routing_tables);
++
++			if (brd < 0)
++				return brd;
++
++			/* decrement/disconnect RTSI_BRD line from source */
++			decr_rtsi_brd_src_use(src, brd, dev);
++		}
++
++		/* set rtsi output selector to default state */
++		reg = default_rtsi_routing[dest - TRIGGER_LINE(0)];
++		ni_set_rtsi_direction(dev, dest, COMEDI_INPUT);
++		ni_set_rtsi_routing(dev, dest, reg);
++	} else {
++		return -EINVAL;
++	}
++	return 0;
++}
++
++static int ni_global_insn_config(struct comedi_device *dev,
++				 struct comedi_insn *insn,
++				 unsigned int *data)
++{
++	switch (data[0]) {
++	case INSN_DEVICE_CONFIG_TEST_ROUTE:
++		data[0] = test_route(data[1], data[2], dev);
++		return 2;
++	case INSN_DEVICE_CONFIG_CONNECT_ROUTE:
++		return connect_route(data[1], data[2], dev);
++	case INSN_DEVICE_CONFIG_DISCONNECT_ROUTE:
++		return disconnect_route(data[1], data[2], dev);
++	/*
++	 * This case is already handled one level up.
++	 * case INSN_DEVICE_CONFIG_GET_ROUTES:
++	 */
++	default:
++		return -EINVAL;
++	}
++	return 1;
+ }
+ 
+ #ifdef PCIDMA
+@@ -5293,6 +5819,16 @@ static int ni_alloc_private(struct comedi_device *dev)
+ 	return 0;
+ }
+ 
++static unsigned int _ni_get_valid_routes(struct comedi_device *dev,
++					 unsigned int n_pairs,
++					 unsigned int *pair_data)
++{
++	struct ni_private *devpriv = dev->private;
++
++	return ni_get_valid_routes(&devpriv->routing_tables, n_pairs,
++				   pair_data);
++}
++
+ static int ni_E_init(struct comedi_device *dev,
+ 		     unsigned int interrupt_pin, unsigned int irq_polarity)
+ {
+@@ -5304,6 +5840,22 @@ static int ni_E_init(struct comedi_device *dev,
+ 	const char *dev_family = devpriv->is_m_series ? "ni_mseries"
+ 						      : "ni_eseries";
+ 
++	/* prepare the device for globally-named routes. */
++	if (ni_assign_device_routes(dev_family, board->name,
++				    &devpriv->routing_tables) < 0) {
++		dev_warn(dev->class_dev, "%s: %s device has no signal routing table.\n",
++			 __func__, board->name);
++		dev_warn(dev->class_dev, "%s: High level NI signal names will not be available for this %s board.\n",
++			 __func__, board->name);
++	} else {
++		/*
++		 * only(?) assign insn_device_config if we have global names for
++		 * this device.
++		 */
++		dev->insn_device_config = ni_global_insn_config;
++		dev->get_valid_routes = _ni_get_valid_routes;
++	}
++
+ 	if (board->n_aochan > MAX_N_AO_CHAN) {
+ 		dev_err(dev->class_dev, "bug! n_aochan > MAX_N_AO_CHAN\n");
+ 		return -EINVAL;
+@@ -5634,15 +6186,6 @@ static int ni_E_init(struct comedi_device *dev,
+ 		ni_writeb(dev, 0x0, NI_M_AO_CALIB_REG);
+ 	}
+ 
+-	/* prepare the device for globally-named routes. */
+-	if (ni_assign_device_routes(dev_family, board->name,
+-				    &devpriv->routing_tables) < 0) {
+-		dev_warn(dev->class_dev, "%s: %s device has no signal routing table.\n",
+-			 __func__, board->name);
+-		dev_warn(dev->class_dev, "%s: High level NI signal names will not be available for this %s board.\n",
+-			 __func__, board->name);
+-	}
+-
+ 	return 0;
+ }
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h
+index 771eaef3815d..1867b64e23cf 100644
+--- a/drivers/staging/comedi/drivers/ni_stc.h
++++ b/drivers/staging/comedi/drivers/ni_stc.h
+@@ -254,6 +254,8 @@
+ #define NISTC_RTSI_TRIG_OLD_CLK_CHAN	7
+ #define NISTC_RTSI_TRIG_NUM_CHAN(_m)	((_m) ? 8 : 7)
+ #define NISTC_RTSI_TRIG_DIR(_c, _m)	((_m) ? BIT(8 + (_c)) : BIT(7 + (_c)))
++#define NISTC_RTSI_TRIG_DIR_SUB_SEL1	BIT(2)	/* only for M-Series */
++#define NISTC_RTSI_TRIG_DIR_SUB_SEL1_SHIFT	2	/* only for M-Series */
+ #define NISTC_RTSI_TRIG_USE_CLK		BIT(1)
+ #define NISTC_RTSI_TRIG_DRV_CLK		BIT(0)
+ 
+@@ -423,6 +425,7 @@
+ #define NISTC_RTSI_TRIGA_OUT_REG	79
+ #define NISTC_RTSI_TRIGB_OUT_REG	80
+ #define NISTC_RTSI_TRIGB_SUB_SEL1	BIT(15)	/* not for M-Series */
++#define NISTC_RTSI_TRIGB_SUB_SEL1_SHIFT	15	/* not for M-Series */
+ #define NISTC_RTSI_TRIG(_c, _s)		(((_s) & 0xf) << (((_c) % 4) * 4))
+ #define NISTC_RTSI_TRIG_MASK(_c)	NISTC_RTSI_TRIG((_c), 0xf)
+ #define NISTC_RTSI_TRIG_TO_SRC(_c, _b)	(((_b) >> (((_c) % 4) * 4)) & 0xf)
+@@ -964,6 +967,7 @@ struct ni_board_struct {
+ #define NUM_GPCT			2
+ 
+ #define NUM_PFI_OUTPUT_SELECT_REGS	6
++#define NUM_RTSI_SHARED_MUXS		(NI_RTSI_BRD(-1) - NI_RTSI_BRD(0) + 1)
+ 
+ #define M_SERIES_EEPROM_SIZE		1024
+ 
+@@ -1062,6 +1066,70 @@ struct ni_private {
+ 
+ 	/* device signal route tables */
+ 	struct ni_route_tables routing_tables;
++
++	/*
++	 * Number of clients (RTSI lines) for current RTSI MUX source.
++	 *
++	 * This allows resource management of RTSI board/shared mux lines by
++	 * marking the RTSI line that is using a particular MUX.  Currently,
++	 * these lines are only automatically allocated based on source of the
++	 * route requested.  Furthermore, the only way that this auto-allocation
++	 * and configuration works is via the globally-named ni signal/terminal
++	 * names.
++	 */
++	u8 rtsi_shared_mux_usage[NUM_RTSI_SHARED_MUXS];
++
++	/*
++	 * softcopy register for rtsi shared mux/board lines.
++	 * For e-series, the bit layout of this register is
++	 * (docs: mhddk/nieseries/ChipObjects/tSTC.{h,ipp},
++	 *        DAQ-STC, Jan 1999, 340934B-01):
++	 *   bits 0:2  --  NI_RTSI_BRD(0) source selection
++	 *   bits 3:5  --  NI_RTSI_BRD(1) source selection
++	 *   bits 6:8  --  NI_RTSI_BRD(2) source selection
++	 *   bits 9:11 --  NI_RTSI_BRD(3) source selection
++	 *   bit  12   --  NI_RTSI_BRD(0) direction, 0:input, 1:output
++	 *   bit  13   --  NI_RTSI_BRD(1) direction, 0:input, 1:output
++	 *   bit  14   --  NI_RTSI_BRD(2) direction, 0:input, 1:output
++	 *   bit  15   --  NI_RTSI_BRD(3) direction, 0:input, 1:output
++	 *   According to DAQ-STC:
++	 *     RTSI Board Interface--Configured as an input, each bidirectional
++	 *     RTSI_BRD pin can drive any of the seven RTSI_TRIGGER pins.
++	 *     RTSI_BRD<0..1> can also be driven by AI STOP and RTSI_BRD<2..3>
++	 *     can also be driven by the AI START and SCAN_IN_PROG signals.
++	 *     These pins provide a mechanism for additional board-level signals
++	 *     to be sent on or received from the RTSI bus.
++	 *   Couple of comments:
++	 *   - Neither the DAQ-STC nor the MHDDK is clear on what the direction
++	 *     of the RTSI_BRD pins actually means.  There does not appear to be
++	 *     any clear indication on what "output" would mean, since the point
++	 *     of the RTSI_BRD lines is to always drive one of the
++	 *     RTSI_TRIGGER<0..6> lines.
++	 *   - The DAQ-STC also indicates that the NI_RTSI_BRD lines can be
++	 *     driven by any of the RTSI_TRIGGER<0..6> lines.
++	 *     But, looking at valid device routes, as visually imported from
++	 *     NI-MAX, there appears to be only one family (so far) that has the
++	 *     ability to route a signal from one TRIGGER_LINE to another
++	 *     TRIGGER_LINE: the 653x family of DIO devices.
++	 *
++	 * For m-series, the bit layout of this register is
++	 * (docs: mhddk/nimseries/ChipObjects/tMSeries.{h,ipp}):
++	 *   bits  0:3  --  NI_RTSI_BRD(0) source selection
++	 *   bits  4:7  --  NI_RTSI_BRD(1) source selection
++	 *   bits  8:11 --  NI_RTSI_BRD(2) source selection
++	 *   bits 12:15 --  NI_RTSI_BRD(3) source selection
++	 *   Note:  The m-series does not have any option to change direction of
++	 *   NI_RTSI_BRD muxes.  Furthermore, there are no register values that
++	 *   indicate the ability to have TRIGGER_LINES driving the output of
++	 *   the NI_RTSI_BRD muxes.
++	 */
++	u16 rtsi_shared_mux_reg;
++
++	/*
++	 * Number of clients (RTSI lines) for current RGOUT0 path.
++	 * Stored in part of in RTSI_TRIG_DIR or RTSI_TRIGB registers
++	 */
++	u8 rgout0_usage;
+ };
+ 
+ static const struct comedi_lrange range_ni_E_ao_ext;

commit 56d0b826d39f5b04dc5df7e270539361627684de
+Author: Spencer E. Olson 
+Date:   Wed Oct 3 14:56:05 2018 -0600
+
+    staging: comedi: ni_mio_common: implement new routing for TRIG_EXT
+    
+    Use new signal routing capability for all comedi command *_src == TRIG_EXT
+    options.  This new interface allows the user specify signals and terminals
+    as TRIG_EXT sources using a very consistent naming convention. Furthermore,
+    the interface allows backwards compatibility to prior behavior of
+    specifying register-level (or near register-level) values as *_arg options
+    when *_src == TRIG_EXT.
+    
+    Annotates and updates tables of register values to reflect this new
+    implementation status.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index 961ea97966f5..31a567d593c9 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -2006,7 +2006,6 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	const struct ni_board_struct *board = dev->board_ptr;
+ 	struct ni_private *devpriv = dev->private;
+ 	int err = 0;
+-	unsigned int tmp;
+ 	unsigned int sources;
+ 
+ 	/* Step 1 : check if triggers are trivially valid */
+@@ -2047,12 +2046,9 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+ 		err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
+ 		break;
+ 	case TRIG_EXT:
+-		tmp = CR_CHAN(cmd->start_arg);
+-
+-		if (tmp > 16)
+-			tmp = 16;
+-		tmp |= (cmd->start_arg & (CR_INVERT | CR_EDGE));
+-		err |= comedi_check_trigger_arg_is(&cmd->start_arg, tmp);
++		err |= ni_check_trigger_arg_roffs(CR_CHAN(cmd->start_arg),
++						  NI_AI_StartTrigger,
++						  &devpriv->routing_tables, 1);
+ 		break;
+ 	}
+ 
+@@ -2064,12 +2060,9 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+ 						    0xffffff);
+ 	} else if (cmd->scan_begin_src == TRIG_EXT) {
+ 		/* external trigger */
+-		unsigned int tmp = CR_CHAN(cmd->scan_begin_arg);
+-
+-		if (tmp > 16)
+-			tmp = 16;
+-		tmp |= (cmd->scan_begin_arg & (CR_INVERT | CR_EDGE));
+-		err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, tmp);
++		err |= ni_check_trigger_arg_roffs(CR_CHAN(cmd->scan_begin_arg),
++						  NI_AI_SampleClock,
++						  &devpriv->routing_tables, 1);
+ 	} else {		/* TRIG_OTHER */
+ 		err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+ 	}
+@@ -2087,12 +2080,9 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+ 		}
+ 	} else if (cmd->convert_src == TRIG_EXT) {
+ 		/* external trigger */
+-		unsigned int tmp = CR_CHAN(cmd->convert_arg);
+-
+-		if (tmp > 16)
+-			tmp = 16;
+-		tmp |= (cmd->convert_arg & (CR_ALT_FILTER | CR_INVERT));
+-		err |= comedi_check_trigger_arg_is(&cmd->convert_arg, tmp);
++		err |= ni_check_trigger_arg_roffs(CR_CHAN(cmd->convert_arg),
++						  NI_AI_ConvertClock,
++						  &devpriv->routing_tables, 1);
+ 	} else if (cmd->convert_src == TRIG_NOW) {
+ 		err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+ 	}
+@@ -2118,7 +2108,7 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	/* step 4: fix up any arguments */
+ 
+ 	if (cmd->scan_begin_src == TRIG_TIMER) {
+-		tmp = cmd->scan_begin_arg;
++		unsigned int tmp = cmd->scan_begin_arg;
+ 		cmd->scan_begin_arg =
+ 		    ni_timer_to_ns(dev, ni_ns_to_timer(dev,
+ 						       cmd->scan_begin_arg,
+@@ -2128,7 +2118,7 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	}
+ 	if (cmd->convert_src == TRIG_TIMER) {
+ 		if (!devpriv->is_611x && !devpriv->is_6143) {
+-			tmp = cmd->convert_arg;
++			unsigned int tmp = cmd->convert_arg;
+ 			cmd->convert_arg =
+ 			    ni_timer_to_ns(dev, ni_ns_to_timer(dev,
+ 							       cmd->convert_arg,
+@@ -2206,8 +2196,10 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ 			   NISTC_AI_TRIG_START1_SEL(0);
+ 		break;
+ 	case TRIG_EXT:
+-		ai_trig |= NISTC_AI_TRIG_START1_SEL(CR_CHAN(cmd->start_arg) +
+-						    1);
++		ai_trig |= NISTC_AI_TRIG_START1_SEL(
++			ni_get_reg_value_roffs(CR_CHAN(cmd->start_arg),
++					       NI_AI_StartTrigger,
++					       &devpriv->routing_tables, 1));
+ 
+ 		if (cmd->start_arg & CR_INVERT)
+ 			ai_trig |= NISTC_AI_TRIG_START1_POLARITY;
+@@ -2317,8 +2309,10 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ 		    (cmd->scan_begin_arg & ~CR_EDGE) !=
+ 		    (cmd->convert_arg & ~CR_EDGE))
+ 			start_stop_select |= NISTC_AI_START_SYNC;
+-		start_stop_select |=
+-		    NISTC_AI_START_SEL(1 + CR_CHAN(cmd->scan_begin_arg));
++		start_stop_select |= NISTC_AI_START_SEL(
++			ni_get_reg_value_roffs(CR_CHAN(cmd->scan_begin_arg),
++					       NI_AI_SampleClock,
++					       &devpriv->routing_tables, 1));
+ 		ni_stc_writew(dev, start_stop_select, NISTC_AI_START_STOP_REG);
+ 		break;
+ 	}
+@@ -2346,8 +2340,10 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ 		ni_stc_writew(dev, mode2, NISTC_AI_MODE2_REG);
+ 		break;
+ 	case TRIG_EXT:
+-		mode1 |= NISTC_AI_MODE1_CONVERT_SRC(1 +
+-						    CR_CHAN(cmd->convert_arg));
++		mode1 |= NISTC_AI_MODE1_CONVERT_SRC(
++			ni_get_reg_value_roffs(CR_CHAN(cmd->convert_arg),
++					       NI_AI_ConvertClock,
++					       &devpriv->routing_tables, 1));
+ 		if ((cmd->convert_arg & CR_INVERT) == 0)
+ 			mode1 |= NISTC_AI_MODE1_CONVERT_POLARITY;
+ 		ni_stc_writew(dev, mode1, NISTC_AI_MODE1_REG);
+@@ -2970,7 +2966,10 @@ static void ni_ao_cmd_set_trigger(struct comedi_device *dev,
+ 		trigsel = NISTC_AO_TRIG_START1_EDGE |
+ 			  NISTC_AO_TRIG_START1_SYNC;
+ 	} else { /* TRIG_EXT */
+-		trigsel = NISTC_AO_TRIG_START1_SEL(CR_CHAN(cmd->start_arg) + 1);
++		trigsel = NISTC_AO_TRIG_START1_SEL(
++			ni_get_reg_value_roffs(CR_CHAN(cmd->start_arg),
++					       NI_AO_StartTrigger,
++					       &devpriv->routing_tables, 1));
+ 		/* 0=active high, 1=active low. see daq-stc 3-24 (p186) */
+ 		if (cmd->start_arg & CR_INVERT)
+ 			trigsel |= NISTC_AO_TRIG_START1_POLARITY;
+@@ -3132,7 +3131,9 @@ static void ni_ao_cmd_set_update(struct comedi_device *dev,
+ 		/* FIXME:  assert scan_begin_arg != 0, ret failure otherwise */
+ 		devpriv->ao_cmd2  |= NISTC_AO_CMD2_BC_GATE_ENA;
+ 		devpriv->ao_mode1 |= NISTC_AO_MODE1_UPDATE_SRC(
+-					CR_CHAN(cmd->scan_begin_arg));
++			ni_get_reg_value(CR_CHAN(cmd->scan_begin_arg),
++					 NI_AO_SampleClock,
++					 &devpriv->routing_tables));
+ 		if (cmd->scan_begin_arg & CR_INVERT)
+ 			devpriv->ao_mode1 |= NISTC_AO_MODE1_UPDATE_SRC_POLARITY;
+ 	}
+@@ -3328,12 +3329,9 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+ 		err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
+ 		break;
+ 	case TRIG_EXT:
+-		tmp = CR_CHAN(cmd->start_arg);
+-
+-		if (tmp > 18)
+-			tmp = 18;
+-		tmp |= (cmd->start_arg & (CR_INVERT | CR_EDGE));
+-		err |= comedi_check_trigger_arg_is(&cmd->start_arg, tmp);
++		err |= ni_check_trigger_arg_roffs(CR_CHAN(cmd->start_arg),
++						  NI_AO_StartTrigger,
++						  &devpriv->routing_tables, 1);
+ 		break;
+ 	}
+ 
+@@ -3343,6 +3341,10 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+ 		err |= comedi_check_trigger_arg_max(&cmd->scan_begin_arg,
+ 						    devpriv->clock_ns *
+ 						    0xffffff);
++	} else {		/* TRIG_EXT */
++		err |= ni_check_trigger_arg(CR_CHAN(cmd->scan_begin_arg),
++					    NI_AO_SampleClock,
++					    &devpriv->routing_tables);
+ 	}
+ 
+ 	err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+@@ -3540,8 +3542,8 @@ static int ni_cdio_check_chanlist(struct comedi_device *dev,
+ static int ni_cdio_cmdtest(struct comedi_device *dev,
+ 			   struct comedi_subdevice *s, struct comedi_cmd *cmd)
+ {
++	struct ni_private *devpriv = dev->private;
+ 	int err = 0;
+-	int tmp;
+ 
+ 	/* Step 1 : check if triggers are trivially valid */
+ 
+@@ -3561,9 +3563,15 @@ static int ni_cdio_cmdtest(struct comedi_device *dev,
+ 
+ 	err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
+ 
+-	tmp = cmd->scan_begin_arg;
+-	tmp &= CR_PACK_FLAGS(NI_M_CDO_MODE_SAMPLE_SRC_MASK, 0, 0, CR_INVERT);
+-	if (tmp != cmd->scan_begin_arg)
++	/*
++	 * Although NI_D[IO]_SampleClock are the same, perhaps we should still,
++	 * for completeness, test whether the cmd is output or input?
++	 */
++	err |= ni_check_trigger_arg(CR_CHAN(cmd->scan_begin_arg),
++				    NI_DO_SampleClock,
++				    &devpriv->routing_tables);
++	if (CR_RANGE(cmd->scan_begin_arg) != 0 ||
++	    CR_AREF(cmd->scan_begin_arg) != 0)
+ 		err |= -EINVAL;
+ 
+ 	err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+@@ -3651,9 +3659,16 @@ static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ 	int retval;
+ 
+ 	ni_writel(dev, NI_M_CDO_CMD_RESET, NI_M_CDIO_CMD_REG);
++	/*
++	 * Although NI_D[IO]_SampleClock are the same, perhaps we should still,
++	 * for completeness, test whether the cmd is output or input(?)
++	 */
+ 	cdo_mode_bits = NI_M_CDO_MODE_FIFO_MODE |
+ 			NI_M_CDO_MODE_HALT_ON_ERROR |
+-			NI_M_CDO_MODE_SAMPLE_SRC(CR_CHAN(cmd->scan_begin_arg));
++			NI_M_CDO_MODE_SAMPLE_SRC(
++				ni_get_reg_value(CR_CHAN(cmd->scan_begin_arg),
++						 NI_DO_SampleClock,
++						 &devpriv->routing_tables));
+ 	if (cmd->scan_begin_arg & CR_INVERT)
+ 		cdo_mode_bits |= NI_M_CDO_MODE_POLARITY;
+ 	ni_writel(dev, cdo_mode_bits, NI_M_CDO_MODE_REG);
+@@ -5286,6 +5301,8 @@ static int ni_E_init(struct comedi_device *dev,
+ 	struct comedi_subdevice *s;
+ 	int ret;
+ 	int i;
++	const char *dev_family = devpriv->is_m_series ? "ni_mseries"
++						      : "ni_eseries";
+ 
+ 	if (board->n_aochan > MAX_N_AO_CHAN) {
+ 		dev_err(dev->class_dev, "bug! n_aochan > MAX_N_AO_CHAN\n");
+@@ -5617,6 +5634,15 @@ static int ni_E_init(struct comedi_device *dev,
+ 		ni_writeb(dev, 0x0, NI_M_AO_CALIB_REG);
+ 	}
+ 
++	/* prepare the device for globally-named routes. */
++	if (ni_assign_device_routes(dev_family, board->name,
++				    &devpriv->routing_tables) < 0) {
++		dev_warn(dev->class_dev, "%s: %s device has no signal routing table.\n",
++			 __func__, board->name);
++		dev_warn(dev->class_dev, "%s: High level NI signal names will not be available for this %s board.\n",
++			 __func__, board->name);
++	}
++
+ 	return 0;
+ }
+ 

commit 4bb90c87abbe21ea469a242c8b350ea39a459c84
+Author: Spencer E. Olson 
+Date:   Wed Oct 3 14:56:04 2018 -0600
+
+    staging: comedi: add interface to ni routing table information
+    
+    Adds interface and associated unittests for accessing/looking-up/validating
+    the new ni routing table information.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig
+index 583bce9bb18e..9ab1ee7d36bf 100644
+--- a/drivers/staging/comedi/Kconfig
++++ b/drivers/staging/comedi/Kconfig
+@@ -1313,5 +1313,9 @@ config COMEDI_NI_LABPC_ISADMA
+ 
+ config COMEDI_NI_TIO
+ 	tristate
++	select COMEDI_NI_ROUTING
++
++config COMEDI_NI_ROUTING
++	tristate
+ 
+ endif # COMEDI
+diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile
+index 8cb518190fc7..b24ac00cab73 100644
+--- a/drivers/staging/comedi/drivers/Makefile
++++ b/drivers/staging/comedi/drivers/Makefile
+@@ -137,6 +137,33 @@ obj-$(CONFIG_COMEDI_VMK80XX)		+= vmk80xx.o
+ obj-$(CONFIG_COMEDI_MITE)		+= mite.o
+ obj-$(CONFIG_COMEDI_NI_TIO)		+= ni_tio.o
+ obj-$(CONFIG_COMEDI_NI_TIOCMD)		+= ni_tiocmd.o
++obj-$(CONFIG_COMEDI_NI_ROUTING)		+= ni_routing.o
++ni_routing-objs				+= ni_routes.o \
++					   ni_routing/ni_route_values.o \
++					   ni_routing/ni_route_values/ni_660x.o \
++					   ni_routing/ni_route_values/ni_eseries.o \
++					   ni_routing/ni_route_values/ni_mseries.o \
++					   ni_routing/ni_device_routes.o \
++					   ni_routing/ni_device_routes/pxi-6030e.o \
++					   ni_routing/ni_device_routes/pci-6070e.o \
++					   ni_routing/ni_device_routes/pci-6220.o \
++					   ni_routing/ni_device_routes/pci-6221.o \
++					   ni_routing/ni_device_routes/pxi-6224.o \
++					   ni_routing/ni_device_routes/pxi-6225.o \
++					   ni_routing/ni_device_routes/pci-6229.o \
++					   ni_routing/ni_device_routes/pci-6251.o \
++					   ni_routing/ni_device_routes/pxi-6251.o \
++					   ni_routing/ni_device_routes/pxie-6251.o \
++					   ni_routing/ni_device_routes/pci-6254.o \
++					   ni_routing/ni_device_routes/pci-6259.o \
++					   ni_routing/ni_device_routes/pci-6534.o \
++					   ni_routing/ni_device_routes/pxie-6535.o \
++					   ni_routing/ni_device_routes/pci-6602.o \
++					   ni_routing/ni_device_routes/pci-6713.o \
++					   ni_routing/ni_device_routes/pci-6723.o \
++					   ni_routing/ni_device_routes/pci-6733.o \
++					   ni_routing/ni_device_routes/pxi-6733.o \
++					   ni_routing/ni_device_routes/pxie-6738.o
+ obj-$(CONFIG_COMEDI_NI_LABPC)		+= ni_labpc_common.o
+ obj-$(CONFIG_COMEDI_NI_LABPC_ISADMA)	+= ni_labpc_isadma.o
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_routes.c b/drivers/staging/comedi/drivers/ni_routes.c
+new file mode 100644
+index 000000000000..eb61494dc2bd
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routes.c
+@@ -0,0 +1,523 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routes.c
++ *  Route information for NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++#include 
++#include 
++#include 
++#include 
++
++#include "../comedi.h"
++
++#include "ni_routes.h"
++#include "ni_routing/ni_route_values.h"
++#include "ni_routing/ni_device_routes.h"
++
++/*
++ * This is defined in ni_routing/ni_route_values.h:
++ * #define B(x)	((x) - NI_NAMES_BASE)
++ */
++
++/*
++ * These are defined in ni_routing/ni_route_values.h to identify clearly
++ * elements of the table that were set.  In other words, entries that are zero
++ * are invalid.  To get the value to use for the register, one must mask out the
++ * high bit.
++ *
++ * #define V(x)	((x) | 0x80)
++ *
++ * #define UNMARK(x)	((x) & (~(0x80)))
++ *
++ */
++
++/* Helper for accessing data. */
++#define RVi(table, src, dest)	((table)[(dest) * NI_NUM_NAMES + (src)])
++
++static const size_t route_table_size = NI_NUM_NAMES * NI_NUM_NAMES;
++
++/*
++ * Find the proper route_values and ni_device_routes tables for this particular
++ * device.
++ *
++ * Return: -ENODATA if either was not found; 0 if both were found.
++ */
++static int ni_find_device_routes(const char *device_family,
++				 const char *board_name,
++				 struct ni_route_tables *tables)
++{
++	const struct ni_device_routes *dr = NULL;
++	const u8 *rv = NULL;
++	int i;
++
++	/* First, find the register_values table for this device family */
++	for (i = 0; ni_all_route_values[i]; ++i) {
++		if (memcmp(ni_all_route_values[i]->family, device_family,
++			   strnlen(device_family, 30)) == 0) {
++			rv = &ni_all_route_values[i]->register_values[0][0];
++			break;
++		}
++	}
++
++	if (!rv)
++		return -ENODATA;
++
++	/* Second, find the set of routes valid for this device. */
++	for (i = 0; ni_device_routes_list[i]; ++i) {
++		if (memcmp(ni_device_routes_list[i]->device, board_name,
++			   strnlen(board_name, 30)) == 0) {
++			dr = ni_device_routes_list[i];
++			break;
++		}
++	}
++
++	if (!dr)
++		return -ENODATA;
++
++	tables->route_values = rv;
++	tables->valid_routes = dr;
++
++	return 0;
++}
++
++/**
++ * ni_assign_device_routes() - Assign the proper lookup table for NI signal
++ *			       routing to the specified NI device.
++ *
++ * Return: -ENODATA if assignment was not successful; 0 if successful.
++ */
++int ni_assign_device_routes(const char *device_family,
++			    const char *board_name,
++			    struct ni_route_tables *tables)
++{
++	memset(tables, 0, sizeof(struct ni_route_tables));
++	return ni_find_device_routes(device_family, board_name, tables);
++}
++EXPORT_SYMBOL_GPL(ni_assign_device_routes);
++
++/**
++ * ni_count_valid_routes() - Count the number of valid routes.
++ * @tables: Routing tables for which to count all valid routes.
++ */
++unsigned int ni_count_valid_routes(const struct ni_route_tables *tables)
++{
++	int total = 0;
++	int i;
++
++	for (i = 0; i < tables->valid_routes->n_route_sets; ++i) {
++		const struct ni_route_set *R = &tables->valid_routes->routes[i];
++		int j;
++
++		for (j = 0; j < R->n_src; ++j) {
++			const int src  = R->src[j];
++			const int dest = R->dest;
++			const u8 *rv = tables->route_values;
++
++			if (RVi(rv, B(src), B(dest)))
++				/* direct routing is valid */
++				++total;
++			else if (channel_is_rtsi(dest) &&
++				 (RVi(rv, B(src), B(NI_RGOUT0)) ||
++				  RVi(rv, B(src), B(NI_RTSI_BRD(0))) ||
++				  RVi(rv, B(src), B(NI_RTSI_BRD(1))) ||
++				  RVi(rv, B(src), B(NI_RTSI_BRD(2))) ||
++				  RVi(rv, B(src), B(NI_RTSI_BRD(3))))) {
++				++total;
++			}
++		}
++	}
++	return total;
++}
++EXPORT_SYMBOL_GPL(ni_count_valid_routes);
++
++/**
++ * ni_get_valid_routes() - Implements INSN_DEVICE_CONFIG_GET_ROUTES.
++ * @tables:	pointer to relevant set of routing tables.
++ * @n_pairs:	Number of pairs for which memory is allocated by the user.  If
++ *		the user specifies '0', only the number of available pairs is
++ *		returned.
++ * @pair_data:	Pointer to memory allocated to return pairs back to user.  Each
++ *		even, odd indexed member of this array will hold source,
++ *		destination of a route pair respectively.
++ *
++ * Return: the number of valid routes if n_pairs == 0; otherwise, the number of
++ *	valid routes copied.
++ */
++unsigned int ni_get_valid_routes(const struct ni_route_tables *tables,
++				 unsigned int n_pairs,
++				 unsigned int *pair_data)
++{
++	unsigned int n_valid = ni_count_valid_routes(tables);
++	int i;
++
++	if (n_pairs == 0 || n_valid == 0)
++		return n_valid;
++
++	if (!pair_data)
++		return 0;
++
++	n_valid = 0;
++
++	for (i = 0; i < tables->valid_routes->n_route_sets; ++i) {
++		const struct ni_route_set *R = &tables->valid_routes->routes[i];
++		int j;
++
++		for (j = 0; j < R->n_src; ++j) {
++			const int src  = R->src[j];
++			const int dest = R->dest;
++			bool valid = false;
++			const u8 *rv = tables->route_values;
++
++			if (RVi(rv, B(src), B(dest)))
++				/* direct routing is valid */
++				valid = true;
++			else if (channel_is_rtsi(dest) &&
++				 (RVi(rv, B(src), B(NI_RGOUT0)) ||
++				  RVi(rv, B(src), B(NI_RTSI_BRD(0))) ||
++				  RVi(rv, B(src), B(NI_RTSI_BRD(1))) ||
++				  RVi(rv, B(src), B(NI_RTSI_BRD(2))) ||
++				  RVi(rv, B(src), B(NI_RTSI_BRD(3))))) {
++				/* indirect routing also valid */
++				valid = true;
++			}
++
++			if (valid) {
++				pair_data[2 * n_valid] = src;
++				pair_data[2 * n_valid + 1] = dest;
++				++n_valid;
++			}
++
++			if (n_valid >= n_pairs)
++				return n_valid;
++		}
++	}
++	return n_valid;
++}
++EXPORT_SYMBOL_GPL(ni_get_valid_routes);
++
++/**
++ * List of NI global signal names that, as destinations, are only routeable
++ * indirectly through the *_arg elements of the comedi_cmd structure.
++ */
++static const int NI_CMD_DESTS[] = {
++	NI_AI_SampleClock,
++	NI_AI_StartTrigger,
++	NI_AI_ConvertClock,
++	NI_AO_SampleClock,
++	NI_AO_StartTrigger,
++	NI_DI_SampleClock,
++	NI_DO_SampleClock,
++};
++
++/**
++ * ni_is_cmd_dest() - Determine whether the given destination is only
++ *		      configurable via a comedi_cmd struct.
++ * @dest: Destination to test.
++ */
++bool ni_is_cmd_dest(int dest)
++{
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(NI_CMD_DESTS); ++i)
++		if (NI_CMD_DESTS[i] == dest)
++			return true;
++	return false;
++}
++EXPORT_SYMBOL_GPL(ni_is_cmd_dest);
++
++/* **** BEGIN Routes sort routines **** */
++static int _ni_sort_destcmp(const void *va, const void *vb)
++{
++	const struct ni_route_set *a = va;
++	const struct ni_route_set *b = vb;
++
++	if (a->dest < b->dest)
++		return -1;
++	else if (a->dest > b->dest)
++		return 1;
++	return 0;
++}
++
++static int _ni_sort_srccmp(const void *vsrc0, const void *vsrc1)
++{
++	const int *src0 = vsrc0;
++	const int *src1 = vsrc1;
++
++	if (*src0 < *src1)
++		return -1;
++	else if (*src0 > *src1)
++		return 1;
++	return 0;
++}
++
++/**
++ * ni_sort_device_routes() - Sort the list of valid device signal routes in
++ *			     preparation for use.
++ * @valid_routes:	pointer to ni_device_routes struct to sort.
++ */
++void ni_sort_device_routes(struct ni_device_routes *valid_routes)
++{
++	unsigned int n;
++
++	/* 1. Count and set the number of ni_route_set objects. */
++	valid_routes->n_route_sets = 0;
++	while (valid_routes->routes[valid_routes->n_route_sets].dest != 0)
++		++valid_routes->n_route_sets;
++
++	/* 2. sort all ni_route_set objects by destination. */
++	sort(valid_routes->routes, valid_routes->n_route_sets,
++	     sizeof(struct ni_route_set), _ni_sort_destcmp, NULL);
++
++	/* 3. Loop through each route_set for sorting. */
++	for (n = 0; n < valid_routes->n_route_sets; ++n) {
++		struct ni_route_set *rs = &valid_routes->routes[n];
++
++		/* 3a. Count and set the number of sources. */
++		rs->n_src = 0;
++		while (rs->src[rs->n_src])
++			++rs->n_src;
++
++		/* 3a. Sort sources. */
++		sort(valid_routes->routes[n].src, valid_routes->routes[n].n_src,
++		     sizeof(int), _ni_sort_srccmp, NULL);
++	}
++}
++EXPORT_SYMBOL_GPL(ni_sort_device_routes);
++
++/* sort all valid device signal routes in prep for use */
++static void ni_sort_all_device_routes(void)
++{
++	unsigned int i;
++
++	for (i = 0; ni_device_routes_list[i]; ++i)
++		ni_sort_device_routes(ni_device_routes_list[i]);
++}
++
++/* **** BEGIN Routes search routines **** */
++static int _ni_bsearch_destcmp(const void *vkey, const void *velt)
++{
++	const int *key = vkey;
++	const struct ni_route_set *elt = velt;
++
++	if (*key < elt->dest)
++		return -1;
++	else if (*key > elt->dest)
++		return 1;
++	return 0;
++}
++
++static int _ni_bsearch_srccmp(const void *vkey, const void *velt)
++{
++	const int *key = vkey;
++	const int *elt = velt;
++
++	if (*key < *elt)
++		return -1;
++	else if (*key > *elt)
++		return 1;
++	return 0;
++}
++
++/**
++ * ni_find_route_set() - Finds the proper route set with the specified
++ *			 destination.
++ * @destination: Destination of which to search for the route set.
++ * @valid_routes: Pointer to device routes within which to search.
++ *
++ * Return: NULL if no route_set is found with the specified @destination;
++ *	otherwise, a pointer to the route_set if found.
++ */
++const struct ni_route_set *
++ni_find_route_set(const int destination,
++		  const struct ni_device_routes *valid_routes)
++{
++	return bsearch(&destination, valid_routes->routes,
++		       valid_routes->n_route_sets, sizeof(struct ni_route_set),
++		       _ni_bsearch_destcmp);
++}
++EXPORT_SYMBOL_GPL(ni_find_route_set);
++
++/**
++ * ni_route_set_has_source() - Determines whether the given source is in
++ *			       included given route_set.
++ *
++ * Return: true if found; false otherwise.
++ */
++bool ni_route_set_has_source(const struct ni_route_set *routes,
++			     const int source)
++{
++	if (!bsearch(&source, routes->src, routes->n_src, sizeof(int),
++		     _ni_bsearch_srccmp))
++		return false;
++	return true;
++}
++EXPORT_SYMBOL_GPL(ni_route_set_has_source);
++
++/**
++ * ni_lookup_route_register() - Look up a register value for a particular route
++ *				without checking whether the route is valid for
++ *				the particular device.
++ * @src:	global-identifier for route source
++ * @dest:	global-identifier for route destination
++ * @tables:	pointer to relevant set of routing tables.
++ *
++ * Return: -EINVAL if the specified route is not valid for this device family.
++ */
++s8 ni_lookup_route_register(int src, int dest,
++			    const struct ni_route_tables *tables)
++{
++	s8 regval;
++
++	/*
++	 * Be sure to use the B() macro to subtract off the NI_NAMES_BASE before
++	 * indexing into the route_values array.
++	 */
++	src = B(src);
++	dest = B(dest);
++	if (src < 0 || src >= NI_NUM_NAMES || dest < 0 || dest >= NI_NUM_NAMES)
++		return -EINVAL;
++	regval = RVi(tables->route_values, src, dest);
++	if (!regval)
++		return -EINVAL;
++	/* mask out the valid-value marking bit */
++	return UNMARK(regval);
++}
++EXPORT_SYMBOL_GPL(ni_lookup_route_register);
++
++/**
++ * ni_route_to_register() - Validates and converts the specified signal route
++ *			    (src-->dest) to the value used at the appropriate
++ *			    register.
++ * @src:	global-identifier for route source
++ * @dest:	global-identifier for route destination
++ * @tables:	pointer to relevant set of routing tables.
++ *
++ * Generally speaking, most routes require the first six bits and a few require
++ * 7 bits.  Special handling is given for the return value when the route is to
++ * be handled by the RTSI sub-device.  In this case, the returned register may
++ * not be sufficient to define the entire route path, but rather may only
++ * indicate the intermediate route.  For example, if the route must go through
++ * the RGOUT0 pin, the (src->RGOUT0) register value will be returned.
++ * Similarly, if the route must go through the NI_RTSI_BRD lines, the BIT(6)
++ * will be set:
++ *
++ * if route does not need RTSI_BRD lines:
++ *   bits 0:7 : register value
++ *              for a route that must go through RGOUT0 pin, this will be equal
++ *              to the (src->RGOUT0) register value.
++ * else: * route is (src->RTSI_BRD(x), RTSI_BRD(x)->TRIGGER_LINE(i)) *
++ *   bits 0:5 : zero
++ *   bits 6   : set to 1
++ *   bits 7:7 : zero
++ *
++ * Return: register value to be used for source at destination with special
++ *	cases given above; Otherwise, -1 if the specified route is not valid for
++ *	this particular device.
++ */
++s8 ni_route_to_register(const int src, const int dest,
++			const struct ni_route_tables *tables)
++{
++	const struct ni_route_set *routes =
++		ni_find_route_set(dest, tables->valid_routes);
++	const u8 *rv;
++	s8 regval;
++
++	/* first check to see if source is listed with bunch of destinations. */
++	if (!routes)
++		return -1;
++	/* 2nd, check to see if destination is in list of source's targets. */
++	if (!ni_route_set_has_source(routes, src))
++		return -1;
++	/*
++	 * finally, check to see if we know how to route...
++	 * Be sure to use the B() macro to subtract off the NI_NAMES_BASE before
++	 * indexing into the route_values array.
++	 */
++	rv = tables->route_values;
++	regval = RVi(rv, B(src), B(dest));
++
++	/*
++	 * if we did not validate the route, we'll see if we can route through
++	 * one of the muxes
++	 */
++	if (!regval && channel_is_rtsi(dest)) {
++		regval = RVi(rv, B(src), B(NI_RGOUT0));
++		if (!regval && (RVi(rv, B(src), B(NI_RTSI_BRD(0))) ||
++				RVi(rv, B(src), B(NI_RTSI_BRD(1))) ||
++				RVi(rv, B(src), B(NI_RTSI_BRD(2))) ||
++				RVi(rv, B(src), B(NI_RTSI_BRD(3)))))
++			regval = BIT(6);
++	}
++
++	if (!regval)
++		return -1;
++	/* mask out the valid-value marking bit */
++	return UNMARK(regval);
++}
++EXPORT_SYMBOL_GPL(ni_route_to_register);
++
++/**
++ * ni_find_route_source() - Finds the signal source corresponding to a signal
++ *			    route (src-->dest) of the specified routing register
++ *			    value and the specified route destination on the
++ *			    specified device.
++ *
++ * Note that this function does _not_ validate the source based on device
++ * routes.
++ *
++ * Return: The NI signal value (e.g. NI_PFI(0) or PXI_Clk10) if found.
++ *	If the source was not found (i.e. the register value is not
++ *	valid for any routes to the destination), -EINVAL is returned.
++ */
++int ni_find_route_source(const u8 src_sel_reg_value, int dest,
++			 const struct ni_route_tables *tables)
++{
++	int src;
++
++	dest = B(dest); /* subtract NI names offset */
++	/* ensure we are not going to under/over run the route value table */
++	if (dest < 0 || dest >= NI_NUM_NAMES)
++		return -EINVAL;
++	for (src = 0; src < NI_NUM_NAMES; ++src)
++		if (RVi(tables->route_values, src, dest) ==
++		    V(src_sel_reg_value))
++			return src + NI_NAMES_BASE;
++	return -EINVAL;
++}
++EXPORT_SYMBOL_GPL(ni_find_route_source);
++
++/* **** END Routes search routines **** */
++
++/* **** BEGIN simple module entry/exit functions **** */
++static int __init ni_routes_module_init(void)
++{
++	ni_sort_all_device_routes();
++	return 0;
++}
++
++static void __exit ni_routes_module_exit(void)
++{
++}
++
++module_init(ni_routes_module_init);
++module_exit(ni_routes_module_exit);
++
++MODULE_AUTHOR("Comedi http://www.comedi.org");
++MODULE_DESCRIPTION("Comedi helper for routing signals-->terminals for NI");
++MODULE_LICENSE("GPL");
++/* **** END simple module entry/exit functions **** */
+diff --git a/drivers/staging/comedi/drivers/ni_routes.h b/drivers/staging/comedi/drivers/ni_routes.h
+new file mode 100644
+index 000000000000..3211a16adc6f
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routes.h
+@@ -0,0 +1,329 @@
++/* SPDX-License-Identifier: GPL-2.0+ */
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routes.h
++ *  Route information for NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++#ifndef _COMEDI_DRIVERS_NI_ROUTES_H
++#define _COMEDI_DRIVERS_NI_ROUTES_H
++
++#include 
++#include 
++
++#ifndef NI_ROUTE_VALUE_EXTERNAL_CONVERSION
++#include 
++#endif
++
++#include "../comedi.h"
++
++/**
++ * struct ni_route_set - Set of destinations with a common source.
++ * @dest: Destination of all sources in this route set.
++ * @n_src: Number of sources for this route set.
++ * @src: List of sources that all map to the same destination.
++ */
++struct ni_route_set {
++	int dest;
++	int n_src;
++	int *src;
++};
++
++/**
++ * struct ni_device_routes - List of all src->dest sets for a particular device.
++ * @device: Name of board/device (e.g. pxi-6733).
++ * @n_route_sets: Number of route sets that are valid for this device.
++ * @routes: List of route sets that are valid for this device.
++ */
++struct ni_device_routes {
++	const char *device;
++	int n_route_sets;
++	struct ni_route_set *routes;
++};
++
++/**
++ * struct ni_route_tables - Register values and valid routes for a device.
++ * @valid_routes: Pointer to a all valid route sets for a single device.
++ * @route_values: Pointer to register values for all routes for the family to
++ *		  which the device belongs.
++ *
++ * Link to the valid src->dest routes and the register values used to assign
++ * such routes for that particular device.
++ */
++struct ni_route_tables {
++	const struct ni_device_routes *valid_routes;
++	const u8 *route_values;
++};
++
++/*
++ * ni_assign_device_routes() - Assign the proper lookup table for NI signal
++ *			       routing to the specified NI device.
++ *
++ * Return: -ENODATA if assignment was not successful; 0 if successful.
++ */
++int ni_assign_device_routes(const char *device_family,
++			    const char *board_name,
++			    struct ni_route_tables *tables);
++
++/*
++ * ni_find_route_set() - Finds the proper route set with the specified
++ *			 destination.
++ * @destination: Destination of which to search for the route set.
++ * @valid_routes: Pointer to device routes within which to search.
++ *
++ * Return: NULL if no route_set is found with the specified @destination;
++ *	otherwise, a pointer to the route_set if found.
++ */
++const struct ni_route_set *
++ni_find_route_set(const int destination,
++		  const struct ni_device_routes *valid_routes);
++
++/*
++ * ni_route_set_has_source() - Determines whether the given source is in
++ *			       included given route_set.
++ *
++ * Return: true if found; false otherwise.
++ */
++bool ni_route_set_has_source(const struct ni_route_set *routes, const int src);
++
++/*
++ * ni_route_to_register() - Validates and converts the specified signal route
++ *			    (src-->dest) to the value used at the appropriate
++ *			    register.
++ * @src:	global-identifier for route source
++ * @dest:	global-identifier for route destination
++ * @tables:	pointer to relevant set of routing tables.
++ *
++ * Generally speaking, most routes require the first six bits and a few require
++ * 7 bits.  Special handling is given for the return value when the route is to
++ * be handled by the RTSI sub-device.  In this case, the returned register may
++ * not be sufficient to define the entire route path, but rather may only
++ * indicate the intermediate route.  For example, if the route must go through
++ * the RGOUT0 pin, the (src->RGOUT0) register value will be returned.
++ * Similarly, if the route must go through the NI_RTSI_BRD lines, the BIT(6)
++ * will be set:
++ *
++ * if route does not need RTSI_BRD lines:
++ *   bits 0:7 : register value
++ *              for a route that must go through RGOUT0 pin, this will be equal
++ *              to the (src->RGOUT0) register value.
++ * else: * route is (src->RTSI_BRD(x), RTSI_BRD(x)->TRIGGER_LINE(i)) *
++ *   bits 0:5 : zero
++ *   bits 6   : set to 1
++ *   bits 7:7 : zero
++ *
++ * Return: register value to be used for source at destination with special
++ *	cases given above; Otherwise, -1 if the specified route is not valid for
++ *	this particular device.
++ */
++s8 ni_route_to_register(const int src, const int dest,
++			const struct ni_route_tables *tables);
++
++static inline bool ni_rtsi_route_requires_mux(s8 value)
++{
++	return value & BIT(6);
++}
++
++/*
++ * ni_lookup_route_register() - Look up a register value for a particular route
++ *				without checking whether the route is valid for
++ *				the particular device.
++ * @src:	global-identifier for route source
++ * @dest:	global-identifier for route destination
++ * @tables:	pointer to relevant set of routing tables.
++ *
++ * Return: -EINVAL if the specified route is not valid for this device family.
++ */
++s8 ni_lookup_route_register(int src, int dest,
++			    const struct ni_route_tables *tables);
++
++/**
++ * route_is_valid() - Determines whether the specified signal route (src-->dest)
++ *		      is valid for the given NI comedi_device.
++ * @src:	global-identifier for route source
++ * @dest:	global-identifier for route destination
++ * @tables:	pointer to relevant set of routing tables.
++ *
++ * Return: True if the route is valid, otherwise false.
++ */
++static inline bool route_is_valid(const int src, const int dest,
++				  const struct ni_route_tables *tables)
++{
++	return ni_route_to_register(src, dest, tables) >= 0;
++}
++
++/*
++ * ni_is_cmd_dest() - Determine whether the given destination is only
++ *		      configurable via a comedi_cmd struct.
++ * @dest: Destination to test.
++ */
++bool ni_is_cmd_dest(int dest);
++
++static inline bool channel_is_pfi(int channel)
++{
++	return NI_PFI(0) <= channel && channel <= NI_PFI(-1);
++}
++
++static inline bool channel_is_rtsi(int channel)
++{
++	return TRIGGER_LINE(0) <= channel && channel <= TRIGGER_LINE(-1);
++}
++
++static inline bool channel_is_ctr(int channel)
++{
++	return channel >= NI_COUNTER_NAMES_BASE &&
++	       channel <= NI_COUNTER_NAMES_MAX;
++}
++
++/*
++ * ni_count_valid_routes() - Count the number of valid routes.
++ * @tables: Routing tables for which to count all valid routes.
++ */
++unsigned int ni_count_valid_routes(const struct ni_route_tables *tables);
++
++/*
++ * ni_get_valid_routes() - Implements INSN_DEVICE_CONFIG_GET_ROUTES.
++ * @tables:	pointer to relevant set of routing tables.
++ * @n_pairs:	Number of pairs for which memory is allocated by the user.  If
++ *		the user specifies '0', only the number of available pairs is
++ *		returned.
++ * @pair_data:	Pointer to memory allocated to return pairs back to user.  Each
++ *		even, odd indexed member of this array will hold source,
++ *		destination of a route pair respectively.
++ *
++ * Return: the number of valid routes if n_pairs == 0; otherwise, the number of
++ *	valid routes copied.
++ */
++unsigned int ni_get_valid_routes(const struct ni_route_tables *tables,
++				 unsigned int n_pairs,
++				 unsigned int *pair_data);
++
++/*
++ * ni_sort_device_routes() - Sort the list of valid device signal routes in
++ *			     preparation for use.
++ * @valid_routes:	pointer to ni_device_routes struct to sort.
++ */
++void ni_sort_device_routes(struct ni_device_routes *valid_routes);
++
++/*
++ * ni_find_route_source() - Finds the signal source corresponding to a signal
++ *			    route (src-->dest) of the specified routing register
++ *			    value and the specified route destination on the
++ *			    specified device.
++ *
++ * Note that this function does _not_ validate the source based on device
++ * routes.
++ *
++ * Return: The NI signal value (e.g. NI_PFI(0) or PXI_Clk10) if found.
++ *	If the source was not found (i.e. the register value is not
++ *	valid for any routes to the destination), -EINVAL is returned.
++ */
++int ni_find_route_source(const u8 src_sel_reg_value, const int dest,
++			 const struct ni_route_tables *tables);
++
++/**
++ * route_register_is_valid() - Determines whether the register value for the
++ *			       specified route destination on the specified
++ *			       device is valid.
++ */
++static inline bool route_register_is_valid(const u8 src_sel_reg_value,
++					   const int dest,
++					   const struct ni_route_tables *tables)
++{
++	return ni_find_route_source(src_sel_reg_value, dest, tables) >= 0;
++}
++
++/**
++ * ni_get_reg_value_roffs() - Determines the proper register value for a
++ *			      particular valid NI signal/terminal route.
++ * @src:	Either a direct register value or one of NI_* signal names.
++ * @dest:	global-identifier for route destination
++ * @tables:	pointer to relevant set of routing tables.
++ * @direct_reg_offset:
++ *		Compatibility compensation argument.  This argument allows us to
++ *		arbitrarily apply an offset to src if src is a direct register
++ *		value reference.  This is necessary to be compatible with
++ *		definitions of register values as previously exported directly
++ *		to user space.
++ *
++ * Return: the register value (>0) to be used at the destination if the src is
++ *	valid for the given destination; -1 otherwise.
++ */
++static inline s8 ni_get_reg_value_roffs(int src, const int dest,
++					const struct ni_route_tables *tables,
++					const int direct_reg_offset)
++{
++	if (src < NI_NAMES_BASE) {
++		src += direct_reg_offset;
++		/*
++		 * In this case, the src is expected to actually be a register
++		 * value.
++		 */
++		if (route_register_is_valid(src, dest, tables))
++			return src;
++		return -1;
++	}
++
++	/*
++	 * Otherwise, the src is expected to be one of the abstracted NI
++	 * signal/terminal names.
++	 */
++	return ni_route_to_register(src, dest, tables);
++}
++
++static inline int ni_get_reg_value(const int src, const int dest,
++				   const struct ni_route_tables *tables)
++{
++	return ni_get_reg_value_roffs(src, dest, tables, 0);
++}
++
++/**
++ * ni_check_trigger_arg_roffs() - Checks the trigger argument (*_arg) of an NI
++ *				  device to ensure that the *_arg value
++ *				  corresponds to _either_ a valid register value
++ *				  to define a trigger source, _or_ a valid NI
++ *				  signal/terminal name that has a valid route to
++ *				  the destination on the particular device.
++ * @src:	Either a direct register value or one of NI_* signal names.
++ * @dest:	global-identifier for route destination
++ * @tables:	pointer to relevant set of routing tables.
++ * @direct_reg_offset:
++ *		Compatibility compensation argument.  This argument allows us to
++ *		arbitrarily apply an offset to src if src is a direct register
++ *		value reference.  This is necessary to be compatible with
++ *		definitions of register values as previously exported directly
++ *		to user space.
++ *
++ * Return: 0 if the src (either register value or NI signal/terminal name) is
++ *	valid for the destination; -EINVAL otherwise.
++ */
++static inline
++int ni_check_trigger_arg_roffs(int src, const int dest,
++			       const struct ni_route_tables *tables,
++			       const int direct_reg_offset)
++{
++	if (ni_get_reg_value_roffs(src, dest, tables, direct_reg_offset) < 0)
++		return -EINVAL;
++	return 0;
++}
++
++static inline int ni_check_trigger_arg(const int src, const int dest,
++				       const struct ni_route_tables *tables)
++{
++	return ni_check_trigger_arg_roffs(src, dest, tables, 0);
++}
++
++#endif /* _COMEDI_DRIVERS_NI_ROUTES_H */
+diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h
+index 1c6bd25da962..771eaef3815d 100644
+--- a/drivers/staging/comedi/drivers/ni_stc.h
++++ b/drivers/staging/comedi/drivers/ni_stc.h
+@@ -15,6 +15,7 @@
+ #define _COMEDI_NI_STC_H
+ 
+ #include "ni_tio.h"
++#include "ni_routes.h"
+ 
+ /*
+  * Registers in the National Instruments DAQ-STC chip
+@@ -1058,6 +1059,9 @@ struct ni_private {
+ 	 * possible.
+ 	 */
+ 	unsigned int ao_needs_arming:1;
++
++	/* device signal route tables */
++	struct ni_route_tables routing_tables;
+ };
+ 
+ static const struct comedi_lrange range_ni_E_ao_ext;
+diff --git a/drivers/staging/comedi/drivers/tests/Makefile b/drivers/staging/comedi/drivers/tests/Makefile
+index 1d58ede0bdf6..b5d8e13d4162 100644
+--- a/drivers/staging/comedi/drivers/tests/Makefile
++++ b/drivers/staging/comedi/drivers/tests/Makefile
+@@ -3,4 +3,5 @@
+ #
+ ccflags-$(CONFIG_COMEDI_DEBUG)		:= -DDEBUG
+ 
+-obj-$(CONFIG_COMEDI_TESTS)		+= example_test.o
++obj-$(CONFIG_COMEDI_TESTS)		+= example_test.o ni_routes_test.o
++CFLAGS_ni_routes_test.o			:= -DDEBUG
+diff --git a/drivers/staging/comedi/drivers/tests/ni_routes_test.c b/drivers/staging/comedi/drivers/tests/ni_routes_test.c
+new file mode 100644
+index 000000000000..a1eda035f270
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/tests/ni_routes_test.c
+@@ -0,0 +1,613 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/tests/ni_routes_test.c
++ *  Unit tests for NI routes (ni_routes.c module).
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++#include 
++
++#include "../ni_stc.h"
++#include "../ni_routes.h"
++#include "unittest.h"
++
++#define RVi(table, src, dest)	((table)[(dest) * NI_NUM_NAMES + (src)])
++#define O(x)	((x) + NI_NAMES_BASE)
++#define B(x)	((x) - NI_NAMES_BASE)
++#define V(x)	((x) | 0x80)
++
++/* *** BEGIN fake board data *** */
++static const char *pci_6070e = "pci-6070e";
++static const char *pci_6220 = "pci-6220";
++static const char *pci_fake = "pci-fake";
++
++static const char *ni_eseries = "ni_eseries";
++static const char *ni_mseries = "ni_mseries";
++
++static struct ni_board_struct board = {
++	.name = NULL,
++};
++
++static struct ni_private private = {
++	.is_m_series = 0,
++};
++
++static const int bad_dest = O(8), dest0 = O(0), desti = O(5);
++static const int ith_dest_index = 2;
++static const int no_val_dest = O(7), no_val_index = 4;
++
++/* These have to be defs to be used in init code below */
++#define rgout0_src0	(O(100))
++#define rgout0_src1	(O(101))
++#define brd0_src0	(O(110))
++#define brd0_src1	(O(111))
++#define brd1_src0	(O(120))
++#define brd1_src1	(O(121))
++#define brd2_src0	(O(130))
++#define brd2_src1	(O(131))
++#define brd3_src0	(O(140))
++#define brd3_src1	(O(141))
++
++/* I1 and I2 should not call O(...).  Mostly here to shut checkpatch.pl up */
++#define I1(x1)	\
++	(int[]){ \
++		x1, 0 \
++	}
++#define I2(x1, x2)	\
++	(int[]){ \
++		(x1), (x2), 0 \
++	}
++#define I3(x1, x2, x3)	\
++	(int[]){ \
++		(x1), (x2), (x3), 0 \
++	}
++
++/* O9 is build to call O(...) for each arg */
++#define O9(x1, x2, x3, x4, x5, x6, x7, x8, x9)	\
++	(int[]){ \
++		O(x1), O(x2), O(x3), O(x4), O(x5), O(x6), O(x7), O(x8), O(x9), \
++		0 \
++	}
++
++static struct ni_device_routes DR = {
++	.device = "testdev",
++	.routes = (struct ni_route_set[]){
++		{.dest = O(0), .src = O9(/**/1, 2, 3, 4, 5, 6, 7, 8, 9)},
++		{.dest = O(1), .src = O9(0, /**/2, 3, 4, 5, 6, 7, 8, 9)},
++		/* ith route_set */
++		{.dest = O(5), .src = O9(0, 1, 2, 3, 4,/**/ 6, 7, 8, 9)},
++		{.dest = O(6), .src = O9(0, 1, 2, 3, 4, 5,/**/ 7, 8, 9)},
++		/* next one will not have valid reg values */
++		{.dest = O(7), .src = O9(0, 1, 2, 3, 4, 5, 6,/**/ 8, 9)},
++		{.dest = O(9), .src = O9(0, 1, 2, 3, 4, 5, 6, 7, 8/**/)},
++
++		/* indirect routes done through muxes */
++		{.dest = TRIGGER_LINE(0), .src = I1(rgout0_src0)},
++		{.dest = TRIGGER_LINE(1), .src = I3(rgout0_src0,
++						    brd3_src0,
++						    brd3_src1)},
++		{.dest = TRIGGER_LINE(2), .src = I3(rgout0_src1,
++						    brd2_src0,
++						    brd2_src1)},
++		{.dest = TRIGGER_LINE(3), .src = I3(rgout0_src1,
++						    brd1_src0,
++						    brd1_src1)},
++		{.dest = TRIGGER_LINE(4), .src = I2(brd0_src0,
++						    brd0_src1)},
++		{.dest = 0},
++	},
++};
++
++#undef I1
++#undef I2
++#undef O9
++
++#define RV9(x1, x2, x3, x4, x5, x6, x7, x8, x9) \
++	[x1] = V(x1), [x2] = V(x2), [x3] = V(x3), [x4] = V(x4), \
++	[x5] = V(x5), [x6] = V(x6), [x7] = V(x7), [x8] = V(x8), \
++	[x9] = V(x9),
++
++/* This table is indexed as RV[destination][source] */
++static const u8 RV[NI_NUM_NAMES][NI_NUM_NAMES] = {
++	[0] = {RV9(/**/1, 2, 3, 4, 5, 6, 7, 8, 9)},
++	[1] = {RV9(0,/**/ 2, 3, 4, 5, 6, 7, 8, 9)},
++	[2] = {RV9(0,  1,/**/3, 4, 5, 6, 7, 8, 9)},
++	[3] = {RV9(0,  1, 2,/**/4, 5, 6, 7, 8, 9)},
++	[4] = {RV9(0,  1, 2, 3,/**/5, 6, 7, 8, 9)},
++	[5] = {RV9(0,  1, 2, 3, 4,/**/6, 7, 8, 9)},
++	[6] = {RV9(0,  1, 2, 3, 4, 5,/**/7, 8, 9)},
++	/* [7] is intentionaly left absent to test invalid routes */
++	[8] = {RV9(0,  1, 2, 3, 4, 5, 6, 7,/**/9)},
++	[9] = {RV9(0,  1, 2, 3, 4, 5, 6, 7, 8/**/)},
++	/* some tests for needing extra muxes */
++	[B(NI_RGOUT0)]	= {[B(rgout0_src0)]   = V(0),
++			   [B(rgout0_src1)]   = V(1)},
++	[B(NI_RTSI_BRD(0))] = {[B(brd0_src0)] = V(0),
++			       [B(brd0_src1)] = V(1)},
++	[B(NI_RTSI_BRD(1))] = {[B(brd1_src0)] = V(0),
++			       [B(brd1_src1)] = V(1)},
++	[B(NI_RTSI_BRD(2))] = {[B(brd2_src0)] = V(0),
++			       [B(brd2_src1)] = V(1)},
++	[B(NI_RTSI_BRD(3))] = {[B(brd3_src0)] = V(0),
++			       [B(brd3_src1)] = V(1)},
++};
++
++#undef RV9
++
++/* *** END fake board data *** */
++
++/* *** BEGIN board data initializers *** */
++static void init_private(void)
++{
++	memset(&private, 0, sizeof(struct ni_private));
++}
++
++static void init_pci_6070e(void)
++{
++	board.name = pci_6070e;
++	init_private();
++	private.is_m_series = 0;
++}
++
++static void init_pci_6220(void)
++{
++	board.name = pci_6220;
++	init_private();
++	private.is_m_series = 1;
++}
++
++static void init_pci_fake(void)
++{
++	board.name = pci_fake;
++	init_private();
++	private.routing_tables.route_values = &RV[0][0];
++	private.routing_tables.valid_routes = &DR;
++}
++
++/* *** END board data initializers *** */
++
++/* Tests that route_sets are in order of the signal destination. */
++static bool route_set_dests_in_order(const struct ni_device_routes *devroutes)
++{
++	int i;
++	int last = NI_NAMES_BASE - 1;
++
++	for (i = 0; i < devroutes->n_route_sets; ++i) {
++		if (last >= devroutes->routes[i].dest)
++			return false;
++		last = devroutes->routes[i].dest;
++	}
++	return true;
++}
++
++/* Tests that all route_set->src are in order of the signal source. */
++bool route_set_sources_in_order(const struct ni_device_routes *devroutes)
++{
++	int i;
++
++	for (i = 0; i < devroutes->n_route_sets; ++i) {
++		int j;
++		int last = NI_NAMES_BASE - 1;
++
++		for (j = 0; j < devroutes->routes[i].n_src; ++j) {
++			if (last >= devroutes->routes[i].src[j])
++				return false;
++			last = devroutes->routes[i].src[j];
++		}
++	}
++	return true;
++}
++
++void test_ni_assign_device_routes(void)
++{
++	const struct ni_device_routes *devroutes, *olddevroutes;
++	const u8 *table, *oldtable;
++
++	init_pci_6070e();
++	ni_assign_device_routes(ni_eseries, pci_6070e, &private.routing_tables);
++	devroutes = private.routing_tables.valid_routes;
++	table = private.routing_tables.route_values;
++
++	unittest(strncmp(devroutes->device, pci_6070e, 10) == 0,
++		 "find device pci-6070e\n");
++	unittest(devroutes->n_route_sets == 37,
++		 "number of pci-6070e route_sets == 37\n");
++	unittest(devroutes->routes->dest == NI_PFI(0),
++		 "first pci-6070e route_set is for NI_PFI(0)\n");
++	unittest(devroutes->routes->n_src == 1,
++		 "first pci-6070e route_set length == 1\n");
++	unittest(devroutes->routes->src[0] == NI_AI_StartTrigger,
++		 "first pci-6070e route_set src. == NI_AI_StartTrigger\n");
++	unittest(devroutes->routes[10].dest == TRIGGER_LINE(0),
++		 "10th pci-6070e route_set is for TRIGGER_LINE(0)\n");
++	unittest(devroutes->routes[10].n_src == 10,
++		 "10th pci-6070e route_set length == 10\n");
++	unittest(devroutes->routes[10].src[0] == NI_CtrSource(0),
++		 "10th pci-6070e route_set src. == NI_CtrSource(0)\n");
++	unittest(route_set_dests_in_order(devroutes),
++		 "all pci-6070e route_sets in order of signal destination\n");
++	unittest(route_set_sources_in_order(devroutes),
++		 "all pci-6070e route_set->src's in order of signal source\n");
++
++	unittest(
++	  RVi(table, B(PXI_Star), B(NI_AI_SampleClock)) == V(17) &&
++	  RVi(table, B(NI_10MHzRefClock), B(TRIGGER_LINE(0))) == 0 &&
++	  RVi(table, B(NI_AI_ConvertClock), B(NI_PFI(0))) == 0 &&
++	  RVi(table, B(NI_AI_ConvertClock), B(NI_PFI(2))) ==
++		V(NI_PFI_OUTPUT_AI_CONVERT),
++	  "pci-6070e finds e-series route_values table\n");
++
++	olddevroutes = devroutes;
++	oldtable = table;
++	init_pci_6220();
++	ni_assign_device_routes(ni_mseries, pci_6220, &private.routing_tables);
++	devroutes = private.routing_tables.valid_routes;
++	table = private.routing_tables.route_values;
++
++	unittest(strncmp(devroutes->device, pci_6220, 10) == 0,
++		 "find device pci-6220\n");
++	unittest(oldtable != table, "pci-6220 find other route_values table\n");
++
++	unittest(
++	  RVi(table, B(PXI_Star), B(NI_AI_SampleClock)) == V(20) &&
++	  RVi(table, B(NI_10MHzRefClock), B(TRIGGER_LINE(0))) == V(12) &&
++	  RVi(table, B(NI_AI_ConvertClock), B(NI_PFI(0))) == V(3) &&
++	  RVi(table, B(NI_AI_ConvertClock), B(NI_PFI(2))) == V(3),
++	  "pci-6220 finds m-series route_values table\n");
++}
++
++void test_ni_sort_device_routes(void)
++{
++	/* We begin by sorting the device routes for use in later tests */
++	ni_sort_device_routes(&DR);
++	/* now we test that sorting. */
++	unittest(route_set_dests_in_order(&DR),
++		 "all route_sets of fake data in order of sig. destination\n");
++	unittest(route_set_sources_in_order(&DR),
++		 "all route_set->src's of fake data in order of sig. source\n");
++}
++
++void test_ni_find_route_set(void)
++{
++	unittest(ni_find_route_set(bad_dest, &DR) == NULL,
++		 "check for nonexistent route_set\n");
++	unittest(ni_find_route_set(dest0, &DR) == &DR.routes[0],
++		 "find first route_set\n");
++	unittest(ni_find_route_set(desti, &DR) == &DR.routes[ith_dest_index],
++		 "find ith route_set\n");
++	unittest(ni_find_route_set(no_val_dest, &DR) ==
++		 &DR.routes[no_val_index],
++		 "find no_val route_set in spite of missing values\n");
++	unittest(ni_find_route_set(DR.routes[DR.n_route_sets - 1].dest, &DR) ==
++		 &DR.routes[DR.n_route_sets - 1],
++		 "find last route_set\n");
++}
++
++void test_ni_route_set_has_source(void)
++{
++	unittest(!ni_route_set_has_source(&DR.routes[0], O(0)),
++		 "check for bad source\n");
++	unittest(ni_route_set_has_source(&DR.routes[0], O(1)),
++		 "find first source\n");
++	unittest(ni_route_set_has_source(&DR.routes[0], O(5)),
++		 "find fifth source\n");
++	unittest(ni_route_set_has_source(&DR.routes[0], O(9)),
++		 "find last source\n");
++}
++
++void test_ni_route_to_register(void)
++{
++	const struct ni_route_tables *T = &private.routing_tables;
++
++	init_pci_fake();
++	unittest(ni_route_to_register(O(0), O(0), T) < 0,
++		 "check for bad route 0-->0\n");
++	unittest(ni_route_to_register(O(1), O(0), T) == 1,
++		 "validate first destination\n");
++	unittest(ni_route_to_register(O(6), O(5), T) == 6,
++		 "validate middle destination\n");
++	unittest(ni_route_to_register(O(8), O(9), T) == 8,
++		 "validate last destination\n");
++
++	/* choice of trigger line in the following is somewhat random */
++	unittest(ni_route_to_register(rgout0_src0, TRIGGER_LINE(0), T) == 0,
++		 "validate indirect route through rgout0 to TRIGGER_LINE(0)\n");
++	unittest(ni_route_to_register(rgout0_src0, TRIGGER_LINE(1), T) == 0,
++		 "validate indirect route through rgout0 to TRIGGER_LINE(1)\n");
++	unittest(ni_route_to_register(rgout0_src1, TRIGGER_LINE(2), T) == 1,
++		 "validate indirect route through rgout0 to TRIGGER_LINE(2)\n");
++	unittest(ni_route_to_register(rgout0_src1, TRIGGER_LINE(3), T) == 1,
++		 "validate indirect route through rgout0 to TRIGGER_LINE(3)\n");
++
++	unittest(ni_route_to_register(brd0_src0, TRIGGER_LINE(4), T) ==
++		 BIT(6),
++		 "validate indirect route through brd0 to TRIGGER_LINE(4)\n");
++	unittest(ni_route_to_register(brd0_src1, TRIGGER_LINE(4), T) ==
++		 BIT(6),
++		 "validate indirect route through brd0 to TRIGGER_LINE(4)\n");
++	unittest(ni_route_to_register(brd1_src0, TRIGGER_LINE(3), T) ==
++		 BIT(6),
++		 "validate indirect route through brd1 to TRIGGER_LINE(3)\n");
++	unittest(ni_route_to_register(brd1_src1, TRIGGER_LINE(3), T) ==
++		 BIT(6),
++		 "validate indirect route through brd1 to TRIGGER_LINE(3)\n");
++	unittest(ni_route_to_register(brd2_src0, TRIGGER_LINE(2), T) ==
++		 BIT(6),
++		 "validate indirect route through brd2 to TRIGGER_LINE(2)\n");
++	unittest(ni_route_to_register(brd2_src1, TRIGGER_LINE(2), T) ==
++		 BIT(6),
++		 "validate indirect route through brd2 to TRIGGER_LINE(2)\n");
++	unittest(ni_route_to_register(brd3_src0, TRIGGER_LINE(1), T) ==
++		 BIT(6),
++		 "validate indirect route through brd3 to TRIGGER_LINE(1)\n");
++	unittest(ni_route_to_register(brd3_src1, TRIGGER_LINE(1), T) ==
++		 BIT(6),
++		 "validate indirect route through brd3 to TRIGGER_LINE(1)\n");
++}
++
++void test_ni_lookup_route_register(void)
++{
++	const struct ni_route_tables *T = &private.routing_tables;
++
++	init_pci_fake();
++	unittest(ni_lookup_route_register(O(0), O(0), T) == -EINVAL,
++		 "check for bad route 0-->0\n");
++	unittest(ni_lookup_route_register(O(1), O(0), T) == 1,
++		 "validate first destination\n");
++	unittest(ni_lookup_route_register(O(6), O(5), T) == 6,
++		 "validate middle destination\n");
++	unittest(ni_lookup_route_register(O(8), O(9), T) == 8,
++		 "validate last destination\n");
++	unittest(ni_lookup_route_register(O(10), O(9), T) == -EINVAL,
++		 "lookup invalid desination\n");
++
++	unittest(ni_lookup_route_register(rgout0_src0, TRIGGER_LINE(0), T) ==
++		 -EINVAL,
++		 "rgout0_src0: no direct lookup of indirect route\n");
++	unittest(ni_lookup_route_register(rgout0_src0, NI_RGOUT0, T) == 0,
++		 "rgout0_src0: lookup indirect route register\n");
++	unittest(ni_lookup_route_register(rgout0_src1, TRIGGER_LINE(2), T) ==
++		 -EINVAL,
++		 "rgout0_src1: no direct lookup of indirect route\n");
++	unittest(ni_lookup_route_register(rgout0_src1, NI_RGOUT0, T) == 1,
++		 "rgout0_src1: lookup indirect route register\n");
++
++	unittest(ni_lookup_route_register(brd0_src0, TRIGGER_LINE(4), T) ==
++		 -EINVAL,
++		 "brd0_src0: no direct lookup of indirect route\n");
++	unittest(ni_lookup_route_register(brd0_src0, NI_RTSI_BRD(0), T) == 0,
++		 "brd0_src0: lookup indirect route register\n");
++	unittest(ni_lookup_route_register(brd0_src1, TRIGGER_LINE(4), T) ==
++		 -EINVAL,
++		 "brd0_src1: no direct lookup of indirect route\n");
++	unittest(ni_lookup_route_register(brd0_src1, NI_RTSI_BRD(0), T) == 1,
++		 "brd0_src1: lookup indirect route register\n");
++}
++
++void test_route_is_valid(void)
++{
++	const struct ni_route_tables *T = &private.routing_tables;
++
++	init_pci_fake();
++	unittest(!route_is_valid(O(0), O(0), T),
++		 "check for bad route 0-->0\n");
++	unittest(route_is_valid(O(0), O(1), T),
++		 "validate first destination\n");
++	unittest(route_is_valid(O(5), O(6), T),
++		 "validate middle destination\n");
++	unittest(route_is_valid(O(8), O(9), T),
++		 "validate last destination\n");
++}
++
++void test_ni_is_cmd_dest(void)
++{
++	init_pci_fake();
++	unittest(ni_is_cmd_dest(NI_AI_SampleClock),
++		 "check that AI/SampleClock is cmd destination\n");
++	unittest(ni_is_cmd_dest(NI_AI_StartTrigger),
++		 "check that AI/StartTrigger is cmd destination\n");
++	unittest(ni_is_cmd_dest(NI_AI_ConvertClock),
++		 "check that AI/ConvertClock is cmd destination\n");
++	unittest(ni_is_cmd_dest(NI_AO_SampleClock),
++		 "check that AO/SampleClock is cmd destination\n");
++	unittest(ni_is_cmd_dest(NI_DO_SampleClock),
++		 "check that DO/SampleClock is cmd destination\n");
++	unittest(!ni_is_cmd_dest(NI_AO_SampleClockTimebase),
++		 "check that AO/SampleClockTimebase _not_ cmd destination\n");
++}
++
++void test_channel_is_pfi(void)
++{
++	init_pci_fake();
++	unittest(channel_is_pfi(NI_PFI(0)), "check First pfi channel\n");
++	unittest(channel_is_pfi(NI_PFI(10)), "check 10th pfi channel\n");
++	unittest(channel_is_pfi(NI_PFI(-1)), "check last pfi channel\n");
++	unittest(!channel_is_pfi(NI_PFI(-1) + 1),
++		 "check first non pfi channel\n");
++}
++
++void test_channel_is_rtsi(void)
++{
++	init_pci_fake();
++	unittest(channel_is_rtsi(TRIGGER_LINE(0)),
++		 "check First rtsi channel\n");
++	unittest(channel_is_rtsi(TRIGGER_LINE(3)),
++		 "check 3rd rtsi channel\n");
++	unittest(channel_is_rtsi(TRIGGER_LINE(-1)),
++		 "check last rtsi channel\n");
++	unittest(!channel_is_rtsi(TRIGGER_LINE(-1) + 1),
++		 "check first non rtsi channel\n");
++}
++
++void test_ni_count_valid_routes(void)
++{
++	const struct ni_route_tables *T = &private.routing_tables;
++
++	init_pci_fake();
++	unittest(ni_count_valid_routes(T) == 57, "count all valid routes\n");
++}
++
++void test_ni_get_valid_routes(void)
++{
++	const struct ni_route_tables *T = &private.routing_tables;
++	unsigned int pair_data[2];
++
++	init_pci_fake();
++	unittest(ni_get_valid_routes(T, 0, NULL) == 57,
++		 "count all valid routes through ni_get_valid_routes\n");
++
++	unittest(ni_get_valid_routes(T, 1, pair_data) == 1,
++		 "copied first valid route from ni_get_valid_routes\n");
++	unittest(pair_data[0] == O(1),
++		 "source of first valid pair from ni_get_valid_routes\n");
++	unittest(pair_data[1] == O(0),
++		 "destination of first valid pair from ni_get_valid_routes\n");
++}
++
++void test_ni_find_route_source(void)
++{
++	const struct ni_route_tables *T = &private.routing_tables;
++
++	init_pci_fake();
++	unittest(ni_find_route_source(4, O(4), T) == -EINVAL,
++		 "check for bad source 4-->4\n");
++	unittest(ni_find_route_source(0, O(1), T) == O(0),
++		 "find first source\n");
++	unittest(ni_find_route_source(4, O(6), T) == O(4),
++		 "find middle source\n");
++	unittest(ni_find_route_source(9, O(8), T) == O(9),
++		 "find last source");
++	unittest(ni_find_route_source(8, O(9), T) == O(8),
++		 "find invalid source (without checking device routes)\n");
++}
++
++void test_route_register_is_valid(void)
++{
++	const struct ni_route_tables *T = &private.routing_tables;
++
++	init_pci_fake();
++	unittest(route_register_is_valid(4, O(4), T) == false,
++		 "check for bad source 4-->4\n");
++	unittest(route_register_is_valid(0, O(1), T) == true,
++		 "find first source\n");
++	unittest(route_register_is_valid(4, O(6), T) == true,
++		 "find middle source\n");
++	unittest(route_register_is_valid(9, O(8), T) == true,
++		 "find last source");
++}
++
++void test_ni_check_trigger_arg(void)
++{
++	const struct ni_route_tables *T = &private.routing_tables;
++
++	init_pci_fake();
++	unittest(ni_check_trigger_arg(0, O(0), T) == -EINVAL,
++		 "check bad direct trigger arg for first reg->dest\n");
++	unittest(ni_check_trigger_arg(0, O(1), T) == 0,
++		 "check direct trigger arg for first reg->dest\n");
++	unittest(ni_check_trigger_arg(4, O(6), T) == 0,
++		 "check direct trigger arg for middle reg->dest\n");
++	unittest(ni_check_trigger_arg(9, O(8), T) == 0,
++		 "check direct trigger arg for last reg->dest\n");
++
++	unittest(ni_check_trigger_arg_roffs(-1, O(0), T, 1) == -EINVAL,
++		 "check bad direct trigger arg for first reg->dest w/offs\n");
++	unittest(ni_check_trigger_arg_roffs(0, O(1), T, 0) == 0,
++		 "check direct trigger arg for first reg->dest w/offs\n");
++	unittest(ni_check_trigger_arg_roffs(3, O(6), T, 1) == 0,
++		 "check direct trigger arg for middle reg->dest w/offs\n");
++	unittest(ni_check_trigger_arg_roffs(7, O(8), T, 2) == 0,
++		 "check direct trigger arg for last reg->dest w/offs\n");
++
++	unittest(ni_check_trigger_arg(O(0), O(0), T) == -EINVAL,
++		 "check bad trigger arg for first src->dest\n");
++	unittest(ni_check_trigger_arg(O(0), O(1), T) == 0,
++		 "check trigger arg for first src->dest\n");
++	unittest(ni_check_trigger_arg(O(5), O(6), T) == 0,
++		 "check trigger arg for middle src->dest\n");
++	unittest(ni_check_trigger_arg(O(8), O(9), T) == 0,
++		 "check trigger arg for last src->dest\n");
++}
++
++void test_ni_get_reg_value(void)
++{
++	const struct ni_route_tables *T = &private.routing_tables;
++
++	init_pci_fake();
++	unittest(ni_get_reg_value(0, O(0), T) == -1,
++		 "check bad direct trigger arg for first reg->dest\n");
++	unittest(ni_get_reg_value(0, O(1), T) == 0,
++		 "check direct trigger arg for first reg->dest\n");
++	unittest(ni_get_reg_value(4, O(6), T) == 4,
++		 "check direct trigger arg for middle reg->dest\n");
++	unittest(ni_get_reg_value(9, O(8), T) == 9,
++		 "check direct trigger arg for last reg->dest\n");
++
++	unittest(ni_get_reg_value_roffs(-1, O(0), T, 1) == -1,
++		 "check bad direct trigger arg for first reg->dest w/offs\n");
++	unittest(ni_get_reg_value_roffs(0, O(1), T, 0) == 0,
++		 "check direct trigger arg for first reg->dest w/offs\n");
++	unittest(ni_get_reg_value_roffs(3, O(6), T, 1) == 4,
++		 "check direct trigger arg for middle reg->dest w/offs\n");
++	unittest(ni_get_reg_value_roffs(7, O(8), T, 2) == 9,
++		 "check direct trigger arg for last reg->dest w/offs\n");
++
++	unittest(ni_get_reg_value(O(0), O(0), T) == -1,
++		 "check bad trigger arg for first src->dest\n");
++	unittest(ni_get_reg_value(O(0), O(1), T) == 0,
++		 "check trigger arg for first src->dest\n");
++	unittest(ni_get_reg_value(O(5), O(6), T) == 5,
++		 "check trigger arg for middle src->dest\n");
++	unittest(ni_get_reg_value(O(8), O(9), T) == 8,
++		 "check trigger arg for last src->dest\n");
++}
++
++/* **** BEGIN simple module entry/exit functions **** */
++static int __init ni_routes_unittest(void)
++{
++	const unittest_fptr unit_tests[] = {
++		(unittest_fptr)test_ni_assign_device_routes,
++		(unittest_fptr)test_ni_sort_device_routes,
++		(unittest_fptr)test_ni_find_route_set,
++		(unittest_fptr)test_ni_route_set_has_source,
++		(unittest_fptr)test_ni_route_to_register,
++		(unittest_fptr)test_ni_lookup_route_register,
++		(unittest_fptr)test_route_is_valid,
++		(unittest_fptr)test_ni_is_cmd_dest,
++		(unittest_fptr)test_channel_is_pfi,
++		(unittest_fptr)test_channel_is_rtsi,
++		(unittest_fptr)test_ni_count_valid_routes,
++		(unittest_fptr)test_ni_get_valid_routes,
++		(unittest_fptr)test_ni_find_route_source,
++		(unittest_fptr)test_route_register_is_valid,
++		(unittest_fptr)test_ni_check_trigger_arg,
++		(unittest_fptr)test_ni_get_reg_value,
++		NULL,
++	};
++
++	exec_unittests("ni_routes", unit_tests);
++	return 0;
++}
++
++static void __exit ni_routes_unittest_exit(void) { }
++
++module_init(ni_routes_unittest);
++module_exit(ni_routes_unittest_exit);
++
++MODULE_AUTHOR("Comedi http://www.comedi.org");
++MODULE_DESCRIPTION("Comedi unit-tests for ni_routes module");
++MODULE_LICENSE("GPL");
++/* **** END simple module entry/exit functions **** */

commit ba932fcfee28b6a23bb8a903ce5a2210ac861721
+Author: Spencer E. Olson 
+Date:   Wed Oct 3 14:56:03 2018 -0600
+
+    staging: comedi: ni_routing: Add NI signal routing info
+    
+    See README for a thorough discussion of this content.
+    
+    Adds tables of all register values for routing various signals to various
+    terminals on National Instruments hardware.  This information is directly
+    compared to and taken from register-level programming documentation and/or
+    register-level programming examples as provided by National Instruments.
+    
+    Furthermore, this information was mostly compared (favorably) to the
+    register values already used in the comedi drivers for NI hardware.
+    
+    Adds tables of valid routes for many devices.  This information is not
+    consistent from device to device, nor entirely consistent within device
+    families.  One additional major challenge is that this information does not
+    seem to be obtainable in any programmatic fashion, neither through the
+    proprietary NIDAQmx(-base) c-libraries, nor with register level
+    programming, _nor_ through any documentation.  In fact, the only consistent
+    source of this information is through the proprietary NI-MAX software,
+    which currently only runs on Windows platforms.  A further challenge is
+    that this information cannot be exported from NI-MAX, except by screenshot.
+    
+    The collection and maintenance of this information is somewhat tedious and
+    requires frequent re-examination and comparison of NI-MAX and/or the
+    NI-MHDDK documentation (register programming information) and NI-MHDDK
+    examples.  Tools are added with this patch to facilitate generating CSV
+    files from the data tables.  These CSV files can be used with a spreadsheet
+    program to provide better visual comparision with screenshots gathered from
+    NI-MAX.  Tools are also added to regenerate the data tables from CSV
+    content--this greatly enhances updating data tables with large changes
+    (such as when adding devices).
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_routing/README b/drivers/staging/comedi/drivers/ni_routing/README
+new file mode 100644
+index 000000000000..b65c4ebedbc4
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/README
+@@ -0,0 +1,240 @@
++Framework for Maintaining Common National Instruments Terminal/Signal names
++
++The contents of this directory are primarily for maintaining and formatting all
++known valid signal routes for various National Instruments devices.
++
++Some background:
++  There have been significant confusions over the past many years for users
++  when trying to understand how to connect to/from signals and terminals on
++  NI hardware using comedi.  The major reason for this is that the actual
++  register values were exposed and required to be used by users.  Several
++  major reasons exist why this caused major confusion for users:
++
++  1) The register values are _NOT_ in user documentation, but rather in
++    arcane locations, such as a few register programming manuals that are
++    increasingly hard to find and the NI-MHDDK (comments in in example code).
++    There is no one place to find the various valid values of the registers.
++
++  2) The register values are _NOT_ completely consistent.  There is no way to
++    gain any sense of intuition of which values, or even enums one should use
++    for various registers.  There was some attempt in prior use of comedi to
++    name enums such that a user might know which enums should be used for
++    varying purposes, but the end-user had to gain a knowledge of register
++    values to correctly wield this approach.
++
++  3) The names for signals and registers found in the various register level
++    programming manuals and vendor-provided documentation are _not_ even
++    close to the same names that are in the end-user documentation.
++
++  4) The sets of routes that are valid are not consistent from device to device.
++    One additional major challenge is that this information does not seem to be
++    obtainable in any programmatic fashion, neither through the proprietary
++    NIDAQmx(-base) c-libraries, nor with register level programming, _nor_
++    through any documentation.  In fact, the only consistent source of this
++    information is through the proprietary NI-MAX software, which currently only
++    runs on Windows platforms.  A further challenge is that this information
++    cannot be exported from NI-MAX, except by screenshot.
++
++
++
++The content of this directory is part of an effort to greatly simplify the use
++of signal routing capabilities of National Instruments data-acquisition and
++control hardware.  In order to facilitate the transfer of register-level
++information _and_ the knowledge of valid routes per device, a few specific
++choices were made:
++
++
++1) The names of the National Instruments signals/terminals that are used in this
++  directory are chosen to be consistent with (a) the NI's user level
++  documentation, (b) NI's user-level code, (c) the information as provided by
++  the proprietary NI-MAX software, and (d) the user interface code provided by
++  the user-land comedilib library.
++
++  The impact of this choice implies that one allows the use of CamelScript names
++  in the kernel.  In short, the choice to use CamelScript and the exact names
++  below is for maintainability, clarity, similarity to manufacturer's
++  documentation, _and_ a mitigation for confusion that has plagued the use of
++  these drivers for years!
++
++2) The bulk of the real content for this directory is stored in two separate
++  collections (i.e. sub-directories) of tables stored in c source files:
++
++  (a) ni_route_values/ni_[series-label]series.c
++
++        This data represents all the various register values to use for the
++        multiple different signal MUXes for the specific device families.
++
++        The values are all wrapped in one of three macros to help document and
++        track which values have been implemented and tested.
++        These macros are:
++          V() : register value is valid, tested, and implemented
++          I() : register value is implemented but needs testing
++          U() : register value is not implemented
++
++        The actual function of these macros will depend on whether the code is
++        compiled in the kernel or whether it is compiled into the conversion
++        tools.  For the conversion tools, it can be used to indicate the status
++        of the register value.  For the kernel, V() and I() both perform the
++        same function and prepare data to be used; U() zeroes out the value to
++        ensure that it cannot be used.
++
++        *** It would be a great help for users to test these values such that
++        these files can be correctly marked/documented ***
++
++  (b) ni_device_routes/[board-name].c
++
++        This data represents the known set of valid signal routes that are
++        possible for each specific board.  Although the family defines the
++        register values to use for a particular signal MUX, not all possible
++        signals are actually available on each board.
++
++        In order for a particular board to take advantage of the effort to
++        simplify/clarify signal routing on NI devices, a corresponding
++        [board-name].c file must be created.  This file should reflect the known
++        valid _direct_ routing capabilities of the board.
++
++        As noted above, the only known consistent source of information for
++        valid device routes comes from the proprietary National Instruments
++        Windows software, NI-MAX.  Also, as noted above, this information can
++        only be visually conveyed from NI-MAX to other media.  To make this
++        easier, the naming conventions used in the [board-name].c file are
++        similar to the naming conventions as presented by NI-MAX.
++
++
++3) Two other files aggregate the above data to integrate it into comedi:
++    ni_route_values.c
++    ni_device_routes.c
++
++  When adding a new [board-name].c file, be sure to also add in the line in
++  ni_device_routes.c to include this information into comedi.
++
++
++4) Several tools have been included to convert from/to the c file formats.
++  These tools are best used/demonstrated via the included Makefile targets:
++  (a) `make csv-files`
++     Creates new csv-files using content of c-files of existing
++     ni_routing/* content.  New csv files are placed in csv
++     sub-directory.
++
++     As noted above, the only consistent source of information of valid
++     device routes comes from the proprietary National Instruments Windows
++     software, NI-MAX.  Also, as noted above, this information can only be
++     visually conveyed from NI-MAX to other media.  This make target creates
++     spreadsheet representations of the routing data.  The choice of using a
++     spreadsheet (ala CSV) to copy this information allows for easy direct
++     visual comparison to the NI-MAX "Valid Routes" tables.
++
++     Furthermore, the register-level information is much easier to identify and
++     correct when entire families of NI devices are shown side by side in table
++     format.  This is made easy by using a file-storage format that can be
++     loaded into a spreadsheet application.
++
++     Finally, .csv content is very easy to edit and read using a variety of
++     tools, including spreadsheets or various other scripting languages.  In
++     fact, the tools provided here enable quick conversion of the
++     spreadsheet-like .csv format to c-files that follow the kernel coding
++     conventions.
++
++
++  (b) `make c-files`
++     Creates new c-files using content of csv sub-directory.  These
++     new c-files can be compared to the active content in the
++     ni_routing directory.
++  (c) `make csv-blank`
++     Create a new blank csv file.  This is useful for establishing a
++     new data table for either a device family (less likely) or a
++     specific board of an existing device family (more likely).
++  (d) `make clean`
++     Remove all generated files/directories.
++  (e) `make everything`
++     Build all csv-files, then all new c-files.
++
++
++
++
++In summary, similar confusion about signal routing configuration, albeit less,
++plagued NI's previous version of their own proprietary drivers.  Earlier than
++2003, NI greatly simplified the situation for users by releasing a new API that
++abstracted the names of signals/terminals to a common and intuitive set of
++names.  In addition, this new API provided a much more common interface to use
++for most of NI hardware.
++
++Comedi already provides such a common interface for data-acquisition and control
++hardware.  This effort complements comedi's abstraction layers by further
++abstracting much more of the use cases for NI hardware, but allowing users _and_
++developers to directly refer to NI documentation (user-level, register-level,
++and the register-level examples of the NI-MHDDK).
++
++
++
++--------------------------------------------------------------------------------
++Various naming conventions and relations:
++--------------------------------------------------------------------------------
++These are various notes that help to relate the naming conventions used in the
++NI-STC with those naming conventions used here.
++--------------------------------------------------------------------------------
++
++  Signal sources for most signals-destinations are given a specific naming
++  convention, although the register values are not consistent.  This next table
++  shows the mapping between the names used in comedi for NI and those names
++  typically used within the NI-STC documentation.
++
++  (comedi)                      (NI-STC input or output)    (NOTE)
++  ------------------------------------------------------------------------------
++  TRIGGER_LINE(i)               RTSI_Trig_i_Output_Select   i in range [0..7]
++  NI_AI_STOP                    AI_STOP
++  NI_AI_SampleClock             AI_START_Select
++  NI_AI_SampleClockTimebase     AI_SI                       If internal sample
++                                                            clock signal is used
++  NI_AI_StartTrigger            AI_START1_Select
++  NI_AI_ReferenceTrigger        AI_START2_Select            for pre-triggered
++                                                            acquisition---not
++                                                            currently supported
++                                                            in comedi
++  NI_AI_ConvertClock            AI_CONVERT_Source_Select
++  NI_AI_ConvertClockTimebase    AI_SI2                      If internal convert
++                                                            signal is used
++  NI_AI_HoldCompleteEvent
++  NI_AI_PauseTrigger            AI_External_Gate
++  NI_AO_SampleClock             AO_UPDATE
++  NI_AO_SampleClockTimebase     AO_UI
++  NI_AO_StartTrigger            AO_START1
++  NI_AO_PauseTrigger            AO_External_Gate
++  NI_DI_SampleClock
++  NI_DO_SampleClock
++  NI_MasterTimebase
++  NI_20MHzTimebase              TIMEBASE 1 && TIMEBASE 3 if no higher clock exists
++  NI_80MHzTimebase              TIMEBASE 3
++  NI_100kHzTimebase             TIMEBASE 2
++  NI_10MHzRefClock
++  PXI_Clk10
++  NI_CtrOut(0)                  GPFO_0                      external ctr0out pin
++  NI_CtrOut(1)                  GPFO_1                      external ctr1out pin
++  NI_CtrSource(0)
++  NI_CtrSource(1)
++  NI_CtrGate(0)
++  NI_CtrGate(1)
++  NI_CtrInternalOutput(0)       G_OUT0, G0_TC               for Ctr1Source, Ctr1Gate
++  NI_CtrInternalOutput(1)       G_OUT1, G1_TC               for Ctr0Source, Ctr0Gate
++  NI_RGOUT0                     RGOUT0                      internal signal
++  NI_FrequencyOutput
++  #NI_FrequencyOutputTimebase
++  NI_ChangeDetectionEvent
++  NI_RTSI_BRD(0)
++  NI_RTSI_BRD(1)
++  NI_RTSI_BRD(2)
++  NI_RTSI_BRD(3)
++  #NI_SoftwareStrobe
++  NI_LogicLow
++  NI_CtrA(0)                    G0_A_Select                 see M-Series user
++                                                            manual (371022K-01)
++  NI_CtrA(1)                    G1_A_Select                 see M-Series user
++                                                            manual (371022K-01)
++  NI_CtrB(0)                    G0_B_Select, up/down        see M-Series user
++                                                            manual (371022K-01)
++  NI_CtrB(1)                    G1_B_Select, up/down        see M-Series user
++                                                            manual (371022K-01)
++  NI_CtrZ(0)                                                see M-Series user
++                                                            manual (371022K-01)
++  NI_CtrZ(1)                                                see M-Series user
++                                                            manual (371022K-01)
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_device_routes.c b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes.c
+new file mode 100644
+index 000000000000..7b6a74dfe48b
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes.c
+@@ -0,0 +1,51 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_device_routes.c
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#include "ni_device_routes.h"
++#include "ni_device_routes/all.h"
++
++struct ni_device_routes *const ni_device_routes_list[] = {
++	&ni_pxi_6030e_device_routes,
++	&ni_pci_6070e_device_routes,
++	&ni_pci_6220_device_routes,
++	&ni_pci_6221_device_routes,
++	&ni_pxi_6224_device_routes,
++	&ni_pxi_6225_device_routes,
++	&ni_pci_6229_device_routes,
++	&ni_pci_6251_device_routes,
++	&ni_pxi_6251_device_routes,
++	&ni_pxie_6251_device_routes,
++	&ni_pci_6254_device_routes,
++	&ni_pci_6259_device_routes,
++	&ni_pci_6534_device_routes,
++	&ni_pci_6602_device_routes,
++	&ni_pci_6713_device_routes,
++	&ni_pci_6723_device_routes,
++	&ni_pci_6733_device_routes,
++	&ni_pxi_6733_device_routes,
++	NULL,
++};
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_device_routes.h b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes.h
+new file mode 100644
+index 000000000000..b9f1c47d19e1
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes.h
+@@ -0,0 +1,32 @@
++/* SPDX-License-Identifier: GPL-2.0+ */
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_device_routes.c
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * This file is meant to be included by comedi/drivers/ni_routes.c
++ */
++
++#ifndef _COMEDI_DRIVERS_NI_ROUTINT_NI_DEVICE_ROUTES_H
++#define _COMEDI_DRIVERS_NI_ROUTINT_NI_DEVICE_ROUTES_H
++
++#include "../ni_routes.h"
++
++extern struct ni_device_routes *const ni_device_routes_list[];
++
++#endif /* _COMEDI_DRIVERS_NI_ROUTINT_NI_DEVICE_ROUTES_H */
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/all.h b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/all.h
+new file mode 100644
+index 000000000000..78b24138acb7
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/all.h
+@@ -0,0 +1,54 @@
++/* SPDX-License-Identifier: GPL-2.0+ */
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_device_routes/all.h
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#ifndef _COMEDI_DRIVERS_NI_ROUTING_NI_DEVICE_ROUTES_EXTERN_H
++#define _COMEDI_DRIVERS_NI_ROUTING_NI_DEVICE_ROUTES_EXTERN_H
++
++#include "../ni_device_routes.h"
++
++extern struct ni_device_routes ni_pxi_6030e_device_routes;
++extern struct ni_device_routes ni_pci_6070e_device_routes;
++extern struct ni_device_routes ni_pci_6220_device_routes;
++extern struct ni_device_routes ni_pci_6221_device_routes;
++extern struct ni_device_routes ni_pxi_6224_device_routes;
++extern struct ni_device_routes ni_pxi_6225_device_routes;
++extern struct ni_device_routes ni_pci_6229_device_routes;
++extern struct ni_device_routes ni_pci_6251_device_routes;
++extern struct ni_device_routes ni_pxi_6251_device_routes;
++extern struct ni_device_routes ni_pxie_6251_device_routes;
++extern struct ni_device_routes ni_pci_6254_device_routes;
++extern struct ni_device_routes ni_pci_6259_device_routes;
++extern struct ni_device_routes ni_pci_6534_device_routes;
++extern struct ni_device_routes ni_pxie_6535_device_routes;
++extern struct ni_device_routes ni_pci_6602_device_routes;
++extern struct ni_device_routes ni_pci_6713_device_routes;
++extern struct ni_device_routes ni_pci_6723_device_routes;
++extern struct ni_device_routes ni_pci_6733_device_routes;
++extern struct ni_device_routes ni_pxi_6733_device_routes;
++extern struct ni_device_routes ni_pxie_6738_device_routes;
++
++#endif //_COMEDI_DRIVERS_NI_ROUTING_NI_DEVICE_ROUTES_EXTERN_H
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6070e.c b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6070e.c
+new file mode 100644
+index 000000000000..f1126a0cb285
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6070e.c
+@@ -0,0 +1,639 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_device_routes/pci-6070e.c
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#include "../ni_device_routes.h"
++#include "all.h"
++
++struct ni_device_routes ni_pci_6070e_device_routes = {
++	.device = "pci-6070e",
++	.routes = (struct ni_route_set[]){
++		{
++			.dest = NI_PFI(0),
++			.src = (int[]){
++				NI_AI_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(1),
++			.src = (int[]){
++				NI_AI_ReferenceTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(2),
++			.src = (int[]){
++				NI_AI_ConvertClock,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(3),
++			.src = (int[]){
++				NI_CtrSource(1),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(4),
++			.src = (int[]){
++				NI_CtrGate(1),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(5),
++			.src = (int[]){
++				NI_AO_SampleClock,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(6),
++			.src = (int[]){
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(7),
++			.src = (int[]){
++				NI_AI_SampleClock,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(8),
++			.src = (int[]){
++				NI_CtrSource(0),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(9),
++			.src = (int[]){
++				NI_CtrGate(0),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(0),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(1),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(2),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(3),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(4),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(5),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(6),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(7),
++			.src = (int[]){
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_MasterTimebase,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_MasterTimebase,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrOut(0),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_CtrInternalOutput(0),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrOut(1),
++			.src = (int[]){
++				NI_CtrInternalOutput(1),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_CtrInternalOutput(0),
++				NI_AI_SampleClockTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_MasterTimebase,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_CtrInternalOutput(0),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ReferenceTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ConvertClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_CtrInternalOutput(0),
++				NI_AI_ConvertClockTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ConvertClockTimebase,
++			.src = (int[]){
++				TRIGGER_LINE(7),
++				NI_AI_SampleClockTimebase,
++				NI_MasterTimebase,
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_HoldComplete,
++			.src = (int[]){
++				NI_AI_HoldCompleteEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_CtrInternalOutput(1),
++				NI_AO_SampleClockTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_MasterTimebase,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_AI_StartTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_MasterTimebase,
++			.src = (int[]){
++				TRIGGER_LINE(7),
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{ /* Termination of list */
++			.dest = 0,
++		},
++	},
++};
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6220.c b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6220.c
+new file mode 100644
+index 000000000000..74a59222963f
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6220.c
+@@ -0,0 +1,1418 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_device_routes/pci-6220.c
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#include "../ni_device_routes.h"
++#include "all.h"
++
++struct ni_device_routes ni_pci_6220_device_routes = {
++	.device = "pci-6220",
++	.routes = (struct ni_route_set[]){
++		{
++			.dest = NI_PFI(0),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(1),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(2),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(3),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(4),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(5),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(6),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(7),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(8),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(9),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(10),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(11),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(12),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(13),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(14),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(15),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(4),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(5),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(6),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(7),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrGate(1),
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrGate(0),
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrA(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrA(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrB(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrB(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrZ(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrZ(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClockTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ReferenceTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ConvertClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_ConvertClockTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ConvertClockTimebase,
++			.src = (int[]){
++				NI_AI_SampleClockTimebase,
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DI_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_ConvertClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DO_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_ConvertClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{ /* Termination of list */
++			.dest = 0,
++		},
++	},
++};
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6221.c b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6221.c
+new file mode 100644
+index 000000000000..44dcbabf2a99
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6221.c
+@@ -0,0 +1,1602 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_device_routes/pci-6221.c
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#include "../ni_device_routes.h"
++#include "all.h"
++
++struct ni_device_routes ni_pci_6221_device_routes = {
++	.device = "pci-6221",
++	.routes = (struct ni_route_set[]){
++		{
++			.dest = NI_PFI(0),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(1),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(2),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(3),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(4),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(5),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(6),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(7),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(8),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(9),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(10),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(11),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(12),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(13),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(14),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(15),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(4),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(5),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(6),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(7),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrGate(1),
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrGate(0),
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrA(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrA(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrB(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrB(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrZ(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrZ(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClockTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ReferenceTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ConvertClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_ConvertClockTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ConvertClockTimebase,
++			.src = (int[]){
++				NI_AI_SampleClockTimebase,
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AO_SampleClockTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AI_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DI_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DO_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{ /* Termination of list */
++			.dest = 0,
++		},
++	},
++};
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6229.c b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6229.c
+new file mode 100644
+index 000000000000..fa5794e4e2b3
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6229.c
+@@ -0,0 +1,1602 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_device_routes/pci-6229.c
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#include "../ni_device_routes.h"
++#include "all.h"
++
++struct ni_device_routes ni_pci_6229_device_routes = {
++	.device = "pci-6229",
++	.routes = (struct ni_route_set[]){
++		{
++			.dest = NI_PFI(0),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(1),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(2),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(3),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(4),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(5),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(6),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(7),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(8),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(9),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(10),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(11),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(12),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(13),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(14),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(15),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(4),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(5),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(6),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(7),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrGate(1),
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrGate(0),
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrA(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrA(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrB(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrB(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrZ(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrZ(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClockTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ReferenceTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ConvertClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_ConvertClockTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ConvertClockTimebase,
++			.src = (int[]){
++				NI_AI_SampleClockTimebase,
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AO_SampleClockTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AI_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DI_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DO_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{ /* Termination of list */
++			.dest = 0,
++		},
++	},
++};
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6251.c b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6251.c
+new file mode 100644
+index 000000000000..645fd1cd2de4
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6251.c
+@@ -0,0 +1,1652 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_device_routes/pci-6251.c
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#include "../ni_device_routes.h"
++#include "all.h"
++
++struct ni_device_routes ni_pci_6251_device_routes = {
++	.device = "pci-6251",
++	.routes = (struct ni_route_set[]){
++		{
++			.dest = NI_PFI(0),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(1),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(2),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(3),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(4),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(5),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(6),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(7),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(8),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(9),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(10),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(11),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(12),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(13),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(14),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(15),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(4),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(5),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(6),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(7),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrGate(1),
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrGate(0),
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrA(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrA(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrB(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrB(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrZ(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrZ(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClockTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ReferenceTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ConvertClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_ConvertClockTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ConvertClockTimebase,
++			.src = (int[]){
++				NI_AI_SampleClockTimebase,
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AO_SampleClockTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AI_StartTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DI_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DO_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{ /* Termination of list */
++			.dest = 0,
++		},
++	},
++};
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6254.c b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6254.c
+new file mode 100644
+index 000000000000..056a240cd3a2
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6254.c
+@@ -0,0 +1,1464 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_device_routes/pci-6254.c
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#include "../ni_device_routes.h"
++#include "all.h"
++
++struct ni_device_routes ni_pci_6254_device_routes = {
++	.device = "pci-6254",
++	.routes = (struct ni_route_set[]){
++		{
++			.dest = NI_PFI(0),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(1),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(2),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(3),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(4),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(5),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(6),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(7),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(8),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(9),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(10),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(11),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(12),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(13),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(14),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(15),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(4),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(5),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(6),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(7),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrGate(1),
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrGate(0),
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrA(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrA(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrB(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrB(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrZ(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrZ(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClockTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ReferenceTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ConvertClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_ConvertClockTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ConvertClockTimebase,
++			.src = (int[]){
++				NI_AI_SampleClockTimebase,
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DI_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_ConvertClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DO_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_ConvertClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{ /* Termination of list */
++			.dest = 0,
++		},
++	},
++};
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6259.c b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6259.c
+new file mode 100644
+index 000000000000..e0b5fa78c3bc
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6259.c
+@@ -0,0 +1,1652 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_device_routes/pci-6259.c
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#include "../ni_device_routes.h"
++#include "all.h"
++
++struct ni_device_routes ni_pci_6259_device_routes = {
++	.device = "pci-6259",
++	.routes = (struct ni_route_set[]){
++		{
++			.dest = NI_PFI(0),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(1),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(2),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(3),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(4),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(5),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(6),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(7),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(8),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(9),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(10),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(11),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(12),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(13),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(14),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(15),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(4),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(5),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(6),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(7),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrGate(1),
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrGate(0),
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrA(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrA(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrB(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrB(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrZ(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrZ(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClockTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ReferenceTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ConvertClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_ConvertClockTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ConvertClockTimebase,
++			.src = (int[]){
++				NI_AI_SampleClockTimebase,
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AO_SampleClockTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AI_StartTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DI_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DO_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{ /* Termination of list */
++			.dest = 0,
++		},
++	},
++};
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6534.c b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6534.c
+new file mode 100644
+index 000000000000..a2472ed288cf
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6534.c
+@@ -0,0 +1,290 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_device_routes/pci-6534.c
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#include "../ni_device_routes.h"
++#include "all.h"
++
++struct ni_device_routes ni_pci_6534_device_routes = {
++	.device = "pci-6534",
++	.routes = (struct ni_route_set[]){
++		{
++			.dest = NI_PFI(0),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(1),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(2),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(3),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(4),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(5),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(6),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(7),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(4),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(5),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(6),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(6),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(7),
++			.src = (int[]){
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_MasterTimebase,
++			.src = (int[]){
++				TRIGGER_LINE(7),
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{ /* Termination of list */
++			.dest = 0,
++		},
++	},
++};
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6602.c b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6602.c
+new file mode 100644
+index 000000000000..91de9dac2d6a
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6602.c
+@@ -0,0 +1,3378 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_device_routes/pci-6602.c
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#include "../ni_device_routes.h"
++#include "all.h"
++
++struct ni_device_routes ni_pci_6602_device_routes = {
++	.device = "pci-6602",
++	.routes = (struct ni_route_set[]){
++		{
++			.dest = NI_PFI(2),
++			.src = (int[]){
++				NI_80MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(3),
++			.src = (int[]){
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(4),
++			.src = (int[]){
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(6),
++			.src = (int[]){
++				NI_80MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(7),
++			.src = (int[]){
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(8),
++			.src = (int[]){
++				NI_PFI(7),
++				NI_PFI(15),
++				NI_PFI(23),
++				NI_PFI(31),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(9),
++			.src = (int[]){
++				NI_PFI(7),
++				NI_PFI(15),
++				NI_PFI(23),
++				NI_PFI(31),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(10),
++			.src = (int[]){
++				NI_CtrGate(7),
++				NI_LogicLow,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(11),
++			.src = (int[]){
++				NI_CtrSource(7),
++				NI_LogicLow,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(12),
++			.src = (int[]){
++				NI_PFI(6),
++				NI_PFI(14),
++				NI_PFI(22),
++				NI_PFI(30),
++				NI_PFI(38),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(13),
++			.src = (int[]){
++				NI_PFI(6),
++				NI_PFI(14),
++				NI_PFI(22),
++				NI_PFI(30),
++				NI_PFI(38),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(14),
++			.src = (int[]){
++				NI_CtrGate(6),
++				NI_LogicLow,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(15),
++			.src = (int[]){
++				NI_CtrSource(6),
++				NI_LogicLow,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(16),
++			.src = (int[]){
++				NI_PFI(5),
++				NI_PFI(13),
++				NI_PFI(21),
++				NI_PFI(29),
++				NI_PFI(37),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(17),
++			.src = (int[]){
++				NI_PFI(5),
++				NI_PFI(13),
++				NI_PFI(21),
++				NI_PFI(29),
++				NI_PFI(37),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(18),
++			.src = (int[]){
++				NI_CtrGate(5),
++				NI_LogicLow,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(19),
++			.src = (int[]){
++				NI_CtrSource(5),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(20),
++			.src = (int[]){
++				NI_PFI(4),
++				NI_PFI(12),
++				NI_PFI(28),
++				NI_PFI(36),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(21),
++			.src = (int[]){
++				NI_PFI(4),
++				NI_PFI(12),
++				NI_PFI(20),
++				NI_PFI(28),
++				NI_PFI(36),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(22),
++			.src = (int[]){
++				NI_CtrGate(4),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(23),
++			.src = (int[]){
++				NI_CtrSource(4),
++				NI_LogicLow,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(24),
++			.src = (int[]){
++				NI_PFI(3),
++				NI_PFI(11),
++				NI_PFI(19),
++				NI_PFI(27),
++				NI_PFI(35),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(3),
++				NI_CtrSource(7),
++				NI_CtrGate(3),
++				NI_CtrGate(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(25),
++			.src = (int[]){
++				NI_PFI(3),
++				NI_PFI(11),
++				NI_PFI(19),
++				NI_PFI(27),
++				NI_PFI(35),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(3),
++				NI_CtrSource(7),
++				NI_CtrGate(3),
++				NI_CtrGate(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(26),
++			.src = (int[]){
++				NI_CtrGate(3),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(27),
++			.src = (int[]){
++				NI_CtrSource(3),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(28),
++			.src = (int[]){
++				NI_PFI(2),
++				NI_PFI(10),
++				NI_PFI(18),
++				NI_PFI(26),
++				NI_PFI(34),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(2),
++				NI_CtrSource(6),
++				NI_CtrGate(2),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(29),
++			.src = (int[]){
++				NI_PFI(2),
++				NI_PFI(10),
++				NI_PFI(18),
++				NI_PFI(26),
++				NI_PFI(34),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(2),
++				NI_CtrSource(6),
++				NI_CtrGate(2),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(30),
++			.src = (int[]){
++				NI_CtrGate(2),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(31),
++			.src = (int[]){
++				NI_CtrSource(2),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(32),
++			.src = (int[]){
++				NI_PFI(1),
++				NI_PFI(9),
++				NI_PFI(17),
++				NI_PFI(25),
++				NI_PFI(33),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrSource(5),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(33),
++			.src = (int[]){
++				NI_PFI(1),
++				NI_PFI(9),
++				NI_PFI(17),
++				NI_PFI(25),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrSource(5),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(34),
++			.src = (int[]){
++				NI_CtrGate(1),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(35),
++			.src = (int[]){
++				NI_CtrSource(1),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(36),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(5),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(37),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(5),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(38),
++			.src = (int[]){
++				NI_CtrGate(0),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(39),
++			.src = (int[]){
++				NI_CtrSource(0),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrSource(4),
++				NI_CtrSource(5),
++				NI_CtrSource(6),
++				NI_CtrSource(7),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrGate(4),
++				NI_CtrGate(5),
++				NI_CtrGate(6),
++				NI_CtrGate(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrSource(4),
++				NI_CtrSource(5),
++				NI_CtrSource(6),
++				NI_CtrSource(7),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrGate(4),
++				NI_CtrGate(5),
++				NI_CtrGate(6),
++				NI_CtrGate(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrSource(4),
++				NI_CtrSource(5),
++				NI_CtrSource(6),
++				NI_CtrSource(7),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrGate(4),
++				NI_CtrGate(5),
++				NI_CtrGate(6),
++				NI_CtrGate(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrSource(4),
++				NI_CtrSource(5),
++				NI_CtrSource(6),
++				NI_CtrSource(7),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrGate(4),
++				NI_CtrGate(5),
++				NI_CtrGate(6),
++				NI_CtrGate(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(4),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrSource(4),
++				NI_CtrSource(5),
++				NI_CtrSource(6),
++				NI_CtrSource(7),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrGate(4),
++				NI_CtrGate(5),
++				NI_CtrGate(6),
++				NI_CtrGate(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(5),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrSource(4),
++				NI_CtrSource(5),
++				NI_CtrSource(6),
++				NI_CtrSource(7),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrGate(4),
++				NI_CtrGate(5),
++				NI_CtrGate(6),
++				NI_CtrGate(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(6),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrSource(4),
++				NI_CtrSource(5),
++				NI_CtrSource(6),
++				NI_CtrSource(7),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrGate(4),
++				NI_CtrGate(5),
++				NI_CtrGate(6),
++				NI_CtrGate(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(7),
++			.src = (int[]){
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(3),
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(4),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(5),
++				NI_CtrSource(6),
++				NI_CtrSource(7),
++				NI_CtrGate(5),
++				NI_CtrGate(6),
++				NI_CtrGate(7),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(5),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(4),
++				NI_CtrSource(6),
++				NI_CtrSource(7),
++				NI_CtrGate(4),
++				NI_CtrGate(6),
++				NI_CtrGate(7),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(6),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(4),
++				NI_CtrSource(5),
++				NI_CtrSource(7),
++				NI_CtrGate(4),
++				NI_CtrGate(5),
++				NI_CtrGate(7),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(7),
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(7),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(4),
++				NI_CtrSource(5),
++				NI_CtrSource(6),
++				NI_CtrGate(4),
++				NI_CtrGate(5),
++				NI_CtrGate(6),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(3),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(4),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(5),
++				NI_CtrSource(6),
++				NI_CtrSource(7),
++				NI_CtrGate(5),
++				NI_CtrGate(6),
++				NI_CtrGate(7),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(5),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(4),
++				NI_CtrSource(6),
++				NI_CtrSource(7),
++				NI_CtrGate(4),
++				NI_CtrGate(6),
++				NI_CtrGate(7),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(6),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(4),
++				NI_CtrSource(5),
++				NI_CtrSource(7),
++				NI_CtrGate(4),
++				NI_CtrGate(5),
++				NI_CtrGate(7),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(7),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(4),
++				NI_CtrSource(5),
++				NI_CtrSource(6),
++				NI_CtrGate(4),
++				NI_CtrGate(5),
++				NI_CtrGate(6),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(3),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(4),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(5),
++				NI_CtrSource(6),
++				NI_CtrSource(7),
++				NI_CtrGate(4),
++				NI_CtrGate(5),
++				NI_CtrGate(6),
++				NI_CtrGate(7),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(5),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(4),
++				NI_CtrSource(6),
++				NI_CtrSource(7),
++				NI_CtrGate(4),
++				NI_CtrGate(5),
++				NI_CtrGate(6),
++				NI_CtrGate(7),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(6),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(4),
++				NI_CtrSource(5),
++				NI_CtrSource(7),
++				NI_CtrGate(4),
++				NI_CtrGate(5),
++				NI_CtrGate(6),
++				NI_CtrGate(7),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(7),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(4),
++				NI_CtrSource(5),
++				NI_CtrSource(6),
++				NI_CtrGate(4),
++				NI_CtrGate(5),
++				NI_CtrGate(6),
++				NI_CtrGate(7),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(3),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(4),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(5),
++				NI_CtrSource(6),
++				NI_CtrSource(7),
++				NI_CtrGate(5),
++				NI_CtrGate(6),
++				NI_CtrGate(7),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(5),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(4),
++				NI_CtrSource(6),
++				NI_CtrSource(7),
++				NI_CtrGate(4),
++				NI_CtrGate(6),
++				NI_CtrGate(7),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(6),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(6),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(4),
++				NI_CtrSource(5),
++				NI_CtrSource(7),
++				NI_CtrGate(4),
++				NI_CtrGate(5),
++				NI_CtrGate(7),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(7),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(7),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				NI_PFI(16),
++				NI_PFI(17),
++				NI_PFI(18),
++				NI_PFI(19),
++				NI_PFI(20),
++				NI_PFI(21),
++				NI_PFI(22),
++				NI_PFI(23),
++				NI_PFI(24),
++				NI_PFI(25),
++				NI_PFI(26),
++				NI_PFI(27),
++				NI_PFI(28),
++				NI_PFI(29),
++				NI_PFI(30),
++				NI_PFI(31),
++				NI_PFI(32),
++				NI_PFI(33),
++				NI_PFI(34),
++				NI_PFI(35),
++				NI_PFI(36),
++				NI_PFI(37),
++				NI_PFI(38),
++				NI_PFI(39),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(4),
++				NI_CtrSource(5),
++				NI_CtrSource(6),
++				NI_CtrGate(4),
++				NI_CtrGate(5),
++				NI_CtrGate(6),
++				NI_CtrInternalOutput(4),
++				NI_CtrInternalOutput(5),
++				NI_CtrInternalOutput(6),
++				NI_LogicLow,
++				NI_LogicHigh,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_MasterTimebase,
++			.src = (int[]){
++				TRIGGER_LINE(7),
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{ /* Termination of list */
++			.dest = 0,
++		},
++	},
++};
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6713.c b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6713.c
+new file mode 100644
+index 000000000000..d378b36d2084
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6713.c
+@@ -0,0 +1,400 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_device_routes/pci-6713.c
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#include "../ni_device_routes.h"
++#include "all.h"
++
++struct ni_device_routes ni_pci_6713_device_routes = {
++	.device = "pci-6713",
++	.routes = (struct ni_route_set[]){
++		{
++			.dest = NI_PFI(3),
++			.src = (int[]){
++				NI_CtrSource(1),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(4),
++			.src = (int[]){
++				NI_CtrGate(1),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(5),
++			.src = (int[]){
++				NI_AO_SampleClock,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(6),
++			.src = (int[]){
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(8),
++			.src = (int[]){
++				NI_CtrSource(0),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(9),
++			.src = (int[]){
++				NI_CtrGate(0),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(0),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(1),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(2),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(3),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(4),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(5),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(6),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(7),
++			.src = (int[]){
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_MasterTimebase,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_MasterTimebase,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_CtrInternalOutput(1),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_CtrInternalOutput(0),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrOut(0),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_CtrInternalOutput(0),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrOut(1),
++			.src = (int[]){
++				NI_CtrInternalOutput(1),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_CtrInternalOutput(1),
++				NI_AO_SampleClockTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_MasterTimebase,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_MasterTimebase,
++			.src = (int[]){
++				TRIGGER_LINE(7),
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{ /* Termination of list */
++			.dest = 0,
++		},
++	},
++};
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6723.c b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6723.c
+new file mode 100644
+index 000000000000..e0cc57ab06e7
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6723.c
+@@ -0,0 +1,400 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_device_routes/pci-6723.c
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#include "../ni_device_routes.h"
++#include "all.h"
++
++struct ni_device_routes ni_pci_6723_device_routes = {
++	.device = "pci-6723",
++	.routes = (struct ni_route_set[]){
++		{
++			.dest = NI_PFI(3),
++			.src = (int[]){
++				NI_CtrSource(1),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(4),
++			.src = (int[]){
++				NI_CtrGate(1),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(5),
++			.src = (int[]){
++				NI_AO_SampleClock,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(6),
++			.src = (int[]){
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(8),
++			.src = (int[]){
++				NI_CtrSource(0),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(9),
++			.src = (int[]){
++				NI_CtrGate(0),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(0),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(1),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(2),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(3),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(4),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(5),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(6),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(7),
++			.src = (int[]){
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_MasterTimebase,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_MasterTimebase,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_CtrInternalOutput(1),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_CtrInternalOutput(0),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrOut(0),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_CtrInternalOutput(0),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrOut(1),
++			.src = (int[]){
++				NI_CtrInternalOutput(1),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_CtrInternalOutput(1),
++				NI_AO_SampleClockTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_MasterTimebase,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_MasterTimebase,
++			.src = (int[]){
++				TRIGGER_LINE(7),
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{ /* Termination of list */
++			.dest = 0,
++		},
++	},
++};
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6733.c b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6733.c
+new file mode 100644
+index 000000000000..f6e1e17ab854
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pci-6733.c
+@@ -0,0 +1,428 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_device_routes/pci-6733.c
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#include "../ni_device_routes.h"
++#include "all.h"
++
++struct ni_device_routes ni_pci_6733_device_routes = {
++	.device = "pci-6733",
++	.routes = (struct ni_route_set[]){
++		{
++			.dest = NI_PFI(3),
++			.src = (int[]){
++				NI_CtrSource(1),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(4),
++			.src = (int[]){
++				NI_CtrGate(1),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(5),
++			.src = (int[]){
++				NI_AO_SampleClock,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(6),
++			.src = (int[]){
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(8),
++			.src = (int[]){
++				NI_CtrSource(0),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(9),
++			.src = (int[]){
++				NI_CtrGate(0),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(0),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(1),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(2),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(3),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(4),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(5),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(6),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(7),
++			.src = (int[]){
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_MasterTimebase,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_MasterTimebase,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_CtrInternalOutput(1),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_CtrInternalOutput(0),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrOut(0),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_CtrInternalOutput(0),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrOut(1),
++			.src = (int[]){
++				NI_CtrInternalOutput(1),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_CtrInternalOutput(1),
++				NI_AO_SampleClockTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_MasterTimebase,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DI_SampleClock,
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_AO_SampleClock,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DO_SampleClock,
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_AO_SampleClock,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_MasterTimebase,
++			.src = (int[]){
++				TRIGGER_LINE(7),
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{ /* Termination of list */
++			.dest = 0,
++		},
++	},
++};
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pxi-6030e.c b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pxi-6030e.c
+new file mode 100644
+index 000000000000..9978d632117f
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pxi-6030e.c
+@@ -0,0 +1,608 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_device_routes/pxi-6030e.c
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#include "../ni_device_routes.h"
++#include "all.h"
++
++struct ni_device_routes ni_pxi_6030e_device_routes = {
++	.device = "pxi-6030e",
++	.routes = (struct ni_route_set[]){
++		{
++			.dest = NI_PFI(0),
++			.src = (int[]){
++				NI_AI_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(1),
++			.src = (int[]){
++				NI_AI_ReferenceTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(2),
++			.src = (int[]){
++				NI_AI_ConvertClock,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(3),
++			.src = (int[]){
++				NI_CtrSource(1),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(4),
++			.src = (int[]){
++				NI_CtrGate(1),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(5),
++			.src = (int[]){
++				NI_AO_SampleClock,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(6),
++			.src = (int[]){
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(7),
++			.src = (int[]){
++				NI_AI_SampleClock,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(8),
++			.src = (int[]){
++				NI_CtrSource(0),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(9),
++			.src = (int[]){
++				NI_CtrGate(0),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(0),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(1),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(2),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(3),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(4),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(5),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(7),
++			.src = (int[]){
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(7),
++				NI_MasterTimebase,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(7),
++				NI_MasterTimebase,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrOut(0),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				NI_CtrInternalOutput(0),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrOut(1),
++			.src = (int[]){
++				NI_CtrInternalOutput(1),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				NI_CtrInternalOutput(0),
++				NI_AI_SampleClockTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(7),
++				NI_MasterTimebase,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				NI_CtrInternalOutput(0),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ReferenceTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ConvertClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				NI_CtrInternalOutput(0),
++				NI_AI_ConvertClockTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ConvertClockTimebase,
++			.src = (int[]){
++				TRIGGER_LINE(7),
++				NI_AI_SampleClockTimebase,
++				NI_MasterTimebase,
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_HoldComplete,
++			.src = (int[]){
++				NI_AI_HoldCompleteEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				NI_CtrInternalOutput(1),
++				NI_AO_SampleClockTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(7),
++				NI_MasterTimebase,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				NI_AI_StartTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_MasterTimebase,
++			.src = (int[]){
++				TRIGGER_LINE(7),
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{ /* Termination of list */
++			.dest = 0,
++		},
++	},
++};
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pxi-6224.c b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pxi-6224.c
+new file mode 100644
+index 000000000000..1b89e27d7aa5
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pxi-6224.c
+@@ -0,0 +1,1432 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_device_routes/pxi-6224.c
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#include "../ni_device_routes.h"
++#include "all.h"
++
++struct ni_device_routes ni_pxi_6224_device_routes = {
++	.device = "pxi-6224",
++	.routes = (struct ni_route_set[]){
++		{
++			.dest = NI_PFI(0),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(1),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(2),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(3),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(4),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(5),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(6),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(7),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(8),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(9),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(10),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(11),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(12),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(13),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(14),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(15),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(4),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(5),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(6),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(7),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				PXI_Clk10,
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrGate(0),
++				PXI_Clk10,
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrA(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrA(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrB(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrB(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrZ(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrZ(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClockTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				PXI_Clk10,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ReferenceTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ConvertClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_ConvertClockTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ConvertClockTimebase,
++			.src = (int[]){
++				NI_AI_SampleClockTimebase,
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DI_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_ConvertClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DO_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_ConvertClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{ /* Termination of list */
++			.dest = 0,
++		},
++	},
++};
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pxi-6225.c b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pxi-6225.c
+new file mode 100644
+index 000000000000..10dfc34bc87c
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pxi-6225.c
+@@ -0,0 +1,1613 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_device_routes/pxi-6225.c
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#include "../ni_device_routes.h"
++#include "all.h"
++
++struct ni_device_routes ni_pxi_6225_device_routes = {
++	.device = "pxi-6225",
++	.routes = (struct ni_route_set[]){
++		{
++			.dest = NI_PFI(0),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(1),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(2),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(3),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(4),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(5),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(6),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(7),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(8),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(9),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(10),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(11),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(12),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(13),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(14),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(15),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(4),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(5),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(6),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(7),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				PXI_Clk10,
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrGate(0),
++				PXI_Clk10,
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrA(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrA(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrB(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrB(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrZ(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrZ(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClockTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				PXI_Clk10,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ReferenceTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ConvertClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_ConvertClockTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ConvertClockTimebase,
++			.src = (int[]){
++				NI_AI_SampleClockTimebase,
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AO_SampleClockTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				PXI_Clk10,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AI_StartTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DI_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DO_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{ /* Termination of list */
++			.dest = 0,
++		},
++	},
++};
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pxi-6251.c b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pxi-6251.c
+new file mode 100644
+index 000000000000..25db4b7363de
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pxi-6251.c
+@@ -0,0 +1,1655 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_device_routes/pxi-6251.c
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#include "../ni_device_routes.h"
++#include "all.h"
++
++struct ni_device_routes ni_pxi_6251_device_routes = {
++	.device = "pxi-6251",
++	.routes = (struct ni_route_set[]){
++		{
++			.dest = NI_PFI(0),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(1),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(2),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(3),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(4),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(5),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(6),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(7),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(8),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(9),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(10),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(11),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(12),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(13),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(14),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(15),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(4),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(5),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(6),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(7),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				PXI_Star,
++				PXI_Clk10,
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrGate(0),
++				PXI_Star,
++				PXI_Clk10,
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrInternalOutput(0),
++				PXI_Star,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				PXI_Star,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrA(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				PXI_Star,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrA(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				PXI_Star,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrB(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				PXI_Star,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrB(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				PXI_Star,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrZ(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				PXI_Star,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrZ(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				PXI_Star,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				PXI_Star,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				NI_AI_SampleClockTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				PXI_Star,
++				PXI_Clk10,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ReferenceTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				PXI_Star,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ConvertClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				NI_AI_ConvertClockTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ConvertClockTimebase,
++			.src = (int[]){
++				NI_AI_SampleClockTimebase,
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				PXI_Star,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				NI_AO_SampleClockTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				PXI_Star,
++				PXI_Clk10,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				PXI_Star,
++				NI_AI_StartTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				PXI_Star,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DI_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				NI_AI_SampleClock,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DO_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				NI_AI_SampleClock,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{ /* Termination of list */
++			.dest = 0,
++		},
++	},
++};
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pxi-6733.c b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pxi-6733.c
+new file mode 100644
+index 000000000000..27da4433fc4a
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pxi-6733.c
+@@ -0,0 +1,428 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_device_routes/pxi-6733.c
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#include "../ni_device_routes.h"
++#include "all.h"
++
++struct ni_device_routes ni_pxi_6733_device_routes = {
++	.device = "pxi-6733",
++	.routes = (struct ni_route_set[]){
++		{
++			.dest = NI_PFI(3),
++			.src = (int[]){
++				NI_CtrSource(1),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(4),
++			.src = (int[]){
++				NI_CtrGate(1),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(5),
++			.src = (int[]){
++				NI_AO_SampleClock,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(6),
++			.src = (int[]){
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(8),
++			.src = (int[]){
++				NI_CtrSource(0),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(9),
++			.src = (int[]){
++				NI_CtrGate(0),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(0),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(1),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(2),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(3),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(4),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(5),
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(7),
++			.src = (int[]){
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(7),
++				PXI_Star,
++				NI_MasterTimebase,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(7),
++				PXI_Star,
++				NI_MasterTimebase,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				NI_CtrInternalOutput(0),
++				PXI_Star,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrOut(0),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				NI_CtrInternalOutput(0),
++				PXI_Star,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrOut(1),
++			.src = (int[]){
++				NI_CtrInternalOutput(1),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = PXI_Star,
++			.src = (int[]){
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrInternalOutput(0),
++				NI_CtrOut(0),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				NI_CtrInternalOutput(1),
++				PXI_Star,
++				NI_AO_SampleClockTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(7),
++				PXI_Star,
++				NI_MasterTimebase,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				PXI_Star,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				PXI_Star,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DI_SampleClock,
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				PXI_Star,
++				NI_AO_SampleClock,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DO_SampleClock,
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				PXI_Star,
++				NI_AO_SampleClock,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_MasterTimebase,
++			.src = (int[]){
++				TRIGGER_LINE(7),
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{ /* Termination of list */
++			.dest = 0,
++		},
++	},
++};
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pxie-6251.c b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pxie-6251.c
+new file mode 100644
+index 000000000000..8354fe971d59
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pxie-6251.c
+@@ -0,0 +1,1656 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_device_routes/pxie-6251.c
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#include "../ni_device_routes.h"
++#include "all.h"
++
++struct ni_device_routes ni_pxie_6251_device_routes = {
++	.device = "pxie-6251",
++	.routes = (struct ni_route_set[]){
++		{
++			.dest = NI_PFI(0),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(1),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(2),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(3),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(4),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(5),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(6),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(7),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(8),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(9),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(10),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(11),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(12),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(13),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(14),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(15),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_DI_SampleClock,
++				NI_DO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(4),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(5),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(6),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(7),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AI_ConvertClock,
++				NI_AI_PauseTrigger,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrGate(1),
++				PXI_Clk10,
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrGate(0),
++				PXI_Clk10,
++				NI_20MHzTimebase,
++				NI_80MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrA(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrA(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrB(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrB(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrZ(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrZ(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(1),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_AI_StartTrigger,
++				NI_AI_ReferenceTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClockTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				PXI_Clk10,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ReferenceTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ConvertClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_ConvertClockTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_ConvertClockTimebase,
++			.src = (int[]){
++				NI_AI_SampleClockTimebase,
++				NI_20MHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AI_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AO_SampleClockTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				PXI_Clk10,
++				NI_20MHzTimebase,
++				NI_100kHzTimebase,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AI_StartTrigger,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DI_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DO_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_PFI(8),
++				NI_PFI(9),
++				NI_PFI(10),
++				NI_PFI(11),
++				NI_PFI(12),
++				NI_PFI(13),
++				NI_PFI(14),
++				NI_PFI(15),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_AI_SampleClock,
++				NI_AI_ConvertClock,
++				NI_AO_SampleClock,
++				NI_FrequencyOutput,
++				NI_ChangeDetectionEvent,
++				NI_AnalogComparisonEvent,
++				0, /* Termination */
++			}
++		},
++		{ /* Termination of list */
++			.dest = 0,
++		},
++	},
++};
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pxie-6535.c b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pxie-6535.c
+new file mode 100644
+index 000000000000..2ebb679e0129
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pxie-6535.c
+@@ -0,0 +1,575 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_device_routes/pxie-6535.c
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#include "../ni_device_routes.h"
++#include "all.h"
++
++struct ni_device_routes ni_pxie_6535_device_routes = {
++	.device = "pxie-6535",
++	.routes = (struct ni_route_set[]){
++		{
++			.dest = NI_PFI(0),
++			.src = (int[]){
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_InputBufferFull,
++				NI_DI_ReadyForStartEvent,
++				NI_DI_ReadyForTransferEventBurst,
++				NI_DI_ReadyForTransferEventPipelined,
++				NI_DO_StartTrigger,
++				NI_DO_OutputBufferFull,
++				NI_DO_DataActiveEvent,
++				NI_DO_ReadyForStartEvent,
++				NI_DO_ReadyForTransferEvent,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_InputBufferFull,
++				NI_DI_ReadyForStartEvent,
++				NI_DI_ReadyForTransferEventBurst,
++				NI_DI_ReadyForTransferEventPipelined,
++				NI_DO_StartTrigger,
++				NI_DO_OutputBufferFull,
++				NI_DO_DataActiveEvent,
++				NI_DO_ReadyForStartEvent,
++				NI_DO_ReadyForTransferEvent,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_InputBufferFull,
++				NI_DI_ReadyForStartEvent,
++				NI_DI_ReadyForTransferEventBurst,
++				NI_DI_ReadyForTransferEventPipelined,
++				NI_DO_StartTrigger,
++				NI_DO_OutputBufferFull,
++				NI_DO_DataActiveEvent,
++				NI_DO_ReadyForStartEvent,
++				NI_DO_ReadyForTransferEvent,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(4),
++				NI_PFI(5),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_InputBufferFull,
++				NI_DI_ReadyForStartEvent,
++				NI_DI_ReadyForTransferEventBurst,
++				NI_DI_ReadyForTransferEventPipelined,
++				NI_DO_StartTrigger,
++				NI_DO_OutputBufferFull,
++				NI_DO_DataActiveEvent,
++				NI_DO_ReadyForStartEvent,
++				NI_DO_ReadyForTransferEvent,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(4),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(5),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_InputBufferFull,
++				NI_DI_ReadyForStartEvent,
++				NI_DI_ReadyForTransferEventBurst,
++				NI_DI_ReadyForTransferEventPipelined,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_OutputBufferFull,
++				NI_DO_DataActiveEvent,
++				NI_DO_ReadyForStartEvent,
++				NI_DO_ReadyForTransferEvent,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(5),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_InputBufferFull,
++				NI_DI_ReadyForStartEvent,
++				NI_DI_ReadyForTransferEventBurst,
++				NI_DI_ReadyForTransferEventPipelined,
++				NI_DO_StartTrigger,
++				NI_DO_OutputBufferFull,
++				NI_DO_DataActiveEvent,
++				NI_DO_ReadyForStartEvent,
++				NI_DO_ReadyForTransferEvent,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_InputBufferFull,
++				NI_DI_ReadyForStartEvent,
++				NI_DI_ReadyForTransferEventBurst,
++				NI_DI_ReadyForTransferEventPipelined,
++				NI_DO_StartTrigger,
++				NI_DO_OutputBufferFull,
++				NI_DO_DataActiveEvent,
++				NI_DO_ReadyForStartEvent,
++				NI_DO_ReadyForTransferEvent,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_InputBufferFull,
++				NI_DI_ReadyForStartEvent,
++				NI_DI_ReadyForTransferEventBurst,
++				NI_DI_ReadyForTransferEventPipelined,
++				NI_DO_StartTrigger,
++				NI_DO_OutputBufferFull,
++				NI_DO_DataActiveEvent,
++				NI_DO_ReadyForStartEvent,
++				NI_DO_ReadyForTransferEvent,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_InputBufferFull,
++				NI_DI_ReadyForStartEvent,
++				NI_DI_ReadyForTransferEventBurst,
++				NI_DI_ReadyForTransferEventPipelined,
++				NI_DO_StartTrigger,
++				NI_DO_OutputBufferFull,
++				NI_DO_DataActiveEvent,
++				NI_DO_ReadyForStartEvent,
++				NI_DO_ReadyForTransferEvent,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_InputBufferFull,
++				NI_DI_ReadyForStartEvent,
++				NI_DI_ReadyForTransferEventBurst,
++				NI_DI_ReadyForTransferEventPipelined,
++				NI_DO_StartTrigger,
++				NI_DO_OutputBufferFull,
++				NI_DO_DataActiveEvent,
++				NI_DO_ReadyForStartEvent,
++				NI_DO_ReadyForTransferEvent,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(4),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_InputBufferFull,
++				NI_DI_ReadyForStartEvent,
++				NI_DI_ReadyForTransferEventBurst,
++				NI_DI_ReadyForTransferEventPipelined,
++				NI_DO_StartTrigger,
++				NI_DO_OutputBufferFull,
++				NI_DO_DataActiveEvent,
++				NI_DO_ReadyForStartEvent,
++				NI_DO_ReadyForTransferEvent,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(5),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(6),
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_InputBufferFull,
++				NI_DI_ReadyForStartEvent,
++				NI_DI_ReadyForTransferEventBurst,
++				NI_DI_ReadyForTransferEventPipelined,
++				NI_DO_StartTrigger,
++				NI_DO_OutputBufferFull,
++				NI_DO_DataActiveEvent,
++				NI_DO_ReadyForStartEvent,
++				NI_DO_ReadyForTransferEvent,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(6),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_InputBufferFull,
++				NI_DI_ReadyForStartEvent,
++				NI_DI_ReadyForTransferEventBurst,
++				NI_DI_ReadyForTransferEventPipelined,
++				NI_DO_StartTrigger,
++				NI_DO_OutputBufferFull,
++				NI_DO_DataActiveEvent,
++				NI_DO_ReadyForStartEvent,
++				NI_DO_ReadyForTransferEvent,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(7),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_InputBufferFull,
++				NI_DI_ReadyForStartEvent,
++				NI_DI_ReadyForTransferEventBurst,
++				NI_DI_ReadyForTransferEventPipelined,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_OutputBufferFull,
++				NI_DO_DataActiveEvent,
++				NI_DO_ReadyForStartEvent,
++				NI_DO_ReadyForTransferEvent,
++				NI_ChangeDetectionEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DI_SampleClock,
++			.src = (int[]){
++				NI_PFI(5),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DI_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DI_ReferenceTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DI_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DO_SampleClock,
++			.src = (int[]){
++				NI_PFI(4),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DO_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DO_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				0, /* Termination */
++			}
++		},
++		{ /* Termination of list */
++			.dest = 0,
++		},
++	},
++};
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pxie-6738.c b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pxie-6738.c
+new file mode 100644
+index 000000000000..d88504314d7f
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_device_routes/pxie-6738.c
+@@ -0,0 +1,3083 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_device_routes/pxie-6738.c
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#include "../ni_device_routes.h"
++#include "all.h"
++
++struct ni_device_routes ni_pxie_6738_device_routes = {
++	.device = "pxie-6738",
++	.routes = (struct ni_route_set[]){
++		{
++			.dest = NI_PFI(0),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(1),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(2),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(3),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(4),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(5),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(6),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_PFI(7),
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrZ(0),
++				NI_CtrZ(1),
++				NI_CtrZ(2),
++				NI_CtrZ(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrZ(0),
++				NI_CtrZ(1),
++				NI_CtrZ(2),
++				NI_CtrZ(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrZ(0),
++				NI_CtrZ(1),
++				NI_CtrZ(2),
++				NI_CtrZ(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrZ(0),
++				NI_CtrZ(1),
++				NI_CtrZ(2),
++				NI_CtrZ(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(4),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrZ(0),
++				NI_CtrZ(1),
++				NI_CtrZ(2),
++				NI_CtrZ(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(5),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrZ(0),
++				NI_CtrZ(1),
++				NI_CtrZ(2),
++				NI_CtrZ(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(6),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrZ(0),
++				NI_CtrZ(1),
++				NI_CtrZ(2),
++				NI_CtrZ(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = TRIGGER_LINE(7),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrZ(0),
++				NI_CtrZ(1),
++				NI_CtrZ(2),
++				NI_CtrZ(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				PXI_Clk10,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_20MHzTimebase,
++				NI_100MHzTimebase,
++				NI_100kHzTimebase,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				PXI_Clk10,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_20MHzTimebase,
++				NI_100MHzTimebase,
++				NI_100kHzTimebase,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(3),
++				PXI_Clk10,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_20MHzTimebase,
++				NI_100MHzTimebase,
++				NI_100kHzTimebase,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSource(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				PXI_Clk10,
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_20MHzTimebase,
++				NI_100MHzTimebase,
++				NI_100kHzTimebase,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrGate(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrAux(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrA(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrA(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrA(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrA(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrB(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrB(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrB(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrB(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrZ(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrZ(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrZ(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrZ(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrArmStartTrigger(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSampleClock(0),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSampleClock(1),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSampleClock(2),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_CtrSampleClock(3),
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClockTimebase,
++				NI_DI_SampleClock,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				PXI_Clk10,
++				NI_20MHzTimebase,
++				NI_100MHzTimebase,
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_AO_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DI_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DI_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				PXI_Clk10,
++				NI_DI_SampleClockTimebase,
++				NI_20MHzTimebase,
++				NI_100MHzTimebase,
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DI_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DI_ReferenceTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DI_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DO_SampleClock,
++				NI_DO_StartTrigger,
++				NI_DO_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DO_SampleClock,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_DO_SampleClockTimebase,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DO_SampleClockTimebase,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				PXI_Clk10,
++				NI_20MHzTimebase,
++				NI_100MHzTimebase,
++				NI_100kHzTimebase,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DO_StartTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_DO_PauseTrigger,
++			.src = (int[]){
++				NI_PFI(0),
++				NI_PFI(1),
++				NI_PFI(2),
++				NI_PFI(3),
++				NI_PFI(4),
++				NI_PFI(5),
++				NI_PFI(6),
++				NI_PFI(7),
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				NI_CtrSource(0),
++				NI_CtrSource(1),
++				NI_CtrSource(2),
++				NI_CtrSource(3),
++				NI_CtrGate(0),
++				NI_CtrGate(1),
++				NI_CtrGate(2),
++				NI_CtrGate(3),
++				NI_CtrArmStartTrigger(0),
++				NI_CtrArmStartTrigger(1),
++				NI_CtrArmStartTrigger(2),
++				NI_CtrArmStartTrigger(3),
++				NI_CtrInternalOutput(0),
++				NI_CtrInternalOutput(1),
++				NI_CtrInternalOutput(2),
++				NI_CtrInternalOutput(3),
++				NI_CtrSampleClock(0),
++				NI_CtrSampleClock(1),
++				NI_CtrSampleClock(2),
++				NI_CtrSampleClock(3),
++				NI_AO_SampleClock,
++				NI_AO_StartTrigger,
++				NI_AO_PauseTrigger,
++				NI_DI_SampleClock,
++				NI_DI_StartTrigger,
++				NI_DI_ReferenceTrigger,
++				NI_DI_PauseTrigger,
++				NI_10MHzRefClock,
++				NI_ChangeDetectionEvent,
++				NI_WatchdogExpiredEvent,
++				0, /* Termination */
++			}
++		},
++		{
++			.dest = NI_WatchdogExpirationTrigger,
++			.src = (int[]){
++				TRIGGER_LINE(0),
++				TRIGGER_LINE(1),
++				TRIGGER_LINE(2),
++				TRIGGER_LINE(3),
++				TRIGGER_LINE(4),
++				TRIGGER_LINE(5),
++				TRIGGER_LINE(6),
++				TRIGGER_LINE(7),
++				0, /* Termination */
++			}
++		},
++		{ /* Termination of list */
++			.dest = 0,
++		},
++	},
++};
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_route_values.c b/drivers/staging/comedi/drivers/ni_routing/ni_route_values.c
+new file mode 100644
+index 000000000000..5901762734ed
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_route_values.c
+@@ -0,0 +1,42 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_route_values.c
++ *  Route information for NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * This file includes the tables that are a list of all the values of various
++ * signals routes available on NI hardware.  In many cases, one does not
++ * explicitly make these routes, rather one might indicate that something is
++ * used as the source of one particular trigger or another (using
++ * *_src=TRIG_EXT).
++ *
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#include "ni_route_values.h"
++#include "ni_route_values/all.h"
++
++const struct family_route_values *const ni_all_route_values[] = {
++	&ni_660x_route_values,
++	&ni_eseries_route_values,
++	&ni_mseries_route_values,
++	NULL,
++};
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_route_values.h b/drivers/staging/comedi/drivers/ni_routing/ni_route_values.h
+new file mode 100644
+index 000000000000..80e0145fb82b
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_route_values.h
+@@ -0,0 +1,98 @@
++/* SPDX-License-Identifier: GPL-2.0+ */
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_route_values.h
++ *  Route information for NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++#ifndef _COMEDI_DRIVERS_NI_ROUTINT_NI_ROUTE_VALUES_H
++#define _COMEDI_DRIVERS_NI_ROUTINT_NI_ROUTE_VALUES_H
++
++#include "../../comedi.h"
++#include 
++
++/*
++ * This file includes the tables that are a list of all the values of various
++ * signals routes available on NI hardware.  In many cases, one does not
++ * explicitly make these routes, rather one might indicate that something is
++ * used as the source of one particular trigger or another (using
++ * *_src=TRIG_EXT).
++ *
++ * This file is meant to be included by comedi/drivers/ni_routes.c
++ */
++
++#define B(x)	((x) - NI_NAMES_BASE)
++
++/** Marks a register value as valid, implemented, and tested. */
++#define V(x)	(((x) & 0x7f) | 0x80)
++
++#ifndef NI_ROUTE_VALUE_EXTERNAL_CONVERSION
++	/** Marks a register value as implemented but needing testing. */
++	#define I(x)	V(x)
++	/** Marks a register value as not implemented. */
++	#define U(x)	0x0
++
++	typedef u8 register_type;
++#else
++	/** Marks a register value as implemented but needing testing. */
++	#define I(x)	(((x) & 0x7f) | 0x100)
++	/** Marks a register value as not implemented. */
++	#define U(x)	(((x) & 0x7f) | 0x200)
++
++	/** Tests whether a register is marked as valid/implemented/tested */
++	#define MARKED_V(x)	(((x) & 0x80) != 0)
++	/** Tests whether a register is implemented but not tested */
++	#define MARKED_I(x)	(((x) & 0x100) != 0)
++	/** Tests whether a register is not implemented */
++	#define MARKED_U(x)	(((x) & 0x200) != 0)
++
++	/* need more space to store extra marks */
++	typedef u16 register_type;
++#endif
++
++/* Mask out the marking bit(s). */
++#define UNMARK(x)	((x) & 0x7f)
++
++/*
++ * Gi_SRC(x,1) implements Gi_Src_SubSelect = 1
++ *
++ * This appears to only really be a valid MUX for m-series devices.
++ */
++#define Gi_SRC(val, subsel)	((val) | ((subsel) << 6))
++
++/**
++ * struct family_route_values - Register values for all routes for a particular
++ *				family.
++ * @family: lower-case string representation of a specific series or family of
++ *	    devices from National Instruments where each member of this family
++ *	    shares the same register values for the various signal MUXes.  It
++ *	    should be noted that not all devices of any family have access to
++ *	    all routes defined.
++ * @register_values: Table of all register values for various signal MUXes on
++ *	    National Instruments devices.  The first index of this table is the
++ *	    signal destination (i.e. identification of the signal MUX).  The
++ *	    second index of this table is the signal source (i.e. input of the
++ *	    signal MUX).
++ */
++struct family_route_values {
++	const char *family;
++	const register_type register_values[NI_NUM_NAMES][NI_NUM_NAMES];
++
++};
++
++extern const struct family_route_values *const ni_all_route_values[];
++
++#endif /* _COMEDI_DRIVERS_NI_ROUTINT_NI_ROUTE_VALUES_H */
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_route_values/all.h b/drivers/staging/comedi/drivers/ni_routing/ni_route_values/all.h
+new file mode 100644
+index 000000000000..7227461500b5
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_route_values/all.h
+@@ -0,0 +1,37 @@
++/* SPDX-License-Identifier: GPL-2.0+ */
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_route_values/all.h
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#ifndef _COMEDI_DRIVERS_NI_ROUTING_NI_ROUTE_VALUES_EXTERN_H
++#define _COMEDI_DRIVERS_NI_ROUTING_NI_ROUTE_VALUES_EXTERN_H
++
++#include "../ni_route_values.h"
++
++extern const struct family_route_values ni_660x_route_values;
++extern const struct family_route_values ni_eseries_route_values;
++extern const struct family_route_values ni_mseries_route_values;
++
++#endif //_COMEDI_DRIVERS_NI_ROUTING_NI_ROUTE_VALUES_EXTERN_H
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_route_values/ni_660x.c b/drivers/staging/comedi/drivers/ni_routing/ni_route_values/ni_660x.c
+new file mode 100644
+index 000000000000..f1c7e6646261
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_route_values/ni_660x.c
+@@ -0,0 +1,650 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_route_values/ni_660x.c
++ *  Route information for NI_660X boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * This file includes a list of all the values of various signals routes
++ * available on NI 660x hardware.  In many cases, one does not explicitly make
++ * these routes, rather one might indicate that something is used as the source
++ * of one particular trigger or another (using *_src=TRIG_EXT).
++ *
++ * The contents of this file can be generated using the tools in
++ * comedi/drivers/ni_routing/tools.  This file also contains specific notes to
++ * this family of devices.
++ *
++ * Please use those tools to help maintain the contents of this file, but be
++ * mindful to not lose the notes already made in this file, since these notes
++ * are critical to a complete undertsanding of the register values of this
++ * family.
++ */
++
++#include "../ni_route_values.h"
++#include "all.h"
++
++const struct family_route_values ni_660x_route_values = {
++	.family = "ni_660x",
++	.register_values = {
++		/*
++		 * destination = {
++		 *              source          = register value,
++		 *              ...
++		 * }
++		 */
++		[B(NI_PFI(8))] = {
++			[B(NI_CtrInternalOutput(7))]	= I(1),
++		},
++		[B(NI_PFI(10))] = {
++			[B(NI_CtrGate(7))]	= I(1),
++		},
++		[B(NI_PFI(11))] = {
++			[B(NI_CtrSource(7))]	= I(1),
++		},
++		[B(NI_PFI(12))] = {
++			[B(NI_CtrInternalOutput(6))]	= I(1),
++		},
++		[B(NI_PFI(14))] = {
++			[B(NI_CtrGate(6))]	= I(1),
++		},
++		[B(NI_PFI(15))] = {
++			[B(NI_CtrSource(6))]	= I(1),
++		},
++		[B(NI_PFI(16))] = {
++			[B(NI_CtrInternalOutput(5))]	= I(1),
++		},
++		[B(NI_PFI(18))] = {
++			[B(NI_CtrGate(5))]	= I(1),
++		},
++		[B(NI_PFI(19))] = {
++			[B(NI_CtrSource(5))]	= I(1),
++		},
++		[B(NI_PFI(20))] = {
++			[B(NI_CtrInternalOutput(4))]	= I(1),
++		},
++		[B(NI_PFI(22))] = {
++			[B(NI_CtrGate(4))]	= I(1),
++		},
++		[B(NI_PFI(23))] = {
++			[B(NI_CtrSource(4))]	= I(1),
++		},
++		[B(NI_PFI(24))] = {
++			[B(NI_CtrInternalOutput(3))]	= I(1),
++		},
++		[B(NI_PFI(26))] = {
++			[B(NI_CtrGate(3))]	= I(1),
++		},
++		[B(NI_PFI(27))] = {
++			[B(NI_CtrSource(3))]	= I(1),
++		},
++		[B(NI_PFI(28))] = {
++			[B(NI_CtrInternalOutput(2))]	= I(1),
++		},
++		[B(NI_PFI(30))] = {
++			[B(NI_CtrGate(2))]	= I(1),
++		},
++		[B(NI_PFI(31))] = {
++			[B(NI_CtrSource(2))]	= I(1),
++		},
++		[B(NI_PFI(32))] = {
++			[B(NI_CtrInternalOutput(1))]	= I(1),
++		},
++		[B(NI_PFI(34))] = {
++			[B(NI_CtrGate(1))]	= I(1),
++		},
++		[B(NI_PFI(35))] = {
++			[B(NI_CtrSource(1))]	= I(1),
++		},
++		[B(NI_PFI(36))] = {
++			[B(NI_CtrInternalOutput(0))]	= I(1),
++		},
++		[B(NI_PFI(38))] = {
++			[B(NI_CtrGate(0))]	= I(1),
++		},
++		[B(NI_PFI(39))] = {
++			[B(NI_CtrSource(0))]	= I(1),
++		},
++		[B(NI_CtrSource(0))] = {
++			/* These are not currently implemented in ni modules */
++			[B(NI_PFI(11))]	= U(9),
++			[B(NI_PFI(15))]	= U(8),
++			[B(NI_PFI(19))]	= U(7),
++			[B(NI_PFI(23))]	= U(6),
++			[B(NI_PFI(27))]	= U(5),
++			[B(NI_PFI(31))]	= U(4),
++			[B(NI_PFI(35))]	= U(3),
++			[B(NI_PFI(39))]	= U(2 /* or 1 */),
++			[B(TRIGGER_LINE(0))]	= U(11),
++			[B(TRIGGER_LINE(1))]	= U(12),
++			[B(TRIGGER_LINE(2))]	= U(13),
++			[B(TRIGGER_LINE(3))]	= U(14),
++			[B(TRIGGER_LINE(4))]	= U(15),
++			[B(TRIGGER_LINE(5))]	= U(16),
++			[B(TRIGGER_LINE(6))]	= U(17),
++			[B(NI_CtrGate(1))]	= U(10),
++			[B(NI_20MHzTimebase)]	= U(0),
++			[B(NI_80MHzTimebase)]	= U(30),
++			[B(NI_100kHzTimebase)]	= U(18),
++			[B(NI_LogicLow)]	= U(31),
++		},
++		[B(NI_CtrSource(1))] = {
++			/* These are not currently implemented in ni modules */
++			[B(NI_PFI(11))]	= U(9),
++			[B(NI_PFI(15))]	= U(8),
++			[B(NI_PFI(19))]	= U(7),
++			[B(NI_PFI(23))]	= U(6),
++			[B(NI_PFI(27))]	= U(5),
++			[B(NI_PFI(31))]	= U(4),
++			[B(NI_PFI(35))]	= U(3 /* or 1 */),
++			[B(NI_PFI(39))]	= U(2),
++			[B(TRIGGER_LINE(0))]	= U(11),
++			[B(TRIGGER_LINE(1))]	= U(12),
++			[B(TRIGGER_LINE(2))]	= U(13),
++			[B(TRIGGER_LINE(3))]	= U(14),
++			[B(TRIGGER_LINE(4))]	= U(15),
++			[B(TRIGGER_LINE(5))]	= U(16),
++			[B(TRIGGER_LINE(6))]	= U(17),
++			[B(NI_CtrGate(2))]	= U(10),
++			[B(NI_20MHzTimebase)]	= U(0),
++			[B(NI_80MHzTimebase)]	= U(30),
++			[B(NI_100kHzTimebase)]	= U(18),
++			[B(NI_LogicLow)]	= U(31),
++		},
++		[B(NI_CtrSource(2))] = {
++			/* These are not currently implemented in ni modules */
++			[B(NI_PFI(11))]	= U(9),
++			[B(NI_PFI(15))]	= U(8),
++			[B(NI_PFI(19))]	= U(7),
++			[B(NI_PFI(23))]	= U(6),
++			[B(NI_PFI(27))]	= U(5),
++			[B(NI_PFI(31))]	= U(4 /* or 1 */),
++			[B(NI_PFI(35))]	= U(3),
++			[B(NI_PFI(39))]	= U(2),
++			[B(TRIGGER_LINE(0))]	= U(11),
++			[B(TRIGGER_LINE(1))]	= U(12),
++			[B(TRIGGER_LINE(2))]	= U(13),
++			[B(TRIGGER_LINE(3))]	= U(14),
++			[B(TRIGGER_LINE(4))]	= U(15),
++			[B(TRIGGER_LINE(5))]	= U(16),
++			[B(TRIGGER_LINE(6))]	= U(17),
++			[B(NI_CtrGate(3))]	= U(10),
++			[B(NI_20MHzTimebase)]	= U(0),
++			[B(NI_80MHzTimebase)]	= U(30),
++			[B(NI_100kHzTimebase)]	= U(18),
++			[B(NI_LogicLow)]	= U(31),
++		},
++		[B(NI_CtrSource(3))] = {
++			/* These are not currently implemented in ni modules */
++			[B(NI_PFI(11))]	= U(9),
++			[B(NI_PFI(15))]	= U(8),
++			[B(NI_PFI(19))]	= U(7),
++			[B(NI_PFI(23))]	= U(6),
++			[B(NI_PFI(27))]	= U(5 /* or 1 */),
++			[B(NI_PFI(31))]	= U(4),
++			[B(NI_PFI(35))]	= U(3),
++			[B(NI_PFI(39))]	= U(2),
++			[B(TRIGGER_LINE(0))]	= U(11),
++			[B(TRIGGER_LINE(1))]	= U(12),
++			[B(TRIGGER_LINE(2))]	= U(13),
++			[B(TRIGGER_LINE(3))]	= U(14),
++			[B(TRIGGER_LINE(4))]	= U(15),
++			[B(TRIGGER_LINE(5))]	= U(16),
++			[B(TRIGGER_LINE(6))]	= U(17),
++			[B(NI_CtrGate(4))]	= U(10),
++			[B(NI_20MHzTimebase)]	= U(0),
++			[B(NI_80MHzTimebase)]	= U(30),
++			[B(NI_100kHzTimebase)]	= U(18),
++			[B(NI_LogicLow)]	= U(31),
++		},
++		[B(NI_CtrSource(4))] = {
++			/* These are not currently implemented in ni modules */
++			[B(NI_PFI(11))]	= U(9),
++			[B(NI_PFI(15))]	= U(8),
++			[B(NI_PFI(19))]	= U(7),
++			[B(NI_PFI(23))]	= U(6 /* or 1 */),
++			[B(NI_PFI(27))]	= U(5),
++			[B(NI_PFI(31))]	= U(4),
++			[B(NI_PFI(35))]	= U(3),
++			[B(NI_PFI(39))]	= U(2),
++			[B(TRIGGER_LINE(0))]	= U(11),
++			[B(TRIGGER_LINE(1))]	= U(12),
++			[B(TRIGGER_LINE(2))]	= U(13),
++			[B(TRIGGER_LINE(3))]	= U(14),
++			[B(TRIGGER_LINE(4))]	= U(15),
++			[B(TRIGGER_LINE(5))]	= U(16),
++			[B(TRIGGER_LINE(6))]	= U(17),
++			[B(NI_CtrGate(5))]	= U(10),
++			[B(NI_20MHzTimebase)]	= U(0),
++			[B(NI_80MHzTimebase)]	= U(30),
++			[B(NI_100kHzTimebase)]	= U(18),
++			[B(NI_LogicLow)]	= U(31),
++		},
++		[B(NI_CtrSource(5))] = {
++			/* These are not currently implemented in ni modules */
++			[B(NI_PFI(11))]	= U(9),
++			[B(NI_PFI(15))]	= U(8),
++			[B(NI_PFI(19))]	= U(7 /* or 1 */),
++			[B(NI_PFI(23))]	= U(6),
++			[B(NI_PFI(27))]	= U(5),
++			[B(NI_PFI(31))]	= U(4),
++			[B(NI_PFI(35))]	= U(3),
++			[B(NI_PFI(39))]	= U(2),
++			[B(TRIGGER_LINE(0))]	= U(11),
++			[B(TRIGGER_LINE(1))]	= U(12),
++			[B(TRIGGER_LINE(2))]	= U(13),
++			[B(TRIGGER_LINE(3))]	= U(14),
++			[B(TRIGGER_LINE(4))]	= U(15),
++			[B(TRIGGER_LINE(5))]	= U(16),
++			[B(TRIGGER_LINE(6))]	= U(17),
++			[B(NI_CtrGate(6))]	= U(10),
++			[B(NI_20MHzTimebase)]	= U(0),
++			[B(NI_80MHzTimebase)]	= U(30),
++			[B(NI_100kHzTimebase)]	= U(18),
++			[B(NI_LogicLow)]	= U(31),
++		},
++		[B(NI_CtrSource(6))] = {
++			/* These are not currently implemented in ni modules */
++			[B(NI_PFI(11))]	= U(9),
++			[B(NI_PFI(15))]	= U(8 /* or 1 */),
++			[B(NI_PFI(19))]	= U(7),
++			[B(NI_PFI(23))]	= U(6),
++			[B(NI_PFI(27))]	= U(5),
++			[B(NI_PFI(31))]	= U(4),
++			[B(NI_PFI(35))]	= U(3),
++			[B(NI_PFI(39))]	= U(2),
++			[B(TRIGGER_LINE(0))]	= U(11),
++			[B(TRIGGER_LINE(1))]	= U(12),
++			[B(TRIGGER_LINE(2))]	= U(13),
++			[B(TRIGGER_LINE(3))]	= U(14),
++			[B(TRIGGER_LINE(4))]	= U(15),
++			[B(TRIGGER_LINE(5))]	= U(16),
++			[B(TRIGGER_LINE(6))]	= U(17),
++			[B(NI_CtrGate(7))]	= U(10),
++			[B(NI_20MHzTimebase)]	= U(0),
++			[B(NI_80MHzTimebase)]	= U(30),
++			[B(NI_100kHzTimebase)]	= U(18),
++			[B(NI_LogicLow)]	= U(31),
++		},
++		[B(NI_CtrSource(7))] = {
++			/* These are not currently implemented in ni modules */
++			[B(NI_PFI(11))]	= U(9 /* or 1 */),
++			[B(NI_PFI(15))]	= U(8),
++			[B(NI_PFI(19))]	= U(7),
++			[B(NI_PFI(23))]	= U(6),
++			[B(NI_PFI(27))]	= U(5),
++			[B(NI_PFI(31))]	= U(4),
++			[B(NI_PFI(35))]	= U(3),
++			[B(NI_PFI(39))]	= U(2),
++			[B(TRIGGER_LINE(0))]	= U(11),
++			[B(TRIGGER_LINE(1))]	= U(12),
++			[B(TRIGGER_LINE(2))]	= U(13),
++			[B(TRIGGER_LINE(3))]	= U(14),
++			[B(TRIGGER_LINE(4))]	= U(15),
++			[B(TRIGGER_LINE(5))]	= U(16),
++			[B(TRIGGER_LINE(6))]	= U(17),
++			[B(NI_CtrGate(0))]	= U(10),
++			[B(NI_20MHzTimebase)]	= U(0),
++			[B(NI_80MHzTimebase)]	= U(30),
++			[B(NI_100kHzTimebase)]	= U(18),
++			[B(NI_LogicLow)]	= U(31),
++		},
++		[B(NI_CtrGate(0))] = {
++			[B(NI_PFI(10))]	= I(9),
++			[B(NI_PFI(14))]	= I(8),
++			[B(NI_PFI(18))]	= I(7),
++			[B(NI_PFI(22))]	= I(6),
++			[B(NI_PFI(26))]	= I(5),
++			[B(NI_PFI(30))]	= I(4),
++			[B(NI_PFI(34))]	= I(3),
++			[B(NI_PFI(38))]	= I(2 /* or 1 */),
++			[B(NI_PFI(39))]	= I(0),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(NI_CtrSource(1))]	= I(10),
++			[B(NI_CtrInternalOutput(1))]	= I(20),
++			[B(NI_LogicLow)]	= I(31 /* or 30 */),
++		},
++		[B(NI_CtrGate(1))] = {
++			[B(NI_PFI(10))]	= I(9),
++			[B(NI_PFI(14))]	= I(8),
++			[B(NI_PFI(18))]	= I(7),
++			[B(NI_PFI(22))]	= I(6),
++			[B(NI_PFI(26))]	= I(5),
++			[B(NI_PFI(30))]	= I(4),
++			[B(NI_PFI(34))]	= I(3 /* or 1 */),
++			[B(NI_PFI(35))]	= I(0),
++			[B(NI_PFI(38))]	= I(2),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(NI_CtrSource(2))]	= I(10),
++			[B(NI_CtrInternalOutput(2))]	= I(20),
++			[B(NI_LogicLow)]	= I(31 /* or 30 */),
++		},
++		[B(NI_CtrGate(2))] = {
++			[B(NI_PFI(10))]	= I(9),
++			[B(NI_PFI(14))]	= I(8),
++			[B(NI_PFI(18))]	= I(7),
++			[B(NI_PFI(22))]	= I(6),
++			[B(NI_PFI(26))]	= I(5),
++			[B(NI_PFI(30))]	= I(4 /* or 1 */),
++			[B(NI_PFI(31))]	= I(0),
++			[B(NI_PFI(34))]	= I(3),
++			[B(NI_PFI(38))]	= I(2),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(NI_CtrSource(3))]	= I(10),
++			[B(NI_CtrInternalOutput(3))]	= I(20),
++			[B(NI_LogicLow)]	= I(31 /* or 30 */),
++		},
++		[B(NI_CtrGate(3))] = {
++			[B(NI_PFI(10))]	= I(9),
++			[B(NI_PFI(14))]	= I(8),
++			[B(NI_PFI(18))]	= I(7),
++			[B(NI_PFI(22))]	= I(6),
++			[B(NI_PFI(26))]	= I(5 /* or 1 */),
++			[B(NI_PFI(27))]	= I(0),
++			[B(NI_PFI(30))]	= I(4),
++			[B(NI_PFI(34))]	= I(3),
++			[B(NI_PFI(38))]	= I(2),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(NI_CtrSource(4))]	= I(10),
++			[B(NI_CtrInternalOutput(4))]	= I(20),
++			[B(NI_LogicLow)]	= I(31 /* or 30 */),
++		},
++		[B(NI_CtrGate(4))] = {
++			[B(NI_PFI(10))]	= I(9),
++			[B(NI_PFI(14))]	= I(8),
++			[B(NI_PFI(18))]	= I(7),
++			[B(NI_PFI(22))]	= I(6 /* or 1 */),
++			[B(NI_PFI(23))]	= I(0),
++			[B(NI_PFI(26))]	= I(5),
++			[B(NI_PFI(30))]	= I(4),
++			[B(NI_PFI(34))]	= I(3),
++			[B(NI_PFI(38))]	= I(2),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(NI_CtrSource(5))]	= I(10),
++			[B(NI_CtrInternalOutput(5))]	= I(20),
++			[B(NI_LogicLow)]	= I(31 /* or 30 */),
++		},
++		[B(NI_CtrGate(5))] = {
++			[B(NI_PFI(10))]	= I(9),
++			[B(NI_PFI(14))]	= I(8),
++			[B(NI_PFI(18))]	= I(7 /* or 1 */),
++			[B(NI_PFI(19))]	= I(0),
++			[B(NI_PFI(22))]	= I(6),
++			[B(NI_PFI(26))]	= I(5),
++			[B(NI_PFI(30))]	= I(4),
++			[B(NI_PFI(34))]	= I(3),
++			[B(NI_PFI(38))]	= I(2),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(NI_CtrSource(6))]	= I(10),
++			[B(NI_CtrInternalOutput(6))]	= I(20),
++			[B(NI_LogicLow)]	= I(31 /* or 30 */),
++		},
++		[B(NI_CtrGate(6))] = {
++			[B(NI_PFI(10))]	= I(9),
++			[B(NI_PFI(14))]	= I(8 /* or 1 */),
++			[B(NI_PFI(15))]	= I(0),
++			[B(NI_PFI(18))]	= I(7),
++			[B(NI_PFI(22))]	= I(6),
++			[B(NI_PFI(26))]	= I(5),
++			[B(NI_PFI(30))]	= I(4),
++			[B(NI_PFI(34))]	= I(3),
++			[B(NI_PFI(38))]	= I(2),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(NI_CtrSource(7))]	= I(10),
++			[B(NI_CtrInternalOutput(7))]	= I(20),
++			[B(NI_LogicLow)]	= I(31 /* or 30 */),
++		},
++		[B(NI_CtrGate(7))] = {
++			[B(NI_PFI(10))]	= I(9 /* or 1 */),
++			[B(NI_PFI(11))]	= I(0),
++			[B(NI_PFI(14))]	= I(8),
++			[B(NI_PFI(18))]	= I(7),
++			[B(NI_PFI(22))]	= I(6),
++			[B(NI_PFI(26))]	= I(5),
++			[B(NI_PFI(30))]	= I(4),
++			[B(NI_PFI(34))]	= I(3),
++			[B(NI_PFI(38))]	= I(2),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(NI_CtrSource(0))]	= I(10),
++			[B(NI_CtrInternalOutput(0))]	= I(20),
++			[B(NI_LogicLow)]	= I(31 /* or 30 */),
++		},
++		[B(NI_CtrAux(0))] = {
++			[B(NI_PFI(9))]	= I(9),
++			[B(NI_PFI(13))]	= I(8),
++			[B(NI_PFI(17))]	= I(7),
++			[B(NI_PFI(21))]	= I(6),
++			[B(NI_PFI(25))]	= I(5),
++			[B(NI_PFI(29))]	= I(4),
++			[B(NI_PFI(33))]	= I(3),
++			[B(NI_PFI(37))]	= I(2 /* or 1 */),
++			[B(NI_PFI(39))]	= I(0),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(NI_CtrSource(1))]	= I(10),
++			[B(NI_CtrGate(1))]	= I(30),
++			[B(NI_CtrInternalOutput(1))]	= I(20),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_CtrAux(1))] = {
++			[B(NI_PFI(9))]	= I(9),
++			[B(NI_PFI(13))]	= I(8),
++			[B(NI_PFI(17))]	= I(7),
++			[B(NI_PFI(21))]	= I(6),
++			[B(NI_PFI(25))]	= I(5),
++			[B(NI_PFI(29))]	= I(4),
++			[B(NI_PFI(33))]	= I(3 /* or 1 */),
++			[B(NI_PFI(35))]	= I(0),
++			[B(NI_PFI(37))]	= I(2),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(NI_CtrSource(2))]	= I(10),
++			[B(NI_CtrGate(2))]	= I(30),
++			[B(NI_CtrInternalOutput(2))]	= I(20),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_CtrAux(2))] = {
++			[B(NI_PFI(9))]	= I(9),
++			[B(NI_PFI(13))]	= I(8),
++			[B(NI_PFI(17))]	= I(7),
++			[B(NI_PFI(21))]	= I(6),
++			[B(NI_PFI(25))]	= I(5),
++			[B(NI_PFI(29))]	= I(4 /* or 1 */),
++			[B(NI_PFI(31))]	= I(0),
++			[B(NI_PFI(33))]	= I(3),
++			[B(NI_PFI(37))]	= I(2),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(NI_CtrSource(3))]	= I(10),
++			[B(NI_CtrGate(3))]	= I(30),
++			[B(NI_CtrInternalOutput(3))]	= I(20),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_CtrAux(3))] = {
++			[B(NI_PFI(9))]	= I(9),
++			[B(NI_PFI(13))]	= I(8),
++			[B(NI_PFI(17))]	= I(7),
++			[B(NI_PFI(21))]	= I(6),
++			[B(NI_PFI(25))]	= I(5 /* or 1 */),
++			[B(NI_PFI(27))]	= I(0),
++			[B(NI_PFI(29))]	= I(4),
++			[B(NI_PFI(33))]	= I(3),
++			[B(NI_PFI(37))]	= I(2),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(NI_CtrSource(4))]	= I(10),
++			[B(NI_CtrGate(4))]	= I(30),
++			[B(NI_CtrInternalOutput(4))]	= I(20),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_CtrAux(4))] = {
++			[B(NI_PFI(9))]	= I(9),
++			[B(NI_PFI(13))]	= I(8),
++			[B(NI_PFI(17))]	= I(7),
++			[B(NI_PFI(21))]	= I(6 /* or 1 */),
++			[B(NI_PFI(23))]	= I(0),
++			[B(NI_PFI(25))]	= I(5),
++			[B(NI_PFI(29))]	= I(4),
++			[B(NI_PFI(33))]	= I(3),
++			[B(NI_PFI(37))]	= I(2),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(NI_CtrSource(5))]	= I(10),
++			[B(NI_CtrGate(5))]	= I(30),
++			[B(NI_CtrInternalOutput(5))]	= I(20),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_CtrAux(5))] = {
++			[B(NI_PFI(9))]	= I(9),
++			[B(NI_PFI(13))]	= I(8),
++			[B(NI_PFI(17))]	= I(7 /* or 1 */),
++			[B(NI_PFI(19))]	= I(0),
++			[B(NI_PFI(21))]	= I(6),
++			[B(NI_PFI(25))]	= I(5),
++			[B(NI_PFI(29))]	= I(4),
++			[B(NI_PFI(33))]	= I(3),
++			[B(NI_PFI(37))]	= I(2),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(NI_CtrSource(6))]	= I(10),
++			[B(NI_CtrGate(6))]	= I(30),
++			[B(NI_CtrInternalOutput(6))]	= I(20),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_CtrAux(6))] = {
++			[B(NI_PFI(9))]	= I(9),
++			[B(NI_PFI(13))]	= I(8 /* or 1 */),
++			[B(NI_PFI(15))]	= I(0),
++			[B(NI_PFI(17))]	= I(7),
++			[B(NI_PFI(21))]	= I(6),
++			[B(NI_PFI(25))]	= I(5),
++			[B(NI_PFI(29))]	= I(4),
++			[B(NI_PFI(33))]	= I(3),
++			[B(NI_PFI(37))]	= I(2),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(NI_CtrSource(7))]	= I(10),
++			[B(NI_CtrGate(7))]	= I(30),
++			[B(NI_CtrInternalOutput(7))]	= I(20),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_CtrAux(7))] = {
++			[B(NI_PFI(9))]	= I(9 /* or 1 */),
++			[B(NI_PFI(11))]	= I(0),
++			[B(NI_PFI(13))]	= I(8),
++			[B(NI_PFI(17))]	= I(7),
++			[B(NI_PFI(21))]	= I(6),
++			[B(NI_PFI(25))]	= I(5),
++			[B(NI_PFI(29))]	= I(4),
++			[B(NI_PFI(33))]	= I(3),
++			[B(NI_PFI(37))]	= I(2),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(NI_CtrSource(0))]	= I(10),
++			[B(NI_CtrGate(0))]	= I(30),
++			[B(NI_CtrInternalOutput(0))]	= I(20),
++			[B(NI_LogicLow)]	= I(31),
++		},
++	},
++};
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_route_values/ni_eseries.c b/drivers/staging/comedi/drivers/ni_routing/ni_route_values/ni_eseries.c
+new file mode 100644
+index 000000000000..d1ab3c9ce585
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_route_values/ni_eseries.c
+@@ -0,0 +1,602 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_route_values/ni_eseries.c
++ *  Route information for NI_ESERIES boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * This file includes a list of all the values of various signals routes
++ * available on NI 660x hardware.  In many cases, one does not explicitly make
++ * these routes, rather one might indicate that something is used as the source
++ * of one particular trigger or another (using *_src=TRIG_EXT).
++ *
++ * The contents of this file can be generated using the tools in
++ * comedi/drivers/ni_routing/tools.  This file also contains specific notes to
++ * this family of devices.
++ *
++ * Please use those tools to help maintain the contents of this file, but be
++ * mindful to not lose the notes already made in this file, since these notes
++ * are critical to a complete undertsanding of the register values of this
++ * family.
++ */
++
++#include "../ni_route_values.h"
++#include "all.h"
++
++/*
++ * Note that for e-series devices, the backplane TRIGGER_LINE(6) is generally
++ * not connected to RTSI(6).
++ */
++
++const struct family_route_values ni_eseries_route_values = {
++	.family = "ni_eseries",
++	.register_values = {
++		/*
++		 * destination = {
++		 *              source          = register value,
++		 *              ...
++		 * }
++		 */
++		[B(NI_PFI(0))] = {
++			[B(NI_AI_StartTrigger)]	= I(NI_PFI_OUTPUT_AI_START1),
++		},
++		[B(NI_PFI(1))] = {
++			[B(NI_AI_ReferenceTrigger)]	= I(NI_PFI_OUTPUT_AI_START2),
++		},
++		[B(NI_PFI(2))] = {
++			[B(NI_AI_ConvertClock)]	= I(NI_PFI_OUTPUT_AI_CONVERT),
++		},
++		[B(NI_PFI(3))] = {
++			[B(NI_CtrSource(1))]	= I(NI_PFI_OUTPUT_G_SRC1),
++		},
++		[B(NI_PFI(4))] = {
++			[B(NI_CtrGate(1))]	= I(NI_PFI_OUTPUT_G_GATE1),
++		},
++		[B(NI_PFI(5))] = {
++			[B(NI_AO_SampleClock)]	= I(NI_PFI_OUTPUT_AO_UPDATE_N),
++		},
++		[B(NI_PFI(6))] = {
++			[B(NI_AO_StartTrigger)]	= I(NI_PFI_OUTPUT_AO_START1),
++		},
++		[B(NI_PFI(7))] = {
++			[B(NI_AI_SampleClock)]	= I(NI_PFI_OUTPUT_AI_START_PULSE),
++		},
++		[B(NI_PFI(8))] = {
++			[B(NI_CtrSource(0))]	= I(NI_PFI_OUTPUT_G_SRC0),
++		},
++		[B(NI_PFI(9))] = {
++			[B(NI_CtrGate(0))]	= I(NI_PFI_OUTPUT_G_GATE0),
++		},
++		[B(TRIGGER_LINE(0))] = {
++			[B(NI_RTSI_BRD(0))]	= I(8),
++			[B(NI_RTSI_BRD(1))]	= I(9),
++			[B(NI_RTSI_BRD(2))]	= I(10),
++			[B(NI_RTSI_BRD(3))]	= I(11),
++			[B(NI_CtrSource(0))]	= I(5),
++			[B(NI_CtrGate(0))]	= I(6),
++			[B(NI_AI_StartTrigger)]	= I(0),
++			[B(NI_AI_ReferenceTrigger)]	= I(1),
++			[B(NI_AI_ConvertClock)]	= I(2),
++			[B(NI_AO_SampleClock)]	= I(3),
++			[B(NI_AO_StartTrigger)]	= I(4),
++			[B(NI_RGOUT0)]	= I(7),
++		},
++		[B(TRIGGER_LINE(1))] = {
++			[B(NI_RTSI_BRD(0))]	= I(8),
++			[B(NI_RTSI_BRD(1))]	= I(9),
++			[B(NI_RTSI_BRD(2))]	= I(10),
++			[B(NI_RTSI_BRD(3))]	= I(11),
++			[B(NI_CtrSource(0))]	= I(5),
++			[B(NI_CtrGate(0))]	= I(6),
++			[B(NI_AI_StartTrigger)]	= I(0),
++			[B(NI_AI_ReferenceTrigger)]	= I(1),
++			[B(NI_AI_ConvertClock)]	= I(2),
++			[B(NI_AO_SampleClock)]	= I(3),
++			[B(NI_AO_StartTrigger)]	= I(4),
++			[B(NI_RGOUT0)]	= I(7),
++		},
++		[B(TRIGGER_LINE(2))] = {
++			[B(NI_RTSI_BRD(0))]	= I(8),
++			[B(NI_RTSI_BRD(1))]	= I(9),
++			[B(NI_RTSI_BRD(2))]	= I(10),
++			[B(NI_RTSI_BRD(3))]	= I(11),
++			[B(NI_CtrSource(0))]	= I(5),
++			[B(NI_CtrGate(0))]	= I(6),
++			[B(NI_AI_StartTrigger)]	= I(0),
++			[B(NI_AI_ReferenceTrigger)]	= I(1),
++			[B(NI_AI_ConvertClock)]	= I(2),
++			[B(NI_AO_SampleClock)]	= I(3),
++			[B(NI_AO_StartTrigger)]	= I(4),
++			[B(NI_RGOUT0)]	= I(7),
++		},
++		[B(TRIGGER_LINE(3))] = {
++			[B(NI_RTSI_BRD(0))]	= I(8),
++			[B(NI_RTSI_BRD(1))]	= I(9),
++			[B(NI_RTSI_BRD(2))]	= I(10),
++			[B(NI_RTSI_BRD(3))]	= I(11),
++			[B(NI_CtrSource(0))]	= I(5),
++			[B(NI_CtrGate(0))]	= I(6),
++			[B(NI_AI_StartTrigger)]	= I(0),
++			[B(NI_AI_ReferenceTrigger)]	= I(1),
++			[B(NI_AI_ConvertClock)]	= I(2),
++			[B(NI_AO_SampleClock)]	= I(3),
++			[B(NI_AO_StartTrigger)]	= I(4),
++			[B(NI_RGOUT0)]	= I(7),
++		},
++		[B(TRIGGER_LINE(4))] = {
++			[B(NI_RTSI_BRD(0))]	= I(8),
++			[B(NI_RTSI_BRD(1))]	= I(9),
++			[B(NI_RTSI_BRD(2))]	= I(10),
++			[B(NI_RTSI_BRD(3))]	= I(11),
++			[B(NI_CtrSource(0))]	= I(5),
++			[B(NI_CtrGate(0))]	= I(6),
++			[B(NI_AI_StartTrigger)]	= I(0),
++			[B(NI_AI_ReferenceTrigger)]	= I(1),
++			[B(NI_AI_ConvertClock)]	= I(2),
++			[B(NI_AO_SampleClock)]	= I(3),
++			[B(NI_AO_StartTrigger)]	= I(4),
++			[B(NI_RGOUT0)]	= I(7),
++		},
++		[B(TRIGGER_LINE(5))] = {
++			[B(NI_RTSI_BRD(0))]	= I(8),
++			[B(NI_RTSI_BRD(1))]	= I(9),
++			[B(NI_RTSI_BRD(2))]	= I(10),
++			[B(NI_RTSI_BRD(3))]	= I(11),
++			[B(NI_CtrSource(0))]	= I(5),
++			[B(NI_CtrGate(0))]	= I(6),
++			[B(NI_AI_StartTrigger)]	= I(0),
++			[B(NI_AI_ReferenceTrigger)]	= I(1),
++			[B(NI_AI_ConvertClock)]	= I(2),
++			[B(NI_AO_SampleClock)]	= I(3),
++			[B(NI_AO_StartTrigger)]	= I(4),
++			[B(NI_RGOUT0)]	= I(7),
++		},
++		[B(TRIGGER_LINE(6))] = {
++			[B(NI_RTSI_BRD(0))]	= I(8),
++			[B(NI_RTSI_BRD(1))]	= I(9),
++			[B(NI_RTSI_BRD(2))]	= I(10),
++			[B(NI_RTSI_BRD(3))]	= I(11),
++			[B(NI_CtrSource(0))]	= I(5),
++			[B(NI_CtrGate(0))]	= I(6),
++			[B(NI_AI_StartTrigger)]	= I(0),
++			[B(NI_AI_ReferenceTrigger)]	= I(1),
++			[B(NI_AI_ConvertClock)]	= I(2),
++			[B(NI_AO_SampleClock)]	= I(3),
++			[B(NI_AO_StartTrigger)]	= I(4),
++			[B(NI_RGOUT0)]	= I(7),
++		},
++		[B(TRIGGER_LINE(7))] = {
++			[B(NI_20MHzTimebase)]	= I(NI_RTSI_OUTPUT_RTSI_OSC),
++		},
++		[B(NI_RTSI_BRD(0))] = {
++			[B(TRIGGER_LINE(0))]	= I(0),
++			[B(TRIGGER_LINE(1))]	= I(1),
++			[B(TRIGGER_LINE(2))]	= I(2),
++			[B(TRIGGER_LINE(3))]	= I(3),
++			[B(TRIGGER_LINE(4))]	= I(4),
++			[B(TRIGGER_LINE(5))]	= I(5),
++			[B(TRIGGER_LINE(6))]	= I(6),
++			[B(PXI_Star)]	= I(6),
++			[B(NI_AI_STOP)]	= I(7),
++		},
++		[B(NI_RTSI_BRD(1))] = {
++			[B(TRIGGER_LINE(0))]	= I(0),
++			[B(TRIGGER_LINE(1))]	= I(1),
++			[B(TRIGGER_LINE(2))]	= I(2),
++			[B(TRIGGER_LINE(3))]	= I(3),
++			[B(TRIGGER_LINE(4))]	= I(4),
++			[B(TRIGGER_LINE(5))]	= I(5),
++			[B(TRIGGER_LINE(6))]	= I(6),
++			[B(PXI_Star)]	= I(6),
++			[B(NI_AI_STOP)]	= I(7),
++		},
++		[B(NI_RTSI_BRD(2))] = {
++			[B(TRIGGER_LINE(0))]	= I(0),
++			[B(TRIGGER_LINE(1))]	= I(1),
++			[B(TRIGGER_LINE(2))]	= I(2),
++			[B(TRIGGER_LINE(3))]	= I(3),
++			[B(TRIGGER_LINE(4))]	= I(4),
++			[B(TRIGGER_LINE(5))]	= I(5),
++			[B(TRIGGER_LINE(6))]	= I(6),
++			[B(PXI_Star)]	= I(6),
++			[B(NI_AI_SampleClock)]	= I(7),
++		},
++		[B(NI_RTSI_BRD(3))] = {
++			[B(TRIGGER_LINE(0))]	= I(0),
++			[B(TRIGGER_LINE(1))]	= I(1),
++			[B(TRIGGER_LINE(2))]	= I(2),
++			[B(TRIGGER_LINE(3))]	= I(3),
++			[B(TRIGGER_LINE(4))]	= I(4),
++			[B(TRIGGER_LINE(5))]	= I(5),
++			[B(TRIGGER_LINE(6))]	= I(6),
++			[B(PXI_Star)]	= I(6),
++			[B(NI_AI_SampleClock)]	= I(7),
++		},
++		[B(NI_CtrSource(0))] = {
++			/* These are not currently implemented in ni modules */
++			[B(NI_PFI(0))]	= U(1),
++			[B(NI_PFI(1))]	= U(2),
++			[B(NI_PFI(2))]	= U(3),
++			[B(NI_PFI(3))]	= U(4),
++			[B(NI_PFI(4))]	= U(5),
++			[B(NI_PFI(5))]	= U(6),
++			[B(NI_PFI(6))]	= U(7),
++			[B(NI_PFI(7))]	= U(8),
++			[B(NI_PFI(8))]	= U(9),
++			[B(NI_PFI(9))]	= U(10),
++			[B(TRIGGER_LINE(0))]	= U(11),
++			[B(TRIGGER_LINE(1))]	= U(12),
++			[B(TRIGGER_LINE(2))]	= U(13),
++			[B(TRIGGER_LINE(3))]	= U(14),
++			[B(TRIGGER_LINE(4))]	= U(15),
++			[B(TRIGGER_LINE(5))]	= U(16),
++			[B(TRIGGER_LINE(6))]	= U(17),
++			[B(NI_CtrInternalOutput(1))]	= U(19),
++			[B(PXI_Star)]	= U(17),
++			[B(NI_20MHzTimebase)]	= U(0),
++			[B(NI_100kHzTimebase)]	= U(18),
++			[B(NI_LogicLow)]	= U(31),
++		},
++		[B(NI_CtrSource(1))] = {
++			/* These are not currently implemented in ni modules */
++			[B(NI_PFI(0))]	= U(1),
++			[B(NI_PFI(1))]	= U(2),
++			[B(NI_PFI(2))]	= U(3),
++			[B(NI_PFI(3))]	= U(4),
++			[B(NI_PFI(4))]	= U(5),
++			[B(NI_PFI(5))]	= U(6),
++			[B(NI_PFI(6))]	= U(7),
++			[B(NI_PFI(7))]	= U(8),
++			[B(NI_PFI(8))]	= U(9),
++			[B(NI_PFI(9))]	= U(10),
++			[B(TRIGGER_LINE(0))]	= U(11),
++			[B(TRIGGER_LINE(1))]	= U(12),
++			[B(TRIGGER_LINE(2))]	= U(13),
++			[B(TRIGGER_LINE(3))]	= U(14),
++			[B(TRIGGER_LINE(4))]	= U(15),
++			[B(TRIGGER_LINE(5))]	= U(16),
++			[B(TRIGGER_LINE(6))]	= U(17),
++			[B(NI_CtrInternalOutput(0))]	= U(19),
++			[B(PXI_Star)]	= U(17),
++			[B(NI_20MHzTimebase)]	= U(0),
++			[B(NI_100kHzTimebase)]	= U(18),
++			[B(NI_LogicLow)]	= U(31),
++		},
++		[B(NI_CtrGate(0))] = {
++			[B(NI_PFI(0))]	= I(1),
++			[B(NI_PFI(1))]	= I(2),
++			[B(NI_PFI(2))]	= I(3),
++			[B(NI_PFI(3))]	= I(4),
++			[B(NI_PFI(4))]	= I(5),
++			[B(NI_PFI(5))]	= I(6),
++			[B(NI_PFI(6))]	= I(7),
++			[B(NI_PFI(7))]	= I(8),
++			[B(NI_PFI(8))]	= I(9),
++			[B(NI_PFI(9))]	= I(10),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(NI_CtrInternalOutput(1))]	= I(20),
++			[B(PXI_Star)]	= I(17),
++			[B(NI_AI_StartTrigger)]	= I(21),
++			[B(NI_AI_ReferenceTrigger)]	= I(18),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_CtrGate(1))] = {
++			[B(NI_PFI(0))]	= I(1),
++			[B(NI_PFI(1))]	= I(2),
++			[B(NI_PFI(2))]	= I(3),
++			[B(NI_PFI(3))]	= I(4),
++			[B(NI_PFI(4))]	= I(5),
++			[B(NI_PFI(5))]	= I(6),
++			[B(NI_PFI(6))]	= I(7),
++			[B(NI_PFI(7))]	= I(8),
++			[B(NI_PFI(8))]	= I(9),
++			[B(NI_PFI(9))]	= I(10),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(NI_CtrInternalOutput(0))]	= I(20),
++			[B(PXI_Star)]	= I(17),
++			[B(NI_AI_StartTrigger)]	= I(21),
++			[B(NI_AI_ReferenceTrigger)]	= I(18),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_CtrOut(0))] = {
++			[B(TRIGGER_LINE(0))]	= I(1),
++			[B(TRIGGER_LINE(1))]	= I(2),
++			[B(TRIGGER_LINE(2))]	= I(3),
++			[B(TRIGGER_LINE(3))]	= I(4),
++			[B(TRIGGER_LINE(4))]	= I(5),
++			[B(TRIGGER_LINE(5))]	= I(6),
++			[B(TRIGGER_LINE(6))]	= I(7),
++			[B(NI_CtrInternalOutput(0))]	= I(0),
++			[B(PXI_Star)]	= I(7),
++		},
++		[B(NI_CtrOut(1))] = {
++			[B(NI_CtrInternalOutput(1))]	= I(0),
++		},
++		[B(NI_AI_SampleClock)] = {
++			[B(NI_PFI(0))]	= I(1),
++			[B(NI_PFI(1))]	= I(2),
++			[B(NI_PFI(2))]	= I(3),
++			[B(NI_PFI(3))]	= I(4),
++			[B(NI_PFI(4))]	= I(5),
++			[B(NI_PFI(5))]	= I(6),
++			[B(NI_PFI(6))]	= I(7),
++			[B(NI_PFI(7))]	= I(8),
++			[B(NI_PFI(8))]	= I(9),
++			[B(NI_PFI(9))]	= I(10),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(NI_CtrInternalOutput(0))]	= I(19),
++			[B(PXI_Star)]	= I(17),
++			[B(NI_AI_SampleClockTimebase)]	= I(0),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_AI_SampleClockTimebase)] = {
++			/* These are not currently implemented in ni modules */
++			[B(NI_PFI(0))]	= U(1),
++			[B(NI_PFI(1))]	= U(2),
++			[B(NI_PFI(2))]	= U(3),
++			[B(NI_PFI(3))]	= U(4),
++			[B(NI_PFI(4))]	= U(5),
++			[B(NI_PFI(5))]	= U(6),
++			[B(NI_PFI(6))]	= U(7),
++			[B(NI_PFI(7))]	= U(8),
++			[B(NI_PFI(8))]	= U(9),
++			[B(NI_PFI(9))]	= U(10),
++			[B(TRIGGER_LINE(0))]	= U(11),
++			[B(TRIGGER_LINE(1))]	= U(12),
++			[B(TRIGGER_LINE(2))]	= U(13),
++			[B(TRIGGER_LINE(3))]	= U(14),
++			[B(TRIGGER_LINE(4))]	= U(15),
++			[B(TRIGGER_LINE(5))]	= U(16),
++			[B(TRIGGER_LINE(6))]	= U(17),
++			[B(PXI_Star)]	= U(17),
++			[B(NI_20MHzTimebase)]	= U(0),
++			[B(NI_100kHzTimebase)]	= U(19),
++			[B(NI_LogicLow)]	= U(31),
++		},
++		[B(NI_AI_StartTrigger)] = {
++			[B(NI_PFI(0))]	= I(1),
++			[B(NI_PFI(1))]	= I(2),
++			[B(NI_PFI(2))]	= I(3),
++			[B(NI_PFI(3))]	= I(4),
++			[B(NI_PFI(4))]	= I(5),
++			[B(NI_PFI(5))]	= I(6),
++			[B(NI_PFI(6))]	= I(7),
++			[B(NI_PFI(7))]	= I(8),
++			[B(NI_PFI(8))]	= I(9),
++			[B(NI_PFI(9))]	= I(10),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(NI_CtrInternalOutput(0))]	= I(18),
++			[B(PXI_Star)]	= I(17),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_AI_ReferenceTrigger)] = {
++			/* These are not currently implemented in ni modules */
++			[B(NI_PFI(0))]	= U(1),
++			[B(NI_PFI(1))]	= U(2),
++			[B(NI_PFI(2))]	= U(3),
++			[B(NI_PFI(3))]	= U(4),
++			[B(NI_PFI(4))]	= U(5),
++			[B(NI_PFI(5))]	= U(6),
++			[B(NI_PFI(6))]	= U(7),
++			[B(NI_PFI(7))]	= U(8),
++			[B(NI_PFI(8))]	= U(9),
++			[B(NI_PFI(9))]	= U(10),
++			[B(TRIGGER_LINE(0))]	= U(11),
++			[B(TRIGGER_LINE(1))]	= U(12),
++			[B(TRIGGER_LINE(2))]	= U(13),
++			[B(TRIGGER_LINE(3))]	= U(14),
++			[B(TRIGGER_LINE(4))]	= U(15),
++			[B(TRIGGER_LINE(5))]	= U(16),
++			[B(TRIGGER_LINE(6))]	= U(17),
++			[B(PXI_Star)]	= U(17),
++			[B(NI_LogicLow)]	= U(31),
++		},
++		[B(NI_AI_ConvertClock)] = {
++			[B(NI_PFI(0))]	= I(1),
++			[B(NI_PFI(1))]	= I(2),
++			[B(NI_PFI(2))]	= I(3),
++			[B(NI_PFI(3))]	= I(4),
++			[B(NI_PFI(4))]	= I(5),
++			[B(NI_PFI(5))]	= I(6),
++			[B(NI_PFI(6))]	= I(7),
++			[B(NI_PFI(7))]	= I(8),
++			[B(NI_PFI(8))]	= I(9),
++			[B(NI_PFI(9))]	= I(10),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(NI_CtrInternalOutput(0))]	= I(19),
++			[B(PXI_Star)]	= I(17),
++			[B(NI_AI_ConvertClockTimebase)]	= I(0),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_AI_ConvertClockTimebase)] = {
++			/* These are not currently implemented in ni modules */
++			[B(NI_AI_SampleClockTimebase)]	= U(0),
++			[B(NI_20MHzTimebase)]	= U(1),
++		},
++		[B(NI_AI_PauseTrigger)] = {
++			/* These are not currently implemented in ni modules */
++			[B(NI_PFI(0))]	= U(1),
++			[B(NI_PFI(1))]	= U(2),
++			[B(NI_PFI(2))]	= U(3),
++			[B(NI_PFI(3))]	= U(4),
++			[B(NI_PFI(4))]	= U(5),
++			[B(NI_PFI(5))]	= U(6),
++			[B(NI_PFI(6))]	= U(7),
++			[B(NI_PFI(7))]	= U(8),
++			[B(NI_PFI(8))]	= U(9),
++			[B(NI_PFI(9))]	= U(10),
++			[B(TRIGGER_LINE(0))]	= U(11),
++			[B(TRIGGER_LINE(1))]	= U(12),
++			[B(TRIGGER_LINE(2))]	= U(13),
++			[B(TRIGGER_LINE(3))]	= U(14),
++			[B(TRIGGER_LINE(4))]	= U(15),
++			[B(TRIGGER_LINE(5))]	= U(16),
++			[B(TRIGGER_LINE(6))]	= U(17),
++			[B(PXI_Star)]	= U(17),
++			[B(NI_LogicLow)]	= U(31),
++		},
++		[B(NI_AO_SampleClock)] = {
++			[B(NI_PFI(0))]	= I(1),
++			[B(NI_PFI(1))]	= I(2),
++			[B(NI_PFI(2))]	= I(3),
++			[B(NI_PFI(3))]	= I(4),
++			[B(NI_PFI(4))]	= I(5),
++			[B(NI_PFI(5))]	= I(6),
++			[B(NI_PFI(6))]	= I(7),
++			[B(NI_PFI(7))]	= I(8),
++			[B(NI_PFI(8))]	= I(9),
++			[B(NI_PFI(9))]	= I(10),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(NI_CtrInternalOutput(1))]	= I(19),
++			[B(PXI_Star)]	= I(17),
++			[B(NI_AO_SampleClockTimebase)]	= I(0),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_AO_SampleClockTimebase)] = {
++			/* These are not currently implemented in ni modules */
++			[B(NI_PFI(0))]	= U(1),
++			[B(NI_PFI(1))]	= U(2),
++			[B(NI_PFI(2))]	= U(3),
++			[B(NI_PFI(3))]	= U(4),
++			[B(NI_PFI(4))]	= U(5),
++			[B(NI_PFI(5))]	= U(6),
++			[B(NI_PFI(6))]	= U(7),
++			[B(NI_PFI(7))]	= U(8),
++			[B(NI_PFI(8))]	= U(9),
++			[B(NI_PFI(9))]	= U(10),
++			[B(TRIGGER_LINE(0))]	= U(11),
++			[B(TRIGGER_LINE(1))]	= U(12),
++			[B(TRIGGER_LINE(2))]	= U(13),
++			[B(TRIGGER_LINE(3))]	= U(14),
++			[B(TRIGGER_LINE(4))]	= U(15),
++			[B(TRIGGER_LINE(5))]	= U(16),
++			[B(TRIGGER_LINE(6))]	= U(17),
++			[B(PXI_Star)]	= U(17),
++			[B(NI_20MHzTimebase)]	= U(0),
++			[B(NI_100kHzTimebase)]	= U(19),
++			[B(NI_LogicLow)]	= U(31),
++		},
++		[B(NI_AO_StartTrigger)] = {
++			[B(NI_PFI(0))]	= I(1),
++			[B(NI_PFI(1))]	= I(2),
++			[B(NI_PFI(2))]	= I(3),
++			[B(NI_PFI(3))]	= I(4),
++			[B(NI_PFI(4))]	= I(5),
++			[B(NI_PFI(5))]	= I(6),
++			[B(NI_PFI(6))]	= I(7),
++			[B(NI_PFI(7))]	= I(8),
++			[B(NI_PFI(8))]	= I(9),
++			[B(NI_PFI(9))]	= I(10),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(PXI_Star)]	= I(17),
++			/*
++			 * for the signal route
++			 * (NI_AI_StartTrigger->NI_AO_StartTrigger), MHDDK says
++			 * used register value 18 and DAQ-STC says 19.
++			 * Hoping that the MHDDK is correct--being a "working"
++			 * example.
++			 */
++			[B(NI_AI_StartTrigger)]	= I(18),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_AO_PauseTrigger)] = {
++			/* These are not currently implemented in ni modules */
++			[B(NI_PFI(0))]	= U(1),
++			[B(NI_PFI(1))]	= U(2),
++			[B(NI_PFI(2))]	= U(3),
++			[B(NI_PFI(3))]	= U(4),
++			[B(NI_PFI(4))]	= U(5),
++			[B(NI_PFI(5))]	= U(6),
++			[B(NI_PFI(6))]	= U(7),
++			[B(NI_PFI(7))]	= U(8),
++			[B(NI_PFI(8))]	= U(9),
++			[B(NI_PFI(9))]	= U(10),
++			[B(TRIGGER_LINE(0))]	= U(11),
++			[B(TRIGGER_LINE(1))]	= U(12),
++			[B(TRIGGER_LINE(2))]	= U(13),
++			[B(TRIGGER_LINE(3))]	= U(14),
++			[B(TRIGGER_LINE(4))]	= U(15),
++			[B(TRIGGER_LINE(5))]	= U(16),
++			[B(TRIGGER_LINE(6))]	= U(17),
++			[B(PXI_Star)]	= U(17),
++			[B(NI_LogicLow)]	= U(31),
++		},
++		[B(NI_MasterTimebase)] = {
++			/* These are not currently implemented in ni modules */
++			[B(TRIGGER_LINE(7))]	= U(1),
++			[B(PXI_Star)]	= U(2),
++			[B(PXI_Clk10)]	= U(3),
++			[B(NI_10MHzRefClock)]	= U(0),
++		},
++		/*
++		 * This symbol is not defined and nothing for this is
++		 * implemented--just including this because data was found in
++		 * the NI-STC for it--can't remember where.
++		 * [B(NI_FrequencyOutTimebase)] = {
++		 *	** These are not currently implemented in ni modules **
++		 *	[B(NI_20MHzTimebase)]	= U(0),
++		 *	[B(NI_100kHzTimebase)]	= U(1),
++		 * },
++		 */
++		[B(NI_RGOUT0)] = {
++			[B(NI_CtrInternalOutput(0))]	= I(0),
++			[B(NI_CtrOut(0))]	= I(1),
++		},
++	},
++};
+diff --git a/drivers/staging/comedi/drivers/ni_routing/ni_route_values/ni_mseries.c b/drivers/staging/comedi/drivers/ni_routing/ni_route_values/ni_mseries.c
+new file mode 100644
+index 000000000000..c59d8afe0ae9
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/ni_route_values/ni_mseries.c
+@@ -0,0 +1,1752 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/ni_route_values/ni_mseries.c
++ *  Route information for NI_MSERIES boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * This file includes a list of all the values of various signals routes
++ * available on NI 660x hardware.  In many cases, one does not explicitly make
++ * these routes, rather one might indicate that something is used as the source
++ * of one particular trigger or another (using *_src=TRIG_EXT).
++ *
++ * The contents of this file can be generated using the tools in
++ * comedi/drivers/ni_routing/tools.  This file also contains specific notes to
++ * this family of devices.
++ *
++ * Please use those tools to help maintain the contents of this file, but be
++ * mindful to not lose the notes already made in this file, since these notes
++ * are critical to a complete undertsanding of the register values of this
++ * family.
++ */
++
++#include "../ni_route_values.h"
++#include "all.h"
++
++/*
++ * GATE SELECT NOTE:
++ * CtrAux and CtrArmStartrigger register values are not documented in the
++ * DAQ-STC.  There is some evidence that using CtrGate values is valid (see
++ * comedi.h).  Some information and hints exist in the M-Series user manual
++ * (ni-62xx user-manual 371022K-01).
++ */
++
++const struct family_route_values ni_mseries_route_values = {
++	.family = "ni_mseries",
++	.register_values = {
++		/*
++		 * destination = {
++		 *              source          = register value,
++		 *              ...
++		 * }
++		 */
++		[B(NI_PFI(0))] = {
++			[B(TRIGGER_LINE(0))]	= I(18),
++			[B(TRIGGER_LINE(1))]	= I(19),
++			[B(TRIGGER_LINE(2))]	= I(20),
++			[B(TRIGGER_LINE(3))]	= I(21),
++			[B(TRIGGER_LINE(4))]	= I(22),
++			[B(TRIGGER_LINE(5))]	= I(23),
++			[B(TRIGGER_LINE(6))]	= I(24),
++			[B(TRIGGER_LINE(7))]	= I(25),
++			[B(NI_CtrSource(0))]	= I(9),
++			[B(NI_CtrSource(1))]	= I(4),
++			[B(NI_CtrGate(0))]	= I(10),
++			[B(NI_CtrGate(1))]	= I(5),
++			[B(NI_CtrInternalOutput(0))]	= I(13),
++			[B(NI_CtrInternalOutput(1))]	= I(14),
++			[B(PXI_Star)]	= I(26),
++			[B(NI_AI_SampleClock)]	= I(8),
++			[B(NI_AI_StartTrigger)]	= I(1),
++			[B(NI_AI_ReferenceTrigger)]	= I(2),
++			[B(NI_AI_ConvertClock)]	= I(3),
++			[B(NI_AI_ExternalMUXClock)]	= I(12),
++			[B(NI_AO_SampleClock)]	= I(6),
++			[B(NI_AO_StartTrigger)]	= I(7),
++			[B(NI_DI_SampleClock)]	= I(29),
++			[B(NI_DO_SampleClock)]	= I(30),
++			[B(NI_FrequencyOutput)]	= I(15),
++			[B(NI_ChangeDetectionEvent)]	= I(28),
++			[B(NI_AnalogComparisonEvent)]	= I(17),
++			[B(NI_SCXI_Trig1)]	= I(27),
++			[B(NI_ExternalStrobe)]	= I(11),
++			[B(NI_PFI_DO)]	= I(16),
++		},
++		[B(NI_PFI(1))] = {
++			[B(TRIGGER_LINE(0))]	= I(18),
++			[B(TRIGGER_LINE(1))]	= I(19),
++			[B(TRIGGER_LINE(2))]	= I(20),
++			[B(TRIGGER_LINE(3))]	= I(21),
++			[B(TRIGGER_LINE(4))]	= I(22),
++			[B(TRIGGER_LINE(5))]	= I(23),
++			[B(TRIGGER_LINE(6))]	= I(24),
++			[B(TRIGGER_LINE(7))]	= I(25),
++			[B(NI_CtrSource(0))]	= I(9),
++			[B(NI_CtrSource(1))]	= I(4),
++			[B(NI_CtrGate(0))]	= I(10),
++			[B(NI_CtrGate(1))]	= I(5),
++			[B(NI_CtrInternalOutput(0))]	= I(13),
++			[B(NI_CtrInternalOutput(1))]	= I(14),
++			[B(PXI_Star)]	= I(26),
++			[B(NI_AI_SampleClock)]	= I(8),
++			[B(NI_AI_StartTrigger)]	= I(1),
++			[B(NI_AI_ReferenceTrigger)]	= I(2),
++			[B(NI_AI_ConvertClock)]	= I(3),
++			[B(NI_AI_ExternalMUXClock)]	= I(12),
++			[B(NI_AO_SampleClock)]	= I(6),
++			[B(NI_AO_StartTrigger)]	= I(7),
++			[B(NI_DI_SampleClock)]	= I(29),
++			[B(NI_DO_SampleClock)]	= I(30),
++			[B(NI_FrequencyOutput)]	= I(15),
++			[B(NI_ChangeDetectionEvent)]	= I(28),
++			[B(NI_AnalogComparisonEvent)]	= I(17),
++			[B(NI_SCXI_Trig1)]	= I(27),
++			[B(NI_ExternalStrobe)]	= I(11),
++			[B(NI_PFI_DO)]	= I(16),
++		},
++		[B(NI_PFI(2))] = {
++			[B(TRIGGER_LINE(0))]	= I(18),
++			[B(TRIGGER_LINE(1))]	= I(19),
++			[B(TRIGGER_LINE(2))]	= I(20),
++			[B(TRIGGER_LINE(3))]	= I(21),
++			[B(TRIGGER_LINE(4))]	= I(22),
++			[B(TRIGGER_LINE(5))]	= I(23),
++			[B(TRIGGER_LINE(6))]	= I(24),
++			[B(TRIGGER_LINE(7))]	= I(25),
++			[B(NI_CtrSource(0))]	= I(9),
++			[B(NI_CtrSource(1))]	= I(4),
++			[B(NI_CtrGate(0))]	= I(10),
++			[B(NI_CtrGate(1))]	= I(5),
++			[B(NI_CtrInternalOutput(0))]	= I(13),
++			[B(NI_CtrInternalOutput(1))]	= I(14),
++			[B(PXI_Star)]	= I(26),
++			[B(NI_AI_SampleClock)]	= I(8),
++			[B(NI_AI_StartTrigger)]	= I(1),
++			[B(NI_AI_ReferenceTrigger)]	= I(2),
++			[B(NI_AI_ConvertClock)]	= I(3),
++			[B(NI_AI_ExternalMUXClock)]	= I(12),
++			[B(NI_AO_SampleClock)]	= I(6),
++			[B(NI_AO_StartTrigger)]	= I(7),
++			[B(NI_DI_SampleClock)]	= I(29),
++			[B(NI_DO_SampleClock)]	= I(30),
++			[B(NI_FrequencyOutput)]	= I(15),
++			[B(NI_ChangeDetectionEvent)]	= I(28),
++			[B(NI_AnalogComparisonEvent)]	= I(17),
++			[B(NI_SCXI_Trig1)]	= I(27),
++			[B(NI_ExternalStrobe)]	= I(11),
++			[B(NI_PFI_DO)]	= I(16),
++		},
++		[B(NI_PFI(3))] = {
++			[B(TRIGGER_LINE(0))]	= I(18),
++			[B(TRIGGER_LINE(1))]	= I(19),
++			[B(TRIGGER_LINE(2))]	= I(20),
++			[B(TRIGGER_LINE(3))]	= I(21),
++			[B(TRIGGER_LINE(4))]	= I(22),
++			[B(TRIGGER_LINE(5))]	= I(23),
++			[B(TRIGGER_LINE(6))]	= I(24),
++			[B(TRIGGER_LINE(7))]	= I(25),
++			[B(NI_CtrSource(0))]	= I(9),
++			[B(NI_CtrSource(1))]	= I(4),
++			[B(NI_CtrGate(0))]	= I(10),
++			[B(NI_CtrGate(1))]	= I(5),
++			[B(NI_CtrInternalOutput(0))]	= I(13),
++			[B(NI_CtrInternalOutput(1))]	= I(14),
++			[B(PXI_Star)]	= I(26),
++			[B(NI_AI_SampleClock)]	= I(8),
++			[B(NI_AI_StartTrigger)]	= I(1),
++			[B(NI_AI_ReferenceTrigger)]	= I(2),
++			[B(NI_AI_ConvertClock)]	= I(3),
++			[B(NI_AI_ExternalMUXClock)]	= I(12),
++			[B(NI_AO_SampleClock)]	= I(6),
++			[B(NI_AO_StartTrigger)]	= I(7),
++			[B(NI_DI_SampleClock)]	= I(29),
++			[B(NI_DO_SampleClock)]	= I(30),
++			[B(NI_FrequencyOutput)]	= I(15),
++			[B(NI_ChangeDetectionEvent)]	= I(28),
++			[B(NI_AnalogComparisonEvent)]	= I(17),
++			[B(NI_SCXI_Trig1)]	= I(27),
++			[B(NI_ExternalStrobe)]	= I(11),
++			[B(NI_PFI_DO)]	= I(16),
++		},
++		[B(NI_PFI(4))] = {
++			[B(TRIGGER_LINE(0))]	= I(18),
++			[B(TRIGGER_LINE(1))]	= I(19),
++			[B(TRIGGER_LINE(2))]	= I(20),
++			[B(TRIGGER_LINE(3))]	= I(21),
++			[B(TRIGGER_LINE(4))]	= I(22),
++			[B(TRIGGER_LINE(5))]	= I(23),
++			[B(TRIGGER_LINE(6))]	= I(24),
++			[B(TRIGGER_LINE(7))]	= I(25),
++			[B(NI_CtrSource(0))]	= I(9),
++			[B(NI_CtrSource(1))]	= I(4),
++			[B(NI_CtrGate(0))]	= I(10),
++			[B(NI_CtrGate(1))]	= I(5),
++			[B(NI_CtrInternalOutput(0))]	= I(13),
++			[B(NI_CtrInternalOutput(1))]	= I(14),
++			[B(PXI_Star)]	= I(26),
++			[B(NI_AI_SampleClock)]	= I(8),
++			[B(NI_AI_StartTrigger)]	= I(1),
++			[B(NI_AI_ReferenceTrigger)]	= I(2),
++			[B(NI_AI_ConvertClock)]	= I(3),
++			[B(NI_AI_ExternalMUXClock)]	= I(12),
++			[B(NI_AO_SampleClock)]	= I(6),
++			[B(NI_AO_StartTrigger)]	= I(7),
++			[B(NI_DI_SampleClock)]	= I(29),
++			[B(NI_DO_SampleClock)]	= I(30),
++			[B(NI_FrequencyOutput)]	= I(15),
++			[B(NI_ChangeDetectionEvent)]	= I(28),
++			[B(NI_AnalogComparisonEvent)]	= I(17),
++			[B(NI_SCXI_Trig1)]	= I(27),
++			[B(NI_ExternalStrobe)]	= I(11),
++			[B(NI_PFI_DO)]	= I(16),
++		},
++		[B(NI_PFI(5))] = {
++			[B(TRIGGER_LINE(0))]	= I(18),
++			[B(TRIGGER_LINE(1))]	= I(19),
++			[B(TRIGGER_LINE(2))]	= I(20),
++			[B(TRIGGER_LINE(3))]	= I(21),
++			[B(TRIGGER_LINE(4))]	= I(22),
++			[B(TRIGGER_LINE(5))]	= I(23),
++			[B(TRIGGER_LINE(6))]	= I(24),
++			[B(TRIGGER_LINE(7))]	= I(25),
++			[B(NI_CtrSource(0))]	= I(9),
++			[B(NI_CtrSource(1))]	= I(4),
++			[B(NI_CtrGate(0))]	= I(10),
++			[B(NI_CtrGate(1))]	= I(5),
++			[B(NI_CtrInternalOutput(0))]	= I(13),
++			[B(NI_CtrInternalOutput(1))]	= I(14),
++			[B(PXI_Star)]	= I(26),
++			[B(NI_AI_SampleClock)]	= I(8),
++			[B(NI_AI_StartTrigger)]	= I(1),
++			[B(NI_AI_ReferenceTrigger)]	= I(2),
++			[B(NI_AI_ConvertClock)]	= I(3),
++			[B(NI_AI_ExternalMUXClock)]	= I(12),
++			[B(NI_AO_SampleClock)]	= I(6),
++			[B(NI_AO_StartTrigger)]	= I(7),
++			[B(NI_DI_SampleClock)]	= I(29),
++			[B(NI_DO_SampleClock)]	= I(30),
++			[B(NI_FrequencyOutput)]	= I(15),
++			[B(NI_ChangeDetectionEvent)]	= I(28),
++			[B(NI_AnalogComparisonEvent)]	= I(17),
++			[B(NI_SCXI_Trig1)]	= I(27),
++			[B(NI_ExternalStrobe)]	= I(11),
++			[B(NI_PFI_DO)]	= I(16),
++		},
++		[B(NI_PFI(6))] = {
++			[B(TRIGGER_LINE(0))]	= I(18),
++			[B(TRIGGER_LINE(1))]	= I(19),
++			[B(TRIGGER_LINE(2))]	= I(20),
++			[B(TRIGGER_LINE(3))]	= I(21),
++			[B(TRIGGER_LINE(4))]	= I(22),
++			[B(TRIGGER_LINE(5))]	= I(23),
++			[B(TRIGGER_LINE(6))]	= I(24),
++			[B(TRIGGER_LINE(7))]	= I(25),
++			[B(NI_CtrSource(0))]	= I(9),
++			[B(NI_CtrSource(1))]	= I(4),
++			[B(NI_CtrGate(0))]	= I(10),
++			[B(NI_CtrGate(1))]	= I(5),
++			[B(NI_CtrInternalOutput(0))]	= I(13),
++			[B(NI_CtrInternalOutput(1))]	= I(14),
++			[B(PXI_Star)]	= I(26),
++			[B(NI_AI_SampleClock)]	= I(8),
++			[B(NI_AI_StartTrigger)]	= I(1),
++			[B(NI_AI_ReferenceTrigger)]	= I(2),
++			[B(NI_AI_ConvertClock)]	= I(3),
++			[B(NI_AI_ExternalMUXClock)]	= I(12),
++			[B(NI_AO_SampleClock)]	= I(6),
++			[B(NI_AO_StartTrigger)]	= I(7),
++			[B(NI_DI_SampleClock)]	= I(29),
++			[B(NI_DO_SampleClock)]	= I(30),
++			[B(NI_FrequencyOutput)]	= I(15),
++			[B(NI_ChangeDetectionEvent)]	= I(28),
++			[B(NI_AnalogComparisonEvent)]	= I(17),
++			[B(NI_SCXI_Trig1)]	= I(27),
++			[B(NI_ExternalStrobe)]	= I(11),
++			[B(NI_PFI_DO)]	= I(16),
++		},
++		[B(NI_PFI(7))] = {
++			[B(TRIGGER_LINE(0))]	= I(18),
++			[B(TRIGGER_LINE(1))]	= I(19),
++			[B(TRIGGER_LINE(2))]	= I(20),
++			[B(TRIGGER_LINE(3))]	= I(21),
++			[B(TRIGGER_LINE(4))]	= I(22),
++			[B(TRIGGER_LINE(5))]	= I(23),
++			[B(TRIGGER_LINE(6))]	= I(24),
++			[B(TRIGGER_LINE(7))]	= I(25),
++			[B(NI_CtrSource(0))]	= I(9),
++			[B(NI_CtrSource(1))]	= I(4),
++			[B(NI_CtrGate(0))]	= I(10),
++			[B(NI_CtrGate(1))]	= I(5),
++			[B(NI_CtrInternalOutput(0))]	= I(13),
++			[B(NI_CtrInternalOutput(1))]	= I(14),
++			[B(PXI_Star)]	= I(26),
++			[B(NI_AI_SampleClock)]	= I(8),
++			[B(NI_AI_StartTrigger)]	= I(1),
++			[B(NI_AI_ReferenceTrigger)]	= I(2),
++			[B(NI_AI_ConvertClock)]	= I(3),
++			[B(NI_AI_ExternalMUXClock)]	= I(12),
++			[B(NI_AO_SampleClock)]	= I(6),
++			[B(NI_AO_StartTrigger)]	= I(7),
++			[B(NI_DI_SampleClock)]	= I(29),
++			[B(NI_DO_SampleClock)]	= I(30),
++			[B(NI_FrequencyOutput)]	= I(15),
++			[B(NI_ChangeDetectionEvent)]	= I(28),
++			[B(NI_AnalogComparisonEvent)]	= I(17),
++			[B(NI_SCXI_Trig1)]	= I(27),
++			[B(NI_ExternalStrobe)]	= I(11),
++			[B(NI_PFI_DO)]	= I(16),
++		},
++		[B(NI_PFI(8))] = {
++			[B(TRIGGER_LINE(0))]	= I(18),
++			[B(TRIGGER_LINE(1))]	= I(19),
++			[B(TRIGGER_LINE(2))]	= I(20),
++			[B(TRIGGER_LINE(3))]	= I(21),
++			[B(TRIGGER_LINE(4))]	= I(22),
++			[B(TRIGGER_LINE(5))]	= I(23),
++			[B(TRIGGER_LINE(6))]	= I(24),
++			[B(TRIGGER_LINE(7))]	= I(25),
++			[B(NI_CtrSource(0))]	= I(9),
++			[B(NI_CtrSource(1))]	= I(4),
++			[B(NI_CtrGate(0))]	= I(10),
++			[B(NI_CtrGate(1))]	= I(5),
++			[B(NI_CtrInternalOutput(0))]	= I(13),
++			[B(NI_CtrInternalOutput(1))]	= I(14),
++			[B(PXI_Star)]	= I(26),
++			[B(NI_AI_SampleClock)]	= I(8),
++			[B(NI_AI_StartTrigger)]	= I(1),
++			[B(NI_AI_ReferenceTrigger)]	= I(2),
++			[B(NI_AI_ConvertClock)]	= I(3),
++			[B(NI_AI_ExternalMUXClock)]	= I(12),
++			[B(NI_AO_SampleClock)]	= I(6),
++			[B(NI_AO_StartTrigger)]	= I(7),
++			[B(NI_DI_SampleClock)]	= I(29),
++			[B(NI_DO_SampleClock)]	= I(30),
++			[B(NI_FrequencyOutput)]	= I(15),
++			[B(NI_ChangeDetectionEvent)]	= I(28),
++			[B(NI_AnalogComparisonEvent)]	= I(17),
++			[B(NI_SCXI_Trig1)]	= I(27),
++			[B(NI_ExternalStrobe)]	= I(11),
++			[B(NI_PFI_DO)]	= I(16),
++		},
++		[B(NI_PFI(9))] = {
++			[B(TRIGGER_LINE(0))]	= I(18),
++			[B(TRIGGER_LINE(1))]	= I(19),
++			[B(TRIGGER_LINE(2))]	= I(20),
++			[B(TRIGGER_LINE(3))]	= I(21),
++			[B(TRIGGER_LINE(4))]	= I(22),
++			[B(TRIGGER_LINE(5))]	= I(23),
++			[B(TRIGGER_LINE(6))]	= I(24),
++			[B(TRIGGER_LINE(7))]	= I(25),
++			[B(NI_CtrSource(0))]	= I(9),
++			[B(NI_CtrSource(1))]	= I(4),
++			[B(NI_CtrGate(0))]	= I(10),
++			[B(NI_CtrGate(1))]	= I(5),
++			[B(NI_CtrInternalOutput(0))]	= I(13),
++			[B(NI_CtrInternalOutput(1))]	= I(14),
++			[B(PXI_Star)]	= I(26),
++			[B(NI_AI_SampleClock)]	= I(8),
++			[B(NI_AI_StartTrigger)]	= I(1),
++			[B(NI_AI_ReferenceTrigger)]	= I(2),
++			[B(NI_AI_ConvertClock)]	= I(3),
++			[B(NI_AI_ExternalMUXClock)]	= I(12),
++			[B(NI_AO_SampleClock)]	= I(6),
++			[B(NI_AO_StartTrigger)]	= I(7),
++			[B(NI_DI_SampleClock)]	= I(29),
++			[B(NI_DO_SampleClock)]	= I(30),
++			[B(NI_FrequencyOutput)]	= I(15),
++			[B(NI_ChangeDetectionEvent)]	= I(28),
++			[B(NI_AnalogComparisonEvent)]	= I(17),
++			[B(NI_SCXI_Trig1)]	= I(27),
++			[B(NI_ExternalStrobe)]	= I(11),
++			[B(NI_PFI_DO)]	= I(16),
++		},
++		[B(NI_PFI(10))] = {
++			[B(TRIGGER_LINE(0))]	= I(18),
++			[B(TRIGGER_LINE(1))]	= I(19),
++			[B(TRIGGER_LINE(2))]	= I(20),
++			[B(TRIGGER_LINE(3))]	= I(21),
++			[B(TRIGGER_LINE(4))]	= I(22),
++			[B(TRIGGER_LINE(5))]	= I(23),
++			[B(TRIGGER_LINE(6))]	= I(24),
++			[B(TRIGGER_LINE(7))]	= I(25),
++			[B(NI_CtrSource(0))]	= I(9),
++			[B(NI_CtrSource(1))]	= I(4),
++			[B(NI_CtrGate(0))]	= I(10),
++			[B(NI_CtrGate(1))]	= I(5),
++			[B(NI_CtrInternalOutput(0))]	= I(13),
++			[B(NI_CtrInternalOutput(1))]	= I(14),
++			[B(PXI_Star)]	= I(26),
++			[B(NI_AI_SampleClock)]	= I(8),
++			[B(NI_AI_StartTrigger)]	= I(1),
++			[B(NI_AI_ReferenceTrigger)]	= I(2),
++			[B(NI_AI_ConvertClock)]	= I(3),
++			[B(NI_AI_ExternalMUXClock)]	= I(12),
++			[B(NI_AO_SampleClock)]	= I(6),
++			[B(NI_AO_StartTrigger)]	= I(7),
++			[B(NI_DI_SampleClock)]	= I(29),
++			[B(NI_DO_SampleClock)]	= I(30),
++			[B(NI_FrequencyOutput)]	= I(15),
++			[B(NI_ChangeDetectionEvent)]	= I(28),
++			[B(NI_AnalogComparisonEvent)]	= I(17),
++			[B(NI_SCXI_Trig1)]	= I(27),
++			[B(NI_ExternalStrobe)]	= I(11),
++			[B(NI_PFI_DO)]	= I(16),
++		},
++		[B(NI_PFI(11))] = {
++			[B(TRIGGER_LINE(0))]	= I(18),
++			[B(TRIGGER_LINE(1))]	= I(19),
++			[B(TRIGGER_LINE(2))]	= I(20),
++			[B(TRIGGER_LINE(3))]	= I(21),
++			[B(TRIGGER_LINE(4))]	= I(22),
++			[B(TRIGGER_LINE(5))]	= I(23),
++			[B(TRIGGER_LINE(6))]	= I(24),
++			[B(TRIGGER_LINE(7))]	= I(25),
++			[B(NI_CtrSource(0))]	= I(9),
++			[B(NI_CtrSource(1))]	= I(4),
++			[B(NI_CtrGate(0))]	= I(10),
++			[B(NI_CtrGate(1))]	= I(5),
++			[B(NI_CtrInternalOutput(0))]	= I(13),
++			[B(NI_CtrInternalOutput(1))]	= I(14),
++			[B(PXI_Star)]	= I(26),
++			[B(NI_AI_SampleClock)]	= I(8),
++			[B(NI_AI_StartTrigger)]	= I(1),
++			[B(NI_AI_ReferenceTrigger)]	= I(2),
++			[B(NI_AI_ConvertClock)]	= I(3),
++			[B(NI_AI_ExternalMUXClock)]	= I(12),
++			[B(NI_AO_SampleClock)]	= I(6),
++			[B(NI_AO_StartTrigger)]	= I(7),
++			[B(NI_DI_SampleClock)]	= I(29),
++			[B(NI_DO_SampleClock)]	= I(30),
++			[B(NI_FrequencyOutput)]	= I(15),
++			[B(NI_ChangeDetectionEvent)]	= I(28),
++			[B(NI_AnalogComparisonEvent)]	= I(17),
++			[B(NI_SCXI_Trig1)]	= I(27),
++			[B(NI_ExternalStrobe)]	= I(11),
++			[B(NI_PFI_DO)]	= I(16),
++		},
++		[B(NI_PFI(12))] = {
++			[B(TRIGGER_LINE(0))]	= I(18),
++			[B(TRIGGER_LINE(1))]	= I(19),
++			[B(TRIGGER_LINE(2))]	= I(20),
++			[B(TRIGGER_LINE(3))]	= I(21),
++			[B(TRIGGER_LINE(4))]	= I(22),
++			[B(TRIGGER_LINE(5))]	= I(23),
++			[B(TRIGGER_LINE(6))]	= I(24),
++			[B(TRIGGER_LINE(7))]	= I(25),
++			[B(NI_CtrSource(0))]	= I(9),
++			[B(NI_CtrSource(1))]	= I(4),
++			[B(NI_CtrGate(0))]	= I(10),
++			[B(NI_CtrGate(1))]	= I(5),
++			[B(NI_CtrInternalOutput(0))]	= I(13),
++			[B(NI_CtrInternalOutput(1))]	= I(14),
++			[B(PXI_Star)]	= I(26),
++			[B(NI_AI_SampleClock)]	= I(8),
++			[B(NI_AI_StartTrigger)]	= I(1),
++			[B(NI_AI_ReferenceTrigger)]	= I(2),
++			[B(NI_AI_ConvertClock)]	= I(3),
++			[B(NI_AI_ExternalMUXClock)]	= I(12),
++			[B(NI_AO_SampleClock)]	= I(6),
++			[B(NI_AO_StartTrigger)]	= I(7),
++			[B(NI_DI_SampleClock)]	= I(29),
++			[B(NI_DO_SampleClock)]	= I(30),
++			[B(NI_FrequencyOutput)]	= I(15),
++			[B(NI_ChangeDetectionEvent)]	= I(28),
++			[B(NI_AnalogComparisonEvent)]	= I(17),
++			[B(NI_SCXI_Trig1)]	= I(27),
++			[B(NI_ExternalStrobe)]	= I(11),
++			[B(NI_PFI_DO)]	= I(16),
++		},
++		[B(NI_PFI(13))] = {
++			[B(TRIGGER_LINE(0))]	= I(18),
++			[B(TRIGGER_LINE(1))]	= I(19),
++			[B(TRIGGER_LINE(2))]	= I(20),
++			[B(TRIGGER_LINE(3))]	= I(21),
++			[B(TRIGGER_LINE(4))]	= I(22),
++			[B(TRIGGER_LINE(5))]	= I(23),
++			[B(TRIGGER_LINE(6))]	= I(24),
++			[B(TRIGGER_LINE(7))]	= I(25),
++			[B(NI_CtrSource(0))]	= I(9),
++			[B(NI_CtrSource(1))]	= I(4),
++			[B(NI_CtrGate(0))]	= I(10),
++			[B(NI_CtrGate(1))]	= I(5),
++			[B(NI_CtrInternalOutput(0))]	= I(13),
++			[B(NI_CtrInternalOutput(1))]	= I(14),
++			[B(PXI_Star)]	= I(26),
++			[B(NI_AI_SampleClock)]	= I(8),
++			[B(NI_AI_StartTrigger)]	= I(1),
++			[B(NI_AI_ReferenceTrigger)]	= I(2),
++			[B(NI_AI_ConvertClock)]	= I(3),
++			[B(NI_AI_ExternalMUXClock)]	= I(12),
++			[B(NI_AO_SampleClock)]	= I(6),
++			[B(NI_AO_StartTrigger)]	= I(7),
++			[B(NI_DI_SampleClock)]	= I(29),
++			[B(NI_DO_SampleClock)]	= I(30),
++			[B(NI_FrequencyOutput)]	= I(15),
++			[B(NI_ChangeDetectionEvent)]	= I(28),
++			[B(NI_AnalogComparisonEvent)]	= I(17),
++			[B(NI_SCXI_Trig1)]	= I(27),
++			[B(NI_ExternalStrobe)]	= I(11),
++			[B(NI_PFI_DO)]	= I(16),
++		},
++		[B(NI_PFI(14))] = {
++			[B(TRIGGER_LINE(0))]	= I(18),
++			[B(TRIGGER_LINE(1))]	= I(19),
++			[B(TRIGGER_LINE(2))]	= I(20),
++			[B(TRIGGER_LINE(3))]	= I(21),
++			[B(TRIGGER_LINE(4))]	= I(22),
++			[B(TRIGGER_LINE(5))]	= I(23),
++			[B(TRIGGER_LINE(6))]	= I(24),
++			[B(TRIGGER_LINE(7))]	= I(25),
++			[B(NI_CtrSource(0))]	= I(9),
++			[B(NI_CtrSource(1))]	= I(4),
++			[B(NI_CtrGate(0))]	= I(10),
++			[B(NI_CtrGate(1))]	= I(5),
++			[B(NI_CtrInternalOutput(0))]	= I(13),
++			[B(NI_CtrInternalOutput(1))]	= I(14),
++			[B(PXI_Star)]	= I(26),
++			[B(NI_AI_SampleClock)]	= I(8),
++			[B(NI_AI_StartTrigger)]	= I(1),
++			[B(NI_AI_ReferenceTrigger)]	= I(2),
++			[B(NI_AI_ConvertClock)]	= I(3),
++			[B(NI_AI_ExternalMUXClock)]	= I(12),
++			[B(NI_AO_SampleClock)]	= I(6),
++			[B(NI_AO_StartTrigger)]	= I(7),
++			[B(NI_DI_SampleClock)]	= I(29),
++			[B(NI_DO_SampleClock)]	= I(30),
++			[B(NI_FrequencyOutput)]	= I(15),
++			[B(NI_ChangeDetectionEvent)]	= I(28),
++			[B(NI_AnalogComparisonEvent)]	= I(17),
++			[B(NI_SCXI_Trig1)]	= I(27),
++			[B(NI_ExternalStrobe)]	= I(11),
++			[B(NI_PFI_DO)]	= I(16),
++		},
++		[B(NI_PFI(15))] = {
++			[B(TRIGGER_LINE(0))]	= I(18),
++			[B(TRIGGER_LINE(1))]	= I(19),
++			[B(TRIGGER_LINE(2))]	= I(20),
++			[B(TRIGGER_LINE(3))]	= I(21),
++			[B(TRIGGER_LINE(4))]	= I(22),
++			[B(TRIGGER_LINE(5))]	= I(23),
++			[B(TRIGGER_LINE(6))]	= I(24),
++			[B(TRIGGER_LINE(7))]	= I(25),
++			[B(NI_CtrSource(0))]	= I(9),
++			[B(NI_CtrSource(1))]	= I(4),
++			[B(NI_CtrGate(0))]	= I(10),
++			[B(NI_CtrGate(1))]	= I(5),
++			[B(NI_CtrInternalOutput(0))]	= I(13),
++			[B(NI_CtrInternalOutput(1))]	= I(14),
++			[B(PXI_Star)]	= I(26),
++			[B(NI_AI_SampleClock)]	= I(8),
++			[B(NI_AI_StartTrigger)]	= I(1),
++			[B(NI_AI_ReferenceTrigger)]	= I(2),
++			[B(NI_AI_ConvertClock)]	= I(3),
++			[B(NI_AI_ExternalMUXClock)]	= I(12),
++			[B(NI_AO_SampleClock)]	= I(6),
++			[B(NI_AO_StartTrigger)]	= I(7),
++			[B(NI_DI_SampleClock)]	= I(29),
++			[B(NI_DO_SampleClock)]	= I(30),
++			[B(NI_FrequencyOutput)]	= I(15),
++			[B(NI_ChangeDetectionEvent)]	= I(28),
++			[B(NI_AnalogComparisonEvent)]	= I(17),
++			[B(NI_SCXI_Trig1)]	= I(27),
++			[B(NI_ExternalStrobe)]	= I(11),
++			[B(NI_PFI_DO)]	= I(16),
++		},
++		[B(TRIGGER_LINE(0))] = {
++			[B(NI_RTSI_BRD(0))]	= I(8),
++			[B(NI_RTSI_BRD(1))]	= I(9),
++			[B(NI_RTSI_BRD(2))]	= I(10),
++			[B(NI_RTSI_BRD(3))]	= I(11),
++			[B(NI_CtrSource(0))]	= I(5),
++			[B(NI_CtrGate(0))]	= I(6),
++			[B(NI_AI_StartTrigger)]	= I(0),
++			[B(NI_AI_ReferenceTrigger)]	= I(1),
++			[B(NI_AI_ConvertClock)]	= I(2),
++			[B(NI_AO_SampleClock)]	= I(3),
++			[B(NI_AO_StartTrigger)]	= I(4),
++			/*
++			 * for (*->TRIGGER_LINE(*)) MUX, a value of 12 should be
++			 * RTSI_OSC according to MHDDK mseries source.  There
++			 * are hints in comedi that show that this is actually a
++			 * 20MHz source for 628x cards(?)
++			 */
++			[B(NI_10MHzRefClock)]	= I(12),
++			[B(NI_RGOUT0)]	= I(7),
++		},
++		[B(TRIGGER_LINE(1))] = {
++			[B(NI_RTSI_BRD(0))]	= I(8),
++			[B(NI_RTSI_BRD(1))]	= I(9),
++			[B(NI_RTSI_BRD(2))]	= I(10),
++			[B(NI_RTSI_BRD(3))]	= I(11),
++			[B(NI_CtrSource(0))]	= I(5),
++			[B(NI_CtrGate(0))]	= I(6),
++			[B(NI_AI_StartTrigger)]	= I(0),
++			[B(NI_AI_ReferenceTrigger)]	= I(1),
++			[B(NI_AI_ConvertClock)]	= I(2),
++			[B(NI_AO_SampleClock)]	= I(3),
++			[B(NI_AO_StartTrigger)]	= I(4),
++			/*
++			 * for (*->TRIGGER_LINE(*)) MUX, a value of 12 should be
++			 * RTSI_OSC according to MHDDK mseries source.  There
++			 * are hints in comedi that show that this is actually a
++			 * 20MHz source for 628x cards(?)
++			 */
++			[B(NI_10MHzRefClock)]	= I(12),
++			[B(NI_RGOUT0)]	= I(7),
++		},
++		[B(TRIGGER_LINE(2))] = {
++			[B(NI_RTSI_BRD(0))]	= I(8),
++			[B(NI_RTSI_BRD(1))]	= I(9),
++			[B(NI_RTSI_BRD(2))]	= I(10),
++			[B(NI_RTSI_BRD(3))]	= I(11),
++			[B(NI_CtrSource(0))]	= I(5),
++			[B(NI_CtrGate(0))]	= I(6),
++			[B(NI_AI_StartTrigger)]	= I(0),
++			[B(NI_AI_ReferenceTrigger)]	= I(1),
++			[B(NI_AI_ConvertClock)]	= I(2),
++			[B(NI_AO_SampleClock)]	= I(3),
++			[B(NI_AO_StartTrigger)]	= I(4),
++			/*
++			 * for (*->TRIGGER_LINE(*)) MUX, a value of 12 should be
++			 * RTSI_OSC according to MHDDK mseries source.  There
++			 * are hints in comedi that show that this is actually a
++			 * 20MHz source for 628x cards(?)
++			 */
++			[B(NI_10MHzRefClock)]	= I(12),
++			[B(NI_RGOUT0)]	= I(7),
++		},
++		[B(TRIGGER_LINE(3))] = {
++			[B(NI_RTSI_BRD(0))]	= I(8),
++			[B(NI_RTSI_BRD(1))]	= I(9),
++			[B(NI_RTSI_BRD(2))]	= I(10),
++			[B(NI_RTSI_BRD(3))]	= I(11),
++			[B(NI_CtrSource(0))]	= I(5),
++			[B(NI_CtrGate(0))]	= I(6),
++			[B(NI_AI_StartTrigger)]	= I(0),
++			[B(NI_AI_ReferenceTrigger)]	= I(1),
++			[B(NI_AI_ConvertClock)]	= I(2),
++			[B(NI_AO_SampleClock)]	= I(3),
++			[B(NI_AO_StartTrigger)]	= I(4),
++			/*
++			 * for (*->TRIGGER_LINE(*)) MUX, a value of 12 should be
++			 * RTSI_OSC according to MHDDK mseries source.  There
++			 * are hints in comedi that show that this is actually a
++			 * 20MHz source for 628x cards(?)
++			 */
++			[B(NI_10MHzRefClock)]	= I(12),
++			[B(NI_RGOUT0)]	= I(7),
++		},
++		[B(TRIGGER_LINE(4))] = {
++			[B(NI_RTSI_BRD(0))]	= I(8),
++			[B(NI_RTSI_BRD(1))]	= I(9),
++			[B(NI_RTSI_BRD(2))]	= I(10),
++			[B(NI_RTSI_BRD(3))]	= I(11),
++			[B(NI_CtrSource(0))]	= I(5),
++			[B(NI_CtrGate(0))]	= I(6),
++			[B(NI_AI_StartTrigger)]	= I(0),
++			[B(NI_AI_ReferenceTrigger)]	= I(1),
++			[B(NI_AI_ConvertClock)]	= I(2),
++			[B(NI_AO_SampleClock)]	= I(3),
++			[B(NI_AO_StartTrigger)]	= I(4),
++			/*
++			 * for (*->TRIGGER_LINE(*)) MUX, a value of 12 should be
++			 * RTSI_OSC according to MHDDK mseries source.  There
++			 * are hints in comedi that show that this is actually a
++			 * 20MHz source for 628x cards(?)
++			 */
++			[B(NI_10MHzRefClock)]	= I(12),
++			[B(NI_RGOUT0)]	= I(7),
++		},
++		[B(TRIGGER_LINE(5))] = {
++			[B(NI_RTSI_BRD(0))]	= I(8),
++			[B(NI_RTSI_BRD(1))]	= I(9),
++			[B(NI_RTSI_BRD(2))]	= I(10),
++			[B(NI_RTSI_BRD(3))]	= I(11),
++			[B(NI_CtrSource(0))]	= I(5),
++			[B(NI_CtrGate(0))]	= I(6),
++			[B(NI_AI_StartTrigger)]	= I(0),
++			[B(NI_AI_ReferenceTrigger)]	= I(1),
++			[B(NI_AI_ConvertClock)]	= I(2),
++			[B(NI_AO_SampleClock)]	= I(3),
++			[B(NI_AO_StartTrigger)]	= I(4),
++			/*
++			 * for (*->TRIGGER_LINE(*)) MUX, a value of 12 should be
++			 * RTSI_OSC according to MHDDK mseries source.  There
++			 * are hints in comedi that show that this is actually a
++			 * 20MHz source for 628x cards(?)
++			 */
++			[B(NI_10MHzRefClock)]	= I(12),
++			[B(NI_RGOUT0)]	= I(7),
++		},
++		[B(TRIGGER_LINE(6))] = {
++			[B(NI_RTSI_BRD(0))]	= I(8),
++			[B(NI_RTSI_BRD(1))]	= I(9),
++			[B(NI_RTSI_BRD(2))]	= I(10),
++			[B(NI_RTSI_BRD(3))]	= I(11),
++			[B(NI_CtrSource(0))]	= I(5),
++			[B(NI_CtrGate(0))]	= I(6),
++			[B(NI_AI_StartTrigger)]	= I(0),
++			[B(NI_AI_ReferenceTrigger)]	= I(1),
++			[B(NI_AI_ConvertClock)]	= I(2),
++			[B(NI_AO_SampleClock)]	= I(3),
++			[B(NI_AO_StartTrigger)]	= I(4),
++			/*
++			 * for (*->TRIGGER_LINE(*)) MUX, a value of 12 should be
++			 * RTSI_OSC according to MHDDK mseries source.  There
++			 * are hints in comedi that show that this is actually a
++			 * 20MHz source for 628x cards(?)
++			 */
++			[B(NI_10MHzRefClock)]	= I(12),
++			[B(NI_RGOUT0)]	= I(7),
++		},
++		[B(TRIGGER_LINE(7))] = {
++			[B(NI_RTSI_BRD(0))]	= I(8),
++			[B(NI_RTSI_BRD(1))]	= I(9),
++			[B(NI_RTSI_BRD(2))]	= I(10),
++			[B(NI_RTSI_BRD(3))]	= I(11),
++			[B(NI_CtrSource(0))]	= I(5),
++			[B(NI_CtrGate(0))]	= I(6),
++			[B(NI_AI_StartTrigger)]	= I(0),
++			[B(NI_AI_ReferenceTrigger)]	= I(1),
++			[B(NI_AI_ConvertClock)]	= I(2),
++			[B(NI_AO_SampleClock)]	= I(3),
++			[B(NI_AO_StartTrigger)]	= I(4),
++			/*
++			 * for (*->TRIGGER_LINE(*)) MUX, a value of 12 should be
++			 * RTSI_OSC according to MHDDK mseries source.  There
++			 * are hints in comedi that show that this is actually a
++			 * 20MHz source for 628x cards(?)
++			 */
++			[B(NI_10MHzRefClock)]	= I(12),
++			[B(NI_RGOUT0)]	= I(7),
++		},
++		[B(NI_RTSI_BRD(0))] = {
++			[B(NI_PFI(0))]	= I(0),
++			[B(NI_PFI(1))]	= I(1),
++			[B(NI_PFI(2))]	= I(2),
++			[B(NI_PFI(3))]	= I(3),
++			[B(NI_PFI(4))]	= I(4),
++			[B(NI_PFI(5))]	= I(5),
++			[B(NI_CtrSource(1))]	= I(11),
++			[B(NI_CtrGate(1))]	= I(10),
++			[B(NI_CtrZ(0))]	= I(13),
++			[B(NI_CtrZ(1))]	= I(12),
++			[B(NI_CtrOut(1))]	= I(9),
++			[B(NI_AI_SampleClock)]	= I(15),
++			[B(NI_AI_PauseTrigger)]	= I(7),
++			[B(NI_AO_PauseTrigger)]	= I(6),
++			[B(NI_FrequencyOutput)]	= I(8),
++			[B(NI_AnalogComparisonEvent)]	= I(14),
++		},
++		[B(NI_RTSI_BRD(1))] = {
++			[B(NI_PFI(0))]	= I(0),
++			[B(NI_PFI(1))]	= I(1),
++			[B(NI_PFI(2))]	= I(2),
++			[B(NI_PFI(3))]	= I(3),
++			[B(NI_PFI(4))]	= I(4),
++			[B(NI_PFI(5))]	= I(5),
++			[B(NI_CtrSource(1))]	= I(11),
++			[B(NI_CtrGate(1))]	= I(10),
++			[B(NI_CtrZ(0))]	= I(13),
++			[B(NI_CtrZ(1))]	= I(12),
++			[B(NI_CtrOut(1))]	= I(9),
++			[B(NI_AI_SampleClock)]	= I(15),
++			[B(NI_AI_PauseTrigger)]	= I(7),
++			[B(NI_AO_PauseTrigger)]	= I(6),
++			[B(NI_FrequencyOutput)]	= I(8),
++			[B(NI_AnalogComparisonEvent)]	= I(14),
++		},
++		[B(NI_RTSI_BRD(2))] = {
++			[B(NI_PFI(0))]	= I(0),
++			[B(NI_PFI(1))]	= I(1),
++			[B(NI_PFI(2))]	= I(2),
++			[B(NI_PFI(3))]	= I(3),
++			[B(NI_PFI(4))]	= I(4),
++			[B(NI_PFI(5))]	= I(5),
++			[B(NI_CtrSource(1))]	= I(11),
++			[B(NI_CtrGate(1))]	= I(10),
++			[B(NI_CtrZ(0))]	= I(13),
++			[B(NI_CtrZ(1))]	= I(12),
++			[B(NI_CtrOut(1))]	= I(9),
++			[B(NI_AI_SampleClock)]	= I(15),
++			[B(NI_AI_PauseTrigger)]	= I(7),
++			[B(NI_AO_PauseTrigger)]	= I(6),
++			[B(NI_FrequencyOutput)]	= I(8),
++			[B(NI_AnalogComparisonEvent)]	= I(14),
++		},
++		[B(NI_RTSI_BRD(3))] = {
++			[B(NI_PFI(0))]	= I(0),
++			[B(NI_PFI(1))]	= I(1),
++			[B(NI_PFI(2))]	= I(2),
++			[B(NI_PFI(3))]	= I(3),
++			[B(NI_PFI(4))]	= I(4),
++			[B(NI_PFI(5))]	= I(5),
++			[B(NI_CtrSource(1))]	= I(11),
++			[B(NI_CtrGate(1))]	= I(10),
++			[B(NI_CtrZ(0))]	= I(13),
++			[B(NI_CtrZ(1))]	= I(12),
++			[B(NI_CtrOut(1))]	= I(9),
++			[B(NI_AI_SampleClock)]	= I(15),
++			[B(NI_AI_PauseTrigger)]	= I(7),
++			[B(NI_AO_PauseTrigger)]	= I(6),
++			[B(NI_FrequencyOutput)]	= I(8),
++			[B(NI_AnalogComparisonEvent)]	= I(14),
++		},
++		[B(NI_CtrSource(0))] = {
++			/* These are not currently implemented in ni modules */
++			[B(NI_PFI(0))]	= U(1),
++			[B(NI_PFI(1))]	= U(2),
++			[B(NI_PFI(2))]	= U(3),
++			[B(NI_PFI(3))]	= U(4),
++			[B(NI_PFI(4))]	= U(5),
++			[B(NI_PFI(5))]	= U(6),
++			[B(NI_PFI(6))]	= U(7),
++			[B(NI_PFI(7))]	= U(8),
++			[B(NI_PFI(8))]	= U(9),
++			[B(NI_PFI(9))]	= U(10),
++			[B(NI_PFI(10))]	= U(21),
++			[B(NI_PFI(11))]	= U(22),
++			[B(NI_PFI(12))]	= U(23),
++			[B(NI_PFI(13))]	= U(24),
++			[B(NI_PFI(14))]	= U(25),
++			[B(NI_PFI(15))]	= U(26),
++			[B(TRIGGER_LINE(0))]	= U(11),
++			[B(TRIGGER_LINE(1))]	= U(12),
++			[B(TRIGGER_LINE(2))]	= U(13),
++			[B(TRIGGER_LINE(3))]	= U(14),
++			[B(TRIGGER_LINE(4))]	= U(15),
++			[B(TRIGGER_LINE(5))]	= U(16),
++			[B(TRIGGER_LINE(6))]	= U(17),
++			[B(TRIGGER_LINE(7))]	= U(27),
++			[B(NI_CtrGate(1))]	= U(Gi_SRC(20, 0)),
++			[B(NI_CtrInternalOutput(1))]	= U(19),
++			[B(PXI_Star)]	= U(Gi_SRC(20, 1)),
++			[B(PXI_Clk10)]	= U(29),
++			[B(NI_20MHzTimebase)]	= U(0),
++			[B(NI_80MHzTimebase)]	= U(Gi_SRC(30, 0)),
++			[B(NI_100kHzTimebase)]	= U(18),
++			[B(NI_AnalogComparisonEvent)]	= U(Gi_SRC(30, 1)),
++			[B(NI_LogicLow)]	= U(31),
++		},
++		[B(NI_CtrSource(1))] = {
++			/* These are not currently implemented in ni modules */
++			[B(NI_PFI(0))]	= U(1),
++			[B(NI_PFI(1))]	= U(2),
++			[B(NI_PFI(2))]	= U(3),
++			[B(NI_PFI(3))]	= U(4),
++			[B(NI_PFI(4))]	= U(5),
++			[B(NI_PFI(5))]	= U(6),
++			[B(NI_PFI(6))]	= U(7),
++			[B(NI_PFI(7))]	= U(8),
++			[B(NI_PFI(8))]	= U(9),
++			[B(NI_PFI(9))]	= U(10),
++			[B(NI_PFI(10))]	= U(21),
++			[B(NI_PFI(11))]	= U(22),
++			[B(NI_PFI(12))]	= U(23),
++			[B(NI_PFI(13))]	= U(24),
++			[B(NI_PFI(14))]	= U(25),
++			[B(NI_PFI(15))]	= U(26),
++			[B(TRIGGER_LINE(0))]	= U(11),
++			[B(TRIGGER_LINE(1))]	= U(12),
++			[B(TRIGGER_LINE(2))]	= U(13),
++			[B(TRIGGER_LINE(3))]	= U(14),
++			[B(TRIGGER_LINE(4))]	= U(15),
++			[B(TRIGGER_LINE(5))]	= U(16),
++			[B(TRIGGER_LINE(6))]	= U(17),
++			[B(TRIGGER_LINE(7))]	= U(27),
++			[B(NI_CtrGate(0))]	= U(Gi_SRC(20, 0)),
++			[B(NI_CtrInternalOutput(0))]	= U(19),
++			[B(PXI_Star)]	= U(Gi_SRC(20, 1)),
++			[B(PXI_Clk10)]	= U(29),
++			[B(NI_20MHzTimebase)]	= U(0),
++			[B(NI_80MHzTimebase)]	= U(Gi_SRC(30, 0)),
++			[B(NI_100kHzTimebase)]	= U(18),
++			[B(NI_AnalogComparisonEvent)]	= U(Gi_SRC(30, 1)),
++			[B(NI_LogicLow)]	= U(31),
++		},
++		[B(NI_CtrGate(0))] = {
++			[B(NI_PFI(0))]	= I(1 /* source:  mhddk examples */),
++			[B(NI_PFI(1))]	= I(2),
++			[B(NI_PFI(2))]	= I(3),
++			[B(NI_PFI(3))]	= I(4),
++			[B(NI_PFI(4))]	= I(5),
++			[B(NI_PFI(5))]	= I(6),
++			[B(NI_PFI(6))]	= I(7),
++			[B(NI_PFI(7))]	= I(8),
++			[B(NI_PFI(8))]	= I(9),
++			[B(NI_PFI(9))]	= I(10),
++			[B(NI_PFI(10))]	= I(21),
++			[B(NI_PFI(11))]	= I(22),
++			[B(NI_PFI(12))]	= I(23),
++			[B(NI_PFI(13))]	= I(24),
++			[B(NI_PFI(14))]	= I(25),
++			[B(NI_PFI(15))]	= I(26),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(TRIGGER_LINE(7))]	= I(27),
++			[B(NI_CtrSource(1))]	= I(29),
++			/* source for following line:  mhddk GP examples */
++			[B(NI_CtrInternalOutput(1))]	= I(20),
++			[B(PXI_Star)]	= I(19),
++			[B(NI_AI_StartTrigger)]	= I(28),
++			[B(NI_AI_ReferenceTrigger)]	= I(18),
++			[B(NI_AnalogComparisonEvent)]	= I(30),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_CtrGate(1))] = {
++			/* source for following line:  mhddk examples */
++			[B(NI_PFI(0))]	= I(1),
++			[B(NI_PFI(1))]	= I(2),
++			[B(NI_PFI(2))]	= I(3),
++			[B(NI_PFI(3))]	= I(4),
++			[B(NI_PFI(4))]	= I(5),
++			[B(NI_PFI(5))]	= I(6),
++			[B(NI_PFI(6))]	= I(7),
++			[B(NI_PFI(7))]	= I(8),
++			[B(NI_PFI(8))]	= I(9),
++			[B(NI_PFI(9))]	= I(10),
++			[B(NI_PFI(10))]	= I(21),
++			[B(NI_PFI(11))]	= I(22),
++			[B(NI_PFI(12))]	= I(23),
++			[B(NI_PFI(13))]	= I(24),
++			[B(NI_PFI(14))]	= I(25),
++			[B(NI_PFI(15))]	= I(26),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(TRIGGER_LINE(7))]	= I(27),
++			[B(NI_CtrSource(0))]	= I(29),
++			/* source for following line:  mhddk GP examples */
++			[B(NI_CtrInternalOutput(0))]	= I(20),
++			[B(PXI_Star)]	= I(19),
++			[B(NI_AI_StartTrigger)]	= I(28),
++			[B(NI_AI_ReferenceTrigger)]	= I(18),
++			[B(NI_AnalogComparisonEvent)]	= I(30),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_CtrAux(0))] = {
++			/* these are just a guess; see GATE SELECT NOTE */
++			[B(NI_PFI(0))]	= I(1),
++			[B(NI_PFI(1))]	= I(2),
++			[B(NI_PFI(2))]	= I(3),
++			[B(NI_PFI(3))]	= I(4),
++			[B(NI_PFI(4))]	= I(5),
++			[B(NI_PFI(5))]	= I(6),
++			[B(NI_PFI(6))]	= I(7),
++			[B(NI_PFI(7))]	= I(8),
++			[B(NI_PFI(8))]	= I(9),
++			[B(NI_PFI(9))]	= I(10),
++			[B(NI_PFI(10))]	= I(21),
++			[B(NI_PFI(11))]	= I(22),
++			[B(NI_PFI(12))]	= I(23),
++			[B(NI_PFI(13))]	= I(24),
++			[B(NI_PFI(14))]	= I(25),
++			[B(NI_PFI(15))]	= I(26),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(TRIGGER_LINE(7))]	= I(27),
++			[B(NI_CtrSource(1))]	= I(29),
++			/* source for following line:  mhddk GP examples */
++			[B(NI_CtrInternalOutput(1))]	= I(20),
++			[B(PXI_Star)]	= I(19),
++			[B(NI_AI_StartTrigger)]	= I(28),
++			[B(NI_AI_ReferenceTrigger)]	= I(18),
++			[B(NI_AnalogComparisonEvent)]	= I(30),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_CtrAux(1))] = {
++			/* these are just a guess; see GATE SELECT NOTE */
++			[B(NI_PFI(0))]	= I(1),
++			[B(NI_PFI(1))]	= I(2),
++			[B(NI_PFI(2))]	= I(3),
++			[B(NI_PFI(3))]	= I(4),
++			[B(NI_PFI(4))]	= I(5),
++			[B(NI_PFI(5))]	= I(6),
++			[B(NI_PFI(6))]	= I(7),
++			[B(NI_PFI(7))]	= I(8),
++			[B(NI_PFI(8))]	= I(9),
++			[B(NI_PFI(9))]	= I(10),
++			[B(NI_PFI(10))]	= I(21),
++			[B(NI_PFI(11))]	= I(22),
++			[B(NI_PFI(12))]	= I(23),
++			[B(NI_PFI(13))]	= I(24),
++			[B(NI_PFI(14))]	= I(25),
++			[B(NI_PFI(15))]	= I(26),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(TRIGGER_LINE(7))]	= I(27),
++			[B(NI_CtrSource(0))]	= I(29),
++			/* source for following line:  mhddk GP examples */
++			[B(NI_CtrInternalOutput(0))]	= I(20),
++			[B(PXI_Star)]	= I(19),
++			[B(NI_AI_StartTrigger)]	= I(28),
++			[B(NI_AI_ReferenceTrigger)]	= I(18),
++			[B(NI_AnalogComparisonEvent)]	= I(30),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_CtrA(0))] = {
++			/*
++			 * See nimseries/Examples for outputs; inputs a guess
++			 * from device routes shown on NI-MAX.
++			 * see M-Series user manual (371022K-01)
++			 */
++			[B(NI_PFI(0))]	= I(1),
++			[B(NI_PFI(1))]	= I(2),
++			[B(NI_PFI(2))]	= I(3),
++			[B(NI_PFI(3))]	= I(4),
++			[B(NI_PFI(4))]	= I(5),
++			[B(NI_PFI(5))]	= I(6),
++			[B(NI_PFI(6))]	= I(7),
++			[B(NI_PFI(7))]	= I(8),
++			[B(NI_PFI(8))]	= I(9),
++			[B(NI_PFI(9))]	= I(10),
++			[B(NI_PFI(10))]	= I(21),
++			[B(NI_PFI(11))]	= I(22),
++			[B(NI_PFI(12))]	= I(23),
++			[B(NI_PFI(13))]	= I(24),
++			[B(NI_PFI(14))]	= I(25),
++			[B(NI_PFI(15))]	= I(26),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(TRIGGER_LINE(7))]	= I(27),
++			[B(PXI_Star)]	= I(20),
++			[B(NI_AnalogComparisonEvent)]	= I(30),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_CtrA(1))] = {
++			/*
++			 * See nimseries/Examples for outputs; inputs a guess
++			 * from device routes shown on NI-MAX.
++			 * see M-Series user manual (371022K-01)
++			 */
++			[B(NI_PFI(0))]	= I(1),
++			[B(NI_PFI(1))]	= I(2),
++			[B(NI_PFI(2))]	= I(3),
++			[B(NI_PFI(3))]	= I(4),
++			[B(NI_PFI(4))]	= I(5),
++			[B(NI_PFI(5))]	= I(6),
++			[B(NI_PFI(6))]	= I(7),
++			[B(NI_PFI(7))]	= I(8),
++			[B(NI_PFI(8))]	= I(9),
++			[B(NI_PFI(9))]	= I(10),
++			[B(NI_PFI(10))]	= I(21),
++			[B(NI_PFI(11))]	= I(22),
++			[B(NI_PFI(12))]	= I(23),
++			[B(NI_PFI(13))]	= I(24),
++			[B(NI_PFI(14))]	= I(25),
++			[B(NI_PFI(15))]	= I(26),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(TRIGGER_LINE(7))]	= I(27),
++			[B(PXI_Star)]	= I(20),
++			[B(NI_AnalogComparisonEvent)]	= I(30),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_CtrB(0))] = {
++			/*
++			 * See nimseries/Examples for outputs; inputs a guess
++			 * from device routes shown on NI-MAX.
++			 * see M-Series user manual (371022K-01)
++			 */
++			[B(NI_PFI(0))]	= I(1),
++			[B(NI_PFI(1))]	= I(2),
++			[B(NI_PFI(2))]	= I(3),
++			[B(NI_PFI(3))]	= I(4),
++			[B(NI_PFI(4))]	= I(5),
++			[B(NI_PFI(5))]	= I(6),
++			[B(NI_PFI(6))]	= I(7),
++			[B(NI_PFI(7))]	= I(8),
++			[B(NI_PFI(8))]	= I(9),
++			[B(NI_PFI(9))]	= I(10),
++			[B(NI_PFI(10))]	= I(21),
++			[B(NI_PFI(11))]	= I(22),
++			[B(NI_PFI(12))]	= I(23),
++			[B(NI_PFI(13))]	= I(24),
++			[B(NI_PFI(14))]	= I(25),
++			[B(NI_PFI(15))]	= I(26),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(TRIGGER_LINE(7))]	= I(27),
++			[B(PXI_Star)]	= I(20),
++			[B(NI_AnalogComparisonEvent)]	= I(30),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_CtrB(1))] = {
++			/*
++			 * See nimseries/Examples for outputs; inputs a guess
++			 * from device routes shown on NI-MAX.
++			 * see M-Series user manual (371022K-01)
++			 */
++			[B(NI_PFI(0))]	= I(1),
++			[B(NI_PFI(1))]	= I(2),
++			[B(NI_PFI(2))]	= I(3),
++			[B(NI_PFI(3))]	= I(4),
++			[B(NI_PFI(4))]	= I(5),
++			[B(NI_PFI(5))]	= I(6),
++			[B(NI_PFI(6))]	= I(7),
++			[B(NI_PFI(7))]	= I(8),
++			[B(NI_PFI(8))]	= I(9),
++			[B(NI_PFI(9))]	= I(10),
++			[B(NI_PFI(10))]	= I(21),
++			[B(NI_PFI(11))]	= I(22),
++			[B(NI_PFI(12))]	= I(23),
++			[B(NI_PFI(13))]	= I(24),
++			[B(NI_PFI(14))]	= I(25),
++			[B(NI_PFI(15))]	= I(26),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(TRIGGER_LINE(7))]	= I(27),
++			[B(PXI_Star)]	= I(20),
++			[B(NI_AnalogComparisonEvent)]	= I(30),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_CtrZ(0))] = {
++			/*
++			 * See nimseries/Examples for outputs; inputs a guess
++			 * from device routes shown on NI-MAX.
++			 * see M-Series user manual (371022K-01)
++			 */
++			[B(NI_PFI(0))]	= I(1),
++			[B(NI_PFI(1))]	= I(2),
++			[B(NI_PFI(2))]	= I(3),
++			[B(NI_PFI(3))]	= I(4),
++			[B(NI_PFI(4))]	= I(5),
++			[B(NI_PFI(5))]	= I(6),
++			[B(NI_PFI(6))]	= I(7),
++			[B(NI_PFI(7))]	= I(8),
++			[B(NI_PFI(8))]	= I(9),
++			[B(NI_PFI(9))]	= I(10),
++			[B(NI_PFI(10))]	= I(21),
++			[B(NI_PFI(11))]	= I(22),
++			[B(NI_PFI(12))]	= I(23),
++			[B(NI_PFI(13))]	= I(24),
++			[B(NI_PFI(14))]	= I(25),
++			[B(NI_PFI(15))]	= I(26),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(TRIGGER_LINE(7))]	= I(27),
++			[B(PXI_Star)]	= I(20),
++			[B(NI_AnalogComparisonEvent)]	= I(30),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_CtrZ(1))] = {
++			/*
++			 * See nimseries/Examples for outputs; inputs a guess
++			 * from device routes shown on NI-MAX.
++			 * see M-Series user manual (371022K-01)
++			 */
++			[B(NI_PFI(0))]	= I(1),
++			[B(NI_PFI(1))]	= I(2),
++			[B(NI_PFI(2))]	= I(3),
++			[B(NI_PFI(3))]	= I(4),
++			[B(NI_PFI(4))]	= I(5),
++			[B(NI_PFI(5))]	= I(6),
++			[B(NI_PFI(6))]	= I(7),
++			[B(NI_PFI(7))]	= I(8),
++			[B(NI_PFI(8))]	= I(9),
++			[B(NI_PFI(9))]	= I(10),
++			[B(NI_PFI(10))]	= I(21),
++			[B(NI_PFI(11))]	= I(22),
++			[B(NI_PFI(12))]	= I(23),
++			[B(NI_PFI(13))]	= I(24),
++			[B(NI_PFI(14))]	= I(25),
++			[B(NI_PFI(15))]	= I(26),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(TRIGGER_LINE(7))]	= I(27),
++			[B(PXI_Star)]	= I(20),
++			[B(NI_AnalogComparisonEvent)]	= I(30),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_CtrArmStartTrigger(0))] = {
++			/* these are just a guess; see GATE SELECT NOTE */
++			[B(NI_PFI(0))]	= I(1),
++			[B(NI_PFI(1))]	= I(2),
++			[B(NI_PFI(2))]	= I(3),
++			[B(NI_PFI(3))]	= I(4),
++			[B(NI_PFI(4))]	= I(5),
++			[B(NI_PFI(5))]	= I(6),
++			[B(NI_PFI(6))]	= I(7),
++			[B(NI_PFI(7))]	= I(8),
++			[B(NI_PFI(8))]	= I(9),
++			[B(NI_PFI(9))]	= I(10),
++			[B(NI_PFI(10))]	= I(21),
++			[B(NI_PFI(11))]	= I(22),
++			[B(NI_PFI(12))]	= I(23),
++			[B(NI_PFI(13))]	= I(24),
++			[B(NI_PFI(14))]	= I(25),
++			[B(NI_PFI(15))]	= I(26),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(TRIGGER_LINE(7))]	= I(27),
++			[B(NI_CtrSource(1))]	= I(29),
++			/* source for following line:  mhddk GP examples */
++			[B(NI_CtrInternalOutput(1))]	= I(20),
++			[B(PXI_Star)]	= I(19),
++			[B(NI_AI_StartTrigger)]	= I(28),
++			[B(NI_AI_ReferenceTrigger)]	= I(18),
++			[B(NI_AnalogComparisonEvent)]	= I(30),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_CtrArmStartTrigger(1))] = {
++			/* these are just a guess; see GATE SELECT NOTE */
++			[B(NI_PFI(0))]	= I(1),
++			[B(NI_PFI(1))]	= I(2),
++			[B(NI_PFI(2))]	= I(3),
++			[B(NI_PFI(3))]	= I(4),
++			[B(NI_PFI(4))]	= I(5),
++			[B(NI_PFI(5))]	= I(6),
++			[B(NI_PFI(6))]	= I(7),
++			[B(NI_PFI(7))]	= I(8),
++			[B(NI_PFI(8))]	= I(9),
++			[B(NI_PFI(9))]	= I(10),
++			[B(NI_PFI(10))]	= I(21),
++			[B(NI_PFI(11))]	= I(22),
++			[B(NI_PFI(12))]	= I(23),
++			[B(NI_PFI(13))]	= I(24),
++			[B(NI_PFI(14))]	= I(25),
++			[B(NI_PFI(15))]	= I(26),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(TRIGGER_LINE(7))]	= I(27),
++			[B(NI_CtrSource(0))]	= I(29),
++			/* source for following line:  mhddk GP examples */
++			[B(NI_CtrInternalOutput(0))]	= I(20),
++			[B(PXI_Star)]	= I(19),
++			[B(NI_AI_StartTrigger)]	= I(28),
++			[B(NI_AI_ReferenceTrigger)]	= I(18),
++			[B(NI_AnalogComparisonEvent)]	= I(30),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_CtrOut(0))] = {
++			[B(TRIGGER_LINE(0))]	= I(1),
++			[B(TRIGGER_LINE(1))]	= I(2),
++			[B(TRIGGER_LINE(2))]	= I(3),
++			[B(TRIGGER_LINE(3))]	= I(4),
++			[B(TRIGGER_LINE(4))]	= I(5),
++			[B(TRIGGER_LINE(5))]	= I(6),
++			[B(TRIGGER_LINE(6))]	= I(7),
++			[B(NI_CtrInternalOutput(0))]	= I(0),
++		},
++		[B(NI_CtrOut(1))] = {
++			[B(NI_CtrInternalOutput(1))]	= I(0),
++		},
++		[B(NI_AI_SampleClock)] = {
++			[B(NI_PFI(0))]	= I(1),
++			[B(NI_PFI(1))]	= I(2),
++			[B(NI_PFI(2))]	= I(3),
++			[B(NI_PFI(3))]	= I(4),
++			[B(NI_PFI(4))]	= I(5),
++			[B(NI_PFI(5))]	= I(6),
++			[B(NI_PFI(6))]	= I(7),
++			[B(NI_PFI(7))]	= I(8),
++			[B(NI_PFI(8))]	= I(9),
++			[B(NI_PFI(9))]	= I(10),
++			[B(NI_PFI(10))]	= I(21),
++			[B(NI_PFI(11))]	= I(22),
++			[B(NI_PFI(12))]	= I(23),
++			[B(NI_PFI(13))]	= I(24),
++			[B(NI_PFI(14))]	= I(25),
++			[B(NI_PFI(15))]	= I(26),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(TRIGGER_LINE(7))]	= I(27),
++			[B(NI_CtrInternalOutput(0))]	= I(19),
++			[B(NI_CtrInternalOutput(1))]	= I(28),
++			[B(PXI_Star)]	= I(20),
++			[B(NI_AI_SampleClockTimebase)]	= I(0),
++			[B(NI_AnalogComparisonEvent)]	= I(30),
++			[B(NI_SCXI_Trig1)]	= I(29),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_AI_SampleClockTimebase)] = {
++			/* These are not currently implemented in ni modules */
++			[B(NI_PFI(0))]	= U(1),
++			[B(NI_PFI(1))]	= U(2),
++			[B(NI_PFI(2))]	= U(3),
++			[B(NI_PFI(3))]	= U(4),
++			[B(NI_PFI(4))]	= U(5),
++			[B(NI_PFI(5))]	= U(6),
++			[B(NI_PFI(6))]	= U(7),
++			[B(NI_PFI(7))]	= U(8),
++			[B(NI_PFI(8))]	= U(9),
++			[B(NI_PFI(9))]	= U(10),
++			[B(NI_PFI(10))]	= U(21),
++			[B(NI_PFI(11))]	= U(22),
++			[B(NI_PFI(12))]	= U(23),
++			[B(NI_PFI(13))]	= U(24),
++			[B(NI_PFI(14))]	= U(25),
++			[B(NI_PFI(15))]	= U(26),
++			[B(TRIGGER_LINE(0))]	= U(11),
++			[B(TRIGGER_LINE(1))]	= U(12),
++			[B(TRIGGER_LINE(2))]	= U(13),
++			[B(TRIGGER_LINE(3))]	= U(14),
++			[B(TRIGGER_LINE(4))]	= U(15),
++			[B(TRIGGER_LINE(5))]	= U(16),
++			[B(TRIGGER_LINE(6))]	= U(17),
++			[B(TRIGGER_LINE(7))]	= U(27),
++			[B(PXI_Star)]	= U(20),
++			[B(PXI_Clk10)]	= U(29),
++			/*
++			 * For routes (*->NI_AI_SampleClockTimebase) and
++			 * (*->NI_AO_SampleClockTimebase), tMSeries.h of MHDDK
++			 * shows 0 value as selecting ground (case ground?) and
++			 * 28 value selecting TIMEBASE 1.
++			 */
++			[B(NI_20MHzTimebase)]	= U(28),
++			[B(NI_100kHzTimebase)]	= U(19),
++			[B(NI_AnalogComparisonEvent)]	= U(30),
++			[B(NI_LogicLow)]	= U(31),
++			[B(NI_CaseGround)]	= U(0),
++		},
++		[B(NI_AI_StartTrigger)] = {
++			[B(NI_PFI(0))]	= I(1),
++			[B(NI_PFI(1))]	= I(2),
++			[B(NI_PFI(2))]	= I(3),
++			[B(NI_PFI(3))]	= I(4),
++			[B(NI_PFI(4))]	= I(5),
++			[B(NI_PFI(5))]	= I(6),
++			[B(NI_PFI(6))]	= I(7),
++			[B(NI_PFI(7))]	= I(8),
++			[B(NI_PFI(8))]	= I(9),
++			[B(NI_PFI(9))]	= I(10),
++			[B(NI_PFI(10))]	= I(21),
++			[B(NI_PFI(11))]	= I(22),
++			[B(NI_PFI(12))]	= I(23),
++			[B(NI_PFI(13))]	= I(24),
++			[B(NI_PFI(14))]	= I(25),
++			[B(NI_PFI(15))]	= I(26),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(TRIGGER_LINE(7))]	= I(27),
++			[B(NI_CtrInternalOutput(0))]	= I(18),
++			[B(NI_CtrInternalOutput(1))]	= I(19),
++			[B(PXI_Star)]	= I(20),
++			[B(NI_AnalogComparisonEvent)]	= I(30),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_AI_ReferenceTrigger)] = {
++			/* These are not currently implemented in ni modules */
++			[B(NI_PFI(0))]	= U(1),
++			[B(NI_PFI(1))]	= U(2),
++			[B(NI_PFI(2))]	= U(3),
++			[B(NI_PFI(3))]	= U(4),
++			[B(NI_PFI(4))]	= U(5),
++			[B(NI_PFI(5))]	= U(6),
++			[B(NI_PFI(6))]	= U(7),
++			[B(NI_PFI(7))]	= U(8),
++			[B(NI_PFI(8))]	= U(9),
++			[B(NI_PFI(9))]	= U(10),
++			[B(NI_PFI(10))]	= U(21),
++			[B(NI_PFI(11))]	= U(22),
++			[B(NI_PFI(12))]	= U(23),
++			[B(NI_PFI(13))]	= U(24),
++			[B(NI_PFI(14))]	= U(25),
++			[B(NI_PFI(15))]	= U(26),
++			[B(TRIGGER_LINE(0))]	= U(11),
++			[B(TRIGGER_LINE(1))]	= U(12),
++			[B(TRIGGER_LINE(2))]	= U(13),
++			[B(TRIGGER_LINE(3))]	= U(14),
++			[B(TRIGGER_LINE(4))]	= U(15),
++			[B(TRIGGER_LINE(5))]	= U(16),
++			[B(TRIGGER_LINE(6))]	= U(17),
++			[B(TRIGGER_LINE(7))]	= U(27),
++			[B(PXI_Star)]	= U(20),
++			[B(NI_AnalogComparisonEvent)]	= U(30),
++			[B(NI_LogicLow)]	= U(31),
++		},
++		[B(NI_AI_ConvertClock)] = {
++			[B(NI_PFI(0))]	= I(1),
++			[B(NI_PFI(1))]	= I(2),
++			[B(NI_PFI(2))]	= I(3),
++			[B(NI_PFI(3))]	= I(4),
++			[B(NI_PFI(4))]	= I(5),
++			[B(NI_PFI(5))]	= I(6),
++			[B(NI_PFI(6))]	= I(7),
++			[B(NI_PFI(7))]	= I(8),
++			[B(NI_PFI(8))]	= I(9),
++			[B(NI_PFI(9))]	= I(10),
++			[B(NI_PFI(10))]	= I(21),
++			[B(NI_PFI(11))]	= I(22),
++			[B(NI_PFI(12))]	= I(23),
++			[B(NI_PFI(13))]	= I(24),
++			[B(NI_PFI(14))]	= I(25),
++			[B(NI_PFI(15))]	= I(26),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(TRIGGER_LINE(7))]	= I(27),
++			/* source for following line:  mhddk example headers */
++			[B(NI_CtrInternalOutput(0))]	= I(19),
++			/* source for following line:  mhddk example headers */
++			[B(NI_CtrInternalOutput(1))]	= I(18),
++			[B(PXI_Star)]	= I(20),
++			[B(NI_AI_ConvertClockTimebase)]	= I(0),
++			[B(NI_AnalogComparisonEvent)]	= I(30),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_AI_ConvertClockTimebase)] = {
++			/* These are not currently implemented in ni modules */
++			[B(NI_AI_SampleClockTimebase)]	= U(0),
++			[B(NI_20MHzTimebase)]	= U(1),
++		},
++		[B(NI_AI_PauseTrigger)] = {
++			/* These are not currently implemented in ni modules */
++			[B(NI_PFI(0))]	= U(1),
++			[B(NI_PFI(1))]	= U(2),
++			[B(NI_PFI(2))]	= U(3),
++			[B(NI_PFI(3))]	= U(4),
++			[B(NI_PFI(4))]	= U(5),
++			[B(NI_PFI(5))]	= U(6),
++			[B(NI_PFI(6))]	= U(7),
++			[B(NI_PFI(7))]	= U(8),
++			[B(NI_PFI(8))]	= U(9),
++			[B(NI_PFI(9))]	= U(10),
++			[B(NI_PFI(10))]	= U(21),
++			[B(NI_PFI(11))]	= U(22),
++			[B(NI_PFI(12))]	= U(23),
++			[B(NI_PFI(13))]	= U(24),
++			[B(NI_PFI(14))]	= U(25),
++			[B(NI_PFI(15))]	= U(26),
++			[B(TRIGGER_LINE(0))]	= U(11),
++			[B(TRIGGER_LINE(1))]	= U(12),
++			[B(TRIGGER_LINE(2))]	= U(13),
++			[B(TRIGGER_LINE(3))]	= U(14),
++			[B(TRIGGER_LINE(4))]	= U(15),
++			[B(TRIGGER_LINE(5))]	= U(16),
++			[B(TRIGGER_LINE(6))]	= U(17),
++			[B(TRIGGER_LINE(7))]	= U(27),
++			[B(PXI_Star)]	= U(20),
++			[B(NI_AnalogComparisonEvent)]	= U(30),
++			[B(NI_LogicLow)]	= U(31),
++		},
++		[B(NI_AO_SampleClock)] = {
++			[B(NI_PFI(0))]	= I(1),
++			[B(NI_PFI(1))]	= I(2),
++			[B(NI_PFI(2))]	= I(3),
++			[B(NI_PFI(3))]	= I(4),
++			[B(NI_PFI(4))]	= I(5),
++			[B(NI_PFI(5))]	= I(6),
++			[B(NI_PFI(6))]	= I(7),
++			[B(NI_PFI(7))]	= I(8),
++			[B(NI_PFI(8))]	= I(9),
++			[B(NI_PFI(9))]	= I(10),
++			[B(NI_PFI(10))]	= I(21),
++			[B(NI_PFI(11))]	= I(22),
++			[B(NI_PFI(12))]	= I(23),
++			[B(NI_PFI(13))]	= I(24),
++			[B(NI_PFI(14))]	= I(25),
++			[B(NI_PFI(15))]	= I(26),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(TRIGGER_LINE(7))]	= I(27),
++			[B(NI_CtrInternalOutput(0))]	= I(18),
++			[B(NI_CtrInternalOutput(1))]	= I(19),
++			[B(PXI_Star)]	= I(20),
++			[B(NI_AO_SampleClockTimebase)]	= I(0),
++			[B(NI_AnalogComparisonEvent)]	= I(30),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_AO_SampleClockTimebase)] = {
++			/* These are not currently implemented in ni modules */
++			[B(NI_PFI(0))]	= U(1),
++			[B(NI_PFI(1))]	= U(2),
++			[B(NI_PFI(2))]	= U(3),
++			[B(NI_PFI(3))]	= U(4),
++			[B(NI_PFI(4))]	= U(5),
++			[B(NI_PFI(5))]	= U(6),
++			[B(NI_PFI(6))]	= U(7),
++			[B(NI_PFI(7))]	= U(8),
++			[B(NI_PFI(8))]	= U(9),
++			[B(NI_PFI(9))]	= U(10),
++			[B(NI_PFI(10))]	= U(21),
++			[B(NI_PFI(11))]	= U(22),
++			[B(NI_PFI(12))]	= U(23),
++			[B(NI_PFI(13))]	= U(24),
++			[B(NI_PFI(14))]	= U(25),
++			[B(NI_PFI(15))]	= U(26),
++			[B(TRIGGER_LINE(0))]	= U(11),
++			[B(TRIGGER_LINE(1))]	= U(12),
++			[B(TRIGGER_LINE(2))]	= U(13),
++			[B(TRIGGER_LINE(3))]	= U(14),
++			[B(TRIGGER_LINE(4))]	= U(15),
++			[B(TRIGGER_LINE(5))]	= U(16),
++			[B(TRIGGER_LINE(6))]	= U(17),
++			[B(TRIGGER_LINE(7))]	= U(27),
++			[B(PXI_Star)]	= U(20),
++			[B(PXI_Clk10)]	= U(29),
++			/*
++			 * For routes (*->NI_AI_SampleClockTimebase) and
++			 * (*->NI_AO_SampleClockTimebase), tMSeries.h of MHDDK
++			 * shows 0 value as selecting ground (case ground?) and
++			 * 28 value selecting TIMEBASE 1.
++			 */
++			[B(NI_20MHzTimebase)]	= U(28),
++			[B(NI_100kHzTimebase)]	= U(19),
++			[B(NI_AnalogComparisonEvent)]	= U(30),
++			[B(NI_LogicLow)]	= U(31),
++			[B(NI_CaseGround)]	= U(0),
++		},
++		[B(NI_AO_StartTrigger)] = {
++			[B(NI_PFI(0))]	= I(1),
++			[B(NI_PFI(1))]	= I(2),
++			[B(NI_PFI(2))]	= I(3),
++			[B(NI_PFI(3))]	= I(4),
++			[B(NI_PFI(4))]	= I(5),
++			[B(NI_PFI(5))]	= I(6),
++			[B(NI_PFI(6))]	= I(7),
++			[B(NI_PFI(7))]	= I(8),
++			[B(NI_PFI(8))]	= I(9),
++			[B(NI_PFI(9))]	= I(10),
++			[B(NI_PFI(10))]	= I(21),
++			[B(NI_PFI(11))]	= I(22),
++			[B(NI_PFI(12))]	= I(23),
++			[B(NI_PFI(13))]	= I(24),
++			[B(NI_PFI(14))]	= I(25),
++			[B(NI_PFI(15))]	= I(26),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(TRIGGER_LINE(7))]	= I(27),
++			[B(PXI_Star)]	= I(20),
++			/*
++			 * for the signal route
++			 * (NI_AI_StartTrigger->NI_AO_StartTrigger), DAQ-STC &
++			 * MHDDK disagreed for e-series.  MHDDK for m-series
++			 * agrees with DAQ-STC description and uses the value 18
++			 * for the route
++			 * (NI_AI_ReferenceTrigger->NI_AO_StartTrigger).  The
++			 * m-series devices are supposed to have DAQ-STC2.
++			 * There are no DAQ-STC2 docs to compare with.
++			 */
++			[B(NI_AI_StartTrigger)]	= I(19),
++			[B(NI_AI_ReferenceTrigger)]	= I(18),
++			[B(NI_AnalogComparisonEvent)]	= I(30),
++			[B(NI_LogicLow)]	= I(31),
++		},
++		[B(NI_AO_PauseTrigger)] = {
++			/* These are not currently implemented in ni modules */
++			[B(NI_PFI(0))]	= U(1),
++			[B(NI_PFI(1))]	= U(2),
++			[B(NI_PFI(2))]	= U(3),
++			[B(NI_PFI(3))]	= U(4),
++			[B(NI_PFI(4))]	= U(5),
++			[B(NI_PFI(5))]	= U(6),
++			[B(NI_PFI(6))]	= U(7),
++			[B(NI_PFI(7))]	= U(8),
++			[B(NI_PFI(8))]	= U(9),
++			[B(NI_PFI(9))]	= U(10),
++			[B(NI_PFI(10))]	= U(21),
++			[B(NI_PFI(11))]	= U(22),
++			[B(NI_PFI(12))]	= U(23),
++			[B(NI_PFI(13))]	= U(24),
++			[B(NI_PFI(14))]	= U(25),
++			[B(NI_PFI(15))]	= U(26),
++			[B(TRIGGER_LINE(0))]	= U(11),
++			[B(TRIGGER_LINE(1))]	= U(12),
++			[B(TRIGGER_LINE(2))]	= U(13),
++			[B(TRIGGER_LINE(3))]	= U(14),
++			[B(TRIGGER_LINE(4))]	= U(15),
++			[B(TRIGGER_LINE(5))]	= U(16),
++			[B(TRIGGER_LINE(6))]	= U(17),
++			[B(TRIGGER_LINE(7))]	= U(27),
++			[B(PXI_Star)]	= U(20),
++			[B(NI_AnalogComparisonEvent)]	= U(30),
++			[B(NI_LogicLow)]	= U(31),
++		},
++		[B(NI_DI_SampleClock)] = {
++			[B(NI_PFI(0))]	= I(1),
++			[B(NI_PFI(1))]	= I(2),
++			[B(NI_PFI(2))]	= I(3),
++			[B(NI_PFI(3))]	= I(4),
++			[B(NI_PFI(4))]	= I(5),
++			[B(NI_PFI(5))]	= I(6),
++			[B(NI_PFI(6))]	= I(7),
++			[B(NI_PFI(7))]	= I(8),
++			[B(NI_PFI(8))]	= I(9),
++			[B(NI_PFI(9))]	= I(10),
++			[B(NI_PFI(10))]	= I(21),
++			[B(NI_PFI(11))]	= I(22),
++			[B(NI_PFI(12))]	= I(23),
++			[B(NI_PFI(13))]	= I(24),
++			[B(NI_PFI(14))]	= I(25),
++			[B(NI_PFI(15))]	= I(26),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(TRIGGER_LINE(7))]	= I(27),
++			[B(NI_CtrInternalOutput(0))]	= I(28),
++			[B(NI_CtrInternalOutput(1))]	= I(29),
++			[B(PXI_Star)]	= I(20),
++			[B(NI_AI_SampleClock)]	= I(18),
++			[B(NI_AI_ConvertClock)]	= I(19),
++			[B(NI_AO_SampleClock)]	= I(31),
++			[B(NI_FrequencyOutput)]	= I(32),
++			[B(NI_ChangeDetectionEvent)]	= I(33),
++			[B(NI_CaseGround)]	= I(0),
++		},
++		[B(NI_DO_SampleClock)] = {
++			[B(NI_PFI(0))]	= I(1),
++			[B(NI_PFI(1))]	= I(2),
++			[B(NI_PFI(2))]	= I(3),
++			[B(NI_PFI(3))]	= I(4),
++			[B(NI_PFI(4))]	= I(5),
++			[B(NI_PFI(5))]	= I(6),
++			[B(NI_PFI(6))]	= I(7),
++			[B(NI_PFI(7))]	= I(8),
++			[B(NI_PFI(8))]	= I(9),
++			[B(NI_PFI(9))]	= I(10),
++			[B(NI_PFI(10))]	= I(21),
++			[B(NI_PFI(11))]	= I(22),
++			[B(NI_PFI(12))]	= I(23),
++			[B(NI_PFI(13))]	= I(24),
++			[B(NI_PFI(14))]	= I(25),
++			[B(NI_PFI(15))]	= I(26),
++			[B(TRIGGER_LINE(0))]	= I(11),
++			[B(TRIGGER_LINE(1))]	= I(12),
++			[B(TRIGGER_LINE(2))]	= I(13),
++			[B(TRIGGER_LINE(3))]	= I(14),
++			[B(TRIGGER_LINE(4))]	= I(15),
++			[B(TRIGGER_LINE(5))]	= I(16),
++			[B(TRIGGER_LINE(6))]	= I(17),
++			[B(TRIGGER_LINE(7))]	= I(27),
++			[B(NI_CtrInternalOutput(0))]	= I(28),
++			[B(NI_CtrInternalOutput(1))]	= I(29),
++			[B(PXI_Star)]	= I(20),
++			[B(NI_AI_SampleClock)]	= I(18),
++			[B(NI_AI_ConvertClock)]	= I(19),
++			[B(NI_AO_SampleClock)]	= I(31),
++			[B(NI_FrequencyOutput)]	= I(32),
++			[B(NI_ChangeDetectionEvent)]	= I(33),
++			[B(NI_CaseGround)]	= I(0),
++		},
++		[B(NI_MasterTimebase)] = {
++			/* These are not currently implemented in ni modules */
++			[B(TRIGGER_LINE(0))]	= U(11),
++			[B(TRIGGER_LINE(1))]	= U(12),
++			[B(TRIGGER_LINE(2))]	= U(13),
++			[B(TRIGGER_LINE(3))]	= U(14),
++			[B(TRIGGER_LINE(4))]	= U(15),
++			[B(TRIGGER_LINE(5))]	= U(16),
++			[B(TRIGGER_LINE(6))]	= U(17),
++			[B(TRIGGER_LINE(7))]	= U(27),
++			[B(PXI_Star)]	= U(20),
++			[B(PXI_Clk10)]	= U(29),
++			[B(NI_10MHzRefClock)]	= U(0),
++		},
++		/*
++		 * This symbol is not defined and nothing for this is
++		 * implemented--just including this because data was found in
++		 * the NI-STC for it--can't remember where.
++		 * [B(NI_FrequencyOutTimebase)] = {
++		 *	** These are not currently implemented in ni modules **
++		 *	[B(NI_20MHzTimebase)]	= U(0),
++		 *	[B(NI_100kHzTimebase)]	= U(1),
++		 * },
++		 */
++		[B(NI_RGOUT0)] = {
++			[B(NI_CtrInternalOutput(0))]	= I(0),
++			[B(NI_CtrOut(0))]	= I(1),
++		},
++	},
++};
+diff --git a/drivers/staging/comedi/drivers/ni_routing/tools/.gitignore b/drivers/staging/comedi/drivers/ni_routing/tools/.gitignore
+new file mode 100644
+index 000000000000..ef38008280a9
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/tools/.gitignore
+@@ -0,0 +1,7 @@
++comedi_h.py
++*.pyc
++ni_values.py
++convert_c_to_py
++c/
++csv/
++all_cfiles.c
+diff --git a/drivers/staging/comedi/drivers/ni_routing/tools/Makefile b/drivers/staging/comedi/drivers/ni_routing/tools/Makefile
+new file mode 100644
+index 000000000000..1966850584d2
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/tools/Makefile
+@@ -0,0 +1,79 @@
++# this make file is simply to help autogenerate these files:
++# 	ni_route_values.h
++#	ni_device_routes.h
++# in order to do this, we are also generating a python representation (using
++# ctypesgen) of ../../comedi.h.
++# This allows us to sort NI signal/terminal names numerically to use a binary
++# search through the device_routes tables to find valid routes.
++
++ALL:
++	@echo Typical targets:
++	@echo "\`make csv-files\`"
++	@echo "  Creates new csv-files using content of c-files of existing"
++	@echo "  ni_routing/* content.  New csv files are placed in csv"
++	@echo "  sub-directory."
++	@echo "\`make c-files\`"
++	@echo "  Creates new c-files using content of csv sub-directory.  These"
++	@echo "  new c-files can be compared to the active content in the"
++	@echo "  ni_routing directory."
++	@echo "\`make csv-blank\`"
++	@echo "  Create a new blank csv file.  This is useful for establishing a"
++	@echo "  new data table for either a device family \(less likely\) or a"
++	@echo "  specific board of an existing device family \(more likely\)."
++	@echo "\`make clean-partial\`"
++	@echo "  Remove all generated files/directories EXCEPT for csv/c files."
++	@echo "\`make clean\`"
++	@echo "  Remove all generated files/directories."
++	@echo "\`make everything\`"
++	@echo "  Build all csv-files, then all new c-files."
++
++everything : csv-files c-files csv-blank
++
++CPPFLAGS=-D"BIT(x)=(1UL<<(x))" -D__user=
++
++comedi_h.py : ../../../comedi.h
++	ctypesgen $< --include "sys/ioctl.h" --cpp 'gcc -E $(CPPFLAGS)' -o $@
++
++convert_c_to_py: all_cfiles.c
++	gcc -g convert_c_to_py.c -o convert_c_to_py -std=c99
++
++ni_values.py: convert_c_to_py
++	./convert_c_to_py
++
++csv-files : ni_values.py comedi_h.py
++	./convert_py_to_csv.py
++
++csv-blank :
++	./make_blank_csv.py
++	@echo New blank csv signal table in csv/blank_route_table.csv
++
++c-files : comedi_h.py
++	./convert_csv_to_c.py --route_values --device_routes
++
++ROUTE_VALUES_SRC=$(wildcard ../ni_route_values/*.c)
++DEVICE_ROUTES_SRC=$(wildcard ../ni_device_routes/*.c)
++all_cfiles.c : $(DEVICE_ROUTES_SRC) $(ROUTE_VALUES_SRC)
++	@for i in $(DEVICE_ROUTES_SRC) $(ROUTE_VALUES_SRC); do \
++		echo "#include \"$$i\"" >> all_cfiles.c; \
++	done
++
++clean-partial :
++	$(RM) -rf comedi_h.py ni_values.py convert_c_to_py all_cfiles.c *.pyc \
++		__pycache__/
++
++clean : partial_clean
++	$(RM) -rf c/ csv/
++
++# Note:  One could also use ctypeslib in order to generate these files.  The
++# caveat is that ctypeslib does not do a great job at handling macro functions.
++# The make rules are as follows:
++# comedi.h.xml : ../../comedi.h
++# 	# note that we have to use PWD here to avoid h2xml finding a system
++# 	# installed version of the comedilib/comedi.h file
++# 	h2xml ${PWD}/../../comedi.h -c -D__user="" -D"BIT(x)=(1<<(x))" \
++# 		-o comedi.h.xml
++#
++# comedi_h.py : comedi.h.xml
++# 	xml2py ./comedi.h.xml -o comedi_h.py
++# clean :
++# 	rm -f comedi.h.xml comedi_h.py comedi_h.pyc
+diff --git a/drivers/staging/comedi/drivers/ni_routing/tools/convert_c_to_py.c b/drivers/staging/comedi/drivers/ni_routing/tools/convert_c_to_py.c
+new file mode 100644
+index 000000000000..dedb6f2fc678
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/tools/convert_c_to_py.c
+@@ -0,0 +1,159 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++
++typedef uint8_t u8;
++typedef uint16_t u16;
++typedef int8_t  s8;
++#define __user
++#define BIT(x)  (1UL << (x))
++
++#define NI_ROUTE_VALUE_EXTERNAL_CONVERSION 1
++
++#include "../ni_route_values.c"
++#include "../ni_device_routes.c"
++#include "all_cfiles.c"
++
++#include 
++
++#define RVij(rv, src, dest)	((rv)->register_values[(dest)][(src)])
++
++/*
++ * write out
++ * {
++ *   "family" : "",
++ *   "register_values": {
++ *      :[src0, src1, ...],
++ *      :[src0, src1, ...],
++ *      ...
++ *   }
++ * }
++ */
++void family_write(const struct family_route_values *rv, FILE *fp)
++{
++	fprintf(fp,
++		"  \"%s\" : {\n"
++		"    # dest -> {src0:val0, src1:val1, ...}\n"
++		, rv->family);
++	for (unsigned int dest = NI_NAMES_BASE;
++	     dest < (NI_NAMES_BASE + NI_NUM_NAMES);
++	     ++dest) {
++		unsigned int src = NI_NAMES_BASE;
++
++		for (; src < (NI_NAMES_BASE + NI_NUM_NAMES) &&
++		     RVij(rv, B(src), B(dest)) == 0; ++src)
++			;
++
++		if (src >= (NI_NAMES_BASE + NI_NUM_NAMES))
++			continue; /* no data here */
++
++		fprintf(fp, "    %u : {\n", dest);
++		for (src = NI_NAMES_BASE; src < (NI_NAMES_BASE + NI_NUM_NAMES);
++		     ++src) {
++			register_type r = RVij(rv, B(src), B(dest));
++			const char *M;
++
++			if (r == 0) {
++				continue;
++			} else if (MARKED_V(r)) {
++				M = "V";
++			} else if (MARKED_I(r)) {
++				M = "I";
++			} else if (MARKED_U(r)) {
++				M = "U";
++			} else {
++				fprintf(stderr,
++					"Invalid register marking %s[%u][%u] = %u\n",
++					rv->family, dest, src, r);
++				exit(1);
++			}
++
++			fprintf(fp, "      %u : \"%s(%u)\",\n",
++				src, M, UNMARK(r));
++		}
++		fprintf(fp, "    },\n");
++	}
++	fprintf(fp, "  },\n\n");
++}
++
++bool is_valid_ni_sig(unsigned int sig)
++{
++	return (sig >= NI_NAMES_BASE) && (sig < (NI_NAMES_BASE + NI_NUM_NAMES));
++}
++
++/*
++ * write out
++ * {
++ *   "family" : "",
++ *   "register_values": {
++ *      :[src0, src1, ...],
++ *      :[src0, src1, ...],
++ *      ...
++ *   }
++ * }
++ */
++void device_write(const struct ni_device_routes *dR, FILE *fp)
++{
++	fprintf(fp,
++		"  \"%s\" : {\n"
++		"    # dest -> [src0, src1, ...]\n"
++		, dR->device);
++
++	unsigned int i = 0;
++
++	while (dR->routes[i].dest != 0) {
++		if (!is_valid_ni_sig(dR->routes[i].dest)) {
++			fprintf(stderr,
++				"Invalid NI signal value [%u] for destination %s.[%u]\n",
++				dR->routes[i].dest, dR->device, i);
++			exit(1);
++		}
++
++		fprintf(fp, "    %u : [", dR->routes[i].dest);
++
++		unsigned int j = 0;
++
++		while (dR->routes[i].src[j] != 0) {
++			if (!is_valid_ni_sig(dR->routes[i].src[j])) {
++				fprintf(stderr,
++					"Invalid NI signal value [%u] for source %s.[%u].[%u]\n",
++					dR->routes[i].src[j], dR->device, i, j);
++				exit(1);
++			}
++
++			fprintf(fp, "%u,", dR->routes[i].src[j]);
++
++			++j;
++		}
++		fprintf(fp, "],\n");
++
++		++i;
++	}
++	fprintf(fp, "  },\n\n");
++}
++
++int main(void)
++{
++	FILE *fp = fopen("ni_values.py", "w");
++
++	/* write route register values */
++	fprintf(fp, "ni_route_values = {\n");
++	for (int i = 0; ni_all_route_values[i]; ++i)
++		family_write(ni_all_route_values[i], fp);
++	fprintf(fp, "}\n\n");
++
++	/* write valid device routes */
++	fprintf(fp, "ni_device_routes = {\n");
++	for (int i = 0; ni_device_routes_list[i]; ++i)
++		device_write(ni_device_routes_list[i], fp);
++	fprintf(fp, "}\n");
++
++	/* finish; close file */
++	fclose(fp);
++	return 0;
++}
+diff --git a/drivers/staging/comedi/drivers/ni_routing/tools/convert_csv_to_c.py b/drivers/staging/comedi/drivers/ni_routing/tools/convert_csv_to_c.py
+new file mode 100755
+index 000000000000..532eb6372a5a
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/tools/convert_csv_to_c.py
+@@ -0,0 +1,503 @@
++#!/usr/bin/env python3
++# SPDX-License-Identifier: GPL-2.0+
++# vim: ts=2:sw=2:et:tw=80:nowrap
++
++# This is simply to aide in creating the entries in the order of the value of
++# the device-global NI signal/terminal constants defined in comedi.h
++import comedi_h
++import os, sys, re
++from csv_collection import CSVCollection
++
++
++def c_to_o(filename, prefix='\t\t\t\t\t   ni_routing/', suffix=' \\'):
++  if not filename.endswith('.c'):
++    return ''
++  return prefix + filename.rpartition('.c')[0] + '.o' + suffix
++
++
++def routedict_to_structinit_single(name, D, return_name=False):
++  Locals = dict()
++  lines = [
++    '\t.family = "{}",'.format(name),
++    '\t.register_values = {',
++    '\t\t/*',
++    '\t\t * destination = {',
++	  '\t\t *              source          = register value,',
++	  '\t\t *              ...',
++	  '\t\t * }',
++		'\t\t */',
++  ]
++  if (False):
++    # print table with index0:src, index1:dest
++    D0 = D # (src-> dest->reg_value)
++    #D1 : destD
++  else:
++    D0 = dict()
++    for src, destD in D.items():
++      for dest, val in destD.items():
++        D0.setdefault(dest, {})[src] = val
++
++
++  D0 = sorted(D0.items(), key=lambda i: eval(i[0], comedi_h.__dict__, Locals))
++
++  for D0_sig, D1_D in D0:
++    D1 = sorted(D1_D.items(), key=lambda i: eval(i[0], comedi_h.__dict__, Locals))
++
++    lines.append('\t\t[B({})] = {{'.format(D0_sig))
++    for D1_sig, value in D1:
++      if not re.match('[VIU]\([^)]*\)', value):
++        sys.stderr.write('Invalid register format: {}\n'.format(repr(value)))
++        sys.stderr.write(
++          'Register values should be formatted with V(),I(),or U()\n')
++        raise RuntimeError('Invalid register values format')
++      lines.append('\t\t\t[B({})]\t= {},'.format(D1_sig, value))
++    lines.append('\t\t},')
++  lines.append('\t},')
++
++  lines = '\n'.join(lines)
++  if return_name:
++    return N, lines
++  else:
++    return lines
++
++
++def routedict_to_routelist_single(name, D, indent=1):
++  Locals = dict()
++
++  indents = dict(
++    I0 = '\t'*(indent),
++    I1 = '\t'*(indent+1),
++    I2 = '\t'*(indent+2),
++    I3 = '\t'*(indent+3),
++    I4 = '\t'*(indent+4),
++  )
++
++  if (False):
++    # data is src -> dest-list
++    D0 = D
++    keyname = 'src'
++    valname = 'dest'
++  else:
++    # data is dest -> src-list
++    keyname = 'dest'
++    valname = 'src'
++    D0 = dict()
++    for src, destD in D.items():
++      for dest, val in destD.items():
++        D0.setdefault(dest, {})[src] = val
++
++  # Sort by order of device-global names (numerically)
++  D0 = sorted(D0.items(), key=lambda i: eval(i[0], comedi_h.__dict__, Locals))
++
++  lines = [ '{I0}.device = "{name}",\n'
++            '{I0}.routes = (struct ni_route_set[]){{'
++            .format(name=name, **indents) ]
++  for D0_sig, D1_D in D0:
++    D1 = [ k for k,v in D1_D.items() if v ]
++    D1.sort(key=lambda i: eval(i, comedi_h.__dict__, Locals))
++
++    lines.append('{I1}{{\n{I2}.{keyname} = {D0_sig},\n'
++                         '{I2}.{valname} = (int[]){{'
++                 .format(keyname=keyname, valname=valname, D0_sig=D0_sig, **indents)
++    )
++    for D1_sig in D1:
++      lines.append( '{I3}{D1_sig},'.format(D1_sig=D1_sig, **indents) )
++    lines.append( '{I3}0, /* Termination */'.format(**indents) )
++
++    lines.append('{I2}}}\n{I1}}},'.format(**indents))
++
++  lines.append('{I1}{{ /* Termination of list */\n{I2}.{keyname} = 0,\n{I1}}},'
++               .format(keyname=keyname, **indents))
++
++  lines.append('{I0}}},'.format(**indents))
++
++  return '\n'.join(lines)
++
++
++class DeviceRoutes(CSVCollection):
++  MKFILE_SEGMENTS = 'device-route.mk'
++  SET_C = 'ni_device_routes.c'
++  ITEMS_DIR = 'ni_device_routes'
++  EXTERN_H = 'all.h'
++  OUTPUT_DIR = 'c'
++
++  output_file_top = """\
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/{filename}
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#include "ni_device_routes.h"
++#include "{extern_h}"\
++""".format(filename=SET_C, extern_h=os.path.join(ITEMS_DIR, EXTERN_H))
++
++  extern_header = """\
++/* SPDX-License-Identifier: GPL-2.0+ */
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/{filename}
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#ifndef _COMEDI_DRIVERS_NI_ROUTING_NI_DEVICE_ROUTES_EXTERN_H
++#define _COMEDI_DRIVERS_NI_ROUTING_NI_DEVICE_ROUTES_EXTERN_H
++
++#include "../ni_device_routes.h"
++
++{externs}
++
++#endif //_COMEDI_DRIVERS_NI_ROUTING_NI_DEVICE_ROUTES_EXTERN_H
++"""
++
++  single_output_file_top = """\
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/{filename}
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#include "../ni_device_routes.h"
++#include "{extern_h}"
++
++struct ni_device_routes {table_name} = {{\
++"""
++
++  def __init__(self, pattern='csv/device_routes/*.csv'):
++    super(DeviceRoutes,self).__init__(pattern)
++
++  def to_listinit(self):
++    chunks = [ self.output_file_top,
++      '',
++      'struct ni_device_routes *const ni_device_routes_list[] = {'
++    ]
++    # put the sheets in lexical order of device numbers then bus
++    sheets = sorted(self.items(), key=lambda i : tuple(i[0].split('-')[::-1]) )
++
++    externs = []
++    objs = [c_to_o(self.SET_C)]
++
++    for sheet,D in sheets:
++      S = sheet.lower()
++      dev_table_name = 'ni_{}_device_routes'.format(S.replace('-','_'))
++      sheet_filename = os.path.join(self.ITEMS_DIR,'{}.c'.format(S))
++      externs.append('extern struct ni_device_routes {};'.format(dev_table_name))
++
++      chunks.append('\t&{},'.format(dev_table_name))
++
++      s_chunks = [
++        self.single_output_file_top.format(
++          filename    = sheet_filename,
++          table_name  = dev_table_name,
++          extern_h    = self.EXTERN_H,
++        ),
++        routedict_to_routelist_single(S, D),
++        '};',
++      ]
++
++      objs.append(c_to_o(sheet_filename))
++
++      with open(os.path.join(self.OUTPUT_DIR, sheet_filename), 'w') as f:
++        f.write('\n'.join(s_chunks))
++        f.write('\n')
++
++    with open(os.path.join(self.OUTPUT_DIR, self.MKFILE_SEGMENTS), 'w') as f:
++      f.write('# This is the segment that should be included in comedi/drivers/Makefile\n')
++      f.write('ni_routing-objs\t\t\t\t+= \\\n')
++      f.write('\n'.join(objs))
++      f.write('\n')
++
++    EXTERN_H = os.path.join(self.ITEMS_DIR, self.EXTERN_H)
++    with open(os.path.join(self.OUTPUT_DIR, EXTERN_H), 'w') as f:
++      f.write(self.extern_header.format(
++        filename=EXTERN_H, externs='\n'.join(externs)))
++
++    chunks.append('\tNULL,') # terminate list
++    chunks.append('};')
++    return '\n'.join(chunks)
++
++  def save(self):
++    filename=os.path.join(self.OUTPUT_DIR, self.SET_C)
++
++    try:
++      os.makedirs(os.path.join(self.OUTPUT_DIR, self.ITEMS_DIR))
++    except:
++      pass
++    with open(filename,'w') as f:
++      f.write( self.to_listinit() )
++      f.write( '\n' )
++
++
++class RouteValues(CSVCollection):
++  MKFILE_SEGMENTS = 'route-values.mk'
++  SET_C = 'ni_route_values.c'
++  ITEMS_DIR = 'ni_route_values'
++  EXTERN_H = 'all.h'
++  OUTPUT_DIR = 'c'
++
++  output_file_top = """\
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/{filename}
++ *  Route information for NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * This file includes the tables that are a list of all the values of various
++ * signals routes available on NI hardware.  In many cases, one does not
++ * explicitly make these routes, rather one might indicate that something is
++ * used as the source of one particular trigger or another (using
++ * *_src=TRIG_EXT).
++ *
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#include "ni_route_values.h"
++#include "{extern_h}"\
++""".format(filename=SET_C, extern_h=os.path.join(ITEMS_DIR, EXTERN_H))
++
++  extern_header = """\
++/* SPDX-License-Identifier: GPL-2.0+ */
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/{filename}
++ *  List of valid routes for specific NI boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * The contents of this file are generated using the tools in
++ * comedi/drivers/ni_routing/tools
++ *
++ * Please use those tools to help maintain the contents of this file.
++ */
++
++#ifndef _COMEDI_DRIVERS_NI_ROUTING_NI_ROUTE_VALUES_EXTERN_H
++#define _COMEDI_DRIVERS_NI_ROUTING_NI_ROUTE_VALUES_EXTERN_H
++
++#include "../ni_route_values.h"
++
++{externs}
++
++#endif //_COMEDI_DRIVERS_NI_ROUTING_NI_ROUTE_VALUES_EXTERN_H
++"""
++
++  single_output_file_top = """\
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/ni_routing/{filename}
++ *  Route information for {sheet} boards.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++/*
++ * This file includes a list of all the values of various signals routes
++ * available on NI 660x hardware.  In many cases, one does not explicitly make
++ * these routes, rather one might indicate that something is used as the source
++ * of one particular trigger or another (using *_src=TRIG_EXT).
++ *
++ * The contents of this file can be generated using the tools in
++ * comedi/drivers/ni_routing/tools.  This file also contains specific notes to
++ * this family of devices.
++ *
++ * Please use those tools to help maintain the contents of this file, but be
++ * mindful to not lose the notes already made in this file, since these notes
++ * are critical to a complete undertsanding of the register values of this
++ * family.
++ */
++
++#include "../ni_route_values.h"
++#include "{extern_h}"
++
++const struct family_route_values {table_name} = {{\
++"""
++
++  def __init__(self, pattern='csv/route_values/*.csv'):
++    super(RouteValues,self).__init__(pattern)
++
++  def to_structinit(self):
++    chunks = [ self.output_file_top,
++      '',
++      'const struct family_route_values *const ni_all_route_values[] = {'
++    ]
++    # put the sheets in lexical order for consistency
++    sheets = sorted(self.items(), key=lambda i : i[0] )
++
++    externs = []
++    objs = [c_to_o(self.SET_C)]
++
++    for sheet,D in sheets:
++      S = sheet.lower()
++      fam_table_name = '{}_route_values'.format(S.replace('-','_'))
++      sheet_filename = os.path.join(self.ITEMS_DIR,'{}.c'.format(S))
++      externs.append('extern const struct family_route_values {};'.format(fam_table_name))
++
++      chunks.append('\t&{},'.format(fam_table_name))
++
++      s_chunks = [
++        self.single_output_file_top.format(
++          filename    = sheet_filename,
++          sheet       = sheet.upper(),
++          table_name  = fam_table_name,
++          extern_h    = self.EXTERN_H,
++        ),
++        routedict_to_structinit_single(S, D),
++        '};',
++      ]
++
++      objs.append(c_to_o(sheet_filename))
++
++      with open(os.path.join(self.OUTPUT_DIR, sheet_filename), 'w') as f:
++        f.write('\n'.join(s_chunks))
++        f.write( '\n' )
++
++    with open(os.path.join(self.OUTPUT_DIR, self.MKFILE_SEGMENTS), 'w') as f:
++      f.write('# This is the segment that should be included in comedi/drivers/Makefile\n')
++      f.write('ni_routing-objs\t\t\t\t+= \\\n')
++      f.write('\n'.join(objs))
++      f.write('\n')
++
++    EXTERN_H = os.path.join(self.ITEMS_DIR, self.EXTERN_H)
++    with open(os.path.join(self.OUTPUT_DIR, EXTERN_H), 'w') as f:
++      f.write(self.extern_header.format(
++        filename=EXTERN_H, externs='\n'.join(externs)))
++
++    chunks.append('\tNULL,') # terminate list
++    chunks.append('};')
++    return '\n'.join(chunks)
++
++  def save(self):
++    filename=os.path.join(self.OUTPUT_DIR, self.SET_C)
++
++    try:
++      os.makedirs(os.path.join(self.OUTPUT_DIR, self.ITEMS_DIR))
++    except:
++      pass
++    with open(filename,'w') as f:
++      f.write( self.to_structinit() )
++      f.write( '\n' )
++
++
++
++if __name__ == '__main__':
++  import argparse
++  parser = argparse.ArgumentParser()
++  parser.add_argument( '--route_values', action='store_true',
++    help='Extract route values from csv/route_values/*.csv' )
++  parser.add_argument( '--device_routes', action='store_true',
++    help='Extract route values from csv/device_routes/*.csv' )
++  args = parser.parse_args()
++  KL = list()
++  if args.route_values:
++    KL.append( RouteValues )
++  if args.device_routes:
++    KL.append( DeviceRoutes )
++  if not KL:
++    parser.error('nothing to do...')
++  for K in KL:
++    doc = K()
++    doc.save()
+diff --git a/drivers/staging/comedi/drivers/ni_routing/tools/convert_py_to_csv.py b/drivers/staging/comedi/drivers/ni_routing/tools/convert_py_to_csv.py
+new file mode 100755
+index 000000000000..b3e6472bac22
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/tools/convert_py_to_csv.py
+@@ -0,0 +1,67 @@
++#!/usr/bin/env python3
++# SPDX-License-Identifier: GPL-2.0+
++# vim: ts=2:sw=2:et:tw=80:nowrap
++
++from os import path
++import os, csv
++from itertools import chain
++
++from csv_collection import CSVCollection
++from ni_names import value_to_name
++import ni_values
++
++CSV_DIR = 'csv'
++
++def iter_src_values(D):
++  return D.items()
++
++def iter_src(D):
++  for dest in D:
++    yield dest, 1
++
++def create_csv(name, D, src_iter):
++  # have to change dest->{src:val} to src->{dest:val}
++  fieldnames = [value_to_name[i] for i in sorted(D.keys())]
++  fieldnames.insert(0, CSVCollection.source_column_name)
++
++  S = dict()
++  for dest, srcD in D.items():
++    for src,val in src_iter(srcD):
++      S.setdefault(src,{})[dest] = val
++
++  S = sorted(S.items(), key = lambda src_destD : src_destD[0])
++
++
++  csv_fname = path.join(CSV_DIR, name + '.csv')
++  with open(csv_fname, 'w') as F_csv:
++    dR = csv.DictWriter(F_csv, fieldnames, delimiter=';', quotechar='"')
++    dR.writeheader()
++
++    # now change the json back into the csv dictionaries
++    rows = [
++      dict(chain(
++        ((CSVCollection.source_column_name,value_to_name[src]),),
++        *(((value_to_name[dest],v),) for dest,v in destD.items())
++      ))
++      for src, destD in S
++    ]
++
++    dR.writerows(rows)
++
++
++def to_csv():
++  for d in ['route_values', 'device_routes']:
++    try:
++      os.makedirs(path.join(CSV_DIR,d))
++    except:
++      pass
++
++  for family, dst_src_map in ni_values.ni_route_values.items():
++    create_csv(path.join('route_values',family), dst_src_map, iter_src_values)
++
++  for device, dst_src_map in ni_values.ni_device_routes.items():
++    create_csv(path.join('device_routes',device), dst_src_map, iter_src)
++
++
++if __name__ == '__main__':
++  to_csv()
+diff --git a/drivers/staging/comedi/drivers/ni_routing/tools/csv_collection.py b/drivers/staging/comedi/drivers/ni_routing/tools/csv_collection.py
+new file mode 100644
+index 000000000000..12617329a928
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/tools/csv_collection.py
+@@ -0,0 +1,40 @@
++# SPDX-License-Identifier: GPL-2.0+
++# vim: ts=2:sw=2:et:tw=80:nowrap
++
++import os, csv, glob
++
++class CSVCollection(dict):
++  delimiter=';'
++  quotechar='"'
++  source_column_name = 'Sources / Destinations'
++
++  """
++  This class is a dictionary representation of the collection of sheets that
++  exist in a given .ODS file.
++  """
++  def __init__(self, pattern, skip_commented_lines=True, strip_lines=True):
++    super(CSVCollection, self).__init__()
++    self.pattern = pattern
++    C = '#' if skip_commented_lines else 'blahblahblah'
++
++    if strip_lines:
++      strip = lambda s:s.strip()
++    else:
++      strip = lambda s:s
++
++    # load all CSV files
++    key = self.source_column_name
++    for fname in glob.glob(pattern):
++      with open(fname) as F:
++        dR = csv.DictReader(F, delimiter=self.delimiter,
++                            quotechar=self.quotechar)
++        name = os.path.basename(fname).partition('.')[0]
++        D = {
++          r[key]:{f:strip(c) for f,c in r.items()
++                  if f != key and f[:1] not in ['', C] and
++                     strip(c)[:1] not in ['', C]}
++          for r in dR if r[key][:1] not in ['', C]
++        }
++        # now, go back through and eliminate all empty dictionaries
++        D = {k:v for k,v in D.items() if v}
++        self[name] = D
+diff --git a/drivers/staging/comedi/drivers/ni_routing/tools/make_blank_csv.py b/drivers/staging/comedi/drivers/ni_routing/tools/make_blank_csv.py
+new file mode 100755
+index 000000000000..89c90a0ba24d
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/tools/make_blank_csv.py
+@@ -0,0 +1,32 @@
++#!/usr/bin/env python3
++# SPDX-License-Identifier: GPL-2.0+
++# vim: ts=2:sw=2:et:tw=80:nowrap
++
++from os import path
++import os, csv
++
++from csv_collection import CSVCollection
++from ni_names import value_to_name
++
++CSV_DIR = 'csv'
++
++def to_csv():
++  try:
++    os.makedirs(CSV_DIR)
++  except:
++    pass
++
++  csv_fname = path.join(CSV_DIR, 'blank_route_table.csv')
++
++  fieldnames = [sig for sig_val, sig in sorted(value_to_name.items())]
++  fieldnames.insert(0, CSVCollection.source_column_name)
++
++  with open(csv_fname, 'w') as F_csv:
++    dR = csv.DictWriter(F_csv, fieldnames, delimiter=';', quotechar='"')
++    dR.writeheader()
++
++    for sig in fieldnames[1:]:
++      dR.writerow({CSVCollection.source_column_name: sig})
++
++if __name__ == '__main__':
++  to_csv()
+diff --git a/drivers/staging/comedi/drivers/ni_routing/tools/ni_names.py b/drivers/staging/comedi/drivers/ni_routing/tools/ni_names.py
+new file mode 100644
+index 000000000000..5f9b825968b1
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/ni_routing/tools/ni_names.py
+@@ -0,0 +1,56 @@
++# SPDX-License-Identifier: GPL-2.0+
++# vim: ts=2:sw=2:et:tw=80:nowrap
++"""
++This file helps to extract string names of NI signals as included in comedi.h
++between NI_NAMES_BASE and NI_NAMES_BASE+NI_NUM_NAMES.
++"""
++
++# This is simply to aide in creating the entries in the order of the value of
++# the device-global NI signal/terminal constants defined in comedi.h
++import comedi_h
++
++
++ni_macros = (
++  'NI_PFI',
++  'TRIGGER_LINE',
++  'NI_RTSI_BRD',
++  'NI_CtrSource',
++  'NI_CtrGate',
++  'NI_CtrAux',
++  'NI_CtrA',
++  'NI_CtrB',
++  'NI_CtrZ',
++  'NI_CtrArmStartTrigger',
++  'NI_CtrInternalOutput',
++  'NI_CtrOut',
++  'NI_CtrSampleClock',
++)
++
++def get_ni_names():
++  name_dict = dict()
++
++  # load all the static names; start with those that do not begin with NI_
++  name_dict['PXI_Star'] = comedi_h.PXI_Star
++  name_dict['PXI_Clk10'] = comedi_h.PXI_Clk10
++
++  #load all macro values
++  for fun in ni_macros:
++    f = getattr(comedi_h, fun)
++    name_dict.update({
++      '{}({})'.format(fun,i):f(i) for i in range(1 + f(-1) - f(0))
++    })
++
++  #load everything else in ni_common_signal_names enum
++  name_dict.update({
++    k:v for k,v in comedi_h.__dict__.items()
++    if k.startswith('NI_') and (not callable(v)) and
++       comedi_h.NI_COUNTER_NAMES_MAX < v < (comedi_h.NI_NAMES_BASE + comedi_h.NI_NUM_NAMES)
++  })
++
++  # now create reverse lookup (value -> name)
++
++  val_dict = {v:k for k,v in name_dict.items()}
++
++  return name_dict, val_dict
++
++name_to_value, value_to_name = get_ni_names()

commit d7569ad766511fe708a8bd7476baa305d1510daf
+Author: Spencer E. Olson 
+Date:   Wed Oct 3 14:56:02 2018 -0600
+
+    staging: comedi: add new device-global config interface
+    
+    Adds interface for configuring options that are global to all sub-devices.
+    For now, only options to configure device-globally identified signal routes
+    have been defined.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
+index e9ce395836ec..e90b17775284 100644
+--- a/drivers/staging/comedi/comedi.h
++++ b/drivers/staging/comedi/comedi.h
+@@ -107,6 +107,7 @@
+ #define INSN_WRITE		(1 | INSN_MASK_WRITE)
+ #define INSN_BITS		(2 | INSN_MASK_READ | INSN_MASK_WRITE)
+ #define INSN_CONFIG		(3 | INSN_MASK_READ | INSN_MASK_WRITE)
++#define INSN_DEVICE_CONFIG	(INSN_CONFIG | INSN_MASK_SPECIAL)
+ #define INSN_GTOD		(4 | INSN_MASK_READ | INSN_MASK_SPECIAL)
+ #define INSN_WAIT		(5 | INSN_MASK_WRITE | INSN_MASK_SPECIAL)
+ #define INSN_INTTRIG		(6 | INSN_MASK_WRITE | INSN_MASK_SPECIAL)
+@@ -350,6 +351,23 @@ enum configuration_ids {
+ 	INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS = 5005,
+ };
+ 
++/**
++ * enum device_configuration_ids - COMEDI configuration instruction codes global
++ * to an entire device.
++ * @INSN_DEVICE_CONFIG_TEST_ROUTE:	Validate the possibility of a
++ *					globally-named route
++ * @INSN_DEVICE_CONFIG_CONNECT_ROUTE:	Connect a globally-named route
++ * @INSN_DEVICE_CONFIG_DISCONNECT_ROUTE:Disconnect a globally-named route
++ * @INSN_DEVICE_CONFIG_GET_ROUTES:	Get a list of all globally-named routes
++ *					that are valid for a particular device.
++ */
++enum device_config_route_ids {
++	INSN_DEVICE_CONFIG_TEST_ROUTE = 0,
++	INSN_DEVICE_CONFIG_CONNECT_ROUTE = 1,
++	INSN_DEVICE_CONFIG_DISCONNECT_ROUTE = 2,
++	INSN_DEVICE_CONFIG_GET_ROUTES = 3,
++};
++
+ /**
+  * enum comedi_digital_trig_op - operations for configuring a digital trigger
+  * @COMEDI_DIGITAL_TRIG_DISABLE:	Return digital trigger to its default,
+diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
+index 548baa790507..c1c6b2b4ab91 100644
+--- a/drivers/staging/comedi/comedi_fops.c
++++ b/drivers/staging/comedi/comedi_fops.c
+@@ -1234,6 +1234,57 @@ static int check_insn_config_length(struct comedi_insn *insn,
+ 	return -EINVAL;
+ }
+ 
++static int check_insn_device_config_length(struct comedi_insn *insn,
++					   unsigned int *data)
++{
++	if (insn->n < 1)
++		return -EINVAL;
++
++	switch (data[0]) {
++	case INSN_DEVICE_CONFIG_TEST_ROUTE:
++	case INSN_DEVICE_CONFIG_CONNECT_ROUTE:
++	case INSN_DEVICE_CONFIG_DISCONNECT_ROUTE:
++		if (insn->n == 3)
++			return 0;
++		break;
++	case INSN_DEVICE_CONFIG_GET_ROUTES:
++		/*
++		 * Big enough for config_id and the length of the userland
++		 * memory buffer.  Additional length should be in factors of 2
++		 * to communicate any returned route pairs (source,destination).
++		 */
++		if (insn->n >= 2)
++			return 0;
++		break;
++	}
++	return -EINVAL;
++}
++
++/**
++ * get_valid_routes() - Calls low-level driver get_valid_routes function to
++ *			either return a count of valid routes to user, or copy
++ *			of list of all valid device routes to buffer in
++ *			userspace.
++ * @dev: comedi device pointer
++ * @data: data from user insn call.  The length of the data must be >= 2.
++ *	  data[0] must contain the INSN_DEVICE_CONFIG config_id.
++ *	  data[1](input) contains the number of _pairs_ for which memory is
++ *		  allotted from the user.  If the user specifies '0', then only
++ *		  the number of pairs available is returned.
++ *	  data[1](output) returns either the number of pairs available (if none
++ *		  where requested) or the number of _pairs_ that are copied back
++ *		  to the user.
++ *	  data[2::2] returns each (source, destination) pair.
++ *
++ * Return: -EINVAL if low-level driver does not allocate and return routes as
++ *	   expected.  Returns 0 otherwise.
++ */
++static int get_valid_routes(struct comedi_device *dev, unsigned int *data)
++{
++	data[1] = dev->get_valid_routes(dev, data[1], data + 2);
++	return 0;
++}
++
+ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn,
+ 		      unsigned int *data, void *file)
+ {
+@@ -1297,6 +1348,24 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn,
+ 			if (ret >= 0)
+ 				ret = 1;
+ 			break;
++		case INSN_DEVICE_CONFIG:
++			ret = check_insn_device_config_length(insn, data);
++			if (ret)
++				break;
++
++			if (data[0] == INSN_DEVICE_CONFIG_GET_ROUTES) {
++				/*
++				 * data[1] should be the number of _pairs_ that
++				 * the memory can hold.
++				 */
++				data[1] = (insn->n - 2) / 2;
++				ret = get_valid_routes(dev, data);
++				break;
++			}
++
++			/* other global device config instructions. */
++			ret = dev->insn_device_config(dev, insn, data);
++			break;
+ 		default:
+ 			dev_dbg(dev->class_dev, "invalid insn\n");
+ 			ret = -EINVAL;
+diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
+index 5775a93917f4..a7d569cfca5d 100644
+--- a/drivers/staging/comedi/comedidev.h
++++ b/drivers/staging/comedi/comedidev.h
+@@ -516,6 +516,15 @@ struct comedi_driver {
+  *	called when @use_count changes from 0 to 1.
+  * @close: Optional pointer to a function set by the low-level driver to be
+  *	called when @use_count changed from 1 to 0.
++ * @insn_device_config: Optional pointer to a handler for all sub-instructions
++ *	except %INSN_DEVICE_CONFIG_GET_ROUTES of the %INSN_DEVICE_CONFIG
++ *	instruction.  If this is not initialized by the low-level driver, a
++ *	default handler will be set during post-configuration.
++ * @get_valid_routes: Optional pointer to a handler for the
++ *	%INSN_DEVICE_CONFIG_GET_ROUTES sub-instruction of the
++ *	%INSN_DEVICE_CONFIG instruction set.  If this is not initialized by the
++ *	low-level driver, a default handler that copies zero routes back to the
++ *	user will be used.
+  *
+  * This is the main control data structure for a COMEDI device (as far as the
+  * COMEDI core is concerned).  There are two groups of COMEDI devices -
+@@ -565,6 +574,11 @@ struct comedi_device {
+ 
+ 	int (*open)(struct comedi_device *dev);
+ 	void (*close)(struct comedi_device *dev);
++	int (*insn_device_config)(struct comedi_device *dev,
++				  struct comedi_insn *insn, unsigned int *data);
++	unsigned int (*get_valid_routes)(struct comedi_device *dev,
++					 unsigned int n_pairs,
++					 unsigned int *pair_data);
+ };
+ 
+ /*
+diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
+index 57dd63d548b7..eefa62f42c0f 100644
+--- a/drivers/staging/comedi/drivers.c
++++ b/drivers/staging/comedi/drivers.c
+@@ -211,6 +211,19 @@ static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s)
+ 	return -EINVAL;
+ }
+ 
++static int insn_device_inval(struct comedi_device *dev,
++			     struct comedi_insn *insn, unsigned int *data)
++{
++	return -EINVAL;
++}
++
++static unsigned int get_zero_valid_routes(struct comedi_device *dev,
++					  unsigned int n_pairs,
++					  unsigned int *pair_data)
++{
++	return 0;
++}
++
+ int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	       struct comedi_insn *insn, unsigned int *data)
+ {
+@@ -652,6 +665,12 @@ static int __comedi_device_postconfig(struct comedi_device *dev)
+ 	int ret;
+ 	int i;
+ 
++	if (!dev->insn_device_config)
++		dev->insn_device_config = insn_device_inval;
++
++	if (!dev->get_valid_routes)
++		dev->get_valid_routes = get_zero_valid_routes;
++
+ 	for (i = 0; i < dev->n_subdevices; i++) {
+ 		s = &dev->subdevices[i];
+ 

commit 5912827dfe78a0befae8a5e44f419eaf3deced72
+Author: Spencer E. Olson 
+Date:   Wed Oct 3 14:56:01 2018 -0600
+
+    staging: comedi: add abstracted NI signal/terminal named constants
+    
+    This change adds abstracted constants for National Instruments
+    terminal/signal names.
+    
+    Some background:
+      There have been significant confusions over the past many years for users
+      when trying to understand how to connect to/from signals and terminals on
+      NI hardware using comedi.  The major reason for this is that the actual
+      register values were exposed and required to be used by users.  Several
+      major reasons exist why this caused major confusion for users:
+    
+      1) The register values are _NOT_ in user documentation, but rather in
+        arcane locations, such as a few register programming manuals that are
+        increasingly hard to find and the NI-MHDDK (comments in in example
+        code).  There is no one place to find the various valid values of the
+        registers.
+    
+      2) The register values are _NOT_ completely consistent.  There is no way
+        to gain any sense of intuition of which values, or even enums one
+        should use for various registers.  There was some attempt in prior use
+        of comedi to name enums such that a user might know which enums should
+        be used for varying purposes, but the end-user had to gain a knowledge
+        of register values to correctly wield this approach.
+    
+      3) The names for signals and registers found in the various register
+        level programming manuals and vendor-provided documentation are _not_
+        even close to the same names that are in the end-user documentation.
+    
+    Similar confusion, albeit less, plagued NI's previous version of their own
+    proprietary drivers.  Earlier than 2003, NI greatly simplified the
+    situation for users by releasing a new API that abstracted the names of
+    signals/terminals to a common and intuitive set of names.  In addition,
+    this new API provided a much more common interface to use for most of NI
+    hardware.
+    
+    The names added here mirror the names chosen and well documented by NI.
+    These names are exposed to the user via the comedilib user library.  By
+    keeping the names in this format, in spite of the use of CamelScript,
+    maintenance will be greatly eased and confusion for users _and_ comedi
+    developers will be greatly reduced.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
+index cf7b2b970327..e9ce395836ec 100644
+--- a/drivers/staging/comedi/comedi.h
++++ b/drivers/staging/comedi/comedi.h
+@@ -931,6 +931,157 @@ enum i8254_mode {
+ 	I8254_BINARY = 0
+ };
+ 
++/* *** BEGIN GLOBALLY-NAMED NI TERMINALS/SIGNALS *** */
++
++/*
++ * Common National Instruments Terminal/Signal names.
++ * Some of these have no NI_ prefix as they are useful for non-NI hardware, such
++ * as those that utilize the PXI/RTSI trigger lines.
++ *
++ * NOTE ABOUT THE CHOICE OF NAMES HERE AND THE CAMELSCRIPT:
++ *   The choice to use CamelScript and the exact names below is for
++ *   maintainability, clarity, similarity to manufacturer's documentation,
++ *   _and_ a mitigation for confusion that has plagued the use of these drivers
++ *   for years!
++ *
++ *   More detail:
++ *   There have been significant confusions over the past many years for users
++ *   when trying to understand how to connect to/from signals and terminals on
++ *   NI hardware using comedi.  The major reason for this is that the actual
++ *   register values were exposed and required to be used by users.  Several
++ *   major reasons exist why this caused major confusion for users:
++ *   1) The register values are _NOT_ in user documentation, but rather in
++ *     arcane locations, such as a few register programming manuals that are
++ *     increasingly hard to find and the NI MHDDK (comments in in example code).
++ *     There is no one place to find the various valid values of the registers.
++ *   2) The register values are _NOT_ completely consistent.  There is no way to
++ *     gain any sense of intuition of which values, or even enums one should use
++ *     for various registers.  There was some attempt in prior use of comedi to
++ *     name enums such that a user might know which enums should be used for
++ *     varying purposes, but the end-user had to gain a knowledge of register
++ *     values to correctly wield this approach.
++ *   3) The names for signals and registers found in the various register level
++ *     programming manuals and vendor-provided documentation are _not_ even
++ *     close to the same names that are in the end-user documentation.
++ *
++ *   Similar, albeit less, confusion plagued NI's previous version of their own
++ *   drivers.  Earlier than 2003, NI greatly simplified the situation for users
++ *   by releasing a new API that abstracted the names of signals/terminals to a
++ *   common and intuitive set of names.
++ *
++ *   The names below mirror the names chosen and well documented by NI.  These
++ *   names are exposed to the user via the comedilib user library.  By keeping
++ *   the names below, in spite of the use of CamelScript, maintenance will be
++ *   greatly eased and confusion for users _and_ comedi developers will be
++ *   greatly reduced.
++ */
++
++/*
++ * Base of abstracted NI names.
++ * The first 16 bits of *_arg are reserved for channel selection.
++ * Since we only actually need the first 4 or 5 bits for all register values on
++ * NI select registers anyways, we'll identify all values >= (1<<15) as being an
++ * abstracted NI signal/terminal name.
++ * These values are also used/returned by INSN_DEVICE_CONFIG_TEST_ROUTE,
++ * INSN_DEVICE_CONFIG_CONNECT_ROUTE, INSN_DEVICE_CONFIG_DISCONNECT_ROUTE,
++ * and INSN_DEVICE_CONFIG_GET_ROUTES.
++ */
++#define NI_NAMES_BASE	0x8000u
++/*
++ * not necessarily all allowed 64 PFIs are valid--certainly not for all devices
++ */
++#define NI_PFI(x)	(NI_NAMES_BASE        + ((x) & 0x3f))
++/* 8 trigger lines by standard, Some devices cannot talk to all eight. */
++#define TRIGGER_LINE(x)	(NI_PFI(-1)       + 1 + ((x) & 0x7))
++/* 4 RTSI shared MUXes to route signals to/from TRIGGER_LINES on NI hardware */
++#define NI_RTSI_BRD(x)	(TRIGGER_LINE(-1) + 1 + ((x) & 0x3))
++
++/* *** Counter/timer names : 8 counters max *** */
++#define NI_COUNTER_NAMES_BASE  (NI_RTSI_BRD(-1)  + 1)
++#define NI_MAX_COUNTERS	       7
++#define NI_CtrSource(x)	       (NI_COUNTER_NAMES_BASE + ((x) & NI_MAX_COUNTERS))
++/* Gate, Aux, A,B,Z are all treated, at times as gates */
++#define NI_GATES_NAMES_BASE    (NI_CtrSource(-1) + 1)
++#define NI_CtrGate(x)	       (NI_GATES_NAMES_BASE   + ((x) & NI_MAX_COUNTERS))
++#define NI_CtrAux(x)	       (NI_CtrGate(-1)   + 1  + ((x) & NI_MAX_COUNTERS))
++#define NI_CtrA(x)	       (NI_CtrAux(-1)    + 1  + ((x) & NI_MAX_COUNTERS))
++#define NI_CtrB(x)	       (NI_CtrA(-1)      + 1  + ((x) & NI_MAX_COUNTERS))
++#define NI_CtrZ(x)	       (NI_CtrB(-1)      + 1  + ((x) & NI_MAX_COUNTERS))
++#define NI_GATES_NAMES_MAX     NI_CtrZ(-1)
++#define NI_CtrArmStartTrigger(x) (NI_CtrZ(-1)    + 1  + ((x) & NI_MAX_COUNTERS))
++#define NI_CtrInternalOutput(x) \
++		     (NI_CtrArmStartTrigger(-1)  + 1  + ((x) & NI_MAX_COUNTERS))
++/** external pin(s) labeled conveniently as CtrOut. */
++#define NI_CtrOut(x)  (NI_CtrInternalOutput(-1)  + 1  + ((x) & NI_MAX_COUNTERS))
++/** For Buffered sampling of ctr -- x series capability. */
++#define NI_CtrSampleClock(x)	(NI_CtrOut(-1)   + 1  + ((x) & NI_MAX_COUNTERS))
++#define NI_COUNTER_NAMES_MAX   NI_CtrSampleClock(-1)
++
++enum ni_common_signal_names {
++	/* PXI_Star: this is a non-NI-specific signal */
++	PXI_Star = NI_COUNTER_NAMES_MAX + 1,
++	PXI_Clk10,
++	PXIe_Clk100,
++	NI_AI_SampleClock,
++	NI_AI_SampleClockTimebase,
++	NI_AI_StartTrigger,
++	NI_AI_ReferenceTrigger,
++	NI_AI_ConvertClock,
++	NI_AI_ConvertClockTimebase,
++	NI_AI_PauseTrigger,
++	NI_AI_HoldCompleteEvent,
++	NI_AI_HoldComplete,
++	NI_AI_ExternalMUXClock,
++	NI_AI_STOP, /* pulse signal that occurs when a update is finished(?) */
++	NI_AO_SampleClock,
++	NI_AO_SampleClockTimebase,
++	NI_AO_StartTrigger,
++	NI_AO_PauseTrigger,
++	NI_DI_SampleClock,
++	NI_DI_SampleClockTimebase,
++	NI_DI_StartTrigger,
++	NI_DI_ReferenceTrigger,
++	NI_DI_PauseTrigger,
++	NI_DI_InputBufferFull,
++	NI_DI_ReadyForStartEvent,
++	NI_DI_ReadyForTransferEventBurst,
++	NI_DI_ReadyForTransferEventPipelined,
++	NI_DO_SampleClock,
++	NI_DO_SampleClockTimebase,
++	NI_DO_StartTrigger,
++	NI_DO_PauseTrigger,
++	NI_DO_OutputBufferFull,
++	NI_DO_DataActiveEvent,
++	NI_DO_ReadyForStartEvent,
++	NI_DO_ReadyForTransferEvent,
++	NI_MasterTimebase,
++	NI_20MHzTimebase,
++	NI_80MHzTimebase,
++	NI_100MHzTimebase,
++	NI_200MHzTimebase,
++	NI_100kHzTimebase,
++	NI_10MHzRefClock,
++	NI_FrequencyOutput,
++	NI_ChangeDetectionEvent,
++	NI_AnalogComparisonEvent,
++	NI_WatchdogExpiredEvent,
++	NI_WatchdogExpirationTrigger,
++	NI_SCXI_Trig1,
++	NI_LogicLow,
++	NI_LogicHigh,
++	NI_ExternalStrobe,
++	NI_PFI_DO,
++	NI_CaseGround,
++	/* special internal signal used as variable source for RTSI bus: */
++	NI_RGOUT0,
++
++	/* just a name to make the next more convenient, regardless of above */
++	_NI_NAMES_MAX_PLUS_1,
++	NI_NUM_NAMES = _NI_NAMES_MAX_PLUS_1 - NI_NAMES_BASE,
++};
++
++/* *** END GLOBALLY-NAMED NI TERMINALS/SIGNALS *** */
++
+ #define NI_USUAL_PFI_SELECT(x)	(((x) < 10) ? (0x1 + (x)) : (0xb + (x)))
+ #define NI_USUAL_RTSI_SELECT(x)	(((x) < 7) ? (0xb + (x)) : 0x1b)
+ 

commit 040e9e4dfa14de632824b9368462c1bd20d05733
+Author: Spencer E. Olson 
+Date:   Wed Oct 3 14:56:00 2018 -0600
+
+    staging: comedi: tests: add unittest framework for comedi
+    
+    Adds a framework for unittests for comedi drivers.  It was certainly
+    possible to write some unit tests before and test various aspects of a
+    particular driver, but this framework makes this a bit easier and hopefully
+    inspires more unittest modules to be written.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile
+index 98b42b47dfe1..8cb518190fc7 100644
+--- a/drivers/staging/comedi/drivers/Makefile
++++ b/drivers/staging/comedi/drivers/Makefile
+@@ -145,3 +145,4 @@ obj-$(CONFIG_COMEDI_8255_SA)		+= 8255.o
+ obj-$(CONFIG_COMEDI_AMPLC_DIO200)	+= amplc_dio200_common.o
+ obj-$(CONFIG_COMEDI_AMPLC_PC236)	+= amplc_pc236_common.o
+ obj-$(CONFIG_COMEDI_DAS08)		+= das08.o
++obj-$(CONFIG_COMEDI_TESTS)		+= tests/
+diff --git a/drivers/staging/comedi/drivers/tests/Makefile b/drivers/staging/comedi/drivers/tests/Makefile
+new file mode 100644
+index 000000000000..1d58ede0bdf6
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/tests/Makefile
+@@ -0,0 +1,6 @@
++# SPDX-License-Identifier: GPL-2.0
++# Makefile for comedi drivers unit tests
++#
++ccflags-$(CONFIG_COMEDI_DEBUG)		:= -DDEBUG
++
++obj-$(CONFIG_COMEDI_TESTS)		+= example_test.o
+diff --git a/drivers/staging/comedi/drivers/tests/example_test.c b/drivers/staging/comedi/drivers/tests/example_test.c
+new file mode 100644
+index 000000000000..fc65158b8e8e
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/tests/example_test.c
+@@ -0,0 +1,72 @@
++// SPDX-License-Identifier: GPL-2.0+
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/tests/example_test.c
++ *  Example set of unit tests.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++#include 
++
++#include "unittest.h"
++
++/* *** BEGIN fake board data *** */
++struct comedi_device {
++	const char *board_name;
++	int item;
++};
++
++static struct comedi_device dev = {
++	.board_name = "fake_device",
++};
++
++/* *** END fake board data *** */
++
++/* *** BEGIN fake data init *** */
++void init_fake(void)
++{
++	dev.item = 10;
++}
++
++/* *** END fake data init *** */
++
++void test0(void)
++{
++	init_fake();
++	unittest(dev.item != 11, "negative result\n");
++	unittest(dev.item == 10, "positive result\n");
++}
++
++/* **** BEGIN simple module entry/exit functions **** */
++static int __init unittest_enter(void)
++{
++	const unittest_fptr unit_tests[] = {
++		(unittest_fptr)test0,
++		NULL,
++	};
++
++	exec_unittests("example", unit_tests);
++	return 0;
++}
++
++static void __exit unittest_exit(void) { }
++
++module_init(unittest_enter);
++module_exit(unittest_exit);
++
++MODULE_AUTHOR("Spencer Olson ");
++MODULE_DESCRIPTION("Comedi unit-tests example");
++MODULE_LICENSE("GPL");
++/* **** END simple module entry/exit functions **** */
+diff --git a/drivers/staging/comedi/drivers/tests/unittest.h b/drivers/staging/comedi/drivers/tests/unittest.h
+new file mode 100644
+index 000000000000..b8e622ea1de1
+--- /dev/null
++++ b/drivers/staging/comedi/drivers/tests/unittest.h
+@@ -0,0 +1,63 @@
++/* SPDX-License-Identifier: GPL-2.0+ */
++/* vim: set ts=8 sw=8 noet tw=80 nowrap: */
++/*
++ *  comedi/drivers/tests/unittest.h
++ *  Simple framework for unittests for comedi drivers.
++ *
++ *  COMEDI - Linux Control and Measurement Device Interface
++ *  Copyright (C) 2016 Spencer E. Olson 
++ *  based of parts of drivers/of/unittest.c
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ */
++
++#ifndef _COMEDI_DRIVERS_TESTS_UNITTEST_H
++#define _COMEDI_DRIVERS_TESTS_UNITTEST_H
++
++static struct unittest_results {
++	int passed;
++	int failed;
++} unittest_results;
++
++typedef void *(*unittest_fptr)(void);
++
++#define unittest(result, fmt, ...) ({ \
++	bool failed = !(result); \
++	if (failed) { \
++		++unittest_results.failed; \
++		pr_err("FAIL %s():%i " fmt, __func__, __LINE__, \
++		       ##__VA_ARGS__); \
++	} else { \
++		++unittest_results.passed; \
++		pr_debug("pass %s():%i " fmt, __func__, __LINE__, \
++			 ##__VA_ARGS__); \
++	} \
++	failed; \
++})
++
++/**
++ * Execute an array of unit tests.
++ * @name:	Name of set of unit tests--will be shown at INFO log level.
++ * @unit_tests:	A null-terminated list of unit tests to execute.
++ */
++static inline void exec_unittests(const char *name,
++				  const unittest_fptr *unit_tests)
++{
++	pr_info("begin comedi:\"%s\" unittests\n", name);
++
++	for (; (*unit_tests) != NULL; ++unit_tests)
++		(*unit_tests)();
++
++	pr_info("end of comedi:\"%s\" unittests - %i passed, %i failed\n", name,
++		unittest_results.passed, unittest_results.failed);
++}
++
++#endif /* _COMEDI_DRIVERS_TESTS_UNITTEST_H */

commit e0b2ca8979c4b923d28eb4daa3a783463debd31c
+Author: Spencer E. Olson 
+Date:   Wed Sep 19 10:51:06 2018 -0600
+
+    staging: comedi: comedi_test: implement INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS
+    
+    Adds implementation of the new INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS
+    instruction.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c
+index d437af721bd8..ef4c7c8a2b71 100644
+--- a/drivers/staging/comedi/drivers/comedi_test.c
++++ b/drivers/staging/comedi/drivers/comedi_test.c
+@@ -626,6 +626,48 @@ static int waveform_ao_insn_write(struct comedi_device *dev,
+ 	return insn->n;
+ }
+ 
++static int waveform_ai_insn_config(struct comedi_device *dev,
++				   struct comedi_subdevice *s,
++				   struct comedi_insn *insn,
++				   unsigned int *data)
++{
++	if (data[0] == INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS) {
++		/*
++		 * input:  data[1], data[2] : scan_begin_src, convert_src
++		 * output: data[1], data[2] : scan_begin_min, convert_min
++		 */
++		if (data[1] == TRIG_FOLLOW) {
++			/* exactly TRIG_FOLLOW case */
++			data[1] = 0;
++			data[2] = NSEC_PER_USEC;
++		} else {
++			data[1] = NSEC_PER_USEC;
++			if (data[2] & TRIG_TIMER)
++				data[2] = NSEC_PER_USEC;
++			else
++				data[2] = 0;
++		}
++		return 0;
++	}
++
++	return -EINVAL;
++}
++
++static int waveform_ao_insn_config(struct comedi_device *dev,
++				   struct comedi_subdevice *s,
++				   struct comedi_insn *insn,
++				   unsigned int *data)
++{
++	if (data[0] == INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS) {
++		/* we don't care about actual channels */
++		data[1] = NSEC_PER_USEC; /* scan_begin_min */
++		data[2] = 0;		 /* convert_min */
++		return 0;
++	}
++
++	return -EINVAL;
++}
++
+ static int waveform_common_attach(struct comedi_device *dev,
+ 				  int amplitude, int period)
+ {
+@@ -658,6 +700,7 @@ static int waveform_common_attach(struct comedi_device *dev,
+ 	s->do_cmd = waveform_ai_cmd;
+ 	s->do_cmdtest = waveform_ai_cmdtest;
+ 	s->cancel = waveform_ai_cancel;
++	s->insn_config = waveform_ai_insn_config;
+ 
+ 	s = &dev->subdevices[1];
+ 	dev->write_subdev = s;
+@@ -673,6 +716,7 @@ static int waveform_common_attach(struct comedi_device *dev,
+ 	s->do_cmd = waveform_ao_cmd;
+ 	s->do_cmdtest = waveform_ao_cmdtest;
+ 	s->cancel = waveform_ao_cancel;
++	s->insn_config = waveform_ao_insn_config;
+ 
+ 	/* Our default loopback value is just a 0V flatline */
+ 	for (i = 0; i < s->n_chan; i++)

commit 3ad53c40902005c50122be34e2b60dd763314180
+Author: Spencer E. Olson 
+Date:   Wed Sep 19 10:51:05 2018 -0600
+
+    staging: comedi: ni_pcidio: implement INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS
+    
+    Adds implementation of the new INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS
+    instruction.  This patch also adds data for this implementation, based on
+    spec sheets from NI.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
+index 6692af5ff79b..b9a0dc6eac44 100644
+--- a/drivers/staging/comedi/drivers/ni_pcidio.c
++++ b/drivers/staging/comedi/drivers/ni_pcidio.c
+@@ -260,18 +260,22 @@ enum nidio_boardid {
+ struct nidio_board {
+ 	const char *name;
+ 	unsigned int uses_firmware:1;
++	unsigned int dio_speed;
+ };
+ 
+ static const struct nidio_board nidio_boards[] = {
+ 	[BOARD_PCIDIO_32HS] = {
+ 		.name		= "pci-dio-32hs",
++		.dio_speed	= 50,
+ 	},
+ 	[BOARD_PXI6533] = {
+ 		.name		= "pxi-6533",
++		.dio_speed	= 50,
+ 	},
+ 	[BOARD_PCI6534] = {
+ 		.name		= "pci-6534",
+ 		.uses_firmware	= 1,
++		.dio_speed	= 50,
+ 	},
+ };
+ 
+@@ -467,6 +471,15 @@ static int ni_pcidio_insn_config(struct comedi_device *dev,
+ {
+ 	int ret;
+ 
++	if (data[0] == INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS) {
++		const struct nidio_board *board = dev->board_ptr;
++
++		/* we don't care about actual channels */
++		data[1] = board->dio_speed;
++		data[2] = 0;
++		return 0;
++	}
++
+ 	ret = comedi_dio_insn_config(dev, s, insn, data, 0);
+ 	if (ret)
+ 		return ret;

commit 51fd3673838396844f15de0e906be5333bfbbc8d
+Author: Spencer E. Olson 
+Date:   Wed Sep 19 10:51:04 2018 -0600
+
+    staging: comedi: ni_mio_common: implement INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS
+    
+    Adds implementation of the new INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS
+    instruction.  This patch also adds data for digital subdevices that are
+    streaming capable (within the ni_mio_* family).  Mostly, only the m-series
+    devices are capable of digital streaming.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index 44fcb3790113..961ea97966f5 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -2464,6 +2464,7 @@ static int ni_ai_insn_config(struct comedi_device *dev,
+ 			     struct comedi_subdevice *s,
+ 			     struct comedi_insn *insn, unsigned int *data)
+ {
++	const struct ni_board_struct *board = dev->board_ptr;
+ 	struct ni_private *devpriv = dev->private;
+ 
+ 	if (insn->n < 1)
+@@ -2498,6 +2499,15 @@ static int ni_ai_insn_config(struct comedi_device *dev,
+ 			}
+ 		}
+ 		return 2;
++	case INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS:
++		/* we don't care about actual channels */
++		/* data[3] : chanlist_len */
++		data[1] = ni_min_ai_scan_period_ns(dev, data[3]);
++		if (devpriv->is_611x || devpriv->is_6143)
++			data[2] = 0; /* simultaneous output */
++		else
++			data[2] = board->ai_speed;
++		return 0;
+ 	default:
+ 		break;
+ 	}
+@@ -2834,6 +2844,11 @@ static int ni_ao_insn_config(struct comedi_device *dev,
+ 		return 0;
+ 	case INSN_CONFIG_ARM:
+ 		return ni_ao_arm(dev, s);
++	case INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS:
++		/* we don't care about actual channels */
++		data[1] = board->ao_speed;
++		data[2] = 0;
++		return 0;
+ 	default:
+ 		break;
+ 	}
+@@ -3475,6 +3490,15 @@ static int ni_m_series_dio_insn_config(struct comedi_device *dev,
+ {
+ 	int ret;
+ 
++	if (data[0] == INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS) {
++		const struct ni_board_struct *board = dev->board_ptr;
++
++		/* we don't care about actual channels */
++		data[1] = board->dio_speed;
++		data[2] = 0;
++		return 0;
++	}
++
+ 	ret = comedi_dio_insn_config(dev, s, insn, data, 0);
+ 	if (ret)
+ 		return ret;
+diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
+index f9e466d18b3f..14b26fffe049 100644
+--- a/drivers/staging/comedi/drivers/ni_pcimio.c
++++ b/drivers/staging/comedi/drivers/ni_pcimio.c
+@@ -693,6 +693,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 		.ai_speed	= 4000,
+ 		.reg_type	= ni_reg_622x,
+ 		.caldac		= { caldac_none },
++		.dio_speed	= 1000,
+ 	},
+ 	[BOARD_PCI6221] = {
+ 		.name		= "pci-6221",
+@@ -708,6 +709,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 		.reg_type	= ni_reg_622x,
+ 		.ao_speed	= 1200,
+ 		.caldac		= { caldac_none },
++		.dio_speed	= 1000,
+ 	},
+ 	[BOARD_PCI6221_37PIN] = {
+ 		.name		= "pci-6221_37pin",
+@@ -738,6 +740,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 		.reg_type	= ni_reg_622x,
+ 		.ao_speed	= 1200,
+ 		.caldac		= { caldac_none },
++		.dio_speed	= 1000,
+ 	},
+ 	[BOARD_PCI6224] = {
+ 		.name		= "pci-6224",
+@@ -749,6 +752,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 		.reg_type	= ni_reg_622x,
+ 		.has_32dio_chan	= 1,
+ 		.caldac		= { caldac_none },
++		.dio_speed	= 1000,
+ 	},
+ 	[BOARD_PXI6224] = {
+ 		.name		= "pxi-6224",
+@@ -760,6 +764,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 		.reg_type	= ni_reg_622x,
+ 		.has_32dio_chan	= 1,
+ 		.caldac		= { caldac_none },
++		.dio_speed	= 1000,
+ 	},
+ 	[BOARD_PCI6225] = {
+ 		.name		= "pci-6225",
+@@ -776,6 +781,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 		.ao_speed	= 1200,
+ 		.has_32dio_chan	= 1,
+ 		.caldac		= { caldac_none },
++		.dio_speed	= 1000,
+ 	},
+ 	[BOARD_PXI6225] = {
+ 		.name		= "pxi-6225",
+@@ -792,6 +798,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 		.ao_speed	= 1200,
+ 		.has_32dio_chan	= 1,
+ 		.caldac		= { caldac_none },
++		.dio_speed	= 1000,
+ 	},
+ 	[BOARD_PCI6229] = {
+ 		.name		= "pci-6229",
+@@ -824,6 +831,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 		.ao_speed	= 1200,
+ 		.has_32dio_chan	= 1,
+ 		.caldac		= { caldac_none },
++		.dio_speed	= 1000,
+ 	},
+ 	[BOARD_PCI6250] = {
+ 		.name		= "pci-6250",
+@@ -844,6 +852,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 		.ai_speed	= 800,
+ 		.reg_type	= ni_reg_625x,
+ 		.caldac		= { caldac_none },
++		.dio_speed	= 100,
+ 	},
+ 	[BOARD_PCI6251] = {
+ 		.name		= "pci-6251",
+@@ -859,6 +868,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 		.reg_type	= ni_reg_625x,
+ 		.ao_speed	= 350,
+ 		.caldac		= { caldac_none },
++		.dio_speed	= 100,
+ 	},
+ 	[BOARD_PXI6251] = {
+ 		.name		= "pxi-6251",
+@@ -874,6 +884,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 		.reg_type	= ni_reg_625x,
+ 		.ao_speed	= 350,
+ 		.caldac		= { caldac_none },
++		.dio_speed	= 100,
+ 	},
+ 	[BOARD_PCIE6251] = {
+ 		.name		= "pcie-6251",
+@@ -889,6 +900,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 		.reg_type	= ni_reg_625x,
+ 		.ao_speed	= 350,
+ 		.caldac		= { caldac_none },
++		.dio_speed	= 100,
+ 	},
+ 	[BOARD_PXIE6251] = {
+ 		.name		= "pxie-6251",
+@@ -904,6 +916,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 		.reg_type	= ni_reg_625x,
+ 		.ao_speed	= 350,
+ 		.caldac		= { caldac_none },
++		.dio_speed	= 100,
+ 	},
+ 	[BOARD_PCI6254] = {
+ 		.name		= "pci-6254",
+@@ -926,6 +939,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 		.reg_type	= ni_reg_625x,
+ 		.has_32dio_chan	= 1,
+ 		.caldac		= { caldac_none },
++		.dio_speed	= 100,
+ 	},
+ 	[BOARD_PCI6259] = {
+ 		.name		= "pci-6259",
+@@ -958,6 +972,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 		.ao_speed	= 350,
+ 		.has_32dio_chan	= 1,
+ 		.caldac		= { caldac_none },
++		.dio_speed	= 100,
+ 	},
+ 	[BOARD_PCIE6259] = {
+ 		.name		= "pcie-6259",
+@@ -990,6 +1005,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 		.ao_speed	= 350,
+ 		.has_32dio_chan	= 1,
+ 		.caldac		= { caldac_none },
++		.dio_speed	= 100,
+ 	},
+ 	[BOARD_PCI6280] = {
+ 		.name		= "pci-6280",
+@@ -1012,6 +1028,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 		.ao_fifo_depth	= 8191,
+ 		.reg_type	= ni_reg_628x,
+ 		.caldac		= { caldac_none },
++		.dio_speed	= 100,
+ 	},
+ 	[BOARD_PCI6281] = {
+ 		.name		= "pci-6281",
+@@ -1027,6 +1044,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 		.reg_type	= ni_reg_628x,
+ 		.ao_speed	= 350,
+ 		.caldac		= { caldac_none },
++		.dio_speed	= 100,
+ 	},
+ 	[BOARD_PXI6281] = {
+ 		.name		= "pxi-6281",
+@@ -1042,6 +1060,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 		.reg_type	= ni_reg_628x,
+ 		.ao_speed	= 350,
+ 		.caldac		= { caldac_none },
++		.dio_speed	= 100,
+ 	},
+ 	[BOARD_PCI6284] = {
+ 		.name		= "pci-6284",
+@@ -1064,6 +1083,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 		.reg_type	= ni_reg_628x,
+ 		.has_32dio_chan	= 1,
+ 		.caldac		= { caldac_none },
++		.dio_speed	= 100,
+ 	},
+ 	[BOARD_PCI6289] = {
+ 		.name		= "pci-6289",
+@@ -1096,6 +1116,7 @@ static const struct ni_board_struct ni_boards[] = {
+ 		.ao_speed	= 350,
+ 		.has_32dio_chan	= 1,
+ 		.caldac		= { caldac_none },
++		.dio_speed	= 100,
+ 	},
+ 	[BOARD_PCI6143] = {
+ 		.name		= "pci-6143",
+diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h
+index 831088c5cabb..1c6bd25da962 100644
+--- a/drivers/staging/comedi/drivers/ni_stc.h
++++ b/drivers/staging/comedi/drivers/ni_stc.h
+@@ -953,6 +953,7 @@ struct ni_board_struct {
+ 	int reg_type;
+ 	unsigned int has_8255:1;
+ 	unsigned int has_32dio_chan:1;
++	unsigned int dio_speed; /* not for e-series */
+ 
+ 	enum caldac_enum caldac[3];
+ };

commit 832f33366c771855951313a9bab4926f2a0d37a1
+Author: Spencer E. Olson 
+Date:   Wed Sep 19 10:51:03 2018 -0600
+
+    staging: comedi: add facility to directly query subdevice timing constraints
+    
+    Adds facility to directly query the hardware speed limits of subdevices,
+    in particular for scan_begin and convert signals.  This information can be
+    critical for integrating comedi with other hardware modules, and also
+    comedi modules together with software where software requires specific
+    timing capabilities in order to properly coordinate multiple devices.
+    
+    Currently, comedi_command_test almost satisfies this need, but really only
+    for when *_src == TRIG_TIMER.  For *_src == TRIG_EXT, comedi_command_test
+    does not help at all.  For many subdevices, one might simply use
+    *_src==TRIG_TIMER in command_test in order to determine these limits.  For
+    other subdevices, this tactic does not work since *_src == TRIG_TIMER might
+    not be valid.  There is also the possibility that the timing limits are
+    different between the TRIG_TIMER and TRIG_EXT modes.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
+index bb961ac79b7e..cf7b2b970327 100644
+--- a/drivers/staging/comedi/comedi.h
++++ b/drivers/staging/comedi/comedi.h
+@@ -301,6 +301,8 @@ enum comedi_io_direction {
+  * @INSN_CONFIG_PWM_SET_H_BRIDGE: Set PWM H bridge duty cycle and polarity for
+  *				a relay simultaneously.
+  * @INSN_CONFIG_PWM_GET_H_BRIDGE: Get PWM H bridge duty cycle and polarity.
++ * @INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS: Get the hardware timing restraints,
++ *				regardless of trigger sources.
+  */
+ enum configuration_ids {
+ 	INSN_CONFIG_DIO_INPUT = COMEDI_INPUT,
+@@ -344,7 +346,8 @@ enum configuration_ids {
+ 	INSN_CONFIG_PWM_GET_PERIOD = 5001,
+ 	INSN_CONFIG_GET_PWM_STATUS = 5002,
+ 	INSN_CONFIG_PWM_SET_H_BRIDGE = 5003,
+-	INSN_CONFIG_PWM_GET_H_BRIDGE = 5004
++	INSN_CONFIG_PWM_GET_H_BRIDGE = 5004,
++	INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS = 5005,
+ };
+ 
+ /**
+diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
+index e18b61cdbdeb..548baa790507 100644
+--- a/drivers/staging/comedi/comedi_fops.c
++++ b/drivers/staging/comedi/comedi_fops.c
+@@ -1216,6 +1216,10 @@ static int check_insn_config_length(struct comedi_insn *insn,
+ 		if (insn->n == 6)
+ 			return 0;
+ 		break;
++	case INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS:
++		if (insn->n >= 4)
++			return 0;
++		break;
+ 		/*
+ 		 * by default we allow the insn since we don't have checks for
+ 		 * all possible cases yet

commit 1cbca5852d6c16e85a21487a15d211195aacd4a1
+Author: Spencer E. Olson 
+Date:   Wed Oct 3 14:54:16 2018 -0600
+
+    staging: comedi: ni_mio_common: protect register write overflow
+    
+    Fixes two problems introduced as early as
+    commit 03aef4b6dc12  ("Staging: comedi: add ni_mio_common code"):
+    (1) Ensures that the last four bits of NISTC_RTSI_TRIGB_OUT_REG register is
+        not unduly overwritten on e-series devices.  On e-series devices, the
+        first three of the last four bits are reserved.  The last bit defines
+        the output selection of the RGOUT0 pin, otherwise known as
+        RTSI_Sub_Selection.  For m-series devices, these last four bits are
+        indeed used as the output selection of the RTSI7 pin (and the
+        RTSI_Sub_Selection bit for the RGOUT0 pin is moved to the
+        RTSI_Trig_Direction register.
+    (2) Allows all 4 RTSI_BRD lines to be treated as valid sources for RTSI
+        lines.
+    
+    This patch also cleans up the ni_get_rtsi_routing command for readability.
+    
+    Fixes: 03aef4b6dc12  ("Staging: comedi: add ni_mio_common code")
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index 4dee2fc37aed..44fcb3790113 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -4980,7 +4980,10 @@ static int ni_valid_rtsi_output_source(struct comedi_device *dev,
+ 	case NI_RTSI_OUTPUT_G_SRC0:
+ 	case NI_RTSI_OUTPUT_G_GATE0:
+ 	case NI_RTSI_OUTPUT_RGOUT0:
+-	case NI_RTSI_OUTPUT_RTSI_BRD_0:
++	case NI_RTSI_OUTPUT_RTSI_BRD(0):
++	case NI_RTSI_OUTPUT_RTSI_BRD(1):
++	case NI_RTSI_OUTPUT_RTSI_BRD(2):
++	case NI_RTSI_OUTPUT_RTSI_BRD(3):
+ 		return 1;
+ 	case NI_RTSI_OUTPUT_RTSI_OSC:
+ 		return (devpriv->is_m_series) ? 1 : 0;
+@@ -5001,11 +5004,18 @@ static int ni_set_rtsi_routing(struct comedi_device *dev,
+ 		devpriv->rtsi_trig_a_output_reg |= NISTC_RTSI_TRIG(chan, src);
+ 		ni_stc_writew(dev, devpriv->rtsi_trig_a_output_reg,
+ 			      NISTC_RTSI_TRIGA_OUT_REG);
+-	} else if (chan < 8) {
++	} else if (chan < NISTC_RTSI_TRIG_NUM_CHAN(devpriv->is_m_series)) {
+ 		devpriv->rtsi_trig_b_output_reg &= ~NISTC_RTSI_TRIG_MASK(chan);
+ 		devpriv->rtsi_trig_b_output_reg |= NISTC_RTSI_TRIG(chan, src);
+ 		ni_stc_writew(dev, devpriv->rtsi_trig_b_output_reg,
+ 			      NISTC_RTSI_TRIGB_OUT_REG);
++	} else if (chan != NISTC_RTSI_TRIG_OLD_CLK_CHAN) {
++		/* probably should never reach this, since the
++		 * ni_valid_rtsi_output_source above errors out if chan is too
++		 * high
++		 */
++		dev_err(dev->class_dev, "%s: unknown rtsi channel\n", __func__);
++		return -EINVAL;
+ 	}
+ 	return 2;
+ }
+@@ -5021,12 +5031,12 @@ static unsigned int ni_get_rtsi_routing(struct comedi_device *dev,
+ 	} else if (chan < NISTC_RTSI_TRIG_NUM_CHAN(devpriv->is_m_series)) {
+ 		return NISTC_RTSI_TRIG_TO_SRC(chan,
+ 					      devpriv->rtsi_trig_b_output_reg);
+-	} else {
+-		if (chan == NISTC_RTSI_TRIG_OLD_CLK_CHAN)
+-			return NI_RTSI_OUTPUT_RTSI_OSC;
+-		dev_err(dev->class_dev, "bug! should never get here?\n");
+-		return 0;
++	} else if (chan == NISTC_RTSI_TRIG_OLD_CLK_CHAN) {
++		return NI_RTSI_OUTPUT_RTSI_OSC;
+ 	}
++
++	dev_err(dev->class_dev, "%s: unknown rtsi channel\n", __func__);
++	return -EINVAL;
+ }
+ 
+ static int ni_rtsi_insn_config(struct comedi_device *dev,

commit f515f86b34b2e7d4b24cc9b7375c9e749895088e
+Author: Olga Kornievskaia 
+Date:   Thu Jun 29 09:25:36 2017 -0400
+
+    fix parallelism for rpc tasks
+    
+    Hi folks,
+    
+    On a multi-core machine, is it expected that we can have parallel RPCs
+    handled by each of the per-core workqueue?
+    
+    In testing a read workload, observing via "top" command that a single
+    "kworker" thread is running servicing the requests (no parallelism).
+    It's more prominent while doing these operations over krb5p mount.
+    
+    What has been suggested by Bruce is to try this and in my testing I
+    see then the read workload spread among all the kworker threads.
+    
+    Signed-off-by: Olga Kornievskaia 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
+index 25e6051e97f2..d9db2eab3a8d 100644
+--- a/net/sunrpc/sched.c
++++ b/net/sunrpc/sched.c
+@@ -1104,7 +1104,7 @@ static int rpciod_start(void)
+ 	 * Create the rpciod thread and wait for it to start.
+ 	 */
+ 	dprintk("RPC:       creating workqueue rpciod\n");
+-	wq = alloc_workqueue("rpciod", WQ_MEM_RECLAIM, 0);
++	wq = alloc_workqueue("rpciod", WQ_MEM_RECLAIM | WQ_UNBOUND, 0);
+ 	if (!wq)
+ 		goto out_failed;
+ 	rpciod_workqueue = wq;

commit 05b7278d510a6a1c23624caee5b0a9667a72e745
+Author: Olga Kornievskaia 
+Date:   Thu Mar 23 14:36:20 2017 -0400
+
+    nfsd: fix oops on unsupported operation
+    
+    I'm hitting the BUG in nfsd4_max_reply() at fs/nfsd/nfs4proc.c:2495 when
+    client sends an operation the server doesn't support.
+    
+    in nfsd4_max_reply() it checks for NULL rsize_bop but a non-supported
+    operation wouldn't have that set.
+    
+    Cc: Kinglong Mee 
+    Fixes: 2282cd2c05e2 "NFSD: Get response size before operation..."
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index cbeeda1e94a2..d86031b6ad79 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -2489,7 +2489,7 @@ bool nfsd4_spo_must_allow(struct svc_rqst *rqstp)
+ 
+ int nfsd4_max_reply(struct svc_rqst *rqstp, struct nfsd4_op *op)
+ {
+-	if (op->opnum == OP_ILLEGAL)
++	if (op->opnum == OP_ILLEGAL || op->status == nfserr_notsupp)
+ 		return op_encode_hdr_size * sizeof(__be32);
+ 
+ 	BUG_ON(OPDESC(op)->op_rsize_bop == NULL);

commit 1ffe8bdc09f8bfcaad76d71ae68b623c7e03f20f
+Author: Spencer E. Olson 
+Date:   Mon Oct 10 08:14:19 2016 -0600
+
+    staging: comedi: ni_mio_common: split out ao arming from ni_ao_inttrig
+    
+    AO device arming was previously done as a part of ni_ao_inttrig which is
+    called as a result of the user calling comedi_internal_trigger.  For
+    start_src == TRIG_EXT, this does not make very much sense since external
+    triggers should not conceptually need to be software triggered also.  This
+    patch splits out the arming functionality to allow arming to specifically
+    and separately be done via the CONFIG_INSN_ARM ioctl command.
+    
+    In order to provide backwards compatibility, this patch also provides
+    automatic arming if ni_ao_inttrig is simply called.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index 0f97d7b611d7..9812508fe8d3 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -2729,66 +2729,36 @@ static int ni_ao_insn_write(struct comedi_device *dev,
+ 	return insn->n;
+ }
+ 
+-static int ni_ao_insn_config(struct comedi_device *dev,
+-			     struct comedi_subdevice *s,
+-			     struct comedi_insn *insn, unsigned int *data)
+-{
+-	const struct ni_board_struct *board = dev->board_ptr;
+-	struct ni_private *devpriv = dev->private;
+-	unsigned int nbytes;
+-
+-	switch (data[0]) {
+-	case INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE:
+-		switch (data[1]) {
+-		case COMEDI_OUTPUT:
+-			nbytes = comedi_samples_to_bytes(s,
+-							 board->ao_fifo_depth);
+-			data[2] = 1 + nbytes;
+-			if (devpriv->mite)
+-				data[2] += devpriv->mite->fifo_size;
+-			break;
+-		case COMEDI_INPUT:
+-			data[2] = 0;
+-			break;
+-		default:
+-			return -EINVAL;
+-		}
+-		return 0;
+-	default:
+-		break;
+-	}
+-
+-	return -EINVAL;
+-}
+-
+-static int ni_ao_inttrig(struct comedi_device *dev,
+-			 struct comedi_subdevice *s,
+-			 unsigned int trig_num)
++/*
++ * Arms the AO device in preparation for a trigger event.
++ * This function also allocates and prepares a DMA channel (or FIFO if DMA is
++ * not used).  As a part of this preparation, this function preloads the DAC
++ * registers with the first values of the output stream.  This ensures that the
++ * first clock cycle after the trigger can be used for output.
++ *
++ * Note that this function _must_ happen after a user has written data to the
++ * output buffers via either mmap or write(fileno,...).
++ */
++static int ni_ao_arm(struct comedi_device *dev,
++		     struct comedi_subdevice *s)
+ {
+ 	struct ni_private *devpriv = dev->private;
+-	struct comedi_cmd *cmd = &s->async->cmd;
+ 	int ret;
+ 	int interrupt_b_bits;
+ 	int i;
+ 	static const int timeout = 1000;
+ 
+ 	/*
+-	 * Require trig_num == cmd->start_arg when cmd->start_src == TRIG_INT.
+-	 * For backwards compatibility, also allow trig_num == 0 when
+-	 * cmd->start_src != TRIG_INT (i.e. when cmd->start_src == TRIG_EXT);
+-	 * in that case, the internal trigger is being used as a pre-trigger
+-	 * before the external trigger.
++	 * Prevent ao from doing things like trying to allocate the ao dma
++	 * channel multiple times.
+ 	 */
+-	if (!(trig_num == cmd->start_arg ||
+-	      (trig_num == 0 && cmd->start_src != TRIG_INT)))
++	if (!devpriv->ao_needs_arming) {
++		dev_dbg(dev->class_dev, "%s: device does not need arming!\n",
++			__func__);
+ 		return -EINVAL;
++	}
+ 
+-	/*
+-	 * Null trig at beginning prevent ao start trigger from executing more
+-	 * than once per command (and doing things like trying to allocate the
+-	 * ao dma channel multiple times).
+-	 */
+-	s->async->inttrig = NULL;
++	devpriv->ao_needs_arming = 0;
+ 
+ 	ni_set_bits(dev, NISTC_INTB_ENA_REG,
+ 		    NISTC_INTB_ENA_AO_FIFO | NISTC_INTB_ENA_AO_ERR, 0);
+@@ -2840,6 +2810,75 @@ static int ni_ao_inttrig(struct comedi_device *dev,
+ 			   devpriv->ao_cmd1,
+ 		      NISTC_AO_CMD1_REG);
+ 
++	return 0;
++}
++
++static int ni_ao_insn_config(struct comedi_device *dev,
++			     struct comedi_subdevice *s,
++			     struct comedi_insn *insn, unsigned int *data)
++{
++	const struct ni_board_struct *board = dev->board_ptr;
++	struct ni_private *devpriv = dev->private;
++	unsigned int nbytes;
++
++	switch (data[0]) {
++	case INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE:
++		switch (data[1]) {
++		case COMEDI_OUTPUT:
++			nbytes = comedi_samples_to_bytes(s,
++							 board->ao_fifo_depth);
++			data[2] = 1 + nbytes;
++			if (devpriv->mite)
++				data[2] += devpriv->mite->fifo_size;
++			break;
++		case COMEDI_INPUT:
++			data[2] = 0;
++			break;
++		default:
++			return -EINVAL;
++		}
++		return 0;
++	case INSN_CONFIG_ARM:
++		return ni_ao_arm(dev, s);
++	default:
++		break;
++	}
++
++	return -EINVAL;
++}
++
++static int ni_ao_inttrig(struct comedi_device *dev,
++			 struct comedi_subdevice *s,
++			 unsigned int trig_num)
++{
++	struct ni_private *devpriv = dev->private;
++	struct comedi_cmd *cmd = &s->async->cmd;
++	int ret;
++
++	/*
++	 * Require trig_num == cmd->start_arg when cmd->start_src == TRIG_INT.
++	 * For backwards compatibility, also allow trig_num == 0 when
++	 * cmd->start_src != TRIG_INT (i.e. when cmd->start_src == TRIG_EXT);
++	 * in that case, the internal trigger is being used as a pre-trigger
++	 * before the external trigger.
++	 */
++	if (!(trig_num == cmd->start_arg ||
++	      (trig_num == 0 && cmd->start_src != TRIG_INT)))
++		return -EINVAL;
++
++	/*
++	 * Null trig at beginning prevent ao start trigger from executing more
++	 * than once per command.
++	 */
++	s->async->inttrig = NULL;
++
++	if (devpriv->ao_needs_arming) {
++		/* only arm this device if it still needs arming */
++		ret = ni_ao_arm(dev, s);
++		if (ret)
++			return ret;
++	}
++
+ 	ni_stc_writew(dev, NISTC_AO_CMD2_START1_PULSE | devpriv->ao_cmd2,
+ 		      NISTC_AO_CMD2_REG);
+ 
+@@ -3227,10 +3266,17 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ 	ni_ao_cmd_set_interrupts(dev, s);
+ 
+ 	/*
+-	 * arm(ing) and star(ting) happen in ni_ao_inttrig, which _must_ be
+-	 * called for ao commands since 1) TRIG_NOW is not supported and 2) DMA
+-	 * must be setup and initially written to before arm/start happen.
++	 * arm(ing) must happen later so that DMA can be setup and DACs
++	 * preloaded with the actual output buffer before starting.
++	 *
++	 * start(ing) must happen _after_ arming is completed.  Starting can be
++	 * done either via ni_ao_inttrig, or via an external trigger.
++	 *
++	 * **Currently, ni_ao_inttrig will automatically attempt a call to
++	 * ni_ao_arm if the device still needs arming at that point.  This
++	 * allows backwards compatibility.
+ 	 */
++	devpriv->ao_needs_arming = 1;
+ 	return 0;
+ }
+ 
+diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h
+index 1966519cb6e5..f27b545f83eb 100644
+--- a/drivers/staging/comedi/drivers/ni_stc.h
++++ b/drivers/staging/comedi/drivers/ni_stc.h
+@@ -1053,6 +1053,20 @@ struct ni_private {
+ 	unsigned int is_67xx:1;
+ 	unsigned int is_6711:1;
+ 	unsigned int is_6713:1;
++
++	/*
++	 * Boolean value of whether device needs to be armed.
++	 *
++	 * Currently, only NI AO devices are known to be needing arming, since
++	 * the DAC registers must be preloaded before triggering.
++	 * This variable should only be set true during a command operation
++	 * (e.g ni_ao_cmd) and should then be set false by the arming
++	 * function (e.g. ni_ao_arm).
++	 *
++	 * This variable helps to ensure that multiple DMA allocations are not
++	 * possible.
++	 */
++	unsigned int ao_needs_arming:1;
+ };
+ 
+ static const struct comedi_lrange range_ni_E_ao_ext;

commit cc7a6d6c4614bbf65d57dac31706fb01377d8371
+Author: Spencer E. Olson 
+Date:   Sat Oct 8 15:38:43 2016 -0600
+
+    staging: comedi: make constants slightly more consistent
+    
+    This makes INSN_CONFIG_DIO_{INPUT,OUTPUT,OPENDRAIN} simply be copies of the
+    already-existing constants COMEDI_INPUT, COMEDI_OUTPUT, and
+    COMEDI_OPENDRAIN.
+    
+    This change also ensures that if a user happens to use, for example,
+    COMEDI_INPUT in place of where INSN_CONFIG_DIO_INPUT, the result will
+    always be the same and also acceptable and correct usage.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
+index a67ed578af5e..a1c1081906c5 100644
+--- a/drivers/staging/comedi/comedi.h
++++ b/drivers/staging/comedi/comedi.h
+@@ -244,6 +244,22 @@ enum comedi_subdevice_type {
+ 
+ /* configuration instructions */
+ 
++/**
++ * enum comedi_io_direction - COMEDI I/O directions
++ * @COMEDI_INPUT:	Input.
++ * @COMEDI_OUTPUT:	Output.
++ * @COMEDI_OPENDRAIN:	Open-drain (or open-collector) output.
++ *
++ * These are used by the %INSN_CONFIG_DIO_QUERY configuration instruction to
++ * report a direction.  They may also be used in other places where a direction
++ * needs to be specified.
++ */
++enum comedi_io_direction {
++	COMEDI_INPUT = 0,
++	COMEDI_OUTPUT = 1,
++	COMEDI_OPENDRAIN = 2
++};
++
+ /**
+  * enum configuration_ids - COMEDI configuration instruction codes
+  * @INSN_CONFIG_DIO_INPUT:	Configure digital I/O as input.
+@@ -296,9 +312,9 @@ enum comedi_subdevice_type {
+  * @INSN_CONFIG_PWM_GET_H_BRIDGE: Get PWM H bridge duty cycle and polarity.
+  */
+ enum configuration_ids {
+-	INSN_CONFIG_DIO_INPUT = 0,
+-	INSN_CONFIG_DIO_OUTPUT = 1,
+-	INSN_CONFIG_DIO_OPENDRAIN = 2,
++	INSN_CONFIG_DIO_INPUT = COMEDI_INPUT,
++	INSN_CONFIG_DIO_OUTPUT = COMEDI_OUTPUT,
++	INSN_CONFIG_DIO_OPENDRAIN = COMEDI_OPENDRAIN,
+ 	INSN_CONFIG_ANALOG_TRIG = 16,
+ /*	INSN_CONFIG_WAVEFORM = 17, */
+ /*	INSN_CONFIG_TRIG = 18, */
+@@ -396,22 +412,6 @@ enum comedi_digital_trig_op {
+ 	COMEDI_DIGITAL_TRIG_ENABLE_LEVELS = 2
+ };
+ 
+-/**
+- * enum comedi_io_direction - COMEDI I/O directions
+- * @COMEDI_INPUT:	Input.
+- * @COMEDI_OUTPUT:	Output.
+- * @COMEDI_OPENDRAIN:	Open-drain (or open-collector) output.
+- *
+- * These are used by the %INSN_CONFIG_DIO_QUERY configuration instruction to
+- * report a direction.  They may also be used in other places where a direction
+- * needs to be specified.
+- */
+-enum comedi_io_direction {
+-	COMEDI_INPUT = 0,
+-	COMEDI_OUTPUT = 1,
+-	COMEDI_OPENDRAIN = 2
+-};
+-
+ /**
+  * enum comedi_support_level - support level for a COMEDI feature
+  * @COMEDI_UNKNOWN_SUPPORT:	Unspecified support for feature.

commit 5c53440daa050909e761ebcce8483b28fb163273
+Author: Spencer E. Olson 
+Date:   Sat Oct 8 15:37:29 2016 -0600
+
+    staging: comedi: porting NI_GPCT constants from comedi.org module
+    
+    Information pertaining to the NI_GPCT_ARM* registers were added to the
+    comedi.org version of the comedi kernel.  This adds this information to
+    the staging-tree version of the comedi kernel.  Relevant comments are also
+    copied over.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
+index 08fb26b51a5f..a67ed578af5e 100644
+--- a/drivers/staging/comedi/comedi.h
++++ b/drivers/staging/comedi/comedi.h
+@@ -1104,18 +1104,19 @@ enum ni_gpct_other_select {
+ enum ni_gpct_arm_source {
+ 	NI_GPCT_ARM_IMMEDIATE = 0x0,
+ 	/*
+-	 * Start both the counter and the adjacent pared
+-	 * counter simultaneously
++	 * Start both the counter and the adjacent paired counter simultaneously
+ 	 */
+ 	NI_GPCT_ARM_PAIRED_IMMEDIATE = 0x1,
+ 	/*
+-	 * NI doesn't document bits for selecting hardware arm triggers.
+-	 * If the NI_GPCT_ARM_UNKNOWN bit is set, we will pass the least
+-	 * significant bits (3 bits for 660x or 5 bits for m-series)
+-	 * through to the hardware.  This will at least allow someone to
+-	 * figure out what the bits do later.
++	 * If the NI_GPCT_HW_ARM bit is set, we will pass the least significant
++	 * bits (3 bits for 660x or 5 bits for m-series) through to the
++	 * hardware. To select a hardware trigger, pass the appropriate select
++	 * bit, e.g.,
++	 * NI_GPCT_HW_ARM | NI_GPCT_AI_START1_GATE_SELECT or
++	 * NI_GPCT_HW_ARM | NI_GPCT_PFI_GATE_SELECT(pfi_number)
+ 	 */
+-	NI_GPCT_ARM_UNKNOWN = 0x1000,
++	NI_GPCT_HW_ARM = 0x1000,
++	NI_GPCT_ARM_UNKNOWN = NI_GPCT_HW_ARM,	/* for backward compatibility */
+ };
+ 
+ /* digital filtering options for ni 660x for use with INSN_CONFIG_FILTER. */

commit f164cbf98fa8692ecbe1f870c50522985d34d1c2
+Author: Spencer E. Olson 
+Date:   Wed Jan 27 14:28:29 2016 -0700
+
+    staging: comedi: ni_mio_common: add finite regeneration to dio output
+    
+    This patch continues the implementation of reinterpreting stop_arg when
+    stop_src == TRIG_NONE for national instruments cdio output on e/m-series
+    devices.  This is part of a series of patches that allow a user to have a
+    specific buffer repeated as-is indefinitely.  The contents of the DMA
+    buffer can be left static or changed by the user via mmap access to the DMA
+    buffer.  If the contents are changed by the user, additional munging is not
+    performed by the driver and only a single call to
+    comedi_mark_buffer_written should be done.  The original behavior is
+    preserved when stop_arg == 0, as would be the prior use case.
+    
+    As opposed to analog output, this patch is relatively simple.  First, the
+    digital output capabilities are much more limited/simple as compared to the
+    analog output device on NI e/m-series hardware, and second, this patch
+    relies on changes made with the earlier patch to accomplish limiting the
+    DMA buffer transfer.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index 1a22c79c2817..929389b52572 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -3630,7 +3630,9 @@ static int ni_cdio_cmdtest(struct comedi_device *dev,
+ 	err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+ 	err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+ 					   cmd->chanlist_len);
+-	err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
++	err |= comedi_check_trigger_arg_max(&cmd->stop_arg,
++					    s->async->prealloc_bufsz /
++					    comedi_bytes_per_scan(s));
+ 
+ 	if (err)
+ 		return 3;
+@@ -3707,6 +3709,7 @@ static int ni_cdo_inttrig(struct comedi_device *dev,
+ 
+ static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
++	struct ni_private *devpriv = dev->private;
+ 	const struct comedi_cmd *cmd = &s->async->cmd;
+ 	unsigned cdo_mode_bits;
+ 	int retval;
+@@ -3731,6 +3734,10 @@ static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ 	if (retval < 0)
+ 		return retval;
+ 
++	ni_cmd_set_mite_transfer(devpriv->cdo_mite_ring, s, cmd,
++				 s->async->prealloc_bufsz /
++				 comedi_bytes_per_scan(s));
++
+ 	s->async->inttrig = ni_cdo_inttrig;
+ 
+ 	return 0;

commit 6aab7fee7a24395db1b556a5e5cf30aa2627c2be
+Author: Spencer E. Olson 
+Date:   Wed Jan 27 14:28:28 2016 -0700
+
+    staging: comedi: ni_mio_common: adds finite regeneration to AO output
+    
+    This patch implements for analog output the reinterpretation of stop_arg
+    when stop_src == TRIG_NONE to allow the user to specify the length of the
+    buffer that should be repeated.  The intent is to allow a user to have a
+    specific buffer repeated as-is indefinitely.  The contents of the DMA
+    buffer can be left static or changed by the user via mmap access to the DMA
+    buffer.  If the contents are changed by the user, additional munging is not
+    performed by the driver and only a single call to
+    comedi_mark_buffer_written should be done.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index 8f0fe3a26c73..1a22c79c2817 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -1500,7 +1500,8 @@ static void handle_b_interrupt(struct comedi_device *dev,
+ 		s->async->events |= COMEDI_CB_OVERFLOW;
+ 	}
+ 
+-	if (b_status & NISTC_AO_STATUS1_BC_TC)
++	if (s->async->cmd.stop_src != TRIG_NONE &&
++	    b_status & NISTC_AO_STATUS1_BC_TC)
+ 		s->async->events |= COMEDI_CB_EOA;
+ 
+ #ifndef PCIDMA
+@@ -2073,6 +2074,37 @@ static unsigned ni_timer_to_ns(const struct comedi_device *dev, int timer)
+ 	return devpriv->clock_ns * (timer + 1);
+ }
+ 
++static void ni_cmd_set_mite_transfer(struct mite_dma_descriptor_ring *ring,
++				     struct comedi_subdevice *sdev,
++				     const struct comedi_cmd *cmd,
++				     unsigned int max_count) {
++#ifdef PCIDMA
++	unsigned int nbytes = max_count;
++
++	if (cmd->stop_arg > 0 && cmd->stop_arg < max_count)
++		nbytes = cmd->stop_arg;
++	nbytes *= comedi_bytes_per_scan(sdev);
++
++	if (nbytes > sdev->async->prealloc_bufsz) {
++		if (cmd->stop_arg > 0)
++			dev_err(sdev->device->class_dev,
++				"ni_cmd_set_mite_transfer: tried exact data transfer limits greater than buffer size\n");
++
++		/*
++		 * we can only transfer up to the size of the buffer.  In this
++		 * case, the user is expected to continue to write into the
++		 * comedi buffer (already implemented as a ring buffer).
++		 */
++		nbytes = sdev->async->prealloc_bufsz;
++	}
++
++	mite_init_ring_descriptors(ring, sdev, nbytes);
++#else
++	dev_err(sdev->device->class_dev,
++		"ni_cmd_set_mite_transfer: exact data transfer limits not implemented yet without DMA\n");
++#endif
++}
++
+ static unsigned ni_min_ai_scan_period_ns(struct comedi_device *dev,
+ 					 unsigned num_channels)
+ {
+@@ -3062,12 +3094,16 @@ static void ni_ao_cmd_set_counters(struct comedi_device *dev,
+ 	devpriv->ao_mode2 &= ~NISTC_AO_MODE2_UC_INIT_LOAD_SRC;
+ 	ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG);
+ 
++	/*
++	 * if a user specifies '0', this automatically assumes the entire 24bit
++	 * address space is available for the (multiple iterations of single
++	 * buffer) MISB.  Otherwise, stop_arg specifies the MISB length that
++	 * will be used, regardless of whether we are in continuous mode or not.
++	 * In continuous mode, the output will just iterate indefinitely over
++	 * the MISB.
++	 */
+ 	{
+-		/*
+-		 * Current behavior is to configure the maximum update count
+-		 * possible when continuous output mode is requested.
+-		 */
+-		unsigned int stop_arg = cmd->stop_src == TRIG_COUNT ?
++		unsigned int stop_arg = cmd->stop_arg > 0 ?
+ 			(cmd->stop_arg & 0xffffff) : 0xffffff;
+ 
+ 		if (devpriv->is_m_series) {
+@@ -3311,6 +3347,7 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ 	ni_ao_cmd_set_channels(dev, s);
+ 	ni_ao_cmd_set_stop_conditions(dev, cmd);
+ 	ni_ao_cmd_set_fifo_mode(dev);
++	ni_cmd_set_mite_transfer(devpriv->ao_mite_ring, s, cmd, 0x00ffffff);
+ 	ni_ao_cmd_set_interrupts(dev, s);
+ 
+ 	/*
+@@ -3381,11 +3418,7 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+ 	err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+ 	err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+ 					   cmd->chanlist_len);
+-
+-	if (cmd->stop_src == TRIG_COUNT)
+-		err |= comedi_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff);
+-	else	/* TRIG_NONE */
+-		err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
++	err |= comedi_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff);
+ 
+ 	if (err)
+ 		return 3;
+@@ -5240,7 +5273,6 @@ static irqreturn_t ni_E_interrupt(int irq, void *d)
+ 	unsigned long flags;
+ #ifdef PCIDMA
+ 	struct ni_private *devpriv = dev->private;
+-	struct mite_struct *mite = devpriv->mite;
+ #endif
+ 
+ 	if (!dev->attached)
+@@ -5252,8 +5284,7 @@ static irqreturn_t ni_E_interrupt(int irq, void *d)
+ 	a_status = ni_stc_readw(dev, NISTC_AI_STATUS1_REG);
+ 	b_status = ni_stc_readw(dev, NISTC_AO_STATUS1_REG);
+ #ifdef PCIDMA
+-	if (mite) {
+-		struct ni_private *devpriv = dev->private;
++	if (devpriv->mite) {
+ 		unsigned long flags_too;
+ 
+ 		spin_lock_irqsave(&devpriv->mite_channel_lock, flags_too);
+@@ -5269,7 +5300,7 @@ static irqreturn_t ni_E_interrupt(int irq, void *d)
+ 			ao_mite_status = mite_get_status(devpriv->ao_mite_chan);
+ 			if (ao_mite_status & CHSR_LINKC)
+ 				writel(CHOR_CLRLC,
+-				       mite->mite_io_addr +
++				       devpriv->mite->mite_io_addr +
+ 				       MITE_CHOR(devpriv->
+ 						 ao_mite_chan->channel));
+ 		}

commit 080e6795cba316663a5eb4f49500937eca4f32cd
+Author: Spencer E. Olson 
+Date:   Wed Jan 27 14:28:27 2016 -0700
+
+    staging: comedi: ni_mio_common: Cleans up/clarifies ni_ao_cmd
+    
+    This patch implements ni_ao_cmd much more closely organized like NI MHDDK
+    examples and DAQ-STC pseudo-code.  Adds comments with some more specific
+    references to the DAQ-STC.
+    
+    For stop_src==TRIG_NONE (continuous output mode of entire buffer), the
+    count for the UC counter was corrected to represent the maximum count
+    possible (0xffffff).  Prior behavior for stop_src=TRIG_NONE did not
+    actually follow the DAQ-STC.  Furthermore, stop_src==TRIG_NONE now
+    correctly uses code specialized for either m-series or e-series devices.
+    
+    It should be noted that stop_src==TRIG_NONE does _not_ with this patch
+    (or with prior behavior in ni_mio_common) actually implement true
+    continuous output.  Rather, the output is simply configured to operate as a
+    single buffer output, but where the buffer is as large as is possible with
+    NI-STC hardware.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index 9df20d922d32..8f0fe3a26c73 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -2912,42 +2912,68 @@ static int ni_ao_inttrig(struct comedi_device *dev,
+ 	return 0;
+ }
+ 
+-static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
++/*
++ * begin ni_ao_cmd.
++ * Organized similar to NI-STC and MHDDK examples.
++ * ni_ao_cmd is broken out into configuration sub-routines for clarity.
++ */
++
++static void ni_ao_cmd_personalize(struct comedi_device *dev,
++				  const struct comedi_cmd *cmd)
+ {
+ 	const struct ni_board_struct *board = dev->board_ptr;
+-	struct ni_private *devpriv = dev->private;
+-	const struct comedi_cmd *cmd = &s->async->cmd;
+-	int bits;
+-	int i;
+-	unsigned trigvar;
+-	unsigned val;
+-
+-	if (dev->irq == 0) {
+-		dev_err(dev->class_dev, "cannot run command without an irq\n");
+-		return -EIO;
+-	}
++	unsigned bits;
+ 
+ 	ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG);
+ 
+-	ni_stc_writew(dev, NISTC_AO_CMD1_DISARM, NISTC_AO_CMD1_REG);
++	bits =
++	  /* fast CPU interface--only eseries */
++	  /* ((slow CPU interface) ? 0 : AO_Fast_CPU) | */
++	  NISTC_AO_PERSONAL_BC_SRC_SEL  |
++	  0 /* (use_original_pulse ? 0 : NISTC_AO_PERSONAL_UPDATE_TIMEBASE) */ |
++	  /*
++	   * FIXME:  start setting following bit when appropriate.  Need to
++	   * determine whether board is E4 or E1.
++	   * FROM MHHDK:
++	   * if board is E4 or E1
++	   *   Set bit "NISTC_AO_PERSONAL_UPDATE_PW" to 0
++	   * else
++	   *   set it to 1
++	   */
++	  NISTC_AO_PERSONAL_UPDATE_PW   |
++	  /* FIXME:  when should we set following bit to zero? */
++	  NISTC_AO_PERSONAL_TMRDACWR_PW |
++	  (board->ao_fifo_depth ?
++	    NISTC_AO_PERSONAL_FIFO_ENA : NISTC_AO_PERSONAL_DMA_PIO_CTRL)
++	  ;
++#if 0
++	/*
++	 * FIXME:
++	 * add something like ".has_individual_dacs = 0" to ni_board_struct
++	 * since, as F Hess pointed out, not all in m series have singles.  not
++	 * sure if e-series all have duals...
++	 */
+ 
+-	if (devpriv->is_6xxx) {
+-		ni_ao_win_outw(dev, NI611X_AO_MISC_CLEAR_WG,
+-			       NI611X_AO_MISC_REG);
++	/*
++	 * F Hess: windows driver does not set NISTC_AO_PERSONAL_NUM_DAC bit for
++	 * 6281, verified with bus analyzer.
++	 */
++	if (devpriv->is_m_series)
++		bits |= NISTC_AO_PERSONAL_NUM_DAC;
++#endif
++	ni_stc_writew(dev, bits, NISTC_AO_PERSONAL_REG);
+ 
+-		bits = 0;
+-		for (i = 0; i < cmd->chanlist_len; i++) {
+-			int chan;
++	ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG);
++}
+ 
+-			chan = CR_CHAN(cmd->chanlist[i]);
+-			bits |= 1 << chan;
+-			ni_ao_win_outw(dev, chan, NI611X_AO_WAVEFORM_GEN_REG);
+-		}
+-		ni_ao_win_outw(dev, bits, NI611X_AO_TIMED_REG);
+-	}
++static void ni_ao_cmd_set_trigger(struct comedi_device *dev,
++				  const struct comedi_cmd *cmd)
++{
++	struct ni_private *devpriv = dev->private;
+ 
+-	ni_ao_config_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len, 1);
++	ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG);
+ 
++	/* sync */
+ 	if (cmd->stop_src == TRIG_NONE) {
+ 		devpriv->ao_mode1 |= NISTC_AO_MODE1_CONTINUOUS;
+ 		devpriv->ao_mode1 &= ~NISTC_AO_MODE1_TRIGGER_ONCE;
+@@ -2957,179 +2983,346 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ 	}
+ 	ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG);
+ 
+-	val = devpriv->ao_trigger_select;
+-	switch (cmd->start_src) {
+-	case TRIG_INT:
+-	case TRIG_NOW:
+-		val &= ~(NISTC_AO_TRIG_START1_POLARITY |
+-			 NISTC_AO_TRIG_START1_SEL_MASK);
+-		val |= NISTC_AO_TRIG_START1_EDGE |
+-		       NISTC_AO_TRIG_START1_SYNC;
+-		break;
+-	case TRIG_EXT:
+-		val = NISTC_AO_TRIG_START1_SEL(CR_CHAN(cmd->start_arg) + 1);
+-		if (cmd->start_arg & CR_INVERT) {
+-			/* 0=active high, 1=active low. see daq-stc 3-24 (p186) */
+-			val |= NISTC_AO_TRIG_START1_POLARITY;
+-		}
+-		if (cmd->start_arg & CR_EDGE) {
+-			/* 0=edge detection disabled, 1=enabled */
+-			val |= NISTC_AO_TRIG_START1_EDGE;
++	{
++		unsigned int trigsel = devpriv->ao_trigger_select;
++
++		switch (cmd->start_src) {
++		case TRIG_INT:
++		case TRIG_NOW:
++			trigsel &= ~(NISTC_AO_TRIG_START1_POLARITY |
++				     NISTC_AO_TRIG_START1_SEL_MASK);
++			trigsel |= NISTC_AO_TRIG_START1_EDGE |
++				   NISTC_AO_TRIG_START1_SYNC;
++			break;
++		case TRIG_EXT:
++			trigsel = NISTC_AO_TRIG_START1_SEL(
++					CR_CHAN(cmd->start_arg) + 1);
++			if (cmd->start_arg & CR_INVERT)
++				/*
++				 * 0=active high, 1=active low.
++				 * see daq-stc 3-24 (p186)
++				 */
++				trigsel |= NISTC_AO_TRIG_START1_POLARITY;
++			if (cmd->start_arg & CR_EDGE)
++				/* 0=edge detection disabled, 1=enabled */
++				trigsel |= NISTC_AO_TRIG_START1_EDGE;
++			break;
++		default:
++			BUG();
++			break;
+ 		}
++
++		devpriv->ao_trigger_select = trigsel;
+ 		ni_stc_writew(dev, devpriv->ao_trigger_select,
+ 			      NISTC_AO_TRIG_SEL_REG);
+-		break;
+-	default:
+-		BUG();
+-		break;
+ 	}
+-	devpriv->ao_trigger_select = val;
+-	ni_stc_writew(dev, devpriv->ao_trigger_select, NISTC_AO_TRIG_SEL_REG);
++	/* AO_Delayed_START1 = 0, we do not support delayed start...yet */
+ 
++	/* sync */
++	/* select DA_START1 as PFI6/AO_START1 when configured as an output */
+ 	devpriv->ao_mode3 &= ~NISTC_AO_MODE3_TRIG_LEN;
+ 	ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG);
+ 
++	ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG);
++}
++
++static void ni_ao_cmd_set_counters(struct comedi_device *dev,
++				   const struct comedi_cmd *cmd)
++{
++	struct ni_private *devpriv = dev->private;
++	/* Not supporting 'waveform staging' or 'local buffer with pauses' */
++
++	ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG);
++	/*
++	 * This relies on ao_mode1/(Trigger_Once | Continuous) being set in
++	 * set_trigger above.  It is unclear whether we really need to re-write
++	 * this register with these values.  The mhddk examples for e-series
++	 * show writing this in both places, but the examples for m-series show
++	 * a single write in the set_counters function (here).
++	 */
+ 	ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG);
++
++	/* sync (upload number of buffer iterations -1) */
++	/* indicate that we want to use BC_Load_A_Register as the source */
+ 	devpriv->ao_mode2 &= ~NISTC_AO_MODE2_BC_INIT_LOAD_SRC;
+ 	ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG);
+-	if (cmd->stop_src == TRIG_NONE)
+-		ni_stc_writel(dev, 0xffffff, NISTC_AO_BC_LOADA_REG);
+-	else
+-		ni_stc_writel(dev, 0, NISTC_AO_BC_LOADA_REG);
++
++	/*
++	 * if the BC_TC interrupt is still issued in spite of UC, BC, UI
++	 * ignoring BC_TC, then we will need to find a way to ignore that
++	 * interrupt in continuous mode.
++	 */
++	ni_stc_writel(dev, 0, NISTC_AO_BC_LOADA_REG); /* iter once */
++
++	/* sync (issue command to load number of buffer iterations -1) */
+ 	ni_stc_writew(dev, NISTC_AO_CMD1_BC_LOAD, NISTC_AO_CMD1_REG);
++
++	/* sync (upload number of updates in buffer) */
++	/* indicate that we want to use UC_Load_A_Register as the source */
+ 	devpriv->ao_mode2 &= ~NISTC_AO_MODE2_UC_INIT_LOAD_SRC;
+ 	ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG);
+-	switch (cmd->stop_src) {
+-	case TRIG_COUNT:
++
++	{
++		/*
++		 * Current behavior is to configure the maximum update count
++		 * possible when continuous output mode is requested.
++		 */
++		unsigned int stop_arg = cmd->stop_src == TRIG_COUNT ?
++			(cmd->stop_arg & 0xffffff) : 0xffffff;
++
+ 		if (devpriv->is_m_series) {
+-			/*  this is how the NI example code does it for m-series boards, verified correct with 6259 */
+-			ni_stc_writel(dev, cmd->stop_arg - 1,
+-				      NISTC_AO_UC_LOADA_REG);
++			/*
++			 * this is how the NI example code does it for m-series
++			 * boards, verified correct with 6259
++			 */
++			ni_stc_writel(dev, stop_arg - 1, NISTC_AO_UC_LOADA_REG);
++
++			/* sync (issue cmd to load number of updates in MISB) */
+ 			ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD,
+ 				      NISTC_AO_CMD1_REG);
+ 		} else {
+-			ni_stc_writel(dev, cmd->stop_arg,
+-				      NISTC_AO_UC_LOADA_REG);
++			ni_stc_writel(dev, stop_arg, NISTC_AO_UC_LOADA_REG);
++
++			/* sync (issue cmd to load number of updates in MISB) */
+ 			ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD,
+ 				      NISTC_AO_CMD1_REG);
+-			ni_stc_writel(dev, cmd->stop_arg - 1,
+-				      NISTC_AO_UC_LOADA_REG);
++
++			/*
++			 * sync (upload number of updates-1 in MISB)
++			 * --eseries only?
++			 */
++			ni_stc_writel(dev, stop_arg - 1, NISTC_AO_UC_LOADA_REG);
+ 		}
+-		break;
+-	case TRIG_NONE:
+-		ni_stc_writel(dev, 0xffffff, NISTC_AO_UC_LOADA_REG);
+-		ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, NISTC_AO_CMD1_REG);
+-		ni_stc_writel(dev, 0xffffff, NISTC_AO_UC_LOADA_REG);
+-		break;
+-	default:
+-		ni_stc_writel(dev, 0, NISTC_AO_UC_LOADA_REG);
+-		ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, NISTC_AO_CMD1_REG);
+-		ni_stc_writel(dev, cmd->stop_arg, NISTC_AO_UC_LOADA_REG);
+ 	}
+ 
+-	devpriv->ao_mode1 &= ~(NISTC_AO_MODE1_UPDATE_SRC_MASK |
+-			       NISTC_AO_MODE1_UI_SRC_MASK |
+-			       NISTC_AO_MODE1_UPDATE_SRC_POLARITY |
+-			       NISTC_AO_MODE1_UI_SRC_POLARITY);
++	ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG);
++}
++
++static void ni_ao_cmd_set_update(struct comedi_device *dev,
++				 const struct comedi_cmd *cmd)
++{
++	struct ni_private *devpriv = dev->private;
++
++	ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG);
++
++	/*
++	 * zero out these bit fields to be set below. Does an ao-reset do this
++	 * automatically?
++	 */
++	devpriv->ao_mode1 &= ~(
++	  NISTC_AO_MODE1_UI_SRC_MASK         |
++	  NISTC_AO_MODE1_UI_SRC_POLARITY     |
++	  NISTC_AO_MODE1_UPDATE_SRC_MASK     |
++	  NISTC_AO_MODE1_UPDATE_SRC_POLARITY
++	);
++
+ 	switch (cmd->scan_begin_src) {
+ 	case TRIG_TIMER:
+-		devpriv->ao_cmd2 &= ~NISTC_AO_CMD2_BC_GATE_ENA;
+-		trigvar =
+-		    ni_ns_to_timer(dev, cmd->scan_begin_arg,
+-				   CMDF_ROUND_NEAREST);
+-		ni_stc_writel(dev, 1, NISTC_AO_UI_LOADA_REG);
+-		ni_stc_writew(dev, NISTC_AO_CMD1_UI_LOAD, NISTC_AO_CMD1_REG);
+-		ni_stc_writel(dev, trigvar, NISTC_AO_UI_LOADA_REG);
++		devpriv->ao_cmd2  &= ~NISTC_AO_CMD2_BC_GATE_ENA;
++
++		/*
++		 * NOTE: there are several other ways of configuring internal
++		 * updates, but we'll only support one for now:  using
++		 * AO_IN_TIMEBASE, w/o waveform staging, w/o a delay between
++		 * START1 and first update, and also w/o local buffer mode w/
++		 * pauses.
++		 */
++
++		/*
++		 * This is already done above:
++		 * devpriv->ao_mode1 &= ~(
++		 *   // set UPDATE_Source to UI_TC:
++		 *   NISTC_AO_MODE1_UPDATE_SRC_MASK |
++		 *   // set UPDATE_Source_Polarity to rising (required?)
++		 *   NISTC_AO_MODE1_UPDATE_SRC_POLARITY |
++		 *   // set UI_Source to AO_IN_TIMEBASE1:
++		 *   NISTC_AO_MODE1_UI_SRC_MASK     |
++		 *   // set UI_Source_Polarity to rising (required?)
++		 *   NISTC_AO_MODE1_UI_SRC_POLARITY
++		 * );
++		 */
++
++		/*
++		 * TODO:  use ao_ui_clock_source to allow all possible signals
++		 * to be routed to UI_Source_Select.  See tSTC.h for
++		 * eseries/ni67xx and tMSeries.h for mseries.
++		 */
++
++		{
++			unsigned trigvar = ni_ns_to_timer(dev,
++							  cmd->scan_begin_arg,
++							  CMDF_ROUND_NEAREST);
++
++			/*
++			 * Wait N TB3 ticks after the start trigger before
++			 * clocking(N must be >=2).
++			 */
++			/* following line: 2-1 per STC */
++			ni_stc_writel(dev, 1,           NISTC_AO_UI_LOADA_REG);
++			ni_stc_writew(dev, NISTC_AO_CMD1_UI_LOAD,
++				      NISTC_AO_CMD1_REG);
++			/* following line: N-1 per STC */
++			ni_stc_writel(dev, trigvar - 1, NISTC_AO_UI_LOADA_REG);
++		}
+ 		break;
+ 	case TRIG_EXT:
+-		devpriv->ao_mode1 |=
+-		    NISTC_AO_MODE1_UPDATE_SRC(cmd->scan_begin_arg);
++		/* FIXME:  assert scan_begin_arg != 0, ret failure otherwise */
++		devpriv->ao_cmd2  |= NISTC_AO_CMD2_BC_GATE_ENA;
++		devpriv->ao_mode1 |= NISTC_AO_MODE1_UPDATE_SRC(
++					CR_CHAN(cmd->scan_begin_arg));
+ 		if (cmd->scan_begin_arg & CR_INVERT)
+ 			devpriv->ao_mode1 |= NISTC_AO_MODE1_UPDATE_SRC_POLARITY;
+-		devpriv->ao_cmd2 |= NISTC_AO_CMD2_BC_GATE_ENA;
+ 		break;
+ 	default:
+ 		BUG();
+ 		break;
+ 	}
++
+ 	ni_stc_writew(dev, devpriv->ao_cmd2, NISTC_AO_CMD2_REG);
+ 	ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG);
+ 	devpriv->ao_mode2 &= ~(NISTC_AO_MODE2_UI_RELOAD_MODE(3) |
+ 			       NISTC_AO_MODE2_UI_INIT_LOAD_SRC);
+ 	ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG);
+ 
++	/* Configure DAQ-STC for Timed update mode */
++	devpriv->ao_cmd1 |= NISTC_AO_CMD1_DAC1_UPDATE_MODE |
++			    NISTC_AO_CMD1_DAC0_UPDATE_MODE;
++	/* We are not using UPDATE2-->don't have to set DACx_Source_Select */
++	ni_stc_writew(dev, devpriv->ao_cmd1, NISTC_AO_CMD1_REG);
++
++	ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG);
++}
++
++static void ni_ao_cmd_set_channels(struct comedi_device *dev,
++				   struct comedi_subdevice *s)
++{
++	struct ni_private *devpriv = dev->private;
++	const struct comedi_cmd *cmd = &s->async->cmd;
++	unsigned bits = 0;
++
++	ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG);
++
++	if (devpriv->is_6xxx) {
++		unsigned int i;
++
++		bits = 0;
++		for (i = 0; i < cmd->chanlist_len; ++i) {
++			int chan = CR_CHAN(cmd->chanlist[i]);
++
++			bits |= 1 << chan;
++			ni_ao_win_outw(dev, chan, NI611X_AO_WAVEFORM_GEN_REG);
++		}
++		ni_ao_win_outw(dev, bits, NI611X_AO_TIMED_REG);
++	}
++
++	ni_ao_config_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len, 1);
++
+ 	if (cmd->scan_end_arg > 1) {
+ 		devpriv->ao_mode1 |= NISTC_AO_MODE1_MULTI_CHAN;
+-		ni_stc_writew(dev,
+-			      NISTC_AO_OUT_CTRL_CHANS(cmd->scan_end_arg - 1) |
+-			      NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ,
+-			      NISTC_AO_OUT_CTRL_REG);
+-	} else {
+-		unsigned bits;
++		bits = NISTC_AO_OUT_CTRL_CHANS(cmd->scan_end_arg - 1)
++				 | NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ;
+ 
++	} else {
+ 		devpriv->ao_mode1 &= ~NISTC_AO_MODE1_MULTI_CHAN;
+ 		bits = NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ;
+-		if (devpriv->is_m_series || devpriv->is_6xxx) {
++		if (devpriv->is_m_series | devpriv->is_6xxx)
+ 			bits |= NISTC_AO_OUT_CTRL_CHANS(0);
+-		} else {
+-			bits |=
+-			    NISTC_AO_OUT_CTRL_CHANS(CR_CHAN(cmd->chanlist[0]));
+-		}
+-		ni_stc_writew(dev, bits, NISTC_AO_OUT_CTRL_REG);
++		else
++			bits |= NISTC_AO_OUT_CTRL_CHANS(
++					CR_CHAN(cmd->chanlist[0]));
+ 	}
++
+ 	ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG);
++	ni_stc_writew(dev, bits,              NISTC_AO_OUT_CTRL_REG);
+ 
+-	/* Configure DAQ-STC for Timed update mode */
+-	devpriv->ao_cmd1 |= NISTC_AO_CMD1_DAC1_UPDATE_MODE |
+-			    NISTC_AO_CMD1_DAC0_UPDATE_MODE;
+-	/* We are not using UPDATE2-->don't have to set DACx_Source_Select */
+-	ni_stc_writew(dev, devpriv->ao_cmd1, NISTC_AO_CMD1_REG);
++	ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG);
++}
++
++static void ni_ao_cmd_set_stop_conditions(struct comedi_device *dev,
++					  const struct comedi_cmd *cmd)
++{
++	struct ni_private *devpriv = dev->private;
++
++	ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG);
+ 
+ 	devpriv->ao_mode3 |= NISTC_AO_MODE3_STOP_ON_OVERRUN_ERR;
+ 	ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG);
+ 
++	/*
++	 * Since we are not supporting waveform staging, we ignore these errors:
++	 * NISTC_AO_MODE3_STOP_ON_BC_TC_ERR,
++	 * NISTC_AO_MODE3_STOP_ON_BC_TC_TRIG_ERR
++	 */
++
++	ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG);
++}
++
++static void ni_ao_cmd_set_fifo_mode(struct comedi_device *dev)
++{
++	struct ni_private *devpriv = dev->private;
++
++	ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG);
++
+ 	devpriv->ao_mode2 &= ~NISTC_AO_MODE2_FIFO_MODE_MASK;
+ #ifdef PCIDMA
+ 	devpriv->ao_mode2 |= NISTC_AO_MODE2_FIFO_MODE_HF_F;
+ #else
+ 	devpriv->ao_mode2 |= NISTC_AO_MODE2_FIFO_MODE_HF;
+ #endif
++	/* NOTE:  this is where use_onboard_memory=True would be implemented */
+ 	devpriv->ao_mode2 &= ~NISTC_AO_MODE2_FIFO_REXMIT_ENA;
+ 	ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG);
+ 
+-	bits = NISTC_AO_PERSONAL_BC_SRC_SEL |
+-	       NISTC_AO_PERSONAL_UPDATE_PW |
+-	       NISTC_AO_PERSONAL_TMRDACWR_PW;
+-	if (board->ao_fifo_depth)
+-		bits |= NISTC_AO_PERSONAL_FIFO_ENA;
+-	else
+-		bits |= NISTC_AO_PERSONAL_DMA_PIO_CTRL;
+-#if 0
+-	/*
+-	 * F Hess: windows driver does not set NISTC_AO_PERSONAL_NUM_DAC bit
+-	 * for 6281, verified with bus analyzer.
+-	 */
+-	if (devpriv->is_m_series)
+-		bits |= NISTC_AO_PERSONAL_NUM_DAC;
+-#endif
+-	ni_stc_writew(dev, bits, NISTC_AO_PERSONAL_REG);
+-	/*  enable sending of ao dma requests */
++	/* enable sending of ao fifo requests (dma request) */
+ 	ni_stc_writew(dev, NISTC_AO_START_AOFREQ_ENA, NISTC_AO_START_SEL_REG);
+ 
+ 	ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG);
+ 
+-	if (cmd->stop_src == TRIG_COUNT) {
+-		ni_stc_writew(dev, NISTC_INTB_ACK_AO_BC_TC,
+-			      NISTC_INTB_ACK_REG);
++	/* we are not supporting boards with virtual fifos */
++}
++
++static void ni_ao_cmd_set_interrupts(struct comedi_device *dev,
++				     struct comedi_subdevice *s)
++{
++	if (s->async->cmd.stop_src == TRIG_COUNT)
+ 		ni_set_bits(dev, NISTC_INTB_ENA_REG,
+ 			    NISTC_INTB_ENA_AO_BC_TC, 1);
+-	}
+ 
+ 	s->async->inttrig = ni_ao_inttrig;
++}
+ 
++static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
++{
++	struct ni_private *devpriv = dev->private;
++	const struct comedi_cmd *cmd = &s->async->cmd;
++
++	if (dev->irq == 0) {
++		dev_err(dev->class_dev, "cannot run command without an irq");
++		return -EIO;
++	}
++
++	/* ni_ao_reset should have already been done */
++	ni_ao_cmd_personalize(dev, cmd);
++	/* clearing fifo and preload happens elsewhere */
++
++	ni_ao_cmd_set_trigger(dev, cmd);
++	ni_ao_cmd_set_counters(dev, cmd);
++	ni_ao_cmd_set_update(dev, cmd);
++	ni_ao_cmd_set_channels(dev, s);
++	ni_ao_cmd_set_stop_conditions(dev, cmd);
++	ni_ao_cmd_set_fifo_mode(dev);
++	ni_ao_cmd_set_interrupts(dev, s);
++
++	/*
++	 * arm(ing) and star(ting) happen in ni_ao_inttrig, which _must_ be
++	 * called for ao commands since 1) TRIG_NOW is not supported and 2) DMA
++	 * must be setup and initially written to before arm/start happen.
++	 */
+ 	return 0;
+ }
+ 
++/* end ni_ao_cmd */
++
+ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+ 			 struct comedi_cmd *cmd)
+ {

commit d2a6c32a2209ac79cb52b56e46ec37fdc1df6ce1
+Author: Spencer E. Olson 
+Date:   Wed Jan 27 14:28:26 2016 -0700
+
+    staging: comedi: ni_mio_common: make more bits in ao_cmd1 reg be stateful
+    
+    Bits NISTC_AO_CMD1_DAC0_UPDATE_MODE and NISTC_AO_CMD1_DAC1_UPDATE_MODE are
+    now saved in the local copy of the AO_CMD1 register.  This is more
+    appropriate than prior methods of setting these bits specifically _both_
+    in the ni_ao_cmd configuration function _and_ the ni_ao_inttrig trigger
+    function.  With this patch, the bits are only specifically called out now
+    in the ni_ao_cmd configuration function.  In the ni_ao_inttrig trigger
+    function, only the UI_ARM, UC_ARM, BC_ARM bits of the ao_cmd1 register are
+    specifically called out.  Each of these bits is a strobe bit, while the
+    DAC[0-1]_UPDATE_MODE bits are simple write bits.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index 7d2091d8b72b..9df20d922d32 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -2903,8 +2903,6 @@ static int ni_ao_inttrig(struct comedi_device *dev,
+ 	ni_stc_writew(dev, NISTC_AO_CMD1_UI_ARM |
+ 			   NISTC_AO_CMD1_UC_ARM |
+ 			   NISTC_AO_CMD1_BC_ARM |
+-			   NISTC_AO_CMD1_DAC1_UPDATE_MODE |
+-			   NISTC_AO_CMD1_DAC0_UPDATE_MODE |
+ 			   devpriv->ao_cmd1,
+ 		      NISTC_AO_CMD1_REG);
+ 
+@@ -3081,9 +3079,11 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ 	}
+ 	ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG);
+ 
+-	ni_stc_writew(dev, NISTC_AO_CMD1_DAC1_UPDATE_MODE |
+-			   NISTC_AO_CMD1_DAC0_UPDATE_MODE,
+-		      NISTC_AO_CMD1_REG);
++	/* Configure DAQ-STC for Timed update mode */
++	devpriv->ao_cmd1 |= NISTC_AO_CMD1_DAC1_UPDATE_MODE |
++			    NISTC_AO_CMD1_DAC0_UPDATE_MODE;
++	/* We are not using UPDATE2-->don't have to set DACx_Source_Select */
++	ni_stc_writew(dev, devpriv->ao_cmd1, NISTC_AO_CMD1_REG);
+ 
+ 	devpriv->ao_mode3 |= NISTC_AO_MODE3_STOP_ON_OVERRUN_ERR;
+ 	ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG);

commit 5c93736c208d89c7832624b8f3a2ce616473ab65
+Author: Spencer E. Olson 
+Date:   Wed Jan 27 14:28:25 2016 -0700
+
+    staging: comedi: ni_mio_common: Cleans up/clarifies ni_ao_reset
+    
+    This patch implements ni_ao_reset much more closely organized like NI MHDDK
+    examples and DAQ-STC pseudo-code.  Adds comments with some more specific
+    references to the DAQ-STC.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index 1978d65636fd..7d2091d8b72b 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -3215,48 +3215,70 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
+ 
+ static int ni_ao_reset(struct comedi_device *dev, struct comedi_subdevice *s)
+ {
++	/* See 3.6.1.2 "Resetting", of DAQ-STC Technical Reference Manual */
++
++	/*
++	 * In the following, the "--sync" comments are meant to denote
++	 * asynchronous boundaries for setting the registers as described in the
++	 * DAQ-STC mostly in the order also described in the DAQ-STC.
++	 */
++
+ 	struct ni_private *devpriv = dev->private;
+ 
+ 	ni_release_ao_mite_channel(dev);
+ 
++	/* --sync (reset AO) */
++	if (devpriv->is_m_series)
++		/* following example in mhddk for m-series */
++		ni_stc_writew(dev, NISTC_RESET_AO, NISTC_RESET_REG);
++
++	/*--sync (start config) */
+ 	ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG);
++
++	/*--sync (Disarm) */
+ 	ni_stc_writew(dev, NISTC_AO_CMD1_DISARM, NISTC_AO_CMD1_REG);
+-	ni_set_bits(dev, NISTC_INTB_ENA_REG, ~0, 0);
+-	ni_stc_writew(dev, NISTC_AO_PERSONAL_BC_SRC_SEL, NISTC_AO_PERSONAL_REG);
+-	ni_stc_writew(dev, NISTC_INTB_ACK_AO_ALL, NISTC_INTB_ACK_REG);
+-	ni_stc_writew(dev, NISTC_AO_PERSONAL_BC_SRC_SEL |
+-			   NISTC_AO_PERSONAL_UPDATE_PW |
+-			   NISTC_AO_PERSONAL_TMRDACWR_PW,
+-		      NISTC_AO_PERSONAL_REG);
+-	ni_stc_writew(dev, 0, NISTC_AO_OUT_CTRL_REG);
+-	ni_stc_writew(dev, 0, NISTC_AO_START_SEL_REG);
+-	devpriv->ao_cmd1 = 0;
+-	ni_stc_writew(dev, devpriv->ao_cmd1, NISTC_AO_CMD1_REG);
+-	devpriv->ao_cmd2 = 0;
+-	ni_stc_writew(dev, devpriv->ao_cmd2, NISTC_AO_CMD2_REG);
++
++	/*
++	 * --sync
++	 * (clear bunch of registers--mseries mhddk examples do not include
++	 * this)
++	 */
++	devpriv->ao_cmd1  = 0;
++	devpriv->ao_cmd2  = 0;
+ 	devpriv->ao_mode1 = 0;
+-	ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG);
+ 	devpriv->ao_mode2 = 0;
+-	ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG);
+ 	if (devpriv->is_m_series)
+ 		devpriv->ao_mode3 = NISTC_AO_MODE3_LAST_GATE_DISABLE;
+ 	else
+ 		devpriv->ao_mode3 = 0;
+-	ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG);
+ 	devpriv->ao_trigger_select = 0;
+-	ni_stc_writew(dev, devpriv->ao_trigger_select,
+-		      NISTC_AO_TRIG_SEL_REG);
+-	if (devpriv->is_6xxx) {
+-		unsigned immediate_bits = 0;
+-		unsigned i;
+ 
+-		for (i = 0; i < s->n_chan; ++i)
+-			immediate_bits |= 1 << i;
+-		ni_ao_win_outw(dev, immediate_bits, NI671X_AO_IMMEDIATE_REG);
++	ni_stc_writew(dev, 0, NISTC_AO_PERSONAL_REG);
++	ni_stc_writew(dev, 0, NISTC_AO_CMD1_REG);
++	ni_stc_writew(dev, 0, NISTC_AO_CMD2_REG);
++	ni_stc_writew(dev, 0, NISTC_AO_MODE1_REG);
++	ni_stc_writew(dev, 0, NISTC_AO_MODE2_REG);
++	ni_stc_writew(dev, 0, NISTC_AO_OUT_CTRL_REG);
++	ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG);
++	ni_stc_writew(dev, 0, NISTC_AO_START_SEL_REG);
++	ni_stc_writew(dev, 0, NISTC_AO_TRIG_SEL_REG);
++
++	/*--sync (disable interrupts) */
++	ni_set_bits(dev, NISTC_INTB_ENA_REG, ~0, 0);
++
++	/*--sync (ack) */
++	ni_stc_writew(dev, NISTC_AO_PERSONAL_BC_SRC_SEL, NISTC_AO_PERSONAL_REG);
++	ni_stc_writew(dev, NISTC_INTB_ACK_AO_ALL, NISTC_INTB_ACK_REG);
++
++	/*--not in DAQ-STC.  which doc? */
++	if (devpriv->is_6xxx) {
++		ni_ao_win_outw(dev, (1u << s->n_chan) - 1u,
++			       NI671X_AO_IMMEDIATE_REG);
+ 		ni_ao_win_outw(dev, NI611X_AO_MISC_CLEAR_WG,
+ 			       NI611X_AO_MISC_REG);
+ 	}
+ 	ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG);
++	/*--end */
+ 
+ 	return 0;
+ }

commit 5b293beb2ef0c45cd3c0e00ce67930b5d3471c13
+Author: Spencer E. Olson 
+Date:   Wed Jan 27 14:28:24 2016 -0700
+
+    staging: comedi: mite: enable continuous regeneration of finite samples
+    
+    This change enables the mite DMA controller to only transfer the amount of
+    data needed by a command.  By default, the old behavior of transferring the
+    entire comedi DMA data buffer is still in effect.  These changes allow a
+    command to only transmit a limited portion of that data buffer as needed.
+    
+    This patch begins to reinterprets stop_arg when stop_src == TRIG_NONE to
+    allow the user to specify the length of the buffer that should be repeated.
+    The intent is to allow a user to have a specific buffer repeated as-is
+    indefinitely.  The contents of the DMA buffer can be left static or changed
+    by the user via mmap access to the DMA buffer.  If the contents are changed
+    by the user, additional munging is not performed by the driver and only a
+    single call to comedi_mark_buffer_written should be done.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c
+index fa7ae2c04556..8f24702c3380 100644
+--- a/drivers/staging/comedi/drivers/mite.c
++++ b/drivers/staging/comedi/drivers/mite.c
+@@ -297,7 +297,6 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring,
+ {
+ 	struct comedi_async *async = s->async;
+ 	unsigned int n_links;
+-	int i;
+ 
+ 	if (ring->descriptors) {
+ 		dma_free_coherent(ring->hw_dev,
+@@ -326,17 +325,58 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring,
+ 	}
+ 	ring->n_links = n_links;
+ 
+-	for (i = 0; i < n_links; i++) {
++	return mite_init_ring_descriptors(ring, s, n_links << PAGE_SHIFT);
++}
++EXPORT_SYMBOL_GPL(mite_buf_change);
++
++/*
++ * initializes the ring buffer descriptors to provide correct DMA transfer links
++ * to the exact amount of memory required.  When the ring buffer is allocated in
++ * mite_buf_change, the default is to initialize the ring to refer to the entire
++ * DMA data buffer.  A command may call this function later to re-initialize and
++ * shorten the amount of memory that will be transferred.
++ */
++int mite_init_ring_descriptors(struct mite_dma_descriptor_ring *ring,
++			       struct comedi_subdevice *s,
++			       unsigned int nbytes)
++{
++	struct comedi_async *async = s->async;
++	unsigned int n_full_links = nbytes >> PAGE_SHIFT;
++	unsigned int remainder = nbytes % PAGE_SIZE;
++	int i;
++
++	dev_dbg(s->device->class_dev,
++		"mite: init ring buffer to %u bytes\n", nbytes);
++
++	if ((n_full_links + (remainder > 0 ? 1 : 0)) > ring->n_links) {
++		dev_err(s->device->class_dev,
++			"mite: ring buffer too small for requested init\n");
++		return -ENOMEM;
++	}
++
++	/* We set the descriptors for all full links. */
++	for (i = 0; i < n_full_links; ++i) {
+ 		ring->descriptors[i].count = cpu_to_le32(PAGE_SIZE);
+ 		ring->descriptors[i].addr =
+ 		    cpu_to_le32(async->buf_map->page_list[i].dma_addr);
+ 		ring->descriptors[i].next =
+-		    cpu_to_le32(ring->descriptors_dma_addr + (i +
+-							      1) *
+-				sizeof(struct mite_dma_descriptor));
++		    cpu_to_le32(ring->descriptors_dma_addr +
++				(i + 1) * sizeof(struct mite_dma_descriptor));
+ 	}
+-	ring->descriptors[n_links - 1].next =
+-	    cpu_to_le32(ring->descriptors_dma_addr);
++
++	/* the last link is either a remainder or was a full link. */
++	if (remainder > 0) {
++		/* set the lesser count for the remainder link */
++		ring->descriptors[i].count = cpu_to_le32(remainder);
++		ring->descriptors[i].addr =
++		    cpu_to_le32(async->buf_map->page_list[i].dma_addr);
++		/* increment i so that assignment below refs last link */
++		++i;
++	}
++
++	/* Assign the last link->next to point back to the head of the list. */
++	ring->descriptors[i - 1].next = cpu_to_le32(ring->descriptors_dma_addr);
++
+ 	/*
+ 	 * barrier is meant to insure that all the writes to the dma descriptors
+ 	 * have completed before the dma controller is commanded to read them
+@@ -344,7 +384,7 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring,
+ 	smp_wmb();
+ 	return 0;
+ }
+-EXPORT_SYMBOL_GPL(mite_buf_change);
++EXPORT_SYMBOL_GPL(mite_init_ring_descriptors);
+ 
+ void mite_prep_dma(struct mite_channel *mite_chan,
+ 		   unsigned int num_device_bits, unsigned int num_memory_bits)
+@@ -552,6 +592,7 @@ int mite_sync_output_dma(struct mite_channel *mite_chan,
+ 	unsigned int old_alloc_count = async->buf_read_alloc_count;
+ 	u32 nbytes_ub, nbytes_lb;
+ 	int count;
++	bool finite_regen = (cmd->stop_src == TRIG_NONE && stop_count != 0);
+ 
+ 	/* read alloc as much as we can */
+ 	comedi_buf_read_alloc(s, async->prealloc_bufsz);
+@@ -561,11 +602,24 @@ int mite_sync_output_dma(struct mite_channel *mite_chan,
+ 	nbytes_ub = mite_bytes_read_from_memory_ub(mite_chan);
+ 	if (cmd->stop_src == TRIG_COUNT && (int)(nbytes_ub - stop_count) > 0)
+ 		nbytes_ub = stop_count;
+-	if ((int)(nbytes_ub - old_alloc_count) > 0) {
++
++	if ((!finite_regen || stop_count > old_alloc_count) &&
++	    ((int)(nbytes_ub - old_alloc_count) > 0)) {
+ 		dev_warn(s->device->class_dev, "mite: DMA underrun\n");
+ 		async->events |= COMEDI_CB_OVERFLOW;
+ 		return -1;
+ 	}
++
++	if (finite_regen) {
++		/*
++		 * This is a special case where we continuously output a finite
++		 * buffer.  In this case, we do not free any of the memory,
++		 * hence we expect that old_alloc_count will reach a maximum of
++		 * stop_count bytes.
++		 */
++		return 0;
++	}
++
+ 	count = nbytes_lb - async->buf_read_count;
+ 	if (count <= 0)
+ 		return 0;
+diff --git a/drivers/staging/comedi/drivers/mite.h b/drivers/staging/comedi/drivers/mite.h
+index c32d4e4ddccc..87534b07ec81 100644
+--- a/drivers/staging/comedi/drivers/mite.h
++++ b/drivers/staging/comedi/drivers/mite.h
+@@ -110,6 +110,9 @@ void mite_prep_dma(struct mite_channel *mite_chan,
+ 		   unsigned int num_device_bits, unsigned int num_memory_bits);
+ int mite_buf_change(struct mite_dma_descriptor_ring *ring,
+ 		    struct comedi_subdevice *s);
++int mite_init_ring_descriptors(struct mite_dma_descriptor_ring *ring,
++			       struct comedi_subdevice *s,
++			       unsigned int nbytes);
+ 
+ enum mite_registers {
+ 	/*

commit f08a28e65cbdf80b4b4da7e423c45ee7c3ef35ac
+Author: Spencer E. Olson 
+Date:   Tue Jan 12 11:05:10 2016 -0700
+
+    staging: comedi: ni_mio_common: use CR_CHAN more consistently
+    
+    Generally, the CR_CHAN macro is/should be used to access the relevant bits
+    for channel identification in cmd->*_arg when the corresponding
+    cmd->*_src==TRIG_EXT, including cmd->convert_arg in this case.
+    
+    This patch does not fix a bug per se, as NISTC_AI_MODE1_CONVERT_SRC() already
+    masks the value sufficiently, but using CR_CHAN() here makes the code clearer as
+    it avoids passing some irrelevant bits to NISTC_AI_MODE1_CONVERT_SRC() in the
+    first place.
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
+index 5e8130a7d670..1978d65636fd 100644
+--- a/drivers/staging/comedi/drivers/ni_mio_common.c
++++ b/drivers/staging/comedi/drivers/ni_mio_common.c
+@@ -2428,7 +2428,8 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+ 		ni_stc_writew(dev, mode2, NISTC_AI_MODE2_REG);
+ 		break;
+ 	case TRIG_EXT:
+-		mode1 |= NISTC_AI_MODE1_CONVERT_SRC(1 + cmd->convert_arg);
++		mode1 |= NISTC_AI_MODE1_CONVERT_SRC(1 +
++						    CR_CHAN(cmd->convert_arg));
+ 		if ((cmd->convert_arg & CR_INVERT) == 0)
+ 			mode1 |= NISTC_AI_MODE1_CONVERT_POLARITY;
+ 		ni_stc_writew(dev, mode1, NISTC_AI_MODE1_REG);

commit 1fd24a4702d2af0ea4d5845126cf57d4d1796216
+Author: Spencer E. Olson 
+Date:   Tue Jan 12 10:33:18 2016 -0700
+
+    staging: comedi: ni_tiocmd: change mistaken use of start_src for start_arg
+    
+    This fixes a bug in function ni_tio_input_inttrig().  The trigger number
+    should be compared to cmd->start_arg, not cmd->start_src.
+    
+    Fixes: 6a760394d7eb ("staging: comedi: ni_tiocmd: clarify the cmd->start_arg validation and use")
+    Cc:  # 3.17+
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c
+index 437f723bb34d..823e47910004 100644
+--- a/drivers/staging/comedi/drivers/ni_tiocmd.c
++++ b/drivers/staging/comedi/drivers/ni_tiocmd.c
+@@ -92,7 +92,7 @@ static int ni_tio_input_inttrig(struct comedi_device *dev,
+ 	unsigned long flags;
+ 	int ret = 0;
+ 
+-	if (trig_num != cmd->start_src)
++	if (trig_num != cmd->start_arg)
+ 		return -EINVAL;
+ 
+ 	spin_lock_irqsave(&counter->lock, flags);

commit d4631301225a44d36b98ce39a2e3d6e00f59d8fb
+Author: Spencer E. Olson 
+Date:   Mon Jan 11 23:29:33 2016 -0700
+
+    staging: comedi: ni_pcimio: Adds PXI-6251 to supported boards
+    
+    Signed-off-by: Spencer E. Olson 
+    Reviewed-by: Ian Abbott 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
+index 30a5a75d1fe7..231e37d6b7c6 100644
+--- a/drivers/staging/comedi/drivers/ni_pcimio.c
++++ b/drivers/staging/comedi/drivers/ni_pcimio.c
+@@ -26,7 +26,8 @@ Devices: [National Instruments] PCI-MIO-16XE-50 (ni_pcimio),
+   PXI-6040E, PCI-6030E, PCI-6031E, PCI-6032E, PCI-6033E, PCI-6071E, PCI-6023E,
+   PCI-6024E, PCI-6025E, PXI-6025E, PCI-6034E, PCI-6035E, PCI-6052E,
+   PCI-6110, PCI-6111, PCI-6220, PCI-6221, PCI-6224, PXI-6224,
+-  PCI-6225, PXI-6225, PCI-6229, PCI-6250, PCI-6251, PCIe-6251, PXIe-6251,
++  PCI-6225, PXI-6225, PCI-6229, PCI-6250,
++  PCI-6251, PXI-6251, PCIe-6251, PXIe-6251,
+   PCI-6254, PCI-6259, PCIe-6259,
+   PCI-6280, PCI-6281, PXI-6281, PCI-6284, PCI-6289,
+   PCI-6711, PXI-6711, PCI-6713, PXI-6713,
+@@ -193,6 +194,7 @@ enum ni_pcimio_boardid {
+ 	BOARD_PCI6229,
+ 	BOARD_PCI6250,
+ 	BOARD_PCI6251,
++	BOARD_PXI6251,
+ 	BOARD_PCIE6251,
+ 	BOARD_PXIE6251,
+ 	BOARD_PCI6254,
+@@ -811,6 +813,21 @@ static const struct ni_board_struct ni_boards[] = {
+ 		.ao_speed	= 350,
+ 		.caldac		= { caldac_none },
+ 	},
++	[BOARD_PXI6251] = {
++		.name		= "pxi-6251",
++		.n_adchan	= 16,
++		.ai_maxdata	= 0xffff,
++		.ai_fifo_depth	= 4095,
++		.gainlkup	= ai_gain_628x,
++		.ai_speed	= 800,
++		.n_aochan	= 2,
++		.ao_maxdata	= 0xffff,
++		.ao_fifo_depth	= 8191,
++		.ao_range_table	= &range_ni_M_625x_ao,
++		.reg_type	= ni_reg_625x,
++		.ao_speed	= 350,
++		.caldac		= { caldac_none },
++	},
+ 	[BOARD_PCIE6251] = {
+ 		.name		= "pcie-6251",
+ 		.n_adchan	= 16,
+@@ -1290,6 +1307,7 @@ static const struct pci_device_id ni_pcimio_pci_table[] = {
+ 	{ PCI_VDEVICE(NI, 0x71bc), BOARD_PCI6221_37PIN },
+ 	{ PCI_VDEVICE(NI, 0x717d), BOARD_PCIE6251 },
+ 	{ PCI_VDEVICE(NI, 0x72e8), BOARD_PXIE6251 },
++	{ PCI_VDEVICE(NI, 0x70ad), BOARD_PXI6251 },
+ 	{ 0 }
+ };
+ MODULE_DEVICE_TABLE(pci, ni_pcimio_pci_table);

commit a41cbe86df3afbc82311a1640e20858c0cd7e065
+Author: Olga Kornievskaia 
+Date:   Mon Sep 14 19:54:36 2015 -0400
+
+    Failing to send a CLOSE if file is opened WRONLY and server reboots on a 4.x mount
+    
+    A test case is as the description says:
+    open(foobar, O_WRONLY);
+    sleep()  --> reboot the server
+    close(foobar)
+    
+    The bug is because in nfs4state.c in nfs4_reclaim_open_state() a few
+    line before going to restart, there is
+    clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &state->flags).
+    
+    NFS4CLNT_RECLAIM_NOGRACE is a flag for the client states not open
+    owner states. Value of NFS4CLNT_RECLAIM_NOGRACE is 4 which is the
+    value of NFS_O_WRONLY_STATE in nfs4_state->flags. So clearing it wipes
+    out state and when we go to close it, “call_close” doesn’t get set as
+    state flag is not set and CLOSE doesn’t go on the wire.
+    
+    Signed-off-by: Olga Kornievskaia 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
+index da73bc443238..5db324635e92 100644
+--- a/fs/nfs/nfs4state.c
++++ b/fs/nfs/nfs4state.c
+@@ -1481,7 +1481,7 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs
+ 					spin_unlock(&state->state_lock);
+ 				}
+ 				nfs4_put_open_state(state);
+-				clear_bit(NFS4CLNT_RECLAIM_NOGRACE,
++				clear_bit(NFS_STATE_RECLAIM_NOGRACE,
+ 					&state->flags);
+ 				spin_lock(&sp->so_lock);
+ 				goto restart;

commit 5df4eb054fe056ecb15875e812fdadbc47568d7d
+Author: John DeSilva 
+Date:   Fri Sep 5 11:13:17 2014 -0400
+
+    HID: Add Holtek USB ID 04d9:a0c2 ETEKCITY Scroll
+    
+    The report descriptor for the HOLTEK USB ID 04d9:a0c2 (ETEKCITY Scroll
+    T-140 Gaming Mouse) is set to a very large amount of consumer usages
+    (2^16), exceeding HID_MAX_USAGES. Added id, bindings and comments for
+    the mouse, added to hid_have_special_driver, and reduced the usage and
+    logical maximums to 0x2fff, consistent with the other mice in the
+    category. Tested on the hardware.
+    
+    Signed-off-by: John C. DeSilva 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
+index c527f5ec4cfc..eb50818de41f 100644
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -1793,6 +1793,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A070) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081) },
++	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A0C2) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_TABLET) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_JESS2, USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD) },
+ 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
+diff --git a/drivers/hid/hid-holtek-mouse.c b/drivers/hid/hid-holtek-mouse.c
+index d60fbd0adc0c..78b3a0c76775 100644
+--- a/drivers/hid/hid-holtek-mouse.c
++++ b/drivers/hid/hid-holtek-mouse.c
+@@ -29,6 +29,7 @@
+  *   and Zalman ZM-GM1
+  * - USB ID 04d9:a081, sold as SHARKOON DarkGlider Gaming mouse
+  * - USB ID 04d9:a072, sold as LEETGION Hellion Gaming Mouse
++ * - USB ID 04d9:a0c2, sold as ETEKCITY Scroll T-140 Gaming Mouse
+  */
+ 
+ static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+@@ -42,6 +43,7 @@ static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+ 		switch (hdev->product) {
+ 		case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067:
+ 		case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072:
++		case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A0C2:
+ 			if (*rsize >= 122 && rdesc[115] == 0xff && rdesc[116] == 0x7f
+ 					&& rdesc[120] == 0xff && rdesc[121] == 0x7f) {
+ 				hid_info(hdev, "Fixing up report descriptor\n");
+@@ -74,6 +76,8 @@ static const struct hid_device_id holtek_mouse_devices[] = {
+ 			USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072) },
+ 	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT,
+ 			USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081) },
++	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT,
++			USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A0C2) },
+ 	{ }
+ };
+ MODULE_DEVICE_TABLE(hid, holtek_mouse_devices);
+diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
+index 3943ffe1a333..29e9b4872ebd 100644
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -479,6 +479,7 @@
+ #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A070	0xa070
+ #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072	0xa072
+ #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081	0xa081
++#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A0C2	0xa0c2
+ #define USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A096	0xa096
+ 
+ #define USB_VENDOR_ID_IMATION		0x0718

commit d14b71231e78645008c3e2edee5496b4722d4d62
+Author: Lars Hamre 
+Date:   Thu Aug 7 21:21:42 2014 -0400
+
+    Staging: nokia_h4p: removed unnecessary return statement in nokia_fw.c
+    
+    This is a patch to the nokia_fw.c file that removes an unnecessary return statement found by the checkpatch.pl tool
+    
+    Signed-off-by: Lars Hamre 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/nokia_h4p/nokia_fw.c b/drivers/staging/nokia_h4p/nokia_fw.c
+index 14ba2193efb6..18953aed5a29 100644
+--- a/drivers/staging/nokia_h4p/nokia_fw.c
++++ b/drivers/staging/nokia_h4p/nokia_fw.c
+@@ -197,8 +197,6 @@ void hci_h4p_parse_fw_event(struct hci_h4p_info *info, struct sk_buff *skb)
+ 		dev_err(info->dev, "Don't know how to parse fw event\n");
+ 		info->fw_error = -EINVAL;
+ 	}
+-
+-	return;
+ }
+ 
+ MODULE_FIRMWARE(FW_NAME_TI1271_PRELE);

commit 1a9357f443d64aa41e9b0dc414953663a6fcca19
+Author: Jim Rees 
+Date:   Fri May 17 17:33:00 2013 -0400
+
+    nfsd: avoid undefined signed overflow
+    
+    In C, signed integer overflow results in undefined behavior, but unsigned
+    overflow wraps around. So do the subtraction first, then cast to signed.
+    
+    Reported-by: Joakim Tjernlund 
+    Signed-off-by: Jim Rees 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 91ead0ed9f11..72f0c4e9a942 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -3427,7 +3427,7 @@ grace_disallows_io(struct net *net, struct inode *inode)
+ /* Returns true iff a is later than b: */
+ static bool stateid_generation_after(stateid_t *a, stateid_t *b)
+ {
+-	return (s32)a->si_generation - (s32)b->si_generation > 0;
++	return (s32)(a->si_generation - b->si_generation) > 0;
+ }
+ 
+ static __be32 check_stateid_generation(stateid_t *in, stateid_t *ref, bool has_session)

commit e0367a61567de103b1946bf87115e15253194195
+Author: David R. Bild 
+Date:   Sat Jan 12 10:19:19 2013 -0500
+
+    kbuild: clear KBUILD_SRC when calling 'make' in RPM spec
+    
+    'make rpm-pkg' and 'make binrpm-pkg' fail when the kernel source is
+    read-only.  Specifically, when the RPM spec generated by
+    scripts/package/mkspec is run, KBUILD_SRC happens to be set to the
+    source location and thus the invocation of 'make headers_install'
+    fails when an internal call to 'filechk' tries to write a file into
+    the source tree.
+    
+    The fix is to clear KBUILD_SRC for the 'make headers_install'
+    invocation in the spec file, as is already done for the 'make
+    modules_install' invocation.
+    
+    Signed-off-by: David R. Bild 
+    Signed-off-by: Michal Marek 
+
+diff --git a/scripts/package/mkspec b/scripts/package/mkspec
+index 4bf17ddf7c7f..fbbfd08853d3 100755
+--- a/scripts/package/mkspec
++++ b/scripts/package/mkspec
+@@ -95,7 +95,7 @@ echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/vmlinuz-$KERNELRELEASE"
+ echo "%endif"
+ echo "%endif"
+ 
+-echo 'make %{?_smp_mflags} INSTALL_HDR_PATH=$RPM_BUILD_ROOT/usr headers_install'
++echo 'make %{?_smp_mflags} INSTALL_HDR_PATH=$RPM_BUILD_ROOT/usr KBUILD_SRC= headers_install'
+ echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$KERNELRELEASE"
+ 
+ echo 'cp .config $RPM_BUILD_ROOT'"/boot/config-$KERNELRELEASE"

commit a68c2f12b4b28994aaf622bbe5724b7258cc2fcf
+Author: Scott Wolchok 
+Date:   Thu Dec 20 15:05:52 2012 -0800
+
+    sendfile: allows bypassing of notifier events
+    
+    do_sendfile() in fs/read_write.c does not call the fsnotify functions,
+    unlike its neighbors.  This manifests as a lack of inotify ACCESS events
+    when a file is sent using sendfile(2).
+    
+    Addresses
+      https://bugzilla.kernel.org/show_bug.cgi?id=12812
+    
+    [akpm@linux-foundation.org: use fsnotify_modify(out.file), not fsnotify_access(), per Dave]
+    Signed-off-by: Alan Cox 
+    Cc: Dave Chinner 
+    Cc: Jens Axboe 
+    Cc: Scott Wolchok 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/read_write.c b/fs/read_write.c
+index 1edaf099ddd7..bb34af315280 100644
+--- a/fs/read_write.c
++++ b/fs/read_write.c
+@@ -935,6 +935,8 @@ ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, size_t count,
+ 	if (retval > 0) {
+ 		add_rchar(current, retval);
+ 		add_wchar(current, retval);
++		fsnotify_access(in.file);
++		fsnotify_modify(out.file);
+ 	}
+ 
+ 	inc_syscr(current);

commit d751f748b359534d78e2b2e52b59d39f0e0540aa
+Author: Jim Rees 
+Date:   Fri Nov 16 18:12:06 2012 -0500
+
+    NFS: Reduce stack use in encode_exchange_id()
+    
+    encode_exchange_id() uses more stack space than necessary, giving a compile
+    time warning. Reduce the size of the static buffer for implementation name.
+    
+    Signed-off-by: Jim Rees 
+    Reviewed-by: "Adamson, Dros" 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
+index 40836ee5dc3a..142aacb92459 100644
+--- a/fs/nfs/nfs4xdr.c
++++ b/fs/nfs/nfs4xdr.c
+@@ -270,6 +270,8 @@ static int nfs4_stat_to_errno(int);
+ 
+ #if defined(CONFIG_NFS_V4_1)
+ #define NFS4_MAX_MACHINE_NAME_LEN (64)
++#define IMPL_NAME_LIMIT (sizeof(utsname()->sysname) + sizeof(utsname()->release) + \
++			 sizeof(utsname()->version) + sizeof(utsname()->machine) + 8)
+ 
+ #define encode_exchange_id_maxsz (op_encode_hdr_maxsz + \
+ 				encode_verifier_maxsz + \
+@@ -282,7 +284,7 @@ static int nfs4_stat_to_errno(int);
+ 				1 /* nii_domain */ + \
+ 				XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \
+ 				1 /* nii_name */ + \
+-				XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \
++				XDR_QUADLEN(IMPL_NAME_LIMIT) + \
+ 				3 /* nii_date */)
+ #define decode_exchange_id_maxsz (op_decode_hdr_maxsz + \
+ 				2 /* eir_clientid */ + \
+@@ -1713,7 +1715,7 @@ static void encode_exchange_id(struct xdr_stream *xdr,
+ 			       struct compound_hdr *hdr)
+ {
+ 	__be32 *p;
+-	char impl_name[NFS4_OPAQUE_LIMIT];
++	char impl_name[IMPL_NAME_LIMIT];
+ 	int len = 0;
+ 
+ 	encode_op_hdr(xdr, OP_EXCHANGE_ID, decode_exchange_id_maxsz, hdr);
+@@ -1728,7 +1730,7 @@ static void encode_exchange_id(struct xdr_stream *xdr,
+ 	if (send_implementation_id &&
+ 	    sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) > 1 &&
+ 	    sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN)
+-		<= NFS4_OPAQUE_LIMIT + 1)
++		<= sizeof(impl_name) + 1)
+ 		len = snprintf(impl_name, sizeof(impl_name), "%s %s %s %s",
+ 			       utsname()->sysname, utsname()->release,
+ 			       utsname()->version, utsname()->machine);

commit 10bd295a0b6488ebe634b72a11d8986bd3af3819
+Author: Jim Rees 
+Date:   Mon Apr 9 22:33:39 2012 -0400
+
+    fix page number calculation bug for block layout decode buffer
+    
+    Signed-off-by: Jim Rees 
+    Suggested-by: Andy Adamson 
+    Suggested-by: Fred Isaman 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
+index 9c94297bb70e..7f6a23f0244e 100644
+--- a/fs/nfs/blocklayout/blocklayout.c
++++ b/fs/nfs/blocklayout/blocklayout.c
+@@ -38,6 +38,8 @@
+ #include 	/* various write calls */
+ #include 
+ 
++#include "../pnfs.h"
++#include "../internal.h"
+ #include "blocklayout.h"
+ 
+ #define NFSDBG_FACILITY	NFSDBG_PNFS_LD
+@@ -868,7 +870,7 @@ nfs4_blk_get_deviceinfo(struct nfs_server *server, const struct nfs_fh *fh,
+ 	 * GETDEVICEINFO's maxcount
+ 	 */
+ 	max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
+-	max_pages = max_resp_sz >> PAGE_SHIFT;
++	max_pages = nfs_page_array_len(0, max_resp_sz);
+ 	dprintk("%s max_resp_sz %u max_pages %d\n",
+ 		__func__, max_resp_sz, max_pages);
+ 

commit fdc17abbc4b6094b34ee8ff5d91eaba8637594a2
+Author: Jim Rees 
+Date:   Thu Sep 22 21:50:09 2011 -0400
+
+    pnfsblock: fix size of upcall message
+    
+    Make the status field explicitly 32 bits.  "...it's unlikely that the kernel
+    and userspace would differ on the size of an int here, but it might be a
+    good idea to go ahead and make that explicitly 32 bits in case we end up
+    dealing with more exotic arches at some point in the future."
+    
+    Suggested-by: Jeff Layton 
+    Signed-off-by: Jim Rees 
+    Signed-off-by: Benny Halevy 
+    Cc: stable@kernel.org [3.0]
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklayout.h
+index f27d827960a3..58dc256402e3 100644
+--- a/fs/nfs/blocklayout/blocklayout.h
++++ b/fs/nfs/blocklayout/blocklayout.h
+@@ -150,7 +150,7 @@ BLK_LSEG2EXT(struct pnfs_layout_segment *lseg)
+ }
+ 
+ struct bl_dev_msg {
+-	int status;
++	int32_t status;
+ 	uint32_t major, minor;
+ };
+ 

commit 516f2e24faa7548a61d9ba790958528469c2e284
+Author: Jim Rees 
+Date:   Thu Sep 22 21:50:08 2011 -0400
+
+    pnfsblock: fix return code confusion
+    
+    Always return PTR_ERR, not NULL, from nfs4_blk_get_deviceinfo and
+    nfs4_blk_decode_device.
+    
+    Check for IS_ERR, not NULL, in bl_set_layoutdriver when calling
+    nfs4_blk_get_deviceinfo.
+    
+    Signed-off-by: Jim Rees 
+    Signed-off-by: Benny Halevy 
+    Cc: stable@kernel.org [3.0]
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
+index 9561c8fc8bdb..d2432f0dc40c 100644
+--- a/fs/nfs/blocklayout/blocklayout.c
++++ b/fs/nfs/blocklayout/blocklayout.c
+@@ -805,7 +805,7 @@ nfs4_blk_get_deviceinfo(struct nfs_server *server, const struct nfs_fh *fh,
+ 			struct nfs4_deviceid *d_id)
+ {
+ 	struct pnfs_device *dev;
+-	struct pnfs_block_dev *rv = NULL;
++	struct pnfs_block_dev *rv;
+ 	u32 max_resp_sz;
+ 	int max_pages;
+ 	struct page **pages = NULL;
+@@ -823,18 +823,20 @@ nfs4_blk_get_deviceinfo(struct nfs_server *server, const struct nfs_fh *fh,
+ 	dev = kmalloc(sizeof(*dev), GFP_NOFS);
+ 	if (!dev) {
+ 		dprintk("%s kmalloc failed\n", __func__);
+-		return NULL;
++		return ERR_PTR(-ENOMEM);
+ 	}
+ 
+ 	pages = kzalloc(max_pages * sizeof(struct page *), GFP_NOFS);
+ 	if (pages == NULL) {
+ 		kfree(dev);
+-		return NULL;
++		return ERR_PTR(-ENOMEM);
+ 	}
+ 	for (i = 0; i < max_pages; i++) {
+ 		pages[i] = alloc_page(GFP_NOFS);
+-		if (!pages[i])
++		if (!pages[i]) {
++			rv = ERR_PTR(-ENOMEM);
+ 			goto out_free;
++		}
+ 	}
+ 
+ 	memcpy(&dev->dev_id, d_id, sizeof(*d_id));
+@@ -847,8 +849,10 @@ nfs4_blk_get_deviceinfo(struct nfs_server *server, const struct nfs_fh *fh,
+ 	dprintk("%s: dev_id: %s\n", __func__, dev->dev_id.data);
+ 	rc = nfs4_proc_getdeviceinfo(server, dev);
+ 	dprintk("%s getdevice info returns %d\n", __func__, rc);
+-	if (rc)
++	if (rc) {
++		rv = ERR_PTR(rc);
+ 		goto out_free;
++	}
+ 
+ 	rv = nfs4_blk_decode_device(server, dev);
+  out_free:
+@@ -866,7 +870,7 @@ bl_set_layoutdriver(struct nfs_server *server, const struct nfs_fh *fh)
+ 	struct pnfs_devicelist *dlist = NULL;
+ 	struct pnfs_block_dev *bdev;
+ 	LIST_HEAD(block_disklist);
+-	int status = 0, i;
++	int status, i;
+ 
+ 	dprintk("%s enter\n", __func__);
+ 
+@@ -898,8 +902,8 @@ bl_set_layoutdriver(struct nfs_server *server, const struct nfs_fh *fh)
+ 		for (i = 0; i < dlist->num_devs; i++) {
+ 			bdev = nfs4_blk_get_deviceinfo(server, fh,
+ 						       &dlist->dev_id[i]);
+-			if (!bdev) {
+-				status = -ENODEV;
++			if (IS_ERR(bdev)) {
++				status = PTR_ERR(bdev);
+ 				goto out_error;
+ 			}
+ 			spin_lock(&b_mt_id->bm_lock);
+diff --git a/fs/nfs/blocklayout/blocklayoutdev.c b/fs/nfs/blocklayout/blocklayoutdev.c
+index a83b393fb01c..0b1fb0e25b93 100644
+--- a/fs/nfs/blocklayout/blocklayoutdev.c
++++ b/fs/nfs/blocklayout/blocklayoutdev.c
+@@ -131,7 +131,7 @@ struct pnfs_block_dev *
+ nfs4_blk_decode_device(struct nfs_server *server,
+ 		       struct pnfs_device *dev)
+ {
+-	struct pnfs_block_dev *rv = NULL;
++	struct pnfs_block_dev *rv;
+ 	struct block_device *bd = NULL;
+ 	struct rpc_pipe_msg msg;
+ 	struct bl_msg_hdr bl_msg = {
+@@ -141,7 +141,7 @@ nfs4_blk_decode_device(struct nfs_server *server,
+ 	uint8_t *dataptr;
+ 	DECLARE_WAITQUEUE(wq, current);
+ 	struct bl_dev_msg *reply = &bl_mount_reply;
+-	int offset, len, i;
++	int offset, len, i, rc;
+ 
+ 	dprintk("%s CREATING PIPEFS MESSAGE\n", __func__);
+ 	dprintk("%s: deviceid: %s, mincount: %d\n", __func__, dev->dev_id.data,
+@@ -168,8 +168,10 @@ nfs4_blk_decode_device(struct nfs_server *server,
+ 
+ 	dprintk("%s CALLING USERSPACE DAEMON\n", __func__);
+ 	add_wait_queue(&bl_wq, &wq);
+-	if (rpc_queue_upcall(bl_device_pipe->d_inode, &msg) < 0) {
++	rc = rpc_queue_upcall(bl_device_pipe->d_inode, &msg);
++	if (rc < 0) {
+ 		remove_wait_queue(&bl_wq, &wq);
++		rv = ERR_PTR(rc);
+ 		goto out;
+ 	}
+ 
+@@ -187,8 +189,9 @@ nfs4_blk_decode_device(struct nfs_server *server,
+ 
+ 	bd = nfs4_blkdev_get(MKDEV(reply->major, reply->minor));
+ 	if (IS_ERR(bd)) {
+-		dprintk("%s failed to open device : %ld\n",
+-			__func__, PTR_ERR(bd));
++		rc = PTR_ERR(bd);
++		dprintk("%s failed to open device : %d\n", __func__, rc);
++		rv = ERR_PTR(rc);
+ 		goto out;
+ 	}
+ 

commit 025a70ed6518f635f66f314d6959718be79638db
+Author: Jim Rees 
+Date:   Sat Jul 30 20:52:43 2011 -0400
+
+    pnfsblock: remove device operations
+    
+    Signed-off-by: Jim Rees 
+    Signed-off-by: Fred Isaman 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Benny Halevy 
+    [upcall bugfixes]
+    Signed-off-by: Peng Tao 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/blocklayout/Makefile b/fs/nfs/blocklayout/Makefile
+index 5bf3409084d2..d5815505c020 100644
+--- a/fs/nfs/blocklayout/Makefile
++++ b/fs/nfs/blocklayout/Makefile
+@@ -2,4 +2,4 @@
+ # Makefile for the pNFS block layout driver kernel module
+ #
+ obj-$(CONFIG_PNFS_BLOCK) += blocklayoutdriver.o
+-blocklayoutdriver-objs := blocklayout.o extents.o blocklayoutdev.o
++blocklayoutdriver-objs := blocklayout.o extents.o blocklayoutdev.o blocklayoutdm.o
+diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklayout.h
+index dd25f1b3fe1e..1527f88e00dd 100644
+--- a/fs/nfs/blocklayout/blocklayout.h
++++ b/fs/nfs/blocklayout/blocklayout.h
+@@ -128,5 +128,8 @@ struct pnfs_block_dev *nfs4_blk_decode_device(struct nfs_server *server,
+ int nfs4_blk_process_layoutget(struct pnfs_layout_hdr *lo,
+ 				struct nfs4_layoutget_res *lgr, gfp_t gfp_flags);
+ 
++/* blocklayoutdm.c */
++void bl_free_block_dev(struct pnfs_block_dev *bdev);
++
+ void bl_put_extent(struct pnfs_block_extent *be);
+ #endif /* FS_NFS_NFS4BLOCKLAYOUT_H */
+diff --git a/fs/nfs/blocklayout/blocklayoutdm.c b/fs/nfs/blocklayout/blocklayoutdm.c
+new file mode 100644
+index 000000000000..d055c7558073
+--- /dev/null
++++ b/fs/nfs/blocklayout/blocklayoutdm.c
+@@ -0,0 +1,111 @@
++/*
++ *  linux/fs/nfs/blocklayout/blocklayoutdm.c
++ *
++ *  Module for the NFSv4.1 pNFS block layout driver.
++ *
++ *  Copyright (c) 2007 The Regents of the University of Michigan.
++ *  All rights reserved.
++ *
++ *  Fred Isaman 
++ *  Andy Adamson 
++ *
++ * permission is granted to use, copy, create derivative works and
++ * redistribute this software and such derivative works for any purpose,
++ * so long as the name of the university of michigan is not used in
++ * any advertising or publicity pertaining to the use or distribution
++ * of this software without specific, written prior authorization.  if
++ * the above copyright notice or any other identification of the
++ * university of michigan is included in any copy of any portion of
++ * this software, then the disclaimer below must also be included.
++ *
++ * this software is provided as is, without representation from the
++ * university of michigan as to its fitness for any purpose, and without
++ * warranty by the university of michigan of any kind, either express
++ * or implied, including without limitation the implied warranties of
++ * merchantability and fitness for a particular purpose.  the regents
++ * of the university of michigan shall not be liable for any damages,
++ * including special, indirect, incidental, or consequential damages,
++ * with respect to any claim arising out or in connection with the use
++ * of the software, even if it has been or is hereafter advised of the
++ * possibility of such damages.
++ */
++
++#include  /* gendisk - used in a dprintk*/
++#include 
++#include 
++
++#include "blocklayout.h"
++
++#define NFSDBG_FACILITY         NFSDBG_PNFS_LD
++
++static void dev_remove(dev_t dev)
++{
++	struct rpc_pipe_msg msg;
++	struct bl_dev_msg bl_umount_request;
++	struct bl_msg_hdr bl_msg = {
++		.type = BL_DEVICE_UMOUNT,
++		.totallen = sizeof(bl_umount_request),
++	};
++	uint8_t *dataptr;
++	DECLARE_WAITQUEUE(wq, current);
++
++	dprintk("Entering %s\n", __func__);
++
++	memset(&msg, 0, sizeof(msg));
++	msg.data = kzalloc(1 + sizeof(bl_umount_request), GFP_NOFS);
++	if (!msg.data)
++		goto out;
++
++	memset(&bl_umount_request, 0, sizeof(bl_umount_request));
++	bl_umount_request.major = MAJOR(dev);
++	bl_umount_request.minor = MINOR(dev);
++
++	memcpy(msg.data, &bl_msg, sizeof(bl_msg));
++	dataptr = (uint8_t *) msg.data;
++	memcpy(&dataptr[sizeof(bl_msg)], &bl_umount_request, sizeof(bl_umount_request));
++	msg.len = sizeof(bl_msg) + bl_msg.totallen;
++
++	add_wait_queue(&bl_wq, &wq);
++	if (rpc_queue_upcall(bl_device_pipe->d_inode, &msg) < 0) {
++		remove_wait_queue(&bl_wq, &wq);
++		goto out;
++	}
++
++	set_current_state(TASK_UNINTERRUPTIBLE);
++	schedule();
++	__set_current_state(TASK_RUNNING);
++	remove_wait_queue(&bl_wq, &wq);
++
++out:
++	kfree(msg.data);
++}
++
++/*
++ * Release meta device
++ */
++static void nfs4_blk_metadev_release(struct pnfs_block_dev *bdev)
++{
++	int rv;
++
++	dprintk("%s Releasing\n", __func__);
++	rv = nfs4_blkdev_put(bdev->bm_mdev);
++	if (rv)
++		printk(KERN_ERR "%s nfs4_blkdev_put returns %d\n",
++				__func__, rv);
++
++	dev_remove(bdev->bm_mdev->bd_dev);
++}
++
++void bl_free_block_dev(struct pnfs_block_dev *bdev)
++{
++	if (bdev) {
++		if (bdev->bm_mdev) {
++			dprintk("%s Removing DM device: %d:%d\n",
++				__func__,
++				MAJOR(bdev->bm_mdev->bd_dev),
++				MINOR(bdev->bm_mdev->bd_dev));
++			nfs4_blk_metadev_release(bdev);
++		}
++		kfree(bdev);
++	}
++}

commit fe0a9b740881d181e3c96c1f6f6043e252692ffe
+Author: Jim Rees 
+Date:   Sat Jul 30 20:52:42 2011 -0400
+
+    pnfsblock: add device operations
+    
+    Signed-off-by: Jim Rees 
+    Signed-off-by: Fred Isaman 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Benny Halevy 
+    [upcall bugfixes]
+    Signed-off-by: Peng Tao 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/blocklayout/Makefile b/fs/nfs/blocklayout/Makefile
+index 5cfadf6ebc90..5bf3409084d2 100644
+--- a/fs/nfs/blocklayout/Makefile
++++ b/fs/nfs/blocklayout/Makefile
+@@ -2,4 +2,4 @@
+ # Makefile for the pNFS block layout driver kernel module
+ #
+ obj-$(CONFIG_PNFS_BLOCK) += blocklayoutdriver.o
+-blocklayoutdriver-objs := blocklayout.o extents.o
++blocklayoutdriver-objs := blocklayout.o extents.o blocklayoutdev.o
+diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
+index 8dde3723482e..c83878441047 100644
+--- a/fs/nfs/blocklayout/blocklayout.c
++++ b/fs/nfs/blocklayout/blocklayout.c
+@@ -31,6 +31,8 @@
+  */
+ #include 
+ #include 
++#include 
++#include 
+ 
+ #include "blocklayout.h"
+ 
+@@ -40,6 +42,9 @@ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Andy Adamson ");
+ MODULE_DESCRIPTION("The NFSv4.1 pNFS Block layout driver");
+ 
++struct dentry *bl_device_pipe;
++wait_queue_head_t bl_wq;
++
+ static enum pnfs_try_status
+ bl_read_pagelist(struct nfs_read_data *rdata)
+ {
+@@ -176,13 +181,49 @@ static struct pnfs_layoutdriver_type blocklayout_type = {
+ 	.pg_write_ops			= &bl_pg_write_ops,
+ };
+ 
++static const struct rpc_pipe_ops bl_upcall_ops = {
++	.upcall		= bl_pipe_upcall,
++	.downcall	= bl_pipe_downcall,
++	.destroy_msg	= bl_pipe_destroy_msg,
++};
++
+ static int __init nfs4blocklayout_init(void)
+ {
++	struct vfsmount *mnt;
++	struct path path;
+ 	int ret;
+ 
+ 	dprintk("%s: NFSv4 Block Layout Driver Registering...\n", __func__);
+ 
+ 	ret = pnfs_register_layoutdriver(&blocklayout_type);
++	if (ret)
++		goto out;
++
++	init_waitqueue_head(&bl_wq);
++
++	mnt = rpc_get_mount();
++	if (IS_ERR(mnt)) {
++		ret = PTR_ERR(mnt);
++		goto out_remove;
++	}
++
++	ret = vfs_path_lookup(mnt->mnt_root,
++			      mnt,
++			      NFS_PIPE_DIRNAME, 0, &path);
++	if (ret)
++		goto out_remove;
++
++	bl_device_pipe = rpc_mkpipe(path.dentry, "blocklayout", NULL,
++				    &bl_upcall_ops, 0);
++	if (IS_ERR(bl_device_pipe)) {
++		ret = PTR_ERR(bl_device_pipe);
++		goto out_remove;
++	}
++out:
++	return ret;
++
++out_remove:
++	pnfs_unregister_layoutdriver(&blocklayout_type);
+ 	return ret;
+ }
+ 
+@@ -192,6 +233,7 @@ static void __exit nfs4blocklayout_exit(void)
+ 	       __func__);
+ 
+ 	pnfs_unregister_layoutdriver(&blocklayout_type);
++	rpc_unlink(bl_device_pipe);
+ }
+ 
+ MODULE_ALIAS("nfs-layouttype4-3");
+diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklayout.h
+index 98e2f60c2143..dd25f1b3fe1e 100644
+--- a/fs/nfs/blocklayout/blocklayout.h
++++ b/fs/nfs/blocklayout/blocklayout.h
+@@ -34,8 +34,16 @@
+ 
+ #include 
+ #include 
++#include 
++
+ #include "../pnfs.h"
+ 
++struct pnfs_block_dev {
++	struct list_head		bm_node;
++	struct nfs4_deviceid		bm_mdevid;    /* associated devid */
++	struct block_device		*bm_mdev;     /* meta device itself */
++};
++
+ enum exstate4 {
+ 	PNFS_BLOCK_READWRITE_DATA	= 0,
+ 	PNFS_BLOCK_READ_DATA		= 1,
+@@ -88,5 +96,37 @@ static inline struct pnfs_block_layout *BLK_LO2EXT(struct pnfs_layout_hdr *lo)
+ 	return container_of(lo, struct pnfs_block_layout, bl_layout);
+ }
+ 
++struct bl_dev_msg {
++	int status;
++	uint32_t major, minor;
++};
++
++struct bl_msg_hdr {
++	u8  type;
++	u16 totallen; /* length of entire message, including hdr itself */
++};
++
++extern struct dentry *bl_device_pipe;
++extern wait_queue_head_t bl_wq;
++
++#define BL_DEVICE_UMOUNT               0x0 /* Umount--delete devices */
++#define BL_DEVICE_MOUNT                0x1 /* Mount--create devices*/
++#define BL_DEVICE_REQUEST_INIT         0x0 /* Start request */
++#define BL_DEVICE_REQUEST_PROC         0x1 /* User level process succeeds */
++#define BL_DEVICE_REQUEST_ERR          0x2 /* User level process fails */
++
++/* blocklayoutdev.c */
++ssize_t bl_pipe_upcall(struct file *, struct rpc_pipe_msg *,
++		       char __user *, size_t);
++ssize_t bl_pipe_downcall(struct file *, const char __user *, size_t);
++void bl_pipe_destroy_msg(struct rpc_pipe_msg *);
++struct block_device *nfs4_blkdev_get(dev_t dev);
++int nfs4_blkdev_put(struct block_device *bdev);
++struct pnfs_block_dev *nfs4_blk_decode_device(struct nfs_server *server,
++						struct pnfs_device *dev,
++						struct list_head *sdlist);
++int nfs4_blk_process_layoutget(struct pnfs_layout_hdr *lo,
++				struct nfs4_layoutget_res *lgr, gfp_t gfp_flags);
++
+ void bl_put_extent(struct pnfs_block_extent *be);
+ #endif /* FS_NFS_NFS4BLOCKLAYOUT_H */
+diff --git a/fs/nfs/blocklayout/blocklayoutdev.c b/fs/nfs/blocklayout/blocklayoutdev.c
+new file mode 100644
+index 000000000000..7e1377fcfdce
+--- /dev/null
++++ b/fs/nfs/blocklayout/blocklayoutdev.c
+@@ -0,0 +1,191 @@
++/*
++ *  linux/fs/nfs/blocklayout/blocklayoutdev.c
++ *
++ *  Device operations for the pnfs nfs4 file layout driver.
++ *
++ *  Copyright (c) 2006 The Regents of the University of Michigan.
++ *  All rights reserved.
++ *
++ *  Andy Adamson 
++ *  Fred Isaman 
++ *
++ * permission is granted to use, copy, create derivative works and
++ * redistribute this software and such derivative works for any purpose,
++ * so long as the name of the university of michigan is not used in
++ * any advertising or publicity pertaining to the use or distribution
++ * of this software without specific, written prior authorization.  if
++ * the above copyright notice or any other identification of the
++ * university of michigan is included in any copy of any portion of
++ * this software, then the disclaimer below must also be included.
++ *
++ * this software is provided as is, without representation from the
++ * university of michigan as to its fitness for any purpose, and without
++ * warranty by the university of michigan of any kind, either express
++ * or implied, including without limitation the implied warranties of
++ * merchantability and fitness for a particular purpose.  the regents
++ * of the university of michigan shall not be liable for any damages,
++ * including special, indirect, incidental, or consequential damages,
++ * with respect to any claim arising out or in connection with the use
++ * of the software, even if it has been or is hereafter advised of the
++ * possibility of such damages.
++ */
++#include 
++#include  /* __bread */
++
++#include 
++#include 
++#include 
++
++#include "blocklayout.h"
++
++#define NFSDBG_FACILITY         NFSDBG_PNFS_LD
++
++/* Open a block_device by device number. */
++struct block_device *nfs4_blkdev_get(dev_t dev)
++{
++	struct block_device *bd;
++
++	dprintk("%s enter\n", __func__);
++	bd = blkdev_get_by_dev(dev, FMODE_READ, NULL);
++	if (IS_ERR(bd))
++		goto fail;
++	return bd;
++fail:
++	dprintk("%s failed to open device : %ld\n",
++			__func__, PTR_ERR(bd));
++	return NULL;
++}
++
++/*
++ * Release the block device
++ */
++int nfs4_blkdev_put(struct block_device *bdev)
++{
++	dprintk("%s for device %d:%d\n", __func__, MAJOR(bdev->bd_dev),
++			MINOR(bdev->bd_dev));
++	return blkdev_put(bdev, FMODE_READ);
++}
++
++/*
++ * Shouldn't there be a rpc_generic_upcall() to do this for us?
++ */
++ssize_t bl_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg,
++		       char __user *dst, size_t buflen)
++{
++	char *data = (char *)msg->data + msg->copied;
++	size_t mlen = min(msg->len - msg->copied, buflen);
++	unsigned long left;
++
++	left = copy_to_user(dst, data, mlen);
++	if (left == mlen) {
++		msg->errno = -EFAULT;
++		return -EFAULT;
++	}
++
++	mlen -= left;
++	msg->copied += mlen;
++	msg->errno = 0;
++	return mlen;
++}
++
++static struct bl_dev_msg bl_mount_reply;
++
++ssize_t bl_pipe_downcall(struct file *filp, const char __user *src,
++			 size_t mlen)
++{
++	if (mlen != sizeof (struct bl_dev_msg))
++		return -EINVAL;
++
++	if (copy_from_user(&bl_mount_reply, src, mlen) != 0)
++		return -EFAULT;
++
++	wake_up(&bl_wq);
++
++	return mlen;
++}
++
++void bl_pipe_destroy_msg(struct rpc_pipe_msg *msg)
++{
++	if (msg->errno >= 0)
++		return;
++	wake_up(&bl_wq);
++}
++
++/*
++ * Decodes pnfs_block_deviceaddr4 which is XDR encoded in dev->dev_addr_buf.
++ */
++struct pnfs_block_dev *
++nfs4_blk_decode_device(struct nfs_server *server,
++		       struct pnfs_device *dev,
++		       struct list_head *sdlist)
++{
++	struct pnfs_block_dev *rv = NULL;
++	struct block_device *bd = NULL;
++	struct rpc_pipe_msg msg;
++	struct bl_msg_hdr bl_msg = {
++		.type = BL_DEVICE_MOUNT,
++		.totallen = dev->mincount,
++	};
++	uint8_t *dataptr;
++	DECLARE_WAITQUEUE(wq, current);
++	struct bl_dev_msg *reply = &bl_mount_reply;
++
++	dprintk("%s CREATING PIPEFS MESSAGE\n", __func__);
++	dprintk("%s: deviceid: %s, mincount: %d\n", __func__, dev->dev_id.data,
++		dev->mincount);
++
++	memset(&msg, 0, sizeof(msg));
++	msg.data = kzalloc(sizeof(bl_msg) + dev->mincount, GFP_NOFS);
++	if (!msg.data) {
++		rv = ERR_PTR(-ENOMEM);
++		goto out;
++	}
++
++	memcpy(msg.data, &bl_msg, sizeof(bl_msg));
++	dataptr = (uint8_t *) msg.data;
++	memcpy(&dataptr[sizeof(bl_msg)], dev->area, dev->mincount);
++	msg.len = sizeof(bl_msg) + dev->mincount;
++
++	dprintk("%s CALLING USERSPACE DAEMON\n", __func__);
++	add_wait_queue(&bl_wq, &wq);
++	if (rpc_queue_upcall(bl_device_pipe->d_inode, &msg) < 0) {
++		remove_wait_queue(&bl_wq, &wq);
++		goto out;
++	}
++
++	set_current_state(TASK_UNINTERRUPTIBLE);
++	schedule();
++	__set_current_state(TASK_RUNNING);
++	remove_wait_queue(&bl_wq, &wq);
++
++	if (reply->status != BL_DEVICE_REQUEST_PROC) {
++		dprintk("%s failed to open device: %d\n",
++			__func__, reply->status);
++		rv = ERR_PTR(-EINVAL);
++		goto out;
++	}
++
++	bd = nfs4_blkdev_get(MKDEV(reply->major, reply->minor));
++	if (IS_ERR(bd)) {
++		dprintk("%s failed to open device : %ld\n",
++			__func__, PTR_ERR(bd));
++		goto out;
++	}
++
++	rv = kzalloc(sizeof(*rv), GFP_NOFS);
++	if (!rv) {
++		rv = ERR_PTR(-ENOMEM);
++		goto out;
++	}
++
++	rv->bm_mdev = bd;
++	memcpy(&rv->bm_mdevid, &dev->dev_id, sizeof(struct nfs4_deviceid));
++	dprintk("%s Created device %s with bd_block_size %u\n",
++		__func__,
++		bd->bd_disk->disk_name,
++		bd->bd_block_size);
++
++out:
++	kfree(msg.data);
++	return rv;
++}
+diff --git a/fs/nfs/client.c b/fs/nfs/client.c
+index de00a373f085..5833fbbf59b0 100644
+--- a/fs/nfs/client.c
++++ b/fs/nfs/client.c
+@@ -105,7 +105,7 @@ struct rpc_program nfs_program = {
+ 	.nrvers			= ARRAY_SIZE(nfs_version),
+ 	.version		= nfs_version,
+ 	.stats			= &nfs_rpcstat,
+-	.pipe_dir_name		= "/nfs",
++	.pipe_dir_name		= NFS_PIPE_DIRNAME,
+ };
+ 
+ struct rpc_stat nfs_rpcstat = {
+diff --git a/include/linux/nfs.h b/include/linux/nfs.h
+index f387919bbc59..8c6ee44914cb 100644
+--- a/include/linux/nfs.h
++++ b/include/linux/nfs.h
+@@ -29,6 +29,8 @@
+ #define NFS_MNT_VERSION		1
+ #define NFS_MNT3_VERSION	3
+ 
++#define NFS_PIPE_DIRNAME "/nfs"
++
+ /*
+  * NFS stats. The good thing with these values is that NFSv3 errors are
+  * a superset of NFSv2 errors (with the exception of NFSERR_WFLUSH which

commit 3b6445a6f68b839d1b437756b9c72312e33339b2
+Author: Jim Rees 
+Date:   Tue Feb 22 19:31:57 2011 -0500
+
+    NFSv4.1: fix typo in filelayout_check_layout
+    
+    Signed-off-by: Jim Rees 
+    Signed-off-by: Benny Halevy 
+
+diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
+index be79dc9f386d..dd6ccf007673 100644
+--- a/fs/nfs/nfs4filelayout.c
++++ b/fs/nfs/nfs4filelayout.c
+@@ -428,7 +428,7 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo,
+ 	dprintk("--> %s\n", __func__);
+ 
+ 	if (fl->pattern_offset > lgr->range.offset) {
+-		dprintk("%s pattern_offset %lld to large\n",
++		dprintk("%s pattern_offset %lld too large\n",
+ 				__func__, fl->pattern_offset);
+ 		goto out;
+ 	}

commit 7ab672ce312133ee4a5d85b71447b2b334403681
+Author: Dean Hildebrand 
+Date:   Wed Oct 20 00:18:00 2010 -0400
+
+    NFSv4.1: pnfs: filelayout: introduce minimal file layout driver
+    
+    This driver just registers itself and supplies trivial mount/umount functions.
+    
+    Signed-off-by: Dean Hildebrand 
+    Signed-off-by: Marc Eshel 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Fred Isaman 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
+index bb9e773d4312..08a8889c5149 100644
+--- a/fs/nfs/Makefile
++++ b/fs/nfs/Makefile
+@@ -18,3 +18,6 @@ nfs-$(CONFIG_NFS_V4)	+= nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
+ nfs-$(CONFIG_NFS_V4_1)	+= pnfs.o
+ nfs-$(CONFIG_SYSCTL) += sysctl.o
+ nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
++
++obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o
++nfs_layout_nfsv41_files-y := nfs4filelayout.o
+diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
+new file mode 100644
+index 000000000000..696e283c2632
+--- /dev/null
++++ b/fs/nfs/nfs4filelayout.c
+@@ -0,0 +1,78 @@
++/*
++ *  Module for the pnfs nfs4 file layout driver.
++ *  Defines all I/O and Policy interface operations, plus code
++ *  to register itself with the pNFS client.
++ *
++ *  Copyright (c) 2002
++ *  The Regents of the University of Michigan
++ *  All Rights Reserved
++ *
++ *  Dean Hildebrand 
++ *
++ *  Permission is granted to use, copy, create derivative works, and
++ *  redistribute this software and such derivative works for any purpose,
++ *  so long as the name of the University of Michigan is not used in
++ *  any advertising or publicity pertaining to the use or distribution
++ *  of this software without specific, written prior authorization. If
++ *  the above copyright notice or any other identification of the
++ *  University of Michigan is included in any copy of any portion of
++ *  this software, then the disclaimer below must also be included.
++ *
++ *  This software is provided as is, without representation or warranty
++ *  of any kind either express or implied, including without limitation
++ *  the implied warranties of merchantability, fitness for a particular
++ *  purpose, or noninfringement.  The Regents of the University of
++ *  Michigan shall not be liable for any damages, including special,
++ *  indirect, incidental, or consequential damages, with respect to any
++ *  claim arising out of or in connection with the use of the software,
++ *  even if it has been or is hereafter advised of the possibility of
++ *  such damages.
++ */
++
++#include 
++#include "pnfs.h"
++
++#define NFSDBG_FACILITY         NFSDBG_PNFS_LD
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Dean Hildebrand ");
++MODULE_DESCRIPTION("The NFSv4 file layout driver");
++
++int
++filelayout_initialize_mountpoint(struct nfs_server *nfss)
++{
++	return 0;
++}
++
++int
++filelayout_uninitialize_mountpoint(struct nfs_server *nfss)
++{
++	dprintk("--> %s\n", __func__);
++
++	return 0;
++}
++
++static struct pnfs_layoutdriver_type filelayout_type = {
++	.id = LAYOUT_NFSV4_1_FILES,
++	.name = "LAYOUT_NFSV4_1_FILES",
++	.owner = THIS_MODULE,
++	.initialize_mountpoint   = filelayout_initialize_mountpoint,
++	.uninitialize_mountpoint = filelayout_uninitialize_mountpoint,
++};
++
++static int __init nfs4filelayout_init(void)
++{
++	printk(KERN_INFO "%s: NFSv4 File Layout Driver Registering...\n",
++	       __func__);
++	return pnfs_register_layoutdriver(&filelayout_type);
++}
++
++static void __exit nfs4filelayout_exit(void)
++{
++	printk(KERN_INFO "%s: NFSv4 File Layout Driver Unregistering...\n",
++	       __func__);
++	pnfs_unregister_layoutdriver(&filelayout_type);
++}
++
++module_init(nfs4filelayout_init);
++module_exit(nfs4filelayout_exit);
+diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
+index aba3da2a6227..499872fa895c 100644
+--- a/include/linux/nfs_fs.h
++++ b/include/linux/nfs_fs.h
+@@ -616,6 +616,7 @@ nfs_fileid_to_ino_t(u64 fileid)
+ #define NFSDBG_MOUNT		0x0400
+ #define NFSDBG_FSCACHE		0x0800
+ #define NFSDBG_PNFS		0x1000
++#define NFSDBG_PNFS_LD		0x2000
+ #define NFSDBG_ALL		0xFFFF
+ 
+ #ifdef __KERNEL__

commit c772567d97fa0fca454eea68aeae915ca1bc732b
+Author: Dean Hildebrand 
+Date:   Wed Oct 20 00:17:55 2010 -0400
+
+    NFSv4.1: pnfsd, pnfs: protocol level pnfs constants
+    
+    Use only layoutreturn constant for both returns and recalls.
+    (return_* works better for recall_type rather the other way around)
+    
+    Signed-off-by: Dean Hildebrand 
+    Signed-off-by: Marc Eshel 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Fred Isaman 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
+index 07e40c625972..6c0406e87d5c 100644
+--- a/include/linux/nfs4.h
++++ b/include/linux/nfs4.h
+@@ -471,6 +471,8 @@ enum lock_type4 {
+ #define FATTR4_WORD1_TIME_MODIFY        (1UL << 21)
+ #define FATTR4_WORD1_TIME_MODIFY_SET    (1UL << 22)
+ #define FATTR4_WORD1_MOUNTED_ON_FILEID  (1UL << 23)
++#define FATTR4_WORD1_FS_LAYOUT_TYPES    (1UL << 30)
++#define FATTR4_WORD2_LAYOUT_BLKSIZE     (1UL << 1)
+ 
+ #define NFSPROC4_NULL 0
+ #define NFSPROC4_COMPOUND 1
+@@ -550,6 +552,49 @@ enum state_protect_how4 {
+ 	SP4_SSV		= 2
+ };
+ 
++enum pnfs_layouttype {
++	LAYOUT_NFSV4_1_FILES  = 1,
++	LAYOUT_OSD2_OBJECTS = 2,
++	LAYOUT_BLOCK_VOLUME = 3,
++};
++
++/* used for both layout return and recall */
++enum pnfs_layoutreturn_type {
++	RETURN_FILE = 1,
++	RETURN_FSID = 2,
++	RETURN_ALL  = 3
++};
++
++enum pnfs_iomode {
++	IOMODE_READ = 1,
++	IOMODE_RW = 2,
++	IOMODE_ANY = 3,
++};
++
++enum pnfs_notify_deviceid_type4 {
++	NOTIFY_DEVICEID4_CHANGE = 1 << 1,
++	NOTIFY_DEVICEID4_DELETE = 1 << 2,
++};
++
++#define NFL4_UFLG_MASK			0x0000003F
++#define NFL4_UFLG_DENSE			0x00000001
++#define NFL4_UFLG_COMMIT_THRU_MDS	0x00000002
++#define NFL4_UFLG_STRIPE_UNIT_SIZE_MASK	0xFFFFFFC0
++
++/* Encoded in the loh_body field of type layouthint4 */
++enum filelayout_hint_care4 {
++	NFLH4_CARE_DENSE		= NFL4_UFLG_DENSE,
++	NFLH4_CARE_COMMIT_THRU_MDS	= NFL4_UFLG_COMMIT_THRU_MDS,
++	NFLH4_CARE_STRIPE_UNIT_SIZE	= 0x00000040,
++	NFLH4_CARE_STRIPE_COUNT		= 0x00000080
++};
++
++#define NFS4_DEVICEID4_SIZE 16
++
++struct nfs4_deviceid {
++	char data[NFS4_DEVICEID4_SIZE];
++};
++
+ #endif
+ #endif
+ 

commit 47f9940c55c0bdc65188749cae4e841601f513bb
+Author: Meelap Shah 
+Date:   Tue Jul 17 04:04:40 2007 -0700
+
+    knfsd: nfsd4: don't delegate files that have had conflicts
+    
+    One more incremental delegation policy improvement: don't give out a
+    delegation on a file if conflicting access has previously required that a
+    delegation be revoked on that file.  (In practice we'll forget about the
+    conflict when the struct nfs4_file is removed on close, so this is of limited
+    use for now, though it should at least solve a temporary problem with
+    self-conflicts on write opens from the same client.)
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 46249886ea86..e4a4c87ec8c6 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -195,6 +195,8 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
+ 	struct nfs4_callback *cb = &stp->st_stateowner->so_client->cl_callback;
+ 
+ 	dprintk("NFSD alloc_init_deleg\n");
++	if (fp->fi_had_conflict)
++		return NULL;
+ 	if (num_delegations > max_delegations)
+ 		return NULL;
+ 	dp = kmem_cache_alloc(deleg_slab, GFP_KERNEL);
+@@ -1002,6 +1004,7 @@ alloc_init_file(struct inode *ino)
+ 		list_add(&fp->fi_hash, &file_hashtbl[hashval]);
+ 		fp->fi_inode = igrab(ino);
+ 		fp->fi_id = current_fileid++;
++		fp->fi_had_conflict = false;
+ 		return fp;
+ 	}
+ 	return NULL;
+@@ -1328,6 +1331,7 @@ do_recall(void *__dp)
+ {
+ 	struct nfs4_delegation *dp = __dp;
+ 
++	dp->dl_file->fi_had_conflict = true;
+ 	nfsd4_cb_recall(dp);
+ 	return 0;
+ }
+diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
+index 732de9cad4a8..db348f749376 100644
+--- a/include/linux/nfsd/state.h
++++ b/include/linux/nfsd/state.h
+@@ -224,6 +224,7 @@ struct nfs4_file {
+ 	struct inode		*fi_inode;
+ 	u32                     fi_id;      /* used with stateowner->so_id 
+ 					     * for stateid_hashtbl hash */
++	bool			fi_had_conflict;
+ };
+ 
+ /*

commit c2f1a551dea8b37c2e0cb886885c250fb703e9d8
+Author: Meelap Shah 
+Date:   Tue Jul 17 04:04:39 2007 -0700
+
+    knfsd: nfsd4: vary maximum delegation limit based on RAM size
+    
+    Our original NFSv4 delegation policy was to give out a read delegation on any
+    open when it was possible to.
+    
+    Since the lifetime of a delegation isn't limited to that of an open, a client
+    may quite reasonably hang on to a delegation as long as it has the inode
+    cached.  This becomes an obvious problem the first time a client's inode cache
+    approaches the size of the server's total memory.
+    
+    Our first quick solution was to add a hard-coded limit.  This patch makes a
+    mild incremental improvement by varying that limit according to the server's
+    total memory size, allowing at most 4 delegations per megabyte of RAM.
+    
+    My quick back-of-the-envelope calculation finds that in the worst case (where
+    every delegation is for a different inode), a delegation could take about
+    1.5K, which would make the worst case usage about 6% of memory.  The new limit
+    works out to be about the same as the old on a 1-gig server.
+    
+    [akpm@linux-foundation.org: Don't needlessly bloat vmlinux]
+    [akpm@linux-foundation.org: Make it right for highmem machines]
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 9cc31eaf3857..46249886ea86 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -49,6 +49,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -150,6 +151,7 @@ get_nfs4_file(struct nfs4_file *fi)
+ }
+ 
+ static int num_delegations;
++unsigned int max_delegations;
+ 
+ /*
+  * Open owner state (share locks)
+@@ -193,7 +195,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
+ 	struct nfs4_callback *cb = &stp->st_stateowner->so_client->cl_callback;
+ 
+ 	dprintk("NFSD alloc_init_deleg\n");
+-	if (num_delegations > STATEID_HASH_SIZE * 4)
++	if (num_delegations > max_delegations)
+ 		return NULL;
+ 	dp = kmem_cache_alloc(deleg_slab, GFP_KERNEL);
+ 	if (dp == NULL)
+@@ -3197,6 +3199,27 @@ get_nfs4_grace_period(void)
+ 	return max(user_lease_time, lease_time) * HZ;
+ }
+ 
++/*
++ * Since the lifetime of a delegation isn't limited to that of an open, a
++ * client may quite reasonably hang on to a delegation as long as it has
++ * the inode cached.  This becomes an obvious problem the first time a
++ * client's inode cache approaches the size of the server's total memory.
++ *
++ * For now we avoid this problem by imposing a hard limit on the number
++ * of delegations, which varies according to the server's memory size.
++ */
++static void
++set_max_delegations(void)
++{
++	/*
++	 * Allow at most 4 delegations per megabyte of RAM.  Quick
++	 * estimates suggest that in the worst case (where every delegation
++	 * is for a different inode), a delegation could take about 1.5K,
++	 * giving a worst case usage of about 6% of memory.
++	 */
++	max_delegations = nr_free_buffer_pages() >> (20 - 2 - PAGE_SHIFT);
++}
++
+ /* initialization to perform when the nfsd service is started: */
+ 
+ static void
+@@ -3212,6 +3235,7 @@ __nfs4_state_start(void)
+ 	       grace_time/HZ);
+ 	laundry_wq = create_singlethread_workqueue("nfsd4");
+ 	queue_delayed_work(laundry_wq, &laundromat_work, grace_time);
++	set_max_delegations();
+ }
+ 
+ int
+diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
+index 0d8420497765..ce5e345a9bce 100644
+--- a/include/linux/nfsd/nfsd.h
++++ b/include/linux/nfsd/nfsd.h
+@@ -148,6 +148,7 @@ extern int nfsd_max_blksize;
+  * NFSv4 State
+  */
+ #ifdef CONFIG_NFSD_V4
++extern unsigned int max_delegations;
+ void nfs4_state_init(void);
+ int nfs4_state_start(void);
+ void nfs4_state_shutdown(void);
+diff --git a/mm/page_alloc.c b/mm/page_alloc.c
+index 1a889c3fec59..e2a10b957f23 100644
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -1484,6 +1484,7 @@ unsigned int nr_free_buffer_pages(void)
+ {
+ 	return nr_free_zone_pages(gfp_zone(GFP_USER));
+ }
++EXPORT_SYMBOL_GPL(nr_free_buffer_pages);
+ 
+ /*
+  * Amount of free RAM allocatable within all zones

commit 31e6306a4046926b598484f1cacf69309382eac6
+Author: Fred Isaman 
+Date:   Sat Jul 30 20:52:55 2011 -0400
+
+    pnfsblock: note written INVAL areas for layoutcommit
+    
+    Signed-off-by: Peng Tao 
+    Signed-off-by: Fred Isaman 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Jim Rees 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
+index 2e373826db80..21efef7c2fd2 100644
+--- a/fs/nfs/blocklayout/blocklayout.c
++++ b/fs/nfs/blocklayout/blocklayout.c
+@@ -329,6 +329,30 @@ bl_read_pagelist(struct nfs_read_data *rdata)
+ 	return PNFS_NOT_ATTEMPTED;
+ }
+ 
++static void mark_extents_written(struct pnfs_block_layout *bl,
++				 __u64 offset, __u32 count)
++{
++	sector_t isect, end;
++	struct pnfs_block_extent *be;
++
++	dprintk("%s(%llu, %u)\n", __func__, offset, count);
++	if (count == 0)
++		return;
++	isect = (offset & (long)(PAGE_CACHE_MASK)) >> SECTOR_SHIFT;
++	end = (offset + count + PAGE_CACHE_SIZE - 1) & (long)(PAGE_CACHE_MASK);
++	end >>= SECTOR_SHIFT;
++	while (isect < end) {
++		sector_t len;
++		be = bl_find_get_extent(bl, isect, NULL);
++		BUG_ON(!be); /* FIXME */
++		len = min(end, be->be_f_offset + be->be_length) - isect;
++		if (be->be_state == PNFS_BLOCK_INVALID_DATA)
++			bl_mark_for_commit(be, isect, len); /* What if fails? */
++		isect += len;
++		bl_put_extent(be);
++	}
++}
++
+ /* This is basically copied from mpage_end_io_read */
+ static void bl_end_io_write(struct bio *bio, int err)
+ {
+@@ -355,6 +379,14 @@ static void bl_write_cleanup(struct work_struct *work)
+ 	dprintk("%s enter\n", __func__);
+ 	task = container_of(work, struct rpc_task, u.tk_work);
+ 	wdata = container_of(task, struct nfs_write_data, task);
++	if (!wdata->task.tk_status) {
++		/* Marks for LAYOUTCOMMIT */
++		/* BUG - this should be called after each bio, not after
++		 * all finish, unless have some way of storing success/failure
++		 */
++		mark_extents_written(BLK_LSEG2EXT(wdata->lseg),
++				     wdata->args.offset, wdata->args.count);
++	}
+ 	pnfs_ld_write_done(wdata);
+ }
+ 
+diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklayout.h
+index 6a703b79c33d..f27d827960a3 100644
+--- a/fs/nfs/blocklayout/blocklayout.h
++++ b/fs/nfs/blocklayout/blocklayout.h
+@@ -201,5 +201,7 @@ void clean_pnfs_block_layoutupdate(struct pnfs_block_layout *bl,
+ 				   int status);
+ int bl_add_merge_extent(struct pnfs_block_layout *bl,
+ 			 struct pnfs_block_extent *new);
++int bl_mark_for_commit(struct pnfs_block_extent *be,
++			sector_t offset, sector_t length);
+ 
+ #endif /* FS_NFS_NFS4BLOCKLAYOUT_H */
+diff --git a/fs/nfs/blocklayout/extents.c b/fs/nfs/blocklayout/extents.c
+index 7521940dcca5..19fa7b0b8c00 100644
+--- a/fs/nfs/blocklayout/extents.c
++++ b/fs/nfs/blocklayout/extents.c
+@@ -217,6 +217,48 @@ int bl_is_sector_init(struct pnfs_inval_markings *marks, sector_t isect)
+ 	return rv;
+ }
+ 
++/* Assume start, end already sector aligned */
++static int
++_range_has_tag(struct my_tree *tree, u64 start, u64 end, int32_t tag)
++{
++	struct pnfs_inval_tracking *pos;
++	u64 expect = 0;
++
++	dprintk("%s(%llu, %llu, %i) enter\n", __func__, start, end, tag);
++	list_for_each_entry_reverse(pos, &tree->mtt_stub, it_link) {
++		if (pos->it_sector >= end)
++			continue;
++		if (!expect) {
++			if ((pos->it_sector == end - tree->mtt_step_size) &&
++			    (pos->it_tags & (1 << tag))) {
++				expect = pos->it_sector - tree->mtt_step_size;
++				if (pos->it_sector < tree->mtt_step_size || expect < start)
++					return 1;
++				continue;
++			} else {
++				return 0;
++			}
++		}
++		if (pos->it_sector != expect || !(pos->it_tags & (1 << tag)))
++			return 0;
++		expect -= tree->mtt_step_size;
++		if (expect < start)
++			return 1;
++	}
++	return 0;
++}
++
++static int is_range_written(struct pnfs_inval_markings *marks,
++			    sector_t start, sector_t end)
++{
++	int rv;
++
++	spin_lock(&marks->im_lock);
++	rv = _range_has_tag(&marks->im_tree, start, end, EXTENT_WRITTEN);
++	spin_unlock(&marks->im_lock);
++	return rv;
++}
++
+ /* Marks sectors in [offest, offset_length) as having been initialized.
+  * All lengths are step-aligned, where step is min(pagesize, blocksize).
+  * Notes where partial block is initialized, and helps prepare it for
+@@ -396,6 +438,59 @@ static void add_to_commitlist(struct pnfs_block_layout *bl,
+ 	print_clist(clist, bl->bl_count);
+ }
+ 
++/* Note the range described by offset, length is guaranteed to be contained
++ * within be.
++ */
++int bl_mark_for_commit(struct pnfs_block_extent *be,
++		    sector_t offset, sector_t length)
++{
++	sector_t new_end, end = offset + length;
++	struct pnfs_block_short_extent *new;
++	struct pnfs_block_layout *bl = container_of(be->be_inval,
++						    struct pnfs_block_layout,
++						    bl_inval);
++
++	new = kmalloc(sizeof(*new), GFP_NOFS);
++	if (!new)
++		return -ENOMEM;
++
++	mark_written_sectors(be->be_inval, offset, length);
++	/* We want to add the range to commit list, but it must be
++	 * block-normalized, and verified that the normalized range has
++	 * been entirely written to disk.
++	 */
++	new->bse_f_offset = offset;
++	offset = normalize(offset, bl->bl_blocksize);
++	if (offset < new->bse_f_offset) {
++		if (is_range_written(be->be_inval, offset, new->bse_f_offset))
++			new->bse_f_offset = offset;
++		else
++			new->bse_f_offset = offset + bl->bl_blocksize;
++	}
++	new_end = normalize_up(end, bl->bl_blocksize);
++	if (end < new_end) {
++		if (is_range_written(be->be_inval, end, new_end))
++			end = new_end;
++		else
++			end = new_end - bl->bl_blocksize;
++	}
++	if (end <= new->bse_f_offset) {
++		kfree(new);
++		return 0;
++	}
++	new->bse_length = end - new->bse_f_offset;
++	new->bse_devid = be->be_devid;
++	new->bse_mdev = be->be_mdev;
++
++	spin_lock(&bl->bl_ext_lock);
++	/* new will be freed, either by add_to_commitlist if it decides not
++	 * to use it, or after LAYOUTCOMMIT uses it in the commitlist.
++	 */
++	add_to_commitlist(bl, new);
++	spin_unlock(&bl->bl_ext_lock);
++	return 0;
++}
++
+ static void print_bl_extent(struct pnfs_block_extent *be)
+ {
+ 	dprintk("PRINT EXTENT extent %p\n", be);

commit 650e2d39bd8f6b99f39b5009dbed9fbd3bb65e54
+Author: Fred Isaman 
+Date:   Sat Jul 30 20:52:54 2011 -0400
+
+    pnfsblock: bl_write_pagelist
+    
+    Note: When upper layer's read/write request cannot be fulfilled, the block
+    layout driver shouldn't silently mark the page as error. It should do
+    what can be done and  leave the rest to the upper layer. To do so, we
+    should set rdata/wdata->res.count properly.
+    
+    When upper layer re-send the read/write request to finish the rest
+    part of the request, pgbase is the position where we should start at.
+    
+    [pnfsblock: bl_write_pagelist support functions]
+    [pnfsblock: bl_write_pagelist adjust for missing PG_USE_PNFS]
+    Signed-off-by: Fred Isaman 
+    [pnfsblock: handle errors when read or write pagelist.]
+    Signed-off-by: Zhang Jingwang 
+    [pnfs-block: use new write_pagelist api]
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Jim Rees 
+    
+    [SQUASHME: pnfsblock: mds_offset is set in the generic layer]
+    Signed-off-by: Boaz Harrosh 
+    Signed-off-by: Benny Halevy 
+    
+    [pnfsblock: mark IO error with NFS_LAYOUT_{RW|RO}_FAILED]
+    Signed-off-by: Peng Tao 
+    [pnfsblock: SQUASHME: adjust to API change]
+    Signed-off-by: Fred Isaman 
+    [pnfsblock: fixup blksize alignment in bl_setup_layoutcommit]
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Benny Halevy 
+    [pnfsblock: bl_write_pagelist adjust for missing PG_USE_PNFS]
+    Signed-off-by: Fred Isaman 
+    [pnfsblock: handle errors when read or write pagelist.]
+    Signed-off-by: Zhang Jingwang 
+    [pnfs-block: use new write_pagelist api]
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Jim Rees 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
+index facb5ba21204..2e373826db80 100644
+--- a/fs/nfs/blocklayout/blocklayout.c
++++ b/fs/nfs/blocklayout/blocklayout.c
+@@ -74,6 +74,19 @@ static int is_hole(struct pnfs_block_extent *be, sector_t isect)
+ 		return !bl_is_sector_init(be->be_inval, isect);
+ }
+ 
++/* Given the be associated with isect, determine if page data can be
++ * written to disk.
++ */
++static int is_writable(struct pnfs_block_extent *be, sector_t isect)
++{
++	if (be->be_state == PNFS_BLOCK_READWRITE_DATA)
++		return 1;
++	else if (be->be_state != PNFS_BLOCK_INVALID_DATA)
++		return 0;
++	else
++		return bl_is_sector_init(be->be_inval, isect);
++}
++
+ /* The data we are handed might be spread across several bios.  We need
+  * to track when the last one is finished.
+  */
+@@ -316,11 +329,121 @@ bl_read_pagelist(struct nfs_read_data *rdata)
+ 	return PNFS_NOT_ATTEMPTED;
+ }
+ 
++/* This is basically copied from mpage_end_io_read */
++static void bl_end_io_write(struct bio *bio, int err)
++{
++	struct parallel_io *par = bio->bi_private;
++	const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
++	struct nfs_write_data *wdata = (struct nfs_write_data *)par->data;
++
++	if (!uptodate) {
++		if (!wdata->pnfs_error)
++			wdata->pnfs_error = -EIO;
++		bl_set_lo_fail(wdata->lseg);
++	}
++	bio_put(bio);
++	put_parallel(par);
++}
++
++/* Function scheduled for call during bl_end_par_io_write,
++ * it marks sectors as written and extends the commitlist.
++ */
++static void bl_write_cleanup(struct work_struct *work)
++{
++	struct rpc_task *task;
++	struct nfs_write_data *wdata;
++	dprintk("%s enter\n", __func__);
++	task = container_of(work, struct rpc_task, u.tk_work);
++	wdata = container_of(task, struct nfs_write_data, task);
++	pnfs_ld_write_done(wdata);
++}
++
++/* Called when last of bios associated with a bl_write_pagelist call finishes */
++static void
++bl_end_par_io_write(void *data)
++{
++	struct nfs_write_data *wdata = data;
++
++	/* STUB - ignoring error handling */
++	wdata->task.tk_status = 0;
++	wdata->verf.committed = NFS_FILE_SYNC;
++	INIT_WORK(&wdata->task.u.tk_work, bl_write_cleanup);
++	schedule_work(&wdata->task.u.tk_work);
++}
++
+ static enum pnfs_try_status
+-bl_write_pagelist(struct nfs_write_data *wdata,
+-		  int sync)
++bl_write_pagelist(struct nfs_write_data *wdata, int sync)
+ {
+-	return PNFS_NOT_ATTEMPTED;
++	int i;
++	struct bio *bio = NULL;
++	struct pnfs_block_extent *be = NULL;
++	sector_t isect, extent_length = 0;
++	struct parallel_io *par;
++	loff_t offset = wdata->args.offset;
++	size_t count = wdata->args.count;
++	struct page **pages = wdata->args.pages;
++	int pg_index = wdata->args.pgbase >> PAGE_CACHE_SHIFT;
++
++	dprintk("%s enter, %Zu@%lld\n", __func__, count, offset);
++	/* At this point, wdata->pages is a (sequential) list of nfs_pages.
++	 * We want to write each, and if there is an error remove it from
++	 * list and call
++	 * nfs_retry_request(req) to have it redone using nfs.
++	 * QUEST? Do as block or per req?  Think have to do per block
++	 * as part of end_bio
++	 */
++	par = alloc_parallel(wdata);
++	if (!par)
++		return PNFS_NOT_ATTEMPTED;
++	par->call_ops = *wdata->mds_ops;
++	par->call_ops.rpc_call_done = bl_rpc_do_nothing;
++	par->pnfs_callback = bl_end_par_io_write;
++	/* At this point, have to be more careful with error handling */
++
++	isect = (sector_t) ((offset & (long)PAGE_CACHE_MASK) >> SECTOR_SHIFT);
++	for (i = pg_index; i < wdata->npages ; i++) {
++		if (!extent_length) {
++			/* We've used up the previous extent */
++			bl_put_extent(be);
++			bio = bl_submit_bio(WRITE, bio);
++			/* Get the next one */
++			be = bl_find_get_extent(BLK_LSEG2EXT(wdata->lseg),
++					     isect, NULL);
++			if (!be || !is_writable(be, isect)) {
++				wdata->pnfs_error = -ENOMEM;
++				goto out;
++			}
++			extent_length = be->be_length -
++				(isect - be->be_f_offset);
++		}
++		for (;;) {
++			if (!bio) {
++				bio = bio_alloc(GFP_NOIO, wdata->npages - i);
++				if (!bio) {
++					wdata->pnfs_error = -ENOMEM;
++					goto out;
++				}
++				bio->bi_sector = isect - be->be_f_offset +
++					be->be_v_offset;
++				bio->bi_bdev = be->be_mdev;
++				bio->bi_end_io = bl_end_io_write;
++				bio->bi_private = par;
++			}
++			if (bio_add_page(bio, pages[i], PAGE_SIZE, 0))
++				break;
++			bio = bl_submit_bio(WRITE, bio);
++		}
++		isect += PAGE_CACHE_SECTORS;
++		extent_length -= PAGE_CACHE_SECTORS;
++	}
++	wdata->res.count = (isect << SECTOR_SHIFT) - (offset);
++	if (count < wdata->res.count)
++		wdata->res.count = count;
++out:
++	bl_put_extent(be);
++	bl_submit_bio(WRITE, bio);
++	put_parallel(par);
++	return PNFS_ATTEMPTED;
+ }
+ 
+ /* FIXME - range ignored */

commit 9549ec01b0dcf1c1eb277cba60067236b3f48508
+Author: Fred Isaman 
+Date:   Sat Jul 30 20:52:53 2011 -0400
+
+    pnfsblock: bl_read_pagelist
+    
+    Note: When upper layer's read/write request cannot be fulfilled, the block
+    layout driver shouldn't silently mark the page as error. It should do
+    what can be done and  leave the rest to the upper layer. To do so, we
+    should set rdata/wdata->res.count properly.
+    
+    When upper layer re-send the read/write request to finish the rest
+    part of the request, pgbase is the position where we should start at.
+    
+    [pnfsblock: mark IO error with NFS_LAYOUT_{RW|RO}_FAILED]
+    Signed-off-by: Peng Tao 
+    [pnfsblock: read path error handling]
+    Signed-off-by: Fred Isaman 
+    [pnfsblock: handle errors when read or write pagelist.]
+    Signed-off-by: Zhang Jingwang 
+    [pnfs-block: use new read_pagelist api]
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Jim Rees 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
+index 6c1bafb8920b..facb5ba21204 100644
+--- a/fs/nfs/blocklayout/blocklayout.c
++++ b/fs/nfs/blocklayout/blocklayout.c
+@@ -29,10 +29,12 @@
+  * of the software, even if it has been or is hereafter advised of the
+  * possibility of such damages.
+  */
++
+ #include 
+ #include 
+ #include 
+ #include 
++#include 		/* struct bio */
+ 
+ #include "blocklayout.h"
+ 
+@@ -45,9 +47,272 @@ MODULE_DESCRIPTION("The NFSv4.1 pNFS Block layout driver");
+ struct dentry *bl_device_pipe;
+ wait_queue_head_t bl_wq;
+ 
++static void print_page(struct page *page)
++{
++	dprintk("PRINTPAGE page %p\n", page);
++	dprintk("	PagePrivate %d\n", PagePrivate(page));
++	dprintk("	PageUptodate %d\n", PageUptodate(page));
++	dprintk("	PageError %d\n", PageError(page));
++	dprintk("	PageDirty %d\n", PageDirty(page));
++	dprintk("	PageReferenced %d\n", PageReferenced(page));
++	dprintk("	PageLocked %d\n", PageLocked(page));
++	dprintk("	PageWriteback %d\n", PageWriteback(page));
++	dprintk("	PageMappedToDisk %d\n", PageMappedToDisk(page));
++	dprintk("\n");
++}
++
++/* Given the be associated with isect, determine if page data needs to be
++ * initialized.
++ */
++static int is_hole(struct pnfs_block_extent *be, sector_t isect)
++{
++	if (be->be_state == PNFS_BLOCK_NONE_DATA)
++		return 1;
++	else if (be->be_state != PNFS_BLOCK_INVALID_DATA)
++		return 0;
++	else
++		return !bl_is_sector_init(be->be_inval, isect);
++}
++
++/* The data we are handed might be spread across several bios.  We need
++ * to track when the last one is finished.
++ */
++struct parallel_io {
++	struct kref refcnt;
++	struct rpc_call_ops call_ops;
++	void (*pnfs_callback) (void *data);
++	void *data;
++};
++
++static inline struct parallel_io *alloc_parallel(void *data)
++{
++	struct parallel_io *rv;
++
++	rv  = kmalloc(sizeof(*rv), GFP_NOFS);
++	if (rv) {
++		rv->data = data;
++		kref_init(&rv->refcnt);
++	}
++	return rv;
++}
++
++static inline void get_parallel(struct parallel_io *p)
++{
++	kref_get(&p->refcnt);
++}
++
++static void destroy_parallel(struct kref *kref)
++{
++	struct parallel_io *p = container_of(kref, struct parallel_io, refcnt);
++
++	dprintk("%s enter\n", __func__);
++	p->pnfs_callback(p->data);
++	kfree(p);
++}
++
++static inline void put_parallel(struct parallel_io *p)
++{
++	kref_put(&p->refcnt, destroy_parallel);
++}
++
++static struct bio *
++bl_submit_bio(int rw, struct bio *bio)
++{
++	if (bio) {
++		get_parallel(bio->bi_private);
++		dprintk("%s submitting %s bio %u@%llu\n", __func__,
++			rw == READ ? "read" : "write",
++			bio->bi_size, (unsigned long long)bio->bi_sector);
++		submit_bio(rw, bio);
++	}
++	return NULL;
++}
++
++static struct bio *bl_alloc_init_bio(int npg, sector_t isect,
++				     struct pnfs_block_extent *be,
++				     void (*end_io)(struct bio *, int err),
++				     struct parallel_io *par)
++{
++	struct bio *bio;
++
++	bio = bio_alloc(GFP_NOIO, npg);
++	if (!bio)
++		return NULL;
++
++	bio->bi_sector = isect - be->be_f_offset + be->be_v_offset;
++	bio->bi_bdev = be->be_mdev;
++	bio->bi_end_io = end_io;
++	bio->bi_private = par;
++	return bio;
++}
++
++static struct bio *bl_add_page_to_bio(struct bio *bio, int npg, int rw,
++				      sector_t isect, struct page *page,
++				      struct pnfs_block_extent *be,
++				      void (*end_io)(struct bio *, int err),
++				      struct parallel_io *par)
++{
++retry:
++	if (!bio) {
++		bio = bl_alloc_init_bio(npg, isect, be, end_io, par);
++		if (!bio)
++			return ERR_PTR(-ENOMEM);
++	}
++	if (bio_add_page(bio, page, PAGE_CACHE_SIZE, 0) < PAGE_CACHE_SIZE) {
++		bio = bl_submit_bio(rw, bio);
++		goto retry;
++	}
++	return bio;
++}
++
++static void bl_set_lo_fail(struct pnfs_layout_segment *lseg)
++{
++	if (lseg->pls_range.iomode == IOMODE_RW) {
++		dprintk("%s Setting layout IOMODE_RW fail bit\n", __func__);
++		set_bit(lo_fail_bit(IOMODE_RW), &lseg->pls_layout->plh_flags);
++	} else {
++		dprintk("%s Setting layout IOMODE_READ fail bit\n", __func__);
++		set_bit(lo_fail_bit(IOMODE_READ), &lseg->pls_layout->plh_flags);
++	}
++}
++
++/* This is basically copied from mpage_end_io_read */
++static void bl_end_io_read(struct bio *bio, int err)
++{
++	struct parallel_io *par = bio->bi_private;
++	const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
++	struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
++	struct nfs_read_data *rdata = (struct nfs_read_data *)par->data;
++
++	do {
++		struct page *page = bvec->bv_page;
++
++		if (--bvec >= bio->bi_io_vec)
++			prefetchw(&bvec->bv_page->flags);
++		if (uptodate)
++			SetPageUptodate(page);
++	} while (bvec >= bio->bi_io_vec);
++	if (!uptodate) {
++		if (!rdata->pnfs_error)
++			rdata->pnfs_error = -EIO;
++		bl_set_lo_fail(rdata->lseg);
++	}
++	bio_put(bio);
++	put_parallel(par);
++}
++
++static void bl_read_cleanup(struct work_struct *work)
++{
++	struct rpc_task *task;
++	struct nfs_read_data *rdata;
++	dprintk("%s enter\n", __func__);
++	task = container_of(work, struct rpc_task, u.tk_work);
++	rdata = container_of(task, struct nfs_read_data, task);
++	pnfs_ld_read_done(rdata);
++}
++
++static void
++bl_end_par_io_read(void *data)
++{
++	struct nfs_read_data *rdata = data;
++
++	INIT_WORK(&rdata->task.u.tk_work, bl_read_cleanup);
++	schedule_work(&rdata->task.u.tk_work);
++}
++
++/* We don't want normal .rpc_call_done callback used, so we replace it
++ * with this stub.
++ */
++static void bl_rpc_do_nothing(struct rpc_task *task, void *calldata)
++{
++	return;
++}
++
+ static enum pnfs_try_status
+ bl_read_pagelist(struct nfs_read_data *rdata)
+ {
++	int i, hole;
++	struct bio *bio = NULL;
++	struct pnfs_block_extent *be = NULL, *cow_read = NULL;
++	sector_t isect, extent_length = 0;
++	struct parallel_io *par;
++	loff_t f_offset = rdata->args.offset;
++	size_t count = rdata->args.count;
++	struct page **pages = rdata->args.pages;
++	int pg_index = rdata->args.pgbase >> PAGE_CACHE_SHIFT;
++
++	dprintk("%s enter nr_pages %u offset %lld count %Zd\n", __func__,
++	       rdata->npages, f_offset, count);
++
++	par = alloc_parallel(rdata);
++	if (!par)
++		goto use_mds;
++	par->call_ops = *rdata->mds_ops;
++	par->call_ops.rpc_call_done = bl_rpc_do_nothing;
++	par->pnfs_callback = bl_end_par_io_read;
++	/* At this point, we can no longer jump to use_mds */
++
++	isect = (sector_t) (f_offset >> SECTOR_SHIFT);
++	/* Code assumes extents are page-aligned */
++	for (i = pg_index; i < rdata->npages; i++) {
++		if (!extent_length) {
++			/* We've used up the previous extent */
++			bl_put_extent(be);
++			bl_put_extent(cow_read);
++			bio = bl_submit_bio(READ, bio);
++			/* Get the next one */
++			be = bl_find_get_extent(BLK_LSEG2EXT(rdata->lseg),
++					     isect, &cow_read);
++			if (!be) {
++				rdata->pnfs_error = -EIO;
++				goto out;
++			}
++			extent_length = be->be_length -
++				(isect - be->be_f_offset);
++			if (cow_read) {
++				sector_t cow_length = cow_read->be_length -
++					(isect - cow_read->be_f_offset);
++				extent_length = min(extent_length, cow_length);
++			}
++		}
++		hole = is_hole(be, isect);
++		if (hole && !cow_read) {
++			bio = bl_submit_bio(READ, bio);
++			/* Fill hole w/ zeroes w/o accessing device */
++			dprintk("%s Zeroing page for hole\n", __func__);
++			zero_user_segment(pages[i], 0, PAGE_CACHE_SIZE);
++			print_page(pages[i]);
++			SetPageUptodate(pages[i]);
++		} else {
++			struct pnfs_block_extent *be_read;
++
++			be_read = (hole && cow_read) ? cow_read : be;
++			bio = bl_add_page_to_bio(bio, rdata->npages - i, READ,
++						 isect, pages[i], be_read,
++						 bl_end_io_read, par);
++			if (IS_ERR(bio)) {
++				rdata->pnfs_error = PTR_ERR(bio);
++				goto out;
++			}
++		}
++		isect += PAGE_CACHE_SECTORS;
++		extent_length -= PAGE_CACHE_SECTORS;
++	}
++	if ((isect << SECTOR_SHIFT) >= rdata->inode->i_size) {
++		rdata->res.eof = 1;
++		rdata->res.count = rdata->inode->i_size - f_offset;
++	} else {
++		rdata->res.count = (isect << SECTOR_SHIFT) - f_offset;
++	}
++out:
++	bl_put_extent(be);
++	bl_put_extent(cow_read);
++	bl_submit_bio(READ, bio);
++	put_parallel(par);
++	return PNFS_ATTEMPTED;
++
++ use_mds:
++	dprintk("Giving up and using normal NFS\n");
+ 	return PNFS_NOT_ATTEMPTED;
+ }
+ 

commit b2be7811dd94816f3df76708c8eb7f55bf7289e2
+Author: Fred Isaman 
+Date:   Sat Jul 30 20:52:52 2011 -0400
+
+    pnfsblock: cleanup_layoutcommit
+    
+    In blocklayout driver. There are two things happening
+    while layoutcommit/cleanup.
+    1. the modified extents are encoded.
+    2. On cleanup the extents are put back on the layout rw
+       extents list, for reads.
+    
+    In the new system where actual xdr encoding is done in
+    encode_layoutcommit() directly into xdr buffer, these are
+    the new commit stages:
+    
+    1. On setup_layoutcommit, the range is adjusted as before
+       and a structure is allocated for communication with
+       bl_encode_layoutcommit && bl_cleanup_layoutcommit
+       (Generic layer provides a void-star to hang it on)
+    
+    2. bl_encode_layoutcommit is called to do the actual
+       encoding directly into xdr. The commit-extent-list is not
+       freed and is stored on above structure.
+       FIXME: The code is not yet converted to the new XDR cleanup
+    
+    3. On cleanup the commit-extent-list is put back by a call
+       to set_to_rw() as before, but with no need for XDR decoding
+       of the list as before. And the commit-extent-list is freed.
+       Finally allocated structure is freed.
+    
+    [rm inode and pnfs_layout_hdr args from cleanup_layoutcommit()]
+    Signed-off-by: Jim Rees 
+    [pnfsblock: introduce bl_committing list]
+    Signed-off-by: Peng Tao 
+    [pnfsblock: SQUASHME: adjust to API change]
+    Signed-off-by: Fred Isaman 
+    [blocklayout: encode_layoutcommit implementation]
+    Signed-off-by: Boaz Harrosh 
+    [pnfsblock: fix bug setting up layoutcommit.]
+    Signed-off-by: Tao Guo 
+    [pnfsblock: cleanup_layoutcommit wants a status parameter]
+    Signed-off-by: Boaz Harrosh 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Jim Rees 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
+index d096835cfd6b..6c1bafb8920b 100644
+--- a/fs/nfs/blocklayout/blocklayout.c
++++ b/fs/nfs/blocklayout/blocklayout.c
+@@ -162,6 +162,10 @@ bl_encode_layoutcommit(struct pnfs_layout_hdr *lo, struct xdr_stream *xdr,
+ static void
+ bl_cleanup_layoutcommit(struct nfs4_layoutcommit_data *lcdata)
+ {
++	struct pnfs_layout_hdr *lo = NFS_I(lcdata->args.inode)->layout;
++
++	dprintk("%s enter\n", __func__);
++	clean_pnfs_block_layoutupdate(BLK_LO2EXT(lo), &lcdata->args, lcdata->res.status);
+ }
+ 
+ static void free_blk_mountid(struct block_mount_id *mid)
+diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklayout.h
+index 3caaefce85a5..6a703b79c33d 100644
+--- a/fs/nfs/blocklayout/blocklayout.h
++++ b/fs/nfs/blocklayout/blocklayout.h
+@@ -196,6 +196,9 @@ int bl_is_sector_init(struct pnfs_inval_markings *marks, sector_t isect);
+ int encode_pnfs_block_layoutupdate(struct pnfs_block_layout *bl,
+ 				   struct xdr_stream *xdr,
+ 				   const struct nfs4_layoutcommit_args *arg);
++void clean_pnfs_block_layoutupdate(struct pnfs_block_layout *bl,
++				   const struct nfs4_layoutcommit_args *arg,
++				   int status);
+ int bl_add_merge_extent(struct pnfs_block_layout *bl,
+ 			 struct pnfs_block_extent *new);
+ 
+diff --git a/fs/nfs/blocklayout/extents.c b/fs/nfs/blocklayout/extents.c
+index 84bf24087720..7521940dcca5 100644
+--- a/fs/nfs/blocklayout/extents.c
++++ b/fs/nfs/blocklayout/extents.c
+@@ -329,6 +329,73 @@ static void print_clist(struct list_head *list, unsigned int count)
+ 	}
+ }
+ 
++/* Note: In theory, we should do more checking that devid's match between
++ * old and new, but if they don't, the lists are too corrupt to salvage anyway.
++ */
++/* Note this is very similar to bl_add_merge_extent */
++static void add_to_commitlist(struct pnfs_block_layout *bl,
++			      struct pnfs_block_short_extent *new)
++{
++	struct list_head *clist = &bl->bl_commit;
++	struct pnfs_block_short_extent *old, *save;
++	sector_t end = new->bse_f_offset + new->bse_length;
++
++	dprintk("%s enter\n", __func__);
++	print_short_extent(new);
++	print_clist(clist, bl->bl_count);
++	bl->bl_count++;
++	/* Scan for proper place to insert, extending new to the left
++	 * as much as possible.
++	 */
++	list_for_each_entry_safe(old, save, clist, bse_node) {
++		if (new->bse_f_offset < old->bse_f_offset)
++			break;
++		if (end <= old->bse_f_offset + old->bse_length) {
++			/* Range is already in list */
++			bl->bl_count--;
++			kfree(new);
++			return;
++		} else if (new->bse_f_offset <=
++				old->bse_f_offset + old->bse_length) {
++			/* new overlaps or abuts existing be */
++			if (new->bse_mdev == old->bse_mdev) {
++				/* extend new to fully replace old */
++				new->bse_length += new->bse_f_offset -
++						old->bse_f_offset;
++				new->bse_f_offset = old->bse_f_offset;
++				list_del(&old->bse_node);
++				bl->bl_count--;
++				kfree(old);
++			}
++		}
++	}
++	/* Note that if we never hit the above break, old will not point to a
++	 * valid extent.  However, in that case &old->bse_node==list.
++	 */
++	list_add_tail(&new->bse_node, &old->bse_node);
++	/* Scan forward for overlaps.  If we find any, extend new and
++	 * remove the overlapped extent.
++	 */
++	old = list_prepare_entry(new, clist, bse_node);
++	list_for_each_entry_safe_continue(old, save, clist, bse_node) {
++		if (end < old->bse_f_offset)
++			break;
++		/* new overlaps or abuts old */
++		if (new->bse_mdev == old->bse_mdev) {
++			if (end < old->bse_f_offset + old->bse_length) {
++				/* extend new to fully cover old */
++				end = old->bse_f_offset + old->bse_length;
++				new->bse_length = end - new->bse_f_offset;
++			}
++			list_del(&old->bse_node);
++			bl->bl_count--;
++			kfree(old);
++		}
++	}
++	dprintk("%s: after merging\n", __func__);
++	print_clist(clist, bl->bl_count);
++}
++
+ static void print_bl_extent(struct pnfs_block_extent *be)
+ {
+ 	dprintk("PRINT EXTENT extent %p\n", be);
+@@ -539,6 +606,34 @@ bl_find_get_extent(struct pnfs_block_layout *bl, sector_t isect,
+ 	return ret;
+ }
+ 
++/* Similar to bl_find_get_extent, but called with lock held, and ignores cow */
++static struct pnfs_block_extent *
++bl_find_get_extent_locked(struct pnfs_block_layout *bl, sector_t isect)
++{
++	struct pnfs_block_extent *be, *ret = NULL;
++	int i;
++
++	dprintk("%s enter with isect %llu\n", __func__, (u64)isect);
++	for (i = 0; i < EXTENT_LISTS; i++) {
++		if (ret)
++			break;
++		list_for_each_entry_reverse(be, &bl->bl_extents[i], be_node) {
++			if (isect >= be->be_f_offset + be->be_length)
++				break;
++			if (isect >= be->be_f_offset) {
++				/* We have found an extent */
++				dprintk("%s Get %p (%i)\n", __func__, be,
++					atomic_read(&be->be_refcnt.refcount));
++				kref_get(&be->be_refcnt);
++				ret = be;
++				break;
++			}
++		}
++	}
++	print_bl_extent(ret);
++	return ret;
++}
++
+ int
+ encode_pnfs_block_layoutupdate(struct pnfs_block_layout *bl,
+ 			       struct xdr_stream *xdr,
+@@ -628,3 +723,118 @@ _front_merge(struct pnfs_block_extent *be, struct list_head *head,
+ 	kfree(storage);
+ 	return be;
+ }
++
++static u64
++set_to_rw(struct pnfs_block_layout *bl, u64 offset, u64 length)
++{
++	u64 rv = offset + length;
++	struct pnfs_block_extent *be, *e1, *e2, *e3, *new, *old;
++	struct pnfs_block_extent *children[3];
++	struct pnfs_block_extent *merge1 = NULL, *merge2 = NULL;
++	int i = 0, j;
++
++	dprintk("%s(%llu, %llu)\n", __func__, offset, length);
++	/* Create storage for up to three new extents e1, e2, e3 */
++	e1 = kmalloc(sizeof(*e1), GFP_ATOMIC);
++	e2 = kmalloc(sizeof(*e2), GFP_ATOMIC);
++	e3 = kmalloc(sizeof(*e3), GFP_ATOMIC);
++	/* BUG - we are ignoring any failure */
++	if (!e1 || !e2 || !e3)
++		goto out_nosplit;
++
++	spin_lock(&bl->bl_ext_lock);
++	be = bl_find_get_extent_locked(bl, offset);
++	rv = be->be_f_offset + be->be_length;
++	if (be->be_state != PNFS_BLOCK_INVALID_DATA) {
++		spin_unlock(&bl->bl_ext_lock);
++		goto out_nosplit;
++	}
++	/* Add e* to children, bumping e*'s krefs */
++	if (be->be_f_offset != offset) {
++		_prep_new_extent(e1, be, be->be_f_offset,
++				 offset - be->be_f_offset,
++				 PNFS_BLOCK_INVALID_DATA);
++		children[i++] = e1;
++		print_bl_extent(e1);
++	} else
++		merge1 = e1;
++	_prep_new_extent(e2, be, offset,
++			 min(length, be->be_f_offset + be->be_length - offset),
++			 PNFS_BLOCK_READWRITE_DATA);
++	children[i++] = e2;
++	print_bl_extent(e2);
++	if (offset + length < be->be_f_offset + be->be_length) {
++		_prep_new_extent(e3, be, e2->be_f_offset + e2->be_length,
++				 be->be_f_offset + be->be_length -
++				 offset - length,
++				 PNFS_BLOCK_INVALID_DATA);
++		children[i++] = e3;
++		print_bl_extent(e3);
++	} else
++		merge2 = e3;
++
++	/* Remove be from list, and insert the e* */
++	/* We don't get refs on e*, since this list is the base reference
++	 * set when init'ed.
++	 */
++	if (i < 3)
++		children[i] = NULL;
++	new = children[0];
++	list_replace(&be->be_node, &new->be_node);
++	bl_put_extent(be);
++	new = _front_merge(new, &bl->bl_extents[RW_EXTENT], merge1);
++	for (j = 1; j < i; j++) {
++		old = new;
++		new = children[j];
++		list_add(&new->be_node, &old->be_node);
++	}
++	if (merge2) {
++		/* This is a HACK, should just create a _back_merge function */
++		new = list_entry(new->be_node.next,
++				 struct pnfs_block_extent, be_node);
++		new = _front_merge(new, &bl->bl_extents[RW_EXTENT], merge2);
++	}
++	spin_unlock(&bl->bl_ext_lock);
++
++	/* Since we removed the base reference above, be is now scheduled for
++	 * destruction.
++	 */
++	bl_put_extent(be);
++	dprintk("%s returns %llu after split\n", __func__, rv);
++	return rv;
++
++ out_nosplit:
++	kfree(e1);
++	kfree(e2);
++	kfree(e3);
++	dprintk("%s returns %llu without splitting\n", __func__, rv);
++	return rv;
++}
++
++void
++clean_pnfs_block_layoutupdate(struct pnfs_block_layout *bl,
++			      const struct nfs4_layoutcommit_args *arg,
++			      int status)
++{
++	struct pnfs_block_short_extent *lce, *save;
++
++	dprintk("%s status %d\n", __func__, status);
++	list_for_each_entry_safe(lce, save, &bl->bl_committing, bse_node) {
++		if (likely(!status)) {
++			u64 offset = lce->bse_f_offset;
++			u64 end = offset + lce->bse_length;
++
++			do {
++				offset = set_to_rw(bl, offset, end - offset);
++			} while (offset < end);
++			list_del(&lce->bse_node);
++
++			kfree(lce);
++		} else {
++			list_del(&lce->bse_node);
++			spin_lock(&bl->bl_ext_lock);
++			add_to_commitlist(bl, lce);
++			spin_unlock(&bl->bl_ext_lock);
++		}
++	}
++}

commit 90ace12ac42f65d1f077c5ef5ec2efafdcac338f
+Author: Fred Isaman 
+Date:   Sat Jul 30 20:52:51 2011 -0400
+
+    pnfsblock: encode_layoutcommit
+    
+    In blocklayout driver. There are two things happening
+    while layoutcommit/cleanup.
+    1. the modified extents are encoded.
+    2. On cleanup the extents are put back on the layout rw
+       extents list, for reads.
+    
+    In the new system where actual xdr encoding is done in
+    encode_layoutcommit() directly into xdr buffer, these are
+    the new commit stages:
+    
+    1. On setup_layoutcommit, the range is adjusted as before
+       and a structure is allocated for communication with
+       bl_encode_layoutcommit && bl_cleanup_layoutcommit
+       (Generic layer provides a void-star to hang it on)
+    
+    2. bl_encode_layoutcommit is called to do the actual
+       encoding directly into xdr. The commit-extent-list is not
+       freed and is stored on above structure.
+       FIXME: The code is not yet converted to the new XDR cleanup
+    
+    3. On cleanup the commit-extent-list is put back by a call
+       to set_to_rw() as before, but with no need for XDR decoding
+       of the list as before. And the commit-extent-list is freed.
+       Finally allocated structure is freed.
+    
+    [rm inode and pnfs_layout_hdr args from cleanup_layoutcommit()]
+    [pnfsblock: get rid of deprecated xdr macros]
+    Signed-off-by: Jim Rees 
+    Signed-off-by: Peng Tao 
+    Signed-off-by: Fred Isaman 
+    [blocklayout: encode_layoutcommit implementation]
+    Signed-off-by: Boaz Harrosh 
+    [pnfsblock: fix bug setting up layoutcommit.]
+    Signed-off-by: Tao Guo 
+    [pnfsblock: prevent commit list corruption]
+    [pnfsblock: fix layoutcommit with an empty opaque]
+    Signed-off-by: Fred Isaman 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Jim Rees 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
+index 8c29a189f09b..d096835cfd6b 100644
+--- a/fs/nfs/blocklayout/blocklayout.c
++++ b/fs/nfs/blocklayout/blocklayout.c
+@@ -155,6 +155,8 @@ static void
+ bl_encode_layoutcommit(struct pnfs_layout_hdr *lo, struct xdr_stream *xdr,
+ 		       const struct nfs4_layoutcommit_args *arg)
+ {
++	dprintk("%s enter\n", __func__);
++	encode_pnfs_block_layoutupdate(BLK_LO2EXT(lo), xdr, arg);
+ }
+ 
+ static void
+diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklayout.h
+index fcf47b55b5ce..3caaefce85a5 100644
+--- a/fs/nfs/blocklayout/blocklayout.h
++++ b/fs/nfs/blocklayout/blocklayout.h
+@@ -91,6 +91,15 @@ struct pnfs_block_extent {
+ 	struct pnfs_inval_markings *be_inval; /* tracks INVAL->RW transition */
+ };
+ 
++/* Shortened extent used by LAYOUTCOMMIT */
++struct pnfs_block_short_extent {
++	struct list_head bse_node;
++	struct nfs4_deviceid bse_devid;
++	struct block_device *bse_mdev;
++	sector_t	bse_f_offset;	/* the starting offset in the file */
++	sector_t	bse_length;	/* the size of the extent */
++};
++
+ static inline void
+ BL_INIT_INVAL_MARKS(struct pnfs_inval_markings *marks, sector_t blocksize)
+ {
+@@ -184,6 +193,9 @@ int bl_mark_sectors_init(struct pnfs_inval_markings *marks,
+ void bl_put_extent(struct pnfs_block_extent *be);
+ struct pnfs_block_extent *bl_alloc_extent(void);
+ int bl_is_sector_init(struct pnfs_inval_markings *marks, sector_t isect);
++int encode_pnfs_block_layoutupdate(struct pnfs_block_layout *bl,
++				   struct xdr_stream *xdr,
++				   const struct nfs4_layoutcommit_args *arg);
+ int bl_add_merge_extent(struct pnfs_block_layout *bl,
+ 			 struct pnfs_block_extent *new);
+ 
+diff --git a/fs/nfs/blocklayout/extents.c b/fs/nfs/blocklayout/extents.c
+index 292aadfd4d46..84bf24087720 100644
+--- a/fs/nfs/blocklayout/extents.c
++++ b/fs/nfs/blocklayout/extents.c
+@@ -286,6 +286,49 @@ int bl_mark_sectors_init(struct pnfs_inval_markings *marks,
+ 	return -ENOMEM;
+ }
+ 
++/* Marks sectors in [offest, offset+length) as having been written to disk.
++ * All lengths should be block aligned.
++ */
++static int mark_written_sectors(struct pnfs_inval_markings *marks,
++				sector_t offset, sector_t length)
++{
++	int status;
++
++	dprintk("%s(offset=%llu,len=%llu) enter\n", __func__,
++		(u64)offset, (u64)length);
++	spin_lock(&marks->im_lock);
++	status = _set_range(&marks->im_tree, EXTENT_WRITTEN, offset, length);
++	spin_unlock(&marks->im_lock);
++	return status;
++}
++
++static void print_short_extent(struct pnfs_block_short_extent *be)
++{
++	dprintk("PRINT SHORT EXTENT extent %p\n", be);
++	if (be) {
++		dprintk("        be_f_offset %llu\n", (u64)be->bse_f_offset);
++		dprintk("        be_length   %llu\n", (u64)be->bse_length);
++	}
++}
++
++static void print_clist(struct list_head *list, unsigned int count)
++{
++	struct pnfs_block_short_extent *be;
++	unsigned int i = 0;
++
++	ifdebug(FACILITY) {
++		printk(KERN_DEBUG "****************\n");
++		printk(KERN_DEBUG "Extent list looks like:\n");
++		list_for_each_entry(be, list, bse_node) {
++			i++;
++			print_short_extent(be);
++		}
++		if (i != count)
++			printk(KERN_DEBUG "\n\nExpected %u entries\n\n\n", count);
++		printk(KERN_DEBUG "****************\n");
++	}
++}
++
+ static void print_bl_extent(struct pnfs_block_extent *be)
+ {
+ 	dprintk("PRINT EXTENT extent %p\n", be);
+@@ -378,65 +421,67 @@ bl_add_merge_extent(struct pnfs_block_layout *bl,
+ 	/* Scan for proper place to insert, extending new to the left
+ 	 * as much as possible.
+ 	 */
+-	list_for_each_entry_safe(be, tmp, list, be_node) {
+-		if (new->be_f_offset < be->be_f_offset)
++	list_for_each_entry_safe_reverse(be, tmp, list, be_node) {
++		if (new->be_f_offset >= be->be_f_offset + be->be_length)
+ 			break;
+-		if (end <= be->be_f_offset + be->be_length) {
+-			/* new is a subset of existing be*/
++		if (new->be_f_offset >= be->be_f_offset) {
++			if (end <= be->be_f_offset + be->be_length) {
++				/* new is a subset of existing be*/
++				if (extents_consistent(be, new)) {
++					dprintk("%s: new is subset, ignoring\n",
++						__func__);
++					bl_put_extent(new);
++					return 0;
++				} else {
++					goto out_err;
++				}
++			} else {
++				/* |<--   be   -->|
++				 *          |<--   new   -->| */
++				if (extents_consistent(be, new)) {
++					/* extend new to fully replace be */
++					new->be_length += new->be_f_offset -
++						be->be_f_offset;
++					new->be_f_offset = be->be_f_offset;
++					new->be_v_offset = be->be_v_offset;
++					dprintk("%s: removing %p\n", __func__, be);
++					list_del(&be->be_node);
++					bl_put_extent(be);
++				} else {
++					goto out_err;
++				}
++			}
++		} else if (end >= be->be_f_offset + be->be_length) {
++			/* new extent overlap existing be */
+ 			if (extents_consistent(be, new)) {
+-				dprintk("%s: new is subset, ignoring\n",
+-					__func__);
+-				bl_put_extent(new);
+-				return 0;
+-			} else
++				/* extend new to fully replace be */
++				dprintk("%s: removing %p\n", __func__, be);
++				list_del(&be->be_node);
++				bl_put_extent(be);
++			} else {
+ 				goto out_err;
+-		} else if (new->be_f_offset <=
+-				be->be_f_offset + be->be_length) {
+-			/* new overlaps or abuts existing be */
+-			if (extents_consistent(be, new)) {
++			}
++		} else if (end > be->be_f_offset) {
++			/*           |<--   be   -->|
++			 *|<--   new   -->| */
++			if (extents_consistent(new, be)) {
+ 				/* extend new to fully replace be */
+-				new->be_length += new->be_f_offset -
+-						  be->be_f_offset;
+-				new->be_f_offset = be->be_f_offset;
+-				new->be_v_offset = be->be_v_offset;
++				new->be_length += be->be_f_offset + be->be_length -
++					new->be_f_offset - new->be_length;
+ 				dprintk("%s: removing %p\n", __func__, be);
+ 				list_del(&be->be_node);
+ 				bl_put_extent(be);
+-			} else if (new->be_f_offset !=
+-				   be->be_f_offset + be->be_length)
++			} else {
+ 				goto out_err;
++			}
+ 		}
+ 	}
+ 	/* Note that if we never hit the above break, be will not point to a
+ 	 * valid extent.  However, in that case &be->be_node==list.
+ 	 */
+-	list_add_tail(&new->be_node, &be->be_node);
++	list_add(&new->be_node, &be->be_node);
+ 	dprintk("%s: inserting new\n", __func__);
+ 	print_elist(list);
+-	/* Scan forward for overlaps.  If we find any, extend new and
+-	 * remove the overlapped extent.
+-	 */
+-	be = list_prepare_entry(new, list, be_node);
+-	list_for_each_entry_safe_continue(be, tmp, list, be_node) {
+-		if (end < be->be_f_offset)
+-			break;
+-		/* new overlaps or abuts existing be */
+-		if (extents_consistent(be, new)) {
+-			if (end < be->be_f_offset + be->be_length) {
+-				/* extend new to fully cover be */
+-				end = be->be_f_offset + be->be_length;
+-				new->be_length = end - new->be_f_offset;
+-			}
+-			dprintk("%s: removing %p\n", __func__, be);
+-			list_del(&be->be_node);
+-			bl_put_extent(be);
+-		} else if (end != be->be_f_offset) {
+-			list_del(&new->be_node);
+-			goto out_err;
+-		}
+-	}
+-	dprintk("%s: after merging\n", __func__);
+-	print_elist(list);
+ 	/* FIXME - The per-list consistency checks have all been done,
+ 	 * should now check cross-list consistency.
+ 	 */
+@@ -494,6 +539,49 @@ bl_find_get_extent(struct pnfs_block_layout *bl, sector_t isect,
+ 	return ret;
+ }
+ 
++int
++encode_pnfs_block_layoutupdate(struct pnfs_block_layout *bl,
++			       struct xdr_stream *xdr,
++			       const struct nfs4_layoutcommit_args *arg)
++{
++	struct pnfs_block_short_extent *lce, *save;
++	unsigned int count = 0;
++	__be32 *p, *xdr_start;
++
++	dprintk("%s enter\n", __func__);
++	/* BUG - creation of bl_commit is buggy - need to wait for
++	 * entire block to be marked WRITTEN before it can be added.
++	 */
++	spin_lock(&bl->bl_ext_lock);
++	/* Want to adjust for possible truncate */
++	/* We now want to adjust argument range */
++
++	/* XDR encode the ranges found */
++	xdr_start = xdr_reserve_space(xdr, 8);
++	if (!xdr_start)
++		goto out;
++	list_for_each_entry_safe(lce, save, &bl->bl_commit, bse_node) {
++		p = xdr_reserve_space(xdr, 7 * 4 + sizeof(lce->bse_devid.data));
++		if (!p)
++			break;
++		p = xdr_encode_opaque_fixed(p, lce->bse_devid.data, NFS4_DEVICEID4_SIZE);
++		p = xdr_encode_hyper(p, lce->bse_f_offset << SECTOR_SHIFT);
++		p = xdr_encode_hyper(p, lce->bse_length << SECTOR_SHIFT);
++		p = xdr_encode_hyper(p, 0LL);
++		*p++ = cpu_to_be32(PNFS_BLOCK_READWRITE_DATA);
++		list_del(&lce->bse_node);
++		list_add_tail(&lce->bse_node, &bl->bl_committing);
++		bl->bl_count--;
++		count++;
++	}
++	xdr_start[0] = cpu_to_be32((xdr->p - xdr_start - 1) * 4);
++	xdr_start[1] = cpu_to_be32(count);
++out:
++	spin_unlock(&bl->bl_ext_lock);
++	dprintk("%s found %i ranges\n", __func__, count);
++	return 0;
++}
++
+ /* Helper function to set_to_rw that initialize a new extent */
+ static void
+ _prep_new_extent(struct pnfs_block_extent *new,

commit 9f3770422c771da32c1d14e650c695eec27dbd1d
+Author: Fred Isaman 
+Date:   Sat Jul 30 20:52:50 2011 -0400
+
+    pnfsblock: merge rw extents
+    
+    Signed-off-by: Fred Isaman 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Jim Rees 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/blocklayout/extents.c b/fs/nfs/blocklayout/extents.c
+index 473faee9cdef..292aadfd4d46 100644
+--- a/fs/nfs/blocklayout/extents.c
++++ b/fs/nfs/blocklayout/extents.c
+@@ -493,3 +493,50 @@ bl_find_get_extent(struct pnfs_block_layout *bl, sector_t isect,
+ 	print_bl_extent(ret);
+ 	return ret;
+ }
++
++/* Helper function to set_to_rw that initialize a new extent */
++static void
++_prep_new_extent(struct pnfs_block_extent *new,
++		 struct pnfs_block_extent *orig,
++		 sector_t offset, sector_t length, int state)
++{
++	kref_init(&new->be_refcnt);
++	/* don't need to INIT_LIST_HEAD(&new->be_node) */
++	memcpy(&new->be_devid, &orig->be_devid, sizeof(struct nfs4_deviceid));
++	new->be_mdev = orig->be_mdev;
++	new->be_f_offset = offset;
++	new->be_length = length;
++	new->be_v_offset = orig->be_v_offset - orig->be_f_offset + offset;
++	new->be_state = state;
++	new->be_inval = orig->be_inval;
++}
++
++/* Tries to merge be with extent in front of it in list.
++ * Frees storage if not used.
++ */
++static struct pnfs_block_extent *
++_front_merge(struct pnfs_block_extent *be, struct list_head *head,
++	     struct pnfs_block_extent *storage)
++{
++	struct pnfs_block_extent *prev;
++
++	if (!storage)
++		goto no_merge;
++	if (&be->be_node == head || be->be_node.prev == head)
++		goto no_merge;
++	prev = list_entry(be->be_node.prev, struct pnfs_block_extent, be_node);
++	if ((prev->be_f_offset + prev->be_length != be->be_f_offset) ||
++	    !extents_consistent(prev, be))
++		goto no_merge;
++	_prep_new_extent(storage, prev, prev->be_f_offset,
++			 prev->be_length + be->be_length, prev->be_state);
++	list_replace(&prev->be_node, &storage->be_node);
++	bl_put_extent(prev);
++	list_del(&be->be_node);
++	bl_put_extent(be);
++	return storage;
++
++ no_merge:
++	kfree(storage);
++	return be;
++}

commit c1c2a4cd352269f1fb585b4a5c63abe24dd946c6
+Author: Fred Isaman 
+Date:   Sat Jul 30 20:52:49 2011 -0400
+
+    pnfsblock: add extent manipulation functions
+    
+    Adds working implementations of various support functions
+    to handle INVAL extents, needed by writes, such as
+    bl_mark_sectors_init and bl_is_sector_init.
+    
+    [pnfsblock: fix 64-bit compiler warnings for extent manipulation]
+    Signed-off-by: Fred Isaman 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Benny Halevy 
+    [Implement release_inval_marks]
+    Signed-off-by: Zhang Jingwang 
+    Signed-off-by: Jim Rees 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
+index 6cd7f4f3acdb..8c29a189f09b 100644
+--- a/fs/nfs/blocklayout/blocklayout.c
++++ b/fs/nfs/blocklayout/blocklayout.c
+@@ -78,10 +78,15 @@ release_extents(struct pnfs_block_layout *bl, struct pnfs_layout_range *range)
+ 	spin_unlock(&bl->bl_ext_lock);
+ }
+ 
+-/* STUB */
+ static void
+ release_inval_marks(struct pnfs_inval_markings *marks)
+ {
++	struct pnfs_inval_tracking *pos, *temp;
++
++	list_for_each_entry_safe(pos, temp, &marks->im_tree.mtt_stub, it_link) {
++		list_del(&pos->it_link);
++		kfree(pos);
++	}
+ 	return;
+ }
+ 
+diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklayout.h
+index 3e1b5fc152d7..fcf47b55b5ce 100644
+--- a/fs/nfs/blocklayout/blocklayout.h
++++ b/fs/nfs/blocklayout/blocklayout.h
+@@ -38,6 +38,9 @@
+ 
+ #include "../pnfs.h"
+ 
++#define PAGE_CACHE_SECTORS (PAGE_CACHE_SIZE >> SECTOR_SHIFT)
++#define PAGE_CACHE_SECTOR_SHIFT (PAGE_CACHE_SHIFT - SECTOR_SHIFT)
++
+ struct block_mount_id {
+ 	spinlock_t			bm_lock;    /* protects list */
+ 	struct list_head		bm_devlist; /* holds pnfs_block_dev */
+@@ -56,8 +59,23 @@ enum exstate4 {
+ 	PNFS_BLOCK_NONE_DATA		= 3  /* unmapped, it's a hole */
+ };
+ 
++#define MY_MAX_TAGS (15) /* tag bitnums used must be less than this */
++
++struct my_tree {
++	sector_t		mtt_step_size;	/* Internal sector alignment */
++	struct list_head	mtt_stub; /* Should be a radix tree */
++};
++
+ struct pnfs_inval_markings {
+-	/* STUB */
++	spinlock_t	im_lock;
++	struct my_tree	im_tree;	/* Sectors that need LAYOUTCOMMIT */
++	sector_t	im_block_size;	/* Server blocksize in sectors */
++};
++
++struct pnfs_inval_tracking {
++	struct list_head it_link;
++	int		 it_sector;
++	int		 it_tags;
+ };
+ 
+ /* sector_t fields are all in 512-byte sectors */
+@@ -76,7 +94,11 @@ struct pnfs_block_extent {
+ static inline void
+ BL_INIT_INVAL_MARKS(struct pnfs_inval_markings *marks, sector_t blocksize)
+ {
+-	/* STUB */
++	spin_lock_init(&marks->im_lock);
++	INIT_LIST_HEAD(&marks->im_tree.mtt_stub);
++	marks->im_block_size = blocksize;
++	marks->im_tree.mtt_step_size = min((sector_t)PAGE_CACHE_SECTORS,
++					   blocksize);
+ }
+ 
+ enum extentclass4 {
+@@ -156,8 +178,12 @@ void bl_free_block_dev(struct pnfs_block_dev *bdev);
+ struct pnfs_block_extent *
+ bl_find_get_extent(struct pnfs_block_layout *bl, sector_t isect,
+ 		struct pnfs_block_extent **cow_read);
++int bl_mark_sectors_init(struct pnfs_inval_markings *marks,
++			     sector_t offset, sector_t length,
++			     sector_t **pages);
+ void bl_put_extent(struct pnfs_block_extent *be);
+ struct pnfs_block_extent *bl_alloc_extent(void);
++int bl_is_sector_init(struct pnfs_inval_markings *marks, sector_t isect);
+ int bl_add_merge_extent(struct pnfs_block_layout *bl,
+ 			 struct pnfs_block_extent *new);
+ 
+diff --git a/fs/nfs/blocklayout/extents.c b/fs/nfs/blocklayout/extents.c
+index 8fa93e23cb24..473faee9cdef 100644
+--- a/fs/nfs/blocklayout/extents.c
++++ b/fs/nfs/blocklayout/extents.c
+@@ -33,6 +33,259 @@
+ #include "blocklayout.h"
+ #define NFSDBG_FACILITY         NFSDBG_PNFS_LD
+ 
++/* Bit numbers */
++#define EXTENT_INITIALIZED 0
++#define EXTENT_WRITTEN     1
++#define EXTENT_IN_COMMIT   2
++#define INTERNAL_EXISTS    MY_MAX_TAGS
++#define INTERNAL_MASK      ((1 << INTERNAL_EXISTS) - 1)
++
++/* Returns largest t<=s s.t. t%base==0 */
++static inline sector_t normalize(sector_t s, int base)
++{
++	sector_t tmp = s; /* Since do_div modifies its argument */
++	return s - do_div(tmp, base);
++}
++
++static inline sector_t normalize_up(sector_t s, int base)
++{
++	return normalize(s + base - 1, base);
++}
++
++/* Complete stub using list while determine API wanted */
++
++/* Returns tags, or negative */
++static int32_t _find_entry(struct my_tree *tree, u64 s)
++{
++	struct pnfs_inval_tracking *pos;
++
++	dprintk("%s(%llu) enter\n", __func__, s);
++	list_for_each_entry_reverse(pos, &tree->mtt_stub, it_link) {
++		if (pos->it_sector > s)
++			continue;
++		else if (pos->it_sector == s)
++			return pos->it_tags & INTERNAL_MASK;
++		else
++			break;
++	}
++	return -ENOENT;
++}
++
++static inline
++int _has_tag(struct my_tree *tree, u64 s, int32_t tag)
++{
++	int32_t tags;
++
++	dprintk("%s(%llu, %i) enter\n", __func__, s, tag);
++	s = normalize(s, tree->mtt_step_size);
++	tags = _find_entry(tree, s);
++	if ((tags < 0) || !(tags & (1 << tag)))
++		return 0;
++	else
++		return 1;
++}
++
++/* Creates entry with tag, or if entry already exists, unions tag to it.
++ * If storage is not NULL, newly created entry will use it.
++ * Returns number of entries added, or negative on error.
++ */
++static int _add_entry(struct my_tree *tree, u64 s, int32_t tag,
++		      struct pnfs_inval_tracking *storage)
++{
++	int found = 0;
++	struct pnfs_inval_tracking *pos;
++
++	dprintk("%s(%llu, %i, %p) enter\n", __func__, s, tag, storage);
++	list_for_each_entry_reverse(pos, &tree->mtt_stub, it_link) {
++		if (pos->it_sector > s)
++			continue;
++		else if (pos->it_sector == s) {
++			found = 1;
++			break;
++		} else
++			break;
++	}
++	if (found) {
++		pos->it_tags |= (1 << tag);
++		return 0;
++	} else {
++		struct pnfs_inval_tracking *new;
++		if (storage)
++			new = storage;
++		else {
++			new = kmalloc(sizeof(*new), GFP_NOFS);
++			if (!new)
++				return -ENOMEM;
++		}
++		new->it_sector = s;
++		new->it_tags = (1 << tag);
++		list_add(&new->it_link, &pos->it_link);
++		return 1;
++	}
++}
++
++/* XXXX Really want option to not create */
++/* Over range, unions tag with existing entries, else creates entry with tag */
++static int _set_range(struct my_tree *tree, int32_t tag, u64 s, u64 length)
++{
++	u64 i;
++
++	dprintk("%s(%i, %llu, %llu) enter\n", __func__, tag, s, length);
++	for (i = normalize(s, tree->mtt_step_size); i < s + length;
++	     i += tree->mtt_step_size)
++		if (_add_entry(tree, i, tag, NULL))
++			return -ENOMEM;
++	return 0;
++}
++
++/* Ensure that future operations on given range of tree will not malloc */
++static int _preload_range(struct my_tree *tree, u64 offset, u64 length)
++{
++	u64 start, end, s;
++	int count, i, used = 0, status = -ENOMEM;
++	struct pnfs_inval_tracking **storage;
++
++	dprintk("%s(%llu, %llu) enter\n", __func__, offset, length);
++	start = normalize(offset, tree->mtt_step_size);
++	end = normalize_up(offset + length, tree->mtt_step_size);
++	count = (int)(end - start) / (int)tree->mtt_step_size;
++
++	/* Pre-malloc what memory we might need */
++	storage = kmalloc(sizeof(*storage) * count, GFP_NOFS);
++	if (!storage)
++		return -ENOMEM;
++	for (i = 0; i < count; i++) {
++		storage[i] = kmalloc(sizeof(struct pnfs_inval_tracking),
++				     GFP_NOFS);
++		if (!storage[i])
++			goto out_cleanup;
++	}
++
++	/* Now need lock - HOW??? */
++
++	for (s = start; s < end; s += tree->mtt_step_size)
++		used += _add_entry(tree, s, INTERNAL_EXISTS, storage[used]);
++
++	/* Unlock - HOW??? */
++	status = 0;
++
++ out_cleanup:
++	for (i = used; i < count; i++) {
++		if (!storage[i])
++			break;
++		kfree(storage[i]);
++	}
++	kfree(storage);
++	return status;
++}
++
++static void set_needs_init(sector_t *array, sector_t offset)
++{
++	sector_t *p = array;
++
++	dprintk("%s enter\n", __func__);
++	if (!p)
++		return;
++	while (*p < offset)
++		p++;
++	if (*p == offset)
++		return;
++	else if (*p == ~0) {
++		*p++ = offset;
++		*p = ~0;
++		return;
++	} else {
++		sector_t *save = p;
++		dprintk("%s Adding %llu\n", __func__, (u64)offset);
++		while (*p != ~0)
++			p++;
++		p++;
++		memmove(save + 1, save, (char *)p - (char *)save);
++		*save = offset;
++		return;
++	}
++}
++
++/* We are relying on page lock to serialize this */
++int bl_is_sector_init(struct pnfs_inval_markings *marks, sector_t isect)
++{
++	int rv;
++
++	spin_lock(&marks->im_lock);
++	rv = _has_tag(&marks->im_tree, isect, EXTENT_INITIALIZED);
++	spin_unlock(&marks->im_lock);
++	return rv;
++}
++
++/* Marks sectors in [offest, offset_length) as having been initialized.
++ * All lengths are step-aligned, where step is min(pagesize, blocksize).
++ * Notes where partial block is initialized, and helps prepare it for
++ * complete initialization later.
++ */
++/* Currently assumes offset is page-aligned */
++int bl_mark_sectors_init(struct pnfs_inval_markings *marks,
++			     sector_t offset, sector_t length,
++			     sector_t **pages)
++{
++	sector_t s, start, end;
++	sector_t *array = NULL; /* Pages to mark */
++
++	dprintk("%s(offset=%llu,len=%llu) enter\n",
++		__func__, (u64)offset, (u64)length);
++	s = max((sector_t) 3,
++		2 * (marks->im_block_size / (PAGE_CACHE_SECTORS)));
++	dprintk("%s set max=%llu\n", __func__, (u64)s);
++	if (pages) {
++		array = kmalloc(s * sizeof(sector_t), GFP_NOFS);
++		if (!array)
++			goto outerr;
++		array[0] = ~0;
++	}
++
++	start = normalize(offset, marks->im_block_size);
++	end = normalize_up(offset + length, marks->im_block_size);
++	if (_preload_range(&marks->im_tree, start, end - start))
++		goto outerr;
++
++	spin_lock(&marks->im_lock);
++
++	for (s = normalize_up(start, PAGE_CACHE_SECTORS);
++	     s < offset; s += PAGE_CACHE_SECTORS) {
++		dprintk("%s pre-area pages\n", __func__);
++		/* Portion of used block is not initialized */
++		if (!_has_tag(&marks->im_tree, s, EXTENT_INITIALIZED))
++			set_needs_init(array, s);
++	}
++	if (_set_range(&marks->im_tree, EXTENT_INITIALIZED, offset, length))
++		goto out_unlock;
++	for (s = normalize_up(offset + length, PAGE_CACHE_SECTORS);
++	     s < end; s += PAGE_CACHE_SECTORS) {
++		dprintk("%s post-area pages\n", __func__);
++		if (!_has_tag(&marks->im_tree, s, EXTENT_INITIALIZED))
++			set_needs_init(array, s);
++	}
++
++	spin_unlock(&marks->im_lock);
++
++	if (pages) {
++		if (array[0] == ~0) {
++			kfree(array);
++			*pages = NULL;
++		} else
++			*pages = array;
++	}
++	return 0;
++
++ out_unlock:
++	spin_unlock(&marks->im_lock);
++ outerr:
++	if (pages) {
++		kfree(array);
++		*pages = NULL;
++	}
++	return -ENOMEM;
++}
++
+ static void print_bl_extent(struct pnfs_block_extent *be)
+ {
+ 	dprintk("PRINT EXTENT extent %p\n", be);

commit 6d742ba538f98164f3c5e05cdcadb4ec6ddf504f
+Author: Fred Isaman 
+Date:   Sat Jul 30 20:52:48 2011 -0400
+
+    pnfsblock: bl_find_get_extent
+    
+    Implement bl_find_get_extent(), one of the core extent manipulation
+    routines.
+    
+    [pnfsblock: Lookup list entry of layouts and tags in reverse order]
+    Signed-off-by: Zhang Jingwang 
+    Signed-off-by: Fred Isaman 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Jim Rees 
+    
+    pnfsblock: fix print format warnings for sector_t and size_t
+    
+    gcc spews warnings about these on x86_64, e.g.:
+    fs/nfs/blocklayout/blocklayout.c:74: warning: format ‘%Lu’ expects type ‘long long unsigned int’, but argument 2 has type ‘sector_t’
+    fs/nfs/blocklayout/blocklayout.c:388: warning: format ‘%d’ expects type ‘int’, but argument 5 has type ‘size_t’
+    
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Jim Rees 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklayout.h
+index d645880f61a0..3e1b5fc152d7 100644
+--- a/fs/nfs/blocklayout/blocklayout.h
++++ b/fs/nfs/blocklayout/blocklayout.h
+@@ -153,6 +153,9 @@ int nfs4_blk_process_layoutget(struct pnfs_layout_hdr *lo,
+ void bl_free_block_dev(struct pnfs_block_dev *bdev);
+ 
+ /* extents.c */
++struct pnfs_block_extent *
++bl_find_get_extent(struct pnfs_block_layout *bl, sector_t isect,
++		struct pnfs_block_extent **cow_read);
+ void bl_put_extent(struct pnfs_block_extent *be);
+ struct pnfs_block_extent *bl_alloc_extent(void);
+ int bl_add_merge_extent(struct pnfs_block_layout *bl,
+diff --git a/fs/nfs/blocklayout/extents.c b/fs/nfs/blocklayout/extents.c
+index ee4891f32492..8fa93e23cb24 100644
+--- a/fs/nfs/blocklayout/extents.c
++++ b/fs/nfs/blocklayout/extents.c
+@@ -193,3 +193,50 @@ bl_add_merge_extent(struct pnfs_block_layout *bl,
+ 	bl_put_extent(new);
+ 	return -EIO;
+ }
++
++/* Returns extent, or NULL.  If a second READ extent exists, it is returned
++ * in cow_read, if given.
++ *
++ * The extents are kept in two seperate ordered lists, one for READ and NONE,
++ * one for READWRITE and INVALID.  Within each list, we assume:
++ * 1. Extents are ordered by file offset.
++ * 2. For any given isect, there is at most one extents that matches.
++ */
++struct pnfs_block_extent *
++bl_find_get_extent(struct pnfs_block_layout *bl, sector_t isect,
++	    struct pnfs_block_extent **cow_read)
++{
++	struct pnfs_block_extent *be, *cow, *ret;
++	int i;
++
++	dprintk("%s enter with isect %llu\n", __func__, (u64)isect);
++	cow = ret = NULL;
++	spin_lock(&bl->bl_ext_lock);
++	for (i = 0; i < EXTENT_LISTS; i++) {
++		list_for_each_entry_reverse(be, &bl->bl_extents[i], be_node) {
++			if (isect >= be->be_f_offset + be->be_length)
++				break;
++			if (isect >= be->be_f_offset) {
++				/* We have found an extent */
++				dprintk("%s Get %p (%i)\n", __func__, be,
++					atomic_read(&be->be_refcnt.refcount));
++				kref_get(&be->be_refcnt);
++				if (!ret)
++					ret = be;
++				else if (be->be_state != PNFS_BLOCK_READ_DATA)
++					bl_put_extent(be);
++				else
++					cow = be;
++				break;
++			}
++		}
++		if (ret &&
++		    (!cow_read || ret->be_state != PNFS_BLOCK_INVALID_DATA))
++			break;
++	}
++	spin_unlock(&bl->bl_ext_lock);
++	if (cow_read)
++		*cow_read = cow;
++	print_bl_extent(ret);
++	return ret;
++}

commit e9437ccef92a28ba4c9009404bb8c9b5672dc54a
+Author: Fred Isaman 
+Date:   Sat Jul 30 20:52:47 2011 -0400
+
+    pnfsblock: xdr decode pnfs_block_layout4
+    
+    XDR decodes the block layout payload sent in LAYOUTGET result, storing
+    the result in an extent list.
+    
+    [pnfsblock: get rid of deprecated xdr macros]
+    Signed-off-by: Jim Rees 
+    Signed-off-by: Fred Isaman 
+    [pnfsblock: fix bug getting pnfs_layout_type in translate_devid().]
+    Signed-off-by: Tao Guo 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Jim Rees 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/blocklayout/blocklayoutdev.c b/fs/nfs/blocklayout/blocklayoutdev.c
+index b23fe601d1c9..a83b393fb01c 100644
+--- a/fs/nfs/blocklayout/blocklayoutdev.c
++++ b/fs/nfs/blocklayout/blocklayoutdev.c
+@@ -40,6 +40,19 @@
+ 
+ #define NFSDBG_FACILITY         NFSDBG_PNFS_LD
+ 
++static int decode_sector_number(__be32 **rp, sector_t *sp)
++{
++	uint64_t s;
++
++	*rp = xdr_decode_hyper(*rp, &s);
++	if (s & 0x1ff) {
++		printk(KERN_WARNING "%s: sector not aligned\n", __func__);
++		return -1;
++	}
++	*sp = s >> SECTOR_SHIFT;
++	return 0;
++}
++
+ /* Open a block_device by device number. */
+ struct block_device *nfs4_blkdev_get(dev_t dev)
+ {
+@@ -197,10 +210,201 @@ nfs4_blk_decode_device(struct nfs_server *server,
+ 	return rv;
+ }
+ 
++/* Map deviceid returned by the server to constructed block_device */
++static struct block_device *translate_devid(struct pnfs_layout_hdr *lo,
++					    struct nfs4_deviceid *id)
++{
++	struct block_device *rv = NULL;
++	struct block_mount_id *mid;
++	struct pnfs_block_dev *dev;
++
++	dprintk("%s enter, lo=%p, id=%p\n", __func__, lo, id);
++	mid = BLK_ID(lo);
++	spin_lock(&mid->bm_lock);
++	list_for_each_entry(dev, &mid->bm_devlist, bm_node) {
++		if (memcmp(id->data, dev->bm_mdevid.data,
++			   NFS4_DEVICEID4_SIZE) == 0) {
++			rv = dev->bm_mdev;
++			goto out;
++		}
++	}
++ out:
++	spin_unlock(&mid->bm_lock);
++	dprintk("%s returning %p\n", __func__, rv);
++	return rv;
++}
++
++/* Tracks info needed to ensure extents in layout obey constraints of spec */
++struct layout_verification {
++	u32 mode;	/* R or RW */
++	u64 start;	/* Expected start of next non-COW extent */
++	u64 inval;	/* Start of INVAL coverage */
++	u64 cowread;	/* End of COW read coverage */
++};
++
++/* Verify the extent meets the layout requirements of the pnfs-block draft,
++ * section 2.3.1.
++ */
++static int verify_extent(struct pnfs_block_extent *be,
++			 struct layout_verification *lv)
++{
++	if (lv->mode == IOMODE_READ) {
++		if (be->be_state == PNFS_BLOCK_READWRITE_DATA ||
++		    be->be_state == PNFS_BLOCK_INVALID_DATA)
++			return -EIO;
++		if (be->be_f_offset != lv->start)
++			return -EIO;
++		lv->start += be->be_length;
++		return 0;
++	}
++	/* lv->mode == IOMODE_RW */
++	if (be->be_state == PNFS_BLOCK_READWRITE_DATA) {
++		if (be->be_f_offset != lv->start)
++			return -EIO;
++		if (lv->cowread > lv->start)
++			return -EIO;
++		lv->start += be->be_length;
++		lv->inval = lv->start;
++		return 0;
++	} else if (be->be_state == PNFS_BLOCK_INVALID_DATA) {
++		if (be->be_f_offset != lv->start)
++			return -EIO;
++		lv->start += be->be_length;
++		return 0;
++	} else if (be->be_state == PNFS_BLOCK_READ_DATA) {
++		if (be->be_f_offset > lv->start)
++			return -EIO;
++		if (be->be_f_offset < lv->inval)
++			return -EIO;
++		if (be->be_f_offset < lv->cowread)
++			return -EIO;
++		/* It looks like you might want to min this with lv->start,
++		 * but you really don't.
++		 */
++		lv->inval = lv->inval + be->be_length;
++		lv->cowread = be->be_f_offset + be->be_length;
++		return 0;
++	} else
++		return -EIO;
++}
++
++/* XDR decode pnfs_block_layout4 structure */
+ int
+ nfs4_blk_process_layoutget(struct pnfs_layout_hdr *lo,
+ 			   struct nfs4_layoutget_res *lgr, gfp_t gfp_flags)
+ {
+-	/* STUB */
+-	return -EIO;
++	struct pnfs_block_layout *bl = BLK_LO2EXT(lo);
++	int i, status = -EIO;
++	uint32_t count;
++	struct pnfs_block_extent *be = NULL, *save;
++	struct xdr_stream stream;
++	struct xdr_buf buf;
++	struct page *scratch;
++	__be32 *p;
++	struct layout_verification lv = {
++		.mode = lgr->range.iomode,
++		.start = lgr->range.offset >> SECTOR_SHIFT,
++		.inval = lgr->range.offset >> SECTOR_SHIFT,
++		.cowread = lgr->range.offset >> SECTOR_SHIFT,
++	};
++	LIST_HEAD(extents);
++
++	dprintk("---> %s\n", __func__);
++
++	scratch = alloc_page(gfp_flags);
++	if (!scratch)
++		return -ENOMEM;
++
++	xdr_init_decode_pages(&stream, &buf, lgr->layoutp->pages, lgr->layoutp->len);
++	xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE);
++
++	p = xdr_inline_decode(&stream, 4);
++	if (unlikely(!p))
++		goto out_err;
++
++	count = be32_to_cpup(p++);
++
++	dprintk("%s enter, number of extents %i\n", __func__, count);
++	p = xdr_inline_decode(&stream, (28 + NFS4_DEVICEID4_SIZE) * count);
++	if (unlikely(!p))
++		goto out_err;
++
++	/* Decode individual extents, putting them in temporary
++	 * staging area until whole layout is decoded to make error
++	 * recovery easier.
++	 */
++	for (i = 0; i < count; i++) {
++		be = bl_alloc_extent();
++		if (!be) {
++			status = -ENOMEM;
++			goto out_err;
++		}
++		memcpy(&be->be_devid, p, NFS4_DEVICEID4_SIZE);
++		p += XDR_QUADLEN(NFS4_DEVICEID4_SIZE);
++		be->be_mdev = translate_devid(lo, &be->be_devid);
++		if (!be->be_mdev)
++			goto out_err;
++
++		/* The next three values are read in as bytes,
++		 * but stored as 512-byte sector lengths
++		 */
++		if (decode_sector_number(&p, &be->be_f_offset) < 0)
++			goto out_err;
++		if (decode_sector_number(&p, &be->be_length) < 0)
++			goto out_err;
++		if (decode_sector_number(&p, &be->be_v_offset) < 0)
++			goto out_err;
++		be->be_state = be32_to_cpup(p++);
++		if (be->be_state == PNFS_BLOCK_INVALID_DATA)
++			be->be_inval = &bl->bl_inval;
++		if (verify_extent(be, &lv)) {
++			dprintk("%s verify failed\n", __func__);
++			goto out_err;
++		}
++		list_add_tail(&be->be_node, &extents);
++	}
++	if (lgr->range.offset + lgr->range.length !=
++			lv.start << SECTOR_SHIFT) {
++		dprintk("%s Final length mismatch\n", __func__);
++		be = NULL;
++		goto out_err;
++	}
++	if (lv.start < lv.cowread) {
++		dprintk("%s Final uncovered COW extent\n", __func__);
++		be = NULL;
++		goto out_err;
++	}
++	/* Extents decoded properly, now try to merge them in to
++	 * existing layout extents.
++	 */
++	spin_lock(&bl->bl_ext_lock);
++	list_for_each_entry_safe(be, save, &extents, be_node) {
++		list_del(&be->be_node);
++		status = bl_add_merge_extent(bl, be);
++		if (status) {
++			spin_unlock(&bl->bl_ext_lock);
++			/* This is a fairly catastrophic error, as the
++			 * entire layout extent lists are now corrupted.
++			 * We should have some way to distinguish this.
++			 */
++			be = NULL;
++			goto out_err;
++		}
++	}
++	spin_unlock(&bl->bl_ext_lock);
++	status = 0;
++ out:
++	__free_page(scratch);
++	dprintk("%s returns %i\n", __func__, status);
++	return status;
++
++ out_err:
++	bl_put_extent(be);
++	while (!list_empty(&extents)) {
++		be = list_first_entry(&extents, struct pnfs_block_extent,
++				      be_node);
++		list_del(&be->be_node);
++		bl_put_extent(be);
++	}
++	goto out;
+ }

commit 2f9fd182607e7b3bdca35f6ed7f2fae539f7c46b
+Author: Fred Isaman 
+Date:   Sat Jul 30 20:52:46 2011 -0400
+
+    pnfsblock: call and parse getdevicelist
+    
+    Call GETDEVICELIST during mount, then call and parse GETDEVICEINFO
+    for each device returned.
+    
+    [pnfsblock: get rid of deprecated xdr macros]
+    Signed-off-by: Jim Rees 
+    [pnfsblock: fix pnfs_deviceid references]
+    Signed-off-by: Fred Isaman 
+    [pnfsblock: fix print format warnings for sector_t and size_t]
+    [pnfs-block: #include ]
+    [pnfsblock: no PNFS_NFS_SERVER]
+    Signed-off-by: Benny Halevy 
+    [pnfsblock: fix bug determining size of striped volume]
+    [pnfsblock: fix oops when using multiple devices]
+    Signed-off-by: Fred Isaman 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Benny Halevy 
+    [pnfsblock: get rid of vmap and deviceid->area structure]
+    Signed-off-by: Peng Tao 
+    Signed-off-by: Jim Rees 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
+index e7bc7a57b3bb..6cd7f4f3acdb 100644
+--- a/fs/nfs/blocklayout/blocklayout.c
++++ b/fs/nfs/blocklayout/blocklayout.c
+@@ -157,17 +157,153 @@ bl_cleanup_layoutcommit(struct nfs4_layoutcommit_data *lcdata)
+ {
+ }
+ 
++static void free_blk_mountid(struct block_mount_id *mid)
++{
++	if (mid) {
++		struct pnfs_block_dev *dev;
++		spin_lock(&mid->bm_lock);
++		while (!list_empty(&mid->bm_devlist)) {
++			dev = list_first_entry(&mid->bm_devlist,
++					       struct pnfs_block_dev,
++					       bm_node);
++			list_del(&dev->bm_node);
++			bl_free_block_dev(dev);
++		}
++		spin_unlock(&mid->bm_lock);
++		kfree(mid);
++	}
++}
++
++/* This is mostly copied from the filelayout's get_device_info function.
++ * It seems much of this should be at the generic pnfs level.
++ */
++static struct pnfs_block_dev *
++nfs4_blk_get_deviceinfo(struct nfs_server *server, const struct nfs_fh *fh,
++			struct nfs4_deviceid *d_id)
++{
++	struct pnfs_device *dev;
++	struct pnfs_block_dev *rv = NULL;
++	u32 max_resp_sz;
++	int max_pages;
++	struct page **pages = NULL;
++	int i, rc;
++
++	/*
++	 * Use the session max response size as the basis for setting
++	 * GETDEVICEINFO's maxcount
++	 */
++	max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
++	max_pages = max_resp_sz >> PAGE_SHIFT;
++	dprintk("%s max_resp_sz %u max_pages %d\n",
++		__func__, max_resp_sz, max_pages);
++
++	dev = kmalloc(sizeof(*dev), GFP_NOFS);
++	if (!dev) {
++		dprintk("%s kmalloc failed\n", __func__);
++		return NULL;
++	}
++
++	pages = kzalloc(max_pages * sizeof(struct page *), GFP_NOFS);
++	if (pages == NULL) {
++		kfree(dev);
++		return NULL;
++	}
++	for (i = 0; i < max_pages; i++) {
++		pages[i] = alloc_page(GFP_NOFS);
++		if (!pages[i])
++			goto out_free;
++	}
++
++	memcpy(&dev->dev_id, d_id, sizeof(*d_id));
++	dev->layout_type = LAYOUT_BLOCK_VOLUME;
++	dev->pages = pages;
++	dev->pgbase = 0;
++	dev->pglen = PAGE_SIZE * max_pages;
++	dev->mincount = 0;
++
++	dprintk("%s: dev_id: %s\n", __func__, dev->dev_id.data);
++	rc = nfs4_proc_getdeviceinfo(server, dev);
++	dprintk("%s getdevice info returns %d\n", __func__, rc);
++	if (rc)
++		goto out_free;
++
++	rv = nfs4_blk_decode_device(server, dev);
++ out_free:
++	for (i = 0; i < max_pages; i++)
++		__free_page(pages[i]);
++	kfree(pages);
++	kfree(dev);
++	return rv;
++}
++
+ static int
+ bl_set_layoutdriver(struct nfs_server *server, const struct nfs_fh *fh)
+ {
++	struct block_mount_id *b_mt_id = NULL;
++	struct pnfs_devicelist *dlist = NULL;
++	struct pnfs_block_dev *bdev;
++	LIST_HEAD(block_disklist);
++	int status = 0, i;
++
+ 	dprintk("%s enter\n", __func__);
+-	return 0;
++
++	if (server->pnfs_blksize == 0) {
++		dprintk("%s Server did not return blksize\n", __func__);
++		return -EINVAL;
++	}
++	b_mt_id = kzalloc(sizeof(struct block_mount_id), GFP_NOFS);
++	if (!b_mt_id) {
++		status = -ENOMEM;
++		goto out_error;
++	}
++	/* Initialize nfs4 block layout mount id */
++	spin_lock_init(&b_mt_id->bm_lock);
++	INIT_LIST_HEAD(&b_mt_id->bm_devlist);
++
++	dlist = kmalloc(sizeof(struct pnfs_devicelist), GFP_NOFS);
++	if (!dlist) {
++		status = -ENOMEM;
++		goto out_error;
++	}
++	dlist->eof = 0;
++	while (!dlist->eof) {
++		status = nfs4_proc_getdevicelist(server, fh, dlist);
++		if (status)
++			goto out_error;
++		dprintk("%s GETDEVICELIST numdevs=%i, eof=%i\n",
++			__func__, dlist->num_devs, dlist->eof);
++		for (i = 0; i < dlist->num_devs; i++) {
++			bdev = nfs4_blk_get_deviceinfo(server, fh,
++						       &dlist->dev_id[i]);
++			if (!bdev) {
++				status = -ENODEV;
++				goto out_error;
++			}
++			spin_lock(&b_mt_id->bm_lock);
++			list_add(&bdev->bm_node, &b_mt_id->bm_devlist);
++			spin_unlock(&b_mt_id->bm_lock);
++		}
++	}
++	dprintk("%s SUCCESS\n", __func__);
++	server->pnfs_ld_data = b_mt_id;
++
++ out_return:
++	kfree(dlist);
++	return status;
++
++ out_error:
++	free_blk_mountid(b_mt_id);
++	goto out_return;
+ }
+ 
+ static int
+ bl_clear_layoutdriver(struct nfs_server *server)
+ {
++	struct block_mount_id *b_mt_id = server->pnfs_ld_data;
++
+ 	dprintk("%s enter\n", __func__);
++	free_blk_mountid(b_mt_id);
++	dprintk("%s RETURNS\n", __func__);
+ 	return 0;
+ }
+ 
+diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklayout.h
+index 581d8f47a723..d645880f61a0 100644
+--- a/fs/nfs/blocklayout/blocklayout.h
++++ b/fs/nfs/blocklayout/blocklayout.h
+@@ -38,6 +38,11 @@
+ 
+ #include "../pnfs.h"
+ 
++struct block_mount_id {
++	spinlock_t			bm_lock;    /* protects list */
++	struct list_head		bm_devlist; /* holds pnfs_block_dev */
++};
++
+ struct pnfs_block_dev {
+ 	struct list_head		bm_node;
+ 	struct nfs4_deviceid		bm_mdevid;    /* associated devid */
+@@ -99,7 +104,10 @@ struct pnfs_block_layout {
+ 	sector_t		bl_blocksize;  /* Server blocksize in sectors */
+ };
+ 
+-static inline struct pnfs_block_layout *BLK_LO2EXT(struct pnfs_layout_hdr *lo)
++#define BLK_ID(lo) ((struct block_mount_id *)(NFS_SERVER(lo->plh_inode)->pnfs_ld_data))
++
++static inline struct pnfs_block_layout *
++BLK_LO2EXT(struct pnfs_layout_hdr *lo)
+ {
+ 	return container_of(lo, struct pnfs_block_layout, bl_layout);
+ }
+@@ -137,8 +145,7 @@ void bl_pipe_destroy_msg(struct rpc_pipe_msg *);
+ struct block_device *nfs4_blkdev_get(dev_t dev);
+ int nfs4_blkdev_put(struct block_device *bdev);
+ struct pnfs_block_dev *nfs4_blk_decode_device(struct nfs_server *server,
+-						struct pnfs_device *dev,
+-						struct list_head *sdlist);
++						struct pnfs_device *dev);
+ int nfs4_blk_process_layoutget(struct pnfs_layout_hdr *lo,
+ 				struct nfs4_layoutget_res *lgr, gfp_t gfp_flags);
+ 
+diff --git a/fs/nfs/blocklayout/blocklayoutdev.c b/fs/nfs/blocklayout/blocklayoutdev.c
+index 64da33a40eaf..b23fe601d1c9 100644
+--- a/fs/nfs/blocklayout/blocklayoutdev.c
++++ b/fs/nfs/blocklayout/blocklayoutdev.c
+@@ -116,8 +116,7 @@ void bl_pipe_destroy_msg(struct rpc_pipe_msg *msg)
+  */
+ struct pnfs_block_dev *
+ nfs4_blk_decode_device(struct nfs_server *server,
+-		       struct pnfs_device *dev,
+-		       struct list_head *sdlist)
++		       struct pnfs_device *dev)
+ {
+ 	struct pnfs_block_dev *rv = NULL;
+ 	struct block_device *bd = NULL;
+@@ -129,6 +128,7 @@ nfs4_blk_decode_device(struct nfs_server *server,
+ 	uint8_t *dataptr;
+ 	DECLARE_WAITQUEUE(wq, current);
+ 	struct bl_dev_msg *reply = &bl_mount_reply;
++	int offset, len, i;
+ 
+ 	dprintk("%s CREATING PIPEFS MESSAGE\n", __func__);
+ 	dprintk("%s: deviceid: %s, mincount: %d\n", __func__, dev->dev_id.data,
+@@ -143,7 +143,14 @@ nfs4_blk_decode_device(struct nfs_server *server,
+ 
+ 	memcpy(msg.data, &bl_msg, sizeof(bl_msg));
+ 	dataptr = (uint8_t *) msg.data;
+-	memcpy(&dataptr[sizeof(bl_msg)], dev->area, dev->mincount);
++	len = dev->mincount;
++	offset = sizeof(bl_msg);
++	for (i = 0; len > 0; i++) {
++		memcpy(&dataptr[offset], page_address(dev->pages[i]),
++				len < PAGE_CACHE_SIZE ? len : PAGE_CACHE_SIZE);
++		len -= PAGE_CACHE_SIZE;
++		offset += PAGE_CACHE_SIZE;
++	}
+ 	msg.len = sizeof(bl_msg) + dev->mincount;
+ 
+ 	dprintk("%s CALLING USERSPACE DAEMON\n", __func__);
+diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
+index 606fbde2e757..e0b5d80a43f6 100644
+--- a/fs/nfs/pnfs.h
++++ b/fs/nfs/pnfs.h
+@@ -140,7 +140,6 @@ struct pnfs_device {
+ 	unsigned int  layout_type;
+ 	unsigned int  mincount;
+ 	struct page **pages;
+-	void          *area;
+ 	unsigned int  pgbase;
+ 	unsigned int  pglen;
+ };
+diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
+index b2ea8b82d2cb..cc03fc1dfb72 100644
+--- a/include/linux/nfs_fs_sb.h
++++ b/include/linux/nfs_fs_sb.h
+@@ -146,6 +146,7 @@ struct nfs_server {
+ 	struct pnfs_layoutdriver_type  *pnfs_curr_ld; /* Active layout driver */
+ 	struct rpc_wait_queue	roc_rpcwaitq;
+ 	u32			pnfs_blksize;	/* layout_blksize attr */
++	void			*pnfs_ld_data;	/* per mount point data */
+ 
+ 	/* the following fields are protected by nfs_client->cl_lock */
+ 	struct rb_root		state_owners;

commit 03341d2cc91c700fc38883e572043a6a8f17dd5c
+Author: Fred Isaman 
+Date:   Sat Jul 30 20:52:45 2011 -0400
+
+    pnfsblock: merge extents
+    
+    Replace a stub, so that extents underlying the layouts are properly
+    added, merged, or ignored as necessary.
+    
+    Signed-off-by: Fred Isaman 
+    [pnfsblock: delete the new node before put it]
+    Signed-off-by: Mingyang Guo 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Peng Tao 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Jim Rees 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklayout.h
+index 3e05b08d5347..581d8f47a723 100644
+--- a/fs/nfs/blocklayout/blocklayout.h
++++ b/fs/nfs/blocklayout/blocklayout.h
+@@ -80,6 +80,14 @@ enum extentclass4 {
+ 	EXTENT_LISTS    = 2,
+ };
+ 
++static inline int bl_choose_list(enum exstate4 state)
++{
++	if (state == PNFS_BLOCK_READ_DATA || state == PNFS_BLOCK_NONE_DATA)
++		return RO_EXTENT;
++	else
++		return RW_EXTENT;
++}
++
+ struct pnfs_block_layout {
+ 	struct pnfs_layout_hdr bl_layout;
+ 	struct pnfs_inval_markings bl_inval; /* tracks INVAL->RW transition */
+@@ -137,5 +145,10 @@ int nfs4_blk_process_layoutget(struct pnfs_layout_hdr *lo,
+ /* blocklayoutdm.c */
+ void bl_free_block_dev(struct pnfs_block_dev *bdev);
+ 
++/* extents.c */
+ void bl_put_extent(struct pnfs_block_extent *be);
++struct pnfs_block_extent *bl_alloc_extent(void);
++int bl_add_merge_extent(struct pnfs_block_layout *bl,
++			 struct pnfs_block_extent *new);
++
+ #endif /* FS_NFS_NFS4BLOCKLAYOUT_H */
+diff --git a/fs/nfs/blocklayout/extents.c b/fs/nfs/blocklayout/extents.c
+index d0ca7604d33e..ee4891f32492 100644
+--- a/fs/nfs/blocklayout/extents.c
++++ b/fs/nfs/blocklayout/extents.c
+@@ -87,3 +87,109 @@ static void print_elist(struct list_head *list)
+ 	}
+ 	dprintk("****************\n");
+ }
++
++static inline int
++extents_consistent(struct pnfs_block_extent *old, struct pnfs_block_extent *new)
++{
++	/* Note this assumes new->be_f_offset >= old->be_f_offset */
++	return (new->be_state == old->be_state) &&
++		((new->be_state == PNFS_BLOCK_NONE_DATA) ||
++		 ((new->be_v_offset - old->be_v_offset ==
++		   new->be_f_offset - old->be_f_offset) &&
++		  new->be_mdev == old->be_mdev));
++}
++
++/* Adds new to appropriate list in bl, modifying new and removing existing
++ * extents as appropriate to deal with overlaps.
++ *
++ * See bl_find_get_extent for list constraints.
++ *
++ * Refcount on new is already set.  If end up not using it, or error out,
++ * need to put the reference.
++ *
++ * bl->bl_ext_lock is held by caller.
++ */
++int
++bl_add_merge_extent(struct pnfs_block_layout *bl,
++		     struct pnfs_block_extent *new)
++{
++	struct pnfs_block_extent *be, *tmp;
++	sector_t end = new->be_f_offset + new->be_length;
++	struct list_head *list;
++
++	dprintk("%s enter with be=%p\n", __func__, new);
++	print_bl_extent(new);
++	list = &bl->bl_extents[bl_choose_list(new->be_state)];
++	print_elist(list);
++
++	/* Scan for proper place to insert, extending new to the left
++	 * as much as possible.
++	 */
++	list_for_each_entry_safe(be, tmp, list, be_node) {
++		if (new->be_f_offset < be->be_f_offset)
++			break;
++		if (end <= be->be_f_offset + be->be_length) {
++			/* new is a subset of existing be*/
++			if (extents_consistent(be, new)) {
++				dprintk("%s: new is subset, ignoring\n",
++					__func__);
++				bl_put_extent(new);
++				return 0;
++			} else
++				goto out_err;
++		} else if (new->be_f_offset <=
++				be->be_f_offset + be->be_length) {
++			/* new overlaps or abuts existing be */
++			if (extents_consistent(be, new)) {
++				/* extend new to fully replace be */
++				new->be_length += new->be_f_offset -
++						  be->be_f_offset;
++				new->be_f_offset = be->be_f_offset;
++				new->be_v_offset = be->be_v_offset;
++				dprintk("%s: removing %p\n", __func__, be);
++				list_del(&be->be_node);
++				bl_put_extent(be);
++			} else if (new->be_f_offset !=
++				   be->be_f_offset + be->be_length)
++				goto out_err;
++		}
++	}
++	/* Note that if we never hit the above break, be will not point to a
++	 * valid extent.  However, in that case &be->be_node==list.
++	 */
++	list_add_tail(&new->be_node, &be->be_node);
++	dprintk("%s: inserting new\n", __func__);
++	print_elist(list);
++	/* Scan forward for overlaps.  If we find any, extend new and
++	 * remove the overlapped extent.
++	 */
++	be = list_prepare_entry(new, list, be_node);
++	list_for_each_entry_safe_continue(be, tmp, list, be_node) {
++		if (end < be->be_f_offset)
++			break;
++		/* new overlaps or abuts existing be */
++		if (extents_consistent(be, new)) {
++			if (end < be->be_f_offset + be->be_length) {
++				/* extend new to fully cover be */
++				end = be->be_f_offset + be->be_length;
++				new->be_length = end - new->be_f_offset;
++			}
++			dprintk("%s: removing %p\n", __func__, be);
++			list_del(&be->be_node);
++			bl_put_extent(be);
++		} else if (end != be->be_f_offset) {
++			list_del(&new->be_node);
++			goto out_err;
++		}
++	}
++	dprintk("%s: after merging\n", __func__);
++	print_elist(list);
++	/* FIXME - The per-list consistency checks have all been done,
++	 * should now check cross-list consistency.
++	 */
++	return 0;
++
++ out_err:
++	bl_put_extent(new);
++	return -EIO;
++}

commit a60d2ebd93d3c5db5b6913c4844b8e6bd3b5538e
+Author: Fred Isaman 
+Date:   Sat Jul 30 20:52:44 2011 -0400
+
+    pnfsblock: lseg alloc and free
+    
+    Signed-off-by: Fred Isaman 
+    [pnfsblock: fix bug getting pnfs_layout_type in translate_devid().]
+    Signed-off-by: Tao Guo 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Zhang Jingwang 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Jim Rees 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
+index c83878441047..e7bc7a57b3bb 100644
+--- a/fs/nfs/blocklayout/blocklayout.c
++++ b/fs/nfs/blocklayout/blocklayout.c
+@@ -115,16 +115,35 @@ static struct pnfs_layout_hdr *bl_alloc_layout_hdr(struct inode *inode,
+ 	return &bl->bl_layout;
+ }
+ 
+-static void
+-bl_free_lseg(struct pnfs_layout_segment *lseg)
++static void bl_free_lseg(struct pnfs_layout_segment *lseg)
+ {
++	dprintk("%s enter\n", __func__);
++	kfree(lseg);
+ }
+ 
+-static struct pnfs_layout_segment *
+-bl_alloc_lseg(struct pnfs_layout_hdr *lo,
+-	      struct nfs4_layoutget_res *lgr, gfp_t gfp_flags)
++/* We pretty much ignore lseg, and store all data layout wide, so we
++ * can correctly merge.
++ */
++static struct pnfs_layout_segment *bl_alloc_lseg(struct pnfs_layout_hdr *lo,
++						 struct nfs4_layoutget_res *lgr,
++						 gfp_t gfp_flags)
+ {
+-	return NULL;
++	struct pnfs_layout_segment *lseg;
++	int status;
++
++	dprintk("%s enter\n", __func__);
++	lseg = kzalloc(sizeof(*lseg), gfp_flags);
++	if (!lseg)
++		return ERR_PTR(-ENOMEM);
++	status = nfs4_blk_process_layoutget(lo, lgr, gfp_flags);
++	if (status) {
++		/* We don't want to call the full-blown bl_free_lseg,
++		 * since on error extents were not touched.
++		 */
++		kfree(lseg);
++		return ERR_PTR(status);
++	}
++	return lseg;
+ }
+ 
+ static void
+diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklayout.h
+index 1527f88e00dd..3e05b08d5347 100644
+--- a/fs/nfs/blocklayout/blocklayout.h
++++ b/fs/nfs/blocklayout/blocklayout.h
+@@ -96,6 +96,12 @@ static inline struct pnfs_block_layout *BLK_LO2EXT(struct pnfs_layout_hdr *lo)
+ 	return container_of(lo, struct pnfs_block_layout, bl_layout);
+ }
+ 
++static inline struct pnfs_block_layout *
++BLK_LSEG2EXT(struct pnfs_layout_segment *lseg)
++{
++	return BLK_LO2EXT(lseg->pls_layout);
++}
++
+ struct bl_dev_msg {
+ 	int status;
+ 	uint32_t major, minor;
+diff --git a/fs/nfs/blocklayout/blocklayoutdev.c b/fs/nfs/blocklayout/blocklayoutdev.c
+index 7e1377fcfdce..64da33a40eaf 100644
+--- a/fs/nfs/blocklayout/blocklayoutdev.c
++++ b/fs/nfs/blocklayout/blocklayoutdev.c
+@@ -189,3 +189,11 @@ nfs4_blk_decode_device(struct nfs_server *server,
+ 	kfree(msg.data);
+ 	return rv;
+ }
++
++int
++nfs4_blk_process_layoutget(struct pnfs_layout_hdr *lo,
++			   struct nfs4_layoutget_res *lgr, gfp_t gfp_flags)
++{
++	/* STUB */
++	return -EIO;
++}

commit 9e69296999362c4e4b2821b64389b47e86e4821b
+Author: Fred Isaman 
+Date:   Sat Jul 30 20:52:41 2011 -0400
+
+    pnfsblock: basic extent code
+    
+    Adds structures and basic create/delete code for extents.
+    
+    Signed-off-by: Fred Isaman 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Zhang Jingwang 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Jim Rees 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/blocklayout/Makefile b/fs/nfs/blocklayout/Makefile
+index 6bf49cd5da06..5cfadf6ebc90 100644
+--- a/fs/nfs/blocklayout/Makefile
++++ b/fs/nfs/blocklayout/Makefile
+@@ -2,4 +2,4 @@
+ # Makefile for the pNFS block layout driver kernel module
+ #
+ obj-$(CONFIG_PNFS_BLOCK) += blocklayoutdriver.o
+-blocklayoutdriver-objs := blocklayout.o
++blocklayoutdriver-objs := blocklayout.o extents.o
+diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
+index 1f5287c2230a..8dde3723482e 100644
+--- a/fs/nfs/blocklayout/blocklayout.c
++++ b/fs/nfs/blocklayout/blocklayout.c
+@@ -53,12 +53,24 @@ bl_write_pagelist(struct nfs_write_data *wdata,
+ 	return PNFS_NOT_ATTEMPTED;
+ }
+ 
+-/* STUB */
++/* FIXME - range ignored */
+ static void
+-release_extents(struct pnfs_block_layout *bl,
+-		struct pnfs_layout_range *range)
++release_extents(struct pnfs_block_layout *bl, struct pnfs_layout_range *range)
+ {
+-	return;
++	int i;
++	struct pnfs_block_extent *be;
++
++	spin_lock(&bl->bl_ext_lock);
++	for (i = 0; i < EXTENT_LISTS; i++) {
++		while (!list_empty(&bl->bl_extents[i])) {
++			be = list_first_entry(&bl->bl_extents[i],
++					      struct pnfs_block_extent,
++					      be_node);
++			list_del(&be->be_node);
++			bl_put_extent(be);
++		}
++	}
++	spin_unlock(&bl->bl_ext_lock);
+ }
+ 
+ /* STUB */
+diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklayout.h
+index 8bfa4668ff31..98e2f60c2143 100644
+--- a/fs/nfs/blocklayout/blocklayout.h
++++ b/fs/nfs/blocklayout/blocklayout.h
+@@ -88,4 +88,5 @@ static inline struct pnfs_block_layout *BLK_LO2EXT(struct pnfs_layout_hdr *lo)
+ 	return container_of(lo, struct pnfs_block_layout, bl_layout);
+ }
+ 
++void bl_put_extent(struct pnfs_block_extent *be);
+ #endif /* FS_NFS_NFS4BLOCKLAYOUT_H */
+diff --git a/fs/nfs/blocklayout/extents.c b/fs/nfs/blocklayout/extents.c
+new file mode 100644
+index 000000000000..d0ca7604d33e
+--- /dev/null
++++ b/fs/nfs/blocklayout/extents.c
+@@ -0,0 +1,89 @@
++/*
++ *  linux/fs/nfs/blocklayout/blocklayout.h
++ *
++ *  Module for the NFSv4.1 pNFS block layout driver.
++ *
++ *  Copyright (c) 2006 The Regents of the University of Michigan.
++ *  All rights reserved.
++ *
++ *  Andy Adamson 
++ *  Fred Isaman 
++ *
++ * permission is granted to use, copy, create derivative works and
++ * redistribute this software and such derivative works for any purpose,
++ * so long as the name of the university of michigan is not used in
++ * any advertising or publicity pertaining to the use or distribution
++ * of this software without specific, written prior authorization.  if
++ * the above copyright notice or any other identification of the
++ * university of michigan is included in any copy of any portion of
++ * this software, then the disclaimer below must also be included.
++ *
++ * this software is provided as is, without representation from the
++ * university of michigan as to its fitness for any purpose, and without
++ * warranty by the university of michigan of any kind, either express
++ * or implied, including without limitation the implied warranties of
++ * merchantability and fitness for a particular purpose.  the regents
++ * of the university of michigan shall not be liable for any damages,
++ * including special, indirect, incidental, or consequential damages,
++ * with respect to any claim arising out or in connection with the use
++ * of the software, even if it has been or is hereafter advised of the
++ * possibility of such damages.
++ */
++
++#include "blocklayout.h"
++#define NFSDBG_FACILITY         NFSDBG_PNFS_LD
++
++static void print_bl_extent(struct pnfs_block_extent *be)
++{
++	dprintk("PRINT EXTENT extent %p\n", be);
++	if (be) {
++		dprintk("        be_f_offset %llu\n", (u64)be->be_f_offset);
++		dprintk("        be_length   %llu\n", (u64)be->be_length);
++		dprintk("        be_v_offset %llu\n", (u64)be->be_v_offset);
++		dprintk("        be_state    %d\n", be->be_state);
++	}
++}
++
++static void
++destroy_extent(struct kref *kref)
++{
++	struct pnfs_block_extent *be;
++
++	be = container_of(kref, struct pnfs_block_extent, be_refcnt);
++	dprintk("%s be=%p\n", __func__, be);
++	kfree(be);
++}
++
++void
++bl_put_extent(struct pnfs_block_extent *be)
++{
++	if (be) {
++		dprintk("%s enter %p (%i)\n", __func__, be,
++			atomic_read(&be->be_refcnt.refcount));
++		kref_put(&be->be_refcnt, destroy_extent);
++	}
++}
++
++struct pnfs_block_extent *bl_alloc_extent(void)
++{
++	struct pnfs_block_extent *be;
++
++	be = kmalloc(sizeof(struct pnfs_block_extent), GFP_NOFS);
++	if (!be)
++		return NULL;
++	INIT_LIST_HEAD(&be->be_node);
++	kref_init(&be->be_refcnt);
++	be->be_inval = NULL;
++	return be;
++}
++
++static void print_elist(struct list_head *list)
++{
++	struct pnfs_block_extent *be;
++	dprintk("****************\n");
++	dprintk("Extent list looks like:\n");
++	list_for_each_entry(be, list, be_node) {
++		print_bl_extent(be);
++	}
++	dprintk("****************\n");
++}

commit 155e7524f28fa374da041434085050693c3df45b
+Author: Fred Isaman 
+Date:   Sat Jul 30 20:52:39 2011 -0400
+
+    pnfsblock: add blocklayout Kconfig option, Makefile, and stubs
+    
+    Define a configuration variable to enable/disable compilation of the
+    block driver code.
+    
+    Add the minimal structure for a pnfs block layout driver, and empty
+    list-heads that will hold the extent data
+    
+    [pnfsblock: make NFS_V4_1 select PNFS_BLOCK]
+    Signed-off-by: Peng Tao 
+    Signed-off-by: Fred Isaman 
+    Signed-off-by: Benny Halevy 
+    [pnfs-block: fix CONFIG_PNFS_BLOCK dependencies]
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Benny Halevy 
+    [pnfsblock: SQUASHME: adjust to API change]
+    Signed-off-by: Fred Isaman 
+    [pnfs: move pnfs_layout_type inline in nfs_inode]
+    Signed-off-by: Benny Halevy 
+    [blocklayout: encode_layoutcommit implementation]
+    Signed-off-by: Boaz Harrosh 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Benny Halevy 
+    [pnfsblock: layout alloc and free]
+    Signed-off-by: Fred Isaman 
+    [pnfs: move pnfs_layout_type inline in nfs_inode]
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Benny Halevy 
+    [pnfsblock: define module alias]
+    Signed-off-by: Peng Tao 
+    [rm inode and pnfs_layout_hdr args from cleanup_layoutcommit()]
+    Signed-off-by: Jim Rees 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
+index 2cde5d954750..be020771c6b4 100644
+--- a/fs/nfs/Kconfig
++++ b/fs/nfs/Kconfig
+@@ -79,15 +79,21 @@ config NFS_V4_1
+ 	depends on NFS_FS && NFS_V4 && EXPERIMENTAL
+ 	select SUNRPC_BACKCHANNEL
+ 	select PNFS_FILE_LAYOUT
++	select PNFS_BLOCK
++	select MD
++	select BLK_DEV_DM
+ 	help
+ 	  This option enables support for minor version 1 of the NFSv4 protocol
+-	  (RFC 5661) in the kernel's NFS client.
++	  (RFC 5661 and RFC 5663) in the kernel's NFS client.
+ 
+ 	  If unsure, say N.
+ 
+ config PNFS_FILE_LAYOUT
+ 	tristate
+ 
++config PNFS_BLOCK
++	tristate
++
+ config PNFS_OBJLAYOUT
+ 	tristate "Provide support for the pNFS Objects Layout Driver for NFSv4.1 pNFS (EXPERIMENTAL)"
+ 	depends on NFS_FS && NFS_V4_1 && SCSI_OSD_ULD
+diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
+index 6a34f7dd0e6f..b58613d0abb3 100644
+--- a/fs/nfs/Makefile
++++ b/fs/nfs/Makefile
+@@ -23,3 +23,4 @@ obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o
+ nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o
+ 
+ obj-$(CONFIG_PNFS_OBJLAYOUT) += objlayout/
++obj-$(CONFIG_PNFS_BLOCK) += blocklayout/
+diff --git a/fs/nfs/blocklayout/Makefile b/fs/nfs/blocklayout/Makefile
+new file mode 100644
+index 000000000000..6bf49cd5da06
+--- /dev/null
++++ b/fs/nfs/blocklayout/Makefile
+@@ -0,0 +1,5 @@
++#
++# Makefile for the pNFS block layout driver kernel module
++#
++obj-$(CONFIG_PNFS_BLOCK) += blocklayoutdriver.o
++blocklayoutdriver-objs := blocklayout.o
+diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
+new file mode 100644
+index 000000000000..44562cbbe394
+--- /dev/null
++++ b/fs/nfs/blocklayout/blocklayout.c
+@@ -0,0 +1,174 @@
++/*
++ *  linux/fs/nfs/blocklayout/blocklayout.c
++ *
++ *  Module for the NFSv4.1 pNFS block layout driver.
++ *
++ *  Copyright (c) 2006 The Regents of the University of Michigan.
++ *  All rights reserved.
++ *
++ *  Andy Adamson 
++ *  Fred Isaman 
++ *
++ * permission is granted to use, copy, create derivative works and
++ * redistribute this software and such derivative works for any purpose,
++ * so long as the name of the university of michigan is not used in
++ * any advertising or publicity pertaining to the use or distribution
++ * of this software without specific, written prior authorization.  if
++ * the above copyright notice or any other identification of the
++ * university of michigan is included in any copy of any portion of
++ * this software, then the disclaimer below must also be included.
++ *
++ * this software is provided as is, without representation from the
++ * university of michigan as to its fitness for any purpose, and without
++ * warranty by the university of michigan of any kind, either express
++ * or implied, including without limitation the implied warranties of
++ * merchantability and fitness for a particular purpose.  the regents
++ * of the university of michigan shall not be liable for any damages,
++ * including special, indirect, incidental, or consequential damages,
++ * with respect to any claim arising out or in connection with the use
++ * of the software, even if it has been or is hereafter advised of the
++ * possibility of such damages.
++ */
++#include 
++#include 
++
++#include "blocklayout.h"
++
++#define NFSDBG_FACILITY	NFSDBG_PNFS_LD
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Andy Adamson ");
++MODULE_DESCRIPTION("The NFSv4.1 pNFS Block layout driver");
++
++static enum pnfs_try_status
++bl_read_pagelist(struct nfs_read_data *rdata)
++{
++	return PNFS_NOT_ATTEMPTED;
++}
++
++static enum pnfs_try_status
++bl_write_pagelist(struct nfs_write_data *wdata,
++		  int sync)
++{
++	return PNFS_NOT_ATTEMPTED;
++}
++
++/* STUB */
++static void
++release_extents(struct pnfs_block_layout *bl,
++		struct pnfs_layout_range *range)
++{
++	return;
++}
++
++/* STUB */
++static void
++release_inval_marks(struct pnfs_inval_markings *marks)
++{
++	return;
++}
++
++static void bl_free_layout_hdr(struct pnfs_layout_hdr *lo)
++{
++	struct pnfs_block_layout *bl = BLK_LO2EXT(lo);
++
++	dprintk("%s enter\n", __func__);
++	release_extents(bl, NULL);
++	release_inval_marks(&bl->bl_inval);
++	kfree(bl);
++}
++
++static struct pnfs_layout_hdr *bl_alloc_layout_hdr(struct inode *inode,
++						   gfp_t gfp_flags)
++{
++	struct pnfs_block_layout *bl;
++
++	dprintk("%s enter\n", __func__);
++	bl = kzalloc(sizeof(*bl), gfp_flags);
++	if (!bl)
++		return NULL;
++	spin_lock_init(&bl->bl_ext_lock);
++	INIT_LIST_HEAD(&bl->bl_extents[0]);
++	INIT_LIST_HEAD(&bl->bl_extents[1]);
++	INIT_LIST_HEAD(&bl->bl_commit);
++	INIT_LIST_HEAD(&bl->bl_committing);
++	bl->bl_count = 0;
++	bl->bl_blocksize = NFS_SERVER(inode)->pnfs_blksize >> SECTOR_SHIFT;
++	BL_INIT_INVAL_MARKS(&bl->bl_inval, bl->bl_blocksize);
++	return &bl->bl_layout;
++}
++
++static void
++bl_free_lseg(struct pnfs_layout_segment *lseg)
++{
++}
++
++static struct pnfs_layout_segment *
++bl_alloc_lseg(struct pnfs_layout_hdr *lo,
++	      struct nfs4_layoutget_res *lgr, gfp_t gfp_flags)
++{
++	return NULL;
++}
++
++static void
++bl_encode_layoutcommit(struct pnfs_layout_hdr *lo, struct xdr_stream *xdr,
++		       const struct nfs4_layoutcommit_args *arg)
++{
++}
++
++static void
++bl_cleanup_layoutcommit(struct nfs4_layoutcommit_data *lcdata)
++{
++}
++
++static int
++bl_set_layoutdriver(struct nfs_server *server, const struct nfs_fh *fh)
++{
++	dprintk("%s enter\n", __func__);
++	return 0;
++}
++
++static int
++bl_clear_layoutdriver(struct nfs_server *server)
++{
++	dprintk("%s enter\n", __func__);
++	return 0;
++}
++
++static struct pnfs_layoutdriver_type blocklayout_type = {
++	.id				= LAYOUT_BLOCK_VOLUME,
++	.name				= "LAYOUT_BLOCK_VOLUME",
++	.read_pagelist			= bl_read_pagelist,
++	.write_pagelist			= bl_write_pagelist,
++	.alloc_layout_hdr		= bl_alloc_layout_hdr,
++	.free_layout_hdr		= bl_free_layout_hdr,
++	.alloc_lseg			= bl_alloc_lseg,
++	.free_lseg			= bl_free_lseg,
++	.encode_layoutcommit		= bl_encode_layoutcommit,
++	.cleanup_layoutcommit		= bl_cleanup_layoutcommit,
++	.set_layoutdriver		= bl_set_layoutdriver,
++	.clear_layoutdriver		= bl_clear_layoutdriver,
++};
++
++static int __init nfs4blocklayout_init(void)
++{
++	int ret;
++
++	dprintk("%s: NFSv4 Block Layout Driver Registering...\n", __func__);
++
++	ret = pnfs_register_layoutdriver(&blocklayout_type);
++	return ret;
++}
++
++static void __exit nfs4blocklayout_exit(void)
++{
++	dprintk("%s: NFSv4 Block Layout Driver Unregistering...\n",
++	       __func__);
++
++	pnfs_unregister_layoutdriver(&blocklayout_type);
++}
++
++MODULE_ALIAS("nfs-layouttype4-3");
++
++module_init(nfs4blocklayout_init);
++module_exit(nfs4blocklayout_exit);
+diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklayout.h
+new file mode 100644
+index 000000000000..8bfa4668ff31
+--- /dev/null
++++ b/fs/nfs/blocklayout/blocklayout.h
+@@ -0,0 +1,91 @@
++/*
++ *  linux/fs/nfs/blocklayout/blocklayout.h
++ *
++ *  Module for the NFSv4.1 pNFS block layout driver.
++ *
++ *  Copyright (c) 2006 The Regents of the University of Michigan.
++ *  All rights reserved.
++ *
++ *  Andy Adamson 
++ *  Fred Isaman 
++ *
++ * permission is granted to use, copy, create derivative works and
++ * redistribute this software and such derivative works for any purpose,
++ * so long as the name of the university of michigan is not used in
++ * any advertising or publicity pertaining to the use or distribution
++ * of this software without specific, written prior authorization.  if
++ * the above copyright notice or any other identification of the
++ * university of michigan is included in any copy of any portion of
++ * this software, then the disclaimer below must also be included.
++ *
++ * this software is provided as is, without representation from the
++ * university of michigan as to its fitness for any purpose, and without
++ * warranty by the university of michigan of any kind, either express
++ * or implied, including without limitation the implied warranties of
++ * merchantability and fitness for a particular purpose.  the regents
++ * of the university of michigan shall not be liable for any damages,
++ * including special, indirect, incidental, or consequential damages,
++ * with respect to any claim arising out or in connection with the use
++ * of the software, even if it has been or is hereafter advised of the
++ * possibility of such damages.
++ */
++#ifndef FS_NFS_NFS4BLOCKLAYOUT_H
++#define FS_NFS_NFS4BLOCKLAYOUT_H
++
++#include 
++#include 
++#include "../pnfs.h"
++
++enum exstate4 {
++	PNFS_BLOCK_READWRITE_DATA	= 0,
++	PNFS_BLOCK_READ_DATA		= 1,
++	PNFS_BLOCK_INVALID_DATA		= 2, /* mapped, but data is invalid */
++	PNFS_BLOCK_NONE_DATA		= 3  /* unmapped, it's a hole */
++};
++
++struct pnfs_inval_markings {
++	/* STUB */
++};
++
++/* sector_t fields are all in 512-byte sectors */
++struct pnfs_block_extent {
++	struct kref	be_refcnt;
++	struct list_head be_node;	/* link into lseg list */
++	struct nfs4_deviceid be_devid;  /* FIXME: could use device cache instead */
++	struct block_device *be_mdev;
++	sector_t	be_f_offset;	/* the starting offset in the file */
++	sector_t	be_length;	/* the size of the extent */
++	sector_t	be_v_offset;	/* the starting offset in the volume */
++	enum exstate4	be_state;	/* the state of this extent */
++	struct pnfs_inval_markings *be_inval; /* tracks INVAL->RW transition */
++};
++
++static inline void
++BL_INIT_INVAL_MARKS(struct pnfs_inval_markings *marks, sector_t blocksize)
++{
++	/* STUB */
++}
++
++enum extentclass4 {
++	RW_EXTENT       = 0, /* READWRTE and INVAL */
++	RO_EXTENT       = 1, /* READ and NONE */
++	EXTENT_LISTS    = 2,
++};
++
++struct pnfs_block_layout {
++	struct pnfs_layout_hdr bl_layout;
++	struct pnfs_inval_markings bl_inval; /* tracks INVAL->RW transition */
++	spinlock_t		bl_ext_lock;   /* Protects list manipulation */
++	struct list_head	bl_extents[EXTENT_LISTS]; /* R and RW extents */
++	struct list_head	bl_commit;	/* Needs layout commit */
++	struct list_head	bl_committing;	/* Layout committing */
++	unsigned int		bl_count;	/* entries in bl_commit */
++	sector_t		bl_blocksize;  /* Server blocksize in sectors */
++};
++
++static inline struct pnfs_block_layout *BLK_LO2EXT(struct pnfs_layout_hdr *lo)
++{
++	return container_of(lo, struct pnfs_block_layout, bl_layout);
++}
++
++#endif /* FS_NFS_NFS4BLOCKLAYOUT_H */

commit dae100c2b1b9463996aab9162f2258145c43f7df
+Author: Fred Isaman 
+Date:   Sat Jul 30 20:52:37 2011 -0400
+
+    pnfs: ask for layout_blksize and save it in nfs_server
+    
+    Block layout needs it to determine IO size.
+    
+    Signed-off-by: Fred Isaman 
+    Signed-off-by: Tao Guo 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Jim Rees 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/client.c b/fs/nfs/client.c
+index a9b18483cb24..de00a373f085 100644
+--- a/fs/nfs/client.c
++++ b/fs/nfs/client.c
+@@ -936,6 +936,7 @@ static void nfs_server_set_fsinfo(struct nfs_server *server,
+ 	if (server->wsize > NFS_MAX_FILE_IO_SIZE)
+ 		server->wsize = NFS_MAX_FILE_IO_SIZE;
+ 	server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
++	server->pnfs_blksize = fsinfo->blksize;
+ 	set_pnfs_layoutdriver(server, mntfh, fsinfo->layouttype);
+ 
+ 	server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL);
+diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
+index 1909ee8be350..1ec1a85fa71c 100644
+--- a/fs/nfs/nfs4_fs.h
++++ b/fs/nfs/nfs4_fs.h
+@@ -318,7 +318,7 @@ extern const struct nfs4_minor_version_ops *nfs_v4_minor_ops[];
+ extern const u32 nfs4_fattr_bitmap[2];
+ extern const u32 nfs4_statfs_bitmap[2];
+ extern const u32 nfs4_pathconf_bitmap[2];
+-extern const u32 nfs4_fsinfo_bitmap[2];
++extern const u32 nfs4_fsinfo_bitmap[3];
+ extern const u32 nfs4_fs_locations_bitmap[2];
+ 
+ /* nfs4renewd.c */
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index af32d3df0544..e86de799dd12 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -140,12 +140,13 @@ const u32 nfs4_pathconf_bitmap[2] = {
+ 	0
+ };
+ 
+-const u32 nfs4_fsinfo_bitmap[2] = { FATTR4_WORD0_MAXFILESIZE
++const u32 nfs4_fsinfo_bitmap[3] = { FATTR4_WORD0_MAXFILESIZE
+ 			| FATTR4_WORD0_MAXREAD
+ 			| FATTR4_WORD0_MAXWRITE
+ 			| FATTR4_WORD0_LEASE_TIME,
+ 			FATTR4_WORD1_TIME_DELTA
+-			| FATTR4_WORD1_FS_LAYOUT_TYPES
++			| FATTR4_WORD1_FS_LAYOUT_TYPES,
++			FATTR4_WORD2_LAYOUT_BLKSIZE
+ };
+ 
+ const u32 nfs4_fs_locations_bitmap[2] = {
+diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
+index 5f769f8d05b0..026166993d11 100644
+--- a/fs/nfs/nfs4xdr.c
++++ b/fs/nfs/nfs4xdr.c
+@@ -113,7 +113,11 @@ static int nfs4_stat_to_errno(int);
+ #define encode_restorefh_maxsz  (op_encode_hdr_maxsz)
+ #define decode_restorefh_maxsz  (op_decode_hdr_maxsz)
+ #define encode_fsinfo_maxsz	(encode_getattr_maxsz)
+-#define decode_fsinfo_maxsz	(op_decode_hdr_maxsz + 15)
++/* The 5 accounts for the PNFS attributes, and assumes that at most three
++ * layout types will be returned.
++ */
++#define decode_fsinfo_maxsz	(op_decode_hdr_maxsz + \
++				 nfs4_fattr_bitmap_maxsz + 4 + 8 + 5)
+ #define encode_renew_maxsz	(op_encode_hdr_maxsz + 3)
+ #define decode_renew_maxsz	(op_decode_hdr_maxsz)
+ #define encode_setclientid_maxsz \
+@@ -1123,6 +1127,35 @@ static void encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm
+ 	hdr->replen += decode_getattr_maxsz;
+ }
+ 
++static void
++encode_getattr_three(struct xdr_stream *xdr,
++		     uint32_t bm0, uint32_t bm1, uint32_t bm2,
++		     struct compound_hdr *hdr)
++{
++	__be32 *p;
++
++	p = reserve_space(xdr, 4);
++	*p = cpu_to_be32(OP_GETATTR);
++	if (bm2) {
++		p = reserve_space(xdr, 16);
++		*p++ = cpu_to_be32(3);
++		*p++ = cpu_to_be32(bm0);
++		*p++ = cpu_to_be32(bm1);
++		*p = cpu_to_be32(bm2);
++	} else if (bm1) {
++		p = reserve_space(xdr, 12);
++		*p++ = cpu_to_be32(2);
++		*p++ = cpu_to_be32(bm0);
++		*p = cpu_to_be32(bm1);
++	} else {
++		p = reserve_space(xdr, 8);
++		*p++ = cpu_to_be32(1);
++		*p = cpu_to_be32(bm0);
++	}
++	hdr->nops++;
++	hdr->replen += decode_getattr_maxsz;
++}
++
+ static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
+ {
+ 	encode_getattr_two(xdr, bitmask[0] & nfs4_fattr_bitmap[0],
+@@ -1131,8 +1164,11 @@ static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct c
+ 
+ static void encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
+ {
+-	encode_getattr_two(xdr, bitmask[0] & nfs4_fsinfo_bitmap[0],
+-			   bitmask[1] & nfs4_fsinfo_bitmap[1], hdr);
++	encode_getattr_three(xdr,
++			     bitmask[0] & nfs4_fsinfo_bitmap[0],
++			     bitmask[1] & nfs4_fsinfo_bitmap[1],
++			     bitmask[2] & nfs4_fsinfo_bitmap[2],
++			     hdr);
+ }
+ 
+ static void encode_fs_locations(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
+@@ -2643,7 +2679,7 @@ static void nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req,
+ 	struct compound_hdr hdr = {
+ 		.nops	= 0,
+ 	};
+-	const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 };
++	const u32 lease_bitmap[3] = { FATTR4_WORD0_LEASE_TIME };
+ 
+ 	encode_compound_hdr(xdr, req, &hdr);
+ 	encode_setclientid_confirm(xdr, arg, &hdr);
+@@ -2787,7 +2823,7 @@ static void nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req,
+ 	struct compound_hdr hdr = {
+ 		.minorversion = nfs4_xdr_minorversion(&args->la_seq_args),
+ 	};
+-	const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 };
++	const u32 lease_bitmap[3] = { FATTR4_WORD0_LEASE_TIME };
+ 
+ 	encode_compound_hdr(xdr, req, &hdr);
+ 	encode_sequence(xdr, &args->la_seq_args, &hdr);
+@@ -3068,14 +3104,17 @@ static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap)
+ 		goto out_overflow;
+ 	bmlen = be32_to_cpup(p);
+ 
+-	bitmap[0] = bitmap[1] = 0;
++	bitmap[0] = bitmap[1] = bitmap[2] = 0;
+ 	p = xdr_inline_decode(xdr, (bmlen << 2));
+ 	if (unlikely(!p))
+ 		goto out_overflow;
+ 	if (bmlen > 0) {
+ 		bitmap[0] = be32_to_cpup(p++);
+-		if (bmlen > 1)
+-			bitmap[1] = be32_to_cpup(p);
++		if (bmlen > 1) {
++			bitmap[1] = be32_to_cpup(p++);
++			if (bmlen > 2)
++				bitmap[2] = be32_to_cpup(p);
++		}
+ 	}
+ 	return 0;
+ out_overflow:
+@@ -3107,8 +3146,9 @@ static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint3
+ 			return ret;
+ 		bitmap[0] &= ~FATTR4_WORD0_SUPPORTED_ATTRS;
+ 	} else
+-		bitmask[0] = bitmask[1] = 0;
+-	dprintk("%s: bitmask=%08x:%08x\n", __func__, bitmask[0], bitmask[1]);
++		bitmask[0] = bitmask[1] = bitmask[2] = 0;
++	dprintk("%s: bitmask=%08x:%08x:%08x\n", __func__,
++		bitmask[0], bitmask[1], bitmask[2]);
+ 	return 0;
+ }
+ 
+@@ -4162,7 +4202,7 @@ static int decode_create(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
+ static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_res *res)
+ {
+ 	__be32 *savep;
+-	uint32_t attrlen, bitmap[2] = {0};
++	uint32_t attrlen, bitmap[3] = {0};
+ 	int status;
+ 
+ 	if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
+@@ -4188,7 +4228,7 @@ static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_re
+ static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat)
+ {
+ 	__be32 *savep;
+-	uint32_t attrlen, bitmap[2] = {0};
++	uint32_t attrlen, bitmap[3] = {0};
+ 	int status;
+ 
+ 	if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
+@@ -4220,7 +4260,7 @@ static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat)
+ static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf)
+ {
+ 	__be32 *savep;
+-	uint32_t attrlen, bitmap[2] = {0};
++	uint32_t attrlen, bitmap[3] = {0};
+ 	int status;
+ 
+ 	if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
+@@ -4360,7 +4400,7 @@ static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fat
+ {
+ 	__be32 *savep;
+ 	uint32_t attrlen,
+-		 bitmap[2] = {0};
++		 bitmap[3] = {0};
+ 	int status;
+ 
+ 	status = decode_op_hdr(xdr, OP_GETATTR);
+@@ -4446,10 +4486,32 @@ static int decode_attr_pnfstype(struct xdr_stream *xdr, uint32_t *bitmap,
+ 	return status;
+ }
+ 
++/*
++ * The prefered block size for layout directed io
++ */
++static int decode_attr_layout_blksize(struct xdr_stream *xdr, uint32_t *bitmap,
++				      uint32_t *res)
++{
++	__be32 *p;
++
++	dprintk("%s: bitmap is %x\n", __func__, bitmap[2]);
++	*res = 0;
++	if (bitmap[2] & FATTR4_WORD2_LAYOUT_BLKSIZE) {
++		p = xdr_inline_decode(xdr, 4);
++		if (unlikely(!p)) {
++			print_overflow_msg(__func__, xdr);
++			return -EIO;
++		}
++		*res = be32_to_cpup(p);
++		bitmap[2] &= ~FATTR4_WORD2_LAYOUT_BLKSIZE;
++	}
++	return 0;
++}
++
+ static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)
+ {
+ 	__be32 *savep;
+-	uint32_t attrlen, bitmap[2];
++	uint32_t attrlen, bitmap[3];
+ 	int status;
+ 
+ 	if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
+@@ -4477,6 +4539,9 @@ static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)
+ 	status = decode_attr_pnfstype(xdr, bitmap, &fsinfo->layouttype);
+ 	if (status != 0)
+ 		goto xdr_error;
++	status = decode_attr_layout_blksize(xdr, bitmap, &fsinfo->blksize);
++	if (status)
++		goto xdr_error;
+ 
+ 	status = verify_attr_len(xdr, savep, attrlen);
+ xdr_error:
+@@ -4896,7 +4961,7 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
+ {
+ 	__be32 *savep;
+ 	uint32_t attrlen,
+-		 bitmap[2] = {0};
++		 bitmap[3] = {0};
+ 	struct kvec *iov = req->rq_rcv_buf.head;
+ 	int status;
+ 
+@@ -6852,7 +6917,7 @@ static int nfs4_xdr_dec_free_stateid(struct rpc_rqst *rqstp,
+ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
+ 		       int plus)
+ {
+-	uint32_t bitmap[2] = {0};
++	uint32_t bitmap[3] = {0};
+ 	uint32_t len;
+ 	__be32 *p = xdr_inline_decode(xdr, 4);
+ 	if (unlikely(!p))
+diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
+index 4faeac8f448a..b2ea8b82d2cb 100644
+--- a/include/linux/nfs_fs_sb.h
++++ b/include/linux/nfs_fs_sb.h
+@@ -132,7 +132,7 @@ struct nfs_server {
+ #endif
+ 
+ #ifdef CONFIG_NFS_V4
+-	u32			attr_bitmask[2];/* V4 bitmask representing the set
++	u32			attr_bitmask[3];/* V4 bitmask representing the set
+ 						   of attributes supported on this
+ 						   filesystem */
+ 	u32			cache_consistency_bitmask[2];
+@@ -145,6 +145,7 @@ struct nfs_server {
+ 						   filesystem */
+ 	struct pnfs_layoutdriver_type  *pnfs_curr_ld; /* Active layout driver */
+ 	struct rpc_wait_queue	roc_rpcwaitq;
++	u32			pnfs_blksize;	/* layout_blksize attr */
+ 
+ 	/* the following fields are protected by nfs_client->cl_lock */
+ 	struct rb_root		state_owners;
+diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
+index 21f333eae3c8..94f27e56df9c 100644
+--- a/include/linux/nfs_xdr.h
++++ b/include/linux/nfs_xdr.h
+@@ -122,6 +122,7 @@ struct nfs_fsinfo {
+ 	struct timespec		time_delta; /* server time granularity */
+ 	__u32			lease_time; /* in seconds */
+ 	__u32			layouttype; /* supported pnfs layout driver */
++	__u32			blksize; /* preferred pnfs io block size */
+ };
+ 
+ struct nfs_fsstat {
+@@ -954,7 +955,7 @@ struct nfs4_server_caps_arg {
+ };
+ 
+ struct nfs4_server_caps_res {
+-	u32				attr_bitmask[2];
++	u32				attr_bitmask[3];
+ 	u32				acl_bitmask;
+ 	u32				has_links;
+ 	u32				has_symlinks;

commit 0c12eaffdf09466f36a9ffe970dda8f4aeb6efc0
+Author: Casey Bodley 
+Date:   Sat Jul 23 14:58:10 2011 -0400
+
+    nfsd: don't break lease on CLAIM_DELEGATE_CUR
+    
+    CLAIM_DELEGATE_CUR is used in response to a broken lease; allowing it
+    to break the lease and return EAGAIN leaves the client unable to make
+    progress in returning the delegation
+    
+    nfs4_get_vfs_file() now takes struct nfsd4_open for access to the
+    claim type, and calls nfsd_open() with NFSD_MAY_NOT_BREAK_LEASE when
+    claim type is CLAIM_DELEGATE_CUR
+    
+    Signed-off-by: Casey Bodley 
+    Cc: stable@kernel.org
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 47da52576e66..3787ec117400 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2585,12 +2585,18 @@ static inline int nfs4_access_to_access(u32 nfs4_access)
+ 	return flags;
+ }
+ 
+-static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file
+-*fp, struct svc_fh *cur_fh, u32 nfs4_access)
++static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file *fp,
++		struct svc_fh *cur_fh, struct nfsd4_open *open)
+ {
+ 	__be32 status;
+-	int oflag = nfs4_access_to_omode(nfs4_access);
+-	int access = nfs4_access_to_access(nfs4_access);
++	int oflag = nfs4_access_to_omode(open->op_share_access);
++	int access = nfs4_access_to_access(open->op_share_access);
++
++	/* CLAIM_DELEGATE_CUR is used in response to a broken lease;
++	 * allowing it to break the lease and return EAGAIN leaves the
++	 * client unable to make progress in returning the delegation */
++	if (open->op_claim_type == NFS4_OPEN_CLAIM_DELEGATE_CUR)
++		access |= NFSD_MAY_NOT_BREAK_LEASE;
+ 
+ 	if (!fp->fi_fds[oflag]) {
+ 		status = nfsd_open(rqstp, cur_fh, S_IFREG, access,
+@@ -2615,7 +2621,7 @@ nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp,
+ 	if (stp == NULL)
+ 		return nfserr_resource;
+ 
+-	status = nfs4_get_vfs_file(rqstp, fp, cur_fh, open->op_share_access);
++	status = nfs4_get_vfs_file(rqstp, fp, cur_fh, open);
+ 	if (status) {
+ 		kmem_cache_free(stateid_slab, stp);
+ 		return status;
+@@ -2648,7 +2654,7 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct nfs4_file *fp, struct svc_fh *c
+ 
+ 	new_access = !test_bit(op_share_access, &stp->st_access_bmap);
+ 	if (new_access) {
+-		status = nfs4_get_vfs_file(rqstp, fp, cur_fh, op_share_access);
++		status = nfs4_get_vfs_file(rqstp, fp, cur_fh, open);
+ 		if (status)
+ 			return status;
+ 	}

commit 7d751f6f8c679f51b73d01a1b5269347a929004c
+Author: Casey Bodley 
+Date:   Fri Jun 3 12:21:23 2011 -0400
+
+    nfsd: link returns nfserr_delay when breaking lease
+    
+    fix for commit 4795bb37effb7b8fe77e2d2034545d062d3788a8, nfsd: break
+    lease on unlink, link, and rename
+    
+    if the LINK operation breaks a delegation, it returns NFS4ERR_NOENT
+    (which is not a valid error in rfc 5661) instead of NFS4ERR_DELAY.
+    the return value of nfsd_break_lease() in nfsd_link() must be
+    converted from host_err to err
+    
+    Signed-off-by: Casey Bodley 
+    Cc: stable@kernel.org
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index d5718273bb32..f3fb61b69a1e 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -1660,8 +1660,10 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
+ 	if (!dold->d_inode)
+ 		goto out_drop_write;
+ 	host_err = nfsd_break_lease(dold->d_inode);
+-	if (host_err)
++	if (host_err) {
++		err = nfserrno(host_err);
+ 		goto out_drop_write;
++	}
+ 	host_err = vfs_link(dold, dirp, dnew);
+ 	if (!host_err) {
+ 		err = nfserrno(commit_metadata(ffhp));

commit 9660439861aa8dbd5e2b8087f33e20760c2c9afc
+Author: Olga Kornievskaia 
+Date:   Tue Oct 21 14:13:47 2008 -0400
+
+    svcrpc: take advantage of tcp autotuning
+    
+    Allow the NFSv4 server to make use of TCP autotuning behaviour, which
+    was previously disabled by setting the sk_userlocks variable.
+    
+    Set the receive buffers to be big enough to receive the whole RPC
+    request, and set this for the listening socket, not the accept socket.
+    
+    Remove the code that readjusts the receive/send buffer sizes for the
+    accepted socket. Previously this code was used to influence the TCP
+    window management behaviour, which is no longer needed when autotuning
+    is enabled.
+    
+    This can improve IO bandwidth on networks with high bandwidth-delay
+    products, where a large tcp window is required.  It also simplifies
+    performance tuning, since getting adequate tcp buffers previously
+    required increasing the number of nfsd threads.
+    
+    Signed-off-by: Olga Kornievskaia 
+    Cc: Jim Rees 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
+index a4fafcbc6ea0..213dea8b283c 100644
+--- a/net/sunrpc/svcsock.c
++++ b/net/sunrpc/svcsock.c
+@@ -436,7 +436,6 @@ static void svc_sock_setbufsize(struct socket *sock, unsigned int snd,
+ 	lock_sock(sock->sk);
+ 	sock->sk->sk_sndbuf = snd * 2;
+ 	sock->sk->sk_rcvbuf = rcv * 2;
+-	sock->sk->sk_userlocks |= SOCK_SNDBUF_LOCK|SOCK_RCVBUF_LOCK;
+ 	sock->sk->sk_write_space(sock->sk);
+ 	release_sock(sock->sk);
+ #endif
+@@ -973,23 +972,6 @@ static int svc_tcp_recv_record(struct svc_sock *svsk, struct svc_rqst *rqstp)
+ 	unsigned int want;
+ 	int len;
+ 
+-	if (test_and_clear_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags))
+-		/* sndbuf needs to have room for one request
+-		 * per thread, otherwise we can stall even when the
+-		 * network isn't a bottleneck.
+-		 *
+-		 * We count all threads rather than threads in a
+-		 * particular pool, which provides an upper bound
+-		 * on the number of threads which will access the socket.
+-		 *
+-		 * rcvbuf just needs to be able to hold a few requests.
+-		 * Normally they will be removed from the queue
+-		 * as soon a a complete request arrives.
+-		 */
+-		svc_sock_setbufsize(svsk->sk_sock,
+-				    (serv->sv_nrthreads+3) * serv->sv_max_mesg,
+-				    3 * serv->sv_max_mesg);
+-
+ 	clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
+ 
+ 	if (svsk->sk_tcplen < sizeof(rpc_fraghdr)) {
+@@ -1367,15 +1349,6 @@ static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv)
+ 
+ 		tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF;
+ 
+-		/* initialise setting must have enough space to
+-		 * receive and respond to one request.
+-		 * svc_tcp_recvfrom will re-adjust if necessary
+-		 */
+-		svc_sock_setbufsize(svsk->sk_sock,
+-				    3 * svsk->sk_xprt.xpt_server->sv_max_mesg,
+-				    3 * svsk->sk_xprt.xpt_server->sv_max_mesg);
+-
+-		set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags);
+ 		set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
+ 		if (sk->sk_state != TCP_ESTABLISHED)
+ 			set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
+@@ -1439,8 +1412,14 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
+ 	/* Initialize the socket */
+ 	if (sock->type == SOCK_DGRAM)
+ 		svc_udp_init(svsk, serv);
+-	else
++	else {
++		/* initialise setting must have enough space to
++		 * receive and respond to one request.
++		 */
++		svc_sock_setbufsize(svsk->sk_sock, 4 * serv->sv_max_mesg,
++					4 * serv->sv_max_mesg);
+ 		svc_tcp_init(svsk, serv);
++	}
+ 
+ 	dprintk("svc: svc_setup_socket created %p (inet %p)\n",
+ 				svsk, svsk->sk_sk);

commit f8628220bb395104697be9c447c1085846dfc97c
+Author: Kevin Coffman 
+Date:   Thu Mar 3 00:51:41 2011 +0000
+
+    gss:krb5 only include enctype numbers in gm_upcall_enctypes
+    
+    Make the value in gm_upcall_enctypes just the enctype values.
+    This allows the values to be used more easily elsewhere.
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index 45dbf1521b9a..f3914d0c5079 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -417,7 +417,7 @@ static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg,
+ 		gss_msg->msg.len += len;
+ 	}
+ 	if (mech->gm_upcall_enctypes) {
+-		len = sprintf(p, mech->gm_upcall_enctypes);
++		len = sprintf(p, "enctypes=%s ", mech->gm_upcall_enctypes);
+ 		p += len;
+ 		gss_msg->msg.len += len;
+ 	}
+diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
+index f375decc024b..9022f0a6503e 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
++++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
+@@ -750,7 +750,7 @@ static struct gss_api_mech gss_kerberos_mech = {
+ 	.gm_ops		= &gss_kerberos_ops,
+ 	.gm_pf_num	= ARRAY_SIZE(gss_kerberos_pfs),
+ 	.gm_pfs		= gss_kerberos_pfs,
+-	.gm_upcall_enctypes = "enctypes=18,17,16,23,3,1,2 ",
++	.gm_upcall_enctypes = "18,17,16,23,3,1,2",
+ };
+ 
+ static int __init init_kerberos_module(void)

commit b0b0c0a26e846ae6646af9f59a3d2ea06b49cbc7
+Author: Kevin Coffman 
+Date:   Wed Mar 2 19:51:42 2011 -0500
+
+    nfsd: add proc file listing kernel's gss_krb5 enctypes
+    
+    Add a new proc file which lists the encryption types supported
+    by the kernel's gss_krb5 code.
+    
+    Newer MIT Kerberos libraries support the assertion of acceptor
+    subkeys.  This enctype information allows user-land (svcgssd)
+    to request that the Kerberos libraries limit the encryption
+    types that it uses when generating the subkeys.
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index 33b3e2b06779..35dcfa8eba21 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -12,13 +12,14 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include "idmap.h"
+ #include "nfsd.h"
+ #include "cache.h"
+ 
+ /*
+- *	We have a single directory with 9 nodes in it.
++ *	We have a single directory with several nodes in it.
+  */
+ enum {
+ 	NFSD_Root = 1,
+@@ -42,6 +43,7 @@ enum {
+ 	NFSD_Versions,
+ 	NFSD_Ports,
+ 	NFSD_MaxBlkSize,
++	NFSD_SupportedEnctypes,
+ 	/*
+ 	 * The below MUST come last.  Otherwise we leave a hole in nfsd_files[]
+ 	 * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops
+@@ -187,6 +189,32 @@ static struct file_operations export_features_operations = {
+ 	.release	= single_release,
+ };
+ 
++static int supported_enctypes_show(struct seq_file *m, void *v)
++{
++	struct gss_api_mech *k5mech;
++
++	k5mech = gss_mech_get_by_name("krb5");
++	if (k5mech == NULL)
++		goto out;
++	if (k5mech->gm_upcall_enctypes != NULL)
++		seq_printf(m, k5mech->gm_upcall_enctypes);
++	gss_mech_put(k5mech);
++out:
++	return 0;
++}
++
++static int supported_enctypes_open(struct inode *inode, struct file *file)
++{
++	return single_open(file, supported_enctypes_show, NULL);
++}
++
++static struct file_operations supported_enctypes_ops = {
++	.open		= supported_enctypes_open,
++	.read		= seq_read,
++	.llseek		= seq_lseek,
++	.release	= single_release,
++};
++
+ extern int nfsd_pool_stats_open(struct inode *inode, struct file *file);
+ extern int nfsd_pool_stats_release(struct inode *inode, struct file *file);
+ 
+@@ -1397,6 +1425,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
+ 		[NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR},
+ 		[NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO},
+ 		[NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO},
++		[NFSD_SupportedEnctypes] = {"supported_krb5_enctypes", &supported_enctypes_ops, S_IRUGO},
+ #ifdef CONFIG_NFSD_V4
+ 		[NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
+ 		[NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR},

commit 540c8cb6a576f34a9a0b04467f46bb6e67a1f852
+Author: Kevin Coffman 
+Date:   Wed Mar 2 19:51:41 2011 -0500
+
+    gss:krb5 only include enctype numbers in gm_upcall_enctypes
+    
+    Make the value in gm_upcall_enctypes just the enctype values.
+    This allows the values to be used more easily elsewhere.
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index 45dbf1521b9a..f3914d0c5079 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -417,7 +417,7 @@ static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg,
+ 		gss_msg->msg.len += len;
+ 	}
+ 	if (mech->gm_upcall_enctypes) {
+-		len = sprintf(p, mech->gm_upcall_enctypes);
++		len = sprintf(p, "enctypes=%s ", mech->gm_upcall_enctypes);
+ 		p += len;
+ 		gss_msg->msg.len += len;
+ 	}
+diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
+index f375decc024b..9022f0a6503e 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
++++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
+@@ -750,7 +750,7 @@ static struct gss_api_mech gss_kerberos_mech = {
+ 	.gm_ops		= &gss_kerberos_ops,
+ 	.gm_pf_num	= ARRAY_SIZE(gss_kerberos_pfs),
+ 	.gm_pfs		= gss_kerberos_pfs,
+-	.gm_upcall_enctypes = "enctypes=18,17,16,23,3,1,2 ",
++	.gm_upcall_enctypes = "18,17,16,23,3,1,2",
+ };
+ 
+ static int __init init_kerberos_module(void)

commit 77a3569d6c4e14e89fa628df383b6dccc0cce6be
+Author: J. Bruce Fields 
+Date:   Fri Apr 30 18:51:44 2010 -0400
+
+    nfsd4: keep finer-grained callback status
+    
+    Distinguish between when the callback channel is known to be down, and
+    when it is not yet confirmed.  This will be useful in the 4.1 case.
+    
+    Also, we don't seem to be using the fact that this field is atomic.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 18b740bd29ac..d32f49d6ca2c 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -470,8 +470,6 @@ static int max_cb_time(void)
+ 	return max(nfsd4_lease/10, (time_t)1) * HZ;
+ }
+ 
+-/* Reference counting, callback cleanup, etc., all look racy as heck.
+- * And why is cl_cb_set an atomic? */
+ 
+ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses)
+ {
+@@ -526,14 +524,20 @@ static void warn_no_callback_path(struct nfs4_client *clp, int reason)
+ 		(int)clp->cl_name.len, clp->cl_name.data, reason);
+ }
+ 
++static void nfsd4_mark_cb_down(struct nfs4_client *clp, int reason)
++{
++	clp->cl_cb_state = NFSD4_CB_DOWN;
++	warn_no_callback_path(clp, reason);
++}
++
+ static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata)
+ {
+ 	struct nfs4_client *clp = container_of(calldata, struct nfs4_client, cl_cb_null);
+ 
+ 	if (task->tk_status)
+-		warn_no_callback_path(clp, task->tk_status);
++		nfsd4_mark_cb_down(clp, task->tk_status);
+ 	else
+-		atomic_set(&clp->cl_cb_set, 1);
++		clp->cl_cb_state = NFSD4_CB_UP;
+ }
+ 
+ static const struct rpc_call_ops nfsd4_cb_probe_ops = {
+@@ -579,14 +583,15 @@ static void do_probe_callback(struct nfs4_client *clp)
+  */
+ void nfsd4_probe_callback(struct nfs4_client *clp)
+ {
++	/* XXX: atomicity?  Also, should we be using cl_cb_flags? */
++	clp->cl_cb_state = NFSD4_CB_UNKNOWN;
+ 	set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags);
+ 	do_probe_callback(clp);
+ }
+ 
+ void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *conn)
+ {
+-	BUG_ON(atomic_read(&clp->cl_cb_set));
+-
++	clp->cl_cb_state = NFSD4_CB_UNKNOWN;
+ 	spin_lock(&clp->cl_lock);
+ 	memcpy(&clp->cl_cb_conn, conn, sizeof(struct nfs4_cb_conn));
+ 	spin_unlock(&clp->cl_lock);
+@@ -693,8 +698,7 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
+ 		break;
+ 	default:
+ 		/* Network partition? */
+-		atomic_set(&clp->cl_cb_set, 0);
+-		warn_no_callback_path(clp, task->tk_status);
++		nfsd4_mark_cb_down(clp, task->tk_status);
+ 		if (current_rpc_client != task->tk_client) {
+ 			/* queue a callback on the new connection: */
+ 			atomic_inc(&dp->dl_count);
+@@ -707,10 +711,8 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
+ 		task->tk_status = 0;
+ 		rpc_restart_call_prepare(task);
+ 		return;
+-	} else {
+-		atomic_set(&clp->cl_cb_set, 0);
+-		warn_no_callback_path(clp, task->tk_status);
+-	}
++	} else
++		nfsd4_mark_cb_down(clp, task->tk_status);
+ }
+ 
+ static void nfsd4_cb_recall_release(void *calldata)
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 290370bc9ae7..919ad25660d6 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1071,7 +1071,7 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir,
+ 
+ 	memcpy(clp->cl_recdir, recdir, HEXDIR_LEN);
+ 	atomic_set(&clp->cl_refcount, 0);
+-	atomic_set(&clp->cl_cb_set, 0);
++	clp->cl_cb_state = NFSD4_CB_UNKNOWN;
+ 	INIT_LIST_HEAD(&clp->cl_idhash);
+ 	INIT_LIST_HEAD(&clp->cl_strhash);
+ 	INIT_LIST_HEAD(&clp->cl_openowners);
+@@ -2003,7 +2003,6 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+ 		if (!same_creds(&conf->cl_cred, &unconf->cl_cred))
+ 			status = nfserr_clid_inuse;
+ 		else {
+-			atomic_set(&conf->cl_cb_set, 0);
+ 			nfsd4_change_callback(conf, &unconf->cl_cb_conn);
+ 			nfsd4_probe_callback(conf);
+ 			expire_client(unconf);
+@@ -2633,7 +2632,8 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
+ {
+ 	struct nfs4_delegation *dp;
+ 	struct nfs4_stateowner *sop = stp->st_stateowner;
+-	int cb_up = atomic_read(&sop->so_client->cl_cb_set);
++	/* XXX: or unknown and nfsv4.1: */
++	int cb_up = (sop->so_client->cl_cb_state == NFSD4_CB_UP);
+ 	struct file_lock *fl;
+ 	int status, flag = 0;
+ 
+@@ -2823,7 +2823,7 @@ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	renew_client(clp);
+ 	status = nfserr_cb_path_down;
+ 	if (!list_empty(&clp->cl_delegations)
+-			&& !atomic_read(&clp->cl_cb_set))
++			&& clp->cl_cb_state != NFSD4_CB_UP)
+ 		goto out;
+ 	status = nfs_ok;
+ out:
+diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
+index 442f6d8e024c..32ff615c36f4 100644
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -242,7 +242,10 @@ struct nfs4_client {
+ 	unsigned long		cl_cb_flags;
+ 	struct rpc_clnt		*cl_cb_client;
+ 	u32			cl_cb_ident;
+-	atomic_t		cl_cb_set;
++#define NFSD4_CB_UP		0
++#define NFSD4_CB_UNKNOWN	1
++#define NFSD4_CB_DOWN		2
++	int			cl_cb_state;
+ 	struct nfsd4_callback	cl_cb_null;
+ 	struct nfsd4_session	*cl_cb_session;
+ 

commit dcbeaa68dbbdacbbb330a86c7fc95a28473fc209
+Author: J. Bruce Fields 
+Date:   Tue Jun 15 17:25:45 2010 -0400
+
+    nfsd4: allow backchannel recovery
+    
+    Now that we have a list of connections to choose from, we can teach the
+    callback code to just pick a suitable connection and use that, instead
+    of insisting on forever using the connection that the first
+    create_session was sent with.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index dd183af24fe6..18b740bd29ac 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -473,8 +473,7 @@ static int max_cb_time(void)
+ /* Reference counting, callback cleanup, etc., all look racy as heck.
+  * And why is cl_cb_set an atomic? */
+ 
+-static int setup_callback_client(struct nfs4_client *clp,
+-		struct nfs4_cb_conn *conn)
++static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses)
+ {
+ 	struct rpc_timeout	timeparms = {
+ 		.to_initval	= max_cb_time(),
+@@ -501,6 +500,10 @@ static int setup_callback_client(struct nfs4_client *clp,
+ 		args.protocol = XPRT_TRANSPORT_TCP;
+ 		clp->cl_cb_ident = conn->cb_ident;
+ 	} else {
++		if (!conn->cb_xprt)
++			return -EINVAL;
++		clp->cl_cb_conn.cb_xprt = conn->cb_xprt;
++		clp->cl_cb_session = ses;
+ 		args.bc_xprt = conn->cb_xprt;
+ 		args.prognumber = clp->cl_cb_session->se_cb_prog;
+ 		args.protocol = XPRT_TRANSPORT_BC_TCP;
+@@ -756,10 +759,27 @@ static void nfsd4_release_cb(struct nfsd4_callback *cb)
+ 		cb->cb_ops->rpc_release(cb);
+ }
+ 
++/* requires cl_lock: */
++static struct nfsd4_conn * __nfsd4_find_backchannel(struct nfs4_client *clp)
++{
++	struct nfsd4_session *s;
++	struct nfsd4_conn *c;
++
++	list_for_each_entry(s, &clp->cl_sessions, se_perclnt) {
++		list_for_each_entry(c, &s->se_conns, cn_persession) {
++			if (c->cn_flags & NFS4_CDFC4_BACK)
++				return c;
++		}
++	}
++	return NULL;
++}
++
+ static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
+ {
+ 	struct nfs4_cb_conn conn;
+ 	struct nfs4_client *clp = cb->cb_clp;
++	struct nfsd4_session *ses = NULL;
++	struct nfsd4_conn *c;
+ 	int err;
+ 
+ 	/*
+@@ -770,6 +790,10 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
+ 		rpc_shutdown_client(clp->cl_cb_client);
+ 		clp->cl_cb_client = NULL;
+ 	}
++	if (clp->cl_cb_conn.cb_xprt) {
++		svc_xprt_put(clp->cl_cb_conn.cb_xprt);
++		clp->cl_cb_conn.cb_xprt = NULL;
++	}
+ 	if (test_bit(NFSD4_CLIENT_KILL, &clp->cl_cb_flags))
+ 		return;
+ 	spin_lock(&clp->cl_lock);
+@@ -780,9 +804,15 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
+ 	BUG_ON(!clp->cl_cb_flags);
+ 	clear_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags);
+ 	memcpy(&conn, &cb->cb_clp->cl_cb_conn, sizeof(struct nfs4_cb_conn));
++	c = __nfsd4_find_backchannel(clp);
++	if (c) {
++		svc_xprt_get(c->cn_xprt);
++		conn.cb_xprt = c->cn_xprt;
++		ses = c->cn_session;
++	}
+ 	spin_unlock(&clp->cl_lock);
+ 
+-	err = setup_callback_client(clp, &conn);
++	err = setup_callback_client(clp, &conn, ses);
+ 	if (err)
+ 		warn_no_callback_path(clp, err);
+ }
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 956174f488a7..290370bc9ae7 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -642,6 +642,7 @@ static void nfsd4_conn_lost(struct svc_xpt_user *u)
+ 		free_conn(c);
+ 	}
+ 	spin_unlock(&clp->cl_lock);
++	/* XXX: mark callback for update, probe callback */
+ }
+ 
+ static struct nfsd4_conn *alloc_conn(struct svc_rqst *rqstp, u32 flags)
+@@ -790,16 +791,19 @@ static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct n
+ 		free_session(&new->se_ref);
+ 		return NULL;
+ 	}
+-	if (!clp->cl_cb_session && (cses->flags & SESSION4_BACK_CHAN)) {
++	if (cses->flags & SESSION4_BACK_CHAN) {
+ 		struct sockaddr *sa = svc_addr(rqstp);
+-
+-		clp->cl_cb_session = new;
+-		clp->cl_cb_conn.cb_xprt = rqstp->rq_xprt;
+-		svc_xprt_get(rqstp->rq_xprt);
++		/*
++		 * This is a little silly; with sessions there's no real
++		 * use for the callback address.  Use the peer address
++		 * as a reasonable default for now, but consider fixing
++		 * the rpc client not to require an address in the
++		 * future:
++		 */
+ 		rpc_copy_addr((struct sockaddr *)&clp->cl_cb_conn.cb_addr, sa);
+ 		clp->cl_cb_conn.cb_addrlen = svc_addr_len(sa);
+-		nfsd4_probe_callback(clp);
+ 	}
++	nfsd4_probe_callback(clp);
+ 	return new;
+ }
+ 

commit 4c6493785a1ea9c3b3522f199760a90a30e1626c
+Author: J. Bruce Fields 
+Date:   Tue Jun 15 14:22:37 2010 -0400
+
+    nfsd4: modify session list under cl_lock
+    
+    We want to traverse this from the callback code.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index b583e4e800ab..3cf9900d5f32 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -771,7 +771,9 @@ static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct n
+ 	idx = hash_sessionid(&new->se_sessionid);
+ 	spin_lock(&client_lock);
+ 	list_add(&new->se_hash, &sessionid_hashtbl[idx]);
++	spin_lock(&clp->cl_lock);
+ 	list_add(&new->se_perclnt, &clp->cl_sessions);
++	spin_unlock(&clp->cl_lock);
+ 	spin_unlock(&client_lock);
+ 
+ 	status = nfsd4_new_conn(rqstp, new);
+@@ -819,7 +821,9 @@ static void
+ unhash_session(struct nfsd4_session *ses)
+ {
+ 	list_del(&ses->se_hash);
++	spin_lock(&ses->se_client->cl_lock);
+ 	list_del(&ses->se_perclnt);
++	spin_unlock(&ses->se_client->cl_lock);
+ }
+ 
+ /* must be called under the client_lock */
+@@ -925,8 +929,10 @@ unhash_client_locked(struct nfs4_client *clp)
+ 
+ 	mark_client_expired(clp);
+ 	list_del(&clp->cl_lru);
++	spin_lock(&clp->cl_lock);
+ 	list_for_each_entry(ses, &clp->cl_sessions, se_perclnt)
+ 		list_del_init(&ses->se_hash);
++	spin_unlock(&clp->cl_lock);
+ }
+ 
+ static void

commit b10e30f6559978e3c8ca2a70c1cb35d6680a4021
+Author: J. Bruce Fields 
+Date:   Tue Dec 14 15:05:13 2010 +0000
+
+    lockd: reorganize nlm_host_rebooted
+    
+    Minor reorganization; no change in behavior.  This will save some
+    duplicated code after we split the client and server host caches.
+    
+    Signed-off-by: J. Bruce Fields 
+    [ cel: Forward-ported to 2.6.37 ]
+    Signed-off-by: Chuck Lever 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/lockd/host.c b/fs/lockd/host.c
+index cada3a12d557..2dbf1392acfc 100644
+--- a/fs/lockd/host.c
++++ b/fs/lockd/host.c
+@@ -441,6 +441,31 @@ void nlm_release_host(struct nlm_host *host)
+ 	}
+ }
+ 
++static struct nlm_host *next_host_state(struct hlist_head *cache,
++					struct nsm_handle *nsm,
++					const struct nlm_reboot *info)
++{
++	struct nlm_host *host = NULL;
++	struct hlist_head *chain;
++	struct hlist_node *pos;
++
++	mutex_lock(&nlm_host_mutex);
++	for_each_host(host, pos, chain, cache) {
++		if (host->h_nsmhandle == nsm
++		    && host->h_nsmstate != info->state) {
++			host->h_nsmstate = info->state;
++			host->h_state++;
++
++			nlm_get_host(host);
++			mutex_unlock(&nlm_host_mutex);
++			goto out;
++		}
++	}
++out:
++	mutex_unlock(&nlm_host_mutex);
++	return host;
++}
++
+ /**
+  * nlm_host_rebooted - Release all resources held by rebooted host
+  * @info: pointer to decoded results of NLM_SM_NOTIFY call
+@@ -450,8 +475,6 @@ void nlm_release_host(struct nlm_host *host)
+  */
+ void nlm_host_rebooted(const struct nlm_reboot *info)
+ {
+-	struct hlist_head *chain;
+-	struct hlist_node *pos;
+ 	struct nsm_handle *nsm;
+ 	struct nlm_host	*host;
+ 
+@@ -464,30 +487,17 @@ void nlm_host_rebooted(const struct nlm_reboot *info)
+ 	 * lock for this.
+ 	 * To avoid processing a host several times, we match the nsmstate.
+ 	 */
+-again:	mutex_lock(&nlm_host_mutex);
+-	for_each_host(host, pos, chain, nlm_hosts) {
+-		if (host->h_nsmhandle == nsm
+-		 && host->h_nsmstate != info->state) {
+-			host->h_nsmstate = info->state;
+-			host->h_state++;
+-
+-			nlm_get_host(host);
+-			mutex_unlock(&nlm_host_mutex);
+-
+-			if (host->h_server) {
+-				/* We're server for this guy, just ditch
+-				 * all the locks he held. */
+-				nlmsvc_free_host_resources(host);
+-			} else {
+-				/* He's the server, initiate lock recovery. */
+-				nlmclnt_recovery(host);
+-			}
+-
+-			nlm_release_host(host);
+-			goto again;
++	while ((host = next_host_state(nlm_hosts, nsm, info)) != NULL) {
++		if (host->h_server) {
++			/* We're server for this guy, just ditch
++			 * all the locks he held. */
++			nlmsvc_free_host_resources(host);
++		} else {
++			/* He's the server, initiate lock recovery. */
++			nlmclnt_recovery(host);
+ 		}
++		nlm_release_host(host);
+ 	}
+-	mutex_unlock(&nlm_host_mutex);
+ 	nsm_release(nsm);
+ }
+ 

commit b113746888c260a02f6ae1e92b0b9ef7e9c38993
+Author: J. Bruce Fields 
+Date:   Tue Dec 14 15:05:03 2010 +0000
+
+    lockd: define host_for_each{_safe} macros
+    
+    We've got a lot of loops like this, and I find them a little easier to
+    read with the macros.  More such loops are coming.
+    
+    Signed-off-by: J. Bruce Fields 
+    [ cel: Forward-ported to 2.6.37 ]
+    Signed-off-by: Chuck Lever 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/lockd/host.c b/fs/lockd/host.c
+index ed0c59fe23ce..cada3a12d557 100644
+--- a/fs/lockd/host.c
++++ b/fs/lockd/host.c
+@@ -26,6 +26,18 @@
+ #define NLM_HOST_COLLECT	(120 * HZ)
+ 
+ static struct hlist_head	nlm_hosts[NLM_HOST_NRHASH];
++
++#define for_each_host(host, pos, chain, table) \
++	for ((chain) = (table); \
++	     (chain) < (table) + NLM_HOST_NRHASH; ++(chain)) \
++		hlist_for_each_entry((host), (pos), (chain), h_hash)
++
++#define for_each_host_safe(host, pos, next, chain, table) \
++	for ((chain) = (table); \
++	     (chain) < (table) + NLM_HOST_NRHASH; ++(chain)) \
++		hlist_for_each_entry_safe((host), (pos), (next), \
++						(chain), h_hash)
++
+ static unsigned long		next_gc;
+ static int			nrhosts;
+ static DEFINE_MUTEX(nlm_host_mutex);
+@@ -453,28 +465,26 @@ void nlm_host_rebooted(const struct nlm_reboot *info)
+ 	 * To avoid processing a host several times, we match the nsmstate.
+ 	 */
+ again:	mutex_lock(&nlm_host_mutex);
+-	for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) {
+-		hlist_for_each_entry(host, pos, chain, h_hash) {
+-			if (host->h_nsmhandle == nsm
+-			 && host->h_nsmstate != info->state) {
+-				host->h_nsmstate = info->state;
+-				host->h_state++;
+-
+-				nlm_get_host(host);
+-				mutex_unlock(&nlm_host_mutex);
+-
+-				if (host->h_server) {
+-					/* We're server for this guy, just ditch
+-					 * all the locks he held. */
+-					nlmsvc_free_host_resources(host);
+-				} else {
+-					/* He's the server, initiate lock recovery. */
+-					nlmclnt_recovery(host);
+-				}
+-
+-				nlm_release_host(host);
+-				goto again;
++	for_each_host(host, pos, chain, nlm_hosts) {
++		if (host->h_nsmhandle == nsm
++		 && host->h_nsmstate != info->state) {
++			host->h_nsmstate = info->state;
++			host->h_state++;
++
++			nlm_get_host(host);
++			mutex_unlock(&nlm_host_mutex);
++
++			if (host->h_server) {
++				/* We're server for this guy, just ditch
++				 * all the locks he held. */
++				nlmsvc_free_host_resources(host);
++			} else {
++				/* He's the server, initiate lock recovery. */
++				nlmclnt_recovery(host);
+ 			}
++
++			nlm_release_host(host);
++			goto again;
+ 		}
+ 	}
+ 	mutex_unlock(&nlm_host_mutex);
+@@ -497,13 +507,11 @@ nlm_shutdown_hosts(void)
+ 
+ 	/* First, make all hosts eligible for gc */
+ 	dprintk("lockd: nuking all hosts...\n");
+-	for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) {
+-		hlist_for_each_entry(host, pos, chain, h_hash) {
+-			host->h_expires = jiffies - 1;
+-			if (host->h_rpcclnt) {
+-				rpc_shutdown_client(host->h_rpcclnt);
+-				host->h_rpcclnt = NULL;
+-			}
++	for_each_host(host, pos, chain, nlm_hosts) {
++		host->h_expires = jiffies - 1;
++		if (host->h_rpcclnt) {
++			rpc_shutdown_client(host->h_rpcclnt);
++			host->h_rpcclnt = NULL;
+ 		}
+ 	}
+ 
+@@ -515,12 +523,10 @@ nlm_shutdown_hosts(void)
+ 	if (nrhosts) {
+ 		printk(KERN_WARNING "lockd: couldn't shutdown host module!\n");
+ 		dprintk("lockd: %d hosts left:\n", nrhosts);
+-		for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) {
+-			hlist_for_each_entry(host, pos, chain, h_hash) {
+-				dprintk("       %s (cnt %d use %d exp %ld)\n",
+-					host->h_name, atomic_read(&host->h_count),
+-					host->h_inuse, host->h_expires);
+-			}
++		for_each_host(host, pos, chain, nlm_hosts) {
++			dprintk("       %s (cnt %d use %d exp %ld)\n",
++				host->h_name, atomic_read(&host->h_count),
++				host->h_inuse, host->h_expires);
+ 		}
+ 	}
+ }
+@@ -538,29 +544,26 @@ nlm_gc_hosts(void)
+ 	struct nlm_host	*host;
+ 
+ 	dprintk("lockd: host garbage collection\n");
+-	for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) {
+-		hlist_for_each_entry(host, pos, chain, h_hash)
+-			host->h_inuse = 0;
+-	}
++	for_each_host(host, pos, chain, nlm_hosts)
++		host->h_inuse = 0;
+ 
+ 	/* Mark all hosts that hold locks, blocks or shares */
+ 	nlmsvc_mark_resources();
+ 
+-	for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) {
+-		hlist_for_each_entry_safe(host, pos, next, chain, h_hash) {
+-			if (atomic_read(&host->h_count) || host->h_inuse
+-			 || time_before(jiffies, host->h_expires)) {
+-				dprintk("nlm_gc_hosts skipping %s (cnt %d use %d exp %ld)\n",
+-					host->h_name, atomic_read(&host->h_count),
+-					host->h_inuse, host->h_expires);
+-				continue;
+-			}
+-			dprintk("lockd: delete host %s\n", host->h_name);
+-			hlist_del_init(&host->h_hash);
+-
+-			nlm_destroy_host(host);
+-			nrhosts--;
++	for_each_host_safe(host, pos, next, chain, nlm_hosts) {
++		if (atomic_read(&host->h_count) || host->h_inuse
++		 || time_before(jiffies, host->h_expires)) {
++			dprintk("nlm_gc_hosts skipping %s "
++				"(cnt %d use %d exp %ld)\n",
++				host->h_name, atomic_read(&host->h_count),
++				host->h_inuse, host->h_expires);
++			continue;
+ 		}
++		dprintk("lockd: delete host %s\n", host->h_name);
++		hlist_del_init(&host->h_hash);
++
++		nlm_destroy_host(host);
++		nrhosts--;
+ 	}
+ 
+ 	next_gc = jiffies + NLM_HOST_COLLECT;

commit d29c374cd20de620898d2936396048518809ae24
+Author: J. Bruce Fields 
+Date:   Tue Jun 15 17:34:11 2010 -0400
+
+    nfsd4: track backchannel connections
+    
+    We need to keep track of which connections are available for use with
+    the backchannel, which for the forechannel, and which for both.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 7e817d13cd82..c470cb78c6c1 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -644,7 +644,7 @@ static void nfsd4_conn_lost(struct svc_xpt_user *u)
+ 	spin_unlock(&clp->cl_lock);
+ }
+ 
+-static struct nfsd4_conn *alloc_conn(struct svc_rqst *rqstp)
++static struct nfsd4_conn *alloc_conn(struct svc_rqst *rqstp, u32 flags)
+ {
+ 	struct nfsd4_conn *conn;
+ 
+@@ -653,7 +653,7 @@ static struct nfsd4_conn *alloc_conn(struct svc_rqst *rqstp)
+ 		return NULL;
+ 	svc_xprt_get(rqstp->rq_xprt);
+ 	conn->cn_xprt = rqstp->rq_xprt;
+-	conn->cn_flags = NFS4_CDFC4_FORE;
++	conn->cn_flags = flags;
+ 	INIT_LIST_HEAD(&conn->cn_xpt_user.list);
+ 	return conn;
+ }
+@@ -682,8 +682,11 @@ static void nfsd4_register_conn(struct nfsd4_conn *conn)
+ static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses)
+ {
+ 	struct nfsd4_conn *conn;
++	u32 flags = NFS4_CDFC4_FORE;
+ 
+-	conn = alloc_conn(rqstp);
++	if (ses->se_flags & SESSION4_BACK_CHAN)
++		flags |= NFS4_CDFC4_BACK;
++	conn = alloc_conn(rqstp, flags);
+ 	if (!conn)
+ 		return nfserr_jukebox;
+ 	nfsd4_hash_conn(conn, ses);
+@@ -1640,7 +1643,7 @@ static void nfsd4_sequence_check_conn(struct svc_rqst *rqstp, struct nfsd4_sessi
+ 	if (c)
+ 		return;
+ 
+-	new = alloc_conn(rqstp);
++	new = alloc_conn(rqstp, NFS4_CDFC4_FORE);
+ 
+ 	spin_lock(&clp->cl_lock);
+ 	c = __nfsd4_find_conn(rqstp, ses);

commit ac7c46f29a44f6d7f6d2e36dc874c0b7056acad2
+Author: J. Bruce Fields 
+Date:   Mon Jun 14 19:01:57 2010 -0400
+
+    nfsd4: make backchannel sequence number per-session
+    
+    Currently we don't deal well with a client that has multiple sessions
+    associated with it (even simultaneously, or serially over the lifetime
+    of the client).
+    
+    In particular, we don't attempt to keep the backchannel running after
+    the original session diseappears.
+    
+    We will fix that soon.
+    
+    Once we do that, we need the slot sequence number to be per-session;
+    otherwise, for example, we cannot correctly handle a case like this:
+    
+            - All session 1 connections are lost.
+            - The client creates session 2.  We use it for the backchannel
+              (since it's the only working choice).
+            - The client gives us a new connection to use with session 1.
+            - The client destroys session 2.
+    
+    At this point our only choice is to go back to using session 1.  When we
+    do so we must use the sequence number that is next for session 1.  We
+    therefore need to maintain multiple sequence number streams.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 78ac779c09ff..5df9dda47bf4 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -260,7 +260,7 @@ encode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_callback *cb,
+ 
+ 	WRITE32(OP_CB_SEQUENCE);
+ 	WRITEMEM(ses->se_sessionid.data, NFS4_MAX_SESSIONID_LEN);
+-	WRITE32(cb->cb_clp->cl_cb_seq_nr);
++	WRITE32(ses->se_cb_seq_nr);
+ 	WRITE32(0);		/* slotid, always 0 */
+ 	WRITE32(0);		/* highest slotid always 0 */
+ 	WRITE32(0);		/* cachethis always 0 */
+@@ -369,7 +369,7 @@ decode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_callback *cb,
+ 		goto out;
+ 	}
+ 	READ32(dummy);
+-	if (dummy != cb->cb_clp->cl_cb_seq_nr) {
++	if (dummy != ses->se_cb_seq_nr) {
+ 		dprintk("%s Invalid sequence number\n", __func__);
+ 		goto out;
+ 	}
+@@ -643,11 +643,11 @@ static void nfsd4_cb_done(struct rpc_task *task, void *calldata)
+ 
+ 	if (clp->cl_cb_conn.cb_minorversion) {
+ 		/* No need for lock, access serialized in nfsd4_cb_prepare */
+-		++clp->cl_cb_seq_nr;
++		++clp->cl_cb_session->se_cb_seq_nr;
+ 		clear_bit(0, &clp->cl_cb_slot_busy);
+ 		rpc_wake_up_next(&clp->cl_cb_waitq);
+ 		dprintk("%s: freed slot, new seqid=%d\n", __func__,
+-			clp->cl_cb_seq_nr);
++			clp->cl_cb_session->se_cb_seq_nr);
+ 
+ 		/* We're done looking into the sequence information */
+ 		task->tk_msg.rpc_resp = NULL;
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index c942511f73e6..6367c445d015 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -725,8 +725,7 @@ void free_session(struct kref *kref)
+ 	kfree(ses);
+ }
+ 
+-
+-static __be32 alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp, struct nfsd4_create_session *cses)
++static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp, struct nfsd4_create_session *cses)
+ {
+ 	struct nfsd4_session *new;
+ 	struct nfsd4_channel_attrs *fchan = &cses->fore_channel;
+@@ -747,7 +746,7 @@ static __be32 alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp
+ 	new = alloc_session(slotsize, numslots);
+ 	if (!new) {
+ 		nfsd4_put_drc_mem(slotsize, fchan->maxreqs);
+-		return nfserr_jukebox;
++		return NULL;
+ 	}
+ 	init_forechannel_attrs(&new->se_fchannel, fchan, numslots, slotsize);
+ 
+@@ -756,6 +755,7 @@ static __be32 alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp
+ 
+ 	INIT_LIST_HEAD(&new->se_conns);
+ 
++	new->se_cb_seq_nr = 1;
+ 	new->se_flags = cses->flags;
+ 	kref_init(&new->se_ref);
+ 	idx = hash_sessionid(&new->se_sessionid);
+@@ -765,9 +765,10 @@ static __be32 alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp
+ 	spin_unlock(&client_lock);
+ 
+ 	status = nfsd4_new_conn(rqstp, new);
++	/* whoops: benny points out, status is ignored! (err, or bogus) */
+ 	if (status) {
+ 		free_session(&new->se_ref);
+-		return nfserr_jukebox;
++		return NULL;
+ 	}
+ 	if (!clp->cl_cb_session && (cses->flags & SESSION4_BACK_CHAN)) {
+ 		struct sockaddr *sa = svc_addr(rqstp);
+@@ -779,10 +780,9 @@ static __be32 alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp
+ 		clp->cl_cb_conn.cb_addrlen = svc_addr_len(sa);
+ 		clp->cl_cb_conn.cb_minorversion = 1;
+ 		clp->cl_cb_conn.cb_prog = cses->callback_prog;
+-		clp->cl_cb_seq_nr = 1;
+ 		nfsd4_probe_callback(clp, &clp->cl_cb_conn);
+ 	}
+-	return nfs_ok;
++	return new;
+ }
+ 
+ /* caller must hold client_lock */
+@@ -1485,6 +1485,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
+ {
+ 	struct sockaddr *sa = svc_addr(rqstp);
+ 	struct nfs4_client *conf, *unconf;
++	struct nfsd4_session *new;
+ 	struct nfsd4_clid_slot *cs_slot = NULL;
+ 	int status = 0;
+ 
+@@ -1538,11 +1539,12 @@ nfsd4_create_session(struct svc_rqst *rqstp,
+ 	cr_ses->flags &= ~SESSION4_PERSIST;
+ 	cr_ses->flags &= ~SESSION4_RDMA;
+ 
+-	status = alloc_init_session(rqstp, conf, cr_ses);
+-	if (status)
++	status = nfserr_jukebox;
++	new = alloc_init_session(rqstp, conf, cr_ses);
++	if (!new)
+ 		goto out;
+-
+-	memcpy(cr_ses->sessionid.data, conf->cl_cb_session->se_sessionid.data,
++	status = nfs_ok;
++	memcpy(cr_ses->sessionid.data, new->se_sessionid.data,
+ 	       NFS4_MAX_SESSIONID_LEN);
+ 	cr_ses->seqid = cs_slot->sl_seqid;
+ 
+diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
+index cdce26ad50b5..7f5b2671ef18 100644
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -172,6 +172,7 @@ struct nfsd4_session {
+ 	struct nfsd4_channel_attrs se_fchannel;
+ 	struct nfsd4_channel_attrs se_bchannel;
+ 	struct list_head	se_conns;
++	u32			se_cb_seq_nr;
+ 	struct nfsd4_slot	*se_slots[];	/* forward channel slots */
+ };
+ 
+@@ -249,7 +250,6 @@ struct nfs4_client {
+ 	/* for nfs41 callbacks */
+ 	/* We currently support a single back channel with a single slot */
+ 	unsigned long		cl_cb_slot_busy;
+-	u32			cl_cb_seq_nr;
+ 	struct rpc_wait_queue	cl_cb_waitq;	/* backchannel callers may */
+ 						/* wait here for slots */
+ };

commit 90c8145bb6fe1d9e0a808de6a701748967588bbd
+Author: J. Bruce Fields 
+Date:   Mon Jun 14 17:49:37 2010 -0400
+
+    nfsd4: use client pointer to backchannel session
+    
+    Instead of copying the sessionid, use the new cl_cb_session pointer,
+    which indicates which session we're using for the backchannel.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index a269dbeff150..78ac779c09ff 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -251,6 +251,7 @@ encode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_callback *cb,
+ 		   struct nfs4_cb_compound_hdr *hdr)
+ {
+ 	__be32 *p;
++	struct nfsd4_session *ses = cb->cb_clp->cl_cb_session;
+ 
+ 	if (hdr->minorversion == 0)
+ 		return;
+@@ -258,7 +259,7 @@ encode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_callback *cb,
+ 	RESERVE_SPACE(1 + NFS4_MAX_SESSIONID_LEN + 20);
+ 
+ 	WRITE32(OP_CB_SEQUENCE);
+-	WRITEMEM(cb->cb_clp->cl_sessionid.data, NFS4_MAX_SESSIONID_LEN);
++	WRITEMEM(ses->se_sessionid.data, NFS4_MAX_SESSIONID_LEN);
+ 	WRITE32(cb->cb_clp->cl_cb_seq_nr);
+ 	WRITE32(0);		/* slotid, always 0 */
+ 	WRITE32(0);		/* highest slotid always 0 */
+@@ -341,6 +342,7 @@ static int
+ decode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_callback *cb,
+ 		   struct rpc_rqst *rqstp)
+ {
++	struct nfsd4_session *ses = cb->cb_clp->cl_cb_session;
+ 	struct nfs4_sessionid id;
+ 	int status;
+ 	u32 dummy;
+@@ -362,8 +364,7 @@ decode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_callback *cb,
+ 	READ_BUF(NFS4_MAX_SESSIONID_LEN + 16);
+ 	memcpy(id.data, p, NFS4_MAX_SESSIONID_LEN);
+ 	p += XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN);
+-	if (memcmp(id.data, cb->cb_clp->cl_sessionid.data,
+-		   NFS4_MAX_SESSIONID_LEN)) {
++	if (memcmp(id.data, ses->se_sessionid.data, NFS4_MAX_SESSIONID_LEN)) {
+ 		dprintk("%s Invalid session id\n", __func__);
+ 		goto out;
+ 	}
+@@ -587,7 +588,7 @@ void nfsd4_probe_callback(struct nfs4_client *clp, struct nfs4_cb_conn *conn)
+ static int nfsd41_cb_setup_sequence(struct nfs4_client *clp,
+ 		struct rpc_task *task)
+ {
+-	u32 *ptr = (u32 *)clp->cl_sessionid.data;
++	u32 *ptr = (u32 *)clp->cl_cb_session->se_sessionid.data;
+ 	int status = 0;
+ 
+ 	dprintk("%s: %u:%u:%u:%u\n", __func__,
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index db5d8c8537ed..c942511f73e6 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -753,8 +753,6 @@ static __be32 alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp
+ 
+ 	new->se_client = clp;
+ 	gen_sessionid(new);
+-	memcpy(clp->cl_sessionid.data, new->se_sessionid.data,
+-	       NFS4_MAX_SESSIONID_LEN);
+ 
+ 	INIT_LIST_HEAD(&new->se_conns);
+ 
+@@ -1544,7 +1542,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
+ 	if (status)
+ 		goto out;
+ 
+-	memcpy(cr_ses->sessionid.data, conf->cl_sessionid.data,
++	memcpy(cr_ses->sessionid.data, conf->cl_cb_session->se_sessionid.data,
+ 	       NFS4_MAX_SESSIONID_LEN);
+ 	cr_ses->seqid = cs_slot->sl_seqid;
+ 
+diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
+index 6e63c1d272bf..cdce26ad50b5 100644
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -243,7 +243,6 @@ struct nfs4_client {
+ 	struct list_head	cl_sessions;
+ 	struct nfsd4_clid_slot	cl_cs_slot;	/* create_session slot */
+ 	u32			cl_exchange_flags;
+-	struct nfs4_sessionid	cl_sessionid;
+ 	/* number of rpc's in progress over an associated session: */
+ 	atomic_t		cl_refcount;
+ 

commit edd76786633a3145661c7a90c9baccae8e3c9e84
+Author: J. Bruce Fields 
+Date:   Mon Jun 14 22:26:31 2010 -0400
+
+    nfsd4: move callback setup into session init code
+    
+    The backchannel should  be associated with a session, it isn't really
+    global to the client.
+    
+    We do, however, want a pointer global to the client which tracks which
+    session we're currently using for client-based callbacks.
+    
+    This is a first step in that direction; for now, just reshuffling of
+    code with no significant change in behavior.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 7f1282859cd6..db5d8c8537ed 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -771,6 +771,19 @@ static __be32 alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp
+ 		free_session(&new->se_ref);
+ 		return nfserr_jukebox;
+ 	}
++	if (!clp->cl_cb_session && (cses->flags & SESSION4_BACK_CHAN)) {
++		struct sockaddr *sa = svc_addr(rqstp);
++
++		clp->cl_cb_session = new;
++		clp->cl_cb_conn.cb_xprt = rqstp->rq_xprt;
++		svc_xprt_get(rqstp->rq_xprt);
++		rpc_copy_addr((struct sockaddr *)&clp->cl_cb_conn.cb_addr, sa);
++		clp->cl_cb_conn.cb_addrlen = svc_addr_len(sa);
++		clp->cl_cb_conn.cb_minorversion = 1;
++		clp->cl_cb_conn.cb_prog = cses->callback_prog;
++		clp->cl_cb_seq_nr = 1;
++		nfsd4_probe_callback(clp, &clp->cl_cb_conn);
++	}
+ 	return nfs_ok;
+ }
+ 
+@@ -1045,7 +1058,7 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir,
+ 	clp->cl_flavor = rqstp->rq_flavor;
+ 	copy_cred(&clp->cl_cred, &rqstp->rq_cred);
+ 	gen_confirm(clp);
+-
++	clp->cl_cb_session = NULL;
+ 	return clp;
+ }
+ 
+@@ -1515,20 +1528,6 @@ nfsd4_create_session(struct svc_rqst *rqstp,
+ 
+ 		cs_slot->sl_seqid++; /* from 0 to 1 */
+ 		move_to_confirmed(unconf);
+-
+-		if (cr_ses->flags & SESSION4_BACK_CHAN) {
+-			unconf->cl_cb_conn.cb_xprt = rqstp->rq_xprt;
+-			svc_xprt_get(rqstp->rq_xprt);
+-			rpc_copy_addr(
+-				(struct sockaddr *)&unconf->cl_cb_conn.cb_addr,
+-				sa);
+-			unconf->cl_cb_conn.cb_addrlen = svc_addr_len(sa);
+-			unconf->cl_cb_conn.cb_minorversion =
+-				cstate->minorversion;
+-			unconf->cl_cb_conn.cb_prog = cr_ses->callback_prog;
+-			unconf->cl_cb_seq_nr = 1;
+-			nfsd4_probe_callback(unconf, &unconf->cl_cb_conn);
+-		}
+ 		conf = unconf;
+ 	} else {
+ 		status = nfserr_stale_clientid;
+diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
+index 8d5e2370cce0..6e63c1d272bf 100644
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -234,6 +234,7 @@ struct nfs4_client {
+ 	u32			cl_cb_ident;
+ 	atomic_t		cl_cb_set;
+ 	struct nfsd4_callback	cl_cb_null;
++	struct nfsd4_session	*cl_cb_session;
+ 
+ 	/* for all client information that callback code might need: */
+ 	spinlock_t		cl_lock;

commit 19cf5c026f3ee06027523e59478e3fa54f573e5e
+Author: J. Bruce Fields 
+Date:   Sun Jun 6 18:37:16 2010 -0400
+
+    nfsd4: use callbacks on svc_xprt_deletion
+    
+    Remove connections from the list when they go down.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index c7c1a7afa197..b7e9793b58f5 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -625,6 +625,25 @@ static void init_forechannel_attrs(struct nfsd4_channel_attrs *new, struct nfsd4
+ 	new->maxops = min_t(u32, req->maxops, NFSD_MAX_OPS_PER_COMPOUND);
+ }
+ 
++static void free_conn(struct nfsd4_conn *c)
++{
++	svc_xprt_put(c->cn_xprt);
++	kfree(c);
++}
++
++static void nfsd4_conn_lost(struct svc_xpt_user *u)
++{
++	struct nfsd4_conn *c = container_of(u, struct nfsd4_conn, cn_xpt_user);
++	struct nfs4_client *clp = c->cn_session->se_client;
++
++	spin_lock(&clp->cl_lock);
++	if (!list_empty(&c->cn_persession)) {
++		list_del(&c->cn_persession);
++		free_conn(c);
++	}
++	spin_unlock(&clp->cl_lock);
++}
++
+ static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses)
+ {
+ 	struct nfs4_client *clp = ses->se_client;
+@@ -636,18 +655,34 @@ static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses)
+ 	conn->cn_flags = NFS4_CDFC4_FORE;
+ 	svc_xprt_get(rqstp->rq_xprt);
+ 	conn->cn_xprt = rqstp->rq_xprt;
++	conn->cn_session = ses;
+ 
+ 	spin_lock(&clp->cl_lock);
+ 	list_add(&conn->cn_persession, &ses->se_conns);
+ 	spin_unlock(&clp->cl_lock);
+ 
++	conn->cn_xpt_user.callback = nfsd4_conn_lost;
++	register_xpt_user(rqstp->rq_xprt, &conn->cn_xpt_user);
+ 	return nfs_ok;
+ }
+ 
+-static void free_conn(struct nfsd4_conn *c)
++static void nfsd4_del_conns(struct nfsd4_session *s)
+ {
+-	svc_xprt_put(c->cn_xprt);
+-	kfree(c);
++	struct nfs4_client *clp = s->se_client;
++	struct nfsd4_conn *c;
++
++	spin_lock(&clp->cl_lock);
++	while (!list_empty(&s->se_conns)) {
++		c = list_first_entry(&s->se_conns, struct nfsd4_conn, cn_persession);
++		list_del_init(&c->cn_persession);
++		spin_unlock(&clp->cl_lock);
++
++		unregister_xpt_user(c->cn_xprt, &c->cn_xpt_user);
++		free_conn(c);
++
++		spin_lock(&clp->cl_lock);
++	}
++	spin_unlock(&clp->cl_lock);
+ }
+ 
+ void free_session(struct kref *kref)
+@@ -656,12 +691,7 @@ void free_session(struct kref *kref)
+ 	int mem;
+ 
+ 	ses = container_of(kref, struct nfsd4_session, se_ref);
+-	while (!list_empty(&ses->se_conns)) {
+-		struct nfsd4_conn *c;
+-		c = list_first_entry(&ses->se_conns, struct nfsd4_conn, cn_persession);
+-		list_del(&c->cn_persession);
+-		free_conn(c);
+-	}
++	nfsd4_del_conns(ses);
+ 	spin_lock(&nfsd_drc_lock);
+ 	mem = ses->se_fchannel.maxreqs * slot_bytes(&ses->se_fchannel);
+ 	nfsd_drc_mem_used -= mem;
+@@ -1552,6 +1582,9 @@ nfsd4_destroy_session(struct svc_rqst *r,
+ 	/* wait for callbacks */
+ 	nfsd4_shutdown_callback(ses->se_client);
+ 	nfs4_unlock_state();
++
++	nfsd4_del_conns(ses);
++
+ 	nfsd4_put_session(ses);
+ 	status = nfs_ok;
+ out:
+diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
+index 29413c2ed270..8d5e2370cce0 100644
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -35,6 +35,7 @@
+ #ifndef _NFSD4_STATE_H
+ #define _NFSD4_STATE_H
+ 
++#include 
+ #include 
+ #include "nfsfh.h"
+ 
+@@ -155,6 +156,8 @@ struct nfsd4_clid_slot {
+ struct nfsd4_conn {
+ 	struct list_head cn_persession;
+ 	struct svc_xprt *cn_xprt;
++	struct svc_xpt_user cn_xpt_user;
++	struct nfsd4_session *cn_session;
+ /* CDFC4_FORE, CDFC4_BACK: */
+ 	unsigned char cn_flags;
+ };

commit edc7a894034acb4c7ff8305716ca5df8aaf8e642
+Author: J. Bruce Fields 
+Date:   Mon Mar 22 15:37:17 2010 -0400
+
+    nfsd: provide callbacks on svc_xprt deletion
+    
+    NFSv4.1 needs warning when a client tcp connection goes down, if that
+    connection is being used as a backchannel, so that it can warn the
+    client that it has lost the backchannel connection.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/include/linux/sunrpc/svc_xprt.h b/include/linux/sunrpc/svc_xprt.h
+index bb182979569e..bbdb680ffbe9 100644
+--- a/include/linux/sunrpc/svc_xprt.h
++++ b/include/linux/sunrpc/svc_xprt.h
+@@ -33,6 +33,16 @@ struct svc_xprt_class {
+ 	u32			xcl_max_payload;
+ };
+ 
++/*
++ * This is embedded in an object that wants a callback before deleting
++ * an xprt; intended for use by NFSv4.1, which needs to know when a
++ * client's tcp connection (and hence possibly a backchannel) goes away.
++ */
++struct svc_xpt_user {
++	struct list_head list;
++	void (*callback)(struct svc_xpt_user *);
++};
++
+ struct svc_xprt {
+ 	struct svc_xprt_class	*xpt_class;
+ 	struct svc_xprt_ops	*xpt_ops;
+@@ -67,10 +77,25 @@ struct svc_xprt {
+ 	struct sockaddr_storage	xpt_remote;	/* remote peer's address */
+ 	size_t			xpt_remotelen;	/* length of address */
+ 	struct rpc_wait_queue	xpt_bc_pending;	/* backchannel wait queue */
++	struct list_head	xpt_users;	/* callbacks on free */
+ 
+ 	struct net		*xpt_net;
+ };
+ 
++static inline void register_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u)
++{
++	spin_lock(&xpt->xpt_lock);
++	list_add(&u->list, &xpt->xpt_users);
++	spin_unlock(&xpt->xpt_lock);
++}
++
++static inline void unregister_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u)
++{
++	spin_lock(&xpt->xpt_lock);
++	list_del_init(&u->list);
++	spin_unlock(&xpt->xpt_lock);
++}
++
+ int	svc_reg_xprt_class(struct svc_xprt_class *);
+ void	svc_unreg_xprt_class(struct svc_xprt_class *);
+ void	svc_xprt_init(struct svc_xprt_class *, struct svc_xprt *,
+diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
+index 678b6ee4da7b..12025eedc781 100644
+--- a/net/sunrpc/svc_xprt.c
++++ b/net/sunrpc/svc_xprt.c
+@@ -156,6 +156,7 @@ void svc_xprt_init(struct svc_xprt_class *xcl, struct svc_xprt *xprt,
+ 	INIT_LIST_HEAD(&xprt->xpt_list);
+ 	INIT_LIST_HEAD(&xprt->xpt_ready);
+ 	INIT_LIST_HEAD(&xprt->xpt_deferred);
++	INIT_LIST_HEAD(&xprt->xpt_users);
+ 	mutex_init(&xprt->xpt_mutex);
+ 	spin_lock_init(&xprt->xpt_lock);
+ 	set_bit(XPT_BUSY, &xprt->xpt_flags);
+@@ -881,6 +882,19 @@ static void svc_age_temp_xprts(unsigned long closure)
+ 	mod_timer(&serv->sv_temptimer, jiffies + svc_conn_age_period * HZ);
+ }
+ 
++static void call_xpt_users(struct svc_xprt *xprt)
++{
++	struct svc_xpt_user *u;
++
++	spin_lock(&xprt->xpt_lock);
++	while (!list_empty(&xprt->xpt_users)) {
++		u = list_first_entry(&xprt->xpt_users, struct svc_xpt_user, list);
++		list_del(&u->list);
++		u->callback(u);
++	}
++	spin_unlock(&xprt->xpt_lock);
++}
++
+ /*
+  * Remove a dead transport
+  */
+@@ -913,6 +927,7 @@ void svc_delete_xprt(struct svc_xprt *xprt)
+ 	while ((dr = svc_deferred_dequeue(xprt)) != NULL)
+ 		kfree(dr);
+ 
++	call_xpt_users(xprt);
+ 	svc_xprt_put(xprt);
+ }
+ 

commit c7662518c781edc8059cd9737d18168154bf7510
+Author: J. Bruce Fields 
+Date:   Sun Jun 6 18:12:14 2010 -0400
+
+    nfsd4: keep per-session list of connections
+    
+    The spec requires us in various places to keep track of the connections
+    associated with each session.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index f86476c23b2f..c7c1a7afa197 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -625,11 +625,58 @@ static void init_forechannel_attrs(struct nfsd4_channel_attrs *new, struct nfsd4
+ 	new->maxops = min_t(u32, req->maxops, NFSD_MAX_OPS_PER_COMPOUND);
+ }
+ 
++static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses)
++{
++	struct nfs4_client *clp = ses->se_client;
++	struct nfsd4_conn *conn;
++
++	conn = kmalloc(sizeof(struct nfsd4_conn), GFP_KERNEL);
++	if (!conn)
++		return nfserr_jukebox;
++	conn->cn_flags = NFS4_CDFC4_FORE;
++	svc_xprt_get(rqstp->rq_xprt);
++	conn->cn_xprt = rqstp->rq_xprt;
++
++	spin_lock(&clp->cl_lock);
++	list_add(&conn->cn_persession, &ses->se_conns);
++	spin_unlock(&clp->cl_lock);
++
++	return nfs_ok;
++}
++
++static void free_conn(struct nfsd4_conn *c)
++{
++	svc_xprt_put(c->cn_xprt);
++	kfree(c);
++}
++
++void free_session(struct kref *kref)
++{
++	struct nfsd4_session *ses;
++	int mem;
++
++	ses = container_of(kref, struct nfsd4_session, se_ref);
++	while (!list_empty(&ses->se_conns)) {
++		struct nfsd4_conn *c;
++		c = list_first_entry(&ses->se_conns, struct nfsd4_conn, cn_persession);
++		list_del(&c->cn_persession);
++		free_conn(c);
++	}
++	spin_lock(&nfsd_drc_lock);
++	mem = ses->se_fchannel.maxreqs * slot_bytes(&ses->se_fchannel);
++	nfsd_drc_mem_used -= mem;
++	spin_unlock(&nfsd_drc_lock);
++	free_session_slots(ses);
++	kfree(ses);
++}
++
++
+ static __be32 alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp, struct nfsd4_create_session *cses)
+ {
+ 	struct nfsd4_session *new;
+ 	struct nfsd4_channel_attrs *fchan = &cses->fore_channel;
+ 	int numslots, slotsize;
++	int status;
+ 	int idx;
+ 
+ 	/*
+@@ -654,6 +701,8 @@ static __be32 alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp
+ 	memcpy(clp->cl_sessionid.data, new->se_sessionid.data,
+ 	       NFS4_MAX_SESSIONID_LEN);
+ 
++	INIT_LIST_HEAD(&new->se_conns);
++
+ 	new->se_flags = cses->flags;
+ 	kref_init(&new->se_ref);
+ 	idx = hash_sessionid(&new->se_sessionid);
+@@ -662,6 +711,11 @@ static __be32 alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp
+ 	list_add(&new->se_perclnt, &clp->cl_sessions);
+ 	spin_unlock(&client_lock);
+ 
++	status = nfsd4_new_conn(rqstp, new);
++	if (status) {
++		free_session(&new->se_ref);
++		return nfserr_jukebox;
++	}
+ 	return nfs_ok;
+ }
+ 
+@@ -694,21 +748,6 @@ unhash_session(struct nfsd4_session *ses)
+ 	list_del(&ses->se_perclnt);
+ }
+ 
+-void
+-free_session(struct kref *kref)
+-{
+-	struct nfsd4_session *ses;
+-	int mem;
+-
+-	ses = container_of(kref, struct nfsd4_session, se_ref);
+-	spin_lock(&nfsd_drc_lock);
+-	mem = ses->se_fchannel.maxreqs * slot_bytes(&ses->se_fchannel);
+-	nfsd_drc_mem_used -= mem;
+-	spin_unlock(&nfsd_drc_lock);
+-	free_session_slots(ses);
+-	kfree(ses);
+-}
+-
+ /* must be called under the client_lock */
+ static inline void
+ renew_client_locked(struct nfs4_client *clp)
+diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
+index 58bc2a63ca14..29413c2ed270 100644
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -152,6 +152,13 @@ struct nfsd4_clid_slot {
+ 	struct nfsd4_create_session	sl_cr_ses;
+ };
+ 
++struct nfsd4_conn {
++	struct list_head cn_persession;
++	struct svc_xprt *cn_xprt;
++/* CDFC4_FORE, CDFC4_BACK: */
++	unsigned char cn_flags;
++};
++
+ struct nfsd4_session {
+ 	struct kref		se_ref;
+ 	struct list_head	se_hash;	/* hash by sessionid */
+@@ -161,6 +168,7 @@ struct nfsd4_session {
+ 	struct nfs4_sessionid	se_sessionid;
+ 	struct nfsd4_channel_attrs se_fchannel;
+ 	struct nfsd4_channel_attrs se_bchannel;
++	struct list_head	se_conns;
+ 	struct nfsd4_slot	*se_slots[];	/* forward channel slots */
+ };
+ 
+diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
+index 07e40c625972..79b15fb2f304 100644
+--- a/include/linux/nfs4.h
++++ b/include/linux/nfs4.h
+@@ -61,6 +61,9 @@
+ #define NFS4_SHARE_SIGNAL_DELEG_WHEN_RESRC_AVAIL	0x10000
+ #define NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED		0x20000
+ 
++#define NFS4_CDFC4_FORE	0x1
++#define NFS4_CDFC4_BACK 0x2
++
+ #define NFS4_SET_TO_SERVER_TIME	0
+ #define NFS4_SET_TO_CLIENT_TIME	1
+ 

commit 6ff8da088766d70f0441feb982b82978a6cbf7ef
+Author: J. Bruce Fields 
+Date:   Fri Jun 4 20:04:45 2010 -0400
+
+    nfsd4: Move callback setup to callback queue
+    
+    Instead of creating the new rpc client from a regular server thread,
+    set a flag, kick off a null call, and allow the null call to do the work
+    of setting up the client on the callback workqueue.
+    
+    Use a spinlock to ensure the callback work gets a consistent view of the
+    callback parameters.
+    
+    This allows, for example, changing the callback from contexts where
+    sleeping is not allowed.  I hope it will also keep the locking simple as
+    we add more session and trunking features, by serializing most of the
+    callback-specific work.
+    
+    This also closes a small race where the the new cb_ident could be used
+    with an old connection (or vice-versa).
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 07c3be6eea64..a269dbeff150 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -284,7 +284,7 @@ nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, __be32 *p,
+ 	struct xdr_stream xdr;
+ 	struct nfs4_delegation *args = cb->cb_op;
+ 	struct nfs4_cb_compound_hdr hdr = {
+-		.ident = args->dl_ident,
++		.ident = cb->cb_clp->cl_cb_ident,
+ 		.minorversion = cb->cb_minorversion,
+ 	};
+ 
+@@ -506,7 +506,8 @@ int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn)
+ 			PTR_ERR(client));
+ 		return PTR_ERR(client);
+ 	}
+-	nfsd4_set_callback_client(clp, client);
++	clp->cl_cb_ident = conn->cb_ident;
++	clp->cl_cb_client = client;
+ 	return 0;
+ 
+ }
+@@ -569,15 +570,12 @@ void do_probe_callback(struct nfs4_client *clp)
+  */
+ void nfsd4_probe_callback(struct nfs4_client *clp, struct nfs4_cb_conn *conn)
+ {
+-	int status;
+-
+ 	BUG_ON(atomic_read(&clp->cl_cb_set));
+ 
+-	status = setup_callback_client(clp, conn);
+-	if (status) {
+-		warn_no_callback_path(clp, status);
+-		return;
+-	}
++	spin_lock(&clp->cl_lock);
++	memcpy(&clp->cl_cb_conn, conn, sizeof(struct nfs4_cb_conn));
++	set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags);
++	spin_unlock(&clp->cl_lock);
+ 	do_probe_callback(clp);
+ }
+ 
+@@ -730,19 +728,16 @@ void nfsd4_destroy_callback_queue(void)
+ }
+ 
+ /* must be called under the state lock */
+-void nfsd4_set_callback_client(struct nfs4_client *clp, struct rpc_clnt *new)
++void nfsd4_shutdown_callback(struct nfs4_client *clp)
+ {
+-	struct rpc_clnt *old = clp->cl_cb_client;
+-
+-	clp->cl_cb_client = new;
++	set_bit(NFSD4_CLIENT_KILL, &clp->cl_cb_flags);
+ 	/*
+-	 * After this, any work that saw the old value of cl_cb_client will
+-	 * be gone:
++	 * Note this won't actually result in a null callback;
++	 * instead, nfsd4_do_callback_rpc() will detect the killed
++	 * client, destroy the rpc client, and stop:
+ 	 */
++	do_probe_callback(clp);
+ 	flush_workqueue(callback_wq);
+-	/* So we can safely shut it down: */
+-	if (old)
+-		rpc_shutdown_client(old);
+ }
+ 
+ void nfsd4_release_cb(struct nfsd4_callback *cb)
+@@ -751,15 +746,51 @@ void nfsd4_release_cb(struct nfsd4_callback *cb)
+ 		cb->cb_ops->rpc_release(cb);
+ }
+ 
++void nfsd4_process_cb_update(struct nfsd4_callback *cb)
++{
++	struct nfs4_cb_conn conn;
++	struct nfs4_client *clp = cb->cb_clp;
++	int err;
++
++	/*
++	 * This is either an update, or the client dying; in either case,
++	 * kill the old client:
++	 */
++	if (clp->cl_cb_client) {
++		rpc_shutdown_client(clp->cl_cb_client);
++		clp->cl_cb_client = NULL;
++	}
++	if (test_bit(NFSD4_CLIENT_KILL, &clp->cl_cb_flags))
++		return;
++	spin_lock(&clp->cl_lock);
++	/*
++	 * Only serialized callback code is allowed to clear these
++	 * flags; main nfsd code can only set them:
++	 */
++	BUG_ON(!clp->cl_cb_flags);
++	clear_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags);
++	memcpy(&conn, &cb->cb_clp->cl_cb_conn, sizeof(struct nfs4_cb_conn));
++	spin_unlock(&clp->cl_lock);
++
++	err = setup_callback_client(clp, &conn);
++	if (err)
++		warn_no_callback_path(clp, err);
++}
++
+ void nfsd4_do_callback_rpc(struct work_struct *w)
+ {
+ 	struct nfsd4_callback *cb = container_of(w, struct nfsd4_callback, cb_work);
+ 	struct nfs4_client *clp = cb->cb_clp;
+-	struct rpc_clnt *clnt = clp->cl_cb_client;
++	struct rpc_clnt *clnt;
+ 
+-	if (clnt == NULL) {
++	if (clp->cl_cb_flags)
++		nfsd4_process_cb_update(cb);
++
++	clnt = clp->cl_cb_client;
++	if (!clnt) {
++		/* Callback channel broken, or client killed; give up: */
+ 		nfsd4_release_cb(cb);
+-		return; /* Client is shutting down; give up. */
++		return;
+ 	}
+ 	rpc_call_async(clnt, &cb->cb_msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN,
+ 			cb->cb_ops, cb);
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 2f464fb26afc..d3f12dcc1696 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -207,7 +207,6 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
+ {
+ 	struct nfs4_delegation *dp;
+ 	struct nfs4_file *fp = stp->st_file;
+-	struct nfs4_cb_conn *conn = &stp->st_stateowner->so_client->cl_cb_conn;
+ 
+ 	dprintk("NFSD alloc_init_deleg\n");
+ 	/*
+@@ -234,7 +233,6 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
+ 	nfs4_file_get_access(fp, O_RDONLY);
+ 	dp->dl_flock = NULL;
+ 	dp->dl_type = type;
+-	dp->dl_ident = conn->cb_ident;
+ 	dp->dl_stateid.si_boot = boot_time;
+ 	dp->dl_stateid.si_stateownerid = current_delegid++;
+ 	dp->dl_stateid.si_fileid = 0;
+@@ -875,7 +873,7 @@ expire_client(struct nfs4_client *clp)
+ 		sop = list_entry(clp->cl_openowners.next, struct nfs4_stateowner, so_perclient);
+ 		release_openowner(sop);
+ 	}
+-	nfsd4_set_callback_client(clp, NULL);
++	nfsd4_shutdown_callback(clp);
+ 	if (clp->cl_cb_conn.cb_xprt)
+ 		svc_xprt_put(clp->cl_cb_conn.cb_xprt);
+ 	list_del(&clp->cl_idhash);
+@@ -978,6 +976,7 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir,
+ 	INIT_LIST_HEAD(&clp->cl_delegations);
+ 	INIT_LIST_HEAD(&clp->cl_sessions);
+ 	INIT_LIST_HEAD(&clp->cl_lru);
++	spin_lock_init(&clp->cl_lock);
+ 	INIT_WORK(&clp->cl_cb_null.cb_work, nfsd4_do_callback_rpc);
+ 	clp->cl_time = get_seconds();
+ 	clear_bit(0, &clp->cl_cb_slot_busy);
+@@ -1547,7 +1546,7 @@ nfsd4_destroy_session(struct svc_rqst *r,
+ 
+ 	nfs4_lock_state();
+ 	/* wait for callbacks */
+-	nfsd4_set_callback_client(ses->se_client, NULL);
++	nfsd4_shutdown_callback(ses->se_client);
+ 	nfs4_unlock_state();
+ 	nfsd4_put_session(ses);
+ 	status = nfs_ok;
+diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
+index 2ece6bee65f7..58bc2a63ca14 100644
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -84,7 +84,6 @@ struct nfs4_delegation {
+ 	u32			dl_type;
+ 	time_t			dl_time;
+ /* For recall: */
+-	u32			dl_ident;
+ 	stateid_t		dl_stateid;
+ 	struct knfsd_fh		dl_fh;
+ 	int			dl_retries;
+@@ -217,10 +216,17 @@ struct nfs4_client {
+ 
+ 	/* for v4.0 and v4.1 callbacks: */
+ 	struct nfs4_cb_conn	cl_cb_conn;
++#define NFSD4_CLIENT_CB_UPDATE	1
++#define NFSD4_CLIENT_KILL	2
++	unsigned long		cl_cb_flags;
+ 	struct rpc_clnt		*cl_cb_client;
++	u32			cl_cb_ident;
+ 	atomic_t		cl_cb_set;
+ 	struct nfsd4_callback	cl_cb_null;
+ 
++	/* for all client information that callback code might need: */
++	spinlock_t		cl_lock;
++
+ 	/* for nfs41 */
+ 	struct list_head	cl_sessions;
+ 	struct nfsd4_clid_slot	cl_cs_slot;	/* create_session slot */
+@@ -439,7 +445,7 @@ extern void nfsd4_do_callback_rpc(struct work_struct *);
+ extern void nfsd4_cb_recall(struct nfs4_delegation *dp);
+ extern int nfsd4_create_callback_queue(void);
+ extern void nfsd4_destroy_callback_queue(void);
+-extern void nfsd4_set_callback_client(struct nfs4_client *, struct rpc_clnt *);
++extern void nfsd4_shutdown_callback(struct nfs4_client *);
+ extern void nfs4_put_delegation(struct nfs4_delegation *dp);
+ extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname);
+ extern void nfsd4_init_recdir(char *recdir_name);

commit fb003923263c3f0cb02adbd56a22fe16ef5c0e77
+Author: J. Bruce Fields 
+Date:   Mon May 31 18:21:37 2010 -0400
+
+    nfsd4: remove separate cb_args struct
+    
+    I don't see the point of the separate struct.  It seems to just be
+    getting in the way.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 26fa878005cc..07c3be6eea64 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -247,7 +247,7 @@ encode_cb_recall(struct xdr_stream *xdr, struct nfs4_delegation *dp,
+ }
+ 
+ static void
+-encode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_cb_args *args,
++encode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_callback *cb,
+ 		   struct nfs4_cb_compound_hdr *hdr)
+ {
+ 	__be32 *p;
+@@ -258,8 +258,8 @@ encode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_cb_args *args,
+ 	RESERVE_SPACE(1 + NFS4_MAX_SESSIONID_LEN + 20);
+ 
+ 	WRITE32(OP_CB_SEQUENCE);
+-	WRITEMEM(args->args_clp->cl_sessionid.data, NFS4_MAX_SESSIONID_LEN);
+-	WRITE32(args->args_clp->cl_cb_seq_nr);
++	WRITEMEM(cb->cb_clp->cl_sessionid.data, NFS4_MAX_SESSIONID_LEN);
++	WRITE32(cb->cb_clp->cl_cb_seq_nr);
+ 	WRITE32(0);		/* slotid, always 0 */
+ 	WRITE32(0);		/* highest slotid always 0 */
+ 	WRITE32(0);		/* cachethis always 0 */
+@@ -279,18 +279,18 @@ nfs4_xdr_enc_cb_null(struct rpc_rqst *req, __be32 *p)
+ 
+ static int
+ nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, __be32 *p,
+-		struct nfsd4_cb_args *rpc_args)
++		struct nfsd4_callback *cb)
+ {
+ 	struct xdr_stream xdr;
+-	struct nfs4_delegation *args = rpc_args->args_op;
++	struct nfs4_delegation *args = cb->cb_op;
+ 	struct nfs4_cb_compound_hdr hdr = {
+ 		.ident = args->dl_ident,
+-		.minorversion = rpc_args->args_minorversion,
++		.minorversion = cb->cb_minorversion,
+ 	};
+ 
+ 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+ 	encode_cb_compound_hdr(&xdr, &hdr);
+-	encode_cb_sequence(&xdr, rpc_args, &hdr);
++	encode_cb_sequence(&xdr, cb, &hdr);
+ 	encode_cb_recall(&xdr, args, &hdr);
+ 	encode_cb_nops(&hdr);
+ 	return 0;
+@@ -338,7 +338,7 @@ decode_cb_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
+  * with a single slot.
+  */
+ static int
+-decode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_cb_args *res,
++decode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_callback *cb,
+ 		   struct rpc_rqst *rqstp)
+ {
+ 	struct nfs4_sessionid id;
+@@ -346,7 +346,7 @@ decode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_cb_args *res,
+ 	u32 dummy;
+ 	__be32 *p;
+ 
+-	if (res->args_minorversion == 0)
++	if (cb->cb_minorversion == 0)
+ 		return 0;
+ 
+ 	status = decode_cb_op_hdr(xdr, OP_CB_SEQUENCE);
+@@ -362,13 +362,13 @@ decode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_cb_args *res,
+ 	READ_BUF(NFS4_MAX_SESSIONID_LEN + 16);
+ 	memcpy(id.data, p, NFS4_MAX_SESSIONID_LEN);
+ 	p += XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN);
+-	if (memcmp(id.data, res->args_clp->cl_sessionid.data,
++	if (memcmp(id.data, cb->cb_clp->cl_sessionid.data,
+ 		   NFS4_MAX_SESSIONID_LEN)) {
+ 		dprintk("%s Invalid session id\n", __func__);
+ 		goto out;
+ 	}
+ 	READ32(dummy);
+-	if (dummy != res->args_clp->cl_cb_seq_nr) {
++	if (dummy != cb->cb_clp->cl_cb_seq_nr) {
+ 		dprintk("%s Invalid sequence number\n", __func__);
+ 		goto out;
+ 	}
+@@ -392,7 +392,7 @@ nfs4_xdr_dec_cb_null(struct rpc_rqst *req, __be32 *p)
+ 
+ static int
+ nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp, __be32 *p,
+-		struct nfsd4_cb_args *args)
++		struct nfsd4_callback *cb)
+ {
+ 	struct xdr_stream xdr;
+ 	struct nfs4_cb_compound_hdr hdr;
+@@ -402,8 +402,8 @@ nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp, __be32 *p,
+ 	status = decode_cb_compound_hdr(&xdr, &hdr);
+ 	if (status)
+ 		goto out;
+-	if (args) {
+-		status = decode_cb_sequence(&xdr, args, rqstp);
++	if (cb) {
++		status = decode_cb_sequence(&xdr, cb, rqstp);
+ 		if (status)
+ 			goto out;
+ 	}
+@@ -551,8 +551,8 @@ void do_probe_callback(struct nfs4_client *clp)
+ {
+ 	struct nfsd4_callback *cb = &clp->cl_cb_null;
+ 
+-	cb->cb_args.args_op = NULL;
+-	cb->cb_args.args_clp = clp;
++	cb->cb_op = NULL;
++	cb->cb_clp = clp;
+ 
+ 	cb->cb_msg.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL];
+ 	cb->cb_msg.rpc_argp = NULL;
+@@ -615,11 +615,10 @@ static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata)
+ 	struct nfsd4_callback *cb = calldata;
+ 	struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall);
+ 	struct nfs4_client *clp = dp->dl_client;
+-	struct nfsd4_cb_args *args = task->tk_msg.rpc_argp;
+ 	u32 minorversion = clp->cl_cb_conn.cb_minorversion;
+ 	int status = 0;
+ 
+-	args->args_minorversion = minorversion;
++	cb->cb_minorversion = minorversion;
+ 	if (minorversion) {
+ 		status = nfsd41_cb_setup_sequence(clp, task);
+ 		if (status) {
+@@ -755,7 +754,7 @@ void nfsd4_release_cb(struct nfsd4_callback *cb)
+ void nfsd4_do_callback_rpc(struct work_struct *w)
+ {
+ 	struct nfsd4_callback *cb = container_of(w, struct nfsd4_callback, cb_work);
+-	struct nfs4_client *clp = cb->cb_args.args_clp;
++	struct nfs4_client *clp = cb->cb_clp;
+ 	struct rpc_clnt *clnt = clp->cl_cb_client;
+ 
+ 	if (clnt == NULL) {
+@@ -771,11 +770,11 @@ void nfsd4_cb_recall(struct nfs4_delegation *dp)
+ 	struct nfsd4_callback *cb = &dp->dl_recall;
+ 
+ 	dp->dl_retries = 1;
+-	cb->cb_args.args_op = dp;
+-	cb->cb_args.args_clp = dp->dl_client;
++	cb->cb_op = dp;
++	cb->cb_clp = dp->dl_client;
+ 	cb->cb_msg.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL];
+-	cb->cb_msg.rpc_argp = &cb->cb_args;
+-	cb->cb_msg.rpc_resp = &cb->cb_args;
++	cb->cb_msg.rpc_argp = cb;
++	cb->cb_msg.rpc_resp = cb;
+ 	cb->cb_msg.rpc_cred = callback_cred;
+ 
+ 	cb->cb_ops = &nfsd4_cb_recall_ops;
+diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
+index 19732d531cda..2ece6bee65f7 100644
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -64,14 +64,10 @@ typedef struct {
+ 	(s)->si_fileid, \
+ 	(s)->si_generation
+ 
+-struct nfsd4_cb_args {
+-	void			*args_op;
+-	struct nfs4_client	*args_clp;
+-	u32			args_minorversion;
+-};
+-
+ struct nfsd4_callback {
+-	struct nfsd4_cb_args cb_args;
++	void *cb_op;
++	struct nfs4_client *cb_clp;
++	u32 cb_minorversion;
+ 	struct rpc_message cb_msg;
+ 	const struct rpc_call_ops *cb_ops;
+ 	struct work_struct cb_work;

commit cee277d92495a9ea49a6137fe7005d7c76b31b5b
+Author: J. Bruce Fields 
+Date:   Wed May 26 17:52:14 2010 -0400
+
+    nfsd4: use generic callback code in null case
+    
+    This will eventually allow us, for example, to kick off null callback
+    from contexts where we can't sleep.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index a037f26252ee..26fa878005cc 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -519,7 +519,7 @@ static void warn_no_callback_path(struct nfs4_client *clp, int reason)
+ 
+ static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata)
+ {
+-	struct nfs4_client *clp = calldata;
++	struct nfs4_client *clp = container_of(calldata, struct nfs4_client, cl_cb_null);
+ 
+ 	if (task->tk_status)
+ 		warn_no_callback_path(clp, task->tk_status);
+@@ -528,6 +528,8 @@ static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata)
+ }
+ 
+ static const struct rpc_call_ops nfsd4_cb_probe_ops = {
++	/* XXX: release method to ensure we set the cb channel down if
++	 * necessary on early failure? */
+ 	.rpc_call_done = nfsd4_cb_probe_done,
+ };
+ 
+@@ -543,21 +545,23 @@ int set_callback_cred(void)
+ 	return 0;
+ }
+ 
++static struct workqueue_struct *callback_wq;
+ 
+ void do_probe_callback(struct nfs4_client *clp)
+ {
+-	struct rpc_message msg = {
+-		.rpc_proc       = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
+-		.rpc_argp       = clp,
+-		.rpc_cred	= callback_cred
+-	};
+-	int status;
++	struct nfsd4_callback *cb = &clp->cl_cb_null;
+ 
+-	status = rpc_call_async(clp->cl_cb_client, &msg,
+-				RPC_TASK_SOFT | RPC_TASK_SOFTCONN,
+-				&nfsd4_cb_probe_ops, (void *)clp);
+-	if (status)
+-		warn_no_callback_path(clp, status);
++	cb->cb_args.args_op = NULL;
++	cb->cb_args.args_clp = clp;
++
++	cb->cb_msg.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL];
++	cb->cb_msg.rpc_argp = NULL;
++	cb->cb_msg.rpc_resp = NULL;
++	cb->cb_msg.rpc_cred = callback_cred;
++
++	cb->cb_ops = &nfsd4_cb_probe_ops;
++
++	queue_work(callback_wq, &cb->cb_work);
+ }
+ 
+ /*
+@@ -713,8 +717,6 @@ static const struct rpc_call_ops nfsd4_cb_recall_ops = {
+ 	.rpc_release = nfsd4_cb_recall_release,
+ };
+ 
+-static struct workqueue_struct *callback_wq;
+-
+ int nfsd4_create_callback_queue(void)
+ {
+ 	callback_wq = create_singlethread_workqueue("nfsd4_callbacks");
+@@ -760,7 +762,8 @@ void nfsd4_do_callback_rpc(struct work_struct *w)
+ 		nfsd4_release_cb(cb);
+ 		return; /* Client is shutting down; give up. */
+ 	}
+-	rpc_call_async(clnt, &cb->cb_msg, RPC_TASK_SOFT, cb->cb_ops, cb);
++	rpc_call_async(clnt, &cb->cb_msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN,
++			cb->cb_ops, cb);
+ }
+ 
+ void nfsd4_cb_recall(struct nfs4_delegation *dp)
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index d347180ce55a..2f464fb26afc 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -978,6 +978,7 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir,
+ 	INIT_LIST_HEAD(&clp->cl_delegations);
+ 	INIT_LIST_HEAD(&clp->cl_sessions);
+ 	INIT_LIST_HEAD(&clp->cl_lru);
++	INIT_WORK(&clp->cl_cb_null.cb_work, nfsd4_do_callback_rpc);
+ 	clp->cl_time = get_seconds();
+ 	clear_bit(0, &clp->cl_cb_slot_busy);
+ 	rpc_init_wait_queue(&clp->cl_cb_waitq, "Backchannel slot table");
+diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
+index 6e592148ad80..19732d531cda 100644
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -223,6 +223,7 @@ struct nfs4_client {
+ 	struct nfs4_cb_conn	cl_cb_conn;
+ 	struct rpc_clnt		*cl_cb_client;
+ 	atomic_t		cl_cb_set;
++	struct nfsd4_callback	cl_cb_null;
+ 
+ 	/* for nfs41 */
+ 	struct list_head	cl_sessions;

commit 5878453dbde627a8e1b5a4693087e36cb88d45b1
+Author: J. Bruce Fields 
+Date:   Sun May 16 16:47:08 2010 -0400
+
+    nfsd4: generic callback code
+    
+    Make the recall callback code more generic, so that other callbacks
+    will be able to use it too.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 5508e928fd9f..a037f26252ee 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -585,7 +585,6 @@ void nfsd4_probe_callback(struct nfs4_client *clp, struct nfs4_cb_conn *conn)
+ static int nfsd41_cb_setup_sequence(struct nfs4_client *clp,
+ 		struct rpc_task *task)
+ {
+-	struct nfsd4_cb_args *args = task->tk_msg.rpc_argp;
+ 	u32 *ptr = (u32 *)clp->cl_sessionid.data;
+ 	int status = 0;
+ 
+@@ -598,14 +597,6 @@ static int nfsd41_cb_setup_sequence(struct nfs4_client *clp,
+ 		status = -EAGAIN;
+ 		goto out;
+ 	}
+-
+-	/*
+-	 * We'll need the clp during XDR encoding and decoding,
+-	 * and the sequence during decoding to verify the reply
+-	 */
+-	args->args_clp = clp;
+-	task->tk_msg.rpc_resp = args;
+-
+ out:
+ 	dprintk("%s status=%d\n", __func__, status);
+ 	return status;
+@@ -617,7 +608,8 @@ static int nfsd41_cb_setup_sequence(struct nfs4_client *clp,
+  */
+ static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata)
+ {
+-	struct nfs4_delegation *dp = calldata;
++	struct nfsd4_callback *cb = calldata;
++	struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall);
+ 	struct nfs4_client *clp = dp->dl_client;
+ 	struct nfsd4_cb_args *args = task->tk_msg.rpc_argp;
+ 	u32 minorversion = clp->cl_cb_conn.cb_minorversion;
+@@ -640,7 +632,8 @@ static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata)
+ 
+ static void nfsd4_cb_done(struct rpc_task *task, void *calldata)
+ {
+-	struct nfs4_delegation *dp = calldata;
++	struct nfsd4_callback *cb = calldata;
++	struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall);
+ 	struct nfs4_client *clp = dp->dl_client;
+ 
+ 	dprintk("%s: minorversion=%d\n", __func__,
+@@ -662,7 +655,8 @@ static void nfsd4_cb_done(struct rpc_task *task, void *calldata)
+ 
+ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
+ {
+-	struct nfs4_delegation *dp = calldata;
++	struct nfsd4_callback *cb = calldata;
++	struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall);
+ 	struct nfs4_client *clp = dp->dl_client;
+ 	struct rpc_clnt *current_rpc_client = clp->cl_cb_client;
+ 
+@@ -707,7 +701,8 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
+ 
+ static void nfsd4_cb_recall_release(void *calldata)
+ {
+-	struct nfs4_delegation *dp = calldata;
++	struct nfsd4_callback *cb = calldata;
++	struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall);
+ 
+ 	nfs4_put_delegation(dp);
+ }
+@@ -749,42 +744,39 @@ void nfsd4_set_callback_client(struct nfs4_client *clp, struct rpc_clnt *new)
+ 		rpc_shutdown_client(old);
+ }
+ 
+-/*
+- * called with dp->dl_count inc'ed.
+- */
+-static void _nfsd4_cb_recall(struct nfs4_delegation *dp)
++void nfsd4_release_cb(struct nfsd4_callback *cb)
+ {
+-	struct nfs4_client *clp = dp->dl_client;
++	if (cb->cb_ops->rpc_release)
++		cb->cb_ops->rpc_release(cb);
++}
++
++void nfsd4_do_callback_rpc(struct work_struct *w)
++{
++	struct nfsd4_callback *cb = container_of(w, struct nfsd4_callback, cb_work);
++	struct nfs4_client *clp = cb->cb_args.args_clp;
+ 	struct rpc_clnt *clnt = clp->cl_cb_client;
+-	struct nfsd4_cb_args *args = &dp->dl_recall.cb_args;
+-	struct rpc_message msg = {
+-		.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL],
+-		.rpc_cred = callback_cred
+-	};
+ 
+ 	if (clnt == NULL) {
+-		nfs4_put_delegation(dp);
++		nfsd4_release_cb(cb);
+ 		return; /* Client is shutting down; give up. */
+ 	}
+-
+-	args->args_op = dp;
+-	msg.rpc_argp = args;
+-	dp->dl_retries = 1;
+-	rpc_call_async(clnt, &msg, RPC_TASK_SOFT, &nfsd4_cb_recall_ops, dp);
++	rpc_call_async(clnt, &cb->cb_msg, RPC_TASK_SOFT, cb->cb_ops, cb);
+ }
+ 
+-void nfsd4_do_callback_rpc(struct work_struct *w)
++void nfsd4_cb_recall(struct nfs4_delegation *dp)
+ {
+-	/* XXX: for now, just send off delegation recall. */
+-	/* In future, generalize to handle any sort of callback. */
+-	struct nfsd4_callback *c = container_of(w, struct nfsd4_callback, cb_work);
+-	struct nfs4_delegation *dp = container_of(c, struct nfs4_delegation, dl_recall);
+-
+-	_nfsd4_cb_recall(dp);
+-}
++	struct nfsd4_callback *cb = &dp->dl_recall;
+ 
++	dp->dl_retries = 1;
++	cb->cb_args.args_op = dp;
++	cb->cb_args.args_clp = dp->dl_client;
++	cb->cb_msg.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL];
++	cb->cb_msg.rpc_argp = &cb->cb_args;
++	cb->cb_msg.rpc_resp = &cb->cb_args;
++	cb->cb_msg.rpc_cred = callback_cred;
++
++	cb->cb_ops = &nfsd4_cb_recall_ops;
++	dp->dl_retries = 1;
+ 
+-void nfsd4_cb_recall(struct nfs4_delegation *dp)
+-{
+ 	queue_work(callback_wq, &dp->dl_recall.cb_work);
+ }
+diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
+index f988b90ec213..6e592148ad80 100644
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -72,6 +72,8 @@ struct nfsd4_cb_args {
+ 
+ struct nfsd4_callback {
+ 	struct nfsd4_cb_args cb_args;
++	struct rpc_message cb_msg;
++	const struct rpc_call_ops *cb_ops;
+ 	struct work_struct cb_work;
+ };
+ 

commit 1c8556026edac60368ceef446f0febc08014ba78
+Author: J. Bruce Fields 
+Date:   Wed May 26 17:46:00 2010 -0400
+
+    nfsd4: rename nfs4_rpc_args->nfsd4_cb_args
+    
+    With apologies for the gratuitous rename, the new name seems more
+    helpful to me.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 5687fce85641..5508e928fd9f 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -247,7 +247,7 @@ encode_cb_recall(struct xdr_stream *xdr, struct nfs4_delegation *dp,
+ }
+ 
+ static void
+-encode_cb_sequence(struct xdr_stream *xdr, struct nfs4_rpc_args *args,
++encode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_cb_args *args,
+ 		   struct nfs4_cb_compound_hdr *hdr)
+ {
+ 	__be32 *p;
+@@ -279,7 +279,7 @@ nfs4_xdr_enc_cb_null(struct rpc_rqst *req, __be32 *p)
+ 
+ static int
+ nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, __be32 *p,
+-		struct nfs4_rpc_args *rpc_args)
++		struct nfsd4_cb_args *rpc_args)
+ {
+ 	struct xdr_stream xdr;
+ 	struct nfs4_delegation *args = rpc_args->args_op;
+@@ -338,7 +338,7 @@ decode_cb_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
+  * with a single slot.
+  */
+ static int
+-decode_cb_sequence(struct xdr_stream *xdr, struct nfs4_rpc_args *res,
++decode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_cb_args *res,
+ 		   struct rpc_rqst *rqstp)
+ {
+ 	struct nfs4_sessionid id;
+@@ -392,7 +392,7 @@ nfs4_xdr_dec_cb_null(struct rpc_rqst *req, __be32 *p)
+ 
+ static int
+ nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp, __be32 *p,
+-		struct nfs4_rpc_args *args)
++		struct nfsd4_cb_args *args)
+ {
+ 	struct xdr_stream xdr;
+ 	struct nfs4_cb_compound_hdr hdr;
+@@ -585,7 +585,7 @@ void nfsd4_probe_callback(struct nfs4_client *clp, struct nfs4_cb_conn *conn)
+ static int nfsd41_cb_setup_sequence(struct nfs4_client *clp,
+ 		struct rpc_task *task)
+ {
+-	struct nfs4_rpc_args *args = task->tk_msg.rpc_argp;
++	struct nfsd4_cb_args *args = task->tk_msg.rpc_argp;
+ 	u32 *ptr = (u32 *)clp->cl_sessionid.data;
+ 	int status = 0;
+ 
+@@ -619,7 +619,7 @@ static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata)
+ {
+ 	struct nfs4_delegation *dp = calldata;
+ 	struct nfs4_client *clp = dp->dl_client;
+-	struct nfs4_rpc_args *args = task->tk_msg.rpc_argp;
++	struct nfsd4_cb_args *args = task->tk_msg.rpc_argp;
+ 	u32 minorversion = clp->cl_cb_conn.cb_minorversion;
+ 	int status = 0;
+ 
+@@ -756,7 +756,7 @@ static void _nfsd4_cb_recall(struct nfs4_delegation *dp)
+ {
+ 	struct nfs4_client *clp = dp->dl_client;
+ 	struct rpc_clnt *clnt = clp->cl_cb_client;
+-	struct nfs4_rpc_args *args = &dp->dl_recall.cb_args;
++	struct nfsd4_cb_args *args = &dp->dl_recall.cb_args;
+ 	struct rpc_message msg = {
+ 		.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL],
+ 		.rpc_cred = callback_cred
+diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
+index 59313f1d8e67..f988b90ec213 100644
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -64,14 +64,14 @@ typedef struct {
+ 	(s)->si_fileid, \
+ 	(s)->si_generation
+ 
+-struct nfs4_rpc_args {
++struct nfsd4_cb_args {
+ 	void			*args_op;
+ 	struct nfs4_client	*args_clp;
+ 	u32			args_minorversion;
+ };
+ 
+ struct nfsd4_callback {
+-	struct nfs4_rpc_args cb_args;
++	struct nfsd4_cb_args cb_args;
+ 	struct work_struct cb_work;
+ };
+ 

commit 586f36735e1d38c32bbfbb2716461e7178724b15
+Author: J. Bruce Fields 
+Date:   Wed May 26 17:40:53 2010 -0400
+
+    nfsd4: combine nfs4_rpc_args and nfsd4_cb_sequence
+    
+    These two structs don't really need to be distinct as far as I can tell.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 4566b69128a3..5687fce85641 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -247,7 +247,7 @@ encode_cb_recall(struct xdr_stream *xdr, struct nfs4_delegation *dp,
+ }
+ 
+ static void
+-encode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_cb_sequence *args,
++encode_cb_sequence(struct xdr_stream *xdr, struct nfs4_rpc_args *args,
+ 		   struct nfs4_cb_compound_hdr *hdr)
+ {
+ 	__be32 *p;
+@@ -258,8 +258,8 @@ encode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_cb_sequence *args,
+ 	RESERVE_SPACE(1 + NFS4_MAX_SESSIONID_LEN + 20);
+ 
+ 	WRITE32(OP_CB_SEQUENCE);
+-	WRITEMEM(args->cbs_clp->cl_sessionid.data, NFS4_MAX_SESSIONID_LEN);
+-	WRITE32(args->cbs_clp->cl_cb_seq_nr);
++	WRITEMEM(args->args_clp->cl_sessionid.data, NFS4_MAX_SESSIONID_LEN);
++	WRITE32(args->args_clp->cl_cb_seq_nr);
+ 	WRITE32(0);		/* slotid, always 0 */
+ 	WRITE32(0);		/* highest slotid always 0 */
+ 	WRITE32(0);		/* cachethis always 0 */
+@@ -285,12 +285,12 @@ nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, __be32 *p,
+ 	struct nfs4_delegation *args = rpc_args->args_op;
+ 	struct nfs4_cb_compound_hdr hdr = {
+ 		.ident = args->dl_ident,
+-		.minorversion = rpc_args->args_seq.cbs_minorversion,
++		.minorversion = rpc_args->args_minorversion,
+ 	};
+ 
+ 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+ 	encode_cb_compound_hdr(&xdr, &hdr);
+-	encode_cb_sequence(&xdr, &rpc_args->args_seq, &hdr);
++	encode_cb_sequence(&xdr, rpc_args, &hdr);
+ 	encode_cb_recall(&xdr, args, &hdr);
+ 	encode_cb_nops(&hdr);
+ 	return 0;
+@@ -338,7 +338,7 @@ decode_cb_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
+  * with a single slot.
+  */
+ static int
+-decode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_cb_sequence *res,
++decode_cb_sequence(struct xdr_stream *xdr, struct nfs4_rpc_args *res,
+ 		   struct rpc_rqst *rqstp)
+ {
+ 	struct nfs4_sessionid id;
+@@ -346,7 +346,7 @@ decode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_cb_sequence *res,
+ 	u32 dummy;
+ 	__be32 *p;
+ 
+-	if (res->cbs_minorversion == 0)
++	if (res->args_minorversion == 0)
+ 		return 0;
+ 
+ 	status = decode_cb_op_hdr(xdr, OP_CB_SEQUENCE);
+@@ -362,13 +362,13 @@ decode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_cb_sequence *res,
+ 	READ_BUF(NFS4_MAX_SESSIONID_LEN + 16);
+ 	memcpy(id.data, p, NFS4_MAX_SESSIONID_LEN);
+ 	p += XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN);
+-	if (memcmp(id.data, res->cbs_clp->cl_sessionid.data,
++	if (memcmp(id.data, res->args_clp->cl_sessionid.data,
+ 		   NFS4_MAX_SESSIONID_LEN)) {
+ 		dprintk("%s Invalid session id\n", __func__);
+ 		goto out;
+ 	}
+ 	READ32(dummy);
+-	if (dummy != res->cbs_clp->cl_cb_seq_nr) {
++	if (dummy != res->args_clp->cl_cb_seq_nr) {
+ 		dprintk("%s Invalid sequence number\n", __func__);
+ 		goto out;
+ 	}
+@@ -392,7 +392,7 @@ nfs4_xdr_dec_cb_null(struct rpc_rqst *req, __be32 *p)
+ 
+ static int
+ nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp, __be32 *p,
+-		struct nfsd4_cb_sequence *seq)
++		struct nfs4_rpc_args *args)
+ {
+ 	struct xdr_stream xdr;
+ 	struct nfs4_cb_compound_hdr hdr;
+@@ -402,8 +402,8 @@ nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp, __be32 *p,
+ 	status = decode_cb_compound_hdr(&xdr, &hdr);
+ 	if (status)
+ 		goto out;
+-	if (seq) {
+-		status = decode_cb_sequence(&xdr, seq, rqstp);
++	if (args) {
++		status = decode_cb_sequence(&xdr, args, rqstp);
+ 		if (status)
+ 			goto out;
+ 	}
+@@ -603,8 +603,8 @@ static int nfsd41_cb_setup_sequence(struct nfs4_client *clp,
+ 	 * We'll need the clp during XDR encoding and decoding,
+ 	 * and the sequence during decoding to verify the reply
+ 	 */
+-	args->args_seq.cbs_clp = clp;
+-	task->tk_msg.rpc_resp = &args->args_seq;
++	args->args_clp = clp;
++	task->tk_msg.rpc_resp = args;
+ 
+ out:
+ 	dprintk("%s status=%d\n", __func__, status);
+@@ -623,7 +623,7 @@ static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata)
+ 	u32 minorversion = clp->cl_cb_conn.cb_minorversion;
+ 	int status = 0;
+ 
+-	args->args_seq.cbs_minorversion = minorversion;
++	args->args_minorversion = minorversion;
+ 	if (minorversion) {
+ 		status = nfsd41_cb_setup_sequence(clp, task);
+ 		if (status) {
+diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
+index 322518c88e4b..59313f1d8e67 100644
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -64,15 +64,10 @@ typedef struct {
+ 	(s)->si_fileid, \
+ 	(s)->si_generation
+ 
+-struct nfsd4_cb_sequence {
+-	/* args/res */
+-	u32			cbs_minorversion;
+-	struct nfs4_client	*cbs_clp;
+-};
+-
+ struct nfs4_rpc_args {
+-	void				*args_op;
+-	struct nfsd4_cb_sequence	args_seq;
++	void			*args_op;
++	struct nfs4_client	*args_clp;
++	u32			args_minorversion;
+ };
+ 
+ struct nfsd4_callback {

commit 07263f1efe7d5b96e6713471abfa087f41bb2b7c
+Author: J. Bruce Fields 
+Date:   Mon May 31 19:09:40 2010 -0400
+
+    nfsd4: minor variable renaming (cb -> conn)
+    
+    Now that we have both nfsd4_callback and nfsd4_cb_conn structures, I get
+    confused if variables of both types are always named cb....
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 1112f451295a..4566b69128a3 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -472,7 +472,7 @@ static int max_cb_time(void)
+ /* Reference counting, callback cleanup, etc., all look racy as heck.
+  * And why is cl_cb_set an atomic? */
+ 
+-int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *cb)
++int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn)
+ {
+ 	struct rpc_timeout	timeparms = {
+ 		.to_initval	= max_cb_time(),
+@@ -481,11 +481,11 @@ int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *cb)
+ 	struct rpc_create_args args = {
+ 		.net		= &init_net,
+ 		.protocol	= XPRT_TRANSPORT_TCP,
+-		.address	= (struct sockaddr *) &cb->cb_addr,
+-		.addrsize	= cb->cb_addrlen,
++		.address	= (struct sockaddr *) &conn->cb_addr,
++		.addrsize	= conn->cb_addrlen,
+ 		.timeout	= &timeparms,
+ 		.program	= &cb_program,
+-		.prognumber	= cb->cb_prog,
++		.prognumber	= conn->cb_prog,
+ 		.version	= 0,
+ 		.authflavor	= clp->cl_flavor,
+ 		.flags		= (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET),
+@@ -495,8 +495,8 @@ int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *cb)
+ 
+ 	if (!clp->cl_principal && (clp->cl_flavor >= RPC_AUTH_GSS_KRB5))
+ 		return -EINVAL;
+-	if (cb->cb_minorversion) {
+-		args.bc_xprt = cb->cb_xprt;
++	if (conn->cb_minorversion) {
++		args.bc_xprt = conn->cb_xprt;
+ 		args.protocol = XPRT_TRANSPORT_BC_TCP;
+ 	}
+ 	/* Create RPC client */
+@@ -563,13 +563,13 @@ void do_probe_callback(struct nfs4_client *clp)
+ /*
+  * Set up the callback client and put a NFSPROC4_CB_NULL on the wire...
+  */
+-void nfsd4_probe_callback(struct nfs4_client *clp, struct nfs4_cb_conn *cb)
++void nfsd4_probe_callback(struct nfs4_client *clp, struct nfs4_cb_conn *conn)
+ {
+ 	int status;
+ 
+ 	BUG_ON(atomic_read(&clp->cl_cb_set));
+ 
+-	status = setup_callback_client(clp, cb);
++	status = setup_callback_client(clp, conn);
+ 	if (status) {
+ 		warn_no_callback_path(clp, status);
+ 		return;
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index cf0d2ffb3c84..d347180ce55a 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -207,7 +207,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
+ {
+ 	struct nfs4_delegation *dp;
+ 	struct nfs4_file *fp = stp->st_file;
+-	struct nfs4_cb_conn *cb = &stp->st_stateowner->so_client->cl_cb_conn;
++	struct nfs4_cb_conn *conn = &stp->st_stateowner->so_client->cl_cb_conn;
+ 
+ 	dprintk("NFSD alloc_init_deleg\n");
+ 	/*
+@@ -234,7 +234,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
+ 	nfs4_file_get_access(fp, O_RDONLY);
+ 	dp->dl_flock = NULL;
+ 	dp->dl_type = type;
+-	dp->dl_ident = cb->cb_ident;
++	dp->dl_ident = conn->cb_ident;
+ 	dp->dl_stateid.si_boot = boot_time;
+ 	dp->dl_stateid.si_stateownerid = current_delegid++;
+ 	dp->dl_stateid.si_fileid = 0;
+@@ -1098,7 +1098,7 @@ find_unconfirmed_client_by_str(const char *dname, unsigned int hashval,
+ static void
+ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se, u32 scopeid)
+ {
+-	struct nfs4_cb_conn *cb = &clp->cl_cb_conn;
++	struct nfs4_cb_conn *conn = &clp->cl_cb_conn;
+ 	unsigned short expected_family;
+ 
+ 	/* Currently, we only support tcp and tcp6 for the callback channel */
+@@ -1111,24 +1111,24 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se, u32 scopeid)
+ 	else
+ 		goto out_err;
+ 
+-	cb->cb_addrlen = rpc_uaddr2sockaddr(se->se_callback_addr_val,
++	conn->cb_addrlen = rpc_uaddr2sockaddr(se->se_callback_addr_val,
+ 					    se->se_callback_addr_len,
+-					    (struct sockaddr *) &cb->cb_addr,
+-					    sizeof(cb->cb_addr));
++					    (struct sockaddr *)&conn->cb_addr,
++					    sizeof(conn->cb_addr));
+ 
+-	if (!cb->cb_addrlen || cb->cb_addr.ss_family != expected_family)
++	if (!conn->cb_addrlen || conn->cb_addr.ss_family != expected_family)
+ 		goto out_err;
+ 
+-	if (cb->cb_addr.ss_family == AF_INET6)
+-		((struct sockaddr_in6 *) &cb->cb_addr)->sin6_scope_id = scopeid;
++	if (conn->cb_addr.ss_family == AF_INET6)
++		((struct sockaddr_in6 *)&conn->cb_addr)->sin6_scope_id = scopeid;
+ 
+-	cb->cb_minorversion = 0;
+-	cb->cb_prog = se->se_callback_prog;
+-	cb->cb_ident = se->se_callback_ident;
++	conn->cb_minorversion = 0;
++	conn->cb_prog = se->se_callback_prog;
++	conn->cb_ident = se->se_callback_ident;
+ 	return;
+ out_err:
+-	cb->cb_addr.ss_family = AF_UNSPEC;
+-	cb->cb_addrlen = 0;
++	conn->cb_addr.ss_family = AF_UNSPEC;
++	conn->cb_addrlen = 0;
+ 	dprintk(KERN_INFO "NFSD: this client (clientid %08x/%08x) "
+ 		"will not receive delegations\n",
+ 		clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);

commit f9d7562fdb9dc0ada3a7aba5dbbe9d965e2a105d
+Author: J. Bruce Fields 
+Date:   Thu Jul 8 11:02:09 2010 -0400
+
+    nfsd4: share file descriptors between stateid's
+    
+    The vfs doesn't really allow us to "upgrade" a file descriptor from
+    read-only to read-write, and our attempt to do so in nfs4_upgrade_open
+    is ugly and incomplete.
+    
+    Move to a different scheme where we keep multiple opens, shared between
+    open stateid's, in the nfs4_file struct.  Each file will be opened at
+    most 3 times (for read, write, and read-write), and those opens will be
+    shared between all clients and openers.  On upgrade we will do another
+    open if necessary instead of attempting to upgrade an existing open.
+    We keep count of the number of readers and writers so we know when to
+    close the shared files.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index b996a4badeb8..7ab572f9f388 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -162,6 +162,28 @@ static struct list_head	ownerstr_hashtbl[OWNER_HASH_SIZE];
+ static struct list_head file_hashtbl[FILE_HASH_SIZE];
+ static struct list_head stateid_hashtbl[STATEID_HASH_SIZE];
+ 
++static inline void nfs4_file_get_access(struct nfs4_file *fp, int oflag)
++{
++	BUG_ON(!(fp->fi_fds[oflag] || fp->fi_fds[O_RDWR]));
++	atomic_inc(&fp->fi_access[oflag]);
++}
++
++static inline void nfs4_file_put_fd(struct nfs4_file *fp, int oflag)
++{
++	if (fp->fi_fds[oflag]) {
++		fput(fp->fi_fds[oflag]);
++		fp->fi_fds[oflag] = NULL;
++	}
++}
++
++static inline void nfs4_file_put_access(struct nfs4_file *fp, int oflag)
++{
++	if (atomic_dec_and_test(&fp->fi_access[oflag])) {
++		nfs4_file_put_fd(fp, O_RDWR);
++		nfs4_file_put_fd(fp, oflag);
++	}
++}
++
+ static struct nfs4_delegation *
+ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_fh *current_fh, u32 type)
+ {
+@@ -191,9 +213,8 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
+ 	dp->dl_client = clp;
+ 	get_nfs4_file(fp);
+ 	dp->dl_file = fp;
++	nfs4_file_get_access(fp, O_RDONLY);
+ 	dp->dl_flock = NULL;
+-	get_file(stp->st_vfs_file);
+-	dp->dl_vfs_file = stp->st_vfs_file;
+ 	dp->dl_type = type;
+ 	dp->dl_ident = cb->cb_ident;
+ 	dp->dl_stateid.si_boot = boot_time;
+@@ -228,15 +249,12 @@ nfs4_put_delegation(struct nfs4_delegation *dp)
+ static void
+ nfs4_close_delegation(struct nfs4_delegation *dp)
+ {
+-	struct file *filp = dp->dl_vfs_file;
++	struct file *filp = find_readable_file(dp->dl_file);
+ 
+ 	dprintk("NFSD: close_delegation dp %p\n",dp);
+-	dp->dl_vfs_file = NULL;
+-	/* The following nfsd_close may not actually close the file,
+-	 * but we want to remove the lease in any case. */
+ 	if (dp->dl_flock)
+ 		vfs_setlease(filp, F_UNLCK, &dp->dl_flock);
+-	nfsd_close(filp);
++	nfs4_file_put_access(dp->dl_file, O_RDONLY);
+ }
+ 
+ /* Called under the state lock. */
+@@ -308,8 +326,12 @@ static void free_generic_stateid(struct nfs4_stateid *stp)
+ 
+ static void release_lock_stateid(struct nfs4_stateid *stp)
+ {
++	struct file *file;
++
+ 	unhash_generic_stateid(stp);
+-	locks_remove_posix(stp->st_vfs_file, (fl_owner_t)stp->st_stateowner);
++	file = find_any_file(stp->st_file);
++	if (file)
++		locks_remove_posix(file, (fl_owner_t)stp->st_stateowner);
+ 	free_generic_stateid(stp);
+ }
+ 
+@@ -347,11 +369,85 @@ release_stateid_lockowners(struct nfs4_stateid *open_stp)
+ 	}
+ }
+ 
++/*
++ * We store the NONE, READ, WRITE, and BOTH bits separately in the
++ * st_{access,deny}_bmap field of the stateid, in order to track not
++ * only what share bits are currently in force, but also what
++ * combinations of share bits previous opens have used.  This allows us
++ * to enforce the recommendation of rfc 3530 14.2.19 that the server
++ * return an error if the client attempt to downgrade to a combination
++ * of share bits not explicable by closing some of its previous opens.
++ *
++ * XXX: This enforcement is actually incomplete, since we don't keep
++ * track of access/deny bit combinations; so, e.g., we allow:
++ *
++ *	OPEN allow read, deny write
++ *	OPEN allow both, deny none
++ *	DOWNGRADE allow read, deny none
++ *
++ * which we should reject.
++ */
++static void
++set_access(unsigned int *access, unsigned long bmap) {
++	int i;
++
++	*access = 0;
++	for (i = 1; i < 4; i++) {
++		if (test_bit(i, &bmap))
++			*access |= i;
++	}
++}
++
++static void
++set_deny(unsigned int *deny, unsigned long bmap) {
++	int i;
++
++	*deny = 0;
++	for (i = 0; i < 4; i++) {
++		if (test_bit(i, &bmap))
++			*deny |= i ;
++	}
++}
++
++static int
++test_share(struct nfs4_stateid *stp, struct nfsd4_open *open) {
++	unsigned int access, deny;
++
++	set_access(&access, stp->st_access_bmap);
++	set_deny(&deny, stp->st_deny_bmap);
++	if ((access & open->op_share_deny) || (deny & open->op_share_access))
++		return 0;
++	return 1;
++}
++
++static int nfs4_access_to_omode(u32 access)
++{
++	switch (access) {
++	case NFS4_SHARE_ACCESS_READ:
++		return O_RDONLY;
++	case NFS4_SHARE_ACCESS_WRITE:
++		return O_WRONLY;
++	case NFS4_SHARE_ACCESS_BOTH:
++		return O_RDWR;
++	}
++	BUG();
++}
++
++static int nfs4_access_bmap_to_omode(struct nfs4_stateid *stp)
++{
++	unsigned int access;
++
++	set_access(&access, stp->st_access_bmap);
++	return nfs4_access_to_omode(access);
++}
++
+ static void release_open_stateid(struct nfs4_stateid *stp)
+ {
++	int oflag = nfs4_access_bmap_to_omode(stp);
++
+ 	unhash_generic_stateid(stp);
+ 	release_stateid_lockowners(stp);
+-	nfsd_close(stp->st_vfs_file);
++	nfs4_file_put_access(stp->st_file, oflag);
+ 	free_generic_stateid(stp);
+ }
+ 
+@@ -1763,6 +1859,8 @@ alloc_init_file(struct inode *ino)
+ 		fp->fi_inode = igrab(ino);
+ 		fp->fi_id = current_fileid++;
+ 		fp->fi_had_conflict = false;
++		memset(fp->fi_fds, 0, sizeof(fp->fi_fds));
++		memset(fp->fi_access, 0, sizeof(fp->fi_access));
+ 		spin_lock(&recall_lock);
+ 		list_add(&fp->fi_hash, &file_hashtbl[hashval]);
+ 		spin_unlock(&recall_lock);
+@@ -1973,57 +2071,6 @@ static inline int deny_valid(u32 x)
+ 	return x <= NFS4_SHARE_DENY_BOTH;
+ }
+ 
+-/*
+- * We store the NONE, READ, WRITE, and BOTH bits separately in the
+- * st_{access,deny}_bmap field of the stateid, in order to track not
+- * only what share bits are currently in force, but also what
+- * combinations of share bits previous opens have used.  This allows us
+- * to enforce the recommendation of rfc 3530 14.2.19 that the server
+- * return an error if the client attempt to downgrade to a combination
+- * of share bits not explicable by closing some of its previous opens.
+- *
+- * XXX: This enforcement is actually incomplete, since we don't keep
+- * track of access/deny bit combinations; so, e.g., we allow:
+- *
+- *	OPEN allow read, deny write
+- *	OPEN allow both, deny none
+- *	DOWNGRADE allow read, deny none
+- *
+- * which we should reject.
+- */
+-static void
+-set_access(unsigned int *access, unsigned long bmap) {
+-	int i;
+-
+-	*access = 0;
+-	for (i = 1; i < 4; i++) {
+-		if (test_bit(i, &bmap))
+-			*access |= i;
+-	}
+-}
+-
+-static void
+-set_deny(unsigned int *deny, unsigned long bmap) {
+-	int i;
+-
+-	*deny = 0;
+-	for (i = 0; i < 4; i++) {
+-		if (test_bit(i, &bmap))
+-			*deny |= i ;
+-	}
+-}
+-
+-static int
+-test_share(struct nfs4_stateid *stp, struct nfsd4_open *open) {
+-	unsigned int access, deny;
+-
+-	set_access(&access, stp->st_access_bmap);
+-	set_deny(&deny, stp->st_deny_bmap);
+-	if ((access & open->op_share_deny) || (deny & open->op_share_access))
+-		return 0;
+-	return 1;
+-}
+-
+ /*
+  * Called to check deny when READ with all zero stateid or
+  * WRITE with all zero or all one stateid
+@@ -2055,14 +2102,12 @@ nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
+ }
+ 
+ static inline void
+-nfs4_file_downgrade(struct file *filp, unsigned int share_access)
++nfs4_file_downgrade(struct nfs4_file *fp, unsigned int share_access)
+ {
+-	if (share_access & NFS4_SHARE_ACCESS_WRITE) {
+-		drop_file_write_access(filp);
+-		spin_lock(&filp->f_lock);
+-		filp->f_mode = (filp->f_mode | FMODE_READ) & ~FMODE_WRITE;
+-		spin_unlock(&filp->f_lock);
+-	}
++	if (share_access & NFS4_SHARE_ACCESS_WRITE)
++		nfs4_file_put_access(fp, O_WRONLY);
++	if (share_access & NFS4_SHARE_ACCESS_READ)
++		nfs4_file_put_access(fp, O_RDONLY);
+ }
+ 
+ /*
+@@ -2328,32 +2373,42 @@ static inline int nfs4_access_to_access(u32 nfs4_access)
+ 	return flags;
+ }
+ 
++static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file
++*fp, struct svc_fh *cur_fh, u32 nfs4_access)
++{
++	__be32 status;
++	int oflag = nfs4_access_to_omode(nfs4_access);
++	int access = nfs4_access_to_access(nfs4_access);
++
++	if (!fp->fi_fds[oflag]) {
++		status = nfsd_open(rqstp, cur_fh, S_IFREG, access,
++			&fp->fi_fds[oflag]);
++		if (status == nfserr_dropit)
++			status = nfserr_jukebox;
++		if (status)
++			return status;
++	}
++	nfs4_file_get_access(fp, oflag);
++
++	return nfs_ok;
++}
++
+ static __be32
+ nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp,
+-		struct nfs4_delegation *dp,
+-		struct svc_fh *cur_fh, struct nfsd4_open *open)
++		struct nfs4_file *fp, struct svc_fh *cur_fh,
++		struct nfsd4_open *open)
+ {
+ 	struct nfs4_stateid *stp;
++	__be32 status;
+ 
+ 	stp = nfs4_alloc_stateid();
+ 	if (stp == NULL)
+ 		return nfserr_resource;
+ 
+-	if (dp) {
+-		get_file(dp->dl_vfs_file);
+-		stp->st_vfs_file = dp->dl_vfs_file;
+-	} else {
+-		__be32 status;
+-		int access = nfs4_access_to_access(open->op_share_access);
+-
+-		status = nfsd_open(rqstp, cur_fh, S_IFREG, access,
+-					&stp->st_vfs_file);
+-		if (status) {
+-			if (status == nfserr_dropit)
+-				status = nfserr_jukebox;
+-			kmem_cache_free(stateid_slab, stp);
+-			return status;
+-		}
++	status = nfs4_get_vfs_file(rqstp, fp, cur_fh, open->op_share_access);
++	if (status) {
++		kmem_cache_free(stateid_slab, stp);
++		return status;
+ 	}
+ 	*stpp = stp;
+ 	return 0;
+@@ -2375,36 +2430,29 @@ nfsd4_truncate(struct svc_rqst *rqstp, struct svc_fh *fh,
+ }
+ 
+ static __be32
+-nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_stateid *stp, struct nfsd4_open *open)
++nfs4_upgrade_open(struct svc_rqst *rqstp, struct nfs4_file *fp, struct svc_fh *cur_fh, struct nfs4_stateid *stp, struct nfsd4_open *open)
+ {
+-	struct file *filp = stp->st_vfs_file;
+-	struct inode *inode = filp->f_path.dentry->d_inode;
+-	unsigned int share_access, new_writer;
+-	u32 op_share_access;
++	u32 op_share_access, new_access;
+ 	__be32 status;
+ 
+-	set_access(&share_access, stp->st_access_bmap);
+-	new_writer = (~share_access) & open->op_share_access
+-			& NFS4_SHARE_ACCESS_WRITE;
+-
+-	if (new_writer) {
+-		int err = get_write_access(inode);
+-		if (err)
+-			return nfserrno(err);
+-		err = mnt_want_write(cur_fh->fh_export->ex_path.mnt);
+-		if (err)
+-			return nfserrno(err);
+-		file_take_write(filp);
++	set_access(&new_access, stp->st_access_bmap);
++	new_access = (~new_access) & open->op_share_access & ~NFS4_SHARE_WANT_MASK;
++
++	if (new_access) {
++		status = nfs4_get_vfs_file(rqstp, fp, cur_fh, new_access);
++		if (status)
++			return status;
+ 	}
+ 	status = nfsd4_truncate(rqstp, cur_fh, open);
+ 	if (status) {
+-		if (new_writer)
+-			put_write_access(inode);
++		if (new_access) {
++			int oflag = nfs4_access_to_omode(new_access);
++			nfs4_file_put_access(fp, oflag);
++		}
+ 		return status;
+ 	}
+ 	/* remember the open */
+ 	op_share_access = open->op_share_access & ~NFS4_SHARE_WANT_MASK;
+-	filp->f_mode |= op_share_access;
+ 	__set_bit(op_share_access, &stp->st_access_bmap);
+ 	__set_bit(open->op_share_deny, &stp->st_deny_bmap);
+ 
+@@ -2468,13 +2516,14 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
+ 	fl.fl_type = flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK;
+ 	fl.fl_end = OFFSET_MAX;
+ 	fl.fl_owner =  (fl_owner_t)dp;
+-	fl.fl_file = stp->st_vfs_file;
++	fl.fl_file = find_readable_file(stp->st_file);
++	BUG_ON(!fl.fl_file);
+ 	fl.fl_pid = current->tgid;
+ 
+ 	/* vfs_setlease checks to see if delegation should be handed out.
+ 	 * the lock_manager callbacks fl_mylease and fl_change are used
+ 	 */
+-	if ((status = vfs_setlease(stp->st_vfs_file, fl.fl_type, &flp))) {
++	if ((status = vfs_setlease(fl.fl_file, fl.fl_type, &flp))) {
+ 		dprintk("NFSD: setlease failed [%d], no delegation\n", status);
+ 		unhash_delegation(dp);
+ 		flag = NFS4_OPEN_DELEGATE_NONE;
+@@ -2538,13 +2587,12 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
+ 	 */
+ 	if (stp) {
+ 		/* Stateid was found, this is an OPEN upgrade */
+-		status = nfs4_upgrade_open(rqstp, current_fh, stp, open);
++		status = nfs4_upgrade_open(rqstp, fp, current_fh, stp, open);
+ 		if (status)
+ 			goto out;
+ 		update_stateid(&stp->st_stateid);
+ 	} else {
+-		/* Stateid was not found, this is a new OPEN */
+-		status = nfs4_new_open(rqstp, &stp, dp, current_fh, open);
++		status = nfs4_new_open(rqstp, &stp, fp, current_fh, open);
+ 		if (status)
+ 			goto out;
+ 		init_stateid(stp, fp, open);
+@@ -2746,7 +2794,7 @@ search_close_lru(u32 st_id, int flags)
+ static inline int
+ nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp)
+ {
+-	return fhp->fh_dentry->d_inode != stp->st_vfs_file->f_path.dentry->d_inode;
++	return fhp->fh_dentry->d_inode != stp->st_file->fi_inode;
+ }
+ 
+ static int
+@@ -2894,7 +2942,8 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
+ 			goto out;
+ 		renew_client(dp->dl_client);
+ 		if (filpp)
+-			*filpp = dp->dl_vfs_file;
++			*filpp = find_readable_file(dp->dl_file);
++		BUG_ON(!*filpp);
+ 	} else { /* open or lock stateid */
+ 		stp = find_stateid(stateid, flags);
+ 		if (!stp)
+@@ -2911,8 +2960,13 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
+ 		if (status)
+ 			goto out;
+ 		renew_client(stp->st_stateowner->so_client);
+-		if (filpp)
+-			*filpp = stp->st_vfs_file;
++		if (filpp) {
++			if (flags & RD_STATE)
++				*filpp = find_readable_file(stp->st_file);
++			else
++				*filpp = find_writeable_file(stp->st_file);
++			BUG_ON(!*filpp); /* assured by check_openmode */
++		}
+ 	}
+ 	status = nfs_ok;
+ out:
+@@ -3148,8 +3202,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
+ 		goto out;
+ 	}
+ 	set_access(&share_access, stp->st_access_bmap);
+-	nfs4_file_downgrade(stp->st_vfs_file,
+-	                    share_access & ~od->od_share_access);
++	nfs4_file_downgrade(stp->st_file, share_access & ~od->od_share_access);
+ 
+ 	reset_union_bmap_access(od->od_share_access, &stp->st_access_bmap);
+ 	reset_union_bmap_deny(od->od_share_deny, &stp->st_deny_bmap);
+@@ -3468,7 +3521,6 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc
+ 	stp->st_stateid.si_stateownerid = sop->so_id;
+ 	stp->st_stateid.si_fileid = fp->fi_id;
+ 	stp->st_stateid.si_generation = 0;
+-	stp->st_vfs_file = open_stp->st_vfs_file; /* FIXME refcount?? */
+ 	stp->st_deny_bmap = open_stp->st_deny_bmap;
+ 	stp->st_openstp = open_stp;
+ 
+@@ -3568,7 +3620,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 		lock_sop = lock->lk_replay_owner;
+ 	}
+ 	/* lock->lk_replay_owner and lock_stp have been created or found */
+-	filp = lock_stp->st_vfs_file;
+ 
+ 	status = nfserr_grace;
+ 	if (locks_in_grace() && !lock->lk_reclaim)
+@@ -3581,11 +3632,13 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	switch (lock->lk_type) {
+ 		case NFS4_READ_LT:
+ 		case NFS4_READW_LT:
++			filp = find_readable_file(lock_stp->st_file);
+ 			file_lock.fl_type = F_RDLCK;
+ 			cmd = F_SETLK;
+ 		break;
+ 		case NFS4_WRITE_LT:
+ 		case NFS4_WRITEW_LT:
++			filp = find_writeable_file(lock_stp->st_file);
+ 			file_lock.fl_type = F_WRLCK;
+ 			cmd = F_SETLK;
+ 		break;
+@@ -3593,6 +3646,10 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 			status = nfserr_inval;
+ 		goto out;
+ 	}
++	if (!filp) {
++		status = nfserr_openmode;
++		goto out;
++	}
+ 	file_lock.fl_owner = (fl_owner_t)lock_sop;
+ 	file_lock.fl_pid = current->tgid;
+ 	file_lock.fl_file = filp;
+@@ -3761,7 +3818,11 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 					&locku->lu_stateowner, &stp, NULL)))
+ 		goto out;
+ 
+-	filp = stp->st_vfs_file;
++	filp = find_any_file(stp->st_file);
++	if (!filp) {
++		status = nfserr_lock_range;
++		goto out;
++	}
+ 	BUG_ON(!filp);
+ 	locks_init_lock(&file_lock);
+ 	file_lock.fl_type = F_UNLCK;
+@@ -3808,10 +3869,10 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+  * 	0: no locks held by lockowner
+  */
+ static int
+-check_for_locks(struct file *filp, struct nfs4_stateowner *lowner)
++check_for_locks(struct nfs4_file *filp, struct nfs4_stateowner *lowner)
+ {
+ 	struct file_lock **flpp;
+-	struct inode *inode = filp->f_path.dentry->d_inode;
++	struct inode *inode = filp->fi_inode;
+ 	int status = 0;
+ 
+ 	lock_kernel();
+@@ -3862,7 +3923,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
+ 				continue;
+ 			list_for_each_entry(stp, &sop->so_stateids,
+ 					st_perstateowner) {
+-				if (check_for_locks(stp->st_vfs_file, sop))
++				if (check_for_locks(stp->st_file, sop))
+ 					goto out;
+ 				/* Note: so_perclient unused for lockowners,
+ 				 * so it's OK to fool with here. */
+diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
+index 72377761270e..b76ac3a82e39 100644
+--- a/fs/nfsd/nfsd.h
++++ b/fs/nfsd/nfsd.h
+@@ -153,6 +153,7 @@ void		nfsd_lockd_shutdown(void);
+ #define nfserr_bad_seqid	cpu_to_be32(NFSERR_BAD_SEQID)
+ #define	nfserr_symlink		cpu_to_be32(NFSERR_SYMLINK)
+ #define	nfserr_not_same		cpu_to_be32(NFSERR_NOT_SAME)
++#define nfserr_lock_range	cpu_to_be32(NFSERR_LOCK_RANGE)
+ #define	nfserr_restorefh	cpu_to_be32(NFSERR_RESTOREFH)
+ #define	nfserr_attrnotsupp	cpu_to_be32(NFSERR_ATTRNOTSUPP)
+ #define	nfserr_bad_xdr		cpu_to_be32(NFSERR_BAD_XDR)
+diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
+index 006c84230c7c..7731a75971dd 100644
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -88,7 +88,6 @@ struct nfs4_delegation {
+ 	struct nfs4_client	*dl_client;
+ 	struct nfs4_file	*dl_file;
+ 	struct file_lock	*dl_flock;
+-	struct file		*dl_vfs_file;
+ 	u32			dl_type;
+ 	time_t			dl_time;
+ /* For recall: */
+@@ -342,12 +341,50 @@ struct nfs4_file {
+ 	struct list_head        fi_hash;    /* hash by "struct inode *" */
+ 	struct list_head        fi_stateids;
+ 	struct list_head	fi_delegations;
++	/* One each for O_RDONLY, O_WRONLY, O_RDWR: */
++	struct file *		fi_fds[3];
++	/* One each for O_RDONLY, O_WRONLY: */
++	atomic_t		fi_access[2];
++	/*
++	 * Each open stateid contributes 1 to either fi_readers or
++	 * fi_writers, or both, depending on the open mode.  A
++	 * delegation also takes an fi_readers reference.  Lock
++	 * stateid's take none.
++	 */
++	atomic_t		fi_readers;
++	atomic_t		fi_writers;
+ 	struct inode		*fi_inode;
+ 	u32                     fi_id;      /* used with stateowner->so_id 
+ 					     * for stateid_hashtbl hash */
+ 	bool			fi_had_conflict;
+ };
+ 
++/* XXX: for first cut may fall back on returning file that doesn't work
++ * at all? */
++static inline struct file *find_writeable_file(struct nfs4_file *f)
++{
++	if (f->fi_fds[O_RDWR])
++		return f->fi_fds[O_RDWR];
++	return f->fi_fds[O_WRONLY];
++}
++
++static inline struct file *find_readable_file(struct nfs4_file *f)
++{
++	if (f->fi_fds[O_RDWR])
++		return f->fi_fds[O_RDWR];
++	return f->fi_fds[O_RDONLY];
++}
++
++static inline struct file *find_any_file(struct nfs4_file *f)
++{
++	if (f->fi_fds[O_RDWR])
++		return f->fi_fds[O_RDWR];
++	else if (f->fi_fds[O_RDWR])
++		return f->fi_fds[O_WRONLY];
++	else
++		return f->fi_fds[O_RDONLY];
++}
++
+ /*
+ * nfs4_stateid can either be an open stateid or (eventually) a lock stateid
+ *
+@@ -373,7 +410,6 @@ struct nfs4_stateid {
+ 	struct nfs4_stateowner      * st_stateowner;
+ 	struct nfs4_file            * st_file;
+ 	stateid_t                     st_stateid;
+-	struct file                 * st_vfs_file;
+ 	unsigned long                 st_access_bmap;
+ 	unsigned long                 st_deny_bmap;
+ 	struct nfs4_stateid         * st_openstp;

commit 866e26115cba6b59cec669b6307599e3e4440491
+Author: J. Bruce Fields 
+Date:   Tue Jul 20 15:23:15 2010 -0700
+
+    timers: Document meaning of deferrable timer
+    
+    Steal some text from 6e453a67510 "Add support for deferrable timers".  A
+    reader shouldn't have to dig through the git logs for the basic
+    description of a deferrable timer.
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: johnstul@us.ibm.com
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Thomas Gleixner 
+
+diff --git a/kernel/timer.c b/kernel/timer.c
+index ee305c8d4e18..ce98685cd1cb 100644
+--- a/kernel/timer.c
++++ b/kernel/timer.c
+@@ -90,8 +90,13 @@ static DEFINE_PER_CPU(struct tvec_base *, tvec_bases) = &boot_tvec_bases;
+ 
+ /*
+  * Note that all tvec_bases are 2 byte aligned and lower bit of
+- * base in timer_list is guaranteed to be zero. Use the LSB for
+- * the new flag to indicate whether the timer is deferrable
++ * base in timer_list is guaranteed to be zero. Use the LSB to
++ * indicate whether the timer is deferrable.
++ *
++ * A deferrable timer will work normally when the system is busy, but
++ * will not cause a CPU to come out of idle just to service it; instead,
++ * the timer will be serviced when the CPU eventually wakes up with a
++ * subsequent non-deferrable timer.
+  */
+ #define TBASE_DEFERRABLE_FLAG		(0x1)
+ 

commit 6a85d6c76962db769bb2f2cb11b17b16f32c4158
+Author: J. Bruce Fields 
+Date:   Tue Jul 6 12:39:12 2010 -0400
+
+    nfsd4: comment nitpick
+    
+    Reported-by: "Madan, Anshul" 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index ebbf3b6b2457..e3611b55531b 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -605,7 +605,7 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_ac
+ 	return error;
+ }
+ 
+-#endif /* defined(CONFIG_NFS_V4) */
++#endif /* defined(CONFIG_NFSD_V4) */
+ 
+ #ifdef CONFIG_NFSD_V3
+ /*

commit cba9ba4b902270c22f8b9c5149a284216b633fc1
+Author: J. Bruce Fields 
+Date:   Tue Jun 1 11:21:40 2010 -0400
+
+    nfsd4: fix delegation recall race use-after-free
+    
+    When the rarely-used callback-connection-changing setclientid occurs
+    simultaneously with a delegation recall, we rerun the recall by
+    requeueing it on a workqueue.  But we also need to take a reference on
+    the delegation in that case, since the delegation held by the rpc itself
+    will be released by the rpc_release callback.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index a4686326b5ae..1e6497ed3e12 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -689,6 +689,7 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
+ 		warn_no_callback_path(clp, task->tk_status);
+ 		if (current_rpc_client != task->tk_client) {
+ 			/* queue a callback on the new connection: */
++			atomic_inc(&dp->dl_count);
+ 			nfsd4_cb_recall(dp);
+ 			return;
+ 		}

commit ac94bf582529343bb7f354d0eef6dc4e566bbbd5
+Author: J. Bruce Fields 
+Date:   Mon May 31 19:06:39 2010 -0400
+
+    nfsd4: fix deleg leak on callback error
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 874a56a0801c..a4686326b5ae 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -761,8 +761,10 @@ static void _nfsd4_cb_recall(struct nfs4_delegation *dp)
+ 		.rpc_cred = callback_cred
+ 	};
+ 
+-	if (clnt == NULL)
++	if (clnt == NULL) {
++		nfs4_put_delegation(dp);
+ 		return; /* Client is shutting down; give up. */
++	}
+ 
+ 	args->args_op = dp;
+ 	msg.rpc_argp = args;

commit ec8acac84aea4245ae2cc999d56a68f0302cc847
+Author: J. Bruce Fields 
+Date:   Wed Jun 16 13:03:04 2010 -0400
+
+    nfsd4: remove some debugging code
+    
+    This is overkill.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 603076f66fe7..182448f7112a 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -591,10 +591,8 @@ find_in_sessionid_hashtbl(struct nfs4_sessionid *sessionid)
+ 
+ 	dump_sessionid(__func__, sessionid);
+ 	idx = hash_sessionid(sessionid);
+-	dprintk("%s: idx is %d\n", __func__, idx);
+ 	/* Search in the appropriate list */
+ 	list_for_each_entry(elem, &sessionid_hashtbl[idx], se_hash) {
+-		dump_sessionid("list traversal", &elem->se_sessionid);
+ 		if (!memcmp(elem->se_sessionid.data, sessionid->data,
+ 			    NFS4_MAX_SESSIONID_LEN)) {
+ 			return elem;

commit 4731030d58a146630f5e8a0519661a5344a60f45
+Author: J. Bruce Fields 
+Date:   Tue Jun 22 16:17:12 2010 -0400
+
+    nfsd4: translate memory errors to delay, not serverfault
+    
+    If the server is out of memory is better for clients to back off and
+    retry than to just error out.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 5a69ee69b44f..603076f66fe7 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -457,7 +457,7 @@ static int set_forechannel_drc_size(struct nfsd4_channel_attrs *fchan)
+ 	spin_unlock(&nfsd_drc_lock);
+ 
+ 	if (fchan->maxreqs == 0)
+-		return nfserr_serverfault;
++		return nfserr_jukebox;
+ 
+ 	fchan->maxresp_cached = size + NFSD_MIN_HDR_SEQ_SZ;
+ 	return 0;
+@@ -542,7 +542,7 @@ alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp,
+ 	BUILD_BUG_ON(NFSD_MAX_SLOTS_PER_SESSION * sizeof(struct nfsd4_slot)
+ 		     + sizeof(struct nfsd4_session) > PAGE_SIZE);
+ 
+-	status = nfserr_serverfault;
++	status = nfserr_jukebox;
+ 	/* allocate struct nfsd4_session and slot table pointers in one piece */
+ 	slotsize = tmp.se_fchannel.maxreqs * sizeof(struct nfsd4_slot *);
+ 	new = kzalloc(sizeof(*new) + slotsize, GFP_KERNEL);
+@@ -1219,7 +1219,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
+ 	/* Normal case */
+ 	new = create_client(exid->clname, dname, rqstp, &verf);
+ 	if (new == NULL) {
+-		status = nfserr_serverfault;
++		status = nfserr_jukebox;
+ 		goto out;
+ 	}
+ 

commit 76407f76e0f71428f3c31faff004bff87fea51ba
+Author: J. Bruce Fields 
+Date:   Tue Jun 22 14:10:14 2010 -0400
+
+    nfsd4; fix session reference count leak
+    
+    Note the session has to be put() here regardless of what happens to the
+    client.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 117670864af0..5a69ee69b44f 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -714,7 +714,6 @@ release_session_client(struct nfsd4_session *session)
+ 	} else
+ 		renew_client_locked(clp);
+ 	spin_unlock(&client_lock);
+-	nfsd4_put_session(session);
+ }
+ 
+ /* must be called under the client_lock */
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index ac17a7080239..835924f5ca54 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -3325,6 +3325,7 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compo
+ 		}
+ 		/* Renew the clientid on success and on replay */
+ 		release_session_client(cs->session);
++		nfsd4_put_session(cs->session);
+ 	}
+ 	return 1;
+ }

commit 44b56603c4c476b845a824cff6fe905c6268b2a1
+Merge: c3935e304958 b160fdabe93a
+Author: J. Bruce Fields 
+Date:   Tue Jun 8 20:05:18 2010 -0400
+
+    Merge branch 'for-2.6.34-incoming' into for-2.6.35-incoming
+

commit c3935e30495869dd611e1cd62253c94ebc7c6c04
+Author: J. Bruce Fields 
+Date:   Fri Jun 4 16:42:08 2010 -0400
+
+    nfsd4: shut down callback queue outside state lock
+    
+    This reportedly causes a lockdep warning on nfsd shutdown.  That looks
+    like a false positive to me, but there's no reason why this needs the
+    state lock anyway.
+    
+    Reported-by: Jeff Layton 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 12f7109720c2..4a2734758778 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -4122,8 +4122,8 @@ nfs4_state_shutdown(void)
+ 	nfs4_lock_state();
+ 	nfs4_release_reclaim();
+ 	__nfs4_state_shutdown();
+-	nfsd4_destroy_callback_queue();
+ 	nfs4_unlock_state();
++	nfsd4_destroy_callback_queue();
+ }
+ 
+ /*

commit 68a4b48ce6cb73a9643bae6dd3e0f062e3fd8ef7
+Author: J. Bruce Fields 
+Date:   Thu May 27 09:30:39 2010 -0400
+
+    nfsd4: don't bother storing callback reply tag
+    
+    We don't use this, and probably never will.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index ae917921ed41..c8dd03c3f0fd 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -143,8 +143,6 @@ struct nfs4_cb_compound_hdr {
+ 	u32		minorversion;
+ 	/* res */
+ 	int		status;
+-	u32		taglen;
+-	char		*tag;
+ };
+ 
+ static struct {
+@@ -293,13 +291,14 @@ nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, __be32 *p,
+ static int
+ decode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr){
+         __be32 *p;
++	u32 taglen;
+ 
+         READ_BUF(8);
+         READ32(hdr->status);
+-        READ32(hdr->taglen);
+-        READ_BUF(hdr->taglen + 4);
+-        hdr->tag = (char *)p;
+-        p += XDR_QUADLEN(hdr->taglen);
++	/* We've got no use for the tag; ignore it: */
++        READ32(taglen);
++        READ_BUF(taglen + 4);
++        p += XDR_QUADLEN(taglen);
+         READ32(hdr->nops);
+         return 0;
+ }

commit 24a0111e405abeb74701ce3b7b665365c27de19e
+Author: J. Bruce Fields 
+Date:   Tue May 18 20:01:35 2010 -0400
+
+    nfsd4: fix use of op_share_access
+    
+    NFSv4.1 adds additional flags to the share_access argument of the open
+    call.  These flags need to be masked out in some of the existing code,
+    but current code does that inconsistently.
+    
+    Tested-by: Michael Groshans 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 12f7109720c2..117670864af0 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2255,6 +2255,13 @@ find_delegation_file(struct nfs4_file *fp, stateid_t *stid)
+ 	return NULL;
+ }
+ 
++int share_access_to_flags(u32 share_access)
++{
++	share_access &= ~NFS4_SHARE_WANT_MASK;
++
++	return share_access == NFS4_SHARE_ACCESS_READ ? RD_STATE : WR_STATE;
++}
++
+ static __be32
+ nfs4_check_deleg(struct nfs4_file *fp, struct nfsd4_open *open,
+ 		struct nfs4_delegation **dp)
+@@ -2265,8 +2272,7 @@ nfs4_check_deleg(struct nfs4_file *fp, struct nfsd4_open *open,
+ 	*dp = find_delegation_file(fp, &open->op_delegate_stateid);
+ 	if (*dp == NULL)
+ 		goto out;
+-	flags = open->op_share_access == NFS4_SHARE_ACCESS_READ ?
+-						RD_STATE : WR_STATE;
++	flags = share_access_to_flags(open->op_share_access);
+ 	status = nfs4_check_delegmode(*dp, flags);
+ 	if (status)
+ 		*dp = NULL;
+@@ -2358,6 +2364,7 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_sta
+ 	struct file *filp = stp->st_vfs_file;
+ 	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	unsigned int share_access, new_writer;
++	u32 op_share_access;
+ 	__be32 status;
+ 
+ 	set_access(&share_access, stp->st_access_bmap);
+@@ -2380,8 +2387,9 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_sta
+ 		return status;
+ 	}
+ 	/* remember the open */
+-	filp->f_mode |= open->op_share_access;
+-	__set_bit(open->op_share_access, &stp->st_access_bmap);
++	op_share_access = open->op_share_access & ~NFS4_SHARE_WANT_MASK;
++	filp->f_mode |= op_share_access;
++	__set_bit(op_share_access, &stp->st_access_bmap);
+ 	__set_bit(open->op_share_deny, &stp->st_deny_bmap);
+ 
+ 	return nfs_ok;

commit 172c85dd5764d2766bfd68621e5b54e85c4a6cfa
+Author: J. Bruce Fields 
+Date:   Sun May 30 11:53:12 2010 -0400
+
+    nfsd4: treat more recall errors as failures
+    
+    If a recall fails for some unexpected reason, instead of ignoring it and
+    treating it like a success, it's safer to treat it as a failure,
+    preventing further delgation grants and returning CB_PATH_DOWN.
+    
+    Also put put switches in a (two me) more logical order, with normal case
+    first.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 8a21db22bba4..ae917921ed41 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -667,7 +667,14 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
+ 	}
+ 
+ 	switch (task->tk_status) {
+-	case -EIO:
++	case 0:
++		return;
++	case -EBADHANDLE:
++	case -NFS4ERR_BAD_STATEID:
++		/* Race: client probably got cb_recall
++		 * before open reply granting delegation */
++		break;
++	default:
+ 		/* Network partition? */
+ 		atomic_set(&clp->cl_cb_set, 0);
+ 		warn_no_callback_path(clp, task->tk_status);
+@@ -676,14 +683,6 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
+ 			nfsd4_cb_recall(dp);
+ 			return;
+ 		}
+-	case -EBADHANDLE:
+-	case -NFS4ERR_BAD_STATEID:
+-		/* Race: client probably got cb_recall
+-		 * before open reply granting delegation */
+-		break;
+-	default:
+-		/* success, or error we can't handle */
+-		return;
+ 	}
+ 	if (dp->dl_retries--) {
+ 		rpc_delay(task, 2*HZ);

commit 378b7d37f90399b7c34373a5925450529afb917b
+Author: J. Bruce Fields 
+Date:   Tue May 25 11:57:56 2010 -0400
+
+    nfsd4: remove extra put() on callback errors
+    
+    Since rpc_call_async() guarantees that the release method will be called
+    even on failure, this put is wrong.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index eb78e7e22077..8a21db22bba4 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -752,7 +752,6 @@ static void _nfsd4_cb_recall(struct nfs4_delegation *dp)
+ 		.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL],
+ 		.rpc_cred = callback_cred
+ 	};
+-	int status;
+ 
+ 	if (clnt == NULL)
+ 		return; /* Client is shutting down; give up. */
+@@ -760,10 +759,7 @@ static void _nfsd4_cb_recall(struct nfs4_delegation *dp)
+ 	args->args_op = dp;
+ 	msg.rpc_argp = args;
+ 	dp->dl_retries = 1;
+-	status = rpc_call_async(clnt, &msg, RPC_TASK_SOFT,
+-				&nfsd4_cb_recall_ops, dp);
+-	if (status)
+-		nfs4_put_delegation(dp);
++	rpc_call_async(clnt, &msg, RPC_TASK_SOFT, &nfsd4_cb_recall_ops, dp);
+ }
+ 
+ void nfsd4_do_callback_rpc(struct work_struct *w)

commit 0a68b0bed08eeb7ec62e0125f17856b1ccb1ea4b
+Author: J. Bruce Fields 
+Date:   Wed May 26 08:42:24 2010 -0400
+
+    sunrpc: fix leak on error on socket xprt setup
+    
+    Also collect exit code together while we're at it.
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: Trond Myklebust 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
+index b7cd8cccbe72..2a9675136c68 100644
+--- a/net/sunrpc/xprtsock.c
++++ b/net/sunrpc/xprtsock.c
+@@ -2293,6 +2293,7 @@ static struct rpc_xprt *xs_setup_udp(struct xprt_create *args)
+ 	struct sockaddr *addr = args->dstaddr;
+ 	struct rpc_xprt *xprt;
+ 	struct sock_xprt *transport;
++	struct rpc_xprt *ret;
+ 
+ 	xprt = xs_setup_xprt(args, xprt_udp_slot_table_entries);
+ 	if (IS_ERR(xprt))
+@@ -2330,8 +2331,8 @@ static struct rpc_xprt *xs_setup_udp(struct xprt_create *args)
+ 		xs_format_peer_addresses(xprt, "udp", RPCBIND_NETID_UDP6);
+ 		break;
+ 	default:
+-		kfree(xprt);
+-		return ERR_PTR(-EAFNOSUPPORT);
++		ret = ERR_PTR(-EAFNOSUPPORT);
++		goto out_err;
+ 	}
+ 
+ 	if (xprt_bound(xprt))
+@@ -2346,10 +2347,11 @@ static struct rpc_xprt *xs_setup_udp(struct xprt_create *args)
+ 
+ 	if (try_module_get(THIS_MODULE))
+ 		return xprt;
+-
++	ret = ERR_PTR(-EINVAL);
++out_err:
+ 	kfree(xprt->slot);
+ 	kfree(xprt);
+-	return ERR_PTR(-EINVAL);
++	return ret;
+ }
+ 
+ static const struct rpc_timeout xs_tcp_default_timeout = {
+@@ -2368,6 +2370,7 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args)
+ 	struct sockaddr *addr = args->dstaddr;
+ 	struct rpc_xprt *xprt;
+ 	struct sock_xprt *transport;
++	struct rpc_xprt *ret;
+ 
+ 	xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries);
+ 	if (IS_ERR(xprt))
+@@ -2403,8 +2406,8 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args)
+ 		xs_format_peer_addresses(xprt, "tcp", RPCBIND_NETID_TCP6);
+ 		break;
+ 	default:
+-		kfree(xprt);
+-		return ERR_PTR(-EAFNOSUPPORT);
++		ret = ERR_PTR(-EAFNOSUPPORT);
++		goto out_err;
+ 	}
+ 
+ 	if (xprt_bound(xprt))
+@@ -2420,10 +2423,11 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args)
+ 
+ 	if (try_module_get(THIS_MODULE))
+ 		return xprt;
+-
++	ret = ERR_PTR(-EINVAL);
++out_err:
+ 	kfree(xprt->slot);
+ 	kfree(xprt);
+-	return ERR_PTR(-EINVAL);
++	return ret;
+ }
+ 
+ /**
+@@ -2437,6 +2441,7 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
+ 	struct rpc_xprt *xprt;
+ 	struct sock_xprt *transport;
+ 	struct svc_sock *bc_sock;
++	struct rpc_xprt *ret;
+ 
+ 	xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries);
+ 	if (IS_ERR(xprt))
+@@ -2476,8 +2481,8 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
+ 				   RPCBIND_NETID_TCP6);
+ 		break;
+ 	default:
+-		kfree(xprt);
+-		return ERR_PTR(-EAFNOSUPPORT);
++		ret = ERR_PTR(-EAFNOSUPPORT);
++		goto out_err;
+ 	}
+ 
+ 	if (xprt_bound(xprt))
+@@ -2499,9 +2504,11 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
+ 
+ 	if (try_module_get(THIS_MODULE))
+ 		return xprt;
++	ret = ERR_PTR(-EINVAL);
++out_err:
+ 	kfree(xprt->slot);
+ 	kfree(xprt);
+-	return ERR_PTR(-EINVAL);
++	return ret;
+ }
+ 
+ static struct xprt_class	xs_udp_transport = {

commit e4e83ea47babd9d4bf95a13aed87f8ef51e46472
+Author: J. Bruce Fields 
+Date:   Thu Apr 22 16:21:39 2010 -0400
+
+    Revert "nfsd4: distinguish expired from stale stateids"
+    
+    This reverts commit 78155ed75f470710f2aecb3e75e3d97107ba8374.
+    
+    We're depending here on the boot time that we use to generate the
+    stateid being monotonic, but get_seconds() is not necessarily.
+    
+    We still depend at least on boot_time being different every time, but
+    that is a safer bet.
+    
+    We have a few reports of errors that might be explained by this problem,
+    though we haven't been able to confirm any of them.
+    
+    But the minor gain of distinguishing expired from stale errors seems not
+    worth the risk.
+    
+    Conflicts:
+    
+            fs/nfsd/nfs4state.c
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 296eded356b6..12f7109720c2 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -190,7 +190,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
+ 	dp->dl_vfs_file = stp->st_vfs_file;
+ 	dp->dl_type = type;
+ 	dp->dl_ident = cb->cb_ident;
+-	dp->dl_stateid.si_boot = get_seconds();
++	dp->dl_stateid.si_boot = boot_time;
+ 	dp->dl_stateid.si_stateownerid = current_delegid++;
+ 	dp->dl_stateid.si_fileid = 0;
+ 	dp->dl_stateid.si_generation = 0;
+@@ -1884,7 +1884,7 @@ init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *
+ 	stp->st_stateowner = sop;
+ 	get_nfs4_file(fp);
+ 	stp->st_file = fp;
+-	stp->st_stateid.si_boot = get_seconds();
++	stp->st_stateid.si_boot = boot_time;
+ 	stp->st_stateid.si_stateownerid = sop->so_id;
+ 	stp->st_stateid.si_fileid = fp->fi_id;
+ 	stp->st_stateid.si_generation = 0;
+@@ -2733,39 +2733,11 @@ nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp)
+ static int
+ STALE_STATEID(stateid_t *stateid)
+ {
+-	if (time_after((unsigned long)boot_time,
+-			(unsigned long)stateid->si_boot)) {
+-		dprintk("NFSD: stale stateid " STATEID_FMT "!\n",
+-			STATEID_VAL(stateid));
+-		return 1;
+-	}
+-	return 0;
+-}
+-
+-static int
+-EXPIRED_STATEID(stateid_t *stateid)
+-{
+-	if (time_before((unsigned long)boot_time,
+-			((unsigned long)stateid->si_boot)) &&
+-	    time_before((unsigned long)(stateid->si_boot + nfsd4_lease), get_seconds())) {
+-		dprintk("NFSD: expired stateid " STATEID_FMT "!\n",
+-			STATEID_VAL(stateid));
+-		return 1;
+-	}
+-	return 0;
+-}
+-
+-static __be32
+-stateid_error_map(stateid_t *stateid)
+-{
+-	if (STALE_STATEID(stateid))
+-		return nfserr_stale_stateid;
+-	if (EXPIRED_STATEID(stateid))
+-		return nfserr_expired;
+-
+-	dprintk("NFSD: bad stateid " STATEID_FMT "!\n",
++	if (stateid->si_boot == boot_time)
++		return 0;
++	dprintk("NFSD: stale stateid " STATEID_FMT "!\n",
+ 		STATEID_VAL(stateid));
+-	return nfserr_bad_stateid;
++	return 1;
+ }
+ 
+ static inline int
+@@ -2889,10 +2861,8 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
+ 	status = nfserr_bad_stateid;
+ 	if (is_delegation_stateid(stateid)) {
+ 		dp = find_delegation_stateid(ino, stateid);
+-		if (!dp) {
+-			status = stateid_error_map(stateid);
++		if (!dp)
+ 			goto out;
+-		}
+ 		status = check_stateid_generation(stateid, &dp->dl_stateid,
+ 						  flags);
+ 		if (status)
+@@ -2905,10 +2875,8 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
+ 			*filpp = dp->dl_vfs_file;
+ 	} else { /* open or lock stateid */
+ 		stp = find_stateid(stateid, flags);
+-		if (!stp) {
+-			status = stateid_error_map(stateid);
++		if (!stp)
+ 			goto out;
+-		}
+ 		if (nfs4_check_fh(current_fh, stp))
+ 			goto out;
+ 		if (!stp->st_stateowner->so_confirmed)
+@@ -2980,7 +2948,7 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
+ 		 */
+ 		sop = search_close_lru(stateid->si_stateownerid, flags);
+ 		if (sop == NULL)
+-			return stateid_error_map(stateid);
++			return nfserr_bad_stateid;
+ 		*sopp = sop;
+ 		goto check_replay;
+ 	}
+@@ -3247,10 +3215,8 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	if (!is_delegation_stateid(stateid))
+ 		goto out;
+ 	dp = find_delegation_stateid(inode, stateid);
+-	if (!dp) {
+-		status = stateid_error_map(stateid);
++	if (!dp)
+ 		goto out;
+-	}
+ 	status = check_stateid_generation(stateid, &dp->dl_stateid, flags);
+ 	if (status)
+ 		goto out;
+@@ -3476,7 +3442,7 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc
+ 	stp->st_stateowner = sop;
+ 	get_nfs4_file(fp);
+ 	stp->st_file = fp;
+-	stp->st_stateid.si_boot = get_seconds();
++	stp->st_stateid.si_boot = boot_time;
+ 	stp->st_stateid.si_stateownerid = sop->so_id;
+ 	stp->st_stateid.si_fileid = fp->fi_id;
+ 	stp->st_stateid.si_generation = 0;

commit b7299f44394336f51b526247a870d47d28f4f97c
+Author: J. Bruce Fields 
+Date:   Fri May 14 17:57:35 2010 -0400
+
+    nfs4: minor callback code simplification, comment
+    
+    Note the position in the version array doesn't have to match the actual
+    rpc version number--to me it seems clearer to maintain the distinction.
+    
+    Also document choice of rpc callback version number, as discussed in
+    e.g. http://www.ietf.org/mail-archive/web/nfsv4/current/msg07985.html
+    and followups.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 77bc9d3c80fd..eb78e7e22077 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -424,13 +424,19 @@ static struct rpc_procinfo     nfs4_cb_procedures[] = {
+ };
+ 
+ static struct rpc_version       nfs_cb_version4 = {
++/*
++ * Note on the callback rpc program version number: despite language in rfc
++ * 5661 section 18.36.3 requiring servers to use 4 in this field, the
++ * official xdr descriptions for both 4.0 and 4.1 specify version 1, and
++ * in practice that appears to be what implementations use.  The section
++ * 18.36.3 language is expected to be fixed in an erratum.
++ */
+         .number                 = 1,
+         .nrprocs                = ARRAY_SIZE(nfs4_cb_procedures),
+         .procs                  = nfs4_cb_procedures
+ };
+ 
+ static struct rpc_version *	nfs_cb_version[] = {
+-	NULL,
+ 	&nfs_cb_version4,
+ };
+ 
+@@ -471,7 +477,7 @@ int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *cb)
+ 		.timeout	= &timeparms,
+ 		.program	= &cb_program,
+ 		.prognumber	= cb->cb_prog,
+-		.version	= nfs_cb_version[1]->number,
++		.version	= 0,
+ 		.authflavor	= clp->cl_flavor,
+ 		.flags		= (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET),
+ 		.client_name    = clp->cl_principal,

commit fffdaef2eb4a7333952e55cf97f1fc0fcc35f981
+Author: Kevin Coffman 
+Date:   Wed Mar 17 13:03:06 2010 -0400
+
+    gss_krb5: Add support for rc4-hmac encryption
+    
+    Add necessary changes to add kernel support for the rc4-hmac Kerberos
+    encryption type used by Microsoft and described in rfc4757.
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: Steve Dickson 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
+index 79f6ac2492f5..5e774a5abf2c 100644
+--- a/include/linux/sunrpc/gss_krb5.h
++++ b/include/linux/sunrpc/gss_krb5.h
+@@ -317,5 +317,14 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset,
+ 		     struct xdr_buf *buf, u32 *plainoffset,
+ 		     u32 *plainlen);
+ 
++int
++krb5_rc4_setup_seq_key(struct krb5_ctx *kctx,
++		       struct crypto_blkcipher *cipher,
++		       unsigned char *cksum);
++
++int
++krb5_rc4_setup_enc_key(struct krb5_ctx *kctx,
++		       struct crypto_blkcipher *cipher,
++		       s32 seqnum);
+ void
+ gss_krb5_make_confounder(char *p, u32 conflen);
+diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+index ed4106a3daf2..75ee993ea057 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
++++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+@@ -124,6 +124,114 @@ checksummer(struct scatterlist *sg, void *data)
+ 	return crypto_hash_update(desc, sg, sg->length);
+ }
+ 
++static int
++arcfour_hmac_md5_usage_to_salt(unsigned int usage, u8 salt[4])
++{
++	unsigned int ms_usage;
++
++	switch (usage) {
++	case KG_USAGE_SIGN:
++		ms_usage = 15;
++		break;
++	case KG_USAGE_SEAL:
++		ms_usage = 13;
++		break;
++	default:
++		return EINVAL;;
++	}
++	salt[0] = (ms_usage >> 0) & 0xff;
++	salt[1] = (ms_usage >> 8) & 0xff;
++	salt[2] = (ms_usage >> 16) & 0xff;
++	salt[3] = (ms_usage >> 24) & 0xff;
++
++	return 0;
++}
++
++static u32
++make_checksum_hmac_md5(struct krb5_ctx *kctx, char *header, int hdrlen,
++		       struct xdr_buf *body, int body_offset, u8 *cksumkey,
++		       unsigned int usage, struct xdr_netobj *cksumout)
++{
++	struct hash_desc                desc;
++	struct scatterlist              sg[1];
++	int err;
++	u8 checksumdata[GSS_KRB5_MAX_CKSUM_LEN];
++	u8 rc4salt[4];
++	struct crypto_hash *md5;
++	struct crypto_hash *hmac_md5;
++
++	if (cksumkey == NULL)
++		return GSS_S_FAILURE;
++
++	if (cksumout->len < kctx->gk5e->cksumlength) {
++		dprintk("%s: checksum buffer length, %u, too small for %s\n",
++			__func__, cksumout->len, kctx->gk5e->name);
++		return GSS_S_FAILURE;
++	}
++
++	if (arcfour_hmac_md5_usage_to_salt(usage, rc4salt)) {
++		dprintk("%s: invalid usage value %u\n", __func__, usage);
++		return GSS_S_FAILURE;
++	}
++
++	md5 = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC);
++	if (IS_ERR(md5))
++		return GSS_S_FAILURE;
++
++	hmac_md5 = crypto_alloc_hash(kctx->gk5e->cksum_name, 0,
++				     CRYPTO_ALG_ASYNC);
++	if (IS_ERR(hmac_md5)) {
++		crypto_free_hash(md5);
++		return GSS_S_FAILURE;
++	}
++
++	desc.tfm = md5;
++	desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
++
++	err = crypto_hash_init(&desc);
++	if (err)
++		goto out;
++	sg_init_one(sg, rc4salt, 4);
++	err = crypto_hash_update(&desc, sg, 4);
++	if (err)
++		goto out;
++
++	sg_init_one(sg, header, hdrlen);
++	err = crypto_hash_update(&desc, sg, hdrlen);
++	if (err)
++		goto out;
++	err = xdr_process_buf(body, body_offset, body->len - body_offset,
++			      checksummer, &desc);
++	if (err)
++		goto out;
++	err = crypto_hash_final(&desc, checksumdata);
++	if (err)
++		goto out;
++
++	desc.tfm = hmac_md5;
++	desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
++
++	err = crypto_hash_init(&desc);
++	if (err)
++		goto out;
++	err = crypto_hash_setkey(hmac_md5, cksumkey, kctx->gk5e->keylength);
++	if (err)
++		goto out;
++
++	sg_init_one(sg, checksumdata, crypto_hash_digestsize(md5));
++	err = crypto_hash_digest(&desc, sg, crypto_hash_digestsize(md5),
++				 checksumdata);
++	if (err)
++		goto out;
++
++	memcpy(cksumout->data, checksumdata, kctx->gk5e->cksumlength);
++	cksumout->len = kctx->gk5e->cksumlength;
++out:
++	crypto_free_hash(md5);
++	crypto_free_hash(hmac_md5);
++	return err ? GSS_S_FAILURE : 0;
++}
++
+ /*
+  * checksum the plaintext data and hdrlen bytes of the token header
+  * The checksum is performed over the first 8 bytes of the
+@@ -140,6 +248,11 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
+ 	u8 checksumdata[GSS_KRB5_MAX_CKSUM_LEN];
+ 	unsigned int checksumlen;
+ 
++	if (kctx->gk5e->ctype == CKSUMTYPE_HMAC_MD5_ARCFOUR)
++		return make_checksum_hmac_md5(kctx, header, hdrlen,
++					      body, body_offset,
++					      cksumkey, usage, cksumout);
++
+ 	if (cksumout->len < kctx->gk5e->cksumlength) {
+ 		dprintk("%s: checksum buffer length, %u, too small for %s\n",
+ 			__func__, cksumout->len, kctx->gk5e->name);
+@@ -733,3 +846,145 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf,
+ 		ret = GSS_S_FAILURE;
+ 	return ret;
+ }
++
++/*
++ * Compute Kseq given the initial session key and the checksum.
++ * Set the key of the given cipher.
++ */
++int
++krb5_rc4_setup_seq_key(struct krb5_ctx *kctx, struct crypto_blkcipher *cipher,
++		       unsigned char *cksum)
++{
++	struct crypto_hash *hmac;
++	struct hash_desc desc;
++	struct scatterlist sg[1];
++	u8 Kseq[GSS_KRB5_MAX_KEYLEN];
++	u32 zeroconstant = 0;
++	int err;
++
++	dprintk("%s: entered\n", __func__);
++
++	hmac = crypto_alloc_hash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC);
++	if (IS_ERR(hmac)) {
++		dprintk("%s: error %ld, allocating hash '%s'\n",
++			__func__, PTR_ERR(hmac), kctx->gk5e->cksum_name);
++		return PTR_ERR(hmac);
++	}
++
++	desc.tfm = hmac;
++	desc.flags = 0;
++
++	err = crypto_hash_init(&desc);
++	if (err)
++		goto out_err;
++
++	/* Compute intermediate Kseq from session key */
++	err = crypto_hash_setkey(hmac, kctx->Ksess, kctx->gk5e->keylength);
++	if (err)
++		goto out_err;
++
++	sg_init_table(sg, 1);
++	sg_set_buf(sg, &zeroconstant, 4);
++
++	err = crypto_hash_digest(&desc, sg, 4, Kseq);
++	if (err)
++		goto out_err;
++
++	/* Compute final Kseq from the checksum and intermediate Kseq */
++	err = crypto_hash_setkey(hmac, Kseq, kctx->gk5e->keylength);
++	if (err)
++		goto out_err;
++
++	sg_set_buf(sg, cksum, 8);
++
++	err = crypto_hash_digest(&desc, sg, 8, Kseq);
++	if (err)
++		goto out_err;
++
++	err = crypto_blkcipher_setkey(cipher, Kseq, kctx->gk5e->keylength);
++	if (err)
++		goto out_err;
++
++	err = 0;
++
++out_err:
++	crypto_free_hash(hmac);
++	dprintk("%s: returning %d\n", __func__, err);
++	return err;
++}
++
++/*
++ * Compute Kcrypt given the initial session key and the plaintext seqnum.
++ * Set the key of cipher kctx->enc.
++ */
++int
++krb5_rc4_setup_enc_key(struct krb5_ctx *kctx, struct crypto_blkcipher *cipher,
++		       s32 seqnum)
++{
++	struct crypto_hash *hmac;
++	struct hash_desc desc;
++	struct scatterlist sg[1];
++	u8 Kcrypt[GSS_KRB5_MAX_KEYLEN];
++	u8 zeroconstant[4] = {0};
++	u8 seqnumarray[4];
++	int err, i;
++
++	dprintk("%s: entered, seqnum %u\n", __func__, seqnum);
++
++	hmac = crypto_alloc_hash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC);
++	if (IS_ERR(hmac)) {
++		dprintk("%s: error %ld, allocating hash '%s'\n",
++			__func__, PTR_ERR(hmac), kctx->gk5e->cksum_name);
++		return PTR_ERR(hmac);
++	}
++
++	desc.tfm = hmac;
++	desc.flags = 0;
++
++	err = crypto_hash_init(&desc);
++	if (err)
++		goto out_err;
++
++	/* Compute intermediate Kcrypt from session key */
++	for (i = 0; i < kctx->gk5e->keylength; i++)
++		Kcrypt[i] = kctx->Ksess[i] ^ 0xf0;
++
++	err = crypto_hash_setkey(hmac, Kcrypt, kctx->gk5e->keylength);
++	if (err)
++		goto out_err;
++
++	sg_init_table(sg, 1);
++	sg_set_buf(sg, zeroconstant, 4);
++
++	err = crypto_hash_digest(&desc, sg, 4, Kcrypt);
++	if (err)
++		goto out_err;
++
++	/* Compute final Kcrypt from the seqnum and intermediate Kcrypt */
++	err = crypto_hash_setkey(hmac, Kcrypt, kctx->gk5e->keylength);
++	if (err)
++		goto out_err;
++
++	seqnumarray[0] = (unsigned char) ((seqnum >> 24) & 0xff);
++	seqnumarray[1] = (unsigned char) ((seqnum >> 16) & 0xff);
++	seqnumarray[2] = (unsigned char) ((seqnum >> 8) & 0xff);
++	seqnumarray[3] = (unsigned char) ((seqnum >> 0) & 0xff);
++
++	sg_set_buf(sg, seqnumarray, 4);
++
++	err = crypto_hash_digest(&desc, sg, 4, Kcrypt);
++	if (err)
++		goto out_err;
++
++	err = crypto_blkcipher_setkey(cipher, Kcrypt, kctx->gk5e->keylength);
++	if (err)
++		goto out_err;
++
++	err = 0;
++
++out_err:
++	crypto_free_hash(hmac);
++	dprintk("%s: returning %d\n", __func__, err);
++	return err;
++}
++
+diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
+index ef6b31349046..54eda5f0c58b 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
++++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
+@@ -72,6 +72,27 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
+ 	  .cksumlength = 8,
+ 	  .keyed_cksum = 0,
+ 	},
++	/*
++	 * RC4-HMAC
++	 */
++	{
++	  .etype = ENCTYPE_ARCFOUR_HMAC,
++	  .ctype = CKSUMTYPE_HMAC_MD5_ARCFOUR,
++	  .name = "rc4-hmac",
++	  .encrypt_name = "ecb(arc4)",
++	  .cksum_name = "hmac(md5)",
++	  .encrypt = krb5_encrypt,
++	  .decrypt = krb5_decrypt,
++	  .mk_key = NULL,
++	  .signalg = SGN_ALG_HMAC_MD5,
++	  .sealalg = SEAL_ALG_MICROSOFT_RC4,
++	  .keybytes = 16,
++	  .keylength = 16,
++	  .blocksize = 1,
++	  .conflen = 8,
++	  .cksumlength = 8,
++	  .keyed_cksum = 1,
++	},
+ 	/*
+ 	 * 3DES
+ 	 */
+@@ -392,6 +413,79 @@ context_derive_keys_des3(struct krb5_ctx *ctx)
+ 	return -EINVAL;
+ }
+ 
++/*
++ * Note that RC4 depends on deriving keys using the sequence
++ * number or the checksum of a token.  Therefore, the final keys
++ * cannot be calculated until the token is being constructed!
++ */
++static int
++context_derive_keys_rc4(struct krb5_ctx *ctx)
++{
++	struct crypto_hash *hmac;
++	char sigkeyconstant[] = "signaturekey";
++	int slen = strlen(sigkeyconstant) + 1;	/* include null terminator */
++	struct hash_desc desc;
++	struct scatterlist sg[1];
++	int err;
++
++	dprintk("RPC:       %s: entered\n", __func__);
++	/*
++	 * derive cksum (aka Ksign) key
++	 */
++	hmac = crypto_alloc_hash(ctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC);
++	if (IS_ERR(hmac)) {
++		dprintk("%s: error %ld allocating hash '%s'\n",
++			__func__, PTR_ERR(hmac), ctx->gk5e->cksum_name);
++		err = PTR_ERR(hmac);
++		goto out_err;
++	}
++
++	err = crypto_hash_setkey(hmac, ctx->Ksess, ctx->gk5e->keylength);
++	if (err)
++		goto out_err_free_hmac;
++
++	sg_init_table(sg, 1);
++	sg_set_buf(sg, sigkeyconstant, slen);
++
++	desc.tfm = hmac;
++	desc.flags = 0;
++
++	err = crypto_hash_init(&desc);
++	if (err)
++		goto out_err_free_hmac;
++
++	err = crypto_hash_digest(&desc, sg, slen, ctx->cksum);
++	if (err)
++		goto out_err_free_hmac;
++	/*
++	 * allocate hash, and blkciphers for data and seqnum encryption
++	 */
++	ctx->enc = crypto_alloc_blkcipher(ctx->gk5e->encrypt_name, 0,
++					  CRYPTO_ALG_ASYNC);
++	if (IS_ERR(ctx->enc)) {
++		err = PTR_ERR(ctx->enc);
++		goto out_err_free_hmac;
++	}
++
++	ctx->seq = crypto_alloc_blkcipher(ctx->gk5e->encrypt_name, 0,
++					  CRYPTO_ALG_ASYNC);
++	if (IS_ERR(ctx->seq)) {
++		crypto_free_blkcipher(ctx->enc);
++		err = PTR_ERR(ctx->seq);
++		goto out_err_free_hmac;
++	}
++
++	dprintk("RPC:       %s: returning success\n", __func__);
++
++	err = 0;
++
++out_err_free_hmac:
++	crypto_free_hash(hmac);
++out_err:
++	dprintk("RPC:       %s: returning %d\n", __func__, err);
++	return err;
++}
++
+ static int
+ context_derive_keys_new(struct krb5_ctx *ctx)
+ {
+@@ -561,6 +655,8 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx)
+ 	switch (ctx->enctype) {
+ 	case ENCTYPE_DES3_CBC_RAW:
+ 		return context_derive_keys_des3(ctx);
++	case ENCTYPE_ARCFOUR_HMAC:
++		return context_derive_keys_rc4(ctx);
+ 	case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
+ 	case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
+ 		return context_derive_keys_new(ctx);
+diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
+index 36fe487d93d2..d7941eab7796 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
+@@ -213,6 +213,7 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
+ 		BUG();
+ 	case ENCTYPE_DES_CBC_RAW:
+ 	case ENCTYPE_DES3_CBC_RAW:
++	case ENCTYPE_ARCFOUR_HMAC:
+ 		return gss_get_mic_v1(ctx, text, token);
+ 	case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
+ 	case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
+diff --git a/net/sunrpc/auth_gss/gss_krb5_seqnum.c b/net/sunrpc/auth_gss/gss_krb5_seqnum.c
+index 83b593084976..415c013ba382 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_seqnum.c
++++ b/net/sunrpc/auth_gss/gss_krb5_seqnum.c
+@@ -39,6 +39,38 @@
+ # define RPCDBG_FACILITY        RPCDBG_AUTH
+ #endif
+ 
++static s32
++krb5_make_rc4_seq_num(struct krb5_ctx *kctx, int direction, s32 seqnum,
++		      unsigned char *cksum, unsigned char *buf)
++{
++	struct crypto_blkcipher *cipher;
++	unsigned char plain[8];
++	s32 code;
++
++	dprintk("RPC:       %s:\n", __func__);
++	cipher = crypto_alloc_blkcipher(kctx->gk5e->encrypt_name, 0,
++					CRYPTO_ALG_ASYNC);
++	if (IS_ERR(cipher))
++		return PTR_ERR(cipher);
++
++	plain[0] = (unsigned char) ((seqnum >> 24) & 0xff);
++	plain[1] = (unsigned char) ((seqnum >> 16) & 0xff);
++	plain[2] = (unsigned char) ((seqnum >> 8) & 0xff);
++	plain[3] = (unsigned char) ((seqnum >> 0) & 0xff);
++	plain[4] = direction;
++	plain[5] = direction;
++	plain[6] = direction;
++	plain[7] = direction;
++
++	code = krb5_rc4_setup_seq_key(kctx, cipher, cksum);
++	if (code)
++		goto out;
++
++	code = krb5_encrypt(cipher, cksum, plain, buf, 8);
++out:
++	crypto_free_blkcipher(cipher);
++	return code;
++}
+ s32
+ krb5_make_seq_num(struct krb5_ctx *kctx,
+ 		struct crypto_blkcipher *key,
+@@ -48,6 +80,10 @@ krb5_make_seq_num(struct krb5_ctx *kctx,
+ {
+ 	unsigned char plain[8];
+ 
++	if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC)
++		return krb5_make_rc4_seq_num(kctx, direction, seqnum,
++					     cksum, buf);
++
+ 	plain[0] = (unsigned char) (seqnum & 0xff);
+ 	plain[1] = (unsigned char) ((seqnum >> 8) & 0xff);
+ 	plain[2] = (unsigned char) ((seqnum >> 16) & 0xff);
+@@ -61,6 +97,43 @@ krb5_make_seq_num(struct krb5_ctx *kctx,
+ 	return krb5_encrypt(key, cksum, plain, buf, 8);
+ }
+ 
++static s32
++krb5_get_rc4_seq_num(struct krb5_ctx *kctx, unsigned char *cksum,
++		     unsigned char *buf, int *direction, s32 *seqnum)
++{
++	struct crypto_blkcipher *cipher;
++	unsigned char plain[8];
++	s32 code;
++
++	dprintk("RPC:       %s:\n", __func__);
++	cipher = crypto_alloc_blkcipher(kctx->gk5e->encrypt_name, 0,
++					CRYPTO_ALG_ASYNC);
++	if (IS_ERR(cipher))
++		return PTR_ERR(cipher);
++
++	code = krb5_rc4_setup_seq_key(kctx, cipher, cksum);
++	if (code)
++		goto out;
++
++	code = krb5_decrypt(cipher, cksum, buf, plain, 8);
++	if (code)
++		goto out;
++
++	if ((plain[4] != plain[5]) || (plain[4] != plain[6])
++				   || (plain[4] != plain[7])) {
++		code = (s32)KG_BAD_SEQ;
++		goto out;
++	}
++
++	*direction = plain[4];
++
++	*seqnum = ((plain[0] << 24) | (plain[1] << 16) |
++					(plain[2] << 8) | (plain[3]));
++out:
++	crypto_free_blkcipher(cipher);
++	return code;
++}
++
+ s32
+ krb5_get_seq_num(struct krb5_ctx *kctx,
+ 	       unsigned char *cksum,
+@@ -73,6 +146,10 @@ krb5_get_seq_num(struct krb5_ctx *kctx,
+ 
+ 	dprintk("RPC:       krb5_get_seq_num:\n");
+ 
++	if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC)
++		return krb5_get_rc4_seq_num(kctx, cksum, buf,
++					    direction, seqnum);
++
+ 	if ((code = krb5_decrypt(key, cksum, buf, plain, 8)))
+ 		return code;
+ 
+diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
+index 97eb91b8c70c..6cd930f3678f 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
+@@ -216,6 +216,7 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
+ 		BUG();
+ 	case ENCTYPE_DES_CBC_RAW:
+ 	case ENCTYPE_DES3_CBC_RAW:
++	case ENCTYPE_ARCFOUR_HMAC:
+ 		return gss_verify_mic_v1(ctx, message_buffer, read_token);
+ 	case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
+ 	case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
+diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+index 383db891c835..2763e3e48db4 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
++++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+@@ -232,9 +232,26 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
+ 			       seq_send, ptr + GSS_KRB5_TOK_HDR_LEN, ptr + 8)))
+ 		return GSS_S_FAILURE;
+ 
+-	if (gss_encrypt_xdr_buf(kctx->enc, buf, offset + headlen - conflen,
+-									pages))
+-		return GSS_S_FAILURE;
++	if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC) {
++		struct crypto_blkcipher *cipher;
++		int err;
++		cipher = crypto_alloc_blkcipher(kctx->gk5e->encrypt_name, 0,
++						CRYPTO_ALG_ASYNC);
++		if (IS_ERR(cipher))
++			return GSS_S_FAILURE;
++
++		krb5_rc4_setup_enc_key(kctx, cipher, seq_send);
++
++		err = gss_encrypt_xdr_buf(cipher, buf,
++					  offset + headlen - conflen, pages);
++		crypto_free_blkcipher(cipher);
++		if (err)
++			return GSS_S_FAILURE;
++	} else {
++		if (gss_encrypt_xdr_buf(kctx->enc, buf,
++					offset + headlen - conflen, pages))
++			return GSS_S_FAILURE;
++	}
+ 
+ 	return (kctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE;
+ }
+@@ -291,8 +308,37 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
+ 	 */
+ 	crypt_offset = ptr + (GSS_KRB5_TOK_HDR_LEN + kctx->gk5e->cksumlength) -
+ 					(unsigned char *)buf->head[0].iov_base;
+-	if (gss_decrypt_xdr_buf(kctx->enc, buf, crypt_offset))
+-		return GSS_S_DEFECTIVE_TOKEN;
++
++	/*
++	 * Need plaintext seqnum to derive encryption key for arcfour-hmac
++	 */
++	if (krb5_get_seq_num(kctx, ptr + GSS_KRB5_TOK_HDR_LEN,
++			     ptr + 8, &direction, &seqnum))
++		return GSS_S_BAD_SIG;
++
++	if ((kctx->initiate && direction != 0xff) ||
++	    (!kctx->initiate && direction != 0))
++		return GSS_S_BAD_SIG;
++
++	if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC) {
++		struct crypto_blkcipher *cipher;
++		int err;
++
++		cipher = crypto_alloc_blkcipher(kctx->gk5e->encrypt_name, 0,
++						CRYPTO_ALG_ASYNC);
++		if (IS_ERR(cipher))
++			return GSS_S_FAILURE;
++
++		krb5_rc4_setup_enc_key(kctx, cipher, seqnum);
++
++		err = gss_decrypt_xdr_buf(cipher, buf, crypt_offset);
++		crypto_free_blkcipher(cipher);
++		if (err)
++			return GSS_S_DEFECTIVE_TOKEN;
++	} else {
++		if (gss_decrypt_xdr_buf(kctx->enc, buf, crypt_offset))
++			return GSS_S_DEFECTIVE_TOKEN;
++	}
+ 
+ 	if (kctx->gk5e->keyed_cksum)
+ 		cksumkey = kctx->cksum;
+@@ -316,14 +362,6 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
+ 
+ 	/* do sequencing checks */
+ 
+-	if (krb5_get_seq_num(kctx, ptr + GSS_KRB5_TOK_HDR_LEN,
+-				    ptr + 8, &direction, &seqnum))
+-		return GSS_S_BAD_SIG;
+-
+-	if ((kctx->initiate && direction != 0xff) ||
+-	    (!kctx->initiate && direction != 0))
+-		return GSS_S_BAD_SIG;
+-
+ 	/* Copy the data back to the right position.  XXX: Would probably be
+ 	 * better to copy and encrypt at the same time. */
+ 
+@@ -521,6 +559,7 @@ gss_wrap_kerberos(struct gss_ctx *gctx, int offset,
+ 		BUG();
+ 	case ENCTYPE_DES_CBC_RAW:
+ 	case ENCTYPE_DES3_CBC_RAW:
++	case ENCTYPE_ARCFOUR_HMAC:
+ 		return gss_wrap_kerberos_v1(kctx, offset, buf, pages);
+ 	case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
+ 	case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
+@@ -538,6 +577,7 @@ gss_unwrap_kerberos(struct gss_ctx *gctx, int offset, struct xdr_buf *buf)
+ 		BUG();
+ 	case ENCTYPE_DES_CBC_RAW:
+ 	case ENCTYPE_DES3_CBC_RAW:
++	case ENCTYPE_ARCFOUR_HMAC:
+ 		return gss_unwrap_kerberos_v1(kctx, offset, buf);
+ 	case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
+ 	case ENCTYPE_AES256_CTS_HMAC_SHA1_96:

commit 5af46547ec451918f3ba51efe59b317d33adf701
+Author: Kevin Coffman 
+Date:   Wed Mar 17 13:03:05 2010 -0400
+
+    gss_krb5: Use confounder length in wrap code
+    
+    All encryption types use a confounder at the beginning of the
+    wrap token.  In all encryption types except arcfour-hmac, the
+    confounder is the same as the blocksize.  arcfour-hmac has a
+    blocksize of one, but uses an eight byte confounder.
+    
+    Add an entry to the crypto framework definitions for the
+    confounder length and change the wrap/unwrap code to use
+    the confounder length rather than assuming it is always
+    the blocksize.
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: Steve Dickson 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
+index d840856edecc..79f6ac2492f5 100644
+--- a/include/linux/sunrpc/gss_krb5.h
++++ b/include/linux/sunrpc/gss_krb5.h
+@@ -64,6 +64,9 @@ struct gss_krb5_enctype {
+ 	const u16		signalg;	/* signing algorithm */
+ 	const u16		sealalg;	/* sealing algorithm */
+ 	const u32		blocksize;	/* encryption blocksize */
++	const u32		conflen;	/* confounder length
++						   (normally the same as
++						   the blocksize) */
+ 	const u32		cksumlength;	/* checksum length */
+ 	const u32		keyed_cksum;	/* is it a keyed cksum? */
+ 	const u32		keybytes;	/* raw key len, in bytes */
+diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+index 33ae7023cf3a..ed4106a3daf2 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
++++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+@@ -554,9 +554,9 @@ gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset,
+ 
+ 	/* hide the gss token header and insert the confounder */
+ 	offset += GSS_KRB5_TOK_HDR_LEN;
+-	if (xdr_extend_head(buf, offset, blocksize))
++	if (xdr_extend_head(buf, offset, kctx->gk5e->conflen))
+ 		return GSS_S_FAILURE;
+-	gss_krb5_make_confounder(buf->head[0].iov_base + offset, blocksize);
++	gss_krb5_make_confounder(buf->head[0].iov_base + offset, kctx->gk5e->conflen);
+ 	offset -= GSS_KRB5_TOK_HDR_LEN;
+ 
+ 	if (buf->tail[0].iov_base != NULL) {
+@@ -726,7 +726,7 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf,
+ 		ret = GSS_S_BAD_SIG;
+ 		goto out_err;
+ 	}
+-	*headskip = crypto_blkcipher_blocksize(cipher);
++	*headskip = kctx->gk5e->conflen;
+ 	*tailskip = kctx->gk5e->cksumlength;
+ out_err:
+ 	if (ret && ret != GSS_S_BAD_SIG)
+diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
+index 893fad71e306..ef6b31349046 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
++++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
+@@ -68,6 +68,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
+ 	  .keybytes = 7,
+ 	  .keylength = 8,
+ 	  .blocksize = 8,
++	  .conflen = 8,
+ 	  .cksumlength = 8,
+ 	  .keyed_cksum = 0,
+ 	},
+@@ -88,6 +89,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
+ 	  .keybytes = 21,
+ 	  .keylength = 24,
+ 	  .blocksize = 8,
++	  .conflen = 8,
+ 	  .cksumlength = 20,
+ 	  .keyed_cksum = 1,
+ 	},
+@@ -110,6 +112,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
+ 	  .keybytes = 16,
+ 	  .keylength = 16,
+ 	  .blocksize = 16,
++	  .conflen = 16,
+ 	  .cksumlength = 12,
+ 	  .keyed_cksum = 1,
+ 	},
+@@ -132,6 +135,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
+ 	  .keybytes = 32,
+ 	  .keylength = 32,
+ 	  .blocksize = 16,
++	  .conflen = 16,
+ 	  .cksumlength = 12,
+ 	  .keyed_cksum = 1,
+ 	},
+diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+index a95e7e0ac0e3..383db891c835 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
++++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+@@ -168,6 +168,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
+ 	struct page		**tmp_pages;
+ 	u32			seq_send;
+ 	u8			*cksumkey;
++	u32			conflen = kctx->gk5e->conflen;
+ 
+ 	dprintk("RPC:       %s\n", __func__);
+ 
+@@ -176,7 +177,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
+ 	blocksize = crypto_blkcipher_blocksize(kctx->enc);
+ 	gss_krb5_add_padding(buf, offset, blocksize);
+ 	BUG_ON((buf->len - offset) % blocksize);
+-	plainlen = blocksize + buf->len - offset;
++	plainlen = conflen + buf->len - offset;
+ 
+ 	headlen = g_token_size(&kctx->mech_used,
+ 		GSS_KRB5_TOK_HDR_LEN + kctx->gk5e->cksumlength + plainlen) -
+@@ -204,7 +205,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
+ 	memset(ptr + 4, 0xff, 4);
+ 	*(__be16 *)(ptr + 4) = cpu_to_le16(kctx->gk5e->sealalg);
+ 
+-	gss_krb5_make_confounder(msg_start, blocksize);
++	gss_krb5_make_confounder(msg_start, conflen);
+ 
+ 	if (kctx->gk5e->keyed_cksum)
+ 		cksumkey = kctx->cksum;
+@@ -214,7 +215,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
+ 	/* XXXJBF: UGH!: */
+ 	tmp_pages = buf->pages;
+ 	buf->pages = pages;
+-	if (make_checksum(kctx, ptr, 8, buf, offset + headlen - blocksize,
++	if (make_checksum(kctx, ptr, 8, buf, offset + headlen - conflen,
+ 					cksumkey, KG_USAGE_SEAL, &md5cksum))
+ 		return GSS_S_FAILURE;
+ 	buf->pages = tmp_pages;
+@@ -231,7 +232,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
+ 			       seq_send, ptr + GSS_KRB5_TOK_HDR_LEN, ptr + 8)))
+ 		return GSS_S_FAILURE;
+ 
+-	if (gss_encrypt_xdr_buf(kctx->enc, buf, offset + headlen - blocksize,
++	if (gss_encrypt_xdr_buf(kctx->enc, buf, offset + headlen - conflen,
+ 									pages))
+ 		return GSS_S_FAILURE;
+ 
+@@ -254,6 +255,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
+ 	void			*data_start, *orig_start;
+ 	int			data_len;
+ 	int			blocksize;
++	u32			conflen = kctx->gk5e->conflen;
+ 	int			crypt_offset;
+ 	u8			*cksumkey;
+ 
+@@ -327,7 +329,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
+ 
+ 	blocksize = crypto_blkcipher_blocksize(kctx->enc);
+ 	data_start = ptr + (GSS_KRB5_TOK_HDR_LEN + kctx->gk5e->cksumlength) +
+-					blocksize;
++					conflen;
+ 	orig_start = buf->head[0].iov_base + offset;
+ 	data_len = (buf->head[0].iov_base + buf->head[0].iov_len) - data_start;
+ 	memmove(orig_start, data_start, data_len);

commit 1dbd9029f3024d058da1cf6c6658c28aac2e4e1c
+Author: Kevin Coffman 
+Date:   Wed Mar 17 13:03:04 2010 -0400
+
+    gssd_krb5: More arcfour-hmac support
+    
+    For the arcfour-hmac support, the make_seq_num and get_seq_num
+    functions need access to the kerberos context structure.
+    This will be used in a later patch.
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: Steve Dickson 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
+index b0ab827add26..d840856edecc 100644
+--- a/include/linux/sunrpc/gss_krb5.h
++++ b/include/linux/sunrpc/gss_krb5.h
+@@ -275,12 +275,13 @@ gss_decrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *inbuf,
+ 		    int offset);
+ 
+ s32
+-krb5_make_seq_num(struct crypto_blkcipher *key,
++krb5_make_seq_num(struct krb5_ctx *kctx,
++		struct crypto_blkcipher *key,
+ 		int direction,
+ 		u32 seqnum, unsigned char *cksum, unsigned char *buf);
+ 
+ s32
+-krb5_get_seq_num(struct crypto_blkcipher *key,
++krb5_get_seq_num(struct krb5_ctx *kctx,
+ 	       unsigned char *cksum,
+ 	       unsigned char *buf, int *direction, u32 *seqnum);
+ 
+diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
+index e22fed3d9a1b..36fe487d93d2 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
+@@ -152,9 +152,8 @@ gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text,
+ 	seq_send = ctx->seq_send++;
+ 	spin_unlock(&krb5_seq_lock);
+ 
+-	if (krb5_make_seq_num(ctx->seq, ctx->initiate ? 0 : 0xff,
+-			      seq_send, ptr + GSS_KRB5_TOK_HDR_LEN,
+-			      ptr + 8))
++	if (krb5_make_seq_num(ctx, ctx->seq, ctx->initiate ? 0 : 0xff,
++			      seq_send, ptr + GSS_KRB5_TOK_HDR_LEN, ptr + 8))
+ 		return GSS_S_FAILURE;
+ 
+ 	return (ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE;
+diff --git a/net/sunrpc/auth_gss/gss_krb5_seqnum.c b/net/sunrpc/auth_gss/gss_krb5_seqnum.c
+index 6331cd6866ec..83b593084976 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_seqnum.c
++++ b/net/sunrpc/auth_gss/gss_krb5_seqnum.c
+@@ -40,7 +40,8 @@
+ #endif
+ 
+ s32
+-krb5_make_seq_num(struct crypto_blkcipher *key,
++krb5_make_seq_num(struct krb5_ctx *kctx,
++		struct crypto_blkcipher *key,
+ 		int direction,
+ 		u32 seqnum,
+ 		unsigned char *cksum, unsigned char *buf)
+@@ -61,13 +62,14 @@ krb5_make_seq_num(struct crypto_blkcipher *key,
+ }
+ 
+ s32
+-krb5_get_seq_num(struct crypto_blkcipher *key,
++krb5_get_seq_num(struct krb5_ctx *kctx,
+ 	       unsigned char *cksum,
+ 	       unsigned char *buf,
+ 	       int *direction, u32 *seqnum)
+ {
+ 	s32 code;
+ 	unsigned char plain[8];
++	struct crypto_blkcipher *key = kctx->seq;
+ 
+ 	dprintk("RPC:       krb5_get_seq_num:\n");
+ 
+diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
+index ef91366e3dea..97eb91b8c70c 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
+@@ -131,7 +131,8 @@ gss_verify_mic_v1(struct krb5_ctx *ctx,
+ 
+ 	/* do sequencing checks */
+ 
+-	if (krb5_get_seq_num(ctx->seq, ptr + GSS_KRB5_TOK_HDR_LEN, ptr + 8, &direction, &seqnum))
++	if (krb5_get_seq_num(ctx, ptr + GSS_KRB5_TOK_HDR_LEN, ptr + 8,
++			     &direction, &seqnum))
+ 		return GSS_S_FAILURE;
+ 
+ 	if ((ctx->initiate && direction != 0xff) ||
+diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+index 097cc27494cc..a95e7e0ac0e3 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
++++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+@@ -227,7 +227,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
+ 
+ 	/* XXX would probably be more efficient to compute checksum
+ 	 * and encrypt at the same time: */
+-	if ((krb5_make_seq_num(kctx->seq, kctx->initiate ? 0 : 0xff,
++	if ((krb5_make_seq_num(kctx, kctx->seq, kctx->initiate ? 0 : 0xff,
+ 			       seq_send, ptr + GSS_KRB5_TOK_HDR_LEN, ptr + 8)))
+ 		return GSS_S_FAILURE;
+ 
+@@ -314,8 +314,8 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
+ 
+ 	/* do sequencing checks */
+ 
+-	if (krb5_get_seq_num(kctx->seq, ptr + GSS_KRB5_TOK_HDR_LEN, ptr + 8,
+-				    &direction, &seqnum))
++	if (krb5_get_seq_num(kctx, ptr + GSS_KRB5_TOK_HDR_LEN,
++				    ptr + 8, &direction, &seqnum))
+ 		return GSS_S_BAD_SIG;
+ 
+ 	if ((kctx->initiate && direction != 0xff) ||

commit fc263a917afad3bda7b823a6edc803a40e7f6015
+Author: Kevin Coffman 
+Date:   Wed Mar 17 13:03:03 2010 -0400
+
+    gss_krb5: Save the raw session key in the context
+    
+    This is needed for deriving arcfour-hmac keys "on the fly"
+    using the sequence number or checksu
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: Steve Dickson 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
+index 633f41f11a40..b0ab827add26 100644
+--- a/include/linux/sunrpc/gss_krb5.h
++++ b/include/linux/sunrpc/gss_krb5.h
+@@ -101,6 +101,7 @@ struct krb5_ctx {
+ 	struct crypto_blkcipher *initiator_enc;
+ 	struct crypto_blkcipher *acceptor_enc_aux;
+ 	struct crypto_blkcipher *initiator_enc_aux;
++	u8			Ksess[GSS_KRB5_MAX_KEYLEN]; /* session key */
+ 	u8			cksum[GSS_KRB5_MAX_KEYLEN];
+ 	s32			endtime;
+ 	u32			seq_send;
+diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
+index 506a2e7d4fad..893fad71e306 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
++++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
+@@ -344,7 +344,7 @@ set_cdata(u8 cdata[GSS_KRB5_K5CLENGTH], u32 usage, u8 seed)
+ }
+ 
+ static int
+-context_derive_keys_des3(struct krb5_ctx *ctx, u8 *rawkey, u32 keylen)
++context_derive_keys_des3(struct krb5_ctx *ctx)
+ {
+ 	struct xdr_netobj c, keyin, keyout;
+ 	u8 cdata[GSS_KRB5_K5CLENGTH];
+@@ -353,18 +353,18 @@ context_derive_keys_des3(struct krb5_ctx *ctx, u8 *rawkey, u32 keylen)
+ 	c.len = GSS_KRB5_K5CLENGTH;
+ 	c.data = cdata;
+ 
+-	keyin.data = rawkey;
+-	keyin.len = keylen;
+-	keyout.len = keylen;
++	keyin.data = ctx->Ksess;
++	keyin.len = ctx->gk5e->keylength;
++	keyout.len = ctx->gk5e->keylength;
+ 
+ 	/* seq uses the raw key */
+ 	ctx->seq = context_v2_alloc_cipher(ctx, ctx->gk5e->encrypt_name,
+-					   rawkey);
++					   ctx->Ksess);
+ 	if (ctx->seq == NULL)
+ 		goto out_err;
+ 
+ 	ctx->enc = context_v2_alloc_cipher(ctx, ctx->gk5e->encrypt_name,
+-					   rawkey);
++					   ctx->Ksess);
+ 	if (ctx->enc == NULL)
+ 		goto out_free_seq;
+ 
+@@ -389,7 +389,7 @@ context_derive_keys_des3(struct krb5_ctx *ctx, u8 *rawkey, u32 keylen)
+ }
+ 
+ static int
+-context_derive_keys_new(struct krb5_ctx *ctx, u8 *rawkey, u32 keylen)
++context_derive_keys_new(struct krb5_ctx *ctx)
+ {
+ 	struct xdr_netobj c, keyin, keyout;
+ 	u8 cdata[GSS_KRB5_K5CLENGTH];
+@@ -398,9 +398,9 @@ context_derive_keys_new(struct krb5_ctx *ctx, u8 *rawkey, u32 keylen)
+ 	c.len = GSS_KRB5_K5CLENGTH;
+ 	c.data = cdata;
+ 
+-	keyin.data = rawkey;
+-	keyin.len = keylen;
+-	keyout.len = keylen;
++	keyin.data = ctx->Ksess;
++	keyin.len = ctx->gk5e->keylength;
++	keyout.len = ctx->gk5e->keylength;
+ 
+ 	/* initiator seal encryption */
+ 	set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_ENCRYPTION);
+@@ -502,7 +502,6 @@ context_derive_keys_new(struct krb5_ctx *ctx, u8 *rawkey, u32 keylen)
+ static int
+ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx)
+ {
+-	u8 rawkey[GSS_KRB5_MAX_KEYLEN];
+ 	int keylen;
+ 
+ 	p = simple_get_bytes(p, end, &ctx->flags, sizeof(ctx->flags));
+@@ -538,7 +537,7 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx)
+ 	}
+ 	keylen = ctx->gk5e->keylength;
+ 
+-	p = simple_get_bytes(p, end, rawkey, keylen);
++	p = simple_get_bytes(p, end, ctx->Ksess, keylen);
+ 	if (IS_ERR(p))
+ 		goto out_err;
+ 
+@@ -557,10 +556,10 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx)
+ 
+ 	switch (ctx->enctype) {
+ 	case ENCTYPE_DES3_CBC_RAW:
+-		return context_derive_keys_des3(ctx, rawkey, keylen);
++		return context_derive_keys_des3(ctx);
+ 	case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
+ 	case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
+-		return context_derive_keys_new(ctx, rawkey, keylen);
++		return context_derive_keys_new(ctx);
+ 	default:
+ 		return -EINVAL;
+ 	}

commit 8b23707612cffdba694dcd18aa8a018918aa86dc
+Author: Kevin Coffman 
+Date:   Wed Mar 17 13:03:02 2010 -0400
+
+    gssd_krb5: arcfour-hmac support
+    
+    For arcfour-hmac support, the make_checksum function needs a usage
+    field to correctly calculate the checksum differently for MIC and
+    WRAP tokens.
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: Steve Dickson 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
+index 43148ec9a46c..633f41f11a40 100644
+--- a/include/linux/sunrpc/gss_krb5.h
++++ b/include/linux/sunrpc/gss_krb5.h
+@@ -235,12 +235,12 @@ enum seal_alg {
+ u32
+ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
+ 		struct xdr_buf *body, int body_offset, u8 *cksumkey,
+-		struct xdr_netobj *cksumout);
++		unsigned int usage, struct xdr_netobj *cksumout);
+ 
+ u32
+ make_checksum_v2(struct krb5_ctx *, char *header, int hdrlen,
+ 		 struct xdr_buf *body, int body_offset, u8 *key,
+-		 struct xdr_netobj *cksum);
++		 unsigned int usage, struct xdr_netobj *cksum);
+ 
+ u32 gss_get_mic_kerberos(struct gss_ctx *, struct xdr_buf *,
+ 		struct xdr_netobj *);
+diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+index 967484a914f3..33ae7023cf3a 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
++++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+@@ -132,7 +132,7 @@ checksummer(struct scatterlist *sg, void *data)
+ u32
+ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
+ 	      struct xdr_buf *body, int body_offset, u8 *cksumkey,
+-	      struct xdr_netobj *cksumout)
++	      unsigned int usage, struct xdr_netobj *cksumout)
+ {
+ 	struct hash_desc                desc;
+ 	struct scatterlist              sg[1];
+@@ -208,7 +208,7 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
+ u32
+ make_checksum_v2(struct krb5_ctx *kctx, char *header, int hdrlen,
+ 		 struct xdr_buf *body, int body_offset, u8 *cksumkey,
+-		 struct xdr_netobj *cksumout)
++		 unsigned int usage, struct xdr_netobj *cksumout)
+ {
+ 	struct hash_desc desc;
+ 	struct scatterlist sg[1];
+@@ -537,15 +537,18 @@ gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset,
+ 	int nblocks, nbytes;
+ 	struct encryptor_desc desc;
+ 	u32 cbcbytes;
++	unsigned int usage;
+ 
+ 	if (kctx->initiate) {
+ 		cipher = kctx->initiator_enc;
+ 		aux_cipher = kctx->initiator_enc_aux;
+ 		cksumkey = kctx->initiator_integ;
++		usage = KG_USAGE_INITIATOR_SEAL;
+ 	} else {
+ 		cipher = kctx->acceptor_enc;
+ 		aux_cipher = kctx->acceptor_enc_aux;
+ 		cksumkey = kctx->acceptor_integ;
++		usage = KG_USAGE_ACCEPTOR_SEAL;
+ 	}
+ 	blocksize = crypto_blkcipher_blocksize(cipher);
+ 
+@@ -590,7 +593,8 @@ gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset,
+ 	buf->pages = pages;
+ 
+ 	err = make_checksum_v2(kctx, NULL, 0, buf,
+-			       offset + GSS_KRB5_TOK_HDR_LEN, cksumkey, &hmac);
++			       offset + GSS_KRB5_TOK_HDR_LEN,
++			       cksumkey, usage, &hmac);
+ 	buf->pages = save_pages;
+ 	if (err)
+ 		return GSS_S_FAILURE;
+@@ -654,15 +658,18 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf,
+ 	u8 pkt_hmac[GSS_KRB5_MAX_CKSUM_LEN];
+ 	int nblocks, blocksize, cbcbytes;
+ 	struct decryptor_desc desc;
++	unsigned int usage;
+ 
+ 	if (kctx->initiate) {
+ 		cipher = kctx->acceptor_enc;
+ 		aux_cipher = kctx->acceptor_enc_aux;
+ 		cksum_key = kctx->acceptor_integ;
++		usage = KG_USAGE_ACCEPTOR_SEAL;
+ 	} else {
+ 		cipher = kctx->initiator_enc;
+ 		aux_cipher = kctx->initiator_enc_aux;
+ 		cksum_key = kctx->initiator_integ;
++		usage = KG_USAGE_INITIATOR_SEAL;
+ 	}
+ 	blocksize = crypto_blkcipher_blocksize(cipher);
+ 
+@@ -705,7 +712,7 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf,
+ 	our_hmac_obj.data = our_hmac;
+ 
+ 	ret = make_checksum_v2(kctx, NULL, 0, &subbuf, 0,
+-			       cksum_key, &our_hmac_obj);
++			       cksum_key, usage, &our_hmac_obj);
+ 	if (ret)
+ 		goto out_err;
+ 
+diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
+index 477a546d19bb..e22fed3d9a1b 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
+@@ -142,7 +142,8 @@ gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text,
+ 	else
+ 		cksumkey = NULL;
+ 
+-	if (make_checksum(ctx, ptr, 8, text, 0, cksumkey, &md5cksum))
++	if (make_checksum(ctx, ptr, 8, text, 0, cksumkey,
++			  KG_USAGE_SIGN, &md5cksum))
+ 		return GSS_S_FAILURE;
+ 
+ 	memcpy(ptr + GSS_KRB5_TOK_HDR_LEN, md5cksum.data, md5cksum.len);
+@@ -170,6 +171,7 @@ gss_get_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *text,
+ 	s32 now;
+ 	u64 seq_send;
+ 	u8 *cksumkey;
++	unsigned int cksum_usage;
+ 
+ 	dprintk("RPC:       %s\n", __func__);
+ 
+@@ -182,13 +184,16 @@ gss_get_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *text,
+ 	spin_unlock(&krb5_seq_lock);
+ 	*((u64 *)(krb5_hdr + 8)) = cpu_to_be64(seq_send);
+ 
+-	if (ctx->initiate)
++	if (ctx->initiate) {
+ 		cksumkey = ctx->initiator_sign;
+-	else
++		cksum_usage = KG_USAGE_INITIATOR_SIGN;
++	} else {
+ 		cksumkey = ctx->acceptor_sign;
++		cksum_usage = KG_USAGE_ACCEPTOR_SIGN;
++	}
+ 
+ 	if (make_checksum_v2(ctx, krb5_hdr, GSS_KRB5_TOK_HDR_LEN,
+-			     text, 0, cksumkey, &cksumobj))
++			     text, 0, cksumkey, cksum_usage, &cksumobj))
+ 		return GSS_S_FAILURE;
+ 
+ 	memcpy(krb5_hdr + GSS_KRB5_TOK_HDR_LEN, cksumobj.data, cksumobj.len);
+diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
+index 4ede4cc4391f..ef91366e3dea 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
+@@ -115,7 +115,7 @@ gss_verify_mic_v1(struct krb5_ctx *ctx,
+ 		cksumkey = NULL;
+ 
+ 	if (make_checksum(ctx, ptr, 8, message_buffer, 0,
+-			  cksumkey, &md5cksum))
++			  cksumkey, KG_USAGE_SIGN, &md5cksum))
+ 		return GSS_S_FAILURE;
+ 
+ 	if (memcmp(md5cksum.data, ptr + GSS_KRB5_TOK_HDR_LEN,
+@@ -154,6 +154,7 @@ gss_verify_mic_v2(struct krb5_ctx *ctx,
+ 	u8 *cksumkey;
+ 	u8 flags;
+ 	int i;
++	unsigned int cksum_usage;
+ 
+ 	dprintk("RPC:       %s\n", __func__);
+ 
+@@ -174,13 +175,16 @@ gss_verify_mic_v2(struct krb5_ctx *ctx,
+ 		if (ptr[i] != 0xff)
+ 			return GSS_S_DEFECTIVE_TOKEN;
+ 
+-	if (ctx->initiate)
++	if (ctx->initiate) {
+ 		cksumkey = ctx->acceptor_sign;
+-	else
++		cksum_usage = KG_USAGE_ACCEPTOR_SIGN;
++	} else {
+ 		cksumkey = ctx->initiator_sign;
++		cksum_usage = KG_USAGE_INITIATOR_SIGN;
++	}
+ 
+ 	if (make_checksum_v2(ctx, ptr, GSS_KRB5_TOK_HDR_LEN, message_buffer, 0,
+-			     cksumkey, &cksumobj))
++			     cksumkey, cksum_usage, &cksumobj))
+ 		return GSS_S_FAILURE;
+ 
+ 	if (memcmp(cksumobj.data, ptr + GSS_KRB5_TOK_HDR_LEN,
+diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+index a1a3585fa761..097cc27494cc 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
++++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+@@ -215,7 +215,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
+ 	tmp_pages = buf->pages;
+ 	buf->pages = pages;
+ 	if (make_checksum(kctx, ptr, 8, buf, offset + headlen - blocksize,
+-					cksumkey, &md5cksum))
++					cksumkey, KG_USAGE_SEAL, &md5cksum))
+ 		return GSS_S_FAILURE;
+ 	buf->pages = tmp_pages;
+ 
+@@ -298,7 +298,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
+ 		cksumkey = NULL;
+ 
+ 	if (make_checksum(kctx, ptr, 8, buf, crypt_offset,
+-						cksumkey, &md5cksum))
++					cksumkey, KG_USAGE_SEAL, &md5cksum))
+ 		return GSS_S_FAILURE;
+ 
+ 	if (memcmp(md5cksum.data, ptr + GSS_KRB5_TOK_HDR_LEN,

commit 934a95aa1c9c6ad77838800b79c306e982437605
+Author: Kevin Coffman 
+Date:   Wed Mar 17 13:03:00 2010 -0400
+
+    gss_krb5: add remaining pieces to enable AES encryption support
+    
+    Add the remaining pieces to enable support for Kerberos AES
+    encryption types.
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: Steve Dickson 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
+index 0085a30fd204..43148ec9a46c 100644
+--- a/include/linux/sunrpc/gss_krb5.h
++++ b/include/linux/sunrpc/gss_krb5.h
+@@ -99,6 +99,8 @@ struct krb5_ctx {
+ 	struct crypto_blkcipher	*seq;
+ 	struct crypto_blkcipher *acceptor_enc;
+ 	struct crypto_blkcipher *initiator_enc;
++	struct crypto_blkcipher *acceptor_enc_aux;
++	struct crypto_blkcipher *initiator_enc_aux;
+ 	u8			cksum[GSS_KRB5_MAX_KEYLEN];
+ 	s32			endtime;
+ 	u32			seq_send;
+@@ -294,3 +296,21 @@ u32
+ gss_krb5_des3_make_key(const struct gss_krb5_enctype *gk5e,
+ 		       struct xdr_netobj *randombits,
+ 		       struct xdr_netobj *key);
++
++u32
++gss_krb5_aes_make_key(const struct gss_krb5_enctype *gk5e,
++		      struct xdr_netobj *randombits,
++		      struct xdr_netobj *key);
++
++u32
++gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset,
++		     struct xdr_buf *buf, int ec,
++		     struct page **pages);
++
++u32
++gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset,
++		     struct xdr_buf *buf, u32 *plainoffset,
++		     u32 *plainlen);
++
++void
++gss_krb5_make_confounder(char *p, u32 conflen);
+diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+index ca52ac28a537..967484a914f3 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
++++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+@@ -41,6 +41,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ 
+@@ -478,3 +479,250 @@ xdr_extend_head(struct xdr_buf *buf, unsigned int base, unsigned int shiftlen)
+ 
+ 	return 0;
+ }
++
++static u32
++gss_krb5_cts_crypt(struct crypto_blkcipher *cipher, struct xdr_buf *buf,
++		   u32 offset, u8 *iv, struct page **pages, int encrypt)
++{
++	u32 ret;
++	struct scatterlist sg[1];
++	struct blkcipher_desc desc = { .tfm = cipher, .info = iv };
++	u8 data[crypto_blkcipher_blocksize(cipher) * 2];
++	struct page **save_pages;
++	u32 len = buf->len - offset;
++
++	BUG_ON(len > crypto_blkcipher_blocksize(cipher) * 2);
++
++	/*
++	 * For encryption, we want to read from the cleartext
++	 * page cache pages, and write the encrypted data to
++	 * the supplied xdr_buf pages.
++	 */
++	save_pages = buf->pages;
++	if (encrypt)
++		buf->pages = pages;
++
++	ret = read_bytes_from_xdr_buf(buf, offset, data, len);
++	buf->pages = save_pages;
++	if (ret)
++		goto out;
++
++	sg_init_one(sg, data, len);
++
++	if (encrypt)
++		ret = crypto_blkcipher_encrypt_iv(&desc, sg, sg, len);
++	else
++		ret = crypto_blkcipher_decrypt_iv(&desc, sg, sg, len);
++
++	if (ret)
++		goto out;
++
++	ret = write_bytes_to_xdr_buf(buf, offset, data, len);
++
++out:
++	return ret;
++}
++
++u32
++gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset,
++		     struct xdr_buf *buf, int ec, struct page **pages)
++{
++	u32 err;
++	struct xdr_netobj hmac;
++	u8 *cksumkey;
++	u8 *ecptr;
++	struct crypto_blkcipher *cipher, *aux_cipher;
++	int blocksize;
++	struct page **save_pages;
++	int nblocks, nbytes;
++	struct encryptor_desc desc;
++	u32 cbcbytes;
++
++	if (kctx->initiate) {
++		cipher = kctx->initiator_enc;
++		aux_cipher = kctx->initiator_enc_aux;
++		cksumkey = kctx->initiator_integ;
++	} else {
++		cipher = kctx->acceptor_enc;
++		aux_cipher = kctx->acceptor_enc_aux;
++		cksumkey = kctx->acceptor_integ;
++	}
++	blocksize = crypto_blkcipher_blocksize(cipher);
++
++	/* hide the gss token header and insert the confounder */
++	offset += GSS_KRB5_TOK_HDR_LEN;
++	if (xdr_extend_head(buf, offset, blocksize))
++		return GSS_S_FAILURE;
++	gss_krb5_make_confounder(buf->head[0].iov_base + offset, blocksize);
++	offset -= GSS_KRB5_TOK_HDR_LEN;
++
++	if (buf->tail[0].iov_base != NULL) {
++		ecptr = buf->tail[0].iov_base + buf->tail[0].iov_len;
++	} else {
++		buf->tail[0].iov_base = buf->head[0].iov_base
++							+ buf->head[0].iov_len;
++		buf->tail[0].iov_len = 0;
++		ecptr = buf->tail[0].iov_base;
++	}
++
++	memset(ecptr, 'X', ec);
++	buf->tail[0].iov_len += ec;
++	buf->len += ec;
++
++	/* copy plaintext gss token header after filler (if any) */
++	memcpy(ecptr + ec, buf->head[0].iov_base + offset,
++						GSS_KRB5_TOK_HDR_LEN);
++	buf->tail[0].iov_len += GSS_KRB5_TOK_HDR_LEN;
++	buf->len += GSS_KRB5_TOK_HDR_LEN;
++
++	/* Do the HMAC */
++	hmac.len = GSS_KRB5_MAX_CKSUM_LEN;
++	hmac.data = buf->tail[0].iov_base + buf->tail[0].iov_len;
++
++	/*
++	 * When we are called, pages points to the real page cache
++	 * data -- which we can't go and encrypt!  buf->pages points
++	 * to scratch pages which we are going to send off to the
++	 * client/server.  Swap in the plaintext pages to calculate
++	 * the hmac.
++	 */
++	save_pages = buf->pages;
++	buf->pages = pages;
++
++	err = make_checksum_v2(kctx, NULL, 0, buf,
++			       offset + GSS_KRB5_TOK_HDR_LEN, cksumkey, &hmac);
++	buf->pages = save_pages;
++	if (err)
++		return GSS_S_FAILURE;
++
++	nbytes = buf->len - offset - GSS_KRB5_TOK_HDR_LEN;
++	nblocks = (nbytes + blocksize - 1) / blocksize;
++	cbcbytes = 0;
++	if (nblocks > 2)
++		cbcbytes = (nblocks - 2) * blocksize;
++
++	memset(desc.iv, 0, sizeof(desc.iv));
++
++	if (cbcbytes) {
++		desc.pos = offset + GSS_KRB5_TOK_HDR_LEN;
++		desc.fragno = 0;
++		desc.fraglen = 0;
++		desc.pages = pages;
++		desc.outbuf = buf;
++		desc.desc.info = desc.iv;
++		desc.desc.flags = 0;
++		desc.desc.tfm = aux_cipher;
++
++		sg_init_table(desc.infrags, 4);
++		sg_init_table(desc.outfrags, 4);
++
++		err = xdr_process_buf(buf, offset + GSS_KRB5_TOK_HDR_LEN,
++				      cbcbytes, encryptor, &desc);
++		if (err)
++			goto out_err;
++	}
++
++	/* Make sure IV carries forward from any CBC results. */
++	err = gss_krb5_cts_crypt(cipher, buf,
++				 offset + GSS_KRB5_TOK_HDR_LEN + cbcbytes,
++				 desc.iv, pages, 1);
++	if (err) {
++		err = GSS_S_FAILURE;
++		goto out_err;
++	}
++
++	/* Now update buf to account for HMAC */
++	buf->tail[0].iov_len += kctx->gk5e->cksumlength;
++	buf->len += kctx->gk5e->cksumlength;
++
++out_err:
++	if (err)
++		err = GSS_S_FAILURE;
++	return err;
++}
++
++u32
++gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf,
++		     u32 *headskip, u32 *tailskip)
++{
++	struct xdr_buf subbuf;
++	u32 ret = 0;
++	u8 *cksum_key;
++	struct crypto_blkcipher *cipher, *aux_cipher;
++	struct xdr_netobj our_hmac_obj;
++	u8 our_hmac[GSS_KRB5_MAX_CKSUM_LEN];
++	u8 pkt_hmac[GSS_KRB5_MAX_CKSUM_LEN];
++	int nblocks, blocksize, cbcbytes;
++	struct decryptor_desc desc;
++
++	if (kctx->initiate) {
++		cipher = kctx->acceptor_enc;
++		aux_cipher = kctx->acceptor_enc_aux;
++		cksum_key = kctx->acceptor_integ;
++	} else {
++		cipher = kctx->initiator_enc;
++		aux_cipher = kctx->initiator_enc_aux;
++		cksum_key = kctx->initiator_integ;
++	}
++	blocksize = crypto_blkcipher_blocksize(cipher);
++
++
++	/* create a segment skipping the header and leaving out the checksum */
++	xdr_buf_subsegment(buf, &subbuf, offset + GSS_KRB5_TOK_HDR_LEN,
++				    (buf->len - offset - GSS_KRB5_TOK_HDR_LEN -
++				     kctx->gk5e->cksumlength));
++
++	nblocks = (subbuf.len + blocksize - 1) / blocksize;
++
++	cbcbytes = 0;
++	if (nblocks > 2)
++		cbcbytes = (nblocks - 2) * blocksize;
++
++	memset(desc.iv, 0, sizeof(desc.iv));
++
++	if (cbcbytes) {
++		desc.fragno = 0;
++		desc.fraglen = 0;
++		desc.desc.info = desc.iv;
++		desc.desc.flags = 0;
++		desc.desc.tfm = aux_cipher;
++
++		sg_init_table(desc.frags, 4);
++
++		ret = xdr_process_buf(&subbuf, 0, cbcbytes, decryptor, &desc);
++		if (ret)
++			goto out_err;
++	}
++
++	/* Make sure IV carries forward from any CBC results. */
++	ret = gss_krb5_cts_crypt(cipher, &subbuf, cbcbytes, desc.iv, NULL, 0);
++	if (ret)
++		goto out_err;
++
++
++	/* Calculate our hmac over the plaintext data */
++	our_hmac_obj.len = sizeof(our_hmac);
++	our_hmac_obj.data = our_hmac;
++
++	ret = make_checksum_v2(kctx, NULL, 0, &subbuf, 0,
++			       cksum_key, &our_hmac_obj);
++	if (ret)
++		goto out_err;
++
++	/* Get the packet's hmac value */
++	ret = read_bytes_from_xdr_buf(buf, buf->len - kctx->gk5e->cksumlength,
++				      pkt_hmac, kctx->gk5e->cksumlength);
++	if (ret)
++		goto out_err;
++
++	if (memcmp(pkt_hmac, our_hmac, kctx->gk5e->cksumlength) != 0) {
++		ret = GSS_S_BAD_SIG;
++		goto out_err;
++	}
++	*headskip = crypto_blkcipher_blocksize(cipher);
++	*tailskip = kctx->gk5e->cksumlength;
++out_err:
++	if (ret && ret != GSS_S_BAD_SIG)
++		ret = GSS_S_FAILURE;
++	return ret;
++}
+diff --git a/net/sunrpc/auth_gss/gss_krb5_keys.c b/net/sunrpc/auth_gss/gss_krb5_keys.c
+index d54668790f0c..33b87f04b30b 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_keys.c
++++ b/net/sunrpc/auth_gss/gss_krb5_keys.c
+@@ -303,3 +303,33 @@ u32 gss_krb5_des3_make_key(const struct gss_krb5_enctype *gk5e,
+ err_out:
+ 	return ret;
+ }
++
++/*
++ * This is the aes key derivation postprocess function
++ */
++u32 gss_krb5_aes_make_key(const struct gss_krb5_enctype *gk5e,
++			  struct xdr_netobj *randombits,
++			  struct xdr_netobj *key)
++{
++	u32 ret = EINVAL;
++
++	if (key->len != 16 && key->len != 32) {
++		dprintk("%s: key->len is %d\n", __func__, key->len);
++		goto err_out;
++	}
++	if (randombits->len != 16 && randombits->len != 32) {
++		dprintk("%s: randombits->len is %d\n",
++			__func__, randombits->len);
++		goto err_out;
++	}
++	if (randombits->len != key->len) {
++		dprintk("%s: randombits->len is %d, key->len is %d\n",
++			__func__, randombits->len, key->len);
++		goto err_out;
++	}
++	memcpy(key->data, randombits->data, key->len);
++	ret = 0;
++err_out:
++	return ret;
++}
++
+diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
+index ce80f996758a..694ad77c86bf 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
++++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
+@@ -91,6 +91,50 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
+ 	  .cksumlength = 20,
+ 	  .keyed_cksum = 1,
+ 	},
++	/*
++	 * AES128
++	 */
++	{
++	  .etype = ENCTYPE_AES128_CTS_HMAC_SHA1_96,
++	  .ctype = CKSUMTYPE_HMAC_SHA1_96_AES128,
++	  .name = "aes128-cts",
++	  .encrypt_name = "cts(cbc(aes))",
++	  .cksum_name = "hmac(sha1)",
++	  .encrypt = krb5_encrypt,
++	  .decrypt = krb5_decrypt,
++	  .mk_key = gss_krb5_aes_make_key,
++	  .encrypt_v2 = gss_krb5_aes_encrypt,
++	  .decrypt_v2 = gss_krb5_aes_decrypt,
++	  .signalg = -1,
++	  .sealalg = -1,
++	  .keybytes = 16,
++	  .keylength = 16,
++	  .blocksize = 16,
++	  .cksumlength = 12,
++	  .keyed_cksum = 1,
++	},
++	/*
++	 * AES256
++	 */
++	{
++	  .etype = ENCTYPE_AES256_CTS_HMAC_SHA1_96,
++	  .ctype = CKSUMTYPE_HMAC_SHA1_96_AES256,
++	  .name = "aes256-cts",
++	  .encrypt_name = "cts(cbc(aes))",
++	  .cksum_name = "hmac(sha1)",
++	  .encrypt = krb5_encrypt,
++	  .decrypt = krb5_decrypt,
++	  .mk_key = gss_krb5_aes_make_key,
++	  .encrypt_v2 = gss_krb5_aes_encrypt,
++	  .decrypt_v2 = gss_krb5_aes_decrypt,
++	  .signalg = -1,
++	  .sealalg = -1,
++	  .keybytes = 32,
++	  .keylength = 32,
++	  .blocksize = 16,
++	  .cksumlength = 12,
++	  .keyed_cksum = 1,
++	},
+ };
+ 
+ static const int num_supported_enctypes =
+@@ -270,20 +314,19 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx)
+ }
+ 
+ struct crypto_blkcipher *
+-context_v2_alloc_cipher(struct krb5_ctx *ctx, u8 *key)
++context_v2_alloc_cipher(struct krb5_ctx *ctx, const char *cname, u8 *key)
+ {
+ 	struct crypto_blkcipher *cp;
+ 
+-	cp = crypto_alloc_blkcipher(ctx->gk5e->encrypt_name,
+-					0, CRYPTO_ALG_ASYNC);
++	cp = crypto_alloc_blkcipher(cname, 0, CRYPTO_ALG_ASYNC);
+ 	if (IS_ERR(cp)) {
+ 		dprintk("gss_kerberos_mech: unable to initialize "
+-			"crypto algorithm %s\n", ctx->gk5e->encrypt_name);
++			"crypto algorithm %s\n", cname);
+ 		return NULL;
+ 	}
+ 	if (crypto_blkcipher_setkey(cp, key, ctx->gk5e->keylength)) {
+ 		dprintk("gss_kerberos_mech: error setting key for "
+-			"crypto algorithm %s\n", ctx->gk5e->encrypt_name);
++			"crypto algorithm %s\n", cname);
+ 		crypto_free_blkcipher(cp);
+ 		return NULL;
+ 	}
+@@ -315,11 +358,13 @@ context_derive_keys_des3(struct krb5_ctx *ctx, u8 *rawkey, u32 keylen)
+ 	keyout.len = keylen;
+ 
+ 	/* seq uses the raw key */
+-	ctx->seq = context_v2_alloc_cipher(ctx, rawkey);
++	ctx->seq = context_v2_alloc_cipher(ctx, ctx->gk5e->encrypt_name,
++					   rawkey);
+ 	if (ctx->seq == NULL)
+ 		goto out_err;
+ 
+-	ctx->enc = context_v2_alloc_cipher(ctx, rawkey);
++	ctx->enc = context_v2_alloc_cipher(ctx, ctx->gk5e->encrypt_name,
++					   rawkey);
+ 	if (ctx->enc == NULL)
+ 		goto out_free_seq;
+ 
+@@ -366,7 +411,9 @@ context_derive_keys_new(struct krb5_ctx *ctx, u8 *rawkey, u32 keylen)
+ 			__func__, err);
+ 		goto out_err;
+ 	}
+-	ctx->initiator_enc = context_v2_alloc_cipher(ctx, ctx->initiator_seal);
++	ctx->initiator_enc = context_v2_alloc_cipher(ctx,
++						     ctx->gk5e->encrypt_name,
++						     ctx->initiator_seal);
+ 	if (ctx->initiator_enc == NULL)
+ 		goto out_err;
+ 
+@@ -379,7 +426,9 @@ context_derive_keys_new(struct krb5_ctx *ctx, u8 *rawkey, u32 keylen)
+ 			__func__, err);
+ 		goto out_free_initiator_enc;
+ 	}
+-	ctx->acceptor_enc = context_v2_alloc_cipher(ctx, ctx->acceptor_seal);
++	ctx->acceptor_enc = context_v2_alloc_cipher(ctx,
++						    ctx->gk5e->encrypt_name,
++						    ctx->acceptor_seal);
+ 	if (ctx->acceptor_enc == NULL)
+ 		goto out_free_initiator_enc;
+ 
+@@ -423,6 +472,23 @@ context_derive_keys_new(struct krb5_ctx *ctx, u8 *rawkey, u32 keylen)
+ 		goto out_free_acceptor_enc;
+ 	}
+ 
++	switch (ctx->enctype) {
++	case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
++	case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
++		ctx->initiator_enc_aux =
++			context_v2_alloc_cipher(ctx, "cbc(aes)",
++						ctx->initiator_seal);
++		if (ctx->initiator_enc_aux == NULL)
++			goto out_free_acceptor_enc;
++		ctx->acceptor_enc_aux =
++			context_v2_alloc_cipher(ctx, "cbc(aes)",
++						ctx->acceptor_seal);
++		if (ctx->acceptor_enc_aux == NULL) {
++			crypto_free_blkcipher(ctx->initiator_enc_aux);
++			goto out_free_acceptor_enc;
++		}
++	}
++
+ 	return 0;
+ 
+ out_free_acceptor_enc:
+@@ -537,6 +603,8 @@ gss_delete_sec_context_kerberos(void *internal_ctx) {
+ 	crypto_free_blkcipher(kctx->enc);
+ 	crypto_free_blkcipher(kctx->acceptor_enc);
+ 	crypto_free_blkcipher(kctx->initiator_enc);
++	crypto_free_blkcipher(kctx->acceptor_enc_aux);
++	crypto_free_blkcipher(kctx->initiator_enc_aux);
+ 	kfree(kctx->mech_used.data);
+ 	kfree(kctx);
+ }
+diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+index 4aa46b28298c..a1a3585fa761 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
++++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+@@ -113,8 +113,8 @@ gss_krb5_remove_padding(struct xdr_buf *buf, int blocksize)
+ 	return 0;
+ }
+ 
+-static void
+-make_confounder(char *p, u32 conflen)
++void
++gss_krb5_make_confounder(char *p, u32 conflen)
+ {
+ 	static u64 i = 0;
+ 	u64 *q = (u64 *)p;
+@@ -204,7 +204,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
+ 	memset(ptr + 4, 0xff, 4);
+ 	*(__be16 *)(ptr + 4) = cpu_to_le16(kctx->gk5e->sealalg);
+ 
+-	make_confounder(msg_start, blocksize);
++	gss_krb5_make_confounder(msg_start, blocksize);
+ 
+ 	if (kctx->gk5e->keyed_cksum)
+ 		cksumkey = kctx->cksum;

commit de9c17eb4a912c9028f7b470eb80815144883b26
+Author: Kevin Coffman 
+Date:   Wed Mar 17 13:02:59 2010 -0400
+
+    gss_krb5: add support for new token formats in rfc4121
+    
+    This is a step toward support for AES encryption types which are
+    required to use the new token formats defined in rfc4121.
+    
+    Signed-off-by: Kevin Coffman 
+    [SteveD: Fixed a typo in gss_verify_mic_v2()]
+    Signed-off-by: Steve Dickson 
+    [Trond: Got rid of the TEST_ROTATE/TEST_EXTRA_COUNT crap]
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
+index db0522b4c4c9..0085a30fd204 100644
+--- a/include/linux/sunrpc/gss_krb5.h
++++ b/include/linux/sunrpc/gss_krb5.h
+@@ -53,6 +53,8 @@
+ /* Maximum blocksize for the supported crypto algorithms */
+ #define GSS_KRB5_MAX_BLOCKSIZE  (16)
+ 
++struct krb5_ctx;
++
+ struct gss_krb5_enctype {
+ 	const u32		etype;		/* encryption (key) type */
+ 	const u32		ctype;		/* checksum type */
+@@ -75,6 +77,12 @@ struct gss_krb5_enctype {
+ 	u32 (*mk_key) (const struct gss_krb5_enctype *gk5e,
+ 		       struct xdr_netobj *in,
+ 		       struct xdr_netobj *out);	/* complete key generation */
++	u32 (*encrypt_v2) (struct krb5_ctx *kctx, u32 offset,
++			   struct xdr_buf *buf, int ec,
++			   struct page **pages); /* v2 encryption function */
++	u32 (*decrypt_v2) (struct krb5_ctx *kctx, u32 offset,
++			   struct xdr_buf *buf, u32 *headskip,
++			   u32 *tailskip);	/* v2 decryption function */
+ };
+ 
+ /* krb5_ctx flags definitions */
+@@ -112,6 +120,18 @@ extern spinlock_t krb5_seq_lock;
+ #define KG_TOK_MIC_MSG    0x0101
+ #define KG_TOK_WRAP_MSG   0x0201
+ 
++#define KG2_TOK_INITIAL     0x0101
++#define KG2_TOK_RESPONSE    0x0202
++#define KG2_TOK_MIC         0x0404
++#define KG2_TOK_WRAP        0x0504
++
++#define KG2_TOKEN_FLAG_SENTBYACCEPTOR   0x01
++#define KG2_TOKEN_FLAG_SEALED           0x02
++#define KG2_TOKEN_FLAG_ACCEPTORSUBKEY   0x04
++
++#define KG2_RESP_FLAG_ERROR             0x0001
++#define KG2_RESP_FLAG_DELEG_OK          0x0002
++
+ enum sgn_alg {
+ 	SGN_ALG_DES_MAC_MD5 = 0x0000,
+ 	SGN_ALG_MD2_5 = 0x0001,
+@@ -136,6 +156,9 @@ enum seal_alg {
+ #define CKSUMTYPE_RSA_MD5_DES		0x0008
+ #define CKSUMTYPE_NIST_SHA		0x0009
+ #define CKSUMTYPE_HMAC_SHA1_DES3	0x000c
++#define CKSUMTYPE_HMAC_SHA1_96_AES128   0x000f
++#define CKSUMTYPE_HMAC_SHA1_96_AES256   0x0010
++#define CKSUMTYPE_HMAC_MD5_ARCFOUR      -138 /* Microsoft md5 hmac cksumtype */
+ 
+ /* from gssapi_err_krb5.h */
+ #define KG_CCACHE_NOMATCH                        (39756032L)
+@@ -212,6 +235,11 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
+ 		struct xdr_buf *body, int body_offset, u8 *cksumkey,
+ 		struct xdr_netobj *cksumout);
+ 
++u32
++make_checksum_v2(struct krb5_ctx *, char *header, int hdrlen,
++		 struct xdr_buf *body, int body_offset, u8 *key,
++		 struct xdr_netobj *cksum);
++
+ u32 gss_get_mic_kerberos(struct gss_ctx *, struct xdr_buf *,
+ 		struct xdr_netobj *);
+ 
+diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+index bb76873aa019..ca52ac28a537 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
++++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+@@ -197,6 +197,80 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
+ 	return err ? GSS_S_FAILURE : 0;
+ }
+ 
++/*
++ * checksum the plaintext data and hdrlen bytes of the token header
++ * Per rfc4121, sec. 4.2.4, the checksum is performed over the data
++ * body then over the first 16 octets of the MIC token
++ * Inclusion of the header data in the calculation of the
++ * checksum is optional.
++ */
++u32
++make_checksum_v2(struct krb5_ctx *kctx, char *header, int hdrlen,
++		 struct xdr_buf *body, int body_offset, u8 *cksumkey,
++		 struct xdr_netobj *cksumout)
++{
++	struct hash_desc desc;
++	struct scatterlist sg[1];
++	int err;
++	u8 checksumdata[GSS_KRB5_MAX_CKSUM_LEN];
++	unsigned int checksumlen;
++
++	if (kctx->gk5e->keyed_cksum == 0) {
++		dprintk("%s: expected keyed hash for %s\n",
++			__func__, kctx->gk5e->name);
++		return GSS_S_FAILURE;
++	}
++	if (cksumkey == NULL) {
++		dprintk("%s: no key supplied for %s\n",
++			__func__, kctx->gk5e->name);
++		return GSS_S_FAILURE;
++	}
++
++	desc.tfm = crypto_alloc_hash(kctx->gk5e->cksum_name, 0,
++							CRYPTO_ALG_ASYNC);
++	if (IS_ERR(desc.tfm))
++		return GSS_S_FAILURE;
++	checksumlen = crypto_hash_digestsize(desc.tfm);
++	desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
++
++	err = crypto_hash_setkey(desc.tfm, cksumkey, kctx->gk5e->keylength);
++	if (err)
++		goto out;
++
++	err = crypto_hash_init(&desc);
++	if (err)
++		goto out;
++	err = xdr_process_buf(body, body_offset, body->len - body_offset,
++			      checksummer, &desc);
++	if (err)
++		goto out;
++	if (header != NULL) {
++		sg_init_one(sg, header, hdrlen);
++		err = crypto_hash_update(&desc, sg, hdrlen);
++		if (err)
++			goto out;
++	}
++	err = crypto_hash_final(&desc, checksumdata);
++	if (err)
++		goto out;
++
++	cksumout->len = kctx->gk5e->cksumlength;
++
++	switch (kctx->gk5e->ctype) {
++	case CKSUMTYPE_HMAC_SHA1_96_AES128:
++	case CKSUMTYPE_HMAC_SHA1_96_AES256:
++		/* note that this truncates the hash */
++		memcpy(cksumout->data, checksumdata, kctx->gk5e->cksumlength);
++		break;
++	default:
++		BUG();
++		break;
++	}
++out:
++	crypto_free_hash(desc.tfm);
++	return err ? GSS_S_FAILURE : 0;
++}
++
+ struct encryptor_desc {
+ 	u8 iv[GSS_KRB5_MAX_BLOCKSIZE];
+ 	struct blkcipher_desc desc;
+diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
+index 7ede900049a7..477a546d19bb 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
+@@ -91,6 +91,33 @@ setup_token(struct krb5_ctx *ctx, struct xdr_netobj *token)
+ 	return (char *)krb5_hdr;
+ }
+ 
++static void *
++setup_token_v2(struct krb5_ctx *ctx, struct xdr_netobj *token)
++{
++	__be16 *ptr, *krb5_hdr;
++	u8 *p, flags = 0x00;
++
++	if ((ctx->flags & KRB5_CTX_FLAG_INITIATOR) == 0)
++		flags |= 0x01;
++	if (ctx->flags & KRB5_CTX_FLAG_ACCEPTOR_SUBKEY)
++		flags |= 0x04;
++
++	/* Per rfc 4121, sec 4.2.6.1, there is no header,
++	 * just start the token */
++	krb5_hdr = ptr = (__be16 *)token->data;
++
++	*ptr++ = KG2_TOK_MIC;
++	p = (u8 *)ptr;
++	*p++ = flags;
++	*p++ = 0xff;
++	ptr = (__be16 *)p;
++	*ptr++ = 0xffff;
++	*ptr++ = 0xffff;
++
++	token->len = GSS_KRB5_TOK_HDR_LEN + ctx->gk5e->cksumlength;
++	return krb5_hdr;
++}
++
+ static u32
+ gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text,
+ 		struct xdr_netobj *token)
+@@ -132,6 +159,45 @@ gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text,
+ 	return (ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE;
+ }
+ 
++u32
++gss_get_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *text,
++		struct xdr_netobj *token)
++{
++	char cksumdata[GSS_KRB5_MAX_CKSUM_LEN];
++	struct xdr_netobj cksumobj = { .len = sizeof(cksumdata),
++				       .data = cksumdata};
++	void *krb5_hdr;
++	s32 now;
++	u64 seq_send;
++	u8 *cksumkey;
++
++	dprintk("RPC:       %s\n", __func__);
++
++	krb5_hdr = setup_token_v2(ctx, token);
++
++	/* Set up the sequence number. Now 64-bits in clear
++	 * text and w/o direction indicator */
++	spin_lock(&krb5_seq_lock);
++	seq_send = ctx->seq_send64++;
++	spin_unlock(&krb5_seq_lock);
++	*((u64 *)(krb5_hdr + 8)) = cpu_to_be64(seq_send);
++
++	if (ctx->initiate)
++		cksumkey = ctx->initiator_sign;
++	else
++		cksumkey = ctx->acceptor_sign;
++
++	if (make_checksum_v2(ctx, krb5_hdr, GSS_KRB5_TOK_HDR_LEN,
++			     text, 0, cksumkey, &cksumobj))
++		return GSS_S_FAILURE;
++
++	memcpy(krb5_hdr + GSS_KRB5_TOK_HDR_LEN, cksumobj.data, cksumobj.len);
++
++	now = get_seconds();
++
++	return (ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE;
++}
++
+ u32
+ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
+ 		     struct xdr_netobj *token)
+@@ -144,6 +210,9 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
+ 	case ENCTYPE_DES_CBC_RAW:
+ 	case ENCTYPE_DES3_CBC_RAW:
+ 		return gss_get_mic_v1(ctx, text, token);
++	case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
++	case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
++		return gss_get_mic_v2(ctx, text, token);
+ 	}
+ }
+ 
+diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
+index 3e15bdb5a9eb..4ede4cc4391f 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
+@@ -141,6 +141,64 @@ gss_verify_mic_v1(struct krb5_ctx *ctx,
+ 	return GSS_S_COMPLETE;
+ }
+ 
++static u32
++gss_verify_mic_v2(struct krb5_ctx *ctx,
++		struct xdr_buf *message_buffer, struct xdr_netobj *read_token)
++{
++	char cksumdata[GSS_KRB5_MAX_CKSUM_LEN];
++	struct xdr_netobj cksumobj = {.len = sizeof(cksumdata),
++				      .data = cksumdata};
++	s32 now;
++	u64 seqnum;
++	u8 *ptr = read_token->data;
++	u8 *cksumkey;
++	u8 flags;
++	int i;
++
++	dprintk("RPC:       %s\n", __func__);
++
++	if (be16_to_cpu(*((__be16 *)ptr)) != KG2_TOK_MIC)
++		return GSS_S_DEFECTIVE_TOKEN;
++
++	flags = ptr[2];
++	if ((!ctx->initiate && (flags & KG2_TOKEN_FLAG_SENTBYACCEPTOR)) ||
++	    (ctx->initiate && !(flags & KG2_TOKEN_FLAG_SENTBYACCEPTOR)))
++		return GSS_S_BAD_SIG;
++
++	if (flags & KG2_TOKEN_FLAG_SEALED) {
++		dprintk("%s: token has unexpected sealed flag\n", __func__);
++		return GSS_S_FAILURE;
++	}
++
++	for (i = 3; i < 8; i++)
++		if (ptr[i] != 0xff)
++			return GSS_S_DEFECTIVE_TOKEN;
++
++	if (ctx->initiate)
++		cksumkey = ctx->acceptor_sign;
++	else
++		cksumkey = ctx->initiator_sign;
++
++	if (make_checksum_v2(ctx, ptr, GSS_KRB5_TOK_HDR_LEN, message_buffer, 0,
++			     cksumkey, &cksumobj))
++		return GSS_S_FAILURE;
++
++	if (memcmp(cksumobj.data, ptr + GSS_KRB5_TOK_HDR_LEN,
++				ctx->gk5e->cksumlength))
++		return GSS_S_BAD_SIG;
++
++	/* it got through unscathed.  Make sure the context is unexpired */
++	now = get_seconds();
++	if (now > ctx->endtime)
++		return GSS_S_CONTEXT_EXPIRED;
++
++	/* do sequencing checks */
++
++	seqnum = be64_to_cpup((__be64 *)ptr + 8);
++
++	return GSS_S_COMPLETE;
++}
++
+ u32
+ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
+ 			struct xdr_buf *message_buffer,
+@@ -154,6 +212,9 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
+ 	case ENCTYPE_DES_CBC_RAW:
+ 	case ENCTYPE_DES3_CBC_RAW:
+ 		return gss_verify_mic_v1(ctx, message_buffer, read_token);
++	case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
++	case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
++		return gss_verify_mic_v2(ctx, message_buffer, read_token);
+ 	}
+ }
+ 
+diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+index 1c8ebd3dbd3c..4aa46b28298c 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
++++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+@@ -340,6 +340,174 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
+ 	return GSS_S_COMPLETE;
+ }
+ 
++/*
++ * We cannot currently handle tokens with rotated data.  We need a
++ * generalized routine to rotate the data in place.  It is anticipated
++ * that we won't encounter rotated data in the general case.
++ */
++static u32
++rotate_left(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf, u16 rrc)
++{
++	unsigned int realrrc = rrc % (buf->len - offset - GSS_KRB5_TOK_HDR_LEN);
++
++	if (realrrc == 0)
++		return 0;
++
++	dprintk("%s: cannot process token with rotated data: "
++		"rrc %u, realrrc %u\n", __func__, rrc, realrrc);
++	return 1;
++}
++
++static u32
++gss_wrap_kerberos_v2(struct krb5_ctx *kctx, u32 offset,
++		     struct xdr_buf *buf, struct page **pages)
++{
++	int		blocksize;
++	u8		*ptr, *plainhdr;
++	s32		now;
++	u8		flags = 0x00;
++	__be16		*be16ptr, ec = 0;
++	__be64		*be64ptr;
++	u32		err;
++
++	dprintk("RPC:       %s\n", __func__);
++
++	if (kctx->gk5e->encrypt_v2 == NULL)
++		return GSS_S_FAILURE;
++
++	/* make room for gss token header */
++	if (xdr_extend_head(buf, offset, GSS_KRB5_TOK_HDR_LEN))
++		return GSS_S_FAILURE;
++
++	/* construct gss token header */
++	ptr = plainhdr = buf->head[0].iov_base + offset;
++	*ptr++ = (unsigned char) ((KG2_TOK_WRAP>>8) & 0xff);
++	*ptr++ = (unsigned char) (KG2_TOK_WRAP & 0xff);
++
++	if ((kctx->flags & KRB5_CTX_FLAG_INITIATOR) == 0)
++		flags |= KG2_TOKEN_FLAG_SENTBYACCEPTOR;
++	if ((kctx->flags & KRB5_CTX_FLAG_ACCEPTOR_SUBKEY) != 0)
++		flags |= KG2_TOKEN_FLAG_ACCEPTORSUBKEY;
++	/* We always do confidentiality in wrap tokens */
++	flags |= KG2_TOKEN_FLAG_SEALED;
++
++	*ptr++ = flags;
++	*ptr++ = 0xff;
++	be16ptr = (__be16 *)ptr;
++
++	blocksize = crypto_blkcipher_blocksize(kctx->acceptor_enc);
++	*be16ptr++ = cpu_to_be16(ec);
++	/* "inner" token header always uses 0 for RRC */
++	*be16ptr++ = cpu_to_be16(0);
++
++	be64ptr = (__be64 *)be16ptr;
++	spin_lock(&krb5_seq_lock);
++	*be64ptr = cpu_to_be64(kctx->seq_send64++);
++	spin_unlock(&krb5_seq_lock);
++
++	err = (*kctx->gk5e->encrypt_v2)(kctx, offset, buf, ec, pages);
++	if (err)
++		return err;
++
++	now = get_seconds();
++	return (kctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE;
++}
++
++static u32
++gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
++{
++	s32		now;
++	u64		seqnum;
++	u8		*ptr;
++	u8		flags = 0x00;
++	u16		ec, rrc;
++	int		err;
++	u32		headskip, tailskip;
++	u8		decrypted_hdr[GSS_KRB5_TOK_HDR_LEN];
++	unsigned int	movelen;
++
++
++	dprintk("RPC:       %s\n", __func__);
++
++	if (kctx->gk5e->decrypt_v2 == NULL)
++		return GSS_S_FAILURE;
++
++	ptr = buf->head[0].iov_base + offset;
++
++	if (be16_to_cpu(*((__be16 *)ptr)) != KG2_TOK_WRAP)
++		return GSS_S_DEFECTIVE_TOKEN;
++
++	flags = ptr[2];
++	if ((!kctx->initiate && (flags & KG2_TOKEN_FLAG_SENTBYACCEPTOR)) ||
++	    (kctx->initiate && !(flags & KG2_TOKEN_FLAG_SENTBYACCEPTOR)))
++		return GSS_S_BAD_SIG;
++
++	if ((flags & KG2_TOKEN_FLAG_SEALED) == 0) {
++		dprintk("%s: token missing expected sealed flag\n", __func__);
++		return GSS_S_DEFECTIVE_TOKEN;
++	}
++
++	if (ptr[3] != 0xff)
++		return GSS_S_DEFECTIVE_TOKEN;
++
++	ec = be16_to_cpup((__be16 *)(ptr + 4));
++	rrc = be16_to_cpup((__be16 *)(ptr + 6));
++
++	seqnum = be64_to_cpup((__be64 *)(ptr + 8));
++
++	if (rrc != 0) {
++		err = rotate_left(kctx, offset, buf, rrc);
++		if (err)
++			return GSS_S_FAILURE;
++	}
++
++	err = (*kctx->gk5e->decrypt_v2)(kctx, offset, buf,
++					&headskip, &tailskip);
++	if (err)
++		return GSS_S_FAILURE;
++
++	/*
++	 * Retrieve the decrypted gss token header and verify
++	 * it against the original
++	 */
++	err = read_bytes_from_xdr_buf(buf,
++				buf->len - GSS_KRB5_TOK_HDR_LEN - tailskip,
++				decrypted_hdr, GSS_KRB5_TOK_HDR_LEN);
++	if (err) {
++		dprintk("%s: error %u getting decrypted_hdr\n", __func__, err);
++		return GSS_S_FAILURE;
++	}
++	if (memcmp(ptr, decrypted_hdr, 6)
++				|| memcmp(ptr + 8, decrypted_hdr + 8, 8)) {
++		dprintk("%s: token hdr, plaintext hdr mismatch!\n", __func__);
++		return GSS_S_FAILURE;
++	}
++
++	/* do sequencing checks */
++
++	/* it got through unscathed.  Make sure the context is unexpired */
++	now = get_seconds();
++	if (now > kctx->endtime)
++		return GSS_S_CONTEXT_EXPIRED;
++
++	/*
++	 * Move the head data back to the right position in xdr_buf.
++	 * We ignore any "ec" data since it might be in the head or
++	 * the tail, and we really don't need to deal with it.
++	 * Note that buf->head[0].iov_len may indicate the available
++	 * head buffer space rather than that actually occupied.
++	 */
++	movelen = min_t(unsigned int, buf->head[0].iov_len, buf->len);
++	movelen -= offset + GSS_KRB5_TOK_HDR_LEN + headskip;
++	BUG_ON(offset + GSS_KRB5_TOK_HDR_LEN + headskip + movelen >
++							buf->head[0].iov_len);
++	memmove(ptr, ptr + GSS_KRB5_TOK_HDR_LEN + headskip, movelen);
++	buf->head[0].iov_len -= GSS_KRB5_TOK_HDR_LEN + headskip;
++	buf->len -= GSS_KRB5_TOK_HDR_LEN + headskip;
++
++	return GSS_S_COMPLETE;
++}
++
+ u32
+ gss_wrap_kerberos(struct gss_ctx *gctx, int offset,
+ 		  struct xdr_buf *buf, struct page **pages)
+@@ -352,6 +520,9 @@ gss_wrap_kerberos(struct gss_ctx *gctx, int offset,
+ 	case ENCTYPE_DES_CBC_RAW:
+ 	case ENCTYPE_DES3_CBC_RAW:
+ 		return gss_wrap_kerberos_v1(kctx, offset, buf, pages);
++	case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
++	case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
++		return gss_wrap_kerberos_v2(kctx, offset, buf, pages);
+ 	}
+ }
+ 
+@@ -366,6 +537,9 @@ gss_unwrap_kerberos(struct gss_ctx *gctx, int offset, struct xdr_buf *buf)
+ 	case ENCTYPE_DES_CBC_RAW:
+ 	case ENCTYPE_DES3_CBC_RAW:
+ 		return gss_unwrap_kerberos_v1(kctx, offset, buf);
++	case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
++	case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
++		return gss_unwrap_kerberos_v2(kctx, offset, buf);
+ 	}
+ }
+ 

commit c43abaedaff92a7bcbfe04b593164bb5faba3078
+Author: Kevin Coffman 
+Date:   Wed Mar 17 13:02:58 2010 -0400
+
+    xdr: Add an export for the helper function write_bytes_to_xdr_buf()
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: Steve Dickson 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
+index 2763fde88499..a1f82a87d34d 100644
+--- a/net/sunrpc/xdr.c
++++ b/net/sunrpc/xdr.c
+@@ -762,6 +762,7 @@ int write_bytes_to_xdr_buf(struct xdr_buf *buf, unsigned int base, void *obj, un
+ 	__write_bytes_to_xdr_buf(&subbuf, obj, len);
+ 	return 0;
+ }
++EXPORT_SYMBOL_GPL(write_bytes_to_xdr_buf);
+ 
+ int
+ xdr_decode_word(struct xdr_buf *buf, unsigned int base, u32 *obj)

commit 958142e97e04d6c266ae093739bbbbd03afcd497
+Author: Kevin Coffman 
+Date:   Wed Mar 17 13:02:55 2010 -0400
+
+    gss_krb5: add support for triple-des encryption
+    
+    Add the final pieces to support the triple-des encryption type.
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: Steve Dickson 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
+index 04d5279f17df..db0522b4c4c9 100644
+--- a/include/linux/sunrpc/gss_krb5.h
++++ b/include/linux/sunrpc/gss_krb5.h
+@@ -261,3 +261,8 @@ krb5_derive_key(const struct gss_krb5_enctype *gk5e,
+ 		const struct xdr_netobj *inkey,
+ 		struct xdr_netobj *outkey,
+ 		const struct xdr_netobj *in_constant);
++
++u32
++gss_krb5_des3_make_key(const struct gss_krb5_enctype *gk5e,
++		       struct xdr_netobj *randombits,
++		       struct xdr_netobj *key);
+diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+index cae04d7a45a5..bb76873aa019 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
++++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+@@ -184,6 +184,9 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
+ 		       checksumdata + checksumlen - kctx->gk5e->cksumlength,
+ 		       kctx->gk5e->cksumlength);
+ 		break;
++	case CKSUMTYPE_HMAC_SHA1_DES3:
++		memcpy(cksumout->data, checksumdata, kctx->gk5e->cksumlength);
++		break;
+ 	default:
+ 		BUG();
+ 		break;
+diff --git a/net/sunrpc/auth_gss/gss_krb5_keys.c b/net/sunrpc/auth_gss/gss_krb5_keys.c
+index 253b4149584a..d54668790f0c 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_keys.c
++++ b/net/sunrpc/auth_gss/gss_krb5_keys.c
+@@ -250,3 +250,56 @@ u32 krb5_derive_key(const struct gss_krb5_enctype *gk5e,
+ err_return:
+ 	return ret;
+ }
++
++#define smask(step) ((1<>step)&smask(step)))
++#define parity_char(x) pstep(pstep(pstep((x), 4), 2), 1)
++
++static void mit_des_fixup_key_parity(u8 key[8])
++{
++	int i;
++	for (i = 0; i < 8; i++) {
++		key[i] &= 0xfe;
++		key[i] |= 1^parity_char(key[i]);
++	}
++}
++
++/*
++ * This is the des3 key derivation postprocess function
++ */
++u32 gss_krb5_des3_make_key(const struct gss_krb5_enctype *gk5e,
++			   struct xdr_netobj *randombits,
++			   struct xdr_netobj *key)
++{
++	int i;
++	u32 ret = EINVAL;
++
++	if (key->len != 24) {
++		dprintk("%s: key->len is %d\n", __func__, key->len);
++		goto err_out;
++	}
++	if (randombits->len != 21) {
++		dprintk("%s: randombits->len is %d\n",
++			__func__, randombits->len);
++		goto err_out;
++	}
++
++	/* take the seven bytes, move them around into the top 7 bits of the
++	   8 key bytes, then compute the parity bits.  Do this three times. */
++
++	for (i = 0; i < 3; i++) {
++		memcpy(key->data + i*8, randombits->data + i*7, 7);
++		key->data[i*8+7] = (((key->data[i*8]&1)<<1) |
++				    ((key->data[i*8+1]&1)<<2) |
++				    ((key->data[i*8+2]&1)<<3) |
++				    ((key->data[i*8+3]&1)<<4) |
++				    ((key->data[i*8+4]&1)<<5) |
++				    ((key->data[i*8+5]&1)<<6) |
++				    ((key->data[i*8+6]&1)<<7));
++
++		mit_des_fixup_key_parity(key->data + i*8);
++	}
++	ret = 0;
++err_out:
++	return ret;
++}
+diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
+index 03f1dcddbd29..7cebdf843266 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
++++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
+@@ -71,6 +71,26 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
+ 	  .cksumlength = 8,
+ 	  .keyed_cksum = 0,
+ 	},
++	/*
++	 * 3DES
++	 */
++	{
++	  .etype = ENCTYPE_DES3_CBC_RAW,
++	  .ctype = CKSUMTYPE_HMAC_SHA1_DES3,
++	  .name = "des3-hmac-sha1",
++	  .encrypt_name = "cbc(des3_ede)",
++	  .cksum_name = "hmac(sha1)",
++	  .encrypt = krb5_encrypt,
++	  .decrypt = krb5_decrypt,
++	  .mk_key = gss_krb5_des3_make_key,
++	  .signalg = SGN_ALG_HMAC_SHA1_DES3_KD,
++	  .sealalg = SEAL_ALG_DES3KD,
++	  .keybytes = 21,
++	  .keylength = 24,
++	  .blocksize = 8,
++	  .cksumlength = 20,
++	  .keyed_cksum = 1,
++	},
+ };
+ 
+ static const int num_supported_enctypes =
+@@ -440,6 +460,9 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx)
+ 	p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype));
+ 	if (IS_ERR(p))
+ 		goto out_err;
++	/* Map ENCTYPE_DES3_CBC_SHA1 to ENCTYPE_DES3_CBC_RAW */
++	if (ctx->enctype == ENCTYPE_DES3_CBC_SHA1)
++		ctx->enctype = ENCTYPE_DES3_CBC_RAW;
+ 	ctx->gk5e = get_gss_krb5_enctype(ctx->enctype);
+ 	if (ctx->gk5e == NULL) {
+ 		dprintk("gss_kerberos_mech: unsupported krb5 enctype %u\n",
+diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
+index cd512719092b..7ede900049a7 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
+@@ -142,6 +142,7 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
+ 	default:
+ 		BUG();
+ 	case ENCTYPE_DES_CBC_RAW:
++	case ENCTYPE_DES3_CBC_RAW:
+ 		return gss_get_mic_v1(ctx, text, token);
+ 	}
+ }
+diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
+index 7515bffddf15..3e15bdb5a9eb 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
+@@ -152,6 +152,7 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
+ 	default:
+ 		BUG();
+ 	case ENCTYPE_DES_CBC_RAW:
++	case ENCTYPE_DES3_CBC_RAW:
+ 		return gss_verify_mic_v1(ctx, message_buffer, read_token);
+ 	}
+ }
+diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+index 2eb3046a84ea..1c8ebd3dbd3c 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
++++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+@@ -350,6 +350,7 @@ gss_wrap_kerberos(struct gss_ctx *gctx, int offset,
+ 	default:
+ 		BUG();
+ 	case ENCTYPE_DES_CBC_RAW:
++	case ENCTYPE_DES3_CBC_RAW:
+ 		return gss_wrap_kerberos_v1(kctx, offset, buf, pages);
+ 	}
+ }
+@@ -363,6 +364,7 @@ gss_unwrap_kerberos(struct gss_ctx *gctx, int offset, struct xdr_buf *buf)
+ 	default:
+ 		BUG();
+ 	case ENCTYPE_DES_CBC_RAW:
++	case ENCTYPE_DES3_CBC_RAW:
+ 		return gss_unwrap_kerberos_v1(kctx, offset, buf);
+ 	}
+ }

commit 47d84807762966c3611c38adecec6ea703ddda7a
+Author: Kevin Coffman 
+Date:   Wed Mar 17 13:02:54 2010 -0400
+
+    gss_krb5: handle new context format from gssd
+    
+    For encryption types other than DES, gssd sends down context information
+    in a new format.  This new format includes the information needed to
+    support the new Kerberos GSS-API tokens defined in rfc4121.
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: Steve Dickson 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
+index d31ba0304d18..04d5279f17df 100644
+--- a/include/linux/sunrpc/gss_krb5.h
++++ b/include/linux/sunrpc/gss_krb5.h
+@@ -72,21 +72,36 @@ struct gss_krb5_enctype {
+ 	u32 (*decrypt) (struct crypto_blkcipher *tfm,
+ 			void *iv, void *in, void *out,
+ 			int length);		/* decryption function */
+-	u32 (*mk_key) (struct gss_krb5_enctype *gk5e,
++	u32 (*mk_key) (const struct gss_krb5_enctype *gk5e,
+ 		       struct xdr_netobj *in,
+ 		       struct xdr_netobj *out);	/* complete key generation */
+ };
+ 
++/* krb5_ctx flags definitions */
++#define KRB5_CTX_FLAG_INITIATOR         0x00000001
++#define KRB5_CTX_FLAG_CFX               0x00000002
++#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY   0x00000004
++
+ struct krb5_ctx {
+ 	int			initiate; /* 1 = initiating, 0 = accepting */
+ 	u32			enctype;
++	u32			flags;
+ 	const struct gss_krb5_enctype *gk5e; /* enctype-specific info */
+ 	struct crypto_blkcipher	*enc;
+ 	struct crypto_blkcipher	*seq;
++	struct crypto_blkcipher *acceptor_enc;
++	struct crypto_blkcipher *initiator_enc;
+ 	u8			cksum[GSS_KRB5_MAX_KEYLEN];
+ 	s32			endtime;
+ 	u32			seq_send;
++	u64			seq_send64;
+ 	struct xdr_netobj	mech_used;
++	u8			initiator_sign[GSS_KRB5_MAX_KEYLEN];
++	u8			acceptor_sign[GSS_KRB5_MAX_KEYLEN];
++	u8			initiator_seal[GSS_KRB5_MAX_KEYLEN];
++	u8			acceptor_seal[GSS_KRB5_MAX_KEYLEN];
++	u8			initiator_integ[GSS_KRB5_MAX_KEYLEN];
++	u8			acceptor_integ[GSS_KRB5_MAX_KEYLEN];
+ };
+ 
+ extern spinlock_t krb5_seq_lock;
+@@ -151,6 +166,10 @@ enum seal_alg {
+ #define ENCTYPE_DES3_CBC_RAW    0x0006	/* DES-3 cbc mode raw */
+ #define ENCTYPE_DES_HMAC_SHA1   0x0008
+ #define ENCTYPE_DES3_CBC_SHA1   0x0010
++#define ENCTYPE_AES128_CTS_HMAC_SHA1_96 0x0011
++#define ENCTYPE_AES256_CTS_HMAC_SHA1_96 0x0012
++#define ENCTYPE_ARCFOUR_HMAC            0x0017
++#define ENCTYPE_ARCFOUR_HMAC_EXP        0x0018
+ #define ENCTYPE_UNKNOWN         0x01ff
+ 
+ /*
+@@ -238,7 +257,7 @@ int
+ xdr_extend_head(struct xdr_buf *buf, unsigned int base, unsigned int shiftlen);
+ 
+ u32
+-krb5_derive_key(struct gss_krb5_enctype *gk5e,
++krb5_derive_key(const struct gss_krb5_enctype *gk5e,
+ 		const struct xdr_netobj *inkey,
+ 		struct xdr_netobj *outkey,
+ 		const struct xdr_netobj *in_constant);
+diff --git a/net/sunrpc/auth_gss/gss_krb5_keys.c b/net/sunrpc/auth_gss/gss_krb5_keys.c
+index 832ce901bf68..253b4149584a 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_keys.c
++++ b/net/sunrpc/auth_gss/gss_krb5_keys.c
+@@ -147,7 +147,7 @@ static void krb5_nfold(u32 inbits, const u8 *in,
+  * Taken from MIT Kerberos and modified.
+  */
+ 
+-u32 krb5_derive_key(struct gss_krb5_enctype *gk5e,
++u32 krb5_derive_key(const struct gss_krb5_enctype *gk5e,
+ 		    const struct xdr_netobj *inkey,
+ 		    struct xdr_netobj *outkey,
+ 		    const struct xdr_netobj *in_constant)
+diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
+index fdf0eb2057ab..8b612e733563 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
++++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
+@@ -48,6 +48,8 @@
+ # define RPCDBG_FACILITY	RPCDBG_AUTH
+ #endif
+ 
++static struct gss_api_mech gss_kerberos_mech;	/* forward declaration */
++
+ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
+ 	/*
+ 	 * DES (All DES enctypes are mapped to the same gss functionality)
+@@ -247,6 +249,237 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx)
+ 	return PTR_ERR(p);
+ }
+ 
++struct crypto_blkcipher *
++context_v2_alloc_cipher(struct krb5_ctx *ctx, u8 *key)
++{
++	struct crypto_blkcipher *cp;
++
++	cp = crypto_alloc_blkcipher(ctx->gk5e->encrypt_name,
++					0, CRYPTO_ALG_ASYNC);
++	if (IS_ERR(cp)) {
++		dprintk("gss_kerberos_mech: unable to initialize "
++			"crypto algorithm %s\n", ctx->gk5e->encrypt_name);
++		return NULL;
++	}
++	if (crypto_blkcipher_setkey(cp, key, ctx->gk5e->keylength)) {
++		dprintk("gss_kerberos_mech: error setting key for "
++			"crypto algorithm %s\n", ctx->gk5e->encrypt_name);
++		crypto_free_blkcipher(cp);
++		return NULL;
++	}
++	return cp;
++}
++
++static inline void
++set_cdata(u8 cdata[GSS_KRB5_K5CLENGTH], u32 usage, u8 seed)
++{
++	cdata[0] = (usage>>24)&0xff;
++	cdata[1] = (usage>>16)&0xff;
++	cdata[2] = (usage>>8)&0xff;
++	cdata[3] = usage&0xff;
++	cdata[4] = seed;
++}
++
++static int
++context_derive_keys_des3(struct krb5_ctx *ctx, u8 *rawkey, u32 keylen)
++{
++	struct xdr_netobj c, keyin, keyout;
++	u8 cdata[GSS_KRB5_K5CLENGTH];
++	u32 err;
++
++	c.len = GSS_KRB5_K5CLENGTH;
++	c.data = cdata;
++
++	keyin.data = rawkey;
++	keyin.len = keylen;
++	keyout.len = keylen;
++
++	/* seq uses the raw key */
++	ctx->seq = context_v2_alloc_cipher(ctx, rawkey);
++	if (ctx->seq == NULL)
++		goto out_err;
++
++	ctx->enc = context_v2_alloc_cipher(ctx, rawkey);
++	if (ctx->enc == NULL)
++		goto out_free_seq;
++
++	/* derive cksum */
++	set_cdata(cdata, KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM);
++	keyout.data = ctx->cksum;
++	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c);
++	if (err) {
++		dprintk("%s: Error %d deriving cksum key\n",
++			__func__, err);
++		goto out_free_enc;
++	}
++
++	return 0;
++
++out_free_enc:
++	crypto_free_blkcipher(ctx->enc);
++out_free_seq:
++	crypto_free_blkcipher(ctx->seq);
++out_err:
++	return -EINVAL;
++}
++
++static int
++context_derive_keys_new(struct krb5_ctx *ctx, u8 *rawkey, u32 keylen)
++{
++	struct xdr_netobj c, keyin, keyout;
++	u8 cdata[GSS_KRB5_K5CLENGTH];
++	u32 err;
++
++	c.len = GSS_KRB5_K5CLENGTH;
++	c.data = cdata;
++
++	keyin.data = rawkey;
++	keyin.len = keylen;
++	keyout.len = keylen;
++
++	/* initiator seal encryption */
++	set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_ENCRYPTION);
++	keyout.data = ctx->initiator_seal;
++	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c);
++	if (err) {
++		dprintk("%s: Error %d deriving initiator_seal key\n",
++			__func__, err);
++		goto out_err;
++	}
++	ctx->initiator_enc = context_v2_alloc_cipher(ctx, ctx->initiator_seal);
++	if (ctx->initiator_enc == NULL)
++		goto out_err;
++
++	/* acceptor seal encryption */
++	set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_ENCRYPTION);
++	keyout.data = ctx->acceptor_seal;
++	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c);
++	if (err) {
++		dprintk("%s: Error %d deriving acceptor_seal key\n",
++			__func__, err);
++		goto out_free_initiator_enc;
++	}
++	ctx->acceptor_enc = context_v2_alloc_cipher(ctx, ctx->acceptor_seal);
++	if (ctx->acceptor_enc == NULL)
++		goto out_free_initiator_enc;
++
++	/* initiator sign checksum */
++	set_cdata(cdata, KG_USAGE_INITIATOR_SIGN, KEY_USAGE_SEED_CHECKSUM);
++	keyout.data = ctx->initiator_sign;
++	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c);
++	if (err) {
++		dprintk("%s: Error %d deriving initiator_sign key\n",
++			__func__, err);
++		goto out_free_acceptor_enc;
++	}
++
++	/* acceptor sign checksum */
++	set_cdata(cdata, KG_USAGE_ACCEPTOR_SIGN, KEY_USAGE_SEED_CHECKSUM);
++	keyout.data = ctx->acceptor_sign;
++	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c);
++	if (err) {
++		dprintk("%s: Error %d deriving acceptor_sign key\n",
++			__func__, err);
++		goto out_free_acceptor_enc;
++	}
++
++	/* initiator seal integrity */
++	set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_INTEGRITY);
++	keyout.data = ctx->initiator_integ;
++	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c);
++	if (err) {
++		dprintk("%s: Error %d deriving initiator_integ key\n",
++			__func__, err);
++		goto out_free_acceptor_enc;
++	}
++
++	/* acceptor seal integrity */
++	set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_INTEGRITY);
++	keyout.data = ctx->acceptor_integ;
++	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c);
++	if (err) {
++		dprintk("%s: Error %d deriving acceptor_integ key\n",
++			__func__, err);
++		goto out_free_acceptor_enc;
++	}
++
++	return 0;
++
++out_free_acceptor_enc:
++	crypto_free_blkcipher(ctx->acceptor_enc);
++out_free_initiator_enc:
++	crypto_free_blkcipher(ctx->initiator_enc);
++out_err:
++	return -EINVAL;
++}
++
++static int
++gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx)
++{
++	u8 rawkey[GSS_KRB5_MAX_KEYLEN];
++	int keylen;
++
++	p = simple_get_bytes(p, end, &ctx->flags, sizeof(ctx->flags));
++	if (IS_ERR(p))
++		goto out_err;
++	ctx->initiate = ctx->flags & KRB5_CTX_FLAG_INITIATOR;
++
++	p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime));
++	if (IS_ERR(p))
++		goto out_err;
++	p = simple_get_bytes(p, end, &ctx->seq_send64, sizeof(ctx->seq_send64));
++	if (IS_ERR(p))
++		goto out_err;
++	/* set seq_send for use by "older" enctypes */
++	ctx->seq_send = ctx->seq_send64;
++	if (ctx->seq_send64 != ctx->seq_send) {
++		dprintk("%s: seq_send64 %lx, seq_send %x overflow?\n", __func__,
++			(long unsigned)ctx->seq_send64, ctx->seq_send);
++		goto out_err;
++	}
++	p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype));
++	if (IS_ERR(p))
++		goto out_err;
++	ctx->gk5e = get_gss_krb5_enctype(ctx->enctype);
++	if (ctx->gk5e == NULL) {
++		dprintk("gss_kerberos_mech: unsupported krb5 enctype %u\n",
++			ctx->enctype);
++		p = ERR_PTR(-EINVAL);
++		goto out_err;
++	}
++	keylen = ctx->gk5e->keylength;
++
++	p = simple_get_bytes(p, end, rawkey, keylen);
++	if (IS_ERR(p))
++		goto out_err;
++
++	if (p != end) {
++		p = ERR_PTR(-EINVAL);
++		goto out_err;
++	}
++
++	ctx->mech_used.data = kmemdup(gss_kerberos_mech.gm_oid.data,
++				      gss_kerberos_mech.gm_oid.len, GFP_KERNEL);
++	if (unlikely(ctx->mech_used.data == NULL)) {
++		p = ERR_PTR(-ENOMEM);
++		goto out_err;
++	}
++	ctx->mech_used.len = gss_kerberos_mech.gm_oid.len;
++
++	switch (ctx->enctype) {
++	case ENCTYPE_DES3_CBC_RAW:
++		return context_derive_keys_des3(ctx, rawkey, keylen);
++	case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
++	case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
++		return context_derive_keys_new(ctx, rawkey, keylen);
++	default:
++		return -EINVAL;
++	}
++
++out_err:
++	return PTR_ERR(p);
++}
++
+ static int
+ gss_import_sec_context_kerberos(const void *p, size_t len,
+ 				struct gss_ctx *ctx_id)
+@@ -262,7 +495,7 @@ gss_import_sec_context_kerberos(const void *p, size_t len,
+ 	if (len == 85)
+ 		ret = gss_import_v1_context(p, end, ctx);
+ 	else
+-		ret = -EINVAL;
++		ret = gss_import_v2_context(p, end, ctx);
+ 
+ 	if (ret == 0)
+ 		ctx_id->internal_ctx_id = ctx;
+@@ -279,6 +512,8 @@ gss_delete_sec_context_kerberos(void *internal_ctx) {
+ 
+ 	crypto_free_blkcipher(kctx->seq);
+ 	crypto_free_blkcipher(kctx->enc);
++	crypto_free_blkcipher(kctx->acceptor_enc);
++	crypto_free_blkcipher(kctx->initiator_enc);
+ 	kfree(kctx->mech_used.data);
+ 	kfree(kctx);
+ }

commit 4891f2d008e4343eedea39ba1fe74864f1d32be0
+Author: Kevin Coffman 
+Date:   Wed Mar 17 13:02:53 2010 -0400
+
+    gss_krb5: import functionality to derive keys into the kernel
+    
+    Import the code to derive Kerberos keys from a base key into the
+    kernel.  This will allow us to change the format of the context
+    information sent down from gssd to include only a single key.
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: Steve Dickson 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
+index abf26efd44ac..d31ba0304d18 100644
+--- a/include/linux/sunrpc/gss_krb5.h
++++ b/include/linux/sunrpc/gss_krb5.h
+@@ -41,6 +41,9 @@
+ #include 
+ #include 
+ 
++/* Length of constant used in key derivation */
++#define GSS_KRB5_K5CLENGTH (5)
++
+ /* Maximum key length (in bytes) for the supported crypto algorithms*/
+ #define GSS_KRB5_MAX_KEYLEN (32)
+ 
+@@ -69,6 +72,9 @@ struct gss_krb5_enctype {
+ 	u32 (*decrypt) (struct crypto_blkcipher *tfm,
+ 			void *iv, void *in, void *out,
+ 			int length);		/* decryption function */
++	u32 (*mk_key) (struct gss_krb5_enctype *gk5e,
++		       struct xdr_netobj *in,
++		       struct xdr_netobj *out);	/* complete key generation */
+ };
+ 
+ struct krb5_ctx {
+@@ -147,6 +153,25 @@ enum seal_alg {
+ #define ENCTYPE_DES3_CBC_SHA1   0x0010
+ #define ENCTYPE_UNKNOWN         0x01ff
+ 
++/*
++ * Constants used for key derivation
++ */
++/* for 3DES */
++#define KG_USAGE_SEAL (22)
++#define KG_USAGE_SIGN (23)
++#define KG_USAGE_SEQ  (24)
++
++/* from rfc3961 */
++#define KEY_USAGE_SEED_CHECKSUM         (0x99)
++#define KEY_USAGE_SEED_ENCRYPTION       (0xAA)
++#define KEY_USAGE_SEED_INTEGRITY        (0x55)
++
++/* from rfc4121 */
++#define KG_USAGE_ACCEPTOR_SEAL  (22)
++#define KG_USAGE_ACCEPTOR_SIGN  (23)
++#define KG_USAGE_INITIATOR_SEAL (24)
++#define KG_USAGE_INITIATOR_SIGN (25)
++
+ /*
+  * This compile-time check verifies that we will not exceed the
+  * slack space allotted by the client and server auth_gss code
+@@ -211,3 +236,9 @@ krb5_get_seq_num(struct crypto_blkcipher *key,
+ 
+ int
+ xdr_extend_head(struct xdr_buf *buf, unsigned int base, unsigned int shiftlen);
++
++u32
++krb5_derive_key(struct gss_krb5_enctype *gk5e,
++		const struct xdr_netobj *inkey,
++		struct xdr_netobj *outkey,
++		const struct xdr_netobj *in_constant);
+diff --git a/net/sunrpc/auth_gss/Makefile b/net/sunrpc/auth_gss/Makefile
+index 4de8bcf26fa7..74a231735f67 100644
+--- a/net/sunrpc/auth_gss/Makefile
++++ b/net/sunrpc/auth_gss/Makefile
+@@ -10,7 +10,7 @@ auth_rpcgss-objs := auth_gss.o gss_generic_token.o \
+ obj-$(CONFIG_RPCSEC_GSS_KRB5) += rpcsec_gss_krb5.o
+ 
+ rpcsec_gss_krb5-objs := gss_krb5_mech.o gss_krb5_seal.o gss_krb5_unseal.o \
+-	gss_krb5_seqnum.o gss_krb5_wrap.o gss_krb5_crypto.o
++	gss_krb5_seqnum.o gss_krb5_wrap.o gss_krb5_crypto.o gss_krb5_keys.o
+ 
+ obj-$(CONFIG_RPCSEC_GSS_SPKM3) += rpcsec_gss_spkm3.o
+ 
+diff --git a/net/sunrpc/auth_gss/gss_krb5_keys.c b/net/sunrpc/auth_gss/gss_krb5_keys.c
+new file mode 100644
+index 000000000000..832ce901bf68
+--- /dev/null
++++ b/net/sunrpc/auth_gss/gss_krb5_keys.c
+@@ -0,0 +1,252 @@
++/*
++ * COPYRIGHT (c) 2008
++ * The Regents of the University of Michigan
++ * ALL RIGHTS RESERVED
++ *
++ * Permission is granted to use, copy, create derivative works
++ * and redistribute this software and such derivative works
++ * for any purpose, so long as the name of The University of
++ * Michigan is not used in any advertising or publicity
++ * pertaining to the use of distribution of this software
++ * without specific, written prior authorization.  If the
++ * above copyright notice or any other identification of the
++ * University of Michigan is included in any copy of any
++ * portion of this software, then the disclaimer below must
++ * also be included.
++ *
++ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
++ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
++ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
++ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
++ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
++ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
++ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
++ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
++ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
++ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGES.
++ */
++
++/*
++ * Copyright (C) 1998 by the FundsXpress, INC.
++ *
++ * All rights reserved.
++ *
++ * Export of this software from the United States of America may require
++ * a specific license from the United States Government.  It is the
++ * responsibility of any person or organization contemplating export to
++ * obtain such a license before exporting.
++ *
++ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
++ * distribute this software and its documentation for any purpose and
++ * without fee is hereby granted, provided that the above copyright
++ * notice appear in all copies and that both that copyright notice and
++ * this permission notice appear in supporting documentation, and that
++ * the name of FundsXpress. not be used in advertising or publicity pertaining
++ * to distribution of the software without specific, written prior
++ * permission.  FundsXpress makes no representations about the suitability of
++ * this software for any purpose.  It is provided "as is" without express
++ * or implied warranty.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#ifdef RPC_DEBUG
++# define RPCDBG_FACILITY        RPCDBG_AUTH
++#endif
++
++/*
++ * This is the n-fold function as described in rfc3961, sec 5.1
++ * Taken from MIT Kerberos and modified.
++ */
++
++static void krb5_nfold(u32 inbits, const u8 *in,
++		       u32 outbits, u8 *out)
++{
++	int a, b, c, lcm;
++	int byte, i, msbit;
++
++	/* the code below is more readable if I make these bytes
++	   instead of bits */
++
++	inbits >>= 3;
++	outbits >>= 3;
++
++	/* first compute lcm(n,k) */
++
++	a = outbits;
++	b = inbits;
++
++	while (b != 0) {
++		c = b;
++		b = a%b;
++		a = c;
++	}
++
++	lcm = outbits*inbits/a;
++
++	/* now do the real work */
++
++	memset(out, 0, outbits);
++	byte = 0;
++
++	/* this will end up cycling through k lcm(k,n)/k times, which
++	   is correct */
++	for (i = lcm-1; i >= 0; i--) {
++		/* compute the msbit in k which gets added into this byte */
++		msbit = (
++			/* first, start with the msbit in the first,
++			 * unrotated byte */
++			 ((inbits << 3) - 1)
++			 /* then, for each byte, shift to the right
++			  * for each repetition */
++			 + (((inbits << 3) + 13) * (i/inbits))
++			 /* last, pick out the correct byte within
++			  * that shifted repetition */
++			 + ((inbits - (i % inbits)) << 3)
++			 ) % (inbits << 3);
++
++		/* pull out the byte value itself */
++		byte += (((in[((inbits - 1) - (msbit >> 3)) % inbits] << 8)|
++				  (in[((inbits) - (msbit >> 3)) % inbits]))
++				 >> ((msbit & 7) + 1)) & 0xff;
++
++		/* do the addition */
++		byte += out[i % outbits];
++		out[i % outbits] = byte & 0xff;
++
++		/* keep around the carry bit, if any */
++		byte >>= 8;
++
++	}
++
++	/* if there's a carry bit left over, add it back in */
++	if (byte) {
++		for (i = outbits - 1; i >= 0; i--) {
++			/* do the addition */
++			byte += out[i];
++			out[i] = byte & 0xff;
++
++			/* keep around the carry bit, if any */
++			byte >>= 8;
++		}
++	}
++}
++
++/*
++ * This is the DK (derive_key) function as described in rfc3961, sec 5.1
++ * Taken from MIT Kerberos and modified.
++ */
++
++u32 krb5_derive_key(struct gss_krb5_enctype *gk5e,
++		    const struct xdr_netobj *inkey,
++		    struct xdr_netobj *outkey,
++		    const struct xdr_netobj *in_constant)
++{
++	size_t blocksize, keybytes, keylength, n;
++	unsigned char *inblockdata, *outblockdata, *rawkey;
++	struct xdr_netobj inblock, outblock;
++	struct crypto_blkcipher *cipher;
++	u32 ret = EINVAL;
++
++	blocksize = gk5e->blocksize;
++	keybytes = gk5e->keybytes;
++	keylength = gk5e->keylength;
++
++	if ((inkey->len != keylength) || (outkey->len != keylength))
++		goto err_return;
++
++	cipher = crypto_alloc_blkcipher(gk5e->encrypt_name, 0,
++					CRYPTO_ALG_ASYNC);
++	if (IS_ERR(cipher))
++		goto err_return;
++	if (crypto_blkcipher_setkey(cipher, inkey->data, inkey->len))
++		goto err_return;
++
++	/* allocate and set up buffers */
++
++	ret = ENOMEM;
++	inblockdata = kmalloc(blocksize, GFP_KERNEL);
++	if (inblockdata == NULL)
++		goto err_free_cipher;
++
++	outblockdata = kmalloc(blocksize, GFP_KERNEL);
++	if (outblockdata == NULL)
++		goto err_free_in;
++
++	rawkey = kmalloc(keybytes, GFP_KERNEL);
++	if (rawkey == NULL)
++		goto err_free_out;
++
++	inblock.data = (char *) inblockdata;
++	inblock.len = blocksize;
++
++	outblock.data = (char *) outblockdata;
++	outblock.len = blocksize;
++
++	/* initialize the input block */
++
++	if (in_constant->len == inblock.len) {
++		memcpy(inblock.data, in_constant->data, inblock.len);
++	} else {
++		krb5_nfold(in_constant->len * 8, in_constant->data,
++			   inblock.len * 8, inblock.data);
++	}
++
++	/* loop encrypting the blocks until enough key bytes are generated */
++
++	n = 0;
++	while (n < keybytes) {
++		(*(gk5e->encrypt))(cipher, NULL, inblock.data,
++				   outblock.data, inblock.len);
++
++		if ((keybytes - n) <= outblock.len) {
++			memcpy(rawkey + n, outblock.data, (keybytes - n));
++			break;
++		}
++
++		memcpy(rawkey + n, outblock.data, outblock.len);
++		memcpy(inblock.data, outblock.data, outblock.len);
++		n += outblock.len;
++	}
++
++	/* postprocess the key */
++
++	inblock.data = (char *) rawkey;
++	inblock.len = keybytes;
++
++	BUG_ON(gk5e->mk_key == NULL);
++	ret = (*(gk5e->mk_key))(gk5e, &inblock, outkey);
++	if (ret) {
++		dprintk("%s: got %d from mk_key function for '%s'\n",
++			__func__, ret, gk5e->encrypt_name);
++		goto err_free_raw;
++	}
++
++	/* clean memory, free resources and exit */
++
++	ret = 0;
++
++err_free_raw:
++	memset(rawkey, 0, keybytes);
++	kfree(rawkey);
++err_free_out:
++	memset(outblockdata, 0, blocksize);
++	kfree(outblockdata);
++err_free_in:
++	memset(inblockdata, 0, blocksize);
++	kfree(inblockdata);
++err_free_cipher:
++	crypto_free_blkcipher(cipher);
++err_return:
++	return ret;
++}
+diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
+index 6f93f4752be4..fdf0eb2057ab 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
++++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
+@@ -60,6 +60,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
+ 	  .cksum_name = "md5",
+ 	  .encrypt = krb5_encrypt,
+ 	  .decrypt = krb5_decrypt,
++	  .mk_key = NULL,
+ 	  .signalg = SGN_ALG_DES_MAC_MD5,
+ 	  .sealalg = SEAL_ALG_DES,
+ 	  .keybytes = 7,

commit e1f6c07b1160ef28e8754d12e6c03288dd9d5ca8
+Author: Kevin Coffman 
+Date:   Wed Mar 17 13:02:52 2010 -0400
+
+    gss_krb5: add ability to have a keyed checksum (hmac)
+    
+    Encryption types besides DES may use a keyed checksum (hmac).
+    Modify the make_checksum() function to allow for a key
+    and take care of enctype-specific processing such as truncating
+    the resulting hash.
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: Steve Dickson 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
+index f94935599d13..abf26efd44ac 100644
+--- a/include/linux/sunrpc/gss_krb5.h
++++ b/include/linux/sunrpc/gss_krb5.h
+@@ -41,6 +41,9 @@
+ #include 
+ #include 
+ 
++/* Maximum key length (in bytes) for the supported crypto algorithms*/
++#define GSS_KRB5_MAX_KEYLEN (32)
++
+ /* Maximum checksum function output for the supported crypto algorithms */
+ #define GSS_KRB5_MAX_CKSUM_LEN  (20)
+ 
+@@ -74,6 +77,7 @@ struct krb5_ctx {
+ 	const struct gss_krb5_enctype *gk5e; /* enctype-specific info */
+ 	struct crypto_blkcipher	*enc;
+ 	struct crypto_blkcipher	*seq;
++	u8			cksum[GSS_KRB5_MAX_KEYLEN];
+ 	s32			endtime;
+ 	u32			seq_send;
+ 	struct xdr_netobj	mech_used;
+@@ -159,9 +163,10 @@ enum seal_alg {
+ 	+ GSS_KRB5_TOK_HDR_LEN                                   \
+ 	+ GSS_KRB5_MAX_CKSUM_LEN)
+ 
+-s32
+-make_checksum(char *, char *header, int hdrlen, struct xdr_buf *body,
+-		   int body_offset, struct xdr_netobj *cksum);
++u32
++make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
++		struct xdr_buf *body, int body_offset, u8 *cksumkey,
++		struct xdr_netobj *cksumout);
+ 
+ u32 gss_get_mic_kerberos(struct gss_ctx *, struct xdr_buf *,
+ 		struct xdr_netobj *);
+diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+index ccd5236953f7..cae04d7a45a5 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
++++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+@@ -123,21 +123,42 @@ checksummer(struct scatterlist *sg, void *data)
+ 	return crypto_hash_update(desc, sg, sg->length);
+ }
+ 
+-/* checksum the plaintext data and hdrlen bytes of the token header */
+-s32
+-make_checksum(char *cksumname, char *header, int hdrlen, struct xdr_buf *body,
+-		   int body_offset, struct xdr_netobj *cksum)
++/*
++ * checksum the plaintext data and hdrlen bytes of the token header
++ * The checksum is performed over the first 8 bytes of the
++ * gss token header and then over the data body
++ */
++u32
++make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
++	      struct xdr_buf *body, int body_offset, u8 *cksumkey,
++	      struct xdr_netobj *cksumout)
+ {
+-	struct hash_desc                desc; /* XXX add to ctx? */
++	struct hash_desc                desc;
+ 	struct scatterlist              sg[1];
+ 	int err;
++	u8 checksumdata[GSS_KRB5_MAX_CKSUM_LEN];
++	unsigned int checksumlen;
++
++	if (cksumout->len < kctx->gk5e->cksumlength) {
++		dprintk("%s: checksum buffer length, %u, too small for %s\n",
++			__func__, cksumout->len, kctx->gk5e->name);
++		return GSS_S_FAILURE;
++	}
+ 
+-	desc.tfm = crypto_alloc_hash(cksumname, 0, CRYPTO_ALG_ASYNC);
++	desc.tfm = crypto_alloc_hash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC);
+ 	if (IS_ERR(desc.tfm))
+ 		return GSS_S_FAILURE;
+-	cksum->len = crypto_hash_digestsize(desc.tfm);
+ 	desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+ 
++	checksumlen = crypto_hash_digestsize(desc.tfm);
++
++	if (cksumkey != NULL) {
++		err = crypto_hash_setkey(desc.tfm, cksumkey,
++					 kctx->gk5e->keylength);
++		if (err)
++			goto out;
++	}
++
+ 	err = crypto_hash_init(&desc);
+ 	if (err)
+ 		goto out;
+@@ -149,8 +170,25 @@ make_checksum(char *cksumname, char *header, int hdrlen, struct xdr_buf *body,
+ 			      checksummer, &desc);
+ 	if (err)
+ 		goto out;
+-	err = crypto_hash_final(&desc, cksum->data);
++	err = crypto_hash_final(&desc, checksumdata);
++	if (err)
++		goto out;
+ 
++	switch (kctx->gk5e->ctype) {
++	case CKSUMTYPE_RSA_MD5:
++		err = kctx->gk5e->encrypt(kctx->seq, NULL, checksumdata,
++					  checksumdata, checksumlen);
++		if (err)
++			goto out;
++		memcpy(cksumout->data,
++		       checksumdata + checksumlen - kctx->gk5e->cksumlength,
++		       kctx->gk5e->cksumlength);
++		break;
++	default:
++		BUG();
++		break;
++	}
++	cksumout->len = kctx->gk5e->cksumlength;
+ out:
+ 	crypto_free_hash(desc.tfm);
+ 	return err ? GSS_S_FAILURE : 0;
+diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
+index a66eb706aeb7..6f93f4752be4 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
++++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
+@@ -66,6 +66,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
+ 	  .keylength = 8,
+ 	  .blocksize = 8,
+ 	  .cksumlength = 8,
++	  .keyed_cksum = 0,
+ 	},
+ };
+ 
+diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
+index 46c6f44e5c3f..cd512719092b 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
+@@ -101,6 +101,7 @@ gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text,
+ 	void			*ptr;
+ 	s32			now;
+ 	u32			seq_send;
++	u8			*cksumkey;
+ 
+ 	dprintk("RPC:       %s\n", __func__);
+ 	BUG_ON(ctx == NULL);
+@@ -109,15 +110,15 @@ gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text,
+ 
+ 	ptr = setup_token(ctx, token);
+ 
+-	if (make_checksum((char *)ctx->gk5e->cksum_name, ptr, 8,
+-						text, 0, &md5cksum))
+-		return GSS_S_FAILURE;
++	if (ctx->gk5e->keyed_cksum)
++		cksumkey = ctx->cksum;
++	else
++		cksumkey = NULL;
+ 
+-	if (krb5_encrypt(ctx->seq, NULL, md5cksum.data,
+-			  md5cksum.data, md5cksum.len))
++	if (make_checksum(ctx, ptr, 8, text, 0, cksumkey, &md5cksum))
+ 		return GSS_S_FAILURE;
+ 
+-	memcpy(ptr + GSS_KRB5_TOK_HDR_LEN, md5cksum.data + md5cksum.len - 8, 8);
++	memcpy(ptr + GSS_KRB5_TOK_HDR_LEN, md5cksum.data, md5cksum.len);
+ 
+ 	spin_lock(&krb5_seq_lock);
+ 	seq_send = ctx->seq_send++;
+diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
+index 10ee641a39d0..7515bffddf15 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
+@@ -84,6 +84,7 @@ gss_verify_mic_v1(struct krb5_ctx *ctx,
+ 	u32			seqnum;
+ 	unsigned char		*ptr = (unsigned char *)read_token->data;
+ 	int			bodysize;
++	u8			*cksumkey;
+ 
+ 	dprintk("RPC:       krb5_read_token\n");
+ 
+@@ -108,14 +109,16 @@ gss_verify_mic_v1(struct krb5_ctx *ctx,
+ 	if ((ptr[6] != 0xff) || (ptr[7] != 0xff))
+ 		return GSS_S_DEFECTIVE_TOKEN;
+ 
+-	if (make_checksum((char *)ctx->gk5e->cksum_name, ptr, 8,
+-					message_buffer, 0, &md5cksum))
+-		return GSS_S_FAILURE;
++	if (ctx->gk5e->keyed_cksum)
++		cksumkey = ctx->cksum;
++	else
++		cksumkey = NULL;
+ 
+-	if (krb5_encrypt(ctx->seq, NULL, md5cksum.data, md5cksum.data, 16))
++	if (make_checksum(ctx, ptr, 8, message_buffer, 0,
++			  cksumkey, &md5cksum))
+ 		return GSS_S_FAILURE;
+ 
+-	if (memcmp(md5cksum.data + 8, ptr + GSS_KRB5_TOK_HDR_LEN,
++	if (memcmp(md5cksum.data, ptr + GSS_KRB5_TOK_HDR_LEN,
+ 					ctx->gk5e->cksumlength))
+ 		return GSS_S_BAD_SIG;
+ 
+diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+index 7188891bcc33..2eb3046a84ea 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
++++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+@@ -167,6 +167,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
+ 	int			headlen;
+ 	struct page		**tmp_pages;
+ 	u32			seq_send;
++	u8			*cksumkey;
+ 
+ 	dprintk("RPC:       %s\n", __func__);
+ 
+@@ -205,18 +206,20 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
+ 
+ 	make_confounder(msg_start, blocksize);
+ 
++	if (kctx->gk5e->keyed_cksum)
++		cksumkey = kctx->cksum;
++	else
++		cksumkey = NULL;
++
+ 	/* XXXJBF: UGH!: */
+ 	tmp_pages = buf->pages;
+ 	buf->pages = pages;
+-	if (make_checksum((char *)kctx->gk5e->cksum_name, ptr, 8, buf,
+-				offset + headlen - blocksize, &md5cksum))
++	if (make_checksum(kctx, ptr, 8, buf, offset + headlen - blocksize,
++					cksumkey, &md5cksum))
+ 		return GSS_S_FAILURE;
+ 	buf->pages = tmp_pages;
+ 
+-	if (krb5_encrypt(kctx->seq, NULL, md5cksum.data,
+-			  md5cksum.data, md5cksum.len))
+-		return GSS_S_FAILURE;
+-	memcpy(ptr + GSS_KRB5_TOK_HDR_LEN, md5cksum.data + md5cksum.len - 8, 8);
++	memcpy(ptr + GSS_KRB5_TOK_HDR_LEN, md5cksum.data, md5cksum.len);
+ 
+ 	spin_lock(&krb5_seq_lock);
+ 	seq_send = kctx->seq_send++;
+@@ -252,6 +255,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
+ 	int			data_len;
+ 	int			blocksize;
+ 	int			crypt_offset;
++	u8			*cksumkey;
+ 
+ 	dprintk("RPC:       gss_unwrap_kerberos\n");
+ 
+@@ -288,15 +292,17 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
+ 	if (gss_decrypt_xdr_buf(kctx->enc, buf, crypt_offset))
+ 		return GSS_S_DEFECTIVE_TOKEN;
+ 
+-	if (make_checksum((char *)kctx->gk5e->cksum_name, ptr, 8, buf,
+-						crypt_offset, &md5cksum))
+-		return GSS_S_FAILURE;
++	if (kctx->gk5e->keyed_cksum)
++		cksumkey = kctx->cksum;
++	else
++		cksumkey = NULL;
+ 
+-	if (krb5_encrypt(kctx->seq, NULL, md5cksum.data,
+-			   md5cksum.data, md5cksum.len))
++	if (make_checksum(kctx, ptr, 8, buf, crypt_offset,
++						cksumkey, &md5cksum))
+ 		return GSS_S_FAILURE;
+ 
+-	if (memcmp(md5cksum.data + 8, ptr + GSS_KRB5_TOK_HDR_LEN, 8))
++	if (memcmp(md5cksum.data, ptr + GSS_KRB5_TOK_HDR_LEN,
++						kctx->gk5e->cksumlength))
+ 		return GSS_S_BAD_SIG;
+ 
+ 	/* it got through unscathed.  Make sure the context is unexpired */

commit 81d4a4333a1dfd6070f046265d928bb4c79aff88
+Author: Kevin Coffman 
+Date:   Wed Mar 17 13:02:51 2010 -0400
+
+    gss_krb5: introduce encryption type framework
+    
+    Add enctype framework and change functions to use the generic
+    values from it rather than the values hard-coded for des.
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: Steve Dickson 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
+index 5378e455482c..f94935599d13 100644
+--- a/include/linux/sunrpc/gss_krb5.h
++++ b/include/linux/sunrpc/gss_krb5.h
+@@ -4,7 +4,7 @@
+  *  Adapted from MIT Kerberos 5-1.2.1 lib/include/krb5.h,
+  *  lib/gssapi/krb5/gssapiP_krb5.h, and others
+  *
+- *  Copyright (c) 2000 The Regents of the University of Michigan.
++ *  Copyright (c) 2000-2008 The Regents of the University of Michigan.
+  *  All rights reserved.
+  *
+  *  Andy Adamson   
+@@ -36,6 +36,7 @@
+  *
+  */
+ 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -46,9 +47,31 @@
+ /* Maximum blocksize for the supported crypto algorithms */
+ #define GSS_KRB5_MAX_BLOCKSIZE  (16)
+ 
++struct gss_krb5_enctype {
++	const u32		etype;		/* encryption (key) type */
++	const u32		ctype;		/* checksum type */
++	const char		*name;		/* "friendly" name */
++	const char		*encrypt_name;	/* crypto encrypt name */
++	const char		*cksum_name;	/* crypto checksum name */
++	const u16		signalg;	/* signing algorithm */
++	const u16		sealalg;	/* sealing algorithm */
++	const u32		blocksize;	/* encryption blocksize */
++	const u32		cksumlength;	/* checksum length */
++	const u32		keyed_cksum;	/* is it a keyed cksum? */
++	const u32		keybytes;	/* raw key len, in bytes */
++	const u32		keylength;	/* final key len, in bytes */
++	u32 (*encrypt) (struct crypto_blkcipher *tfm,
++			void *iv, void *in, void *out,
++			int length);		/* encryption function */
++	u32 (*decrypt) (struct crypto_blkcipher *tfm,
++			void *iv, void *in, void *out,
++			int length);		/* decryption function */
++};
++
+ struct krb5_ctx {
+ 	int			initiate; /* 1 = initiating, 0 = accepting */
+ 	u32			enctype;
++	const struct gss_krb5_enctype *gk5e; /* enctype-specific info */
+ 	struct crypto_blkcipher	*enc;
+ 	struct crypto_blkcipher	*seq;
+ 	s32			endtime;
+diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+index 746b3e139aed..ccd5236953f7 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
++++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+@@ -1,7 +1,7 @@
+ /*
+  *  linux/net/sunrpc/gss_krb5_crypto.c
+  *
+- *  Copyright (c) 2000 The Regents of the University of Michigan.
++ *  Copyright (c) 2000-2008 The Regents of the University of Michigan.
+  *  All rights reserved.
+  *
+  *  Andy Adamson   
+@@ -58,13 +58,13 @@ krb5_encrypt(
+ {
+ 	u32 ret = -EINVAL;
+ 	struct scatterlist sg[1];
+-	u8 local_iv[16] = {0};
++	u8 local_iv[GSS_KRB5_MAX_BLOCKSIZE] = {0};
+ 	struct blkcipher_desc desc = { .tfm = tfm, .info = local_iv };
+ 
+ 	if (length % crypto_blkcipher_blocksize(tfm) != 0)
+ 		goto out;
+ 
+-	if (crypto_blkcipher_ivsize(tfm) > 16) {
++	if (crypto_blkcipher_ivsize(tfm) > GSS_KRB5_MAX_BLOCKSIZE) {
+ 		dprintk("RPC:       gss_k5encrypt: tfm iv size too large %d\n",
+ 			crypto_blkcipher_ivsize(tfm));
+ 		goto out;
+@@ -92,13 +92,13 @@ krb5_decrypt(
+ {
+ 	u32 ret = -EINVAL;
+ 	struct scatterlist sg[1];
+-	u8 local_iv[16] = {0};
++	u8 local_iv[GSS_KRB5_MAX_BLOCKSIZE] = {0};
+ 	struct blkcipher_desc desc = { .tfm = tfm, .info = local_iv };
+ 
+ 	if (length % crypto_blkcipher_blocksize(tfm) != 0)
+ 		goto out;
+ 
+-	if (crypto_blkcipher_ivsize(tfm) > 16) {
++	if (crypto_blkcipher_ivsize(tfm) > GSS_KRB5_MAX_BLOCKSIZE) {
+ 		dprintk("RPC:       gss_k5decrypt: tfm iv size too large %d\n",
+ 			crypto_blkcipher_ivsize(tfm));
+ 		goto out;
+@@ -157,7 +157,7 @@ make_checksum(char *cksumname, char *header, int hdrlen, struct xdr_buf *body,
+ }
+ 
+ struct encryptor_desc {
+-	u8 iv[8]; /* XXX hard-coded blocksize */
++	u8 iv[GSS_KRB5_MAX_BLOCKSIZE];
+ 	struct blkcipher_desc desc;
+ 	int pos;
+ 	struct xdr_buf *outbuf;
+@@ -198,7 +198,7 @@ encryptor(struct scatterlist *sg, void *data)
+ 	desc->fraglen += sg->length;
+ 	desc->pos += sg->length;
+ 
+-	fraglen = thislen & 7; /* XXX hardcoded blocksize */
++	fraglen = thislen & (crypto_blkcipher_blocksize(desc->desc.tfm) - 1);
+ 	thislen -= fraglen;
+ 
+ 	if (thislen == 0)
+@@ -256,7 +256,7 @@ gss_encrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *buf,
+ }
+ 
+ struct decryptor_desc {
+-	u8 iv[8]; /* XXX hard-coded blocksize */
++	u8 iv[GSS_KRB5_MAX_BLOCKSIZE];
+ 	struct blkcipher_desc desc;
+ 	struct scatterlist frags[4];
+ 	int fragno;
+@@ -278,7 +278,7 @@ decryptor(struct scatterlist *sg, void *data)
+ 	desc->fragno++;
+ 	desc->fraglen += sg->length;
+ 
+-	fraglen = thislen & 7; /* XXX hardcoded blocksize */
++	fraglen = thislen & (crypto_blkcipher_blocksize(desc->desc.tfm) - 1);
+ 	thislen -= fraglen;
+ 
+ 	if (thislen == 0)
+diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
+index afe09108e1b0..a66eb706aeb7 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
++++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
+@@ -1,7 +1,7 @@
+ /*
+  *  linux/net/sunrpc/gss_krb5_mech.c
+  *
+- *  Copyright (c) 2001 The Regents of the University of Michigan.
++ *  Copyright (c) 2001-2008 The Regents of the University of Michigan.
+  *  All rights reserved.
+  *
+  *  Andy Adamson 
+@@ -48,6 +48,50 @@
+ # define RPCDBG_FACILITY	RPCDBG_AUTH
+ #endif
+ 
++static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
++	/*
++	 * DES (All DES enctypes are mapped to the same gss functionality)
++	 */
++	{
++	  .etype = ENCTYPE_DES_CBC_RAW,
++	  .ctype = CKSUMTYPE_RSA_MD5,
++	  .name = "des-cbc-crc",
++	  .encrypt_name = "cbc(des)",
++	  .cksum_name = "md5",
++	  .encrypt = krb5_encrypt,
++	  .decrypt = krb5_decrypt,
++	  .signalg = SGN_ALG_DES_MAC_MD5,
++	  .sealalg = SEAL_ALG_DES,
++	  .keybytes = 7,
++	  .keylength = 8,
++	  .blocksize = 8,
++	  .cksumlength = 8,
++	},
++};
++
++static const int num_supported_enctypes =
++	ARRAY_SIZE(supported_gss_krb5_enctypes);
++
++static int
++supported_gss_krb5_enctype(int etype)
++{
++	int i;
++	for (i = 0; i < num_supported_enctypes; i++)
++		if (supported_gss_krb5_enctypes[i].etype == etype)
++			return 1;
++	return 0;
++}
++
++static const struct gss_krb5_enctype *
++get_gss_krb5_enctype(int etype)
++{
++	int i;
++	for (i = 0; i < num_supported_enctypes; i++)
++		if (supported_gss_krb5_enctypes[i].etype == etype)
++			return &supported_gss_krb5_enctypes[i];
++	return NULL;
++}
++
+ static const void *
+ simple_get_bytes(const void *p, const void *end, void *res, int len)
+ {
+@@ -78,35 +122,45 @@ simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res)
+ }
+ 
+ static inline const void *
+-get_key(const void *p, const void *end, struct crypto_blkcipher **res)
++get_key(const void *p, const void *end,
++	struct krb5_ctx *ctx, struct crypto_blkcipher **res)
+ {
+ 	struct xdr_netobj	key;
+ 	int			alg;
+-	char			*alg_name;
+ 
+ 	p = simple_get_bytes(p, end, &alg, sizeof(alg));
+ 	if (IS_ERR(p))
+ 		goto out_err;
++
++	switch (alg) {
++	case ENCTYPE_DES_CBC_CRC:
++	case ENCTYPE_DES_CBC_MD4:
++	case ENCTYPE_DES_CBC_MD5:
++		/* Map all these key types to ENCTYPE_DES_CBC_RAW */
++		alg = ENCTYPE_DES_CBC_RAW;
++		break;
++	}
++
++	if (!supported_gss_krb5_enctype(alg)) {
++		printk(KERN_WARNING "gss_kerberos_mech: unsupported "
++			"encryption key algorithm %d\n", alg);
++		goto out_err;
++	}
+ 	p = simple_get_netobj(p, end, &key);
+ 	if (IS_ERR(p))
+ 		goto out_err;
+ 
+-	switch (alg) {
+-		case ENCTYPE_DES_CBC_RAW:
+-			alg_name = "cbc(des)";
+-			break;
+-		default:
+-			printk("gss_kerberos_mech: unsupported algorithm %d\n", alg);
+-			goto out_err_free_key;
+-	}
+-	*res = crypto_alloc_blkcipher(alg_name, 0, CRYPTO_ALG_ASYNC);
++	*res = crypto_alloc_blkcipher(ctx->gk5e->encrypt_name, 0,
++							CRYPTO_ALG_ASYNC);
+ 	if (IS_ERR(*res)) {
+-		printk("gss_kerberos_mech: unable to initialize crypto algorithm %s\n", alg_name);
++		printk(KERN_WARNING "gss_kerberos_mech: unable to initialize "
++			"crypto algorithm %s\n", ctx->gk5e->encrypt_name);
+ 		*res = NULL;
+ 		goto out_err_free_key;
+ 	}
+ 	if (crypto_blkcipher_setkey(*res, key.data, key.len)) {
+-		printk("gss_kerberos_mech: error setting key for crypto algorithm %s\n", alg_name);
++		printk(KERN_WARNING "gss_kerberos_mech: error setting key for "
++			"crypto algorithm %s\n", ctx->gk5e->encrypt_name);
+ 		goto out_err_free_tfm;
+ 	}
+ 
+@@ -134,6 +188,10 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx)
+ 	/* Old format supports only DES!  Any other enctype uses new format */
+ 	ctx->enctype = ENCTYPE_DES_CBC_RAW;
+ 
++	ctx->gk5e = get_gss_krb5_enctype(ctx->enctype);
++	if (ctx->gk5e == NULL)
++		goto out_err;
++
+ 	/* The downcall format was designed before we completely understood
+ 	 * the uses of the context fields; so it includes some stuff we
+ 	 * just give some minimal sanity-checking, and some we ignore
+@@ -164,10 +222,10 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx)
+ 	p = simple_get_netobj(p, end, &ctx->mech_used);
+ 	if (IS_ERR(p))
+ 		goto out_err;
+-	p = get_key(p, end, &ctx->enc);
++	p = get_key(p, end, ctx, &ctx->enc);
+ 	if (IS_ERR(p))
+ 		goto out_err_free_mech;
+-	p = get_key(p, end, &ctx->seq);
++	p = get_key(p, end, ctx, &ctx->seq);
+ 	if (IS_ERR(p))
+ 		goto out_err_free_key1;
+ 	if (p != end) {
+diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
+index 71c2014e7ebf..46c6f44e5c3f 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
+@@ -3,7 +3,7 @@
+  *
+  *  Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/krb5/k5seal.c
+  *
+- *  Copyright (c) 2000 The Regents of the University of Michigan.
++ *  Copyright (c) 2000-2008 The Regents of the University of Michigan.
+  *  All rights reserved.
+  *
+  *  Andy Adamson	
+@@ -70,36 +70,47 @@
+ 
+ DEFINE_SPINLOCK(krb5_seq_lock);
+ 
++static char *
++setup_token(struct krb5_ctx *ctx, struct xdr_netobj *token)
++{
++	__be16 *ptr, *krb5_hdr;
++	int body_size = GSS_KRB5_TOK_HDR_LEN + ctx->gk5e->cksumlength;
++
++	token->len = g_token_size(&ctx->mech_used, body_size);
++
++	ptr = (__be16 *)token->data;
++	g_make_token_header(&ctx->mech_used, body_size, (unsigned char **)&ptr);
++
++	/* ptr now at start of header described in rfc 1964, section 1.2.1: */
++	krb5_hdr = ptr;
++	*ptr++ = KG_TOK_MIC_MSG;
++	*ptr++ = cpu_to_le16(ctx->gk5e->signalg);
++	*ptr++ = SEAL_ALG_NONE;
++	*ptr++ = 0xffff;
++
++	return (char *)krb5_hdr;
++}
++
+ static u32
+ gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text,
+ 		struct xdr_netobj *token)
+ {
+-	char			cksumdata[16];
+-	struct xdr_netobj	md5cksum = {.len = 0, .data = cksumdata};
+-	unsigned char		*ptr, *msg_start;
++	char			cksumdata[GSS_KRB5_MAX_CKSUM_LEN];
++	struct xdr_netobj	md5cksum = {.len = sizeof(cksumdata),
++					    .data = cksumdata};
++	void			*ptr;
+ 	s32			now;
+ 	u32			seq_send;
+ 
+-	dprintk("RPC:       gss_krb5_seal\n");
++	dprintk("RPC:       %s\n", __func__);
+ 	BUG_ON(ctx == NULL);
+ 
+ 	now = get_seconds();
+ 
+-	token->len = g_token_size(&ctx->mech_used, GSS_KRB5_TOK_HDR_LEN + 8);
+-
+-	ptr = token->data;
+-	g_make_token_header(&ctx->mech_used, GSS_KRB5_TOK_HDR_LEN + 8, &ptr);
+-
+-	/* ptr now at header described in rfc 1964, section 1.2.1: */
+-	ptr[0] = (unsigned char) ((KG_TOK_MIC_MSG >> 8) & 0xff);
+-	ptr[1] = (unsigned char) (KG_TOK_MIC_MSG & 0xff);
+-
+-	msg_start = ptr + GSS_KRB5_TOK_HDR_LEN + 8;
+-
+-	*(__be16 *)(ptr + 2) = htons(SGN_ALG_DES_MAC_MD5);
+-	memset(ptr + 4, 0xff, 4);
++	ptr = setup_token(ctx, token);
+ 
+-	if (make_checksum("md5", ptr, 8, text, 0, &md5cksum))
++	if (make_checksum((char *)ctx->gk5e->cksum_name, ptr, 8,
++						text, 0, &md5cksum))
+ 		return GSS_S_FAILURE;
+ 
+ 	if (krb5_encrypt(ctx->seq, NULL, md5cksum.data,
+diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
+index 069d4b59807a..10ee641a39d0 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
+@@ -3,7 +3,7 @@
+  *
+  *  Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/krb5/k5unseal.c
+  *
+- *  Copyright (c) 2000 The Regents of the University of Michigan.
++ *  Copyright (c) 2000-2008 The Regents of the University of Michigan.
+  *  All rights reserved.
+  *
+  *  Andy Adamson   
+@@ -76,8 +76,9 @@ gss_verify_mic_v1(struct krb5_ctx *ctx,
+ {
+ 	int			signalg;
+ 	int			sealalg;
+-	char			cksumdata[16];
+-	struct xdr_netobj	md5cksum = {.len = 0, .data = cksumdata};
++	char			cksumdata[GSS_KRB5_MAX_CKSUM_LEN];
++	struct xdr_netobj	md5cksum = {.len = sizeof(cksumdata),
++					    .data = cksumdata};
+ 	s32			now;
+ 	int			direction;
+ 	u32			seqnum;
+@@ -97,7 +98,7 @@ gss_verify_mic_v1(struct krb5_ctx *ctx,
+ 	/* XXX sanity-check bodysize?? */
+ 
+ 	signalg = ptr[2] + (ptr[3] << 8);
+-	if (signalg != SGN_ALG_DES_MAC_MD5)
++	if (signalg != ctx->gk5e->signalg)
+ 		return GSS_S_DEFECTIVE_TOKEN;
+ 
+ 	sealalg = ptr[4] + (ptr[5] << 8);
+@@ -107,13 +108,15 @@ gss_verify_mic_v1(struct krb5_ctx *ctx,
+ 	if ((ptr[6] != 0xff) || (ptr[7] != 0xff))
+ 		return GSS_S_DEFECTIVE_TOKEN;
+ 
+-	if (make_checksum("md5", ptr, 8, message_buffer, 0, &md5cksum))
++	if (make_checksum((char *)ctx->gk5e->cksum_name, ptr, 8,
++					message_buffer, 0, &md5cksum))
+ 		return GSS_S_FAILURE;
+ 
+ 	if (krb5_encrypt(ctx->seq, NULL, md5cksum.data, md5cksum.data, 16))
+ 		return GSS_S_FAILURE;
+ 
+-	if (memcmp(md5cksum.data + 8, ptr + GSS_KRB5_TOK_HDR_LEN, 8))
++	if (memcmp(md5cksum.data + 8, ptr + GSS_KRB5_TOK_HDR_LEN,
++					ctx->gk5e->cksumlength))
+ 		return GSS_S_BAD_SIG;
+ 
+ 	/* it got through unscathed.  Make sure the context is unexpired */
+diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+index b45b59b17ae1..7188891bcc33 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
++++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+@@ -1,3 +1,33 @@
++/*
++ * COPYRIGHT (c) 2008
++ * The Regents of the University of Michigan
++ * ALL RIGHTS RESERVED
++ *
++ * Permission is granted to use, copy, create derivative works
++ * and redistribute this software and such derivative works
++ * for any purpose, so long as the name of The University of
++ * Michigan is not used in any advertising or publicity
++ * pertaining to the use of distribution of this software
++ * without specific, written prior authorization.  If the
++ * above copyright notice or any other identification of the
++ * University of Michigan is included in any copy of any
++ * portion of this software, then the disclaimer below must
++ * also be included.
++ *
++ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
++ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
++ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
++ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
++ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
++ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
++ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
++ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
++ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
++ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGES.
++ */
++
+ #include 
+ #include 
+ #include 
+@@ -128,8 +158,9 @@ static u32
+ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
+ 		struct xdr_buf *buf, struct page **pages)
+ {
+-	char			cksumdata[16];
+-	struct xdr_netobj	md5cksum = {.len = 0, .data = cksumdata};
++	char			cksumdata[GSS_KRB5_MAX_CKSUM_LEN];
++	struct xdr_netobj	md5cksum = {.len = sizeof(cksumdata),
++					    .data = cksumdata};
+ 	int			blocksize = 0, plainlen;
+ 	unsigned char		*ptr, *msg_start;
+ 	s32			now;
+@@ -137,7 +168,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
+ 	struct page		**tmp_pages;
+ 	u32			seq_send;
+ 
+-	dprintk("RPC:       gss_wrap_kerberos\n");
++	dprintk("RPC:       %s\n", __func__);
+ 
+ 	now = get_seconds();
+ 
+@@ -146,8 +177,9 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
+ 	BUG_ON((buf->len - offset) % blocksize);
+ 	plainlen = blocksize + buf->len - offset;
+ 
+-	headlen = g_token_size(&kctx->mech_used, 24 + plainlen) -
+-						(buf->len - offset);
++	headlen = g_token_size(&kctx->mech_used,
++		GSS_KRB5_TOK_HDR_LEN + kctx->gk5e->cksumlength + plainlen) -
++		(buf->len - offset);
+ 
+ 	ptr = buf->head[0].iov_base + offset;
+ 	/* shift data to make room for header. */
+@@ -157,25 +189,26 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
+ 	BUG_ON((buf->len - offset - headlen) % blocksize);
+ 
+ 	g_make_token_header(&kctx->mech_used,
+-				GSS_KRB5_TOK_HDR_LEN + 8 + plainlen, &ptr);
++				GSS_KRB5_TOK_HDR_LEN +
++				kctx->gk5e->cksumlength + plainlen, &ptr);
+ 
+ 
+ 	/* ptr now at header described in rfc 1964, section 1.2.1: */
+ 	ptr[0] = (unsigned char) ((KG_TOK_WRAP_MSG >> 8) & 0xff);
+ 	ptr[1] = (unsigned char) (KG_TOK_WRAP_MSG & 0xff);
+ 
+-	msg_start = ptr + 24;
++	msg_start = ptr + GSS_KRB5_TOK_HDR_LEN + kctx->gk5e->cksumlength;
+ 
+-	*(__be16 *)(ptr + 2) = htons(SGN_ALG_DES_MAC_MD5);
++	*(__be16 *)(ptr + 2) = cpu_to_le16(kctx->gk5e->signalg);
+ 	memset(ptr + 4, 0xff, 4);
+-	*(__be16 *)(ptr + 4) = htons(SEAL_ALG_DES);
++	*(__be16 *)(ptr + 4) = cpu_to_le16(kctx->gk5e->sealalg);
+ 
+ 	make_confounder(msg_start, blocksize);
+ 
+ 	/* XXXJBF: UGH!: */
+ 	tmp_pages = buf->pages;
+ 	buf->pages = pages;
+-	if (make_checksum("md5", ptr, 8, buf,
++	if (make_checksum((char *)kctx->gk5e->cksum_name, ptr, 8, buf,
+ 				offset + headlen - blocksize, &md5cksum))
+ 		return GSS_S_FAILURE;
+ 	buf->pages = tmp_pages;
+@@ -207,8 +240,9 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
+ {
+ 	int			signalg;
+ 	int			sealalg;
+-	char			cksumdata[16];
+-	struct xdr_netobj	md5cksum = {.len = 0, .data = cksumdata};
++	char			cksumdata[GSS_KRB5_MAX_CKSUM_LEN];
++	struct xdr_netobj	md5cksum = {.len = sizeof(cksumdata),
++					    .data = cksumdata};
+ 	s32			now;
+ 	int			direction;
+ 	s32			seqnum;
+@@ -217,6 +251,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
+ 	void			*data_start, *orig_start;
+ 	int			data_len;
+ 	int			blocksize;
++	int			crypt_offset;
+ 
+ 	dprintk("RPC:       gss_unwrap_kerberos\n");
+ 
+@@ -234,22 +269,27 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
+ 	/* get the sign and seal algorithms */
+ 
+ 	signalg = ptr[2] + (ptr[3] << 8);
+-	if (signalg != SGN_ALG_DES_MAC_MD5)
++	if (signalg != kctx->gk5e->signalg)
+ 		return GSS_S_DEFECTIVE_TOKEN;
+ 
+ 	sealalg = ptr[4] + (ptr[5] << 8);
+-	if (sealalg != SEAL_ALG_DES)
++	if (sealalg != kctx->gk5e->sealalg)
+ 		return GSS_S_DEFECTIVE_TOKEN;
+ 
+ 	if ((ptr[6] != 0xff) || (ptr[7] != 0xff))
+ 		return GSS_S_DEFECTIVE_TOKEN;
+ 
+-	if (gss_decrypt_xdr_buf(kctx->enc, buf,
+-			ptr + GSS_KRB5_TOK_HDR_LEN + 8 - (unsigned char *)buf->head[0].iov_base))
++	/*
++	 * Data starts after token header and checksum.  ptr points
++	 * to the beginning of the token header
++	 */
++	crypt_offset = ptr + (GSS_KRB5_TOK_HDR_LEN + kctx->gk5e->cksumlength) -
++					(unsigned char *)buf->head[0].iov_base;
++	if (gss_decrypt_xdr_buf(kctx->enc, buf, crypt_offset))
+ 		return GSS_S_DEFECTIVE_TOKEN;
+ 
+-	if (make_checksum("md5", ptr, 8, buf,
+-		 ptr + GSS_KRB5_TOK_HDR_LEN + 8 - (unsigned char *)buf->head[0].iov_base, &md5cksum))
++	if (make_checksum((char *)kctx->gk5e->cksum_name, ptr, 8, buf,
++						crypt_offset, &md5cksum))
+ 		return GSS_S_FAILURE;
+ 
+ 	if (krb5_encrypt(kctx->seq, NULL, md5cksum.data,
+@@ -280,7 +320,8 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
+ 	 * better to copy and encrypt at the same time. */
+ 
+ 	blocksize = crypto_blkcipher_blocksize(kctx->enc);
+-	data_start = ptr + GSS_KRB5_TOK_HDR_LEN + 8 + blocksize;
++	data_start = ptr + (GSS_KRB5_TOK_HDR_LEN + kctx->gk5e->cksumlength) +
++					blocksize;
+ 	orig_start = buf->head[0].iov_base + offset;
+ 	data_len = (buf->head[0].iov_base + buf->head[0].iov_len) - data_start;
+ 	memmove(orig_start, data_start, data_len);

commit a8cc1cb7d7a12b0e2855832d10cfbfaffebfad6c
+Author: Kevin Coffman 
+Date:   Wed Mar 17 13:02:50 2010 -0400
+
+    gss_krb5: prepare for new context format
+    
+    Prepare for new context format by splitting out the old "v1"
+    context processing function
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: Steve Dickson 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
+index 0cd940e897ed..afe09108e1b0 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
++++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
+@@ -123,53 +123,47 @@ get_key(const void *p, const void *end, struct crypto_blkcipher **res)
+ }
+ 
+ static int
+-gss_import_sec_context_kerberos(const void *p,
+-				size_t len,
+-				struct gss_ctx *ctx_id)
++gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx)
+ {
+-	const void *end = (const void *)((const char *)p + len);
+-	struct	krb5_ctx *ctx;
+ 	int tmp;
+ 
+-	if (!(ctx = kzalloc(sizeof(*ctx), GFP_NOFS))) {
+-		p = ERR_PTR(-ENOMEM);
+-		goto out_err;
+-	}
+-
+ 	p = simple_get_bytes(p, end, &ctx->initiate, sizeof(ctx->initiate));
+ 	if (IS_ERR(p))
+-		goto out_err_free_ctx;
++		goto out_err;
++
++	/* Old format supports only DES!  Any other enctype uses new format */
+ 	ctx->enctype = ENCTYPE_DES_CBC_RAW;
++
+ 	/* The downcall format was designed before we completely understood
+ 	 * the uses of the context fields; so it includes some stuff we
+ 	 * just give some minimal sanity-checking, and some we ignore
+ 	 * completely (like the next twenty bytes): */
+ 	if (unlikely(p + 20 > end || p + 20 < p))
+-		goto out_err_free_ctx;
++		goto out_err;
+ 	p += 20;
+ 	p = simple_get_bytes(p, end, &tmp, sizeof(tmp));
+ 	if (IS_ERR(p))
+-		goto out_err_free_ctx;
++		goto out_err;
+ 	if (tmp != SGN_ALG_DES_MAC_MD5) {
+ 		p = ERR_PTR(-ENOSYS);
+-		goto out_err_free_ctx;
++		goto out_err;
+ 	}
+ 	p = simple_get_bytes(p, end, &tmp, sizeof(tmp));
+ 	if (IS_ERR(p))
+-		goto out_err_free_ctx;
++		goto out_err;
+ 	if (tmp != SEAL_ALG_DES) {
+ 		p = ERR_PTR(-ENOSYS);
+-		goto out_err_free_ctx;
++		goto out_err;
+ 	}
+ 	p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime));
+ 	if (IS_ERR(p))
+-		goto out_err_free_ctx;
++		goto out_err;
+ 	p = simple_get_bytes(p, end, &ctx->seq_send, sizeof(ctx->seq_send));
+ 	if (IS_ERR(p))
+-		goto out_err_free_ctx;
++		goto out_err;
+ 	p = simple_get_netobj(p, end, &ctx->mech_used);
+ 	if (IS_ERR(p))
+-		goto out_err_free_ctx;
++		goto out_err;
+ 	p = get_key(p, end, &ctx->enc);
+ 	if (IS_ERR(p))
+ 		goto out_err_free_mech;
+@@ -181,9 +175,6 @@ gss_import_sec_context_kerberos(const void *p,
+ 		goto out_err_free_key2;
+ 	}
+ 
+-	ctx_id->internal_ctx_id = ctx;
+-
+-	dprintk("RPC:       Successfully imported new context.\n");
+ 	return 0;
+ 
+ out_err_free_key2:
+@@ -192,12 +183,36 @@ gss_import_sec_context_kerberos(const void *p,
+ 	crypto_free_blkcipher(ctx->enc);
+ out_err_free_mech:
+ 	kfree(ctx->mech_used.data);
+-out_err_free_ctx:
+-	kfree(ctx);
+ out_err:
+ 	return PTR_ERR(p);
+ }
+ 
++static int
++gss_import_sec_context_kerberos(const void *p, size_t len,
++				struct gss_ctx *ctx_id)
++{
++	const void *end = (const void *)((const char *)p + len);
++	struct  krb5_ctx *ctx;
++	int ret;
++
++	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
++	if (ctx == NULL)
++		return -ENOMEM;
++
++	if (len == 85)
++		ret = gss_import_v1_context(p, end, ctx);
++	else
++		ret = -EINVAL;
++
++	if (ret == 0)
++		ctx_id->internal_ctx_id = ctx;
++	else
++		kfree(ctx);
++
++	dprintk("RPC:       %s: returning %d\n", __func__, ret);
++	return ret;
++}
++
+ static void
+ gss_delete_sec_context_kerberos(void *internal_ctx) {
+ 	struct krb5_ctx *kctx = internal_ctx;

commit 1ac3719a2214c545c7e19d34e272a148ca9a24f1
+Author: Kevin Coffman 
+Date:   Wed Mar 17 13:02:49 2010 -0400
+
+    gss_krb5: split up functions in preparation of adding new enctypes
+    
+    Add encryption type to the krb5 context structure and use it to switch
+    to the correct functions depending on the encryption type.
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: Steve Dickson 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
+index 31bb8a538bf1..5378e455482c 100644
+--- a/include/linux/sunrpc/gss_krb5.h
++++ b/include/linux/sunrpc/gss_krb5.h
+@@ -48,6 +48,7 @@
+ 
+ struct krb5_ctx {
+ 	int			initiate; /* 1 = initiating, 0 = accepting */
++	u32			enctype;
+ 	struct crypto_blkcipher	*enc;
+ 	struct crypto_blkcipher	*seq;
+ 	s32			endtime;
+diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
+index 2deb0ed72ff4..0cd940e897ed 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
++++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
+@@ -139,6 +139,7 @@ gss_import_sec_context_kerberos(const void *p,
+ 	p = simple_get_bytes(p, end, &ctx->initiate, sizeof(ctx->initiate));
+ 	if (IS_ERR(p))
+ 		goto out_err_free_ctx;
++	ctx->enctype = ENCTYPE_DES_CBC_RAW;
+ 	/* The downcall format was designed before we completely understood
+ 	 * the uses of the context fields; so it includes some stuff we
+ 	 * just give some minimal sanity-checking, and some we ignore
+diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
+index 88fe6e75ed7e..71c2014e7ebf 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
+@@ -70,11 +70,10 @@
+ 
+ DEFINE_SPINLOCK(krb5_seq_lock);
+ 
+-u32
+-gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
++static u32
++gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text,
+ 		struct xdr_netobj *token)
+ {
+-	struct krb5_ctx		*ctx = gss_ctx->internal_ctx_id;
+ 	char			cksumdata[16];
+ 	struct xdr_netobj	md5cksum = {.len = 0, .data = cksumdata};
+ 	unsigned char		*ptr, *msg_start;
+@@ -120,3 +119,18 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
+ 
+ 	return (ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE;
+ }
++
++u32
++gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
++		     struct xdr_netobj *token)
++{
++	struct krb5_ctx		*ctx = gss_ctx->internal_ctx_id;
++
++	switch (ctx->enctype) {
++	default:
++		BUG();
++	case ENCTYPE_DES_CBC_RAW:
++		return gss_get_mic_v1(ctx, text, token);
++	}
++}
++
+diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
+index ce6c247edad0..069d4b59807a 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
+@@ -70,11 +70,10 @@
+ /* read_token is a mic token, and message_buffer is the data that the mic was
+  * supposedly taken over. */
+ 
+-u32
+-gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
++static u32
++gss_verify_mic_v1(struct krb5_ctx *ctx,
+ 		struct xdr_buf *message_buffer, struct xdr_netobj *read_token)
+ {
+-	struct krb5_ctx		*ctx = gss_ctx->internal_ctx_id;
+ 	int			signalg;
+ 	int			sealalg;
+ 	char			cksumdata[16];
+@@ -135,3 +134,19 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
+ 
+ 	return GSS_S_COMPLETE;
+ }
++
++u32
++gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
++			struct xdr_buf *message_buffer,
++			struct xdr_netobj *read_token)
++{
++	struct krb5_ctx *ctx = gss_ctx->internal_ctx_id;
++
++	switch (ctx->enctype) {
++	default:
++		BUG();
++	case ENCTYPE_DES_CBC_RAW:
++		return gss_verify_mic_v1(ctx, message_buffer, read_token);
++	}
++}
++
+diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+index 5d6c3b12ea70..b45b59b17ae1 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
++++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+@@ -124,11 +124,10 @@ make_confounder(char *p, u32 conflen)
+ 
+ /* XXX factor out common code with seal/unseal. */
+ 
+-u32
+-gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
++static u32
++gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
+ 		struct xdr_buf *buf, struct page **pages)
+ {
+-	struct krb5_ctx		*kctx = ctx->internal_ctx_id;
+ 	char			cksumdata[16];
+ 	struct xdr_netobj	md5cksum = {.len = 0, .data = cksumdata};
+ 	int			blocksize = 0, plainlen;
+@@ -203,10 +202,9 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
+ 	return (kctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE;
+ }
+ 
+-u32
+-gss_unwrap_kerberos(struct gss_ctx *ctx, int offset, struct xdr_buf *buf)
++static u32
++gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
+ {
+-	struct krb5_ctx		*kctx = ctx->internal_ctx_id;
+ 	int			signalg;
+ 	int			sealalg;
+ 	char			cksumdata[16];
+@@ -294,3 +292,31 @@ gss_unwrap_kerberos(struct gss_ctx *ctx, int offset, struct xdr_buf *buf)
+ 
+ 	return GSS_S_COMPLETE;
+ }
++
++u32
++gss_wrap_kerberos(struct gss_ctx *gctx, int offset,
++		  struct xdr_buf *buf, struct page **pages)
++{
++	struct krb5_ctx	*kctx = gctx->internal_ctx_id;
++
++	switch (kctx->enctype) {
++	default:
++		BUG();
++	case ENCTYPE_DES_CBC_RAW:
++		return gss_wrap_kerberos_v1(kctx, offset, buf, pages);
++	}
++}
++
++u32
++gss_unwrap_kerberos(struct gss_ctx *gctx, int offset, struct xdr_buf *buf)
++{
++	struct krb5_ctx	*kctx = gctx->internal_ctx_id;
++
++	switch (kctx->enctype) {
++	default:
++		BUG();
++	case ENCTYPE_DES_CBC_RAW:
++		return gss_unwrap_kerberos_v1(kctx, offset, buf);
++	}
++}
++

commit 54ec3d462f3c2a3fe48a7bd592160bee31360087
+Author: J. Bruce Fields 
+Date:   Wed Mar 17 13:02:48 2010 -0400
+
+    gss_krb5: Don't expect blocksize to always be 8 when calculating padding
+    
+    Signed-off-by: Steve Dickson 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+index 496281fabb91..5d6c3b12ea70 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
++++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+@@ -12,10 +12,7 @@
+ static inline int
+ gss_krb5_padding(int blocksize, int length)
+ {
+-	/* Most of the code is block-size independent but currently we
+-	 * use only 8: */
+-	BUG_ON(blocksize != 8);
+-	return 8 - (length & 7);
++	return blocksize - (length % blocksize);
+ }
+ 
+ static inline void

commit 7561042fb7870be0b4ee57efddce68bda8968abf
+Author: Kevin Coffman 
+Date:   Wed Mar 17 13:02:47 2010 -0400
+
+    gss_krb5: Added and improved code comments
+    
+    Signed-off-by: Steve Dickson 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index 75602ece58eb..d64a58b8ed33 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -1316,15 +1316,21 @@ gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
+ 	inpages = snd_buf->pages + first;
+ 	snd_buf->pages = rqstp->rq_enc_pages;
+ 	snd_buf->page_base -= first << PAGE_CACHE_SHIFT;
+-	/* Give the tail its own page, in case we need extra space in the
+-	 * head when wrapping: */
++	/*
++	 * Give the tail its own page, in case we need extra space in the
++	 * head when wrapping:
++	 *
++	 * call_allocate() allocates twice the slack space required
++	 * by the authentication flavor to rq_callsize.
++	 * For GSS, slack is GSS_CRED_SLACK.
++	 */
+ 	if (snd_buf->page_len || snd_buf->tail[0].iov_len) {
+ 		tmp = page_address(rqstp->rq_enc_pages[rqstp->rq_enc_pages_num - 1]);
+ 		memcpy(tmp, snd_buf->tail[0].iov_base, snd_buf->tail[0].iov_len);
+ 		snd_buf->tail[0].iov_base = tmp;
+ 	}
+ 	maj_stat = gss_wrap(ctx->gc_gss_ctx, offset, snd_buf, inpages);
+-	/* RPC_SLACK_SPACE should prevent this ever happening: */
++	/* slack space should prevent this ever happening: */
+ 	BUG_ON(snd_buf->len > snd_buf->buflen);
+ 	status = -EIO;
+ 	/* We're assuming that when GSS_S_CONTEXT_EXPIRED, the encryption was
+diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
+index 76e4c6f4ac3c..28a84ef41d13 100644
+--- a/net/sunrpc/auth_gss/gss_mech_switch.c
++++ b/net/sunrpc/auth_gss/gss_mech_switch.c
+@@ -285,6 +285,20 @@ gss_verify_mic(struct gss_ctx		*context_handle,
+ 				 mic_token);
+ }
+ 
++/*
++ * This function is called from both the client and server code.
++ * Each makes guarantees about how much "slack" space is available
++ * for the underlying function in "buf"'s head and tail while
++ * performing the wrap.
++ *
++ * The client and server code allocate RPC_MAX_AUTH_SIZE extra
++ * space in both the head and tail which is available for use by
++ * the wrap function.
++ *
++ * Underlying functions should verify they do not use more than
++ * RPC_MAX_AUTH_SIZE of extra space in either the head or tail
++ * when performing the wrap.
++ */
+ u32
+ gss_wrap(struct gss_ctx	*ctx_id,
+ 	 int		offset,
+diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
+index b81e790ef9f4..1d9ac4ac818a 100644
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -1315,6 +1315,14 @@ svcauth_gss_wrap_resp_priv(struct svc_rqst *rqstp)
+ 	inpages = resbuf->pages;
+ 	/* XXX: Would be better to write some xdr helper functions for
+ 	 * nfs{2,3,4}xdr.c that place the data right, instead of copying: */
++
++	/*
++	 * If there is currently tail data, make sure there is
++	 * room for the head, tail, and 2 * RPC_MAX_AUTH_SIZE in
++	 * the page, and move the current tail data such that
++	 * there is RPC_MAX_AUTH_SIZE slack space available in
++	 * both the head and tail.
++	 */
+ 	if (resbuf->tail[0].iov_base) {
+ 		BUG_ON(resbuf->tail[0].iov_base >= resbuf->head[0].iov_base
+ 							+ PAGE_SIZE);
+@@ -1327,6 +1335,13 @@ svcauth_gss_wrap_resp_priv(struct svc_rqst *rqstp)
+ 			resbuf->tail[0].iov_len);
+ 		resbuf->tail[0].iov_base += RPC_MAX_AUTH_SIZE;
+ 	}
++	/*
++	 * If there is no current tail data, make sure there is
++	 * room for the head data, and 2 * RPC_MAX_AUTH_SIZE in the
++	 * allotted page, and set up tail information such that there
++	 * is RPC_MAX_AUTH_SIZE slack space available in both the
++	 * head and tail.
++	 */
+ 	if (resbuf->tail[0].iov_base == NULL) {
+ 		if (resbuf->head[0].iov_len + 2*RPC_MAX_AUTH_SIZE > PAGE_SIZE)
+ 			return -ENOMEM;

commit 725f2865d4df31ac0768b13ae763beadc4bb8ce9
+Author: Kevin Coffman 
+Date:   Wed Mar 17 13:02:46 2010 -0400
+
+    gss_krb5: Introduce encryption type framework
+    
+    Make the client and server code consistent regarding the extra buffer
+    space made available for the auth code when wrapping data.
+    
+    Add some comments/documentation about the available buffer space
+    in the xdr_buf head and tail when gss_wrap is called.
+    
+    Add a compile-time check to make sure we are not exceeding the available
+    buffer space.
+    
+    Add a central function to shift head data.
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: Steve Dickson 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
+index e7bbdba474d5..31bb8a538bf1 100644
+--- a/include/linux/sunrpc/gss_krb5.h
++++ b/include/linux/sunrpc/gss_krb5.h
+@@ -40,6 +40,12 @@
+ #include 
+ #include 
+ 
++/* Maximum checksum function output for the supported crypto algorithms */
++#define GSS_KRB5_MAX_CKSUM_LEN  (20)
++
++/* Maximum blocksize for the supported crypto algorithms */
++#define GSS_KRB5_MAX_BLOCKSIZE  (16)
++
+ struct krb5_ctx {
+ 	int			initiate; /* 1 = initiating, 0 = accepting */
+ 	struct crypto_blkcipher	*enc;
+@@ -113,6 +119,22 @@ enum seal_alg {
+ #define ENCTYPE_DES3_CBC_SHA1   0x0010
+ #define ENCTYPE_UNKNOWN         0x01ff
+ 
++/*
++ * This compile-time check verifies that we will not exceed the
++ * slack space allotted by the client and server auth_gss code
++ * before they call gss_wrap().
++ */
++#define GSS_KRB5_MAX_SLACK_NEEDED \
++	(GSS_KRB5_TOK_HDR_LEN     /* gss token header */         \
++	+ GSS_KRB5_MAX_CKSUM_LEN  /* gss token checksum */       \
++	+ GSS_KRB5_MAX_BLOCKSIZE  /* confounder */               \
++	+ GSS_KRB5_MAX_BLOCKSIZE  /* possible padding */         \
++	+ GSS_KRB5_TOK_HDR_LEN    /* encrypted hdr in v2 token */\
++	+ GSS_KRB5_MAX_CKSUM_LEN  /* encryption hmac */          \
++	+ 4 + 4                   /* RPC verifier */             \
++	+ GSS_KRB5_TOK_HDR_LEN                                   \
++	+ GSS_KRB5_MAX_CKSUM_LEN)
++
+ s32
+ make_checksum(char *, char *header, int hdrlen, struct xdr_buf *body,
+ 		   int body_offset, struct xdr_netobj *cksum);
+@@ -157,3 +179,6 @@ s32
+ krb5_get_seq_num(struct crypto_blkcipher *key,
+ 	       unsigned char *cksum,
+ 	       unsigned char *buf, int *direction, u32 *seqnum);
++
++int
++xdr_extend_head(struct xdr_buf *buf, unsigned int base, unsigned int shiftlen);
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index c389ccf6437d..75602ece58eb 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -61,7 +61,7 @@ static const struct rpc_credops gss_nullops;
+ # define RPCDBG_FACILITY	RPCDBG_AUTH
+ #endif
+ 
+-#define GSS_CRED_SLACK		1024
++#define GSS_CRED_SLACK		(RPC_MAX_AUTH_SIZE * 2)
+ /* length of a krb5 verifier (48), plus data added before arguments when
+  * using integrity (two 4-byte integers): */
+ #define GSS_VERF_SLACK		100
+diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+index e9b636176687..746b3e139aed 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
++++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+@@ -325,3 +325,41 @@ gss_decrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *buf,
+ 
+ 	return xdr_process_buf(buf, offset, buf->len - offset, decryptor, &desc);
+ }
++
++/*
++ * This function makes the assumption that it was ultimately called
++ * from gss_wrap().
++ *
++ * The client auth_gss code moves any existing tail data into a
++ * separate page before calling gss_wrap.
++ * The server svcauth_gss code ensures that both the head and the
++ * tail have slack space of RPC_MAX_AUTH_SIZE before calling gss_wrap.
++ *
++ * Even with that guarantee, this function may be called more than
++ * once in the processing of gss_wrap().  The best we can do is
++ * verify at compile-time (see GSS_KRB5_SLACK_CHECK) that the
++ * largest expected shift will fit within RPC_MAX_AUTH_SIZE.
++ * At run-time we can verify that a single invocation of this
++ * function doesn't attempt to use more the RPC_MAX_AUTH_SIZE.
++ */
++
++int
++xdr_extend_head(struct xdr_buf *buf, unsigned int base, unsigned int shiftlen)
++{
++	u8 *p;
++
++	if (shiftlen == 0)
++		return 0;
++
++	BUILD_BUG_ON(GSS_KRB5_MAX_SLACK_NEEDED > RPC_MAX_AUTH_SIZE);
++	BUG_ON(shiftlen > RPC_MAX_AUTH_SIZE);
++
++	p = buf->head[0].iov_base + base;
++
++	memmove(p + shiftlen, p, buf->head[0].iov_len - base);
++
++	buf->head[0].iov_len += shiftlen;
++	buf->len += shiftlen;
++
++	return 0;
++}
+diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+index a6e905637e03..496281fabb91 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
++++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+@@ -155,11 +155,9 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
+ 
+ 	ptr = buf->head[0].iov_base + offset;
+ 	/* shift data to make room for header. */
++	xdr_extend_head(buf, offset, headlen);
++
+ 	/* XXX Would be cleverer to encrypt while copying. */
+-	/* XXX bounds checking, slack, etc. */
+-	memmove(ptr + headlen, ptr, buf->head[0].iov_len - offset);
+-	buf->head[0].iov_len += headlen;
+-	buf->len += headlen;
+ 	BUG_ON((buf->len - offset - headlen) % blocksize);
+ 
+ 	g_make_token_header(&kctx->mech_used,

commit 4dc6ec00f6347b72312fa41dfc587d5302b05544
+Author: J. Bruce Fields 
+Date:   Mon Apr 19 15:11:28 2010 -0400
+
+    nfsd4: implement reclaim_complete
+    
+    This is a mandatory operation.  Also, here (not in open) is where we
+    should be committing the reboot recovery information.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/Documentation/filesystems/nfs/nfs41-server.txt b/Documentation/filesystems/nfs/nfs41-server.txt
+index 6a53a84afc72..04884914a1c8 100644
+--- a/Documentation/filesystems/nfs/nfs41-server.txt
++++ b/Documentation/filesystems/nfs/nfs41-server.txt
+@@ -137,7 +137,7 @@ NS*| OPENATTR             | OPT        |              | Section 18.17  |
+    | READ                 | REQ        |              | Section 18.22  |
+    | READDIR              | REQ        |              | Section 18.23  |
+    | READLINK             | OPT        |              | Section 18.24  |
+-NS | RECLAIM_COMPLETE     | REQ        |              | Section 18.51  |
++   | RECLAIM_COMPLETE     | REQ        |              | Section 18.51  |
+    | RELEASE_LOCKOWNER    | MNI        |              | N/A            |
+    | REMOVE               | REQ        |              | Section 18.25  |
+    | RENAME               | REQ        |              | Section 18.26  |
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index e2dc9608281b..59ec449b0c7f 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -1312,6 +1312,11 @@ static struct nfsd4_operation nfsd4_ops[] = {
+ 		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP,
+ 		.op_name = "OP_SEQUENCE",
+ 	},
++	[OP_RECLAIM_COMPLETE] = {
++		.op_func = (nfsd4op_func)nfsd4_reclaim_complete,
++		.op_flags = ALLOWED_WITHOUT_FH,
++		.op_name = "OP_RECLAIM_COMPLETE",
++	},
+ };
+ 
+ static const char *nfsd4_op_name(unsigned opnum)
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index ede9dde52fe8..84b0fe9a262a 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1501,6 +1501,35 @@ nfsd4_sequence(struct svc_rqst *rqstp,
+ 	return status;
+ }
+ 
++__be32
++nfsd4_reclaim_complete(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_reclaim_complete *rc)
++{
++	if (rc->rca_one_fs) {
++		if (!cstate->current_fh.fh_dentry)
++			return nfserr_nofilehandle;
++		/*
++		 * We don't take advantage of the rca_one_fs case.
++		 * That's OK, it's optional, we can safely ignore it.
++		 */
++		 return nfs_ok;
++	}
++	nfs4_lock_state();
++	if (is_client_expired(cstate->session->se_client)) {
++		nfs4_unlock_state();
++		/*
++		 * The following error isn't really legal.
++		 * But we only get here if the client just explicitly
++		 * destroyed the client.  Surely it no longer cares what
++		 * error it gets back on an operation for the dead
++		 * client.
++		 */
++		return nfserr_stale_clientid;
++	}
++	nfsd4_create_clid_dir(cstate->session->se_client);
++	nfs4_unlock_state();
++	return nfs_ok;
++}
++
+ __be32
+ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 		  struct nfsd4_setclientid *setclid)
+@@ -2510,10 +2539,8 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
+ 	}
+ 	memcpy(&open->op_stateid, &stp->st_stateid, sizeof(stateid_t));
+ 
+-	if (nfsd4_has_session(&resp->cstate)) {
++	if (nfsd4_has_session(&resp->cstate))
+ 		open->op_stateowner->so_confirmed = 1;
+-		nfsd4_create_clid_dir(open->op_stateowner->so_client);
+-	}
+ 
+ 	/*
+ 	* Attempt to hand out a delegation. No error return, because the
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index 126d0caabb3c..ac17a7080239 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -1234,6 +1234,16 @@ nfsd4_decode_sequence(struct nfsd4_compoundargs *argp,
+ 	DECODE_TAIL;
+ }
+ 
++static __be32 nfsd4_decode_reclaim_complete(struct nfsd4_compoundargs *argp, struct nfsd4_reclaim_complete *rc)
++{
++	DECODE_HEAD;
++
++	READ_BUF(4);
++	READ32(rc->rca_one_fs);
++
++	DECODE_TAIL;
++}
++
+ static __be32
+ nfsd4_decode_noop(struct nfsd4_compoundargs *argp, void *p)
+ {
+@@ -1346,7 +1356,7 @@ static nfsd4_dec nfsd41_dec_ops[] = {
+ 	[OP_TEST_STATEID]	= (nfsd4_dec)nfsd4_decode_notsupp,
+ 	[OP_WANT_DELEGATION]	= (nfsd4_dec)nfsd4_decode_notsupp,
+ 	[OP_DESTROY_CLIENTID]	= (nfsd4_dec)nfsd4_decode_notsupp,
+-	[OP_RECLAIM_COMPLETE]	= (nfsd4_dec)nfsd4_decode_notsupp,
++	[OP_RECLAIM_COMPLETE]	= (nfsd4_dec)nfsd4_decode_reclaim_complete,
+ };
+ 
+ struct nfsd4_minorversion_ops {
+diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
+index c28958ec216c..4d476ff08ae6 100644
+--- a/fs/nfsd/xdr4.h
++++ b/fs/nfsd/xdr4.h
+@@ -381,6 +381,10 @@ struct nfsd4_destroy_session {
+ 	struct nfs4_sessionid	sessionid;
+ };
+ 
++struct nfsd4_reclaim_complete {
++	u32 rca_one_fs;
++};
++
+ struct nfsd4_op {
+ 	int					opnum;
+ 	__be32					status;
+@@ -421,6 +425,7 @@ struct nfsd4_op {
+ 		struct nfsd4_create_session	create_session;
+ 		struct nfsd4_destroy_session	destroy_session;
+ 		struct nfsd4_sequence		sequence;
++		struct nfsd4_reclaim_complete	reclaim_complete;
+ 	} u;
+ 	struct nfs4_replay *			replay;
+ };
+@@ -523,6 +528,7 @@ extern __be32 nfsd4_sequence(struct svc_rqst *,
+ extern __be32 nfsd4_destroy_session(struct svc_rqst *,
+ 		struct nfsd4_compound_state *,
+ 		struct nfsd4_destroy_session *);
++__be32 nfsd4_reclaim_complete(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_reclaim_complete *);
+ extern __be32 nfsd4_process_open1(struct nfsd4_compound_state *,
+ 		struct nfsd4_open *open);
+ extern __be32 nfsd4_process_open2(struct svc_rqst *rqstp,

commit 5d4cec2f2fdbb3d830fa014226d0d965df548bad
+Author: J. Bruce Fields 
+Date:   Sat May 1 12:56:06 2010 -0400
+
+    nfsd4: fix bare destroy_session null dereference
+    
+    It's legal to send a DESTROY_SESSION outside any session (as the only
+    operation in a compound), in which case cstate->session will be NULL;
+    check for that case.
+    
+    While we're at it, move these checks into a separate helper function.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index f05a3276ba6b..835d6cef9ae9 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1352,6 +1352,13 @@ static bool nfsd4_last_compound_op(struct svc_rqst *rqstp)
+ 	return argp->opcnt == resp->opcnt;
+ }
+ 
++static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid)
++{
++	if (!session)
++		return 0;
++	return !memcmp(sid, &session->se_sessionid, sizeof(*sid));
++}
++
+ __be32
+ nfsd4_destroy_session(struct svc_rqst *r,
+ 		      struct nfsd4_compound_state *cstate,
+@@ -1367,8 +1374,7 @@ nfsd4_destroy_session(struct svc_rqst *r,
+ 	 * - Do we need to clear any callback info from previous session?
+ 	 */
+ 
+-	if (!memcmp(&sessionid->sessionid, &cstate->session->se_sessionid,
+-					sizeof(struct nfs4_sessionid))) {
++	if (nfsd4_compound_in_session(cstate->session, &sessionid->sessionid)) {
+ 		if (!nfsd4_last_compound_op(r))
+ 			return nfserr_not_only_op;
+ 	}

commit 5306293c9cd2caf41849cc909281bda628bb989e
+Merge: dbd65a7e44ff 66f41d4c5c8a
+Author: J. Bruce Fields 
+Date:   Tue May 4 11:27:05 2010 -0400
+
+    Merge commit 'v2.6.34-rc6'
+    
+    Conflicts:
+            fs/nfsd/nfs4callback.c
+
+diff --cc fs/nfsd/nfs4callback.c
+index ea77aa63754a,7e32bd394e86..1d5051d46b46
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@@ -32,7 -32,7 +32,8 @@@
+   */
+  
+  #include 
+ +#include 
++ #include 
+  #include "nfsd.h"
+  #include "state.h"
+  

commit fb4b698fc78347419aa9ae7114e1375f92107500
+Author: J. Bruce Fields 
+Date:   Wed Apr 28 17:45:06 2010 -0400
+
+    nfsd: further comment typos
+    
+    Whoops, missed some more.
+    
+    "Reviewed-by, I guess": Chuck Lever 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h
+index 45bb5a8102c1..80d55bbc5365 100644
+--- a/include/linux/nfsd/nfsfh.h
++++ b/include/linux/nfsd/nfsfh.h
+@@ -40,12 +40,12 @@ struct nfs_fhbase_old {
+  * This is the new flexible, extensible style NFSv2/v3 file handle.
+  * by Neil Brown  - March 2000
+  *
+- * The file handle is seens as a list of four-byte words.
++ * The file handle starts with a sequence of four-byte words.
+  * The first word contains a version number (1) and three descriptor bytes
+  * that tell how the remaining 3 variable length fields should be handled.
+  * These three bytes are auth_type, fsid_type and fileid_type.
+  *
+- * All 4byte values are in host-byte-order.
++ * All four-byte values are in host-byte-order.
+  *
+  * The auth_type field specifies how the filehandle can be authenticated
+  * This might allow a file to be confirmed to be in a writable part of a

commit 26c0c75e69265961e891ed80b38fb62a548ab371
+Author: J. Bruce Fields 
+Date:   Sat Apr 24 15:35:43 2010 -0400
+
+    nfsd4: fix unlikely race in session replay case
+    
+    In the replay case, the
+    
+            renew_client(session->se_client);
+    
+    happens after we've droppped the sessionid_lock, and without holding a
+    reference on the session; so there's nothing preventing the session
+    being freed before we get here.
+    
+    Thanks to Benny Halevy for catching a bug in an earlier version of this
+    patch.
+    
+    Signed-off-by: J. Bruce Fields 
+    Acked-by: Benny Halevy 
+
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index e147dbcb7ef7..61282f8405b5 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -1027,6 +1027,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
+ 	resp->rqstp = rqstp;
+ 	resp->cstate.minorversion = args->minorversion;
+ 	resp->cstate.replay_owner = NULL;
++	resp->cstate.session = NULL;
+ 	fh_init(&resp->cstate.current_fh, NFS4_FHSIZE);
+ 	fh_init(&resp->cstate.save_fh, NFS4_FHSIZE);
+ 	/* Use the deferral mechanism only for NFSv4.0 compounds */
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index bba9fff49cfe..737315c61e7e 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1443,11 +1443,10 @@ nfsd4_sequence(struct svc_rqst *rqstp,
+ 	cstate->slot = slot;
+ 	cstate->session = session;
+ 
+-	/* Hold a session reference until done processing the compound:
+-	 * nfsd4_put_session called only if the cstate slot is set.
+-	 */
+-	nfsd4_get_session(session);
+ out:
++	/* Hold a session reference until done processing the compound. */
++	if (cstate->session)
++		nfsd4_get_session(cstate->session);
+ 	spin_unlock(&sessionid_lock);
+ 	/* Renew the clientid on success and on replay */
+ 	if (cstate->session) {
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index fb27b1db007b..05bc5bd63c95 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -3306,10 +3306,12 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compo
+ 		iov = &rqstp->rq_res.head[0];
+ 	iov->iov_len = ((char*)resp->p) - (char*)iov->iov_base;
+ 	BUG_ON(iov->iov_len > PAGE_SIZE);
+-	if (nfsd4_has_session(cs) && cs->status != nfserr_replay_cache) {
+-		nfsd4_store_cache_entry(resp);
+-		dprintk("%s: SET SLOT STATE TO AVAILABLE\n", __func__);
+-		resp->cstate.slot->sl_inuse = false;
++	if (nfsd4_has_session(cs)) {
++		if (cs->status != nfserr_replay_cache) {
++			nfsd4_store_cache_entry(resp);
++			dprintk("%s: SET SLOT STATE TO AVAILABLE\n", __func__);
++			resp->cstate.slot->sl_inuse = false;
++		}
+ 		nfsd4_put_session(resp->cstate.session);
+ 	}
+ 	return 1;

commit e0c8233622cbd49d171bc57b60e725f2fb748750
+Author: J. Bruce Fields 
+Date:   Thu Apr 22 17:04:25 2010 -0400
+
+    nfsd4: fix filehandle comment
+    
+    Minor typos.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h
+index 65e333afaee4..45bb5a8102c1 100644
+--- a/include/linux/nfsd/nfsfh.h
++++ b/include/linux/nfsd/nfsfh.h
+@@ -40,8 +40,8 @@ struct nfs_fhbase_old {
+  * This is the new flexible, extensible style NFSv2/v3 file handle.
+  * by Neil Brown  - March 2000
+  *
+- * The file handle is seens as a list of 4byte words.
+- * The first word contains a version number (1) and four descriptor bytes
++ * The file handle is seens as a list of four-byte words.
++ * The first word contains a version number (1) and three descriptor bytes
+  * that tell how the remaining 3 variable length fields should be handled.
+  * These three bytes are auth_type, fsid_type and fileid_type.
+  *

commit 5771635592267758e7dc5647f2a0088aa6244159
+Author: J. Bruce Fields 
+Date:   Wed Apr 21 12:27:19 2010 -0400
+
+    nfsd4: complete enforcement of 4.1 op ordering
+    
+    Enforce the rules about compound op ordering.
+    
+    Motivated by implementing RECLAIM_COMPLETE, for which the client is
+    implicit in the current session, so it is important to ensure a
+    succesful SEQUENCE proceeds the RECLAIM_COMPLETE.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index 37514c469846..e147dbcb7ef7 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -968,20 +968,36 @@ static struct nfsd4_operation nfsd4_ops[];
+ static const char *nfsd4_op_name(unsigned opnum);
+ 
+ /*
+- * Enforce NFSv4.1 COMPOUND ordering rules.
++ * Enforce NFSv4.1 COMPOUND ordering rules:
+  *
+- * TODO:
+- * - enforce NFS4ERR_NOT_ONLY_OP,
+- * - DESTROY_SESSION MUST be the final operation in the COMPOUND request.
++ * Also note, enforced elsewhere:
++ *	- SEQUENCE other than as first op results in
++ *	  NFS4ERR_SEQUENCE_POS. (Enforced in nfsd4_sequence().)
++ *	- BIND_CONN_TO_SESSION must be the only op in its compound
++ *	  (Will be enforced in nfsd4_bind_conn_to_session().)
++ *	- DESTROY_SESSION must be the final operation in a compound, if
++ *	  sessionid's in SEQUENCE and DESTROY_SESSION are the same.
++ *	  (Enforced in nfsd4_destroy_session().)
+  */
+-static bool nfs41_op_ordering_ok(struct nfsd4_compoundargs *args)
++static __be32 nfs41_check_op_ordering(struct nfsd4_compoundargs *args)
+ {
+-	if (args->minorversion && args->opcnt > 0) {
+-		struct nfsd4_op *op = &args->ops[0];
+-		return (op->status == nfserr_op_illegal) ||
+-		       (nfsd4_ops[op->opnum].op_flags & ALLOWED_AS_FIRST_OP);
+-	}
+-	return true;
++	struct nfsd4_op *op = &args->ops[0];
++
++	/* These ordering requirements don't apply to NFSv4.0: */
++	if (args->minorversion == 0)
++		return nfs_ok;
++	/* This is weird, but OK, not our problem: */
++	if (args->opcnt == 0)
++		return nfs_ok;
++	if (op->status == nfserr_op_illegal)
++		return nfs_ok;
++	if (!(nfsd4_ops[op->opnum].op_flags & ALLOWED_AS_FIRST_OP))
++		return nfserr_op_not_in_session;
++	if (op->opnum == OP_SEQUENCE)
++		return nfs_ok;
++	if (args->opcnt != 1)
++		return nfserr_not_only_op;
++	return nfs_ok;
+ }
+ 
+ /*
+@@ -1023,13 +1039,13 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
+ 	if (args->minorversion > nfsd_supported_minorversion)
+ 		goto out;
+ 
+-	if (!nfs41_op_ordering_ok(args)) {
++	status = nfs41_check_op_ordering(args);
++	if (status) {
+ 		op = &args->ops[0];
+-		op->status = nfserr_sequence_pos;
++		op->status = status;
+ 		goto encode_op;
+ 	}
+ 
+-	status = nfs_ok;
+ 	while (!status && resp->opcnt < args->opcnt) {
+ 		op = &args->ops[resp->opcnt++];
+ 
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 4300d9ffe95f..bba9fff49cfe 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1343,6 +1343,14 @@ nfsd4_create_session(struct svc_rqst *rqstp,
+ 	return status;
+ }
+ 
++static bool nfsd4_last_compound_op(struct svc_rqst *rqstp)
++{
++	struct nfsd4_compoundres *resp = rqstp->rq_resp;
++	struct nfsd4_compoundargs *argp = rqstp->rq_argp;
++
++	return argp->opcnt == resp->opcnt;
++}
++
+ __be32
+ nfsd4_destroy_session(struct svc_rqst *r,
+ 		      struct nfsd4_compound_state *cstate,
+@@ -1358,6 +1366,11 @@ nfsd4_destroy_session(struct svc_rqst *r,
+ 	 * - Do we need to clear any callback info from previous session?
+ 	 */
+ 
++	if (!memcmp(&sessionid->sessionid, &cstate->session->se_sessionid,
++					sizeof(struct nfs4_sessionid))) {
++		if (!nfsd4_last_compound_op(r))
++			return nfserr_not_only_op;
++	}
+ 	dump_sessionid(__func__, &sessionid->sessionid);
+ 	spin_lock(&sessionid_lock);
+ 	ses = find_in_sessionid_hashtbl(&sessionid->sessionid);

commit 4b21d0defcc9680da8a694e92d5fe8eb668c2c0b
+Author: J. Bruce Fields 
+Date:   Sun Mar 7 23:39:01 2010 -0500
+
+    nfsd4: allow 4.0 clients to change callback path
+    
+    The rfc allows a client to change the callback parameters, but we didn't
+    previously implement it.
+    
+    Teach the callbacks to rerun themselves (by placing themselves on a
+    workqueue) when they recognize that their rpc task has been killed and
+    that the callback connection has changed.
+    
+    Then we can change the callback connection by setting up a new rpc
+    client, modifying the nfs4 client to point at it, waiting for any work
+    in progress to complete, and then shutting down the old client.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index d6c46a9de422..ea77aa63754a 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -457,9 +457,8 @@ static int max_cb_time(void)
+ /* Reference counting, callback cleanup, etc., all look racy as heck.
+  * And why is cl_cb_set an atomic? */
+ 
+-int setup_callback_client(struct nfs4_client *clp)
++int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *cb)
+ {
+-	struct nfs4_cb_conn *cb = &clp->cl_cb_conn;
+ 	struct rpc_timeout	timeparms = {
+ 		.to_initval	= max_cb_time(),
+ 		.to_retries	= 0,
+@@ -481,7 +480,7 @@ int setup_callback_client(struct nfs4_client *clp)
+ 	if (!clp->cl_principal && (clp->cl_flavor >= RPC_AUTH_GSS_KRB5))
+ 		return -EINVAL;
+ 	if (cb->cb_minorversion) {
+-		args.bc_xprt = clp->cl_cb_conn.cb_xprt;
++		args.bc_xprt = cb->cb_xprt;
+ 		args.protocol = XPRT_TRANSPORT_BC_TCP;
+ 	}
+ 	/* Create RPC client */
+@@ -491,7 +490,7 @@ int setup_callback_client(struct nfs4_client *clp)
+ 			PTR_ERR(client));
+ 		return PTR_ERR(client);
+ 	}
+-	clp->cl_cb_client = client;
++	nfsd4_set_callback_client(clp, client);
+ 	return 0;
+ 
+ }
+@@ -548,14 +547,13 @@ void do_probe_callback(struct nfs4_client *clp)
+ /*
+  * Set up the callback client and put a NFSPROC4_CB_NULL on the wire...
+  */
+-void
+-nfsd4_probe_callback(struct nfs4_client *clp)
++void nfsd4_probe_callback(struct nfs4_client *clp, struct nfs4_cb_conn *cb)
+ {
+ 	int status;
+ 
+ 	BUG_ON(atomic_read(&clp->cl_cb_set));
+ 
+-	status = setup_callback_client(clp);
++	status = setup_callback_client(clp, cb);
+ 	if (status) {
+ 		warn_no_callback_path(clp, status);
+ 		return;
+@@ -645,18 +643,32 @@ static void nfsd4_cb_done(struct rpc_task *task, void *calldata)
+ 	}
+ }
+ 
++
+ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
+ {
+ 	struct nfs4_delegation *dp = calldata;
+ 	struct nfs4_client *clp = dp->dl_client;
++	struct rpc_clnt *current_rpc_client = clp->cl_cb_client;
+ 
+ 	nfsd4_cb_done(task, calldata);
+ 
++	if (current_rpc_client == NULL) {
++		/* We're shutting down; give up. */
++		/* XXX: err, or is it ok just to fall through
++		 * and rpc_restart_call? */
++		return;
++	}
++
+ 	switch (task->tk_status) {
+ 	case -EIO:
+ 		/* Network partition? */
+ 		atomic_set(&clp->cl_cb_set, 0);
+ 		warn_no_callback_path(clp, task->tk_status);
++		if (current_rpc_client != task->tk_client) {
++			/* queue a callback on the new connection: */
++			nfsd4_cb_recall(dp);
++			return;
++		}
+ 	case -EBADHANDLE:
+ 	case -NFS4ERR_BAD_STATEID:
+ 		/* Race: client probably got cb_recall
+@@ -705,8 +717,7 @@ void nfsd4_destroy_callback_queue(void)
+ 	destroy_workqueue(callback_wq);
+ }
+ 
+-void nfsd4_set_callback_client(struct nfs4_client *clp, struct rpc_clnt
+-*new)
++void nfsd4_set_callback_client(struct nfs4_client *clp, struct rpc_clnt *new)
+ {
+ 	struct rpc_clnt *old = clp->cl_cb_client;
+ 
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 59c9bd4c89e1..4300d9ffe95f 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1312,7 +1312,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
+ 				cstate->minorversion;
+ 			unconf->cl_cb_conn.cb_prog = cr_ses->callback_prog;
+ 			unconf->cl_cb_seq_nr = 1;
+-			nfsd4_probe_callback(unconf);
++			nfsd4_probe_callback(unconf, &unconf->cl_cb_conn);
+ 		}
+ 		conf = unconf;
+ 	} else {
+@@ -1605,9 +1605,8 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+ 		if (!same_creds(&conf->cl_cred, &unconf->cl_cred))
+ 			status = nfserr_clid_inuse;
+ 		else {
+-			/* XXX: We just turn off callbacks until we can handle
+-			  * change request correctly. */
+ 			atomic_set(&conf->cl_cb_set, 0);
++			nfsd4_probe_callback(conf, &unconf->cl_cb_conn);
+ 			expire_client(unconf);
+ 			status = nfs_ok;
+ 
+@@ -1641,7 +1640,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+ 			}
+ 			move_to_confirmed(unconf);
+ 			conf = unconf;
+-			nfsd4_probe_callback(conf);
++			nfsd4_probe_callback(conf, &conf->cl_cb_conn);
+ 			status = nfs_ok;
+ 		}
+ 	} else if ((!conf || (conf && !same_verf(&conf->cl_confirm, &confirm)))
+diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
+index cf43812e6da5..98836fd87f69 100644
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -390,7 +390,7 @@ extern int nfs4_in_grace(void);
+ extern __be32 nfs4_check_open_reclaim(clientid_t *clid);
+ extern void nfs4_free_stateowner(struct kref *kref);
+ extern int set_callback_cred(void);
+-extern void nfsd4_probe_callback(struct nfs4_client *clp);
++extern void nfsd4_probe_callback(struct nfs4_client *clp, struct nfs4_cb_conn *);
+ extern void nfsd4_do_callback_rpc(struct work_struct *);
+ extern void nfsd4_cb_recall(struct nfs4_delegation *dp);
+ extern int nfsd4_create_callback_queue(void);

commit 2bf23875f55af6038a5d1c164a52cec4c24609ba
+Author: J. Bruce Fields 
+Date:   Mon Mar 8 12:37:27 2010 -0500
+
+    nfsd4: rearrange cb data structures
+    
+    Mainly I just want to separate the arguments used for setting up the tcp
+    client from the rest.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 5856fc8adb70..d6c46a9de422 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -455,7 +455,7 @@ static int max_cb_time(void)
+ }
+ 
+ /* Reference counting, callback cleanup, etc., all look racy as heck.
+- * And why is cb_set an atomic? */
++ * And why is cl_cb_set an atomic? */
+ 
+ int setup_callback_client(struct nfs4_client *clp)
+ {
+@@ -481,7 +481,7 @@ int setup_callback_client(struct nfs4_client *clp)
+ 	if (!clp->cl_principal && (clp->cl_flavor >= RPC_AUTH_GSS_KRB5))
+ 		return -EINVAL;
+ 	if (cb->cb_minorversion) {
+-		args.bc_xprt = clp->cl_cb_xprt;
++		args.bc_xprt = clp->cl_cb_conn.cb_xprt;
+ 		args.protocol = XPRT_TRANSPORT_BC_TCP;
+ 	}
+ 	/* Create RPC client */
+@@ -491,7 +491,7 @@ int setup_callback_client(struct nfs4_client *clp)
+ 			PTR_ERR(client));
+ 		return PTR_ERR(client);
+ 	}
+-	cb->cb_client = client;
++	clp->cl_cb_client = client;
+ 	return 0;
+ 
+ }
+@@ -509,7 +509,7 @@ static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata)
+ 	if (task->tk_status)
+ 		warn_no_callback_path(clp, task->tk_status);
+ 	else
+-		atomic_set(&clp->cl_cb_conn.cb_set, 1);
++		atomic_set(&clp->cl_cb_set, 1);
+ }
+ 
+ static const struct rpc_call_ops nfsd4_cb_probe_ops = {
+@@ -531,7 +531,6 @@ int set_callback_cred(void)
+ 
+ void do_probe_callback(struct nfs4_client *clp)
+ {
+-	struct nfs4_cb_conn *cb = &clp->cl_cb_conn;
+ 	struct rpc_message msg = {
+ 		.rpc_proc       = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
+ 		.rpc_argp       = clp,
+@@ -539,7 +538,7 @@ void do_probe_callback(struct nfs4_client *clp)
+ 	};
+ 	int status;
+ 
+-	status = rpc_call_async(cb->cb_client, &msg,
++	status = rpc_call_async(clp->cl_cb_client, &msg,
+ 				RPC_TASK_SOFT | RPC_TASK_SOFTCONN,
+ 				&nfsd4_cb_probe_ops, (void *)clp);
+ 	if (status)
+@@ -554,7 +553,7 @@ nfsd4_probe_callback(struct nfs4_client *clp)
+ {
+ 	int status;
+ 
+-	BUG_ON(atomic_read(&clp->cl_cb_conn.cb_set));
++	BUG_ON(atomic_read(&clp->cl_cb_set));
+ 
+ 	status = setup_callback_client(clp);
+ 	if (status) {
+@@ -656,7 +655,7 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
+ 	switch (task->tk_status) {
+ 	case -EIO:
+ 		/* Network partition? */
+-		atomic_set(&clp->cl_cb_conn.cb_set, 0);
++		atomic_set(&clp->cl_cb_set, 0);
+ 		warn_no_callback_path(clp, task->tk_status);
+ 	case -EBADHANDLE:
+ 	case -NFS4ERR_BAD_STATEID:
+@@ -673,7 +672,7 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
+ 		rpc_restart_call(task);
+ 		return;
+ 	} else {
+-		atomic_set(&clp->cl_cb_conn.cb_set, 0);
++		atomic_set(&clp->cl_cb_set, 0);
+ 		warn_no_callback_path(clp, task->tk_status);
+ 	}
+ }
+@@ -709,11 +708,11 @@ void nfsd4_destroy_callback_queue(void)
+ void nfsd4_set_callback_client(struct nfs4_client *clp, struct rpc_clnt
+ *new)
+ {
+-	struct rpc_clnt *old = clp->cl_cb_conn.cb_client;
++	struct rpc_clnt *old = clp->cl_cb_client;
+ 
+-	clp->cl_cb_conn.cb_client = new;
++	clp->cl_cb_client = new;
+ 	/*
+-	 * After this, any work that saw the old value of cb_client will
++	 * After this, any work that saw the old value of cl_cb_client will
+ 	 * be gone:
+ 	 */
+ 	flush_workqueue(callback_wq);
+@@ -728,7 +727,7 @@ void nfsd4_set_callback_client(struct nfs4_client *clp, struct rpc_clnt
+ static void _nfsd4_cb_recall(struct nfs4_delegation *dp)
+ {
+ 	struct nfs4_client *clp = dp->dl_client;
+-	struct rpc_clnt *clnt = clp->cl_cb_conn.cb_client;
++	struct rpc_clnt *clnt = clp->cl_cb_client;
+ 	struct nfs4_rpc_args *args = &dp->dl_recall.cb_args;
+ 	struct rpc_message msg = {
+ 		.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL],
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index cf650cbb814b..59c9bd4c89e1 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -726,8 +726,8 @@ expire_client(struct nfs4_client *clp)
+ 		release_session(ses);
+ 	}
+ 	nfsd4_set_callback_client(clp, NULL);
+-	if (clp->cl_cb_xprt)
+-		svc_xprt_put(clp->cl_cb_xprt);
++	if (clp->cl_cb_conn.cb_xprt)
++		svc_xprt_put(clp->cl_cb_conn.cb_xprt);
+ 	free_client(clp);
+ }
+ 
+@@ -814,7 +814,7 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir,
+ 	}
+ 
+ 	memcpy(clp->cl_recdir, recdir, HEXDIR_LEN);
+-	atomic_set(&clp->cl_cb_conn.cb_set, 0);
++	atomic_set(&clp->cl_cb_set, 0);
+ 	INIT_LIST_HEAD(&clp->cl_idhash);
+ 	INIT_LIST_HEAD(&clp->cl_strhash);
+ 	INIT_LIST_HEAD(&clp->cl_openowners);
+@@ -1302,8 +1302,8 @@ nfsd4_create_session(struct svc_rqst *rqstp,
+ 		move_to_confirmed(unconf);
+ 
+ 		if (cr_ses->flags & SESSION4_BACK_CHAN) {
+-			unconf->cl_cb_xprt = rqstp->rq_xprt;
+-			svc_xprt_get(unconf->cl_cb_xprt);
++			unconf->cl_cb_conn.cb_xprt = rqstp->rq_xprt;
++			svc_xprt_get(rqstp->rq_xprt);
+ 			rpc_copy_addr(
+ 				(struct sockaddr *)&unconf->cl_cb_conn.cb_addr,
+ 				sa);
+@@ -1607,7 +1607,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+ 		else {
+ 			/* XXX: We just turn off callbacks until we can handle
+ 			  * change request correctly. */
+-			atomic_set(&conf->cl_cb_conn.cb_set, 0);
++			atomic_set(&conf->cl_cb_set, 0);
+ 			expire_client(unconf);
+ 			status = nfs_ok;
+ 
+@@ -2320,7 +2320,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
+ {
+ 	struct nfs4_delegation *dp;
+ 	struct nfs4_stateowner *sop = stp->st_stateowner;
+-	struct nfs4_cb_conn *cb = &sop->so_client->cl_cb_conn;
++	int cb_up = atomic_read(&sop->so_client->cl_cb_set);
+ 	struct file_lock fl, *flp = &fl;
+ 	int status, flag = 0;
+ 
+@@ -2328,7 +2328,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
+ 	open->op_recall = 0;
+ 	switch (open->op_claim_type) {
+ 		case NFS4_OPEN_CLAIM_PREVIOUS:
+-			if (!atomic_read(&cb->cb_set))
++			if (!cb_up)
+ 				open->op_recall = 1;
+ 			flag = open->op_delegate_type;
+ 			if (flag == NFS4_OPEN_DELEGATE_NONE)
+@@ -2339,7 +2339,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
+ 			 * had the chance to reclaim theirs.... */
+ 			if (locks_in_grace())
+ 				goto out;
+-			if (!atomic_read(&cb->cb_set) || !sop->so_confirmed)
++			if (!cb_up || !sop->so_confirmed)
+ 				goto out;
+ 			if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
+ 				flag = NFS4_OPEN_DELEGATE_WRITE;
+@@ -2510,7 +2510,7 @@ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	renew_client(clp);
+ 	status = nfserr_cb_path_down;
+ 	if (!list_empty(&clp->cl_delegations)
+-			&& !atomic_read(&clp->cl_cb_conn.cb_set))
++			&& !atomic_read(&clp->cl_cb_set))
+ 		goto out;
+ 	status = nfs_ok;
+ out:
+diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
+index cef20abf330c..cf43812e6da5 100644
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -107,9 +107,7 @@ struct nfs4_cb_conn {
+ 	u32                     cb_prog;
+ 	u32			cb_minorversion;
+ 	u32                     cb_ident;	/* minorversion 0 only */
+-	/* RPC client info */
+-	atomic_t		cb_set;     /* successful CB_NULL call */
+-	struct rpc_clnt *       cb_client;
++	struct svc_xprt		*cb_xprt;	/* minorversion 1 only */
+ };
+ 
+ /* Maximum number of slots per session. 160 is useful for long haul TCP */
+@@ -223,9 +221,13 @@ struct nfs4_client {
+ 	struct svc_cred		cl_cred; 	/* setclientid principal */
+ 	clientid_t		cl_clientid;	/* generated by server */
+ 	nfs4_verifier		cl_confirm;	/* generated by server */
+-	struct nfs4_cb_conn	cl_cb_conn;     /* callback info */
+ 	u32			cl_firststate;	/* recovery dir creation */
+ 
++	/* for v4.0 and v4.1 callbacks: */
++	struct nfs4_cb_conn	cl_cb_conn;
++	struct rpc_clnt		*cl_cb_client;
++	atomic_t		cl_cb_set;
++
+ 	/* for nfs41 */
+ 	struct list_head	cl_sessions;
+ 	struct nfsd4_clid_slot	cl_cs_slot;	/* create_session slot */
+@@ -236,7 +238,6 @@ struct nfs4_client {
+ 	/* We currently support a single back channel with a single slot */
+ 	unsigned long		cl_cb_slot_busy;
+ 	u32			cl_cb_seq_nr;
+-	struct svc_xprt		*cl_cb_xprt;	/* 4.1 callback transport */
+ 	struct rpc_wait_queue	cl_cb_waitq;	/* backchannel callers may */
+ 						/* wait here for slots */
+ };

commit b12a05cbdfdf7e4d8cbe8fa78e995f971420086b
+Author: J. Bruce Fields 
+Date:   Thu Mar 4 11:32:59 2010 -0500
+
+    nfsd4: cl_count is unused
+    
+    Now that the shutdown sequence guarantees callbacks are shut down before
+    the client is destroyed, we no longer have a use for cl_count.
+    
+    We'll probably reinstate a reference count on the client some day, but
+    it will be held by users other than callbacks.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index e078c747f49d..5856fc8adb70 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -681,10 +681,8 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
+ static void nfsd4_cb_recall_release(void *calldata)
+ {
+ 	struct nfs4_delegation *dp = calldata;
+-	struct nfs4_client *clp = dp->dl_client;
+ 
+ 	nfs4_put_delegation(dp);
+-	put_nfs4_client(clp);
+ }
+ 
+ static const struct rpc_call_ops nfsd4_cb_recall_ops = {
+@@ -746,10 +744,8 @@ static void _nfsd4_cb_recall(struct nfs4_delegation *dp)
+ 	dp->dl_retries = 1;
+ 	status = rpc_call_async(clnt, &msg, RPC_TASK_SOFT,
+ 				&nfsd4_cb_recall_ops, dp);
+-	if (status) {
+-		put_nfs4_client(clp);
++	if (status)
+ 		nfs4_put_delegation(dp);
+-	}
+ }
+ 
+ void nfsd4_do_callback_rpc(struct work_struct *w)
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index adc51d10d435..cf650cbb814b 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -690,13 +690,6 @@ free_client(struct nfs4_client *clp)
+ 	kfree(clp);
+ }
+ 
+-void
+-put_nfs4_client(struct nfs4_client *clp)
+-{
+-	if (atomic_dec_and_test(&clp->cl_count))
+-		free_client(clp);
+-}
+-
+ static void
+ expire_client(struct nfs4_client *clp)
+ {
+@@ -735,7 +728,7 @@ expire_client(struct nfs4_client *clp)
+ 	nfsd4_set_callback_client(clp, NULL);
+ 	if (clp->cl_cb_xprt)
+ 		svc_xprt_put(clp->cl_cb_xprt);
+-	put_nfs4_client(clp);
++	free_client(clp);
+ }
+ 
+ static void copy_verf(struct nfs4_client *target, nfs4_verifier *source)
+@@ -821,7 +814,6 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir,
+ 	}
+ 
+ 	memcpy(clp->cl_recdir, recdir, HEXDIR_LEN);
+-	atomic_set(&clp->cl_count, 1);
+ 	atomic_set(&clp->cl_cb_conn.cb_set, 0);
+ 	INIT_LIST_HEAD(&clp->cl_idhash);
+ 	INIT_LIST_HEAD(&clp->cl_strhash);
+@@ -2010,7 +2002,6 @@ void nfsd_break_deleg_cb(struct file_lock *fl)
+ 	 * lock) we know the server hasn't removed the lease yet, we know
+ 	 * it's safe to take a reference: */
+ 	atomic_inc(&dp->dl_count);
+-	atomic_inc(&dp->dl_client->cl_count);
+ 
+ 	spin_lock(&recall_lock);
+ 	list_add_tail(&dp->dl_recall_lru, &del_recall_lru);
+diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
+index c4c92aea8f39..cef20abf330c 100644
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -224,7 +224,6 @@ struct nfs4_client {
+ 	clientid_t		cl_clientid;	/* generated by server */
+ 	nfs4_verifier		cl_confirm;	/* generated by server */
+ 	struct nfs4_cb_conn	cl_cb_conn;     /* callback info */
+-	atomic_t		cl_count;	/* ref count */
+ 	u32			cl_firststate;	/* recovery dir creation */
+ 
+ 	/* for nfs41 */
+@@ -388,7 +387,6 @@ extern void nfs4_lock_state(void);
+ extern void nfs4_unlock_state(void);
+ extern int nfs4_in_grace(void);
+ extern __be32 nfs4_check_open_reclaim(clientid_t *clid);
+-extern void put_nfs4_client(struct nfs4_client *clp);
+ extern void nfs4_free_stateowner(struct kref *kref);
+ extern int set_callback_cred(void);
+ extern void nfsd4_probe_callback(struct nfs4_client *clp);

commit b5a1a81e5c25fb6bb3fdc1812ba69ff6ab638fcf
+Author: J. Bruce Fields 
+Date:   Wed Mar 3 14:52:55 2010 -0500
+
+    nfsd4: don't sleep in lease-break callback
+    
+    The NFSv4 server's fl_break callback can sleep (dropping the BKL), in
+    order to allocate a new rpc task to send a recall to the client.
+    
+    As far as I can tell this doesn't cause any races in the current code,
+    but the analysis is difficult.  Also, the sleep here may complicate the
+    move away from the BKL.
+    
+    So, just schedule some work to do the job for us instead.  The work will
+    later also prove useful for restarting a call after the callback
+    information is changed.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 91eb2ea9ef0a..e078c747f49d 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -32,6 +32,7 @@
+  */
+ 
+ #include 
++#include 
+ #include "nfsd.h"
+ #include "state.h"
+ 
+@@ -692,11 +693,41 @@ static const struct rpc_call_ops nfsd4_cb_recall_ops = {
+ 	.rpc_release = nfsd4_cb_recall_release,
+ };
+ 
++static struct workqueue_struct *callback_wq;
++
++int nfsd4_create_callback_queue(void)
++{
++	callback_wq = create_singlethread_workqueue("nfsd4_callbacks");
++	if (!callback_wq)
++		return -ENOMEM;
++	return 0;
++}
++
++void nfsd4_destroy_callback_queue(void)
++{
++	destroy_workqueue(callback_wq);
++}
++
++void nfsd4_set_callback_client(struct nfs4_client *clp, struct rpc_clnt
++*new)
++{
++	struct rpc_clnt *old = clp->cl_cb_conn.cb_client;
++
++	clp->cl_cb_conn.cb_client = new;
++	/*
++	 * After this, any work that saw the old value of cb_client will
++	 * be gone:
++	 */
++	flush_workqueue(callback_wq);
++	/* So we can safely shut it down: */
++	if (old)
++		rpc_shutdown_client(old);
++}
++
+ /*
+  * called with dp->dl_count inc'ed.
+  */
+-void
+-nfsd4_cb_recall(struct nfs4_delegation *dp)
++static void _nfsd4_cb_recall(struct nfs4_delegation *dp)
+ {
+ 	struct nfs4_client *clp = dp->dl_client;
+ 	struct rpc_clnt *clnt = clp->cl_cb_conn.cb_client;
+@@ -707,6 +738,9 @@ nfsd4_cb_recall(struct nfs4_delegation *dp)
+ 	};
+ 	int status;
+ 
++	if (clnt == NULL)
++		return; /* Client is shutting down; give up. */
++
+ 	args->args_op = dp;
+ 	msg.rpc_argp = args;
+ 	dp->dl_retries = 1;
+@@ -717,3 +751,19 @@ nfsd4_cb_recall(struct nfs4_delegation *dp)
+ 		nfs4_put_delegation(dp);
+ 	}
+ }
++
++void nfsd4_do_callback_rpc(struct work_struct *w)
++{
++	/* XXX: for now, just send off delegation recall. */
++	/* In future, generalize to handle any sort of callback. */
++	struct nfsd4_callback *c = container_of(w, struct nfsd4_callback, cb_work);
++	struct nfs4_delegation *dp = container_of(c, struct nfs4_delegation, dl_recall);
++
++	_nfsd4_cb_recall(dp);
++}
++
++
++void nfsd4_cb_recall(struct nfs4_delegation *dp)
++{
++	queue_work(callback_wq, &dp->dl_recall.cb_work);
++}
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 5051ade30dfb..adc51d10d435 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -198,6 +198,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
+ 	atomic_set(&dp->dl_count, 1);
+ 	list_add(&dp->dl_perfile, &fp->fi_delegations);
+ 	list_add(&dp->dl_perclnt, &clp->cl_delegations);
++	INIT_WORK(&dp->dl_recall.cb_work, nfsd4_do_callback_rpc);
+ 	return dp;
+ }
+ 
+@@ -679,21 +680,6 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name)
+ 	return clp;
+ }
+ 
+-static void
+-shutdown_callback_client(struct nfs4_client *clp)
+-{
+-	struct rpc_clnt *clnt = clp->cl_cb_conn.cb_client;
+-
+-	if (clnt) {
+-		/*
+-		 * Callback threads take a reference on the client, so there
+-		 * should be no outstanding callbacks at this point.
+-		 */
+-		clp->cl_cb_conn.cb_client = NULL;
+-		rpc_shutdown_client(clnt);
+-	}
+-}
+-
+ static inline void
+ free_client(struct nfs4_client *clp)
+ {
+@@ -746,7 +732,7 @@ expire_client(struct nfs4_client *clp)
+ 				 se_perclnt);
+ 		release_session(ses);
+ 	}
+-	shutdown_callback_client(clp);
++	nfsd4_set_callback_client(clp, NULL);
+ 	if (clp->cl_cb_xprt)
+ 		svc_xprt_put(clp->cl_cb_xprt);
+ 	put_nfs4_client(clp);
+@@ -1392,7 +1378,7 @@ nfsd4_destroy_session(struct svc_rqst *r,
+ 	spin_unlock(&sessionid_lock);
+ 
+ 	/* wait for callbacks */
+-	shutdown_callback_client(ses->se_client);
++	nfsd4_set_callback_client(ses->se_client, NULL);
+ 	nfsd4_put_session(ses);
+ 	status = nfs_ok;
+ out:
+@@ -4004,16 +3990,27 @@ set_max_delegations(void)
+ static int
+ __nfs4_state_start(void)
+ {
++	int ret;
++
+ 	boot_time = get_seconds();
+ 	locks_start_grace(&nfsd4_manager);
+ 	printk(KERN_INFO "NFSD: starting %ld-second grace period\n",
+ 	       nfsd4_grace);
++	ret = set_callback_cred();
++	if (ret)
++		return -ENOMEM;
+ 	laundry_wq = create_singlethread_workqueue("nfsd4");
+ 	if (laundry_wq == NULL)
+ 		return -ENOMEM;
++	ret = nfsd4_create_callback_queue();
++	if (ret)
++		goto out_free_laundry;
+ 	queue_delayed_work(laundry_wq, &laundromat_work, nfsd4_grace * HZ);
+ 	set_max_delegations();
+-	return set_callback_cred();
++	return 0;
++out_free_laundry:
++	destroy_workqueue(laundry_wq);
++	return ret;
+ }
+ 
+ int
+@@ -4075,6 +4072,7 @@ nfs4_state_shutdown(void)
+ 	nfs4_lock_state();
+ 	nfs4_release_reclaim();
+ 	__nfs4_state_shutdown();
++	nfsd4_destroy_callback_queue();
+ 	nfs4_unlock_state();
+ }
+ 
+diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
+index b85437982a8d..c4c92aea8f39 100644
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -77,6 +77,7 @@ struct nfs4_rpc_args {
+ 
+ struct nfsd4_callback {
+ 	struct nfs4_rpc_args cb_args;
++	struct work_struct cb_work;
+ };
+ 
+ struct nfs4_delegation {
+@@ -391,7 +392,11 @@ extern void put_nfs4_client(struct nfs4_client *clp);
+ extern void nfs4_free_stateowner(struct kref *kref);
+ extern int set_callback_cred(void);
+ extern void nfsd4_probe_callback(struct nfs4_client *clp);
++extern void nfsd4_do_callback_rpc(struct work_struct *);
+ extern void nfsd4_cb_recall(struct nfs4_delegation *dp);
++extern int nfsd4_create_callback_queue(void);
++extern void nfsd4_destroy_callback_queue(void);
++extern void nfsd4_set_callback_client(struct nfs4_client *, struct rpc_clnt *);
+ extern void nfs4_put_delegation(struct nfs4_delegation *dp);
+ extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname);
+ extern void nfsd4_init_recdir(char *recdir_name);

commit 3c4ab2aaa90826060b1e8d4036f9bb8325f8759e
+Author: J. Bruce Fields 
+Date:   Mon Apr 19 15:12:51 2010 -0400
+
+    nfsd4: indentation cleanup
+    
+    Looks like a put-and-paste mistake.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
+index efa337739534..c28958ec216c 100644
+--- a/fs/nfsd/xdr4.h
++++ b/fs/nfsd/xdr4.h
+@@ -513,9 +513,8 @@ extern void nfsd4_store_cache_entry(struct nfsd4_compoundres *resp);
+ extern __be32 nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp,
+ 		struct nfsd4_sequence *seq);
+ extern __be32 nfsd4_exchange_id(struct svc_rqst *rqstp,
+-		struct nfsd4_compound_state *,
+-struct nfsd4_exchange_id *);
+-		extern __be32 nfsd4_create_session(struct svc_rqst *,
++		struct nfsd4_compound_state *, struct nfsd4_exchange_id *);
++extern __be32 nfsd4_create_session(struct svc_rqst *,
+ 		struct nfsd4_compound_state *,
+ 		struct nfsd4_create_session *);
+ extern __be32 nfsd4_sequence(struct svc_rqst *,

commit 408b79bcc32d7221a4975771ab6bff3d3173d530
+Author: J. Bruce Fields 
+Date:   Thu Apr 15 15:11:09 2010 -0400
+
+    nfsd4: consistent session flag setting
+    
+    We should clear these flags on any new create_session, not just on the
+    first one.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 5d86df1d1881..5051ade30dfb 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1323,12 +1323,6 @@ nfsd4_create_session(struct svc_rqst *rqstp,
+ 		cs_slot->sl_seqid++; /* from 0 to 1 */
+ 		move_to_confirmed(unconf);
+ 
+-		/*
+-		 * We do not support RDMA or persistent sessions
+-		 */
+-		cr_ses->flags &= ~SESSION4_PERSIST;
+-		cr_ses->flags &= ~SESSION4_RDMA;
+-
+ 		if (cr_ses->flags & SESSION4_BACK_CHAN) {
+ 			unconf->cl_cb_xprt = rqstp->rq_xprt;
+ 			svc_xprt_get(unconf->cl_cb_xprt);
+@@ -1348,6 +1342,12 @@ nfsd4_create_session(struct svc_rqst *rqstp,
+ 		goto out;
+ 	}
+ 
++	/*
++	 * We do not support RDMA or persistent sessions
++	 */
++	cr_ses->flags &= ~SESSION4_PERSIST;
++	cr_ses->flags &= ~SESSION4_RDMA;
++
+ 	status = alloc_init_session(rqstp, conf, cr_ses);
+ 	if (status)
+ 		goto out;

commit 9045b4b9f7f340f43de0cf687b5b52f6feaaa984
+Author: J. Bruce Fields 
+Date:   Sun Feb 21 17:53:04 2010 -0800
+
+    nfsd4: remove probe task's reference on client
+    
+    Any null probe rpc will be synchronously destroyed by the
+    rpc_shutdown_client() in expire_client(), so the rpc task cannot outlast
+    the nfs4 client.  Therefore there's no need for that task to hold a
+    reference on the client.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index b99c3f0f1d35..91eb2ea9ef0a 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -509,7 +509,6 @@ static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata)
+ 		warn_no_callback_path(clp, task->tk_status);
+ 	else
+ 		atomic_set(&clp->cl_cb_conn.cb_set, 1);
+-	put_nfs4_client(clp);
+ }
+ 
+ static const struct rpc_call_ops nfsd4_cb_probe_ops = {
+@@ -542,10 +541,8 @@ void do_probe_callback(struct nfs4_client *clp)
+ 	status = rpc_call_async(cb->cb_client, &msg,
+ 				RPC_TASK_SOFT | RPC_TASK_SOFTCONN,
+ 				&nfsd4_cb_probe_ops, (void *)clp);
+-	if (status) {
++	if (status)
+ 		warn_no_callback_path(clp, status);
+-		put_nfs4_client(clp);
+-	}
+ }
+ 
+ /*
+@@ -563,10 +560,6 @@ nfsd4_probe_callback(struct nfs4_client *clp)
+ 		warn_no_callback_path(clp, status);
+ 		return;
+ 	}
+-
+-	/* the task holds a reference to the nfs4_client struct */
+-	atomic_inc(&clp->cl_count);
+-
+ 	do_probe_callback(clp);
+ }
+ 

commit 3df796dbe97a98a6a25e6b7b88e9d326e261f371
+Author: J. Bruce Fields 
+Date:   Sun Feb 21 17:51:53 2010 -0800
+
+    nfsd4: remove dprintk
+    
+    I haven't found this useful.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 9ce58318ca8c..5d86df1d1881 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -718,9 +718,6 @@ expire_client(struct nfs4_client *clp)
+ 	struct nfs4_delegation *dp;
+ 	struct list_head reaplist;
+ 
+-	dprintk("NFSD: expire_client cl_count %d\n",
+-	                    atomic_read(&clp->cl_count));
+-
+ 	INIT_LIST_HEAD(&reaplist);
+ 	spin_lock(&recall_lock);
+ 	while (!list_empty(&clp->cl_delegations)) {

commit 147efd0dd702ce2f1ab44449bd70369405ef68fd
+Author: J. Bruce Fields 
+Date:   Sun Feb 21 17:41:19 2010 -0800
+
+    nfsd4: shutdown callbacks on expiry
+    
+    Once we've expired the client, there's no further purpose to the
+    callbacks; go ahead and shut down the callback client rather than
+    waiting for the last reference to go.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index efef7f2442d5..9ce58318ca8c 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -697,9 +697,6 @@ shutdown_callback_client(struct nfs4_client *clp)
+ static inline void
+ free_client(struct nfs4_client *clp)
+ {
+-	shutdown_callback_client(clp);
+-	if (clp->cl_cb_xprt)
+-		svc_xprt_put(clp->cl_cb_xprt);
+ 	if (clp->cl_cred.cr_group_info)
+ 		put_group_info(clp->cl_cred.cr_group_info);
+ 	kfree(clp->cl_principal);
+@@ -752,6 +749,9 @@ expire_client(struct nfs4_client *clp)
+ 				 se_perclnt);
+ 		release_session(ses);
+ 	}
++	shutdown_callback_client(clp);
++	if (clp->cl_cb_xprt)
++		svc_xprt_put(clp->cl_cb_xprt);
+ 	put_nfs4_client(clp);
+ }
+ 

commit 227f98d98d2ed7929f41426adc21f57b927354a6
+Author: J. Bruce Fields 
+Date:   Thu Feb 18 08:27:24 2010 -0800
+
+    nfsd4: preallocate nfs4_rpc_args
+    
+    Instead of allocating this small structure, just include it in the
+    delegation.
+    
+    The nfsd4_callback structure isn't really necessary yet, but we plan to
+    add to it all the information necessary to perform a callback.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index ed12ad40828b..b99c3f0f1d35 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -78,11 +78,6 @@ enum nfs_cb_opnum4 {
+ 					cb_sequence_dec_sz +            \
+ 					op_dec_sz)
+ 
+-struct nfs4_rpc_args {
+-	void				*args_op;
+-	struct nfsd4_cb_sequence	args_seq;
+-};
+-
+ /*
+ * Generic encode routines from fs/nfs/nfs4xdr.c
+ */
+@@ -676,7 +671,7 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
+ 		break;
+ 	default:
+ 		/* success, or error we can't handle */
+-		goto done;
++		return;
+ 	}
+ 	if (dp->dl_retries--) {
+ 		rpc_delay(task, 2*HZ);
+@@ -687,8 +682,6 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
+ 		atomic_set(&clp->cl_cb_conn.cb_set, 0);
+ 		warn_no_callback_path(clp, task->tk_status);
+ 	}
+-done:
+-	kfree(task->tk_msg.rpc_argp);
+ }
+ 
+ static void nfsd4_cb_recall_release(void *calldata)
+@@ -714,24 +707,19 @@ nfsd4_cb_recall(struct nfs4_delegation *dp)
+ {
+ 	struct nfs4_client *clp = dp->dl_client;
+ 	struct rpc_clnt *clnt = clp->cl_cb_conn.cb_client;
+-	struct nfs4_rpc_args *args;
++	struct nfs4_rpc_args *args = &dp->dl_recall.cb_args;
+ 	struct rpc_message msg = {
+ 		.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL],
+ 		.rpc_cred = callback_cred
+ 	};
+-	int status = -ENOMEM;
++	int status;
+ 
+-	args = kzalloc(sizeof(*args), GFP_KERNEL);
+-	if (!args)
+-		goto out;
+ 	args->args_op = dp;
+ 	msg.rpc_argp = args;
+ 	dp->dl_retries = 1;
+ 	status = rpc_call_async(clnt, &msg, RPC_TASK_SOFT,
+ 				&nfsd4_cb_recall_ops, dp);
+-out:
+ 	if (status) {
+-		kfree(args);
+ 		put_nfs4_client(clp);
+ 		nfs4_put_delegation(dp);
+ 	}
+diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
+index fefeae27f25e..b85437982a8d 100644
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -70,6 +70,15 @@ struct nfsd4_cb_sequence {
+ 	struct nfs4_client	*cbs_clp;
+ };
+ 
++struct nfs4_rpc_args {
++	void				*args_op;
++	struct nfsd4_cb_sequence	args_seq;
++};
++
++struct nfsd4_callback {
++	struct nfs4_rpc_args cb_args;
++};
++
+ struct nfs4_delegation {
+ 	struct list_head	dl_perfile;
+ 	struct list_head	dl_perclnt;
+@@ -86,6 +95,7 @@ struct nfs4_delegation {
+ 	stateid_t		dl_stateid;
+ 	struct knfsd_fh		dl_fh;
+ 	int			dl_retries;
++	struct nfsd4_callback	dl_recall;
+ };
+ 
+ /* client delegation callback info */

commit 788e69e548cc8d127b90f0de1f7b7e983d1d587a
+Author: J. Bruce Fields 
+Date:   Mon Mar 29 21:02:31 2010 -0400
+
+    svcrpc: don't hold sv_lock over svc_xprt_put()
+    
+    svc_xprt_put() can call tcp_close(), which can sleep, so we shouldn't be
+    holding this lock.
+    
+    In fact, only the xpt_list removal and the sv_tmpcnt decrement should
+    need the sv_lock here.
+    
+    Reported-by: Mi Jinlong 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
+index 8f0f1fb3dc52..c334f5413c60 100644
+--- a/net/sunrpc/svc_xprt.c
++++ b/net/sunrpc/svc_xprt.c
+@@ -892,12 +892,12 @@ void svc_delete_xprt(struct svc_xprt *xprt)
+ 	 */
+ 	if (test_bit(XPT_TEMP, &xprt->xpt_flags))
+ 		serv->sv_tmpcnt--;
++	spin_unlock_bh(&serv->sv_lock);
+ 
+ 	while ((dr = svc_deferred_dequeue(xprt)) != NULL)
+ 		kfree(dr);
+ 
+ 	svc_xprt_put(xprt);
+-	spin_unlock_bh(&serv->sv_lock);
+ }
+ 
+ void svc_close_xprt(struct svc_xprt *xprt)

commit e739cf1da48e841bc5d744a99764c1a668b4bdd2
+Merge: e7b184f199fd 57d54889cd00
+Author: J. Bruce Fields 
+Date:   Tue Mar 9 17:22:08 2010 -0500
+
+    Merge commit 'v2.6.34-rc1' into for-2.6.35-incoming
+

commit e7b184f199fd3c80b618ec8244cbda70857d2779
+Author: J. Bruce Fields 
+Date:   Tue Mar 2 11:18:40 2010 -0500
+
+    nfsd4: document lease/grace-period limits
+    
+    The current documentation here is out of date, and not quite right.
+    
+    (Future work: some user documentation would be useful.)
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index 7ab70ff212d8..413cb8ef951b 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -1208,9 +1208,6 @@ static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
+ #ifdef CONFIG_NFSD_V4
+ static ssize_t __nfsd4_write_time(struct file *file, char *buf, size_t size, time_t *time)
+ {
+-	/* if size > 10 seconds, call
+-	 * nfs4_reset_lease() then write out the new lease (seconds) as reply
+-	 */
+ 	char *mesg = buf;
+ 	int rv, i;
+ 
+@@ -1220,6 +1217,18 @@ static ssize_t __nfsd4_write_time(struct file *file, char *buf, size_t size, tim
+ 		rv = get_int(&mesg, &i);
+ 		if (rv)
+ 			return rv;
++		/*
++		 * Some sanity checking.  We don't have a reason for
++		 * these particular numbers, but problems with the
++		 * extremes are:
++		 *	- Too short: the briefest network outage may
++		 *	  cause clients to lose all their locks.  Also,
++		 *	  the frequent polling may be wasteful.
++		 *	- Too long: do you really want reboot recovery
++		 *	  to take more than an hour?  Or to make other
++		 *	  clients wait an hour before being able to
++		 *	  revoke a dead client's locks?
++		 */
+ 		if (i < 10 || i > 3600)
+ 			return -EINVAL;
+ 		*time = i;

commit efc4bb4fdd09c11f5558446e584a494c6feb43c7
+Author: J. Bruce Fields 
+Date:   Tue Mar 2 11:04:06 2010 -0500
+
+    nfsd4: allow setting grace period time
+    
+    Allow explicit configuration of the grace period time as well as the
+    lease period time.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 4471046e19e0..6edfe23694e6 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -45,7 +45,7 @@
+ 
+ /* Globals */
+ time_t nfsd4_lease = 90;     /* default lease time */
+-static time_t nfsd4_grace = 90;
++time_t nfsd4_grace = 90;
+ static time_t boot_time;
+ static u32 current_ownerid = 1;
+ static u32 current_fileid = 1;
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index 9c73caccffff..7ab70ff212d8 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -45,6 +45,7 @@ enum {
+ 	 */
+ #ifdef CONFIG_NFSD_V4
+ 	NFSD_Leasetime,
++	NFSD_Gracetime,
+ 	NFSD_RecoveryDir,
+ #endif
+ };
+@@ -69,6 +70,7 @@ static ssize_t write_ports(struct file *file, char *buf, size_t size);
+ static ssize_t write_maxblksize(struct file *file, char *buf, size_t size);
+ #ifdef CONFIG_NFSD_V4
+ static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
++static ssize_t write_gracetime(struct file *file, char *buf, size_t size);
+ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
+ #endif
+ 
+@@ -90,6 +92,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
+ 	[NFSD_MaxBlkSize] = write_maxblksize,
+ #ifdef CONFIG_NFSD_V4
+ 	[NFSD_Leasetime] = write_leasetime,
++	[NFSD_Gracetime] = write_gracetime,
+ 	[NFSD_RecoveryDir] = write_recoverydir,
+ #endif
+ };
+@@ -1261,6 +1264,21 @@ static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
+ 	return nfsd4_write_time(file, buf, size, &nfsd4_lease);
+ }
+ 
++/**
++ * write_gracetime - Set or report current NFSv4 grace period time
++ *
++ * As above, but sets the time of the NFSv4 grace period.
++ *
++ * Note this should never be set to less than the *previous*
++ * lease-period time, but we don't try to enforce this.  (In the common
++ * case (a new boot), we don't know what the previous lease time was
++ * anyway.)
++ */
++static ssize_t write_gracetime(struct file *file, char *buf, size_t size)
++{
++	return nfsd4_write_time(file, buf, size, &nfsd4_grace);
++}
++
+ extern char *nfs4_recoverydir(void);
+ 
+ static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size)
+@@ -1352,6 +1370,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
+ 		[NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO},
+ #ifdef CONFIG_NFSD_V4
+ 		[NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
++		[NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR},
+ 		[NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR},
+ #endif
+ 		/* last one */ {""}
+diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
+index b463093af255..72377761270e 100644
+--- a/fs/nfsd/nfsd.h
++++ b/fs/nfsd/nfsd.h
+@@ -228,6 +228,7 @@ extern struct timeval	nfssvc_boot;
+ #ifdef CONFIG_NFSD_V4
+ 
+ extern time_t nfsd4_lease;
++extern time_t nfsd4_grace;
+ 
+ /* before processing a COMPOUND operation, we have to check that there
+  * is enough space in the buffer for XDR encode to succeed.  otherwise,

commit f013574014816c7a557b3c52233f3620463f0b9b
+Author: J. Bruce Fields 
+Date:   Mon Mar 1 19:32:36 2010 -0500
+
+    nfsd4: reshuffle lease-setting code to allow reuse
+    
+    We'll soon allow setting the grace period, so we'll want to share this
+    code.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index 6738e9d8a83d..9c73caccffff 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -1203,26 +1203,36 @@ static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
+ }
+ 
+ #ifdef CONFIG_NFSD_V4
+-static ssize_t __write_leasetime(struct file *file, char *buf, size_t size)
++static ssize_t __nfsd4_write_time(struct file *file, char *buf, size_t size, time_t *time)
+ {
+ 	/* if size > 10 seconds, call
+ 	 * nfs4_reset_lease() then write out the new lease (seconds) as reply
+ 	 */
+ 	char *mesg = buf;
+-	int rv, lease;
++	int rv, i;
+ 
+ 	if (size > 0) {
+ 		if (nfsd_serv)
+ 			return -EBUSY;
+-		rv = get_int(&mesg, &lease);
++		rv = get_int(&mesg, &i);
+ 		if (rv)
+ 			return rv;
+-		if (lease < 10 || lease > 3600)
++		if (i < 10 || i > 3600)
+ 			return -EINVAL;
+-		nfsd4_lease = lease;
++		*time = i;
+ 	}
+ 
+-	return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%ld\n", nfsd4_lease);
++	return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%ld\n", *time);
++}
++
++static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size, time_t *time)
++{
++	ssize_t rv;
++
++	mutex_lock(&nfsd_mutex);
++	rv = __nfsd4_write_time(file, buf, size, time);
++	mutex_unlock(&nfsd_mutex);
++	return rv;
+ }
+ 
+ /**
+@@ -1248,12 +1258,7 @@ static ssize_t __write_leasetime(struct file *file, char *buf, size_t size)
+  */
+ static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
+ {
+-	ssize_t rv;
+-
+-	mutex_lock(&nfsd_mutex);
+-	rv = __write_leasetime(file, buf, size);
+-	mutex_unlock(&nfsd_mutex);
+-	return rv;
++	return nfsd4_write_time(file, buf, size, &nfsd4_lease);
+ }
+ 
+ extern char *nfs4_recoverydir(void);

commit f958a1320ff7a1e0e861d3c90de6da12a88839dc
+Author: J. Bruce Fields 
+Date:   Mon Mar 1 19:43:02 2010 -0500
+
+    nfsd4: remove unnecessary lease-setting function
+    
+    This is another layer of indirection that doesn't really buy us
+    anything.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index eb8d124ec14d..4471046e19e0 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -4115,15 +4115,3 @@ nfs4_recoverydir(void)
+ {
+ 	return user_recovery_dirname;
+ }
+-
+-/*
+- * Called when leasetime is changed.
+- *
+- * nfsd4_lease is protected by nfsd_mutex since it's only really accessed
+- * when nfsd is starting
+- */
+-void
+-nfs4_reset_lease(time_t leasetime)
+-{
+-	nfsd4_lease = leasetime;
+-}
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index 8bff6741b1e6..6738e9d8a83d 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -1219,7 +1219,7 @@ static ssize_t __write_leasetime(struct file *file, char *buf, size_t size)
+ 			return rv;
+ 		if (lease < 10 || lease > 3600)
+ 			return -EINVAL;
+-		nfs4_reset_lease(lease);
++		nfsd4_lease = lease;
+ 	}
+ 
+ 	return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%ld\n", nfsd4_lease);

commit e46b498c84163e86e2627c30bca298c968664f65
+Author: J. Bruce Fields 
+Date:   Mon Mar 1 19:21:21 2010 -0500
+
+    nfsd4: simplify lease/grace interaction
+    
+    The original code here assumed we'd allow the user to change the lease
+    any time, but only allow the change to take effect on restart.  Since
+    then we modified the code to allow setting the lease on when the server
+    is down.  Update the rest of the code to reflect that fact, clarify
+    variable names, and add document.
+    
+    Also, the code insisted that the grace period always be the longer of
+    the old and new lease periods, but that's overly conservative--as long
+    as it lasts at least the old lease period, old clients should still know
+    to recover in time.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index cc9164a34bec..eb8d124ec14d 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -45,7 +45,7 @@
+ 
+ /* Globals */
+ time_t nfsd4_lease = 90;     /* default lease time */
+-static time_t user_lease_time = 90;
++static time_t nfsd4_grace = 90;
+ static time_t boot_time;
+ static u32 current_ownerid = 1;
+ static u32 current_fileid = 1;
+@@ -2551,6 +2551,12 @@ nfsd4_end_grace(void)
+ 	dprintk("NFSD: end of grace period\n");
+ 	nfsd4_recdir_purge_old();
+ 	locks_end_grace(&nfsd4_manager);
++	/*
++	 * Now that every NFSv4 client has had the chance to recover and
++	 * to see the (possibly new, possibly shorter) lease time, we
++	 * can safely set the next grace time to the current lease time:
++	 */
++	nfsd4_grace = nfsd4_lease;
+ }
+ 
+ static time_t
+@@ -3973,12 +3979,6 @@ nfsd4_load_reboot_recovery_data(void)
+ 		printk("NFSD: Failure reading reboot recovery data\n");
+ }
+ 
+-unsigned long
+-get_nfs4_grace_period(void)
+-{
+-	return max(user_lease_time, nfsd4_lease) * HZ;
+-}
+-
+ /*
+  * Since the lifetime of a delegation isn't limited to that of an open, a
+  * client may quite reasonably hang on to a delegation as long as it has
+@@ -4005,18 +4005,14 @@ set_max_delegations(void)
+ static int
+ __nfs4_state_start(void)
+ {
+-	unsigned long grace_time;
+-
+ 	boot_time = get_seconds();
+-	grace_time = get_nfs4_grace_period();
+-	nfsd4_lease = user_lease_time;
+ 	locks_start_grace(&nfsd4_manager);
+ 	printk(KERN_INFO "NFSD: starting %ld-second grace period\n",
+-	       grace_time/HZ);
++	       nfsd4_grace);
+ 	laundry_wq = create_singlethread_workqueue("nfsd4");
+ 	if (laundry_wq == NULL)
+ 		return -ENOMEM;
+-	queue_delayed_work(laundry_wq, &laundromat_work, grace_time);
++	queue_delayed_work(laundry_wq, &laundromat_work, nfsd4_grace * HZ);
+ 	set_max_delegations();
+ 	return set_callback_cred();
+ }
+@@ -4123,17 +4119,11 @@ nfs4_recoverydir(void)
+ /*
+  * Called when leasetime is changed.
+  *
+- * The only way the protocol gives us to handle on-the-fly lease changes is to
+- * simulate a reboot.  Instead of doing that, we just wait till the next time
+- * we start to register any changes in lease time.  If the administrator
+- * really wants to change the lease time *now*, they can go ahead and bring
+- * nfsd down and then back up again after changing the lease time.
+- *
+- * user_lease_time is protected by nfsd_mutex since it's only really accessed
++ * nfsd4_lease is protected by nfsd_mutex since it's only really accessed
+  * when nfsd is starting
+  */
+ void
+ nfs4_reset_lease(time_t leasetime)
+ {
+-	user_lease_time = leasetime;
++	nfsd4_lease = leasetime;
+ }

commit cf07d2ea43e5c22149435ee9002cb737eac20eca
+Author: J. Bruce Fields 
+Date:   Sun Feb 28 23:20:19 2010 -0500
+
+    nfsd4: simplify references to nfsd4 lease time
+    
+    Instead of accessing the lease time directly, some users call
+    nfs4_lease_time(), and some a macro, NFSD_LEASE_TIME, defined as
+    nfs4_lease_time().  Neither layer of indirection serves any purpose.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 4bc22c763de7..ed12ad40828b 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -455,7 +455,7 @@ static struct rpc_program cb_program = {
+ 
+ static int max_cb_time(void)
+ {
+-	return max(NFSD_LEASE_TIME/10, (time_t)1) * HZ;
++	return max(nfsd4_lease/10, (time_t)1) * HZ;
+ }
+ 
+ /* Reference counting, callback cleanup, etc., all look racy as heck.
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 3a20c09353ed..cc9164a34bec 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -44,7 +44,7 @@
+ #define NFSDDBG_FACILITY                NFSDDBG_PROC
+ 
+ /* Globals */
+-static time_t lease_time = 90;     /* default lease time */
++time_t nfsd4_lease = 90;     /* default lease time */
+ static time_t user_lease_time = 90;
+ static time_t boot_time;
+ static u32 current_ownerid = 1;
+@@ -2560,9 +2560,9 @@ nfs4_laundromat(void)
+ 	struct nfs4_stateowner *sop;
+ 	struct nfs4_delegation *dp;
+ 	struct list_head *pos, *next, reaplist;
+-	time_t cutoff = get_seconds() - NFSD_LEASE_TIME;
+-	time_t t, clientid_val = NFSD_LEASE_TIME;
+-	time_t u, test_val = NFSD_LEASE_TIME;
++	time_t cutoff = get_seconds() - nfsd4_lease;
++	time_t t, clientid_val = nfsd4_lease;
++	time_t u, test_val = nfsd4_lease;
+ 
+ 	nfs4_lock_state();
+ 
+@@ -2602,7 +2602,7 @@ nfs4_laundromat(void)
+ 		list_del_init(&dp->dl_recall_lru);
+ 		unhash_delegation(dp);
+ 	}
+-	test_val = NFSD_LEASE_TIME;
++	test_val = nfsd4_lease;
+ 	list_for_each_safe(pos, next, &close_lru) {
+ 		sop = list_entry(pos, struct nfs4_stateowner, so_close_lru);
+ 		if (time_after((unsigned long)sop->so_time, (unsigned long)cutoff)) {
+@@ -2672,7 +2672,7 @@ EXPIRED_STATEID(stateid_t *stateid)
+ {
+ 	if (time_before((unsigned long)boot_time,
+ 			((unsigned long)stateid->si_boot)) &&
+-	    time_before((unsigned long)(stateid->si_boot + lease_time), get_seconds())) {
++	    time_before((unsigned long)(stateid->si_boot + nfsd4_lease), get_seconds())) {
+ 		dprintk("NFSD: expired stateid " STATEID_FMT "!\n",
+ 			STATEID_VAL(stateid));
+ 		return 1;
+@@ -3976,7 +3976,7 @@ nfsd4_load_reboot_recovery_data(void)
+ unsigned long
+ get_nfs4_grace_period(void)
+ {
+-	return max(user_lease_time, lease_time) * HZ;
++	return max(user_lease_time, nfsd4_lease) * HZ;
+ }
+ 
+ /*
+@@ -4009,7 +4009,7 @@ __nfs4_state_start(void)
+ 
+ 	boot_time = get_seconds();
+ 	grace_time = get_nfs4_grace_period();
+-	lease_time = user_lease_time;
++	nfsd4_lease = user_lease_time;
+ 	locks_start_grace(&nfsd4_manager);
+ 	printk(KERN_INFO "NFSD: starting %ld-second grace period\n",
+ 	       grace_time/HZ);
+@@ -4036,12 +4036,6 @@ nfs4_state_start(void)
+ 	return 0;
+ }
+ 
+-time_t
+-nfs4_lease_time(void)
+-{
+-	return lease_time;
+-}
+-
+ static void
+ __nfs4_state_shutdown(void)
+ {
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index c458fb11c957..f61bd736152b 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -1899,7 +1899,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
+ 	if (bmval0 & FATTR4_WORD0_LEASE_TIME) {
+ 		if ((buflen -= 4) < 0)
+ 			goto out_resource;
+-		WRITE32(NFSD_LEASE_TIME);
++		WRITE32(nfsd4_lease);
+ 	}
+ 	if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) {
+ 		if ((buflen -= 4) < 0)
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index 0f0e77f2012f..8bff6741b1e6 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -1203,8 +1203,6 @@ static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
+ }
+ 
+ #ifdef CONFIG_NFSD_V4
+-extern time_t nfs4_leasetime(void);
+-
+ static ssize_t __write_leasetime(struct file *file, char *buf, size_t size)
+ {
+ 	/* if size > 10 seconds, call
+@@ -1224,8 +1222,7 @@ static ssize_t __write_leasetime(struct file *file, char *buf, size_t size)
+ 		nfs4_reset_lease(lease);
+ 	}
+ 
+-	return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%ld\n",
+-							nfs4_lease_time());
++	return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%ld\n", nfsd4_lease);
+ }
+ 
+ /**
+diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
+index e942a1aaac92..b463093af255 100644
+--- a/fs/nfsd/nfsd.h
++++ b/fs/nfsd/nfsd.h
+@@ -82,7 +82,6 @@ int nfs4_state_init(void);
+ void nfsd4_free_slabs(void);
+ int nfs4_state_start(void);
+ void nfs4_state_shutdown(void);
+-time_t nfs4_lease_time(void);
+ void nfs4_reset_lease(time_t leasetime);
+ int nfs4_reset_recoverydir(char *recdir);
+ #else
+@@ -90,7 +89,6 @@ static inline int nfs4_state_init(void) { return 0; }
+ static inline void nfsd4_free_slabs(void) { }
+ static inline int nfs4_state_start(void) { return 0; }
+ static inline void nfs4_state_shutdown(void) { }
+-static inline time_t nfs4_lease_time(void) { return 0; }
+ static inline void nfs4_reset_lease(time_t leasetime) { }
+ static inline int nfs4_reset_recoverydir(char *recdir) { return 0; }
+ #endif
+@@ -229,6 +227,8 @@ extern struct timeval	nfssvc_boot;
+ 
+ #ifdef CONFIG_NFSD_V4
+ 
++extern time_t nfsd4_lease;
++
+ /* before processing a COMPOUND operation, we have to check that there
+  * is enough space in the buffer for XDR encode to succeed.  otherwise,
+  * we might process an operation with side effects, and be unable to
+@@ -247,7 +247,6 @@ extern struct timeval	nfssvc_boot;
+ #define	COMPOUND_SLACK_SPACE		140    /* OP_GETFH */
+ #define COMPOUND_ERR_SLACK_SPACE	12     /* OP_SETATTR */
+ 
+-#define NFSD_LEASE_TIME                 (nfs4_lease_time())
+ #define NFSD_LAUNDROMAT_MINTIMEOUT      10   /* seconds */
+ 
+ /*

commit 4ea41e2de5bba756858bb40f964e3490b6d1a25c
+Merge: 8d75da8afd06 398007f863a4
+Author: J. Bruce Fields 
+Date:   Thu Mar 4 12:03:16 2010 -0500
+
+    Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs into for-2.6.34-incoming
+    
+    Resolve merge conflict in fs/xfs/linux-2.6/xfs_export.c.
+
+diff --cc fs/xfs/linux-2.6/xfs_export.c
+index 8f4d70789e3f,87b8cbd23d4b..846b75aeb2ab
+--- a/fs/xfs/linux-2.6/xfs_export.c
++++ b/fs/xfs/linux-2.6/xfs_export.c
+@@@ -216,24 -215,6 +216,24 @@@ xfs_fs_get_parent
+  	return d_obtain_alias(VFS_I(cip));
+  }
+  
+ +STATIC int
+ +xfs_fs_nfs_commit_metadata(
+ +	struct inode		*inode)
+ +{
+ +	struct xfs_inode	*ip = XFS_I(inode);
+ +	struct xfs_mount	*mp = ip->i_mount;
+ +	int			error = 0;
+ +
+ +	xfs_ilock(ip, XFS_ILOCK_SHARED);
+ +	if (xfs_ipincount(ip)) {
+- 		error = _xfs_log_force(mp, ip->i_itemp->ili_last_lsn,
+- 				XFS_LOG_FORCE | XFS_LOG_SYNC, NULL);
+++		error = _xfs_log_force_lsn(mp, ip->i_itemp->ili_last_lsn,
+++				XFS_LOG_SYNC, NULL);
+ +	}
+ +	xfs_iunlock(ip, XFS_ILOCK_SHARED);
+ +
+ +	return error;
+ +}
+ +
+  const struct export_operations xfs_export_operations = {
+  	.encode_fh		= xfs_fs_encode_fh,
+  	.fh_to_dentry		= xfs_fs_fh_to_dentry,

commit 8d75da8afd068fa58b35e69c7c8c46770d9e7a98
+Author: J. Bruce Fields 
+Date:   Wed Mar 3 16:13:29 2010 -0500
+
+    nfsd4: fix minor memory leak
+    
+    There's no need to allocate this cred more than once.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 8fa412ce8021..4bc22c763de7 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -525,6 +525,8 @@ static struct rpc_cred *callback_cred;
+ 
+ int set_callback_cred(void)
+ {
++	if (callback_cred)
++		return 0;
+ 	callback_cred = rpc_lookup_machine_cred();
+ 	if (!callback_cred)
+ 		return -ENOMEM;

commit ccdb357ccb77cc4cbe4f7abee9efd19957f0753a
+Author: J. Bruce Fields 
+Date:   Tue Mar 2 15:49:21 2010 -0500
+
+    svcrpc: treat uid's as unsigned
+    
+    We should consistently treat uid's as unsigned--it's confusing when
+    the display of uid's in the cache contents isn't consistent with their
+    representation in upcalls.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
+index 97f0e9e12024..afdcb0459a83 100644
+--- a/net/sunrpc/svcauth_unix.c
++++ b/net/sunrpc/svcauth_unix.c
+@@ -624,7 +624,7 @@ static int unix_gid_show(struct seq_file *m,
+ 	else
+ 		glen = 0;
+ 
+-	seq_printf(m, "%d %d:", ug->uid, glen);
++	seq_printf(m, "%u %d:", ug->uid, glen);
+ 	for (i = 0; i < glen; i++)
+ 		seq_printf(m, " %d", GROUP_AT(ug->gi, i));
+ 	seq_printf(m, "\n");

commit 1b644b6e6f6160ae35ce4b52c2ca89ed3e356e18
+Author: J. Bruce Fields 
+Date:   Sun Feb 28 16:33:31 2010 -0500
+
+    Revert "sunrpc: move the close processing after do recvfrom method"
+    
+    This reverts commit b0401d725334a94d57335790b8ac2404144748ee, which
+    moved svc_delete_xprt() outside of XPT_BUSY, and allowed it to be called
+    after svc_xpt_recived(), removing its last reference and destroying it
+    after it had already been queued for future processing.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
+index 818c4c365b28..8f0f1fb3dc52 100644
+--- a/net/sunrpc/svc_xprt.c
++++ b/net/sunrpc/svc_xprt.c
+@@ -706,7 +706,10 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
+ 	spin_unlock_bh(&pool->sp_lock);
+ 
+ 	len = 0;
+-	if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) {
++	if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) {
++		dprintk("svc_recv: found XPT_CLOSE\n");
++		svc_delete_xprt(xprt);
++	} else if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) {
+ 		struct svc_xprt *newxpt;
+ 		newxpt = xprt->xpt_ops->xpo_accept(xprt);
+ 		if (newxpt) {
+@@ -732,7 +735,7 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
+ 			svc_xprt_received(newxpt);
+ 		}
+ 		svc_xprt_received(xprt);
+-	} else if (!test_bit(XPT_CLOSE, &xprt->xpt_flags)) {
++	} else {
+ 		dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n",
+ 			rqstp, pool->sp_id, xprt,
+ 			atomic_read(&xprt->xpt_ref.refcount));
+@@ -745,11 +748,6 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
+ 		dprintk("svc: got len=%d\n", len);
+ 	}
+ 
+-	if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) {
+-		dprintk("svc_recv: found XPT_CLOSE\n");
+-		svc_delete_xprt(xprt);
+-	}
+-
+ 	/* No data, incomplete (TCP) read, or accept() */
+ 	if (len == 0 || len == -EAGAIN) {
+ 		rqstp->rq_res.len = 0;

commit f5822754ea006563e1bf0a1f43faaad49c0d8bb2
+Author: J. Bruce Fields 
+Date:   Sun Feb 28 16:32:51 2010 -0500
+
+    Revert "sunrpc: fix peername failed on closed listener"
+    
+    This reverts commit b292cf9ce70d221c3f04ff62db5ab13d9a249ca8.  The
+    commit that it attempted to patch up,
+    b0401d725334a94d57335790b8ac2404144748ee, was fundamentally wrong, and
+    will also be reverted.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
+index 09838300dac4..818c4c365b28 100644
+--- a/net/sunrpc/svc_xprt.c
++++ b/net/sunrpc/svc_xprt.c
+@@ -706,8 +706,7 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
+ 	spin_unlock_bh(&pool->sp_lock);
+ 
+ 	len = 0;
+-	if (test_bit(XPT_LISTENER, &xprt->xpt_flags) &&
+-	    !test_bit(XPT_CLOSE, &xprt->xpt_flags)) {
++	if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) {
+ 		struct svc_xprt *newxpt;
+ 		newxpt = xprt->xpt_ops->xpo_accept(xprt);
+ 		if (newxpt) {

commit 260c64d23532caf19abb77e696971da05c388489
+Author: J. Bruce Fields 
+Date:   Mon Feb 8 13:42:26 2010 -0500
+
+    Revert "nfsd4: fix error return when pseudoroot missing"
+    
+    Commit f39bde24b275ddc45d fixed the error return from PUTROOTFH in the
+    case where there is no pseudofilesystem.
+    
+    This is really a case we shouldn't hit on a correctly configured server:
+    in the absence of a root filehandle, there's no point accepting version
+    4 NFS rpc calls at all.
+    
+    But the shared responsibility between kernel and userspace here means
+    the kernel on its own can't eliminate the possiblity of this happening.
+    And we have indeed gotten this wrong in distro's, so new client-side
+    mount code that attempts to negotiate v4 by default first has to work
+    around this case.
+    
+    Therefore when commit f39bde24b275ddc45d arrived at roughly the same
+    time as the new v4-default mount code, which explicitly checked only for
+    the previous error, the result was previously fine mounts suddenly
+    failing.
+    
+    We'll fix both sides for now: revert the error change, and make the
+    client-side mount workaround more robust.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
+index c487810a2366..a0c4016413f1 100644
+--- a/fs/nfsd/export.c
++++ b/fs/nfsd/export.c
+@@ -1316,19 +1316,11 @@ rqst_exp_parent(struct svc_rqst *rqstp, struct path *path)
+ 
+ static struct svc_export *find_fsidzero_export(struct svc_rqst *rqstp)
+ {
+-	struct svc_export *exp;
+ 	u32 fsidv[2];
+ 
+ 	mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL);
+ 
+-	exp = rqst_exp_find(rqstp, FSID_NUM, fsidv);
+-	/*
+-	 * We shouldn't have accepting an nfsv4 request at all if we
+-	 * don't have a pseudoexport!:
+-	 */
+-	if (IS_ERR(exp) && PTR_ERR(exp) == -ENOENT)
+-		exp = ERR_PTR(-ESERVERFAULT);
+-	return exp;
++	return rqst_exp_find(rqstp, FSID_NUM, fsidv);
+ }
+ 
+ /*

commit 73834d6f90f6833663f9effd4cf9b79b63bc36e1
+Author: J. Bruce Fields 
+Date:   Wed Jan 20 17:17:04 2010 -0500
+
+    nfsd: 4.1 has an rfc number
+    
+    No need to refer to an internet draft; there's an RFC now.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/Documentation/filesystems/nfs/nfs41-server.txt b/Documentation/filesystems/nfs/nfs41-server.txt
+index 1bd0d0c05171..6a53a84afc72 100644
+--- a/Documentation/filesystems/nfs/nfs41-server.txt
++++ b/Documentation/filesystems/nfs/nfs41-server.txt
+@@ -17,8 +17,7 @@ kernels must turn 4.1 on or off *before* turning support for version 4
+ on or off; rpc.nfsd does this correctly.)
+ 
+ The NFSv4 minorversion 1 (NFSv4.1) implementation in nfsd is based
+-on the latest NFSv4.1 Internet Draft:
+-http://tools.ietf.org/html/draft-ietf-nfsv4-minorversion1-29
++on RFC 5661.
+ 
+ From the many new features in NFSv4.1 the current implementation
+ focuses on the mandatory-to-implement NFSv4.1 Sessions, providing
+@@ -44,7 +43,7 @@ interoperability problems with future clients.  Known issues:
+ 	  trunking, but this is a mandatory feature, and its use is
+ 	  recommended to clients in a number of places.  (E.g. to ensure
+ 	  timely renewal in case an existing connection's retry timeouts
+-	  have gotten too long; see section 8.3 of the draft.)
++	  have gotten too long; see section 8.3 of the RFC.)
+ 	  Therefore, lack of this feature may cause future clients to
+ 	  fail.
+ 	- Incomplete backchannel support: incomplete backchannel gss

commit 3d354cbc43db36e7e8b27ed78901064b87864ffc
+Author: J. Bruce Fields 
+Date:   Sun Dec 20 10:43:35 2009 -0500
+
+    nfsd: fix "insecure" export option
+    
+    A typo in 12045a6ee9908b "nfsd: let "insecure" flag vary by
+    pseudoflavor" reversed the sense of the "insecure" flag.
+    
+    Reported-by: Michael Guntsche 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
+index 1c12177b908c..55c8e63af0be 100644
+--- a/fs/nfsd/nfsfh.c
++++ b/fs/nfsd/nfsfh.c
+@@ -89,7 +89,7 @@ static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp,
+ 	int flags = nfsexp_flags(rqstp, exp);
+ 
+ 	/* Check if the request originated from a secure port. */
+-	if (!rqstp->rq_secure && (flags & NFSEXP_INSECURE_PORT)) {
++	if (!rqstp->rq_secure && !(flags & NFSEXP_INSECURE_PORT)) {
+ 		RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
+ 		dprintk(KERN_WARNING
+ 		       "nfsd: request from insecure port %s!\n",

commit f69ac2f5a36948e1adf071074414c5d1907b89b7
+Author: J. Bruce Fields 
+Date:   Fri Dec 18 16:31:34 2009 -0500
+
+    nfsd: fix "insecure" export option
+    
+    A typo in 12045a6ee9908b "nfsd: let "insecure" flag vary by
+    pseudoflavor" reversed the sense of the "insecure" flag.
+    
+    Reported-by: Michael Guntsche 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
+index 1c12177b908c..55c8e63af0be 100644
+--- a/fs/nfsd/nfsfh.c
++++ b/fs/nfsd/nfsfh.c
+@@ -89,7 +89,7 @@ static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp,
+ 	int flags = nfsexp_flags(rqstp, exp);
+ 
+ 	/* Check if the request originated from a secure port. */
+-	if (!rqstp->rq_secure && (flags & NFSEXP_INSECURE_PORT)) {
++	if (!rqstp->rq_secure && !(flags & NFSEXP_INSECURE_PORT)) {
+ 		RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
+ 		dprintk(KERN_WARNING
+ 		       "nfsd: request from insecure port %s!\n",

commit 7663dacd926584093dfc350892792054692b6cb3
+Author: J. Bruce Fields 
+Date:   Fri Dec 4 19:49:00 2009 -0500
+
+    nfsd: remove pointless paths in file headers
+    
+    The new .h files have paths at the top that are now out of date.  While
+    we're here, just remove all of those from fs/nfsd; they never served any
+    purpose.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
+index 71209d4993d0..79717a40daba 100644
+--- a/fs/nfsd/auth.c
++++ b/fs/nfsd/auth.c
+@@ -1,8 +1,4 @@
+-/*
+- * linux/fs/nfsd/auth.c
+- *
+- * Copyright (C) 1995, 1996 Olaf Kirch 
+- */
++/* Copyright (C) 1995, 1996 Olaf Kirch  */
+ 
+ #include 
+ #include "nfsd.h"
+diff --git a/fs/nfsd/cache.h b/fs/nfsd/cache.h
+index a165425dea41..d892be61016c 100644
+--- a/fs/nfsd/cache.h
++++ b/fs/nfsd/cache.h
+@@ -1,6 +1,4 @@
+ /*
+- * include/linux/nfsd/cache.h
+- *
+  * Request reply cache. This was heavily inspired by the
+  * implementation in 4.3BSD/4.4BSD.
+  *
+diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
+index b26a3644fbb9..c487810a2366 100644
+--- a/fs/nfsd/export.c
++++ b/fs/nfsd/export.c
+@@ -1,7 +1,5 @@
+ #define MSNFS	/* HACK HACK */
+ /*
+- * linux/fs/nfsd/export.c
+- *
+  * NFS exporting and validation.
+  *
+  * We maintain a list of clients, each of which has a list of
+diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
+index 6f12777ed227..0c6d81670137 100644
+--- a/fs/nfsd/lockd.c
++++ b/fs/nfsd/lockd.c
+@@ -1,6 +1,4 @@
+ /*
+- * linux/fs/nfsd/lockd.c
+- *
+  * This file contains all the stubs needed when communicating with lockd.
+  * This level of indirection is necessary so we can run nfsd+lockd without
+  * requiring the nfs client to be compiled in/loaded, and vice versa.
+diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
+index 874e2a94bf4f..f20589d2ae27 100644
+--- a/fs/nfsd/nfs2acl.c
++++ b/fs/nfsd/nfs2acl.c
+@@ -1,6 +1,4 @@
+ /*
+- * linux/fs/nfsd/nfs2acl.c
+- *
+  * Process version 2 NFSACL requests.
+  *
+  * Copyright (C) 2002-2003 Andreas Gruenbacher 
+diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c
+index c6011ddbadc0..e0c4846bad92 100644
+--- a/fs/nfsd/nfs3acl.c
++++ b/fs/nfsd/nfs3acl.c
+@@ -1,6 +1,4 @@
+ /*
+- * linux/fs/nfsd/nfs3acl.c
+- *
+  * Process version 3 NFSACL requests.
+  *
+  * Copyright (C) 2002-2003 Andreas Gruenbacher 
+diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
+index 90b19ca75b34..3d68f45a37b9 100644
+--- a/fs/nfsd/nfs3proc.c
++++ b/fs/nfsd/nfs3proc.c
+@@ -1,6 +1,4 @@
+ /*
+- * linux/fs/nfsd/nfs3proc.c
+- *
+  * Process version 3 NFS requests.
+  *
+  * Copyright (C) 1996, 1997, 1998 Olaf Kirch 
+diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
+index c523bb88c10b..2a533a0af2a9 100644
+--- a/fs/nfsd/nfs3xdr.c
++++ b/fs/nfsd/nfs3xdr.c
+@@ -1,6 +1,4 @@
+ /*
+- * linux/fs/nfsd/nfs3xdr.c
+- *
+  * XDR support for nfsd/protocol version 3.
+  *
+  * Copyright (C) 1995, 1996, 1997 Olaf Kirch 
+diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
+index d6f0cea4babe..88150685df34 100644
+--- a/fs/nfsd/nfs4acl.c
++++ b/fs/nfsd/nfs4acl.c
+@@ -1,6 +1,4 @@
+ /*
+- *  fs/nfs4acl/acl.c
+- *
+  *  Common NFSv4 ACL handling code.
+  *
+  *  Copyright (c) 2002, 2003 The Regents of the University of Michigan.
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index f7a315827638..c6eed2a3b093 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -1,6 +1,4 @@
+ /*
+- *  linux/fs/nfsd/nfs4callback.c
+- *
+  *  Copyright (c) 2001 The Regents of the University of Michigan.
+  *  All rights reserved.
+  *
+diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
+index 8e518cd5ac1b..6e2983b27f3c 100644
+--- a/fs/nfsd/nfs4idmap.c
++++ b/fs/nfsd/nfs4idmap.c
+@@ -1,6 +1,4 @@
+ /*
+- *  fs/nfsd/nfs4idmap.c
+- *
+  *  Mapping of UID/GIDs to name and vice versa.
+  *
+  *  Copyright (c) 2002, 2003 The Regents of the University of
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index e2b5666f25d1..37514c469846 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -1,6 +1,4 @@
+ /*
+- *  fs/nfsd/nfs4proc.c
+- *
+  *  Server-side procedures for NFSv4.
+  *
+  *  Copyright (c) 2002 The Regents of the University of Michigan.
+diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
+index 6744e7f2da0e..5a754f7b71ed 100644
+--- a/fs/nfsd/nfs4recover.c
++++ b/fs/nfsd/nfs4recover.c
+@@ -1,6 +1,4 @@
+ /*
+-*  linux/fs/nfsd/nfs4recover.c
+-*
+ *  Copyright (c) 2004 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 2923e6c1da18..f19ed866c95f 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1,6 +1,4 @@
+ /*
+-*  linux/fs/nfsd/nfs4state.c
+-*
+ *  Copyright (c) 2001 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
+index 18aa9729a380..da08560c4818 100644
+--- a/fs/nfsd/nfscache.c
++++ b/fs/nfsd/nfscache.c
+@@ -1,6 +1,4 @@
+ /*
+- * linux/fs/nfsd/nfscache.c
+- *
+  * Request reply cache. This is currently a global cache, but this may
+  * change in the future and be a per-client cache.
+  *
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index e7051ac4dc73..2604c3e70ea5 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -1,6 +1,4 @@
+ /*
+- * linux/fs/nfsd/nfsctl.c
+- *
+  * Syscall interface to knfsd.
+  *
+  * Copyright (C) 1995, 1996 Olaf Kirch 
+diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
+index ac121ad16540..e942a1aaac92 100644
+--- a/fs/nfsd/nfsd.h
++++ b/fs/nfsd/nfsd.h
+@@ -1,6 +1,4 @@
+ /*
+- * linux/include/linux/nfsd/nfsd.h
+- *
+  * Hodge-podge collection of knfsd-related stuff.
+  * I will sort this out later.
+  *
+diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
+index 44812c32e51e..1c12177b908c 100644
+--- a/fs/nfsd/nfsfh.c
++++ b/fs/nfsd/nfsfh.c
+@@ -1,6 +1,4 @@
+ /*
+- * linux/fs/nfsd/nfsfh.c
+- *
+  * NFS server file handle treatment.
+  *
+  * Copyright (C) 1995, 1996 Olaf Kirch 
+diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
+index 21a5f793c3d1..a047ad6111ef 100644
+--- a/fs/nfsd/nfsproc.c
++++ b/fs/nfsd/nfsproc.c
+@@ -1,7 +1,4 @@
+ /*
+- * nfsproc2.c	Process version 2 NFS requests.
+- * linux/fs/nfsd/nfs2proc.c
+- * 
+  * Process version 2 NFS requests.
+  *
+  * Copyright (C) 1995-1997 Olaf Kirch 
+diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
+index b520ce10bd15..171699eb07c8 100644
+--- a/fs/nfsd/nfssvc.c
++++ b/fs/nfsd/nfssvc.c
+@@ -1,6 +1,4 @@
+ /*
+- * linux/fs/nfsd/nfssvc.c
+- *
+  * Central processing for nfsd.
+  *
+  * Authors:	Olaf Kirch (okir@monad.swb.de)
+diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
+index 3bec831704af..4ce005dbf3e6 100644
+--- a/fs/nfsd/nfsxdr.c
++++ b/fs/nfsd/nfsxdr.c
+@@ -1,6 +1,4 @@
+ /*
+- * linux/fs/nfsd/nfsxdr.c
+- *
+  * XDR support for nfsd
+  *
+  * Copyright (C) 1995, 1996 Olaf Kirch 
+diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
+index 775b8d281d6a..fefeae27f25e 100644
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -1,6 +1,4 @@
+ /*
+- *  linux/include/nfsd/state.h
+- *
+  *  Copyright (c) 2001 The Regents of the University of Michigan.
+  *  All rights reserved.
+  *
+diff --git a/fs/nfsd/stats.c b/fs/nfsd/stats.c
+index 3fc69dfd3091..5232d3e8fb2f 100644
+--- a/fs/nfsd/stats.c
++++ b/fs/nfsd/stats.c
+@@ -1,6 +1,4 @@
+ /*
+- * linux/fs/nfsd/stats.c
+- *
+  * procfs-based user access to knfsd statistics
+  *
+  * /proc/net/rpc/nfsd
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index f6ca32b07e11..e3ef3ec0efd0 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -1,7 +1,5 @@
+ #define MSNFS	/* HACK HACK */
+ /*
+- * linux/fs/nfsd/vfs.c
+- *
+  * File operations used by nfsd. Some of these have been ripped from
+  * other parts of the kernel because they weren't exported, others
+  * are partial duplicates with added or changed functionality.
+diff --git a/fs/nfsd/xdr.h b/fs/nfsd/xdr.h
+index 87fe6f64b8f7..53b1863dd8f6 100644
+--- a/fs/nfsd/xdr.h
++++ b/fs/nfsd/xdr.h
+@@ -1,8 +1,4 @@
+-/*
+- * linux/include/linux/nfsd/xdr.h
+- *
+- * XDR types for nfsd. This is mainly a typing exercise.
+- */
++/* XDR types for nfsd. This is mainly a typing exercise. */
+ 
+ #ifndef LINUX_NFSD_H
+ #define LINUX_NFSD_H
+diff --git a/fs/nfsd/xdr3.h b/fs/nfsd/xdr3.h
+index b330756973cf..7df980eb0562 100644
+--- a/fs/nfsd/xdr3.h
++++ b/fs/nfsd/xdr3.h
+@@ -1,6 +1,4 @@
+ /*
+- * linux/include/linux/nfsd/xdr3.h
+- *
+  * XDR types for NFSv3 in nfsd.
+  *
+  * Copyright (C) 1996-1998, Olaf Kirch 
+diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
+index 83202a1cf07b..efa337739534 100644
+--- a/fs/nfsd/xdr4.h
++++ b/fs/nfsd/xdr4.h
+@@ -1,6 +1,4 @@
+ /*
+- *  include/linux/nfsd/xdr4.h
+- *
+  *  Server-side types for NFSv4.
+  *
+  *  Copyright (c) 2002 The Regents of the University of Michigan.

commit 1557aca7904ed6fadd22cdc3364754070bb3d3c3
+Author: J. Bruce Fields 
+Date:   Fri Dec 4 19:36:06 2009 -0500
+
+    nfsd: move most of nfsfh.h to fs/nfsd
+    
+    Most of this can be trivially moved to a private header as well.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
+index 7d5ba1b0ffcf..b26a3644fbb9 100644
+--- a/fs/nfsd/export.c
++++ b/fs/nfsd/export.c
+@@ -22,6 +22,7 @@
+ #include 
+ 
+ #include "nfsd.h"
++#include "nfsfh.h"
+ 
+ #define NFSDDBG_FACILITY	NFSDDBG_EXPORT
+ 
+diff --git a/fs/nfsd/nfsfh.h b/fs/nfsd/nfsfh.h
+new file mode 100644
+index 000000000000..cdfb8c6a4206
+--- /dev/null
++++ b/fs/nfsd/nfsfh.h
+@@ -0,0 +1,208 @@
++/* Copyright (C) 1995, 1996, 1997 Olaf Kirch  */
++
++#ifndef _LINUX_NFSD_FH_INT_H
++#define _LINUX_NFSD_FH_INT_H
++
++#include 
++
++enum nfsd_fsid {
++	FSID_DEV = 0,
++	FSID_NUM,
++	FSID_MAJOR_MINOR,
++	FSID_ENCODE_DEV,
++	FSID_UUID4_INUM,
++	FSID_UUID8,
++	FSID_UUID16,
++	FSID_UUID16_INUM,
++};
++
++enum fsid_source {
++	FSIDSOURCE_DEV,
++	FSIDSOURCE_FSID,
++	FSIDSOURCE_UUID,
++};
++extern enum fsid_source fsid_source(struct svc_fh *fhp);
++
++
++/* This might look a little large to "inline" but in all calls except
++ * one, 'vers' is constant so moste of the function disappears.
++ */
++static inline void mk_fsid(int vers, u32 *fsidv, dev_t dev, ino_t ino,
++			   u32 fsid, unsigned char *uuid)
++{
++	u32 *up;
++	switch(vers) {
++	case FSID_DEV:
++		fsidv[0] = htonl((MAJOR(dev)<<16) |
++				 MINOR(dev));
++		fsidv[1] = ino_t_to_u32(ino);
++		break;
++	case FSID_NUM:
++		fsidv[0] = fsid;
++		break;
++	case FSID_MAJOR_MINOR:
++		fsidv[0] = htonl(MAJOR(dev));
++		fsidv[1] = htonl(MINOR(dev));
++		fsidv[2] = ino_t_to_u32(ino);
++		break;
++
++	case FSID_ENCODE_DEV:
++		fsidv[0] = new_encode_dev(dev);
++		fsidv[1] = ino_t_to_u32(ino);
++		break;
++
++	case FSID_UUID4_INUM:
++		/* 4 byte fsid and inode number */
++		up = (u32*)uuid;
++		fsidv[0] = ino_t_to_u32(ino);
++		fsidv[1] = up[0] ^ up[1] ^ up[2] ^ up[3];
++		break;
++
++	case FSID_UUID8:
++		/* 8 byte fsid  */
++		up = (u32*)uuid;
++		fsidv[0] = up[0] ^ up[2];
++		fsidv[1] = up[1] ^ up[3];
++		break;
++
++	case FSID_UUID16:
++		/* 16 byte fsid - NFSv3+ only */
++		memcpy(fsidv, uuid, 16);
++		break;
++
++	case FSID_UUID16_INUM:
++		/* 8 byte inode and 16 byte fsid */
++		*(u64*)fsidv = (u64)ino;
++		memcpy(fsidv+2, uuid, 16);
++		break;
++	default: BUG();
++	}
++}
++
++static inline int key_len(int type)
++{
++	switch(type) {
++	case FSID_DEV:		return 8;
++	case FSID_NUM: 		return 4;
++	case FSID_MAJOR_MINOR:	return 12;
++	case FSID_ENCODE_DEV:	return 8;
++	case FSID_UUID4_INUM:	return 8;
++	case FSID_UUID8:	return 8;
++	case FSID_UUID16:	return 16;
++	case FSID_UUID16_INUM:	return 24;
++	default: return 0;
++	}
++}
++
++/*
++ * Shorthand for dprintk()'s
++ */
++extern char * SVCFH_fmt(struct svc_fh *fhp);
++
++/*
++ * Function prototypes
++ */
++__be32	fh_verify(struct svc_rqst *, struct svc_fh *, int, int);
++__be32	fh_compose(struct svc_fh *, struct svc_export *, struct dentry *, struct svc_fh *);
++__be32	fh_update(struct svc_fh *);
++void	fh_put(struct svc_fh *);
++
++static __inline__ struct svc_fh *
++fh_copy(struct svc_fh *dst, struct svc_fh *src)
++{
++	WARN_ON(src->fh_dentry || src->fh_locked);
++			
++	*dst = *src;
++	return dst;
++}
++
++static inline void
++fh_copy_shallow(struct knfsd_fh *dst, struct knfsd_fh *src)
++{
++	dst->fh_size = src->fh_size;
++	memcpy(&dst->fh_base, &src->fh_base, src->fh_size);
++}
++
++static __inline__ struct svc_fh *
++fh_init(struct svc_fh *fhp, int maxsize)
++{
++	memset(fhp, 0, sizeof(*fhp));
++	fhp->fh_maxsize = maxsize;
++	return fhp;
++}
++
++#ifdef CONFIG_NFSD_V3
++/*
++ * Fill in the pre_op attr for the wcc data
++ */
++static inline void
++fill_pre_wcc(struct svc_fh *fhp)
++{
++	struct inode    *inode;
++
++	inode = fhp->fh_dentry->d_inode;
++	if (!fhp->fh_pre_saved) {
++		fhp->fh_pre_mtime = inode->i_mtime;
++		fhp->fh_pre_ctime = inode->i_ctime;
++		fhp->fh_pre_size  = inode->i_size;
++		fhp->fh_pre_change = inode->i_version;
++		fhp->fh_pre_saved = 1;
++	}
++}
++
++extern void fill_post_wcc(struct svc_fh *);
++#else
++#define	fill_pre_wcc(ignored)
++#define fill_post_wcc(notused)
++#endif /* CONFIG_NFSD_V3 */
++
++
++/*
++ * Lock a file handle/inode
++ * NOTE: both fh_lock and fh_unlock are done "by hand" in
++ * vfs.c:nfsd_rename as it needs to grab 2 i_mutex's at once
++ * so, any changes here should be reflected there.
++ */
++
++static inline void
++fh_lock_nested(struct svc_fh *fhp, unsigned int subclass)
++{
++	struct dentry	*dentry = fhp->fh_dentry;
++	struct inode	*inode;
++
++	BUG_ON(!dentry);
++
++	if (fhp->fh_locked) {
++		printk(KERN_WARNING "fh_lock: %s/%s already locked!\n",
++			dentry->d_parent->d_name.name, dentry->d_name.name);
++		return;
++	}
++
++	inode = dentry->d_inode;
++	mutex_lock_nested(&inode->i_mutex, subclass);
++	fill_pre_wcc(fhp);
++	fhp->fh_locked = 1;
++}
++
++static inline void
++fh_lock(struct svc_fh *fhp)
++{
++	fh_lock_nested(fhp, I_MUTEX_NORMAL);
++}
++
++/*
++ * Unlock a file handle/inode
++ */
++static inline void
++fh_unlock(struct svc_fh *fhp)
++{
++	BUG_ON(!fhp->fh_dentry);
++
++	if (fhp->fh_locked) {
++		fill_post_wcc(fhp);
++		mutex_unlock(&fhp->fh_dentry->d_inode->i_mutex);
++		fhp->fh_locked = 0;
++	}
++}
++
++#endif /* _LINUX_NFSD_FH_INT_H */
+diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
+index 2af75686e0d3..775b8d281d6a 100644
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -38,6 +38,7 @@
+ #define _NFSD4_STATE_H
+ 
+ #include 
++#include "nfsfh.h"
+ 
+ typedef struct {
+ 	u32             cl_boot;
+diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
+index f4fa6d351bbd..4b1de0a9ea75 100644
+--- a/fs/nfsd/vfs.h
++++ b/fs/nfsd/vfs.h
+@@ -5,6 +5,8 @@
+ #ifndef LINUX_NFSD_VFS_H
+ #define LINUX_NFSD_VFS_H
+ 
++#include "nfsfh.h"
++
+ /*
+  * Flags for nfsd_permission
+  */
+diff --git a/fs/nfsd/xdr.h b/fs/nfsd/xdr.h
+index 235ee5c3be54..87fe6f64b8f7 100644
+--- a/fs/nfsd/xdr.h
++++ b/fs/nfsd/xdr.h
+@@ -9,6 +9,7 @@
+ 
+ #include 
+ #include "nfsd.h"
++#include "nfsfh.h"
+ 
+ struct nfsd_fhandle {
+ 	struct svc_fh		fh;
+diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h
+index 49523edbc510..65e333afaee4 100644
+--- a/include/linux/nfsd/nfsfh.h
++++ b/include/linux/nfsd/nfsfh.h
+@@ -162,205 +162,6 @@ typedef struct svc_fh {
+ 
+ } svc_fh;
+ 
+-enum nfsd_fsid {
+-	FSID_DEV = 0,
+-	FSID_NUM,
+-	FSID_MAJOR_MINOR,
+-	FSID_ENCODE_DEV,
+-	FSID_UUID4_INUM,
+-	FSID_UUID8,
+-	FSID_UUID16,
+-	FSID_UUID16_INUM,
+-};
+-
+-enum fsid_source {
+-	FSIDSOURCE_DEV,
+-	FSIDSOURCE_FSID,
+-	FSIDSOURCE_UUID,
+-};
+-extern enum fsid_source fsid_source(struct svc_fh *fhp);
+-
+-
+-/* This might look a little large to "inline" but in all calls except
+- * one, 'vers' is constant so moste of the function disappears.
+- */
+-static inline void mk_fsid(int vers, u32 *fsidv, dev_t dev, ino_t ino,
+-			   u32 fsid, unsigned char *uuid)
+-{
+-	u32 *up;
+-	switch(vers) {
+-	case FSID_DEV:
+-		fsidv[0] = htonl((MAJOR(dev)<<16) |
+-				 MINOR(dev));
+-		fsidv[1] = ino_t_to_u32(ino);
+-		break;
+-	case FSID_NUM:
+-		fsidv[0] = fsid;
+-		break;
+-	case FSID_MAJOR_MINOR:
+-		fsidv[0] = htonl(MAJOR(dev));
+-		fsidv[1] = htonl(MINOR(dev));
+-		fsidv[2] = ino_t_to_u32(ino);
+-		break;
+-
+-	case FSID_ENCODE_DEV:
+-		fsidv[0] = new_encode_dev(dev);
+-		fsidv[1] = ino_t_to_u32(ino);
+-		break;
+-
+-	case FSID_UUID4_INUM:
+-		/* 4 byte fsid and inode number */
+-		up = (u32*)uuid;
+-		fsidv[0] = ino_t_to_u32(ino);
+-		fsidv[1] = up[0] ^ up[1] ^ up[2] ^ up[3];
+-		break;
+-
+-	case FSID_UUID8:
+-		/* 8 byte fsid  */
+-		up = (u32*)uuid;
+-		fsidv[0] = up[0] ^ up[2];
+-		fsidv[1] = up[1] ^ up[3];
+-		break;
+-
+-	case FSID_UUID16:
+-		/* 16 byte fsid - NFSv3+ only */
+-		memcpy(fsidv, uuid, 16);
+-		break;
+-
+-	case FSID_UUID16_INUM:
+-		/* 8 byte inode and 16 byte fsid */
+-		*(u64*)fsidv = (u64)ino;
+-		memcpy(fsidv+2, uuid, 16);
+-		break;
+-	default: BUG();
+-	}
+-}
+-
+-static inline int key_len(int type)
+-{
+-	switch(type) {
+-	case FSID_DEV:		return 8;
+-	case FSID_NUM: 		return 4;
+-	case FSID_MAJOR_MINOR:	return 12;
+-	case FSID_ENCODE_DEV:	return 8;
+-	case FSID_UUID4_INUM:	return 8;
+-	case FSID_UUID8:	return 8;
+-	case FSID_UUID16:	return 16;
+-	case FSID_UUID16_INUM:	return 24;
+-	default: return 0;
+-	}
+-}
+-
+-/*
+- * Shorthand for dprintk()'s
+- */
+-extern char * SVCFH_fmt(struct svc_fh *fhp);
+-
+-/*
+- * Function prototypes
+- */
+-__be32	fh_verify(struct svc_rqst *, struct svc_fh *, int, int);
+-__be32	fh_compose(struct svc_fh *, struct svc_export *, struct dentry *, struct svc_fh *);
+-__be32	fh_update(struct svc_fh *);
+-void	fh_put(struct svc_fh *);
+-
+-static __inline__ struct svc_fh *
+-fh_copy(struct svc_fh *dst, struct svc_fh *src)
+-{
+-	WARN_ON(src->fh_dentry || src->fh_locked);
+-			
+-	*dst = *src;
+-	return dst;
+-}
+-
+-static inline void
+-fh_copy_shallow(struct knfsd_fh *dst, struct knfsd_fh *src)
+-{
+-	dst->fh_size = src->fh_size;
+-	memcpy(&dst->fh_base, &src->fh_base, src->fh_size);
+-}
+-
+-static __inline__ struct svc_fh *
+-fh_init(struct svc_fh *fhp, int maxsize)
+-{
+-	memset(fhp, 0, sizeof(*fhp));
+-	fhp->fh_maxsize = maxsize;
+-	return fhp;
+-}
+-
+-#ifdef CONFIG_NFSD_V3
+-/*
+- * Fill in the pre_op attr for the wcc data
+- */
+-static inline void
+-fill_pre_wcc(struct svc_fh *fhp)
+-{
+-	struct inode    *inode;
+-
+-	inode = fhp->fh_dentry->d_inode;
+-	if (!fhp->fh_pre_saved) {
+-		fhp->fh_pre_mtime = inode->i_mtime;
+-		fhp->fh_pre_ctime = inode->i_ctime;
+-		fhp->fh_pre_size  = inode->i_size;
+-		fhp->fh_pre_change = inode->i_version;
+-		fhp->fh_pre_saved = 1;
+-	}
+-}
+-
+-extern void fill_post_wcc(struct svc_fh *);
+-#else
+-#define	fill_pre_wcc(ignored)
+-#define fill_post_wcc(notused)
+-#endif /* CONFIG_NFSD_V3 */
+-
+-
+-/*
+- * Lock a file handle/inode
+- * NOTE: both fh_lock and fh_unlock are done "by hand" in
+- * vfs.c:nfsd_rename as it needs to grab 2 i_mutex's at once
+- * so, any changes here should be reflected there.
+- */
+-
+-static inline void
+-fh_lock_nested(struct svc_fh *fhp, unsigned int subclass)
+-{
+-	struct dentry	*dentry = fhp->fh_dentry;
+-	struct inode	*inode;
+-
+-	BUG_ON(!dentry);
+-
+-	if (fhp->fh_locked) {
+-		printk(KERN_WARNING "fh_lock: %s/%s already locked!\n",
+-			dentry->d_parent->d_name.name, dentry->d_name.name);
+-		return;
+-	}
+-
+-	inode = dentry->d_inode;
+-	mutex_lock_nested(&inode->i_mutex, subclass);
+-	fill_pre_wcc(fhp);
+-	fhp->fh_locked = 1;
+-}
+-
+-static inline void
+-fh_lock(struct svc_fh *fhp)
+-{
+-	fh_lock_nested(fhp, I_MUTEX_NORMAL);
+-}
+-
+-/*
+- * Unlock a file handle/inode
+- */
+-static inline void
+-fh_unlock(struct svc_fh *fhp)
+-{
+-	BUG_ON(!fhp->fh_dentry);
+-
+-	if (fhp->fh_locked) {
+-		fill_post_wcc(fhp);
+-		mutex_unlock(&fhp->fh_dentry->d_inode->i_mutex);
+-		fhp->fh_locked = 0;
+-	}
+-}
+ #endif /* __KERNEL__ */
+ 
+ 

commit c7af6b0895229bd080b86afc91302b66f6df0378
+Author: J. Bruce Fields 
+Date:   Fri Dec 4 18:29:33 2009 -0500
+
+    nfsd: remove unused field rq_reffh
+    
+    This field is never referenced anywhere else.  I don't know what it was
+    intended for.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
+index d1567d627557..5a3085b9b394 100644
+--- a/include/linux/sunrpc/svc.h
++++ b/include/linux/sunrpc/svc.h
+@@ -273,10 +273,6 @@ struct svc_rqst {
+ 	struct auth_domain *	rq_client;	/* RPC peer info */
+ 	struct auth_domain *	rq_gssclient;	/* "gss/"-style peer info */
+ 	struct svc_cacherep *	rq_cacherep;	/* cache info */
+-	struct knfsd_fh *	rq_reffh;	/* Referrence filehandle, used to
+-						 * determine what device number
+-						 * to report (real or virtual)
+-						 */
+ 	int			rq_splice_ok;   /* turned off in gss privacy
+ 						 * to prevent encrypting page
+ 						 * cache pages */

commit 3d8986c7585457c45fd349b2c542c7c1ecd20843
+Author: J. Bruce Fields 
+Date:   Tue Dec 15 14:09:03 2009 -0500
+
+    nfsd: enable V4ROOT exports
+    
+    With the v4root option now enforced everywhere it should be, it is safe
+    to advertise support for it to mountd.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
+index 41f0d4e25374..8ae78a61eea4 100644
+--- a/include/linux/nfsd/export.h
++++ b/include/linux/nfsd/export.h
+@@ -50,7 +50,7 @@
+  */
+ #define	NFSEXP_V4ROOT		0x10000
+ /* All flags that we claim to support.  (Note we don't support NOACL.) */
+-#define NFSEXP_ALLFLAGS		0x7E3F
++#define NFSEXP_ALLFLAGS		0x17E3F
+ 
+ /* The flags that may vary depending on security flavor: */
+ #define NFSEXP_SECINFO_FLAGS	(NFSEXP_READONLY | NFSEXP_ROOTSQUASH \

commit 774b147828e32ec698e49d95d0498fc71da7082d
+Author: J. Bruce Fields 
+Date:   Sun Dec 13 20:21:48 2009 -0500
+
+    nfsd: make V4ROOT exports read-only
+    
+    I can't see any use for writeable V4ROOT exports.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
+index 18ac20ffedd2..7d5ba1b0ffcf 100644
+--- a/fs/nfsd/export.c
++++ b/fs/nfsd/export.c
+@@ -355,7 +355,7 @@ static struct svc_export *svc_export_update(struct svc_export *new,
+ 					    struct svc_export *old);
+ static struct svc_export *svc_export_lookup(struct svc_export *);
+ 
+-static int check_export(struct inode *inode, int flags, unsigned char *uuid)
++static int check_export(struct inode *inode, int *flags, unsigned char *uuid)
+ {
+ 
+ 	/*
+@@ -367,6 +367,13 @@ static int check_export(struct inode *inode, int flags, unsigned char *uuid)
+ 	    !S_ISREG(inode->i_mode))
+ 		return -ENOTDIR;
+ 
++	/*
++	 * Mountd should never pass down a writeable V4ROOT export, but,
++	 * just to make sure:
++	 */
++	if (*flags & NFSEXP_V4ROOT)
++		*flags |= NFSEXP_READONLY;
++
+ 	/* There are two requirements on a filesystem to be exportable.
+ 	 * 1:  We must be able to identify the filesystem from a number.
+ 	 *       either a device number (so FS_REQUIRES_DEV needed)
+@@ -375,7 +382,7 @@ static int check_export(struct inode *inode, int flags, unsigned char *uuid)
+ 	 *       This means that s_export_op must be set.
+ 	 */
+ 	if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) &&
+-	    !(flags & NFSEXP_FSID) &&
++	    !(*flags & NFSEXP_FSID) &&
+ 	    uuid == NULL) {
+ 		dprintk("exp_export: export of non-dev fs without fsid\n");
+ 		return -EINVAL;
+@@ -590,7 +597,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
+ 				goto out4;
+ 		}
+ 
+-		err = check_export(exp.ex_path.dentry->d_inode, exp.ex_flags,
++		err = check_export(exp.ex_path.dentry->d_inode, &exp.ex_flags,
+ 				   exp.ex_uuid);
+ 		if (err)
+ 			goto out4;
+@@ -1029,7 +1036,7 @@ exp_export(struct nfsctl_export *nxp)
+ 		goto finish;
+ 	}
+ 
+-	err = check_export(path.dentry->d_inode, nxp->ex_flags, NULL);
++	err = check_export(path.dentry->d_inode, &nxp->ex_flags, NULL);
+ 	if (err) goto finish;
+ 
+ 	err = -ENOMEM;

commit f2ca7153ca49a407ea1c7232c9fa7e9849f03f9c
+Author: J. Bruce Fields 
+Date:   Thu Nov 12 17:26:19 2009 -0500
+
+    nfsd: allow exports of symlinks
+    
+    We want to allow exports of symlinks, to allow mountd to communicate to
+    the kernel which symlinks lead to exports, and hence which symlinks need
+    to be visible on the pseudofilesystem.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
+index c64d55f319bd..18ac20ffedd2 100644
+--- a/fs/nfsd/export.c
++++ b/fs/nfsd/export.c
+@@ -358,10 +358,12 @@ static struct svc_export *svc_export_lookup(struct svc_export *);
+ static int check_export(struct inode *inode, int flags, unsigned char *uuid)
+ {
+ 
+-	/* We currently export only dirs and regular files.
+-	 * This is what umountd does.
++	/*
++	 * We currently export only dirs, regular files, and (for v4
++	 * pseudoroot) symlinks.
+ 	 */
+ 	if (!S_ISDIR(inode->i_mode) &&
++	    !S_ISLNK(inode->i_mode) &&
+ 	    !S_ISREG(inode->i_mode))
+ 		return -ENOTDIR;
+ 

commit 3227fa41abc191384fa81b3bcf52aa7fccb31536
+Author: J. Bruce Fields 
+Date:   Sun Oct 25 21:43:01 2009 -0400
+
+    nfsd: filter readdir results in V4ROOT case
+    
+    As with lookup, we treat every boject as a mountpoint and pretend it
+    doesn't exist if it isn't exported.
+    
+    The preexisting code here is confusing, but I haven't yet figured out
+    how to make it clearer.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index cab978031100..a8587e90fd5a 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -2196,11 +2196,14 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
+ 	 * we will not follow the cross mount and will fill the attribtutes
+ 	 * directly from the mountpoint dentry.
+ 	 */
+-	if (d_mountpoint(dentry) && !attributes_need_mount(cd->rd_bmval))
+-		ignore_crossmnt = 1;
+-	else if (d_mountpoint(dentry)) {
++	if (nfsd_mountpoint(dentry, exp)) {
+ 		int err;
+ 
++		if (!(exp->ex_flags & NFSEXP_V4ROOT)
++				&& !attributes_need_mount(cd->rd_bmval)) {
++			ignore_crossmnt = 1;
++			goto out_encode;
++		}
+ 		/*
+ 		 * Why the heck aren't we just using nfsd_lookup??
+ 		 * Different "."/".." handling?  Something else?
+@@ -2216,6 +2219,7 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
+ 			goto out_put;
+ 
+ 	}
++out_encode:
+ 	nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval,
+ 					cd->rd_rqstp, ignore_crossmnt);
+ out_put:
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index eaf2f0dca12a..a0015a958aef 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -170,7 +170,7 @@ static int nfsd_lookup_parent(struct svc_rqst *rqstp, struct dentry *dparent, st
+  * For nfsd purposes, we treat V4ROOT exports as though there was an
+  * export at *every* directory.
+  */
+-static int nfsd_mountpoint(struct dentry *dentry, struct svc_export *exp)
++int nfsd_mountpoint(struct dentry *dentry, struct svc_export *exp)
+ {
+ 	if (d_mountpoint(dentry))
+ 		return 1;
+diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
+index b8011fd2fcab..f4fa6d351bbd 100644
+--- a/fs/nfsd/vfs.h
++++ b/fs/nfsd/vfs.h
+@@ -40,6 +40,7 @@ __be32		 nfsd_lookup_dentry(struct svc_rqst *, struct svc_fh *,
+ 				struct svc_export **, struct dentry **);
+ __be32		nfsd_setattr(struct svc_rqst *, struct svc_fh *,
+ 				struct iattr *, int, time_t);
++int nfsd_mountpoint(struct dentry *, struct svc_export *);
+ #ifdef CONFIG_NFSD_V4
+ __be32          nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
+                     struct nfs4_acl *);

commit 82ead7fe41da960ed80652d13d5a1072f85f5aca
+Author: J. Bruce Fields 
+Date:   Sun Oct 25 21:33:15 2009 -0400
+
+    nfsd: filter lookup results in V4ROOT case
+    
+    We treat every object as a mountpoint and pretend it doesn't exist if
+    it isn't exported.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index 7e2fdd50113f..eaf2f0dca12a 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -166,6 +166,19 @@ static int nfsd_lookup_parent(struct svc_rqst *rqstp, struct dentry *dparent, st
+ 	return 0;
+ }
+ 
++/*
++ * For nfsd purposes, we treat V4ROOT exports as though there was an
++ * export at *every* directory.
++ */
++static int nfsd_mountpoint(struct dentry *dentry, struct svc_export *exp)
++{
++	if (d_mountpoint(dentry))
++		return 1;
++	if (!(exp->ex_flags & NFSEXP_V4ROOT))
++		return 0;
++	return dentry->d_inode != NULL;
++}
++
+ __be32
+ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ 		   const char *name, unsigned int len,
+@@ -211,7 +224,7 @@ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ 		/*
+ 		 * check if we have crossed a mount point ...
+ 		 */
+-		if (d_mountpoint(dentry)) {
++		if (nfsd_mountpoint(dentry, exp)) {
+ 			if ((host_err = nfsd_cross_mnt(rqstp, &dentry, &exp))) {
+ 				dput(dentry);
+ 				goto out_nfserr;

commit 3b6cee7bc4b2f7858e9202293104acda8826bb68
+Author: J. Bruce Fields 
+Date:   Sun Oct 25 21:18:19 2009 -0400
+
+    nfsd4: don't continue "under" mounts in V4ROOT case
+    
+    If /A/mount/point/ has filesystem "B" mounted on top of it, and if "A"
+    is exported, but not "B", then the nfs server has always returned to the
+    client a filehandle for the mountpoint, instead of for the root of "B",
+    allowing the client to see the subtree of "A" that would otherwise be
+    hidden by B.
+    
+    Disable this behavior in the case of V4ROOT exports; we implement the
+    path restrictions of V4ROOT exports by treating *every* directory as if
+    it were a mountpoint, and allowing traversal *only* if the new directory
+    is exported.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index 04bdba12d21b..7e2fdd50113f 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -99,8 +99,16 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
+ 
+ 	exp2 = rqst_exp_get_by_name(rqstp, &path);
+ 	if (IS_ERR(exp2)) {
+-		if (PTR_ERR(exp2) != -ENOENT)
+-			err = PTR_ERR(exp2);
++		err = PTR_ERR(exp2);
++		/*
++		 * We normally allow NFS clients to continue
++		 * "underneath" a mountpoint that is not exported.
++		 * The exception is V4ROOT, where no traversal is ever
++		 * allowed without an explicit export of the new
++		 * directory.
++		 */
++		if (err == -ENOENT && !(exp->ex_flags & NFSEXP_V4ROOT))
++			err = 0;
+ 		path_put(&path);
+ 		goto out;
+ 	}

commit 12045a6ee9908b38b6d286530c7d816e39071346
+Author: J. Bruce Fields 
+Date:   Tue Dec 8 18:15:52 2009 -0500
+
+    nfsd: let "insecure" flag vary by pseudoflavor
+    
+    This was an oversight; it should be among the export flags that can be
+    allowed to vary by pseudoflavor.  This allows an administrator to (for
+    example) allow auth_sys mounts only from low ports, but allow auth_krb5
+    mounts to use any port.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
+index 0eb1c59f5ab8..951938d6c495 100644
+--- a/fs/nfsd/nfsfh.c
++++ b/fs/nfsd/nfsfh.c
+@@ -88,8 +88,10 @@ nfsd_mode_check(struct svc_rqst *rqstp, umode_t mode, int type)
+ static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp,
+ 					  struct svc_export *exp)
+ {
++	int flags = nfsexp_flags(rqstp, exp);
++
+ 	/* Check if the request originated from a secure port. */
+-	if (!rqstp->rq_secure && EX_SECURE(exp)) {
++	if (!rqstp->rq_secure && (flags & NFSEXP_INSECURE_PORT)) {
+ 		RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
+ 		dprintk(KERN_WARNING
+ 		       "nfsd: request from insecure port %s!\n",
+diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
+index 4f1df1d7312c..4cafbe1255f0 100644
+--- a/include/linux/nfsd/export.h
++++ b/include/linux/nfsd/export.h
+@@ -44,7 +44,8 @@
+ 
+ /* The flags that may vary depending on security flavor: */
+ #define NFSEXP_SECINFO_FLAGS	(NFSEXP_READONLY | NFSEXP_ROOTSQUASH \
+-					| NFSEXP_ALLSQUASH)
++					| NFSEXP_ALLSQUASH \
++					| NFSEXP_INSECURE_PORT)
+ 
+ #ifdef __KERNEL__
+ 
+@@ -109,7 +110,6 @@ struct svc_expkey {
+ 	struct path		ek_path;
+ };
+ 
+-#define EX_SECURE(exp)		(!((exp)->ex_flags & NFSEXP_INSECURE_PORT))
+ #define EX_ISSYNC(exp)		(!((exp)->ex_flags & NFSEXP_ASYNC))
+ #define EX_NOHIDE(exp)		((exp)->ex_flags & NFSEXP_NOHIDE)
+ #define EX_WGATHER(exp)		((exp)->ex_flags & NFSEXP_GATHERED_WRITES)

commit e8e8753f7a32ce4f636771126fc8eba0dc4ad817
+Author: J. Bruce Fields 
+Date:   Mon Dec 14 12:53:32 2009 -0500
+
+    nfsd: new interface to advertise export features
+    
+    Soon we will add the new V4ROOT flag, and allow the INSECURE flag to
+    vary by pseudoflavor.  It would be useful for nfs-utils (for example,
+    for improved exportfs error reporting) to be able to know when this
+    happens.  Use this new interface for that purpose.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index 0415680d3f58..e7051ac4dc73 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -31,6 +31,7 @@ enum {
+ 	NFSD_Getfd,
+ 	NFSD_Getfs,
+ 	NFSD_List,
++	NFSD_Export_features,
+ 	NFSD_Fh,
+ 	NFSD_FO_UnlockIP,
+ 	NFSD_FO_UnlockFS,
+@@ -149,6 +150,24 @@ static const struct file_operations exports_operations = {
+ 	.owner		= THIS_MODULE,
+ };
+ 
++static int export_features_show(struct seq_file *m, void *v)
++{
++	seq_printf(m, "0x%x 0x%x\n", NFSEXP_ALLFLAGS, NFSEXP_SECINFO_FLAGS);
++	return 0;
++}
++
++static int export_features_open(struct inode *inode, struct file *file)
++{
++	return single_open(file, export_features_show, NULL);
++}
++
++static struct file_operations export_features_operations = {
++	.open		= export_features_open,
++	.read		= seq_read,
++	.llseek		= seq_lseek,
++	.release	= single_release,
++};
++
+ extern int nfsd_pool_stats_open(struct inode *inode, struct file *file);
+ extern int nfsd_pool_stats_release(struct inode *inode, struct file *file);
+ 
+@@ -1306,6 +1325,8 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
+ 		[NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR},
+ 		[NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR},
+ 		[NFSD_List] = {"exports", &exports_operations, S_IRUGO},
++		[NFSD_Export_features] = {"export_features",
++					&export_features_operations, S_IRUGO},
+ 		[NFSD_FO_UnlockIP] = {"unlock_ip",
+ 					&transaction_ops, S_IWUSR|S_IRUSR},
+ 		[NFSD_FO_UnlockFS] = {"unlock_filesystem",
+diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
+index ef3d416fcf67..4f1df1d7312c 100644
+--- a/include/linux/nfsd/export.h
++++ b/include/linux/nfsd/export.h
+@@ -39,7 +39,8 @@
+ #define NFSEXP_FSID		0x2000
+ #define	NFSEXP_CROSSMOUNT	0x4000
+ #define	NFSEXP_NOACL		0x8000	/* reserved for possible ACL related use */
+-#define NFSEXP_ALLFLAGS		0xFE3F
++/* All flags that we claim to support.  (Note we don't support NOACL.) */
++#define NFSEXP_ALLFLAGS		0x7E3F
+ 
+ /* The flags that may vary depending on security flavor: */
+ #define NFSEXP_SECINFO_FLAGS	(NFSEXP_READONLY | NFSEXP_ROOTSQUASH \

commit 57ecb34febc4c133ca0ccc7817796605a78a01d3
+Author: J. Bruce Fields 
+Date:   Tue Dec 1 19:42:57 2009 -0500
+
+    nfsd4: fix share mode permissions
+    
+    NFSv4 opens may function as locks denying other NFSv4 users the rights
+    to open a file.
+    
+    We're requiring a user to have write permissions before they can deny
+    write.  We're *not* requiring a user to have write permissions to deny
+    read, which is if anything a more drastic denial.
+    
+    What was intended was to require write permissions for DENY_READ.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index 60a93cdefef5..a468224a118f 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -171,7 +171,7 @@ do_open_permission(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs
+ 		accmode |= NFSD_MAY_READ;
+ 	if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
+ 		accmode |= (NFSD_MAY_WRITE | NFSD_MAY_TRUNC);
+-	if (open->op_share_deny & NFS4_SHARE_DENY_WRITE)
++	if (open->op_share_deny & NFS4_SHARE_DENY_READ)
+ 		accmode |= NFSD_MAY_WRITE;
+ 
+ 	status = fh_verify(rqstp, current_fh, S_IFREG, accmode);

commit d4e935bd67ca05db4119b67801d9ece6ae139f05
+Author: J. Bruce Fields 
+Date:   Thu Dec 3 15:58:33 2009 -0500
+
+    The rpc server does not require that service threads take the BKL.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
+index 293fa0528a6e..e66ec5d169f7 100644
+--- a/fs/nfs/callback.c
++++ b/fs/nfs/callback.c
+@@ -78,11 +78,6 @@ nfs4_callback_svc(void *vrqstp)
+ 
+ 	set_freezable();
+ 
+-	/*
+-	 * FIXME: do we really need to run this under the BKL? If so, please
+-	 * add a comment about what it's intended to protect.
+-	 */
+-	lock_kernel();
+ 	while (!kthread_should_stop()) {
+ 		/*
+ 		 * Listen for a request on the socket
+@@ -104,7 +99,6 @@ nfs4_callback_svc(void *vrqstp)
+ 		preverr = err;
+ 		svc_process(rqstp);
+ 	}
+-	unlock_kernel();
+ 	return 0;
+ }
+ 
+@@ -160,11 +154,6 @@ nfs41_callback_svc(void *vrqstp)
+ 
+ 	set_freezable();
+ 
+-	/*
+-	 * FIXME: do we really need to run this under the BKL? If so, please
+-	 * add a comment about what it's intended to protect.
+-	 */
+-	lock_kernel();
+ 	while (!kthread_should_stop()) {
+ 		prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE);
+ 		spin_lock_bh(&serv->sv_cb_lock);
+@@ -183,7 +172,6 @@ nfs41_callback_svc(void *vrqstp)
+ 		}
+ 		finish_wait(&serv->sv_cb_waitq, &wq);
+ 	}
+-	unlock_kernel();
+ 	return 0;
+ }
+ 

commit 864f0f61f829bac5f150a903aad9619322a25424
+Author: J. Bruce Fields 
+Date:   Wed Nov 25 17:42:05 2009 -0500
+
+    nfsd: simplify fh_verify access checks
+    
+    All nfsd security depends on the security checks in fh_verify, and
+    especially on nfsd_setuser().
+    
+    It therefore bothers me that the nfsd_setuser call may be made from
+    three different places, depending on whether the filehandle has already
+    been mapped to a dentry, and on whether subtreechecking is in force.
+    
+    Instead, make an unconditional call in fh_verify(), so it's trivial to
+    verify that the call always occurs.
+    
+    That leaves us with a redundant nfsd_setuser() call in the subtreecheck
+    case--it needs the correct user set earlier in order to check execute
+    permissions on the path to this filehandle--but I'm willing to accept
+    that minor inefficiency in the subtreecheck case in return for more
+    straightforward permission checking.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
+index d0d8a217a3ea..a77efb8c2243 100644
+--- a/fs/nfsd/nfsfh.c
++++ b/fs/nfsd/nfsfh.c
+@@ -233,14 +233,6 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
+ 		goto out;
+ 	}
+ 
+-	if (exp->ex_flags & NFSEXP_NOSUBTREECHECK) {
+-		error = nfsd_setuser_and_check_port(rqstp, exp);
+-		if (error) {
+-			dput(dentry);
+-			goto out;
+-		}
+-	}
+-
+ 	if (S_ISDIR(dentry->d_inode->i_mode) &&
+ 			(dentry->d_flags & DCACHE_DISCONNECTED)) {
+ 		printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n",
+@@ -295,28 +287,28 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
+ 		error = nfsd_set_fh_dentry(rqstp, fhp);
+ 		if (error)
+ 			goto out;
+-		dentry = fhp->fh_dentry;
+-		exp = fhp->fh_export;
+-	} else {
+-		/*
+-		 * just rechecking permissions
+-		 * (e.g. nfsproc_create calls fh_verify, then nfsd_create
+-		 * does as well)
+-		 */
+-		dprintk("nfsd: fh_verify - just checking\n");
+-		dentry = fhp->fh_dentry;
+-		exp = fhp->fh_export;
+-		/*
+-		 * Set user creds for this exportpoint; necessary even
+-		 * in the "just checking" case because this may be a
+-		 * filehandle that was created by fh_compose, and that
+-		 * is about to be used in another nfsv4 compound
+-		 * operation.
+-		 */
+-		error = nfsd_setuser_and_check_port(rqstp, exp);
+-		if (error)
+-			goto out;
+ 	}
++	dentry = fhp->fh_dentry;
++	exp = fhp->fh_export;
++	/*
++	 * We still have to do all these permission checks, even when
++	 * fh_dentry is already set:
++	 * 	- fh_verify may be called multiple times with different
++	 * 	  "access" arguments (e.g. nfsd_proc_create calls
++	 * 	  fh_verify(...,NFSD_MAY_EXEC) first, then later (in
++	 * 	  nfsd_create) calls fh_verify(...,NFSD_MAY_CREATE).
++	 *	- in the NFSv4 case, the filehandle may have been filled
++	 *	  in by fh_compose, and given a dentry, but further
++	 *	  compound operations performed with that filehandle
++	 *	  still need permissions checks.  In the worst case, a
++	 *	  mountpoint crossing may have changed the export
++	 *	  options, and we may now need to use a different uid
++	 *	  (for example, if different id-squashing options are in
++	 *	  effect on the new filesystem).
++	 */
++	error = nfsd_setuser_and_check_port(rqstp, exp);
++	if (error)
++		goto out;
+ 
+ 	error = nfsd_mode_check(rqstp, dentry->d_inode->i_mode, type);
+ 	if (error)

commit 9b8b317d58084b9a44f6f33b355c4278d9f841fb
+Merge: 78c210efdefe 648f4e3e50c4
+Author: J. Bruce Fields 
+Date:   Mon Nov 23 12:34:58 2009 -0500
+
+    Merge commit 'v2.6.32-rc8' into HEAD
+

commit 78c210efdefe07131f91ed512a3308b15bb14e2f
+Author: J. Bruce Fields 
+Date:   Thu Aug 6 15:41:34 2009 -0400
+
+    Revert "knfsd: avoid overloading the CPU scheduler with enormous load averages"
+    
+    This reverts commit 59a252ff8c0f2fa32c896f69d56ae33e641ce7ad.
+    
+    This helps in an entirely cached workload but not necessarily in
+    workloads that require waiting on disk.
+    
+    Conflicts:
+    
+            include/linux/sunrpc/svc.h
+            net/sunrpc/svc_xprt.c
+    
+    Reported-by: Simon Kirby 
+    Tested-by: Jesper Krogh 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
+index 52e8cb0a7569..d1567d627557 100644
+--- a/include/linux/sunrpc/svc.h
++++ b/include/linux/sunrpc/svc.h
+@@ -29,7 +29,6 @@ struct svc_pool_stats {
+ 	unsigned long	packets;
+ 	unsigned long	sockets_queued;
+ 	unsigned long	threads_woken;
+-	unsigned long	overloads_avoided;
+ 	unsigned long	threads_timedout;
+ };
+ 
+@@ -50,7 +49,6 @@ struct svc_pool {
+ 	struct list_head	sp_sockets;	/* pending sockets */
+ 	unsigned int		sp_nrthreads;	/* # of threads in pool */
+ 	struct list_head	sp_all_threads;	/* all server threads */
+-	int			sp_nwaking;	/* number of threads woken but not yet active */
+ 	struct svc_pool_stats	sp_stats;	/* statistics on pool operation */
+ } ____cacheline_aligned_in_smp;
+ 
+@@ -284,7 +282,6 @@ struct svc_rqst {
+ 						 * cache pages */
+ 	wait_queue_head_t	rq_wait;	/* synchronization */
+ 	struct task_struct	*rq_task;	/* service thread */
+-	int			rq_waking;	/* 1 if thread is being woken */
+ };
+ 
+ /*
+diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
+index df124f78ee48..2c58b75a236f 100644
+--- a/net/sunrpc/svc_xprt.c
++++ b/net/sunrpc/svc_xprt.c
+@@ -16,8 +16,6 @@
+ 
+ #define RPCDBG_FACILITY	RPCDBG_SVCXPRT
+ 
+-#define SVC_MAX_WAKING 5
+-
+ static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt);
+ static int svc_deferred_recv(struct svc_rqst *rqstp);
+ static struct cache_deferred_req *svc_defer(struct cache_req *req);
+@@ -306,7 +304,6 @@ void svc_xprt_enqueue(struct svc_xprt *xprt)
+ 	struct svc_pool *pool;
+ 	struct svc_rqst	*rqstp;
+ 	int cpu;
+-	int thread_avail;
+ 
+ 	if (!(xprt->xpt_flags &
+ 	      ((1<sp_lock);
+ 
++	if (!list_empty(&pool->sp_threads) &&
++	    !list_empty(&pool->sp_sockets))
++		printk(KERN_ERR
++		       "svc_xprt_enqueue: "
++		       "threads and transports both waiting??\n");
++
+ 	if (test_bit(XPT_DEAD, &xprt->xpt_flags)) {
+ 		/* Don't enqueue dead transports */
+ 		dprintk("svc: transport %p is dead, not enqueued\n", xprt);
+@@ -358,15 +361,7 @@ void svc_xprt_enqueue(struct svc_xprt *xprt)
+ 	}
+ 
+  process:
+-	/* Work out whether threads are available */
+-	thread_avail = !list_empty(&pool->sp_threads);	/* threads are asleep */
+-	if (pool->sp_nwaking >= SVC_MAX_WAKING) {
+-		/* too many threads are runnable and trying to wake up */
+-		thread_avail = 0;
+-		pool->sp_stats.overloads_avoided++;
+-	}
+-
+-	if (thread_avail) {
++	if (!list_empty(&pool->sp_threads)) {
+ 		rqstp = list_entry(pool->sp_threads.next,
+ 				   struct svc_rqst,
+ 				   rq_list);
+@@ -381,8 +376,6 @@ void svc_xprt_enqueue(struct svc_xprt *xprt)
+ 		svc_xprt_get(xprt);
+ 		rqstp->rq_reserved = serv->sv_max_mesg;
+ 		atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved);
+-		rqstp->rq_waking = 1;
+-		pool->sp_nwaking++;
+ 		pool->sp_stats.threads_woken++;
+ 		BUG_ON(xprt->xpt_pool != pool);
+ 		wake_up(&rqstp->rq_wait);
+@@ -651,11 +644,6 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
+ 		return -EINTR;
+ 
+ 	spin_lock_bh(&pool->sp_lock);
+-	if (rqstp->rq_waking) {
+-		rqstp->rq_waking = 0;
+-		pool->sp_nwaking--;
+-		BUG_ON(pool->sp_nwaking < 0);
+-	}
+ 	xprt = svc_xprt_dequeue(pool);
+ 	if (xprt) {
+ 		rqstp->rq_xprt = xprt;
+@@ -1204,16 +1192,15 @@ static int svc_pool_stats_show(struct seq_file *m, void *p)
+ 	struct svc_pool *pool = p;
+ 
+ 	if (p == SEQ_START_TOKEN) {
+-		seq_puts(m, "# pool packets-arrived sockets-enqueued threads-woken overloads-avoided threads-timedout\n");
++		seq_puts(m, "# pool packets-arrived sockets-enqueued threads-woken threads-timedout\n");
+ 		return 0;
+ 	}
+ 
+-	seq_printf(m, "%u %lu %lu %lu %lu %lu\n",
++	seq_printf(m, "%u %lu %lu %lu %lu\n",
+ 		pool->sp_id,
+ 		pool->sp_stats.packets,
+ 		pool->sp_stats.sockets_queued,
+ 		pool->sp_stats.threads_woken,
+-		pool->sp_stats.overloads_avoided,
+ 		pool->sp_stats.threads_timedout);
+ 
+ 	return 0;

commit 0a3adadee42f2865bb867b8c5f4955b7def9baad
+Author: J. Bruce Fields 
+Date:   Wed Nov 4 18:12:35 2009 -0500
+
+    nfsd: make fs/nfsd/vfs.h for common includes
+    
+    None of this stuff is used outside nfsd, so move it out of the common
+    linux include directory.
+    
+    Actually, probably none of the stuff in include/linux/nfsd/nfsd.h really
+    belongs there, so later we may remove that file entirely.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
+index b2786a5f9afe..812bc64874f6 100644
+--- a/fs/nfsd/lockd.c
++++ b/fs/nfsd/lockd.c
+@@ -16,6 +16,7 @@
+ #include 
+ #include 
+ #include 
++#include "vfs.h"
+ 
+ #define NFSDDBG_FACILITY		NFSDDBG_LOCKD
+ 
+diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
+index e2a17f0a96a7..38c883d48b02 100644
+--- a/fs/nfsd/nfs2acl.c
++++ b/fs/nfsd/nfs2acl.c
+@@ -14,6 +14,7 @@
+ #include 
+ #include 
+ #include 
++#include "vfs.h"
+ 
+ #define NFSDDBG_FACILITY		NFSDDBG_PROC
+ #define RETURN_STATUS(st)	{ resp->status = (st); return (st); }
+diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c
+index ff73596eb550..526d85a65f76 100644
+--- a/fs/nfsd/nfs3acl.c
++++ b/fs/nfsd/nfs3acl.c
+@@ -13,6 +13,7 @@
+ #include 
+ #include 
+ #include 
++#include "vfs.h"
+ 
+ #define RETURN_STATUS(st)	{ resp->status = (st); return (st); }
+ 
+diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
+index a713c418a922..1a259d313e14 100644
+--- a/fs/nfsd/nfs3proc.c
++++ b/fs/nfsd/nfs3proc.c
+@@ -25,6 +25,7 @@
+ #include 
+ #include 
+ #include 
++#include "vfs.h"
+ 
+ #define NFSDDBG_FACILITY		NFSDDBG_PROC
+ 
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index bebc0c2e1b0a..60a93cdefef5 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -48,6 +48,7 @@
+ #include 
+ #include 
+ #include 
++#include "vfs.h"
+ 
+ #define NFSDDBG_FACILITY		NFSDDBG_PROC
+ 
+diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
+index b5348405046b..c7a6b245c7ad 100644
+--- a/fs/nfsd/nfs4recover.c
++++ b/fs/nfsd/nfs4recover.c
+@@ -47,6 +47,7 @@
+ #include 
+ #include 
+ #include 
++#include "vfs.h"
+ 
+ #define NFSDDBG_FACILITY                NFSDDBG_PROC
+ 
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index c8b621a120cd..850960e5d626 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -56,6 +56,7 @@
+ #include 
+ #include 
+ #include 
++#include "vfs.h"
+ 
+ #define NFSDDBG_FACILITY                NFSDDBG_PROC
+ 
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index 0fbd50cee1f6..db0fc55670b3 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -57,6 +57,7 @@
+ #include 
+ #include 
+ #include 
++#include "vfs.h"
+ 
+ #define NFSDDBG_FACILITY		NFSDDBG_XDR
+ 
+diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
+index 01965b2f3a76..d0d8a217a3ea 100644
+--- a/fs/nfsd/nfsfh.c
++++ b/fs/nfsd/nfsfh.c
+@@ -22,6 +22,7 @@
+ #include 
+ #include 
+ #include 
++#include "vfs.h"
+ #include "auth.h"
+ 
+ #define NFSDDBG_FACILITY		NFSDDBG_FH
+diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
+index c5393d1b8955..6c967e1ba37b 100644
+--- a/fs/nfsd/nfsproc.c
++++ b/fs/nfsd/nfsproc.c
+@@ -24,6 +24,7 @@
+ #include 
+ #include 
+ #include 
++#include "vfs.h"
+ 
+ typedef struct svc_rqst	svc_rqst;
+ typedef struct svc_buf	svc_buf;
+diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
+index 67ea83eedd43..2944b31dcbe6 100644
+--- a/fs/nfsd/nfssvc.c
++++ b/fs/nfsd/nfssvc.c
+@@ -35,6 +35,7 @@
+ #include 
+ #include 
+ #include 
++#include "vfs.h"
+ 
+ #define NFSDDBG_FACILITY	NFSDDBG_SVC
+ 
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index 638573968dcf..a7038ede671a 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -56,6 +56,7 @@
+ #endif /* CONFIG_NFSD_V4 */
+ #include 
+ #include 
++#include "vfs.h"
+ 
+ #include 
+ 
+diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
+new file mode 100644
+index 000000000000..b8011fd2fcab
+--- /dev/null
++++ b/fs/nfsd/vfs.h
+@@ -0,0 +1,98 @@
++/*
++ * Copyright (C) 1995-1997 Olaf Kirch 
++ */
++
++#ifndef LINUX_NFSD_VFS_H
++#define LINUX_NFSD_VFS_H
++
++/*
++ * Flags for nfsd_permission
++ */
++#define NFSD_MAY_NOP		0
++#define NFSD_MAY_EXEC		1 /* == MAY_EXEC */
++#define NFSD_MAY_WRITE		2 /* == MAY_WRITE */
++#define NFSD_MAY_READ		4 /* == MAY_READ */
++#define NFSD_MAY_SATTR		8
++#define NFSD_MAY_TRUNC		16
++#define NFSD_MAY_LOCK		32
++#define NFSD_MAY_OWNER_OVERRIDE	64
++#define NFSD_MAY_LOCAL_ACCESS	128 /* IRIX doing local access check on device special file*/
++#define NFSD_MAY_BYPASS_GSS_ON_ROOT 256
++
++#define NFSD_MAY_CREATE		(NFSD_MAY_EXEC|NFSD_MAY_WRITE)
++#define NFSD_MAY_REMOVE		(NFSD_MAY_EXEC|NFSD_MAY_WRITE|NFSD_MAY_TRUNC)
++
++/*
++ * Callback function for readdir
++ */
++typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int);
++
++/* nfsd/vfs.c */
++int		fh_lock_parent(struct svc_fh *, struct dentry *);
++int		nfsd_racache_init(int);
++void		nfsd_racache_shutdown(void);
++int		nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
++		                struct svc_export **expp);
++__be32		nfsd_lookup(struct svc_rqst *, struct svc_fh *,
++				const char *, unsigned int, struct svc_fh *);
++__be32		 nfsd_lookup_dentry(struct svc_rqst *, struct svc_fh *,
++				const char *, unsigned int,
++				struct svc_export **, struct dentry **);
++__be32		nfsd_setattr(struct svc_rqst *, struct svc_fh *,
++				struct iattr *, int, time_t);
++#ifdef CONFIG_NFSD_V4
++__be32          nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
++                    struct nfs4_acl *);
++int             nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **);
++#endif /* CONFIG_NFSD_V4 */
++__be32		nfsd_create(struct svc_rqst *, struct svc_fh *,
++				char *name, int len, struct iattr *attrs,
++				int type, dev_t rdev, struct svc_fh *res);
++#ifdef CONFIG_NFSD_V3
++__be32		nfsd_access(struct svc_rqst *, struct svc_fh *, u32 *, u32 *);
++__be32		nfsd_create_v3(struct svc_rqst *, struct svc_fh *,
++				char *name, int len, struct iattr *attrs,
++				struct svc_fh *res, int createmode,
++				u32 *verifier, int *truncp, int *created);
++__be32		nfsd_commit(struct svc_rqst *, struct svc_fh *,
++				loff_t, unsigned long);
++#endif /* CONFIG_NFSD_V3 */
++__be32		nfsd_open(struct svc_rqst *, struct svc_fh *, int,
++				int, struct file **);
++void		nfsd_close(struct file *);
++__be32 		nfsd_read(struct svc_rqst *, struct svc_fh *, struct file *,
++				loff_t, struct kvec *, int, unsigned long *);
++__be32 		nfsd_write(struct svc_rqst *, struct svc_fh *,struct file *,
++				loff_t, struct kvec *,int, unsigned long *, int *);
++__be32		nfsd_readlink(struct svc_rqst *, struct svc_fh *,
++				char *, int *);
++__be32		nfsd_symlink(struct svc_rqst *, struct svc_fh *,
++				char *name, int len, char *path, int plen,
++				struct svc_fh *res, struct iattr *);
++__be32		nfsd_link(struct svc_rqst *, struct svc_fh *,
++				char *, int, struct svc_fh *);
++__be32		nfsd_rename(struct svc_rqst *,
++				struct svc_fh *, char *, int,
++				struct svc_fh *, char *, int);
++__be32		nfsd_remove(struct svc_rqst *,
++				struct svc_fh *, char *, int);
++__be32		nfsd_unlink(struct svc_rqst *, struct svc_fh *, int type,
++				char *name, int len);
++int		nfsd_truncate(struct svc_rqst *, struct svc_fh *,
++				unsigned long size);
++__be32		nfsd_readdir(struct svc_rqst *, struct svc_fh *,
++			     loff_t *, struct readdir_cd *, filldir_t);
++__be32		nfsd_statfs(struct svc_rqst *, struct svc_fh *,
++				struct kstatfs *, int access);
++
++int		nfsd_notify_change(struct inode *, struct iattr *);
++__be32		nfsd_permission(struct svc_rqst *, struct svc_export *,
++				struct dentry *, int);
++int		nfsd_sync_dir(struct dentry *dp);
++
++#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
++struct posix_acl *nfsd_get_posix_acl(struct svc_fh *, int);
++int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *);
++#endif
++
++#endif /* LINUX_NFSD_VFS_H */
+diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
+index 510ffdd5020e..e4518d090a8c 100644
+--- a/include/linux/nfsd/nfsd.h
++++ b/include/linux/nfsd/nfsd.h
+@@ -25,30 +25,10 @@
+  */
+ #define NFSD_SUPPORTED_MINOR_VERSION	1
+ 
+-/*
+- * Flags for nfsd_permission
+- */
+-#define NFSD_MAY_NOP		0
+-#define NFSD_MAY_EXEC		1 /* == MAY_EXEC */
+-#define NFSD_MAY_WRITE		2 /* == MAY_WRITE */
+-#define NFSD_MAY_READ		4 /* == MAY_READ */
+-#define NFSD_MAY_SATTR		8
+-#define NFSD_MAY_TRUNC		16
+-#define NFSD_MAY_LOCK		32
+-#define NFSD_MAY_OWNER_OVERRIDE	64
+-#define NFSD_MAY_LOCAL_ACCESS	128 /* IRIX doing local access check on device special file*/
+-#define NFSD_MAY_BYPASS_GSS_ON_ROOT 256
+-
+-#define NFSD_MAY_CREATE		(NFSD_MAY_EXEC|NFSD_MAY_WRITE)
+-#define NFSD_MAY_REMOVE		(NFSD_MAY_EXEC|NFSD_MAY_WRITE|NFSD_MAY_TRUNC)
+-
+-/*
+- * Callback function for readdir
+- */
+ struct readdir_cd {
+ 	__be32			err;	/* 0, nfserr, or nfserr_eof */
+ };
+-typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int);
++
+ 
+ extern struct svc_program	nfsd_program;
+ extern struct svc_version	nfsd_version2, nfsd_version3,
+@@ -73,69 +53,6 @@ int		nfsd_nrpools(void);
+ int		nfsd_get_nrthreads(int n, int *);
+ int		nfsd_set_nrthreads(int n, int *);
+ 
+-/* nfsd/vfs.c */
+-int		fh_lock_parent(struct svc_fh *, struct dentry *);
+-int		nfsd_racache_init(int);
+-void		nfsd_racache_shutdown(void);
+-int		nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
+-		                struct svc_export **expp);
+-__be32		nfsd_lookup(struct svc_rqst *, struct svc_fh *,
+-				const char *, unsigned int, struct svc_fh *);
+-__be32		 nfsd_lookup_dentry(struct svc_rqst *, struct svc_fh *,
+-				const char *, unsigned int,
+-				struct svc_export **, struct dentry **);
+-__be32		nfsd_setattr(struct svc_rqst *, struct svc_fh *,
+-				struct iattr *, int, time_t);
+-#ifdef CONFIG_NFSD_V4
+-__be32          nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
+-                    struct nfs4_acl *);
+-int             nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **);
+-#endif /* CONFIG_NFSD_V4 */
+-__be32		nfsd_create(struct svc_rqst *, struct svc_fh *,
+-				char *name, int len, struct iattr *attrs,
+-				int type, dev_t rdev, struct svc_fh *res);
+-#ifdef CONFIG_NFSD_V3
+-__be32		nfsd_access(struct svc_rqst *, struct svc_fh *, u32 *, u32 *);
+-__be32		nfsd_create_v3(struct svc_rqst *, struct svc_fh *,
+-				char *name, int len, struct iattr *attrs,
+-				struct svc_fh *res, int createmode,
+-				u32 *verifier, int *truncp, int *created);
+-__be32		nfsd_commit(struct svc_rqst *, struct svc_fh *,
+-				loff_t, unsigned long);
+-#endif /* CONFIG_NFSD_V3 */
+-__be32		nfsd_open(struct svc_rqst *, struct svc_fh *, int,
+-				int, struct file **);
+-void		nfsd_close(struct file *);
+-__be32 		nfsd_read(struct svc_rqst *, struct svc_fh *, struct file *,
+-				loff_t, struct kvec *, int, unsigned long *);
+-__be32 		nfsd_write(struct svc_rqst *, struct svc_fh *,struct file *,
+-				loff_t, struct kvec *,int, unsigned long *, int *);
+-__be32		nfsd_readlink(struct svc_rqst *, struct svc_fh *,
+-				char *, int *);
+-__be32		nfsd_symlink(struct svc_rqst *, struct svc_fh *,
+-				char *name, int len, char *path, int plen,
+-				struct svc_fh *res, struct iattr *);
+-__be32		nfsd_link(struct svc_rqst *, struct svc_fh *,
+-				char *, int, struct svc_fh *);
+-__be32		nfsd_rename(struct svc_rqst *,
+-				struct svc_fh *, char *, int,
+-				struct svc_fh *, char *, int);
+-__be32		nfsd_remove(struct svc_rqst *,
+-				struct svc_fh *, char *, int);
+-__be32		nfsd_unlink(struct svc_rqst *, struct svc_fh *, int type,
+-				char *name, int len);
+-int		nfsd_truncate(struct svc_rqst *, struct svc_fh *,
+-				unsigned long size);
+-__be32		nfsd_readdir(struct svc_rqst *, struct svc_fh *,
+-			     loff_t *, struct readdir_cd *, filldir_t);
+-__be32		nfsd_statfs(struct svc_rqst *, struct svc_fh *,
+-				struct kstatfs *, int access);
+-
+-int		nfsd_notify_change(struct inode *, struct iattr *);
+-__be32		nfsd_permission(struct svc_rqst *, struct svc_export *,
+-				struct dentry *, int);
+-int		nfsd_sync_dir(struct dentry *dp);
+-
+ #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
+ #ifdef CONFIG_NFSD_V2_ACL
+ extern struct svc_version nfsd_acl_version2;
+@@ -147,8 +64,6 @@ extern struct svc_version nfsd_acl_version3;
+ #else
+ #define nfsd_acl_version3 NULL
+ #endif
+-struct posix_acl *nfsd_get_posix_acl(struct svc_fh *, int);
+-int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *);
+ #endif
+ 
+ enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL };

commit ea4878a24d7e6a467d369b962bab95bd6a12cbe0
+Author: J. Bruce Fields 
+Date:   Fri Nov 6 13:59:43 2009 -0500
+
+    nfs: move more to Documentation/filesystems/nfs
+    
+    Oops: I missed two files in the first commit that created this
+    directory.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
+index 482151c883a5..658154f52557 100644
+--- a/Documentation/filesystems/00-INDEX
++++ b/Documentation/filesystems/00-INDEX
+@@ -84,8 +84,6 @@ relay.txt
+ 	- info on relay, for efficient streaming from kernel to user space.
+ romfs.txt
+ 	- description of the ROMFS filesystem.
+-rpc-cache.txt
+-	- introduction to the caching mechanisms in the sunrpc layer.
+ seq_file.txt
+ 	- how to use the seq_file API
+ sharedsubtree.txt
+diff --git a/Documentation/filesystems/nfs/00-INDEX b/Documentation/filesystems/nfs/00-INDEX
+index 6ff3d212027b..2f68cd688769 100644
+--- a/Documentation/filesystems/nfs/00-INDEX
++++ b/Documentation/filesystems/nfs/00-INDEX
+@@ -2,6 +2,8 @@
+ 	- this file (nfs-related documentation).
+ Exporting
+ 	- explanation of how to make filesystems exportable.
++knfsd-stats.txt
++	- statistics which the NFS server makes available to user space.
+ nfs.txt
+ 	- nfs client, and DNS resolution for fs_locations.
+ nfs41-server.txt
+@@ -10,3 +12,5 @@ nfs-rdma.txt
+ 	- how to install and setup the Linux NFS/RDMA client and server software
+ nfsroot.txt
+ 	- short guide on setting up a diskless box with NFS root filesystem.
++rpc-cache.txt
++	- introduction to the caching mechanisms in the sunrpc layer.
+diff --git a/Documentation/filesystems/knfsd-stats.txt b/Documentation/filesystems/nfs/knfsd-stats.txt
+similarity index 100%
+rename from Documentation/filesystems/knfsd-stats.txt
+rename to Documentation/filesystems/nfs/knfsd-stats.txt
+diff --git a/Documentation/filesystems/rpc-cache.txt b/Documentation/filesystems/nfs/rpc-cache.txt
+similarity index 100%
+rename from Documentation/filesystems/rpc-cache.txt
+rename to Documentation/filesystems/nfs/rpc-cache.txt

commit dc83d6e27fa80babe31c80aa8568f125f72edf57
+Author: J. Bruce Fields 
+Date:   Tue Oct 20 18:51:34 2009 -0400
+
+    nfsd4: don't try to map gid's in generic rpc code
+    
+    For nfsd we provide users the option of mapping uid's to server-side
+    supplementary group lists.  That makes sense for nfsd, but not
+    necessarily for other rpc users (such as the callback client).
+    
+    So move that lookup to svcauth_unix_set_client, which is a
+    program-specific method.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
+index 117f68a8aa40..97cc3de7432e 100644
+--- a/net/sunrpc/svcauth_unix.c
++++ b/net/sunrpc/svcauth_unix.c
+@@ -655,23 +655,25 @@ static struct unix_gid *unix_gid_lookup(uid_t uid)
+ 		return NULL;
+ }
+ 
+-static int unix_gid_find(uid_t uid, struct group_info **gip,
+-			 struct svc_rqst *rqstp)
++static struct group_info *unix_gid_find(uid_t uid, struct svc_rqst *rqstp)
+ {
+-	struct unix_gid *ug = unix_gid_lookup(uid);
++	struct unix_gid *ug;
++	struct group_info *gi;
++	int ret;
++
++	ug = unix_gid_lookup(uid);
+ 	if (!ug)
+-		return -EAGAIN;
+-	switch (cache_check(&unix_gid_cache, &ug->h, &rqstp->rq_chandle)) {
++		return ERR_PTR(-EAGAIN);
++	ret = cache_check(&unix_gid_cache, &ug->h, &rqstp->rq_chandle);
++	switch (ret) {
+ 	case -ENOENT:
+-		*gip = NULL;
+-		return 0;
++		return ERR_PTR(-ENOENT);
+ 	case 0:
+-		*gip = ug->gi;
+-		get_group_info(*gip);
++		gi = get_group_info(ug->gi);
+ 		cache_put(&ug->h, &unix_gid_cache);
+-		return 0;
++		return gi;
+ 	default:
+-		return -EAGAIN;
++		return ERR_PTR(-EAGAIN);
+ 	}
+ }
+ 
+@@ -681,6 +683,8 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
+ 	struct sockaddr_in *sin;
+ 	struct sockaddr_in6 *sin6, sin6_storage;
+ 	struct ip_map *ipm;
++	struct group_info *gi;
++	struct svc_cred *cred = &rqstp->rq_cred;
+ 
+ 	switch (rqstp->rq_addr.ss_family) {
+ 	case AF_INET:
+@@ -722,6 +726,17 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
+ 			ip_map_cached_put(rqstp, ipm);
+ 			break;
+ 	}
++
++	gi = unix_gid_find(cred->cr_uid, rqstp);
++	switch (PTR_ERR(gi)) {
++	case -EAGAIN:
++		return SVC_DROP;
++	case -ENOENT:
++		break;
++	default:
++		put_group_info(cred->cr_group_info);
++		cred->cr_group_info = gi;
++	}
+ 	return SVC_OK;
+ }
+ 
+@@ -818,19 +833,11 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
+ 	slen = svc_getnl(argv);			/* gids length */
+ 	if (slen > 16 || (len -= (slen + 2)*4) < 0)
+ 		goto badcred;
+-	if (unix_gid_find(cred->cr_uid, &cred->cr_group_info, rqstp)
+-	    == -EAGAIN)
++	cred->cr_group_info = groups_alloc(slen);
++	if (cred->cr_group_info == NULL)
+ 		return SVC_DROP;
+-	if (cred->cr_group_info == NULL) {
+-		cred->cr_group_info = groups_alloc(slen);
+-		if (cred->cr_group_info == NULL)
+-			return SVC_DROP;
+-		for (i = 0; i < slen; i++)
+-			GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv);
+-	} else {
+-		for (i = 0; i < slen ; i++)
+-			svc_getnl(argv);
+-	}
++	for (i = 0; i < slen; i++)
++		GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv);
+ 	if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
+ 		*authp = rpc_autherr_badverf;
+ 		return SVC_DENIED;

commit efe0cb6d5a1f20ad4df045a055048afed4c5e660
+Author: J. Bruce Fields 
+Date:   Sat Oct 24 20:52:16 2009 -0400
+
+    nfsd4.1: common slot allocation size calculation
+    
+    We do the same calculation in a couple places; use a helper function,
+    and add a little documentation, in the hopes of preventing bugs like
+    that fixed in the last patch.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index c17137110412..42dab9587afe 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -524,6 +524,15 @@ free_session_slots(struct nfsd4_session *ses)
+ 		kfree(ses->se_slots[i]);
+ }
+ 
++/*
++ * We don't actually need to cache the rpc and session headers, so we
++ * can allocate a little less for each slot:
++ */
++static inline int slot_bytes(struct nfsd4_channel_attrs *ca)
++{
++	return ca->maxresp_cached - NFSD_MIN_HDR_SEQ_SZ;
++}
++
+ static int
+ alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp,
+ 		   struct nfsd4_create_session *cses)
+@@ -555,7 +564,7 @@ alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp,
+ 	memcpy(new, &tmp, sizeof(*new));
+ 
+ 	/* allocate each struct nfsd4_slot and data cache in one piece */
+-	cachesize = new->se_fchannel.maxresp_cached - NFSD_MIN_HDR_SEQ_SZ;
++	cachesize = slot_bytes(&new->se_fchannel);
+ 	for (i = 0; i < new->se_fchannel.maxreqs; i++) {
+ 		sp = kzalloc(sizeof(*sp) + cachesize, GFP_KERNEL);
+ 		if (!sp)
+@@ -633,8 +642,7 @@ free_session(struct kref *kref)
+ 
+ 	ses = container_of(kref, struct nfsd4_session, se_ref);
+ 	spin_lock(&nfsd_drc_lock);
+-	mem = ses->se_fchannel.maxreqs
+-		* (ses->se_fchannel.maxresp_cached - NFSD_MIN_HDR_SEQ_SZ);
++	mem = ses->se_fchannel.maxreqs * slot_bytes(&ses->se_fchannel);
+ 	nfsd_drc_mem_used -= mem;
+ 	spin_unlock(&nfsd_drc_lock);
+ 	free_session_slots(ses);

commit dd829c45640ff14d7a039af40b3b3975f1b2e484
+Author: J. Bruce Fields 
+Date:   Wed Oct 21 17:54:13 2009 -0400
+
+    nfsd4.1: fix session memory use calculation
+    
+    Unbalanced calculations on creation and destruction of sessions could
+    cause our estimate of cache memory used to become negative, sometimes
+    resulting in spurious SERVERFAULT returns to client CREATE_SESSION
+    requests.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index fcb9817881a1..c17137110412 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -629,10 +629,13 @@ void
+ free_session(struct kref *kref)
+ {
+ 	struct nfsd4_session *ses;
++	int mem;
+ 
+ 	ses = container_of(kref, struct nfsd4_session, se_ref);
+ 	spin_lock(&nfsd_drc_lock);
+-	nfsd_drc_mem_used -= ses->se_fchannel.maxreqs * NFSD_SLOT_CACHE_SIZE;
++	mem = ses->se_fchannel.maxreqs
++		* (ses->se_fchannel.maxresp_cached - NFSD_MIN_HDR_SEQ_SZ);
++	nfsd_drc_mem_used -= mem;
+ 	spin_unlock(&nfsd_drc_lock);
+ 	free_session_slots(ses);
+ 	kfree(ses);

commit dc7a08166f3a5f23e79e839a8a88849bd3397c32
+Author: J. Bruce Fields 
+Date:   Tue Oct 27 14:41:35 2009 -0400
+
+    nfs: new subdir Documentation/filesystems/nfs
+    
+    We're adding enough nfs documentation that it may as well have its own
+    subdirectory.
+    
+    Acked-by: Randy Dunlap 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
+index f15621ee5599..482151c883a5 100644
+--- a/Documentation/filesystems/00-INDEX
++++ b/Documentation/filesystems/00-INDEX
+@@ -1,7 +1,5 @@
+ 00-INDEX
+ 	- this file (info on some of the filesystems supported by linux).
+-Exporting
+-	- explanation of how to make filesystems exportable.
+ Locking
+ 	- info on locking rules as they pertain to Linux VFS.
+ 9p.txt
+@@ -66,12 +64,8 @@ mandatory-locking.txt
+ 	- info on the Linux implementation of Sys V mandatory file locking.
+ ncpfs.txt
+ 	- info on Novell Netware(tm) filesystem using NCP protocol.
+-nfs41-server.txt
+-	- info on the Linux server implementation of NFSv4 minor version 1.
+-nfs-rdma.txt
+-	- how to install and setup the Linux NFS/RDMA client and server software.
+-nfsroot.txt
+-	- short guide on setting up a diskless box with NFS root filesystem.
++nfs/
++	- nfs-related documentation.
+ nilfs2.txt
+ 	- info and mount options for the NILFS2 filesystem.
+ ntfs.txt
+diff --git a/Documentation/filesystems/nfs/00-INDEX b/Documentation/filesystems/nfs/00-INDEX
+new file mode 100644
+index 000000000000..6ff3d212027b
+--- /dev/null
++++ b/Documentation/filesystems/nfs/00-INDEX
+@@ -0,0 +1,12 @@
++00-INDEX
++	- this file (nfs-related documentation).
++Exporting
++	- explanation of how to make filesystems exportable.
++nfs.txt
++	- nfs client, and DNS resolution for fs_locations.
++nfs41-server.txt
++	- info on the Linux server implementation of NFSv4 minor version 1.
++nfs-rdma.txt
++	- how to install and setup the Linux NFS/RDMA client and server software
++nfsroot.txt
++	- short guide on setting up a diskless box with NFS root filesystem.
+diff --git a/Documentation/filesystems/Exporting b/Documentation/filesystems/nfs/Exporting
+similarity index 100%
+rename from Documentation/filesystems/Exporting
+rename to Documentation/filesystems/nfs/Exporting
+diff --git a/Documentation/filesystems/nfs-rdma.txt b/Documentation/filesystems/nfs/nfs-rdma.txt
+similarity index 100%
+rename from Documentation/filesystems/nfs-rdma.txt
+rename to Documentation/filesystems/nfs/nfs-rdma.txt
+diff --git a/Documentation/filesystems/nfs.txt b/Documentation/filesystems/nfs/nfs.txt
+similarity index 100%
+rename from Documentation/filesystems/nfs.txt
+rename to Documentation/filesystems/nfs/nfs.txt
+diff --git a/Documentation/filesystems/nfs41-server.txt b/Documentation/filesystems/nfs/nfs41-server.txt
+similarity index 100%
+rename from Documentation/filesystems/nfs41-server.txt
+rename to Documentation/filesystems/nfs/nfs41-server.txt
+diff --git a/Documentation/filesystems/nfsroot.txt b/Documentation/filesystems/nfs/nfsroot.txt
+similarity index 100%
+rename from Documentation/filesystems/nfsroot.txt
+rename to Documentation/filesystems/nfs/nfsroot.txt
+diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting
+index 92b888d540a6..a7e9746ee7ea 100644
+--- a/Documentation/filesystems/porting
++++ b/Documentation/filesystems/porting
+@@ -140,7 +140,7 @@ Callers of notify_change() need ->i_mutex now.
+ New super_block field "struct export_operations *s_export_op" for
+ explicit support for exporting, e.g. via NFS.  The structure is fully
+ documented at its declaration in include/linux/fs.h, and in
+-Documentation/filesystems/Exporting.
++Documentation/filesystems/nfs/Exporting.
+ 
+ Briefly it allows for the definition of decode_fh and encode_fh operations
+ to encode and decode filehandles, and allows the filesystem to use
+diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
+index 9107b387e91f..dab0f04b4264 100644
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -1017,7 +1017,7 @@ and is between 256 and 4096 characters. It is defined in the file
+ 			No delay
+ 
+ 	ip=		[IP_PNP]
+-			See Documentation/filesystems/nfsroot.txt.
++			See Documentation/filesystems/nfs/nfsroot.txt.
+ 
+ 	ip2=		[HW] Set IO/IRQ pairs for up to 4 IntelliPort boards
+ 			See comment before ip2_setup() in
+@@ -1538,10 +1538,10 @@ and is between 256 and 4096 characters. It is defined in the file
+ 			going to be removed in 2.6.29.
+ 
+ 	nfsaddrs=	[NFS]
+-			See Documentation/filesystems/nfsroot.txt.
++			See Documentation/filesystems/nfs/nfsroot.txt.
+ 
+ 	nfsroot=	[NFS] nfs root filesystem for disk-less boxes.
+-			See Documentation/filesystems/nfsroot.txt.
++			See Documentation/filesystems/nfs/nfsroot.txt.
+ 
+ 	nfs.callback_tcpport=
+ 			[NFS] set the TCP port on which the NFSv4 callback
+diff --git a/fs/cifs/export.c b/fs/cifs/export.c
+index 75949d6a5f1b..6177f7cca16a 100644
+--- a/fs/cifs/export.c
++++ b/fs/cifs/export.c
+@@ -24,7 +24,7 @@
+  */
+ 
+  /*
+-  * See Documentation/filesystems/Exporting
++  * See Documentation/filesystems/nfs/Exporting
+   * and examples in fs/exportfs
+   *
+   * Since cifs is a network file system, an "fsid" must be included for
+diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
+index 197c7db583c7..e9e175949a63 100644
+--- a/fs/exportfs/expfs.c
++++ b/fs/exportfs/expfs.c
+@@ -6,7 +6,7 @@
+  * and for mapping back from file handles to dentries.
+  *
+  * For details on why we do all the strange and hairy things in here
+- * take a look at Documentation/filesystems/Exporting.
++ * take a look at Documentation/filesystems/nfs/Exporting.
+  */
+ #include 
+ #include 
+diff --git a/fs/isofs/export.c b/fs/isofs/export.c
+index e81a30593ba9..ed752cb38474 100644
+--- a/fs/isofs/export.c
++++ b/fs/isofs/export.c
+@@ -9,7 +9,7 @@
+  *
+  * The following files are helpful:
+  *
+- *     Documentation/filesystems/Exporting
++ *     Documentation/filesystems/nfs/Exporting
+  *     fs/exportfs/expfs.c.
+  */
+ 
+diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
+index 2a77bc25d5af..59e5673b4597 100644
+--- a/fs/nfs/Kconfig
++++ b/fs/nfs/Kconfig
+@@ -90,7 +90,7 @@ config ROOT_NFS
+ 	  If you want your system to mount its root file system via NFS,
+ 	  choose Y here.  This is common practice for managing systems
+ 	  without local permanent storage.  For details, read
+-	  .
++	  .
+ 
+ 	  Most people say N here.
+ 
+diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h
+index 27e772cefb6a..dc12f416a49f 100644
+--- a/include/linux/exportfs.h
++++ b/include/linux/exportfs.h
+@@ -97,7 +97,7 @@ struct fid {
+  * @get_name:       find the name for a given inode in a given directory
+  * @get_parent:     find the parent of a given directory
+  *
+- * See Documentation/filesystems/Exporting for details on how to use
++ * See Documentation/filesystems/nfs/Exporting for details on how to use
+  * this interface correctly.
+  *
+  * encode_fh:
+diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
+index 70491d9035eb..0c94a1ac2946 100644
+--- a/net/ipv4/Kconfig
++++ b/net/ipv4/Kconfig
+@@ -166,7 +166,7 @@ config IP_PNP_DHCP
+ 
+ 	  If unsure, say Y. Note that if you want to use DHCP, a DHCP server
+ 	  must be operating on your network.  Read
+-	   for details.
++	   for details.
+ 
+ config IP_PNP_BOOTP
+ 	bool "IP: BOOTP support"
+@@ -181,7 +181,7 @@ config IP_PNP_BOOTP
+ 	  does BOOTP itself, providing all necessary information on the kernel
+ 	  command line, you can say N here. If unsure, say Y. Note that if you
+ 	  want to use BOOTP, a BOOTP server must be operating on your network.
+-	  Read  for details.
++	  Read  for details.
+ 
+ config IP_PNP_RARP
+ 	bool "IP: RARP support"
+@@ -194,7 +194,7 @@ config IP_PNP_RARP
+ 	  older protocol which is being obsoleted by BOOTP and DHCP), say Y
+ 	  here. Note that if you want to use RARP, a RARP server must be
+ 	  operating on your network. Read
+-	   for details.
++	   for details.
+ 
+ # not yet ready..
+ #   bool '    IP: ARP support' CONFIG_IP_PNP_ARP
+diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
+index f8d04c256454..7dcbf4706099 100644
+--- a/net/ipv4/ipconfig.c
++++ b/net/ipv4/ipconfig.c
+@@ -1447,7 +1447,7 @@ late_initcall(ip_auto_config);
+ 
+ /*
+  *  Decode any IP configuration options in the "ip=" or "nfsaddrs=" kernel
+- *  command line parameter.  See Documentation/filesystems/nfsroot.txt.
++ *  command line parameter.  See Documentation/filesystems/nfs/nfsroot.txt.
+  */
+ static int __init ic_proto_name(char *name)
+ {

commit e343eb0d60f74547e0aeb5bd151105c2e6cfe588
+Merge: ddc04fd4d516 012abeea669e
+Author: J. Bruce Fields 
+Date:   Tue Oct 27 18:45:17 2009 -0400
+
+    Merge commit 'v2.6.32-rc5' into for-2.6.33
+

commit f39bde24b275ddc45df1ed835725b609e178c7a0
+Author: J. Bruce Fields 
+Date:   Sun Sep 27 14:41:43 2009 -0400
+
+    nfsd4: fix error return when pseudoroot missing
+    
+    We really shouldn't hit this case at all, and forthcoming kernel and
+    nfs-utils changes should eliminate this case; if it does happen,
+    consider it a bug rather than reporting an error that doesn't really
+    make sense for the operation (since there's no reason for a server to be
+    accepting v4 traffic yet have no root filehandle).
+    
+    Also move some exp_pseudoroot code into a helper function while we're
+    here.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
+index c1c9e035d4a4..b73baba3fb97 100644
+--- a/fs/nfsd/export.c
++++ b/fs/nfsd/export.c
+@@ -1320,6 +1320,23 @@ rqst_exp_parent(struct svc_rqst *rqstp, struct path *path)
+ 	return exp;
+ }
+ 
++static struct svc_export *find_fsidzero_export(struct svc_rqst *rqstp)
++{
++	struct svc_export *exp;
++	u32 fsidv[2];
++
++	mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL);
++
++	exp = rqst_exp_find(rqstp, FSID_NUM, fsidv);
++	/*
++	 * We shouldn't have accepting an nfsv4 request at all if we
++	 * don't have a pseudoexport!:
++	 */
++	if (IS_ERR(exp) && PTR_ERR(exp) == -ENOENT)
++		exp = ERR_PTR(-ESERVERFAULT);
++	return exp;
++}
++
+ /*
+  * Called when we need the filehandle for the root of the pseudofs,
+  * for a given NFSv4 client.   The root is defined to be the
+@@ -1330,11 +1347,8 @@ exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp)
+ {
+ 	struct svc_export *exp;
+ 	__be32 rv;
+-	u32 fsidv[2];
+-
+-	mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL);
+ 
+-	exp = rqst_exp_find(rqstp, FSID_NUM, fsidv);
++	exp = find_fsidzero_export(rqstp);
+ 	if (IS_ERR(exp))
+ 		return nfserrno(PTR_ERR(exp));
+ 	rv = fh_compose(fhp, exp, exp->ex_path.dentry, NULL);
+diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
+index 0eb9c820b7a6..c5393d1b8955 100644
+--- a/fs/nfsd/nfsproc.c
++++ b/fs/nfsd/nfsproc.c
+@@ -758,6 +758,7 @@ nfserrno (int errno)
+ 		{ nfserr_io, -ETXTBSY },
+ 		{ nfserr_notsupp, -EOPNOTSUPP },
+ 		{ nfserr_toosmall, -ETOOSMALL },
++		{ nfserr_serverfault, -ESERVERFAULT },
+ 	};
+ 	int	i;
+ 

commit 289ede453e5a621de19c61e630302b1845cc1d59
+Author: J. Bruce Fields 
+Date:   Sat Sep 26 20:32:24 2009 -0400
+
+    nfsd: minor nfsd_lookup cleanup
+    
+    Break out some of nfsd_lookup_dentry into helper functions.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index b8ed58bab8b1..638573968dcf 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -141,6 +141,40 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
+ 	return err;
+ }
+ 
++static void follow_to_parent(struct path *path)
++{
++	struct dentry *dp;
++
++	while (path->dentry == path->mnt->mnt_root && follow_up(path))
++		;
++	dp = dget_parent(path->dentry);
++	dput(path->dentry);
++	path->dentry = dp;
++}
++
++static int nfsd_lookup_parent(struct svc_rqst *rqstp, struct dentry *dparent, struct svc_export **exp, struct dentry **dentryp)
++{
++	struct svc_export *exp2;
++	struct path path = {.mnt = mntget((*exp)->ex_path.mnt),
++			    .dentry = dget(dparent)};
++
++	follow_to_parent(&path);
++
++	exp2 = rqst_exp_parent(rqstp, &path);
++	if (PTR_ERR(exp2) == -ENOENT) {
++		*dentryp = dget(dparent);
++	} else if (IS_ERR(exp2)) {
++		path_put(&path);
++		return PTR_ERR(exp2);
++	} else {
++		*dentryp = dget(path.dentry);
++		exp_put(*exp);
++		*exp = exp2;
++	}
++	path_put(&path);
++	return 0;
++}
++
+ __be32
+ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ 		   const char *name, unsigned int len,
+@@ -173,31 +207,9 @@ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ 			dentry = dget(dparent); /* .. == . just like at / */
+ 		else {
+ 			/* checking mountpoint crossing is very different when stepping up */
+-			struct svc_export *exp2 = NULL;
+-			struct dentry *dp;
+-			struct path path = {.mnt = mntget(exp->ex_path.mnt),
+-					    .dentry = dget(dparent)};
+-
+-			while (path.dentry == path.mnt->mnt_root &&
+-			       follow_up(&path))
+-				;
+-			dp = dget_parent(path.dentry);
+-			dput(path.dentry);
+-			path.dentry = dp;
+-
+-			exp2 = rqst_exp_parent(rqstp, &path);
+-			if (PTR_ERR(exp2) == -ENOENT) {
+-				dentry = dget(dparent);
+-			} else if (IS_ERR(exp2)) {
+-				host_err = PTR_ERR(exp2);
+-				path_put(&path);
++			host_err = nfsd_lookup_parent(rqstp, dparent, &exp, &dentry);
++			if (host_err)
+ 				goto out_nfserr;
+-			} else {
+-				dentry = dget(path.dentry);
+-				exp_put(exp);
+-				exp = exp2;
+-			}
+-			path_put(&path);
+ 		}
+ 	} else {
+ 		fh_lock(fhp);

commit fed83811269d0f559d2da9139e12c5e5d9874d5c
+Author: J. Bruce Fields 
+Date:   Sat Sep 26 16:53:01 2009 -0400
+
+    nfsd4: cross mountpoints when looking up parents
+    
+    3c394ddaa7ea4205f933fd9b481166b2669368a9 "nfsd4: nfsv4 clients should
+    cross mountpoints" forgot to handle lookups of parents directories.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index a293f0273263..b8ed58bab8b1 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -169,7 +169,7 @@ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ 			dentry = dget(dparent);
+ 		else if (dparent != exp->ex_path.dentry)
+ 			dentry = dget_parent(dparent);
+-		else if (!EX_NOHIDE(exp))
++		else if (!EX_NOHIDE(exp) && !nfsd_v4client(rqstp))
+ 			dentry = dget(dparent); /* .. == . just like at / */
+ 		else {
+ 			/* checking mountpoint crossing is very different when stepping up */

commit 03d6a74b5f85ff46f20e1382982b7f4860f5fec6
+Author: J. Bruce Fields 
+Date:   Tue Sep 22 11:09:12 2009 -0400
+
+    nfsd: fix Documentation typo
+    
+    Caught by Benny, thanks!
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/Documentation/filesystems/nfs41-server.txt b/Documentation/filesystems/nfs41-server.txt
+index 5920fe26e6ff..1f95e7731886 100644
+--- a/Documentation/filesystems/nfs41-server.txt
++++ b/Documentation/filesystems/nfs41-server.txt
+@@ -41,7 +41,7 @@ interoperability problems with future clients.  Known issues:
+ 	  conformant with the spec (for example, we don't use kerberos
+ 	  on the backchannel correctly).
+ 	- no trunking support: no clients currently take advantage of
+-	  trunking, but this is a mandatory failure, and its use is
++	  trunking, but this is a mandatory feature, and its use is
+ 	  recommended to clients in a number of places.  (E.g. to ensure
+ 	  timely renewal in case an existing connection's retry timeouts
+ 	  have gotten too long; see section 8.3 of the draft.)

commit 285a0f00c27a02f1223a198c88de2130e9bab059
+Author: J. Bruce Fields 
+Date:   Sun Sep 20 17:01:33 2009 -0400
+
+    nfsd: revise 4.1 status documentation
+    
+    Some small updates, a caveat about the minorversion control interface,
+    and an attempt to put missing features in context.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/Documentation/filesystems/nfs41-server.txt b/Documentation/filesystems/nfs41-server.txt
+index 05d81cbcb2e1..5920fe26e6ff 100644
+--- a/Documentation/filesystems/nfs41-server.txt
++++ b/Documentation/filesystems/nfs41-server.txt
+@@ -11,6 +11,11 @@ the /proc/fs/nfsd/versions control file.  Note that to write this
+ control file, the nfsd service must be taken down.  Use your user-mode
+ nfs-utils to set this up; see rpc.nfsd(8)
+ 
++(Warning: older servers will interpret "+4.1" and "-4.1" as "+4" and
++"-4", respectively.  Therefore, code meant to work on both new and old
++kernels must turn 4.1 on or off *before* turning support for version 4
++on or off; rpc.nfsd does this correctly.)
++
+ The NFSv4 minorversion 1 (NFSv4.1) implementation in nfsd is based
+ on the latest NFSv4.1 Internet Draft:
+ http://tools.ietf.org/html/draft-ietf-nfsv4-minorversion1-29
+@@ -25,6 +30,49 @@ are still under development out of tree.
+ See http://wiki.linux-nfs.org/wiki/index.php/PNFS_prototype_design
+ for more information.
+ 
++The current implementation is intended for developers only: while it
++does support ordinary file operations on clients we have tested against
++(including the linux client), it is incomplete in ways which may limit
++features unexpectedly, cause known bugs in rare cases, or cause
++interoperability problems with future clients.  Known issues:
++
++	- gss support is questionable: currently mounts with kerberos
++	  from a linux client are possible, but we aren't really
++	  conformant with the spec (for example, we don't use kerberos
++	  on the backchannel correctly).
++	- no trunking support: no clients currently take advantage of
++	  trunking, but this is a mandatory failure, and its use is
++	  recommended to clients in a number of places.  (E.g. to ensure
++	  timely renewal in case an existing connection's retry timeouts
++	  have gotten too long; see section 8.3 of the draft.)
++	  Therefore, lack of this feature may cause future clients to
++	  fail.
++	- Incomplete backchannel support: incomplete backchannel gss
++	  support and no support for BACKCHANNEL_CTL mean that
++	  callbacks (hence delegations and layouts) may not be
++	  available and clients confused by the incomplete
++	  implementation may fail.
++	- Server reboot recovery is unsupported; if the server reboots,
++	  clients may fail.
++	- We do not support SSV, which provides security for shared
++	  client-server state (thus preventing unauthorized tampering
++	  with locks and opens, for example).  It is mandatory for
++	  servers to support this, though no clients use it yet.
++	- Mandatory operations which we do not support, such as
++	  DESTROY_CLIENTID, FREE_STATEID, SECINFO_NO_NAME, and
++	  TEST_STATEID, are not currently used by clients, but will be
++	  (and the spec recommends their uses in common cases), and
++	  clients should not be expected to know how to recover from the
++	  case where they are not supported.  This will eventually cause
++	  interoperability failures.
++
++In addition, some limitations are inherited from the current NFSv4
++implementation:
++
++	- Incomplete delegation enforcement: if a file is renamed or
++	  unlinked, a client holding a delegation may continue to
++	  indefinitely allow opens of the file under the old name.
++
+ The table below, taken from the NFSv4.1 document, lists
+ the operations that are mandatory to implement (REQ), optional
+ (OPT), and NFSv4.0 operations that are required not to implement (MNI)
+@@ -142,6 +190,12 @@ NS*| CB_WANTS_CANCELLED      | OPT       | FDELG,      | Section 20.10 |
+ 
+ Implementation notes:
+ 
++DELEGPURGE:
++* mandatory only for servers that support CLAIM_DELEGATE_PREV and/or
++  CLAIM_DELEG_PREV_FH (which allows clients to keep delegations that
++  persist across client reboots).  Thus we need not implement this for
++  now.
++
+ EXCHANGE_ID:
+ * only SP4_NONE state protection supported
+ * implementation ids are ignored

commit 80fc015bdfe1f5b870c1e1ee02d78e709523fee7
+Author: J. Bruce Fields 
+Date:   Tue Sep 15 18:07:35 2009 -0400
+
+    nfsd4: use common rpc_cred for all callbacks
+    
+    Callbacks are always made using the machine's identity, so we can use a
+    single auth_generic credential shared among callbacks to all clients and
+    let the rpc code take care of the rest.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 4abb88264c72..128519769ea8 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -432,42 +432,29 @@ static const struct rpc_call_ops nfsd4_cb_probe_ops = {
+ 	.rpc_call_done = nfsd4_cb_probe_done,
+ };
+ 
+-static struct rpc_cred *lookup_cb_cred(struct nfs4_cb_conn *cb)
++static struct rpc_cred *callback_cred;
++
++int set_callback_cred(void)
+ {
+-	struct auth_cred acred = {
+-		.machine_cred = 1
+-	};
+-	struct rpc_auth *auth = cb->cb_client->cl_auth;
+-
+-	/*
+-	 * Note in the gss case this doesn't actually have to wait for a
+-	 * gss upcall (or any calls to the client); this just creates a
+-	 * non-uptodate cred which the rpc state machine will fill in with
+-	 * a refresh_upcall later.
+-	 */
+-	return auth->au_ops->lookup_cred(auth, &acred, RPCAUTH_LOOKUP_NEW);
++	callback_cred = rpc_lookup_machine_cred();
++	if (!callback_cred)
++		return -ENOMEM;
++	return 0;
+ }
+ 
++
+ void do_probe_callback(struct nfs4_client *clp)
+ {
+ 	struct nfs4_cb_conn *cb = &clp->cl_cb_conn;
+ 	struct rpc_message msg = {
+ 		.rpc_proc       = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
+ 		.rpc_argp       = clp,
++		.rpc_cred	= callback_cred
+ 	};
+-	struct rpc_cred *cred;
+ 	int status;
+ 
+-	cred = lookup_cb_cred(cb);
+-	if (IS_ERR(cred)) {
+-		status = PTR_ERR(cred);
+-		goto out;
+-	}
+-	cb->cb_cred = cred;
+-	msg.rpc_cred = cb->cb_cred;
+ 	status = rpc_call_async(cb->cb_client, &msg, RPC_TASK_SOFT,
+ 				&nfsd4_cb_probe_ops, (void *)clp);
+-out:
+ 	if (status) {
+ 		warn_no_callback_path(clp, status);
+ 		put_nfs4_client(clp);
+@@ -550,7 +537,7 @@ nfsd4_cb_recall(struct nfs4_delegation *dp)
+ 	struct rpc_message msg = {
+ 		.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL],
+ 		.rpc_argp = dp,
+-		.rpc_cred = clp->cl_cb_conn.cb_cred
++		.rpc_cred = callback_cred
+ 	};
+ 	int status;
+ 
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 11db40cb2f2b..0445192d660d 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -696,10 +696,6 @@ shutdown_callback_client(struct nfs4_client *clp)
+ 		clp->cl_cb_conn.cb_client = NULL;
+ 		rpc_shutdown_client(clnt);
+ 	}
+-	if (clp->cl_cb_conn.cb_cred) {
+-		put_rpccred(clp->cl_cb_conn.cb_cred);
+-		clp->cl_cb_conn.cb_cred = NULL;
+-	}
+ }
+ 
+ static inline void
+@@ -4020,7 +4016,7 @@ __nfs4_state_start(void)
+ 		return -ENOMEM;
+ 	queue_delayed_work(laundry_wq, &laundromat_work, grace_time);
+ 	set_max_delegations();
+-	return 0;
++	return set_callback_cred();
+ }
+ 
+ int
+diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
+index 70ef5f4abbbc..9bf3aa8c5aea 100644
+--- a/include/linux/nfsd/state.h
++++ b/include/linux/nfsd/state.h
+@@ -89,7 +89,6 @@ struct nfs4_cb_conn {
+ 	/* RPC client info */
+ 	atomic_t		cb_set;     /* successful CB_NULL call */
+ 	struct rpc_clnt *       cb_client;
+-	struct rpc_cred	*	cb_cred;
+ };
+ 
+ /* Maximum number of slots per session. 160 is useful for long haul TCP */
+@@ -362,6 +361,7 @@ extern int nfs4_in_grace(void);
+ extern __be32 nfs4_check_open_reclaim(clientid_t *clid);
+ extern void put_nfs4_client(struct nfs4_client *clp);
+ extern void nfs4_free_stateowner(struct kref *kref);
++extern int set_callback_cred(void);
+ extern void nfsd4_probe_callback(struct nfs4_client *clp);
+ extern void nfsd4_cb_recall(struct nfs4_delegation *dp);
+ extern void nfs4_put_delegation(struct nfs4_delegation *dp);

commit 29ab23cc5d351658d01a4327d55e9106a73fd04f
+Author: J. Bruce Fields 
+Date:   Tue Sep 15 15:56:50 2009 -0400
+
+    nfsd4: allow nfs4 state startup to fail
+    
+    The failure here is pretty unlikely, but we should handle it anyway.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 46e9ac526872..11db40cb2f2b 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -4004,7 +4004,7 @@ set_max_delegations(void)
+ 
+ /* initialization to perform when the nfsd service is started: */
+ 
+-static void
++static int
+ __nfs4_state_start(void)
+ {
+ 	unsigned long grace_time;
+@@ -4016,19 +4016,26 @@ __nfs4_state_start(void)
+ 	printk(KERN_INFO "NFSD: starting %ld-second grace period\n",
+ 	       grace_time/HZ);
+ 	laundry_wq = create_singlethread_workqueue("nfsd4");
++	if (laundry_wq == NULL)
++		return -ENOMEM;
+ 	queue_delayed_work(laundry_wq, &laundromat_work, grace_time);
+ 	set_max_delegations();
++	return 0;
+ }
+ 
+-void
++int
+ nfs4_state_start(void)
+ {
++	int ret;
++
+ 	if (nfs4_init)
+-		return;
++		return 0;
+ 	nfsd4_load_reboot_recovery_data();
+-	__nfs4_state_start();
++	ret = __nfs4_state_start();
++	if (ret)
++		return ret;
+ 	nfs4_init = 1;
+-	return;
++	return 0;
+ }
+ 
+ time_t
+diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
+index 4472449c0937..fcc001088261 100644
+--- a/fs/nfsd/nfssvc.c
++++ b/fs/nfsd/nfssvc.c
+@@ -411,7 +411,9 @@ nfsd_svc(unsigned short port, int nrservs)
+ 	error =	nfsd_racache_init(2*nrservs);
+ 	if (error<0)
+ 		goto out;
+-	nfs4_state_start();
++	error = nfs4_state_start();
++	if (error)
++		goto out;
+ 
+ 	nfsd_reset_versions();
+ 
+diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
+index 2812ed52669d..24fdf89cea83 100644
+--- a/include/linux/nfsd/nfsd.h
++++ b/include/linux/nfsd/nfsd.h
+@@ -166,7 +166,7 @@ extern int nfsd_max_blksize;
+ extern unsigned int max_delegations;
+ int nfs4_state_init(void);
+ void nfsd4_free_slabs(void);
+-void nfs4_state_start(void);
++int nfs4_state_start(void);
+ void nfs4_state_shutdown(void);
+ time_t nfs4_lease_time(void);
+ void nfs4_reset_lease(time_t leasetime);
+@@ -174,7 +174,7 @@ int nfs4_reset_recoverydir(char *recdir);
+ #else
+ static inline int nfs4_state_init(void) { return 0; }
+ static inline void nfsd4_free_slabs(void) { }
+-static inline void nfs4_state_start(void) { }
++static inline int nfs4_state_start(void) { }
+ static inline void nfs4_state_shutdown(void) { }
+ static inline time_t nfs4_lease_time(void) { return 0; }
+ static inline void nfs4_reset_lease(time_t leasetime) { }

commit 886e3b7fe6054230c89ae078a09565ed183ecc73
+Author: J. Bruce Fields 
+Date:   Tue Sep 15 12:22:42 2009 -0400
+
+    nfsd4: fix null dereference creating nfsv4 callback client
+    
+    On setting up the callback to the client, we attempt to use the same
+    authentication flavor the client did.  We find an rpc cred to use by
+    calling rpcauth_lookup_credcache(), which assumes that the given
+    authentication flavor has a credentials cache.  However, this is not
+    required to be true--in particular, auth_null does not use one.
+    Instead, we should call the auth's lookup_cred() method.
+    
+    Without this, a client attempting to mount using nfsv4 and auth_null
+    triggers a null dereference.
+    
+    Cc: stable@kernel.org
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 63bb384b4d5c..4abb88264c72 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -437,6 +437,7 @@ static struct rpc_cred *lookup_cb_cred(struct nfs4_cb_conn *cb)
+ 	struct auth_cred acred = {
+ 		.machine_cred = 1
+ 	};
++	struct rpc_auth *auth = cb->cb_client->cl_auth;
+ 
+ 	/*
+ 	 * Note in the gss case this doesn't actually have to wait for a
+@@ -444,8 +445,7 @@ static struct rpc_cred *lookup_cb_cred(struct nfs4_cb_conn *cb)
+ 	 * non-uptodate cred which the rpc state machine will fill in with
+ 	 * a refresh_upcall later.
+ 	 */
+-	return rpcauth_lookup_credcache(cb->cb_client->cl_auth, &acred,
+-							RPCAUTH_LOOKUP_NEW);
++	return auth->au_ops->lookup_cred(auth, &acred, RPCAUTH_LOOKUP_NEW);
+ }
+ 
+ void do_probe_callback(struct nfs4_client *clp)

commit aed100fafb90aaabe8fb31e58af9dc7e68696507
+Author: J. Bruce Fields 
+Date:   Fri Sep 4 14:40:36 2009 -0400
+
+    nfsd: fix leak on error in nfsv3 readdir
+    
+    Note the !dchild->d_inode case can leak the filehandle.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
+index f16184a39941..edf926e1062f 100644
+--- a/fs/nfsd/nfs3xdr.c
++++ b/fs/nfsd/nfs3xdr.c
+@@ -825,7 +825,6 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
+ 	dparent = cd->fh.fh_dentry;
+ 	exp  = cd->fh.fh_export;
+ 
+-	fh_init(fhp, NFS3_FHSIZE);
+ 	if (isdotent(name, namlen)) {
+ 		if (namlen == 2) {
+ 			dchild = dget_parent(dparent);
+@@ -859,15 +858,17 @@ __be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const c
+ 	struct svc_fh	fh;
+ 	int err;
+ 
++	fh_init(&fh, NFS3_FHSIZE);
+ 	err = compose_entry_fh(cd, &fh, name, namlen);
+ 	if (err) {
+ 		*p++ = 0;
+ 		*p++ = 0;
+-		return p;
++		goto out;
+ 	}
+ 	p = encode_post_op_attr(cd->rqstp, p, &fh);
+ 	*p++ = xdr_one;			/* yes, a file handle follows */
+ 	p = encode_fh(p, &fh);
++out:
+ 	fh_put(&fh);
+ 	return p;
+ }

commit 8177e6d6dfb9cd03d9bdeb647c32161f8f58f686
+Author: J. Bruce Fields 
+Date:   Fri Sep 4 14:13:09 2009 -0400
+
+    nfsd: clean up readdirplus encoding
+    
+    Make the return from compose_entry_fh() zero or an error, even though
+    the returned error isn't used, just to make the meaning of the return
+    immediately obvious.
+    
+    Move some repeated code out of main function into helper.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
+index 01d4ec1c88e0..f16184a39941 100644
+--- a/fs/nfsd/nfs3xdr.c
++++ b/fs/nfsd/nfs3xdr.c
+@@ -814,17 +814,6 @@ encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name,
+ 	return p;
+ }
+ 
+-static __be32 *
+-encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p,
+-		struct svc_fh *fhp)
+-{
+-	p = encode_post_op_attr(cd->rqstp, p, fhp);
+-	*p++ = xdr_one;			/* yes, a file handle follows */
+-	p = encode_fh(p, fhp);
+-	fh_put(fhp);
+-	return p;
+-}
+-
+ static int
+ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
+ 		const char *name, int namlen)
+@@ -843,22 +832,46 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
+ 			if (dchild == dparent) {
+ 				/* filesystem root - cannot return filehandle for ".." */
+ 				dput(dchild);
+-				return 1;
++				return -ENOENT;
+ 			}
+ 		} else
+ 			dchild = dget(dparent);
+ 	} else
+ 		dchild = lookup_one_len(name, dparent, namlen);
+ 	if (IS_ERR(dchild))
+-		return 1;
+-	if (d_mountpoint(dchild) ||
+-	    fh_compose(fhp, exp, dchild, &cd->fh) != 0 ||
+-	    !dchild->d_inode)
+-		rv = 1;
++		return -ENOENT;
++	rv = -ENOENT;
++	if (d_mountpoint(dchild))
++		goto out;
++	rv = fh_compose(fhp, exp, dchild, &cd->fh);
++	if (rv)
++		goto out;
++	if (!dchild->d_inode)
++		goto out;
++	rv = 0;
++out:
+ 	dput(dchild);
+ 	return rv;
+ }
+ 
++__be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen)
++{
++	struct svc_fh	fh;
++	int err;
++
++	err = compose_entry_fh(cd, &fh, name, namlen);
++	if (err) {
++		*p++ = 0;
++		*p++ = 0;
++		return p;
++	}
++	p = encode_post_op_attr(cd->rqstp, p, &fh);
++	*p++ = xdr_one;			/* yes, a file handle follows */
++	p = encode_fh(p, &fh);
++	fh_put(&fh);
++	return p;
++}
++
+ /*
+  * Encode a directory entry. This one works for both normal readdir
+  * and readdirplus.
+@@ -929,16 +942,8 @@ encode_entry(struct readdir_cd *ccd, const char *name, int namlen,
+ 
+ 		p = encode_entry_baggage(cd, p, name, namlen, ino);
+ 
+-		/* throw in readdirplus baggage */
+-		if (plus) {
+-			struct svc_fh	fh;
+-
+-			if (compose_entry_fh(cd, &fh, name, namlen) > 0) {
+-				*p++ = 0;
+-				*p++ = 0;
+-			} else
+-				p = encode_entryplus_baggage(cd, p, &fh);
+-		}
++		if (plus)
++			p = encode_entryplus_baggage(cd, p, name, namlen);
+ 		num_entry_words = p - cd->buffer;
+ 	} else if (cd->rqstp->rq_respages[pn+1] != NULL) {
+ 		/* temporarily encode entry into next page, then move back to
+@@ -951,17 +956,8 @@ encode_entry(struct readdir_cd *ccd, const char *name, int namlen,
+ 
+ 		p1 = encode_entry_baggage(cd, p1, name, namlen, ino);
+ 
+-		/* throw in readdirplus baggage */
+-		if (plus) {
+-			struct svc_fh	fh;
+-
+-			if (compose_entry_fh(cd, &fh, name, namlen) > 0) {
+-				/* zero out the filehandle */
+-				*p1++ = 0;
+-				*p1++ = 0;
+-			} else
+-				p1 = encode_entryplus_baggage(cd, p1, &fh);
+-		}
++		if (plus)
++			p = encode_entryplus_baggage(cd, p1, name, namlen);
+ 
+ 		/* determine entry word length and lengths to go in pages */
+ 		num_entry_words = p1 - tmp;

commit 1be10a88cac5e589cdd2bcb0cf6a13ed30bcc233
+Author: J. Bruce Fields 
+Date:   Fri Sep 4 11:59:32 2009 -0400
+
+    nfsd4: filehandle leak or error exit from fh_compose()
+    
+    A number of callers (nfsd4_encode_fattr(), at least) don't bother to
+    release the filehandle returned to fh_compose() if fh_compose() returns
+    an error.  So, modify fh_compose() to release the filehandle before
+    returning an error.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
+index bce0b2bfbc61..01965b2f3a76 100644
+--- a/fs/nfsd/nfsfh.c
++++ b/fs/nfsd/nfsfh.c
+@@ -557,8 +557,10 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
+ 
+ 		if (inode)
+ 			_fh_update(fhp, exp, dentry);
+-		if (fhp->fh_handle.fh_fileid_type == 255)
++		if (fhp->fh_handle.fh_fileid_type == 255) {
++			fh_put(fhp);
+ 			return nfserr_opnotsupp;
++		}
+ 	}
+ 
+ 	return 0;

commit bc6c53d5a1383d5d9632adf33bd03458cfc0869d
+Author: J. Bruce Fields 
+Date:   Wed Sep 2 19:50:40 2009 -0400
+
+    nfsd: move fsid_type choice out of fh_compose
+    
+    More trivial cleanup.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
+index 78d8ebf162ca..bce0b2bfbc61 100644
+--- a/fs/nfsd/nfsfh.c
++++ b/fs/nfsd/nfsfh.c
+@@ -431,43 +431,17 @@ static bool fsid_type_ok_for_exp(u8 fsid_type, struct svc_export *exp)
+ 	return 1;
+ }
+ 
+-__be32
+-fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
+-	   struct svc_fh *ref_fh)
+-{
+-	/* ref_fh is a reference file handle.
+-	 * if it is non-null and for the same filesystem, then we should compose
+-	 * a filehandle which is of the same version, where possible.
+-	 * Currently, that means that if ref_fh->fh_handle.fh_version == 0xca
+-	 * Then create a 32byte filehandle using nfs_fhbase_old
+-	 *
+-	 */
+ 
++static void set_version_and_fsid_type(struct svc_fh *fhp, struct svc_export *exp, struct svc_fh *ref_fh)
++{
+ 	u8 version;
+-	u8 fsid_type = 0;
+-	struct inode * inode = dentry->d_inode;
+-	struct dentry *parent = dentry->d_parent;
+-	__u32 *datap;
+-	dev_t ex_dev = exp_sb(exp)->s_dev;
+-
+-	dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %s/%s, ino=%ld)\n",
+-		MAJOR(ex_dev), MINOR(ex_dev),
+-		(long) exp->ex_path.dentry->d_inode->i_ino,
+-		parent->d_name.name, dentry->d_name.name,
+-		(inode ? inode->i_ino : 0));
+-
+-	/* Choose filehandle version and fsid type based on
+-	 * the reference filehandle (if it is in the same export)
+-	 * or the export options.
+-	 */
+- retry:
++	u8 fsid_type;
++retry:
+ 	version = 1;
+ 	if (ref_fh && ref_fh->fh_export == exp) {
+ 		version = ref_fh->fh_handle.fh_version;
+ 		fsid_type = ref_fh->fh_handle.fh_fsid_type;
+ 
+-		if (ref_fh == fhp)
+-			fh_put(ref_fh);
+ 		ref_fh = NULL;
+ 
+ 		switch (version) {
+@@ -502,11 +476,44 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
+ 			else
+ 				fsid_type = FSID_UUID4_INUM;
+ 		}
+-	} else if (!old_valid_dev(ex_dev))
++	} else if (!old_valid_dev(exp_sb(exp)->s_dev))
+ 		/* for newer device numbers, we must use a newer fsid format */
+ 		fsid_type = FSID_ENCODE_DEV;
+ 	else
+ 		fsid_type = FSID_DEV;
++	fhp->fh_handle.fh_version = version;
++	if (version)
++		fhp->fh_handle.fh_fsid_type = fsid_type;
++}
++
++__be32
++fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
++	   struct svc_fh *ref_fh)
++{
++	/* ref_fh is a reference file handle.
++	 * if it is non-null and for the same filesystem, then we should compose
++	 * a filehandle which is of the same version, where possible.
++	 * Currently, that means that if ref_fh->fh_handle.fh_version == 0xca
++	 * Then create a 32byte filehandle using nfs_fhbase_old
++	 *
++	 */
++
++	struct inode * inode = dentry->d_inode;
++	struct dentry *parent = dentry->d_parent;
++	__u32 *datap;
++	dev_t ex_dev = exp_sb(exp)->s_dev;
++
++	dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %s/%s, ino=%ld)\n",
++		MAJOR(ex_dev), MINOR(ex_dev),
++		(long) exp->ex_path.dentry->d_inode->i_ino,
++		parent->d_name.name, dentry->d_name.name,
++		(inode ? inode->i_ino : 0));
++
++	/* Choose filehandle version and fsid type based on
++	 * the reference filehandle (if it is in the same export)
++	 * or the export options.
++	 */
++	 set_version_and_fsid_type(fhp, exp, ref_fh);
+ 
+ 	if (ref_fh == fhp)
+ 		fh_put(ref_fh);
+@@ -524,7 +531,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
+ 	fhp->fh_export = exp;
+ 	cache_get(&exp->h);
+ 
+-	if (version == 0xca) {
++	if (fhp->fh_handle.fh_version == 0xca) {
+ 		/* old style filehandle please */
+ 		memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE);
+ 		fhp->fh_handle.fh_size = NFS_FHSIZE;
+@@ -538,15 +545,13 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
+ 			_fh_update_old(dentry, exp, &fhp->fh_handle);
+ 	} else {
+ 		int len;
+-		fhp->fh_handle.fh_version = 1;
+ 		fhp->fh_handle.fh_auth_type = 0;
+ 		datap = fhp->fh_handle.fh_auth+0;
+-		fhp->fh_handle.fh_fsid_type = fsid_type;
+-		mk_fsid(fsid_type, datap, ex_dev,
++		mk_fsid(fhp->fh_handle.fh_fsid_type, datap, ex_dev,
+ 			exp->ex_path.dentry->d_inode->i_ino,
+ 			exp->ex_fsid, exp->ex_uuid);
+ 
+-		len = key_len(fsid_type);
++		len = key_len(fhp->fh_handle.fh_fsid_type);
+ 		datap += len/4;
+ 		fhp->fh_handle.fh_size = 4 + len;
+ 

commit 8e498751f2f36074ffa6fc7f0a9ec6e055b350e6
+Author: J. Bruce Fields 
+Date:   Wed Sep 2 19:31:32 2009 -0400
+
+    nfsd: move some of fh_compose into helper functions
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
+index 8847f3fbfc1e..78d8ebf162ca 100644
+--- a/fs/nfsd/nfsfh.c
++++ b/fs/nfsd/nfsfh.c
+@@ -397,6 +397,40 @@ static inline void _fh_update_old(struct dentry *dentry,
+ 		fh->ofh_dirino = 0;
+ }
+ 
++static bool is_root_export(struct svc_export *exp)
++{
++	return exp->ex_path.dentry == exp->ex_path.dentry->d_sb->s_root;
++}
++
++static struct super_block *exp_sb(struct svc_export *exp)
++{
++	return exp->ex_path.dentry->d_inode->i_sb;
++}
++
++static bool fsid_type_ok_for_exp(u8 fsid_type, struct svc_export *exp)
++{
++	switch (fsid_type) {
++	case FSID_DEV:
++		if (!old_valid_dev(exp_sb(exp)->s_dev))
++			return 0;
++		/* FALL THROUGH */
++	case FSID_MAJOR_MINOR:
++	case FSID_ENCODE_DEV:
++		return exp_sb(exp)->s_type->fs_flags & FS_REQUIRES_DEV;
++	case FSID_NUM:
++		return exp->ex_flags & NFSEXP_FSID;
++	case FSID_UUID8:
++	case FSID_UUID16:
++		if (!is_root_export(exp))
++			return 0;
++		/* fall through */
++	case FSID_UUID4_INUM:
++	case FSID_UUID16_INUM:
++		return exp->ex_uuid != NULL;
++	}
++	return 1;
++}
++
+ __be32
+ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
+ 	   struct svc_fh *ref_fh)
+@@ -414,8 +448,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
+ 	struct inode * inode = dentry->d_inode;
+ 	struct dentry *parent = dentry->d_parent;
+ 	__u32 *datap;
+-	dev_t ex_dev = exp->ex_path.dentry->d_inode->i_sb->s_dev;
+-	int root_export = (exp->ex_path.dentry == exp->ex_path.dentry->d_sb->s_root);
++	dev_t ex_dev = exp_sb(exp)->s_dev;
+ 
+ 	dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %s/%s, ino=%ld)\n",
+ 		MAJOR(ex_dev), MINOR(ex_dev),
+@@ -447,49 +480,24 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
+ 			goto retry;
+ 		}
+ 
+-		/* Need to check that this type works for this
+-		 * export point.  As the fsid -> filesystem mapping
+-		 * was guided by user-space, there is no guarantee
+-		 * that the filesystem actually supports that fsid
+-		 * type. If it doesn't we loop around again without
+-		 * ref_fh set.
++		/*
++		 * As the fsid -> filesystem mapping was guided by
++		 * user-space, there is no guarantee that the filesystem
++		 * actually supports that fsid type. If it doesn't we
++		 * loop around again without ref_fh set.
+ 		 */
+-		switch(fsid_type) {
+-		case FSID_DEV:
+-			if (!old_valid_dev(ex_dev))
+-				goto retry;
+-			/* FALL THROUGH */
+-		case FSID_MAJOR_MINOR:
+-		case FSID_ENCODE_DEV:
+-			if (!(exp->ex_path.dentry->d_inode->i_sb->s_type->fs_flags
+-			      & FS_REQUIRES_DEV))
+-				goto retry;
+-			break;
+-		case FSID_NUM:
+-			if (! (exp->ex_flags & NFSEXP_FSID))
+-				goto retry;
+-			break;
+-		case FSID_UUID8:
+-		case FSID_UUID16:
+-			if (!root_export)
+-				goto retry;
+-			/* fall through */
+-		case FSID_UUID4_INUM:
+-		case FSID_UUID16_INUM:
+-			if (exp->ex_uuid == NULL)
+-				goto retry;
+-			break;
+-		}
++		if (!fsid_type_ok_for_exp(fsid_type, exp))
++			goto retry;
+ 	} else if (exp->ex_flags & NFSEXP_FSID) {
+ 		fsid_type = FSID_NUM;
+ 	} else if (exp->ex_uuid) {
+ 		if (fhp->fh_maxsize >= 64) {
+-			if (root_export)
++			if (is_root_export(exp))
+ 				fsid_type = FSID_UUID16;
+ 			else
+ 				fsid_type = FSID_UUID16_INUM;
+ 		} else {
+-			if (root_export)
++			if (is_root_export(exp))
+ 				fsid_type = FSID_UUID8;
+ 			else
+ 				fsid_type = FSID_UUID4_INUM;
+@@ -639,8 +647,7 @@ enum fsid_source fsid_source(struct svc_fh *fhp)
+ 	case FSID_DEV:
+ 	case FSID_ENCODE_DEV:
+ 	case FSID_MAJOR_MINOR:
+-		if (fhp->fh_export->ex_path.dentry->d_inode->i_sb->s_type->fs_flags
+-		    & FS_REQUIRES_DEV)
++		if (exp_sb(fhp->fh_export)->s_type->fs_flags & FS_REQUIRES_DEV)
+ 			return FSIDSOURCE_DEV;
+ 		break;
+ 	case FSID_NUM:

commit e9dc122166b8d863d3057a66ada04838e5548e52
+Merge: 560ab42ef923 405d8f8b1d93
+Author: J. Bruce Fields 
+Date:   Fri Aug 21 11:27:29 2009 -0400
+
+    Merge branch 'nfs-for-2.6.32' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6 into for-2.6.32-incoming
+    
+    Conflicts:
+            net/sunrpc/cache.c
+
+diff --cc net/sunrpc/cache.c
+index bbd31f1215e7,45cdaff9b361..ade8a7e99cd3
+--- a/net/sunrpc/cache.c
++++ b/net/sunrpc/cache.c
+@@@ -175,23 -177,13 +177,29 @@@ struct cache_head *sunrpc_cache_update(
+  }
+  EXPORT_SYMBOL_GPL(sunrpc_cache_update);
+  
+- static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h);
++ static int cache_make_upcall(struct cache_detail *cd, struct cache_head *h)
++ {
++ 	if (!cd->cache_upcall)
++ 		return -EINVAL;
++ 	return cd->cache_upcall(cd, h);
++ }
+  
+ +static inline int cache_is_valid(struct cache_detail *detail, struct cache_head *h)
+ +{
+ +	if (!test_bit(CACHE_VALID, &h->flags) ||
+ +	    h->expiry_time < get_seconds())
+ +		return -EAGAIN;
+ +	else if (detail->flush_time > h->last_refresh)
+ +		return -EAGAIN;
+ +	else {
+ +		/* entry is valid */
+ +		if (test_bit(CACHE_NEGATIVE, &h->flags))
+ +			return -ENOENT;
+ +		else
+ +			return 0;
+ +	}
+ +}
+++
+  /*
+   * This is the generic cache management routine for all
+   * the authentication caches.
+@@@ -924,19 -887,7 +903,7 @@@ static int cache_release(struct inode *
+  
+  
+  
+- static const struct file_operations cache_file_operations = {
+- 	.owner		= THIS_MODULE,
+- 	.llseek		= no_llseek,
+- 	.read		= cache_read,
+- 	.write		= cache_write,
+- 	.poll		= cache_poll,
+- 	.ioctl		= cache_ioctl, /* for FIONREAD */
+- 	.open		= cache_open,
+- 	.release	= cache_release,
+- };
+- 
+- 
+ -static void queue_loose(struct cache_detail *detail, struct cache_head *ch)
+ +static void cache_dequeue(struct cache_detail *detail, struct cache_head *ch)
+  {
+  	struct cache_queue *cq;
+  	spin_lock(&queue_lock);

commit 4dceef96756b667360741712a8e37490f8458516
+Author: J. Bruce Fields 
+Date:   Thu Aug 20 17:08:39 2009 -0400
+
+    nfs: fix compile error in rpc_pipefs.h
+    
+    This include is needed for the definition of delayed_work.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h
+index a92571a34556..cf14db975da0 100644
+--- a/include/linux/sunrpc/rpc_pipe_fs.h
++++ b/include/linux/sunrpc/rpc_pipe_fs.h
+@@ -3,6 +3,8 @@
+ 
+ #ifdef __KERNEL__
+ 
++#include 
++
+ struct rpc_pipe_msg {
+ 	struct list_head list;
+ 	void *data;

commit 413d63d7106b914a4a004ac08698f10c618e4616
+Author: J. Bruce Fields 
+Date:   Tue Jul 28 11:37:25 2009 -0400
+
+    nfsd: minor write_pool_threads exit cleanup
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index 48da164bb597..b51e7ae8b570 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -784,11 +784,7 @@ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
+ 		size -= len;
+ 		mesg += len;
+ 	}
+-
+-	kfree(nthreads);
+-	mutex_unlock(&nfsd_mutex);
+-	return (mesg-buf);
+-
++	rv = mesg - buf;
+ out_free:
+ 	kfree(nthreads);
+ 	mutex_unlock(&nfsd_mutex);

commit e4636d535e32768c8c500641ddb144f56e3dc5c0
+Author: J. Bruce Fields 
+Date:   Mon Jun 15 19:07:13 2009 -0700
+
+    nfsd: minor nfsd_vfs_write cleanup
+    
+    There's no need to check host_err >= 0 every time here when we could
+    check host_err < 0 once, following the usual kernel style.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index 6ad76a4cfc01..1cf70616a11e 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -1053,19 +1053,20 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+ 	oldfs = get_fs(); set_fs(KERNEL_DS);
+ 	host_err = vfs_writev(file, (struct iovec __user *)vec, vlen, &offset);
+ 	set_fs(oldfs);
+-	if (host_err >= 0) {
+-		*cnt = host_err;
+-		nfsdstats.io_write += host_err;
+-		fsnotify_modify(file->f_path.dentry);
+-	}
++	if (host_err < 0)
++		goto out_nfserr;
++	*cnt = host_err;
++	nfsdstats.io_write += host_err;
++	fsnotify_modify(file->f_path.dentry);
+ 
+ 	/* clear setuid/setgid flag after write */
+-	if (host_err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID)))
++	if (inode->i_mode & (S_ISUID | S_ISGID))
+ 		kill_suid(dentry);
+ 
+-	if (host_err >= 0 && stable && use_wgather)
++	if (stable && use_wgather)
+ 		host_err = wait_for_concurrent_writes(file);
+ 
++out_nfserr:
+ 	dprintk("nfsd: write complete host_err=%d\n", host_err);
+ 	if (host_err >= 0)
+ 		err = 0;

commit d911df7b8d44de41661363a4e29ee710180ba025
+Author: J. Bruce Fields 
+Date:   Mon Jun 15 16:03:53 2009 -0700
+
+    nfsd: Pull write-gathering code out of nfsd_vfs_write
+    
+    This is a relatively self-contained piece of code that handles a special
+    case--move it to its own function.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index ebf56c6040ca..6ad76a4cfc01 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -963,6 +963,43 @@ static void kill_suid(struct dentry *dentry)
+ 	mutex_unlock(&dentry->d_inode->i_mutex);
+ }
+ 
++/*
++ * Gathered writes: If another process is currently writing to the file,
++ * there's a high chance this is another nfsd (triggered by a bulk write
++ * from a client's biod). Rather than syncing the file with each write
++ * request, we sleep for 10 msec.
++ *
++ * I don't know if this roughly approximates C. Juszak's idea of
++ * gathered writes, but it's a nice and simple solution (IMHO), and it
++ * seems to work:-)
++ *
++ * Note: we do this only in the NFSv2 case, since v3 and higher have a
++ * better tool (separate unstable writes and commits) for solving this
++ * problem.
++ */
++static int wait_for_concurrent_writes(struct file *file)
++{
++	struct inode *inode = file->f_path.dentry->d_inode;
++	static ino_t last_ino;
++	static dev_t last_dev;
++	int err = 0;
++
++	if (atomic_read(&inode->i_writecount) > 1
++	    || (last_ino == inode->i_ino && last_dev == inode->i_sb->s_dev)) {
++		dprintk("nfsd: write defer %d\n", task_pid_nr(current));
++		msleep(10);
++		dprintk("nfsd: write resume %d\n", task_pid_nr(current));
++	}
++
++	if (inode->i_state & I_DIRTY) {
++		dprintk("nfsd: write sync %d\n", task_pid_nr(current));
++		err = nfsd_sync(file);
++	}
++	last_ino = inode->i_ino;
++	last_dev = inode->i_sb->s_dev;
++	return err;
++}
++
+ static __be32
+ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+ 				loff_t offset, struct kvec *vec, int vlen,
+@@ -1026,36 +1063,8 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+ 	if (host_err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID)))
+ 		kill_suid(dentry);
+ 
+-	if (host_err >= 0 && stable && use_wgather) {
+-		static ino_t	last_ino;
+-		static dev_t	last_dev;
+-
+-		/*
+-		 * Gathered writes: If another process is currently
+-		 * writing to the file, there's a high chance
+-		 * this is another nfsd (triggered by a bulk write
+-		 * from a client's biod). Rather than syncing the
+-		 * file with each write request, we sleep for 10 msec.
+-		 *
+-		 * I don't know if this roughly approximates
+-		 * C. Juszak's idea of gathered writes, but it's a
+-		 * nice and simple solution (IMHO), and it seems to
+-		 * work:-)
+-		 */
+-		if (atomic_read(&inode->i_writecount) > 1
+-		    || (last_ino == inode->i_ino && last_dev == inode->i_sb->s_dev)) {
+-			dprintk("nfsd: write defer %d\n", task_pid_nr(current));
+-			msleep(10);
+-			dprintk("nfsd: write resume %d\n", task_pid_nr(current));
+-		}
+-
+-		if (inode->i_state & I_DIRTY) {
+-			dprintk("nfsd: write sync %d\n", task_pid_nr(current));
+-			host_err=nfsd_sync(file);
+-		}
+-		last_ino = inode->i_ino;
+-		last_dev = inode->i_sb->s_dev;
+-	}
++	if (host_err >= 0 && stable && use_wgather)
++		host_err = wait_for_concurrent_writes(file);
+ 
+ 	dprintk("nfsd: write complete host_err=%d\n", host_err);
+ 	if (host_err >= 0)

commit 9d2a3f31d6d7832cd441eeda08bc2266cdd5d972
+Author: J. Bruce Fields 
+Date:   Mon Jun 15 18:47:56 2009 -0700
+
+    nfsd: track last inode only in use_wgather case
+    
+    Updating last_ino and last_dev probably isn't useful in the !use_wgather
+    case.
+    
+    Also remove some pointless ifdef'd-out code.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index f30cc4eadb0a..ebf56c6040ca 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -1026,7 +1026,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+ 	if (host_err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID)))
+ 		kill_suid(dentry);
+ 
+-	if (host_err >= 0 && stable) {
++	if (host_err >= 0 && stable && use_wgather) {
+ 		static ino_t	last_ino;
+ 		static dev_t	last_dev;
+ 
+@@ -1042,21 +1042,16 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+ 		 * nice and simple solution (IMHO), and it seems to
+ 		 * work:-)
+ 		 */
+-		if (use_wgather) {
+-			if (atomic_read(&inode->i_writecount) > 1
+-			    || (last_ino == inode->i_ino && last_dev == inode->i_sb->s_dev)) {
+-				dprintk("nfsd: write defer %d\n", task_pid_nr(current));
+-				msleep(10);
+-				dprintk("nfsd: write resume %d\n", task_pid_nr(current));
+-			}
++		if (atomic_read(&inode->i_writecount) > 1
++		    || (last_ino == inode->i_ino && last_dev == inode->i_sb->s_dev)) {
++			dprintk("nfsd: write defer %d\n", task_pid_nr(current));
++			msleep(10);
++			dprintk("nfsd: write resume %d\n", task_pid_nr(current));
++		}
+ 
+-			if (inode->i_state & I_DIRTY) {
+-				dprintk("nfsd: write sync %d\n", task_pid_nr(current));
+-				host_err=nfsd_sync(file);
+-			}
+-#if 0
+-			wake_up(&inode->i_wait);
+-#endif
++		if (inode->i_state & I_DIRTY) {
++			dprintk("nfsd: write sync %d\n", task_pid_nr(current));
++			host_err=nfsd_sync(file);
+ 		}
+ 		last_ino = inode->i_ino;
+ 		last_dev = inode->i_sb->s_dev;

commit 7eef4091a653c243a87e5375c54504cc03bec4d8
+Merge: 0a93a47f042c 07a2039b8eb0
+Author: J. Bruce Fields 
+Date:   Mon Jun 15 18:08:07 2009 -0700
+
+    Merge commit 'v2.6.30' into for-2.6.31
+

commit 7f4218354fe312b327af06c3d8c95ed5f214c8ca
+Author: J. Bruce Fields 
+Date:   Wed May 27 18:51:06 2009 -0400
+
+    nfsd: Revert "svcrpc: take advantage of tcp autotuning"
+    
+    This reverts commit 47a14ef1af48c696b214ac168f056ddc79793d0e "svcrpc:
+    take advantage of tcp autotuning", which uncovered some further problems
+    in the server rpc code, causing significant performance regressions in
+    common cases.
+    
+    We will likely reinstate this patch after releasing 2.6.30 and applying
+    some work on the underlying fixes to the problem (developed by Trond).
+    
+    Reported-by: Jeff Moyer 
+    Cc: Olga Kornievskaia 
+    Cc: Jim Rees 
+    Cc: Trond Myklebust 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
+index af3198814c15..9d504234af4a 100644
+--- a/net/sunrpc/svcsock.c
++++ b/net/sunrpc/svcsock.c
+@@ -345,6 +345,7 @@ static void svc_sock_setbufsize(struct socket *sock, unsigned int snd,
+ 	lock_sock(sock->sk);
+ 	sock->sk->sk_sndbuf = snd * 2;
+ 	sock->sk->sk_rcvbuf = rcv * 2;
++	sock->sk->sk_userlocks |= SOCK_SNDBUF_LOCK|SOCK_RCVBUF_LOCK;
+ 	release_sock(sock->sk);
+ #endif
+ }
+@@ -796,6 +797,23 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
+ 		test_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags),
+ 		test_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags));
+ 
++	if (test_and_clear_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags))
++		/* sndbuf needs to have room for one request
++		 * per thread, otherwise we can stall even when the
++		 * network isn't a bottleneck.
++		 *
++		 * We count all threads rather than threads in a
++		 * particular pool, which provides an upper bound
++		 * on the number of threads which will access the socket.
++		 *
++		 * rcvbuf just needs to be able to hold a few requests.
++		 * Normally they will be removed from the queue
++		 * as soon a a complete request arrives.
++		 */
++		svc_sock_setbufsize(svsk->sk_sock,
++				    (serv->sv_nrthreads+3) * serv->sv_max_mesg,
++				    3 * serv->sv_max_mesg);
++
+ 	clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
+ 
+ 	/* Receive data. If we haven't got the record length yet, get
+@@ -1043,6 +1061,15 @@ static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv)
+ 
+ 		tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF;
+ 
++		/* initialise setting must have enough space to
++		 * receive and respond to one request.
++		 * svc_tcp_recvfrom will re-adjust if necessary
++		 */
++		svc_sock_setbufsize(svsk->sk_sock,
++				    3 * svsk->sk_xprt.xpt_server->sv_max_mesg,
++				    3 * svsk->sk_xprt.xpt_server->sv_max_mesg);
++
++		set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags);
+ 		set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
+ 		if (sk->sk_state != TCP_ESTABLISHED)
+ 			set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
+@@ -1112,14 +1139,8 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
+ 	/* Initialize the socket */
+ 	if (sock->type == SOCK_DGRAM)
+ 		svc_udp_init(svsk, serv);
+-	else {
+-		/* initialise setting must have enough space to
+-		 * receive and respond to one request.
+-		 */
+-		svc_sock_setbufsize(svsk->sk_sock, 4 * serv->sv_max_mesg,
+-					4 * serv->sv_max_mesg);
++	else
+ 		svc_tcp_init(svsk, serv);
+-	}
+ 
+ 	dprintk("svc: svc_setup_socket created %p (inet %p)\n",
+ 				svsk, svsk->sk_sk);

commit 8daed1e549b55827758b3af7b8132a73fc51526f
+Author: J. Bruce Fields 
+Date:   Mon May 11 16:10:19 2009 -0400
+
+    nfsd: silence lockdep warning
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
+index 5275097a7565..b5348405046b 100644
+--- a/fs/nfsd/nfs4recover.c
++++ b/fs/nfsd/nfs4recover.c
+@@ -229,7 +229,7 @@ nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
+ 		goto out;
+ 	status = vfs_readdir(filp, nfsd4_build_namelist, &names);
+ 	fput(filp);
+-	mutex_lock(&dir->d_inode->i_mutex);
++	mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
+ 	while (!list_empty(&names)) {
+ 		entry = list_entry(names.next, struct name_list, list);
+ 
+@@ -264,7 +264,7 @@ nfsd4_unlink_clid_dir(char *name, int namlen)
+ 
+ 	dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name);
+ 
+-	mutex_lock(&rec_dir.dentry->d_inode->i_mutex);
++	mutex_lock_nested(&rec_dir.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
+ 	dentry = lookup_one_len(name, rec_dir.dentry, namlen);
+ 	if (IS_ERR(dentry)) {
+ 		status = PTR_ERR(dentry);

commit 89996df4b5b1a09c279f50b3fd03aa9df735f5cb
+Author: J. Bruce Fields 
+Date:   Wed May 6 16:32:54 2009 -0400
+
+    lockd: fix list corruption on lockd restart
+    
+    If lockd is signalled soon enough after restart then locks_start_grace()
+    will try to re-add an entry to a list and trigger a lock corruption
+    warning.
+    
+    Thanks to Wang Chen for the problem report and diagnosis.
+    
+    WARNING: at lib/list_debug.c:26 __list_add+0x27/0x5c()
+    ...
+    list_add corruption. next->prev should be prev (ef8fe958), but was ef8ff128.  (next=ef8ff128).
+    ...
+    Pid: 23062, comm: lockd Tainted: G        W  2.6.30-rc2 #3
+    Call Trace:
+    [] warn_slowpath+0x71/0xa0
+    [] ? update_curr+0x11d/0x125
+    [] ? trace_hardirqs_on_caller+0x18/0x150
+    [] ? trace_hardirqs_on+0xb/0xd
+    [] ? _raw_spin_lock+0x53/0xfa
+    [] __list_add+0x27/0x5c
+    [] locks_start_grace+0x22/0x30 [lockd]
+    [] set_grace_period+0x39/0x53 [lockd]
+    [] ? lock_kernel+0x1c/0x28
+    [] lockd+0x64/0x164 [lockd]
+    [] ? trace_hardirqs_on_caller+0x18/0x150
+    [] ? complete+0x34/0x3e
+    [] ? lockd+0x0/0x164 [lockd]
+    [] ? lockd+0x0/0x164 [lockd]
+    [] kthread+0x45/0x6b
+    [] ? kthread+0x0/0x6b
+    [] kernel_thread_helper+0x7/0x10
+    
+    Reported-by: Wang Chen 
+    Signed-off-by: J. Bruce Fields 
+    Cc: stable@kernel.org
+
+diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
+index abf83881f68a..1a54ae14a192 100644
+--- a/fs/lockd/svc.c
++++ b/fs/lockd/svc.c
+@@ -104,6 +104,16 @@ static void set_grace_period(void)
+ 	schedule_delayed_work(&grace_period_end, grace_period);
+ }
+ 
++static void restart_grace(void)
++{
++	if (nlmsvc_ops) {
++		cancel_delayed_work_sync(&grace_period_end);
++		locks_end_grace(&lockd_manager);
++		nlmsvc_invalidate_all();
++		set_grace_period();
++	}
++}
++
+ /*
+  * This is the lockd kernel thread
+  */
+@@ -149,10 +159,7 @@ lockd(void *vrqstp)
+ 
+ 		if (signalled()) {
+ 			flush_signals(current);
+-			if (nlmsvc_ops) {
+-				nlmsvc_invalidate_all();
+-				set_grace_period();
+-			}
++			restart_grace();
+ 			continue;
+ 		}
+ 

commit b2c0cea6b1cb210e962f07047df602875564069e
+Author: J. Bruce Fields 
+Date:   Tue May 5 19:04:29 2009 -0400
+
+    nfsd4: check for negative dentry before use in nfsv4 readdir
+    
+    After 2f9092e1020246168b1309b35e085ecd7ff9ff72 "Fix i_mutex vs.  readdir
+    handling in nfsd" (and 14f7dd63 "Copy XFS readdir hack into nfsd code"),
+    an entry may be removed between the first mutex_unlock and the second
+    mutex_lock. In this case, lookup_one_len() will return a negative
+    dentry.  Check for this case to avoid a NULL dereference.
+    
+    Signed-off-by: J. Bruce Fields 
+    Reviewed-by: J. R. Okajima 
+    Cc: stable@kernel.org
+
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index b820c311931c..b73549d293be 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -2214,6 +2214,15 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
+ 	dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen);
+ 	if (IS_ERR(dentry))
+ 		return nfserrno(PTR_ERR(dentry));
++	if (!dentry->d_inode) {
++		/*
++		 * nfsd_buffered_readdir drops the i_mutex between
++		 * readdir and calling this callback, leaving a window
++		 * where this directory entry could have gone away.
++		 */
++		dput(dentry);
++		return nfserr_noent;
++	}
+ 
+ 	exp_get(exp);
+ 	/*
+@@ -2276,6 +2285,7 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
+ 	struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common);
+ 	int buflen;
+ 	__be32 *p = cd->buffer;
++	__be32 *cookiep;
+ 	__be32 nfserr = nfserr_toosmall;
+ 
+ 	/* In nfsv4, "." and ".." never make it onto the wire.. */
+@@ -2292,7 +2302,7 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
+ 		goto fail;
+ 
+ 	*p++ = xdr_one;                             /* mark entry present */
+-	cd->offset = p;                             /* remember pointer */
++	cookiep = p;
+ 	p = xdr_encode_hyper(p, NFS_OFFSET_MAX);    /* offset of next entry */
+ 	p = xdr_encode_array(p, name, namlen);      /* name length & name */
+ 
+@@ -2306,6 +2316,8 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
+ 		goto fail;
+ 	case nfserr_dropit:
+ 		goto fail;
++	case nfserr_noent:
++		goto skip_entry;
+ 	default:
+ 		/*
+ 		 * If the client requested the RDATTR_ERROR attribute,
+@@ -2324,6 +2336,8 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
+ 	}
+ 	cd->buflen -= (p - cd->buffer);
+ 	cd->buffer = p;
++	cd->offset = cookiep;
++skip_entry:
+ 	cd->common.err = nfs_ok;
+ 	return 0;
+ fail:

commit 63e4863fabc6e165a6ca813051305be58966da45
+Author: J. Bruce Fields 
+Date:   Fri May 1 22:36:55 2009 -0400
+
+    nfsd4: make recall callback an asynchronous rpc
+    
+    As with the probe, this removes the need for another kthread.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index b88b207d75d9..f4fab69a8c30 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -494,6 +494,49 @@ nfsd4_probe_callback(struct nfs4_client *clp)
+ 	do_probe_callback(clp);
+ }
+ 
++static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
++{
++	struct nfs4_delegation *dp = calldata;
++	struct nfs4_client *clp = dp->dl_client;
++
++	switch (task->tk_status) {
++	case -EIO:
++		/* Network partition? */
++		atomic_set(&clp->cl_cb_conn.cb_set, 0);
++		warn_no_callback_path(clp, task->tk_status);
++	case -EBADHANDLE:
++	case -NFS4ERR_BAD_STATEID:
++		/* Race: client probably got cb_recall
++		 * before open reply granting delegation */
++		break;
++	default:
++		/* success, or error we can't handle */
++		return;
++	}
++	if (dp->dl_retries--) {
++		rpc_delay(task, 2*HZ);
++		task->tk_status = 0;
++		rpc_restart_call(task);
++	} else {
++		atomic_set(&clp->cl_cb_conn.cb_set, 0);
++		warn_no_callback_path(clp, task->tk_status);
++	}
++}
++
++static void nfsd4_cb_recall_release(void *calldata)
++{
++	struct nfs4_delegation *dp = calldata;
++	struct nfs4_client *clp = dp->dl_client;
++
++	nfs4_put_delegation(dp);
++	put_nfs4_client(clp);
++}
++
++static const struct rpc_call_ops nfsd4_cb_recall_ops = {
++	.rpc_call_done = nfsd4_cb_recall_done,
++	.rpc_release = nfsd4_cb_recall_release,
++};
++
+ /*
+  * called with dp->dl_count inc'ed.
+  */
+@@ -507,32 +550,13 @@ nfsd4_cb_recall(struct nfs4_delegation *dp)
+ 		.rpc_argp = dp,
+ 		.rpc_cred = clp->cl_cb_conn.cb_cred
+ 	};
+-	int status = 0;
++	int status;
+ 
+ 	dp->dl_retries = 1;
+-	status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT);
+-	while (dp->dl_retries--) {
+-		switch (status) {
+-			case -EIO:
+-				/* Network partition? */
+-				atomic_set(&clp->cl_cb_conn.cb_set, 0);
+-			case -EBADHANDLE:
+-			case -NFS4ERR_BAD_STATEID:
+-				/* Race: client probably got cb_recall
+-				 * before open reply granting delegation */
+-				break;
+-			default:
+-				goto out_put_cred;
+-		}
+-		ssleep(2);
+-		status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT);
++	status = rpc_call_async(clnt, &msg, RPC_TASK_SOFT,
++				&nfsd4_cb_recall_ops, dp);
++	if (status) {
++		put_nfs4_client(clp);
++		nfs4_put_delegation(dp);
+ 	}
+-out_put_cred:
+-	/*
+-	 * Success or failure, now we're either waiting for lease expiration
+-	 * or deleg_return.
+-	 */
+-	put_nfs4_client(clp);
+-	nfs4_put_delegation(dp);
+-	return;
+ }
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index cbb16e191d5b..a4bdf2589b41 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2059,19 +2059,6 @@ nfs4_file_downgrade(struct file *filp, unsigned int share_access)
+ 	}
+ }
+ 
+-/*
+- * Recall a delegation
+- */
+-static int
+-do_recall(void *__dp)
+-{
+-	struct nfs4_delegation *dp = __dp;
+-
+-	dp->dl_file->fi_had_conflict = true;
+-	nfsd4_cb_recall(dp);
+-	return 0;
+-}
+-
+ /*
+  * Spawn a thread to perform a recall on the delegation represented
+  * by the lease (file_lock)
+@@ -2083,8 +2070,7 @@ do_recall(void *__dp)
+ static
+ void nfsd_break_deleg_cb(struct file_lock *fl)
+ {
+-	struct nfs4_delegation *dp=  (struct nfs4_delegation *)fl->fl_owner;
+-	struct task_struct *t;
++	struct nfs4_delegation *dp = (struct nfs4_delegation *)fl->fl_owner;
+ 
+ 	dprintk("NFSD nfsd_break_deleg_cb: dp %p fl %p\n",dp,fl);
+ 	if (!dp)
+@@ -2112,16 +2098,8 @@ void nfsd_break_deleg_cb(struct file_lock *fl)
+ 	 */
+ 	fl->fl_break_time = 0;
+ 
+-	t = kthread_run(do_recall, dp, "%s", "nfs4_cb_recall");
+-	if (IS_ERR(t)) {
+-		struct nfs4_client *clp = dp->dl_client;
+-
+-		printk(KERN_INFO "NFSD: Callback thread failed for "
+-			"for client (clientid %08x/%08x)\n",
+-			clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
+-		put_nfs4_client(dp->dl_client);
+-		nfs4_put_delegation(dp);
+-	}
++	dp->dl_file->fi_had_conflict = true;
++	nfsd4_cb_recall(dp);
+ }
+ 
+ /*

commit 3aea09dc9106407d8bc18e593fbffda9ad632844
+Author: J. Bruce Fields 
+Date:   Fri May 1 20:11:12 2009 -0400
+
+    nfsd4: track recall retries in nfs4_delegation
+    
+    Move this out of a local variable into the nfs4_delegation object in
+    preparation for making this an async rpc call (at which point we'll need
+    any state like this in a common object that's preserved across function
+    calls).
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 0420b5e6e20d..b88b207d75d9 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -507,11 +507,11 @@ nfsd4_cb_recall(struct nfs4_delegation *dp)
+ 		.rpc_argp = dp,
+ 		.rpc_cred = clp->cl_cb_conn.cb_cred
+ 	};
+-	int retries = 1;
+ 	int status = 0;
+ 
++	dp->dl_retries = 1;
+ 	status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT);
+-	while (retries--) {
++	while (dp->dl_retries--) {
+ 		switch (status) {
+ 			case -EIO:
+ 				/* Network partition? */
+diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
+index 346b603072ce..c0c49215ddc5 100644
+--- a/include/linux/nfsd/state.h
++++ b/include/linux/nfsd/state.h
+@@ -76,6 +76,7 @@ struct nfs4_delegation {
+ 	u32			dl_ident;
+ 	stateid_t		dl_stateid;
+ 	struct knfsd_fh		dl_fh;
++	int			dl_retries;
+ };
+ 
+ /* client delegation callback info */

commit 6707bd3d420f53ae8f090dac871843f6f43c9980
+Author: J. Bruce Fields 
+Date:   Fri May 1 19:57:46 2009 -0400
+
+    nfsd4: remove unused dl_trunc
+    
+    There's no point in keeping this field around--it's always zero.
+    
+    (Background: the protocol allows you to tell the client that the file is
+    about to be truncated, as an optimization to save the client from
+    writing back dirty pages that will just be discarded.  We don't
+    implement this hint.  If we do some day, adding this field back in will
+    be the least of the work involved.)
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 2509305f6f53..0420b5e6e20d 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -224,7 +224,7 @@ encode_cb_recall(struct xdr_stream *xdr, struct nfs4_delegation *dp)
+ 	WRITE32(OP_CB_RECALL);
+ 	WRITE32(dp->dl_stateid.si_generation);
+ 	WRITEMEM(&dp->dl_stateid.si_opaque, sizeof(stateid_opaque_t));
+-	WRITE32(dp->dl_trunc);
++	WRITE32(0); /* truncate optimization not implemented */
+ 	WRITE32(len);
+ 	WRITEMEM(&dp->dl_fh.fh_base, len);
+ 	return 0;
+@@ -510,8 +510,6 @@ nfsd4_cb_recall(struct nfs4_delegation *dp)
+ 	int retries = 1;
+ 	int status = 0;
+ 
+-	dp->dl_trunc = 0; /* XXX need to implement truncate optimization */
+-
+ 	status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT);
+ 	while (retries--) {
+ 		switch (status) {
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 3e5345e01b13..cbb16e191d5b 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -204,7 +204,6 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
+ 	dp->dl_vfs_file = stp->st_vfs_file;
+ 	dp->dl_type = type;
+ 	dp->dl_ident = cb->cb_ident;
+-	dp->dl_trunc = 0;
+ 	dp->dl_stateid.si_boot = get_seconds();
+ 	dp->dl_stateid.si_stateownerid = current_delegid++;
+ 	dp->dl_stateid.si_fileid = 0;
+diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
+index 233b60d39b84..346b603072ce 100644
+--- a/include/linux/nfsd/state.h
++++ b/include/linux/nfsd/state.h
+@@ -74,7 +74,6 @@ struct nfs4_delegation {
+ 	time_t			dl_time;
+ /* For recall: */
+ 	u32			dl_ident;
+-	int			dl_trunc;
+ 	stateid_t		dl_stateid;
+ 	struct knfsd_fh		dl_fh;
+ };

commit b53d40c5070bffde1b2bcaf848412a50d8894794
+Author: J. Bruce Fields 
+Date:   Fri May 1 19:50:00 2009 -0400
+
+    nfsd4: eliminate struct nfs4_cb_recall
+    
+    The nfs4_cb_recall struct is used only in nfs4_delegation, so its
+    pointer to the containing delegation is unnecessary--we could just use
+    container_of().
+    
+    But there's no real reason to have this a separate struct at all--just
+    move these fields to nfs4_delegation.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index ed860d7ddd19..2509305f6f53 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -215,18 +215,18 @@ encode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr)
+ }
+ 
+ static int
+-encode_cb_recall(struct xdr_stream *xdr, struct nfs4_cb_recall *cb_rec)
++encode_cb_recall(struct xdr_stream *xdr, struct nfs4_delegation *dp)
+ {
+ 	__be32 *p;
+-	int len = cb_rec->cbr_fh.fh_size;
++	int len = dp->dl_fh.fh_size;
+ 
+-	RESERVE_SPACE(12+sizeof(cb_rec->cbr_stateid) + len);
++	RESERVE_SPACE(12+sizeof(dp->dl_stateid) + len);
+ 	WRITE32(OP_CB_RECALL);
+-	WRITE32(cb_rec->cbr_stateid.si_generation);
+-	WRITEMEM(&cb_rec->cbr_stateid.si_opaque, sizeof(stateid_opaque_t));
+-	WRITE32(cb_rec->cbr_trunc);
++	WRITE32(dp->dl_stateid.si_generation);
++	WRITEMEM(&dp->dl_stateid.si_opaque, sizeof(stateid_opaque_t));
++	WRITE32(dp->dl_trunc);
+ 	WRITE32(len);
+-	WRITEMEM(&cb_rec->cbr_fh.fh_base, len);
++	WRITEMEM(&dp->dl_fh.fh_base, len);
+ 	return 0;
+ }
+ 
+@@ -241,11 +241,11 @@ nfs4_xdr_enc_cb_null(struct rpc_rqst *req, __be32 *p)
+ }
+ 
+ static int
+-nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, __be32 *p, struct nfs4_cb_recall *args)
++nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, __be32 *p, struct nfs4_delegation *args)
+ {
+ 	struct xdr_stream xdr;
+ 	struct nfs4_cb_compound_hdr hdr = {
+-		.ident = args->cbr_ident,
++		.ident = args->dl_ident,
+ 		.nops   = 1,
+ 	};
+ 
+@@ -502,17 +502,15 @@ nfsd4_cb_recall(struct nfs4_delegation *dp)
+ {
+ 	struct nfs4_client *clp = dp->dl_client;
+ 	struct rpc_clnt *clnt = clp->cl_cb_conn.cb_client;
+-	struct nfs4_cb_recall *cbr = &dp->dl_recall;
+ 	struct rpc_message msg = {
+ 		.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL],
+-		.rpc_argp = cbr,
++		.rpc_argp = dp,
+ 		.rpc_cred = clp->cl_cb_conn.cb_cred
+ 	};
+ 	int retries = 1;
+ 	int status = 0;
+ 
+-	cbr->cbr_trunc = 0; /* XXX need to implement truncate optimization */
+-	cbr->cbr_dp = dp;
++	dp->dl_trunc = 0; /* XXX need to implement truncate optimization */
+ 
+ 	status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT);
+ 	while (retries--) {
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index d7b5e6b89207..3e5345e01b13 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -203,9 +203,8 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
+ 	get_file(stp->st_vfs_file);
+ 	dp->dl_vfs_file = stp->st_vfs_file;
+ 	dp->dl_type = type;
+-	dp->dl_recall.cbr_dp = NULL;
+-	dp->dl_recall.cbr_ident = cb->cb_ident;
+-	dp->dl_recall.cbr_trunc = 0;
++	dp->dl_ident = cb->cb_ident;
++	dp->dl_trunc = 0;
+ 	dp->dl_stateid.si_boot = get_seconds();
+ 	dp->dl_stateid.si_stateownerid = current_delegid++;
+ 	dp->dl_stateid.si_fileid = 0;
+diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
+index 563c367a3013..233b60d39b84 100644
+--- a/include/linux/nfsd/state.h
++++ b/include/linux/nfsd/state.h
+@@ -61,15 +61,6 @@ typedef struct {
+ #define si_stateownerid   si_opaque.so_stateownerid
+ #define si_fileid         si_opaque.so_fileid
+ 
+-
+-struct nfs4_cb_recall {
+-	u32			cbr_ident;
+-	int			cbr_trunc;
+-	stateid_t		cbr_stateid;
+-	struct knfsd_fh		cbr_fh;
+-	struct nfs4_delegation	*cbr_dp;
+-};
+-
+ struct nfs4_delegation {
+ 	struct list_head	dl_perfile;
+ 	struct list_head	dl_perclnt;
+@@ -81,12 +72,13 @@ struct nfs4_delegation {
+ 	struct file		*dl_vfs_file;
+ 	u32			dl_type;
+ 	time_t			dl_time;
+-	struct nfs4_cb_recall	dl_recall;
++/* For recall: */
++	u32			dl_ident;
++	int			dl_trunc;
++	stateid_t		dl_stateid;
++	struct knfsd_fh		dl_fh;
+ };
+ 
+-#define dl_stateid      dl_recall.cbr_stateid
+-#define dl_fh           dl_recall.cbr_fh
+-
+ /* client delegation callback info */
+ struct nfs4_cb_conn {
+ 	/* SETCLIENTID info */

commit c237dc0303bcf6f4cc2e0efe4fe4e341c6f34dac
+Author: J. Bruce Fields 
+Date:   Wed Apr 29 19:09:19 2009 -0400
+
+    nfsd4: rename callback struct to cb_conn
+    
+    I want to use the name for a struct that actually does represent a
+    single callback.
+    
+    (Actually, I've never been sure it helps to a separate struct for the
+    callback information.  Some day maybe those fields could just be dumped
+    into struct nfs4_client.  I don't know.)
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 0aaf68beedbd..ed860d7ddd19 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -369,7 +369,7 @@ static int max_cb_time(void)
+ int setup_callback_client(struct nfs4_client *clp)
+ {
+ 	struct sockaddr_in	addr;
+-	struct nfs4_callback    *cb = &clp->cl_callback;
++	struct nfs4_cb_conn *cb = &clp->cl_cb_conn;
+ 	struct rpc_timeout	timeparms = {
+ 		.to_initval	= max_cb_time(),
+ 		.to_retries	= 0,
+@@ -422,7 +422,7 @@ static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata)
+ 	if (task->tk_status)
+ 		warn_no_callback_path(clp, task->tk_status);
+ 	else
+-		atomic_set(&clp->cl_callback.cb_set, 1);
++		atomic_set(&clp->cl_cb_conn.cb_set, 1);
+ 	put_nfs4_client(clp);
+ }
+ 
+@@ -430,7 +430,7 @@ static const struct rpc_call_ops nfsd4_cb_probe_ops = {
+ 	.rpc_call_done = nfsd4_cb_probe_done,
+ };
+ 
+-static struct rpc_cred *lookup_cb_cred(struct nfs4_callback *cb)
++static struct rpc_cred *lookup_cb_cred(struct nfs4_cb_conn *cb)
+ {
+ 	struct auth_cred acred = {
+ 		.machine_cred = 1
+@@ -448,7 +448,7 @@ static struct rpc_cred *lookup_cb_cred(struct nfs4_callback *cb)
+ 
+ void do_probe_callback(struct nfs4_client *clp)
+ {
+-	struct nfs4_callback    *cb = &clp->cl_callback;
++	struct nfs4_cb_conn *cb = &clp->cl_cb_conn;
+ 	struct rpc_message msg = {
+ 		.rpc_proc       = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
+ 		.rpc_argp       = clp,
+@@ -480,7 +480,7 @@ nfsd4_probe_callback(struct nfs4_client *clp)
+ {
+ 	int status;
+ 
+-	BUG_ON(atomic_read(&clp->cl_callback.cb_set));
++	BUG_ON(atomic_read(&clp->cl_cb_conn.cb_set));
+ 
+ 	status = setup_callback_client(clp);
+ 	if (status) {
+@@ -501,12 +501,12 @@ void
+ nfsd4_cb_recall(struct nfs4_delegation *dp)
+ {
+ 	struct nfs4_client *clp = dp->dl_client;
+-	struct rpc_clnt *clnt = clp->cl_callback.cb_client;
++	struct rpc_clnt *clnt = clp->cl_cb_conn.cb_client;
+ 	struct nfs4_cb_recall *cbr = &dp->dl_recall;
+ 	struct rpc_message msg = {
+ 		.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL],
+ 		.rpc_argp = cbr,
+-		.rpc_cred = clp->cl_callback.cb_cred
++		.rpc_cred = clp->cl_cb_conn.cb_cred
+ 	};
+ 	int retries = 1;
+ 	int status = 0;
+@@ -519,7 +519,7 @@ nfsd4_cb_recall(struct nfs4_delegation *dp)
+ 		switch (status) {
+ 			case -EIO:
+ 				/* Network partition? */
+-				atomic_set(&clp->cl_callback.cb_set, 0);
++				atomic_set(&clp->cl_cb_conn.cb_set, 0);
+ 			case -EBADHANDLE:
+ 			case -NFS4ERR_BAD_STATEID:
+ 				/* Race: client probably got cb_recall
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index b205c7d7bc6a..d7b5e6b89207 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -182,7 +182,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
+ {
+ 	struct nfs4_delegation *dp;
+ 	struct nfs4_file *fp = stp->st_file;
+-	struct nfs4_callback *cb = &stp->st_stateowner->so_client->cl_callback;
++	struct nfs4_cb_conn *cb = &stp->st_stateowner->so_client->cl_cb_conn;
+ 
+ 	dprintk("NFSD alloc_init_deleg\n");
+ 	if (fp->fi_had_conflict)
+@@ -633,19 +633,19 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name)
+ static void
+ shutdown_callback_client(struct nfs4_client *clp)
+ {
+-	struct rpc_clnt *clnt = clp->cl_callback.cb_client;
++	struct rpc_clnt *clnt = clp->cl_cb_conn.cb_client;
+ 
+ 	if (clnt) {
+ 		/*
+ 		 * Callback threads take a reference on the client, so there
+ 		 * should be no outstanding callbacks at this point.
+ 		 */
+-		clp->cl_callback.cb_client = NULL;
++		clp->cl_cb_conn.cb_client = NULL;
+ 		rpc_shutdown_client(clnt);
+ 	}
+-	if (clp->cl_callback.cb_cred) {
+-		put_rpccred(clp->cl_callback.cb_cred);
+-		clp->cl_callback.cb_cred = NULL;
++	if (clp->cl_cb_conn.cb_cred) {
++		put_rpccred(clp->cl_cb_conn.cb_cred);
++		clp->cl_cb_conn.cb_cred = NULL;
+ 	}
+ }
+ 
+@@ -719,7 +719,7 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir)
+ 		return NULL;
+ 	memcpy(clp->cl_recdir, recdir, HEXDIR_LEN);
+ 	atomic_set(&clp->cl_count, 1);
+-	atomic_set(&clp->cl_callback.cb_set, 0);
++	atomic_set(&clp->cl_cb_conn.cb_set, 0);
+ 	INIT_LIST_HEAD(&clp->cl_idhash);
+ 	INIT_LIST_HEAD(&clp->cl_strhash);
+ 	INIT_LIST_HEAD(&clp->cl_openowners);
+@@ -971,7 +971,7 @@ parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigne
+ static void
+ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
+ {
+-	struct nfs4_callback *cb = &clp->cl_callback;
++	struct nfs4_cb_conn *cb = &clp->cl_cb_conn;
+ 
+ 	/* Currently, we only support tcp for the callback channel */
+ 	if ((se->se_callback_netid_len != 3) || memcmp((char *)se->se_callback_netid_val, "tcp", 3))
+@@ -1691,7 +1691,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+ 		else {
+ 			/* XXX: We just turn off callbacks until we can handle
+ 			  * change request correctly. */
+-			atomic_set(&conf->cl_callback.cb_set, 0);
++			atomic_set(&conf->cl_cb_conn.cb_set, 0);
+ 			expire_client(unconf);
+ 			status = nfs_ok;
+ 
+@@ -2425,7 +2425,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
+ {
+ 	struct nfs4_delegation *dp;
+ 	struct nfs4_stateowner *sop = stp->st_stateowner;
+-	struct nfs4_callback *cb = &sop->so_client->cl_callback;
++	struct nfs4_cb_conn *cb = &sop->so_client->cl_cb_conn;
+ 	struct file_lock fl, *flp = &fl;
+ 	int status, flag = 0;
+ 
+@@ -2617,7 +2617,7 @@ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	renew_client(clp);
+ 	status = nfserr_cb_path_down;
+ 	if (!list_empty(&clp->cl_delegations)
+-			&& !atomic_read(&clp->cl_callback.cb_set))
++			&& !atomic_read(&clp->cl_cb_conn.cb_set))
+ 		goto out;
+ 	status = nfs_ok;
+ out:
+diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
+index 8d882a3eb4b9..563c367a3013 100644
+--- a/include/linux/nfsd/state.h
++++ b/include/linux/nfsd/state.h
+@@ -88,7 +88,7 @@ struct nfs4_delegation {
+ #define dl_fh           dl_recall.cbr_fh
+ 
+ /* client delegation callback info */
+-struct nfs4_callback {
++struct nfs4_cb_conn {
+ 	/* SETCLIENTID info */
+ 	u32                     cb_addr;
+ 	unsigned short          cb_port;
+@@ -186,7 +186,7 @@ struct nfs4_client {
+ 	struct svc_cred		cl_cred; 	/* setclientid principal */
+ 	clientid_t		cl_clientid;	/* generated by server */
+ 	nfs4_verifier		cl_confirm;	/* generated by server */
+-	struct nfs4_callback	cl_callback;    /* callback info */
++	struct nfs4_cb_conn	cl_cb_conn;     /* callback info */
+ 	atomic_t		cl_count;	/* ref count */
+ 	u32			cl_firststate;	/* recovery dir creation */
+ 

commit e300a63ce4ccec073d254d883a3638d5dca1d771
+Author: J. Bruce Fields 
+Date:   Thu Mar 5 15:01:11 2009 -0500
+
+    nfsd4: replace callback thread by asynchronous rpc
+    
+    We don't really need a synchronous rpc, and moving to an asynchronous
+    rpc allows us to do without this extra kthread.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index cc10ed35ac81..0aaf68beedbd 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -415,6 +415,21 @@ static void warn_no_callback_path(struct nfs4_client *clp, int reason)
+ 		(int)clp->cl_name.len, clp->cl_name.data, reason);
+ }
+ 
++static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata)
++{
++	struct nfs4_client *clp = calldata;
++
++	if (task->tk_status)
++		warn_no_callback_path(clp, task->tk_status);
++	else
++		atomic_set(&clp->cl_callback.cb_set, 1);
++	put_nfs4_client(clp);
++}
++
++static const struct rpc_call_ops nfsd4_cb_probe_ops = {
++	.rpc_call_done = nfsd4_cb_probe_done,
++};
++
+ static struct rpc_cred *lookup_cb_cred(struct nfs4_callback *cb)
+ {
+ 	struct auth_cred acred = {
+@@ -431,9 +446,8 @@ static struct rpc_cred *lookup_cb_cred(struct nfs4_callback *cb)
+ 							RPCAUTH_LOOKUP_NEW);
+ }
+ 
+-static int do_probe_callback(void *data)
++void do_probe_callback(struct nfs4_client *clp)
+ {
+-	struct nfs4_client *clp = data;
+ 	struct nfs4_callback    *cb = &clp->cl_callback;
+ 	struct rpc_message msg = {
+ 		.rpc_proc       = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
+@@ -449,15 +463,13 @@ static int do_probe_callback(void *data)
+ 	}
+ 	cb->cb_cred = cred;
+ 	msg.rpc_cred = cb->cb_cred;
+-	status = rpc_call_sync(cb->cb_client, &msg, RPC_TASK_SOFT);
++	status = rpc_call_async(cb->cb_client, &msg, RPC_TASK_SOFT,
++				&nfsd4_cb_probe_ops, (void *)clp);
+ out:
+-	if (status)
++	if (status) {
+ 		warn_no_callback_path(clp, status);
+-	else
+-		atomic_set(&cb->cb_set, 1);
+-
+-	put_nfs4_client(clp);
+-	return 0;
++		put_nfs4_client(clp);
++	}
+ }
+ 
+ /*
+@@ -466,7 +478,6 @@ static int do_probe_callback(void *data)
+ void
+ nfsd4_probe_callback(struct nfs4_client *clp)
+ {
+-	struct task_struct *t;
+ 	int status;
+ 
+ 	BUG_ON(atomic_read(&clp->cl_callback.cb_set));
+@@ -480,12 +491,7 @@ nfsd4_probe_callback(struct nfs4_client *clp)
+ 	/* the task holds a reference to the nfs4_client struct */
+ 	atomic_inc(&clp->cl_count);
+ 
+-	t = kthread_run(do_probe_callback, clp, "nfs4_cb_probe");
+-
+-	if (IS_ERR(t))
+-		atomic_dec(&clp->cl_count);
+-
+-	return;
++	do_probe_callback(clp);
+ }
+ 
+ /*

commit 3cef9ab266a932899e756f7e1ea7a988a97bf3b2
+Author: J. Bruce Fields 
+Date:   Mon Feb 23 21:42:10 2009 -0800
+
+    nfsd4: lookup up callback cred only once
+    
+    Lookup the callback cred once and then use it for all subsequent
+    callbacks.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 711c6282151f..cc10ed35ac81 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -415,6 +415,22 @@ static void warn_no_callback_path(struct nfs4_client *clp, int reason)
+ 		(int)clp->cl_name.len, clp->cl_name.data, reason);
+ }
+ 
++static struct rpc_cred *lookup_cb_cred(struct nfs4_callback *cb)
++{
++	struct auth_cred acred = {
++		.machine_cred = 1
++	};
++
++	/*
++	 * Note in the gss case this doesn't actually have to wait for a
++	 * gss upcall (or any calls to the client); this just creates a
++	 * non-uptodate cred which the rpc state machine will fill in with
++	 * a refresh_upcall later.
++	 */
++	return rpcauth_lookup_credcache(cb->cb_client->cl_auth, &acred,
++							RPCAUTH_LOOKUP_NEW);
++}
++
+ static int do_probe_callback(void *data)
+ {
+ 	struct nfs4_client *clp = data;
+@@ -423,9 +439,18 @@ static int do_probe_callback(void *data)
+ 		.rpc_proc       = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
+ 		.rpc_argp       = clp,
+ 	};
++	struct rpc_cred *cred;
+ 	int status;
+ 
++	cred = lookup_cb_cred(cb);
++	if (IS_ERR(cred)) {
++		status = PTR_ERR(cred);
++		goto out;
++	}
++	cb->cb_cred = cred;
++	msg.rpc_cred = cb->cb_cred;
+ 	status = rpc_call_sync(cb->cb_client, &msg, RPC_TASK_SOFT);
++out:
+ 	if (status)
+ 		warn_no_callback_path(clp, status);
+ 	else
+@@ -475,6 +500,7 @@ nfsd4_cb_recall(struct nfs4_delegation *dp)
+ 	struct rpc_message msg = {
+ 		.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL],
+ 		.rpc_argp = cbr,
++		.rpc_cred = clp->cl_callback.cb_cred
+ 	};
+ 	int retries = 1;
+ 	int status = 0;
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 7e1fcc3aade4..b205c7d7bc6a 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -643,6 +643,10 @@ shutdown_callback_client(struct nfs4_client *clp)
+ 		clp->cl_callback.cb_client = NULL;
+ 		rpc_shutdown_client(clnt);
+ 	}
++	if (clp->cl_callback.cb_cred) {
++		put_rpccred(clp->cl_callback.cb_cred);
++		clp->cl_callback.cb_cred = NULL;
++	}
+ }
+ 
+ static inline void
+diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
+index 4d61c873feed..8d882a3eb4b9 100644
+--- a/include/linux/nfsd/state.h
++++ b/include/linux/nfsd/state.h
+@@ -97,6 +97,7 @@ struct nfs4_callback {
+ 	/* RPC client info */
+ 	atomic_t		cb_set;     /* successful CB_NULL call */
+ 	struct rpc_clnt *       cb_client;
++	struct rpc_cred	*	cb_cred;
+ };
+ 
+ /* Maximum number of slots per session. 128 is useful for long haul TCP */

commit ecdd03b7914c91ef849e49c4d466c87f4981b5cd
+Author: J. Bruce Fields 
+Date:   Mon Feb 23 19:35:22 2009 -0800
+
+    nfsd4: create rpc callback client from server thread
+    
+    The code is a little simpler, and it should be easier to avoid races, if
+    we just do all rpc client creation/destruction from nfsd or laundromat
+    threads and do only the rpc calls themselves asynchronously.  The rpc
+    creation doesn't involve any significant waiting (it doesn't call the
+    client, for example), so there's no reason not to do this.
+    
+    Also don't bother destroying the client on failure of the rpc null
+    probe.  We may want to retry the probe later anyway.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 4788d09d9bec..711c6282151f 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -409,6 +409,12 @@ int setup_callback_client(struct nfs4_client *clp)
+ 
+ }
+ 
++static void warn_no_callback_path(struct nfs4_client *clp, int reason)
++{
++	dprintk("NFSD: warning: no callback path to client %.*s: error %d\n",
++		(int)clp->cl_name.len, clp->cl_name.data, reason);
++}
++
+ static int do_probe_callback(void *data)
+ {
+ 	struct nfs4_client *clp = data;
+@@ -419,24 +425,12 @@ static int do_probe_callback(void *data)
+ 	};
+ 	int status;
+ 
+-	status = setup_callback_client(clp);
+-	if (status)
+-		goto out_err;
+-
+ 	status = rpc_call_sync(cb->cb_client, &msg, RPC_TASK_SOFT);
+-
+ 	if (status)
+-		goto out_release_client;
++		warn_no_callback_path(clp, status);
++	else
++		atomic_set(&cb->cb_set, 1);
+ 
+-	atomic_set(&cb->cb_set, 1);
+-	put_nfs4_client(clp);
+-	return 0;
+-out_release_client:
+-	rpc_shutdown_client(cb->cb_client);
+-	cb->cb_client = NULL;
+-out_err:
+-	dprintk("NFSD: warning: no callback path to client %.*s: error %d\n",
+-		(int)clp->cl_name.len, clp->cl_name.data, status);
+ 	put_nfs4_client(clp);
+ 	return 0;
+ }
+@@ -448,9 +442,16 @@ void
+ nfsd4_probe_callback(struct nfs4_client *clp)
+ {
+ 	struct task_struct *t;
++	int status;
+ 
+ 	BUG_ON(atomic_read(&clp->cl_callback.cb_set));
+ 
++	status = setup_callback_client(clp);
++	if (status) {
++		warn_no_callback_path(clp, status);
++		return;
++	}
++
+ 	/* the task holds a reference to the nfs4_client struct */
+ 	atomic_inc(&clp->cl_count);
+ 

commit e1cab5a5896e142190cd66a8287099b52e5855a7
+Author: J. Bruce Fields 
+Date:   Mon Feb 23 10:45:27 2009 -0800
+
+    nfsd4: set cb_client inside setup_callback_client
+    
+    This is just a minor code simplification.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 049f052a6eb3..4788d09d9bec 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -366,7 +366,7 @@ static int max_cb_time(void)
+ /* Reference counting, callback cleanup, etc., all look racy as heck.
+  * And why is cb_set an atomic? */
+ 
+-static struct rpc_clnt *setup_callback_client(struct nfs4_client *clp)
++int setup_callback_client(struct nfs4_client *clp)
+ {
+ 	struct sockaddr_in	addr;
+ 	struct nfs4_callback    *cb = &clp->cl_callback;
+@@ -389,7 +389,7 @@ static struct rpc_clnt *setup_callback_client(struct nfs4_client *clp)
+ 	struct rpc_clnt *client;
+ 
+ 	if (!clp->cl_principal && (clp->cl_flavor >= RPC_AUTH_GSS_KRB5))
+-		return ERR_PTR(-EINVAL);
++		return -EINVAL;
+ 
+ 	/* Initialize address */
+ 	memset(&addr, 0, sizeof(addr));
+@@ -399,10 +399,13 @@ static struct rpc_clnt *setup_callback_client(struct nfs4_client *clp)
+ 
+ 	/* Create RPC client */
+ 	client = rpc_create(&args);
+-	if (IS_ERR(client))
++	if (IS_ERR(client)) {
+ 		dprintk("NFSD: couldn't create callback client: %ld\n",
+ 			PTR_ERR(client));
+-	return client;
++		return PTR_ERR(client);
++	}
++	cb->cb_client = client;
++	return 0;
+ 
+ }
+ 
+@@ -414,28 +417,23 @@ static int do_probe_callback(void *data)
+ 		.rpc_proc       = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
+ 		.rpc_argp       = clp,
+ 	};
+-	struct rpc_clnt *client;
+ 	int status;
+ 
+-	client = setup_callback_client(clp);
+-	if (IS_ERR(client)) {
+-		status = PTR_ERR(client);
+-		dprintk("NFSD: couldn't create callback client: %d\n",
+-								status);
++	status = setup_callback_client(clp);
++	if (status)
+ 		goto out_err;
+-	}
+ 
+-	status = rpc_call_sync(client, &msg, RPC_TASK_SOFT);
++	status = rpc_call_sync(cb->cb_client, &msg, RPC_TASK_SOFT);
+ 
+ 	if (status)
+ 		goto out_release_client;
+ 
+-	cb->cb_client = client;
+ 	atomic_set(&cb->cb_set, 1);
+ 	put_nfs4_client(clp);
+ 	return 0;
+ out_release_client:
+-	rpc_shutdown_client(client);
++	rpc_shutdown_client(cb->cb_client);
++	cb->cb_client = NULL;
+ out_err:
+ 	dprintk("NFSD: warning: no callback path to client %.*s: error %d\n",
+ 		(int)clp->cl_name.len, clp->cl_name.data, status);

commit 595947acaaef373445131471a78650003f5d8e7d
+Author: J. Bruce Fields 
+Date:   Thu Mar 5 17:18:10 2009 -0500
+
+    nfsd4: set shorter timeout
+    
+    We tried to do something overly complicated with the callback rpc
+    timeouts here.  And they're wrong--the result is that by the time a
+    single callback times out, it's already too late to tell the client
+    (using the cb_path_down return to RENEW) that the callback is down.
+    
+    Use a much shorter, simpler timeout.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 290289bd44f7..049f052a6eb3 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -358,6 +358,11 @@ static struct rpc_program cb_program = {
+ 		.pipe_dir_name  = "/nfsd4_cb",
+ };
+ 
++static int max_cb_time(void)
++{
++	return max(NFSD_LEASE_TIME/10, (time_t)1) * HZ;
++}
++
+ /* Reference counting, callback cleanup, etc., all look racy as heck.
+  * And why is cb_set an atomic? */
+ 
+@@ -366,10 +371,8 @@ static struct rpc_clnt *setup_callback_client(struct nfs4_client *clp)
+ 	struct sockaddr_in	addr;
+ 	struct nfs4_callback    *cb = &clp->cl_callback;
+ 	struct rpc_timeout	timeparms = {
+-		.to_initval	= (NFSD_LEASE_TIME/4) * HZ,
+-		.to_retries	= 5,
+-		.to_maxval	= (NFSD_LEASE_TIME/2) * HZ,
+-		.to_exponential	= 1,
++		.to_initval	= max_cb_time(),
++		.to_retries	= 0,
+ 	};
+ 	struct rpc_create_args args = {
+ 		.protocol	= IPPROTO_TCP,

commit f64f79ea5f5e02ba8585f35a10b4a3bcab0cea52
+Author: J. Bruce Fields 
+Date:   Wed Apr 29 13:45:36 2009 -0400
+
+    nfsd4: setclientid_confirm callback-change fixes
+    
+    This setclientid_confirm case should allow the client to change
+    callbacks, but it currently has a dummy implementation that just turns
+    off callbacks completely.  That dummy implementation isn't completely
+    correct either, though:
+    
+            - There's no need to remove any client recovery directory in
+              this case.
+            - New clientid confirm verifiers should be generated (and
+              returned) in setclientid; there's no need to generate a new
+              one here.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index d24dd12ddb4d..7e1fcc3aade4 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1688,8 +1688,6 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+ 			/* XXX: We just turn off callbacks until we can handle
+ 			  * change request correctly. */
+ 			atomic_set(&conf->cl_callback.cb_set, 0);
+-			gen_confirm(conf);
+-			nfsd4_remove_clid_dir(unconf);
+ 			expire_client(unconf);
+ 			status = nfs_ok;
+ 

commit b8fd47aefa5f13df1edacbc7e68d9874635109e5
+Author: J. Bruce Fields 
+Date:   Wed Apr 29 11:36:17 2009 -0400
+
+    nfsd: quiet compile warning
+    
+    Stephen Rothwell said:
+    "Today's linux-next build (powerpc ppc64_defconfig) produced this new
+    warning:
+    
+    fs/nfsd/nfs4state.c: In function 'EXPIRED_STATEID':
+    fs/nfsd/nfs4state.c:2757: warning: comparison of distinct pointer types lacks a cast
+    
+    Caused by commit 78155ed75f470710f2aecb3e75e3d97107ba8374 ("nfsd4:
+    distinguish expired from stale stateids")."
+    
+    Signed-off-by: J. Bruce Fields 
+    Reported-by: Stephen Rothwell 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 74e822ec34cb..d24dd12ddb4d 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2754,7 +2754,7 @@ EXPIRED_STATEID(stateid_t *stateid)
+ {
+ 	if (time_before((unsigned long)boot_time,
+ 			((unsigned long)stateid->si_boot)) &&
+-	    time_before((stateid->si_boot + lease_time), get_seconds())) {
++	    time_before((unsigned long)(stateid->si_boot + lease_time), get_seconds())) {
+ 		dprintk("NFSD: expired stateid (%08x/%08x/%08x/%08x)!\n",
+ 			stateid->si_boot, stateid->si_stateownerid,
+ 			stateid->si_fileid, stateid->si_generation);

commit c654b8a9cba6002aad1c01919e4928a79a4a6dcf
+Author: J. Bruce Fields 
+Date:   Thu Apr 16 17:33:25 2009 -0400
+
+    nfsd: support ext4 i_version
+    
+    ext4 supports a real NFSv4 change attribute, which is bumped whenever
+    the ctime would be updated, including times when two updates arrive
+    within a jiffy of each other.  (Note that although ext4 has space for
+    nanosecond-precision ctime, the real resolution is lower: it actually
+    uses jiffies as the time-source.)  This ensures clients will invalidate
+    their caches when they need to.
+    
+    There is some fear that keeping the i_version up-to-date could have
+    performance drawbacks, so for now it's turned on only by a mount option.
+    We hope to do something better eventually.
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: Theodore Tso 
+
+diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
+index 17d0dd997204..01d4ec1c88e0 100644
+--- a/fs/nfsd/nfs3xdr.c
++++ b/fs/nfsd/nfs3xdr.c
+@@ -272,6 +272,7 @@ void fill_post_wcc(struct svc_fh *fhp)
+ 
+ 	err = vfs_getattr(fhp->fh_export->ex_path.mnt, fhp->fh_dentry,
+ 			&fhp->fh_post_attr);
++	fhp->fh_post_change = fhp->fh_dentry->d_inode->i_version;
+ 	if (err)
+ 		fhp->fh_post_saved = 0;
+ 	else
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index 4a71fcd3f036..12d36a7361cd 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -1490,13 +1490,41 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
+ 	memcpy(p, ptr, nbytes);					\
+ 	p += XDR_QUADLEN(nbytes);				\
+ }} while (0)
+-#define WRITECINFO(c)		do {				\
+-	*p++ = htonl(c.atomic);					\
+-	*p++ = htonl(c.before_ctime_sec);				\
+-	*p++ = htonl(c.before_ctime_nsec);				\
+-	*p++ = htonl(c.after_ctime_sec);				\
+-	*p++ = htonl(c.after_ctime_nsec);				\
+-} while (0)
++
++static void write32(__be32 **p, u32 n)
++{
++	*(*p)++ = n;
++}
++
++static void write64(__be32 **p, u64 n)
++{
++	write32(p, (u32)(n >> 32));
++	write32(p, (u32)n);
++}
++
++static void write_change(__be32 **p, struct kstat *stat, struct inode *inode)
++{
++	if (IS_I_VERSION(inode)) {
++		write64(p, inode->i_version);
++	} else {
++		write32(p, stat->ctime.tv_sec);
++		write32(p, stat->ctime.tv_nsec);
++	}
++}
++
++static void write_cinfo(__be32 **p, struct nfsd4_change_info *c)
++{
++	write32(p, c->atomic);
++	if (c->change_supported) {
++		write64(p, c->before_change);
++		write64(p, c->after_change);
++	} else {
++		write32(p, c->before_ctime_sec);
++		write32(p, c->before_ctime_nsec);
++		write32(p, c->after_ctime_sec);
++		write32(p, c->after_ctime_nsec);
++	}
++}
+ 
+ #define RESERVE_SPACE(nbytes)	do {				\
+ 	p = resp->p;						\
+@@ -1849,16 +1877,9 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
+ 			WRITE32(NFS4_FH_PERSISTENT|NFS4_FH_VOL_RENAME);
+ 	}
+ 	if (bmval0 & FATTR4_WORD0_CHANGE) {
+-		/*
+-		 * Note: This _must_ be consistent with the scheme for writing
+-		 * change_info, so any changes made here must be reflected there
+-		 * as well.  (See xdr4.h:set_change_info() and the WRITECINFO()
+-		 * macro above.)
+-		 */
+ 		if ((buflen -= 8) < 0)
+ 			goto out_resource;
+-		WRITE32(stat.ctime.tv_sec);
+-		WRITE32(stat.ctime.tv_nsec);
++		write_change(&p, &stat, dentry->d_inode);
+ 	}
+ 	if (bmval0 & FATTR4_WORD0_SIZE) {
+ 		if ((buflen -= 8) < 0)
+@@ -2364,7 +2385,7 @@ nfsd4_encode_create(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
+ 
+ 	if (!nfserr) {
+ 		RESERVE_SPACE(32);
+-		WRITECINFO(create->cr_cinfo);
++		write_cinfo(&p, &create->cr_cinfo);
+ 		WRITE32(2);
+ 		WRITE32(create->cr_bmval[0]);
+ 		WRITE32(create->cr_bmval[1]);
+@@ -2475,7 +2496,7 @@ nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_li
+ 
+ 	if (!nfserr) {
+ 		RESERVE_SPACE(20);
+-		WRITECINFO(link->li_cinfo);
++		write_cinfo(&p, &link->li_cinfo);
+ 		ADJUST_ARGS();
+ 	}
+ 	return nfserr;
+@@ -2493,7 +2514,7 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_op
+ 
+ 	nfsd4_encode_stateid(resp, &open->op_stateid);
+ 	RESERVE_SPACE(40);
+-	WRITECINFO(open->op_cinfo);
++	write_cinfo(&p, &open->op_cinfo);
+ 	WRITE32(open->op_rflags);
+ 	WRITE32(2);
+ 	WRITE32(open->op_bmval[0]);
+@@ -2771,7 +2792,7 @@ nfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
+ 
+ 	if (!nfserr) {
+ 		RESERVE_SPACE(20);
+-		WRITECINFO(remove->rm_cinfo);
++		write_cinfo(&p, &remove->rm_cinfo);
+ 		ADJUST_ARGS();
+ 	}
+ 	return nfserr;
+@@ -2784,8 +2805,8 @@ nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
+ 
+ 	if (!nfserr) {
+ 		RESERVE_SPACE(40);
+-		WRITECINFO(rename->rn_sinfo);
+-		WRITECINFO(rename->rn_tinfo);
++		write_cinfo(&p, &rename->rn_sinfo);
++		write_cinfo(&p, &rename->rn_tinfo);
+ 		ADJUST_ARGS();
+ 	}
+ 	return nfserr;
+diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h
+index afa19016c4a8..8f641c908450 100644
+--- a/include/linux/nfsd/nfsfh.h
++++ b/include/linux/nfsd/nfsfh.h
+@@ -151,9 +151,15 @@ typedef struct svc_fh {
+ 	__u64			fh_pre_size;	/* size before operation */
+ 	struct timespec		fh_pre_mtime;	/* mtime before oper */
+ 	struct timespec		fh_pre_ctime;	/* ctime before oper */
++	/*
++	 * pre-op nfsv4 change attr: note must check IS_I_VERSION(inode)
++	 *  to find out if it is valid.
++	 */
++	u64			fh_pre_change;
+ 
+ 	/* Post-op attributes saved in fh_unlock */
+ 	struct kstat		fh_post_attr;	/* full attrs after operation */
++	u64			fh_post_change; /* nfsv4 change; see above */
+ #endif /* CONFIG_NFSD_V3 */
+ 
+ } svc_fh;
+@@ -298,6 +304,7 @@ fill_pre_wcc(struct svc_fh *fhp)
+ 		fhp->fh_pre_mtime = inode->i_mtime;
+ 		fhp->fh_pre_ctime = inode->i_ctime;
+ 		fhp->fh_pre_size  = inode->i_size;
++		fhp->fh_pre_change = inode->i_version;
+ 		fhp->fh_pre_saved = 1;
+ 	}
+ }
+diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
+index f80d6013fdc3..d0f050f01eca 100644
+--- a/include/linux/nfsd/xdr4.h
++++ b/include/linux/nfsd/xdr4.h
+@@ -64,10 +64,13 @@ static inline bool nfsd4_has_session(struct nfsd4_compound_state *cs)
+ 
+ struct nfsd4_change_info {
+ 	u32		atomic;
++	bool		change_supported;
+ 	u32		before_ctime_sec;
+ 	u32		before_ctime_nsec;
++	u64		before_change;
+ 	u32		after_ctime_sec;
+ 	u32		after_ctime_nsec;
++	u64		after_change;
+ };
+ 
+ struct nfsd4_access {
+@@ -503,10 +506,16 @@ set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp)
+ {
+ 	BUG_ON(!fhp->fh_pre_saved || !fhp->fh_post_saved);
+ 	cinfo->atomic = 1;
+-	cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec;
+-	cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec;
+-	cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec;
+-	cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec;
++	cinfo->change_supported = IS_I_VERSION(fhp->fh_dentry->d_inode);
++	if (cinfo->change_supported) {
++		cinfo->before_change = fhp->fh_pre_change;
++		cinfo->after_change = fhp->fh_post_change;
++	} else {
++		cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec;
++		cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec;
++		cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec;
++		cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec;
++	}
+ }
+ 
+ int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *);

commit 3352d2c2d0540955a7bbb3421a28330af7f9d79c
+Author: J. Bruce Fields 
+Date:   Tue Apr 7 17:03:19 2009 -0700
+
+    nfsd4: delete obsolete xdr comments
+    
+    We don't need comments to tell us these macros are ugly.  And we're long
+    past trying to share any of this code with the BSD's.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index fe46edeab2f6..4a71fcd3f036 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -83,16 +83,6 @@ check_filename(char *str, int len, __be32 err)
+ 	return 0;
+ }
+ 
+-/*
+- * START OF "GENERIC" DECODE ROUTINES.
+- *   These may look a little ugly since they are imported from a "generic"
+- * set of XDR encode/decode routines which are intended to be shared by
+- * all of our NFSv4 implementations (OpenBSD, MacOS X...).
+- *
+- * If the pain of reading these is too great, it should be a straightforward
+- * task to translate them into Linux-specific versions which are more
+- * consistent with the style used in NFSv2/v3...
+- */
+ #define DECODE_HEAD				\
+ 	__be32 *p;				\
+ 	__be32 status
+@@ -1489,20 +1479,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
+ 
+ 	DECODE_TAIL;
+ }
+-/*
+- * END OF "GENERIC" DECODE ROUTINES.
+- */
+ 
+-/*
+- * START OF "GENERIC" ENCODE ROUTINES.
+- *   These may look a little ugly since they are imported from a "generic"
+- * set of XDR encode/decode routines which are intended to be shared by
+- * all of our NFSv4 implementations (OpenBSD, MacOS X...).
+- *
+- * If the pain of reading these is too great, it should be a straightforward
+- * task to translate them into Linux-specific versions which are more
+- * consistent with the style used in NFSv2/v3...
+- */
+ #define WRITE32(n)               *p++ = htonl(n)
+ #define WRITE64(n)               do {				\
+ 	*p++ = htonl((u32)((n) >> 32));				\
+@@ -3252,10 +3229,6 @@ nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
+ 	ADJUST_ARGS();
+ }
+ 
+-/*
+- * END OF "GENERIC" ENCODE ROUTINES.
+- */
+-
+ int
+ nfs4svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy)
+ {

commit bc749ca4c405d507e6ec6e3f3e5475e9a09faf0a
+Author: J. Bruce Fields 
+Date:   Tue Apr 7 16:55:27 2009 -0700
+
+    nfsd: eliminate ENCODE_HEAD macro
+    
+    This macro doesn't serve any useful purpose.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index b820c311931c..fe46edeab2f6 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -1503,8 +1503,6 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
+  * task to translate them into Linux-specific versions which are more
+  * consistent with the style used in NFSv2/v3...
+  */
+-#define ENCODE_HEAD              __be32 *p
+-
+ #define WRITE32(n)               *p++ = htonl(n)
+ #define WRITE64(n)               do {				\
+ 	*p++ = htonl((u32)((n) >> 32));				\
+@@ -2334,7 +2332,7 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
+ static void
+ nfsd4_encode_stateid(struct nfsd4_compoundres *resp, stateid_t *sid)
+ {
+-	ENCODE_HEAD;
++	__be32 *p;
+ 
+ 	RESERVE_SPACE(sizeof(stateid_t));
+ 	WRITE32(sid->si_generation);
+@@ -2345,7 +2343,7 @@ nfsd4_encode_stateid(struct nfsd4_compoundres *resp, stateid_t *sid)
+ static __be32
+ nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_access *access)
+ {
+-	ENCODE_HEAD;
++	__be32 *p;
+ 
+ 	if (!nfserr) {
+ 		RESERVE_SPACE(8);
+@@ -2372,7 +2370,7 @@ nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_c
+ static __be32
+ nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_commit *commit)
+ {
+-	ENCODE_HEAD;
++	__be32 *p;
+ 
+ 	if (!nfserr) {
+ 		RESERVE_SPACE(8);
+@@ -2385,7 +2383,7 @@ nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
+ static __be32
+ nfsd4_encode_create(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_create *create)
+ {
+-	ENCODE_HEAD;
++	__be32 *p;
+ 
+ 	if (!nfserr) {
+ 		RESERVE_SPACE(32);
+@@ -2421,7 +2419,7 @@ nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh
+ {
+ 	struct svc_fh *fhp = *fhpp;
+ 	unsigned int len;
+-	ENCODE_HEAD;
++	__be32 *p;
+ 
+ 	if (!nfserr) {
+ 		len = fhp->fh_handle.fh_size;
+@@ -2440,7 +2438,7 @@ nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh
+ static void
+ nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denied *ld)
+ {
+-	ENCODE_HEAD;
++	__be32 *p;
+ 
+ 	RESERVE_SPACE(32 + XDR_LEN(ld->ld_sop ? ld->ld_sop->so_owner.len : 0));
+ 	WRITE64(ld->ld_start);
+@@ -2496,7 +2494,7 @@ nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_l
+ static __be32
+ nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_link *link)
+ {
+-	ENCODE_HEAD;
++	__be32 *p;
+ 
+ 	if (!nfserr) {
+ 		RESERVE_SPACE(20);
+@@ -2510,7 +2508,7 @@ nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_li
+ static __be32
+ nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open *open)
+ {
+-	ENCODE_HEAD;
++	__be32 *p;
+ 	ENCODE_SEQID_OP_HEAD;
+ 
+ 	if (nfserr)
+@@ -2605,7 +2603,7 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
+ 	int v, pn;
+ 	unsigned long maxcount; 
+ 	long len;
+-	ENCODE_HEAD;
++	__be32 *p;
+ 
+ 	if (nfserr)
+ 		return nfserr;
+@@ -2667,7 +2665,7 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd
+ {
+ 	int maxcount;
+ 	char *page;
+-	ENCODE_HEAD;
++	__be32 *p;
+ 
+ 	if (nfserr)
+ 		return nfserr;
+@@ -2716,7 +2714,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
+ 	int maxcount;
+ 	loff_t offset;
+ 	__be32 *page, *savep, *tailbase;
+-	ENCODE_HEAD;
++	__be32 *p;
+ 
+ 	if (nfserr)
+ 		return nfserr;
+@@ -2792,7 +2790,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
+ static __be32
+ nfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_remove *remove)
+ {
+-	ENCODE_HEAD;
++	__be32 *p;
+ 
+ 	if (!nfserr) {
+ 		RESERVE_SPACE(20);
+@@ -2805,7 +2803,7 @@ nfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
+ static __be32
+ nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_rename *rename)
+ {
+-	ENCODE_HEAD;
++	__be32 *p;
+ 
+ 	if (!nfserr) {
+ 		RESERVE_SPACE(40);
+@@ -2825,7 +2823,7 @@ nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, __be32 nfserr,
+ 	u32 nflavs;
+ 	struct exp_flavor_info *flavs;
+ 	struct exp_flavor_info def_flavs[2];
+-	ENCODE_HEAD;
++	__be32 *p;
+ 
+ 	if (nfserr)
+ 		goto out;
+@@ -2890,7 +2888,7 @@ nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, __be32 nfserr,
+ static __be32
+ nfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setattr *setattr)
+ {
+-	ENCODE_HEAD;
++	__be32 *p;
+ 
+ 	RESERVE_SPACE(12);
+ 	if (nfserr) {
+@@ -2910,7 +2908,7 @@ nfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
+ static __be32
+ nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setclientid *scd)
+ {
+-	ENCODE_HEAD;
++	__be32 *p;
+ 
+ 	if (!nfserr) {
+ 		RESERVE_SPACE(8 + sizeof(nfs4_verifier));
+@@ -2930,7 +2928,7 @@ nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct n
+ static __be32
+ nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_write *write)
+ {
+-	ENCODE_HEAD;
++	__be32 *p;
+ 
+ 	if (!nfserr) {
+ 		RESERVE_SPACE(16);
+@@ -2946,7 +2944,7 @@ static __be32
+ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, int nfserr,
+ 			 struct nfsd4_exchange_id *exid)
+ {
+-	ENCODE_HEAD;
++	__be32 *p;
+ 	char *major_id;
+ 	char *server_scope;
+ 	int major_id_sz;
+@@ -3001,7 +2999,7 @@ static __be32
+ nfsd4_encode_create_session(struct nfsd4_compoundres *resp, int nfserr,
+ 			    struct nfsd4_create_session *sess)
+ {
+-	ENCODE_HEAD;
++	__be32 *p;
+ 
+ 	if (nfserr)
+ 		return nfserr;
+@@ -3057,7 +3055,7 @@ __be32
+ nfsd4_encode_sequence(struct nfsd4_compoundres *resp, int nfserr,
+ 		      struct nfsd4_sequence *seq)
+ {
+-	ENCODE_HEAD;
++	__be32 *p;
+ 
+ 	if (nfserr)
+ 		return nfserr;
+@@ -3205,7 +3203,7 @@ void
+ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
+ {
+ 	__be32 *statp;
+-	ENCODE_HEAD;
++	__be32 *p;
+ 
+ 	RESERVE_SPACE(8);
+ 	WRITE32(op->opnum);
+@@ -3239,7 +3237,7 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
+ void
+ nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
+ {
+-	ENCODE_HEAD;
++	__be32 *p;
+ 	struct nfs4_replay *rp = op->replay;
+ 
+ 	BUG_ON(!rp);

commit a5422a5111811401f7756345e4c237ff06cf6d1e
+Author: Fred Isaman 
+Date:   Thu Apr 23 16:40:32 2009 +0300
+
+    lib: find_last_bit.o needed by a module only, move it from lib to obj
+    
+    Currently, although find_last_bit is EXPORTed, it is statically linked
+    with the kernel and is referenced only under CONFIG_SMP.
+    
+    When CONFIG_SMP is undefined and find_last_bit is referenced only by
+    modules, linking fails with:
+    
+      ERROR: "find_last_bit" [fs/nfs/nfs.ko] undefined!
+    
+    Cc: Rusty Russell 
+    Cc: Trond Myklebust 
+    Signed-off-by: Fred Isaman 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/lib/Makefile b/lib/Makefile
+index d6edd6753f40..33a40e40e3ee 100644
+--- a/lib/Makefile
++++ b/lib/Makefile
+@@ -38,7 +38,7 @@ lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
+ lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
+ lib-$(CONFIG_GENERIC_FIND_FIRST_BIT) += find_next_bit.o
+ lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o
+-lib-$(CONFIG_GENERIC_FIND_LAST_BIT) += find_last_bit.o
++obj-$(CONFIG_GENERIC_FIND_LAST_BIT) += find_last_bit.o
+ obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
+ obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
+ obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o

commit 47a14ef1af48c696b214ac168f056ddc79793d0e
+Author: Olga Kornievskaia 
+Date:   Tue Oct 21 14:13:47 2008 -0400
+
+    svcrpc: take advantage of tcp autotuning
+    
+    Allow the NFSv4 server to make use of TCP autotuning behaviour, which
+    was previously disabled by setting the sk_userlocks variable.
+    
+    Set the receive buffers to be big enough to receive the whole RPC
+    request, and set this for the listening socket, not the accept socket.
+    
+    Remove the code that readjusts the receive/send buffer sizes for the
+    accepted socket. Previously this code was used to influence the TCP
+    window management behaviour, which is no longer needed when autotuning
+    is enabled.
+    
+    This can improve IO bandwidth on networks with high bandwidth-delay
+    products, where a large tcp window is required.  It also simplifies
+    performance tuning, since getting adequate tcp buffers previously
+    required increasing the number of nfsd threads.
+    
+    Signed-off-by: Olga Kornievskaia 
+    Cc: Jim Rees 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
+index 5763e6460fea..7a2a90fb2e06 100644
+--- a/net/sunrpc/svcsock.c
++++ b/net/sunrpc/svcsock.c
+@@ -345,7 +345,6 @@ static void svc_sock_setbufsize(struct socket *sock, unsigned int snd,
+ 	lock_sock(sock->sk);
+ 	sock->sk->sk_sndbuf = snd * 2;
+ 	sock->sk->sk_rcvbuf = rcv * 2;
+-	sock->sk->sk_userlocks |= SOCK_SNDBUF_LOCK|SOCK_RCVBUF_LOCK;
+ 	release_sock(sock->sk);
+ #endif
+ }
+@@ -797,23 +796,6 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
+ 		test_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags),
+ 		test_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags));
+ 
+-	if (test_and_clear_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags))
+-		/* sndbuf needs to have room for one request
+-		 * per thread, otherwise we can stall even when the
+-		 * network isn't a bottleneck.
+-		 *
+-		 * We count all threads rather than threads in a
+-		 * particular pool, which provides an upper bound
+-		 * on the number of threads which will access the socket.
+-		 *
+-		 * rcvbuf just needs to be able to hold a few requests.
+-		 * Normally they will be removed from the queue
+-		 * as soon a a complete request arrives.
+-		 */
+-		svc_sock_setbufsize(svsk->sk_sock,
+-				    (serv->sv_nrthreads+3) * serv->sv_max_mesg,
+-				    3 * serv->sv_max_mesg);
+-
+ 	clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
+ 
+ 	/* Receive data. If we haven't got the record length yet, get
+@@ -1061,15 +1043,6 @@ static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv)
+ 
+ 		tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF;
+ 
+-		/* initialise setting must have enough space to
+-		 * receive and respond to one request.
+-		 * svc_tcp_recvfrom will re-adjust if necessary
+-		 */
+-		svc_sock_setbufsize(svsk->sk_sock,
+-				    3 * svsk->sk_xprt.xpt_server->sv_max_mesg,
+-				    3 * svsk->sk_xprt.xpt_server->sv_max_mesg);
+-
+-		set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags);
+ 		set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
+ 		if (sk->sk_state != TCP_ESTABLISHED)
+ 			set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
+@@ -1140,8 +1113,14 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
+ 	/* Initialize the socket */
+ 	if (sock->type == SOCK_DGRAM)
+ 		svc_udp_init(svsk, serv);
+-	else
++	else {
++		/* initialise setting must have enough space to
++		 * receive and respond to one request.
++		 */
++		svc_sock_setbufsize(svsk->sk_sock, 4 * serv->sv_max_mesg,
++					4 * serv->sv_max_mesg);
+ 		svc_tcp_init(svsk, serv);
++	}
+ 
+ 	/*
+ 	 * We start one listener per sv_serv.  We want AF_INET

commit 026722c25e6eb018eab8b9a3c198c258f5b7a2e7
+Author: J. Bruce Fields 
+Date:   Wed Mar 18 15:06:26 2009 -0400
+
+    nfsd4: don't check ip address in setclientid
+    
+    The spec allows clients to change ip address, so we shouldn't be
+    requiring that setclientid always come from the same address.  For
+    example, a client could reboot and get a new dhcpd address, but still
+    present the same clientid to the server.  In that case the server should
+    revoke the client's previous state and allow it to continue, instead of
+    (as it currently does) returning a CLID_INUSE error.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 54651aa45790..070e9e5c0452 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -791,10 +791,9 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	if (conf) {
+ 		/* RFC 3530 14.2.33 CASE 0: */
+ 		status = nfserr_clid_inuse;
+-		if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)
+-				|| conf->cl_addr != sin->sin_addr.s_addr) {
+-			dprintk("NFSD: setclientid: string in use by clientat %pI4\n",
+-				&conf->cl_addr);
++		if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)) {
++			dprintk("NFSD: setclientid: string in use by client"
++				" at %pI4\n", &conf->cl_addr);
+ 			goto out;
+ 		}
+ 	}

commit 5cb031b0afddad73ea4191c9f0b76d20ca447dc0
+Author: J. Bruce Fields 
+Date:   Sat Mar 14 16:38:41 2009 -0400
+
+    nfsd4: remove redundant check from nfsd4_open
+    
+    Note that we already checked for this invalid case at the top of this
+    function.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index 36d74cda87a8..f156b85b4129 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -206,10 +206,6 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 
+ 	switch (open->op_claim_type) {
+ 		case NFS4_OPEN_CLAIM_DELEGATE_CUR:
+-			status = nfserr_inval;
+-			if (open->op_create)
+-				goto out;
+-			/* fall through */
+ 		case NFS4_OPEN_CLAIM_NULL:
+ 			/*
+ 			 * (1) set CURRENT_FH to the file being opened,

commit 05f4f678b0511a24795a017b5332455077be3b1c
+Author: J. Bruce Fields 
+Date:   Fri Mar 13 16:02:59 2009 -0400
+
+    nfsd4: don't do lookup within readdir in recovery code
+    
+    The main nfsd code was recently modified to no longer do lookups from
+    withing the readdir callback, to avoid locking problems on certain
+    filesystems.
+    
+    This (rather hacky, and overdue for replacement) NFSv4 recovery code has
+    the same problem.  Fix it to build up a list of names (instead of
+    dentries) and do the lookups afterwards.
+    
+    Reported symptoms were a deadlock in the xfs code (called from
+    nfsd4_recdir_load), with /var/lib/nfs on xfs.
+    
+    Signed-off-by: J. Bruce Fields 
+    Reported-by: David Warren 
+
+diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
+index 74f7b67567fd..b11cf8d34280 100644
+--- a/fs/nfsd/nfs4recover.c
++++ b/fs/nfsd/nfs4recover.c
+@@ -182,36 +182,26 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
+ 
+ typedef int (recdir_func)(struct dentry *, struct dentry *);
+ 
+-struct dentry_list {
+-	struct dentry *dentry;
++struct name_list {
++	char name[HEXDIR_LEN];
+ 	struct list_head list;
+ };
+ 
+-struct dentry_list_arg {
+-	struct list_head dentries;
+-	struct dentry *parent;
+-};
+-
+ static int
+-nfsd4_build_dentrylist(void *arg, const char *name, int namlen,
++nfsd4_build_namelist(void *arg, const char *name, int namlen,
+ 		loff_t offset, u64 ino, unsigned int d_type)
+ {
+-	struct dentry_list_arg *dla = arg;
+-	struct list_head *dentries = &dla->dentries;
+-	struct dentry *parent = dla->parent;
+-	struct dentry *dentry;
+-	struct dentry_list *child;
++	struct list_head *names = arg;
++	struct name_list *entry;
+ 
+-	if (name && isdotent(name, namlen))
++	if (namlen != HEXDIR_LEN - 1)
+ 		return 0;
+-	dentry = lookup_one_len(name, parent, namlen);
+-	if (IS_ERR(dentry))
+-		return PTR_ERR(dentry);
+-	child = kmalloc(sizeof(*child), GFP_KERNEL);
+-	if (child == NULL)
++	entry = kmalloc(sizeof(struct name_list), GFP_KERNEL);
++	if (entry == NULL)
+ 		return -ENOMEM;
+-	child->dentry = dentry;
+-	list_add(&child->list, dentries);
++	memcpy(entry->name, name, HEXDIR_LEN - 1);
++	entry->name[HEXDIR_LEN - 1] = '\0';
++	list_add(&entry->list, names);
+ 	return 0;
+ }
+ 
+@@ -220,11 +210,9 @@ nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
+ {
+ 	const struct cred *original_cred;
+ 	struct file *filp;
+-	struct dentry_list_arg dla = {
+-		.parent = dir,
+-	};
+-	struct list_head *dentries = &dla.dentries;
+-	struct dentry_list *child;
++	LIST_HEAD(names);
++	struct name_list *entry;
++	struct dentry *dentry;
+ 	int status;
+ 
+ 	if (!rec_dir_init)
+@@ -233,31 +221,34 @@ nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
+ 	status = nfs4_save_creds(&original_cred);
+ 	if (status < 0)
+ 		return status;
+-	INIT_LIST_HEAD(dentries);
+ 
+ 	filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY,
+ 			   current_cred());
+ 	status = PTR_ERR(filp);
+ 	if (IS_ERR(filp))
+ 		goto out;
+-	INIT_LIST_HEAD(dentries);
+-	status = vfs_readdir(filp, nfsd4_build_dentrylist, &dla);
++	status = vfs_readdir(filp, nfsd4_build_namelist, &names);
+ 	fput(filp);
+-	while (!list_empty(dentries)) {
+-		child = list_entry(dentries->next, struct dentry_list, list);
+-		status = f(dir, child->dentry);
++	while (!list_empty(&names)) {
++		entry = list_entry(names.next, struct name_list, list);
++
++		dentry = lookup_one_len(entry->name, dir, HEXDIR_LEN-1);
++		if (IS_ERR(dentry)) {
++			status = PTR_ERR(dentry);
++			goto out;
++		}
++		status = f(dir, dentry);
++		dput(dentry);
+ 		if (status)
+ 			goto out;
+-		list_del(&child->list);
+-		dput(child->dentry);
+-		kfree(child);
++		list_del(&entry->list);
++		kfree(entry);
+ 	}
+ out:
+-	while (!list_empty(dentries)) {
+-		child = list_entry(dentries->next, struct dentry_list, list);
+-		list_del(&child->list);
+-		dput(child->dentry);
+-		kfree(child);
++	while (!list_empty(&names)) {
++		entry = list_entry(names.next, struct name_list, list);
++		list_del(&entry->list);
++		kfree(entry);
+ 	}
+ 	nfs4_reset_creds(original_cred);
+ 	return status;

commit a1c8c4d1ff54c6c86930ee3c4c73c69eeb9ede61
+Author: J. Bruce Fields 
+Date:   Mon Mar 9 12:17:29 2009 -0400
+
+    nfsd4: support putpubfh operation
+    
+    Currently putpubfh returns NFSERR_OPNOTSUPP, which isn't actually
+    allowed for v4.  The right error is probably NFSERR_NOTSUPP.
+    
+    But let's just implement it; though rarely seen, it can be used by
+    Solaris (with a special mount option), is mandated by the rfc, and is
+    trivial for us to support.
+    
+    Thanks to Yang Hongyang for pointing out the original problem, and to
+    Mike Eisler, Tom Talpey, Trond Myklebust, and Dave Noveck for further
+    argument....
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index 283d77a47120..36d74cda87a8 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -1045,7 +1045,7 @@ static struct nfsd4_operation nfsd4_ops[OP_RELEASE_LOCKOWNER+1] = {
+ 		.op_name = "OP_PUTFH",
+ 	},
+ 	[OP_PUTPUBFH] = {
+-		/* unsupported, just for future reference: */
++		.op_func = (nfsd4op_func)nfsd4_putrootfh,
+ 		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
+ 		.op_name = "OP_PUTPUBFH",
+ 	},
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index aaf5f234df25..76a0b2a8d69b 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -1031,7 +1031,7 @@ static nfsd4_dec nfsd4_dec_ops[] = {
+ 	[OP_OPEN_CONFIRM]	= (nfsd4_dec)nfsd4_decode_open_confirm,
+ 	[OP_OPEN_DOWNGRADE]	= (nfsd4_dec)nfsd4_decode_open_downgrade,
+ 	[OP_PUTFH]		= (nfsd4_dec)nfsd4_decode_putfh,
+-	[OP_PUTPUBFH]		= (nfsd4_dec)nfsd4_decode_notsupp,
++	[OP_PUTPUBFH]		= (nfsd4_dec)nfsd4_decode_noop,
+ 	[OP_PUTROOTFH]		= (nfsd4_dec)nfsd4_decode_noop,
+ 	[OP_READ]		= (nfsd4_dec)nfsd4_decode_read,
+ 	[OP_READDIR]		= (nfsd4_dec)nfsd4_decode_readdir,

commit a601caeda21c0e94c153dbd146ec0899cc5f324f
+Author: J. Bruce Fields 
+Date:   Sun Feb 22 16:43:45 2009 -0800
+
+    nfsd4: move rpc_client setup to a separate function
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 8d55f5047503..290289bd44f7 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -361,9 +361,8 @@ static struct rpc_program cb_program = {
+ /* Reference counting, callback cleanup, etc., all look racy as heck.
+  * And why is cb_set an atomic? */
+ 
+-static int do_probe_callback(void *data)
++static struct rpc_clnt *setup_callback_client(struct nfs4_client *clp)
+ {
+-	struct nfs4_client *clp = data;
+ 	struct sockaddr_in	addr;
+ 	struct nfs4_callback    *cb = &clp->cl_callback;
+ 	struct rpc_timeout	timeparms = {
+@@ -384,15 +383,10 @@ static int do_probe_callback(void *data)
+ 		.flags		= (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET),
+ 		.client_name    = clp->cl_principal,
+ 	};
+-	struct rpc_message msg = {
+-		.rpc_proc       = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
+-		.rpc_argp       = clp,
+-	};
+ 	struct rpc_clnt *client;
+-	int status = -EINVAL;
+ 
+ 	if (!clp->cl_principal && (clp->cl_flavor >= RPC_AUTH_GSS_KRB5))
+-		goto out_err;
++		return ERR_PTR(-EINVAL);
+ 
+ 	/* Initialize address */
+ 	memset(&addr, 0, sizeof(addr));
+@@ -402,6 +396,25 @@ static int do_probe_callback(void *data)
+ 
+ 	/* Create RPC client */
+ 	client = rpc_create(&args);
++	if (IS_ERR(client))
++		dprintk("NFSD: couldn't create callback client: %ld\n",
++			PTR_ERR(client));
++	return client;
++
++}
++
++static int do_probe_callback(void *data)
++{
++	struct nfs4_client *clp = data;
++	struct nfs4_callback    *cb = &clp->cl_callback;
++	struct rpc_message msg = {
++		.rpc_proc       = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
++		.rpc_argp       = clp,
++	};
++	struct rpc_clnt *client;
++	int status;
++
++	client = setup_callback_client(clp);
+ 	if (IS_ERR(client)) {
+ 		status = PTR_ERR(client);
+ 		dprintk("NFSD: couldn't create callback client: %d\n",

commit 418cd20aa19b54554cab383e2fd0d1cb8c4732ee
+Author: J. Bruce Fields 
+Date:   Sun Feb 22 15:52:13 2009 -0800
+
+    nfsd4: fix do_probe_callback errors
+    
+    The errors returned aren't used.  Just return 0 and make them available
+    to a dprintk().  Also, consistently use -ERRNO errors instead of nfs
+    errors.
+    
+    Signed-off-by: J. Bruce Fields 
+    Reviewed-by: Benny Halevy 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 5dcd38e5f138..8d55f5047503 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -389,12 +389,10 @@ static int do_probe_callback(void *data)
+ 		.rpc_argp       = clp,
+ 	};
+ 	struct rpc_clnt *client;
+-	int status;
++	int status = -EINVAL;
+ 
+-	if (!clp->cl_principal && (clp->cl_flavor >= RPC_AUTH_GSS_KRB5)) {
+-		status = nfserr_cb_path_down;
++	if (!clp->cl_principal && (clp->cl_flavor >= RPC_AUTH_GSS_KRB5))
+ 		goto out_err;
+-	}
+ 
+ 	/* Initialize address */
+ 	memset(&addr, 0, sizeof(addr));
+@@ -405,8 +403,9 @@ static int do_probe_callback(void *data)
+ 	/* Create RPC client */
+ 	client = rpc_create(&args);
+ 	if (IS_ERR(client)) {
+-		dprintk("NFSD: couldn't create callback client\n");
+ 		status = PTR_ERR(client);
++		dprintk("NFSD: couldn't create callback client: %d\n",
++								status);
+ 		goto out_err;
+ 	}
+ 
+@@ -422,10 +421,10 @@ static int do_probe_callback(void *data)
+ out_release_client:
+ 	rpc_shutdown_client(client);
+ out_err:
+-	dprintk("NFSD: warning: no callback path to client %.*s\n",
+-		(int)clp->cl_name.len, clp->cl_name.data);
++	dprintk("NFSD: warning: no callback path to client %.*s: error %d\n",
++		(int)clp->cl_name.len, clp->cl_name.data, status);
+ 	put_nfs4_client(clp);
+-	return status;
++	return 0;
+ }
+ 
+ /*

commit 8b671b80707e4fc76adfe4387df07b3be1007c1e
+Author: J. Bruce Fields 
+Date:   Sun Feb 22 14:51:34 2009 -0800
+
+    nfsd4: remove use of mutex for file_hashtable
+    
+    As part of reducing the scope of the client_mutex, and in order to
+    remove the need for mutexes from the callback code (so that callbacks
+    can be done as asynchronous rpc calls), move manipulations of the
+    file_hashtable under the recall_lock.
+    
+    Update the relevant comments while we're here.
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: Alexandros Batsakis 
+    Reviewed-by: Benny Halevy 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 3fd7136321ca..5dcd38e5f138 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -491,8 +491,6 @@ nfsd4_cb_recall(struct nfs4_delegation *dp)
+ 	 * or deleg_return.
+ 	 */
+ 	put_nfs4_client(clp);
+-	nfs4_lock_state();
+ 	nfs4_put_delegation(dp);
+-	nfs4_unlock_state();
+ 	return;
+ }
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 89e575e7daea..54651aa45790 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -78,14 +78,18 @@ static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, state
+ static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
+ static void nfs4_set_recdir(char *recdir);
+ 
+-/* Locking:
+- *
+- * client_mutex:
+- * 	protects clientid_hashtbl[], clientstr_hashtbl[],
+- * 	unconfstr_hashtbl[], uncofid_hashtbl[].
+- */
++/* Locking: */
++
++/* Currently used for almost all code touching nfsv4 state: */
+ static DEFINE_MUTEX(client_mutex);
+ 
++/*
++ * Currently used for the del_recall_lru and file hash table.  In an
++ * effort to decrease the scope of the client_mutex, this spinlock may
++ * eventually cover more:
++ */
++static DEFINE_SPINLOCK(recall_lock);
++
+ static struct kmem_cache *stateowner_slab = NULL;
+ static struct kmem_cache *file_slab = NULL;
+ static struct kmem_cache *stateid_slab = NULL;
+@@ -116,33 +120,23 @@ opaque_hashval(const void *ptr, int nbytes)
+ 	return x;
+ }
+ 
+-/*
+- * Delegation state
+- */
+-
+-/* recall_lock protects the del_recall_lru */
+-static DEFINE_SPINLOCK(recall_lock);
+ static struct list_head del_recall_lru;
+ 
+-static void
+-free_nfs4_file(struct kref *kref)
+-{
+-	struct nfs4_file *fp = container_of(kref, struct nfs4_file, fi_ref);
+-	list_del(&fp->fi_hash);
+-	iput(fp->fi_inode);
+-	kmem_cache_free(file_slab, fp);
+-}
+-
+ static inline void
+ put_nfs4_file(struct nfs4_file *fi)
+ {
+-	kref_put(&fi->fi_ref, free_nfs4_file);
++	if (atomic_dec_and_lock(&fi->fi_ref, &recall_lock)) {
++		list_del(&fi->fi_hash);
++		spin_unlock(&recall_lock);
++		iput(fi->fi_inode);
++		kmem_cache_free(file_slab, fi);
++	}
+ }
+ 
+ static inline void
+ get_nfs4_file(struct nfs4_file *fi)
+ {
+-	kref_get(&fi->fi_ref);
++	atomic_inc(&fi->fi_ref);
+ }
+ 
+ static int num_delegations;
+@@ -1000,11 +994,13 @@ alloc_init_file(struct inode *ino)
+ 
+ 	fp = kmem_cache_alloc(file_slab, GFP_KERNEL);
+ 	if (fp) {
+-		kref_init(&fp->fi_ref);
++		atomic_set(&fp->fi_ref, 1);
+ 		INIT_LIST_HEAD(&fp->fi_hash);
+ 		INIT_LIST_HEAD(&fp->fi_stateids);
+ 		INIT_LIST_HEAD(&fp->fi_delegations);
++		spin_lock(&recall_lock);
+ 		list_add(&fp->fi_hash, &file_hashtbl[hashval]);
++		spin_unlock(&recall_lock);
+ 		fp->fi_inode = igrab(ino);
+ 		fp->fi_id = current_fileid++;
+ 		fp->fi_had_conflict = false;
+@@ -1177,12 +1173,15 @@ find_file(struct inode *ino)
+ 	unsigned int hashval = file_hashval(ino);
+ 	struct nfs4_file *fp;
+ 
++	spin_lock(&recall_lock);
+ 	list_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) {
+ 		if (fp->fi_inode == ino) {
+ 			get_nfs4_file(fp);
++			spin_unlock(&recall_lock);
+ 			return fp;
+ 		}
+ 	}
++	spin_unlock(&recall_lock);
+ 	return NULL;
+ }
+ 
+diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
+index 503b6bb53a56..a6e4a00fa392 100644
+--- a/include/linux/nfsd/state.h
++++ b/include/linux/nfsd/state.h
+@@ -214,7 +214,7 @@ struct nfs4_stateowner {
+ *      share_acces, share_deny on the file.
+ */
+ struct nfs4_file {
+-	struct kref		fi_ref;
++	atomic_t		fi_ref;
+ 	struct list_head        fi_hash;    /* hash by "struct inode *" */
+ 	struct list_head        fi_stateids;
+ 	struct list_head	fi_delegations;

commit d7fdcfe0aaaf6dffca6fa857bab374182fe7ca8b
+Author: J. Bruce Fields 
+Date:   Sat Feb 21 15:39:54 2009 -0800
+
+    nfsd4: put_nfs4_client does not require state lock
+    
+    Since free_client() is guaranteed to only be called once, and to only
+    touch the client structure itself (not any common data structures), it
+    has no need for the state lock.
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: Alexandros Batsakis 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 3ddc9fb2e358..3fd7136321ca 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -490,8 +490,8 @@ nfsd4_cb_recall(struct nfs4_delegation *dp)
+ 	 * Success or failure, now we're either waiting for lease expiration
+ 	 * or deleg_return.
+ 	 */
+-	nfs4_lock_state();
+ 	put_nfs4_client(clp);
++	nfs4_lock_state();
+ 	nfs4_put_delegation(dp);
+ 	nfs4_unlock_state();
+ 	return;

commit 18f82731b7784ba81ee9b1ed6a8179b577fa898b
+Author: J. Bruce Fields 
+Date:   Sat Feb 21 15:23:01 2009 -0800
+
+    nfsd4: rename io_during_grace_disallowed
+    
+    Use a slightly clearer, more concise name.  Also removed unused
+    argument.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 5957f7766bdc..89e575e7daea 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2019,7 +2019,7 @@ check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
+  * that are not able to provide mandatory locking.
+  */
+ static inline int
+-io_during_grace_disallowed(struct inode *inode, int flags)
++grace_disallows_io(struct inode *inode)
+ {
+ 	return locks_in_grace() && mandatory_lock(inode);
+ }
+@@ -2063,7 +2063,7 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
+ 	if (filpp)
+ 		*filpp = NULL;
+ 
+-	if (io_during_grace_disallowed(ino, flags))
++	if (grace_disallows_io(ino))
+ 		return nfserr_grace;
+ 
+ 	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))

commit 6150ef0dc7f734366d297e2eb5697ae458a1ea19
+Author: J. Bruce Fields 
+Date:   Sat Feb 21 13:36:16 2009 -0800
+
+    nfsd4: remove unused CHECK_FH flag
+    
+    All users now pass this, so it's meaningless.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index af66073ed423..77f584f69dfe 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -519,7 +519,7 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	/* check stateid */
+ 	if ((status = nfs4_preprocess_stateid_op(&cstate->current_fh,
+ 				&read->rd_stateid,
+-				CHECK_FH | RD_STATE, &read->rd_filp))) {
++				RD_STATE, &read->rd_filp))) {
+ 		dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
+ 		goto out;
+ 	}
+@@ -651,7 +651,7 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
+ 		nfs4_lock_state();
+ 		status = nfs4_preprocess_stateid_op(&cstate->current_fh,
+-			&setattr->sa_stateid, CHECK_FH | WR_STATE, NULL);
++			&setattr->sa_stateid, WR_STATE, NULL);
+ 		nfs4_unlock_state();
+ 		if (status) {
+ 			dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");
+@@ -690,7 +690,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 
+ 	nfs4_lock_state();
+ 	status = nfs4_preprocess_stateid_op(&cstate->current_fh, stateid,
+-					CHECK_FH | WR_STATE, &filp);
++					WR_STATE, &filp);
+ 	if (filp)
+ 		get_file(filp);
+ 	nfs4_unlock_state();
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 6ae28e606afc..5957f7766bdc 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2091,7 +2091,7 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
+ 		stp = find_stateid(stateid, flags);
+ 		if (!stp)
+ 			goto out;
+-		if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp))
++		if (nfs4_check_fh(current_fh, stp))
+ 			goto out;
+ 		if (!stp->st_stateowner->so_confirmed)
+ 			goto out;
+diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
+index c9311a1e2e1a..503b6bb53a56 100644
+--- a/include/linux/nfsd/state.h
++++ b/include/linux/nfsd/state.h
+@@ -256,7 +256,6 @@ struct nfs4_stateid {
+ };
+ 
+ /* flags for preprocess_seqid_op() */
+-#define CHECK_FH                0x00000001
+ #define CONFIRM                 0x00000002
+ #define OPEN_STATE              0x00000004
+ #define LOCK_STATE              0x00000008

commit 7e0f7cf582abd6c85232331dfe726a4e4b0fd98e
+Author: J. Bruce Fields 
+Date:   Sat Feb 21 13:32:28 2009 -0800
+
+    nfsd4: fail when delegreturn gets a non-delegation stateid
+    
+    Previous cleanup reveals an obvious (though harmless) bug: when
+    delegreturn gets a stateid that isn't for a delegation, it should return
+    an error rather than doing nothing.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 3570a0d1133f..6ae28e606afc 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2418,10 +2418,9 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	status = nfserr_stale_stateid;
+ 	if (STALE_STATEID(stateid))
+ 		goto out;
+-	status = nfs_ok;
++	status = nfserr_bad_stateid;
+ 	if (!is_delegation_stateid(stateid))
+ 		goto out;
+-	status = nfserr_bad_stateid;
+ 	dp = find_delegation_stateid(inode, stateid);
+ 	if (!dp)
+ 		goto out;

commit 203a8c8e66278a5936a230edaac29017e50c88fb
+Author: J. Bruce Fields 
+Date:   Sat Feb 21 13:29:14 2009 -0800
+
+    nfsd4: separate delegreturn case from preprocess_stateid_op
+    
+    Delegreturn is enough a special case for preprocess_stateid_op to
+    warrant just open-coding it in delegreturn.
+    
+    There should be no change in behavior here; we're just reshuffling code.
+    
+    Thanks to Yang Hongyang for catching a critical typo.
+    
+    Reviewed-by: Yang Hongyang 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index d5555850cb64..3570a0d1133f 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2000,10 +2000,7 @@ __be32 nfs4_check_openmode(struct nfs4_stateid *stp, int flags)
+ static inline __be32
+ check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
+ {
+-	/* Trying to call delegreturn with a special stateid? Yuch: */
+-	if (!(flags & (RD_STATE | WR_STATE)))
+-		return nfserr_bad_stateid;
+-	else if (ONE_STATEID(stateid) && (flags & RD_STATE))
++	if (ONE_STATEID(stateid) && (flags & RD_STATE))
+ 		return nfs_ok;
+ 	else if (locks_in_grace()) {
+ 		/* Answer in remaining cases depends on existance of
+@@ -2024,8 +2021,7 @@ check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
+ static inline int
+ io_during_grace_disallowed(struct inode *inode, int flags)
+ {
+-	return locks_in_grace() && (flags & (RD_STATE | WR_STATE))
+-		&& mandatory_lock(inode);
++	return locks_in_grace() && mandatory_lock(inode);
+ }
+ 
+ static int check_stateid_generation(stateid_t *in, stateid_t *ref)
+@@ -2089,8 +2085,6 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
+ 		if (status)
+ 			goto out;
+ 		renew_client(dp->dl_client);
+-		if (flags & DELEG_RET)
+-			unhash_delegation(dp);
+ 		if (filpp)
+ 			*filpp = dp->dl_vfs_file;
+ 	} else { /* open or lock stateid */
+@@ -2408,16 +2402,38 @@ __be32
+ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 		  struct nfsd4_delegreturn *dr)
+ {
++	struct nfs4_delegation *dp;
++	stateid_t *stateid = &dr->dr_stateid;
++	struct inode *inode;
+ 	__be32 status;
+ 
+ 	if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0)))
+-		goto out;
++		return status;
++	inode = cstate->current_fh.fh_dentry->d_inode;
+ 
+ 	nfs4_lock_state();
+-	status = nfs4_preprocess_stateid_op(&cstate->current_fh,
+-					    &dr->dr_stateid, DELEG_RET, NULL);
+-	nfs4_unlock_state();
++	status = nfserr_bad_stateid;
++	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
++		goto out;
++	status = nfserr_stale_stateid;
++	if (STALE_STATEID(stateid))
++		goto out;
++	status = nfs_ok;
++	if (!is_delegation_stateid(stateid))
++		goto out;
++	status = nfserr_bad_stateid;
++	dp = find_delegation_stateid(inode, stateid);
++	if (!dp)
++		goto out;
++	status = check_stateid_generation(stateid, &dp->dl_stateid);
++	if (status)
++		goto out;
++	renew_client(dp->dl_client);
++
++	unhash_delegation(dp);
+ out:
++	nfs4_unlock_state();
++
+ 	return status;
+ }
+ 
+diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
+index 1130d534bb63..c9311a1e2e1a 100644
+--- a/include/linux/nfsd/state.h
++++ b/include/linux/nfsd/state.h
+@@ -263,7 +263,6 @@ struct nfs4_stateid {
+ #define RD_STATE	        0x00000010
+ #define WR_STATE	        0x00000020
+ #define CLOSE_STATE             0x00000040
+-#define DELEG_RET               0x00000080
+ 
+ #define seqid_mutating_err(err)                       \
+ 	(((err) != nfserr_stale_clientid) &&    \

commit 3e633079e377d2b527a8390f63ceb887b5cabfbf
+Author: J. Bruce Fields 
+Date:   Sat Feb 21 13:17:19 2009 -0800
+
+    nfsd4: add a helper function to decide if stateid is delegation
+    
+    Make this check self-documenting.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 909a7a493688..d5555850cb64 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2048,6 +2048,11 @@ static int check_stateid_generation(stateid_t *in, stateid_t *ref)
+ 	return nfs_ok;
+ }
+ 
++static int is_delegation_stateid(stateid_t *stateid)
++{
++	return stateid->si_fileid == 0;
++}
++
+ /*
+ * Checks for stateid operations
+ */
+@@ -2073,7 +2078,7 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
+ 		goto out;
+ 
+ 	status = nfserr_bad_stateid;
+-	if (!stateid->si_fileid) { /* delegation stateid */
++	if (is_delegation_stateid(stateid)) {
+ 		dp = find_delegation_stateid(ino, stateid);
+ 		if (!dp)
+ 			goto out;

commit 819a8f539acf7838d62fec20e88401ff53303cd1
+Author: J. Bruce Fields 
+Date:   Sat Feb 21 12:13:24 2009 -0800
+
+    nfsd4: remove some dprintk's
+    
+    I can't recall ever seeing these printk's used to debug a problem.  I'll
+    happily put them back if we see a case where they'd be useful.  (Though
+    if we do that the find_XXX() errors would probably be better
+    reported in find_XXX() functions themselves.)
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 099938ebc9d3..909a7a493688 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2059,9 +2059,6 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
+ 	struct inode *ino = current_fh->fh_dentry->d_inode;
+ 	__be32 status;
+ 
+-	dprintk("NFSD: preprocess_stateid_op: stateid = (%08x/%08x/%08x/%08x)\n",
+-		stateid->si_boot, stateid->si_stateownerid, 
+-		stateid->si_fileid, stateid->si_generation); 
+ 	if (filpp)
+ 		*filpp = NULL;
+ 
+@@ -2078,10 +2075,8 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
+ 	status = nfserr_bad_stateid;
+ 	if (!stateid->si_fileid) { /* delegation stateid */
+ 		dp = find_delegation_stateid(ino, stateid);
+-		if (!dp) {
+-			dprintk("NFSD: delegation stateid not found\n");
++		if (!dp)
+ 			goto out;
+-		}
+ 		status = check_stateid_generation(stateid, &dp->dl_stateid);
+ 		if (status)
+ 			goto out;
+@@ -2095,10 +2090,8 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
+ 			*filpp = dp->dl_vfs_file;
+ 	} else { /* open or lock stateid */
+ 		stp = find_stateid(stateid, flags);
+-		if (!stp) {
+-			dprintk("NFSD: open or lock stateid not found\n");
++		if (!stp)
+ 			goto out;
+-		}
+ 		if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp))
+ 			goto out;
+ 		if (!stp->st_stateowner->so_confirmed)

commit fd03b09906c32aea7b47f1275c9cd6034141159d
+Author: J. Bruce Fields 
+Date:   Sat Feb 21 11:27:30 2009 -0800
+
+    nfsd4: remove unneeded local variable
+    
+    We no longer need stidp.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 16fcb656f47f..099938ebc9d3 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2056,7 +2056,6 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
+ {
+ 	struct nfs4_stateid *stp = NULL;
+ 	struct nfs4_delegation *dp = NULL;
+-	stateid_t *stidp;
+ 	struct inode *ino = current_fh->fh_dentry->d_inode;
+ 	__be32 status;
+ 
+@@ -2083,8 +2082,7 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
+ 			dprintk("NFSD: delegation stateid not found\n");
+ 			goto out;
+ 		}
+-		stidp = &dp->dl_stateid;
+-		status = check_stateid_generation(stateid, stidp);
++		status = check_stateid_generation(stateid, &dp->dl_stateid);
+ 		if (status)
+ 			goto out;
+ 		status = nfs4_check_delegmode(dp, flags);
+@@ -2105,8 +2103,7 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
+ 			goto out;
+ 		if (!stp->st_stateowner->so_confirmed)
+ 			goto out;
+-		stidp = &stp->st_stateid;
+-		status = check_stateid_generation(stateid, stidp);
++		status = check_stateid_generation(stateid, &stp->st_stateid);
+ 		if (status)
+ 			goto out;
+ 		status = nfs4_check_openmode(stp, flags);

commit dc9bf700ed2fc3eab50f31000b13fda781e7c9f1
+Author: J. Bruce Fields 
+Date:   Sat Feb 21 11:14:43 2009 -0800
+
+    nfsd4: remove redundant "if" in nfs4_preprocess_stateid_op
+    
+    Note that we exit this first big "if" with stp == NULL if and only if we
+    took the first branch; therefore, the second "if" is redundant, and we
+    can just combine the two, simplifying the logic.
+    
+    Reviewed-by: Yang Hongyang 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index d6ca2be306dc..16fcb656f47f 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2087,6 +2087,14 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
+ 		status = check_stateid_generation(stateid, stidp);
+ 		if (status)
+ 			goto out;
++		status = nfs4_check_delegmode(dp, flags);
++		if (status)
++			goto out;
++		renew_client(dp->dl_client);
++		if (flags & DELEG_RET)
++			unhash_delegation(dp);
++		if (filpp)
++			*filpp = dp->dl_vfs_file;
+ 	} else { /* open or lock stateid */
+ 		stp = find_stateid(stateid, flags);
+ 		if (!stp) {
+@@ -2101,23 +2109,12 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
+ 		status = check_stateid_generation(stateid, stidp);
+ 		if (status)
+ 			goto out;
+-	}
+-	if (stp) {
+ 		status = nfs4_check_openmode(stp, flags);
+ 		if (status)
+ 			goto out;
+ 		renew_client(stp->st_stateowner->so_client);
+ 		if (filpp)
+ 			*filpp = stp->st_vfs_file;
+-	} else {
+-		status = nfs4_check_delegmode(dp, flags);
+-		if (status)
+-			goto out;
+-		renew_client(dp->dl_client);
+-		if (flags & DELEG_RET)
+-			unhash_delegation(dp);
+-		if (filpp)
+-			*filpp = dp->dl_vfs_file;
+ 	}
+ 	status = nfs_ok;
+ out:

commit 0c2a498fa6d33d8ca9c8a0c29039c41e1734cb9e
+Author: J. Bruce Fields 
+Date:   Sat Feb 21 11:11:50 2009 -0800
+
+    nfsd4: move check_stateid_generation check
+    
+    No change in behavior.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index b7e2f251ea95..d6ca2be306dc 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2084,6 +2084,9 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
+ 			goto out;
+ 		}
+ 		stidp = &dp->dl_stateid;
++		status = check_stateid_generation(stateid, stidp);
++		if (status)
++			goto out;
+ 	} else { /* open or lock stateid */
+ 		stp = find_stateid(stateid, flags);
+ 		if (!stp) {
+@@ -2095,10 +2098,10 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
+ 		if (!stp->st_stateowner->so_confirmed)
+ 			goto out;
+ 		stidp = &stp->st_stateid;
++		status = check_stateid_generation(stateid, stidp);
++		if (status)
++			goto out;
+ 	}
+-	status = check_stateid_generation(stateid, stidp);
+-	if (status)
+-		goto out;
+ 	if (stp) {
+ 		status = nfs4_check_openmode(stp, flags);
+ 		if (status)

commit a4455be0850009f5da9a3b82523079922cd4b26e
+Author: J. Bruce Fields 
+Date:   Sat Feb 21 10:40:22 2009 -0800
+
+    nfsd4: trivial preprocess_stateid_op cleanup
+    
+    Remove a couple redundant comments, adjust style; no change in behavior.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 7f616e928a57..b7e2f251ea95 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2072,21 +2072,21 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
+ 	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
+ 		return check_special_stateids(current_fh, stateid, flags);
+ 
+-	/* STALE STATEID */
+ 	status = nfserr_stale_stateid;
+ 	if (STALE_STATEID(stateid)) 
+ 		goto out;
+ 
+-	/* BAD STATEID */
+ 	status = nfserr_bad_stateid;
+ 	if (!stateid->si_fileid) { /* delegation stateid */
+-		if(!(dp = find_delegation_stateid(ino, stateid))) {
++		dp = find_delegation_stateid(ino, stateid);
++		if (!dp) {
+ 			dprintk("NFSD: delegation stateid not found\n");
+ 			goto out;
+ 		}
+ 		stidp = &dp->dl_stateid;
+ 	} else { /* open or lock stateid */
+-		if (!(stp = find_stateid(stateid, flags))) {
++		stp = find_stateid(stateid, flags);
++		if (!stp) {
+ 			dprintk("NFSD: open or lock stateid not found\n");
+ 			goto out;
+ 		}
+@@ -2100,13 +2100,15 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
+ 	if (status)
+ 		goto out;
+ 	if (stp) {
+-		if ((status = nfs4_check_openmode(stp,flags)))
++		status = nfs4_check_openmode(stp, flags);
++		if (status)
+ 			goto out;
+ 		renew_client(stp->st_stateowner->so_client);
+ 		if (filpp)
+ 			*filpp = stp->st_vfs_file;
+ 	} else {
+-		if ((status = nfs4_check_delegmode(dp, flags)))
++		status = nfs4_check_delegmode(dp, flags);
++		if (status)
+ 			goto out;
+ 		renew_client(dp->dl_client);
+ 		if (flags & DELEG_RET)

commit 6c02eaa1d1e53b9b2cc27d0c6fff3e57da4b611f
+Author: J. Bruce Fields 
+Date:   Mon Feb 2 17:30:51 2009 -0500
+
+    nfsd4: use helper for copying delegation filehandle
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index c464181b5994..c6804db33c17 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -218,7 +218,7 @@ static int
+ encode_cb_recall(struct xdr_stream *xdr, struct nfs4_cb_recall *cb_rec)
+ {
+ 	__be32 *p;
+-	int len = cb_rec->cbr_fhlen;
++	int len = cb_rec->cbr_fh.fh_size;
+ 
+ 	RESERVE_SPACE(12+sizeof(cb_rec->cbr_stateid) + len);
+ 	WRITE32(OP_CB_RECALL);
+@@ -226,7 +226,7 @@ encode_cb_recall(struct xdr_stream *xdr, struct nfs4_cb_recall *cb_rec)
+ 	WRITEMEM(&cb_rec->cbr_stateid.si_opaque, sizeof(stateid_opaque_t));
+ 	WRITE32(cb_rec->cbr_trunc);
+ 	WRITE32(len);
+-	WRITEMEM(cb_rec->cbr_fhval, len);
++	WRITEMEM(&cb_rec->cbr_fh.fh_base, len);
+ 	return 0;
+ }
+ 
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 41a3590ef2cc..7f616e928a57 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -215,9 +215,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
+ 	dp->dl_stateid.si_stateownerid = current_delegid++;
+ 	dp->dl_stateid.si_fileid = 0;
+ 	dp->dl_stateid.si_generation = 0;
+-	dp->dl_fhlen = current_fh->fh_handle.fh_size;
+-	memcpy(dp->dl_fhval, ¤t_fh->fh_handle.fh_base,
+-		        current_fh->fh_handle.fh_size);
++	fh_copy_shallow(&dp->dl_fh, ¤t_fh->fh_handle);
+ 	dp->dl_time = 0;
+ 	atomic_set(&dp->dl_count, 1);
+ 	list_add(&dp->dl_perfile, &fp->fi_delegations);
+diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
+index b65b2a6274b0..1130d534bb63 100644
+--- a/include/linux/nfsd/state.h
++++ b/include/linux/nfsd/state.h
+@@ -66,8 +66,7 @@ struct nfs4_cb_recall {
+ 	u32			cbr_ident;
+ 	int			cbr_trunc;
+ 	stateid_t		cbr_stateid;
+-	u32			cbr_fhlen;
+-	char			cbr_fhval[NFS4_FHSIZE];
++	struct knfsd_fh		cbr_fh;
+ 	struct nfs4_delegation	*cbr_dp;
+ };
+ 
+@@ -86,8 +85,7 @@ struct nfs4_delegation {
+ };
+ 
+ #define dl_stateid      dl_recall.cbr_stateid
+-#define dl_fhlen        dl_recall.cbr_fhlen
+-#define dl_fhval        dl_recall.cbr_fhval
++#define dl_fh           dl_recall.cbr_fh
+ 
+ /* client delegation callback info */
+ struct nfs4_callback {

commit a4773c08f2872626cb923433284488fbe8acb0ae
+Author: J. Bruce Fields 
+Date:   Mon Feb 2 17:23:10 2009 -0500
+
+    nfsd4: use helper for copying filehandles for replay
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index 326506272258..af66073ed423 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -123,10 +123,8 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
+ 	fh_dup2(current_fh, &resfh);
+ 
+ 	/* set reply cache */
+-	open->op_stateowner->so_replay.rp_openfh_len = resfh.fh_handle.fh_size;
+-	memcpy(open->op_stateowner->so_replay.rp_openfh,
+-			&resfh.fh_handle.fh_base, resfh.fh_handle.fh_size);
+-
++	fh_copy_shallow(&open->op_stateowner->so_replay.rp_openfh,
++			&resfh.fh_handle);
+ 	if (!created)
+ 		status = do_open_permission(rqstp, current_fh, open,
+ 					    NFSD_MAY_NOP);
+@@ -152,10 +150,8 @@ do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_
+ 	memset(&open->op_cinfo, 0, sizeof(struct nfsd4_change_info));
+ 
+ 	/* set replay cache */
+-	open->op_stateowner->so_replay.rp_openfh_len = current_fh->fh_handle.fh_size;
+-	memcpy(open->op_stateowner->so_replay.rp_openfh,
+-		¤t_fh->fh_handle.fh_base,
+-		current_fh->fh_handle.fh_size);
++	fh_copy_shallow(&open->op_stateowner->so_replay.rp_openfh,
++			¤t_fh->fh_handle);
+ 
+ 	open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) &&
+ 		(open->op_iattr.ia_size == 0);
+@@ -187,9 +183,8 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	if (status == nfserr_replay_me) {
+ 		struct nfs4_replay *rp = &open->op_stateowner->so_replay;
+ 		fh_put(&cstate->current_fh);
+-		cstate->current_fh.fh_handle.fh_size = rp->rp_openfh_len;
+-		memcpy(&cstate->current_fh.fh_handle.fh_base, rp->rp_openfh,
+-				rp->rp_openfh_len);
++		fh_copy_shallow(&cstate->current_fh.fh_handle,
++				&rp->rp_openfh);
+ 		status = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP);
+ 		if (status)
+ 			dprintk("nfsd4_open: replay failed"
+diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h
+index fa317f6c154b..afa19016c4a8 100644
+--- a/include/linux/nfsd/nfsfh.h
++++ b/include/linux/nfsd/nfsfh.h
+@@ -269,6 +269,13 @@ fh_copy(struct svc_fh *dst, struct svc_fh *src)
+ 	return dst;
+ }
+ 
++static inline void
++fh_copy_shallow(struct knfsd_fh *dst, struct knfsd_fh *src)
++{
++	dst->fh_size = src->fh_size;
++	memcpy(&dst->fh_base, &src->fh_base, src->fh_size);
++}
++
+ static __inline__ struct svc_fh *
+ fh_init(struct svc_fh *fhp, int maxsize)
+ {
+diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
+index 128298c0362d..b65b2a6274b0 100644
+--- a/include/linux/nfsd/state.h
++++ b/include/linux/nfsd/state.h
+@@ -168,8 +168,7 @@ struct nfs4_replay {
+ 	unsigned int		rp_buflen;
+ 	char			*rp_buf;
+ 	unsigned		intrp_allocated;
+-	int			rp_openfh_len;
+-	char			rp_openfh[NFS4_FHSIZE];
++	struct knfsd_fh		rp_openfh;
+ 	char			rp_ibuf[NFSD4_REPLAY_ISIZE];
+ };
+ 

commit 13024b7b4097d33fe6bba34b1c83602e88753270
+Author: J. Bruce Fields 
+Date:   Mon Feb 2 17:04:03 2009 -0500
+
+    nfsd4: fix misplaced comment
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index 85b9a084177a..326506272258 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -120,9 +120,9 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
+ 		goto out;
+ 
+ 	set_change_info(&open->op_cinfo, current_fh);
++	fh_dup2(current_fh, &resfh);
+ 
+ 	/* set reply cache */
+-	fh_dup2(current_fh, &resfh);
+ 	open->op_stateowner->so_replay.rp_openfh_len = resfh.fh_handle.fh_size;
+ 	memcpy(open->op_stateowner->so_replay.rp_openfh,
+ 			&resfh.fh_handle.fh_base, resfh.fh_handle.fh_size);

commit 99f88726381f676bba6e7dcf74b7412857d7946a
+Author: J. Bruce Fields 
+Date:   Mon Feb 2 15:12:27 2009 -0500
+
+    nfsd: clarify exclusive create bitmask result.
+    
+    The use of |= is confusing--the bitmask is always initialized to zero in
+    this case, so we're effectively just doing an assignment here.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index 9fa60a3ad48c..85b9a084177a 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -103,11 +103,13 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
+ 					(u32 *)open->op_verf.data,
+ 					&open->op_truncate, &created);
+ 
+-		/* If we ever decide to use different attrs to store the
+-		 * verifier in nfsd_create_v3, then we'll need to change this
++		/*
++		 * Following rfc 3530 14.2.16, use the returned bitmask
++		 * to indicate which attributes we used to store the
++		 * verifier:
+ 		 */
+ 		if (open->op_createmode == NFS4_CREATE_EXCLUSIVE && status == 0)
+-			open->op_bmval[1] |= (FATTR4_WORD1_TIME_ACCESS |
++			open->op_bmval[1] = (FATTR4_WORD1_TIME_ACCESS |
+ 						FATTR4_WORD1_TIME_MODIFY);
+ 	} else {
+ 		status = nfsd_lookup(rqstp, current_fh,

commit f044ff830f1afe91e4388320f0c7b6e08d2e05f8
+Author: J. Bruce Fields 
+Date:   Sun Jan 11 15:24:04 2009 -0500
+
+    nfsd4: split open/lockowner release code
+    
+    The caller always knows specifically whether it's releasing a lockowner
+    or an openowner, and the code is simpler if we use separate functions
+    (and the apparent recursion is gone).
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 6ab30772496e..41a3590ef2cc 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -116,9 +116,6 @@ opaque_hashval(const void *ptr, int nbytes)
+ 	return x;
+ }
+ 
+-/* forward declarations */
+-static void release_stateowner(struct nfs4_stateowner *sop);
+-
+ /*
+  * Delegation state
+  */
+@@ -329,6 +326,26 @@ static void release_lock_stateid(struct nfs4_stateid *stp)
+ 	free_generic_stateid(stp);
+ }
+ 
++static void unhash_lockowner(struct nfs4_stateowner *sop)
++{
++	struct nfs4_stateid *stp;
++
++	list_del(&sop->so_idhash);
++	list_del(&sop->so_strhash);
++	list_del(&sop->so_perstateid);
++	while (!list_empty(&sop->so_stateids)) {
++		stp = list_first_entry(&sop->so_stateids,
++				struct nfs4_stateid, st_perstateowner);
++		release_lock_stateid(stp);
++	}
++}
++
++static void release_lockowner(struct nfs4_stateowner *sop)
++{
++	unhash_lockowner(sop);
++	nfs4_put_stateowner(sop);
++}
++
+ static void
+ release_stateid_lockowners(struct nfs4_stateid *open_stp)
+ {
+@@ -339,7 +356,7 @@ release_stateid_lockowners(struct nfs4_stateid *open_stp)
+ 				struct nfs4_stateowner, so_perstateid);
+ 		/* list_del(&open_stp->st_lockowners);  */
+ 		BUG_ON(lock_sop->so_is_open_owner);
+-		release_stateowner(lock_sop);
++		release_lockowner(lock_sop);
+ 	}
+ }
+ 
+@@ -351,30 +368,24 @@ static void release_open_stateid(struct nfs4_stateid *stp)
+ 	free_generic_stateid(stp);
+ }
+ 
+-static void
+-unhash_stateowner(struct nfs4_stateowner *sop)
++static void unhash_openowner(struct nfs4_stateowner *sop)
+ {
+ 	struct nfs4_stateid *stp;
+ 
+ 	list_del(&sop->so_idhash);
+ 	list_del(&sop->so_strhash);
+-	if (sop->so_is_open_owner)
+-		list_del(&sop->so_perclient);
+-	list_del(&sop->so_perstateid);
++	list_del(&sop->so_perclient);
++	list_del(&sop->so_perstateid); /* XXX: necessary? */
+ 	while (!list_empty(&sop->so_stateids)) {
+-		stp = list_entry(sop->so_stateids.next,
+-			struct nfs4_stateid, st_perstateowner);
+-		if (sop->so_is_open_owner)
+-			release_open_stateid(stp);
+-		else
+-			release_lock_stateid(stp);
++		stp = list_first_entry(&sop->so_stateids,
++				struct nfs4_stateid, st_perstateowner);
++		release_open_stateid(stp);
+ 	}
+ }
+ 
+-static void
+-release_stateowner(struct nfs4_stateowner *sop)
++static void release_openowner(struct nfs4_stateowner *sop)
+ {
+-	unhash_stateowner(sop);
++	unhash_openowner(sop);
+ 	list_del(&sop->so_close_lru);
+ 	nfs4_put_stateowner(sop);
+ }
+@@ -488,7 +499,7 @@ expire_client(struct nfs4_client *clp)
+ 	list_del(&clp->cl_lru);
+ 	while (!list_empty(&clp->cl_openowners)) {
+ 		sop = list_entry(clp->cl_openowners.next, struct nfs4_stateowner, so_perclient);
+-		release_stateowner(sop);
++		release_openowner(sop);
+ 	}
+ 	put_nfs4_client(clp);
+ }
+@@ -1443,7 +1454,7 @@ nfsd4_process_open1(struct nfsd4_open *open)
+ 	if (!sop->so_confirmed) {
+ 		/* Replace unconfirmed owners without checking for replay. */
+ 		clp = sop->so_client;
+-		release_stateowner(sop);
++		release_openowner(sop);
+ 		open->op_stateowner = NULL;
+ 		goto renew;
+ 	}
+@@ -1906,7 +1917,7 @@ nfs4_laundromat(void)
+ 		}
+ 		dprintk("NFSD: purging unused open stateowner (so_id %d)\n",
+ 			sop->so_id);
+-		release_stateowner(sop);
++		release_openowner(sop);
+ 	}
+ 	if (clientid_val < NFSD_LAUNDROMAT_MINTIMEOUT)
+ 		clientid_val = NFSD_LAUNDROMAT_MINTIMEOUT;
+@@ -2796,7 +2807,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	}
+ out:
+ 	if (status && lock->lk_is_new && lock_sop)
+-		release_stateowner(lock_sop);
++		release_lockowner(lock_sop);
+ 	if (lock->lk_replay_owner) {
+ 		nfs4_get_stateowner(lock->lk_replay_owner);
+ 		cstate->replay_owner = lock->lk_replay_owner;
+@@ -3045,7 +3056,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
+ 		/* unhash_stateowner deletes so_perclient only
+ 		 * for openowners. */
+ 		list_del(&sop->so_perclient);
+-		release_stateowner(sop);
++		release_lockowner(sop);
+ 	}
+ out:
+ 	nfs4_unlock_state();

commit f1d110caf7d759eae2c02c84343f63d83db9b9be
+Author: J. Bruce Fields 
+Date:   Sun Jan 11 14:37:31 2009 -0500
+
+    nfsd4: remove a forward declaration
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index e83b3c865aa3..6ab30772496e 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -75,7 +75,6 @@ static stateid_t onestateid;              /* bits all 1 */
+ /* forward declarations */
+ static struct nfs4_stateid * find_stateid(stateid_t *stid, int flags);
+ static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid);
+-static void release_stateid_lockowners(struct nfs4_stateid *open_stp);
+ static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
+ static void nfs4_set_recdir(char *recdir);
+ 
+@@ -330,6 +329,20 @@ static void release_lock_stateid(struct nfs4_stateid *stp)
+ 	free_generic_stateid(stp);
+ }
+ 
++static void
++release_stateid_lockowners(struct nfs4_stateid *open_stp)
++{
++	struct nfs4_stateowner *lock_sop;
++
++	while (!list_empty(&open_stp->st_lockowners)) {
++		lock_sop = list_entry(open_stp->st_lockowners.next,
++				struct nfs4_stateowner, so_perstateid);
++		/* list_del(&open_stp->st_lockowners);  */
++		BUG_ON(lock_sop->so_is_open_owner);
++		release_stateowner(lock_sop);
++	}
++}
++
+ static void release_open_stateid(struct nfs4_stateid *stp)
+ {
+ 	unhash_generic_stateid(stp);
+@@ -338,6 +351,34 @@ static void release_open_stateid(struct nfs4_stateid *stp)
+ 	free_generic_stateid(stp);
+ }
+ 
++static void
++unhash_stateowner(struct nfs4_stateowner *sop)
++{
++	struct nfs4_stateid *stp;
++
++	list_del(&sop->so_idhash);
++	list_del(&sop->so_strhash);
++	if (sop->so_is_open_owner)
++		list_del(&sop->so_perclient);
++	list_del(&sop->so_perstateid);
++	while (!list_empty(&sop->so_stateids)) {
++		stp = list_entry(sop->so_stateids.next,
++			struct nfs4_stateid, st_perstateowner);
++		if (sop->so_is_open_owner)
++			release_open_stateid(stp);
++		else
++			release_lock_stateid(stp);
++	}
++}
++
++static void
++release_stateowner(struct nfs4_stateowner *sop)
++{
++	unhash_stateowner(sop);
++	list_del(&sop->so_close_lru);
++	nfs4_put_stateowner(sop);
++}
++
+ static inline void
+ renew_client(struct nfs4_client *clp)
+ {
+@@ -1064,48 +1105,6 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
+ 	return sop;
+ }
+ 
+-static void
+-release_stateid_lockowners(struct nfs4_stateid *open_stp)
+-{
+-	struct nfs4_stateowner *lock_sop;
+-
+-	while (!list_empty(&open_stp->st_lockowners)) {
+-		lock_sop = list_entry(open_stp->st_lockowners.next,
+-				struct nfs4_stateowner, so_perstateid);
+-		/* list_del(&open_stp->st_lockowners);  */
+-		BUG_ON(lock_sop->so_is_open_owner);
+-		release_stateowner(lock_sop);
+-	}
+-}
+-
+-static void
+-unhash_stateowner(struct nfs4_stateowner *sop)
+-{
+-	struct nfs4_stateid *stp;
+-
+-	list_del(&sop->so_idhash);
+-	list_del(&sop->so_strhash);
+-	if (sop->so_is_open_owner)
+-		list_del(&sop->so_perclient);
+-	list_del(&sop->so_perstateid);
+-	while (!list_empty(&sop->so_stateids)) {
+-		stp = list_entry(sop->so_stateids.next,
+-			struct nfs4_stateid, st_perstateowner);
+-		if (sop->so_is_open_owner)
+-			release_open_stateid(stp);
+-		else
+-			release_lock_stateid(stp);
+-	}
+-}
+-
+-static void
+-release_stateowner(struct nfs4_stateowner *sop)
+-{
+-	unhash_stateowner(sop);
+-	list_del(&sop->so_close_lru);
+-	nfs4_put_stateowner(sop);
+-}
+-
+ static inline void
+ init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *open) {
+ 	struct nfs4_stateowner *sop = open->op_stateowner;

commit 2283963f27fdd56b185e49a964c290130c7c95ab
+Author: J. Bruce Fields 
+Date:   Sun Jan 11 14:27:17 2009 -0500
+
+    nfsd4: split lockstateid/openstateid release logic
+    
+    The flags here attempt to make the code more general, but I find it
+    actually just adds confusion.
+    
+    I think it's clearer to separate the logic for the open and lock cases
+    entirely.  And eventually we may want to separate the stateowner and
+    stateid types as well, as many of the fields aren't shared between the
+    lock and open cases.
+    
+    Also move to eliminate forward references.
+    
+    Start with the stateid's.
+    
+    Signed-off-by: J. Bruce Fields 
+    Reviewed-by: Benny Halevy 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index b6f60f48e94b..e83b3c865aa3 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -119,7 +119,6 @@ opaque_hashval(const void *ptr, int nbytes)
+ 
+ /* forward declarations */
+ static void release_stateowner(struct nfs4_stateowner *sop);
+-static void release_stateid(struct nfs4_stateid *stp, int flags);
+ 
+ /*
+  * Delegation state
+@@ -311,6 +310,34 @@ static struct list_head	unconf_id_hashtbl[CLIENT_HASH_SIZE];
+ static struct list_head client_lru;
+ static struct list_head close_lru;
+ 
++static void unhash_generic_stateid(struct nfs4_stateid *stp)
++{
++	list_del(&stp->st_hash);
++	list_del(&stp->st_perfile);
++	list_del(&stp->st_perstateowner);
++}
++
++static void free_generic_stateid(struct nfs4_stateid *stp)
++{
++	put_nfs4_file(stp->st_file);
++	kmem_cache_free(stateid_slab, stp);
++}
++
++static void release_lock_stateid(struct nfs4_stateid *stp)
++{
++	unhash_generic_stateid(stp);
++	locks_remove_posix(stp->st_vfs_file, (fl_owner_t)stp->st_stateowner);
++	free_generic_stateid(stp);
++}
++
++static void release_open_stateid(struct nfs4_stateid *stp)
++{
++	unhash_generic_stateid(stp);
++	release_stateid_lockowners(stp);
++	nfsd_close(stp->st_vfs_file);
++	free_generic_stateid(stp);
++}
++
+ static inline void
+ renew_client(struct nfs4_client *clp)
+ {
+@@ -1065,9 +1092,9 @@ unhash_stateowner(struct nfs4_stateowner *sop)
+ 		stp = list_entry(sop->so_stateids.next,
+ 			struct nfs4_stateid, st_perstateowner);
+ 		if (sop->so_is_open_owner)
+-			release_stateid(stp, OPEN_STATE);
++			release_open_stateid(stp);
+ 		else
+-			release_stateid(stp, LOCK_STATE);
++			release_lock_stateid(stp);
+ 	}
+ }
+ 
+@@ -1105,24 +1132,6 @@ init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *
+ 	stp->st_openstp = NULL;
+ }
+ 
+-static void
+-release_stateid(struct nfs4_stateid *stp, int flags)
+-{
+-	struct file *filp = stp->st_vfs_file;
+-
+-	list_del(&stp->st_hash);
+-	list_del(&stp->st_perfile);
+-	list_del(&stp->st_perstateowner);
+-	if (flags & OPEN_STATE) {
+-		release_stateid_lockowners(stp);
+-		stp->st_vfs_file = NULL;
+-		nfsd_close(filp);
+-	} else if (flags & LOCK_STATE)
+-		locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner);
+-	put_nfs4_file(stp->st_file);
+-	kmem_cache_free(stateid_slab, stp);
+-}
+-
+ static void
+ move_to_close_lru(struct nfs4_stateowner *sop)
+ {
+@@ -1764,7 +1773,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
+ 		init_stateid(stp, fp, open);
+ 		status = nfsd4_truncate(rqstp, current_fh, open);
+ 		if (status) {
+-			release_stateid(stp, OPEN_STATE);
++			release_open_stateid(stp);
+ 			goto out;
+ 		}
+ 	}
+@@ -2373,7 +2382,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	memcpy(&close->cl_stateid, &stp->st_stateid, sizeof(stateid_t));
+ 
+ 	/* release_stateid() calls nfsd_close() if needed */
+-	release_stateid(stp, OPEN_STATE);
++	release_open_stateid(stp);
+ 
+ 	/* place unused nfs4_stateowners on so_close_lru list to be
+ 	 * released by the laundromat service after the lease period

commit 76a67ec6fb79ff3570dcb5342142c16098299911
+Author: J. Bruce Fields 
+Date:   Mon Mar 16 18:34:20 2009 -0400
+
+    nfsd: nfsd should drop CAP_MKNOD for non-root
+    
+    Since creating a device node is normally an operation requiring special
+    privilege, Igor Zhbanov points out that it is surprising (to say the
+    least) that a client can, for example, create a device node on a
+    filesystem exported with root_squash.
+    
+    So, make sure CAP_MKNOD is among the capabilities dropped when an nfsd
+    thread handles a request from a non-root user.
+    
+    Reported-by: Igor Zhbanov 
+    Cc: stable@kernel.org
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/include/linux/capability.h b/include/linux/capability.h
+index 1b9872556131..4864a43b2b45 100644
+--- a/include/linux/capability.h
++++ b/include/linux/capability.h
+@@ -393,8 +393,10 @@ struct cpu_vfs_cap_data {
+ # define CAP_FULL_SET     ((kernel_cap_t){{ ~0, ~0 }})
+ # define CAP_INIT_EFF_SET ((kernel_cap_t){{ ~CAP_TO_MASK(CAP_SETPCAP), ~0 }})
+ # define CAP_FS_SET       ((kernel_cap_t){{ CAP_FS_MASK_B0, CAP_FS_MASK_B1 } })
+-# define CAP_NFSD_SET     ((kernel_cap_t){{ CAP_FS_MASK_B0|CAP_TO_MASK(CAP_SYS_RESOURCE), \
+-					CAP_FS_MASK_B1 } })
++# define CAP_NFSD_SET     ((kernel_cap_t){{ CAP_FS_MASK_B0 \
++					    | CAP_TO_MASK(CAP_SYS_RESOURCE) \
++					    | CAP_TO_MASK(CAP_MKNOD), \
++					    CAP_FS_MASK_B1 } })
+ 
+ #endif /* _KERNEL_CAPABILITY_U32S != 2 */
+ 

commit 9d9b87c1218be78ddecbc85ec3bb91c79c1d56ab
+Author: J. Bruce Fields 
+Date:   Wed Feb 4 17:35:38 2009 -0500
+
+    lockd: fix regression in lockd's handling of blocked locks
+    
+    If a client requests a blocking lock, is denied, then requests it again,
+    then here in nlmsvc_lock() we will call vfs_lock_file() without FL_SLEEP
+    set, because we've already queued a block and don't need the locks code
+    to do it again.
+    
+    But that means vfs_lock_file() will return -EAGAIN instead of
+    FILE_LOCK_DENIED.  So we still need to translate that -EAGAIN return
+    into a nlm_lck_blocked error in this case, and put ourselves back on
+    lockd's block list.
+    
+    The bug was introduced by bde74e4bc64415b1 "locks: add special return
+    value for asynchronous locks".
+    
+    Thanks to Frank van Maarseveen for the report; his original test
+    case was essentially
+    
+            for i in `seq 30`; do flock /nfsmount/foo sleep 10 & done
+    
+    Tested-by: Frank van Maarseveen 
+    Reported-by: Frank van Maarseveen 
+    Cc: Miklos Szeredi 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
+index 6063a8e4b9f3..763b78a6e9de 100644
+--- a/fs/lockd/svclock.c
++++ b/fs/lockd/svclock.c
+@@ -427,7 +427,7 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
+ 			goto out;
+ 		case -EAGAIN:
+ 			ret = nlm_lck_denied;
+-			goto out;
++			break;
+ 		case FILE_LOCK_DEFERRED:
+ 			if (wait)
+ 				break;
+@@ -443,6 +443,10 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
+ 			goto out;
+ 	}
+ 
++	ret = nlm_lck_denied;
++	if (!wait)
++		goto out;
++
+ 	ret = nlm_lck_blocked;
+ 
+ 	/* Append to list of blocked */

commit ce0cf6622c9a6f18c2723ea4bef7616799a1ca39
+Author: J. Bruce Fields 
+Date:   Sun Nov 2 16:18:08 2008 -0500
+
+    nfs: note that CONFIG_SUNRPC_XPRT_RDMA turns on server side support too
+    
+    We forgot to update this when adding server-side support.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig
+index eda4a7aee596..dcef600d0bf5 100644
+--- a/net/sunrpc/Kconfig
++++ b/net/sunrpc/Kconfig
+@@ -9,9 +9,8 @@ config SUNRPC_XPRT_RDMA
+ 	depends on SUNRPC && INFINIBAND && EXPERIMENTAL
+ 	default SUNRPC && INFINIBAND
+ 	help
+-	  This option enables an RPC client transport capability that
+-	  allows the NFS client to mount servers via an RDMA-enabled
+-	  transport.
++	  This option allows the NFS client and server to support
++	  an RDMA-enabled transport.
+ 
+ 	  To compile RPC client RDMA transport support as a module,
+ 	  choose M here: the module will be called xprtrdma.

commit 9a8d248e2d2e9c880ac4561f27fea5dc200655bd
+Author: J. Bruce Fields 
+Date:   Tue Jan 6 13:37:03 2009 -0500
+
+    nfsd: fix double-locks of directory mutex
+    
+    A number of nfsd operations depend on the i_mutex to cover more code
+    than just the fsync, so the approach of 4c728ef583b3d8 "add a vfs_fsync
+    helper" doesn't work for nfsd.  Revert the parts of those patches that
+    touch nfsd.
+    
+    Note: we can't, however, remove the logic from vfs_fsync that was needed
+    only for the special case of nfsd, because a vfs_fsync(NULL,...) call
+    can still result indirectly from a stackable filesystem that was called
+    by nfsd.  (Thanks to Christoph Hellwig for pointing this out.)
+    
+    Reported-by: Eric Sesterhenn 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index 44aa92aba891..6e50aaa56ca2 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -744,16 +744,44 @@ nfsd_close(struct file *filp)
+ 	fput(filp);
+ }
+ 
++/*
++ * Sync a file
++ * As this calls fsync (not fdatasync) there is no need for a write_inode
++ * after it.
++ */
++static inline int nfsd_dosync(struct file *filp, struct dentry *dp,
++			      const struct file_operations *fop)
++{
++	struct inode *inode = dp->d_inode;
++	int (*fsync) (struct file *, struct dentry *, int);
++	int err;
++
++	err = filemap_fdatawrite(inode->i_mapping);
++	if (err == 0 && fop && (fsync = fop->fsync))
++		err = fsync(filp, dp, 0);
++	if (err == 0)
++		err = filemap_fdatawait(inode->i_mapping);
++
++	return err;
++}
++
+ static int
+ nfsd_sync(struct file *filp)
+ {
+-	return vfs_fsync(filp, filp->f_path.dentry, 0);
++        int err;
++	struct inode *inode = filp->f_path.dentry->d_inode;
++	dprintk("nfsd: sync file %s\n", filp->f_path.dentry->d_name.name);
++	mutex_lock(&inode->i_mutex);
++	err=nfsd_dosync(filp, filp->f_path.dentry, filp->f_op);
++	mutex_unlock(&inode->i_mutex);
++
++	return err;
+ }
+ 
+ int
+-nfsd_sync_dir(struct dentry *dentry)
++nfsd_sync_dir(struct dentry *dp)
+ {
+-	return vfs_fsync(NULL, dentry, 0);
++	return nfsd_dosync(NULL, dp, dp->d_inode->i_fop);
+ }
+ 
+ /*

commit 55ef1274dddd4de387c54d110e354ffbb6cdc706
+Author: J. Bruce Fields 
+Date:   Sat Dec 20 11:58:38 2008 -0800
+
+    nfsd: Ensure nfsv4 calls the underlying filesystem on LOCKT
+    
+    Since nfsv4 allows LOCKT without an open, but the ->lock() method is a
+    file method, we fake up a struct file in the nfsv4 code with just the
+    fields we need initialized.  But we forgot to initialize the file
+    operations, with the result that LOCKT never results in a call to the
+    filesystem's ->lock() method (if it exists).
+    
+    We could just add that one more initialization.  But this hack of faking
+    up a struct file with only some fields initialized seems the kind of
+    thing that might cause more problems in the future.  We should either do
+    an open and get a real struct file, or make lock-testing an inode (not a
+    file) method.
+    
+    This patch does the former.
+    
+    Reported-by: Marc Eshel 
+    Tested-by: Marc Eshel 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 06b89df92218..e62d0e3df8b3 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2781,6 +2781,25 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	return status;
+ }
+ 
++/*
++ * The NFSv4 spec allows a client to do a LOCKT without holding an OPEN,
++ * so we do a temporary open here just to get an open file to pass to
++ * vfs_test_lock.  (Arguably perhaps test_lock should be done with an
++ * inode operation.)
++ */
++static int nfsd_test_lock(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file_lock *lock)
++{
++	struct file *file;
++	int err;
++
++	err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file);
++	if (err)
++		return err;
++	err = vfs_test_lock(file, lock);
++	nfsd_close(file);
++	return err;
++}
++
+ /*
+  * LOCKT operation
+  */
+@@ -2789,7 +2808,6 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	    struct nfsd4_lockt *lockt)
+ {
+ 	struct inode *inode;
+-	struct file file;
+ 	struct file_lock file_lock;
+ 	int error;
+ 	__be32 status;
+@@ -2847,16 +2865,8 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 
+ 	nfs4_transform_lock_offset(&file_lock);
+ 
+-	/* vfs_test_lock uses the struct file _only_ to resolve the inode.
+-	 * since LOCKT doesn't require an OPEN, and therefore a struct
+-	 * file may not exist, pass vfs_test_lock a struct file with
+-	 * only the dentry:inode set.
+-	 */
+-	memset(&file, 0, sizeof (struct file));
+-	file.f_path.dentry = cstate->current_fh.fh_dentry;
+-
+ 	status = nfs_ok;
+-	error = vfs_test_lock(&file, &file_lock);
++	error = nfsd_test_lock(rqstp, &cstate->current_fh, &file_lock);
+ 	if (error) {
+ 		status = nfserrno(error);
+ 		goto out;

commit 548eaca46b3cf4419b6c2be839a106d8641ffb70
+Author: J. Bruce Fields 
+Date:   Mon Oct 20 17:48:43 2008 -0400
+
+    nfsd: document new filehandle fsid types
+    
+    Descriptions taken from mountd code (in nfs-utils/utils/mountd/cache.c).
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h
+index d1941cb965e9..b2e093870bc6 100644
+--- a/include/linux/nfsd/nfsfh.h
++++ b/include/linux/nfsd/nfsfh.h
+@@ -68,6 +68,10 @@ struct nfs_fhbase_old {
+  *     1  - 4 byte user specified identifier
+  *     2  - 4 byte major, 4 byte minor, 4 byte inode number - DEPRECATED
+  *     3  - 4 byte device id, encoded for user-space, 4 byte inode number
++ *     4  - 4 byte inode number and 4 byte uuid
++ *     5  - 8 byte uuid
++ *     6  - 16 byte uuid
++ *     7  - 8 byte inode number and 16 byte uuid
+  *
+  * The fileid_type identified how the file within the filesystem is encoded.
+  * This is (will be) passed to, and set by, the underlying filesystem if it supports

commit b3d47676d474ecd914c72049c87e71e5f0ffe040
+Author: J. Bruce Fields 
+Date:   Mon Oct 20 13:01:59 2008 -0400
+
+    nfsd: update fh_verify description
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
+index f0da7d9c3a92..019a8a20184d 100644
+--- a/fs/nfsd/nfsfh.c
++++ b/fs/nfsd/nfsfh.c
+@@ -258,14 +258,32 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
+ 	return error;
+ }
+ 
+-/*
+- * Perform sanity checks on the dentry in a client's file handle.
++/**
++ * fh_verify - filehandle lookup and access checking
++ * @rqstp: pointer to current rpc request
++ * @fhp: filehandle to be verified
++ * @type: expected type of object pointed to by filehandle
++ * @access: type of access needed to object
++ *
++ * Look up a dentry from the on-the-wire filehandle, check the client's
++ * access to the export, and set the current task's credentials.
++ *
++ * Regardless of success or failure of fh_verify(), fh_put() should be
++ * called on @fhp when the caller is finished with the filehandle.
++ *
++ * fh_verify() may be called multiple times on a given filehandle, for
++ * example, when processing an NFSv4 compound.  The first call will look
++ * up a dentry using the on-the-wire filehandle.  Subsequent calls will
++ * skip the lookup and just perform the other checks and possibly change
++ * the current task's credentials.
+  *
+- * Note that the file handle dentry may need to be freed even after
+- * an error return.
++ * @type specifies the type of object expected using one of the S_IF*
++ * constants defined in include/linux/stat.h.  The caller may use zero
++ * to indicate that it doesn't care, or a negative integer to indicate
++ * that it expects something not of the given type.
+  *
+- * This is only called at the start of an nfsproc call, so fhp points to
+- * a svc_fh which is all 0 except for the over-the-wire file handle.
++ * @access is formed from the NFSD_MAY_* constants defined in
++ * include/linux/nfsd/nfsd.h.
+  */
+ __be32
+ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)

commit 2efef7080f471d312a9c4feb3dc5ee038039c7ed
+Author: Olga Kornievskaia 
+Date:   Tue Dec 23 16:19:56 2008 -0500
+
+    rpc: add service field to new upcall
+    
+    This patch extends the new upcall with a "service" field that currently
+    can have 2 values: "*" or "nfs". These values specify matching rules for
+    principals in the keytab file. The "*" means that gssd is allowed to use
+    "root", "nfs", or "host" keytab entries while the other option requires
+    "nfs".
+    
+    Restricting gssd to use the "nfs" principal is needed for when the
+    server performs a callback to the client.  The server in this case has
+    to authenticate itself as an "nfs" principal.
+    
+    We also need "service" field to distiguish between two client-side cases
+    both currently using a uid of 0: the case of regular file access by the
+    root user, and the case of state-management calls (such as setclientid)
+    which should use a keytab for authentication.  (And the upcall should
+    fail if an appropriate principal can't be found.)
+    
+    Signed-off: Olga Kornievskaia 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index 1e8cced55ff7..e630b38a6047 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -369,7 +369,7 @@ static void gss_encode_v0_msg(struct gss_upcall_msg *gss_msg)
+ }
+ 
+ static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg,
+-				struct rpc_clnt *clnt)
++				struct rpc_clnt *clnt, int machine_cred)
+ {
+ 	char *p = gss_msg->databuf;
+ 	int len = 0;
+@@ -383,6 +383,15 @@ static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg,
+ 		p += len;
+ 		gss_msg->msg.len += len;
+ 	}
++	if (machine_cred) {
++		len = sprintf(p, "service=* ");
++		p += len;
++		gss_msg->msg.len += len;
++	} else if (!strcmp(clnt->cl_program->name, "nfs4_cb")) {
++		len = sprintf(p, "service=nfs ");
++		p += len;
++		gss_msg->msg.len += len;
++	}
+ 	len = sprintf(p, "\n");
+ 	gss_msg->msg.len += len;
+ 
+@@ -391,16 +400,17 @@ static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg,
+ }
+ 
+ static void gss_encode_msg(struct gss_upcall_msg *gss_msg,
+-				struct rpc_clnt *clnt)
++				struct rpc_clnt *clnt, int machine_cred)
+ {
+ 	if (pipe_version == 0)
+ 		gss_encode_v0_msg(gss_msg);
+ 	else /* pipe_version == 1 */
+-		gss_encode_v1_msg(gss_msg, clnt);
++		gss_encode_v1_msg(gss_msg, clnt, machine_cred);
+ }
+ 
+ static inline struct gss_upcall_msg *
+-gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid, struct rpc_clnt *clnt)
++gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid, struct rpc_clnt *clnt,
++		int machine_cred)
+ {
+ 	struct gss_upcall_msg *gss_msg;
+ 	int vers;
+@@ -420,7 +430,7 @@ gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid, struct rpc_clnt *clnt)
+ 	atomic_set(&gss_msg->count, 1);
+ 	gss_msg->uid = uid;
+ 	gss_msg->auth = gss_auth;
+-	gss_encode_msg(gss_msg, clnt);
++	gss_encode_msg(gss_msg, clnt, machine_cred);
+ 	return gss_msg;
+ }
+ 
+@@ -432,11 +442,7 @@ gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cr
+ 	struct gss_upcall_msg *gss_new, *gss_msg;
+ 	uid_t uid = cred->cr_uid;
+ 
+-	/* Special case: rpc.gssd assumes that uid == 0 implies machine creds */
+-	if (gss_cred->gc_machine_cred != 0)
+-		uid = 0;
+-
+-	gss_new = gss_alloc_msg(gss_auth, uid, clnt);
++	gss_new = gss_alloc_msg(gss_auth, uid, clnt, gss_cred->gc_machine_cred);
+ 	if (IS_ERR(gss_new))
+ 		return gss_new;
+ 	gss_msg = gss_add_msg(gss_auth, gss_new);

commit 8b1c7bf5b624c9bc91b41ae577b9fc5c21641705
+Author: Olga Kornievskaia 
+Date:   Tue Dec 23 16:19:26 2008 -0500
+
+    rpc: add target field to new upcall
+    
+    This patch extends the new upcall by adding a "target" field
+    communicating who we want to authenticate to (equivalently, the service
+    principal that we want to acquire a ticket for).
+    
+    Signed-off: Olga Kornievskaia 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index 153b3e11e61a..1e8cced55ff7 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -368,25 +368,39 @@ static void gss_encode_v0_msg(struct gss_upcall_msg *gss_msg)
+ 	gss_msg->msg.len = sizeof(gss_msg->uid);
+ }
+ 
+-static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg)
++static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg,
++				struct rpc_clnt *clnt)
+ {
+-	gss_msg->msg.len = sprintf(gss_msg->databuf, "mech=%s uid=%d\n",
++	char *p = gss_msg->databuf;
++	int len = 0;
++
++	gss_msg->msg.len = sprintf(gss_msg->databuf, "mech=%s uid=%d ",
+ 				   gss_msg->auth->mech->gm_name,
+ 				   gss_msg->uid);
++	p += gss_msg->msg.len;
++	if (clnt->cl_principal) {
++		len = sprintf(p, "target=%s ", clnt->cl_principal);
++		p += len;
++		gss_msg->msg.len += len;
++	}
++	len = sprintf(p, "\n");
++	gss_msg->msg.len += len;
++
+ 	gss_msg->msg.data = gss_msg->databuf;
+ 	BUG_ON(gss_msg->msg.len > UPCALL_BUF_LEN);
+ }
+ 
+-static void gss_encode_msg(struct gss_upcall_msg *gss_msg)
++static void gss_encode_msg(struct gss_upcall_msg *gss_msg,
++				struct rpc_clnt *clnt)
+ {
+ 	if (pipe_version == 0)
+ 		gss_encode_v0_msg(gss_msg);
+ 	else /* pipe_version == 1 */
+-		gss_encode_v1_msg(gss_msg);
++		gss_encode_v1_msg(gss_msg, clnt);
+ }
+ 
+ static inline struct gss_upcall_msg *
+-gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid)
++gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid, struct rpc_clnt *clnt)
+ {
+ 	struct gss_upcall_msg *gss_msg;
+ 	int vers;
+@@ -406,7 +420,7 @@ gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid)
+ 	atomic_set(&gss_msg->count, 1);
+ 	gss_msg->uid = uid;
+ 	gss_msg->auth = gss_auth;
+-	gss_encode_msg(gss_msg);
++	gss_encode_msg(gss_msg, clnt);
+ 	return gss_msg;
+ }
+ 
+@@ -422,7 +436,7 @@ gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cr
+ 	if (gss_cred->gc_machine_cred != 0)
+ 		uid = 0;
+ 
+-	gss_new = gss_alloc_msg(gss_auth, uid);
++	gss_new = gss_alloc_msg(gss_auth, uid, clnt);
+ 	if (IS_ERR(gss_new))
+ 		return gss_new;
+ 	gss_msg = gss_add_msg(gss_auth, gss_new);

commit 61054b14d545e257b9415d5ca0cd5f43762b4d0c
+Author: Olga Kornievskaia 
+Date:   Tue Dec 23 16:19:00 2008 -0500
+
+    nfsd: support callbacks with gss flavors
+    
+    This patch adds server-side support for callbacks other than AUTH_SYS.
+    
+    Signed-off-by: Olga Kornievskaia 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 3ca141782145..6d7d8c02c197 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -358,6 +358,7 @@ static struct rpc_program cb_program = {
+ 		.nrvers		= ARRAY_SIZE(nfs_cb_version),
+ 		.version	= nfs_cb_version,
+ 		.stats		= &cb_stats,
++		.pipe_dir_name  = "/nfsd4_cb",
+ };
+ 
+ /* Reference counting, callback cleanup, etc., all look racy as heck.
+@@ -382,7 +383,7 @@ static int do_probe_callback(void *data)
+ 		.program	= &cb_program,
+ 		.prognumber	= cb->cb_prog,
+ 		.version	= nfs_cb_version[1]->number,
+-		.authflavor	= RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */
++		.authflavor	= clp->cl_flavor,
+ 		.flags		= (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET),
+ 		.client_name    = clp->cl_principal,
+ 	};
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index f3b9a8d064f3..07db31568ac9 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -786,6 +786,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	}
+ 	copy_verf(new, &clverifier);
+ 	new->cl_addr = sin->sin_addr.s_addr;
++	new->cl_flavor = rqstp->rq_flavor;
+ 	princ = svc_gss_principal(rqstp);
+ 	if (princ) {
+ 		new->cl_principal = kstrdup(princ, GFP_KERNEL);
+diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
+index ce7cbf4b7c93..128298c0362d 100644
+--- a/include/linux/nfsd/state.h
++++ b/include/linux/nfsd/state.h
+@@ -124,6 +124,7 @@ struct nfs4_client {
+ 	nfs4_verifier		cl_verifier; 	/* generated by client */
+ 	time_t                  cl_time;        /* time of last lease renewal */
+ 	__be32			cl_addr; 	/* client ipaddress */
++	u32			cl_flavor;	/* setclientid pseudoflavor */
+ 	char			*cl_principal;	/* setclientid principal name */
+ 	struct svc_cred		cl_cred; 	/* setclientid principal */
+ 	clientid_t		cl_clientid;	/* generated by server */
+diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
+index 3105efbb182d..192453248870 100644
+--- a/net/sunrpc/rpc_pipe.c
++++ b/net/sunrpc/rpc_pipe.c
+@@ -407,6 +407,7 @@ enum {
+ 	RPCAUTH_nfs,
+ 	RPCAUTH_portmap,
+ 	RPCAUTH_statd,
++	RPCAUTH_nfsd4_cb,
+ 	RPCAUTH_RootEOF
+ };
+ 
+@@ -440,6 +441,10 @@ static struct rpc_filelist files[] = {
+ 		.name = "statd",
+ 		.mode = S_IFDIR | S_IRUGO | S_IXUGO,
+ 	},
++	[RPCAUTH_nfsd4_cb] = {
++		.name = "nfsd4_cb",
++		.mode = S_IFDIR | S_IRUGO | S_IXUGO,
++	},
+ };
+ 
+ enum {

commit 945b34a7725a5f0741de7775132aafc58bfecfbb
+Author: Olga Kornievskaia 
+Date:   Tue Dec 23 16:18:34 2008 -0500
+
+    rpc: allow gss callbacks to client
+    
+    This patch adds client-side support to allow for callbacks other than
+    AUTH_SYS.
+    
+    Signed-off-by: Olga Kornievskaia 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
+index c2e9cfd9e5a4..3e634f2a1083 100644
+--- a/fs/nfs/callback.c
++++ b/fs/nfs/callback.c
+@@ -16,6 +16,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ 
+@@ -182,10 +183,34 @@ void nfs_callback_down(void)
+ 	mutex_unlock(&nfs_callback_mutex);
+ }
+ 
++static int check_gss_callback_principal(struct nfs_client *clp,
++					struct svc_rqst *rqstp)
++{
++	struct rpc_clnt *r = clp->cl_rpcclient;
++	char *p = svc_gss_principal(rqstp);
++
++	/*
++	 * It might just be a normal user principal, in which case
++	 * userspace won't bother to tell us the name at all.
++	 */
++	if (p == NULL)
++		return SVC_DENIED;
++
++	/* Expect a GSS_C_NT_HOSTBASED_NAME like "nfs@serverhostname" */
++
++	if (memcmp(p, "nfs@", 4) != 0)
++		return SVC_DENIED;
++	p += 4;
++	if (strcmp(p, r->cl_server) != 0)
++		return SVC_DENIED;
++	return SVC_OK;
++}
++
+ static int nfs_callback_authenticate(struct svc_rqst *rqstp)
+ {
+ 	struct nfs_client *clp;
+ 	RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
++	int ret = SVC_OK;
+ 
+ 	/* Don't talk to strangers */
+ 	clp = nfs_find_client(svc_addr(rqstp), 4);
+@@ -194,21 +219,22 @@ static int nfs_callback_authenticate(struct svc_rqst *rqstp)
+ 
+ 	dprintk("%s: %s NFSv4 callback!\n", __func__,
+ 			svc_print_addr(rqstp, buf, sizeof(buf)));
+-	nfs_put_client(clp);
+ 
+ 	switch (rqstp->rq_authop->flavour) {
+ 		case RPC_AUTH_NULL:
+ 			if (rqstp->rq_proc != CB_NULL)
+-				return SVC_DENIED;
++				ret = SVC_DENIED;
+ 			break;
+ 		case RPC_AUTH_UNIX:
+ 			break;
+ 		case RPC_AUTH_GSS:
+-			/* FIXME: RPCSEC_GSS handling? */
++			ret = check_gss_callback_principal(clp, rqstp);
++			break;
+ 		default:
+-			return SVC_DENIED;
++			ret = SVC_DENIED;
+ 	}
+-	return SVC_OK;
++	nfs_put_client(clp);
++	return ret;
+ }
+ 
+ /*
+diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
+index e9baa6ebb1dd..2278a50c6444 100644
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -935,6 +935,7 @@ char *svc_gss_principal(struct svc_rqst *rqstp)
+ 		return gd->rsci->client_name;
+ 	return NULL;
+ }
++EXPORT_SYMBOL_GPL(svc_gss_principal);
+ 
+ static int
+ svcauth_gss_set_client(struct svc_rqst *rqstp)

commit 608207e8884e083ad8b8d33eda868da70f0d63e8
+Author: Olga Kornievskaia 
+Date:   Tue Dec 23 16:17:40 2008 -0500
+
+    rpc: pass target name down to rpc level on callbacks
+    
+    The rpc client needs to know the principal that the setclientid was done
+    as, so it can tell gssd who to authenticate to.
+    
+    Signed-off-by: Olga Kornievskaia 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 094747a1227c..3ca141782145 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -384,6 +384,7 @@ static int do_probe_callback(void *data)
+ 		.version	= nfs_cb_version[1]->number,
+ 		.authflavor	= RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */
+ 		.flags		= (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET),
++		.client_name    = clp->cl_principal,
+ 	};
+ 	struct rpc_message msg = {
+ 		.rpc_proc       = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
+@@ -392,6 +393,11 @@ static int do_probe_callback(void *data)
+ 	struct rpc_clnt *client;
+ 	int status;
+ 
++	if (!clp->cl_principal && (clp->cl_flavor >= RPC_AUTH_GSS_KRB5)) {
++		status = nfserr_cb_path_down;
++		goto out_err;
++	}
++
+ 	/* Initialize address */
+ 	memset(&addr, 0, sizeof(addr));
+ 	addr.sin_family = AF_INET;
+diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
+index 6f0ee1b84a4f..c39a21040dcb 100644
+--- a/include/linux/sunrpc/clnt.h
++++ b/include/linux/sunrpc/clnt.h
+@@ -58,6 +58,7 @@ struct rpc_clnt {
+ 	struct rpc_timeout	cl_timeout_default;
+ 	struct rpc_program *	cl_program;
+ 	char			cl_inline_name[32];
++	char			*cl_principal;	/* target to authenticate to */
+ };
+ 
+ /*
+@@ -108,6 +109,7 @@ struct rpc_create_args {
+ 	u32			version;
+ 	rpc_authflavor_t	authflavor;
+ 	unsigned long		flags;
++	char			*client_name;
+ };
+ 
+ /* Values for "flags" field */
+diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
+index 4895c341e46d..347f2a25abb6 100644
+--- a/net/sunrpc/clnt.c
++++ b/net/sunrpc/clnt.c
+@@ -197,6 +197,12 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
+ 
+ 	clnt->cl_rtt = &clnt->cl_rtt_default;
+ 	rpc_init_rtt(&clnt->cl_rtt_default, clnt->cl_timeout->to_initval);
++	clnt->cl_principal = NULL;
++	if (args->client_name) {
++		clnt->cl_principal = kstrdup(args->client_name, GFP_KERNEL);
++		if (!clnt->cl_principal)
++			goto out_no_principal;
++	}
+ 
+ 	kref_init(&clnt->cl_kref);
+ 
+@@ -226,6 +232,8 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
+ 		rpc_put_mount();
+ 	}
+ out_no_path:
++	kfree(clnt->cl_principal);
++out_no_principal:
+ 	rpc_free_iostats(clnt->cl_metrics);
+ out_no_stats:
+ 	if (clnt->cl_server != clnt->cl_inline_name)
+@@ -354,6 +362,11 @@ rpc_clone_client(struct rpc_clnt *clnt)
+ 	new->cl_metrics = rpc_alloc_iostats(clnt);
+ 	if (new->cl_metrics == NULL)
+ 		goto out_no_stats;
++	if (clnt->cl_principal) {
++		new->cl_principal = kstrdup(clnt->cl_principal, GFP_KERNEL);
++		if (new->cl_principal == NULL)
++			goto out_no_principal;
++	}
+ 	kref_init(&new->cl_kref);
+ 	err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name);
+ 	if (err != 0)
+@@ -366,6 +379,8 @@ rpc_clone_client(struct rpc_clnt *clnt)
+ 	rpciod_up();
+ 	return new;
+ out_no_path:
++	kfree(new->cl_principal);
++out_no_principal:
+ 	rpc_free_iostats(new->cl_metrics);
+ out_no_stats:
+ 	kfree(new);
+@@ -417,6 +432,7 @@ rpc_free_client(struct kref *kref)
+ out_free:
+ 	rpc_unregister_client(clnt);
+ 	rpc_free_iostats(clnt->cl_metrics);
++	kfree(clnt->cl_principal);
+ 	clnt->cl_metrics = NULL;
+ 	xprt_put(clnt->cl_xprt);
+ 	rpciod_down();

commit 68e76ad0baf8f5d5060377c2423ee6eed5c63057
+Author: Olga Kornievskaia 
+Date:   Tue Dec 23 16:17:15 2008 -0500
+
+    nfsd: pass client principal name in rsc downcall
+    
+    Two principals are involved in krb5 authentication: the target, who we
+    authenticate *to* (normally the name of the server, like
+    nfs/server.citi.umich.edu@CITI.UMICH.EDU), and the source, we we
+    authenticate *as* (normally a user, like bfields@UMICH.EDU)
+    
+    In the case of NFSv4 callbacks, the target of the callback should be the
+    source of the client's setclientid call, and the source should be the
+    nfs server's own principal.
+    
+    Therefore we allow svcgssd to pass down the name of the principal that
+    just authenticated, so that on setclientid we can store that principal
+    name with the new client, to be used later on callbacks.
+    
+    Signed-off-by: Olga Kornievskaia 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 1a052ac2bde9..f3b9a8d064f3 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -54,6 +54,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #define NFSDDBG_FACILITY                NFSDDBG_PROC
+ 
+@@ -377,6 +378,7 @@ free_client(struct nfs4_client *clp)
+ 	shutdown_callback_client(clp);
+ 	if (clp->cl_cred.cr_group_info)
+ 		put_group_info(clp->cl_cred.cr_group_info);
++	kfree(clp->cl_principal);
+ 	kfree(clp->cl_name.data);
+ 	kfree(clp);
+ }
+@@ -696,6 +698,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	unsigned int 		strhashval;
+ 	struct nfs4_client	*conf, *unconf, *new;
+ 	__be32 			status;
++	char			*princ;
+ 	char                    dname[HEXDIR_LEN];
+ 	
+ 	if (!check_name(clname))
+@@ -783,6 +786,14 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	}
+ 	copy_verf(new, &clverifier);
+ 	new->cl_addr = sin->sin_addr.s_addr;
++	princ = svc_gss_principal(rqstp);
++	if (princ) {
++		new->cl_principal = kstrdup(princ, GFP_KERNEL);
++		if (new->cl_principal == NULL) {
++			free_client(new);
++			goto out;
++		}
++	}
+ 	copy_cred(&new->cl_cred, &rqstp->rq_cred);
+ 	gen_confirm(new);
+ 	gen_callback(new, setclid);
+diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
+index d0fe2e378452..ce7cbf4b7c93 100644
+--- a/include/linux/nfsd/state.h
++++ b/include/linux/nfsd/state.h
+@@ -124,6 +124,7 @@ struct nfs4_client {
+ 	nfs4_verifier		cl_verifier; 	/* generated by client */
+ 	time_t                  cl_time;        /* time of last lease renewal */
+ 	__be32			cl_addr; 	/* client ipaddress */
++	char			*cl_principal;	/* setclientid principal name */
+ 	struct svc_cred		cl_cred; 	/* setclientid principal */
+ 	clientid_t		cl_clientid;	/* generated by server */
+ 	nfs4_verifier		cl_confirm;	/* generated by server */
+diff --git a/include/linux/sunrpc/svcauth_gss.h b/include/linux/sunrpc/svcauth_gss.h
+index c9165d9771a8..ca7d725861fc 100644
+--- a/include/linux/sunrpc/svcauth_gss.h
++++ b/include/linux/sunrpc/svcauth_gss.h
+@@ -20,6 +20,7 @@ int gss_svc_init(void);
+ void gss_svc_shutdown(void);
+ int svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name);
+ u32 svcauth_gss_flavor(struct auth_domain *dom);
++char *svc_gss_principal(struct svc_rqst *);
+ 
+ #endif /* __KERNEL__ */
+ #endif /* _LINUX_SUNRPC_SVCAUTH_GSS_H */
+diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
+index 12803da95dc4..e9baa6ebb1dd 100644
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -332,6 +332,7 @@ struct rsc {
+ 	struct svc_cred		cred;
+ 	struct gss_svc_seq_data	seqdata;
+ 	struct gss_ctx		*mechctx;
++	char			*client_name;
+ };
+ 
+ static struct cache_head *rsc_table[RSC_HASHMAX];
+@@ -346,6 +347,7 @@ static void rsc_free(struct rsc *rsci)
+ 		gss_delete_sec_context(&rsci->mechctx);
+ 	if (rsci->cred.cr_group_info)
+ 		put_group_info(rsci->cred.cr_group_info);
++	kfree(rsci->client_name);
+ }
+ 
+ static void rsc_put(struct kref *ref)
+@@ -383,6 +385,7 @@ rsc_init(struct cache_head *cnew, struct cache_head *ctmp)
+ 	tmp->handle.data = NULL;
+ 	new->mechctx = NULL;
+ 	new->cred.cr_group_info = NULL;
++	new->client_name = NULL;
+ }
+ 
+ static void
+@@ -397,6 +400,8 @@ update_rsc(struct cache_head *cnew, struct cache_head *ctmp)
+ 	spin_lock_init(&new->seqdata.sd_lock);
+ 	new->cred = tmp->cred;
+ 	tmp->cred.cr_group_info = NULL;
++	new->client_name = tmp->client_name;
++	tmp->client_name = NULL;
+ }
+ 
+ static struct cache_head *
+@@ -486,6 +491,15 @@ static int rsc_parse(struct cache_detail *cd,
+ 		status = gss_import_sec_context(buf, len, gm, &rsci.mechctx);
+ 		if (status)
+ 			goto out;
++
++		/* get client name */
++		len = qword_get(&mesg, buf, mlen);
++		if (len > 0) {
++			rsci.client_name = kstrdup(buf, GFP_KERNEL);
++			if (!rsci.client_name)
++				goto out;
++		}
++
+ 	}
+ 	rsci.h.expiry_time = expiry;
+ 	rscp = rsc_update(&rsci, rscp);
+@@ -913,6 +927,15 @@ struct gss_svc_data {
+ 	struct rsc			*rsci;
+ };
+ 
++char *svc_gss_principal(struct svc_rqst *rqstp)
++{
++	struct gss_svc_data *gd = (struct gss_svc_data *)rqstp->rq_auth_data;
++
++	if (gd && gd->rsci)
++		return gd->rsci->client_name;
++	return NULL;
++}
++
+ static int
+ svcauth_gss_set_client(struct svc_rqst *rqstp)
+ {

commit 34769fc488b463cb753fc632f8f5ba56c918b7cb
+Author: J. Bruce Fields 
+Date:   Tue Dec 23 16:16:37 2008 -0500
+
+    rpc: implement new upcall
+    
+    Implement the new upcall.  We decide which version of the upcall gssd
+    will use (new or old), by creating both pipes (the new one named "gssd",
+    the old one named after the mechanism (e.g., "krb5")), and then waiting
+    to see which version gssd actually opens.
+    
+    We don't permit pipes of the two different types to be opened at once.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index fe06acd6029b..153b3e11e61a 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -72,7 +72,13 @@ struct gss_auth {
+ 	struct gss_api_mech *mech;
+ 	enum rpc_gss_svc service;
+ 	struct rpc_clnt *client;
+-	struct dentry *dentry;
++	/*
++	 * There are two upcall pipes; dentry[1], named "gssd", is used
++	 * for the new text-based upcall; dentry[0] is named after the
++	 * mechanism (for example, "krb5") and exists for
++	 * backwards-compatibility with older gssd's.
++	 */
++	struct dentry *dentry[2];
+ };
+ 
+ /* pipe_version >= 0 if and only if someone has a pipe open. */
+@@ -83,7 +89,8 @@ static struct rpc_wait_queue pipe_version_rpc_waitqueue;
+ static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue);
+ 
+ static void gss_free_ctx(struct gss_cl_ctx *);
+-static struct rpc_pipe_ops gss_upcall_ops;
++static struct rpc_pipe_ops gss_upcall_ops_v0;
++static struct rpc_pipe_ops gss_upcall_ops_v1;
+ 
+ static inline struct gss_cl_ctx *
+ gss_get_ctx(struct gss_cl_ctx *ctx)
+@@ -227,6 +234,7 @@ gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct
+ 	return p;
+ }
+ 
++#define UPCALL_BUF_LEN 128
+ 
+ struct gss_upcall_msg {
+ 	atomic_t count;
+@@ -238,6 +246,7 @@ struct gss_upcall_msg {
+ 	struct rpc_wait_queue rpc_waitqueue;
+ 	wait_queue_head_t waitqueue;
+ 	struct gss_cl_ctx *ctx;
++	char databuf[UPCALL_BUF_LEN];
+ };
+ 
+ static int get_pipe_version(void)
+@@ -247,7 +256,7 @@ static int get_pipe_version(void)
+ 	spin_lock(&pipe_version_lock);
+ 	if (pipe_version >= 0) {
+ 		atomic_inc(&pipe_users);
+-		ret = 0;
++		ret = pipe_version;
+ 	} else
+ 		ret = -EAGAIN;
+ 	spin_unlock(&pipe_version_lock);
+@@ -353,6 +362,29 @@ gss_upcall_callback(struct rpc_task *task)
+ 	gss_release_msg(gss_msg);
+ }
+ 
++static void gss_encode_v0_msg(struct gss_upcall_msg *gss_msg)
++{
++	gss_msg->msg.data = &gss_msg->uid;
++	gss_msg->msg.len = sizeof(gss_msg->uid);
++}
++
++static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg)
++{
++	gss_msg->msg.len = sprintf(gss_msg->databuf, "mech=%s uid=%d\n",
++				   gss_msg->auth->mech->gm_name,
++				   gss_msg->uid);
++	gss_msg->msg.data = gss_msg->databuf;
++	BUG_ON(gss_msg->msg.len > UPCALL_BUF_LEN);
++}
++
++static void gss_encode_msg(struct gss_upcall_msg *gss_msg)
++{
++	if (pipe_version == 0)
++		gss_encode_v0_msg(gss_msg);
++	else /* pipe_version == 1 */
++		gss_encode_v1_msg(gss_msg);
++}
++
+ static inline struct gss_upcall_msg *
+ gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid)
+ {
+@@ -367,15 +399,14 @@ gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid)
+ 		kfree(gss_msg);
+ 		return ERR_PTR(vers);
+ 	}
+-	gss_msg->inode = RPC_I(gss_auth->dentry->d_inode);
++	gss_msg->inode = RPC_I(gss_auth->dentry[vers]->d_inode);
+ 	INIT_LIST_HEAD(&gss_msg->list);
+ 	rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
+ 	init_waitqueue_head(&gss_msg->waitqueue);
+ 	atomic_set(&gss_msg->count, 1);
+-	gss_msg->msg.data = &gss_msg->uid;
+-	gss_msg->msg.len = sizeof(gss_msg->uid);
+ 	gss_msg->uid = uid;
+ 	gss_msg->auth = gss_auth;
++	gss_encode_msg(gss_msg);
+ 	return gss_msg;
+ }
+ 
+@@ -613,18 +644,36 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
+ 	return err;
+ }
+ 
+-static int
+-gss_pipe_open(struct inode *inode)
++static int gss_pipe_open(struct inode *inode, int new_version)
+ {
++	int ret = 0;
++
+ 	spin_lock(&pipe_version_lock);
+ 	if (pipe_version < 0) {
+-		pipe_version = 0;
++		/* First open of any gss pipe determines the version: */
++		pipe_version = new_version;
+ 		rpc_wake_up(&pipe_version_rpc_waitqueue);
+ 		wake_up(&pipe_version_waitqueue);
++	} else if (pipe_version != new_version) {
++		/* Trying to open a pipe of a different version */
++		ret = -EBUSY;
++		goto out;
+ 	}
+ 	atomic_inc(&pipe_users);
++out:
+ 	spin_unlock(&pipe_version_lock);
+-	return 0;
++	return ret;
++
++}
++
++static int gss_pipe_open_v0(struct inode *inode)
++{
++	return gss_pipe_open(inode, 0);
++}
++
++static int gss_pipe_open_v1(struct inode *inode)
++{
++	return gss_pipe_open(inode, 1);
+ }
+ 
+ static void
+@@ -702,20 +751,38 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
+ 	atomic_set(&auth->au_count, 1);
+ 	kref_init(&gss_auth->kref);
+ 
+-	gss_auth->dentry = rpc_mkpipe(clnt->cl_dentry, gss_auth->mech->gm_name,
+-			clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
+-	if (IS_ERR(gss_auth->dentry)) {
+-		err = PTR_ERR(gss_auth->dentry);
++	/*
++	 * Note: if we created the old pipe first, then someone who
++	 * examined the directory at the right moment might conclude
++	 * that we supported only the old pipe.  So we instead create
++	 * the new pipe first.
++	 */
++	gss_auth->dentry[1] = rpc_mkpipe(clnt->cl_dentry,
++					 "gssd",
++					 clnt, &gss_upcall_ops_v1,
++					 RPC_PIPE_WAIT_FOR_OPEN);
++	if (IS_ERR(gss_auth->dentry[1])) {
++		err = PTR_ERR(gss_auth->dentry[1]);
+ 		goto err_put_mech;
+ 	}
+ 
++	gss_auth->dentry[0] = rpc_mkpipe(clnt->cl_dentry,
++					 gss_auth->mech->gm_name,
++					 clnt, &gss_upcall_ops_v0,
++					 RPC_PIPE_WAIT_FOR_OPEN);
++	if (IS_ERR(gss_auth->dentry[0])) {
++		err = PTR_ERR(gss_auth->dentry[0]);
++		goto err_unlink_pipe_1;
++	}
+ 	err = rpcauth_init_credcache(auth);
+ 	if (err)
+-		goto err_unlink_pipe;
++		goto err_unlink_pipe_0;
+ 
+ 	return auth;
+-err_unlink_pipe:
+-	rpc_unlink(gss_auth->dentry);
++err_unlink_pipe_0:
++	rpc_unlink(gss_auth->dentry[0]);
++err_unlink_pipe_1:
++	rpc_unlink(gss_auth->dentry[1]);
+ err_put_mech:
+ 	gss_mech_put(gss_auth->mech);
+ err_free:
+@@ -728,7 +795,8 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
+ static void
+ gss_free(struct gss_auth *gss_auth)
+ {
+-	rpc_unlink(gss_auth->dentry);
++	rpc_unlink(gss_auth->dentry[1]);
++	rpc_unlink(gss_auth->dentry[0]);
+ 	gss_mech_put(gss_auth->mech);
+ 
+ 	kfree(gss_auth);
+@@ -1419,11 +1487,19 @@ static const struct rpc_credops gss_nullops = {
+ 	.crunwrap_resp	= gss_unwrap_resp,
+ };
+ 
+-static struct rpc_pipe_ops gss_upcall_ops = {
++static struct rpc_pipe_ops gss_upcall_ops_v0 = {
++	.upcall		= gss_pipe_upcall,
++	.downcall	= gss_pipe_downcall,
++	.destroy_msg	= gss_pipe_destroy_msg,
++	.open_pipe	= gss_pipe_open_v0,
++	.release_pipe	= gss_pipe_release,
++};
++
++static struct rpc_pipe_ops gss_upcall_ops_v1 = {
+ 	.upcall		= gss_pipe_upcall,
+ 	.downcall	= gss_pipe_downcall,
+ 	.destroy_msg	= gss_pipe_destroy_msg,
+-	.open_pipe	= gss_pipe_open,
++	.open_pipe	= gss_pipe_open_v1,
+ 	.release_pipe	= gss_pipe_release,
+ };
+ 

commit 5b7ddd4a7b19f913901140ef7807dbf5e2b301cd
+Author: J. Bruce Fields 
+Date:   Tue Dec 23 16:15:44 2008 -0500
+
+    rpc: store pointer to pipe inode in gss upcall message
+    
+    Keep a pointer to the inode that the message is queued on in the struct
+    gss_upcall_msg.  This will be convenient, especially after we have a
+    choice of two pipes that an upcall could be queued on.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index e451d104a434..fe06acd6029b 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -234,6 +234,7 @@ struct gss_upcall_msg {
+ 	struct rpc_pipe_msg msg;
+ 	struct list_head list;
+ 	struct gss_auth *auth;
++	struct rpc_inode *inode;
+ 	struct rpc_wait_queue rpc_waitqueue;
+ 	wait_queue_head_t waitqueue;
+ 	struct gss_cl_ctx *ctx;
+@@ -296,8 +297,8 @@ __gss_find_upcall(struct rpc_inode *rpci, uid_t uid)
+ static inline struct gss_upcall_msg *
+ gss_add_msg(struct gss_auth *gss_auth, struct gss_upcall_msg *gss_msg)
+ {
+-	struct inode *inode = gss_auth->dentry->d_inode;
+-	struct rpc_inode *rpci = RPC_I(inode);
++	struct rpc_inode *rpci = gss_msg->inode;
++	struct inode *inode = &rpci->vfs_inode;
+ 	struct gss_upcall_msg *old;
+ 
+ 	spin_lock(&inode->i_lock);
+@@ -323,8 +324,7 @@ __gss_unhash_msg(struct gss_upcall_msg *gss_msg)
+ static void
+ gss_unhash_msg(struct gss_upcall_msg *gss_msg)
+ {
+-	struct gss_auth *gss_auth = gss_msg->auth;
+-	struct inode *inode = gss_auth->dentry->d_inode;
++	struct inode *inode = &gss_msg->inode->vfs_inode;
+ 
+ 	if (list_empty(&gss_msg->list))
+ 		return;
+@@ -340,7 +340,7 @@ gss_upcall_callback(struct rpc_task *task)
+ 	struct gss_cred *gss_cred = container_of(task->tk_msg.rpc_cred,
+ 			struct gss_cred, gc_base);
+ 	struct gss_upcall_msg *gss_msg = gss_cred->gc_upcall;
+-	struct inode *inode = gss_msg->auth->dentry->d_inode;
++	struct inode *inode = &gss_msg->inode->vfs_inode;
+ 
+ 	spin_lock(&inode->i_lock);
+ 	if (gss_msg->ctx)
+@@ -367,6 +367,7 @@ gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid)
+ 		kfree(gss_msg);
+ 		return ERR_PTR(vers);
+ 	}
++	gss_msg->inode = RPC_I(gss_auth->dentry->d_inode);
+ 	INIT_LIST_HEAD(&gss_msg->list);
+ 	rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
+ 	init_waitqueue_head(&gss_msg->waitqueue);
+@@ -395,7 +396,8 @@ gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cr
+ 		return gss_new;
+ 	gss_msg = gss_add_msg(gss_auth, gss_new);
+ 	if (gss_msg == gss_new) {
+-		int res = rpc_queue_upcall(gss_auth->dentry->d_inode, &gss_new->msg);
++		struct inode *inode = &gss_new->inode->vfs_inode;
++		int res = rpc_queue_upcall(inode, &gss_new->msg);
+ 		if (res) {
+ 			gss_unhash_msg(gss_new);
+ 			gss_msg = ERR_PTR(res);
+@@ -426,7 +428,7 @@ gss_refresh_upcall(struct rpc_task *task)
+ 	struct gss_cred *gss_cred = container_of(cred,
+ 			struct gss_cred, gc_base);
+ 	struct gss_upcall_msg *gss_msg;
+-	struct inode *inode = gss_auth->dentry->d_inode;
++	struct inode *inode;
+ 	int err = 0;
+ 
+ 	dprintk("RPC: %5u gss_refresh_upcall for uid %u\n", task->tk_pid,
+@@ -444,6 +446,7 @@ gss_refresh_upcall(struct rpc_task *task)
+ 		err = PTR_ERR(gss_msg);
+ 		goto out;
+ 	}
++	inode = &gss_msg->inode->vfs_inode;
+ 	spin_lock(&inode->i_lock);
+ 	if (gss_cred->gc_upcall != NULL)
+ 		rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL);
+@@ -470,7 +473,7 @@ gss_refresh_upcall(struct rpc_task *task)
+ static inline int
+ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
+ {
+-	struct inode *inode = gss_auth->dentry->d_inode;
++	struct inode *inode;
+ 	struct rpc_cred *cred = &gss_cred->gc_base;
+ 	struct gss_upcall_msg *gss_msg;
+ 	DEFINE_WAIT(wait);
+@@ -492,6 +495,7 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
+ 		err = PTR_ERR(gss_msg);
+ 		goto out;
+ 	}
++	inode = &gss_msg->inode->vfs_inode;
+ 	for (;;) {
+ 		prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_INTERRUPTIBLE);
+ 		spin_lock(&inode->i_lock);

commit 79a3f20b641f9f93787ada49d1d7cfa98ee5a11e
+Author: J. Bruce Fields 
+Date:   Tue Dec 23 16:10:52 2008 -0500
+
+    rpc: use count of pipe openers to wait for first open
+    
+    Introduce a global variable pipe_version which will eventually be used
+    to keep track of which version of the upcall gssd is using.
+    
+    For now, though, it only keeps track of whether any pipe is open or not;
+    it is negative if not, zero if one is opened.  We use this to wait for
+    the first gssd to open a pipe.
+    
+    (Minor digression: note this waits only for the very first open of any
+    pipe, not for the first open of a pipe for a given auth; thus we still
+    need the RPC_PIPE_WAIT_FOR_OPEN behavior to wait for gssd to open new
+    pipes that pop up on subsequent mounts.)
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index 51aa27d32b5a..e451d104a434 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -75,7 +75,12 @@ struct gss_auth {
+ 	struct dentry *dentry;
+ };
+ 
++/* pipe_version >= 0 if and only if someone has a pipe open. */
++static int pipe_version = -1;
+ static atomic_t pipe_users = ATOMIC_INIT(0);
++static DEFINE_SPINLOCK(pipe_version_lock);
++static struct rpc_wait_queue pipe_version_rpc_waitqueue;
++static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue);
+ 
+ static void gss_free_ctx(struct gss_cl_ctx *);
+ static struct rpc_pipe_ops gss_upcall_ops;
+@@ -234,12 +239,34 @@ struct gss_upcall_msg {
+ 	struct gss_cl_ctx *ctx;
+ };
+ 
++static int get_pipe_version(void)
++{
++	int ret;
++
++	spin_lock(&pipe_version_lock);
++	if (pipe_version >= 0) {
++		atomic_inc(&pipe_users);
++		ret = 0;
++	} else
++		ret = -EAGAIN;
++	spin_unlock(&pipe_version_lock);
++	return ret;
++}
++
++static void put_pipe_version(void)
++{
++	if (atomic_dec_and_lock(&pipe_users, &pipe_version_lock)) {
++		pipe_version = -1;
++		spin_unlock(&pipe_version_lock);
++	}
++}
++
+ static void
+ gss_release_msg(struct gss_upcall_msg *gss_msg)
+ {
+ 	if (!atomic_dec_and_test(&gss_msg->count))
+ 		return;
+-	atomic_dec(&pipe_users);
++	put_pipe_version();
+ 	BUG_ON(!list_empty(&gss_msg->list));
+ 	if (gss_msg->ctx != NULL)
+ 		gss_put_ctx(gss_msg->ctx);
+@@ -330,11 +357,16 @@ static inline struct gss_upcall_msg *
+ gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid)
+ {
+ 	struct gss_upcall_msg *gss_msg;
++	int vers;
+ 
+ 	gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS);
+ 	if (gss_msg == NULL)
+ 		return ERR_PTR(-ENOMEM);
+-	atomic_inc(&pipe_users);
++	vers = get_pipe_version();
++	if (vers < 0) {
++		kfree(gss_msg);
++		return ERR_PTR(vers);
++	}
+ 	INIT_LIST_HEAD(&gss_msg->list);
+ 	rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
+ 	init_waitqueue_head(&gss_msg->waitqueue);
+@@ -400,6 +432,14 @@ gss_refresh_upcall(struct rpc_task *task)
+ 	dprintk("RPC: %5u gss_refresh_upcall for uid %u\n", task->tk_pid,
+ 								cred->cr_uid);
+ 	gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred);
++	if (IS_ERR(gss_msg) == -EAGAIN) {
++		/* XXX: warning on the first, under the assumption we
++		 * shouldn't normally hit this case on a refresh. */
++		warn_gssd();
++		task->tk_timeout = 15*HZ;
++		rpc_sleep_on(&pipe_version_rpc_waitqueue, task, NULL);
++		return 0;
++	}
+ 	if (IS_ERR(gss_msg)) {
+ 		err = PTR_ERR(gss_msg);
+ 		goto out;
+@@ -437,7 +477,17 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
+ 	int err = 0;
+ 
+ 	dprintk("RPC:       gss_upcall for uid %u\n", cred->cr_uid);
++retry:
+ 	gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred);
++	if (PTR_ERR(gss_msg) == -EAGAIN) {
++		err = wait_event_interruptible_timeout(pipe_version_waitqueue,
++				pipe_version >= 0, 15*HZ);
++		if (err)
++			goto out;
++		if (pipe_version < 0)
++			warn_gssd();
++		goto retry;
++	}
+ 	if (IS_ERR(gss_msg)) {
+ 		err = PTR_ERR(gss_msg);
+ 		goto out;
+@@ -562,7 +612,14 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
+ static int
+ gss_pipe_open(struct inode *inode)
+ {
++	spin_lock(&pipe_version_lock);
++	if (pipe_version < 0) {
++		pipe_version = 0;
++		rpc_wake_up(&pipe_version_rpc_waitqueue);
++		wake_up(&pipe_version_waitqueue);
++	}
+ 	atomic_inc(&pipe_users);
++	spin_unlock(&pipe_version_lock);
+ 	return 0;
+ }
+ 
+@@ -586,7 +643,7 @@ gss_pipe_release(struct inode *inode)
+ 	}
+ 	spin_unlock(&inode->i_lock);
+ 
+-	atomic_dec(&pipe_users);
++	put_pipe_version();
+ }
+ 
+ static void
+@@ -1379,6 +1436,7 @@ static int __init init_rpcsec_gss(void)
+ 	err = gss_svc_init();
+ 	if (err)
+ 		goto out_unregister;
++	rpc_init_wait_queue(&pipe_version_rpc_waitqueue, "gss pipe version");
+ 	return 0;
+ out_unregister:
+ 	rpcauth_unregister(&authgss_ops);

commit cf81939d6fcdf381fcb069d780c29eceb516bccd
+Author: J. Bruce Fields 
+Date:   Tue Dec 23 16:10:19 2008 -0500
+
+    rpc: track number of users of the gss upcall pipe
+    
+    Keep a count of the number of pipes open plus the number of messages on
+    a pipe.  This count isn't used yet.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index bc512fff8a41..51aa27d32b5a 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -75,6 +75,8 @@ struct gss_auth {
+ 	struct dentry *dentry;
+ };
+ 
++static atomic_t pipe_users = ATOMIC_INIT(0);
++
+ static void gss_free_ctx(struct gss_cl_ctx *);
+ static struct rpc_pipe_ops gss_upcall_ops;
+ 
+@@ -237,6 +239,7 @@ gss_release_msg(struct gss_upcall_msg *gss_msg)
+ {
+ 	if (!atomic_dec_and_test(&gss_msg->count))
+ 		return;
++	atomic_dec(&pipe_users);
+ 	BUG_ON(!list_empty(&gss_msg->list));
+ 	if (gss_msg->ctx != NULL)
+ 		gss_put_ctx(gss_msg->ctx);
+@@ -331,6 +334,7 @@ gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid)
+ 	gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS);
+ 	if (gss_msg == NULL)
+ 		return ERR_PTR(-ENOMEM);
++	atomic_inc(&pipe_users);
+ 	INIT_LIST_HEAD(&gss_msg->list);
+ 	rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
+ 	init_waitqueue_head(&gss_msg->waitqueue);
+@@ -555,6 +559,13 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
+ 	return err;
+ }
+ 
++static int
++gss_pipe_open(struct inode *inode)
++{
++	atomic_inc(&pipe_users);
++	return 0;
++}
++
+ static void
+ gss_pipe_release(struct inode *inode)
+ {
+@@ -574,6 +585,8 @@ gss_pipe_release(struct inode *inode)
+ 		spin_lock(&inode->i_lock);
+ 	}
+ 	spin_unlock(&inode->i_lock);
++
++	atomic_dec(&pipe_users);
+ }
+ 
+ static void
+@@ -1349,6 +1362,7 @@ static struct rpc_pipe_ops gss_upcall_ops = {
+ 	.upcall		= gss_pipe_upcall,
+ 	.downcall	= gss_pipe_downcall,
+ 	.destroy_msg	= gss_pipe_destroy_msg,
++	.open_pipe	= gss_pipe_open,
+ 	.release_pipe	= gss_pipe_release,
+ };
+ 

commit e712804ae4bd858bd89272aa3fc1a577294c0940
+Author: J. Bruce Fields 
+Date:   Tue Dec 23 16:09:47 2008 -0500
+
+    rpc: call release_pipe only on last close
+    
+    I can't see any reason we need to call this until either the kernel or
+    the last gssd closes the pipe.
+    
+    Also, this allows to guarantee that open_pipe and release_pipe are
+    called strictly in pairs; open_pipe on gssd's first open, release_pipe
+    on gssd's last close (or on the close of the kernel side of the pipe, if
+    that comes first).
+    
+    That will make it very easy for the gss code to keep track of which
+    pipes gssd is using.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
+index c9b57f47108c..3105efbb182d 100644
+--- a/net/sunrpc/rpc_pipe.c
++++ b/net/sunrpc/rpc_pipe.c
+@@ -126,13 +126,14 @@ rpc_close_pipes(struct inode *inode)
+ {
+ 	struct rpc_inode *rpci = RPC_I(inode);
+ 	struct rpc_pipe_ops *ops;
++	int need_release;
+ 
+ 	mutex_lock(&inode->i_mutex);
+ 	ops = rpci->ops;
+ 	if (ops != NULL) {
+ 		LIST_HEAD(free_list);
+-
+ 		spin_lock(&inode->i_lock);
++		need_release = rpci->nreaders != 0 || rpci->nwriters != 0;
+ 		rpci->nreaders = 0;
+ 		list_splice_init(&rpci->in_upcall, &free_list);
+ 		list_splice_init(&rpci->pipe, &free_list);
+@@ -141,7 +142,7 @@ rpc_close_pipes(struct inode *inode)
+ 		spin_unlock(&inode->i_lock);
+ 		rpc_purge_list(rpci, &free_list, ops->destroy_msg, -EPIPE);
+ 		rpci->nwriters = 0;
+-		if (ops->release_pipe)
++		if (need_release && ops->release_pipe)
+ 			ops->release_pipe(inode);
+ 		cancel_delayed_work_sync(&rpci->queue_timeout);
+ 	}
+@@ -196,6 +197,7 @@ rpc_pipe_release(struct inode *inode, struct file *filp)
+ {
+ 	struct rpc_inode *rpci = RPC_I(inode);
+ 	struct rpc_pipe_msg *msg;
++	int last_close;
+ 
+ 	mutex_lock(&inode->i_mutex);
+ 	if (rpci->ops == NULL)
+@@ -222,7 +224,8 @@ rpc_pipe_release(struct inode *inode, struct file *filp)
+ 					rpci->ops->destroy_msg, -EAGAIN);
+ 		}
+ 	}
+-	if (rpci->ops->release_pipe)
++	last_close = rpci->nwriters == 0 && rpci->nreaders == 0;
++	if (last_close && rpci->ops->release_pipe)
+ 		rpci->ops->release_pipe(inode);
+ out:
+ 	mutex_unlock(&inode->i_mutex);

commit c381060869317b3c84430d4f54965d409cbfe65f
+Author: J. Bruce Fields 
+Date:   Tue Dec 23 16:08:32 2008 -0500
+
+    rpc: add an rpc_pipe_open method
+    
+    We want to transition to a new gssd upcall which is text-based and more
+    easily extensible.
+    
+    To simplify upgrades, as well as testing and debugging, it will help if
+    we can upgrade gssd (to a version which understands the new upcall)
+    without having to choose at boot (or module-load) time whether we want
+    the new or the old upcall.
+    
+    We will do this by providing two different pipes: one named, as
+    currently, after the mechanism (normally "krb5"), and supporting the
+    old upcall.  One named "gssd" and supporting the new upcall version.
+    
+    We allow gssd to indicate which version it supports by its choice of
+    which pipe to open.
+    
+    As we have no interest in supporting *simultaneous* use of both
+    versions, we'll forbid opening both pipes at the same time.
+    
+    So, add a new pipe_open callback to the rpc_pipefs api, which the gss
+    code can use to track which pipes have been open, and to refuse opens of
+    incompatible pipes.
+    
+    We only need this to be called on the first open of a given pipe.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h
+index 51b977a4ca20..cea764c2359f 100644
+--- a/include/linux/sunrpc/rpc_pipe_fs.h
++++ b/include/linux/sunrpc/rpc_pipe_fs.h
+@@ -15,6 +15,7 @@ struct rpc_pipe_ops {
+ 	ssize_t (*upcall)(struct file *, struct rpc_pipe_msg *, char __user *, size_t);
+ 	ssize_t (*downcall)(struct file *, const char __user *, size_t);
+ 	void (*release_pipe)(struct inode *);
++	int (*open_pipe)(struct inode *);
+ 	void (*destroy_msg)(struct rpc_pipe_msg *);
+ };
+ 
+diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
+index 55b2049834c4..c9b57f47108c 100644
+--- a/net/sunrpc/rpc_pipe.c
++++ b/net/sunrpc/rpc_pipe.c
+@@ -169,16 +169,24 @@ static int
+ rpc_pipe_open(struct inode *inode, struct file *filp)
+ {
+ 	struct rpc_inode *rpci = RPC_I(inode);
++	int first_open;
+ 	int res = -ENXIO;
+ 
+ 	mutex_lock(&inode->i_mutex);
+-	if (rpci->ops != NULL) {
+-		if (filp->f_mode & FMODE_READ)
+-			rpci->nreaders ++;
+-		if (filp->f_mode & FMODE_WRITE)
+-			rpci->nwriters ++;
+-		res = 0;
++	if (rpci->ops == NULL)
++		goto out;
++	first_open = rpci->nreaders == 0 && rpci->nwriters == 0;
++	if (first_open && rpci->ops->open_pipe) {
++		res = rpci->ops->open_pipe(inode);
++		if (res)
++			goto out;
+ 	}
++	if (filp->f_mode & FMODE_READ)
++		rpci->nreaders++;
++	if (filp->f_mode & FMODE_WRITE)
++		rpci->nwriters++;
++	res = 0;
++out:
+ 	mutex_unlock(&inode->i_mutex);
+ 	return res;
+ }
+@@ -748,7 +756,7 @@ rpc_rmdir(struct dentry *dentry)
+  * @name: name of pipe
+  * @private: private data to associate with the pipe, for the caller's use
+  * @ops: operations defining the behavior of the pipe: upcall, downcall,
+- *	release_pipe, and destroy_msg.
++ *	release_pipe, open_pipe, and destroy_msg.
+  * @flags: rpc_inode flags
+  *
+  * Data is made available for userspace to read by calls to

commit db75b3d6b5b0dad29860370618ea94d2726641b4
+Author: J. Bruce Fields 
+Date:   Tue Dec 23 16:07:13 2008 -0500
+
+    rpc: minor gss_alloc_msg cleanup
+    
+    I want to add a little more code here, so it'll be convenient to have
+    this flatter.
+    
+    Also, I'll want to add another error condition, so it'll be more
+    convenient to return -ENOMEM than NULL in the error case.  The only
+    caller is already converting NULL to -ENOMEM anyway.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index 0fe35664c687..bc512fff8a41 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -329,16 +329,16 @@ gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid)
+ 	struct gss_upcall_msg *gss_msg;
+ 
+ 	gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS);
+-	if (gss_msg != NULL) {
+-		INIT_LIST_HEAD(&gss_msg->list);
+-		rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
+-		init_waitqueue_head(&gss_msg->waitqueue);
+-		atomic_set(&gss_msg->count, 1);
+-		gss_msg->msg.data = &gss_msg->uid;
+-		gss_msg->msg.len = sizeof(gss_msg->uid);
+-		gss_msg->uid = uid;
+-		gss_msg->auth = gss_auth;
+-	}
++	if (gss_msg == NULL)
++		return ERR_PTR(-ENOMEM);
++	INIT_LIST_HEAD(&gss_msg->list);
++	rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
++	init_waitqueue_head(&gss_msg->waitqueue);
++	atomic_set(&gss_msg->count, 1);
++	gss_msg->msg.data = &gss_msg->uid;
++	gss_msg->msg.len = sizeof(gss_msg->uid);
++	gss_msg->uid = uid;
++	gss_msg->auth = gss_auth;
+ 	return gss_msg;
+ }
+ 
+@@ -355,8 +355,8 @@ gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cr
+ 		uid = 0;
+ 
+ 	gss_new = gss_alloc_msg(gss_auth, uid);
+-	if (gss_new == NULL)
+-		return ERR_PTR(-ENOMEM);
++	if (IS_ERR(gss_new))
++		return gss_new;
+ 	gss_msg = gss_add_msg(gss_auth, gss_new);
+ 	if (gss_msg == gss_new) {
+ 		int res = rpc_queue_upcall(gss_auth->dentry->d_inode, &gss_new->msg);

commit b03568c32226163cb3588ea8993adb268ed497a5
+Author: J. Bruce Fields 
+Date:   Tue Dec 23 16:06:55 2008 -0500
+
+    rpc: factor out warning code from gss_pipe_destroy_msg
+    
+    We'll want to call this from elsewhere soon.  And this is a bit nicer
+    anyway.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index ea4567fae5dd..0fe35664c687 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -369,6 +369,18 @@ gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cr
+ 	return gss_msg;
+ }
+ 
++static void warn_gssd(void)
++{
++	static unsigned long ratelimit;
++	unsigned long now = jiffies;
++
++	if (time_after(now, ratelimit)) {
++		printk(KERN_WARNING "RPC: AUTH_GSS upcall timed out.\n"
++				"Please check user daemon is running.\n");
++		ratelimit = now + 15*HZ;
++	}
++}
++
+ static inline int
+ gss_refresh_upcall(struct rpc_task *task)
+ {
+@@ -568,21 +580,14 @@ static void
+ gss_pipe_destroy_msg(struct rpc_pipe_msg *msg)
+ {
+ 	struct gss_upcall_msg *gss_msg = container_of(msg, struct gss_upcall_msg, msg);
+-	static unsigned long ratelimit;
+ 
+ 	if (msg->errno < 0) {
+ 		dprintk("RPC:       gss_pipe_destroy_msg releasing msg %p\n",
+ 				gss_msg);
+ 		atomic_inc(&gss_msg->count);
+ 		gss_unhash_msg(gss_msg);
+-		if (msg->errno == -ETIMEDOUT) {
+-			unsigned long now = jiffies;
+-			if (time_after(now, ratelimit)) {
+-				printk(KERN_WARNING "RPC: AUTH_GSS upcall timed out.\n"
+-						    "Please check user daemon is running!\n");
+-				ratelimit = now + 15*HZ;
+-			}
+-		}
++		if (msg->errno == -ETIMEDOUT)
++			warn_gssd();
+ 		gss_release_msg(gss_msg);
+ 	}
+ }

commit 99db35636842ede13bf3b6bf1a8d8f4f1c4c93bf
+Author: J. Bruce Fields 
+Date:   Tue Dec 23 16:06:33 2008 -0500
+
+    rpc: remove unnecessary assignment
+    
+    We're just about to kfree() gss_auth, so there's no point to setting any
+    of its fields.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index cb19c9ded1fa..ea4567fae5dd 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -650,7 +650,6 @@ static void
+ gss_free(struct gss_auth *gss_auth)
+ {
+ 	rpc_unlink(gss_auth->dentry);
+-	gss_auth->dentry = NULL;
+ 	gss_mech_put(gss_auth->mech);
+ 
+ 	kfree(gss_auth);

commit a4f4d6df537368297a84e6b9444f403f99bf59f6
+Author: J. Bruce Fields 
+Date:   Mon Dec 8 18:24:18 2008 -0500
+
+    EXPORTFS: handle NULL returns from fh_to_dentry()/fh_to_parent()
+    
+    While 440037287c5 "[PATCH] switch all filesystems over to
+    d_obtain_alias" removed some cases where fh_to_dentry() and
+    fh_to_parent() could return NULL, there are still a few NULL returns
+    left in individual filesystems.  Thus it was a mistake for that commit
+    to remove the handling of NULL returns in the callers.
+    
+    Revert those parts of 440037287c5 which removed the NULL handling.
+    
+    (We could, alternatively, modify all implementations to return -ESTALE
+    instead of NULL, but that proves to require fixing a number of
+    filesystems, and in some cases it's arguably more natural to return
+    NULL.)
+    
+    Thanks to David for original patch and Linus, Christoph, and Hugh for
+    review.
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: David Howells 
+    Cc: Christoph Hellwig 
+    Cc: Hugh Dickins 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
+index 80246bad1b7f..890e01828817 100644
+--- a/fs/exportfs/expfs.c
++++ b/fs/exportfs/expfs.c
+@@ -367,6 +367,8 @@ struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid,
+ 	 * Try to get any dentry for the given file handle from the filesystem.
+ 	 */
+ 	result = nop->fh_to_dentry(mnt->mnt_sb, fid, fh_len, fileid_type);
++	if (!result)
++		result = ERR_PTR(-ESTALE);
+ 	if (IS_ERR(result))
+ 		return result;
+ 
+@@ -420,6 +422,8 @@ struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid,
+ 
+ 		target_dir = nop->fh_to_parent(mnt->mnt_sb, fid,
+ 				fh_len, fileid_type);
++		if (!target_dir)
++			goto err_result;
+ 		err = PTR_ERR(target_dir);
+ 		if (IS_ERR(target_dir))
+ 			goto err_result;

commit e4625eb826de4f6774ee602c442ba23b686bdcc7
+Author: J. Bruce Fields 
+Date:   Mon Nov 24 10:32:46 2008 -0600
+
+    nfsd: use of unitialized list head on error exit in nfs4recover.c
+    
+    Thanks to Matthew Dodd for this bug report:
+    
+    A file label issue while running SELinux in MLS mode provoked the
+    following bug, which is a result of use before init on a 'struct list_head'.
+    
+    In nfsd4_list_rec_dir() if the call to dentry_open() fails the 'goto
+    out' skips INIT_LIST_HEAD() which results in the normally improbable
+    case where list_entry() returns NULL.
+    
+    Trace follows.
+    
+    NFSD: Using /var/lib/nfs/v4recovery as the NFSv4 state recovery directory
+    SELinux:  Context unconfined_t:object_r:var_lib_nfs_t:s0 is not valid
+    (left unmapped).
+    type=1400 audit(1227298063.609:282): avc:  denied  { read } for
+    pid=1890 comm="rpc.nfsd" name="v4recovery" dev=dm-0 ino=148726
+    scontext=system_u:system_r:nfsd_t:s0-s15:c0.c1023
+    tcontext=system_u:object_r:unlabeled_t:s15:c0.c1023 tclass=dir
+    BUG: unable to handle kernel NULL pointer dereference at 00000004
+    IP: [] list_del+0x6/0x60
+    *pde = 0d9ce067 *pte = 00000000
+    Oops: 0000 [#1] SMP
+    Modules linked in: nfsd lockd nfs_acl auth_rpcgss exportfs autofs4
+    sunrpc ipv6 dm_multipath scsi_dh ppdev parport_pc sg parport floppy
+    ata_piix pata_acpi ata_generic libata pcnet32 i2c_piix4 mii pcspkr
+    i2c_core dm_snapshot dm_zero dm_mirror dm_log dm_mod BusLogic sd_mod
+    scsi_mod crc_t10dif ext3 jbd mbcache uhci_hcd ohci_hcd ehci_hcd [last
+    unloaded: microcode]
+    
+    Pid: 1890, comm: rpc.nfsd Not tainted (2.6.27.5-37.fc9.i686 #1)
+    EIP: 0060:[] EFLAGS: 00010217 CPU: 0
+    EIP is at list_del+0x6/0x60
+    EAX: 00000000 EBX: 00000000 ECX: 00000000 EDX: cd99e480
+    ESI: cf9caed8 EDI: 00000000 EBP: cf9caebc ESP: cf9caeb8
+      DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
+    Process rpc.nfsd (pid: 1890, ti=cf9ca000 task=cf4de580 task.ti=cf9ca000)
+    Stack: 00000000 cf9caef0 d0a9f139 c0496d04 d0a9f217 fffffff3 00000000
+    00000000
+            00000000 00000000 cf32b220 00000000 00000008 00000801 cf9caefc
+    d0a9f193
+            00000000 cf9caf08 d0a9b6ea 00000000 cf9caf1c d0a874f2 cf9c3004
+    00000008
+    Call Trace:
+      [] ? nfsd4_list_rec_dir+0xf3/0x13a [nfsd]
+      [] ? do_path_lookup+0x12d/0x175
+      [] ? load_recdir+0x0/0x26 [nfsd]
+      [] ? nfsd4_recdir_load+0x13/0x34 [nfsd]
+      [] ? nfs4_state_start+0x2a/0xc5 [nfsd]
+      [] ? nfsd_svc+0x51/0xff [nfsd]
+      [] ? write_svc+0x0/0x1e [nfsd]
+      [] ? write_svc+0x1b/0x1e [nfsd]
+      [] ? nfsctl_transaction_write+0x3a/0x61 [nfsd]
+      [] ? sys_nfsservctl+0x116/0x154
+      [] ? putname+0x24/0x2f
+      [] ? putname+0x24/0x2f
+      [] ? do_sys_open+0xad/0xb7
+      [] ? filp_close+0x50/0x5a
+      [] ? sys_open+0x1e/0x26
+      [] ? syscall_call+0x7/0xb
+      [] ? init_cyrix+0x185/0x490
+      =======================
+    Code: 75 e1 8b 53 08 8d 4b 04 8d 46 04 e8 75 00 00 00 8b 53 10 8d 4b 0c
+    8d 46 0c e8 67 00 00 00 5b 5e 5f 5d c3 90 90 55 89 e5 53 89 c3 <8b> 40
+    04 8b 00 39 d8 74 16 50 53 68 3e d6 6f c0 6a 30 68 78 d6
+    EIP: [] list_del+0x6/0x60 SS:ESP 0068:cf9caeb8
+    ---[ end trace a89c4ad091c4ad53 ]---
+    
+    Cc: Matthew N. Dodd 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
+index bb93946ace22..b79ec930d9f1 100644
+--- a/fs/nfsd/nfs4recover.c
++++ b/fs/nfsd/nfs4recover.c
+@@ -225,12 +225,12 @@ nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
+ 		return 0;
+ 
+ 	nfs4_save_user(&uid, &gid);
++	INIT_LIST_HEAD(dentries);
+ 
+ 	filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY);
+ 	status = PTR_ERR(filp);
+ 	if (IS_ERR(filp))
+ 		goto out;
+-	INIT_LIST_HEAD(dentries);
+ 	status = vfs_readdir(filp, nfsd4_build_dentrylist, &dla);
+ 	fput(filp);
+ 	while (!list_empty(dentries)) {

commit 2c5e76158fcea6e3b9536a74efa7b5e2e846d374
+Author: J. Bruce Fields 
+Date:   Thu Nov 20 14:36:17 2008 -0600
+
+    nfsd: clean up grace period on early exit
+    
+    If nfsd was shut down before the grace period ended, we could end up
+    with a freed object still on grace_list.  Thanks to Jeff Moyer for
+    reporting the resulting list corruption warnings.
+    
+    Signed-off-by: J. Bruce Fields 
+    Tested-by: Jeff Moyer 
+
+diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
+index c631a83931ce..56b076736b56 100644
+--- a/fs/lockd/svc.c
++++ b/fs/lockd/svc.c
+@@ -181,6 +181,7 @@ lockd(void *vrqstp)
+ 	}
+ 	flush_signals(current);
+ 	cancel_delayed_work_sync(&grace_period_end);
++	locks_end_grace(&lockd_manager);
+ 	if (nlmsvc_ops)
+ 		nlmsvc_invalidate_all();
+ 	nlm_shutdown_hosts();
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index b0bebc552a11..1a052ac2bde9 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -3261,6 +3261,7 @@ nfs4_state_shutdown(void)
+ {
+ 	cancel_rearming_delayed_workqueue(laundry_wq, &laundromat_work);
+ 	destroy_workqueue(laundry_wq);
++	locks_end_grace(&nfsd4_manager);
+ 	nfs4_lock_state();
+ 	nfs4_release_reclaim();
+ 	__nfs4_state_shutdown();

commit 8d7c4203c681a3ec359eccff4e53bc8c0ccf403b
+Author: J. Bruce Fields 
+Date:   Thu Oct 30 13:48:33 2008 -0400
+
+    nfsd: fix failure to set eof in readdir in some situations
+    
+    Before 14f7dd632011bb89c035722edd6ea0d90ca6b078 "[PATCH] Copy XFS
+    readdir hack into nfsd code", readdir_cd->err was reset to eof before
+    each call to vfs_readdir; afterwards, it is set only once.  Similarly,
+    c002a6c7977320f95b5edede5ce4e0eeecf291ff "[PATCH] Optimise NFS readdir
+    hack slightly", can cause us to exit without nfserr_eof set.  Fix this.
+    
+    This ensures the "eof" bit is set when needed in readdir replies.  (The
+    particular case I saw was an nfsv4 readdir of an empty directory, which
+    returned with no entries (the protocol requires "." and ".." to be
+    filtered out), but with eof unset.)
+    
+    Cc: David Woodhouse 
+    Cc: Al Viro 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index 0bc56f6d9276..848a03e83a42 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -1912,6 +1912,7 @@ static int nfsd_buffered_readdir(struct file *file, filldir_t func,
+ 			de = (struct buffered_dirent *)((char *)de + reclen);
+ 		}
+ 		offset = vfs_llseek(file, 0, SEEK_CUR);
++		cdp->err = nfserr_eof;
+ 		if (!buf.full)
+ 			break;
+ 	}

commit 30bc4dfd3b64eb1fbefe2c63e30d8fc129273e20
+Author: J. Bruce Fields 
+Date:   Mon Oct 20 16:34:21 2008 -0400
+
+    nfsd: clean up expkey_parse error cases
+    
+    We might as well do all of these at the end.  Fix up a couple minor
+    style nits while we're there.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
+index 7ce2c6e4e23e..5cd882b8871a 100644
+--- a/fs/nfsd/export.c
++++ b/fs/nfsd/export.c
+@@ -99,7 +99,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
+ 	int fsidtype;
+ 	char *ep;
+ 	struct svc_expkey key;
+-	struct svc_expkey *ek;
++	struct svc_expkey *ek = NULL;
+ 
+ 	if (mesg[mlen-1] != '\n')
+ 		return -EINVAL;
+@@ -107,7 +107,8 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
+ 
+ 	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ 	err = -ENOMEM;
+-	if (!buf) goto out;
++	if (!buf)
++		goto out;
+ 
+ 	err = -EINVAL;
+ 	if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
+@@ -151,38 +152,34 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
+ 
+ 	/* now we want a pathname, or empty meaning NEGATIVE  */
+ 	err = -EINVAL;
+-	if ((len=qword_get(&mesg, buf, PAGE_SIZE)) < 0) {
+-		cache_put(&ek->h, &svc_expkey_cache);
++	len = qword_get(&mesg, buf, PAGE_SIZE);
++	if (len < 0)
+ 		goto out;
+-	}
+ 	dprintk("Path seems to be <%s>\n", buf);
+ 	err = 0;
+ 	if (len == 0) {
+ 		set_bit(CACHE_NEGATIVE, &key.h.flags);
+ 		ek = svc_expkey_update(&key, ek);
+-		if (ek)
+-			cache_put(&ek->h, &svc_expkey_cache);
+-		else err = -ENOMEM;
++		if (!ek)
++			err = -ENOMEM;
+ 	} else {
+ 		struct nameidata nd;
+ 		err = path_lookup(buf, 0, &nd);
+-		if (err) {
+-			cache_put(&ek->h, &svc_expkey_cache);
++		if (err)
+ 			goto out;
+-		}
+ 
+ 		dprintk("Found the path %s\n", buf);
+ 		key.ek_path = nd.path;
+ 
+ 		ek = svc_expkey_update(&key, ek);
+-		if (ek)
+-			cache_put(&ek->h, &svc_expkey_cache);
+-		else
++		if (!ek)
+ 			err = -ENOMEM;
+ 		path_put(&nd.path);
+ 	}
+ 	cache_flush();
+  out:
++	if (ek)
++		cache_put(&ek->h, &svc_expkey_cache);
+ 	if (dom)
+ 		auth_domain_put(dom);
+ 	kfree(buf);

commit 456018d791ff4ef03d610f72486c637056bcd749
+Author: J. Bruce Fields 
+Date:   Wed Oct 8 15:31:14 2008 -0400
+
+    NFS: Cleanup nfs_set_port
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
+index 5d2a5d3c4241..d212ee41caf2 100644
+--- a/fs/nfs/internal.h
++++ b/fs/nfs/internal.h
+@@ -285,16 +285,15 @@ unsigned int nfs_page_array_len(unsigned int base, size_t len)
+  */
+ static inline void nfs_set_port(struct sockaddr *sap, unsigned short port)
+ {
++	struct sockaddr_in *ap = (struct sockaddr_in *)sap;
++	struct sockaddr_in6 *ap6 = (struct sockaddr_in6 *)sap;
++
+ 	switch (sap->sa_family) {
+-	case AF_INET: {
+-	      struct sockaddr_in *ap = (struct sockaddr_in *)sap;
+-	      ap->sin_port = htons(port);
+-	      break;
+-	}
+-	case AF_INET6: {
+-	       struct sockaddr_in6 *ap = (struct sockaddr_in6 *)sap;
+-	       ap->sin6_port = htons(port);
+-	       break;
+-	}
++	case AF_INET:
++		ap->sin_port = htons(port);
++		break;
++	case AF_INET6:
++		ap6->sin6_port = htons(port);
++		break;
+ 	}
+ }

commit 107e0008dfb8bd6366bc8827f5bbbc0c1f795d2d
+Merge: 293739138580 67080c82361b
+Author: J. Bruce Fields 
+Date:   Wed Oct 8 18:22:18 2008 -0400
+
+    Merge branch 'from-tomtucker' into for-2.6.28
+

commit ea31a4437c59219bf3ea946d58984b01a45a289c
+Author: J. Bruce Fields 
+Date:   Wed Aug 20 16:10:23 2008 -0400
+
+    nfs: Fix misparsing of nfsv4 fs_locations attribute
+    
+    The code incorrectly assumes here that the server name (or ip address)
+    is null-terminated.  This can cause referrals to fail in some cases.
+    
+    Also support ipv6 addresses.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
+index 8d91bd88e310..5d2a5d3c4241 100644
+--- a/fs/nfs/internal.h
++++ b/fs/nfs/internal.h
+@@ -153,6 +153,7 @@ extern void nfs4_clear_inode(struct inode *);
+ void nfs_zap_acl_cache(struct inode *inode);
+ 
+ /* super.c */
++void nfs_parse_ip_address(char *, size_t, struct sockaddr *, size_t *);
+ extern struct file_system_type nfs_xdev_fs_type;
+ #ifdef CONFIG_NFS_V4
+ extern struct file_system_type nfs4_xdev_fs_type;
+@@ -276,6 +277,7 @@ unsigned int nfs_page_array_len(unsigned int base, size_t len)
+ 		PAGE_SIZE - 1) >> PAGE_SHIFT;
+ }
+ 
++#define IPV6_SCOPE_DELIMITER	'%'
+ 
+ /*
+  * Set the port number in an address.  Be agnostic about the address
+diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
+index 6bcc5696f911..30befc39b3c6 100644
+--- a/fs/nfs/nfs4namespace.c
++++ b/fs/nfs/nfs4namespace.c
+@@ -93,50 +93,42 @@ static int nfs4_validate_fspath(const struct vfsmount *mnt_parent,
+ 	return 0;
+ }
+ 
+-/*
+- * Check if the string represents a "valid" IPv4 address
+- */
+-static inline int valid_ipaddr4(const char *buf)
+-{
+-	int rc, count, in[4];
+-
+-	rc = sscanf(buf, "%d.%d.%d.%d", &in[0], &in[1], &in[2], &in[3]);
+-	if (rc != 4)
+-		return -EINVAL;
+-	for (count = 0; count < 4; count++) {
+-		if (in[count] > 255)
+-			return -EINVAL;
+-	}
+-	return 0;
+-}
+-
+ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata,
+ 				     char *page, char *page2,
+ 				     const struct nfs4_fs_location *location)
+ {
+ 	struct vfsmount *mnt = ERR_PTR(-ENOENT);
+ 	char *mnt_path;
++	int page2len;
+ 	unsigned int s;
+ 
+ 	mnt_path = nfs4_pathname_string(&location->rootpath, page2, PAGE_SIZE);
+ 	if (IS_ERR(mnt_path))
+ 		return mnt;
+ 	mountdata->mnt_path = mnt_path;
++	page2 += strlen(mnt_path) + 1;
++	page2len = PAGE_SIZE - strlen(mnt_path) - 1;
+ 
+ 	for (s = 0; s < location->nservers; s++) {
+-		struct sockaddr_in addr = {
+-			.sin_family	= AF_INET,
+-			.sin_port	= htons(NFS_PORT),
+-		};
++		const struct nfs4_string *buf = &location->servers[s];
++		struct sockaddr_storage addr;
+ 
+-		if (location->servers[s].len <= 0 ||
+-		    valid_ipaddr4(location->servers[s].data) < 0)
++		if (buf->len <= 0 || buf->len >= PAGE_SIZE)
+ 			continue;
+ 
+-		mountdata->hostname = location->servers[s].data;
+-		addr.sin_addr.s_addr = in_aton(mountdata->hostname),
+ 		mountdata->addr = (struct sockaddr *)&addr;
+-		mountdata->addrlen = sizeof(addr);
++
++		if (memchr(buf->data, IPV6_SCOPE_DELIMITER, buf->len))
++			continue;
++		nfs_parse_ip_address(buf->data, buf->len,
++				mountdata->addr, &mountdata->addrlen);
++		if (mountdata->addr->sa_family == AF_UNSPEC)
++			continue;
++		nfs_set_port(mountdata->addr, NFS_PORT);
++
++		strncpy(page2, buf->data, page2len);
++		page2[page2len] = '\0';
++		mountdata->hostname = page2;
+ 
+ 		snprintf(page, PAGE_SIZE, "%s:%s",
+ 				mountdata->hostname,
+diff --git a/fs/nfs/super.c b/fs/nfs/super.c
+index b99096b8e827..20dc4ccdff56 100644
+--- a/fs/nfs/super.c
++++ b/fs/nfs/super.c
+@@ -716,8 +716,6 @@ static void nfs_parse_ipv4_address(char *string, size_t str_len,
+ 	*addr_len = 0;
+ }
+ 
+-#define IPV6_SCOPE_DELIMITER	'%'
+-
+ #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ static void nfs_parse_ipv6_scope_id(const char *string, const size_t str_len,
+ 				    const char *delim,
+@@ -790,7 +788,7 @@ static void nfs_parse_ipv6_address(char *string, size_t str_len,
+  * If there is a problem constructing the new sockaddr, set the address
+  * family to AF_UNSPEC.
+  */
+-static void nfs_parse_ip_address(char *string, size_t str_len,
++void nfs_parse_ip_address(char *string, size_t str_len,
+ 				 struct sockaddr *sap, size_t *addr_len)
+ {
+ 	unsigned int i, colons;

commit f0c929251e01a7a86b6254c775cb6b65c6457f10
+Author: J. Bruce Fields 
+Date:   Wed Aug 20 16:10:22 2008 -0400
+
+    nfs: prepare to share nfs_set_port
+    
+    We plan to use this function elsewhere.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
+index 7bcf6ec2d458..8d91bd88e310 100644
+--- a/fs/nfs/internal.h
++++ b/fs/nfs/internal.h
+@@ -276,3 +276,23 @@ unsigned int nfs_page_array_len(unsigned int base, size_t len)
+ 		PAGE_SIZE - 1) >> PAGE_SHIFT;
+ }
+ 
++
++/*
++ * Set the port number in an address.  Be agnostic about the address
++ * family.
++ */
++static inline void nfs_set_port(struct sockaddr *sap, unsigned short port)
++{
++	switch (sap->sa_family) {
++	case AF_INET: {
++	      struct sockaddr_in *ap = (struct sockaddr_in *)sap;
++	      ap->sin_port = htons(port);
++	      break;
++	}
++	case AF_INET6: {
++	       struct sockaddr_in6 *ap = (struct sockaddr_in6 *)sap;
++	       ap->sin6_port = htons(port);
++	       break;
++	}
++	}
++}
+diff --git a/fs/nfs/super.c b/fs/nfs/super.c
+index 1e3558697219..b99096b8e827 100644
+--- a/fs/nfs/super.c
++++ b/fs/nfs/super.c
+@@ -674,25 +674,6 @@ static void nfs_umount_begin(struct super_block *sb)
+ 		rpc_killall_tasks(rpc);
+ }
+ 
+-/*
+- * Set the port number in an address.  Be agnostic about the address family.
+- */
+-static void nfs_set_port(struct sockaddr *sap, unsigned short port)
+-{
+-	switch (sap->sa_family) {
+-	case AF_INET: {
+-		struct sockaddr_in *ap = (struct sockaddr_in *)sap;
+-		ap->sin_port = htons(port);
+-		break;
+-	}
+-	case AF_INET6: {
+-		struct sockaddr_in6 *ap = (struct sockaddr_in6 *)sap;
+-		ap->sin6_port = htons(port);
+-		break;
+-	}
+-	}
+-}
+-
+ /*
+  * Sanity-check a server address provided by the mount command.
+  *

commit 460cdbc83268dd9641b57d893b03ef52fcc3f96d
+Author: J. Bruce Fields 
+Date:   Wed Aug 20 16:10:21 2008 -0400
+
+    nfs: replace while loop by for loops in nfs_follow_referral
+    
+    Whoever wrote this had a bizarre allergy to for loops.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
+index 956cbbc2ae9f..6bcc5696f911 100644
+--- a/fs/nfs/nfs4namespace.c
++++ b/fs/nfs/nfs4namespace.c
+@@ -116,24 +116,22 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata,
+ {
+ 	struct vfsmount *mnt = ERR_PTR(-ENOENT);
+ 	char *mnt_path;
+-	unsigned int s = 0;
++	unsigned int s;
+ 
+ 	mnt_path = nfs4_pathname_string(&location->rootpath, page2, PAGE_SIZE);
+ 	if (IS_ERR(mnt_path))
+ 		return mnt;
+ 	mountdata->mnt_path = mnt_path;
+ 
+-	while (s < location->nservers) {
++	for (s = 0; s < location->nservers; s++) {
+ 		struct sockaddr_in addr = {
+ 			.sin_family	= AF_INET,
+ 			.sin_port	= htons(NFS_PORT),
+ 		};
+ 
+ 		if (location->servers[s].len <= 0 ||
+-		    valid_ipaddr4(location->servers[s].data) < 0) {
+-			s++;
++		    valid_ipaddr4(location->servers[s].data) < 0)
+ 			continue;
+-		}
+ 
+ 		mountdata->hostname = location->servers[s].data;
+ 		addr.sin_addr.s_addr = in_aton(mountdata->hostname),
+@@ -147,7 +145,6 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata,
+ 		mnt = vfs_kern_mount(&nfs4_referral_fs_type, 0, page, mountdata);
+ 		if (!IS_ERR(mnt))
+ 			break;
+-		s++;
+ 	}
+ 	return mnt;
+ }
+@@ -193,20 +190,16 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent,
+ 		goto out;
+ 	}
+ 
+-	loc = 0;
+-	while (loc < locations->nlocations) {
++	for (loc = 0; loc < locations->nlocations; loc++) {
+ 		const struct nfs4_fs_location *location = &locations->locations[loc];
+ 
+ 		if (location == NULL || location->nservers <= 0 ||
+-		    location->rootpath.ncomponents == 0) {
+-			loc++;
++		    location->rootpath.ncomponents == 0)
+ 			continue;
+-		}
+ 
+ 		mnt = try_location(&mountdata, page, page2, location);
+ 		if (!IS_ERR(mnt))
+ 			break;
+-		loc++;
+ 	}
+ 
+ out:

commit 4ada29d5c4dd2d3ba89510bdbc64be22961fd1cb
+Author: J. Bruce Fields 
+Date:   Wed Aug 20 16:10:20 2008 -0400
+
+    nfs: break up nfs_follow_referral
+    
+    This function is a little longer and more deeply nested than necessary.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
+index b112857301f7..956cbbc2ae9f 100644
+--- a/fs/nfs/nfs4namespace.c
++++ b/fs/nfs/nfs4namespace.c
+@@ -110,6 +110,48 @@ static inline int valid_ipaddr4(const char *buf)
+ 	return 0;
+ }
+ 
++static struct vfsmount *try_location(struct nfs_clone_mount *mountdata,
++				     char *page, char *page2,
++				     const struct nfs4_fs_location *location)
++{
++	struct vfsmount *mnt = ERR_PTR(-ENOENT);
++	char *mnt_path;
++	unsigned int s = 0;
++
++	mnt_path = nfs4_pathname_string(&location->rootpath, page2, PAGE_SIZE);
++	if (IS_ERR(mnt_path))
++		return mnt;
++	mountdata->mnt_path = mnt_path;
++
++	while (s < location->nservers) {
++		struct sockaddr_in addr = {
++			.sin_family	= AF_INET,
++			.sin_port	= htons(NFS_PORT),
++		};
++
++		if (location->servers[s].len <= 0 ||
++		    valid_ipaddr4(location->servers[s].data) < 0) {
++			s++;
++			continue;
++		}
++
++		mountdata->hostname = location->servers[s].data;
++		addr.sin_addr.s_addr = in_aton(mountdata->hostname),
++		mountdata->addr = (struct sockaddr *)&addr;
++		mountdata->addrlen = sizeof(addr);
++
++		snprintf(page, PAGE_SIZE, "%s:%s",
++				mountdata->hostname,
++				mountdata->mnt_path);
++
++		mnt = vfs_kern_mount(&nfs4_referral_fs_type, 0, page, mountdata);
++		if (!IS_ERR(mnt))
++			break;
++		s++;
++	}
++	return mnt;
++}
++
+ /**
+  * nfs_follow_referral - set up mountpoint when hitting a referral on moved error
+  * @mnt_parent - mountpoint of parent directory
+@@ -128,7 +170,6 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent,
+ 		.authflavor = NFS_SB(mnt_parent->mnt_sb)->client->cl_auth->au_flavor,
+ 	};
+ 	char *page = NULL, *page2 = NULL;
+-	unsigned int s;
+ 	int loc, error;
+ 
+ 	if (locations == NULL || locations->nlocations <= 0)
+@@ -153,9 +194,8 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent,
+ 	}
+ 
+ 	loc = 0;
+-	while (loc < locations->nlocations && IS_ERR(mnt)) {
++	while (loc < locations->nlocations) {
+ 		const struct nfs4_fs_location *location = &locations->locations[loc];
+-		char *mnt_path;
+ 
+ 		if (location == NULL || location->nservers <= 0 ||
+ 		    location->rootpath.ncomponents == 0) {
+@@ -163,41 +203,9 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent,
+ 			continue;
+ 		}
+ 
+-		mnt_path = nfs4_pathname_string(&location->rootpath, page2, PAGE_SIZE);
+-		if (IS_ERR(mnt_path)) {
+-			loc++;
+-			continue;
+-		}
+-		mountdata.mnt_path = mnt_path;
+-
+-		s = 0;
+-		while (s < location->nservers) {
+-			struct sockaddr_in addr = {
+-				.sin_family	= AF_INET,
+-				.sin_port	= htons(NFS_PORT),
+-			};
+-
+-			if (location->servers[s].len <= 0 ||
+-			    valid_ipaddr4(location->servers[s].data) < 0) {
+-				s++;
+-				continue;
+-			}
+-
+-			mountdata.hostname = location->servers[s].data;
+-			addr.sin_addr.s_addr = in_aton(mountdata.hostname),
+-			mountdata.addr = (struct sockaddr *)&addr;
+-			mountdata.addrlen = sizeof(addr);
+-
+-			snprintf(page, PAGE_SIZE, "%s:%s",
+-					mountdata.hostname,
+-					mountdata.mnt_path);
+-
+-			mnt = vfs_kern_mount(&nfs4_referral_fs_type, 0, page, &mountdata);
+-			if (!IS_ERR(mnt)) {
+-				break;
+-			}
+-			s++;
+-		}
++		mnt = try_location(&mountdata, page, page2, location);
++		if (!IS_ERR(mnt))
++			break;
+ 		loc++;
+ 	}
+ 

commit f200c11c257b8db5c49dfc0b7f84bceae3109779
+Author: J. Bruce Fields 
+Date:   Thu Aug 14 18:32:55 2008 -0400
+
+    nfs: remove an obsolete nfs_flock comment
+    
+    We *do* now allow bsd flocks over nfs.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/file.c b/fs/nfs/file.c
+index 3ddb00433f4f..d319b49f8f06 100644
+--- a/fs/nfs/file.c
++++ b/fs/nfs/file.c
+@@ -702,13 +702,6 @@ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
+ 			filp->f_path.dentry->d_name.name,
+ 			fl->fl_type, fl->fl_flags);
+ 
+-	/*
+-	 * No BSD flocks over NFS allowed.
+-	 * Note: we could try to fake a POSIX lock request here by
+-	 * using ((u32) filp | 0x80000000) or some such as the pid.
+-	 * Not sure whether that would be unique, though, or whether
+-	 * that would break in other places.
+-	 */
+ 	if (!(fl->fl_flags & FL_FLOCK))
+ 		return -ENOLCK;
+ 

commit d22b1cff099737f74f3ac5950094508b4cddec1e
+Author: J. Bruce Fields 
+Date:   Wed Feb 6 15:05:12 2008 -0500
+
+    lockd: reject reclaims outside the grace period
+    
+    The current lockd does not reject reclaims that arrive outside of the
+    grace period.
+    
+    Accepting a reclaim means promising to the client that no conflicting
+    locks were granted since last it held the lock.  We can meet that
+    promise if we assume the only lockers are nfs clients, and that they are
+    sufficiently well-behaved to reclaim only locks that they held before,
+    and that only reclaim locks have been permitted so far.  Once we leave
+    the grace period (and start permitting non-reclaims), we can no longer
+    keep that promise.  So we must start rejecting reclaims at that point.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
+index 808d246ada4d..6063a8e4b9f3 100644
+--- a/fs/lockd/svclock.c
++++ b/fs/lockd/svclock.c
+@@ -410,6 +410,10 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
+ 		ret = nlm_lck_denied_grace_period;
+ 		goto out;
+ 	}
++	if (reclaim && !locks_in_grace()) {
++		ret = nlm_lck_denied_grace_period;
++		goto out;
++	}
+ 
+ 	if (!wait)
+ 		lock->fl.fl_flags &= ~FL_SLEEP;

commit b2b5028905226f85075a408b1118857c9aa48bb3
+Author: J. Bruce Fields 
+Date:   Wed Feb 6 13:59:23 2008 -0500
+
+    lockd: move grace period checks to common code
+    
+    Do all the grace period checks in svclock.c.  This simplifies the code a
+    bit, and will ease some later changes.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
+index 7ca617367b3e..f6f18fa5cf8b 100644
+--- a/fs/lockd/svc4proc.c
++++ b/fs/lockd/svc4proc.c
+@@ -88,12 +88,6 @@ nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
+ 	dprintk("lockd: TEST4        called\n");
+ 	resp->cookie = argp->cookie;
+ 
+-	/* Don't accept test requests during grace period */
+-	if (locks_in_grace()) {
+-		resp->status = nlm_lck_denied_grace_period;
+-		return rc;
+-	}
+-
+ 	/* Obtain client and file */
+ 	if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
+ 		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
+@@ -122,12 +116,6 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
+ 
+ 	resp->cookie = argp->cookie;
+ 
+-	/* Don't accept new lock requests during grace period */
+-	if (locks_in_grace() && !argp->reclaim) {
+-		resp->status = nlm_lck_denied_grace_period;
+-		return rc;
+-	}
+-
+ 	/* Obtain client and file */
+ 	if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
+ 		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
+@@ -146,7 +134,8 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
+ 
+ 	/* Now try to lock the file */
+ 	resp->status = nlmsvc_lock(rqstp, file, host, &argp->lock,
+-					argp->block, &argp->cookie);
++					argp->block, &argp->cookie,
++					argp->reclaim);
+ 	if (resp->status == nlm_drop_reply)
+ 		rc = rpc_drop_reply;
+ 	else
+diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
+index cf0d5c2c318d..808d246ada4d 100644
+--- a/fs/lockd/svclock.c
++++ b/fs/lockd/svclock.c
+@@ -360,7 +360,7 @@ nlmsvc_defer_lock_rqst(struct svc_rqst *rqstp, struct nlm_block *block)
+ __be32
+ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
+ 	    struct nlm_host *host, struct nlm_lock *lock, int wait,
+-	    struct nlm_cookie *cookie)
++	    struct nlm_cookie *cookie, int reclaim)
+ {
+ 	struct nlm_block	*block = NULL;
+ 	int			error;
+@@ -406,6 +406,11 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
+ 		goto out;
+ 	}
+ 
++	if (locks_in_grace() && !reclaim) {
++		ret = nlm_lck_denied_grace_period;
++		goto out;
++	}
++
+ 	if (!wait)
+ 		lock->fl.fl_flags &= ~FL_SLEEP;
+ 	error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL);
+@@ -502,6 +507,10 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
+ 		goto out;
+ 	}
+ 
++	if (locks_in_grace()) {
++		ret = nlm_lck_denied_grace_period;
++		goto out;
++	}
+ 	error = vfs_test_lock(file->f_file, &lock->fl);
+ 	if (error == FILE_LOCK_DEFERRED) {
+ 		ret = nlmsvc_defer_lock_rqst(rqstp, block);
+@@ -582,6 +591,9 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
+ 				(long long)lock->fl.fl_start,
+ 				(long long)lock->fl.fl_end);
+ 
++	if (locks_in_grace())
++		return nlm_lck_denied_grace_period;
++
+ 	mutex_lock(&file->f_mutex);
+ 	block = nlmsvc_lookup_block(file, lock);
+ 	mutex_unlock(&file->f_mutex);
+diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
+index 1b013e198804..a587b81338b1 100644
+--- a/fs/lockd/svcproc.c
++++ b/fs/lockd/svcproc.c
+@@ -117,12 +117,6 @@ nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
+ 	dprintk("lockd: TEST          called\n");
+ 	resp->cookie = argp->cookie;
+ 
+-	/* Don't accept test requests during grace period */
+-	if (locks_in_grace()) {
+-		resp->status = nlm_lck_denied_grace_period;
+-		return rc;
+-	}
+-
+ 	/* Obtain client and file */
+ 	if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
+ 		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
+@@ -152,12 +146,6 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
+ 
+ 	resp->cookie = argp->cookie;
+ 
+-	/* Don't accept new lock requests during grace period */
+-	if (locks_in_grace() && !argp->reclaim) {
+-		resp->status = nlm_lck_denied_grace_period;
+-		return rc;
+-	}
+-
+ 	/* Obtain client and file */
+ 	if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
+ 		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
+@@ -176,7 +164,8 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
+ 
+ 	/* Now try to lock the file */
+ 	resp->status = cast_status(nlmsvc_lock(rqstp, file, host, &argp->lock,
+-					       argp->block, &argp->cookie));
++					       argp->block, &argp->cookie,
++					       argp->reclaim));
+ 	if (resp->status == nlm_drop_reply)
+ 		rc = rpc_drop_reply;
+ 	else
+diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
+index ec8af115843d..973ab1d6e862 100644
+--- a/include/linux/lockd/lockd.h
++++ b/include/linux/lockd/lockd.h
+@@ -242,7 +242,7 @@ typedef int	  (*nlm_host_match_fn_t)(void *cur, struct nlm_host *ref);
+  */
+ __be32		  nlmsvc_lock(struct svc_rqst *, struct nlm_file *,
+ 			      struct nlm_host *, struct nlm_lock *, int,
+-			      struct nlm_cookie *);
++			      struct nlm_cookie *, int);
+ __be32		  nlmsvc_unlock(struct nlm_file *, struct nlm_lock *);
+ __be32		  nlmsvc_testlock(struct svc_rqst *, struct nlm_file *,
+ 			struct nlm_host *, struct nlm_lock *,

commit af558e33bedab672f5cfd3260bce7445e353fe21
+Author: J. Bruce Fields 
+Date:   Thu Sep 6 12:34:25 2007 -0400
+
+    nfsd: common grace period control
+    
+    Rewrite grace period code to unify management of grace period across
+    lockd and nfsd.  The current code has lockd and nfsd cooperate to
+    compute a grace period which is satisfactory to them both, and then
+    individually enforce it.  This creates a slight race condition, since
+    the enforcement is not coordinated.  It's also more complicated than
+    necessary.
+    
+    Here instead we have lockd and nfsd each inform common code when they
+    enter the grace period, and when they're ready to leave the grace
+    period, and allow normal locking only after both of them are ready to
+    leave.
+    
+    We also expect the locks_start_grace()/locks_end_grace() interface here
+    to be simpler to build on for future cluster/high-availability work,
+    which may require (for example) putting individual filesystems into
+    grace, or enforcing grace periods across multiple cluster nodes.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/lockd/Makefile b/fs/lockd/Makefile
+index 7725a0a9a555..97f6073ab339 100644
+--- a/fs/lockd/Makefile
++++ b/fs/lockd/Makefile
+@@ -5,6 +5,6 @@
+ obj-$(CONFIG_LOCKD) += lockd.o
+ 
+ lockd-objs-y := clntlock.o clntproc.o host.o svc.o svclock.o svcshare.o \
+-	        svcproc.o svcsubs.o mon.o xdr.o
++	        svcproc.o svcsubs.o mon.o xdr.o grace.o
+ lockd-objs-$(CONFIG_LOCKD_V4) += xdr4.o svc4proc.o
+ lockd-objs		      := $(lockd-objs-y)
+diff --git a/fs/lockd/grace.c b/fs/lockd/grace.c
+new file mode 100644
+index 000000000000..183cc1f0af1c
+--- /dev/null
++++ b/fs/lockd/grace.c
+@@ -0,0 +1,59 @@
++/*
++ * Common code for control of lockd and nfsv4 grace periods.
++ */
++
++#include 
++#include 
++
++static LIST_HEAD(grace_list);
++static DEFINE_SPINLOCK(grace_lock);
++
++/**
++ * locks_start_grace
++ * @lm: who this grace period is for
++ *
++ * A grace period is a period during which locks should not be given
++ * out.  Currently grace periods are only enforced by the two lock
++ * managers (lockd and nfsd), using the locks_in_grace() function to
++ * check when they are in a grace period.
++ *
++ * This function is called to start a grace period.
++ */
++void locks_start_grace(struct lock_manager *lm)
++{
++	spin_lock(&grace_lock);
++	list_add(&lm->list, &grace_list);
++	spin_unlock(&grace_lock);
++}
++EXPORT_SYMBOL_GPL(locks_start_grace);
++
++/**
++ * locks_end_grace
++ * @lm: who this grace period is for
++ *
++ * Call this function to state that the given lock manager is ready to
++ * resume regular locking.  The grace period will not end until all lock
++ * managers that called locks_start_grace() also call locks_end_grace().
++ * Note that callers count on it being safe to call this more than once,
++ * and the second call should be a no-op.
++ */
++void locks_end_grace(struct lock_manager *lm)
++{
++	spin_lock(&grace_lock);
++	list_del_init(&lm->list);
++	spin_unlock(&grace_lock);
++}
++EXPORT_SYMBOL_GPL(locks_end_grace);
++
++/**
++ * locks_in_grace
++ *
++ * Lock managers call this function to determine when it is OK for them
++ * to answer ordinary lock requests, and when they should accept only
++ * lock reclaims.
++ */
++int locks_in_grace(void)
++{
++	return !list_empty(&grace_list);
++}
++EXPORT_SYMBOL_GPL(locks_in_grace);
+diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
+index f345ef7fb8ae..f013aed11533 100644
+--- a/fs/lockd/svc.c
++++ b/fs/lockd/svc.c
+@@ -51,7 +51,6 @@ static DEFINE_MUTEX(nlmsvc_mutex);
+ static unsigned int		nlmsvc_users;
+ static struct task_struct	*nlmsvc_task;
+ static struct svc_rqst		*nlmsvc_rqst;
+-int				nlmsvc_grace_period;
+ unsigned long			nlmsvc_timeout;
+ 
+ /*
+@@ -85,30 +84,21 @@ static unsigned long get_lockd_grace_period(void)
+ 		return nlm_timeout * 5 * HZ;
+ }
+ 
+-unsigned long get_nfs_grace_period(void)
+-{
+-	unsigned long lockdgrace = get_lockd_grace_period();
+-	unsigned long nfsdgrace = 0;
+-
+-	if (nlmsvc_ops)
+-		nfsdgrace = nlmsvc_ops->get_grace_period();
+-
+-	return max(lockdgrace, nfsdgrace);
+-}
+-EXPORT_SYMBOL(get_nfs_grace_period);
++static struct lock_manager lockd_manager = {
++};
+ 
+ static void grace_ender(struct work_struct *not_used)
+ {
+-	nlmsvc_grace_period = 0;
++	locks_end_grace(&lockd_manager);
+ }
+ 
+ static DECLARE_DELAYED_WORK(grace_period_end, grace_ender);
+ 
+ static void set_grace_period(void)
+ {
+-	unsigned long grace_period = get_nfs_grace_period() + jiffies;
++	unsigned long grace_period = get_lockd_grace_period();
+ 
+-	nlmsvc_grace_period = 1;
++	locks_start_grace(&lockd_manager);
+ 	cancel_delayed_work_sync(&grace_period_end);
+ 	schedule_delayed_work(&grace_period_end, grace_period);
+ }
+diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
+index 4a714f64515b..7ca617367b3e 100644
+--- a/fs/lockd/svc4proc.c
++++ b/fs/lockd/svc4proc.c
+@@ -89,7 +89,7 @@ nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
+ 	resp->cookie = argp->cookie;
+ 
+ 	/* Don't accept test requests during grace period */
+-	if (nlmsvc_grace_period) {
++	if (locks_in_grace()) {
+ 		resp->status = nlm_lck_denied_grace_period;
+ 		return rc;
+ 	}
+@@ -123,7 +123,7 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
+ 	resp->cookie = argp->cookie;
+ 
+ 	/* Don't accept new lock requests during grace period */
+-	if (nlmsvc_grace_period && !argp->reclaim) {
++	if (locks_in_grace() && !argp->reclaim) {
+ 		resp->status = nlm_lck_denied_grace_period;
+ 		return rc;
+ 	}
+@@ -169,7 +169,7 @@ nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
+ 	resp->cookie = argp->cookie;
+ 
+ 	/* Don't accept requests during grace period */
+-	if (nlmsvc_grace_period) {
++	if (locks_in_grace()) {
+ 		resp->status = nlm_lck_denied_grace_period;
+ 		return rpc_success;
+ 	}
+@@ -202,7 +202,7 @@ nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
+ 	resp->cookie = argp->cookie;
+ 
+ 	/* Don't accept new lock requests during grace period */
+-	if (nlmsvc_grace_period) {
++	if (locks_in_grace()) {
+ 		resp->status = nlm_lck_denied_grace_period;
+ 		return rpc_success;
+ 	}
+@@ -341,7 +341,7 @@ nlm4svc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
+ 	resp->cookie = argp->cookie;
+ 
+ 	/* Don't accept new lock requests during grace period */
+-	if (nlmsvc_grace_period && !argp->reclaim) {
++	if (locks_in_grace() && !argp->reclaim) {
+ 		resp->status = nlm_lck_denied_grace_period;
+ 		return rpc_success;
+ 	}
+@@ -374,7 +374,7 @@ nlm4svc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
+ 	resp->cookie = argp->cookie;
+ 
+ 	/* Don't accept requests during grace period */
+-	if (nlmsvc_grace_period) {
++	if (locks_in_grace()) {
+ 		resp->status = nlm_lck_denied_grace_period;
+ 		return rpc_success;
+ 	}
+diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
+index 76262c1986f2..1b013e198804 100644
+--- a/fs/lockd/svcproc.c
++++ b/fs/lockd/svcproc.c
+@@ -118,7 +118,7 @@ nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
+ 	resp->cookie = argp->cookie;
+ 
+ 	/* Don't accept test requests during grace period */
+-	if (nlmsvc_grace_period) {
++	if (locks_in_grace()) {
+ 		resp->status = nlm_lck_denied_grace_period;
+ 		return rc;
+ 	}
+@@ -153,7 +153,7 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
+ 	resp->cookie = argp->cookie;
+ 
+ 	/* Don't accept new lock requests during grace period */
+-	if (nlmsvc_grace_period && !argp->reclaim) {
++	if (locks_in_grace() && !argp->reclaim) {
+ 		resp->status = nlm_lck_denied_grace_period;
+ 		return rc;
+ 	}
+@@ -199,7 +199,7 @@ nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
+ 	resp->cookie = argp->cookie;
+ 
+ 	/* Don't accept requests during grace period */
+-	if (nlmsvc_grace_period) {
++	if (locks_in_grace()) {
+ 		resp->status = nlm_lck_denied_grace_period;
+ 		return rpc_success;
+ 	}
+@@ -232,7 +232,7 @@ nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
+ 	resp->cookie = argp->cookie;
+ 
+ 	/* Don't accept new lock requests during grace period */
+-	if (nlmsvc_grace_period) {
++	if (locks_in_grace()) {
+ 		resp->status = nlm_lck_denied_grace_period;
+ 		return rpc_success;
+ 	}
+@@ -373,7 +373,7 @@ nlmsvc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
+ 	resp->cookie = argp->cookie;
+ 
+ 	/* Don't accept new lock requests during grace period */
+-	if (nlmsvc_grace_period && !argp->reclaim) {
++	if (locks_in_grace() && !argp->reclaim) {
+ 		resp->status = nlm_lck_denied_grace_period;
+ 		return rpc_success;
+ 	}
+@@ -406,7 +406,7 @@ nlmsvc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
+ 	resp->cookie = argp->cookie;
+ 
+ 	/* Don't accept requests during grace period */
+-	if (nlmsvc_grace_period) {
++	if (locks_in_grace()) {
+ 		resp->status = nlm_lck_denied_grace_period;
+ 		return rpc_success;
+ 	}
+diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
+index 15c6faeec77c..b2786a5f9afe 100644
+--- a/fs/nfsd/lockd.c
++++ b/fs/nfsd/lockd.c
+@@ -70,7 +70,6 @@ nlm_fclose(struct file *filp)
+ static struct nlmsvc_binding	nfsd_nlm_ops = {
+ 	.fopen		= nlm_fopen,		/* open file for locking */
+ 	.fclose		= nlm_fclose,		/* close file */
+-	.get_grace_period = get_nfs4_grace_period,
+ };
+ 
+ void
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index e5b51ffafc6c..669461e291ae 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -201,10 +201,10 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	/* Openowner is now set, so sequence id will get bumped.  Now we need
+ 	 * these checks before we do any creates: */
+ 	status = nfserr_grace;
+-	if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
++	if (locks_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
+ 		goto out;
+ 	status = nfserr_no_grace;
+-	if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
++	if (!locks_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
+ 		goto out;
+ 
+ 	switch (open->op_claim_type) {
+@@ -575,7 +575,7 @@ nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ {
+ 	__be32 status;
+ 
+-	if (nfs4_in_grace())
++	if (locks_in_grace())
+ 		return nfserr_grace;
+ 	status = nfsd_unlink(rqstp, &cstate->current_fh, 0,
+ 			     remove->rm_name, remove->rm_namelen);
+@@ -596,7 +596,7 @@ nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 
+ 	if (!cstate->save_fh.fh_dentry)
+ 		return status;
+-	if (nfs4_in_grace() && !(cstate->save_fh.fh_export->ex_flags
++	if (locks_in_grace() && !(cstate->save_fh.fh_export->ex_flags
+ 					& NFSEXP_NOSUBTREECHECK))
+ 		return nfserr_grace;
+ 	status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 1578d7a2667e..0cc7ff5d5ab5 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -61,7 +61,6 @@
+ static time_t lease_time = 90;     /* default lease time */
+ static time_t user_lease_time = 90;
+ static time_t boot_time;
+-static int in_grace = 1;
+ static u32 current_ownerid = 1;
+ static u32 current_fileid = 1;
+ static u32 current_delegid = 1;
+@@ -1640,7 +1639,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
+ 		case NFS4_OPEN_CLAIM_NULL:
+ 			/* Let's not give out any delegations till everyone's
+ 			 * had the chance to reclaim theirs.... */
+-			if (nfs4_in_grace())
++			if (locks_in_grace())
+ 				goto out;
+ 			if (!atomic_read(&cb->cb_set) || !sop->so_confirmed)
+ 				goto out;
+@@ -1816,12 +1815,15 @@ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	return status;
+ }
+ 
++struct lock_manager nfsd4_manager = {
++};
++
+ static void
+-end_grace(void)
++nfsd4_end_grace(void)
+ {
+ 	dprintk("NFSD: end of grace period\n");
+ 	nfsd4_recdir_purge_old();
+-	in_grace = 0;
++	locks_end_grace(&nfsd4_manager);
+ }
+ 
+ static time_t
+@@ -1838,8 +1840,8 @@ nfs4_laundromat(void)
+ 	nfs4_lock_state();
+ 
+ 	dprintk("NFSD: laundromat service - starting\n");
+-	if (in_grace)
+-		end_grace();
++	if (locks_in_grace())
++		nfsd4_end_grace();
+ 	list_for_each_safe(pos, next, &client_lru) {
+ 		clp = list_entry(pos, struct nfs4_client, cl_lru);
+ 		if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) {
+@@ -1974,7 +1976,7 @@ check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
+ 		return nfserr_bad_stateid;
+ 	else if (ONE_STATEID(stateid) && (flags & RD_STATE))
+ 		return nfs_ok;
+-	else if (nfs4_in_grace()) {
++	else if (locks_in_grace()) {
+ 		/* Answer in remaining cases depends on existance of
+ 		 * conflicting state; so we must wait out the grace period. */
+ 		return nfserr_grace;
+@@ -1993,7 +1995,7 @@ check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
+ static inline int
+ io_during_grace_disallowed(struct inode *inode, int flags)
+ {
+-	return nfs4_in_grace() && (flags & (RD_STATE | WR_STATE))
++	return locks_in_grace() && (flags & (RD_STATE | WR_STATE))
+ 		&& mandatory_lock(inode);
+ }
+ 
+@@ -2693,10 +2695,10 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	filp = lock_stp->st_vfs_file;
+ 
+ 	status = nfserr_grace;
+-	if (nfs4_in_grace() && !lock->lk_reclaim)
++	if (locks_in_grace() && !lock->lk_reclaim)
+ 		goto out;
+ 	status = nfserr_no_grace;
+-	if (!nfs4_in_grace() && lock->lk_reclaim)
++	if (!locks_in_grace() && lock->lk_reclaim)
+ 		goto out;
+ 
+ 	locks_init_lock(&file_lock);
+@@ -2779,7 +2781,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	int error;
+ 	__be32 status;
+ 
+-	if (nfs4_in_grace())
++	if (locks_in_grace())
+ 		return nfserr_grace;
+ 
+ 	if (check_lock_length(lockt->lt_offset, lockt->lt_length))
+@@ -3192,9 +3194,9 @@ __nfs4_state_start(void)
+ 	unsigned long grace_time;
+ 
+ 	boot_time = get_seconds();
+-	grace_time = get_nfs_grace_period();
++	grace_time = get_nfs4_grace_period();
+ 	lease_time = user_lease_time;
+-	in_grace = 1;
++	locks_start_grace(&nfsd4_manager);
+ 	printk(KERN_INFO "NFSD: starting %ld-second grace period\n",
+ 	       grace_time/HZ);
+ 	laundry_wq = create_singlethread_workqueue("nfsd4");
+@@ -3213,12 +3215,6 @@ nfs4_state_start(void)
+ 	return;
+ }
+ 
+-int
+-nfs4_in_grace(void)
+-{
+-	return in_grace;
+-}
+-
+ time_t
+ nfs4_lease_time(void)
+ {
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 9f540165a078..27cfa723b92a 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -942,6 +942,14 @@ struct lock_manager_operations {
+ 	int (*fl_change)(struct file_lock **, int);
+ };
+ 
++struct lock_manager {
++	struct list_head list;
++};
++
++void locks_start_grace(struct lock_manager *);
++void locks_end_grace(struct lock_manager *);
++int locks_in_grace(void);
++
+ /* that will die - we need it for nfs_lock_info */
+ #include 
+ 
+diff --git a/include/linux/lockd/bind.h b/include/linux/lockd/bind.h
+index 3d25bcd139d1..1f0465c374dc 100644
+--- a/include/linux/lockd/bind.h
++++ b/include/linux/lockd/bind.h
+@@ -27,7 +27,6 @@ struct nlmsvc_binding {
+ 						struct nfs_fh *,
+ 						struct file **);
+ 	void			(*fclose)(struct file *);
+-	unsigned long		(*get_grace_period)(void);
+ };
+ 
+ extern struct nlmsvc_binding *	nlmsvc_ops;
+@@ -56,12 +55,4 @@ extern int	nlmclnt_proc(struct nlm_host *host, int cmd,
+ extern int	lockd_up(int proto);
+ extern void	lockd_down(void);
+ 
+-unsigned long get_nfs_grace_period(void);
+-
+-#ifdef CONFIG_NFSD_V4
+-unsigned long get_nfs4_grace_period(void);
+-#else
+-static inline unsigned long get_nfs4_grace_period(void) {return 0;}
+-#endif
+-
+ #endif /* LINUX_LOCKD_BIND_H */

commit c8ab5f2a13fb41a878863c61a1e27d78f1844b5e
+Author: J. Bruce Fields 
+Date:   Tue Mar 18 19:00:19 2008 -0400
+
+    lockd: don't depend on lockd main loop to end grace
+    
+    End lockd's grace period using schedule_delayed_work() instead of a
+    check on every pass through the main loop.
+    
+    After a later patch, we'll depend on lockd to end its grace period even
+    if it's not currently handling requests; so it shouldn't depend on being
+    woken up from the main loop to do so.
+    
+    Also, Nakano Hiroaki (who independently produced a similar patch)
+    noticed that the current behavior is buggy in the face of jiffies
+    wraparound:
+    
+            "lockd uses time_before() to determine whether the grace period
+            has expired. This would seem to be enough to avoid timer
+            wrap-around issues, but, unfortunately, that is not the case.
+            The time_* family of comparison functions can be safely used to
+            compare jiffies relatively close in time, but they stop working
+            after approximately LONG_MAX/2 ticks. nfsd can suffer this
+            problem because the time_before() comparison in lockd() is not
+            performed until the first request comes in, which means that if
+            there is no lockd traffic for more than LONG_MAX/2 ticks we are
+            screwed.
+    
+            "The implication of this is that once time_before() starts
+            misbehaving any attempt from a NFS client to execute fcntl()
+            will be received with a NLM_LCK_DENIED_GRACE_PERIOD message for
+            25 days (assuming HZ=1000). In other words, the 50 seconds grace
+            period could turn into a grace period of 50 days or more.
+    
+            "Note: This bug was analyzed independently by Oda-san
+             and myself."
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: Nakano Hiroaki 
+    Cc: Itsuro Oda 
+
+diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
+index bdc607bb25e9..f345ef7fb8ae 100644
+--- a/fs/lockd/svc.c
++++ b/fs/lockd/svc.c
+@@ -97,15 +97,20 @@ unsigned long get_nfs_grace_period(void)
+ }
+ EXPORT_SYMBOL(get_nfs_grace_period);
+ 
+-static unsigned long set_grace_period(void)
++static void grace_ender(struct work_struct *not_used)
+ {
+-	nlmsvc_grace_period = 1;
+-	return get_nfs_grace_period() + jiffies;
++	nlmsvc_grace_period = 0;
+ }
+ 
+-static inline void clear_grace_period(void)
++static DECLARE_DELAYED_WORK(grace_period_end, grace_ender);
++
++static void set_grace_period(void)
+ {
+-	nlmsvc_grace_period = 0;
++	unsigned long grace_period = get_nfs_grace_period() + jiffies;
++
++	nlmsvc_grace_period = 1;
++	cancel_delayed_work_sync(&grace_period_end);
++	schedule_delayed_work(&grace_period_end, grace_period);
+ }
+ 
+ /*
+@@ -116,7 +121,6 @@ lockd(void *vrqstp)
+ {
+ 	int		err = 0, preverr = 0;
+ 	struct svc_rqst *rqstp = vrqstp;
+-	unsigned long grace_period_expire;
+ 
+ 	/* try_to_freeze() is called from svc_recv() */
+ 	set_freezable();
+@@ -139,7 +143,7 @@ lockd(void *vrqstp)
+ 		nlm_timeout = LOCKD_DFLT_TIMEO;
+ 	nlmsvc_timeout = nlm_timeout * HZ;
+ 
+-	grace_period_expire = set_grace_period();
++	set_grace_period();
+ 
+ 	/*
+ 	 * The main request loop. We don't terminate until the last
+@@ -153,16 +157,13 @@ lockd(void *vrqstp)
+ 			flush_signals(current);
+ 			if (nlmsvc_ops) {
+ 				nlmsvc_invalidate_all();
+-				grace_period_expire = set_grace_period();
++				set_grace_period();
+ 			}
+ 			continue;
+ 		}
+ 
+ 		timeout = nlmsvc_retry_blocked();
+ 
+-		if (time_before(grace_period_expire, jiffies))
+-			clear_grace_period();
+-
+ 		/*
+ 		 * Find a socket with data available and call its
+ 		 * recvfrom routine.
+@@ -189,6 +190,7 @@ lockd(void *vrqstp)
+ 		svc_process(rqstp);
+ 	}
+ 	flush_signals(current);
++	cancel_delayed_work_sync(&grace_period_end);
+ 	if (nlmsvc_ops)
+ 		nlmsvc_invalidate_all();
+ 	nlm_shutdown_hosts();

commit 8fafa90082ab18859d97627fc454edf12f7efbff
+Author: J. Bruce Fields 
+Date:   Thu Jan 24 11:11:34 2008 -0500
+
+    locks: allow lockd to process blocked locks during grace period
+    
+    The check here is currently harmless but unnecessary, since, as the
+    comment notes, there aren't any blocked-lock callbacks to process
+    during the grace period anyway.
+    
+    And eventually we want to allow multiple grace periods that come and go
+    for different filesystems over the course of the lifetime of lockd, at
+    which point this check is just going to get in the way.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
+index 1553fecc567d..bdc607bb25e9 100644
+--- a/fs/lockd/svc.c
++++ b/fs/lockd/svc.c
+@@ -158,15 +158,9 @@ lockd(void *vrqstp)
+ 			continue;
+ 		}
+ 
+-		/*
+-		 * Retry any blocked locks that have been notified by
+-		 * the VFS. Don't do this during grace period.
+-		 * (Theoretically, there shouldn't even be blocked locks
+-		 * during grace period).
+-		 */
+-		if (!nlmsvc_grace_period) {
+-			timeout = nlmsvc_retry_blocked();
+-		} else if (time_before(grace_period_expire, jiffies))
++		timeout = nlmsvc_retry_blocked();
++
++		if (time_before(grace_period_expire, jiffies))
+ 			clear_grace_period();
+ 
+ 		/*

commit 04716e6621ff4abb422d64ba7b48718f52716a3e
+Author: J. Bruce Fields 
+Date:   Thu Aug 7 13:00:20 2008 -0400
+
+    nfsd: permit unauthenticated stat of export root
+    
+    RFC 2623 section 2.3.2 permits the server to bypass gss authentication
+    checks for certain operations that a client may perform when mounting.
+    In the case of a client that doesn't have some form of credentials
+    available to it on boot, this allows it to perform the mount unattended.
+    (Presumably real file access won't be needed until a user with
+    credentials logs in.)
+    
+    Being slightly more lenient allows lots of old clients to access
+    krb5-only exports, with the only loss being a small amount of
+    information leaked about the root directory of the export.
+    
+    This affects only v2 and v3; v4 still requires authentication for all
+    access.
+    
+    Thanks to Peter Staubach testing against a Solaris client, which
+    suggesting addition of v3 getattr, to the list, and to Trond for noting
+    that doing so exposes no additional information.
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: Peter Staubach 
+    Cc: Trond Myklebust 
+
+diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
+index 4d617ea28cfc..9dbd2eb91281 100644
+--- a/fs/nfsd/nfs3proc.c
++++ b/fs/nfsd/nfs3proc.c
+@@ -63,7 +63,8 @@ nfsd3_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle  *argp,
+ 		SVCFH_fmt(&argp->fh));
+ 
+ 	fh_copy(&resp->fh, &argp->fh);
+-	nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
++	nfserr = fh_verify(rqstp, &resp->fh, 0,
++			NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
+ 	if (nfserr)
+ 		RETURN_STATUS(nfserr);
+ 
+@@ -530,7 +531,7 @@ nfsd3_proc_fsstat(struct svc_rqst * rqstp, struct nfsd_fhandle    *argp,
+ 	dprintk("nfsd: FSSTAT(3)   %s\n",
+ 				SVCFH_fmt(&argp->fh));
+ 
+-	nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats);
++	nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats, 0);
+ 	fh_put(&argp->fh);
+ 	RETURN_STATUS(nfserr);
+ }
+@@ -558,7 +559,8 @@ nfsd3_proc_fsinfo(struct svc_rqst * rqstp, struct nfsd_fhandle    *argp,
+ 	resp->f_maxfilesize = ~(u32) 0;
+ 	resp->f_properties = NFS3_FSF_DEFAULT;
+ 
+-	nfserr = fh_verify(rqstp, &argp->fh, 0, NFSD_MAY_NOP);
++	nfserr = fh_verify(rqstp, &argp->fh, 0,
++			NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
+ 
+ 	/* Check special features of the file system. May request
+ 	 * different read/write sizes for file systems known to have
+diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
+index ea37c96f0445..cd25d91895a1 100644
+--- a/fs/nfsd/nfsfh.c
++++ b/fs/nfsd/nfsfh.c
+@@ -302,17 +302,27 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
+ 	if (error)
+ 		goto out;
+ 
+-	if (!(access & NFSD_MAY_LOCK)) {
+-		/*
+-		 * pseudoflavor restrictions are not enforced on NLM,
+-		 * which clients virtually always use auth_sys for,
+-		 * even while using RPCSEC_GSS for NFS.
+-		 */
+-		error = check_nfsd_access(exp, rqstp);
+-		if (error)
+-			goto out;
+-	}
++	/*
++	 * pseudoflavor restrictions are not enforced on NLM,
++	 * which clients virtually always use auth_sys for,
++	 * even while using RPCSEC_GSS for NFS.
++	 */
++	if (access & NFSD_MAY_LOCK)
++		goto skip_pseudoflavor_check;
++	/*
++	 * Clients may expect to be able to use auth_sys during mount,
++	 * even if they use gss for everything else; see section 2.3.2
++	 * of rfc 2623.
++	 */
++	if (access & NFSD_MAY_BYPASS_GSS_ON_ROOT
++			&& exp->ex_path.dentry == dentry)
++		goto skip_pseudoflavor_check;
++
++	error = check_nfsd_access(exp, rqstp);
++	if (error)
++		goto out;
+ 
++skip_pseudoflavor_check:
+ 	/* Finally, check access permissions. */
+ 	error = nfsd_permission(rqstp, exp, dentry, access);
+ 
+diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
+index 0766f95d236a..5cffeca7acef 100644
+--- a/fs/nfsd/nfsproc.c
++++ b/fs/nfsd/nfsproc.c
+@@ -65,7 +65,8 @@ nfsd_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle  *argp,
+ 	dprintk("nfsd: GETATTR  %s\n", SVCFH_fmt(&argp->fh));
+ 
+ 	fh_copy(&resp->fh, &argp->fh);
+-	nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
++	nfserr = fh_verify(rqstp, &resp->fh, 0,
++			NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
+ 	return nfsd_return_attrs(nfserr, resp);
+ }
+ 
+@@ -521,7 +522,8 @@ nfsd_proc_statfs(struct svc_rqst * rqstp, struct nfsd_fhandle   *argp,
+ 
+ 	dprintk("nfsd: STATFS   %s\n", SVCFH_fmt(&argp->fh));
+ 
+-	nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats);
++	nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats,
++			NFSD_MAY_BYPASS_GSS_ON_ROOT);
+ 	fh_put(&argp->fh);
+ 	return nfserr;
+ }
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index 18060bed5267..1319e8027d55 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -1866,9 +1866,9 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp,
+  * N.B. After this call fhp needs an fh_put
+  */
+ __be32
+-nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat)
++nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat, int access)
+ {
+-	__be32 err = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP);
++	__be32 err = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP | access);
+ 	if (!err && vfs_statfs(fhp->fh_dentry,stat))
+ 		err = nfserr_io;
+ 	return err;
+diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
+index 108f47e5fd95..21269405ffe2 100644
+--- a/include/linux/nfsd/nfsd.h
++++ b/include/linux/nfsd/nfsd.h
+@@ -38,6 +38,7 @@
+ #define NFSD_MAY_LOCK		32
+ #define NFSD_MAY_OWNER_OVERRIDE	64
+ #define NFSD_MAY_LOCAL_ACCESS	128 /* IRIX doing local access check on device special file*/
++#define NFSD_MAY_BYPASS_GSS_ON_ROOT 256
+ 
+ #define NFSD_MAY_CREATE		(NFSD_MAY_EXEC|NFSD_MAY_WRITE)
+ #define NFSD_MAY_REMOVE		(NFSD_MAY_EXEC|NFSD_MAY_WRITE|NFSD_MAY_TRUNC)
+@@ -125,7 +126,7 @@ int		nfsd_truncate(struct svc_rqst *, struct svc_fh *,
+ __be32		nfsd_readdir(struct svc_rqst *, struct svc_fh *,
+ 			     loff_t *, struct readdir_cd *, filldir_t);
+ __be32		nfsd_statfs(struct svc_rqst *, struct svc_fh *,
+-				struct kstatfs *);
++				struct kstatfs *, int access);
+ 
+ int		nfsd_notify_change(struct inode *, struct iattr *);
+ __be32		nfsd_permission(struct svc_rqst *, struct svc_export *,

commit 91b80969ba466ba4b915a4a1d03add8c297add3f
+Author: J. Bruce Fields 
+Date:   Fri Aug 29 19:18:45 2008 -0400
+
+    nfsd: fix buffer overrun decoding NFSv4 acl
+    
+    The array we kmalloc() here is not large enough.
+    
+    Thanks to Johann Dahm and David Richter for bug report and testing.
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: David Richter 
+    Tested-by: Johann Dahm 
+
+diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
+index b6ed38380ab8..54b8b4140c8f 100644
+--- a/fs/nfsd/nfs4acl.c
++++ b/fs/nfsd/nfs4acl.c
+@@ -443,7 +443,7 @@ init_state(struct posix_acl_state *state, int cnt)
+ 	 * enough space for either:
+ 	 */
+ 	alloc = sizeof(struct posix_ace_state_array)
+-		+ cnt*sizeof(struct posix_ace_state);
++		+ cnt*sizeof(struct posix_user_ace_state);
+ 	state->users = kzalloc(alloc, GFP_KERNEL);
+ 	if (!state->users)
+ 		return -ENOMEM;

commit e8b43555a2a8c71e8501924e260f62b9545c598b
+Author: J. Bruce Fields 
+Date:   Wed Jul 23 08:49:50 2008 -0400
+
+    MAINTAINERS: mention lockd and sunrpc in nfs entries
+    
+    The actual division of labor is a little vague in some of the common
+    code, but if the patches get to one of us then we can sort it out.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 0652ab384d51..c382ad39bb9b 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -2418,7 +2418,7 @@ L:	kernel-janitors@vger.kernel.org
+ W:	http://www.kerneljanitors.org/
+ S:	Maintained
+ 
+-KERNEL NFSD
++KERNEL NFSD, SUNRPC, AND LOCKD SERVERS
+ P:	J. Bruce Fields
+ M:	bfields@fieldses.org
+ P:	Neil Brown
+@@ -3036,7 +3036,7 @@ M:	ja@ssi.bg
+ L:	netdev@vger.kernel.org
+ S:	Maintained
+ 
+-NFS CLIENT
++NFS, SUNRPC, AND LOCKD CLIENTS
+ P:	Trond Myklebust
+ M:	Trond.Myklebust@netapp.com
+ L:	linux-nfs@vger.kernel.org

commit ad1060c89cfe451de849373d98e42fad58dd25ae
+Author: J. Bruce Fields 
+Date:   Fri Jul 18 15:04:16 2008 -0400
+
+    nfsd: Use C99 initializers in fs/nfsd/nfs4xdr.c
+    
+    Thanks to problem report and original patch from Harvey Harrison.
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: Harvey Harrison 
+    Cc: Benny Halevy 
+
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index 9b6a9bafc6b4..d4b9d09a6683 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -1000,43 +1000,43 @@ nfsd4_decode_notsupp(struct nfsd4_compoundargs *argp, void *p)
+ typedef __be32(*nfsd4_dec)(struct nfsd4_compoundargs *argp, void *);
+ 
+ static nfsd4_dec nfsd4_dec_ops[] = {
+-	[OP_ACCESS]		(nfsd4_dec)nfsd4_decode_access,
+-	[OP_CLOSE]		(nfsd4_dec)nfsd4_decode_close,
+-	[OP_COMMIT]		(nfsd4_dec)nfsd4_decode_commit,
+-	[OP_CREATE]		(nfsd4_dec)nfsd4_decode_create,
+-	[OP_DELEGPURGE]		(nfsd4_dec)nfsd4_decode_notsupp,
+-	[OP_DELEGRETURN]	(nfsd4_dec)nfsd4_decode_delegreturn,
+-	[OP_GETATTR]		(nfsd4_dec)nfsd4_decode_getattr,
+-	[OP_GETFH]		(nfsd4_dec)nfsd4_decode_noop,
+-	[OP_LINK]		(nfsd4_dec)nfsd4_decode_link,
+-	[OP_LOCK]		(nfsd4_dec)nfsd4_decode_lock,
+-	[OP_LOCKT]		(nfsd4_dec)nfsd4_decode_lockt,
+-	[OP_LOCKU]		(nfsd4_dec)nfsd4_decode_locku,
+-	[OP_LOOKUP]		(nfsd4_dec)nfsd4_decode_lookup,
+-	[OP_LOOKUPP]		(nfsd4_dec)nfsd4_decode_noop,
+-	[OP_NVERIFY]		(nfsd4_dec)nfsd4_decode_verify,
+-	[OP_OPEN]		(nfsd4_dec)nfsd4_decode_open,
+-	[OP_OPENATTR]		(nfsd4_dec)nfsd4_decode_notsupp,
+-	[OP_OPEN_CONFIRM]	(nfsd4_dec)nfsd4_decode_open_confirm,
+-	[OP_OPEN_DOWNGRADE]	(nfsd4_dec)nfsd4_decode_open_downgrade,
+-	[OP_PUTFH]		(nfsd4_dec)nfsd4_decode_putfh,
+-	[OP_PUTPUBFH]		(nfsd4_dec)nfsd4_decode_notsupp,
+-	[OP_PUTROOTFH]		(nfsd4_dec)nfsd4_decode_noop,
+-	[OP_READ]		(nfsd4_dec)nfsd4_decode_read,
+-	[OP_READDIR]		(nfsd4_dec)nfsd4_decode_readdir,
+-	[OP_READLINK]		(nfsd4_dec)nfsd4_decode_noop,
+-	[OP_REMOVE]		(nfsd4_dec)nfsd4_decode_remove,
+-	[OP_RENAME]		(nfsd4_dec)nfsd4_decode_rename,
+-	[OP_RENEW]		(nfsd4_dec)nfsd4_decode_renew,
+-	[OP_RESTOREFH]		(nfsd4_dec)nfsd4_decode_noop,
+-	[OP_SAVEFH]		(nfsd4_dec)nfsd4_decode_noop,
+-	[OP_SECINFO]		(nfsd4_dec)nfsd4_decode_secinfo,
+-	[OP_SETATTR]		(nfsd4_dec)nfsd4_decode_setattr,
+-	[OP_SETCLIENTID]	(nfsd4_dec)nfsd4_decode_setclientid,
+-	[OP_SETCLIENTID_CONFIRM](nfsd4_dec)nfsd4_decode_setclientid_confirm,
+-	[OP_VERIFY]		(nfsd4_dec)nfsd4_decode_verify,
+-	[OP_WRITE]		(nfsd4_dec)nfsd4_decode_write,
+-	[OP_RELEASE_LOCKOWNER]	(nfsd4_dec)nfsd4_decode_release_lockowner,
++	[OP_ACCESS]		= (nfsd4_dec)nfsd4_decode_access,
++	[OP_CLOSE]		= (nfsd4_dec)nfsd4_decode_close,
++	[OP_COMMIT]		= (nfsd4_dec)nfsd4_decode_commit,
++	[OP_CREATE]		= (nfsd4_dec)nfsd4_decode_create,
++	[OP_DELEGPURGE]		= (nfsd4_dec)nfsd4_decode_notsupp,
++	[OP_DELEGRETURN]	= (nfsd4_dec)nfsd4_decode_delegreturn,
++	[OP_GETATTR]		= (nfsd4_dec)nfsd4_decode_getattr,
++	[OP_GETFH]		= (nfsd4_dec)nfsd4_decode_noop,
++	[OP_LINK]		= (nfsd4_dec)nfsd4_decode_link,
++	[OP_LOCK]		= (nfsd4_dec)nfsd4_decode_lock,
++	[OP_LOCKT]		= (nfsd4_dec)nfsd4_decode_lockt,
++	[OP_LOCKU]		= (nfsd4_dec)nfsd4_decode_locku,
++	[OP_LOOKUP]		= (nfsd4_dec)nfsd4_decode_lookup,
++	[OP_LOOKUPP]		= (nfsd4_dec)nfsd4_decode_noop,
++	[OP_NVERIFY]		= (nfsd4_dec)nfsd4_decode_verify,
++	[OP_OPEN]		= (nfsd4_dec)nfsd4_decode_open,
++	[OP_OPENATTR]		= (nfsd4_dec)nfsd4_decode_notsupp,
++	[OP_OPEN_CONFIRM]	= (nfsd4_dec)nfsd4_decode_open_confirm,
++	[OP_OPEN_DOWNGRADE]	= (nfsd4_dec)nfsd4_decode_open_downgrade,
++	[OP_PUTFH]		= (nfsd4_dec)nfsd4_decode_putfh,
++	[OP_PUTPUBFH]		= (nfsd4_dec)nfsd4_decode_notsupp,
++	[OP_PUTROOTFH]		= (nfsd4_dec)nfsd4_decode_noop,
++	[OP_READ]		= (nfsd4_dec)nfsd4_decode_read,
++	[OP_READDIR]		= (nfsd4_dec)nfsd4_decode_readdir,
++	[OP_READLINK]		= (nfsd4_dec)nfsd4_decode_noop,
++	[OP_REMOVE]		= (nfsd4_dec)nfsd4_decode_remove,
++	[OP_RENAME]		= (nfsd4_dec)nfsd4_decode_rename,
++	[OP_RENEW]		= (nfsd4_dec)nfsd4_decode_renew,
++	[OP_RESTOREFH]		= (nfsd4_dec)nfsd4_decode_noop,
++	[OP_SAVEFH]		= (nfsd4_dec)nfsd4_decode_noop,
++	[OP_SECINFO]		= (nfsd4_dec)nfsd4_decode_secinfo,
++	[OP_SETATTR]		= (nfsd4_dec)nfsd4_decode_setattr,
++	[OP_SETCLIENTID]	= (nfsd4_dec)nfsd4_decode_setclientid,
++	[OP_SETCLIENTID_CONFIRM] = (nfsd4_dec)nfsd4_decode_setclientid_confirm,
++	[OP_VERIFY]		= (nfsd4_dec)nfsd4_decode_verify,
++	[OP_WRITE]		= (nfsd4_dec)nfsd4_decode_write,
++	[OP_RELEASE_LOCKOWNER]	= (nfsd4_dec)nfsd4_decode_release_lockowner,
+ };
+ 
+ struct nfsd4_minorversion_ops {
+@@ -1045,7 +1045,7 @@ struct nfsd4_minorversion_ops {
+ };
+ 
+ static struct nfsd4_minorversion_ops nfsd4_minorversion[] = {
+-	[0] { nfsd4_dec_ops, ARRAY_SIZE(nfsd4_dec_ops) },
++	[0] = { nfsd4_dec_ops, ARRAY_SIZE(nfsd4_dec_ops) },
+ };
+ 
+ static __be32
+@@ -2577,42 +2577,42 @@ nfsd4_encode_noop(struct nfsd4_compoundres *resp, __be32 nfserr, void *p)
+ typedef __be32(* nfsd4_enc)(struct nfsd4_compoundres *, __be32, void *);
+ 
+ static nfsd4_enc nfsd4_enc_ops[] = {
+-	[OP_ACCESS]		(nfsd4_enc)nfsd4_encode_access,
+-	[OP_CLOSE]		(nfsd4_enc)nfsd4_encode_close,
+-	[OP_COMMIT]		(nfsd4_enc)nfsd4_encode_commit,
+-	[OP_CREATE]		(nfsd4_enc)nfsd4_encode_create,
+-	[OP_DELEGPURGE]		(nfsd4_enc)nfsd4_encode_noop,
+-	[OP_DELEGRETURN]	(nfsd4_enc)nfsd4_encode_noop,
+-	[OP_GETATTR]		(nfsd4_enc)nfsd4_encode_getattr,
+-	[OP_GETFH]		(nfsd4_enc)nfsd4_encode_getfh,
+-	[OP_LINK]		(nfsd4_enc)nfsd4_encode_link,
+-	[OP_LOCK]		(nfsd4_enc)nfsd4_encode_lock,
+-	[OP_LOCKT]		(nfsd4_enc)nfsd4_encode_lockt,
+-	[OP_LOCKU]		(nfsd4_enc)nfsd4_encode_locku,
+-	[OP_LOOKUP]		(nfsd4_enc)nfsd4_encode_noop,
+-	[OP_LOOKUPP]		(nfsd4_enc)nfsd4_encode_noop,
+-	[OP_NVERIFY]		(nfsd4_enc)nfsd4_encode_noop,
+-	[OP_OPEN]		(nfsd4_enc)nfsd4_encode_open,
+-	[OP_OPEN_CONFIRM]	(nfsd4_enc)nfsd4_encode_open_confirm,
+-	[OP_OPEN_DOWNGRADE]	(nfsd4_enc)nfsd4_encode_open_downgrade,
+-	[OP_PUTFH]		(nfsd4_enc)nfsd4_encode_noop,
+-	[OP_PUTPUBFH]		(nfsd4_enc)nfsd4_encode_noop,
+-	[OP_PUTROOTFH]		(nfsd4_enc)nfsd4_encode_noop,
+-	[OP_READ]		(nfsd4_enc)nfsd4_encode_read,
+-	[OP_READDIR]		(nfsd4_enc)nfsd4_encode_readdir,
+-	[OP_READLINK]		(nfsd4_enc)nfsd4_encode_readlink,
+-	[OP_REMOVE]		(nfsd4_enc)nfsd4_encode_remove,
+-	[OP_RENAME]		(nfsd4_enc)nfsd4_encode_rename,
+-	[OP_RENEW]		(nfsd4_enc)nfsd4_encode_noop,
+-	[OP_RESTOREFH]		(nfsd4_enc)nfsd4_encode_noop,
+-	[OP_SAVEFH]		(nfsd4_enc)nfsd4_encode_noop,
+-	[OP_SECINFO]		(nfsd4_enc)nfsd4_encode_secinfo,
+-	[OP_SETATTR]		(nfsd4_enc)nfsd4_encode_setattr,
+-	[OP_SETCLIENTID]	(nfsd4_enc)nfsd4_encode_setclientid,
+-	[OP_SETCLIENTID_CONFIRM](nfsd4_enc)nfsd4_encode_noop,
+-	[OP_VERIFY]		(nfsd4_enc)nfsd4_encode_noop,
+-	[OP_WRITE]		(nfsd4_enc)nfsd4_encode_write,
+-	[OP_RELEASE_LOCKOWNER]	(nfsd4_enc)nfsd4_encode_noop,
++	[OP_ACCESS]		= (nfsd4_enc)nfsd4_encode_access,
++	[OP_CLOSE]		= (nfsd4_enc)nfsd4_encode_close,
++	[OP_COMMIT]		= (nfsd4_enc)nfsd4_encode_commit,
++	[OP_CREATE]		= (nfsd4_enc)nfsd4_encode_create,
++	[OP_DELEGPURGE]		= (nfsd4_enc)nfsd4_encode_noop,
++	[OP_DELEGRETURN]	= (nfsd4_enc)nfsd4_encode_noop,
++	[OP_GETATTR]		= (nfsd4_enc)nfsd4_encode_getattr,
++	[OP_GETFH]		= (nfsd4_enc)nfsd4_encode_getfh,
++	[OP_LINK]		= (nfsd4_enc)nfsd4_encode_link,
++	[OP_LOCK]		= (nfsd4_enc)nfsd4_encode_lock,
++	[OP_LOCKT]		= (nfsd4_enc)nfsd4_encode_lockt,
++	[OP_LOCKU]		= (nfsd4_enc)nfsd4_encode_locku,
++	[OP_LOOKUP]		= (nfsd4_enc)nfsd4_encode_noop,
++	[OP_LOOKUPP]		= (nfsd4_enc)nfsd4_encode_noop,
++	[OP_NVERIFY]		= (nfsd4_enc)nfsd4_encode_noop,
++	[OP_OPEN]		= (nfsd4_enc)nfsd4_encode_open,
++	[OP_OPEN_CONFIRM]	= (nfsd4_enc)nfsd4_encode_open_confirm,
++	[OP_OPEN_DOWNGRADE]	= (nfsd4_enc)nfsd4_encode_open_downgrade,
++	[OP_PUTFH]		= (nfsd4_enc)nfsd4_encode_noop,
++	[OP_PUTPUBFH]		= (nfsd4_enc)nfsd4_encode_noop,
++	[OP_PUTROOTFH]		= (nfsd4_enc)nfsd4_encode_noop,
++	[OP_READ]		= (nfsd4_enc)nfsd4_encode_read,
++	[OP_READDIR]		= (nfsd4_enc)nfsd4_encode_readdir,
++	[OP_READLINK]		= (nfsd4_enc)nfsd4_encode_readlink,
++	[OP_REMOVE]		= (nfsd4_enc)nfsd4_encode_remove,
++	[OP_RENAME]		= (nfsd4_enc)nfsd4_encode_rename,
++	[OP_RENEW]		= (nfsd4_enc)nfsd4_encode_noop,
++	[OP_RESTOREFH]		= (nfsd4_enc)nfsd4_encode_noop,
++	[OP_SAVEFH]		= (nfsd4_enc)nfsd4_encode_noop,
++	[OP_SECINFO]		= (nfsd4_enc)nfsd4_encode_secinfo,
++	[OP_SETATTR]		= (nfsd4_enc)nfsd4_encode_setattr,
++	[OP_SETCLIENTID]	= (nfsd4_enc)nfsd4_encode_setclientid,
++	[OP_SETCLIENTID_CONFIRM] = (nfsd4_enc)nfsd4_encode_noop,
++	[OP_VERIFY]		= (nfsd4_enc)nfsd4_encode_noop,
++	[OP_WRITE]		= (nfsd4_enc)nfsd4_encode_write,
++	[OP_RELEASE_LOCKOWNER]	= (nfsd4_enc)nfsd4_encode_noop,
+ };
+ 
+ void

commit 560de0e65904db392e1c443c4bf5ee750573336b
+Author: J. Bruce Fields 
+Date:   Tue Jul 15 15:05:45 2008 -0400
+
+    lockd: get host reference in nlmsvc_create_block() instead of callers
+    
+    It may not be obvious (till you look at the definition of
+    nlm_alloc_call()) that a function like nlmsvc_create_block() should
+    consume a reference on success or failure, so I find it clearer if it
+    takes the reference it needs itself.
+    
+    And both callers already do this immediately before the call anyway.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
+index 51a0dea0ae8a..b8f86b73a85d 100644
+--- a/fs/lockd/svclock.c
++++ b/fs/lockd/svclock.c
+@@ -180,6 +180,7 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_host *host,
+ 	struct nlm_block	*block;
+ 	struct nlm_rqst		*call = NULL;
+ 
++	nlm_get_host(host);
+ 	call = nlm_alloc_call(host);
+ 	if (call == NULL)
+ 		return NULL;
+@@ -380,8 +381,7 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
+ 	 */
+ 	block = nlmsvc_lookup_block(file, lock);
+ 	if (block == NULL) {
+-		block = nlmsvc_create_block(rqstp, nlm_get_host(host), file,
+-					    lock, cookie);
++		block = nlmsvc_create_block(rqstp, host, file, lock, cookie);
+ 		ret = nlm_lck_denied_nolocks;
+ 		if (block == NULL)
+ 			goto out;
+@@ -476,7 +476,6 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
+ 
+ 		if (conf == NULL)
+ 			return nlm_granted;
+-		nlm_get_host(host);
+ 		block = nlmsvc_create_block(rqstp, host, file, lock, cookie);
+ 		if (block == NULL) {
+ 			kfree(conf);

commit 6d7bbbbacc5202eaabbc232681cc325b22a73eeb
+Author: J. Bruce Fields 
+Date:   Tue Jul 15 14:38:32 2008 -0400
+
+    lockd: minor svclock.c style fixes
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
+index bcf73f6e8226..51a0dea0ae8a 100644
+--- a/fs/lockd/svclock.c
++++ b/fs/lockd/svclock.c
+@@ -129,9 +129,9 @@ nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock)
+ 
+ static inline int nlm_cookie_match(struct nlm_cookie *a, struct nlm_cookie *b)
+ {
+-	if(a->len != b->len)
++	if (a->len != b->len)
+ 		return 0;
+-	if(memcmp(a->data,b->data,a->len))
++	if (memcmp(a->data, b->data, a->len))
+ 		return 0;
+ 	return 1;
+ }
+@@ -381,7 +381,7 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
+ 	block = nlmsvc_lookup_block(file, lock);
+ 	if (block == NULL) {
+ 		block = nlmsvc_create_block(rqstp, nlm_get_host(host), file,
+-				lock, cookie);
++					    lock, cookie);
+ 		ret = nlm_lck_denied_nolocks;
+ 		if (block == NULL)
+ 			goto out;
+@@ -412,7 +412,7 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
+ 	lock->fl.fl_flags &= ~FL_SLEEP;
+ 
+ 	dprintk("lockd: vfs_lock_file returned %d\n", error);
+-	switch(error) {
++	switch (error) {
+ 		case 0:
+ 			ret = nlm_granted;
+ 			goto out;
+@@ -880,7 +880,7 @@ nlmsvc_retry_blocked(void)
+ 
+ 		if (block->b_when == NLM_NEVER)
+ 			break;
+-	        if (time_after(block->b_when,jiffies)) {
++		if (time_after(block->b_when, jiffies)) {
+ 			timeout = block->b_when - jiffies;
+ 			break;
+ 		}

commit 53025f5efd5a1c14fca75c479b11d97d9dd958a5
+Author: J. Bruce Fields 
+Date:   Thu Jul 10 16:47:41 2008 -0700
+
+    Documentation: clarify tcp_{r,w}mem sysctl docs
+    
+    Fix some of the defaults and attempt to clarify some language.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: David S. Miller 
+
+diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
+index 277437951e4d..dc04fdd6af34 100644
+--- a/Documentation/networking/ip-sysctl.txt
++++ b/Documentation/networking/ip-sysctl.txt
+@@ -336,7 +336,7 @@ tcp_rmem - vector of 3 INTEGERs: min, default, max
+ 	pressure.
+ 	Default: 8K
+ 
+-	default: default size of receive buffer used by TCP sockets.
++	default: initial size of receive buffer used by TCP sockets.
+ 	This value overrides net.core.rmem_default used by other protocols.
+ 	Default: 87380 bytes. This value results in window of 65535 with
+ 	default setting of tcp_adv_win_scale and tcp_app_win:0 and a bit
+@@ -344,8 +344,10 @@ tcp_rmem - vector of 3 INTEGERs: min, default, max
+ 
+ 	max: maximal size of receive buffer allowed for automatically
+ 	selected receiver buffers for TCP socket. This value does not override
+-	net.core.rmem_max, "static" selection via SO_RCVBUF does not use this.
+-	Default: 87380*2 bytes.
++	net.core.rmem_max.  Calling setsockopt() with SO_RCVBUF disables
++	automatic tuning of that socket's receive buffer size, in which
++	case this value is ignored.
++	Default: between 87380B and 4MB, depending on RAM size.
+ 
+ tcp_sack - BOOLEAN
+ 	Enable select acknowledgments (SACKS).
+@@ -419,19 +421,21 @@ tcp_window_scaling - BOOLEAN
+ 	Enable window scaling as defined in RFC1323.
+ 
+ tcp_wmem - vector of 3 INTEGERs: min, default, max
+-	min: Amount of memory reserved for send buffers for TCP socket.
++	min: Amount of memory reserved for send buffers for TCP sockets.
+ 	Each TCP socket has rights to use it due to fact of its birth.
+ 	Default: 4K
+ 
+-	default: Amount of memory allowed for send buffers for TCP socket
+-	by default. This value overrides net.core.wmem_default used
+-	by other protocols, it is usually lower than net.core.wmem_default.
++	default: initial size of send buffer used by TCP sockets.  This
++	value overrides net.core.wmem_default used by other protocols.
++	It is usually lower than net.core.wmem_default.
+ 	Default: 16K
+ 
+-	max: Maximal amount of memory allowed for automatically selected
+-	send buffers for TCP socket. This value does not override
+-	net.core.wmem_max, "static" selection via SO_SNDBUF does not use this.
+-	Default: 128K
++	max: Maximal amount of memory allowed for automatically tuned
++	send buffers for TCP sockets. This value does not override
++	net.core.wmem_max.  Calling setsockopt() with SO_SNDBUF disables
++	automatic tuning of that socket's send buffer size, in which case
++	this value is ignored.
++	Default: between 64K and 4MB, depending on RAM size.
+ 
+ tcp_workaround_signed_windows - BOOLEAN
+ 	If set, assume no receipt of a window scaling option means the

commit a486aeda9b2b0d944aecce7871b3186379b898de
+Author: J. Bruce Fields 
+Date:   Mon Jun 9 16:51:35 2008 -0400
+
+    rpc: minor cleanup of scheduler callback code
+    
+    Try to make the comment here a little more clear and concise.
+    
+    Also, this macro definition seems unnecessary.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
+index d1a5c8c1a0f1..64981a2f1cae 100644
+--- a/include/linux/sunrpc/sched.h
++++ b/include/linux/sunrpc/sched.h
+@@ -135,7 +135,6 @@ struct rpc_task_setup {
+ #define RPC_IS_SWAPPER(t)	((t)->tk_flags & RPC_TASK_SWAPPER)
+ #define RPC_DO_ROOTOVERRIDE(t)	((t)->tk_flags & RPC_TASK_ROOTCREDS)
+ #define RPC_ASSASSINATED(t)	((t)->tk_flags & RPC_TASK_KILLED)
+-#define RPC_DO_CALLBACK(t)	((t)->tk_callback != NULL)
+ #define RPC_IS_SOFT(t)		((t)->tk_flags & RPC_TASK_SOFT)
+ 
+ #define RPC_TASK_RUNNING	0
+diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
+index 6eab9bf94baf..6288af05c20f 100644
+--- a/net/sunrpc/sched.c
++++ b/net/sunrpc/sched.c
+@@ -626,19 +626,15 @@ static void __rpc_execute(struct rpc_task *task)
+ 		/*
+ 		 * Execute any pending callback.
+ 		 */
+-		if (RPC_DO_CALLBACK(task)) {
+-			/* Define a callback save pointer */
++		if (task->tk_callback) {
+ 			void (*save_callback)(struct rpc_task *);
+ 
+ 			/*
+-			 * If a callback exists, save it, reset it,
+-			 * call it.
+-			 * The save is needed to stop from resetting
+-			 * another callback set within the callback handler
+-			 * - Dave
++			 * We set tk_callback to NULL before calling it,
++			 * in case it sets the tk_callback field itself:
+ 			 */
+-			save_callback=task->tk_callback;
+-			task->tk_callback=NULL;
++			save_callback = task->tk_callback;
++			task->tk_callback = NULL;
+ 			save_callback(task);
+ 		}
+ 

commit d25a03cf966f2cf9990dc0bf2a921a554919ea34
+Author: J. Bruce Fields 
+Date:   Mon Jun 9 16:51:34 2008 -0400
+
+    rpc: remove some unused macros
+    
+    There used to be a print_hexl() function that used isprint(), now gone.
+    I don't know why NFS_NGROUPS and CA_RUN_AS_MACHINE were here.
+    
+    I also don't know why another #define that's actually used was marked
+    "unused".
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index ebfd630541fa..834a83199bdf 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -63,22 +63,11 @@ static const struct rpc_credops gss_nullops;
+ # define RPCDBG_FACILITY	RPCDBG_AUTH
+ #endif
+ 
+-#define NFS_NGROUPS	16
+-
+-#define GSS_CRED_SLACK		1024		/* XXX: unused */
++#define GSS_CRED_SLACK		1024
+ /* length of a krb5 verifier (48), plus data added before arguments when
+  * using integrity (two 4-byte integers): */
+ #define GSS_VERF_SLACK		100
+ 
+-/* XXX this define must match the gssd define
+-* as it is passed to gssd to signal the use of
+-* machine creds should be part of the shared rpc interface */
+-
+-#define CA_RUN_AS_MACHINE  0x00000200
+-
+-/* dump the buffer in `emacs-hexl' style */
+-#define isprint(c)      ((c > 0x1f) && (c < 0x7f))
+-
+ struct gss_auth {
+ 	struct kref kref;
+ 	struct rpc_auth rpc_auth;

commit 720b8f2d6f7de9e16f1217448cc7396e1604e175
+Author: J. Bruce Fields 
+Date:   Mon Jun 9 16:51:33 2008 -0400
+
+    rpc: eliminate unused variable in auth_gss upcall code
+    
+    Also, a minor comment grammar fix in the same file.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index bf7585b80543..ebfd630541fa 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -272,7 +272,7 @@ __gss_find_upcall(struct rpc_inode *rpci, uid_t uid)
+ 	return NULL;
+ }
+ 
+-/* Try to add a upcall to the pipefs queue.
++/* Try to add an upcall to the pipefs queue.
+  * If an upcall owned by our uid already exists, then we return a reference
+  * to that upcall instead of adding the new upcall.
+  */
+@@ -493,7 +493,6 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
+ {
+ 	const void *p, *end;
+ 	void *buf;
+-	struct rpc_clnt *clnt;
+ 	struct gss_upcall_msg *gss_msg;
+ 	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct gss_cl_ctx *ctx;
+@@ -507,7 +506,6 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
+ 	if (!buf)
+ 		goto out;
+ 
+-	clnt = RPC_I(inode)->private;
+ 	err = -EFAULT;
+ 	if (copy_from_user(buf, src, mlen))
+ 		goto err;

commit b6b6152c46861dd914d0e6cea9c27df057d6e235
+Author: Olga Kornievskaia 
+Date:   Mon Jun 9 16:51:31 2008 -0400
+
+    rpc: bring back cl_chatty
+    
+    The cl_chatty flag alows us to control whether a given rpc client leaves
+    
+            "server X not responding, timed out"
+    
+    messages in the syslog.  Such messages make sense for ordinary nfs
+    clients (where an unresponsive server means applications on the
+    mountpoint are probably hanging), but not for the callback client (which
+    can fail more commonly, with the only result just of disabling some
+    optimizations).
+    
+    Previously cl_chatty was removed, do to lack of users; reinstate it, and
+    use it for the nfsd's callback client.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 4d4760e687c3..702fa577aa6e 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -381,7 +381,7 @@ static int do_probe_callback(void *data)
+ 		.program	= &cb_program,
+ 		.version	= nfs_cb_version[1]->number,
+ 		.authflavor	= RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */
+-		.flags		= (RPC_CLNT_CREATE_NOPING),
++		.flags		= (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET),
+ 	};
+ 	struct rpc_message msg = {
+ 		.rpc_proc       = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
+diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
+index 6fff7f82ef12..764fd4c286e0 100644
+--- a/include/linux/sunrpc/clnt.h
++++ b/include/linux/sunrpc/clnt.h
+@@ -42,7 +42,8 @@ struct rpc_clnt {
+ 
+ 	unsigned int		cl_softrtry : 1,/* soft timeouts */
+ 				cl_discrtry : 1,/* disconnect before retry */
+-				cl_autobind : 1;/* use getport() */
++				cl_autobind : 1,/* use getport() */
++				cl_chatty   : 1;/* be verbose */
+ 
+ 	struct rpc_rtt *	cl_rtt;		/* RTO estimator data */
+ 	const struct rpc_timeout *cl_timeout;	/* Timeout strategy */
+@@ -114,6 +115,7 @@ struct rpc_create_args {
+ #define RPC_CLNT_CREATE_NONPRIVPORT	(1UL << 3)
+ #define RPC_CLNT_CREATE_NOPING		(1UL << 4)
+ #define RPC_CLNT_CREATE_DISCRTRY	(1UL << 5)
++#define RPC_CLNT_CREATE_QUIET		(1UL << 6)
+ 
+ struct rpc_clnt *rpc_create(struct rpc_create_args *args);
+ struct rpc_clnt	*rpc_bind_new_program(struct rpc_clnt *,
+diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
+index 0530eea37b59..09631f6e30e9 100644
+--- a/net/sunrpc/clnt.c
++++ b/net/sunrpc/clnt.c
+@@ -324,6 +324,8 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
+ 		clnt->cl_autobind = 1;
+ 	if (args->flags & RPC_CLNT_CREATE_DISCRTRY)
+ 		clnt->cl_discrtry = 1;
++	if (!(args->flags & RPC_CLNT_CREATE_QUIET))
++		clnt->cl_chatty = 1;
+ 
+ 	return clnt;
+ }
+@@ -1149,7 +1151,8 @@ call_status(struct rpc_task *task)
+ 		rpc_exit(task, status);
+ 		break;
+ 	default:
+-		printk("%s: RPC call returned error %d\n",
++		if (clnt->cl_chatty)
++			printk("%s: RPC call returned error %d\n",
+ 			       clnt->cl_protname, -status);
+ 		rpc_exit(task, status);
+ 	}
+@@ -1174,7 +1177,8 @@ call_timeout(struct rpc_task *task)
+ 	task->tk_timeouts++;
+ 
+ 	if (RPC_IS_SOFT(task)) {
+-		printk(KERN_NOTICE "%s: server %s not responding, timed out\n",
++		if (clnt->cl_chatty)
++			printk(KERN_NOTICE "%s: server %s not responding, timed out\n",
+ 				clnt->cl_protname, clnt->cl_server);
+ 		rpc_exit(task, -EIO);
+ 		return;
+@@ -1182,7 +1186,8 @@ call_timeout(struct rpc_task *task)
+ 
+ 	if (!(task->tk_flags & RPC_CALL_MAJORSEEN)) {
+ 		task->tk_flags |= RPC_CALL_MAJORSEEN;
+-		printk(KERN_NOTICE "%s: server %s not responding, still trying\n",
++		if (clnt->cl_chatty)
++			printk(KERN_NOTICE "%s: server %s not responding, still trying\n",
+ 			clnt->cl_protname, clnt->cl_server);
+ 	}
+ 	rpc_force_rebind(clnt);
+@@ -1213,8 +1218,9 @@ call_decode(struct rpc_task *task)
+ 			task->tk_pid, task->tk_status);
+ 
+ 	if (task->tk_flags & RPC_CALL_MAJORSEEN) {
+-		printk(KERN_NOTICE "%s: server %s OK\n",
+-			clnt->cl_protname, clnt->cl_server);
++		if (clnt->cl_chatty)
++			printk(KERN_NOTICE "%s: server %s OK\n",
++				clnt->cl_protname, clnt->cl_server);
+ 		task->tk_flags &= ~RPC_CALL_MAJORSEEN;
+ 	}
+ 

commit 4f83aa302f8f8b42397c6d3703d670f0588c03ec
+Author: J. Bruce Fields 
+Date:   Mon Jul 7 15:02:02 2008 -0400
+
+    nfsd: document open share bit tracking
+    
+    It's not immediately obvious from the code why we're doing this.
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: Benny Halevy 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index eca8aaa450f1..c29b6ed2a0bb 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1173,6 +1173,24 @@ static inline int deny_valid(u32 x)
+ 	return x <= NFS4_SHARE_DENY_BOTH;
+ }
+ 
++/*
++ * We store the NONE, READ, WRITE, and BOTH bits separately in the
++ * st_{access,deny}_bmap field of the stateid, in order to track not
++ * only what share bits are currently in force, but also what
++ * combinations of share bits previous opens have used.  This allows us
++ * to enforce the recommendation of rfc 3530 14.2.19 that the server
++ * return an error if the client attempt to downgrade to a combination
++ * of share bits not explicable by closing some of its previous opens.
++ *
++ * XXX: This enforcement is actually incomplete, since we don't keep
++ * track of access/deny bit combinations; so, e.g., we allow:
++ *
++ *	OPEN allow read, deny write
++ *	OPEN allow both, deny none
++ *	DOWNGRADE allow read, deny none
++ *
++ * which we should reject.
++ */
+ static void
+ set_access(unsigned int *access, unsigned long bmap) {
+ 	int i;

commit e86322f611eef95aafaf726fd3965e5b211f1985
+Merge: b001a1b6aa96 8948896c9e09
+Author: J. Bruce Fields 
+Date:   Thu Jul 3 16:24:06 2008 -0400
+
+    Merge branch 'for-bfields' of git://linux-nfs.org/~tomtucker/xprt-switch-2.6 into for-2.6.27
+

commit b620754bfeb8b0e0c6622b03d5ee2f1af1d3082f
+Author: J. Bruce Fields 
+Date:   Thu Jul 3 15:26:35 2008 -0400
+
+    svcrpc: fix handling of garbage args
+    
+    To return garbage_args, the accept_stat must be 0, and we must have a
+    verifier.  So we shouldn't be resetting the write pointer as we reject
+    the call.
+    
+    Also, we must add the two placeholder words here regardless of success
+    of the unwrap, to ensure the output buffer is left in a consistent state
+    for svcauth_gss_release().
+    
+    This fixes a BUG() in svcauth_gss.c:svcauth_gss_release().
+    
+    Thanks to Aime Le Rouzic for bug report, debugging help, and testing.
+    
+    Signed-off-by: J. Bruce Fields 
+    Tested-by: Aime Le Rouzic 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
+index 5905d56737d6..81ae3d62a0cc 100644
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -1144,20 +1144,20 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
+ 		case RPC_GSS_SVC_NONE:
+ 			break;
+ 		case RPC_GSS_SVC_INTEGRITY:
++			/* placeholders for length and seq. number: */
++			svc_putnl(resv, 0);
++			svc_putnl(resv, 0);
+ 			if (unwrap_integ_data(&rqstp->rq_arg,
+ 					gc->gc_seq, rsci->mechctx))
+ 				goto garbage_args;
++			break;
++		case RPC_GSS_SVC_PRIVACY:
+ 			/* placeholders for length and seq. number: */
+ 			svc_putnl(resv, 0);
+ 			svc_putnl(resv, 0);
+-			break;
+-		case RPC_GSS_SVC_PRIVACY:
+ 			if (unwrap_priv_data(rqstp, &rqstp->rq_arg,
+ 					gc->gc_seq, rsci->mechctx))
+ 				goto garbage_args;
+-			/* placeholders for length and seq. number: */
+-			svc_putnl(resv, 0);
+-			svc_putnl(resv, 0);
+ 			break;
+ 		default:
+ 			goto auth_err;
+@@ -1170,8 +1170,6 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
+ 		goto out;
+ 	}
+ garbage_args:
+-	/* Restore write pointer to its original value: */
+-	xdr_ressize_check(rqstp, reject_stat);
+ 	ret = SVC_GARBAGE;
+ 	goto out;
+ auth_err:

commit 3cd2cfeae187fb754f9530e3f919256f350e89ca
+Author: J. Bruce Fields 
+Date:   Mon Jun 2 16:01:51 2008 -0400
+
+    nfs: rewrap NFS/RDMA documentation to 80 lines
+    
+    Wrap long lines.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/Documentation/filesystems/nfs-rdma.txt b/Documentation/filesystems/nfs-rdma.txt
+index 9ad453d4891a..44bd766f2e5d 100644
+--- a/Documentation/filesystems/nfs-rdma.txt
++++ b/Documentation/filesystems/nfs-rdma.txt
+@@ -63,10 +63,10 @@ Installation
+   - Install nfs-utils-1.1.2 or greater on the client
+ 
+     An NFS/RDMA mount point can be obtained by using the mount.nfs command in
+-    nfs-utils-1.1.2 or greater (nfs-utils-1.1.1 was the first nfs-utils version
+-    with support for NFS/RDMA mounts, but for various reasons we recommend using
+-    nfs-utils-1.1.2 or greater). To see which version of mount.nfs you are
+-    using, type:
++    nfs-utils-1.1.2 or greater (nfs-utils-1.1.1 was the first nfs-utils
++    version with support for NFS/RDMA mounts, but for various reasons we
++    recommend using nfs-utils-1.1.2 or greater). To see which version of
++    mount.nfs you are using, type:
+ 
+     $ /sbin/mount.nfs -V
+ 
+@@ -91,8 +91,9 @@ Installation
+ 
+     After building the nfs-utils package, there will be a mount.nfs binary in
+     the utils/mount directory. This binary can be used to initiate NFS v2, v3,
+-    or v4 mounts. To initiate a v4 mount, the binary must be called mount.nfs4.
+-    The standard technique is to create a symlink called mount.nfs4 to mount.nfs.
++    or v4 mounts. To initiate a v4 mount, the binary must be called
++    mount.nfs4.  The standard technique is to create a symlink called
++    mount.nfs4 to mount.nfs.
+ 
+     This mount.nfs binary should be installed at /sbin/mount.nfs as follows:
+ 
+@@ -214,11 +215,11 @@ NFS/RDMA Setup
+     /vol0   192.168.0.47(fsid=0,rw,async,insecure,no_root_squash)
+     /vol0   192.168.0.0/255.255.255.0(fsid=0,rw,async,insecure,no_root_squash)
+ 
+-    The IP address(es) is(are) the client's IPoIB address for an InfiniBand HCA or the
+-    cleint's iWARP address(es) for an RNIC.
++    The IP address(es) is(are) the client's IPoIB address for an InfiniBand
++    HCA or the cleint's iWARP address(es) for an RNIC.
+ 
+-    NOTE: The "insecure" option must be used because the NFS/RDMA client does not
+-    use a reserved port.
++    NOTE: The "insecure" option must be used because the NFS/RDMA client does
++    not use a reserved port.
+ 
+  Each time a machine boots:
+ 
+@@ -234,12 +235,13 @@ NFS/RDMA Setup
+ 
+   - Start the NFS server
+ 
+-    If the NFS/RDMA server was built as a module (CONFIG_SUNRPC_XPRT_RDMA=m in kernel config),
+-    load the RDMA transport module:
++    If the NFS/RDMA server was built as a module (CONFIG_SUNRPC_XPRT_RDMA=m in
++    kernel config), load the RDMA transport module:
+ 
+     $ modprobe svcrdma
+ 
+-    Regardless of how the server was built (module or built-in), start the server:
++    Regardless of how the server was built (module or built-in), start the
++    server:
+ 
+     $ /etc/init.d/nfs start
+ 
+@@ -253,17 +255,17 @@ NFS/RDMA Setup
+ 
+   - On the client system
+ 
+-    If the NFS/RDMA client was built as a module (CONFIG_SUNRPC_XPRT_RDMA=m in kernel config),
+-    load the RDMA client module:
++    If the NFS/RDMA client was built as a module (CONFIG_SUNRPC_XPRT_RDMA=m in
++    kernel config), load the RDMA client module:
+ 
+     $ modprobe xprtrdma.ko
+ 
+-    Regardless of how the client was built (module or built-in), use this command to
+-    mount the NFS/RDMA server:
++    Regardless of how the client was built (module or built-in), use this
++    command to mount the NFS/RDMA server:
+ 
+     $ mount -o rdma,port=2050 :/ /mnt
+ 
+-    To verify that the mount is using RDMA, run "cat /proc/mounts" and check the
+-    "proto" field for the given mount.
++    To verify that the mount is using RDMA, run "cat /proc/mounts" and check
++    the "proto" field for the given mount.
+ 
+   Congratulations! You're using NFS/RDMA!

commit 863a24882ed0a57ff25daaf39885f3a47b706e4b
+Author: Kevin Coffman 
+Date:   Wed Apr 30 12:46:08 2008 -0400
+
+    gss_krb5: Use random value to initialize confounder
+    
+    Initialize the value used for the confounder to a random value
+    rather than starting from zero.
+    Allow for confounders of length 8 or 16 (which will be needed for AES).
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+index 283cb25c6237..ae8e69b59c4c 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
++++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+@@ -87,8 +87,8 @@ gss_krb5_remove_padding(struct xdr_buf *buf, int blocksize)
+ 	return 0;
+ }
+ 
+-static inline void
+-make_confounder(char *p, int blocksize)
++static void
++make_confounder(char *p, u32 conflen)
+ {
+ 	static u64 i = 0;
+ 	u64 *q = (u64 *)p;
+@@ -102,8 +102,22 @@ make_confounder(char *p, int blocksize)
+ 	 * uniqueness would mean worrying about atomicity and rollover, and I
+ 	 * don't care enough. */
+ 
+-	BUG_ON(blocksize != 8);
+-	*q = i++;
++	/* initialize to random value */
++	if (i == 0) {
++		i = random32();
++		i = (i << 32) | random32();
++	}
++
++	switch (conflen) {
++	case 16:
++		*q++ = i++;
++		/* fall through */
++	case 8:
++		*q++ = i++;
++		break;
++	default:
++		BUG();
++	}
+ }
+ 
+ /* Assumptions: the head and tail of inbuf are ours to play with.

commit db8add57898751b9c0ff93ead25f20d21da5ddd0
+Author: Kevin Coffman 
+Date:   Wed Apr 30 12:45:58 2008 -0400
+
+    gss_krb5: move gss_krb5_crypto into the krb5 module
+    
+    The gss_krb5_crypto.o object belongs in the rpcsec_gss_krb5 module.
+    Also, there is no need to export symbols from gss_krb5_crypto.c
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/net/sunrpc/auth_gss/Makefile b/net/sunrpc/auth_gss/Makefile
+index f3431a7e33da..4de8bcf26fa7 100644
+--- a/net/sunrpc/auth_gss/Makefile
++++ b/net/sunrpc/auth_gss/Makefile
+@@ -5,12 +5,12 @@
+ obj-$(CONFIG_SUNRPC_GSS) += auth_rpcgss.o
+ 
+ auth_rpcgss-objs := auth_gss.o gss_generic_token.o \
+-	gss_mech_switch.o svcauth_gss.o gss_krb5_crypto.o
++	gss_mech_switch.o svcauth_gss.o
+ 
+ obj-$(CONFIG_RPCSEC_GSS_KRB5) += rpcsec_gss_krb5.o
+ 
+ rpcsec_gss_krb5-objs := gss_krb5_mech.o gss_krb5_seal.o gss_krb5_unseal.o \
+-	gss_krb5_seqnum.o gss_krb5_wrap.o
++	gss_krb5_seqnum.o gss_krb5_wrap.o gss_krb5_crypto.o
+ 
+ obj-$(CONFIG_RPCSEC_GSS_SPKM3) += rpcsec_gss_spkm3.o
+ 
+diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+index 1d52308ca324..c93fca204558 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
++++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+@@ -83,8 +83,6 @@ krb5_encrypt(
+ 	return ret;
+ }
+ 
+-EXPORT_SYMBOL(krb5_encrypt);
+-
+ u32
+ krb5_decrypt(
+      struct crypto_blkcipher *tfm,
+@@ -118,8 +116,6 @@ krb5_decrypt(
+ 	return ret;
+ }
+ 
+-EXPORT_SYMBOL(krb5_decrypt);
+-
+ static int
+ checksummer(struct scatterlist *sg, void *data)
+ {
+@@ -161,8 +157,6 @@ make_checksum(char *cksumname, char *header, int hdrlen, struct xdr_buf *body,
+ 	return err ? GSS_S_FAILURE : 0;
+ }
+ 
+-EXPORT_SYMBOL(make_checksum);
+-
+ struct encryptor_desc {
+ 	u8 iv[8]; /* XXX hard-coded blocksize */
+ 	struct blkcipher_desc desc;
+@@ -262,8 +256,6 @@ gss_encrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *buf,
+ 	return ret;
+ }
+ 
+-EXPORT_SYMBOL(gss_encrypt_xdr_buf);
+-
+ struct decryptor_desc {
+ 	u8 iv[8]; /* XXX hard-coded blocksize */
+ 	struct blkcipher_desc desc;
+@@ -334,5 +326,3 @@ gss_decrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *buf,
+ 
+ 	return xdr_process_buf(buf, offset, buf->len - offset, decryptor, &desc);
+ }
+-
+-EXPORT_SYMBOL(gss_decrypt_xdr_buf);

commit d00953a53e9a2edbe005c1e596f1e96a8a293401
+Author: Kevin Coffman 
+Date:   Wed Apr 30 12:45:53 2008 -0400
+
+    gss_krb5: create a define for token header size and clean up ptr location
+    
+    cleanup:
+    Document token header size with a #define instead of open-coding it.
+    
+    Don't needlessly increment "ptr" past the beginning of the header
+    which makes the values passed to functions more understandable and
+    eliminates the need for extra "krb5_hdr" pointer.
+    
+    Clean up some intersecting  white-space issues flagged by checkpatch.pl.
+    
+    This leaves the checksum length hard-coded at 8 for DES.  A later patch
+    cleans that up.
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
+index a10f1fb0bf7c..e7bbdba474d5 100644
+--- a/include/linux/sunrpc/gss_krb5.h
++++ b/include/linux/sunrpc/gss_krb5.h
+@@ -51,6 +51,9 @@ struct krb5_ctx {
+ 
+ extern spinlock_t krb5_seq_lock;
+ 
++/* The length of the Kerberos GSS token header */
++#define GSS_KRB5_TOK_HDR_LEN	(16)
++
+ #define KG_TOK_MIC_MSG    0x0101
+ #define KG_TOK_WRAP_MSG   0x0201
+ 
+diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
+index 5f1d36dfbcf7..b8f42ef7178e 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
+@@ -78,7 +78,7 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
+ 	struct krb5_ctx		*ctx = gss_ctx->internal_ctx_id;
+ 	char			cksumdata[16];
+ 	struct xdr_netobj	md5cksum = {.len = 0, .data = cksumdata};
+-	unsigned char		*ptr, *krb5_hdr, *msg_start;
++	unsigned char		*ptr, *msg_start;
+ 	s32			now;
+ 	u32			seq_send;
+ 
+@@ -87,36 +87,36 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
+ 
+ 	now = get_seconds();
+ 
+-	token->len = g_token_size(&ctx->mech_used, 24);
++	token->len = g_token_size(&ctx->mech_used, GSS_KRB5_TOK_HDR_LEN + 8);
+ 
+ 	ptr = token->data;
+-	g_make_token_header(&ctx->mech_used, 24, &ptr);
++	g_make_token_header(&ctx->mech_used, GSS_KRB5_TOK_HDR_LEN + 8, &ptr);
+ 
+-	*ptr++ = (unsigned char) ((KG_TOK_MIC_MSG>>8)&0xff);
+-	*ptr++ = (unsigned char) (KG_TOK_MIC_MSG&0xff);
++	/* ptr now at header described in rfc 1964, section 1.2.1: */
++	ptr[0] = (unsigned char) ((KG_TOK_MIC_MSG >> 8) & 0xff);
++	ptr[1] = (unsigned char) (KG_TOK_MIC_MSG & 0xff);
+ 
+-	/* ptr now at byte 2 of header described in rfc 1964, section 1.2.1: */
+-	krb5_hdr = ptr - 2;
+-	msg_start = krb5_hdr + 24;
++	msg_start = ptr + GSS_KRB5_TOK_HDR_LEN + 8;
+ 
+-	*(__be16 *)(krb5_hdr + 2) = htons(SGN_ALG_DES_MAC_MD5);
+-	memset(krb5_hdr + 4, 0xff, 4);
++	*(__be16 *)(ptr + 2) = htons(SGN_ALG_DES_MAC_MD5);
++	memset(ptr + 4, 0xff, 4);
+ 
+-	if (make_checksum("md5", krb5_hdr, 8, text, 0, &md5cksum))
++	if (make_checksum("md5", ptr, 8, text, 0, &md5cksum))
+ 		return GSS_S_FAILURE;
+ 
+ 	if (krb5_encrypt(ctx->seq, NULL, md5cksum.data,
+ 			  md5cksum.data, md5cksum.len))
+ 		return GSS_S_FAILURE;
+ 
+-	memcpy(krb5_hdr + 16, md5cksum.data + md5cksum.len - 8, 8);
++	memcpy(ptr + GSS_KRB5_TOK_HDR_LEN, md5cksum.data + md5cksum.len - 8, 8);
+ 
+ 	spin_lock(&krb5_seq_lock);
+ 	seq_send = ctx->seq_send++;
+ 	spin_unlock(&krb5_seq_lock);
+ 
+ 	if (krb5_make_seq_num(ctx->seq, ctx->initiate ? 0 : 0xff,
+-			      seq_send, krb5_hdr + 16, krb5_hdr + 8))
++			      seq_send, ptr + GSS_KRB5_TOK_HDR_LEN,
++			      ptr + 8))
+ 		return GSS_S_FAILURE;
+ 
+ 	return (ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE;
+diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
+index d91a5d004803..066ec73c84d6 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
+@@ -92,30 +92,30 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
+ 					read_token->len))
+ 		return GSS_S_DEFECTIVE_TOKEN;
+ 
+-	if ((*ptr++ != ((KG_TOK_MIC_MSG>>8)&0xff)) ||
+-	    (*ptr++ != ( KG_TOK_MIC_MSG    &0xff))   )
++	if ((ptr[0] != ((KG_TOK_MIC_MSG >> 8) & 0xff)) ||
++	    (ptr[1] !=  (KG_TOK_MIC_MSG & 0xff)))
+ 		return GSS_S_DEFECTIVE_TOKEN;
+ 
+ 	/* XXX sanity-check bodysize?? */
+ 
+-	signalg = ptr[0] + (ptr[1] << 8);
++	signalg = ptr[2] + (ptr[3] << 8);
+ 	if (signalg != SGN_ALG_DES_MAC_MD5)
+ 		return GSS_S_DEFECTIVE_TOKEN;
+ 
+-	sealalg = ptr[2] + (ptr[3] << 8);
++	sealalg = ptr[4] + (ptr[5] << 8);
+ 	if (sealalg != SEAL_ALG_NONE)
+ 		return GSS_S_DEFECTIVE_TOKEN;
+ 
+-	if ((ptr[4] != 0xff) || (ptr[5] != 0xff))
++	if ((ptr[6] != 0xff) || (ptr[7] != 0xff))
+ 		return GSS_S_DEFECTIVE_TOKEN;
+ 
+-	if (make_checksum("md5", ptr - 2, 8, message_buffer, 0, &md5cksum))
++	if (make_checksum("md5", ptr, 8, message_buffer, 0, &md5cksum))
+ 		return GSS_S_FAILURE;
+ 
+ 	if (krb5_encrypt(ctx->seq, NULL, md5cksum.data, md5cksum.data, 16))
+ 		return GSS_S_FAILURE;
+ 
+-	if (memcmp(md5cksum.data + 8, ptr + 14, 8))
++	if (memcmp(md5cksum.data + 8, ptr + GSS_KRB5_TOK_HDR_LEN, 8))
+ 		return GSS_S_BAD_SIG;
+ 
+ 	/* it got through unscathed.  Make sure the context is unexpired */
+@@ -127,7 +127,7 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
+ 
+ 	/* do sequencing checks */
+ 
+-	if (krb5_get_seq_num(ctx->seq, ptr + 14, ptr + 6, &direction, &seqnum))
++	if (krb5_get_seq_num(ctx->seq, ptr + GSS_KRB5_TOK_HDR_LEN, ptr + 8, &direction, &seqnum))
+ 		return GSS_S_FAILURE;
+ 
+ 	if ((ctx->initiate && direction != 0xff) ||
+diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+index b00b1b426301..283cb25c6237 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
++++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+@@ -122,7 +122,7 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
+ 	char			cksumdata[16];
+ 	struct xdr_netobj	md5cksum = {.len = 0, .data = cksumdata};
+ 	int			blocksize = 0, plainlen;
+-	unsigned char		*ptr, *krb5_hdr, *msg_start;
++	unsigned char		*ptr, *msg_start;
+ 	s32			now;
+ 	int			headlen;
+ 	struct page		**tmp_pages;
+@@ -149,26 +149,26 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
+ 	buf->len += headlen;
+ 	BUG_ON((buf->len - offset - headlen) % blocksize);
+ 
+-	g_make_token_header(&kctx->mech_used, 24 + plainlen, &ptr);
++	g_make_token_header(&kctx->mech_used,
++				GSS_KRB5_TOK_HDR_LEN + 8 + plainlen, &ptr);
+ 
+ 
+-	*ptr++ = (unsigned char) ((KG_TOK_WRAP_MSG>>8)&0xff);
+-	*ptr++ = (unsigned char) (KG_TOK_WRAP_MSG&0xff);
++	/* ptr now at header described in rfc 1964, section 1.2.1: */
++	ptr[0] = (unsigned char) ((KG_TOK_WRAP_MSG >> 8) & 0xff);
++	ptr[1] = (unsigned char) (KG_TOK_WRAP_MSG & 0xff);
+ 
+-	/* ptr now at byte 2 of header described in rfc 1964, section 1.2.1: */
+-	krb5_hdr = ptr - 2;
+-	msg_start = krb5_hdr + 24;
++	msg_start = ptr + 24;
+ 
+-	*(__be16 *)(krb5_hdr + 2) = htons(SGN_ALG_DES_MAC_MD5);
+-	memset(krb5_hdr + 4, 0xff, 4);
+-	*(__be16 *)(krb5_hdr + 4) = htons(SEAL_ALG_DES);
++	*(__be16 *)(ptr + 2) = htons(SGN_ALG_DES_MAC_MD5);
++	memset(ptr + 4, 0xff, 4);
++	*(__be16 *)(ptr + 4) = htons(SEAL_ALG_DES);
+ 
+ 	make_confounder(msg_start, blocksize);
+ 
+ 	/* XXXJBF: UGH!: */
+ 	tmp_pages = buf->pages;
+ 	buf->pages = pages;
+-	if (make_checksum("md5", krb5_hdr, 8, buf,
++	if (make_checksum("md5", ptr, 8, buf,
+ 				offset + headlen - blocksize, &md5cksum))
+ 		return GSS_S_FAILURE;
+ 	buf->pages = tmp_pages;
+@@ -176,7 +176,7 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
+ 	if (krb5_encrypt(kctx->seq, NULL, md5cksum.data,
+ 			  md5cksum.data, md5cksum.len))
+ 		return GSS_S_FAILURE;
+-	memcpy(krb5_hdr + 16, md5cksum.data + md5cksum.len - 8, 8);
++	memcpy(ptr + GSS_KRB5_TOK_HDR_LEN, md5cksum.data + md5cksum.len - 8, 8);
+ 
+ 	spin_lock(&krb5_seq_lock);
+ 	seq_send = kctx->seq_send++;
+@@ -185,7 +185,7 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
+ 	/* XXX would probably be more efficient to compute checksum
+ 	 * and encrypt at the same time: */
+ 	if ((krb5_make_seq_num(kctx->seq, kctx->initiate ? 0 : 0xff,
+-			       seq_send, krb5_hdr + 16, krb5_hdr + 8)))
++			       seq_send, ptr + GSS_KRB5_TOK_HDR_LEN, ptr + 8)))
+ 		return GSS_S_FAILURE;
+ 
+ 	if (gss_encrypt_xdr_buf(kctx->enc, buf, offset + headlen - blocksize,
+@@ -219,38 +219,38 @@ gss_unwrap_kerberos(struct gss_ctx *ctx, int offset, struct xdr_buf *buf)
+ 					buf->len - offset))
+ 		return GSS_S_DEFECTIVE_TOKEN;
+ 
+-	if ((*ptr++ != ((KG_TOK_WRAP_MSG>>8)&0xff)) ||
+-	    (*ptr++ !=  (KG_TOK_WRAP_MSG    &0xff))   )
++	if ((ptr[0] != ((KG_TOK_WRAP_MSG >> 8) & 0xff)) ||
++	    (ptr[1] !=  (KG_TOK_WRAP_MSG & 0xff)))
+ 		return GSS_S_DEFECTIVE_TOKEN;
+ 
+ 	/* XXX sanity-check bodysize?? */
+ 
+ 	/* get the sign and seal algorithms */
+ 
+-	signalg = ptr[0] + (ptr[1] << 8);
++	signalg = ptr[2] + (ptr[3] << 8);
+ 	if (signalg != SGN_ALG_DES_MAC_MD5)
+ 		return GSS_S_DEFECTIVE_TOKEN;
+ 
+-	sealalg = ptr[2] + (ptr[3] << 8);
++	sealalg = ptr[4] + (ptr[5] << 8);
+ 	if (sealalg != SEAL_ALG_DES)
+ 		return GSS_S_DEFECTIVE_TOKEN;
+ 
+-	if ((ptr[4] != 0xff) || (ptr[5] != 0xff))
++	if ((ptr[6] != 0xff) || (ptr[7] != 0xff))
+ 		return GSS_S_DEFECTIVE_TOKEN;
+ 
+ 	if (gss_decrypt_xdr_buf(kctx->enc, buf,
+-			ptr + 22 - (unsigned char *)buf->head[0].iov_base))
++			ptr + GSS_KRB5_TOK_HDR_LEN + 8 - (unsigned char *)buf->head[0].iov_base))
+ 		return GSS_S_DEFECTIVE_TOKEN;
+ 
+-	if (make_checksum("md5", ptr - 2, 8, buf,
+-		 ptr + 22 - (unsigned char *)buf->head[0].iov_base, &md5cksum))
++	if (make_checksum("md5", ptr, 8, buf,
++		 ptr + GSS_KRB5_TOK_HDR_LEN + 8 - (unsigned char *)buf->head[0].iov_base, &md5cksum))
+ 		return GSS_S_FAILURE;
+ 
+ 	if (krb5_encrypt(kctx->seq, NULL, md5cksum.data,
+ 			   md5cksum.data, md5cksum.len))
+ 		return GSS_S_FAILURE;
+ 
+-	if (memcmp(md5cksum.data + 8, ptr + 14, 8))
++	if (memcmp(md5cksum.data + 8, ptr + GSS_KRB5_TOK_HDR_LEN, 8))
+ 		return GSS_S_BAD_SIG;
+ 
+ 	/* it got through unscathed.  Make sure the context is unexpired */
+@@ -262,8 +262,8 @@ gss_unwrap_kerberos(struct gss_ctx *ctx, int offset, struct xdr_buf *buf)
+ 
+ 	/* do sequencing checks */
+ 
+-	if (krb5_get_seq_num(kctx->seq, ptr + 14, ptr + 6, &direction,
+-				    &seqnum))
++	if (krb5_get_seq_num(kctx->seq, ptr + GSS_KRB5_TOK_HDR_LEN, ptr + 8,
++				    &direction, &seqnum))
+ 		return GSS_S_BAD_SIG;
+ 
+ 	if ((kctx->initiate && direction != 0xff) ||
+@@ -274,7 +274,7 @@ gss_unwrap_kerberos(struct gss_ctx *ctx, int offset, struct xdr_buf *buf)
+ 	 * better to copy and encrypt at the same time. */
+ 
+ 	blocksize = crypto_blkcipher_blocksize(kctx->enc);
+-	data_start = ptr + 22 + blocksize;
++	data_start = ptr + GSS_KRB5_TOK_HDR_LEN + 8 + blocksize;
+ 	orig_start = buf->head[0].iov_base + offset;
+ 	data_len = (buf->head[0].iov_base + buf->head[0].iov_len) - data_start;
+ 	memmove(orig_start, data_start, data_len);

commit 7c11337d9d81cde0a08a0da63cbfb20653890fa1
+Author: J. Bruce Fields 
+Date:   Wed Jun 4 18:50:06 2008 -0400
+
+    nfsd: remove three unused NFS4_ACE_* defines
+    
+    These flag bits aren't used by either the protocol or our
+    implementation, so I don't know why they were here.
+    
+    Thanks to Johann Dahm for running across these.
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: Johann Dahm 
+
+diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
+index 8726491de154..ea0366769484 100644
+--- a/include/linux/nfs4.h
++++ b/include/linux/nfs4.h
+@@ -65,9 +65,6 @@
+ #define NFS4_ACE_SUCCESSFUL_ACCESS_ACE_FLAG   0x00000010
+ #define NFS4_ACE_FAILED_ACCESS_ACE_FLAG       0x00000020
+ #define NFS4_ACE_IDENTIFIER_GROUP             0x00000040
+-#define NFS4_ACE_OWNER                        0x00000080
+-#define NFS4_ACE_GROUP                        0x00000100
+-#define NFS4_ACE_EVERYONE                     0x00000200
+ 
+ #define NFS4_ACE_READ_DATA                    0x00000001
+ #define NFS4_ACE_LIST_DIRECTORY               0x00000001

commit 3b12cd9862d5f560031d90bda78952ab55e36b24
+Author: J. Bruce Fields 
+Date:   Mon May 5 17:17:44 2008 -0400
+
+    nfsd: add dprintk of compound return
+    
+    We already print each operation of the compound when debugging is turned
+    on; printing the result could also help with remote debugging.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index c309c881bd4e..313484380a9b 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -952,6 +952,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
+ out:
+ 	nfsd4_release_compoundargs(args);
+ 	cstate_free(cstate);
++	dprintk("nfsv4 compound returned %d\n", ntohl(status));
+ 	return status;
+ }
+ 

commit 68432a03f8ff93a9eecee95cc8f02e7fe2025cc9
+Merge: d71a4dd72e67 a6f911c04e20
+Author: J. Bruce Fields 
+Date:   Tue May 20 19:57:38 2008 -0400
+
+    Merge branch 'from-tomtucker' into for-2.6.26
+

commit d71a4dd72e67210ae0767ccae69c79f1c933ff64
+Author: J. Bruce Fields 
+Date:   Fri May 9 12:01:19 2008 -0700
+
+    svcrpc: fix proc/net/rpc/auth.unix.ip/content display
+    
+    Commit f15364bd4cf8799a7677b6daeed7b67d9139d974 ("IPv6 support for NFS
+    server export caches") dropped a couple spaces, rendering the output
+    here difficult to read.
+    
+    (However note that we expect the output to be parsed only by humans, not
+    machines, so this shouldn't have broken any userland software.)
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
+index 3f30ee6006ae..f24800f2c098 100644
+--- a/net/sunrpc/svcauth_unix.c
++++ b/net/sunrpc/svcauth_unix.c
+@@ -278,7 +278,7 @@ static int ip_map_show(struct seq_file *m,
+ 		dom = im->m_client->h.name;
+ 
+ 	if (ipv6_addr_v4mapped(&addr)) {
+-		seq_printf(m, "%s" NIPQUAD_FMT "%s\n",
++		seq_printf(m, "%s " NIPQUAD_FMT " %s\n",
+ 			im->m_class,
+ 			ntohl(addr.s6_addr32[3]) >> 24 & 0xff,
+ 			ntohl(addr.s6_addr32[3]) >> 16 & 0xff,
+@@ -286,7 +286,7 @@ static int ip_map_show(struct seq_file *m,
+ 			ntohl(addr.s6_addr32[3]) >>  0 & 0xff,
+ 			dom);
+ 	} else {
+-		seq_printf(m, "%s" NIP6_FMT "%s\n",
++		seq_printf(m, "%s " NIP6_FMT " %s\n",
+ 			im->m_class, NIP6(addr), dom);
+ 	}
+ 	return 0;

commit 88dd0be3874566796fa4ffbdf927a53c4a6a2f4b
+Author: J. Bruce Fields 
+Date:   Mon May 5 19:47:29 2008 -0400
+
+    nfsd: reorder printk in do_probe_callback to avoid use-after-free
+    
+    We're currently dereferencing the client after we drop our reference
+    count to it.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 0b3ffa9840c2..4d4760e687c3 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -419,9 +419,9 @@ static int do_probe_callback(void *data)
+ out_release_client:
+ 	rpc_shutdown_client(client);
+ out_err:
+-	put_nfs4_client(clp);
+ 	dprintk("NFSD: warning: no callback path to client %.*s\n",
+ 		(int)clp->cl_name.len, clp->cl_name.data);
++	put_nfs4_client(clp);
+ 	return status;
+ }
+ 

commit b55e0ba19cd2d83317a7f1dbb626080951442ab3
+Author: J. Bruce Fields 
+Date:   Mon Apr 28 18:22:50 2008 -0400
+
+    nfsd: remove unnecessary atomic ops
+    
+    These bit operations don't need to be atomic.  They're all done under a
+    single big mutex anyway.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 8799b8708188..5c97d47676ae 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1579,8 +1579,8 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_sta
+ 	}
+ 	/* remember the open */
+ 	filp->f_mode |= open->op_share_access;
+-	set_bit(open->op_share_access, &stp->st_access_bmap);
+-	set_bit(open->op_share_deny, &stp->st_deny_bmap);
++	__set_bit(open->op_share_access, &stp->st_access_bmap);
++	__set_bit(open->op_share_deny, &stp->st_deny_bmap);
+ 
+ 	return nfs_ok;
+ }

commit 38def50fabc479dc96ea6bd2cb2526e0dfc36fa4
+Author: Fred Isaman 
+Date:   Thu May 1 20:03:22 2008 +0300
+
+    nfs: fix race in nfs_dirty_request
+    
+    When called from nfs_flush_incompatible, the req is not locked, so
+    req->wb_page might be set to NULL before it is used by PageWriteback.
+    
+    Signed-off-by: Fred Isaman 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/write.c b/fs/nfs/write.c
+index 1ade11d1ba07..6d8ace3e3259 100644
+--- a/fs/nfs/write.c
++++ b/fs/nfs/write.c
+@@ -415,7 +415,7 @@ nfs_dirty_request(struct nfs_page *req)
+ 
+ 	if (page == NULL || test_bit(PG_NEED_COMMIT, &req->wb_flags))
+ 		return 0;
+-	return !PageWriteback(req->wb_page);
++	return !PageWriteback(page);
+ }
+ 
+ #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)

commit dceba9944181b1fd5993417b5c8fa0e3dda38f8d
+Author: Kevin Coffman 
+Date:   Tue Apr 29 01:01:22 2008 -0700
+
+    keys: check starting keyring as part of search
+    
+    Check the starting keyring as part of the search to (a) see if that is what
+    we're searching for, and (b) to check it is still valid for searching.
+    
+    The scenario: User in process A does things that cause things to be created in
+    its process session keyring.  The user then does an su to another user and
+    starts a new process, B.  The two processes now share the same process session
+    keyring.
+    
+    Process B does an NFS access which results in an upcall to gssd.  When gssd
+    attempts to instantiate the context key (to be linked into the process session
+    keyring), it is denied access even though it has an authorization key.
+    
+    The order of calls is:
+    
+       keyctl_instantiate_key()
+          lookup_user_key()                             (the default: case)
+             search_process_keyrings(current)
+                search_process_keyrings(rka->context)   (recursive call)
+                   keyring_search_aux()
+    
+    keyring_search_aux() verifies the keys and keyrings underneath the top-level
+    keyring it is given, but that top-level keyring is neither fully validated nor
+    checked to see if it is the thing being searched for.
+    
+    This patch changes keyring_search_aux() to:
+    1) do more validation on the top keyring it is given and
+    2) check whether that top-level keyring is the thing being searched for
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: David Howells 
+    Cc: Paul Moore 
+    Cc: Chris Wright 
+    Cc: Stephen Smalley 
+    Cc: James Morris 
+    Cc: Kevin Coffman 
+    Cc: Trond Myklebust 
+    Cc: "J. Bruce Fields" 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/security/keys/keyring.c b/security/keys/keyring.c
+index 88292e3dee96..70f0c313c888 100644
+--- a/security/keys/keyring.c
++++ b/security/keys/keyring.c
+@@ -292,7 +292,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
+ 
+ 	struct keyring_list *keylist;
+ 	struct timespec now;
+-	unsigned long possessed;
++	unsigned long possessed, kflags;
+ 	struct key *keyring, *key;
+ 	key_ref_t key_ref;
+ 	long err;
+@@ -319,6 +319,32 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
+ 	err = -EAGAIN;
+ 	sp = 0;
+ 
++	/* firstly we should check to see if this top-level keyring is what we
++	 * are looking for */
++	key_ref = ERR_PTR(-EAGAIN);
++	kflags = keyring->flags;
++	if (keyring->type == type && match(keyring, description)) {
++		key = keyring;
++
++		/* check it isn't negative and hasn't expired or been
++		 * revoked */
++		if (kflags & (1 << KEY_FLAG_REVOKED))
++			goto error_2;
++		if (key->expiry && now.tv_sec >= key->expiry)
++			goto error_2;
++		key_ref = ERR_PTR(-ENOKEY);
++		if (kflags & (1 << KEY_FLAG_NEGATIVE))
++			goto error_2;
++		goto found;
++	}
++
++	/* otherwise, the top keyring must not be revoked, expired, or
++	 * negatively instantiated if we are to search it */
++	key_ref = ERR_PTR(-EAGAIN);
++	if (kflags & ((1 << KEY_FLAG_REVOKED) | (1 << KEY_FLAG_NEGATIVE)) ||
++	    (keyring->expiry && now.tv_sec >= keyring->expiry))
++		goto error_2;
++
+ 	/* start processing a new keyring */
+ descend:
+ 	if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
+@@ -331,13 +357,14 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
+ 	/* iterate through the keys in this keyring first */
+ 	for (kix = 0; kix < keylist->nkeys; kix++) {
+ 		key = keylist->keys[kix];
++		kflags = key->flags;
+ 
+ 		/* ignore keys not of this type */
+ 		if (key->type != type)
+ 			continue;
+ 
+ 		/* skip revoked keys and expired keys */
+-		if (test_bit(KEY_FLAG_REVOKED, &key->flags))
++		if (kflags & (1 << KEY_FLAG_REVOKED))
+ 			continue;
+ 
+ 		if (key->expiry && now.tv_sec >= key->expiry)
+@@ -352,8 +379,8 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
+ 					context, KEY_SEARCH) < 0)
+ 			continue;
+ 
+-		/* we set a different error code if we find a negative key */
+-		if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) {
++		/* we set a different error code if we pass a negative key */
++		if (kflags & (1 << KEY_FLAG_NEGATIVE)) {
+ 			err = -ENOKEY;
+ 			continue;
+ 		}

commit e36cd4a2873c398ba188f16e4087cce7f00a1506
+Author: J. Bruce Fields 
+Date:   Thu Apr 24 16:59:30 2008 -0400
+
+    nfsd: don't allow setting ctime over v4
+    
+    Presumably this is left over from earlier drafts of v4, which listed
+    TIME_METADATA as writeable.  It's read-only in rfc 3530, and shouldn't
+    be modifiable anyway.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index 1ba7ad981935..c513bbdf2d36 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -376,20 +376,6 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia
+ 			goto xdr_error;
+ 		}
+ 	}
+-	if (bmval[1] & FATTR4_WORD1_TIME_METADATA) {
+-		/* We require the high 32 bits of 'seconds' to be 0, and we ignore
+-		   all 32 bits of 'nseconds'. */
+-		READ_BUF(12);
+-		len += 12;
+-		READ32(dummy32);
+-		if (dummy32)
+-			return nfserr_inval;
+-		READ32(iattr->ia_ctime.tv_sec);
+-		READ32(iattr->ia_ctime.tv_nsec);
+-		if (iattr->ia_ctime.tv_nsec >= (u32)1000000000)
+-			return nfserr_inval;
+-		iattr->ia_valid |= ATTR_CTIME;
+-	}
+ 	if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
+ 		READ_BUF(4);
+ 		len += 4;
+diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
+index 21ee440dd3e7..41d30c9c9de6 100644
+--- a/include/linux/nfsd/nfsd.h
++++ b/include/linux/nfsd/nfsd.h
+@@ -329,7 +329,7 @@ extern struct timeval	nfssvc_boot;
+ (FATTR4_WORD0_SIZE              | FATTR4_WORD0_ACL                                         )
+ #define NFSD_WRITEABLE_ATTRS_WORD1                                                          \
+ (FATTR4_WORD1_MODE              | FATTR4_WORD1_OWNER         | FATTR4_WORD1_OWNER_GROUP     \
+- | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_METADATA | FATTR4_WORD1_TIME_MODIFY_SET)
++ | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET)
+ 
+ #endif /* CONFIG_NFSD_V4 */
+ 

commit 1a747ee0cc11a198f9e2435add821bd0dfedb7c1
+Author: J. Bruce Fields 
+Date:   Thu Apr 24 10:08:22 2008 -0400
+
+    locks: don't call ->copy_lock methods on return of conflicting locks
+    
+    The file_lock structure is used both as a heavy-weight representation of
+    an active lock, with pointers to reference-counted structures, etc., and
+    as a simple container for parameters that describe a file lock.
+    
+    The conflicting lock returned from __posix_lock_file is an example of
+    the latter; so don't call the filesystem or lock manager callbacks when
+    copying to it.  This also saves the need for an unnecessary
+    locks_init_lock in the nfsv4 server.
+    
+    Thanks to Trond for pointing out the error.
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: Trond Myklebust 
+
+diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
+index 1f122c1940af..4d81553d2948 100644
+--- a/fs/lockd/svclock.c
++++ b/fs/lockd/svclock.c
+@@ -632,7 +632,7 @@ nlmsvc_update_deferred_block(struct nlm_block *block, struct file_lock *conf,
+ 		block->b_flags |= B_TIMED_OUT;
+ 	if (conf) {
+ 		if (block->b_fl)
+-			locks_copy_lock(block->b_fl, conf);
++			__locks_copy_lock(block->b_fl, conf);
+ 	}
+ }
+ 
+diff --git a/fs/locks.c b/fs/locks.c
+index 2e0fa661e423..e1ea2fe03681 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -224,7 +224,7 @@ static void locks_copy_private(struct file_lock *new, struct file_lock *fl)
+ /*
+  * Initialize a new lock from an existing file_lock structure.
+  */
+-static void __locks_copy_lock(struct file_lock *new, const struct file_lock *fl)
++void __locks_copy_lock(struct file_lock *new, const struct file_lock *fl)
+ {
+ 	new->fl_owner = fl->fl_owner;
+ 	new->fl_pid = fl->fl_pid;
+@@ -833,7 +833,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
+ 			if (!posix_locks_conflict(request, fl))
+ 				continue;
+ 			if (conflock)
+-				locks_copy_lock(conflock, fl);
++				__locks_copy_lock(conflock, fl);
+ 			error = -EAGAIN;
+ 			if (!(request->fl_flags & FL_SLEEP))
+ 				goto out;
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 55dfdd71f1b0..8799b8708188 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2712,9 +2712,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	* Note: locks.c uses the BKL to protect the inode's lock list.
+ 	*/
+ 
+-	/* XXX?: Just to divert the locks_release_private at the start of
+-	 * locks_copy_lock: */
+-	locks_init_lock(&conflock);
+ 	err = vfs_lock_file(filp, cmd, &file_lock, &conflock);
+ 	switch (-err) {
+ 	case 0: /* success! */
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index cc2be2cf7d41..6556f2f967e5 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -973,6 +973,7 @@ extern int do_sync_mapping_range(struct address_space *mapping, loff_t offset,
+ /* fs/locks.c */
+ extern void locks_init_lock(struct file_lock *);
+ extern void locks_copy_lock(struct file_lock *, struct file_lock *);
++extern void __locks_copy_lock(struct file_lock *, const struct file_lock *);
+ extern void locks_remove_posix(struct file *, fl_owner_t);
+ extern void locks_remove_flock(struct file *);
+ extern void posix_test_lock(struct file *, struct file_lock *);

commit 9d91cdcc0cce3186742f38e7352459b2087fbb86
+Author: David M. Richter 
+Date:   Wed Apr 23 16:29:02 2008 -0400
+
+    leases: remove unneeded variable from fcntl_setlease().
+    
+    fcntl_setlease() has a struct dentry* that is used only once; this patch
+    removes it.
+    
+    Signed-off-by: David M. Richter 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/locks.c b/fs/locks.c
+index 6a132cd4fa57..2e0fa661e423 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -1493,8 +1493,7 @@ EXPORT_SYMBOL_GPL(vfs_setlease);
+ int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
+ {
+ 	struct file_lock fl, *flp = &fl;
+-	struct dentry *dentry = filp->f_path.dentry;
+-	struct inode *inode = dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	int error;
+ 
+ 	locks_init_lock(&fl);

commit 190855576743a510219fc67886dace29b825d8cb
+Author: David M. Richter 
+Date:   Wed Apr 23 16:29:01 2008 -0400
+
+    leases: move lock allocation earlier in generic_setlease()
+    
+    In generic_setlease(), the struct file_lock is allocated after tests for the
+    presence of conflicting readers/writers is done, despite the fact that the
+    allocation might block; this patch moves the allocation earlier.  A subsequent
+    set of patches will rely on this behavior to properly serialize between a
+    modified __break_lease() and generic_setlease().
+    
+    Signed-off-by: David M. Richter 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/locks.c b/fs/locks.c
+index da1d0ddb4abd..6a132cd4fa57 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -1368,6 +1368,11 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
+ 	lease = *flp;
+ 
+ 	if (arg != F_UNLCK) {
++		error = -ENOMEM;
++		new_fl = locks_alloc_lock();
++		if (new_fl == NULL)
++			goto out;
++
+ 		error = -EAGAIN;
+ 		if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
+ 			goto out;
+@@ -1375,11 +1380,6 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
+ 		    && ((atomic_read(&dentry->d_count) > 1)
+ 			|| (atomic_read(&inode->i_count) > 1)))
+ 			goto out;
+-
+-		error = -ENOMEM;
+-		new_fl = locks_alloc_lock();
+-		if (new_fl == NULL)
+-			goto out;
+ 	}
+ 
+ 	/*

commit 288b2fd8251cb0bcb14b8a93755ef9c78de70e0f
+Author: David M. Richter 
+Date:   Wed Apr 23 16:29:00 2008 -0400
+
+    leases: when unlocking, skip locking-related steps
+    
+    In generic_setlease(), we don't need to allocate a new struct file_lock
+    or check for readers or writers when called with F_UNLCK.
+    
+    Signed-off-by: David M. Richter 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/locks.c b/fs/locks.c
+index b9f3a0bed300..da1d0ddb4abd 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -1367,18 +1367,20 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
+ 
+ 	lease = *flp;
+ 
+-	error = -EAGAIN;
+-	if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
+-		goto out;
+-	if ((arg == F_WRLCK)
+-	    && ((atomic_read(&dentry->d_count) > 1)
+-		|| (atomic_read(&inode->i_count) > 1)))
+-		goto out;
++	if (arg != F_UNLCK) {
++		error = -EAGAIN;
++		if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
++			goto out;
++		if ((arg == F_WRLCK)
++		    && ((atomic_read(&dentry->d_count) > 1)
++			|| (atomic_read(&inode->i_count) > 1)))
++			goto out;
+ 
+-	error = -ENOMEM;
+-	new_fl = locks_alloc_lock();
+-	if (new_fl == NULL)
+-		goto out;
++		error = -ENOMEM;
++		new_fl = locks_alloc_lock();
++		if (new_fl == NULL)
++			goto out;
++	}
+ 
+ 	/*
+ 	 * At this point, we know that if there is an exclusive

commit 5fcc60c3a05bf417229fba715e7aec52bf6717fb
+Author: David M. Richter 
+Date:   Wed Apr 23 16:28:59 2008 -0400
+
+    leases: fix a return-value mixup
+    
+    Fixes a return-value mixup from 85c59580b30c82aa771aa33b37217a6b6851bc14
+    "locks: Fix potential OOPS in generic_setlease()", in which -ENOMEM replaced
+    what had been intended to stay -EAGAIN in the variable "error".
+    
+    Signed-off-by: David M. Richter 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/locks.c b/fs/locks.c
+index 592faadbcec1..b9f3a0bed300 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -1404,6 +1404,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
+ 			rdlease_count++;
+ 	}
+ 
++	error = -EAGAIN;
+ 	if ((arg == F_RDLCK && (wrlease_count > 0)) ||
+ 	    (arg == F_WRLCK && ((rdlease_count + wrlease_count) > 0)))
+ 		goto out;

commit ff7d9756b501744540be65e172d27ee321d86103
+Author: Olga Kornievskaia 
+Date:   Fri Mar 28 16:04:56 2008 -0400
+
+    nfsd: use static memory for callback program and stats
+    
+    There's no need to dynamically allocate this memory, and doing so may
+    create the possibility of races on shutdown of the rpc client.  (We've
+    witnessed it only after adding rpcsec_gss support to the server, after
+    which the rpc code can send destroys calls that expect to still be able
+    to access the rpc_stats structure after it has been destroyed.)
+    
+    Such races are in theory possible if the module containing this "static"
+    memory is removed very quickly after an rpc client is destroyed, but
+    we haven't seen that happen.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index aae2b29ae2c9..562abf3380d0 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -344,6 +344,21 @@ static struct rpc_version *	nfs_cb_version[] = {
+ 	&nfs_cb_version4,
+ };
+ 
++static struct rpc_program cb_program;
++
++static struct rpc_stat cb_stats = {
++		.program	= &cb_program
++};
++
++#define NFS4_CALLBACK 0x40000000
++static struct rpc_program cb_program = {
++		.name 		= "nfs4_cb",
++		.number		= NFS4_CALLBACK,
++		.nrvers		= ARRAY_SIZE(nfs_cb_version),
++		.version	= nfs_cb_version,
++		.stats		= &cb_stats,
++};
++
+ /* Reference counting, callback cleanup, etc., all look racy as heck.
+  * And why is cb_set an atomic? */
+ 
+@@ -358,13 +373,12 @@ static int do_probe_callback(void *data)
+ 		.to_maxval	= (NFSD_LEASE_TIME/2) * HZ,
+ 		.to_exponential	= 1,
+ 	};
+-	struct rpc_program *	program = &cb->cb_program;
+ 	struct rpc_create_args args = {
+ 		.protocol	= IPPROTO_TCP,
+ 		.address	= (struct sockaddr *)&addr,
+ 		.addrsize	= sizeof(addr),
+ 		.timeout	= &timeparms,
+-		.program	= program,
++		.program	= &cb_program,
+ 		.version	= nfs_cb_version[1]->number,
+ 		.authflavor	= RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */
+ 		.flags		= (RPC_CLNT_CREATE_NOPING),
+@@ -382,16 +396,8 @@ static int do_probe_callback(void *data)
+ 	addr.sin_port = htons(cb->cb_port);
+ 	addr.sin_addr.s_addr = htonl(cb->cb_addr);
+ 
+-	/* Initialize rpc_program */
+-	program->name = "nfs4_cb";
+-	program->number = cb->cb_prog;
+-	program->nrvers = ARRAY_SIZE(nfs_cb_version);
+-	program->version = nfs_cb_version;
+-	program->stats = &cb->cb_stat;
+-
+ 	/* Initialize rpc_stat */
+-	memset(program->stats, 0, sizeof(cb->cb_stat));
+-	program->stats->program = program;
++	memset(args.program->stats, 0, sizeof(struct rpc_stat));
+ 
+ 	/* Create RPC client */
+ 	client = rpc_create(&args);

commit e1ba1ab76e68de9f4a93fae8406627924efaed99
+Author: J. Bruce Fields 
+Date:   Mon Apr 7 13:09:47 2008 -0400
+
+    nfsd: fix comment
+    
+    Obvious comment nit.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
+index 2e5de77ff030..a9f153867554 100644
+--- a/fs/nfs/callback.c
++++ b/fs/nfs/callback.c
+@@ -153,7 +153,7 @@ int nfs_callback_up(void)
+ }
+ 
+ /*
+- * Kill the server process if it is not already up.
++ * Kill the server process if it is not already down.
+  */
+ void nfs_callback_down(void)
+ {

commit 3c61eecb607dbc2777074b1a95b8a97e31a96a73
+Author: J. Bruce Fields 
+Date:   Mon Apr 7 13:05:27 2008 -0400
+
+    lockd: Fix stale nlmsvc_unlink_block comment
+    
+    As of 5996a298da43a03081e9ba2116983d173001c862 ("NLM: don't unlock on
+    cancel requests") we no longer unlock in this case, so the comment is no
+    longer accurate.
+    
+    Thanks to Stuart Friedberg for pointing out the inconsistency.
+    
+    Cc: Stuart Friedberg 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
+index 4da7c4c27064..1f122c1940af 100644
+--- a/fs/lockd/svclock.c
++++ b/fs/lockd/svclock.c
+@@ -227,8 +227,7 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_host *host,
+ }
+ 
+ /*
+- * Delete a block. If the lock was cancelled or the grant callback
+- * failed, unlock is set to 1.
++ * Delete a block.
+  * It is the caller's responsibility to check whether the file
+  * can be closed hereafter.
+  */

commit 4ab4b0bedda7d41c63cef98cd5d6cabada460936
+Author: Kevin Coffman 
+Date:   Mon Mar 31 10:31:44 2008 -0400
+
+    sunrpc: make token header values less confusing
+    
+    g_make_token_header() and g_token_size() add two too many, and
+    therefore their callers pass in "(logical_value - 2)" rather
+    than "logical_value" as hard-coded values which causes confusion.
+    
+    This dates back to the original g_make_token_header which took an
+    optional token type (token_id) value and added it to the token.
+    This was removed, but the routine always adds room for the token_id
+    rather than not.
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/net/sunrpc/auth_gss/gss_generic_token.c b/net/sunrpc/auth_gss/gss_generic_token.c
+index ea8c92ecdae5..d83b881685fe 100644
+--- a/net/sunrpc/auth_gss/gss_generic_token.c
++++ b/net/sunrpc/auth_gss/gss_generic_token.c
+@@ -148,7 +148,7 @@ int
+ g_token_size(struct xdr_netobj *mech, unsigned int body_size)
+ {
+ 	/* set body_size to sequence contents size */
+-	body_size += 4 + (int) mech->len;         /* NEED overflow check */
++	body_size += 2 + (int) mech->len;         /* NEED overflow check */
+ 	return(1 + der_length_size(body_size) + body_size);
+ }
+ 
+@@ -161,7 +161,7 @@ void
+ g_make_token_header(struct xdr_netobj *mech, int body_size, unsigned char **buf)
+ {
+ 	*(*buf)++ = 0x60;
+-	der_write_length(buf, 4 + mech->len + body_size);
++	der_write_length(buf, 2 + mech->len + body_size);
+ 	*(*buf)++ = 0x06;
+ 	*(*buf)++ = (unsigned char) mech->len;
+ 	TWRITE_STR(*buf, mech->data, ((int) mech->len));
+diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
+index 8e3c87df5836..5f1d36dfbcf7 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
+@@ -87,10 +87,10 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
+ 
+ 	now = get_seconds();
+ 
+-	token->len = g_token_size(&ctx->mech_used, 22);
++	token->len = g_token_size(&ctx->mech_used, 24);
+ 
+ 	ptr = token->data;
+-	g_make_token_header(&ctx->mech_used, 22, &ptr);
++	g_make_token_header(&ctx->mech_used, 24, &ptr);
+ 
+ 	*ptr++ = (unsigned char) ((KG_TOK_MIC_MSG>>8)&0xff);
+ 	*ptr++ = (unsigned char) (KG_TOK_MIC_MSG&0xff);
+diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+index 3cd99a795d7a..b00b1b426301 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
++++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+@@ -137,7 +137,7 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
+ 	BUG_ON((buf->len - offset) % blocksize);
+ 	plainlen = blocksize + buf->len - offset;
+ 
+-	headlen = g_token_size(&kctx->mech_used, 22 + plainlen) -
++	headlen = g_token_size(&kctx->mech_used, 24 + plainlen) -
+ 						(buf->len - offset);
+ 
+ 	ptr = buf->head[0].iov_base + offset;
+@@ -149,7 +149,7 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
+ 	buf->len += headlen;
+ 	BUG_ON((buf->len - offset - headlen) % blocksize);
+ 
+-	g_make_token_header(&kctx->mech_used, 22 + plainlen, &ptr);
++	g_make_token_header(&kctx->mech_used, 24 + plainlen, &ptr);
+ 
+ 
+ 	*ptr++ = (unsigned char) ((KG_TOK_WRAP_MSG>>8)&0xff);
+diff --git a/net/sunrpc/auth_gss/gss_spkm3_seal.c b/net/sunrpc/auth_gss/gss_spkm3_seal.c
+index abf17ce2e3b1..c832712f8d55 100644
+--- a/net/sunrpc/auth_gss/gss_spkm3_seal.c
++++ b/net/sunrpc/auth_gss/gss_spkm3_seal.c
+@@ -107,10 +107,10 @@ spkm3_make_token(struct spkm3_ctx *ctx,
+ 		tokenlen = 10 + ctxelen + 1 + md5elen + 1;
+ 
+ 		/* Create token header using generic routines */
+-		token->len = g_token_size(&ctx->mech_used, tokenlen);
++		token->len = g_token_size(&ctx->mech_used, tokenlen + 2);
+ 
+ 		ptr = token->data;
+-		g_make_token_header(&ctx->mech_used, tokenlen, &ptr);
++		g_make_token_header(&ctx->mech_used, tokenlen + 2, &ptr);
+ 
+ 		spkm3_make_mic_token(&ptr, tokenlen, &mic_hdr, &md5cksum, md5elen, md5zbit);
+ 	} else if (toktype == SPKM_WRAP_TOK) { /* Not Supported */

commit 5743d65c2f77d5145fb4c4262c4dd70c3f078776
+Author: Kevin Coffman 
+Date:   Mon Mar 31 10:31:33 2008 -0400
+
+    gss_krb5: consistently use unsigned for seqnum
+    
+    Consistently use unsigned (u32 vs. s32) for seqnum.
+    
+    In get_mic function, send the local copy of seq_send,
+    rather than the context version.
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
+index 216738394f64..a10f1fb0bf7c 100644
+--- a/include/linux/sunrpc/gss_krb5.h
++++ b/include/linux/sunrpc/gss_krb5.h
+@@ -148,9 +148,9 @@ gss_decrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *inbuf,
+ s32
+ krb5_make_seq_num(struct crypto_blkcipher *key,
+ 		int direction,
+-		s32 seqnum, unsigned char *cksum, unsigned char *buf);
++		u32 seqnum, unsigned char *cksum, unsigned char *buf);
+ 
+ s32
+ krb5_get_seq_num(struct crypto_blkcipher *key,
+ 	       unsigned char *cksum,
+-	       unsigned char *buf, int *direction, s32 * seqnum);
++	       unsigned char *buf, int *direction, u32 *seqnum);
+diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
+index 39c08b7e33af..8e3c87df5836 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
+@@ -116,7 +116,7 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
+ 	spin_unlock(&krb5_seq_lock);
+ 
+ 	if (krb5_make_seq_num(ctx->seq, ctx->initiate ? 0 : 0xff,
+-			       ctx->seq_send, krb5_hdr + 16, krb5_hdr + 8))
++			      seq_send, krb5_hdr + 16, krb5_hdr + 8))
+ 		return GSS_S_FAILURE;
+ 
+ 	return (ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE;
+diff --git a/net/sunrpc/auth_gss/gss_krb5_seqnum.c b/net/sunrpc/auth_gss/gss_krb5_seqnum.c
+index 43f3421f1e6a..f160be6c1a46 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_seqnum.c
++++ b/net/sunrpc/auth_gss/gss_krb5_seqnum.c
+@@ -43,7 +43,7 @@
+ s32
+ krb5_make_seq_num(struct crypto_blkcipher *key,
+ 		int direction,
+-		s32 seqnum,
++		u32 seqnum,
+ 		unsigned char *cksum, unsigned char *buf)
+ {
+ 	unsigned char plain[8];
+@@ -65,7 +65,7 @@ s32
+ krb5_get_seq_num(struct crypto_blkcipher *key,
+ 	       unsigned char *cksum,
+ 	       unsigned char *buf,
+-	       int *direction, s32 * seqnum)
++	       int *direction, u32 *seqnum)
+ {
+ 	s32 code;
+ 	unsigned char plain[8];
+diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
+index e30a993466bc..d91a5d004803 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
+@@ -82,7 +82,7 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
+ 	struct xdr_netobj	md5cksum = {.len = 0, .data = cksumdata};
+ 	s32			now;
+ 	int			direction;
+-	s32			seqnum;
++	u32			seqnum;
+ 	unsigned char		*ptr = (unsigned char *)read_token->data;
+ 	int			bodysize;
+ 

commit 03550fac06c4f0c39a1885d46015c28794413c82
+Author: J. Bruce Fields 
+Date:   Fri Mar 14 17:51:12 2008 -0400
+
+    nfsd: move most of fh_verify to separate function
+    
+    Move the code that actually parses the filehandle and looks up the
+    dentry and export to a separate function.  This simplifies the reference
+    counting a little and moves fh_verify() a little closer to the kernel
+    ideal of small, minimally-indentended functions.  Clean up a few other
+    minor style sins along the way.
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: Neil Brown 
+
+diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
+index 3e6b3f41ee1f..100ae5641162 100644
+--- a/fs/nfsd/nfsfh.c
++++ b/fs/nfsd/nfsfh.c
+@@ -112,6 +112,124 @@ static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp,
+ 	return nfserrno(nfsd_setuser(rqstp, exp));
+ }
+ 
++/*
++ * Use the given filehandle to look up the corresponding export and
++ * dentry.  On success, the results are used to set fh_export and
++ * fh_dentry.
++ */
++static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
++{
++	struct knfsd_fh	*fh = &fhp->fh_handle;
++	struct fid *fid = NULL, sfid;
++	struct svc_export *exp;
++	struct dentry *dentry;
++	int fileid_type;
++	int data_left = fh->fh_size/4;
++	__be32 error;
++
++	error = nfserr_stale;
++	if (rqstp->rq_vers > 2)
++		error = nfserr_badhandle;
++	if (rqstp->rq_vers == 4 && fh->fh_size == 0)
++		return nfserr_nofilehandle;
++
++	if (fh->fh_version == 1) {
++		int len;
++
++		if (--data_left < 0)
++			return error;
++		if (fh->fh_auth_type != 0)
++			return error;
++		len = key_len(fh->fh_fsid_type) / 4;
++		if (len == 0)
++			return error;
++		if  (fh->fh_fsid_type == FSID_MAJOR_MINOR) {
++			/* deprecated, convert to type 3 */
++			len = key_len(FSID_ENCODE_DEV)/4;
++			fh->fh_fsid_type = FSID_ENCODE_DEV;
++			fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl(fh->fh_fsid[0]), ntohl(fh->fh_fsid[1])));
++			fh->fh_fsid[1] = fh->fh_fsid[2];
++		}
++		data_left -= len;
++		if (data_left < 0)
++			return error;
++		exp = rqst_exp_find(rqstp, fh->fh_fsid_type, fh->fh_auth);
++		fid = (struct fid *)(fh->fh_auth + len);
++	} else {
++		__u32 tfh[2];
++		dev_t xdev;
++		ino_t xino;
++
++		if (fh->fh_size != NFS_FHSIZE)
++			return error;
++		/* assume old filehandle format */
++		xdev = old_decode_dev(fh->ofh_xdev);
++		xino = u32_to_ino_t(fh->ofh_xino);
++		mk_fsid(FSID_DEV, tfh, xdev, xino, 0, NULL);
++		exp = rqst_exp_find(rqstp, FSID_DEV, tfh);
++	}
++
++	error = nfserr_stale;
++	if (PTR_ERR(exp) == -ENOENT)
++		return error;
++
++	if (IS_ERR(exp))
++		return nfserrno(PTR_ERR(exp));
++
++	error = nfsd_setuser_and_check_port(rqstp, exp);
++	if (error)
++		goto out;
++
++	/*
++	 * Look up the dentry using the NFS file handle.
++	 */
++	error = nfserr_stale;
++	if (rqstp->rq_vers > 2)
++		error = nfserr_badhandle;
++
++	if (fh->fh_version != 1) {
++		sfid.i32.ino = fh->ofh_ino;
++		sfid.i32.gen = fh->ofh_generation;
++		sfid.i32.parent_ino = fh->ofh_dirino;
++		fid = &sfid;
++		data_left = 3;
++		if (fh->ofh_dirino == 0)
++			fileid_type = FILEID_INO32_GEN;
++		else
++			fileid_type = FILEID_INO32_GEN_PARENT;
++	} else
++		fileid_type = fh->fh_fileid_type;
++
++	if (fileid_type == FILEID_ROOT)
++		dentry = dget(exp->ex_path.dentry);
++	else {
++		dentry = exportfs_decode_fh(exp->ex_path.mnt, fid,
++				data_left, fileid_type,
++				nfsd_acceptable, exp);
++	}
++	if (dentry == NULL)
++		goto out;
++	if (IS_ERR(dentry)) {
++		if (PTR_ERR(dentry) != -EINVAL)
++			error = nfserrno(PTR_ERR(dentry));
++		goto out;
++	}
++
++	if (S_ISDIR(dentry->d_inode->i_mode) &&
++			(dentry->d_flags & DCACHE_DISCONNECTED)) {
++		printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n",
++				dentry->d_parent->d_name.name, dentry->d_name.name);
++	}
++
++	fhp->fh_dentry = dentry;
++	fhp->fh_export = exp;
++	nfsd_nr_verified++;
++	return 0;
++out:
++	exp_put(exp);
++	return error;
++}
++
+ /*
+  * Perform sanity checks on the dentry in a client's file handle.
+  *
+@@ -124,115 +242,18 @@ static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp,
+ __be32
+ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
+ {
+-	struct knfsd_fh	*fh = &fhp->fh_handle;
+-	struct svc_export *exp = NULL;
++	struct svc_export *exp;
+ 	struct dentry	*dentry;
+-	__be32		error = 0;
++	__be32		error;
+ 
+ 	dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
+ 
+ 	if (!fhp->fh_dentry) {
+-		struct fid *fid = NULL, sfid;
+-		int fileid_type;
+-		int data_left = fh->fh_size/4;
+-
+-		error = nfserr_stale;
+-		if (rqstp->rq_vers > 2)
+-			error = nfserr_badhandle;
+-		if (rqstp->rq_vers == 4 && fh->fh_size == 0)
+-			return nfserr_nofilehandle;
+-
+-		if (fh->fh_version == 1) {
+-			int len;
+-			if (--data_left<0) goto out;
+-			switch (fh->fh_auth_type) {
+-			case 0: break;
+-			default: goto out;
+-			}
+-			len = key_len(fh->fh_fsid_type) / 4;
+-			if (len == 0) goto out;
+-			if  (fh->fh_fsid_type == FSID_MAJOR_MINOR) {
+-				/* deprecated, convert to type 3 */
+-				len = key_len(FSID_ENCODE_DEV)/4;
+-				fh->fh_fsid_type = FSID_ENCODE_DEV;
+-				fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl(fh->fh_fsid[0]), ntohl(fh->fh_fsid[1])));
+-				fh->fh_fsid[1] = fh->fh_fsid[2];
+-			}
+-			if ((data_left -= len)<0) goto out;
+-			exp = rqst_exp_find(rqstp, fh->fh_fsid_type,
+-					    fh->fh_auth);
+-			fid = (struct fid *)(fh->fh_auth + len);
+-		} else {
+-			__u32 tfh[2];
+-			dev_t xdev;
+-			ino_t xino;
+-			if (fh->fh_size != NFS_FHSIZE)
+-				goto out;
+-			/* assume old filehandle format */
+-			xdev = old_decode_dev(fh->ofh_xdev);
+-			xino = u32_to_ino_t(fh->ofh_xino);
+-			mk_fsid(FSID_DEV, tfh, xdev, xino, 0, NULL);
+-			exp = rqst_exp_find(rqstp, FSID_DEV, tfh);
+-		}
+-
+-		error = nfserr_stale;
+-		if (PTR_ERR(exp) == -ENOENT)
+-			goto out;
+-
+-		if (IS_ERR(exp)) {
+-			error = nfserrno(PTR_ERR(exp));
+-			goto out;
+-		}
+-
+-		error = nfsd_setuser_and_check_port(rqstp, exp);
++		error = nfsd_set_fh_dentry(rqstp, fhp);
+ 		if (error)
+ 			goto out;
+-
+-		/*
+-		 * Look up the dentry using the NFS file handle.
+-		 */
+-		error = nfserr_stale;
+-		if (rqstp->rq_vers > 2)
+-			error = nfserr_badhandle;
+-
+-		if (fh->fh_version != 1) {
+-			sfid.i32.ino = fh->ofh_ino;
+-			sfid.i32.gen = fh->ofh_generation;
+-			sfid.i32.parent_ino = fh->ofh_dirino;
+-			fid = &sfid;
+-			data_left = 3;
+-			if (fh->ofh_dirino == 0)
+-				fileid_type = FILEID_INO32_GEN;
+-			else
+-				fileid_type = FILEID_INO32_GEN_PARENT;
+-		} else
+-			fileid_type = fh->fh_fileid_type;
+-
+-		if (fileid_type == FILEID_ROOT)
+-			dentry = dget(exp->ex_path.dentry);
+-		else {
+-			dentry = exportfs_decode_fh(exp->ex_path.mnt, fid,
+-					data_left, fileid_type,
+-					nfsd_acceptable, exp);
+-		}
+-		if (dentry == NULL)
+-			goto out;
+-		if (IS_ERR(dentry)) {
+-			if (PTR_ERR(dentry) != -EINVAL)
+-				error = nfserrno(PTR_ERR(dentry));
+-			goto out;
+-		}
+-
+-		if (S_ISDIR(dentry->d_inode->i_mode) &&
+-		    (dentry->d_flags & DCACHE_DISCONNECTED)) {
+-			printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n",
+-			       dentry->d_parent->d_name.name, dentry->d_name.name);
+-		}
+-
+-		fhp->fh_dentry = dentry;
+-		fhp->fh_export = exp;
+-		nfsd_nr_verified++;
+-		cache_get(&exp->h);
++		dentry = fhp->fh_dentry;
++		exp = fhp->fh_export;
+ 	} else {
+ 		/*
+ 		 * just rechecking permissions
+@@ -242,7 +263,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
+ 		dprintk("nfsd: fh_verify - just checking\n");
+ 		dentry = fhp->fh_dentry;
+ 		exp = fhp->fh_export;
+-		cache_get(&exp->h);
+ 		/*
+ 		 * Set user creds for this exportpoint; necessary even
+ 		 * in the "just checking" case because this may be a
+@@ -281,8 +301,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
+ 			access, ntohl(error));
+ 	}
+ out:
+-	if (exp && !IS_ERR(exp))
+-		exp_put(exp);
+ 	if (error == nfserr_stale)
+ 		nfsdstats.fh_stale++;
+ 	return error;

commit 30aef3166ab27f7bcb14c5e809205af8126fa10b
+Author: Kevin Coffman 
+Date:   Thu Feb 21 13:44:27 2008 -0500
+
+    Remove define for KRB5_CKSUM_LENGTH, which will become enctype-dependent
+    
+    cleanup: When adding new encryption types, the checksum length
+    can be different for each enctype.  Face the fact that the
+    current code only supports DES which has a checksum length of 8.
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
+index 5a4b1e0206e3..216738394f64 100644
+--- a/include/linux/sunrpc/gss_krb5.h
++++ b/include/linux/sunrpc/gss_krb5.h
+@@ -70,8 +70,6 @@ enum seal_alg {
+ 	SEAL_ALG_DES3KD = 0x0002
+ };
+ 
+-#define KRB5_CKSUM_LENGTH 8
+-
+ #define CKSUMTYPE_CRC32			0x0001
+ #define CKSUMTYPE_RSA_MD4		0x0002
+ #define CKSUMTYPE_RSA_MD4_DES		0x0003
+diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
+index dedcbd6108f4..39c08b7e33af 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
+@@ -109,8 +109,7 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
+ 			  md5cksum.data, md5cksum.len))
+ 		return GSS_S_FAILURE;
+ 
+-	memcpy(krb5_hdr + 16, md5cksum.data + md5cksum.len - KRB5_CKSUM_LENGTH,
+-	       KRB5_CKSUM_LENGTH);
++	memcpy(krb5_hdr + 16, md5cksum.data + md5cksum.len - 8, 8);
+ 
+ 	spin_lock(&krb5_seq_lock);
+ 	seq_send = ctx->seq_send++;
+diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+index 3bdc527ee64a..3cd99a795d7a 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
++++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+@@ -176,9 +176,7 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
+ 	if (krb5_encrypt(kctx->seq, NULL, md5cksum.data,
+ 			  md5cksum.data, md5cksum.len))
+ 		return GSS_S_FAILURE;
+-	memcpy(krb5_hdr + 16,
+-	       md5cksum.data + md5cksum.len - KRB5_CKSUM_LENGTH,
+-	       KRB5_CKSUM_LENGTH);
++	memcpy(krb5_hdr + 16, md5cksum.data + md5cksum.len - 8, 8);
+ 
+ 	spin_lock(&krb5_seq_lock);
+ 	seq_send = kctx->seq_send++;

commit 3d4a6886786f839976c36e62303507692bf87d8d
+Author: Kevin Coffman 
+Date:   Thu Feb 21 13:44:12 2008 -0500
+
+    Correct grammer/typos in dprintks
+    
+    cleanup:  Fix grammer/typos to use "too" instead of "to"
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+index 0dd792338fa9..1d52308ca324 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
++++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+@@ -66,8 +66,8 @@ krb5_encrypt(
+ 		goto out;
+ 
+ 	if (crypto_blkcipher_ivsize(tfm) > 16) {
+-		dprintk("RPC:       gss_k5encrypt: tfm iv size to large %d\n",
+-			 crypto_blkcipher_ivsize(tfm));
++		dprintk("RPC:       gss_k5encrypt: tfm iv size too large %d\n",
++			crypto_blkcipher_ivsize(tfm));
+ 		goto out;
+ 	}
+ 
+@@ -102,7 +102,7 @@ krb5_decrypt(
+ 		goto out;
+ 
+ 	if (crypto_blkcipher_ivsize(tfm) > 16) {
+-		dprintk("RPC:       gss_k5decrypt: tfm iv size to large %d\n",
++		dprintk("RPC:       gss_k5decrypt: tfm iv size too large %d\n",
+ 			crypto_blkcipher_ivsize(tfm));
+ 		goto out;
+ 	}

commit d8421202121ce74daf4625ca9d1d825bbd7ce66a
+Author: J. Bruce Fields 
+Date:   Wed Feb 20 15:40:15 2008 -0500
+
+    lockd: convert nsm_mutex to a spinlock
+    
+    There's no reason for a mutex here, except to allow an allocation under
+    the lock, which we can avoid with the usual trick of preallocating
+    memory for the new object and freeing it if it turns out to be
+    unnecessary.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/lockd/host.c b/fs/lockd/host.c
+index de0ffb6106c4..c7854791898f 100644
+--- a/fs/lockd/host.c
++++ b/fs/lockd/host.c
+@@ -457,7 +457,7 @@ nlm_gc_hosts(void)
+  * Manage NSM handles
+  */
+ static LIST_HEAD(nsm_handles);
+-static DEFINE_MUTEX(nsm_mutex);
++static DEFINE_SPINLOCK(nsm_lock);
+ 
+ static struct nsm_handle *
+ __nsm_find(const struct sockaddr_in *sin,
+@@ -479,7 +479,8 @@ __nsm_find(const struct sockaddr_in *sin,
+ 		return NULL;
+ 	}
+ 
+-	mutex_lock(&nsm_mutex);
++retry:
++	spin_lock(&nsm_lock);
+ 	list_for_each_entry(pos, &nsm_handles, sm_link) {
+ 
+ 		if (hostname && nsm_use_hostnames) {
+@@ -489,28 +490,32 @@ __nsm_find(const struct sockaddr_in *sin,
+ 		} else if (!nlm_cmp_addr(&pos->sm_addr, sin))
+ 			continue;
+ 		atomic_inc(&pos->sm_count);
++		kfree(nsm);
+ 		nsm = pos;
+-		goto out;
++		goto found;
+ 	}
+-
+-	if (!create) {
+-		nsm = NULL;
+-		goto out;
++	if (nsm) {
++		list_add(&nsm->sm_link, &nsm_handles);
++		goto found;
+ 	}
++	spin_unlock(&nsm_lock);
++
++	if (!create)
++		return NULL;
+ 
+ 	nsm = kzalloc(sizeof(*nsm) + hostname_len + 1, GFP_KERNEL);
+ 	if (nsm == NULL)
+-		goto out;
++		return NULL;
++
+ 	nsm->sm_addr = *sin;
+ 	nsm->sm_name = (char *) (nsm + 1);
+ 	memcpy(nsm->sm_name, hostname, hostname_len);
+ 	nsm->sm_name[hostname_len] = '\0';
+ 	atomic_set(&nsm->sm_count, 1);
++	goto retry;
+ 
+-	list_add(&nsm->sm_link, &nsm_handles);
+-
+-out:
+-	mutex_unlock(&nsm_mutex);
++found:
++	spin_unlock(&nsm_lock);
+ 	return nsm;
+ }
+ 
+@@ -529,10 +534,9 @@ nsm_release(struct nsm_handle *nsm)
+ {
+ 	if (!nsm)
+ 		return;
+-	mutex_lock(&nsm_mutex);
+-	if (atomic_dec_and_test(&nsm->sm_count)) {
++	if (atomic_dec_and_lock(&nsm->sm_count, &nsm_lock)) {
+ 		list_del(&nsm->sm_link);
++		spin_unlock(&nsm_lock);
+ 		kfree(nsm);
+ 	}
+-	mutex_unlock(&nsm_mutex);
+ }

commit a95e56e72c196970a8067cd515c658d064813170
+Author: J. Bruce Fields 
+Date:   Wed Feb 20 15:27:31 2008 -0500
+
+    lockd: clean up __nsm_find()
+    
+    Use list_for_each_entry().  Also, in keeping with kernel style, make the
+    normal case (kzalloc succeeds) unindented and handle the abnormal case
+    with a goto.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/lockd/host.c b/fs/lockd/host.c
+index 960911c4a11c..de0ffb6106c4 100644
+--- a/fs/lockd/host.c
++++ b/fs/lockd/host.c
+@@ -465,7 +465,7 @@ __nsm_find(const struct sockaddr_in *sin,
+ 		int create)
+ {
+ 	struct nsm_handle *nsm = NULL;
+-	struct list_head *pos;
++	struct nsm_handle *pos;
+ 
+ 	if (!sin)
+ 		return NULL;
+@@ -480,16 +480,16 @@ __nsm_find(const struct sockaddr_in *sin,
+ 	}
+ 
+ 	mutex_lock(&nsm_mutex);
+-	list_for_each(pos, &nsm_handles) {
+-		nsm = list_entry(pos, struct nsm_handle, sm_link);
++	list_for_each_entry(pos, &nsm_handles, sm_link) {
+ 
+ 		if (hostname && nsm_use_hostnames) {
+-			if (strlen(nsm->sm_name) != hostname_len
+-			 || memcmp(nsm->sm_name, hostname, hostname_len))
++			if (strlen(pos->sm_name) != hostname_len
++			 || memcmp(pos->sm_name, hostname, hostname_len))
+ 				continue;
+-		} else if (!nlm_cmp_addr(&nsm->sm_addr, sin))
++		} else if (!nlm_cmp_addr(&pos->sm_addr, sin))
+ 			continue;
+-		atomic_inc(&nsm->sm_count);
++		atomic_inc(&pos->sm_count);
++		nsm = pos;
+ 		goto out;
+ 	}
+ 
+@@ -499,15 +499,15 @@ __nsm_find(const struct sockaddr_in *sin,
+ 	}
+ 
+ 	nsm = kzalloc(sizeof(*nsm) + hostname_len + 1, GFP_KERNEL);
+-	if (nsm != NULL) {
+-		nsm->sm_addr = *sin;
+-		nsm->sm_name = (char *) (nsm + 1);
+-		memcpy(nsm->sm_name, hostname, hostname_len);
+-		nsm->sm_name[hostname_len] = '\0';
+-		atomic_set(&nsm->sm_count, 1);
+-
+-		list_add(&nsm->sm_link, &nsm_handles);
+-	}
++	if (nsm == NULL)
++		goto out;
++	nsm->sm_addr = *sin;
++	nsm->sm_name = (char *) (nsm + 1);
++	memcpy(nsm->sm_name, hostname, hostname_len);
++	nsm->sm_name[hostname_len] = '\0';
++	atomic_set(&nsm->sm_count, 1);
++
++	list_add(&nsm->sm_link, &nsm_handles);
+ 
+ out:
+ 	mutex_unlock(&nsm_mutex);

commit 164f98adbbd50c67177b096a59f55c1a56a45c82
+Author: J. Bruce Fields 
+Date:   Wed Feb 20 14:02:47 2008 -0500
+
+    lockd: fix race in nlm_release()
+    
+    The sm_count is decremented to zero but left on the nsm_handles list.
+    So in the space between decrementing sm_count and acquiring nsm_mutex,
+    it is possible for another task to find this nsm_handle, increment the
+    use count and then enter nsm_release itself.
+    
+    Thus there's nothing to prevent the nsm being freed before we acquire
+    nsm_mutex here.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/lockd/host.c b/fs/lockd/host.c
+index c3f119426d83..960911c4a11c 100644
+--- a/fs/lockd/host.c
++++ b/fs/lockd/host.c
+@@ -529,12 +529,10 @@ nsm_release(struct nsm_handle *nsm)
+ {
+ 	if (!nsm)
+ 		return;
++	mutex_lock(&nsm_mutex);
+ 	if (atomic_dec_and_test(&nsm->sm_count)) {
+-		mutex_lock(&nsm_mutex);
+-		if (atomic_read(&nsm->sm_count) == 0) {
+-			list_del(&nsm->sm_link);
+-			kfree(nsm);
+-		}
+-		mutex_unlock(&nsm_mutex);
++		list_del(&nsm->sm_link);
++		kfree(nsm);
+ 	}
++	mutex_unlock(&nsm_mutex);
+ }

commit c0ce6ec87c59d7a29438717b1f72f83fb408f416
+Author: J. Bruce Fields 
+Date:   Mon Feb 11 15:48:47 2008 -0500
+
+    nfsd: clarify readdir/mountpoint-crossing code
+    
+    The code here is difficult to understand; attempt to clarify somewhat by
+    pulling out one of the more mystifying conditionals into a separate
+    function.
+    
+    While we're here, also add lease_time to the list of attributes that we
+    don't really need to cross a mountpoint to fetch.
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: Peter Staubach 
+
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index 0e6a179eccaf..1ba7ad981935 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -1867,6 +1867,15 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
+ 	goto out;
+ }
+ 
++static inline int attributes_need_mount(u32 *bmval)
++{
++	if (bmval[0] & ~(FATTR4_WORD0_RDATTR_ERROR | FATTR4_WORD0_LEASE_TIME))
++		return 1;
++	if (bmval[1] & ~FATTR4_WORD1_MOUNTED_ON_FILEID)
++		return 1;
++	return 0;
++}
++
+ static __be32
+ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
+ 		const char *name, int namlen, __be32 *p, int *buflen)
+@@ -1888,9 +1897,7 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
+ 	 * we will not follow the cross mount and will fill the attribtutes
+ 	 * directly from the mountpoint dentry.
+ 	 */
+-	if (d_mountpoint(dentry) &&
+-	    (cd->rd_bmval[0] & ~FATTR4_WORD0_RDATTR_ERROR) == 0 &&
+-	    (cd->rd_bmval[1] & ~FATTR4_WORD1_MOUNTED_ON_FILEID) == 0)
++	if (d_mountpoint(dentry) && !attributes_need_mount(cd->rd_bmval))
+ 		ignore_crossmnt = 1;
+ 	else if (d_mountpoint(dentry)) {
+ 		int err;

commit 67eb6ff610d50da231a37beb634d6dea4b5025ab
+Author: J. Bruce Fields 
+Date:   Thu Jan 31 16:14:54 2008 -0500
+
+    svcrpc: move unused field from cache_deferred_req
+    
+    This field is set once and never used; probably some artifact of an
+    earlier implementation idea.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h
+index 03547d6abee5..2d8b211b9324 100644
+--- a/include/linux/sunrpc/cache.h
++++ b/include/linux/sunrpc/cache.h
+@@ -120,7 +120,6 @@ struct cache_deferred_req {
+ 	struct list_head	hash;	/* on hash chain */
+ 	struct list_head	recent; /* on fifo */
+ 	struct cache_head	*item;  /* cache item we wait on */
+-	time_t			recv_time;
+ 	void			*owner; /* we might need to discard all defered requests
+ 					 * owned by someone */
+ 	void			(*revisit)(struct cache_deferred_req *req,
+diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
+index b5f2786251b9..d75530ff2a6d 100644
+--- a/net/sunrpc/cache.c
++++ b/net/sunrpc/cache.c
+@@ -571,7 +571,6 @@ static int cache_defer_req(struct cache_req *req, struct cache_head *item)
+ 		return -ETIMEDOUT;
+ 
+ 	dreq->item = item;
+-	dreq->recv_time = get_seconds();
+ 
+ 	spin_lock(&cache_defer_lock);
+ 

commit 6a85fa3adddd3a74bd5b94c4b72668d307b88377
+Author: J. Bruce Fields 
+Date:   Sat Jan 26 23:36:48 2008 -0500
+
+    nfsd4: kill unnecessary check in preprocess_stateid_op
+    
+    This condition is always true.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index b83b58da0cc0..a40d1ec52fea 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2052,7 +2052,7 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
+ 		renew_client(stp->st_stateowner->so_client);
+ 		if (filpp)
+ 			*filpp = stp->st_vfs_file;
+-	} else if (dp) {
++	} else {
+ 		if ((status = nfs4_check_delegmode(dp, flags)))
+ 			goto out;
+ 		renew_client(dp->dl_client);

commit 0836f587258c2a24bfdc8810ad2327e7f354b6c7
+Author: J. Bruce Fields 
+Date:   Sat Jan 26 19:08:12 2008 -0500
+
+    nfsd4: simplify stateid sequencing checks
+    
+    Pull this common code into a separate function.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index b73e96db1f50..b83b58da0cc0 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1975,6 +1975,26 @@ io_during_grace_disallowed(struct inode *inode, int flags)
+ 		&& mandatory_lock(inode);
+ }
+ 
++static int check_stateid_generation(stateid_t *in, stateid_t *ref)
++{
++	/* If the client sends us a stateid from the future, it's buggy: */
++	if (in->si_generation > ref->si_generation)
++		return nfserr_bad_stateid;
++	/*
++	 * The following, however, can happen.  For example, if the
++	 * client sends an open and some IO at the same time, the open
++	 * may bump si_generation while the IO is still in flight.
++	 * Thanks to hard links and renames, the client never knows what
++	 * file an open will affect.  So it could avoid that situation
++	 * only by serializing all opens and IO from the same open
++	 * owner.  To recover from the old_stateid error, the client
++	 * will just have to retry the IO:
++	 */
++	if (in->si_generation < ref->si_generation)
++		return nfserr_old_stateid;
++	return nfs_ok;
++}
++
+ /*
+ * Checks for stateid operations
+ */
+@@ -2023,12 +2043,8 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
+ 			goto out;
+ 		stidp = &stp->st_stateid;
+ 	}
+-	if (stateid->si_generation > stidp->si_generation)
+-		goto out;
+-
+-	/* OLD STATEID */
+-	status = nfserr_old_stateid;
+-	if (stateid->si_generation < stidp->si_generation)
++	status = check_stateid_generation(stateid, stidp);
++	if (status)
+ 		goto out;
+ 	if (stp) {
+ 		if ((status = nfs4_check_openmode(stp,flags)))
+@@ -2065,6 +2081,7 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
+ {
+ 	struct nfs4_stateid *stp;
+ 	struct nfs4_stateowner *sop;
++	__be32 status;
+ 
+ 	dprintk("NFSD: preprocess_seqid_op: seqid=%d " 
+ 			"stateid = (%08x/%08x/%08x/%08x)\n", seqid,
+@@ -2150,15 +2167,9 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
+ 				" confirmed yet!\n");
+ 		return nfserr_bad_stateid;
+ 	}
+-	if (stateid->si_generation > stp->st_stateid.si_generation) {
+-		dprintk("NFSD: preprocess_seqid_op: future stateid?!\n");
+-		return nfserr_bad_stateid;
+-	}
+-
+-	if (stateid->si_generation < stp->st_stateid.si_generation) {
+-		dprintk("NFSD: preprocess_seqid_op: old stateid!\n");
+-		return nfserr_old_stateid;
+-	}
++	status = check_stateid_generation(stateid, &stp->st_stateid);
++	if (status)
++		return status;
+ 	renew_client(sop->so_client);
+ 	return nfs_ok;
+ 

commit f3362737be14668f4e8f5c8d082eb131aafc1353
+Author: J. Bruce Fields 
+Date:   Sat Jan 26 14:58:45 2008 -0500
+
+    nfsd4: remove unnecessary CHECK_FH check in preprocess_seqid_op
+    
+    Every caller sets this flag, so it's meaningless.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 81a75f3081f4..b73e96db1f50 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2127,7 +2127,7 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
+                }
+ 	}
+ 
+-	if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) {
++	if (nfs4_check_fh(current_fh, stp)) {
+ 		dprintk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n");
+ 		return nfserr_bad_stateid;
+ 	}
+@@ -2194,7 +2194,7 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 
+ 	if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+ 					oc->oc_seqid, &oc->oc_req_stateid,
+-					CHECK_FH | CONFIRM | OPEN_STATE,
++					CONFIRM | OPEN_STATE,
+ 					&oc->oc_stateowner, &stp, NULL)))
+ 		goto out; 
+ 
+@@ -2265,7 +2265,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
+ 	if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+ 					od->od_seqid,
+ 					&od->od_stateid, 
+-					CHECK_FH | OPEN_STATE, 
++					OPEN_STATE,
+ 					&od->od_stateowner, &stp, NULL)))
+ 		goto out; 
+ 
+@@ -2318,7 +2318,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+ 					close->cl_seqid,
+ 					&close->cl_stateid, 
+-					CHECK_FH | OPEN_STATE | CLOSE_STATE,
++					OPEN_STATE | CLOSE_STATE,
+ 					&close->cl_stateowner, &stp, NULL)))
+ 		goto out; 
+ 	status = nfs_ok;
+@@ -2623,7 +2623,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 		status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+ 				        lock->lk_new_open_seqid,
+ 		                        &lock->lk_new_open_stateid,
+-		                        CHECK_FH | OPEN_STATE,
++					OPEN_STATE,
+ 		                        &lock->lk_replay_owner, &open_stp,
+ 					lock);
+ 		if (status)
+@@ -2650,7 +2650,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 		status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+ 				       lock->lk_old_lock_seqid, 
+ 				       &lock->lk_old_lock_stateid, 
+-				       CHECK_FH | LOCK_STATE, 
++				       LOCK_STATE,
+ 				       &lock->lk_replay_owner, &lock_stp, lock);
+ 		if (status)
+ 			goto out;
+@@ -2847,7 +2847,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+ 					locku->lu_seqid, 
+ 					&locku->lu_stateid, 
+-					CHECK_FH | LOCK_STATE, 
++					LOCK_STATE,
+ 					&locku->lu_stateowner, &stp, NULL)))
+ 		goto out;
+ 

commit 065f30ec14b1460c695b371bc44e068832a60d9b
+Author: J. Bruce Fields 
+Date:   Sat Jan 19 13:58:23 2008 -0500
+
+    nfs: remove unnecessary NFS_NEED_* defines
+    
+    Thanks to Robert Day for pointing out that these two defines are unused.
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: Trond Myklebust Trond Myklebust 
+    Cc: Neil Brown 
+    Cc: "Robert P. J. Day" 
+
+diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c
+index 83e865a16ad1..412738dbfbc7 100644
+--- a/fs/nfs/symlink.c
++++ b/fs/nfs/symlink.c
+@@ -10,7 +10,6 @@
+  *  nfs symlink handling code
+  */
+ 
+-#define NFS_NEED_XDR_TYPES
+ #include 
+ #include 
+ #include 
+diff --git a/include/linux/nfs3.h b/include/linux/nfs3.h
+index 7f11fa589207..539f3b550eab 100644
+--- a/include/linux/nfs3.h
++++ b/include/linux/nfs3.h
+@@ -96,7 +96,7 @@ struct nfs3_fh {
+ #define MOUNTPROC3_UMNTALL	4
+  
+ 
+-#if defined(__KERNEL__) || defined(NFS_NEED_KERNEL_TYPES)
++#if defined(__KERNEL__)
+ 
+ /* Number of 32bit words in post_op_attr */
+ #define NFS3_POST_OP_ATTR_WORDS		22

commit 76cb9521795a167ae3d206343c072f602d84f815
+Author: Kevin Coffman 
+Date:   Mon Mar 24 21:26:16 2008 +0800
+
+    [CRYPTO] cts: Add CTS mode required for Kerberos AES support
+    
+    Implement CTS wrapper for CBC mode required for support of AES
+    encryption support for Kerberos (rfc3962).
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: Herbert Xu 
+
+diff --git a/crypto/Kconfig b/crypto/Kconfig
+index 69f1be6816f7..e14ff1275018 100644
+--- a/crypto/Kconfig
++++ b/crypto/Kconfig
+@@ -213,6 +213,17 @@ config CRYPTO_CTR
+ 	  CTR: Counter mode
+ 	  This block cipher algorithm is required for IPSec.
+ 
++config CRYPTO_CTS
++	tristate "CTS support"
++	select CRYPTO_BLKCIPHER
++	help
++	  CTS: Cipher Text Stealing
++	  This is the Cipher Text Stealing mode as described by
++	  Section 8 of rfc2040 and referenced by rfc3962.
++	  (rfc3962 includes errata information in its Appendix A)
++	  This mode is required for Kerberos gss mechanism support
++	  for AES encryption.
++
+ config CRYPTO_GCM
+ 	tristate "GCM/GMAC support"
+ 	select CRYPTO_CTR
+diff --git a/crypto/Makefile b/crypto/Makefile
+index cf702a270c59..6d34bf7ecf8d 100644
+--- a/crypto/Makefile
++++ b/crypto/Makefile
+@@ -35,6 +35,7 @@ obj-$(CONFIG_CRYPTO_GF128MUL) += gf128mul.o
+ obj-$(CONFIG_CRYPTO_ECB) += ecb.o
+ obj-$(CONFIG_CRYPTO_CBC) += cbc.o
+ obj-$(CONFIG_CRYPTO_PCBC) += pcbc.o
++obj-$(CONFIG_CRYPTO_CTS) += cts.o
+ obj-$(CONFIG_CRYPTO_LRW) += lrw.o
+ obj-$(CONFIG_CRYPTO_XTS) += xts.o
+ obj-$(CONFIG_CRYPTO_CTR) += ctr.o
+diff --git a/crypto/cts.c b/crypto/cts.c
+new file mode 100644
+index 000000000000..c4e70bfb4970
+--- /dev/null
++++ b/crypto/cts.c
+@@ -0,0 +1,347 @@
++/*
++ * CTS: Cipher Text Stealing mode
++ *
++ * COPYRIGHT (c) 2008
++ * The Regents of the University of Michigan
++ * ALL RIGHTS RESERVED
++ *
++ * Permission is granted to use, copy, create derivative works
++ * and redistribute this software and such derivative works
++ * for any purpose, so long as the name of The University of
++ * Michigan is not used in any advertising or publicity
++ * pertaining to the use of distribution of this software
++ * without specific, written prior authorization.  If the
++ * above copyright notice or any other identification of the
++ * University of Michigan is included in any copy of any
++ * portion of this software, then the disclaimer below must
++ * also be included.
++ *
++ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
++ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
++ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
++ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
++ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
++ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
++ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
++ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
++ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
++ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGES.
++ */
++
++/* Derived from various:
++ *	Copyright (c) 2006 Herbert Xu 
++ */
++
++/*
++ * This is the Cipher Text Stealing mode as described by
++ * Section 8 of rfc2040 and referenced by rfc3962.
++ * rfc3962 includes errata information in its Appendix A.
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++struct crypto_cts_ctx {
++	struct crypto_blkcipher *child;
++};
++
++static int crypto_cts_setkey(struct crypto_tfm *parent, const u8 *key,
++			     unsigned int keylen)
++{
++	struct crypto_cts_ctx *ctx = crypto_tfm_ctx(parent);
++	struct crypto_blkcipher *child = ctx->child;
++	int err;
++
++	crypto_blkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
++	crypto_blkcipher_set_flags(child, crypto_tfm_get_flags(parent) &
++				       CRYPTO_TFM_REQ_MASK);
++	err = crypto_blkcipher_setkey(child, key, keylen);
++	crypto_tfm_set_flags(parent, crypto_blkcipher_get_flags(child) &
++				     CRYPTO_TFM_RES_MASK);
++	return err;
++}
++
++static int cts_cbc_encrypt(struct crypto_cts_ctx *ctx,
++			   struct blkcipher_desc *desc,
++			   struct scatterlist *dst,
++			   struct scatterlist *src,
++			   unsigned int offset,
++			   unsigned int nbytes)
++{
++	int bsize = crypto_blkcipher_blocksize(desc->tfm);
++	u8 tmp[bsize], tmp2[bsize];
++	struct blkcipher_desc lcldesc;
++	struct scatterlist sgsrc[1], sgdst[1];
++	int lastn = nbytes - bsize;
++	u8 iv[bsize];
++	u8 s[bsize * 2], d[bsize * 2];
++	int err;
++
++	if (lastn < 0)
++		return -EINVAL;
++
++	memset(s, 0, sizeof(s));
++	scatterwalk_map_and_copy(s, src, offset, nbytes, 0);
++
++	memcpy(iv, desc->info, bsize);
++
++	lcldesc.tfm = ctx->child;
++	lcldesc.info = iv;
++	lcldesc.flags = desc->flags;
++
++	sg_set_buf(&sgsrc[0], s, bsize);
++	sg_set_buf(&sgdst[0], tmp, bsize);
++	err = crypto_blkcipher_encrypt_iv(&lcldesc, sgdst, sgsrc, bsize);
++
++	memcpy(d + bsize, tmp, lastn);
++
++	lcldesc.info = tmp;
++
++	sg_set_buf(&sgsrc[0], s + bsize, bsize);
++	sg_set_buf(&sgdst[0], tmp2, bsize);
++	err = crypto_blkcipher_encrypt_iv(&lcldesc, sgdst, sgsrc, bsize);
++
++	memcpy(d, tmp2, bsize);
++
++	scatterwalk_map_and_copy(d, dst, offset, nbytes, 1);
++
++	memcpy(desc->info, tmp2, bsize);
++
++	return err;
++}
++
++static int crypto_cts_encrypt(struct blkcipher_desc *desc,
++			      struct scatterlist *dst, struct scatterlist *src,
++			      unsigned int nbytes)
++{
++	struct crypto_cts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
++	int bsize = crypto_blkcipher_blocksize(desc->tfm);
++	int tot_blocks = (nbytes + bsize - 1) / bsize;
++	int cbc_blocks = tot_blocks > 2 ? tot_blocks - 2 : 0;
++	struct blkcipher_desc lcldesc;
++	int err;
++
++	lcldesc.tfm = ctx->child;
++	lcldesc.info = desc->info;
++	lcldesc.flags = desc->flags;
++
++	if (tot_blocks == 1) {
++		err = crypto_blkcipher_encrypt_iv(&lcldesc, dst, src, bsize);
++	} else if (nbytes <= bsize * 2) {
++		err = cts_cbc_encrypt(ctx, desc, dst, src, 0, nbytes);
++	} else {
++		/* do normal function for tot_blocks - 2 */
++		err = crypto_blkcipher_encrypt_iv(&lcldesc, dst, src,
++							cbc_blocks * bsize);
++		if (err == 0) {
++			/* do cts for final two blocks */
++			err = cts_cbc_encrypt(ctx, desc, dst, src,
++						cbc_blocks * bsize,
++						nbytes - (cbc_blocks * bsize));
++		}
++	}
++
++	return err;
++}
++
++static int cts_cbc_decrypt(struct crypto_cts_ctx *ctx,
++			   struct blkcipher_desc *desc,
++			   struct scatterlist *dst,
++			   struct scatterlist *src,
++			   unsigned int offset,
++			   unsigned int nbytes)
++{
++	int bsize = crypto_blkcipher_blocksize(desc->tfm);
++	u8 tmp[bsize];
++	struct blkcipher_desc lcldesc;
++	struct scatterlist sgsrc[1], sgdst[1];
++	int lastn = nbytes - bsize;
++	u8 iv[bsize];
++	u8 s[bsize * 2], d[bsize * 2];
++	int err;
++
++	if (lastn < 0)
++		return -EINVAL;
++
++	scatterwalk_map_and_copy(s, src, offset, nbytes, 0);
++
++	lcldesc.tfm = ctx->child;
++	lcldesc.info = iv;
++	lcldesc.flags = desc->flags;
++
++	/* 1. Decrypt Cn-1 (s) to create Dn (tmp)*/
++	memset(iv, 0, sizeof(iv));
++	sg_set_buf(&sgsrc[0], s, bsize);
++	sg_set_buf(&sgdst[0], tmp, bsize);
++	err = crypto_blkcipher_decrypt_iv(&lcldesc, sgdst, sgsrc, bsize);
++	if (err)
++		return err;
++	/* 2. Pad Cn with zeros at the end to create C of length BB */
++	memset(iv, 0, sizeof(iv));
++	memcpy(iv, s + bsize, lastn);
++	/* 3. Exclusive-or Dn (tmp) with C (iv) to create Xn (tmp) */
++	crypto_xor(tmp, iv, bsize);
++	/* 4. Select the first Ln bytes of Xn (tmp) to create Pn */
++	memcpy(d + bsize, tmp, lastn);
++
++	/* 5. Append the tail (BB - Ln) bytes of Xn (tmp) to Cn to create En */
++	memcpy(s + bsize + lastn, tmp + lastn, bsize - lastn);
++	/* 6. Decrypt En to create Pn-1 */
++	memset(iv, 0, sizeof(iv));
++	sg_set_buf(&sgsrc[0], s + bsize, bsize);
++	sg_set_buf(&sgdst[0], d, bsize);
++	err = crypto_blkcipher_decrypt_iv(&lcldesc, sgdst, sgsrc, bsize);
++
++	/* XOR with previous block */
++	crypto_xor(d, desc->info, bsize);
++
++	scatterwalk_map_and_copy(d, dst, offset, nbytes, 1);
++
++	memcpy(desc->info, s, bsize);
++	return err;
++}
++
++static int crypto_cts_decrypt(struct blkcipher_desc *desc,
++			      struct scatterlist *dst, struct scatterlist *src,
++			      unsigned int nbytes)
++{
++	struct crypto_cts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
++	int bsize = crypto_blkcipher_blocksize(desc->tfm);
++	int tot_blocks = (nbytes + bsize - 1) / bsize;
++	int cbc_blocks = tot_blocks > 2 ? tot_blocks - 2 : 0;
++	struct blkcipher_desc lcldesc;
++	int err;
++
++	lcldesc.tfm = ctx->child;
++	lcldesc.info = desc->info;
++	lcldesc.flags = desc->flags;
++
++	if (tot_blocks == 1) {
++		err = crypto_blkcipher_decrypt_iv(&lcldesc, dst, src, bsize);
++	} else if (nbytes <= bsize * 2) {
++		err = cts_cbc_decrypt(ctx, desc, dst, src, 0, nbytes);
++	} else {
++		/* do normal function for tot_blocks - 2 */
++		err = crypto_blkcipher_decrypt_iv(&lcldesc, dst, src,
++							cbc_blocks * bsize);
++		if (err == 0) {
++			/* do cts for final two blocks */
++			err = cts_cbc_decrypt(ctx, desc, dst, src,
++						cbc_blocks * bsize,
++						nbytes - (cbc_blocks * bsize));
++		}
++	}
++	return err;
++}
++
++static int crypto_cts_init_tfm(struct crypto_tfm *tfm)
++{
++	struct crypto_instance *inst = (void *)tfm->__crt_alg;
++	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
++	struct crypto_cts_ctx *ctx = crypto_tfm_ctx(tfm);
++	struct crypto_blkcipher *cipher;
++
++	cipher = crypto_spawn_blkcipher(spawn);
++	if (IS_ERR(cipher))
++		return PTR_ERR(cipher);
++
++	ctx->child = cipher;
++	return 0;
++}
++
++static void crypto_cts_exit_tfm(struct crypto_tfm *tfm)
++{
++	struct crypto_cts_ctx *ctx = crypto_tfm_ctx(tfm);
++	crypto_free_blkcipher(ctx->child);
++}
++
++static struct crypto_instance *crypto_cts_alloc(struct rtattr **tb)
++{
++	struct crypto_instance *inst;
++	struct crypto_alg *alg;
++	int err;
++
++	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
++	if (err)
++		return ERR_PTR(err);
++
++	alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_BLKCIPHER,
++				  CRYPTO_ALG_TYPE_MASK);
++	err = PTR_ERR(alg);
++	if (IS_ERR(alg))
++		return ERR_PTR(err);
++
++	inst = ERR_PTR(-EINVAL);
++	if (!is_power_of_2(alg->cra_blocksize))
++		goto out_put_alg;
++
++	inst = crypto_alloc_instance("cts", alg);
++	if (IS_ERR(inst))
++		goto out_put_alg;
++
++	inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
++	inst->alg.cra_priority = alg->cra_priority;
++	inst->alg.cra_blocksize = alg->cra_blocksize;
++	inst->alg.cra_alignmask = alg->cra_alignmask;
++	inst->alg.cra_type = &crypto_blkcipher_type;
++
++	/* We access the data as u32s when xoring. */
++	inst->alg.cra_alignmask |= __alignof__(u32) - 1;
++
++	inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
++	inst->alg.cra_blkcipher.min_keysize = alg->cra_blkcipher.min_keysize;
++	inst->alg.cra_blkcipher.max_keysize = alg->cra_blkcipher.max_keysize;
++
++	inst->alg.cra_blkcipher.geniv = "seqiv";
++
++	inst->alg.cra_ctxsize = sizeof(struct crypto_cts_ctx);
++
++	inst->alg.cra_init = crypto_cts_init_tfm;
++	inst->alg.cra_exit = crypto_cts_exit_tfm;
++
++	inst->alg.cra_blkcipher.setkey = crypto_cts_setkey;
++	inst->alg.cra_blkcipher.encrypt = crypto_cts_encrypt;
++	inst->alg.cra_blkcipher.decrypt = crypto_cts_decrypt;
++
++out_put_alg:
++	crypto_mod_put(alg);
++	return inst;
++}
++
++static void crypto_cts_free(struct crypto_instance *inst)
++{
++	crypto_drop_spawn(crypto_instance_ctx(inst));
++	kfree(inst);
++}
++
++static struct crypto_template crypto_cts_tmpl = {
++	.name = "cts",
++	.alloc = crypto_cts_alloc,
++	.free = crypto_cts_free,
++	.module = THIS_MODULE,
++};
++
++static int __init crypto_cts_module_init(void)
++{
++	return crypto_register_template(&crypto_cts_tmpl);
++}
++
++static void __exit crypto_cts_module_exit(void)
++{
++	crypto_unregister_template(&crypto_cts_tmpl);
++}
++
++module_init(crypto_cts_module_init);
++module_exit(crypto_cts_module_exit);
++
++MODULE_LICENSE("Dual BSD/GPL");
++MODULE_DESCRIPTION("CTS-CBC CipherText Stealing for CBC");
+diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
+index 30e75d49f35a..689482cd16c2 100644
+--- a/crypto/tcrypt.c
++++ b/crypto/tcrypt.c
+@@ -82,9 +82,8 @@ static char *check[] = {
+ 	"des", "md5", "des3_ede", "rot13", "sha1", "sha224", "sha256",
+ 	"blowfish", "twofish", "serpent", "sha384", "sha512", "md4", "aes",
+ 	"cast6", "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
+-	"arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
+ 	"khazad", "wp512", "wp384", "wp256", "tnepres", "xeta",  "fcrypt",
+-	"camellia", "seed", "salsa20", "lzo", NULL
++	"camellia", "seed", "salsa20", "lzo", "cts", NULL
+ };
+ 
+ static void hexdump(unsigned char *buf, unsigned int len)
+@@ -1328,6 +1327,12 @@ static void do_test(void)
+ 		test_cipher("ecb(seed)", DECRYPT, seed_dec_tv_template,
+ 			    SEED_DEC_TEST_VECTORS);
+ 
++		//CTS
++		test_cipher("cts(cbc(aes))", ENCRYPT, cts_mode_enc_tv_template,
++			    CTS_MODE_ENC_TEST_VECTORS);
++		test_cipher("cts(cbc(aes))", DECRYPT, cts_mode_dec_tv_template,
++			    CTS_MODE_DEC_TEST_VECTORS);
++
+ 		test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
+ 		test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
+ 		test_hash("wp512", wp512_tv_template, WP512_TEST_VECTORS);
+@@ -1611,6 +1616,13 @@ static void do_test(void)
+ 			  AES_CCM_DEC_TEST_VECTORS);
+ 		break;
+ 
++	case 38:
++		test_cipher("cts(cbc(aes))", ENCRYPT, cts_mode_enc_tv_template,
++			    CTS_MODE_ENC_TEST_VECTORS);
++		test_cipher("cts(cbc(aes))", DECRYPT, cts_mode_dec_tv_template,
++			    CTS_MODE_DEC_TEST_VECTORS);
++		break;
++
+ 	case 100:
+ 		test_hash("hmac(md5)", hmac_md5_tv_template,
+ 			  HMAC_MD5_TEST_VECTORS);
+diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h
+index aae79e9c256c..47bc0ecb8978 100644
+--- a/crypto/tcrypt.h
++++ b/crypto/tcrypt.h
+@@ -7622,6 +7622,215 @@ static struct cipher_testvec salsa20_stream_enc_tv_template[] = {
+ 	},
+ };
+ 
++/*
++ * CTS (Cipher Text Stealing) mode tests
++ */
++#define CTS_MODE_ENC_TEST_VECTORS 6
++#define CTS_MODE_DEC_TEST_VECTORS 6
++static struct cipher_testvec cts_mode_enc_tv_template[] = {
++	{ /* from rfc3962 */
++		.klen	= 16,
++		.key    = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++			  "\x74\x65\x72\x69\x79\x61\x6b\x69",
++		.ilen	= 17,
++		.input  = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++			  "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++			  "\x20",
++		.rlen	= 17,
++		.result	= "\xc6\x35\x35\x68\xf2\xbf\x8c\xb4"
++			  "\xd8\xa5\x80\x36\x2d\xa7\xff\x7f"
++			  "\x97",
++	}, {
++		.klen	= 16,
++		.key    = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++			  "\x74\x65\x72\x69\x79\x61\x6b\x69",
++		.ilen   = 31,
++		.input  = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++			  "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++			  "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++			  "\x20\x47\x61\x75\x27\x73\x20",
++		.rlen   = 31,
++		.result = "\xfc\x00\x78\x3e\x0e\xfd\xb2\xc1"
++			  "\xd4\x45\xd4\xc8\xef\xf7\xed\x22"
++			  "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++			  "\xc0\x7b\x25\xe2\x5e\xcf\xe5",
++	}, {
++		.klen	= 16,
++		.key    = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++			  "\x74\x65\x72\x69\x79\x61\x6b\x69",
++		.ilen   = 32,
++		.input  = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++			  "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++			  "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++			  "\x20\x47\x61\x75\x27\x73\x20\x43",
++		.rlen   = 32,
++		.result = "\x39\x31\x25\x23\xa7\x86\x62\xd5"
++			  "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8"
++			  "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++			  "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84",
++	}, {
++		.klen	= 16,
++		.key    = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++			  "\x74\x65\x72\x69\x79\x61\x6b\x69",
++		.ilen   = 47,
++		.input  = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++			  "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++			  "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++			  "\x20\x47\x61\x75\x27\x73\x20\x43"
++			  "\x68\x69\x63\x6b\x65\x6e\x2c\x20"
++			  "\x70\x6c\x65\x61\x73\x65\x2c",
++		.rlen   = 47,
++		.result = "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++			  "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
++			  "\xb3\xff\xfd\x94\x0c\x16\xa1\x8c"
++			  "\x1b\x55\x49\xd2\xf8\x38\x02\x9e"
++			  "\x39\x31\x25\x23\xa7\x86\x62\xd5"
++			  "\xbe\x7f\xcb\xcc\x98\xeb\xf5",
++	}, {
++		.klen	= 16,
++		.key    = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++			  "\x74\x65\x72\x69\x79\x61\x6b\x69",
++		.ilen   = 48,
++		.input  = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++			  "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++			  "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++			  "\x20\x47\x61\x75\x27\x73\x20\x43"
++			  "\x68\x69\x63\x6b\x65\x6e\x2c\x20"
++			  "\x70\x6c\x65\x61\x73\x65\x2c\x20",
++		.rlen   = 48,
++		.result = "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++			  "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
++			  "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0"
++			  "\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8"
++			  "\x39\x31\x25\x23\xa7\x86\x62\xd5"
++			  "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8",
++	}, {
++		.klen	= 16,
++		.key    = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++			  "\x74\x65\x72\x69\x79\x61\x6b\x69",
++		.ilen   = 64,
++		.input  = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++			  "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++			  "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++			  "\x20\x47\x61\x75\x27\x73\x20\x43"
++			  "\x68\x69\x63\x6b\x65\x6e\x2c\x20"
++			  "\x70\x6c\x65\x61\x73\x65\x2c\x20"
++			  "\x61\x6e\x64\x20\x77\x6f\x6e\x74"
++			  "\x6f\x6e\x20\x73\x6f\x75\x70\x2e",
++		.rlen   = 64,
++		.result = "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++			  "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
++			  "\x39\x31\x25\x23\xa7\x86\x62\xd5"
++			  "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8"
++			  "\x48\x07\xef\xe8\x36\xee\x89\xa5"
++			  "\x26\x73\x0d\xbc\x2f\x7b\xc8\x40"
++			  "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0"
++			  "\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8",
++	}
++};
++
++static struct cipher_testvec cts_mode_dec_tv_template[] = {
++	{ /* from rfc3962 */
++		.klen	= 16,
++		.key    = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++			  "\x74\x65\x72\x69\x79\x61\x6b\x69",
++		.rlen	= 17,
++		.result = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++			  "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++			  "\x20",
++		.ilen	= 17,
++		.input	= "\xc6\x35\x35\x68\xf2\xbf\x8c\xb4"
++			  "\xd8\xa5\x80\x36\x2d\xa7\xff\x7f"
++			  "\x97",
++	}, {
++		.klen	= 16,
++		.key    = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++			  "\x74\x65\x72\x69\x79\x61\x6b\x69",
++		.rlen   = 31,
++		.result = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++			  "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++			  "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++			  "\x20\x47\x61\x75\x27\x73\x20",
++		.ilen   = 31,
++		.input  = "\xfc\x00\x78\x3e\x0e\xfd\xb2\xc1"
++			  "\xd4\x45\xd4\xc8\xef\xf7\xed\x22"
++			  "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++			  "\xc0\x7b\x25\xe2\x5e\xcf\xe5",
++	}, {
++		.klen	= 16,
++		.key    = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++			  "\x74\x65\x72\x69\x79\x61\x6b\x69",
++		.rlen   = 32,
++		.result = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++			  "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++			  "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++			  "\x20\x47\x61\x75\x27\x73\x20\x43",
++		.ilen   = 32,
++		.input  = "\x39\x31\x25\x23\xa7\x86\x62\xd5"
++			  "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8"
++			  "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++			  "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84",
++	}, {
++		.klen	= 16,
++		.key    = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++			  "\x74\x65\x72\x69\x79\x61\x6b\x69",
++		.rlen   = 47,
++		.result = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++			  "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++			  "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++			  "\x20\x47\x61\x75\x27\x73\x20\x43"
++			  "\x68\x69\x63\x6b\x65\x6e\x2c\x20"
++			  "\x70\x6c\x65\x61\x73\x65\x2c",
++		.ilen   = 47,
++		.input  = "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++			  "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
++			  "\xb3\xff\xfd\x94\x0c\x16\xa1\x8c"
++			  "\x1b\x55\x49\xd2\xf8\x38\x02\x9e"
++			  "\x39\x31\x25\x23\xa7\x86\x62\xd5"
++			  "\xbe\x7f\xcb\xcc\x98\xeb\xf5",
++	}, {
++		.klen	= 16,
++		.key    = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++			  "\x74\x65\x72\x69\x79\x61\x6b\x69",
++		.rlen   = 48,
++		.result = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++			  "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++			  "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++			  "\x20\x47\x61\x75\x27\x73\x20\x43"
++			  "\x68\x69\x63\x6b\x65\x6e\x2c\x20"
++			  "\x70\x6c\x65\x61\x73\x65\x2c\x20",
++		.ilen   = 48,
++		.input  = "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++			  "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
++			  "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0"
++			  "\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8"
++			  "\x39\x31\x25\x23\xa7\x86\x62\xd5"
++			  "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8",
++	}, {
++		.klen	= 16,
++		.key    = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++			  "\x74\x65\x72\x69\x79\x61\x6b\x69",
++		.rlen   = 64,
++		.result = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++			  "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++			  "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++			  "\x20\x47\x61\x75\x27\x73\x20\x43"
++			  "\x68\x69\x63\x6b\x65\x6e\x2c\x20"
++			  "\x70\x6c\x65\x61\x73\x65\x2c\x20"
++			  "\x61\x6e\x64\x20\x77\x6f\x6e\x74"
++			  "\x6f\x6e\x20\x73\x6f\x75\x70\x2e",
++		.ilen   = 64,
++		.input  = "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++			  "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
++			  "\x39\x31\x25\x23\xa7\x86\x62\xd5"
++			  "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8"
++			  "\x48\x07\xef\xe8\x36\xee\x89\xa5"
++			  "\x26\x73\x0d\xbc\x2f\x7b\xc8\x40"
++			  "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0"
++			  "\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8",
++	}
++};
++
+ /*
+  * Compression stuff.
+  */

commit 441092415770ddec648800701895913c4bfd60c1
+Author: Fred Isaman 
+Date:   Wed Apr 2 15:21:15 2008 +0300
+
+    nfs: fix printout of multiword bitfields
+    
+    Benny points out that zero-padding of multiword bitfields is necessary,
+    and that delimiting each word is nice to avoid endianess confusion.
+    
+    bhalevy: without zero padding output can be ambiguous. Also,
+    since the printed array of two 32-bit unsigned integers is not a
+    64-bit number, delimiting the output with a semicolon makes more sense.
+    
+    Signed-off-by: Fred Isaman 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
+index 809ef0d787e3..5a2d64927b35 100644
+--- a/fs/nfs/nfs4xdr.c
++++ b/fs/nfs/nfs4xdr.c
+@@ -1191,8 +1191,8 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
+ 		attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
+ 	WRITE32(attrs[0] & readdir->bitmask[0]);
+ 	WRITE32(attrs[1] & readdir->bitmask[1]);
+-	dprintk("%s: cookie = %Lu, verifier = 0x%x%x, bitmap = 0x%x%x\n",
+-			__FUNCTION__,
++	dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n",
++			__func__,
+ 			(unsigned long long)readdir->cookie,
+ 			((u32 *)readdir->verifier.data)[0],
+ 			((u32 *)readdir->verifier.data)[1],
+@@ -2291,7 +2291,7 @@ static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint3
+ 		bitmap[0] &= ~FATTR4_WORD0_SUPPORTED_ATTRS;
+ 	} else
+ 		bitmask[0] = bitmask[1] = 0;
+-	dprintk("%s: bitmask=0x%x%x\n", __FUNCTION__, bitmask[0], bitmask[1]);
++	dprintk("%s: bitmask=%08x:%08x\n", __func__, bitmask[0], bitmask[1]);
+ 	return 0;
+ }
+ 
+@@ -3505,8 +3505,8 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
+ 		return status;
+ 	READ_BUF(8);
+ 	COPYMEM(readdir->verifier.data, 8);
+-	dprintk("%s: verifier = 0x%x%x\n",
+-			__FUNCTION__,
++	dprintk("%s: verifier = %08x:%08x\n",
++			__func__,
+ 			((u32 *)readdir->verifier.data)[0],
+ 			((u32 *)readdir->verifier.data)[1]);
+ 

commit 19e729a928172103e101ffd0829fd13e68c13f78
+Author: J. Bruce Fields 
+Date:   Mon Apr 14 15:03:02 2008 -0400
+
+    locks: fix possible infinite loop in fcntl(F_SETLKW) over nfs
+    
+    Miklos Szeredi found the bug:
+    
+            "Basically what happens is that on the server nlm_fopen() calls
+            nfsd_open() which returns -EACCES, to which nlm_fopen() returns
+            NLM_LCK_DENIED.
+    
+            "On the client this will turn into a -EAGAIN (nlm_stat_to_errno()),
+            which in will cause fcntl_setlk() to retry forever."
+    
+    So, for example, opening a file on an nfs filesystem, changing
+    permissions to forbid further access, then trying to lock the file,
+    could result in an infinite loop.
+    
+    And Trond Myklebust identified the culprit, from Marc Eshel and I:
+    
+            7723ec9777d9832849b76475b1a21a2872a40d20 "locks: factor out
+            generic/filesystem switch from setlock code"
+    
+    That commit claimed to just be reshuffling code, but actually introduced
+    a behavioral change by calling the lock method repeatedly as long as it
+    returned -EAGAIN.
+    
+    We assumed this would be safe, since we assumed a lock of type SETLKW
+    would only return with either success or an error other than -EAGAIN.
+    However, nfs does can in fact return -EAGAIN in this situation, and
+    independently of whether that behavior is correct or not, we don't
+    actually need this change, and it seems far safer not to depend on such
+    assumptions about the filesystem's ->lock method.
+    
+    Therefore, revert the problematic part of the original commit.  This
+    leaves vfs_lock_file() and its other callers unchanged, while returning
+    fcntl_setlk and fcntl_setlk64 to their former behavior.
+    
+    Signed-off-by: J. Bruce Fields 
+    Tested-by: Miklos Szeredi 
+    Cc: Trond Myklebust 
+    Cc: Marc Eshel 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/locks.c b/fs/locks.c
+index d83fab1b77b5..43c0af21a0c5 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -1801,17 +1801,21 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
+ 	if (error)
+ 		goto out;
+ 
+-	for (;;) {
+-		error = vfs_lock_file(filp, cmd, file_lock, NULL);
+-		if (error != -EAGAIN || cmd == F_SETLK)
+-			break;
+-		error = wait_event_interruptible(file_lock->fl_wait,
+-				!file_lock->fl_next);
+-		if (!error)
+-			continue;
++	if (filp->f_op && filp->f_op->lock != NULL)
++		error = filp->f_op->lock(filp, cmd, file_lock);
++	else {
++		for (;;) {
++			error = posix_lock_file(filp, file_lock, NULL);
++			if (error != -EAGAIN || cmd == F_SETLK)
++				break;
++			error = wait_event_interruptible(file_lock->fl_wait,
++					!file_lock->fl_next);
++			if (!error)
++				continue;
+ 
+-		locks_delete_block(file_lock);
+-		break;
++			locks_delete_block(file_lock);
++			break;
++		}
+ 	}
+ 
+ 	/*
+@@ -1925,17 +1929,21 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
+ 	if (error)
+ 		goto out;
+ 
+-	for (;;) {
+-		error = vfs_lock_file(filp, cmd, file_lock, NULL);
+-		if (error != -EAGAIN || cmd == F_SETLK64)
+-			break;
+-		error = wait_event_interruptible(file_lock->fl_wait,
+-				!file_lock->fl_next);
+-		if (!error)
+-			continue;
++	if (filp->f_op && filp->f_op->lock != NULL)
++		error = filp->f_op->lock(filp, cmd, file_lock);
++	else {
++		for (;;) {
++			error = posix_lock_file(filp, file_lock, NULL);
++			if (error != -EAGAIN || cmd == F_SETLK64)
++				break;
++			error = wait_event_interruptible(file_lock->fl_wait,
++					!file_lock->fl_next);
++			if (!error)
++				continue;
+ 
+-		locks_delete_block(file_lock);
+-		break;
++			locks_delete_block(file_lock);
++			break;
++		}
+ 	}
+ 
+ 	/*

commit d396c5f158547e50c2b78bc984cb4a72d76e969b
+Author: J. Bruce Fields 
+Date:   Mon Apr 7 16:39:38 2008 -0400
+
+    Move sched-rt-group.txt to scheduler/
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Jonathan Corbet 
+
+diff --git a/Documentation/scheduler/00-INDEX b/Documentation/scheduler/00-INDEX
+index b5f5ca069b2d..fc234d093fbf 100644
+--- a/Documentation/scheduler/00-INDEX
++++ b/Documentation/scheduler/00-INDEX
+@@ -12,5 +12,7 @@ sched-domains.txt
+ 	- information on scheduling domains.
+ sched-nice-design.txt
+ 	- How and why the scheduler's nice levels are implemented.
++sched-rt-group.txt
++	- real-time group scheduling.
+ sched-stats.txt
+ 	- information on schedstats (Linux Scheduler Statistics).
+diff --git a/Documentation/sched-rt-group.txt b/Documentation/scheduler/sched-rt-group.txt
+similarity index 100%
+rename from Documentation/sched-rt-group.txt
+rename to Documentation/scheduler/sched-rt-group.txt

commit 8bcd1cc293f4e76edbfd8f422770c80a018b82d9
+Author: J. Bruce Fields 
+Date:   Mon Apr 7 15:59:04 2008 -0400
+
+    Documentation: move rpc-cache.txt to filesystems/
+    
+    This file is nfs-related.  (Maybe Documentation/filesystems/ would
+    benefit from a separate nfs/ directory at some point.)
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Jonathan Corbet 
+
+diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
+index 08a39cdb27f2..e8fb24671967 100644
+--- a/Documentation/00-INDEX
++++ b/Documentation/00-INDEX
+@@ -319,8 +319,6 @@ robust-futexes.txt
+ 	- a description of what robust futexes are.
+ rocket.txt
+ 	- info on the Comtrol RocketPort multiport serial driver.
+-rpc-cache.txt
+-	- introduction to the caching mechanisms in the sunrpc layer.
+ rt-mutex-design.txt
+ 	- description of the RealTime mutex implementation design.
+ rt-mutex.txt
+diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
+index 2ec174c992f1..52cd611277a3 100644
+--- a/Documentation/filesystems/00-INDEX
++++ b/Documentation/filesystems/00-INDEX
+@@ -84,6 +84,8 @@ relay.txt
+ 	- info on relay, for efficient streaming from kernel to user space.
+ romfs.txt
+ 	- description of the ROMFS filesystem.
++rpc-cache.txt
++	- introduction to the caching mechanisms in the sunrpc layer.
+ seq_file.txt
+ 	- how to use the seq_file API
+ sharedsubtree.txt
+diff --git a/Documentation/rpc-cache.txt b/Documentation/filesystems/rpc-cache.txt
+similarity index 100%
+rename from Documentation/rpc-cache.txt
+rename to Documentation/filesystems/rpc-cache.txt

commit 6ded55da6be9f186ae1022724a5881b43846c164
+Author: J. Bruce Fields 
+Date:   Mon Apr 7 15:59:03 2008 -0400
+
+    Documentation: move nfsroot.txt to filesystems/
+    
+    Documentation/ is a little large, and filesystems/ seems an obvious
+    place for this file.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Jonathan Corbet 
+
+diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
+index fc8e7c7d182f..08a39cdb27f2 100644
+--- a/Documentation/00-INDEX
++++ b/Documentation/00-INDEX
+@@ -271,8 +271,6 @@ netlabel/
+ 	- directory with information on the NetLabel subsystem.
+ networking/
+ 	- directory with info on various aspects of networking with Linux.
+-nfsroot.txt
+-	- short guide on setting up a diskless box with NFS root filesystem.
+ nmi_watchdog.txt
+ 	- info on NMI watchdog for SMP systems.
+ nommu-mmap.txt
+diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
+index e731196410b3..2ec174c992f1 100644
+--- a/Documentation/filesystems/00-INDEX
++++ b/Documentation/filesystems/00-INDEX
+@@ -66,6 +66,8 @@ mandatory-locking.txt
+ 	- info on the Linux implementation of Sys V mandatory file locking.
+ ncpfs.txt
+ 	- info on Novell Netware(tm) filesystem using NCP protocol.
++nfsroot.txt
++	- short guide on setting up a diskless box with NFS root filesystem.
+ ntfs.txt
+ 	- info and mount options for the NTFS filesystem (Windows NT).
+ ocfs2.txt
+diff --git a/Documentation/nfsroot.txt b/Documentation/filesystems/nfsroot.txt
+similarity index 100%
+rename from Documentation/nfsroot.txt
+rename to Documentation/filesystems/nfsroot.txt
+diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
+index 508e2a2c9864..57709e472b9b 100644
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -845,7 +845,7 @@ and is between 256 and 4096 characters. It is defined in the file
+ 			arch/alpha/kernel/core_marvel.c.
+ 
+ 	ip=		[IP_PNP]
+-			See Documentation/nfsroot.txt.
++			See Documentation/filesystems/nfsroot.txt.
+ 
+ 	ip2=		[HW] Set IO/IRQ pairs for up to 4 IntelliPort boards
+ 			See comment before ip2_setup() in
+@@ -1199,10 +1199,10 @@ and is between 256 and 4096 characters. It is defined in the file
+ 			file if at all.
+ 
+ 	nfsaddrs=	[NFS]
+-			See Documentation/nfsroot.txt.
++			See Documentation/filesystems/nfsroot.txt.
+ 
+ 	nfsroot=	[NFS] nfs root filesystem for disk-less boxes.
+-			See Documentation/nfsroot.txt.
++			See Documentation/filesystems/nfsroot.txt.
+ 
+ 	nfs.callback_tcpport=
+ 			[NFS] set the TCP port on which the NFSv4 callback
+diff --git a/fs/Kconfig b/fs/Kconfig
+index d7312825592b..c509123bea49 100644
+--- a/fs/Kconfig
++++ b/fs/Kconfig
+@@ -1744,10 +1744,10 @@ config ROOT_NFS
+ 	  If you want your Linux box to mount its whole root file system (the
+ 	  one containing the directory /) from some other computer over the
+ 	  net via NFS (presumably because your box doesn't have a hard disk),
+-	  say Y. Read  for details. It is
+-	  likely that in this case, you also want to say Y to "Kernel level IP
+-	  autoconfiguration" so that your box can discover its network address
+-	  at boot time.
++	  say Y. Read  for
++	  details. It is likely that in this case, you also want to say Y to
++	  "Kernel level IP autoconfiguration" so that your box can discover
++	  its network address at boot time.
+ 
+ 	  Most people say N here.
+ 
+diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
+index 9c7e5ffb223d..4670683b4688 100644
+--- a/net/ipv4/Kconfig
++++ b/net/ipv4/Kconfig
+@@ -160,7 +160,7 @@ config IP_PNP_DHCP
+ 
+ 	  If unsure, say Y. Note that if you want to use DHCP, a DHCP server
+ 	  must be operating on your network.  Read
+-	   for details.
++	   for details.
+ 
+ config IP_PNP_BOOTP
+ 	bool "IP: BOOTP support"
+@@ -175,7 +175,7 @@ config IP_PNP_BOOTP
+ 	  does BOOTP itself, providing all necessary information on the kernel
+ 	  command line, you can say N here. If unsure, say Y. Note that if you
+ 	  want to use BOOTP, a BOOTP server must be operating on your network.
+-	  Read  for details.
++	  Read  for details.
+ 
+ config IP_PNP_RARP
+ 	bool "IP: RARP support"
+@@ -187,8 +187,8 @@ config IP_PNP_RARP
+ 	  discovered automatically at boot time using the RARP protocol (an
+ 	  older protocol which is being obsoleted by BOOTP and DHCP), say Y
+ 	  here. Note that if you want to use RARP, a RARP server must be
+-	  operating on your network. Read  for
+-	  details.
++	  operating on your network. Read
++	   for details.
+ 
+ # not yet ready..
+ #   bool '    IP: ARP support' CONFIG_IP_PNP_ARP		
+diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
+index 7c992fbbc2c3..4824fe8996bf 100644
+--- a/net/ipv4/ipconfig.c
++++ b/net/ipv4/ipconfig.c
+@@ -1411,7 +1411,7 @@ late_initcall(ip_auto_config);
+ 
+ /*
+  *  Decode any IP configuration options in the "ip=" or "nfsaddrs=" kernel
+- *  command line parameter.  See Documentation/nfsroot.txt.
++ *  command line parameter.  See Documentation/filesystems/nfsroot.txt.
+  */
+ static int __init ic_proto_name(char *name)
+ {

commit dc07e721a26ec7e0adb66340f1763d220cfbbd0c
+Author: J. Bruce Fields 
+Date:   Mon Apr 7 15:59:05 2008 -0400
+
+    Spell out behavior of atomic_dec_and_lock() in kerneldoc
+    
+    A little more detail here wouldn't hurt.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Jonathan Corbet 
+
+diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
+index 576a5f77d3bd..1129ee0a7180 100644
+--- a/include/linux/spinlock.h
++++ b/include/linux/spinlock.h
+@@ -341,6 +341,9 @@ static inline void double_spin_unlock(spinlock_t *l1, spinlock_t *l2,
+  * atomic_dec_and_lock - lock on reaching reference count zero
+  * @atomic: the atomic counter
+  * @lock: the spinlock in question
++ *
++ * Decrements @atomic by 1.  If the result is 0, returns true and locks
++ * @lock.  Returns false for all other cases.
+  */
+ extern int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock);
+ #define atomic_dec_and_lock(atomic, lock) \

commit 4af68bffac444a23f027e18ff244101e63b79227
+Author: Fred Isaman 
+Date:   Wed Mar 19 11:54:04 2008 -0400
+
+    nfs: remove duplicate initializations of nfs_read_data field
+    
+    Signed-off-by: Fred Isaman 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/read.c b/fs/nfs/read.c
+index ab2f7d233e01..d333f5fedca1 100644
+--- a/fs/nfs/read.c
++++ b/fs/nfs/read.c
+@@ -251,7 +251,6 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne
+ 		data = nfs_readdata_alloc(1);
+ 		if (!data)
+ 			goto out_bad;
+-		INIT_LIST_HEAD(&data->pages);
+ 		list_add(&data->pages, &list);
+ 		requests++;
+ 		nbytes -= len;
+@@ -298,7 +297,6 @@ static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned
+ 	if (!data)
+ 		goto out_bad;
+ 
+-	INIT_LIST_HEAD(&data->pages);
+ 	pages = data->pagevec;
+ 	while (!list_empty(head)) {
+ 		req = nfs_list_entry(head->next);

commit 6d884e8fc8114dc8877218f06a9a9a1d801901e4
+Author: Fred 
+Date:   Wed Mar 19 11:24:38 2008 -0400
+
+    nfs: nfs_redirty_request
+    
+    Both flush functions have the same error handling routine.  Pull
+    it out as a function.
+    
+    Signed-off-by: Fred Isaman 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/write.c b/fs/nfs/write.c
+index 4cb88df12f83..ce40cadb15db 100644
+--- a/fs/nfs/write.c
++++ b/fs/nfs/write.c
+@@ -282,8 +282,6 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
+ 	spin_unlock(&inode->i_lock);
+ 	if (!nfs_pageio_add_request(pgio, req)) {
+ 		nfs_redirty_request(req);
+-		nfs_end_page_writeback(page);
+-		nfs_clear_page_tag_locked(req);
+ 		return pgio->pg_error;
+ 	}
+ 	return 0;
+@@ -402,7 +400,7 @@ static void nfs_inode_remove_request(struct nfs_page *req)
+ }
+ 
+ static void
+-nfs_redirty_request(struct nfs_page *req)
++nfs_mark_request_dirty(struct nfs_page *req)
+ {
+ 	__set_page_dirty_nobuffers(req->wb_page);
+ }
+@@ -456,7 +454,7 @@ int nfs_reschedule_unstable_write(struct nfs_page *req)
+ 		return 1;
+ 	}
+ 	if (test_and_clear_bit(PG_NEED_RESCHED, &req->wb_flags)) {
+-		nfs_redirty_request(req);
++		nfs_mark_request_dirty(req);
+ 		return 1;
+ 	}
+ 	return 0;
+@@ -847,6 +845,17 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
+ 		rpc_put_task(task);
+ }
+ 
++/* If a nfs_flush_* function fails, it should remove reqs from @head and
++ * call this on each, which will prepare them to be retried on next
++ * writeback using standard nfs.
++ */
++static void nfs_redirty_request(struct nfs_page *req)
++{
++	nfs_mark_request_dirty(req);
++	nfs_end_page_writeback(req->wb_page);
++	nfs_clear_page_tag_locked(req);
++}
++
+ /*
+  * Generate multiple small requests to write out a single
+  * contiguous dirty area on one page.
+@@ -902,8 +911,6 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned
+ 		nfs_writedata_release(data);
+ 	}
+ 	nfs_redirty_request(req);
+-	nfs_end_page_writeback(req->wb_page);
+-	nfs_clear_page_tag_locked(req);
+ 	return -ENOMEM;
+ }
+ 
+@@ -944,8 +951,6 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned i
+ 		req = nfs_list_entry(head->next);
+ 		nfs_list_remove_request(req);
+ 		nfs_redirty_request(req);
+-		nfs_end_page_writeback(req->wb_page);
+-		nfs_clear_page_tag_locked(req);
+ 	}
+ 	return -ENOMEM;
+ }
+@@ -1298,7 +1303,7 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
+ 		}
+ 		/* We have a mismatch. Write the page again */
+ 		dprintk(" mismatch\n");
+-		nfs_redirty_request(req);
++		nfs_mark_request_dirty(req);
+ 	next:
+ 		nfs_clear_page_tag_locked(req);
+ 	}

commit f8512ad0da16cbe156f3a7627971cdf0b39c4138
+Author: Fred Isaman 
+Date:   Wed Mar 19 11:24:39 2008 -0400
+
+    nfs: don't ignore return value from nfs_pageio_add_request
+    
+    Ignoring the return value from nfs_pageio_add_request can cause deadlocks.
+    
+    In read path:
+      call nfs_pageio_add_request from readpage_async_filler
+      assume at this point that there are requests already in desc, that
+        can't be merged with the current request.
+      so nfs_pageio_doio is fired up to clear out desc.
+      assume something goes wrong in setting up the io, so desc->pg_error is set.
+      This causes nfs_pageio_add_request to return 0, *WITHOUT* adding the original
+        request.
+      BUT, since return code is ignored, readpage_async_filler assumes it has
+        been added, and does nothing further, leaving page locked.
+      do_generic_mapping_read will eventually call lock_page, resulting in deadlock
+    
+    In write path:
+      page is marked dirty by generic_perform_write
+      nfs_writepages is called
+      call nfs_pageio_add_request from nfs_page_async_flush
+      assume at this point that there are requests already in desc, that
+        can't be merged with the current request.
+      so nfs_pageio_doio is fired up to clear out desc.
+      assume something goes wrong in setting up the io, so desc->pg_error is set.
+      This causes nfs_page_async_flush to return 0, *WITHOUT* adding the original
+        request, yet marking the request as locked (PG_BUSY) and in writeback,
+        clearing dirty marks.
+      The next time a write is done to the page, deadlock will result as
+        nfs_write_end calls nfs_update_request
+    
+    Signed-off-by: Fred Isaman 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/read.c b/fs/nfs/read.c
+index 3d7d9631e125..5a70be589bbe 100644
+--- a/fs/nfs/read.c
++++ b/fs/nfs/read.c
+@@ -533,7 +533,10 @@ readpage_async_filler(void *data, struct page *page)
+ 
+ 	if (len < PAGE_CACHE_SIZE)
+ 		zero_user_segment(page, len, PAGE_CACHE_SIZE);
+-	nfs_pageio_add_request(desc->pgio, new);
++	if (!nfs_pageio_add_request(desc->pgio, new)) {
++		error = desc->pgio->pg_error;
++		goto out_unlock;
++	}
+ 	return 0;
+ out_error:
+ 	error = PTR_ERR(new);
+diff --git a/fs/nfs/write.c b/fs/nfs/write.c
+index 80c61fdb2720..bed63416a55b 100644
+--- a/fs/nfs/write.c
++++ b/fs/nfs/write.c
+@@ -39,6 +39,7 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context*,
+ 					    unsigned int, unsigned int);
+ static void nfs_pageio_init_write(struct nfs_pageio_descriptor *desc,
+ 				  struct inode *inode, int ioflags);
++static void nfs_redirty_request(struct nfs_page *req);
+ static const struct rpc_call_ops nfs_write_partial_ops;
+ static const struct rpc_call_ops nfs_write_full_ops;
+ static const struct rpc_call_ops nfs_commit_ops;
+@@ -288,7 +289,12 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
+ 		BUG();
+ 	}
+ 	spin_unlock(&inode->i_lock);
+-	nfs_pageio_add_request(pgio, req);
++	if (!nfs_pageio_add_request(pgio, req)) {
++		nfs_redirty_request(req);
++		nfs_end_page_writeback(page);
++		nfs_clear_page_tag_locked(req);
++		return pgio->pg_error;
++	}
+ 	return 0;
+ }
+ 

commit b663c6fd98c9cf586279db03cec3257c413efd00
+Author: J. Bruce Fields 
+Date:   Fri Mar 14 19:37:11 2008 -0400
+
+    nfsd: fix oops on access from high-numbered ports
+    
+    This bug was always here, but before my commit 6fa02839bf9412e18e77
+    ("recheck for secure ports in fh_verify"), it could only be triggered by
+    failure of a kmalloc().  After that commit it could be triggered by a
+    client making a request from a non-reserved port for access to an export
+    marked "secure".  (Exports are "secure" by default.)
+    
+    The result is a struct svc_export with a reference count one too low,
+    resulting in likely oopses next time the export is accessed.
+    
+    The reference counting here is not straightforward; a later patch will
+    clean up fh_verify().
+    
+    Thanks to Lukas Hejtmanek for the bug report and followup.
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: Lukas Hejtmanek 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
+index 1eb771d79cca..3e6b3f41ee1f 100644
+--- a/fs/nfsd/nfsfh.c
++++ b/fs/nfsd/nfsfh.c
+@@ -232,6 +232,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
+ 		fhp->fh_dentry = dentry;
+ 		fhp->fh_export = exp;
+ 		nfsd_nr_verified++;
++		cache_get(&exp->h);
+ 	} else {
+ 		/*
+ 		 * just rechecking permissions
+@@ -241,6 +242,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
+ 		dprintk("nfsd: fh_verify - just checking\n");
+ 		dentry = fhp->fh_dentry;
+ 		exp = fhp->fh_export;
++		cache_get(&exp->h);
+ 		/*
+ 		 * Set user creds for this exportpoint; necessary even
+ 		 * in the "just checking" case because this may be a
+@@ -252,8 +254,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
+ 		if (error)
+ 			goto out;
+ 	}
+-	cache_get(&exp->h);
+-
+ 
+ 	error = nfsd_mode_check(rqstp, dentry->d_inode->i_mode, type);
+ 	if (error)

commit 2f42b5d043ee271d1e5d30ecd77186b6c4d4e534
+Author: Fred Isaman 
+Date:   Thu Mar 13 15:26:30 2008 +0200
+
+    NFS: fix encode_fsinfo_maxsz
+    
+    The previous value was not taking into account space for bitmap array size.
+    
+    Signed-off-by: Fred Isaman 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
+index db1ed9c46ede..37421dd4805d 100644
+--- a/fs/nfs/nfs4xdr.c
++++ b/fs/nfs/nfs4xdr.c
+@@ -110,7 +110,7 @@ static int nfs4_stat_to_errno(int);
+ #define decode_savefh_maxsz     (op_decode_hdr_maxsz)
+ #define encode_restorefh_maxsz  (op_encode_hdr_maxsz)
+ #define decode_restorefh_maxsz  (op_decode_hdr_maxsz)
+-#define encode_fsinfo_maxsz	(op_encode_hdr_maxsz + 2)
++#define encode_fsinfo_maxsz	(encode_getattr_maxsz)
+ #define decode_fsinfo_maxsz	(op_decode_hdr_maxsz + 11)
+ #define encode_renew_maxsz	(op_encode_hdr_maxsz + 3)
+ #define decode_renew_maxsz	(op_decode_hdr_maxsz)

commit 8d042218b075de3cdbe066198515b3521553746e
+Author: Olga Kornievskaia 
+Date:   Wed Feb 13 16:47:06 2008 -0500
+
+    NFS: add missing spkm3 strings to mount option parser
+    
+    This patch adds previous missing spkm3 string values that are needed
+    to parse mount options in the kernel.
+
+diff --git a/fs/nfs/super.c b/fs/nfs/super.c
+index 7f4505f6ac6f..1fb381843650 100644
+--- a/fs/nfs/super.c
++++ b/fs/nfs/super.c
+@@ -190,6 +190,10 @@ static match_table_t nfs_secflavor_tokens = {
+ 	{ Opt_sec_lkeyi, "lkeyi" },
+ 	{ Opt_sec_lkeyp, "lkeyp" },
+ 
++	{ Opt_sec_spkm, "spkm3" },
++	{ Opt_sec_spkmi, "spkm3i" },
++	{ Opt_sec_spkmp, "spkm3p" },
++
+ 	{ Opt_sec_err, NULL }
+ };
+ 

commit df24d9a6a9014010513d6af1105f4de05c504a4b
+Author: J. Bruce Fields 
+Date:   Wed Feb 13 15:03:20 2008 -0800
+
+    Documentation: prune redundant SubmitChecklist items
+    
+    Kernel style is mentioned twice, and the git apply trick is a bit redundant
+    given the checkpatch.pl recommendation (which also checks for bad
+    whitespace).
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: "Randy.Dunlap" 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/Documentation/SubmitChecklist b/Documentation/SubmitChecklist
+index 34e06d2f194f..da10e0714241 100644
+--- a/Documentation/SubmitChecklist
++++ b/Documentation/SubmitChecklist
+@@ -20,7 +20,11 @@ kernel patches.
+ 4: ppc64 is a good architecture for cross-compilation checking because it
+    tends to use `unsigned long' for 64-bit quantities.
+ 
+-5: Matches kernel coding style(!)
++5: Check your patch for general style as detailed in
++   Documentation/CodingStyle.  Check for trivial violations with the
++   patch style checker prior to submission (scripts/checkpatch.pl).
++   You should be able to justify all violations that remain in
++   your patch.
+ 
+ 6: Any new or modified CONFIG options don't muck up the config menu.
+ 
+@@ -79,13 +83,3 @@ kernel patches.
+ 23: Tested after it has been merged into the -mm patchset to make sure
+     that it still works with all of the other queued patches and various
+     changes in the VM, VFS, and other subsystems.
+-
+-24: Avoid whitespace damage such as indenting with spaces or whitespace
+-    at the end of lines.  You can test this by feeding the patch to
+-    "git apply --check --whitespace=error-all"
+-
+-25: Check your patch for general style as detailed in
+-    Documentation/CodingStyle.  Check for trivial violations with the
+-    patch style checker prior to submission (scripts/checkpatch.pl).
+-    You should be able to justify all violations that remain in
+-    your patch.

commit fbb7878c1a2ee40a1e983bf20f3dd3a80255dcf2
+Author: J. Bruce Fields 
+Date:   Thu Feb 7 23:10:21 2008 -0500
+
+    nfsd: clean up svc_reserve_auth()
+    
+    This is a void function attempting to return the return value from
+    another void function, which seems harmless but extremely weird, and
+    apparently makes some compilers complain.
+    
+    While we're there, clean up a little (e.g. the switch statement had a
+    minor style problem and seemed overkill as long as there's only one
+    case).
+    
+    Thanks to Trond for noticing this.
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
+index 64c771056187..64c97552964a 100644
+--- a/include/linux/sunrpc/svc.h
++++ b/include/linux/sunrpc/svc.h
+@@ -409,16 +409,13 @@ char *		   svc_print_addr(struct svc_rqst *, char *, size_t);
+  * for all cases without actually generating the checksum, so we just use a
+  * static value.
+  */
+-static inline void
+-svc_reserve_auth(struct svc_rqst *rqstp, int space)
++static inline void svc_reserve_auth(struct svc_rqst *rqstp, int space)
+ {
+-	int			added_space = 0;
++	int added_space = 0;
+ 
+-	switch(rqstp->rq_authop->flavour) {
+-		case RPC_AUTH_GSS:
+-			added_space = RPC_MAX_AUTH_SIZE;
+-	}
+-	return svc_reserve(rqstp, space + added_space);
++	if (rqstp->rq_authop->flavour)
++		added_space = RPC_MAX_AUTH_SIZE;
++	svc_reserve(rqstp, space + added_space);
+ }
+ 
+ #endif /* SUNRPC_SVC_H */

commit 3ab32df72bfa7bee9126cc5b1abc037aef124f15
+Author: J. Bruce Fields 
+Date:   Thu Feb 7 00:13:40 2008 -0800
+
+    REPORTING-BUGS: cc the mailing list too
+    
+    People should also cc relevant mailing lists when reporting bugs.
+    
+    Signed-off-by: J. Bruce Fields 
+    Acked-by: Randy Dunlap 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/REPORTING-BUGS b/REPORTING-BUGS
+index ac02e42a2627..ab0c56630a8c 100644
+--- a/REPORTING-BUGS
++++ b/REPORTING-BUGS
+@@ -10,11 +10,12 @@ bug report. This explains what you should do with the "Oops" information
+ to make it useful to the recipient.
+ 
+       Send the output to the maintainer of the kernel area that seems to
+-be involved with the problem. Don't worry too much about getting the
+-wrong person. If you are unsure send it to the person responsible for the
+-code relevant to what you were doing. If it occurs repeatably try and
+-describe how to recreate it. That is worth even more than the oops itself.
+-The list of maintainers is in the MAINTAINERS file in this directory.
++be involved with the problem, and cc the relevant mailing list. Don't
++worry too much about getting the wrong person. If you are unsure send it
++to the person responsible for the code relevant to what you were doing.
++If it occurs repeatably try and describe how to recreate it. That is
++worth even more than the oops itself.  The list of maintainers and
++mailing lists is in the MAINTAINERS file in this directory.
+ 
+       If it is a security bug, please copy the Security Contact listed
+ in the MAINTAINERS file.  They can help coordinate bugfix and disclosure.

commit 9b8eae7248dad42091204f83ed3448e661456af1
+Author: J. Bruce Fields 
+Date:   Thu Feb 7 00:13:37 2008 -0800
+
+    Documentation: create new scheduler/ subdirectory
+    
+    The top-level Documentation/ directory is unmanageably large, so we
+    should take any obvious opportunities to move stuff into subdirectories.
+    These sched-*.txt files seem an obvious easy case.
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: Ingo Molnar 
+    Acked-by: Randy Dunlap 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
+index 4d4dde447fe7..d273b557a934 100644
+--- a/Documentation/00-INDEX
++++ b/Documentation/00-INDEX
+@@ -332,20 +332,8 @@ rtc.txt
+ 	- notes on how to use the Real Time Clock (aka CMOS clock) driver.
+ s390/
+ 	- directory with info on using Linux on the IBM S390.
+-sched-arch.txt
+-	- CPU Scheduler implementation hints for architecture specific code.
+-sched-coding.txt
+-	- reference for various scheduler-related methods in the O(1) scheduler.
+-sched-design.txt
+-	- goals, design and implementation of the Linux O(1) scheduler.
+-sched-design-CFS.txt
+-	- goals, design and implementation of the Complete Fair Scheduler.
+-sched-domains.txt
+-	- information on scheduling domains.
+-sched-nice-design.txt
+-	- How and why the scheduler's nice levels are implemented.
+-sched-stats.txt
+-	- information on schedstats (Linux Scheduler Statistics).
++scheduler/
++	- directory with info on the scheduler.
+ scsi/
+ 	- directory with info on Linux scsi support.
+ serial/
+diff --git a/Documentation/ABI/testing/sysfs-kernel-uids b/Documentation/ABI/testing/sysfs-kernel-uids
+index 648d65dbc0e7..28f14695a852 100644
+--- a/Documentation/ABI/testing/sysfs-kernel-uids
++++ b/Documentation/ABI/testing/sysfs-kernel-uids
+@@ -11,4 +11,4 @@ Description:
+ 		example would be, if User A has shares = 1024 and user
+ 		B has shares = 2048, User B will get twice the CPU
+ 		bandwidth user A will. For more details refer
+-		Documentation/sched-design-CFS.txt
++		Documentation/scheduler/sched-design-CFS.txt
+diff --git a/Documentation/scheduler/00-INDEX b/Documentation/scheduler/00-INDEX
+new file mode 100644
+index 000000000000..b5f5ca069b2d
+--- /dev/null
++++ b/Documentation/scheduler/00-INDEX
+@@ -0,0 +1,16 @@
++00-INDEX
++	- this file.
++sched-arch.txt
++	- CPU Scheduler implementation hints for architecture specific code.
++sched-coding.txt
++	- reference for various scheduler-related methods in the O(1) scheduler.
++sched-design.txt
++	- goals, design and implementation of the Linux O(1) scheduler.
++sched-design-CFS.txt
++	- goals, design and implementation of the Complete Fair Scheduler.
++sched-domains.txt
++	- information on scheduling domains.
++sched-nice-design.txt
++	- How and why the scheduler's nice levels are implemented.
++sched-stats.txt
++	- information on schedstats (Linux Scheduler Statistics).
+diff --git a/Documentation/sched-arch.txt b/Documentation/scheduler/sched-arch.txt
+similarity index 100%
+rename from Documentation/sched-arch.txt
+rename to Documentation/scheduler/sched-arch.txt
+diff --git a/Documentation/sched-coding.txt b/Documentation/scheduler/sched-coding.txt
+similarity index 100%
+rename from Documentation/sched-coding.txt
+rename to Documentation/scheduler/sched-coding.txt
+diff --git a/Documentation/sched-design-CFS.txt b/Documentation/scheduler/sched-design-CFS.txt
+similarity index 100%
+rename from Documentation/sched-design-CFS.txt
+rename to Documentation/scheduler/sched-design-CFS.txt
+diff --git a/Documentation/sched-design.txt b/Documentation/scheduler/sched-design.txt
+similarity index 100%
+rename from Documentation/sched-design.txt
+rename to Documentation/scheduler/sched-design.txt
+diff --git a/Documentation/sched-domains.txt b/Documentation/scheduler/sched-domains.txt
+similarity index 100%
+rename from Documentation/sched-domains.txt
+rename to Documentation/scheduler/sched-domains.txt
+diff --git a/Documentation/sched-nice-design.txt b/Documentation/scheduler/sched-nice-design.txt
+similarity index 100%
+rename from Documentation/sched-nice-design.txt
+rename to Documentation/scheduler/sched-nice-design.txt
+diff --git a/Documentation/sched-stats.txt b/Documentation/scheduler/sched-stats.txt
+similarity index 100%
+rename from Documentation/sched-stats.txt
+rename to Documentation/scheduler/sched-stats.txt

commit d3cf91d0e201962a6367191e5926f5b0920b0339
+Author: J. Bruce Fields 
+Date:   Thu Feb 7 00:13:35 2008 -0800
+
+    Documentation: move sharedsubtrees.txt to filesystems/
+    
+    This documentation is also vfs-related.
+    
+    Signed-off-by: J. Bruce Fields 
+    Acked-by: Randy Dunlap 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
+index bb5e21034209..4d4dde447fe7 100644
+--- a/Documentation/00-INDEX
++++ b/Documentation/00-INDEX
+@@ -358,8 +358,6 @@ sgi-visws.txt
+ 	- short blurb on the SGI Visual Workstations.
+ sh/
+ 	- directory with info on porting Linux to a new architecture.
+-sharedsubtree.txt
+-	- a description of shared subtrees for namespaces.
+ smart-config.txt
+ 	- description of the Smart Config makefile feature.
+ sony-laptop.txt
+diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
+index 632fe3f376eb..e68021c08fbd 100644
+--- a/Documentation/filesystems/00-INDEX
++++ b/Documentation/filesystems/00-INDEX
+@@ -82,6 +82,8 @@ relay.txt
+ 	- info on relay, for efficient streaming from kernel to user space.
+ romfs.txt
+ 	- description of the ROMFS filesystem.
++sharedsubtree.txt
++	- a description of shared subtrees for namespaces.
+ smbfs.txt
+ 	- info on using filesystems with the SMB protocol (Win 3.11 and NT).
+ spufs.txt
+diff --git a/Documentation/sharedsubtree.txt b/Documentation/filesystems/sharedsubtree.txt
+similarity index 100%
+rename from Documentation/sharedsubtree.txt
+rename to Documentation/filesystems/sharedsubtree.txt

commit e9b1a4d160f68397d29183ce76af1cc774508aba
+Author: J. Bruce Fields 
+Date:   Thu Feb 7 00:13:35 2008 -0800
+
+    Documentation: move dnotify.txt to filesystems/
+    
+    I'm inclined to think dnotify belongs in filesystems/.
+    
+    Signed-off-by: J. Bruce Fields 
+    Acked-by: Randy Dunlap 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
+index c1067e48b529..bb5e21034209 100644
+--- a/Documentation/00-INDEX
++++ b/Documentation/00-INDEX
+@@ -126,8 +126,6 @@ devices.txt
+ 	- plain ASCII listing of all the nodes in /dev/ with major minor #'s.
+ digiepca.txt
+ 	- info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards.
+-dnotify.txt
+-	- info about directory notification in Linux.
+ dontdiff
+ 	- file containing a list of files that should never be diff'ed.
+ driver-model/
+diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
+index 1de155e2dc36..632fe3f376eb 100644
+--- a/Documentation/filesystems/00-INDEX
++++ b/Documentation/filesystems/00-INDEX
+@@ -32,6 +32,8 @@ directory-locking
+ 	- info about the locking scheme used for directory operations.
+ dlmfs.txt
+ 	- info on the userspace interface to the OCFS2 DLM.
++dnotify.txt
++	- info about directory notification in Linux.
+ ecryptfs.txt
+ 	- docs on eCryptfs: stacked cryptographic filesystem for Linux.
+ ext2.txt
+diff --git a/Documentation/dnotify.txt b/Documentation/filesystems/dnotify.txt
+similarity index 99%
+rename from Documentation/dnotify.txt
+rename to Documentation/filesystems/dnotify.txt
+index 6984fca6002a..9f5d338ddbb8 100644
+--- a/Documentation/dnotify.txt
++++ b/Documentation/filesystems/dnotify.txt
+@@ -69,24 +69,24 @@ Example
+ 	#include 
+ 	#include 
+ 	#include 
+-	
++
+ 	static volatile int event_fd;
+-	
++
+ 	static void handler(int sig, siginfo_t *si, void *data)
+ 	{
+ 		event_fd = si->si_fd;
+ 	}
+-	
++
+ 	int main(void)
+ 	{
+ 		struct sigaction act;
+ 		int fd;
+-		
++
+ 		act.sa_sigaction = handler;
+ 		sigemptyset(&act.sa_mask);
+ 		act.sa_flags = SA_SIGINFO;
+ 		sigaction(SIGRTMIN + 1, &act, NULL);
+-		
++
+ 		fd = open(".", O_RDONLY);
+ 		fcntl(fd, F_SETSIG, SIGRTMIN + 1);
+ 		fcntl(fd, F_NOTIFY, DN_MODIFY|DN_CREATE|DN_MULTISHOT);

commit b533184fc353d4a2d07929b4ac424a6f1bf5a3b9
+Author: J. Bruce Fields 
+Date:   Fri Oct 26 18:05:40 2007 -0400
+
+    locks: clarify posix_locks_deadlock
+    
+    For such a short function (with such a long comment),
+    posix_locks_deadlock() seems to cause a lot of confusion.  Attempt to
+    make it a bit clearer:
+    
+            - Remove the initial posix_same_owner() check, which can never
+              pass (since this is only called in the case that block_fl and
+              caller_fl conflict)
+            - Use an explicit loop (and a helper function) instead of a goto.
+            - Rewrite the comment, attempting a clearer explanation, and
+              removing some uninteresting historical detail.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/locks.c b/fs/locks.c
+index 8b8388eca05e..c3eecb895acf 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -683,45 +683,55 @@ posix_test_lock(struct file *filp, struct file_lock *fl)
+ 
+ EXPORT_SYMBOL(posix_test_lock);
+ 
+-/* This function tests for deadlock condition before putting a process to
+- * sleep. The detection scheme is no longer recursive. Recursive was neat,
+- * but dangerous - we risked stack corruption if the lock data was bad, or
+- * if the recursion was too deep for any other reason.
+- *
+- * We rely on the fact that a task can only be on one lock's wait queue
+- * at a time. When we find blocked_task on a wait queue we can re-search
+- * with blocked_task equal to that queue's owner, until either blocked_task
+- * isn't found, or blocked_task is found on a queue owned by my_task.
+- *
+- * Note: the above assumption may not be true when handling lock requests
+- * from a broken NFS client. But broken NFS clients have a lot more to
+- * worry about than proper deadlock detection anyway... --okir
+- *
+- * However, the failure of this assumption (also possible in the case of
+- * multiple tasks sharing the same open file table) also means there's no
+- * guarantee that the loop below will terminate.  As a hack, we give up
+- * after a few iterations.
++/*
++ * Deadlock detection:
++ *
++ * We attempt to detect deadlocks that are due purely to posix file
++ * locks.
++ *
++ * We assume that a task can be waiting for at most one lock at a time.
++ * So for any acquired lock, the process holding that lock may be
++ * waiting on at most one other lock.  That lock in turns may be held by
++ * someone waiting for at most one other lock.  Given a requested lock
++ * caller_fl which is about to wait for a conflicting lock block_fl, we
++ * follow this chain of waiters to ensure we are not about to create a
++ * cycle.
++ *
++ * Since we do this before we ever put a process to sleep on a lock, we
++ * are ensured that there is never a cycle; that is what guarantees that
++ * the while() loop in posix_locks_deadlock() eventually completes.
++ *
++ * Note: the above assumption may not be true when handling lock
++ * requests from a broken NFS client. It may also fail in the presence
++ * of tasks (such as posix threads) sharing the same open file table.
++ *
++ * To handle those cases, we just bail out after a few iterations.
+  */
+ 
+ #define MAX_DEADLK_ITERATIONS 10
+ 
++/* Find a lock that the owner of the given block_fl is blocking on. */
++static struct file_lock *what_owner_is_waiting_for(struct file_lock *block_fl)
++{
++	struct file_lock *fl;
++
++	list_for_each_entry(fl, &blocked_list, fl_link) {
++		if (posix_same_owner(fl, block_fl))
++			return fl->fl_next;
++	}
++	return NULL;
++}
++
+ static int posix_locks_deadlock(struct file_lock *caller_fl,
+ 				struct file_lock *block_fl)
+ {
+-	struct file_lock *fl;
+ 	int i = 0;
+ 
+-next_task:
+-	if (posix_same_owner(caller_fl, block_fl))
+-		return 1;
+-	list_for_each_entry(fl, &blocked_list, fl_link) {
+-		if (posix_same_owner(fl, block_fl)) {
+-			if (i++ > MAX_DEADLK_ITERATIONS)
+-				return 0;
+-			fl = fl->fl_next;
+-			block_fl = fl;
+-			goto next_task;
+-		}
++	while ((block_fl = what_owner_is_waiting_for(block_fl))) {
++		if (i++ > MAX_DEADLK_ITERATIONS)
++			return 0;
++		if (posix_same_owner(caller_fl, block_fl))
++			return 1;
+ 	}
+ 	return 0;
+ }

commit 87d26ea7771ad637035e6bd5a2700d81ee9162da
+Author: J. Bruce Fields 
+Date:   Tue Jan 22 17:40:42 2008 -0500
+
+    nfsd: more careful input validation in nfsctl write methods
+    
+    Neil Brown points out that we're checking buf[size-1] in a couple places
+    without first checking whether size is zero.
+    
+    Actually, given the implementation of simple_transaction_get(), buf[-1]
+    is zero, so in both of these cases the subsequent check of the value of
+    buf[size-1] will catch this case.
+    
+    But it seems fragile to depend on that, so add explicit checks for this
+    case.
+    
+    Signed-off-by: J. Bruce Fields 
+    Acked-by: NeilBrown 
+
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index bc22e0b0343a..8516137cdbb0 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -304,6 +304,9 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
+ 	struct auth_domain *dom;
+ 	struct knfsd_fh fh;
+ 
++	if (size == 0)
++		return -EINVAL;
++
+ 	if (buf[size-1] != '\n')
+ 		return -EINVAL;
+ 	buf[size-1] = 0;
+@@ -663,7 +666,7 @@ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
+ 	char *recdir;
+ 	int len, status;
+ 
+-	if (size > PATH_MAX || buf[size-1] != '\n')
++	if (size == 0 || size > PATH_MAX || buf[size-1] != '\n')
+ 		return -EINVAL;
+ 	buf[size-1] = 0;
+ 

commit 50431d94e732ba71b66a83c5435890728e313095
+Author: J. Bruce Fields 
+Date:   Fri Aug 31 17:09:33 2007 -0400
+
+    lockd: minor log message fix
+    
+    Wendy Cheng noticed that function name doesn't agree here.
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: Wendy Cheng 
+
+diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
+index 84ebba33b98d..dbbefbcd6712 100644
+--- a/fs/lockd/svcsubs.c
++++ b/fs/lockd/svcsubs.c
+@@ -87,7 +87,7 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
+ 	unsigned int	hash;
+ 	__be32		nfserr;
+ 
+-	nlm_debug_print_fh("nlm_file_lookup", f);
++	nlm_debug_print_fh("nlm_lookup_file", f);
+ 
+ 	hash = file_hash(f);
+ 

commit f7b8066f9ff68016489ff6f9fb358aa59bd14e1b
+Author: J. Bruce Fields 
+Date:   Mon Jan 21 12:20:45 2008 -0500
+
+    knfsd: don't bother mapping putrootfh enoent to eperm
+    
+    Neither EPERM and ENOENT map to valid errors for PUTROOTFH according to
+    rfc 3530, and, if anything, ENOENT is likely to be slightly more
+    informative; so don't bother mapping ENOENT to EPERM.  (Probably this
+    was originally done because one likely cause was that there is an fsid=0
+    export but that it isn't permitted to this particular client.  Now that
+    we allow WRONGSEC returns, this is somewhat less likely.)
+    
+    In the long term we should work to make this situation less likely,
+    perhaps by turning off nfsv4 service entirely in the absence of the
+    pseudofs root, or constructing a pseudofilesystem root ourselves in the
+    kernel as necessary.
+    
+    Thanks to Benny Halevy  for pointing out this
+    problem.
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: Benny Halevy 
+
+diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
+index cbbc594ef592..79b4bf812960 100644
+--- a/fs/nfsd/export.c
++++ b/fs/nfsd/export.c
+@@ -1357,8 +1357,6 @@ exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp)
+ 	mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL);
+ 
+ 	exp = rqst_exp_find(rqstp, FSID_NUM, fsidv);
+-	if (PTR_ERR(exp) == -ENOENT)
+-		return nfserr_perm;
+ 	if (IS_ERR(exp))
+ 		return nfserrno(PTR_ERR(exp));
+ 	rv = fh_compose(fhp, exp, exp->ex_dentry, NULL);

commit cb5c7d668e1af269a9409721268f027b86abf29c
+Author: J. Bruce Fields 
+Date:   Mon Jan 14 16:05:07 2008 -0500
+
+    svcrpc: ensure gss DESTROY tokens free contexts from cache
+    
+    If we don't do this then we'll end up with a pointless unusable context
+    sitting in the cache until the time the original context would have
+    expired.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
+index e8ed848ecd67..481f984e9a22 100644
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -1126,6 +1126,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
+ 	case RPC_GSS_PROC_DESTROY:
+ 		if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq))
+ 			goto auth_err;
++		rsci->h.expiry_time = get_seconds();
+ 		set_bit(CACHE_NEGATIVE, &rsci->h.flags);
+ 		if (resv->iov_len + 4 > PAGE_SIZE)
+ 			goto drop;

commit 8838dc43d6544570e8969a74ddc4a0d21abffde6
+Author: J. Bruce Fields 
+Date:   Mon Jan 14 13:12:19 2008 -0500
+
+    nfsd4: clean up access_valid, deny_valid checks.
+    
+    Document these checks a little better and inline, as suggested by Neil
+    Brown (note both functions have two callers).  Remove an obviously bogus
+    check while we're there (checking whether unsigned value is negative).
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: Neil Brown 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index c4b10a1e6c30..f6744bc03dae 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1157,14 +1157,19 @@ find_file(struct inode *ino)
+ 	return NULL;
+ }
+ 
+-static int access_valid(u32 x)
++static inline int access_valid(u32 x)
+ {
+-	return (x > 0 && x < 4);
++	if (x < NFS4_SHARE_ACCESS_READ)
++		return 0;
++	if (x > NFS4_SHARE_ACCESS_BOTH)
++		return 0;
++	return 1;
+ }
+ 
+-static int deny_valid(u32 x)
++static inline int deny_valid(u32 x)
+ {
+-	return (x >= 0 && x < 5);
++	/* Note: unlike access bits, deny bits may be zero. */
++	return x <= NFS4_SHARE_DENY_BOTH;
+ }
+ 
+ static void

commit b39c18fce003bb2d5a51a4734d8fdd2c81fa1a78
+Author: J. Bruce Fields 
+Date:   Sun Jan 6 21:32:37 2008 -0500
+
+    sunrpc: gss: simplify rsi_parse logic
+    
+    Make an obvious simplification that removes a few lines and some
+    unnecessary indentation; no change in behavior.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
+index 688cc31040f3..e8ed848ecd67 100644
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -224,38 +224,34 @@ static int rsi_parse(struct cache_detail *cd,
+ 
+ 	/* major/minor */
+ 	len = qword_get(&mesg, buf, mlen);
+-	if (len < 0)
++	if (len <= 0)
+ 		goto out;
+-	if (len == 0) {
++	rsii.major_status = simple_strtoul(buf, &ep, 10);
++	if (*ep)
++		goto out;
++	len = qword_get(&mesg, buf, mlen);
++	if (len <= 0)
++		goto out;
++	rsii.minor_status = simple_strtoul(buf, &ep, 10);
++	if (*ep)
+ 		goto out;
+-	} else {
+-		rsii.major_status = simple_strtoul(buf, &ep, 10);
+-		if (*ep)
+-			goto out;
+-		len = qword_get(&mesg, buf, mlen);
+-		if (len <= 0)
+-			goto out;
+-		rsii.minor_status = simple_strtoul(buf, &ep, 10);
+-		if (*ep)
+-			goto out;
+ 
+-		/* out_handle */
+-		len = qword_get(&mesg, buf, mlen);
+-		if (len < 0)
+-			goto out;
+-		status = -ENOMEM;
+-		if (dup_to_netobj(&rsii.out_handle, buf, len))
+-			goto out;
++	/* out_handle */
++	len = qword_get(&mesg, buf, mlen);
++	if (len < 0)
++		goto out;
++	status = -ENOMEM;
++	if (dup_to_netobj(&rsii.out_handle, buf, len))
++		goto out;
+ 
+-		/* out_token */
+-		len = qword_get(&mesg, buf, mlen);
+-		status = -EINVAL;
+-		if (len < 0)
+-			goto out;
+-		status = -ENOMEM;
+-		if (dup_to_netobj(&rsii.out_token, buf, len))
+-			goto out;
+-	}
++	/* out_token */
++	len = qword_get(&mesg, buf, mlen);
++	status = -EINVAL;
++	if (len < 0)
++		goto out;
++	status = -ENOMEM;
++	if (dup_to_netobj(&rsii.out_token, buf, len))
++		goto out;
+ 	rsii.h.expiry_time = expiry;
+ 	rsip = rsi_update(&rsii, rsip);
+ 	status = 0;

commit 980e5a40a44400edc3f75b7931b8e75fcc3c21a3
+Author: J. Bruce Fields 
+Date:   Wed Dec 12 18:21:17 2007 -0500
+
+    nfsd: fix rsi_cache reference count leak
+    
+    For some reason we haven't been put()'ing the reference count here.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
+index aa790bb4f7a1..688cc31040f3 100644
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -975,6 +975,7 @@ static int svcauth_gss_handle_init(struct svc_rqst *rqstp,
+ 	struct kvec *resv = &rqstp->rq_res.head[0];
+ 	struct xdr_netobj tmpobj;
+ 	struct rsi *rsip, rsikey;
++	int ret;
+ 
+ 	/* Read the verifier; should be NULL: */
+ 	*authp = rpc_autherr_badverf;
+@@ -1014,23 +1015,27 @@ static int svcauth_gss_handle_init(struct svc_rqst *rqstp,
+ 		/* No upcall result: */
+ 		return SVC_DROP;
+ 	case 0:
++		ret = SVC_DROP;
+ 		/* Got an answer to the upcall; use it: */
+ 		if (gss_write_init_verf(rqstp, rsip))
+-			return SVC_DROP;
++			goto out;
+ 		if (resv->iov_len + 4 > PAGE_SIZE)
+-			return SVC_DROP;
++			goto out;
+ 		svc_putnl(resv, RPC_SUCCESS);
+ 		if (svc_safe_putnetobj(resv, &rsip->out_handle))
+-			return SVC_DROP;
++			goto out;
+ 		if (resv->iov_len + 3 * 4 > PAGE_SIZE)
+-			return SVC_DROP;
++			goto out;
+ 		svc_putnl(resv, rsip->major_status);
+ 		svc_putnl(resv, rsip->minor_status);
+ 		svc_putnl(resv, GSS_SEQ_WIN);
+ 		if (svc_safe_putnetobj(resv, &rsip->out_token))
+-			return SVC_DROP;
++			goto out;
+ 	}
+-	return SVC_COMPLETE;
++	ret = SVC_COMPLETE;
++out:
++	cache_put(&rsip->h, &rsi_cache);
++	return ret;
+ }
+ 
+ /*

commit 5c002b3bb294a637312cab7ad92a0deafa05a758
+Author: J. Bruce Fields 
+Date:   Fri Nov 30 16:55:23 2007 -0500
+
+    nfsd: allow root to set uid and gid on create
+    
+    The server silently ignores attempts to set the uid and gid on create.
+    Based on the comment, this appears to have been done to prevent some
+    overly-clever IRIX client from causing itself problems.
+    
+    Perhaps we should remove that hack completely.  For now, at least, it
+    makes sense to allow root (when no_root_squash is set) to set uid and
+    gid.
+    
+    While we're there, since nfsd_create and nfsd_create_v3 share the same
+    logic, pull that out into a separate function.  And spell out the
+    individual modifications of ia_valid instead of doing them both at once
+    inside a conditional.
+    
+    Thanks to Roger Willcocks  for the bug report
+    and original patch on which this is based.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index 755ba43c13e1..cc75e4fcd02b 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -1151,6 +1151,26 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ }
+ #endif /* CONFIG_NFSD_V3 */
+ 
++__be32
++nfsd_create_setattr(struct svc_rqst *rqstp, struct svc_fh *resfhp,
++			struct iattr *iap)
++{
++	/*
++	 * Mode has already been set earlier in create:
++	 */
++	iap->ia_valid &= ~ATTR_MODE;
++	/*
++	 * Setting uid/gid works only for root.  Irix appears to
++	 * send along the gid on create when it tries to implement
++	 * setgid directories via NFS:
++	 */
++	if (current->fsuid != 0)
++		iap->ia_valid &= ~(ATTR_UID|ATTR_GID);
++	if (iap->ia_valid)
++		return nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
++	return 0;
++}
++
+ /*
+  * Create a file (regular, directory, device, fifo); UNIX sockets 
+  * not yet implemented.
+@@ -1167,6 +1187,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ 	struct dentry	*dentry, *dchild = NULL;
+ 	struct inode	*dirp;
+ 	__be32		err;
++	__be32		err2;
+ 	int		host_err;
+ 
+ 	err = nfserr_perm;
+@@ -1257,16 +1278,9 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ 	}
+ 
+ 
+-	/* Set file attributes. Mode has already been set and
+-	 * setting uid/gid works only for root. Irix appears to
+-	 * send along the gid when it tries to implement setgid
+-	 * directories via NFS.
+-	 */
+-	if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) {
+-		__be32 err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
+-		if (err2)
+-			err = err2;
+-	}
++	err2 = nfsd_create_setattr(rqstp, resfhp, iap);
++	if (err2)
++		err = err2;
+ 	/*
+ 	 * Update the file handle to get the new inode info.
+ 	 */
+@@ -1295,6 +1309,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ 	struct dentry	*dentry, *dchild = NULL;
+ 	struct inode	*dirp;
+ 	__be32		err;
++	__be32		err2;
+ 	int		host_err;
+ 	__u32		v_mtime=0, v_atime=0;
+ 
+@@ -1399,16 +1414,10 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ 		iap->ia_atime.tv_nsec = 0;
+ 	}
+ 
+-	/* Set file attributes.
+-	 * Irix appears to send along the gid when it tries to
+-	 * implement setgid directories via NFS. Clear out all that cruft.
+-	 */
+  set_attr:
+-	if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) {
+- 		__be32 err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
+-		if (err2)
+-			err = err2;
+-	}
++	err2 = nfsd_create_setattr(rqstp, resfhp, iap);
++	if (err2)
++		err = err2;
+ 
+ 	/*
+ 	 * Update the filehandle to get the new inode info.

commit 39325bd03fc16d903f1e0f51104436d939899c8c
+Author: J. Bruce Fields 
+Date:   Mon Nov 26 17:06:39 2007 -0500
+
+    nfsd4: fix bad seqid on lock request incompatible with open mode
+    
+    The failure to return a stateowner from nfs4_preprocess_seqid_op() means
+    in the case where a lock request is of a type incompatible with an open
+    (due to, e.g., an application attempting a write lock on a file open for
+    read), means that fs/nfsd/nfs4xdr.c:ENCODE_SEQID_OP_TAIL() never bumps
+    the seqid as it should.  The client, attempting to close the file
+    afterwards, then gets an (incorrect) bad sequence id error.  Worse, this
+    prevents the open file from ever being closed, so we leak state.
+    
+    Thanks to Benny Halevy and Trond Myklebust for analysis, and to Steven
+    Wilton for the report and extensive data-gathering.
+    
+    Cc: Benny Halevy 
+    Cc: Steven Wilton 
+    Cc: Trond Myklebust 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 11aa4b6b4fa2..c4b10a1e6c30 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2093,8 +2093,10 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
+ 		goto check_replay;
+ 	}
+ 
++	*stpp = stp;
++	*sopp = sop = stp->st_stateowner;
++
+ 	if (lock) {
+-		struct nfs4_stateowner *sop = stp->st_stateowner;
+ 		clientid_t *lockclid = &lock->v.new.clientid;
+ 		struct nfs4_client *clp = sop->so_client;
+ 		int lkflg = 0;
+@@ -2124,9 +2126,6 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
+ 		return nfserr_bad_stateid;
+ 	}
+ 
+-	*stpp = stp;
+-	*sopp = sop = stp->st_stateowner;
+-
+ 	/*
+ 	*  We now validate the seqid and stateid generation numbers.
+ 	*  For the moment, we ignore the possibility of 

commit 404ec117be5d36e1a4c4582d0c518594333e32df
+Author: J. Bruce Fields 
+Date:   Fri Nov 23 22:26:18 2007 -0500
+
+    nfsd4: recognize callback channel failure earlier
+    
+    When the callback channel fails, we inform the client of that by
+    returning a cb_path_down error the next time it tries to renew its
+    lease.
+    
+    If we wait most of a lease period before deciding that a callback has
+    failed and that the callback channel is down, then we decrease the
+    chances that the client will find out in time to do anything about it.
+    
+    So, mark the channel down as soon as we recognize that an rpc has
+    failed.  However, continue trying to recall delegations anyway, in hopes
+    it will come back up.  This will prevent more delegations from being
+    given out, and ensure cb_path_down is returned to renew calls earlier,
+    while still making the best effort to deliver recalls of existing
+    delegations.
+    
+    Also fix a couple comments and remove a dprink that doesn't seem likely
+    to be useful.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 6eb5cd2381ab..aae2b29ae2c9 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -457,9 +457,6 @@ nfsd4_cb_recall(struct nfs4_delegation *dp)
+ 	int retries = 1;
+ 	int status = 0;
+ 
+-	if ((!atomic_read(&clp->cl_callback.cb_set)) || !clnt)
+-		return;
+-
+ 	cbr->cbr_trunc = 0; /* XXX need to implement truncate optimization */
+ 	cbr->cbr_dp = dp;
+ 
+@@ -468,6 +465,7 @@ nfsd4_cb_recall(struct nfs4_delegation *dp)
+ 		switch (status) {
+ 			case -EIO:
+ 				/* Network partition? */
++				atomic_set(&clp->cl_callback.cb_set, 0);
+ 			case -EBADHANDLE:
+ 			case -NFS4ERR_BAD_STATEID:
+ 				/* Race: client probably got cb_recall
+@@ -480,11 +478,10 @@ nfsd4_cb_recall(struct nfs4_delegation *dp)
+ 		status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT);
+ 	}
+ out_put_cred:
+-	if (status == -EIO)
+-		atomic_set(&clp->cl_callback.cb_set, 0);
+-	/* Success or failure, now we're either waiting for lease expiration
+-	 * or deleg_return. */
+-	dprintk("NFSD: nfs4_cb_recall: dp %p dl_flock %p dl_count %d\n",dp, dp->dl_flock, atomic_read(&dp->dl_count));
++	/*
++	 * Success or failure, now we're either waiting for lease expiration
++	 * or deleg_return.
++	 */
+ 	put_nfs4_client(clp);
+ 	nfs4_put_delegation(dp);
+ 	return;
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index b9d395856b3a..11aa4b6b4fa2 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -361,8 +361,11 @@ shutdown_callback_client(struct nfs4_client *clp)
+ {
+ 	struct rpc_clnt *clnt = clp->cl_callback.cb_client;
+ 
+-	/* shutdown rpc client, ending any outstanding recall rpcs */
+ 	if (clnt) {
++		/*
++		 * Callback threads take a reference on the client, so there
++		 * should be no outstanding callbacks at this point.
++		 */
+ 		clp->cl_callback.cb_client = NULL;
+ 		rpc_shutdown_client(clnt);
+ 	}

commit 35bba9a37e68c68a820a1a772f016255c0838f79
+Author: J. Bruce Fields 
+Date:   Wed Nov 21 22:07:08 2007 -0500
+
+    nfsd4: miscellaneous nfs4state.c style fixes
+    
+    Fix various minor style violations.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 78b9139cdd0f..b9d395856b3a 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -339,21 +339,20 @@ STALE_CLIENTID(clientid_t *clid)
+  * This type of memory management is somewhat inefficient, but we use it
+  * anyway since SETCLIENTID is not a common operation.
+  */
+-static inline struct nfs4_client *
+-alloc_client(struct xdr_netobj name)
++static struct nfs4_client *alloc_client(struct xdr_netobj name)
+ {
+ 	struct nfs4_client *clp;
+ 
+-	if ((clp = kzalloc(sizeof(struct nfs4_client), GFP_KERNEL))!= NULL) {
+-		if ((clp->cl_name.data = kmalloc(name.len, GFP_KERNEL)) != NULL) {
+-			memcpy(clp->cl_name.data, name.data, name.len);
+-			clp->cl_name.len = name.len;
+-		}
+-		else {
+-			kfree(clp);
+-			clp = NULL;
+-		}
++	clp = kzalloc(sizeof(struct nfs4_client), GFP_KERNEL);
++	if (clp == NULL)
++		return NULL;
++	clp->cl_name.data = kmalloc(name.len, GFP_KERNEL);
++	if (clp->cl_name.data == NULL) {
++		kfree(clp);
++		return NULL;
+ 	}
++	memcpy(clp->cl_name.data, name.data, name.len);
++	clp->cl_name.len = name.len;
+ 	return clp;
+ }
+ 
+@@ -421,12 +420,13 @@ expire_client(struct nfs4_client *clp)
+ 	put_nfs4_client(clp);
+ }
+ 
+-static struct nfs4_client *
+-create_client(struct xdr_netobj name, char *recdir) {
++static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir)
++{
+ 	struct nfs4_client *clp;
+ 
+-	if (!(clp = alloc_client(name)))
+-		goto out;
++	clp = alloc_client(name);
++	if (clp == NULL)
++		return NULL;
+ 	memcpy(clp->cl_recdir, recdir, HEXDIR_LEN);
+ 	atomic_set(&clp->cl_count, 1);
+ 	atomic_set(&clp->cl_callback.cb_set, 0);
+@@ -435,32 +435,30 @@ create_client(struct xdr_netobj name, char *recdir) {
+ 	INIT_LIST_HEAD(&clp->cl_openowners);
+ 	INIT_LIST_HEAD(&clp->cl_delegations);
+ 	INIT_LIST_HEAD(&clp->cl_lru);
+-out:
+ 	return clp;
+ }
+ 
+-static void
+-copy_verf(struct nfs4_client *target, nfs4_verifier *source) {
+-	memcpy(target->cl_verifier.data, source->data, sizeof(target->cl_verifier.data));
++static void copy_verf(struct nfs4_client *target, nfs4_verifier *source)
++{
++	memcpy(target->cl_verifier.data, source->data,
++			sizeof(target->cl_verifier.data));
+ }
+ 
+-static void
+-copy_clid(struct nfs4_client *target, struct nfs4_client *source) {
++static void copy_clid(struct nfs4_client *target, struct nfs4_client *source)
++{
+ 	target->cl_clientid.cl_boot = source->cl_clientid.cl_boot; 
+ 	target->cl_clientid.cl_id = source->cl_clientid.cl_id; 
+ }
+ 
+-static void
+-copy_cred(struct svc_cred *target, struct svc_cred *source) {
+-
++static void copy_cred(struct svc_cred *target, struct svc_cred *source)
++{
+ 	target->cr_uid = source->cr_uid;
+ 	target->cr_gid = source->cr_gid;
+ 	target->cr_group_info = source->cr_group_info;
+ 	get_group_info(target->cr_group_info);
+ }
+ 
+-static inline int
+-same_name(const char *n1, const char *n2)
++static int same_name(const char *n1, const char *n2)
+ {
+ 	return 0 == memcmp(n1, n2, HEXDIR_LEN);
+ }
+@@ -502,9 +500,8 @@ static void gen_confirm(struct nfs4_client *clp)
+ 	*p++ = i++;
+ }
+ 
+-static int
+-check_name(struct xdr_netobj name) {
+-
++static int check_name(struct xdr_netobj name)
++{
+ 	if (name.len == 0) 
+ 		return 0;
+ 	if (name.len > NFS4_OPAQUE_LIMIT) {

commit 5ec7b46c2f4a6f5e136188d598a3f9912ca922e9
+Author: J. Bruce Fields 
+Date:   Wed Nov 21 21:58:56 2007 -0500
+
+    nfsd4: make current_clientid local
+    
+    Declare this variable in the one function where it's used, and clean up
+    some minor style problems.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 60cc937b7076..78b9139cdd0f 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -61,7 +61,6 @@ static time_t lease_time = 90;     /* default lease time */
+ static time_t user_lease_time = 90;
+ static time_t boot_time;
+ static int in_grace = 1;
+-static u32 current_clientid = 1;
+ static u32 current_ownerid = 1;
+ static u32 current_fileid = 1;
+ static u32 current_delegid = 1;
+@@ -485,8 +484,10 @@ same_creds(struct svc_cred *cr1, struct svc_cred *cr2)
+ 	return cr1->cr_uid == cr2->cr_uid;
+ }
+ 
+-static void
+-gen_clid(struct nfs4_client *clp) {
++static void gen_clid(struct nfs4_client *clp)
++{
++	static u32 current_clientid = 1;
++
+ 	clp->cl_clientid.cl_boot = boot_time;
+ 	clp->cl_clientid.cl_id = current_clientid++; 
+ }

commit 99d965eda736b839a63fe85438ee03a0f660053c
+Author: J. Bruce Fields 
+Date:   Wed Nov 21 14:10:07 2007 -0500
+
+    nfsd: fix encode_entryplus_baggage() indentation
+    
+    Fix bizarre indentation.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
+index 4b1ffe3be7e2..d7647f70e02b 100644
+--- a/fs/nfsd/nfs3xdr.c
++++ b/fs/nfsd/nfs3xdr.c
+@@ -817,11 +817,11 @@ static __be32 *
+ encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p,
+ 		struct svc_fh *fhp)
+ {
+-		p = encode_post_op_attr(cd->rqstp, p, fhp);
+-		*p++ = xdr_one;			/* yes, a file handle follows */
+-		p = encode_fh(p, fhp);
+-		fh_put(fhp);
+-		return p;
++	p = encode_post_op_attr(cd->rqstp, p, fhp);
++	*p++ = xdr_one;			/* yes, a file handle follows */
++	p = encode_fh(p, fhp);
++	fh_put(fhp);
++	return p;
+ }
+ 
+ static int

commit 366e0c1d9116ed03320779ecf9c162204f4c712e
+Author: J. Bruce Fields 
+Date:   Tue Nov 20 15:54:10 2007 -0500
+
+    nfsd4: kill unneeded cl_confirm check
+    
+    We generate a unique cl_confirm for every new client; so if we've
+    already checked that this cl_confirm agrees with the cl_confirm of
+    unconf, then we already know that it does not agree with the cl_confirm
+    of conf.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 23b5fc71f9fb..60cc937b7076 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -835,9 +835,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+ 	 * SETCLIENTID_CONFIRM request processing consisting
+ 	 * of 4 bullet points, labeled as CASE1 - CASE4 below.
+ 	 */
+-	if ((conf && unconf) && 
+-	    (same_verf(&unconf->cl_confirm, &confirm)) &&
+-	    (!same_verf(&conf->cl_confirm, &unconf->cl_confirm))) {
++	if (conf && unconf && same_verf(&confirm, &unconf->cl_confirm)) {
+ 		/*
+ 		 * RFC 3530 14.2.34 CASE 1:
+ 		 * callback update

commit f3aba4e5a1b963c8bd43394cb15fb9fb6a229cd2
+Author: J. Bruce Fields 
+Date:   Tue Nov 20 16:52:07 2007 -0500
+
+    nfsd4: remove unnecessary cl_verifier check from setclientid_confirm
+    
+    Again, the only way conf and unconf can have the same clientid is if
+    they were created in the "probable callback update" case of setclientid,
+    in which case we already know that the cl_verifier fields must agree.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index df3e7a7ad31e..23b5fc71f9fb 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -837,7 +837,6 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+ 	 */
+ 	if ((conf && unconf) && 
+ 	    (same_verf(&unconf->cl_confirm, &confirm)) &&
+-	    (same_verf(&conf->cl_verifier, &unconf->cl_verifier)) &&
+ 	    (!same_verf(&conf->cl_confirm, &unconf->cl_confirm))) {
+ 		/*
+ 		 * RFC 3530 14.2.34 CASE 1:
+@@ -855,9 +854,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+ 			status = nfs_ok;
+ 
+ 		}
+-	} else if ((conf && !unconf) ||
+-	    ((conf && unconf) && 
+-	     !same_verf(&conf->cl_verifier, &unconf->cl_verifier))) {
++	} else if (conf && !unconf) {
+ 		/*
+ 		 * RFC 3530 14.2.34 CASE 2:
+ 		 * probable retransmitted request; play it safe and

commit f394baad139f8a67a40b4246d53d3b818af2eb88
+Author: J. Bruce Fields 
+Date:   Tue Nov 20 15:39:07 2007 -0500
+
+    nfsd4: kill unnecessary same_name() in setclientid_confirm
+    
+    If conf and unconf are both found in the lookup by cl_clientid, then
+    they share the same cl_clientid.  We always create a unique new
+    cl_clientid field when creating a new client--the only exception is the
+    "probable callback update" case in setclientid, where we copy the old
+    cl_clientid from another clientid with the same name.
+    
+    Therefore two clients with the same cl_client field also always share
+    the same cl_name field, and a couple of the checks here are redundant.
+    
+    Thanks to Simon Holm Thøgersen for a compile fix.
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: Simon Holm Thøgersen 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 9f6322e830fa..df3e7a7ad31e 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -838,7 +838,6 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+ 	if ((conf && unconf) && 
+ 	    (same_verf(&unconf->cl_confirm, &confirm)) &&
+ 	    (same_verf(&conf->cl_verifier, &unconf->cl_verifier)) &&
+-	    (same_name(conf->cl_recdir,unconf->cl_recdir))  &&
+ 	    (!same_verf(&conf->cl_confirm, &unconf->cl_confirm))) {
+ 		/*
+ 		 * RFC 3530 14.2.34 CASE 1:
+@@ -858,8 +857,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+ 		}
+ 	} else if ((conf && !unconf) ||
+ 	    ((conf && unconf) && 
+-	     (!same_verf(&conf->cl_verifier, &unconf->cl_verifier) ||
+-	      !same_name(conf->cl_recdir, unconf->cl_recdir)))) {
++	     !same_verf(&conf->cl_verifier, &unconf->cl_verifier))) {
+ 		/*
+ 		 * RFC 3530 14.2.34 CASE 2:
+ 		 * probable retransmitted request; play it safe and

commit deda2faa8e71474c828d8eefc8bc0f19d02062ef
+Author: J. Bruce Fields 
+Date:   Mon Nov 19 20:31:04 2007 -0500
+
+    nfsd: uniquify cl_confirm values
+    
+    Using a counter instead of the nanoseconds value seems more likely to
+    produce a unique cl_confirm.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 035e70a01027..9f6322e830fa 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -491,15 +491,14 @@ gen_clid(struct nfs4_client *clp) {
+ 	clp->cl_clientid.cl_id = current_clientid++; 
+ }
+ 
+-static void
+-gen_confirm(struct nfs4_client *clp) {
+-	struct timespec 	tv;
+-	u32 *			p;
++static void gen_confirm(struct nfs4_client *clp)
++{
++	static u32 i;
++	u32 *p;
+ 
+-	tv = CURRENT_TIME;
+ 	p = (u32 *)clp->cl_confirm.data;
+-	*p++ = tv.tv_sec;
+-	*p++ = tv.tv_nsec;
++	*p++ = get_seconds();
++	*p++ = i++;
+ }
+ 
+ static int

commit 49ba87811f34a0219dc7a373cd24aa68450f2058
+Author: J. Bruce Fields 
+Date:   Mon Nov 19 19:09:50 2007 -0500
+
+    nfsd: eliminate final bogus case from setclientid logic
+    
+    We're supposed to generate a different cl_confirm verifier for each new
+    client, so these to cl_confirm values should never be the same.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 242fee7c1018..035e70a01027 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -769,7 +769,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 		if (new == NULL)
+ 			goto out;
+ 		gen_clid(new);
+-	} else if (!same_verf(&conf->cl_confirm, &unconf->cl_confirm)) {
++	} else {
+ 		/*
+ 		 * RFC 3530 14.2.33 CASE 3:
+ 		 * probable client reboot; state will be removed if
+@@ -780,11 +780,6 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 		if (new == NULL)
+ 			goto out;
+ 		gen_clid(new);
+-	} else {
+-		/* No cases hit !!! */
+-		status = nfserr_inval;
+-		goto out;
+-
+ 	}
+ 	copy_verf(new, &clverifier);
+ 	new->cl_addr = sin->sin_addr.s_addr;

commit a186e767473bd329122f0229b91573b9b6fa43c1
+Author: J. Bruce Fields 
+Date:   Tue Nov 20 16:11:27 2007 -0500
+
+    nfsd4: kill some unneeded setclientid comments
+    
+    Most of these comments just summarize the code.
+    
+    The matching of code to the cases described in the RFC may still be
+    useful, though; add specific section references to make that easier to
+    follow.  Also update references to the outdated RFC 3010.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 9d81c7117ae6..242fee7c1018 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -683,39 +683,6 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
+ 	return;
+ }
+ 
+-/*
+- * RFC 3010 has a complex implmentation description of processing a 
+- * SETCLIENTID request consisting of 5 bullets, labeled as 
+- * CASE0 - CASE4 below.
+- *
+- * NOTES:
+- * 	callback information will be processed in a future patch
+- *
+- *	an unconfirmed record is added when:
+- *      NORMAL (part of CASE 4): there is no confirmed nor unconfirmed record.
+- *	CASE 1: confirmed record found with matching name, principal,
+- *		verifier, and clientid.
+- *	CASE 2: confirmed record found with matching name, principal,
+- *		and there is no unconfirmed record with matching
+- *		name and principal
+- *
+- *      an unconfirmed record is replaced when:
+- *	CASE 3: confirmed record found with matching name, principal,
+- *		and an unconfirmed record is found with matching 
+- *		name, principal, and with clientid and
+- *		confirm that does not match the confirmed record.
+- *	CASE 4: there is no confirmed record with matching name and 
+- *		principal. there is an unconfirmed record with 
+- *		matching name, principal.
+- *
+- *	an unconfirmed record is deleted when:
+- *	CASE 1: an unconfirmed record that matches input name, verifier,
+- *		and confirmed clientid.
+- *	CASE 4: any unconfirmed records with matching name and principal
+- *		that exist after an unconfirmed record has been replaced
+- *		as described above.
+- *
+- */
+ __be32
+ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 		  struct nfsd4_setclientid *setclid)
+@@ -748,11 +715,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	nfs4_lock_state();
+ 	conf = find_confirmed_client_by_str(dname, strhashval);
+ 	if (conf) {
+-		/* 
+-		 * CASE 0:
+-		 * clname match, confirmed, different principal
+-		 * or different ip_address
+-		 */
++		/* RFC 3530 14.2.33 CASE 0: */
+ 		status = nfserr_clid_inuse;
+ 		if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)
+ 				|| conf->cl_addr != sin->sin_addr.s_addr) {
+@@ -761,12 +724,17 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 			goto out;
+ 		}
+ 	}
++	/*
++	 * section 14.2.33 of RFC 3530 (under the heading "IMPLEMENTATION")
++	 * has a description of SETCLIENTID request processing consisting
++	 * of 5 bullet points, labeled as CASE0 - CASE4 below.
++	 */
+ 	unconf = find_unconfirmed_client_by_str(dname, strhashval);
+ 	status = nfserr_resource;
+ 	if (!conf) {
+-		/* 
+-		 * CASE 4:
+-		 * placed first, because it is the normal case.
++		/*
++		 * RFC 3530 14.2.33 CASE 4:
++		 * placed first, because it is the normal case
+ 		 */
+ 		if (unconf)
+ 			expire_client(unconf);
+@@ -776,17 +744,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 		gen_clid(new);
+ 	} else if (same_verf(&conf->cl_verifier, &clverifier)) {
+ 		/*
+-		 * CASE 1:
+-		 * cl_name match, confirmed, principal match
+-		 * verifier match: probable callback update
+-		 *
+-		 * remove any unconfirmed nfs4_client with 
+-		 * matching cl_name, cl_verifier, and cl_clientid
+-		 *
+-		 * create and insert an unconfirmed nfs4_client with same 
+-		 * cl_name, cl_verifier, and cl_clientid as existing 
+-		 * nfs4_client,  but with the new callback info and a 
+-		 * new cl_confirm
++		 * RFC 3530 14.2.33 CASE 1:
++		 * probable callback update
+ 		 */
+ 		if (unconf) {
+ 			/* Note this is removing unconfirmed {*x***},
+@@ -802,32 +761,19 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 		copy_clid(new, conf);
+ 	} else if (!unconf) {
+ 		/*
+-		 * CASE 2:
+-		 * clname match, confirmed, principal match
+-		 * verfier does not match
+-		 * no unconfirmed. create a new unconfirmed nfs4_client
+-		 * using input clverifier, clname, and callback info
+-		 * and generate a new cl_clientid and cl_confirm.
++		 * RFC 3530 14.2.33 CASE 2:
++		 * probable client reboot; state will be removed if
++		 * confirmed.
+ 		 */
+ 		new = create_client(clname, dname);
+ 		if (new == NULL)
+ 			goto out;
+ 		gen_clid(new);
+ 	} else if (!same_verf(&conf->cl_confirm, &unconf->cl_confirm)) {
+-		/*	
+-		 * CASE3:
+-		 * confirmed found (name, principal match)
+-		 * confirmed verifier does not match input clverifier
+-		 *
+-		 * unconfirmed found (name match)
+-		 * confirmed->cl_confirm != unconfirmed->cl_confirm
+-		 *
+-		 * remove unconfirmed.
+-		 *
+-		 * create an unconfirmed nfs4_client 
+-		 * with same cl_name as existing confirmed nfs4_client, 
+-		 * but with new callback info, new cl_clientid,
+-		 * new cl_verifier and a new cl_confirm
++		/*
++		 * RFC 3530 14.2.33 CASE 3:
++		 * probable client reboot; state will be removed if
++		 * confirmed.
+ 		 */
+ 		expire_client(unconf);
+ 		new = create_client(clname, dname);
+@@ -857,11 +803,9 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 
+ 
+ /*
+- * RFC 3010 has a complex implmentation description of processing a 
+- * SETCLIENTID_CONFIRM request consisting of 4 bullets describing
+- * processing on a DRC miss, labeled as CASE1 - CASE4 below.
+- *
+- * NOTE: callback information will be processed here in a future patch
++ * Section 14.2.34 of RFC 3530 (under the heading "IMPLEMENTATION") has
++ * a description of SETCLIENTID_CONFIRM request processing consisting of 4
++ * bullets, labeled as CASE1 - CASE4 below.
+  */
+ __be32
+ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+@@ -892,16 +836,20 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+ 	if (unconf && unconf->cl_addr != sin->sin_addr.s_addr)
+ 		goto out;
+ 
++	/*
++	 * section 14.2.34 of RFC 3530 has a description of
++	 * SETCLIENTID_CONFIRM request processing consisting
++	 * of 4 bullet points, labeled as CASE1 - CASE4 below.
++	 */
+ 	if ((conf && unconf) && 
+ 	    (same_verf(&unconf->cl_confirm, &confirm)) &&
+ 	    (same_verf(&conf->cl_verifier, &unconf->cl_verifier)) &&
+ 	    (same_name(conf->cl_recdir,unconf->cl_recdir))  &&
+ 	    (!same_verf(&conf->cl_confirm, &unconf->cl_confirm))) {
+-		/* CASE 1:
+-		* unconf record that matches input clientid and input confirm.
+-		* conf record that matches input clientid.
+-		* conf and unconf records match names, verifiers
+-		*/
++		/*
++		 * RFC 3530 14.2.34 CASE 1:
++		 * callback update
++		 */
+ 		if (!same_creds(&conf->cl_cred, &unconf->cl_cred))
+ 			status = nfserr_clid_inuse;
+ 		else {
+@@ -918,11 +866,10 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+ 	    ((conf && unconf) && 
+ 	     (!same_verf(&conf->cl_verifier, &unconf->cl_verifier) ||
+ 	      !same_name(conf->cl_recdir, unconf->cl_recdir)))) {
+-		/* CASE 2:
+-		 * conf record that matches input clientid.
+-		 * if unconf record matches input clientid, then
+-		 * unconf->cl_name or unconf->cl_verifier don't match the
+-		 * conf record.
++		/*
++		 * RFC 3530 14.2.34 CASE 2:
++		 * probable retransmitted request; play it safe and
++		 * do nothing.
+ 		 */
+ 		if (!same_creds(&conf->cl_cred, &rqstp->rq_cred))
+ 			status = nfserr_clid_inuse;
+@@ -930,10 +877,9 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+ 			status = nfs_ok;
+ 	} else if (!conf && unconf
+ 			&& same_verf(&unconf->cl_confirm, &confirm)) {
+-		/* CASE 3:
+-		 * conf record not found.
+-		 * unconf record found.
+-		 * unconf->cl_confirm matches input confirm
++		/*
++		 * RFC 3530 14.2.34 CASE 3:
++		 * Normal case; new or rebooted client:
+ 		 */
+ 		if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred)) {
+ 			status = nfserr_clid_inuse;
+@@ -954,11 +900,9 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+ 	} else if ((!conf || (conf && !same_verf(&conf->cl_confirm, &confirm)))
+ 	    && (!unconf || (unconf && !same_verf(&unconf->cl_confirm,
+ 				    				&confirm)))) {
+-		/* CASE 4:
+-		 * conf record not found, or if conf, conf->cl_confirm does not
+-		 * match input confirm.
+-		 * unconf record not found, or if unconf, unconf->cl_confirm
+-		 * does not match input confirm.
++		/*
++		 * RFC 3530 14.2.34 CASE 4:
++		 * Client probably hasn't noticed that we rebooted yet.
+ 		 */
+ 		status = nfserr_stale_clientid;
+ 	} else {

commit 1f69f172c73a2bf0bf55da9346da8dccea9035cf
+Author: J. Bruce Fields 
+Date:   Thu Nov 15 17:06:58 2007 -0500
+
+    nfsd: minor fs/nfsd/auth.h cleanup
+    
+    While we're here, let's remove the redundant (and now wrong) pathname in
+    the comment, and the #ifdef __KERNEL__'s.
+    
+    Acked-by: NeilBrown 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/auth.h b/fs/nfsd/auth.h
+index 0fb9f7212195..78b3c0e93822 100644
+--- a/fs/nfsd/auth.h
++++ b/fs/nfsd/auth.h
+@@ -1,6 +1,4 @@
+ /*
+- * include/linux/nfsd/auth.h
+- *
+  * nfsd-specific authentication stuff.
+  * uid/gid mapping not yet implemented.
+  *
+@@ -10,8 +8,6 @@
+ #ifndef LINUX_NFSD_AUTH_H
+ #define LINUX_NFSD_AUTH_H
+ 
+-#ifdef __KERNEL__
+-
+ #define nfsd_luid(rq, uid)	((u32)(uid))
+ #define nfsd_lgid(rq, gid)	((u32)(gid))
+ #define nfsd_ruid(rq, uid)	((u32)(uid))
+@@ -23,5 +19,4 @@
+  */
+ int nfsd_setuser(struct svc_rqst *, struct svc_export *);
+ 
+-#endif /* __KERNEL__ */
+ #endif /* LINUX_NFSD_AUTH_H */

commit 2e8138a274d81d87591db0803b1e81f4284ff935
+Author: J. Bruce Fields 
+Date:   Thu Nov 15 17:05:43 2007 -0500
+
+    nfsd: move nfsd/auth.h into fs/nfsd
+    
+    This header is used only in a few places in fs/nfsd, so there seems to
+    be little point to having it in include/.  (Thanks to Robert Day for
+    pointing this out.)
+    
+    Cc: Robert P. J. Day 
+    Acked-by: NeilBrown 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/include/linux/nfsd/auth.h b/fs/nfsd/auth.h
+similarity index 100%
+rename from include/linux/nfsd/auth.h
+rename to fs/nfsd/auth.h
+diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
+index be515c5a8154..4b1ffe3be7e2 100644
+--- a/fs/nfsd/nfs3xdr.c
++++ b/fs/nfsd/nfs3xdr.c
+@@ -21,6 +21,7 @@
+ #include 
+ #include 
+ #include 
++#include "auth.h"
+ 
+ #define NFSDDBG_FACILITY		NFSDDBG_XDR
+ 
+diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
+index 468f17a78441..8fbd2dc08a92 100644
+--- a/fs/nfsd/nfsfh.c
++++ b/fs/nfsd/nfsfh.c
+@@ -22,6 +22,7 @@
+ #include 
+ #include 
+ #include 
++#include "auth.h"
+ 
+ #define NFSDDBG_FACILITY		NFSDDBG_FH
+ 
+diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
+index 7003c313272f..61ad61743d94 100644
+--- a/fs/nfsd/nfsxdr.c
++++ b/fs/nfsd/nfsxdr.c
+@@ -15,6 +15,7 @@
+ #include 
+ #include 
+ #include 
++#include "auth.h"
+ 
+ #define NFSDDBG_FACILITY		NFSDDBG_XDR
+ 
+diff --git a/include/linux/nfsd/Kbuild b/include/linux/nfsd/Kbuild
+index d9c5455808e5..e726fc3a4375 100644
+--- a/include/linux/nfsd/Kbuild
++++ b/include/linux/nfsd/Kbuild
+@@ -4,4 +4,3 @@ unifdef-y += stats.h
+ unifdef-y += syscall.h
+ unifdef-y += nfsfh.h
+ unifdef-y += debug.h
+-unifdef-y += auth.h
+diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
+index a51a30f30cee..8caf4c4f64e6 100644
+--- a/include/linux/nfsd/nfsd.h
++++ b/include/linux/nfsd/nfsd.h
+@@ -20,7 +20,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ #include 
+ /*
+  * nfsd version
+diff --git a/include/linux/nfsd/syscall.h b/include/linux/nfsd/syscall.h
+index 8bcddccb6c42..4e439765b705 100644
+--- a/include/linux/nfsd/syscall.h
++++ b/include/linux/nfsd/syscall.h
+@@ -18,7 +18,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ 
+ /*
+  * Version of the syscall interface

commit dbf847ecb6318d3a22c6758fe39696d00f39063a
+Author: J. Bruce Fields 
+Date:   Thu Nov 8 17:20:34 2007 -0500
+
+    knfsd: allow cache_register to return error on failure
+    
+    Newer server features such as nfsv4 and gss depend on proc to work, so a
+    failure to initialize the proc files they need should be treated as
+    fatal.
+    
+    Thanks to Andrew Morton for style fix and compile fix in case where
+    CONFIG_NFSD_V4 is undefined.
+    
+    Cc: Andrew Morton 
+    Acked-by: NeilBrown 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
+index d29b70a28f2b..cbbc594ef592 100644
+--- a/fs/nfsd/export.c
++++ b/fs/nfsd/export.c
+@@ -1637,13 +1637,19 @@ exp_verify_string(char *cp, int max)
+ /*
+  * Initialize the exports module.
+  */
+-void
++int
+ nfsd_export_init(void)
+ {
++	int rv;
+ 	dprintk("nfsd: initializing export module.\n");
+ 
+-	cache_register(&svc_export_cache);
+-	cache_register(&svc_expkey_cache);
++	rv = cache_register(&svc_export_cache);
++	if (rv)
++		return rv;
++	rv = cache_register(&svc_expkey_cache);
++	if (rv)
++		cache_unregister(&svc_export_cache);
++	return rv;
+ 
+ }
+ 
+diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
+index ef22179c49ad..996bd88b75ba 100644
+--- a/fs/nfsd/nfs4idmap.c
++++ b/fs/nfsd/nfs4idmap.c
+@@ -464,11 +464,18 @@ nametoid_update(struct ent *new, struct ent *old)
+  * Exported API
+  */
+ 
+-void
++int
+ nfsd_idmap_init(void)
+ {
+-	cache_register(&idtoname_cache);
+-	cache_register(&nametoid_cache);
++	int rv;
++
++	rv = cache_register(&idtoname_cache);
++	if (rv)
++		return rv;
++	rv = cache_register(&nametoid_cache);
++	if (rv)
++		cache_unregister(&idtoname_cache);
++	return rv;
+ }
+ 
+ void
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index 2b95597aa4a5..4aba92698581 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -707,9 +707,13 @@ static int __init init_nfsd(void)
+ 	retval = nfsd_reply_cache_init();
+ 	if (retval)
+ 		goto out_free_stat;
+-	nfsd_export_init();	/* Exports table */
++	retval = nfsd_export_init();
++	if (retval)
++		goto out_free_cache;
+ 	nfsd_lockd_init();	/* lockd->nfsd callbacks */
+-	nfsd_idmap_init();      /* Name to ID mapping */
++	retval = nfsd_idmap_init();
++	if (retval)
++		goto out_free_lockd;
+ 	retval = create_proc_exports_entry();
+ 	if (retval)
+ 		goto out_free_idmap;
+@@ -720,10 +724,12 @@ static int __init init_nfsd(void)
+ out_free_all:
+ 	remove_proc_entry("fs/nfs/exports", NULL);
+ 	remove_proc_entry("fs/nfs", NULL);
+-	nfsd_idmap_shutdown();
+ out_free_idmap:
++	nfsd_idmap_shutdown();
++out_free_lockd:
+ 	nfsd_lockd_shutdown();
+ 	nfsd_export_shutdown();
++out_free_cache:
+ 	nfsd_reply_cache_shutdown();
+ out_free_stat:
+ 	nfsd_stat_shutdown();
+diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
+index bcb7abafbca9..3a1687251367 100644
+--- a/include/linux/nfsd/export.h
++++ b/include/linux/nfsd/export.h
+@@ -122,7 +122,7 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp);
+ /*
+  * Function declarations
+  */
+-void			nfsd_export_init(void);
++int			nfsd_export_init(void);
+ void			nfsd_export_shutdown(void);
+ void			nfsd_export_flush(void);
+ void			exp_readlock(void);
+diff --git a/include/linux/nfsd_idmap.h b/include/linux/nfsd_idmap.h
+index e82746fcad14..d4a2ac18bd4c 100644
+--- a/include/linux/nfsd_idmap.h
++++ b/include/linux/nfsd_idmap.h
+@@ -44,11 +44,16 @@
+ #define IDMAP_NAMESZ 128
+ 
+ #ifdef CONFIG_NFSD_V4
+-void nfsd_idmap_init(void);
++int nfsd_idmap_init(void);
+ void nfsd_idmap_shutdown(void);
+ #else
+-static inline void nfsd_idmap_init(void) {};
+-static inline void nfsd_idmap_shutdown(void) {};
++static inline int nfsd_idmap_init(void)
++{
++	return 0;
++}
++static inline void nfsd_idmap_shutdown(void)
++{
++}
+ #endif
+ 
+ int nfsd_map_name_to_uid(struct svc_rqst *, const char *, size_t, __u32 *);
+diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h
+index b683b5ddeea9..03547d6abee5 100644
+--- a/include/linux/sunrpc/cache.h
++++ b/include/linux/sunrpc/cache.h
+@@ -169,7 +169,7 @@ extern int cache_check(struct cache_detail *detail,
+ extern void cache_flush(void);
+ extern void cache_purge(struct cache_detail *detail);
+ #define NEVER (0x7FFFFFFF)
+-extern void cache_register(struct cache_detail *cd);
++extern int cache_register(struct cache_detail *cd);
+ extern void cache_unregister(struct cache_detail *cd);
+ 
+ extern void qword_add(char **bpp, int *lp, char *str);
+diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
+index d329a12500aa..aa790bb4f7a1 100644
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -1386,10 +1386,19 @@ int
+ gss_svc_init(void)
+ {
+ 	int rv = svc_auth_register(RPC_AUTH_GSS, &svcauthops_gss);
+-	if (rv == 0) {
+-		cache_register(&rsc_cache);
+-		cache_register(&rsi_cache);
+-	}
++	if (rv)
++		return rv;
++	rv = cache_register(&rsc_cache);
++	if (rv)
++		goto out1;
++	rv = cache_register(&rsi_cache);
++	if (rv)
++		goto out2;
++	return 0;
++out2:
++	cache_unregister(&rsc_cache);
++out1:
++	svc_auth_unregister(RPC_AUTH_GSS);
+ 	return rv;
+ }
+ 
+diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
+index f41a7cc4cf62..50b1a8b441fe 100644
+--- a/net/sunrpc/cache.c
++++ b/net/sunrpc/cache.c
+@@ -304,20 +304,21 @@ static void remove_cache_proc_entries(struct cache_detail *cd)
+ 	remove_proc_entry(cd->name, proc_net_rpc);
+ }
+ 
+-static void create_cache_proc_entries(struct cache_detail *cd)
++#ifdef CONFIG_PROC_FS
++static int create_cache_proc_entries(struct cache_detail *cd)
+ {
+ 	struct proc_dir_entry *p;
+ 
+ 	cd->proc_ent = proc_mkdir(cd->name, proc_net_rpc);
+ 	if (cd->proc_ent == NULL)
+-		return;
++		goto out_nomem;
+ 	cd->proc_ent->owner = cd->owner;
+ 	cd->channel_ent = cd->content_ent = NULL;
+ 
+ 	p = create_proc_entry("flush", S_IFREG|S_IRUSR|S_IWUSR, cd->proc_ent);
+ 	cd->flush_ent = p;
+ 	if (p == NULL)
+-		return;
++		goto out_nomem;
+ 	p->proc_fops = &cache_flush_operations;
+ 	p->owner = cd->owner;
+ 	p->data = cd;
+@@ -327,7 +328,7 @@ static void create_cache_proc_entries(struct cache_detail *cd)
+ 				      cd->proc_ent);
+ 		cd->channel_ent = p;
+ 		if (p == NULL)
+-			return;
++			goto out_nomem;
+ 		p->proc_fops = &cache_file_operations;
+ 		p->owner = cd->owner;
+ 		p->data = cd;
+@@ -337,16 +338,30 @@ static void create_cache_proc_entries(struct cache_detail *cd)
+ 				      cd->proc_ent);
+ 		cd->content_ent = p;
+ 		if (p == NULL)
+-			return;
++			goto out_nomem;
+ 		p->proc_fops = &content_file_operations;
+ 		p->owner = cd->owner;
+ 		p->data = cd;
+ 	}
++	return 0;
++out_nomem:
++	remove_cache_proc_entries(cd);
++	return -ENOMEM;
+ }
++#else /* CONFIG_PROC_FS */
++static int create_cache_proc_entries(struct cache_detail *cd)
++{
++	return 0;
++}
++#endif
+ 
+-void cache_register(struct cache_detail *cd)
++int cache_register(struct cache_detail *cd)
+ {
+-	create_cache_proc_entries(cd);
++	int ret;
++
++	ret = create_cache_proc_entries(cd);
++	if (ret)
++		return ret;
+ 	rwlock_init(&cd->hash_lock);
+ 	INIT_LIST_HEAD(&cd->queue);
+ 	spin_lock(&cache_list_lock);
+@@ -360,6 +375,7 @@ void cache_register(struct cache_detail *cd)
+ 
+ 	/* start the cleaning process */
+ 	schedule_delayed_work(&cache_cleaner, 0);
++	return 0;
+ }
+ 
+ void cache_unregister(struct cache_detail *cd)

commit ffe9386b6e08e7132cb7730025d0ea310e08a182
+Author: J. Bruce Fields 
+Date:   Mon Nov 12 17:04:29 2007 -0500
+
+    nfsd: move cache proc (un)registration to separate function
+    
+    Just some minor cleanup.
+    
+    Also I don't see much point in trying to register further proc entries
+    if initial entries fail; so just stop trying in that case.
+    
+    Acked-by: NeilBrown 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
+index 365586a999ea..f41a7cc4cf62 100644
+--- a/net/sunrpc/cache.c
++++ b/net/sunrpc/cache.c
+@@ -290,44 +290,63 @@ static const struct file_operations cache_flush_operations;
+ static void do_cache_clean(struct work_struct *work);
+ static DECLARE_DELAYED_WORK(cache_cleaner, do_cache_clean);
+ 
+-void cache_register(struct cache_detail *cd)
++static void remove_cache_proc_entries(struct cache_detail *cd)
+ {
+-	cd->proc_ent = proc_mkdir(cd->name, proc_net_rpc);
+-	if (cd->proc_ent) {
+-		struct proc_dir_entry *p;
+-		cd->proc_ent->owner = cd->owner;
+-		cd->channel_ent = cd->content_ent = NULL;
++	if (cd->proc_ent == NULL)
++		return;
++	if (cd->flush_ent)
++		remove_proc_entry("flush", cd->proc_ent);
++	if (cd->channel_ent)
++		remove_proc_entry("channel", cd->proc_ent);
++	if (cd->content_ent)
++		remove_proc_entry("content", cd->proc_ent);
++	cd->proc_ent = NULL;
++	remove_proc_entry(cd->name, proc_net_rpc);
++}
+ 
+-		p = create_proc_entry("flush", S_IFREG|S_IRUSR|S_IWUSR,
+-				      cd->proc_ent);
+-		cd->flush_ent =  p;
+-		if (p) {
+-			p->proc_fops = &cache_flush_operations;
+-			p->owner = cd->owner;
+-			p->data = cd;
+-		}
++static void create_cache_proc_entries(struct cache_detail *cd)
++{
++	struct proc_dir_entry *p;
+ 
+-		if (cd->cache_request || cd->cache_parse) {
+-			p = create_proc_entry("channel", S_IFREG|S_IRUSR|S_IWUSR,
+-					      cd->proc_ent);
+-			cd->channel_ent = p;
+-			if (p) {
+-				p->proc_fops = &cache_file_operations;
+-				p->owner = cd->owner;
+-				p->data = cd;
+-			}
+-		}
+-		if (cd->cache_show) {
+-			p = create_proc_entry("content", S_IFREG|S_IRUSR|S_IWUSR,
+-					      cd->proc_ent);
+-			cd->content_ent = p;
+-			if (p) {
+-				p->proc_fops = &content_file_operations;
+-				p->owner = cd->owner;
+-				p->data = cd;
+-			}
+-		}
++	cd->proc_ent = proc_mkdir(cd->name, proc_net_rpc);
++	if (cd->proc_ent == NULL)
++		return;
++	cd->proc_ent->owner = cd->owner;
++	cd->channel_ent = cd->content_ent = NULL;
++
++	p = create_proc_entry("flush", S_IFREG|S_IRUSR|S_IWUSR, cd->proc_ent);
++	cd->flush_ent = p;
++	if (p == NULL)
++		return;
++	p->proc_fops = &cache_flush_operations;
++	p->owner = cd->owner;
++	p->data = cd;
++
++	if (cd->cache_request || cd->cache_parse) {
++		p = create_proc_entry("channel", S_IFREG|S_IRUSR|S_IWUSR,
++				      cd->proc_ent);
++		cd->channel_ent = p;
++		if (p == NULL)
++			return;
++		p->proc_fops = &cache_file_operations;
++		p->owner = cd->owner;
++		p->data = cd;
++	}
++	if (cd->cache_show) {
++		p = create_proc_entry("content", S_IFREG|S_IRUSR|S_IWUSR,
++				      cd->proc_ent);
++		cd->content_ent = p;
++		if (p == NULL)
++			return;
++		p->proc_fops = &content_file_operations;
++		p->owner = cd->owner;
++		p->data = cd;
+ 	}
++}
++
++void cache_register(struct cache_detail *cd)
++{
++	create_cache_proc_entries(cd);
+ 	rwlock_init(&cd->hash_lock);
+ 	INIT_LIST_HEAD(&cd->queue);
+ 	spin_lock(&cache_list_lock);
+@@ -358,17 +377,7 @@ void cache_unregister(struct cache_detail *cd)
+ 	list_del_init(&cd->others);
+ 	write_unlock(&cd->hash_lock);
+ 	spin_unlock(&cache_list_lock);
+-	if (cd->proc_ent) {
+-		if (cd->flush_ent)
+-			remove_proc_entry("flush", cd->proc_ent);
+-		if (cd->channel_ent)
+-			remove_proc_entry("channel", cd->proc_ent);
+-		if (cd->content_ent)
+-			remove_proc_entry("content", cd->proc_ent);
+-
+-		cd->proc_ent = NULL;
+-		remove_proc_entry(cd->name, proc_net_rpc);
+-	}
++	remove_cache_proc_entries(cd);
+ 	if (list_empty(&cache_list)) {
+ 		/* module must be being unloaded so its safe to kill the worker */
+ 		cancel_delayed_work_sync(&cache_cleaner);

commit e331f606a85a2a9e84e9c63c94d43c0517136139
+Author: J. Bruce Fields 
+Date:   Mon Nov 12 17:32:21 2007 -0500
+
+    nfsd: fail init on /proc/fs/nfs/exports creation failure
+    
+    I assume the reason failure of creation was ignored here was just to
+    continue support embedded systems that want nfsd but not proc.
+    
+    However, in cases where proc is supported it would be clearer to fail
+    entirely than to come up with some features disabled.
+    
+    Acked-by: NeilBrown 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index 2bfda9b8f504..2b95597aa4a5 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -674,6 +674,27 @@ static struct file_system_type nfsd_fs_type = {
+ 	.kill_sb	= kill_litter_super,
+ };
+ 
++#ifdef CONFIG_PROC_FS
++static int create_proc_exports_entry(void)
++{
++	struct proc_dir_entry *entry;
++
++	entry = proc_mkdir("fs/nfs", NULL);
++	if (!entry)
++		return -ENOMEM;
++	entry = create_proc_entry("fs/nfs/exports", 0, NULL);
++	if (!entry)
++		return -ENOMEM;
++	entry->proc_fops =  &exports_operations;
++	return 0;
++}
++#else /* CONFIG_PROC_FS */
++static int create_proc_exports_entry(void)
++{
++	return 0;
++}
++#endif
++
+ static int __init init_nfsd(void)
+ {
+ 	int retval;
+@@ -689,23 +710,21 @@ static int __init init_nfsd(void)
+ 	nfsd_export_init();	/* Exports table */
+ 	nfsd_lockd_init();	/* lockd->nfsd callbacks */
+ 	nfsd_idmap_init();      /* Name to ID mapping */
+-	if (proc_mkdir("fs/nfs", NULL)) {
+-		struct proc_dir_entry *entry;
+-		entry = create_proc_entry("fs/nfs/exports", 0, NULL);
+-		if (entry)
+-			entry->proc_fops =  &exports_operations;
+-	}
++	retval = create_proc_exports_entry();
++	if (retval)
++		goto out_free_idmap;
+ 	retval = register_filesystem(&nfsd_fs_type);
+ 	if (retval)
+ 		goto out_free_all;
+ 	return 0;
+ out_free_all:
+-	nfsd_idmap_shutdown();
+-	nfsd_export_shutdown();
+-	nfsd_reply_cache_shutdown();
+ 	remove_proc_entry("fs/nfs/exports", NULL);
+ 	remove_proc_entry("fs/nfs", NULL);
++	nfsd_idmap_shutdown();
++out_free_idmap:
+ 	nfsd_lockd_shutdown();
++	nfsd_export_shutdown();
++	nfsd_reply_cache_shutdown();
+ out_free_stat:
+ 	nfsd_stat_shutdown();
+ 	nfsd4_free_slabs();

commit 440bcc592052e42c7050a51489c65e18df4a0636
+Author: J. Bruce Fields 
+Date:   Mon Nov 12 17:09:49 2007 -0500
+
+    nfsd: select CONFIG_PROC_FS in nfsv4 and gss server cases
+    
+    The server depends on upcalls under /proc to support nfsv4 and gss.
+    
+    Acked-by: NeilBrown 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/Kconfig b/fs/Kconfig
+index 219ec06a8c7e..987b5d7cb21a 100644
+--- a/fs/Kconfig
++++ b/fs/Kconfig
+@@ -1674,6 +1674,8 @@ config NFSD
+ 	select CRYPTO_MD5 if NFSD_V4
+ 	select CRYPTO if NFSD_V4
+ 	select FS_POSIX_ACL if NFSD_V4
++	select PROC_FS if NFSD_V4
++	select PROC_FS if SUNRPC_GSS
+ 	help
+ 	  If you want your Linux box to act as an NFS *server*, so that other
+ 	  computers on your local network which support NFS can access certain

commit df95a9d4fb91d819d3fb55dd437056df59e7f15e
+Author: J. Bruce Fields 
+Date:   Thu Nov 8 16:09:59 2007 -0500
+
+    knfsd: cache unregistration needn't return error
+    
+    There's really nothing much the caller can do if cache unregistration
+    fails.  And indeed, all any caller does in this case is print an error
+    and continue.  So just return void and move the printk's inside
+    cache_unregister.
+    
+    Acked-by: NeilBrown 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
+index 66d0aeb32a47..d29b70a28f2b 100644
+--- a/fs/nfsd/export.c
++++ b/fs/nfsd/export.c
+@@ -1670,10 +1670,8 @@ nfsd_export_shutdown(void)
+ 
+ 	exp_writelock();
+ 
+-	if (cache_unregister(&svc_expkey_cache))
+-		printk(KERN_ERR "nfsd: failed to unregister expkey cache\n");
+-	if (cache_unregister(&svc_export_cache))
+-		printk(KERN_ERR "nfsd: failed to unregister export cache\n");
++	cache_unregister(&svc_expkey_cache);
++	cache_unregister(&svc_export_cache);
+ 	svcauth_unix_purge();
+ 
+ 	exp_writeunlock();
+diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
+index 5b56c77c15c5..ef22179c49ad 100644
+--- a/fs/nfsd/nfs4idmap.c
++++ b/fs/nfsd/nfs4idmap.c
+@@ -474,10 +474,8 @@ nfsd_idmap_init(void)
+ void
+ nfsd_idmap_shutdown(void)
+ {
+-	if (cache_unregister(&idtoname_cache))
+-		printk(KERN_ERR "nfsd: failed to unregister idtoname cache\n");
+-	if (cache_unregister(&nametoid_cache))
+-		printk(KERN_ERR "nfsd: failed to unregister nametoid cache\n");
++	cache_unregister(&idtoname_cache);
++	cache_unregister(&nametoid_cache);
+ }
+ 
+ /*
+diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h
+index bd7a6b0a87af..b683b5ddeea9 100644
+--- a/include/linux/sunrpc/cache.h
++++ b/include/linux/sunrpc/cache.h
+@@ -170,7 +170,7 @@ extern void cache_flush(void);
+ extern void cache_purge(struct cache_detail *detail);
+ #define NEVER (0x7FFFFFFF)
+ extern void cache_register(struct cache_detail *cd);
+-extern int cache_unregister(struct cache_detail *cd);
++extern void cache_unregister(struct cache_detail *cd);
+ 
+ extern void qword_add(char **bpp, int *lp, char *str);
+ extern void qword_addhex(char **bpp, int *lp, char *buf, int blen);
+diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
+index 73940df6c460..d329a12500aa 100644
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -1396,9 +1396,7 @@ gss_svc_init(void)
+ void
+ gss_svc_shutdown(void)
+ {
+-	if (cache_unregister(&rsc_cache))
+-		printk(KERN_ERR "auth_rpcgss: failed to unregister rsc cache\n");
+-	if (cache_unregister(&rsi_cache))
+-		printk(KERN_ERR "auth_rpcgss: failed to unregister rsi cache\n");
++	cache_unregister(&rsc_cache);
++	cache_unregister(&rsi_cache);
+ 	svc_auth_unregister(RPC_AUTH_GSS);
+ }
+diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
+index 3b11277d27b1..365586a999ea 100644
+--- a/net/sunrpc/cache.c
++++ b/net/sunrpc/cache.c
+@@ -343,7 +343,7 @@ void cache_register(struct cache_detail *cd)
+ 	schedule_delayed_work(&cache_cleaner, 0);
+ }
+ 
+-int cache_unregister(struct cache_detail *cd)
++void cache_unregister(struct cache_detail *cd)
+ {
+ 	cache_purge(cd);
+ 	spin_lock(&cache_list_lock);
+@@ -351,7 +351,7 @@ int cache_unregister(struct cache_detail *cd)
+ 	if (cd->entries || atomic_read(&cd->inuse)) {
+ 		write_unlock(&cd->hash_lock);
+ 		spin_unlock(&cache_list_lock);
+-		return -EBUSY;
++		goto out;
+ 	}
+ 	if (current_detail == cd)
+ 		current_detail = NULL;
+@@ -373,7 +373,9 @@ int cache_unregister(struct cache_detail *cd)
+ 		/* module must be being unloaded so its safe to kill the worker */
+ 		cancel_delayed_work_sync(&cache_cleaner);
+ 	}
+-	return 0;
++	return;
++out:
++	printk(KERN_ERR "nfsd: failed to unregister %s cache\n", cd->name);
+ }
+ 
+ /* clean cache tries to find something to clean
+diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
+index 1a7e309d008b..ef7dc78e2c7b 100644
+--- a/net/sunrpc/sunrpc_syms.c
++++ b/net/sunrpc/sunrpc_syms.c
+@@ -98,10 +98,8 @@ cleanup_sunrpc(void)
+ 	cleanup_socket_xprt();
+ 	unregister_rpc_pipefs();
+ 	rpc_destroy_mempool();
+-	if (cache_unregister(&ip_map_cache))
+-		printk(KERN_ERR "sunrpc: failed to unregister ip_map cache\n");
+-	if (cache_unregister(&unix_gid_cache))
+-	      printk(KERN_ERR "sunrpc: failed to unregister unix_gid cache\n");
++	cache_unregister(&ip_map_cache);
++	cache_unregister(&unix_gid_cache);
+ #ifdef RPC_DEBUG
+ 	rpc_unregister_sysctl();
+ #endif

commit d5c3428b2cb26d605fddc4878f4fcc03c23df89f
+Author: J. Bruce Fields 
+Date:   Fri Nov 9 14:10:56 2007 -0500
+
+    nfsd: fail module init on reply cache init failure
+    
+    If the reply cache initialization fails due to a kmalloc failure,
+    currently we try to soldier on with a reduced (or nonexistant) reply
+    cache.
+    
+    Better to just fail immediately: the failure is then much easier to
+    understand and debug, and it could save us complexity in some later
+    code.  (But actually, it doesn't help currently because the cache is
+    also turned off in some odd failure cases; we should probably find a
+    better way to handle those failure cases some day.)
+    
+    Fix some minor style problems while we're at it, and rename
+    nfsd_cache_init() to remove the need for a comment describing it.
+    
+    Acked-by: NeilBrown 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
+index 578f2c9d56be..5bfc2ac60d54 100644
+--- a/fs/nfsd/nfscache.c
++++ b/fs/nfsd/nfscache.c
+@@ -44,17 +44,17 @@ static int	nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *vec);
+  */
+ static DEFINE_SPINLOCK(cache_lock);
+ 
+-void
+-nfsd_cache_init(void)
++int nfsd_reply_cache_init(void)
+ {
+ 	struct svc_cacherep	*rp;
+ 	int			i;
+ 
+ 	INIT_LIST_HEAD(&lru_head);
+ 	i = CACHESIZE;
+-	while(i) {
++	while (i) {
+ 		rp = kmalloc(sizeof(*rp), GFP_KERNEL);
+-		if (!rp) break;
++		if (!rp)
++			goto out_nomem;
+ 		list_add(&rp->c_lru, &lru_head);
+ 		rp->c_state = RC_UNUSED;
+ 		rp->c_type = RC_NOCACHE;
+@@ -62,23 +62,19 @@ nfsd_cache_init(void)
+ 		i--;
+ 	}
+ 
+-	if (i)
+-		printk (KERN_ERR "nfsd: cannot allocate all %d cache entries, only got %d\n",
+-			CACHESIZE, CACHESIZE-i);
+-
+ 	hash_list = kcalloc (HASHSIZE, sizeof(struct hlist_head), GFP_KERNEL);
+-	if (!hash_list) {
+-		nfsd_cache_shutdown();
+-		printk (KERN_ERR "nfsd: cannot allocate %Zd bytes for hash list\n",
+-			HASHSIZE * sizeof(struct hlist_head));
+-		return;
+-	}
++	if (!hash_list)
++		goto out_nomem;
+ 
+ 	cache_disabled = 0;
++	return 0;
++out_nomem:
++	printk(KERN_ERR "nfsd: failed to allocate reply cache\n");
++	nfsd_reply_cache_shutdown();
++	return -ENOMEM;
+ }
+ 
+-void
+-nfsd_cache_shutdown(void)
++void nfsd_reply_cache_shutdown(void)
+ {
+ 	struct svc_cacherep	*rp;
+ 
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index ecf377944286..2bfda9b8f504 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -683,7 +683,9 @@ static int __init init_nfsd(void)
+ 	if (retval)
+ 		return retval;
+ 	nfsd_stat_init();	/* Statistics */
+-	nfsd_cache_init();	/* RPC reply cache */
++	retval = nfsd_reply_cache_init();
++	if (retval)
++		goto out_free_stat;
+ 	nfsd_export_init();	/* Exports table */
+ 	nfsd_lockd_init();	/* lockd->nfsd callbacks */
+ 	nfsd_idmap_init();      /* Name to ID mapping */
+@@ -700,11 +702,12 @@ static int __init init_nfsd(void)
+ out_free_all:
+ 	nfsd_idmap_shutdown();
+ 	nfsd_export_shutdown();
+-	nfsd_cache_shutdown();
++	nfsd_reply_cache_shutdown();
+ 	remove_proc_entry("fs/nfs/exports", NULL);
+ 	remove_proc_entry("fs/nfs", NULL);
+-	nfsd_stat_shutdown();
+ 	nfsd_lockd_shutdown();
++out_free_stat:
++	nfsd_stat_shutdown();
+ 	nfsd4_free_slabs();
+ 	return retval;
+ }
+@@ -712,7 +715,7 @@ static int __init init_nfsd(void)
+ static void __exit exit_nfsd(void)
+ {
+ 	nfsd_export_shutdown();
+-	nfsd_cache_shutdown();
++	nfsd_reply_cache_shutdown();
+ 	remove_proc_entry("fs/nfs/exports", NULL);
+ 	remove_proc_entry("fs/nfs", NULL);
+ 	nfsd_stat_shutdown();
+diff --git a/include/linux/nfsd/cache.h b/include/linux/nfsd/cache.h
+index 007480cd6a60..7b5d784cc858 100644
+--- a/include/linux/nfsd/cache.h
++++ b/include/linux/nfsd/cache.h
+@@ -72,8 +72,8 @@ enum {
+  */
+ #define RC_DELAY		(HZ/5)
+ 
+-void	nfsd_cache_init(void);
+-void	nfsd_cache_shutdown(void);
++int	nfsd_reply_cache_init(void);
++void	nfsd_reply_cache_shutdown(void);
+ int	nfsd_cache_lookup(struct svc_rqst *, int);
+ void	nfsd_cache_update(struct svc_rqst *, int, __be32 *);
+ 

commit 26808d3f10b1213bbb6e27d441be40e20ab84611
+Author: J. Bruce Fields 
+Date:   Fri Nov 9 13:44:06 2007 -0500
+
+    nfsd: cleanup nfsd module initialization cleanup
+    
+    Handle the failure case here with something closer to the standard
+    kernel style.
+    
+    Doesn't really matter for now, but I'd like to add a few more failure
+    cases, and then this'll help.
+    
+    Acked-by: NeilBrown 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index d8d50a773a5b..ecf377944286 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -694,16 +694,18 @@ static int __init init_nfsd(void)
+ 			entry->proc_fops =  &exports_operations;
+ 	}
+ 	retval = register_filesystem(&nfsd_fs_type);
+-	if (retval) {
+-		nfsd_idmap_shutdown();
+-		nfsd_export_shutdown();
+-		nfsd_cache_shutdown();
+-		remove_proc_entry("fs/nfs/exports", NULL);
+-		remove_proc_entry("fs/nfs", NULL);
+-		nfsd_stat_shutdown();
+-		nfsd_lockd_shutdown();
+-		nfsd4_free_slabs();
+-	}
++	if (retval)
++		goto out_free_all;
++	return 0;
++out_free_all:
++	nfsd_idmap_shutdown();
++	nfsd_export_shutdown();
++	nfsd_cache_shutdown();
++	remove_proc_entry("fs/nfs/exports", NULL);
++	remove_proc_entry("fs/nfs", NULL);
++	nfsd_stat_shutdown();
++	nfsd_lockd_shutdown();
++	nfsd4_free_slabs();
+ 	return retval;
+ }
+ 

commit 46b25895767c606c630a97b03a895934a7a36a70
+Author: J. Bruce Fields 
+Date:   Fri Nov 9 12:31:55 2007 -0500
+
+    knfsd: cleanup nfsd4 properly on module init failure
+    
+    We forgot to shut down the nfs4 state and idmapping code in this case.
+    
+    Acked-by: NeilBrown 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index 77dc9893b7ba..d8d50a773a5b 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -695,12 +695,14 @@ static int __init init_nfsd(void)
+ 	}
+ 	retval = register_filesystem(&nfsd_fs_type);
+ 	if (retval) {
++		nfsd_idmap_shutdown();
+ 		nfsd_export_shutdown();
+ 		nfsd_cache_shutdown();
+ 		remove_proc_entry("fs/nfs/exports", NULL);
+ 		remove_proc_entry("fs/nfs", NULL);
+ 		nfsd_stat_shutdown();
+ 		nfsd_lockd_shutdown();
++		nfsd4_free_slabs();
+ 	}
+ 	return retval;
+ }

commit ca2a05aa7c72309ee65164c78fa2be7a5038215e
+Author: J. Bruce Fields 
+Date:   Sun Nov 11 15:43:12 2007 -0500
+
+    nfsd: Fix handling of negative lengths in read_buf()
+    
+    The length "nbytes" passed into read_buf should never be negative, but
+    we check only for too-large values of "nbytes", not for too-small
+    values.  Make nbytes unsigned, so it's clear that the former tests are
+    sufficient.  (Despite this read_buf() currently correctly returns an xdr
+    error in the case of a negative length, thanks to an unsigned
+    comparison with size_of() and bounds-checking in kmalloc().  This seems
+    very fragile, though.)
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index 57333944af7f..bf1e792a65a0 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -148,12 +148,12 @@ xdr_error:					\
+ 	}					\
+ } while (0)
+ 
+-static __be32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes)
++static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes)
+ {
+ 	/* We want more bytes than seem to be available.
+ 	 * Maybe we need a new page, maybe we have just run out
+ 	 */
+-	int avail = (char*)argp->end - (char*)argp->p;
++	unsigned int avail = (char *)argp->end - (char *)argp->p;
+ 	__be32 *p;
+ 	if (avail + argp->pagelen < nbytes)
+ 		return NULL;
+@@ -169,6 +169,11 @@ static __be32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes)
+ 			return NULL;
+ 		
+ 	}
++	/*
++	 * The following memcpy is safe because read_buf is always
++	 * called with nbytes > avail, and the two cases above both
++	 * guarantee p points to at least nbytes bytes.
++	 */
+ 	memcpy(p, argp->p, avail);
+ 	/* step to next page */
+ 	argp->p = page_address(argp->pagelist[0]);

commit a490c681cbcf65d548138c377bb691c85824d323
+Author: J. Bruce Fields 
+Date:   Tue Nov 6 14:15:19 2007 -0500
+
+    knfsd: fix cache.c comment
+    
+    The path here must be left over from some earlier draft; fix it.  And do
+    some more minor cleanup while we're there.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
+index d27bbe0ee907..3b11277d27b1 100644
+--- a/net/sunrpc/cache.c
++++ b/net/sunrpc/cache.c
+@@ -634,13 +634,13 @@ void cache_clean_deferred(void *owner)
+ /*
+  * communicate with user-space
+  *
+- * We have a magic /proc file - /proc/sunrpc/cache
+- * On read, you get a full request, or block
+- * On write, an update request is processed
+- * Poll works if anything to read, and always allows write
++ * We have a magic /proc file - /proc/sunrpc//channel.
++ * On read, you get a full request, or block.
++ * On write, an update request is processed.
++ * Poll works if anything to read, and always allows write.
+  *
+  * Implemented by linked list of requests.  Each open file has
+- * a ->private that also exists in this list.  New request are added
++ * a ->private that also exists in this list.  New requests are added
+  * to the end and may wakeup and preceding readers.
+  * New readers are added to the head.  If, on read, an item is found with
+  * CACHE_UPCALLING clear, we free it from the list.

commit d4395e03fec0895d01451904b8a2276ceda663c9
+Author: J. Bruce Fields 
+Date:   Fri Oct 26 13:32:50 2007 -0400
+
+    knfsd: fix broken length check in nfs4idmap.c
+    
+    Obviously at some point we thought "error" represented the length when
+    positive.  This appears to be a long-standing typo.
+    
+    Thanks to Prasad Potluri  for finding the problem and
+    proposing an earlier version of this patch.
+    
+    Cc: Steve French 
+    Cc: Prasad V Potluri 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
+index 4c0c683ce07a..5b56c77c15c5 100644
+--- a/fs/nfsd/nfs4idmap.c
++++ b/fs/nfsd/nfs4idmap.c
+@@ -255,13 +255,10 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen)
+ 		goto out;
+ 	if (len == 0)
+ 		set_bit(CACHE_NEGATIVE, &ent.h.flags);
+-	else {
+-		if (error >= IDMAP_NAMESZ) {
+-			error = -EINVAL;
+-			goto out;
+-		}
++	else if (len >= IDMAP_NAMESZ)
++		goto out;
++	else
+ 		memcpy(ent.name, buf1, sizeof(ent.name));
+-	}
+ 	error = -ENOMEM;
+ 	res = idtoname_update(&ent, res);
+ 	if (res == NULL)

commit 63c86716ea34ad94d52e5b0abbda152574dc42b5
+Author: J. Bruce Fields 
+Date:   Thu Oct 25 19:00:26 2007 -0400
+
+    nfsd: move callback rpc_client creation into separate thread
+    
+    The whole reason to move this callback-channel probe into a separate
+    thread was because (for now) we don't have an easy way to create the
+    rpc_client asynchronously.  But I forgot to move the rpc_create() to the
+    spawned thread.  Doh!  Fix that.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index a9735a672963..6eb5cd2381ab 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -350,30 +350,6 @@ static struct rpc_version *	nfs_cb_version[] = {
+ static int do_probe_callback(void *data)
+ {
+ 	struct nfs4_client *clp = data;
+-	struct nfs4_callback *cb = &clp->cl_callback;
+-	struct rpc_message msg = {
+-		.rpc_proc       = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
+-		.rpc_argp       = clp,
+-	};
+-	int status;
+-
+-	status = rpc_call_sync(cb->cb_client, &msg, RPC_TASK_SOFT);
+-
+-	if (status) {
+-		rpc_shutdown_client(cb->cb_client);
+-		cb->cb_client = NULL;
+-	} else
+-		atomic_set(&cb->cb_set, 1);
+-	put_nfs4_client(clp);
+-	return 0;
+-}
+-
+-/*
+- * Set up the callback client and put a NFSPROC4_CB_NULL on the wire...
+- */
+-void
+-nfsd4_probe_callback(struct nfs4_client *clp)
+-{
+ 	struct sockaddr_in	addr;
+ 	struct nfs4_callback    *cb = &clp->cl_callback;
+ 	struct rpc_timeout	timeparms = {
+@@ -390,12 +366,15 @@ nfsd4_probe_callback(struct nfs4_client *clp)
+ 		.timeout	= &timeparms,
+ 		.program	= program,
+ 		.version	= nfs_cb_version[1]->number,
+-		.authflavor	= RPC_AUTH_UNIX,	/* XXX: need AUTH_GSS... */
++		.authflavor	= RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */
+ 		.flags		= (RPC_CLNT_CREATE_NOPING),
+ 	};
+-	struct task_struct *t;
+-
+-	BUG_ON(atomic_read(&clp->cl_callback.cb_set));
++	struct rpc_message msg = {
++		.rpc_proc       = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
++		.rpc_argp       = clp,
++	};
++	struct rpc_clnt *client;
++	int status;
+ 
+ 	/* Initialize address */
+ 	memset(&addr, 0, sizeof(addr));
+@@ -415,29 +394,50 @@ nfsd4_probe_callback(struct nfs4_client *clp)
+ 	program->stats->program = program;
+ 
+ 	/* Create RPC client */
+-	cb->cb_client = rpc_create(&args);
+-	if (IS_ERR(cb->cb_client)) {
++	client = rpc_create(&args);
++	if (IS_ERR(client)) {
+ 		dprintk("NFSD: couldn't create callback client\n");
++		status = PTR_ERR(client);
+ 		goto out_err;
+ 	}
+ 
++	status = rpc_call_sync(client, &msg, RPC_TASK_SOFT);
++
++	if (status)
++		goto out_release_client;
++
++	cb->cb_client = client;
++	atomic_set(&cb->cb_set, 1);
++	put_nfs4_client(clp);
++	return 0;
++out_release_client:
++	rpc_shutdown_client(client);
++out_err:
++	put_nfs4_client(clp);
++	dprintk("NFSD: warning: no callback path to client %.*s\n",
++		(int)clp->cl_name.len, clp->cl_name.data);
++	return status;
++}
++
++/*
++ * Set up the callback client and put a NFSPROC4_CB_NULL on the wire...
++ */
++void
++nfsd4_probe_callback(struct nfs4_client *clp)
++{
++	struct task_struct *t;
++
++	BUG_ON(atomic_read(&clp->cl_callback.cb_set));
++
+ 	/* the task holds a reference to the nfs4_client struct */
+ 	atomic_inc(&clp->cl_count);
+ 
+ 	t = kthread_run(do_probe_callback, clp, "nfs4_cb_probe");
+ 
+ 	if (IS_ERR(t))
+-		goto out_release_clp;
++		atomic_dec(&clp->cl_count);
+ 
+ 	return;
+-
+-out_release_clp:
+-	atomic_dec(&clp->cl_count);
+-	rpc_shutdown_client(cb->cb_client);
+-out_err:
+-	cb->cb_client = NULL;
+-	dprintk("NFSD: warning: no callback path to client %.*s\n",
+-		(int)clp->cl_name.len, clp->cl_name.data);
+ }
+ 
+ /*

commit 46f8a64bae11f5c9b15b4401f6e9863281999b66
+Author: J. Bruce Fields 
+Date:   Thu Nov 22 13:54:18 2007 -0500
+
+    nfsd4: probe callback channel only once
+    
+    Our callback code doesn't actually handle concurrent attempts to probe
+    the callback channel.  Some rethinking of the locking may be required.
+    However, we can also just move the callback probing to this case.  Since
+    this is the only time a client is "confirmed" (and since that can only
+    happen once in the lifetime of a client), this ensures we only probe
+    once.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 9d536a8cb379..a9735a672963 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -395,8 +395,7 @@ nfsd4_probe_callback(struct nfs4_client *clp)
+ 	};
+ 	struct task_struct *t;
+ 
+-	if (atomic_read(&cb->cb_set))
+-		return;
++	BUG_ON(atomic_read(&clp->cl_callback.cb_set));
+ 
+ 	/* Initialize address */
+ 	memset(&addr, 0, sizeof(addr));
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 31673cd251c3..9d81c7117ae6 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -948,6 +948,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+ 			}
+ 			move_to_confirmed(unconf);
+ 			conf = unconf;
++			nfsd4_probe_callback(conf);
+ 			status = nfs_ok;
+ 		}
+ 	} else if ((!conf || (conf && !same_verf(&conf->cl_confirm, &confirm)))
+@@ -965,8 +966,6 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+ 		status = nfserr_clid_inuse;
+ 	}
+ out:
+-	if (!status)
+-		nfsd4_probe_callback(conf);
+ 	nfs4_unlock_state();
+ 	return status;
+ }

commit 3d1c550874bcaf0d9b7fb66f601caed109074f4b
+Author: J. Bruce Fields 
+Date:   Tue Jan 15 16:43:19 2008 -0500
+
+    nfs4: allow nfsv4 acls on non-regular-files
+    
+    The rfc doesn't give any reason it shouldn't be possible to set an
+    attribute on a non-regular file.  And if the server supports it, then it
+    shouldn't be up to us to prevent it.
+    
+    Thanks to Erez for the report and Trond for further analysis.
+    
+    Signed-off-by: J. Bruce Fields 
+    Tested-by: Erez Zadok 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index b3d4e8e5696a..89efbcd6fd53 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -3617,10 +3617,6 @@ int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf,
+ 	if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0)
+ 		return -EOPNOTSUPP;
+ 
+-	if (!S_ISREG(inode->i_mode) &&
+-	    (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
+-		return -EPERM;
+-
+ 	return nfs4_proc_set_acl(inode, buf, buflen);
+ }
+ 

commit 93a44a75b97b9d8a03dd3d3f3247c3d0ec46aa4c
+Author: J. Bruce Fields 
+Date:   Tue Nov 6 13:06:03 2007 -0500
+
+    sunrpc: document the rpc_pipefs kernel api
+    
+    Add kerneldoc comments for the rpc_pipefs.c functions that are exported.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
+index c59f3ca2b41b..5364e2e52e07 100644
+--- a/net/sunrpc/rpc_pipe.c
++++ b/net/sunrpc/rpc_pipe.c
+@@ -76,6 +76,16 @@ rpc_timeout_upcall_queue(struct work_struct *work)
+ 	rpc_purge_list(rpci, &free_list, destroy_msg, -ETIMEDOUT);
+ }
+ 
++/**
++ * rpc_queue_upcall
++ * @inode: inode of upcall pipe on which to queue given message
++ * @msg: message to queue
++ *
++ * Call with an @inode created by rpc_mkpipe() to queue an upcall.
++ * A userspace process may then later read the upcall by performing a
++ * read on an open file for this inode.  It is up to the caller to
++ * initialize the fields of @msg (other than @msg->list) appropriately.
++ */
+ int
+ rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg)
+ {
+@@ -663,7 +673,16 @@ rpc_lookup_negative(char *path, struct nameidata *nd)
+ 	return dentry;
+ }
+ 
+-
++/**
++ * rpc_mkdir - Create a new directory in rpc_pipefs
++ * @path: path from the rpc_pipefs root to the new directory
++ * @rpc_clnt: rpc client to associate with this directory
++ *
++ * This creates a directory at the given @path associated with
++ * @rpc_clnt, which will contain a file named "info" with some basic
++ * information about the client, together with any "pipes" that may
++ * later be created using rpc_mkpipe().
++ */
+ struct dentry *
+ rpc_mkdir(char *path, struct rpc_clnt *rpc_client)
+ {
+@@ -699,6 +718,10 @@ rpc_mkdir(char *path, struct rpc_clnt *rpc_client)
+ 	goto out;
+ }
+ 
++/**
++ * rpc_rmdir - Remove a directory created with rpc_mkdir()
++ * @dentry: directory to remove
++ */
+ int
+ rpc_rmdir(struct dentry *dentry)
+ {
+@@ -717,6 +740,25 @@ rpc_rmdir(struct dentry *dentry)
+ 	return error;
+ }
+ 
++/**
++ * rpc_mkpipe - make an rpc_pipefs file for kernel<->userspace communication
++ * @parent: dentry of directory to create new "pipe" in
++ * @name: name of pipe
++ * @private: private data to associate with the pipe, for the caller's use
++ * @ops: operations defining the behavior of the pipe: upcall, downcall,
++ *	release_pipe, and destroy_msg.
++ *
++ * Data is made available for userspace to read by calls to
++ * rpc_queue_upcall().  The actual reads will result in calls to
++ * @ops->upcall, which will be called with the file pointer,
++ * message, and userspace buffer to copy to.
++ *
++ * Writes can come at any time, and do not necessarily have to be
++ * responses to upcalls.  They will result in calls to @msg->downcall.
++ *
++ * The @private argument passed here will be available to all these methods
++ * from the file pointer, via RPC_I(file->f_dentry->d_inode)->private.
++ */
+ struct dentry *
+ rpc_mkpipe(struct dentry *parent, const char *name, void *private, struct rpc_pipe_ops *ops, int flags)
+ {
+@@ -764,6 +806,14 @@ rpc_mkpipe(struct dentry *parent, const char *name, void *private, struct rpc_pi
+ 	goto out;
+ }
+ 
++/**
++ * rpc_unlink - remove a pipe
++ * @dentry: dentry for the pipe, as returned from rpc_mkpipe
++ *
++ * After this call, lookups will no longer find the pipe, and any
++ * attempts to read or write using preexisting opens of the pipe will
++ * return -EPIPE.
++ */
+ int
+ rpc_unlink(struct dentry *dentry)
+ {

commit eda4f9b7996e5520934ca2a7310b363463a4e3b0
+Author: J. Bruce Fields 
+Date:   Tue Nov 6 13:05:36 2007 -0500
+
+    sunrpc: rpc_pipe_poll may miss available data in some cases
+    
+    Pipe messages start out life on a queue on the inode, but when first
+    read they're moved to the filp's private pointer.  So it's possible for
+    a poll here to return null even though there's a partially read message
+    available.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
+index 18f0a8dcc095..c59f3ca2b41b 100644
+--- a/net/sunrpc/rpc_pipe.c
++++ b/net/sunrpc/rpc_pipe.c
+@@ -280,7 +280,7 @@ rpc_pipe_poll(struct file *filp, struct poll_table_struct *wait)
+ 	mask = POLLOUT | POLLWRNORM;
+ 	if (rpci->ops == NULL)
+ 		mask |= POLLERR | POLLHUP;
+-	if (!list_empty(&rpci->pipe))
++	if (filp->private_data || !list_empty(&rpci->pipe))
+ 		mask |= POLLIN | POLLRDNORM;
+ 	return mask;
+ }

commit ef338bee3f4f509e82066e100f76fecbbbbc4cca
+Author: Kevin Coffman 
+Date:   Fri Nov 9 18:42:09 2007 -0500
+
+    sunrpc: return error if unsupported enctype or cksumtype is encountered
+    
+    Return an error from gss_import_sec_context_kerberos if the
+    negotiated context contains encryption or checksum types not
+    supported by the kernel code.
+    
+    This fixes an Oops because success was assumed and later code found
+    no internal_ctx_id.
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
+index 9843eacef11d..60c3dba545d7 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
++++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
+@@ -147,13 +147,17 @@ gss_import_sec_context_kerberos(const void *p,
+ 	p = simple_get_bytes(p, end, &tmp, sizeof(tmp));
+ 	if (IS_ERR(p))
+ 		goto out_err_free_ctx;
+-	if (tmp != SGN_ALG_DES_MAC_MD5)
++	if (tmp != SGN_ALG_DES_MAC_MD5) {
++		p = ERR_PTR(-ENOSYS);
+ 		goto out_err_free_ctx;
++	}
+ 	p = simple_get_bytes(p, end, &tmp, sizeof(tmp));
+ 	if (IS_ERR(p))
+ 		goto out_err_free_ctx;
+-	if (tmp != SEAL_ALG_DES)
++	if (tmp != SEAL_ALG_DES) {
++		p = ERR_PTR(-ENOSYS);
+ 		goto out_err_free_ctx;
++	}
+ 	p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime));
+ 	if (IS_ERR(p))
+ 		goto out_err_free_ctx;
+diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
+index 1c6eda5077c1..dedcbd6108f4 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
+@@ -83,6 +83,7 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
+ 	u32			seq_send;
+ 
+ 	dprintk("RPC:       gss_krb5_seal\n");
++	BUG_ON(ctx == NULL);
+ 
+ 	now = get_seconds();
+ 

commit ffc40f569272b6be60c66441aeae79a686ff54d9
+Author: Kevin Coffman 
+Date:   Fri Nov 9 18:42:04 2007 -0500
+
+    sunrpc: gss_pipe_downcall(), don't assume all errors are transient
+    
+    Instead of mapping all errors except EACCES to EAGAIN, map all errors
+    except EAGAIN to EACCES.
+    
+    An example is user-land negotiating a Kerberos context with an encryption
+    type that is not supported by the kernel code.  (This can happen due to
+    mis-configuration or a bug in the Kerberos code that does not honor our
+    request to limit the encryption types negotiated.)  This failure is not
+    transient, and returning EAGAIN causes mount to continuously retry rather
+    than giving up.
+    
+    Signed-off-by: Kevin Coffman 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index 53995af9ca4b..c42362c33944 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -540,7 +540,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
+ 	p = gss_fill_context(p, end, ctx, gss_msg->auth->mech);
+ 	if (IS_ERR(p)) {
+ 		err = PTR_ERR(p);
+-		gss_msg->msg.errno = (err == -EACCES) ? -EACCES : -EAGAIN;
++		gss_msg->msg.errno = (err == -EAGAIN) ? -EAGAIN : -EACCES;
+ 		goto err_release_msg;
+ 	}
+ 	gss_msg->ctx = gss_get_ctx(ctx);

commit 6fa02839bf9412e18e773d04e96182b4cd0b5d57
+Author: J. Bruce Fields 
+Date:   Mon Nov 12 16:05:03 2007 -0500
+
+    nfsd4: recheck for secure ports in fh_verify
+    
+    As with commit 7fc90ec93a5eb71f4b08403baf5ba7176b3ec6b1 ("knfsd: nfsd:
+    call nfsd_setuser() on fh_compose(), fix nfsd4 permissions problem")
+    this is a case where we need to redo a security check in fh_verify()
+    even though the filehandle already has an associated dentry--if the
+    filehandle was created by fh_compose() in an earlier operation of the
+    nfsv4 compound, then we may not have done these checks yet.
+    
+    Without this fix it is possible, for example, to traverse from an export
+    without the secure ports requirement to one with it in a single
+    compound, and bypass the secure port check on the new export.
+    
+    While we're here, fix up some minor style problems and change a printk()
+    to a dprintk(), to make it harder for random unprivileged users to spam
+    the logs.
+    
+    Signed-off-by: J. Bruce Fields 
+    Reviewed-By: NeilBrown 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
+index 4f712e970584..468f17a78441 100644
+--- a/fs/nfsd/nfsfh.c
++++ b/fs/nfsd/nfsfh.c
+@@ -95,6 +95,22 @@ nfsd_mode_check(struct svc_rqst *rqstp, umode_t mode, int type)
+ 	return 0;
+ }
+ 
++static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp,
++					  struct svc_export *exp)
++{
++	/* Check if the request originated from a secure port. */
++	if (!rqstp->rq_secure && EX_SECURE(exp)) {
++		char buf[RPC_MAX_ADDRBUFLEN];
++		dprintk(KERN_WARNING
++		       "nfsd: request from insecure port %s!\n",
++		       svc_print_addr(rqstp, buf, sizeof(buf)));
++		return nfserr_perm;
++	}
++
++	/* Set user creds for this exportpoint */
++	return nfserrno(nfsd_setuser(rqstp, exp));
++}
++
+ /*
+  * Perform sanity checks on the dentry in a client's file handle.
+  *
+@@ -167,18 +183,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
+ 			goto out;
+ 		}
+ 
+-		/* Check if the request originated from a secure port. */
+-		error = nfserr_perm;
+-		if (!rqstp->rq_secure && EX_SECURE(exp)) {
+-			char buf[RPC_MAX_ADDRBUFLEN];
+-			printk(KERN_WARNING
+-			       "nfsd: request from insecure port %s!\n",
+-			       svc_print_addr(rqstp, buf, sizeof(buf)));
+-			goto out;
+-		}
+-
+-		/* Set user creds for this exportpoint */
+-		error = nfserrno(nfsd_setuser(rqstp, exp));
++		error = nfsd_setuser_and_check_port(rqstp, exp);
+ 		if (error)
+ 			goto out;
+ 
+@@ -227,18 +232,22 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
+ 		fhp->fh_export = exp;
+ 		nfsd_nr_verified++;
+ 	} else {
+-		/* just rechecking permissions
+-		 * (e.g. nfsproc_create calls fh_verify, then nfsd_create does as well)
++		/*
++		 * just rechecking permissions
++		 * (e.g. nfsproc_create calls fh_verify, then nfsd_create
++		 * does as well)
+ 		 */
+ 		dprintk("nfsd: fh_verify - just checking\n");
+ 		dentry = fhp->fh_dentry;
+ 		exp = fhp->fh_export;
+-		/* Set user creds for this exportpoint; necessary even
++		/*
++		 * Set user creds for this exportpoint; necessary even
+ 		 * in the "just checking" case because this may be a
+ 		 * filehandle that was created by fh_compose, and that
+ 		 * is about to be used in another nfsv4 compound
+-		 * operation */
+-		error = nfserrno(nfsd_setuser(rqstp, exp));
++		 * operation.
++		 */
++		error = nfsd_setuser_and_check_port(rqstp, exp);
+ 		if (error)
+ 			goto out;
+ 	}

commit ac8587dcb58e40dd336d99d60f852041e06cc3dd
+Author: J. Bruce Fields 
+Date:   Mon Nov 12 16:05:02 2007 -0500
+
+    knfsd: fix spurious EINVAL errors on first access of new filesystem
+    
+    The v2/v3 acl code in nfsd is translating any return from fh_verify() to
+    nfserr_inval.  This is particularly unfortunate in the case of an
+    nfserr_dropit return, which is an internal error meant to indicate to
+    callers that this request has been deferred and should just be dropped
+    pending the results of an upcall to mountd.
+    
+    Thanks to Roland  for bug report and data collection.
+    
+    Cc: Roland 
+    Acked-by: Andreas Gruenbacher 
+    Signed-off-by: J. Bruce Fields 
+    Reviewed-By: NeilBrown 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
+index b61742885011..0e5fa11e6b44 100644
+--- a/fs/nfsd/nfs2acl.c
++++ b/fs/nfsd/nfs2acl.c
+@@ -41,7 +41,7 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst * rqstp,
+ 
+ 	fh = fh_copy(&resp->fh, &argp->fh);
+ 	if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP)))
+-		RETURN_STATUS(nfserr_inval);
++		RETURN_STATUS(nfserr);
+ 
+ 	if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
+ 		RETURN_STATUS(nfserr_inval);
+diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c
+index 3e3f2de82c36..b647f2f872dc 100644
+--- a/fs/nfsd/nfs3acl.c
++++ b/fs/nfsd/nfs3acl.c
+@@ -37,7 +37,7 @@ static __be32 nfsd3_proc_getacl(struct svc_rqst * rqstp,
+ 
+ 	fh = fh_copy(&resp->fh, &argp->fh);
+ 	if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP)))
+-		RETURN_STATUS(nfserr_inval);
++		RETURN_STATUS(nfserr);
+ 
+ 	if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
+ 		RETURN_STATUS(nfserr_inval);

commit 97855b49b6bac0bd25f16b017883634d13591d00
+Author: J. Bruce Fields 
+Date:   Tue Oct 30 11:20:02 2007 -0400
+
+    locks: fix possible infinite loop in posix deadlock detection
+    
+    It's currently possible to send posix_locks_deadlock() into an infinite
+    loop (under the BKL).
+    
+    For now, fix this just by bailing out after a few iterations.  We may
+    want to fix this in a way that better clarifies the semantics of
+    deadlock detection.  But that will take more time, and this minimal fix
+    is probably adequate for any realistic scenario, and is simple enough to
+    be appropriate for applying to stable kernels now.
+    
+    Thanks to George Davis for reporting the problem.
+    
+    Cc: "George G. Davis" 
+    Signed-off-by: J. Bruce Fields 
+    Acked-by: Alan Cox 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/locks.c b/fs/locks.c
+index 0127a2846819..8b8388eca05e 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -696,17 +696,28 @@ EXPORT_SYMBOL(posix_test_lock);
+  * Note: the above assumption may not be true when handling lock requests
+  * from a broken NFS client. But broken NFS clients have a lot more to
+  * worry about than proper deadlock detection anyway... --okir
++ *
++ * However, the failure of this assumption (also possible in the case of
++ * multiple tasks sharing the same open file table) also means there's no
++ * guarantee that the loop below will terminate.  As a hack, we give up
++ * after a few iterations.
+  */
++
++#define MAX_DEADLK_ITERATIONS 10
++
+ static int posix_locks_deadlock(struct file_lock *caller_fl,
+ 				struct file_lock *block_fl)
+ {
+ 	struct file_lock *fl;
++	int i = 0;
+ 
+ next_task:
+ 	if (posix_same_owner(caller_fl, block_fl))
+ 		return 1;
+ 	list_for_each_entry(fl, &blocked_list, fl_link) {
+ 		if (posix_same_owner(fl, block_fl)) {
++			if (i++ > MAX_DEADLK_ITERATIONS)
++				return 0;
+ 			fl = fl->fl_next;
+ 			block_fl = fl;
+ 			goto next_task;

commit bc2a3f86f46569fb091792867ce67c9ab24dfd0f
+Author: J. Bruce Fields 
+Date:   Mon Oct 29 14:37:18 2007 -0700
+
+    sunrpc: fix rpc debugging
+    
+    Commit baa3a2a0d24ebcf1c451bec8e5bee3d3467f4cbb ("sysctl: remove broken
+    sunrpc debug binary sysctls"), by removing initialization of the
+    ctl_name field, broke this conditional, preventing the display of
+    rpc_tasks that you previously got when turning on rpc debugging.
+    
+    [akpm@linux-foundation.org: coding-style fixes]
+    Signed-off-by: J. Bruce Fields 
+    Acked-by: "Eric W. Biederman" 
+    Cc: "David S. Miller" 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c
+index 864b541bbf51..2be714e9b382 100644
+--- a/net/sunrpc/sysctl.c
++++ b/net/sunrpc/sysctl.c
+@@ -87,9 +87,8 @@ proc_dodebug(ctl_table *table, int write, struct file *file,
+ 			left--, s++;
+ 		*(unsigned int *) table->data = value;
+ 		/* Display the RPC tasks on writing to rpc_debug */
+-		if (table->ctl_name == CTL_RPCDEBUG) {
++		if (strcmp(table->procname, "rpc_debug") == 0)
+ 			rpc_show_tasks();
+-		}
+ 	} else {
+ 		if (!access_ok(VERIFY_WRITE, buffer, left))
+ 			return -EFAULT;

commit 521c2a43b2e72dd5c9ab1b1ae7f894ba8a58779d
+Author: J. Bruce Fields 
+Date:   Tue Oct 30 01:07:15 2007 -0700
+
+    [SUNRPC]: fix rpc debugging
+    
+    Commit baa3a2a0d24ebcf1c451bec8e5bee3d3467f4cbb, by removing initialization
+    of the ctl_name field, broke this conditional, preventing the display of
+    rpc_tasks that you previously got when turning on rpc debugging.
+    
+    [akpm@linux-foundation.org: coding-style fixes]
+    
+    Signed-off-by: J. Bruce Fields 
+    Acked-by: "Eric W. Biederman" 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c
+index 864b541bbf51..2be714e9b382 100644
+--- a/net/sunrpc/sysctl.c
++++ b/net/sunrpc/sysctl.c
+@@ -87,9 +87,8 @@ proc_dodebug(ctl_table *table, int write, struct file *file,
+ 			left--, s++;
+ 		*(unsigned int *) table->data = value;
+ 		/* Display the RPC tasks on writing to rpc_debug */
+-		if (table->ctl_name == CTL_RPCDEBUG) {
++		if (strcmp(table->procname, "rpc_debug") == 0)
+ 			rpc_show_tasks();
+-		}
+ 	} else {
+ 		if (!access_ok(VERIFY_WRITE, buffer, left))
+ 			return -EFAULT;

commit 321bcf92163038e2b96fd3bf9bc29f755c81d9ef
+Author: J. Bruce Fields 
+Date:   Sun Oct 21 16:41:38 2007 -0700
+
+    dcache: don't expose uninitialized memory in /proc//fd/
+    
+    Well, it's not especially important that target->d_iname get the contents
+    of dentry->d_iname, but it's important that it get initialized with
+    *something*, otherwise we're just exposing some random piece of memory to
+    anyone who reads the link at /proc//fd/ for the deleted file, when
+    it's still held open by someone.
+    
+    I've run a test program that copies a short (<36 character) name ontop of a
+    long (>=36 character) name and see that the first time I run it, without
+    this patch, I get unpredicatable results out of /proc//fd/.
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: Al Viro 
+    Cc: Christoph Hellwig 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/dcache.c b/fs/dcache.c
+index 2bb3f7ac683b..d9ca1e5ceb92 100644
+--- a/fs/dcache.c
++++ b/fs/dcache.c
+@@ -1479,6 +1479,8 @@ static void switch_names(struct dentry *dentry, struct dentry *target)
+ 			 * dentry:internal, target:external.  Steal target's
+ 			 * storage and make target internal.
+ 			 */
++			memcpy(target->d_iname, dentry->d_name.name,
++					dentry->d_name.len + 1);
+ 			dentry->d_name.name = target->d_name.name;
+ 			target->d_name.name = target->d_iname;
+ 		}

commit 5e7fc436426b1f9e106f511a049de91c82ec2c53
+Author: J. Bruce Fields 
+Date:   Tue Oct 2 14:18:12 2007 -0400
+
+    nfsd: remove IS_ISMNDLCK macro
+    
+    This macro is only used in one place; in this place it seems simpler to
+    put open-code it and move the comment to where it's used.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index 9152f87eea18..085ded6f6d3a 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -61,12 +61,6 @@
+ #define NFSDDBG_FACILITY		NFSDDBG_FILEOP
+ 
+ 
+-/* We must ignore files (but only files) which might have mandatory
+- * locks on them because there is no way to know if the accesser has
+- * the lock.
+- */
+-#define IS_ISMNDLK(i)	(S_ISREG((i)->i_mode) && mandatory_lock(i))
+-
+ /*
+  * This is a cache of readahead params that help us choose the proper
+  * readahead strategy. Initially, we set all readahead parameters to 0
+@@ -680,7 +674,12 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
+ 	err = nfserr_perm;
+ 	if (IS_APPEND(inode) && (access & MAY_WRITE))
+ 		goto out;
+-	if (IS_ISMNDLK(inode))
++	/*
++	 * We must ignore files (but only files) which might have mandatory
++	 * locks on them because there is no way to know if the accesser has
++	 * the lock.
++	 */
++	if (S_ISREG((inode)->i_mode) && mandatory_lock(inode))
+ 		goto out;
+ 
+ 	if (!inode->i_fop)

commit 98257af5a2ad0c5b502ebd07094d9fd8ce87acef
+Author: J. Bruce Fields 
+Date:   Sun Sep 30 22:18:55 2007 -0400
+
+    Documentation: move locks.txt in filesystems/
+    
+    This documentation (about file locking) belongs in filesystems/.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
+index 910473cb1c1c..cc10ce7dc339 100644
+--- a/Documentation/00-INDEX
++++ b/Documentation/00-INDEX
+@@ -230,8 +230,6 @@ local_ops.txt
+ 	- semantics and behavior of local atomic operations.
+ lockdep-design.txt
+ 	- documentation on the runtime locking correctness validator.
+-locks.txt
+-	- info on file locking implementations, flock() vs. fcntl(), etc.
+ logo.gif
+ 	- full colour GIF image of Linux logo (penguin - Tux).
+ logo.txt
+diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
+index e801076812a4..599593a17067 100644
+--- a/Documentation/filesystems/00-INDEX
++++ b/Documentation/filesystems/00-INDEX
+@@ -52,6 +52,8 @@ isofs.txt
+ 	- info and mount options for the ISO 9660 (CDROM) filesystem.
+ jfs.txt
+ 	- info and mount options for the JFS filesystem.
++locks.txt
++	- info on file locking implementations, flock() vs. fcntl(), etc.
+ mandatory-locking.txt
+ 	- info on the Linux implementation of Sys V mandatory file locking.
+ ncpfs.txt
+diff --git a/Documentation/locks.txt b/Documentation/filesystems/locks.txt
+similarity index 100%
+rename from Documentation/locks.txt
+rename to Documentation/filesystems/locks.txt

commit 9efa68ed079af97f4e9477eadef567ffe64f7afc
+Author: J. Bruce Fields 
+Date:   Tue Sep 25 11:57:19 2007 -0400
+
+    locks: add warning about mandatory locking races
+    
+    The mandatory file locking implementation has long-standing races that
+    probably render it useless.  I know of no plans to fix them.  Till we
+    do, we should at least warn people.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/Documentation/filesystems/mandatory-locking.txt b/Documentation/filesystems/mandatory-locking.txt
+index bc449d49eee5..0979d1d2ca8b 100644
+--- a/Documentation/filesystems/mandatory-locking.txt
++++ b/Documentation/filesystems/mandatory-locking.txt
+@@ -3,7 +3,26 @@
+ 		Andy Walker 
+ 
+ 			   15 April 1996
+-
++		     (Updated September 2007)
++
++0. Why you should avoid mandatory locking
++-----------------------------------------
++
++The Linux implementation is prey to a number of difficult-to-fix race
++conditions which in practice make it not dependable:
++
++	- The write system call checks for a mandatory lock only once
++	  at its start.  It is therefore possible for a lock request to
++	  be granted after this check but before the data is modified.
++	  A process may then see file data change even while a mandatory
++	  lock was held.
++	- Similarly, an exclusive lock may be granted on a file after
++	  the kernel has decided to proceed with a read, but before the
++	  read has actually completed, and the reading process may see
++	  the file data in a state which should not have been visible
++	  to it.
++	- Similar races make the claimed mutual exclusion between lock
++	  and mmap similarly unreliable.
+ 
+ 1. What is  mandatory locking?
+ ------------------------------

commit 4f3b19ca41fbe572e3d44caf516c215b286fe2a6
+Author: J. Bruce Fields 
+Date:   Mon Sep 24 18:52:09 2007 -0400
+
+    Documentation: move mandatory locking documentation to filesystems/
+    
+    Shouldn't this mandatory-locking documentation be in the
+    Documentation/filesystems directory?
+    
+    Give it a more descriptive name while we're at it, and update 00-INDEX
+    with a more inclusive description of Documentation/filesystems (which
+    has already talked about more than just individual filesystems).
+    
+    Signed-off-by: J. Bruce Fields 
+    Acked-by: Randy Dunlap 
+
+diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
+index 43e89b1537d9..910473cb1c1c 100644
+--- a/Documentation/00-INDEX
++++ b/Documentation/00-INDEX
+@@ -145,7 +145,7 @@ fb/
+ feature-removal-schedule.txt
+ 	- list of files and features that are going to be removed.
+ filesystems/
+-	- directory with info on the various filesystems that Linux supports.
++	- info on the vfs and the various filesystems that Linux supports.
+ firmware_class/
+ 	- request_firmware() hotplug interface info.
+ floppy.txt
+@@ -240,8 +240,6 @@ m68k/
+ 	- directory with info about Linux on Motorola 68k architecture.
+ magic-number.txt
+ 	- list of magic numbers used to mark/protect kernel data structures.
+-mandatory.txt
+-	- info on the Linux implementation of Sys V mandatory file locking.
+ mca.txt
+ 	- info on supporting Micro Channel Architecture (e.g. PS/2) systems.
+ md.txt
+diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
+index 59db1bca7027..e801076812a4 100644
+--- a/Documentation/filesystems/00-INDEX
++++ b/Documentation/filesystems/00-INDEX
+@@ -52,6 +52,8 @@ isofs.txt
+ 	- info and mount options for the ISO 9660 (CDROM) filesystem.
+ jfs.txt
+ 	- info and mount options for the JFS filesystem.
++mandatory-locking.txt
++	- info on the Linux implementation of Sys V mandatory file locking.
+ ncpfs.txt
+ 	- info on Novell Netware(tm) filesystem using NCP protocol.
+ ntfs.txt
+diff --git a/Documentation/mandatory.txt b/Documentation/filesystems/mandatory-locking.txt
+similarity index 100%
+rename from Documentation/mandatory.txt
+rename to Documentation/filesystems/mandatory-locking.txt
+diff --git a/Documentation/locks.txt b/Documentation/locks.txt
+index e3b402ef33bd..fab857accbd6 100644
+--- a/Documentation/locks.txt
++++ b/Documentation/locks.txt
+@@ -53,11 +53,11 @@ fcntl(), with all the problems that implies.
+ 1.3 Mandatory Locking As A Mount Option
+ ---------------------------------------
+ 
+-Mandatory locking, as described in 'Documentation/mandatory.txt' was prior
+-to this release a general configuration option that was valid for all
+-mounted filesystems. This had a number of inherent dangers, not the least
+-of which was the ability to freeze an NFS server by asking it to read a
+-file for which a mandatory lock existed.
++Mandatory locking, as described in 'Documentation/filesystems/mandatory.txt'
++was prior to this release a general configuration option that was valid for
++all mounted filesystems.  This had a number of inherent dangers, not the
++least of which was the ability to freeze an NFS server by asking it to read
++a file for which a mandatory lock existed.
+ 
+ From this release of the kernel, mandatory locking can be turned on and off
+ on a per-filesystem basis, using the mount options 'mand' and 'nomand'.

commit 02888f41e9d7fa95d1f5b2f76e0f0af6ea8198cc
+Author: J. Bruce Fields 
+Date:   Wed Sep 12 15:45:07 2007 -0400
+
+    locks: fix flock_lock_file() comment
+    
+    This comment wasn't updated when lease support was added, and it makes
+    essentially the same mistake that the code made before a recent bugfix.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/locks.c b/fs/locks.c
+index 6e22c8129a80..c7c69d29a576 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -715,8 +715,7 @@ static int posix_locks_deadlock(struct file_lock *caller_fl,
+ }
+ 
+ /* Try to create a FLOCK lock on filp. We always insert new FLOCK locks
+- * at the head of the list, but that's secret knowledge known only to
+- * flock_lock_file and posix_lock_file.
++ * after any leases, but before any posix locks.
+  *
+  * Note that if called with an FL_EXISTS argument, the caller may determine
+  * whether or not a lock was successfully freed by testing the return

commit b842e240f27678aa5d71611cddc8d17a93fb0caf
+Author: J. Bruce Fields 
+Date:   Thu May 10 19:02:07 2007 -0400
+
+    locks: reverse order of posix_locks_conflict() arguments
+    
+    The first argument to posix_locks_conflict() is meant to be a lock request,
+    and the second a lock from an inode's lock request.  It doesn't really
+    make a difference which order you call them in, since the only
+    asymmetric test in posix_lock_conflict() is the check whether the second
+    argument is a posix lock--and every caller already does that check for
+    some reason.
+    
+    But may as well fix posix_test_lock() to call posix_locks_conflict()
+    with the arguments in the same order as everywhere else.
+    
+    Signed-off-by: "J. Bruce Fields" 
+
+diff --git a/fs/locks.c b/fs/locks.c
+index c795eaaf6c4c..51bae6227c25 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -668,7 +668,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl)
+ 	for (cfl = filp->f_path.dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) {
+ 		if (!IS_POSIX(cfl))
+ 			continue;
+-		if (posix_locks_conflict(cfl, fl))
++		if (posix_locks_conflict(fl, cfl))
+ 			break;
+ 	}
+ 	if (cfl)

commit a16e92edcd0a2846455a30823e1bac964e743baa
+Author: J. Bruce Fields 
+Date:   Fri Sep 28 16:45:51 2007 -0400
+
+    knfsd: query filesystem for NFSv4 getattr of FATTR4_MAXNAME
+    
+    Without this we always return 2^32-1 as the the maximum namelength.
+    
+    Thanks to Andreas Gruenbacher for bug report and testing.
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: Andreas Gruenbacher 
+
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index 9cf900740c76..e15f2cf8ac15 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -1475,7 +1475,8 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
+ 	err = vfs_getattr(exp->ex_mnt, dentry, &stat);
+ 	if (err)
+ 		goto out_nfserr;
+-	if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL)) ||
++	if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL |
++			FATTR4_WORD0_MAXNAME)) ||
+ 	    (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE |
+ 		       FATTR4_WORD1_SPACE_TOTAL))) {
+ 		err = vfs_statfs(dentry, &statfs);
+@@ -1721,7 +1722,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
+ 	if (bmval0 & FATTR4_WORD0_MAXNAME) {
+ 		if ((buflen -= 4) < 0)
+ 			goto out_resource;
+-		WRITE32(~(u32) 0);
++		WRITE32(statfs.f_namelen);
+ 	}
+ 	if (bmval0 & FATTR4_WORD0_MAXREAD) {
+ 		if ((buflen -= 8) < 0)

commit cfdcad4da1903720b9b8c1f176e46a0ebf546be3
+Author: J. Bruce Fields 
+Date:   Wed Sep 12 20:35:15 2007 -0400
+
+    knfsd: nfsv4 delegation recall should take reference on client
+    
+    It's not enough to take a reference on the delegation object itself; we
+    need to ensure that the rpc_client won't go away just as we're about to
+    make an rpc call.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index c1cb7e009c1e..9d536a8cb379 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -486,6 +486,7 @@ nfsd4_cb_recall(struct nfs4_delegation *dp)
+ 	/* Success or failure, now we're either waiting for lease expiration
+ 	 * or deleg_return. */
+ 	dprintk("NFSD: nfs4_cb_recall: dp %p dl_flock %p dl_count %d\n",dp, dp->dl_flock, atomic_read(&dp->dl_count));
++	put_nfs4_client(clp);
+ 	nfs4_put_delegation(dp);
+ 	return;
+ }
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index e706c6961691..6f182d25793d 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1345,6 +1345,7 @@ void nfsd_break_deleg_cb(struct file_lock *fl)
+ 	 * lock) we know the server hasn't removed the lease yet, we know
+ 	 * it's safe to take a reference: */
+ 	atomic_inc(&dp->dl_count);
++	atomic_inc(&dp->dl_client->cl_count);
+ 
+ 	spin_lock(&recall_lock);
+ 	list_add_tail(&dp->dl_recall_lru, &del_recall_lru);
+@@ -1367,6 +1368,7 @@ void nfsd_break_deleg_cb(struct file_lock *fl)
+ 		printk(KERN_INFO "NFSD: Callback thread failed for "
+ 			"for client (clientid %08x/%08x)\n",
+ 			clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
++		put_nfs4_client(dp->dl_client);
+ 		nfs4_put_delegation(dp);
+ 	}
+ }

commit 1b1a9b3163a83f52ea2ac333846d4dfd2c4edd90
+Author: J. Bruce Fields 
+Date:   Wed Sep 12 08:43:59 2007 -0400
+
+    knfsd: don't shutdown callbacks until nfsv4 client is freed
+    
+    If a callback still holds a reference on the client, then it may be
+    about to perform an rpc call, so it isn't safe to call rpc_shutdown().
+    (Though rpc_shutdown() does wait for any outstanding rpc's, it can't
+    know if a new rpc is about to be issued with that client.)
+    
+    So, wait to shutdown the rpc_client until the reference count on the
+    client has gone to zero.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 48fbdac33c7c..e706c6961691 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -358,9 +358,22 @@ alloc_client(struct xdr_netobj name)
+ 	return clp;
+ }
+ 
++static void
++shutdown_callback_client(struct nfs4_client *clp)
++{
++	struct rpc_clnt *clnt = clp->cl_callback.cb_client;
++
++	/* shutdown rpc client, ending any outstanding recall rpcs */
++	if (clnt) {
++		clp->cl_callback.cb_client = NULL;
++		rpc_shutdown_client(clnt);
++	}
++}
++
+ static inline void
+ free_client(struct nfs4_client *clp)
+ {
++	shutdown_callback_client(clp);
+ 	if (clp->cl_cred.cr_group_info)
+ 		put_group_info(clp->cl_cred.cr_group_info);
+ 	kfree(clp->cl_name.data);
+@@ -374,18 +387,6 @@ put_nfs4_client(struct nfs4_client *clp)
+ 		free_client(clp);
+ }
+ 
+-static void
+-shutdown_callback_client(struct nfs4_client *clp)
+-{
+-	struct rpc_clnt *clnt = clp->cl_callback.cb_client;
+-
+-	/* shutdown rpc client, ending any outstanding recall rpcs */
+-	if (clnt) {
+-		clp->cl_callback.cb_client = NULL;
+-		rpc_shutdown_client(clnt);
+-	}
+-}
+-
+ static void
+ expire_client(struct nfs4_client *clp)
+ {
+@@ -396,8 +397,6 @@ expire_client(struct nfs4_client *clp)
+ 	dprintk("NFSD: expire_client cl_count %d\n",
+ 	                    atomic_read(&clp->cl_count));
+ 
+-	shutdown_callback_client(clp);
+-
+ 	INIT_LIST_HEAD(&reaplist);
+ 	spin_lock(&recall_lock);
+ 	while (!list_empty(&clp->cl_delegations)) {

commit 0272e1fd9f4fa8a43357c168e081744f99e67195
+Author: J. Bruce Fields 
+Date:   Wed Sep 12 18:56:12 2007 -0400
+
+    knfsd: let nfsd manage timing out its own leases
+    
+    Currently there's a race that can cause an oops in generic_setlease.
+    
+    (In detail: nfsd, when it removes a lease, does so by calling
+    vfs_setlease() with F_UNLCK and a pointer to the fl_flock field, which
+    in turn points to nfsd's existing lease; but the first thing the
+    setlease code does is call time_out_leases().  If the lease happens to
+    already be beyond the lease break time, that will free the lease and (in
+    nfsd's release_private callback) set fl_flock to NULL, leading to a NULL
+    deference soon after in vfs_setlease().)
+    
+    There are probably other things to fix here too, but it seems inherently
+    racy to allow either locks.c or nfsd to time out this lease.  Instead
+    just set the fl_break_time to 0 (preventing locks.c from ever timing out
+    this lock) and leave it up to nfsd's laundromat thread to deal with it.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 6256492b2363..48fbdac33c7c 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1354,8 +1354,12 @@ void nfsd_break_deleg_cb(struct file_lock *fl)
+ 	/* only place dl_time is set. protected by lock_kernel*/
+ 	dp->dl_time = get_seconds();
+ 
+-	/* XXX need to merge NFSD_LEASE_TIME with fs/locks.c:lease_break_time */
+-	fl->fl_break_time = jiffies + NFSD_LEASE_TIME * HZ;
++	/*
++	 * We don't want the locks code to timeout the lease for us;
++	 * we'll remove it ourself if the delegation isn't returned
++	 * in time.
++	 */
++	fl->fl_break_time = 0;
+ 
+ 	t = kthread_run(do_recall, dp, "%s", "nfs4_cb_recall");
+ 	if (IS_ERR(t)) {

commit 21fcd02be34f73bbc94db267b4db6ccd7332923d
+Author: J. Bruce Fields 
+Date:   Thu Aug 9 20:16:22 2007 -0400
+
+    svcgss: move init code into separate function
+    
+    We've let svcauth_gss_accept() get much too long and hairy.  The
+    RPC_GSS_PROC_INIT and RPC_GSS_PROC_CONTINUE_INIT cases share very little
+    with the other cases, so it's very natural to split them off into a
+    separate function.
+    
+    This will also nicely isolate the piece of code we need to parametrize
+    to authenticating gss-protected NFSv4 callbacks on behalf of the NFS
+    client.
+    
+    Signed-off-by: J. Bruce Fields 
+    Acked-by: Neil Brown 
+
+diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
+index 7da7050f06c3..73940df6c460 100644
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -631,7 +631,8 @@ svc_safe_putnetobj(struct kvec *resv, struct xdr_netobj *o)
+ 	return 0;
+ }
+ 
+-/* Verify the checksum on the header and return SVC_OK on success.
++/*
++ * Verify the checksum on the header and return SVC_OK on success.
+  * Otherwise, return SVC_DROP (in the case of a bad sequence number)
+  * or return SVC_DENIED and indicate error in authp.
+  */
+@@ -960,6 +961,78 @@ gss_write_init_verf(struct svc_rqst *rqstp, struct rsi *rsip)
+ 	return rc;
+ }
+ 
++/*
++ * Having read the cred already and found we're in the context
++ * initiation case, read the verifier and initiate (or check the results
++ * of) upcalls to userspace for help with context initiation.  If
++ * the upcall results are available, write the verifier and result.
++ * Otherwise, drop the request pending an answer to the upcall.
++ */
++static int svcauth_gss_handle_init(struct svc_rqst *rqstp,
++			struct rpc_gss_wire_cred *gc, __be32 *authp)
++{
++	struct kvec *argv = &rqstp->rq_arg.head[0];
++	struct kvec *resv = &rqstp->rq_res.head[0];
++	struct xdr_netobj tmpobj;
++	struct rsi *rsip, rsikey;
++
++	/* Read the verifier; should be NULL: */
++	*authp = rpc_autherr_badverf;
++	if (argv->iov_len < 2 * 4)
++		return SVC_DENIED;
++	if (svc_getnl(argv) != RPC_AUTH_NULL)
++		return SVC_DENIED;
++	if (svc_getnl(argv) != 0)
++		return SVC_DENIED;
++
++	/* Martial context handle and token for upcall: */
++	*authp = rpc_autherr_badcred;
++	if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0)
++		return SVC_DENIED;
++	memset(&rsikey, 0, sizeof(rsikey));
++	if (dup_netobj(&rsikey.in_handle, &gc->gc_ctx))
++		return SVC_DROP;
++	*authp = rpc_autherr_badverf;
++	if (svc_safe_getnetobj(argv, &tmpobj)) {
++		kfree(rsikey.in_handle.data);
++		return SVC_DENIED;
++	}
++	if (dup_netobj(&rsikey.in_token, &tmpobj)) {
++		kfree(rsikey.in_handle.data);
++		return SVC_DROP;
++	}
++
++	/* Perform upcall, or find upcall result: */
++	rsip = rsi_lookup(&rsikey);
++	rsi_free(&rsikey);
++	if (!rsip)
++		return SVC_DROP;
++	switch (cache_check(&rsi_cache, &rsip->h, &rqstp->rq_chandle)) {
++	case -EAGAIN:
++	case -ETIMEDOUT:
++	case -ENOENT:
++		/* No upcall result: */
++		return SVC_DROP;
++	case 0:
++		/* Got an answer to the upcall; use it: */
++		if (gss_write_init_verf(rqstp, rsip))
++			return SVC_DROP;
++		if (resv->iov_len + 4 > PAGE_SIZE)
++			return SVC_DROP;
++		svc_putnl(resv, RPC_SUCCESS);
++		if (svc_safe_putnetobj(resv, &rsip->out_handle))
++			return SVC_DROP;
++		if (resv->iov_len + 3 * 4 > PAGE_SIZE)
++			return SVC_DROP;
++		svc_putnl(resv, rsip->major_status);
++		svc_putnl(resv, rsip->minor_status);
++		svc_putnl(resv, GSS_SEQ_WIN);
++		if (svc_safe_putnetobj(resv, &rsip->out_token))
++			return SVC_DROP;
++	}
++	return SVC_COMPLETE;
++}
++
+ /*
+  * Accept an rpcsec packet.
+  * If context establishment, punt to user space
+@@ -974,11 +1047,9 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
+ 	struct kvec	*argv = &rqstp->rq_arg.head[0];
+ 	struct kvec	*resv = &rqstp->rq_res.head[0];
+ 	u32		crlen;
+-	struct xdr_netobj tmpobj;
+ 	struct gss_svc_data *svcdata = rqstp->rq_auth_data;
+ 	struct rpc_gss_wire_cred *gc;
+ 	struct rsc	*rsci = NULL;
+-	struct rsi	*rsip, rsikey;
+ 	__be32		*rpcstart;
+ 	__be32		*reject_stat = resv->iov_base + resv->iov_len;
+ 	int		ret;
+@@ -1023,30 +1094,14 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
+ 	if ((gc->gc_proc != RPC_GSS_PROC_DATA) && (rqstp->rq_proc != 0))
+ 		goto auth_err;
+ 
+-	/*
+-	 * We've successfully parsed the credential. Let's check out the
+-	 * verifier.  An AUTH_NULL verifier is allowed (and required) for
+-	 * INIT and CONTINUE_INIT requests. AUTH_RPCSEC_GSS is required for
+-	 * PROC_DATA and PROC_DESTROY.
+-	 *
+-	 * AUTH_NULL verifier is 0 (AUTH_NULL), 0 (length).
+-	 * AUTH_RPCSEC_GSS verifier is:
+-	 *   6 (AUTH_RPCSEC_GSS), length, checksum.
+-	 * checksum is calculated over rpcheader from xid up to here.
+-	 */
+ 	*authp = rpc_autherr_badverf;
+ 	switch (gc->gc_proc) {
+ 	case RPC_GSS_PROC_INIT:
+ 	case RPC_GSS_PROC_CONTINUE_INIT:
+-		if (argv->iov_len < 2 * 4)
+-			goto auth_err;
+-		if (svc_getnl(argv) != RPC_AUTH_NULL)
+-			goto auth_err;
+-		if (svc_getnl(argv) != 0)
+-			goto auth_err;
+-		break;
++		return svcauth_gss_handle_init(rqstp, gc, authp);
+ 	case RPC_GSS_PROC_DATA:
+ 	case RPC_GSS_PROC_DESTROY:
++		/* Look up the context, and check the verifier: */
+ 		*authp = rpcsec_gsserr_credproblem;
+ 		rsci = gss_svc_searchbyctx(&gc->gc_ctx);
+ 		if (!rsci)
+@@ -1067,51 +1122,6 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
+ 
+ 	/* now act upon the command: */
+ 	switch (gc->gc_proc) {
+-	case RPC_GSS_PROC_INIT:
+-	case RPC_GSS_PROC_CONTINUE_INIT:
+-		*authp = rpc_autherr_badcred;
+-		if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0)
+-			goto auth_err;
+-		memset(&rsikey, 0, sizeof(rsikey));
+-		if (dup_netobj(&rsikey.in_handle, &gc->gc_ctx))
+-			goto drop;
+-		*authp = rpc_autherr_badverf;
+-		if (svc_safe_getnetobj(argv, &tmpobj)) {
+-			kfree(rsikey.in_handle.data);
+-			goto auth_err;
+-		}
+-		if (dup_netobj(&rsikey.in_token, &tmpobj)) {
+-			kfree(rsikey.in_handle.data);
+-			goto drop;
+-		}
+-
+-		rsip = rsi_lookup(&rsikey);
+-		rsi_free(&rsikey);
+-		if (!rsip) {
+-			goto drop;
+-		}
+-		switch(cache_check(&rsi_cache, &rsip->h, &rqstp->rq_chandle)) {
+-		case -EAGAIN:
+-		case -ETIMEDOUT:
+-		case -ENOENT:
+-			goto drop;
+-		case 0:
+-			if (gss_write_init_verf(rqstp, rsip))
+-				goto drop;
+-			if (resv->iov_len + 4 > PAGE_SIZE)
+-				goto drop;
+-			svc_putnl(resv, RPC_SUCCESS);
+-			if (svc_safe_putnetobj(resv, &rsip->out_handle))
+-				goto drop;
+-			if (resv->iov_len + 3 * 4 > PAGE_SIZE)
+-				goto drop;
+-			svc_putnl(resv, rsip->major_status);
+-			svc_putnl(resv, rsip->minor_status);
+-			svc_putnl(resv, GSS_SEQ_WIN);
+-			if (svc_safe_putnetobj(resv, &rsip->out_token))
+-				goto drop;
+-		}
+-		goto complete;
+ 	case RPC_GSS_PROC_DESTROY:
+ 		if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq))
+ 			goto auth_err;
+@@ -1158,7 +1168,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
+ 		goto out;
+ 	}
+ auth_err:
+-	/* Restore write pointer to original value: */
++	/* Restore write pointer to its original value: */
+ 	xdr_ressize_check(rqstp, reject_stat);
+ 	ret = SVC_DENIED;
+ 	goto out;

commit c175b83c4c4be72535c5c12abc155e29a08323a0
+Author: J. Bruce Fields 
+Date:   Thu Aug 9 18:34:32 2007 -0400
+
+    knfsd: remove code duplication in nfsd4_setclientid()
+    
+    Each branch of this if-then-else has a bunch of duplicated code that we
+    could just put at the end.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Acked-by: Neil Brown 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 09573b9f76c7..6256492b2363 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -774,13 +774,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 		new = create_client(clname, dname);
+ 		if (new == NULL)
+ 			goto out;
+-		copy_verf(new, &clverifier);
+-		new->cl_addr = sin->sin_addr.s_addr;
+-		copy_cred(&new->cl_cred,&rqstp->rq_cred);
+ 		gen_clid(new);
+-		gen_confirm(new);
+-		gen_callback(new, setclid);
+-		add_to_unconfirmed(new, strhashval);
+ 	} else if (same_verf(&conf->cl_verifier, &clverifier)) {
+ 		/*
+ 		 * CASE 1:
+@@ -806,13 +800,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 		new = create_client(clname, dname);
+ 		if (new == NULL)
+ 			goto out;
+-		copy_verf(new,&conf->cl_verifier);
+-		new->cl_addr = sin->sin_addr.s_addr;
+-		copy_cred(&new->cl_cred,&rqstp->rq_cred);
+ 		copy_clid(new, conf);
+-		gen_confirm(new);
+-		gen_callback(new, setclid);
+-		add_to_unconfirmed(new,strhashval);
+ 	} else if (!unconf) {
+ 		/*
+ 		 * CASE 2:
+@@ -825,13 +813,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 		new = create_client(clname, dname);
+ 		if (new == NULL)
+ 			goto out;
+-		copy_verf(new,&clverifier);
+-		new->cl_addr = sin->sin_addr.s_addr;
+-		copy_cred(&new->cl_cred,&rqstp->rq_cred);
+ 		gen_clid(new);
+-		gen_confirm(new);
+-		gen_callback(new, setclid);
+-		add_to_unconfirmed(new, strhashval);
+ 	} else if (!same_verf(&conf->cl_confirm, &unconf->cl_confirm)) {
+ 		/*	
+ 		 * CASE3:
+@@ -852,19 +834,19 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 		new = create_client(clname, dname);
+ 		if (new == NULL)
+ 			goto out;
+-		copy_verf(new,&clverifier);
+-		new->cl_addr = sin->sin_addr.s_addr;
+-		copy_cred(&new->cl_cred,&rqstp->rq_cred);
+ 		gen_clid(new);
+-		gen_confirm(new);
+-		gen_callback(new, setclid);
+-		add_to_unconfirmed(new, strhashval);
+ 	} else {
+ 		/* No cases hit !!! */
+ 		status = nfserr_inval;
+ 		goto out;
+ 
+ 	}
++	copy_verf(new, &clverifier);
++	new->cl_addr = sin->sin_addr.s_addr;
++	copy_cred(&new->cl_cred, &rqstp->rq_cred);
++	gen_confirm(new);
++	gen_callback(new, setclid);
++	add_to_unconfirmed(new, strhashval);
+ 	setclid->se_clientid.cl_boot = new->cl_clientid.cl_boot;
+ 	setclid->se_clientid.cl_id = new->cl_clientid.cl_id;
+ 	memcpy(setclid->se_confirm.data, new->cl_confirm.data, sizeof(setclid->se_confirm.data));

commit e8ff2a8453cedf38d6d7a0528cb9c308066a3e3e
+Author: J. Bruce Fields 
+Date:   Wed Aug 1 15:30:59 2007 -0400
+
+    knfsd: move nfsv4 slab creation/destruction to module init/exit
+    
+    We have some slabs that the nfs4 server uses to store state objects.
+    We're currently creating and destroying those slabs whenever the server
+    is brought up or down.  That seems excessive; may as well just do that
+    in module initialization and exit.
+    
+    Also add some minor header cleanup.  (Thanks to Andrew Morton for that
+    and a compile fix.)
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Acked-by:  Neil Brown 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 2b20eb8589a0..09573b9f76c7 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1021,7 +1021,7 @@ nfsd4_free_slab(struct kmem_cache **slab)
+ 	*slab = NULL;
+ }
+ 
+-static void
++void
+ nfsd4_free_slabs(void)
+ {
+ 	nfsd4_free_slab(&stateowner_slab);
+@@ -3152,11 +3152,14 @@ nfs4_check_open_reclaim(clientid_t *clid)
+ 
+ /* initialization to perform at module load time: */
+ 
+-void
++int
+ nfs4_state_init(void)
+ {
+-	int i;
++	int i, status;
+ 
++	status = nfsd4_init_slabs();
++	if (status)
++		return status;
+ 	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
+ 		INIT_LIST_HEAD(&conf_id_hashtbl[i]);
+ 		INIT_LIST_HEAD(&conf_str_hashtbl[i]);
+@@ -3185,6 +3188,7 @@ nfs4_state_init(void)
+ 	for (i = 0; i < CLIENT_HASH_SIZE; i++)
+ 		INIT_LIST_HEAD(&reclaim_str_hashtbl[i]);
+ 	reclaim_str_hashtbl_size = 0;
++	return 0;
+ }
+ 
+ static void
+@@ -3245,20 +3249,15 @@ __nfs4_state_start(void)
+ 	set_max_delegations();
+ }
+ 
+-int
++void
+ nfs4_state_start(void)
+ {
+-	int status;
+-
+ 	if (nfs4_init)
+-		return 0;
+-	status = nfsd4_init_slabs();
+-	if (status)
+-		return status;
++		return;
+ 	nfsd4_load_reboot_recovery_data();
+ 	__nfs4_state_start();
+ 	nfs4_init = 1;
+-	return 0;
++	return;
+ }
+ 
+ int
+@@ -3316,7 +3315,6 @@ nfs4_state_shutdown(void)
+ 	nfs4_lock_state();
+ 	nfs4_release_reclaim();
+ 	__nfs4_state_shutdown();
+-	nfsd4_free_slabs();
+ 	nfs4_unlock_state();
+ }
+ 
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index baac89d917ca..d135f5f98519 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -679,11 +679,13 @@ static int __init init_nfsd(void)
+ 	int retval;
+ 	printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n");
+ 
++	retval = nfs4_state_init(); /* nfs4 locking state */
++	if (retval)
++		return retval;
+ 	nfsd_stat_init();	/* Statistics */
+ 	nfsd_cache_init();	/* RPC reply cache */
+ 	nfsd_export_init();	/* Exports table */
+ 	nfsd_lockd_init();	/* lockd->nfsd callbacks */
+-	nfs4_state_init();	/* NFSv4 locking state */
+ 	nfsd_idmap_init();      /* Name to ID mapping */
+ 	if (proc_mkdir("fs/nfs", NULL)) {
+ 		struct proc_dir_entry *entry;
+@@ -712,6 +714,7 @@ static void __exit exit_nfsd(void)
+ 	nfsd_stat_shutdown();
+ 	nfsd_lockd_shutdown();
+ 	nfsd_idmap_shutdown();
++	nfsd4_free_slabs();
+ 	unregister_filesystem(&nfsd_fs_type);
+ }
+ 
+diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
+index ef46f3228330..1190aeaa92be 100644
+--- a/fs/nfsd/nfssvc.c
++++ b/fs/nfsd/nfssvc.c
+@@ -349,9 +349,7 @@ nfsd_svc(unsigned short port, int nrservs)
+ 	error =	nfsd_racache_init(2*nrservs);
+ 	if (error<0)
+ 		goto out;
+-	error = nfs4_state_start();
+-	if (error<0)
+-		goto out;
++	nfs4_state_start();
+ 
+ 	nfsd_reset_versions();
+ 
+diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
+index e452256d3f72..604a0d786bc6 100644
+--- a/include/linux/nfsd/nfsd.h
++++ b/include/linux/nfsd/nfsd.h
+@@ -153,19 +153,21 @@ extern int nfsd_max_blksize;
+  */
+ #ifdef CONFIG_NFSD_V4
+ extern unsigned int max_delegations;
+-void nfs4_state_init(void);
+-int nfs4_state_start(void);
++int nfs4_state_init(void);
++void nfsd4_free_slabs(void);
++void nfs4_state_start(void);
+ void nfs4_state_shutdown(void);
+ time_t nfs4_lease_time(void);
+ void nfs4_reset_lease(time_t leasetime);
+ int nfs4_reset_recoverydir(char *recdir);
+ #else
+-static inline void nfs4_state_init(void){};
+-static inline int nfs4_state_start(void){return 0;}
+-static inline void nfs4_state_shutdown(void){}
+-static inline time_t nfs4_lease_time(void){return 0;}
+-static inline void nfs4_reset_lease(time_t leasetime){}
+-static inline int nfs4_reset_recoverydir(char *recdir) {return 0;}
++static inline int nfs4_state_init(void) { return 0; }
++static inline void nfsd4_free_slabs(void) { }
++static inline void nfs4_state_start(void) { }
++static inline void nfs4_state_shutdown(void) { }
++static inline time_t nfs4_lease_time(void) { return 0; }
++static inline void nfs4_reset_lease(time_t leasetime) { }
++static inline int nfs4_reset_recoverydir(char *recdir) { return 0; }
+ #endif
+ 
+ /*

commit 2b47eece1fa519a81c8b802af77a8b8aa44baa10
+Author: J. Bruce Fields 
+Date:   Fri Jul 27 18:06:50 2007 -0400
+
+    knfsd: spawn kernel thread to probe callback channel
+    
+    We want to allow gss on the callback channel, so people using krb5 can
+    still get the benefits of delegations.
+    
+    But looking up the rpc credential can take some time in that case.  And
+    we shouldn't delay the response to setclientid_confirm while we wait.
+    
+    It may be inefficient, but for now the simplest solution is just to
+    spawn a new thread as necessary for the purpose.
+    
+    (Thanks to Adrian Bunk for catching a missing static here.)
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Cc: Adrian Bunk 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 31d6633c7fe4..c17a5202ee3f 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -39,6 +39,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -365,6 +366,35 @@ nfsd4_lookupcred(struct nfs4_client *clp, int taskflags)
+         return ret;
+ }
+ 
++/* Reference counting, callback cleanup, etc., all look racy as heck.
++ * And why is cb_set an atomic? */
++
++static int do_probe_callback(void *data)
++{
++	struct nfs4_client *clp = data;
++	struct nfs4_callback *cb = &clp->cl_callback;
++	struct rpc_message msg = {
++		.rpc_proc       = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
++		.rpc_argp       = clp,
++	};
++	int status;
++
++	msg.rpc_cred = nfsd4_lookupcred(clp, 0);
++	if (IS_ERR(msg.rpc_cred))
++		goto out;
++	status = rpc_call_sync(cb->cb_client, &msg, RPC_TASK_SOFT);
++	put_rpccred(msg.rpc_cred);
++
++	if (status) {
++		rpc_shutdown_client(cb->cb_client);
++		cb->cb_client = NULL;
++	} else
++		atomic_set(&cb->cb_set, 1);
++out:
++	put_nfs4_client(clp);
++	return 0;
++}
++
+ /*
+  * Set up the callback client and put a NFSPROC4_CB_NULL on the wire...
+  */
+@@ -390,11 +420,7 @@ nfsd4_probe_callback(struct nfs4_client *clp)
+ 		.authflavor	= RPC_AUTH_UNIX,	/* XXX: need AUTH_GSS... */
+ 		.flags		= (RPC_CLNT_CREATE_NOPING),
+ 	};
+-	struct rpc_message msg = {
+-		.rpc_proc       = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
+-		.rpc_argp       = clp,
+-	};
+-	int status;
++	struct task_struct *t;
+ 
+ 	if (atomic_read(&cb->cb_set))
+ 		return;
+@@ -426,16 +452,11 @@ nfsd4_probe_callback(struct nfs4_client *clp)
+ 	/* the task holds a reference to the nfs4_client struct */
+ 	atomic_inc(&clp->cl_count);
+ 
+-	msg.rpc_cred = nfsd4_lookupcred(clp,0);
+-	if (IS_ERR(msg.rpc_cred))
+-		goto out_release_clp;
+-	status = rpc_call_async(cb->cb_client, &msg, RPC_TASK_ASYNC, &nfs4_cb_null_ops, NULL);
+-	put_rpccred(msg.rpc_cred);
++	t = kthread_run(do_probe_callback, clp, "nfs4_cb_probe");
+ 
+-	if (status != 0) {
+-		dprintk("NFSD: asynchronous NFSPROC4_CB_NULL failed!\n");
++	if (IS_ERR(t))
+ 		goto out_release_clp;
+-	}
++
+ 	return;
+ 
+ out_release_clp:
+@@ -447,30 +468,6 @@ nfsd4_probe_callback(struct nfs4_client *clp)
+ 		(int)clp->cl_name.len, clp->cl_name.data);
+ }
+ 
+-static void
+-nfs4_cb_null(struct rpc_task *task, void *dummy)
+-{
+-	struct nfs4_client *clp = (struct nfs4_client *)task->tk_msg.rpc_argp;
+-	struct nfs4_callback *cb = &clp->cl_callback;
+-	__be32 addr = htonl(cb->cb_addr);
+-
+-	dprintk("NFSD: nfs4_cb_null task->tk_status %d\n", task->tk_status);
+-
+-	if (task->tk_status < 0) {
+-		dprintk("NFSD: callback establishment to client %.*s failed\n",
+-			(int)clp->cl_name.len, clp->cl_name.data);
+-		goto out;
+-	}
+-	atomic_set(&cb->cb_set, 1);
+-	dprintk("NFSD: callback set to client %u.%u.%u.%u\n", NIPQUAD(addr));
+-out:
+-	put_nfs4_client(clp);
+-}
+-
+-static const struct rpc_call_ops nfs4_cb_null_ops = {
+-	.rpc_call_done = nfs4_cb_null,
+-};
+-
+ /*
+  * called with dp->dl_count inc'ed.
+  * nfs4_lock_state() may or may not have been called.

commit c9b6cbe56d3ac471e6cd72a59ec9e324b3417016
+Author: J. Bruce Fields 
+Date:   Fri Jul 27 16:36:45 2007 -0400
+
+    knfsd: nfs4 name->id mapping not correctly parsing negative downcall
+    
+    Note that qword_get() returns length or -1, not an -ERROR.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Acked-by:  Neil Brown 
+
+diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
+index 2ccffde81b84..4c0c683ce07a 100644
+--- a/fs/nfsd/nfs4idmap.c
++++ b/fs/nfsd/nfs4idmap.c
+@@ -207,6 +207,7 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen)
+ {
+ 	struct ent ent, *res;
+ 	char *buf1, *bp;
++	int len;
+ 	int error = -EINVAL;
+ 
+ 	if (buf[buflen - 1] != '\n')
+@@ -248,10 +249,11 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen)
+ 		goto out;
+ 
+ 	/* Name */
+-	error = qword_get(&buf, buf1, PAGE_SIZE);
+-	if (error == -EINVAL)
++	error = -EINVAL;
++	len = qword_get(&buf, buf1, PAGE_SIZE);
++	if (len < 0)
+ 		goto out;
+-	if (error == -ENOENT)
++	if (len == 0)
+ 		set_bit(CACHE_NEGATIVE, &ent.h.flags);
+ 	else {
+ 		if (error >= IDMAP_NAMESZ) {

commit 2fdada03b3876ab9f84ede160f187e888cafefb4
+Author: J. Bruce Fields 
+Date:   Fri Jul 27 16:10:37 2007 -0400
+
+    knfsd: demote some printk()s to dprintk()s
+    
+    To quote a recent mail from Andrew Morton:
+    
+            Look: if there's a way in which an unprivileged user can trigger
+            a printk we fix it, end of story.
+    
+    OK.  I assume that goes double for printk()s that might be triggered by
+    random hosts on the internet.  So, disable some printk()s that look like
+    they could be triggered by malfunctioning or malicious clients.  For
+    now, just downgrade them to dprintk()s.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Acked-by:  Neil Brown 
+
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index 29b7e63cb32c..18ead1790bb3 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -238,12 +238,12 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 			break;
+              	case NFS4_OPEN_CLAIM_DELEGATE_PREV:
+ 			open->op_stateowner->so_confirmed = 1;
+-			printk("NFSD: unsupported OPEN claim type %d\n",
++			dprintk("NFSD: unsupported OPEN claim type %d\n",
+ 				open->op_claim_type);
+ 			status = nfserr_notsupp;
+ 			goto out;
+ 		default:
+-			printk("NFSD: Invalid OPEN claim type %d\n",
++			dprintk("NFSD: Invalid OPEN claim type %d\n",
+ 				open->op_claim_type);
+ 			status = nfserr_inval;
+ 			goto out;
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 578d809e85ec..2b20eb8589a0 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -509,7 +509,7 @@ check_name(struct xdr_netobj name) {
+ 	if (name.len == 0) 
+ 		return 0;
+ 	if (name.len > NFS4_OPAQUE_LIMIT) {
+-		printk("NFSD: check_name: name too long(%d)!\n", name.len);
++		dprintk("NFSD: check_name: name too long(%d)!\n", name.len);
+ 		return 0;
+ 	}
+ 	return 1;
+@@ -1742,7 +1742,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
+ 	if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS
+ 			&& flag == NFS4_OPEN_DELEGATE_NONE
+ 			&& open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE)
+-		printk("NFSD: WARNING: refusing delegation reclaim\n");
++		dprintk("NFSD: WARNING: refusing delegation reclaim\n");
+ 	open->op_delegate_type = flag;
+ }
+ 
+@@ -2151,7 +2151,7 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
+ 	*sopp = NULL;
+ 
+ 	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) {
+-		printk("NFSD: preprocess_seqid_op: magic stateid!\n");
++		dprintk("NFSD: preprocess_seqid_op: magic stateid!\n");
+ 		return nfserr_bad_stateid;
+ 	}
+ 
+@@ -2202,7 +2202,7 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
+ 	}
+ 
+ 	if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) {
+-		printk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n");
++		dprintk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n");
+ 		return nfserr_bad_stateid;
+ 	}
+ 
+@@ -2218,22 +2218,22 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
+ 		goto check_replay;
+ 
+ 	if (sop->so_confirmed && flags & CONFIRM) {
+-		printk("NFSD: preprocess_seqid_op: expected"
++		dprintk("NFSD: preprocess_seqid_op: expected"
+ 				" unconfirmed stateowner!\n");
+ 		return nfserr_bad_stateid;
+ 	}
+ 	if (!sop->so_confirmed && !(flags & CONFIRM)) {
+-		printk("NFSD: preprocess_seqid_op: stateowner not"
++		dprintk("NFSD: preprocess_seqid_op: stateowner not"
+ 				" confirmed yet!\n");
+ 		return nfserr_bad_stateid;
+ 	}
+ 	if (stateid->si_generation > stp->st_stateid.si_generation) {
+-		printk("NFSD: preprocess_seqid_op: future stateid?!\n");
++		dprintk("NFSD: preprocess_seqid_op: future stateid?!\n");
+ 		return nfserr_bad_stateid;
+ 	}
+ 
+ 	if (stateid->si_generation < stp->st_stateid.si_generation) {
+-		printk("NFSD: preprocess_seqid_op: old stateid!\n");
++		dprintk("NFSD: preprocess_seqid_op: old stateid!\n");
+ 		return nfserr_old_stateid;
+ 	}
+ 	renew_client(sop->so_client);
+@@ -2245,7 +2245,7 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
+ 		/* indicate replay to calling function */
+ 		return nfserr_replay_me;
+ 	}
+-	printk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d)\n",
++	dprintk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d)\n",
+ 			sop->so_seqid, seqid);
+ 	*sopp = NULL;
+ 	return nfserr_bad_seqid;
+@@ -2858,7 +2858,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 			file_lock.fl_type = F_WRLCK;
+ 		break;
+ 		default:
+-			printk("NFSD: nfs4_lockt: bad lock type!\n");
++			dprintk("NFSD: nfs4_lockt: bad lock type!\n");
+ 			status = nfserr_inval;
+ 		goto out;
+ 	}

commit 599e0a2290b22d959c7748bda83da3614187a299
+Author: J. Bruce Fields 
+Date:   Thu Jul 26 17:04:54 2007 -0400
+
+    knfsd: cleanup of nfsd4 cmp_* functions
+    
+    Benny Halevy suggested renaming cmp_* to same_* to make the meaning of
+    the return value clearer.
+    
+    Fix some nearby style deviations while we're at it, including a small
+    swath of creative indentation in nfs4_preprocess_seqid_op().
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Acked-by:  Neil Brown 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 3f559700788f..578d809e85ec 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -462,26 +462,28 @@ copy_cred(struct svc_cred *target, struct svc_cred *source) {
+ }
+ 
+ static inline int
+-same_name(const char *n1, const char *n2) {
++same_name(const char *n1, const char *n2)
++{
+ 	return 0 == memcmp(n1, n2, HEXDIR_LEN);
+ }
+ 
+ static int
+-cmp_verf(nfs4_verifier *v1, nfs4_verifier *v2) {
+-	return(!memcmp(v1->data,v2->data,sizeof(v1->data)));
++same_verf(nfs4_verifier *v1, nfs4_verifier *v2)
++{
++	return 0 == memcmp(v1->data, v2->data, sizeof(v1->data));
+ }
+ 
+ static int
+-cmp_clid(clientid_t * cl1, clientid_t * cl2) {
+-	return((cl1->cl_boot == cl2->cl_boot) &&
+-	   	(cl1->cl_id == cl2->cl_id));
++same_clid(clientid_t *cl1, clientid_t *cl2)
++{
++	return (cl1->cl_boot == cl2->cl_boot) && (cl1->cl_id == cl2->cl_id);
+ }
+ 
+ /* XXX what about NGROUP */
+ static int
+-cmp_creds(struct svc_cred *cr1, struct svc_cred *cr2){
+-	return(cr1->cr_uid == cr2->cr_uid);
+-
++same_creds(struct svc_cred *cr1, struct svc_cred *cr2)
++{
++	return cr1->cr_uid == cr2->cr_uid;
+ }
+ 
+ static void
+@@ -546,7 +548,7 @@ find_confirmed_client(clientid_t *clid)
+ 	unsigned int idhashval = clientid_hashval(clid->cl_id);
+ 
+ 	list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) {
+-		if (cmp_clid(&clp->cl_clientid, clid))
++		if (same_clid(&clp->cl_clientid, clid))
+ 			return clp;
+ 	}
+ 	return NULL;
+@@ -559,7 +561,7 @@ find_unconfirmed_client(clientid_t *clid)
+ 	unsigned int idhashval = clientid_hashval(clid->cl_id);
+ 
+ 	list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) {
+-		if (cmp_clid(&clp->cl_clientid, clid))
++		if (same_clid(&clp->cl_clientid, clid))
+ 			return clp;
+ 	}
+ 	return NULL;
+@@ -753,7 +755,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 		 * or different ip_address
+ 		 */
+ 		status = nfserr_clid_inuse;
+-		if (!cmp_creds(&conf->cl_cred, &rqstp->rq_cred)
++		if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)
+ 				|| conf->cl_addr != sin->sin_addr.s_addr) {
+ 			dprintk("NFSD: setclientid: string in use by client"
+ 				"at %u.%u.%u.%u\n", NIPQUAD(conf->cl_addr));
+@@ -779,7 +781,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 		gen_confirm(new);
+ 		gen_callback(new, setclid);
+ 		add_to_unconfirmed(new, strhashval);
+-	} else if (cmp_verf(&conf->cl_verifier, &clverifier)) {
++	} else if (same_verf(&conf->cl_verifier, &clverifier)) {
+ 		/*
+ 		 * CASE 1:
+ 		 * cl_name match, confirmed, principal match
+@@ -830,7 +832,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 		gen_confirm(new);
+ 		gen_callback(new, setclid);
+ 		add_to_unconfirmed(new, strhashval);
+-	} else if (!cmp_verf(&conf->cl_confirm, &unconf->cl_confirm)) {
++	} else if (!same_verf(&conf->cl_confirm, &unconf->cl_confirm)) {
+ 		/*	
+ 		 * CASE3:
+ 		 * confirmed found (name, principal match)
+@@ -910,16 +912,16 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+ 		goto out;
+ 
+ 	if ((conf && unconf) && 
+-	    (cmp_verf(&unconf->cl_confirm, &confirm)) &&
+-	    (cmp_verf(&conf->cl_verifier, &unconf->cl_verifier)) &&
++	    (same_verf(&unconf->cl_confirm, &confirm)) &&
++	    (same_verf(&conf->cl_verifier, &unconf->cl_verifier)) &&
+ 	    (same_name(conf->cl_recdir,unconf->cl_recdir))  &&
+-	    (!cmp_verf(&conf->cl_confirm, &unconf->cl_confirm))) {
++	    (!same_verf(&conf->cl_confirm, &unconf->cl_confirm))) {
+ 		/* CASE 1:
+ 		* unconf record that matches input clientid and input confirm.
+ 		* conf record that matches input clientid.
+ 		* conf and unconf records match names, verifiers
+ 		*/
+-		if (!cmp_creds(&conf->cl_cred, &unconf->cl_cred)) 
++		if (!same_creds(&conf->cl_cred, &unconf->cl_cred))
+ 			status = nfserr_clid_inuse;
+ 		else {
+ 			/* XXX: We just turn off callbacks until we can handle
+@@ -933,7 +935,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+ 		}
+ 	} else if ((conf && !unconf) ||
+ 	    ((conf && unconf) && 
+-	     (!cmp_verf(&conf->cl_verifier, &unconf->cl_verifier) ||
++	     (!same_verf(&conf->cl_verifier, &unconf->cl_verifier) ||
+ 	      !same_name(conf->cl_recdir, unconf->cl_recdir)))) {
+ 		/* CASE 2:
+ 		 * conf record that matches input clientid.
+@@ -941,18 +943,18 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+ 		 * unconf->cl_name or unconf->cl_verifier don't match the
+ 		 * conf record.
+ 		 */
+-		if (!cmp_creds(&conf->cl_cred,&rqstp->rq_cred))
++		if (!same_creds(&conf->cl_cred, &rqstp->rq_cred))
+ 			status = nfserr_clid_inuse;
+ 		else
+ 			status = nfs_ok;
+ 	} else if (!conf && unconf
+-			&& cmp_verf(&unconf->cl_confirm, &confirm)) {
++			&& same_verf(&unconf->cl_confirm, &confirm)) {
+ 		/* CASE 3:
+ 		 * conf record not found.
+ 		 * unconf record found.
+ 		 * unconf->cl_confirm matches input confirm
+ 		 */
+-		if (!cmp_creds(&unconf->cl_cred, &rqstp->rq_cred)) {
++		if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred)) {
+ 			status = nfserr_clid_inuse;
+ 		} else {
+ 			unsigned int hash =
+@@ -967,8 +969,8 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+ 			conf = unconf;
+ 			status = nfs_ok;
+ 		}
+-	} else if ((!conf || (conf && !cmp_verf(&conf->cl_confirm, &confirm)))
+-	    && (!unconf || (unconf && !cmp_verf(&unconf->cl_confirm,
++	} else if ((!conf || (conf && !same_verf(&conf->cl_confirm, &confirm)))
++	    && (!unconf || (unconf && !same_verf(&unconf->cl_confirm,
+ 				    				&confirm)))) {
+ 		/* CASE 4:
+ 		 * conf record not found, or if conf, conf->cl_confirm does not
+@@ -1207,10 +1209,12 @@ move_to_close_lru(struct nfs4_stateowner *sop)
+ }
+ 
+ static int
+-cmp_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner, clientid_t *clid) {
+-	return ((sop->so_owner.len == owner->len) && 
+-	 !memcmp(sop->so_owner.data, owner->data, owner->len) && 
+-	  (sop->so_client->cl_clientid.cl_id == clid->cl_id));
++same_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner,
++							clientid_t *clid)
++{
++	return (sop->so_owner.len == owner->len) &&
++		0 == memcmp(sop->so_owner.data, owner->data, owner->len) &&
++		(sop->so_client->cl_clientid.cl_id == clid->cl_id);
+ }
+ 
+ static struct nfs4_stateowner *
+@@ -1219,7 +1223,7 @@ find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open)
+ 	struct nfs4_stateowner *so = NULL;
+ 
+ 	list_for_each_entry(so, &ownerstr_hashtbl[hashval], so_strhash) {
+-		if (cmp_owner_str(so, &open->op_owner, &open->op_clientid))
++		if (same_owner_str(so, &open->op_owner, &open->op_clientid))
+ 			return so;
+ 	}
+ 	return NULL;
+@@ -2181,21 +2185,20 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
+ 		lkflg = setlkflg(lock->lk_type);
+ 
+ 		if (lock->lk_is_new) {
+-                       if (!sop->so_is_open_owner)
+-			       return nfserr_bad_stateid;
+-                       if (!cmp_clid(&clp->cl_clientid, lockclid))
++			if (!sop->so_is_open_owner)
++				return nfserr_bad_stateid;
++			if (!same_clid(&clp->cl_clientid, lockclid))
+ 			       return nfserr_bad_stateid;
+-                       /* stp is the open stateid */
+-                       status = nfs4_check_openmode(stp, lkflg);
+-                       if (status)
+-			       return status;
+-               } else {
+-                       /* stp is the lock stateid */
+-                       status = nfs4_check_openmode(stp->st_openstp, lkflg);
+-                       if (status)
+-			       return status;
++			/* stp is the open stateid */
++			status = nfs4_check_openmode(stp, lkflg);
++			if (status)
++				return status;
++		} else {
++			/* stp is the lock stateid */
++			status = nfs4_check_openmode(stp->st_openstp, lkflg);
++			if (status)
++				return status;
+                }
+-
+ 	}
+ 
+ 	if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) {
+@@ -2561,7 +2564,7 @@ find_lockstateowner_str(struct inode *inode, clientid_t *clid,
+ 	struct nfs4_stateowner *op;
+ 
+ 	list_for_each_entry(op, &lock_ownerstr_hashtbl[hashval], so_strhash) {
+-		if (cmp_owner_str(op, owner, clid))
++		if (same_owner_str(op, owner, clid))
+ 			return op;
+ 	}
+ 	return NULL;
+@@ -3025,7 +3028,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
+ 	INIT_LIST_HEAD(&matches);
+ 	for (i = 0; i < LOCK_HASH_SIZE; i++) {
+ 		list_for_each_entry(sop, &lock_ownerid_hashtbl[i], so_idhash) {
+-			if (!cmp_owner_str(sop, owner, clid))
++			if (!same_owner_str(sop, owner, clid))
+ 				continue;
+ 			list_for_each_entry(stp, &sop->so_stateids,
+ 					st_perstateowner) {

commit 3b398f0ef8db6a9bb431474afd871f4295203d2d
+Author: J. Bruce Fields 
+Date:   Tue Jul 24 21:38:18 2007 -0400
+
+    knfsd: delete code made redundant by map_new_errors
+    
+    I moved this check into map_new_errors, but forgot to delete the
+    original.  Oops.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Acked-by:  Neil Brown 
+
+diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
+index 221eeaa68a2d..ef46f3228330 100644
+--- a/fs/nfsd/nfssvc.c
++++ b/fs/nfsd/nfssvc.c
+@@ -546,8 +546,6 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
+ 	/* Now call the procedure handler, and encode NFS status. */
+ 	nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp);
+ 	nfserr = map_new_errors(rqstp->rq_vers, nfserr);
+-	if (nfserr == nfserr_jukebox && rqstp->rq_vers == 2)
+-		nfserr = nfserr_dropit;
+ 	if (nfserr == nfserr_dropit) {
+ 		dprintk("nfsd: Dropping request; may be revisited later\n");
+ 		nfsd_cache_update(rqstp, RC_NOCACHE, NULL);

commit dca1dd30ce0a6234acc751bb90efba1b49079669
+Author: J. Bruce Fields 
+Date:   Thu Jul 12 15:30:32 2007 -0400
+
+    nfsd: remove unused cache_for_each macro
+    
+    This macro is unused.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Acked-by:  Neil Brown 
+
+diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h
+index 3699dff7db8f..bd7a6b0a87af 100644
+--- a/include/linux/sunrpc/cache.h
++++ b/include/linux/sunrpc/cache.h
+@@ -136,16 +136,6 @@ sunrpc_cache_update(struct cache_detail *detail,
+ 		    struct cache_head *new, struct cache_head *old, int hash);
+ 
+ 
+-#define cache_for_each(pos, detail, index, member) 						\
+-	for (({read_lock(&(detail)->hash_lock); index = (detail)->hash_size;}) ;		\
+-	     ({if (index==0)read_unlock(&(detail)->hash_lock); index--;});			\
+-		)										\
+-		for (pos = container_of((detail)->hash_table[index], typeof(*pos), member);	\
+-		     &pos->member;								\
+-		     pos = container_of(pos->member.next, typeof(*pos), member))
+-
+-	     
+-
+ extern void cache_clean_deferred(void *owner);
+ 
+ static inline struct cache_head  *cache_get(struct cache_head *h)

commit 45457e0916f8253691a44d3574949b6d3d5872b1
+Author: J. Bruce Fields 
+Date:   Fri Jun 22 17:26:32 2007 -0400
+
+    nfsd: tone down inaccurate dprintk
+    
+    The nfserr_dropit happens routinely on upcalls (so a kmalloc failure is
+    almost never the actual cause), but I occasionally get a complant from
+    some tester that's worried because they ran across this message after
+    turning on debugging to research some unrelated problem.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Acked-by:  Neil Brown 
+
+diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
+index a8c89ae4c743..221eeaa68a2d 100644
+--- a/fs/nfsd/nfssvc.c
++++ b/fs/nfsd/nfssvc.c
+@@ -549,7 +549,7 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
+ 	if (nfserr == nfserr_jukebox && rqstp->rq_vers == 2)
+ 		nfserr = nfserr_dropit;
+ 	if (nfserr == nfserr_dropit) {
+-		dprintk("nfsd: Dropping request due to malloc failure!\n");
++		dprintk("nfsd: Dropping request; may be revisited later\n");
+ 		nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
+ 		return 0;
+ 	}

commit afde94f398b62c8596a8d0cbfc25798f0b52a371
+Author: J. Bruce Fields 
+Date:   Wed Sep 26 14:38:08 2007 -0400
+
+    SUNRPC: Fix default hostname created in rpc_create()
+    
+    Since 43780b87fa7..., rpc_create() fills in a default hostname based on
+    the ip address if the servername passed in is null.  A small typo made
+    that default incorrect.  (But this information appears to be used only
+    for debugging right now, so I don't believe the typo causes any bugs in
+    the current kernel.)
+    
+    Thanks to Olga Kornievskaia for bug report and testing.
+    
+    Signed-off-by: J. Bruce Fields 
+    Cc: Olga Kornievskaia 
+    Cc: Chuck Lever 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
+index 6cdf53c489b7..e9866fc93df1 100644
+--- a/net/sunrpc/clnt.c
++++ b/net/sunrpc/clnt.c
+@@ -259,7 +259,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
+ 	 */
+ 	if (args->servername == NULL) {
+ 		struct sockaddr_in *addr =
+-					(struct sockaddr_in *) &args->address;
++					(struct sockaddr_in *) args->address;
+ 		snprintf(servername, sizeof(servername), NIPQUAD_FMT,
+ 			NIPQUAD(addr->sin_addr.s_addr));
+ 		args->servername = servername;

commit bf19aacecbeebccb2c3d150a8bd9416b7dba81fe
+Author: J. Bruce Fields 
+Date:   Wed Sep 26 14:38:09 2007 -0400
+
+    nfs: add server port to rpc_pipe info file
+    
+    On the client, when an alternate server port is specified on the mount
+    commandline, we need to make sure gssd knows about it.
+    
+    Also, on the server side, when we're sending krb5 callbacks to the
+    client, we'll use the same mechanism to let gssd know about the callback
+    port.
+    
+    Thanks to Olga Kornievskaia for testing and for an earlier
+    implementation.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Cc: Olga Kornievskaia 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
+index ae83ac84f63b..c8433e8865aa 100644
+--- a/net/sunrpc/rpc_pipe.c
++++ b/net/sunrpc/rpc_pipe.c
+@@ -329,6 +329,7 @@ rpc_show_info(struct seq_file *m, void *v)
+ 			clnt->cl_prog, clnt->cl_vers);
+ 	seq_printf(m, "address: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR));
+ 	seq_printf(m, "protocol: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PROTO));
++	seq_printf(m, "port: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PORT));
+ 	return 0;
+ }
+ 

commit 9700382c3c9ff3e673e587084d76eedb3ba88668
+Author: david m. richter 
+Date:   Tue Jul 31 00:39:12 2007 -0700
+
+    VFS: fix a race in lease-breaking during truncate
+    
+    It is possible that another process could acquire a new file lease right
+    after break_lease() is called during a truncate, but before lease-granting
+    is disabled by the subsequent get_write_access().  Merely switching the
+    order of the break_lease() and get_write_access() calls prevents this race.
+    
+    Signed-off-by: David M. Richter 
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/open.c b/fs/open.c
+index e27c205364d3..1d9e5e98bf4e 100644
+--- a/fs/open.c
++++ b/fs/open.c
+@@ -256,24 +256,26 @@ static long do_sys_truncate(const char __user * path, loff_t length)
+ 	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+ 		goto dput_and_out;
+ 
+-	/*
+-	 * Make sure that there are no leases.
+-	 */
+-	error = break_lease(inode, FMODE_WRITE);
++	error = get_write_access(inode);
+ 	if (error)
+ 		goto dput_and_out;
+ 
+-	error = get_write_access(inode);
++	/*
++	 * Make sure that there are no leases.  get_write_access() protects
++	 * against the truncate racing with a lease-granting setlease().
++	 */
++	error = break_lease(inode, FMODE_WRITE);
+ 	if (error)
+-		goto dput_and_out;
++		goto put_write_and_out;
+ 
+ 	error = locks_verify_truncate(inode, NULL, length);
+ 	if (!error) {
+ 		DQUOT_INIT(inode);
+ 		error = do_truncate(nd.dentry, length, 0, NULL);
+ 	}
+-	put_write_access(inode);
+ 
++put_write_and_out:
++	put_write_access(inode);
+ dput_and_out:
+ 	path_release(&nd);
+ out:

commit 4a4b88317aa02c82e66e37debb764d4ff3eedd70
+Author: J. Bruce Fields 
+Date:   Tue Jul 31 00:37:53 2007 -0700
+
+    knfsd: eliminate unnecessary -ENOENT returns on export downcalls
+    
+    A succesful downcall with a negative result (which indicates that the given
+    filesystem is not exported to the given user) should not return an error.
+    
+    Currently mountd is depending on stdio to write these downcalls.  With some
+    versions of libc this appears to cause subsequent writes to attempt to write
+    all accumulated data (for which writes previously failed) along with any new
+    data.  This can prevent the kernel from seeing responses to later downcalls.
+    Symptoms will be that nfsd fails to respond to certain requests.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Cc: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
+index 2d295dda4c1d..cba899a3494e 100644
+--- a/fs/nfsd/export.c
++++ b/fs/nfsd/export.c
+@@ -564,9 +564,10 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
+ 
+ 	/* flags */
+ 	err = get_int(&mesg, &an_int);
+-	if (err == -ENOENT)
++	if (err == -ENOENT) {
++		err = 0;
+ 		set_bit(CACHE_NEGATIVE, &exp.h.flags);
+-	else {
++	} else {
+ 		if (err || an_int < 0) goto out;	
+ 		exp.ex_flags= an_int;
+ 	

commit 0a725fc4d3bfc4734164863d6c50208b109ca5c7
+Author: J. Bruce Fields 
+Date:   Tue Jul 31 00:37:52 2007 -0700
+
+    nfsd4: idmap upcalls should use unsigned uid and gid
+    
+    We shouldn't be using negative uid's and gid's in the idmap upcalls.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Cc: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
+index 2cf9a9a2d89c..2ccffde81b84 100644
+--- a/fs/nfsd/nfs4idmap.c
++++ b/fs/nfsd/nfs4idmap.c
+@@ -138,7 +138,7 @@ idtoname_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
+ 	char idstr[11];
+ 
+ 	qword_add(bpp, blen, ent->authname);
+-	snprintf(idstr, sizeof(idstr), "%d", ent->id);
++	snprintf(idstr, sizeof(idstr), "%u", ent->id);
+ 	qword_add(bpp, blen, ent->type == IDMAP_TYPE_GROUP ? "group" : "user");
+ 	qword_add(bpp, blen, idstr);
+ 
+@@ -165,7 +165,7 @@ idtoname_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
+ 		return 0;
+ 	}
+ 	ent = container_of(h, struct ent, h);
+-	seq_printf(m, "%s %s %d", ent->authname,
++	seq_printf(m, "%s %s %u", ent->authname,
+ 			ent->type == IDMAP_TYPE_GROUP ? "group" : "user",
+ 			ent->id);
+ 	if (test_bit(CACHE_VALID, &h->flags))
+@@ -349,7 +349,7 @@ nametoid_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
+ 			ent->type == IDMAP_TYPE_GROUP ? "group" : "user",
+ 			ent->name);
+ 	if (test_bit(CACHE_VALID, &h->flags))
+-		seq_printf(m, " %d", ent->id);
++		seq_printf(m, " %u", ent->id);
+ 	seq_printf(m, "\n");
+ 	return 0;
+ }

commit cb276805803b8e0616159d80a441ab26a931ada4
+Author: J. Bruce Fields 
+Date:   Mon Jul 23 18:43:52 2007 -0700
+
+    nfsd: fix possible oops on re-insertion of rpcsec_gss modules
+    
+    The handling of the re-registration case is wrong here; the "test" that was
+    returned from auth_domain_lookup will not be used again, so that reference
+    should be put.  And auth_domain_lookup never did anything with "new" in
+    this case, so we should just clean it up ourself.
+    
+    Thanks to Akinobu Mita for bug report, analysis, and testing.
+    
+    Cc: Akinobu Mita 
+    Signed-off-by: "J. Bruce Fields" 
+    Cc: Neil Brown 
+    Cc: Trond Myklebust 
+    Cc: 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
+index 490697542fc2..dc2f41e9f577 100644
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -769,11 +769,12 @@ svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name)
+ 	new->h.flavour = &svcauthops_gss;
+ 	new->pseudoflavor = pseudoflavor;
+ 
++	stat = 0;
+ 	test = auth_domain_lookup(name, &new->h);
+-	if (test != &new->h) { /* XXX Duplicate registration? */
+-		auth_domain_put(&new->h);
+-		/* dangling ref-count... */
+-		goto out;
++	if (test != &new->h) { /* Duplicate registration */
++		auth_domain_put(test);
++		kfree(new->h.name);
++		goto out_free_dom;
+ 	}
+ 	return 0;
+ 

commit 3e63516c826454c964eefdd24d33e188064c6679
+Author: J. Bruce Fields 
+Date:   Sat Jul 21 04:37:30 2007 -0700
+
+    knfsd: fix typo in export display, print uid and gid as unsigned
+    
+    For display purposes, treat uid's and gid's as unsigned ints for now.
+    Also fix a typo.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Cc: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
+index 6ab8de40904c..2d295dda4c1d 100644
+--- a/fs/nfsd/export.c
++++ b/fs/nfsd/export.c
+@@ -1503,9 +1503,9 @@ static void exp_flags(struct seq_file *m, int flag, int fsid,
+ 	if (flag & NFSEXP_FSID)
+ 		seq_printf(m, ",fsid=%d", fsid);
+ 	if (anonu != (uid_t)-2 && anonu != (0x10000-2))
+-		seq_printf(m, ",sanonuid=%d", anonu);
++		seq_printf(m, ",anonuid=%u", anonu);
+ 	if (anong != (gid_t)-2 && anong != (0x10000-2))
+-		seq_printf(m, ",sanongid=%d", anong);
++		seq_printf(m, ",anongid=%u", anong);
+ 	if (fsloc && fsloc->locations_count > 0) {
+ 		char *loctype = (fsloc->migrated) ? "refer" : "replicas";
+ 		int i;

commit be879c4e249a8875d7129f3b0c1bb62584dafbd8
+Author: J. Bruce Fields 
+Date:   Wed Jul 11 18:39:02 2007 -0400
+
+    SUNRPC: move bkl locking and xdr proc invocation into a common helper
+    
+    Since every invocation of xdr encode or decode functions takes the BKL now,
+    there's a lot of redundant lock_kernel/unlock_kernel pairs that we can pull
+    out into a common function.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
+index 9e340fa23c06..c6b53d181bfa 100644
+--- a/include/linux/sunrpc/xdr.h
++++ b/include/linux/sunrpc/xdr.h
+@@ -12,6 +12,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ /*
+  * Buffer adjustment
+@@ -35,6 +36,21 @@ struct xdr_netobj {
+  */
+ typedef int	(*kxdrproc_t)(void *rqstp, __be32 *data, void *obj);
+ 
++/*
++ * We're still requiring the BKL in the xdr code until it's been
++ * more carefully audited, at which point this wrapper will become
++ * unnecessary.
++ */
++static inline int rpc_call_xdrproc(kxdrproc_t xdrproc, void *rqstp, __be32 *data, void *obj)
++{
++	int ret;
++
++	lock_kernel();
++	ret = xdrproc(rqstp, data, obj);
++	unlock_kernel();
++	return ret;
++}
++
+ /*
+  * Basic structure for transmission/reception of a client XDR message.
+  * Features a header (for a linear buffer containing RPC headers
+diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
+index 29a8ecc60928..1ea27559b1de 100644
+--- a/net/sunrpc/auth.c
++++ b/net/sunrpc/auth.c
+@@ -13,7 +13,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ 
+ #ifdef RPC_DEBUG
+ # define RPCDBG_FACILITY	RPCDBG_AUTH
+@@ -476,17 +475,13 @@ rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp,
+ 		__be32 *data, void *obj)
+ {
+ 	struct rpc_cred *cred = task->tk_msg.rpc_cred;
+-	int ret;
+ 
+ 	dprintk("RPC: %5u using %s cred %p to wrap rpc data\n",
+ 			task->tk_pid, cred->cr_ops->cr_name, cred);
+ 	if (cred->cr_ops->crwrap_req)
+ 		return cred->cr_ops->crwrap_req(task, encode, rqstp, data, obj);
+ 	/* By default, we encode the arguments normally. */
+-	lock_kernel();
+-	ret = encode(rqstp, data, obj);
+-	unlock_kernel();
+-	return ret;
++	return rpc_call_xdrproc(encode, rqstp, data, obj);
+ }
+ 
+ int
+@@ -494,7 +489,6 @@ rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp,
+ 		__be32 *data, void *obj)
+ {
+ 	struct rpc_cred *cred = task->tk_msg.rpc_cred;
+-	int ret;
+ 
+ 	dprintk("RPC: %5u using %s cred %p to unwrap rpc data\n",
+ 			task->tk_pid, cred->cr_ops->cr_name, cred);
+@@ -502,10 +496,7 @@ rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp,
+ 		return cred->cr_ops->crunwrap_resp(task, decode, rqstp,
+ 						   data, obj);
+ 	/* By default, we decode the arguments normally. */
+-	lock_kernel();
+-	ret = decode(rqstp, data, obj);
+-	unlock_kernel();
+-	return ret;
++	return rpc_call_xdrproc(decode, rqstp, data, obj);
+ }
+ 
+ int
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index abfda33bac64..4bbc59cc237c 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -43,7 +43,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ #include 
+ #include 
+ #include 
+@@ -1000,9 +999,7 @@ gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
+ 	offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base;
+ 	*p++ = htonl(rqstp->rq_seqno);
+ 
+-	lock_kernel();
+-	status = encode(rqstp, p, obj);
+-	unlock_kernel();
++	status = rpc_call_xdrproc(encode, rqstp, p, obj);
+ 	if (status)
+ 		return status;
+ 
+@@ -1096,9 +1093,7 @@ gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
+ 	offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base;
+ 	*p++ = htonl(rqstp->rq_seqno);
+ 
+-	lock_kernel();
+-	status = encode(rqstp, p, obj);
+-	unlock_kernel();
++	status = rpc_call_xdrproc(encode, rqstp, p, obj);
+ 	if (status)
+ 		return status;
+ 
+@@ -1157,16 +1152,12 @@ gss_wrap_req(struct rpc_task *task,
+ 		/* The spec seems a little ambiguous here, but I think that not
+ 		 * wrapping context destruction requests makes the most sense.
+ 		 */
+-		lock_kernel();
+-		status = encode(rqstp, p, obj);
+-		unlock_kernel();
++		status = rpc_call_xdrproc(encode, rqstp, p, obj);
+ 		goto out;
+ 	}
+ 	switch (gss_cred->gc_service) {
+ 		case RPC_GSS_SVC_NONE:
+-			lock_kernel();
+-			status = encode(rqstp, p, obj);
+-			unlock_kernel();
++			status = rpc_call_xdrproc(encode, rqstp, p, obj);
+ 			break;
+ 		case RPC_GSS_SVC_INTEGRITY:
+ 			status = gss_wrap_req_integ(cred, ctx, encode,
+@@ -1282,9 +1273,7 @@ gss_unwrap_resp(struct rpc_task *task,
+ 	cred->cr_auth->au_rslack = cred->cr_auth->au_verfsize + (p - savedp)
+ 						+ (savedlen - head->iov_len);
+ out_decode:
+-	lock_kernel();
+-	status = decode(rqstp, p, obj);
+-	unlock_kernel();
++	status = rpc_call_xdrproc(decode, rqstp, p, obj);
+ out:
+ 	gss_put_ctx(ctx);
+ 	dprintk("RPC: %5u gss_unwrap_resp returning %d\n", task->tk_pid,

commit c7d51402d2a64c5b96531f9900bb368020ebbbbb
+Author: J. Bruce Fields 
+Date:   Thu Jul 19 01:49:20 2007 -0700
+
+    knfsd: clean up EX_RDONLY
+    
+    Share a little common code, reverse the arguments for consistency, drop the
+    unnecessary "inline", and lowercase the name.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Acked-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
+index cf61dc8ae942..21928056e35e 100644
+--- a/fs/nfsd/auth.c
++++ b/fs/nfsd/auth.c
+@@ -9,10 +9,11 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #define	CAP_NFSD_MASK (CAP_FS_MASK|CAP_TO_MASK(CAP_SYS_RESOURCE))
+ 
+-static int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)
++int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)
+ {
+ 	struct exp_flavor_info *f;
+ 	struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index f2684e57cf22..ee96a897a29e 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -1797,16 +1797,9 @@ nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat)
+ 	return err;
+ }
+ 
+-static inline int EX_RDONLY(struct svc_export *exp, struct svc_rqst *rqstp)
++static int exp_rdonly(struct svc_rqst *rqstp, struct svc_export *exp)
+ {
+-	struct exp_flavor_info *f;
+-	struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
+-
+-	for (f = exp->ex_flavors; f < end; f++) {
+-		if (f->pseudoflavor == rqstp->rq_flavor)
+-			return f->flags & NFSEXP_READONLY;
+-	}
+-	return exp->ex_flags & NFSEXP_READONLY;
++	return nfsexp_flags(rqstp, exp) & NFSEXP_READONLY;
+ }
+ 
+ /*
+@@ -1845,7 +1838,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
+ 	 */
+ 	if (!(acc & MAY_LOCAL_ACCESS))
+ 		if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) {
+-			if (EX_RDONLY(exp, rqstp) || IS_RDONLY(inode))
++			if (exp_rdonly(rqstp, exp) || IS_RDONLY(inode))
+ 				return nfserr_rofs;
+ 			if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode))
+ 				return nfserr_perm;
+diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
+index fb4e93016666..5cd192469096 100644
+--- a/include/linux/nfsd/export.h
++++ b/include/linux/nfsd/export.h
+@@ -116,6 +116,7 @@ struct svc_expkey {
+ #define EX_NOHIDE(exp)		((exp)->ex_flags & NFSEXP_NOHIDE)
+ #define EX_WGATHER(exp)		((exp)->ex_flags & NFSEXP_GATHERED_WRITES)
+ 
++int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp);
+ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp);
+ 
+ /*

commit e22841c637dc8b308b40f59d64a5b6683d458ab7
+Author: J. Bruce Fields 
+Date:   Thu Jul 19 01:49:20 2007 -0700
+
+    knfsd: move EX_RDONLY out of header
+    
+    EX_RDONLY is only called in one place; just put it there.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Acked-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index 5c97d0ea9e22..f2684e57cf22 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -1797,6 +1797,18 @@ nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat)
+ 	return err;
+ }
+ 
++static inline int EX_RDONLY(struct svc_export *exp, struct svc_rqst *rqstp)
++{
++	struct exp_flavor_info *f;
++	struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
++
++	for (f = exp->ex_flavors; f < end; f++) {
++		if (f->pseudoflavor == rqstp->rq_flavor)
++			return f->flags & NFSEXP_READONLY;
++	}
++	return exp->ex_flags & NFSEXP_READONLY;
++}
++
+ /*
+  * Check for a user's access permissions to this inode.
+  */
+diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
+index 78feb7beff75..fb4e93016666 100644
+--- a/include/linux/nfsd/export.h
++++ b/include/linux/nfsd/export.h
+@@ -116,18 +116,6 @@ struct svc_expkey {
+ #define EX_NOHIDE(exp)		((exp)->ex_flags & NFSEXP_NOHIDE)
+ #define EX_WGATHER(exp)		((exp)->ex_flags & NFSEXP_GATHERED_WRITES)
+ 
+-static inline int EX_RDONLY(struct svc_export *exp, struct svc_rqst *rqstp)
+-{
+-	struct exp_flavor_info *f;
+-	struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
+-
+-	for (f = exp->ex_flavors; f < end; f++) {
+-		if (f->pseudoflavor == rqstp->rq_flavor)
+-			return f->flags & NFSEXP_READONLY;
+-	}
+-	return exp->ex_flags & NFSEXP_READONLY;
+-}
+-
+ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp);
+ 
+ /*

commit 5d3dbbeaf56d0365ac6b5c0a0da0bd31cc4781e1
+Author: J. Bruce Fields 
+Date:   Thu Jul 19 01:49:19 2007 -0700
+
+    nfsd: remove unnecessary NULL checks from nfsd_cross_mnt
+    
+    We can now assume that rqst_exp_get_by_name() does not return NULL; so clean
+    up some unnecessary checks.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Acked-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index b8da5ddb3a0a..5c97d0ea9e22 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -120,14 +120,14 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
+ 		mntput(mnt);
+ 		goto out;
+ 	}
+-	if (exp2 && ((exp->ex_flags & NFSEXP_CROSSMOUNT) || EX_NOHIDE(exp2))) {
++	if ((exp->ex_flags & NFSEXP_CROSSMOUNT) || EX_NOHIDE(exp2)) {
+ 		/* successfully crossed mount point */
+ 		exp_put(exp);
+ 		*expp = exp2;
+ 		dput(dentry);
+ 		*dpp = mounts;
+ 	} else {
+-		if (exp2) exp_put(exp2);
++		exp_put(exp2);
+ 		dput(mounts);
+ 	}
+ 	mntput(mnt);

commit 9a25b96c1f6e1a3c85c9524f3046c7c75d8fecc7
+Author: J. Bruce Fields 
+Date:   Thu Jul 19 01:49:18 2007 -0700
+
+    nfsd: return errors, not NULL, from export functions
+    
+    I converted the various export-returning functions to return -ENOENT instead
+    of NULL, but missed a few cases.
+    
+    This particular case could cause actual bugs in the case of a krb5 client that
+    doesn't match any ip-based client and that is trying to access a filesystem
+    not exported to krb5 clients.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Acked-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
+index c7bbf460b009..6ab8de40904c 100644
+--- a/fs/nfsd/export.c
++++ b/fs/nfsd/export.c
+@@ -1265,7 +1265,7 @@ struct svc_export *
+ rqst_exp_get_by_name(struct svc_rqst *rqstp, struct vfsmount *mnt,
+ 		struct dentry *dentry)
+ {
+-	struct svc_export *gssexp, *exp = NULL;
++	struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT);
+ 
+ 	if (rqstp->rq_client == NULL)
+ 		goto gss;
+@@ -1288,7 +1288,7 @@ rqst_exp_get_by_name(struct svc_rqst *rqstp, struct vfsmount *mnt,
+ 						&rqstp->rq_chandle);
+ 	if (PTR_ERR(gssexp) == -ENOENT)
+ 		return exp;
+-	if (exp && !IS_ERR(exp))
++	if (!IS_ERR(exp))
+ 		exp_put(exp);
+ 	return gssexp;
+ }
+@@ -1296,7 +1296,7 @@ rqst_exp_get_by_name(struct svc_rqst *rqstp, struct vfsmount *mnt,
+ struct svc_export *
+ rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv)
+ {
+-	struct svc_export *gssexp, *exp = NULL;
++	struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT);
+ 
+ 	if (rqstp->rq_client == NULL)
+ 		goto gss;
+@@ -1318,7 +1318,7 @@ rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv)
+ 						&rqstp->rq_chandle);
+ 	if (PTR_ERR(gssexp) == -ENOENT)
+ 		return exp;
+-	if (exp && !IS_ERR(exp))
++	if (!IS_ERR(exp))
+ 		exp_put(exp);
+ 	return gssexp;
+ }

commit a280df32db291f41b3922ac218674be526af5b9b
+Author: J. Bruce Fields 
+Date:   Thu Jul 19 01:49:18 2007 -0700
+
+    nfsd: fix possible read-ahead cache and export table corruption
+    
+    The value of nperbucket calculated here is too small--we should be rounding up
+    instead of down--with the result that the index j in the following loop can
+    overflow the raparm_hash array.  At least in my case, the next thing in memory
+    turns out to be export_table, so the symptoms I see are crashes caused by the
+    appearance of four zeroed-out export entries in the first bucket of the hash
+    table of exports (which were actually entries in the readahead cache, a
+    pointer to which had been written to the export table in this initialization
+    code).
+    
+    It looks like the bug was probably introduced with commit
+    fce1456a19f5c08b688c29f00ef90fdfa074c79b ("knfsd: make the readahead params
+    cache SMP-friendly").
+    
+    Cc: 
+    Cc: Greg Banks 
+    Signed-off-by: "J. Bruce Fields" 
+    Acked-by: NeilBrown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index e90f4a8a1d01..b8da5ddb3a0a 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -1916,7 +1916,7 @@ nfsd_racache_init(int cache_size)
+ 		raparm_hash[i].pb_head = NULL;
+ 		spin_lock_init(&raparm_hash[i].pb_lock);
+ 	}
+-	nperbucket = cache_size >> RAPARM_HASH_BITS;
++	nperbucket = DIV_ROUND_UP(cache_size, RAPARM_HASH_SIZE);
+ 	for (i = 0; i < cache_size - 1; i++) {
+ 		if (i % nperbucket == 0)
+ 			raparm_hash[j++].pb_head = raparml + i;

commit 6924c55492c904695f13c552c461c2211f4fdd6a
+Author: J. Bruce Fields 
+Date:   Fri May 11 16:22:50 2007 -0400
+
+    locks: fix vfs_test_lock() comment
+    
+    Thanks to Doug Chapman for pointing out that the comment here is
+    inconsistent with the function prototype.
+    
+    Signed-off-by: "J. Bruce Fields" 
+
+diff --git a/fs/locks.c b/fs/locks.c
+index 4a8072736efa..4f2d749ac624 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -1600,8 +1600,7 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd)
+ /**
+  * vfs_test_lock - test file byte range lock
+  * @filp: The file to test lock for
+- * @fl: The lock to test
+- * @conf: Place to return a copy of the conflicting lock, if found
++ * @fl: The lock to test; also used to hold result
+  *
+  * Returns -ERRNO on failure.  Indicates presence of conflicting lock by
+  * setting conf->fl_type to something other than F_UNLCK.

commit 6d34ac199a4af5c678a3a8f3275aeb2586b72da3
+Author: J. Bruce Fields 
+Date:   Fri May 11 16:09:32 2007 -0400
+
+    locks: make posix_test_lock() interface more consistent
+    
+    Since posix_test_lock(), like fcntl() and ->lock(), indicates absence or
+    presence of a conflict lock by setting fl_type to, respectively, F_UNLCK
+    or something other than F_UNLCK, the return value is no longer needed.
+    
+    Signed-off-by: "J. Bruce Fields" 
+
+diff --git a/fs/locks.c b/fs/locks.c
+index 4c73b857dded..4a8072736efa 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -659,7 +659,7 @@ static int locks_block_on_timeout(struct file_lock *blocker, struct file_lock *w
+ 	return result;
+ }
+ 
+-int
++void
+ posix_test_lock(struct file *filp, struct file_lock *fl)
+ {
+ 	struct file_lock *cfl;
+@@ -671,14 +671,12 @@ posix_test_lock(struct file *filp, struct file_lock *fl)
+ 		if (posix_locks_conflict(cfl, fl))
+ 			break;
+ 	}
+-	if (cfl) {
++	if (cfl)
+ 		__locks_copy_lock(fl, cfl);
+-		unlock_kernel();
+-		return 1;
+-	} else
++	else
+ 		fl->fl_type = F_UNLCK;
+ 	unlock_kernel();
+-	return 0;
++	return;
+ }
+ 
+ EXPORT_SYMBOL(posix_test_lock);
+diff --git a/fs/nfs/file.c b/fs/nfs/file.c
+index 13ac6fa2b62b..c87dc713b5d7 100644
+--- a/fs/nfs/file.c
++++ b/fs/nfs/file.c
+@@ -402,7 +402,9 @@ static int do_getlk(struct file *filp, int cmd, struct file_lock *fl)
+ 
+ 	lock_kernel();
+ 	/* Try local locking first */
+-	if (posix_test_lock(filp, fl)) {
++	posix_test_lock(filp, fl);
++	if (fl->fl_type != F_UNLCK) {
++		/* found a conflict */
+ 		goto out;
+ 	}
+ 
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index b188c2e5338d..80deaaf1b746 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -862,7 +862,7 @@ extern void locks_init_lock(struct file_lock *);
+ extern void locks_copy_lock(struct file_lock *, struct file_lock *);
+ extern void locks_remove_posix(struct file *, fl_owner_t);
+ extern void locks_remove_flock(struct file *);
+-extern int posix_test_lock(struct file *, struct file_lock *);
++extern void posix_test_lock(struct file *, struct file_lock *);
+ extern int posix_lock_file(struct file *, struct file_lock *, struct file_lock *);
+ extern int posix_lock_file_wait(struct file *, struct file_lock *);
+ extern int posix_unblock_lock(struct file *, struct file_lock *);

commit 370f6599e8bc03fd9fc6d1a1be00ae0c6373ca59
+Author: J. Bruce Fields 
+Date:   Fri Jun 8 15:23:34 2007 -0400
+
+    nfs: disable leases over NFS
+    
+    As Peter Staubach says elsewhere
+    (http://marc.info/?l=linux-kernel&m=118113649526444&w=2):
+    
+    > The problem is that some file system such as NFSv2 and NFSv3 do
+    > not have sufficient support to be able to support leases correctly.
+    > In particular for these two file systems, there is no over the wire
+    > protocol support.
+    >
+    > Currently, these two file systems fail the fcntl(F_SETLEASE) call
+    > accidentally, due to a reference counting difference.  These file
+    > systems should fail more consciously, with a proper error to
+    > indicate that the call is invalid for them.
+    
+    Define an nfs setlease method that just returns -EINVAL.
+    
+    If someone can demonstrate a real need, perhaps we could reenable
+    them in the presence of the "nolock" mount option.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Cc: Peter Staubach 
+    Cc: Trond Myklebust 
+
+diff --git a/fs/nfs/file.c b/fs/nfs/file.c
+index 8689b736fdd9..13ac6fa2b62b 100644
+--- a/fs/nfs/file.c
++++ b/fs/nfs/file.c
+@@ -53,6 +53,7 @@ static int  nfs_fsync(struct file *, struct dentry *dentry, int datasync);
+ static int nfs_check_flags(int flags);
+ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl);
+ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl);
++static int nfs_setlease(struct file *file, long arg, struct file_lock **fl);
+ 
+ const struct file_operations nfs_file_operations = {
+ 	.llseek		= nfs_file_llseek,
+@@ -69,6 +70,7 @@ const struct file_operations nfs_file_operations = {
+ 	.flock		= nfs_flock,
+ 	.splice_read	= nfs_file_splice_read,
+ 	.check_flags	= nfs_check_flags,
++	.setlease	= nfs_setlease,
+ };
+ 
+ const struct inode_operations nfs_file_inode_operations = {
+@@ -558,3 +560,13 @@ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
+ 		return do_unlk(filp, cmd, fl);
+ 	return do_setlk(filp, cmd, fl);
+ }
++
++static int nfs_setlease(struct file *file, long arg, struct file_lock **fl)
++{
++	/*
++	 * There is no protocol support for leases, so we have no way
++	 * to implement them correctly in the face of opens by other
++	 * clients.
++	 */
++	return -EINVAL;
++}

commit 4698afe8e3a725576366f86560a8a8242b21b9f7
+Author: J. Bruce Fields 
+Date:   Wed Jul 4 17:21:37 2007 -0400
+
+    locks: export setlease to filesystems
+    
+    Export setlease so it can used by filesystems to implement their lease
+    methods.
+    
+    Signed-off-by: "J. Bruce Fields" 
+
+diff --git a/fs/locks.c b/fs/locks.c
+index 94f5d8065e3a..4c73b857dded 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -1336,7 +1336,7 @@ int fcntl_getlease(struct file *filp)
+  *
+  *	Called with kernel lock held.
+  */
+-static int setlease(struct file *filp, long arg, struct file_lock **flp)
++int setlease(struct file *filp, long arg, struct file_lock **flp)
+ {
+ 	struct file_lock *fl, **before, **my_before = NULL, *lease;
+ 	struct dentry *dentry = filp->f_path.dentry;
+@@ -1421,6 +1421,7 @@ static int setlease(struct file *filp, long arg, struct file_lock **flp)
+ out:
+ 	return error;
+ }
++EXPORT_SYMBOL(setlease);
+ 
+  /**
+  *	vfs_setlease        -       sets a lease on an open file
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index c8ddf34e9710..b188c2e5338d 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -872,6 +872,7 @@ extern int vfs_cancel_lock(struct file *filp, struct file_lock *fl);
+ extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl);
+ extern int __break_lease(struct inode *inode, unsigned int flags);
+ extern void lease_get_mtime(struct inode *, struct timespec *time);
++extern int setlease(struct file *, long, struct file_lock **);
+ extern int vfs_setlease(struct file *, long, struct file_lock **);
+ extern int lease_modify(struct file_lock **, int);
+ extern int lock_may_read(struct inode *, loff_t start, unsigned long count);

commit a9933cea7a1d80dd9efae9f1acd857f5dce742b9
+Author: J. Bruce Fields 
+Date:   Thu Jun 7 17:09:49 2007 -0400
+
+    locks: rename lease functions to reflect locks.c conventions
+    
+    We've been using the convention that vfs_foo is the function that calls
+    a filesystem-specific foo method if it exists, or falls back on a
+    generic method if it doesn't; thus vfs_foo is what is called when some
+    other part of the kernel (normally lockd or nfsd) wants to get a lock,
+    whereas foo is what filesystems call to use the underlying local
+    functionality as part of their lock implementation.
+    
+    So rename setlease to vfs_setlease (which will call a
+    filesystem-specific setlease after a later patch) and __setlease to
+    setlease.
+    
+    Also, vfs_setlease need only be GPL-exported as long as it's only needed
+    by lockd and nfsd.
+    
+    Signed-off-by: "J. Bruce Fields" 
+
+diff --git a/fs/locks.c b/fs/locks.c
+index 0e5873b0be54..a65d85c1fdc2 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -1326,7 +1326,7 @@ int fcntl_getlease(struct file *filp)
+ }
+ 
+ /**
+- *	__setlease	-	sets a lease on an open file
++ *	setlease	-	sets a lease on an open file
+  *	@filp: file pointer
+  *	@arg: type of lease to obtain
+  *	@flp: input - file_lock to use, output - file_lock inserted
+@@ -1336,7 +1336,7 @@ int fcntl_getlease(struct file *filp)
+  *
+  *	Called with kernel lock held.
+  */
+-static int __setlease(struct file *filp, long arg, struct file_lock **flp)
++static int setlease(struct file *filp, long arg, struct file_lock **flp)
+ {
+ 	struct file_lock *fl, **before, **my_before = NULL, *lease;
+ 	struct dentry *dentry = filp->f_path.dentry;
+@@ -1423,7 +1423,7 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp)
+ }
+ 
+  /**
+- *	setlease        -       sets a lease on an open file
++ *	vfs_setlease        -       sets a lease on an open file
+  *	@filp: file pointer
+  *	@arg: type of lease to obtain
+  *	@lease: file_lock to use
+@@ -1432,18 +1432,17 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp)
+  *	The fl_lmops fl_break function is required by break_lease
+  */
+ 
+-int setlease(struct file *filp, long arg, struct file_lock **lease)
++int vfs_setlease(struct file *filp, long arg, struct file_lock **lease)
+ {
+ 	int error;
+ 
+ 	lock_kernel();
+-	error = __setlease(filp, arg, lease);
++	error = setlease(filp, arg, lease);
+ 	unlock_kernel();
+ 
+ 	return error;
+ }
+-
+-EXPORT_SYMBOL(setlease);
++EXPORT_SYMBOL_GPL(vfs_setlease);
+ 
+ /**
+  *	fcntl_setlease	-	sets a lease on an open file
+@@ -1469,7 +1468,7 @@ int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
+ 
+ 	lock_kernel();
+ 
+-	error = __setlease(filp, arg, &flp);
++	error = vfs_setlease(filp, arg, &flp);
+ 	if (error || arg == F_UNLCK)
+ 		goto out_unlock;
+ 
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index e4a4c87ec8c6..6284807bd37e 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -256,7 +256,7 @@ nfs4_close_delegation(struct nfs4_delegation *dp)
+ 	/* The following nfsd_close may not actually close the file,
+ 	 * but we want to remove the lease in any case. */
+ 	if (dp->dl_flock)
+-		setlease(filp, F_UNLCK, &dp->dl_flock);
++		vfs_setlease(filp, F_UNLCK, &dp->dl_flock);
+ 	nfsd_close(filp);
+ }
+ 
+@@ -1402,7 +1402,7 @@ void nfsd_release_deleg_cb(struct file_lock *fl)
+ /*
+  * Set the delegation file_lock back pointer.
+  *
+- * Called from __setlease() with lock_kernel() held.
++ * Called from setlease() with lock_kernel() held.
+  */
+ static
+ void nfsd_copy_lock_deleg_cb(struct file_lock *new, struct file_lock *fl)
+@@ -1416,7 +1416,7 @@ void nfsd_copy_lock_deleg_cb(struct file_lock *new, struct file_lock *fl)
+ }
+ 
+ /*
+- * Called from __setlease() with lock_kernel() held
++ * Called from setlease() with lock_kernel() held
+  */
+ static
+ int nfsd_same_client_deleg_cb(struct file_lock *onlist, struct file_lock *try)
+@@ -1716,10 +1716,10 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
+ 	fl.fl_file = stp->st_vfs_file;
+ 	fl.fl_pid = current->tgid;
+ 
+-	/* setlease checks to see if delegation should be handed out.
++	/* vfs_setlease checks to see if delegation should be handed out.
+ 	 * the lock_manager callbacks fl_mylease and fl_change are used
+ 	 */
+-	if ((status = setlease(stp->st_vfs_file,
++	if ((status = vfs_setlease(stp->st_vfs_file,
+ 		flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK, &flp))) {
+ 		dprintk("NFSD: setlease failed [%d], no delegation\n", status);
+ 		unhash_delegation(dp);
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 98205f680476..a24f029accc0 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -872,7 +872,7 @@ extern int vfs_cancel_lock(struct file *filp, struct file_lock *fl);
+ extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl);
+ extern int __break_lease(struct inode *inode, unsigned int flags);
+ extern void lease_get_mtime(struct inode *, struct timespec *time);
+-extern int setlease(struct file *, long, struct file_lock **);
++extern int vfs_setlease(struct file *, long, struct file_lock **);
+ extern int lease_modify(struct file_lock **, int);
+ extern int lock_may_read(struct inode *, loff_t start, unsigned long count);
+ extern int lock_may_write(struct inode *, loff_t start, unsigned long count);

commit 6d5e8b05caf074ae5676ad9aaf92e381226a14a7
+Author: J. Bruce Fields 
+Date:   Thu May 31 17:03:46 2007 -0400
+
+    locks: share more common lease code
+    
+    Share more code between setlease (used by nfsd) and fcntl.
+    
+    Also some minor cleanup.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Acked-by: Christoph Hellwig 
+
+diff --git a/fs/locks.c b/fs/locks.c
+index 838ca542c556..0e5873b0be54 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -1343,6 +1343,14 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp)
+ 	struct inode *inode = dentry->d_inode;
+ 	int error, rdlease_count = 0, wrlease_count = 0;
+ 
++	if ((current->fsuid != inode->i_uid) && !capable(CAP_LEASE))
++		return -EACCES;
++	if (!S_ISREG(inode->i_mode))
++		return -EINVAL;
++	error = security_file_lock(filp, arg);
++	if (error)
++		return error;
++
+ 	time_out_leases(inode);
+ 
+ 	BUG_ON(!(*flp)->fl_lmops->fl_break);
+@@ -1426,18 +1434,8 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp)
+ 
+ int setlease(struct file *filp, long arg, struct file_lock **lease)
+ {
+-	struct dentry *dentry = filp->f_path.dentry;
+-	struct inode *inode = dentry->d_inode;
+ 	int error;
+ 
+-	if ((current->fsuid != inode->i_uid) && !capable(CAP_LEASE))
+-		return -EACCES;
+-	if (!S_ISREG(inode->i_mode))
+-		return -EINVAL;
+-	error = security_file_lock(filp, arg);
+-	if (error)
+-		return error;
+-
+ 	lock_kernel();
+ 	error = __setlease(filp, arg, lease);
+ 	unlock_kernel();
+@@ -1464,14 +1462,6 @@ int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
+ 	struct inode *inode = dentry->d_inode;
+ 	int error;
+ 
+-	if ((current->fsuid != inode->i_uid) && !capable(CAP_LEASE))
+-		return -EACCES;
+-	if (!S_ISREG(inode->i_mode))
+-		return -EINVAL;
+-	error = security_file_lock(filp, arg);
+-	if (error)
+-		return error;
+-
+ 	locks_init_lock(&fl);
+ 	error = lease_init(filp, arg, &fl);
+ 	if (error)
+@@ -1485,9 +1475,9 @@ int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
+ 
+ 	error = fasync_helper(fd, filp, 1, &flp->fl_fasync);
+ 	if (error < 0) {
+-		/* remove lease just inserted by __setlease */
++		/* remove lease just inserted by setlease */
+ 		flp->fl_type = F_UNLCK | F_INPROGRESS;
+-		flp->fl_break_time = jiffies- 10;
++		flp->fl_break_time = jiffies - 10;
+ 		time_out_leases(inode);
+ 		goto out_unlock;
+ 	}

commit e32b8ee27b486f682a6d13533cfe6549c8abcdef
+Author: J. Bruce Fields 
+Date:   Thu Mar 1 14:34:35 2007 -0500
+
+    locks: clean up lease_alloc()
+    
+    Return the newly allocated structure as the return value instead of
+    using a struct ** parameter.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/locks.c b/fs/locks.c
+index 3c23fd261022..838ca542c556 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -458,22 +458,20 @@ static int lease_init(struct file *filp, int type, struct file_lock *fl)
+ }
+ 
+ /* Allocate a file_lock initialised to this type of lease */
+-static int lease_alloc(struct file *filp, int type, struct file_lock **flp)
++static struct file_lock *lease_alloc(struct file *filp, int type)
+ {
+ 	struct file_lock *fl = locks_alloc_lock();
+ 	int error = -ENOMEM;
+ 
+ 	if (fl == NULL)
+-		goto out;
++		return ERR_PTR(error);
+ 
+ 	error = lease_init(filp, type, fl);
+ 	if (error) {
+ 		locks_free_lock(fl);
+-		fl = NULL;
++		return ERR_PTR(error);
+ 	}
+-out:
+-	*flp = fl;
+-	return error;
++	return fl;
+ }
+ 
+ /* Check if two locks overlap each other.
+@@ -1179,12 +1177,10 @@ int __break_lease(struct inode *inode, unsigned int mode)
+ 	int error = 0, future;
+ 	struct file_lock *new_fl, *flock;
+ 	struct file_lock *fl;
+-	int alloc_err;
+ 	unsigned long break_time;
+ 	int i_have_this_lease = 0;
+ 
+-	alloc_err = lease_alloc(NULL, mode & FMODE_WRITE ? F_WRLCK : F_RDLCK,
+-			&new_fl);
++	new_fl = lease_alloc(NULL, mode & FMODE_WRITE ? F_WRLCK : F_RDLCK);
+ 
+ 	lock_kernel();
+ 
+@@ -1212,8 +1208,9 @@ int __break_lease(struct inode *inode, unsigned int mode)
+ 		goto out;
+ 	}
+ 
+-	if (alloc_err && !i_have_this_lease && ((mode & O_NONBLOCK) == 0)) {
+-		error = alloc_err;
++	if (IS_ERR(new_fl) && !i_have_this_lease
++			&& ((mode & O_NONBLOCK) == 0)) {
++		error = PTR_ERR(new_fl);
+ 		goto out;
+ 	}
+ 
+@@ -1260,7 +1257,7 @@ int __break_lease(struct inode *inode, unsigned int mode)
+ 
+ out:
+ 	unlock_kernel();
+-	if (!alloc_err)
++	if (!IS_ERR(new_fl))
+ 		locks_free_lock(new_fl);
+ 	return error;
+ }

commit d2ab0b0c4c2570921a9ec1eff1e3a5143e05b231
+Author: J. Bruce Fields 
+Date:   Sat Jun 30 12:40:32 2007 -0400
+
+    locks: convert an -EINVAL return to a BUG
+    
+    There's no point trying to return an error in these cases, which all represent
+    bugs in the callers.
+    
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/locks.c b/fs/locks.c
+index 924e4a7fb1d5..3c23fd261022 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -1348,9 +1348,7 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp)
+ 
+ 	time_out_leases(inode);
+ 
+-	error = -EINVAL;
+-	if (!flp || !(*flp) || !(*flp)->fl_lmops || !(*flp)->fl_lmops->fl_break)
+-		goto out;
++	BUG_ON(!(*flp)->fl_lmops->fl_break);
+ 
+ 	lease = *flp;
+ 

commit 87250dd26a34c65ae31d08837174222889007641
+Author: david m. richter 
+Date:   Wed May 9 16:10:27 2007 -0400
+
+    leases: minor break_lease() comment clarification
+    
+    clarify that break_lease() checks for presence of any lock, not just leases.
+    
+    Signed-off-by: David M. Richter 
+    Signed-off-by: "J. Bruce Fields" 
+
+diff --git a/fs/locks.c b/fs/locks.c
+index 431a8b871fce..924e4a7fb1d5 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -1169,9 +1169,9 @@ static void time_out_leases(struct inode *inode)
+  *	@inode: the inode of the file to return
+  *	@mode: the open mode (read or write)
+  *
+- *	break_lease (inlined for speed) has checked there already
+- *	is a lease on this file.  Leases are broken on a call to open()
+- *	or truncate().  This function can sleep unless you
++ *	break_lease (inlined for speed) has checked there already is at least
++ *	some kind of lock (maybe a lease) on this file.  Leases are broken on
++ *	a call to open() or truncate().  This function can sleep unless you
+  *	specified %O_NONBLOCK to your open().
+  */
+ int __break_lease(struct inode *inode, unsigned int mode)

commit 1269bc69b6649282091bb7007372acf4ab8357fd
+Author: J. Bruce Fields 
+Date:   Tue Jul 17 04:04:52 2007 -0700
+
+    knfsd: nfsd: enforce per-flavor id squashing
+    
+    Allow root squashing to vary per-pseudoflavor, so that you can (for example)
+    allow root access only when sufficiently strong security is in use.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
+index 6e92b0fe5323..cf61dc8ae942 100644
+--- a/fs/nfsd/auth.c
++++ b/fs/nfsd/auth.c
+@@ -12,17 +12,31 @@
+ 
+ #define	CAP_NFSD_MASK (CAP_FS_MASK|CAP_TO_MASK(CAP_SYS_RESOURCE))
+ 
++static int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)
++{
++	struct exp_flavor_info *f;
++	struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
++
++	for (f = exp->ex_flavors; f < end; f++) {
++		if (f->pseudoflavor == rqstp->rq_flavor)
++			return f->flags;
++	}
++	return exp->ex_flags;
++
++}
++
+ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
+ {
+ 	struct svc_cred	cred = rqstp->rq_cred;
+ 	int i;
++	int flags = nfsexp_flags(rqstp, exp);
+ 	int ret;
+ 
+-	if (exp->ex_flags & NFSEXP_ALLSQUASH) {
++	if (flags & NFSEXP_ALLSQUASH) {
+ 		cred.cr_uid = exp->ex_anon_uid;
+ 		cred.cr_gid = exp->ex_anon_gid;
+ 		cred.cr_group_info = groups_alloc(0);
+-	} else if (exp->ex_flags & NFSEXP_ROOTSQUASH) {
++	} else if (flags & NFSEXP_ROOTSQUASH) {
+ 		struct group_info *gi;
+ 		if (!cred.cr_uid)
+ 			cred.cr_uid = exp->ex_anon_uid;
+diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
+index a01f775cb944..78feb7beff75 100644
+--- a/include/linux/nfsd/export.h
++++ b/include/linux/nfsd/export.h
+@@ -43,7 +43,8 @@
+ #define NFSEXP_ALLFLAGS		0xFE3F
+ 
+ /* The flags that may vary depending on security flavor: */
+-#define NFSEXP_SECINFO_FLAGS	0
++#define NFSEXP_SECINFO_FLAGS	(NFSEXP_READONLY | NFSEXP_ROOTSQUASH \
++					| NFSEXP_ALLSQUASH)
+ 
+ #ifdef __KERNEL__
+ 

commit 9091224f3cff4721f295df29e8a99705a63bc4c7
+Author: J. Bruce Fields 
+Date:   Tue Jul 17 04:04:52 2007 -0700
+
+    knfsd: nfsd: allow auth_sys nlm on rpcsec_gss exports
+    
+    Our clients (like other clients, as far as I know) use only auth_sys for nlm,
+    even when using rpcsec_gss for the main nfs operations.
+    
+    Administrators that want to deny non-kerberos-authenticated locking requests
+    will need to turn off NFS protocol versions less than 4....
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
+index 8d2b49914843..0eb464a39aae 100644
+--- a/fs/nfsd/nfsfh.c
++++ b/fs/nfsd/nfsfh.c
+@@ -249,10 +249,16 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
+ 	if (error)
+ 		goto out;
+ 
+-	/* Check security flavor */
+-	error = check_nfsd_access(exp, rqstp);
+-	if (error)
+-		goto out;
++	if (!(access & MAY_LOCK)) {
++		/*
++		 * pseudoflavor restrictions are not enforced on NLM,
++		 * which clients virtually always use auth_sys for,
++		 * even while using RPCSEC_GSS for NFS.
++		 */
++		error = check_nfsd_access(exp, rqstp);
++		if (error)
++			goto out;
++	}
+ 
+ 	/* Finally, check access permissions. */
+ 	error = nfsd_permission(rqstp, exp, dentry, access);

commit 4796f45740bc6f2e3e6cc14e7ed481b38bd0bd39
+Author: J. Bruce Fields 
+Date:   Tue Jul 17 04:04:51 2007 -0700
+
+    knfsd: nfsd4: secinfo handling without secinfo= option
+    
+    We could return some sort of error in the case where someone asks for secinfo
+    on an export without the secinfo= option set--that'd be no worse than what
+    we've been doing.  But it's not really correct.  So, hack up an approximate
+    secinfo response in that case--it may not be complete, but it'll tell the
+    client at least one acceptable security flavor.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index 864498f8f2d9..b3d55c6747fd 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -57,6 +57,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #define NFSDDBG_FACILITY		NFSDDBG_XDR
+ 
+@@ -2454,15 +2455,38 @@ nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, int nfserr,
+ {
+ 	int i = 0;
+ 	struct svc_export *exp = secinfo->si_exp;
++	u32 nflavs;
++	struct exp_flavor_info *flavs;
++	struct exp_flavor_info def_flavs[2];
+ 	ENCODE_HEAD;
+ 
+ 	if (nfserr)
+ 		goto out;
++	if (exp->ex_nflavors) {
++		flavs = exp->ex_flavors;
++		nflavs = exp->ex_nflavors;
++	} else { /* Handling of some defaults in absence of real secinfo: */
++		flavs = def_flavs;
++		if (exp->ex_client->flavour->flavour == RPC_AUTH_UNIX) {
++			nflavs = 2;
++			flavs[0].pseudoflavor = RPC_AUTH_UNIX;
++			flavs[1].pseudoflavor = RPC_AUTH_NULL;
++		} else if (exp->ex_client->flavour->flavour == RPC_AUTH_GSS) {
++			nflavs = 1;
++			flavs[0].pseudoflavor
++					= svcauth_gss_flavor(exp->ex_client);
++		} else {
++			nflavs = 1;
++			flavs[0].pseudoflavor
++					= exp->ex_client->flavour->flavour;
++		}
++	}
++
+ 	RESERVE_SPACE(4);
+-	WRITE32(exp->ex_nflavors);
++	WRITE32(nflavs);
+ 	ADJUST_ARGS();
+-	for (i = 0; i < exp->ex_nflavors; i++) {
+-		u32 flav = exp->ex_flavors[i].pseudoflavor;
++	for (i = 0; i < nflavs; i++) {
++		u32 flav = flavs[i].pseudoflavor;
+ 		struct gss_api_mech *gm = gss_mech_get_by_pseudoflavor(flav);
+ 
+ 		if (gm) {
+diff --git a/include/linux/sunrpc/svcauth_gss.h b/include/linux/sunrpc/svcauth_gss.h
+index 5a5db16ab660..417a1def56db 100644
+--- a/include/linux/sunrpc/svcauth_gss.h
++++ b/include/linux/sunrpc/svcauth_gss.h
+@@ -22,6 +22,7 @@
+ int gss_svc_init(void);
+ void gss_svc_shutdown(void);
+ int svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name);
++u32 svcauth_gss_flavor(struct auth_domain *dom);
+ 
+ #endif /* __KERNEL__ */
+ #endif /* _LINUX_SUNRPC_SVCAUTH_GSS_H */
+diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
+index e4b3de08b040..490697542fc2 100644
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -743,6 +743,15 @@ find_gss_auth_domain(struct gss_ctx *ctx, u32 svc)
+ 
+ static struct auth_ops svcauthops_gss;
+ 
++u32 svcauth_gss_flavor(struct auth_domain *dom)
++{
++	struct gss_domain *gd = container_of(dom, struct gss_domain, h);
++
++	return gd->pseudoflavor;
++}
++
++EXPORT_SYMBOL(svcauth_gss_flavor);
++
+ int
+ svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name)
+ {

commit dcb488a3b7ac3987e21148f44f641c9b2e734232
+Author: Andy Adamson 
+Date:   Tue Jul 17 04:04:51 2007 -0700
+
+    knfsd: nfsd4: implement secinfo
+    
+    Implement the secinfo operation.
+    
+    (Thanks to Usha Ketineni wrote an earlier version of this support.)
+    
+    Cc: Usha Ketineni 
+    Signed-off-by: Andy Adamson 
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index a106e3be7c13..3c627128e205 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -47,6 +47,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #define NFSDDBG_FACILITY		NFSDDBG_PROC
+ 
+@@ -609,6 +610,30 @@ nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	return status;
+ }
+ 
++static __be32
++nfsd4_secinfo(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
++	      struct nfsd4_secinfo *secinfo)
++{
++	struct svc_fh resfh;
++	struct svc_export *exp;
++	struct dentry *dentry;
++	__be32 err;
++
++	fh_init(&resfh, NFS4_FHSIZE);
++	err = nfsd_lookup_dentry(rqstp, &cstate->current_fh,
++				    secinfo->si_name, secinfo->si_namelen,
++				    &exp, &dentry);
++	if (err)
++		return err;
++	if (dentry->d_inode == NULL) {
++		exp_put(exp);
++		err = nfserr_noent;
++	} else
++		secinfo->si_exp = exp;
++	dput(dentry);
++	return err;
++}
++
+ static __be32
+ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	      struct nfsd4_setattr *setattr)
+@@ -1008,6 +1033,9 @@ static struct nfsd4_operation nfsd4_ops[OP_RELEASE_LOCKOWNER+1] = {
+ 	[OP_SAVEFH] = {
+ 		.op_func = (nfsd4op_func)nfsd4_savefh,
+ 	},
++	[OP_SECINFO] = {
++		.op_func = (nfsd4op_func)nfsd4_secinfo,
++	},
+ 	[OP_SETATTR] = {
+ 		.op_func = (nfsd4op_func)nfsd4_setattr,
+ 	},
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index b0bfbda375e1..864498f8f2d9 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -56,6 +56,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #define NFSDDBG_FACILITY		NFSDDBG_XDR
+ 
+@@ -818,6 +819,23 @@ nfsd4_decode_renew(struct nfsd4_compoundargs *argp, clientid_t *clientid)
+ 	DECODE_TAIL;
+ }
+ 
++static __be32
++nfsd4_decode_secinfo(struct nfsd4_compoundargs *argp,
++		     struct nfsd4_secinfo *secinfo)
++{
++	DECODE_HEAD;
++
++	READ_BUF(4);
++	READ32(secinfo->si_namelen);
++	READ_BUF(secinfo->si_namelen);
++	SAVEMEM(secinfo->si_name, secinfo->si_namelen);
++	status = check_filename(secinfo->si_name, secinfo->si_namelen,
++								nfserr_noent);
++	if (status)
++		return status;
++	DECODE_TAIL;
++}
++
+ static __be32
+ nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr)
+ {
+@@ -1131,6 +1149,9 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
+ 		case OP_SAVEFH:
+ 			op->status = nfs_ok;
+ 			break;
++		case OP_SECINFO:
++			op->status = nfsd4_decode_secinfo(argp, &op->u.secinfo);
++			break;
+ 		case OP_SETATTR:
+ 			op->status = nfsd4_decode_setattr(argp, &op->u.setattr);
+ 			break;
+@@ -1847,11 +1868,19 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
+ 	if (d_mountpoint(dentry)) {
+ 		int err;
+ 
++		/*
++		 * Why the heck aren't we just using nfsd_lookup??
++		 * Different "."/".." handling?  Something else?
++		 * At least, add a comment here to explain....
++		 */
+ 		err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp);
+ 		if (err) {
+ 			nfserr = nfserrno(err);
+ 			goto out_put;
+ 		}
++		nfserr = check_nfsd_access(exp, cd->rd_rqstp);
++		if (nfserr)
++			goto out_put;
+ 
+ 	}
+ 	nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval,
+@@ -2419,6 +2448,49 @@ nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
+ 	}
+ }
+ 
++static void
++nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, int nfserr,
++		     struct nfsd4_secinfo *secinfo)
++{
++	int i = 0;
++	struct svc_export *exp = secinfo->si_exp;
++	ENCODE_HEAD;
++
++	if (nfserr)
++		goto out;
++	RESERVE_SPACE(4);
++	WRITE32(exp->ex_nflavors);
++	ADJUST_ARGS();
++	for (i = 0; i < exp->ex_nflavors; i++) {
++		u32 flav = exp->ex_flavors[i].pseudoflavor;
++		struct gss_api_mech *gm = gss_mech_get_by_pseudoflavor(flav);
++
++		if (gm) {
++			RESERVE_SPACE(4);
++			WRITE32(RPC_AUTH_GSS);
++			ADJUST_ARGS();
++			RESERVE_SPACE(4 + gm->gm_oid.len);
++			WRITE32(gm->gm_oid.len);
++			WRITEMEM(gm->gm_oid.data, gm->gm_oid.len);
++			ADJUST_ARGS();
++			RESERVE_SPACE(4);
++			WRITE32(0); /* qop */
++			ADJUST_ARGS();
++			RESERVE_SPACE(4);
++			WRITE32(gss_pseudoflavor_to_service(gm, flav));
++			ADJUST_ARGS();
++			gss_mech_put(gm);
++		} else {
++			RESERVE_SPACE(4);
++			WRITE32(flav);
++			ADJUST_ARGS();
++		}
++	}
++out:
++	if (exp)
++		exp_put(exp);
++}
++
+ /*
+  * The SETATTR encode routine is special -- it always encodes a bitmap,
+  * regardless of the error status.
+@@ -2559,6 +2631,9 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
+ 		break;
+ 	case OP_SAVEFH:
+ 		break;
++	case OP_SECINFO:
++		nfsd4_encode_secinfo(resp, op->status, &op->u.secinfo);
++		break;
+ 	case OP_SETATTR:
+ 		nfsd4_encode_setattr(resp, op->status, &op->u.setattr);
+ 		break;
+diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
+index 54ef1a18a56c..e452256d3f72 100644
+--- a/include/linux/nfsd/nfsd.h
++++ b/include/linux/nfsd/nfsd.h
+@@ -71,6 +71,9 @@ int		nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
+ 		                struct svc_export **expp);
+ __be32		nfsd_lookup(struct svc_rqst *, struct svc_fh *,
+ 				const char *, int, struct svc_fh *);
++__be32		 nfsd_lookup_dentry(struct svc_rqst *, struct svc_fh *,
++				const char *, int,
++				struct svc_export **, struct dentry **);
+ __be32		nfsd_setattr(struct svc_rqst *, struct svc_fh *,
+ 				struct iattr *, int, time_t);
+ #ifdef CONFIG_NFSD_V4
+diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
+index 09799bcee0ac..1b653267133a 100644
+--- a/include/linux/nfsd/xdr4.h
++++ b/include/linux/nfsd/xdr4.h
+@@ -293,6 +293,12 @@ struct nfsd4_rename {
+ 	struct nfsd4_change_info  rn_tinfo; /* response */
+ };
+ 
++struct nfsd4_secinfo {
++	u32 si_namelen;					/* request */
++	char *si_name;					/* request */
++	struct svc_export *si_exp;			/* response */
++};
++
+ struct nfsd4_setattr {
+ 	stateid_t	sa_stateid;         /* request */
+ 	u32		sa_bmval[2];        /* request */
+@@ -365,6 +371,7 @@ struct nfsd4_op {
+ 		struct nfsd4_remove		remove;
+ 		struct nfsd4_rename		rename;
+ 		clientid_t			renew;
++		struct nfsd4_secinfo		secinfo;
+ 		struct nfsd4_setattr		setattr;
+ 		struct nfsd4_setclientid	setclientid;
+ 		struct nfsd4_setclientid_confirm setclientid_confirm;

commit 91fe39d35ebd6adaece4e090f6b1a3e4b6a59c97
+Author: J. Bruce Fields 
+Date:   Tue Jul 17 04:04:49 2007 -0700
+
+    knfsd: nfsd: display export secinfo information
+    
+    Add secinfo information to the display in proc/net/sunrpc/nfsd.export/content.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
+index 06d5cd4a52c4..c7bbf460b009 100644
+--- a/fs/nfsd/export.c
++++ b/fs/nfsd/export.c
+@@ -641,6 +641,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
+ 
+ static void exp_flags(struct seq_file *m, int flag, int fsid,
+ 		uid_t anonu, uid_t anong, struct nfsd4_fs_locations *fslocs);
++static void show_secinfo(struct seq_file *m, struct svc_export *exp);
+ 
+ static int svc_export_show(struct seq_file *m,
+ 			   struct cache_detail *cd,
+@@ -670,6 +671,7 @@ static int svc_export_show(struct seq_file *m,
+ 				seq_printf(m, "%02x", exp->ex_uuid[i]);
+ 			}
+ 		}
++		show_secinfo(m, exp);
+ 	}
+ 	seq_puts(m, ")\n");
+ 	return 0;
+@@ -1467,6 +1469,33 @@ static void show_expflags(struct seq_file *m, int flags, int mask)
+ 	}
+ }
+ 
++static void show_secinfo_flags(struct seq_file *m, int flags)
++{
++	seq_printf(m, ",");
++	show_expflags(m, flags, NFSEXP_SECINFO_FLAGS);
++}
++
++static void show_secinfo(struct seq_file *m, struct svc_export *exp)
++{
++	struct exp_flavor_info *f;
++	struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
++	int lastflags = 0, first = 0;
++
++	if (exp->ex_nflavors == 0)
++		return;
++	for (f = exp->ex_flavors; f < end; f++) {
++		if (first || f->flags != lastflags) {
++			if (!first)
++				show_secinfo_flags(m, lastflags);
++			seq_printf(m, ",sec=%d", f->pseudoflavor);
++			lastflags = f->flags;
++		} else {
++			seq_printf(m, ":%d", f->pseudoflavor);
++		}
++	}
++	show_secinfo_flags(m, lastflags);
++}
++
+ static void exp_flags(struct seq_file *m, int flag, int fsid,
+ 		uid_t anonu, uid_t anong, struct nfsd4_fs_locations *fsloc)
+ {

commit ac34cdb03dfdb8cdc824f41f577434c5c2521155
+Author: J. Bruce Fields 
+Date:   Tue Jul 17 04:04:49 2007 -0700
+
+    knfsd: nfsd: factor out code from show_expflags
+    
+    Factor out some code to be shared by secinfo display code.  Remove some
+    unnecessary conditional printing of commas where we know the condition is
+    true.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
+index 323cbdcc9bfd..06d5cd4a52c4 100644
+--- a/fs/nfsd/export.c
++++ b/fs/nfsd/export.c
+@@ -1453,28 +1453,35 @@ static struct flags {
+ 	{ 0, {"", ""}}
+ };
+ 
+-static void exp_flags(struct seq_file *m, int flag, int fsid,
+-		uid_t anonu, uid_t anong, struct nfsd4_fs_locations *fsloc)
++static void show_expflags(struct seq_file *m, int flags, int mask)
+ {
+-	int first = 0;
+ 	struct flags *flg;
++	int state, first = 0;
+ 
+ 	for (flg = expflags; flg->flag; flg++) {
+-		int state = (flg->flag & flag)?0:1;
++		if (flg->flag & ~mask)
++			continue;
++		state = (flg->flag & flags) ? 0 : 1;
+ 		if (*flg->name[state])
+ 			seq_printf(m, "%s%s", first++?",":"", flg->name[state]);
+ 	}
++}
++
++static void exp_flags(struct seq_file *m, int flag, int fsid,
++		uid_t anonu, uid_t anong, struct nfsd4_fs_locations *fsloc)
++{
++	show_expflags(m, flag, NFSEXP_ALLFLAGS);
+ 	if (flag & NFSEXP_FSID)
+-		seq_printf(m, "%sfsid=%d", first++?",":"", fsid);
++		seq_printf(m, ",fsid=%d", fsid);
+ 	if (anonu != (uid_t)-2 && anonu != (0x10000-2))
+-		seq_printf(m, "%sanonuid=%d", first++?",":"", anonu);
++		seq_printf(m, ",sanonuid=%d", anonu);
+ 	if (anong != (gid_t)-2 && anong != (0x10000-2))
+-		seq_printf(m, "%sanongid=%d", first++?",":"", anong);
++		seq_printf(m, ",sanongid=%d", anong);
+ 	if (fsloc && fsloc->locations_count > 0) {
+ 		char *loctype = (fsloc->migrated) ? "refer" : "replicas";
+ 		int i;
+ 
+-		seq_printf(m, "%s%s=", first++?",":"", loctype);
++		seq_printf(m, ",%s=", loctype);
+ 		seq_escape(m, fsloc->locations[0].path, ",;@ \t\n\\");
+ 		seq_putc(m, '@');
+ 		seq_escape(m, fsloc->locations[0].hosts, ",;@ \t\n\\");

commit 0ec757df9743025f14190d6034d8bd2bf37c2dd1
+Author: J. Bruce Fields 
+Date:   Tue Jul 17 04:04:48 2007 -0700
+
+    knfsd: nfsd4: make readonly access depend on pseudoflavor
+    
+    Allow readonly access to vary depending on the pseudoflavor, using the flag
+    passed with each pseudoflavor in the export downcall.  The rest of the flags
+    are ignored for now, though some day we might also allow id squashing to vary
+    based on the flavor.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
+index d5fe392b14fb..8d2b49914843 100644
+--- a/fs/nfsd/nfsfh.c
++++ b/fs/nfsd/nfsfh.c
+@@ -255,7 +255,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
+ 		goto out;
+ 
+ 	/* Finally, check access permissions. */
+-	error = nfsd_permission(exp, dentry, access);
++	error = nfsd_permission(rqstp, exp, dentry, access);
+ 
+ 	if (error) {
+ 		dprintk("fh_verify: %s/%s permission failure, "
+diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
+index b2c7147aa921..977a71f64e19 100644
+--- a/fs/nfsd/nfsproc.c
++++ b/fs/nfsd/nfsproc.c
+@@ -278,7 +278,8 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
+ 					 *   echo thing > device-special-file-or-pipe
+ 					 * by doing a CREATE with type==0
+ 					 */
+-					nfserr = nfsd_permission(newfhp->fh_export,
++					nfserr = nfsd_permission(rqstp,
++								 newfhp->fh_export,
+ 								 newfhp->fh_dentry,
+ 								 MAY_WRITE|MAY_LOCAL_ACCESS);
+ 					if (nfserr && nfserr != nfserr_rofs)
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index 8e109e586a74..e90f4a8a1d01 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -328,7 +328,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
+ 	/* The size case is special. It changes the file as well as the attributes.  */
+ 	if (iap->ia_valid & ATTR_SIZE) {
+ 		if (iap->ia_size < inode->i_size) {
+-			err = nfsd_permission(fhp->fh_export, dentry, MAY_TRUNC|MAY_OWNER_OVERRIDE);
++			err = nfsd_permission(rqstp, fhp->fh_export, dentry, MAY_TRUNC|MAY_OWNER_OVERRIDE);
+ 			if (err)
+ 				goto out;
+ 		}
+@@ -616,7 +616,7 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *suppor
+ 
+ 			sresult |= map->access;
+ 
+-			err2 = nfsd_permission(export, dentry, map->how);
++			err2 = nfsd_permission(rqstp, export, dentry, map->how);
+ 			switch (err2) {
+ 			case nfs_ok:
+ 				result |= map->access;
+@@ -1043,7 +1043,7 @@ nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+ 	__be32		err;
+ 
+ 	if (file) {
+-		err = nfsd_permission(fhp->fh_export, fhp->fh_dentry,
++		err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry,
+ 				MAY_READ|MAY_OWNER_OVERRIDE);
+ 		if (err)
+ 			goto out;
+@@ -1072,7 +1072,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+ 	__be32			err = 0;
+ 
+ 	if (file) {
+-		err = nfsd_permission(fhp->fh_export, fhp->fh_dentry,
++		err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry,
+ 				MAY_WRITE|MAY_OWNER_OVERRIDE);
+ 		if (err)
+ 			goto out;
+@@ -1801,7 +1801,8 @@ nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat)
+  * Check for a user's access permissions to this inode.
+  */
+ __be32
+-nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
++nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
++					struct dentry *dentry, int acc)
+ {
+ 	struct inode	*inode = dentry->d_inode;
+ 	int		err;
+@@ -1832,7 +1833,7 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
+ 	 */
+ 	if (!(acc & MAY_LOCAL_ACCESS))
+ 		if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) {
+-			if (EX_RDONLY(exp) || IS_RDONLY(inode))
++			if (EX_RDONLY(exp, rqstp) || IS_RDONLY(inode))
+ 				return nfserr_rofs;
+ 			if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode))
+ 				return nfserr_perm;
+diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
+index 424be41130ba..a01f775cb944 100644
+--- a/include/linux/nfsd/export.h
++++ b/include/linux/nfsd/export.h
+@@ -112,10 +112,21 @@ struct svc_expkey {
+ 
+ #define EX_SECURE(exp)		(!((exp)->ex_flags & NFSEXP_INSECURE_PORT))
+ #define EX_ISSYNC(exp)		(!((exp)->ex_flags & NFSEXP_ASYNC))
+-#define EX_RDONLY(exp)		((exp)->ex_flags & NFSEXP_READONLY)
+ #define EX_NOHIDE(exp)		((exp)->ex_flags & NFSEXP_NOHIDE)
+ #define EX_WGATHER(exp)		((exp)->ex_flags & NFSEXP_GATHERED_WRITES)
+ 
++static inline int EX_RDONLY(struct svc_export *exp, struct svc_rqst *rqstp)
++{
++	struct exp_flavor_info *f;
++	struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
++
++	for (f = exp->ex_flavors; f < end; f++) {
++		if (f->pseudoflavor == rqstp->rq_flavor)
++			return f->flags & NFSEXP_READONLY;
++	}
++	return exp->ex_flags & NFSEXP_READONLY;
++}
++
+ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp);
+ 
+ /*
+diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
+index 62499c2f0918..54ef1a18a56c 100644
+--- a/include/linux/nfsd/nfsd.h
++++ b/include/linux/nfsd/nfsd.h
+@@ -119,7 +119,8 @@ __be32		nfsd_statfs(struct svc_rqst *, struct svc_fh *,
+ 				struct kstatfs *);
+ 
+ int		nfsd_notify_change(struct inode *, struct iattr *);
+-__be32		nfsd_permission(struct svc_export *, struct dentry *, int);
++__be32		nfsd_permission(struct svc_rqst *, struct svc_export *,
++				struct dentry *, int);
+ int		nfsd_sync_dir(struct dentry *dp);
+ 
+ #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)

commit 32c1eb0cd7ee00b5eb7b6f7059c635fbc1052966
+Author: Andy Adamson 
+Date:   Tue Jul 17 04:04:48 2007 -0700
+
+    knfsd: nfsd4: return nfserr_wrongsec
+    
+    Make the first actual use of the secinfo information by using it to return
+    nfserr_wrongsec when an export is found that doesn't allow the flavor used on
+    this request.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Andy Adamson 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
+index 4537a8f5cb9a..323cbdcc9bfd 100644
+--- a/fs/nfsd/export.c
++++ b/fs/nfsd/export.c
+@@ -1228,6 +1228,28 @@ exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv,
+ 	return exp;
+ }
+ 
++__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)
++{
++	struct exp_flavor_info *f;
++	struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
++
++	/* legacy gss-only clients are always OK: */
++	if (exp->ex_client == rqstp->rq_gssclient)
++		return 0;
++	/* ip-address based client; check sec= export option: */
++	for (f = exp->ex_flavors; f < end; f++) {
++		if (f->pseudoflavor == rqstp->rq_flavor)
++			return 0;
++	}
++	/* defaults in absence of sec= options: */
++	if (exp->ex_nflavors == 0) {
++		if (rqstp->rq_flavor == RPC_AUTH_NULL ||
++		    rqstp->rq_flavor == RPC_AUTH_UNIX)
++			return 0;
++	}
++	return nfserr_wrongsec;
++}
++
+ /*
+  * Uses rq_client and rq_gssclient to find an export; uses rq_client (an
+  * auth_unix client) if it's available and has secinfo information;
+@@ -1340,6 +1362,10 @@ exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp)
+ 	if (IS_ERR(exp))
+ 		return nfserrno(PTR_ERR(exp));
+ 	rv = fh_compose(fhp, exp, exp->ex_dentry, NULL);
++	if (rv)
++		goto out;
++	rv = check_nfsd_access(exp, rqstp);
++out:
+ 	exp_put(exp);
+ 	return rv;
+ }
+diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
+index 22cb5be79ad0..d5fe392b14fb 100644
+--- a/fs/nfsd/nfsfh.c
++++ b/fs/nfsd/nfsfh.c
+@@ -20,6 +20,7 @@
+ 
+ #include 
+ #include 
++#include 
+ #include 
+ 
+ #define NFSDDBG_FACILITY		NFSDDBG_FH
+@@ -248,6 +249,11 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
+ 	if (error)
+ 		goto out;
+ 
++	/* Check security flavor */
++	error = check_nfsd_access(exp, rqstp);
++	if (error)
++		goto out;
++
+ 	/* Finally, check access permissions. */
+ 	error = nfsd_permission(exp, dentry, access);
+ 
+diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
+index 5c8192bcbced..a8c89ae4c743 100644
+--- a/fs/nfsd/nfssvc.c
++++ b/fs/nfsd/nfssvc.c
+@@ -494,6 +494,15 @@ nfsd(struct svc_rqst *rqstp)
+ 	module_put_and_exit(0);
+ }
+ 
++static __be32 map_new_errors(u32 vers, __be32 nfserr)
++{
++	if (nfserr == nfserr_jukebox && vers == 2)
++		return nfserr_dropit;
++	if (nfserr == nfserr_wrongsec && vers < 4)
++		return nfserr_acces;
++	return nfserr;
++}
++
+ int
+ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
+ {
+@@ -536,6 +545,7 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
+ 
+ 	/* Now call the procedure handler, and encode NFS status. */
+ 	nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp);
++	nfserr = map_new_errors(rqstp->rq_vers, nfserr);
+ 	if (nfserr == nfserr_jukebox && rqstp->rq_vers == 2)
+ 		nfserr = nfserr_dropit;
+ 	if (nfserr == nfserr_dropit) {
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index 627f460a4007..8e109e586a74 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -240,6 +240,9 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
+ 	err = nfsd_lookup_dentry(rqstp, fhp, name, len, &exp, &dentry);
+ 	if (err)
+ 		return err;
++	err = check_nfsd_access(exp, rqstp);
++	if (err)
++		goto out;
+ 	/*
+ 	 * Note: we compose the file handle now, but as the
+ 	 * dentry may be negative, it may need to be updated.
+@@ -247,6 +250,7 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
+ 	err = fh_compose(resfh, exp, dentry, fhp);
+ 	if (!err && !dentry->d_inode)
+ 		err = nfserr_noent;
++out:
+ 	dput(dentry);
+ 	exp_put(exp);
+ 	return err;
+diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
+index 1ba53e524749..424be41130ba 100644
+--- a/include/linux/nfsd/export.h
++++ b/include/linux/nfsd/export.h
+@@ -116,6 +116,7 @@ struct svc_expkey {
+ #define EX_NOHIDE(exp)		((exp)->ex_flags & NFSEXP_NOHIDE)
+ #define EX_WGATHER(exp)		((exp)->ex_flags & NFSEXP_GATHERED_WRITES)
+ 
++__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp);
+ 
+ /*
+  * Function declarations
+diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
+index ce5e345a9bce..62499c2f0918 100644
+--- a/include/linux/nfsd/nfsd.h
++++ b/include/linux/nfsd/nfsd.h
+@@ -236,6 +236,7 @@ void		nfsd_lockd_shutdown(void);
+ #define	nfserr_badname		__constant_htonl(NFSERR_BADNAME)
+ #define	nfserr_cb_path_down	__constant_htonl(NFSERR_CB_PATH_DOWN)
+ #define	nfserr_locked		__constant_htonl(NFSERR_LOCKED)
++#define	nfserr_wrongsec		__constant_htonl(NFSERR_WRONGSEC)
+ #define	nfserr_replay_me	__constant_htonl(NFSERR_REPLAY_ME)
+ 
+ /* error codes for internal use */

commit 6c0a654dceaa4342270306de77eadb0173dfb58a
+Author: J. Bruce Fields 
+Date:   Tue Jul 17 04:04:47 2007 -0700
+
+    knfsd: nfsd: factor nfsd_lookup into 2 pieces
+    
+    Factor nfsd_lookup into nfsd_lookup_dentry, which finds the right dentry and
+    export, and a second part which composes the filehandle (and which will later
+    check the security flavor on the new export).
+    
+    No change in behavior.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index 65043af232ee..627f460a4007 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -135,21 +135,10 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
+ 	return err;
+ }
+ 
+-/*
+- * Look up one component of a pathname.
+- * N.B. After this call _both_ fhp and resfh need an fh_put
+- *
+- * If the lookup would cross a mountpoint, and the mounted filesystem
+- * is exported to the client with NFSEXP_NOHIDE, then the lookup is
+- * accepted as it stands and the mounted directory is
+- * returned. Otherwise the covered directory is returned.
+- * NOTE: this mountpoint crossing is not supported properly by all
+- *   clients and is explicitly disallowed for NFSv3
+- *      NeilBrown 
+- */
+ __be32
+-nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
+-					int len, struct svc_fh *resfh)
++nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,
++		   const char *name, int len,
++		   struct svc_export **exp_ret, struct dentry **dentry_ret)
+ {
+ 	struct svc_export	*exp;
+ 	struct dentry		*dparent;
+@@ -219,6 +208,38 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
+ 			}
+ 		}
+ 	}
++	*dentry_ret = dentry;
++	*exp_ret = exp;
++	return 0;
++
++out_nfserr:
++	exp_put(exp);
++	return nfserrno(host_err);
++}
++
++/*
++ * Look up one component of a pathname.
++ * N.B. After this call _both_ fhp and resfh need an fh_put
++ *
++ * If the lookup would cross a mountpoint, and the mounted filesystem
++ * is exported to the client with NFSEXP_NOHIDE, then the lookup is
++ * accepted as it stands and the mounted directory is
++ * returned. Otherwise the covered directory is returned.
++ * NOTE: this mountpoint crossing is not supported properly by all
++ *   clients and is explicitly disallowed for NFSv3
++ *      NeilBrown 
++ */
++__be32
++nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
++					int len, struct svc_fh *resfh)
++{
++	struct svc_export	*exp;
++	struct dentry		*dentry;
++	__be32 err;
++
++	err = nfsd_lookup_dentry(rqstp, fhp, name, len, &exp, &dentry);
++	if (err)
++		return err;
+ 	/*
+ 	 * Note: we compose the file handle now, but as the
+ 	 * dentry may be negative, it may need to be updated.
+@@ -227,15 +248,11 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
+ 	if (!err && !dentry->d_inode)
+ 		err = nfserr_noent;
+ 	dput(dentry);
+-out:
+ 	exp_put(exp);
+ 	return err;
+-
+-out_nfserr:
+-	err = nfserrno(host_err);
+-	goto out;
+ }
+ 
++
+ /*
+  * Set various file attributes.
+  * N.B. After this call fhp needs an fh_put

commit 2ea2209f073dc7049bd285b4f5dbc0aa273f9746
+Author: J. Bruce Fields 
+Date:   Tue Jul 17 04:04:46 2007 -0700
+
+    knfsd: nfsd: use ip-address-based domain in secinfo case
+    
+    With this patch, we fall back on using the gss/pseudoflavor only if we fail to
+    find a matching auth_unix export that has a secinfo list.
+    
+    As long as sec= options aren't used, there's still no change in behavior here
+    (except possibly for some additional auth_unix cache lookups, whose results
+    will be ignored).
+    
+    The sec= option, however, is not actually enforced yet; later patches will add
+    the necessary checks.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
+index ac225a79376c..4537a8f5cb9a 100644
+--- a/fs/nfsd/export.c
++++ b/fs/nfsd/export.c
+@@ -1229,6 +1229,10 @@ exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv,
+ }
+ 
+ /*
++ * Uses rq_client and rq_gssclient to find an export; uses rq_client (an
++ * auth_unix client) if it's available and has secinfo information;
++ * otherwise, will try to use rq_gssclient.
++ *
+  * Called from functions that handle requests; functions that do work on
+  * behalf of mountd are passed a single client name to use, and should
+  * use exp_get_by_name() or exp_find().
+@@ -1237,29 +1241,83 @@ struct svc_export *
+ rqst_exp_get_by_name(struct svc_rqst *rqstp, struct vfsmount *mnt,
+ 		struct dentry *dentry)
+ {
+-	struct auth_domain *clp;
++	struct svc_export *gssexp, *exp = NULL;
++
++	if (rqstp->rq_client == NULL)
++		goto gss;
+ 
+-	clp = rqstp->rq_gssclient ? rqstp->rq_gssclient : rqstp->rq_client;
+-	return exp_get_by_name(clp, mnt, dentry, &rqstp->rq_chandle);
++	/* First try the auth_unix client: */
++	exp = exp_get_by_name(rqstp->rq_client, mnt, dentry,
++						&rqstp->rq_chandle);
++	if (PTR_ERR(exp) == -ENOENT)
++		goto gss;
++	if (IS_ERR(exp))
++		return exp;
++	/* If it has secinfo, assume there are no gss/... clients */
++	if (exp->ex_nflavors > 0)
++		return exp;
++gss:
++	/* Otherwise, try falling back on gss client */
++	if (rqstp->rq_gssclient == NULL)
++		return exp;
++	gssexp = exp_get_by_name(rqstp->rq_gssclient, mnt, dentry,
++						&rqstp->rq_chandle);
++	if (PTR_ERR(gssexp) == -ENOENT)
++		return exp;
++	if (exp && !IS_ERR(exp))
++		exp_put(exp);
++	return gssexp;
+ }
+ 
+ struct svc_export *
+ rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv)
+ {
+-	struct auth_domain *clp;
++	struct svc_export *gssexp, *exp = NULL;
++
++	if (rqstp->rq_client == NULL)
++		goto gss;
+ 
+-	clp = rqstp->rq_gssclient ? rqstp->rq_gssclient : rqstp->rq_client;
+-	return exp_find(clp, fsid_type, fsidv, &rqstp->rq_chandle);
++	/* First try the auth_unix client: */
++	exp = exp_find(rqstp->rq_client, fsid_type, fsidv, &rqstp->rq_chandle);
++	if (PTR_ERR(exp) == -ENOENT)
++		goto gss;
++	if (IS_ERR(exp))
++		return exp;
++	/* If it has secinfo, assume there are no gss/... clients */
++	if (exp->ex_nflavors > 0)
++		return exp;
++gss:
++	/* Otherwise, try falling back on gss client */
++	if (rqstp->rq_gssclient == NULL)
++		return exp;
++	gssexp = exp_find(rqstp->rq_gssclient, fsid_type, fsidv,
++						&rqstp->rq_chandle);
++	if (PTR_ERR(gssexp) == -ENOENT)
++		return exp;
++	if (exp && !IS_ERR(exp))
++		exp_put(exp);
++	return gssexp;
+ }
+ 
+ struct svc_export *
+ rqst_exp_parent(struct svc_rqst *rqstp, struct vfsmount *mnt,
+ 		struct dentry *dentry)
+ {
+-	struct auth_domain *clp;
++	struct svc_export *exp;
+ 
+-	clp = rqstp->rq_gssclient ? rqstp->rq_gssclient : rqstp->rq_client;
+-	return exp_parent(rqstp->rq_client, mnt, dentry, &rqstp->rq_chandle);
++	dget(dentry);
++	exp = rqst_exp_get_by_name(rqstp, mnt, dentry);
++
++	while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(dentry)) {
++		struct dentry *parent;
++
++		parent = dget_parent(dentry);
++		dput(dentry);
++		dentry = parent;
++		exp = rqst_exp_get_by_name(rqstp, mnt, dentry);
++	}
++	dput(dentry);
++	return exp;
+ }
+ 
+ /*

commit 3ab4d8b1215d61736e2a9a26bea7cc2e6b029e3d
+Author: J. Bruce Fields 
+Date:   Tue Jul 17 04:04:46 2007 -0700
+
+    knfsd: nfsd: set rq_client to ip-address-determined-domain
+    
+    We want it to be possible for users to restrict exports both by IP address and
+    by pseudoflavor.  The pseudoflavor information has previously been passed
+    using special auth_domains stored in the rq_client field.  After the preceding
+    patch that stored the pseudoflavor in rq_pflavor, that's now superfluous; so
+    now we use rq_client for the ip information, as auth_null and auth_unix do.
+    
+    However, we keep around the special auth_domain in the rq_gssclient field for
+    backwards compatibility purposes, so we can still do upcalls using the old
+    "gss/pseudoflavor" auth_domain if upcalls using the unix domain to give us an
+    appropriate export.  This allows us to continue supporting old mountd.
+    
+    In fact, for this first patch, we always use the "gss/pseudoflavor"
+    auth_domain (and only it) if it is available; thus rq_client is ignored in the
+    auth_gss case, and this patch on its own makes no change in behavior; that
+    will be left to later patches.
+    
+    Note on idmap: I'm almost tempted to just replace the auth_domain in the idmap
+    upcall by a dummy value--no version of idmapd has ever used it, and it's
+    unlikely anyone really wants to perform idmapping differently depending on the
+    where the client is (they may want to perform *credential* mapping
+    differently, but that's a different matter--the idmapper just handles id's
+    used in getattr and setattr).  But I'm updating the idmapd code anyway, just
+    out of general backwards-compatibility paranoia.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
+index 9b569af695ab..ac225a79376c 100644
+--- a/fs/nfsd/export.c
++++ b/fs/nfsd/export.c
+@@ -1237,21 +1237,28 @@ struct svc_export *
+ rqst_exp_get_by_name(struct svc_rqst *rqstp, struct vfsmount *mnt,
+ 		struct dentry *dentry)
+ {
+-	return exp_get_by_name(rqstp->rq_client, mnt, dentry,
+-						&rqstp->rq_chandle);
++	struct auth_domain *clp;
++
++	clp = rqstp->rq_gssclient ? rqstp->rq_gssclient : rqstp->rq_client;
++	return exp_get_by_name(clp, mnt, dentry, &rqstp->rq_chandle);
+ }
+ 
+ struct svc_export *
+ rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv)
+ {
+-	return exp_find(rqstp->rq_client, fsid_type, fsidv,
+-						&rqstp->rq_chandle);
++	struct auth_domain *clp;
++
++	clp = rqstp->rq_gssclient ? rqstp->rq_gssclient : rqstp->rq_client;
++	return exp_find(clp, fsid_type, fsidv, &rqstp->rq_chandle);
+ }
+ 
+ struct svc_export *
+ rqst_exp_parent(struct svc_rqst *rqstp, struct vfsmount *mnt,
+ 		struct dentry *dentry)
+ {
++	struct auth_domain *clp;
++
++	clp = rqstp->rq_gssclient ? rqstp->rq_gssclient : rqstp->rq_client;
+ 	return exp_parent(rqstp->rq_client, mnt, dentry, &rqstp->rq_chandle);
+ }
+ 
+diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
+index 45aa21ce6784..2cf9a9a2d89c 100644
+--- a/fs/nfsd/nfs4idmap.c
++++ b/fs/nfsd/nfs4idmap.c
+@@ -587,6 +587,15 @@ idmap_lookup(struct svc_rqst *rqstp,
+ 	return ret;
+ }
+ 
++static char *
++rqst_authname(struct svc_rqst *rqstp)
++{
++	struct auth_domain *clp;
++
++	clp = rqstp->rq_gssclient ? rqstp->rq_gssclient : rqstp->rq_client;
++	return clp->name;
++}
++
+ static int
+ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen,
+ 		uid_t *id)
+@@ -600,7 +609,7 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen
+ 		return -EINVAL;
+ 	memcpy(key.name, name, namelen);
+ 	key.name[namelen] = '\0';
+-	strlcpy(key.authname, rqstp->rq_client->name, sizeof(key.authname));
++	strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
+ 	ret = idmap_lookup(rqstp, nametoid_lookup, &key, &nametoid_cache, &item);
+ 	if (ret == -ENOENT)
+ 		ret = -ESRCH; /* nfserr_badname */
+@@ -620,7 +629,7 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)
+ 	};
+ 	int ret;
+ 
+-	strlcpy(key.authname, rqstp->rq_client->name, sizeof(key.authname));
++	strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
+ 	ret = idmap_lookup(rqstp, idtoname_lookup, &key, &idtoname_cache, &item);
+ 	if (ret == -ENOENT)
+ 		return sprintf(name, "%u", id);
+diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
+index 180e068ea064..22cb5be79ad0 100644
+--- a/fs/nfsd/nfsfh.c
++++ b/fs/nfsd/nfsfh.c
+@@ -120,8 +120,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
+ 		int data_left = fh->fh_size/4;
+ 
+ 		error = nfserr_stale;
+-		if (rqstp->rq_client == NULL)
+-			goto out;
+ 		if (rqstp->rq_vers > 2)
+ 			error = nfserr_badhandle;
+ 		if (rqstp->rq_vers == 4 && fh->fh_size == 0)
+diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
+index 705a90aa345e..8531a70da73d 100644
+--- a/include/linux/sunrpc/svc.h
++++ b/include/linux/sunrpc/svc.h
+@@ -249,6 +249,7 @@ struct svc_rqst {
+ 						 */
+ 	/* Catering to nfsd */
+ 	struct auth_domain *	rq_client;	/* RPC peer info */
++	struct auth_domain *	rq_gssclient;	/* "gss/"-style peer info */
+ 	struct svc_cacherep *	rq_cacherep;	/* cache info */
+ 	struct knfsd_fh *	rq_reffh;	/* Referrence filehandle, used to
+ 						 * determine what device number
+diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h
+index de92619b0826..22e1ef8e200e 100644
+--- a/include/linux/sunrpc/svcauth.h
++++ b/include/linux/sunrpc/svcauth.h
+@@ -127,6 +127,7 @@ extern struct auth_domain *auth_unix_lookup(struct in_addr addr);
+ extern int auth_unix_forget_old(struct auth_domain *dom);
+ extern void svcauth_unix_purge(void);
+ extern void svcauth_unix_info_release(void *);
++extern int svcauth_unix_set_client(struct svc_rqst *rqstp);
+ 
+ static inline unsigned long hash_str(char *name, int bits)
+ {
+diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
+index 7a3e1758bea1..e4b3de08b040 100644
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -913,10 +913,23 @@ svcauth_gss_set_client(struct svc_rqst *rqstp)
+ 	struct gss_svc_data *svcdata = rqstp->rq_auth_data;
+ 	struct rsc *rsci = svcdata->rsci;
+ 	struct rpc_gss_wire_cred *gc = &svcdata->clcred;
++	int stat;
+ 
+-	rqstp->rq_client = find_gss_auth_domain(rsci->mechctx, gc->gc_svc);
+-	if (rqstp->rq_client == NULL)
++	/*
++	 * A gss export can be specified either by:
++	 * 	export	*(sec=krb5,rw)
++	 * or by
++	 * 	export gss/krb5(rw)
++	 * The latter is deprecated; but for backwards compatibility reasons
++	 * the nfsd code will still fall back on trying it if the former
++	 * doesn't work; so we try to make both available to nfsd, below.
++	 */
++	rqstp->rq_gssclient = find_gss_auth_domain(rsci->mechctx, gc->gc_svc);
++	if (rqstp->rq_gssclient == NULL)
+ 		return SVC_DENIED;
++	stat = svcauth_unix_set_client(rqstp);
++	if (stat == SVC_DROP)
++		return stat;
+ 	return SVC_OK;
+ }
+ 
+@@ -1088,7 +1101,6 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
+ 			svc_putnl(resv, GSS_SEQ_WIN);
+ 			if (svc_safe_putnetobj(resv, &rsip->out_token))
+ 				goto drop;
+-			rqstp->rq_client = NULL;
+ 		}
+ 		goto complete;
+ 	case RPC_GSS_PROC_DESTROY:
+@@ -1319,6 +1331,9 @@ svcauth_gss_release(struct svc_rqst *rqstp)
+ 	if (rqstp->rq_client)
+ 		auth_domain_put(rqstp->rq_client);
+ 	rqstp->rq_client = NULL;
++	if (rqstp->rq_gssclient)
++		auth_domain_put(rqstp->rq_gssclient);
++	rqstp->rq_gssclient = NULL;
+ 	if (rqstp->rq_cred.cr_group_info)
+ 		put_group_info(rqstp->rq_cred.cr_group_info);
+ 	rqstp->rq_cred.cr_group_info = NULL;
+diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
+index d9fdf2e4d242..411479411b21 100644
+--- a/net/sunrpc/svcauth_unix.c
++++ b/net/sunrpc/svcauth_unix.c
+@@ -638,7 +638,7 @@ static int unix_gid_find(uid_t uid, struct group_info **gip,
+ 	}
+ }
+ 
+-static int
++int
+ svcauth_unix_set_client(struct svc_rqst *rqstp)
+ {
+ 	struct sockaddr_in *sin = svc_addr_in(rqstp);
+@@ -673,6 +673,8 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
+ 	return SVC_OK;
+ }
+ 
++EXPORT_SYMBOL(svcauth_unix_set_client);
++
+ static int
+ svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp)
+ {

commit 0989a7889695831e49e2c53c1884f52645516a90
+Author: J. Bruce Fields 
+Date:   Tue Jul 17 04:04:44 2007 -0700
+
+    knfsd: nfsd: provide export lookup wrappers which take a svc_rqst
+    
+    Split the callers of exp_get_by_name(), exp_find(), and exp_parent() into
+    those that are processing requests and those that are doing other stuff (like
+    looking up filehandles for mountd).
+    
+    No change in behavior, just a (fairly pointless, on its own) cleanup.
+    
+    (Note this has the effect of making nfsd_cross_mnt() pass rqstp->rq_client
+    instead of exp->ex_client into exp_find_by_name().  However, the two should
+    have the same value at this point.)
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
+index af6abb2529c9..9b569af695ab 100644
+--- a/fs/nfsd/export.c
++++ b/fs/nfsd/export.c
+@@ -1228,6 +1228,32 @@ exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv,
+ 	return exp;
+ }
+ 
++/*
++ * Called from functions that handle requests; functions that do work on
++ * behalf of mountd are passed a single client name to use, and should
++ * use exp_get_by_name() or exp_find().
++ */
++struct svc_export *
++rqst_exp_get_by_name(struct svc_rqst *rqstp, struct vfsmount *mnt,
++		struct dentry *dentry)
++{
++	return exp_get_by_name(rqstp->rq_client, mnt, dentry,
++						&rqstp->rq_chandle);
++}
++
++struct svc_export *
++rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv)
++{
++	return exp_find(rqstp->rq_client, fsid_type, fsidv,
++						&rqstp->rq_chandle);
++}
++
++struct svc_export *
++rqst_exp_parent(struct svc_rqst *rqstp, struct vfsmount *mnt,
++		struct dentry *dentry)
++{
++	return exp_parent(rqstp->rq_client, mnt, dentry, &rqstp->rq_chandle);
++}
+ 
+ /*
+  * Called when we need the filehandle for the root of the pseudofs,
+@@ -1243,7 +1269,7 @@ exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp)
+ 
+ 	mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL);
+ 
+-	exp = exp_find(rqstp->rq_client, FSID_NUM, fsidv, rqstp->rq_chandle);
++	exp = rqst_exp_find(rqstp, FSID_NUM, fsidv);
+ 	if (PTR_ERR(exp) == -ENOENT)
+ 		return nfserr_perm;
+ 	if (IS_ERR(exp))
+diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
+index 89f9041a7782..180e068ea064 100644
+--- a/fs/nfsd/nfsfh.c
++++ b/fs/nfsd/nfsfh.c
+@@ -145,7 +145,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
+ 				fh->fh_fsid[1] = fh->fh_fsid[2];
+ 			}
+ 			if ((data_left -= len)<0) goto out;
+-			exp = exp_find(rqstp->rq_client, fh->fh_fsid_type, datap, &rqstp->rq_chandle);
++			exp = rqst_exp_find(rqstp, fh->fh_fsid_type, datap);
+ 			datap += len;
+ 		} else {
+ 			dev_t xdev;
+@@ -156,8 +156,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
+ 			xdev = old_decode_dev(fh->ofh_xdev);
+ 			xino = u32_to_ino_t(fh->ofh_xino);
+ 			mk_fsid(FSID_DEV, tfh, xdev, xino, 0, NULL);
+-			exp = exp_find(rqstp->rq_client, FSID_DEV, tfh,
+-				       &rqstp->rq_chandle);
++			exp = rqst_exp_find(rqstp, FSID_DEV, tfh);
+ 		}
+ 
+ 		error = nfserr_stale;
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index ec6aaf8b0e36..65043af232ee 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -113,7 +113,7 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
+ 
+ 	while (follow_down(&mnt,&mounts)&&d_mountpoint(mounts));
+ 
+-	exp2 = exp_get_by_name(exp->ex_client, mnt, mounts, &rqstp->rq_chandle);
++	exp2 = rqst_exp_get_by_name(rqstp, mnt, mounts);
+ 	if (IS_ERR(exp2)) {
+ 		err = PTR_ERR(exp2);
+ 		dput(mounts);
+@@ -188,8 +188,7 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
+ 			dput(dentry);
+ 			dentry = dp;
+ 
+-			exp2 = exp_parent(exp->ex_client, mnt, dentry,
+-					  &rqstp->rq_chandle);
++			exp2 = rqst_exp_parent(rqstp, mnt, dentry);
+ 			if (PTR_ERR(exp2) == -ENOENT) {
+ 				dput(dentry);
+ 				dentry = dget(dparent);
+diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
+index 5ed4f277eeac..1ba53e524749 100644
+--- a/include/linux/nfsd/export.h
++++ b/include/linux/nfsd/export.h
+@@ -129,10 +129,16 @@ struct svc_export *	exp_get_by_name(struct auth_domain *clp,
+ 					struct vfsmount *mnt,
+ 					struct dentry *dentry,
+ 					struct cache_req *reqp);
++struct svc_export *	rqst_exp_get_by_name(struct svc_rqst *,
++					     struct vfsmount *,
++					     struct dentry *);
+ struct svc_export *	exp_parent(struct auth_domain *clp,
+ 				   struct vfsmount *mnt,
+ 				   struct dentry *dentry,
+ 				   struct cache_req *reqp);
++struct svc_export *	rqst_exp_parent(struct svc_rqst *,
++					struct vfsmount *mnt,
++					struct dentry *dentry);
+ int			exp_rootfh(struct auth_domain *, 
+ 					char *path, struct knfsd_fh *, int maxsize);
+ __be32			exp_pseudoroot(struct svc_rqst *, struct svc_fh *);
+@@ -152,6 +158,7 @@ static inline void exp_get(struct svc_export *exp)
+ extern struct svc_export *
+ exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv,
+ 	 struct cache_req *reqp);
++struct svc_export * rqst_exp_find(struct svc_rqst *, int, u32 *);
+ 
+ #endif /* __KERNEL__ */
+ 

commit 87548c37c8bdbf98aea002c9c04e4dc8aa27fe1b
+Author: J. Bruce Fields 
+Date:   Tue Jul 17 04:04:44 2007 -0700
+
+    knfsd: nfsd: remove superfluous assignment from nfsd_lookup
+    
+    The "err" variable will only be used in the final return, which always happens
+    after either the preceding
+    
+            err = fh_compose(...);
+    
+    or after the following
+    
+            err = nfserrno(host_err);
+    
+    So the earlier assignment to err is ignored.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index 0a18149ce963..ec6aaf8b0e36 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -168,8 +168,6 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
+ 	exp  = fhp->fh_export;
+ 	exp_get(exp);
+ 
+-	err = nfserr_acces;
+-
+ 	/* Lookup the name, but don't follow links */
+ 	if (isdotent(name, len)) {
+ 		if (len==1)

commit df547efb03e3e8f9ea726e1d07fbbd6fd0706cd7
+Author: J. Bruce Fields 
+Date:   Tue Jul 17 04:04:43 2007 -0700
+
+    knfsd: nfsd4: simplify exp_pseudoroot arguments
+    
+    We're passing three arguments to exp_pseudoroot, two of which are just fields
+    of the svc_rqst.  Soon we'll want to pass in a third field as well.  So let's
+    just give up and pass in the whole struct svc_rqst.
+    
+    Also sneak in some minor style cleanups while we're at it.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
+index fbbbcc5a2fa3..af6abb2529c9 100644
+--- a/fs/nfsd/export.c
++++ b/fs/nfsd/export.c
+@@ -1235,8 +1235,7 @@ exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv,
+  * export point with fsid==0
+  */
+ __be32
+-exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
+-	       struct cache_req *creq)
++exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp)
+ {
+ 	struct svc_export *exp;
+ 	__be32 rv;
+@@ -1244,7 +1243,7 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
+ 
+ 	mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL);
+ 
+-	exp = exp_find(clp, FSID_NUM, fsidv, creq);
++	exp = exp_find(rqstp->rq_client, FSID_NUM, fsidv, rqstp->rq_chandle);
+ 	if (PTR_ERR(exp) == -ENOENT)
+ 		return nfserr_perm;
+ 	if (IS_ERR(exp))
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index 8522729830db..a106e3be7c13 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -286,8 +286,7 @@ nfsd4_putrootfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	__be32 status;
+ 
+ 	fh_put(&cstate->current_fh);
+-	status = exp_pseudoroot(rqstp->rq_client, &cstate->current_fh,
+-			      &rqstp->rq_chandle);
++	status = exp_pseudoroot(rqstp, &cstate->current_fh);
+ 	return status;
+ }
+ 
+@@ -474,8 +473,8 @@ nfsd4_lookupp(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	__be32 ret;
+ 
+ 	fh_init(&tmp_fh, NFS4_FHSIZE);
+-	if((ret = exp_pseudoroot(rqstp->rq_client, &tmp_fh,
+-			      &rqstp->rq_chandle)) != 0)
++	ret = exp_pseudoroot(rqstp, &tmp_fh);
++	if (ret)
+ 		return ret;
+ 	if (tmp_fh.fh_dentry == cstate->current_fh.fh_dentry) {
+ 		fh_put(&tmp_fh);
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index 15809dfd88a5..b0bfbda375e1 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -1296,7 +1296,7 @@ static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp, __be32 *
+ 	char *path, *rootpath;
+ 
+ 	fh_init(&tmp_fh, NFS4_FHSIZE);
+-	*stat = exp_pseudoroot(rqstp->rq_client, &tmp_fh, &rqstp->rq_chandle);
++	*stat = exp_pseudoroot(rqstp, &tmp_fh);
+ 	if (*stat)
+ 		return NULL;
+ 	rootpath = tmp_fh.fh_export->ex_path;
+diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
+index 736f0eafcedf..5ed4f277eeac 100644
+--- a/include/linux/nfsd/export.h
++++ b/include/linux/nfsd/export.h
+@@ -135,7 +135,7 @@ struct svc_export *	exp_parent(struct auth_domain *clp,
+ 				   struct cache_req *reqp);
+ int			exp_rootfh(struct auth_domain *, 
+ 					char *path, struct knfsd_fh *, int maxsize);
+-__be32			exp_pseudoroot(struct auth_domain *, struct svc_fh *fhp, struct cache_req *creq);
++__be32			exp_pseudoroot(struct svc_rqst *, struct svc_fh *);
+ __be32			nfserrno(int errno);
+ 
+ extern struct cache_detail svc_export_cache;

commit e677bfe4d451f8271986a229270c6eecd1f62b3f
+Author: Andy Adamson 
+Date:   Tue Jul 17 04:04:42 2007 -0700
+
+    knfsd: nfsd4: parse secinfo information in exports downcall
+    
+    We add a list of pseudoflavors to each export downcall, which will be used
+    both as a list of security flavors allowed on that export, and (in the order
+    given) as the list of pseudoflavors to return on secinfo calls.
+    
+    This patch parses the new downcall information and adds it to the export
+    structure, but doesn't use it for anything yet.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Andy Adamson 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
+index d4accdcb53a2..fbbbcc5a2fa3 100644
+--- a/fs/nfsd/export.c
++++ b/fs/nfsd/export.c
+@@ -33,6 +33,8 @@
+ #include 
+ #include 
+ #include 
++#include 
++#include 
+ 
+ #define NFSDDBG_FACILITY	NFSDDBG_EXPORT
+ 
+@@ -452,8 +454,48 @@ fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc)
+ 	return err;
+ }
+ 
++static int secinfo_parse(char **mesg, char *buf, struct svc_export *exp)
++{
++	int listsize, err;
++	struct exp_flavor_info *f;
++
++	err = get_int(mesg, &listsize);
++	if (err)
++		return err;
++	if (listsize < 0 || listsize > MAX_SECINFO_LIST)
++		return -EINVAL;
++
++	for (f = exp->ex_flavors; f < exp->ex_flavors + listsize; f++) {
++		err = get_int(mesg, &f->pseudoflavor);
++		if (err)
++			return err;
++		/*
++		 * Just a quick sanity check; we could also try to check
++		 * whether this pseudoflavor is supported, but at worst
++		 * an unsupported pseudoflavor on the export would just
++		 * be a pseudoflavor that won't match the flavor of any
++		 * authenticated request.  The administrator will
++		 * probably discover the problem when someone fails to
++		 * authenticate.
++		 */
++		if (f->pseudoflavor < 0)
++			return -EINVAL;
++		err = get_int(mesg, &f->flags);
++		if (err)
++			return err;
++		/* Only some flags are allowed to differ between flavors: */
++		if (~NFSEXP_SECINFO_FLAGS & (f->flags ^ exp->ex_flags))
++			return -EINVAL;
++	}
++	exp->ex_nflavors = listsize;
++	return 0;
++}
++
+ #else /* CONFIG_NFSD_V4 */
+-static inline int fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc) { return 0; }
++static inline int
++fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc){return 0;}
++static inline int
++secinfo_parse(char **mesg, char *buf, struct svc_export *exp) { return 0; }
+ #endif
+ 
+ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
+@@ -477,6 +519,9 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
+ 
+ 	exp.ex_uuid = NULL;
+ 
++	/* secinfo */
++	exp.ex_nflavors = 0;
++
+ 	if (mesg[mlen-1] != '\n')
+ 		return -EINVAL;
+ 	mesg[mlen-1] = 0;
+@@ -554,7 +599,9 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
+ 					if (exp.ex_uuid == NULL)
+ 						err = -ENOMEM;
+ 				}
+-			} else
++			} else if (strcmp(buf, "secinfo") == 0)
++				err = secinfo_parse(&mesg, buf, &exp);
++			else
+ 				/* quietly ignore unknown words and anything
+ 				 * following. Newer user-space can try to set
+ 				 * new values, then see what the result was.
+@@ -655,6 +702,7 @@ static void export_update(struct cache_head *cnew, struct cache_head *citem)
+ {
+ 	struct svc_export *new = container_of(cnew, struct svc_export, h);
+ 	struct svc_export *item = container_of(citem, struct svc_export, h);
++	int i;
+ 
+ 	new->ex_flags = item->ex_flags;
+ 	new->ex_anon_uid = item->ex_anon_uid;
+@@ -670,6 +718,10 @@ static void export_update(struct cache_head *cnew, struct cache_head *citem)
+ 	item->ex_fslocs.locations_count = 0;
+ 	new->ex_fslocs.migrated = item->ex_fslocs.migrated;
+ 	item->ex_fslocs.migrated = 0;
++	new->ex_nflavors = item->ex_nflavors;
++	for (i = 0; i < MAX_SECINFO_LIST; i++) {
++		new->ex_flavors[i] = item->ex_flavors[i];
++	}
+ }
+ 
+ static struct cache_head *svc_export_alloc(void)
+diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
+index 9f62d6182d32..736f0eafcedf 100644
+--- a/include/linux/nfsd/export.h
++++ b/include/linux/nfsd/export.h
+@@ -42,6 +42,8 @@
+ #define	NFSEXP_NOACL		0x8000	/* reserved for possible ACL related use */
+ #define NFSEXP_ALLFLAGS		0xFE3F
+ 
++/* The flags that may vary depending on security flavor: */
++#define NFSEXP_SECINFO_FLAGS	0
+ 
+ #ifdef __KERNEL__
+ 
+@@ -64,6 +66,19 @@ struct nfsd4_fs_locations {
+ 	int migrated;
+ };
+ 
++/*
++ * We keep an array of pseudoflavors with the export, in order from most
++ * to least preferred.  For the forseeable future, we don't expect more
++ * than the eight pseudoflavors null, unix, krb5, krb5i, krb5p, skpm3,
++ * spkm3i, and spkm3p (and using all 8 at once should be rare).
++ */
++#define MAX_SECINFO_LIST	8
++
++struct exp_flavor_info {
++	u32	pseudoflavor;
++	u32	flags;
++};
++
+ struct svc_export {
+ 	struct cache_head	h;
+ 	struct auth_domain *	ex_client;
+@@ -76,6 +91,8 @@ struct svc_export {
+ 	int			ex_fsid;
+ 	unsigned char *		ex_uuid; /* 16 byte fsid */
+ 	struct nfsd4_fs_locations ex_fslocs;
++	int			ex_nflavors;
++	struct exp_flavor_info	ex_flavors[MAX_SECINFO_LIST];
+ };
+ 
+ /* an "export key" (expkey) maps a filehandlefragement to an

commit c4170583f655dca5da32bd14173d6a93805fc48b
+Author: Andy Adamson 
+Date:   Tue Jul 17 04:04:42 2007 -0700
+
+    knfsd: nfsd4: store pseudoflavor in request
+    
+    Add a new field to the svc_rqst structure to record the pseudoflavor that the
+    request was made with.  For now we record the pseudoflavor but don't use it
+    for anything.
+    
+    Signed-off-by: Andy Adamson 
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h
+index bbac101ac372..459c5fc11d51 100644
+--- a/include/linux/sunrpc/gss_api.h
++++ b/include/linux/sunrpc/gss_api.h
+@@ -58,6 +58,7 @@ u32 gss_unwrap(
+ u32 gss_delete_sec_context(
+ 		struct gss_ctx		**ctx_id);
+ 
++u32 gss_svc_to_pseudoflavor(struct gss_api_mech *, u32 service);
+ u32 gss_pseudoflavor_to_service(struct gss_api_mech *, u32 pseudoflavor);
+ char *gss_service_to_auth_domain_name(struct gss_api_mech *, u32 service);
+ 
+diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
+index 129d50f2225c..705a90aa345e 100644
+--- a/include/linux/sunrpc/svc.h
++++ b/include/linux/sunrpc/svc.h
+@@ -212,6 +212,7 @@ struct svc_rqst {
+ 	struct svc_pool *	rq_pool;	/* thread pool */
+ 	struct svc_procedure *	rq_procinfo;	/* procedure info */
+ 	struct auth_ops *	rq_authop;	/* authentication flavour */
++	u32			rq_flavor;	/* pseudoflavor */
+ 	struct svc_cred		rq_cred;	/* auth info */
+ 	struct sk_buff *	rq_skbuff;	/* fast recv inet buffer */
+ 	struct svc_deferred_req*rq_deferred;	/* deferred request we are replaying */
+diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
+index 26872517ccf3..61801a069ff0 100644
+--- a/net/sunrpc/auth_gss/gss_mech_switch.c
++++ b/net/sunrpc/auth_gss/gss_mech_switch.c
+@@ -193,6 +193,20 @@ gss_mech_get_by_pseudoflavor(u32 pseudoflavor)
+ 
+ EXPORT_SYMBOL(gss_mech_get_by_pseudoflavor);
+ 
++u32
++gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 service)
++{
++	int i;
++
++	for (i = 0; i < gm->gm_pf_num; i++) {
++		if (gm->gm_pfs[i].service == service) {
++			return gm->gm_pfs[i].pseudoflavor;
++		}
++	}
++	return RPC_AUTH_MAXFLAVOR; /* illegal value */
++}
++EXPORT_SYMBOL(gss_svc_to_pseudoflavor);
++
+ u32
+ gss_pseudoflavor_to_service(struct gss_api_mech *gm, u32 pseudoflavor)
+ {
+diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
+index c094583386fd..7a3e1758bea1 100644
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -1131,6 +1131,8 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
+ 		}
+ 		svcdata->rsci = rsci;
+ 		cache_get(&rsci->h);
++		rqstp->rq_flavor = gss_svc_to_pseudoflavor(
++					rsci->mechctx->mech_type, gc->gc_svc);
+ 		ret = SVC_OK;
+ 		goto out;
+ 	}
+diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
+index 07dcd20cbee4..d9fdf2e4d242 100644
+--- a/net/sunrpc/svcauth_unix.c
++++ b/net/sunrpc/svcauth_unix.c
+@@ -5,6 +5,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -707,6 +708,7 @@ svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp)
+ 	svc_putnl(resv, RPC_AUTH_NULL);
+ 	svc_putnl(resv, 0);
+ 
++	rqstp->rq_flavor = RPC_AUTH_NULL;
+ 	return SVC_OK;
+ }
+ 
+@@ -784,6 +786,7 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
+ 	svc_putnl(resv, RPC_AUTH_NULL);
+ 	svc_putnl(resv, 0);
+ 
++	rqstp->rq_flavor = RPC_AUTH_UNIX;
+ 	return SVC_OK;
+ 
+ badcred:

commit 42ed95c4e7415714aaab604ae7b1602b87b27b73
+Author: J. Bruce Fields 
+Date:   Tue Jul 17 04:04:41 2007 -0700
+
+    knfsd: nfsd4: build rpcsec_gss whenever nfsd4 is built
+    
+    Select rpcsec_gss support whenever asked for NFSv4 support.  The rfc actually
+    requires gss, and gss is also the main reason to migrate to v4.  We already do
+    this on the client side.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/Kconfig b/fs/Kconfig
+index ee11f8d94085..613df554728d 100644
+--- a/fs/Kconfig
++++ b/fs/Kconfig
+@@ -1675,6 +1675,7 @@ config NFSD_V3_ACL
+ config NFSD_V4
+ 	bool "Provide NFSv4 server support (EXPERIMENTAL)"
+ 	depends on NFSD_V3 && EXPERIMENTAL
++	select RPCSEC_GSS_KRB5
+ 	help
+ 	  If you would like to include the NFSv4 server as well as the NFSv2
+ 	  and NFSv3 servers, say Y here.  This feature is experimental, and

commit 4b4e5a1411c8b970983fb6022db1da31c4f5c301
+Author: J. Bruce Fields 
+Date:   Sun Jul 15 23:41:53 2007 -0700
+
+    Fix trivial typos in anon_inodes.c comments
+    
+    Trivial typo and grammar fixes.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Cc: Davide Libenzi 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
+index 40fe3a3222e4..a260198306c2 100644
+--- a/fs/anon_inodes.c
++++ b/fs/anon_inodes.c
+@@ -53,7 +53,7 @@ static struct dentry_operations anon_inodefs_dentry_operations = {
+ };
+ 
+ /**
+- * anon_inode_getfd - creates a new file instance by hooking it up to and
++ * anon_inode_getfd - creates a new file instance by hooking it up to an
+  *                    anonymous inode, and a dentry that describe the "class"
+  *                    of the file
+  *
+@@ -66,7 +66,7 @@ static struct dentry_operations anon_inodefs_dentry_operations = {
+  *
+  * Creates a new file by hooking it on a single inode. This is useful for files
+  * that do not need to have a full-fledged inode in order to operate correctly.
+- * All the files created with anon_inode_getfd() will share a single inode, by
++ * All the files created with anon_inode_getfd() will share a single inode,
+  * hence saving memory and avoiding code duplication for the file/inode/dentry
+  * setup.
+  */
+@@ -141,9 +141,9 @@ int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile,
+ }
+ 
+ /*
+- * A single inode exist for all anon_inode files. Contrary to pipes,
+- * anon_inode inodes has no per-instance data associated, so we can avoid
+- * the allocation of multiple of them.
++ * A single inode exists for all anon_inode files. Contrary to pipes,
++ * anon_inode inodes have no associated per-instance data, so we need
++ * only allocate one of them.
+  */
+ static struct inode *anon_inode_mkinode(void)
+ {

commit 3ee17abd14c728d4e0ca7a991c58f2250cb091af
+Author: J. Bruce Fields 
+Date:   Wed Feb 21 00:58:50 2007 -0500
+
+    locks: factor out generic/filesystem switch from test_lock
+    
+    Factor out the code that switches between generic and filesystem-specific lock
+    methods; eventually we want to call this from lock managers (lockd and nfsd)
+    too; currently they only call the generic methods.
+    
+    This patch does that for test_lock.
+    
+    Note that this hasn't been necessary until recently, because the few
+    filesystems that define ->lock() (nfs, cifs...) aren't exportable via NFS.
+    However GFS (and, in the future, other cluster filesystems) need to implement
+    their own locking to get cluster-coherent locking, and also want to be able to
+    export locking to NFS (lockd and NFSv4).
+    
+    So we accomplish this by factoring out code such as this and exporting it for
+    the use of lockd and nfsd.
+    
+    Signed-off-by: "J. Bruce Fields" 
+
+diff --git a/fs/locks.c b/fs/locks.c
+index 749a0dc7cd4b..a31648e3ec1b 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -1611,6 +1611,24 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd)
+ 	return error;
+ }
+ 
++/**
++ * vfs_test_lock - test file byte range lock
++ * @filp: The file to test lock for
++ * @fl: The lock to test
++ * @conf: Place to return a copy of the conflicting lock, if found
++ *
++ * Returns -ERRNO on failure.  Indicates presence of conflicting lock by
++ * setting conf->fl_type to something other than F_UNLCK.
++ */
++int vfs_test_lock(struct file *filp, struct file_lock *fl)
++{
++	if (filp->f_op && filp->f_op->lock)
++		return filp->f_op->lock(filp, F_GETLK, fl);
++	posix_test_lock(filp, fl);
++	return 0;
++}
++EXPORT_SYMBOL_GPL(vfs_test_lock);
++
+ static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl)
+ {
+ 	flock->l_pid = fl->fl_pid;
+@@ -1663,12 +1681,9 @@ int fcntl_getlk(struct file *filp, struct flock __user *l)
+ 	if (error)
+ 		goto out;
+ 
+-	if (filp->f_op && filp->f_op->lock) {
+-		error = filp->f_op->lock(filp, F_GETLK, &file_lock);
+-		if (error < 0)
+-			goto out;
+-	} else
+-		posix_test_lock(filp, &file_lock);
++	error = vfs_test_lock(filp, &file_lock);
++	if (error)
++		goto out;
+  
+ 	flock.l_type = file_lock.fl_type;
+ 	if (file_lock.fl_type != F_UNLCK) {
+@@ -1797,13 +1812,10 @@ int fcntl_getlk64(struct file *filp, struct flock64 __user *l)
+ 	if (error)
+ 		goto out;
+ 
+-	if (filp->f_op && filp->f_op->lock) {
+-		error = filp->f_op->lock(filp, F_GETLK, &file_lock);
+-		if (error < 0)
+-			goto out;
+-	} else
+-		posix_test_lock(filp, &file_lock);
+- 
++	error = vfs_test_lock(filp, &file_lock);
++	if (error)
++		goto out;
++
+ 	flock.l_type = file_lock.fl_type;
+ 	if (file_lock.fl_type != F_UNLCK)
+ 		posix_lock_to_flock64(&flock, &file_lock);
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 9e1ddffe3884..2a2a43988f50 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -856,6 +856,7 @@ extern int posix_lock_file_conf(struct file *, struct file_lock *, struct file_l
+ extern int posix_lock_file(struct file *, struct file_lock *);
+ extern int posix_lock_file_wait(struct file *, struct file_lock *);
+ extern int posix_unblock_lock(struct file *, struct file_lock *);
++extern int vfs_test_lock(struct file *, struct file_lock *);
+ extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl);
+ extern int __break_lease(struct inode *inode, unsigned int flags);
+ extern void lease_get_mtime(struct inode *, struct timespec *time);

commit 70cc6487a4e08b8698c0e2ec935fb48d10490162
+Author: J. Bruce Fields 
+Date:   Thu Feb 22 18:48:53 2007 -0500
+
+    locks: make ->lock release private data before returning in GETLK case
+    
+    The file_lock argument to ->lock is used to return the conflicting lock
+    when found.  There's no reason for the filesystem to return any private
+    information with this conflicting lock, but nfsv4 is.
+    
+    Fix nfsv4 client, and modify locks.c to stop calling fl_release_private
+    for it in this case.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Cc: "Trond Myklebust" "
+
+diff --git a/fs/locks.c b/fs/locks.c
+index 957775ba6468..b07e6e6f819b 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -1665,8 +1665,6 @@ int fcntl_getlk(struct file *filp, struct flock __user *l)
+ 
+ 	if (filp->f_op && filp->f_op->lock) {
+ 		error = filp->f_op->lock(filp, F_GETLK, &file_lock);
+-		if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
+-			file_lock.fl_ops->fl_release_private(&file_lock);
+ 		if (error < 0)
+ 			goto out;
+ 		else
+@@ -1804,8 +1802,6 @@ int fcntl_getlk64(struct file *filp, struct flock64 __user *l)
+ 
+ 	if (filp->f_op && filp->f_op->lock) {
+ 		error = filp->f_op->lock(filp, F_GETLK, &file_lock);
+-		if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
+-			file_lock.fl_ops->fl_release_private(&file_lock);
+ 		if (error < 0)
+ 			goto out;
+ 		else
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index f52cf5c33c6c..d9000ec52f72 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -3018,6 +3018,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock
+ 		case -NFS4ERR_DENIED:
+ 			status = 0;
+ 	}
++	request->fl_ops->fl_release_private(request);
+ out:
+ 	up_read(&clp->cl_sem);
+ 	return status;

commit 08efa202eb398ce7939885a4a01df370fd392068
+Author: J. Bruce Fields 
+Date:   Tue May 1 10:56:25 2007 -0400
+
+    NFS4: invalidate cached acl on setacl
+    
+    The ACL that the server sets may not be exactly the one we set--for
+    example, it may silently turn off bits that it does not support.  So we
+    should remove any cached ACL so that any subsequent request for the ACL
+    will go to the server.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index f52cf5c33c6c..3b5ca1b15fe9 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -2647,8 +2647,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
+ 	nfs_inode_return_delegation(inode);
+ 	buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
+ 	ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+-	if (ret == 0)
+-		nfs4_write_cached_acl(inode, buf, buflen);
++	nfs_zap_caches(inode);
+ 	return ret;
+ }
+ 

commit c2fa1b8a6c059dd08a802545fed3badc8df2adc1
+Author: J. Bruce Fields 
+Date:   Tue Feb 20 16:10:11 2007 -0500
+
+    locks: create posix-to-flock helper functions
+    
+    Factor out a bit of messy code by creating posix-to-flock counterparts
+    to the existing flock-to-posix helper functions.
+    
+    Cc: Christoph Hellwig 
+    Signed-off-by: "J. Bruce Fields" 
+
+diff --git a/fs/locks.c b/fs/locks.c
+index 1a00b8bc65ed..957775ba6468 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -1611,6 +1611,38 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd)
+ 	return error;
+ }
+ 
++static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl)
++{
++	flock->l_pid = fl->fl_pid;
++#if BITS_PER_LONG == 32
++	/*
++	 * Make sure we can represent the posix lock via
++	 * legacy 32bit flock.
++	 */
++	if (fl->fl_start > OFFT_OFFSET_MAX)
++		return -EOVERFLOW;
++	if (fl->fl_end != OFFSET_MAX && fl->fl_end > OFFT_OFFSET_MAX)
++		return -EOVERFLOW;
++#endif
++	flock->l_start = fl->fl_start;
++	flock->l_len = fl->fl_end == OFFSET_MAX ? 0 :
++		fl->fl_end - fl->fl_start + 1;
++	flock->l_whence = 0;
++	return 0;
++}
++
++#if BITS_PER_LONG == 32
++static void posix_lock_to_flock64(struct flock64 *flock, struct file_lock *fl)
++{
++	flock->l_pid = fl->fl_pid;
++	flock->l_start = fl->fl_start;
++	flock->l_len = fl->fl_end == OFFSET_MAX ? 0 :
++		fl->fl_end - fl->fl_start + 1;
++	flock->l_whence = 0;
++	flock->l_type = fl->fl_type;
++}
++#endif
++
+ /* Report the first existing lock that would conflict with l.
+  * This implements the F_GETLK command of fcntl().
+  */
+@@ -1645,24 +1677,9 @@ int fcntl_getlk(struct file *filp, struct flock __user *l)
+  
+ 	flock.l_type = F_UNLCK;
+ 	if (fl != NULL) {
+-		flock.l_pid = fl->fl_pid;
+-#if BITS_PER_LONG == 32
+-		/*
+-		 * Make sure we can represent the posix lock via
+-		 * legacy 32bit flock.
+-		 */
+-		error = -EOVERFLOW;
+-		if (fl->fl_start > OFFT_OFFSET_MAX)
+-			goto out;
+-		if ((fl->fl_end != OFFSET_MAX)
+-		    && (fl->fl_end > OFFT_OFFSET_MAX))
++		error = posix_lock_to_flock(&flock, fl);
++		if (error)
+ 			goto out;
+-#endif
+-		flock.l_start = fl->fl_start;
+-		flock.l_len = fl->fl_end == OFFSET_MAX ? 0 :
+-			fl->fl_end - fl->fl_start + 1;
+-		flock.l_whence = 0;
+-		flock.l_type = fl->fl_type;
+ 	}
+ 	error = -EFAULT;
+ 	if (!copy_to_user(l, &flock, sizeof(flock)))
+@@ -1798,14 +1815,8 @@ int fcntl_getlk64(struct file *filp, struct flock64 __user *l)
+ 	}
+  
+ 	flock.l_type = F_UNLCK;
+-	if (fl != NULL) {
+-		flock.l_pid = fl->fl_pid;
+-		flock.l_start = fl->fl_start;
+-		flock.l_len = fl->fl_end == OFFSET_MAX ? 0 :
+-			fl->fl_end - fl->fl_start + 1;
+-		flock.l_whence = 0;
+-		flock.l_type = fl->fl_type;
+-	}
++	if (fl != NULL)
++		posix_lock_to_flock64(&flock, fl);
+ 	error = -EFAULT;
+ 	if (!copy_to_user(l, &flock, sizeof(flock)))
+ 		error = 0;

commit 226a998dbf3c6f9b85f67d08a52c5a2143ed9d88
+Author: J. Bruce Fields 
+Date:   Wed Feb 14 14:25:00 2007 -0500
+
+    locks: trivial removal of unnecessary parentheses
+    
+    Remove some unnecessary parentheses.
+    
+    Signed-off-by: "J. Bruce Fields" 
+
+diff --git a/fs/locks.c b/fs/locks.c
+index 52a81005dab4..1a00b8bc65ed 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -1738,7 +1738,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
+ 	else {
+ 		for (;;) {
+ 			error = posix_lock_file(filp, file_lock);
+-			if ((error != -EAGAIN) || (cmd == F_SETLK))
++			if (error != -EAGAIN || cmd == F_SETLK)
+ 				break;
+ 			error = wait_event_interruptible(file_lock->fl_wait,
+ 					!file_lock->fl_next);
+@@ -1881,7 +1881,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
+ 	else {
+ 		for (;;) {
+ 			error = posix_lock_file(filp, file_lock);
+-			if ((error != -EAGAIN) || (cmd == F_SETLK64))
++			if (error != -EAGAIN || cmd == F_SETLK64)
+ 				break;
+ 			error = wait_event_interruptible(file_lock->fl_wait,
+ 					!file_lock->fl_next);

commit 21315edd4877b593d5bf17a601a48fc836b8ba58
+Author: J. Bruce Fields 
+Date:   Mon Mar 26 21:32:09 2007 -0800
+
+    [PATCH] knfsd: nfsd4: demote "clientid in use" printk to a dprintk
+    
+    The reused clientid here is a more of a problem for the client than the
+    server, and the client can report the problem itself if it's serious.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 9e4067999209..0b03c1ed21c5 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -750,9 +750,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 		status = nfserr_clid_inuse;
+ 		if (!cmp_creds(&conf->cl_cred, &rqstp->rq_cred)
+ 				|| conf->cl_addr != sin->sin_addr.s_addr) {
+-			printk("NFSD: setclientid: string in use by client"
+-			"(clientid %08x/%08x)\n",
+-			conf->cl_clientid.cl_boot, conf->cl_clientid.cl_id);
++			dprintk("NFSD: setclientid: string in use by client"
++				"at %u.%u.%u.%u\n", NIPQUAD(conf->cl_addr));
+ 			goto out;
+ 		}
+ 	}

commit 54c044094947826105317dadd01deca083627ea1
+Author: J. Bruce Fields 
+Date:   Mon Mar 26 21:32:09 2007 -0800
+
+    [PATCH] knfsd: nfsd4: fix inheritance flags on v4 ace derived from posix default ace
+    
+    A regression introduced in the last set of acl patches removed the
+    INHERIT_ONLY flag from aces derived from the posix acl.  Fix.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
+index 832673b14587..673a53c014a3 100644
+--- a/fs/nfsd/nfs4acl.c
++++ b/fs/nfsd/nfs4acl.c
+@@ -228,7 +228,7 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
+ 	struct posix_acl_summary pas;
+ 	unsigned short deny;
+ 	int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ?
+-					NFS4_INHERITANCE_FLAGS : 0);
++		NFS4_INHERITANCE_FLAGS | NFS4_ACE_INHERIT_ONLY_ACE : 0);
+ 
+ 	BUG_ON(pacl->a_count < 3);
+ 	summarize_posix_acl(pacl, &pas);

commit f70ee5ec8fc59ba2d905e6daf0d395edf6fb461d
+Author: J. Bruce Fields 
+Date:   Wed Mar 21 08:50:12 2007 +1100
+
+    [CRYPTO] api: scatterwalk_copychunks() fails to advance through scatterlist
+    
+    In the loop in scatterwalk_copychunks(), if walk->offset is zero,
+    then scatterwalk_pagedone rounds that up to the nearest page boundary:
+    
+                    walk->offset += PAGE_SIZE - 1;
+                    walk->offset &= PAGE_MASK;
+    
+    which is a no-op in this case, so we don't advance to the next element
+    of the scatterlist array:
+    
+                    if (walk->offset >= walk->sg->offset + walk->sg->length)
+                            scatterwalk_start(walk, sg_next(walk->sg));
+    
+    and we end up copying the same data twice.
+    
+    It appears that other callers of scatterwalk_{page}done first advance
+    walk->offset, so I believe that's the correct thing to do here.
+    
+    This caused a bug in NFS when run with krb5p security, which would
+    cause some writes to fail with permissions errors--for example, writes
+    of less than 8 bytes (the des blocksize) at the start of a file.
+    
+    A git-bisect shows the bug was originally introduced by
+    5c64097aa0f6dc4f27718ef47ca9a12538d62860, first in 2.6.19-rc1.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Herbert Xu 
+
+diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c
+index 35172d3f043b..a66423121773 100644
+--- a/crypto/scatterwalk.c
++++ b/crypto/scatterwalk.c
+@@ -91,6 +91,8 @@ void scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
+ 		memcpy_dir(buf, vaddr, len_this_page, out);
+ 		scatterwalk_unmap(vaddr, out);
+ 
++		scatterwalk_advance(walk, nbytes);
++
+ 		if (nbytes == len_this_page)
+ 			break;
+ 
+@@ -99,7 +101,5 @@ void scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
+ 
+ 		scatterwalk_pagedone(walk, out, 1);
+ 	}
+-
+-	scatterwalk_advance(walk, nbytes);
+ }
+ EXPORT_SYMBOL_GPL(scatterwalk_copychunks);

commit 3160a711ef754758e7f85ae371cf900252c1a392
+Author: J. Bruce Fields 
+Date:   Fri Feb 16 01:28:37 2007 -0800
+
+    [PATCH] knfsd: nfsd4: fix handling of directories without default ACLs
+    
+    When setting an ACL that lacks inheritable ACEs on a directory, we should set
+    a default ACL of zero length, not a default ACL with all bits denied.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
+index 0a69cce33efe..832673b14587 100644
+--- a/fs/nfsd/nfs4acl.c
++++ b/fs/nfsd/nfs4acl.c
+@@ -416,6 +416,7 @@ struct posix_ace_state_array {
+  * calculated so far: */
+ 
+ struct posix_acl_state {
++	int empty;
+ 	struct posix_ace_state owner;
+ 	struct posix_ace_state group;
+ 	struct posix_ace_state other;
+@@ -431,6 +432,7 @@ init_state(struct posix_acl_state *state, int cnt)
+ 	int alloc;
+ 
+ 	memset(state, 0, sizeof(struct posix_acl_state));
++	state->empty = 1;
+ 	/*
+ 	 * In the worst case, each individual acl could be for a distinct
+ 	 * named user or group, but we don't no which, so we allocate
+@@ -498,6 +500,20 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)
+ 	int nace;
+ 	int i, error = 0;
+ 
++	/*
++	 * ACLs with no ACEs are treated differently in the inheritable
++	 * and effective cases: when there are no inheritable ACEs, we
++	 * set a zero-length default posix acl:
++	 */
++	if (state->empty && (flags & NFS4_ACL_TYPE_DEFAULT)) {
++		pacl = posix_acl_alloc(0, GFP_KERNEL);
++		return pacl ? pacl : ERR_PTR(-ENOMEM);
++	}
++	/*
++	 * When there are no effective ACEs, the following will end
++	 * up setting a 3-element effective posix ACL with all
++	 * permissions zero.
++	 */
+ 	nace = 4 + state->users->n + state->groups->n;
+ 	pacl = posix_acl_alloc(nace, GFP_KERNEL);
+ 	if (!pacl)
+@@ -613,6 +629,8 @@ static void process_one_v4_ace(struct posix_acl_state *state,
+ 	u32 mask = ace->access_mask;
+ 	int i;
+ 
++	state->empty = 0;
++
+ 	switch (ace2type(ace)) {
+ 	case ACL_USER_OBJ:
+ 		if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
+@@ -717,7 +735,8 @@ int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl,
+ 		ret = PTR_ERR(*pacl);
+ 		goto out_dstate;
+ 	}
+-	*dpacl = posix_state_to_acl(&default_acl_state, flags);
++	*dpacl = posix_state_to_acl(&default_acl_state,
++						flags | NFS4_ACL_TYPE_DEFAULT);
+ 	if (IS_ERR(*dpacl)) {
+ 		ret = PTR_ERR(*dpacl);
+ 		posix_acl_release(*pacl);

commit f34f924274ad8f84c6d86ea9e52b0682347f5701
+Author: J. Bruce Fields 
+Date:   Fri Feb 16 01:28:34 2007 -0800
+
+    [PATCH] knfsd: nfsd4: fix error return on unsupported acl
+    
+    We should be returning ATTRNOTSUPP, not NOTSUPP, when acls are unsupported.
+    
+    Also fix a comment.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index bb0f1860f582..5d090f11f2be 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -253,7 +253,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia
+ 		return status;
+ 
+ 	/*
+-	 * According to spec, unsupported attributes return ERR_NOTSUPP;
++	 * According to spec, unsupported attributes return ERR_ATTRNOTSUPP;
+ 	 * read-only attributes return ERR_INVAL.
+ 	 */
+ 	if ((bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0) || (bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1))
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index 8283236c6a0f..7e6aa245b5d5 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -466,7 +466,10 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ 	posix_acl_release(dpacl);
+ 	return (error);
+ out_nfserr:
+-	error = nfserrno(host_error);
++	if (host_error == -EOPNOTSUPP)
++		error = nfserr_attrnotsupp;
++	else
++		error = nfserrno(host_error);
+ 	goto out;
+ }
+ 

commit 28e05dd8457c7a7fa1c3faac169a95e0ce4b4a12
+Author: J. Bruce Fields 
+Date:   Fri Feb 16 01:28:30 2007 -0800
+
+    [PATCH] knfsd: nfsd4: represent nfsv4 acl with array instead of linked list
+    
+    Simplify the memory management and code a bit by representing acls with an
+    array instead of a linked list.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
+index 6c52658e9a26..2797051cd2b4 100644
+--- a/fs/nfsd/nfs4acl.c
++++ b/fs/nfsd/nfs4acl.c
+@@ -128,74 +128,58 @@ struct ace_container {
+ };
+ 
+ static short ace2type(struct nfs4_ace *);
+-static int _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, unsigned int);
+-int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
++static void _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *,
++				unsigned int);
++void nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
+ 
+ struct nfs4_acl *
+ nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl,
+ 			unsigned int flags)
+ {
+ 	struct nfs4_acl *acl;
+-	int error = -EINVAL;
++	int size = 0;
+ 
+-	if ((pacl != NULL &&
+-		(posix_acl_valid(pacl) < 0 || pacl->a_count == 0)) ||
+-	    (dpacl != NULL &&
+-		(posix_acl_valid(dpacl) < 0 || dpacl->a_count == 0)))
+-		goto out_err;
+-
+-	acl = nfs4_acl_new();
+-	if (acl == NULL) {
+-		error = -ENOMEM;
+-		goto out_err;
++	if (pacl) {
++		if (posix_acl_valid(pacl) < 0)
++			return ERR_PTR(-EINVAL);
++		size += 2*pacl->a_count;
+ 	}
+-
+-	if (pacl != NULL) {
+-		error = _posix_to_nfsv4_one(pacl, acl,
+-						flags & ~NFS4_ACL_TYPE_DEFAULT);
+-		if (error < 0)
+-			goto out_acl;
++	if (dpacl) {
++		if (posix_acl_valid(dpacl) < 0)
++			return ERR_PTR(-EINVAL);
++		size += 2*dpacl->a_count;
+ 	}
+ 
+-	if (dpacl != NULL) {
+-		error = _posix_to_nfsv4_one(dpacl, acl,
+-						flags | NFS4_ACL_TYPE_DEFAULT);
+-		if (error < 0)
+-			goto out_acl;
+-	}
++	/* Allocate for worst case: one (deny, allow) pair each: */
++	acl = nfs4_acl_new(size);
++	if (acl == NULL)
++		return ERR_PTR(-ENOMEM);
+ 
+-	return acl;
++	if (pacl)
++		_posix_to_nfsv4_one(pacl, acl, flags & ~NFS4_ACL_TYPE_DEFAULT);
+ 
+-out_acl:
+-	nfs4_acl_free(acl);
+-out_err:
+-	acl = ERR_PTR(error);
++	if (dpacl)
++		_posix_to_nfsv4_one(dpacl, acl, flags | NFS4_ACL_TYPE_DEFAULT);
+ 
+ 	return acl;
+ }
+ 
+-static int
++static void
+ nfs4_acl_add_pair(struct nfs4_acl *acl, int eflag, u32 mask, int whotype,
+ 		uid_t owner, unsigned int flags)
+ {
+-	int error;
+-
+-	error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
++	nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
+ 				 eflag, mask, whotype, owner);
+-	if (error < 0)
+-		return error;
+-	error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
++	nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+ 				eflag, deny_mask(mask, flags), whotype, owner);
+-	return error;
+ }
+ 
+ /* We assume the acl has been verified with posix_acl_valid. */
+-static int
++static void
+ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
+ 						unsigned int flags)
+ {
+ 	struct posix_acl_entry *pa, *pe, *group_owner_entry;
+-	int error = -EINVAL;
+ 	u32 mask, mask_mask;
+ 	int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ?
+ 					NFS4_INHERITANCE_FLAGS : 0);
+@@ -211,23 +195,16 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
+ 	pa = pacl->a_entries;
+ 	BUG_ON(pa->e_tag != ACL_USER_OBJ);
+ 	mask = mask_from_posix(pa->e_perm, flags | NFS4_ACL_OWNER);
+-	error = nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_OWNER, 0, flags);
+-	if (error < 0)
+-		goto out;
++	nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_OWNER, 0, flags);
+ 	pa++;
+ 
+ 	while (pa->e_tag == ACL_USER) {
+ 		mask = mask_from_posix(pa->e_perm, flags);
+-		error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
++		nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+ 				eflag,  mask_mask, NFS4_ACL_WHO_NAMED, pa->e_id);
+-		if (error < 0)
+-			goto out;
+ 
+-
+-		error = nfs4_acl_add_pair(acl, eflag, mask,
++		nfs4_acl_add_pair(acl, eflag, mask,
+ 				NFS4_ACL_WHO_NAMED, pa->e_id, flags);
+-		if (error < 0)
+-			goto out;
+ 		pa++;
+ 	}
+ 
+@@ -238,34 +215,25 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
+ 
+ 	if (pacl->a_count > 3) {
+ 		BUG_ON(pa->e_tag != ACL_GROUP_OBJ);
+-		error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
++		nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+ 				NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask,
+ 				NFS4_ACL_WHO_GROUP, 0);
+-		if (error < 0)
+-			goto out;
+ 	}
+ 	group_owner_entry = pa;
+ 	mask = mask_from_posix(pa->e_perm, flags);
+-	error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
++	nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
+ 			NFS4_ACE_IDENTIFIER_GROUP | eflag, mask,
+ 			NFS4_ACL_WHO_GROUP, 0);
+-	if (error < 0)
+-		goto out;
+ 	pa++;
+ 
+ 	while (pa->e_tag == ACL_GROUP) {
+ 		mask = mask_from_posix(pa->e_perm, flags);
+-		error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
++		nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+ 				NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask,
+ 				NFS4_ACL_WHO_NAMED, pa->e_id);
+-		if (error < 0)
+-			goto out;
+-
+-		error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
++		nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
+ 		    		NFS4_ACE_IDENTIFIER_GROUP | eflag, mask,
+ 		    		NFS4_ACL_WHO_NAMED, pa->e_id);
+-		if (error < 0)
+-			goto out;
+ 		pa++;
+ 	}
+ 
+@@ -273,19 +241,15 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
+ 
+ 	pa = group_owner_entry;
+ 	mask = mask_from_posix(pa->e_perm, flags);
+-	error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
++	nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+ 			NFS4_ACE_IDENTIFIER_GROUP | eflag,
+ 			deny_mask(mask, flags), NFS4_ACL_WHO_GROUP, 0);
+-	if (error < 0)
+-		goto out;
+ 	pa++;
+ 	while (pa->e_tag == ACL_GROUP) {
+ 		mask = mask_from_posix(pa->e_perm, flags);
+-		error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
++		nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+ 		    		NFS4_ACE_IDENTIFIER_GROUP | eflag,
+ 		    		deny_mask(mask, flags), NFS4_ACL_WHO_NAMED, pa->e_id);
+-		if (error < 0)
+-			goto out;
+ 		pa++;
+ 	}
+ 
+@@ -293,10 +257,7 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
+ 		pa++;
+ 	BUG_ON(pa->e_tag != ACL_OTHER);
+ 	mask = mask_from_posix(pa->e_perm, flags);
+-	error = nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_EVERYONE, 0, flags);
+-
+-out:
+-	return error;
++	nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_EVERYONE, 0, flags);
+ }
+ 
+ static void
+@@ -640,7 +601,7 @@ int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl,
+ 	if (ret)
+ 		goto out_estate;
+ 	ret = -EINVAL;
+-	list_for_each_entry(ace, &acl->ace_head, l_ace) {
++	for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) {
+ 		if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE &&
+ 		    ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE)
+ 			goto out_dstate;
+@@ -705,48 +666,22 @@ EXPORT_SYMBOL(nfs4_acl_posix_to_nfsv4);
+ EXPORT_SYMBOL(nfs4_acl_nfsv4_to_posix);
+ 
+ struct nfs4_acl *
+-nfs4_acl_new(void)
++nfs4_acl_new(int n)
+ {
+ 	struct nfs4_acl *acl;
+ 
+-	if ((acl = kmalloc(sizeof(*acl), GFP_KERNEL)) == NULL)
++	acl = kmalloc(sizeof(*acl) + n*sizeof(struct nfs4_ace), GFP_KERNEL);
++	if (acl == NULL)
+ 		return NULL;
+-
+ 	acl->naces = 0;
+-	INIT_LIST_HEAD(&acl->ace_head);
+-
+ 	return acl;
+ }
+ 
+ void
+-nfs4_acl_free(struct nfs4_acl *acl)
+-{
+-	struct list_head *h;
+-	struct nfs4_ace *ace;
+-
+-	if (!acl)
+-		return;
+-
+-	while (!list_empty(&acl->ace_head)) {
+-		h = acl->ace_head.next;
+-		list_del(h);
+-		ace = list_entry(h, struct nfs4_ace, l_ace);
+-		kfree(ace);
+-	}
+-
+-	kfree(acl);
+-
+-	return;
+-}
+-
+-int
+ nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask,
+ 		int whotype, uid_t who)
+ {
+-	struct nfs4_ace *ace;
+-
+-	if ((ace = kmalloc(sizeof(*ace), GFP_KERNEL)) == NULL)
+-		return -ENOMEM;
++	struct nfs4_ace *ace = acl->aces + acl->naces;
+ 
+ 	ace->type = type;
+ 	ace->flag = flag;
+@@ -754,10 +689,7 @@ nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask,
+ 	ace->whotype = whotype;
+ 	ace->who = who;
+ 
+-	list_add_tail(&ace->l_ace, &acl->ace_head);
+ 	acl->naces++;
+-
+-	return 0;
+ }
+ 
+ static struct {
+@@ -811,7 +743,6 @@ nfs4_acl_write_who(int who, char *p)
+ }
+ 
+ EXPORT_SYMBOL(nfs4_acl_new);
+-EXPORT_SYMBOL(nfs4_acl_free);
+ EXPORT_SYMBOL(nfs4_acl_add_ace);
+ EXPORT_SYMBOL(nfs4_acl_get_whotype);
+ EXPORT_SYMBOL(nfs4_acl_write_who);
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index 0efba557fb55..fbb4af969243 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -273,42 +273,42 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia
+ 		iattr->ia_valid |= ATTR_SIZE;
+ 	}
+ 	if (bmval[0] & FATTR4_WORD0_ACL) {
+-		int nace, i;
+-		struct nfs4_ace ace;
++		int nace;
++		struct nfs4_ace *ace;
+ 
+ 		READ_BUF(4); len += 4;
+ 		READ32(nace);
+ 
+-		*acl = nfs4_acl_new();
++		if (nace > NFS4_ACL_MAX)
++			return nfserr_resource;
++
++		*acl = nfs4_acl_new(nace);
+ 		if (*acl == NULL) {
+ 			host_err = -ENOMEM;
+ 			goto out_nfserr;
+ 		}
+-		defer_free(argp, (void (*)(const void *))nfs4_acl_free, *acl);
++		defer_free(argp, kfree, *acl);
+ 
+-		for (i = 0; i < nace; i++) {
++		(*acl)->naces = nace;
++		for (ace = (*acl)->aces; ace < (*acl)->aces + nace; ace++) {
+ 			READ_BUF(16); len += 16;
+-			READ32(ace.type);
+-			READ32(ace.flag);
+-			READ32(ace.access_mask);
++			READ32(ace->type);
++			READ32(ace->flag);
++			READ32(ace->access_mask);
+ 			READ32(dummy32);
+ 			READ_BUF(dummy32);
+ 			len += XDR_QUADLEN(dummy32) << 2;
+ 			READMEM(buf, dummy32);
+-			ace.whotype = nfs4_acl_get_whotype(buf, dummy32);
++			ace->whotype = nfs4_acl_get_whotype(buf, dummy32);
+ 			host_err = 0;
+-			if (ace.whotype != NFS4_ACL_WHO_NAMED)
+-				ace.who = 0;
+-			else if (ace.flag & NFS4_ACE_IDENTIFIER_GROUP)
++			if (ace->whotype != NFS4_ACL_WHO_NAMED)
++				ace->who = 0;
++			else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP)
+ 				host_err = nfsd_map_name_to_gid(argp->rqstp,
+-						buf, dummy32, &ace.who);
++						buf, dummy32, &ace->who);
+ 			else
+ 				host_err = nfsd_map_name_to_uid(argp->rqstp,
+-						buf, dummy32, &ace.who);
+-			if (host_err)
+-				goto out_nfserr;
+-			host_err = nfs4_acl_add_ace(*acl, ace.type, ace.flag,
+-				 ace.access_mask, ace.whotype, ace.who);
++						buf, dummy32, &ace->who);
+ 			if (host_err)
+ 				goto out_nfserr;
+ 		}
+@@ -1596,7 +1596,6 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
+ 	}
+ 	if (bmval0 & FATTR4_WORD0_ACL) {
+ 		struct nfs4_ace *ace;
+-		struct list_head *h;
+ 
+ 		if (acl == NULL) {
+ 			if ((buflen -= 4) < 0)
+@@ -1609,9 +1608,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
+ 			goto out_resource;
+ 		WRITE32(acl->naces);
+ 
+-		list_for_each(h, &acl->ace_head) {
+-			ace = list_entry(h, struct nfs4_ace, l_ace);
+-
++		for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) {
+ 			if ((buflen -= 4*3) < 0)
+ 				goto out_resource;
+ 			WRITE32(ace->type);
+@@ -1821,7 +1818,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
+ 	status = nfs_ok;
+ 
+ out:
+-	nfs4_acl_free(acl);
++	kfree(acl);
+ 	if (fhp == &tempfh)
+ 		fh_put(&tempfh);
+ 	return status;
+diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
+index db05182ca0e8..1be5be88debe 100644
+--- a/include/linux/nfs4.h
++++ b/include/linux/nfs4.h
+@@ -105,12 +105,11 @@ struct nfs4_ace {
+ 	uint32_t	access_mask;
+ 	int		whotype;
+ 	uid_t		who;
+-	struct list_head l_ace;
+ };
+ 
+ struct nfs4_acl {
+ 	uint32_t	naces;
+-	struct list_head ace_head;
++	struct nfs4_ace	aces[0];
+ };
+ 
+ typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier;
+diff --git a/include/linux/nfs4_acl.h b/include/linux/nfs4_acl.h
+index 22aff4d01f20..409b6e02f337 100644
+--- a/include/linux/nfs4_acl.h
++++ b/include/linux/nfs4_acl.h
+@@ -39,9 +39,12 @@
+ 
+ #include 
+ 
+-struct nfs4_acl *nfs4_acl_new(void);
+-void nfs4_acl_free(struct nfs4_acl *);
+-int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
++/* Maximum ACL we'll accept from client; chosen (somewhat arbitrarily) to
++ * fit in a page: */
++#define NFS4_ACL_MAX 170
++
++struct nfs4_acl *nfs4_acl_new(int);
++void nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
+ int nfs4_acl_get_whotype(char *, u32);
+ int nfs4_acl_write_who(int who, char *p);
+ int nfs4_acl_permission(struct nfs4_acl *acl, uid_t owner, gid_t group,

commit 575a6290f035b16e3301014d9b176422ec9062bb
+Author: J. Bruce Fields 
+Date:   Fri Feb 16 01:28:29 2007 -0800
+
+    [PATCH] knfsd: nfsd4: simplify nfsv4->posix translation
+    
+    The code that splits an incoming nfsv4 ACL into inheritable and effective
+    parts can be combined with the the code that translates each to a posix acl,
+    resulting in simpler code that requires one less pass through the ACL.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
+index 785418b0b799..6c52658e9a26 100644
+--- a/fs/nfsd/nfs4acl.c
++++ b/fs/nfsd/nfs4acl.c
+@@ -129,9 +129,7 @@ struct ace_container {
+ 
+ static short ace2type(struct nfs4_ace *);
+ static int _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, unsigned int);
+-static struct posix_acl *_nfsv4_to_posix_one(struct nfs4_acl *, unsigned int);
+ int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
+-static int nfs4_acl_split(struct nfs4_acl *, struct nfs4_acl *);
+ 
+ struct nfs4_acl *
+ nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl,
+@@ -344,46 +342,6 @@ sort_pacl(struct posix_acl *pacl)
+ 	return;
+ }
+ 
+-int
+-nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl,
+-		struct posix_acl **dpacl, unsigned int flags)
+-{
+-	struct nfs4_acl *dacl;
+-	int error = -ENOMEM;
+-
+-	*pacl = NULL;
+-	*dpacl = NULL;
+-
+-	dacl = nfs4_acl_new();
+-	if (dacl == NULL)
+-		goto out;
+-
+-	error = nfs4_acl_split(acl, dacl);
+-	if (error)
+-		goto out_acl;
+-
+-	*pacl = _nfsv4_to_posix_one(acl, flags);
+-	if (IS_ERR(*pacl)) {
+-		error = PTR_ERR(*pacl);
+-		*pacl = NULL;
+-		goto out_acl;
+-	}
+-
+-	*dpacl = _nfsv4_to_posix_one(dacl, flags);
+-	if (IS_ERR(*dpacl)) {
+-		error = PTR_ERR(*dpacl);
+-		*dpacl = NULL;
+-	}
+-out_acl:
+-	if (error) {
+-		posix_acl_release(*pacl);
+-		*pacl = NULL;
+-	}
+-	nfs4_acl_free(dacl);
+-out:
+-	return error;
+-}
+-
+ /*
+  * While processing the NFSv4 ACE, this maintains bitmasks representing
+  * which permission bits have been allowed and which denied to a given
+@@ -668,76 +626,61 @@ static void process_one_v4_ace(struct posix_acl_state *state,
+ 	}
+ }
+ 
+-static struct posix_acl *
+-_nfsv4_to_posix_one(struct nfs4_acl *n4acl, unsigned int flags)
++int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl,
++			    struct posix_acl **dpacl, unsigned int flags)
+ {
+-	struct posix_acl_state state;
+-	struct posix_acl *pacl;
++	struct posix_acl_state effective_acl_state, default_acl_state;
+ 	struct nfs4_ace *ace;
+ 	int ret;
+ 
+-	ret = init_state(&state, n4acl->naces);
++	ret = init_state(&effective_acl_state, acl->naces);
+ 	if (ret)
+-		return ERR_PTR(ret);
+-
+-	list_for_each_entry(ace, &n4acl->ace_head, l_ace)
+-		process_one_v4_ace(&state, ace);
+-
+-	pacl = posix_state_to_acl(&state, flags);
+-
+-	free_state(&state);
+-
+-	if (!IS_ERR(pacl))
+-		sort_pacl(pacl);
+-	return pacl;
+-}
+-
+-static int
+-nfs4_acl_split(struct nfs4_acl *acl, struct nfs4_acl *dacl)
+-{
+-	struct list_head *h, *n;
+-	struct nfs4_ace *ace;
+-	int error = 0;
+-
+-	list_for_each_safe(h, n, &acl->ace_head) {
+-		ace = list_entry(h, struct nfs4_ace, l_ace);
+-
++		return ret;
++	ret = init_state(&default_acl_state, acl->naces);
++	if (ret)
++		goto out_estate;
++	ret = -EINVAL;
++	list_for_each_entry(ace, &acl->ace_head, l_ace) {
+ 		if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE &&
+ 		    ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE)
+-			return -EINVAL;
+-
++			goto out_dstate;
+ 		if (ace->flag & ~NFS4_SUPPORTED_FLAGS)
+-			return -EINVAL;
+-
++			goto out_dstate;
+ 		if ((ace->flag & NFS4_INHERITANCE_FLAGS) == 0) {
+-			/* Leave this ace in the effective acl: */
++			process_one_v4_ace(&effective_acl_state, ace);
+ 			continue;
+ 		}
++		if (!(flags & NFS4_ACL_DIR))
++			goto out_dstate;
+ 		/*
+ 		 * Note that when only one of FILE_INHERIT or DIRECTORY_INHERIT
+ 		 * is set, we're effectively turning on the other.  That's OK,
+ 		 * according to rfc 3530.
+ 		 */
+-		if (ace->flag & NFS4_ACE_INHERIT_ONLY_ACE) {
+-			/* Add this ace to the default acl and remove it
+-			 * from the effective acl: */
+-			error = nfs4_acl_add_ace(dacl, ace->type, ace->flag,
+-				ace->access_mask, ace->whotype, ace->who);
+-			if (error)
+-				return error;
+-			list_del(h);
+-			kfree(ace);
+-			acl->naces--;
+-		} else {
+-			/* Add this ace to the default, but leave it in
+-			 * the effective acl as well: */
+-			error = nfs4_acl_add_ace(dacl, ace->type, ace->flag,
+-				ace->access_mask, ace->whotype, ace->who);
+-			if (error)
+-				return error;
+-		}
++		process_one_v4_ace(&default_acl_state, ace);
++
++		if (!(ace->flag & NFS4_ACE_INHERIT_ONLY_ACE))
++			process_one_v4_ace(&effective_acl_state, ace);
+ 	}
+-	return 0;
++	*pacl = posix_state_to_acl(&effective_acl_state, flags);
++	if (IS_ERR(*pacl)) {
++		ret = PTR_ERR(*pacl);
++		goto out_dstate;
++	}
++	*dpacl = posix_state_to_acl(&default_acl_state, flags);
++	if (IS_ERR(*dpacl)) {
++		ret = PTR_ERR(*dpacl);
++		posix_acl_release(*pacl);
++		goto out_dstate;
++	}
++	sort_pacl(*pacl);
++	sort_pacl(*dpacl);
++	ret = 0;
++out_dstate:
++	free_state(&default_acl_state);
++out_estate:
++	free_state(&effective_acl_state);
++	return ret;
+ }
+ 
+ static short

commit 7bdfa68c5e70b815e85dab0bdd9f48ec103c4002
+Author: J. Bruce Fields 
+Date:   Fri Feb 16 01:28:28 2007 -0800
+
+    [PATCH] knfsd: nfsd4: relax checking of ACL inheritance bits
+    
+    The rfc allows us to be more permissive about the ACL inheritance bits we
+    accept:
+    
+            "If the server supports a single "inherit ACE" flag that applies to
+            both files and directories, the server may reject the request
+            (i.e., requiring the client to set both the file and directory
+            inheritance flags). The server may also accept the request and
+            silently turn on the ACE4_DIRECTORY_INHERIT_ACE flag."
+    
+    Let's take the latter option--the ACL is a complex attribute that could be
+    rejected for a wide variety of reasons, and the protocol gives us little
+    ability to explain the reason for the rejection, so erroring out is a
+    user-unfriendly last resort.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
+index 5d94555cdc83..785418b0b799 100644
+--- a/fs/nfsd/nfs4acl.c
++++ b/fs/nfsd/nfs4acl.c
+@@ -61,9 +61,11 @@
+ 
+ /* flags used to simulate posix default ACLs */
+ #define NFS4_INHERITANCE_FLAGS (NFS4_ACE_FILE_INHERIT_ACE \
+-		| NFS4_ACE_DIRECTORY_INHERIT_ACE | NFS4_ACE_INHERIT_ONLY_ACE)
++		| NFS4_ACE_DIRECTORY_INHERIT_ACE)
+ 
+-#define NFS4_SUPPORTED_FLAGS (NFS4_INHERITANCE_FLAGS | NFS4_ACE_IDENTIFIER_GROUP)
++#define NFS4_SUPPORTED_FLAGS (NFS4_INHERITANCE_FLAGS \
++		| NFS4_ACE_INHERIT_ONLY_ACE \
++		| NFS4_ACE_IDENTIFIER_GROUP)
+ 
+ #define MASK_EQUAL(mask1, mask2) \
+ 	( ((mask1) & NFS4_ACE_MASK_ALL) == ((mask2) & NFS4_ACE_MASK_ALL) )
+@@ -707,11 +709,16 @@ nfs4_acl_split(struct nfs4_acl *acl, struct nfs4_acl *dacl)
+ 		if (ace->flag & ~NFS4_SUPPORTED_FLAGS)
+ 			return -EINVAL;
+ 
+-		switch (ace->flag & NFS4_INHERITANCE_FLAGS) {
+-		case 0:
++		if ((ace->flag & NFS4_INHERITANCE_FLAGS) == 0) {
+ 			/* Leave this ace in the effective acl: */
+ 			continue;
+-		case NFS4_INHERITANCE_FLAGS:
++		}
++		/*
++		 * Note that when only one of FILE_INHERIT or DIRECTORY_INHERIT
++		 * is set, we're effectively turning on the other.  That's OK,
++		 * according to rfc 3530.
++		 */
++		if (ace->flag & NFS4_ACE_INHERIT_ONLY_ACE) {
+ 			/* Add this ace to the default acl and remove it
+ 			 * from the effective acl: */
+ 			error = nfs4_acl_add_ace(dacl, ace->type, ace->flag,
+@@ -721,17 +728,13 @@ nfs4_acl_split(struct nfs4_acl *acl, struct nfs4_acl *dacl)
+ 			list_del(h);
+ 			kfree(ace);
+ 			acl->naces--;
+-			break;
+-		case NFS4_INHERITANCE_FLAGS & ~NFS4_ACE_INHERIT_ONLY_ACE:
++		} else {
+ 			/* Add this ace to the default, but leave it in
+ 			 * the effective acl as well: */
+ 			error = nfs4_acl_add_ace(dacl, ace->type, ace->flag,
+ 				ace->access_mask, ace->whotype, ace->who);
+ 			if (error)
+ 				return error;
+-			break;
+-		default:
+-			return -EINVAL;
+ 		}
+ 	}
+ 	return 0;

commit f534a257acfd9dae0a689be64397919907b283ba
+Author: J. Bruce Fields 
+Date:   Fri Feb 16 01:28:27 2007 -0800
+
+    [PATCH] knfsd: nfsd4: fix non-terminated string
+    
+    The server name is expected to be a null-terminated string, so we can't pass
+    in the raw client identifier.
+    
+    What's more, the client identifier is just a binary, not necessarily
+    printable, blob.  Let's just use the ip address instead.  The server name
+    appears to exist just to help debugging by making some printk's more
+    informative.
+    
+    Note that the string is copies into the rpc client structure, so the pointer
+    to the local variable does not outlive the function call.
+    
+    Signed-off-by: "J. Bruce Fields" 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index f57655a7a2b6..fb14d68eacab 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -387,7 +387,6 @@ nfsd4_probe_callback(struct nfs4_client *clp)
+ 		.address	= (struct sockaddr *)&addr,
+ 		.addrsize	= sizeof(addr),
+ 		.timeout	= &timeparms,
+-		.servername	= clp->cl_name.data,
+ 		.program	= program,
+ 		.version	= nfs_cb_version[1]->number,
+ 		.authflavor	= RPC_AUTH_UNIX,	/* XXX: need AUTH_GSS... */
+@@ -397,6 +396,7 @@ nfsd4_probe_callback(struct nfs4_client *clp)
+ 		.rpc_proc       = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
+ 		.rpc_argp       = clp,
+ 	};
++	char clientname[16];
+ 	int status;
+ 
+ 	if (atomic_read(&cb->cb_set))
+@@ -419,6 +419,11 @@ nfsd4_probe_callback(struct nfs4_client *clp)
+ 	memset(program->stats, 0, sizeof(cb->cb_stat));
+ 	program->stats->program = program;
+ 
++	/* Just here to make some printk's more useful: */
++	snprintf(clientname, sizeof(clientname),
++		"%u.%u.%u.%u", NIPQUAD(addr.sin_addr));
++	args.servername = clientname;
++
+ 	/* Create RPC client */
+ 	cb->cb_client = rpc_create(&args);
+ 	if (IS_ERR(cb->cb_client)) {

commit adeb8133dd57f380e70a389a89a2ea3ae227f9e2
+Author: Olga Kornievskaia 
+Date:   Mon Dec 4 20:22:34 2006 -0500
+
+    rpc: spkm3 update
+    
+    This updates the spkm3 code to bring it up to date with our current
+    understanding of the spkm3 spec.
+    
+    In doing so, we're changing the downcall format used by gssd in the spkm3 case,
+    which will cause an incompatilibity with old userland spkm3 support.  Since the
+    old code a) didn't implement the protocol correctly, and b) was never
+    distributed except in the form of some experimental patches from the citi web
+    site, we're assuming this is OK.
+    
+    We do detect the old downcall format and print warning (and fail).  We also
+    include a version number in the new downcall format, to be used in the
+    future in case any further change is required.
+    
+    In some more detail:
+    
+            - fix integrity support
+            - removed dependency on NIDs. instead OIDs are used
+            - known OID values for algorithms added.
+            - fixed some context fields and types
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/gss_spkm3.h b/include/linux/sunrpc/gss_spkm3.h
+index 2cf3fbb40b4f..e3e6a3437f8b 100644
+--- a/include/linux/sunrpc/gss_spkm3.h
++++ b/include/linux/sunrpc/gss_spkm3.h
+@@ -12,27 +12,19 @@
+ #include 
+ 
+ struct spkm3_ctx {
+-	struct xdr_netobj	ctx_id; /* per message context id */
+-	int			qop;         /* negotiated qop */
++	struct xdr_netobj	ctx_id;  /* per message context id */
++	int			endtime; /* endtime of the context */
+ 	struct xdr_netobj	mech_used;
+ 	unsigned int		ret_flags ;
+-	unsigned int		req_flags ;
+-	struct xdr_netobj	share_key;
+-	int			conf_alg;
+-	struct crypto_blkcipher	*derived_conf_key;
+-	int			intg_alg;
+-	struct crypto_blkcipher	*derived_integ_key;
+-	int			keyestb_alg;   /* alg used to get share_key */
+-	int			owf_alg;   /* one way function */
++	struct xdr_netobj	conf_alg;
++	struct xdr_netobj	derived_conf_key;
++	struct xdr_netobj	intg_alg;
++	struct xdr_netobj 	derived_integ_key;
+ };
+ 
+-/* from openssl/objects.h */
+-/* XXX need SEAL_ALG_NONE */
+-#define NID_md5		4
+-#define NID_dhKeyAgreement	28 
+-#define NID_des_cbc		31 
+-#define NID_sha1		64
+-#define NID_cast5_cbc		108
++/* OIDs declarations for K-ALG, I-ALG, C-ALG, and OWF-ALG */
++extern const struct xdr_netobj hmac_md5_oid;
++extern const struct xdr_netobj cast5_cbc_oid;
+ 
+ /* SPKM InnerContext Token types */
+ 
+@@ -46,11 +38,13 @@ u32 spkm3_make_token(struct spkm3_ctx *ctx, struct xdr_buf * text, struct xdr_ne
+ u32 spkm3_read_token(struct spkm3_ctx *ctx, struct xdr_netobj *read_token, struct xdr_buf *message_buffer, int toktype);
+ 
+ #define CKSUMTYPE_RSA_MD5            0x0007
++#define CKSUMTYPE_HMAC_MD5           0x0008
+ 
+-s32 make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
+-                   int body_offset, struct xdr_netobj *cksum);
++s32 make_spkm3_checksum(s32 cksumtype, struct xdr_netobj *key, char *header,
++		unsigned int hdrlen, struct xdr_buf *body,
++		unsigned int body_offset, struct xdr_netobj *cksum);
+ void asn1_bitstring_len(struct xdr_netobj *in, int *enclen, int *zerobits);
+-int decode_asn1_bitstring(struct xdr_netobj *out, char *in, int enclen, 
++int decode_asn1_bitstring(struct xdr_netobj *out, char *in, int enclen,
+                    int explen);
+ void spkm3_mic_header(unsigned char **hdrbuf, unsigned int *hdrlen, 
+                    unsigned char *ctxhdr, int elen, int zbit);
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index d12ee5f54c0c..a02ecc1f230d 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -68,7 +68,7 @@ static struct rpc_credops gss_credops;
+ #define GSS_CRED_SLACK		1024		/* XXX: unused */
+ /* length of a krb5 verifier (48), plus data added before arguments when
+  * using integrity (two 4-byte integers): */
+-#define GSS_VERF_SLACK		56
++#define GSS_VERF_SLACK		100
+ 
+ /* XXX this define must match the gssd define
+ * as it is passed to gssd to signal the use of
+diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c
+index d57f60838895..41465072d0b5 100644
+--- a/net/sunrpc/auth_gss/gss_spkm3_mech.c
++++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c
+@@ -82,133 +82,73 @@ simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res)
+ 	return q;
+ }
+ 
+-static inline const void *
+-get_key(const void *p, const void *end, struct crypto_blkcipher **res,
+-	int *resalg)
+-{
+-	struct xdr_netobj	key = { 0 };
+-	int			setkey = 0;
+-	char			*alg_name;
+-
+-	p = simple_get_bytes(p, end, resalg, sizeof(*resalg));
+-	if (IS_ERR(p))
+-		goto out_err;
+-	p = simple_get_netobj(p, end, &key);
+-	if (IS_ERR(p))
+-		goto out_err;
+-
+-	switch (*resalg) {
+-		case NID_des_cbc:
+-			alg_name = "cbc(des)";
+-			setkey = 1;
+-			break;
+-		case NID_cast5_cbc:
+-			/* XXXX here in name only, not used */
+-			alg_name = "cbc(cast5)";
+-			setkey = 0; /* XXX will need to set to 1 */
+-			break;
+-		case NID_md5:
+-			if (key.len == 0) {
+-				dprintk("RPC: SPKM3 get_key: NID_md5 zero Key length\n");
+-			}
+-			alg_name = "md5";
+-			setkey = 0;
+-			break;
+-		default:
+-			dprintk("gss_spkm3_mech: unsupported algorithm %d\n", *resalg);
+-			goto out_err_free_key;
+-	}
+-	*res = crypto_alloc_blkcipher(alg_name, 0, CRYPTO_ALG_ASYNC);
+-	if (IS_ERR(*res)) {
+-		printk("gss_spkm3_mech: unable to initialize crypto algorthm %s\n", alg_name);
+-		*res = NULL;
+-		goto out_err_free_key;
+-	}
+-	if (setkey) {
+-		if (crypto_blkcipher_setkey(*res, key.data, key.len)) {
+-			printk("gss_spkm3_mech: error setting key for crypto algorthm %s\n", alg_name);
+-			goto out_err_free_tfm;
+-		}
+-	}
+-
+-	if(key.len > 0)
+-		kfree(key.data);
+-	return p;
+-
+-out_err_free_tfm:
+-	crypto_free_blkcipher(*res);
+-out_err_free_key:
+-	if(key.len > 0)
+-		kfree(key.data);
+-	p = ERR_PTR(-EINVAL);
+-out_err:
+-	return p;
+-}
+-
+ static int
+ gss_import_sec_context_spkm3(const void *p, size_t len,
+ 				struct gss_ctx *ctx_id)
+ {
+ 	const void *end = (const void *)((const char *)p + len);
+ 	struct	spkm3_ctx *ctx;
++	int	version;
+ 
+ 	if (!(ctx = kzalloc(sizeof(*ctx), GFP_KERNEL)))
+ 		goto out_err;
+ 
++	p = simple_get_bytes(p, end, &version, sizeof(version));
++	if (IS_ERR(p))
++		goto out_err_free_ctx;
++	if (version != 1) {
++		dprintk("RPC: unknown spkm3 token format: obsolete nfs-utils?\n");
++		goto out_err_free_ctx;
++	}
++
+ 	p = simple_get_netobj(p, end, &ctx->ctx_id);
+ 	if (IS_ERR(p))
+ 		goto out_err_free_ctx;
+ 
+-	p = simple_get_bytes(p, end, &ctx->qop, sizeof(ctx->qop));
++	p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime));
+ 	if (IS_ERR(p))
+ 		goto out_err_free_ctx_id;
+ 
+ 	p = simple_get_netobj(p, end, &ctx->mech_used);
+ 	if (IS_ERR(p))
+-		goto out_err_free_mech;
++		goto out_err_free_ctx_id;
+ 
+ 	p = simple_get_bytes(p, end, &ctx->ret_flags, sizeof(ctx->ret_flags));
+ 	if (IS_ERR(p))
+ 		goto out_err_free_mech;
+ 
+-	p = simple_get_bytes(p, end, &ctx->req_flags, sizeof(ctx->req_flags));
++	p = simple_get_netobj(p, end, &ctx->conf_alg);
+ 	if (IS_ERR(p))
+ 		goto out_err_free_mech;
+ 
+-	p = simple_get_netobj(p, end, &ctx->share_key);
+-	if (IS_ERR(p))
+-		goto out_err_free_s_key;
+-
+-	p = get_key(p, end, &ctx->derived_conf_key, &ctx->conf_alg);
++	p = simple_get_netobj(p, end, &ctx->derived_conf_key);
+ 	if (IS_ERR(p))
+-		goto out_err_free_s_key;
++		goto out_err_free_conf_alg;
+ 
+-	p = get_key(p, end, &ctx->derived_integ_key, &ctx->intg_alg);
++	p = simple_get_netobj(p, end, &ctx->intg_alg);
+ 	if (IS_ERR(p))
+-		goto out_err_free_key1;
++		goto out_err_free_conf_key;
+ 
+-	p = simple_get_bytes(p, end, &ctx->keyestb_alg, sizeof(ctx->keyestb_alg));
++	p = simple_get_netobj(p, end, &ctx->derived_integ_key);
+ 	if (IS_ERR(p))
+-		goto out_err_free_key2;
+-
+-	p = simple_get_bytes(p, end, &ctx->owf_alg, sizeof(ctx->owf_alg));
+-	if (IS_ERR(p))
+-		goto out_err_free_key2;
++		goto out_err_free_intg_alg;
+ 
+ 	if (p != end)
+-		goto out_err_free_key2;
++		goto out_err_free_intg_key;
+ 
+ 	ctx_id->internal_ctx_id = ctx;
+ 
+ 	dprintk("Successfully imported new spkm context.\n");
+ 	return 0;
+ 
+-out_err_free_key2:
+-	crypto_free_blkcipher(ctx->derived_integ_key);
+-out_err_free_key1:
+-	crypto_free_blkcipher(ctx->derived_conf_key);
+-out_err_free_s_key:
+-	kfree(ctx->share_key.data);
++out_err_free_intg_key:
++	kfree(ctx->derived_integ_key.data);
++out_err_free_intg_alg:
++	kfree(ctx->intg_alg.data);
++out_err_free_conf_key:
++	kfree(ctx->derived_conf_key.data);
++out_err_free_conf_alg:
++	kfree(ctx->conf_alg.data);
+ out_err_free_mech:
+ 	kfree(ctx->mech_used.data);
+ out_err_free_ctx_id:
+@@ -220,13 +160,16 @@ gss_import_sec_context_spkm3(const void *p, size_t len,
+ }
+ 
+ static void
+-gss_delete_sec_context_spkm3(void *internal_ctx) {
++gss_delete_sec_context_spkm3(void *internal_ctx)
++{
+ 	struct spkm3_ctx *sctx = internal_ctx;
+ 
+-	crypto_free_blkcipher(sctx->derived_integ_key);
+-	crypto_free_blkcipher(sctx->derived_conf_key);
+-	kfree(sctx->share_key.data);
++	kfree(sctx->derived_integ_key.data);
++	kfree(sctx->intg_alg.data);
++	kfree(sctx->derived_conf_key.data);
++	kfree(sctx->conf_alg.data);
+ 	kfree(sctx->mech_used.data);
++	kfree(sctx->ctx_id.data);
+ 	kfree(sctx);
+ }
+ 
+@@ -238,7 +181,6 @@ gss_verify_mic_spkm3(struct gss_ctx		*ctx,
+ 	u32 maj_stat = 0;
+ 	struct spkm3_ctx *sctx = ctx->internal_ctx_id;
+ 
+-	dprintk("RPC: gss_verify_mic_spkm3 calling spkm3_read_token\n");
+ 	maj_stat = spkm3_read_token(sctx, checksum, signbuf, SPKM_MIC_TOK);
+ 
+ 	dprintk("RPC: gss_verify_mic_spkm3 returning %d\n", maj_stat);
+@@ -253,10 +195,9 @@ gss_get_mic_spkm3(struct gss_ctx	*ctx,
+ 	u32 err = 0;
+ 	struct spkm3_ctx *sctx = ctx->internal_ctx_id;
+ 
+-	dprintk("RPC: gss_get_mic_spkm3\n");
+-
+ 	err = spkm3_make_token(sctx, message_buffer,
+-			      message_token, SPKM_MIC_TOK);
++				message_token, SPKM_MIC_TOK);
++	dprintk("RPC: gss_get_mic_spkm3 returning %d\n", err);
+ 	return err;
+ }
+ 
+diff --git a/net/sunrpc/auth_gss/gss_spkm3_seal.c b/net/sunrpc/auth_gss/gss_spkm3_seal.c
+index 18c7862bc234..b179d58c6249 100644
+--- a/net/sunrpc/auth_gss/gss_spkm3_seal.c
++++ b/net/sunrpc/auth_gss/gss_spkm3_seal.c
+@@ -39,11 +39,17 @@
+ #include 
+ #include 
+ #include 
++#include 
++#include 
++#include 
+ 
+ #ifdef RPC_DEBUG
+ # define RPCDBG_FACILITY        RPCDBG_AUTH
+ #endif
+ 
++const struct xdr_netobj hmac_md5_oid = { 8, "\x2B\x06\x01\x05\x05\x08\x01\x01"};
++const struct xdr_netobj cast5_cbc_oid = {9, "\x2A\x86\x48\x86\xF6\x7D\x07\x42\x0A"};
++
+ /*
+  * spkm3_make_token()
+  *
+@@ -66,29 +72,23 @@ spkm3_make_token(struct spkm3_ctx *ctx,
+ 	int			ctxelen = 0, ctxzbit = 0;
+ 	int			md5elen = 0, md5zbit = 0;
+ 
+-	dprintk("RPC: spkm3_make_token\n");
+-
+ 	now = jiffies;
+ 
+ 	if (ctx->ctx_id.len != 16) {
+ 		dprintk("RPC: spkm3_make_token BAD ctx_id.len %d\n",
+-			ctx->ctx_id.len);
++				ctx->ctx_id.len);
+ 		goto out_err;
+ 	}
+-		
+-	switch (ctx->intg_alg) {
+-		case NID_md5:
+-			checksum_type = CKSUMTYPE_RSA_MD5;
+-			break;
+-		default:
+-			dprintk("RPC: gss_spkm3_seal: ctx->signalg %d not"
+-				" supported\n", ctx->intg_alg);
+-			goto out_err;
+-	}
+-	/* XXX since we don't support WRAP, perhaps we don't care... */
+-	if (ctx->conf_alg != NID_cast5_cbc) {
+-		dprintk("RPC: gss_spkm3_seal: ctx->sealalg %d not supported\n",
+-			ctx->conf_alg);
++
++	if (!g_OID_equal(&ctx->intg_alg, &hmac_md5_oid)) {
++		dprintk("RPC: gss_spkm3_seal: unsupported I-ALG algorithm."
++				"only support hmac-md5 I-ALG.\n");
++		goto out_err;
++	} else
++		checksum_type = CKSUMTYPE_HMAC_MD5;
++
++	if (!g_OID_equal(&ctx->conf_alg, &cast5_cbc_oid)) {
++		dprintk("RPC: gss_spkm3_seal: unsupported C-ALG algorithm\n");
+ 		goto out_err;
+ 	}
+ 
+@@ -96,10 +96,10 @@ spkm3_make_token(struct spkm3_ctx *ctx,
+ 		/* Calculate checksum over the mic-header */
+ 		asn1_bitstring_len(&ctx->ctx_id, &ctxelen, &ctxzbit);
+ 		spkm3_mic_header(&mic_hdr.data, &mic_hdr.len, ctx->ctx_id.data,
+-		                         ctxelen, ctxzbit);
+-
+-		if (make_checksum(checksum_type, mic_hdr.data, mic_hdr.len, 
+-		                             text, 0, &md5cksum))
++				ctxelen, ctxzbit);
++		if (make_spkm3_checksum(checksum_type, &ctx->derived_integ_key,
++					(char *)mic_hdr.data, mic_hdr.len,
++					text, 0, &md5cksum))
+ 			goto out_err;
+ 
+ 		asn1_bitstring_len(&md5cksum, &md5elen, &md5zbit);
+@@ -121,7 +121,66 @@ spkm3_make_token(struct spkm3_ctx *ctx,
+ 
+ 	return  GSS_S_COMPLETE;
+ out_err:
++	if (md5cksum.data)
++		kfree(md5cksum.data);
++
+ 	token->data = NULL;
+ 	token->len = 0;
+ 	return GSS_S_FAILURE;
+ }
++
++static int
++spkm3_checksummer(struct scatterlist *sg, void *data)
++{
++	struct hash_desc *desc = data;
++
++	return crypto_hash_update(desc, sg, sg->length);
++}
++
++/* checksum the plaintext data and hdrlen bytes of the token header */
++s32
++make_spkm3_checksum(s32 cksumtype, struct xdr_netobj *key, char *header,
++		    unsigned int hdrlen, struct xdr_buf *body,
++		    unsigned int body_offset, struct xdr_netobj *cksum)
++{
++	char				*cksumname;
++	struct hash_desc		desc; /* XXX add to ctx? */
++	struct scatterlist		sg[1];
++	int err;
++
++	switch (cksumtype) {
++		case CKSUMTYPE_HMAC_MD5:
++			cksumname = "md5";
++			break;
++		default:
++			dprintk("RPC:      spkm3_make_checksum:"
++					" unsupported checksum %d", cksumtype);
++			return GSS_S_FAILURE;
++	}
++
++	if (key->data == NULL || key->len <= 0) return GSS_S_FAILURE;
++
++	desc.tfm = crypto_alloc_hash(cksumname, 0, CRYPTO_ALG_ASYNC);
++	if (IS_ERR(desc.tfm))
++		return GSS_S_FAILURE;
++	cksum->len = crypto_hash_digestsize(desc.tfm);
++	desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
++
++	err = crypto_hash_setkey(desc.tfm, key->data, key->len);
++	if (err)
++		goto out;
++
++	sg_set_buf(sg, header, hdrlen);
++	crypto_hash_update(&desc, sg, 1);
++
++	xdr_process_buf(body, body_offset, body->len - body_offset,
++			spkm3_checksummer, &desc);
++	crypto_hash_final(&desc, cksum->data);
++
++out:
++	crypto_free_hash(desc.tfm);
++
++	return err ? GSS_S_FAILURE : 0;
++}
++
++EXPORT_SYMBOL(make_spkm3_checksum);
+diff --git a/net/sunrpc/auth_gss/gss_spkm3_token.c b/net/sunrpc/auth_gss/gss_spkm3_token.c
+index 854a983ccf26..35188b6ea8f7 100644
+--- a/net/sunrpc/auth_gss/gss_spkm3_token.c
++++ b/net/sunrpc/auth_gss/gss_spkm3_token.c
+@@ -172,10 +172,10 @@ spkm3_mic_header(unsigned char **hdrbuf, unsigned int *hdrlen, unsigned char *ct
+ 	*(u8 *)hptr++ = zbit;
+ 	memcpy(hptr, ctxdata, elen);
+ 	hptr += elen;
+-	*hdrlen = hptr - top; 
++	*hdrlen = hptr - top;
+ }
+-		
+-/* 
++
++/*
+  * spkm3_mic_innercontext_token()
+  *
+  * *tokp points to the beginning of the SPKM_MIC token  described 
+diff --git a/net/sunrpc/auth_gss/gss_spkm3_unseal.c b/net/sunrpc/auth_gss/gss_spkm3_unseal.c
+index 544eb6fd9094..e54581ca7570 100644
+--- a/net/sunrpc/auth_gss/gss_spkm3_unseal.c
++++ b/net/sunrpc/auth_gss/gss_spkm3_unseal.c
+@@ -54,66 +54,70 @@ spkm3_read_token(struct spkm3_ctx *ctx,
+ 		struct xdr_buf *message_buffer, /* signbuf */
+ 		int toktype)
+ {
++	s32			checksum_type;
+ 	s32			code;
+ 	struct xdr_netobj	wire_cksum = {.len =0, .data = NULL};
+ 	char			cksumdata[16];
+ 	struct xdr_netobj	md5cksum = {.len = 0, .data = cksumdata};
+ 	unsigned char		*ptr = (unsigned char *)read_token->data;
+-	unsigned char           *cksum;
++	unsigned char		*cksum;
+ 	int			bodysize, md5elen;
+ 	int			mic_hdrlen;
+ 	u32			ret = GSS_S_DEFECTIVE_TOKEN;
+ 
+-	dprintk("RPC: spkm3_read_token read_token->len %d\n", read_token->len);
+-
+ 	if (g_verify_token_header((struct xdr_netobj *) &ctx->mech_used,
+ 					&bodysize, &ptr, read_token->len))
+ 		goto out;
+ 
+ 	/* decode the token */
+ 
+-	if (toktype == SPKM_MIC_TOK) {
+-
+-		if ((ret = spkm3_verify_mic_token(&ptr, &mic_hdrlen, &cksum))) 
+-			goto out;
+-
+-		if (*cksum++ != 0x03) {
+-			dprintk("RPC: spkm3_read_token BAD checksum type\n");
+-			goto out;
+-		}
+-		md5elen = *cksum++; 
+-		cksum++; 	/* move past the zbit */
+-	
+-		if(!decode_asn1_bitstring(&wire_cksum, cksum, md5elen - 1, 16))
+-			goto out;
+-
+-		/* HARD CODED FOR MD5 */
+-
+-		/* compute the checksum of the message.
+-		*  ptr + 2 = start of header piece of checksum
+-		*  mic_hdrlen + 2 = length of header piece of checksum
+-		*/
+-		ret = GSS_S_DEFECTIVE_TOKEN;
+-		code = make_checksum(CKSUMTYPE_RSA_MD5, ptr + 2, 
+-					mic_hdrlen + 2, 
+-		                        message_buffer, 0, &md5cksum);
+-
+-		if (code)
+-			goto out;
+-
+-		dprintk("RPC: spkm3_read_token: digest wire_cksum.len %d:\n", 
+-			wire_cksum.len);
+-
+-		ret = GSS_S_BAD_SIG;
+-		code = memcmp(md5cksum.data, wire_cksum.data, wire_cksum.len);
+-		if (code)
+-			goto out;
+-
+-	} else { 
+-		dprintk("RPC: BAD or UNSUPPORTED SPKM3 token type: %d\n",toktype);
++	if (toktype != SPKM_MIC_TOK) {
++		dprintk("RPC: BAD SPKM3 token type: %d\n", toktype);
++		goto out;
++	}
++
++	if ((ret = spkm3_verify_mic_token(&ptr, &mic_hdrlen, &cksum)))
++		goto out;
++
++	if (*cksum++ != 0x03) {
++		dprintk("RPC: spkm3_read_token BAD checksum type\n");
++		goto out;
++	}
++	md5elen = *cksum++;
++	cksum++; 	/* move past the zbit */
++
++	if (!decode_asn1_bitstring(&wire_cksum, cksum, md5elen - 1, 16))
++		goto out;
++
++	/* HARD CODED FOR MD5 */
++
++	/* compute the checksum of the message.
++	 * ptr + 2 = start of header piece of checksum
++	 * mic_hdrlen + 2 = length of header piece of checksum
++	 */
++	ret = GSS_S_DEFECTIVE_TOKEN;
++	if (!g_OID_equal(&ctx->intg_alg, &hmac_md5_oid)) {
++		dprintk("RPC: gss_spkm3_seal: unsupported I-ALG algorithm\n");
++		goto out;
++	}
++
++	checksum_type = CKSUMTYPE_HMAC_MD5;
++
++	code = make_spkm3_checksum(checksum_type,
++		&ctx->derived_integ_key, ptr + 2, mic_hdrlen + 2,
++		message_buffer, 0, &md5cksum);
++
++	if (code)
++		goto out;
++
++	ret = GSS_S_BAD_SIG;
++	code = memcmp(md5cksum.data, wire_cksum.data, wire_cksum.len);
++	if (code) {
++		dprintk("RPC: bad MIC checksum\n");
+ 		goto out;
+ 	}
+ 
++
+ 	/* XXX: need to add expiration and sequencing */
+ 	ret = GSS_S_COMPLETE;
+ out:

commit 37a4e6cb0391f2293ba3d59e3a63ec0e56ed720d
+Author: Olga Kornievskaia 
+Date:   Mon Dec 4 20:22:33 2006 -0500
+
+    rpc: move process_xdr_buf
+    
+    Since process_xdr_buf() is useful outside of the kerberos-specific code, we
+    move it to net/sunrpc/xdr.c, export it, and rename it in keeping with xdr_*
+    naming convention of xdr.c.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
+index 441b91dbafe5..4d17846cd78a 100644
+--- a/include/linux/sunrpc/xdr.h
++++ b/include/linux/sunrpc/xdr.h
+@@ -11,6 +11,7 @@
+ 
+ #include 
+ #include 
++#include 
+ 
+ /*
+  * Buffer adjustment
+@@ -196,6 +197,7 @@ extern void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32
+ extern __be32 *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes);
+ extern void xdr_read_pages(struct xdr_stream *xdr, unsigned int len);
+ extern void xdr_enter_page(struct xdr_stream *xdr, unsigned int len);
++extern int xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len, int (*actor)(struct scatterlist *, void *), void *data);
+ 
+ #endif /* __KERNEL__ */
+ 
+diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+index 4c53896f1b08..10d05ea37213 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
++++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+@@ -43,6 +43,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #ifdef RPC_DEBUG
+ # define RPCDBG_FACILITY        RPCDBG_AUTH
+@@ -119,72 +120,6 @@ krb5_decrypt(
+ 
+ EXPORT_SYMBOL(krb5_decrypt);
+ 
+-static int
+-process_xdr_buf(struct xdr_buf *buf, int offset, int len,
+-		int (*actor)(struct scatterlist *, void *), void *data)
+-{
+-	int i, page_len, thislen, page_offset, ret = 0;
+-	struct scatterlist	sg[1];
+-
+-	if (offset >= buf->head[0].iov_len) {
+-		offset -= buf->head[0].iov_len;
+-	} else {
+-		thislen = buf->head[0].iov_len - offset;
+-		if (thislen > len)
+-			thislen = len;
+-		sg_set_buf(sg, buf->head[0].iov_base + offset, thislen);
+-		ret = actor(sg, data);
+-		if (ret)
+-			goto out;
+-		offset = 0;
+-		len -= thislen;
+-	}
+-	if (len == 0)
+-		goto out;
+-
+-	if (offset >= buf->page_len) {
+-		offset -= buf->page_len;
+-	} else {
+-		page_len = buf->page_len - offset;
+-		if (page_len > len)
+-			page_len = len;
+-		len -= page_len;
+-		page_offset = (offset + buf->page_base) & (PAGE_CACHE_SIZE - 1);
+-		i = (offset + buf->page_base) >> PAGE_CACHE_SHIFT;
+-		thislen = PAGE_CACHE_SIZE - page_offset;
+-		do {
+-			if (thislen > page_len)
+-				thislen = page_len;
+-			sg->page = buf->pages[i];
+-			sg->offset = page_offset;
+-			sg->length = thislen;
+-			ret = actor(sg, data);
+-			if (ret)
+-				goto out;
+-			page_len -= thislen;
+-			i++;
+-			page_offset = 0;
+-			thislen = PAGE_CACHE_SIZE;
+-		} while (page_len != 0);
+-		offset = 0;
+-	}
+-	if (len == 0)
+-		goto out;
+-
+-	if (offset < buf->tail[0].iov_len) {
+-		thislen = buf->tail[0].iov_len - offset;
+-		if (thislen > len)
+-			thislen = len;
+-		sg_set_buf(sg, buf->tail[0].iov_base + offset, thislen);
+-		ret = actor(sg, data);
+-		len -= thislen;
+-	}
+-	if (len != 0)
+-		ret = -EINVAL;
+-out:
+-	return ret;
+-}
+-
+ static int
+ checksummer(struct scatterlist *sg, void *data)
+ {
+@@ -225,7 +160,7 @@ make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
+ 	err = crypto_hash_update(&desc, sg, hdrlen);
+ 	if (err)
+ 		goto out;
+-	err = process_xdr_buf(body, body_offset, body->len - body_offset,
++	err = xdr_process_buf(body, body_offset, body->len - body_offset,
+ 			      checksummer, &desc);
+ 	if (err)
+ 		goto out;
+@@ -323,7 +258,7 @@ gss_encrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *buf,
+ 	desc.fragno = 0;
+ 	desc.fraglen = 0;
+ 
+-	ret = process_xdr_buf(buf, offset, buf->len - offset, encryptor, &desc);
++	ret = xdr_process_buf(buf, offset, buf->len - offset, encryptor, &desc);
+ 	return ret;
+ }
+ 
+@@ -389,7 +324,7 @@ gss_decrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *buf,
+ 	desc.desc.flags = 0;
+ 	desc.fragno = 0;
+ 	desc.fraglen = 0;
+-	return process_xdr_buf(buf, offset, buf->len - offset, decryptor, &desc);
++	return xdr_process_buf(buf, offset, buf->len - offset, decryptor, &desc);
+ }
+ 
+ EXPORT_SYMBOL(gss_decrypt_xdr_buf);
+diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
+index 5a6485946f3c..a0af250ca319 100644
+--- a/net/sunrpc/xdr.c
++++ b/net/sunrpc/xdr.c
+@@ -1021,3 +1021,71 @@ xdr_encode_array2(struct xdr_buf *buf, unsigned int base,
+ 
+ 	return xdr_xcode_array2(buf, base, desc, 1);
+ }
++
++int
++xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len,
++                int (*actor)(struct scatterlist *, void *), void *data)
++{
++	int i, ret = 0;
++	unsigned page_len, thislen, page_offset;
++	struct scatterlist      sg[1];
++
++	if (offset >= buf->head[0].iov_len) {
++		offset -= buf->head[0].iov_len;
++	} else {
++		thislen = buf->head[0].iov_len - offset;
++		if (thislen > len)
++			thislen = len;
++		sg_set_buf(sg, buf->head[0].iov_base + offset, thislen);
++		ret = actor(sg, data);
++		if (ret)
++			goto out;
++		offset = 0;
++		len -= thislen;
++	}
++	if (len == 0)
++		goto out;
++
++	if (offset >= buf->page_len) {
++		offset -= buf->page_len;
++	} else {
++		page_len = buf->page_len - offset;
++		if (page_len > len)
++			page_len = len;
++		len -= page_len;
++		page_offset = (offset + buf->page_base) & (PAGE_CACHE_SIZE - 1);
++		i = (offset + buf->page_base) >> PAGE_CACHE_SHIFT;
++		thislen = PAGE_CACHE_SIZE - page_offset;
++		do {
++			if (thislen > page_len)
++				thislen = page_len;
++			sg->page = buf->pages[i];
++			sg->offset = page_offset;
++			sg->length = thislen;
++			ret = actor(sg, data);
++			if (ret)
++				goto out;
++			page_len -= thislen;
++			i++;
++			page_offset = 0;
++			thislen = PAGE_CACHE_SIZE;
++		} while (page_len != 0);
++		offset = 0;
++	}
++	if (len == 0)
++		goto out;
++	if (offset < buf->tail[0].iov_len) {
++		thislen = buf->tail[0].iov_len - offset;
++		if (thislen > len)
++			thislen = len;
++		sg_set_buf(sg, buf->tail[0].iov_base + offset, thislen);
++		ret = actor(sg, data);
++		len -= thislen;
++	}
++	if (len != 0)
++		ret = -EINVAL;
++out:
++	return ret;
++}
++EXPORT_SYMBOL(xdr_process_buf);
++

commit 8fc7500bb8ea3b5c909869d00628635e964ae882
+Author: J. Bruce Fields 
+Date:   Mon Dec 4 20:22:31 2006 -0500
+
+    rpc: gss: eliminate print_hexl()'s
+    
+    Dumping all this data to the logs is wasteful (even when debugging is turned
+    off), and creates too much output to be useful when it's turned on.
+    
+    Fix a minor style bug or two while we're at it.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/auth_gss.h b/include/linux/sunrpc/auth_gss.h
+index 97b62e97dd8d..2db2fbf34947 100644
+--- a/include/linux/sunrpc/auth_gss.h
++++ b/include/linux/sunrpc/auth_gss.h
+@@ -90,8 +90,6 @@ struct gss_cred {
+ #define gc_flags		gc_base.cr_flags
+ #define gc_expire		gc_base.cr_expire
+ 
+-void print_hexl(u32 *p, u_int length, u_int offset);
+-
+ #endif /* __KERNEL__ */
+ #endif /* _LINUX_SUNRPC_AUTH_GSS_H */
+ 
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index e5a84a482e57..d12ee5f54c0c 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -94,46 +94,6 @@ struct gss_auth {
+ static void gss_destroy_ctx(struct gss_cl_ctx *);
+ static struct rpc_pipe_ops gss_upcall_ops;
+ 
+-void
+-print_hexl(u32 *p, u_int length, u_int offset)
+-{
+-	u_int i, j, jm;
+-	u8 c, *cp;
+-	
+-	dprintk("RPC: print_hexl: length %d\n",length);
+-	dprintk("\n");
+-	cp = (u8 *) p;
+-	
+-	for (i = 0; i < length; i += 0x10) {
+-		dprintk("  %04x: ", (u_int)(i + offset));
+-		jm = length - i;
+-		jm = jm > 16 ? 16 : jm;
+-		
+-		for (j = 0; j < jm; j++) {
+-			if ((j % 2) == 1)
+-				dprintk("%02x ", (u_int)cp[i+j]);
+-			else
+-				dprintk("%02x", (u_int)cp[i+j]);
+-		}
+-		for (; j < 16; j++) {
+-			if ((j % 2) == 1)
+-				dprintk("   ");
+-			else
+-				dprintk("  ");
+-		}
+-		dprintk(" ");
+-		
+-		for (j = 0; j < jm; j++) {
+-			c = cp[i+j];
+-			c = isprint(c) ? c : '.';
+-			dprintk("%c", c);
+-		}
+-		dprintk("\n");
+-	}
+-}
+-
+-EXPORT_SYMBOL(print_hexl);
+-
+ static inline struct gss_cl_ctx *
+ gss_get_ctx(struct gss_cl_ctx *ctx)
+ {
+diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+index e11a40b25cce..4c53896f1b08 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
++++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+@@ -61,9 +61,6 @@ krb5_encrypt(
+ 	u8 local_iv[16] = {0};
+ 	struct blkcipher_desc desc = { .tfm = tfm, .info = local_iv };
+ 
+-	dprintk("RPC:      krb5_encrypt: input data:\n");
+-	print_hexl((u32 *)in, length, 0);
+-
+ 	if (length % crypto_blkcipher_blocksize(tfm) != 0)
+ 		goto out;
+ 
+@@ -80,12 +77,9 @@ krb5_encrypt(
+ 	sg_set_buf(sg, out, length);
+ 
+ 	ret = crypto_blkcipher_encrypt_iv(&desc, sg, sg, length);
+-
+-	dprintk("RPC:      krb5_encrypt: output data:\n");
+-	print_hexl((u32 *)out, length, 0);
+ out:
+ 	dprintk("RPC:      krb5_encrypt returns %d\n",ret);
+-	return(ret);
++	return ret;
+ }
+ 
+ EXPORT_SYMBOL(krb5_encrypt);
+@@ -103,9 +97,6 @@ krb5_decrypt(
+ 	u8 local_iv[16] = {0};
+ 	struct blkcipher_desc desc = { .tfm = tfm, .info = local_iv };
+ 
+-	dprintk("RPC:      krb5_decrypt: input data:\n");
+-	print_hexl((u32 *)in, length, 0);
+-
+ 	if (length % crypto_blkcipher_blocksize(tfm) != 0)
+ 		goto out;
+ 
+@@ -121,12 +112,9 @@ krb5_decrypt(
+ 	sg_set_buf(sg, out, length);
+ 
+ 	ret = crypto_blkcipher_decrypt_iv(&desc, sg, sg, length);
+-
+-	dprintk("RPC:      krb5_decrypt: output_data:\n");
+-	print_hexl((u32 *)out, length, 0);
+ out:
+ 	dprintk("RPC:      gss_k5decrypt returns %d\n",ret);
+-	return(ret);
++	return ret;
+ }
+ 
+ EXPORT_SYMBOL(krb5_decrypt);
+diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
+index 08601ee4cd73..dc58af0b8b4c 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
+@@ -129,9 +129,6 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
+ 		memcpy(krb5_hdr + 16,
+ 		       md5cksum.data + md5cksum.len - KRB5_CKSUM_LENGTH,
+ 		       KRB5_CKSUM_LENGTH);
+-
+-		dprintk("RPC:      make_seal_token: cksum data: \n");
+-		print_hexl((u32 *) (krb5_hdr + 16), KRB5_CKSUM_LENGTH, 0);
+ 		break;
+ 	default:
+ 		BUG();
+diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+index cc45c1605f80..0f512e8e0d19 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
++++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+@@ -199,9 +199,6 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
+ 		memcpy(krb5_hdr + 16,
+ 		       md5cksum.data + md5cksum.len - KRB5_CKSUM_LENGTH,
+ 		       KRB5_CKSUM_LENGTH);
+-
+-		dprintk("RPC:      make_seal_token: cksum data: \n");
+-		print_hexl((u32 *) (krb5_hdr + 16), KRB5_CKSUM_LENGTH, 0);
+ 		break;
+ 	default:
+ 		BUG();
+diff --git a/net/sunrpc/auth_gss/gss_spkm3_unseal.c b/net/sunrpc/auth_gss/gss_spkm3_unseal.c
+index 8537f581ef9b..544eb6fd9094 100644
+--- a/net/sunrpc/auth_gss/gss_spkm3_unseal.c
++++ b/net/sunrpc/auth_gss/gss_spkm3_unseal.c
+@@ -103,10 +103,6 @@ spkm3_read_token(struct spkm3_ctx *ctx,
+ 
+ 		dprintk("RPC: spkm3_read_token: digest wire_cksum.len %d:\n", 
+ 			wire_cksum.len);
+-		dprintk("          md5cksum.data\n");
+-		print_hexl((u32 *) md5cksum.data, 16, 0);
+-		dprintk("          cksum.data:\n");
+-		print_hexl((u32 *) wire_cksum.data, wire_cksum.len, 0);
+ 
+ 		ret = GSS_S_BAD_SIG;
+ 		code = memcmp(md5cksum.data, wire_cksum.data, wire_cksum.len);

commit 2dec51466a08ac1c67da41bfd0518d43d983a2eb
+Author: J. Bruce Fields 
+Date:   Tue Sep 12 11:53:23 2006 -0400
+
+    NFSv4: It's perfectly legal for clp to be NULL here....
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/client.c b/fs/nfs/client.c
+index 110f80e7bd4c..ec1938d4b814 100644
+--- a/fs/nfs/client.c
++++ b/fs/nfs/client.c
+@@ -269,7 +269,7 @@ struct nfs_client *nfs_find_client(const struct sockaddr_in *addr, int nfsversio
+ 	clp = __nfs_find_client(addr, nfsversion);
+ 	spin_unlock(&nfs_client_lock);
+ 
+-	BUG_ON(clp->cl_cons_state == 0);
++	BUG_ON(clp && clp->cl_cons_state == 0);
+ 
+ 	return clp;
+ }

commit 297de4f65698ee1e1c75e27d57933b5fa8227e72
+Author: Andy Adamson 
+Date:   Tue Aug 29 12:19:41 2006 -0400
+
+    Fix a referral error Oops
+    
+    Fix an oops when the referral server is not responding.
+    Check the error return from nfs4_set_client() in nfs4_create_referral_server.
+    
+    Signed-off-by: Andy Adamson 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/client.c b/fs/nfs/client.c
+index a4aa47913a5c..110f80e7bd4c 100644
+--- a/fs/nfs/client.c
++++ b/fs/nfs/client.c
+@@ -1059,6 +1059,8 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
+ 			parent_server->client->cl_xprt->prot,
+ 			parent_client->retrans_timeo,
+ 			parent_client->retrans_count);
++	if (error < 0)
++		goto error;
+ 
+ 	/* Initialise the client representation from the parent server */
+ 	nfs_server_copy_userdata(server, parent_server);

commit 7c9fdcfb1b64c47ed618c103b617af3f86e1239c
+Author: J. Bruce Fields 
+Date:   Fri Jun 30 01:56:19 2006 -0700
+
+    [PATCH] knfsd: svcrpc: gss: server-side implementation of rpcsec_gss privacy
+    
+    Server-side implementation of rpcsec_gss privacy, which enables encryption of
+    the payload of every rpc request and response.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
+index ce8dc0db214e..94217ec9e2dd 100644
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -832,6 +832,74 @@ unwrap_integ_data(struct xdr_buf *buf, u32 seq, struct gss_ctx *ctx)
+ 	return stat;
+ }
+ 
++static inline int
++total_buf_len(struct xdr_buf *buf)
++{
++	return buf->head[0].iov_len + buf->page_len + buf->tail[0].iov_len;
++}
++
++static void
++fix_priv_head(struct xdr_buf *buf, int pad)
++{
++	if (buf->page_len == 0) {
++		/* We need to adjust head and buf->len in tandem in this
++		 * case to make svc_defer() work--it finds the original
++		 * buffer start using buf->len - buf->head[0].iov_len. */
++		buf->head[0].iov_len -= pad;
++	}
++}
++
++static int
++unwrap_priv_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct gss_ctx *ctx)
++{
++	u32 priv_len, maj_stat;
++	int pad, saved_len, remaining_len, offset;
++
++	rqstp->rq_sendfile_ok = 0;
++
++	priv_len = ntohl(svc_getu32(&buf->head[0]));
++	if (rqstp->rq_deferred) {
++		/* Already decrypted last time through! The sequence number
++		 * check at out_seq is unnecessary but harmless: */
++		goto out_seq;
++	}
++	/* buf->len is the number of bytes from the original start of the
++	 * request to the end, where head[0].iov_len is just the bytes
++	 * not yet read from the head, so these two values are different: */
++	remaining_len = total_buf_len(buf);
++	if (priv_len > remaining_len)
++		return -EINVAL;
++	pad = remaining_len - priv_len;
++	buf->len -= pad;
++	fix_priv_head(buf, pad);
++
++	/* Maybe it would be better to give gss_unwrap a length parameter: */
++	saved_len = buf->len;
++	buf->len = priv_len;
++	maj_stat = gss_unwrap(ctx, 0, buf);
++	pad = priv_len - buf->len;
++	buf->len = saved_len;
++	buf->len -= pad;
++	/* The upper layers assume the buffer is aligned on 4-byte boundaries.
++	 * In the krb5p case, at least, the data ends up offset, so we need to
++	 * move it around. */
++	/* XXX: This is very inefficient.  It would be better to either do
++	 * this while we encrypt, or maybe in the receive code, if we can peak
++	 * ahead and work out the service and mechanism there. */
++	offset = buf->head[0].iov_len % 4;
++	if (offset) {
++		buf->buflen = RPCSVC_MAXPAYLOAD;
++		xdr_shift_buf(buf, offset);
++		fix_priv_head(buf, pad);
++	}
++	if (maj_stat != GSS_S_COMPLETE)
++		return -EINVAL;
++out_seq:
++	if (ntohl(svc_getu32(&buf->head[0])) != seq)
++		return -EINVAL;
++	return 0;
++}
++
+ struct gss_svc_data {
+ 	/* decoded gss client cred: */
+ 	struct rpc_gss_wire_cred	clcred;
+@@ -1047,7 +1115,14 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
+ 			svc_putu32(resv, 0);
+ 			break;
+ 		case RPC_GSS_SVC_PRIVACY:
+-			/* currently unsupported */
++			if (unwrap_priv_data(rqstp, &rqstp->rq_arg,
++					gc->gc_seq, rsci->mechctx))
++				goto auth_err;
++			/* placeholders for length and seq. number: */
++			svcdata->body_start = resv->iov_base + resv->iov_len;
++			svc_putu32(resv, 0);
++			svc_putu32(resv, 0);
++			break;
+ 		default:
+ 			goto auth_err;
+ 		}
+@@ -1089,9 +1164,8 @@ svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp)
+ 	gsd->body_start = NULL;
+ 	/* move accept_stat to right place: */
+ 	memcpy(p, p + 2, 4);
+-	/* don't wrap in failure case: */
+-	/* Note: counting on not getting here if call was not even
+-	 * accepted! */
++	/* Don't wrap in failure case: */
++	/* Counting on not getting here if call was not even accepted! */
+ 	if (*p != rpc_success) {
+ 		resbuf->head[0].iov_len -= 2 * 4;
+ 		goto out;
+@@ -1138,6 +1212,65 @@ svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp)
+ 	return stat;
+ }
+ 
++static inline int
++svcauth_gss_wrap_resp_priv(struct svc_rqst *rqstp)
++{
++	struct gss_svc_data *gsd = (struct gss_svc_data *)rqstp->rq_auth_data;
++	struct rpc_gss_wire_cred *gc = &gsd->clcred;
++	struct xdr_buf *resbuf = &rqstp->rq_res;
++	struct page **inpages = NULL;
++	u32 *p;
++	int offset, *len;
++	int pad;
++
++	p = gsd->body_start;
++	gsd->body_start = NULL;
++	/* move accept_stat to right place: */
++	memcpy(p, p + 2, 4);
++	/* Don't wrap in failure case: */
++	/* Counting on not getting here if call was not even accepted! */
++	if (*p != rpc_success) {
++		resbuf->head[0].iov_len -= 2 * 4;
++		return 0;
++	}
++	p++;
++	len = p++;
++	offset = (u8 *)p - (u8 *)resbuf->head[0].iov_base;
++	*p++ = htonl(gc->gc_seq);
++	inpages = resbuf->pages;
++	/* XXX: Would be better to write some xdr helper functions for
++	 * nfs{2,3,4}xdr.c that place the data right, instead of copying: */
++	if (resbuf->tail[0].iov_base && rqstp->rq_restailpage == 0) {
++		BUG_ON(resbuf->tail[0].iov_base >= resbuf->head[0].iov_base
++							+ PAGE_SIZE);
++		BUG_ON(resbuf->tail[0].iov_base < resbuf->head[0].iov_base);
++		if (resbuf->tail[0].iov_len + resbuf->head[0].iov_len
++				+ 2 * RPC_MAX_AUTH_SIZE > PAGE_SIZE)
++			return -ENOMEM;
++		memmove(resbuf->tail[0].iov_base + RPC_MAX_AUTH_SIZE,
++			resbuf->tail[0].iov_base,
++			resbuf->tail[0].iov_len);
++		resbuf->tail[0].iov_base += RPC_MAX_AUTH_SIZE;
++	}
++	if (resbuf->tail[0].iov_base == NULL) {
++		if (resbuf->head[0].iov_len + 2*RPC_MAX_AUTH_SIZE > PAGE_SIZE)
++			return -ENOMEM;
++		resbuf->tail[0].iov_base = resbuf->head[0].iov_base
++			+ resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE;
++		resbuf->tail[0].iov_len = 0;
++		rqstp->rq_restailpage = 0;
++	}
++	if (gss_wrap(gsd->rsci->mechctx, offset, resbuf, inpages))
++		return -ENOMEM;
++	*len = htonl(resbuf->len - offset);
++	pad = 3 - ((resbuf->len - offset - 1)&3);
++	p = (u32 *)(resbuf->tail[0].iov_base + resbuf->tail[0].iov_len);
++	memset(p, 0, pad);
++	resbuf->tail[0].iov_len += pad;
++	resbuf->len += pad;
++	return 0;
++}
++
+ static int
+ svcauth_gss_release(struct svc_rqst *rqstp)
+ {
+@@ -1152,15 +1285,22 @@ svcauth_gss_release(struct svc_rqst *rqstp)
+ 	if (gsd->body_start == NULL)
+ 		goto out;
+ 	/* normally not set till svc_send, but we need it here: */
+-	resbuf->len = resbuf->head[0].iov_len
+-		+ resbuf->page_len + resbuf->tail[0].iov_len;
++	/* XXX: what for?  Do we mess it up the moment we call svc_putu32
++	 * or whatever? */
++	resbuf->len = total_buf_len(resbuf);
+ 	switch (gc->gc_svc) {
+ 	case RPC_GSS_SVC_NONE:
+ 		break;
+ 	case RPC_GSS_SVC_INTEGRITY:
+-		svcauth_gss_wrap_resp_integ(rqstp);
++		stat = svcauth_gss_wrap_resp_integ(rqstp);
++		if (stat)
++			goto out_err;
+ 		break;
+ 	case RPC_GSS_SVC_PRIVACY:
++		stat = svcauth_gss_wrap_resp_priv(rqstp);
++		if (stat)
++			goto out_err;
++		break;
+ 	default:
+ 		goto out_err;
+ 	}
+diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
+index fb168a30fd3f..01ba60a49572 100644
+--- a/net/sunrpc/svc.c
++++ b/net/sunrpc/svc.c
+@@ -280,6 +280,7 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
+ 	rqstp->rq_res.page_base = 0;
+ 	rqstp->rq_res.page_len = 0;
+ 	rqstp->rq_res.buflen = PAGE_SIZE;
++	rqstp->rq_res.tail[0].iov_base = NULL;
+ 	rqstp->rq_res.tail[0].iov_len = 0;
+ 	/* Will be turned off only in gss privacy case: */
+ 	rqstp->rq_sendfile_ok = 1;

commit 5c04c46aec16b3267d8fe03af886f2d41e448cd0
+Author: J. Bruce Fields 
+Date:   Fri Jun 30 01:56:19 2006 -0700
+
+    [PATCH] knfsd: nfsd: mark rqstp to prevent use of sendfile in privacy case
+    
+    Add a rq_sendfile_ok flag to svc_rqst which will be cleared in the privacy
+    case so that the wrapping code will get copies of the read data instead of
+    real page cache pages.  This makes life simpler when we encrypt the response.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index 423e1ba07044..e170030d45da 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -837,7 +837,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+ 	if (ra && ra->p_set)
+ 		file->f_ra = ra->p_ra;
+ 
+-	if (file->f_op->sendfile) {
++	if (file->f_op->sendfile && rqstp->rq_sendfile_ok) {
+ 		svc_pushback_unused_pages(rqstp);
+ 		err = file->f_op->sendfile(file, &offset, *count,
+ 						 nfsd_read_actor, rqstp);
+diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
+index 503564384545..7b27c09b5604 100644
+--- a/include/linux/sunrpc/svc.h
++++ b/include/linux/sunrpc/svc.h
+@@ -159,7 +159,9 @@ struct svc_rqst {
+ 						 * determine what device number
+ 						 * to report (real or virtual)
+ 						 */
+-
++	int			rq_sendfile_ok; /* turned off in gss privacy
++						 * to prevent encrypting page
++						 * cache pages */
+ 	wait_queue_head_t	rq_wait;	/* synchronization */
+ };
+ 
+diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
+index b08419e1fc68..fb168a30fd3f 100644
+--- a/net/sunrpc/svc.c
++++ b/net/sunrpc/svc.c
+@@ -281,6 +281,8 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
+ 	rqstp->rq_res.page_len = 0;
+ 	rqstp->rq_res.buflen = PAGE_SIZE;
+ 	rqstp->rq_res.tail[0].iov_len = 0;
++	/* Will be turned off only in gss privacy case: */
++	rqstp->rq_sendfile_ok = 1;
+ 	/* tcp needs a space for the record length... */
+ 	if (rqstp->rq_prot == IPPROTO_TCP)
+ 		svc_putu32(resv, 0);

commit e142ede8e064cb1ae9c2bfb17f36ab145b95ccd2
+Author: J. Bruce Fields 
+Date:   Fri Jun 30 01:56:18 2006 -0700
+
+    [PATCH] knfsd: svcrpc: Simplify nfsd rpcsec_gss integrity code
+    
+    Pull out some of the integrity code into its own function, otherwise
+    svcauth_gss_release() is going to become very ungainly after the addition of
+    privacy code.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
+index 71f57a5d800d..ce8dc0db214e 100644
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -1072,8 +1072,8 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
+ 	return ret;
+ }
+ 
+-static int
+-svcauth_gss_release(struct svc_rqst *rqstp)
++static inline int
++svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp)
+ {
+ 	struct gss_svc_data *gsd = (struct gss_svc_data *)rqstp->rq_auth_data;
+ 	struct rpc_gss_wire_cred *gc = &gsd->clcred;
+@@ -1085,6 +1085,67 @@ svcauth_gss_release(struct svc_rqst *rqstp)
+ 	int integ_offset, integ_len;
+ 	int stat = -EINVAL;
+ 
++	p = gsd->body_start;
++	gsd->body_start = NULL;
++	/* move accept_stat to right place: */
++	memcpy(p, p + 2, 4);
++	/* don't wrap in failure case: */
++	/* Note: counting on not getting here if call was not even
++	 * accepted! */
++	if (*p != rpc_success) {
++		resbuf->head[0].iov_len -= 2 * 4;
++		goto out;
++	}
++	p++;
++	integ_offset = (u8 *)(p + 1) - (u8 *)resbuf->head[0].iov_base;
++	integ_len = resbuf->len - integ_offset;
++	BUG_ON(integ_len % 4);
++	*p++ = htonl(integ_len);
++	*p++ = htonl(gc->gc_seq);
++	if (xdr_buf_subsegment(resbuf, &integ_buf, integ_offset,
++				integ_len))
++		BUG();
++	if (resbuf->page_len == 0
++			&& resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE
++			< PAGE_SIZE) {
++		BUG_ON(resbuf->tail[0].iov_len);
++		/* Use head for everything */
++		resv = &resbuf->head[0];
++	} else if (resbuf->tail[0].iov_base == NULL) {
++		if (resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE > PAGE_SIZE)
++			goto out_err;
++		resbuf->tail[0].iov_base = resbuf->head[0].iov_base
++						+ resbuf->head[0].iov_len;
++		resbuf->tail[0].iov_len = 0;
++		rqstp->rq_restailpage = 0;
++		resv = &resbuf->tail[0];
++	} else {
++		resv = &resbuf->tail[0];
++	}
++	mic.data = (u8 *)resv->iov_base + resv->iov_len + 4;
++	if (gss_get_mic(gsd->rsci->mechctx, &integ_buf, &mic))
++		goto out_err;
++	svc_putu32(resv, htonl(mic.len));
++	memset(mic.data + mic.len, 0,
++			round_up_to_quad(mic.len) - mic.len);
++	resv->iov_len += XDR_QUADLEN(mic.len) << 2;
++	/* not strictly required: */
++	resbuf->len += XDR_QUADLEN(mic.len) << 2;
++	BUG_ON(resv->iov_len > PAGE_SIZE);
++out:
++	stat = 0;
++out_err:
++	return stat;
++}
++
++static int
++svcauth_gss_release(struct svc_rqst *rqstp)
++{
++	struct gss_svc_data *gsd = (struct gss_svc_data *)rqstp->rq_auth_data;
++	struct rpc_gss_wire_cred *gc = &gsd->clcred;
++	struct xdr_buf *resbuf = &rqstp->rq_res;
++	int stat = -EINVAL;
++
+ 	if (gc->gc_proc != RPC_GSS_PROC_DATA)
+ 		goto out;
+ 	/* Release can be called twice, but we only wrap once. */
+@@ -1097,55 +1158,7 @@ svcauth_gss_release(struct svc_rqst *rqstp)
+ 	case RPC_GSS_SVC_NONE:
+ 		break;
+ 	case RPC_GSS_SVC_INTEGRITY:
+-		p = gsd->body_start;
+-		gsd->body_start = NULL;
+-		/* move accept_stat to right place: */
+-		memcpy(p, p + 2, 4);
+-		/* don't wrap in failure case: */
+-		/* Note: counting on not getting here if call was not even
+-		 * accepted! */
+-		if (*p != rpc_success) {
+-			resbuf->head[0].iov_len -= 2 * 4;
+-			goto out;
+-		}
+-		p++;
+-		integ_offset = (u8 *)(p + 1) - (u8 *)resbuf->head[0].iov_base;
+-		integ_len = resbuf->len - integ_offset;
+-		BUG_ON(integ_len % 4);
+-		*p++ = htonl(integ_len);
+-		*p++ = htonl(gc->gc_seq);
+-		if (xdr_buf_subsegment(resbuf, &integ_buf, integ_offset,
+-					integ_len))
+-			BUG();
+-		if (resbuf->page_len == 0
+-			&& resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE
+-				< PAGE_SIZE) {
+-			BUG_ON(resbuf->tail[0].iov_len);
+-			/* Use head for everything */
+-			resv = &resbuf->head[0];
+-		} else if (resbuf->tail[0].iov_base == NULL) {
+-			if (resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE
+-					> PAGE_SIZE)
+-				goto out_err;
+-			resbuf->tail[0].iov_base =
+-				resbuf->head[0].iov_base
+-				+ resbuf->head[0].iov_len;
+-			resbuf->tail[0].iov_len = 0;
+-			rqstp->rq_restailpage = 0;
+-			resv = &resbuf->tail[0];
+-		} else {
+-			resv = &resbuf->tail[0];
+-		}
+-		mic.data = (u8 *)resv->iov_base + resv->iov_len + 4;
+-		if (gss_get_mic(gsd->rsci->mechctx, &integ_buf, &mic))
+-			goto out_err;
+-		svc_putu32(resv, htonl(mic.len));
+-		memset(mic.data + mic.len, 0,
+-				round_up_to_quad(mic.len) - mic.len);
+-		resv->iov_len += XDR_QUADLEN(mic.len) << 2;
+-		/* not strictly required: */
+-		resbuf->len += XDR_QUADLEN(mic.len) << 2;
+-		BUG_ON(resv->iov_len > PAGE_SIZE);
++		svcauth_gss_wrap_resp_integ(rqstp);
+ 		break;
+ 	case RPC_GSS_SVC_PRIVACY:
+ 	default:

commit 9ecb6a08d84d0e795648d5add64f154bc406914b
+Author: J. Bruce Fields 
+Date:   Fri Jun 30 01:56:17 2006 -0700
+
+    [PATCH] knfsd: nfsd4: fix open flag passing
+    
+    Since nfsv4 actually keeps around the file descriptors it gets from open
+    (instead of just using them for a single read or write operation), we need to
+    make sure that we can do RDWR opens and not just RDONLY/WRONLY.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 591dc6ba6e19..9daa0b9feb8d 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1790,10 +1790,10 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
+ 	} else {
+ 		/* Stateid was not found, this is a new OPEN */
+ 		int flags = 0;
++		if (open->op_share_access & NFS4_SHARE_ACCESS_READ)
++			flags |= MAY_READ;
+ 		if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
+-			flags = MAY_WRITE;
+-		else
+-			flags = MAY_READ;
++			flags |= MAY_WRITE;
+ 		status = nfs4_new_open(rqstp, &stp, dp, current_fh, flags);
+ 		if (status)
+ 			goto out;
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index f916b170e136..423e1ba07044 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -673,7 +673,10 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
+ 		goto out_nfserr;
+ 
+ 	if (access & MAY_WRITE) {
+-		flags = O_WRONLY|O_LARGEFILE;
++		if (access & MAY_READ)
++			flags = O_RDWR|O_LARGEFILE;
++		else
++			flags = O_WRONLY|O_LARGEFILE;
+ 
+ 		DQUOT_INIT(inode);
+ 	}

commit ba5a6a19d83babe00be3711db3deee5c57587b8f
+Author: J. Bruce Fields 
+Date:   Fri Jun 30 01:56:16 2006 -0700
+
+    [PATCH] knfsd: nfsd4: fix some open argument tests
+    
+    These tests always returned true; clearly that wasn't what was intended.
+    
+    In keeping with kernel style, make them functions instead of macros while
+    we're at it.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 4810577347cf..591dc6ba6e19 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1237,8 +1237,15 @@ find_file(struct inode *ino)
+ 	return NULL;
+ }
+ 
+-#define TEST_ACCESS(x) ((x > 0 || x < 4)?1:0)
+-#define TEST_DENY(x) ((x >= 0 || x < 5)?1:0)
++static int access_valid(u32 x)
++{
++	return (x > 0 && x < 4);
++}
++
++static int deny_valid(u32 x)
++{
++	return (x >= 0 && x < 5);
++}
+ 
+ static void
+ set_access(unsigned int *access, unsigned long bmap) {
+@@ -1745,7 +1752,8 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
+ 	int status;
+ 
+ 	status = nfserr_inval;
+-	if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny))
++	if (!access_valid(open->op_share_access)
++			|| !deny_valid(open->op_share_deny))
+ 		goto out;
+ 	/*
+ 	 * Lookup file; if found, lookup stateid and check open request,
+@@ -2317,7 +2325,8 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct n
+ 			(int)current_fh->fh_dentry->d_name.len,
+ 			current_fh->fh_dentry->d_name.name);
+ 
+-	if (!TEST_ACCESS(od->od_share_access) || !TEST_DENY(od->od_share_deny))
++	if (!access_valid(od->od_share_access)
++			|| !deny_valid(od->od_share_deny))
+ 		return nfserr_inval;
+ 
+ 	nfs4_lock_state();

commit 1df0cada03644e37ae6fefd7c0267d9a531991e2
+Author: J. Bruce Fields 
+Date:   Fri Jun 30 01:56:16 2006 -0700
+
+    [PATCH] knfsd: svcrpc: gss: simplify rsc_parse()
+    
+    Adopt a simpler convention for gss_mech_put(), to simplify rsc_parse().
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
+index f8bac6ccd524..d88468d21c37 100644
+--- a/net/sunrpc/auth_gss/gss_mech_switch.c
++++ b/net/sunrpc/auth_gss/gss_mech_switch.c
+@@ -224,7 +224,8 @@ EXPORT_SYMBOL(gss_service_to_auth_domain_name);
+ void
+ gss_mech_put(struct gss_api_mech * gm)
+ {
+-	module_put(gm->gm_owner);
++	if (gm)
++		module_put(gm->gm_owner);
+ }
+ 
+ EXPORT_SYMBOL(gss_mech_put);
+@@ -307,8 +308,7 @@ gss_delete_sec_context(struct gss_ctx	**context_handle)
+ 		(*context_handle)->mech_type->gm_ops
+ 			->gss_delete_sec_context((*context_handle)
+ 							->internal_ctx_id);
+-	if ((*context_handle)->mech_type)
+-		gss_mech_put((*context_handle)->mech_type);
++	gss_mech_put((*context_handle)->mech_type);
+ 	kfree(*context_handle);
+ 	*context_handle=NULL;
+ 	return GSS_S_COMPLETE;
+diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
+index d51e316c5821..71f57a5d800d 100644
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -425,6 +425,7 @@ static int rsc_parse(struct cache_detail *cd,
+ 	struct rsc rsci, *rscp = NULL;
+ 	time_t expiry;
+ 	int status = -EINVAL;
++	struct gss_api_mech *gm = NULL;
+ 
+ 	memset(&rsci, 0, sizeof(rsci));
+ 	/* context handle */
+@@ -453,7 +454,6 @@ static int rsc_parse(struct cache_detail *cd,
+ 		set_bit(CACHE_NEGATIVE, &rsci.h.flags);
+ 	else {
+ 		int N, i;
+-		struct gss_api_mech *gm;
+ 
+ 		/* gid */
+ 		if (get_int(&mesg, &rsci.cred.cr_gid))
+@@ -488,21 +488,17 @@ static int rsc_parse(struct cache_detail *cd,
+ 		status = -EINVAL;
+ 		/* mech-specific data: */
+ 		len = qword_get(&mesg, buf, mlen);
+-		if (len < 0) {
+-			gss_mech_put(gm);
++		if (len < 0)
+ 			goto out;
+-		}
+ 		status = gss_import_sec_context(buf, len, gm, &rsci.mechctx);
+-		if (status) {
+-			gss_mech_put(gm);
++		if (status)
+ 			goto out;
+-		}
+-		gss_mech_put(gm);
+ 	}
+ 	rsci.h.expiry_time = expiry;
+ 	rscp = rsc_update(&rsci, rscp);
+ 	status = 0;
+ out:
++	gss_mech_put(gm);
+ 	rsc_free(&rsci);
+ 	if (rscp)
+ 		cache_put(&rscp->h, &rsc_cache);

commit 270d56e536dcd37cc819a6adb51d918185411048
+Author: David M. Richter 
+Date:   Fri Jun 30 01:56:15 2006 -0700
+
+    [PATCH] knfsd: nfsd: fix misplaced fh_unlock() in nfsd_link()
+    
+    In the event that lookup_one_len() fails in nfsd_link(), fh_unlock() is
+    skipped and locks are held overlong.
+    
+    Patch was tested on 2.6.17-rc2 by causing lookup_one_len() to fail and
+    verifying that fh_unlock() gets called appropriately.
+    
+    Signed-off-by: David M. Richter 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index b653ede37e66..f916b170e136 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -1517,14 +1517,15 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
+ 			err = nfserrno(err);
+ 	}
+ 
+-	fh_unlock(ffhp);
+ 	dput(dnew);
++out_unlock:
++	fh_unlock(ffhp);
+ out:
+ 	return err;
+ 
+ out_nfserr:
+ 	err = nfserrno(err);
+-	goto out;
++	goto out_unlock;
+ }
+ 
+ /*

commit 6e46d8a9ccbcd3273bdb6902ca2b6da62c253e73
+Author: J. Bruce Fields 
+Date:   Fri Jun 30 01:56:14 2006 -0700
+
+    [PATCH] knfsd: nfsd4: remove superfluous grace period checks
+    
+    We're checking nfs_in_grace here a few times when there isn't really any
+    reason to--bad_stateid is probably the more sensible return value anyway.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 21497321a525..4810577347cf 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2070,16 +2070,12 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
+ 	if (!stateid->si_fileid) { /* delegation stateid */
+ 		if(!(dp = find_delegation_stateid(ino, stateid))) {
+ 			dprintk("NFSD: delegation stateid not found\n");
+-			if (nfs4_in_grace())
+-				status = nfserr_grace;
+ 			goto out;
+ 		}
+ 		stidp = &dp->dl_stateid;
+ 	} else { /* open or lock stateid */
+ 		if (!(stp = find_stateid(stateid, flags))) {
+ 			dprintk("NFSD: open or lock stateid not found\n");
+-			if (nfs4_in_grace())
+-				status = nfserr_grace;
+ 			goto out;
+ 		}
+ 		if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp))

commit 7fc90ec93a5eb71f4b08403baf5ba7176b3ec6b1
+Author: J. Bruce Fields 
+Date:   Fri Jun 30 01:56:14 2006 -0700
+
+    [PATCH] knfsd: nfsd: call nfsd_setuser() on fh_compose(), fix nfsd4 permissions problem
+    
+    In the typical v2/v3 case the only new filehandles used as arguments to
+    operations are filehandles taken directly off the wire, which don't get
+    dentries until fh_verify() is called.
+    
+    But in v4 the filehandles that are arguments to operations were often created
+    by previous operations (putrootfh, lookup, etc.) using fh_compose, which sets
+    the dentry in the filehandle without calling nfsd_setuser().
+    
+    This also means that, for example, if filesystem B is mounted on filesystem A,
+    and filesystem A is exported without root-squashing, then a client can bypass
+    the rootsquashing on B using a compound that starts at a filehandle in A,
+    crosses into B using lookups, and then does stuff in B.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
+index ca96ede30a10..ecc439d2565f 100644
+--- a/fs/nfsd/nfsfh.c
++++ b/fs/nfsd/nfsfh.c
+@@ -187,13 +187,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
+ 			goto out;
+ 		}
+ 
+-		/* Set user creds for this exportpoint */
+-		error = nfsd_setuser(rqstp, exp);
+-		if (error) {
+-			error = nfserrno(error);
+-			goto out;
+-		}
+-
+ 		/*
+ 		 * Look up the dentry using the NFS file handle.
+ 		 */
+@@ -251,6 +244,14 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
+ 	}
+ 	cache_get(&exp->h);
+ 
++	/* Set user creds for this exportpoint; necessary even in the "just
++	 * checking" case because this may be a filehandle that was created by
++	 * fh_compose, and that is about to be used in another nfsv4 compound
++	 * operation */
++	error = nfserrno(nfsd_setuser(rqstp, exp));
++	if (error)
++		goto out;
++
+ 	error = nfsd_mode_check(rqstp, dentry->d_inode->i_mode, type);
+ 	if (error)
+ 		goto out;

commit a8cddc5dfc1d03a91885ef27eb91418e665577ce
+Author: J. Bruce Fields 
+Date:   Fri Jun 30 01:56:13 2006 -0700
+
+    [PATCH] knfsd: nfsd4: fix open_confirm locking
+    
+    Fix an improper unlock in an error path.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 7c7d01672d35..21497321a525 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2252,8 +2252,9 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs
+ 			(int)current_fh->fh_dentry->d_name.len,
+ 			current_fh->fh_dentry->d_name.name);
+ 
+-	if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0)))
+-		goto out;
++	status = fh_verify(rqstp, current_fh, S_IFREG, 0);
++	if (status)
++		return status;
+ 
+ 	nfs4_lock_state();
+ 

commit 33a43f2802d8d7be3a9b541785c4ca9ad79e4310
+Author: Andy Adamson 
+Date:   Fri Jun 9 09:34:30 2006 -0400
+
+    NFSv4: A root pathname is sent as a zero component4
+    
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
+index 646f16da0722..1750d996f49f 100644
+--- a/fs/nfs/nfs4xdr.c
++++ b/fs/nfs/nfs4xdr.c
+@@ -2408,8 +2408,10 @@ static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path)
+ 
+ 	READ_BUF(4);
+ 	READ32(n);
+-	if (n <= 0)
++	if (n < 0)
+ 		goto out_eio;
++	if (n == 0)
++		goto root_path;
+ 	dprintk("path ");
+ 	path->ncomponents = 0;
+ 	while (path->ncomponents < n) {
+@@ -2430,6 +2432,13 @@ static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path)
+ out:
+ 	dprintk("\n");
+ 	return status;
++root_path:
++/* a root pathname is sent as a zero component4 */
++	path->ncomponents = 1;
++	path->components[0].len=0;
++	path->components[0].data=NULL;
++	dprintk("path /\n");
++	goto out;
+ out_eio:
+ 	dprintk(" status %d", status);
+ 	status = -EIO;

commit 6f54e2d0d3a904e55c9c50b78542072f6c42080e
+Author: J. Bruce Fields 
+Date:   Mon Apr 10 22:55:36 2006 -0700
+
+    [PATCH] knfsd: svcrpc: WARN() instead of returning an error from svc_take_page
+    
+    Every caller of svc_take_page ignores its return value and assumes it
+    succeeded.  So just WARN() instead of returning an ignored error.  This would
+    have saved some time debugging a recent nfsd4 problem.
+    
+    If there are still failure cases here, then the result is probably that we
+    overwrite an earlier part of the reply while xdr-encoding.
+    
+    While the corrupted reply is a nasty bug, it would be worse to panic here and
+    create the possibility of a remote DOS; hence WARN() instead of BUG().
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Cc: Ingo Oeser 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
+index 50cab2a09f28..503564384545 100644
+--- a/include/linux/sunrpc/svc.h
++++ b/include/linux/sunrpc/svc.h
+@@ -197,15 +197,16 @@ svc_take_res_page(struct svc_rqst *rqstp)
+ 	return rqstp->rq_respages[rqstp->rq_resused++];
+ }
+ 
+-static inline int svc_take_page(struct svc_rqst *rqstp)
++static inline void svc_take_page(struct svc_rqst *rqstp)
+ {
+-	if (rqstp->rq_arghi <= rqstp->rq_argused)
+-		return -ENOMEM;
++	if (rqstp->rq_arghi <= rqstp->rq_argused) {
++		WARN_ON(1);
++		return;
++	}
+ 	rqstp->rq_arghi--;
+ 	rqstp->rq_respages[rqstp->rq_resused] =
+ 		rqstp->rq_argpages[rqstp->rq_arghi];
+ 	rqstp->rq_resused++;
+-	return 0;
+ }
+ 
+ static inline void svc_pushback_allpages(struct svc_rqst *rqstp)

commit eb76b3fda1f7c2aa2d1523b36835048a15e5e5d2
+Author: Andy Adamson 
+Date:   Sun Mar 26 01:37:26 2006 -0800
+
+    [PATCH] NFSD4: return conflict lock without races
+    
+    Update the NFSv4 server to use the new posix_lock_file_conf() interface.
+    Remove unnecessary (and race-prone) posix_test_file() calls.
+    
+    Signed-off-by: Andy Adamson 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+    Cc: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index c7b87e92f91b..47ec112b266c 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2750,37 +2750,31 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
+ 	* Note: locks.c uses the BKL to protect the inode's lock list.
+ 	*/
+ 
+-	status = posix_lock_file(filp, &file_lock);
+-	dprintk("NFSD: nfsd4_lock: posix_lock_file status %d\n",status);
++	/* XXX?: Just to divert the locks_release_private at the start of
++	 * locks_copy_lock: */
++	conflock.fl_ops = NULL;
++	conflock.fl_lmops = NULL;
++	status = posix_lock_file_conf(filp, &file_lock, &conflock);
++	dprintk("NFSD: nfsd4_lock: posix_lock_file_conf status %d\n",status);
+ 	switch (-status) {
+ 	case 0: /* success! */
+ 		update_stateid(&lock_stp->st_stateid);
+ 		memcpy(&lock->lk_resp_stateid, &lock_stp->st_stateid, 
+ 				sizeof(stateid_t));
+-		goto out;
+-	case (EAGAIN):
+-		goto conflicting_lock;
++		break;
++	case (EAGAIN):		/* conflock holds conflicting lock */
++		status = nfserr_denied;
++		dprintk("NFSD: nfsd4_lock: conflicting lock found!\n");
++		nfs4_set_lock_denied(&conflock, &lock->lk_denied);
++		break;
+ 	case (EDEADLK):
+ 		status = nfserr_deadlock;
+-		dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status);
+-		goto out;
++		break;
+ 	default:        
+-		status = nfserrno(status);
+-		dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status);
+-		goto out;
+-	}
+-
+-conflicting_lock:
+-	dprintk("NFSD: nfsd4_lock: conflicting lock found!\n");
+-	status = nfserr_denied;
+-	/* XXX There is a race here. Future patch needed to provide 
+-	 * an atomic posix_lock_and_test_file
+-	 */
+-	if (!posix_test_lock(filp, &file_lock, &conflock)) {
+-		status = nfserr_serverfault;
+-		goto out;
++		dprintk("NFSD: nfsd4_lock: posix_lock_file_conf() failed! status %d\n",status);
++		status = nfserr_resource;
++		break;
+ 	}
+-	nfs4_set_lock_denied(&conflock, &lock->lk_denied);
+ out:
+ 	if (status && lock->lk_is_new && lock_sop)
+ 		release_stateowner(lock_sop);

commit 5842add2f3b519111b6401f3a35862bd00a3aa7e
+Author: Andy Adamson 
+Date:   Sun Mar 26 01:37:26 2006 -0800
+
+    [PATCH] VFS,fs/locks.c,NFSD4: add race_free posix_lock_file_conf() interface
+    
+    Lockd and the NFSv4 server both exercise a race condition where
+    posix_test_lock() is called either before or after posix_lock_file() to
+    deal with a denied lock request due to a conflicting lock.
+    
+    Remove the race condition for the NFSv4 server by adding a new conflicting
+    lock parameter to __posix_lock_file() , changing the name to
+    __posix_lock_file_conf().
+    
+    Keep posix_lock_file() interface, add posix_lock_conf() interface, both
+    call __posix_lock_file_conf().
+    
+    [akpm@osdl.org: Put the EXPORT_SYMBOL() where it belongs]
+    Signed-off-by: Andy Adamson 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/locks.c b/fs/locks.c
+index 4badf6a0e7b6..4d9e71d43e7e 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -792,9 +792,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *new_fl)
+ 	return error;
+ }
+ 
+-EXPORT_SYMBOL(posix_lock_file);
+-
+-static int __posix_lock_file(struct inode *inode, struct file_lock *request)
++static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request, struct file_lock *conflock)
+ {
+ 	struct file_lock *fl;
+ 	struct file_lock *new_fl, *new_fl2;
+@@ -818,6 +816,8 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request)
+ 				continue;
+ 			if (!posix_locks_conflict(request, fl))
+ 				continue;
++			if (conflock)
++				locks_copy_lock(conflock, fl);
+ 			error = -EAGAIN;
+ 			if (!(request->fl_flags & FL_SLEEP))
+ 				goto out;
+@@ -987,8 +987,24 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request)
+  */
+ int posix_lock_file(struct file *filp, struct file_lock *fl)
+ {
+-	return __posix_lock_file(filp->f_dentry->d_inode, fl);
++	return __posix_lock_file_conf(filp->f_dentry->d_inode, fl, NULL);
++}
++EXPORT_SYMBOL(posix_lock_file);
++
++/**
++ * posix_lock_file_conf - Apply a POSIX-style lock to a file
++ * @filp: The file to apply the lock to
++ * @fl: The lock to be applied
++ * @conflock: Place to return a copy of the conflicting lock, if found.
++ *
++ * Except for the conflock parameter, acts just like posix_lock_file.
++ */
++int posix_lock_file_conf(struct file *filp, struct file_lock *fl,
++			struct file_lock *conflock)
++{
++	return __posix_lock_file_conf(filp->f_dentry->d_inode, fl, conflock);
+ }
++EXPORT_SYMBOL(posix_lock_file_conf);
+ 
+ /**
+  * posix_lock_file_wait - Apply a POSIX-style lock to a file
+@@ -1004,7 +1020,7 @@ int posix_lock_file_wait(struct file *filp, struct file_lock *fl)
+ 	int error;
+ 	might_sleep ();
+ 	for (;;) {
+-		error = __posix_lock_file(filp->f_dentry->d_inode, fl);
++		error = posix_lock_file(filp, fl);
+ 		if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP))
+ 			break;
+ 		error = wait_event_interruptible(fl->fl_wait, !fl->fl_next);
+@@ -1076,7 +1092,7 @@ int locks_mandatory_area(int read_write, struct inode *inode,
+ 	fl.fl_end = offset + count - 1;
+ 
+ 	for (;;) {
+-		error = __posix_lock_file(inode, &fl);
++		error = __posix_lock_file_conf(inode, &fl, NULL);
+ 		if (error != -EAGAIN)
+ 			break;
+ 		if (!(fl.fl_flags & FL_SLEEP))
+@@ -1689,7 +1705,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
+ 		error = filp->f_op->lock(filp, cmd, file_lock);
+ 	else {
+ 		for (;;) {
+-			error = __posix_lock_file(inode, file_lock);
++			error = posix_lock_file(filp, file_lock);
+ 			if ((error != -EAGAIN) || (cmd == F_SETLK))
+ 				break;
+ 			error = wait_event_interruptible(file_lock->fl_wait,
+@@ -1832,7 +1848,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
+ 		error = filp->f_op->lock(filp, cmd, file_lock);
+ 	else {
+ 		for (;;) {
+-			error = __posix_lock_file(inode, file_lock);
++			error = posix_lock_file(filp, file_lock);
+ 			if ((error != -EAGAIN) || (cmd == F_SETLK64))
+ 				break;
+ 			error = wait_event_interruptible(file_lock->fl_wait,
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 9674679525f9..ab67181a5a55 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -763,6 +763,7 @@ extern void locks_copy_lock(struct file_lock *, struct file_lock *);
+ extern void locks_remove_posix(struct file *, fl_owner_t);
+ extern void locks_remove_flock(struct file *);
+ extern int posix_test_lock(struct file *, struct file_lock *, struct file_lock *);
++extern int posix_lock_file_conf(struct file *, struct file_lock *, struct file_lock *);
+ extern int posix_lock_file(struct file *, struct file_lock *);
+ extern int posix_lock_file_wait(struct file *, struct file_lock *);
+ extern int posix_unblock_lock(struct file *, struct file_lock *);

commit 8dc7c3115b611c00006eac3ee5b108296432aab7
+Author: Andy Adamson 
+Date:   Mon Mar 20 13:44:26 2006 -0500
+
+    locks,lockd: fix race in nlmsvc_testlock
+    
+    posix_test_lock() returns a pointer to a struct file_lock which is unprotected
+    and can be removed while in use by the caller.  Move the conflicting lock from
+    the return to a parameter, and copy the conflicting lock.
+    
+    In most cases the caller ends up putting the copy of the conflicting lock on
+    the stack.  On i386, sizeof(struct file_lock) appears to be about 100 bytes.
+    We're assuming that's reasonable.
+    
+    Signed-off-by: Andy Adamson 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
+index f5398097b84b..d683dd022e08 100644
+--- a/fs/lockd/svclock.c
++++ b/fs/lockd/svclock.c
+@@ -376,8 +376,6 @@ u32
+ nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock,
+ 				       struct nlm_lock *conflock)
+ {
+-	struct file_lock	*fl;
+-
+ 	dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n",
+ 				file->f_file->f_dentry->d_inode->i_sb->s_id,
+ 				file->f_file->f_dentry->d_inode->i_ino,
+@@ -385,14 +383,14 @@ nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock,
+ 				(long long)lock->fl.fl_start,
+ 				(long long)lock->fl.fl_end);
+ 
+-	if ((fl = posix_test_lock(file->f_file, &lock->fl)) != NULL) {
++	if (posix_test_lock(file->f_file, &lock->fl, &conflock->fl)) {
+ 		dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n",
+-				fl->fl_type, (long long)fl->fl_start,
+-				(long long)fl->fl_end);
++				conflock->fl.fl_type,
++				(long long)conflock->fl.fl_start,
++				(long long)conflock->fl.fl_end);
+ 		conflock->caller = "somehost";	/* FIXME */
+ 		conflock->oh.len = 0;		/* don't return OH info */
+-		conflock->svid = fl->fl_pid;
+-		conflock->fl = *fl;
++		conflock->svid = conflock->fl.fl_pid;
+ 		return nlm_lck_denied;
+ 	}
+ 
+diff --git a/fs/locks.c b/fs/locks.c
+index cb940b142c5f..231b23c12c3d 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -672,8 +672,9 @@ static int locks_block_on_timeout(struct file_lock *blocker, struct file_lock *w
+ 	return result;
+ }
+ 
+-struct file_lock *
+-posix_test_lock(struct file *filp, struct file_lock *fl)
++int
++posix_test_lock(struct file *filp, struct file_lock *fl,
++		struct file_lock *conflock)
+ {
+ 	struct file_lock *cfl;
+ 
+@@ -684,9 +685,13 @@ posix_test_lock(struct file *filp, struct file_lock *fl)
+ 		if (posix_locks_conflict(cfl, fl))
+ 			break;
+ 	}
++	if (cfl) {
++		locks_copy_lock(conflock, cfl);
++		unlock_kernel();
++		return 1;
++	}
+ 	unlock_kernel();
+-
+-	return (cfl);
++	return 0;
+ }
+ 
+ EXPORT_SYMBOL(posix_test_lock);
+@@ -1563,7 +1568,7 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd)
+  */
+ int fcntl_getlk(struct file *filp, struct flock __user *l)
+ {
+-	struct file_lock *fl, file_lock;
++	struct file_lock *fl, cfl, file_lock;
+ 	struct flock flock;
+ 	int error;
+ 
+@@ -1587,7 +1592,7 @@ int fcntl_getlk(struct file *filp, struct flock __user *l)
+ 		else
+ 		  fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock);
+ 	} else {
+-		fl = posix_test_lock(filp, &file_lock);
++		fl = (posix_test_lock(filp, &file_lock, &cfl) ? &cfl : NULL);
+ 	}
+  
+ 	flock.l_type = F_UNLCK;
+@@ -1717,7 +1722,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
+  */
+ int fcntl_getlk64(struct file *filp, struct flock64 __user *l)
+ {
+-	struct file_lock *fl, file_lock;
++	struct file_lock *fl, cfl, file_lock;
+ 	struct flock64 flock;
+ 	int error;
+ 
+@@ -1741,7 +1746,7 @@ int fcntl_getlk64(struct file *filp, struct flock64 __user *l)
+ 		else
+ 		  fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock);
+ 	} else {
+-		fl = posix_test_lock(filp, &file_lock);
++		fl = (posix_test_lock(filp, &file_lock, &cfl) ? &cfl : NULL);
+ 	}
+  
+ 	flock.l_type = F_UNLCK;
+diff --git a/fs/nfs/file.c b/fs/nfs/file.c
+index 1cf07e4ad136..ee140c53dba6 100644
+--- a/fs/nfs/file.c
++++ b/fs/nfs/file.c
+@@ -392,15 +392,14 @@ nfs_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t
+ 
+ static int do_getlk(struct file *filp, int cmd, struct file_lock *fl)
+ {
+-	struct file_lock *cfl;
++	struct file_lock cfl;
+ 	struct inode *inode = filp->f_mapping->host;
+ 	int status = 0;
+ 
+ 	lock_kernel();
+ 	/* Try local locking first */
+-	cfl = posix_test_lock(filp, fl);
+-	if (cfl != NULL) {
+-		locks_copy_lock(fl, cfl);
++	if (posix_test_lock(filp, fl, &cfl)) {
++		locks_copy_lock(fl, &cfl);
+ 		goto out;
+ 	}
+ 
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 1143cfb64549..f6ab762bea99 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2639,7 +2639,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
+ 	struct nfs4_stateid *lock_stp;
+ 	struct file *filp;
+ 	struct file_lock file_lock;
+-	struct file_lock *conflock;
++	struct file_lock conflock;
+ 	int status = 0;
+ 	unsigned int strhashval;
+ 
+@@ -2775,11 +2775,11 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
+ 	/* XXX There is a race here. Future patch needed to provide 
+ 	 * an atomic posix_lock_and_test_file
+ 	 */
+-	if (!(conflock = posix_test_lock(filp, &file_lock))) {
++	if (!posix_test_lock(filp, &file_lock, &conflock)) {
+ 		status = nfserr_serverfault;
+ 		goto out;
+ 	}
+-	nfs4_set_lock_denied(conflock, &lock->lk_denied);
++	nfs4_set_lock_denied(&conflock, &lock->lk_denied);
+ out:
+ 	if (status && lock->lk_is_new && lock_sop)
+ 		release_stateowner(lock_sop);
+@@ -2800,7 +2800,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
+ 	struct inode *inode;
+ 	struct file file;
+ 	struct file_lock file_lock;
+-	struct file_lock *conflicting_lock;
++	struct file_lock conflock;
+ 	int status;
+ 
+ 	if (nfs4_in_grace())
+@@ -2864,10 +2864,9 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
+ 	file.f_dentry = current_fh->fh_dentry;
+ 
+ 	status = nfs_ok;
+-	conflicting_lock = posix_test_lock(&file, &file_lock);
+-	if (conflicting_lock) {
++	if (posix_test_lock(&file, &file_lock, &conflock)) {
+ 		status = nfserr_denied;
+-		nfs4_set_lock_denied(conflicting_lock, &lockt->lt_denied);
++		nfs4_set_lock_denied(&conflock, &lockt->lt_denied);
+ 	}
+ out:
+ 	nfs4_unlock_state();
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index b01482c721ae..8ef4dd788a83 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -754,7 +754,7 @@ extern void locks_init_lock(struct file_lock *);
+ extern void locks_copy_lock(struct file_lock *, struct file_lock *);
+ extern void locks_remove_posix(struct file *, fl_owner_t);
+ extern void locks_remove_flock(struct file *);
+-extern struct file_lock *posix_test_lock(struct file *, struct file_lock *);
++extern int posix_test_lock(struct file *, struct file_lock *, struct file_lock *);
+ extern int posix_lock_file(struct file *, struct file_lock *);
+ extern int posix_lock_file_wait(struct file *, struct file_lock *);
+ extern int posix_unblock_lock(struct file *, struct file_lock *);

commit 2e0af86f618c697b44e2d67dff151256c58201c4
+Author: Andy Adamson 
+Date:   Mon Mar 20 13:44:26 2006 -0500
+
+    locks: remove unused posix_block_lock
+    
+    posix_lock_file() is used to add a blocked lock to Lockd's block, so
+    posix_block_lock() is no longer needed.
+    
+    Signed-off-by: Andy Adamson 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/locks.c b/fs/locks.c
+index d2c5306e3db0..cb940b142c5f 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -1954,21 +1954,6 @@ void locks_remove_flock(struct file *filp)
+ 	unlock_kernel();
+ }
+ 
+-/**
+- *	posix_block_lock - blocks waiting for a file lock
+- *	@blocker: the lock which is blocking
+- *	@waiter: the lock which conflicts and has to wait
+- *
+- * lockd needs to block waiting for locks.
+- */
+-void
+-posix_block_lock(struct file_lock *blocker, struct file_lock *waiter)
+-{
+-	locks_insert_block(blocker, waiter);
+-}
+-
+-EXPORT_SYMBOL(posix_block_lock);
+-
+ /**
+  *	posix_unblock_lock - stop waiting for a file lock
+  *      @filp:   how the file was opened
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index be21e860a9f2..b01482c721ae 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -757,7 +757,6 @@ extern void locks_remove_flock(struct file *);
+ extern struct file_lock *posix_test_lock(struct file *, struct file_lock *);
+ extern int posix_lock_file(struct file *, struct file_lock *);
+ extern int posix_lock_file_wait(struct file *, struct file_lock *);
+-extern void posix_block_lock(struct file_lock *, struct file_lock *);
+ extern int posix_unblock_lock(struct file *, struct file_lock *);
+ extern int posix_locks_deadlock(struct file_lock *, struct file_lock *);
+ extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl);

commit a85f193e2fb7d53e48ae6a9d9ea990bfb4cea555
+Author: Andy Adamson 
+Date:   Mon Mar 20 13:44:25 2006 -0500
+
+    lockd: make nlmsvc_lock use only posix_lock_file
+    
+    Reorganize nlmsvc_lock() to make full use of posix_lock_file(), which does
+    eveything nlmsvc_lock() needs - no need to call posix_test_lock(),
+    posix_locks_deadlock(), or posix_block_lock() separately.
+    
+    Signed-off-by: Andy Adamson 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
+index 58bbfede94ec..f5398097b84b 100644
+--- a/fs/lockd/svclock.c
++++ b/fs/lockd/svclock.c
+@@ -297,7 +297,6 @@ u32
+ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
+ 			struct nlm_lock *lock, int wait, struct nlm_cookie *cookie)
+ {
+-	struct file_lock	*conflock;
+ 	struct nlm_block	*block;
+ 	int			error;
+ 	u32			ret;
+@@ -320,14 +319,15 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
+ 	/* Lock file against concurrent access */
+ 	down(&file->f_sema);
+ 
+-	if (!(conflock = posix_test_lock(file->f_file, &lock->fl))) {
+-		error = posix_lock_file(file->f_file, &lock->fl);
++	error = posix_lock_file(file->f_file, &lock->fl);
++
++	dprintk("lockd: posix_lock_file returned %d\n", error);
+ 
++	if (error != -EAGAIN) {
+ 		if (block)
+ 			nlmsvc_delete_block(block, 0);
+ 		up(&file->f_sema);
+ 
+-		dprintk("lockd: posix_lock_file returned %d\n", -error);
+ 		switch(-error) {
+ 		case 0:
+ 			ret = nlm_granted;
+@@ -335,9 +335,6 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
+ 		case EDEADLK:
+ 			ret = nlm_deadlock;
+ 			goto out;
+-		case EAGAIN:
+-			ret = nlm_lck_denied;
+-			goto out;
+ 		default:			/* includes ENOLCK */
+ 			ret = nlm_lck_denied_nolocks;
+ 			goto out;
+@@ -349,11 +346,6 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
+ 		goto out_unlock;
+ 	}
+ 
+-	if (posix_locks_deadlock(&lock->fl, conflock)) {
+-		ret = nlm_deadlock;
+-		goto out_unlock;
+-	}
+-
+ 	/* If we don't have a block, create and initialize it. Then
+ 	 * retry because we may have slept in kmalloc. */
+ 	/* We have to release f_sema as nlmsvc_create_block may try to
+@@ -369,13 +361,6 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
+ 	/* Append to list of blocked */
+ 	nlmsvc_insert_block(block, NLM_NEVER);
+ 
+-	if (list_empty(&block->b_call.a_args.lock.fl.fl_block)) {
+-		/* Now add block to block list of the conflicting lock
+-		   if we haven't done so. */
+-		dprintk("lockd: blocking on this lock.\n");
+-		posix_block_lock(conflock, &block->b_call.a_args.lock.fl);
+-	}
+-
+ 	ret = nlm_lck_blocked;
+ out_unlock:
+ 	up(&file->f_sema);

commit 5de0e5024a4e21251fd80dbfdb83316ce97086bc
+Author: Andy Adamson 
+Date:   Mon Mar 20 13:44:25 2006 -0500
+
+    lockd: simplify nlmsvc_grant_blocked
+    
+    Reorganize nlmsvc_grant_blocked() to make full use of posix_lock_file().  Note
+    that there's no need for separate calls to posix_test_lock(),
+    posix_locks_deadlock(), or posix_block_lock().
+    
+    Signed-off-by: Andy Adamson 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
+index 42dd105456c5..58bbfede94ec 100644
+--- a/fs/lockd/svclock.c
++++ b/fs/lockd/svclock.c
+@@ -519,7 +519,6 @@ nlmsvc_grant_blocked(struct nlm_block *block)
+ {
+ 	struct nlm_file		*file = block->b_file;
+ 	struct nlm_lock		*lock = &block->b_call.a_args.lock;
+-	struct file_lock	*conflock;
+ 	int			error;
+ 
+ 	dprintk("lockd: grant blocked lock %p\n", block);
+@@ -539,19 +538,15 @@ nlmsvc_grant_blocked(struct nlm_block *block)
+ 	}
+ 
+ 	/* Try the lock operation again */
+-	if ((conflock = posix_test_lock(file->f_file, &lock->fl)) != NULL) {
+-		/* Bummer, we blocked again */
++	error = posix_lock_file(file->f_file, &lock->fl);
++	switch (error) {
++	case 0:
++		break;
++	case -EAGAIN:
+ 		dprintk("lockd: lock still blocked\n");
+ 		nlmsvc_insert_block(block, NLM_NEVER);
+-		posix_block_lock(conflock, &lock->fl);
+ 		goto out_unlock;
+-	}
+-
+-	/* Alright, no conflicting lock. Now lock it for real. If the
+-	 * following yields an error, this is most probably due to low
+-	 * memory. Retry the lock in a few seconds.
+-	 */
+-	if ((error = posix_lock_file(file->f_file, &lock->fl)) < 0) {
++	default:
+ 		printk(KERN_WARNING "lockd: unexpected error %d in %s!\n",
+ 				-error, __FUNCTION__);
+ 		nlmsvc_insert_block(block, 10 * HZ);

commit 15dadef9460ad8d3b1d5ede1c1697dc79af44a72
+Author: Andy Adamson 
+Date:   Mon Mar 20 13:44:24 2006 -0500
+
+    lockd: clean up nlmsvc_lock
+    
+    Slightly more consistent dprintk error reporting, consolidate some up()'s.
+    
+    Signed-off-by: Andy Adamson 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
+index a525a141dd3b..42dd105456c5 100644
+--- a/fs/lockd/svclock.c
++++ b/fs/lockd/svclock.c
+@@ -300,6 +300,7 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
+ 	struct file_lock	*conflock;
+ 	struct nlm_block	*block;
+ 	int			error;
++	u32			ret;
+ 
+ 	dprintk("lockd: nlmsvc_lock(%s/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n",
+ 				file->f_file->f_dentry->d_inode->i_sb->s_id,
+@@ -329,24 +330,28 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
+ 		dprintk("lockd: posix_lock_file returned %d\n", -error);
+ 		switch(-error) {
+ 		case 0:
+-			return nlm_granted;
++			ret = nlm_granted;
++			goto out;
+ 		case EDEADLK:
+-			return nlm_deadlock;
++			ret = nlm_deadlock;
++			goto out;
+ 		case EAGAIN:
+-			return nlm_lck_denied;
++			ret = nlm_lck_denied;
++			goto out;
+ 		default:			/* includes ENOLCK */
+-			return nlm_lck_denied_nolocks;
++			ret = nlm_lck_denied_nolocks;
++			goto out;
+ 		}
+ 	}
+ 
+ 	if (!wait) {
+-		up(&file->f_sema);
+-		return nlm_lck_denied;
++		ret = nlm_lck_denied;
++		goto out_unlock;
+ 	}
+ 
+ 	if (posix_locks_deadlock(&lock->fl, conflock)) {
+-		up(&file->f_sema);
+-		return nlm_deadlock;
++		ret = nlm_deadlock;
++		goto out_unlock;
+ 	}
+ 
+ 	/* If we don't have a block, create and initialize it. Then
+@@ -371,8 +376,12 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
+ 		posix_block_lock(conflock, &block->b_call.a_args.lock.fl);
+ 	}
+ 
++	ret = nlm_lck_blocked;
++out_unlock:
+ 	up(&file->f_sema);
+-	return nlm_lck_blocked;
++out:
++	dprintk("lockd: nlmsvc_lock returned %u\n", ret);
++	return ret;
+ }
+ 
+ /*
+@@ -535,8 +544,7 @@ nlmsvc_grant_blocked(struct nlm_block *block)
+ 		dprintk("lockd: lock still blocked\n");
+ 		nlmsvc_insert_block(block, NLM_NEVER);
+ 		posix_block_lock(conflock, &lock->fl);
+-		up(&file->f_sema);
+-		return;
++		goto out_unlock;
+ 	}
+ 
+ 	/* Alright, no conflicting lock. Now lock it for real. If the
+@@ -547,8 +555,7 @@ nlmsvc_grant_blocked(struct nlm_block *block)
+ 		printk(KERN_WARNING "lockd: unexpected error %d in %s!\n",
+ 				-error, __FUNCTION__);
+ 		nlmsvc_insert_block(block, 10 * HZ);
+-		up(&file->f_sema);
+-		return;
++		goto out_unlock;
+ 	}
+ 
+ callback:
+@@ -565,6 +572,7 @@ nlmsvc_grant_blocked(struct nlm_block *block)
+ 	if (nlmsvc_async_call(&block->b_call, NLMPROC_GRANTED_MSG,
+ 						&nlmsvc_grant_ops) < 0)
+ 		nlm_release_host(block->b_call.a_host);
++out_unlock:
+ 	up(&file->f_sema);
+ }
+ 

commit 5274881992b8a632620f69346401da66e480a23b
+Author: Fred Isaman 
+Date:   Wed Jan 18 17:43:43 2006 -0800
+
+    [PATCH] nfsd4: clean up settattr code
+    
+    Clean up some unnecessary special-casing in the setattr code..
+    
+    Signed-off-by: Fred Isaman 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index b3f169f400db..a00fe8686293 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -594,10 +594,6 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se
+ {
+ 	int status = nfs_ok;
+ 
+-	if (!current_fh->fh_dentry)
+-		return nfserr_nofilehandle;
+-
+-	status = nfs_ok;
+ 	if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
+ 		nfs4_lock_state();
+ 		status = nfs4_preprocess_stateid_op(current_fh,
+@@ -799,17 +795,13 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
+ 		/* All operations except RENEW, SETCLIENTID, RESTOREFH
+ 		* SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH
+ 		* require a valid current filehandle
+-		*
+-		* SETATTR NOFILEHANDLE error handled in nfsd4_setattr
+-		* due to required returned bitmap argument
+ 		*/
+ 		if ((!current_fh->fh_dentry) &&
+ 		   !((op->opnum == OP_PUTFH) || (op->opnum == OP_PUTROOTFH) ||
+ 		   (op->opnum == OP_SETCLIENTID) ||
+ 		   (op->opnum == OP_SETCLIENTID_CONFIRM) ||
+ 		   (op->opnum == OP_RENEW) || (op->opnum == OP_RESTOREFH) ||
+-		   (op->opnum == OP_RELEASE_LOCKOWNER) ||
+-		   (op->opnum == OP_SETATTR))) {
++		   (op->opnum == OP_RELEASE_LOCKOWNER))) {
+ 			op->status = nfserr_nofilehandle;
+ 			goto encode_op;
+ 		}

commit 34081efc12aaaa12f20e5b59f3cb98ba6e27fb34
+Author: Fred Isaman 
+Date:   Wed Jan 18 17:43:40 2006 -0800
+
+    [PATCH] nfsd4: Fix bug in rdattr_error return
+    
+    Fix bug in rdattr_error return which causes correct error code to be
+    overwritten by nfserr_toosmall.
+    
+    Signed-off-by: Fred Isaman 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index 6b743327686c..69d3501173a8 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -1764,10 +1764,11 @@ nfsd4_encode_dirent(struct readdir_cd *ccd, const char *name, int namlen,
+ 		 */
+ 		if (!(cd->rd_bmval[0] & FATTR4_WORD0_RDATTR_ERROR))
+ 			goto fail;
+-		nfserr = nfserr_toosmall;
+ 		p = nfsd4_encode_rdattr_error(p, buflen, nfserr);
+-		if (p == NULL)
++		if (p == NULL) {
++			nfserr = nfserr_toosmall;
+ 			goto fail;
++		}
+ 	}
+ 	cd->buflen -= (p - cd->buffer);
+ 	cd->buffer = p;

commit 6c26d08f02f829a833d393c3f1b196538a9ec2c4
+Author: J. Bruce Fields 
+Date:   Wed Jan 18 17:43:38 2006 -0800
+
+    [PATCH] nfsd4: fix open_downgrade
+    
+    Bad bookkeeping of the share reservations when handling open upgrades was
+    causing open downgrade to fail.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 7167dcf8e1fe..82c36ccd8b5c 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1609,26 +1609,26 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_sta
+ {
+ 	struct file *filp = stp->st_vfs_file;
+ 	struct inode *inode = filp->f_dentry->d_inode;
+-	unsigned int share_access;
++	unsigned int share_access, new_writer;
+ 	int status;
+ 
+ 	set_access(&share_access, stp->st_access_bmap);
+-	share_access = ~share_access;
+-	share_access &= open->op_share_access;
+-
+-	if (!(share_access & NFS4_SHARE_ACCESS_WRITE))
+-		return nfsd4_truncate(rqstp, cur_fh, open);
++	new_writer = (~share_access) & open->op_share_access
++			& NFS4_SHARE_ACCESS_WRITE;
+ 
+-	status = get_write_access(inode);
+-	if (status)
+-		return nfserrno(status);
++	if (new_writer) {
++		status = get_write_access(inode);
++		if (status)
++			return nfserrno(status);
++	}
+ 	status = nfsd4_truncate(rqstp, cur_fh, open);
+ 	if (status) {
+-		put_write_access(inode);
++		if (new_writer)
++			put_write_access(inode);
+ 		return status;
+ 	}
+ 	/* remember the open */
+-	filp->f_mode = (filp->f_mode | FMODE_WRITE) & ~FMODE_READ;
++	filp->f_mode |= open->op_share_access;
+ 	set_bit(open->op_share_access, &stp->st_access_bmap);
+ 	set_bit(open->op_share_deny, &stp->st_deny_bmap);
+ 

commit fb553c0f17444e090db951b96df4d2d71b4f4b6b
+Author: J. Bruce Fields 
+Date:   Wed Jan 18 17:43:36 2006 -0800
+
+    [PATCH] nfsd4: don't create on open that fails due to ERR_GRACE
+    
+    In an earlier patch (commit b648330a1d741d5df8a5076b2a0a2519c69c8f41) I noted
+    that a too-early grace-period check was preventing us from bumping the
+    sequence id on open.  Unfortunately in that patch I stupidly moved the
+    grace-period check back too far, so now an open for create can succesfully
+    create the file while still returning ERR_GRACE.
+    
+    The correct place for that check is after we've set the open_owner and handled
+    any replays, but before we actually start mucking with the filesystem.
+    
+    Thanks to Avishay Traeger for reporting the bug.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index 89028f2d8d26..b3f169f400db 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -192,6 +192,14 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
+ 	}
+ 	if (status)
+ 		goto out;
++
++	/* Openowner is now set, so sequence id will get bumped.  Now we need
++	 * these checks before we do any creates: */
++	if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
++		return nfserr_grace;
++	if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
++		return nfserr_no_grace;
++
+ 	switch (open->op_claim_type) {
+ 		case NFS4_OPEN_CLAIM_DELEGATE_CUR:
+ 			status = nfserr_inval;
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index b92dc9e08973..7167dcf8e1fe 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1732,12 +1732,6 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
+ 	struct nfs4_delegation *dp = NULL;
+ 	int status;
+ 
+-	if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
+-		return nfserr_grace;
+-
+-	if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
+-		return nfserr_no_grace;
+-
+ 	status = nfserr_inval;
+ 	if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny))
+ 		goto out;

commit 0f442aa299bb47046db4077d9c122a1b539311ce
+Author: J. Bruce Fields 
+Date:   Wed Jan 18 17:43:34 2006 -0800
+
+    [PATCH] nfsd4: simplify process-open1 logic
+    
+    nfsd4_process_open1 is very highly nested; flatten it out a bit.
+    
+    Also, the preceding comment, which just outlines the logic, seems redundant.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index dc792b6b4513..b92dc9e08973 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1429,90 +1429,61 @@ static struct lock_manager_operations nfsd_lease_mng_ops = {
+ };
+ 
+ 
+-/*
+- * nfsd4_process_open1()
+- * 	lookup stateowner.
+- * 		found:
+- * 			check confirmed 
+- * 				confirmed:
+- * 					check seqid
+- * 				not confirmed:
+- * 					delete owner
+- * 					create new owner
+- * 		notfound:
+- * 			verify clientid
+- * 			create new owner
+- *
+- * called with nfs4_lock_state() held.
+- */
+ int
+ nfsd4_process_open1(struct nfsd4_open *open)
+ {
+-	int status;
+ 	clientid_t *clientid = &open->op_clientid;
+ 	struct nfs4_client *clp = NULL;
+ 	unsigned int strhashval;
+ 	struct nfs4_stateowner *sop = NULL;
+ 
+-	status = nfserr_inval;
+ 	if (!check_name(open->op_owner))
+-		goto out;
++		return nfserr_inval;
+ 
+ 	if (STALE_CLIENTID(&open->op_clientid))
+ 		return nfserr_stale_clientid;
+ 
+ 	strhashval = ownerstr_hashval(clientid->cl_id, open->op_owner);
+ 	sop = find_openstateowner_str(strhashval, open);
+-	if (sop) {
+-		open->op_stateowner = sop;
+-		if (!sop->so_confirmed) {
+-			/* Replace any unconfirmed stateowner without
+-			 * even checking for replays */
+-			clp = sop->so_client;
+-			release_stateowner(sop);
+-		} else if (open->op_seqid == sop->so_seqid) {
+-			/* normal case */
+-			goto renew;
+-		} else if (open->op_seqid == sop->so_seqid - 1) {
+-			/* replay */
+-			if (sop->so_replay.rp_buflen)
+-				return NFSERR_REPLAY_ME;
+-			else {
+-				/* The original OPEN failed so spectacularly
+-				 * that we don't even have replay data saved!
+-				 * Therefore, we have no choice but to continue
+-				 * processing this OPEN; presumably, we'll
+-				 * fail again for the same reason.
+-				 */
+-				dprintk("nfsd4_process_open1:"
+-					" replay with no replay cache\n");
+-				goto renew;
+-			}
+-		} else {
+-			status = nfserr_bad_seqid;
+-			goto out;
+-		}
+-	} else {
+-		/* nfs4_stateowner not found.
+-		 * Verify clientid and instantiate new nfs4_stateowner.
+-		 * If verify fails this is presumably the result of the
+-		 * client's lease expiring.
+-		 */
+-		status = nfserr_expired;
++	open->op_stateowner = sop;
++	if (!sop) {
++		/* Make sure the client's lease hasn't expired. */
+ 		clp = find_confirmed_client(clientid);
+ 		if (clp == NULL)
+-			goto out;
++			return nfserr_expired;
++		goto renew;
+ 	}
+-	status = nfserr_resource;
+-	sop = alloc_init_open_stateowner(strhashval, clp, open);
+-	if (sop == NULL)
+-		goto out;
+-	open->op_stateowner = sop;
++	if (!sop->so_confirmed) {
++		/* Replace unconfirmed owners without checking for replay. */
++		clp = sop->so_client;
++		release_stateowner(sop);
++		open->op_stateowner = NULL;
++		goto renew;
++	}
++	if (open->op_seqid == sop->so_seqid - 1) {
++		if (sop->so_replay.rp_buflen)
++			return NFSERR_REPLAY_ME;
++		/* The original OPEN failed so spectacularly
++		 * that we don't even have replay data saved!
++		 * Therefore, we have no choice but to continue
++		 * processing this OPEN; presumably, we'll
++		 * fail again for the same reason.
++		 */
++		dprintk("nfsd4_process_open1: replay with no replay cache\n");
++		goto renew;
++	}
++	if (open->op_seqid != sop->so_seqid)
++		return nfserr_bad_seqid;
+ renew:
+-	status = nfs_ok;
++	if (open->op_stateowner == NULL) {
++		sop = alloc_init_open_stateowner(strhashval, clp, open);
++		if (sop == NULL)
++			return nfserr_resource;
++		open->op_stateowner = sop;
++	}
++	list_del_init(&sop->so_close_lru);
+ 	renew_client(sop->so_client);
+-out:
+-	return status;
++	return nfs_ok;
+ }
+ 
+ static inline int

commit 375c5547cbf39423078535affac66c8afdc8fafb
+Author: J. Bruce Fields 
+Date:   Wed Jan 18 17:43:33 2006 -0800
+
+    [PATCH] nfsd4: nfs4state.c miscellaneous goto removals
+    
+    Remove some goto's that made the logic here a little more tortuous than
+    necessary.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index 69ee182575ab..89028f2d8d26 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -592,25 +592,21 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se
+ 	status = nfs_ok;
+ 	if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
+ 		nfs4_lock_state();
+-		if ((status = nfs4_preprocess_stateid_op(current_fh,
+-						&setattr->sa_stateid,
+-						CHECK_FH | WR_STATE, NULL))) {
+-			dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");
+-			goto out_unlock;
+-		}
++		status = nfs4_preprocess_stateid_op(current_fh,
++			&setattr->sa_stateid, CHECK_FH | WR_STATE, NULL);
+ 		nfs4_unlock_state();
++		if (status) {
++			dprintk("NFSD: nfsd4_setattr: couldn't process stateid!");
++			return status;
++		}
+ 	}
+ 	status = nfs_ok;
+ 	if (setattr->sa_acl != NULL)
+ 		status = nfsd4_set_nfs4_acl(rqstp, current_fh, setattr->sa_acl);
+ 	if (status)
+-		goto out;
++		return status;
+ 	status = nfsd_setattr(rqstp, current_fh, &setattr->sa_iattr,
+ 				0, (time_t)0);
+-out:
+-	return status;
+-out_unlock:
+-	nfs4_unlock_state();
+ 	return status;
+ }
+ 
+@@ -628,15 +624,17 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
+ 		return nfserr_inval;
+ 
+ 	nfs4_lock_state();
+-	if ((status = nfs4_preprocess_stateid_op(current_fh, stateid,
+-					CHECK_FH | WR_STATE, &filp))) {
+-		dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
+-		goto out;
+-	}
++	status = nfs4_preprocess_stateid_op(current_fh, stateid,
++					CHECK_FH | WR_STATE, &filp);
+ 	if (filp)
+ 		get_file(filp);
+ 	nfs4_unlock_state();
+ 
++	if (status) {
++		dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
++		return status;
++	}
++
+ 	write->wr_bytes_written = write->wr_buflen;
+ 	write->wr_how_written = write->wr_stable_how;
+ 	p = (u32 *)write->wr_verifier.data;
+@@ -652,9 +650,6 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
+ 	if (status == nfserr_symlink)
+ 		status = nfserr_inval;
+ 	return status;
+-out:
+-	nfs4_unlock_state();
+-	return status;
+ }
+ 
+ /* This routine never returns NFS_OK!  If there are no other errors, it

commit ae8b625313db4dd4b060962c2a02f3a2837ca61b
+Author: J. Bruce Fields 
+Date:   Wed Jan 18 17:43:32 2006 -0800
+
+    [PATCH] nfsd4: no replays on unconfirmed owners
+    
+    We shouldn't check for replays until after checking whether the open owner is
+    confirmed.  Clients are allowed to reuse openowners without bumping the seqid.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index e13d2233ff8c..dc792b6b4513 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1465,8 +1465,16 @@ nfsd4_process_open1(struct nfsd4_open *open)
+ 	sop = find_openstateowner_str(strhashval, open);
+ 	if (sop) {
+ 		open->op_stateowner = sop;
+-		/* check for replay */
+-		if (open->op_seqid == sop->so_seqid - 1){
++		if (!sop->so_confirmed) {
++			/* Replace any unconfirmed stateowner without
++			 * even checking for replays */
++			clp = sop->so_client;
++			release_stateowner(sop);
++		} else if (open->op_seqid == sop->so_seqid) {
++			/* normal case */
++			goto renew;
++		} else if (open->op_seqid == sop->so_seqid - 1) {
++			/* replay */
+ 			if (sop->so_replay.rp_buflen)
+ 				return NFSERR_REPLAY_ME;
+ 			else {
+@@ -1480,19 +1488,9 @@ nfsd4_process_open1(struct nfsd4_open *open)
+ 					" replay with no replay cache\n");
+ 				goto renew;
+ 			}
+-		} else if (sop->so_confirmed) {
+-			if (open->op_seqid == sop->so_seqid)
+-				goto renew;
++		} else {
+ 			status = nfserr_bad_seqid;
+ 			goto out;
+-		} else {
+-			/* If we get here, we received an OPEN for an
+-			 * unconfirmed nfs4_stateowner. Since the seqid's are
+-			 * different, purge the existing nfs4_stateowner, and
+-			 * instantiate a new one.
+-			 */
+-			clp = sop->so_client;
+-			release_stateowner(sop);
+ 		}
+ 	} else {
+ 		/* nfs4_stateowner not found.

commit a525825df15221a95d4c1f5a291d9fde77ef10bc
+Author: J. Bruce Fields 
+Date:   Wed Jan 18 17:43:30 2006 -0800
+
+    [PATCH] nfsd4: handle replays of failed open reclaims
+    
+    We need to make sure open reclaims are marked confirmed immediately so that we
+    can handle replays even if they fail (e.g.  with a seqid-incrementing error).
+    (See 8.1.8.)
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index 2a1766ce216f..69ee182575ab 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -210,6 +210,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
+ 				goto out;
+ 			break;
+ 		case NFS4_OPEN_CLAIM_PREVIOUS:
++			open->op_stateowner->so_confirmed = 1;
+ 			/*
+ 			 * The CURRENT_FH is already set to the file being
+ 			 * opened.  (1) set open->op_cinfo, (2) set
+@@ -221,6 +222,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
+ 				goto out;
+ 			break;
+              	case NFS4_OPEN_CLAIM_DELEGATE_PREV:
++			open->op_stateowner->so_confirmed = 1;
+ 			printk("NFSD: unsupported OPEN claim type %d\n",
+ 				open->op_claim_type);
+ 			status = nfserr_notsupp;

commit c2642ab05b855d2d3b850ddf90dbb02b1b9358ac
+Author: J. Bruce Fields 
+Date:   Wed Jan 18 17:43:29 2006 -0800
+
+    [PATCH] nfsd4: recovery lookup dir check
+    
+    Make sure we get a directory when we look up the recovery directory.
+    
+    Thanks to Christoph Hellwig for the bug report.
+    
+    Based on feedback from Christoph and others, we may remove the need for this
+    lookup and just pass in a file descriptor from userspace instead, and/or
+    completely move the directory handling to userspace.  For now we're just
+    fixing the obvious bugs.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
+index 64f4af3651a1..06da7506363c 100644
+--- a/fs/nfsd/nfs4recover.c
++++ b/fs/nfsd/nfs4recover.c
+@@ -399,9 +399,10 @@ nfsd4_init_recdir(char *rec_dirname)
+ 
+ 	nfs4_save_user(&uid, &gid);
+ 
+-	status = path_lookup(rec_dirname, LOOKUP_FOLLOW, &rec_dir);
+-	if (status == -ENOENT)
+-		printk("NFSD: recovery directory %s doesn't exist\n",
++	status = path_lookup(rec_dirname, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
++			&rec_dir);
++	if (status)
++		printk("NFSD: unable to find recovery directory %s\n",
+ 				rec_dirname);
+ 
+ 	if (!status)

commit d22749b62f3e12de26b86a200f9a5bf7afe3590e
+Author: J. Bruce Fields 
+Date:   Wed Jan 18 17:43:27 2006 -0800
+
+    [PATCH] nfsd4: fix open of recovery directory
+    
+    We should be opening this directory RDONLY, not RDWR.
+    
+    Thanks to Christoph Hellwig for the bug report.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
+index be963a133aaa..64f4af3651a1 100644
+--- a/fs/nfsd/nfs4recover.c
++++ b/fs/nfsd/nfs4recover.c
+@@ -222,8 +222,7 @@ nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
+ 
+ 	nfs4_save_user(&uid, &gid);
+ 
+-	filp = dentry_open(dget(dir), mntget(rec_dir.mnt),
+-			O_RDWR);
++	filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY);
+ 	status = PTR_ERR(filp);
+ 	if (IS_ERR(filp))
+ 		goto out;

commit 5fb8b49e2955cc473929c5994b8389111daed59d
+Author: J. Bruce Fields 
+Date:   Wed Jan 18 17:43:26 2006 -0800
+
+    [PATCH] svcrpc: gss: svc context creation error handling
+    
+    Allow mechanisms to return more varied errors on the context creation
+    downcall.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
+index fdad66dc9a9f..23632d84d8d7 100644
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -420,7 +420,8 @@ static int rsc_parse(struct cache_detail *cd,
+ 			gss_mech_put(gm);
+ 			goto out;
+ 		}
+-		if (gss_import_sec_context(buf, len, gm, &rsci.mechctx)) {
++		status = gss_import_sec_context(buf, len, gm, &rsci.mechctx);
++		if (status) {
+ 			gss_mech_put(gm);
+ 			goto out;
+ 		}

commit 91a4762e0ab0880fa00e8f0b7a052e4929d867a6
+Author: Kevin Coffman 
+Date:   Wed Jan 18 17:43:25 2006 -0800
+
+    [PATCH] svcrpc: gss: server context init failure handling
+    
+    We require the server's gssd to create a completed context before asking the
+    kernel to send a final context init reply.  However, gssd could be buggy, or
+    under some bizarre circumstances we might purge the context from our cache
+    before we get the chance to use it here.
+    
+    Handle this case by returning GSS_S_NO_CONTEXT to the client.
+    
+    Also move the relevant code here to a separate function rather than nesting
+    excessively.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
+index d2ccc7e8faab..fdad66dc9a9f 100644
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -755,6 +755,21 @@ svcauth_gss_set_client(struct svc_rqst *rqstp)
+ 	return SVC_OK;
+ }
+ 
++static inline int
++gss_write_init_verf(struct svc_rqst *rqstp, struct rsi *rsip)
++{
++	struct rsc *rsci;
++
++	if (rsip->major_status != GSS_S_COMPLETE)
++		return gss_write_null_verf(rqstp);
++	rsci = gss_svc_searchbyctx(&rsip->out_handle);
++	if (rsci == NULL) {
++		rsip->major_status = GSS_S_NO_CONTEXT;
++		return gss_write_null_verf(rqstp);
++	}
++	return gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN);
++}
++
+ /*
+  * Accept an rpcsec packet.
+  * If context establishment, punt to user space
+@@ -890,18 +905,8 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
+ 		case -ENOENT:
+ 			goto drop;
+ 		case 0:
+-			if (rsip->major_status == GSS_S_COMPLETE) {
+-				rsci = gss_svc_searchbyctx(&rsip->out_handle);
+-				if (!rsci) {
+-					goto drop;
+-				}
+-				if (gss_write_verf(rqstp, rsci->mechctx,
+-							GSS_SEQ_WIN))
+-					goto drop;
+-			} else {
+-				if (gss_write_null_verf(rqstp))
+-					goto drop;
+-			}
++			if (gss_write_init_verf(rqstp, rsip))
++				goto drop;
+ 			if (resv->iov_len + 4 > PAGE_SIZE)
+ 				goto drop;
+ 			svc_putu32(resv, rpc_success);

commit 822f1005ae1f3a4a8b136f38a6933d3f719f4c4a
+Author: Andy Adamson 
+Date:   Wed Jan 18 17:43:24 2006 -0800
+
+    [PATCH] svcrpc: gss: handle the GSS_S_CONTINUE
+    
+    Kerberos context initiation is handled in a single round trip, but other
+    mechanisms (including spkm3) may require more, so we need to handle the
+    GSS_S_CONTINUE case in svcauth_gss_accept.  Send a null verifier.
+    
+    Signed-off-by: Andy Adamson 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
+index e4ada15ed856..d2ccc7e8faab 100644
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -585,6 +585,20 @@ gss_verify_header(struct svc_rqst *rqstp, struct rsc *rsci,
+ 	return SVC_OK;
+ }
+ 
++static int
++gss_write_null_verf(struct svc_rqst *rqstp)
++{
++	u32     *p;
++
++	svc_putu32(rqstp->rq_res.head, htonl(RPC_AUTH_NULL));
++	p = rqstp->rq_res.head->iov_base + rqstp->rq_res.head->iov_len;
++	/* don't really need to check if head->iov_len > PAGE_SIZE ... */
++	*p++ = 0;
++	if (!xdr_ressize_check(rqstp, p))
++		return -1;
++	return 0;
++}
++
+ static int
+ gss_write_verf(struct svc_rqst *rqstp, struct gss_ctx *ctx_id, u32 seq)
+ {
+@@ -876,12 +890,18 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
+ 		case -ENOENT:
+ 			goto drop;
+ 		case 0:
+-			rsci = gss_svc_searchbyctx(&rsip->out_handle);
+-			if (!rsci) {
+-				goto drop;
++			if (rsip->major_status == GSS_S_COMPLETE) {
++				rsci = gss_svc_searchbyctx(&rsip->out_handle);
++				if (!rsci) {
++					goto drop;
++				}
++				if (gss_write_verf(rqstp, rsci->mechctx,
++							GSS_SEQ_WIN))
++					goto drop;
++			} else {
++				if (gss_write_null_verf(rqstp))
++					goto drop;
+ 			}
+-			if (gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN))
+-				goto drop;
+ 			if (resv->iov_len + 4 > PAGE_SIZE)
+ 				goto drop;
+ 			svc_putu32(resv, rpc_success);

commit fd44527707f2697fd2959e8bdb321ae588d150e2
+Author: J. Bruce Fields 
+Date:   Wed Jan 18 17:43:23 2006 -0800
+
+    [PATCH] nfsd4: operation debugging
+    
+    Simple, useful debugging printk: print the number of each op as we process it.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index 361b4007d4a0..2a1766ce216f 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -768,6 +768,8 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
+ 	while (!status && resp->opcnt < args->opcnt) {
+ 		op = &args->ops[resp->opcnt++];
+ 
++		dprintk("nfsv4 compound op #%d: %d\n", resp->opcnt, op->opnum);
++
+ 		/*
+ 		 * The XDR decode routines may have pre-set op->status;
+ 		 * for example, if there is a miscellaneous XDR error

commit 796dadfd02eda1e3e6e42ecc8379d8b1c1523ddf
+Author: J. Bruce Fields 
+Date:   Wed Jan 18 17:43:22 2006 -0800
+
+    [PATCH] nfsd4: fix check_for_locks
+    
+    Fix some bad logic.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 3510e2ca40d2..e13d2233ff8c 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2989,9 +2989,10 @@ check_for_locks(struct file *filp, struct nfs4_stateowner *lowner)
+ 
+ 	lock_kernel();
+ 	for (flpp = &inode->i_flock; *flpp != NULL; flpp = &(*flpp)->fl_next) {
+-		if ((*flpp)->fl_owner == (fl_owner_t)lowner)
++		if ((*flpp)->fl_owner == (fl_owner_t)lowner) {
+ 			status = 1;
+ 			goto out;
++		}
+ 	}
+ out:
+ 	unlock_kernel();

commit 04ef59548470b81829e8593c1b39776ce0534d68
+Author: J. Bruce Fields 
+Date:   Wed Jan 18 17:43:21 2006 -0800
+
+    [PATCH] nfsd4: remove release_state_owner()
+    
+    It's confusing having both release_stateowner() and release_state_owner().
+    
+    And as it turns out, release_state_owner() is short and only called from one
+    place; so just remove it.
+    
+    Also note the confirmed check is superfluous there--preprocess_seqid_op
+    already check this.
+    
+    And remove a redundant comment and a superfluous line assignment while we're
+    at it.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 578ea521c827..3510e2ca40d2 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1178,7 +1178,6 @@ release_stateid(struct nfs4_stateid *stp, int flags)
+ 		locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner);
+ 	put_nfs4_file(stp->st_file);
+ 	kmem_cache_free(stateid_slab, stp);
+-	stp = NULL;
+ }
+ 
+ static void
+@@ -1191,22 +1190,6 @@ move_to_close_lru(struct nfs4_stateowner *sop)
+ 	sop->so_time = get_seconds();
+ }
+ 
+-static void
+-release_state_owner(struct nfs4_stateid *stp, int flag)
+-{
+-	struct nfs4_stateowner *sop = stp->st_stateowner;
+-
+-	dprintk("NFSD: release_state_owner\n");
+-	release_stateid(stp, flag);
+-
+-	/* place unused nfs4_stateowners on so_close_lru list to be
+-	 * released by the laundromat service after the lease period
+-	 * to enable us to handle CLOSE replay
+-	 */
+-	if (sop->so_confirmed && list_empty(&sop->so_stateids))
+-		move_to_close_lru(sop);
+-}
+-
+ static int
+ cmp_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner, clientid_t *clid) {
+ 	return ((sop->so_owner.len == owner->len) && 
+@@ -2423,15 +2406,19 @@ nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_clos
+ 					CHECK_FH | OPEN_STATE | CLOSE_STATE,
+ 					&close->cl_stateowner, &stp, NULL)))
+ 		goto out; 
+-	/*
+-	*  Return success, but first update the stateid.
+-	*/
+ 	status = nfs_ok;
+ 	update_stateid(&stp->st_stateid);
+ 	memcpy(&close->cl_stateid, &stp->st_stateid, sizeof(stateid_t));
+ 
+-	/* release_state_owner() calls nfsd_close() if needed */
+-	release_state_owner(stp, OPEN_STATE);
++	/* release_stateid() calls nfsd_close() if needed */
++	release_stateid(stp, OPEN_STATE);
++
++	/* place unused nfs4_stateowners on so_close_lru list to be
++	 * released by the laundromat service after the lease period
++	 * to enable us to handle CLOSE replay
++	 */
++	if (list_empty(&close->cl_stateowner->so_stateids))
++		move_to_close_lru(close->cl_stateowner);
+ out:
+ 	if (close->cl_stateowner) {
+ 		nfs4_get_stateowner(close->cl_stateowner);

commit 3a65588adc4401622b204caa897123e16a4a0318
+Author: J. Bruce Fields 
+Date:   Wed Jan 18 17:43:19 2006 -0800
+
+    [PATCH] nfsd4: rename lk_stateowner
+    
+    One of the things that's confusing about nfsd4_lock is that the lk_stateowner
+    field could be set to either of two different lockowners: the open owner or
+    the lock owner.  Rename to lk_replay_owner and add a comment to make it clear
+    that it's used for whichever stateowner has its sequence id bumped for replay
+    detection.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 5bf7fd3947ce..578ea521c827 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2725,11 +2725,11 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
+ 				        lock->lk_new_open_seqid,
+ 		                        &lock->lk_new_open_stateid,
+ 		                        CHECK_FH | OPEN_STATE,
+-		                        &lock->lk_stateowner, &open_stp,
++		                        &lock->lk_replay_owner, &open_stp,
+ 					lock);
+ 		if (status)
+ 			goto out;
+-		open_sop = lock->lk_stateowner;
++		open_sop = lock->lk_replay_owner;
+ 		/* create lockowner and lock stateid */
+ 		fp = open_stp->st_file;
+ 		strhashval = lock_ownerstr_hashval(fp->fi_inode, 
+@@ -2752,12 +2752,12 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
+ 				       lock->lk_old_lock_seqid, 
+ 				       &lock->lk_old_lock_stateid, 
+ 				       CHECK_FH | LOCK_STATE, 
+-				       &lock->lk_stateowner, &lock_stp, lock);
++				       &lock->lk_replay_owner, &lock_stp, lock);
+ 		if (status)
+ 			goto out;
+-		lock_sop = lock->lk_stateowner;
++		lock_sop = lock->lk_replay_owner;
+ 	}
+-	/* lock->lk_stateowner and lock_stp have been created or found */
++	/* lock->lk_replay_owner and lock_stp have been created or found */
+ 	filp = lock_stp->st_vfs_file;
+ 
+ 	status = nfserr_grace;
+@@ -2830,9 +2830,9 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
+ out:
+ 	if (status && lock->lk_is_new && lock_sop)
+ 		release_stateowner(lock_sop);
+-	if (lock->lk_stateowner) {
+-		nfs4_get_stateowner(lock->lk_stateowner);
+-		*replay_owner = lock->lk_stateowner;
++	if (lock->lk_replay_owner) {
++		nfs4_get_stateowner(lock->lk_replay_owner);
++		*replay_owner = lock->lk_replay_owner;
+ 	}
+ 	nfs4_unlock_state();
+ 	return status;
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index dcd673186944..6b743327686c 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -528,7 +528,7 @@ nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock)
+ {
+ 	DECODE_HEAD;
+ 
+-	lock->lk_stateowner = NULL;
++	lock->lk_replay_owner = NULL;
+ 	/*
+ 	* type, reclaim(boolean), offset, length, new_lock_owner(boolean)
+ 	*/
+@@ -1895,7 +1895,6 @@ nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denie
+ static void
+ nfsd4_encode_lock(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lock *lock)
+ {
+-
+ 	ENCODE_SEQID_OP_HEAD;
+ 
+ 	if (!nfserr) {
+@@ -1906,7 +1905,7 @@ nfsd4_encode_lock(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lock
+ 	} else if (nfserr == nfserr_denied)
+ 		nfsd4_encode_lock_denied(resp, &lock->lk_denied);
+ 
+-	ENCODE_SEQID_OP_TAIL(lock->lk_stateowner);
++	ENCODE_SEQID_OP_TAIL(lock->lk_replay_owner);
+ }
+ 
+ static void
+diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
+index 8903688890ce..77adba7d2281 100644
+--- a/include/linux/nfsd/xdr4.h
++++ b/include/linux/nfsd/xdr4.h
+@@ -145,8 +145,9 @@ struct nfsd4_lock {
+ 		} ok;
+ 		struct nfsd4_lock_denied        denied;
+ 	} u;
+-
+-	struct nfs4_stateowner *lk_stateowner;
++	/* The lk_replay_owner is the open owner in the open_to_lock_owner
++	 * case and the lock owner otherwise: */
++	struct nfs4_stateowner *lk_replay_owner;
+ };
+ #define lk_new_open_seqid       v.new.open_seqid
+ #define lk_new_open_stateid     v.new.open_stateid

commit 8a280510852959c0d51b1d625e90c0491c238368
+Author: J. Bruce Fields 
+Date:   Wed Jan 18 17:43:18 2006 -0800
+
+    [PATCH] nfsd4: fix nfsd4_lock cleanup on failure
+    
+    release_state_owner also puts the lock owner on the close_lru.  There's no
+    need for that, though; replays of the failed lock would be handled by the
+    openowner not the lockowner.
+    
+    Also consolidate the cleanup a bit, fixing leaks that can happen if errors
+    occur between the time a new lock owner is allocated and the lock is done.
+    
+    Remove a comment and dprintk that look a little redundant.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 3d4a2ec97caa..5bf7fd3947ce 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2744,10 +2744,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
+ 		if (lock_sop == NULL)
+ 			goto out;
+ 		lock_stp = alloc_init_lock_stateid(lock_sop, fp, open_stp);
+-		if (lock_stp == NULL) {
+-			release_stateowner(lock_sop);
++		if (lock_stp == NULL)
+ 			goto out;
+-		}
+ 	} else {
+ 		/* lock (lock owner + lock stateid) already exists */
+ 		status = nfs4_preprocess_seqid_op(current_fh,
+@@ -2815,7 +2813,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
+ 		status = nfserr_deadlock;
+ 	default:        
+ 		dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status);
+-		goto out_destroy_new_stateid;
++		goto out;
+ 	}
+ 
+ conflicting_lock:
+@@ -2829,17 +2827,9 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
+ 		goto out;
+ 	}
+ 	nfs4_set_lock_denied(conflock, &lock->lk_denied);
+-
+-out_destroy_new_stateid:
+-	if (lock->lk_is_new) {
+-		dprintk("NFSD: nfsd4_lock: destroy new stateid!\n");
+-		/*
+-		 * An error encountered after instantiation of the new
+-		 * stateid has forced us to destroy it.
+-		 */
+-		release_state_owner(lock_stp, LOCK_STATE);
+-	}
+ out:
++	if (status && lock->lk_is_new && lock_sop)
++		release_stateowner(lock_sop);
+ 	if (lock->lk_stateowner) {
+ 		nfs4_get_stateowner(lock->lk_stateowner);
+ 		*replay_owner = lock->lk_stateowner;

commit a6f6ef2f1d7329111fcad7db48fb7adba5062d0a
+Author: Andy Adamson 
+Date:   Wed Jan 18 17:43:17 2006 -0800
+
+    [PATCH] nfsd4: misc lock fixes
+    
+    Logic fixes for LOCK and UNLOCK.
+    
+    - Move the permission check on the current file handle outside of
+      nfs4_lock_state()
+    
+    - remove the file manager fl_release_private calls; fl_ops is not set.
+    
+    Signed-off-by: Andy Adamson 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 6bbefd06f10d..3d4a2ec97caa 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2700,6 +2700,11 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
+ 	if (check_lock_length(lock->lk_offset, lock->lk_length))
+ 		 return nfserr_inval;
+ 
++	if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) {
++		dprintk("NFSD: nfsd4_lock: permission denied!\n");
++		return status;
++	}
++
+ 	nfs4_lock_state();
+ 
+ 	if (lock->lk_is_new) {
+@@ -2757,11 +2762,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
+ 	/* lock->lk_stateowner and lock_stp have been created or found */
+ 	filp = lock_stp->st_vfs_file;
+ 
+-	if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) {
+-		dprintk("NFSD: nfsd4_lock: permission denied!\n");
+-		goto out;
+-	}
+-
+ 	status = nfserr_grace;
+ 	if (nfs4_in_grace() && !lock->lk_reclaim)
+ 		goto out;
+@@ -2802,8 +2802,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
+ 	*/
+ 
+ 	status = posix_lock_file(filp, &file_lock);
+-	if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
+-		file_lock.fl_ops->fl_release_private(&file_lock);
+ 	dprintk("NFSD: nfsd4_lock: posix_lock_file status %d\n",status);
+ 	switch (-status) {
+ 	case 0: /* success! */
+@@ -2977,8 +2975,6 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
+ 	*  Try to unlock the file in the VFS.
+ 	*/
+ 	status = posix_lock_file(filp, &file_lock); 
+-	if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
+-		file_lock.fl_ops->fl_release_private(&file_lock);
+ 	if (status) {
+ 		dprintk("NFSD: nfs4_locku: posix_lock_file failed!\n");
+ 		goto out_nfserr;

commit 1918e341383ab787d6c5b17200f4ed901b10c777
+Author: J. Bruce Fields 
+Date:   Wed Jan 18 17:43:16 2006 -0800
+
+    [PATCH] svcrpc: save and restore the daddr field when request deferred
+    
+    The server code currently keeps track of the destination address on every
+    request so that it can reply using the same address.  However we forget to do
+    that in the case of a deferred request.  Remedy this oversight.  >From folks
+    at PolyServe.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
+index e4086ec8b952..50cab2a09f28 100644
+--- a/include/linux/sunrpc/svc.h
++++ b/include/linux/sunrpc/svc.h
+@@ -246,6 +246,7 @@ struct svc_deferred_req {
+ 	u32			prot;	/* protocol (UDP or TCP) */
+ 	struct sockaddr_in	addr;
+ 	struct svc_sock		*svsk;	/* where reply must go */
++	u32			daddr;	/* where reply must come from */
+ 	struct cache_deferred_req handle;
+ 	int			argslen;
+ 	u32			args[0];
+diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
+index e67613e4eb18..50580620e897 100644
+--- a/net/sunrpc/svcsock.c
++++ b/net/sunrpc/svcsock.c
+@@ -1527,6 +1527,7 @@ svc_defer(struct cache_req *req)
+ 		dr->handle.owner = rqstp->rq_server;
+ 		dr->prot = rqstp->rq_prot;
+ 		dr->addr = rqstp->rq_addr;
++		dr->daddr = rqstp->rq_daddr;
+ 		dr->argslen = rqstp->rq_arg.len >> 2;
+ 		memcpy(dr->args, rqstp->rq_arg.head[0].iov_base-skip, dr->argslen<<2);
+ 	}
+@@ -1552,6 +1553,7 @@ static int svc_deferred_recv(struct svc_rqst *rqstp)
+ 	rqstp->rq_arg.len = dr->argslen<<2;
+ 	rqstp->rq_prot        = dr->prot;
+ 	rqstp->rq_addr        = dr->addr;
++	rqstp->rq_daddr       = dr->daddr;
+ 	return dr->argslen<<2;
+ }
+ 

commit ad8e4b75c8a7bed475d72ce09bf5267188621961
+Author: Martin Murray 
+Date:   Tue Jan 10 13:02:29 2006 -0800
+
+    [AF_NETLINK]: Fix DoS in netlink_rcv_skb()
+    
+    From: Martin Murray 
+    
+    Sanity check nlmsg_len during netlink_rcv_skb.  An nlmsg_len == 0 can
+    cause infinite loop in kernel, effectively DoSing machine.  Noted by
+    Matin Murray.
+    
+    Signed-off-by: Chris Wright 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
+index a67f1b44c9a3..bb50c8a9fcad 100644
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -1422,7 +1422,7 @@ static int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *,
+ 	while (skb->len >= nlmsg_total_size(0)) {
+ 		nlh = (struct nlmsghdr *) skb->data;
+ 
+-		if (skb->len < nlh->nlmsg_len)
++		if (nlh->nlmsg_len < NLMSG_HDRLEN || skb->len < nlh->nlmsg_len)
+ 			return 0;
+ 
+ 		total_len = min(NLMSG_ALIGN(nlh->nlmsg_len), skb->len);

commit 6cd7525a00f3b926e8bd2e402954ed3e09a8e924
+Author: Chuck Lever 
+Date:   Thu Sep 22 21:24:59 2005 -0400
+
+    SUNRPC: fix bug in patch "portmapper doesn't need a reserved port"
+    
+     The in-kernel portmapper does in fact need a reserved port when registering
+     new services, but not when performing bind queries.
+    
+     Ensure that we distinguish between the two cases.
+    
+     Signed-off-by: Chuck Lever 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c
+index d8e3f220002b..a398575f94b8 100644
+--- a/net/sunrpc/pmap_clnt.c
++++ b/net/sunrpc/pmap_clnt.c
+@@ -26,7 +26,7 @@
+ #define PMAP_GETPORT		3
+ 
+ static struct rpc_procinfo	pmap_procedures[];
+-static struct rpc_clnt *	pmap_create(char *, struct sockaddr_in *, int);
++static struct rpc_clnt *	pmap_create(char *, struct sockaddr_in *, int, int);
+ static void			pmap_getport_done(struct rpc_task *);
+ static struct rpc_program	pmap_program;
+ static DEFINE_SPINLOCK(pmap_lock);
+@@ -65,7 +65,7 @@ rpc_getport(struct rpc_task *task, struct rpc_clnt *clnt)
+ 	map->pm_binding = 1;
+ 	spin_unlock(&pmap_lock);
+ 
+-	pmap_clnt = pmap_create(clnt->cl_server, sap, map->pm_prot);
++	pmap_clnt = pmap_create(clnt->cl_server, sap, map->pm_prot, 0);
+ 	if (IS_ERR(pmap_clnt)) {
+ 		task->tk_status = PTR_ERR(pmap_clnt);
+ 		goto bailout;
+@@ -112,7 +112,7 @@ rpc_getport_external(struct sockaddr_in *sin, __u32 prog, __u32 vers, int prot)
+ 			NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
+ 
+ 	sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr));
+-	pmap_clnt = pmap_create(hostname, sin, prot);
++	pmap_clnt = pmap_create(hostname, sin, prot, 0);
+ 	if (IS_ERR(pmap_clnt))
+ 		return PTR_ERR(pmap_clnt);
+ 
+@@ -171,7 +171,7 @@ rpc_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
+ 
+ 	sin.sin_family = AF_INET;
+ 	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+-	pmap_clnt = pmap_create("localhost", &sin, IPPROTO_UDP);
++	pmap_clnt = pmap_create("localhost", &sin, IPPROTO_UDP, 1);
+ 	if (IS_ERR(pmap_clnt)) {
+ 		error = PTR_ERR(pmap_clnt);
+ 		dprintk("RPC: couldn't create pmap client. Error = %d\n", error);
+@@ -198,7 +198,7 @@ rpc_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
+ }
+ 
+ static struct rpc_clnt *
+-pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto)
++pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto, int privileged)
+ {
+ 	struct rpc_xprt	*xprt;
+ 	struct rpc_clnt	*clnt;
+@@ -208,7 +208,8 @@ pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto)
+ 	if (IS_ERR(xprt))
+ 		return (struct rpc_clnt *)xprt;
+ 	xprt->addr.sin_port = htons(RPC_PMAP_PORT);
+-	xprt->resvport = 0;
++	if (!privileged)
++		xprt->resvport = 0;
+ 
+ 	/* printk("pmap: create clnt\n"); */
+ 	clnt = rpc_new_client(xprt, hostname,

commit 262965f53defd312a294b45366ea17907b6a616b
+Author: Chuck Lever 
+Date:   Thu Aug 11 16:25:56 2005 -0400
+
+    [PATCH] RPC: separate TCP and UDP socket write paths
+    
+     Split the RPC client's main socket write path into a TCP version and a UDP
+     version to eliminate another dependency on the "xprt->stream" variable.
+    
+     Compiler optimization removes unneeded code from xs_sendpages, as this
+     function is now called with some constant arguments.
+    
+     We can now cleanly perform transport protocol-specific return code testing
+     and error recovery in each path.
+    
+     Test-plan:
+     Millions of fsx operations.  Performance characterization such as
+     "sio" or "iozone".  Examine oprofile results for any changes before and
+     after this patch is applied.
+    
+     Version: Thu, 11 Aug 2005 16:08:46 -0400
+    
+     Signed-off-by: Chuck Lever 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
+index f91529787b9b..57988300640a 100644
+--- a/net/sunrpc/xprtsock.c
++++ b/net/sunrpc/xprtsock.c
+@@ -40,6 +40,12 @@
+  */
+ #define XS_MAX_RESVPORT		(800U)
+ 
++/*
++ * How many times to try sending a request on a socket before waiting
++ * for the socket buffer to clear.
++ */
++#define XS_SENDMSG_RETRY	(10U)
++
+ #ifdef RPC_DEBUG
+ # undef  RPC_DEBUG_DATA
+ # define RPCDBG_FACILITY	RPCDBG_TRANS
+@@ -114,13 +120,18 @@ static int xs_send_tail(struct socket *sock, struct xdr_buf *xdr, unsigned int b
+  * @base: starting position in the buffer
+  *
+  */
+-static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base)
++static inline int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base)
+ {
+ 	struct page **ppage = xdr->pages;
+ 	unsigned int len, pglen = xdr->page_len;
+ 	int err, ret = 0;
+ 	ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
+ 
++	if (unlikely(!sock))
++		return -ENOTCONN;
++
++	clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
++
+ 	len = xdr->head[0].iov_len;
+ 	if (base < len || (addr != NULL && base == 0)) {
+ 		err = xs_send_head(sock, addr, addrlen, xdr, base, len);
+@@ -187,140 +198,162 @@ static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
+ }
+ 
+ /**
+- * xs_sendmsg - write an RPC request to a socket
+- * @xprt: generic transport
+- * @req: the RPC request to write
++ * xs_nospace - place task on wait queue if transmit was incomplete
++ * @task: task to put to sleep
+  *
+  */
+-static int xs_sendmsg(struct rpc_xprt *xprt, struct rpc_rqst *req)
++static void xs_nospace(struct rpc_task *task)
+ {
+-	struct socket *sock = xprt->sock;
+-	struct xdr_buf *xdr = &req->rq_snd_buf;
+-	struct sockaddr *addr = NULL;
+-	int addrlen = 0;
+-	unsigned int skip;
+-	int result;
++	struct rpc_rqst *req = task->tk_rqstp;
++	struct rpc_xprt *xprt = req->rq_xprt;
+ 
+-	if (!sock)
+-		return -ENOTCONN;
++	dprintk("RPC: %4d xmit incomplete (%u left of %u)\n",
++			task->tk_pid, req->rq_slen - req->rq_bytes_sent,
++			req->rq_slen);
++
++	if (test_bit(SOCK_ASYNC_NOSPACE, &xprt->sock->flags)) {
++		/* Protect against races with write_space */
++		spin_lock_bh(&xprt->transport_lock);
++
++		/* Don't race with disconnect */
++		if (!xprt_connected(xprt))
++			task->tk_status = -ENOTCONN;
++		else if (test_bit(SOCK_NOSPACE, &xprt->sock->flags))
++			xprt_wait_for_buffer_space(task);
++
++		spin_unlock_bh(&xprt->transport_lock);
++	} else
++		/* Keep holding the socket if it is blocked */
++		rpc_delay(task, HZ>>4);
++}
++
++/**
++ * xs_udp_send_request - write an RPC request to a UDP socket
++ * @task: address of RPC task that manages the state of an RPC request
++ *
++ * Return values:
++ *        0:	The request has been sent
++ *   EAGAIN:	The socket was blocked, please call again later to
++ *		complete the request
++ * ENOTCONN:	Caller needs to invoke connect logic then call again
++ *    other:	Some other error occured, the request was not sent
++ */
++static int xs_udp_send_request(struct rpc_task *task)
++{
++	struct rpc_rqst *req = task->tk_rqstp;
++	struct rpc_xprt *xprt = req->rq_xprt;
++	struct xdr_buf *xdr = &req->rq_snd_buf;
++	int status;
+ 
+ 	xs_pktdump("packet data:",
+ 				req->rq_svec->iov_base,
+ 				req->rq_svec->iov_len);
+ 
+-	/* For UDP, we need to provide an address */
+-	if (!xprt->stream) {
+-		addr = (struct sockaddr *) &xprt->addr;
+-		addrlen = sizeof(xprt->addr);
+-	}
+-	/* Don't repeat bytes */
+-	skip = req->rq_bytes_sent;
++	req->rq_xtime = jiffies;
++	status = xs_sendpages(xprt->sock, (struct sockaddr *) &xprt->addr,
++				sizeof(xprt->addr), xdr, req->rq_bytes_sent);
+ 
+-	clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
+-	result = xs_sendpages(sock, addr, addrlen, xdr, skip);
++	dprintk("RPC:      xs_udp_send_request(%u) = %d\n",
++			xdr->len - req->rq_bytes_sent, status);
+ 
+-	dprintk("RPC:      xs_sendmsg(%d) = %d\n", xdr->len - skip, result);
++	if (likely(status >= (int) req->rq_slen))
++		return 0;
+ 
+-	if (result >= 0)
+-		return result;
++	/* Still some bytes left; set up for a retry later. */
++	if (status > 0)
++		status = -EAGAIN;
+ 
+-	switch (result) {
++	switch (status) {
++	case -ENETUNREACH:
++	case -EPIPE:
+ 	case -ECONNREFUSED:
+ 		/* When the server has died, an ICMP port unreachable message
+ 		 * prompts ECONNREFUSED. */
+-	case -EAGAIN:
+ 		break;
+-	case -ECONNRESET:
+-	case -ENOTCONN:
+-	case -EPIPE:
+-		/* connection broken */
+-		if (xprt->stream)
+-			result = -ENOTCONN;
++	case -EAGAIN:
++		xs_nospace(task);
+ 		break;
+ 	default:
++		dprintk("RPC:      sendmsg returned unrecognized error %d\n",
++			-status);
+ 		break;
+ 	}
+-	return result;
++
++	return status;
+ }
+ 
+ /**
+- * xs_send_request - write an RPC request to a socket
++ * xs_tcp_send_request - write an RPC request to a TCP socket
+  * @task: address of RPC task that manages the state of an RPC request
+  *
+  * Return values:
+- *      0:  The request has been sent
+- * EAGAIN:  The socket was blocked, please call again later to
+- *          complete the request
+- *  other:  Some other error occured, the request was not sent
++ *        0:	The request has been sent
++ *   EAGAIN:	The socket was blocked, please call again later to
++ *		complete the request
++ * ENOTCONN:	Caller needs to invoke connect logic then call again
++ *    other:	Some other error occured, the request was not sent
+  *
+  * XXX: In the case of soft timeouts, should we eventually give up
+- *      if the socket is not able to make progress?
++ *	if sendmsg is not able to make progress?
+  */
+-static int xs_send_request(struct rpc_task *task)
++static int xs_tcp_send_request(struct rpc_task *task)
+ {
+ 	struct rpc_rqst *req = task->tk_rqstp;
+ 	struct rpc_xprt *xprt = req->rq_xprt;
++	struct xdr_buf *xdr = &req->rq_snd_buf;
++	u32 *marker = req->rq_svec[0].iov_base;
+ 	int status, retry = 0;
+ 
+-	/* set up everything as needed. */
+ 	/* Write the record marker */
+-	if (xprt->stream) {
+-		u32 *marker = req->rq_svec[0].iov_base;
++	*marker = htonl(0x80000000|(req->rq_slen-sizeof(*marker)));
+ 
+-		*marker = htonl(0x80000000|(req->rq_slen-sizeof(*marker)));
+-	}
++	xs_pktdump("packet data:",
++				req->rq_svec->iov_base,
++				req->rq_svec->iov_len);
+ 
+ 	/* Continue transmitting the packet/record. We must be careful
+ 	 * to cope with writespace callbacks arriving _after_ we have
+-	 * called sendmsg().
+-	 */
++	 * called sendmsg(). */
+ 	while (1) {
+ 		req->rq_xtime = jiffies;
+-		status = xs_sendmsg(xprt, req);
++		status = xs_sendpages(xprt->sock, NULL, 0, xdr,
++						req->rq_bytes_sent);
+ 
+-		if (status < 0)
+-			break;
++		dprintk("RPC:      xs_tcp_send_request(%u) = %d\n",
++				xdr->len - req->rq_bytes_sent, status);
+ 
+-		if (xprt->stream) {
+-			req->rq_bytes_sent += status;
+-
+-			/* If we've sent the entire packet, immediately
+-			 * reset the count of bytes sent. */
+-			if (req->rq_bytes_sent >= req->rq_slen) {
+-				req->rq_bytes_sent = 0;
+-				return 0;
+-			}
+-		} else {
+-			if (status >= req->rq_slen)
+-				return 0;
+-			status = -EAGAIN;
++		if (unlikely(status < 0))
+ 			break;
+-		}
+ 
+-		dprintk("RPC: %4d xmit incomplete (%d left of %d)\n",
+-				task->tk_pid, req->rq_slen - req->rq_bytes_sent,
+-				req->rq_slen);
++		/* If we've sent the entire packet, immediately
++		 * reset the count of bytes sent. */
++		req->rq_bytes_sent += status;
++		if (likely(req->rq_bytes_sent >= req->rq_slen)) {
++			req->rq_bytes_sent = 0;
++			return 0;
++		}
+ 
+ 		status = -EAGAIN;
+-		if (retry++ > 50)
++		if (retry++ > XS_SENDMSG_RETRY)
+ 			break;
+ 	}
+ 
+-	if (status == -EAGAIN) {
+-		if (test_bit(SOCK_ASYNC_NOSPACE, &xprt->sock->flags)) {
+-			/* Protect against races with write_space */
+-			spin_lock_bh(&xprt->transport_lock);
+-			/* Don't race with disconnect */
+-			if (!xprt_connected(xprt))
+-				task->tk_status = -ENOTCONN;
+-			else if (test_bit(SOCK_NOSPACE, &xprt->sock->flags))
+-				xprt_wait_for_buffer_space(task);
+-			spin_unlock_bh(&xprt->transport_lock);
+-			return status;
+-		}
+-		/* Keep holding the socket if it is blocked */
+-		rpc_delay(task, HZ>>4);
++	switch (status) {
++	case -EAGAIN:
++		xs_nospace(task);
++		break;
++	case -ECONNREFUSED:
++	case -ECONNRESET:
++	case -ENOTCONN:
++	case -EPIPE:
++		status = -ENOTCONN;
++		break;
++	default:
++		dprintk("RPC:      sendmsg returned unrecognized error %d\n",
++			-status);
++		break;
+ 	}
++
+ 	return status;
+ }
+ 
+@@ -992,10 +1025,18 @@ static void xs_connect(struct rpc_task *task)
+ 	}
+ }
+ 
+-static struct rpc_xprt_ops xs_ops = {
++static struct rpc_xprt_ops xs_udp_ops = {
++	.set_buffer_size	= xs_set_buffer_size,
++	.connect		= xs_connect,
++	.send_request		= xs_udp_send_request,
++	.close			= xs_close,
++	.destroy		= xs_destroy,
++};
++
++static struct rpc_xprt_ops xs_tcp_ops = {
+ 	.set_buffer_size	= xs_set_buffer_size,
+ 	.connect		= xs_connect,
+-	.send_request		= xs_send_request,
++	.send_request		= xs_tcp_send_request,
+ 	.close			= xs_close,
+ 	.destroy		= xs_destroy,
+ };
+@@ -1033,7 +1074,7 @@ int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to)
+ 
+ 	INIT_WORK(&xprt->connect_worker, xs_udp_connect_worker, xprt);
+ 
+-	xprt->ops = &xs_ops;
++	xprt->ops = &xs_udp_ops;
+ 
+ 	if (to)
+ 		xprt->timeout = *to;
+@@ -1072,7 +1113,7 @@ int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to)
+ 
+ 	INIT_WORK(&xprt->connect_worker, xs_tcp_connect_worker, xprt);
+ 
+-	xprt->ops = &xs_ops;
++	xprt->ops = &xs_tcp_ops;
+ 
+ 	if (to)
+ 		xprt->timeout = *to;

commit b0d93ad511ce2f37823a07c7a3258117a431f5fb
+Author: Chuck Lever 
+Date:   Thu Aug 11 16:25:53 2005 -0400
+
+    [PATCH] RPC: separate TCP and UDP transport connection logic
+    
+     Create separate connection worker functions for managing UDP and TCP
+     transport sockets.  This eliminates several dependencies on "xprt->stream".
+    
+     Test-plan:
+     Destructive testing (unplugging the network temporarily).  Connectathon with
+     v2, v3, and v4.
+    
+     Version: Thu, 11 Aug 2005 16:08:18 -0400
+    
+     Signed-off-by: Chuck Lever 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
+index 70a772d7a796..f91529787b9b 100644
+--- a/net/sunrpc/xprtsock.c
++++ b/net/sunrpc/xprtsock.c
+@@ -836,102 +836,118 @@ static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
+ 	return err;
+ }
+ 
+-static struct socket *xs_create(struct rpc_xprt *xprt, int proto, int resvport)
++/**
++ * xs_udp_connect_worker - set up a UDP socket
++ * @args: RPC transport to connect
++ *
++ * Invoked by a work queue tasklet.
++ */
++static void xs_udp_connect_worker(void *args)
+ {
+-	struct socket *sock;
+-	int type, err;
+-
+-	dprintk("RPC:      xs_create(%s %d)\n",
+-			   (proto == IPPROTO_UDP)? "udp" : "tcp", proto);
++	struct rpc_xprt *xprt = (struct rpc_xprt *) args;
++	struct socket *sock = xprt->sock;
++	int err, status = -EIO;
+ 
+-	type = (proto == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
++	if (xprt->shutdown || xprt->addr.sin_port == 0)
++		goto out;
+ 
+-	if ((err = sock_create_kern(PF_INET, type, proto, &sock)) < 0) {
+-		dprintk("RPC:      can't create socket (%d).\n", -err);
+-		return NULL;
+-	}
++	dprintk("RPC:      xs_udp_connect_worker for xprt %p\n", xprt);
+ 
+-	/* If the caller has the capability, bind to a reserved port */
+-	if (resvport && xs_bindresvport(xprt, sock) < 0)
+-		goto failed;
++	/* Start by resetting any existing state */
++	xs_close(xprt);
+ 
+-	return sock;
++	if ((err = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock)) < 0) {
++		dprintk("RPC:      can't create UDP transport socket (%d).\n", -err);
++		goto out;
++	}
+ 
+-failed:
+-	sock_release(sock);
+-	return NULL;
+-}
++	if (xprt->resvport && xs_bindresvport(xprt, sock) < 0) {
++		sock_release(sock);
++		goto out;
++	}
+ 
+-static void xs_bind(struct rpc_xprt *xprt, struct socket *sock)
+-{
+-	struct sock *sk = sock->sk;
++	if (!xprt->inet) {
++		struct sock *sk = sock->sk;
+ 
+-	if (xprt->inet)
+-		return;
++		write_lock_bh(&sk->sk_callback_lock);
+ 
+-	write_lock_bh(&sk->sk_callback_lock);
+-	sk->sk_user_data = xprt;
+-	xprt->old_data_ready = sk->sk_data_ready;
+-	xprt->old_state_change = sk->sk_state_change;
+-	xprt->old_write_space = sk->sk_write_space;
+-	if (xprt->prot == IPPROTO_UDP) {
++		sk->sk_user_data = xprt;
++		xprt->old_data_ready = sk->sk_data_ready;
++		xprt->old_state_change = sk->sk_state_change;
++		xprt->old_write_space = sk->sk_write_space;
+ 		sk->sk_data_ready = xs_udp_data_ready;
+ 		sk->sk_write_space = xs_udp_write_space;
+ 		sk->sk_no_check = UDP_CSUM_NORCV;
++
+ 		xprt_set_connected(xprt);
+-	} else {
+-		tcp_sk(sk)->nonagle = 1;	/* disable Nagle's algorithm */
+-		sk->sk_data_ready = xs_tcp_data_ready;
+-		sk->sk_state_change = xs_tcp_state_change;
+-		sk->sk_write_space = xs_tcp_write_space;
+-		xprt_clear_connected(xprt);
+-	}
+ 
+-	/* Reset to new socket */
+-	xprt->sock = sock;
+-	xprt->inet = sk;
+-	write_unlock_bh(&sk->sk_callback_lock);
++		/* Reset to new socket */
++		xprt->sock = sock;
++		xprt->inet = sk;
+ 
+-	return;
++		write_unlock_bh(&sk->sk_callback_lock);
++	}
++	xs_set_buffer_size(xprt);
++	status = 0;
++out:
++	xprt_wake_pending_tasks(xprt, status);
++	xprt_clear_connecting(xprt);
+ }
+ 
+ /**
+- * xs_connect_worker - try to connect a socket to a remote endpoint
++ * xs_tcp_connect_worker - connect a TCP socket to a remote endpoint
+  * @args: RPC transport to connect
+  *
+  * Invoked by a work queue tasklet.
+  */
+-static void xs_connect_worker(void *args)
++static void xs_tcp_connect_worker(void *args)
+ {
+ 	struct rpc_xprt *xprt = (struct rpc_xprt *)args;
+ 	struct socket *sock = xprt->sock;
+-	int status = -EIO;
++	int err, status = -EIO;
+ 
+ 	if (xprt->shutdown || xprt->addr.sin_port == 0)
+ 		goto out;
+ 
+-	dprintk("RPC:      xs_connect_worker xprt %p\n", xprt);
++	dprintk("RPC:      xs_tcp_connect_worker for xprt %p\n", xprt);
+ 
+-	/*
+-	 * Start by resetting any existing state
+-	 */
++	/* Start by resetting any existing socket state */
+ 	xs_close(xprt);
+-	sock = xs_create(xprt, xprt->prot, xprt->resvport);
+-	if (sock == NULL) {
+-		/* couldn't create socket or bind to reserved port;
+-		 * this is likely a permanent error, so cause an abort */
++
++	if ((err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) {
++		dprintk("RPC:      can't create TCP transport socket (%d).\n", -err);
+ 		goto out;
+ 	}
+-	xs_bind(xprt, sock);
+-	xs_set_buffer_size(xprt);
+ 
+-	status = 0;
+-	if (!xprt->stream)
++	if (xprt->resvport && xs_bindresvport(xprt, sock) < 0) {
++		sock_release(sock);
+ 		goto out;
++	}
+ 
+-	/*
+-	 * Tell the socket layer to start connecting...
+-	 */
++	if (!xprt->inet) {
++		struct sock *sk = sock->sk;
++
++		write_lock_bh(&sk->sk_callback_lock);
++
++		sk->sk_user_data = xprt;
++		xprt->old_data_ready = sk->sk_data_ready;
++		xprt->old_state_change = sk->sk_state_change;
++		xprt->old_write_space = sk->sk_write_space;
++		sk->sk_data_ready = xs_tcp_data_ready;
++		sk->sk_state_change = xs_tcp_state_change;
++		sk->sk_write_space = xs_tcp_write_space;
++		tcp_sk(sk)->nonagle = 1;
++
++		xprt_clear_connected(xprt);
++
++		/* Reset to new socket */
++		xprt->sock = sock;
++		xprt->inet = sk;
++
++		write_unlock_bh(&sk->sk_callback_lock);
++	}
++
++	/* Tell the socket layer to start connecting... */
+ 	status = sock->ops->connect(sock, (struct sockaddr *) &xprt->addr,
+ 			sizeof(xprt->addr), O_NONBLOCK);
+ 	dprintk("RPC: %p  connect status %d connected %d sock state %d\n",
+@@ -959,18 +975,20 @@ static void xs_connect(struct rpc_task *task)
+ {
+ 	struct rpc_xprt *xprt = task->tk_xprt;
+ 
+-	if (!xprt_test_and_set_connecting(xprt)) {
+-		if (xprt->sock != NULL) {
+-			dprintk("RPC:      xs_connect delayed xprt %p\n", xprt);
+-			schedule_delayed_work(&xprt->connect_worker,
++	if (xprt_test_and_set_connecting(xprt))
++		return;
++
++	if (xprt->sock != NULL) {
++		dprintk("RPC:      xs_connect delayed xprt %p\n", xprt);
++		schedule_delayed_work(&xprt->connect_worker,
+ 					RPC_REESTABLISH_TIMEOUT);
+-		} else {
+-			dprintk("RPC:      xs_connect scheduled xprt %p\n", xprt);
+-			schedule_work(&xprt->connect_worker);
+-			/* flush_scheduled_work can sleep... */
+-			if (!RPC_IS_ASYNC(task))
+-				flush_scheduled_work();
+-		}
++	} else {
++		dprintk("RPC:      xs_connect scheduled xprt %p\n", xprt);
++		schedule_work(&xprt->connect_worker);
++
++		/* flush_scheduled_work can sleep... */
++		if (!RPC_IS_ASYNC(task))
++			flush_scheduled_work();
+ 	}
+ }
+ 
+@@ -1013,7 +1031,7 @@ int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to)
+ 	/* XXX: header size can vary due to auth type, IPv6, etc. */
+ 	xprt->max_payload = (1U << 16) - (MAX_HEADER << 3);
+ 
+-	INIT_WORK(&xprt->connect_worker, xs_connect_worker, xprt);
++	INIT_WORK(&xprt->connect_worker, xs_udp_connect_worker, xprt);
+ 
+ 	xprt->ops = &xs_ops;
+ 
+@@ -1052,7 +1070,7 @@ int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to)
+ 	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
+ 	xprt->max_payload = (1U << 31) - 1;
+ 
+-	INIT_WORK(&xprt->connect_worker, xs_connect_worker, xprt);
++	INIT_WORK(&xprt->connect_worker, xs_tcp_connect_worker, xprt);
+ 
+ 	xprt->ops = &xs_ops;
+ 

commit c7b2cae8a634015b72941ba2fc6c4bc9b8d3a129
+Author: Chuck Lever 
+Date:   Thu Aug 11 16:25:50 2005 -0400
+
+    [PATCH] RPC: separate TCP and UDP write space callbacks
+    
+     Split the socket write space callback function into a TCP version and UDP
+     version, eliminating one dependence on the "xprt->stream" variable.
+    
+     Keep the common pieces of this path in xprt.c so other transports can use
+     it too.
+    
+     Test-plan:
+     Write-intensive workload on a single mount point.
+    
+     Version: Thu, 11 Aug 2005 16:07:51 -0400
+    
+     Signed-off-by: Chuck Lever 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
+index bfbc492ae36d..e73174c7e450 100644
+--- a/include/linux/sunrpc/xprt.h
++++ b/include/linux/sunrpc/xprt.h
+@@ -240,6 +240,8 @@ int			xprt_destroy(struct rpc_xprt *xprt);
+  * Transport switch helper functions
+  */
+ void			xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status);
++void			xprt_wait_for_buffer_space(struct rpc_task *task);
++void			xprt_write_space(struct rpc_xprt *xprt);
+ struct rpc_rqst *	xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid);
+ void			xprt_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied);
+ void			xprt_disconnect(struct rpc_xprt *xprt);
+diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
+index 247fa1ec870c..31ef7dc7eed6 100644
+--- a/net/sunrpc/xprt.c
++++ b/net/sunrpc/xprt.c
+@@ -241,6 +241,40 @@ void xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status)
+ 		rpc_wake_up(&xprt->pending);
+ }
+ 
++/**
++ * xprt_wait_for_buffer_space - wait for transport output buffer to clear
++ * @task: task to be put to sleep
++ *
++ */
++void xprt_wait_for_buffer_space(struct rpc_task *task)
++{
++	struct rpc_rqst *req = task->tk_rqstp;
++	struct rpc_xprt *xprt = req->rq_xprt;
++
++	task->tk_timeout = req->rq_timeout;
++	rpc_sleep_on(&xprt->pending, task, NULL, NULL);
++}
++
++/**
++ * xprt_write_space - wake the task waiting for transport output buffer space
++ * @xprt: transport with waiting tasks
++ *
++ * Can be called in a soft IRQ context, so xprt_write_space never sleeps.
++ */
++void xprt_write_space(struct rpc_xprt *xprt)
++{
++	if (unlikely(xprt->shutdown))
++		return;
++
++	spin_lock_bh(&xprt->transport_lock);
++	if (xprt->snd_task) {
++		dprintk("RPC:      write space: waking waiting task on xprt %p\n",
++				xprt);
++		rpc_wake_up_task(xprt->snd_task);
++	}
++	spin_unlock_bh(&xprt->transport_lock);
++}
++
+ static void xprt_reset_majortimeo(struct rpc_rqst *req)
+ {
+ 	struct rpc_timeout *to = &req->rq_xprt->timeout;
+diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
+index 7f0b9f7f167b..70a772d7a796 100644
+--- a/net/sunrpc/xprtsock.c
++++ b/net/sunrpc/xprtsock.c
+@@ -308,15 +308,13 @@ static int xs_send_request(struct rpc_task *task)
+ 
+ 	if (status == -EAGAIN) {
+ 		if (test_bit(SOCK_ASYNC_NOSPACE, &xprt->sock->flags)) {
+-			/* Protect against races with xs_write_space */
++			/* Protect against races with write_space */
+ 			spin_lock_bh(&xprt->transport_lock);
+ 			/* Don't race with disconnect */
+ 			if (!xprt_connected(xprt))
+ 				task->tk_status = -ENOTCONN;
+-			else if (test_bit(SOCK_NOSPACE, &xprt->sock->flags)) {
+-				task->tk_timeout = req->rq_timeout;
+-				rpc_sleep_on(&xprt->pending, task, NULL, NULL);
+-			}
++			else if (test_bit(SOCK_NOSPACE, &xprt->sock->flags))
++				xprt_wait_for_buffer_space(task);
+ 			spin_unlock_bh(&xprt->transport_lock);
+ 			return status;
+ 		}
+@@ -721,45 +719,68 @@ static void xs_tcp_state_change(struct sock *sk)
+ }
+ 
+ /**
+- * xs_write_space - callback invoked when socket buffer space becomes
+- *                         available
++ * xs_udp_write_space - callback invoked when socket buffer space
++ *                             becomes available
+  * @sk: socket whose state has changed
+  *
+  * Called when more output buffer space is available for this socket.
+  * We try not to wake our writers until they can make "significant"
+- * progress, otherwise we'll waste resources thrashing sock_sendmsg
++ * progress, otherwise we'll waste resources thrashing kernel_sendmsg
+  * with a bunch of small requests.
+  */
+-static void xs_write_space(struct sock *sk)
++static void xs_udp_write_space(struct sock *sk)
+ {
+-	struct rpc_xprt *xprt;
+-	struct socket *sock;
+-
+ 	read_lock(&sk->sk_callback_lock);
+-	if (!(xprt = xprt_from_sock(sk)) || !(sock = sk->sk_socket))
+-		goto out;
+-	if (xprt->shutdown)
+-		goto out;
+ 
+-	/* Wait until we have enough socket memory */
+-	if (xprt->stream) {
+-		/* from net/core/stream.c:sk_stream_write_space */
+-		if (sk_stream_wspace(sk) < sk_stream_min_wspace(sk))
++	/* from net/core/sock.c:sock_def_write_space */
++	if (sock_writeable(sk)) {
++		struct socket *sock;
++		struct rpc_xprt *xprt;
++
++		if (unlikely(!(sock = sk->sk_socket)))
+ 			goto out;
+-	} else {
+-		/* from net/core/sock.c:sock_def_write_space */
+-		if (!sock_writeable(sk))
++		if (unlikely(!(xprt = xprt_from_sock(sk))))
++			goto out;
++		if (unlikely(!test_and_clear_bit(SOCK_NOSPACE, &sock->flags)))
+ 			goto out;
++
++		xprt_write_space(xprt);
+ 	}
+ 
+-	if (!test_and_clear_bit(SOCK_NOSPACE, &sock->flags))
+-		goto out;
++ out:
++	read_unlock(&sk->sk_callback_lock);
++}
+ 
+-	spin_lock_bh(&xprt->transport_lock);
+-	if (xprt->snd_task)
+-		rpc_wake_up_task(xprt->snd_task);
+-	spin_unlock_bh(&xprt->transport_lock);
+-out:
++/**
++ * xs_tcp_write_space - callback invoked when socket buffer space
++ *                             becomes available
++ * @sk: socket whose state has changed
++ *
++ * Called when more output buffer space is available for this socket.
++ * We try not to wake our writers until they can make "significant"
++ * progress, otherwise we'll waste resources thrashing kernel_sendmsg
++ * with a bunch of small requests.
++ */
++static void xs_tcp_write_space(struct sock *sk)
++{
++	read_lock(&sk->sk_callback_lock);
++
++	/* from net/core/stream.c:sk_stream_write_space */
++	if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) {
++		struct socket *sock;
++		struct rpc_xprt *xprt;
++
++		if (unlikely(!(sock = sk->sk_socket)))
++			goto out;
++		if (unlikely(!(xprt = xprt_from_sock(sk))))
++			goto out;
++		if (unlikely(!test_and_clear_bit(SOCK_NOSPACE, &sock->flags)))
++			goto out;
++
++		xprt_write_space(xprt);
++	}
++
++ out:
+ 	read_unlock(&sk->sk_callback_lock);
+ }
+ 
+@@ -855,15 +876,16 @@ static void xs_bind(struct rpc_xprt *xprt, struct socket *sock)
+ 	xprt->old_write_space = sk->sk_write_space;
+ 	if (xprt->prot == IPPROTO_UDP) {
+ 		sk->sk_data_ready = xs_udp_data_ready;
++		sk->sk_write_space = xs_udp_write_space;
+ 		sk->sk_no_check = UDP_CSUM_NORCV;
+ 		xprt_set_connected(xprt);
+ 	} else {
+ 		tcp_sk(sk)->nonagle = 1;	/* disable Nagle's algorithm */
+ 		sk->sk_data_ready = xs_tcp_data_ready;
+ 		sk->sk_state_change = xs_tcp_state_change;
++		sk->sk_write_space = xs_tcp_write_space;
+ 		xprt_clear_connected(xprt);
+ 	}
+-	sk->sk_write_space = xs_write_space;
+ 
+ 	/* Reset to new socket */
+ 	xprt->sock = sock;

commit 55aa4f58aa43dc9a51fb80010630d94b96053a2e
+Author: Chuck Lever 
+Date:   Thu Aug 11 16:25:47 2005 -0400
+
+    [PATCH] RPC: client-side transport switch cleanup
+    
+     Clean-up: change some comments to reflect the realities of the new RPC
+     transport switch mechanism.  Get rid of unused xprt_receive() prototype.
+    
+     Also, organize function prototypes in xprt.h by usage and scope.
+    
+     Test-plan:
+     Compile kernel with CONFIG_NFS enabled.
+    
+     Version: Thu, 11 Aug 2005 16:07:21 -0400
+    
+     Signed-off-by: Chuck Lever 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
+index d5223993fca9..bfbc492ae36d 100644
+--- a/include/linux/sunrpc/xprt.h
++++ b/include/linux/sunrpc/xprt.h
+@@ -1,5 +1,5 @@
+ /*
+- *  linux/include/linux/sunrpc/clnt_xprt.h
++ *  linux/include/linux/sunrpc/xprt.h
+  *
+  *  Declarations for the RPC transport interface.
+  *
+@@ -150,8 +150,8 @@ struct rpc_xprt {
+ 	unsigned long		cong;		/* current congestion */
+ 	unsigned long		cwnd;		/* congestion window */
+ 
+-	unsigned int		rcvsize,	/* socket receive buffer size */
+-				sndsize;	/* socket send buffer size */
++	unsigned int		rcvsize,	/* transport rcv buffer size */
++				sndsize;	/* transport send buffer size */
+ 
+ 	size_t			max_payload;	/* largest RPC payload size,
+ 						   in bytes */
+@@ -184,12 +184,12 @@ struct rpc_xprt {
+ 	unsigned long		tcp_copied,	/* copied to request */
+ 				tcp_flags;
+ 	/*
+-	 * Connection of sockets
++	 * Connection of transports
+ 	 */
+-	struct work_struct	sock_connect;
++	struct work_struct	connect_worker;
+ 	unsigned short		port;
+ 	/*
+-	 * Disconnection of idle sockets
++	 * Disconnection of idle transports
+ 	 */
+ 	struct work_struct	task_cleanup;
+ 	struct timer_list	timer;
+@@ -219,27 +219,36 @@ struct rpc_xprt {
+ 
+ #ifdef __KERNEL__
+ 
+-struct rpc_xprt *	xprt_create_proto(int proto, struct sockaddr_in *addr,
+-					struct rpc_timeout *toparms);
+-void			xprt_disconnect(struct rpc_xprt *);
+-int			xprt_destroy(struct rpc_xprt *);
+-void			xprt_set_timeout(struct rpc_timeout *, unsigned int,
+-					unsigned long);
+-struct rpc_rqst *	xprt_lookup_rqst(struct rpc_xprt *, u32);
+-void			xprt_complete_rqst(struct rpc_xprt *,
+-					struct rpc_rqst *, int);
+-void			xprt_reserve(struct rpc_task *);
+-int			xprt_prepare_transmit(struct rpc_task *);
+-void			xprt_transmit(struct rpc_task *);
+-void			xprt_receive(struct rpc_task *);
+-void			xprt_wake_pending_tasks(struct rpc_xprt *, int);
++/*
++ * Transport operations used by ULPs
++ */
++struct rpc_xprt *	xprt_create_proto(int proto, struct sockaddr_in *addr, struct rpc_timeout *to);
++void			xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr);
++
++/*
++ * Generic internal transport functions
++ */
++void			xprt_connect(struct rpc_task *task);
++void			xprt_reserve(struct rpc_task *task);
++int			xprt_prepare_transmit(struct rpc_task *task);
++void			xprt_transmit(struct rpc_task *task);
+ int			xprt_adjust_timeout(struct rpc_rqst *req);
+-void			xprt_release(struct rpc_task *);
+-void			xprt_connect(struct rpc_task *);
+-int			xs_setup_udp(struct rpc_xprt *,
+-					struct rpc_timeout *);
+-int			xs_setup_tcp(struct rpc_xprt *,
+-					struct rpc_timeout *);
++void			xprt_release(struct rpc_task *task);
++int			xprt_destroy(struct rpc_xprt *xprt);
++
++/*
++ * Transport switch helper functions
++ */
++void			xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status);
++struct rpc_rqst *	xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid);
++void			xprt_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied);
++void			xprt_disconnect(struct rpc_xprt *xprt);
++
++/*
++ * Socket transport setup operations
++ */
++int			xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to);
++int			xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to);
+ 
+ /*
+  * Reserved bit positions in xprt->state
+diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
+index 0d1b010a4a01..4677959d2834 100644
+--- a/net/sunrpc/clnt.c
++++ b/net/sunrpc/clnt.c
+@@ -1,5 +1,5 @@
+ /*
+- *  linux/net/sunrpc/rpcclnt.c
++ *  linux/net/sunrpc/clnt.c
+  *
+  *  This file contains the high-level RPC interface.
+  *  It is modeled as a finite state machine to support both synchronous
+diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
+index 2f9cd468b953..247fa1ec870c 100644
+--- a/net/sunrpc/xprt.c
++++ b/net/sunrpc/xprt.c
+@@ -10,12 +10,12 @@
+  *	one is available. Otherwise, it sleeps on the backlog queue
+  *	(xprt_reserve).
+  *  -	Next, the caller puts together the RPC message, stuffs it into
+- *	the request struct, and calls xprt_call().
+- *  -	xprt_call transmits the message and installs the caller on the
+- *	socket's wait list. At the same time, it installs a timer that
++ *	the request struct, and calls xprt_transmit().
++ *  -	xprt_transmit sends the message and installs the caller on the
++ *	transport's wait list. At the same time, it installs a timer that
+  *	is run after the packet's timeout has expired.
+  *  -	When a packet arrives, the data_ready handler walks the list of
+- *	pending requests for that socket. If a matching XID is found, the
++ *	pending requests for that transport. If a matching XID is found, the
+  *	caller is woken up, and the timer removed.
+  *  -	When no reply arrives within the timeout interval, the timer is
+  *	fired by the kernel and runs xprt_timer(). It either adjusts the
+@@ -32,6 +32,8 @@
+  *  tasks that rely on callbacks.
+  *
+  *  Copyright (C) 1995-1997, Olaf Kirch 
++ *
++ *  Transport switch API copyright (C) 2005, Chuck Lever 
+  */
+ 
+ #include 
+@@ -52,8 +54,6 @@
+ # define RPCDBG_FACILITY	RPCDBG_XPRT
+ #endif
+ 
+-#define XPRT_MAX_BACKOFF	(8)
+-
+ /*
+  * Local functions
+  */
+@@ -65,9 +65,9 @@ static int      __xprt_get_cong(struct rpc_xprt *, struct rpc_task *);
+ static int	xprt_clear_backlog(struct rpc_xprt *xprt);
+ 
+ /*
+- * Serialize write access to sockets, in order to prevent different
++ * Serialize write access to transports, in order to prevent different
+  * requests from interfering with each other.
+- * Also prevents TCP socket connects from colliding with writes.
++ * Also prevents transport connects from colliding with writes.
+  */
+ static int
+ __xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
+@@ -91,7 +91,7 @@ __xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
+ 	clear_bit(XPRT_LOCKED, &xprt->state);
+ 	smp_mb__after_clear_bit();
+ out_sleep:
+-	dprintk("RPC: %4d failed to lock socket %p\n", task->tk_pid, xprt);
++	dprintk("RPC: %4d failed to lock transport %p\n", task->tk_pid, xprt);
+ 	task->tk_timeout = 0;
+ 	task->tk_status = -EAGAIN;
+ 	if (req && req->rq_ntrans)
+@@ -144,7 +144,7 @@ __xprt_lock_write_next(struct rpc_xprt *xprt)
+ }
+ 
+ /*
+- * Releases the socket for use by other requests.
++ * Releases the transport for use by other requests.
+  */
+ static void
+ __xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task)
+@@ -294,8 +294,7 @@ int xprt_adjust_timeout(struct rpc_rqst *req)
+ 	return status;
+ }
+ 
+-static void
+-xprt_socket_autoclose(void *args)
++static void xprt_autoclose(void *args)
+ {
+ 	struct rpc_xprt *xprt = (struct rpc_xprt *)args;
+ 
+@@ -329,7 +328,6 @@ xprt_init_autodisconnect(unsigned long data)
+ 	if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
+ 		goto out_abort;
+ 	spin_unlock(&xprt->transport_lock);
+-	/* Let keventd close the socket */
+ 	if (xprt_connecting(xprt))
+ 		xprt_release_write(xprt, NULL);
+ 	else
+@@ -770,7 +768,7 @@ static struct rpc_xprt *xprt_setup(int proto, struct sockaddr_in *ap, struct rpc
+ 
+ 	INIT_LIST_HEAD(&xprt->free);
+ 	INIT_LIST_HEAD(&xprt->recv);
+-	INIT_WORK(&xprt->task_cleanup, xprt_socket_autoclose, xprt);
++	INIT_WORK(&xprt->task_cleanup, xprt_autoclose, xprt);
+ 	init_timer(&xprt->timer);
+ 	xprt->timer.function = xprt_init_autodisconnect;
+ 	xprt->timer.data = (unsigned long) xprt;
+diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
+index 182da2edf61c..7f0b9f7f167b 100644
+--- a/net/sunrpc/xprtsock.c
++++ b/net/sunrpc/xprtsock.c
+@@ -11,6 +11,8 @@
+  * Rewrite of larges part of the code in order to stabilize TCP stuff.
+  * Fix behaviour when socket buffer is full.
+  *  (C) 1999 Trond Myklebust 
++ *
++ * IP socket transport implementation, (C) 2005 Chuck Lever 
+  */
+ 
+ #include 
+@@ -363,7 +365,7 @@ static void xs_destroy(struct rpc_xprt *xprt)
+ {
+ 	dprintk("RPC:      xs_destroy xprt %p\n", xprt);
+ 
+-	cancel_delayed_work(&xprt->sock_connect);
++	cancel_delayed_work(&xprt->connect_worker);
+ 	flush_scheduled_work();
+ 
+ 	xprt_disconnect(xprt);
+@@ -938,11 +940,11 @@ static void xs_connect(struct rpc_task *task)
+ 	if (!xprt_test_and_set_connecting(xprt)) {
+ 		if (xprt->sock != NULL) {
+ 			dprintk("RPC:      xs_connect delayed xprt %p\n", xprt);
+-			schedule_delayed_work(&xprt->sock_connect,
++			schedule_delayed_work(&xprt->connect_worker,
+ 					RPC_REESTABLISH_TIMEOUT);
+ 		} else {
+ 			dprintk("RPC:      xs_connect scheduled xprt %p\n", xprt);
+-			schedule_work(&xprt->sock_connect);
++			schedule_work(&xprt->connect_worker);
+ 			/* flush_scheduled_work can sleep... */
+ 			if (!RPC_IS_ASYNC(task))
+ 				flush_scheduled_work();
+@@ -989,7 +991,7 @@ int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to)
+ 	/* XXX: header size can vary due to auth type, IPv6, etc. */
+ 	xprt->max_payload = (1U << 16) - (MAX_HEADER << 3);
+ 
+-	INIT_WORK(&xprt->sock_connect, xs_connect_worker, xprt);
++	INIT_WORK(&xprt->connect_worker, xs_connect_worker, xprt);
+ 
+ 	xprt->ops = &xs_ops;
+ 
+@@ -1028,7 +1030,7 @@ int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to)
+ 	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
+ 	xprt->max_payload = (1U << 31) - 1;
+ 
+-	INIT_WORK(&xprt->sock_connect, xs_connect_worker, xprt);
++	INIT_WORK(&xprt->connect_worker, xs_connect_worker, xprt);
+ 
+ 	xprt->ops = &xs_ops;
+ 

commit 44fbac2288dfed6f1963ac00bf922c3bcd779cd1
+Author: Chuck Lever 
+Date:   Thu Aug 11 16:25:44 2005 -0400
+
+    [PATCH] RPC: Add helper for waking tasks pending on a transport
+    
+     Clean-up: remove only reference to xprt->pending from the socket transport
+     implementation.  This makes a cleaner interface for other transport
+     implementations as well.
+    
+     Test-plan:
+     Compile kernel with CONFIG_NFS enabled.
+    
+     Version: Thu, 11 Aug 2005 16:06:52 -0400
+    
+     Signed-off-by: Chuck Lever 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
+index 009a3bb4f997..d5223993fca9 100644
+--- a/include/linux/sunrpc/xprt.h
++++ b/include/linux/sunrpc/xprt.h
+@@ -232,6 +232,7 @@ void			xprt_reserve(struct rpc_task *);
+ int			xprt_prepare_transmit(struct rpc_task *);
+ void			xprt_transmit(struct rpc_task *);
+ void			xprt_receive(struct rpc_task *);
++void			xprt_wake_pending_tasks(struct rpc_xprt *, int);
+ int			xprt_adjust_timeout(struct rpc_rqst *req);
+ void			xprt_release(struct rpc_task *);
+ void			xprt_connect(struct rpc_task *);
+diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
+index 57c5e77b155e..2f9cd468b953 100644
+--- a/net/sunrpc/xprt.c
++++ b/net/sunrpc/xprt.c
+@@ -227,6 +227,20 @@ xprt_adjust_cwnd(struct rpc_xprt *xprt, int result)
+ 	xprt->cwnd = cwnd;
+ }
+ 
++/**
++ * xprt_wake_pending_tasks - wake all tasks on a transport's pending queue
++ * @xprt: transport with waiting tasks
++ * @status: result code to plant in each task before waking it
++ *
++ */
++void xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status)
++{
++	if (status < 0)
++		rpc_wake_up_status(&xprt->pending, status);
++	else
++		rpc_wake_up(&xprt->pending);
++}
++
+ static void xprt_reset_majortimeo(struct rpc_rqst *req)
+ {
+ 	struct rpc_timeout *to = &req->rq_xprt->timeout;
+@@ -300,7 +314,7 @@ void xprt_disconnect(struct rpc_xprt *xprt)
+ 	dprintk("RPC:      disconnected transport %p\n", xprt);
+ 	spin_lock_bh(&xprt->transport_lock);
+ 	xprt_clear_connected(xprt);
+-	rpc_wake_up_status(&xprt->pending, -ENOTCONN);
++	xprt_wake_pending_tasks(xprt, -ENOTCONN);
+ 	spin_unlock_bh(&xprt->transport_lock);
+ }
+ 
+@@ -803,7 +817,7 @@ static void xprt_shutdown(struct rpc_xprt *xprt)
+ 	xprt->shutdown = 1;
+ 	rpc_wake_up(&xprt->sending);
+ 	rpc_wake_up(&xprt->resend);
+-	rpc_wake_up(&xprt->pending);
++	xprt_wake_pending_tasks(xprt, -EIO);
+ 	rpc_wake_up(&xprt->backlog);
+ 	wake_up(&xprt->cong_wait);
+ 	del_timer_sync(&xprt->timer);
+diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
+index 76a33b54f436..182da2edf61c 100644
+--- a/net/sunrpc/xprtsock.c
++++ b/net/sunrpc/xprtsock.c
+@@ -703,7 +703,7 @@ static void xs_tcp_state_change(struct sock *sk)
+ 			xprt->tcp_reclen = 0;
+ 			xprt->tcp_copied = 0;
+ 			xprt->tcp_flags = XPRT_COPY_RECM | XPRT_COPY_XID;
+-			rpc_wake_up(&xprt->pending);
++			xprt_wake_pending_tasks(xprt, 0);
+ 		}
+ 		spin_unlock_bh(&xprt->transport_lock);
+ 		break;
+@@ -920,10 +920,7 @@ static void xs_connect_worker(void *args)
+ 		}
+ 	}
+ out:
+-	if (status < 0)
+-		rpc_wake_up_status(&xprt->pending, status);
+-	else
+-		rpc_wake_up(&xprt->pending);
++	xprt_wake_pending_tasks(xprt, status);
+ out_clear:
+ 	xprt_clear_connecting(xprt);
+ }

commit 86b9f57dfdf455763d2be73a742a9a88bb664173
+Author: Chuck Lever 
+Date:   Thu Aug 11 16:25:41 2005 -0400
+
+    [PATCH] RPC: Eliminate socket.h includes in RPC client
+    
+     Clean-up: get rid of unnecessary socket.h and in.h includes in the generic
+     parts of the RPC client.
+    
+     Test-plan:
+     Compile kernel with CONFIG_NFS enabled.
+    
+     Version: Thu, 11 Aug 2005 16:06:23 -0400
+    
+     Signed-off-by: Chuck Lever 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
+index 505e2d4b3d62..a415d99c394d 100644
+--- a/net/sunrpc/auth.c
++++ b/net/sunrpc/auth.c
+@@ -11,7 +11,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ #include 
+ #include 
+ 
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index 2f7b867161d2..53a030acdf75 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -42,8 +42,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+-#include 
+ #include 
+ #include 
+ #include 
+diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
+index 606a8a82cafb..462c5b86b073 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
++++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
+@@ -39,7 +39,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ #include 
+ #include 
+ #include 
+diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
+index 9dfb68377d69..58aeaddd8c79 100644
+--- a/net/sunrpc/auth_gss/gss_mech_switch.c
++++ b/net/sunrpc/auth_gss/gss_mech_switch.c
+@@ -35,7 +35,6 @@
+ 
+ #include 
+ #include 
+-#include 
+ #include 
+ #include 
+ #include 
+diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c
+index 9b72d3abf823..f56767aaa927 100644
+--- a/net/sunrpc/auth_null.c
++++ b/net/sunrpc/auth_null.c
+@@ -7,9 +7,7 @@
+  */
+ 
+ #include 
+-#include 
+ #include 
+-#include 
+ #include 
+ #include 
+ #include 
+diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c
+index 4ff297a9b15b..890fb5ea0dcb 100644
+--- a/net/sunrpc/auth_unix.c
++++ b/net/sunrpc/auth_unix.c
+@@ -9,8 +9,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+-#include 
+ #include 
+ #include 
+ 
+diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
+index ab50c3c9e6a8..0d1b010a4a01 100644
+--- a/net/sunrpc/clnt.c
++++ b/net/sunrpc/clnt.c
+@@ -27,7 +27,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ #include 
+ 
+ #include 
+diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
+index ed48ff022d35..2387e7b823ff 100644
+--- a/net/sunrpc/sunrpc_syms.c
++++ b/net/sunrpc/sunrpc_syms.c
+@@ -10,7 +10,6 @@
+ #include 
+ 
+ #include 
+-#include 
+ #include 
+ #include 
+ #include 

commit 2226feb6bcd0e5e117a9be3ea3dd3ffc14f3e41e
+Author: Chuck Lever 
+Date:   Thu Aug 11 16:25:38 2005 -0400
+
+    [PATCH] RPC: rename the sockstate field
+    
+     Clean-up: get rid of a name reference to sockets in the generic parts of the
+     RPC client by renaming the sockstate field in the rpc_xprt structure.
+    
+     Test-plan:
+     Compile kernel with CONFIG_NFS enabled.
+    
+     Version: Thu, 11 Aug 2005 16:05:53 -0400
+    
+     Signed-off-by: Chuck Lever 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
+index 41ce296dded1..009a3bb4f997 100644
+--- a/include/linux/sunrpc/xprt.h
++++ b/include/linux/sunrpc/xprt.h
+@@ -163,7 +163,7 @@ struct rpc_xprt {
+ 	struct list_head	free;		/* free slots */
+ 	struct rpc_rqst *	slot;		/* slot table storage */
+ 	unsigned int		max_reqs;	/* total slots */
+-	unsigned long		sockstate;	/* Socket state */
++	unsigned long		state;		/* transport state */
+ 	unsigned char		shutdown   : 1,	/* being shut down */
+ 				nocong	   : 1,	/* no congestion control */
+ 				resvport   : 1, /* use a reserved port */
+@@ -240,16 +240,54 @@ int			xs_setup_udp(struct rpc_xprt *,
+ int			xs_setup_tcp(struct rpc_xprt *,
+ 					struct rpc_timeout *);
+ 
+-#define XPRT_LOCKED	0
+-#define XPRT_CONNECT	1
+-#define XPRT_CONNECTING	2
+-
+-#define xprt_connected(xp)		(test_bit(XPRT_CONNECT, &(xp)->sockstate))
+-#define xprt_set_connected(xp)		(set_bit(XPRT_CONNECT, &(xp)->sockstate))
+-#define xprt_test_and_set_connected(xp)	(test_and_set_bit(XPRT_CONNECT, &(xp)->sockstate))
+-#define xprt_test_and_clear_connected(xp) \
+-					(test_and_clear_bit(XPRT_CONNECT, &(xp)->sockstate))
+-#define xprt_clear_connected(xp)	(clear_bit(XPRT_CONNECT, &(xp)->sockstate))
++/*
++ * Reserved bit positions in xprt->state
++ */
++#define XPRT_LOCKED		(0)
++#define XPRT_CONNECTED		(1)
++#define XPRT_CONNECTING		(2)
++
++static inline void xprt_set_connected(struct rpc_xprt *xprt)
++{
++	set_bit(XPRT_CONNECTED, &xprt->state);
++}
++
++static inline void xprt_clear_connected(struct rpc_xprt *xprt)
++{
++	clear_bit(XPRT_CONNECTED, &xprt->state);
++}
++
++static inline int xprt_connected(struct rpc_xprt *xprt)
++{
++	return test_bit(XPRT_CONNECTED, &xprt->state);
++}
++
++static inline int xprt_test_and_set_connected(struct rpc_xprt *xprt)
++{
++	return test_and_set_bit(XPRT_CONNECTED, &xprt->state);
++}
++
++static inline int xprt_test_and_clear_connected(struct rpc_xprt *xprt)
++{
++	return test_and_clear_bit(XPRT_CONNECTED, &xprt->state);
++}
++
++static inline void xprt_clear_connecting(struct rpc_xprt *xprt)
++{
++	smp_mb__before_clear_bit();
++	clear_bit(XPRT_CONNECTING, &xprt->state);
++	smp_mb__after_clear_bit();
++}
++
++static inline int xprt_connecting(struct rpc_xprt *xprt)
++{
++	return test_bit(XPRT_CONNECTING, &xprt->state);
++}
++
++static inline int xprt_test_and_set_connecting(struct rpc_xprt *xprt)
++{
++	return test_and_set_bit(XPRT_CONNECTING, &xprt->state);
++}
+ 
+ #endif /* __KERNEL__*/
+ 
+diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
+index 9c45c522e3ef..57c5e77b155e 100644
+--- a/net/sunrpc/xprt.c
++++ b/net/sunrpc/xprt.c
+@@ -74,7 +74,7 @@ __xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
+ {
+ 	struct rpc_rqst *req = task->tk_rqstp;
+ 
+-	if (test_and_set_bit(XPRT_LOCKED, &xprt->sockstate)) {
++	if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) {
+ 		if (task == xprt->snd_task)
+ 			return 1;
+ 		goto out_sleep;
+@@ -88,7 +88,7 @@ __xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
+ 		return 1;
+ 	}
+ 	smp_mb__before_clear_bit();
+-	clear_bit(XPRT_LOCKED, &xprt->sockstate);
++	clear_bit(XPRT_LOCKED, &xprt->state);
+ 	smp_mb__after_clear_bit();
+ out_sleep:
+ 	dprintk("RPC: %4d failed to lock socket %p\n", task->tk_pid, xprt);
+@@ -118,7 +118,7 @@ __xprt_lock_write_next(struct rpc_xprt *xprt)
+ {
+ 	struct rpc_task *task;
+ 
+-	if (test_and_set_bit(XPRT_LOCKED, &xprt->sockstate))
++	if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
+ 		return;
+ 	if (!xprt->nocong && RPCXPRT_CONGESTED(xprt))
+ 		goto out_unlock;
+@@ -139,7 +139,7 @@ __xprt_lock_write_next(struct rpc_xprt *xprt)
+ 	}
+ out_unlock:
+ 	smp_mb__before_clear_bit();
+-	clear_bit(XPRT_LOCKED, &xprt->sockstate);
++	clear_bit(XPRT_LOCKED, &xprt->state);
+ 	smp_mb__after_clear_bit();
+ }
+ 
+@@ -152,7 +152,7 @@ __xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task)
+ 	if (xprt->snd_task == task) {
+ 		xprt->snd_task = NULL;
+ 		smp_mb__before_clear_bit();
+-		clear_bit(XPRT_LOCKED, &xprt->sockstate);
++		clear_bit(XPRT_LOCKED, &xprt->state);
+ 		smp_mb__after_clear_bit();
+ 		__xprt_lock_write_next(xprt);
+ 	}
+@@ -312,11 +312,11 @@ xprt_init_autodisconnect(unsigned long data)
+ 	spin_lock(&xprt->transport_lock);
+ 	if (!list_empty(&xprt->recv) || xprt->shutdown)
+ 		goto out_abort;
+-	if (test_and_set_bit(XPRT_LOCKED, &xprt->sockstate))
++	if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
+ 		goto out_abort;
+ 	spin_unlock(&xprt->transport_lock);
+ 	/* Let keventd close the socket */
+-	if (test_bit(XPRT_CONNECTING, &xprt->sockstate) != 0)
++	if (xprt_connecting(xprt))
+ 		xprt_release_write(xprt, NULL);
+ 	else
+ 		schedule_work(&xprt->task_cleanup);
+diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
+index bc90caab6088..76a33b54f436 100644
+--- a/net/sunrpc/xprtsock.c
++++ b/net/sunrpc/xprtsock.c
+@@ -925,9 +925,7 @@ static void xs_connect_worker(void *args)
+ 	else
+ 		rpc_wake_up(&xprt->pending);
+ out_clear:
+-	smp_mb__before_clear_bit();
+-	clear_bit(XPRT_CONNECTING, &xprt->sockstate);
+-	smp_mb__after_clear_bit();
++	xprt_clear_connecting(xprt);
+ }
+ 
+ /**
+@@ -940,7 +938,7 @@ static void xs_connect(struct rpc_task *task)
+ {
+ 	struct rpc_xprt *xprt = task->tk_xprt;
+ 
+-	if (!test_and_set_bit(XPRT_CONNECTING, &xprt->sockstate)) {
++	if (!xprt_test_and_set_connecting(xprt)) {
+ 		if (xprt->sock != NULL) {
+ 			dprintk("RPC:      xs_connect delayed xprt %p\n", xprt);
+ 			schedule_delayed_work(&xprt->sock_connect,

commit 5dc07727f86b25851e95193a0c484ea21b531c47
+Author: Chuck Lever 
+Date:   Thu Aug 11 16:25:35 2005 -0400
+
+    [PATCH] RPC: Rename xprt_lock
+    
+     Clean-up: Replace the xprt_lock with something more aptly named.  This lock
+     single-threads the XID and request slot reservation process.
+    
+     Test-plan:
+     Compile kernel with CONFIG_NFS enabled.
+    
+     Version: Thu, 11 Aug 2005 16:05:26 -0400
+    
+     Signed-off-by: Chuck Lever 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
+index c4f903f0e17c..41ce296dded1 100644
+--- a/include/linux/sunrpc/xprt.h
++++ b/include/linux/sunrpc/xprt.h
+@@ -199,7 +199,7 @@ struct rpc_xprt {
+ 	 * Send stuff
+ 	 */
+ 	spinlock_t		transport_lock;	/* lock transport info */
+-	spinlock_t		xprt_lock;	/* lock xprt info */
++	spinlock_t		reserve_lock;	/* lock slot table */
+ 	struct rpc_task *	snd_task;	/* Task blocked in send */
+ 
+ 	struct list_head	recv;
+diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
+index 1f0da8c1a3b0..9c45c522e3ef 100644
+--- a/net/sunrpc/xprt.c
++++ b/net/sunrpc/xprt.c
+@@ -643,9 +643,9 @@ void xprt_reserve(struct rpc_task *task)
+ 
+ 	task->tk_status = -EIO;
+ 	if (!xprt->shutdown) {
+-		spin_lock(&xprt->xprt_lock);
++		spin_lock(&xprt->reserve_lock);
+ 		do_xprt_reserve(task);
+-		spin_unlock(&xprt->xprt_lock);
++		spin_unlock(&xprt->reserve_lock);
+ 	}
+ }
+ 
+@@ -698,10 +698,10 @@ void xprt_release(struct rpc_task *task)
+ 
+ 	dprintk("RPC: %4d release request %p\n", task->tk_pid, req);
+ 
+-	spin_lock(&xprt->xprt_lock);
++	spin_lock(&xprt->reserve_lock);
+ 	list_add(&req->rq_list, &xprt->free);
+ 	xprt_clear_backlog(xprt);
+-	spin_unlock(&xprt->xprt_lock);
++	spin_unlock(&xprt->reserve_lock);
+ }
+ 
+ /**
+@@ -751,7 +751,7 @@ static struct rpc_xprt *xprt_setup(int proto, struct sockaddr_in *ap, struct rpc
+ 	}
+ 
+ 	spin_lock_init(&xprt->transport_lock);
+-	spin_lock_init(&xprt->xprt_lock);
++	spin_lock_init(&xprt->reserve_lock);
+ 	init_waitqueue_head(&xprt->cong_wait);
+ 
+ 	INIT_LIST_HEAD(&xprt->free);

commit 4a0f8c04f2ece949d54a0c4fd7490259cf23a58a
+Author: Chuck Lever 
+Date:   Thu Aug 11 16:25:32 2005 -0400
+
+    [PATCH] RPC: Rename sock_lock
+    
+     Clean-up: replace a name reference to sockets in the generic parts of the RPC
+     client by renaming sock_lock in the rpc_xprt structure.
+    
+     Test-plan:
+     Compile kernel with CONFIG_NFS enabled.
+    
+     Version: Thu, 11 Aug 2005 16:05:00 -0400
+    
+     Signed-off-by: Chuck Lever 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
+index d82b47ab73cb..c4f903f0e17c 100644
+--- a/include/linux/sunrpc/xprt.h
++++ b/include/linux/sunrpc/xprt.h
+@@ -198,7 +198,7 @@ struct rpc_xprt {
+ 	/*
+ 	 * Send stuff
+ 	 */
+-	spinlock_t		sock_lock;	/* lock socket info */
++	spinlock_t		transport_lock;	/* lock transport info */
+ 	spinlock_t		xprt_lock;	/* lock xprt info */
+ 	struct rpc_task *	snd_task;	/* Task blocked in send */
+ 
+diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
+index 589195e630ef..1f0da8c1a3b0 100644
+--- a/net/sunrpc/xprt.c
++++ b/net/sunrpc/xprt.c
+@@ -106,9 +106,9 @@ xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
+ {
+ 	int retval;
+ 
+-	spin_lock_bh(&xprt->sock_lock);
++	spin_lock_bh(&xprt->transport_lock);
+ 	retval = __xprt_lock_write(xprt, task);
+-	spin_unlock_bh(&xprt->sock_lock);
++	spin_unlock_bh(&xprt->transport_lock);
+ 	return retval;
+ }
+ 
+@@ -161,9 +161,9 @@ __xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task)
+ static inline void
+ xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task)
+ {
+-	spin_lock_bh(&xprt->sock_lock);
++	spin_lock_bh(&xprt->transport_lock);
+ 	__xprt_release_write(xprt, task);
+-	spin_unlock_bh(&xprt->sock_lock);
++	spin_unlock_bh(&xprt->transport_lock);
+ }
+ 
+ /*
+@@ -266,9 +266,9 @@ int xprt_adjust_timeout(struct rpc_rqst *req)
+ 		req->rq_retries = 0;
+ 		xprt_reset_majortimeo(req);
+ 		/* Reset the RTT counters == "slow start" */
+-		spin_lock_bh(&xprt->sock_lock);
++		spin_lock_bh(&xprt->transport_lock);
+ 		rpc_init_rtt(req->rq_task->tk_client->cl_rtt, to->to_initval);
+-		spin_unlock_bh(&xprt->sock_lock);
++		spin_unlock_bh(&xprt->transport_lock);
+ 		pprintk("RPC: %lu timeout\n", jiffies);
+ 		status = -ETIMEDOUT;
+ 	}
+@@ -298,10 +298,10 @@ xprt_socket_autoclose(void *args)
+ void xprt_disconnect(struct rpc_xprt *xprt)
+ {
+ 	dprintk("RPC:      disconnected transport %p\n", xprt);
+-	spin_lock_bh(&xprt->sock_lock);
++	spin_lock_bh(&xprt->transport_lock);
+ 	xprt_clear_connected(xprt);
+ 	rpc_wake_up_status(&xprt->pending, -ENOTCONN);
+-	spin_unlock_bh(&xprt->sock_lock);
++	spin_unlock_bh(&xprt->transport_lock);
+ }
+ 
+ static void
+@@ -309,12 +309,12 @@ xprt_init_autodisconnect(unsigned long data)
+ {
+ 	struct rpc_xprt *xprt = (struct rpc_xprt *)data;
+ 
+-	spin_lock(&xprt->sock_lock);
++	spin_lock(&xprt->transport_lock);
+ 	if (!list_empty(&xprt->recv) || xprt->shutdown)
+ 		goto out_abort;
+ 	if (test_and_set_bit(XPRT_LOCKED, &xprt->sockstate))
+ 		goto out_abort;
+-	spin_unlock(&xprt->sock_lock);
++	spin_unlock(&xprt->transport_lock);
+ 	/* Let keventd close the socket */
+ 	if (test_bit(XPRT_CONNECTING, &xprt->sockstate) != 0)
+ 		xprt_release_write(xprt, NULL);
+@@ -322,7 +322,7 @@ xprt_init_autodisconnect(unsigned long data)
+ 		schedule_work(&xprt->task_cleanup);
+ 	return;
+ out_abort:
+-	spin_unlock(&xprt->sock_lock);
++	spin_unlock(&xprt->transport_lock);
+ }
+ 
+ /**
+@@ -482,7 +482,7 @@ xprt_timer(struct rpc_task *task)
+ 	struct rpc_rqst	*req = task->tk_rqstp;
+ 	struct rpc_xprt *xprt = req->rq_xprt;
+ 
+-	spin_lock(&xprt->sock_lock);
++	spin_lock(&xprt->transport_lock);
+ 	if (req->rq_received)
+ 		goto out;
+ 
+@@ -496,7 +496,7 @@ xprt_timer(struct rpc_task *task)
+ out:
+ 	task->tk_timeout = 0;
+ 	rpc_wake_up_task(task);
+-	spin_unlock(&xprt->sock_lock);
++	spin_unlock(&xprt->transport_lock);
+ }
+ 
+ /**
+@@ -515,7 +515,7 @@ int xprt_prepare_transmit(struct rpc_task *task)
+ 	if (xprt->shutdown)
+ 		return -EIO;
+ 
+-	spin_lock_bh(&xprt->sock_lock);
++	spin_lock_bh(&xprt->transport_lock);
+ 	if (req->rq_received && !req->rq_bytes_sent) {
+ 		err = req->rq_received;
+ 		goto out_unlock;
+@@ -530,7 +530,7 @@ int xprt_prepare_transmit(struct rpc_task *task)
+ 		goto out_unlock;
+ 	}
+ out_unlock:
+-	spin_unlock_bh(&xprt->sock_lock);
++	spin_unlock_bh(&xprt->transport_lock);
+ 	return err;
+ }
+ 
+@@ -552,13 +552,13 @@ void xprt_transmit(struct rpc_task *task)
+ 	smp_rmb();
+ 	if (!req->rq_received) {
+ 		if (list_empty(&req->rq_list)) {
+-			spin_lock_bh(&xprt->sock_lock);
++			spin_lock_bh(&xprt->transport_lock);
+ 			/* Update the softirq receive buffer */
+ 			memcpy(&req->rq_private_buf, &req->rq_rcv_buf,
+ 					sizeof(req->rq_private_buf));
+ 			/* Add request to the receive list */
+ 			list_add_tail(&req->rq_list, &xprt->recv);
+-			spin_unlock_bh(&xprt->sock_lock);
++			spin_unlock_bh(&xprt->transport_lock);
+ 			xprt_reset_majortimeo(req);
+ 			/* Turn off autodisconnect */
+ 			del_singleshot_timer_sync(&xprt->timer);
+@@ -592,7 +592,7 @@ void xprt_transmit(struct rpc_task *task)
+  out_receive:
+ 	dprintk("RPC: %4d xmit complete\n", task->tk_pid);
+ 	/* Set the task's receive timeout value */
+-	spin_lock_bh(&xprt->sock_lock);
++	spin_lock_bh(&xprt->transport_lock);
+ 	if (!xprt->nocong) {
+ 		int timer = task->tk_msg.rpc_proc->p_timer;
+ 		task->tk_timeout = rpc_calc_rto(clnt->cl_rtt, timer);
+@@ -607,7 +607,7 @@ void xprt_transmit(struct rpc_task *task)
+ 	else if (!req->rq_received)
+ 		rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer);
+ 	__xprt_release_write(xprt, task);
+-	spin_unlock_bh(&xprt->sock_lock);
++	spin_unlock_bh(&xprt->transport_lock);
+ }
+ 
+ static inline void do_xprt_reserve(struct rpc_task *task)
+@@ -683,7 +683,7 @@ void xprt_release(struct rpc_task *task)
+ 
+ 	if (!(req = task->tk_rqstp))
+ 		return;
+-	spin_lock_bh(&xprt->sock_lock);
++	spin_lock_bh(&xprt->transport_lock);
+ 	__xprt_release_write(xprt, task);
+ 	__xprt_put_cong(xprt, req);
+ 	if (!list_empty(&req->rq_list))
+@@ -692,7 +692,7 @@ void xprt_release(struct rpc_task *task)
+ 	if (list_empty(&xprt->recv) && !xprt->shutdown)
+ 		mod_timer(&xprt->timer,
+ 				xprt->last_used + RPC_IDLE_DISCONNECT_TIMEOUT);
+-	spin_unlock_bh(&xprt->sock_lock);
++	spin_unlock_bh(&xprt->transport_lock);
+ 	task->tk_rqstp = NULL;
+ 	memset(req, 0, sizeof(*req));	/* mark unused */
+ 
+@@ -750,7 +750,7 @@ static struct rpc_xprt *xprt_setup(int proto, struct sockaddr_in *ap, struct rpc
+ 		return ERR_PTR(result);
+ 	}
+ 
+-	spin_lock_init(&xprt->sock_lock);
++	spin_lock_init(&xprt->transport_lock);
+ 	spin_lock_init(&xprt->xprt_lock);
+ 	init_waitqueue_head(&xprt->cong_wait);
+ 
+diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
+index a5a04203a6b0..bc90caab6088 100644
+--- a/net/sunrpc/xprtsock.c
++++ b/net/sunrpc/xprtsock.c
+@@ -307,7 +307,7 @@ static int xs_send_request(struct rpc_task *task)
+ 	if (status == -EAGAIN) {
+ 		if (test_bit(SOCK_ASYNC_NOSPACE, &xprt->sock->flags)) {
+ 			/* Protect against races with xs_write_space */
+-			spin_lock_bh(&xprt->sock_lock);
++			spin_lock_bh(&xprt->transport_lock);
+ 			/* Don't race with disconnect */
+ 			if (!xprt_connected(xprt))
+ 				task->tk_status = -ENOTCONN;
+@@ -315,7 +315,7 @@ static int xs_send_request(struct rpc_task *task)
+ 				task->tk_timeout = req->rq_timeout;
+ 				rpc_sleep_on(&xprt->pending, task, NULL, NULL);
+ 			}
+-			spin_unlock_bh(&xprt->sock_lock);
++			spin_unlock_bh(&xprt->transport_lock);
+ 			return status;
+ 		}
+ 		/* Keep holding the socket if it is blocked */
+@@ -415,7 +415,7 @@ static void xs_udp_data_ready(struct sock *sk, int len)
+ 		goto dropit;
+ 
+ 	/* Look up and lock the request corresponding to the given XID */
+-	spin_lock(&xprt->sock_lock);
++	spin_lock(&xprt->transport_lock);
+ 	rovr = xprt_lookup_rqst(xprt, *xp);
+ 	if (!rovr)
+ 		goto out_unlock;
+@@ -436,7 +436,7 @@ static void xs_udp_data_ready(struct sock *sk, int len)
+ 	xprt_complete_rqst(xprt, rovr, copied);
+ 
+  out_unlock:
+-	spin_unlock(&xprt->sock_lock);
++	spin_unlock(&xprt->transport_lock);
+  dropit:
+ 	skb_free_datagram(sk, skb);
+  out:
+@@ -531,13 +531,13 @@ static inline void xs_tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc
+ 	ssize_t r;
+ 
+ 	/* Find and lock the request corresponding to this xid */
+-	spin_lock(&xprt->sock_lock);
++	spin_lock(&xprt->transport_lock);
+ 	req = xprt_lookup_rqst(xprt, xprt->tcp_xid);
+ 	if (!req) {
+ 		xprt->tcp_flags &= ~XPRT_COPY_DATA;
+ 		dprintk("RPC:      XID %08x request not found!\n",
+ 				ntohl(xprt->tcp_xid));
+-		spin_unlock(&xprt->sock_lock);
++		spin_unlock(&xprt->transport_lock);
+ 		return;
+ 	}
+ 
+@@ -597,7 +597,7 @@ static inline void xs_tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc
+ 				req->rq_task->tk_pid);
+ 		xprt_complete_rqst(xprt, req, xprt->tcp_copied);
+ 	}
+-	spin_unlock(&xprt->sock_lock);
++	spin_unlock(&xprt->transport_lock);
+ 	xs_tcp_check_recm(xprt);
+ }
+ 
+@@ -696,7 +696,7 @@ static void xs_tcp_state_change(struct sock *sk)
+ 
+ 	switch (sk->sk_state) {
+ 	case TCP_ESTABLISHED:
+-		spin_lock_bh(&xprt->sock_lock);
++		spin_lock_bh(&xprt->transport_lock);
+ 		if (!xprt_test_and_set_connected(xprt)) {
+ 			/* Reset TCP record info */
+ 			xprt->tcp_offset = 0;
+@@ -705,7 +705,7 @@ static void xs_tcp_state_change(struct sock *sk)
+ 			xprt->tcp_flags = XPRT_COPY_RECM | XPRT_COPY_XID;
+ 			rpc_wake_up(&xprt->pending);
+ 		}
+-		spin_unlock_bh(&xprt->sock_lock);
++		spin_unlock_bh(&xprt->transport_lock);
+ 		break;
+ 	case TCP_SYN_SENT:
+ 	case TCP_SYN_RECV:
+@@ -753,10 +753,10 @@ static void xs_write_space(struct sock *sk)
+ 	if (!test_and_clear_bit(SOCK_NOSPACE, &sock->flags))
+ 		goto out;
+ 
+-	spin_lock_bh(&xprt->sock_lock);
++	spin_lock_bh(&xprt->transport_lock);
+ 	if (xprt->snd_task)
+ 		rpc_wake_up_task(xprt->snd_task);
+-	spin_unlock_bh(&xprt->sock_lock);
++	spin_unlock_bh(&xprt->transport_lock);
+ out:
+ 	read_unlock(&sk->sk_callback_lock);
+ }

commit b4b5cc85ed4ecbe4adbfbc4df028850de67a9f09
+Author: Chuck Lever 
+Date:   Thu Aug 11 16:25:29 2005 -0400
+
+    [PATCH] RPC: Reduce stack utilization in xs_sendpages
+    
+     Reduce stack utilization of the RPC socket transport's send path.
+    
+     A couple of unlikely()s are added to ensure the compiler places the
+     tail processing at the end of the csect.
+    
+     Test-plan:
+     Millions of fsx operations.  Performance characterization such as "sio" or
+     "iozone".
+    
+     Version: Thu, 11 Aug 2005 16:04:30 -0400
+    
+     Signed-off-by: Chuck Lever 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
+index 80222de3afa4..a5a04203a6b0 100644
+--- a/net/sunrpc/xprtsock.c
++++ b/net/sunrpc/xprtsock.c
+@@ -68,6 +68,41 @@ static inline void xs_pktdump(char *msg, u32 *packet, unsigned int count)
+ }
+ #endif
+ 
++#define XS_SENDMSG_FLAGS	(MSG_DONTWAIT | MSG_NOSIGNAL)
++
++static inline int xs_send_head(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, unsigned int len)
++{
++	struct kvec iov = {
++		.iov_base	= xdr->head[0].iov_base + base,
++		.iov_len	= len - base,
++	};
++	struct msghdr msg = {
++		.msg_name	= addr,
++		.msg_namelen	= addrlen,
++		.msg_flags	= XS_SENDMSG_FLAGS,
++	};
++
++	if (xdr->len > len)
++		msg.msg_flags |= MSG_MORE;
++
++	if (likely(iov.iov_len))
++		return kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
++	return kernel_sendmsg(sock, &msg, NULL, 0, 0);
++}
++
++static int xs_send_tail(struct socket *sock, struct xdr_buf *xdr, unsigned int base, unsigned int len)
++{
++	struct kvec iov = {
++		.iov_base	= xdr->tail[0].iov_base + base,
++		.iov_len	= len - base,
++	};
++	struct msghdr msg = {
++		.msg_flags	= XS_SENDMSG_FLAGS,
++	};
++
++	return kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
++}
++
+ /**
+  * xs_sendpages - write pages directly to a socket
+  * @sock: socket to send on
+@@ -77,7 +112,7 @@ static inline void xs_pktdump(char *msg, u32 *packet, unsigned int count)
+  * @base: starting position in the buffer
+  *
+  */
+-static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, int msgflags)
++static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base)
+ {
+ 	struct page **ppage = xdr->pages;
+ 	unsigned int len, pglen = xdr->page_len;
+@@ -86,35 +121,20 @@ static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
+ 
+ 	len = xdr->head[0].iov_len;
+ 	if (base < len || (addr != NULL && base == 0)) {
+-		struct kvec iov = {
+-			.iov_base = xdr->head[0].iov_base + base,
+-			.iov_len  = len - base,
+-		};
+-		struct msghdr msg = {
+-			.msg_name    = addr,
+-			.msg_namelen = addrlen,
+-			.msg_flags   = msgflags,
+-		};
+-		if (xdr->len > len)
+-			msg.msg_flags |= MSG_MORE;
+-
+-		if (iov.iov_len != 0)
+-			err = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
+-		else
+-			err = kernel_sendmsg(sock, &msg, NULL, 0, 0);
++		err = xs_send_head(sock, addr, addrlen, xdr, base, len);
+ 		if (ret == 0)
+ 			ret = err;
+ 		else if (err > 0)
+ 			ret += err;
+-		if (err != iov.iov_len)
++		if (err != (len - base))
+ 			goto out;
+ 		base = 0;
+ 	} else
+ 		base -= len;
+ 
+-	if (pglen == 0)
++	if (unlikely(pglen == 0))
+ 		goto copy_tail;
+-	if (base >= pglen) {
++	if (unlikely(base >= pglen)) {
+ 		base -= pglen;
+ 		goto copy_tail;
+ 	}
+@@ -127,7 +147,7 @@ static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
+ 
+ 	sendpage = sock->ops->sendpage ? : sock_no_sendpage;
+ 	do {
+-		int flags = msgflags;
++		int flags = XS_SENDMSG_FLAGS;
+ 
+ 		len = PAGE_CACHE_SIZE;
+ 		if (base)
+@@ -154,14 +174,7 @@ static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
+ copy_tail:
+ 	len = xdr->tail[0].iov_len;
+ 	if (base < len) {
+-		struct kvec iov = {
+-			.iov_base = xdr->tail[0].iov_base + base,
+-			.iov_len  = len - base,
+-		};
+-		struct msghdr msg = {
+-			.msg_flags   = msgflags,
+-		};
+-		err = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
++		err = xs_send_tail(sock, xdr, base, len);
+ 		if (ret == 0)
+ 			ret = err;
+ 		else if (err > 0)
+@@ -202,7 +215,7 @@ static int xs_sendmsg(struct rpc_xprt *xprt, struct rpc_rqst *req)
+ 	skip = req->rq_bytes_sent;
+ 
+ 	clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
+-	result = xs_sendpages(sock, addr, addrlen, xdr, skip, MSG_DONTWAIT);
++	result = xs_sendpages(sock, addr, addrlen, xdr, skip);
+ 
+ 	dprintk("RPC:      xs_sendmsg(%d) = %d\n", xdr->len - skip, result);
+ 

commit 9903cd1c27a1f30e8efea75e125be3b2002f7cb9
+Author: Chuck Lever 
+Date:   Thu Aug 11 16:25:26 2005 -0400
+
+    [PATCH] RPC: transport switch function naming
+    
+     Introduce block header comments and a function naming convention to the
+     socket transport implementation.  Provide a debug setting for transports
+     that is separate from RPCDBG_XPRT.  Eliminate xprt_default_timeout().
+    
+     Provide block comments for exposed interfaces in xprt.c, and eliminate
+     the useless obvious comments.
+    
+     Convert printk's to dprintk's.
+    
+     Test-plan:
+     Compile kernel with CONFIG_NFS enabled.
+    
+     Version: Thu, 11 Aug 2005 16:04:04 -0400
+    
+     Signed-off-by: Chuck Lever 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
+index eadb31e3c198..42d299747956 100644
+--- a/include/linux/sunrpc/debug.h
++++ b/include/linux/sunrpc/debug.h
+@@ -32,6 +32,7 @@
+ #define RPCDBG_AUTH		0x0010
+ #define RPCDBG_PMAP		0x0020
+ #define RPCDBG_SCHED		0x0040
++#define RPCDBG_TRANS		0x0080
+ #define RPCDBG_SVCSOCK		0x0100
+ #define RPCDBG_SVCDSP		0x0200
+ #define RPCDBG_MISC		0x0400
+diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
+index 4342acf4d1cd..589195e630ef 100644
+--- a/net/sunrpc/xprt.c
++++ b/net/sunrpc/xprt.c
+@@ -227,9 +227,6 @@ xprt_adjust_cwnd(struct rpc_xprt *xprt, int result)
+ 	xprt->cwnd = cwnd;
+ }
+ 
+-/*
+- * Reset the major timeout value
+- */
+ static void xprt_reset_majortimeo(struct rpc_rqst *req)
+ {
+ 	struct rpc_timeout *to = &req->rq_xprt->timeout;
+@@ -244,8 +241,10 @@ static void xprt_reset_majortimeo(struct rpc_rqst *req)
+ 	req->rq_majortimeo += jiffies;
+ }
+ 
+-/*
+- * Adjust timeout values etc for next retransmit
++/**
++ * xprt_adjust_timeout - adjust timeout values for next retransmit
++ * @req: RPC request containing parameters to use for the adjustment
++ *
+  */
+ int xprt_adjust_timeout(struct rpc_rqst *req)
+ {
+@@ -291,8 +290,10 @@ xprt_socket_autoclose(void *args)
+ 	xprt_release_write(xprt, NULL);
+ }
+ 
+-/*
+- * Mark a transport as disconnected
++/**
++ * xprt_disconnect - mark a transport as disconnected
++ * @xprt: transport to flag for disconnect
++ *
+  */
+ void xprt_disconnect(struct rpc_xprt *xprt)
+ {
+@@ -303,9 +304,6 @@ void xprt_disconnect(struct rpc_xprt *xprt)
+ 	spin_unlock_bh(&xprt->sock_lock);
+ }
+ 
+-/*
+- * Used to allow disconnection when we've been idle
+- */
+ static void
+ xprt_init_autodisconnect(unsigned long data)
+ {
+@@ -327,8 +325,9 @@ xprt_init_autodisconnect(unsigned long data)
+ 	spin_unlock(&xprt->sock_lock);
+ }
+ 
+-/*
+- * Attempt to connect a TCP socket.
++/**
++ * xprt_connect - schedule a transport connect operation
++ * @task: RPC task that is requesting the connect
+  *
+  */
+ void xprt_connect(struct rpc_task *task)
+@@ -361,11 +360,7 @@ void xprt_connect(struct rpc_task *task)
+ 	return;
+ }
+ 
+-/*
+- * We arrive here when awoken from waiting on connection establishment.
+- */
+-static void
+-xprt_connect_status(struct rpc_task *task)
++static void xprt_connect_status(struct rpc_task *task)
+ {
+ 	struct rpc_xprt	*xprt = task->tk_xprt;
+ 
+@@ -404,8 +399,11 @@ xprt_connect_status(struct rpc_task *task)
+ 	}
+ }
+ 
+-/*
+- * Look up the RPC request corresponding to a reply, and then lock it.
++/**
++ * xprt_lookup_rqst - find an RPC request corresponding to an XID
++ * @xprt: transport on which the original request was transmitted
++ * @xid: RPC XID of incoming reply
++ *
+  */
+ struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid)
+ {
+@@ -422,9 +420,12 @@ struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid)
+ 	return req;
+ }
+ 
+-/*
+- * Complete reply received.
+- * The TCP code relies on us to remove the request from xprt->pending.
++/**
++ * xprt_complete_rqst - called when reply processing is complete
++ * @xprt: controlling transport
++ * @req: RPC request that just completed
++ * @copied: actual number of bytes received from the transport
++ *
+  */
+ void xprt_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied)
+ {
+@@ -498,12 +499,12 @@ xprt_timer(struct rpc_task *task)
+ 	spin_unlock(&xprt->sock_lock);
+ }
+ 
+-/*
+- * Place the actual RPC call.
+- * We have to copy the iovec because sendmsg fiddles with its contents.
++/**
++ * xprt_prepare_transmit - reserve the transport before sending a request
++ * @task: RPC task about to send a request
++ *
+  */
+-int
+-xprt_prepare_transmit(struct rpc_task *task)
++int xprt_prepare_transmit(struct rpc_task *task)
+ {
+ 	struct rpc_rqst	*req = task->tk_rqstp;
+ 	struct rpc_xprt	*xprt = req->rq_xprt;
+@@ -533,8 +534,13 @@ xprt_prepare_transmit(struct rpc_task *task)
+ 	return err;
+ }
+ 
+-void
+-xprt_transmit(struct rpc_task *task)
++/**
++ * xprt_transmit - send an RPC request on a transport
++ * @task: controlling RPC task
++ *
++ * We have to copy the iovec because sendmsg fiddles with its contents.
++ */
++void xprt_transmit(struct rpc_task *task)
+ {
+ 	struct rpc_clnt *clnt = task->tk_client;
+ 	struct rpc_rqst	*req = task->tk_rqstp;
+@@ -604,11 +610,7 @@ xprt_transmit(struct rpc_task *task)
+ 	spin_unlock_bh(&xprt->sock_lock);
+ }
+ 
+-/*
+- * Reserve an RPC call slot.
+- */
+-static inline void
+-do_xprt_reserve(struct rpc_task *task)
++static inline void do_xprt_reserve(struct rpc_task *task)
+ {
+ 	struct rpc_xprt	*xprt = task->tk_xprt;
+ 
+@@ -628,8 +630,14 @@ do_xprt_reserve(struct rpc_task *task)
+ 	rpc_sleep_on(&xprt->backlog, task, NULL, NULL);
+ }
+ 
+-void
+-xprt_reserve(struct rpc_task *task)
++/**
++ * xprt_reserve - allocate an RPC request slot
++ * @task: RPC task requesting a slot allocation
++ *
++ * If no more slots are available, place the task on the transport's
++ * backlog queue.
++ */
++void xprt_reserve(struct rpc_task *task)
+ {
+ 	struct rpc_xprt	*xprt = task->tk_xprt;
+ 
+@@ -641,9 +649,6 @@ xprt_reserve(struct rpc_task *task)
+ 	}
+ }
+ 
+-/*
+- * Allocate a 'unique' XID
+- */
+ static inline u32 xprt_alloc_xid(struct rpc_xprt *xprt)
+ {
+ 	return xprt->xid++;
+@@ -654,11 +659,7 @@ static inline void xprt_init_xid(struct rpc_xprt *xprt)
+ 	get_random_bytes(&xprt->xid, sizeof(xprt->xid));
+ }
+ 
+-/*
+- * Initialize RPC request
+- */
+-static void
+-xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
++static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
+ {
+ 	struct rpc_rqst	*req = task->tk_rqstp;
+ 
+@@ -670,11 +671,12 @@ xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
+ 			req, ntohl(req->rq_xid));
+ }
+ 
+-/*
+- * Release an RPC call slot
++/**
++ * xprt_release - release an RPC request slot
++ * @task: task which is finished with the slot
++ *
+  */
+-void
+-xprt_release(struct rpc_task *task)
++void xprt_release(struct rpc_task *task)
+ {
+ 	struct rpc_xprt	*xprt = task->tk_xprt;
+ 	struct rpc_rqst	*req;
+@@ -702,11 +704,14 @@ xprt_release(struct rpc_task *task)
+ 	spin_unlock(&xprt->xprt_lock);
+ }
+ 
+-/*
+- * Set constant timeout
++/**
++ * xprt_set_timeout - set constant RPC timeout
++ * @to: RPC timeout parameters to set up
++ * @retr: number of retries
++ * @incr: amount of increase after each retry
++ *
+  */
+-void
+-xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr)
++void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr)
+ {
+ 	to->to_initval   = 
+ 	to->to_increment = incr;
+@@ -715,11 +720,7 @@ xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr)
+ 	to->to_exponential = 0;
+ }
+ 
+-/*
+- * Initialize an RPC client
+- */
+-static struct rpc_xprt *
+-xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to)
++static struct rpc_xprt *xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to)
+ {
+ 	int result;
+ 	struct rpc_xprt	*xprt;
+@@ -778,11 +779,14 @@ xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to)
+ 	return xprt;
+ }
+ 
+-/*
+- * Create an RPC client transport given the protocol and peer address.
++/**
++ * xprt_create_proto - create an RPC client transport
++ * @proto: requested transport protocol
++ * @sap: remote peer's address
++ * @to: timeout parameters for new transport
++ *
+  */
+-struct rpc_xprt *
+-xprt_create_proto(int proto, struct sockaddr_in *sap, struct rpc_timeout *to)
++struct rpc_xprt *xprt_create_proto(int proto, struct sockaddr_in *sap, struct rpc_timeout *to)
+ {
+ 	struct rpc_xprt	*xprt;
+ 
+@@ -794,11 +798,7 @@ xprt_create_proto(int proto, struct sockaddr_in *sap, struct rpc_timeout *to)
+ 	return xprt;
+ }
+ 
+-/*
+- * Prepare for transport shutdown.
+- */
+-static void
+-xprt_shutdown(struct rpc_xprt *xprt)
++static void xprt_shutdown(struct rpc_xprt *xprt)
+ {
+ 	xprt->shutdown = 1;
+ 	rpc_wake_up(&xprt->sending);
+@@ -809,21 +809,18 @@ xprt_shutdown(struct rpc_xprt *xprt)
+ 	del_timer_sync(&xprt->timer);
+ }
+ 
+-/*
+- * Clear the xprt backlog queue
+- */
+-static int
+-xprt_clear_backlog(struct rpc_xprt *xprt) {
++static int xprt_clear_backlog(struct rpc_xprt *xprt) {
+ 	rpc_wake_up_next(&xprt->backlog);
+ 	wake_up(&xprt->cong_wait);
+ 	return 1;
+ }
+ 
+-/*
+- * Destroy an RPC transport, killing off all requests.
++/**
++ * xprt_destroy - destroy an RPC transport, killing off all requests.
++ * @xprt: transport to destroy
++ *
+  */
+-int
+-xprt_destroy(struct rpc_xprt *xprt)
++int xprt_destroy(struct rpc_xprt *xprt)
+ {
+ 	dprintk("RPC:      destroying transport %p\n", xprt);
+ 	xprt_shutdown(xprt);
+diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
+index fa1180ac4823..80222de3afa4 100644
+--- a/net/sunrpc/xprtsock.c
++++ b/net/sunrpc/xprtsock.c
+@@ -33,23 +33,21 @@
+ #include 
+ #include 
+ 
++/*
++ * Maximum port number to use when requesting a reserved port.
++ */
++#define XS_MAX_RESVPORT		(800U)
++
+ #ifdef RPC_DEBUG
+ # undef  RPC_DEBUG_DATA
+-# define RPCDBG_FACILITY	RPCDBG_XPRT
++# define RPCDBG_FACILITY	RPCDBG_TRANS
+ #endif
+ 
+-#define XPRT_MAX_RESVPORT	(800)
+-
+ #ifdef RPC_DEBUG_DATA
+-/*
+- * Print the buffer contents (first 128 bytes only--just enough for
+- * diropres return).
+- */
+-static void
+-xprt_pktdump(char *msg, u32 *packet, unsigned int count)
++static void xs_pktdump(char *msg, u32 *packet, unsigned int count)
+ {
+-	u8	*buf = (u8 *) packet;
+-	int	j;
++	u8 *buf = (u8 *) packet;
++	int j;
+ 
+ 	dprintk("RPC:      %s\n", msg);
+ 	for (j = 0; j < count && j < 128; j += 4) {
+@@ -64,25 +62,22 @@ xprt_pktdump(char *msg, u32 *packet, unsigned int count)
+ 	dprintk("\n");
+ }
+ #else
+-static inline void
+-xprt_pktdump(char *msg, u32 *packet, unsigned int count)
++static inline void xs_pktdump(char *msg, u32 *packet, unsigned int count)
+ {
+ 	/* NOP */
+ }
+ #endif
+ 
+-/*
+- * Look up RPC transport given an INET socket
++/**
++ * xs_sendpages - write pages directly to a socket
++ * @sock: socket to send on
++ * @addr: UDP only -- address of destination
++ * @addrlen: UDP only -- length of destination address
++ * @xdr: buffer containing this request
++ * @base: starting position in the buffer
++ *
+  */
+-static inline struct rpc_xprt *
+-xprt_from_sock(struct sock *sk)
+-{
+-	return (struct rpc_xprt *) sk->sk_user_data;
+-}
+-
+-static int
+-xdr_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
+-		struct xdr_buf *xdr, unsigned int base, int msgflags)
++static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, int msgflags)
+ {
+ 	struct page **ppage = xdr->pages;
+ 	unsigned int len, pglen = xdr->page_len;
+@@ -125,7 +120,7 @@ xdr_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
+ 	}
+ 	if (base || xdr->page_base) {
+ 		pglen -= base;
+-		base  += xdr->page_base;
++		base += xdr->page_base;
+ 		ppage += base >> PAGE_CACHE_SHIFT;
+ 		base &= ~PAGE_CACHE_MASK;
+ 	}
+@@ -176,23 +171,25 @@ xdr_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
+ 	return ret;
+ }
+ 
+-/*
+- * Write data to socket.
++/**
++ * xs_sendmsg - write an RPC request to a socket
++ * @xprt: generic transport
++ * @req: the RPC request to write
++ *
+  */
+-static inline int
+-xprt_sendmsg(struct rpc_xprt *xprt, struct rpc_rqst *req)
++static int xs_sendmsg(struct rpc_xprt *xprt, struct rpc_rqst *req)
+ {
+-	struct socket	*sock = xprt->sock;
+-	struct xdr_buf	*xdr = &req->rq_snd_buf;
++	struct socket *sock = xprt->sock;
++	struct xdr_buf *xdr = &req->rq_snd_buf;
+ 	struct sockaddr *addr = NULL;
+ 	int addrlen = 0;
+-	unsigned int	skip;
+-	int		result;
++	unsigned int skip;
++	int result;
+ 
+ 	if (!sock)
+ 		return -ENOTCONN;
+ 
+-	xprt_pktdump("packet data:",
++	xs_pktdump("packet data:",
+ 				req->rq_svec->iov_base,
+ 				req->rq_svec->iov_len);
+ 
+@@ -201,13 +198,13 @@ xprt_sendmsg(struct rpc_xprt *xprt, struct rpc_rqst *req)
+ 		addr = (struct sockaddr *) &xprt->addr;
+ 		addrlen = sizeof(xprt->addr);
+ 	}
+-	/* Dont repeat bytes */
++	/* Don't repeat bytes */
+ 	skip = req->rq_bytes_sent;
+ 
+ 	clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
+-	result = xdr_sendpages(sock, addr, addrlen, xdr, skip, MSG_DONTWAIT);
++	result = xs_sendpages(sock, addr, addrlen, xdr, skip, MSG_DONTWAIT);
+ 
+-	dprintk("RPC:      xprt_sendmsg(%d) = %d\n", xdr->len - skip, result);
++	dprintk("RPC:      xs_sendmsg(%d) = %d\n", xdr->len - skip, result);
+ 
+ 	if (result >= 0)
+ 		return result;
+@@ -215,8 +212,7 @@ xprt_sendmsg(struct rpc_xprt *xprt, struct rpc_rqst *req)
+ 	switch (result) {
+ 	case -ECONNREFUSED:
+ 		/* When the server has died, an ICMP port unreachable message
+-		 * prompts ECONNREFUSED.
+-		 */
++		 * prompts ECONNREFUSED. */
+ 	case -EAGAIN:
+ 		break;
+ 	case -ECONNRESET:
+@@ -227,13 +223,25 @@ xprt_sendmsg(struct rpc_xprt *xprt, struct rpc_rqst *req)
+ 			result = -ENOTCONN;
+ 		break;
+ 	default:
+-		printk(KERN_NOTICE "RPC: sendmsg returned error %d\n", -result);
++		break;
+ 	}
+ 	return result;
+ }
+ 
+-static int
+-xprt_send_request(struct rpc_task *task)
++/**
++ * xs_send_request - write an RPC request to a socket
++ * @task: address of RPC task that manages the state of an RPC request
++ *
++ * Return values:
++ *      0:  The request has been sent
++ * EAGAIN:  The socket was blocked, please call again later to
++ *          complete the request
++ *  other:  Some other error occured, the request was not sent
++ *
++ * XXX: In the case of soft timeouts, should we eventually give up
++ *      if the socket is not able to make progress?
++ */
++static int xs_send_request(struct rpc_task *task)
+ {
+ 	struct rpc_rqst *req = task->tk_rqstp;
+ 	struct rpc_xprt *xprt = req->rq_xprt;
+@@ -242,18 +250,18 @@ xprt_send_request(struct rpc_task *task)
+ 	/* set up everything as needed. */
+ 	/* Write the record marker */
+ 	if (xprt->stream) {
+-		u32	*marker = req->rq_svec[0].iov_base;
++		u32 *marker = req->rq_svec[0].iov_base;
+ 
+ 		*marker = htonl(0x80000000|(req->rq_slen-sizeof(*marker)));
+ 	}
+ 
+ 	/* Continue transmitting the packet/record. We must be careful
+ 	 * to cope with writespace callbacks arriving _after_ we have
+-	 * called xprt_sendmsg().
++	 * called sendmsg().
+ 	 */
+ 	while (1) {
+ 		req->rq_xtime = jiffies;
+-		status = xprt_sendmsg(xprt, req);
++		status = xs_sendmsg(xprt, req);
+ 
+ 		if (status < 0)
+ 			break;
+@@ -285,7 +293,7 @@ xprt_send_request(struct rpc_task *task)
+ 
+ 	if (status == -EAGAIN) {
+ 		if (test_bit(SOCK_ASYNC_NOSPACE, &xprt->sock->flags)) {
+-			/* Protect against races with xprt_write_space */
++			/* Protect against races with xs_write_space */
+ 			spin_lock_bh(&xprt->sock_lock);
+ 			/* Don't race with disconnect */
+ 			if (!xprt_connected(xprt))
+@@ -303,65 +311,77 @@ xprt_send_request(struct rpc_task *task)
+ 	return status;
+ }
+ 
+-/*
+- * Close down a transport socket
++/**
++ * xs_close - close a socket
++ * @xprt: transport
++ *
+  */
+-static void
+-xprt_close(struct rpc_xprt *xprt)
++static void xs_close(struct rpc_xprt *xprt)
+ {
+-	struct socket	*sock = xprt->sock;
+-	struct sock	*sk = xprt->inet;
++	struct socket *sock = xprt->sock;
++	struct sock *sk = xprt->inet;
+ 
+ 	if (!sk)
+ 		return;
+ 
++	dprintk("RPC:      xs_close xprt %p\n", xprt);
++
+ 	write_lock_bh(&sk->sk_callback_lock);
+ 	xprt->inet = NULL;
+ 	xprt->sock = NULL;
+ 
+-	sk->sk_user_data    = NULL;
+-	sk->sk_data_ready   = xprt->old_data_ready;
++	sk->sk_user_data = NULL;
++	sk->sk_data_ready = xprt->old_data_ready;
+ 	sk->sk_state_change = xprt->old_state_change;
+-	sk->sk_write_space  = xprt->old_write_space;
++	sk->sk_write_space = xprt->old_write_space;
+ 	write_unlock_bh(&sk->sk_callback_lock);
+ 
+-	sk->sk_no_check	 = 0;
++	sk->sk_no_check = 0;
+ 
+ 	sock_release(sock);
+ }
+ 
+-static void xprt_socket_destroy(struct rpc_xprt *xprt)
++/**
++ * xs_destroy - prepare to shutdown a transport
++ * @xprt: doomed transport
++ *
++ */
++static void xs_destroy(struct rpc_xprt *xprt)
+ {
++	dprintk("RPC:      xs_destroy xprt %p\n", xprt);
++
+ 	cancel_delayed_work(&xprt->sock_connect);
+ 	flush_scheduled_work();
+ 
+ 	xprt_disconnect(xprt);
+-	xprt_close(xprt);
++	xs_close(xprt);
+ 	kfree(xprt->slot);
+ }
+ 
+-/*
+- * Input handler for RPC replies. Called from a bottom half and hence
+- * atomic.
++static inline struct rpc_xprt *xprt_from_sock(struct sock *sk)
++{
++	return (struct rpc_xprt *) sk->sk_user_data;
++}
++
++/**
++ * xs_udp_data_ready - "data ready" callback for UDP sockets
++ * @sk: socket with data to read
++ * @len: how much data to read
++ *
+  */
+-static void
+-udp_data_ready(struct sock *sk, int len)
++static void xs_udp_data_ready(struct sock *sk, int len)
+ {
+-	struct rpc_task	*task;
+-	struct rpc_xprt	*xprt;
++	struct rpc_task *task;
++	struct rpc_xprt *xprt;
+ 	struct rpc_rqst *rovr;
+-	struct sk_buff	*skb;
++	struct sk_buff *skb;
+ 	int err, repsize, copied;
+ 	u32 _xid, *xp;
+ 
+ 	read_lock(&sk->sk_callback_lock);
+-	dprintk("RPC:      udp_data_ready...\n");
+-	if (!(xprt = xprt_from_sock(sk))) {
+-		printk("RPC:      udp_data_ready request not found!\n");
++	dprintk("RPC:      xs_udp_data_ready...\n");
++	if (!(xprt = xprt_from_sock(sk)))
+ 		goto out;
+-	}
+-
+-	dprintk("RPC:      udp_data_ready client %p\n", xprt);
+ 
+ 	if ((skb = skb_recv_datagram(sk, 0, 1, &err)) == NULL)
+ 		goto out;
+@@ -371,7 +391,7 @@ udp_data_ready(struct sock *sk, int len)
+ 
+ 	repsize = skb->len - sizeof(struct udphdr);
+ 	if (repsize < 4) {
+-		printk("RPC: impossible RPC reply size %d!\n", repsize);
++		dprintk("RPC:      impossible RPC reply size %d!\n", repsize);
+ 		goto dropit;
+ 	}
+ 
+@@ -410,11 +430,7 @@ udp_data_ready(struct sock *sk, int len)
+ 	read_unlock(&sk->sk_callback_lock);
+ }
+ 
+-/*
+- * Copy from an skb into memory and shrink the skb.
+- */
+-static inline size_t
+-tcp_copy_data(skb_reader_t *desc, void *p, size_t len)
++static inline size_t xs_tcp_copy_data(skb_reader_t *desc, void *p, size_t len)
+ {
+ 	if (len > desc->count)
+ 		len = desc->count;
+@@ -430,18 +446,14 @@ tcp_copy_data(skb_reader_t *desc, void *p, size_t len)
+ 	return len;
+ }
+ 
+-/*
+- * TCP read fragment marker
+- */
+-static inline void
+-tcp_read_fraghdr(struct rpc_xprt *xprt, skb_reader_t *desc)
++static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, skb_reader_t *desc)
+ {
+ 	size_t len, used;
+ 	char *p;
+ 
+ 	p = ((char *) &xprt->tcp_recm) + xprt->tcp_offset;
+ 	len = sizeof(xprt->tcp_recm) - xprt->tcp_offset;
+-	used = tcp_copy_data(desc, p, len);
++	used = xs_tcp_copy_data(desc, p, len);
+ 	xprt->tcp_offset += used;
+ 	if (used != len)
+ 		return;
+@@ -455,15 +467,15 @@ tcp_read_fraghdr(struct rpc_xprt *xprt, skb_reader_t *desc)
+ 	xprt->tcp_offset = 0;
+ 	/* Sanity check of the record length */
+ 	if (xprt->tcp_reclen < 4) {
+-		printk(KERN_ERR "RPC: Invalid TCP record fragment length\n");
++		dprintk("RPC:      invalid TCP record fragment length\n");
+ 		xprt_disconnect(xprt);
++		return;
+ 	}
+ 	dprintk("RPC:      reading TCP record fragment of length %d\n",
+ 			xprt->tcp_reclen);
+ }
+ 
+-static void
+-tcp_check_recm(struct rpc_xprt *xprt)
++static void xs_tcp_check_recm(struct rpc_xprt *xprt)
+ {
+ 	dprintk("RPC:      xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u, tcp_flags = %lx\n",
+ 			xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen, xprt->tcp_flags);
+@@ -478,11 +490,7 @@ tcp_check_recm(struct rpc_xprt *xprt)
+ 	}
+ }
+ 
+-/*
+- * TCP read xid
+- */
+-static inline void
+-tcp_read_xid(struct rpc_xprt *xprt, skb_reader_t *desc)
++static inline void xs_tcp_read_xid(struct rpc_xprt *xprt, skb_reader_t *desc)
+ {
+ 	size_t len, used;
+ 	char *p;
+@@ -490,7 +498,7 @@ tcp_read_xid(struct rpc_xprt *xprt, skb_reader_t *desc)
+ 	len = sizeof(xprt->tcp_xid) - xprt->tcp_offset;
+ 	dprintk("RPC:      reading XID (%Zu bytes)\n", len);
+ 	p = ((char *) &xprt->tcp_xid) + xprt->tcp_offset;
+-	used = tcp_copy_data(desc, p, len);
++	used = xs_tcp_copy_data(desc, p, len);
+ 	xprt->tcp_offset += used;
+ 	if (used != len)
+ 		return;
+@@ -499,14 +507,10 @@ tcp_read_xid(struct rpc_xprt *xprt, skb_reader_t *desc)
+ 	xprt->tcp_copied = 4;
+ 	dprintk("RPC:      reading reply for XID %08x\n",
+ 						ntohl(xprt->tcp_xid));
+-	tcp_check_recm(xprt);
++	xs_tcp_check_recm(xprt);
+ }
+ 
+-/*
+- * TCP read and complete request
+- */
+-static inline void
+-tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc)
++static inline void xs_tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc)
+ {
+ 	struct rpc_rqst *req;
+ 	struct xdr_buf *rcvbuf;
+@@ -533,12 +537,12 @@ tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc)
+ 		memcpy(&my_desc, desc, sizeof(my_desc));
+ 		my_desc.count = len;
+ 		r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
+-					  &my_desc, tcp_copy_data);
++					  &my_desc, xs_tcp_copy_data);
+ 		desc->count -= r;
+ 		desc->offset += r;
+ 	} else
+ 		r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
+-					  desc, tcp_copy_data);
++					  desc, xs_tcp_copy_data);
+ 
+ 	if (r > 0) {
+ 		xprt->tcp_copied += r;
+@@ -581,14 +585,10 @@ tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc)
+ 		xprt_complete_rqst(xprt, req, xprt->tcp_copied);
+ 	}
+ 	spin_unlock(&xprt->sock_lock);
+-	tcp_check_recm(xprt);
++	xs_tcp_check_recm(xprt);
+ }
+ 
+-/*
+- * TCP discard extra bytes from a short read
+- */
+-static inline void
+-tcp_read_discard(struct rpc_xprt *xprt, skb_reader_t *desc)
++static inline void xs_tcp_read_discard(struct rpc_xprt *xprt, skb_reader_t *desc)
+ {
+ 	size_t len;
+ 
+@@ -599,16 +599,10 @@ tcp_read_discard(struct rpc_xprt *xprt, skb_reader_t *desc)
+ 	desc->offset += len;
+ 	xprt->tcp_offset += len;
+ 	dprintk("RPC:      discarded %Zu bytes\n", len);
+-	tcp_check_recm(xprt);
++	xs_tcp_check_recm(xprt);
+ }
+ 
+-/*
+- * TCP record receive routine
+- * We first have to grab the record marker, then the XID, then the data.
+- */
+-static int
+-tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+-		unsigned int offset, size_t len)
++static int xs_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, unsigned int offset, size_t len)
+ {
+ 	struct rpc_xprt *xprt = rd_desc->arg.data;
+ 	skb_reader_t desc = {
+@@ -616,64 +610,72 @@ tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 		.offset	= offset,
+ 		.count	= len,
+ 		.csum	= 0
+-       	};
++	};
+ 
+-	dprintk("RPC:      tcp_data_recv\n");
++	dprintk("RPC:      xs_tcp_data_recv started\n");
+ 	do {
+ 		/* Read in a new fragment marker if necessary */
+ 		/* Can we ever really expect to get completely empty fragments? */
+ 		if (xprt->tcp_flags & XPRT_COPY_RECM) {
+-			tcp_read_fraghdr(xprt, &desc);
++			xs_tcp_read_fraghdr(xprt, &desc);
+ 			continue;
+ 		}
+ 		/* Read in the xid if necessary */
+ 		if (xprt->tcp_flags & XPRT_COPY_XID) {
+-			tcp_read_xid(xprt, &desc);
++			xs_tcp_read_xid(xprt, &desc);
+ 			continue;
+ 		}
+ 		/* Read in the request data */
+ 		if (xprt->tcp_flags & XPRT_COPY_DATA) {
+-			tcp_read_request(xprt, &desc);
++			xs_tcp_read_request(xprt, &desc);
+ 			continue;
+ 		}
+ 		/* Skip over any trailing bytes on short reads */
+-		tcp_read_discard(xprt, &desc);
++		xs_tcp_read_discard(xprt, &desc);
+ 	} while (desc.count);
+-	dprintk("RPC:      tcp_data_recv done\n");
++	dprintk("RPC:      xs_tcp_data_recv done\n");
+ 	return len - desc.count;
+ }
+ 
+-static void tcp_data_ready(struct sock *sk, int bytes)
++/**
++ * xs_tcp_data_ready - "data ready" callback for TCP sockets
++ * @sk: socket with data to read
++ * @bytes: how much data to read
++ *
++ */
++static void xs_tcp_data_ready(struct sock *sk, int bytes)
+ {
+ 	struct rpc_xprt *xprt;
+ 	read_descriptor_t rd_desc;
+ 
+ 	read_lock(&sk->sk_callback_lock);
+-	dprintk("RPC:      tcp_data_ready...\n");
+-	if (!(xprt = xprt_from_sock(sk))) {
+-		printk("RPC:      tcp_data_ready socket info not found!\n");
++	dprintk("RPC:      xs_tcp_data_ready...\n");
++	if (!(xprt = xprt_from_sock(sk)))
+ 		goto out;
+-	}
+ 	if (xprt->shutdown)
+ 		goto out;
+ 
+-	/* We use rd_desc to pass struct xprt to tcp_data_recv */
++	/* We use rd_desc to pass struct xprt to xs_tcp_data_recv */
+ 	rd_desc.arg.data = xprt;
+ 	rd_desc.count = 65536;
+-	tcp_read_sock(sk, &rd_desc, tcp_data_recv);
++	tcp_read_sock(sk, &rd_desc, xs_tcp_data_recv);
+ out:
+ 	read_unlock(&sk->sk_callback_lock);
+ }
+ 
+-static void
+-tcp_state_change(struct sock *sk)
++/**
++ * xs_tcp_state_change - callback to handle TCP socket state changes
++ * @sk: socket whose state has changed
++ *
++ */
++static void xs_tcp_state_change(struct sock *sk)
+ {
+-	struct rpc_xprt	*xprt;
++	struct rpc_xprt *xprt;
+ 
+ 	read_lock(&sk->sk_callback_lock);
+ 	if (!(xprt = xprt_from_sock(sk)))
+ 		goto out;
+-	dprintk("RPC:      tcp_state_change client %p...\n", xprt);
++	dprintk("RPC:      xs_tcp_state_change client %p...\n", xprt);
+ 	dprintk("RPC:      state %x conn %d dead %d zapped %d\n",
+ 				sk->sk_state, xprt_connected(xprt),
+ 				sock_flag(sk, SOCK_DEAD),
+@@ -703,17 +705,20 @@ tcp_state_change(struct sock *sk)
+ 	read_unlock(&sk->sk_callback_lock);
+ }
+ 
+-/*
++/**
++ * xs_write_space - callback invoked when socket buffer space becomes
++ *                         available
++ * @sk: socket whose state has changed
++ *
+  * Called when more output buffer space is available for this socket.
+  * We try not to wake our writers until they can make "significant"
+  * progress, otherwise we'll waste resources thrashing sock_sendmsg
+  * with a bunch of small requests.
+  */
+-static void
+-xprt_write_space(struct sock *sk)
++static void xs_write_space(struct sock *sk)
+ {
+-	struct rpc_xprt	*xprt;
+-	struct socket	*sock;
++	struct rpc_xprt *xprt;
++	struct socket *sock;
+ 
+ 	read_lock(&sk->sk_callback_lock);
+ 	if (!(xprt = xprt_from_sock(sk)) || !(sock = sk->sk_socket))
+@@ -743,11 +748,15 @@ xprt_write_space(struct sock *sk)
+ 	read_unlock(&sk->sk_callback_lock);
+ }
+ 
+-/*
+- * Set socket buffer length
++/**
++ * xs_set_buffer_size - set send and receive limits
++ * @xprt: generic transport
++ *
++ * Set socket send and receive limits based on the
++ * sndsize and rcvsize fields in the generic transport
++ * structure. This applies only to UDP sockets.
+  */
+-static void
+-xprt_sock_setbufsize(struct rpc_xprt *xprt)
++static void xs_set_buffer_size(struct rpc_xprt *xprt)
+ {
+ 	struct sock *sk = xprt->inet;
+ 
+@@ -764,15 +773,12 @@ xprt_sock_setbufsize(struct rpc_xprt *xprt)
+ 	}
+ }
+ 
+-/*
+- * Bind to a reserved port
+- */
+-static inline int xprt_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
++static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
+ {
+ 	struct sockaddr_in myaddr = {
+ 		.sin_family = AF_INET,
+ 	};
+-	int		err, port;
++	int err, port;
+ 
+ 	/* Were we already bound to a given port? Try to reuse it */
+ 	port = xprt->port;
+@@ -782,20 +788,47 @@ static inline int xprt_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
+ 						sizeof(myaddr));
+ 		if (err == 0) {
+ 			xprt->port = port;
++			dprintk("RPC:      xs_bindresvport bound to port %u\n",
++					port);
+ 			return 0;
+ 		}
+ 		if (--port == 0)
+-			port = XPRT_MAX_RESVPORT;
++			port = XS_MAX_RESVPORT;
+ 	} while (err == -EADDRINUSE && port != xprt->port);
+ 
+-	printk("RPC: Can't bind to reserved port (%d).\n", -err);
++	dprintk("RPC:      can't bind to reserved port (%d).\n", -err);
+ 	return err;
+ }
+ 
+-static void
+-xprt_bind_socket(struct rpc_xprt *xprt, struct socket *sock)
++static struct socket *xs_create(struct rpc_xprt *xprt, int proto, int resvport)
+ {
+-	struct sock	*sk = sock->sk;
++	struct socket *sock;
++	int type, err;
++
++	dprintk("RPC:      xs_create(%s %d)\n",
++			   (proto == IPPROTO_UDP)? "udp" : "tcp", proto);
++
++	type = (proto == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
++
++	if ((err = sock_create_kern(PF_INET, type, proto, &sock)) < 0) {
++		dprintk("RPC:      can't create socket (%d).\n", -err);
++		return NULL;
++	}
++
++	/* If the caller has the capability, bind to a reserved port */
++	if (resvport && xs_bindresvport(xprt, sock) < 0)
++		goto failed;
++
++	return sock;
++
++failed:
++	sock_release(sock);
++	return NULL;
++}
++
++static void xs_bind(struct rpc_xprt *xprt, struct socket *sock)
++{
++	struct sock *sk = sock->sk;
+ 
+ 	if (xprt->inet)
+ 		return;
+@@ -806,16 +839,16 @@ xprt_bind_socket(struct rpc_xprt *xprt, struct socket *sock)
+ 	xprt->old_state_change = sk->sk_state_change;
+ 	xprt->old_write_space = sk->sk_write_space;
+ 	if (xprt->prot == IPPROTO_UDP) {
+-		sk->sk_data_ready = udp_data_ready;
++		sk->sk_data_ready = xs_udp_data_ready;
+ 		sk->sk_no_check = UDP_CSUM_NORCV;
+ 		xprt_set_connected(xprt);
+ 	} else {
+ 		tcp_sk(sk)->nonagle = 1;	/* disable Nagle's algorithm */
+-		sk->sk_data_ready = tcp_data_ready;
+-		sk->sk_state_change = tcp_state_change;
++		sk->sk_data_ready = xs_tcp_data_ready;
++		sk->sk_state_change = xs_tcp_state_change;
+ 		xprt_clear_connected(xprt);
+ 	}
+-	sk->sk_write_space = xprt_write_space;
++	sk->sk_write_space = xs_write_space;
+ 
+ 	/* Reset to new socket */
+ 	xprt->sock = sock;
+@@ -825,39 +858,13 @@ xprt_bind_socket(struct rpc_xprt *xprt, struct socket *sock)
+ 	return;
+ }
+ 
+-/*
+- * Datastream sockets are created here, but xprt_connect will create
+- * and connect stream sockets.
++/**
++ * xs_connect_worker - try to connect a socket to a remote endpoint
++ * @args: RPC transport to connect
++ *
++ * Invoked by a work queue tasklet.
+  */
+-static struct socket * xprt_create_socket(struct rpc_xprt *xprt, int proto, int resvport)
+-{
+-	struct socket	*sock;
+-	int		type, err;
+-
+-	dprintk("RPC:      xprt_create_socket(%s %d)\n",
+-			   (proto == IPPROTO_UDP)? "udp" : "tcp", proto);
+-
+-	type = (proto == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
+-
+-	if ((err = sock_create_kern(PF_INET, type, proto, &sock)) < 0) {
+-		printk("RPC: can't create socket (%d).\n", -err);
+-		return NULL;
+-	}
+-
+-	/* If the caller has the capability, bind to a reserved port */
+-	if (resvport && xprt_bindresvport(xprt, sock) < 0) {
+-		printk("RPC: can't bind to reserved port.\n");
+-		goto failed;
+-	}
+-
+-	return sock;
+-
+-failed:
+-	sock_release(sock);
+-	return NULL;
+-}
+-
+-static void xprt_socket_connect(void *args)
++static void xs_connect_worker(void *args)
+ {
+ 	struct rpc_xprt *xprt = (struct rpc_xprt *)args;
+ 	struct socket *sock = xprt->sock;
+@@ -866,18 +873,20 @@ static void xprt_socket_connect(void *args)
+ 	if (xprt->shutdown || xprt->addr.sin_port == 0)
+ 		goto out;
+ 
++	dprintk("RPC:      xs_connect_worker xprt %p\n", xprt);
++
+ 	/*
+ 	 * Start by resetting any existing state
+ 	 */
+-	xprt_close(xprt);
+-	sock = xprt_create_socket(xprt, xprt->prot, xprt->resvport);
++	xs_close(xprt);
++	sock = xs_create(xprt, xprt->prot, xprt->resvport);
+ 	if (sock == NULL) {
+ 		/* couldn't create socket or bind to reserved port;
+ 		 * this is likely a permanent error, so cause an abort */
+ 		goto out;
+ 	}
+-	xprt_bind_socket(xprt, sock);
+-	xprt_sock_setbufsize(xprt);
++	xs_bind(xprt, sock);
++	xs_set_buffer_size(xprt);
+ 
+ 	status = 0;
+ 	if (!xprt->stream)
+@@ -908,20 +917,23 @@ static void xprt_socket_connect(void *args)
+ 	smp_mb__after_clear_bit();
+ }
+ 
+-static void
+-xprt_connect_sock(struct rpc_task *task)
++/**
++ * xs_connect - connect a socket to a remote endpoint
++ * @task: address of RPC task that manages state of connect request
++ *
++ * TCP: If the remote end dropped the connection, delay reconnecting.
++ */
++static void xs_connect(struct rpc_task *task)
+ {
+ 	struct rpc_xprt *xprt = task->tk_xprt;
+ 
+ 	if (!test_and_set_bit(XPRT_CONNECTING, &xprt->sockstate)) {
+-		/* Note: if we are here due to a dropped connection
+-		 * 	 we delay reconnecting by RPC_REESTABLISH_TIMEOUT/HZ
+-		 * 	 seconds
+-		 */
+-		if (xprt->sock != NULL)
++		if (xprt->sock != NULL) {
++			dprintk("RPC:      xs_connect delayed xprt %p\n", xprt);
+ 			schedule_delayed_work(&xprt->sock_connect,
+ 					RPC_REESTABLISH_TIMEOUT);
+-		else {
++		} else {
++			dprintk("RPC:      xs_connect scheduled xprt %p\n", xprt);
+ 			schedule_work(&xprt->sock_connect);
+ 			/* flush_scheduled_work can sleep... */
+ 			if (!RPC_IS_ASYNC(task))
+@@ -930,29 +942,23 @@ xprt_connect_sock(struct rpc_task *task)
+ 	}
+ }
+ 
+-/*
+- * Set default timeout parameters
+- */
+-static void
+-xprt_default_timeout(struct rpc_timeout *to, int proto)
+-{
+-	if (proto == IPPROTO_UDP)
+-		xprt_set_timeout(to, 5,  5 * HZ);
+-	else
+-		xprt_set_timeout(to, 2, 60 * HZ);
+-}
+-
+-static struct rpc_xprt_ops xprt_socket_ops = {
+-	.set_buffer_size	= xprt_sock_setbufsize,
+-	.connect		= xprt_connect_sock,
+-	.send_request		= xprt_send_request,
+-	.close			= xprt_close,
+-	.destroy		= xprt_socket_destroy,
++static struct rpc_xprt_ops xs_ops = {
++	.set_buffer_size	= xs_set_buffer_size,
++	.connect		= xs_connect,
++	.send_request		= xs_send_request,
++	.close			= xs_close,
++	.destroy		= xs_destroy,
+ };
+ 
+ extern unsigned int xprt_udp_slot_table_entries;
+ extern unsigned int xprt_tcp_slot_table_entries;
+ 
++/**
++ * xs_setup_udp - Set up transport to use a UDP socket
++ * @xprt: transport to set up
++ * @to:   timeout parameters
++ *
++ */
+ int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to)
+ {
+ 	size_t slot_table_size;
+@@ -967,7 +973,7 @@ int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to)
+ 	memset(xprt->slot, 0, slot_table_size);
+ 
+ 	xprt->prot = IPPROTO_UDP;
+-	xprt->port = XPRT_MAX_RESVPORT;
++	xprt->port = XS_MAX_RESVPORT;
+ 	xprt->stream = 0;
+ 	xprt->nocong = 0;
+ 	xprt->cwnd = RPC_INITCWND;
+@@ -975,18 +981,24 @@ int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to)
+ 	/* XXX: header size can vary due to auth type, IPv6, etc. */
+ 	xprt->max_payload = (1U << 16) - (MAX_HEADER << 3);
+ 
+-	INIT_WORK(&xprt->sock_connect, xprt_socket_connect, xprt);
++	INIT_WORK(&xprt->sock_connect, xs_connect_worker, xprt);
+ 
+-	xprt->ops = &xprt_socket_ops;
++	xprt->ops = &xs_ops;
+ 
+ 	if (to)
+ 		xprt->timeout = *to;
+ 	else
+-		xprt_default_timeout(to, xprt->prot);
++		xprt_set_timeout(&xprt->timeout, 5, 5 * HZ);
+ 
+ 	return 0;
+ }
+ 
++/**
++ * xs_setup_tcp - Set up transport to use a TCP socket
++ * @xprt: transport to set up
++ * @to: timeout parameters
++ *
++ */
+ int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to)
+ {
+ 	size_t slot_table_size;
+@@ -1001,21 +1013,21 @@ int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to)
+ 	memset(xprt->slot, 0, slot_table_size);
+ 
+ 	xprt->prot = IPPROTO_TCP;
+-	xprt->port = XPRT_MAX_RESVPORT;
++	xprt->port = XS_MAX_RESVPORT;
+ 	xprt->stream = 1;
+ 	xprt->nocong = 1;
+ 	xprt->cwnd = RPC_MAXCWND(xprt);
+ 	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
+ 	xprt->max_payload = (1U << 31) - 1;
+ 
+-	INIT_WORK(&xprt->sock_connect, xprt_socket_connect, xprt);
++	INIT_WORK(&xprt->sock_connect, xs_connect_worker, xprt);
+ 
+-	xprt->ops = &xprt_socket_ops;
++	xprt->ops = &xs_ops;
+ 
+ 	if (to)
+ 		xprt->timeout = *to;
+ 	else
+-		xprt_default_timeout(to, xprt->prot);
++		xprt_set_timeout(&xprt->timeout, 2, 60 * HZ);
+ 
+ 	return 0;
+ }

commit a246b0105bbd9a70a698f69baae2042996f2a0e9
+Author: Chuck Lever 
+Date:   Thu Aug 11 16:25:23 2005 -0400
+
+    [PATCH] RPC: introduce client-side transport switch
+    
+     Move the bulk of client-side socket-specific code into a separate source
+     file, net/sunrpc/xprtsock.c.
+    
+     Test-plan:
+     Millions of fsx operations.  Performance characterization such as "sio" or
+     "iozone".  Destructive testing (unplugging the network temporarily, server
+     reboots).  Connectathon with v2, v3, and v4.
+    
+     Version: Thu, 11 Aug 2005 16:03:38 -0400
+    
+     Signed-off-by: Chuck Lever 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
+index d8b7656bca41..5da968729cf8 100644
+--- a/include/linux/sunrpc/xdr.h
++++ b/include/linux/sunrpc/xdr.h
+@@ -165,11 +165,6 @@ extern int csum_partial_copy_to_xdr(struct xdr_buf *, struct sk_buff *);
+ extern ssize_t xdr_partial_copy_from_skb(struct xdr_buf *, unsigned int,
+ 		skb_reader_t *, skb_read_actor_t);
+ 
+-struct socket;
+-struct sockaddr;
+-extern int xdr_sendpages(struct socket *, struct sockaddr *, int,
+-		struct xdr_buf *, unsigned int, int);
+-
+ extern int xdr_encode_word(struct xdr_buf *, int, u32);
+ extern int xdr_decode_word(struct xdr_buf *, int, u32 *);
+ 
+diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
+index e618c1649814..d82b47ab73cb 100644
+--- a/include/linux/sunrpc/xprt.h
++++ b/include/linux/sunrpc/xprt.h
+@@ -59,7 +59,13 @@ extern unsigned int xprt_tcp_slot_table_entries;
+  */
+ #define RPC_REESTABLISH_TIMEOUT	(15*HZ)
+ 
+-/* RPC call and reply header size as number of 32bit words (verifier
++/*
++ * RPC transport idle timeout.
++ */
++#define RPC_IDLE_DISCONNECT_TIMEOUT	(5*60*HZ)
++
++/*
++ * RPC call and reply header size as number of 32bit words (verifier
+  * size computed separately)
+  */
+ #define RPC_CALLHDRSIZE		6
+@@ -121,12 +127,19 @@ struct rpc_rqst {
+ #define rq_svec			rq_snd_buf.head
+ #define rq_slen			rq_snd_buf.len
+ 
+-#define XPRT_LAST_FRAG		(1 << 0)
+-#define XPRT_COPY_RECM		(1 << 1)
+-#define XPRT_COPY_XID		(1 << 2)
+-#define XPRT_COPY_DATA		(1 << 3)
++struct rpc_task;
++struct rpc_xprt;
++
++struct rpc_xprt_ops {
++	void		(*set_buffer_size)(struct rpc_xprt *xprt);
++	void		(*connect)(struct rpc_task *task);
++	int		(*send_request)(struct rpc_task *task);
++	void		(*close)(struct rpc_xprt *xprt);
++	void		(*destroy)(struct rpc_xprt *xprt);
++};
+ 
+ struct rpc_xprt {
++	struct rpc_xprt_ops *	ops;		/* transport methods */
+ 	struct socket *		sock;		/* BSD socket layer */
+ 	struct sock *		inet;		/* INET layer */
+ 
+@@ -199,14 +212,22 @@ struct rpc_xprt {
+ 	wait_queue_head_t	cong_wait;
+ };
+ 
++#define XPRT_LAST_FRAG		(1 << 0)
++#define XPRT_COPY_RECM		(1 << 1)
++#define XPRT_COPY_XID		(1 << 2)
++#define XPRT_COPY_DATA		(1 << 3)
++
+ #ifdef __KERNEL__
+ 
+ struct rpc_xprt *	xprt_create_proto(int proto, struct sockaddr_in *addr,
+ 					struct rpc_timeout *toparms);
++void			xprt_disconnect(struct rpc_xprt *);
+ int			xprt_destroy(struct rpc_xprt *);
+ void			xprt_set_timeout(struct rpc_timeout *, unsigned int,
+ 					unsigned long);
+-
++struct rpc_rqst *	xprt_lookup_rqst(struct rpc_xprt *, u32);
++void			xprt_complete_rqst(struct rpc_xprt *,
++					struct rpc_rqst *, int);
+ void			xprt_reserve(struct rpc_task *);
+ int			xprt_prepare_transmit(struct rpc_task *);
+ void			xprt_transmit(struct rpc_task *);
+@@ -214,7 +235,10 @@ void			xprt_receive(struct rpc_task *);
+ int			xprt_adjust_timeout(struct rpc_rqst *req);
+ void			xprt_release(struct rpc_task *);
+ void			xprt_connect(struct rpc_task *);
+-void			xprt_sock_setbufsize(struct rpc_xprt *);
++int			xs_setup_udp(struct rpc_xprt *,
++					struct rpc_timeout *);
++int			xs_setup_tcp(struct rpc_xprt *,
++					struct rpc_timeout *);
+ 
+ #define XPRT_LOCKED	0
+ #define XPRT_CONNECT	1
+diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile
+index f0a955627177..cdcab9ca4c60 100644
+--- a/net/sunrpc/Makefile
++++ b/net/sunrpc/Makefile
+@@ -6,7 +6,7 @@
+ obj-$(CONFIG_SUNRPC) += sunrpc.o
+ obj-$(CONFIG_SUNRPC_GSS) += auth_gss/
+ 
+-sunrpc-y := clnt.o xprt.o socklib.o sched.o \
++sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \
+ 	    auth.o auth_null.o auth_unix.o \
+ 	    svc.o svcsock.o svcauth.o svcauth_unix.o \
+ 	    pmap_clnt.o timer.o xdr.o \
+diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
+index 2d3cf0a52d82..ab50c3c9e6a8 100644
+--- a/net/sunrpc/clnt.c
++++ b/net/sunrpc/clnt.c
+@@ -525,8 +525,7 @@ rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize
+ 	xprt->rcvsize = 0;
+ 	if (rcvsize)
+ 		xprt->rcvsize = rcvsize + RPC_SLACK_SPACE;
+-	if (xprt_connected(xprt))
+-		xprt_sock_setbufsize(xprt);
++	xprt->ops->set_buffer_size(xprt);
+ }
+ 
+ /*
+diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c
+index 1b9616a12e24..ef483262f17f 100644
+--- a/net/sunrpc/sysctl.c
++++ b/net/sunrpc/sysctl.c
+@@ -119,6 +119,9 @@ proc_dodebug(ctl_table *table, int write, struct file *file,
+ 	return 0;
+ }
+ 
++unsigned int xprt_udp_slot_table_entries = RPC_DEF_SLOT_TABLE;
++unsigned int xprt_tcp_slot_table_entries = RPC_DEF_SLOT_TABLE;
++
+ static unsigned int min_slot_table_size = RPC_MIN_SLOT_TABLE;
+ static unsigned int max_slot_table_size = RPC_MAX_SLOT_TABLE;
+ 
+diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
+index 9cc12aeed22c..32df43372ee9 100644
+--- a/net/sunrpc/xdr.c
++++ b/net/sunrpc/xdr.c
+@@ -6,15 +6,12 @@
+  * Copyright (C) 1995, 1996 Olaf Kirch 
+  */
+ 
++#include 
+ #include 
+-#include 
+ #include 
+ #include 
+ #include 
+ #include 
+-#include 
+-#include 
+-#include 
+ #include 
+ #include 
+ 
+@@ -177,103 +174,6 @@ xdr_inline_pages(struct xdr_buf *xdr, unsigned int offset,
+ }
+ 
+ 
+-int
+-xdr_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
+-		struct xdr_buf *xdr, unsigned int base, int msgflags)
+-{
+-	struct page **ppage = xdr->pages;
+-	unsigned int len, pglen = xdr->page_len;
+-	int err, ret = 0;
+-	ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
+-
+-	len = xdr->head[0].iov_len;
+-	if (base < len || (addr != NULL && base == 0)) {
+-		struct kvec iov = {
+-			.iov_base = xdr->head[0].iov_base + base,
+-			.iov_len  = len - base,
+-		};
+-		struct msghdr msg = {
+-			.msg_name    = addr,
+-			.msg_namelen = addrlen,
+-			.msg_flags   = msgflags,
+-		};
+-		if (xdr->len > len)
+-			msg.msg_flags |= MSG_MORE;
+-
+-		if (iov.iov_len != 0)
+-			err = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
+-		else
+-			err = kernel_sendmsg(sock, &msg, NULL, 0, 0);
+-		if (ret == 0)
+-			ret = err;
+-		else if (err > 0)
+-			ret += err;
+-		if (err != iov.iov_len)
+-			goto out;
+-		base = 0;
+-	} else
+-		base -= len;
+-
+-	if (pglen == 0)
+-		goto copy_tail;
+-	if (base >= pglen) {
+-		base -= pglen;
+-		goto copy_tail;
+-	}
+-	if (base || xdr->page_base) {
+-		pglen -= base;
+-		base  += xdr->page_base;
+-		ppage += base >> PAGE_CACHE_SHIFT;
+-		base &= ~PAGE_CACHE_MASK;
+-	}
+-
+-	sendpage = sock->ops->sendpage ? : sock_no_sendpage;
+-	do {
+-		int flags = msgflags;
+-
+-		len = PAGE_CACHE_SIZE;
+-		if (base)
+-			len -= base;
+-		if (pglen < len)
+-			len = pglen;
+-
+-		if (pglen != len || xdr->tail[0].iov_len != 0)
+-			flags |= MSG_MORE;
+-
+-		/* Hmm... We might be dealing with highmem pages */
+-		if (PageHighMem(*ppage))
+-			sendpage = sock_no_sendpage;
+-		err = sendpage(sock, *ppage, base, len, flags);
+-		if (ret == 0)
+-			ret = err;
+-		else if (err > 0)
+-			ret += err;
+-		if (err != len)
+-			goto out;
+-		base = 0;
+-		ppage++;
+-	} while ((pglen -= len) != 0);
+-copy_tail:
+-	len = xdr->tail[0].iov_len;
+-	if (base < len) {
+-		struct kvec iov = {
+-			.iov_base = xdr->tail[0].iov_base + base,
+-			.iov_len  = len - base,
+-		};
+-		struct msghdr msg = {
+-			.msg_flags   = msgflags,
+-		};
+-		err = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
+-		if (ret == 0)
+-			ret = err;
+-		else if (err > 0)
+-			ret += err;
+-	}
+-out:
+-	return ret;
+-}
+-
+-
+ /*
+  * Helper routines for doing 'memmove' like operations on a struct xdr_buf
+  *
+diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
+index 67444f494fea..4342acf4d1cd 100644
+--- a/net/sunrpc/xprt.c
++++ b/net/sunrpc/xprt.c
+@@ -32,37 +32,16 @@
+  *  tasks that rely on callbacks.
+  *
+  *  Copyright (C) 1995-1997, Olaf Kirch 
+- *
+- *  TCP callback races fixes (C) 1998 Red Hat Software 
+- *  TCP send fixes (C) 1998 Red Hat Software 
+- *  TCP NFS related read + write fixes
+- *   (C) 1999 Dave Airlie, University of Limerick, Ireland 
+- *
+- *  Rewrite of larges part of the code in order to stabilize TCP stuff.
+- *  Fix behaviour when socket buffer is full.
+- *   (C) 1999 Trond Myklebust 
+  */
+ 
++#include 
++
+ #include 
+-#include 
+-#include 
+-#include 
+-#include 
+-#include 
+-#include 
+-#include 
+-#include 
+-#include 
+-#include 
+-#include 
+-#include 
++#include 
+ #include 
+ #include 
+ 
+-#include 
+-#include 
+-#include 
+-#include 
++#include 
+ 
+ /*
+  * Local variables
+@@ -74,64 +53,17 @@
+ #endif
+ 
+ #define XPRT_MAX_BACKOFF	(8)
+-#define XPRT_IDLE_TIMEOUT	(5*60*HZ)
+-#define XPRT_MAX_RESVPORT	(800)
+ 
+ /*
+  * Local functions
+  */
+ static void	xprt_request_init(struct rpc_task *, struct rpc_xprt *);
+ static inline void	do_xprt_reserve(struct rpc_task *);
+-static void	xprt_disconnect(struct rpc_xprt *);
+ static void	xprt_connect_status(struct rpc_task *task);
+-static struct rpc_xprt * xprt_setup(int proto, struct sockaddr_in *ap,
+-						struct rpc_timeout *to);
+-static struct socket *xprt_create_socket(struct rpc_xprt *, int, int);
+-static void	xprt_bind_socket(struct rpc_xprt *, struct socket *);
+ static int      __xprt_get_cong(struct rpc_xprt *, struct rpc_task *);
+ 
+ static int	xprt_clear_backlog(struct rpc_xprt *xprt);
+ 
+-#ifdef RPC_DEBUG_DATA
+-/*
+- * Print the buffer contents (first 128 bytes only--just enough for
+- * diropres return).
+- */
+-static void
+-xprt_pktdump(char *msg, u32 *packet, unsigned int count)
+-{
+-	u8	*buf = (u8 *) packet;
+-	int	j;
+-
+-	dprintk("RPC:      %s\n", msg);
+-	for (j = 0; j < count && j < 128; j += 4) {
+-		if (!(j & 31)) {
+-			if (j)
+-				dprintk("\n");
+-			dprintk("0x%04x ", j);
+-		}
+-		dprintk("%02x%02x%02x%02x ",
+-			buf[j], buf[j+1], buf[j+2], buf[j+3]);
+-	}
+-	dprintk("\n");
+-}
+-#else
+-static inline void
+-xprt_pktdump(char *msg, u32 *packet, unsigned int count)
+-{
+-	/* NOP */
+-}
+-#endif
+-
+-/*
+- * Look up RPC transport given an INET socket
+- */
+-static inline struct rpc_xprt *
+-xprt_from_sock(struct sock *sk)
+-{
+-	return (struct rpc_xprt *) sk->sk_user_data;
+-}
+-
+ /*
+  * Serialize write access to sockets, in order to prevent different
+  * requests from interfering with each other.
+@@ -234,62 +166,6 @@ xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task)
+ 	spin_unlock_bh(&xprt->sock_lock);
+ }
+ 
+-/*
+- * Write data to socket.
+- */
+-static inline int
+-xprt_sendmsg(struct rpc_xprt *xprt, struct rpc_rqst *req)
+-{
+-	struct socket	*sock = xprt->sock;
+-	struct xdr_buf	*xdr = &req->rq_snd_buf;
+-	struct sockaddr *addr = NULL;
+-	int addrlen = 0;
+-	unsigned int	skip;
+-	int		result;
+-
+-	if (!sock)
+-		return -ENOTCONN;
+-
+-	xprt_pktdump("packet data:",
+-				req->rq_svec->iov_base,
+-				req->rq_svec->iov_len);
+-
+-	/* For UDP, we need to provide an address */
+-	if (!xprt->stream) {
+-		addr = (struct sockaddr *) &xprt->addr;
+-		addrlen = sizeof(xprt->addr);
+-	}
+-	/* Dont repeat bytes */
+-	skip = req->rq_bytes_sent;
+-
+-	clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
+-	result = xdr_sendpages(sock, addr, addrlen, xdr, skip, MSG_DONTWAIT);
+-
+-	dprintk("RPC:      xprt_sendmsg(%d) = %d\n", xdr->len - skip, result);
+-
+-	if (result >= 0)
+-		return result;
+-
+-	switch (result) {
+-	case -ECONNREFUSED:
+-		/* When the server has died, an ICMP port unreachable message
+-		 * prompts ECONNREFUSED.
+-		 */
+-	case -EAGAIN:
+-		break;
+-	case -ECONNRESET:
+-	case -ENOTCONN:
+-	case -EPIPE:
+-		/* connection broken */
+-		if (xprt->stream)
+-			result = -ENOTCONN;
+-		break;
+-	default:
+-		printk(KERN_NOTICE "RPC: sendmsg returned error %d\n", -result);
+-	}
+-	return result;
+-}
+-
+ /*
+  * Van Jacobson congestion avoidance. Check if the congestion window
+  * overflowed. Put the task to sleep if this is the case.
+@@ -405,48 +281,20 @@ int xprt_adjust_timeout(struct rpc_rqst *req)
+ 	return status;
+ }
+ 
+-/*
+- * Close down a transport socket
+- */
+-static void
+-xprt_close(struct rpc_xprt *xprt)
+-{
+-	struct socket	*sock = xprt->sock;
+-	struct sock	*sk = xprt->inet;
+-
+-	if (!sk)
+-		return;
+-
+-	write_lock_bh(&sk->sk_callback_lock);
+-	xprt->inet = NULL;
+-	xprt->sock = NULL;
+-
+-	sk->sk_user_data    = NULL;
+-	sk->sk_data_ready   = xprt->old_data_ready;
+-	sk->sk_state_change = xprt->old_state_change;
+-	sk->sk_write_space  = xprt->old_write_space;
+-	write_unlock_bh(&sk->sk_callback_lock);
+-
+-	sk->sk_no_check	 = 0;
+-
+-	sock_release(sock);
+-}
+-
+ static void
+ xprt_socket_autoclose(void *args)
+ {
+ 	struct rpc_xprt *xprt = (struct rpc_xprt *)args;
+ 
+ 	xprt_disconnect(xprt);
+-	xprt_close(xprt);
++	xprt->ops->close(xprt);
+ 	xprt_release_write(xprt, NULL);
+ }
+ 
+ /*
+  * Mark a transport as disconnected
+  */
+-static void
+-xprt_disconnect(struct rpc_xprt *xprt)
++void xprt_disconnect(struct rpc_xprt *xprt)
+ {
+ 	dprintk("RPC:      disconnected transport %p\n", xprt);
+ 	spin_lock_bh(&xprt->sock_lock);
+@@ -479,57 +327,6 @@ xprt_init_autodisconnect(unsigned long data)
+ 	spin_unlock(&xprt->sock_lock);
+ }
+ 
+-static void xprt_socket_connect(void *args)
+-{
+-	struct rpc_xprt *xprt = (struct rpc_xprt *)args;
+-	struct socket *sock = xprt->sock;
+-	int status = -EIO;
+-
+-	if (xprt->shutdown || xprt->addr.sin_port == 0)
+-		goto out;
+-
+-	/*
+-	 * Start by resetting any existing state
+-	 */
+-	xprt_close(xprt);
+-	sock = xprt_create_socket(xprt, xprt->prot, xprt->resvport);
+-	if (sock == NULL) {
+-		/* couldn't create socket or bind to reserved port;
+-		 * this is likely a permanent error, so cause an abort */
+-		goto out;
+-	}
+-	xprt_bind_socket(xprt, sock);
+-	xprt_sock_setbufsize(xprt);
+-
+-	status = 0;
+-	if (!xprt->stream)
+-		goto out;
+-
+-	/*
+-	 * Tell the socket layer to start connecting...
+-	 */
+-	status = sock->ops->connect(sock, (struct sockaddr *) &xprt->addr,
+-			sizeof(xprt->addr), O_NONBLOCK);
+-	dprintk("RPC: %p  connect status %d connected %d sock state %d\n",
+-			xprt, -status, xprt_connected(xprt), sock->sk->sk_state);
+-	if (status < 0) {
+-		switch (status) {
+-			case -EINPROGRESS:
+-			case -EALREADY:
+-				goto out_clear;
+-		}
+-	}
+-out:
+-	if (status < 0)
+-		rpc_wake_up_status(&xprt->pending, status);
+-	else
+-		rpc_wake_up(&xprt->pending);
+-out_clear:
+-	smp_mb__before_clear_bit();
+-	clear_bit(XPRT_CONNECTING, &xprt->sockstate);
+-	smp_mb__after_clear_bit();
+-}
+-
+ /*
+  * Attempt to connect a TCP socket.
+  *
+@@ -552,30 +349,16 @@ void xprt_connect(struct rpc_task *task)
+ 	if (!xprt_lock_write(xprt, task))
+ 		return;
+ 	if (xprt_connected(xprt))
+-		goto out_write;
++		xprt_release_write(xprt, task);
++	else {
++		if (task->tk_rqstp)
++			task->tk_rqstp->rq_bytes_sent = 0;
+ 
+-	if (task->tk_rqstp)
+-		task->tk_rqstp->rq_bytes_sent = 0;
+-
+-	task->tk_timeout = RPC_CONNECT_TIMEOUT;
+-	rpc_sleep_on(&xprt->pending, task, xprt_connect_status, NULL);
+-	if (!test_and_set_bit(XPRT_CONNECTING, &xprt->sockstate)) {
+-		/* Note: if we are here due to a dropped connection
+-		 * 	 we delay reconnecting by RPC_REESTABLISH_TIMEOUT/HZ
+-		 * 	 seconds
+-		 */
+-		if (xprt->sock != NULL)
+-			schedule_delayed_work(&xprt->sock_connect,
+-					RPC_REESTABLISH_TIMEOUT);
+-		else {
+-			schedule_work(&xprt->sock_connect);
+-			if (!RPC_IS_ASYNC(task))
+-				flush_scheduled_work();
+-		}
++		task->tk_timeout = RPC_CONNECT_TIMEOUT;
++		rpc_sleep_on(&xprt->pending, task, xprt_connect_status, NULL);
++		xprt->ops->connect(task);
+ 	}
+ 	return;
+- out_write:
+-	xprt_release_write(xprt, task);
+ }
+ 
+ /*
+@@ -624,8 +407,7 @@ xprt_connect_status(struct rpc_task *task)
+ /*
+  * Look up the RPC request corresponding to a reply, and then lock it.
+  */
+-static inline struct rpc_rqst *
+-xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid)
++struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid)
+ {
+ 	struct list_head *pos;
+ 	struct rpc_rqst	*req = NULL;
+@@ -644,8 +426,7 @@ xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid)
+  * Complete reply received.
+  * The TCP code relies on us to remove the request from xprt->pending.
+  */
+-static void
+-xprt_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied)
++void xprt_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied)
+ {
+ 	struct rpc_task	*task = req->rq_task;
+ 	struct rpc_clnt *clnt = task->tk_client;
+@@ -691,409 +472,6 @@ xprt_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied)
+ 	return;
+ }
+ 
+-/*
+- * Input handler for RPC replies. Called from a bottom half and hence
+- * atomic.
+- */
+-static void
+-udp_data_ready(struct sock *sk, int len)
+-{
+-	struct rpc_task	*task;
+-	struct rpc_xprt	*xprt;
+-	struct rpc_rqst *rovr;
+-	struct sk_buff	*skb;
+-	int err, repsize, copied;
+-	u32 _xid, *xp;
+-
+-	read_lock(&sk->sk_callback_lock);
+-	dprintk("RPC:      udp_data_ready...\n");
+-	if (!(xprt = xprt_from_sock(sk))) {
+-		printk("RPC:      udp_data_ready request not found!\n");
+-		goto out;
+-	}
+-
+-	dprintk("RPC:      udp_data_ready client %p\n", xprt);
+-
+-	if ((skb = skb_recv_datagram(sk, 0, 1, &err)) == NULL)
+-		goto out;
+-
+-	if (xprt->shutdown)
+-		goto dropit;
+-
+-	repsize = skb->len - sizeof(struct udphdr);
+-	if (repsize < 4) {
+-		printk("RPC: impossible RPC reply size %d!\n", repsize);
+-		goto dropit;
+-	}
+-
+-	/* Copy the XID from the skb... */
+-	xp = skb_header_pointer(skb, sizeof(struct udphdr),
+-				sizeof(_xid), &_xid);
+-	if (xp == NULL)
+-		goto dropit;
+-
+-	/* Look up and lock the request corresponding to the given XID */
+-	spin_lock(&xprt->sock_lock);
+-	rovr = xprt_lookup_rqst(xprt, *xp);
+-	if (!rovr)
+-		goto out_unlock;
+-	task = rovr->rq_task;
+-
+-	dprintk("RPC: %4d received reply\n", task->tk_pid);
+-
+-	if ((copied = rovr->rq_private_buf.buflen) > repsize)
+-		copied = repsize;
+-
+-	/* Suck it into the iovec, verify checksum if not done by hw. */
+-	if (csum_partial_copy_to_xdr(&rovr->rq_private_buf, skb))
+-		goto out_unlock;
+-
+-	/* Something worked... */
+-	dst_confirm(skb->dst);
+-
+-	xprt_complete_rqst(xprt, rovr, copied);
+-
+- out_unlock:
+-	spin_unlock(&xprt->sock_lock);
+- dropit:
+-	skb_free_datagram(sk, skb);
+- out:
+-	read_unlock(&sk->sk_callback_lock);
+-}
+-
+-/*
+- * Copy from an skb into memory and shrink the skb.
+- */
+-static inline size_t
+-tcp_copy_data(skb_reader_t *desc, void *p, size_t len)
+-{
+-	if (len > desc->count)
+-		len = desc->count;
+-	if (skb_copy_bits(desc->skb, desc->offset, p, len)) {
+-		dprintk("RPC:      failed to copy %zu bytes from skb. %zu bytes remain\n",
+-				len, desc->count);
+-		return 0;
+-	}
+-	desc->offset += len;
+-	desc->count -= len;
+-	dprintk("RPC:      copied %zu bytes from skb. %zu bytes remain\n",
+-			len, desc->count);
+-	return len;
+-}
+-
+-/*
+- * TCP read fragment marker
+- */
+-static inline void
+-tcp_read_fraghdr(struct rpc_xprt *xprt, skb_reader_t *desc)
+-{
+-	size_t len, used;
+-	char *p;
+-
+-	p = ((char *) &xprt->tcp_recm) + xprt->tcp_offset;
+-	len = sizeof(xprt->tcp_recm) - xprt->tcp_offset;
+-	used = tcp_copy_data(desc, p, len);
+-	xprt->tcp_offset += used;
+-	if (used != len)
+-		return;
+-	xprt->tcp_reclen = ntohl(xprt->tcp_recm);
+-	if (xprt->tcp_reclen & 0x80000000)
+-		xprt->tcp_flags |= XPRT_LAST_FRAG;
+-	else
+-		xprt->tcp_flags &= ~XPRT_LAST_FRAG;
+-	xprt->tcp_reclen &= 0x7fffffff;
+-	xprt->tcp_flags &= ~XPRT_COPY_RECM;
+-	xprt->tcp_offset = 0;
+-	/* Sanity check of the record length */
+-	if (xprt->tcp_reclen < 4) {
+-		printk(KERN_ERR "RPC: Invalid TCP record fragment length\n");
+-		xprt_disconnect(xprt);
+-	}
+-	dprintk("RPC:      reading TCP record fragment of length %d\n",
+-			xprt->tcp_reclen);
+-}
+-
+-static void
+-tcp_check_recm(struct rpc_xprt *xprt)
+-{
+-	dprintk("RPC:      xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u, tcp_flags = %lx\n",
+-			xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen, xprt->tcp_flags);
+-	if (xprt->tcp_offset == xprt->tcp_reclen) {
+-		xprt->tcp_flags |= XPRT_COPY_RECM;
+-		xprt->tcp_offset = 0;
+-		if (xprt->tcp_flags & XPRT_LAST_FRAG) {
+-			xprt->tcp_flags &= ~XPRT_COPY_DATA;
+-			xprt->tcp_flags |= XPRT_COPY_XID;
+-			xprt->tcp_copied = 0;
+-		}
+-	}
+-}
+-
+-/*
+- * TCP read xid
+- */
+-static inline void
+-tcp_read_xid(struct rpc_xprt *xprt, skb_reader_t *desc)
+-{
+-	size_t len, used;
+-	char *p;
+-
+-	len = sizeof(xprt->tcp_xid) - xprt->tcp_offset;
+-	dprintk("RPC:      reading XID (%Zu bytes)\n", len);
+-	p = ((char *) &xprt->tcp_xid) + xprt->tcp_offset;
+-	used = tcp_copy_data(desc, p, len);
+-	xprt->tcp_offset += used;
+-	if (used != len)
+-		return;
+-	xprt->tcp_flags &= ~XPRT_COPY_XID;
+-	xprt->tcp_flags |= XPRT_COPY_DATA;
+-	xprt->tcp_copied = 4;
+-	dprintk("RPC:      reading reply for XID %08x\n",
+-						ntohl(xprt->tcp_xid));
+-	tcp_check_recm(xprt);
+-}
+-
+-/*
+- * TCP read and complete request
+- */
+-static inline void
+-tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc)
+-{
+-	struct rpc_rqst *req;
+-	struct xdr_buf *rcvbuf;
+-	size_t len;
+-	ssize_t r;
+-
+-	/* Find and lock the request corresponding to this xid */
+-	spin_lock(&xprt->sock_lock);
+-	req = xprt_lookup_rqst(xprt, xprt->tcp_xid);
+-	if (!req) {
+-		xprt->tcp_flags &= ~XPRT_COPY_DATA;
+-		dprintk("RPC:      XID %08x request not found!\n",
+-				ntohl(xprt->tcp_xid));
+-		spin_unlock(&xprt->sock_lock);
+-		return;
+-	}
+-
+-	rcvbuf = &req->rq_private_buf;
+-	len = desc->count;
+-	if (len > xprt->tcp_reclen - xprt->tcp_offset) {
+-		skb_reader_t my_desc;
+-
+-		len = xprt->tcp_reclen - xprt->tcp_offset;
+-		memcpy(&my_desc, desc, sizeof(my_desc));
+-		my_desc.count = len;
+-		r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
+-					  &my_desc, tcp_copy_data);
+-		desc->count -= r;
+-		desc->offset += r;
+-	} else
+-		r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
+-					  desc, tcp_copy_data);
+-
+-	if (r > 0) {
+-		xprt->tcp_copied += r;
+-		xprt->tcp_offset += r;
+-	}
+-	if (r != len) {
+-		/* Error when copying to the receive buffer,
+-		 * usually because we weren't able to allocate
+-		 * additional buffer pages. All we can do now
+-		 * is turn off XPRT_COPY_DATA, so the request
+-		 * will not receive any additional updates,
+-		 * and time out.
+-		 * Any remaining data from this record will
+-		 * be discarded.
+-		 */
+-		xprt->tcp_flags &= ~XPRT_COPY_DATA;
+-		dprintk("RPC:      XID %08x truncated request\n",
+-				ntohl(xprt->tcp_xid));
+-		dprintk("RPC:      xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u\n",
+-				xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen);
+-		goto out;
+-	}
+-
+-	dprintk("RPC:      XID %08x read %Zd bytes\n",
+-			ntohl(xprt->tcp_xid), r);
+-	dprintk("RPC:      xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u\n",
+-			xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen);
+-
+-	if (xprt->tcp_copied == req->rq_private_buf.buflen)
+-		xprt->tcp_flags &= ~XPRT_COPY_DATA;
+-	else if (xprt->tcp_offset == xprt->tcp_reclen) {
+-		if (xprt->tcp_flags & XPRT_LAST_FRAG)
+-			xprt->tcp_flags &= ~XPRT_COPY_DATA;
+-	}
+-
+-out:
+-	if (!(xprt->tcp_flags & XPRT_COPY_DATA)) {
+-		dprintk("RPC: %4d received reply complete\n",
+-				req->rq_task->tk_pid);
+-		xprt_complete_rqst(xprt, req, xprt->tcp_copied);
+-	}
+-	spin_unlock(&xprt->sock_lock);
+-	tcp_check_recm(xprt);
+-}
+-
+-/*
+- * TCP discard extra bytes from a short read
+- */
+-static inline void
+-tcp_read_discard(struct rpc_xprt *xprt, skb_reader_t *desc)
+-{
+-	size_t len;
+-
+-	len = xprt->tcp_reclen - xprt->tcp_offset;
+-	if (len > desc->count)
+-		len = desc->count;
+-	desc->count -= len;
+-	desc->offset += len;
+-	xprt->tcp_offset += len;
+-	dprintk("RPC:      discarded %Zu bytes\n", len);
+-	tcp_check_recm(xprt);
+-}
+-
+-/*
+- * TCP record receive routine
+- * We first have to grab the record marker, then the XID, then the data.
+- */
+-static int
+-tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+-		unsigned int offset, size_t len)
+-{
+-	struct rpc_xprt *xprt = rd_desc->arg.data;
+-	skb_reader_t desc = {
+-		.skb	= skb,
+-		.offset	= offset,
+-		.count	= len,
+-		.csum	= 0
+-       	};
+-
+-	dprintk("RPC:      tcp_data_recv\n");
+-	do {
+-		/* Read in a new fragment marker if necessary */
+-		/* Can we ever really expect to get completely empty fragments? */
+-		if (xprt->tcp_flags & XPRT_COPY_RECM) {
+-			tcp_read_fraghdr(xprt, &desc);
+-			continue;
+-		}
+-		/* Read in the xid if necessary */
+-		if (xprt->tcp_flags & XPRT_COPY_XID) {
+-			tcp_read_xid(xprt, &desc);
+-			continue;
+-		}
+-		/* Read in the request data */
+-		if (xprt->tcp_flags & XPRT_COPY_DATA) {
+-			tcp_read_request(xprt, &desc);
+-			continue;
+-		}
+-		/* Skip over any trailing bytes on short reads */
+-		tcp_read_discard(xprt, &desc);
+-	} while (desc.count);
+-	dprintk("RPC:      tcp_data_recv done\n");
+-	return len - desc.count;
+-}
+-
+-static void tcp_data_ready(struct sock *sk, int bytes)
+-{
+-	struct rpc_xprt *xprt;
+-	read_descriptor_t rd_desc;
+-
+-	read_lock(&sk->sk_callback_lock);
+-	dprintk("RPC:      tcp_data_ready...\n");
+-	if (!(xprt = xprt_from_sock(sk))) {
+-		printk("RPC:      tcp_data_ready socket info not found!\n");
+-		goto out;
+-	}
+-	if (xprt->shutdown)
+-		goto out;
+-
+-	/* We use rd_desc to pass struct xprt to tcp_data_recv */
+-	rd_desc.arg.data = xprt;
+-	rd_desc.count = 65536;
+-	tcp_read_sock(sk, &rd_desc, tcp_data_recv);
+-out:
+-	read_unlock(&sk->sk_callback_lock);
+-}
+-
+-static void
+-tcp_state_change(struct sock *sk)
+-{
+-	struct rpc_xprt	*xprt;
+-
+-	read_lock(&sk->sk_callback_lock);
+-	if (!(xprt = xprt_from_sock(sk)))
+-		goto out;
+-	dprintk("RPC:      tcp_state_change client %p...\n", xprt);
+-	dprintk("RPC:      state %x conn %d dead %d zapped %d\n",
+-				sk->sk_state, xprt_connected(xprt),
+-				sock_flag(sk, SOCK_DEAD),
+-				sock_flag(sk, SOCK_ZAPPED));
+-
+-	switch (sk->sk_state) {
+-	case TCP_ESTABLISHED:
+-		spin_lock_bh(&xprt->sock_lock);
+-		if (!xprt_test_and_set_connected(xprt)) {
+-			/* Reset TCP record info */
+-			xprt->tcp_offset = 0;
+-			xprt->tcp_reclen = 0;
+-			xprt->tcp_copied = 0;
+-			xprt->tcp_flags = XPRT_COPY_RECM | XPRT_COPY_XID;
+-			rpc_wake_up(&xprt->pending);
+-		}
+-		spin_unlock_bh(&xprt->sock_lock);
+-		break;
+-	case TCP_SYN_SENT:
+-	case TCP_SYN_RECV:
+-		break;
+-	default:
+-		xprt_disconnect(xprt);
+-		break;
+-	}
+- out:
+-	read_unlock(&sk->sk_callback_lock);
+-}
+-
+-/*
+- * Called when more output buffer space is available for this socket.
+- * We try not to wake our writers until they can make "significant"
+- * progress, otherwise we'll waste resources thrashing sock_sendmsg
+- * with a bunch of small requests.
+- */
+-static void
+-xprt_write_space(struct sock *sk)
+-{
+-	struct rpc_xprt	*xprt;
+-	struct socket	*sock;
+-
+-	read_lock(&sk->sk_callback_lock);
+-	if (!(xprt = xprt_from_sock(sk)) || !(sock = sk->sk_socket))
+-		goto out;
+-	if (xprt->shutdown)
+-		goto out;
+-
+-	/* Wait until we have enough socket memory */
+-	if (xprt->stream) {
+-		/* from net/core/stream.c:sk_stream_write_space */
+-		if (sk_stream_wspace(sk) < sk_stream_min_wspace(sk))
+-			goto out;
+-	} else {
+-		/* from net/core/sock.c:sock_def_write_space */
+-		if (!sock_writeable(sk))
+-			goto out;
+-	}
+-
+-	if (!test_and_clear_bit(SOCK_NOSPACE, &sock->flags))
+-		goto out;
+-
+-	spin_lock_bh(&xprt->sock_lock);
+-	if (xprt->snd_task)
+-		rpc_wake_up_task(xprt->snd_task);
+-	spin_unlock_bh(&xprt->sock_lock);
+-out:
+-	read_unlock(&sk->sk_callback_lock);
+-}
+-
+ /*
+  * RPC receive timeout handler.
+  */
+@@ -1161,19 +539,10 @@ xprt_transmit(struct rpc_task *task)
+ 	struct rpc_clnt *clnt = task->tk_client;
+ 	struct rpc_rqst	*req = task->tk_rqstp;
+ 	struct rpc_xprt	*xprt = req->rq_xprt;
+-	int status, retry = 0;
+-
++	int status;
+ 
+ 	dprintk("RPC: %4d xprt_transmit(%u)\n", task->tk_pid, req->rq_slen);
+ 
+-	/* set up everything as needed. */
+-	/* Write the record marker */
+-	if (xprt->stream) {
+-		u32	*marker = req->rq_svec[0].iov_base;
+-
+-		*marker = htonl(0x80000000|(req->rq_slen-sizeof(*marker)));
+-	}
+-
+ 	smp_rmb();
+ 	if (!req->rq_received) {
+ 		if (list_empty(&req->rq_list)) {
+@@ -1191,41 +560,9 @@ xprt_transmit(struct rpc_task *task)
+ 	} else if (!req->rq_bytes_sent)
+ 		return;
+ 
+-	/* Continue transmitting the packet/record. We must be careful
+-	 * to cope with writespace callbacks arriving _after_ we have
+-	 * called xprt_sendmsg().
+-	 */
+-	while (1) {
+-		req->rq_xtime = jiffies;
+-		status = xprt_sendmsg(xprt, req);
+-
+-		if (status < 0)
+-			break;
+-
+-		if (xprt->stream) {
+-			req->rq_bytes_sent += status;
+-
+-			/* If we've sent the entire packet, immediately
+-			 * reset the count of bytes sent. */
+-			if (req->rq_bytes_sent >= req->rq_slen) {
+-				req->rq_bytes_sent = 0;
+-				goto out_receive;
+-			}
+-		} else {
+-			if (status >= req->rq_slen)
+-				goto out_receive;
+-			status = -EAGAIN;
+-			break;
+-		}
+-
+-		dprintk("RPC: %4d xmit incomplete (%d left of %d)\n",
+-				task->tk_pid, req->rq_slen - req->rq_bytes_sent,
+-				req->rq_slen);
+-
+-		status = -EAGAIN;
+-		if (retry++ > 50)
+-			break;
+-	}
++	status = xprt->ops->send_request(task);
++	if (!status)
++		goto out_receive;
+ 
+ 	/* Note: at this point, task->tk_sleeping has not yet been set,
+ 	 *	 hence there is no danger of the waking up task being put on
+@@ -1234,26 +571,10 @@ xprt_transmit(struct rpc_task *task)
+ 	task->tk_status = status;
+ 
+ 	switch (status) {
+-	case -EAGAIN:
+-		if (test_bit(SOCK_ASYNC_NOSPACE, &xprt->sock->flags)) {
+-			/* Protect against races with xprt_write_space */
+-			spin_lock_bh(&xprt->sock_lock);
+-			/* Don't race with disconnect */
+-			if (!xprt_connected(xprt))
+-				task->tk_status = -ENOTCONN;
+-			else if (test_bit(SOCK_NOSPACE, &xprt->sock->flags)) {
+-				task->tk_timeout = req->rq_timeout;
+-				rpc_sleep_on(&xprt->pending, task, NULL, NULL);
+-			}
+-			spin_unlock_bh(&xprt->sock_lock);
+-			return;
+-		}
+-		/* Keep holding the socket if it is blocked */
+-		rpc_delay(task, HZ>>4);
+-		return;
+ 	case -ECONNREFUSED:
+ 		task->tk_timeout = RPC_REESTABLISH_TIMEOUT;
+ 		rpc_sleep_on(&xprt->sending, task, NULL, NULL);
++	case -EAGAIN:
+ 	case -ENOTCONN:
+ 		return;
+ 	default:
+@@ -1367,7 +688,8 @@ xprt_release(struct rpc_task *task)
+ 		list_del(&req->rq_list);
+ 	xprt->last_used = jiffies;
+ 	if (list_empty(&xprt->recv) && !xprt->shutdown)
+-		mod_timer(&xprt->timer, xprt->last_used + XPRT_IDLE_TIMEOUT);
++		mod_timer(&xprt->timer,
++				xprt->last_used + RPC_IDLE_DISCONNECT_TIMEOUT);
+ 	spin_unlock_bh(&xprt->sock_lock);
+ 	task->tk_rqstp = NULL;
+ 	memset(req, 0, sizeof(*req));	/* mark unused */
+@@ -1380,18 +702,6 @@ xprt_release(struct rpc_task *task)
+ 	spin_unlock(&xprt->xprt_lock);
+ }
+ 
+-/*
+- * Set default timeout parameters
+- */
+-static void
+-xprt_default_timeout(struct rpc_timeout *to, int proto)
+-{
+-	if (proto == IPPROTO_UDP)
+-		xprt_set_timeout(to, 5,  5 * HZ);
+-	else
+-		xprt_set_timeout(to, 2, 60 * HZ);
+-}
+-
+ /*
+  * Set constant timeout
+  */
+@@ -1405,68 +715,51 @@ xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr)
+ 	to->to_exponential = 0;
+ }
+ 
+-unsigned int xprt_udp_slot_table_entries = RPC_DEF_SLOT_TABLE;
+-unsigned int xprt_tcp_slot_table_entries = RPC_DEF_SLOT_TABLE;
+-
+ /*
+  * Initialize an RPC client
+  */
+ static struct rpc_xprt *
+ xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to)
+ {
++	int result;
+ 	struct rpc_xprt	*xprt;
+-	unsigned int entries;
+-	size_t slot_table_size;
+ 	struct rpc_rqst	*req;
+ 
+-	dprintk("RPC:      setting up %s transport...\n",
+-				proto == IPPROTO_UDP? "UDP" : "TCP");
+-
+-	entries = (proto == IPPROTO_TCP)?
+-		xprt_tcp_slot_table_entries : xprt_udp_slot_table_entries;
+-
+ 	if ((xprt = kmalloc(sizeof(struct rpc_xprt), GFP_KERNEL)) == NULL)
+ 		return ERR_PTR(-ENOMEM);
+ 	memset(xprt, 0, sizeof(*xprt)); /* Nnnngh! */
+-	xprt->max_reqs = entries;
+-	slot_table_size = entries * sizeof(xprt->slot[0]);
+-	xprt->slot = kmalloc(slot_table_size, GFP_KERNEL);
+-	if (xprt->slot == NULL) {
+-		kfree(xprt);
+-		return ERR_PTR(-ENOMEM);
+-	}
+-	memset(xprt->slot, 0, slot_table_size);
+ 
+ 	xprt->addr = *ap;
+-	xprt->prot = proto;
+-	xprt->stream = (proto == IPPROTO_TCP)? 1 : 0;
+-	if (xprt->stream) {
+-		xprt->cwnd = RPC_MAXCWND(xprt);
+-		xprt->nocong = 1;
+-		xprt->max_payload = (1U << 31) - 1;
+-	} else {
+-		xprt->cwnd = RPC_INITCWND;
+-		xprt->max_payload = (1U << 16) - (MAX_HEADER << 3);
++
++	switch (proto) {
++	case IPPROTO_UDP:
++		result = xs_setup_udp(xprt, to);
++		break;
++	case IPPROTO_TCP:
++		result = xs_setup_tcp(xprt, to);
++		break;
++	default:
++		printk(KERN_ERR "RPC: unrecognized transport protocol: %d\n",
++				proto);
++		result = -EIO;
++		break;
++	}
++	if (result) {
++		kfree(xprt);
++		return ERR_PTR(result);
+ 	}
++
+ 	spin_lock_init(&xprt->sock_lock);
+ 	spin_lock_init(&xprt->xprt_lock);
+ 	init_waitqueue_head(&xprt->cong_wait);
+ 
+ 	INIT_LIST_HEAD(&xprt->free);
+ 	INIT_LIST_HEAD(&xprt->recv);
+-	INIT_WORK(&xprt->sock_connect, xprt_socket_connect, xprt);
+ 	INIT_WORK(&xprt->task_cleanup, xprt_socket_autoclose, xprt);
+ 	init_timer(&xprt->timer);
+ 	xprt->timer.function = xprt_init_autodisconnect;
+ 	xprt->timer.data = (unsigned long) xprt;
+ 	xprt->last_used = jiffies;
+-	xprt->port = XPRT_MAX_RESVPORT;
+-
+-	/* Set timeout parameters */
+-	if (to) {
+-		xprt->timeout = *to;
+-	} else
+-		xprt_default_timeout(&xprt->timeout, xprt->prot);
+ 
+ 	rpc_init_wait_queue(&xprt->pending, "xprt_pending");
+ 	rpc_init_wait_queue(&xprt->sending, "xprt_sending");
+@@ -1474,134 +767,17 @@ xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to)
+ 	rpc_init_priority_wait_queue(&xprt->backlog, "xprt_backlog");
+ 
+ 	/* initialize free list */
+-	for (req = &xprt->slot[entries-1]; req >= &xprt->slot[0]; req--)
++	for (req = &xprt->slot[xprt->max_reqs-1]; req >= &xprt->slot[0]; req--)
+ 		list_add(&req->rq_list, &xprt->free);
+ 
+ 	xprt_init_xid(xprt);
+ 
+-	/* Check whether we want to use a reserved port */
+-	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
+-
+ 	dprintk("RPC:      created transport %p with %u slots\n", xprt,
+ 			xprt->max_reqs);
+ 	
+ 	return xprt;
+ }
+ 
+-/*
+- * Bind to a reserved port
+- */
+-static inline int xprt_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
+-{
+-	struct sockaddr_in myaddr = {
+-		.sin_family = AF_INET,
+-	};
+-	int		err, port;
+-
+-	/* Were we already bound to a given port? Try to reuse it */
+-	port = xprt->port;
+-	do {
+-		myaddr.sin_port = htons(port);
+-		err = sock->ops->bind(sock, (struct sockaddr *) &myaddr,
+-						sizeof(myaddr));
+-		if (err == 0) {
+-			xprt->port = port;
+-			return 0;
+-		}
+-		if (--port == 0)
+-			port = XPRT_MAX_RESVPORT;
+-	} while (err == -EADDRINUSE && port != xprt->port);
+-
+-	printk("RPC: Can't bind to reserved port (%d).\n", -err);
+-	return err;
+-}
+-
+-static void
+-xprt_bind_socket(struct rpc_xprt *xprt, struct socket *sock)
+-{
+-	struct sock	*sk = sock->sk;
+-
+-	if (xprt->inet)
+-		return;
+-
+-	write_lock_bh(&sk->sk_callback_lock);
+-	sk->sk_user_data = xprt;
+-	xprt->old_data_ready = sk->sk_data_ready;
+-	xprt->old_state_change = sk->sk_state_change;
+-	xprt->old_write_space = sk->sk_write_space;
+-	if (xprt->prot == IPPROTO_UDP) {
+-		sk->sk_data_ready = udp_data_ready;
+-		sk->sk_no_check = UDP_CSUM_NORCV;
+-		xprt_set_connected(xprt);
+-	} else {
+-		tcp_sk(sk)->nonagle = 1;	/* disable Nagle's algorithm */
+-		sk->sk_data_ready = tcp_data_ready;
+-		sk->sk_state_change = tcp_state_change;
+-		xprt_clear_connected(xprt);
+-	}
+-	sk->sk_write_space = xprt_write_space;
+-
+-	/* Reset to new socket */
+-	xprt->sock = sock;
+-	xprt->inet = sk;
+-	write_unlock_bh(&sk->sk_callback_lock);
+-
+-	return;
+-}
+-
+-/*
+- * Set socket buffer length
+- */
+-void
+-xprt_sock_setbufsize(struct rpc_xprt *xprt)
+-{
+-	struct sock *sk = xprt->inet;
+-
+-	if (xprt->stream)
+-		return;
+-	if (xprt->rcvsize) {
+-		sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
+-		sk->sk_rcvbuf = xprt->rcvsize * xprt->max_reqs *  2;
+-	}
+-	if (xprt->sndsize) {
+-		sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
+-		sk->sk_sndbuf = xprt->sndsize * xprt->max_reqs * 2;
+-		sk->sk_write_space(sk);
+-	}
+-}
+-
+-/*
+- * Datastream sockets are created here, but xprt_connect will create
+- * and connect stream sockets.
+- */
+-static struct socket * xprt_create_socket(struct rpc_xprt *xprt, int proto, int resvport)
+-{
+-	struct socket	*sock;
+-	int		type, err;
+-
+-	dprintk("RPC:      xprt_create_socket(%s %d)\n",
+-			   (proto == IPPROTO_UDP)? "udp" : "tcp", proto);
+-
+-	type = (proto == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
+-
+-	if ((err = sock_create_kern(PF_INET, type, proto, &sock)) < 0) {
+-		printk("RPC: can't create socket (%d).\n", -err);
+-		return NULL;
+-	}
+-
+-	/* If the caller has the capability, bind to a reserved port */
+-	if (resvport && xprt_bindresvport(xprt, sock) < 0) {
+-		printk("RPC: can't bind to reserved port.\n");
+-		goto failed;
+-	}
+-
+-	return sock;
+-
+-failed:
+-	sock_release(sock);
+-	return NULL;
+-}
+-
+ /*
+  * Create an RPC client transport given the protocol and peer address.
+  */
+@@ -1631,10 +807,6 @@ xprt_shutdown(struct rpc_xprt *xprt)
+ 	rpc_wake_up(&xprt->backlog);
+ 	wake_up(&xprt->cong_wait);
+ 	del_timer_sync(&xprt->timer);
+-
+-	/* synchronously wait for connect worker to finish */
+-	cancel_delayed_work(&xprt->sock_connect);
+-	flush_scheduled_work();
+ }
+ 
+ /*
+@@ -1655,9 +827,7 @@ xprt_destroy(struct rpc_xprt *xprt)
+ {
+ 	dprintk("RPC:      destroying transport %p\n", xprt);
+ 	xprt_shutdown(xprt);
+-	xprt_disconnect(xprt);
+-	xprt_close(xprt);
+-	kfree(xprt->slot);
++	xprt->ops->destroy(xprt);
+ 	kfree(xprt);
+ 
+ 	return 0;
+diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
+new file mode 100644
+index 000000000000..fa1180ac4823
+--- /dev/null
++++ b/net/sunrpc/xprtsock.c
+@@ -0,0 +1,1021 @@
++/*
++ * linux/net/sunrpc/xprtsock.c
++ *
++ * Client-side transport implementation for sockets.
++ *
++ * TCP callback races fixes (C) 1998 Red Hat Software 
++ * TCP send fixes (C) 1998 Red Hat Software 
++ * TCP NFS related read + write fixes
++ *  (C) 1999 Dave Airlie, University of Limerick, Ireland 
++ *
++ * Rewrite of larges part of the code in order to stabilize TCP stuff.
++ * Fix behaviour when socket buffer is full.
++ *  (C) 1999 Trond Myklebust 
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++#include 
++#include 
++#include 
++
++#ifdef RPC_DEBUG
++# undef  RPC_DEBUG_DATA
++# define RPCDBG_FACILITY	RPCDBG_XPRT
++#endif
++
++#define XPRT_MAX_RESVPORT	(800)
++
++#ifdef RPC_DEBUG_DATA
++/*
++ * Print the buffer contents (first 128 bytes only--just enough for
++ * diropres return).
++ */
++static void
++xprt_pktdump(char *msg, u32 *packet, unsigned int count)
++{
++	u8	*buf = (u8 *) packet;
++	int	j;
++
++	dprintk("RPC:      %s\n", msg);
++	for (j = 0; j < count && j < 128; j += 4) {
++		if (!(j & 31)) {
++			if (j)
++				dprintk("\n");
++			dprintk("0x%04x ", j);
++		}
++		dprintk("%02x%02x%02x%02x ",
++			buf[j], buf[j+1], buf[j+2], buf[j+3]);
++	}
++	dprintk("\n");
++}
++#else
++static inline void
++xprt_pktdump(char *msg, u32 *packet, unsigned int count)
++{
++	/* NOP */
++}
++#endif
++
++/*
++ * Look up RPC transport given an INET socket
++ */
++static inline struct rpc_xprt *
++xprt_from_sock(struct sock *sk)
++{
++	return (struct rpc_xprt *) sk->sk_user_data;
++}
++
++static int
++xdr_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
++		struct xdr_buf *xdr, unsigned int base, int msgflags)
++{
++	struct page **ppage = xdr->pages;
++	unsigned int len, pglen = xdr->page_len;
++	int err, ret = 0;
++	ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
++
++	len = xdr->head[0].iov_len;
++	if (base < len || (addr != NULL && base == 0)) {
++		struct kvec iov = {
++			.iov_base = xdr->head[0].iov_base + base,
++			.iov_len  = len - base,
++		};
++		struct msghdr msg = {
++			.msg_name    = addr,
++			.msg_namelen = addrlen,
++			.msg_flags   = msgflags,
++		};
++		if (xdr->len > len)
++			msg.msg_flags |= MSG_MORE;
++
++		if (iov.iov_len != 0)
++			err = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
++		else
++			err = kernel_sendmsg(sock, &msg, NULL, 0, 0);
++		if (ret == 0)
++			ret = err;
++		else if (err > 0)
++			ret += err;
++		if (err != iov.iov_len)
++			goto out;
++		base = 0;
++	} else
++		base -= len;
++
++	if (pglen == 0)
++		goto copy_tail;
++	if (base >= pglen) {
++		base -= pglen;
++		goto copy_tail;
++	}
++	if (base || xdr->page_base) {
++		pglen -= base;
++		base  += xdr->page_base;
++		ppage += base >> PAGE_CACHE_SHIFT;
++		base &= ~PAGE_CACHE_MASK;
++	}
++
++	sendpage = sock->ops->sendpage ? : sock_no_sendpage;
++	do {
++		int flags = msgflags;
++
++		len = PAGE_CACHE_SIZE;
++		if (base)
++			len -= base;
++		if (pglen < len)
++			len = pglen;
++
++		if (pglen != len || xdr->tail[0].iov_len != 0)
++			flags |= MSG_MORE;
++
++		/* Hmm... We might be dealing with highmem pages */
++		if (PageHighMem(*ppage))
++			sendpage = sock_no_sendpage;
++		err = sendpage(sock, *ppage, base, len, flags);
++		if (ret == 0)
++			ret = err;
++		else if (err > 0)
++			ret += err;
++		if (err != len)
++			goto out;
++		base = 0;
++		ppage++;
++	} while ((pglen -= len) != 0);
++copy_tail:
++	len = xdr->tail[0].iov_len;
++	if (base < len) {
++		struct kvec iov = {
++			.iov_base = xdr->tail[0].iov_base + base,
++			.iov_len  = len - base,
++		};
++		struct msghdr msg = {
++			.msg_flags   = msgflags,
++		};
++		err = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
++		if (ret == 0)
++			ret = err;
++		else if (err > 0)
++			ret += err;
++	}
++out:
++	return ret;
++}
++
++/*
++ * Write data to socket.
++ */
++static inline int
++xprt_sendmsg(struct rpc_xprt *xprt, struct rpc_rqst *req)
++{
++	struct socket	*sock = xprt->sock;
++	struct xdr_buf	*xdr = &req->rq_snd_buf;
++	struct sockaddr *addr = NULL;
++	int addrlen = 0;
++	unsigned int	skip;
++	int		result;
++
++	if (!sock)
++		return -ENOTCONN;
++
++	xprt_pktdump("packet data:",
++				req->rq_svec->iov_base,
++				req->rq_svec->iov_len);
++
++	/* For UDP, we need to provide an address */
++	if (!xprt->stream) {
++		addr = (struct sockaddr *) &xprt->addr;
++		addrlen = sizeof(xprt->addr);
++	}
++	/* Dont repeat bytes */
++	skip = req->rq_bytes_sent;
++
++	clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
++	result = xdr_sendpages(sock, addr, addrlen, xdr, skip, MSG_DONTWAIT);
++
++	dprintk("RPC:      xprt_sendmsg(%d) = %d\n", xdr->len - skip, result);
++
++	if (result >= 0)
++		return result;
++
++	switch (result) {
++	case -ECONNREFUSED:
++		/* When the server has died, an ICMP port unreachable message
++		 * prompts ECONNREFUSED.
++		 */
++	case -EAGAIN:
++		break;
++	case -ECONNRESET:
++	case -ENOTCONN:
++	case -EPIPE:
++		/* connection broken */
++		if (xprt->stream)
++			result = -ENOTCONN;
++		break;
++	default:
++		printk(KERN_NOTICE "RPC: sendmsg returned error %d\n", -result);
++	}
++	return result;
++}
++
++static int
++xprt_send_request(struct rpc_task *task)
++{
++	struct rpc_rqst *req = task->tk_rqstp;
++	struct rpc_xprt *xprt = req->rq_xprt;
++	int status, retry = 0;
++
++	/* set up everything as needed. */
++	/* Write the record marker */
++	if (xprt->stream) {
++		u32	*marker = req->rq_svec[0].iov_base;
++
++		*marker = htonl(0x80000000|(req->rq_slen-sizeof(*marker)));
++	}
++
++	/* Continue transmitting the packet/record. We must be careful
++	 * to cope with writespace callbacks arriving _after_ we have
++	 * called xprt_sendmsg().
++	 */
++	while (1) {
++		req->rq_xtime = jiffies;
++		status = xprt_sendmsg(xprt, req);
++
++		if (status < 0)
++			break;
++
++		if (xprt->stream) {
++			req->rq_bytes_sent += status;
++
++			/* If we've sent the entire packet, immediately
++			 * reset the count of bytes sent. */
++			if (req->rq_bytes_sent >= req->rq_slen) {
++				req->rq_bytes_sent = 0;
++				return 0;
++			}
++		} else {
++			if (status >= req->rq_slen)
++				return 0;
++			status = -EAGAIN;
++			break;
++		}
++
++		dprintk("RPC: %4d xmit incomplete (%d left of %d)\n",
++				task->tk_pid, req->rq_slen - req->rq_bytes_sent,
++				req->rq_slen);
++
++		status = -EAGAIN;
++		if (retry++ > 50)
++			break;
++	}
++
++	if (status == -EAGAIN) {
++		if (test_bit(SOCK_ASYNC_NOSPACE, &xprt->sock->flags)) {
++			/* Protect against races with xprt_write_space */
++			spin_lock_bh(&xprt->sock_lock);
++			/* Don't race with disconnect */
++			if (!xprt_connected(xprt))
++				task->tk_status = -ENOTCONN;
++			else if (test_bit(SOCK_NOSPACE, &xprt->sock->flags)) {
++				task->tk_timeout = req->rq_timeout;
++				rpc_sleep_on(&xprt->pending, task, NULL, NULL);
++			}
++			spin_unlock_bh(&xprt->sock_lock);
++			return status;
++		}
++		/* Keep holding the socket if it is blocked */
++		rpc_delay(task, HZ>>4);
++	}
++	return status;
++}
++
++/*
++ * Close down a transport socket
++ */
++static void
++xprt_close(struct rpc_xprt *xprt)
++{
++	struct socket	*sock = xprt->sock;
++	struct sock	*sk = xprt->inet;
++
++	if (!sk)
++		return;
++
++	write_lock_bh(&sk->sk_callback_lock);
++	xprt->inet = NULL;
++	xprt->sock = NULL;
++
++	sk->sk_user_data    = NULL;
++	sk->sk_data_ready   = xprt->old_data_ready;
++	sk->sk_state_change = xprt->old_state_change;
++	sk->sk_write_space  = xprt->old_write_space;
++	write_unlock_bh(&sk->sk_callback_lock);
++
++	sk->sk_no_check	 = 0;
++
++	sock_release(sock);
++}
++
++static void xprt_socket_destroy(struct rpc_xprt *xprt)
++{
++	cancel_delayed_work(&xprt->sock_connect);
++	flush_scheduled_work();
++
++	xprt_disconnect(xprt);
++	xprt_close(xprt);
++	kfree(xprt->slot);
++}
++
++/*
++ * Input handler for RPC replies. Called from a bottom half and hence
++ * atomic.
++ */
++static void
++udp_data_ready(struct sock *sk, int len)
++{
++	struct rpc_task	*task;
++	struct rpc_xprt	*xprt;
++	struct rpc_rqst *rovr;
++	struct sk_buff	*skb;
++	int err, repsize, copied;
++	u32 _xid, *xp;
++
++	read_lock(&sk->sk_callback_lock);
++	dprintk("RPC:      udp_data_ready...\n");
++	if (!(xprt = xprt_from_sock(sk))) {
++		printk("RPC:      udp_data_ready request not found!\n");
++		goto out;
++	}
++
++	dprintk("RPC:      udp_data_ready client %p\n", xprt);
++
++	if ((skb = skb_recv_datagram(sk, 0, 1, &err)) == NULL)
++		goto out;
++
++	if (xprt->shutdown)
++		goto dropit;
++
++	repsize = skb->len - sizeof(struct udphdr);
++	if (repsize < 4) {
++		printk("RPC: impossible RPC reply size %d!\n", repsize);
++		goto dropit;
++	}
++
++	/* Copy the XID from the skb... */
++	xp = skb_header_pointer(skb, sizeof(struct udphdr),
++				sizeof(_xid), &_xid);
++	if (xp == NULL)
++		goto dropit;
++
++	/* Look up and lock the request corresponding to the given XID */
++	spin_lock(&xprt->sock_lock);
++	rovr = xprt_lookup_rqst(xprt, *xp);
++	if (!rovr)
++		goto out_unlock;
++	task = rovr->rq_task;
++
++	dprintk("RPC: %4d received reply\n", task->tk_pid);
++
++	if ((copied = rovr->rq_private_buf.buflen) > repsize)
++		copied = repsize;
++
++	/* Suck it into the iovec, verify checksum if not done by hw. */
++	if (csum_partial_copy_to_xdr(&rovr->rq_private_buf, skb))
++		goto out_unlock;
++
++	/* Something worked... */
++	dst_confirm(skb->dst);
++
++	xprt_complete_rqst(xprt, rovr, copied);
++
++ out_unlock:
++	spin_unlock(&xprt->sock_lock);
++ dropit:
++	skb_free_datagram(sk, skb);
++ out:
++	read_unlock(&sk->sk_callback_lock);
++}
++
++/*
++ * Copy from an skb into memory and shrink the skb.
++ */
++static inline size_t
++tcp_copy_data(skb_reader_t *desc, void *p, size_t len)
++{
++	if (len > desc->count)
++		len = desc->count;
++	if (skb_copy_bits(desc->skb, desc->offset, p, len)) {
++		dprintk("RPC:      failed to copy %zu bytes from skb. %zu bytes remain\n",
++				len, desc->count);
++		return 0;
++	}
++	desc->offset += len;
++	desc->count -= len;
++	dprintk("RPC:      copied %zu bytes from skb. %zu bytes remain\n",
++			len, desc->count);
++	return len;
++}
++
++/*
++ * TCP read fragment marker
++ */
++static inline void
++tcp_read_fraghdr(struct rpc_xprt *xprt, skb_reader_t *desc)
++{
++	size_t len, used;
++	char *p;
++
++	p = ((char *) &xprt->tcp_recm) + xprt->tcp_offset;
++	len = sizeof(xprt->tcp_recm) - xprt->tcp_offset;
++	used = tcp_copy_data(desc, p, len);
++	xprt->tcp_offset += used;
++	if (used != len)
++		return;
++	xprt->tcp_reclen = ntohl(xprt->tcp_recm);
++	if (xprt->tcp_reclen & 0x80000000)
++		xprt->tcp_flags |= XPRT_LAST_FRAG;
++	else
++		xprt->tcp_flags &= ~XPRT_LAST_FRAG;
++	xprt->tcp_reclen &= 0x7fffffff;
++	xprt->tcp_flags &= ~XPRT_COPY_RECM;
++	xprt->tcp_offset = 0;
++	/* Sanity check of the record length */
++	if (xprt->tcp_reclen < 4) {
++		printk(KERN_ERR "RPC: Invalid TCP record fragment length\n");
++		xprt_disconnect(xprt);
++	}
++	dprintk("RPC:      reading TCP record fragment of length %d\n",
++			xprt->tcp_reclen);
++}
++
++static void
++tcp_check_recm(struct rpc_xprt *xprt)
++{
++	dprintk("RPC:      xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u, tcp_flags = %lx\n",
++			xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen, xprt->tcp_flags);
++	if (xprt->tcp_offset == xprt->tcp_reclen) {
++		xprt->tcp_flags |= XPRT_COPY_RECM;
++		xprt->tcp_offset = 0;
++		if (xprt->tcp_flags & XPRT_LAST_FRAG) {
++			xprt->tcp_flags &= ~XPRT_COPY_DATA;
++			xprt->tcp_flags |= XPRT_COPY_XID;
++			xprt->tcp_copied = 0;
++		}
++	}
++}
++
++/*
++ * TCP read xid
++ */
++static inline void
++tcp_read_xid(struct rpc_xprt *xprt, skb_reader_t *desc)
++{
++	size_t len, used;
++	char *p;
++
++	len = sizeof(xprt->tcp_xid) - xprt->tcp_offset;
++	dprintk("RPC:      reading XID (%Zu bytes)\n", len);
++	p = ((char *) &xprt->tcp_xid) + xprt->tcp_offset;
++	used = tcp_copy_data(desc, p, len);
++	xprt->tcp_offset += used;
++	if (used != len)
++		return;
++	xprt->tcp_flags &= ~XPRT_COPY_XID;
++	xprt->tcp_flags |= XPRT_COPY_DATA;
++	xprt->tcp_copied = 4;
++	dprintk("RPC:      reading reply for XID %08x\n",
++						ntohl(xprt->tcp_xid));
++	tcp_check_recm(xprt);
++}
++
++/*
++ * TCP read and complete request
++ */
++static inline void
++tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc)
++{
++	struct rpc_rqst *req;
++	struct xdr_buf *rcvbuf;
++	size_t len;
++	ssize_t r;
++
++	/* Find and lock the request corresponding to this xid */
++	spin_lock(&xprt->sock_lock);
++	req = xprt_lookup_rqst(xprt, xprt->tcp_xid);
++	if (!req) {
++		xprt->tcp_flags &= ~XPRT_COPY_DATA;
++		dprintk("RPC:      XID %08x request not found!\n",
++				ntohl(xprt->tcp_xid));
++		spin_unlock(&xprt->sock_lock);
++		return;
++	}
++
++	rcvbuf = &req->rq_private_buf;
++	len = desc->count;
++	if (len > xprt->tcp_reclen - xprt->tcp_offset) {
++		skb_reader_t my_desc;
++
++		len = xprt->tcp_reclen - xprt->tcp_offset;
++		memcpy(&my_desc, desc, sizeof(my_desc));
++		my_desc.count = len;
++		r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
++					  &my_desc, tcp_copy_data);
++		desc->count -= r;
++		desc->offset += r;
++	} else
++		r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
++					  desc, tcp_copy_data);
++
++	if (r > 0) {
++		xprt->tcp_copied += r;
++		xprt->tcp_offset += r;
++	}
++	if (r != len) {
++		/* Error when copying to the receive buffer,
++		 * usually because we weren't able to allocate
++		 * additional buffer pages. All we can do now
++		 * is turn off XPRT_COPY_DATA, so the request
++		 * will not receive any additional updates,
++		 * and time out.
++		 * Any remaining data from this record will
++		 * be discarded.
++		 */
++		xprt->tcp_flags &= ~XPRT_COPY_DATA;
++		dprintk("RPC:      XID %08x truncated request\n",
++				ntohl(xprt->tcp_xid));
++		dprintk("RPC:      xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u\n",
++				xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen);
++		goto out;
++	}
++
++	dprintk("RPC:      XID %08x read %Zd bytes\n",
++			ntohl(xprt->tcp_xid), r);
++	dprintk("RPC:      xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u\n",
++			xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen);
++
++	if (xprt->tcp_copied == req->rq_private_buf.buflen)
++		xprt->tcp_flags &= ~XPRT_COPY_DATA;
++	else if (xprt->tcp_offset == xprt->tcp_reclen) {
++		if (xprt->tcp_flags & XPRT_LAST_FRAG)
++			xprt->tcp_flags &= ~XPRT_COPY_DATA;
++	}
++
++out:
++	if (!(xprt->tcp_flags & XPRT_COPY_DATA)) {
++		dprintk("RPC: %4d received reply complete\n",
++				req->rq_task->tk_pid);
++		xprt_complete_rqst(xprt, req, xprt->tcp_copied);
++	}
++	spin_unlock(&xprt->sock_lock);
++	tcp_check_recm(xprt);
++}
++
++/*
++ * TCP discard extra bytes from a short read
++ */
++static inline void
++tcp_read_discard(struct rpc_xprt *xprt, skb_reader_t *desc)
++{
++	size_t len;
++
++	len = xprt->tcp_reclen - xprt->tcp_offset;
++	if (len > desc->count)
++		len = desc->count;
++	desc->count -= len;
++	desc->offset += len;
++	xprt->tcp_offset += len;
++	dprintk("RPC:      discarded %Zu bytes\n", len);
++	tcp_check_recm(xprt);
++}
++
++/*
++ * TCP record receive routine
++ * We first have to grab the record marker, then the XID, then the data.
++ */
++static int
++tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
++		unsigned int offset, size_t len)
++{
++	struct rpc_xprt *xprt = rd_desc->arg.data;
++	skb_reader_t desc = {
++		.skb	= skb,
++		.offset	= offset,
++		.count	= len,
++		.csum	= 0
++       	};
++
++	dprintk("RPC:      tcp_data_recv\n");
++	do {
++		/* Read in a new fragment marker if necessary */
++		/* Can we ever really expect to get completely empty fragments? */
++		if (xprt->tcp_flags & XPRT_COPY_RECM) {
++			tcp_read_fraghdr(xprt, &desc);
++			continue;
++		}
++		/* Read in the xid if necessary */
++		if (xprt->tcp_flags & XPRT_COPY_XID) {
++			tcp_read_xid(xprt, &desc);
++			continue;
++		}
++		/* Read in the request data */
++		if (xprt->tcp_flags & XPRT_COPY_DATA) {
++			tcp_read_request(xprt, &desc);
++			continue;
++		}
++		/* Skip over any trailing bytes on short reads */
++		tcp_read_discard(xprt, &desc);
++	} while (desc.count);
++	dprintk("RPC:      tcp_data_recv done\n");
++	return len - desc.count;
++}
++
++static void tcp_data_ready(struct sock *sk, int bytes)
++{
++	struct rpc_xprt *xprt;
++	read_descriptor_t rd_desc;
++
++	read_lock(&sk->sk_callback_lock);
++	dprintk("RPC:      tcp_data_ready...\n");
++	if (!(xprt = xprt_from_sock(sk))) {
++		printk("RPC:      tcp_data_ready socket info not found!\n");
++		goto out;
++	}
++	if (xprt->shutdown)
++		goto out;
++
++	/* We use rd_desc to pass struct xprt to tcp_data_recv */
++	rd_desc.arg.data = xprt;
++	rd_desc.count = 65536;
++	tcp_read_sock(sk, &rd_desc, tcp_data_recv);
++out:
++	read_unlock(&sk->sk_callback_lock);
++}
++
++static void
++tcp_state_change(struct sock *sk)
++{
++	struct rpc_xprt	*xprt;
++
++	read_lock(&sk->sk_callback_lock);
++	if (!(xprt = xprt_from_sock(sk)))
++		goto out;
++	dprintk("RPC:      tcp_state_change client %p...\n", xprt);
++	dprintk("RPC:      state %x conn %d dead %d zapped %d\n",
++				sk->sk_state, xprt_connected(xprt),
++				sock_flag(sk, SOCK_DEAD),
++				sock_flag(sk, SOCK_ZAPPED));
++
++	switch (sk->sk_state) {
++	case TCP_ESTABLISHED:
++		spin_lock_bh(&xprt->sock_lock);
++		if (!xprt_test_and_set_connected(xprt)) {
++			/* Reset TCP record info */
++			xprt->tcp_offset = 0;
++			xprt->tcp_reclen = 0;
++			xprt->tcp_copied = 0;
++			xprt->tcp_flags = XPRT_COPY_RECM | XPRT_COPY_XID;
++			rpc_wake_up(&xprt->pending);
++		}
++		spin_unlock_bh(&xprt->sock_lock);
++		break;
++	case TCP_SYN_SENT:
++	case TCP_SYN_RECV:
++		break;
++	default:
++		xprt_disconnect(xprt);
++		break;
++	}
++ out:
++	read_unlock(&sk->sk_callback_lock);
++}
++
++/*
++ * Called when more output buffer space is available for this socket.
++ * We try not to wake our writers until they can make "significant"
++ * progress, otherwise we'll waste resources thrashing sock_sendmsg
++ * with a bunch of small requests.
++ */
++static void
++xprt_write_space(struct sock *sk)
++{
++	struct rpc_xprt	*xprt;
++	struct socket	*sock;
++
++	read_lock(&sk->sk_callback_lock);
++	if (!(xprt = xprt_from_sock(sk)) || !(sock = sk->sk_socket))
++		goto out;
++	if (xprt->shutdown)
++		goto out;
++
++	/* Wait until we have enough socket memory */
++	if (xprt->stream) {
++		/* from net/core/stream.c:sk_stream_write_space */
++		if (sk_stream_wspace(sk) < sk_stream_min_wspace(sk))
++			goto out;
++	} else {
++		/* from net/core/sock.c:sock_def_write_space */
++		if (!sock_writeable(sk))
++			goto out;
++	}
++
++	if (!test_and_clear_bit(SOCK_NOSPACE, &sock->flags))
++		goto out;
++
++	spin_lock_bh(&xprt->sock_lock);
++	if (xprt->snd_task)
++		rpc_wake_up_task(xprt->snd_task);
++	spin_unlock_bh(&xprt->sock_lock);
++out:
++	read_unlock(&sk->sk_callback_lock);
++}
++
++/*
++ * Set socket buffer length
++ */
++static void
++xprt_sock_setbufsize(struct rpc_xprt *xprt)
++{
++	struct sock *sk = xprt->inet;
++
++	if (xprt->stream)
++		return;
++	if (xprt->rcvsize) {
++		sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
++		sk->sk_rcvbuf = xprt->rcvsize * xprt->max_reqs *  2;
++	}
++	if (xprt->sndsize) {
++		sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
++		sk->sk_sndbuf = xprt->sndsize * xprt->max_reqs * 2;
++		sk->sk_write_space(sk);
++	}
++}
++
++/*
++ * Bind to a reserved port
++ */
++static inline int xprt_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
++{
++	struct sockaddr_in myaddr = {
++		.sin_family = AF_INET,
++	};
++	int		err, port;
++
++	/* Were we already bound to a given port? Try to reuse it */
++	port = xprt->port;
++	do {
++		myaddr.sin_port = htons(port);
++		err = sock->ops->bind(sock, (struct sockaddr *) &myaddr,
++						sizeof(myaddr));
++		if (err == 0) {
++			xprt->port = port;
++			return 0;
++		}
++		if (--port == 0)
++			port = XPRT_MAX_RESVPORT;
++	} while (err == -EADDRINUSE && port != xprt->port);
++
++	printk("RPC: Can't bind to reserved port (%d).\n", -err);
++	return err;
++}
++
++static void
++xprt_bind_socket(struct rpc_xprt *xprt, struct socket *sock)
++{
++	struct sock	*sk = sock->sk;
++
++	if (xprt->inet)
++		return;
++
++	write_lock_bh(&sk->sk_callback_lock);
++	sk->sk_user_data = xprt;
++	xprt->old_data_ready = sk->sk_data_ready;
++	xprt->old_state_change = sk->sk_state_change;
++	xprt->old_write_space = sk->sk_write_space;
++	if (xprt->prot == IPPROTO_UDP) {
++		sk->sk_data_ready = udp_data_ready;
++		sk->sk_no_check = UDP_CSUM_NORCV;
++		xprt_set_connected(xprt);
++	} else {
++		tcp_sk(sk)->nonagle = 1;	/* disable Nagle's algorithm */
++		sk->sk_data_ready = tcp_data_ready;
++		sk->sk_state_change = tcp_state_change;
++		xprt_clear_connected(xprt);
++	}
++	sk->sk_write_space = xprt_write_space;
++
++	/* Reset to new socket */
++	xprt->sock = sock;
++	xprt->inet = sk;
++	write_unlock_bh(&sk->sk_callback_lock);
++
++	return;
++}
++
++/*
++ * Datastream sockets are created here, but xprt_connect will create
++ * and connect stream sockets.
++ */
++static struct socket * xprt_create_socket(struct rpc_xprt *xprt, int proto, int resvport)
++{
++	struct socket	*sock;
++	int		type, err;
++
++	dprintk("RPC:      xprt_create_socket(%s %d)\n",
++			   (proto == IPPROTO_UDP)? "udp" : "tcp", proto);
++
++	type = (proto == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
++
++	if ((err = sock_create_kern(PF_INET, type, proto, &sock)) < 0) {
++		printk("RPC: can't create socket (%d).\n", -err);
++		return NULL;
++	}
++
++	/* If the caller has the capability, bind to a reserved port */
++	if (resvport && xprt_bindresvport(xprt, sock) < 0) {
++		printk("RPC: can't bind to reserved port.\n");
++		goto failed;
++	}
++
++	return sock;
++
++failed:
++	sock_release(sock);
++	return NULL;
++}
++
++static void xprt_socket_connect(void *args)
++{
++	struct rpc_xprt *xprt = (struct rpc_xprt *)args;
++	struct socket *sock = xprt->sock;
++	int status = -EIO;
++
++	if (xprt->shutdown || xprt->addr.sin_port == 0)
++		goto out;
++
++	/*
++	 * Start by resetting any existing state
++	 */
++	xprt_close(xprt);
++	sock = xprt_create_socket(xprt, xprt->prot, xprt->resvport);
++	if (sock == NULL) {
++		/* couldn't create socket or bind to reserved port;
++		 * this is likely a permanent error, so cause an abort */
++		goto out;
++	}
++	xprt_bind_socket(xprt, sock);
++	xprt_sock_setbufsize(xprt);
++
++	status = 0;
++	if (!xprt->stream)
++		goto out;
++
++	/*
++	 * Tell the socket layer to start connecting...
++	 */
++	status = sock->ops->connect(sock, (struct sockaddr *) &xprt->addr,
++			sizeof(xprt->addr), O_NONBLOCK);
++	dprintk("RPC: %p  connect status %d connected %d sock state %d\n",
++			xprt, -status, xprt_connected(xprt), sock->sk->sk_state);
++	if (status < 0) {
++		switch (status) {
++			case -EINPROGRESS:
++			case -EALREADY:
++				goto out_clear;
++		}
++	}
++out:
++	if (status < 0)
++		rpc_wake_up_status(&xprt->pending, status);
++	else
++		rpc_wake_up(&xprt->pending);
++out_clear:
++	smp_mb__before_clear_bit();
++	clear_bit(XPRT_CONNECTING, &xprt->sockstate);
++	smp_mb__after_clear_bit();
++}
++
++static void
++xprt_connect_sock(struct rpc_task *task)
++{
++	struct rpc_xprt *xprt = task->tk_xprt;
++
++	if (!test_and_set_bit(XPRT_CONNECTING, &xprt->sockstate)) {
++		/* Note: if we are here due to a dropped connection
++		 * 	 we delay reconnecting by RPC_REESTABLISH_TIMEOUT/HZ
++		 * 	 seconds
++		 */
++		if (xprt->sock != NULL)
++			schedule_delayed_work(&xprt->sock_connect,
++					RPC_REESTABLISH_TIMEOUT);
++		else {
++			schedule_work(&xprt->sock_connect);
++			/* flush_scheduled_work can sleep... */
++			if (!RPC_IS_ASYNC(task))
++				flush_scheduled_work();
++		}
++	}
++}
++
++/*
++ * Set default timeout parameters
++ */
++static void
++xprt_default_timeout(struct rpc_timeout *to, int proto)
++{
++	if (proto == IPPROTO_UDP)
++		xprt_set_timeout(to, 5,  5 * HZ);
++	else
++		xprt_set_timeout(to, 2, 60 * HZ);
++}
++
++static struct rpc_xprt_ops xprt_socket_ops = {
++	.set_buffer_size	= xprt_sock_setbufsize,
++	.connect		= xprt_connect_sock,
++	.send_request		= xprt_send_request,
++	.close			= xprt_close,
++	.destroy		= xprt_socket_destroy,
++};
++
++extern unsigned int xprt_udp_slot_table_entries;
++extern unsigned int xprt_tcp_slot_table_entries;
++
++int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to)
++{
++	size_t slot_table_size;
++
++	dprintk("RPC:      setting up udp-ipv4 transport...\n");
++
++	xprt->max_reqs = xprt_udp_slot_table_entries;
++	slot_table_size = xprt->max_reqs * sizeof(xprt->slot[0]);
++	xprt->slot = kmalloc(slot_table_size, GFP_KERNEL);
++	if (xprt->slot == NULL)
++		return -ENOMEM;
++	memset(xprt->slot, 0, slot_table_size);
++
++	xprt->prot = IPPROTO_UDP;
++	xprt->port = XPRT_MAX_RESVPORT;
++	xprt->stream = 0;
++	xprt->nocong = 0;
++	xprt->cwnd = RPC_INITCWND;
++	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
++	/* XXX: header size can vary due to auth type, IPv6, etc. */
++	xprt->max_payload = (1U << 16) - (MAX_HEADER << 3);
++
++	INIT_WORK(&xprt->sock_connect, xprt_socket_connect, xprt);
++
++	xprt->ops = &xprt_socket_ops;
++
++	if (to)
++		xprt->timeout = *to;
++	else
++		xprt_default_timeout(to, xprt->prot);
++
++	return 0;
++}
++
++int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to)
++{
++	size_t slot_table_size;
++
++	dprintk("RPC:      setting up tcp-ipv4 transport...\n");
++
++	xprt->max_reqs = xprt_tcp_slot_table_entries;
++	slot_table_size = xprt->max_reqs * sizeof(xprt->slot[0]);
++	xprt->slot = kmalloc(slot_table_size, GFP_KERNEL);
++	if (xprt->slot == NULL)
++		return -ENOMEM;
++	memset(xprt->slot, 0, slot_table_size);
++
++	xprt->prot = IPPROTO_TCP;
++	xprt->port = XPRT_MAX_RESVPORT;
++	xprt->stream = 1;
++	xprt->nocong = 1;
++	xprt->cwnd = RPC_MAXCWND(xprt);
++	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
++	xprt->max_payload = (1U << 31) - 1;
++
++	INIT_WORK(&xprt->sock_connect, xprt_socket_connect, xprt);
++
++	xprt->ops = &xprt_socket_ops;
++
++	if (to)
++		xprt->timeout = *to;
++	else
++		xprt_default_timeout(to, xprt->prot);
++
++	return 0;
++}

commit 094bb20b9fcab3a1652a77741caba6b78097d622
+Author: Chuck Lever 
+Date:   Thu Aug 11 16:25:20 2005 -0400
+
+    [PATCH] RPC: extract socket logic common to both client and server
+    
+     Clean-up: Move some code that is common to both RPC client- and server-side
+     socket transports into its own source file, net/sunrpc/socklib.c.
+    
+     Test-plan:
+     Compile kernel with CONFIG_NFS enabled.  Millions of fsx operations over
+     UDP, client and server.  Connectathon over UDP.
+    
+     Version: Thu, 11 Aug 2005 16:03:09 -0400
+    
+     Signed-off-by: Chuck Lever 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
+index 23448d0fb5bc..d8b7656bca41 100644
+--- a/include/linux/sunrpc/xdr.h
++++ b/include/linux/sunrpc/xdr.h
+@@ -161,6 +161,7 @@ typedef struct {
+ 
+ typedef size_t (*skb_read_actor_t)(skb_reader_t *desc, void *to, size_t len);
+ 
++extern int csum_partial_copy_to_xdr(struct xdr_buf *, struct sk_buff *);
+ extern ssize_t xdr_partial_copy_from_skb(struct xdr_buf *, unsigned int,
+ 		skb_reader_t *, skb_read_actor_t);
+ 
+diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile
+index 46a2ce00a29b..f0a955627177 100644
+--- a/net/sunrpc/Makefile
++++ b/net/sunrpc/Makefile
+@@ -6,7 +6,7 @@
+ obj-$(CONFIG_SUNRPC) += sunrpc.o
+ obj-$(CONFIG_SUNRPC_GSS) += auth_gss/
+ 
+-sunrpc-y := clnt.o xprt.o sched.o \
++sunrpc-y := clnt.o xprt.o socklib.o sched.o \
+ 	    auth.o auth_null.o auth_unix.o \
+ 	    svc.o svcsock.o svcauth.o svcauth_unix.o \
+ 	    pmap_clnt.o timer.o xdr.o \
+diff --git a/net/sunrpc/socklib.c b/net/sunrpc/socklib.c
+new file mode 100644
+index 000000000000..8f97e90f36c8
+--- /dev/null
++++ b/net/sunrpc/socklib.c
+@@ -0,0 +1,175 @@
++/*
++ * linux/net/sunrpc/socklib.c
++ *
++ * Common socket helper routines for RPC client and server
++ *
++ * Copyright (C) 1995, 1996 Olaf Kirch 
++ */
++
++#include 
++#include 
++#include 
++#include 
++
++
++/**
++ * skb_read_bits - copy some data bits from skb to internal buffer
++ * @desc: sk_buff copy helper
++ * @to: copy destination
++ * @len: number of bytes to copy
++ *
++ * Possibly called several times to iterate over an sk_buff and copy
++ * data out of it.
++ */
++static size_t skb_read_bits(skb_reader_t *desc, void *to, size_t len)
++{
++	if (len > desc->count)
++		len = desc->count;
++	if (skb_copy_bits(desc->skb, desc->offset, to, len))
++		return 0;
++	desc->count -= len;
++	desc->offset += len;
++	return len;
++}
++
++/**
++ * skb_read_and_csum_bits - copy and checksum from skb to buffer
++ * @desc: sk_buff copy helper
++ * @to: copy destination
++ * @len: number of bytes to copy
++ *
++ * Same as skb_read_bits, but calculate a checksum at the same time.
++ */
++static size_t skb_read_and_csum_bits(skb_reader_t *desc, void *to, size_t len)
++{
++	unsigned int	csum2, pos;
++
++	if (len > desc->count)
++		len = desc->count;
++	pos = desc->offset;
++	csum2 = skb_copy_and_csum_bits(desc->skb, pos, to, len, 0);
++	desc->csum = csum_block_add(desc->csum, csum2, pos);
++	desc->count -= len;
++	desc->offset += len;
++	return len;
++}
++
++/**
++ * xdr_partial_copy_from_skb - copy data out of an skb
++ * @xdr: target XDR buffer
++ * @base: starting offset
++ * @desc: sk_buff copy helper
++ * @copy_actor: virtual method for copying data
++ *
++ */
++ssize_t xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base, skb_reader_t *desc, skb_read_actor_t copy_actor)
++{
++	struct page	**ppage = xdr->pages;
++	unsigned int	len, pglen = xdr->page_len;
++	ssize_t		copied = 0;
++	int		ret;
++
++	len = xdr->head[0].iov_len;
++	if (base < len) {
++		len -= base;
++		ret = copy_actor(desc, (char *)xdr->head[0].iov_base + base, len);
++		copied += ret;
++		if (ret != len || !desc->count)
++			goto out;
++		base = 0;
++	} else
++		base -= len;
++
++	if (unlikely(pglen == 0))
++		goto copy_tail;
++	if (unlikely(base >= pglen)) {
++		base -= pglen;
++		goto copy_tail;
++	}
++	if (base || xdr->page_base) {
++		pglen -= base;
++		base += xdr->page_base;
++		ppage += base >> PAGE_CACHE_SHIFT;
++		base &= ~PAGE_CACHE_MASK;
++	}
++	do {
++		char *kaddr;
++
++		/* ACL likes to be lazy in allocating pages - ACLs
++		 * are small by default but can get huge. */
++		if (unlikely(*ppage == NULL)) {
++			*ppage = alloc_page(GFP_ATOMIC);
++			if (unlikely(*ppage == NULL)) {
++				if (copied == 0)
++					copied = -ENOMEM;
++				goto out;
++			}
++		}
++
++		len = PAGE_CACHE_SIZE;
++		kaddr = kmap_atomic(*ppage, KM_SKB_SUNRPC_DATA);
++		if (base) {
++			len -= base;
++			if (pglen < len)
++				len = pglen;
++			ret = copy_actor(desc, kaddr + base, len);
++			base = 0;
++		} else {
++			if (pglen < len)
++				len = pglen;
++			ret = copy_actor(desc, kaddr, len);
++		}
++		flush_dcache_page(*ppage);
++		kunmap_atomic(kaddr, KM_SKB_SUNRPC_DATA);
++		copied += ret;
++		if (ret != len || !desc->count)
++			goto out;
++		ppage++;
++	} while ((pglen -= len) != 0);
++copy_tail:
++	len = xdr->tail[0].iov_len;
++	if (base < len)
++		copied += copy_actor(desc, (char *)xdr->tail[0].iov_base + base, len - base);
++out:
++	return copied;
++}
++
++/**
++ * csum_partial_copy_to_xdr - checksum and copy data
++ * @xdr: target XDR buffer
++ * @skb: source skb
++ *
++ * We have set things up such that we perform the checksum of the UDP
++ * packet in parallel with the copies into the RPC client iovec.  -DaveM
++ */
++int csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
++{
++	skb_reader_t	desc;
++
++	desc.skb = skb;
++	desc.offset = sizeof(struct udphdr);
++	desc.count = skb->len - desc.offset;
++
++	if (skb->ip_summed == CHECKSUM_UNNECESSARY)
++		goto no_checksum;
++
++	desc.csum = csum_partial(skb->data, desc.offset, skb->csum);
++	if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_and_csum_bits) < 0)
++		return -1;
++	if (desc.offset != skb->len) {
++		unsigned int csum2;
++		csum2 = skb_checksum(skb, desc.offset, skb->len - desc.offset, 0);
++		desc.csum = csum_block_add(desc.csum, csum2, desc.offset);
++	}
++	if (desc.count)
++		return -1;
++	if ((unsigned short)csum_fold(desc.csum))
++		return -1;
++	return 0;
++no_checksum:
++	if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_bits) < 0)
++		return -1;
++	if (desc.count)
++		return -1;
++	return 0;
++}
+diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
+index 30ec3efc48a6..130f2b5d93dd 100644
+--- a/net/sunrpc/svcsock.c
++++ b/net/sunrpc/svcsock.c
+@@ -548,9 +548,6 @@ svc_write_space(struct sock *sk)
+ /*
+  * Receive a datagram from a UDP socket.
+  */
+-extern int
+-csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb);
+-
+ static int
+ svc_udp_recvfrom(struct svc_rqst *rqstp)
+ {
+diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
+index fde16f40a581..9cc12aeed22c 100644
+--- a/net/sunrpc/xdr.c
++++ b/net/sunrpc/xdr.c
+@@ -176,81 +176,6 @@ xdr_inline_pages(struct xdr_buf *xdr, unsigned int offset,
+ 	xdr->buflen += len;
+ }
+ 
+-ssize_t
+-xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base,
+-			  skb_reader_t *desc,
+-			  skb_read_actor_t copy_actor)
+-{
+-	struct page	**ppage = xdr->pages;
+-	unsigned int	len, pglen = xdr->page_len;
+-	ssize_t		copied = 0;
+-	int		ret;
+-
+-	len = xdr->head[0].iov_len;
+-	if (base < len) {
+-		len -= base;
+-		ret = copy_actor(desc, (char *)xdr->head[0].iov_base + base, len);
+-		copied += ret;
+-		if (ret != len || !desc->count)
+-			goto out;
+-		base = 0;
+-	} else
+-		base -= len;
+-
+-	if (pglen == 0)
+-		goto copy_tail;
+-	if (base >= pglen) {
+-		base -= pglen;
+-		goto copy_tail;
+-	}
+-	if (base || xdr->page_base) {
+-		pglen -= base;
+-		base  += xdr->page_base;
+-		ppage += base >> PAGE_CACHE_SHIFT;
+-		base &= ~PAGE_CACHE_MASK;
+-	}
+-	do {
+-		char *kaddr;
+-
+-		/* ACL likes to be lazy in allocating pages - ACLs
+-		 * are small by default but can get huge. */
+-		if (unlikely(*ppage == NULL)) {
+-			*ppage = alloc_page(GFP_ATOMIC);
+-			if (unlikely(*ppage == NULL)) {
+-				if (copied == 0)
+-					copied = -ENOMEM;
+-				goto out;
+-			}
+-		}
+-
+-		len = PAGE_CACHE_SIZE;
+-		kaddr = kmap_atomic(*ppage, KM_SKB_SUNRPC_DATA);
+-		if (base) {
+-			len -= base;
+-			if (pglen < len)
+-				len = pglen;
+-			ret = copy_actor(desc, kaddr + base, len);
+-			base = 0;
+-		} else {
+-			if (pglen < len)
+-				len = pglen;
+-			ret = copy_actor(desc, kaddr, len);
+-		}
+-		flush_dcache_page(*ppage);
+-		kunmap_atomic(kaddr, KM_SKB_SUNRPC_DATA);
+-		copied += ret;
+-		if (ret != len || !desc->count)
+-			goto out;
+-		ppage++;
+-	} while ((pglen -= len) != 0);
+-copy_tail:
+-	len = xdr->tail[0].iov_len;
+-	if (base < len)
+-		copied += copy_actor(desc, (char *)xdr->tail[0].iov_base + base, len - base);
+-out:
+-	return copied;
+-}
+-
+ 
+ int
+ xdr_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
+diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
+index 0e4ffdaa0129..67444f494fea 100644
+--- a/net/sunrpc/xprt.c
++++ b/net/sunrpc/xprt.c
+@@ -691,70 +691,6 @@ xprt_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied)
+ 	return;
+ }
+ 
+-static size_t
+-skb_read_bits(skb_reader_t *desc, void *to, size_t len)
+-{
+-	if (len > desc->count)
+-		len = desc->count;
+-	if (skb_copy_bits(desc->skb, desc->offset, to, len))
+-		return 0;
+-	desc->count -= len;
+-	desc->offset += len;
+-	return len;
+-}
+-
+-static size_t
+-skb_read_and_csum_bits(skb_reader_t *desc, void *to, size_t len)
+-{
+-	unsigned int csum2, pos;
+-
+-	if (len > desc->count)
+-		len = desc->count;
+-	pos = desc->offset;
+-	csum2 = skb_copy_and_csum_bits(desc->skb, pos, to, len, 0);
+-	desc->csum = csum_block_add(desc->csum, csum2, pos);
+-	desc->count -= len;
+-	desc->offset += len;
+-	return len;
+-}
+-
+-/*
+- * We have set things up such that we perform the checksum of the UDP
+- * packet in parallel with the copies into the RPC client iovec.  -DaveM
+- */
+-int
+-csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
+-{
+-	skb_reader_t desc;
+-
+-	desc.skb = skb;
+-	desc.offset = sizeof(struct udphdr);
+-	desc.count = skb->len - desc.offset;
+-
+-	if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+-		goto no_checksum;
+-
+-	desc.csum = csum_partial(skb->data, desc.offset, skb->csum);
+-	if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_and_csum_bits) < 0)
+-		return -1;
+-	if (desc.offset != skb->len) {
+-		unsigned int csum2;
+-		csum2 = skb_checksum(skb, desc.offset, skb->len - desc.offset, 0);
+-		desc.csum = csum_block_add(desc.csum, csum2, desc.offset);
+-	}
+-	if (desc.count)
+-		return -1;
+-	if ((unsigned short)csum_fold(desc.csum))
+-		return -1;
+-	return 0;
+-no_checksum:
+-	if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_bits) < 0)
+-		return -1;
+-	if (desc.count)
+-		return -1;
+-	return 0;
+-}
+-
+ /*
+  * Input handler for RPC replies. Called from a bottom half and hence
+  * atomic.

commit 602f83273c89fdd25f24757564d8001cf723e740
+Author: Chuck Lever 
+Date:   Thu Aug 11 16:25:17 2005 -0400
+
+    [PATCH] RPC: portmapper doesn't need a reserved port
+    
+     The in-kernel portmapper does not require a reserved port for making
+     bind queries.
+    
+     Test-plan:
+     Tens of runs of the Connectathon locking suite with TCP and UDP
+     against several other NFS server implementations using NFSv3,
+     not NFSv4 (which doesn't require rpcbind).
+    
+     Version: Thu, 11 Aug 2005 16:02:43 -0400
+    
+     Signed-off-by: Chuck Lever 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c
+index 4e81f2766923..d8e3f220002b 100644
+--- a/net/sunrpc/pmap_clnt.c
++++ b/net/sunrpc/pmap_clnt.c
+@@ -208,6 +208,7 @@ pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto)
+ 	if (IS_ERR(xprt))
+ 		return (struct rpc_clnt *)xprt;
+ 	xprt->addr.sin_port = htons(RPC_PMAP_PORT);
++	xprt->resvport = 0;
+ 
+ 	/* printk("pmap: create clnt\n"); */
+ 	clnt = rpc_new_client(xprt, hostname,

commit eab5c084b858fd95a873fc2b97de9a9ad937b4ed
+Author: Chuck Lever 
+Date:   Thu Aug 11 16:25:14 2005 -0400
+
+    [PATCH] NFS: use a constant value for TCP retransmit timeouts
+    
+     Implement a best practice: don't use exponential backoff when computing
+     retransmit timeout values on TCP connections, but simply retransmit
+     at regular intervals.
+    
+     This also fixes a bug introduced when xprt_reset_majortimeo() was added.
+    
+     Test-plan:
+     Enable RPC debugging and watch timeout behavior on a NFS/TCP mount.
+    
+     Version: Thu, 11 Aug 2005 16:02:19 -0400
+    
+     Signed-off-by: Chuck Lever 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
+index 6922469d6fc5..b6a1ca508e60 100644
+--- a/fs/nfs/inode.c
++++ b/fs/nfs/inode.c
+@@ -358,6 +358,35 @@ nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
+ 	return no_root_error;
+ }
+ 
++static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, unsigned int timeo, unsigned int retrans)
++{
++	to->to_initval = timeo * HZ / 10;
++	to->to_retries = retrans;
++	if (!to->to_retries)
++		to->to_retries = 2;
++
++	switch (proto) {
++	case IPPROTO_TCP:
++		if (!to->to_initval)
++			to->to_initval = 60 * HZ;
++		if (to->to_initval > RPC_MAX_TCP_TIMEOUT)
++			to->to_initval = RPC_MAX_TCP_TIMEOUT;
++		to->to_increment = to->to_initval;
++		to->to_maxval = to->to_initval + (to->to_increment * to->to_retries);
++		to->to_exponential = 0;
++		break;
++	case IPPROTO_UDP:
++	default:
++		if (!to->to_initval)
++			to->to_initval = 11 * HZ / 10;
++		if (to->to_initval > RPC_MAX_UDP_TIMEOUT)
++			to->to_initval = RPC_MAX_UDP_TIMEOUT;
++		to->to_maxval = RPC_MAX_UDP_TIMEOUT;
++		to->to_exponential = 1;
++		break;
++	}
++}
++
+ /*
+  * Create an RPC client handle.
+  */
+@@ -367,22 +396,12 @@ nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data)
+ 	struct rpc_timeout	timeparms;
+ 	struct rpc_xprt		*xprt = NULL;
+ 	struct rpc_clnt		*clnt = NULL;
+-	int			tcp   = (data->flags & NFS_MOUNT_TCP);
+-
+-	/* Initialize timeout values */
+-	timeparms.to_initval = data->timeo * HZ / 10;
+-	timeparms.to_retries = data->retrans;
+-	timeparms.to_maxval  = tcp ? RPC_MAX_TCP_TIMEOUT : RPC_MAX_UDP_TIMEOUT;
+-	timeparms.to_exponential = 1;
++	int			proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP;
+ 
+-	if (!timeparms.to_initval)
+-		timeparms.to_initval = (tcp ? 600 : 11) * HZ / 10;
+-	if (!timeparms.to_retries)
+-		timeparms.to_retries = 5;
++	nfs_init_timeout_values(&timeparms, proto, data->timeo, data->retrans);
+ 
+ 	/* create transport and client */
+-	xprt = xprt_create_proto(tcp ? IPPROTO_TCP : IPPROTO_UDP,
+-				 &server->addr, &timeparms);
++	xprt = xprt_create_proto(proto, &server->addr, &timeparms);
+ 	if (IS_ERR(xprt)) {
+ 		dprintk("%s: cannot create RPC transport. Error = %ld\n",
+ 				__FUNCTION__, PTR_ERR(xprt));
+@@ -1674,7 +1693,7 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
+ 	struct rpc_clnt *clnt = NULL;
+ 	struct rpc_timeout timeparms;
+ 	rpc_authflavor_t authflavour;
+-	int proto, err = -EIO;
++	int err = -EIO;
+ 
+ 	sb->s_blocksize_bits = 0;
+ 	sb->s_blocksize = 0;
+@@ -1692,30 +1711,8 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
+ 	server->acdirmax = data->acdirmax*HZ;
+ 
+ 	server->rpc_ops = &nfs_v4_clientops;
+-	/* Initialize timeout values */
+-
+-	timeparms.to_initval = data->timeo * HZ / 10;
+-	timeparms.to_retries = data->retrans;
+-	timeparms.to_exponential = 1;
+-	if (!timeparms.to_retries)
+-		timeparms.to_retries = 5;
+ 
+-	proto = data->proto;
+-	/* Which IP protocol do we use? */
+-	switch (proto) {
+-	case IPPROTO_TCP:
+-		timeparms.to_maxval  = RPC_MAX_TCP_TIMEOUT;
+-		if (!timeparms.to_initval)
+-			timeparms.to_initval = 600 * HZ / 10;
+-		break;
+-	case IPPROTO_UDP:
+-		timeparms.to_maxval  = RPC_MAX_UDP_TIMEOUT;
+-		if (!timeparms.to_initval)
+-			timeparms.to_initval = 11 * HZ / 10;
+-		break;
+-	default:
+-		return -EINVAL;
+-	}
++	nfs_init_timeout_values(&timeparms, data->proto, data->timeo, data->retrans);
+ 
+ 	clp = nfs4_get_client(&server->addr.sin_addr);
+ 	if (!clp) {
+@@ -1740,7 +1737,7 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
+ 
+ 	down_write(&clp->cl_sem);
+ 	if (IS_ERR(clp->cl_rpcclient)) {
+-		xprt = xprt_create_proto(proto, &server->addr, &timeparms);
++		xprt = xprt_create_proto(data->proto, &server->addr, &timeparms);
+ 		if (IS_ERR(xprt)) {
+ 			up_write(&clp->cl_sem);
+ 			err = PTR_ERR(xprt);
+diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
+index b28ea0cc0cb7..0e4ffdaa0129 100644
+--- a/net/sunrpc/xprt.c
++++ b/net/sunrpc/xprt.c
+@@ -1453,7 +1453,7 @@ xprt_default_timeout(struct rpc_timeout *to, int proto)
+ 	if (proto == IPPROTO_UDP)
+ 		xprt_set_timeout(to, 5,  5 * HZ);
+ 	else
+-		xprt_set_timeout(to, 5, 60 * HZ);
++		xprt_set_timeout(to, 2, 60 * HZ);
+ }
+ 
+ /*
+@@ -1464,7 +1464,7 @@ xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr)
+ {
+ 	to->to_initval   = 
+ 	to->to_increment = incr;
+-	to->to_maxval    = incr * retr;
++	to->to_maxval    = to->to_initval + (incr * retr);
+ 	to->to_retries   = retr;
+ 	to->to_exponential = 0;
+ }

commit da35187801732397a7e05fb9e77f3700cc35f5db
+Author: Chuck Lever 
+Date:   Thu Aug 11 16:25:11 2005 -0400
+
+    [PATCH] RPC: proper soft timeout behavior for rpcbind
+    
+     Implement a best practice:  for soft mounts, an rpcbind timeout should
+     cause an RPC request to fail.
+    
+     This also provides an FSM hook for retrying an rpcbind with a different
+     rpcbind protocol version.  We'll use this later to try multiple rpcbind
+     protocol versions when binding.  To enable this, expose the RPC error
+     code returned during a portmap request to the FSM so it can make some
+     decision about how to report, retry, or fail the request.
+    
+     Test-plan:
+     Hundreds of passes with connectathon NFSv3 locking suite, on the client
+     and server.
+    
+     Version: Thu, 11 Aug 2005 16:01:53 -0400
+    
+     Signed-off-by: Chuck Lever 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
+index f17e6153b688..2d3cf0a52d82 100644
+--- a/net/sunrpc/clnt.c
++++ b/net/sunrpc/clnt.c
+@@ -53,6 +53,7 @@ static void	call_allocate(struct rpc_task *task);
+ static void	call_encode(struct rpc_task *task);
+ static void	call_decode(struct rpc_task *task);
+ static void	call_bind(struct rpc_task *task);
++static void	call_bind_status(struct rpc_task *task);
+ static void	call_transmit(struct rpc_task *task);
+ static void	call_status(struct rpc_task *task);
+ static void	call_refresh(struct rpc_task *task);
+@@ -734,43 +735,94 @@ static void
+ call_bind(struct rpc_task *task)
+ {
+ 	struct rpc_clnt	*clnt = task->tk_client;
+-	struct rpc_xprt *xprt = clnt->cl_xprt;
+-
+-	dprintk("RPC: %4d call_bind xprt %p %s connected\n", task->tk_pid,
+-			xprt, (xprt_connected(xprt) ? "is" : "is not"));
+ 
+-	task->tk_action = (xprt_connected(xprt)) ? call_transmit : call_connect;
++	dprintk("RPC: %4d call_bind (status %d)\n",
++				task->tk_pid, task->tk_status);
+ 
++	task->tk_action = call_connect;
+ 	if (!clnt->cl_port) {
+-		task->tk_action = call_connect;
++		task->tk_action = call_bind_status;
+ 		task->tk_timeout = RPC_CONNECT_TIMEOUT;
+ 		rpc_getport(task, clnt);
+ 	}
+ }
+ 
+ /*
+- * 4a.	Connect to the RPC server (TCP case)
++ * 4a.	Sort out bind result
++ */
++static void
++call_bind_status(struct rpc_task *task)
++{
++	int status = -EACCES;
++
++	if (task->tk_status >= 0) {
++		dprintk("RPC: %4d call_bind_status (status %d)\n",
++					task->tk_pid, task->tk_status);
++		task->tk_status = 0;
++		task->tk_action = call_connect;
++		return;
++	}
++
++	switch (task->tk_status) {
++	case -EACCES:
++		dprintk("RPC: %4d remote rpcbind: RPC program/version unavailable\n",
++				task->tk_pid);
++		break;
++	case -ETIMEDOUT:
++		dprintk("RPC: %4d rpcbind request timed out\n",
++				task->tk_pid);
++		if (RPC_IS_SOFT(task)) {
++			status = -EIO;
++			break;
++		}
++		goto retry_bind;
++	case -EPFNOSUPPORT:
++		dprintk("RPC: %4d remote rpcbind service unavailable\n",
++				task->tk_pid);
++		break;
++	case -EPROTONOSUPPORT:
++		dprintk("RPC: %4d remote rpcbind version 2 unavailable\n",
++				task->tk_pid);
++		break;
++	default:
++		dprintk("RPC: %4d unrecognized rpcbind error (%d)\n",
++				task->tk_pid, -task->tk_status);
++		status = -EIO;
++		break;
++	}
++
++	rpc_exit(task, status);
++	return;
++
++retry_bind:
++	task->tk_status = 0;
++	task->tk_action = call_bind;
++	return;
++}
++
++/*
++ * 4b.	Connect to the RPC server
+  */
+ static void
+ call_connect(struct rpc_task *task)
+ {
+-	struct rpc_clnt *clnt = task->tk_client;
++	struct rpc_xprt *xprt = task->tk_xprt;
+ 
+-	dprintk("RPC: %4d call_connect status %d\n",
+-				task->tk_pid, task->tk_status);
++	dprintk("RPC: %4d call_connect xprt %p %s connected\n",
++			task->tk_pid, xprt,
++			(xprt_connected(xprt) ? "is" : "is not"));
+ 
+-	if (xprt_connected(clnt->cl_xprt)) {
+-		task->tk_action = call_transmit;
+-		return;
++	task->tk_action = call_transmit;
++	if (!xprt_connected(xprt)) {
++		task->tk_action = call_connect_status;
++		if (task->tk_status < 0)
++			return;
++		xprt_connect(task);
+ 	}
+-	task->tk_action = call_connect_status;
+-	if (task->tk_status < 0)
+-		return;
+-	xprt_connect(task);
+ }
+ 
+ /*
+- * 4b. Sort out connect result
++ * 4c.	Sort out connect result
+  */
+ static void
+ call_connect_status(struct rpc_task *task)
+@@ -778,6 +830,9 @@ call_connect_status(struct rpc_task *task)
+ 	struct rpc_clnt *clnt = task->tk_client;
+ 	int status = task->tk_status;
+ 
++	dprintk("RPC: %5u call_connect_status (status %d)\n", 
++				task->tk_pid, task->tk_status);
++
+ 	task->tk_status = 0;
+ 	if (status >= 0) {
+ 		clnt->cl_stats->netreconn++;
+@@ -785,17 +840,19 @@ call_connect_status(struct rpc_task *task)
+ 		return;
+ 	}
+ 
+-	/* Something failed: we may have to rebind */
++	/* Something failed: remote service port may have changed */
+ 	if (clnt->cl_autobind)
+ 		clnt->cl_port = 0;
++
+ 	switch (status) {
+ 	case -ENOTCONN:
+ 	case -ETIMEDOUT:
+ 	case -EAGAIN:
+-		task->tk_action = (clnt->cl_port == 0) ? call_bind : call_connect;
++		task->tk_action = call_bind;
+ 		break;
+ 	default:
+ 		rpc_exit(task, -EIO);
++		break;
+ 	}
+ }
+ 

commit 23475d66bd8600e0c5353f86c1b74f68df27bdb5
+Author: Chuck Lever 
+Date:   Thu Aug 11 16:25:08 2005 -0400
+
+    [PATCH] RPC: Report connection errors properly when mounting with "soft"
+    
+     Fix up xprt_connect_status: the soft timeout logic was clobbering tk_status,
+     so TCP connect errors were not properly reported on soft mounts.
+    
+     Test-plan:
+     Destructive testing (unplugging the network temporarily).  Connectathon
+     with UDP and TCP.
+    
+     Version: Thu, 11 Aug 2005 16:01:28 -0400
+    
+     Signed-off-by: Chuck Lever 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
+index 3c654e06b084..b28ea0cc0cb7 100644
+--- a/net/sunrpc/xprt.c
++++ b/net/sunrpc/xprt.c
+@@ -592,24 +592,33 @@ xprt_connect_status(struct rpc_task *task)
+ 		return;
+ 	}
+ 
+-	/* if soft mounted, just cause this RPC to fail */
+-	if (RPC_IS_SOFT(task))
+-		task->tk_status = -EIO;
+-
+ 	switch (task->tk_status) {
+ 	case -ECONNREFUSED:
+ 	case -ECONNRESET:
++		dprintk("RPC: %4d xprt_connect_status: server %s refused connection\n",
++				task->tk_pid, task->tk_client->cl_server);
++		break;
+ 	case -ENOTCONN:
+-		return;
++		dprintk("RPC: %4d xprt_connect_status: connection broken\n",
++				task->tk_pid);
++		break;
+ 	case -ETIMEDOUT:
+-		dprintk("RPC: %4d xprt_connect_status: timed out\n",
++		dprintk("RPC: %4d xprt_connect_status: connect attempt timed out\n",
+ 				task->tk_pid);
+ 		break;
+ 	default:
+-		printk(KERN_ERR "RPC: error %d connecting to server %s\n",
+-				-task->tk_status, task->tk_client->cl_server);
++		dprintk("RPC: %4d xprt_connect_status: error %d connecting to server %s\n",
++				task->tk_pid, -task->tk_status, task->tk_client->cl_server);
++		xprt_release_write(xprt, task);
++		task->tk_status = -EIO;
++		return;
++	}
++
++	/* if soft mounted, just cause this RPC to fail */
++	if (RPC_IS_SOFT(task)) {
++		xprt_release_write(xprt, task);
++		task->tk_status = -EIO;
+ 	}
+-	xprt_release_write(xprt, task);
+ }
+ 
+ /*

commit dc59250c6ebed099a9bc0a11298e2281dd896657
+Author: Chuck Lever 
+Date:   Thu Aug 18 11:24:12 2005 -0700
+
+    [PATCH] NFS: Introduce the use of inode->i_lock to protect fields in nfsi
+    
+    Down the road we want to eliminate the use of the global kernel lock entirely
+    from the NFS client.  To do this, we need to protect the fields in the
+    nfs_inode structure adequately.  Start by serializing updates to the
+    "cache_validity" field.
+    
+    Note this change addresses an SMP hang found by njw@osdl.org, where processes
+    deadlock because nfs_end_data_update and nfs_revalidate_mapping update the
+    "cache_validity" field without proper serialization.
+    
+    Test plan:
+     Millions of fsx ops on SMP clients.  Run Nick Wilson's breaknfs program on
+     large SMP clients.
+    
+    Signed-off-by: Chuck Lever 
+    Cc: Trond Myklebust 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
+index 27cf5577f239..147cbf9261ce 100644
+--- a/fs/nfs/dir.c
++++ b/fs/nfs/dir.c
+@@ -189,7 +189,9 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
+ 		goto error;
+ 	}
+ 	SetPageUptodate(page);
++	spin_lock(&inode->i_lock);
+ 	NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME;
++	spin_unlock(&inode->i_lock);
+ 	/* Ensure consistent page alignment of the data.
+ 	 * Note: assumes we have exclusive access to this mapping either
+ 	 *	 through inode->i_sem or some other mechanism.
+@@ -462,7 +464,9 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
+ 						page,
+ 						NFS_SERVER(inode)->dtsize,
+ 						desc->plus);
++	spin_lock(&inode->i_lock);
+ 	NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME;
++	spin_unlock(&inode->i_lock);
+ 	desc->page = page;
+ 	desc->ptr = kmap(page);		/* matching kunmap in nfs_do_filldir */
+ 	if (desc->error >= 0) {
+@@ -1596,7 +1600,10 @@ void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set)
+ 			put_rpccred(cache->cred);
+ 		cache->cred = get_rpccred(set->cred);
+ 	}
++	/* FIXME: replace current access_cache BKL reliance with inode->i_lock */
++	spin_lock(&inode->i_lock);
+ 	nfsi->cache_validity &= ~NFS_INO_INVALID_ACCESS;
++	spin_unlock(&inode->i_lock);
+ 	cache->jiffies = set->jiffies;
+ 	cache->mask = set->mask;
+ }
+diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
+index ee27578277f3..541b418327c8 100644
+--- a/fs/nfs/inode.c
++++ b/fs/nfs/inode.c
+@@ -615,6 +615,8 @@ nfs_zap_caches(struct inode *inode)
+ 	struct nfs_inode *nfsi = NFS_I(inode);
+ 	int mode = inode->i_mode;
+ 
++	spin_lock(&inode->i_lock);
++
+ 	NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);
+ 	NFS_ATTRTIMEO_UPDATE(inode) = jiffies;
+ 
+@@ -623,6 +625,8 @@ nfs_zap_caches(struct inode *inode)
+ 		nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
+ 	else
+ 		nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
++
++	spin_unlock(&inode->i_lock);
+ }
+ 
+ static void nfs_zap_acl_cache(struct inode *inode)
+@@ -632,7 +636,9 @@ static void nfs_zap_acl_cache(struct inode *inode)
+ 	clear_acl_cache = NFS_PROTO(inode)->clear_acl_cache;
+ 	if (clear_acl_cache != NULL)
+ 		clear_acl_cache(inode);
++	spin_lock(&inode->i_lock);
+ 	NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_ACL;
++	spin_unlock(&inode->i_lock);
+ }
+ 
+ /*
+@@ -841,7 +847,9 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr)
+ 			inode->i_uid = attr->ia_uid;
+ 		if ((attr->ia_valid & ATTR_GID) != 0)
+ 			inode->i_gid = attr->ia_gid;
++		spin_lock(&inode->i_lock);
+ 		NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
++		spin_unlock(&inode->i_lock);
+ 	}
+ 	if ((attr->ia_valid & ATTR_SIZE) != 0) {
+ 		inode->i_size = attr->ia_size;
+@@ -1082,6 +1090,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
+ 			 (long long)NFS_FILEID(inode), status);
+ 		goto out;
+ 	}
++	spin_lock(&inode->i_lock);
+ 	cache_validity = nfsi->cache_validity;
+ 	nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE;
+ 
+@@ -1091,6 +1100,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
+ 	 */
+ 	if (verifier == nfsi->cache_change_attribute)
+ 		nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME);
++	spin_unlock(&inode->i_lock);
+ 
+ 	nfs_revalidate_mapping(inode, inode->i_mapping);
+ 
+@@ -1149,12 +1159,16 @@ void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
+ 			nfs_wb_all(inode);
+ 		}
+ 		invalidate_inode_pages2(mapping);
++
++		spin_lock(&inode->i_lock);
+ 		nfsi->cache_validity &= ~NFS_INO_INVALID_DATA;
+ 		if (S_ISDIR(inode->i_mode)) {
+ 			memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf));
+ 			/* This ensures we revalidate child dentries */
+ 			nfsi->cache_change_attribute++;
+ 		}
++		spin_unlock(&inode->i_lock);
++
+ 		dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n",
+ 				inode->i_sb->s_id,
+ 				(long long)NFS_FILEID(inode));
+@@ -1184,10 +1198,12 @@ void nfs_end_data_update(struct inode *inode)
+ 
+ 	if (!nfs_have_delegation(inode, FMODE_READ)) {
+ 		/* Mark the attribute cache for revalidation */
++		spin_lock(&inode->i_lock);
+ 		nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
+ 		/* Directories and symlinks: invalidate page cache too */
+ 		if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+ 			nfsi->cache_validity |= NFS_INO_INVALID_DATA;
++		spin_unlock(&inode->i_lock);
+ 	}
+ 	nfsi->cache_change_attribute ++;
+ 	atomic_dec(&nfsi->data_updates);
+@@ -1212,6 +1228,8 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
+ 	if (nfs_have_delegation(inode, FMODE_READ))
+ 		return 0;
+ 
++	spin_lock(&inode->i_lock);
++
+ 	/* Are we in the process of updating data on the server? */
+ 	data_unstable = nfs_caches_unstable(inode);
+ 
+@@ -1226,13 +1244,17 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
+ 		}
+ 	}
+ 
+-	if ((fattr->valid & NFS_ATTR_FATTR) == 0)
++	if ((fattr->valid & NFS_ATTR_FATTR) == 0) {
++		spin_unlock(&inode->i_lock);
+ 		return 0;
++	}
+ 
+ 	/* Has the inode gone and changed behind our back? */
+ 	if (nfsi->fileid != fattr->fileid
+-			|| (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT))
++			|| (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) {
++		spin_unlock(&inode->i_lock);
+ 		return -EIO;
++	}
+ 
+ 	cur_size = i_size_read(inode);
+  	new_isize = nfs_size_to_loff_t(fattr->size);
+@@ -1271,6 +1293,7 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
+ 		nfsi->cache_validity |= NFS_INO_INVALID_ATIME;
+ 
+ 	nfsi->read_cache_jiffies = fattr->timestamp;
++	spin_unlock(&inode->i_lock);
+ 	return 0;
+ }
+ 
+@@ -1309,11 +1332,15 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign
+ 		goto out_err;
+ 	}
+ 
++	spin_lock(&inode->i_lock);
++
+ 	/*
+ 	 * Make sure the inode's type hasn't changed.
+ 	 */
+-	if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT))
++	if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) {
++		spin_unlock(&inode->i_lock);
+ 		goto out_changed;
++	}
+ 
+ 	/*
+ 	 * Update the read time so we don't revalidate too often.
+@@ -1406,6 +1433,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign
+ 	if (!nfs_have_delegation(inode, FMODE_READ))
+ 		nfsi->cache_validity |= invalid;
+ 
++	spin_unlock(&inode->i_lock);
+ 	return 0;
+  out_changed:
+ 	/*
+diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c
+index a020e650ffc2..6a5bbc0ae941 100644
+--- a/fs/nfs/nfs3acl.c
++++ b/fs/nfs/nfs3acl.c
+@@ -308,7 +308,9 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
+ 	nfs_begin_data_update(inode);
+ 	status = rpc_call(server->client_acl, ACLPROC3_SETACL,
+ 			  &args, &fattr, 0);
++	spin_lock(&inode->i_lock);
+ 	NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ACCESS;
++	spin_unlock(&inode->i_lock);
+ 	nfs_end_data_update(inode);
+ 	dprintk("NFS reply setacl: %d\n", status);
+ 
+diff --git a/fs/nfs/read.c b/fs/nfs/read.c
+index 90df0500ca1b..6ceb1d471f20 100644
+--- a/fs/nfs/read.c
++++ b/fs/nfs/read.c
+@@ -140,7 +140,9 @@ static int nfs_readpage_sync(struct nfs_open_context *ctx, struct inode *inode,
+ 		if (rdata->res.eof != 0 || result == 0)
+ 			break;
+ 	} while (count);
++	spin_lock(&inode->i_lock);
+ 	NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME;
++	spin_unlock(&inode->i_lock);
+ 
+ 	if (count)
+ 		memclear_highpage_flush(page, rdata->args.pgbase, count);
+@@ -473,7 +475,9 @@ void nfs_readpage_result(struct rpc_task *task)
+ 		}
+ 		task->tk_status = -EIO;
+ 	}
++	spin_lock(&data->inode->i_lock);
+ 	NFS_I(data->inode)->cache_validity |= NFS_INO_INVALID_ATIME;
++	spin_unlock(&data->inode->i_lock);
+ 	data->complete(data, status);
+ }
+ 
+diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
+index deef9567788a..9a6047ff1b25 100644
+--- a/include/linux/nfs_fs.h
++++ b/include/linux/nfs_fs.h
+@@ -238,8 +238,11 @@ static inline int nfs_caches_unstable(struct inode *inode)
+ 
+ static inline void NFS_CACHEINV(struct inode *inode)
+ {
+-	if (!nfs_caches_unstable(inode))
++	if (!nfs_caches_unstable(inode)) {
++		spin_lock(&inode->i_lock);
+ 		NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS;
++		spin_unlock(&inode->i_lock);
++	}
+ }
+ 
+ static inline int nfs_server_capable(struct inode *inode, int cap)

commit 412d582ec1dd59aab2353f8cb7e74f2c79cd20b9
+Author: Chuck Lever 
+Date:   Thu Aug 18 11:24:11 2005 -0700
+
+    [PATCH] NFS: use atomic bitops to manipulate flags in nfsi->flags
+    
+    Introduce atomic bitops to manipulate the bits in the nfs_inode structure's
+    "flags" field.
+    
+    Using bitops means we can use a generic wait_on_bit call instead of an ad hoc
+    locking scheme in fs/nfs/inode.c, so we can remove the "nfs_i_wait" field from
+    nfs_inode at the same time.
+    
+    The other new flags field will continue to use bitmask and logic AND and OR.
+    This permits several flags to be set at the same time efficiently.  The
+    following patch adds a spin lock to protect these flags, and this spin lock
+    will later cover other fields in the nfs_inode structure, amortizing the cost
+    of using this type of serialization.
+    
+    Test plan:
+     Millions of fsx ops on SMP clients.
+    
+    Signed-off-by: Chuck Lever 
+    Cc: Trond Myklebust 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
+index 5732e13cd0da..27cf5577f239 100644
+--- a/fs/nfs/dir.c
++++ b/fs/nfs/dir.c
+@@ -182,7 +182,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
+ 		/* We requested READDIRPLUS, but the server doesn't grok it */
+ 		if (error == -ENOTSUPP && desc->plus) {
+ 			NFS_SERVER(inode)->caps &= ~NFS_CAP_READDIRPLUS;
+-			NFS_FLAGS(inode) &= ~NFS_INO_ADVISE_RDPLUS;
++			clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode));
+ 			desc->plus = 0;
+ 			goto again;
+ 		}
+@@ -545,7 +545,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ 			break;
+ 		}
+ 		if (res == -ETOOSMALL && desc->plus) {
+-			NFS_FLAGS(inode) &= ~NFS_INO_ADVISE_RDPLUS;
++			clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode));
+ 			nfs_zap_caches(inode);
+ 			desc->plus = 0;
+ 			desc->entry->eof = 0;
+diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
+index 622184553516..ee27578277f3 100644
+--- a/fs/nfs/inode.c
++++ b/fs/nfs/inode.c
+@@ -739,7 +739,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
+ 			inode->i_fop = &nfs_dir_operations;
+ 			if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS)
+ 			    && fattr->size <= NFS_LIMIT_READDIRPLUS)
+-				NFS_FLAGS(inode) |= NFS_INO_ADVISE_RDPLUS;
++				set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode));
+ 		} else if (S_ISLNK(inode->i_mode))
+ 			inode->i_op = &nfs_symlink_inode_operations;
+ 		else
+@@ -849,26 +849,43 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr)
+ 	}
+ }
+ 
++static int nfs_wait_schedule(void *word)
++{
++	if (signal_pending(current))
++		return -ERESTARTSYS;
++	schedule();
++	return 0;
++}
++
+ /*
+  * Wait for the inode to get unlocked.
+- * (Used for NFS_INO_LOCKED and NFS_INO_REVALIDATING).
+  */
+-static int
+-nfs_wait_on_inode(struct inode *inode, int flag)
++static int nfs_wait_on_inode(struct inode *inode)
+ {
+ 	struct rpc_clnt	*clnt = NFS_CLIENT(inode);
+ 	struct nfs_inode *nfsi = NFS_I(inode);
+-
++	sigset_t oldmask;
+ 	int error;
+-	if (!(NFS_FLAGS(inode) & flag))
+-		return 0;
++
+ 	atomic_inc(&inode->i_count);
+-	error = nfs_wait_event(clnt, nfsi->nfs_i_wait,
+-				!(NFS_FLAGS(inode) & flag));
++	rpc_clnt_sigmask(clnt, &oldmask);
++	error = wait_on_bit_lock(&nfsi->flags, NFS_INO_REVALIDATING,
++					nfs_wait_schedule, TASK_INTERRUPTIBLE);
++	rpc_clnt_sigunmask(clnt, &oldmask);
+ 	iput(inode);
++
+ 	return error;
+ }
+ 
++static void nfs_wake_up_inode(struct inode *inode)
++{
++	struct nfs_inode *nfsi = NFS_I(inode);
++
++	clear_bit(NFS_INO_REVALIDATING, &nfsi->flags);
++	smp_mb__after_clear_bit();
++	wake_up_bit(&nfsi->flags, NFS_INO_REVALIDATING);
++}
++
+ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+ {
+ 	struct inode *inode = dentry->d_inode;
+@@ -1029,18 +1046,19 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
+ 	if (NFS_STALE(inode))
+  		goto out_nowait;
+ 
+-	while (NFS_REVALIDATING(inode)) {
+-		status = nfs_wait_on_inode(inode, NFS_INO_REVALIDATING);
+-		if (status < 0)
+-			goto out_nowait;
+-		if (NFS_ATTRTIMEO(inode) == 0)
+-			continue;
+-		if (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ATIME))
+-			continue;
+-		status = NFS_STALE(inode) ? -ESTALE : 0;
+-		goto out_nowait;
++	status = nfs_wait_on_inode(inode);
++	if (status < 0)
++		goto out;
++	if (NFS_STALE(inode)) {
++		status = -ESTALE;
++		/* Do we trust the cached ESTALE? */
++		if (NFS_ATTRTIMEO(inode) != 0) {
++			if (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ATIME)) {
++				/* no */
++			} else
++				goto out;
++		}
+ 	}
+-	NFS_FLAGS(inode) |= NFS_INO_REVALIDATING;
+ 
+ 	/* Protect against RPC races by saving the change attribute */
+ 	verifier = nfs_save_change_attribute(inode);
+@@ -1052,7 +1070,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
+ 		if (status == -ESTALE) {
+ 			nfs_zap_caches(inode);
+ 			if (!S_ISDIR(inode->i_mode))
+-				NFS_FLAGS(inode) |= NFS_INO_STALE;
++				set_bit(NFS_INO_STALE, &NFS_FLAGS(inode));
+ 		}
+ 		goto out;
+ 	}
+@@ -1083,9 +1101,9 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
+ 		inode->i_sb->s_id,
+ 		(long long)NFS_FILEID(inode));
+ 
+-out:
+-	NFS_FLAGS(inode) &= ~NFS_INO_REVALIDATING;
+-	wake_up(&nfsi->nfs_i_wait);
++ out:
++	nfs_wake_up_inode(inode);
++
+  out_nowait:
+ 	unlock_kernel();
+ 	return status;
+@@ -1404,7 +1422,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign
+ 	 */
+ 	nfs_invalidate_inode(inode);
+  out_err:
+-	NFS_FLAGS(inode) |= NFS_INO_STALE;
++	set_bit(NFS_INO_STALE, &NFS_FLAGS(inode));
+ 	return -ESTALE;
+ }
+ 
+@@ -1996,7 +2014,6 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+ 		nfsi->ndirty = 0;
+ 		nfsi->ncommit = 0;
+ 		nfsi->npages = 0;
+-		init_waitqueue_head(&nfsi->nfs_i_wait);
+ 		nfs4_init_once(nfsi);
+ 	}
+ }
+diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
+index 229a1755842a..deef9567788a 100644
+--- a/include/linux/nfs_fs.h
++++ b/include/linux/nfs_fs.h
+@@ -112,8 +112,8 @@ struct nfs_inode {
+ 	/*
+ 	 * Various flags
+ 	 */
+-	unsigned int		flags;
+-	unsigned long		cache_validity;
++	unsigned long		flags;			/* atomic bit ops */
++	unsigned long		cache_validity;		/* bit mask */
+ 
+ 	/*
+ 	 * read_cache_jiffies is when we started read-caching this inode,
+@@ -175,8 +175,6 @@ struct nfs_inode {
+ 	/* Open contexts for shared mmap writes */
+ 	struct list_head	open_files;
+ 
+-	wait_queue_head_t	nfs_i_wait;
+-
+ #ifdef CONFIG_NFS_V4
+ 	struct nfs4_cached_acl	*nfs4_acl;
+         /* NFSv4 state */
+@@ -199,11 +197,11 @@ struct nfs_inode {
+ #define NFS_INO_REVAL_PAGECACHE	0x0020		/* must revalidate pagecache */
+ 
+ /*
+- * Legal values of flags field
++ * Bit offsets in flags field
+  */
+-#define NFS_INO_REVALIDATING	0x0001		/* revalidating attrs */
+-#define NFS_INO_ADVISE_RDPLUS	0x0002		/* advise readdirplus */
+-#define NFS_INO_STALE		0x0004		/* possible stale inode */
++#define NFS_INO_REVALIDATING	(0)		/* revalidating attrs */
++#define NFS_INO_ADVISE_RDPLUS	(1)		/* advise readdirplus */
++#define NFS_INO_STALE		(2)		/* possible stale inode */
+ 
+ static inline struct nfs_inode *NFS_I(struct inode *inode)
+ {
+@@ -229,8 +227,7 @@ static inline struct nfs_inode *NFS_I(struct inode *inode)
+ #define NFS_ATTRTIMEO_UPDATE(inode)	(NFS_I(inode)->attrtimeo_timestamp)
+ 
+ #define NFS_FLAGS(inode)		(NFS_I(inode)->flags)
+-#define NFS_REVALIDATING(inode)		(NFS_FLAGS(inode) & NFS_INO_REVALIDATING)
+-#define NFS_STALE(inode)		(NFS_FLAGS(inode) & NFS_INO_STALE)
++#define NFS_STALE(inode)		(test_bit(NFS_INO_STALE, &NFS_FLAGS(inode)))
+ 
+ #define NFS_FILEID(inode)		(NFS_I(inode)->fileid)
+ 
+@@ -252,7 +249,7 @@ static inline int nfs_server_capable(struct inode *inode, int cap)
+ 
+ static inline int NFS_USE_READDIRPLUS(struct inode *inode)
+ {
+-	return NFS_FLAGS(inode) & NFS_INO_ADVISE_RDPLUS;
++	return test_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode));
+ }
+ 
+ /**

commit 5529680981807b44abf3be30fb6d612ff04f68ff
+Author: Chuck Lever 
+Date:   Thu Aug 18 11:24:09 2005 -0700
+
+    [PATCH] NFS: split nfsi->flags into two fields
+    
+    Certain bits in nfsi->flags can be manipulated with atomic bitops, and some
+    are better manipulated via logical bitmask operations.
+    
+    This patch splits the flags field into two.  The next patch introduces atomic
+    bitops for one of the fields.
+    
+    Test plan:
+     Millions of fsx ops on SMP clients.
+    
+    Signed-off-by: Chuck Lever 
+    Cc: Trond Myklebust 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
+index b38a57e78a63..5732e13cd0da 100644
+--- a/fs/nfs/dir.c
++++ b/fs/nfs/dir.c
+@@ -189,7 +189,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
+ 		goto error;
+ 	}
+ 	SetPageUptodate(page);
+-	NFS_FLAGS(inode) |= NFS_INO_INVALID_ATIME;
++	NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME;
+ 	/* Ensure consistent page alignment of the data.
+ 	 * Note: assumes we have exclusive access to this mapping either
+ 	 *	 through inode->i_sem or some other mechanism.
+@@ -462,7 +462,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
+ 						page,
+ 						NFS_SERVER(inode)->dtsize,
+ 						desc->plus);
+-	NFS_FLAGS(inode) |= NFS_INO_INVALID_ATIME;
++	NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME;
+ 	desc->page = page;
+ 	desc->ptr = kmap(page);		/* matching kunmap in nfs_do_filldir */
+ 	if (desc->error >= 0) {
+@@ -608,7 +608,7 @@ static inline int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
+ {
+ 	if (IS_ROOT(dentry))
+ 		return 1;
+-	if ((NFS_FLAGS(dir) & NFS_INO_INVALID_ATTR) != 0
++	if ((NFS_I(dir)->cache_validity & NFS_INO_INVALID_ATTR) != 0
+ 			|| nfs_attribute_timeout(dir))
+ 		return 0;
+ 	return nfs_verify_change_attribute(dir, (unsigned long)dentry->d_fsdata);
+@@ -1575,11 +1575,12 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 
+ int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, struct nfs_access_entry *res)
+ {
+-	struct nfs_access_entry *cache = &NFS_I(inode)->cache_access;
++	struct nfs_inode *nfsi = NFS_I(inode);
++	struct nfs_access_entry *cache = &nfsi->cache_access;
+ 
+ 	if (cache->cred != cred
+ 			|| time_after(jiffies, cache->jiffies + NFS_ATTRTIMEO(inode))
+-			|| (NFS_FLAGS(inode) & NFS_INO_INVALID_ACCESS))
++			|| (nfsi->cache_validity & NFS_INO_INVALID_ACCESS))
+ 		return -ENOENT;
+ 	memcpy(res, cache, sizeof(*res));
+ 	return 0;
+@@ -1587,14 +1588,15 @@ int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, struct nfs
+ 
+ void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set)
+ {
+-	struct nfs_access_entry *cache = &NFS_I(inode)->cache_access;
++	struct nfs_inode *nfsi = NFS_I(inode);
++	struct nfs_access_entry *cache = &nfsi->cache_access;
+ 
+ 	if (cache->cred != set->cred) {
+ 		if (cache->cred)
+ 			put_rpccred(cache->cred);
+ 		cache->cred = get_rpccred(set->cred);
+ 	}
+-	NFS_FLAGS(inode) &= ~NFS_INO_INVALID_ACCESS;
++	nfsi->cache_validity &= ~NFS_INO_INVALID_ACCESS;
+ 	cache->jiffies = set->jiffies;
+ 	cache->mask = set->mask;
+ }
+diff --git a/fs/nfs/file.c b/fs/nfs/file.c
+index 5621ba9885f4..f6b9eda925c5 100644
+--- a/fs/nfs/file.c
++++ b/fs/nfs/file.c
+@@ -134,9 +134,10 @@ nfs_file_release(struct inode *inode, struct file *filp)
+  */
+ static int nfs_revalidate_file(struct inode *inode, struct file *filp)
+ {
++	struct nfs_inode *nfsi = NFS_I(inode);
+ 	int retval = 0;
+ 
+-	if ((NFS_FLAGS(inode) & NFS_INO_REVAL_PAGECACHE) || nfs_attribute_timeout(inode))
++	if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) || nfs_attribute_timeout(inode))
+ 		retval = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
+ 	nfs_revalidate_mapping(inode, filp->f_mapping);
+ 	return 0;
+@@ -164,7 +165,7 @@ static int nfs_revalidate_file_size(struct inode *inode, struct file *filp)
+ 		goto force_reval;
+ 	if (nfsi->npages != 0)
+ 		return 0;
+-	if (!(NFS_FLAGS(inode) & NFS_INO_REVAL_PAGECACHE) && !nfs_attribute_timeout(inode))
++	if (!(nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) && !nfs_attribute_timeout(inode))
+ 		return 0;
+ force_reval:
+ 	return __nfs_revalidate_inode(server, inode);
+diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
+index bb7ca022bcb2..622184553516 100644
+--- a/fs/nfs/inode.c
++++ b/fs/nfs/inode.c
+@@ -620,9 +620,9 @@ nfs_zap_caches(struct inode *inode)
+ 
+ 	memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
+ 	if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))
+-		nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
++		nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
+ 	else
+-		nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
++		nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
+ }
+ 
+ static void nfs_zap_acl_cache(struct inode *inode)
+@@ -632,7 +632,7 @@ static void nfs_zap_acl_cache(struct inode *inode)
+ 	clear_acl_cache = NFS_PROTO(inode)->clear_acl_cache;
+ 	if (clear_acl_cache != NULL)
+ 		clear_acl_cache(inode);
+-	NFS_I(inode)->flags &= ~NFS_INO_INVALID_ACL;
++	NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_ACL;
+ }
+ 
+ /*
+@@ -841,7 +841,7 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr)
+ 			inode->i_uid = attr->ia_uid;
+ 		if ((attr->ia_valid & ATTR_GID) != 0)
+ 			inode->i_gid = attr->ia_gid;
+-		NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
++		NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
+ 	}
+ 	if ((attr->ia_valid & ATTR_SIZE) != 0) {
+ 		inode->i_size = attr->ia_size;
+@@ -872,8 +872,7 @@ nfs_wait_on_inode(struct inode *inode, int flag)
+ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+ {
+ 	struct inode *inode = dentry->d_inode;
+-	struct nfs_inode *nfsi = NFS_I(inode);
+-	int need_atime = nfsi->flags & NFS_INO_INVALID_ATIME;
++	int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME;
+ 	int err;
+ 
+ 	if (__IS_FLG(inode, MS_NOATIME))
+@@ -1019,7 +1018,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
+ 	struct nfs_fattr fattr;
+ 	struct nfs_inode *nfsi = NFS_I(inode);
+ 	unsigned long verifier;
+-	unsigned int flags;
++	unsigned long cache_validity;
+ 
+ 	dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n",
+ 		inode->i_sb->s_id, (long long)NFS_FILEID(inode));
+@@ -1036,7 +1035,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
+ 			goto out_nowait;
+ 		if (NFS_ATTRTIMEO(inode) == 0)
+ 			continue;
+-		if (NFS_FLAGS(inode) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ATIME))
++		if (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ATIME))
+ 			continue;
+ 		status = NFS_STALE(inode) ? -ESTALE : 0;
+ 		goto out_nowait;
+@@ -1065,18 +1064,21 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
+ 			 (long long)NFS_FILEID(inode), status);
+ 		goto out;
+ 	}
+-	flags = nfsi->flags;
+-	nfsi->flags &= ~NFS_INO_REVAL_PAGECACHE;
++	cache_validity = nfsi->cache_validity;
++	nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE;
++
+ 	/*
+ 	 * We may need to keep the attributes marked as invalid if
+ 	 * we raced with nfs_end_attr_update().
+ 	 */
+ 	if (verifier == nfsi->cache_change_attribute)
+-		nfsi->flags &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME);
+-	/* Do the page cache invalidation */
++		nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME);
++
+ 	nfs_revalidate_mapping(inode, inode->i_mapping);
+-	if (flags & NFS_INO_INVALID_ACL)
++
++	if (cache_validity & NFS_INO_INVALID_ACL)
+ 		nfs_zap_acl_cache(inode);
++
+ 	dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n",
+ 		inode->i_sb->s_id,
+ 		(long long)NFS_FILEID(inode));
+@@ -1107,7 +1109,7 @@ int nfs_attribute_timeout(struct inode *inode)
+  */
+ int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
+ {
+-	if (!(NFS_FLAGS(inode) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))
++	if (!(NFS_I(inode)->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))
+ 			&& !nfs_attribute_timeout(inode))
+ 		return NFS_STALE(inode) ? -ESTALE : 0;
+ 	return __nfs_revalidate_inode(server, inode);
+@@ -1122,14 +1124,14 @@ void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
+ {
+ 	struct nfs_inode *nfsi = NFS_I(inode);
+ 
+-	if (nfsi->flags & NFS_INO_INVALID_DATA) {
++	if (nfsi->cache_validity & NFS_INO_INVALID_DATA) {
+ 		if (S_ISREG(inode->i_mode)) {
+ 			if (filemap_fdatawrite(mapping) == 0)
+ 				filemap_fdatawait(mapping);
+ 			nfs_wb_all(inode);
+ 		}
+ 		invalidate_inode_pages2(mapping);
+-		nfsi->flags &= ~NFS_INO_INVALID_DATA;
++		nfsi->cache_validity &= ~NFS_INO_INVALID_DATA;
+ 		if (S_ISDIR(inode->i_mode)) {
+ 			memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf));
+ 			/* This ensures we revalidate child dentries */
+@@ -1164,10 +1166,10 @@ void nfs_end_data_update(struct inode *inode)
+ 
+ 	if (!nfs_have_delegation(inode, FMODE_READ)) {
+ 		/* Mark the attribute cache for revalidation */
+-		nfsi->flags |= NFS_INO_INVALID_ATTR;
++		nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
+ 		/* Directories and symlinks: invalidate page cache too */
+ 		if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+-			nfsi->flags |= NFS_INO_INVALID_DATA;
++			nfsi->cache_validity |= NFS_INO_INVALID_DATA;
+ 	}
+ 	nfsi->cache_change_attribute ++;
+ 	atomic_dec(&nfsi->data_updates);
+@@ -1200,9 +1202,9 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
+ 				&& nfsi->change_attr == fattr->pre_change_attr)
+ 			nfsi->change_attr = fattr->change_attr;
+ 		if (nfsi->change_attr != fattr->change_attr) {
+-			nfsi->flags |= NFS_INO_INVALID_ATTR;
++			nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
+ 			if (!data_unstable)
+-				nfsi->flags |= NFS_INO_REVAL_PAGECACHE;
++				nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE;
+ 		}
+ 	}
+ 
+@@ -1227,28 +1229,28 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
+ 
+ 	/* Verify a few of the more important attributes */
+ 	if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) {
+-		nfsi->flags |= NFS_INO_INVALID_ATTR;
++		nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
+ 		if (!data_unstable)
+-			nfsi->flags |= NFS_INO_REVAL_PAGECACHE;
++			nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE;
+ 	}
+ 	if (cur_size != new_isize) {
+-		nfsi->flags |= NFS_INO_INVALID_ATTR;
++		nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
+ 		if (nfsi->npages == 0)
+-			nfsi->flags |= NFS_INO_REVAL_PAGECACHE;
++			nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE;
+ 	}
+ 
+ 	/* Have any file permissions changed? */
+ 	if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)
+ 			|| inode->i_uid != fattr->uid
+ 			|| inode->i_gid != fattr->gid)
+-		nfsi->flags |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL;
++		nfsi->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL;
+ 
+ 	/* Has the link count changed? */
+ 	if (inode->i_nlink != fattr->nlink)
+-		nfsi->flags |= NFS_INO_INVALID_ATTR;
++		nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
+ 
+ 	if (!timespec_equal(&inode->i_atime, &fattr->atime))
+-		nfsi->flags |= NFS_INO_INVALID_ATIME;
++		nfsi->cache_validity |= NFS_INO_INVALID_ATIME;
+ 
+ 	nfsi->read_cache_jiffies = fattr->timestamp;
+ 	return 0;
+@@ -1384,7 +1386,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign
+ 				|| S_ISLNK(inode->i_mode)))
+ 		invalid &= ~NFS_INO_INVALID_DATA;
+ 	if (!nfs_have_delegation(inode, FMODE_READ))
+-		nfsi->flags |= invalid;
++		nfsi->cache_validity |= invalid;
+ 
+ 	return 0;
+  out_changed:
+@@ -1961,7 +1963,8 @@ static struct inode *nfs_alloc_inode(struct super_block *sb)
+ 	nfsi = (struct nfs_inode *)kmem_cache_alloc(nfs_inode_cachep, SLAB_KERNEL);
+ 	if (!nfsi)
+ 		return NULL;
+-	nfsi->flags = 0;
++	nfsi->flags = 0UL;
++	nfsi->cache_validity = 0UL;
+ #ifdef CONFIG_NFS_V3_ACL
+ 	nfsi->acl_access = ERR_PTR(-EAGAIN);
+ 	nfsi->acl_default = ERR_PTR(-EAGAIN);
+diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c
+index 1b7a3ef2f813..a020e650ffc2 100644
+--- a/fs/nfs/nfs3acl.c
++++ b/fs/nfs/nfs3acl.c
+@@ -308,7 +308,7 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
+ 	nfs_begin_data_update(inode);
+ 	status = rpc_call(server->client_acl, ACLPROC3_SETACL,
+ 			  &args, &fattr, 0);
+-	NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS;
++	NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ACCESS;
+ 	nfs_end_data_update(inode);
+ 	dprintk("NFS reply setacl: %d\n", status);
+ 
+diff --git a/fs/nfs/read.c b/fs/nfs/read.c
+index 6f866b8aa2d5..90df0500ca1b 100644
+--- a/fs/nfs/read.c
++++ b/fs/nfs/read.c
+@@ -140,7 +140,7 @@ static int nfs_readpage_sync(struct nfs_open_context *ctx, struct inode *inode,
+ 		if (rdata->res.eof != 0 || result == 0)
+ 			break;
+ 	} while (count);
+-	NFS_FLAGS(inode) |= NFS_INO_INVALID_ATIME;
++	NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME;
+ 
+ 	if (count)
+ 		memclear_highpage_flush(page, rdata->args.pgbase, count);
+@@ -473,7 +473,7 @@ void nfs_readpage_result(struct rpc_task *task)
+ 		}
+ 		task->tk_status = -EIO;
+ 	}
+-	NFS_FLAGS(data->inode) |= NFS_INO_INVALID_ATIME;
++	NFS_I(data->inode)->cache_validity |= NFS_INO_INVALID_ATIME;
+ 	data->complete(data, status);
+ }
+ 
+diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
+index 7d78a783c64a..229a1755842a 100644
+--- a/include/linux/nfs_fs.h
++++ b/include/linux/nfs_fs.h
+@@ -113,6 +113,7 @@ struct nfs_inode {
+ 	 * Various flags
+ 	 */
+ 	unsigned int		flags;
++	unsigned long		cache_validity;
+ 
+ 	/*
+ 	 * read_cache_jiffies is when we started read-caching this inode,
+@@ -188,17 +189,21 @@ struct nfs_inode {
+ };
+ 
+ /*
+- * Legal inode flag values
++ * Cache validity bit flags
+  */
+-#define NFS_INO_STALE		0x0001		/* possible stale inode */
+-#define NFS_INO_ADVISE_RDPLUS   0x0002          /* advise readdirplus */
+-#define NFS_INO_REVALIDATING	0x0004		/* revalidating attrs */
+-#define NFS_INO_INVALID_ATTR	0x0008		/* cached attrs are invalid */
+-#define NFS_INO_INVALID_DATA	0x0010		/* cached data is invalid */
+-#define NFS_INO_INVALID_ATIME	0x0020		/* cached atime is invalid */
+-#define NFS_INO_INVALID_ACCESS	0x0040		/* cached access cred invalid */
+-#define NFS_INO_INVALID_ACL	0x0080		/* cached acls are invalid */
+-#define NFS_INO_REVAL_PAGECACHE	0x1000		/* must revalidate pagecache */
++#define NFS_INO_INVALID_ATTR	0x0001		/* cached attrs are invalid */
++#define NFS_INO_INVALID_DATA	0x0002		/* cached data is invalid */
++#define NFS_INO_INVALID_ATIME	0x0004		/* cached atime is invalid */
++#define NFS_INO_INVALID_ACCESS	0x0008		/* cached access cred invalid */
++#define NFS_INO_INVALID_ACL	0x0010		/* cached acls are invalid */
++#define NFS_INO_REVAL_PAGECACHE	0x0020		/* must revalidate pagecache */
++
++/*
++ * Legal values of flags field
++ */
++#define NFS_INO_REVALIDATING	0x0001		/* revalidating attrs */
++#define NFS_INO_ADVISE_RDPLUS	0x0002		/* advise readdirplus */
++#define NFS_INO_STALE		0x0004		/* possible stale inode */
+ 
+ static inline struct nfs_inode *NFS_I(struct inode *inode)
+ {
+@@ -237,7 +242,7 @@ static inline int nfs_caches_unstable(struct inode *inode)
+ static inline void NFS_CACHEINV(struct inode *inode)
+ {
+ 	if (!nfs_caches_unstable(inode))
+-		NFS_FLAGS(inode) |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS;
++		NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS;
+ }
+ 
+ static inline int nfs_server_capable(struct inode *inode, int cap)

commit 6a19275ada9137435da58990c8f8d3f58e170bf1
+Author: J. Bruce Fields 
+Date:   Wed Jun 22 17:16:23 2005 +0000
+
+    [PATCH] RPC: [PATCH] improve rpcauthauth_create error returns
+    
+     Currently we return -ENOMEM for every single failure to create a new auth.
+     This is actually accurate for auth_null and auth_unix, but for auth_gss it's a
+     bit confusing.
+    
+     Allow rpcauth_create (and the ->create methods) to return errors.  With this
+     patch, the user may sometimes see an EINVAL instead.  Whee.
+    
+     Signed-off-by: J. Bruce Fields 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
+index 350c48c12639..97b3fe7ece63 100644
+--- a/fs/nfs/inode.c
++++ b/fs/nfs/inode.c
+@@ -160,11 +160,10 @@ nfs_clear_inode(struct inode *inode)
+ void
+ nfs_umount_begin(struct super_block *sb)
+ {
+-	struct nfs_server *server = NFS_SB(sb);
+-	struct rpc_clnt	*rpc;
++	struct rpc_clnt	*rpc = NFS_SB(sb)->client;
+ 
+ 	/* -EIO all pending I/O */
+-	if ((rpc = server->client) != NULL)
++	if (!IS_ERR(rpc))
+ 		rpc_killall_tasks(rpc);
+ }
+ 
+@@ -450,11 +449,14 @@ nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent)
+ 		return PTR_ERR(server->client);
+ 	/* RFC 2623, sec 2.3.2 */
+ 	if (authflavor != RPC_AUTH_UNIX) {
++		struct rpc_auth *auth;
++
+ 		server->client_sys = rpc_clone_client(server->client);
+ 		if (IS_ERR(server->client_sys))
+ 			return PTR_ERR(server->client_sys);
+-		if (!rpcauth_create(RPC_AUTH_UNIX, server->client_sys))
+-			return -ENOMEM;
++		auth = rpcauth_create(RPC_AUTH_UNIX, server->client_sys);
++		if (IS_ERR(auth))
++			return PTR_ERR(auth);
+ 	} else {
+ 		atomic_inc(&server->client->cl_count);
+ 		server->client_sys = server->client;
+@@ -1450,6 +1452,7 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
+ 	memset(server, 0, sizeof(struct nfs_server));
+ 	/* Zero out the NFS state stuff */
+ 	init_nfsv4_state(server);
++	server->client = server->client_sys = ERR_PTR(-EINVAL);
+ 
+ 	root = &server->fh;
+ 	if (data->flags & NFS_MOUNT_VER3)
+@@ -1506,9 +1509,9 @@ static void nfs_kill_super(struct super_block *s)
+ 
+ 	kill_anon_super(s);
+ 
+-	if (server->client != NULL && !IS_ERR(server->client))
++	if (!IS_ERR(server->client))
+ 		rpc_shutdown_client(server->client);
+-	if (server->client_sys != NULL && !IS_ERR(server->client_sys))
++	if (!IS_ERR(server->client_sys))
+ 		rpc_shutdown_client(server->client_sys);
+ 
+ 	if (!(server->flags & NFS_MOUNT_NONLM))
+@@ -1650,7 +1653,7 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
+ 	}
+ 
+ 	down_write(&clp->cl_sem);
+-	if (clp->cl_rpcclient == NULL) {
++	if (IS_ERR(clp->cl_rpcclient)) {
+ 		xprt = xprt_create_proto(proto, &server->addr, &timeparms);
+ 		if (IS_ERR(xprt)) {
+ 			up_write(&clp->cl_sem);
+@@ -1711,9 +1714,12 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
+ 	}
+ 
+ 	if (clnt->cl_auth->au_flavor != authflavour) {
+-		if (rpcauth_create(authflavour, clnt) == NULL) {
++		struct rpc_auth *auth;
++
++		auth = rpcauth_create(authflavour, clnt);
++		if (IS_ERR(auth)) {
+ 			dprintk("%s: couldn't create credcache!\n", __FUNCTION__);
+-			return -ENOMEM;
++			return PTR_ERR(auth);
+ 		}
+ 	}
+ 
+@@ -1788,6 +1794,7 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
+ 	memset(server, 0, sizeof(struct nfs_server));
+ 	/* Zero out the NFS state stuff */
+ 	init_nfsv4_state(server);
++	server->client = server->client_sys = ERR_PTR(-EINVAL);
+ 
+ 	p = nfs_copy_user_string(NULL, &data->hostname, 256);
+ 	if (IS_ERR(p))
+diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
+index 17b187f2d776..591ad1d51880 100644
+--- a/fs/nfs/nfs4state.c
++++ b/fs/nfs/nfs4state.c
+@@ -110,6 +110,7 @@ nfs4_alloc_client(struct in_addr *addr)
+ 	INIT_LIST_HEAD(&clp->cl_superblocks);
+ 	init_waitqueue_head(&clp->cl_waitq);
+ 	rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client");
++	clp->cl_rpcclient = ERR_PTR(-EINVAL);
+ 	clp->cl_boot_time = CURRENT_TIME;
+ 	clp->cl_state = 1 << NFS4CLNT_OK;
+ 	return clp;
+@@ -131,7 +132,7 @@ nfs4_free_client(struct nfs4_client *clp)
+ 	if (clp->cl_cred)
+ 		put_rpccred(clp->cl_cred);
+ 	nfs_idmap_delete(clp);
+-	if (clp->cl_rpcclient)
++	if (!IS_ERR(clp->cl_rpcclient))
+ 		rpc_shutdown_client(clp->cl_rpcclient);
+ 	kfree(clp);
+ 	nfs_callback_down();
+diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
+index 9bcec9b927b9..505e2d4b3d62 100644
+--- a/net/sunrpc/auth.c
++++ b/net/sunrpc/auth.c
+@@ -66,10 +66,10 @@ rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt)
+ 	u32			flavor = pseudoflavor_to_flavor(pseudoflavor);
+ 
+ 	if (flavor >= RPC_AUTH_MAXFLAVOR || !(ops = auth_flavors[flavor]))
+-		return NULL;
++		return ERR_PTR(-EINVAL);
+ 	auth = ops->create(clnt, pseudoflavor);
+-	if (!auth)
+-		return NULL;
++	if (IS_ERR(auth))
++		return auth;
+ 	if (clnt->cl_auth)
+ 		rpcauth_destroy(clnt->cl_auth);
+ 	clnt->cl_auth = auth;
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index 7d88db83ab12..2f7b867161d2 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -660,14 +660,16 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
+ {
+ 	struct gss_auth *gss_auth;
+ 	struct rpc_auth * auth;
++	int err = -ENOMEM; /* XXX? */
+ 
+ 	dprintk("RPC:      creating GSS authenticator for client %p\n",clnt);
+ 
+ 	if (!try_module_get(THIS_MODULE))
+-		return NULL;
++		return ERR_PTR(err);
+ 	if (!(gss_auth = kmalloc(sizeof(*gss_auth), GFP_KERNEL)))
+ 		goto out_dec;
+ 	gss_auth->client = clnt;
++	err = -EINVAL;
+ 	gss_auth->mech = gss_mech_get_by_pseudoflavor(flavor);
+ 	if (!gss_auth->mech) {
+ 		printk(KERN_WARNING "%s: Pseudoflavor %d not found!",
+@@ -686,15 +688,18 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
+ 	auth->au_flavor = flavor;
+ 	atomic_set(&auth->au_count, 1);
+ 
+-	if (rpcauth_init_credcache(auth, GSS_CRED_EXPIRE) < 0)
++	err = rpcauth_init_credcache(auth, GSS_CRED_EXPIRE);
++	if (err)
+ 		goto err_put_mech;
+ 
+ 	snprintf(gss_auth->path, sizeof(gss_auth->path), "%s/%s",
+ 			clnt->cl_pathname,
+ 			gss_auth->mech->gm_name);
+ 	gss_auth->dentry = rpc_mkpipe(gss_auth->path, clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
+-	if (IS_ERR(gss_auth->dentry))
++	if (IS_ERR(gss_auth->dentry)) {
++		err = PTR_ERR(gss_auth->dentry);
+ 		goto err_put_mech;
++	}
+ 
+ 	return auth;
+ err_put_mech:
+@@ -703,7 +708,7 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
+ 	kfree(gss_auth);
+ out_dec:
+ 	module_put(THIS_MODULE);
+-	return NULL;
++	return ERR_PTR(err);
+ }
+ 
+ static void
+diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
+index b36797ad8083..9da1deb482e2 100644
+--- a/net/sunrpc/clnt.c
++++ b/net/sunrpc/clnt.c
+@@ -103,6 +103,7 @@ rpc_new_client(struct rpc_xprt *xprt, char *servname,
+ {
+ 	struct rpc_version	*version;
+ 	struct rpc_clnt		*clnt = NULL;
++	struct rpc_auth		*auth;
+ 	int err;
+ 	int len;
+ 
+@@ -157,10 +158,11 @@ rpc_new_client(struct rpc_xprt *xprt, char *servname,
+ 	if (err < 0)
+ 		goto out_no_path;
+ 
+-	err = -ENOMEM;
+-	if (!rpcauth_create(flavor, clnt)) {
++	auth = rpcauth_create(flavor, clnt);
++	if (IS_ERR(auth)) {
+ 		printk(KERN_INFO "RPC: Couldn't create auth handle (flavor %u)\n",
+ 				flavor);
++		err = PTR_ERR(auth);
+ 		goto out_no_auth;
+ 	}
+ 

commit 438b6fdebf2a2e8573e7290bc176feb4d4475f43
+Author: J. Bruce Fields 
+Date:   Wed Jun 22 17:16:23 2005 +0000
+
+    [PATCH] RPC: Don't fall back from krb5p to krb5i
+    
+     We shouldn't be silently falling back from krb5p to krb5i.
+    
+     Signed-off-by: J. Bruce Fields 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index a33b627cbef4..7d88db83ab12 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -675,9 +675,8 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
+ 		goto err_free;
+ 	}
+ 	gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor);
+-	/* FIXME: Will go away once privacy support is merged in */
+-	if (gss_auth->service == RPC_GSS_SVC_PRIVACY)
+-		gss_auth->service = RPC_GSS_SVC_INTEGRITY;
++	if (gss_auth->service == 0)
++		goto err_put_mech;
+ 	INIT_LIST_HEAD(&gss_auth->upcalls);
+ 	spin_lock_init(&gss_auth->lock);
+ 	auth = &gss_auth->rpc_auth;

commit e50a1c2e1f816c81eed6a589019052cb44189267
+Author: J. Bruce Fields 
+Date:   Wed Jun 22 17:16:23 2005 +0000
+
+    [PATCH] NFSv4: client-side caching NFSv4 ACLs
+    
+     Add nfs4_acl field to the nfs_inode, and use it to cache acls.  Only cache
+     acls of size up to a page.  Also prepare for up to a page of acl data even
+     when the user doesn't pass in a buffer, as when they want to get the acl
+     length to decide what size buffer to allocate.
+    
+     Signed-off-by: J. Bruce Fields 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
+index c45bd52cc1d7..350c48c12639 100644
+--- a/fs/nfs/inode.c
++++ b/fs/nfs/inode.c
+@@ -142,10 +142,6 @@ nfs_delete_inode(struct inode * inode)
+ 	clear_inode(inode);
+ }
+ 
+-/*
+- * For the moment, the only task for the NFS clear_inode method is to
+- * release the mmap credential
+- */
+ static void
+ nfs_clear_inode(struct inode *inode)
+ {
+@@ -1923,6 +1919,9 @@ static struct inode *nfs_alloc_inode(struct super_block *sb)
+ 	if (!nfsi)
+ 		return NULL;
+ 	nfsi->flags = 0;
++#ifdef CONFIG_NFS_V4
++	nfsi->nfs4_acl = NULL;
++#endif /* CONFIG_NFS_V4 */
+ 	return &nfsi->vfs_inode;
+ }
+ 
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index d969dd13e7db..128d01cfea19 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -2188,9 +2188,75 @@ static void buf_to_pages(const void *buf, size_t buflen,
+ 	}
+ }
+ 
+-static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
++struct nfs4_cached_acl {
++	int cached;
++	size_t len;
++	char data[];
++};
++
++static void nfs4_set_cached_acl(struct inode *inode, struct nfs4_cached_acl *acl)
++{
++	struct nfs_inode *nfsi = NFS_I(inode);
++
++	spin_lock(&inode->i_lock);
++	kfree(nfsi->nfs4_acl);
++	nfsi->nfs4_acl = acl;
++	spin_unlock(&inode->i_lock);
++}
++
++static void nfs4_zap_acl_attr(struct inode *inode)
++{
++	nfs4_set_cached_acl(inode, NULL);
++}
++
++static inline ssize_t nfs4_read_cached_acl(struct inode *inode, char *buf, size_t buflen)
++{
++	struct nfs_inode *nfsi = NFS_I(inode);
++	struct nfs4_cached_acl *acl;
++	int ret = -ENOENT;
++
++	spin_lock(&inode->i_lock);
++	acl = nfsi->nfs4_acl;
++	if (acl == NULL)
++		goto out;
++	if (buf == NULL) /* user is just asking for length */
++		goto out_len;
++	if (acl->cached == 0)
++		goto out;
++	ret = -ERANGE; /* see getxattr(2) man page */
++	if (acl->len > buflen)
++		goto out;
++	memcpy(buf, acl->data, acl->len);
++out_len:
++	ret = acl->len;
++out:
++	spin_unlock(&inode->i_lock);
++	return ret;
++}
++
++static void nfs4_write_cached_acl(struct inode *inode, const char *buf, size_t acl_len)
++{
++	struct nfs4_cached_acl *acl;
++
++	if (buf && acl_len <= PAGE_SIZE) {
++		acl = kmalloc(sizeof(*acl) + acl_len, GFP_KERNEL);
++		if (acl == NULL)
++			goto out;
++		acl->cached = 1;
++		memcpy(acl->data, buf, acl_len);
++	} else {
++		acl = kmalloc(sizeof(*acl), GFP_KERNEL);
++		if (acl == NULL)
++			goto out;
++		acl->cached = 0;
++	}
++	acl->len = acl_len;
++out:
++	nfs4_set_cached_acl(inode, acl);
++}
++
++static inline ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
+ {
+-	struct nfs_server *server = NFS_SERVER(inode);
+ 	struct page *pages[NFS4ACL_MAXPAGES];
+ 	struct nfs_getaclargs args = {
+ 		.fh = NFS_FH(inode),
+@@ -2198,24 +2264,66 @@ static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
+ 		.acl_len = buflen,
+ 	};
+ 	size_t resp_len = buflen;
++	void *resp_buf;
+ 	struct rpc_message msg = {
+ 		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL],
+ 		.rpc_argp = &args,
+ 		.rpc_resp = &resp_len,
+ 	};
++	struct page *localpage = NULL;
+ 	int ret;
+ 
+-	if (!nfs4_server_supports_acls(server))
+-		return -EOPNOTSUPP;
+-	buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase);
++	if (buflen < PAGE_SIZE) {
++		/* As long as we're doing a round trip to the server anyway,
++		 * let's be prepared for a page of acl data. */
++		localpage = alloc_page(GFP_KERNEL);
++		resp_buf = page_address(localpage);
++		if (localpage == NULL)
++			return -ENOMEM;
++		args.acl_pages[0] = localpage;
++		args.acl_pgbase = 0;
++		args.acl_len = PAGE_SIZE;
++	} else {
++		resp_buf = buf;
++		buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase);
++	}
+ 	ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+-	if (buflen && resp_len > buflen)
+-		return -ERANGE;
+-	if (ret == 0)
+-		ret = resp_len;
++	if (ret)
++		goto out_free;
++	if (resp_len > args.acl_len)
++		nfs4_write_cached_acl(inode, NULL, resp_len);
++	else
++		nfs4_write_cached_acl(inode, resp_buf, resp_len);
++	if (buf) {
++		ret = -ERANGE;
++		if (resp_len > buflen)
++			goto out_free;
++		if (localpage)
++			memcpy(buf, resp_buf, resp_len);
++	}
++	ret = resp_len;
++out_free:
++	if (localpage)
++		__free_page(localpage);
+ 	return ret;
+ }
+ 
++static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
++{
++	struct nfs_server *server = NFS_SERVER(inode);
++	int ret;
++
++	if (!nfs4_server_supports_acls(server))
++		return -EOPNOTSUPP;
++	ret = nfs_revalidate_inode(server, inode);
++	if (ret < 0)
++		return ret;
++	ret = nfs4_read_cached_acl(inode, buf, buflen);
++	if (ret != -ENOENT)
++		return ret;
++	return nfs4_get_acl_uncached(inode, buf, buflen);
++}
++
+ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen)
+ {
+ 	struct nfs_server *server = NFS_SERVER(inode);
+@@ -2236,6 +2344,8 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen
+ 		return -EOPNOTSUPP;
+ 	buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
+ 	ret = rpc_call_sync(NFS_SERVER(inode)->client, &msg, 0);
++	if (ret == 0)
++		nfs4_write_cached_acl(inode, buf, buflen);
+ 	return ret;
+ }
+ 
+@@ -2907,6 +3017,7 @@ struct nfs_rpc_ops	nfs_v4_clientops = {
+ 	.file_open      = nfs4_proc_file_open,
+ 	.file_release   = nfs4_proc_file_release,
+ 	.lock		= nfs4_proc_lock,
++	.clear_acl_cache = nfs4_zap_acl_attr,
+ };
+ 
+ /*
+diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
+index 140bdf489f71..d2b5d7e0e85a 100644
+--- a/include/linux/nfs_fs.h
++++ b/include/linux/nfs_fs.h
+@@ -169,13 +169,13 @@ struct nfs_inode {
+ 	wait_queue_head_t	nfs_i_wait;
+ 
+ #ifdef CONFIG_NFS_V4
++	struct nfs4_cached_acl	*nfs4_acl;
+         /* NFSv4 state */
+ 	struct list_head	open_states;
+ 	struct nfs_delegation	*delegation;
+ 	int			 delegation_state;
+ 	struct rw_semaphore	rwsem;
+ #endif /* CONFIG_NFS_V4*/
+-
+ 	struct inode		vfs_inode;
+ };
+ 

commit 4b580ee3dc00f9828a9a7aad2724f448fdc94075
+Author: J. Bruce Fields 
+Date:   Wed Jun 22 17:16:23 2005 +0000
+
+    [PATCH] NFSv4: ACL support for the NFSv4 client: write
+    
+     Client-side write support for NFSv4 ACLs.
+    
+     Signed-off-by: J. Bruce Fields 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index c91c09938a55..d969dd13e7db 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -2216,6 +2216,29 @@ static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
+ 	return ret;
+ }
+ 
++static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen)
++{
++	struct nfs_server *server = NFS_SERVER(inode);
++	struct page *pages[NFS4ACL_MAXPAGES];
++	struct nfs_setaclargs arg = {
++		.fh		= NFS_FH(inode),
++		.acl_pages	= pages,
++		.acl_len	= buflen,
++	};
++	struct rpc_message msg = {
++		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_SETACL],
++		.rpc_argp	= &arg,
++		.rpc_resp	= NULL,
++	};
++	int ret;
++
++	if (!nfs4_server_supports_acls(server))
++		return -EOPNOTSUPP;
++	buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
++	ret = rpc_call_sync(NFS_SERVER(inode)->client, &msg, 0);
++	return ret;
++}
++
+ static int
+ nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server)
+ {
+@@ -2792,7 +2815,16 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
+ int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf,
+ 		size_t buflen, int flags)
+ {
+-	return -EOPNOTSUPP;
++	struct inode *inode = dentry->d_inode;
++
++	if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0)
++		return -EOPNOTSUPP;
++
++	if (!S_ISREG(inode->i_mode) &&
++	    (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
++		return -EPERM;
++
++	return nfs4_proc_set_acl(inode, buf, buflen);
+ }
+ 
+ /* The getxattr man page suggests returning -ENODATA for unknown attributes,

commit 23ec6965c20db96bc8ea7af0ec178f074dd31c40
+Author: J. Bruce Fields 
+Date:   Wed Jun 22 17:16:22 2005 +0000
+
+    [PATCH] NFSv4: Client-side xdr for writing NFSv4 acls
+    
+     Client-side support for NFSv4 acls: xdr encoding and decoding routines for
+     writing acls
+    
+     Signed-off-by: J. Bruce Fields 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
+index 6f1c003ee33a..325cd6d4f23a 100644
+--- a/fs/nfs/nfs4xdr.c
++++ b/fs/nfs/nfs4xdr.c
+@@ -372,6 +372,13 @@ static int nfs_stat_to_errno(int);
+ 				decode_putfh_maxsz + \
+ 				op_decode_hdr_maxsz + \
+ 				nfs4_fattr_bitmap_maxsz + 1)
++#define NFS4_enc_setacl_sz	(compound_encode_hdr_maxsz + \
++				encode_putfh_maxsz + \
++				op_encode_hdr_maxsz + 4 + \
++				nfs4_fattr_bitmap_maxsz + 1)
++#define NFS4_dec_setacl_sz	(compound_decode_hdr_maxsz + \
++				decode_putfh_maxsz + \
++				op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz)
+ 
+ static struct {
+ 	unsigned int	mode;
+@@ -471,7 +478,7 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const s
+ 	 * In the worst-case, this would be
+ 	 *   12(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime)
+ 	 *          = 36 bytes, plus any contribution from variable-length fields
+-	 *            such as owner/group/acl's.
++	 *            such as owner/group.
+ 	 */
+ 	len = 16;
+ 
+@@ -1095,6 +1102,25 @@ static int encode_renew(struct xdr_stream *xdr, const struct nfs4_client *client
+ 	return 0;
+ }
+ 
++static int
++encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg)
++{
++	uint32_t *p;
++
++	RESERVE_SPACE(4+sizeof(zero_stateid.data));
++	WRITE32(OP_SETATTR);
++	WRITEMEM(zero_stateid.data, sizeof(zero_stateid.data));
++	RESERVE_SPACE(2*4);
++	WRITE32(1);
++	WRITE32(FATTR4_WORD0_ACL);
++	if (arg->acl_len % 4)
++		return -EINVAL;
++	RESERVE_SPACE(4);
++	WRITE32(arg->acl_len);
++	xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len);
++	return 0;
++}
++
+ static int
+ encode_savefh(struct xdr_stream *xdr)
+ {
+@@ -3492,6 +3518,48 @@ static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4
+ 
+ }
+ 
++/*
++ * Encode an SETACL request
++ */
++static int
++nfs4_xdr_enc_setacl(struct rpc_rqst *req, uint32_t *p, struct nfs_setaclargs *args)
++{
++        struct xdr_stream xdr;
++        struct compound_hdr hdr = {
++                .nops   = 2,
++        };
++        int status;
++
++        xdr_init_encode(&xdr, &req->rq_snd_buf, p);
++        encode_compound_hdr(&xdr, &hdr);
++        status = encode_putfh(&xdr, args->fh);
++        if (status)
++                goto out;
++        status = encode_setacl(&xdr, args);
++out:
++        return status;
++}
++/*
++ * Decode SETACL response
++ */
++static int
++nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, uint32_t *p, void *res)
++{
++	struct xdr_stream xdr;
++	struct compound_hdr hdr;
++	int status;
++
++	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
++	status = decode_compound_hdr(&xdr, &hdr);
++	if (status)
++		goto out;
++	status = decode_putfh(&xdr);
++	if (status)
++		goto out;
++	status = decode_setattr(&xdr, res);
++out:
++	return status;
++}
+ 
+ /*
+  * Decode GETACL response
+@@ -4117,6 +4185,7 @@ struct rpc_procinfo	nfs4_procedures[] = {
+   PROC(SERVER_CAPS,	enc_server_caps, dec_server_caps),
+   PROC(DELEGRETURN,	enc_delegreturn, dec_delegreturn),
+   PROC(GETACL,		enc_getacl,	dec_getacl),
++  PROC(SETACL,		enc_setacl,	dec_setacl),
+ };
+ 
+ struct rpc_version		nfs_version4 = {
+diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
+index 6ee7e2585af5..5bb5b2fd7ba2 100644
+--- a/include/linux/nfs4.h
++++ b/include/linux/nfs4.h
+@@ -383,6 +383,7 @@ enum {
+ 	NFSPROC4_CLNT_SERVER_CAPS,
+ 	NFSPROC4_CLNT_DELEGRETURN,
+ 	NFSPROC4_CLNT_GETACL,
++	NFSPROC4_CLNT_SETACL,
+ };
+ 
+ #endif
+diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
+index 9f5e1d407c7b..46b206b460c0 100644
+--- a/include/linux/nfs_xdr.h
++++ b/include/linux/nfs_xdr.h
+@@ -326,6 +326,13 @@ struct nfs_setattrargs {
+ 	const u32 *			bitmask;
+ };
+ 
++struct nfs_setaclargs {
++	struct nfs_fh *			fh;
++	size_t				acl_len;
++	unsigned int			acl_pgbase;
++	struct page **			acl_pages;
++};
++
+ struct nfs_getaclargs {
+ 	struct nfs_fh *			fh;
+ 	size_t				acl_len;

commit aa1870af92d8f6d6db0883696516a83ff2b695a6
+Author: J. Bruce Fields 
+Date:   Wed Jun 22 17:16:22 2005 +0000
+
+    [PATCH] NFSv4: ACL support for the NFSv4 client: read
+    
+     Client-side support for NFSv4 ACLs.  Exports the raw xdr code via the
+     system.nfs4_acl extended attribute.  It is up to userspace to decode the acl
+     (and to provide correctly xdr'd acls on setxattr), and to convert to/from
+     POSIX ACLs if desired.
+    
+     This patch provides only the read support.
+    
+     Signed-off-by: J. Bruce Fields 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index 1b14d17ae9a4..c91c09938a55 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -2162,6 +2162,60 @@ nfs4_proc_file_release(struct inode *inode, struct file *filp)
+ 	return 0;
+ }
+ 
++static inline int nfs4_server_supports_acls(struct nfs_server *server)
++{
++	return (server->caps & NFS_CAP_ACLS)
++		&& (server->acl_bitmask & ACL4_SUPPORT_ALLOW_ACL)
++		&& (server->acl_bitmask & ACL4_SUPPORT_DENY_ACL);
++}
++
++/* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_CACHE_SIZE, and that
++ * it's OK to put sizeof(void) * (XATTR_SIZE_MAX/PAGE_CACHE_SIZE) bytes on
++ * the stack.
++ */
++#define NFS4ACL_MAXPAGES (XATTR_SIZE_MAX >> PAGE_CACHE_SHIFT)
++
++static void buf_to_pages(const void *buf, size_t buflen,
++		struct page **pages, unsigned int *pgbase)
++{
++	const void *p = buf;
++
++	*pgbase = offset_in_page(buf);
++	p -= *pgbase;
++	while (p < buf + buflen) {
++		*(pages++) = virt_to_page(p);
++		p += PAGE_CACHE_SIZE;
++	}
++}
++
++static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
++{
++	struct nfs_server *server = NFS_SERVER(inode);
++	struct page *pages[NFS4ACL_MAXPAGES];
++	struct nfs_getaclargs args = {
++		.fh = NFS_FH(inode),
++		.acl_pages = pages,
++		.acl_len = buflen,
++	};
++	size_t resp_len = buflen;
++	struct rpc_message msg = {
++		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL],
++		.rpc_argp = &args,
++		.rpc_resp = &resp_len,
++	};
++	int ret;
++
++	if (!nfs4_server_supports_acls(server))
++		return -EOPNOTSUPP;
++	buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase);
++	ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
++	if (buflen && resp_len > buflen)
++		return -ERANGE;
++	if (ret == 0)
++		ret = resp_len;
++	return ret;
++}
++
+ static int
+ nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server)
+ {
+@@ -2733,6 +2787,8 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
+ }
+ 
+ 
++#define XATTR_NAME_NFSV4_ACL "system.nfs4_acl"
++
+ int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf,
+ 		size_t buflen, int flags)
+ {
+@@ -2746,18 +2802,23 @@ int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf,
+ ssize_t nfs4_getxattr(struct dentry *dentry, const char *key, void *buf,
+ 		size_t buflen)
+ {
+-	return -EOPNOTSUPP;
++	struct inode *inode = dentry->d_inode;
++
++	if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0)
++		return -EOPNOTSUPP;
++
++	return nfs4_proc_get_acl(inode, buf, buflen);
+ }
+ 
+ ssize_t nfs4_listxattr(struct dentry *dentry, char *buf, size_t buflen)
+ {
+-	ssize_t len = 0;
++	size_t len = strlen(XATTR_NAME_NFSV4_ACL) + 1;
+ 
+ 	if (buf && buflen < len)
+ 		return -ERANGE;
+ 	if (buf)
+-		memcpy(buf, "", 0);
+-	return 0;
++		memcpy(buf, XATTR_NAME_NFSV4_ACL, len);
++	return len;
+ }
+ 
+ struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = {

commit 029d105e66e5a90850d5a09dad76815d0bcfcaa3
+Author: J. Bruce Fields 
+Date:   Wed Jun 22 17:16:22 2005 +0000
+
+    [PATCH] NFSv4: Client-side xdr for reading NFSv4 acls
+    
+     Client-side support for NFSv4 acls: xdr encoding and decoding routines for
+     reading acls
+    
+     Signed-off-by: J. Bruce Fields 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
+index 8204926bb467..6f1c003ee33a 100644
+--- a/fs/nfs/nfs4xdr.c
++++ b/fs/nfs/nfs4xdr.c
+@@ -365,6 +365,13 @@ static int nfs_stat_to_errno(int);
+ 				encode_delegreturn_maxsz)
+ #define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \
+ 				decode_delegreturn_maxsz)
++#define NFS4_enc_getacl_sz	(compound_encode_hdr_maxsz + \
++				encode_putfh_maxsz + \
++				encode_getattr_maxsz)
++#define NFS4_dec_getacl_sz	(compound_decode_hdr_maxsz + \
++				decode_putfh_maxsz + \
++				op_decode_hdr_maxsz + \
++				nfs4_fattr_bitmap_maxsz + 1)
+ 
+ static struct {
+ 	unsigned int	mode;
+@@ -1631,6 +1638,34 @@ static int nfs4_xdr_enc_setattr(struct rpc_rqst *req, uint32_t *p, struct nfs_se
+         return status;
+ }
+ 
++/*
++ * Encode a GETACL request
++ */
++static int
++nfs4_xdr_enc_getacl(struct rpc_rqst *req, uint32_t *p,
++		struct nfs_getaclargs *args)
++{
++	struct xdr_stream xdr;
++	struct rpc_auth *auth = req->rq_task->tk_auth;
++	struct compound_hdr hdr = {
++		.nops   = 2,
++	};
++	int replen, status;
++
++	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
++	encode_compound_hdr(&xdr, &hdr);
++	status = encode_putfh(&xdr, args->fh);
++	if (status)
++		goto out;
++	status = encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0);
++	/* set up reply buffer: */
++	replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_dec_getacl_sz) << 2;
++	xdr_inline_pages(&req->rq_rcv_buf, replen,
++		args->acl_pages, args->acl_pgbase, args->acl_len);
++out:
++	return status;
++}
++
+ /*
+  * Encode a WRITE request
+  */
+@@ -3125,6 +3160,47 @@ static int decode_renew(struct xdr_stream *xdr)
+ 	return decode_op_hdr(xdr, OP_RENEW);
+ }
+ 
++static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
++		size_t *acl_len)
++{
++	uint32_t *savep;
++	uint32_t attrlen,
++		 bitmap[2] = {0};
++	struct kvec *iov = req->rq_rcv_buf.head;
++	int status;
++
++	*acl_len = 0;
++	if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
++		goto out;
++	if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
++		goto out;
++	if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
++		goto out;
++
++	if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U)))
++		return -EIO;
++	if (likely(bitmap[0] & FATTR4_WORD0_ACL)) {
++		int hdrlen, recvd;
++
++		/* We ignore &savep and don't do consistency checks on
++		 * the attr length.  Let userspace figure it out.... */
++		hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base;
++		recvd = req->rq_rcv_buf.len - hdrlen;
++		if (attrlen > recvd) {
++			printk(KERN_WARNING "NFS: server cheating in getattr"
++					" acl reply: attrlen %u > recvd %u\n",
++					attrlen, recvd);
++			return -EINVAL;
++		}
++		if (attrlen <= *acl_len)
++			xdr_read_pages(xdr, attrlen);
++		*acl_len = attrlen;
++	}
++
++out:
++	return status;
++}
++
+ static int
+ decode_savefh(struct xdr_stream *xdr)
+ {
+@@ -3417,6 +3493,29 @@ static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4
+ }
+ 
+ 
++/*
++ * Decode GETACL response
++ */
++static int
++nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, uint32_t *p, size_t *acl_len)
++{
++	struct xdr_stream xdr;
++	struct compound_hdr hdr;
++	int status;
++
++	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
++	status = decode_compound_hdr(&xdr, &hdr);
++	if (status)
++		goto out;
++	status = decode_putfh(&xdr);
++	if (status)
++		goto out;
++	status = decode_getacl(&xdr, rqstp, acl_len);
++
++out:
++	return status;
++}
++
+ /*
+  * Decode CLOSE response
+  */
+@@ -4017,6 +4116,7 @@ struct rpc_procinfo	nfs4_procedures[] = {
+   PROC(READDIR,		enc_readdir,	dec_readdir),
+   PROC(SERVER_CAPS,	enc_server_caps, dec_server_caps),
+   PROC(DELEGRETURN,	enc_delegreturn, dec_delegreturn),
++  PROC(GETACL,		enc_getacl,	dec_getacl),
+ };
+ 
+ struct rpc_version		nfs_version4 = {
+diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
+index 5ca8a8d8ccdf..6ee7e2585af5 100644
+--- a/include/linux/nfs4.h
++++ b/include/linux/nfs4.h
+@@ -382,6 +382,7 @@ enum {
+ 	NFSPROC4_CLNT_READDIR,
+ 	NFSPROC4_CLNT_SERVER_CAPS,
+ 	NFSPROC4_CLNT_DELEGRETURN,
++	NFSPROC4_CLNT_GETACL,
+ };
+ 
+ #endif
+diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
+index cf38db59f347..9f5e1d407c7b 100644
+--- a/include/linux/nfs_xdr.h
++++ b/include/linux/nfs_xdr.h
+@@ -326,6 +326,13 @@ struct nfs_setattrargs {
+ 	const u32 *			bitmask;
+ };
+ 
++struct nfs_getaclargs {
++	struct nfs_fh *			fh;
++	size_t				acl_len;
++	unsigned int			acl_pgbase;
++	struct page **			acl_pages;
++};
++
+ struct nfs_setattrres {
+ 	struct nfs_fattr *              fattr;
+ 	const struct nfs_server *	server;

commit 96928206961be05f22c3839f0097b610cc485b5d
+Author: J. Bruce Fields 
+Date:   Wed Jun 22 17:16:22 2005 +0000
+
+    [PATCH] NFSv4: fix fattr size calculations
+    
+     Make nfs4 fattr size calculations more explicit, revising them downward a
+     bit in the process.
+    
+     Signed-off-by: J. Bruce Fields 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
+index e86406eff0eb..8204926bb467 100644
+--- a/fs/nfs/nfs4xdr.c
++++ b/fs/nfs/nfs4xdr.c
+@@ -83,12 +83,16 @@ static int nfs_stat_to_errno(int);
+ #define encode_getfh_maxsz      (op_encode_hdr_maxsz)
+ #define decode_getfh_maxsz      (op_decode_hdr_maxsz + 1 + \
+ 				((3+NFS4_FHSIZE) >> 2))
+-#define encode_getattr_maxsz    (op_encode_hdr_maxsz + 3)
++#define nfs4_fattr_bitmap_maxsz 3
++#define encode_getattr_maxsz    (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz)
+ #define nfs4_name_maxsz		(1 + ((3 + NFS4_MAXNAMLEN) >> 2))
+ #define nfs4_path_maxsz		(1 + ((3 + NFS4_MAXPATHLEN) >> 2))
+-#define nfs4_fattr_bitmap_maxsz (36 + 2 * nfs4_name_maxsz)
+-#define decode_getattr_maxsz    (op_decode_hdr_maxsz + 3 + \
+-                                nfs4_fattr_bitmap_maxsz)
++/* This is based on getfattr, which uses the most attributes: */
++#define nfs4_fattr_value_maxsz	(1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \
++				3 + 3 + 3 + 2 * nfs4_name_maxsz))
++#define nfs4_fattr_maxsz	(nfs4_fattr_bitmap_maxsz + \
++				nfs4_fattr_value_maxsz)
++#define decode_getattr_maxsz    (op_decode_hdr_maxsz + nfs4_fattr_maxsz)
+ #define encode_savefh_maxsz     (op_encode_hdr_maxsz)
+ #define decode_savefh_maxsz     (op_decode_hdr_maxsz)
+ #define encode_fsinfo_maxsz	(op_encode_hdr_maxsz + 2)
+@@ -123,11 +127,11 @@ static int nfs_stat_to_errno(int);
+ #define encode_symlink_maxsz	(op_encode_hdr_maxsz + \
+ 				1 + nfs4_name_maxsz + \
+ 				nfs4_path_maxsz + \
+-				nfs4_fattr_bitmap_maxsz)
++				nfs4_fattr_maxsz)
+ #define decode_symlink_maxsz	(op_decode_hdr_maxsz + 8)
+ #define encode_create_maxsz	(op_encode_hdr_maxsz + \
+ 				2 + nfs4_name_maxsz + \
+-				nfs4_fattr_bitmap_maxsz)
++				nfs4_fattr_maxsz)
+ #define decode_create_maxsz	(op_decode_hdr_maxsz + 8)
+ #define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4)
+ #define decode_delegreturn_maxsz (op_decode_hdr_maxsz)
+@@ -206,7 +210,7 @@ static int nfs_stat_to_errno(int);
+ #define NFS4_enc_setattr_sz     (compound_encode_hdr_maxsz + \
+                                 encode_putfh_maxsz + \
+                                 op_encode_hdr_maxsz + 4 + \
+-                                nfs4_fattr_bitmap_maxsz + \
++                                nfs4_fattr_maxsz + \
+                                 encode_getattr_maxsz)
+ #define NFS4_dec_setattr_sz     (compound_decode_hdr_maxsz + \
+                                 decode_putfh_maxsz + \

commit 6b3b5496d7b261d6c9202008dc528e52dbd11e57
+Author: J. Bruce Fields 
+Date:   Wed Jun 22 17:16:22 2005 +0000
+
+    [PATCH] NFSv4: Add {get,set,list}xattr methods for nfs4
+    
+     Add {get,set,list}xattr methods for nfs4.  The new methods are no-ops, to be
+     used by subsequent ACL patch.
+    
+     Signed-off-by: J. Bruce Fields 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
+index dffa21abd3ea..5720537bffdd 100644
+--- a/fs/nfs/dir.c
++++ b/fs/nfs/dir.c
+@@ -91,6 +91,9 @@ struct inode_operations nfs4_dir_inode_operations = {
+ 	.permission	= nfs_permission,
+ 	.getattr	= nfs_getattr,
+ 	.setattr	= nfs_setattr,
++	.getxattr       = nfs4_getxattr,
++	.setxattr       = nfs4_setxattr,
++	.listxattr      = nfs4_listxattr,
+ };
+ 
+ #endif /* CONFIG_NFS_V4 */
+diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
+index 85cf3bd36921..d71f416bd9e5 100644
+--- a/fs/nfs/nfs4_fs.h
++++ b/fs/nfs/nfs4_fs.h
+@@ -176,6 +176,13 @@ struct nfs4_state_recovery_ops {
+ 
+ extern struct dentry_operations nfs4_dentry_operations;
+ extern struct inode_operations nfs4_dir_inode_operations;
++extern struct inode_operations nfs4_file_inode_operations;
++
++/* inode.c */
++extern ssize_t nfs4_getxattr(struct dentry *, const char *, void *, size_t);
++extern int nfs4_setxattr(struct dentry *, const char *, const void *, size_t, int);
++extern ssize_t nfs4_listxattr(struct dentry *, char *, size_t);
++
+ 
+ /* nfs4proc.c */
+ extern int nfs4_map_errors(int err);
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index a5a8cb3159a0..1b14d17ae9a4 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -2732,6 +2732,34 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
+ 	return status;
+ }
+ 
++
++int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf,
++		size_t buflen, int flags)
++{
++	return -EOPNOTSUPP;
++}
++
++/* The getxattr man page suggests returning -ENODATA for unknown attributes,
++ * and that's what we'll do for e.g. user attributes that haven't been set.
++ * But we'll follow ext2/ext3's lead by returning -EOPNOTSUPP for unsupported
++ * attributes in kernel-managed attribute namespaces. */
++ssize_t nfs4_getxattr(struct dentry *dentry, const char *key, void *buf,
++		size_t buflen)
++{
++	return -EOPNOTSUPP;
++}
++
++ssize_t nfs4_listxattr(struct dentry *dentry, char *buf, size_t buflen)
++{
++	ssize_t len = 0;
++
++	if (buf && buflen < len)
++		return -ERANGE;
++	if (buf)
++		memcpy(buf, "", 0);
++	return 0;
++}
++
+ struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = {
+ 	.recover_open	= nfs4_open_reclaim,
+ 	.recover_lock	= nfs4_lock_reclaim,
+@@ -2742,11 +2770,20 @@ struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops = {
+ 	.recover_lock	= nfs4_lock_expired,
+ };
+ 
++static struct inode_operations nfs4_file_inode_operations = {
++	.permission	= nfs_permission,
++	.getattr	= nfs_getattr,
++	.setattr	= nfs_setattr,
++	.getxattr	= nfs4_getxattr,
++	.setxattr	= nfs4_setxattr,
++	.listxattr	= nfs4_listxattr,
++};
++
+ struct nfs_rpc_ops	nfs_v4_clientops = {
+ 	.version	= 4,			/* protocol version */
+ 	.dentry_ops	= &nfs4_dentry_operations,
+ 	.dir_inode_ops	= &nfs4_dir_inode_operations,
+-	.file_inode_ops	= &nfs_file_inode_operations,
++	.file_inode_ops	= &nfs4_file_inode_operations,
+ 	.getroot	= nfs4_proc_get_root,
+ 	.getattr	= nfs4_proc_getattr,
+ 	.setattr	= nfs4_proc_setattr,

commit 92cfc62cb8412c9563860b1bf70cd4701f03092e
+Author: J. Bruce Fields 
+Date:   Wed Jun 22 17:16:22 2005 +0000
+
+    [PATCH] NFS: Allow NFS versions to support different sets of inode operations.
+    
+     ACL support will require supporting additional inode operations in v4
+     (getxattr, setxattr, listxattr).  This patch allows different protocol versions
+     to support different inode operations by adding a file_inode_ops to the
+     nfs_rpc_ops (to match the existing dir_inode_ops).
+    
+     Signed-off-by: J. Bruce Fields 
+     Signed-off-by: Trond Myklebust 
+
+diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
+index a38d4b22d1f8..a82f0340744f 100644
+--- a/fs/nfs/inode.c
++++ b/fs/nfs/inode.c
+@@ -686,7 +686,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
+ 		/* Why so? Because we want revalidate for devices/FIFOs, and
+ 		 * that's precisely what we have in nfs_file_inode_operations.
+ 		 */
+-		inode->i_op = &nfs_file_inode_operations;
++		inode->i_op = NFS_SB(sb)->rpc_ops->file_inode_ops;
+ 		if (S_ISREG(inode->i_mode)) {
+ 			inode->i_fop = &nfs_file_operations;
+ 			inode->i_data.a_ops = &nfs_file_aops;
+diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
+index 3878494dfc2c..53953a775714 100644
+--- a/fs/nfs/nfs3proc.c
++++ b/fs/nfs/nfs3proc.c
+@@ -826,6 +826,7 @@ struct nfs_rpc_ops	nfs_v3_clientops = {
+ 	.version	= 3,			/* protocol version */
+ 	.dentry_ops	= &nfs_dentry_operations,
+ 	.dir_inode_ops	= &nfs_dir_inode_operations,
++	.file_inode_ops	= &nfs_file_inode_operations,
+ 	.getroot	= nfs3_proc_get_root,
+ 	.getattr	= nfs3_proc_getattr,
+ 	.setattr	= nfs3_proc_setattr,
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index a69c02b206c1..a5a8cb3159a0 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -2746,6 +2746,7 @@ struct nfs_rpc_ops	nfs_v4_clientops = {
+ 	.version	= 4,			/* protocol version */
+ 	.dentry_ops	= &nfs4_dentry_operations,
+ 	.dir_inode_ops	= &nfs4_dir_inode_operations,
++	.file_inode_ops	= &nfs_file_inode_operations,
+ 	.getroot	= nfs4_proc_get_root,
+ 	.getattr	= nfs4_proc_getattr,
+ 	.setattr	= nfs4_proc_setattr,
+diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
+index d31b4d6e5a5e..cedf636bcf3c 100644
+--- a/fs/nfs/proc.c
++++ b/fs/nfs/proc.c
+@@ -622,6 +622,7 @@ struct nfs_rpc_ops	nfs_v2_clientops = {
+ 	.version	= 2,		       /* protocol version */
+ 	.dentry_ops	= &nfs_dentry_operations,
+ 	.dir_inode_ops	= &nfs_dir_inode_operations,
++	.file_inode_ops	= &nfs_file_inode_operations,
+ 	.getroot	= nfs_proc_get_root,
+ 	.getattr	= nfs_proc_getattr,
+ 	.setattr	= nfs_proc_setattr,
+diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
+index 47037d9521cb..5b45bafd9db5 100644
+--- a/include/linux/nfs_xdr.h
++++ b/include/linux/nfs_xdr.h
+@@ -667,6 +667,7 @@ struct nfs_rpc_ops {
+ 	int	version;		/* Protocol version */
+ 	struct dentry_operations *dentry_ops;
+ 	struct inode_operations *dir_inode_ops;
++	struct inode_operations *file_inode_ops;
+ 
+ 	int	(*getroot) (struct nfs_server *, struct nfs_fh *,
+ 			    struct nfs_fsinfo *);

commit 53240c208776d557dba9d7afedbcdbf512774c16
+Author: Ali Saidi 
+Date:   Tue Oct 7 15:31:19 2008 -0700
+
+    tcp: Fix possible double-ack w/ user dma
+    
+    From: Ali Saidi 
+    
+    When TCP receive copy offload is enabled it's possible that
+    tcp_rcv_established() will cause two acks to be sent for a single
+    packet. In the case that a tcp_dma_early_copy() is successful,
+    copied_early is set to true which causes tcp_cleanup_rbuf() to be
+    called early which can send an ack. Further along in
+    tcp_rcv_established(), __tcp_ack_snd_check() is called and will
+    schedule a delayed ACK. If no packets are processed before the delayed
+    ack timer expires the packet will be acked twice.
+    
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
+index 67ccce2a96bd..7abc6b80d47d 100644
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -4879,7 +4879,8 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
+ 					goto no_ack;
+ 			}
+ 
+-			__tcp_ack_snd_check(sk, 0);
++			if (!copied_early || tp->rcv_nxt != tp->rcv_wup)
++				__tcp_ack_snd_check(sk, 0);
+ no_ack:
+ #ifdef CONFIG_NET_DMA
+ 			if (copied_early)

commit 61322b30139b79ec77170723a3a80043dcc94e87
+Author: J. Bruce Fields - unquoted 
+Date:   Sat Feb 10 01:33:27 2007 -0500
+
+    spkm3: initialize hash
+    
+    There's an initialization step here I missed.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/auth_gss/gss_spkm3_seal.c b/net/sunrpc/auth_gss/gss_spkm3_seal.c
+index 3ec9cd31420c..d158635de6c0 100644
+--- a/net/sunrpc/auth_gss/gss_spkm3_seal.c
++++ b/net/sunrpc/auth_gss/gss_spkm3_seal.c
+@@ -169,6 +169,10 @@ make_spkm3_checksum(s32 cksumtype, struct xdr_netobj *key, char *header,
+ 	if (err)
+ 		goto out;
+ 
++	err = crypto_hash_init(&desc);
++	if (err)
++		goto out;
++
+ 	sg_set_buf(sg, header, hdrlen);
+ 	crypto_hash_update(&desc, sg, sg->length);
+ 

commit b80e183deff5f3d43565b552ed91e511128a6ea9
+Author: J. Bruce Fields - unquoted 
+Date:   Sat Feb 10 01:33:26 2007 -0500
+
+    spkm3: remove bad kfree, unnecessary export
+    
+    We're kfree()'ing something that was allocated on the stack!
+    
+    Also remove an unnecessary symbol export while we're at it.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/auth_gss/gss_spkm3_seal.c b/net/sunrpc/auth_gss/gss_spkm3_seal.c
+index 36c3bae0c42b..3ec9cd31420c 100644
+--- a/net/sunrpc/auth_gss/gss_spkm3_seal.c
++++ b/net/sunrpc/auth_gss/gss_spkm3_seal.c
+@@ -123,9 +123,6 @@ spkm3_make_token(struct spkm3_ctx *ctx,
+ 
+ 	return  GSS_S_COMPLETE;
+ out_err:
+-	if (md5cksum.data)
+-		kfree(md5cksum.data);
+-
+ 	token->data = NULL;
+ 	token->len = 0;
+ 	return GSS_S_FAILURE;
+@@ -184,5 +181,3 @@ make_spkm3_checksum(s32 cksumtype, struct xdr_netobj *key, char *header,
+ 
+ 	return err ? GSS_S_FAILURE : 0;
+ }
+-
+-EXPORT_SYMBOL(make_spkm3_checksum);

commit f32824d8ca9d3f84613ae2422070cc5469fe9e91
+Author: J. Bruce Fields - unquoted 
+Date:   Sat Feb 10 01:33:25 2007 -0500
+
+    spkm3: fix spkm3's use of hmac
+    
+    I think I botched an attempt to keep an spkm3 patch up-to-date with a recent
+    crypto api change.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Trond Myklebust 
+
+diff --git a/net/sunrpc/auth_gss/gss_spkm3_seal.c b/net/sunrpc/auth_gss/gss_spkm3_seal.c
+index 104cbf4f769f..36c3bae0c42b 100644
+--- a/net/sunrpc/auth_gss/gss_spkm3_seal.c
++++ b/net/sunrpc/auth_gss/gss_spkm3_seal.c
+@@ -152,7 +152,7 @@ make_spkm3_checksum(s32 cksumtype, struct xdr_netobj *key, char *header,
+ 
+ 	switch (cksumtype) {
+ 		case CKSUMTYPE_HMAC_MD5:
+-			cksumname = "md5";
++			cksumname = "hmac(md5)";
+ 			break;
+ 		default:
+ 			dprintk("RPC:       spkm3_make_checksum:"
+@@ -173,7 +173,7 @@ make_spkm3_checksum(s32 cksumtype, struct xdr_netobj *key, char *header,
+ 		goto out;
+ 
+ 	sg_set_buf(sg, header, hdrlen);
+-	crypto_hash_update(&desc, sg, 1);
++	crypto_hash_update(&desc, sg, sg->length);
+ 
+ 	xdr_process_buf(body, body_offset, body->len - body_offset,
+ 			spkm3_checksummer, &desc);

commit bec50c47aaf6f1f9247f1860547ab394a0802a4c
+Author: J. Bruce Fields 
+Date:   Fri Feb 16 01:28:36 2007 -0800
+
+    [PATCH] knfsd: nfsd4: acls: avoid unnecessary denies
+    
+    We're inserting deny's between some ACEs in order to enforce posix draft acl
+    semantics which prevent permissions from accumulating across entries in an
+    acl.
+    
+    That's fine, but we're doing that by inserting a deny after *every* allow,
+    which is overkill.  We shouldn't be adding them in places where they actually
+    make no difference.
+    
+    Also replaced some helper functions for creating acl entries; I prefer just
+    assigning directly to the struct fields--it takes a few more lines, but the
+    field names provide some documentation that I think makes the result easier
+    understand.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
+index 8daa3f8bb303..0a69cce33efe 100644
+--- a/fs/nfsd/nfs4acl.c
++++ b/fs/nfsd/nfs4acl.c
+@@ -89,12 +89,19 @@ mask_from_posix(unsigned short perm, unsigned int flags)
+ }
+ 
+ static u32
+-deny_mask(u32 allow_mask, unsigned int flags)
++deny_mask_from_posix(unsigned short perm, u32 flags)
+ {
+-	u32 ret = ~allow_mask & ~NFS4_MASK_UNSUPP;
+-	if (!(flags & NFS4_ACL_DIR))
+-		ret &= ~NFS4_ACE_DELETE_CHILD;
+-	return ret;
++	u32 mask = 0;
++
++	if (perm & ACL_READ)
++		mask |= NFS4_READ_MODE;
++	if (perm & ACL_WRITE)
++		mask |= NFS4_WRITE_MODE;
++	if ((perm & ACL_WRITE) && (flags & NFS4_ACL_DIR))
++		mask |= NFS4_ACE_DELETE_CHILD;
++	if (perm & ACL_EXECUTE)
++		mask |= NFS4_EXECUTE_MODE;
++	return mask;
+ }
+ 
+ /* XXX: modify functions to return NFS errors; they're only ever
+@@ -164,14 +171,51 @@ nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl,
+ 	return acl;
+ }
+ 
++struct posix_acl_summary {
++	unsigned short owner;
++	unsigned short users;
++	unsigned short group;
++	unsigned short groups;
++	unsigned short other;
++	unsigned short mask;
++};
++
+ static void
+-nfs4_acl_add_pair(struct nfs4_acl *acl, int eflag, u32 mask, int whotype,
+-		uid_t owner, unsigned int flags)
++summarize_posix_acl(struct posix_acl *acl, struct posix_acl_summary *pas)
+ {
+-	nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
+-				 eflag, mask, whotype, owner);
+-	nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+-				eflag, deny_mask(mask, flags), whotype, owner);
++	struct posix_acl_entry *pa, *pe;
++	pas->users = 0;
++	pas->groups = 0;
++	pas->mask = 07;
++
++	pe = acl->a_entries + acl->a_count;
++
++	FOREACH_ACL_ENTRY(pa, acl, pe) {
++		switch (pa->e_tag) {
++			case ACL_USER_OBJ:
++				pas->owner = pa->e_perm;
++				break;
++			case ACL_GROUP_OBJ:
++				pas->group = pa->e_perm;
++				break;
++			case ACL_USER:
++				pas->users |= pa->e_perm;
++				break;
++			case ACL_GROUP:
++				pas->groups |= pa->e_perm;
++				break;
++			case ACL_OTHER:
++				pas->other = pa->e_perm;
++				break;
++			case ACL_MASK:
++				pas->mask = pa->e_perm;
++				break;
++		}
++	}
++	/* We'll only care about effective permissions: */
++	pas->users &= pas->mask;
++	pas->group &= pas->mask;
++	pas->groups &= pas->mask;
+ }
+ 
+ /* We assume the acl has been verified with posix_acl_valid. */
+@@ -179,30 +223,63 @@ static void
+ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
+ 						unsigned int flags)
+ {
+-	struct posix_acl_entry *pa, *pe, *group_owner_entry;
+-	u32 mask;
+-	unsigned short mask_mask;
++	struct posix_acl_entry *pa, *group_owner_entry;
++	struct nfs4_ace *ace;
++	struct posix_acl_summary pas;
++	unsigned short deny;
+ 	int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ?
+ 					NFS4_INHERITANCE_FLAGS : 0);
+ 
+ 	BUG_ON(pacl->a_count < 3);
+-	pe = pacl->a_entries + pacl->a_count;
+-	pa = pe - 2; /* if mask entry exists, it's second from the last. */
+-	if (pa->e_tag == ACL_MASK)
+-		mask_mask = pa->e_perm;
+-	else
+-		mask_mask = S_IRWXO;
++	summarize_posix_acl(pacl, &pas);
+ 
+ 	pa = pacl->a_entries;
+-	BUG_ON(pa->e_tag != ACL_USER_OBJ);
+-	mask = mask_from_posix(pa->e_perm, flags | NFS4_ACL_OWNER);
+-	nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_OWNER, 0, flags);
++	ace = acl->aces + acl->naces;
++
++	/* We could deny everything not granted by the owner: */
++	deny = ~pas.owner;
++	/*
++	 * but it is equivalent (and simpler) to deny only what is not
++	 * granted by later entries:
++	 */
++	deny &= pas.users | pas.group | pas.groups | pas.other;
++	if (deny) {
++		ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
++		ace->flag = eflag;
++		ace->access_mask = deny_mask_from_posix(deny, flags);
++		ace->whotype = NFS4_ACL_WHO_OWNER;
++		ace++;
++		acl->naces++;
++	}
++
++	ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
++	ace->flag = eflag;
++	ace->access_mask = mask_from_posix(pa->e_perm, flags | NFS4_ACL_OWNER);
++	ace->whotype = NFS4_ACL_WHO_OWNER;
++	ace++;
++	acl->naces++;
+ 	pa++;
+ 
+ 	while (pa->e_tag == ACL_USER) {
+-		mask = mask_from_posix(pa->e_perm & mask_mask, flags);
+-		nfs4_acl_add_pair(acl, eflag, mask,
+-				NFS4_ACL_WHO_NAMED, pa->e_id, flags);
++		deny = ~(pa->e_perm & pas.mask);
++		deny &= pas.groups | pas.group | pas.other;
++		if (deny) {
++			ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
++			ace->flag = eflag;
++			ace->access_mask = deny_mask_from_posix(deny, flags);
++			ace->whotype = NFS4_ACL_WHO_NAMED;
++			ace->who = pa->e_id;
++			ace++;
++			acl->naces++;
++		}
++		ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
++		ace->flag = eflag;
++		ace->access_mask = mask_from_posix(pa->e_perm & pas.mask,
++						   flags);
++		ace->whotype = NFS4_ACL_WHO_NAMED;
++		ace->who = pa->e_id;
++		ace++;
++		acl->naces++;
+ 		pa++;
+ 	}
+ 
+@@ -212,41 +289,64 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
+ 	/* allow ACEs */
+ 
+ 	group_owner_entry = pa;
+-	mask = mask_from_posix(pa->e_perm & mask_mask, flags);
+-	nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
+-			NFS4_ACE_IDENTIFIER_GROUP | eflag, mask,
+-			NFS4_ACL_WHO_GROUP, 0);
++
++	ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
++	ace->flag = eflag;
++	ace->access_mask = mask_from_posix(pas.group, flags);
++	ace->whotype = NFS4_ACL_WHO_GROUP;
++	ace++;
++	acl->naces++;
+ 	pa++;
+ 
+ 	while (pa->e_tag == ACL_GROUP) {
+-		mask = mask_from_posix(pa->e_perm & mask_mask, flags);
+-		nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
+-		    		NFS4_ACE_IDENTIFIER_GROUP | eflag, mask,
+-		    		NFS4_ACL_WHO_NAMED, pa->e_id);
++		ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
++		ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP;
++		ace->access_mask = mask_from_posix(pa->e_perm & pas.mask,
++						   flags);
++		ace->whotype = NFS4_ACL_WHO_NAMED;
++		ace->who = pa->e_id;
++		ace++;
++		acl->naces++;
+ 		pa++;
+ 	}
+ 
+ 	/* deny ACEs */
+ 
+ 	pa = group_owner_entry;
+-	mask = mask_from_posix(pa->e_perm, flags);
+-	nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+-			NFS4_ACE_IDENTIFIER_GROUP | eflag,
+-			deny_mask(mask, flags), NFS4_ACL_WHO_GROUP, 0);
++
++	deny = ~pas.group & pas.other;
++	if (deny) {
++		ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
++		ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP;
++		ace->access_mask = deny_mask_from_posix(deny, flags);
++		ace->whotype = NFS4_ACL_WHO_GROUP;
++		ace++;
++		acl->naces++;
++	}
+ 	pa++;
++
+ 	while (pa->e_tag == ACL_GROUP) {
+-		mask = mask_from_posix(pa->e_perm, flags);
+-		nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+-		    		NFS4_ACE_IDENTIFIER_GROUP | eflag,
+-		    		deny_mask(mask, flags), NFS4_ACL_WHO_NAMED, pa->e_id);
++		deny = ~(pa->e_perm & pas.mask);
++		deny &= pas.other;
++		if (deny) {
++			ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
++			ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP;
++			ace->access_mask = mask_from_posix(deny, flags);
++			ace->whotype = NFS4_ACL_WHO_NAMED;
++			ace->who = pa->e_id;
++			ace++;
++			acl->naces++;
++		}
+ 		pa++;
+ 	}
+ 
+ 	if (pa->e_tag == ACL_MASK)
+ 		pa++;
+-	BUG_ON(pa->e_tag != ACL_OTHER);
+-	mask = mask_from_posix(pa->e_perm, flags);
+-	nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_EVERYONE, 0, flags);
++	ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
++	ace->flag = eflag;
++	ace->access_mask = mask_from_posix(pa->e_perm, flags);
++	ace->whotype = NFS4_ACL_WHO_EVERYONE;
++	acl->naces++;
+ }
+ 
+ static void

commit f43daf67871d9da5c638994416b4144eac63c992
+Author: J. Bruce Fields 
+Date:   Fri Feb 16 01:28:34 2007 -0800
+
+    [PATCH] knfsd: nfsd4: acls: don't return explicit mask
+    
+    Return just the effective permissions, and forget about the mask.  It isn't
+    worth the complexity.
+    
+    WARNING: This breaks backwards compatibility with overly-picky nfsv4->posix
+    acl translation, as may has been included in some patched versions of libacl.
+    To our knowledge no such version was every distributed by anyone outside citi.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
+index 2797051cd2b4..8daa3f8bb303 100644
+--- a/fs/nfsd/nfs4acl.c
++++ b/fs/nfsd/nfs4acl.c
+@@ -180,7 +180,8 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
+ 						unsigned int flags)
+ {
+ 	struct posix_acl_entry *pa, *pe, *group_owner_entry;
+-	u32 mask, mask_mask;
++	u32 mask;
++	unsigned short mask_mask;
+ 	int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ?
+ 					NFS4_INHERITANCE_FLAGS : 0);
+ 
+@@ -188,9 +189,9 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
+ 	pe = pacl->a_entries + pacl->a_count;
+ 	pa = pe - 2; /* if mask entry exists, it's second from the last. */
+ 	if (pa->e_tag == ACL_MASK)
+-		mask_mask = deny_mask(mask_from_posix(pa->e_perm, flags), flags);
++		mask_mask = pa->e_perm;
+ 	else
+-		mask_mask = 0;
++		mask_mask = S_IRWXO;
+ 
+ 	pa = pacl->a_entries;
+ 	BUG_ON(pa->e_tag != ACL_USER_OBJ);
+@@ -199,10 +200,7 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
+ 	pa++;
+ 
+ 	while (pa->e_tag == ACL_USER) {
+-		mask = mask_from_posix(pa->e_perm, flags);
+-		nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+-				eflag,  mask_mask, NFS4_ACL_WHO_NAMED, pa->e_id);
+-
++		mask = mask_from_posix(pa->e_perm & mask_mask, flags);
+ 		nfs4_acl_add_pair(acl, eflag, mask,
+ 				NFS4_ACL_WHO_NAMED, pa->e_id, flags);
+ 		pa++;
+@@ -213,24 +211,15 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
+ 
+ 	/* allow ACEs */
+ 
+-	if (pacl->a_count > 3) {
+-		BUG_ON(pa->e_tag != ACL_GROUP_OBJ);
+-		nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+-				NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask,
+-				NFS4_ACL_WHO_GROUP, 0);
+-	}
+ 	group_owner_entry = pa;
+-	mask = mask_from_posix(pa->e_perm, flags);
++	mask = mask_from_posix(pa->e_perm & mask_mask, flags);
+ 	nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
+ 			NFS4_ACE_IDENTIFIER_GROUP | eflag, mask,
+ 			NFS4_ACL_WHO_GROUP, 0);
+ 	pa++;
+ 
+ 	while (pa->e_tag == ACL_GROUP) {
+-		mask = mask_from_posix(pa->e_perm, flags);
+-		nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+-				NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask,
+-				NFS4_ACL_WHO_NAMED, pa->e_id);
++		mask = mask_from_posix(pa->e_perm & mask_mask, flags);
+ 		nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
+ 		    		NFS4_ACE_IDENTIFIER_GROUP | eflag, mask,
+ 		    		NFS4_ACL_WHO_NAMED, pa->e_id);

commit a4db5fe5dfb3a5b5b550f1acd95ef3de01a3f063
+Author: J. Bruce Fields 
+Date:   Fri Feb 16 01:28:30 2007 -0800
+
+    [PATCH] knfsd: nfsd4: fix memory leak on kmalloc failure in savemem
+    
+    The wrong pointer is being kfree'd in savemem() when defer_free returns with
+    an error.
+    
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index fbb4af969243..bb0f1860f582 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -199,24 +199,22 @@ defer_free(struct nfsd4_compoundargs *argp,
+ 
+ static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes)
+ {
+-	void *new = NULL;
+ 	if (p == argp->tmp) {
+-		new = kmalloc(nbytes, GFP_KERNEL);
+-		if (!new) return NULL;
+-		p = new;
++		p = kmalloc(nbytes, GFP_KERNEL);
++		if (!p)
++			return NULL;
+ 		memcpy(p, argp->tmp, nbytes);
+ 	} else {
+ 		BUG_ON(p != argp->tmpp);
+ 		argp->tmpp = NULL;
+ 	}
+ 	if (defer_free(argp, kfree, p)) {
+-		kfree(new);
++		kfree(p);
+ 		return NULL;
+ 	} else
+ 		return (char *)p;
+ }
+ 
+-
+ static __be32
+ nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
+ {

\ No newline at end of file diff --git a/detail/42.html b/detail/42.html new file mode 100644 index 0000000..6cb8ab7 --- /dev/null +++ b/detail/42.html @@ -0,0 +1,371 @@ +

Patches contributed by Unknown (ashoka.edu.in)


commit 8e2ff0e4b526179e75cdcd221d94c8ff93070889
+Author: Nishka Dasgupta 
+Date:   Sat Mar 24 08:03:57 2018 +0000
+
+    staging: mt7621-dts: Replace spaces with tabs in indentation
+    
+    Replace spaces with tabs in indentation.
+    Issue found with checkpatch.
+    
+    Signed-off-by: Nishka Dasgupta 
+    Acked-by: Julia Lawall 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/mt7621-dts/mt7621.dtsi b/drivers/staging/mt7621-dts/mt7621.dtsi
+index a6b17ea9ade8..ebcaa8b1fc81 100644
+--- a/drivers/staging/mt7621-dts/mt7621.dtsi
++++ b/drivers/staging/mt7621-dts/mt7621.dtsi
+@@ -142,7 +142,7 @@ cpc: cpc@1fbf0000 {
+ 		mc: mc@1fbf8000 {
+ 			    compatible = "mtk,mt7621-mc";
+ 			    reg = <0x1fbf8000 0x8000>;
+- 		};
++		};
+ 
+ 		uartlite: uartlite@c00 {
+ 			compatible = "ns16550a";

commit f47ecc0cf3d3d8e5d487b8392335ff151e4251f1
+Author: Nishka Dasgupta 
+Date:   Sat Mar 24 11:59:17 2018 +0000
+
+    staging: vt6655: Delete unused typedef enum _chip_type
+    
+    Delete unused typedef enum _chip_type.
+    
+    Signed-off-by: Nishka Dasgupta 
+    Acked-by: Julia Lawall 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/vt6655/device_cfg.h b/drivers/staging/vt6655/device_cfg.h
+index b81f9dda917a..6b41c74f7c2a 100644
+--- a/drivers/staging/vt6655/device_cfg.h
++++ b/drivers/staging/vt6655/device_cfg.h
+@@ -45,8 +45,4 @@
+ 
+ #define PKT_BUF_SZ          2390
+ 
+-typedef enum  _chip_type {
+-	VT3253 = 1
+-} CHIP_TYPE, *PCHIP_TYPE;
+-
+ #endif

commit 02769c265f15b85a706a119abec63986525d74b6
+Author: Nishka Dasgupta 
+Date:   Sat Mar 24 11:59:16 2018 +0000
+
+    staging: vt6655: Delete unused typedef struct _version
+    
+    Delete unused typedef struct _version.
+    
+    Signed-off-by: Nishka Dasgupta 
+    Acked-by: Julia Lawall 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/vt6655/device_cfg.h b/drivers/staging/vt6655/device_cfg.h
+index 73f904b51b96..b81f9dda917a 100644
+--- a/drivers/staging/vt6655/device_cfg.h
++++ b/drivers/staging/vt6655/device_cfg.h
+@@ -16,13 +16,6 @@
+ 
+ #include 
+ 
+-typedef
+-struct _version {
+-	unsigned char   major;
+-	unsigned char   minor;
+-	unsigned char   build;
+-} version_t, *pversion_t;
+-
+ #define VID_TABLE_SIZE      64
+ #define MCAST_TABLE_SIZE    64
+ #define MCAM_SIZE           32

commit 7e131ddea86b7e51f82a9391328e14c52df74348
+Author: Nishka Dasgupta 
+Date:   Sat Mar 24 11:59:15 2018 +0000
+
+    staging: vt6655: Delete unused typedef enum _CARD_STATUS_TYPE
+    
+    Delete unused typedef enum _CARD_STATUS_TYPE.
+    
+    Signed-off-by: Nishka Dasgupta 
+    Acked-by: Julia Lawall 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/vt6655/card.h b/drivers/staging/vt6655/card.h
+index 07d9fa06a94b..5884fd56153e 100644
+--- a/drivers/staging/vt6655/card.h
++++ b/drivers/staging/vt6655/card.h
+@@ -39,12 +39,6 @@
+ #define CB_MAX_CHANNEL_5G       42
+ #define CB_MAX_CHANNEL          (CB_MAX_CHANNEL_24G + CB_MAX_CHANNEL_5G)
+ 
+-typedef enum _CARD_STATUS_TYPE {
+-	CARD_STATUS_MEDIA_CONNECT,
+-	CARD_STATUS_MEDIA_DISCONNECT,
+-	CARD_STATUS_PMKID
+-} CARD_STATUS_TYPE, *PCARD_STATUS_TYPE;
+-
+ struct vnt_private;
+ 
+ void CARDvSetRSPINF(struct vnt_private *priv, u8 bb_type);

commit f45de8cf2f4b05d913975f346b652ece0fcd7ff1
+Author: Nishka Dasgupta 
+Date:   Sat Mar 24 11:59:14 2018 +0000
+
+    staging: vt6655: Delete unused enum CARD_PKT_TYPE
+    
+    Delete unused enum CARD_PKT_TYPE.
+    
+    Signed-off-by: Nishka Dasgupta 
+    Acked-by: Julia Lawall 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/vt6655/card.h b/drivers/staging/vt6655/card.h
+index be5254ab193f..07d9fa06a94b 100644
+--- a/drivers/staging/vt6655/card.h
++++ b/drivers/staging/vt6655/card.h
+@@ -39,13 +39,6 @@
+ #define CB_MAX_CHANNEL_5G       42
+ #define CB_MAX_CHANNEL          (CB_MAX_CHANNEL_24G + CB_MAX_CHANNEL_5G)
+ 
+-enum CARD_PKT_TYPE {
+-	PKT_TYPE_802_11_BCN,
+-	PKT_TYPE_802_11_MNG,
+-	PKT_TYPE_802_11_DATA,
+-	PKT_TYPE_802_11_ALL
+-};
+-
+ typedef enum _CARD_STATUS_TYPE {
+ 	CARD_STATUS_MEDIA_CONNECT,
+ 	CARD_STATUS_MEDIA_DISCONNECT,

commit f81746470b47d9815ecc7de5724242960a87bd2a
+Author: Nishka Dasgupta 
+Date:   Tue Mar 20 20:27:55 2018 +0000
+
+    staging: vt6655: Change typedef enum to enum
+    
+    Change typedef enum to enum. Issue found with checkpatch.
+    
+    Signed-off-by: Nishka Dasgupta 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/vt6655/card.h b/drivers/staging/vt6655/card.h
+index 487039a64587..be5254ab193f 100644
+--- a/drivers/staging/vt6655/card.h
++++ b/drivers/staging/vt6655/card.h
+@@ -39,12 +39,12 @@
+ #define CB_MAX_CHANNEL_5G       42
+ #define CB_MAX_CHANNEL          (CB_MAX_CHANNEL_24G + CB_MAX_CHANNEL_5G)
+ 
+-typedef enum _CARD_PKT_TYPE {
++enum CARD_PKT_TYPE {
+ 	PKT_TYPE_802_11_BCN,
+ 	PKT_TYPE_802_11_MNG,
+ 	PKT_TYPE_802_11_DATA,
+ 	PKT_TYPE_802_11_ALL
+-} CARD_PKT_TYPE, *PCARD_PKT_TYPE;
++};
+ 
+ typedef enum _CARD_STATUS_TYPE {
+ 	CARD_STATUS_MEDIA_CONNECT,

commit 7c1f094ac6a913e0997a2c77daf2567a775c4222
+Author: Nishka Dasgupta 
+Date:   Tue Mar 20 20:47:22 2018 +0000
+
+    staging: vc04_services: bcm2835-camera: Add blank line after declaration
+    
+    Add blank line after declaration. Issue found with checkpatch.
+    
+    Signed-off-by: Nishka Dasgupta 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/vc04_services/bcm2835-camera/controls.c b/drivers/staging/vc04_services/bcm2835-camera/controls.c
+index 0736214e1422..cff7b1e07153 100644
+--- a/drivers/staging/vc04_services/bcm2835-camera/controls.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/controls.c
+@@ -1270,6 +1270,7 @@ int bm2835_mmal_init_controls(struct bm2835_mmal_dev *dev,
+ 				 * mismatches.
+ 				 */
+ 				int i;
++
+ 				mask = 1 << V4L2_SCENE_MODE_NONE;
+ 				for (i = 0;
+ 				     i < ARRAY_SIZE(scene_configs);

commit ad7d95e979eb16362144893784dc3c2bdb8884b7
+Author: Nishka Dasgupta 
+Date:   Thu Mar 15 17:59:15 2018 +0000
+
+    staging: sm750fb: Remove typedef
+    
+    Change typedef enum to enum and ensure compatibility of change. Issue
+    found with checkpatch.
+    
+    Signed-off-by: Nishka Dasgupta 
+    Acked-by: Julia Lawall 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/sm750fb/ddk750_display.c b/drivers/staging/sm750fb/ddk750_display.c
+index c6fd90191530..1273e7d18925 100644
+--- a/drivers/staging/sm750fb/ddk750_display.c
++++ b/drivers/staging/sm750fb/ddk750_display.c
+@@ -111,7 +111,7 @@ static void swPanelPowerSequence(int disp, int delay)
+ 	primary_wait_vertical_sync(delay);
+ }
+ 
+-void ddk750_setLogicalDispOut(disp_output_t output)
++void ddk750_setLogicalDispOut(enum disp_output output)
+ {
+ 	unsigned int reg;
+ 
+diff --git a/drivers/staging/sm750fb/ddk750_display.h b/drivers/staging/sm750fb/ddk750_display.h
+index 523bbf33521c..7fd101d98199 100644
+--- a/drivers/staging/sm750fb/ddk750_display.h
++++ b/drivers/staging/sm750fb/ddk750_display.h
+@@ -89,7 +89,7 @@
+  * LCD1 means panel path TFT1  & panel path DVI (so enable DAC)
+  * CRT means crt path DSUB
+  */
+-typedef enum _disp_output_t {
++enum disp_output {
+ 	do_LCD1_PRI = PNL_2_PRI | PRI_TP_ON | PNL_SEQ_ON | DAC_ON,
+ 	do_LCD1_SEC = PNL_2_SEC | SEC_TP_ON | PNL_SEQ_ON | DAC_ON,
+ 	do_LCD2_PRI = CRT_2_PRI | PRI_TP_ON | DUAL_TFT_ON,
+@@ -100,9 +100,8 @@ typedef enum _disp_output_t {
+ 	 */
+ 	do_CRT_PRI = CRT_2_PRI | PRI_TP_ON | DPMS_ON | DAC_ON,
+ 	do_CRT_SEC = CRT_2_SEC | SEC_TP_ON | DPMS_ON | DAC_ON,
+-}
+-disp_output_t;
++};
+ 
+-void ddk750_setLogicalDispOut(disp_output_t output);
++void ddk750_setLogicalDispOut(enum disp_output output);
+ 
+ #endif
+diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c
+index f996f8460641..edeae9d06883 100644
+--- a/drivers/staging/sm750fb/sm750_hw.c
++++ b/drivers/staging/sm750fb/sm750_hw.c
+@@ -185,7 +185,7 @@ int hw_sm750_output_setMode(struct lynxfb_output *output,
+ 			    struct fb_fix_screeninfo *fix)
+ {
+ 	int ret;
+-	disp_output_t disp_set;
++	enum disp_output disp_set;
+ 	int channel;
+ 
+ 	ret = 0;

commit 816148138518da9362a3b0c46f3cdf3d97282008
+Author: Nishka Dasgupta 
+Date:   Wed Mar 14 18:29:30 2018 +0000
+
+    staging: ks7010: Remove braces around single statement
+    
+    Remove braces around single statement. Issue found with checkpatch.
+    
+    Signed-off-by: Nishka Dasgupta 
+    Acked-by: Julia Lawall 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c
+index 05f7be4638fe..c05102d75ea1 100644
+--- a/drivers/staging/ks7010/ks_hostif.c
++++ b/drivers/staging/ks7010/ks_hostif.c
+@@ -1385,9 +1385,8 @@ static __le16 ks_wlan_cap(struct ks_wlan_private *priv)
+ {
+ 	u16 capability = 0x0000;
+ 
+-	if (priv->reg.preamble == SHORT_PREAMBLE) {
++	if (priv->reg.preamble == SHORT_PREAMBLE)
+ 		capability |= WLAN_CAPABILITY_SHORT_PREAMBLE;
+-	}
+ 
+ 	capability &= ~(WLAN_CAPABILITY_PBCC);	/* pbcc not support */
+ 

commit 1d49c89dc80e16b3313e60e3fadc3ebc3cde7cba
+Author: Nishka Dasgupta 
+Date:   Wed Mar 14 18:22:10 2018 +0000
+
+    staging: speakup: Add blank line after declaration
+    
+    Add blank line after declaration. Issue found with checkpatch.
+    
+    Signed-off-by: Nishka Dasgupta 
+    Reviewed-by: Samuel Thibault 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/speakup/spk_ttyio.c b/drivers/staging/speakup/spk_ttyio.c
+index ade03b03bcd3..eac63aab8162 100644
+--- a/drivers/staging/speakup/spk_ttyio.c
++++ b/drivers/staging/speakup/spk_ttyio.c
+@@ -226,6 +226,7 @@ static int spk_ttyio_out(struct spk_synth *in_synth, const char ch)
+ static int spk_ttyio_out_unicode(struct spk_synth *in_synth, u16 ch)
+ {
+ 	int ret;
++
+ 	if (ch < 0x80)
+ 		ret = spk_ttyio_out(in_synth, ch);
+ 	else if (ch < 0x800) {

commit 951c16bf48676c90c526fafeec3bb6d1ba87ff0b
+Author: Nishka Dasgupta 
+Date:   Sun Mar 4 00:42:44 2018 +0530
+
+    staging: vc04_services: bcm2835-audio: Change to unsigned int *
+    
+    Change 'unsigned *' to 'unsigned int *'. Issue found with checkpatch.
+    
+    Signed-off-by: Nishka Dasgupta 
+    Acked-by: Julia Lawall 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+index 063004052487..8359cf881bef 100644
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -414,7 +414,7 @@ static int snd_bcm2835_pcm_lib_ioctl(struct snd_pcm_substream *substream,
+ 	int ret = snd_pcm_lib_ioctl(substream, cmd, arg);
+ 
+ 	audio_info(" .. substream=%p, cmd=%d, arg=%p (%x) ret=%d\n", substream,
+-		cmd, arg, arg ? *(unsigned *) arg : 0, ret);
++		cmd, arg, arg ? *(unsigned int *)arg : 0, ret);
+ 	return ret;
+ }
+ 

commit d3e3a2b50a1a6336f62de7976cd6af5c37226a3b
+Author: Nishka Dasgupta 
+Date:   Sun Mar 4 00:24:28 2018 +0530
+
+    staging: vc04_services: bcm2835-audio Format multiline comment
+    
+    Format multiline comment by moving '*/' to a new line. Issue found with
+    checkpatch.
+    
+    Signed-off-by: Nishka Dasgupta 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+index 22214ee71dbc..063004052487 100644
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -279,7 +279,8 @@ static int snd_bcm2835_pcm_prepare(struct snd_pcm_substream *substream)
+ 
+ 	/* notify the vchiq that it should enter spdif passthrough mode by
+ 	 * setting channels=0 (see
+-	 * https://github.com/raspberrypi/linux/issues/528) */
++	 * https://github.com/raspberrypi/linux/issues/528)
++	 */
+ 	if (chip->spdif_status & IEC958_AES0_NONAUDIO)
+ 		channels = 0;
+ 	else

commit 0b444fb750f2db7355c7c789cdd84e7e4aa0dd81
+Author: Nishka Dasgupta 
+Date:   Fri Mar 2 01:08:27 2018 +0530
+
+    staging: vc04_services: bcm2835-audio: Add blank line after declaration
+    
+    Add blank line after declaration. Issue found with checkpatch.
+    
+    Signed-off-by: Nishka Dasgupta 
+    Acked-by: Julia Lawall 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+index 5f7551fbf5cf..22214ee71dbc 100644
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -209,6 +209,7 @@ static int snd_bcm2835_playback_close(struct snd_pcm_substream *substream)
+ 	 */
+ 	if (alsa_stream->running) {
+ 		int err;
++
+ 		err = bcm2835_audio_stop(alsa_stream);
+ 		alsa_stream->running = 0;
+ 		if (err)

\ No newline at end of file diff --git a/detail/44.html b/detail/44.html new file mode 100644 index 0000000..82df720 --- /dev/null +++ b/detail/44.html @@ -0,0 +1,3040 @@ +

Patches contributed by Stanford University


commit f15cfca818d756dd1c9492530091dfd583359db3
+Author: Keith Winstein 
+Date:   Sun Oct 25 22:05:47 2020 -0700
+
+    ALSA: usb-audio: Add implicit feedback quirk for Zoom UAC-2
+    
+    The Zoom UAC-2 USB audio interface provides an async playback endpoint
+    ("1 OUT (ASYNC)") and capture endpoint ("2 IN (ASYNC)"), both with
+    2-channel S32_LE in 44.1, 48, 88.2, 96, 176.4, or 192
+    kilosamples/s. The device provides explicit feedback to adjust the
+    host's playback rate, but the feedback appears unstable and biased
+    relative to the device's capture rate.
+    
+    "alsaloop -t 1000" experiences playback underruns and tries to
+    resample the captured audio to match the varying playback
+    rate. Forcing the kernel to use implicit feedback appears to
+    produce more stable results. This causes the host to transmit one
+    playback sample for each capture sample received. (Zoom North America
+    has been notified of this change.)
+    
+    Signed-off-by: Keith Winstein 
+    Tested-by: Keith Winstein 
+    Cc: 
+    BugLink: https://lore.kernel.org/r/20201027071841.GA164525@trolley.csail.mit.edu
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
+index b401ee894e1b..31b1edf53c41 100644
+--- a/sound/usb/pcm.c
++++ b/sound/usb/pcm.c
+@@ -352,6 +352,10 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
+ 		ep = 0x81;
+ 		ifnum = 2;
+ 		goto add_sync_ep_from_ifnum;
++	case USB_ID(0x1686, 0xf029): /* Zoom UAC-2 */
++		ep = 0x82;
++		ifnum = 2;
++		goto add_sync_ep_from_ifnum;
+ 	case USB_ID(0x1397, 0x0001): /* Behringer UFX1604 */
+ 	case USB_ID(0x1397, 0x0002): /* Behringer UFX1204 */
+ 		ep = 0x81;

commit a1d1e9be5a1dafe0ddc2181a9201c2ae29c71eff
+Author: David Ramos 
+Date:   Fri Feb 13 13:11:51 2015 -0800
+
+    svcrpc: fix memory leak in gssp_accept_sec_context_upcall
+    
+    Our UC-KLEE tool found a kernel memory leak of 512 bytes (on x86_64) for
+    each call to gssp_accept_sec_context_upcall()
+    (net/sunrpc/auth_gss/gss_rpc_upcall.c). Since it appears that this call
+    can be triggered by remote connections (at least, from a cursory a
+    glance at the call chain), it may be exploitable to cause kernel memory
+    exhaustion. We found the bug in kernel 3.16.3, but it appears to date
+    back to commit 9dfd87da1aeb0fd364167ad199f40fe96a6a87be (2013-08-20).
+    
+    The gssp_accept_sec_context_upcall() function performs a pair of calls
+    to gssp_alloc_receive_pages() and gssp_free_receive_pages().  The first
+    allocates memory for arg->pages.  The second then frees the pages
+    pointed to by the arg->pages array, but not the array itself.
+    
+    Reported-by: David A. Ramos 
+    Fixes: 9dfd87da1aeb ("rpc: fix huge kmalloc's in gss-proxy”)
+    Signed-off-by: David A. Ramos 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/net/sunrpc/auth_gss/gss_rpc_upcall.c b/net/sunrpc/auth_gss/gss_rpc_upcall.c
+index abbb7dcd1689..59eeed43eda2 100644
+--- a/net/sunrpc/auth_gss/gss_rpc_upcall.c
++++ b/net/sunrpc/auth_gss/gss_rpc_upcall.c
+@@ -217,6 +217,8 @@ static void gssp_free_receive_pages(struct gssx_arg_accept_sec_context *arg)
+ 
+ 	for (i = 0; i < arg->npages && arg->pages[i]; i++)
+ 		__free_page(arg->pages[i]);
++
++	kfree(arg->pages);
+ }
+ 
+ static int gssp_alloc_receive_pages(struct gssx_arg_accept_sec_context *arg)

commit bacd73ae76c310bc3c71d21a2864746fd9696d3c
+Author: Remi Machet 
+Date:   Fri May 16 10:26:02 2008 +1000
+
+    powerpc: Add C2K to configuration
+    
+    Support for the C2K cPCI Single Board Computer from GEFanuc
+    (PowerPC MPC7448 with a Marvell MV64460 chipset).
+    All features of the board are not supported yet, but the board
+    boots, flash works, all Ethernet ports are working and PCI
+    devices are all found (USB and SATA on PCI1 do not work yet).
+    
+    Part 5 of 5: add the Kconfig entry for the C2K board.
+    
+    Signed-off-by: Remi Machet 
+    Signed-off-by: Paul Mackerras 
+
+diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig
+index 429088967813..4f9f8184d164 100644
+--- a/arch/powerpc/platforms/embedded6xx/Kconfig
++++ b/arch/powerpc/platforms/embedded6xx/Kconfig
+@@ -59,6 +59,16 @@ config PPC_PRPMC2800
+ 	help
+ 	  This option enables support for the Motorola PrPMC2800 board
+ 
++config PPC_C2K
++	bool "SBS/GEFanuc C2K board"
++	depends on EMBEDDED6xx
++	select MV64X60
++	select NOT_COHERENT_CACHE
++	select MTD_CFI_I4
++	help
++	  This option enables support for the GE Fanuc C2K board (formerly
++	  an SBS board).
++
+ config TSI108_BRIDGE
+ 	bool
+ 	select PCI

commit 2059615f37505b7ee988549ce4de34b620110ebe
+Author: Remi Machet 
+Date:   Fri May 16 10:25:28 2008 +1000
+
+    powerpc: Default configuration for C2K
+    
+    Support for the C2K cPCI Single Board Computer from GEFanuc
+    (PowerPC MPC7448 with a Marvell MV64460 chipset).
+    All features of the board are not supported yet, but the board
+    boots, flash works, all Ethernet ports are working and PCI
+    devices are all found (USB and SATA on PCI1 do not work yet).
+    
+    Part 4 of 5: this is the default config for the board.  In this
+    configuration the kernel is going to try to boot from MTD
+    partition 3 on the NOR flash (see c2k.dts for details about
+    the partitioning of the flash).
+    
+    Signed-off-by: Remi Machet 
+    Signed-off-by: Paul Mackerras 
+
+diff --git a/arch/powerpc/configs/c2k_defconfig b/arch/powerpc/configs/c2k_defconfig
+new file mode 100644
+index 000000000000..dc599c7e97d5
+--- /dev/null
++++ b/arch/powerpc/configs/c2k_defconfig
+@@ -0,0 +1,1872 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.26-rc2
++# Thu May 15 11:00:14 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++CONFIG_6xx=y
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++# CONFIG_ALTIVEC is not set
++CONFIG_PPC_STD_MMU=y
++CONFIG_PPC_STD_MMU_32=y
++# CONFIG_PPC_MM_SLICES is not set
++# CONFIG_SMP is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_CHECK_CACHE_COHERENCY=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++# CONFIG_PPC_UDBG_16550 is not set
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++CONFIG_BSD_PROCESS_ACCT=y
++# CONFIG_BSD_PROCESS_ACCT_V3 is not set
++# CONFIG_TASKSTATS is not set
++CONFIG_AUDIT=y
++CONFIG_AUDITSYSCALL=y
++CONFIG_AUDIT_TREE=y
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=17
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++CONFIG_NAMESPACES=y
++# CONFIG_UTS_NS is not set
++# CONFIG_IPC_NS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++# CONFIG_EMBEDDED is not set
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_SYSCTL_SYSCALL_CHECK=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++CONFIG_PROFILING=y
++# CONFIG_MARKERS is not set
++CONFIG_OPROFILE=m
++CONFIG_HAVE_OPROFILE=y
++CONFIG_KPROBES=y
++CONFIG_KRETPROBES=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++# CONFIG_HAVE_DMA_ATTRS is not set
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++# CONFIG_MODULE_FORCE_LOAD is not set
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++CONFIG_MODVERSIONS=y
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++CONFIG_PPC_MULTIPLATFORM=y
++# CONFIG_PPC_82xx is not set
++# CONFIG_PPC_83xx is not set
++# CONFIG_PPC_86xx is not set
++CONFIG_CLASSIC32=y
++# CONFIG_PPC_CHRP is not set
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_MPC5121_ADS is not set
++# CONFIG_PPC_MPC52xx is not set
++# CONFIG_PPC_PMAC is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_EMBEDDED6xx=y
++# CONFIG_LINKSTATION is not set
++# CONFIG_STORCENTER is not set
++# CONFIG_MPC7448HPC2 is not set
++# CONFIG_PPC_HOLLY is not set
++# CONFIG_PPC_PRPMC2800 is not set
++CONFIG_PPC_C2K=y
++CONFIG_MV64X60=y
++# CONFIG_IPIC is not set
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++CONFIG_CPU_FREQ=y
++CONFIG_CPU_FREQ_TABLE=y
++# CONFIG_CPU_FREQ_DEBUG is not set
++CONFIG_CPU_FREQ_STAT=y
++# CONFIG_CPU_FREQ_STAT_DETAILS is not set
++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
++CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
++CONFIG_CPU_FREQ_GOV_POWERSAVE=m
++CONFIG_CPU_FREQ_GOV_USERSPACE=y
++CONFIG_CPU_FREQ_GOV_ONDEMAND=m
++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
++
++#
++# CPU Frequency drivers
++#
++# CONFIG_TAU is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++CONFIG_HIGHMEM=y
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++# CONFIG_PREEMPT_NONE is not set
++CONFIG_PREEMPT_VOLUNTARY=y
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_MISC=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++# CONFIG_KEXEC is not set
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_PAGEFLAGS_EXTENDED=y
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_FORCE_MAX_ZONEORDER=11
++# CONFIG_PROC_DEVICETREE is not set
++# CONFIG_CMDLINE_BOOL is not set
++CONFIG_PM=y
++# CONFIG_PM_DEBUG is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++CONFIG_PCI_MSI=y
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++CONFIG_HOTPLUG_PCI=y
++# CONFIG_HOTPLUG_PCI_FAKE is not set
++# CONFIG_HOTPLUG_PCI_CPCI is not set
++CONFIG_HOTPLUG_PCI_SHPC=m
++# CONFIG_HAS_RAPIDIO is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_PAGE_OFFSET=0xc0000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_PHYSICAL_START=0x00000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_PACKET_MMAP=y
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++CONFIG_XFRM_USER=y
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++CONFIG_NET_KEY=m
++# CONFIG_NET_KEY_MIGRATE is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++CONFIG_IP_ADVANCED_ROUTER=y
++CONFIG_ASK_IP_FIB_HASH=y
++# CONFIG_IP_FIB_TRIE is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_MULTIPLE_TABLES=y
++CONFIG_IP_ROUTE_MULTIPATH=y
++CONFIG_IP_ROUTE_VERBOSE=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++CONFIG_NET_IPIP=m
++CONFIG_NET_IPGRE=m
++CONFIG_NET_IPGRE_BROADCAST=y
++CONFIG_IP_MROUTE=y
++CONFIG_IP_PIMSM_V1=y
++CONFIG_IP_PIMSM_V2=y
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++CONFIG_INET_AH=m
++CONFIG_INET_ESP=m
++CONFIG_INET_IPCOMP=m
++CONFIG_INET_XFRM_TUNNEL=m
++CONFIG_INET_TUNNEL=m
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++CONFIG_IP_VS=m
++# CONFIG_IP_VS_DEBUG is not set
++CONFIG_IP_VS_TAB_BITS=12
++
++#
++# IPVS transport protocol load balancing support
++#
++CONFIG_IP_VS_PROTO_TCP=y
++CONFIG_IP_VS_PROTO_UDP=y
++CONFIG_IP_VS_PROTO_ESP=y
++CONFIG_IP_VS_PROTO_AH=y
++
++#
++# IPVS scheduler
++#
++CONFIG_IP_VS_RR=m
++CONFIG_IP_VS_WRR=m
++CONFIG_IP_VS_LC=m
++CONFIG_IP_VS_WLC=m
++CONFIG_IP_VS_LBLC=m
++CONFIG_IP_VS_LBLCR=m
++CONFIG_IP_VS_DH=m
++CONFIG_IP_VS_SH=m
++CONFIG_IP_VS_SED=m
++CONFIG_IP_VS_NQ=m
++
++#
++# IPVS application helper
++#
++CONFIG_IP_VS_FTP=m
++CONFIG_IPV6=m
++CONFIG_IPV6_PRIVACY=y
++# CONFIG_IPV6_ROUTER_PREF is not set
++# CONFIG_IPV6_OPTIMISTIC_DAD is not set
++CONFIG_INET6_AH=m
++CONFIG_INET6_ESP=m
++CONFIG_INET6_IPCOMP=m
++# CONFIG_IPV6_MIP6 is not set
++CONFIG_INET6_XFRM_TUNNEL=m
++CONFIG_INET6_TUNNEL=m
++CONFIG_INET6_XFRM_MODE_TRANSPORT=m
++CONFIG_INET6_XFRM_MODE_TUNNEL=m
++CONFIG_INET6_XFRM_MODE_BEET=m
++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
++CONFIG_IPV6_SIT=m
++CONFIG_IPV6_NDISC_NODETYPE=y
++CONFIG_IPV6_TUNNEL=m
++# CONFIG_IPV6_MULTIPLE_TABLES is not set
++# CONFIG_IPV6_MROUTE is not set
++# CONFIG_NETLABEL is not set
++CONFIG_NETWORK_SECMARK=y
++CONFIG_NETFILTER=y
++# CONFIG_NETFILTER_DEBUG is not set
++CONFIG_NETFILTER_ADVANCED=y
++CONFIG_BRIDGE_NETFILTER=y
++
++#
++# Core Netfilter Configuration
++#
++# CONFIG_NETFILTER_NETLINK_QUEUE is not set
++# CONFIG_NETFILTER_NETLINK_LOG is not set
++# CONFIG_NF_CONNTRACK is not set
++CONFIG_NETFILTER_XTABLES=m
++# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
++# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
++# CONFIG_NETFILTER_XT_TARGET_MARK is not set
++# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
++# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
++# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
++# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
++# CONFIG_NETFILTER_XT_TARGET_SECMARK is not set
++# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
++# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
++# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
++# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
++# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
++# CONFIG_NETFILTER_XT_MATCH_ESP is not set
++# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
++# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
++# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
++# CONFIG_NETFILTER_XT_MATCH_MAC is not set
++# CONFIG_NETFILTER_XT_MATCH_MARK is not set
++# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
++# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
++# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
++# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
++# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
++# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
++# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
++# CONFIG_NETFILTER_XT_MATCH_REALM is not set
++# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
++# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
++# CONFIG_NETFILTER_XT_MATCH_STRING is not set
++# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
++# CONFIG_NETFILTER_XT_MATCH_TIME is not set
++# CONFIG_NETFILTER_XT_MATCH_U32 is not set
++# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
++
++#
++# IP: Netfilter Configuration
++#
++CONFIG_IP_NF_QUEUE=m
++CONFIG_IP_NF_IPTABLES=m
++CONFIG_IP_NF_MATCH_RECENT=m
++CONFIG_IP_NF_MATCH_ECN=m
++# CONFIG_IP_NF_MATCH_AH is not set
++CONFIG_IP_NF_MATCH_TTL=m
++CONFIG_IP_NF_MATCH_ADDRTYPE=m
++CONFIG_IP_NF_FILTER=m
++CONFIG_IP_NF_TARGET_REJECT=m
++CONFIG_IP_NF_TARGET_LOG=m
++CONFIG_IP_NF_TARGET_ULOG=m
++CONFIG_IP_NF_MANGLE=m
++CONFIG_IP_NF_TARGET_ECN=m
++# CONFIG_IP_NF_TARGET_TTL is not set
++CONFIG_IP_NF_RAW=m
++CONFIG_IP_NF_ARPTABLES=m
++CONFIG_IP_NF_ARPFILTER=m
++CONFIG_IP_NF_ARP_MANGLE=m
++
++#
++# IPv6: Netfilter Configuration
++#
++# CONFIG_IP6_NF_QUEUE is not set
++CONFIG_IP6_NF_IPTABLES=m
++CONFIG_IP6_NF_MATCH_RT=m
++CONFIG_IP6_NF_MATCH_OPTS=m
++CONFIG_IP6_NF_MATCH_FRAG=m
++CONFIG_IP6_NF_MATCH_HL=m
++CONFIG_IP6_NF_MATCH_IPV6HEADER=m
++# CONFIG_IP6_NF_MATCH_AH is not set
++# CONFIG_IP6_NF_MATCH_MH is not set
++CONFIG_IP6_NF_MATCH_EUI64=m
++CONFIG_IP6_NF_FILTER=m
++CONFIG_IP6_NF_TARGET_LOG=m
++# CONFIG_IP6_NF_TARGET_REJECT is not set
++CONFIG_IP6_NF_MANGLE=m
++# CONFIG_IP6_NF_TARGET_HL is not set
++CONFIG_IP6_NF_RAW=m
++
++#
++# Bridge: Netfilter Configuration
++#
++CONFIG_BRIDGE_NF_EBTABLES=m
++CONFIG_BRIDGE_EBT_BROUTE=m
++CONFIG_BRIDGE_EBT_T_FILTER=m
++CONFIG_BRIDGE_EBT_T_NAT=m
++CONFIG_BRIDGE_EBT_802_3=m
++CONFIG_BRIDGE_EBT_AMONG=m
++CONFIG_BRIDGE_EBT_ARP=m
++CONFIG_BRIDGE_EBT_IP=m
++CONFIG_BRIDGE_EBT_LIMIT=m
++CONFIG_BRIDGE_EBT_MARK=m
++CONFIG_BRIDGE_EBT_PKTTYPE=m
++CONFIG_BRIDGE_EBT_STP=m
++CONFIG_BRIDGE_EBT_VLAN=m
++CONFIG_BRIDGE_EBT_ARPREPLY=m
++CONFIG_BRIDGE_EBT_DNAT=m
++CONFIG_BRIDGE_EBT_MARK_T=m
++CONFIG_BRIDGE_EBT_REDIRECT=m
++CONFIG_BRIDGE_EBT_SNAT=m
++CONFIG_BRIDGE_EBT_LOG=m
++# CONFIG_BRIDGE_EBT_ULOG is not set
++# CONFIG_BRIDGE_EBT_NFLOG is not set
++# CONFIG_IP_DCCP is not set
++CONFIG_IP_SCTP=m
++# CONFIG_SCTP_DBG_MSG is not set
++# CONFIG_SCTP_DBG_OBJCNT is not set
++# CONFIG_SCTP_HMAC_NONE is not set
++# CONFIG_SCTP_HMAC_SHA1 is not set
++CONFIG_SCTP_HMAC_MD5=y
++# CONFIG_TIPC is not set
++CONFIG_ATM=m
++CONFIG_ATM_CLIP=m
++# CONFIG_ATM_CLIP_NO_ICMP is not set
++CONFIG_ATM_LANE=m
++# CONFIG_ATM_MPOA is not set
++CONFIG_ATM_BR2684=m
++# CONFIG_ATM_BR2684_IPFILTER is not set
++CONFIG_BRIDGE=m
++CONFIG_VLAN_8021Q=m
++# CONFIG_DECNET is not set
++CONFIG_LLC=m
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++CONFIG_NET_SCHED=y
++
++#
++# Queueing/Scheduling
++#
++CONFIG_NET_SCH_CBQ=m
++CONFIG_NET_SCH_HTB=m
++CONFIG_NET_SCH_HFSC=m
++CONFIG_NET_SCH_ATM=m
++CONFIG_NET_SCH_PRIO=m
++# CONFIG_NET_SCH_RR is not set
++CONFIG_NET_SCH_RED=m
++CONFIG_NET_SCH_SFQ=m
++CONFIG_NET_SCH_TEQL=m
++CONFIG_NET_SCH_TBF=m
++CONFIG_NET_SCH_GRED=m
++CONFIG_NET_SCH_DSMARK=m
++CONFIG_NET_SCH_NETEM=m
++
++#
++# Classification
++#
++CONFIG_NET_CLS=y
++# CONFIG_NET_CLS_BASIC is not set
++CONFIG_NET_CLS_TCINDEX=m
++CONFIG_NET_CLS_ROUTE4=m
++CONFIG_NET_CLS_ROUTE=y
++CONFIG_NET_CLS_FW=m
++CONFIG_NET_CLS_U32=m
++CONFIG_CLS_U32_PERF=y
++# CONFIG_CLS_U32_MARK is not set
++CONFIG_NET_CLS_RSVP=m
++CONFIG_NET_CLS_RSVP6=m
++# CONFIG_NET_CLS_FLOW is not set
++# CONFIG_NET_EMATCH is not set
++# CONFIG_NET_CLS_ACT is not set
++CONFIG_NET_CLS_IND=y
++CONFIG_NET_SCH_FIFO=y
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_NET_TCPPROBE is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++CONFIG_BT=m
++CONFIG_BT_L2CAP=m
++CONFIG_BT_SCO=m
++CONFIG_BT_RFCOMM=m
++CONFIG_BT_RFCOMM_TTY=y
++CONFIG_BT_BNEP=m
++CONFIG_BT_BNEP_MC_FILTER=y
++CONFIG_BT_BNEP_PROTO_FILTER=y
++CONFIG_BT_CMTP=m
++CONFIG_BT_HIDP=m
++
++#
++# Bluetooth device drivers
++#
++CONFIG_BT_HCIUSB=m
++CONFIG_BT_HCIUSB_SCO=y
++CONFIG_BT_HCIUART=m
++CONFIG_BT_HCIUART_H4=y
++CONFIG_BT_HCIUART_BCSP=y
++# CONFIG_BT_HCIUART_LL is not set
++CONFIG_BT_HCIBCM203X=m
++# CONFIG_BT_HCIBPA10X is not set
++CONFIG_BT_HCIBFUSB=m
++CONFIG_BT_HCIVHCI=m
++# CONFIG_AF_RXRPC is not set
++CONFIG_FIB_RULES=y
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++CONFIG_WIRELESS_EXT=y
++# CONFIG_MAC80211 is not set
++CONFIG_IEEE80211=m
++# CONFIG_IEEE80211_DEBUG is not set
++CONFIG_IEEE80211_CRYPT_WEP=m
++CONFIG_IEEE80211_CRYPT_CCMP=m
++CONFIG_IEEE80211_CRYPT_TKIP=m
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=m
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++CONFIG_MTD_OF_PARTS=y
++# CONFIG_MTD_AR7_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=m
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++CONFIG_MTD_CFI_I4=y
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++CONFIG_MTD_COMPLEX_MAPPINGS=y
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_PCI is not set
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++CONFIG_OF_I2C=m
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=m
++CONFIG_BLK_DEV_CRYPTOLOOP=m
++CONFIG_BLK_DEV_NBD=m
++# CONFIG_BLK_DEV_SX8 is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=16384
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_MISC_DEVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=m
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++CONFIG_SCSI_NETLINK=y
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=m
++CONFIG_CHR_DEV_ST=m
++CONFIG_CHR_DEV_OSST=m
++CONFIG_BLK_DEV_SR=m
++CONFIG_BLK_DEV_SR_VENDOR=y
++CONFIG_CHR_DEV_SG=m
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++CONFIG_SCSI_CONSTANTS=y
++CONFIG_SCSI_LOGGING=y
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++CONFIG_SCSI_SPI_ATTRS=m
++CONFIG_SCSI_FC_ATTRS=m
++CONFIG_SCSI_ISCSI_ATTRS=m
++# CONFIG_SCSI_SAS_LIBSAS is not set
++CONFIG_SCSI_SRP_ATTRS=m
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++CONFIG_BLK_DEV_3W_XXXX_RAID=m
++CONFIG_SCSI_3W_9XXX=m
++CONFIG_SCSI_ACARD=m
++CONFIG_SCSI_AACRAID=m
++CONFIG_SCSI_AIC7XXX=m
++CONFIG_AIC7XXX_CMDS_PER_DEVICE=4
++CONFIG_AIC7XXX_RESET_DELAY_MS=15000
++# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
++CONFIG_AIC7XXX_DEBUG_MASK=0
++# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
++CONFIG_SCSI_AIC7XXX_OLD=m
++CONFIG_SCSI_AIC79XX=m
++CONFIG_AIC79XX_CMDS_PER_DEVICE=4
++CONFIG_AIC79XX_RESET_DELAY_MS=15000
++# CONFIG_AIC79XX_DEBUG_ENABLE is not set
++CONFIG_AIC79XX_DEBUG_MASK=0
++# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++CONFIG_SCSI_ARCMSR=m
++CONFIG_MEGARAID_NEWGEN=y
++CONFIG_MEGARAID_MM=m
++CONFIG_MEGARAID_MAILBOX=m
++# CONFIG_MEGARAID_LEGACY is not set
++CONFIG_MEGARAID_SAS=m
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_EATA is not set
++CONFIG_SCSI_FUTURE_DOMAIN=m
++CONFIG_SCSI_GDTH=m
++CONFIG_SCSI_IPS=m
++CONFIG_SCSI_INITIO=m
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_MVSAS is not set
++# CONFIG_SCSI_STEX is not set
++CONFIG_SCSI_SYM53C8XX_2=m
++CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
++CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
++CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
++CONFIG_SCSI_SYM53C8XX_MMIO=y
++CONFIG_SCSI_QLOGIC_1280=m
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++CONFIG_SCSI_LPFC=m
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++CONFIG_DUMMY=m
++CONFIG_BONDING=m
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++CONFIG_TUN=m
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++CONFIG_VITESSE_PHY=y
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_MV643XX_ETH=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++# CONFIG_NETDEV_10000 is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_IWLWIFI_LEDS is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_ATM_DRIVERS is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++CONFIG_SLHC=m
++# CONFIG_NET_FC is not set
++CONFIG_NETCONSOLE=m
++# CONFIG_NETCONSOLE_DYNAMIC is not set
++CONFIG_NETPOLL=y
++CONFIG_NETPOLL_TRAP=y
++CONFIG_NET_POLL_CONTROLLER=y
++CONFIG_ISDN=m
++CONFIG_ISDN_I4L=m
++CONFIG_ISDN_PPP=y
++CONFIG_ISDN_PPP_VJ=y
++CONFIG_ISDN_MPP=y
++CONFIG_IPPP_FILTER=y
++# CONFIG_ISDN_PPP_BSDCOMP is not set
++CONFIG_ISDN_AUDIO=y
++CONFIG_ISDN_TTY_FAX=y
++
++#
++# ISDN feature submodules
++#
++CONFIG_ISDN_DRV_LOOP=m
++# CONFIG_ISDN_DIVERSION is not set
++
++#
++# ISDN4Linux hardware drivers
++#
++
++#
++# Passive cards
++#
++CONFIG_ISDN_DRV_HISAX=m
++
++#
++# D-channel protocol features
++#
++CONFIG_HISAX_EURO=y
++CONFIG_DE_AOC=y
++CONFIG_HISAX_NO_SENDCOMPLETE=y
++CONFIG_HISAX_NO_LLC=y
++CONFIG_HISAX_NO_KEYPAD=y
++CONFIG_HISAX_1TR6=y
++CONFIG_HISAX_NI1=y
++CONFIG_HISAX_MAX_CARDS=8
++
++#
++# HiSax supported cards
++#
++CONFIG_HISAX_16_3=y
++CONFIG_HISAX_S0BOX=y
++CONFIG_HISAX_FRITZPCI=y
++CONFIG_HISAX_AVM_A1_PCMCIA=y
++CONFIG_HISAX_ELSA=y
++CONFIG_HISAX_DIEHLDIVA=y
++CONFIG_HISAX_SEDLBAUER=y
++CONFIG_HISAX_NICCY=y
++CONFIG_HISAX_BKM_A4T=y
++CONFIG_HISAX_SCT_QUADRO=y
++CONFIG_HISAX_GAZEL=y
++CONFIG_HISAX_W6692=y
++CONFIG_HISAX_HFC_SX=y
++# CONFIG_HISAX_DEBUG is not set
++
++#
++# HiSax PCMCIA card service modules
++#
++
++#
++# HiSax sub driver modules
++#
++CONFIG_HISAX_ST5481=m
++CONFIG_HISAX_HFCUSB=m
++# CONFIG_HISAX_HFC4S8S is not set
++CONFIG_HISAX_FRITZ_PCIPNP=m
++CONFIG_HISAX_HDLC=y
++
++#
++# Active cards
++#
++CONFIG_HYSDN=m
++CONFIG_HYSDN_CAPI=y
++# CONFIG_ISDN_DRV_GIGASET is not set
++CONFIG_ISDN_CAPI=m
++CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
++CONFIG_CAPI_TRACE=y
++CONFIG_ISDN_CAPI_MIDDLEWARE=y
++CONFIG_ISDN_CAPI_CAPI20=m
++CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
++CONFIG_ISDN_CAPI_CAPIFS=m
++CONFIG_ISDN_CAPI_CAPIDRV=m
++
++#
++# CAPI hardware drivers
++#
++CONFIG_CAPI_AVM=y
++CONFIG_ISDN_DRV_AVMB1_B1PCI=m
++CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
++CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
++CONFIG_ISDN_DRV_AVMB1_T1PCI=m
++CONFIG_ISDN_DRV_AVMB1_C4=m
++CONFIG_CAPI_EICON=y
++CONFIG_ISDN_DIVAS=m
++CONFIG_ISDN_DIVAS_BRIPCI=y
++CONFIG_ISDN_DIVAS_PRIPCI=y
++CONFIG_ISDN_DIVAS_DIVACAPI=m
++CONFIG_ISDN_DIVAS_USERIDI=m
++CONFIG_ISDN_DIVAS_MAINT=m
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++CONFIG_INPUT_MISC=y
++# CONFIG_INPUT_ATI_REMOTE is not set
++# CONFIG_INPUT_ATI_REMOTE2 is not set
++# CONFIG_INPUT_KEYSPAN_REMOTE is not set
++# CONFIG_INPUT_POWERMATE is not set
++# CONFIG_INPUT_YEALINK is not set
++CONFIG_INPUT_UINPUT=m
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++CONFIG_DEVKMEM=y
++CONFIG_SERIAL_NONSTANDARD=y
++# CONFIG_COMPUTONE is not set
++# CONFIG_ROCKETPORT is not set
++# CONFIG_CYCLADES is not set
++# CONFIG_DIGIEPCA is not set
++# CONFIG_MOXA_INTELLIO is not set
++# CONFIG_MOXA_SMARTIO is not set
++# CONFIG_ISI is not set
++# CONFIG_SYNCLINK is not set
++# CONFIG_SYNCLINKMP is not set
++# CONFIG_SYNCLINK_GT is not set
++# CONFIG_N_HDLC is not set
++# CONFIG_RISCOM8 is not set
++# CONFIG_SPECIALIX is not set
++# CONFIG_SX is not set
++# CONFIG_RIO is not set
++# CONFIG_STALDRV is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_MPSC=y
++CONFIG_SERIAL_MPSC_CONSOLE=y
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_UNIX98_PTYS=y
++# CONFIG_LEGACY_PTYS is not set
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=m
++CONFIG_NVRAM=m
++CONFIG_GEN_RTC=m
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++CONFIG_RAW_DRIVER=y
++CONFIG_MAX_RAW_DEVS=8192
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=m
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=m
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++# CONFIG_I2C_MPC is not set
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++# CONFIG_I2C_PCA_PLATFORM is not set
++CONFIG_I2C_MV64XXX=m
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++CONFIG_SENSORS_EEPROM=m
++CONFIG_SENSORS_PCF8574=m
++# CONFIG_PCF8575 is not set
++CONFIG_SENSORS_PCF8591=m
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++# CONFIG_SPI is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=m
++CONFIG_HWMON_VID=m
++# CONFIG_SENSORS_AD7418 is not set
++CONFIG_SENSORS_ADM1021=m
++CONFIG_SENSORS_ADM1025=m
++CONFIG_SENSORS_ADM1026=m
++# CONFIG_SENSORS_ADM1029 is not set
++CONFIG_SENSORS_ADM1031=m
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++CONFIG_SENSORS_DS1621=m
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++CONFIG_SENSORS_GL518SM=m
++# CONFIG_SENSORS_GL520SM is not set
++CONFIG_SENSORS_IT87=m
++# CONFIG_SENSORS_LM63 is not set
++CONFIG_SENSORS_LM75=m
++CONFIG_SENSORS_LM77=m
++CONFIG_SENSORS_LM78=m
++CONFIG_SENSORS_LM80=m
++CONFIG_SENSORS_LM83=m
++CONFIG_SENSORS_LM85=m
++CONFIG_SENSORS_LM87=m
++CONFIG_SENSORS_LM90=m
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++CONFIG_SENSORS_MAX1619=m
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++CONFIG_SENSORS_SMSC47M1=m
++# CONFIG_SENSORS_SMSC47M192 is not set
++CONFIG_SENSORS_SMSC47B397=m
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++CONFIG_SENSORS_VIA686A=m
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++CONFIG_SENSORS_W83781D=m
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++CONFIG_SENSORS_W83L785TS=m
++# CONFIG_SENSORS_W83L786NG is not set
++CONFIG_SENSORS_W83627HF=m
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++CONFIG_SOFT_WATCHDOG=m
++# CONFIG_MV64X60_WDT is not set
++
++#
++# PCI-based Watchdog Cards
++#
++CONFIG_PCIPCWATCHDOG=m
++CONFIG_WDTPCI=m
++CONFIG_WDT_501_PCI=y
++
++#
++# USB-based Watchdog Cards
++#
++CONFIG_USBPCWATCHDOG=m
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++# CONFIG_HTC_PASIC3 is not set
++
++#
++# Multimedia devices
++#
++
++#
++# Multimedia core support
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++
++#
++# Multimedia drivers
++#
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++# CONFIG_HID_SUPPORT is not set
++CONFIG_HID=m
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=m
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++# CONFIG_USB_DEVICE_CLASS is not set
++# CONFIG_USB_DYNAMIC_MINORS is not set
++CONFIG_USB_SUSPEND=y
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_C67X00_HCD is not set
++CONFIG_USB_EHCI_HCD=m
++CONFIG_USB_EHCI_ROOT_HUB_TT=y
++# CONFIG_USB_EHCI_TT_NEWSCHED is not set
++CONFIG_USB_EHCI_HCD_PPC_OF=y
++# CONFIG_USB_ISP116X_HCD is not set
++# CONFIG_USB_ISP1760_HCD is not set
++CONFIG_USB_OHCI_HCD=m
++CONFIG_USB_OHCI_HCD_PPC_OF=y
++CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
++# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
++CONFIG_USB_OHCI_HCD_PCI=y
++CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
++CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++CONFIG_USB_UHCI_HCD=m
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++CONFIG_USB_ACM=m
++CONFIG_USB_PRINTER=m
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=m
++# CONFIG_USB_STORAGE_DEBUG is not set
++CONFIG_USB_STORAGE_DATAFAB=y
++CONFIG_USB_STORAGE_FREECOM=y
++CONFIG_USB_STORAGE_ISD200=y
++CONFIG_USB_STORAGE_DPCM=y
++# CONFIG_USB_STORAGE_USBAT is not set
++CONFIG_USB_STORAGE_SDDR09=y
++CONFIG_USB_STORAGE_SDDR55=y
++CONFIG_USB_STORAGE_JUMPSHOT=y
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_ONETOUCH is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++CONFIG_USB_MDC800=m
++CONFIG_USB_MICROTEK=m
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++CONFIG_USB_SERIAL=m
++CONFIG_USB_EZUSB=y
++CONFIG_USB_SERIAL_GENERIC=y
++# CONFIG_USB_SERIAL_AIRCABLE is not set
++# CONFIG_USB_SERIAL_AIRPRIME is not set
++# CONFIG_USB_SERIAL_ARK3116 is not set
++CONFIG_USB_SERIAL_BELKIN=m
++# CONFIG_USB_SERIAL_CH341 is not set
++CONFIG_USB_SERIAL_WHITEHEAT=m
++CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
++# CONFIG_USB_SERIAL_CP2101 is not set
++# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
++CONFIG_USB_SERIAL_EMPEG=m
++CONFIG_USB_SERIAL_FTDI_SIO=m
++# CONFIG_USB_SERIAL_FUNSOFT is not set
++CONFIG_USB_SERIAL_VISOR=m
++CONFIG_USB_SERIAL_IPAQ=m
++CONFIG_USB_SERIAL_IR=m
++CONFIG_USB_SERIAL_EDGEPORT=m
++CONFIG_USB_SERIAL_EDGEPORT_TI=m
++# CONFIG_USB_SERIAL_GARMIN is not set
++# CONFIG_USB_SERIAL_IPW is not set
++# CONFIG_USB_SERIAL_IUU is not set
++CONFIG_USB_SERIAL_KEYSPAN_PDA=m
++CONFIG_USB_SERIAL_KEYSPAN=m
++CONFIG_USB_SERIAL_KEYSPAN_MPR=y
++CONFIG_USB_SERIAL_KEYSPAN_USA28=y
++CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
++CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
++CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
++CONFIG_USB_SERIAL_KEYSPAN_USA19=y
++CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
++CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
++CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
++CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
++CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
++CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
++CONFIG_USB_SERIAL_KLSI=m
++CONFIG_USB_SERIAL_KOBIL_SCT=m
++CONFIG_USB_SERIAL_MCT_U232=m
++# CONFIG_USB_SERIAL_MOS7720 is not set
++# CONFIG_USB_SERIAL_MOS7840 is not set
++# CONFIG_USB_SERIAL_NAVMAN is not set
++CONFIG_USB_SERIAL_PL2303=m
++# CONFIG_USB_SERIAL_OTI6858 is not set
++# CONFIG_USB_SERIAL_SPCP8X5 is not set
++# CONFIG_USB_SERIAL_HP4X is not set
++CONFIG_USB_SERIAL_SAFE=m
++CONFIG_USB_SERIAL_SAFE_PADDED=y
++# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
++# CONFIG_USB_SERIAL_TI is not set
++CONFIG_USB_SERIAL_CYBERJACK=m
++CONFIG_USB_SERIAL_XIRCOM=m
++# CONFIG_USB_SERIAL_OPTION is not set
++CONFIG_USB_SERIAL_OMNINET=m
++# CONFIG_USB_SERIAL_DEBUG is not set
++
++#
++# USB Miscellaneous drivers
++#
++CONFIG_USB_EMI62=m
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++CONFIG_USB_AUERSWALD=m
++CONFIG_USB_RIO500=m
++CONFIG_USB_LEGOTOWER=m
++CONFIG_USB_LCD=m
++# CONFIG_USB_BERRY_CHARGE is not set
++CONFIG_USB_LED=m
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++CONFIG_USB_TEST=m
++CONFIG_USB_ATM=m
++CONFIG_USB_SPEEDTOUCH=m
++# CONFIG_USB_CXACRU is not set
++# CONFIG_USB_UEAGLEATM is not set
++# CONFIG_USB_XUSBATM is not set
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_ACCESSIBILITY is not set
++CONFIG_INFINIBAND=m
++CONFIG_INFINIBAND_USER_MAD=m
++CONFIG_INFINIBAND_USER_ACCESS=m
++CONFIG_INFINIBAND_USER_MEM=y
++CONFIG_INFINIBAND_ADDR_TRANS=y
++CONFIG_INFINIBAND_MTHCA=m
++CONFIG_INFINIBAND_MTHCA_DEBUG=y
++CONFIG_INFINIBAND_AMSO1100=m
++# CONFIG_INFINIBAND_AMSO1100_DEBUG is not set
++# CONFIG_MLX4_INFINIBAND is not set
++# CONFIG_INFINIBAND_NES is not set
++CONFIG_INFINIBAND_IPOIB=m
++CONFIG_INFINIBAND_IPOIB_CM=y
++CONFIG_INFINIBAND_IPOIB_DEBUG=y
++# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
++CONFIG_INFINIBAND_SRP=m
++# CONFIG_INFINIBAND_ISER is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++CONFIG_DMADEVICES=y
++
++#
++# DMA Devices
++#
++# CONFIG_FSL_DMA is not set
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++# CONFIG_EXT2_FS is not set
++CONFIG_EXT3_FS=m
++CONFIG_EXT3_FS_XATTR=y
++CONFIG_EXT3_FS_POSIX_ACL=y
++CONFIG_EXT3_FS_SECURITY=y
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=m
++CONFIG_FS_MBCACHE=m
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++CONFIG_FS_POSIX_ACL=y
++# CONFIG_XFS_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++CONFIG_QUOTA=y
++# CONFIG_QUOTA_NETLINK_INTERFACE is not set
++CONFIG_PRINT_QUOTA_WARNING=y
++# CONFIG_QFMT_V1 is not set
++CONFIG_QFMT_V2=y
++CONFIG_QUOTACTL=y
++# CONFIG_AUTOFS_FS is not set
++CONFIG_AUTOFS4_FS=m
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++CONFIG_UDF_FS=m
++CONFIG_UDF_NLS=y
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=m
++CONFIG_MSDOS_FS=m
++CONFIG_VFAT_FS=m
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_ECRYPT_FS is not set
++CONFIG_HFS_FS=m
++CONFIG_HFSPLUS_FS=m
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++CONFIG_CRAMFS=m
++CONFIG_VXFS_FS=m
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++CONFIG_NFS_V3_ACL=y
++CONFIG_NFS_V4=y
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_ACL_SUPPORT=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++CONFIG_SUNRPC_XPRT_RDMA=m
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++CONFIG_RPCSEC_GSS_SPKM3=m
++# CONFIG_SMB_FS is not set
++CONFIG_CIFS=m
++# CONFIG_CIFS_STATS is not set
++# CONFIG_CIFS_WEAK_PW_HASH is not set
++CONFIG_CIFS_XATTR=y
++CONFIG_CIFS_POSIX=y
++# CONFIG_CIFS_DEBUG2 is not set
++# CONFIG_CIFS_EXPERIMENTAL is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++CONFIG_OSF_PARTITION=y
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++CONFIG_MAC_PARTITION=y
++CONFIG_MSDOS_PARTITION=y
++CONFIG_BSD_DISKLABEL=y
++CONFIG_MINIX_SUBPARTITION=y
++CONFIG_SOLARIS_X86_PARTITION=y
++CONFIG_UNIXWARE_DISKLABEL=y
++# CONFIG_LDM_PARTITION is not set
++CONFIG_SGI_PARTITION=y
++# CONFIG_ULTRIX_PARTITION is not set
++CONFIG_SUN_PARTITION=y
++# CONFIG_KARMA_PARTITION is not set
++CONFIG_EFI_PARTITION=y
++# CONFIG_SYSV68_PARTITION is not set
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="utf8"
++CONFIG_NLS_CODEPAGE_437=y
++CONFIG_NLS_CODEPAGE_737=m
++CONFIG_NLS_CODEPAGE_775=m
++CONFIG_NLS_CODEPAGE_850=m
++CONFIG_NLS_CODEPAGE_852=m
++CONFIG_NLS_CODEPAGE_855=m
++CONFIG_NLS_CODEPAGE_857=m
++CONFIG_NLS_CODEPAGE_860=m
++CONFIG_NLS_CODEPAGE_861=m
++CONFIG_NLS_CODEPAGE_862=m
++CONFIG_NLS_CODEPAGE_863=m
++CONFIG_NLS_CODEPAGE_864=m
++CONFIG_NLS_CODEPAGE_865=m
++CONFIG_NLS_CODEPAGE_866=m
++CONFIG_NLS_CODEPAGE_869=m
++CONFIG_NLS_CODEPAGE_936=m
++CONFIG_NLS_CODEPAGE_950=m
++CONFIG_NLS_CODEPAGE_932=m
++CONFIG_NLS_CODEPAGE_949=m
++CONFIG_NLS_CODEPAGE_874=m
++CONFIG_NLS_ISO8859_8=m
++CONFIG_NLS_CODEPAGE_1250=m
++CONFIG_NLS_CODEPAGE_1251=m
++CONFIG_NLS_ASCII=y
++CONFIG_NLS_ISO8859_1=m
++CONFIG_NLS_ISO8859_2=m
++CONFIG_NLS_ISO8859_3=m
++CONFIG_NLS_ISO8859_4=m
++CONFIG_NLS_ISO8859_5=m
++CONFIG_NLS_ISO8859_6=m
++CONFIG_NLS_ISO8859_7=m
++CONFIG_NLS_ISO8859_9=m
++CONFIG_NLS_ISO8859_13=m
++CONFIG_NLS_ISO8859_14=m
++CONFIG_NLS_ISO8859_15=m
++CONFIG_NLS_KOI8_R=m
++CONFIG_NLS_KOI8_U=m
++CONFIG_NLS_UTF8=m
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_GENERIC_FIND_FIRST_BIT is not set
++CONFIG_CRC_CCITT=m
++# CONFIG_CRC16 is not set
++CONFIG_CRC_ITU_T=m
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++CONFIG_LIBCRC32C=m
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++CONFIG_CHECK_SIGNATURE=y
++CONFIG_HAVE_LMB=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=1024
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_DEBUG_OBJECTS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++CONFIG_DEBUG_SPINLOCK=y
++# CONFIG_DEBUG_MUTEXES is not set
++CONFIG_DEBUG_SPINLOCK_SLEEP=y
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_HIGHMEM=y
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_DEBUG_INFO=y
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_WRITECOUNT is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_KPROBES_SANITY_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_LKDTM is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++CONFIG_DEBUG_STACKOVERFLOW=y
++CONFIG_DEBUG_STACK_USAGE=y
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_IRQSTACKS is not set
++# CONFIG_BDI_SWITCH is not set
++CONFIG_BOOTX_TEXT=y
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++CONFIG_KEYS=y
++CONFIG_KEYS_DEBUG_PROC_KEYS=y
++CONFIG_SECURITY=y
++CONFIG_SECURITY_NETWORK=y
++# CONFIG_SECURITY_NETWORK_XFRM is not set
++CONFIG_SECURITY_CAPABILITIES=y
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
++CONFIG_SECURITY_SELINUX=y
++CONFIG_SECURITY_SELINUX_BOOTPARAM=y
++CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
++CONFIG_SECURITY_SELINUX_DISABLE=y
++CONFIG_SECURITY_SELINUX_DEVELOP=y
++CONFIG_SECURITY_SELINUX_AVC_STATS=y
++CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
++# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set
++# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
++CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_AEAD=m
++CONFIG_CRYPTO_BLKCIPHER=y
++CONFIG_CRYPTO_HASH=y
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_NULL=m
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_AUTHENC=m
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# Authenticated Encryption with Associated Data
++#
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_SEQIV is not set
++
++#
++# Block modes
++#
++CONFIG_CRYPTO_CBC=y
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_CTS is not set
++CONFIG_CRYPTO_ECB=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_XTS is not set
++
++#
++# Hash modes
++#
++CONFIG_CRYPTO_HMAC=y
++# CONFIG_CRYPTO_XCBC is not set
++
++#
++# Digest
++#
++CONFIG_CRYPTO_CRC32C=m
++CONFIG_CRYPTO_MD4=m
++CONFIG_CRYPTO_MD5=y
++CONFIG_CRYPTO_MICHAEL_MIC=m
++CONFIG_CRYPTO_SHA1=y
++CONFIG_CRYPTO_SHA256=m
++CONFIG_CRYPTO_SHA512=m
++# CONFIG_CRYPTO_TGR192 is not set
++CONFIG_CRYPTO_WP512=m
++
++#
++# Ciphers
++#
++CONFIG_CRYPTO_AES=m
++# CONFIG_CRYPTO_ANUBIS is not set
++CONFIG_CRYPTO_ARC4=m
++CONFIG_CRYPTO_BLOWFISH=m
++# CONFIG_CRYPTO_CAMELLIA is not set
++CONFIG_CRYPTO_CAST5=m
++CONFIG_CRYPTO_CAST6=m
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++CONFIG_CRYPTO_KHAZAD=m
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_SEED is not set
++CONFIG_CRYPTO_SERPENT=m
++CONFIG_CRYPTO_TEA=m
++CONFIG_CRYPTO_TWOFISH=m
++CONFIG_CRYPTO_TWOFISH_COMMON=m
++
++#
++# Compression
++#
++CONFIG_CRYPTO_DEFLATE=m
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
++# CONFIG_VIRTUALIZATION is not set

commit 46388c0d88add1c39926cd415039fe931edd5829
+Author: Remi Machet 
+Date:   Sat May 17 05:31:04 2008 +1000
+
+    powerpc: C2K board driver
+    
+    Support for the C2K cPCI Single Board Computer from GEFanuc
+    (PowerPC MPC7448 with a Marvell MV64460 chipset).
+    All features of the board are not supported yet, but the board
+    boots, flash works, all Ethernet ports are working and PCI
+    devices are all found (USB and SATA on PCI1 do not work yet).
+    
+    Part 3 of 5: driver for the board.  At this time it is very generic
+    and similar to its original, the driver for the prpmc2800.
+    
+    Signed-off-by: Remi Machet 
+    Signed-off-by: Paul Mackerras 
+
+diff --git a/arch/powerpc/platforms/embedded6xx/Makefile b/arch/powerpc/platforms/embedded6xx/Makefile
+index 06524d3ffd2e..0773c08bd444 100644
+--- a/arch/powerpc/platforms/embedded6xx/Makefile
++++ b/arch/powerpc/platforms/embedded6xx/Makefile
+@@ -6,3 +6,4 @@ obj-$(CONFIG_LINKSTATION)	+= linkstation.o ls_uart.o
+ obj-$(CONFIG_STORCENTER)	+= storcenter.o
+ obj-$(CONFIG_PPC_HOLLY)		+= holly.o
+ obj-$(CONFIG_PPC_PRPMC2800)	+= prpmc2800.o
++obj-$(CONFIG_PPC_C2K)		+= c2k.o
+diff --git a/arch/powerpc/platforms/embedded6xx/c2k.c b/arch/powerpc/platforms/embedded6xx/c2k.c
+new file mode 100644
+index 000000000000..d0b25b8c39d1
+--- /dev/null
++++ b/arch/powerpc/platforms/embedded6xx/c2k.c
+@@ -0,0 +1,158 @@
++/*
++ * Board setup routines for the GEFanuc C2K board
++ *
++ * Author: Remi Machet 
++ *
++ * Originated from prpmc2800.c
++ *
++ * 2008 (c) Stanford University
++ * 2007 (c) MontaVista, Software, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation.
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++#include 
++#include 
++#include 
++
++#include 
++
++#include 
++
++#define MV64x60_MPP_CNTL_0	0x0000
++#define MV64x60_MPP_CNTL_2	0x0008
++
++#define MV64x60_GPP_IO_CNTL	0x0000
++#define MV64x60_GPP_LEVEL_CNTL	0x0010
++#define MV64x60_GPP_VALUE_SET	0x0018
++
++static void __iomem *mv64x60_mpp_reg_base;
++static void __iomem *mv64x60_gpp_reg_base;
++
++static void __init c2k_setup_arch(void)
++{
++	struct device_node *np;
++	phys_addr_t paddr;
++	const unsigned int *reg;
++
++	/*
++	 * ioremap mpp and gpp registers in case they are later
++	 * needed by c2k_reset_board().
++	 */
++	np = of_find_compatible_node(NULL, NULL, "marvell,mv64360-mpp");
++	reg = of_get_property(np, "reg", NULL);
++	paddr = of_translate_address(np, reg);
++	of_node_put(np);
++	mv64x60_mpp_reg_base = ioremap(paddr, reg[1]);
++
++	np = of_find_compatible_node(NULL, NULL, "marvell,mv64360-gpp");
++	reg = of_get_property(np, "reg", NULL);
++	paddr = of_translate_address(np, reg);
++	of_node_put(np);
++	mv64x60_gpp_reg_base = ioremap(paddr, reg[1]);
++
++#ifdef CONFIG_PCI
++	mv64x60_pci_init();
++#endif
++}
++
++static void c2k_reset_board(void)
++{
++	u32 temp;
++
++	local_irq_disable();
++
++	temp = in_le32(mv64x60_mpp_reg_base + MV64x60_MPP_CNTL_0);
++	temp &= 0xFFFF0FFF;
++	out_le32(mv64x60_mpp_reg_base + MV64x60_MPP_CNTL_0, temp);
++
++	temp = in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_LEVEL_CNTL);
++	temp |= 0x00000004;
++	out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_LEVEL_CNTL, temp);
++
++	temp = in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_IO_CNTL);
++	temp |= 0x00000004;
++	out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_IO_CNTL, temp);
++
++	temp = in_le32(mv64x60_mpp_reg_base + MV64x60_MPP_CNTL_2);
++	temp &= 0xFFFF0FFF;
++	out_le32(mv64x60_mpp_reg_base + MV64x60_MPP_CNTL_2, temp);
++
++	temp = in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_LEVEL_CNTL);
++	temp |= 0x00080000;
++	out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_LEVEL_CNTL, temp);
++
++	temp = in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_IO_CNTL);
++	temp |= 0x00080000;
++	out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_IO_CNTL, temp);
++
++	out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_VALUE_SET, 0x00080004);
++}
++
++static void c2k_restart(char *cmd)
++{
++	c2k_reset_board();
++	msleep(100);
++	panic("restart failed\n");
++}
++
++#ifdef CONFIG_NOT_COHERENT_CACHE
++#define COHERENCY_SETTING "off"
++#else
++#define COHERENCY_SETTING "on"
++#endif
++
++void c2k_show_cpuinfo(struct seq_file *m)
++{
++	uint memsize = total_memory;
++
++	seq_printf(m, "Vendor\t\t: GEFanuc\n");
++	seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
++	seq_printf(m, "coherency\t: %s\n", COHERENCY_SETTING);
++}
++
++/*
++ * Called very early, device-tree isn't unflattened
++ */
++static int __init c2k_probe(void)
++{
++	unsigned long root = of_get_flat_dt_root();
++
++	if (!of_flat_dt_is_compatible(root, "GEFanuc,C2K"))
++		return 0;
++
++	printk(KERN_INFO "Detected a GEFanuc C2K board\n");
++
++	_set_L2CR(0);
++	_set_L2CR(L2CR_L2E | L2CR_L2PE | L2CR_L2I);
++	return 1;
++}
++
++define_machine(c2k) {
++	.name			= "C2K",
++	.probe			= c2k_probe,
++	.setup_arch		= c2k_setup_arch,
++	.init_early		= mv64x60_init_early,
++	.show_cpuinfo		= c2k_show_cpuinfo,
++	.init_IRQ		= mv64x60_init_irq,
++	.get_irq		= mv64x60_get_irq,
++	.restart		= c2k_restart,
++	.calibrate_decr		= generic_calibrate_decr,
++#ifdef CONFIG_KEXEC
++	.machine_kexec		= default_machine_kexec,
++	.machine_kexec_prepare	= default_machine_kexec_prepare,
++	.machine_crash_shutdown	= default_machine_crash_shutdown,
++#endif
++};

commit c6ec08e03dd06b8dfa3f6d938b0a89c6ed8475c9
+Author: Remi Machet 
+Date:   Wed May 21 06:50:10 2008 +1000
+
+    powerpc: Boot code for the C2K
+    
+    Support for the C2K cPCI Single Board Computer from GEFanuc
+    (PowerPC MPC7448 with a Marvell MV64460 chipset).
+    All features of the board are not supported yet, but the board
+    boots, flash works, all Ethernet ports are working and PCI
+    devices are all found (USB and SATA on PCI1 do not work yet).
+    
+    Part 2 of 5: support for the board in arch/powerpc/boot.
+    
+    Signed-off-by: Remi Machet 
+    Signed-off-by: Paul Mackerras 
+
+diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
+index c3585bed1970..e02fe3603e3e 100644
+--- a/arch/powerpc/boot/Makefile
++++ b/arch/powerpc/boot/Makefile
+@@ -63,7 +63,7 @@ src-plat := of.c cuboot-52xx.c cuboot-824x.c cuboot-83xx.c cuboot-85xx.c holly.c
+ 		ps3-head.S ps3-hvcall.S ps3.c treeboot-bamboo.c cuboot-8xx.c \
+ 		cuboot-pq2.c cuboot-sequoia.c treeboot-walnut.c \
+ 		cuboot-bamboo.c cuboot-mpc7448hpc2.c cuboot-taishan.c \
+-		fixed-head.S ep88xc.c ep405.c \
++		fixed-head.S ep88xc.c ep405.c cuboot-c2k.c \
+ 		cuboot-katmai.c cuboot-rainier.c redboot-8xx.c ep8248e.c \
+ 		cuboot-warp.c cuboot-85xx-cpm2.c cuboot-yosemite.c simpleboot.c \
+ 		virtex405-head.S redboot-83xx.c
+@@ -264,6 +264,7 @@ image-$(CONFIG_KSI8560)			+= cuImage.ksi8560
+ # Board ports in arch/powerpc/platform/embedded6xx/Kconfig
+ image-$(CONFIG_STORCENTER)		+= cuImage.storcenter
+ image-$(CONFIG_MPC7448HPC2)		+= cuImage.mpc7448hpc2
++image-$(CONFIG_PPC_C2K)			+= cuImage.c2k
+ 
+ # For 32-bit powermacs, build the COFF and miboot images
+ # as well as the ELF images.
+diff --git a/arch/powerpc/boot/cuboot-c2k.c b/arch/powerpc/boot/cuboot-c2k.c
+new file mode 100644
+index 000000000000..e43594950ba3
+--- /dev/null
++++ b/arch/powerpc/boot/cuboot-c2k.c
+@@ -0,0 +1,190 @@
++/*
++ * GEFanuc C2K platform code.
++ *
++ * Author: Remi Machet 
++ *
++ * Originated from prpmc2800.c
++ *
++ * 2008 (c) Stanford University
++ * 2007 (c) MontaVista, Software, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation.
++ */
++
++#include "types.h"
++#include "stdio.h"
++#include "io.h"
++#include "ops.h"
++#include "elf.h"
++#include "gunzip_util.h"
++#include "mv64x60.h"
++#include "cuboot.h"
++#include "ppcboot.h"
++
++static u8 *bridge_base;
++
++static void c2k_bridge_setup(u32 mem_size)
++{
++	u32 i, v[30], enables, acc_bits;
++	u32 pci_base_hi, pci_base_lo, size, buf[2];
++	unsigned long cpu_base;
++	int rc;
++	void *devp, *mv64x60_devp;
++	u8 *bridge_pbase, is_coherent;
++	struct mv64x60_cpu2pci_win *tbl;
++	int bus;
++
++	bridge_pbase = mv64x60_get_bridge_pbase();
++	is_coherent = mv64x60_is_coherent();
++
++	if (is_coherent)
++		acc_bits = MV64x60_PCI_ACC_CNTL_SNOOP_WB
++			| MV64x60_PCI_ACC_CNTL_SWAP_NONE
++			| MV64x60_PCI_ACC_CNTL_MBURST_32_BYTES
++			| MV64x60_PCI_ACC_CNTL_RDSIZE_32_BYTES;
++	else
++		acc_bits = MV64x60_PCI_ACC_CNTL_SNOOP_NONE
++			| MV64x60_PCI_ACC_CNTL_SWAP_NONE
++			| MV64x60_PCI_ACC_CNTL_MBURST_128_BYTES
++			| MV64x60_PCI_ACC_CNTL_RDSIZE_256_BYTES;
++
++	mv64x60_config_ctlr_windows(bridge_base, bridge_pbase, is_coherent);
++	mv64x60_devp = find_node_by_compatible(NULL, "marvell,mv64360");
++	if (mv64x60_devp == NULL)
++		fatal("Error: Missing marvell,mv64360 device tree node\n\r");
++
++	enables = in_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE));
++	enables |= 0x007ffe00; /* Disable all cpu->pci windows */
++	out_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE), enables);
++
++	/* Get the cpu -> pci i/o & mem mappings from the device tree */
++	devp = NULL;
++	for (bus = 0; ; bus++) {
++		char name[] = "pci ";
++
++		name[strlen(name)-1] = bus+'0';
++
++		devp = find_node_by_alias(name);
++		if (devp == NULL)
++			break;
++
++		if (bus >= 2)
++			fatal("Error: Only 2 PCI controllers are supported at" \
++				" this time.\n");
++
++		mv64x60_config_pci_windows(bridge_base, bridge_pbase, bus, 0,
++				mem_size, acc_bits);
++
++		rc = getprop(devp, "ranges", v, sizeof(v));
++		if (rc == 0)
++			fatal("Error: Can't find marvell,mv64360-pci ranges"
++				" property\n\r");
++
++		/* Get the cpu -> pci i/o & mem mappings from the device tree */
++
++		for (i = 0; i < rc; i += 6) {
++			switch (v[i] & 0xff000000) {
++			case 0x01000000: /* PCI I/O Space */
++				tbl = mv64x60_cpu2pci_io;
++				break;
++			case 0x02000000: /* PCI MEM Space */
++				tbl = mv64x60_cpu2pci_mem;
++				break;
++			default:
++				continue;
++			}
++
++			pci_base_hi = v[i+1];
++			pci_base_lo = v[i+2];
++			cpu_base = v[i+3];
++			size = v[i+5];
++
++			buf[0] = cpu_base;
++			buf[1] = size;
++
++			if (!dt_xlate_addr(devp, buf, sizeof(buf), &cpu_base))
++				fatal("Error: Can't translate PCI address " \
++						"0x%x\n\r", (u32)cpu_base);
++
++			mv64x60_config_cpu2pci_window(bridge_base, bus,
++				pci_base_hi, pci_base_lo, cpu_base, size, tbl);
++		}
++
++		enables &= ~(3<<(9+bus*5)); /* Enable cpu->pci i/o,
++						cpu->pci mem0 */
++		out_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE),
++			enables);
++	};
++}
++
++static void c2k_fixups(void)
++{
++	u32 mem_size;
++
++	mem_size = mv64x60_get_mem_size(bridge_base);
++	c2k_bridge_setup(mem_size); /* Do necessary bridge setup */
++}
++
++#define MV64x60_MPP_CNTL_0	0xf000
++#define MV64x60_MPP_CNTL_2	0xf008
++#define MV64x60_GPP_IO_CNTL	0xf100
++#define MV64x60_GPP_LEVEL_CNTL	0xf110
++#define MV64x60_GPP_VALUE_SET	0xf118
++
++static void c2k_reset(void)
++{
++	u32 temp;
++
++	udelay(5000000);
++
++	if (bridge_base != 0) {
++		temp = in_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_0));
++		temp &= 0xFFFF0FFF;
++		out_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_0), temp);
++
++		temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL));
++		temp |= 0x00000004;
++		out_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL), temp);
++
++		temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL));
++		temp |= 0x00000004;
++		out_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL), temp);
++
++		temp = in_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_2));
++		temp &= 0xFFFF0FFF;
++		out_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_2), temp);
++
++		temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL));
++		temp |= 0x00080000;
++		out_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL), temp);
++
++		temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL));
++		temp |= 0x00080000;
++		out_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL), temp);
++
++		out_le32((u32 *)(bridge_base + MV64x60_GPP_VALUE_SET),
++				0x00080004);
++	}
++
++	for (;;);
++}
++
++static bd_t bd;
++
++void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
++			unsigned long r6, unsigned long r7)
++{
++	CUBOOT_INIT();
++
++	fdt_init(_dtb_start);
++
++	bridge_base = mv64x60_get_bridge_base();
++
++	platform_ops.fixups = c2k_fixups;
++	platform_ops.exit = c2k_reset;
++
++	if (serial_console_init() < 0)
++		exit();
++}

commit 61586476cda599c64ab2b8f4f808d6a615a2fab2
+Author: Remi Machet 
+Date:   Wed May 21 03:30:24 2008 +1000
+
+    powerpc: DTS file for the C2K
+    
+    Support for the C2K cPCI Single Board Computer from GEFanuc
+    (PowerPC MPC7448 with a Marvell MV64460 chipset).
+    All features of the board are not supported yet, but the board
+    boots, flash works, all Ethernet ports are working and PCI
+    devices are all found (USB and SATA on PCI1 do not work yet).
+    
+    Part 1 of 5: DTS file describing the board peripherals.  As far as I
+    know all peripherals except the FPGA are listed in there (I did not
+    include the FPGA because a lot of work is needed there).
+    
+    Signed-off-by: Remi Machet 
+    Signed-off-by: Paul Mackerras 
+
+diff --git a/arch/powerpc/boot/dts/c2k.dts b/arch/powerpc/boot/dts/c2k.dts
+new file mode 100644
+index 000000000000..f5d625fa3e52
+--- /dev/null
++++ b/arch/powerpc/boot/dts/c2k.dts
+@@ -0,0 +1,371 @@
++/* Device Tree Source for GEFanuc C2K
++ *
++ * Author: Remi Machet 
++ *
++ * Originated from prpmc2800.dts
++ *
++ * 2008 (c) Stanford University
++ * 2007 (c) MontaVista, Software, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation.
++ */
++
++/dts-v1/;
++
++/ {
++	#address-cells = <1>;
++	#size-cells = <1>;
++	model = "C2K";
++	compatible = "GEFanuc,C2K";
++	coherency-off;
++
++	aliases {
++		pci0 = &PCI0;
++		pci1 = &PCI1;
++	};
++
++	cpus {
++		#address-cells = <1>;
++		#size-cells = <0>;
++
++		cpu@0 {
++			device_type = "cpu";
++			compatible = "PowerPC,7447";
++			reg = <0>;
++			clock-frequency = <996000000>;	/* 996 MHz */
++			bus-frequency = <166666667>;	/* 166.6666 MHz */
++			timebase-frequency = <41666667>;	/* 166.6666/4 MHz */
++			i-cache-line-size = <32>;
++			d-cache-line-size = <32>;
++			i-cache-size = <32768>;
++			d-cache-size = <32768>;
++		};
++	};
++
++	memory {
++		device_type = "memory";
++		reg = <0x00000000 0x40000000>;	/* 1GB */
++	};
++
++	system-controller@d8000000 { /* Marvell Discovery */
++		#address-cells = <1>;
++		#size-cells = <1>;
++		model = "mv64460";
++		compatible = "marvell,mv64360";
++		clock-frequency = <166666667>;		/* 166.66... MHz */
++		reg = <0xd8000000 0x00010000>;
++		virtual-reg = <0xd8000000>;
++		ranges = <0xd4000000 0xd4000000 0x01000000	/* PCI 0 I/O Space */
++			  0x80000000 0x80000000 0x08000000	/* PCI 0 MEM Space */
++			  0xd0000000 0xd0000000 0x01000000	/* PCI 1 I/O Space */
++			  0xa0000000 0xa0000000 0x08000000	/* PCI 1 MEM Space */
++			  0xd8100000 0xd8100000 0x00010000	/* FPGA */
++			  0xd8110000 0xd8110000 0x00010000	/* FPGA USARTs */
++			  0xf8000000 0xf8000000 0x08000000	/* User FLASH */
++			  0x00000000 0xd8000000 0x00010000	/* Bridge's regs */
++			  0xd8140000 0xd8140000 0x00040000>;	/* Integrated SRAM */
++
++		mdio@2000 {
++			#address-cells = <1>;
++			#size-cells = <0>;
++			compatible = "marvell,mv64360-mdio";
++			reg = <0x2000 4>;
++			PHY0: ethernet-phy@0 {
++				device_type = "ethernet-phy";
++				interrupts = <76>;	/* GPP 12 */
++				interrupt-parent = <&PIC>;
++				reg = <0>;
++			};
++			PHY1: ethernet-phy@1 {
++				device_type = "ethernet-phy";
++				interrupts = <76>;	/* GPP 12 */
++				interrupt-parent = <&PIC>;
++				reg = <1>;
++			};
++			PHY2: ethernet-phy@2 {
++				device_type = "ethernet-phy";
++				interrupts = <76>;	/* GPP 12 */
++				interrupt-parent = <&PIC>;
++				reg = <2>;
++			};
++		};
++
++		ethernet-group@2000 {
++			#address-cells = <1>;
++			#size-cells = <0>;
++			compatible = "marvell,mv64360-eth-group";
++			reg = <0x2000 0x2000>;
++			ethernet@0 {
++				device_type = "network";
++				compatible = "marvell,mv64360-eth";
++				reg = <0>;
++				interrupts = <32>;
++				interrupt-parent = <&PIC>;
++				phy = <&PHY0>;
++				local-mac-address = [ 00 00 00 00 00 00 ];
++			};
++			ethernet@1 {
++				device_type = "network";
++				compatible = "marvell,mv64360-eth";
++				reg = <1>;
++				interrupts = <33>;
++				interrupt-parent = <&PIC>;
++				phy = <&PHY1>;
++				local-mac-address = [ 00 00 00 00 00 00 ];
++			};
++			ethernet@2 {
++				device_type = "network";
++				compatible = "marvell,mv64360-eth";
++				reg = <2>;
++				interrupts = <34>;
++				interrupt-parent = <&PIC>;
++				phy = <&PHY2>;
++				local-mac-address = [ 00 00 00 00 00 00 ];
++			};
++		};
++
++		SDMA0: sdma@4000 {
++			compatible = "marvell,mv64360-sdma";
++			reg = <0x4000 0xc18>;
++			virtual-reg = <0xd8004000>;
++			interrupt-base = <0>;
++			interrupts = <36>;
++			interrupt-parent = <&PIC>;
++		};
++
++		SDMA1: sdma@6000 {
++			compatible = "marvell,mv64360-sdma";
++			reg = <0x6000 0xc18>;
++			virtual-reg = <0xd8006000>;
++			interrupt-base = <0>;
++			interrupts = <38>;
++			interrupt-parent = <&PIC>;
++		};
++
++		BRG0: brg@b200 {
++			compatible = "marvell,mv64360-brg";
++			reg = <0xb200 0x8>;
++			clock-src = <8>;
++			clock-frequency = <133333333>;
++			current-speed = <115200>;
++		};
++
++		BRG1: brg@b208 {
++			compatible = "marvell,mv64360-brg";
++			reg = <0xb208 0x8>;
++			clock-src = <8>;
++			clock-frequency = <133333333>;
++			current-speed = <115200>;
++		};
++
++		CUNIT: cunit@f200 {
++			reg = <0xf200 0x200>;
++		};
++
++		MPSCROUTING: mpscrouting@b400 {
++			reg = <0xb400 0xc>;
++		};
++
++		MPSCINTR: mpscintr@b800 {
++			reg = <0xb800 0x100>;
++			virtual-reg = <0xd800b800>;
++		};
++
++		MPSC0: mpsc@8000 {
++			device_type = "serial";
++			compatible = "marvell,mv64360-mpsc";
++			reg = <0x8000 0x38>;
++			virtual-reg = <0xd8008000>;
++			sdma = <&SDMA0>;
++			brg = <&BRG0>;
++			cunit = <&CUNIT>;
++			mpscrouting = <&MPSCROUTING>;
++			mpscintr = <&MPSCINTR>;
++			cell-index = <0>;
++			interrupts = <40>;
++			interrupt-parent = <&PIC>;
++		};
++
++		MPSC1: mpsc@9000 {
++			device_type = "serial";
++			compatible = "marvell,mv64360-mpsc";
++			reg = <0x9000 0x38>;
++			virtual-reg = <0xd8009000>;
++			sdma = <&SDMA1>;
++			brg = <&BRG1>;
++			cunit = <&CUNIT>;
++			mpscrouting = <&MPSCROUTING>;
++			mpscintr = <&MPSCINTR>;
++			cell-index = <1>;
++			interrupts = <42>;
++			interrupt-parent = <&PIC>;
++		};
++
++		wdt@b410 {			/* watchdog timer */
++			compatible = "marvell,mv64360-wdt";
++			reg = <0xb410 0x8>;
++		};
++
++		i2c@c000 {
++			compatible = "marvell,mv64360-i2c";
++			reg = <0xc000 0x20>;
++			virtual-reg = <0xd800c000>;
++			interrupts = <37>;
++			interrupt-parent = <&PIC>;
++		};
++
++		PIC: pic {
++			#interrupt-cells = <1>;
++			#address-cells = <0>;
++			compatible = "marvell,mv64360-pic";
++			reg = <0x0000 0x88>;
++			interrupt-controller;
++		};
++
++		mpp@f000 {
++			compatible = "marvell,mv64360-mpp";
++			reg = <0xf000 0x10>;
++		};
++
++		gpp@f100 {
++			compatible = "marvell,mv64360-gpp";
++			reg = <0xf100 0x20>;
++		};
++
++		PCI0: pci@80000000 {
++			#address-cells = <3>;
++			#size-cells = <2>;
++			#interrupt-cells = <1>;
++			device_type = "pci";
++			compatible = "marvell,mv64360-pci";
++			reg = <0x0cf8 0x8>;
++			ranges = <0x01000000 0x0 0x00000000 0xd4000000 0x0 0x01000000
++				  0x02000000 0x0 0x80000000 0x80000000 0x0 0x08000000>;
++			bus-range = <0 255>;
++			clock-frequency = <66000000>;
++			interrupt-pci-iack = <0x0c34>;
++			interrupt-parent = <&PIC>;
++			interrupt-map-mask = <0x0000 0x0 0x0 0x7>;
++			interrupt-map = <
++				/* Only one interrupt line for PMC0 slot (INTA) */
++				0x0000 0 0 1 &PIC 88
++			>;
++		};
++
++
++		PCI1: pci@a0000000 {
++			#address-cells = <3>;
++			#size-cells = <2>;
++			#interrupt-cells = <1>;
++			device_type = "pci";
++			compatible = "marvell,mv64360-pci";
++			reg = <0x0c78 0x8>;
++			ranges = <0x01000000 0x0 0x00000000 0xd0000000 0x0 0x01000000
++				  0x02000000 0x0 0x80000000 0xa0000000 0x0 0x08000000>;
++			bus-range = <0 255>;
++			clock-frequency = <66000000>;
++			interrupt-pci-iack = <0x0cb4>;
++			interrupt-parent = <&PIC>;
++			interrupt-map-mask = <0xf800 0x00 0x00 0x7>;
++			interrupt-map = <
++				/* IDSEL 0x01: PMC1 ? */
++				0x0800 0 0 1 &PIC 88
++				/* IDSEL 0x02: cPCI bridge */
++				0x1000 0 0 1 &PIC 88
++				/* IDSEL 0x03: USB controller */
++				0x1800 0 0 1 &PIC 91
++				/* IDSEL 0x04: SATA controller */
++				0x2000 0 0 1 &PIC 95
++			>;
++		};
++
++		cpu-error@0070 {
++			compatible = "marvell,mv64360-cpu-error";
++			reg = <0x0070 0x10 0x0128 0x28>;
++			interrupts = <3>;
++			interrupt-parent = <&PIC>;
++		};
++
++		sram-ctrl@0380 {
++			compatible = "marvell,mv64360-sram-ctrl";
++			reg = <0x0380 0x80>;
++			interrupts = <13>;
++			interrupt-parent = <&PIC>;
++		};
++
++		pci-error@1d40 {
++			compatible = "marvell,mv64360-pci-error";
++			reg = <0x1d40 0x40 0x0c28 0x4>;
++			interrupts = <12>;
++			interrupt-parent = <&PIC>;
++		};
++
++		pci-error@1dc0 {
++			compatible = "marvell,mv64360-pci-error";
++			reg = <0x1dc0 0x40 0x0ca8 0x4>;
++			interrupts = <16>;
++			interrupt-parent = <&PIC>;
++		};
++
++		mem-ctrl@1400 {
++			compatible = "marvell,mv64360-mem-ctrl";
++			reg = <0x1400 0x60>;
++			interrupts = <17>;
++			interrupt-parent = <&PIC>;
++		};
++		/* Devices attached to the device controller */
++		devicebus@045c {
++			#address-cells = <2>;
++			#size-cells = <1>;
++			compatible = "marvell,mv64306-devctrl";
++			reg = <0x45C 0x88>;
++			interrupts = <1>;
++			interrupt-parent = <&PIC>;
++			ranges = 	<0 0 0xd8100000 0x10000
++					 2 0 0xd8110000 0x10000
++					 4 0 0xf8000000 0x8000000>;
++			fpga@0,0 {
++				compatible = "sbs,fpga-c2k";
++				reg = <0 0 0x10000>;
++			};
++			fpga_usart@2,0 {
++				compatible = "sbs,fpga_usart-c2k";
++				reg = <2 0 0x10000>;
++			};
++			nor_flash@4,0 {
++				compatible = "cfi-flash";
++				reg = <4 0 0x8000000>; /* 128MB */
++				bank-width = <4>;
++				device-width = <1>;
++				#address-cells = <1>;
++				#size-cells = <1>;
++				partition@0 {
++					label = "boot";
++					reg = <0x00000000 0x00080000>;
++				};
++				partition@40000 {
++					label = "kernel";
++					reg = <0x00080000 0x00400000>;
++				};
++				partition@440000 {
++					label = "initrd";
++					reg = <0x00480000 0x00B80000>;
++				};
++				partition@1000000 {
++					label = "rootfs";
++					reg = <0x01000000 0x06800000>;
++				};
++				partition@7800000 {
++					label = "recovery";
++					reg = <0x07800000 0x00800000>;
++					read-only;
++				};
++			};
++		};
++	};
++	chosen {
++		linux,stdout-path = &MPSC0;
++	};
++};

commit 683307da07afd3a7ee55269ee8cb70c8053b0923
+Author: Remi Machet 
+Date:   Thu May 1 10:40:44 2008 +1000
+
+    [POWERPC] Create of_buses for MV64x60 devices
+    
+    For each mv64360 entry in the OpenFirmware database, add the
+    registration of an of_bus to take care of devices connected to
+    the MV64x60 asynchronous devices controller.
+    This change makes it possible for those devices to be detected by
+    drivers that support the of_platform without having a custom call
+    for each of them in the board file.
+    
+    Signed-off-by: Remi Machet 
+    Signed-off-by: Paul Mackerras 
+
+diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c
+index a132e0de8ca5..32e0ad0ebea8 100644
+--- a/arch/powerpc/sysdev/mv64x60_dev.c
++++ b/arch/powerpc/sysdev/mv64x60_dev.c
+@@ -15,6 +15,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ 
+@@ -25,6 +26,11 @@
+  * PowerPC of_platform_bus_type.  They support platform_bus_type instead.
+  */
+ 
++static struct of_device_id __initdata of_mv64x60_devices[] = {
++	{ .compatible = "marvell,mv64306-devctrl", },
++	{}
++};
++
+ /*
+  * Create MPSC platform devices
+  */
+@@ -484,6 +490,10 @@ static int __init mv64x60_device_setup(void)
+ 		of_node_put(np);
+ 	}
+ 
++	/* Now add every node that is on the device bus */
++	for_each_compatible_node(np, NULL, "marvell,mv64360")
++		of_platform_bus_probe(np, of_mv64x60_devices, NULL);
++
+ 	return 0;
+ }
+ arch_initcall(mv64x60_device_setup);

commit df40a57ef16219e5dee75238559960b1dd459c65
+Author: Remi Machet 
+Date:   Tue Apr 22 07:02:56 2008 +1000
+
+    [POWERPC] Fix mv64x60 early console code to use cell-index property
+    
+    The MPSC driver and prpmc2800.dts have been modified to use property
+    'cell-index' as the serial port number, but the early serial console
+    driver for the mv64x60 has not been modified to use this new property.
+    This fixes it.
+    
+    Signed-off-by: Remi Machet (rmachet@slac.stanford.edu)
+    Acked-by: Dale Farnsworth 
+    Signed-off-by: Paul Mackerras 
+
+diff --git a/arch/powerpc/sysdev/mv64x60_udbg.c b/arch/powerpc/sysdev/mv64x60_udbg.c
+index ccdb3b0418fc..2792dc8b038c 100644
+--- a/arch/powerpc/sysdev/mv64x60_udbg.c
++++ b/arch/powerpc/sysdev/mv64x60_udbg.c
+@@ -94,7 +94,7 @@ static void mv64x60_udbg_init(void)
+ 	if (!np)
+ 		return;
+ 
+-	block_index = of_get_property(np, "block-index", NULL);
++	block_index = of_get_property(np, "cell-index", NULL);
+ 	if (!block_index)
+ 		goto error;
+ 

commit ff114b669b45480688198f28d6aad1a61223335d
+Author: Remi Machet 
+Date:   Tue Apr 22 04:46:12 2008 +1000
+
+    [POWERPC] Initialize all mv64x60 devices even if one fails
+    
+    If one of the devices of the mv64x60 init fails, the remaining
+    devices are not initialized.
+    
+    This changes the code to display an error and continue the
+    initialization.
+    
+    Signed-off-by: Remi Machet (rmachet@slac.stanford.edu)
+    Signed-off-by: Paul Mackerras 
+
+diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c
+index c8d9257f431b..41af1223e2a0 100644
+--- a/arch/powerpc/sysdev/mv64x60_dev.c
++++ b/arch/powerpc/sysdev/mv64x60_dev.c
+@@ -431,9 +431,13 @@ static int __init mv64x60_device_setup(void)
+ 	int err;
+ 
+ 	id = 0;
+-	for_each_compatible_node(np, "serial", "marvell,mv64360-mpsc")
+-		if ((err = mv64x60_mpsc_device_setup(np, id++)))
+-			goto error;
++	for_each_compatible_node(np, "serial", "marvell,mv64360-mpsc") {
++		err = mv64x60_mpsc_device_setup(np, id++);
++		if (err)
++			printk(KERN_ERR "Failed to initialize MV64x60 "
++					"serial device %s: error %d.\n",
++					np->full_name, err);
++	}
+ 
+ 	id = 0;
+ 	id2 = 0;
+@@ -441,38 +445,44 @@ static int __init mv64x60_device_setup(void)
+ 		pdev = mv64x60_eth_register_shared_pdev(np, id++);
+ 		if (IS_ERR(pdev)) {
+ 			err = PTR_ERR(pdev);
+-			goto error;
++			printk(KERN_ERR "Failed to initialize MV64x60 "
++					"network block %s: error %d.\n",
++					np->full_name, err);
++			continue;
+ 		}
+ 		for_each_child_of_node(np, np2) {
+ 			if (!of_device_is_compatible(np2,
+ 					"marvell,mv64360-eth"))
+ 				continue;
+ 			err = mv64x60_eth_device_setup(np2, id2++, pdev);
+-			if (err) {
+-				of_node_put(np2);
+-				goto error;
+-			}
++			if (err)
++				printk(KERN_ERR "Failed to initialize "
++						"MV64x60 network device %s: "
++						"error %d.\n",
++						np2->full_name, err);
+ 		}
+ 	}
+ 
+ 	id = 0;
+-	for_each_compatible_node(np, "i2c", "marvell,mv64360-i2c")
+-		if ((err = mv64x60_i2c_device_setup(np, id++)))
+-			goto error;
++	for_each_compatible_node(np, "i2c", "marvell,mv64360-i2c") {
++		err = mv64x60_i2c_device_setup(np, id++);
++		if (err)
++			printk(KERN_ERR "Failed to initialize MV64x60 I2C "
++					"bus %s: error %d.\n",
++					np->full_name, err);
++	}
+ 
+ 	/* support up to one watchdog timer */
+ 	np = of_find_compatible_node(np, NULL, "marvell,mv64360-wdt");
+ 	if (np) {
+ 		if ((err = mv64x60_wdt_device_setup(np, id)))
+-			goto error;
++			printk(KERN_ERR "Failed to initialize MV64x60 "
++					"Watchdog %s: error %d.\n",
++					np->full_name, err);
+ 		of_node_put(np);
+ 	}
+ 
+ 	return 0;
+-
+-error:
+-	of_node_put(np);
+-	return err;
+ }
+ arch_initcall(mv64x60_device_setup);
+ 

commit 21dbfd291fe704986fab63a129f89ed2de471329
+Author: Remi Machet 
+Date:   Tue Apr 22 03:36:48 2008 +1000
+
+    [POWERPC] Use default values if necessary in mv64x60 I2C initialization
+    
+    I2C parameters freq_m and freq_n are assigned defaults in the code,
+    but if properties for those parameters are not found in the open
+    firmware description the init routine returns an error and doesn't
+    create the platform device.
+    
+    This changes the code so that it doesn't return an error if the
+    properties are not found but instead uses the default values.
+    
+    Signed-off-by: Remi Machet (rmachet@slac.stanford.edu)
+    Acked-by: Dale Farnsworth 
+    Signed-off-by: Paul Mackerras 
+
+diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c
+index 047b31027fa6..c8d9257f431b 100644
+--- a/arch/powerpc/sysdev/mv64x60_dev.c
++++ b/arch/powerpc/sysdev/mv64x60_dev.c
+@@ -338,15 +338,13 @@ static int __init mv64x60_i2c_device_setup(struct device_node *np, int id)
+ 
+ 	pdata.freq_m = 8;	/* default */
+ 	prop = of_get_property(np, "freq_m", NULL);
+-	if (!prop)
+-		return -ENODEV;
+-	pdata.freq_m = *prop;
++	if (prop)
++		pdata.freq_m = *prop;
+ 
+ 	pdata.freq_m = 3;	/* default */
+ 	prop = of_get_property(np, "freq_n", NULL);
+-	if (!prop)
+-		return -ENODEV;
+-	pdata.freq_n = *prop;
++	if (prop)
++		pdata.freq_n = *prop;
+ 
+ 	pdata.timeout = 1000;				/* default: 1 second */
+ 

\ No newline at end of file diff --git a/detail/45.html b/detail/45.html new file mode 100644 index 0000000..1a13bd2 --- /dev/null +++ b/detail/45.html @@ -0,0 +1,558 @@ +

Patches contributed by Australian National University


commit 9c0a50022b8ac7e863e6ec8342fa476fe5d1d75c
+Author: Li Dongyang 
+Date:   Tue Nov 14 10:48:04 2017 +1100
+
+    scsi: ses: don't ask for diagnostic pages repeatedly during probe
+    
+    We are testing if there is a match with the ses device in a loop by
+    calling ses_match_to_enclosure(), which will issue scsi receive
+    diagnostics commands to the ses device for every device on the same
+    host.  On one of our boxes with 840 disks, it takes a long time to load
+    the driver:
+    
+    [root@g1b-oss06 ~]# time modprobe ses
+    
+    real    40m48.247s
+    user    0m0.001s
+    sys     0m0.196s
+    
+    With the patch:
+    
+    [root@g1b-oss06 ~]# time modprobe ses
+    
+    real    0m17.915s
+    user    0m0.008s
+    sys     0m0.053s
+    
+    Note that we still need to refresh page 10 when we see a new disk to
+    create the link.
+    
+    Signed-off-by: Li Dongyang 
+    Tested-by: Jason Ozolins 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c
+index 11826c5c2dd4..62f04c0511cf 100644
+--- a/drivers/scsi/ses.c
++++ b/drivers/scsi/ses.c
+@@ -615,13 +615,16 @@ static void ses_enclosure_data_process(struct enclosure_device *edev,
+ }
+ 
+ static void ses_match_to_enclosure(struct enclosure_device *edev,
+-				   struct scsi_device *sdev)
++				   struct scsi_device *sdev,
++				   int refresh)
+ {
++	struct scsi_device *edev_sdev = to_scsi_device(edev->edev.parent);
+ 	struct efd efd = {
+ 		.addr = 0,
+ 	};
+ 
+-	ses_enclosure_data_process(edev, to_scsi_device(edev->edev.parent), 0);
++	if (refresh)
++		ses_enclosure_data_process(edev, edev_sdev, 0);
+ 
+ 	if (scsi_is_sas_rphy(sdev->sdev_target->dev.parent))
+ 		efd.addr = sas_get_address(sdev);
+@@ -652,7 +655,7 @@ static int ses_intf_add(struct device *cdev,
+ 		struct enclosure_device *prev = NULL;
+ 
+ 		while ((edev = enclosure_find(&sdev->host->shost_gendev, prev)) != NULL) {
+-			ses_match_to_enclosure(edev, sdev);
++			ses_match_to_enclosure(edev, sdev, 1);
+ 			prev = edev;
+ 		}
+ 		return -ENODEV;
+@@ -768,7 +771,7 @@ static int ses_intf_add(struct device *cdev,
+ 	shost_for_each_device(tmp_sdev, sdev->host) {
+ 		if (tmp_sdev->lun != 0 || scsi_device_enclosure(tmp_sdev))
+ 			continue;
+-		ses_match_to_enclosure(edev, tmp_sdev);
++		ses_match_to_enclosure(edev, tmp_sdev, 0);
+ 	}
+ 
+ 	return 0;

commit e9105cdefbf64cd7aea300f934c92051e7cb7cff
+Author: Li Dongyang 
+Date:   Wed Aug 16 23:31:23 2017 +1000
+
+    IB/mlx4: use kvmalloc_array to allocate wrid
+    
+    We could use kvmalloc_array instead of the
+    kmalloc and __vmalloc combination.
+    After this we don't need to include linux/vmalloc.h
+    
+    Signed-off-by: Li Dongyang 
+    Reviewed-by: Leon Romanovsky 
+    Signed-off-by: Doug Ledford 
+
+diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
+index e42acfb20588..b40d50c643e1 100644
+--- a/drivers/infiniband/hw/mlx4/qp.c
++++ b/drivers/infiniband/hw/mlx4/qp.c
+@@ -36,7 +36,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ 
+ #include 
+ #include 
+@@ -1174,16 +1173,10 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
+ 		if (err)
+ 			goto err_mtt;
+ 
+-		qp->sq.wrid = kmalloc_array(qp->sq.wqe_cnt, sizeof(u64),
+-					GFP_KERNEL | __GFP_NOWARN);
+-		if (!qp->sq.wrid)
+-			qp->sq.wrid = __vmalloc(qp->sq.wqe_cnt * sizeof(u64),
+-						GFP_KERNEL, PAGE_KERNEL);
+-		qp->rq.wrid = kmalloc_array(qp->rq.wqe_cnt, sizeof(u64),
+-					GFP_KERNEL | __GFP_NOWARN);
+-		if (!qp->rq.wrid)
+-			qp->rq.wrid = __vmalloc(qp->rq.wqe_cnt * sizeof(u64),
+-						GFP_KERNEL, PAGE_KERNEL);
++		qp->sq.wrid = kvmalloc_array(qp->sq.wqe_cnt,
++					     sizeof(u64), GFP_KERNEL);
++		qp->rq.wrid = kvmalloc_array(qp->rq.wqe_cnt,
++					     sizeof(u64), GFP_KERNEL);
+ 		if (!qp->sq.wrid || !qp->rq.wrid) {
+ 			err = -ENOMEM;
+ 			goto err_wrid;
+diff --git a/drivers/infiniband/hw/mlx4/srq.c b/drivers/infiniband/hw/mlx4/srq.c
+index 0facaf5f6d23..dd7a2fce9df4 100644
+--- a/drivers/infiniband/hw/mlx4/srq.c
++++ b/drivers/infiniband/hw/mlx4/srq.c
+@@ -34,7 +34,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ 
+ #include "mlx4_ib.h"
+ #include 
+@@ -171,15 +170,11 @@ struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
+ 		if (err)
+ 			goto err_mtt;
+ 
+-		srq->wrid = kmalloc_array(srq->msrq.max, sizeof(u64),
+-					GFP_KERNEL | __GFP_NOWARN);
++		srq->wrid = kvmalloc_array(srq->msrq.max,
++					   sizeof(u64), GFP_KERNEL);
+ 		if (!srq->wrid) {
+-			srq->wrid = __vmalloc(srq->msrq.max * sizeof(u64),
+-					      GFP_KERNEL, PAGE_KERNEL);
+-			if (!srq->wrid) {
+-				err = -ENOMEM;
+-				goto err_mtt;
+-			}
++			err = -ENOMEM;
++			goto err_mtt;
+ 		}
+ 	}
+ 

commit b588300801f3502a7de5ca897af68019fbb3bc79
+Author: Li Dongyang 
+Date:   Wed Aug 16 23:31:22 2017 +1000
+
+    IB/mlx5: use kvmalloc_array for mlx5_ib_wq
+    
+    We observed multiple times on our Lustre OSS servers that when
+    the system memory is fragmented, kmalloc() in create_kernel_qp()
+    could fail order 4/5 allocations while we still have many free pages.
+    
+    Switch to kvmalloc_array() to allow the operation to contine.
+    
+    Signed-off-by: Li Dongyang 
+    Acked-by: Leon Romanovsky 
+    Signed-off-by: Doug Ledford 
+
+diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
+index 5c7ce9bd466e..e098c97e027a 100644
+--- a/drivers/infiniband/hw/mlx5/qp.c
++++ b/drivers/infiniband/hw/mlx5/qp.c
+@@ -965,11 +965,16 @@ static int create_kernel_qp(struct mlx5_ib_dev *dev,
+ 		goto err_free;
+ 	}
+ 
+-	qp->sq.wrid = kmalloc(qp->sq.wqe_cnt * sizeof(*qp->sq.wrid), GFP_KERNEL);
+-	qp->sq.wr_data = kmalloc(qp->sq.wqe_cnt * sizeof(*qp->sq.wr_data), GFP_KERNEL);
+-	qp->rq.wrid = kmalloc(qp->rq.wqe_cnt * sizeof(*qp->rq.wrid), GFP_KERNEL);
+-	qp->sq.w_list = kmalloc(qp->sq.wqe_cnt * sizeof(*qp->sq.w_list), GFP_KERNEL);
+-	qp->sq.wqe_head = kmalloc(qp->sq.wqe_cnt * sizeof(*qp->sq.wqe_head), GFP_KERNEL);
++	qp->sq.wrid = kvmalloc_array(qp->sq.wqe_cnt,
++				     sizeof(*qp->sq.wrid), GFP_KERNEL);
++	qp->sq.wr_data = kvmalloc_array(qp->sq.wqe_cnt,
++					sizeof(*qp->sq.wr_data), GFP_KERNEL);
++	qp->rq.wrid = kvmalloc_array(qp->rq.wqe_cnt,
++				     sizeof(*qp->rq.wrid), GFP_KERNEL);
++	qp->sq.w_list = kvmalloc_array(qp->sq.wqe_cnt,
++				       sizeof(*qp->sq.w_list), GFP_KERNEL);
++	qp->sq.wqe_head = kvmalloc_array(qp->sq.wqe_cnt,
++					 sizeof(*qp->sq.wqe_head), GFP_KERNEL);
+ 
+ 	if (!qp->sq.wrid || !qp->sq.wr_data || !qp->rq.wrid ||
+ 	    !qp->sq.w_list || !qp->sq.wqe_head) {
+@@ -981,11 +986,11 @@ static int create_kernel_qp(struct mlx5_ib_dev *dev,
+ 	return 0;
+ 
+ err_wrid:
+-	kfree(qp->sq.wqe_head);
+-	kfree(qp->sq.w_list);
+-	kfree(qp->sq.wrid);
+-	kfree(qp->sq.wr_data);
+-	kfree(qp->rq.wrid);
++	kvfree(qp->sq.wqe_head);
++	kvfree(qp->sq.w_list);
++	kvfree(qp->sq.wrid);
++	kvfree(qp->sq.wr_data);
++	kvfree(qp->rq.wrid);
+ 	mlx5_db_free(dev->mdev, &qp->db);
+ 
+ err_free:
+@@ -998,11 +1003,11 @@ static int create_kernel_qp(struct mlx5_ib_dev *dev,
+ 
+ static void destroy_qp_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp)
+ {
+-	kfree(qp->sq.wqe_head);
+-	kfree(qp->sq.w_list);
+-	kfree(qp->sq.wrid);
+-	kfree(qp->sq.wr_data);
+-	kfree(qp->rq.wrid);
++	kvfree(qp->sq.wqe_head);
++	kvfree(qp->sq.w_list);
++	kvfree(qp->sq.wrid);
++	kvfree(qp->sq.wr_data);
++	kvfree(qp->rq.wrid);
+ 	mlx5_db_free(dev->mdev, &qp->db);
+ 	mlx5_buf_free(dev->mdev, &qp->buf);
+ }
+diff --git a/drivers/infiniband/hw/mlx5/srq.c b/drivers/infiniband/hw/mlx5/srq.c
+index 43707b101f47..30b3ddd8e1ab 100644
+--- a/drivers/infiniband/hw/mlx5/srq.c
++++ b/drivers/infiniband/hw/mlx5/srq.c
+@@ -196,7 +196,7 @@ static int create_srq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_srq *srq,
+ 	}
+ 	mlx5_fill_page_array(&srq->buf, in->pas);
+ 
+-	srq->wrid = kmalloc(srq->msrq.max * sizeof(u64), GFP_KERNEL);
++	srq->wrid = kvmalloc_array(srq->msrq.max, sizeof(u64), GFP_KERNEL);
+ 	if (!srq->wrid) {
+ 		err = -ENOMEM;
+ 		goto err_in;
+@@ -230,7 +230,7 @@ static void destroy_srq_user(struct ib_pd *pd, struct mlx5_ib_srq *srq)
+ 
+ static void destroy_srq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_srq *srq)
+ {
+-	kfree(srq->wrid);
++	kvfree(srq->wrid);
+ 	mlx5_buf_free(dev->mdev, &srq->buf);
+ 	mlx5_db_free(dev->mdev, &srq->db);
+ }

commit 817990ba1a1545875fed01a9014ac7f78dedf16d
+Author: Li Dongyang 
+Date:   Fri Dec 2 19:53:17 2016 -0500
+
+    staging: lustre: obdclass: limit lu_site hash table size on clients
+    
+    Allocating a big hash table using the current formula
+    does not really work for clients. We will create new
+    hash table for each mount on a single client which is
+    a lot of memory more than expected.
+    
+    This patch limits the hash table up to 8M for clients,
+    which has 524288 entries.
+    
+    Signed-off-by: Li Dongyang 
+    Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-7689
+    Reviewed-on: http://review.whamcloud.com/18048
+    Reviewed-by: Fan Yong 
+    Reviewed-by: Alex Zhuravlev 
+    Reviewed-by: Oleg Drokin 
+    Signed-off-by: James Simmons 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c
+index a02aaa3a3b37..80e09846e3be 100644
+--- a/drivers/staging/lustre/lustre/obdclass/lu_object.c
++++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c
+@@ -68,6 +68,7 @@ enum {
+ 
+ #define LU_SITE_BITS_MIN	12
+ #define LU_SITE_BITS_MAX	24
++#define LU_SITE_BITS_MAX_CL	19
+ /**
+  * total 256 buckets, we don't want too many buckets because:
+  * - consume too much memory
+@@ -878,6 +879,9 @@ static unsigned long lu_htable_order(struct lu_device *top)
+ 	unsigned long cache_size;
+ 	unsigned long bits;
+ 
++	if (!strcmp(top->ld_type->ldt_name, LUSTRE_VVP_NAME))
++		bits_max = LU_SITE_BITS_MAX_CL;
++
+ 	/*
+ 	 * Calculate hash table size, assuming that we want reasonable
+ 	 * performance when 20% of total memory is occupied by cache of

commit b4f840c15ac78eb3d096eb3267776393b28c789f
+Author: Li Dongyang 
+Date:   Fri Dec 2 19:53:18 2016 -0500
+
+    staging: lustre: mdt: fail FMODE_WRITE open if the client is read only
+    
+    O_WRONLY/O_RDWR open on a file will get EROFS on a read only client,
+    but the rpc gets sent to the mdt anyway.
+    mdt will increase the mot_write_count of the mdt object, blocking
+    subsequent FMODE_EXEC open to the same file.
+    
+    This patch makes sure we fail the FMODE_WRITE open with EROFS on the
+    client straight away without sending the rpc to mdt.
+    
+    Signed-off-by: Li Dongyang 
+    Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-7727
+    Reviewed-on: http://review.whamcloud.com/18242
+    Reviewed-by: Ian Costello 
+    Reviewed-by: Nathaniel Clark 
+    Reviewed-by: Yang Sheng 
+    Reviewed-by: Oleg Drokin 
+    Signed-off-by: James Simmons 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c
+index b07079c4dda0..9426759aedc9 100644
+--- a/drivers/staging/lustre/lustre/llite/namei.c
++++ b/drivers/staging/lustre/lustre/llite/namei.c
+@@ -572,6 +572,10 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
+ 		}
+ 	}
+ 
++	if (it->it_op & IT_OPEN && it->it_flags & FMODE_WRITE &&
++	    dentry->d_sb->s_flags & MS_RDONLY)
++		return ERR_PTR(-EROFS);
++
+ 	if (it->it_op & IT_CREAT)
+ 		opc = LUSTRE_OPC_CREATE;
+ 	else

commit 542c45acfe3f2e0773dbdf7d1d08ad6d86d982b8
+Author: Andrew Wellington 
+Date:   Thu Nov 10 12:30:46 2016 -0500
+
+    staging: lustre: llite: support SELinux context labelling
+    
+    SELinux contexts are applied by the kernel if mount options are
+    not binary. As we don't use any binary mount options in Lustre,
+    remove the binary mount option flag.
+    
+    Signed-off-by: Andrew Wellington 
+    Signed-off-by: John L. Hammond 
+    Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6950
+    Reviewed-on: http://review.whamcloud.com/15840
+    Reviewed-by: Dmitry Eremin 
+    Reviewed-by: Sebastien Buisson 
+    Reviewed-by: Oleg Drokin 
+    Signed-off-by: James Simmons 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c
+index 308da0660285..62d9fcfded15 100644
+--- a/drivers/staging/lustre/lustre/llite/llite_lib.c
++++ b/drivers/staging/lustre/lustre/llite/llite_lib.c
+@@ -717,6 +717,18 @@ static int ll_options(char *options, int *flags)
+ 			*flags &= ~tmp;
+ 			goto next;
+ 		}
++		tmp = ll_set_opt("context", s1, 1);
++		if (tmp)
++			goto next;
++		tmp = ll_set_opt("fscontext", s1, 1);
++		if (tmp)
++			goto next;
++		tmp = ll_set_opt("defcontext", s1, 1);
++		if (tmp)
++			goto next;
++		tmp = ll_set_opt("rootcontext", s1, 1);
++		if (tmp)
++			goto next;
+ 		tmp = ll_set_opt("user_fid2path", s1, LL_SBI_USER_FID2PATH);
+ 		if (tmp) {
+ 			*flags |= tmp;
+diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c
+index 59fbc29aae94..f604824fdc7c 100644
+--- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c
++++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c
+@@ -1216,8 +1216,7 @@ static struct file_system_type lustre_fs_type = {
+ 	.name	 = "lustre",
+ 	.mount	= lustre_mount,
+ 	.kill_sb      = lustre_kill_super,
+-	.fs_flags     = FS_BINARY_MOUNTDATA | FS_REQUIRES_DEV |
+-			FS_RENAME_DOES_D_MOVE,
++	.fs_flags	= FS_REQUIRES_DEV | FS_RENAME_DOES_D_MOVE,
+ };
+ MODULE_ALIAS_FS("lustre");
+ 

commit 494025c634a09f141d9282a5cfdbc24b5415a871
+Author: Li Dongyang 
+Date:   Mon May 9 10:53:46 2016 -0400
+
+    staging: lustre: o2iblnd: make rdma_create_id() support containers
+    
+    Add support for lustre's ko2iblnd driver to work with
+    containers which was requested by Sebastien Buisson.
+    
+    Signed-off-by: Li Dongyang 
+    Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6215
+    Reviewed-on: http://review.whamcloud.com/18759
+    Reviewed-by: James Simmons 
+    Reviewed-by: Sebastien Buisson 
+    Reviewed-by: Oleg Drokin 
+    Signed-off-by: James Simmons 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h
+index b22984fd9ad3..45bbe93a0590 100644
+--- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h
++++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h
+@@ -109,7 +109,7 @@ extern kib_tunables_t  kiblnd_tunables;
+ 					IBLND_CREDIT_HIGHWATER_V1 : \
+ 					t->lnd_peercredits_hiw)
+ 
+-#define kiblnd_rdma_create_id(cb, dev, ps, qpt) rdma_create_id(&init_net, \
++#define kiblnd_rdma_create_id(cb, dev, ps, qpt) rdma_create_id(current->nsproxy->net_ns, \
+ 							       cb, dev, \
+ 							       ps, qpt)
+ 

commit 902a34ad7242bb50e467a24855b544148989daf4
+Author: Li Dongyang 
+Date:   Wed Mar 30 19:48:44 2016 -0400
+
+    staging/lustre/llite: make sure we do cl_page_clip on the last page
+    
+    When we are doing a partial IO on both first and last page,
+    the logic currently only call cl_page_clip on the first page, which
+    will end up with a incorrect i_size.
+    
+    Signed-off-by: Li Dongyang 
+    Reviewed-on: http://review.whamcloud.com/11630
+    Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5552
+    Reviewed-by: Ian Costello 
+    Reviewed-by: Niu Yawei 
+    Reviewed-by: Li Xi 
+    Reviewed-by: Jinshan Xiong 
+    Signed-off-by: Oleg Drokin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c
+index e44ef21b795e..1d2fc3bf9487 100644
+--- a/drivers/staging/lustre/lustre/llite/vvp_io.c
++++ b/drivers/staging/lustre/lustre/llite/vvp_io.c
+@@ -599,12 +599,14 @@ static int vvp_io_commit_sync(const struct lu_env *env, struct cl_io *io,
+ 		page = cl_page_list_first(plist);
+ 		if (plist->pl_nr == 1) {
+ 			cl_page_clip(env, page, from, to);
+-		} else if (from > 0) {
+-			cl_page_clip(env, page, from, PAGE_SIZE);
+ 		} else {
+-		page = cl_page_list_last(plist);
+-		cl_page_clip(env, page, 0, to);
+-	}
++			if (from > 0)
++				cl_page_clip(env, page, from, PAGE_SIZE);
++			if (to != PAGE_SIZE) {
++				page = cl_page_list_last(plist);
++				cl_page_clip(env, page, 0, to);
++			}
++		}
+ 	}
+ 
+ 	cl_2queue_init(queue);

commit a915ffda199013a8ee2dd6a8a23b89ea45879ed3
+Author: Li Dongyang 
+Date:   Wed Mar 25 21:53:24 2015 -0400
+
+    staging/lustre/llite: glimpse the inode before doing fiemap
+    
+    For a new inode, the i_size is 0 until a stat, which will yield
+    an empty fiemap result.
+    Fix the issue by glimpsing the size before doing fiemap.
+    
+    Signed-off-by: Li Dongyang 
+    Signed-off-by: Bob Glossman 
+    Reviewed-by: Andreas Dilger 
+    Reviewed-by: Jinshan Xiong 
+    Reviewed-on: http://review.whamcloud.com/13439
+    Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6091
+    Signed-off-by: Oleg Drokin 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c
+index 6dab3baa8063..85e74d18d1c7 100644
+--- a/drivers/staging/lustre/lustre/llite/file.c
++++ b/drivers/staging/lustre/lustre/llite/file.c
+@@ -1712,6 +1712,12 @@ static int ll_do_fiemap(struct inode *inode, struct ll_user_fiemap *fiemap,
+ 	fm_key.oa.o_oi = lsm->lsm_oi;
+ 	fm_key.oa.o_valid = OBD_MD_FLID | OBD_MD_FLGROUP;
+ 
++	if (i_size_read(inode) == 0) {
++		rc = ll_glimpse_size(inode);
++		if (rc)
++			goto out;
++	}
++
+ 	obdo_from_inode(&fm_key.oa, inode, OBD_MD_FLSIZE);
+ 	obdo_set_parent_fid(&fm_key.oa, &ll_i2info(inode)->lli_fid);
+ 	/* If filesize is 0, then there would be no objects for mapping */

commit f16928fb53111bc23516372df7f6fed86bdfa661
+Author: Sylvain FORET 
+Date:   Fri Apr 27 14:22:36 2007 +0200
+
+    [ALSA] snd_hda_intel: fix for intel imac
+    
+    Add handling of Intel-iMac-specific pinconfig of the sound card.
+    Intel-iMac now handled as a separated subsystem.
+    
+    Signed-off-by: Sylvain FORET 
+    Signed-off-by: Takashi Iwai 
+    Signed-off-by: Jaroslav Kysela 
+
+diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
+index 5e6d02cf6726..ab6d42207814 100644
+--- a/sound/pci/hda/patch_sigmatel.c
++++ b/sound/pci/hda/patch_sigmatel.c
+@@ -62,6 +62,7 @@ enum {
+ 	STAC_MACBOOK,
+ 	STAC_MACBOOK_PRO_V1,
+ 	STAC_MACBOOK_PRO_V2,
++	STAC_IMAC_INTEL,
+ 	STAC_922X_MODELS
+ };
+ 
+@@ -536,6 +537,12 @@ static unsigned int macbook_pro_v2_pin_configs[10] = {
+ 	0x400000fc, 0x400000fb,
+ };
+ 
++static unsigned int imac_intel_pin_configs[10] = {
++	0x0121e230, 0x90a70120, 0x9017e110, 0x400000fe,
++	0x400000fd, 0x0181e021, 0x1145e040, 0x400000fa,
++	0x400000fc, 0x400000fb,
++};
++
+ static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = {
+ 	[STAC_D945_REF] = ref922x_pin_configs,
+ 	[STAC_D945GTP3] = d945gtp3_pin_configs,
+@@ -544,6 +551,7 @@ static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = {
+ 	[STAC_MACBOOK] = macbook_pro_v1_pin_configs,
+ 	[STAC_MACBOOK_PRO_V1] = macbook_pro_v1_pin_configs,
+ 	[STAC_MACBOOK_PRO_V2] = macbook_pro_v2_pin_configs,
++	[STAC_IMAC_INTEL] = imac_intel_pin_configs,
+ };
+ 
+ static const char *stac922x_models[STAC_922X_MODELS] = {
+@@ -554,6 +562,7 @@ static const char *stac922x_models[STAC_922X_MODELS] = {
+ 	[STAC_MACBOOK]	= "macbook",
+ 	[STAC_MACBOOK_PRO_V1]	= "macbook-pro-v1",
+ 	[STAC_MACBOOK_PRO_V2]	= "macbook-pro",
++	[STAC_IMAC_INTEL] = "imac-intel",
+ };
+ 
+ static struct snd_pci_quirk stac922x_cfg_tbl[] = {
+@@ -1920,6 +1929,9 @@ static int patch_stac922x(struct hda_codec *codec)
+ 		case 0x106b1e00: /* MacBook Pro second generation */
+ 			spec->board_config = STAC_MACBOOK_PRO_V2;
+ 			break;
++		case 0x106b0700: /* Intel-based iMac */
++			spec->board_config = STAC_IMAC_INTEL;
++			break;
+ 		}
+ 	}
+ 

\ No newline at end of file diff --git a/detail/46.html b/detail/46.html new file mode 100644 index 0000000..e67d9f7 --- /dev/null +++ b/detail/46.html @@ -0,0 +1,564 @@ +

Patches contributed by Rensselaer Polytechnic Institute


commit acccafe9ca63eac3a202d8805d286ada6ab8cced
+Author: David Brigada 
+Date:   Wed Jun 11 13:27:32 2008 -0400
+
+    kobject: Documentation Spelling Patch
+    
+    Signed-off-by: David Brigada 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/Documentation/kobject.txt b/Documentation/kobject.txt
+index bf3256e04027..51a8021ee532 100644
+--- a/Documentation/kobject.txt
++++ b/Documentation/kobject.txt
+@@ -305,7 +305,7 @@ should not be manipulated by any other user.
+ 
+ A kset keeps its children in a standard kernel linked list.  Kobjects point
+ back to their containing kset via their kset field. In almost all cases,
+-the kobjects belonging to a ket have that kset (or, strictly, its embedded
++the kobjects belonging to a kset have that kset (or, strictly, its embedded
+ kobject) in their parent.
+ 
+ As a kset contains a kobject within it, it should always be dynamically

commit cc2e2767f172fb2f38ca72e22ac98e452550437f
+Author: Matt LaPlante 
+Date:   Tue Oct 3 22:22:29 2006 +0200
+
+    Typos in fs/Kconfig
+    
+    Signed-off-by: Adrian Bunk 
+
+diff --git a/fs/Kconfig b/fs/Kconfig
+index 1453d2d164f7..8d18497de629 100644
+--- a/fs/Kconfig
++++ b/fs/Kconfig
+@@ -74,11 +74,11 @@ config EXT3_FS
+ 	tristate "Ext3 journalling file system support"
+ 	select JBD
+ 	help
+-	  This is the journaling version of the Second extended file system
++	  This is the journalling version of the Second extended file system
+ 	  (often called ext3), the de facto standard Linux file system
+ 	  (method to organize files on a storage device) for hard disks.
+ 
+-	  The journaling code included in this driver means you do not have
++	  The journalling code included in this driver means you do not have
+ 	  to run e2fsck (file system checker) on your file systems after a
+ 	  crash.  The journal keeps track of any changes that were being made
+ 	  at the time the system crashed, and can ensure that your file system
+@@ -143,7 +143,7 @@ config EXT3_FS_SECURITY
+ config JBD
+ 	tristate
+ 	help
+-	  This is a generic journaling layer for block devices.  It is
++	  This is a generic journalling layer for block devices.  It is
+ 	  currently used by the ext3 and OCFS2 file systems, but it could
+ 	  also be used to add journal support to other file systems or block
+ 	  devices such as RAID or LVM.
+@@ -183,7 +183,7 @@ config REISERFS_FS
+ 	tristate "Reiserfs support"
+ 	help
+ 	  Stores not just filenames but the files themselves in a balanced
+-	  tree.  Uses journaling.
++	  tree.  Uses journalling.
+ 
+ 	  Balanced trees are more efficient than traditional file system
+ 	  architectural foundations.
+@@ -1090,7 +1090,7 @@ config JFFS_FS
+ 	tristate "Journalling Flash File System (JFFS) support"
+ 	depends on MTD && BLOCK
+ 	help
+-	  JFFS is the Journaling Flash File System developed by Axis
++	  JFFS is the Journalling Flash File System developed by Axis
+ 	  Communications in Sweden, aimed at providing a crash/powerdown-safe
+ 	  file system for disk-less embedded devices. Further information is
+ 	  available at ().
+@@ -1260,7 +1260,7 @@ config JFFS2_CMODE_NONE
+ config JFFS2_CMODE_PRIORITY
+         bool "priority"
+         help
+-          Tries the compressors in a predefinied order and chooses the first
++          Tries the compressors in a predefined order and chooses the first
+           successful one.
+ 
+ config JFFS2_CMODE_SIZE
+@@ -1950,7 +1950,7 @@ config AFS_FS
+ 	  If you say Y here, you will get an experimental Andrew File System
+ 	  driver. It currently only supports unsecured read-only AFS access.
+ 
+-	  See  for more intormation.
++	  See  for more information.
+ 
+ 	  If unsure, say N.
+ 

commit 4b3f686d4aa8ad815dc68a4e8fabd05b1ebb9f2c
+Author: Matt LaPlante 
+Date:   Tue Oct 3 22:21:02 2006 +0200
+
+    Attack of "the the"s in arch
+    
+    The patch below corrects multiple occurances of "the the"
+    typos across several files, both in source comments and KConfig files.
+    There is no actual code changed, only text.  Note this only affects the /arch
+    directory, and I believe I could find many more elsewhere. :)
+    
+    Signed-off-by: Adrian Bunk 
+
+diff --git a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
+index a6910114b24c..a21b12f06c6b 100644
+--- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
++++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
+@@ -164,7 +164,7 @@ static void lh7a40x_ack_cpld_irq (u32 irq)
+ 	/* CPLD doesn't have ack capability, but some devices may */
+ 
+ #if defined (CPLD_INTMASK_TOUCH)
+-	/* The touch control *must* mask the the interrupt because the
++	/* The touch control *must* mask the interrupt because the
+ 	 * interrupt bit is read by the driver to determine if the pen
+ 	 * is still down. */
+ 	if (irq == IRQ_TOUCH)
+diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
+index af219e51734f..8ff1c6fb5aa1 100644
+--- a/arch/i386/Kconfig
++++ b/arch/i386/Kconfig
+@@ -682,7 +682,7 @@ config EFI
+ 	depends on ACPI
+ 	default n
+ 	---help---
+-	This enables the the kernel to boot on EFI platforms using
++	This enables the kernel to boot on EFI platforms using
+ 	system configuration information passed to it from the firmware.
+ 	This also enables the kernel to use any EFI runtime services that are
+ 	available (such as the EFI variable services).
+diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c
+index 83c3645ccc43..b60d7e8689ed 100644
+--- a/arch/i386/pci/fixup.c
++++ b/arch/i386/pci/fixup.c
+@@ -393,7 +393,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
+  * We pretend to bring them out of full D3 state, and restore the proper
+  * IRQ, PCI cache line size, and BARs, otherwise the device won't function
+  * properly.  In some cases, the device will generate an interrupt on
+- * the wrong IRQ line, causing any devices sharing the the line it's
++ * the wrong IRQ line, causing any devices sharing the line it's
+  * *supposed* to use to be disabled by the kernel's IRQ debug code.
+  */
+ static u16 toshiba_line_size;
+diff --git a/arch/ia64/sn/kernel/xpnet.c b/arch/ia64/sn/kernel/xpnet.c
+index 007703c494a4..c8173db0d84f 100644
+--- a/arch/ia64/sn/kernel/xpnet.c
++++ b/arch/ia64/sn/kernel/xpnet.c
+@@ -225,7 +225,7 @@ xpnet_receive(partid_t partid, int channel, struct xpnet_message *msg)
+ 	skb_put(skb, (msg->size - msg->leadin_ignore - msg->tailout_ignore));
+ 
+ 	/*
+-	 * Move the data over from the the other side.
++	 * Move the data over from the other side.
+ 	 */
+ 	if ((XPNET_VERSION_MINOR(msg->version) == 1) &&
+ 						(msg->embedded_bytes != 0)) {
+diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
+index e767f2ddae72..b7c942cf7741 100644
+--- a/arch/m68knommu/Kconfig
++++ b/arch/m68knommu/Kconfig
+@@ -495,7 +495,7 @@ config VECTORBASE
+ 	hex "Address of the base of system vectors"
+ 	default "0"
+ 	help
+-	  Define the address of the the system vectors. Commonly this is
++	  Define the address of the system vectors. Commonly this is
+ 	  put at the start of RAM, but it doesn't have to be. On ColdFire
+ 	  platforms this address is programmed into the VBR register, thus
+ 	  actually setting the address to use.
+diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
+index 375e0991505d..6f8b25cfa6f0 100644
+--- a/arch/mips/mm/tlbex.c
++++ b/arch/mips/mm/tlbex.c
+@@ -1211,7 +1211,7 @@ static void __init build_r4000_tlb_refill_handler(void)
+ 	 * Overflow check: For the 64bit handler, we need at least one
+ 	 * free instruction slot for the wrap-around branch. In worst
+ 	 * case, if the intended insertion point is a delay slot, we
+-	 * need three, with the the second nop'ed and the third being
++	 * need three, with the second nop'ed and the third being
+ 	 * unused.
+ 	 */
+ #ifdef CONFIG_32BIT
+diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
+index 95c1b8ec4289..192357a3b9fe 100644
+--- a/arch/parisc/kernel/entry.S
++++ b/arch/parisc/kernel/entry.S
+@@ -941,8 +941,8 @@ syscall_exit_rfi:
+ 	 * to "proper" values now (otherwise we'll wind up restoring
+ 	 * whatever was last stored in the task structure, which might
+ 	 * be inconsistent if an interrupt occured while on the gateway
+-	 * page) Note that we may be "trashing" values the user put in
+-	 * them, but we don't support the the user changing them.
++	 * page). Note that we may be "trashing" values the user put in
++	 * them, but we don't support the user changing them.
+ 	 */
+ 
+ 	STREG   %r0,PT_SR2(%r16)
+diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
+index 032e6ab5d3c4..96ef656e4669 100644
+--- a/arch/powerpc/Kconfig
++++ b/arch/powerpc/Kconfig
+@@ -1002,7 +1002,7 @@ config CONSISTENT_START_BOOL
+ 	depends on ADVANCED_OPTIONS && NOT_COHERENT_CACHE
+ 	help
+ 	  This option allows you to set the base virtual address
+-	  of the the consistent memory pool.  This pool of virtual
++	  of the consistent memory pool.  This pool of virtual
+ 	  memory is used to make consistent memory allocations.
+ 
+ config CONSISTENT_START
+@@ -1013,7 +1013,7 @@ config CONSISTENT_SIZE_BOOL
+ 	bool "Set custom consistent memory pool size"
+ 	depends on ADVANCED_OPTIONS && NOT_COHERENT_CACHE
+ 	help
+-	  This option allows you to set the size of the the
++	  This option allows you to set the size of the
+ 	  consistent memory pool.  This pool of virtual memory
+ 	  is used to make consistent memory allocations.
+ 
+diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
+index fdd9e7b66244..077711e63104 100644
+--- a/arch/ppc/Kconfig
++++ b/arch/ppc/Kconfig
+@@ -1345,7 +1345,7 @@ config CONSISTENT_START_BOOL
+ 	depends on ADVANCED_OPTIONS && NOT_COHERENT_CACHE
+ 	help
+ 	  This option allows you to set the base virtual address
+-	  of the the consistent memory pool.  This pool of virtual
++	  of the consistent memory pool.  This pool of virtual
+ 	  memory is used to make consistent memory allocations.
+ 
+ config CONSISTENT_START
+@@ -1356,7 +1356,7 @@ config CONSISTENT_SIZE_BOOL
+ 	bool "Set custom consistent memory pool size"
+ 	depends on ADVANCED_OPTIONS && NOT_COHERENT_CACHE
+ 	help
+-	  This option allows you to set the size of the the
++	  This option allows you to set the size of the
+ 	  consistent memory pool.  This pool of virtual memory
+ 	  is used to make consistent memory allocations.
+ 
+diff --git a/arch/um/Makefile b/arch/um/Makefile
+index f6ad832faf13..c8016a98483b 100644
+--- a/arch/um/Makefile
++++ b/arch/um/Makefile
+@@ -102,7 +102,7 @@ linux: vmlinux
+ define archhelp
+   echo '* linux		- Binary kernel image (./linux) - for backward'
+   echo '		   compatibility only, this creates a hard link to the'
+-  echo '		   real kernel binary, the the "vmlinux" binary you'
++  echo '		   real kernel binary, the "vmlinux" binary you'
+   echo '		   find in the kernel root.'
+ endef
+ 
+diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
+index 24747a413785..cfd9f01fd464 100644
+--- a/arch/um/drivers/line.c
++++ b/arch/um/drivers/line.c
+@@ -497,7 +497,7 @@ void close_lines(struct line *lines, int nlines)
+ }
+ 
+ /* Common setup code for both startup command line and mconsole initialization.
+- * @lines contains the the array (of size @num) to modify;
++ * @lines contains the array (of size @num) to modify;
+  * @init is the setup string;
+  */
+ 
+diff --git a/arch/um/include/sysdep-x86_64/ptrace_user.h b/arch/um/include/sysdep-x86_64/ptrace_user.h
+index 128faf027364..4cd61a852fab 100644
+--- a/arch/um/include/sysdep-x86_64/ptrace_user.h
++++ b/arch/um/include/sysdep-x86_64/ptrace_user.h
+@@ -55,7 +55,7 @@
+ #define PTRACE_OLDSETOPTIONS 21
+ #endif
+ 
+-/* These are before the system call, so the the system call number is RAX
++/* These are before the system call, so the system call number is RAX
+  * rather than ORIG_RAX, and arg4 is R10 rather than RCX
+  */
+ #define REGS_SYSCALL_NR PT_INDEX(RAX)
+diff --git a/arch/v850/kernel/entry.S b/arch/v850/kernel/entry.S
+index d991e4547dbb..8bc521ca081f 100644
+--- a/arch/v850/kernel/entry.S
++++ b/arch/v850/kernel/entry.S
+@@ -195,7 +195,7 @@
+ 	sst.w	lp, PTO+PT_GPR(GPR_LP)[ep];				      \
+ 	type ## _STATE_SAVER
+ /* Pop a register state pushed by PUSH_STATE, except for the stack pointer,
+-   from the the stack.  */
++   from the stack.  */
+ #define POP_STATE(type)							      \
+ 	mov	sp, ep;							      \
+ 	type ## _STATE_RESTORER;					      \
+diff --git a/arch/xtensa/lib/usercopy.S b/arch/xtensa/lib/usercopy.S
+index 265db2693cbd..4641ef510f0e 100644
+--- a/arch/xtensa/lib/usercopy.S
++++ b/arch/xtensa/lib/usercopy.S
+@@ -5,10 +5,10 @@
+  *
+  *  DO NOT COMBINE this function with .
+  *  It needs to remain separate and distinct.  The hal files are part
+- *  of the the Xtensa link-time HAL, and those files may differ per
++ *  of the Xtensa link-time HAL, and those files may differ per
+  *  processor configuration.  Patching the kernel for another
+  *  processor configuration includes replacing the hal files, and we
+- *  could loose the special functionality for accessing user-space
++ *  could lose the special functionality for accessing user-space
+  *  memory during such a patch.  We sacrifice a little code space here
+  *  in favor to simplify code maintenance.
+  *

commit dc474c891c1993c4d608bed00c425b6db93d088d
+Author: Matt LaPlante 
+Date:   Fri Jun 30 01:56:06 2006 -0700
+
+    [PATCH] Documentation/IPMI typos
+    
+    Two typos in Documentation/IPMI.
+    
+    Acked-by: Alan Cox 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/Documentation/IPMI.txt b/Documentation/IPMI.txt
+index bf1cf98d2a27..0256805b548f 100644
+--- a/Documentation/IPMI.txt
++++ b/Documentation/IPMI.txt
+@@ -10,7 +10,7 @@ standard for controlling intelligent devices that monitor a system.
+ It provides for dynamic discovery of sensors in the system and the
+ ability to monitor the sensors and be informed when the sensor's
+ values change or go outside certain boundaries.  It also has a
+-standardized database for field-replacable units (FRUs) and a watchdog
++standardized database for field-replaceable units (FRUs) and a watchdog
+ timer.
+ 
+ To use this, you need an interface to an IPMI controller in your
+@@ -64,7 +64,7 @@ situation, you need to read the section below named 'The SI Driver' or
+ IPMI defines a standard watchdog timer.  You can enable this with the
+ 'IPMI Watchdog Timer' config option.  If you compile the driver into
+ the kernel, then via a kernel command-line option you can have the
+-watchdog timer start as soon as it intitializes.  It also have a lot
++watchdog timer start as soon as it initializes.  It also have a lot
+ of other options, see the 'Watchdog' section below for more details.
+ Note that you can also have the watchdog continue to run if it is
+ closed (by default it is disabled on close).  Go into the 'Watchdog

commit fcb4ee8852e2e9326e102f0910c029de45afabba
+Author: Matt LaPlante 
+Date:   Fri Jun 30 18:57:59 2006 +0200
+
+    arch/arm26/Kconfig typos
+    
+    Signed-off-by: Adrian Bunk 
+
+diff --git a/arch/arm26/Kconfig b/arch/arm26/Kconfig
+index cf4ebf4c274d..c14fe918bc4c 100644
+--- a/arch/arm26/Kconfig
++++ b/arch/arm26/Kconfig
+@@ -79,7 +79,7 @@ config ARCH_A5K
+         bool "A5000"
+ 	select ARCH_MAY_HAVE_PC_FDC
+         help
+-          Say Y here to to support the Acorn A5000.
++          Say Y here to support the Acorn A5000.
+ 
+ 	  Linux can support the
+           internal IDE disk and CD-ROM interface, serial and parallel port,
+@@ -129,7 +129,7 @@ config ZBOOT_ROM_BSS
+ config XIP_KERNEL
+ 	bool "Execute In Place (XIP) kernel image"
+ 	help
+-	  Select this option to create a kernel that can be programed into
++	  Select this option to create a kernel that can be programmed into
+ 	  the OS ROMs.
+ 
+ comment "At least one math emulation must be selected"
+@@ -140,7 +140,7 @@ config FPE_NWFPE
+ 	  Say Y to include the NWFPE floating point emulator in the kernel.
+ 	  This is necessary to run most binaries. Linux does not currently
+ 	  support floating point hardware so you need to say Y here even if
+-	  your machine has an FPA or floating point co-processor podule.
++	  your machine has an FPA or floating point co-processor module.
+ 
+ 	  It is also possible to say M to build the emulator as a module
+ 	  (nwfpe) or indeed to leave it out altogether. However, unless you

commit 590abf09d62841677ac9676574f1017b7f5235e1
+Author: Matt LaPlante 
+Date:   Fri Jun 30 18:56:29 2006 +0200
+
+    Documentation/IPMI typos
+    
+    Acked-by: Alan Cox 
+    Signed-off-by: Adrian Bunk 
+
+diff --git a/Documentation/IPMI.txt b/Documentation/IPMI.txt
+index bf1cf98d2a27..0256805b548f 100644
+--- a/Documentation/IPMI.txt
++++ b/Documentation/IPMI.txt
+@@ -10,7 +10,7 @@ standard for controlling intelligent devices that monitor a system.
+ It provides for dynamic discovery of sensors in the system and the
+ ability to monitor the sensors and be informed when the sensor's
+ values change or go outside certain boundaries.  It also has a
+-standardized database for field-replacable units (FRUs) and a watchdog
++standardized database for field-replaceable units (FRUs) and a watchdog
+ timer.
+ 
+ To use this, you need an interface to an IPMI controller in your
+@@ -64,7 +64,7 @@ situation, you need to read the section below named 'The SI Driver' or
+ IPMI defines a standard watchdog timer.  You can enable this with the
+ 'IPMI Watchdog Timer' config option.  If you compile the driver into
+ the kernel, then via a kernel command-line option you can have the
+-watchdog timer start as soon as it intitializes.  It also have a lot
++watchdog timer start as soon as it initializes.  It also have a lot
+ of other options, see the 'Watchdog' section below for more details.
+ Note that you can also have the watchdog continue to run if it is
+ closed (by default it is disabled on close).  Go into the 'Watchdog

commit 3539c272f18d54dc1e4c109d336d33d6a5c94b93
+Author: Matt LaPlante 
+Date:   Fri Jun 30 18:53:46 2006 +0200
+
+    Kconfig: Typos in net/sched/Kconfig
+    
+    Signed-off-by: Adrian Bunk 
+
+diff --git a/net/sched/Kconfig b/net/sched/Kconfig
+index 13eeee582886..8298ea9ffe19 100644
+--- a/net/sched/Kconfig
++++ b/net/sched/Kconfig
+@@ -305,7 +305,7 @@ config NET_CLS_U32
+ 	tristate "Universal 32bit comparisons w/ hashing (U32)"
+ 	select NET_CLS
+ 	---help---
+-	  Say Y here to be able to classify packetes using a universal
++	  Say Y here to be able to classify packets using a universal
+ 	  32bit pieces based comparison scheme.
+ 
+ 	  To compile this code as a module, choose M here: the
+@@ -485,7 +485,7 @@ config NET_ACT_IPT
+         tristate "IPtables targets"
+         depends on NET_CLS_ACT && NETFILTER && IP_NF_IPTABLES
+         ---help---
+-	  Say Y here to be able to invoke iptables targets after succesful
++	  Say Y here to be able to invoke iptables targets after successful
+ 	  classification.
+ 
+ 	  To compile this code as a module, choose M here: the
+@@ -537,8 +537,8 @@ config NET_ESTIMATOR
+ 	---help---
+ 	  Say Y here to allow using rate estimators to estimate the current
+ 	  rate-of-flow for network devices, queues, etc. This module is
+-	  automaticaly selected if needed but can be selected manually for
+-	  statstical purposes.
++	  automatically selected if needed but can be selected manually for
++	  statistical purposes.
+ 
+ endif # NET_SCHED
+ 

commit c22751b73a3770b3046102bb97b139218ff1875b
+Author: Matt LaPlante 
+Date:   Thu Jun 29 12:51:15 2006 -0700
+
+    [NETFILTE] ipv4: Fix typo (Bugzilla #6753)
+    
+    This patch fixes bugzilla #6753, a typo in the netfilter Kconfig
+    
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
+index e1d7f5fbc526..ef0b5aac5838 100644
+--- a/net/ipv4/netfilter/Kconfig
++++ b/net/ipv4/netfilter/Kconfig
+@@ -332,7 +332,7 @@ config IP_NF_MATCH_HASHLIMIT
+ 	help
+ 	  This option adds a new iptables `hashlimit' match.  
+ 
+-	  As opposed to `limit', this match dynamically crates a hash table
++	  As opposed to `limit', this match dynamically creates a hash table
+ 	  of limit buckets, based on your selection of source/destination
+ 	  ip addresses and/or ports.
+ 

commit 1f1332f727c3229eb2166a83fec5d3de6a73dce2
+Author: Matt LaPlante 
+Date:   Thu Jun 29 01:32:47 2006 -0400
+
+    [PATCH] KConfig: Spellchecking 'similarity' and 'independent'
+    
+    Several KConfig files had 'similarity' and 'independent' spelled incorrectly...
+    
+    Acked-by: Alan Cox 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
+index 0463f6335905..1718429286d4 100644
+--- a/arch/i386/Kconfig
++++ b/arch/i386/Kconfig
+@@ -738,7 +738,7 @@ config KEXEC
+ 	  but it is independent of the system firmware.   And like a reboot
+ 	  you can start any kernel with it, not just Linux.
+ 
+-	  The name comes from the similiarity to the exec system call.
++	  The name comes from the similarity to the exec system call.
+ 
+ 	  It is an ongoing process to be certain the hardware in a machine
+ 	  is properly shutdown, so do not be surprised if this code does not
+diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
+index b9a40a35a9ed..2643dbc3f289 100644
+--- a/arch/powerpc/Kconfig
++++ b/arch/powerpc/Kconfig
+@@ -644,10 +644,10 @@ config KEXEC
+ 	help
+ 	  kexec is a system call that implements the ability to shutdown your
+ 	  current kernel, and to start another kernel.  It is like a reboot
+-	  but it is indepedent of the system firmware.   And like a reboot
++	  but it is independent of the system firmware.   And like a reboot
+ 	  you can start any kernel with it, not just Linux.
+ 
+-	  The name comes from the similiarity to the exec system call.
++	  The name comes from the similarity to the exec system call.
+ 
+ 	  It is an ongoing process to be certain the hardware in a machine
+ 	  is properly shutdown, so do not be surprised if this code does not
+diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
+index b55de4f42aec..a04cdf01596b 100644
+--- a/arch/ppc/Kconfig
++++ b/arch/ppc/Kconfig
+@@ -219,10 +219,10 @@ config KEXEC
+ 	help
+ 	  kexec is a system call that implements the ability to shutdown your
+ 	  current kernel, and to start another kernel.  It is like a reboot
+-	  but it is indepedent of the system firmware.   And like a reboot
++	  but it is independent of the system firmware.   And like a reboot
+ 	  you can start any kernel with it, not just Linux.
+ 
+-	  The name comes from the similiarity to the exec system call.
++	  The name comes from the similarity to the exec system call.
+ 
+ 	  It is an ongoing process to be certain the hardware in a machine
+ 	  is properly shutdown, so do not be surprised if this code does not
+diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
+index 2bcecf422573..1a0db1d4c952 100644
+--- a/arch/sh/Kconfig
++++ b/arch/sh/Kconfig
+@@ -465,10 +465,10 @@ config KEXEC
+ 	help
+ 	  kexec is a system call that implements the ability to shutdown your
+ 	  current kernel, and to start another kernel.  It is like a reboot
+-	  but it is indepedent of the system firmware.  And like a reboot
++	  but it is independent of the system firmware.  And like a reboot
+ 	  you can start any kernel with it, not just Linux.
+ 
+-	  The name comes from the similiarity to the exec system call.
++	  The name comes from the similarity to the exec system call.
+ 
+ 	  It is an ongoing process to be certain the hardware in a machine
+ 	  is properly shutdown, so do not be surprised if this code does not
+diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
+index 91039844820c..e856804c447f 100644
+--- a/arch/x86_64/Kconfig
++++ b/arch/x86_64/Kconfig
+@@ -461,10 +461,10 @@ config KEXEC
+ 	help
+ 	  kexec is a system call that implements the ability to shutdown your
+ 	  current kernel, and to start another kernel.  It is like a reboot
+-	  but it is indepedent of the system firmware.   And like a reboot
++	  but it is independent of the system firmware.   And like a reboot
+ 	  you can start any kernel with it, not just Linux.
+ 
+-	  The name comes from the similiarity to the exec system call.
++	  The name comes from the similarity to the exec system call.
+ 
+ 	  It is an ongoing process to be certain the hardware in a machine
+ 	  is properly shutdown, so do not be surprised if this code does not

\ No newline at end of file diff --git a/detail/47.html b/detail/47.html new file mode 100644 index 0000000..78dd95b --- /dev/null +++ b/detail/47.html @@ -0,0 +1,653 @@ +

Patches contributed by University of Pittsburgh


commit ab52a484455007b3c9c11e18f6d0eed6d8f2de4e
+Author: Paul Elder 
+Date:   Wed Jun 28 23:40:21 2017 +0900
+
+    kselftest: add ksft_print_msg() function to output general information
+    
+    Add a generic information output function: ksft_print_msg()
+    
+    Signed-off-by: Paul Elder 
+    Signed-off-by: Shuah Khan 
+
+diff --git a/tools/testing/selftests/kselftest.h b/tools/testing/selftests/kselftest.h
+index a00844e4c915..08e90c2cc5cb 100644
+--- a/tools/testing/selftests/kselftest.h
++++ b/tools/testing/selftests/kselftest.h
+@@ -55,6 +55,16 @@ static inline void ksft_print_cnts(void)
+ 	printf("1..%d\n", ksft_test_num());
+ }
+ 
++static inline void ksft_print_msg(const char *msg, ...)
++{
++	va_list args;
++
++	va_start(args, msg);
++	printf("# ");
++	vprintf(msg, args);
++	va_end(args);
++}
++
+ static inline void ksft_test_result_pass(const char *msg, ...)
+ {
+ 	va_list args;

commit 151b2732111f0743e764a7bc62d4f580341a62f3
+Author: Paul Elder 
+Date:   Wed Jun 28 23:40:20 2017 +0900
+
+    kselftest: make ksft_* output functions variadic
+    
+    Make the ksft_* output functions variadic to allow string formatting
+    directly in these functions.
+    
+    Signed-off-by: Paul Elder 
+    Signed-off-by: Shuah Khan 
+
+diff --git a/tools/testing/selftests/kselftest.h b/tools/testing/selftests/kselftest.h
+index be01f2d15472..a00844e4c915 100644
+--- a/tools/testing/selftests/kselftest.h
++++ b/tools/testing/selftests/kselftest.h
+@@ -12,6 +12,7 @@
+ 
+ #include 
+ #include 
++#include 
+ 
+ /* define kselftest exit codes */
+ #define KSFT_PASS  0
+@@ -54,22 +55,40 @@ static inline void ksft_print_cnts(void)
+ 	printf("1..%d\n", ksft_test_num());
+ }
+ 
+-static inline void ksft_test_result_pass(const char *msg)
++static inline void ksft_test_result_pass(const char *msg, ...)
+ {
++	va_list args;
++
+ 	ksft_cnt.ksft_pass++;
+-	printf("ok %d %s\n", ksft_test_num(), msg);
++
++	va_start(args, msg);
++	printf("ok %d ", ksft_test_num());
++	vprintf(msg, args);
++	va_end(args);
+ }
+ 
+-static inline void ksft_test_result_fail(const char *msg)
++static inline void ksft_test_result_fail(const char *msg, ...)
+ {
++	va_list args;
++
+ 	ksft_cnt.ksft_fail++;
+-	printf("not ok %d %s\n", ksft_test_num(), msg);
++
++	va_start(args, msg);
++	printf("not ok %d ", ksft_test_num());
++	vprintf(msg, args);
++	va_end(args);
+ }
+ 
+-static inline void ksft_test_result_skip(const char *msg)
++static inline void ksft_test_result_skip(const char *msg, ...)
+ {
++	va_list args;
++
+ 	ksft_cnt.ksft_xskip++;
+-	printf("ok %d # skip %s\n", ksft_test_num(), msg);
++
++	va_start(args, msg);
++	printf("ok %d # skip ", ksft_test_num());
++	vprintf(msg, args);
++	va_end(args);
+ }
+ 
+ static inline int ksft_exit_pass(void)
+@@ -85,9 +104,15 @@ static inline int ksft_exit_fail(void)
+ 	exit(KSFT_FAIL);
+ }
+ 
+-static inline int ksft_exit_fail_msg(const char *msg)
++static inline int ksft_exit_fail_msg(const char *msg, ...)
+ {
+-	printf("Bail out! %s\n", msg);
++	va_list args;
++
++	va_start(args, msg);
++	printf("Bail out! ");
++	vprintf(msg, args);
++	va_end(args);
++
+ 	ksft_print_cnts();
+ 	exit(KSFT_FAIL);
+ }
+@@ -104,12 +129,18 @@ static inline int ksft_exit_xpass(void)
+ 	exit(KSFT_XPASS);
+ }
+ 
+-static inline int ksft_exit_skip(const char *msg)
++static inline int ksft_exit_skip(const char *msg, ...)
+ {
+-	if (msg)
+-		printf("1..%d # Skipped: %s\n", ksft_test_num(), msg);
+-	else
++	if (msg) {
++		va_list args;
++
++		va_start(args, msg);
++		printf("1..%d # Skipped: ", ksft_test_num());
++		vprintf(msg, args);
++		va_end(args);
++	} else {
+ 		ksft_print_cnts();
++	}
+ 	exit(KSFT_SKIP);
+ }
+ 

commit e4d1065b315b433f224920f1617bc3783230501c
+Author: Paul Elder 
+Date:   Fri Jun 16 00:54:22 2017 +0900
+
+    kselftest: make callers of ksft_exit_skip() output the reason for skipping
+    
+    Make the three tests that did use the old ksft_ext_skip()
+    (breakpoints/breakpoint_test_arm64, breakpoints/step_after_suspend_test,
+    and membarrier_test) use the new one, with an output for the
+    reason for skipping all the tests.
+    
+    Signed-off-by: Paul Elder 
+    Signed-off-by: Shuah Khan 
+
+diff --git a/tools/testing/selftests/breakpoints/breakpoint_test_arm64.c b/tools/testing/selftests/breakpoints/breakpoint_test_arm64.c
+index 3897e996541e..fa6d57af5217 100644
+--- a/tools/testing/selftests/breakpoints/breakpoint_test_arm64.c
++++ b/tools/testing/selftests/breakpoints/breakpoint_test_arm64.c
+@@ -101,9 +101,8 @@ static bool set_watchpoint(pid_t pid, int size, int wp)
+ 		return true;
+ 
+ 	if (errno == EIO) {
+-		printf("ptrace(PTRACE_SETREGSET, NT_ARM_HW_WATCH) "
++		ksft_exit_skip("ptrace(PTRACE_SETREGSET, NT_ARM_HW_WATCH) "
+ 			"not supported on this hardware\n");
+-		ksft_exit_skip();
+ 	}
+ 	perror("ptrace(PTRACE_SETREGSET, NT_ARM_HW_WATCH) failed");
+ 	return false;
+diff --git a/tools/testing/selftests/breakpoints/step_after_suspend_test.c b/tools/testing/selftests/breakpoints/step_after_suspend_test.c
+index bf37c1087f25..c60c2effb6bc 100644
+--- a/tools/testing/selftests/breakpoints/step_after_suspend_test.c
++++ b/tools/testing/selftests/breakpoints/step_after_suspend_test.c
+@@ -83,8 +83,8 @@ bool run_test(int cpu)
+ 
+ 	if (ptrace(PTRACE_SINGLESTEP, pid, NULL, NULL) < 0) {
+ 		if (errno == EIO) {
+-			printf("ptrace(PTRACE_SINGLESTEP) not supported on this architecture\n");
+-			ksft_exit_skip();
++			ksft_exit_skip("ptrace(PTRACE_SINGLESTEP) "
++				"not supported on this architecture");
+ 		}
+ 		perror("ptrace(PTRACE_SINGLESTEP) failed");
+ 		return false;
+diff --git a/tools/testing/selftests/membarrier/membarrier_test.c b/tools/testing/selftests/membarrier/membarrier_test.c
+index cae8c984dfb0..18cb9d1da4e4 100644
+--- a/tools/testing/selftests/membarrier/membarrier_test.c
++++ b/tools/testing/selftests/membarrier/membarrier_test.c
+@@ -87,8 +87,7 @@ static enum test_membarrier_status test_membarrier_query(void)
+ 			 * It is valid to build a kernel with
+ 			 * CONFIG_MEMBARRIER=n. However, this skips the tests.
+ 			 */
+-			ksft_test_result_skip("CONFIG_MEMBARRIER is not enabled\n");
+-			return ksft_exit_skip();
++			ksft_exit_skip("CONFIG_MEMBARRIER is not enabled\n");
+ 		}
+ 		ksft_test_result_fail("sys_membarrier() failed\n");
+ 		return TEST_MEMBARRIER_FAIL;
+@@ -108,13 +107,13 @@ int main(int argc, char **argv)
+ 	case TEST_MEMBARRIER_FAIL:
+ 		return ksft_exit_fail();
+ 	case TEST_MEMBARRIER_SKIP:
+-		return ksft_exit_skip();
++		return ksft_exit_skip(NULL);
+ 	}
+ 	switch (test_membarrier()) {
+ 	case TEST_MEMBARRIER_FAIL:
+ 		return ksft_exit_fail();
+ 	case TEST_MEMBARRIER_SKIP:
+-		return ksft_exit_skip();
++		return ksft_exit_skip(NULL);
+ 	}
+ 
+ 	return ksft_exit_pass();

commit 54f57baab644e99b6da34d9538b2a9c0a05b690d
+Author: Paul Elder 
+Date:   Fri Jun 16 00:54:20 2017 +0900
+
+    kselftest: make ksft_exit_skip() output a reason for skipping
+    
+    Make ksft_exit_skip() input an optional message string as the reason
+    for skipping all the tests and outputs it prior to exiting.
+    
+    Signed-off-by: Paul Elder 
+    Signed-off-by: Shuah Khan 
+
+diff --git a/tools/testing/selftests/kselftest.h b/tools/testing/selftests/kselftest.h
+index 1d874a50d957..be01f2d15472 100644
+--- a/tools/testing/selftests/kselftest.h
++++ b/tools/testing/selftests/kselftest.h
+@@ -104,9 +104,12 @@ static inline int ksft_exit_xpass(void)
+ 	exit(KSFT_XPASS);
+ }
+ 
+-static inline int ksft_exit_skip(void)
++static inline int ksft_exit_skip(const char *msg)
+ {
+-	ksft_print_cnts();
++	if (msg)
++		printf("1..%d # Skipped: %s\n", ksft_test_num(), msg);
++	else
++		ksft_print_cnts();
+ 	exit(KSFT_SKIP);
+ }
+ 

commit b901216441e6599063ff2828ec7f2f902b9902f0
+Author: Paul Elder 
+Date:   Mon Jun 12 08:56:50 2017 +0200
+
+    kselftest: breakpoints: convert step_after_suspend_test to TAP13 output
+    
+    Make the step_after_suspend test output in the TAP13 format by using the
+    TAP13 output functions defined in kselftest.h
+    
+    Signed-off-by: Paul Elder 
+    Signed-off-by: Alice Ferrazzi 
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: Shuah Khan 
+
+diff --git a/tools/testing/selftests/breakpoints/step_after_suspend_test.c b/tools/testing/selftests/breakpoints/step_after_suspend_test.c
+index 60b8a95dac26..bf37c1087f25 100644
+--- a/tools/testing/selftests/breakpoints/step_after_suspend_test.c
++++ b/tools/testing/selftests/breakpoints/step_after_suspend_test.c
+@@ -135,28 +135,21 @@ void suspend(void)
+ 	struct itimerspec spec = {};
+ 
+ 	power_state_fd = open("/sys/power/state", O_RDWR);
+-	if (power_state_fd < 0) {
+-		perror("open(\"/sys/power/state\") failed (is this test running as root?)");
+-		ksft_exit_fail();
+-	}
++	if (power_state_fd < 0)
++		ksft_exit_fail_msg(
++			"open(\"/sys/power/state\") failed (is this test running as root?)");
+ 
+ 	timerfd = timerfd_create(CLOCK_BOOTTIME_ALARM, 0);
+-	if (timerfd < 0) {
+-		perror("timerfd_create() failed");
+-		ksft_exit_fail();
+-	}
++	if (timerfd < 0)
++		ksft_exit_fail_msg("timerfd_create() failed");
+ 
+ 	spec.it_value.tv_sec = 5;
+ 	err = timerfd_settime(timerfd, 0, &spec, NULL);
+-	if (err < 0) {
+-		perror("timerfd_settime() failed");
+-		ksft_exit_fail();
+-	}
++	if (err < 0)
++		ksft_exit_fail_msg("timerfd_settime() failed");
+ 
+-	if (write(power_state_fd, "mem", strlen("mem")) != strlen("mem")) {
+-		perror("entering suspend failed");
+-		ksft_exit_fail();
+-	}
++	if (write(power_state_fd, "mem", strlen("mem")) != strlen("mem"))
++		ksft_exit_fail_msg("entering suspend failed");
+ 
+ 	close(timerfd);
+ 	close(power_state_fd);
+@@ -170,6 +163,9 @@ int main(int argc, char **argv)
+ 	cpu_set_t available_cpus;
+ 	int err;
+ 	int cpu;
++	char buf[10];
++
++	ksft_print_header();
+ 
+ 	while ((opt = getopt(argc, argv, "n")) != -1) {
+ 		switch (opt) {
+@@ -187,10 +183,8 @@ int main(int argc, char **argv)
+ 		suspend();
+ 
+ 	err = sched_getaffinity(0, sizeof(available_cpus), &available_cpus);
+-	if (err < 0) {
+-		perror("sched_getaffinity() failed");
+-		ksft_exit_fail();
+-	}
++	if (err < 0)
++		ksft_exit_fail_msg("sched_getaffinity() failed");
+ 
+ 	for (cpu = 0; cpu < CPU_SETSIZE; cpu++) {
+ 		bool test_success;
+@@ -199,18 +193,15 @@ int main(int argc, char **argv)
+ 			continue;
+ 
+ 		test_success = run_test(cpu);
+-		printf("CPU %d: ", cpu);
++		sprintf(buf, "CPU %d", cpu);
+ 		if (test_success) {
+-			printf("[OK]\n");
+-			ksft_inc_pass_cnt();
++			ksft_test_result_pass(buf);
+ 		} else {
+-			printf("[FAILED]\n");
+-			ksft_inc_fail_cnt();
++			ksft_test_result_fail(buf);
+ 			succeeded = false;
+ 		}
+ 	}
+ 
+-	ksft_print_cnts();
+ 	if (succeeded)
+ 		ksft_exit_pass();
+ 	else

commit 748e84b79af0121a39eb55f0cb5a727e08eb91b2
+Author: Paul Elder 
+Date:   Mon Jun 12 08:56:49 2017 +0200
+
+    kselftest: breakpoints: convert breakpoint_test to TAP13 output
+    
+    Make the breakpoints test output in the TAP13 format by using the
+    TAP13 output functions defined in kselftest.h
+    
+    Signed-off-by: Paul Elder 
+    Signed-off-by: Alice Ferrazzi 
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: Shuah Khan 
+
+diff --git a/tools/testing/selftests/breakpoints/breakpoint_test.c b/tools/testing/selftests/breakpoints/breakpoint_test.c
+index 120895ab5505..c02fc9a0e228 100644
+--- a/tools/testing/selftests/breakpoints/breakpoint_test.c
++++ b/tools/testing/selftests/breakpoints/breakpoint_test.c
+@@ -42,10 +42,8 @@ static void set_breakpoint_addr(void *addr, int n)
+ 
+ 	ret = ptrace(PTRACE_POKEUSER, child_pid,
+ 		     offsetof(struct user, u_debugreg[n]), addr);
+-	if (ret) {
+-		perror("Can't set breakpoint addr\n");
+-		ksft_exit_fail();
+-	}
++	if (ret)
++		ksft_exit_fail_msg("Can't set breakpoint addr");
+ }
+ 
+ static void toggle_breakpoint(int n, int type, int len,
+@@ -105,10 +103,8 @@ static void toggle_breakpoint(int n, int type, int len,
+ 
+ 	ret = ptrace(PTRACE_POKEUSER, child_pid,
+ 		     offsetof(struct user, u_debugreg[7]), dr7);
+-	if (ret) {
+-		perror("Can't set dr7");
+-		ksft_exit_fail();
+-	}
++	if (ret)
++		ksft_exit_fail_msg("Can't set dr7");
+ }
+ 
+ /* Dummy variables to test read/write accesses */
+@@ -264,26 +260,29 @@ static void check_success(const char *msg)
+ 	const char *msg2;
+ 	int child_nr_tests;
+ 	int status;
++	int ret;
+ 
+ 	/* Wait for the child to SIGTRAP */
+ 	wait(&status);
+ 
+ 	msg2 = "Failed";
++	ret = 0;
+ 
+ 	if (WSTOPSIG(status) == SIGTRAP) {
+ 		child_nr_tests = ptrace(PTRACE_PEEKDATA, child_pid,
+ 					&nr_tests, 0);
+ 		if (child_nr_tests == nr_tests)
+-			msg2 = "Ok";
+-		if (ptrace(PTRACE_POKEDATA, child_pid, &trapped, 1)) {
+-			perror("Can't poke\n");
+-			ksft_exit_fail();
+-		}
++			ret = 1;
++		if (ptrace(PTRACE_POKEDATA, child_pid, &trapped, 1))
++			ksft_exit_fail_msg("Can't poke");
+ 	}
+ 
+ 	nr_tests++;
+ 
+-	printf("%s [%s]\n", msg, msg2);
++	if (ret)
++		ksft_test_result_pass(msg);
++	else
++		ksft_test_result_fail(msg);
+ }
+ 
+ static void launch_instruction_breakpoints(char *buf, int local, int global)
+@@ -378,6 +377,8 @@ int main(int argc, char **argv)
+ 	pid_t pid;
+ 	int ret;
+ 
++	ksft_print_header();
++
+ 	pid = fork();
+ 	if (!pid) {
+ 		trigger_tests();

commit 326f57a4c378f4dacf8fbeb05a1decfeff74f54e
+Author: Paul Elder 
+Date:   Mon Jun 12 08:56:48 2017 +0200
+
+    kselftest: membarrier: convert to TAP13 output
+    
+    Make the membarrier test output in the TAP13 format by using the
+    TAP13 output functions defined in kselftest.h
+    
+    Signed-off-by: Paul Elder 
+    Signed-off-by: Alice Ferrazzi 
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: Shuah Khan 
+
+diff --git a/tools/testing/selftests/membarrier/membarrier_test.c b/tools/testing/selftests/membarrier/membarrier_test.c
+index 535f0fef4d0b..cae8c984dfb0 100644
+--- a/tools/testing/selftests/membarrier/membarrier_test.c
++++ b/tools/testing/selftests/membarrier/membarrier_test.c
+@@ -21,36 +21,42 @@ static int sys_membarrier(int cmd, int flags)
+ static enum test_membarrier_status test_membarrier_cmd_fail(void)
+ {
+ 	int cmd = -1, flags = 0;
++	const char *test_name = "membarrier command fail";
+ 
+ 	if (sys_membarrier(cmd, flags) != -1) {
+-		printf("membarrier: Wrong command should fail but passed.\n");
++		ksft_test_result_fail(test_name);
+ 		return TEST_MEMBARRIER_FAIL;
+ 	}
++
++	ksft_test_result_pass(test_name);
+ 	return TEST_MEMBARRIER_PASS;
+ }
+ 
+ static enum test_membarrier_status test_membarrier_flags_fail(void)
+ {
+ 	int cmd = MEMBARRIER_CMD_QUERY, flags = 1;
++	const char *test_name = "Wrong flags should fail";
+ 
+ 	if (sys_membarrier(cmd, flags) != -1) {
+-		printf("membarrier: Wrong flags should fail but passed.\n");
++		ksft_test_result_fail(test_name);
+ 		return TEST_MEMBARRIER_FAIL;
+ 	}
++
++	ksft_test_result_pass(test_name);
+ 	return TEST_MEMBARRIER_PASS;
+ }
+ 
+ static enum test_membarrier_status test_membarrier_success(void)
+ {
+ 	int cmd = MEMBARRIER_CMD_SHARED, flags = 0;
++	const char *test_name = "execute MEMBARRIER_CMD_SHARED";
+ 
+ 	if (sys_membarrier(cmd, flags) != 0) {
+-		printf("membarrier: Executing MEMBARRIER_CMD_SHARED failed. %s.\n",
+-				strerror(errno));
++		ksft_test_result_fail(test_name);
+ 		return TEST_MEMBARRIER_FAIL;
+ 	}
+ 
+-	printf("membarrier: MEMBARRIER_CMD_SHARED success.\n");
++	ksft_test_result_pass(test_name);
+ 	return TEST_MEMBARRIER_PASS;
+ }
+ 
+@@ -74,32 +80,30 @@ static enum test_membarrier_status test_membarrier_query(void)
+ {
+ 	int flags = 0, ret;
+ 
+-	printf("membarrier MEMBARRIER_CMD_QUERY ");
+ 	ret = sys_membarrier(MEMBARRIER_CMD_QUERY, flags);
+ 	if (ret < 0) {
+-		printf("failed. %s.\n", strerror(errno));
+-		switch (errno) {
+-		case ENOSYS:
++		if (errno == ENOSYS) {
+ 			/*
+ 			 * It is valid to build a kernel with
+ 			 * CONFIG_MEMBARRIER=n. However, this skips the tests.
+ 			 */
+-			return TEST_MEMBARRIER_SKIP;
+-		case EINVAL:
+-		default:
+-			return TEST_MEMBARRIER_FAIL;
++			ksft_test_result_skip("CONFIG_MEMBARRIER is not enabled\n");
++			return ksft_exit_skip();
+ 		}
++		ksft_test_result_fail("sys_membarrier() failed\n");
++		return TEST_MEMBARRIER_FAIL;
+ 	}
+ 	if (!(ret & MEMBARRIER_CMD_SHARED)) {
+-		printf("command MEMBARRIER_CMD_SHARED is not supported.\n");
++		ksft_test_result_fail("command MEMBARRIER_CMD_SHARED is not supported.\n");
+ 		return TEST_MEMBARRIER_FAIL;
+ 	}
+-	printf("syscall available.\n");
++	ksft_test_result_pass("sys_membarrier available");
+ 	return TEST_MEMBARRIER_PASS;
+ }
+ 
+ int main(int argc, char **argv)
+ {
++	ksft_print_header();
+ 	switch (test_membarrier_query()) {
+ 	case TEST_MEMBARRIER_FAIL:
+ 		return ksft_exit_fail();
+@@ -113,6 +117,5 @@ int main(int argc, char **argv)
+ 		return ksft_exit_skip();
+ 	}
+ 
+-	printf("membarrier: tests done!\n");
+ 	return ksft_exit_pass();
+ }

commit b6a4b66d845ae4c7f4eece419269c65ca332ba7b
+Author: Paul Elder 
+Date:   Mon Jun 12 08:56:47 2017 +0200
+
+    kselftest: add TAP13 conformant versions of ksft_* functions
+    
+    Add TAP13 conformat output functions to kselftest.h.
+    
+    Also add exit functions that output TAP13 exiting text, as well as
+    functions to keep track of testing progress.
+    
+    Signed-off-by: Paul Elder 
+    Signed-off-by: Alice Ferrazzi 
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: Shuah Khan 
+
+diff --git a/tools/testing/selftests/kselftest.h b/tools/testing/selftests/kselftest.h
+index ef1c80d67ac7..1d874a50d957 100644
+--- a/tools/testing/selftests/kselftest.h
++++ b/tools/testing/selftests/kselftest.h
+@@ -31,38 +31,82 @@ struct ksft_count {
+ 
+ static struct ksft_count ksft_cnt;
+ 
++static inline int ksft_test_num(void)
++{
++	return ksft_cnt.ksft_pass + ksft_cnt.ksft_fail +
++		ksft_cnt.ksft_xfail + ksft_cnt.ksft_xpass +
++		ksft_cnt.ksft_xskip;
++}
++
+ static inline void ksft_inc_pass_cnt(void) { ksft_cnt.ksft_pass++; }
+ static inline void ksft_inc_fail_cnt(void) { ksft_cnt.ksft_fail++; }
+ static inline void ksft_inc_xfail_cnt(void) { ksft_cnt.ksft_xfail++; }
+ static inline void ksft_inc_xpass_cnt(void) { ksft_cnt.ksft_xpass++; }
+ static inline void ksft_inc_xskip_cnt(void) { ksft_cnt.ksft_xskip++; }
+ 
++static inline void ksft_print_header(void)
++{
++	printf("TAP version 13\n");
++}
++
+ static inline void ksft_print_cnts(void)
+ {
+-	printf("Pass: %d Fail: %d Xfail: %d Xpass: %d, Xskip: %d\n",
+-		ksft_cnt.ksft_pass, ksft_cnt.ksft_fail,
+-		ksft_cnt.ksft_xfail, ksft_cnt.ksft_xpass,
+-		ksft_cnt.ksft_xskip);
++	printf("1..%d\n", ksft_test_num());
++}
++
++static inline void ksft_test_result_pass(const char *msg)
++{
++	ksft_cnt.ksft_pass++;
++	printf("ok %d %s\n", ksft_test_num(), msg);
++}
++
++static inline void ksft_test_result_fail(const char *msg)
++{
++	ksft_cnt.ksft_fail++;
++	printf("not ok %d %s\n", ksft_test_num(), msg);
++}
++
++static inline void ksft_test_result_skip(const char *msg)
++{
++	ksft_cnt.ksft_xskip++;
++	printf("ok %d # skip %s\n", ksft_test_num(), msg);
+ }
+ 
+ static inline int ksft_exit_pass(void)
+ {
++	ksft_print_cnts();
+ 	exit(KSFT_PASS);
+ }
++
+ static inline int ksft_exit_fail(void)
+ {
++	printf("Bail out!\n");
++	ksft_print_cnts();
+ 	exit(KSFT_FAIL);
+ }
++
++static inline int ksft_exit_fail_msg(const char *msg)
++{
++	printf("Bail out! %s\n", msg);
++	ksft_print_cnts();
++	exit(KSFT_FAIL);
++}
++
+ static inline int ksft_exit_xfail(void)
+ {
++	ksft_print_cnts();
+ 	exit(KSFT_XFAIL);
+ }
++
+ static inline int ksft_exit_xpass(void)
+ {
++	ksft_print_cnts();
+ 	exit(KSFT_XPASS);
+ }
++
+ static inline int ksft_exit_skip(void)
+ {
++	ksft_print_cnts();
+ 	exit(KSFT_SKIP);
+ }
+ 

\ No newline at end of file diff --git a/detail/48.html b/detail/48.html new file mode 100644 index 0000000..6b355f6 --- /dev/null +++ b/detail/48.html @@ -0,0 +1,519 @@ +

Patches contributed by Ohio University


commit f541fb7e20c848f947ca65fbf169efe69400c942
+Author: Samuel Jero 
+Date:   Sun Feb 26 18:22:02 2012 -0700
+
+    dccp: fix bug in sequence number validation during connection setup
+    
+    This fixes a bug in the sequence number validation during the initial handshake.
+    
+    The code did not treat the initial sequence numbers ISS and ISR as read-only and
+    did not keep state for GSR and GSS as required by the specification. This causes
+    problems with retransmissions during the initial handshake, causing the
+    budding connection to be reset.
+    
+    This patch now treats ISS/ISR as read-only and tracks GSS/GSR as required.
+    
+    Signed-off-by: Samuel Jero 
+    Signed-off-by: Gerrit Renker 
+
+diff --git a/include/linux/dccp.h b/include/linux/dccp.h
+index 710c04302a15..eaf95a023af4 100644
+--- a/include/linux/dccp.h
++++ b/include/linux/dccp.h
+@@ -376,8 +376,10 @@ static inline unsigned int dccp_hdr_len(const struct sk_buff *skb)
+ /**
+  * struct dccp_request_sock  -  represent DCCP-specific connection request
+  * @dreq_inet_rsk: structure inherited from
+- * @dreq_iss: initial sequence number sent on the Response (RFC 4340, 7.1)
+- * @dreq_isr: initial sequence number received on the Request
++ * @dreq_iss: initial sequence number, sent on the first Response (RFC 4340, 7.1)
++ * @dreq_gss: greatest sequence number sent (for retransmitted Responses)
++ * @dreq_isr: initial sequence number received in the first Request
++ * @dreq_gsr: greatest sequence number received (for retransmitted Request(s))
+  * @dreq_service: service code present on the Request (there is just one)
+  * @dreq_featneg: feature negotiation options for this connection
+  * The following two fields are analogous to the ones in dccp_sock:
+@@ -387,7 +389,9 @@ static inline unsigned int dccp_hdr_len(const struct sk_buff *skb)
+ struct dccp_request_sock {
+ 	struct inet_request_sock dreq_inet_rsk;
+ 	__u64			 dreq_iss;
++	__u64			 dreq_gss;
+ 	__u64			 dreq_isr;
++	__u64			 dreq_gsr;
+ 	__be32			 dreq_service;
+ 	struct list_head	 dreq_featneg;
+ 	__u32			 dreq_timestamp_echo;
+diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
+index 1c67fe8ff90d..caf6e1734b62 100644
+--- a/net/dccp/ipv4.c
++++ b/net/dccp/ipv4.c
+@@ -300,7 +300,8 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
+ 		 */
+ 		WARN_ON(req->sk);
+ 
+-		if (seq != dccp_rsk(req)->dreq_iss) {
++		if (!between48(seq, dccp_rsk(req)->dreq_iss,
++				    dccp_rsk(req)->dreq_gss)) {
+ 			NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
+ 			goto out;
+ 		}
+@@ -639,11 +640,12 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
+ 	 *
+ 	 * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie
+ 	 *
+-	 * In fact we defer setting S.GSR, S.SWL, S.SWH to
+-	 * dccp_create_openreq_child.
++	 * Setting S.SWL/S.SWH to is deferred to dccp_create_openreq_child().
+ 	 */
+ 	dreq->dreq_isr	   = dcb->dccpd_seq;
++	dreq->dreq_gsr	   = dreq->dreq_isr;
+ 	dreq->dreq_iss	   = dccp_v4_init_sequence(skb);
++	dreq->dreq_gss     = dreq->dreq_iss;
+ 	dreq->dreq_service = service;
+ 
+ 	if (dccp_v4_send_response(sk, req, NULL))
+diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
+index ce903f747e64..4dc588f520e0 100644
+--- a/net/dccp/ipv6.c
++++ b/net/dccp/ipv6.c
+@@ -193,7 +193,8 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ 		 */
+ 		WARN_ON(req->sk != NULL);
+ 
+-		if (seq != dccp_rsk(req)->dreq_iss) {
++		if (!between48(seq, dccp_rsk(req)->dreq_iss,
++				    dccp_rsk(req)->dreq_gss)) {
+ 			NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
+ 			goto out;
+ 		}
+@@ -440,11 +441,12 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
+ 	 *
+ 	 *   Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie
+ 	 *
+-	 *   In fact we defer setting S.GSR, S.SWL, S.SWH to
+-	 *   dccp_create_openreq_child.
++	 * Setting S.SWL/S.SWH to is deferred to dccp_create_openreq_child().
+ 	 */
+ 	dreq->dreq_isr	   = dcb->dccpd_seq;
++	dreq->dreq_gsr     = dreq->dreq_isr;
+ 	dreq->dreq_iss	   = dccp_v6_init_sequence(skb);
++	dreq->dreq_gss     = dreq->dreq_iss;
+ 	dreq->dreq_service = service;
+ 
+ 	if (dccp_v6_send_response(sk, req, NULL))
+diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c
+index 5a7f90bbffac..ea850ce35d4a 100644
+--- a/net/dccp/minisocks.c
++++ b/net/dccp/minisocks.c
+@@ -127,9 +127,11 @@ struct sock *dccp_create_openreq_child(struct sock *sk,
+ 		 *    activation below, as these windows all depend on the local
+ 		 *    and remote Sequence Window feature values (7.5.2).
+ 		 */
+-		newdp->dccps_gss = newdp->dccps_iss = dreq->dreq_iss;
++		newdp->dccps_iss = dreq->dreq_iss;
++		newdp->dccps_gss = dreq->dreq_gss;
+ 		newdp->dccps_gar = newdp->dccps_iss;
+-		newdp->dccps_gsr = newdp->dccps_isr = dreq->dreq_isr;
++		newdp->dccps_isr = dreq->dreq_isr;
++		newdp->dccps_gsr = dreq->dreq_gsr;
+ 
+ 		/*
+ 		 * Activate features: initialise CCIDs, sequence windows etc.
+@@ -164,9 +166,9 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
+ 	/* Check for retransmitted REQUEST */
+ 	if (dccp_hdr(skb)->dccph_type == DCCP_PKT_REQUEST) {
+ 
+-		if (after48(DCCP_SKB_CB(skb)->dccpd_seq, dreq->dreq_isr)) {
++		if (after48(DCCP_SKB_CB(skb)->dccpd_seq, dreq->dreq_gsr)) {
+ 			dccp_pr_debug("Retransmitted REQUEST\n");
+-			dreq->dreq_isr = DCCP_SKB_CB(skb)->dccpd_seq;
++			dreq->dreq_gsr = DCCP_SKB_CB(skb)->dccpd_seq;
+ 			/*
+ 			 * Send another RESPONSE packet
+ 			 * To protect against Request floods, increment retrans
+@@ -186,12 +188,14 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
+ 		goto drop;
+ 
+ 	/* Invalid ACK */
+-	if (DCCP_SKB_CB(skb)->dccpd_ack_seq != dreq->dreq_iss) {
++	if (!between48(DCCP_SKB_CB(skb)->dccpd_ack_seq,
++				dreq->dreq_iss, dreq->dreq_gss)) {
+ 		dccp_pr_debug("Invalid ACK number: ack_seq=%llu, "
+-			      "dreq_iss=%llu\n",
++			      "dreq_iss=%llu, dreq_gss=%llu\n",
+ 			      (unsigned long long)
+ 			      DCCP_SKB_CB(skb)->dccpd_ack_seq,
+-			      (unsigned long long) dreq->dreq_iss);
++			      (unsigned long long) dreq->dreq_iss,
++			      (unsigned long long) dreq->dreq_gss);
+ 		goto drop;
+ 	}
+ 
+diff --git a/net/dccp/output.c b/net/dccp/output.c
+index dede3edb8849..787367308797 100644
+--- a/net/dccp/output.c
++++ b/net/dccp/output.c
+@@ -408,10 +408,10 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
+ 	skb_dst_set(skb, dst_clone(dst));
+ 
+ 	dreq = dccp_rsk(req);
+-	if (inet_rsk(req)->acked)	/* increase ISS upon retransmission */
+-		dccp_inc_seqno(&dreq->dreq_iss);
++	if (inet_rsk(req)->acked)	/* increase GSS upon retransmission */
++		dccp_inc_seqno(&dreq->dreq_gss);
+ 	DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE;
+-	DCCP_SKB_CB(skb)->dccpd_seq  = dreq->dreq_iss;
++	DCCP_SKB_CB(skb)->dccpd_seq  = dreq->dreq_gss;
+ 
+ 	/* Resolve feature dependencies resulting from choice of CCID */
+ 	if (dccp_feat_server_ccid_dependencies(dreq))
+@@ -429,8 +429,8 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
+ 			   DCCP_SKB_CB(skb)->dccpd_opt_len) / 4;
+ 	dh->dccph_type	= DCCP_PKT_RESPONSE;
+ 	dh->dccph_x	= 1;
+-	dccp_hdr_set_seq(dh, dreq->dreq_iss);
+-	dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dreq->dreq_isr);
++	dccp_hdr_set_seq(dh, dreq->dreq_gss);
++	dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dreq->dreq_gsr);
+ 	dccp_hdr_response(skb)->dccph_resp_service = dreq->dreq_service;
+ 
+ 	dccp_csum_outgoing(skb);

commit d96a9e8dd04cf5ab2782ca6192e395c5ca373f7d
+Author: Samuel Jero 
+Date:   Sun Jul 24 20:57:49 2011 -0600
+
+    dccp ccid-2: check Ack Ratio when reducing cwnd
+    
+    This patch causes CCID-2 to check the Ack Ratio after reducing the congestion
+    window. If the Ack Ratio is greater than the congestion window, it is
+    reduced. This prevents timeouts caused by an Ack Ratio larger than the
+    congestion window.
+    
+    In this situation, we choose to set the Ack Ratio to half the congestion window
+    (or one if that's zero) so that if we loose one ack we don't trigger a timeout.
+    
+    Signed-off-by: Samuel Jero 
+    Acked-by: Gerrit Renker 
+
+diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
+index d9dbd9ffe8cd..67164bb6ae4d 100644
+--- a/net/dccp/ccids/ccid2.c
++++ b/net/dccp/ccids/ccid2.c
+@@ -101,6 +101,24 @@ static void ccid2_change_l_ack_ratio(struct sock *sk, u32 val)
+ 				   min_t(u32, val, DCCPF_ACK_RATIO_MAX));
+ }
+ 
++static void ccid2_check_l_ack_ratio(struct sock *sk)
++{
++	struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
++
++	/*
++	 * After a loss, idle period, application limited period, or RTO we
++	 * need to check that the ack ratio is still less than the congestion
++	 * window. Otherwise, we will send an entire congestion window of
++	 * packets and got no response because we haven't sent ack ratio
++	 * packets yet.
++	 * If the ack ratio does need to be reduced, we reduce it to half of
++	 * the congestion window (or 1 if that's zero) instead of to the
++	 * congestion window. This prevents problems if one ack is lost.
++	 */
++	if (dccp_feat_nn_get(sk, DCCPF_ACK_RATIO) > hc->tx_cwnd)
++		ccid2_change_l_ack_ratio(sk, hc->tx_cwnd/2 ? : 1U);
++}
++
+ static void ccid2_change_l_seq_window(struct sock *sk, u64 val)
+ {
+ 	dccp_feat_signal_nn_change(sk, DCCPF_SEQUENCE_WINDOW,
+@@ -187,6 +205,8 @@ static void ccid2_cwnd_application_limited(struct sock *sk, const u32 now)
+ 	}
+ 	hc->tx_cwnd_used  = 0;
+ 	hc->tx_cwnd_stamp = now;
++
++	ccid2_check_l_ack_ratio(sk);
+ }
+ 
+ /* This borrows the code of tcp_cwnd_restart() */
+@@ -205,6 +225,8 @@ static void ccid2_cwnd_restart(struct sock *sk, const u32 now)
+ 
+ 	hc->tx_cwnd_stamp = now;
+ 	hc->tx_cwnd_used  = 0;
++
++	ccid2_check_l_ack_ratio(sk);
+ }
+ 
+ static void ccid2_hc_tx_packet_sent(struct sock *sk, unsigned int len)
+@@ -461,9 +483,7 @@ static void ccid2_congestion_event(struct sock *sk, struct ccid2_seq *seqp)
+ 	hc->tx_cwnd      = hc->tx_cwnd / 2 ? : 1U;
+ 	hc->tx_ssthresh  = max(hc->tx_cwnd, 2U);
+ 
+-	/* Avoid spurious timeouts resulting from Ack Ratio > cwnd */
+-	if (dccp_sk(sk)->dccps_l_ack_ratio > hc->tx_cwnd)
+-		ccid2_change_l_ack_ratio(sk, hc->tx_cwnd);
++	ccid2_check_l_ack_ratio(sk);
+ }
+ 
+ static int ccid2_hc_tx_parse_options(struct sock *sk, u8 packet_type,

commit 0ce95dc792549e0cf704e74aa8acb15a401f8cca
+Author: Samuel Jero 
+Date:   Sun Jul 24 21:05:16 2011 -0600
+
+    dccp ccid-2: increment cwnd correctly
+    
+    This patch fixes an issue where CCID-2 will not increase the congestion
+    window for numerous RTTs after an idle period, application-limited period,
+    or a loss once the algorithm is in Congestion Avoidance.
+    
+    What happens is that, when CCID-2 is in Congestion Avoidance mode, it will
+    increase hc->tx_packets_acked by one for every packet and will increment cwnd
+    every cwnd packets. However, if there is now an idle period in the connection,
+    cwnd will be reduced, possibly below the slow start threshold. This will
+    cause the connection to go into Slow Start. However, in Slow Start CCID-2
+    performs this test to increment cwnd every second ack:
+    
+            ++hc->tx_packets_acked == 2
+    
+    Unfortunately, this will be incorrect, if cwnd previous to the idle period
+    was larger than 2 and if tx_packets_acked was close to cwnd. For example:
+            cwnd=50  and  tx_packets_acked=45.
+    
+    In this case, the current code, will increment tx_packets_acked until it
+    equals two, which will only be once tx_packets_acked (an unsigned 32-bit
+    integer) overflows.
+    
+    My fix is simply to change that test for tx_packets_acked greater than or
+    equal to two in slow start.
+    
+    Signed-off-by: Samuel Jero 
+    Acked-by: Gerrit Renker 
+
+diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
+index 9dbc4d88af16..d9dbd9ffe8cd 100644
+--- a/net/dccp/ccids/ccid2.c
++++ b/net/dccp/ccids/ccid2.c
+@@ -411,7 +411,7 @@ static void ccid2_new_ack(struct sock *sk, struct ccid2_seq *seqp,
+ 	if (hc->tx_cwnd < dp->dccps_l_seq_win &&
+ 	    r_seq_used < dp->dccps_r_seq_win) {
+ 		if (hc->tx_cwnd < hc->tx_ssthresh) {
+-			if (*maxincr > 0 && ++hc->tx_packets_acked == 2) {
++			if (*maxincr > 0 && ++hc->tx_packets_acked >= 2) {
+ 				hc->tx_cwnd += 1;
+ 				*maxincr    -= 1;
+ 				hc->tx_packets_acked = 0;

commit d346d886a4c7f771c184e73833133f23a18de884
+Author: Samuel Jero 
+Date:   Sun Jul 24 20:49:19 2011 -0600
+
+    dccp ccid-2: prevent cwnd > Sequence Window
+    
+    Add a check to prevent CCID-2 from increasing the cwnd greater than the
+    Sequence Window.
+    
+    When the congestion window becomes bigger than the Sequence Window, CCID-2
+    will attempt to keep more data in the network than the DCCP Sequence Window
+    code considers possible. This results in the Sequence Window code issuing
+    a Sync, thereby inducing needless overhead. Further, if this occurs at the
+    sender, CCID-2 will never detect the problem because the Acks it receives
+    will indicate no losses. I have seen this cause a drop of 1/3rd in throughput
+    for a connection.
+    
+    Also add code to adjust the Sequence Window to be about 5 times the number of
+    packets in the network (RFC 4340, 7.5.2) and to adjust the Ack Ratio so that
+    the remote Sequence Window will hold about 5 times the number of packets in
+    the network. This allows the congestion window to increase correctly without
+    being limited by the Sequence Window.
+    
+    Signed-off-by: Samuel Jero 
+    Acked-by: Gerrit Renker 
+
+diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
+index b51cc92376da..9dbc4d88af16 100644
+--- a/net/dccp/ccids/ccid2.c
++++ b/net/dccp/ccids/ccid2.c
+@@ -85,7 +85,6 @@ static int ccid2_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
+ 
+ static void ccid2_change_l_ack_ratio(struct sock *sk, u32 val)
+ {
+-	struct dccp_sock *dp = dccp_sk(sk);
+ 	u32 max_ratio = DIV_ROUND_UP(ccid2_hc_tx_sk(sk)->tx_cwnd, 2);
+ 
+ 	/*
+@@ -98,14 +97,15 @@ static void ccid2_change_l_ack_ratio(struct sock *sk, u32 val)
+ 		DCCP_WARN("Limiting Ack Ratio (%u) to %u\n", val, max_ratio);
+ 		val = max_ratio;
+ 	}
+-	if (val > DCCPF_ACK_RATIO_MAX)
+-		val = DCCPF_ACK_RATIO_MAX;
+-
+-	if (val == dp->dccps_l_ack_ratio)
+-		return;
++	dccp_feat_signal_nn_change(sk, DCCPF_ACK_RATIO,
++				   min_t(u32, val, DCCPF_ACK_RATIO_MAX));
++}
+ 
+-	ccid2_pr_debug("changing local ack ratio to %u\n", val);
+-	dp->dccps_l_ack_ratio = val;
++static void ccid2_change_l_seq_window(struct sock *sk, u64 val)
++{
++	dccp_feat_signal_nn_change(sk, DCCPF_SEQUENCE_WINDOW,
++				   clamp_val(val, DCCPF_SEQ_WMIN,
++						  DCCPF_SEQ_WMAX));
+ }
+ 
+ static void ccid2_hc_tx_rto_expire(unsigned long data)
+@@ -405,17 +405,37 @@ static void ccid2_new_ack(struct sock *sk, struct ccid2_seq *seqp,
+ 			  unsigned int *maxincr)
+ {
+ 	struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
+-
+-	if (hc->tx_cwnd < hc->tx_ssthresh) {
+-		if (*maxincr > 0 && ++hc->tx_packets_acked == 2) {
++	struct dccp_sock *dp = dccp_sk(sk);
++	int r_seq_used = hc->tx_cwnd / dp->dccps_l_ack_ratio;
++
++	if (hc->tx_cwnd < dp->dccps_l_seq_win &&
++	    r_seq_used < dp->dccps_r_seq_win) {
++		if (hc->tx_cwnd < hc->tx_ssthresh) {
++			if (*maxincr > 0 && ++hc->tx_packets_acked == 2) {
++				hc->tx_cwnd += 1;
++				*maxincr    -= 1;
++				hc->tx_packets_acked = 0;
++			}
++		} else if (++hc->tx_packets_acked >= hc->tx_cwnd) {
+ 			hc->tx_cwnd += 1;
+-			*maxincr    -= 1;
+ 			hc->tx_packets_acked = 0;
+ 		}
+-	} else if (++hc->tx_packets_acked >= hc->tx_cwnd) {
+-			hc->tx_cwnd += 1;
+-			hc->tx_packets_acked = 0;
+ 	}
++
++	/*
++	 * Adjust the local sequence window and the ack ratio to allow about
++	 * 5 times the number of packets in the network (RFC 4340 7.5.2)
++	 */
++	if (r_seq_used * CCID2_WIN_CHANGE_FACTOR >= dp->dccps_r_seq_win)
++		ccid2_change_l_ack_ratio(sk, dp->dccps_l_ack_ratio * 2);
++	else if (r_seq_used * CCID2_WIN_CHANGE_FACTOR < dp->dccps_r_seq_win/2)
++		ccid2_change_l_ack_ratio(sk, dp->dccps_l_ack_ratio / 2 ? : 1U);
++
++	if (hc->tx_cwnd * CCID2_WIN_CHANGE_FACTOR >= dp->dccps_l_seq_win)
++		ccid2_change_l_seq_window(sk, dp->dccps_l_seq_win * 2);
++	else if (hc->tx_cwnd * CCID2_WIN_CHANGE_FACTOR < dp->dccps_l_seq_win/2)
++		ccid2_change_l_seq_window(sk, dp->dccps_l_seq_win / 2);
++
+ 	/*
+ 	 * FIXME: RTT is sampled several times per acknowledgment (for each
+ 	 * entry in the Ack Vector), instead of once per Ack (as in TCP SACK).
+diff --git a/net/dccp/ccids/ccid2.h b/net/dccp/ccids/ccid2.h
+index f585d330e1e5..18c97543e522 100644
+--- a/net/dccp/ccids/ccid2.h
++++ b/net/dccp/ccids/ccid2.h
+@@ -43,6 +43,12 @@ struct ccid2_seq {
+ #define CCID2_SEQBUF_LEN 1024
+ #define CCID2_SEQBUF_MAX 128
+ 
++/*
++ * Multiple of congestion window to keep the sequence window at
++ * (RFC 4340 7.5.2)
++ */
++#define CCID2_WIN_CHANGE_FACTOR 5
++
+ /**
+  * struct ccid2_hc_tx_sock - CCID2 TX half connection
+  * @tx_{cwnd,ssthresh,pipe}: as per RFC 4341, section 5

commit a6444f4237af6c9981ddd45ab35a5c06d4e5a4d8
+Author: Samuel Jero 
+Date:   Sun Jul 24 21:06:37 2011 -0600
+
+    dccp: send Confirm options only once
+    
+    If a connection is in the OPEN state, remove feature negotiation Confirm
+    options from the list of options after sending them once; as such options
+    are NOT supposed to be retransmitted and are ONLY supposed to be sent in
+    response to a Change option (RFC 4340 6.2).
+    
+    Signed-off-by: Samuel Jero 
+    Acked-by: Gerrit Renker 
+
+diff --git a/net/dccp/feat.c b/net/dccp/feat.c
+index ad6f9e2cac1a..23cea0ee3101 100644
+--- a/net/dccp/feat.c
++++ b/net/dccp/feat.c
+@@ -665,11 +665,22 @@ int dccp_feat_insert_opts(struct dccp_sock *dp, struct dccp_request_sock *dreq,
+ 			return -1;
+ 		if (pos->needs_mandatory && dccp_insert_option_mandatory(skb))
+ 			return -1;
+-		/*
+-		 * Enter CHANGING after transmitting the Change option (6.6.2).
+-		 */
+-		if (pos->state == FEAT_INITIALISING)
+-			pos->state = FEAT_CHANGING;
++
++		if (skb->sk->sk_state == DCCP_OPEN &&
++		    (opt == DCCPO_CONFIRM_R || opt == DCCPO_CONFIRM_L)) {
++			/*
++			 * Confirms don't get retransmitted (6.6.3) once the
++			 * connection is in state OPEN
++			 */
++			dccp_feat_list_pop(pos);
++		} else {
++			/*
++			 * Enter CHANGING after transmitting the Change
++			 * option (6.6.2).
++			 */
++			if (pos->state == FEAT_INITIALISING)
++				pos->state = FEAT_CHANGING;
++		}
+ 	}
+ 	return 0;
+ }

commit 763dadd47c884853a22f2f19ea27e58431303ff3
+Author: Samuel Jero 
+Date:   Thu Dec 30 12:15:41 2010 +0100
+
+    dccp: fix bug in updating the GSR
+    
+    Currently dccp_check_seqno allows any valid packet to update the Greatest
+    Sequence Number Received, even if that packet's sequence number is less than
+    the current GSR. This patch adds a check to make sure that the new packet's
+    sequence number is greater than GSR.
+    
+    Signed-off-by: Samuel Jero 
+    Signed-off-by: Gerrit Renker 
+
+diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
+index 45087052d894..5fdb07229017 100644
+--- a/net/dccp/dccp.h
++++ b/net/dccp/dccp.h
+@@ -426,7 +426,8 @@ static inline void dccp_update_gsr(struct sock *sk, u64 seq)
+ {
+ 	struct dccp_sock *dp = dccp_sk(sk);
+ 
+-	dp->dccps_gsr = seq;
++	if (after48(seq, dp->dccps_gsr))
++		dp->dccps_gsr = seq;
+ 	/* Sequence validity window depends on remote Sequence Window (7.5.1) */
+ 	dp->dccps_swl = SUB48(ADD48(dp->dccps_gsr, 1), dp->dccps_r_seq_win / 4);
+ 	/*

commit 2cf5be93d1b704f342ad423a49f0e78d73939e66
+Author: Samuel Jero 
+Date:   Thu Dec 30 12:15:16 2010 +0100
+
+    dccp: fix return value for sequence-invalid packets
+    
+    Currently dccp_check_seqno returns 0 (indicating a valid packet) if the
+    acknowledgment number is out of bounds and the sync that RFC 4340 mandates at
+    this point is currently being rate-limited. This function should return -1,
+    indicating an invalid packet.
+    
+    Signed-off-by: Samuel Jero 
+    Acked-by: Gerrit Renker 
+
+diff --git a/net/dccp/input.c b/net/dccp/input.c
+index 15af247ea007..8cde009e8b85 100644
+--- a/net/dccp/input.c
++++ b/net/dccp/input.c
+@@ -260,7 +260,7 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb)
+ 		 */
+ 		if (time_before(now, (dp->dccps_rate_last +
+ 				      sysctl_dccp_sync_ratelimit)))
+-			return 0;
++			return -1;
+ 
+ 		DCCP_WARN("Step 6 failed for %s packet, "
+ 			  "(LSWL(%llu) <= P.seqno(%llu) <= S.SWH(%llu)) and "

\ No newline at end of file diff --git a/detail/5.html b/detail/5.html new file mode 100644 index 0000000..8c97f48 --- /dev/null +++ b/detail/5.html @@ -0,0 +1,82871 @@ +

Patches contributed by University of South Carolina


commit 35e9a9f93994d7f7d12afa41169c7ba05513721b
+Author: Mike Christie 
+Date:   Mon Apr 20 22:42:24 2015 -0500
+
+    SCSI: add 1024 max sectors black list flag
+    
+    This works around a issue with qnap iscsi targets not handling large IOs
+    very well.
+    
+    The target returns:
+    
+    VPD INQUIRY: Block limits page (SBC)
+      Maximum compare and write length: 1 blocks
+      Optimal transfer length granularity: 1 blocks
+      Maximum transfer length: 4294967295 blocks
+      Optimal transfer length: 4294967295 blocks
+      Maximum prefetch, xdread, xdwrite transfer length: 0 blocks
+      Maximum unmap LBA count: 8388607
+      Maximum unmap block descriptor count: 1
+      Optimal unmap granularity: 16383
+      Unmap granularity alignment valid: 0
+      Unmap granularity alignment: 0
+      Maximum write same length: 0xffffffff blocks
+      Maximum atomic transfer length: 0
+      Atomic alignment: 0
+      Atomic transfer length granularity: 0
+    
+    and it is *sometimes* able to handle at least one IO of size up to 8 MB. We
+    have seen in traces where it will sometimes work, but other times it
+    looks like it fails and it looks like it returns failures if we send
+    multiple large IOs sometimes. Also it looks like it can return 2 different
+    errors. It will sometimes send iscsi reject errors indicating out of
+    resources or it will send invalid cdb illegal requests check conditions.
+    And then when it sends iscsi rejects it does not seem to handle retries
+    when there are command sequence holes, so I could not just add code to
+    try and gracefully handle that error code.
+    
+    The problem is that we do not have a good contact for the company,
+    so we are not able to determine under what conditions it returns
+    which error and why it sometimes works.
+    
+    So, this patch just adds a new black list flag to set targets like this to
+    the old max safe sectors of 1024. The max_hw_sectors changes added in 3.19
+    caused this regression, so I also ccing stable.
+    
+    Reported-by: Christian Hesse 
+    Signed-off-by: Mike Christie 
+    Cc: stable@vger.kernel.org
+    Reviewed-by: Christoph Hellwig 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
+index 262ab837a704..9f77d23239a2 100644
+--- a/drivers/scsi/scsi_devinfo.c
++++ b/drivers/scsi/scsi_devinfo.c
+@@ -226,6 +226,7 @@ static struct {
+ 	{"PIONEER", "CD-ROM DRM-624X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
+ 	{"Promise", "VTrak E610f", NULL, BLIST_SPARSELUN | BLIST_NO_RSOC},
+ 	{"Promise", "", NULL, BLIST_SPARSELUN},
++	{"QNAP", "iSCSI Storage", NULL, BLIST_MAX_1024},
+ 	{"QUANTUM", "XP34301", "1071", BLIST_NOTQ},
+ 	{"REGAL", "CDC-4X", NULL, BLIST_MAX5LUN | BLIST_SINGLELUN},
+ 	{"SanDisk", "ImageMate CF-SD1", NULL, BLIST_FORCELUN},
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+index 60aae01caa89..6efab1c455e1 100644
+--- a/drivers/scsi/scsi_scan.c
++++ b/drivers/scsi/scsi_scan.c
+@@ -897,6 +897,12 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
+ 	 */
+ 	if (*bflags & BLIST_MAX_512)
+ 		blk_queue_max_hw_sectors(sdev->request_queue, 512);
++	/*
++	 * Max 1024 sector transfer length for targets that report incorrect
++	 * max/optimal lengths and relied on the old block layer safe default
++	 */
++	else if (*bflags & BLIST_MAX_1024)
++		blk_queue_max_hw_sectors(sdev->request_queue, 1024);
+ 
+ 	/*
+ 	 * Some devices may not want to have a start command automatically
+diff --git a/include/scsi/scsi_devinfo.h b/include/scsi/scsi_devinfo.h
+index 183eaab7c380..96e3f56519e7 100644
+--- a/include/scsi/scsi_devinfo.h
++++ b/include/scsi/scsi_devinfo.h
+@@ -36,5 +36,6 @@
+ 					     for sequential scan */
+ #define BLIST_TRY_VPD_PAGES	0x10000000 /* Attempt to read VPD pages */
+ #define BLIST_NO_RSOC		0x20000000 /* don't try to issue RSOC */
++#define BLIST_MAX_1024		0x40000000 /* maximum 1024 sector cdb length */
+ 
+ #endif

commit b815fc12d4dd2b5586184fb4f867caff05a810d4
+Author: Mike Christie 
+Date:   Fri Apr 10 02:47:27 2015 -0500
+
+    iscsi target: fix oops when adding reject pdu
+    
+    This fixes a oops due to a double list add when adding a reject PDU for
+    iscsit_allocate_iovecs allocation failures. The cmd has already been
+    added to the conn_cmd_list in iscsit_setup_scsi_cmd, so this has us call
+    iscsit_reject_cmd.
+    
+    Note that for ERL0 the reject PDU is not actually sent, so this patch
+    is not completely tested. Just verified we do not oops. The problem is the
+    add reject functions return -1 which is returned all the way up to
+    iscsi_target_rx_thread which for ERL0 will drop the connection.
+    
+    Signed-off-by: Mike Christie 
+    Cc:  # v3.10+
+    Signed-off-by: Nicholas Bellinger 
+
+diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
+index d5f66be6988e..77d64251af40 100644
+--- a/drivers/target/iscsi/iscsi_target.c
++++ b/drivers/target/iscsi/iscsi_target.c
+@@ -1181,7 +1181,7 @@ iscsit_handle_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
+ 	 * traditional iSCSI block I/O.
+ 	 */
+ 	if (iscsit_allocate_iovecs(cmd) < 0) {
+-		return iscsit_add_reject_cmd(cmd,
++		return iscsit_reject_cmd(cmd,
+ 				ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
+ 	}
+ 	immed_data = cmd->immediate_data;

commit 28072ad50ca7328bd99f9dba94ac27c723da0053
+Author: Mike Christie 
+Date:   Wed Jan 28 03:46:53 2015 -0600
+
+    scsi: fix device handler detach oops
+    
+    This fixes a regression caused by commit 1d5203 ("scsi: handle more device
+    handler setup/teardown in common code").
+    
+    The bug is that the alua detach() callout will try to access the
+    sddev->scsi_dh_data, but we have already set it to NULL. This patch
+    moves the clearing of that field to after detach() is called.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Christoph Hellwig 
+
+diff --git a/drivers/scsi/device_handler/scsi_dh.c b/drivers/scsi/device_handler/scsi_dh.c
+index 1dba62c5cf6a..1efebc9eedfb 100644
+--- a/drivers/scsi/device_handler/scsi_dh.c
++++ b/drivers/scsi/device_handler/scsi_dh.c
+@@ -136,11 +136,12 @@ static void __detach_handler (struct kref *kref)
+ 	struct scsi_device_handler *scsi_dh = scsi_dh_data->scsi_dh;
+ 	struct scsi_device *sdev = scsi_dh_data->sdev;
+ 
++	scsi_dh->detach(sdev);
++
+ 	spin_lock_irq(sdev->request_queue->queue_lock);
+ 	sdev->scsi_dh_data = NULL;
+ 	spin_unlock_irq(sdev->request_queue->queue_lock);
+ 
+-	scsi_dh->detach(sdev);
+ 	sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", scsi_dh->name);
+ 	module_put(scsi_dh->module);
+ }

commit 89baaa570ab0b476db09408d209578cfed700e9f
+Author: Mike Christie 
+Date:   Thu Oct 16 01:50:19 2014 -0500
+
+    libceph: use memalloc flags for net IO
+    
+    This patch has ceph's lib code use the memalloc flags.
+    
+    If the VM layer needs to write data out to free up memory to handle new
+    allocation requests, the block layer must be able to make forward progress.
+    To handle that requirement we use structs like mempools to reserve memory for
+    objects like bios and requests.
+    
+    The problem is when we send/receive block layer requests over the network
+    layer, net skb allocations can fail and the system can lock up.
+    To solve this, the memalloc related flags were added. NBD, iSCSI
+    and NFS uses these flags to tell the network/vm layer that it should
+    use memory reserves to fullfill allcation requests for structs like
+    skbs.
+    
+    I am running ceph in a bunch of VMs in my laptop, so this patch was
+    not tested very harshly.
+    
+    Signed-off-by: Mike Christie 
+    Reviewed-by: Ilya Dryomov 
+
+diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c
+index 559c9f619c20..8d1653caffdb 100644
+--- a/net/ceph/messenger.c
++++ b/net/ceph/messenger.c
+@@ -484,7 +484,7 @@ static int ceph_tcp_connect(struct ceph_connection *con)
+ 			       IPPROTO_TCP, &sock);
+ 	if (ret)
+ 		return ret;
+-	sock->sk->sk_allocation = GFP_NOFS;
++	sock->sk->sk_allocation = GFP_NOFS | __GFP_MEMALLOC;
+ 
+ #ifdef CONFIG_LOCKDEP
+ 	lockdep_set_class(&sock->sk->sk_lock, &socket_class);
+@@ -509,6 +509,9 @@ static int ceph_tcp_connect(struct ceph_connection *con)
+ 
+ 		return ret;
+ 	}
++
++	sk_set_memalloc(sock->sk);
++
+ 	con->sock = sock;
+ 	return 0;
+ }
+@@ -2769,8 +2772,11 @@ static void con_work(struct work_struct *work)
+ {
+ 	struct ceph_connection *con = container_of(work, struct ceph_connection,
+ 						   work.work);
++	unsigned long pflags = current->flags;
+ 	bool fault;
+ 
++	current->flags |= PF_MEMALLOC;
++
+ 	mutex_lock(&con->mutex);
+ 	while (true) {
+ 		int ret;
+@@ -2824,6 +2830,8 @@ static void con_work(struct work_struct *work)
+ 		con_fault_finish(con);
+ 
+ 	con->ops->put(con);
++
++	tsk_restore_flags(current, pflags, PF_MEMALLOC);
+ }
+ 
+ /*

commit a41a9ad3bbf61fae0b6bfb232153da60d14fdbd9
+Author: Mike Christie 
+Date:   Mon Sep 29 13:55:41 2014 -0500
+
+    be2iscsi: check ip buffer before copying
+    
+    Dan Carpenter found a issue where be2iscsi would copy the ip
+    from userspace to the driver buffer before checking the len
+    of the data being copied:
+    http://marc.info/?l=linux-scsi&m=140982651504251&w=2
+    
+    This patch just has us only copy what we the driver buffer
+    can support.
+    
+    Cc: 
+    Tested-by: John Soni Jose 
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Christoph Hellwig 
+
+diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c
+index 8478506739fb..681d4e8f003a 100644
+--- a/drivers/scsi/be2iscsi/be_mgmt.c
++++ b/drivers/scsi/be2iscsi/be_mgmt.c
+@@ -943,17 +943,20 @@ mgmt_static_ip_modify(struct beiscsi_hba *phba,
+ 
+ 	if (ip_action == IP_ACTION_ADD) {
+ 		memcpy(req->ip_params.ip_record.ip_addr.addr, ip_param->value,
+-		       ip_param->len);
++		       sizeof(req->ip_params.ip_record.ip_addr.addr));
+ 
+ 		if (subnet_param)
+ 			memcpy(req->ip_params.ip_record.ip_addr.subnet_mask,
+-			       subnet_param->value, subnet_param->len);
++			       subnet_param->value,
++			       sizeof(req->ip_params.ip_record.ip_addr.subnet_mask));
+ 	} else {
+ 		memcpy(req->ip_params.ip_record.ip_addr.addr,
+-		       if_info->ip_addr.addr, ip_param->len);
++		       if_info->ip_addr.addr,
++		       sizeof(req->ip_params.ip_record.ip_addr.addr));
+ 
+ 		memcpy(req->ip_params.ip_record.ip_addr.subnet_mask,
+-		       if_info->ip_addr.subnet_mask, ip_param->len);
++		       if_info->ip_addr.subnet_mask,
++		       sizeof(req->ip_params.ip_record.ip_addr.subnet_mask));
+ 	}
+ 
+ 	rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
+@@ -981,7 +984,7 @@ static int mgmt_modify_gateway(struct beiscsi_hba *phba, uint8_t *gt_addr,
+ 	req->action = gtway_action;
+ 	req->ip_addr.ip_type = BE2_IPV4;
+ 
+-	memcpy(req->ip_addr.addr, gt_addr, param_len);
++	memcpy(req->ip_addr.addr, gt_addr, sizeof(req->ip_addr.addr));
+ 
+ 	return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
+ }

commit 4bfb8ebf4c21f372a8677f9aa99963985e9e6539
+Author: Mike Christie 
+Date:   Mon Sep 29 13:55:42 2014 -0500
+
+    iscsi_tcp: export port being used
+    
+    This just has iscsi_tcp support ISCSI_PARAM_LOCAL_PORT which
+    exports the local port being used by the iscsi connection.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Christoph Hellwig 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index a669f2d11c31..427af0f24b0f 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -726,13 +726,18 @@ static int iscsi_sw_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ 	switch(param) {
+ 	case ISCSI_PARAM_CONN_PORT:
+ 	case ISCSI_PARAM_CONN_ADDRESS:
++	case ISCSI_PARAM_LOCAL_PORT:
+ 		spin_lock_bh(&conn->session->frwd_lock);
+ 		if (!tcp_sw_conn || !tcp_sw_conn->sock) {
+ 			spin_unlock_bh(&conn->session->frwd_lock);
+ 			return -ENOTCONN;
+ 		}
+-		rc = kernel_getpeername(tcp_sw_conn->sock,
+-					(struct sockaddr *)&addr, &len);
++		if (param == ISCSI_PARAM_LOCAL_PORT)
++			rc = kernel_getsockname(tcp_sw_conn->sock,
++						(struct sockaddr *)&addr, &len);
++		else
++			rc = kernel_getpeername(tcp_sw_conn->sock,
++						(struct sockaddr *)&addr, &len);
+ 		spin_unlock_bh(&conn->session->frwd_lock);
+ 		if (rc)
+ 			return rc;
+@@ -895,6 +900,7 @@ static umode_t iscsi_sw_tcp_attr_is_visible(int param_type, int param)
+ 		case ISCSI_PARAM_DATADGST_EN:
+ 		case ISCSI_PARAM_CONN_ADDRESS:
+ 		case ISCSI_PARAM_CONN_PORT:
++		case ISCSI_PARAM_LOCAL_PORT:
+ 		case ISCSI_PARAM_EXP_STATSN:
+ 		case ISCSI_PARAM_PERSISTENT_ADDRESS:
+ 		case ISCSI_PARAM_PERSISTENT_PORT:
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 191b59793519..0d8bc6c66650 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -3505,6 +3505,7 @@ int iscsi_conn_get_addr_param(struct sockaddr_storage *addr,
+ 			len = sprintf(buf, "%pI6\n", &sin6->sin6_addr);
+ 		break;
+ 	case ISCSI_PARAM_CONN_PORT:
++	case ISCSI_PARAM_LOCAL_PORT:
+ 		if (sin)
+ 			len = sprintf(buf, "%hu\n", be16_to_cpu(sin->sin_port));
+ 		else

commit db9bfd64b14a3a8f1868d2164518fdeab1b26ad1
+Author: Mike Christie 
+Date:   Wed Sep 3 00:00:39 2014 -0500
+
+    [SCSI] libiscsi: fix potential buffer overrun in __iscsi_conn_send_pdu
+    
+    This patches fixes a potential buffer overrun in __iscsi_conn_send_pdu.
+    This function is used by iscsi drivers and userspace to send iscsi PDUs/
+    commands. For login commands, we have a set buffer size. For all other
+    commands we do not support data buffers.
+    
+    This was reported by Dan Carpenter here:
+    http://www.spinics.net/lists/linux-scsi/msg66838.html
+    
+    Reported-by: Dan Carpenter 
+    Signed-off-by: Mike Christie 
+    Reviewed-by: Sagi Grimberg 
+    Signed-off-by: Christoph Hellwig 
+    Cc: stable@vger.kernel.org
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index ea025e4806b6..191b59793519 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -717,11 +717,21 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			return NULL;
+ 		}
+ 
++		if (data_size > ISCSI_DEF_MAX_RECV_SEG_LEN) {
++			iscsi_conn_printk(KERN_ERR, conn, "Invalid buffer len of %u for login task. Max len is %u\n", data_size, ISCSI_DEF_MAX_RECV_SEG_LEN);
++			return NULL;
++		}
++
+ 		task = conn->login_task;
+ 	} else {
+ 		if (session->state != ISCSI_STATE_LOGGED_IN)
+ 			return NULL;
+ 
++		if (data_size != 0) {
++			iscsi_conn_printk(KERN_ERR, conn, "Can not send data buffer of len %u for op 0x%x\n", data_size, opcode);
++			return NULL;
++		}
++
+ 		BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
+ 		BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
+ 

commit cbaa42213461e9a722a391b3800d7c111de7049b
+Author: Mike Christie 
+Date:   Wed Sep 3 00:00:39 2014 -0500
+
+    libiscsi: fix potential buffer overrun in __iscsi_conn_send_pdu
+    
+    This patches fixes a potential buffer overrun in __iscsi_conn_send_pdu.
+    This function is used by iscsi drivers and userspace to send iscsi PDUs/
+    commands. For login commands, we have a set buffer size. For all other
+    commands we do not support data buffers.
+    
+    This was reported by Dan Carpenter here:
+    http://www.spinics.net/lists/linux-scsi/msg66838.html
+    
+    Reported-by: Dan Carpenter 
+    Signed-off-by: Mike Christie 
+    Reviewed-by: Sagi Grimberg 
+    Signed-off-by: Christoph Hellwig 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index ea025e4806b6..191b59793519 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -717,11 +717,21 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			return NULL;
+ 		}
+ 
++		if (data_size > ISCSI_DEF_MAX_RECV_SEG_LEN) {
++			iscsi_conn_printk(KERN_ERR, conn, "Invalid buffer len of %u for login task. Max len is %u\n", data_size, ISCSI_DEF_MAX_RECV_SEG_LEN);
++			return NULL;
++		}
++
+ 		task = conn->login_task;
+ 	} else {
+ 		if (session->state != ISCSI_STATE_LOGGED_IN)
+ 			return NULL;
+ 
++		if (data_size != 0) {
++			iscsi_conn_printk(KERN_ERR, conn, "Can not send data buffer of len %u for op 0x%x\n", data_size, opcode);
++			return NULL;
++		}
++
+ 		BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
+ 		BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
+ 

commit bfb5087924921f147d4c5d731cbc8c3a069bed0b
+Author: Mike Christie 
+Date:   Sun Aug 3 18:37:52 2014 -0500
+
+    iscsi class: Fix freeing of skb in get host error path
+    
+    If get_host_stats failes we are using kfree to free the
+    skb. We should be using kfree_skb.
+    
+    This patch was made over Christoph's scsi-queue drivers-for-3.17 branch.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Christoph Hellwig 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 534d3fb87658..67d43e35693d 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -3468,7 +3468,7 @@ iscsi_get_host_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
+ 
+ 		err = transport->get_host_stats(shost, buf, host_stats_size);
+ 		if (err) {
+-			kfree(skbhost_stats);
++			kfree_skb(skbhost_stats);
+ 			goto exit_host_stats;
+ 		}
+ 

commit 09ff742c62a6bbfca7aed485f44c8b16f52e1096
+Author: Mike Christie 
+Date:   Sat Jul 12 15:51:51 2014 -0500
+
+    libiscsi: return new error code when nop times out
+    
+    When a iscsi nop as ping timedout we were failing with the
+    common connection error code, ISCSI_ERR_CONN_FAILED. This
+    patch adds a new error code for this problem so can properly
+    track/distinguish in userspace.
+    
+    Signed-off-by: Mike Christie 
+    Acked-by: Vikas Chaudhary 
+    Reviewed-by: Hannes Reinecke 
+    Signed-off-by: Christoph Hellwig 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index f9f3a1224dfa..ea025e4806b6 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -2097,7 +2097,7 @@ static void iscsi_check_transport_timeouts(unsigned long data)
+ 				  conn->ping_timeout, conn->recv_timeout,
+ 				  last_recv, conn->last_ping, jiffies);
+ 		spin_unlock(&session->frwd_lock);
+-		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
++		iscsi_conn_failure(conn, ISCSI_ERR_NOP_TIMEDOUT);
+ 		return;
+ 	}
+ 
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index fd0421c6d40a..95ed9424a11a 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -527,6 +527,7 @@ enum iscsi_err {
+ 	ISCSI_ERR_XMIT_FAILED		= ISCSI_ERR_BASE + 19,
+ 	ISCSI_ERR_TCP_CONN_CLOSE	= ISCSI_ERR_BASE + 20,
+ 	ISCSI_ERR_SCSI_EH_SESSION_RST	= ISCSI_ERR_BASE + 21,
++	ISCSI_ERR_NOP_TIMEDOUT		= ISCSI_ERR_BASE + 22,
+ };
+ 
+ /*

commit 719e5874d0777b575720249d3ece3dbde3efb452
+Author: Mike Christie 
+Date:   Sat Jul 12 15:51:50 2014 -0500
+
+    iscsi class: fix get_host_stats return code when not supported
+    
+    When the get_host_stats call was not supported we were
+    returing EINVAL. This has us return ENOSYS, because for
+    software iscsi drivers where there is no host it is ok to not
+    have this callout.
+    
+    Signed-off-by: Mike Christie 
+    Acked-by: Vikas Chaudhary 
+    Reviewed-by: Hannes Reinecke 
+    Signed-off-by: Christoph Hellwig 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 14bfa53c6f7d..534d3fb87658 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -3429,7 +3429,7 @@ iscsi_get_host_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
+ 	char *buf;
+ 
+ 	if (!transport->get_host_stats)
+-		return -EINVAL;
++		return -ENOSYS;
+ 
+ 	priv = iscsi_if_transport_lookup(transport);
+ 	if (!priv)

commit 2f7608fc5e6c8a70df3ce31406feee70a42458ba
+Author: Mike Christie 
+Date:   Sat Jul 12 15:51:48 2014 -0500
+
+    iscsi class: fix get_host_stats error handling
+    
+    iscsi_get_host_stats was dropping the error code returned
+    by drivers like qla4xxx.
+    
+    Signed-off-by: Mike Christie 
+    Acked-by: Vikas Chaudhary 
+    Signed-off-by: Christoph Hellwig 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index b481e62a12cc..14bfa53c6f7d 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -3467,6 +3467,10 @@ iscsi_get_host_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
+ 		memset(buf, 0, host_stats_size);
+ 
+ 		err = transport->get_host_stats(shost, buf, host_stats_size);
++		if (err) {
++			kfree(skbhost_stats);
++			goto exit_host_stats;
++		}
+ 
+ 		actual_size = nlmsg_total_size(sizeof(*ev) + host_stats_size);
+ 		skb_trim(skbhost_stats, NLMSG_ALIGN(actual_size));

commit 7f3976f03ff128fd5aa8dc22e4784d03311ebd09
+Author: Mike Christie 
+Date:   Sat Jul 12 15:51:49 2014 -0500
+
+    qla4xxx: fix get_host_stats error propagation
+    
+    qla4xxx was not always returning -EXYZ error codes when
+    qla4xxx_get_host_stats failed.
+    
+    Signed-off-by: Mike Christie 
+    Acked-by: Vikas Chaudhary 
+    Reviewed-by: Hannes Reinecke 
+    Signed-off-by: Christoph Hellwig 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index 82b46ee8e7c1..199fcf79a051 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -1050,6 +1050,7 @@ static int qla4xxx_get_host_stats(struct Scsi_Host *shost, char *buf, int len)
+ 	if (!ql_iscsi_stats) {
+ 		ql4_printk(KERN_ERR, ha,
+ 			   "Unable to allocate memory for iscsi stats\n");
++		ret = -ENOMEM;
+ 		goto exit_host_stats;
+ 	}
+ 
+@@ -1058,6 +1059,7 @@ static int qla4xxx_get_host_stats(struct Scsi_Host *shost, char *buf, int len)
+ 	if (ret != QLA_SUCCESS) {
+ 		ql4_printk(KERN_ERR, ha,
+ 			   "Unable to retrieve iscsi stats\n");
++		ret = -EIO;
+ 		goto exit_host_stats;
+ 	}
+ 	host_stats->mactx_frames = le64_to_cpu(ql_iscsi_stats->mac_tx_frames);

commit 915aafd856d1a4ef1dea30c2b20ada03c93be4d7
+Author: Mike Christie 
+Date:   Tue Jul 1 11:24:38 2014 -0500
+
+    bnx2i, be2iscsi: fix custom stats length
+    
+    The custom stats is an array with custom_length indicating the length
+    of the array. This patch fixes bnx2i and be2iscsi's setting of the
+    custom stats length. They both just have the one, eh_abort_cnt, so that should
+    be in the first entry of the custom array and custom_length should then
+    be one.
+    
+    Reported-by: Rickard Strandqvist 
+    Signed-off-by: Mike Christie 
+    Acked-by: Vikas Chaudhary 
+    Acked-by: Eddie Wai 
+    Signed-off-by: Christoph Hellwig 
+
+diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
+index fd284ff36ecf..86162811812d 100644
+--- a/drivers/scsi/be2iscsi/be_iscsi.c
++++ b/drivers/scsi/be2iscsi/be_iscsi.c
+@@ -914,7 +914,7 @@ void beiscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn,
+ 	stats->r2t_pdus = conn->r2t_pdus_cnt;
+ 	stats->digest_err = 0;
+ 	stats->timeout_err = 0;
+-	stats->custom_length = 0;
++	stats->custom_length = 1;
+ 	strcpy(stats->custom[0].desc, "eh_abort_cnt");
+ 	stats->custom[0].value = conn->eh_abort_cnt;
+ }
+diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
+index 166543f7ef55..9bd9b8148689 100644
+--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
++++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
+@@ -1643,12 +1643,11 @@ static void bnx2i_conn_get_stats(struct iscsi_cls_conn *cls_conn,
+ 	stats->r2t_pdus = conn->r2t_pdus_cnt;
+ 	stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
+ 	stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
+-	stats->custom_length = 3;
+-	strcpy(stats->custom[2].desc, "eh_abort_cnt");
+-	stats->custom[2].value = conn->eh_abort_cnt;
+ 	stats->digest_err = 0;
+ 	stats->timeout_err = 0;
+-	stats->custom_length = 0;
++	strcpy(stats->custom[0].desc, "eh_abort_cnt");
++	stats->custom[0].value = conn->eh_abort_cnt;
++	stats->custom_length = 1;
+ }
+ 
+ 

commit eee2b5c840d93f704554f4a2884cef72742f22e2
+Author: Mike Christie 
+Date:   Fri Feb 7 00:41:42 2014 -0600
+
+    [SCSI] iscsi_tcp: check for valid session before accessing
+    
+    Check that the session is setup before accessing its
+    connection. This fixes a oops where userspace tries
+    to get the ip address before the session is bound to
+    a host.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 12b351213c59..bfb6d07d87f0 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -759,6 +759,9 @@ static int iscsi_sw_tcp_host_get_param(struct Scsi_Host *shost,
+ 
+ 	switch (param) {
+ 	case ISCSI_HOST_PARAM_IPADDRESS:
++		if (!session)
++			return -ENOTCONN;
++
+ 		spin_lock_bh(&session->frwd_lock);
+ 		conn = session->leadconn;
+ 		if (!conn) {

commit 46a84c6516fa09bb8e4cc0c7998ccd4cb5e876a1
+Author: Mike Christie 
+Date:   Fri Feb 7 00:41:39 2014 -0600
+
+    [SCSI] libiscsi: remove unneeded queue work when max_cmdsn is increased
+    
+    iscsi_queuecommand will only take in commands that can fit in the
+    current window. So, if a command is on the cmdqueue then it can
+    fit in the current window. If a command is on the mgmtqueue, then
+    we are setting the immediate bit so they will also fit in the
+    window. As a result, we never need to to do a iscsi_conn_queue_work
+    when the maxCmdSn is increased.
+    
+    What should happen is that a command will complete the window will
+    be increased, then the scsi layer will send us more commands by
+    running the scsi_device queues.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 8738b989a801..5b8605ca42fa 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -110,16 +110,8 @@ static void __iscsi_update_cmdsn(struct iscsi_session *session,
+ 		session->exp_cmdsn = exp_cmdsn;
+ 
+ 	if (max_cmdsn != session->max_cmdsn &&
+-	    !iscsi_sna_lt(max_cmdsn, session->max_cmdsn)) {
++	    !iscsi_sna_lt(max_cmdsn, session->max_cmdsn))
+ 		session->max_cmdsn = max_cmdsn;
+-		/*
+-		 * if the window closed with IO queued, then kick the
+-		 * xmit thread
+-		 */
+-		if (!list_empty(&session->leadconn->cmdqueue) ||
+-		    !list_empty(&session->leadconn->mgmtqueue))
+-			iscsi_conn_queue_work(session->leadconn);
+-	}
+ }
+ 
+ void iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)

commit 126e964a444f125bd428757fb88c24c730f6fcf9
+Author: Mike Christie 
+Date:   Thu Dec 19 01:16:21 2013 -0600
+
+    [SCSI] be2iscsi: fix bad if expression
+    
+    https://bugzilla.kernel.org/show_bug.cgi?id=67091
+    
+    Cc: Jayamohan Kallickal 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
+index 1f375051483a..5642a9b250c2 100644
+--- a/drivers/scsi/be2iscsi/be_main.c
++++ b/drivers/scsi/be2iscsi/be_main.c
+@@ -325,7 +325,7 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
+ 		if (!abrt_task->sc || abrt_task->state == ISCSI_TASK_FREE)
+ 			continue;
+ 
+-		if (abrt_task->sc->device->lun != abrt_task->sc->device->lun)
++		if (sc->device->lun != abrt_task->sc->device->lun)
+ 			continue;
+ 
+ 		/* Invalidate WRB Posted for this Task */

commit 7652113c2f508b1c8176640dcd034730fe79bc48
+Author: Mike Christie 
+Date:   Wed Sep 18 08:33:55 2013 -0600
+
+    If the queue is dying then we only call the rq->end_io callout.
+    This leaves bios setup on the request, because the caller assumes when
+    the blk_execute_rq_nowait/blk_execute_rq call has completed that
+    the rq->bios have been cleaned up.
+    
+    This patch has blk_execute_rq_nowait use __blk_end_request_all
+    to free bios and also call rq->end_io.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/blk-exec.c b/block/blk-exec.c
+index e70621396129..ae4f27d7944e 100644
+--- a/block/blk-exec.c
++++ b/block/blk-exec.c
+@@ -68,9 +68,9 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
+ 	spin_lock_irq(q->queue_lock);
+ 
+ 	if (unlikely(blk_queue_dying(q))) {
++		rq->cmd_flags |= REQ_QUIET; 
+ 		rq->errors = -ENXIO;
+-		if (rq->end_io)
+-			rq->end_io(rq, rq->errors);
++		__blk_end_request_all(rq, rq->errors);
+ 		spin_unlock_irq(q->queue_lock);
+ 		return;
+ 	}

commit 86e92ad299fb0be359efdd61812944497d4d8d52
+Author: Mike Christie 
+Date:   Fri Jun 14 04:56:14 2013 -0500
+
+    dlm: disable nagle for SCTP
+    
+    For TCP we disable Nagle and I cannot think of why it would be needed
+    for SCTP. When disabled it seems to improve dlm_lock operations like it
+    does for TCP.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: David Teigland 
+
+diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
+index a4fad32bb788..4f539dd9b1e9 100644
+--- a/fs/dlm/lowcomms.c
++++ b/fs/dlm/lowcomms.c
+@@ -1346,6 +1346,7 @@ static int sctp_listen_for_all(void)
+ 	int result = -EINVAL, num = 1, i, addr_len;
+ 	struct connection *con = nodeid2con(0, GFP_NOFS);
+ 	int bufsize = NEEDED_RMEM;
++	int one = 1;
+ 
+ 	if (!con)
+ 		return -ENOMEM;
+@@ -1380,6 +1381,11 @@ static int sctp_listen_for_all(void)
+ 		goto create_delsock;
+ 	}
+ 
++	result = kernel_setsockopt(sock, SOL_SCTP, SCTP_NODELAY, (char *)&one,
++				   sizeof(one));
++	if (result < 0)
++		log_print("Could not set SCTP NODELAY error %d\n", result);
++
+ 	/* Init con struct */
+ 	sock->sk->sk_user_data = con;
+ 	con->sock = sock;

commit 5d6898714fe2ce485e95ac74479ed40ebd8d5748
+Author: Mike Christie 
+Date:   Fri Jun 14 04:56:13 2013 -0500
+
+    dlm: retry failed SCTP sends
+    
+    Currently if a SCTP send fails, we lose the data we were trying
+    to send because the writequeue_entry is released when we do the send.
+    When this happens other nodes will then hang waiting for a reply.
+    
+    This adds support for SCTP to retry the send operation.
+    
+    I also removed the retry limit for SCTP use, because we want
+    to make sure we try every path during init time and for longer
+    failures we want to continually retry in case paths come back up
+    while trying other paths. We will do this until userspace tells us
+    to stop.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: David Teigland 
+
+diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
+index 56015c9e8d00..a4fad32bb788 100644
+--- a/fs/dlm/lowcomms.c
++++ b/fs/dlm/lowcomms.c
+@@ -607,15 +607,56 @@ static void sctp_init_failed(void)
+ 	mutex_unlock(&connections_lock);
+ }
+ 
++static void retry_failed_sctp_send(struct connection *recv_con,
++				   struct sctp_send_failed *sn_send_failed,
++				   char *buf)
++{
++	int len = sn_send_failed->ssf_length - sizeof(struct sctp_send_failed);
++	struct dlm_mhandle *mh;
++	struct connection *con;
++	char *retry_buf;
++	int nodeid = sn_send_failed->ssf_info.sinfo_ppid;
++
++	log_print("Retry sending %d bytes to node id %d", len, nodeid);
++
++	con = nodeid2con(nodeid, 0);
++	if (!con) {
++		log_print("Could not look up con for nodeid %d\n",
++			  nodeid);
++		return;
++	}
++
++	mh = dlm_lowcomms_get_buffer(nodeid, len, GFP_NOFS, &retry_buf);
++	if (!mh) {
++		log_print("Could not allocate buf for retry.");
++		return;
++	}
++	memcpy(retry_buf, buf + sizeof(struct sctp_send_failed), len);
++	dlm_lowcomms_commit_buffer(mh);
++
++	/*
++	 * If we got a assoc changed event before the send failed event then
++	 * we only need to retry the send.
++	 */
++	if (con->sctp_assoc) {
++		if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags))
++			queue_work(send_workqueue, &con->swork);
++	} else
++		sctp_init_failed_foreach(con);
++}
++
+ /* Something happened to an association */
+ static void process_sctp_notification(struct connection *con,
+ 				      struct msghdr *msg, char *buf)
+ {
+ 	union sctp_notification *sn = (union sctp_notification *)buf;
+ 
+-	if (sn->sn_header.sn_type == SCTP_ASSOC_CHANGE) {
++	switch (sn->sn_header.sn_type) {
++	case SCTP_SEND_FAILED:
++		retry_failed_sctp_send(con, &sn->sn_send_failed, buf);
++		break;
++	case SCTP_ASSOC_CHANGE:
+ 		switch (sn->sn_assoc_change.sac_state) {
+-
+ 		case SCTP_COMM_UP:
+ 		case SCTP_RESTART:
+ 		{
+@@ -713,14 +754,10 @@ static void process_sctp_notification(struct connection *con,
+ 		}
+ 		break;
+ 
+-		/* We don't know which INIT failed, so clear the PENDING flags
+-		 * on them all.  if assoc_id is zero then it will then try
+-		 * again */
+-
+ 		case SCTP_CANT_STR_ASSOC:
+ 		{
++			/* Will retry init when we get the send failed notification */
+ 			log_print("Can't start SCTP association - retrying");
+-			sctp_init_failed();
+ 		}
+ 		break;
+ 
+@@ -729,6 +766,8 @@ static void process_sctp_notification(struct connection *con,
+ 				  (int)sn->sn_assoc_change.sac_assoc_id,
+ 				  sn->sn_assoc_change.sac_state);
+ 		}
++	default:
++		; /* fall through */
+ 	}
+ }
+ 
+@@ -988,6 +1027,24 @@ static void free_entry(struct writequeue_entry *e)
+ 	kfree(e);
+ }
+ 
++/*
++ * writequeue_entry_complete - try to delete and free write queue entry
++ * @e: write queue entry to try to delete
++ * @completed: bytes completed
++ *
++ * writequeue_lock must be held.
++ */
++static void writequeue_entry_complete(struct writequeue_entry *e, int completed)
++{
++	e->offset += completed;
++	e->len -= completed;
++
++	if (e->len == 0 && e->users == 0) {
++		list_del(&e->list);
++		free_entry(e);
++	}
++}
++
+ /* Initiate an SCTP association.
+    This is a special case of send_to_sock() in that we don't yet have a
+    peeled-off socket for this association, so we use the listening socket
+@@ -1007,16 +1064,14 @@ static void sctp_init_assoc(struct connection *con)
+ 	int addrlen;
+ 	struct kvec iov[1];
+ 
++	mutex_lock(&con->sock_mutex);
+ 	if (test_and_set_bit(CF_INIT_PENDING, &con->flags))
+-		return;
+-
+-	if (con->retries++ > MAX_CONNECT_RETRIES)
+-		return;
++		goto unlock;
+ 
+ 	if (nodeid_to_addr(con->nodeid, NULL, (struct sockaddr *)&rem_addr,
+ 			   con->try_new_addr)) {
+ 		log_print("no address for nodeid %d", con->nodeid);
+-		return;
++		goto unlock;
+ 	}
+ 	base_con = nodeid2con(0, 0);
+ 	BUG_ON(base_con == NULL);
+@@ -1034,17 +1089,17 @@ static void sctp_init_assoc(struct connection *con)
+ 	if (list_empty(&con->writequeue)) {
+ 		spin_unlock(&con->writequeue_lock);
+ 		log_print("writequeue empty for nodeid %d", con->nodeid);
+-		return;
++		goto unlock;
+ 	}
+ 
+ 	e = list_first_entry(&con->writequeue, struct writequeue_entry, list);
+ 	len = e->len;
+ 	offset = e->offset;
+-	spin_unlock(&con->writequeue_lock);
+ 
+ 	/* Send the first block off the write queue */
+ 	iov[0].iov_base = page_address(e->page)+offset;
+ 	iov[0].iov_len = len;
++	spin_unlock(&con->writequeue_lock);
+ 
+ 	if (rem_addr.ss_family == AF_INET) {
+ 		struct sockaddr_in *sin = (struct sockaddr_in *)&rem_addr;
+@@ -1060,7 +1115,7 @@ static void sctp_init_assoc(struct connection *con)
+ 	cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
+ 	sinfo = CMSG_DATA(cmsg);
+ 	memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo));
+-	sinfo->sinfo_ppid = cpu_to_le32(dlm_our_nodeid());
++	sinfo->sinfo_ppid = cpu_to_le32(con->nodeid);
+ 	outmessage.msg_controllen = cmsg->cmsg_len;
+ 	sinfo->sinfo_flags |= SCTP_ADDR_OVER;
+ 
+@@ -1075,15 +1130,12 @@ static void sctp_init_assoc(struct connection *con)
+ 	}
+ 	else {
+ 		spin_lock(&con->writequeue_lock);
+-		e->offset += ret;
+-		e->len -= ret;
+-
+-		if (e->len == 0 && e->users == 0) {
+-			list_del(&e->list);
+-			free_entry(e);
+-		}
++		writequeue_entry_complete(e, ret);
+ 		spin_unlock(&con->writequeue_lock);
+ 	}
++
++unlock:
++	mutex_unlock(&con->sock_mutex);
+ }
+ 
+ /* Connect a new socket to its peer */
+@@ -1533,13 +1585,7 @@ static void send_to_sock(struct connection *con)
+ 		}
+ 
+ 		spin_lock(&con->writequeue_lock);
+-		e->offset += ret;
+-		e->len -= ret;
+-
+-		if (e->len == 0 && e->users == 0) {
+-			list_del(&e->list);
+-			free_entry(e);
+-		}
++		writequeue_entry_complete(e, ret);
+ 	}
+ 	spin_unlock(&con->writequeue_lock);
+ out:

commit 98e1b60ecc441625c91013e88f14cbd1b3c1fa08
+Author: Mike Christie 
+Date:   Fri Jun 14 04:56:12 2013 -0500
+
+    dlm: try other IPs when sctp init assoc fails
+    
+    Currently, if we cannot create a association to the first IP addr
+    that is added to DLM, the SCTP init assoc code will just retry
+    the same IP. This patch adds a simple failover schemes where we
+    will try one of the addresses that was passed into DLM.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: David Teigland 
+
+diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
+index 87e68dd01479..56015c9e8d00 100644
+--- a/fs/dlm/lowcomms.c
++++ b/fs/dlm/lowcomms.c
+@@ -126,6 +126,7 @@ struct connection {
+ 	struct connection *othercon;
+ 	struct work_struct rwork; /* Receive workqueue */
+ 	struct work_struct swork; /* Send workqueue */
++	bool try_new_addr;
+ };
+ #define sock2con(x) ((struct connection *)(x)->sk_user_data)
+ 
+@@ -144,6 +145,7 @@ struct dlm_node_addr {
+ 	struct list_head list;
+ 	int nodeid;
+ 	int addr_count;
++	int curr_addr_index;
+ 	struct sockaddr_storage *addr[DLM_MAX_ADDR_COUNT];
+ };
+ 
+@@ -310,7 +312,7 @@ static int addr_compare(struct sockaddr_storage *x, struct sockaddr_storage *y)
+ }
+ 
+ static int nodeid_to_addr(int nodeid, struct sockaddr_storage *sas_out,
+-			  struct sockaddr *sa_out)
++			  struct sockaddr *sa_out, bool try_new_addr)
+ {
+ 	struct sockaddr_storage sas;
+ 	struct dlm_node_addr *na;
+@@ -320,8 +322,16 @@ static int nodeid_to_addr(int nodeid, struct sockaddr_storage *sas_out,
+ 
+ 	spin_lock(&dlm_node_addrs_spin);
+ 	na = find_node_addr(nodeid);
+-	if (na && na->addr_count)
+-		memcpy(&sas, na->addr[0], sizeof(struct sockaddr_storage));
++	if (na && na->addr_count) {
++		if (try_new_addr) {
++			na->curr_addr_index++;
++			if (na->curr_addr_index == na->addr_count)
++				na->curr_addr_index = 0;
++		}
++
++		memcpy(&sas, na->addr[na->curr_addr_index ],
++			sizeof(struct sockaddr_storage));
++	}
+ 	spin_unlock(&dlm_node_addrs_spin);
+ 
+ 	if (!na)
+@@ -353,19 +363,22 @@ static int addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid)
+ {
+ 	struct dlm_node_addr *na;
+ 	int rv = -EEXIST;
++	int addr_i;
+ 
+ 	spin_lock(&dlm_node_addrs_spin);
+ 	list_for_each_entry(na, &dlm_node_addrs, list) {
+ 		if (!na->addr_count)
+ 			continue;
+ 
+-		if (!addr_compare(na->addr[0], addr))
+-			continue;
+-
+-		*nodeid = na->nodeid;
+-		rv = 0;
+-		break;
++		for (addr_i = 0; addr_i < na->addr_count; addr_i++) {
++			if (addr_compare(na->addr[addr_i], addr)) {
++				*nodeid = na->nodeid;
++				rv = 0;
++				goto unlock;
++			}
++		}
+ 	}
++unlock:
+ 	spin_unlock(&dlm_node_addrs_spin);
+ 	return rv;
+ }
+@@ -561,6 +574,21 @@ static void sctp_send_shutdown(sctp_assoc_t associd)
+ 
+ static void sctp_init_failed_foreach(struct connection *con)
+ {
++
++	/*
++	 * Don't try to recover base con and handle race where the
++	 * other node's assoc init creates a assoc and we get that
++	 * notification, then we get a notification that our attempt
++	 * failed due. This happens when we are still trying the primary
++	 * address, but the other node has already tried secondary addrs
++	 * and found one that worked.
++	 */
++	if (!con->nodeid || con->sctp_assoc)
++		return;
++
++	log_print("Retrying SCTP association init for node %d\n", con->nodeid);
++
++	con->try_new_addr = true;
+ 	con->sctp_assoc = 0;
+ 	if (test_and_clear_bit(CF_INIT_PENDING, &con->flags)) {
+ 		if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags))
+@@ -663,6 +691,7 @@ static void process_sctp_notification(struct connection *con,
+ 				 nodeid, (int)sn->sn_assoc_change.sac_assoc_id);
+ 
+ 			new_con->sctp_assoc = sn->sn_assoc_change.sac_assoc_id;
++			new_con->try_new_addr = false;
+ 			/* Send any pending writes */
+ 			clear_bit(CF_CONNECT_PENDING, &new_con->flags);
+ 			clear_bit(CF_INIT_PENDING, &new_con->flags);
+@@ -984,7 +1013,8 @@ static void sctp_init_assoc(struct connection *con)
+ 	if (con->retries++ > MAX_CONNECT_RETRIES)
+ 		return;
+ 
+-	if (nodeid_to_addr(con->nodeid, NULL, (struct sockaddr *)&rem_addr)) {
++	if (nodeid_to_addr(con->nodeid, NULL, (struct sockaddr *)&rem_addr,
++			   con->try_new_addr)) {
+ 		log_print("no address for nodeid %d", con->nodeid);
+ 		return;
+ 	}
+@@ -1016,6 +1046,14 @@ static void sctp_init_assoc(struct connection *con)
+ 	iov[0].iov_base = page_address(e->page)+offset;
+ 	iov[0].iov_len = len;
+ 
++	if (rem_addr.ss_family == AF_INET) {
++		struct sockaddr_in *sin = (struct sockaddr_in *)&rem_addr;
++		log_print("Trying to connect to %pI4", &sin->sin_addr.s_addr);
++	} else {
++		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&rem_addr;
++		log_print("Trying to connect to %pI6", &sin6->sin6_addr);
++	}
++
+ 	cmsg = CMSG_FIRSTHDR(&outmessage);
+ 	cmsg->cmsg_level = IPPROTO_SCTP;
+ 	cmsg->cmsg_type = SCTP_SNDRCV;
+@@ -1024,6 +1062,7 @@ static void sctp_init_assoc(struct connection *con)
+ 	memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo));
+ 	sinfo->sinfo_ppid = cpu_to_le32(dlm_our_nodeid());
+ 	outmessage.msg_controllen = cmsg->cmsg_len;
++	sinfo->sinfo_flags |= SCTP_ADDR_OVER;
+ 
+ 	ret = kernel_sendmsg(base_con->sock, &outmessage, iov, 1, len);
+ 	if (ret < 0) {
+@@ -1076,7 +1115,7 @@ static void tcp_connect_to_sock(struct connection *con)
+ 		goto out_err;
+ 
+ 	memset(&saddr, 0, sizeof(saddr));
+-	result = nodeid_to_addr(con->nodeid, &saddr, NULL);
++	result = nodeid_to_addr(con->nodeid, &saddr, NULL, false);
+ 	if (result < 0) {
+ 		log_print("no address for nodeid %d", con->nodeid);
+ 		goto out_err;

commit b390ca38d27bd3d2f409e64a6f13d6ff67eb4825
+Author: Mike Christie 
+Date:   Fri Jun 14 04:56:11 2013 -0500
+
+    dlm: clear correct bit during sctp init failure handling
+    
+    We should be testing and cleaing the init pending bit because later
+    when sctp_init_assoc is recalled it will be checking that it is not set
+    and set the bit.
+    
+    We do not want to touch CF_CONNECT_PENDING here because we will queue
+    swork and process_send_sockets will then call the connect_action function.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: David Teigland 
+
+diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
+index 1536599fde8c..87e68dd01479 100644
+--- a/fs/dlm/lowcomms.c
++++ b/fs/dlm/lowcomms.c
+@@ -562,7 +562,7 @@ static void sctp_send_shutdown(sctp_assoc_t associd)
+ static void sctp_init_failed_foreach(struct connection *con)
+ {
+ 	con->sctp_assoc = 0;
+-	if (test_and_clear_bit(CF_CONNECT_PENDING, &con->flags)) {
++	if (test_and_clear_bit(CF_INIT_PENDING, &con->flags)) {
+ 		if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags))
+ 			queue_work(send_workqueue, &con->swork);
+ 	}

commit e1631d0c48ca5ba9878f5923ffe58ef6fd2d5fda
+Author: Mike Christie 
+Date:   Fri Jun 14 04:56:10 2013 -0500
+
+    dlm: set sctp assoc id during setup
+    
+    sctp_assoc was not getting set so later lookups failed.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: David Teigland 
+
+diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
+index efbe7af42002..1536599fde8c 100644
+--- a/fs/dlm/lowcomms.c
++++ b/fs/dlm/lowcomms.c
+@@ -662,6 +662,7 @@ static void process_sctp_notification(struct connection *con,
+ 			log_print("connecting to %d sctp association %d",
+ 				 nodeid, (int)sn->sn_assoc_change.sac_assoc_id);
+ 
++			new_con->sctp_assoc = sn->sn_assoc_change.sac_assoc_id;
+ 			/* Send any pending writes */
+ 			clear_bit(CF_CONNECT_PENDING, &new_con->flags);
+ 			clear_bit(CF_INIT_PENDING, &new_con->flags);

commit efad7e6b1a28be599836c8f15ec04f99a98fb04c
+Author: Mike Christie 
+Date:   Fri Jun 14 04:56:09 2013 -0500
+
+    dlm: clear correct init bit during sctp setup
+    
+    We were clearing the base con's init pending flags, but the
+    con for the node was the one with the pending bit set.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: David Teigland 
+
+diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
+index d0ccd2fd79eb..efbe7af42002 100644
+--- a/fs/dlm/lowcomms.c
++++ b/fs/dlm/lowcomms.c
+@@ -664,7 +664,7 @@ static void process_sctp_notification(struct connection *con,
+ 
+ 			/* Send any pending writes */
+ 			clear_bit(CF_CONNECT_PENDING, &new_con->flags);
+-			clear_bit(CF_INIT_PENDING, &con->flags);
++			clear_bit(CF_INIT_PENDING, &new_con->flags);
+ 			if (!test_and_set_bit(CF_WRITE_PENDING, &new_con->flags)) {
+ 				queue_work(send_workqueue, &new_con->swork);
+ 			}

commit 8526cb114f771851d84425d85d8735a6e0816ba2
+Author: Mike Christie 
+Date:   Mon May 6 12:06:56 2013 -0500
+
+    [SCSI] iscsi class, qla4xxx: fix sess/conn refcounting when find fns are used
+    
+    This fixes a bug where the iscsi class/driver did not do a put_device
+    when a sess/conn device was found. This also simplifies the interface
+    by not having to pass in some arguments that were duplicated and did
+    not need to be exported.
+    
+    Reported-by: Zhao Hongjiang 
+    Signed-off-by: Mike Christie 
+    Acked-by: Vikas Chaudhary 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index d777332dbed8..4d231c12463e 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -5605,6 +5605,7 @@ static int qla4xxx_sysfs_ddb_add(struct Scsi_Host *shost, const char *buf,
+ 		ql4_printk(KERN_ERR, ha,
+ 			   "%s: A non-persistent entry %s found\n",
+ 			   __func__, dev->kobj.name);
++		put_device(dev);
+ 		goto exit_ddb_add;
+ 	}
+ 
+@@ -6112,8 +6113,7 @@ qla4xxx_sysfs_ddb_get_param(struct iscsi_bus_flash_session *fnode_sess,
+ 	int parent_type, parent_index = 0xffff;
+ 	int rc = 0;
+ 
+-	dev = iscsi_find_flashnode_conn(fnode_sess, NULL,
+-					iscsi_is_flashnode_conn_dev);
++	dev = iscsi_find_flashnode_conn(fnode_sess);
+ 	if (!dev)
+ 		return -EIO;
+ 
+@@ -6347,6 +6347,8 @@ qla4xxx_sysfs_ddb_get_param(struct iscsi_bus_flash_session *fnode_sess,
+ 		rc = -ENOSYS;
+ 		break;
+ 	}
++
++	put_device(dev);
+ 	return rc;
+ }
+ 
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 475265a51a51..133926b1bb78 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -1019,8 +1019,7 @@ static int flashnode_match_index(struct device *dev, void *data)
+ /**
+  * iscsi_get_flashnode_by_index -finds flashnode session entry by index
+  * @shost: pointer to host data
+- * @data: pointer to data containing value to use for comparison
+- * @fn: function pointer that does actual comparison
++ * @idx: index to match
+  *
+  * Finds the flashnode session object for the passed index
+  *
+@@ -1029,13 +1028,13 @@ static int flashnode_match_index(struct device *dev, void *data)
+  *  %NULL on failure
+  */
+ static struct iscsi_bus_flash_session *
+-iscsi_get_flashnode_by_index(struct Scsi_Host *shost, void *data,
+-			     int (*fn)(struct device *dev, void *data))
++iscsi_get_flashnode_by_index(struct Scsi_Host *shost, uint32_t idx)
+ {
+ 	struct iscsi_bus_flash_session *fnode_sess = NULL;
+ 	struct device *dev;
+ 
+-	dev = device_find_child(&shost->shost_gendev, data, fn);
++	dev = device_find_child(&shost->shost_gendev, &idx,
++				flashnode_match_index);
+ 	if (dev)
+ 		fnode_sess = iscsi_dev_to_flash_session(dev);
+ 
+@@ -1059,18 +1058,13 @@ struct device *
+ iscsi_find_flashnode_sess(struct Scsi_Host *shost, void *data,
+ 			  int (*fn)(struct device *dev, void *data))
+ {
+-	struct device *dev;
+-
+-	dev = device_find_child(&shost->shost_gendev, data, fn);
+-	return dev;
++	return device_find_child(&shost->shost_gendev, data, fn);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_find_flashnode_sess);
+ 
+ /**
+  * iscsi_find_flashnode_conn - finds flashnode connection entry
+  * @fnode_sess: pointer to parent flashnode session entry
+- * @data: pointer to data containing value to use for comparison
+- * @fn: function pointer that does actual comparison
+  *
+  * Finds the flashnode connection object comparing the data passed using logic
+  * defined in passed function pointer
+@@ -1080,14 +1074,10 @@ EXPORT_SYMBOL_GPL(iscsi_find_flashnode_sess);
+  *  %NULL on failure
+  */
+ struct device *
+-iscsi_find_flashnode_conn(struct iscsi_bus_flash_session *fnode_sess,
+-			  void *data,
+-			  int (*fn)(struct device *dev, void *data))
++iscsi_find_flashnode_conn(struct iscsi_bus_flash_session *fnode_sess)
+ {
+-	struct device *dev;
+-
+-	dev = device_find_child(&fnode_sess->dev, data, fn);
+-	return dev;
++	return device_find_child(&fnode_sess->dev, NULL,
++				 iscsi_is_flashnode_conn_dev);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_find_flashnode_conn);
+ 
+@@ -2808,7 +2798,7 @@ static int iscsi_set_flashnode_param(struct iscsi_transport *transport,
+ 	struct iscsi_bus_flash_session *fnode_sess;
+ 	struct iscsi_bus_flash_conn *fnode_conn;
+ 	struct device *dev;
+-	uint32_t *idx;
++	uint32_t idx;
+ 	int err = 0;
+ 
+ 	if (!transport->set_flashnode_param) {
+@@ -2824,25 +2814,27 @@ static int iscsi_set_flashnode_param(struct iscsi_transport *transport,
+ 		goto put_host;
+ 	}
+ 
+-	idx = &ev->u.set_flashnode.flashnode_idx;
+-	fnode_sess = iscsi_get_flashnode_by_index(shost, idx,
+-						  flashnode_match_index);
++	idx = ev->u.set_flashnode.flashnode_idx;
++	fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
+ 	if (!fnode_sess) {
+ 		pr_err("%s could not find flashnode %u for host no %u\n",
+-		       __func__, *idx, ev->u.set_flashnode.host_no);
++		       __func__, idx, ev->u.set_flashnode.host_no);
+ 		err = -ENODEV;
+ 		goto put_host;
+ 	}
+ 
+-	dev = iscsi_find_flashnode_conn(fnode_sess, NULL,
+-					iscsi_is_flashnode_conn_dev);
++	dev = iscsi_find_flashnode_conn(fnode_sess);
+ 	if (!dev) {
+ 		err = -ENODEV;
+-		goto put_host;
++		goto put_sess;
+ 	}
+ 
+ 	fnode_conn = iscsi_dev_to_flash_conn(dev);
+ 	err = transport->set_flashnode_param(fnode_sess, fnode_conn, data, len);
++	put_device(dev);
++
++put_sess:
++	put_device(&fnode_sess->dev);
+ 
+ put_host:
+ 	scsi_host_put(shost);
+@@ -2891,7 +2883,7 @@ static int iscsi_del_flashnode(struct iscsi_transport *transport,
+ {
+ 	struct Scsi_Host *shost;
+ 	struct iscsi_bus_flash_session *fnode_sess;
+-	uint32_t *idx;
++	uint32_t idx;
+ 	int err = 0;
+ 
+ 	if (!transport->del_flashnode) {
+@@ -2907,17 +2899,17 @@ static int iscsi_del_flashnode(struct iscsi_transport *transport,
+ 		goto put_host;
+ 	}
+ 
+-	idx = &ev->u.del_flashnode.flashnode_idx;
+-	fnode_sess = iscsi_get_flashnode_by_index(shost, idx,
+-						  flashnode_match_index);
++	idx = ev->u.del_flashnode.flashnode_idx;
++	fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
+ 	if (!fnode_sess) {
+ 		pr_err("%s could not find flashnode %u for host no %u\n",
+-		       __func__, *idx, ev->u.del_flashnode.host_no);
++		       __func__, idx, ev->u.del_flashnode.host_no);
+ 		err = -ENODEV;
+ 		goto put_host;
+ 	}
+ 
+ 	err = transport->del_flashnode(fnode_sess);
++	put_device(&fnode_sess->dev);
+ 
+ put_host:
+ 	scsi_host_put(shost);
+@@ -2933,7 +2925,7 @@ static int iscsi_login_flashnode(struct iscsi_transport *transport,
+ 	struct iscsi_bus_flash_session *fnode_sess;
+ 	struct iscsi_bus_flash_conn *fnode_conn;
+ 	struct device *dev;
+-	uint32_t *idx;
++	uint32_t idx;
+ 	int err = 0;
+ 
+ 	if (!transport->login_flashnode) {
+@@ -2949,25 +2941,27 @@ static int iscsi_login_flashnode(struct iscsi_transport *transport,
+ 		goto put_host;
+ 	}
+ 
+-	idx = &ev->u.login_flashnode.flashnode_idx;
+-	fnode_sess = iscsi_get_flashnode_by_index(shost, idx,
+-						  flashnode_match_index);
++	idx = ev->u.login_flashnode.flashnode_idx;
++	fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
+ 	if (!fnode_sess) {
+ 		pr_err("%s could not find flashnode %u for host no %u\n",
+-		       __func__, *idx, ev->u.login_flashnode.host_no);
++		       __func__, idx, ev->u.login_flashnode.host_no);
+ 		err = -ENODEV;
+ 		goto put_host;
+ 	}
+ 
+-	dev = iscsi_find_flashnode_conn(fnode_sess, NULL,
+-					iscsi_is_flashnode_conn_dev);
++	dev = iscsi_find_flashnode_conn(fnode_sess);
+ 	if (!dev) {
+ 		err = -ENODEV;
+-		goto put_host;
++		goto put_sess;
+ 	}
+ 
+ 	fnode_conn = iscsi_dev_to_flash_conn(dev);
+ 	err = transport->login_flashnode(fnode_sess, fnode_conn);
++	put_device(dev);
++
++put_sess:
++	put_device(&fnode_sess->dev);
+ 
+ put_host:
+ 	scsi_host_put(shost);
+@@ -2983,7 +2977,7 @@ static int iscsi_logout_flashnode(struct iscsi_transport *transport,
+ 	struct iscsi_bus_flash_session *fnode_sess;
+ 	struct iscsi_bus_flash_conn *fnode_conn;
+ 	struct device *dev;
+-	uint32_t *idx;
++	uint32_t idx;
+ 	int err = 0;
+ 
+ 	if (!transport->logout_flashnode) {
+@@ -2999,26 +2993,28 @@ static int iscsi_logout_flashnode(struct iscsi_transport *transport,
+ 		goto put_host;
+ 	}
+ 
+-	idx = &ev->u.logout_flashnode.flashnode_idx;
+-	fnode_sess = iscsi_get_flashnode_by_index(shost, idx,
+-						  flashnode_match_index);
++	idx = ev->u.logout_flashnode.flashnode_idx;
++	fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
+ 	if (!fnode_sess) {
+ 		pr_err("%s could not find flashnode %u for host no %u\n",
+-		       __func__, *idx, ev->u.logout_flashnode.host_no);
++		       __func__, idx, ev->u.logout_flashnode.host_no);
+ 		err = -ENODEV;
+ 		goto put_host;
+ 	}
+ 
+-	dev = iscsi_find_flashnode_conn(fnode_sess, NULL,
+-					iscsi_is_flashnode_conn_dev);
++	dev = iscsi_find_flashnode_conn(fnode_sess);
+ 	if (!dev) {
+ 		err = -ENODEV;
+-		goto put_host;
++		goto put_sess;
+ 	}
+ 
+ 	fnode_conn = iscsi_dev_to_flash_conn(dev);
+ 
+ 	err = transport->logout_flashnode(fnode_sess, fnode_conn);
++	put_device(dev);
++
++put_sess:
++	put_device(&fnode_sess->dev);
+ 
+ put_host:
+ 	scsi_host_put(shost);
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 4a58cca2ecc1..d0f1602985e7 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -471,14 +471,10 @@ iscsi_destroy_flashnode_sess(struct iscsi_bus_flash_session *fnode_sess);
+ extern void iscsi_destroy_all_flashnode(struct Scsi_Host *shost);
+ extern int iscsi_flashnode_bus_match(struct device *dev,
+ 				     struct device_driver *drv);
+-extern int iscsi_is_flashnode_conn_dev(struct device *dev, void *data);
+-
+ extern struct device *
+ iscsi_find_flashnode_sess(struct Scsi_Host *shost, void *data,
+ 			  int (*fn)(struct device *dev, void *data));
+-
+ extern struct device *
+-iscsi_find_flashnode_conn(struct iscsi_bus_flash_session *fnode_sess,
+-			  void *data,
+-			  int (*fn)(struct device *dev, void *data));
++iscsi_find_flashnode_conn(struct iscsi_bus_flash_session *fnode_sess);
++
+ #endif

commit 9e45dd73234af9a59613dc2989dcc2df2dab847f
+Author: Mike Christie 
+Date:   Wed Apr 10 11:24:39 2013 -0500
+
+    [SCSI] iscsi_tcp: support PF_MEMALLOC/__GFP_MEMALLOC
+    
+    This patch has software iscsi use PF_MEMALLOC/__GFP_MEMALLOC
+    to be able to better support swap over iscsi disks similar to
+    what was added for nbd.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 1b91ca0dc1e3..9e2588a6881c 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -370,17 +370,24 @@ static inline int iscsi_sw_tcp_xmit_qlen(struct iscsi_conn *conn)
+ static int iscsi_sw_tcp_pdu_xmit(struct iscsi_task *task)
+ {
+ 	struct iscsi_conn *conn = task->conn;
+-	int rc;
++	unsigned long pflags = current->flags;
++	int rc = 0;
++
++	current->flags |= PF_MEMALLOC;
+ 
+ 	while (iscsi_sw_tcp_xmit_qlen(conn)) {
+ 		rc = iscsi_sw_tcp_xmit(conn);
+-		if (rc == 0)
+-			return -EAGAIN;
++		if (rc == 0) {
++			rc = -EAGAIN;
++			break;
++		}
+ 		if (rc < 0)
+-			return rc;
++			break;
++		rc = 0;
+ 	}
+ 
+-	return 0;
++	tsk_restore_flags(current, pflags, PF_MEMALLOC);
++	return rc;
+ }
+ 
+ /*
+@@ -665,6 +672,7 @@ iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session,
+ 	sk->sk_reuse = SK_CAN_REUSE;
+ 	sk->sk_sndtimeo = 15 * HZ; /* FIXME: make it configurable */
+ 	sk->sk_allocation = GFP_ATOMIC;
++	sk_set_memalloc(sk);
+ 
+ 	iscsi_sw_tcp_conn_set_callbacks(conn);
+ 	tcp_sw_conn->sendpage = tcp_sw_conn->sock->ops->sendpage;

commit 27db682bf07fdc105af38827dbbd67d6f0a4ae04
+Author: Mike Christie 
+Date:   Tue Mar 5 22:40:24 2013 -0600
+
+    [SCSI] scsi_dh_alua: fix stpg sense handling
+    
+    For the stpg_endio path we are not evaluating the sense. The bug
+    is that
+    
+    1. The error value is set to -EIO when there is sense, so we hit the first
+    error check and always return SCSI_DH_IO.
+    
+    2. h->senselen is set to zero in submit_stpg. It is not later set to
+    req->sense_len like in the synchrounous exection paths, so we must
+    check the req->sense_len field.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
+index 6f4d8e6f32f1..6648ffbb121a 100644
+--- a/drivers/scsi/device_handler/scsi_dh_alua.c
++++ b/drivers/scsi/device_handler/scsi_dh_alua.c
+@@ -232,13 +232,13 @@ static void stpg_endio(struct request *req, int error)
+ 	struct scsi_sense_hdr sense_hdr;
+ 	unsigned err = SCSI_DH_OK;
+ 
+-	if (error || host_byte(req->errors) != DID_OK ||
+-			msg_byte(req->errors) != COMMAND_COMPLETE) {
++	if (host_byte(req->errors) != DID_OK ||
++	    msg_byte(req->errors) != COMMAND_COMPLETE) {
+ 		err = SCSI_DH_IO;
+ 		goto done;
+ 	}
+ 
+-	if (h->senselen > 0) {
++	if (req->sense_len > 0) {
+ 		err = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
+ 					   &sense_hdr);
+ 		if (!err) {
+@@ -255,7 +255,9 @@ static void stpg_endio(struct request *req, int error)
+ 			    ALUA_DH_NAME, sense_hdr.sense_key,
+ 			    sense_hdr.asc, sense_hdr.ascq);
+ 		err = SCSI_DH_IO;
+-	}
++	} else if (error)
++		err = SCSI_DH_IO;
++
+ 	if (err == SCSI_DH_OK) {
+ 		h->state = TPGS_STATE_OPTIMIZED;
+ 		sdev_printk(KERN_INFO, h->sdev,

commit 87eb5b21d92a92ac2da3163039d62df88c2b8422
+Author: Mike Christie 
+Date:   Fri Mar 1 22:45:48 2013 +0000
+
+    dm: fix limits initialization when there are no data devices
+    
+    dm_calculate_queue_limits will first reset the provided limits to
+    defaults using blk_set_stacking_limits; whereby defeating the purpose of
+    retaining the original live table's limits -- as was intended via commit
+    3ae706561637331aa578e52bb89ecbba5edcb7a9 ("dm: retain table limits when
+    swapping to new table with no devices").
+    
+    Fix this improper limits initialization (in the no data devices case) by
+    avoiding the call to dm_calculate_queue_limits.
+    
+    [patch header revised by Mike Snitzer]
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Mike Snitzer 
+    Cc: stable@vger.kernel.org # v3.6+
+    Signed-off-by: Alasdair G Kergon 
+
+diff --git a/drivers/md/dm.c b/drivers/md/dm.c
+index 0890abd9dffa..1016c14c28a0 100644
+--- a/drivers/md/dm.c
++++ b/drivers/md/dm.c
+@@ -2446,7 +2446,7 @@ static void dm_queue_flush(struct mapped_device *md)
+  */
+ struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table)
+ {
+-	struct dm_table *live_map, *map = ERR_PTR(-EINVAL);
++	struct dm_table *live_map = NULL, *map = ERR_PTR(-EINVAL);
+ 	struct queue_limits limits;
+ 	int r;
+ 
+@@ -2469,10 +2469,12 @@ struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table)
+ 		dm_table_put(live_map);
+ 	}
+ 
+-	r = dm_calculate_queue_limits(table, &limits);
+-	if (r) {
+-		map = ERR_PTR(r);
+-		goto out;
++	if (!live_map) {
++		r = dm_calculate_queue_limits(table, &limits);
++		if (r) {
++			map = ERR_PTR(r);
++			goto out;
++		}
+ 	}
+ 
+ 	map = __bind(md, table, &limits);

commit dc30a436903ccf180b0313d3fc3f44278a1d44c8
+Author: Asim Kadav 
+Date:   Thu Jan 3 11:47:26 2013 -0600
+
+    sound: oss/pas2: Fix possible access out of array
+    
+    Added a fix for hardware dependence bug where a sound card failure
+    should not result in reading beyond array memory index.
+    
+    Signed-off-by: Asim Kadav 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/oss/pas2_card.c b/sound/oss/pas2_card.c
+index dabf8a871dcc..7004e24d209f 100644
+--- a/sound/oss/pas2_card.c
++++ b/sound/oss/pas2_card.c
+@@ -333,6 +333,11 @@ static void __init attach_pas_card(struct address_info *hw_config)
+ 		{
+ 			char            temp[100];
+ 
++			if (pas_model < 0 ||
++			    pas_model >= ARRAY_SIZE(pas_model_names)) {
++				printk(KERN_ERR "pas2 unrecognized model.\n");
++				return;
++			}
+ 			sprintf(temp,
+ 			    "%s rev %d", pas_model_names[(int) pas_model],
+ 				    pas_read(0x2789));

commit d075498c987623107f7bface4dad72fe9260a0d3
+Author: Mike Christie 
+Date:   Thu May 17 23:56:58 2012 -0500
+
+    [SCSI] remove old comment from block/unblock functions
+    
+    We do not hold the host lock when calling these functions,
+    so remove comment.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index 36521a0ac54b..9f00c128e4d1 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -2411,7 +2411,6 @@ EXPORT_SYMBOL(scsi_target_resume);
+  *	(which must be a legal transition).  When the device is in this
+  *	state, all commands are deferred until the scsi lld reenables
+  *	the device with scsi_device_unblock or device_block_tmo fires.
+- *	This routine assumes the host_lock is held on entry.
+  */
+ int
+ scsi_internal_device_block(struct scsi_device *sdev)
+@@ -2455,8 +2454,7 @@ EXPORT_SYMBOL_GPL(scsi_internal_device_block);
+  * Notes:       
+  *	This routine transitions the device to the SDEV_RUNNING state
+  *	or to one of the offline states (which must be a legal transition)
+- *	allowing the midlayer to goose the queue for this device. This
+- *	routine assumes the host_lock is held upon entry.
++ *	allowing the midlayer to goose the queue for this device.
+  */
+ int
+ scsi_internal_device_unblock(struct scsi_device *sdev,

commit 5d9fb5cc1b88277bb28a2a54e51b34cacaa123c2
+Author: Mike Christie 
+Date:   Thu May 17 23:56:57 2012 -0500
+
+    [SCSI] core, classes, mpt2sas: have scsi_internal_device_unblock take new state
+    
+    This has scsi_internal_device_unblock/scsi_target_unblock take
+    the new state to set the devices as an argument instead of
+    always setting to running. The patch also converts users of these
+    functions.
+    
+    This allows the FC and iSCSI class to transition devices from blocked
+    to transport-offline, so that when fast_io_fail/replacement_timeout
+    has fired we do not set the devices back to running. Instead, we
+    set them to SDEV_TRANSPORT_OFFLINE.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
+index b6dd3a5de7f9..b3a1a30055d6 100644
+--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
++++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
+@@ -1158,6 +1158,7 @@ extern struct scsi_transport_template *mpt2sas_transport_template;
+ extern int scsi_internal_device_block(struct scsi_device *sdev);
+ extern u8 mpt2sas_stm_zero_smid_handler(struct MPT2SAS_ADAPTER *ioc,
+     u8 msix_index, u32 reply);
+-extern int scsi_internal_device_unblock(struct scsi_device *sdev);
++extern int scsi_internal_device_unblock(struct scsi_device *sdev,
++					enum scsi_device_state new_state);
+ 
+ #endif /* MPT2SAS_BASE_H_INCLUDED */
+diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+index 76973e8ca4ba..b1ebd6f8dab3 100644
+--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
++++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+@@ -2904,7 +2904,7 @@ _scsih_ublock_io_all_device(struct MPT2SAS_ADAPTER *ioc)
+ 		dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_running, "
+ 		    "handle(0x%04x)\n",
+ 		    sas_device_priv_data->sas_target->handle));
+-		scsi_internal_device_unblock(sdev);
++		scsi_internal_device_unblock(sdev, SDEV_RUNNING);
+ 	}
+ }
+ /**
+@@ -2933,7 +2933,7 @@ _scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
+ 			    "sas address(0x%016llx)\n", ioc->name,
+ 				(unsigned long long)sas_address));
+ 			sas_device_priv_data->block = 0;
+-			scsi_internal_device_unblock(sdev);
++			scsi_internal_device_unblock(sdev, SDEV_RUNNING);
+ 		}
+ 	}
+ }
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index 340c569d4535..36521a0ac54b 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -2444,6 +2444,7 @@ EXPORT_SYMBOL_GPL(scsi_internal_device_block);
+ /**
+  * scsi_internal_device_unblock - resume a device after a block request
+  * @sdev:	device to resume
++ * @new_state:	state to set devices to after unblocking
+  *
+  * Called by scsi lld's or the midlayer to restart the device queue
+  * for the previously suspended scsi device.  Called from interrupt or
+@@ -2453,25 +2454,30 @@ EXPORT_SYMBOL_GPL(scsi_internal_device_block);
+  *
+  * Notes:       
+  *	This routine transitions the device to the SDEV_RUNNING state
+- *	(which must be a legal transition) allowing the midlayer to
+- *	goose the queue for this device.  This routine assumes the 
+- *	host_lock is held upon entry.
++ *	or to one of the offline states (which must be a legal transition)
++ *	allowing the midlayer to goose the queue for this device. This
++ *	routine assumes the host_lock is held upon entry.
+  */
+ int
+-scsi_internal_device_unblock(struct scsi_device *sdev)
++scsi_internal_device_unblock(struct scsi_device *sdev,
++			     enum scsi_device_state new_state)
+ {
+ 	struct request_queue *q = sdev->request_queue; 
+ 	unsigned long flags;
+-	
+-	/* 
+-	 * Try to transition the scsi device to SDEV_RUNNING
+-	 * and goose the device queue if successful.  
++
++	/*
++	 * Try to transition the scsi device to SDEV_RUNNING or one of the
++	 * offlined states and goose the device queue if successful.
+ 	 */
+ 	if (sdev->sdev_state == SDEV_BLOCK)
+-		sdev->sdev_state = SDEV_RUNNING;
+-	else if (sdev->sdev_state == SDEV_CREATED_BLOCK)
+-		sdev->sdev_state = SDEV_CREATED;
+-	else if (sdev->sdev_state != SDEV_CANCEL &&
++		sdev->sdev_state = new_state;
++	else if (sdev->sdev_state == SDEV_CREATED_BLOCK) {
++		if (new_state == SDEV_TRANSPORT_OFFLINE ||
++		    new_state == SDEV_OFFLINE)
++			sdev->sdev_state = new_state;
++		else
++			sdev->sdev_state = SDEV_CREATED;
++	} else if (sdev->sdev_state != SDEV_CANCEL &&
+ 		 sdev->sdev_state != SDEV_OFFLINE)
+ 		return -EINVAL;
+ 
+@@ -2512,26 +2518,26 @@ EXPORT_SYMBOL_GPL(scsi_target_block);
+ static void
+ device_unblock(struct scsi_device *sdev, void *data)
+ {
+-	scsi_internal_device_unblock(sdev);
++	scsi_internal_device_unblock(sdev, *(enum scsi_device_state *)data);
+ }
+ 
+ static int
+ target_unblock(struct device *dev, void *data)
+ {
+ 	if (scsi_is_target_device(dev))
+-		starget_for_each_device(to_scsi_target(dev), NULL,
++		starget_for_each_device(to_scsi_target(dev), data,
+ 					device_unblock);
+ 	return 0;
+ }
+ 
+ void
+-scsi_target_unblock(struct device *dev)
++scsi_target_unblock(struct device *dev, enum scsi_device_state new_state)
+ {
+ 	if (scsi_is_target_device(dev))
+-		starget_for_each_device(to_scsi_target(dev), NULL,
++		starget_for_each_device(to_scsi_target(dev), &new_state,
+ 					device_unblock);
+ 	else
+-		device_for_each_child(dev, NULL, target_unblock);
++		device_for_each_child(dev, &new_state, target_unblock);
+ }
+ EXPORT_SYMBOL_GPL(scsi_target_unblock);
+ 
+diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
+index 07ce3f51701d..cbfe5df24a3b 100644
+--- a/drivers/scsi/scsi_priv.h
++++ b/drivers/scsi/scsi_priv.h
+@@ -2,6 +2,7 @@
+ #define _SCSI_PRIV_H
+ 
+ #include 
++#include 
+ 
+ struct request_queue;
+ struct request;
+@@ -172,6 +173,7 @@ extern struct list_head scsi_sd_probe_domain;
+ 
+ #define SCSI_DEVICE_BLOCK_MAX_TIMEOUT	600	/* units in seconds */
+ extern int scsi_internal_device_block(struct scsi_device *sdev);
+-extern int scsi_internal_device_unblock(struct scsi_device *sdev);
++extern int scsi_internal_device_unblock(struct scsi_device *sdev,
++					enum scsi_device_state new_state);
+ 
+ #endif /* _SCSI_PRIV_H */
+diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
+index 2fded793997c..2d1e68db9b3f 100644
+--- a/drivers/scsi/scsi_transport_fc.c
++++ b/drivers/scsi/scsi_transport_fc.c
+@@ -2495,11 +2495,9 @@ static void fc_terminate_rport_io(struct fc_rport *rport)
+ 		i->f->terminate_rport_io(rport);
+ 
+ 	/*
+-	 * must unblock to flush queued IO. The caller will have set
+-	 * the port_state or flags, so that fc_remote_port_chkready will
+-	 * fail IO.
++	 * Must unblock to flush queued IO. scsi-ml will fail incoming reqs.
+ 	 */
+-	scsi_target_unblock(&rport->dev);
++	scsi_target_unblock(&rport->dev, SDEV_TRANSPORT_OFFLINE);
+ }
+ 
+ /**
+@@ -2830,8 +2828,8 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
+ 
+ 				/* if target, initiate a scan */
+ 				if (rport->scsi_target_id != -1) {
+-					scsi_target_unblock(&rport->dev);
+-
++					scsi_target_unblock(&rport->dev,
++							    SDEV_RUNNING);
+ 					spin_lock_irqsave(shost->host_lock,
+ 							  flags);
+ 					rport->flags |= FC_RPORT_SCAN_PENDING;
+@@ -2900,7 +2898,7 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
+ 			spin_unlock_irqrestore(shost->host_lock, flags);
+ 
+ 			if (ids->roles & FC_PORT_ROLE_FCP_TARGET) {
+-				scsi_target_unblock(&rport->dev);
++				scsi_target_unblock(&rport->dev, SDEV_RUNNING);
+ 
+ 				/* initiate a scan of the target */
+ 				spin_lock_irqsave(shost->host_lock, flags);
+@@ -3105,7 +3103,7 @@ fc_remote_port_rolechg(struct fc_rport  *rport, u32 roles)
+ 		/* ensure any stgt delete functions are done */
+ 		fc_flush_work(shost);
+ 
+-		scsi_target_unblock(&rport->dev);
++		scsi_target_unblock(&rport->dev, SDEV_RUNNING);
+ 		/* initiate a scan of the target */
+ 		spin_lock_irqsave(shost->host_lock, flags);
+ 		rport->flags |= FC_RPORT_SCAN_PENDING;
+@@ -3149,7 +3147,7 @@ fc_timeout_deleted_rport(struct work_struct *work)
+ 			"blocked FC remote port time out: no longer"
+ 			" a FCP target, removing starget\n");
+ 		spin_unlock_irqrestore(shost->host_lock, flags);
+-		scsi_target_unblock(&rport->dev);
++		scsi_target_unblock(&rport->dev, SDEV_TRANSPORT_OFFLINE);
+ 		fc_queue_work(shost, &rport->stgt_delete_work);
+ 		return;
+ 	}
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 1cf640e575da..96ec21a959e9 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -907,7 +907,7 @@ static void session_recovery_timedout(struct work_struct *work)
+ 		session->transport->session_recovery_timedout(session);
+ 
+ 	ISCSI_DBG_TRANS_SESSION(session, "Unblocking SCSI target\n");
+-	scsi_target_unblock(&session->dev);
++	scsi_target_unblock(&session->dev, SDEV_TRANSPORT_OFFLINE);
+ 	ISCSI_DBG_TRANS_SESSION(session, "Completed unblocking SCSI target\n");
+ }
+ 
+@@ -930,7 +930,7 @@ static void __iscsi_unblock_session(struct work_struct *work)
+ 	session->state = ISCSI_SESSION_LOGGED_IN;
+ 	spin_unlock_irqrestore(&session->lock, flags);
+ 	/* start IO */
+-	scsi_target_unblock(&session->dev);
++	scsi_target_unblock(&session->dev, SDEV_RUNNING);
+ 	/*
+ 	 * Only do kernel scanning if the driver is properly hooked into
+ 	 * the async scanning code (drivers like iscsi_tcp do login and
+@@ -1180,7 +1180,7 @@ void iscsi_remove_session(struct iscsi_cls_session *session)
+ 	session->state = ISCSI_SESSION_FREE;
+ 	spin_unlock_irqrestore(&session->lock, flags);
+ 
+-	scsi_target_unblock(&session->dev);
++	scsi_target_unblock(&session->dev, SDEV_TRANSPORT_OFFLINE);
+ 	/* flush running scans then delete devices */
+ 	scsi_flush_work(shost);
+ 	__iscsi_unbind_session(&session->unbind_work);
+diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
+index 404575857962..bd1a14d89009 100644
+--- a/include/scsi/scsi_device.h
++++ b/include/scsi/scsi_device.h
+@@ -374,7 +374,7 @@ extern void scsi_scan_target(struct device *parent, unsigned int channel,
+ 			     unsigned int id, unsigned int lun, int rescan);
+ extern void scsi_target_reap(struct scsi_target *);
+ extern void scsi_target_block(struct device *);
+-extern void scsi_target_unblock(struct device *);
++extern void scsi_target_unblock(struct device *, enum scsi_device_state);
+ extern void scsi_remove_target(struct device *);
+ extern void int_to_scsilun(unsigned int, struct scsi_lun *);
+ extern int scsilun_to_int(struct scsi_lun *);

commit 1b8d26206134458044b0689f48194af00c96d406
+Author: Mike Christie 
+Date:   Thu May 17 23:56:56 2012 -0500
+
+    [SCSI] add new SDEV_TRANSPORT_OFFLINE state
+    
+    This patch adds a new state SDEV_TRANSPORT_OFFLINE. It will
+    be used by transport classes to offline devices for cases like
+    when the fast_io_fail/recovery_tmo fires. In those cases we
+    want all IO to fail, and we have not yet escalated to dev_loss_tmo
+    behavior where we are removing the devices.
+    
+    Currently to handle this state, transport classes are setting
+    the scsi_device's state to running, setting their internal
+    session/port structs state to something that indicates failed,
+    and then failing IO from some transport check in the queuecommand.
+    
+    The reason for the new value is so that users can distinguish
+    between a device failure that is a result of a transport problem
+    vs the wide range of errors that devices get offlined for
+    when a scsi command times out and we offline the devices there.
+    It also fixes the confusion as to why the transport class is
+    failing IO, but has set the device state from blocked to running.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index 6dfb9785d345..340c569d4535 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -1173,6 +1173,7 @@ int scsi_prep_state_check(struct scsi_device *sdev, struct request *req)
+ 	if (unlikely(sdev->sdev_state != SDEV_RUNNING)) {
+ 		switch (sdev->sdev_state) {
+ 		case SDEV_OFFLINE:
++		case SDEV_TRANSPORT_OFFLINE:
+ 			/*
+ 			 * If the device is offline we refuse to process any
+ 			 * commands.  The device must be brought online
+@@ -2081,6 +2082,7 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state)
+ 		switch (oldstate) {
+ 		case SDEV_CREATED:
+ 		case SDEV_OFFLINE:
++		case SDEV_TRANSPORT_OFFLINE:
+ 		case SDEV_QUIESCE:
+ 		case SDEV_BLOCK:
+ 			break;
+@@ -2093,6 +2095,7 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state)
+ 		switch (oldstate) {
+ 		case SDEV_RUNNING:
+ 		case SDEV_OFFLINE:
++		case SDEV_TRANSPORT_OFFLINE:
+ 			break;
+ 		default:
+ 			goto illegal;
+@@ -2100,6 +2103,7 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state)
+ 		break;
+ 
+ 	case SDEV_OFFLINE:
++	case SDEV_TRANSPORT_OFFLINE:
+ 		switch (oldstate) {
+ 		case SDEV_CREATED:
+ 		case SDEV_RUNNING:
+@@ -2136,6 +2140,7 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state)
+ 		case SDEV_RUNNING:
+ 		case SDEV_QUIESCE:
+ 		case SDEV_OFFLINE:
++		case SDEV_TRANSPORT_OFFLINE:
+ 		case SDEV_BLOCK:
+ 			break;
+ 		default:
+@@ -2148,6 +2153,7 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state)
+ 		case SDEV_CREATED:
+ 		case SDEV_RUNNING:
+ 		case SDEV_OFFLINE:
++		case SDEV_TRANSPORT_OFFLINE:
+ 		case SDEV_CANCEL:
+ 			break;
+ 		default:
+diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
+index 04c2a278076e..5747478a2bf8 100644
+--- a/drivers/scsi/scsi_sysfs.c
++++ b/drivers/scsi/scsi_sysfs.c
+@@ -35,6 +35,7 @@ static const struct {
+ 	{ SDEV_DEL, "deleted" },
+ 	{ SDEV_QUIESCE, "quiesce" },
+ 	{ SDEV_OFFLINE,	"offline" },
++	{ SDEV_TRANSPORT_OFFLINE, "transport-offline" },
+ 	{ SDEV_BLOCK,	"blocked" },
+ 	{ SDEV_CREATED_BLOCK, "created-blocked" },
+ };
+diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
+index ba9698852321..404575857962 100644
+--- a/include/scsi/scsi_device.h
++++ b/include/scsi/scsi_device.h
+@@ -42,6 +42,7 @@ enum scsi_device_state {
+ 				 * originate in the mid-layer) */
+ 	SDEV_OFFLINE,		/* Device offlined (by error handling or
+ 				 * user request */
++	SDEV_TRANSPORT_OFFLINE,	/* Offlined by transport class error handler */
+ 	SDEV_BLOCK,		/* Device blocked by scsi lld.  No
+ 				 * scsi commands from user or midlayer
+ 				 * should be issued to the scsi
+@@ -421,6 +422,7 @@ static inline unsigned int sdev_id(struct scsi_device *sdev)
+ static inline int scsi_device_online(struct scsi_device *sdev)
+ {
+ 	return (sdev->sdev_state != SDEV_OFFLINE &&
++		sdev->sdev_state != SDEV_TRANSPORT_OFFLINE &&
+ 		sdev->sdev_state != SDEV_DEL);
+ }
+ static inline int scsi_device_blocked(struct scsi_device *sdev)

commit f220fd4efb334a772f9a14b2372175f38d89355e
+Author: Mike Christie 
+Date:   Sun Jun 3 00:29:45 2012 +0100
+
+    dm mpath: delay retry of bypassed pg
+    
+    If I/O needs retrying and only bypassed priority groups are available,
+    set the pg_init_delay_retry flag to wait before retrying.
+    
+    If, for example, the reason for the bypass is that the controller is
+    getting reset or there is a firmware upgrade happening, retrying right
+    away would cause a flood of log messages and retries for what could be a
+    few seconds or even several minutes.
+    
+    Signed-off-by: Mike Christie 
+    Acked-by: Mike Snitzer 
+    Signed-off-by: Alasdair G Kergon 
+
+diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
+index c35160786cf4..2469ba68dc2b 100644
+--- a/drivers/md/dm-mpath.c
++++ b/drivers/md/dm-mpath.c
+@@ -329,14 +329,18 @@ static void __choose_pgpath(struct multipath *m, size_t nr_bytes)
+ 	/*
+ 	 * Loop through priority groups until we find a valid path.
+ 	 * First time we skip PGs marked 'bypassed'.
+-	 * Second time we only try the ones we skipped.
++	 * Second time we only try the ones we skipped, but set
++	 * pg_init_delay_retry so we do not hammer controllers.
+ 	 */
+ 	do {
+ 		list_for_each_entry(pg, &m->priority_groups, list) {
+ 			if (pg->bypassed == bypassed)
+ 				continue;
+-			if (!__choose_path_in_pg(m, pg, nr_bytes))
++			if (!__choose_path_in_pg(m, pg, nr_bytes)) {
++				if (!bypassed)
++					m->pg_init_delay_retry = 1;
+ 				return;
++			}
+ 		}
+ 	} while (bypassed--);
+ 

commit b83d543fd934d565fb243ef348b06a61d794b31d
+Author: Mike Christie 
+Date:   Wed May 23 20:40:54 2012 -0500
+
+    [SCSI] be2iscsi: fix dma free size mismatch regression
+    
+    This patch should go into 3.5 fixes. The bug was added in the
+    patches for the 3.5 feature window.
+    
+    As you can see from the patch I made a mistake. During
+    development I switched from passing a struct to the size of
+    the struct, but left the sizeof. This results in us allocating
+    4 bytes (sizeof(int)) but then calling pci_free_consistent
+    with the size of the struct.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c
+index 01bb04cd9e75..2a096795b9aa 100644
+--- a/drivers/scsi/be2iscsi/be_mgmt.c
++++ b/drivers/scsi/be2iscsi/be_mgmt.c
+@@ -571,13 +571,12 @@ static int mgmt_exec_nonemb_cmd(struct beiscsi_hba *phba,
+ static int mgmt_alloc_cmd_data(struct beiscsi_hba *phba, struct be_dma_mem *cmd,
+ 			       int iscsi_cmd, int size)
+ {
+-	cmd->va = pci_alloc_consistent(phba->ctrl.pdev, sizeof(size),
+-				       &cmd->dma);
++	cmd->va = pci_alloc_consistent(phba->ctrl.pdev, size, &cmd->dma);
+ 	if (!cmd->va) {
+ 		SE_DEBUG(DBG_LVL_1, "Failed to allocate memory for if info\n");
+ 		return -ENOMEM;
+ 	}
+-	memset(cmd->va, 0, sizeof(size));
++	memset(cmd->va, 0, size);
+ 	cmd->size = size;
+ 	be_cmd_hdr_prepare(cmd->va, CMD_SUBSYSTEM_ISCSI, iscsi_cmd, size);
+ 	return 0;

commit 8fb2ef89b696624ea9853868e370d2e132e76f54
+Author: Mike Christie 
+Date:   Sun Apr 15 21:47:50 2012 -0500
+
+    [SCSI] fc class: fix scanning when devs are offline
+    
+    When a rport is added back or the role is changed the fc class
+    will queue a scan and then call scsi_target_unblock. The problem
+    with this is if the devices are in the SDEV_OFFLINE state and
+    the scan is run before the scsi_target_unblock, then the scan
+    will see LUN0 as offline and the scan will fail. This patch moves
+    the unblock call to before the scan, so we know the device state
+    will be set correctly when the scan is run.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
+index 80fbe2ac0b47..579760420d53 100644
+--- a/drivers/scsi/scsi_transport_fc.c
++++ b/drivers/scsi/scsi_transport_fc.c
+@@ -2808,17 +2808,20 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
+ 						  FC_RPORT_DEVLOSS_PENDING |
+ 						  FC_RPORT_DEVLOSS_CALLBK_DONE);
+ 
++				spin_unlock_irqrestore(shost->host_lock, flags);
++
+ 				/* if target, initiate a scan */
+ 				if (rport->scsi_target_id != -1) {
++					scsi_target_unblock(&rport->dev);
++
++					spin_lock_irqsave(shost->host_lock,
++							  flags);
+ 					rport->flags |= FC_RPORT_SCAN_PENDING;
+ 					scsi_queue_work(shost,
+ 							&rport->scan_work);
+ 					spin_unlock_irqrestore(shost->host_lock,
+ 							flags);
+-					scsi_target_unblock(&rport->dev);
+-				} else
+-					spin_unlock_irqrestore(shost->host_lock,
+-							flags);
++				}
+ 
+ 				fc_bsg_goose_queue(rport);
+ 
+@@ -2876,16 +2879,17 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
+ 			if (fci->f->dd_fcrport_size)
+ 				memset(rport->dd_data, 0,
+ 						fci->f->dd_fcrport_size);
++			spin_unlock_irqrestore(shost->host_lock, flags);
++
++			if (ids->roles & FC_PORT_ROLE_FCP_TARGET) {
++				scsi_target_unblock(&rport->dev);
+ 
+-			if (rport->roles & FC_PORT_ROLE_FCP_TARGET) {
+ 				/* initiate a scan of the target */
++				spin_lock_irqsave(shost->host_lock, flags);
+ 				rport->flags |= FC_RPORT_SCAN_PENDING;
+ 				scsi_queue_work(shost, &rport->scan_work);
+ 				spin_unlock_irqrestore(shost->host_lock, flags);
+-				scsi_target_unblock(&rport->dev);
+-			} else
+-				spin_unlock_irqrestore(shost->host_lock, flags);
+-
++			}
+ 			return rport;
+ 		}
+ 	}
+@@ -3083,12 +3087,12 @@ fc_remote_port_rolechg(struct fc_rport  *rport, u32 roles)
+ 		/* ensure any stgt delete functions are done */
+ 		fc_flush_work(shost);
+ 
++		scsi_target_unblock(&rport->dev);
+ 		/* initiate a scan of the target */
+ 		spin_lock_irqsave(shost->host_lock, flags);
+ 		rport->flags |= FC_RPORT_SCAN_PENDING;
+ 		scsi_queue_work(shost, &rport->scan_work);
+ 		spin_unlock_irqrestore(shost->host_lock, flags);
+-		scsi_target_unblock(&rport->dev);
+ 	}
+ }
+ EXPORT_SYMBOL(fc_remote_port_rolechg);

commit 0e43895ec1f405a25b5d57bc95c11fe17224ec43
+Author: Mike Christie 
+Date:   Tue Apr 3 23:41:51 2012 -0500
+
+    [SCSI] be2iscsi: adding functionality to change network settings using iscsiadm
+    
+    This patch allows iscsiadm to set/ delete static IP and enable /disable
+    DHCP.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Jayamohan Kallickal 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h
+index b15de3eaddf0..60d144550f76 100644
+--- a/drivers/scsi/be2iscsi/be_cmds.h
++++ b/drivers/scsi/be2iscsi/be_cmds.h
+@@ -163,7 +163,8 @@ struct be_mcc_mailbox {
+ #define OPCODE_COMMON_ISCSI_CFG_REMOVE_SGL_PAGES        3
+ #define OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG		7
+ #define OPCODE_COMMON_ISCSI_NTWK_SET_VLAN		14
+-#define OPCODE_COMMON_ISCSI_NTWK_CONFIGURE_STATELESS_IP_ADDR	17
++#define OPCODE_COMMON_ISCSI_NTWK_CONFIG_STATELESS_IP_ADDR	17
++#define OPCODE_COMMON_ISCSI_NTWK_REL_STATELESS_IP_ADDR	18
+ #define OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR		21
+ #define OPCODE_COMMON_ISCSI_NTWK_GET_DEFAULT_GATEWAY	22
+ #define OPCODE_COMMON_ISCSI_NTWK_MODIFY_DEFAULT_GATEWAY 23
+@@ -274,15 +275,15 @@ struct mgmt_conn_login_options {
+ 	struct	mgmt_auth_method_format auth_data;
+ } __packed;
+ 
+-struct ip_address_format {
++struct ip_addr_format {
+ 	u16 size_of_structure;
+ 	u8 reserved;
+ 	u8 ip_type;
+-	u8 ip_address[16];
++	u8 addr[16];
+ 	u32 rsvd0;
+ } __packed;
+ 
+-struct	mgmt_conn_info {
++struct mgmt_conn_info {
+ 	u32	connection_handle;
+ 	u32	connection_status;
+ 	u16	src_port;
+@@ -290,9 +291,9 @@ struct	mgmt_conn_info {
+ 	u16	dest_port_redirected;
+ 	u16	cid;
+ 	u32	estimated_throughput;
+-	struct	ip_address_format	src_ipaddr;
+-	struct	ip_address_format	dest_ipaddr;
+-	struct	ip_address_format	dest_ipaddr_redirected;
++	struct	ip_addr_format	src_ipaddr;
++	struct	ip_addr_format	dest_ipaddr;
++	struct	ip_addr_format	dest_ipaddr_redirected;
+ 	struct	mgmt_conn_login_options	negotiated_login_options;
+ } __packed;
+ 
+@@ -322,43 +323,115 @@ struct mgmt_session_info {
+ 	struct	mgmt_conn_info	conn_list[1];
+ } __packed;
+ 
+-struct  be_cmd_req_get_session {
++struct be_cmd_get_session_req {
+ 	struct be_cmd_req_hdr hdr;
+ 	u32 session_handle;
+ } __packed;
+ 
+-struct  be_cmd_resp_get_session {
++struct be_cmd_get_session_resp {
+ 	struct be_cmd_resp_hdr hdr;
+ 	struct mgmt_session_info session_info;
+ } __packed;
+ 
+ struct mac_addr {
+-	u16 size_of_struct;
++	u16 size_of_structure;
+ 	u8 addr[ETH_ALEN];
+ } __packed;
+ 
+-struct be_cmd_req_get_boot_target {
++struct be_cmd_get_boot_target_req {
+ 	struct be_cmd_req_hdr hdr;
+ } __packed;
+ 
+-struct be_cmd_resp_get_boot_target {
++struct be_cmd_get_boot_target_resp {
+ 	struct be_cmd_resp_hdr hdr;
+ 	u32  boot_session_count;
+ 	int  boot_session_handle;
+ };
+ 
+-struct be_cmd_req_mac_query {
++struct be_cmd_mac_query_req {
+ 	struct be_cmd_req_hdr hdr;
+ 	u8 type;
+ 	u8 permanent;
+ 	u16 if_id;
+ } __packed;
+ 
+-struct be_cmd_resp_mac_query {
++struct be_cmd_get_mac_resp {
+ 	struct be_cmd_resp_hdr hdr;
+ 	struct mac_addr mac;
+ };
+ 
++struct be_ip_addr_subnet_format {
++	u16 size_of_structure;
++	u8 ip_type;
++	u8 ipv6_prefix_length;
++	u8 addr[16];
++	u8 subnet_mask[16];
++	u32 rsvd0;
++} __packed;
++
++struct be_cmd_get_if_info_req {
++	struct be_cmd_req_hdr hdr;
++	u32 interface_hndl;
++	u32 ip_type;
++} __packed;
++
++struct be_cmd_get_if_info_resp {
++	struct be_cmd_req_hdr hdr;
++	u32 interface_hndl;
++	u32 vlan_priority;
++	u32 ip_addr_count;
++	u32 dhcp_state;
++	struct be_ip_addr_subnet_format ip_addr;
++} __packed;
++
++struct be_ip_addr_record {
++	u32 action;
++	u32 interface_hndl;
++	struct be_ip_addr_subnet_format ip_addr;
++	u32 status;
++} __packed;
++
++struct be_ip_addr_record_params {
++	u32 record_entry_count;
++	struct be_ip_addr_record ip_record;
++} __packed;
++
++struct be_cmd_set_ip_addr_req {
++	struct be_cmd_req_hdr hdr;
++	struct be_ip_addr_record_params ip_params;
++} __packed;
++
++
++struct be_cmd_set_dhcp_req {
++	struct be_cmd_req_hdr hdr;
++	u32 interface_hndl;
++	u32 ip_type;
++	u32 flags;
++	u32 retry_count;
++} __packed;
++
++struct be_cmd_rel_dhcp_req {
++	struct be_cmd_req_hdr hdr;
++	u32 interface_hndl;
++	u32 ip_type;
++} __packed;
++
++struct be_cmd_set_def_gateway_req {
++	struct be_cmd_req_hdr hdr;
++	u32 action;
++	struct ip_addr_format ip_addr;
++} __packed;
++
++struct be_cmd_get_def_gateway_req {
++	struct be_cmd_req_hdr hdr;
++	u32 ip_type;
++} __packed;
++
++struct be_cmd_get_def_gateway_resp {
++	struct be_cmd_req_hdr hdr;
++	struct ip_addr_format ip_addr;
++} __packed;
++
+ /******************** Create CQ ***************************/
+ /**
+  * Pseudo amap definition in which each bit of the actual structure is defined
+@@ -489,7 +562,7 @@ struct be_cmd_req_modify_eq_delay {
+ 
+ #define ETH_ALEN	6
+ 
+-struct be_cmd_req_get_mac_addr {
++struct be_cmd_get_nic_conf_req {
+ 	struct be_cmd_req_hdr hdr;
+ 	u32 nic_port_count;
+ 	u32 speed;
+@@ -501,7 +574,7 @@ struct be_cmd_req_get_mac_addr {
+ 	u32 rsvd[23];
+ };
+ 
+-struct be_cmd_resp_get_mac_addr {
++struct be_cmd_get_nic_conf_resp {
+ 	struct be_cmd_resp_hdr hdr;
+ 	u32 nic_port_count;
+ 	u32 speed;
+@@ -541,12 +614,7 @@ int beiscsi_cmd_mccq_create(struct beiscsi_hba *phba,
+ int be_poll_mcc(struct be_ctrl_info *ctrl);
+ int mgmt_check_supported_fw(struct be_ctrl_info *ctrl,
+ 				      struct beiscsi_hba *phba);
+-unsigned int be_cmd_get_mac_addr(struct beiscsi_hba *phba);
+ unsigned int be_cmd_get_initname(struct beiscsi_hba *phba);
+-unsigned int beiscsi_get_boot_target(struct beiscsi_hba *phba);
+-unsigned int beiscsi_get_session_info(struct beiscsi_hba *phba,
+-				  u32 boot_session_handle,
+-				  struct be_dma_mem *nonemb_cmd);
+ 
+ void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag);
+ /*ISCSI Functuions */
+@@ -727,7 +795,7 @@ struct be_eq_delay_params_in {
+ 
+ struct tcp_connect_and_offload_in {
+ 	struct be_cmd_req_hdr hdr;
+-	struct ip_address_format ip_address;
++	struct ip_addr_format ip_address;
+ 	u16 tcp_port;
+ 	u16 cid;
+ 	u16 cq_id;
+@@ -804,7 +872,7 @@ struct be_fw_cfg {
+ 	u32 function_caps;
+ } __packed;
+ 
+-struct be_all_if_id {
++struct be_cmd_get_all_if_id_req {
+ 	struct be_cmd_req_hdr hdr;
+ 	u32 if_count;
+ 	u32 if_hndl_list[1];
+diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
+index 1af777474e42..46cc40e83b36 100644
+--- a/drivers/scsi/be2iscsi/be_iscsi.c
++++ b/drivers/scsi/be2iscsi/be_iscsi.c
+@@ -23,6 +23,8 @@
+ #include 
+ #include 
+ #include 
++#include 
++#include 
+ #include 
+ 
+ #include "be_iscsi.h"
+@@ -207,6 +209,301 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
+ 	return beiscsi_bindconn_cid(phba, beiscsi_conn, beiscsi_ep->ep_cid);
+ }
+ 
++static int beiscsi_create_ipv4_iface(struct beiscsi_hba *phba)
++{
++	if (phba->ipv4_iface)
++		return 0;
++
++	phba->ipv4_iface = iscsi_create_iface(phba->shost,
++					      &beiscsi_iscsi_transport,
++					      ISCSI_IFACE_TYPE_IPV4,
++					      0, 0);
++	if (!phba->ipv4_iface) {
++		shost_printk(KERN_ERR, phba->shost, "Could not "
++			     "create default IPv4 address.\n");
++		return -ENODEV;
++	}
++
++	return 0;
++}
++
++static int beiscsi_create_ipv6_iface(struct beiscsi_hba *phba)
++{
++	if (phba->ipv6_iface)
++		return 0;
++
++	phba->ipv6_iface = iscsi_create_iface(phba->shost,
++					      &beiscsi_iscsi_transport,
++					      ISCSI_IFACE_TYPE_IPV6,
++					      0, 0);
++	if (!phba->ipv6_iface) {
++		shost_printk(KERN_ERR, phba->shost, "Could not "
++			     "create default IPv6 address.\n");
++		return -ENODEV;
++	}
++
++	return 0;
++}
++
++void beiscsi_create_def_ifaces(struct beiscsi_hba *phba)
++{
++	struct be_cmd_get_if_info_resp if_info;
++
++	if (!mgmt_get_if_info(phba, BE2_IPV4, &if_info))
++		beiscsi_create_ipv4_iface(phba);
++
++	if (!mgmt_get_if_info(phba, BE2_IPV6, &if_info))
++		beiscsi_create_ipv6_iface(phba);
++}
++
++void beiscsi_destroy_def_ifaces(struct beiscsi_hba *phba)
++{
++	if (phba->ipv6_iface)
++		iscsi_destroy_iface(phba->ipv6_iface);
++	if (phba->ipv4_iface)
++		iscsi_destroy_iface(phba->ipv4_iface);
++}
++
++static int
++beiscsi_set_static_ip(struct Scsi_Host *shost,
++		struct iscsi_iface_param_info *iface_param,
++		void *data, uint32_t dt_len)
++{
++	struct beiscsi_hba *phba = iscsi_host_priv(shost);
++	struct iscsi_iface_param_info *iface_ip = NULL;
++	struct iscsi_iface_param_info *iface_subnet = NULL;
++	struct nlattr *nla;
++	int ret;
++
++
++	switch (iface_param->param) {
++	case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
++		nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_ADDR);
++		if (nla)
++			iface_ip = nla_data(nla);
++
++		nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_SUBNET);
++		if (nla)
++			iface_subnet = nla_data(nla);
++		break;
++	case ISCSI_NET_PARAM_IPV4_ADDR:
++		iface_ip = iface_param;
++		nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_SUBNET);
++		if (nla)
++			iface_subnet = nla_data(nla);
++		break;
++	case ISCSI_NET_PARAM_IPV4_SUBNET:
++		iface_subnet = iface_param;
++		nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_ADDR);
++		if (nla)
++			iface_ip = nla_data(nla);
++		break;
++	default:
++		shost_printk(KERN_ERR, shost, "Unsupported param %d\n",
++			     iface_param->param);
++	}
++
++	if (!iface_ip || !iface_subnet) {
++		shost_printk(KERN_ERR, shost, "IP and Subnet Mask required\n");
++		return -EINVAL;
++	}
++
++	ret = mgmt_set_ip(phba, iface_ip, iface_subnet,
++			ISCSI_BOOTPROTO_STATIC);
++
++	return ret;
++}
++
++static int
++beiscsi_set_ipv4(struct Scsi_Host *shost,
++		struct iscsi_iface_param_info *iface_param,
++		void *data, uint32_t dt_len)
++{
++	struct beiscsi_hba *phba = iscsi_host_priv(shost);
++	int ret = 0;
++
++	/* Check the param */
++	switch (iface_param->param) {
++	case ISCSI_NET_PARAM_IPV4_GW:
++		ret = mgmt_set_gateway(phba, iface_param);
++		break;
++	case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
++		if (iface_param->value[0] == ISCSI_BOOTPROTO_DHCP)
++			ret = mgmt_set_ip(phba, iface_param,
++					NULL, ISCSI_BOOTPROTO_DHCP);
++		else if (iface_param->value[0] == ISCSI_BOOTPROTO_STATIC)
++			ret = beiscsi_set_static_ip(shost, iface_param,
++						    data, dt_len);
++		else
++			shost_printk(KERN_ERR, shost, "Invalid BOOTPROTO: %d\n",
++					iface_param->value[0]);
++		break;
++	case ISCSI_NET_PARAM_IFACE_ENABLE:
++		if (iface_param->value[0] == ISCSI_IFACE_ENABLE)
++			ret = beiscsi_create_ipv4_iface(phba);
++		else
++			iscsi_destroy_iface(phba->ipv4_iface);
++		break;
++	case ISCSI_NET_PARAM_IPV4_SUBNET:
++	case ISCSI_NET_PARAM_IPV4_ADDR:
++		ret = beiscsi_set_static_ip(shost, iface_param,
++					    data, dt_len);
++		break;
++	default:
++		shost_printk(KERN_ERR, shost, "Param %d not supported\n",
++			     iface_param->param);
++	}
++
++	return ret;
++}
++
++static int
++beiscsi_set_ipv6(struct Scsi_Host *shost,
++		struct iscsi_iface_param_info *iface_param,
++		void *data, uint32_t dt_len)
++{
++	struct beiscsi_hba *phba = iscsi_host_priv(shost);
++	int ret = 0;
++
++	switch (iface_param->param) {
++	case ISCSI_NET_PARAM_IFACE_ENABLE:
++		if (iface_param->value[0] == ISCSI_IFACE_ENABLE)
++			ret = beiscsi_create_ipv6_iface(phba);
++		else {
++			iscsi_destroy_iface(phba->ipv6_iface);
++			ret = 0;
++		}
++		break;
++	case ISCSI_NET_PARAM_IPV6_ADDR:
++		ret = mgmt_set_ip(phba, iface_param, NULL,
++				  ISCSI_BOOTPROTO_STATIC);
++		break;
++	default:
++		shost_printk(KERN_ERR, shost, "Param %d not supported\n",
++			     iface_param->param);
++	}
++
++	return ret;
++}
++
++int be2iscsi_iface_set_param(struct Scsi_Host *shost,
++		void *data, uint32_t dt_len)
++{
++	struct iscsi_iface_param_info *iface_param = NULL;
++	struct nlattr *attrib;
++	uint32_t rm_len = dt_len;
++	int ret = 0 ;
++
++	nla_for_each_attr(attrib, data, dt_len, rm_len) {
++		iface_param = nla_data(attrib);
++
++		if (iface_param->param_type != ISCSI_NET_PARAM)
++			continue;
++
++		/*
++		 * BE2ISCSI only supports 1 interface
++		 */
++		if (iface_param->iface_num) {
++			shost_printk(KERN_ERR, shost, "Invalid iface_num %d."
++				     "Only iface_num 0 is supported.\n",
++				     iface_param->iface_num);
++			return -EINVAL;
++		}
++
++		switch (iface_param->iface_type) {
++		case ISCSI_IFACE_TYPE_IPV4:
++			ret = beiscsi_set_ipv4(shost, iface_param,
++					       data, dt_len);
++			break;
++		case ISCSI_IFACE_TYPE_IPV6:
++			ret = beiscsi_set_ipv6(shost, iface_param,
++					       data, dt_len);
++			break;
++		default:
++			shost_printk(KERN_ERR, shost,
++				     "Invalid iface type :%d passed\n",
++				     iface_param->iface_type);
++			break;
++		}
++
++		if (ret)
++			return ret;
++	}
++
++	return ret;
++}
++
++static int be2iscsi_get_if_param(struct beiscsi_hba *phba,
++		struct iscsi_iface *iface, int param,
++		char *buf)
++{
++	struct be_cmd_get_if_info_resp if_info;
++	int len, ip_type = BE2_IPV4;
++
++	memset(&if_info, 0, sizeof(if_info));
++
++	if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
++		ip_type = BE2_IPV6;
++
++	len = mgmt_get_if_info(phba, ip_type, &if_info);
++	if (len)
++		return len;
++
++	switch (param) {
++	case ISCSI_NET_PARAM_IPV4_ADDR:
++		len = sprintf(buf, "%pI4\n", &if_info.ip_addr.addr);
++		break;
++	case ISCSI_NET_PARAM_IPV6_ADDR:
++		len = sprintf(buf, "%pI6\n", &if_info.ip_addr.addr);
++		break;
++	case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
++		if (!if_info.dhcp_state)
++			len = sprintf(buf, "static");
++		else
++			len = sprintf(buf, "dhcp");
++		break;
++	case ISCSI_NET_PARAM_IPV4_SUBNET:
++		len = sprintf(buf, "%pI4\n", &if_info.ip_addr.subnet_mask);
++		break;
++	default:
++		WARN_ON(1);
++	}
++
++	return len;
++}
++
++int be2iscsi_iface_get_param(struct iscsi_iface *iface,
++		enum iscsi_param_type param_type,
++		int param, char *buf)
++{
++	struct Scsi_Host *shost = iscsi_iface_to_shost(iface);
++	struct beiscsi_hba *phba = iscsi_host_priv(shost);
++	struct be_cmd_get_def_gateway_resp gateway;
++	int len = -ENOSYS;
++
++	switch (param) {
++	case ISCSI_NET_PARAM_IPV4_ADDR:
++	case ISCSI_NET_PARAM_IPV4_SUBNET:
++	case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
++	case ISCSI_NET_PARAM_IPV6_ADDR:
++		len = be2iscsi_get_if_param(phba, iface, param, buf);
++		break;
++	case ISCSI_NET_PARAM_IFACE_ENABLE:
++		len = sprintf(buf, "enabled");
++		break;
++	case ISCSI_NET_PARAM_IPV4_GW:
++		memset(&gateway, 0, sizeof(gateway));
++		len = mgmt_get_gateway(phba, BE2_IPV4, &gateway);
++		if (!len)
++			len = sprintf(buf, "%pI4\n", &gateway.ip_addr.addr);
++		break;
++	default:
++		len = -ENOSYS;
++	}
++
++	return len;
++}
++
+ /**
+  * beiscsi_ep_get_param - get the iscsi parameter
+  * @ep: pointer to iscsi ep
+@@ -359,46 +656,21 @@ int beiscsi_get_host_param(struct Scsi_Host *shost,
+ 
+ int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba)
+ {
+-	struct be_cmd_resp_get_mac_addr *resp;
+-	struct be_mcc_wrb *wrb;
+-	unsigned int tag, wrb_num;
+-	unsigned short status, extd_status;
+-	struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
++	struct be_cmd_get_nic_conf_resp resp;
+ 	int rc;
+ 
+-	if (phba->read_mac_address)
+-		return sysfs_format_mac(buf, phba->mac_address,
+-					ETH_ALEN);
++	if (strlen(phba->mac_address))
++		return strlcpy(buf, phba->mac_address, PAGE_SIZE);
+ 
+-	tag = be_cmd_get_mac_addr(phba);
+-	if (!tag) {
+-		SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n");
+-		return -EBUSY;
+-	} else
+-		wait_event_interruptible(phba->ctrl.mcc_wait[tag],
+-					 phba->ctrl.mcc_numtag[tag]);
++	memset(&resp, 0, sizeof(resp));
++	rc = mgmt_get_nic_conf(phba, &resp);
++	if (rc)
++		return rc;
+ 
+-	wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
+-	extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
+-	status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
+-	if (status || extd_status) {
+-		SE_DEBUG(DBG_LVL_1, "Failed to get be_cmd_get_mac_addr"
+-				    " status = %d extd_status = %d\n",
+-				    status, extd_status);
+-		free_mcc_tag(&phba->ctrl, tag);
+-		return -EAGAIN;
+-	}
+-	wrb = queue_get_wrb(mccq, wrb_num);
+-	free_mcc_tag(&phba->ctrl, tag);
+-	resp = embedded_payload(wrb);
+-	memcpy(phba->mac_address, resp->mac_address, ETH_ALEN);
+-	rc = sysfs_format_mac(buf, phba->mac_address,
+-			       ETH_ALEN);
+-	phba->read_mac_address = 1;
+-	return rc;
++	memcpy(phba->mac_address, resp.mac_address, ETH_ALEN);
++	return sysfs_format_mac(buf, phba->mac_address, ETH_ALEN);
+ }
+ 
+-
+ /**
+  * beiscsi_conn_get_stats - get the iscsi stats
+  * @cls_conn: pointer to iscsi cls conn
+@@ -786,11 +1058,21 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
+ umode_t be2iscsi_attr_is_visible(int param_type, int param)
+ {
+ 	switch (param_type) {
++	case ISCSI_NET_PARAM:
++		switch (param) {
++		case ISCSI_NET_PARAM_IFACE_ENABLE:
++		case ISCSI_NET_PARAM_IPV4_ADDR:
++		case ISCSI_NET_PARAM_IPV4_SUBNET:
++		case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
++		case ISCSI_NET_PARAM_IPV4_GW:
++		case ISCSI_NET_PARAM_IPV6_ADDR:
++			return S_IRUGO;
++		default:
++			return 0;
++		}
+ 	case ISCSI_HOST_PARAM:
+ 		switch (param) {
+ 		case ISCSI_HOST_PARAM_HWADDRESS:
+-		case ISCSI_HOST_PARAM_IPADDRESS:
+-		case ISCSI_HOST_PARAM_INITIATOR_NAME:
+ 			return S_IRUGO;
+ 		default:
+ 			return 0;
+diff --git a/drivers/scsi/be2iscsi/be_iscsi.h b/drivers/scsi/be2iscsi/be_iscsi.h
+index 5c45be134501..8b826fc06bcc 100644
+--- a/drivers/scsi/be2iscsi/be_iscsi.h
++++ b/drivers/scsi/be2iscsi/be_iscsi.h
+@@ -25,6 +25,21 @@
+ 
+ #define BE2_IPV4  0x1
+ #define BE2_IPV6  0x10
++#define BE2_DHCP_V4 0x05
++
++#define NON_BLOCKING 0x0
++#define BLOCKING 0x1
++
++void beiscsi_create_def_ifaces(struct beiscsi_hba *phba);
++
++void beiscsi_destroy_def_ifaces(struct beiscsi_hba *phba);
++
++int be2iscsi_iface_get_param(struct iscsi_iface *iface,
++			     enum iscsi_param_type param_type,
++			     int param, char *buf);
++
++int be2iscsi_iface_set_param(struct Scsi_Host *shost,
++			     void *data, uint32_t count);
+ 
+ umode_t be2iscsi_attr_is_visible(int param_type, int param);
+ 
+diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
+index ff6f851d6fb8..0b1d99c99fd2 100644
+--- a/drivers/scsi/be2iscsi/be_main.c
++++ b/drivers/scsi/be2iscsi/be_main.c
+@@ -231,10 +231,10 @@ static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf)
+ 	case ISCSI_BOOT_TGT_IP_ADDR:
+ 		if (boot_conn->dest_ipaddr.ip_type == 0x1)
+ 			rc = sprintf(buf, "%pI4\n",
+-				(char *)&boot_conn->dest_ipaddr.ip_address);
++				(char *)&boot_conn->dest_ipaddr.addr);
+ 		else
+ 			rc = sprintf(str, "%pI6\n",
+-				(char *)&boot_conn->dest_ipaddr.ip_address);
++				(char *)&boot_conn->dest_ipaddr.addr);
+ 		break;
+ 	case ISCSI_BOOT_TGT_PORT:
+ 		rc = sprintf(str, "%d\n", boot_conn->dest_port);
+@@ -312,12 +312,8 @@ static ssize_t beiscsi_show_boot_eth_info(void *data, int type, char *buf)
+ 		rc = sprintf(str, "0\n");
+ 		break;
+ 	case ISCSI_BOOT_ETH_MAC:
+-		rc  = beiscsi_get_macaddr(buf, phba);
+-		if (rc < 0) {
+-			SE_DEBUG(DBG_LVL_1, "beiscsi_get_macaddr Failed\n");
+-			return rc;
+-		}
+-	break;
++		rc  = beiscsi_get_macaddr(str, phba);
++		break;
+ 	default:
+ 		rc = -ENOSYS;
+ 		break;
+@@ -438,6 +434,7 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev)
+ 	phba->shost = shost;
+ 	phba->pcidev = pci_dev_get(pcidev);
+ 	pci_set_drvdata(pcidev, phba);
++	phba->interface_handle = 0xFFFFFFFF;
+ 
+ 	if (iscsi_host_add(shost, &phba->pcidev->dev))
+ 		goto free_devices;
+@@ -3471,8 +3468,8 @@ static void hwi_disable_intr(struct beiscsi_hba *phba)
+ 
+ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
+ {
+-	struct be_cmd_resp_get_boot_target *boot_resp;
+-	struct be_cmd_resp_get_session *session_resp;
++	struct be_cmd_get_boot_target_resp *boot_resp;
++	struct be_cmd_get_session_resp *session_resp;
+ 	struct be_mcc_wrb *wrb;
+ 	struct be_dma_mem nonemb_cmd;
+ 	unsigned int tag, wrb_num;
+@@ -3480,9 +3477,9 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
+ 	struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
+ 	int ret = -ENOMEM;
+ 
+-	tag = beiscsi_get_boot_target(phba);
++	tag = mgmt_get_boot_target(phba);
+ 	if (!tag) {
+-		SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n");
++		SE_DEBUG(DBG_LVL_1, "beiscsi_get_boot_info Failed\n");
+ 		return -EAGAIN;
+ 	} else
+ 		wait_event_interruptible(phba->ctrl.mcc_wait[tag],
+@@ -3492,7 +3489,7 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
+ 	extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
+ 	status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
+ 	if (status || extd_status) {
+-		SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed"
++		SE_DEBUG(DBG_LVL_1, "beiscsi_get_boot_info Failed"
+ 				    " status = %d extd_status = %d\n",
+ 				    status, extd_status);
+ 		free_mcc_tag(&phba->ctrl, tag);
+@@ -3518,8 +3515,8 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
+ 	}
+ 
+ 	memset(nonemb_cmd.va, 0, sizeof(*session_resp));
+-	tag = beiscsi_get_session_info(phba,
+-		boot_resp->boot_session_handle, &nonemb_cmd);
++	tag = mgmt_get_session_info(phba, boot_resp->boot_session_handle,
++				    &nonemb_cmd);
+ 	if (!tag) {
+ 		SE_DEBUG(DBG_LVL_1, "beiscsi_get_session_info"
+ 			" Failed\n");
+@@ -4267,6 +4264,7 @@ static void beiscsi_remove(struct pci_dev *pcidev)
+ 		return;
+ 	}
+ 
++	beiscsi_destroy_def_ifaces(phba);
+ 	beiscsi_quiesce(phba);
+ 	iscsi_boot_destroy_kset(phba->boot_kset);
+ 	iscsi_host_remove(phba->shost);
+@@ -4453,8 +4451,9 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
+ 		 * iscsi boot.
+ 		 */
+ 		shost_printk(KERN_ERR, phba->shost, "Could not set up "
+-			     "iSCSI boot info.");
++			     "iSCSI boot info.\n");
+ 
++	beiscsi_create_def_ifaces(phba);
+ 	SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED\n\n\n");
+ 	return 0;
+ 
+@@ -4505,6 +4504,8 @@ struct iscsi_transport beiscsi_iscsi_transport = {
+ 	.bind_conn = beiscsi_conn_bind,
+ 	.destroy_conn = iscsi_conn_teardown,
+ 	.attr_is_visible = be2iscsi_attr_is_visible,
++	.set_iface_param = be2iscsi_iface_set_param,
++	.get_iface_param = be2iscsi_iface_get_param,
+ 	.set_param = beiscsi_set_param,
+ 	.get_conn_param = iscsi_conn_get_param,
+ 	.get_session_param = iscsi_session_get_param,
+diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h
+index 13e3bef1d324..40fea6ec879c 100644
+--- a/drivers/scsi/be2iscsi/be_main.h
++++ b/drivers/scsi/be2iscsi/be_main.h
+@@ -316,6 +316,8 @@ struct beiscsi_hba {
+ 	struct iscsi_endpoint **ep_array;
+ 	struct iscsi_boot_kset *boot_kset;
+ 	struct Scsi_Host *shost;
++	struct iscsi_iface *ipv4_iface;
++	struct iscsi_iface *ipv6_iface;
+ 	struct {
+ 		/**
+ 		 * group together since they are used most frequently
+@@ -345,7 +347,7 @@ struct beiscsi_hba {
+ 	struct work_struct work_cqs;	/* The work being queued */
+ 	struct be_ctrl_info ctrl;
+ 	unsigned int generation;
+-	unsigned int read_mac_address;
++	unsigned int interface_handle;
+ 	struct mgmt_session_info boot_sess;
+ 	struct invalidate_command_table inv_tbl[128];
+ 
+diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c
+index ccc3852a7f30..e6cb10d2e74e 100644
+--- a/drivers/scsi/be2iscsi/be_mgmt.c
++++ b/drivers/scsi/be2iscsi/be_mgmt.c
+@@ -23,11 +23,11 @@
+ #include "be_mgmt.h"
+ #include "be_iscsi.h"
+ 
+-unsigned int beiscsi_get_boot_target(struct beiscsi_hba *phba)
++unsigned int mgmt_get_boot_target(struct beiscsi_hba *phba)
+ {
+ 	struct be_ctrl_info *ctrl = &phba->ctrl;
+ 	struct be_mcc_wrb *wrb;
+-	struct be_cmd_req_get_mac_addr *req;
++	struct be_cmd_get_boot_target_req *req;
+ 	unsigned int tag = 0;
+ 
+ 	SE_DEBUG(DBG_LVL_8, "In bescsi_get_boot_target\n");
+@@ -44,22 +44,22 @@ unsigned int beiscsi_get_boot_target(struct beiscsi_hba *phba)
+ 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+ 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
+ 			   OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET,
+-			   sizeof(*req));
++			   sizeof(struct be_cmd_get_boot_target_resp));
+ 
+ 	be_mcc_notify(phba);
+ 	spin_unlock(&ctrl->mbox_lock);
+ 	return tag;
+ }
+ 
+-unsigned int beiscsi_get_session_info(struct beiscsi_hba *phba,
+-				  u32 boot_session_handle,
+-				  struct be_dma_mem *nonemb_cmd)
++unsigned int mgmt_get_session_info(struct beiscsi_hba *phba,
++				   u32 boot_session_handle,
++				   struct be_dma_mem *nonemb_cmd)
+ {
+ 	struct be_ctrl_info *ctrl = &phba->ctrl;
+ 	struct be_mcc_wrb *wrb;
+ 	unsigned int tag = 0;
+-	struct  be_cmd_req_get_session *req;
+-	struct be_cmd_resp_get_session *resp;
++	struct  be_cmd_get_session_req *req;
++	struct be_cmd_get_session_resp *resp;
+ 	struct be_sge *sge;
+ 
+ 	SE_DEBUG(DBG_LVL_8, "In beiscsi_get_session_info\n");
+@@ -396,7 +396,6 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
+ 			 struct sockaddr *dst_addr,
+ 			 struct beiscsi_endpoint *beiscsi_ep,
+ 			 struct be_dma_mem *nonemb_cmd)
+-
+ {
+ 	struct hwi_controller *phwi_ctrlr;
+ 	struct hwi_context_memory *phwi_context;
+@@ -442,17 +441,17 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
+ 	if (dst_addr->sa_family == PF_INET) {
+ 		__be32 s_addr = daddr_in->sin_addr.s_addr;
+ 		req->ip_address.ip_type = BE2_IPV4;
+-		req->ip_address.ip_address[0] = s_addr & 0x000000ff;
+-		req->ip_address.ip_address[1] = (s_addr & 0x0000ff00) >> 8;
+-		req->ip_address.ip_address[2] = (s_addr & 0x00ff0000) >> 16;
+-		req->ip_address.ip_address[3] = (s_addr & 0xff000000) >> 24;
++		req->ip_address.addr[0] = s_addr & 0x000000ff;
++		req->ip_address.addr[1] = (s_addr & 0x0000ff00) >> 8;
++		req->ip_address.addr[2] = (s_addr & 0x00ff0000) >> 16;
++		req->ip_address.addr[3] = (s_addr & 0xff000000) >> 24;
+ 		req->tcp_port = ntohs(daddr_in->sin_port);
+ 		beiscsi_ep->dst_addr = daddr_in->sin_addr.s_addr;
+ 		beiscsi_ep->dst_tcpport = ntohs(daddr_in->sin_port);
+ 		beiscsi_ep->ip_type = BE2_IPV4;
+ 	} else if (dst_addr->sa_family == PF_INET6) {
+ 		req->ip_address.ip_type = BE2_IPV6;
+-		memcpy(&req->ip_address.ip_address,
++		memcpy(&req->ip_address.addr,
+ 		       &daddr_in6->sin6_addr.in6_u.u6_addr8, 16);
+ 		req->tcp_port = ntohs(daddr_in6->sin6_port);
+ 		beiscsi_ep->dst_tcpport = ntohs(daddr_in6->sin6_port);
+@@ -487,34 +486,392 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
+ 	return tag;
+ }
+ 
+-unsigned int be_cmd_get_mac_addr(struct beiscsi_hba *phba)
++unsigned int mgmt_get_all_if_id(struct beiscsi_hba *phba)
+ {
+ 	struct be_ctrl_info *ctrl = &phba->ctrl;
+-	struct be_mcc_wrb *wrb;
+-	struct be_cmd_req_get_mac_addr *req;
+-	unsigned int tag = 0;
++	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
++	struct be_cmd_get_all_if_id_req *req = embedded_payload(wrb);
++	struct be_cmd_get_all_if_id_req *pbe_allid = req;
++	int status = 0;
++
++	memset(wrb, 0, sizeof(*wrb));
++
++	spin_lock(&ctrl->mbox_lock);
++
++	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
++	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
++			   OPCODE_COMMON_ISCSI_NTWK_GET_ALL_IF_ID,
++			   sizeof(*req));
++	status = be_mbox_notify(ctrl);
++	if (!status)
++		phba->interface_handle = pbe_allid->if_hndl_list[0];
++	else {
++		shost_printk(KERN_WARNING, phba->shost,
++			     "Failed in mgmt_get_all_if_id\n");
++	}
++	spin_unlock(&ctrl->mbox_lock);
++
++	return status;
++}
++
++static int mgmt_exec_nonemb_cmd(struct beiscsi_hba *phba,
++				struct be_dma_mem *nonemb_cmd, void *resp_buf,
++				int resp_buf_len)
++{
++	struct be_ctrl_info *ctrl = &phba->ctrl;
++	struct be_mcc_wrb *wrb = wrb_from_mccq(phba);
++	unsigned short status, extd_status;
++	struct be_sge *sge;
++	unsigned int tag;
++	int rc = 0;
+ 
+-	SE_DEBUG(DBG_LVL_8, "In be_cmd_get_mac_addr\n");
+ 	spin_lock(&ctrl->mbox_lock);
+ 	tag = alloc_mcc_tag(phba);
+ 	if (!tag) {
+ 		spin_unlock(&ctrl->mbox_lock);
+-		return tag;
++		rc = -ENOMEM;
++		goto free_cmd;
+ 	}
+-
+-	wrb = wrb_from_mccq(phba);
+-	req = embedded_payload(wrb);
++	memset(wrb, 0, sizeof(*wrb));
+ 	wrb->tag0 |= tag;
+-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
+-			   OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG,
+-			   sizeof(*req));
++	sge = nonembedded_sgl(wrb);
++
++	be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 1);
++	sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
++	sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
++	sge->len = cpu_to_le32(nonemb_cmd->size);
+ 
+ 	be_mcc_notify(phba);
+ 	spin_unlock(&ctrl->mbox_lock);
+-	return tag;
++
++	wait_event_interruptible(phba->ctrl.mcc_wait[tag],
++				 phba->ctrl.mcc_numtag[tag]);
++
++	extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
++	status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
++	if (status || extd_status) {
++		SE_DEBUG(DBG_LVL_1,
++			 "mgmt_exec_nonemb_cmd Failed status = %d"
++			 "extd_status = %d\n", status, extd_status);
++		rc = -EIO;
++		goto free_tag;
++	}
++
++	if (resp_buf)
++		memcpy(resp_buf, nonemb_cmd->va, resp_buf_len);
++
++free_tag:
++	free_mcc_tag(&phba->ctrl, tag);
++free_cmd:
++	pci_free_consistent(ctrl->pdev, nonemb_cmd->size,
++			    nonemb_cmd->va, nonemb_cmd->dma);
++	return rc;
++}
++
++static int mgmt_alloc_cmd_data(struct beiscsi_hba *phba, struct be_dma_mem *cmd,
++			       int iscsi_cmd, int size)
++{
++	cmd->va = pci_alloc_consistent(phba->ctrl.pdev, sizeof(size),
++				       &cmd->dma);
++	if (!cmd->va) {
++		SE_DEBUG(DBG_LVL_1, "Failed to allocate memory for if info\n");
++		return -ENOMEM;
++	}
++	memset(cmd->va, 0, sizeof(size));
++	cmd->size = size;
++	be_cmd_hdr_prepare(cmd->va, CMD_SUBSYSTEM_ISCSI, iscsi_cmd, size);
++	return 0;
+ }
+ 
++static int
++mgmt_static_ip_modify(struct beiscsi_hba *phba,
++		      struct be_cmd_get_if_info_resp *if_info,
++		      struct iscsi_iface_param_info *ip_param,
++		      struct iscsi_iface_param_info *subnet_param,
++		      uint32_t ip_action)
++{
++	struct be_cmd_set_ip_addr_req *req;
++	struct be_dma_mem nonemb_cmd;
++	uint32_t ip_type;
++	int rc;
++
++	rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
++				 OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR,
++				 sizeof(*req));
++	if (rc)
++		return rc;
++
++	ip_type = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ?
++		BE2_IPV6 : BE2_IPV4 ;
++
++	req = nonemb_cmd.va;
++	req->ip_params.record_entry_count = 1;
++	req->ip_params.ip_record.action = ip_action;
++	req->ip_params.ip_record.interface_hndl =
++		phba->interface_handle;
++	req->ip_params.ip_record.ip_addr.size_of_structure =
++		sizeof(struct be_ip_addr_subnet_format);
++	req->ip_params.ip_record.ip_addr.ip_type = ip_type;
++
++	if (ip_action == IP_ACTION_ADD) {
++		memcpy(req->ip_params.ip_record.ip_addr.addr, ip_param->value,
++		       ip_param->len);
++
++		if (subnet_param)
++			memcpy(req->ip_params.ip_record.ip_addr.subnet_mask,
++			       subnet_param->value, subnet_param->len);
++	} else {
++		memcpy(req->ip_params.ip_record.ip_addr.addr,
++		       if_info->ip_addr.addr, ip_param->len);
++
++		memcpy(req->ip_params.ip_record.ip_addr.subnet_mask,
++		       if_info->ip_addr.subnet_mask, ip_param->len);
++	}
++
++	rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
++	if (rc < 0)
++		shost_printk(KERN_WARNING, phba->shost,
++			     "Failed to Modify existing IP Address\n");
++	return rc;
++}
++
++static int mgmt_modify_gateway(struct beiscsi_hba *phba, uint8_t *gt_addr,
++			       uint32_t gtway_action, uint32_t param_len)
++{
++	struct be_cmd_set_def_gateway_req *req;
++	struct be_dma_mem nonemb_cmd;
++	int rt_val;
++
++
++	rt_val = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
++				OPCODE_COMMON_ISCSI_NTWK_MODIFY_DEFAULT_GATEWAY,
++				sizeof(*req));
++	if (rt_val)
++		return rt_val;
++
++	req = nonemb_cmd.va;
++	req->action = gtway_action;
++	req->ip_addr.ip_type = BE2_IPV4;
++
++	memcpy(req->ip_addr.addr, gt_addr, param_len);
++
++	return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
++}
++
++int mgmt_set_ip(struct beiscsi_hba *phba,
++		struct iscsi_iface_param_info *ip_param,
++		struct iscsi_iface_param_info *subnet_param,
++		uint32_t boot_proto)
++{
++	struct be_cmd_get_def_gateway_resp gtway_addr_set;
++	struct be_cmd_get_if_info_resp if_info;
++	struct be_cmd_set_dhcp_req *dhcpreq;
++	struct be_cmd_rel_dhcp_req *reldhcp;
++	struct be_dma_mem nonemb_cmd;
++	uint8_t *gtway_addr;
++	uint32_t ip_type;
++	int rc;
++
++	if (mgmt_get_all_if_id(phba))
++		return -EIO;
++
++	memset(&if_info, 0, sizeof(if_info));
++	ip_type = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ?
++		BE2_IPV6 : BE2_IPV4 ;
++
++	rc = mgmt_get_if_info(phba, ip_type, &if_info);
++	if (rc)
++		return rc;
++
++	if (boot_proto == ISCSI_BOOTPROTO_DHCP) {
++		if (if_info.dhcp_state) {
++			shost_printk(KERN_WARNING, phba->shost,
++				     "DHCP Already Enabled\n");
++			return 0;
++		}
++		/* The ip_param->len is 1 in DHCP case. Setting
++		   proper IP len as this it is used while
++		   freeing the Static IP.
++		 */
++		ip_param->len = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ?
++				IP_V6_LEN : IP_V4_LEN;
++
++	} else {
++		if (if_info.dhcp_state) {
++
++			memset(&if_info, 0, sizeof(if_info));
++			rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
++				OPCODE_COMMON_ISCSI_NTWK_REL_STATELESS_IP_ADDR,
++				sizeof(*reldhcp));
++
++			if (rc)
++				return rc;
++
++			reldhcp = nonemb_cmd.va;
++			reldhcp->interface_hndl = phba->interface_handle;
++			reldhcp->ip_type = ip_type;
++
++			rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
++			if (rc < 0) {
++				shost_printk(KERN_WARNING, phba->shost,
++					     "Failed to Delete existing dhcp\n");
++				return rc;
++			}
++		}
++	}
++
++	/* Delete the Static IP Set */
++	if (if_info.ip_addr.addr[0]) {
++		rc = mgmt_static_ip_modify(phba, &if_info, ip_param, NULL,
++					   IP_ACTION_DEL);
++		if (rc)
++			return rc;
++	}
++
++	/* Delete the Gateway settings if mode change is to DHCP */
++	if (boot_proto == ISCSI_BOOTPROTO_DHCP) {
++		memset(>way_addr_set, 0, sizeof(gtway_addr_set));
++		rc = mgmt_get_gateway(phba, BE2_IPV4, >way_addr_set);
++		if (rc) {
++			shost_printk(KERN_WARNING, phba->shost,
++				     "Failed to Get Gateway Addr\n");
++			return rc;
++		}
++
++		if (gtway_addr_set.ip_addr.addr[0]) {
++			gtway_addr = (uint8_t *)>way_addr_set.ip_addr.addr;
++			rc = mgmt_modify_gateway(phba, gtway_addr,
++						 IP_ACTION_DEL, IP_V4_LEN);
++
++			if (rc) {
++				shost_printk(KERN_WARNING, phba->shost,
++					     "Failed to clear Gateway Addr Set\n");
++				return rc;
++			}
++		}
++	}
++
++	/* Set Adapter to DHCP/Static Mode */
++	if (boot_proto == ISCSI_BOOTPROTO_DHCP) {
++		rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
++			OPCODE_COMMON_ISCSI_NTWK_CONFIG_STATELESS_IP_ADDR,
++			sizeof(*dhcpreq));
++		if (rc)
++			return rc;
++
++		dhcpreq = nonemb_cmd.va;
++		dhcpreq->flags = BLOCKING;
++		dhcpreq->retry_count = 1;
++		dhcpreq->interface_hndl = phba->interface_handle;
++		dhcpreq->ip_type = BE2_DHCP_V4;
++
++		return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
++	} else {
++		return mgmt_static_ip_modify(phba, &if_info, ip_param,
++					     subnet_param, IP_ACTION_ADD);
++	}
++
++	return rc;
++}
++
++int mgmt_set_gateway(struct beiscsi_hba *phba,
++		     struct iscsi_iface_param_info *gateway_param)
++{
++	struct be_cmd_get_def_gateway_resp gtway_addr_set;
++	uint8_t *gtway_addr;
++	int rt_val;
++
++	memset(>way_addr_set, 0, sizeof(gtway_addr_set));
++	rt_val = mgmt_get_gateway(phba, BE2_IPV4, >way_addr_set);
++	if (rt_val) {
++		shost_printk(KERN_WARNING, phba->shost,
++			     "Failed to Get Gateway Addr\n");
++		return rt_val;
++	}
++
++	if (gtway_addr_set.ip_addr.addr[0]) {
++		gtway_addr = (uint8_t *)>way_addr_set.ip_addr.addr;
++		rt_val = mgmt_modify_gateway(phba, gtway_addr, IP_ACTION_DEL,
++					     gateway_param->len);
++		if (rt_val) {
++			shost_printk(KERN_WARNING, phba->shost,
++				     "Failed to clear Gateway Addr Set\n");
++			return rt_val;
++		}
++	}
++
++	gtway_addr = (uint8_t *)&gateway_param->value;
++	rt_val = mgmt_modify_gateway(phba, gtway_addr, IP_ACTION_ADD,
++				     gateway_param->len);
++
++	if (rt_val)
++		shost_printk(KERN_WARNING, phba->shost,
++			     "Failed to Set Gateway Addr\n");
++
++	return rt_val;
++}
++
++int mgmt_get_gateway(struct beiscsi_hba *phba, int ip_type,
++		     struct be_cmd_get_def_gateway_resp *gateway)
++{
++	struct be_cmd_get_def_gateway_req *req;
++	struct be_dma_mem nonemb_cmd;
++	int rc;
++
++	rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
++				 OPCODE_COMMON_ISCSI_NTWK_GET_DEFAULT_GATEWAY,
++				 sizeof(*gateway));
++	if (rc)
++		return rc;
++
++	req = nonemb_cmd.va;
++	req->ip_type = ip_type;
++
++	return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, gateway,
++				    sizeof(*gateway));
++}
++
++int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type,
++		     struct be_cmd_get_if_info_resp *if_info)
++{
++	struct be_cmd_get_if_info_req *req;
++	struct be_dma_mem nonemb_cmd;
++	int rc;
++
++	if (mgmt_get_all_if_id(phba))
++		return -EIO;
++
++	rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
++				 OPCODE_COMMON_ISCSI_NTWK_GET_IF_INFO,
++				 sizeof(*if_info));
++	if (rc)
++		return rc;
++
++	req = nonemb_cmd.va;
++	req->interface_hndl = phba->interface_handle;
++	req->ip_type = ip_type;
++
++	return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, if_info,
++				    sizeof(*if_info));
++}
++
++int mgmt_get_nic_conf(struct beiscsi_hba *phba,
++		      struct be_cmd_get_nic_conf_resp *nic)
++{
++	struct be_dma_mem nonemb_cmd;
++	int rc;
++
++	rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
++				 OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG,
++				 sizeof(*nic));
++	if (rc)
++		return rc;
++
++	return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, nic, sizeof(*nic));
++}
++
++
++
+ unsigned int be_cmd_get_initname(struct beiscsi_hba *phba)
+ {
+ 	unsigned int tag = 0;
+diff --git a/drivers/scsi/be2iscsi/be_mgmt.h b/drivers/scsi/be2iscsi/be_mgmt.h
+index 03400f3f666f..5c2e37693ca8 100644
+--- a/drivers/scsi/be2iscsi/be_mgmt.h
++++ b/drivers/scsi/be2iscsi/be_mgmt.h
+@@ -20,12 +20,16 @@
+ #ifndef _BEISCSI_MGMT_
+ #define _BEISCSI_MGMT_
+ 
+-#include 
+-#include 
+ #include 
+ #include "be_iscsi.h"
+ #include "be_main.h"
+ 
++#define IP_ACTION_ADD	0x01
++#define IP_ACTION_DEL	0x02
++
++#define IP_V6_LEN	16
++#define IP_V4_LEN	4
++
+ /**
+  * Pseudo amap definition in which each bit of the actual structure is defined
+  * as a byte: used to calculate offset/shift/mask of each field
+@@ -263,4 +267,27 @@ unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba,
+ 					 unsigned short issue_reset,
+ 					 unsigned short savecfg_flag);
+ 
++int mgmt_set_ip(struct beiscsi_hba *phba,
++		struct iscsi_iface_param_info *ip_param,
++		struct iscsi_iface_param_info *subnet_param,
++		uint32_t boot_proto);
++
++unsigned int mgmt_get_boot_target(struct beiscsi_hba *phba);
++
++unsigned int mgmt_get_session_info(struct beiscsi_hba *phba,
++				   u32 boot_session_handle,
++				   struct be_dma_mem *nonemb_cmd);
++
++int mgmt_get_nic_conf(struct beiscsi_hba *phba,
++		      struct be_cmd_get_nic_conf_resp *mac);
++
++int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type,
++		     struct be_cmd_get_if_info_resp *if_info);
++
++int mgmt_get_gateway(struct beiscsi_hba *phba, int ip_type,
++		     struct be_cmd_get_def_gateway_resp *gateway);
++
++int mgmt_set_gateway(struct beiscsi_hba *phba,
++		     struct iscsi_iface_param_info *gateway_param);
++
+ #endif

commit 1282ab76d983b2753b5cd4c9ae6b8019b0557b30
+Author: Mike Christie 
+Date:   Wed Apr 18 03:06:00 2012 -0500
+
+    [SCSI] be2iscsi: Freeing of WRB and SGL Handle in cleanup task
+    
+    The WRB and SGL Handle allocated for Login task were not freed
+    back to the pool after the login process was done. This code
+    releases the WRB and SGL Handle after the login process.
+    
+    v2:
+    - Fix up locking so bh calls are not done when not needed.
+    - Make beiscsi_cleanup_task static.
+    
+    Signed-off-by: Jayamohan Kallickal 
+    [various fixes]
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
+index 23344c8c5b79..185cf394b9f0 100644
+--- a/drivers/scsi/be2iscsi/be_main.c
++++ b/drivers/scsi/be2iscsi/be_main.c
+@@ -1252,9 +1252,9 @@ hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn,
+ 	task = pwrb_handle->pio_handle;
+ 
+ 	io_task = task->dd_data;
+-	spin_lock(&phba->mgmt_sgl_lock);
++	spin_lock_bh(&phba->mgmt_sgl_lock);
+ 	free_mgmt_sgl_handle(phba, io_task->psgl_handle);
+-	spin_unlock(&phba->mgmt_sgl_lock);
++	spin_unlock_bh(&phba->mgmt_sgl_lock);
+ 	spin_lock_bh(&session->lock);
+ 	free_wrb_handle(phba, pwrb_context, pwrb_handle);
+ 	spin_unlock_bh(&session->lock);
+@@ -3693,6 +3693,57 @@ static void beiscsi_clean_port(struct beiscsi_hba *phba)
+ 	kfree(phba->ep_array);
+ }
+ 
++static void beiscsi_cleanup_task(struct iscsi_task *task)
++{
++	struct beiscsi_io_task *io_task = task->dd_data;
++	struct iscsi_conn *conn = task->conn;
++	struct beiscsi_conn *beiscsi_conn = conn->dd_data;
++	struct beiscsi_hba *phba = beiscsi_conn->phba;
++	struct beiscsi_session *beiscsi_sess = beiscsi_conn->beiscsi_sess;
++	struct hwi_wrb_context *pwrb_context;
++	struct hwi_controller *phwi_ctrlr;
++
++	phwi_ctrlr = phba->phwi_ctrlr;
++	pwrb_context = &phwi_ctrlr->wrb_context[beiscsi_conn->beiscsi_conn_cid
++			- phba->fw_config.iscsi_cid_start];
++
++	if (io_task->cmd_bhs) {
++		pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs,
++			      io_task->bhs_pa.u.a64.address);
++		io_task->cmd_bhs = NULL;
++	}
++
++	if (task->sc) {
++		if (io_task->pwrb_handle) {
++			free_wrb_handle(phba, pwrb_context,
++					io_task->pwrb_handle);
++			io_task->pwrb_handle = NULL;
++		}
++
++		if (io_task->psgl_handle) {
++			spin_lock(&phba->io_sgl_lock);
++			free_io_sgl_handle(phba, io_task->psgl_handle);
++			spin_unlock(&phba->io_sgl_lock);
++			io_task->psgl_handle = NULL;
++		}
++	} else {
++		if (!beiscsi_conn->login_in_progress) {
++			if (io_task->pwrb_handle) {
++				free_wrb_handle(phba, pwrb_context,
++						io_task->pwrb_handle);
++				io_task->pwrb_handle = NULL;
++			}
++			if (io_task->psgl_handle) {
++				spin_lock(&phba->mgmt_sgl_lock);
++				free_mgmt_sgl_handle(phba,
++						     io_task->psgl_handle);
++				spin_unlock(&phba->mgmt_sgl_lock);
++				io_task->psgl_handle = NULL;
++			}
++		}
++	}
++}
++
+ void
+ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
+ 			   struct beiscsi_offload_params *params)
+@@ -3701,12 +3752,19 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
+ 	struct iscsi_target_context_update_wrb *pwrb = NULL;
+ 	struct be_mem_descriptor *mem_descr;
+ 	struct beiscsi_hba *phba = beiscsi_conn->phba;
++	struct iscsi_task *task = beiscsi_conn->task;
++	struct iscsi_session *session = task->conn->session;
+ 	u32 doorbell = 0;
+ 
+ 	/*
+ 	 * We can always use 0 here because it is reserved by libiscsi for
+ 	 * login/startup related tasks.
+ 	 */
++	beiscsi_conn->login_in_progress = 0;
++	spin_lock_bh(&session->lock);
++	beiscsi_cleanup_task(task);
++	spin_unlock_bh(&session->lock);
++
+ 	pwrb_handle = alloc_wrb_handle(phba, (beiscsi_conn->beiscsi_conn_cid -
+ 				       phba->fw_config.iscsi_cid_start));
+ 	pwrb = (struct iscsi_target_context_update_wrb *)pwrb_handle->pwrb;
+@@ -3862,6 +3920,7 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
+ 				io_task->pwrb_handle =
+ 						beiscsi_conn->plogin_wrb_handle;
+ 			}
++			beiscsi_conn->task = task;
+ 		} else {
+ 			spin_lock(&phba->mgmt_sgl_lock);
+ 			io_task->psgl_handle = alloc_mgmt_sgl_handle(phba);
+@@ -3904,53 +3963,11 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
+ 	io_task->pwrb_handle = NULL;
+ 	pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs,
+ 		      io_task->bhs_pa.u.a64.address);
++	io_task->cmd_bhs = NULL;
+ 	SE_DEBUG(DBG_LVL_1, "Alloc of SGL_ICD Failed\n");
+ 	return -ENOMEM;
+ }
+ 
+-static void beiscsi_cleanup_task(struct iscsi_task *task)
+-{
+-	struct beiscsi_io_task *io_task = task->dd_data;
+-	struct iscsi_conn *conn = task->conn;
+-	struct beiscsi_conn *beiscsi_conn = conn->dd_data;
+-	struct beiscsi_hba *phba = beiscsi_conn->phba;
+-	struct beiscsi_session *beiscsi_sess = beiscsi_conn->beiscsi_sess;
+-	struct hwi_wrb_context *pwrb_context;
+-	struct hwi_controller *phwi_ctrlr;
+-
+-	phwi_ctrlr = phba->phwi_ctrlr;
+-	pwrb_context = &phwi_ctrlr->wrb_context[beiscsi_conn->beiscsi_conn_cid
+-			- phba->fw_config.iscsi_cid_start];
+-	if (io_task->pwrb_handle) {
+-		free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle);
+-		io_task->pwrb_handle = NULL;
+-	}
+-
+-	if (io_task->cmd_bhs) {
+-		pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs,
+-			      io_task->bhs_pa.u.a64.address);
+-	}
+-
+-	if (task->sc) {
+-		if (io_task->psgl_handle) {
+-			spin_lock(&phba->io_sgl_lock);
+-			free_io_sgl_handle(phba, io_task->psgl_handle);
+-			spin_unlock(&phba->io_sgl_lock);
+-			io_task->psgl_handle = NULL;
+-		}
+-	} else {
+-		if (task->hdr &&
+-		   ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN))
+-			return;
+-		if (io_task->psgl_handle) {
+-			spin_lock(&phba->mgmt_sgl_lock);
+-			free_mgmt_sgl_handle(phba, io_task->psgl_handle);
+-			spin_unlock(&phba->mgmt_sgl_lock);
+-			io_task->psgl_handle = NULL;
+-		}
+-	}
+-}
+-
+ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg,
+ 			  unsigned int num_sg, unsigned int xferlen,
+ 			  unsigned int writedir)

commit e8195b24feb208f6e944e7542779f4397776794d
+Author: Matt Renzelmann 
+Date:   Thu Apr 19 07:17:17 2012 +0000
+
+    ks8851: Fix request_irq/free_irq mismatch
+    
+    The dev_id parameter passed to free_irq needs to match the one passed
+    to the corresponding request_irq.
+    
+    Signed-off-by: Matt Renzelmann 
+    Acked-by: Stephen Boyd 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c
+index ad10759e3459..f8dda009d3c0 100644
+--- a/drivers/net/ethernet/micrel/ks8851.c
++++ b/drivers/net/ethernet/micrel/ks8851.c
+@@ -1525,7 +1525,7 @@ static int __devinit ks8851_probe(struct spi_device *spi)
+ 
+ 
+ err_netdev:
+-	free_irq(ndev->irq, ndev);
++	free_irq(ndev->irq, ks);
+ 
+ err_id:
+ err_irq:

commit 579b0637647de6e03e5707b32eb7c2ce56cc0f27
+Author: Matt Renzelmann 
+Date:   Thu Apr 12 17:42:43 2012 -0500
+
+    hostap: GFP_ATOMIC/GFP_KERNEL cleanup
+    
+    The driver is allocating memory during initialization with GFP_ATOMIC
+    even though GFP_KERNEL is sufficient.  This patch fixes it.
+    
+    Signed-off-by: Matt Renzelmann 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
+index bfa0d54221e8..627bc12074c7 100644
+--- a/drivers/net/wireless/hostap/hostap_main.c
++++ b/drivers/net/wireless/hostap/hostap_main.c
+@@ -244,8 +244,7 @@ u16 hostap_tx_callback_register(local_info_t *local,
+ 	unsigned long flags;
+ 	struct hostap_tx_callback_info *entry;
+ 
+-	entry = kmalloc(sizeof(*entry),
+-							   GFP_ATOMIC);
++	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+ 	if (entry == NULL)
+ 		return 0;
+ 

commit 51c61a2838c33dab7b6659b9a3e008bb1b40bc9b
+Author: Matt Renzelmann 
+Date:   Fri Apr 13 07:59:40 2012 +0000
+
+    ks8851: Fix missing mutex_lock/unlock
+    
+    Move the ks8851_rdreg16 call above the call to request_irq and cache
+    the result for subsequent repeated use.  A spurious interrupt may
+    otherwise cause a crash.  Thanks to Stephen Boyd, Flavio Leitner, and
+    Ben Hutchings for feedback.
+    
+    Signed-off-by: Matt Renzelmann 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c
+index c722aa607d07..e5dc0757f077 100644
+--- a/drivers/net/ethernet/micrel/ks8851.c
++++ b/drivers/net/ethernet/micrel/ks8851.c
+@@ -1418,6 +1418,7 @@ static int __devinit ks8851_probe(struct spi_device *spi)
+ 	struct net_device *ndev;
+ 	struct ks8851_net *ks;
+ 	int ret;
++	unsigned cider;
+ 
+ 	ndev = alloc_etherdev(sizeof(struct ks8851_net));
+ 	if (!ndev)
+@@ -1484,8 +1485,8 @@ static int __devinit ks8851_probe(struct spi_device *spi)
+ 	ks8851_soft_reset(ks, GRR_GSR);
+ 
+ 	/* simple check for a valid chip being connected to the bus */
+-
+-	if ((ks8851_rdreg16(ks, KS_CIDER) & ~CIDER_REV_MASK) != CIDER_ID) {
++	cider = ks8851_rdreg16(ks, KS_CIDER);
++	if ((cider & ~CIDER_REV_MASK) != CIDER_ID) {
+ 		dev_err(&spi->dev, "failed to read device ID\n");
+ 		ret = -ENODEV;
+ 		goto err_id;
+@@ -1516,8 +1517,7 @@ static int __devinit ks8851_probe(struct spi_device *spi)
+ 	}
+ 
+ 	netdev_info(ndev, "revision %d, MAC %pM, IRQ %d, %s EEPROM\n",
+-		    CIDER_REV_GET(ks8851_rdreg16(ks, KS_CIDER)),
+-		    ndev->dev_addr, ndev->irq,
++		    CIDER_REV_GET(cider), ndev->dev_addr, ndev->irq,
+ 		    ks->rc_ccr & CCR_EEPROM ? "has" : "no");
+ 
+ 	return 0;

commit 49d0e64b6a61acea3bcdd6b36be3972111edecc5
+Author: Mike Christie 
+Date:   Tue Mar 6 16:09:01 2012 -0600
+
+    [SCSI] iscsi class: fix gfp use in ping compl and host event
+    
+    If a ping or host event were to occur when memory is low
+    we do not want to use GFP_KERNEL, because the paths
+    sending them cannot block for data to be written. These
+    paths might be needed to recover write paths. Use GFP_NOIO
+    instead.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index fac31730addf..1cf640e575da 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -1486,7 +1486,7 @@ void iscsi_post_host_event(uint32_t host_no, struct iscsi_transport *transport,
+ 	struct iscsi_uevent *ev;
+ 	int len = NLMSG_SPACE(sizeof(*ev) + data_size);
+ 
+-	skb = alloc_skb(len, GFP_KERNEL);
++	skb = alloc_skb(len, GFP_NOIO);
+ 	if (!skb) {
+ 		printk(KERN_ERR "gracefully ignored host event (%d):%d OOM\n",
+ 		       host_no, code);
+@@ -1504,7 +1504,7 @@ void iscsi_post_host_event(uint32_t host_no, struct iscsi_transport *transport,
+ 	if (data_size)
+ 		memcpy((char *)ev + sizeof(*ev), data, data_size);
+ 
+-	iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_KERNEL);
++	iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_NOIO);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_post_host_event);
+ 
+@@ -1517,7 +1517,7 @@ void iscsi_ping_comp_event(uint32_t host_no, struct iscsi_transport *transport,
+ 	struct iscsi_uevent *ev;
+ 	int len = NLMSG_SPACE(sizeof(*ev) + data_size);
+ 
+-	skb = alloc_skb(len, GFP_KERNEL);
++	skb = alloc_skb(len, GFP_NOIO);
+ 	if (!skb) {
+ 		printk(KERN_ERR "gracefully ignored ping comp: OOM\n");
+ 		return;
+@@ -1533,7 +1533,7 @@ void iscsi_ping_comp_event(uint32_t host_no, struct iscsi_transport *transport,
+ 	ev->r.ping_comp.data_size = data_size;
+ 	memcpy((char *)ev + sizeof(*ev), data, data_size);
+ 
+-	iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_KERNEL);
++	iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_NOIO);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_ping_comp_event);
+ 

commit fca9f04d460bf7c6af397dd994f1d81a3037f9dc
+Author: Mike Christie 
+Date:   Mon Feb 27 03:08:54 2012 -0800
+
+    [SCSI] qla4xxx: Export CHAP index as sysfs attribute
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Vikas Chaudhary 
+    Reviewed-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
+index 954ba9188256..910536667cf5 100644
+--- a/drivers/scsi/qla4xxx/ql4_glbl.h
++++ b/drivers/scsi/qla4xxx/ql4_glbl.h
+@@ -81,6 +81,8 @@ int qla4xxx_set_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr,
+ 		      uint32_t offset, uint32_t length, uint32_t options);
+ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
+ 		uint8_t outCount, uint32_t *mbx_cmd, uint32_t *mbx_sts);
++int qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username,
++			   char *password, int bidi, uint16_t *chap_index);
+ 
+ void qla4xxx_queue_iocb(struct scsi_qla_host *ha);
+ void qla4xxx_complete_iocb(struct scsi_qla_host *ha);
+diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
+index eaf21852887c..71331e3b4404 100644
+--- a/drivers/scsi/qla4xxx/ql4_mbx.c
++++ b/drivers/scsi/qla4xxx/ql4_mbx.c
+@@ -1426,8 +1426,8 @@ static int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username,
+  * match is found. If a match is not found then add the entry in FLASH and
+  * return the index at which entry is written in the FLASH.
+  **/
+-static int qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username,
+-			    char *password, int bidi, uint16_t *chap_index)
++int qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username,
++			   char *password, int bidi, uint16_t *chap_index)
+ {
+ 	int i, rval;
+ 	int free_index = -1;
+@@ -1446,6 +1446,11 @@ static int qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username,
+ 		return QLA_ERROR;
+ 	}
+ 
++	if (!username || !password) {
++		ql4_printk(KERN_ERR, ha, "Do not have username and psw\n");
++		return QLA_ERROR;
++	}
++
+ 	mutex_lock(&ha->chap_sem);
+ 	for (i = 0; i < max_chap_entries; i++) {
+ 		chap_table = (struct ql4_chap_table *)ha->chap_list + i;
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index c6cfe324ab2f..cbaf2b33e485 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -83,6 +83,8 @@ static void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha);
+ /*
+  * iSCSI template entry points
+  */
++static int qla4xxx_session_get_param(struct iscsi_cls_session *cls_sess,
++				     enum iscsi_param param, char *buf);
+ static int qla4xxx_conn_get_param(struct iscsi_cls_conn *conn,
+ 				  enum iscsi_param param, char *buf);
+ static int qla4xxx_host_get_param(struct Scsi_Host *shost,
+@@ -186,7 +188,7 @@ static struct iscsi_transport qla4xxx_iscsi_transport = {
+ 	.destroy_conn           = qla4xxx_conn_destroy,
+ 	.set_param              = iscsi_set_param,
+ 	.get_conn_param		= qla4xxx_conn_get_param,
+-	.get_session_param	= iscsi_session_get_param,
++	.get_session_param	= qla4xxx_session_get_param,
+ 	.get_ep_param           = qla4xxx_get_ep_param,
+ 	.ep_connect		= qla4xxx_ep_connect,
+ 	.ep_poll		= qla4xxx_ep_poll,
+@@ -317,6 +319,12 @@ static umode_t ql4_attr_is_visible(int param_type, int param)
+ 		case ISCSI_PARAM_MAX_RECV_DLENGTH:
+ 		case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+ 		case ISCSI_PARAM_IFACE_NAME:
++		case ISCSI_PARAM_CHAP_OUT_IDX:
++		case ISCSI_PARAM_CHAP_IN_IDX:
++		case ISCSI_PARAM_USERNAME:
++		case ISCSI_PARAM_PASSWORD:
++		case ISCSI_PARAM_USERNAME_IN:
++		case ISCSI_PARAM_PASSWORD_IN:
+ 			return S_IRUGO;
+ 		default:
+ 			return 0;
+@@ -1288,6 +1296,41 @@ qla4xxx_iface_set_param(struct Scsi_Host *shost, void *data, uint32_t len)
+ 	return rval;
+ }
+ 
++static int qla4xxx_session_get_param(struct iscsi_cls_session *cls_sess,
++				     enum iscsi_param param, char *buf)
++{
++	struct iscsi_session *sess = cls_sess->dd_data;
++	struct ddb_entry *ddb_entry = sess->dd_data;
++	struct scsi_qla_host *ha = ddb_entry->ha;
++	int rval, len;
++	uint16_t idx;
++
++	switch (param) {
++	case ISCSI_PARAM_CHAP_IN_IDX:
++		rval = qla4xxx_get_chap_index(ha, sess->username_in,
++					      sess->password_in, BIDI_CHAP,
++					      &idx);
++		if (rval)
++			return -EINVAL;
++
++		len = sprintf(buf, "%hu\n", idx);
++		break;
++	case ISCSI_PARAM_CHAP_OUT_IDX:
++		rval = qla4xxx_get_chap_index(ha, sess->username,
++					      sess->password, LOCAL_CHAP,
++					      &idx);
++		if (rval)
++			return -EINVAL;
++
++		len = sprintf(buf, "%hu\n", idx);
++		break;
++	default:
++		return iscsi_session_get_param(cls_sess, param, buf);
++	}
++
++	return len;
++}
++
+ static int qla4xxx_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ 				  enum iscsi_param param, char *buf)
+ {

commit 30534952743f73f1de3c6c056400d7249f5c7f75
+Author: Mike Christie 
+Date:   Mon Feb 27 03:08:53 2012 -0800
+
+    [SCSI] scsi_transport: Export CHAP index as sysfs attribute
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Vikas Chaudhary 
+    Reviewed-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 7bf0dec46271..fac31730addf 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -2475,6 +2475,8 @@ iscsi_session_attr(username, ISCSI_PARAM_USERNAME, 1);
+ iscsi_session_attr(username_in, ISCSI_PARAM_USERNAME_IN, 1);
+ iscsi_session_attr(password, ISCSI_PARAM_PASSWORD, 1);
+ iscsi_session_attr(password_in, ISCSI_PARAM_PASSWORD_IN, 1);
++iscsi_session_attr(chap_out_idx, ISCSI_PARAM_CHAP_OUT_IDX, 1);
++iscsi_session_attr(chap_in_idx, ISCSI_PARAM_CHAP_IN_IDX, 1);
+ iscsi_session_attr(fast_abort, ISCSI_PARAM_FAST_ABORT, 0);
+ iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0);
+ iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 0);
+@@ -2571,6 +2573,8 @@ static struct attribute *iscsi_session_attrs[] = {
+ 	&dev_attr_priv_sess_recovery_tmo.attr,
+ 	&dev_attr_priv_sess_state.attr,
+ 	&dev_attr_priv_sess_creator.attr,
++	&dev_attr_sess_chap_out_idx.attr,
++	&dev_attr_sess_chap_in_idx.attr,
+ 	NULL,
+ };
+ 
+@@ -2602,6 +2606,10 @@ static umode_t iscsi_session_attr_is_visible(struct kobject *kobj,
+ 		param = ISCSI_PARAM_TARGET_NAME;
+ 	else if (attr == &dev_attr_sess_tpgt.attr)
+ 		param = ISCSI_PARAM_TPGT;
++	else if (attr == &dev_attr_sess_chap_in_idx.attr)
++		param = ISCSI_PARAM_CHAP_IN_IDX;
++	else if (attr == &dev_attr_sess_chap_out_idx.attr)
++		param = ISCSI_PARAM_CHAP_OUT_IDX;
+ 	else if (attr == &dev_attr_sess_password.attr)
+ 		param = ISCSI_PARAM_USERNAME;
+ 	else if (attr == &dev_attr_sess_password_in.attr)
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index 228a8af05129..9c23ee8fd2d3 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -450,6 +450,9 @@ enum iscsi_param {
+ 
+ 	ISCSI_PARAM_TGT_RESET_TMO,
+ 	ISCSI_PARAM_TARGET_ALIAS,
++
++	ISCSI_PARAM_CHAP_IN_IDX,
++	ISCSI_PARAM_CHAP_OUT_IDX,
+ 	/* must always be last */
+ 	ISCSI_PARAM_MAX,
+ };

commit e3d338a536330b5ffc9f28d7c6a4cdf6ba51867a
+Author: Mike Christie 
+Date:   Thu Jan 26 21:13:11 2012 -0600
+
+    [SCSI] libiscsi: fix cmd timeout/completion race
+    
+    If the driver/lib has called scsi_done and cleaned up internally but
+    scsi layer has not yet called blk_mark_rq_complete when the command
+    times out we hit a problem if the timeout code calls blk_mark_rq_complete first.
+    When the time out code calls into the driver we were returning
+    BLK_EH_RESET_TIMER and that causes the timeout code to just call
+    us again later.
+    
+    We need to be calling BLK_EH_HANDLED so the timeout code can complete
+    the completion process because it had called blk_mark_rq_complete
+    on the command and now owns its processing.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 8582d7c25732..82c3fd4bc938 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1909,6 +1909,16 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
+ 	ISCSI_DBG_EH(session, "scsi cmd %p timedout\n", sc);
+ 
+ 	spin_lock(&session->lock);
++	task = (struct iscsi_task *)sc->SCp.ptr;
++	if (!task) {
++		/*
++		 * Raced with completion. Blk layer has taken ownership
++		 * so let timeout code complete it now.
++		 */
++		rc = BLK_EH_HANDLED;
++		goto done;
++	}
++
+ 	if (session->state != ISCSI_STATE_LOGGED_IN) {
+ 		/*
+ 		 * We are probably in the middle of iscsi recovery so let
+@@ -1925,16 +1935,6 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
+ 		goto done;
+ 	}
+ 
+-	task = (struct iscsi_task *)sc->SCp.ptr;
+-	if (!task) {
+-		/*
+-		 * Raced with completion. Just reset timer, and let it
+-		 * complete normally
+-		 */
+-		rc = BLK_EH_RESET_TIMER;
+-		goto done;
+-	}
+-
+ 	/*
+ 	 * If we have sent (at least queued to the network layer) a pdu or
+ 	 * recvd one for the task since the last timeout ask for

commit 1304be5fe0efb42b7ec6a50dd8e1a9bce2adae17
+Author: Mike Christie 
+Date:   Thu Jan 26 21:13:10 2012 -0600
+
+    [SCSI] libiscsi_tcp: fix max_r2t manipulation
+    
+    Problem description from Xi Wang:
+    A large max_r2t could lead to integer overflow in subsequent call to
+    iscsi_tcp_r2tpool_alloc(), allocating a smaller buffer than expected
+    and leading to out-of-bounds write.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c
+index d3ff9cd40234..e6e6aa9289b8 100644
+--- a/drivers/scsi/cxgbi/libcxgbi.c
++++ b/drivers/scsi/cxgbi/libcxgbi.c
+@@ -2148,11 +2148,10 @@ int cxgbi_set_conn_param(struct iscsi_cls_conn *cls_conn,
+ 			enum iscsi_param param, char *buf, int buflen)
+ {
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+-	struct iscsi_session *session = conn->session;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+ 	struct cxgbi_sock *csk = cconn->cep->csk;
+-	int value, err = 0;
++	int err;
+ 
+ 	log_debug(1 << CXGBI_DBG_ISCSI,
+ 		"cls_conn 0x%p, param %d, buf(%d) %s.\n",
+@@ -2174,15 +2173,7 @@ int cxgbi_set_conn_param(struct iscsi_cls_conn *cls_conn,
+ 							conn->datadgst_en, 0);
+ 		break;
+ 	case ISCSI_PARAM_MAX_R2T:
+-		sscanf(buf, "%d", &value);
+-		if (value <= 0 || !is_power_of_2(value))
+-			return -EINVAL;
+-		if (session->max_r2t == value)
+-			break;
+-		iscsi_tcp_r2tpool_free(session);
+-		err = iscsi_set_param(cls_conn, param, buf, buflen);
+-		if (!err && iscsi_tcp_r2tpool_alloc(session))
+-			return -ENOMEM;
++		return iscsi_tcp_set_max_r2t(conn, buf);
+ 	case ISCSI_PARAM_MAX_RECV_DLENGTH:
+ 		err = iscsi_set_param(cls_conn, param, buf, buflen);
+ 		if (!err)
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index db47158e0dde..453a740fa68e 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -684,10 +684,8 @@ static int iscsi_sw_tcp_conn_set_param(struct iscsi_cls_conn *cls_conn,
+ 				       int buflen)
+ {
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+-	struct iscsi_session *session = conn->session;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
+-	int value;
+ 
+ 	switch(param) {
+ 	case ISCSI_PARAM_HDRDGST_EN:
+@@ -699,16 +697,7 @@ static int iscsi_sw_tcp_conn_set_param(struct iscsi_cls_conn *cls_conn,
+ 			sock_no_sendpage : tcp_sw_conn->sock->ops->sendpage;
+ 		break;
+ 	case ISCSI_PARAM_MAX_R2T:
+-		sscanf(buf, "%d", &value);
+-		if (value <= 0 || !is_power_of_2(value))
+-			return -EINVAL;
+-		if (session->max_r2t == value)
+-			break;
+-		iscsi_tcp_r2tpool_free(session);
+-		iscsi_set_param(cls_conn, param, buf, buflen);
+-		if (iscsi_tcp_r2tpool_alloc(session))
+-			return -ENOMEM;
+-		break;
++		return iscsi_tcp_set_max_r2t(conn, buf);
+ 	default:
+ 		return iscsi_set_param(cls_conn, param, buf, buflen);
+ 	}
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 00592e3bb375..8582d7c25732 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -3201,7 +3201,7 @@ int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
+ 		sscanf(buf, "%d", &session->initial_r2t_en);
+ 		break;
+ 	case ISCSI_PARAM_MAX_R2T:
+-		sscanf(buf, "%d", &session->max_r2t);
++		sscanf(buf, "%hu", &session->max_r2t);
+ 		break;
+ 	case ISCSI_PARAM_IMM_DATA_EN:
+ 		sscanf(buf, "%d", &session->imm_data_en);
+diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
+index 5715a3d0a3d3..c4996b081999 100644
+--- a/drivers/scsi/libiscsi_tcp.c
++++ b/drivers/scsi/libiscsi_tcp.c
+@@ -1170,6 +1170,24 @@ void iscsi_tcp_r2tpool_free(struct iscsi_session *session)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_tcp_r2tpool_free);
+ 
++int iscsi_tcp_set_max_r2t(struct iscsi_conn *conn, char *buf)
++{
++	struct iscsi_session *session = conn->session;
++	unsigned short r2ts = 0;
++
++	sscanf(buf, "%hu", &r2ts);
++	if (session->max_r2t == r2ts)
++		return 0;
++
++	if (!r2ts || !is_power_of_2(r2ts))
++		return -EINVAL;
++
++	session->max_r2t = r2ts;
++	iscsi_tcp_r2tpool_free(session);
++	return iscsi_tcp_r2tpool_alloc(session);
++}
++EXPORT_SYMBOL_GPL(iscsi_tcp_set_max_r2t);
++
+ void iscsi_tcp_conn_get_stats(struct iscsi_cls_conn *cls_conn,
+ 			      struct iscsi_stats *stats)
+ {
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 2e42e9a0e0b6..6e33386a3898 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -268,7 +268,7 @@ struct iscsi_session {
+ 	int			lu_reset_timeout;
+ 	int			tgt_reset_timeout;
+ 	int			initial_r2t_en;
+-	unsigned		max_r2t;
++	unsigned short		max_r2t;
+ 	int			imm_data_en;
+ 	unsigned		first_burst;
+ 	unsigned		max_burst;
+diff --git a/include/scsi/libiscsi_tcp.h b/include/scsi/libiscsi_tcp.h
+index ac0cc1d925ef..215469a9b801 100644
+--- a/include/scsi/libiscsi_tcp.h
++++ b/include/scsi/libiscsi_tcp.h
+@@ -128,7 +128,7 @@ extern void iscsi_tcp_conn_teardown(struct iscsi_cls_conn *cls_conn);
+ /* misc helpers */
+ extern int iscsi_tcp_r2tpool_alloc(struct iscsi_session *session);
+ extern void iscsi_tcp_r2tpool_free(struct iscsi_session *session);
+-
++extern int iscsi_tcp_set_max_r2t(struct iscsi_conn *conn, char *buf);
+ extern void iscsi_tcp_conn_get_stats(struct iscsi_cls_conn *cls_conn,
+ 				     struct iscsi_stats *stats);
+ #endif /* LIBISCSI_TCP_H */

commit df1c7baba1b7b3053950f3845a6575aca47ba9ce
+Author: Mike Christie 
+Date:   Thu Jan 26 21:13:09 2012 -0600
+
+    [SCSI] iscsi: fix setting of pid from netlink skb
+    
+    NETLINK_CREDS's pid now returns 0, so I guess we are supposed to
+    be using NETLINK_CB. This changed while the patch to export the
+    pid was getting merged upstream, so it was not noticed until both
+    the network and iscsi changes were in the same tree.
+    
+    Signed-off-by: Mike Christie 
+    Cc: stable@kernel.org
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 460d6852183b..787044828a70 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -1941,7 +1941,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
+ 	switch (nlh->nlmsg_type) {
+ 	case ISCSI_UEVENT_CREATE_SESSION:
+ 		err = iscsi_if_create_session(priv, ep, ev,
+-					      NETLINK_CREDS(skb)->pid,
++					      NETLINK_CB(skb).pid,
+ 					      ev->u.c_session.initial_cmdsn,
+ 					      ev->u.c_session.cmds_max,
+ 					      ev->u.c_session.queue_depth);
+@@ -1954,7 +1954,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
+ 		}
+ 
+ 		err = iscsi_if_create_session(priv, ep, ev,
+-					NETLINK_CREDS(skb)->pid,
++					NETLINK_CB(skb).pid,
+ 					ev->u.c_bound_session.initial_cmdsn,
+ 					ev->u.c_bound_session.cmds_max,
+ 					ev->u.c_bound_session.queue_depth);

commit 0c70d84b794c9a99f7395b617ecaef34c00d82ec
+Author: Mike Christie 
+Date:   Mon Dec 5 16:44:01 2011 -0600
+
+    [SCSI] iscsi class: export pid of process that created
+    
+    There could be multiple userspace entities creating/destroying/
+    recoverying sessions and also the kernel's iscsi drivers could
+    be doing this too. If the userspace apps do try to manage the kernel
+    ones it can get the driver/fw out of sync and cause the user to
+    loose the root disk, oopses or ping ponging becasue userspace
+    wants to do one thing but the kernel manager thought we
+    are trying to do another.
+    
+    This patch fixes the problem by just exporting the pid of
+    the entity that created the session. Userspace programs like
+    iscsid, iscsiadm, iscsistart, qlogic's tools, etc, can then
+    figure out which sessions they own and only manage them.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 96029e6d027f..c1b172b76689 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -1030,6 +1030,7 @@ iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
+ 		return NULL;
+ 
+ 	session->transport = transport;
++	session->creator = -1;
+ 	session->recovery_tmo = 120;
+ 	session->state = ISCSI_SESSION_FREE;
+ 	INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout);
+@@ -1634,8 +1635,9 @@ EXPORT_SYMBOL_GPL(iscsi_session_event);
+ 
+ static int
+ iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_endpoint *ep,
+-			struct iscsi_uevent *ev, uint32_t initial_cmdsn,
+-			uint16_t cmds_max, uint16_t queue_depth)
++			struct iscsi_uevent *ev, pid_t pid,
++			uint32_t initial_cmdsn,	uint16_t cmds_max,
++			uint16_t queue_depth)
+ {
+ 	struct iscsi_transport *transport = priv->iscsi_transport;
+ 	struct iscsi_cls_session *session;
+@@ -1646,6 +1648,7 @@ iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_endpoint *ep,
+ 	if (!session)
+ 		return -ENOMEM;
+ 
++	session->creator = pid;
+ 	shost = iscsi_session_to_shost(session);
+ 	ev->r.c_session_ret.host_no = shost->host_no;
+ 	ev->r.c_session_ret.sid = session->sid;
+@@ -1938,6 +1941,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
+ 	switch (nlh->nlmsg_type) {
+ 	case ISCSI_UEVENT_CREATE_SESSION:
+ 		err = iscsi_if_create_session(priv, ep, ev,
++					      NETLINK_CREDS(skb)->pid,
+ 					      ev->u.c_session.initial_cmdsn,
+ 					      ev->u.c_session.cmds_max,
+ 					      ev->u.c_session.queue_depth);
+@@ -1950,6 +1954,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
+ 		}
+ 
+ 		err = iscsi_if_create_session(priv, ep, ev,
++					NETLINK_CREDS(skb)->pid,
+ 					ev->u.c_bound_session.initial_cmdsn,
+ 					ev->u.c_bound_session.cmds_max,
+ 					ev->u.c_bound_session.queue_depth);
+@@ -2298,6 +2303,15 @@ show_priv_session_state(struct device *dev, struct device_attribute *attr,
+ }
+ static ISCSI_CLASS_ATTR(priv_sess, state, S_IRUGO, show_priv_session_state,
+ 			NULL);
++static ssize_t
++show_priv_session_creator(struct device *dev, struct device_attribute *attr,
++			char *buf)
++{
++	struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent);
++	return sprintf(buf, "%d\n", session->creator);
++}
++static ISCSI_CLASS_ATTR(priv_sess, creator, S_IRUGO, show_priv_session_creator,
++			NULL);
+ 
+ #define iscsi_priv_session_attr_show(field, format)			\
+ static ssize_t								\
+@@ -2367,6 +2381,7 @@ static struct attribute *iscsi_session_attrs[] = {
+ 	&dev_attr_sess_targetalias.attr,
+ 	&dev_attr_priv_sess_recovery_tmo.attr,
+ 	&dev_attr_priv_sess_state.attr,
++	&dev_attr_priv_sess_creator.attr,
+ 	NULL,
+ };
+ 
+@@ -2424,6 +2439,8 @@ static mode_t iscsi_session_attr_is_visible(struct kobject *kobj,
+ 		return S_IRUGO | S_IWUSR;
+ 	else if (attr == &dev_attr_priv_sess_state.attr)
+ 		return S_IRUGO;
++	else if (attr == &dev_attr_priv_sess_creator.attr)
++		return S_IRUGO;
+ 	else {
+ 		WARN_ONCE(1, "Invalid session attr");
+ 		return 0;
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 5994bcc1b017..c54cedc196e8 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -211,6 +211,11 @@ struct iscsi_cls_session {
+ 	unsigned int target_id;
+ 	bool ida_used;
+ 
++	/*
++	 * pid of userspace process that created session or -1 if
++	 * created by the kernel.
++	 */
++	pid_t creator;
+ 	int state;
+ 	int sid;				/* session id */
+ 	void *dd_data;				/* LLD private data */

commit ff1d0319ac6a5fd859884b30c0a3cb6733b8fb2d
+Author: Mike Christie 
+Date:   Thu Dec 1 21:38:43 2011 -0600
+
+    [SCSI] qla4xxx: check for failed conn setup
+    
+    iscsi_conn_setup can fail so we must check for NULL being
+    returned.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index 95910c9b4776..4169c8baa112 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -1207,6 +1207,9 @@ qla4xxx_conn_create(struct iscsi_cls_session *cls_sess, uint32_t conn_idx)
+ 	DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
+ 	cls_conn = iscsi_conn_setup(cls_sess, sizeof(struct qla_conn),
+ 				    conn_idx);
++	if (!cls_conn)
++		return NULL;
++
+ 	sess = cls_sess->dd_data;
+ 	ddb_entry = sess->dd_data;
+ 	ddb_entry->conn = cls_conn;

commit 13483730a13bef372894aefcf73760f5c6c297be
+Author: Mike Christie 
+Date:   Thu Dec 1 21:38:41 2011 -0600
+
+    [SCSI] qla4xxx: fix flash/ddb support
+    
+    With open-iscsi support, target entries persisted in the FLASH were not
+    login. Added support in the qla4xxx driver to do the login on probe
+    time to the target entries saved in the FLASH by user.
+    With this changes upgrade to the new kernel with open-iscsi support in
+    qla4xxx will ensure users original target entries login on driver load
+    
+    Signed-off-by: Manish Rangankar 
+    Signed-off-by: Ravi Anand 
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
+index ace637bf254e..fd5edc6e166d 100644
+--- a/drivers/scsi/qla4xxx/ql4_def.h
++++ b/drivers/scsi/qla4xxx/ql4_def.h
+@@ -147,7 +147,7 @@
+ #define ISCSI_ALIAS_SIZE		32	/* ISCSI Alias name size */
+ #define ISCSI_NAME_SIZE			0xE0	/* ISCSI Name size */
+ 
+-#define QL4_SESS_RECOVERY_TMO		30	/* iSCSI session */
++#define QL4_SESS_RECOVERY_TMO		120	/* iSCSI session */
+ 						/* recovery timeout */
+ 
+ #define LSDW(x) ((u32)((u64)(x)))
+@@ -173,6 +173,8 @@
+ #define ISNS_DEREG_TOV			5
+ #define HBA_ONLINE_TOV			30
+ #define DISABLE_ACB_TOV			30
++#define IP_CONFIG_TOV			30
++#define LOGIN_TOV			12
+ 
+ #define MAX_RESET_HA_RETRIES		2
+ 
+@@ -240,6 +242,45 @@ struct ddb_entry {
+ 
+ 	uint16_t fw_ddb_index;	/* DDB firmware index */
+ 	uint32_t fw_ddb_device_state; /* F/W Device State  -- see ql4_fw.h */
++	uint16_t ddb_type;
++#define FLASH_DDB 0x01
++
++	struct dev_db_entry fw_ddb_entry;
++	int (*unblock_sess)(struct iscsi_cls_session *cls_session);
++	int (*ddb_change)(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
++			  struct ddb_entry *ddb_entry, uint32_t state);
++
++	/* Driver Re-login  */
++	unsigned long flags;		  /* DDB Flags */
++	uint16_t default_relogin_timeout; /*  Max time to wait for
++					   *  relogin to complete */
++	atomic_t retry_relogin_timer;	  /* Min Time between relogins
++					   * (4000 only) */
++	atomic_t relogin_timer;		  /* Max Time to wait for
++					   * relogin to complete */
++	atomic_t relogin_retry_count;	  /* Num of times relogin has been
++					   * retried */
++	uint32_t default_time2wait;	  /* Default Min time between
++					   * relogins (+aens) */
++
++};
++
++struct qla_ddb_index {
++	struct list_head list;
++	uint16_t fw_ddb_idx;
++	struct dev_db_entry fw_ddb;
++};
++
++#define DDB_IPADDR_LEN 64
++
++struct ql4_tuple_ddb {
++	int port;
++	int tpgt;
++	char ip_addr[DDB_IPADDR_LEN];
++	char iscsi_name[ISCSI_NAME_SIZE];
++	uint16_t options;
++#define DDB_OPT_IPV6 0x0e0e
++#define DDB_OPT_IPV4 0x0f0f
+ };
+ 
+ /*
+@@ -411,7 +452,7 @@ struct scsi_qla_host {
+ #define AF_FW_RECOVERY			19 /* 0x00080000 */
+ #define AF_EEH_BUSY			20 /* 0x00100000 */
+ #define AF_PCI_CHANNEL_IO_PERM_FAILURE	21 /* 0x00200000 */
+-
++#define AF_BUILD_DDB_LIST		22 /* 0x00400000 */
+ 	unsigned long dpc_flags;
+ 
+ #define DPC_RESET_HA			1 /* 0x00000002 */
+@@ -604,6 +645,7 @@ struct scsi_qla_host {
+ 	uint16_t bootload_minor;
+ 	uint16_t bootload_patch;
+ 	uint16_t bootload_build;
++	uint16_t def_timeout; /* Default login timeout */
+ 
+ 	uint32_t flash_state;
+ #define	QLFLASH_WAITING		0
+@@ -623,6 +665,11 @@ struct scsi_qla_host {
+ 	uint16_t iscsi_pci_func_cnt;
+ 	uint8_t model_name[16];
+ 	struct completion disable_acb_comp;
++	struct dma_pool *fw_ddb_dma_pool;
++#define DDB_DMA_BLOCK_SIZE 512
++	uint16_t pri_ddb_idx;
++	uint16_t sec_ddb_idx;
++	int is_reset;
+ };
+ 
+ struct ql4_task_data {
+@@ -835,6 +882,10 @@ static inline int ql4xxx_reset_active(struct scsi_qla_host *ha)
+ /*---------------------------------------------------------------------------*/
+ 
+ /* Defines for qla4xxx_initialize_adapter() and qla4xxx_recover_adapter() */
++
++#define INIT_ADAPTER    0
++#define RESET_ADAPTER   1
++
+ #define PRESERVE_DDB_LIST	0
+ #define REBUILD_DDB_LIST	1
+ 
+diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
+index cbd5a20dbbd1..4ac07f882521 100644
+--- a/drivers/scsi/qla4xxx/ql4_fw.h
++++ b/drivers/scsi/qla4xxx/ql4_fw.h
+@@ -12,6 +12,7 @@
+ #define MAX_PRST_DEV_DB_ENTRIES		64
+ #define MIN_DISC_DEV_DB_ENTRY		MAX_PRST_DEV_DB_ENTRIES
+ #define MAX_DEV_DB_ENTRIES		512
++#define MAX_DEV_DB_ENTRIES_40XX		256
+ 
+ /*************************************************************************
+  *
+@@ -604,6 +605,13 @@ struct addr_ctrl_blk {
+ 	uint8_t res14[140];	/* 274-2FF */
+ };
+ 
++#define IP_ADDR_COUNT	4 /* Total 4 IP address supported in one interface
++			   * One IPv4, one IPv6 link local and 2 IPv6
++			   */
++
++#define IP_STATE_MASK	0x0F000000
++#define IP_STATE_SHIFT	24
++
+ struct init_fw_ctrl_blk {
+ 	struct addr_ctrl_blk pri;
+ /*	struct addr_ctrl_blk sec;*/
+diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
+index 160db9d5ea21..d0dd4b330206 100644
+--- a/drivers/scsi/qla4xxx/ql4_glbl.h
++++ b/drivers/scsi/qla4xxx/ql4_glbl.h
+@@ -13,7 +13,7 @@ struct iscsi_cls_conn;
+ int qla4xxx_hw_reset(struct scsi_qla_host *ha);
+ int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a);
+ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb *srb);
+-int qla4xxx_initialize_adapter(struct scsi_qla_host *ha);
++int qla4xxx_initialize_adapter(struct scsi_qla_host *ha, int is_reset);
+ int qla4xxx_soft_reset(struct scsi_qla_host *ha);
+ irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id);
+ 
+@@ -153,10 +153,13 @@ int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
+ 			  uint32_t *mbx_sts);
+ int qla4xxx_clear_ddb_entry(struct scsi_qla_host *ha, uint32_t fw_ddb_index);
+ int qla4xxx_send_passthru0(struct iscsi_task *task);
++void qla4xxx_free_ddb_index(struct scsi_qla_host *ha);
+ int qla4xxx_get_mgmt_data(struct scsi_qla_host *ha, uint16_t fw_ddb_index,
+ 			  uint16_t stats_size, dma_addr_t stats_dma);
+ void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha,
+ 				       struct ddb_entry *ddb_entry);
++void qla4xxx_update_session_conn_fwddb_param(struct scsi_qla_host *ha,
++					     struct ddb_entry *ddb_entry);
+ int qla4xxx_bootdb_by_index(struct scsi_qla_host *ha,
+ 			    struct dev_db_entry *fw_ddb_entry,
+ 			    dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index);
+@@ -169,11 +172,22 @@ int qla4xxx_set_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma,
+ int qla4xxx_restore_factory_defaults(struct scsi_qla_host *ha,
+ 				     uint32_t region, uint32_t field0,
+ 				     uint32_t field1);
++int qla4xxx_get_ddb_index(struct scsi_qla_host *ha, uint16_t *ddb_index);
++void qla4xxx_login_flash_ddb(struct iscsi_cls_session *cls_session);
++int qla4xxx_unblock_ddb(struct iscsi_cls_session *cls_session);
++int qla4xxx_unblock_flash_ddb(struct iscsi_cls_session *cls_session);
++int qla4xxx_flash_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
++			     struct ddb_entry *ddb_entry, uint32_t state);
++int qla4xxx_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
++		       struct ddb_entry *ddb_entry, uint32_t state);
++void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset);
+ 
+ /* BSG Functions */
+ int qla4xxx_bsg_request(struct bsg_job *bsg_job);
+ int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job);
+ 
++void qla4xxx_arm_relogin_timer(struct ddb_entry *ddb_entry);
++
+ extern int ql4xextended_error_logging;
+ extern int ql4xdontresethba;
+ extern int ql4xenablemsix;
+diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
+index 3075fbaef553..0497873a1dd2 100644
+--- a/drivers/scsi/qla4xxx/ql4_init.c
++++ b/drivers/scsi/qla4xxx/ql4_init.c
+@@ -773,14 +773,14 @@ int qla4xxx_start_firmware(struct scsi_qla_host *ha)
+  * be freed so that when login happens from user space there are free DDB
+  * indices available.
+  **/
+-static void qla4xxx_free_ddb_index(struct scsi_qla_host *ha)
++void qla4xxx_free_ddb_index(struct scsi_qla_host *ha)
+ {
+ 	int max_ddbs;
+ 	int ret;
+ 	uint32_t idx = 0, next_idx = 0;
+ 	uint32_t state = 0, conn_err = 0;
+ 
+-	max_ddbs =  is_qla40XX(ha) ? MAX_PRST_DEV_DB_ENTRIES :
++	max_ddbs =  is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
+ 				     MAX_DEV_DB_ENTRIES;
+ 
+ 	for (idx = 0; idx < max_ddbs; idx = next_idx) {
+@@ -804,7 +804,6 @@ static void qla4xxx_free_ddb_index(struct scsi_qla_host *ha)
+ 	}
+ }
+ 
+-
+ /**
+  * qla4xxx_initialize_adapter - initiailizes hba
+  * @ha: Pointer to host adapter structure.
+@@ -812,7 +811,7 @@ static void qla4xxx_free_ddb_index(struct scsi_qla_host *ha)
+  * This routine parforms all of the steps necessary to initialize the adapter.
+  *
+  **/
+-int qla4xxx_initialize_adapter(struct scsi_qla_host *ha)
++int qla4xxx_initialize_adapter(struct scsi_qla_host *ha, int is_reset)
+ {
+ 	int status = QLA_ERROR;
+ 
+@@ -840,7 +839,8 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha)
+ 	if (status == QLA_ERROR)
+ 		goto exit_init_hba;
+ 
+-	qla4xxx_free_ddb_index(ha);
++	if (is_reset == RESET_ADAPTER)
++		qla4xxx_build_ddb_list(ha, is_reset);
+ 
+ 	set_bit(AF_ONLINE, &ha->flags);
+ exit_init_hba:
+@@ -855,38 +855,12 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha)
+ 	return status;
+ }
+ 
+-/**
+- * qla4xxx_process_ddb_changed - process ddb state change
+- * @ha - Pointer to host adapter structure.
+- * @fw_ddb_index - Firmware's device database index
+- * @state - Device state
+- *
+- * This routine processes a Decive Database Changed AEN Event.
+- **/
+-int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
+-		uint32_t state, uint32_t conn_err)
++int qla4xxx_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
++		       struct ddb_entry *ddb_entry, uint32_t state)
+ {
+-	struct ddb_entry * ddb_entry;
+ 	uint32_t old_fw_ddb_device_state;
+ 	int status = QLA_ERROR;
+ 
+-	/* check for out of range index */
+-	if (fw_ddb_index >= MAX_DDB_ENTRIES)
+-		goto exit_ddb_event;
+-
+-	/* Get the corresponging ddb entry */
+-	ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, fw_ddb_index);
+-	/* Device does not currently exist in our database. */
+-	if (ddb_entry == NULL) {
+-		ql4_printk(KERN_ERR, ha, "%s: No ddb_entry at FW index [%d]\n",
+-			   __func__, fw_ddb_index);
+-
+-		if (state == DDB_DS_NO_CONNECTION_ACTIVE)
+-			clear_bit(fw_ddb_index, ha->ddb_idx_map);
+-
+-		goto exit_ddb_event;
+-	}
+-
+ 	old_fw_ddb_device_state = ddb_entry->fw_ddb_device_state;
+ 	DEBUG2(ql4_printk(KERN_INFO, ha,
+ 			  "%s: DDB - old state = 0x%x, new state = 0x%x for "
+@@ -900,9 +874,7 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
+ 		switch (state) {
+ 		case DDB_DS_SESSION_ACTIVE:
+ 		case DDB_DS_DISCOVERY:
+-			iscsi_conn_start(ddb_entry->conn);
+-			iscsi_conn_login_event(ddb_entry->conn,
+-					       ISCSI_CONN_STATE_LOGGED_IN);
++			ddb_entry->unblock_sess(ddb_entry->sess);
+ 			qla4xxx_update_session_conn_param(ha, ddb_entry);
+ 			status = QLA_SUCCESS;
+ 			break;
+@@ -936,9 +908,7 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
+ 		switch (state) {
+ 		case DDB_DS_SESSION_ACTIVE:
+ 		case DDB_DS_DISCOVERY:
+-			iscsi_conn_start(ddb_entry->conn);
+-			iscsi_conn_login_event(ddb_entry->conn,
+-					       ISCSI_CONN_STATE_LOGGED_IN);
++			ddb_entry->unblock_sess(ddb_entry->sess);
+ 			qla4xxx_update_session_conn_param(ha, ddb_entry);
+ 			status = QLA_SUCCESS;
+ 			break;
+@@ -954,7 +924,198 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
+ 				__func__));
+ 		break;
+ 	}
++	return status;
++}
++
++void qla4xxx_arm_relogin_timer(struct ddb_entry *ddb_entry)
++{
++	/*
++	 * This triggers a relogin.  After the relogin_timer
++	 * expires, the relogin gets scheduled.  We must wait a
++	 * minimum amount of time since receiving an 0x8014 AEN
++	 * with failed device_state or a logout response before
++	 * we can issue another relogin.
++	 *
++	 * Firmware pads this timeout: (time2wait +1).
++	 * Driver retry to login should be longer than F/W.
++	 * Otherwise F/W will fail
++	 * set_ddb() mbx cmd with 0x4005 since it still
++	 * counting down its time2wait.
++	 */
++	atomic_set(&ddb_entry->relogin_timer, 0);
++	atomic_set(&ddb_entry->retry_relogin_timer,
++		   ddb_entry->default_time2wait + 4);
++
++}
++
++int qla4xxx_flash_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
++			     struct ddb_entry *ddb_entry, uint32_t state)
++{
++	uint32_t old_fw_ddb_device_state;
++	int status = QLA_ERROR;
++
++	old_fw_ddb_device_state = ddb_entry->fw_ddb_device_state;
++	DEBUG2(ql4_printk(KERN_INFO, ha,
++			  "%s: DDB - old state = 0x%x, new state = 0x%x for "
++			  "index [%d]\n", __func__,
++			  ddb_entry->fw_ddb_device_state, state, fw_ddb_index));
++
++	ddb_entry->fw_ddb_device_state = state;
++
++	switch (old_fw_ddb_device_state) {
++	case DDB_DS_LOGIN_IN_PROCESS:
++	case DDB_DS_NO_CONNECTION_ACTIVE:
++		switch (state) {
++		case DDB_DS_SESSION_ACTIVE:
++			ddb_entry->unblock_sess(ddb_entry->sess);
++			qla4xxx_update_session_conn_fwddb_param(ha, ddb_entry);
++			status = QLA_SUCCESS;
++			break;
++		case DDB_DS_SESSION_FAILED:
++			iscsi_block_session(ddb_entry->sess);
++			if (!test_bit(DF_RELOGIN, &ddb_entry->flags))
++				qla4xxx_arm_relogin_timer(ddb_entry);
++			status = QLA_SUCCESS;
++			break;
++		}
++		break;
++	case DDB_DS_SESSION_ACTIVE:
++		switch (state) {
++		case DDB_DS_SESSION_FAILED:
++			iscsi_block_session(ddb_entry->sess);
++			if (!test_bit(DF_RELOGIN, &ddb_entry->flags))
++				qla4xxx_arm_relogin_timer(ddb_entry);
++			status = QLA_SUCCESS;
++			break;
++		}
++		break;
++	case DDB_DS_SESSION_FAILED:
++		switch (state) {
++		case DDB_DS_SESSION_ACTIVE:
++			ddb_entry->unblock_sess(ddb_entry->sess);
++			qla4xxx_update_session_conn_fwddb_param(ha, ddb_entry);
++			status = QLA_SUCCESS;
++			break;
++		case DDB_DS_SESSION_FAILED:
++			if (!test_bit(DF_RELOGIN, &ddb_entry->flags))
++				qla4xxx_arm_relogin_timer(ddb_entry);
++			status = QLA_SUCCESS;
++			break;
++		}
++		break;
++	default:
++		DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Unknown Event\n",
++				  __func__));
++		break;
++	}
++	return status;
++}
++
++/**
++ * qla4xxx_process_ddb_changed - process ddb state change
++ * @ha - Pointer to host adapter structure.
++ * @fw_ddb_index - Firmware's device database index
++ * @state - Device state
++ *
++ * This routine processes a Decive Database Changed AEN Event.
++ **/
++int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha,
++				uint32_t fw_ddb_index,
++				uint32_t state, uint32_t conn_err)
++{
++	struct ddb_entry *ddb_entry;
++	int status = QLA_ERROR;
++
++	/* check for out of range index */
++	if (fw_ddb_index >= MAX_DDB_ENTRIES)
++		goto exit_ddb_event;
++
++	/* Get the corresponging ddb entry */
++	ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, fw_ddb_index);
++	/* Device does not currently exist in our database. */
++	if (ddb_entry == NULL) {
++		ql4_printk(KERN_ERR, ha, "%s: No ddb_entry at FW index [%d]\n",
++			   __func__, fw_ddb_index);
++
++		if (state == DDB_DS_NO_CONNECTION_ACTIVE)
++			clear_bit(fw_ddb_index, ha->ddb_idx_map);
++
++		goto exit_ddb_event;
++	}
++
++	ddb_entry->ddb_change(ha, fw_ddb_index, ddb_entry, state);
+ 
+ exit_ddb_event:
+ 	return status;
+ }
++
++/**
++ * qla4xxx_login_flash_ddb - Login to target (DDB)
++ * @cls_session: Pointer to the session to login
++ *
++ * This routine logins to the target.
++ * Issues setddb and conn open mbx
++ **/
++void qla4xxx_login_flash_ddb(struct iscsi_cls_session *cls_session)
++{
++	struct iscsi_session *sess;
++	struct ddb_entry *ddb_entry;
++	struct scsi_qla_host *ha;
++	struct dev_db_entry *fw_ddb_entry = NULL;
++	dma_addr_t fw_ddb_dma;
++	uint32_t mbx_sts = 0;
++	int ret;
++
++	sess = cls_session->dd_data;
++	ddb_entry = sess->dd_data;
++	ha =  ddb_entry->ha;
++
++	if (!test_bit(AF_LINK_UP, &ha->flags))
++		return;
++
++	if (ddb_entry->ddb_type != FLASH_DDB) {
++		DEBUG2(ql4_printk(KERN_INFO, ha,
++				  "Skipping login to non FLASH DB"));
++		goto exit_login;
++	}
++
++	fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL,
++				      &fw_ddb_dma);
++	if (fw_ddb_entry == NULL) {
++		DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n"));
++		goto exit_login;
++	}
++
++	if (ddb_entry->fw_ddb_index == INVALID_ENTRY) {
++		ret = qla4xxx_get_ddb_index(ha, &ddb_entry->fw_ddb_index);
++		if (ret == QLA_ERROR)
++			goto exit_login;
++
++		ha->fw_ddb_index_map[ddb_entry->fw_ddb_index] = ddb_entry;
++		ha->tot_ddbs++;
++	}
++
++	memcpy(fw_ddb_entry, &ddb_entry->fw_ddb_entry,
++	       sizeof(struct dev_db_entry));
++	ddb_entry->sess->target_id = ddb_entry->fw_ddb_index;
++
++	ret = qla4xxx_set_ddb_entry(ha, ddb_entry->fw_ddb_index,
++				    fw_ddb_dma, &mbx_sts);
++	if (ret == QLA_ERROR) {
++		DEBUG2(ql4_printk(KERN_ERR, ha, "Set DDB failed\n"));
++		goto exit_login;
++	}
++
++	ddb_entry->fw_ddb_device_state = DDB_DS_LOGIN_IN_PROCESS;
++	ret = qla4xxx_conn_open(ha, ddb_entry->fw_ddb_index);
++	if (ret == QLA_ERROR) {
++		ql4_printk(KERN_ERR, ha, "%s: Login failed: %s\n", __func__,
++			   sess->targetname);
++		goto exit_login;
++	}
++
++exit_login:
++	if (fw_ddb_entry)
++		dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma);
++}
++
+diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
+index 4c2b84870392..c2593782fbbe 100644
+--- a/drivers/scsi/qla4xxx/ql4_mbx.c
++++ b/drivers/scsi/qla4xxx/ql4_mbx.c
+@@ -41,6 +41,16 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
+ 		return status;
+ 	}
+ 
++	if (is_qla40XX(ha)) {
++		if (test_bit(AF_HA_REMOVAL, &ha->flags)) {
++			DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: "
++					  "prematurely completing mbx cmd as "
++					  "adapter removal detected\n",
++					  ha->host_no, __func__));
++			return status;
++		}
++	}
++
+ 	if (is_qla8022(ha)) {
+ 		if (test_bit(AF_FW_RECOVERY, &ha->flags)) {
+ 			DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: "
+@@ -413,6 +423,7 @@ qla4xxx_update_local_ifcb(struct scsi_qla_host *ha,
+ 	memcpy(ha->name_string, init_fw_cb->iscsi_name,
+ 		min(sizeof(ha->name_string),
+ 		sizeof(init_fw_cb->iscsi_name)));
++	ha->def_timeout = le16_to_cpu(init_fw_cb->def_timeout);
+ 	/*memcpy(ha->alias, init_fw_cb->Alias,
+ 	       min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/
+ 
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index 30f31b127f33..95910c9b4776 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -8,6 +8,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ #include 
+@@ -31,6 +32,13 @@ static struct kmem_cache *srb_cachep;
+ /*
+  * Module parameter information and variables
+  */
++int ql4xdisablesysfsboot = 1;
++module_param(ql4xdisablesysfsboot, int, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(ql4xdisablesysfsboot,
++		"Set to disable exporting boot targets to sysfs\n"
++		" 0 - Export boot targets\n"
++		" 1 - Do not export boot targets (Default)");
++
+ int ql4xdontresethba = 0;
+ module_param(ql4xdontresethba, int, S_IRUGO | S_IWUSR);
+ MODULE_PARM_DESC(ql4xdontresethba,
+@@ -63,7 +71,7 @@ static int ql4xsess_recovery_tmo = QL4_SESS_RECOVERY_TMO;
+ module_param(ql4xsess_recovery_tmo, int, S_IRUGO);
+ MODULE_PARM_DESC(ql4xsess_recovery_tmo,
+ 		"Target Session Recovery Timeout.\n"
+-		" Default: 30 sec.");
++		" Default: 120 sec.");
+ 
+ static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha);
+ /*
+@@ -415,7 +423,7 @@ static int qla4xxx_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
+ 	qla_ep = ep->dd_data;
+ 	ha = to_qla_host(qla_ep->host);
+ 
+-	if (adapter_up(ha))
++	if (adapter_up(ha) && !test_bit(AF_BUILD_DDB_LIST, &ha->flags))
+ 		ret = 1;
+ 
+ 	return ret;
+@@ -975,6 +983,150 @@ static int qla4xxx_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ 
+ }
+ 
++int qla4xxx_get_ddb_index(struct scsi_qla_host *ha, uint16_t *ddb_index)
++{
++	uint32_t mbx_sts = 0;
++	uint16_t tmp_ddb_index;
++	int ret;
++
++get_ddb_index:
++	tmp_ddb_index = find_first_zero_bit(ha->ddb_idx_map, MAX_DDB_ENTRIES);
++
++	if (tmp_ddb_index >= MAX_DDB_ENTRIES) {
++		DEBUG2(ql4_printk(KERN_INFO, ha,
++				  "Free DDB index not available\n"));
++		ret = QLA_ERROR;
++		goto exit_get_ddb_index;
++	}
++
++	if (test_and_set_bit(tmp_ddb_index, ha->ddb_idx_map))
++		goto get_ddb_index;
++
++	DEBUG2(ql4_printk(KERN_INFO, ha,
++			  "Found a free DDB index at %d\n", tmp_ddb_index));
++	ret = qla4xxx_req_ddb_entry(ha, tmp_ddb_index, &mbx_sts);
++	if (ret == QLA_ERROR) {
++		if (mbx_sts == MBOX_STS_COMMAND_ERROR) {
++			ql4_printk(KERN_INFO, ha,
++				   "DDB index = %d not available trying next\n",
++				   tmp_ddb_index);
++			goto get_ddb_index;
++		}
++		DEBUG2(ql4_printk(KERN_INFO, ha,
++				  "Free FW DDB not available\n"));
++	}
++
++	*ddb_index = tmp_ddb_index;
++
++exit_get_ddb_index:
++	return ret;
++}
++
++static int qla4xxx_match_ipaddress(struct scsi_qla_host *ha,
++				   struct ddb_entry *ddb_entry,
++				   char *existing_ipaddr,
++				   char *user_ipaddr)
++{
++	uint8_t dst_ipaddr[IPv6_ADDR_LEN];
++	char formatted_ipaddr[DDB_IPADDR_LEN];
++	int status = QLA_SUCCESS, ret = 0;
++
++	if (ddb_entry->fw_ddb_entry.options & DDB_OPT_IPV6_DEVICE) {
++		ret = in6_pton(user_ipaddr, strlen(user_ipaddr), dst_ipaddr,
++			       '\0', NULL);
++		if (ret == 0) {
++			status = QLA_ERROR;
++			goto out_match;
++		}
++		ret = sprintf(formatted_ipaddr, "%pI6", dst_ipaddr);
++	} else {
++		ret = in4_pton(user_ipaddr, strlen(user_ipaddr), dst_ipaddr,
++			       '\0', NULL);
++		if (ret == 0) {
++			status = QLA_ERROR;
++			goto out_match;
++		}
++		ret = sprintf(formatted_ipaddr, "%pI4", dst_ipaddr);
++	}
++
++	if (strcmp(existing_ipaddr, formatted_ipaddr))
++		status = QLA_ERROR;
++
++out_match:
++	return status;
++}
++
++static int qla4xxx_match_fwdb_session(struct scsi_qla_host *ha,
++				      struct iscsi_cls_conn *cls_conn)
++{
++	int idx = 0, max_ddbs, rval;
++	struct iscsi_cls_session *cls_sess = iscsi_conn_to_session(cls_conn);
++	struct iscsi_session *sess, *existing_sess;
++	struct iscsi_conn *conn, *existing_conn;
++	struct ddb_entry *ddb_entry;
++
++	sess = cls_sess->dd_data;
++	conn = cls_conn->dd_data;
++
++	if (sess->targetname == NULL ||
++	    conn->persistent_address == NULL ||
++	    conn->persistent_port == 0)
++		return QLA_ERROR;
++
++	max_ddbs =  is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
++				     MAX_DEV_DB_ENTRIES;
++
++	for (idx = 0; idx < max_ddbs; idx++) {
++		ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx);
++		if (ddb_entry == NULL)
++			continue;
++
++		if (ddb_entry->ddb_type != FLASH_DDB)
++			continue;
++
++		existing_sess = ddb_entry->sess->dd_data;
++		existing_conn = ddb_entry->conn->dd_data;
++
++		if (existing_sess->targetname == NULL ||
++		    existing_conn->persistent_address == NULL ||
++		    existing_conn->persistent_port == 0)
++			continue;
++
++		DEBUG2(ql4_printk(KERN_INFO, ha,
++				  "IQN = %s User IQN = %s\n",
++				  existing_sess->targetname,
++				  sess->targetname));
++
++		DEBUG2(ql4_printk(KERN_INFO, ha,
++				  "IP = %s User IP = %s\n",
++				  existing_conn->persistent_address,
++				  conn->persistent_address));
++
++		DEBUG2(ql4_printk(KERN_INFO, ha,
++				  "Port = %d User Port = %d\n",
++				  existing_conn->persistent_port,
++				  conn->persistent_port));
++
++		if (strcmp(existing_sess->targetname, sess->targetname))
++			continue;
++		rval = qla4xxx_match_ipaddress(ha, ddb_entry,
++					existing_conn->persistent_address,
++					conn->persistent_address);
++		if (rval == QLA_ERROR)
++			continue;
++		if (existing_conn->persistent_port != conn->persistent_port)
++			continue;
++		break;
++	}
++
++	if (idx == max_ddbs)
++		return QLA_ERROR;
++
++	DEBUG2(ql4_printk(KERN_INFO, ha,
++			  "Match found in fwdb sessions\n"));
++	return QLA_SUCCESS;
++}
++
+ static struct iscsi_cls_session *
+ qla4xxx_session_create(struct iscsi_endpoint *ep,
+ 			uint16_t cmds_max, uint16_t qdepth,
+@@ -984,8 +1136,7 @@ qla4xxx_session_create(struct iscsi_endpoint *ep,
+ 	struct scsi_qla_host *ha;
+ 	struct qla_endpoint *qla_ep;
+ 	struct ddb_entry *ddb_entry;
+-	uint32_t ddb_index;
+-	uint32_t mbx_sts = 0;
++	uint16_t ddb_index;
+ 	struct iscsi_session *sess;
+ 	struct sockaddr *dst_addr;
+ 	int ret;
+@@ -1000,32 +1151,9 @@ qla4xxx_session_create(struct iscsi_endpoint *ep,
+ 	dst_addr = (struct sockaddr *)&qla_ep->dst_addr;
+ 	ha = to_qla_host(qla_ep->host);
+ 
+-get_ddb_index:
+-	ddb_index = find_first_zero_bit(ha->ddb_idx_map, MAX_DDB_ENTRIES);
+-
+-	if (ddb_index >= MAX_DDB_ENTRIES) {
+-		DEBUG2(ql4_printk(KERN_INFO, ha,
+-				  "Free DDB index not available\n"));
++	ret = qla4xxx_get_ddb_index(ha, &ddb_index);
++	if (ret == QLA_ERROR)
+ 		return NULL;
+-	}
+-
+-	if (test_and_set_bit(ddb_index, ha->ddb_idx_map))
+-		goto get_ddb_index;
+-
+-	DEBUG2(ql4_printk(KERN_INFO, ha,
+-			  "Found a free DDB index at %d\n", ddb_index));
+-	ret = qla4xxx_req_ddb_entry(ha, ddb_index, &mbx_sts);
+-	if (ret == QLA_ERROR) {
+-		if (mbx_sts == MBOX_STS_COMMAND_ERROR) {
+-			ql4_printk(KERN_INFO, ha,
+-				   "DDB index = %d not available trying next\n",
+-				   ddb_index);
+-			goto get_ddb_index;
+-		}
+-		DEBUG2(ql4_printk(KERN_INFO, ha,
+-				  "Free FW DDB not available\n"));
+-		return NULL;
+-	}
+ 
+ 	cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport, qla_ep->host,
+ 				       cmds_max, sizeof(struct ddb_entry),
+@@ -1040,6 +1168,8 @@ qla4xxx_session_create(struct iscsi_endpoint *ep,
+ 	ddb_entry->fw_ddb_device_state = DDB_DS_NO_CONNECTION_ACTIVE;
+ 	ddb_entry->ha = ha;
+ 	ddb_entry->sess = cls_sess;
++	ddb_entry->unblock_sess = qla4xxx_unblock_ddb;
++	ddb_entry->ddb_change = qla4xxx_ddb_change;
+ 	cls_sess->recovery_tmo = ql4xsess_recovery_tmo;
+ 	ha->fw_ddb_index_map[ddb_entry->fw_ddb_index] = ddb_entry;
+ 	ha->tot_ddbs++;
+@@ -1109,7 +1239,7 @@ static int qla4xxx_conn_start(struct iscsi_cls_conn *cls_conn)
+ 	struct iscsi_session *sess;
+ 	struct ddb_entry *ddb_entry;
+ 	struct scsi_qla_host *ha;
+-	struct dev_db_entry *fw_ddb_entry;
++	struct dev_db_entry *fw_ddb_entry = NULL;
+ 	dma_addr_t fw_ddb_entry_dma;
+ 	uint32_t mbx_sts = 0;
+ 	int ret = 0;
+@@ -1120,12 +1250,25 @@ static int qla4xxx_conn_start(struct iscsi_cls_conn *cls_conn)
+ 	ddb_entry = sess->dd_data;
+ 	ha = ddb_entry->ha;
+ 
++	/* Check if we have  matching FW DDB, if yes then do not
++	 * login to this target. This could cause target to logout previous
++	 * connection
++	 */
++	ret = qla4xxx_match_fwdb_session(ha, cls_conn);
++	if (ret == QLA_SUCCESS) {
++		ql4_printk(KERN_INFO, ha,
++			   "Session already exist in FW.\n");
++		ret = -EEXIST;
++		goto exit_conn_start;
++	}
++
+ 	fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+ 					  &fw_ddb_entry_dma, GFP_KERNEL);
+ 	if (!fw_ddb_entry) {
+ 		ql4_printk(KERN_ERR, ha,
+ 			   "%s: Unable to allocate dma buffer\n", __func__);
+-		return -ENOMEM;
++		ret = -ENOMEM;
++		goto exit_conn_start;
+ 	}
+ 
+ 	ret = qla4xxx_set_param_ddbentry(ha, ddb_entry, cls_conn, &mbx_sts);
+@@ -1138,9 +1281,7 @@ static int qla4xxx_conn_start(struct iscsi_cls_conn *cls_conn)
+ 		if (mbx_sts)
+ 			if (ddb_entry->fw_ddb_device_state ==
+ 						DDB_DS_SESSION_ACTIVE) {
+-				iscsi_conn_start(ddb_entry->conn);
+-				iscsi_conn_login_event(ddb_entry->conn,
+-						ISCSI_CONN_STATE_LOGGED_IN);
++				ddb_entry->unblock_sess(ddb_entry->sess);
+ 				goto exit_set_param;
+ 			}
+ 
+@@ -1167,8 +1308,9 @@ static int qla4xxx_conn_start(struct iscsi_cls_conn *cls_conn)
+ 	ret = 0;
+ 
+ exit_conn_start:
+-	dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+-			  fw_ddb_entry, fw_ddb_entry_dma);
++	if (fw_ddb_entry)
++		dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
++				  fw_ddb_entry, fw_ddb_entry_dma);
+ 	return ret;
+ }
+ 
+@@ -1344,6 +1486,101 @@ static int qla4xxx_task_xmit(struct iscsi_task *task)
+ 	return -ENOSYS;
+ }
+ 
++static void qla4xxx_copy_fwddb_param(struct scsi_qla_host *ha,
++				     struct dev_db_entry *fw_ddb_entry,
++				     struct iscsi_cls_session *cls_sess,
++				     struct iscsi_cls_conn *cls_conn)
++{
++	int buflen = 0;
++	struct iscsi_session *sess;
++	struct iscsi_conn *conn;
++	char ip_addr[DDB_IPADDR_LEN];
++	uint16_t options = 0;
++
++	sess = cls_sess->dd_data;
++	conn = cls_conn->dd_data;
++
++	conn->max_recv_dlength = BYTE_UNITS *
++			  le16_to_cpu(fw_ddb_entry->iscsi_max_rcv_data_seg_len);
++
++	conn->max_xmit_dlength = BYTE_UNITS *
++			  le16_to_cpu(fw_ddb_entry->iscsi_max_snd_data_seg_len);
++
++	sess->initial_r2t_en =
++			    (BIT_10 & le16_to_cpu(fw_ddb_entry->iscsi_options));
++
++	sess->max_r2t = le16_to_cpu(fw_ddb_entry->iscsi_max_outsnd_r2t);
++
++	sess->imm_data_en = (BIT_11 & le16_to_cpu(fw_ddb_entry->iscsi_options));
++
++	sess->first_burst = BYTE_UNITS *
++			       le16_to_cpu(fw_ddb_entry->iscsi_first_burst_len);
++
++	sess->max_burst = BYTE_UNITS *
++				 le16_to_cpu(fw_ddb_entry->iscsi_max_burst_len);
++
++	sess->time2wait = le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait);
++
++	sess->time2retain = le16_to_cpu(fw_ddb_entry->iscsi_def_time2retain);
++
++	conn->persistent_port = le16_to_cpu(fw_ddb_entry->port);
++
++	sess->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp);
++
++	options = le16_to_cpu(fw_ddb_entry->options);
++	if (options & DDB_OPT_IPV6_DEVICE)
++		sprintf(ip_addr, "%pI6", fw_ddb_entry->ip_addr);
++	else
++		sprintf(ip_addr, "%pI4", fw_ddb_entry->ip_addr);
++
++	iscsi_set_param(cls_conn, ISCSI_PARAM_TARGET_NAME,
++			(char *)fw_ddb_entry->iscsi_name, buflen);
++	iscsi_set_param(cls_conn, ISCSI_PARAM_INITIATOR_NAME,
++			(char *)ha->name_string, buflen);
++	iscsi_set_param(cls_conn, ISCSI_PARAM_PERSISTENT_ADDRESS,
++			(char *)ip_addr, buflen);
++}
++
++void qla4xxx_update_session_conn_fwddb_param(struct scsi_qla_host *ha,
++					     struct ddb_entry *ddb_entry)
++{
++	struct iscsi_cls_session *cls_sess;
++	struct iscsi_cls_conn *cls_conn;
++	uint32_t ddb_state;
++	dma_addr_t fw_ddb_entry_dma;
++	struct dev_db_entry *fw_ddb_entry;
++
++	fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
++					  &fw_ddb_entry_dma, GFP_KERNEL);
++	if (!fw_ddb_entry) {
++		ql4_printk(KERN_ERR, ha,
++			   "%s: Unable to allocate dma buffer\n", __func__);
++		goto exit_session_conn_fwddb_param;
++	}
++
++	if (qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, fw_ddb_entry,
++				    fw_ddb_entry_dma, NULL, NULL, &ddb_state,
++				    NULL, NULL, NULL) == QLA_ERROR) {
++		DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "
++				  "get_ddb_entry for fw_ddb_index %d\n",
++				  ha->host_no, __func__,
++				  ddb_entry->fw_ddb_index));
++		goto exit_session_conn_fwddb_param;
++	}
++
++	cls_sess = ddb_entry->sess;
++
++	cls_conn = ddb_entry->conn;
++
++	/* Update params */
++	qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess, cls_conn);
++
++exit_session_conn_fwddb_param:
++	if (fw_ddb_entry)
++		dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
++				  fw_ddb_entry, fw_ddb_entry_dma);
++}
++
+ void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha,
+ 				       struct ddb_entry *ddb_entry)
+ {
+@@ -1360,7 +1597,7 @@ void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha,
+ 	if (!fw_ddb_entry) {
+ 		ql4_printk(KERN_ERR, ha,
+ 			   "%s: Unable to allocate dma buffer\n", __func__);
+-		return;
++		goto exit_session_conn_param;
+ 	}
+ 
+ 	if (qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, fw_ddb_entry,
+@@ -1370,7 +1607,7 @@ void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha,
+ 				  "get_ddb_entry for fw_ddb_index %d\n",
+ 				  ha->host_no, __func__,
+ 				  ddb_entry->fw_ddb_index));
+-		return;
++		goto exit_session_conn_param;
+ 	}
+ 
+ 	cls_sess = ddb_entry->sess;
+@@ -1379,6 +1616,12 @@ void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha,
+ 	cls_conn = ddb_entry->conn;
+ 	conn = cls_conn->dd_data;
+ 
++	/* Update timers after login */
++	ddb_entry->default_relogin_timeout =
++				le16_to_cpu(fw_ddb_entry->def_timeout);
++	ddb_entry->default_time2wait =
++				le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait);
++
+ 	/* Update params */
+ 	conn->max_recv_dlength = BYTE_UNITS *
+ 			  le16_to_cpu(fw_ddb_entry->iscsi_max_rcv_data_seg_len);
+@@ -1407,6 +1650,11 @@ void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha,
+ 
+ 	memcpy(sess->initiatorname, ha->name_string,
+ 	       min(sizeof(ha->name_string), sizeof(sess->initiatorname)));
++
++exit_session_conn_param:
++	if (fw_ddb_entry)
++		dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
++				  fw_ddb_entry, fw_ddb_entry_dma);
+ }
+ 
+ /*
+@@ -1607,6 +1855,9 @@ static void qla4xxx_mem_free(struct scsi_qla_host *ha)
+ 		vfree(ha->chap_list);
+ 	ha->chap_list = NULL;
+ 
++	if (ha->fw_ddb_dma_pool)
++		dma_pool_destroy(ha->fw_ddb_dma_pool);
++
+ 	/* release io space registers  */
+ 	if (is_qla8022(ha)) {
+ 		if (ha->nx_pcibase)
+@@ -1689,6 +1940,16 @@ static int qla4xxx_mem_alloc(struct scsi_qla_host *ha)
+ 		goto mem_alloc_error_exit;
+ 	}
+ 
++	ha->fw_ddb_dma_pool = dma_pool_create("ql4_fw_ddb", &ha->pdev->dev,
++					      DDB_DMA_BLOCK_SIZE, 8, 0);
++
++	if (ha->fw_ddb_dma_pool == NULL) {
++		ql4_printk(KERN_WARNING, ha,
++			   "%s: fw_ddb_dma_pool allocation failed..\n",
++			   __func__);
++		goto mem_alloc_error_exit;
++	}
++
+ 	return QLA_SUCCESS;
+ 
+ mem_alloc_error_exit:
+@@ -1800,6 +2061,60 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha)
+ 	}
+ }
+ 
++void qla4xxx_check_relogin_flash_ddb(struct iscsi_cls_session *cls_sess)
++{
++	struct iscsi_session *sess;
++	struct ddb_entry *ddb_entry;
++	struct scsi_qla_host *ha;
++
++	sess = cls_sess->dd_data;
++	ddb_entry = sess->dd_data;
++	ha = ddb_entry->ha;
++
++	if (!(ddb_entry->ddb_type == FLASH_DDB))
++		return;
++
++	if (adapter_up(ha) && !test_bit(DF_RELOGIN, &ddb_entry->flags) &&
++	    !iscsi_is_session_online(cls_sess)) {
++		if (atomic_read(&ddb_entry->retry_relogin_timer) !=
++		    INVALID_ENTRY) {
++			if (atomic_read(&ddb_entry->retry_relogin_timer) ==
++					0) {
++				atomic_set(&ddb_entry->retry_relogin_timer,
++					   INVALID_ENTRY);
++				set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags);
++				set_bit(DF_RELOGIN, &ddb_entry->flags);
++				DEBUG2(ql4_printk(KERN_INFO, ha,
++				       "%s: index [%d] login device\n",
++					__func__, ddb_entry->fw_ddb_index));
++			} else
++				atomic_dec(&ddb_entry->retry_relogin_timer);
++		}
++	}
++
++	/* Wait for relogin to timeout */
++	if (atomic_read(&ddb_entry->relogin_timer) &&
++	    (atomic_dec_and_test(&ddb_entry->relogin_timer) != 0)) {
++		/*
++		 * If the relogin times out and the device is
++		 * still NOT ONLINE then try and relogin again.
++		 */
++		if (!iscsi_is_session_online(cls_sess)) {
++			/* Reset retry relogin timer */
++			atomic_inc(&ddb_entry->relogin_retry_count);
++			DEBUG2(ql4_printk(KERN_INFO, ha,
++				"%s: index[%d] relogin timed out-retrying"
++				" relogin (%d), retry (%d)\n", __func__,
++				ddb_entry->fw_ddb_index,
++				atomic_read(&ddb_entry->relogin_retry_count),
++				ddb_entry->default_time2wait + 4));
++			set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags);
++			atomic_set(&ddb_entry->retry_relogin_timer,
++				   ddb_entry->default_time2wait + 4);
++		}
++	}
++}
++
+ /**
+  * qla4xxx_timer - checks every second for work to do.
+  * @ha: Pointer to host adapter structure.
+@@ -1809,6 +2124,8 @@ static void qla4xxx_timer(struct scsi_qla_host *ha)
+ 	int start_dpc = 0;
+ 	uint16_t w;
+ 
++	iscsi_host_for_each_session(ha->host, qla4xxx_check_relogin_flash_ddb);
++
+ 	/* If we are in the middle of AER/EEH processing
+ 	 * skip any processing and reschedule the timer
+ 	 */
+@@ -2078,7 +2395,12 @@ static void qla4xxx_fail_session(struct iscsi_cls_session *cls_session)
+ 	sess = cls_session->dd_data;
+ 	ddb_entry = sess->dd_data;
+ 	ddb_entry->fw_ddb_device_state = DDB_DS_SESSION_FAILED;
+-	iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED);
++
++	if (ddb_entry->ddb_type == FLASH_DDB)
++		iscsi_block_session(ddb_entry->sess);
++	else
++		iscsi_session_failure(cls_session->dd_data,
++				      ISCSI_ERR_CONN_FAILED);
+ }
+ 
+ /**
+@@ -2163,7 +2485,7 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha)
+ 
+ 		/* NOTE: AF_ONLINE flag set upon successful completion of
+ 		 *       qla4xxx_initialize_adapter */
+-		status = qla4xxx_initialize_adapter(ha);
++		status = qla4xxx_initialize_adapter(ha, RESET_ADAPTER);
+ 	}
+ 
+ 	/* Retry failed adapter initialization, if necessary
+@@ -2245,17 +2567,108 @@ static void qla4xxx_relogin_devices(struct iscsi_cls_session *cls_session)
+ 			iscsi_unblock_session(ddb_entry->sess);
+ 		} else {
+ 			/* Trigger relogin */
+-			iscsi_session_failure(cls_session->dd_data,
+-					      ISCSI_ERR_CONN_FAILED);
++			if (ddb_entry->ddb_type == FLASH_DDB) {
++				if (!test_bit(DF_RELOGIN, &ddb_entry->flags))
++					qla4xxx_arm_relogin_timer(ddb_entry);
++			} else
++				iscsi_session_failure(cls_session->dd_data,
++						      ISCSI_ERR_CONN_FAILED);
+ 		}
+ 	}
+ }
+ 
++int qla4xxx_unblock_flash_ddb(struct iscsi_cls_session *cls_session)
++{
++	struct iscsi_session *sess;
++	struct ddb_entry *ddb_entry;
++	struct scsi_qla_host *ha;
++
++	sess = cls_session->dd_data;
++	ddb_entry = sess->dd_data;
++	ha = ddb_entry->ha;
++	ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]"
++		   " unblock session\n", ha->host_no, __func__,
++		   ddb_entry->fw_ddb_index);
++
++	iscsi_unblock_session(ddb_entry->sess);
++
++	/* Start scan target */
++	if (test_bit(AF_ONLINE, &ha->flags)) {
++		ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]"
++			   " start scan\n", ha->host_no, __func__,
++			   ddb_entry->fw_ddb_index);
++		scsi_queue_work(ha->host, &ddb_entry->sess->scan_work);
++	}
++	return QLA_SUCCESS;
++}
++
++int qla4xxx_unblock_ddb(struct iscsi_cls_session *cls_session)
++{
++	struct iscsi_session *sess;
++	struct ddb_entry *ddb_entry;
++	struct scsi_qla_host *ha;
++
++	sess = cls_session->dd_data;
++	ddb_entry = sess->dd_data;
++	ha = ddb_entry->ha;
++	ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]"
++		   " unblock user space session\n", ha->host_no, __func__,
++		   ddb_entry->fw_ddb_index);
++	iscsi_conn_start(ddb_entry->conn);
++	iscsi_conn_login_event(ddb_entry->conn,
++			       ISCSI_CONN_STATE_LOGGED_IN);
++
++	return QLA_SUCCESS;
++}
++
+ static void qla4xxx_relogin_all_devices(struct scsi_qla_host *ha)
+ {
+ 	iscsi_host_for_each_session(ha->host, qla4xxx_relogin_devices);
+ }
+ 
++static void qla4xxx_relogin_flash_ddb(struct iscsi_cls_session *cls_sess)
++{
++	uint16_t relogin_timer;
++	struct iscsi_session *sess;
++	struct ddb_entry *ddb_entry;
++	struct scsi_qla_host *ha;
++
++	sess = cls_sess->dd_data;
++	ddb_entry = sess->dd_data;
++	ha = ddb_entry->ha;
++
++	relogin_timer = max(ddb_entry->default_relogin_timeout,
++			    (uint16_t)RELOGIN_TOV);
++	atomic_set(&ddb_entry->relogin_timer, relogin_timer);
++
++	DEBUG2(ql4_printk(KERN_INFO, ha,
++			  "scsi%ld: Relogin index [%d]. TOV=%d\n", ha->host_no,
++			  ddb_entry->fw_ddb_index, relogin_timer));
++
++	qla4xxx_login_flash_ddb(cls_sess);
++}
++
++static void qla4xxx_dpc_relogin(struct iscsi_cls_session *cls_sess)
++{
++	struct iscsi_session *sess;
++	struct ddb_entry *ddb_entry;
++	struct scsi_qla_host *ha;
++
++	sess = cls_sess->dd_data;
++	ddb_entry = sess->dd_data;
++	ha = ddb_entry->ha;
++
++	if (!(ddb_entry->ddb_type == FLASH_DDB))
++		return;
++
++	if (test_and_clear_bit(DF_RELOGIN, &ddb_entry->flags) &&
++	    !iscsi_is_session_online(cls_sess)) {
++		DEBUG2(ql4_printk(KERN_INFO, ha,
++				  "relogin issued\n"));
++		qla4xxx_relogin_flash_ddb(cls_sess);
++	}
++}
++
+ void qla4xxx_wake_dpc(struct scsi_qla_host *ha)
+ {
+ 	if (ha->dpc_thread)
+@@ -2356,6 +2769,12 @@ static void qla4xxx_do_dpc(struct work_struct *work)
+ 	if (test_and_clear_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags))
+ 		qla4xxx_get_dhcp_ip_address(ha);
+ 
++	/* ---- relogin device? --- */
++	if (adapter_up(ha) &&
++	    test_and_clear_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags)) {
++		iscsi_host_for_each_session(ha->host, qla4xxx_dpc_relogin);
++	}
++
+ 	/* ---- link change? --- */
+ 	if (test_and_clear_bit(DPC_LINK_CHANGED, &ha->dpc_flags)) {
+ 		if (!test_bit(AF_LINK_UP, &ha->flags)) {
+@@ -2368,8 +2787,12 @@ static void qla4xxx_do_dpc(struct work_struct *work)
+ 			 * fatal error recovery.  Therefore, the driver must
+ 			 * manually relogin to devices when recovering from
+ 			 * connection failures, logouts, expired KATO, etc. */
+-
+-			qla4xxx_relogin_all_devices(ha);
++			if (test_and_clear_bit(AF_BUILD_DDB_LIST, &ha->flags)) {
++				qla4xxx_build_ddb_list(ha, ha->is_reset);
++				iscsi_host_for_each_session(ha->host,
++						qla4xxx_login_flash_ddb);
++			} else
++				qla4xxx_relogin_all_devices(ha);
+ 		}
+ 	}
+ }
+@@ -2867,6 +3290,9 @@ static int get_fw_boot_info(struct scsi_qla_host *ha, uint16_t ddb_index[])
+ 			  " target ID %d\n", __func__, ddb_index[0],
+ 			  ddb_index[1]));
+ 
++	ha->pri_ddb_idx = ddb_index[0];
++	ha->sec_ddb_idx = ddb_index[1];
++
+ exit_boot_info_free:
+ 	dma_free_coherent(&ha->pdev->dev, size, buf, buf_dma);
+ exit_boot_info:
+@@ -3034,6 +3460,9 @@ static int qla4xxx_get_boot_info(struct scsi_qla_host *ha)
+ 		return ret;
+ 	}
+ 
++	if (ql4xdisablesysfsboot)
++		return QLA_SUCCESS;
++
+ 	if (ddb_index[0] == 0xffff)
+ 		goto sec_target;
+ 
+@@ -3066,7 +3495,15 @@ static int qla4xxx_setup_boot_info(struct scsi_qla_host *ha)
+ 	struct iscsi_boot_kobj *boot_kobj;
+ 
+ 	if (qla4xxx_get_boot_info(ha) != QLA_SUCCESS)
+-		return 0;
++		return QLA_ERROR;
++
++	if (ql4xdisablesysfsboot) {
++		ql4_printk(KERN_INFO, ha,
++			   "%s: syfsboot disabled - driver will trigger login"
++			   "and publish session for discovery .\n", __func__);
++		return QLA_SUCCESS;
++	}
++
+ 
+ 	ha->boot_kset = iscsi_boot_create_host_kset(ha->host->host_no);
+ 	if (!ha->boot_kset)
+@@ -3108,7 +3545,7 @@ static int qla4xxx_setup_boot_info(struct scsi_qla_host *ha)
+ 	if (!boot_kobj)
+ 		goto put_host;
+ 
+-	return 0;
++	return QLA_SUCCESS;
+ 
+ put_host:
+ 	scsi_host_put(ha->host);
+@@ -3174,9 +3611,507 @@ static void qla4xxx_create_chap_list(struct scsi_qla_host *ha)
+ exit_chap_list:
+ 	dma_free_coherent(&ha->pdev->dev, chap_size,
+ 			chap_flash_data, chap_dma);
+-	return;
+ }
+ 
++static void qla4xxx_get_param_ddb(struct ddb_entry *ddb_entry,
++				  struct ql4_tuple_ddb *tddb)
++{
++	struct scsi_qla_host *ha;
++	struct iscsi_cls_session *cls_sess;
++	struct iscsi_cls_conn *cls_conn;
++	struct iscsi_session *sess;
++	struct iscsi_conn *conn;
++
++	DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
++	ha = ddb_entry->ha;
++	cls_sess = ddb_entry->sess;
++	sess = cls_sess->dd_data;
++	cls_conn = ddb_entry->conn;
++	conn = cls_conn->dd_data;
++
++	tddb->tpgt = sess->tpgt;
++	tddb->port = conn->persistent_port;
++	strncpy(tddb->iscsi_name, sess->targetname, ISCSI_NAME_SIZE);
++	strncpy(tddb->ip_addr, conn->persistent_address, DDB_IPADDR_LEN);
++}
++
++static void qla4xxx_convert_param_ddb(struct dev_db_entry *fw_ddb_entry,
++				      struct ql4_tuple_ddb *tddb)
++{
++	uint16_t options = 0;
++
++	tddb->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp);
++	memcpy(&tddb->iscsi_name[0], &fw_ddb_entry->iscsi_name[0],
++	       min(sizeof(tddb->iscsi_name), sizeof(fw_ddb_entry->iscsi_name)));
++
++	options = le16_to_cpu(fw_ddb_entry->options);
++	if (options & DDB_OPT_IPV6_DEVICE)
++		sprintf(tddb->ip_addr, "%pI6", fw_ddb_entry->ip_addr);
++	else
++		sprintf(tddb->ip_addr, "%pI4", fw_ddb_entry->ip_addr);
++
++	tddb->port = le16_to_cpu(fw_ddb_entry->port);
++}
++
++static int qla4xxx_compare_tuple_ddb(struct scsi_qla_host *ha,
++				     struct ql4_tuple_ddb *old_tddb,
++				     struct ql4_tuple_ddb *new_tddb)
++{
++	if (strcmp(old_tddb->iscsi_name, new_tddb->iscsi_name))
++		return QLA_ERROR;
++
++	if (strcmp(old_tddb->ip_addr, new_tddb->ip_addr))
++		return QLA_ERROR;
++
++	if (old_tddb->port != new_tddb->port)
++		return QLA_ERROR;
++
++	DEBUG2(ql4_printk(KERN_INFO, ha,
++			  "Match Found, fw[%d,%d,%s,%s], [%d,%d,%s,%s]",
++			  old_tddb->port, old_tddb->tpgt, old_tddb->ip_addr,
++			  old_tddb->iscsi_name, new_tddb->port, new_tddb->tpgt,
++			  new_tddb->ip_addr, new_tddb->iscsi_name));
++
++	return QLA_SUCCESS;
++}
++
++static int qla4xxx_is_session_exists(struct scsi_qla_host *ha,
++				     struct dev_db_entry *fw_ddb_entry)
++{
++	struct ddb_entry *ddb_entry;
++	struct ql4_tuple_ddb *fw_tddb = NULL;
++	struct ql4_tuple_ddb *tmp_tddb = NULL;
++	int idx;
++	int ret = QLA_ERROR;
++
++	fw_tddb = vzalloc(sizeof(*fw_tddb));
++	if (!fw_tddb) {
++		DEBUG2(ql4_printk(KERN_WARNING, ha,
++				  "Memory Allocation failed.\n"));
++		ret = QLA_SUCCESS;
++		goto exit_check;
++	}
++
++	tmp_tddb = vzalloc(sizeof(*tmp_tddb));
++	if (!tmp_tddb) {
++		DEBUG2(ql4_printk(KERN_WARNING, ha,
++				  "Memory Allocation failed.\n"));
++		ret = QLA_SUCCESS;
++		goto exit_check;
++	}
++
++	qla4xxx_convert_param_ddb(fw_ddb_entry, fw_tddb);
++
++	for (idx = 0; idx < MAX_DDB_ENTRIES; idx++) {
++		ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx);
++		if (ddb_entry == NULL)
++			continue;
++
++		qla4xxx_get_param_ddb(ddb_entry, tmp_tddb);
++		if (!qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb)) {
++			ret = QLA_SUCCESS; /* found */
++			goto exit_check;
++		}
++	}
++
++exit_check:
++	if (fw_tddb)
++		vfree(fw_tddb);
++	if (tmp_tddb)
++		vfree(tmp_tddb);
++	return ret;
++}
++
++static int qla4xxx_is_flash_ddb_exists(struct scsi_qla_host *ha,
++				       struct list_head *list_nt,
++				       struct dev_db_entry *fw_ddb_entry)
++{
++	struct qla_ddb_index  *nt_ddb_idx, *nt_ddb_idx_tmp;
++	struct ql4_tuple_ddb *fw_tddb = NULL;
++	struct ql4_tuple_ddb *tmp_tddb = NULL;
++	int ret = QLA_ERROR;
++
++	fw_tddb = vzalloc(sizeof(*fw_tddb));
++	if (!fw_tddb) {
++		DEBUG2(ql4_printk(KERN_WARNING, ha,
++				  "Memory Allocation failed.\n"));
++		ret = QLA_SUCCESS;
++		goto exit_check;
++	}
++
++	tmp_tddb = vzalloc(sizeof(*tmp_tddb));
++	if (!tmp_tddb) {
++		DEBUG2(ql4_printk(KERN_WARNING, ha,
++				  "Memory Allocation failed.\n"));
++		ret = QLA_SUCCESS;
++		goto exit_check;
++	}
++
++	qla4xxx_convert_param_ddb(fw_ddb_entry, fw_tddb);
++
++	list_for_each_entry_safe(nt_ddb_idx, nt_ddb_idx_tmp, list_nt, list) {
++		qla4xxx_convert_param_ddb(&nt_ddb_idx->fw_ddb, tmp_tddb);
++		if (!qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb)) {
++			ret = QLA_SUCCESS; /* found */
++			goto exit_check;
++		}
++	}
++
++exit_check:
++	if (fw_tddb)
++		vfree(fw_tddb);
++	if (tmp_tddb)
++		vfree(tmp_tddb);
++	return ret;
++}
++
++static void qla4xxx_free_nt_list(struct list_head *list_nt)
++{
++	struct qla_ddb_index  *nt_ddb_idx, *nt_ddb_idx_tmp;
++
++	/* Free up the normaltargets list */
++	list_for_each_entry_safe(nt_ddb_idx, nt_ddb_idx_tmp, list_nt, list) {
++		list_del_init(&nt_ddb_idx->list);
++		vfree(nt_ddb_idx);
++	}
++
++}
++
++static struct iscsi_endpoint *qla4xxx_get_ep_fwdb(struct scsi_qla_host *ha,
++					struct dev_db_entry *fw_ddb_entry)
++{
++	struct iscsi_endpoint *ep;
++	struct sockaddr_in *addr;
++	struct sockaddr_in6 *addr6;
++	struct sockaddr *dst_addr;
++	char *ip;
++
++	/* TODO: need to destroy on unload iscsi_endpoint*/
++	dst_addr = vmalloc(sizeof(*dst_addr));
++	if (!dst_addr)
++		return NULL;
++
++	if (fw_ddb_entry->options & DDB_OPT_IPV6_DEVICE) {
++		dst_addr->sa_family = AF_INET6;
++		addr6 = (struct sockaddr_in6 *)dst_addr;
++		ip = (char *)&addr6->sin6_addr;
++		memcpy(ip, fw_ddb_entry->ip_addr, IPv6_ADDR_LEN);
++		addr6->sin6_port = htons(le16_to_cpu(fw_ddb_entry->port));
++
++	} else {
++		dst_addr->sa_family = AF_INET;
++		addr = (struct sockaddr_in *)dst_addr;
++		ip = (char *)&addr->sin_addr;
++		memcpy(ip, fw_ddb_entry->ip_addr, IP_ADDR_LEN);
++		addr->sin_port = htons(le16_to_cpu(fw_ddb_entry->port));
++	}
++
++	ep = qla4xxx_ep_connect(ha->host, dst_addr, 0);
++	vfree(dst_addr);
++	return ep;
++}
++
++static int qla4xxx_verify_boot_idx(struct scsi_qla_host *ha, uint16_t idx)
++{
++	if (ql4xdisablesysfsboot)
++		return QLA_SUCCESS;
++	if (idx == ha->pri_ddb_idx || idx == ha->sec_ddb_idx)
++		return QLA_ERROR;
++	return QLA_SUCCESS;
++}
++
++static void qla4xxx_setup_flash_ddb_entry(struct scsi_qla_host *ha,
++					  struct ddb_entry *ddb_entry)
++{
++	ddb_entry->ddb_type = FLASH_DDB;
++	ddb_entry->fw_ddb_index = INVALID_ENTRY;
++	ddb_entry->fw_ddb_device_state = DDB_DS_NO_CONNECTION_ACTIVE;
++	ddb_entry->ha = ha;
++	ddb_entry->unblock_sess = qla4xxx_unblock_flash_ddb;
++	ddb_entry->ddb_change = qla4xxx_flash_ddb_change;
++
++	atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY);
++	atomic_set(&ddb_entry->relogin_timer, 0);
++	atomic_set(&ddb_entry->relogin_retry_count, 0);
++
++	ddb_entry->default_relogin_timeout =
++		le16_to_cpu(ddb_entry->fw_ddb_entry.def_timeout);
++	ddb_entry->default_time2wait =
++		le16_to_cpu(ddb_entry->fw_ddb_entry.iscsi_def_time2wait);
++}
++
++static void qla4xxx_wait_for_ip_configuration(struct scsi_qla_host *ha)
++{
++	uint32_t idx = 0;
++	uint32_t ip_idx[IP_ADDR_COUNT] = {0, 1, 2, 3}; /* 4 IP interfaces */
++	uint32_t sts[MBOX_REG_COUNT];
++	uint32_t ip_state;
++	unsigned long wtime;
++	int ret;
++
++	wtime = jiffies + (HZ * IP_CONFIG_TOV);
++	do {
++		for (idx = 0; idx < IP_ADDR_COUNT; idx++) {
++			if (ip_idx[idx] == -1)
++				continue;
++
++			ret = qla4xxx_get_ip_state(ha, 0, ip_idx[idx], sts);
++
++			if (ret == QLA_ERROR) {
++				ip_idx[idx] = -1;
++				continue;
++			}
++
++			ip_state = (sts[1] & IP_STATE_MASK) >> IP_STATE_SHIFT;
++
++			DEBUG2(ql4_printk(KERN_INFO, ha,
++					  "Waiting for IP state for idx = %d, state = 0x%x\n",
++					  ip_idx[idx], ip_state));
++			if (ip_state == IP_ADDRSTATE_UNCONFIGURED ||
++			    ip_state == IP_ADDRSTATE_INVALID ||
++			    ip_state == IP_ADDRSTATE_PREFERRED ||
++			    ip_state == IP_ADDRSTATE_DEPRICATED ||
++			    ip_state == IP_ADDRSTATE_DISABLING)
++				ip_idx[idx] = -1;
++
++		}
++
++		/* Break if all IP states checked */
++		if ((ip_idx[0] == -1) &&
++		    (ip_idx[1] == -1) &&
++		    (ip_idx[2] == -1) &&
++		    (ip_idx[3] == -1))
++			break;
++		schedule_timeout_uninterruptible(HZ);
++	} while (time_after(wtime, jiffies));
++}
++
++void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset)
++{
++	int max_ddbs;
++	int ret;
++	uint32_t idx = 0, next_idx = 0;
++	uint32_t state = 0, conn_err = 0;
++	uint16_t conn_id;
++	struct dev_db_entry *fw_ddb_entry;
++	struct ddb_entry *ddb_entry = NULL;
++	dma_addr_t fw_ddb_dma;
++	struct iscsi_cls_session *cls_sess;
++	struct iscsi_session *sess;
++	struct iscsi_cls_conn *cls_conn;
++	struct iscsi_endpoint *ep;
++	uint16_t cmds_max = 32, tmo = 0;
++	uint32_t initial_cmdsn = 0;
++	struct list_head list_st, list_nt; /* List of sendtargets */
++	struct qla_ddb_index  *st_ddb_idx, *st_ddb_idx_tmp;
++	int fw_idx_size;
++	unsigned long wtime;
++	struct qla_ddb_index  *nt_ddb_idx;
++
++	if (!test_bit(AF_LINK_UP, &ha->flags)) {
++		set_bit(AF_BUILD_DDB_LIST, &ha->flags);
++		ha->is_reset = is_reset;
++		return;
++	}
++	max_ddbs =  is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
++				     MAX_DEV_DB_ENTRIES;
++
++	fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL,
++				      &fw_ddb_dma);
++	if (fw_ddb_entry == NULL) {
++		DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n"));
++		goto exit_ddb_list;
++	}
++
++	INIT_LIST_HEAD(&list_st);
++	INIT_LIST_HEAD(&list_nt);
++	fw_idx_size = sizeof(struct qla_ddb_index);
++
++	for (idx = 0; idx < max_ddbs; idx = next_idx) {
++		ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry,
++					      fw_ddb_dma, NULL,
++					      &next_idx, &state, &conn_err,
++					      NULL, &conn_id);
++		if (ret == QLA_ERROR)
++			break;
++
++		if (qla4xxx_verify_boot_idx(ha, idx) != QLA_SUCCESS)
++			goto continue_next_st;
++
++		/* Check if ST, add to the list_st */
++		if (strlen((char *) fw_ddb_entry->iscsi_name) != 0)
++			goto continue_next_st;
++
++		st_ddb_idx = vzalloc(fw_idx_size);
++		if (!st_ddb_idx)
++			break;
++
++		st_ddb_idx->fw_ddb_idx = idx;
++
++		list_add_tail(&st_ddb_idx->list, &list_st);
++continue_next_st:
++		if (next_idx == 0)
++			break;
++	}
++
++	/* Before issuing conn open mbox, ensure all IPs states are configured
++	 * Note, conn open fails if IPs are not configured
++	 */
++	qla4xxx_wait_for_ip_configuration(ha);
++
++	/* Go thru the STs and fire the sendtargets by issuing conn open mbx */
++	list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) {
++		qla4xxx_conn_open(ha, st_ddb_idx->fw_ddb_idx);
++	}
++
++	/* Wait to ensure all sendtargets are done for min 12 sec wait */
++	tmo = ((ha->def_timeout < LOGIN_TOV) ? LOGIN_TOV : ha->def_timeout);
++	DEBUG2(ql4_printk(KERN_INFO, ha,
++			  "Default time to wait for build ddb %d\n", tmo));
++
++	wtime = jiffies + (HZ * tmo);
++	do {
++		list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st,
++					 list) {
++			ret = qla4xxx_get_fwddb_entry(ha,
++						      st_ddb_idx->fw_ddb_idx,
++						      NULL, 0, NULL, &next_idx,
++						      &state, &conn_err, NULL,
++						      NULL);
++			if (ret == QLA_ERROR)
++				continue;
++
++			if (state == DDB_DS_NO_CONNECTION_ACTIVE ||
++			    state == DDB_DS_SESSION_FAILED) {
++				list_del_init(&st_ddb_idx->list);
++				vfree(st_ddb_idx);
++			}
++		}
++		schedule_timeout_uninterruptible(HZ / 10);
++	} while (time_after(wtime, jiffies));
++
++	/* Free up the sendtargets list */
++	list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) {
++		list_del_init(&st_ddb_idx->list);
++		vfree(st_ddb_idx);
++	}
++
++	for (idx = 0; idx < max_ddbs; idx = next_idx) {
++		ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry,
++					      fw_ddb_dma, NULL,
++					      &next_idx, &state, &conn_err,
++					      NULL, &conn_id);
++		if (ret == QLA_ERROR)
++			break;
++
++		if (qla4xxx_verify_boot_idx(ha, idx) != QLA_SUCCESS)
++			goto continue_next_nt;
++
++		/* Check if NT, then add to list it */
++		if (strlen((char *) fw_ddb_entry->iscsi_name) == 0)
++			goto continue_next_nt;
++
++		if (state == DDB_DS_NO_CONNECTION_ACTIVE ||
++		    state == DDB_DS_SESSION_FAILED) {
++			DEBUG2(ql4_printk(KERN_INFO, ha,
++					  "Adding  DDB to session = 0x%x\n",
++					  idx));
++			if (is_reset == INIT_ADAPTER) {
++				nt_ddb_idx = vmalloc(fw_idx_size);
++				if (!nt_ddb_idx)
++					break;
++
++				nt_ddb_idx->fw_ddb_idx = idx;
++
++				memcpy(&nt_ddb_idx->fw_ddb, fw_ddb_entry,
++				       sizeof(struct dev_db_entry));
++
++				if (qla4xxx_is_flash_ddb_exists(ha, &list_nt,
++						fw_ddb_entry) == QLA_SUCCESS) {
++					vfree(nt_ddb_idx);
++					goto continue_next_nt;
++				}
++				list_add_tail(&nt_ddb_idx->list, &list_nt);
++			} else if (is_reset == RESET_ADAPTER) {
++				if (qla4xxx_is_session_exists(ha,
++						   fw_ddb_entry) == QLA_SUCCESS)
++					goto continue_next_nt;
++			}
++
++			/* Create session object, with INVALID_ENTRY,
++			 * the targer_id would get set when we issue the login
++			 */
++			cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport,
++						ha->host, cmds_max,
++						sizeof(struct ddb_entry),
++						sizeof(struct ql4_task_data),
++						initial_cmdsn, INVALID_ENTRY);
++			if (!cls_sess)
++				goto exit_ddb_list;
++
++			/*
++			 * iscsi_session_setup increments the driver reference
++			 * count which wouldn't let the driver to be unloaded.
++			 * so calling module_put function to decrement the
++			 * reference count.
++			 **/
++			module_put(qla4xxx_iscsi_transport.owner);
++			sess = cls_sess->dd_data;
++			ddb_entry = sess->dd_data;
++			ddb_entry->sess = cls_sess;
++
++			cls_sess->recovery_tmo = ql4xsess_recovery_tmo;
++			memcpy(&ddb_entry->fw_ddb_entry, fw_ddb_entry,
++			       sizeof(struct dev_db_entry));
++
++			qla4xxx_setup_flash_ddb_entry(ha, ddb_entry);
++
++			cls_conn = iscsi_conn_setup(cls_sess,
++						    sizeof(struct qla_conn),
++						    conn_id);
++			if (!cls_conn)
++				goto exit_ddb_list;
++
++			ddb_entry->conn = cls_conn;
++
++			/* Setup ep, for displaying attributes in sysfs */
++			ep = qla4xxx_get_ep_fwdb(ha, fw_ddb_entry);
++			if (ep) {
++				ep->conn = cls_conn;
++				cls_conn->ep = ep;
++			} else {
++				DEBUG2(ql4_printk(KERN_ERR, ha,
++						  "Unable to get ep\n"));
++			}
++
++			/* Update sess/conn params */
++			qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess,
++						 cls_conn);
++
++			if (is_reset == RESET_ADAPTER) {
++				iscsi_block_session(cls_sess);
++				/* Use the relogin path to discover new devices
++				 *  by short-circuting the logic of setting
++				 *  timer to relogin - instead set the flags
++				 *  to initiate login right away.
++				 */
++				set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags);
++				set_bit(DF_RELOGIN, &ddb_entry->flags);
++			}
++		}
++continue_next_nt:
++		if (next_idx == 0)
++			break;
++	}
++exit_ddb_list:
++	qla4xxx_free_nt_list(&list_nt);
++	if (fw_ddb_entry)
++		dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma);
++
++	qla4xxx_free_ddb_index(ha);
++}
++
++
+ /**
+  * qla4xxx_probe_adapter - callback function to probe HBA
+  * @pdev: pointer to pci_dev structure
+@@ -3298,7 +4233,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
+ 	 * firmware
+ 	 * NOTE: interrupts enabled upon successful completion
+ 	 */
+-	status = qla4xxx_initialize_adapter(ha);
++	status = qla4xxx_initialize_adapter(ha, INIT_ADAPTER);
+ 	while ((!test_bit(AF_ONLINE, &ha->flags)) &&
+ 	    init_retry_count++ < MAX_INIT_RETRIES) {
+ 
+@@ -3319,7 +4254,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
+ 		if (ha->isp_ops->reset_chip(ha) == QLA_ERROR)
+ 			continue;
+ 
+-		status = qla4xxx_initialize_adapter(ha);
++		status = qla4xxx_initialize_adapter(ha, INIT_ADAPTER);
+ 	}
+ 
+ 	if (!test_bit(AF_ONLINE, &ha->flags)) {
+@@ -3386,12 +4321,16 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
+ 	       ha->host_no, ha->firmware_version[0], ha->firmware_version[1],
+ 	       ha->patch_number, ha->build_number);
+ 
+-	qla4xxx_create_chap_list(ha);
+-
+ 	if (qla4xxx_setup_boot_info(ha))
+ 		ql4_printk(KERN_ERR, ha, "%s:ISCSI boot info setup failed\n",
+ 			   __func__);
+ 
++		/* Perform the build ddb list and login to each */
++	qla4xxx_build_ddb_list(ha, INIT_ADAPTER);
++	iscsi_host_for_each_session(ha->host, qla4xxx_login_flash_ddb);
++
++	qla4xxx_create_chap_list(ha);
++
+ 	qla4xxx_create_ifaces(ha);
+ 	return 0;
+ 
+@@ -3449,6 +4388,38 @@ static void qla4xxx_prevent_other_port_reinit(struct scsi_qla_host *ha)
+ 	}
+ }
+ 
++static void qla4xxx_destroy_fw_ddb_session(struct scsi_qla_host *ha)
++{
++	struct ddb_entry *ddb_entry;
++	int options;
++	int idx;
++
++	for (idx = 0; idx < MAX_DDB_ENTRIES; idx++) {
++
++		ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx);
++		if ((ddb_entry != NULL) &&
++		    (ddb_entry->ddb_type == FLASH_DDB)) {
++
++			options = LOGOUT_OPTION_CLOSE_SESSION;
++			if (qla4xxx_session_logout_ddb(ha, ddb_entry, options)
++			    == QLA_ERROR)
++				ql4_printk(KERN_ERR, ha, "%s: Logout failed\n",
++					   __func__);
++
++			qla4xxx_clear_ddb_entry(ha, ddb_entry->fw_ddb_index);
++			/*
++			 * we have decremented the reference count of the driver
++			 * when we setup the session to have the driver unload
++			 * to be seamless without actually destroying the
++			 * session
++			 **/
++			try_module_get(qla4xxx_iscsi_transport.owner);
++			iscsi_destroy_endpoint(ddb_entry->conn->ep);
++			qla4xxx_free_ddb(ha, ddb_entry);
++			iscsi_session_teardown(ddb_entry->sess);
++		}
++	}
++}
+ /**
+  * qla4xxx_remove_adapter - calback function to remove adapter.
+  * @pci_dev: PCI device pointer
+@@ -3465,9 +4436,11 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev)
+ 	/* destroy iface from sysfs */
+ 	qla4xxx_destroy_ifaces(ha);
+ 
+-	if (ha->boot_kset)
++	if ((!ql4xdisablesysfsboot) && ha->boot_kset)
+ 		iscsi_boot_destroy_kset(ha->boot_kset);
+ 
++	qla4xxx_destroy_fw_ddb_session(ha);
++
+ 	scsi_remove_host(ha->host);
+ 
+ 	qla4xxx_free_adapter(ha);
+@@ -4115,7 +5088,7 @@ static uint32_t qla4_8xxx_error_recovery(struct scsi_qla_host *ha)
+ 
+ 		qla4_8xxx_idc_unlock(ha);
+ 		clear_bit(AF_FW_RECOVERY, &ha->flags);
+-		rval = qla4xxx_initialize_adapter(ha);
++		rval = qla4xxx_initialize_adapter(ha, RESET_ADAPTER);
+ 		qla4_8xxx_idc_lock(ha);
+ 
+ 		if (rval != QLA_SUCCESS) {
+@@ -4151,7 +5124,7 @@ static uint32_t qla4_8xxx_error_recovery(struct scsi_qla_host *ha)
+ 		if ((qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE) ==
+ 		    QLA82XX_DEV_READY)) {
+ 			clear_bit(AF_FW_RECOVERY, &ha->flags);
+-			rval = qla4xxx_initialize_adapter(ha);
++			rval = qla4xxx_initialize_adapter(ha, RESET_ADAPTER);
+ 			if (rval == QLA_SUCCESS) {
+ 				ret = qla4xxx_request_irqs(ha);
+ 				if (ret) {
+diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h
+index c15347d3f532..5254e57968f5 100644
+--- a/drivers/scsi/qla4xxx/ql4_version.h
++++ b/drivers/scsi/qla4xxx/ql4_version.h
+@@ -5,4 +5,4 @@
+  * See LICENSE.qla4xxx for copyright and licensing details.
+  */
+ 
+-#define QLA4XXX_DRIVER_VERSION	"5.02.00-k8"
++#define QLA4XXX_DRIVER_VERSION	"5.02.00-k9"

commit 590134fa78fbdbe5fea78c7ae0b2c3364bc9572f
+Author: Mike Christie 
+Date:   Mon Oct 17 22:42:13 2011 -0500
+
+    [SCSI] qla4xxx: export address/port of connection (fix udev disk names)
+    
+    Udev uses the connection's persistent address/port in the
+    /dev/disk/by-path name. qla4xxx is not exporting this value
+    so its iscsi disk names have been lacking the iscsi info.
+    In the old driver we did not have this information but
+    we do now and can fix this by just setting the flags to tell
+    libiscsi/scsi_transport_iscsi to export this info in sysfs.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index ba6a8f3ee6fa..30f31b127f33 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -203,6 +203,8 @@ static mode_t ql4_attr_is_visible(int param_type, int param)
+ 		}
+ 	case ISCSI_PARAM:
+ 		switch (param) {
++		case ISCSI_PARAM_PERSISTENT_ADDRESS:
++		case ISCSI_PARAM_PERSISTENT_PORT:
+ 		case ISCSI_PARAM_CONN_ADDRESS:
+ 		case ISCSI_PARAM_CONN_PORT:
+ 		case ISCSI_PARAM_TARGET_NAME:

commit 2d63673b4d469cf2ddba309a916090b54e31cc35
+Author: Mike Christie 
+Date:   Tue Oct 11 17:55:11 2011 -0500
+
+    [SCSI] iscsi class: fix vlan configuration
+    
+    Userspace was sending the priority/id part of the vlan tag
+    and sysfs was displaying the id in the vlan file. This
+    renames the vlan sysfs file to vlan_id to reflect that it
+    was showing the id and to match the vlan_priority file.
+    This also adds a ISCSI_NET_PARAM_VLAN_TAG iscsi nl command
+    to relfect that we are sending down the vlan/priority
+    part of the tag.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index ce20dab75369..ba6a8f3ee6fa 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -718,7 +718,7 @@ static void qla4xxx_set_ipv6(struct scsi_qla_host *ha,
+ 			qla4xxx_destroy_ipv6_iface(ha);
+ 		}
+ 		break;
+-	case ISCSI_NET_PARAM_VLAN_ID:
++	case ISCSI_NET_PARAM_VLAN_TAG:
+ 		if (iface_param->len != sizeof(init_fw_cb->ipv6_vlan_tag))
+ 			break;
+ 		init_fw_cb->ipv6_vlan_tag =
+@@ -790,7 +790,7 @@ static void qla4xxx_set_ipv4(struct scsi_qla_host *ha,
+ 			qla4xxx_destroy_ipv4_iface(ha);
+ 		}
+ 		break;
+-	case ISCSI_NET_PARAM_VLAN_ID:
++	case ISCSI_NET_PARAM_VLAN_TAG:
+ 		if (iface_param->len != sizeof(init_fw_cb->ipv4_vlan_tag))
+ 			break;
+ 		init_fw_cb->ipv4_vlan_tag =
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 142a09a3afbf..1bcd65a509e6 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -322,7 +322,7 @@ iscsi_iface_net_attr(ipv6_iface, link_local_autocfg,
+ 
+ /* common read only iface attribute */
+ iscsi_iface_net_attr(iface, enabled, ISCSI_NET_PARAM_IFACE_ENABLE);
+-iscsi_iface_net_attr(iface, vlan, ISCSI_NET_PARAM_VLAN_ID);
++iscsi_iface_net_attr(iface, vlan_id, ISCSI_NET_PARAM_VLAN_ID);
+ iscsi_iface_net_attr(iface, vlan_priority, ISCSI_NET_PARAM_VLAN_PRIORITY);
+ iscsi_iface_net_attr(iface, vlan_enabled, ISCSI_NET_PARAM_VLAN_ENABLED);
+ iscsi_iface_net_attr(iface, mtu, ISCSI_NET_PARAM_MTU);
+@@ -338,7 +338,7 @@ static mode_t iscsi_iface_attr_is_visible(struct kobject *kobj,
+ 
+ 	if (attr == &dev_attr_iface_enabled.attr)
+ 		param = ISCSI_NET_PARAM_IFACE_ENABLE;
+-	else if (attr == &dev_attr_iface_vlan.attr)
++	else if (attr == &dev_attr_iface_vlan_id.attr)
+ 		param = ISCSI_NET_PARAM_VLAN_ID;
+ 	else if (attr == &dev_attr_iface_vlan_priority.attr)
+ 		param = ISCSI_NET_PARAM_VLAN_PRIORITY;
+@@ -382,7 +382,7 @@ static mode_t iscsi_iface_attr_is_visible(struct kobject *kobj,
+ 
+ static struct attribute *iscsi_iface_attrs[] = {
+ 	&dev_attr_iface_enabled.attr,
+-	&dev_attr_iface_vlan.attr,
++	&dev_attr_iface_vlan_id.attr,
+ 	&dev_attr_iface_vlan_priority.attr,
+ 	&dev_attr_iface_vlan_enabled.attr,
+ 	&dev_attr_ipv4_iface_ipaddress.attr,
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index 706a1bb1c59b..2703e3bedbf5 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -311,10 +311,11 @@ enum iscsi_net_param {
+ 	ISCSI_NET_PARAM_VLAN_ID			= 13,
+ 	ISCSI_NET_PARAM_VLAN_PRIORITY		= 14,
+ 	ISCSI_NET_PARAM_VLAN_ENABLED		= 15,
+-	ISCSI_NET_PARAM_IFACE_TYPE		= 16,
+-	ISCSI_NET_PARAM_IFACE_NAME		= 17,
+-	ISCSI_NET_PARAM_MTU			= 18,
+-	ISCSI_NET_PARAM_PORT			= 19,
++	ISCSI_NET_PARAM_VLAN_TAG		= 16,
++	ISCSI_NET_PARAM_IFACE_TYPE		= 17,
++	ISCSI_NET_PARAM_IFACE_NAME		= 18,
++	ISCSI_NET_PARAM_MTU			= 19,
++	ISCSI_NET_PARAM_PORT			= 20,
+ };
+ 
+ enum iscsi_conn_state {

commit 00c31889f7513e9ffa6b2b4de8ad6d7f59a61c80
+Author: Mike Christie 
+Date:   Thu Oct 6 03:56:59 2011 -0500
+
+    [SCSI] qla4xxx: fix data alignment and use nl helpers
+    
+    This has the driver use helpers for a common operation and fixes
+    a issue where if multiple iscsi params are sent they could be
+    sent at offsets that cause unaligned accesses. The nla helpers
+    account for the padding needed to align properly for the driver.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index d39205c816d8..ce20dab75369 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -78,8 +78,8 @@ static int qla4xxx_conn_get_param(struct iscsi_cls_conn *conn,
+ 				  enum iscsi_param param, char *buf);
+ static int qla4xxx_host_get_param(struct Scsi_Host *shost,
+ 				  enum iscsi_host_param param, char *buf);
+-static int qla4xxx_iface_set_param(struct Scsi_Host *shost, char *data,
+-				   int count);
++static int qla4xxx_iface_set_param(struct Scsi_Host *shost, void *data,
++				   uint32_t len);
+ static int qla4xxx_get_iface_param(struct iscsi_iface *iface,
+ 				   enum iscsi_param_type param_type,
+ 				   int param, char *buf);
+@@ -842,7 +842,7 @@ qla4xxx_initcb_to_acb(struct addr_ctrl_blk *init_fw_cb)
+ }
+ 
+ static int
+-qla4xxx_iface_set_param(struct Scsi_Host *shost, char *data, int count)
++qla4xxx_iface_set_param(struct Scsi_Host *shost, void *data, uint32_t len)
+ {
+ 	struct scsi_qla_host *ha = to_qla_host(shost);
+ 	int rval = 0;
+@@ -851,8 +851,8 @@ qla4xxx_iface_set_param(struct Scsi_Host *shost, char *data, int count)
+ 	dma_addr_t init_fw_cb_dma;
+ 	uint32_t mbox_cmd[MBOX_REG_COUNT];
+ 	uint32_t mbox_sts[MBOX_REG_COUNT];
+-	uint32_t total_param_count;
+-	uint32_t length;
++	uint32_t rem = len;
++	struct nlattr *attr;
+ 
+ 	init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
+ 					sizeof(struct addr_ctrl_blk),
+@@ -873,11 +873,8 @@ qla4xxx_iface_set_param(struct Scsi_Host *shost, char *data, int count)
+ 		goto exit_init_fw_cb;
+ 	}
+ 
+-	total_param_count = count;
+-	iface_param = (struct iscsi_iface_param_info *)data;
+-
+-	for ( ; total_param_count != 0; total_param_count--) {
+-		length = iface_param->len;
++	nla_for_each_attr(attr, data, len, rem) {
++		iface_param = nla_data(attr);
+ 
+ 		if (iface_param->param_type != ISCSI_NET_PARAM)
+ 			continue;
+@@ -914,10 +911,6 @@ qla4xxx_iface_set_param(struct Scsi_Host *shost, char *data, int count)
+ 			ql4_printk(KERN_ERR, ha, "Invalid iface type\n");
+ 			break;
+ 		}
+-
+-		iface_param = (struct iscsi_iface_param_info *)
+-						((uint8_t *)iface_param +
+-			    sizeof(struct iscsi_iface_param_info) + length);
+ 	}
+ 
+ 	init_fw_cb->cookie = cpu_to_le32(0x11BEAD5A);
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 522423bdcb56..142a09a3afbf 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -1890,7 +1890,7 @@ iscsi_set_path(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+ 
+ static int
+ iscsi_set_iface_params(struct iscsi_transport *transport,
+-		       struct iscsi_uevent *ev)
++		       struct iscsi_uevent *ev, uint32_t len)
+ {
+ 	char *data = (char *)ev + sizeof(*ev);
+ 	struct Scsi_Host *shost;
+@@ -1906,8 +1906,7 @@ iscsi_set_iface_params(struct iscsi_transport *transport,
+ 		return -ENODEV;
+ 	}
+ 
+-	err = transport->set_iface_param(shost, data,
+-					 ev->u.set_iface_params.count);
++	err = transport->set_iface_param(shost, data, len);
+ 	scsi_host_put(shost);
+ 	return err;
+ }
+@@ -2052,7 +2051,8 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
+ 		err = iscsi_set_path(transport, ev);
+ 		break;
+ 	case ISCSI_UEVENT_SET_IFACE_PARAMS:
+-		err = iscsi_set_iface_params(transport, ev);
++		err = iscsi_set_iface_params(transport, ev,
++					     nlmsg_attrlen(nlh, sizeof(*ev)));
+ 		break;
+ 	default:
+ 		err = -ENOSYS;
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index a498ccecf6b1..5994bcc1b017 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -137,7 +137,8 @@ struct iscsi_transport {
+ 	int (*tgt_dscvr) (struct Scsi_Host *shost, enum iscsi_tgt_dscvr type,
+ 			  uint32_t enable, struct sockaddr *dst_addr);
+ 	int (*set_path) (struct Scsi_Host *shost, struct iscsi_path *params);
+-	int (*set_iface_param) (struct Scsi_Host *shost, char *data, int count);
++	int (*set_iface_param) (struct Scsi_Host *shost, void *data,
++				uint32_t len);
+ 	int (*get_iface_param) (struct iscsi_iface *iface,
+ 				enum iscsi_param_type param_type,
+ 				int param, char *buf);

commit 88f4f5170fe74ae28443f304fcd226ddcf84f592
+Author: Mike Christie 
+Date:   Thu Oct 6 03:56:58 2011 -0500
+
+    [SCSI] iscsi class: fix link local mispelling
+    
+    Use the same format for link local variables. Instead
+    of linklocal do link_local.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index d746c351588f..522423bdcb56 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -317,7 +317,7 @@ iscsi_iface_net_attr(ipv6_iface, link_local_addr, ISCSI_NET_PARAM_IPV6_LINKLOCAL
+ iscsi_iface_net_attr(ipv6_iface, router_addr, ISCSI_NET_PARAM_IPV6_ROUTER);
+ iscsi_iface_net_attr(ipv6_iface, ipaddr_autocfg,
+ 		     ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG);
+-iscsi_iface_net_attr(ipv6_iface, linklocal_autocfg,
++iscsi_iface_net_attr(ipv6_iface, link_local_autocfg,
+ 		     ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG);
+ 
+ /* common read only iface attribute */
+@@ -368,7 +368,7 @@ static mode_t iscsi_iface_attr_is_visible(struct kobject *kobj,
+ 			param = ISCSI_NET_PARAM_IPV6_ROUTER;
+ 		else if (attr == &dev_attr_ipv6_iface_ipaddr_autocfg.attr)
+ 			param = ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG;
+-		else if (attr == &dev_attr_ipv6_iface_linklocal_autocfg.attr)
++		else if (attr == &dev_attr_ipv6_iface_link_local_autocfg.attr)
+ 			param = ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG;
+ 		else
+ 			return 0;
+@@ -393,7 +393,7 @@ static struct attribute *iscsi_iface_attrs[] = {
+ 	&dev_attr_ipv6_iface_link_local_addr.attr,
+ 	&dev_attr_ipv6_iface_router_addr.attr,
+ 	&dev_attr_ipv6_iface_ipaddr_autocfg.attr,
+-	&dev_attr_ipv6_iface_linklocal_autocfg.attr,
++	&dev_attr_ipv6_iface_link_local_autocfg.attr,
+ 	&dev_attr_iface_mtu.attr,
+ 	&dev_attr_iface_port.attr,
+ 	NULL,

commit 8d4a690cd4f574bcb70c2cb89c227ba89a51351f
+Author: Mike Christie 
+Date:   Thu Oct 6 03:56:57 2011 -0500
+
+    [SCSI] iscsi class: Replace iscsi_get_next_target_id with IDA
+    
+     Replaced the iscsi_get_next_target_id with IDA to make
+     target-id allocation efficient for iscsi offload drivers
+    
+     This patch should be applied after Jonathen Cameron Patch
+     "ida : simplified functions for id allocation"
+    
+    Signed-off-by: John Soni Jose 
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index c58f6766f4c7..d746c351588f 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -24,6 +24,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -81,6 +82,7 @@ struct iscsi_internal {
+ static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
+ static struct workqueue_struct *iscsi_eh_timer_workq;
+ 
++static DEFINE_IDA(iscsi_sess_ida);
+ /*
+  * list of registered transports and lock that must
+  * be held while accessing list. The iscsi_transport_lock must
+@@ -990,6 +992,7 @@ static void __iscsi_unbind_session(struct work_struct *work)
+ 	struct Scsi_Host *shost = iscsi_session_to_shost(session);
+ 	struct iscsi_cls_host *ihost = shost->shost_data;
+ 	unsigned long flags;
++	unsigned int target_id;
+ 
+ 	ISCSI_DBG_TRANS_SESSION(session, "Unbinding session\n");
+ 
+@@ -1001,10 +1004,15 @@ static void __iscsi_unbind_session(struct work_struct *work)
+ 		mutex_unlock(&ihost->mutex);
+ 		return;
+ 	}
++
++	target_id = session->target_id;
+ 	session->target_id = ISCSI_MAX_TARGET;
+ 	spin_unlock_irqrestore(&session->lock, flags);
+ 	mutex_unlock(&ihost->mutex);
+ 
++	if (session->ida_used)
++		ida_simple_remove(&iscsi_sess_ida, target_id);
++
+ 	scsi_remove_target(&session->dev);
+ 	iscsi_session_event(session, ISCSI_KEVENT_UNBIND_SESSION);
+ 	ISCSI_DBG_TRANS_SESSION(session, "Completed target removal\n");
+@@ -1045,59 +1053,36 @@ iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
+ }
+ EXPORT_SYMBOL_GPL(iscsi_alloc_session);
+ 
+-static int iscsi_get_next_target_id(struct device *dev, void *data)
+-{
+-	struct iscsi_cls_session *session;
+-	unsigned long flags;
+-	int err = 0;
+-
+-	if (!iscsi_is_session_dev(dev))
+-		return 0;
+-
+-	session = iscsi_dev_to_session(dev);
+-	spin_lock_irqsave(&session->lock, flags);
+-	if (*((unsigned int *) data) == session->target_id)
+-		err = -EEXIST;
+-	spin_unlock_irqrestore(&session->lock, flags);
+-	return err;
+-}
+-
+ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
+ {
+ 	struct Scsi_Host *shost = iscsi_session_to_shost(session);
+ 	struct iscsi_cls_host *ihost;
+ 	unsigned long flags;
+-	unsigned int id = target_id;
++	int id = 0;
+ 	int err;
+ 
+ 	ihost = shost->shost_data;
+ 	session->sid = atomic_add_return(1, &iscsi_session_nr);
+ 
+-	if (id == ISCSI_MAX_TARGET) {
+-		for (id = 0; id < ISCSI_MAX_TARGET; id++) {
+-			err = device_for_each_child(&shost->shost_gendev, &id,
+-						    iscsi_get_next_target_id);
+-			if (!err)
+-				break;
+-		}
++	if (target_id == ISCSI_MAX_TARGET) {
++		id = ida_simple_get(&iscsi_sess_ida, 0, 0, GFP_KERNEL);
+ 
+-		if (id == ISCSI_MAX_TARGET) {
++		if (id < 0) {
+ 			iscsi_cls_session_printk(KERN_ERR, session,
+-						 "Too many iscsi targets. Max "
+-						 "number of targets is %d.\n",
+-						 ISCSI_MAX_TARGET - 1);
+-			err = -EOVERFLOW;
+-			goto release_host;
++					"Failure in Target ID Allocation\n");
++			return id;
+ 		}
+-	}
+-	session->target_id = id;
++		session->target_id = (unsigned int)id;
++		session->ida_used = true;
++	} else
++		session->target_id = target_id;
+ 
+ 	dev_set_name(&session->dev, "session%u", session->sid);
+ 	err = device_add(&session->dev);
+ 	if (err) {
+ 		iscsi_cls_session_printk(KERN_ERR, session,
+ 					 "could not register session's dev\n");
+-		goto release_host;
++		goto release_ida;
+ 	}
+ 	transport_register_device(&session->dev);
+ 
+@@ -1109,8 +1094,10 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
+ 	ISCSI_DBG_TRANS_SESSION(session, "Completed session adding\n");
+ 	return 0;
+ 
+-release_host:
+-	scsi_host_put(shost);
++release_ida:
++	if (session->ida_used)
++		ida_simple_remove(&iscsi_sess_ida, session->target_id);
++
+ 	return err;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_add_session);
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 3389cd5ea94c..a498ccecf6b1 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -208,6 +208,7 @@ struct iscsi_cls_session {
+ 	struct delayed_work recovery_work;
+ 
+ 	unsigned int target_id;
++	bool ida_used;
+ 
+ 	int state;
+ 	int sid;				/* session id */

commit 9c224ac21506d29f5a6ff4df0c4cc9f97484fa25
+Author: Mike Christie 
+Date:   Wed Aug 31 21:53:40 2011 -0500
+
+    [SCSI] qla4xxx: select iscsi boot sysfs attrs
+    
+    qla4xxx now uses iscsi_boot_sysfs to export the targets used
+    for boot to sysfs. It needs to select that config option
+    to make sure that module is also built.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/Kconfig b/drivers/scsi/qla4xxx/Kconfig
+index 2c33ce6eac1e..5b1aed4f0754 100644
+--- a/drivers/scsi/qla4xxx/Kconfig
++++ b/drivers/scsi/qla4xxx/Kconfig
+@@ -2,6 +2,7 @@ config SCSI_QLA_ISCSI
+ 	tristate "QLogic ISP4XXX and ISP82XX host adapter family support"
+ 	depends on PCI && SCSI
+ 	select SCSI_ISCSI_ATTRS
++	select ISCSI_BOOT_SYSFS
+ 	---help---
+ 	This driver supports the QLogic 40xx (ISP4XXX) and 8022 (ISP82XX)
+ 	iSCSI host adapter family.

commit 76e4e12ff2b3ef86773989fd897b194eb38016e6
+Author: Mike Christie 
+Date:   Thu Aug 25 00:36:38 2011 -0500
+
+    [SCSI] scsi scan: don't fail scans when host is in recovery
+    
+    The problem is that if we are doing a scsi scan then the device goes
+    into recovery then we will wait for the recovery to complete. It waits
+    because scsi-ml will send inquiries or report luns and the queueing code
+    will have been blocked due to the host not being ready. However, if we
+    are in recovery and then a scan is started the scan will silently fail
+    and some devices will not be added.
+    
+    It is easy to hit the problem where devices do not show up with
+    FC where we are doing tests that disrupt the target controllers.
+    When the controller is disruprted (reboot, or setting firmware, etc),
+    and we cause the dev loss tmo to fire then devices will be removed
+    Then when the problem has been fixed, the rport will be scanned and
+    devices should be added back. But if we cause another disruption before
+    scanning has started then devices will not get added back. If the problem
+    is not started until the scan is started then the devices will be added
+    back.
+    
+    This patch fixes that problem by not failing scans when the host
+    is in recovery. We will let scsi-ml send the IO and let the queueing
+    and scsi error handling deal with it like is done if we went into
+    recovery while scanning.
+    
+    For recovery cases where the host is being torn down then with the
+    patch we will still fail the scan since there is not point in scanning.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
+index fc22ad9dba77..50266c9405fc 100644
+--- a/include/scsi/scsi_host.h
++++ b/include/scsi/scsi_host.h
+@@ -804,7 +804,8 @@ static inline struct device *scsi_get_device(struct Scsi_Host *shost)
+  **/
+ static inline int scsi_host_scan_allowed(struct Scsi_Host *shost)
+ {
+-	return shost->shost_state == SHOST_RUNNING;
++	return shost->shost_state == SHOST_RUNNING ||
++	       shost->shost_state == SHOST_RECOVERY;
+ }
+ 
+ extern void scsi_unblock_requests(struct Scsi_Host *);

commit de37920b87a78e5e4a5e40e65548f1bf1cfb2f5c
+Author: Mike Christie 
+Date:   Sun Aug 14 20:42:56 2011 -0500
+
+    [SCSI] qla4xxx: export iface name
+    
+    Export the name of iface session is attached to. This is needed
+    so tools like iscsiadm/iscsistart can match the sessions to
+    userspace ifaces when rebuilding iscsid's state during boot.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index 456cd6f23f0f..ce391d5511e3 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -213,6 +213,7 @@ static mode_t ql4_attr_is_visible(int param_type, int param)
+ 		case ISCSI_PARAM_FIRST_BURST:
+ 		case ISCSI_PARAM_MAX_RECV_DLENGTH:
+ 		case ISCSI_PARAM_MAX_XMIT_DLENGTH:
++		case ISCSI_PARAM_IFACE_NAME:
+ 			return S_IRUGO;
+ 		default:
+ 			return 0;

commit 90eeb01a038e5fec0efdea4df008f3c18f67b82c
+Author: Mike Christie 
+Date:   Mon Jul 25 13:48:50 2011 -0500
+
+    [SCSI] iscsi class: add bsg support to iscsi class
+    
+    This patch adds bsg support to the iscsi class. There is only
+    1 request, the host vendor one, supported. It is expected that
+    this would be used for things like flash updates.
+    
+    This patch is made over this one
+    http://marc.info/?l=linux-scsi&m=131149780020992&w=2
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
+index 8d9dae89f065..4a79b9d86156 100644
+--- a/drivers/scsi/Kconfig
++++ b/drivers/scsi/Kconfig
+@@ -309,6 +309,7 @@ config SCSI_FC_TGT_ATTRS
+ config SCSI_ISCSI_ATTRS
+ 	tristate "iSCSI Transport Attributes"
+ 	depends on SCSI && NET
++	select BLK_DEV_BSGLIB
+ 	help
+ 	  If you wish to export transport-specific information about
+ 	  each attached iSCSI device to sysfs, say Y.
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 13f90515ff6e..cde679f1b01d 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -23,6 +23,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -31,6 +32,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #define ISCSI_TRANSPORT_VERSION "2.0-870"
+ 
+@@ -447,6 +449,99 @@ void iscsi_destroy_iface(struct iscsi_iface *iface)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_destroy_iface);
+ 
++/*
++ * BSG support
++ */
++/**
++ * iscsi_bsg_host_dispatch - Dispatch command to LLD.
++ * @job: bsg job to be processed
++ */
++static int iscsi_bsg_host_dispatch(struct bsg_job *job)
++{
++	struct Scsi_Host *shost = iscsi_job_to_shost(job);
++	struct iscsi_bsg_request *req = job->request;
++	struct iscsi_bsg_reply *reply = job->reply;
++	struct iscsi_internal *i = to_iscsi_internal(shost->transportt);
++	int cmdlen = sizeof(uint32_t);	/* start with length of msgcode */
++	int ret;
++
++	/* check if we have the msgcode value at least */
++	if (job->request_len < sizeof(uint32_t)) {
++		ret = -ENOMSG;
++		goto fail_host_msg;
++	}
++
++	/* Validate the host command */
++	switch (req->msgcode) {
++	case ISCSI_BSG_HST_VENDOR:
++		cmdlen += sizeof(struct iscsi_bsg_host_vendor);
++		if ((shost->hostt->vendor_id == 0L) ||
++		    (req->rqst_data.h_vendor.vendor_id !=
++			shost->hostt->vendor_id)) {
++			ret = -ESRCH;
++			goto fail_host_msg;
++		}
++		break;
++	default:
++		ret = -EBADR;
++		goto fail_host_msg;
++	}
++
++	/* check if we really have all the request data needed */
++	if (job->request_len < cmdlen) {
++		ret = -ENOMSG;
++		goto fail_host_msg;
++	}
++
++	ret = i->iscsi_transport->bsg_request(job);
++	if (!ret)
++		return 0;
++
++fail_host_msg:
++	/* return the errno failure code as the only status */
++	BUG_ON(job->reply_len < sizeof(uint32_t));
++	reply->reply_payload_rcv_len = 0;
++	reply->result = ret;
++	job->reply_len = sizeof(uint32_t);
++	bsg_job_done(job, ret, 0);
++	return 0;
++}
++
++/**
++ * iscsi_bsg_host_add - Create and add the bsg hooks to receive requests
++ * @shost: shost for iscsi_host
++ * @cls_host: iscsi_cls_host adding the structures to
++ */
++static int
++iscsi_bsg_host_add(struct Scsi_Host *shost, struct iscsi_cls_host *ihost)
++{
++	struct device *dev = &shost->shost_gendev;
++	struct iscsi_internal *i = to_iscsi_internal(shost->transportt);
++	struct request_queue *q;
++	char bsg_name[20];
++	int ret;
++
++	if (!i->iscsi_transport->bsg_request)
++		return -ENOTSUPP;
++
++	snprintf(bsg_name, sizeof(bsg_name), "iscsi_host%d", shost->host_no);
++
++	q = __scsi_alloc_queue(shost, bsg_request_fn);
++	if (!q)
++		return -ENOMEM;
++
++	ret = bsg_setup_queue(dev, q, bsg_name, iscsi_bsg_host_dispatch, 0);
++	if (ret) {
++		shost_printk(KERN_ERR, shost, "bsg interface failed to "
++			     "initialize - no request queue\n");
++		blk_cleanup_queue(q);
++		return ret;
++	}
++
++	ihost->bsg_q = q;
++	return 0;
++}
++
+ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+ 			    struct device *cdev)
+ {
+@@ -456,13 +551,30 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+ 	memset(ihost, 0, sizeof(*ihost));
+ 	atomic_set(&ihost->nr_scans, 0);
+ 	mutex_init(&ihost->mutex);
++
++	iscsi_bsg_host_add(shost, ihost);
++	/* ignore any bsg add error - we just can't do sgio */
++
++	return 0;
++}
++
++static int iscsi_remove_host(struct transport_container *tc,
++			     struct device *dev, struct device *cdev)
++{
++	struct Scsi_Host *shost = dev_to_shost(dev);
++	struct iscsi_cls_host *ihost = shost->shost_data;
++
++	if (ihost->bsg_q) {
++		bsg_remove_queue(ihost->bsg_q);
++		blk_cleanup_queue(ihost->bsg_q);
++	}
+ 	return 0;
+ }
+ 
+ static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
+ 			       "iscsi_host",
+ 			       iscsi_setup_host,
+-			       NULL,
++			       iscsi_remove_host,
+ 			       NULL);
+ 
+ static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
+diff --git a/include/scsi/scsi_bsg_iscsi.h b/include/scsi/scsi_bsg_iscsi.h
+new file mode 100644
+index 000000000000..fd5689d4c052
+--- /dev/null
++++ b/include/scsi/scsi_bsg_iscsi.h
+@@ -0,0 +1,110 @@
++/*
++ *  iSCSI Transport BSG Interface
++ *
++ *  Copyright (C) 2009   James Smart, Emulex Corporation
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *
++ */
++
++#ifndef SCSI_BSG_ISCSI_H
++#define SCSI_BSG_ISCSI_H
++
++/*
++ * This file intended to be included by both kernel and user space
++ */
++
++#include 
++
++/*
++ * iSCSI Transport SGIO v4 BSG Message Support
++ */
++
++/* Default BSG request timeout (in seconds) */
++#define ISCSI_DEFAULT_BSG_TIMEOUT      (10 * HZ)
++
++
++/*
++ * Request Message Codes supported by the iSCSI Transport
++ */
++
++/* define the class masks for the message codes */
++#define ISCSI_BSG_CLS_MASK     0xF0000000      /* find object class */
++#define ISCSI_BSG_HST_MASK     0x80000000      /* iscsi host class */
++
++/* iscsi host Message Codes */
++#define ISCSI_BSG_HST_VENDOR           (ISCSI_BSG_HST_MASK | 0x000000FF)
++
++
++/*
++ * iSCSI Host Messages
++ */
++
++/* ISCSI_BSG_HST_VENDOR : */
++
++/* Request:
++ * Note: When specifying vendor_id, be sure to read the Vendor Type and ID
++ *   formatting requirements specified in scsi_netlink.h
++ */
++struct iscsi_bsg_host_vendor {
++	/*
++	 * Identifies the vendor that the message is formatted for. This
++	 * should be the recipient of the message.
++	 */
++	uint64_t vendor_id;
++
++	/* start of vendor command area */
++	uint32_t vendor_cmd[0];
++};
++
++/* Response:
++ */
++struct iscsi_bsg_host_vendor_reply {
++	/* start of vendor response area */
++	uint32_t vendor_rsp[0];
++};
++
++
++/* request (CDB) structure of the sg_io_v4 */
++struct iscsi_bsg_request {
++	uint32_t msgcode;
++	union {
++		struct iscsi_bsg_host_vendor    h_vendor;
++	} rqst_data;
++} __attribute__((packed));
++
++
++/* response (request sense data) structure of the sg_io_v4 */
++struct iscsi_bsg_reply {
++	/*
++	 * The completion result. Result exists in two forms:
++	 * if negative, it is an -Exxx system errno value. There will
++	 * be no further reply information supplied.
++	 * else, it's the 4-byte scsi error result, with driver, host,
++	 * msg and status fields. The per-msgcode reply structure
++	 * will contain valid data.
++	 */
++	uint32_t result;
++
++	/* If there was reply_payload, how much was recevied ? */
++	uint32_t reply_payload_rcv_len;
++
++	union {
++		struct iscsi_bsg_host_vendor_reply      vendor_reply;
++	} reply_data;
++};
++
++
++#endif /* SCSI_BSG_ISCSI_H */
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 77e6dd60fb4b..4a3edeeae8f6 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -38,6 +38,7 @@ struct iscsi_conn;
+ struct iscsi_task;
+ struct sockaddr;
+ struct iscsi_iface;
++struct bsg_job;
+ 
+ /**
+  * struct iscsi_transport - iSCSI Transport template
+@@ -141,9 +142,9 @@ struct iscsi_transport {
+ 				enum iscsi_param_type param_type,
+ 				int param, char *buf);
+ 	mode_t (*attr_is_visible)(int param_type, int param);
++	int (*bsg_request)(struct bsg_job *job);
+ };
+ 
+-
+ /*
+  * transport registration upcalls
+  */
+@@ -227,8 +228,12 @@ struct iscsi_cls_session {
+ struct iscsi_cls_host {
+ 	atomic_t nr_scans;
+ 	struct mutex mutex;
++	struct request_queue *bsg_q;
+ };
+ 
++#define iscsi_job_to_shost(_job) \
++        dev_to_shost(_job->dev)
++
+ extern void iscsi_host_for_each_session(struct Scsi_Host *shost,
+ 				void (*fn)(struct iscsi_cls_session *));
+ 

commit 5431ae267ab20464cea3e1c1d1bc34d259f3973c
+Author: Mike Christie 
+Date:   Mon Jul 25 13:48:48 2011 -0500
+
+    [SCSI] libiscsi: don't bugon when if user sets markers
+    
+    libiscsi does not support markers and if someone tries
+    to set them the driver does a BUG(). There is not need
+    to be that extreme. Just return -ENOSYS.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 256a999d010b..d7c76f2eb636 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -3163,7 +3163,6 @@ int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
+ {
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	struct iscsi_session *session = conn->session;
+-	uint32_t value;
+ 
+ 	switch(param) {
+ 	case ISCSI_PARAM_FAST_ABORT:
+@@ -3220,14 +3219,6 @@ int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
+ 	case ISCSI_PARAM_ERL:
+ 		sscanf(buf, "%d", &session->erl);
+ 		break;
+-	case ISCSI_PARAM_IFMARKER_EN:
+-		sscanf(buf, "%d", &value);
+-		BUG_ON(value);
+-		break;
+-	case ISCSI_PARAM_OFMARKER_EN:
+-		sscanf(buf, "%d", &value);
+-		BUG_ON(value);
+-		break;
+ 	case ISCSI_PARAM_EXP_STATSN:
+ 		sscanf(buf, "%u", &conn->exp_statsn);
+ 		break;

commit 4223b9e919761ba1405a8505bda0b4efa17e8f0e
+Author: Mike Christie 
+Date:   Mon Jul 25 13:48:47 2011 -0500
+
+    [SCSI] iscsi class: expand vlan support
+    
+    Add support to set vlan priority and enable/disble a vlan.
+    
+    Patch based on code from Vikas Chaudhary.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 2e9b68215593..13f90515ff6e 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -319,6 +319,8 @@ iscsi_iface_net_attr(ipv6_iface, linklocal_autocfg,
+ /* common read only iface attribute */
+ iscsi_iface_net_attr(iface, enabled, ISCSI_NET_PARAM_IFACE_ENABLE);
+ iscsi_iface_net_attr(iface, vlan, ISCSI_NET_PARAM_VLAN_ID);
++iscsi_iface_net_attr(iface, vlan_priority, ISCSI_NET_PARAM_VLAN_PRIORITY);
++iscsi_iface_net_attr(iface, vlan_enabled, ISCSI_NET_PARAM_VLAN_ENABLED);
+ 
+ static mode_t iscsi_iface_attr_is_visible(struct kobject *kobj,
+ 					  struct attribute *attr, int i)
+@@ -332,6 +334,10 @@ static mode_t iscsi_iface_attr_is_visible(struct kobject *kobj,
+ 		param = ISCSI_NET_PARAM_IFACE_ENABLE;
+ 	else if (attr == &dev_attr_iface_vlan.attr)
+ 		param = ISCSI_NET_PARAM_VLAN_ID;
++	else if (attr == &dev_attr_iface_vlan_priority.attr)
++		param = ISCSI_NET_PARAM_VLAN_PRIORITY;
++	else if (attr == &dev_attr_iface_vlan_enabled.attr)
++		param = ISCSI_NET_PARAM_VLAN_ENABLED;
+ 	else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) {
+ 		if (attr == &dev_attr_ipv4_iface_ipaddress.attr)
+ 			param = ISCSI_NET_PARAM_IPV4_ADDR;
+@@ -367,6 +373,8 @@ static mode_t iscsi_iface_attr_is_visible(struct kobject *kobj,
+ static struct attribute *iscsi_iface_attrs[] = {
+ 	&dev_attr_iface_enabled.attr,
+ 	&dev_attr_iface_vlan.attr,
++	&dev_attr_iface_vlan_priority.attr,
++	&dev_attr_iface_vlan_enabled.attr,
+ 	&dev_attr_ipv4_iface_ipaddress.attr,
+ 	&dev_attr_ipv4_iface_gateway.attr,
+ 	&dev_attr_ipv4_iface_subnet.attr,
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index 3753f7e36386..d3f256a232f8 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -281,6 +281,13 @@ struct iscsi_path {
+ #define ISCSI_IFACE_TYPE_IPV4		0x01
+ #define ISCSI_IFACE_TYPE_IPV6		0x02
+ 
++#define ISCSI_MAX_VLAN_ID		4095
++#define ISCSI_MAX_VLAN_PRIORITY		7
++
++/* iscsi vlan enable/disabled setting */
++#define ISCSI_VLAN_DISABLE	0x01
++#define ISCSI_VLAN_ENABLE	0x02
++
+ /* iSCSI network params */
+ enum iscsi_net_param {
+ 	ISCSI_NET_PARAM_IPV4_ADDR		= 1,
+@@ -296,8 +303,10 @@ enum iscsi_net_param {
+ 	ISCSI_NET_PARAM_IPV6_ROUTER_AUTOCFG	= 11,
+ 	ISCSI_NET_PARAM_IFACE_ENABLE		= 12,
+ 	ISCSI_NET_PARAM_VLAN_ID			= 13,
+-	ISCSI_NET_PARAM_IFACE_TYPE		= 14,
+-	ISCSI_NET_PARAM_IFACE_NAME		= 15,
++	ISCSI_NET_PARAM_VLAN_PRIORITY		= 14,
++	ISCSI_NET_PARAM_VLAN_ENABLED		= 15,
++	ISCSI_NET_PARAM_IFACE_TYPE		= 16,
++	ISCSI_NET_PARAM_IFACE_NAME		= 17,
+ };
+ 
+ /*

commit 3093b0484d77ea774d74dfd7f5419831a716a9aa
+Author: Mike Christie 
+Date:   Mon Jul 25 13:48:46 2011 -0500
+
+    [SCSI] be2iscsi: remove host and session casts
+    
+    iscsi_session_to_shost is a macro around dev_to_shost which returns a
+    Scsi_Host so there is no need to cast.
+    
+    iscsi_session_to_shost is a macro around shost_priv which
+    returns a void pointer so no need to cast.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
+index feadaa288080..8b002f6db6ca 100644
+--- a/drivers/scsi/be2iscsi/be_iscsi.c
++++ b/drivers/scsi/be2iscsi/be_iscsi.c
+@@ -177,9 +177,8 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
+ {
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	struct beiscsi_conn *beiscsi_conn = conn->dd_data;
+-	struct Scsi_Host *shost =
+-		(struct Scsi_Host *)iscsi_session_to_shost(cls_session);
+-	struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost);
++	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
++	struct beiscsi_hba *phba = iscsi_host_priv(shost);
+ 	struct beiscsi_endpoint *beiscsi_ep;
+ 	struct iscsi_endpoint *ep;
+ 
+@@ -290,7 +289,7 @@ int beiscsi_set_param(struct iscsi_cls_conn *cls_conn,
+ int beiscsi_get_host_param(struct Scsi_Host *shost,
+ 			   enum iscsi_host_param param, char *buf)
+ {
+-	struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost);
++	struct beiscsi_hba *phba = iscsi_host_priv(shost);
+ 	int status = 0;
+ 
+ 	SE_DEBUG(DBG_LVL_8, "In beiscsi_get_host_param, param= %d\n", param);

commit f27fb2ef7bd88c9c5f67befe4d85e2155aa0e1a8
+Author: Mike Christie 
+Date:   Mon Jul 25 13:48:45 2011 -0500
+
+    [SCSI] iscsi class: sysfs group is_visible callout for iscsi host attrs
+    
+    The iscsi class currently does not support writable sysfs
+    attrs for LLD sysfs settings. This patch converts the
+    iscsi class and driver's host attrs to use the attribute
+    container sysfs group and the sysfs group's is_visible callout
+    to be able to support readable or writable sysfs attrs.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 4f2411298b20..84e8c293a715 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -635,6 +635,15 @@ iscsi_iser_ep_disconnect(struct iscsi_endpoint *ep)
+ static mode_t iser_attr_is_visible(int param_type, int param)
+ {
+ 	switch (param_type) {
++	case ISCSI_HOST_PARAM:
++		switch (param) {
++		case ISCSI_HOST_PARAM_NETDEV_NAME:
++		case ISCSI_HOST_PARAM_HWADDRESS:
++		case ISCSI_HOST_PARAM_INITIATOR_NAME:
++			return S_IRUGO;
++		default:
++			return 0;
++		}
+ 	case ISCSI_PARAM:
+ 		switch (param) {
+ 		case ISCSI_PARAM_MAX_RECV_DLENGTH:
+@@ -697,9 +706,6 @@ static struct iscsi_transport iscsi_iser_transport = {
+ 	.owner                  = THIS_MODULE,
+ 	.name                   = "iser",
+ 	.caps                   = CAP_RECOVERY_L0 | CAP_MULTI_R2T,
+-	.host_param_mask	= ISCSI_HOST_HWADDRESS |
+-				  ISCSI_HOST_NETDEV_NAME |
+-				  ISCSI_HOST_INITIATOR_NAME,
+ 	/* session management */
+ 	.create_session         = iscsi_iser_session_create,
+ 	.destroy_session        = iscsi_iser_session_destroy,
+diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
+index ecd19bb3b207..feadaa288080 100644
+--- a/drivers/scsi/be2iscsi/be_iscsi.c
++++ b/drivers/scsi/be2iscsi/be_iscsi.c
+@@ -737,6 +737,15 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
+ mode_t be2iscsi_attr_is_visible(int param_type, int param)
+ {
+ 	switch (param_type) {
++	case ISCSI_HOST_PARAM:
++		switch (param) {
++		case ISCSI_HOST_PARAM_HWADDRESS:
++		case ISCSI_HOST_PARAM_IPADDRESS:
++		case ISCSI_HOST_PARAM_INITIATOR_NAME:
++			return S_IRUGO;
++		default:
++			return 0;
++		}
+ 	case ISCSI_PARAM:
+ 		switch (param) {
+ 		case ISCSI_PARAM_MAX_RECV_DLENGTH:
+diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
+index 93a3c708411a..72ac64bbceaf 100644
+--- a/drivers/scsi/be2iscsi/be_main.c
++++ b/drivers/scsi/be2iscsi/be_main.c
+@@ -4364,8 +4364,6 @@ struct iscsi_transport beiscsi_iscsi_transport = {
+ 	.name = DRV_NAME,
+ 	.caps = CAP_RECOVERY_L0 | CAP_HDRDGST | CAP_TEXT_NEGO |
+ 		CAP_MULTI_R2T | CAP_DATADGST | CAP_DATA_PATH_OFFLOAD,
+-	.host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+-				ISCSI_HOST_INITIATOR_NAME,
+ 	.create_session = beiscsi_session_create,
+ 	.destroy_session = beiscsi_session_destroy,
+ 	.create_conn = beiscsi_conn_create,
+diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
+index 2db3399d2734..d1e697190970 100644
+--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
++++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
+@@ -2180,6 +2180,15 @@ static int bnx2i_nl_set_path(struct Scsi_Host *shost, struct iscsi_path *params)
+ static mode_t bnx2i_attr_is_visible(int param_type, int param)
+ {
+ 	switch (param_type) {
++	case ISCSI_HOST_PARAM:
++		switch (param) {
++		case ISCSI_HOST_PARAM_NETDEV_NAME:
++		case ISCSI_HOST_PARAM_HWADDRESS:
++		case ISCSI_HOST_PARAM_IPADDRESS:
++			return S_IRUGO;
++		default:
++			return 0;
++		}
+ 	case ISCSI_PARAM:
+ 		switch (param) {
+ 		case ISCSI_PARAM_MAX_RECV_DLENGTH:
+@@ -2251,8 +2260,6 @@ struct iscsi_transport bnx2i_iscsi_transport = {
+ 				  CAP_MULTI_R2T | CAP_DATADGST |
+ 				  CAP_DATA_PATH_OFFLOAD |
+ 				  CAP_TEXT_NEGO,
+-	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+-				  ISCSI_HOST_NETDEV_NAME,
+ 	.create_session		= bnx2i_session_create,
+ 	.destroy_session	= bnx2i_session_destroy,
+ 	.create_conn		= bnx2i_conn_create,
+diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
+index 50d4e3f05038..f76185b010da 100644
+--- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
++++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
+@@ -106,9 +106,6 @@ static struct iscsi_transport cxgb3i_iscsi_transport = {
+ 	.caps		= CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST
+ 				| CAP_DATADGST | CAP_DIGEST_OFFLOAD |
+ 				CAP_PADDING_OFFLOAD | CAP_TEXT_NEGO,
+-	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+-				ISCSI_HOST_INITIATOR_NAME |
+-				ISCSI_HOST_NETDEV_NAME,
+ 	.attr_is_visible	= cxgbi_attr_is_visible,
+ 	.get_host_param	= cxgbi_get_host_param,
+ 	.set_host_param	= cxgbi_set_host_param,
+diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+index 72f19ef7e016..628a6983a20b 100644
+--- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
++++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+@@ -107,9 +107,6 @@ static struct iscsi_transport cxgb4i_iscsi_transport = {
+ 	.caps		= CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST |
+ 				CAP_DATADGST | CAP_DIGEST_OFFLOAD |
+ 				CAP_PADDING_OFFLOAD | CAP_TEXT_NEGO,
+-	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+-				ISCSI_HOST_INITIATOR_NAME |
+-				ISCSI_HOST_NETDEV_NAME,
+ 	.attr_is_visible	= cxgbi_attr_is_visible,
+ 	.get_host_param	= cxgbi_get_host_param,
+ 	.set_host_param	= cxgbi_set_host_param,
+diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c
+index f9c2ca0d8083..67ded44557e1 100644
+--- a/drivers/scsi/cxgbi/libcxgbi.c
++++ b/drivers/scsi/cxgbi/libcxgbi.c
+@@ -2569,6 +2569,16 @@ EXPORT_SYMBOL_GPL(cxgbi_iscsi_cleanup);
+ mode_t cxgbi_attr_is_visible(int param_type, int param)
+ {
+ 	switch (param_type) {
++	case ISCSI_HOST_PARAM:
++		switch (param) {
++		case ISCSI_HOST_PARAM_NETDEV_NAME:
++		case ISCSI_HOST_PARAM_HWADDRESS:
++		case ISCSI_HOST_PARAM_IPADDRESS:
++		case ISCSI_HOST_PARAM_INITIATOR_NAME:
++			return S_IRUGO;
++		default:
++			return 0;
++		}
+ 	case ISCSI_PARAM:
+ 		switch (param) {
+ 		case ISCSI_PARAM_MAX_RECV_DLENGTH:
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 6ab212211760..23e706673d06 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -875,6 +875,16 @@ static void iscsi_sw_tcp_session_destroy(struct iscsi_cls_session *cls_session)
+ static mode_t iscsi_sw_tcp_attr_is_visible(int param_type, int param)
+ {
+ 	switch (param_type) {
++	case ISCSI_HOST_PARAM:
++		switch (param) {
++		case ISCSI_HOST_PARAM_NETDEV_NAME:
++		case ISCSI_HOST_PARAM_HWADDRESS:
++		case ISCSI_HOST_PARAM_IPADDRESS:
++		case ISCSI_HOST_PARAM_INITIATOR_NAME:
++			return S_IRUGO;
++		default:
++			return 0;
++		}
+ 	case ISCSI_PARAM:
+ 		switch (param) {
+ 		case ISCSI_PARAM_MAX_RECV_DLENGTH:
+@@ -955,9 +965,6 @@ static struct iscsi_transport iscsi_sw_tcp_transport = {
+ 	.name			= "tcp",
+ 	.caps			= CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST
+ 				  | CAP_DATADGST,
+-	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+-				  ISCSI_HOST_INITIATOR_NAME |
+-				  ISCSI_HOST_NETDEV_NAME,
+ 	/* session management */
+ 	.create_session		= iscsi_sw_tcp_session_create,
+ 	.destroy_session	= iscsi_sw_tcp_session_destroy,
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index df6da3cb124d..a9da3152ee51 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -138,9 +138,6 @@ static struct iscsi_transport qla4xxx_iscsi_transport = {
+ 	.name			= DRIVER_NAME,
+ 	.caps			= CAP_FW_DB | CAP_SENDTARGETS_OFFLOAD |
+ 				  CAP_DATA_PATH_OFFLOAD,
+-	.host_param_mask	= ISCSI_HOST_HWADDRESS |
+-				  ISCSI_HOST_IPADDRESS |
+-				  ISCSI_HOST_INITIATOR_NAME,
+ 	.tgt_dscvr		= qla4xxx_tgt_dscvr,
+ 	.attr_is_visible	= ql4_attr_is_visible,
+ 	.get_conn_param		= qla4xxx_conn_get_param,
+@@ -156,6 +153,15 @@ static struct scsi_transport_template *qla4xxx_scsi_transport;
+ static mode_t ql4_attr_is_visible(int param_type, int param)
+ {
+ 	switch (param_type) {
++	case ISCSI_HOST_PARAM:
++		switch (param) {
++		case ISCSI_HOST_PARAM_HWADDRESS:
++		case ISCSI_HOST_PARAM_IPADDRESS:
++		case ISCSI_HOST_PARAM_INITIATOR_NAME:
++			return S_IRUGO;
++		default:
++			return 0;
++		}
+ 	case ISCSI_PARAM:
+ 		switch (param) {
+ 		case ISCSI_PARAM_CONN_ADDRESS:
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index a8dd85dc77b1..2e9b68215593 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -32,8 +32,6 @@
+ #include 
+ #include 
+ 
+-#define ISCSI_HOST_ATTRS 4
+-
+ #define ISCSI_TRANSPORT_VERSION "2.0-870"
+ 
+ static int dbg_session;
+@@ -74,7 +72,6 @@ struct iscsi_internal {
+ 	struct list_head list;
+ 	struct device dev;
+ 
+-	struct device_attribute *host_attrs[ISCSI_HOST_ATTRS + 1];
+ 	struct transport_container conn_cont;
+ 	struct transport_container session_cont;
+ };
+@@ -2301,13 +2298,42 @@ iscsi_host_attr(hwaddress, ISCSI_HOST_PARAM_HWADDRESS);
+ iscsi_host_attr(ipaddress, ISCSI_HOST_PARAM_IPADDRESS);
+ iscsi_host_attr(initiatorname, ISCSI_HOST_PARAM_INITIATOR_NAME);
+ 
+-#define SETUP_HOST_RD_ATTR(field, param_flag)				\
+-do {									\
+-	if (tt->host_param_mask & param_flag) {				\
+-		priv->host_attrs[count] = &dev_attr_host_##field; \
+-		count++;						\
+-	}								\
+-} while (0)
++static struct attribute *iscsi_host_attrs[] = {
++	&dev_attr_host_netdev.attr,
++	&dev_attr_host_hwaddress.attr,
++	&dev_attr_host_ipaddress.attr,
++	&dev_attr_host_initiatorname.attr,
++	NULL,
++};
++
++static mode_t iscsi_host_attr_is_visible(struct kobject *kobj,
++					 struct attribute *attr, int i)
++{
++	struct device *cdev = container_of(kobj, struct device, kobj);
++	struct Scsi_Host *shost = transport_class_to_shost(cdev);
++	struct iscsi_internal *priv = to_iscsi_internal(shost->transportt);
++	int param;
++
++	if (attr == &dev_attr_host_netdev.attr)
++		param = ISCSI_HOST_PARAM_NETDEV_NAME;
++	else if (attr == &dev_attr_host_hwaddress.attr)
++		param = ISCSI_HOST_PARAM_HWADDRESS;
++	else if (attr == &dev_attr_host_ipaddress.attr)
++		param = ISCSI_HOST_PARAM_IPADDRESS;
++	else if (attr == &dev_attr_host_initiatorname.attr)
++		param = ISCSI_HOST_PARAM_INITIATOR_NAME;
++	else {
++		WARN_ONCE(1, "Invalid host attr");
++		return 0;
++	}
++
++	return priv->iscsi_transport->attr_is_visible(ISCSI_HOST_PARAM, param);
++}
++
++static struct attribute_group iscsi_host_group = {
++	.attrs = iscsi_host_attrs,
++	.is_visible = iscsi_host_attr_is_visible,
++};
+ 
+ static int iscsi_session_match(struct attribute_container *cont,
+ 			   struct device *dev)
+@@ -2379,7 +2405,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ {
+ 	struct iscsi_internal *priv;
+ 	unsigned long flags;
+-	int count = 0, err;
++	int err;
+ 
+ 	BUG_ON(!tt);
+ 
+@@ -2406,20 +2432,12 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 		goto unregister_dev;
+ 
+ 	/* host parameters */
+-	priv->t.host_attrs.ac.attrs = &priv->host_attrs[0];
+ 	priv->t.host_attrs.ac.class = &iscsi_host_class.class;
+ 	priv->t.host_attrs.ac.match = iscsi_host_match;
++	priv->t.host_attrs.ac.grp = &iscsi_host_group;
+ 	priv->t.host_size = sizeof(struct iscsi_cls_host);
+ 	transport_container_register(&priv->t.host_attrs);
+ 
+-	SETUP_HOST_RD_ATTR(netdev, ISCSI_HOST_NETDEV_NAME);
+-	SETUP_HOST_RD_ATTR(ipaddress, ISCSI_HOST_IPADDRESS);
+-	SETUP_HOST_RD_ATTR(hwaddress, ISCSI_HOST_HWADDRESS);
+-	SETUP_HOST_RD_ATTR(initiatorname, ISCSI_HOST_INITIATOR_NAME);
+-	BUG_ON(count > ISCSI_HOST_ATTRS);
+-	priv->host_attrs[count] = NULL;
+-	count = 0;
+-
+ 	/* connection parameters */
+ 	priv->conn_cont.ac.class = &iscsi_connection_class.class;
+ 	priv->conn_cont.ac.match = iscsi_conn_match;
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index 164a753fdd3a..3753f7e36386 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -391,11 +391,6 @@ enum iscsi_host_param {
+ 	ISCSI_HOST_PARAM_MAX,
+ };
+ 
+-#define ISCSI_HOST_HWADDRESS		(1ULL << ISCSI_HOST_PARAM_HWADDRESS)
+-#define ISCSI_HOST_INITIATOR_NAME	(1ULL << ISCSI_HOST_PARAM_INITIATOR_NAME)
+-#define ISCSI_HOST_NETDEV_NAME		(1ULL << ISCSI_HOST_PARAM_NETDEV_NAME)
+-#define ISCSI_HOST_IPADDRESS		(1ULL << ISCSI_HOST_PARAM_IPADDRESS)
+-
+ #define iscsi_ptr(_handle) ((void*)(unsigned long)_handle)
+ #define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr)
+ 
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index b9e9ef5a881f..77e6dd60fb4b 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -85,8 +85,6 @@ struct iscsi_transport {
+ 	struct module *owner;
+ 	char *name;
+ 	unsigned int caps;
+-	/* LLD sets this to indicate what values it can export to sysfs */
+-	uint64_t host_param_mask;
+ 
+ 	struct iscsi_cls_session *(*create_session) (struct iscsi_endpoint *ep,
+ 					uint16_t cmds_max, uint16_t qdepth,

commit b78dbba0053c6f14384d55b929d21b85d03c38bb
+Author: Mike Christie 
+Date:   Mon Jul 25 13:48:44 2011 -0500
+
+    [SCSI] iscsi class: remove iface param mask
+    
+    We can replace the iface param mask with the
+    attr_is_visible callback.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index 3022c1534156..df6da3cb124d 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -141,17 +141,6 @@ static struct iscsi_transport qla4xxx_iscsi_transport = {
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS |
+ 				  ISCSI_HOST_IPADDRESS |
+ 				  ISCSI_HOST_INITIATOR_NAME,
+-	.iface_param_mask	= ISCSI_NET_IPV4_ADDR |
+-				  ISCSI_NET_IPV4_SUBNET |
+-				  ISCSI_NET_IPV4_GW |
+-				  ISCSI_NET_IPV4_BOOTPROTO |
+-				  ISCSI_NET_IFACE_ENABLE |
+-				  ISCSI_NET_IPV6_LINKLOCAL |
+-				  ISCSI_NET_IPV6_ADDR |
+-				  ISCSI_NET_IPV6_ROUTER |
+-				  ISCSI_NET_IPV6_ADDR_AUTOCFG |
+-				  ISCSI_NET_IPV6_LINKLOCAL_AUTOCFG |
+-				  ISCSI_NET_IFACE_ENABLE,
+ 	.tgt_dscvr		= qla4xxx_tgt_dscvr,
+ 	.attr_is_visible	= ql4_attr_is_visible,
+ 	.get_conn_param		= qla4xxx_conn_get_param,
+@@ -178,6 +167,22 @@ static mode_t ql4_attr_is_visible(int param_type, int param)
+ 		default:
+ 			return 0;
+ 		}
++	case ISCSI_NET_PARAM:
++		switch (param) {
++		case ISCSI_NET_PARAM_IPV4_ADDR:
++		case ISCSI_NET_PARAM_IPV4_SUBNET:
++		case ISCSI_NET_PARAM_IPV4_GW:
++		case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
++		case ISCSI_NET_PARAM_IFACE_ENABLE:
++		case ISCSI_NET_PARAM_IPV6_LINKLOCAL:
++		case ISCSI_NET_PARAM_IPV6_ADDR:
++		case ISCSI_NET_PARAM_IPV6_ROUTER:
++		case ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG:
++		case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG:
++			return S_IRUGO;
++		default:
++			return 0;
++		}
+ 	}
+ 
+ 	return 0;
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 75d7f6e93b67..a8dd85dc77b1 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -329,45 +329,42 @@ static mode_t iscsi_iface_attr_is_visible(struct kobject *kobj,
+ 	struct device *dev = container_of(kobj, struct device, kobj);
+ 	struct iscsi_iface *iface = iscsi_dev_to_iface(dev);
+ 	struct iscsi_transport *t = iface->transport;
++	int param;
+ 
+ 	if (attr == &dev_attr_iface_enabled.attr)
+-		return (t->iface_param_mask & ISCSI_NET_IFACE_ENABLE) ?
+-								S_IRUGO : 0;
++		param = ISCSI_NET_PARAM_IFACE_ENABLE;
+ 	else if (attr == &dev_attr_iface_vlan.attr)
+-		return (t->iface_param_mask & ISCSI_NET_VLAN_ID) ? S_IRUGO : 0;
+-
+-	if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) {
++		param = ISCSI_NET_PARAM_VLAN_ID;
++	else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) {
+ 		if (attr == &dev_attr_ipv4_iface_ipaddress.attr)
+-			return (t->iface_param_mask & ISCSI_NET_IPV4_ADDR) ?
+-								S_IRUGO : 0;
++			param = ISCSI_NET_PARAM_IPV4_ADDR;
+ 		else if (attr == &dev_attr_ipv4_iface_gateway.attr)
+-			return (t->iface_param_mask & ISCSI_NET_IPV4_GW) ?
+-								S_IRUGO : 0;
++			param = ISCSI_NET_PARAM_IPV4_GW;
+ 		else if (attr == &dev_attr_ipv4_iface_subnet.attr)
+-			return (t->iface_param_mask & ISCSI_NET_IPV4_SUBNET) ?
+-								S_IRUGO : 0;
++			param = ISCSI_NET_PARAM_IPV4_SUBNET;
+ 		else if (attr == &dev_attr_ipv4_iface_bootproto.attr)
+-			return (t->iface_param_mask & ISCSI_NET_IPV4_BOOTPROTO) ?
+-								 S_IRUGO : 0;
++			param = ISCSI_NET_PARAM_IPV4_BOOTPROTO;
++		else
++			return 0;
+ 	} else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) {
+ 		if (attr == &dev_attr_ipv6_iface_ipaddress.attr)
+-			return (t->iface_param_mask & ISCSI_NET_IPV6_ADDR) ?
+-								S_IRUGO : 0;
++			param = ISCSI_NET_PARAM_IPV6_ADDR;
+ 		else if (attr == &dev_attr_ipv6_iface_link_local_addr.attr)
+-			return (t->iface_param_mask & ISCSI_NET_IPV6_LINKLOCAL) ?
+-								S_IRUGO : 0;
++			param = ISCSI_NET_PARAM_IPV6_LINKLOCAL;
+ 		else if (attr == &dev_attr_ipv6_iface_router_addr.attr)
+-			return (t->iface_param_mask & ISCSI_NET_IPV6_ROUTER) ?
+-								S_IRUGO : 0;
++			param = ISCSI_NET_PARAM_IPV6_ROUTER;
+ 		else if (attr == &dev_attr_ipv6_iface_ipaddr_autocfg.attr)
+-			return (t->iface_param_mask & ISCSI_NET_IPV6_ADDR_AUTOCFG) ?
+-								S_IRUGO : 0;
++			param = ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG;
+ 		else if (attr == &dev_attr_ipv6_iface_linklocal_autocfg.attr)
+-			return (t->iface_param_mask & ISCSI_NET_IPV6_LINKLOCAL_AUTOCFG) ?
+-								S_IRUGO : 0;
++			param = ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG;
++		else
++			return 0;
++	} else {
++		WARN_ONCE(1, "Invalid iface attr");
++		return 0;
+ 	}
+ 
+-	return 0;
++	return t->attr_is_visible(ISCSI_NET_PARAM, param);
+ }
+ 
+ static struct attribute *iscsi_iface_attrs[] = {
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index a4353ff563f2..164a753fdd3a 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -300,23 +300,6 @@ enum iscsi_net_param {
+ 	ISCSI_NET_PARAM_IFACE_NAME		= 15,
+ };
+ 
+-#define ISCSI_NET_IPV4_ADDR		(1ULL << ISCSI_NET_PARAM_IPV4_ADDR)
+-#define ISCSI_NET_IPV4_SUBNET		(1ULL << ISCSI_NET_PARAM_IPV4_SUBNET)
+-#define ISCSI_NET_IPV4_GW		(1ULL << ISCSI_NET_PARAM_IPV4_GW)
+-#define ISCSI_NET_IPV4_BOOTPROTO	(1ULL << ISCSI_NET_PARAM_IPV4_BOOTPROTO)
+-#define ISCSI_NET_MAC			(1ULL << ISCSI_NET_PARAM_MAC)
+-#define ISCSI_NET_IPV6_LINKLOCAL	(1ULL << ISCSI_NET_PARAM_IPV6_LINKLOCAL)
+-#define ISCSI_NET_IPV6_ADDR		(1ULL << ISCSI_NET_PARAM_IPV6_ADDR)
+-#define ISCSI_NET_IPV6_ROUTER		(1ULL << ISCSI_NET_PARAM_IPV6_ROUTER)
+-#define ISCSI_NET_IPV6_ADDR_AUTOCFG		\
+-				(1ULL << ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG)
+-#define ISCSI_NET_IPV6_LINKLOCAL_AUTOCFG	\
+-				(1ULL << ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG)
+-#define ISCSI_NET_IPV6_ROUTER_AUTOCFG		\
+-                               (1ULL << ISCSI_NET_PARAM_IPV6_ROUTER_AUTOCFG)
+-#define ISCSI_NET_IFACE_ENABLE		(1ULL << ISCSI_NET_PARAM_IFACE_ENABLE)
+-#define ISCSI_NET_VLAN_ID			(1ULL << ISCSI_NET_PARAM_VLAN_ID)
+-
+ /*
+  * Common error codes
+  */
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 53eb93849377..b9e9ef5a881f 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -87,7 +87,6 @@ struct iscsi_transport {
+ 	unsigned int caps;
+ 	/* LLD sets this to indicate what values it can export to sysfs */
+ 	uint64_t host_param_mask;
+-	uint64_t iface_param_mask;
+ 
+ 	struct iscsi_cls_session *(*create_session) (struct iscsi_endpoint *ep,
+ 					uint16_t cmds_max, uint16_t qdepth,

commit 1d063c17298d7cd26cfe350f1e93e1727b4aa53f
+Author: Mike Christie 
+Date:   Mon Jul 25 13:48:43 2011 -0500
+
+    [SCSI] iscsi class: sysfs group is_visible callout for session attrs
+    
+    The iscsi class currently does not support writable sysfs
+    attrs for LLD sysfs settings. This patch converts the
+    iscsi class and driver's session attrs to use the attribute
+    container sysfs group and the sysfs group's is_visible callout
+    to be able to support readable or writable sysfs attrs.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index c716722628cf..4f2411298b20 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -648,6 +648,25 @@ static mode_t iser_attr_is_visible(int param_type, int param)
+ 		case ISCSI_PARAM_PERSISTENT_PORT:
+ 		case ISCSI_PARAM_PING_TMO:
+ 		case ISCSI_PARAM_RECV_TMO:
++		case ISCSI_PARAM_INITIAL_R2T_EN:
++		case ISCSI_PARAM_MAX_R2T:
++		case ISCSI_PARAM_IMM_DATA_EN:
++		case ISCSI_PARAM_FIRST_BURST:
++		case ISCSI_PARAM_MAX_BURST:
++		case ISCSI_PARAM_PDU_INORDER_EN:
++		case ISCSI_PARAM_DATASEQ_INORDER_EN:
++		case ISCSI_PARAM_TARGET_NAME:
++		case ISCSI_PARAM_TPGT:
++		case ISCSI_PARAM_USERNAME:
++		case ISCSI_PARAM_PASSWORD:
++		case ISCSI_PARAM_USERNAME_IN:
++		case ISCSI_PARAM_PASSWORD_IN:
++		case ISCSI_PARAM_FAST_ABORT:
++		case ISCSI_PARAM_ABORT_TMO:
++		case ISCSI_PARAM_LU_RESET_TMO:
++		case ISCSI_PARAM_TGT_RESET_TMO:
++		case ISCSI_PARAM_IFACE_NAME:
++		case ISCSI_PARAM_INITIATOR_NAME:
+ 			return S_IRUGO;
+ 		default:
+ 			return 0;
+@@ -678,19 +697,6 @@ static struct iscsi_transport iscsi_iser_transport = {
+ 	.owner                  = THIS_MODULE,
+ 	.name                   = "iser",
+ 	.caps                   = CAP_RECOVERY_L0 | CAP_MULTI_R2T,
+-	.param_mask		= ISCSI_INITIAL_R2T_EN |
+-				  ISCSI_MAX_R2T |
+-				  ISCSI_IMM_DATA_EN |
+-				  ISCSI_FIRST_BURST |
+-				  ISCSI_MAX_BURST |
+-				  ISCSI_PDU_INORDER_EN |
+-				  ISCSI_DATASEQ_INORDER_EN |
+-				  ISCSI_TARGET_NAME | ISCSI_TPGT |
+-				  ISCSI_USERNAME | ISCSI_PASSWORD |
+-				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+-				  ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+-				  ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
+-				  ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS |
+ 				  ISCSI_HOST_NETDEV_NAME |
+ 				  ISCSI_HOST_INITIATOR_NAME,
+diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
+index 87b7ae1ef488..ecd19bb3b207 100644
+--- a/drivers/scsi/be2iscsi/be_iscsi.c
++++ b/drivers/scsi/be2iscsi/be_iscsi.c
+@@ -750,6 +750,25 @@ mode_t be2iscsi_attr_is_visible(int param_type, int param)
+ 		case ISCSI_PARAM_PERSISTENT_PORT:
+ 		case ISCSI_PARAM_PING_TMO:
+ 		case ISCSI_PARAM_RECV_TMO:
++		case ISCSI_PARAM_INITIAL_R2T_EN:
++		case ISCSI_PARAM_MAX_R2T:
++		case ISCSI_PARAM_IMM_DATA_EN:
++		case ISCSI_PARAM_FIRST_BURST:
++		case ISCSI_PARAM_MAX_BURST:
++		case ISCSI_PARAM_PDU_INORDER_EN:
++		case ISCSI_PARAM_DATASEQ_INORDER_EN:
++		case ISCSI_PARAM_ERL:
++		case ISCSI_PARAM_TARGET_NAME:
++		case ISCSI_PARAM_TPGT:
++		case ISCSI_PARAM_USERNAME:
++		case ISCSI_PARAM_PASSWORD:
++		case ISCSI_PARAM_USERNAME_IN:
++		case ISCSI_PARAM_PASSWORD_IN:
++		case ISCSI_PARAM_FAST_ABORT:
++		case ISCSI_PARAM_ABORT_TMO:
++		case ISCSI_PARAM_LU_RESET_TMO:
++		case ISCSI_PARAM_IFACE_NAME:
++		case ISCSI_PARAM_INITIATOR_NAME:
+ 			return S_IRUGO;
+ 		default:
+ 			return 0;
+diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
+index d2a3e4a4d024..93a3c708411a 100644
+--- a/drivers/scsi/be2iscsi/be_main.c
++++ b/drivers/scsi/be2iscsi/be_main.c
+@@ -4364,21 +4364,6 @@ struct iscsi_transport beiscsi_iscsi_transport = {
+ 	.name = DRV_NAME,
+ 	.caps = CAP_RECOVERY_L0 | CAP_HDRDGST | CAP_TEXT_NEGO |
+ 		CAP_MULTI_R2T | CAP_DATADGST | CAP_DATA_PATH_OFFLOAD,
+-	.param_mask =
+-		ISCSI_INITIAL_R2T_EN |
+-		ISCSI_MAX_R2T |
+-		ISCSI_IMM_DATA_EN |
+-		ISCSI_FIRST_BURST |
+-		ISCSI_MAX_BURST |
+-		ISCSI_PDU_INORDER_EN |
+-		ISCSI_DATASEQ_INORDER_EN |
+-		ISCSI_ERL |
+-		ISCSI_TARGET_NAME | ISCSI_TPGT |
+-		ISCSI_USERNAME | ISCSI_PASSWORD |
+-		ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+-		ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+-		ISCSI_LU_RESET_TMO |
+-		ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
+ 	.host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+ 				ISCSI_HOST_INITIATOR_NAME,
+ 	.create_session = beiscsi_session_create,
+diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
+index 2d529c9fa1ad..2db3399d2734 100644
+--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
++++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
+@@ -2193,6 +2193,26 @@ static mode_t bnx2i_attr_is_visible(int param_type, int param)
+ 		case ISCSI_PARAM_PERSISTENT_PORT:
+ 		case ISCSI_PARAM_PING_TMO:
+ 		case ISCSI_PARAM_RECV_TMO:
++		case ISCSI_PARAM_INITIAL_R2T_EN:
++		case ISCSI_PARAM_MAX_R2T:
++		case ISCSI_PARAM_IMM_DATA_EN:
++		case ISCSI_PARAM_FIRST_BURST:
++		case ISCSI_PARAM_MAX_BURST:
++		case ISCSI_PARAM_PDU_INORDER_EN:
++		case ISCSI_PARAM_DATASEQ_INORDER_EN:
++		case ISCSI_PARAM_ERL:
++		case ISCSI_PARAM_TARGET_NAME:
++		case ISCSI_PARAM_TPGT:
++		case ISCSI_PARAM_USERNAME:
++		case ISCSI_PARAM_PASSWORD:
++		case ISCSI_PARAM_USERNAME_IN:
++		case ISCSI_PARAM_PASSWORD_IN:
++		case ISCSI_PARAM_FAST_ABORT:
++		case ISCSI_PARAM_ABORT_TMO:
++		case ISCSI_PARAM_LU_RESET_TMO:
++		case ISCSI_PARAM_TGT_RESET_TMO:
++		case ISCSI_PARAM_IFACE_NAME:
++		case ISCSI_PARAM_INITIATOR_NAME:
+ 			return S_IRUGO;
+ 		default:
+ 			return 0;
+@@ -2231,20 +2251,6 @@ struct iscsi_transport bnx2i_iscsi_transport = {
+ 				  CAP_MULTI_R2T | CAP_DATADGST |
+ 				  CAP_DATA_PATH_OFFLOAD |
+ 				  CAP_TEXT_NEGO,
+-	.param_mask		= ISCSI_INITIAL_R2T_EN |
+-				  ISCSI_MAX_R2T |
+-				  ISCSI_IMM_DATA_EN |
+-				  ISCSI_FIRST_BURST |
+-				  ISCSI_MAX_BURST |
+-				  ISCSI_PDU_INORDER_EN |
+-				  ISCSI_DATASEQ_INORDER_EN |
+-				  ISCSI_ERL |
+-				  ISCSI_TARGET_NAME | ISCSI_TPGT |
+-				  ISCSI_USERNAME | ISCSI_PASSWORD |
+-				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+-				  ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+-				  ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
+-				  ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+ 				  ISCSI_HOST_NETDEV_NAME,
+ 	.create_session		= bnx2i_session_create,
+diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
+index c13b3f0a4f03..50d4e3f05038 100644
+--- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
++++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
+@@ -106,17 +106,6 @@ static struct iscsi_transport cxgb3i_iscsi_transport = {
+ 	.caps		= CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST
+ 				| CAP_DATADGST | CAP_DIGEST_OFFLOAD |
+ 				CAP_PADDING_OFFLOAD | CAP_TEXT_NEGO,
+-	.param_mask	=
+-				ISCSI_INITIAL_R2T_EN | ISCSI_MAX_R2T |
+-				ISCSI_IMM_DATA_EN | ISCSI_FIRST_BURST |
+-				ISCSI_MAX_BURST | ISCSI_PDU_INORDER_EN |
+-				ISCSI_DATASEQ_INORDER_EN | ISCSI_ERL |
+-				ISCSI_TARGET_NAME | ISCSI_TPGT |
+-				ISCSI_USERNAME | ISCSI_PASSWORD |
+-				ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+-				ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+-				ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
+-				ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+ 				ISCSI_HOST_INITIATOR_NAME |
+ 				ISCSI_HOST_NETDEV_NAME,
+diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+index 89fca4b0787c..72f19ef7e016 100644
+--- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
++++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+@@ -107,17 +107,6 @@ static struct iscsi_transport cxgb4i_iscsi_transport = {
+ 	.caps		= CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST |
+ 				CAP_DATADGST | CAP_DIGEST_OFFLOAD |
+ 				CAP_PADDING_OFFLOAD | CAP_TEXT_NEGO,
+-	.param_mask	=
+-				ISCSI_INITIAL_R2T_EN | ISCSI_MAX_R2T |
+-				ISCSI_IMM_DATA_EN | ISCSI_FIRST_BURST |
+-				ISCSI_MAX_BURST | ISCSI_PDU_INORDER_EN |
+-				ISCSI_DATASEQ_INORDER_EN | ISCSI_ERL |
+-				ISCSI_TARGET_NAME | ISCSI_TPGT |
+-				ISCSI_USERNAME | ISCSI_PASSWORD |
+-				ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+-				ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+-				ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
+-				ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+ 				ISCSI_HOST_INITIATOR_NAME |
+ 				ISCSI_HOST_NETDEV_NAME,
+diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c
+index e5f4f968ed7b..f9c2ca0d8083 100644
+--- a/drivers/scsi/cxgbi/libcxgbi.c
++++ b/drivers/scsi/cxgbi/libcxgbi.c
+@@ -2582,6 +2582,26 @@ mode_t cxgbi_attr_is_visible(int param_type, int param)
+ 		case ISCSI_PARAM_PERSISTENT_PORT:
+ 		case ISCSI_PARAM_PING_TMO:
+ 		case ISCSI_PARAM_RECV_TMO:
++		case ISCSI_PARAM_INITIAL_R2T_EN:
++		case ISCSI_PARAM_MAX_R2T:
++		case ISCSI_PARAM_IMM_DATA_EN:
++		case ISCSI_PARAM_FIRST_BURST:
++		case ISCSI_PARAM_MAX_BURST:
++		case ISCSI_PARAM_PDU_INORDER_EN:
++		case ISCSI_PARAM_DATASEQ_INORDER_EN:
++		case ISCSI_PARAM_ERL:
++		case ISCSI_PARAM_TARGET_NAME:
++		case ISCSI_PARAM_TPGT:
++		case ISCSI_PARAM_USERNAME:
++		case ISCSI_PARAM_PASSWORD:
++		case ISCSI_PARAM_USERNAME_IN:
++		case ISCSI_PARAM_PASSWORD_IN:
++		case ISCSI_PARAM_FAST_ABORT:
++		case ISCSI_PARAM_ABORT_TMO:
++		case ISCSI_PARAM_LU_RESET_TMO:
++		case ISCSI_PARAM_TGT_RESET_TMO:
++		case ISCSI_PARAM_IFACE_NAME:
++		case ISCSI_PARAM_INITIATOR_NAME:
+ 			return S_IRUGO;
+ 		default:
+ 			return 0;
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 1dcb4d183bc9..6ab212211760 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -888,6 +888,26 @@ static mode_t iscsi_sw_tcp_attr_is_visible(int param_type, int param)
+ 		case ISCSI_PARAM_PERSISTENT_PORT:
+ 		case ISCSI_PARAM_PING_TMO:
+ 		case ISCSI_PARAM_RECV_TMO:
++		case ISCSI_PARAM_INITIAL_R2T_EN:
++		case ISCSI_PARAM_MAX_R2T:
++		case ISCSI_PARAM_IMM_DATA_EN:
++		case ISCSI_PARAM_FIRST_BURST:
++		case ISCSI_PARAM_MAX_BURST:
++		case ISCSI_PARAM_PDU_INORDER_EN:
++		case ISCSI_PARAM_DATASEQ_INORDER_EN:
++		case ISCSI_PARAM_ERL:
++		case ISCSI_PARAM_TARGET_NAME:
++		case ISCSI_PARAM_TPGT:
++		case ISCSI_PARAM_USERNAME:
++		case ISCSI_PARAM_PASSWORD:
++		case ISCSI_PARAM_USERNAME_IN:
++		case ISCSI_PARAM_PASSWORD_IN:
++		case ISCSI_PARAM_FAST_ABORT:
++		case ISCSI_PARAM_ABORT_TMO:
++		case ISCSI_PARAM_LU_RESET_TMO:
++		case ISCSI_PARAM_TGT_RESET_TMO:
++		case ISCSI_PARAM_IFACE_NAME:
++		case ISCSI_PARAM_INITIATOR_NAME:
+ 			return S_IRUGO;
+ 		default:
+ 			return 0;
+@@ -935,20 +955,6 @@ static struct iscsi_transport iscsi_sw_tcp_transport = {
+ 	.name			= "tcp",
+ 	.caps			= CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST
+ 				  | CAP_DATADGST,
+-	.param_mask		= ISCSI_INITIAL_R2T_EN |
+-				  ISCSI_MAX_R2T |
+-				  ISCSI_IMM_DATA_EN |
+-				  ISCSI_FIRST_BURST |
+-				  ISCSI_MAX_BURST |
+-				  ISCSI_PDU_INORDER_EN |
+-				  ISCSI_DATASEQ_INORDER_EN |
+-				  ISCSI_ERL |
+-				  ISCSI_TARGET_NAME | ISCSI_TPGT |
+-				  ISCSI_USERNAME | ISCSI_PASSWORD |
+-				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+-				  ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+-				  ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
+-				  ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+ 				  ISCSI_HOST_INITIATOR_NAME |
+ 				  ISCSI_HOST_NETDEV_NAME,
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index f8a1506cb76a..3022c1534156 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -138,8 +138,6 @@ static struct iscsi_transport qla4xxx_iscsi_transport = {
+ 	.name			= DRIVER_NAME,
+ 	.caps			= CAP_FW_DB | CAP_SENDTARGETS_OFFLOAD |
+ 				  CAP_DATA_PATH_OFFLOAD,
+-	.param_mask		= ISCSI_TARGET_NAME | ISCSI_TPGT |
+-				  ISCSI_TARGET_ALIAS,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS |
+ 				  ISCSI_HOST_IPADDRESS |
+ 				  ISCSI_HOST_INITIATOR_NAME,
+@@ -173,6 +171,9 @@ static mode_t ql4_attr_is_visible(int param_type, int param)
+ 		switch (param) {
+ 		case ISCSI_PARAM_CONN_ADDRESS:
+ 		case ISCSI_PARAM_CONN_PORT:
++		case ISCSI_PARAM_TARGET_NAME:
++		case ISCSI_PARAM_TPGT:
++		case ISCSI_PARAM_TARGET_ALIAS:
+ 			return S_IRUGO;
+ 		default:
+ 			return 0;
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index e9eca98e1102..75d7f6e93b67 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -32,8 +32,6 @@
+ #include 
+ #include 
+ 
+-#define ISCSI_SESSION_ATTRS 23
+-#define ISCSI_CONN_ATTRS 13
+ #define ISCSI_HOST_ATTRS 4
+ 
+ #define ISCSI_TRANSPORT_VERSION "2.0-870"
+@@ -79,7 +77,6 @@ struct iscsi_internal {
+ 	struct device_attribute *host_attrs[ISCSI_HOST_ATTRS + 1];
+ 	struct transport_container conn_cont;
+ 	struct transport_container session_cont;
+-	struct device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1];
+ };
+ 
+ static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
+@@ -2114,7 +2111,6 @@ show_session_param_##param(struct device *dev,				\
+ 	iscsi_session_attr_show(param, perm)				\
+ static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_param_##param, \
+ 			NULL);
+-
+ iscsi_session_attr(targetname, ISCSI_PARAM_TARGET_NAME, 0);
+ iscsi_session_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN, 0);
+ iscsi_session_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T, 0);
+@@ -2191,6 +2187,100 @@ static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO | S_IWUSR,		\
+ 			store_priv_session_##field)
+ iscsi_priv_session_rw_attr(recovery_tmo, "%d");
+ 
++static struct attribute *iscsi_session_attrs[] = {
++	&dev_attr_sess_initial_r2t.attr,
++	&dev_attr_sess_max_outstanding_r2t.attr,
++	&dev_attr_sess_immediate_data.attr,
++	&dev_attr_sess_first_burst_len.attr,
++	&dev_attr_sess_max_burst_len.attr,
++	&dev_attr_sess_data_pdu_in_order.attr,
++	&dev_attr_sess_data_seq_in_order.attr,
++	&dev_attr_sess_erl.attr,
++	&dev_attr_sess_targetname.attr,
++	&dev_attr_sess_tpgt.attr,
++	&dev_attr_sess_password.attr,
++	&dev_attr_sess_password_in.attr,
++	&dev_attr_sess_username.attr,
++	&dev_attr_sess_username_in.attr,
++	&dev_attr_sess_fast_abort.attr,
++	&dev_attr_sess_abort_tmo.attr,
++	&dev_attr_sess_lu_reset_tmo.attr,
++	&dev_attr_sess_tgt_reset_tmo.attr,
++	&dev_attr_sess_ifacename.attr,
++	&dev_attr_sess_initiatorname.attr,
++	&dev_attr_sess_targetalias.attr,
++	&dev_attr_priv_sess_recovery_tmo.attr,
++	&dev_attr_priv_sess_state.attr,
++	NULL,
++};
++
++static mode_t iscsi_session_attr_is_visible(struct kobject *kobj,
++					    struct attribute *attr, int i)
++{
++	struct device *cdev = container_of(kobj, struct device, kobj);
++	struct iscsi_cls_session *session = transport_class_to_session(cdev);
++	struct iscsi_transport *t = session->transport;
++	int param;
++
++	if (attr == &dev_attr_sess_initial_r2t.attr)
++		param = ISCSI_PARAM_INITIAL_R2T_EN;
++	else if (attr == &dev_attr_sess_max_outstanding_r2t.attr)
++		param = ISCSI_PARAM_MAX_R2T;
++	else if (attr == &dev_attr_sess_immediate_data.attr)
++		param = ISCSI_PARAM_IMM_DATA_EN;
++	else if (attr == &dev_attr_sess_first_burst_len.attr)
++		param = ISCSI_PARAM_FIRST_BURST;
++	else if (attr == &dev_attr_sess_max_burst_len.attr)
++		param = ISCSI_PARAM_MAX_BURST;
++	else if (attr == &dev_attr_sess_data_pdu_in_order.attr)
++		param = ISCSI_PARAM_PDU_INORDER_EN;
++	else if (attr == &dev_attr_sess_data_seq_in_order.attr)
++		param = ISCSI_PARAM_DATASEQ_INORDER_EN;
++	else if (attr == &dev_attr_sess_erl.attr)
++		param = ISCSI_PARAM_ERL;
++	else if (attr == &dev_attr_sess_targetname.attr)
++		param = ISCSI_PARAM_TARGET_NAME;
++	else if (attr == &dev_attr_sess_tpgt.attr)
++		param = ISCSI_PARAM_TPGT;
++	else if (attr == &dev_attr_sess_password.attr)
++		param = ISCSI_PARAM_USERNAME;
++	else if (attr == &dev_attr_sess_password_in.attr)
++		param = ISCSI_PARAM_USERNAME_IN;
++	else if (attr == &dev_attr_sess_username.attr)
++		param = ISCSI_PARAM_PASSWORD;
++	else if (attr == &dev_attr_sess_username_in.attr)
++		param = ISCSI_PARAM_PASSWORD_IN;
++	else if (attr == &dev_attr_sess_fast_abort.attr)
++		param = ISCSI_PARAM_FAST_ABORT;
++	else if (attr == &dev_attr_sess_abort_tmo.attr)
++		param = ISCSI_PARAM_ABORT_TMO;
++	else if (attr == &dev_attr_sess_lu_reset_tmo.attr)
++		param = ISCSI_PARAM_LU_RESET_TMO;
++	else if (attr == &dev_attr_sess_tgt_reset_tmo.attr)
++		param = ISCSI_PARAM_TGT_RESET_TMO;
++	else if (attr == &dev_attr_sess_ifacename.attr)
++		param = ISCSI_PARAM_IFACE_NAME;
++	else if (attr == &dev_attr_sess_initiatorname.attr)
++		param = ISCSI_PARAM_INITIATOR_NAME;
++	else if (attr == &dev_attr_sess_targetalias.attr)
++		param = ISCSI_PARAM_TARGET_ALIAS;
++	else if (attr == &dev_attr_priv_sess_recovery_tmo.attr)
++		return S_IRUGO | S_IWUSR;
++	else if (attr == &dev_attr_priv_sess_state.attr)
++		return S_IRUGO;
++	else {
++		WARN_ONCE(1, "Invalid session attr");
++		return 0;
++	}
++
++	return t->attr_is_visible(ISCSI_PARAM, param);
++}
++
++static struct attribute_group iscsi_session_group = {
++	.attrs = iscsi_session_attrs,
++	.is_visible = iscsi_session_attr_is_visible,
++};
++
+ /*
+  * iSCSI host attrs
+  */
+@@ -2214,26 +2304,6 @@ iscsi_host_attr(hwaddress, ISCSI_HOST_PARAM_HWADDRESS);
+ iscsi_host_attr(ipaddress, ISCSI_HOST_PARAM_IPADDRESS);
+ iscsi_host_attr(initiatorname, ISCSI_HOST_PARAM_INITIATOR_NAME);
+ 
+-#define SETUP_PRIV_SESSION_RD_ATTR(field)				\
+-do {									\
+-	priv->session_attrs[count] = &dev_attr_priv_sess_##field; \
+-	count++;							\
+-} while (0)
+-
+-#define SETUP_PRIV_SESSION_RW_ATTR(field)				\
+-do {									\
+-	priv->session_attrs[count] = &dev_attr_priv_sess_##field;	\
+-	count++;							\
+-} while (0)
+-
+-#define SETUP_SESSION_RD_ATTR(field, param_flag)			\
+-do {									\
+-	if (tt->param_mask & param_flag) {				\
+-		priv->session_attrs[count] = &dev_attr_sess_##field; \
+-		count++;						\
+-	}								\
+-} while (0)
+-
+ #define SETUP_HOST_RD_ATTR(field, param_flag)				\
+ do {									\
+ 	if (tt->host_param_mask & param_flag) {				\
+@@ -2360,39 +2430,11 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 	transport_container_register(&priv->conn_cont);
+ 
+ 	/* session parameters */
+-	priv->session_cont.ac.attrs = &priv->session_attrs[0];
+ 	priv->session_cont.ac.class = &iscsi_session_class.class;
+ 	priv->session_cont.ac.match = iscsi_session_match;
++	priv->session_cont.ac.grp = &iscsi_session_group;
+ 	transport_container_register(&priv->session_cont);
+ 
+-	SETUP_SESSION_RD_ATTR(initial_r2t, ISCSI_INITIAL_R2T_EN);
+-	SETUP_SESSION_RD_ATTR(max_outstanding_r2t, ISCSI_MAX_R2T);
+-	SETUP_SESSION_RD_ATTR(immediate_data, ISCSI_IMM_DATA_EN);
+-	SETUP_SESSION_RD_ATTR(first_burst_len, ISCSI_FIRST_BURST);
+-	SETUP_SESSION_RD_ATTR(max_burst_len, ISCSI_MAX_BURST);
+-	SETUP_SESSION_RD_ATTR(data_pdu_in_order, ISCSI_PDU_INORDER_EN);
+-	SETUP_SESSION_RD_ATTR(data_seq_in_order, ISCSI_DATASEQ_INORDER_EN);
+-	SETUP_SESSION_RD_ATTR(erl, ISCSI_ERL);
+-	SETUP_SESSION_RD_ATTR(targetname, ISCSI_TARGET_NAME);
+-	SETUP_SESSION_RD_ATTR(tpgt, ISCSI_TPGT);
+-	SETUP_SESSION_RD_ATTR(password, ISCSI_USERNAME);
+-	SETUP_SESSION_RD_ATTR(password_in, ISCSI_USERNAME_IN);
+-	SETUP_SESSION_RD_ATTR(username, ISCSI_PASSWORD);
+-	SETUP_SESSION_RD_ATTR(username_in, ISCSI_PASSWORD_IN);
+-	SETUP_SESSION_RD_ATTR(fast_abort, ISCSI_FAST_ABORT);
+-	SETUP_SESSION_RD_ATTR(abort_tmo, ISCSI_ABORT_TMO);
+-	SETUP_SESSION_RD_ATTR(lu_reset_tmo,ISCSI_LU_RESET_TMO);
+-	SETUP_SESSION_RD_ATTR(tgt_reset_tmo,ISCSI_TGT_RESET_TMO);
+-	SETUP_SESSION_RD_ATTR(ifacename, ISCSI_IFACE_NAME);
+-	SETUP_SESSION_RD_ATTR(initiatorname, ISCSI_INITIATOR_NAME);
+-	SETUP_SESSION_RD_ATTR(targetalias, ISCSI_TARGET_ALIAS);
+-	SETUP_PRIV_SESSION_RW_ATTR(recovery_tmo);
+-	SETUP_PRIV_SESSION_RD_ATTR(state);
+-
+-	BUG_ON(count > ISCSI_SESSION_ATTRS);
+-	priv->session_attrs[count] = NULL;
+-	count = 0;
+-
+ 	spin_lock_irqsave(&iscsi_transport_lock, flags);
+ 	list_add(&priv->list, &iscsi_transports);
+ 	spin_unlock_irqrestore(&iscsi_transport_lock, flags);
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index a563753d578b..a4353ff563f2 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -399,44 +399,6 @@ enum iscsi_param {
+ 	ISCSI_PARAM_MAX,
+ };
+ 
+-#define ISCSI_MAX_RECV_DLENGTH		(1ULL << ISCSI_PARAM_MAX_RECV_DLENGTH)
+-#define ISCSI_MAX_XMIT_DLENGTH		(1ULL << ISCSI_PARAM_MAX_XMIT_DLENGTH)
+-#define ISCSI_HDRDGST_EN		(1ULL << ISCSI_PARAM_HDRDGST_EN)
+-#define ISCSI_DATADGST_EN		(1ULL << ISCSI_PARAM_DATADGST_EN)
+-#define ISCSI_INITIAL_R2T_EN		(1ULL << ISCSI_PARAM_INITIAL_R2T_EN)
+-#define ISCSI_MAX_R2T			(1ULL << ISCSI_PARAM_MAX_R2T)
+-#define ISCSI_IMM_DATA_EN		(1ULL << ISCSI_PARAM_IMM_DATA_EN)
+-#define ISCSI_FIRST_BURST		(1ULL << ISCSI_PARAM_FIRST_BURST)
+-#define ISCSI_MAX_BURST			(1ULL << ISCSI_PARAM_MAX_BURST)
+-#define ISCSI_PDU_INORDER_EN		(1ULL << ISCSI_PARAM_PDU_INORDER_EN)
+-#define ISCSI_DATASEQ_INORDER_EN	(1ULL << ISCSI_PARAM_DATASEQ_INORDER_EN)
+-#define ISCSI_ERL			(1ULL << ISCSI_PARAM_ERL)
+-#define ISCSI_IFMARKER_EN		(1ULL << ISCSI_PARAM_IFMARKER_EN)
+-#define ISCSI_OFMARKER_EN		(1ULL << ISCSI_PARAM_OFMARKER_EN)
+-#define ISCSI_EXP_STATSN		(1ULL << ISCSI_PARAM_EXP_STATSN)
+-#define ISCSI_TARGET_NAME		(1ULL << ISCSI_PARAM_TARGET_NAME)
+-#define ISCSI_TPGT			(1ULL << ISCSI_PARAM_TPGT)
+-#define ISCSI_PERSISTENT_ADDRESS	(1ULL << ISCSI_PARAM_PERSISTENT_ADDRESS)
+-#define ISCSI_PERSISTENT_PORT		(1ULL << ISCSI_PARAM_PERSISTENT_PORT)
+-#define ISCSI_SESS_RECOVERY_TMO		(1ULL << ISCSI_PARAM_SESS_RECOVERY_TMO)
+-#define ISCSI_CONN_PORT			(1ULL << ISCSI_PARAM_CONN_PORT)
+-#define ISCSI_CONN_ADDRESS		(1ULL << ISCSI_PARAM_CONN_ADDRESS)
+-#define ISCSI_USERNAME			(1ULL << ISCSI_PARAM_USERNAME)
+-#define ISCSI_USERNAME_IN		(1ULL << ISCSI_PARAM_USERNAME_IN)
+-#define ISCSI_PASSWORD			(1ULL << ISCSI_PARAM_PASSWORD)
+-#define ISCSI_PASSWORD_IN		(1ULL << ISCSI_PARAM_PASSWORD_IN)
+-#define ISCSI_FAST_ABORT		(1ULL << ISCSI_PARAM_FAST_ABORT)
+-#define ISCSI_ABORT_TMO			(1ULL << ISCSI_PARAM_ABORT_TMO)
+-#define ISCSI_LU_RESET_TMO		(1ULL << ISCSI_PARAM_LU_RESET_TMO)
+-#define ISCSI_HOST_RESET_TMO		(1ULL << ISCSI_PARAM_HOST_RESET_TMO)
+-#define ISCSI_PING_TMO			(1ULL << ISCSI_PARAM_PING_TMO)
+-#define ISCSI_RECV_TMO			(1ULL << ISCSI_PARAM_RECV_TMO)
+-#define ISCSI_IFACE_NAME		(1ULL << ISCSI_PARAM_IFACE_NAME)
+-#define ISCSI_ISID			(1ULL << ISCSI_PARAM_ISID)
+-#define ISCSI_INITIATOR_NAME		(1ULL << ISCSI_PARAM_INITIATOR_NAME)
+-#define ISCSI_TGT_RESET_TMO		(1ULL << ISCSI_PARAM_TGT_RESET_TMO)
+-#define ISCSI_TARGET_ALIAS		(1ULL << ISCSI_PARAM_TARGET_ALIAS)
+-
+ /* iSCSI HBA params */
+ enum iscsi_host_param {
+ 	ISCSI_HOST_PARAM_HWADDRESS,
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 8918329feaac..53eb93849377 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -86,7 +86,6 @@ struct iscsi_transport {
+ 	char *name;
+ 	unsigned int caps;
+ 	/* LLD sets this to indicate what values it can export to sysfs */
+-	uint64_t param_mask;
+ 	uint64_t host_param_mask;
+ 	uint64_t iface_param_mask;
+ 
+@@ -219,6 +218,9 @@ struct iscsi_cls_session {
+ #define iscsi_dev_to_session(_dev) \
+ 	container_of(_dev, struct iscsi_cls_session, dev)
+ 
++#define transport_class_to_session(_cdev) \
++	iscsi_dev_to_session(_cdev->parent)
++
+ #define iscsi_session_to_shost(_session) \
+ 	dev_to_shost(_session->dev.parent)
+ 

commit 3128c6c73cdf3df92c3165bfb785ae50114d18bf
+Author: Mike Christie 
+Date:   Mon Jul 25 13:48:42 2011 -0500
+
+    [SCSI] iscsi cls: sysfs group is_visible callout for conn attrs
+    
+    The iscsi class currently does not support writable sysfs
+    attrs for LLD sysfs settings. This patch converts the
+    iscsi class and drivers to use the attribute container
+    sysfs group and the sysfs group's is_visible callout
+    to be able to support readable or writable sysfs attrs.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 9c61b9c2c597..c716722628cf 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -632,6 +632,31 @@ iscsi_iser_ep_disconnect(struct iscsi_endpoint *ep)
+ 	iser_conn_terminate(ib_conn);
+ }
+ 
++static mode_t iser_attr_is_visible(int param_type, int param)
++{
++	switch (param_type) {
++	case ISCSI_PARAM:
++		switch (param) {
++		case ISCSI_PARAM_MAX_RECV_DLENGTH:
++		case ISCSI_PARAM_MAX_XMIT_DLENGTH:
++		case ISCSI_PARAM_HDRDGST_EN:
++		case ISCSI_PARAM_DATADGST_EN:
++		case ISCSI_PARAM_CONN_ADDRESS:
++		case ISCSI_PARAM_CONN_PORT:
++		case ISCSI_PARAM_EXP_STATSN:
++		case ISCSI_PARAM_PERSISTENT_ADDRESS:
++		case ISCSI_PARAM_PERSISTENT_PORT:
++		case ISCSI_PARAM_PING_TMO:
++		case ISCSI_PARAM_RECV_TMO:
++			return S_IRUGO;
++		default:
++			return 0;
++		}
++	}
++
++	return 0;
++}
++
+ static struct scsi_host_template iscsi_iser_sht = {
+ 	.module                 = THIS_MODULE,
+ 	.name                   = "iSCSI Initiator over iSER, v." DRV_VER,
+@@ -653,28 +678,18 @@ static struct iscsi_transport iscsi_iser_transport = {
+ 	.owner                  = THIS_MODULE,
+ 	.name                   = "iser",
+ 	.caps                   = CAP_RECOVERY_L0 | CAP_MULTI_R2T,
+-	.param_mask		= ISCSI_MAX_RECV_DLENGTH |
+-				  ISCSI_MAX_XMIT_DLENGTH |
+-				  ISCSI_HDRDGST_EN |
+-				  ISCSI_DATADGST_EN |
+-				  ISCSI_INITIAL_R2T_EN |
++	.param_mask		= ISCSI_INITIAL_R2T_EN |
+ 				  ISCSI_MAX_R2T |
+ 				  ISCSI_IMM_DATA_EN |
+ 				  ISCSI_FIRST_BURST |
+ 				  ISCSI_MAX_BURST |
+ 				  ISCSI_PDU_INORDER_EN |
+ 				  ISCSI_DATASEQ_INORDER_EN |
+-				  ISCSI_CONN_PORT |
+-				  ISCSI_CONN_ADDRESS |
+-				  ISCSI_EXP_STATSN |
+-				  ISCSI_PERSISTENT_PORT |
+-				  ISCSI_PERSISTENT_ADDRESS |
+ 				  ISCSI_TARGET_NAME | ISCSI_TPGT |
+ 				  ISCSI_USERNAME | ISCSI_PASSWORD |
+ 				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+ 				  ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+ 				  ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
+-				  ISCSI_PING_TMO | ISCSI_RECV_TMO |
+ 				  ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS |
+ 				  ISCSI_HOST_NETDEV_NAME |
+@@ -686,6 +701,7 @@ static struct iscsi_transport iscsi_iser_transport = {
+ 	.create_conn            = iscsi_iser_conn_create,
+ 	.bind_conn              = iscsi_iser_conn_bind,
+ 	.destroy_conn           = iscsi_iser_conn_destroy,
++	.attr_is_visible	= iser_attr_is_visible,
+ 	.set_param              = iscsi_iser_set_param,
+ 	.get_conn_param		= iscsi_conn_get_param,
+ 	.get_ep_param		= iscsi_iser_get_ep_param,
+diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
+index 3cad10605023..87b7ae1ef488 100644
+--- a/drivers/scsi/be2iscsi/be_iscsi.c
++++ b/drivers/scsi/be2iscsi/be_iscsi.c
+@@ -733,3 +733,28 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
+ 	beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid);
+ 	iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep);
+ }
++
++mode_t be2iscsi_attr_is_visible(int param_type, int param)
++{
++	switch (param_type) {
++	case ISCSI_PARAM:
++		switch (param) {
++		case ISCSI_PARAM_MAX_RECV_DLENGTH:
++		case ISCSI_PARAM_MAX_XMIT_DLENGTH:
++		case ISCSI_PARAM_HDRDGST_EN:
++		case ISCSI_PARAM_DATADGST_EN:
++		case ISCSI_PARAM_CONN_ADDRESS:
++		case ISCSI_PARAM_CONN_PORT:
++		case ISCSI_PARAM_EXP_STATSN:
++		case ISCSI_PARAM_PERSISTENT_ADDRESS:
++		case ISCSI_PARAM_PERSISTENT_PORT:
++		case ISCSI_PARAM_PING_TMO:
++		case ISCSI_PARAM_RECV_TMO:
++			return S_IRUGO;
++		default:
++			return 0;
++		}
++	}
++
++	return 0;
++}
+diff --git a/drivers/scsi/be2iscsi/be_iscsi.h b/drivers/scsi/be2iscsi/be_iscsi.h
+index ff60b7fd92d6..4a1f2e393f31 100644
+--- a/drivers/scsi/be2iscsi/be_iscsi.h
++++ b/drivers/scsi/be2iscsi/be_iscsi.h
+@@ -26,6 +26,8 @@
+ #define BE2_IPV4  0x1
+ #define BE2_IPV6  0x10
+ 
++mode_t be2iscsi_attr_is_visible(int param_type, int param);
++
+ void beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
+ 				struct beiscsi_offload_params *params);
+ 
+diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
+index 0a9bdfa3d939..d2a3e4a4d024 100644
+--- a/drivers/scsi/be2iscsi/be_main.c
++++ b/drivers/scsi/be2iscsi/be_main.c
+@@ -4364,10 +4364,7 @@ struct iscsi_transport beiscsi_iscsi_transport = {
+ 	.name = DRV_NAME,
+ 	.caps = CAP_RECOVERY_L0 | CAP_HDRDGST | CAP_TEXT_NEGO |
+ 		CAP_MULTI_R2T | CAP_DATADGST | CAP_DATA_PATH_OFFLOAD,
+-	.param_mask = ISCSI_MAX_RECV_DLENGTH |
+-		ISCSI_MAX_XMIT_DLENGTH |
+-		ISCSI_HDRDGST_EN |
+-		ISCSI_DATADGST_EN |
++	.param_mask =
+ 		ISCSI_INITIAL_R2T_EN |
+ 		ISCSI_MAX_R2T |
+ 		ISCSI_IMM_DATA_EN |
+@@ -4376,17 +4373,11 @@ struct iscsi_transport beiscsi_iscsi_transport = {
+ 		ISCSI_PDU_INORDER_EN |
+ 		ISCSI_DATASEQ_INORDER_EN |
+ 		ISCSI_ERL |
+-		ISCSI_CONN_PORT |
+-		ISCSI_CONN_ADDRESS |
+-		ISCSI_EXP_STATSN |
+-		ISCSI_PERSISTENT_PORT |
+-		ISCSI_PERSISTENT_ADDRESS |
+ 		ISCSI_TARGET_NAME | ISCSI_TPGT |
+ 		ISCSI_USERNAME | ISCSI_PASSWORD |
+ 		ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+ 		ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+ 		ISCSI_LU_RESET_TMO |
+-		ISCSI_PING_TMO | ISCSI_RECV_TMO |
+ 		ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
+ 	.host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+ 				ISCSI_HOST_INITIATOR_NAME,
+@@ -4395,6 +4386,7 @@ struct iscsi_transport beiscsi_iscsi_transport = {
+ 	.create_conn = beiscsi_conn_create,
+ 	.bind_conn = beiscsi_conn_bind,
+ 	.destroy_conn = iscsi_conn_teardown,
++	.attr_is_visible = be2iscsi_attr_is_visible,
+ 	.set_param = beiscsi_set_param,
+ 	.get_conn_param = iscsi_conn_get_param,
+ 	.get_session_param = iscsi_session_get_param,
+diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
+index cffd4d75df56..2d529c9fa1ad 100644
+--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
++++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
+@@ -2177,6 +2177,30 @@ static int bnx2i_nl_set_path(struct Scsi_Host *shost, struct iscsi_path *params)
+ 	return 0;
+ }
+ 
++static mode_t bnx2i_attr_is_visible(int param_type, int param)
++{
++	switch (param_type) {
++	case ISCSI_PARAM:
++		switch (param) {
++		case ISCSI_PARAM_MAX_RECV_DLENGTH:
++		case ISCSI_PARAM_MAX_XMIT_DLENGTH:
++		case ISCSI_PARAM_HDRDGST_EN:
++		case ISCSI_PARAM_DATADGST_EN:
++		case ISCSI_PARAM_CONN_ADDRESS:
++		case ISCSI_PARAM_CONN_PORT:
++		case ISCSI_PARAM_EXP_STATSN:
++		case ISCSI_PARAM_PERSISTENT_ADDRESS:
++		case ISCSI_PARAM_PERSISTENT_PORT:
++		case ISCSI_PARAM_PING_TMO:
++		case ISCSI_PARAM_RECV_TMO:
++			return S_IRUGO;
++		default:
++			return 0;
++		}
++	}
++
++	return 0;
++}
+ 
+ /*
+  * 'Scsi_Host_Template' structure and 'iscsi_tranport' structure template
+@@ -2207,11 +2231,7 @@ struct iscsi_transport bnx2i_iscsi_transport = {
+ 				  CAP_MULTI_R2T | CAP_DATADGST |
+ 				  CAP_DATA_PATH_OFFLOAD |
+ 				  CAP_TEXT_NEGO,
+-	.param_mask		= ISCSI_MAX_RECV_DLENGTH |
+-				  ISCSI_MAX_XMIT_DLENGTH |
+-				  ISCSI_HDRDGST_EN |
+-				  ISCSI_DATADGST_EN |
+-				  ISCSI_INITIAL_R2T_EN |
++	.param_mask		= ISCSI_INITIAL_R2T_EN |
+ 				  ISCSI_MAX_R2T |
+ 				  ISCSI_IMM_DATA_EN |
+ 				  ISCSI_FIRST_BURST |
+@@ -2219,17 +2239,11 @@ struct iscsi_transport bnx2i_iscsi_transport = {
+ 				  ISCSI_PDU_INORDER_EN |
+ 				  ISCSI_DATASEQ_INORDER_EN |
+ 				  ISCSI_ERL |
+-				  ISCSI_CONN_PORT |
+-				  ISCSI_CONN_ADDRESS |
+-				  ISCSI_EXP_STATSN |
+-				  ISCSI_PERSISTENT_PORT |
+-				  ISCSI_PERSISTENT_ADDRESS |
+ 				  ISCSI_TARGET_NAME | ISCSI_TPGT |
+ 				  ISCSI_USERNAME | ISCSI_PASSWORD |
+ 				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+ 				  ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+ 				  ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
+-				  ISCSI_PING_TMO | ISCSI_RECV_TMO |
+ 				  ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+ 				  ISCSI_HOST_NETDEV_NAME,
+@@ -2238,6 +2252,7 @@ struct iscsi_transport bnx2i_iscsi_transport = {
+ 	.create_conn		= bnx2i_conn_create,
+ 	.bind_conn		= bnx2i_conn_bind,
+ 	.destroy_conn		= bnx2i_conn_destroy,
++	.attr_is_visible	= bnx2i_attr_is_visible,
+ 	.set_param		= iscsi_set_param,
+ 	.get_conn_param		= iscsi_conn_get_param,
+ 	.get_session_param	= iscsi_session_get_param,
+diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
+index bd22041e2789..c13b3f0a4f03 100644
+--- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
++++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
+@@ -106,25 +106,21 @@ static struct iscsi_transport cxgb3i_iscsi_transport = {
+ 	.caps		= CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST
+ 				| CAP_DATADGST | CAP_DIGEST_OFFLOAD |
+ 				CAP_PADDING_OFFLOAD | CAP_TEXT_NEGO,
+-	.param_mask	= ISCSI_MAX_RECV_DLENGTH | ISCSI_MAX_XMIT_DLENGTH |
+-				ISCSI_HDRDGST_EN | ISCSI_DATADGST_EN |
++	.param_mask	=
+ 				ISCSI_INITIAL_R2T_EN | ISCSI_MAX_R2T |
+ 				ISCSI_IMM_DATA_EN | ISCSI_FIRST_BURST |
+ 				ISCSI_MAX_BURST | ISCSI_PDU_INORDER_EN |
+ 				ISCSI_DATASEQ_INORDER_EN | ISCSI_ERL |
+-				ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS |
+-				ISCSI_EXP_STATSN | ISCSI_PERSISTENT_PORT |
+-				ISCSI_PERSISTENT_ADDRESS |
+ 				ISCSI_TARGET_NAME | ISCSI_TPGT |
+ 				ISCSI_USERNAME | ISCSI_PASSWORD |
+ 				ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+ 				ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+ 				ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
+-				ISCSI_PING_TMO | ISCSI_RECV_TMO |
+ 				ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+ 				ISCSI_HOST_INITIATOR_NAME |
+ 				ISCSI_HOST_NETDEV_NAME,
++	.attr_is_visible	= cxgbi_attr_is_visible,
+ 	.get_host_param	= cxgbi_get_host_param,
+ 	.set_host_param	= cxgbi_set_host_param,
+ 	/* session management */
+diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+index ae13c4993aa3..89fca4b0787c 100644
+--- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
++++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+@@ -107,25 +107,21 @@ static struct iscsi_transport cxgb4i_iscsi_transport = {
+ 	.caps		= CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST |
+ 				CAP_DATADGST | CAP_DIGEST_OFFLOAD |
+ 				CAP_PADDING_OFFLOAD | CAP_TEXT_NEGO,
+-	.param_mask	= ISCSI_MAX_RECV_DLENGTH | ISCSI_MAX_XMIT_DLENGTH |
+-				ISCSI_HDRDGST_EN | ISCSI_DATADGST_EN |
++	.param_mask	=
+ 				ISCSI_INITIAL_R2T_EN | ISCSI_MAX_R2T |
+ 				ISCSI_IMM_DATA_EN | ISCSI_FIRST_BURST |
+ 				ISCSI_MAX_BURST | ISCSI_PDU_INORDER_EN |
+ 				ISCSI_DATASEQ_INORDER_EN | ISCSI_ERL |
+-				ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS |
+-				ISCSI_EXP_STATSN | ISCSI_PERSISTENT_PORT |
+-				ISCSI_PERSISTENT_ADDRESS |
+ 				ISCSI_TARGET_NAME | ISCSI_TPGT |
+ 				ISCSI_USERNAME | ISCSI_PASSWORD |
+ 				ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+ 				ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+ 				ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
+-				ISCSI_PING_TMO | ISCSI_RECV_TMO |
+ 				ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+ 				ISCSI_HOST_INITIATOR_NAME |
+ 				ISCSI_HOST_NETDEV_NAME,
++	.attr_is_visible	= cxgbi_attr_is_visible,
+ 	.get_host_param	= cxgbi_get_host_param,
+ 	.set_host_param	= cxgbi_set_host_param,
+ 	/* session management */
+diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c
+index 77ac217ad5ce..e5f4f968ed7b 100644
+--- a/drivers/scsi/cxgbi/libcxgbi.c
++++ b/drivers/scsi/cxgbi/libcxgbi.c
+@@ -2566,6 +2566,32 @@ void cxgbi_iscsi_cleanup(struct iscsi_transport *itp,
+ }
+ EXPORT_SYMBOL_GPL(cxgbi_iscsi_cleanup);
+ 
++mode_t cxgbi_attr_is_visible(int param_type, int param)
++{
++	switch (param_type) {
++	case ISCSI_PARAM:
++		switch (param) {
++		case ISCSI_PARAM_MAX_RECV_DLENGTH:
++		case ISCSI_PARAM_MAX_XMIT_DLENGTH:
++		case ISCSI_PARAM_HDRDGST_EN:
++		case ISCSI_PARAM_DATADGST_EN:
++		case ISCSI_PARAM_CONN_ADDRESS:
++		case ISCSI_PARAM_CONN_PORT:
++		case ISCSI_PARAM_EXP_STATSN:
++		case ISCSI_PARAM_PERSISTENT_ADDRESS:
++		case ISCSI_PARAM_PERSISTENT_PORT:
++		case ISCSI_PARAM_PING_TMO:
++		case ISCSI_PARAM_RECV_TMO:
++			return S_IRUGO;
++		default:
++			return 0;
++		}
++	}
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(cxgbi_attr_is_visible);
++
+ static int __init libcxgbi_init_module(void)
+ {
+ 	sw_tag_idx_bits = (__ilog2_u32(ISCSI_ITT_MASK)) + 1;
+diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h
+index 9267844519c9..5d453a0dba1f 100644
+--- a/drivers/scsi/cxgbi/libcxgbi.h
++++ b/drivers/scsi/cxgbi/libcxgbi.h
+@@ -709,6 +709,7 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *);
+ 
+ void cxgbi_cleanup_task(struct iscsi_task *task);
+ 
++mode_t cxgbi_attr_is_visible(int param_type, int param);
+ void cxgbi_get_conn_stats(struct iscsi_cls_conn *, struct iscsi_stats *);
+ int cxgbi_set_conn_param(struct iscsi_cls_conn *,
+ 			enum iscsi_param, char *, int);
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 7724414588fa..1dcb4d183bc9 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -872,6 +872,31 @@ static void iscsi_sw_tcp_session_destroy(struct iscsi_cls_session *cls_session)
+ 	iscsi_host_free(shost);
+ }
+ 
++static mode_t iscsi_sw_tcp_attr_is_visible(int param_type, int param)
++{
++	switch (param_type) {
++	case ISCSI_PARAM:
++		switch (param) {
++		case ISCSI_PARAM_MAX_RECV_DLENGTH:
++		case ISCSI_PARAM_MAX_XMIT_DLENGTH:
++		case ISCSI_PARAM_HDRDGST_EN:
++		case ISCSI_PARAM_DATADGST_EN:
++		case ISCSI_PARAM_CONN_ADDRESS:
++		case ISCSI_PARAM_CONN_PORT:
++		case ISCSI_PARAM_EXP_STATSN:
++		case ISCSI_PARAM_PERSISTENT_ADDRESS:
++		case ISCSI_PARAM_PERSISTENT_PORT:
++		case ISCSI_PARAM_PING_TMO:
++		case ISCSI_PARAM_RECV_TMO:
++			return S_IRUGO;
++		default:
++			return 0;
++		}
++	}
++
++	return 0;
++}
++
+ static int iscsi_sw_tcp_slave_alloc(struct scsi_device *sdev)
+ {
+ 	set_bit(QUEUE_FLAG_BIDI, &sdev->request_queue->queue_flags);
+@@ -910,11 +935,7 @@ static struct iscsi_transport iscsi_sw_tcp_transport = {
+ 	.name			= "tcp",
+ 	.caps			= CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST
+ 				  | CAP_DATADGST,
+-	.param_mask		= ISCSI_MAX_RECV_DLENGTH |
+-				  ISCSI_MAX_XMIT_DLENGTH |
+-				  ISCSI_HDRDGST_EN |
+-				  ISCSI_DATADGST_EN |
+-				  ISCSI_INITIAL_R2T_EN |
++	.param_mask		= ISCSI_INITIAL_R2T_EN |
+ 				  ISCSI_MAX_R2T |
+ 				  ISCSI_IMM_DATA_EN |
+ 				  ISCSI_FIRST_BURST |
+@@ -922,17 +943,11 @@ static struct iscsi_transport iscsi_sw_tcp_transport = {
+ 				  ISCSI_PDU_INORDER_EN |
+ 				  ISCSI_DATASEQ_INORDER_EN |
+ 				  ISCSI_ERL |
+-				  ISCSI_CONN_PORT |
+-				  ISCSI_CONN_ADDRESS |
+-				  ISCSI_EXP_STATSN |
+-				  ISCSI_PERSISTENT_PORT |
+-				  ISCSI_PERSISTENT_ADDRESS |
+ 				  ISCSI_TARGET_NAME | ISCSI_TPGT |
+ 				  ISCSI_USERNAME | ISCSI_PASSWORD |
+ 				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+ 				  ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+ 				  ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
+-				  ISCSI_PING_TMO | ISCSI_RECV_TMO |
+ 				  ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+ 				  ISCSI_HOST_INITIATOR_NAME |
+@@ -944,6 +959,7 @@ static struct iscsi_transport iscsi_sw_tcp_transport = {
+ 	.create_conn		= iscsi_sw_tcp_conn_create,
+ 	.bind_conn		= iscsi_sw_tcp_conn_bind,
+ 	.destroy_conn		= iscsi_sw_tcp_conn_destroy,
++	.attr_is_visible	= iscsi_sw_tcp_attr_is_visible,
+ 	.set_param		= iscsi_sw_tcp_conn_set_param,
+ 	.get_conn_param		= iscsi_sw_tcp_conn_get_param,
+ 	.get_session_param	= iscsi_session_get_param,
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index 32df0c5fc9cc..f8a1506cb76a 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -100,6 +100,7 @@ static int qla4xxx_slave_alloc(struct scsi_device *device);
+ static int qla4xxx_slave_configure(struct scsi_device *device);
+ static void qla4xxx_slave_destroy(struct scsi_device *sdev);
+ static void qla4xxx_scan_start(struct Scsi_Host *shost);
++static mode_t ql4_attr_is_visible(int param_type, int param);
+ 
+ static struct qla4_8xxx_legacy_intr_set legacy_intr[] =
+     QLA82XX_LEGACY_INTR_CONFIG;
+@@ -137,8 +138,7 @@ static struct iscsi_transport qla4xxx_iscsi_transport = {
+ 	.name			= DRIVER_NAME,
+ 	.caps			= CAP_FW_DB | CAP_SENDTARGETS_OFFLOAD |
+ 				  CAP_DATA_PATH_OFFLOAD,
+-	.param_mask		= ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS |
+-				  ISCSI_TARGET_NAME | ISCSI_TPGT |
++	.param_mask		= ISCSI_TARGET_NAME | ISCSI_TPGT |
+ 				  ISCSI_TARGET_ALIAS,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS |
+ 				  ISCSI_HOST_IPADDRESS |
+@@ -155,6 +155,7 @@ static struct iscsi_transport qla4xxx_iscsi_transport = {
+ 				  ISCSI_NET_IPV6_LINKLOCAL_AUTOCFG |
+ 				  ISCSI_NET_IFACE_ENABLE,
+ 	.tgt_dscvr		= qla4xxx_tgt_dscvr,
++	.attr_is_visible	= ql4_attr_is_visible,
+ 	.get_conn_param		= qla4xxx_conn_get_param,
+ 	.get_session_param	= qla4xxx_sess_get_param,
+ 	.get_host_param		= qla4xxx_host_get_param,
+@@ -165,6 +166,22 @@ static struct iscsi_transport qla4xxx_iscsi_transport = {
+ 
+ static struct scsi_transport_template *qla4xxx_scsi_transport;
+ 
++static mode_t ql4_attr_is_visible(int param_type, int param)
++{
++	switch (param_type) {
++	case ISCSI_PARAM:
++		switch (param) {
++		case ISCSI_PARAM_CONN_ADDRESS:
++		case ISCSI_PARAM_CONN_PORT:
++			return S_IRUGO;
++		default:
++			return 0;
++		}
++	}
++
++	return 0;
++}
++
+ static int qla4xxx_get_iface_param(struct iscsi_iface *iface,
+ 				   enum iscsi_param_type param_type,
+ 				   int param, char *buf)
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 4d5e64f429e7..e9eca98e1102 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -78,7 +78,6 @@ struct iscsi_internal {
+ 
+ 	struct device_attribute *host_attrs[ISCSI_HOST_ATTRS + 1];
+ 	struct transport_container conn_cont;
+-	struct device_attribute *conn_attrs[ISCSI_CONN_ATTRS + 1];
+ 	struct transport_container session_cont;
+ 	struct device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1];
+ };
+@@ -2030,6 +2029,70 @@ static ISCSI_CLASS_ATTR(conn, field, S_IRUGO,				\
+ iscsi_conn_ep_attr(address, ISCSI_PARAM_CONN_ADDRESS);
+ iscsi_conn_ep_attr(port, ISCSI_PARAM_CONN_PORT);
+ 
++static struct attribute *iscsi_conn_attrs[] = {
++	&dev_attr_conn_max_recv_dlength.attr,
++	&dev_attr_conn_max_xmit_dlength.attr,
++	&dev_attr_conn_header_digest.attr,
++	&dev_attr_conn_data_digest.attr,
++	&dev_attr_conn_ifmarker.attr,
++	&dev_attr_conn_ofmarker.attr,
++	&dev_attr_conn_address.attr,
++	&dev_attr_conn_port.attr,
++	&dev_attr_conn_exp_statsn.attr,
++	&dev_attr_conn_persistent_address.attr,
++	&dev_attr_conn_persistent_port.attr,
++	&dev_attr_conn_ping_tmo.attr,
++	&dev_attr_conn_recv_tmo.attr,
++	NULL,
++};
++
++static mode_t iscsi_conn_attr_is_visible(struct kobject *kobj,
++					 struct attribute *attr, int i)
++{
++	struct device *cdev = container_of(kobj, struct device, kobj);
++	struct iscsi_cls_conn *conn = transport_class_to_conn(cdev);
++	struct iscsi_transport *t = conn->transport;
++	int param;
++
++	if (attr == &dev_attr_conn_max_recv_dlength.attr)
++		param = ISCSI_PARAM_MAX_RECV_DLENGTH;
++	else if (attr == &dev_attr_conn_max_xmit_dlength.attr)
++		param = ISCSI_PARAM_MAX_XMIT_DLENGTH;
++	else if (attr == &dev_attr_conn_header_digest.attr)
++		param = ISCSI_PARAM_HDRDGST_EN;
++	else if (attr == &dev_attr_conn_data_digest.attr)
++		param = ISCSI_PARAM_DATADGST_EN;
++	else if (attr == &dev_attr_conn_ifmarker.attr)
++		param = ISCSI_PARAM_IFMARKER_EN;
++	else if (attr == &dev_attr_conn_ofmarker.attr)
++		param = ISCSI_PARAM_OFMARKER_EN;
++	else if (attr == &dev_attr_conn_address.attr)
++		param = ISCSI_PARAM_CONN_ADDRESS;
++	else if (attr == &dev_attr_conn_port.attr)
++		param = ISCSI_PARAM_CONN_PORT;
++	else if (attr == &dev_attr_conn_exp_statsn.attr)
++		param = ISCSI_PARAM_EXP_STATSN;
++	else if (attr == &dev_attr_conn_persistent_address.attr)
++		param = ISCSI_PARAM_PERSISTENT_ADDRESS;
++	else if (attr == &dev_attr_conn_persistent_port.attr)
++		param = ISCSI_PARAM_PERSISTENT_PORT;
++	else if (attr == &dev_attr_conn_ping_tmo.attr)
++		param = ISCSI_PARAM_PING_TMO;
++	else if (attr == &dev_attr_conn_recv_tmo.attr)
++		param = ISCSI_PARAM_RECV_TMO;
++	else {
++		WARN_ONCE(1, "Invalid conn attr");
++		return 0;
++	}
++
++	return t->attr_is_visible(ISCSI_PARAM, param);
++}
++
++static struct attribute_group iscsi_conn_group = {
++	.attrs = iscsi_conn_attrs,
++	.is_visible = iscsi_conn_attr_is_visible,
++};
++
+ /*
+  * iSCSI session attrs
+  */
+@@ -2171,14 +2234,6 @@ do {									\
+ 	}								\
+ } while (0)
+ 
+-#define SETUP_CONN_RD_ATTR(field, param_flag)				\
+-do {									\
+-	if (tt->param_mask & param_flag) {				\
+-		priv->conn_attrs[count] = &dev_attr_conn_##field; \
+-		count++;						\
+-	}								\
+-} while (0)
+-
+ #define SETUP_HOST_RD_ATTR(field, param_flag)				\
+ do {									\
+ 	if (tt->host_param_mask & param_flag) {				\
+@@ -2299,29 +2354,11 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 	count = 0;
+ 
+ 	/* connection parameters */
+-	priv->conn_cont.ac.attrs = &priv->conn_attrs[0];
+ 	priv->conn_cont.ac.class = &iscsi_connection_class.class;
+ 	priv->conn_cont.ac.match = iscsi_conn_match;
++	priv->conn_cont.ac.grp = &iscsi_conn_group;
+ 	transport_container_register(&priv->conn_cont);
+ 
+-	SETUP_CONN_RD_ATTR(max_recv_dlength, ISCSI_MAX_RECV_DLENGTH);
+-	SETUP_CONN_RD_ATTR(max_xmit_dlength, ISCSI_MAX_XMIT_DLENGTH);
+-	SETUP_CONN_RD_ATTR(header_digest, ISCSI_HDRDGST_EN);
+-	SETUP_CONN_RD_ATTR(data_digest, ISCSI_DATADGST_EN);
+-	SETUP_CONN_RD_ATTR(ifmarker, ISCSI_IFMARKER_EN);
+-	SETUP_CONN_RD_ATTR(ofmarker, ISCSI_OFMARKER_EN);
+-	SETUP_CONN_RD_ATTR(address, ISCSI_CONN_ADDRESS);
+-	SETUP_CONN_RD_ATTR(port, ISCSI_CONN_PORT);
+-	SETUP_CONN_RD_ATTR(exp_statsn, ISCSI_EXP_STATSN);
+-	SETUP_CONN_RD_ATTR(persistent_address, ISCSI_PERSISTENT_ADDRESS);
+-	SETUP_CONN_RD_ATTR(persistent_port, ISCSI_PERSISTENT_PORT);
+-	SETUP_CONN_RD_ATTR(ping_tmo, ISCSI_PING_TMO);
+-	SETUP_CONN_RD_ATTR(recv_tmo, ISCSI_RECV_TMO);
+-
+-	BUG_ON(count > ISCSI_CONN_ATTRS);
+-	priv->conn_attrs[count] = NULL;
+-	count = 0;
+-
+ 	/* session parameters */
+ 	priv->session_cont.ac.attrs = &priv->session_attrs[0];
+ 	priv->session_cont.ac.class = &iscsi_session_class.class;
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index e1f210a173a5..8918329feaac 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -144,8 +144,10 @@ struct iscsi_transport {
+ 	int (*get_iface_param) (struct iscsi_iface *iface,
+ 				enum iscsi_param_type param_type,
+ 				int param, char *buf);
++	mode_t (*attr_is_visible)(int param_type, int param);
+ };
+ 
++
+ /*
+  * transport registration upcalls
+  */
+@@ -178,6 +180,9 @@ struct iscsi_cls_conn {
+ #define iscsi_dev_to_conn(_dev) \
+ 	container_of(_dev, struct iscsi_cls_conn, dev)
+ 
++#define transport_class_to_conn(_cdev) \
++	iscsi_dev_to_conn(_cdev->parent)
++
+ #define iscsi_conn_to_session(_conn) \
+ 	iscsi_dev_to_session(_conn->dev.parent)
+ 

commit 8d07913dbe79568eafe5bb73806a08aac294d4e6
+Author: Mike Christie 
+Date:   Mon Jul 25 13:48:40 2011 -0500
+
+    [SCSI] iscsi class: add iface representation
+    
+    A iscsi host can have multiple interfaces. This patch
+    adds a new iface iscsi class for this. It exports the
+    network settings now, and will be extended to also
+    export iscsi initiator port settings like the isid
+    and initiator name for drivers that can support multiple
+    initiator ports.
+    
+    Based on patch from Lalit Chandivade.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 212a8d846748..4d5e64f429e7 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -270,6 +270,185 @@ struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint);
+ 
++/*
++ * Interface to display network param to sysfs
++ */
++
++static void iscsi_iface_release(struct device *dev)
++{
++	struct iscsi_iface *iface = iscsi_dev_to_iface(dev);
++	struct device *parent = iface->dev.parent;
++
++	kfree(iface);
++	put_device(parent);
++}
++
++
++static struct class iscsi_iface_class = {
++	.name = "iscsi_iface",
++	.dev_release = iscsi_iface_release,
++};
++
++#define ISCSI_IFACE_ATTR(_prefix, _name, _mode, _show, _store)	\
++struct device_attribute dev_attr_##_prefix##_##_name =		\
++	__ATTR(_name, _mode, _show, _store)
++
++/* iface attrs show */
++#define iscsi_iface_attr_show(type, name, param_type, param)		\
++static ssize_t								\
++show_##type##_##name(struct device *dev, struct device_attribute *attr,	\
++		     char *buf)						\
++{									\
++	struct iscsi_iface *iface = iscsi_dev_to_iface(dev);		\
++	struct iscsi_transport *t = iface->transport;			\
++	return t->get_iface_param(iface, param_type, param, buf);	\
++}									\
++
++#define iscsi_iface_net_attr(type, name, param)				\
++	iscsi_iface_attr_show(type, name, ISCSI_NET_PARAM, param)	\
++static ISCSI_IFACE_ATTR(type, name, S_IRUGO, show_##type##_##name, NULL);
++
++/* generic read only ipvi4 attribute */
++iscsi_iface_net_attr(ipv4_iface, ipaddress, ISCSI_NET_PARAM_IPV4_ADDR);
++iscsi_iface_net_attr(ipv4_iface, gateway, ISCSI_NET_PARAM_IPV4_GW);
++iscsi_iface_net_attr(ipv4_iface, subnet, ISCSI_NET_PARAM_IPV4_SUBNET);
++iscsi_iface_net_attr(ipv4_iface, bootproto, ISCSI_NET_PARAM_IPV4_BOOTPROTO);
++
++/* generic read only ipv6 attribute */
++iscsi_iface_net_attr(ipv6_iface, ipaddress, ISCSI_NET_PARAM_IPV6_ADDR);
++iscsi_iface_net_attr(ipv6_iface, link_local_addr, ISCSI_NET_PARAM_IPV6_LINKLOCAL);
++iscsi_iface_net_attr(ipv6_iface, router_addr, ISCSI_NET_PARAM_IPV6_ROUTER);
++iscsi_iface_net_attr(ipv6_iface, ipaddr_autocfg,
++		     ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG);
++iscsi_iface_net_attr(ipv6_iface, linklocal_autocfg,
++		     ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG);
++
++/* common read only iface attribute */
++iscsi_iface_net_attr(iface, enabled, ISCSI_NET_PARAM_IFACE_ENABLE);
++iscsi_iface_net_attr(iface, vlan, ISCSI_NET_PARAM_VLAN_ID);
++
++static mode_t iscsi_iface_attr_is_visible(struct kobject *kobj,
++					  struct attribute *attr, int i)
++{
++	struct device *dev = container_of(kobj, struct device, kobj);
++	struct iscsi_iface *iface = iscsi_dev_to_iface(dev);
++	struct iscsi_transport *t = iface->transport;
++
++	if (attr == &dev_attr_iface_enabled.attr)
++		return (t->iface_param_mask & ISCSI_NET_IFACE_ENABLE) ?
++								S_IRUGO : 0;
++	else if (attr == &dev_attr_iface_vlan.attr)
++		return (t->iface_param_mask & ISCSI_NET_VLAN_ID) ? S_IRUGO : 0;
++
++	if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) {
++		if (attr == &dev_attr_ipv4_iface_ipaddress.attr)
++			return (t->iface_param_mask & ISCSI_NET_IPV4_ADDR) ?
++								S_IRUGO : 0;
++		else if (attr == &dev_attr_ipv4_iface_gateway.attr)
++			return (t->iface_param_mask & ISCSI_NET_IPV4_GW) ?
++								S_IRUGO : 0;
++		else if (attr == &dev_attr_ipv4_iface_subnet.attr)
++			return (t->iface_param_mask & ISCSI_NET_IPV4_SUBNET) ?
++								S_IRUGO : 0;
++		else if (attr == &dev_attr_ipv4_iface_bootproto.attr)
++			return (t->iface_param_mask & ISCSI_NET_IPV4_BOOTPROTO) ?
++								 S_IRUGO : 0;
++	} else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) {
++		if (attr == &dev_attr_ipv6_iface_ipaddress.attr)
++			return (t->iface_param_mask & ISCSI_NET_IPV6_ADDR) ?
++								S_IRUGO : 0;
++		else if (attr == &dev_attr_ipv6_iface_link_local_addr.attr)
++			return (t->iface_param_mask & ISCSI_NET_IPV6_LINKLOCAL) ?
++								S_IRUGO : 0;
++		else if (attr == &dev_attr_ipv6_iface_router_addr.attr)
++			return (t->iface_param_mask & ISCSI_NET_IPV6_ROUTER) ?
++								S_IRUGO : 0;
++		else if (attr == &dev_attr_ipv6_iface_ipaddr_autocfg.attr)
++			return (t->iface_param_mask & ISCSI_NET_IPV6_ADDR_AUTOCFG) ?
++								S_IRUGO : 0;
++		else if (attr == &dev_attr_ipv6_iface_linklocal_autocfg.attr)
++			return (t->iface_param_mask & ISCSI_NET_IPV6_LINKLOCAL_AUTOCFG) ?
++								S_IRUGO : 0;
++	}
++
++	return 0;
++}
++
++static struct attribute *iscsi_iface_attrs[] = {
++	&dev_attr_iface_enabled.attr,
++	&dev_attr_iface_vlan.attr,
++	&dev_attr_ipv4_iface_ipaddress.attr,
++	&dev_attr_ipv4_iface_gateway.attr,
++	&dev_attr_ipv4_iface_subnet.attr,
++	&dev_attr_ipv4_iface_bootproto.attr,
++	&dev_attr_ipv6_iface_ipaddress.attr,
++	&dev_attr_ipv6_iface_link_local_addr.attr,
++	&dev_attr_ipv6_iface_router_addr.attr,
++	&dev_attr_ipv6_iface_ipaddr_autocfg.attr,
++	&dev_attr_ipv6_iface_linklocal_autocfg.attr,
++	NULL,
++};
++
++static struct attribute_group iscsi_iface_group = {
++	.attrs = iscsi_iface_attrs,
++	.is_visible = iscsi_iface_attr_is_visible,
++};
++
++struct iscsi_iface *
++iscsi_create_iface(struct Scsi_Host *shost, struct iscsi_transport *transport,
++		   uint32_t iface_type, uint32_t iface_num, int dd_size)
++{
++	struct iscsi_iface *iface;
++	int err;
++
++	iface = kzalloc(sizeof(*iface) + dd_size, GFP_KERNEL);
++	if (!iface)
++		return NULL;
++
++	iface->transport = transport;
++	iface->iface_type = iface_type;
++	iface->iface_num = iface_num;
++	iface->dev.release = iscsi_iface_release;
++	iface->dev.class = &iscsi_iface_class;
++	/* parent reference released in iscsi_iface_release */
++	iface->dev.parent = get_device(&shost->shost_gendev);
++	if (iface_type == ISCSI_IFACE_TYPE_IPV4)
++		dev_set_name(&iface->dev, "ipv4-iface-%u-%u", shost->host_no,
++			     iface_num);
++	else
++		dev_set_name(&iface->dev, "ipv6-iface-%u-%u", shost->host_no,
++			     iface_num);
++
++	err = device_register(&iface->dev);
++	if (err)
++		goto free_iface;
++
++	err = sysfs_create_group(&iface->dev.kobj, &iscsi_iface_group);
++	if (err)
++		goto unreg_iface;
++
++	if (dd_size)
++		iface->dd_data = &iface[1];
++	return iface;
++
++unreg_iface:
++	device_unregister(&iface->dev);
++	return NULL;
++
++free_iface:
++	put_device(iface->dev.parent);
++	kfree(iface);
++	return NULL;
++}
++EXPORT_SYMBOL_GPL(iscsi_create_iface);
++
++void iscsi_destroy_iface(struct iscsi_iface *iface)
++{
++	sysfs_remove_group(&iface->dev.kobj, &iscsi_iface_group);
++	device_unregister(&iface->dev);
++}
++EXPORT_SYMBOL_GPL(iscsi_destroy_iface);
++
+ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+ 			    struct device *cdev)
+ {
+@@ -2175,6 +2354,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 
+ 	BUG_ON(count > ISCSI_SESSION_ATTRS);
+ 	priv->session_attrs[count] = NULL;
++	count = 0;
+ 
+ 	spin_lock_irqsave(&iscsi_transport_lock, flags);
+ 	list_add(&priv->list, &iscsi_transports);
+@@ -2237,10 +2417,14 @@ static __init int iscsi_transport_init(void)
+ 	if (err)
+ 		goto unregister_transport_class;
+ 
+-	err = transport_class_register(&iscsi_host_class);
++	err = class_register(&iscsi_iface_class);
+ 	if (err)
+ 		goto unregister_endpoint_class;
+ 
++	err = transport_class_register(&iscsi_host_class);
++	if (err)
++		goto unregister_iface_class;
++
+ 	err = transport_class_register(&iscsi_connection_class);
+ 	if (err)
+ 		goto unregister_host_class;
+@@ -2270,6 +2454,8 @@ static __init int iscsi_transport_init(void)
+ 	transport_class_unregister(&iscsi_connection_class);
+ unregister_host_class:
+ 	transport_class_unregister(&iscsi_host_class);
++unregister_iface_class:
++	class_unregister(&iscsi_iface_class);
+ unregister_endpoint_class:
+ 	class_unregister(&iscsi_endpoint_class);
+ unregister_transport_class:
+@@ -2285,6 +2471,7 @@ static void __exit iscsi_transport_exit(void)
+ 	transport_class_unregister(&iscsi_session_class);
+ 	transport_class_unregister(&iscsi_host_class);
+ 	class_unregister(&iscsi_endpoint_class);
++	class_unregister(&iscsi_iface_class);
+ 	class_unregister(&iscsi_transport_class);
+ }
+ 
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index e93831e87878..a563753d578b 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -296,10 +296,27 @@ enum iscsi_net_param {
+ 	ISCSI_NET_PARAM_IPV6_ROUTER_AUTOCFG	= 11,
+ 	ISCSI_NET_PARAM_IFACE_ENABLE		= 12,
+ 	ISCSI_NET_PARAM_VLAN_ID			= 13,
+-	ISCSI_NET_IFACE_TYPE			= 14,
+-	ISCSI_NET_IFACE_NAME			= 15,
++	ISCSI_NET_PARAM_IFACE_TYPE		= 14,
++	ISCSI_NET_PARAM_IFACE_NAME		= 15,
+ };
+ 
++#define ISCSI_NET_IPV4_ADDR		(1ULL << ISCSI_NET_PARAM_IPV4_ADDR)
++#define ISCSI_NET_IPV4_SUBNET		(1ULL << ISCSI_NET_PARAM_IPV4_SUBNET)
++#define ISCSI_NET_IPV4_GW		(1ULL << ISCSI_NET_PARAM_IPV4_GW)
++#define ISCSI_NET_IPV4_BOOTPROTO	(1ULL << ISCSI_NET_PARAM_IPV4_BOOTPROTO)
++#define ISCSI_NET_MAC			(1ULL << ISCSI_NET_PARAM_MAC)
++#define ISCSI_NET_IPV6_LINKLOCAL	(1ULL << ISCSI_NET_PARAM_IPV6_LINKLOCAL)
++#define ISCSI_NET_IPV6_ADDR		(1ULL << ISCSI_NET_PARAM_IPV6_ADDR)
++#define ISCSI_NET_IPV6_ROUTER		(1ULL << ISCSI_NET_PARAM_IPV6_ROUTER)
++#define ISCSI_NET_IPV6_ADDR_AUTOCFG		\
++				(1ULL << ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG)
++#define ISCSI_NET_IPV6_LINKLOCAL_AUTOCFG	\
++				(1ULL << ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG)
++#define ISCSI_NET_IPV6_ROUTER_AUTOCFG		\
++                               (1ULL << ISCSI_NET_PARAM_IPV6_ROUTER_AUTOCFG)
++#define ISCSI_NET_IFACE_ENABLE		(1ULL << ISCSI_NET_PARAM_IFACE_ENABLE)
++#define ISCSI_NET_VLAN_ID			(1ULL << ISCSI_NET_PARAM_VLAN_ID)
++
+ /*
+  * Common error codes
+  */
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 9fcce7cd3673..e1f210a173a5 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -37,6 +37,7 @@ struct iscsi_cls_conn;
+ struct iscsi_conn;
+ struct iscsi_task;
+ struct sockaddr;
++struct iscsi_iface;
+ 
+ /**
+  * struct iscsi_transport - iSCSI Transport template
+@@ -87,6 +88,8 @@ struct iscsi_transport {
+ 	/* LLD sets this to indicate what values it can export to sysfs */
+ 	uint64_t param_mask;
+ 	uint64_t host_param_mask;
++	uint64_t iface_param_mask;
++
+ 	struct iscsi_cls_session *(*create_session) (struct iscsi_endpoint *ep,
+ 					uint16_t cmds_max, uint16_t qdepth,
+ 					uint32_t sn);
+@@ -138,6 +141,9 @@ struct iscsi_transport {
+ 			  uint32_t enable, struct sockaddr *dst_addr);
+ 	int (*set_path) (struct Scsi_Host *shost, struct iscsi_path *params);
+ 	int (*set_iface_param) (struct Scsi_Host *shost, char *data, int count);
++	int (*get_iface_param) (struct iscsi_iface *iface,
++				enum iscsi_param_type param_type,
++				int param, char *buf);
+ };
+ 
+ /*
+@@ -229,6 +235,20 @@ struct iscsi_endpoint {
+ 	struct iscsi_cls_conn *conn;
+ };
+ 
++struct iscsi_iface {
++	struct device dev;
++	struct iscsi_transport *transport;
++	uint32_t iface_type;	/* IPv4 or IPv6 */
++	uint32_t iface_num;	/* iface number, 0 - n */
++	void *dd_data;		/* LLD private data */
++};
++
++#define iscsi_dev_to_iface(_dev) \
++	container_of(_dev, struct iscsi_iface, dev)
++
++#define iscsi_iface_to_shost(_iface) \
++	dev_to_shost(_iface->dev.parent)
++
+ /*
+  * session and connection functions that can be used by HW iSCSI LLDs
+  */
+@@ -262,5 +282,11 @@ extern struct iscsi_endpoint *iscsi_create_endpoint(int dd_size);
+ extern void iscsi_destroy_endpoint(struct iscsi_endpoint *ep);
+ extern struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle);
+ extern int iscsi_block_scsi_eh(struct scsi_cmnd *cmd);
++extern struct iscsi_iface *iscsi_create_iface(struct Scsi_Host *shost,
++					      struct iscsi_transport *t,
++					      uint32_t iface_type,
++					      uint32_t iface_num, int dd_size);
++extern void iscsi_destroy_iface(struct iscsi_iface *iface);
++extern struct iscsi_iface *iscsi_lookup_iface(int handle);
+ 
+ #endif

commit d00efe3fa87fdf1df3635ba57ef3f14d03bc3ac8
+Author: Mike Christie 
+Date:   Mon Jul 25 13:48:38 2011 -0500
+
+    [SCSI] qla4xxx: add support for set_net_config
+    
+    Allows user space (iscsiadm) to send down network configuration
+    parameters for LLD to set private network configuration on the iSCSI
+    adapters.
+    
+    Based on patches from Vikas Chaudhary.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
+index 01082aa77098..21aa1dbaf2c3 100644
+--- a/drivers/scsi/qla4xxx/ql4_fw.h
++++ b/drivers/scsi/qla4xxx/ql4_fw.h
+@@ -434,6 +434,14 @@ struct qla_flt_region {
+ #define ACB_STATE_VALID		0x05
+ #define ACB_STATE_DISABLING	0x06
+ 
++/* FLASH offsets */
++#define FLASH_SEGMENT_IFCB	0x04000000
++
++#define FLASH_OPT_RMW_HOLD	0
++#define FLASH_OPT_RMW_INIT	1
++#define FLASH_OPT_COMMIT	2
++#define FLASH_OPT_RMW_COMMIT	3
++
+ /*************************************************************************/
+ 
+ /* Host Adapter Initialization Control Block (from host) */
+@@ -473,6 +481,7 @@ struct addr_ctrl_blk {
+ 
+ 	uint16_t iscsi_opts;	/* 30-31 */
+ 	uint16_t ipv4_tcp_opts;	/* 32-33 */
++#define TCPOPT_DHCP_ENABLE		0x0200
+ 	uint16_t ipv4_ip_opts;	/* 34-35 */
+ #define  IPOPT_IPv4_PROTOCOL_ENABLE	0x8000
+ 
+@@ -574,6 +583,74 @@ struct init_fw_ctrl_blk {
+ /*	struct addr_ctrl_blk sec;*/
+ };
+ 
++struct addr_ctrl_blk_def {
++	uint8_t reserved1[1];	/* 00 */
++	uint8_t control;	/* 01 */
++	uint8_t reserved2[11];	/* 02-0C */
++	uint8_t inst_num;	/* 0D */
++	uint8_t reserved3[34];	/* 0E-2F */
++	uint16_t iscsi_opts;	/* 30-31 */
++	uint16_t ipv4_tcp_opts;	/* 32-33 */
++	uint16_t ipv4_ip_opts;	/* 34-35 */
++	uint16_t iscsi_max_pdu_size;	/* 36-37 */
++	uint8_t ipv4_tos;	/* 38 */
++	uint8_t ipv4_ttl;	/* 39 */
++	uint8_t reserved4[2];	/* 3A-3B */
++	uint16_t def_timeout;	/* 3C-3D */
++	uint16_t iscsi_fburst_len;	/* 3E-3F */
++	uint8_t reserved5[4];	/* 40-43 */
++	uint16_t iscsi_max_outstnd_r2t;	/* 44-45 */
++	uint8_t reserved6[2];	/* 46-47 */
++	uint16_t ipv4_port;	/* 48-49 */
++	uint16_t iscsi_max_burst_len;	/* 4A-4B */
++	uint8_t reserved7[4];	/* 4C-4F */
++	uint8_t ipv4_addr[4];	/* 50-53 */
++	uint16_t ipv4_vlan_tag;	/* 54-55 */
++	uint8_t ipv4_addr_state;	/* 56 */
++	uint8_t ipv4_cacheid;	/* 57 */
++	uint8_t reserved8[8];	/* 58-5F */
++	uint8_t ipv4_subnet[4];	/* 60-63 */
++	uint8_t reserved9[12];	/* 64-6F */
++	uint8_t ipv4_gw_addr[4];	/* 70-73 */
++	uint8_t reserved10[84];	/* 74-C7 */
++	uint8_t abort_timer;	/* C8    */
++	uint8_t ipv4_tcp_wsf;	/* C9    */
++	uint8_t reserved11[10];	/* CA-D3 */
++	uint8_t ipv4_dhcp_vid_len;	/* D4 */
++	uint8_t ipv4_dhcp_vid[11];	/* D5-DF */
++	uint8_t reserved12[20];	/* E0-F3 */
++	uint8_t ipv4_dhcp_alt_cid_len;	/* F4 */
++	uint8_t ipv4_dhcp_alt_cid[11];	/* F5-FF */
++	uint8_t iscsi_name[224];	/* 100-1DF */
++	uint8_t reserved13[32];	/* 1E0-1FF */
++	uint32_t cookie;	/* 200-203 */
++	uint16_t ipv6_port;	/* 204-205 */
++	uint16_t ipv6_opts;	/* 206-207 */
++	uint16_t ipv6_addtl_opts;	/* 208-209 */
++	uint16_t ipv6_tcp_opts;		/* 20A-20B */
++	uint8_t ipv6_tcp_wsf;		/* 20C */
++	uint16_t ipv6_flow_lbl;		/* 20D-20F */
++	uint8_t ipv6_dflt_rtr_addr[16];	/* 210-21F */
++	uint16_t ipv6_vlan_tag;		/* 220-221 */
++	uint8_t ipv6_lnk_lcl_addr_state;	/* 222 */
++	uint8_t ipv6_addr0_state;	/* 223 */
++	uint8_t ipv6_addr1_state;	/* 224 */
++	uint8_t ipv6_dflt_rtr_state;	/* 225 */
++	uint8_t ipv6_traffic_class;	/* 226 */
++	uint8_t ipv6_hop_limit;		/* 227 */
++	uint8_t ipv6_if_id[8];		/* 228-22F */
++	uint8_t ipv6_addr0[16];		/* 230-23F */
++	uint8_t ipv6_addr1[16];		/* 240-24F */
++	uint32_t ipv6_nd_reach_time;	/* 250-253 */
++	uint32_t ipv6_nd_rexmit_timer;	/* 254-257 */
++	uint32_t ipv6_nd_stale_timeout;	/* 258-25B */
++	uint8_t ipv6_dup_addr_detect_count;	/* 25C */
++	uint8_t ipv6_cache_id;		/* 25D */
++	uint8_t reserved14[18];		/* 25E-26F */
++	uint32_t ipv6_gw_advrt_mtu;	/* 270-273 */
++	uint8_t reserved15[140];	/* 274-2FF */
++};
++
+ /*************************************************************************/
+ 
+ struct dev_db_entry {
+diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
+index a53a256c1f8d..786274c48313 100644
+--- a/drivers/scsi/qla4xxx/ql4_glbl.h
++++ b/drivers/scsi/qla4xxx/ql4_glbl.h
+@@ -52,7 +52,17 @@ int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha,
+ 
+ int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index,
+ 			  dma_addr_t fw_ddb_entry_dma);
+-
++uint8_t qla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
++			 uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma);
++int qla4xxx_conn_close_sess_logout(struct scsi_qla_host *ha,
++				   uint16_t fw_ddb_index,
++				   uint16_t connection_id,
++				   uint16_t option);
++int qla4xxx_disable_acb(struct scsi_qla_host *ha);
++int qla4xxx_set_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
++		    uint32_t *mbox_sts, dma_addr_t acb_dma);
++int qla4xxx_get_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
++		    uint32_t *mbox_sts, dma_addr_t acb_dma);
+ void qla4xxx_mark_device_missing(struct scsi_qla_host *ha,
+ 				 struct ddb_entry *ddb_entry);
+ u16 rd_nvram_word(struct scsi_qla_host *ha, int offset);
+@@ -75,7 +85,8 @@ void qla4xxx_dump_buffer(void *b, uint32_t size);
+ int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
+ 	struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod);
+ int qla4_is_relogin_allowed(struct scsi_qla_host *ha, uint32_t conn_err);
+-
++int qla4xxx_set_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr,
++		      uint32_t offset, uint32_t length, uint32_t options);
+ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
+ 		uint8_t outCount, uint32_t *mbx_cmd, uint32_t *mbx_sts);
+ 
+@@ -95,6 +106,11 @@ void qla4xxx_wake_dpc(struct scsi_qla_host *ha);
+ void qla4xxx_get_conn_event_log(struct scsi_qla_host *ha);
+ void qla4xxx_mailbox_premature_completion(struct scsi_qla_host *ha);
+ void qla4xxx_dump_registers(struct scsi_qla_host *ha);
++uint8_t qla4xxx_update_local_ifcb(struct scsi_qla_host *ha,
++				  uint32_t *mbox_cmd,
++				  uint32_t *mbox_sts,
++				  struct addr_ctrl_blk *init_fw_cb,
++				  dma_addr_t init_fw_cb_dma);
+ 
+ void qla4_8xxx_pci_config(struct scsi_qla_host *);
+ int qla4_8xxx_iospace_config(struct scsi_qla_host *ha);
+diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
+index fce8289e9752..559286dcc53c 100644
+--- a/drivers/scsi/qla4xxx/ql4_mbx.c
++++ b/drivers/scsi/qla4xxx/ql4_mbx.c
+@@ -303,7 +303,7 @@ qla4xxx_set_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
+ 	return QLA_SUCCESS;
+ }
+ 
+-static uint8_t
++uint8_t
+ qla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
+ 		 uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma)
+ {
+@@ -363,7 +363,7 @@ qla4xxx_update_local_ip(struct scsi_qla_host *ha,
+ 	}
+ }
+ 
+-static uint8_t
++uint8_t
+ qla4xxx_update_local_ifcb(struct scsi_qla_host *ha,
+ 			  uint32_t *mbox_cmd,
+ 			  uint32_t *mbox_sts,
+@@ -1207,3 +1207,118 @@ int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port)
+ 	return ret_val;
+ }
+ 
++int qla4xxx_set_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr,
++		      uint32_t offset, uint32_t length, uint32_t options)
++{
++	uint32_t mbox_cmd[MBOX_REG_COUNT];
++	uint32_t mbox_sts[MBOX_REG_COUNT];
++	int status = QLA_SUCCESS;
++
++	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
++	memset(&mbox_sts, 0, sizeof(mbox_sts));
++
++	mbox_cmd[0] = MBOX_CMD_WRITE_FLASH;
++	mbox_cmd[1] = LSDW(dma_addr);
++	mbox_cmd[2] = MSDW(dma_addr);
++	mbox_cmd[3] = offset;
++	mbox_cmd[4] = length;
++	mbox_cmd[5] = options;
++
++	status = qla4xxx_mailbox_command(ha, 6, 2, &mbox_cmd[0], &mbox_sts[0]);
++	if (status != QLA_SUCCESS) {
++		DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_WRITE_FLASH "
++				  "failed w/ status %04X, mbx1 %04X\n",
++				  __func__, mbox_sts[0], mbox_sts[1]));
++	}
++	return status;
++}
++
++int qla4xxx_conn_close_sess_logout(struct scsi_qla_host *ha,
++				   uint16_t fw_ddb_index,
++				   uint16_t connection_id,
++				   uint16_t option)
++{
++	uint32_t mbox_cmd[MBOX_REG_COUNT];
++	uint32_t mbox_sts[MBOX_REG_COUNT];
++	int status = QLA_SUCCESS;
++
++	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
++	memset(&mbox_sts, 0, sizeof(mbox_sts));
++
++	mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
++	mbox_cmd[1] = fw_ddb_index;
++	mbox_cmd[2] = connection_id;
++	mbox_cmd[3] = option;
++
++	status = qla4xxx_mailbox_command(ha, 4, 2, &mbox_cmd[0], &mbox_sts[0]);
++	if (status != QLA_SUCCESS) {
++		DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_CONN_CLOSE "
++				  "option %04x failed w/ status %04X %04X\n",
++				  __func__, option, mbox_sts[0], mbox_sts[1]));
++	}
++	return status;
++}
++
++int qla4xxx_disable_acb(struct scsi_qla_host *ha)
++{
++	uint32_t mbox_cmd[MBOX_REG_COUNT];
++	uint32_t mbox_sts[MBOX_REG_COUNT];
++	int status = QLA_SUCCESS;
++
++	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
++	memset(&mbox_sts, 0, sizeof(mbox_sts));
++
++	mbox_cmd[0] = MBOX_CMD_DISABLE_ACB;
++
++	status = qla4xxx_mailbox_command(ha, 8, 5, &mbox_cmd[0], &mbox_sts[0]);
++	if (status != QLA_SUCCESS) {
++		DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_DISABLE_ACB "
++				  "failed w/ status %04X %04X %04X", __func__,
++				  mbox_sts[0], mbox_sts[1], mbox_sts[2]));
++	}
++	return status;
++}
++
++int qla4xxx_get_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
++		    uint32_t *mbox_sts, dma_addr_t acb_dma)
++{
++	int status = QLA_SUCCESS;
++
++	memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);
++	memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);
++	mbox_cmd[0] = MBOX_CMD_GET_ACB;
++	mbox_cmd[1] = 0; /* Primary ACB */
++	mbox_cmd[2] = LSDW(acb_dma);
++	mbox_cmd[3] = MSDW(acb_dma);
++	mbox_cmd[4] = sizeof(struct addr_ctrl_blk);
++
++	status = qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]);
++	if (status != QLA_SUCCESS) {
++		DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_GET_ACB "
++				  "failed w/ status %04X\n", __func__,
++				  mbox_sts[0]));
++	}
++	return status;
++}
++
++int qla4xxx_set_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
++		    uint32_t *mbox_sts, dma_addr_t acb_dma)
++{
++	int status = QLA_SUCCESS;
++
++	memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);
++	memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);
++	mbox_cmd[0] = MBOX_CMD_SET_ACB;
++	mbox_cmd[1] = 0; /* Primary ACB */
++	mbox_cmd[2] = LSDW(acb_dma);
++	mbox_cmd[3] = MSDW(acb_dma);
++	mbox_cmd[4] = sizeof(struct addr_ctrl_blk);
++
++	status = qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]);
++	if (status != QLA_SUCCESS) {
++		DEBUG2(ql4_printk(KERN_WARNING, ha,  "%s: MBOX_CMD_SET_ACB "
++				  "failed w/ status %04X\n", __func__,
++				  mbox_sts[0]));
++	}
++	return status;
++}
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index f2364ec59f03..586f12f17c33 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -80,6 +80,8 @@ static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess,
+ 				  enum iscsi_param param, char *buf);
+ static int qla4xxx_host_get_param(struct Scsi_Host *shost,
+ 				  enum iscsi_host_param param, char *buf);
++static int qla4xxx_iface_set_param(struct Scsi_Host *shost, char *data,
++				   int count);
+ static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session);
+ static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc);
+ 
+@@ -142,6 +144,7 @@ static struct iscsi_transport qla4xxx_iscsi_transport = {
+ 	.get_conn_param		= qla4xxx_conn_get_param,
+ 	.get_session_param	= qla4xxx_sess_get_param,
+ 	.get_host_param		= qla4xxx_host_get_param,
++	.set_iface_param	= qla4xxx_iface_set_param,
+ 	.session_recovery_timedout = qla4xxx_recovery_timedout,
+ };
+ 
+@@ -202,6 +205,285 @@ static int qla4xxx_host_get_param(struct Scsi_Host *shost,
+ 	return len;
+ }
+ 
++static void qla4xxx_set_ipv6(struct scsi_qla_host *ha,
++			     struct iscsi_iface_param_info *iface_param,
++			     struct addr_ctrl_blk *init_fw_cb)
++{
++	/*
++	 * iface_num 0 is valid for IPv6 Addr, linklocal, router, autocfg.
++	 * iface_num 1 is valid only for IPv6 Addr.
++	 */
++	switch (iface_param->param) {
++	case ISCSI_NET_PARAM_IPV6_ADDR:
++		if (iface_param->iface_num & 0x1)
++			/* IPv6 Addr 1 */
++			memcpy(init_fw_cb->ipv6_addr1, iface_param->value,
++			       sizeof(init_fw_cb->ipv6_addr1));
++		else
++			/* IPv6 Addr 0 */
++			memcpy(init_fw_cb->ipv6_addr0, iface_param->value,
++			       sizeof(init_fw_cb->ipv6_addr0));
++		break;
++	case ISCSI_NET_PARAM_IPV6_LINKLOCAL:
++		if (iface_param->iface_num & 0x1)
++			break;
++		memcpy(init_fw_cb->ipv6_if_id, &iface_param->value[8],
++		       sizeof(init_fw_cb->ipv6_if_id));
++		break;
++	case ISCSI_NET_PARAM_IPV6_ROUTER:
++		if (iface_param->iface_num & 0x1)
++			break;
++		memcpy(init_fw_cb->ipv6_dflt_rtr_addr, iface_param->value,
++		       sizeof(init_fw_cb->ipv6_dflt_rtr_addr));
++		break;
++	case ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG:
++		/* Autocfg applies to even interface */
++		if (iface_param->iface_num & 0x1)
++			break;
++
++		if (iface_param->value[0] == ISCSI_IPV6_AUTOCFG_DISABLE)
++			init_fw_cb->ipv6_addtl_opts &=
++				cpu_to_le16(
++				  ~IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE);
++		else if (iface_param->value[0] == ISCSI_IPV6_AUTOCFG_ND_ENABLE)
++			init_fw_cb->ipv6_addtl_opts |=
++				cpu_to_le16(
++				  IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE);
++		else
++			ql4_printk(KERN_ERR, ha, "Invalid autocfg setting for "
++				   "IPv6 addr\n");
++		break;
++	case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG:
++		/* Autocfg applies to even interface */
++		if (iface_param->iface_num & 0x1)
++			break;
++
++		if (iface_param->value[0] ==
++		    ISCSI_IPV6_LINKLOCAL_AUTOCFG_ENABLE)
++			init_fw_cb->ipv6_addtl_opts |= cpu_to_le16(
++					IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR);
++		else if (iface_param->value[0] ==
++			 ISCSI_IPV6_LINKLOCAL_AUTOCFG_DISABLE)
++			init_fw_cb->ipv6_addtl_opts &= cpu_to_le16(
++				       ~IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR);
++		else
++			ql4_printk(KERN_ERR, ha, "Invalid autocfg setting for "
++				   "IPv6 linklocal addr\n");
++		break;
++	case ISCSI_NET_PARAM_IPV6_ROUTER_AUTOCFG:
++		/* Autocfg applies to even interface */
++		if (iface_param->iface_num & 0x1)
++			break;
++
++		if (iface_param->value[0] == ISCSI_IPV6_ROUTER_AUTOCFG_ENABLE)
++			memset(init_fw_cb->ipv6_dflt_rtr_addr, 0,
++			       sizeof(init_fw_cb->ipv6_dflt_rtr_addr));
++		break;
++	case ISCSI_NET_PARAM_IFACE_ENABLE:
++		if (iface_param->value[0] == ISCSI_IFACE_ENABLE)
++			init_fw_cb->ipv6_opts |=
++				cpu_to_le16(IPV6_OPT_IPV6_PROTOCOL_ENABLE);
++		else
++			init_fw_cb->ipv6_opts &=
++				cpu_to_le16(~IPV6_OPT_IPV6_PROTOCOL_ENABLE &
++					    0xFFFF);
++		break;
++	case ISCSI_NET_PARAM_VLAN_ID:
++		if (iface_param->len != sizeof(init_fw_cb->ipv6_vlan_tag))
++			break;
++		init_fw_cb->ipv6_vlan_tag = *(uint16_t *)iface_param->value;
++		break;
++	default:
++		ql4_printk(KERN_ERR, ha, "Unknown IPv6 param = %d\n",
++			   iface_param->param);
++		break;
++	}
++}
++
++static void qla4xxx_set_ipv4(struct scsi_qla_host *ha,
++			     struct iscsi_iface_param_info *iface_param,
++			     struct addr_ctrl_blk *init_fw_cb)
++{
++	switch (iface_param->param) {
++	case ISCSI_NET_PARAM_IPV4_ADDR:
++		memcpy(init_fw_cb->ipv4_addr, iface_param->value,
++		       sizeof(init_fw_cb->ipv4_addr));
++		break;
++	case ISCSI_NET_PARAM_IPV4_SUBNET:
++		memcpy(init_fw_cb->ipv4_subnet,	iface_param->value,
++		       sizeof(init_fw_cb->ipv4_subnet));
++		break;
++	case ISCSI_NET_PARAM_IPV4_GW:
++		memcpy(init_fw_cb->ipv4_gw_addr, iface_param->value,
++		       sizeof(init_fw_cb->ipv4_gw_addr));
++		break;
++	case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
++		if (iface_param->value[0] == ISCSI_BOOTPROTO_DHCP)
++			init_fw_cb->ipv4_tcp_opts |=
++					cpu_to_le16(TCPOPT_DHCP_ENABLE);
++		else if (iface_param->value[0] == ISCSI_BOOTPROTO_STATIC)
++			init_fw_cb->ipv4_tcp_opts &=
++					cpu_to_le16(~TCPOPT_DHCP_ENABLE);
++		else
++			ql4_printk(KERN_ERR, ha, "Invalid IPv4 bootproto\n");
++		break;
++	case ISCSI_NET_PARAM_IFACE_ENABLE:
++		if (iface_param->value[0] == ISCSI_IFACE_ENABLE)
++			init_fw_cb->ipv4_ip_opts |=
++				cpu_to_le16(IPOPT_IPv4_PROTOCOL_ENABLE);
++		else
++			init_fw_cb->ipv4_ip_opts &=
++				cpu_to_le16(~IPOPT_IPv4_PROTOCOL_ENABLE &
++					    0xFFFF);
++		break;
++	case ISCSI_NET_PARAM_VLAN_ID:
++		if (iface_param->len != sizeof(init_fw_cb->ipv4_vlan_tag))
++			break;
++		init_fw_cb->ipv4_vlan_tag = *(uint16_t *)iface_param->value;
++		break;
++	default:
++		ql4_printk(KERN_ERR, ha, "Unknown IPv4 param = %d\n",
++			   iface_param->param);
++		break;
++	}
++}
++
++static void
++qla4xxx_initcb_to_acb(struct addr_ctrl_blk *init_fw_cb)
++{
++	struct addr_ctrl_blk_def *acb;
++	acb = (struct addr_ctrl_blk_def *)init_fw_cb;
++	memset(acb->reserved1, 0, sizeof(acb->reserved1));
++	memset(acb->reserved2, 0, sizeof(acb->reserved2));
++	memset(acb->reserved3, 0, sizeof(acb->reserved3));
++	memset(acb->reserved4, 0, sizeof(acb->reserved4));
++	memset(acb->reserved5, 0, sizeof(acb->reserved5));
++	memset(acb->reserved6, 0, sizeof(acb->reserved6));
++	memset(acb->reserved7, 0, sizeof(acb->reserved7));
++	memset(acb->reserved8, 0, sizeof(acb->reserved8));
++	memset(acb->reserved9, 0, sizeof(acb->reserved9));
++	memset(acb->reserved10, 0, sizeof(acb->reserved10));
++	memset(acb->reserved11, 0, sizeof(acb->reserved11));
++	memset(acb->reserved12, 0, sizeof(acb->reserved12));
++	memset(acb->reserved13, 0, sizeof(acb->reserved13));
++	memset(acb->reserved14, 0, sizeof(acb->reserved14));
++	memset(acb->reserved15, 0, sizeof(acb->reserved15));
++}
++
++static int
++qla4xxx_iface_set_param(struct Scsi_Host *shost, char *data, int count)
++{
++	struct scsi_qla_host *ha = to_qla_host(shost);
++	int rval = 0;
++	struct iscsi_iface_param_info *iface_param = NULL;
++	struct addr_ctrl_blk *init_fw_cb = NULL;
++	dma_addr_t init_fw_cb_dma;
++	uint32_t mbox_cmd[MBOX_REG_COUNT];
++	uint32_t mbox_sts[MBOX_REG_COUNT];
++	uint32_t total_param_count;
++	uint32_t length;
++
++	init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
++					sizeof(struct addr_ctrl_blk),
++					&init_fw_cb_dma, GFP_KERNEL);
++	if (!init_fw_cb) {
++		ql4_printk(KERN_ERR, ha, "%s: Unable to alloc init_cb\n",
++			   __func__);
++		return -ENOMEM;
++	}
++
++	memset(init_fw_cb, 0, sizeof(struct addr_ctrl_blk));
++	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
++	memset(&mbox_sts, 0, sizeof(mbox_sts));
++
++	if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma)) {
++		ql4_printk(KERN_ERR, ha, "%s: get ifcb failed\n", __func__);
++		rval = -EIO;
++		goto exit_init_fw_cb;
++	}
++
++	total_param_count = count;
++	iface_param = (struct iscsi_iface_param_info *)data;
++
++	for ( ; total_param_count != 0; total_param_count--) {
++		length = iface_param->len;
++
++		if (iface_param->param_type != ISCSI_NET_PARAM)
++			continue;
++
++		switch (iface_param->iface_type) {
++		case ISCSI_IFACE_TYPE_IPV4:
++			switch (iface_param->iface_num) {
++			case 0:
++				qla4xxx_set_ipv4(ha, iface_param, init_fw_cb);
++				break;
++			default:
++				/* Cannot have more than one IPv4 interface */
++				ql4_printk(KERN_ERR, ha, "Invalid IPv4 iface "
++					   "number = %d\n",
++					   iface_param->iface_num);
++				break;
++			}
++			break;
++		case ISCSI_IFACE_TYPE_IPV6:
++			switch (iface_param->iface_num) {
++			case 0:
++			case 1:
++				qla4xxx_set_ipv6(ha, iface_param, init_fw_cb);
++				break;
++			default:
++				/* Cannot have more than two IPv6 interface */
++				ql4_printk(KERN_ERR, ha, "Invalid IPv6 iface "
++					   "number = %d\n",
++					   iface_param->iface_num);
++				break;
++			}
++			break;
++		default:
++			ql4_printk(KERN_ERR, ha, "Invalid iface type\n");
++			break;
++		}
++
++		iface_param = (struct iscsi_iface_param_info *)
++						((uint8_t *)iface_param +
++			    sizeof(struct iscsi_iface_param_info) + length);
++	}
++
++	init_fw_cb->cookie = cpu_to_le32(0x11BEAD5A);
++
++	rval = qla4xxx_set_flash(ha, init_fw_cb_dma, FLASH_SEGMENT_IFCB,
++				 sizeof(struct addr_ctrl_blk),
++				 FLASH_OPT_RMW_COMMIT);
++	if (rval != QLA_SUCCESS) {
++		ql4_printk(KERN_ERR, ha, "%s: set flash mbx failed\n",
++			   __func__);
++		rval = -EIO;
++		goto exit_init_fw_cb;
++	}
++
++	qla4xxx_disable_acb(ha);
++
++	qla4xxx_initcb_to_acb(init_fw_cb);
++
++	rval = qla4xxx_set_acb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma);
++	if (rval != QLA_SUCCESS) {
++		ql4_printk(KERN_ERR, ha, "%s: set acb mbx failed\n",
++			   __func__);
++		rval = -EIO;
++		goto exit_init_fw_cb;
++	}
++
++	memset(init_fw_cb, 0, sizeof(struct addr_ctrl_blk));
++	qla4xxx_update_local_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb,
++				  init_fw_cb_dma);
++
++exit_init_fw_cb:
++	dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk),
++			  init_fw_cb, init_fw_cb_dma);
++
++	return rval;
++}
++
+ static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess,
+ 				  enum iscsi_param param, char *buf)
+ {

commit 56c155b5ca427c9a6312bb0e31865f1c8ab10b2b
+Author: Mike Christie 
+Date:   Mon Jul 25 13:48:37 2011 -0500
+
+    [SCSI] iscsi_transport: add support for net settings
+    
+    Allows user space (iscsiadm) to send down network configuration
+    parameters for LLD to set private network configuration on the iSCSI
+    adapters.
+    
+    Based on patch from Lalit Chandivade.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 3fd16d7212de..212a8d846748 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -1557,6 +1557,30 @@ iscsi_set_path(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+ 	return err;
+ }
+ 
++static int
++iscsi_set_iface_params(struct iscsi_transport *transport,
++		       struct iscsi_uevent *ev)
++{
++	char *data = (char *)ev + sizeof(*ev);
++	struct Scsi_Host *shost;
++	int err;
++
++	if (!transport->set_iface_param)
++		return -ENOSYS;
++
++	shost = scsi_host_lookup(ev->u.set_iface_params.host_no);
++	if (!shost) {
++		printk(KERN_ERR "set_iface_params could not find host no %u\n",
++		       ev->u.set_iface_params.host_no);
++		return -ENODEV;
++	}
++
++	err = transport->set_iface_param(shost, data,
++					 ev->u.set_iface_params.count);
++	scsi_host_put(shost);
++	return err;
++}
++
+ static int
+ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
+ {
+@@ -1696,6 +1720,9 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
+ 	case ISCSI_UEVENT_PATH_UPDATE:
+ 		err = iscsi_set_path(transport, ev);
+ 		break;
++	case ISCSI_UEVENT_SET_IFACE_PARAMS:
++		err = iscsi_set_iface_params(transport, ev);
++		break;
+ 	default:
+ 		err = -ENOSYS;
+ 		break;
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index ddb04568a509..e93831e87878 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -59,6 +59,7 @@ enum iscsi_uevent_e {
+ 	ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST	= UEVENT_BASE + 19,
+ 
+ 	ISCSI_UEVENT_PATH_UPDATE	= UEVENT_BASE + 20,
++	ISCSI_UEVENT_SET_IFACE_PARAMS	= UEVENT_BASE + 21,
+ 
+ 	/* up events */
+ 	ISCSI_KEVENT_RECV_PDU		= KEVENT_BASE + 1,
+@@ -172,6 +173,10 @@ struct iscsi_uevent {
+ 		struct msg_set_path {
+ 			uint32_t	host_no;
+ 		} set_path;
++		struct msg_set_iface_params {
++			uint32_t	host_no;
++			uint32_t	count;
++		} set_iface_params;
+ 	} u;
+ 	union {
+ 		/* messages k -> u */
+@@ -214,6 +219,21 @@ struct iscsi_uevent {
+ 	} r;
+ } __attribute__ ((aligned (sizeof(uint64_t))));
+ 
++enum iscsi_param_type {
++	ISCSI_PARAM,		/* iscsi_param (session, conn, target, LU) */
++	ISCSI_HOST_PARAM,	/* iscsi_host_param */
++	ISCSI_NET_PARAM,	/* iscsi_net_param */
++};
++
++struct iscsi_iface_param_info {
++	uint32_t iface_num;	/* iface number, 0 - n */
++	uint32_t len;		/* Actual length of the param */
++	uint16_t param;		/* iscsi param value */
++	uint8_t iface_type;	/* IPv4 or IPv6 */
++	uint8_t param_type;	/* iscsi_param_type */
++	uint8_t value[0];	/* length sized value follows */
++} __packed;
++
+ /*
+  * To keep the struct iscsi_uevent size the same for userspace code
+  * compatibility, the main structure for ISCSI_UEVENT_PATH_UPDATE and
+@@ -237,6 +257,49 @@ struct iscsi_path {
+ 	uint16_t	pmtu;
+ } __attribute__ ((aligned (sizeof(uint64_t))));
+ 
++/* iscsi iface enabled/disabled setting */
++#define ISCSI_IFACE_DISABLE	0x01
++#define ISCSI_IFACE_ENABLE	0x02
++
++/* ipv4 bootproto */
++#define ISCSI_BOOTPROTO_STATIC		0x01
++#define ISCSI_BOOTPROTO_DHCP		0x02
++
++/* ipv6 addr autoconfig type */
++#define ISCSI_IPV6_AUTOCFG_DISABLE		0x01
++#define ISCSI_IPV6_AUTOCFG_ND_ENABLE		0x02
++#define ISCSI_IPV6_AUTOCFG_DHCPV6_ENABLE	0x03
++
++/* ipv6 link local addr type */
++#define ISCSI_IPV6_LINKLOCAL_AUTOCFG_ENABLE	0x01
++#define ISCSI_IPV6_LINKLOCAL_AUTOCFG_DISABLE	0x02
++
++/* ipv6 router addr type */
++#define ISCSI_IPV6_ROUTER_AUTOCFG_ENABLE	0x01
++#define ISCSI_IPV6_ROUTER_AUTOCFG_DISABLE	0x02
++
++#define ISCSI_IFACE_TYPE_IPV4		0x01
++#define ISCSI_IFACE_TYPE_IPV6		0x02
++
++/* iSCSI network params */
++enum iscsi_net_param {
++	ISCSI_NET_PARAM_IPV4_ADDR		= 1,
++	ISCSI_NET_PARAM_IPV4_SUBNET		= 2,
++	ISCSI_NET_PARAM_IPV4_GW			= 3,
++	ISCSI_NET_PARAM_IPV4_BOOTPROTO		= 4,
++	ISCSI_NET_PARAM_MAC			= 5,
++	ISCSI_NET_PARAM_IPV6_LINKLOCAL		= 6,
++	ISCSI_NET_PARAM_IPV6_ADDR		= 7,
++	ISCSI_NET_PARAM_IPV6_ROUTER		= 8,
++	ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG	= 9,
++	ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG	= 10,
++	ISCSI_NET_PARAM_IPV6_ROUTER_AUTOCFG	= 11,
++	ISCSI_NET_PARAM_IFACE_ENABLE		= 12,
++	ISCSI_NET_PARAM_VLAN_ID			= 13,
++	ISCSI_NET_IFACE_TYPE			= 14,
++	ISCSI_NET_IFACE_NAME			= 15,
++};
++
+ /*
+  * Common error codes
+  */
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index bf8f52965675..9fcce7cd3673 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -137,6 +137,7 @@ struct iscsi_transport {
+ 	int (*tgt_dscvr) (struct Scsi_Host *shost, enum iscsi_tgt_dscvr type,
+ 			  uint32_t enable, struct sockaddr *dst_addr);
+ 	int (*set_path) (struct Scsi_Host *shost, struct iscsi_path *params);
++	int (*set_iface_param) (struct Scsi_Host *shost, char *data, int count);
+ };
+ 
+ /*

commit aa387cc895672b00f807ad7c734a2defaf677712
+Author: Mike Christie 
+Date:   Sun Jul 31 22:05:09 2011 +0200
+
+    block: add bsg helper library
+    
+    This moves the FC classes bsg code to the block layer and
+    makes it a lib so that other classes like iscsi and SAS can use it.
+    
+    It is helpful because working with the request queue, bios,
+    creating scatterlists, etc are a pain that the LLD does not
+    have to worry about with normal IOs and should not have to
+    worry about for bsg requests.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/Kconfig b/block/Kconfig
+index 60be1e0455da..e97934eececa 100644
+--- a/block/Kconfig
++++ b/block/Kconfig
+@@ -65,6 +65,16 @@ config BLK_DEV_BSG
+ 
+ 	  If unsure, say Y.
+ 
++config BLK_DEV_BSGLIB
++	bool "Block layer SG support v4 helper lib"
++	default n
++	select BLK_DEV_BSG
++	help
++	  Subsystems will normally enable this if needed. Users will not
++	  normally need to manually enable this.
++
++	  If unsure, say N.
++
+ config BLK_DEV_INTEGRITY
+ 	bool "Block layer data integrity support"
+ 	---help---
+diff --git a/block/Makefile b/block/Makefile
+index 0fec4b3fab51..514c6e4f427a 100644
+--- a/block/Makefile
++++ b/block/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_BLOCK) := elevator.o blk-core.o blk-tag.o blk-sysfs.o \
+ 			blk-iopoll.o blk-lib.o ioctl.o genhd.o scsi_ioctl.o
+ 
+ obj-$(CONFIG_BLK_DEV_BSG)	+= bsg.o
++obj-$(CONFIG_BLK_DEV_BSGLIB)	+= bsg-lib.o
+ obj-$(CONFIG_BLK_CGROUP)	+= blk-cgroup.o
+ obj-$(CONFIG_BLK_DEV_THROTTLING)	+= blk-throttle.o
+ obj-$(CONFIG_IOSCHED_NOOP)	+= noop-iosched.o
+diff --git a/block/bsg-lib.c b/block/bsg-lib.c
+new file mode 100644
+index 000000000000..f8c0a61a529c
+--- /dev/null
++++ b/block/bsg-lib.c
+@@ -0,0 +1,297 @@
++/*
++ *  BSG helper library
++ *
++ *  Copyright (C) 2008   James Smart, Emulex Corporation
++ *  Copyright (C) 2011   Red Hat, Inc.  All rights reserved.
++ *  Copyright (C) 2011   Mike Christie
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++/**
++ * bsg_destroy_job - routine to teardown/delete a bsg job
++ * @job: bsg_job that is to be torn down
++ */
++static void bsg_destroy_job(struct bsg_job *job)
++{
++	put_device(job->dev);	/* release reference for the request */
++
++	kfree(job->request_payload.sg_list);
++	kfree(job->reply_payload.sg_list);
++	kfree(job);
++}
++
++/**
++ * bsg_job_done - completion routine for bsg requests
++ * @job: bsg_job that is complete
++ * @result: job reply result
++ * @reply_payload_rcv_len: length of payload recvd
++ *
++ * The LLD should call this when the bsg job has completed.
++ */
++void bsg_job_done(struct bsg_job *job, int result,
++		  unsigned int reply_payload_rcv_len)
++{
++	struct request *req = job->req;
++	struct request *rsp = req->next_rq;
++	int err;
++
++	err = job->req->errors = result;
++	if (err < 0)
++		/* we're only returning the result field in the reply */
++		job->req->sense_len = sizeof(u32);
++	else
++		job->req->sense_len = job->reply_len;
++	/* we assume all request payload was transferred, residual == 0 */
++	req->resid_len = 0;
++
++	if (rsp) {
++		WARN_ON(reply_payload_rcv_len > rsp->resid_len);
++
++		/* set reply (bidi) residual */
++		rsp->resid_len -= min(reply_payload_rcv_len, rsp->resid_len);
++	}
++	blk_complete_request(req);
++}
++EXPORT_SYMBOL_GPL(bsg_job_done);
++
++/**
++ * bsg_softirq_done - softirq done routine for destroying the bsg requests
++ * @rq: BSG request that holds the job to be destroyed
++ */
++static void bsg_softirq_done(struct request *rq)
++{
++	struct bsg_job *job = rq->special;
++
++	blk_end_request_all(rq, rq->errors);
++	bsg_destroy_job(job);
++}
++
++static int bsg_map_buffer(struct bsg_buffer *buf, struct request *req)
++{
++	size_t sz = (sizeof(struct scatterlist) * req->nr_phys_segments);
++
++	BUG_ON(!req->nr_phys_segments);
++
++	buf->sg_list = kzalloc(sz, GFP_KERNEL);
++	if (!buf->sg_list)
++		return -ENOMEM;
++	sg_init_table(buf->sg_list, req->nr_phys_segments);
++	buf->sg_cnt = blk_rq_map_sg(req->q, req, buf->sg_list);
++	buf->payload_len = blk_rq_bytes(req);
++	return 0;
++}
++
++/**
++ * bsg_create_job - create the bsg_job structure for the bsg request
++ * @dev: device that is being sent the bsg request
++ * @req: BSG request that needs a job structure
++ */
++static int bsg_create_job(struct device *dev, struct request *req)
++{
++	struct request *rsp = req->next_rq;
++	struct request_queue *q = req->q;
++	struct bsg_job *job;
++	int ret;
++
++	BUG_ON(req->special);
++
++	job = kzalloc(sizeof(struct bsg_job) + q->bsg_job_size, GFP_KERNEL);
++	if (!job)
++		return -ENOMEM;
++
++	req->special = job;
++	job->req = req;
++	if (q->bsg_job_size)
++		job->dd_data = (void *)&job[1];
++	job->request = req->cmd;
++	job->request_len = req->cmd_len;
++	job->reply = req->sense;
++	job->reply_len = SCSI_SENSE_BUFFERSIZE;	/* Size of sense buffer
++						 * allocated */
++	if (req->bio) {
++		ret = bsg_map_buffer(&job->request_payload, req);
++		if (ret)
++			goto failjob_rls_job;
++	}
++	if (rsp && rsp->bio) {
++		ret = bsg_map_buffer(&job->reply_payload, rsp);
++		if (ret)
++			goto failjob_rls_rqst_payload;
++	}
++	job->dev = dev;
++	/* take a reference for the request */
++	get_device(job->dev);
++	return 0;
++
++failjob_rls_rqst_payload:
++	kfree(job->request_payload.sg_list);
++failjob_rls_job:
++	kfree(job);
++	return -ENOMEM;
++}
++
++/*
++ * bsg_goose_queue - restart queue in case it was stopped
++ * @q: request q to be restarted
++ */
++void bsg_goose_queue(struct request_queue *q)
++{
++	if (!q)
++		return;
++
++	blk_run_queue_async(q);
++}
++EXPORT_SYMBOL_GPL(bsg_goose_queue);
++
++/**
++ * bsg_request_fn - generic handler for bsg requests
++ * @q: request queue to manage
++ *
++ * On error the create_bsg_job function should return a -Exyz error value
++ * that will be set to the req->errors.
++ *
++ * Drivers/subsys should pass this to the queue init function.
++ */
++void bsg_request_fn(struct request_queue *q)
++{
++	struct device *dev = q->queuedata;
++	struct request *req;
++	struct bsg_job *job;
++	int ret;
++
++	if (!get_device(dev))
++		return;
++
++	while (1) {
++		req = blk_fetch_request(q);
++		if (!req)
++			break;
++		spin_unlock_irq(q->queue_lock);
++
++		ret = bsg_create_job(dev, req);
++		if (ret) {
++			req->errors = ret;
++			blk_end_request_all(req, ret);
++			spin_lock_irq(q->queue_lock);
++			continue;
++		}
++
++		job = req->special;
++		ret = q->bsg_job_fn(job);
++		spin_lock_irq(q->queue_lock);
++		if (ret)
++			break;
++	}
++
++	spin_unlock_irq(q->queue_lock);
++	put_device(dev);
++	spin_lock_irq(q->queue_lock);
++}
++EXPORT_SYMBOL_GPL(bsg_request_fn);
++
++/**
++ * bsg_setup_queue - Create and add the bsg hooks so we can receive requests
++ * @dev: device to attach bsg device to
++ * @q: request queue setup by caller
++ * @name: device to give bsg device
++ * @job_fn: bsg job handler
++ * @dd_job_size: size of LLD data needed for each job
++ *
++ * The caller should have setup the reuqest queue with bsg_request_fn
++ * as the request_fn.
++ */
++int bsg_setup_queue(struct device *dev, struct request_queue *q,
++		    char *name, bsg_job_fn *job_fn, int dd_job_size)
++{
++	int ret;
++
++	q->queuedata = dev;
++	q->bsg_job_size = dd_job_size;
++	q->bsg_job_fn = job_fn;
++	queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q);
++	blk_queue_softirq_done(q, bsg_softirq_done);
++	blk_queue_rq_timeout(q, BLK_DEFAULT_SG_TIMEOUT);
++
++	ret = bsg_register_queue(q, dev, name, NULL);
++	if (ret) {
++		printk(KERN_ERR "%s: bsg interface failed to "
++		       "initialize - register queue\n", dev->kobj.name);
++		return ret;
++	}
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(bsg_setup_queue);
++
++/**
++ * bsg_remove_queue - Deletes the bsg dev from the q
++ * @q:	the request_queue that is to be torn down.
++ *
++ * Notes:
++ *   Before unregistering the queue empty any requests that are blocked
++ */
++void bsg_remove_queue(struct request_queue *q)
++{
++	struct request *req; /* block request */
++	int counts; /* totals for request_list count and starved */
++
++	if (!q)
++		return;
++
++	/* Stop taking in new requests */
++	spin_lock_irq(q->queue_lock);
++	blk_stop_queue(q);
++
++	/* drain all requests in the queue */
++	while (1) {
++		/* need the lock to fetch a request
++		 * this may fetch the same reqeust as the previous pass
++		 */
++		req = blk_fetch_request(q);
++		/* save requests in use and starved */
++		counts = q->rq.count[0] + q->rq.count[1] +
++			 q->rq.starved[0] + q->rq.starved[1];
++		spin_unlock_irq(q->queue_lock);
++		/* any requests still outstanding? */
++		if (counts == 0)
++			break;
++
++		/* This may be the same req as the previous iteration,
++		 * always send the blk_end_request_all after a prefetch.
++		 * It is not okay to not end the request because the
++		 * prefetch started the request.
++		 */
++		if (req) {
++			/* return -ENXIO to indicate that this queue is
++			 * going away
++			 */
++			req->errors = -ENXIO;
++			blk_end_request_all(req, -ENXIO);
++		}
++
++		msleep(200); /* allow bsg to possibly finish */
++		spin_lock_irq(q->queue_lock);
++	}
++	bsg_unregister_queue(q);
++}
++EXPORT_SYMBOL_GPL(bsg_remove_queue);
+diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
+index 0e67c45b3bc9..847928546076 100644
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -30,6 +30,7 @@ struct request_pm_state;
+ struct blk_trace;
+ struct request;
+ struct sg_io_hdr;
++struct bsg_job;
+ 
+ #define BLKDEV_MIN_RQ	4
+ #define BLKDEV_MAX_RQ	128	/* Default maximum */
+@@ -209,6 +210,7 @@ typedef int (merge_bvec_fn) (struct request_queue *, struct bvec_merge_data *,
+ typedef void (softirq_done_fn)(struct request *);
+ typedef int (dma_drain_needed_fn)(struct request *);
+ typedef int (lld_busy_fn) (struct request_queue *q);
++typedef int (bsg_job_fn) (struct bsg_job *);
+ 
+ enum blk_eh_timer_return {
+ 	BLK_EH_NOT_HANDLED,
+@@ -375,6 +377,8 @@ struct request_queue {
+ 	struct mutex		sysfs_lock;
+ 
+ #if defined(CONFIG_BLK_DEV_BSG)
++	bsg_job_fn		*bsg_job_fn;
++	int			bsg_job_size;
+ 	struct bsg_class_device bsg_dev;
+ #endif
+ 
+diff --git a/include/linux/bsg-lib.h b/include/linux/bsg-lib.h
+new file mode 100644
+index 000000000000..f55ab8cdc106
+--- /dev/null
++++ b/include/linux/bsg-lib.h
+@@ -0,0 +1,73 @@
++/*
++ *  BSG helper library
++ *
++ *  Copyright (C) 2008   James Smart, Emulex Corporation
++ *  Copyright (C) 2011   Red Hat, Inc.  All rights reserved.
++ *  Copyright (C) 2011   Mike Christie
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *
++ */
++#ifndef _BLK_BSG_
++#define _BLK_BSG_
++
++#include 
++
++struct request;
++struct device;
++struct scatterlist;
++struct request_queue;
++
++struct bsg_buffer {
++	unsigned int payload_len;
++	int sg_cnt;
++	struct scatterlist *sg_list;
++};
++
++struct bsg_job {
++	struct device *dev;
++	struct request *req;
++
++	/* Transport/driver specific request/reply structs */
++	void *request;
++	void *reply;
++
++	unsigned int request_len;
++	unsigned int reply_len;
++	/*
++	 * On entry : reply_len indicates the buffer size allocated for
++	 * the reply.
++	 *
++	 * Upon completion : the message handler must set reply_len
++	 *  to indicates the size of the reply to be returned to the
++	 *  caller.
++	 */
++
++	/* DMA payloads for the request/response */
++	struct bsg_buffer request_payload;
++	struct bsg_buffer reply_payload;
++
++	void *dd_data;		/* Used for driver-specific storage */
++};
++
++void bsg_job_done(struct bsg_job *job, int result,
++		  unsigned int reply_payload_rcv_len);
++int bsg_setup_queue(struct device *dev, struct request_queue *q, char *name,
++		    bsg_job_fn *job_fn, int dd_job_size);
++void bsg_request_fn(struct request_queue *q);
++void bsg_remove_queue(struct request_queue *q);
++void bsg_goose_queue(struct request_queue *q);
++
++#endif

commit 74dcd0ec735ba9c5bef254b2f6e53068cf3f9ff0
+Author: Mike Christie 
+Date:   Fri Jun 24 15:11:55 2011 -0500
+
+    [SCSI] libiscsi_tcp: fix LLD data allocation
+    
+    Have libiscsi_tcp have upper layers allocate the LLD data
+    along with the iscsi_cls_conn struct, so it is refcounted.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
+index e98ae33f1295..09b232fd9a1b 100644
+--- a/drivers/scsi/libiscsi_tcp.c
++++ b/drivers/scsi/libiscsi_tcp.c
+@@ -1084,7 +1084,8 @@ iscsi_tcp_conn_setup(struct iscsi_cls_session *cls_session, int dd_data_size,
+ 	struct iscsi_cls_conn *cls_conn;
+ 	struct iscsi_tcp_conn *tcp_conn;
+ 
+-	cls_conn = iscsi_conn_setup(cls_session, sizeof(*tcp_conn), conn_idx);
++	cls_conn = iscsi_conn_setup(cls_session,
++				    sizeof(*tcp_conn) + dd_data_size, conn_idx);
+ 	if (!cls_conn)
+ 		return NULL;
+ 	conn = cls_conn->dd_data;
+@@ -1096,22 +1097,13 @@ iscsi_tcp_conn_setup(struct iscsi_cls_session *cls_session, int dd_data_size,
+ 
+ 	tcp_conn = conn->dd_data;
+ 	tcp_conn->iscsi_conn = conn;
+-
+-	tcp_conn->dd_data = kzalloc(dd_data_size, GFP_KERNEL);
+-	if (!tcp_conn->dd_data) {
+-		iscsi_conn_teardown(cls_conn);
+-		return NULL;
+-	}
++	tcp_conn->dd_data = conn->dd_data + sizeof(*tcp_conn);
+ 	return cls_conn;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_tcp_conn_setup);
+ 
+ void iscsi_tcp_conn_teardown(struct iscsi_cls_conn *cls_conn)
+ {
+-	struct iscsi_conn *conn = cls_conn->dd_data;
+-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+-
+-	kfree(tcp_conn->dd_data);
+ 	iscsi_conn_teardown(cls_conn);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_tcp_conn_teardown);

commit 03adb5f91280b433c3685d0ee86b2e1424af3d88
+Author: Mike Christie 
+Date:   Fri Jun 24 15:11:54 2011 -0500
+
+    [SCSI] iscsi_tcp: fix locking around iscsi sk user data
+    
+    iscsi_sw_tcp_conn_restore_callbacks could have set
+    the sk_user_data field to NULL then iscsi_sw_tcp_data_ready
+    could read that and try to access the NULL pointer. This
+    adds some checks for NULL sk_user_data in the sk
+    callback functions and it uses the sk_callback_lock to
+    set/get that sk_user_data field.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 3df985305f69..7724414588fa 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -107,10 +107,12 @@ static int iscsi_sw_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+  * If the socket is in CLOSE or CLOSE_WAIT we should
+  * not close the connection if there is still some
+  * data pending.
++ *
++ * Must be called with sk_callback_lock.
+  */
+ static inline int iscsi_sw_sk_state_check(struct sock *sk)
+ {
+-	struct iscsi_conn *conn = (struct iscsi_conn*)sk->sk_user_data;
++	struct iscsi_conn *conn = sk->sk_user_data;
+ 
+ 	if ((sk->sk_state == TCP_CLOSE_WAIT || sk->sk_state == TCP_CLOSE) &&
+ 	    !atomic_read(&sk->sk_rmem_alloc)) {
+@@ -123,11 +125,17 @@ static inline int iscsi_sw_sk_state_check(struct sock *sk)
+ 
+ static void iscsi_sw_tcp_data_ready(struct sock *sk, int flag)
+ {
+-	struct iscsi_conn *conn = sk->sk_user_data;
+-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	struct iscsi_conn *conn;
++	struct iscsi_tcp_conn *tcp_conn;
+ 	read_descriptor_t rd_desc;
+ 
+ 	read_lock(&sk->sk_callback_lock);
++	conn = sk->sk_user_data;
++	if (!conn) {
++		read_unlock(&sk->sk_callback_lock);
++		return;
++	}
++	tcp_conn = conn->dd_data;
+ 
+ 	/*
+ 	 * Use rd_desc to pass 'conn' to iscsi_tcp_recv.
+@@ -141,11 +149,10 @@ static void iscsi_sw_tcp_data_ready(struct sock *sk, int flag)
+ 
+ 	iscsi_sw_sk_state_check(sk);
+ 
+-	read_unlock(&sk->sk_callback_lock);
+-
+ 	/* If we had to (atomically) map a highmem page,
+ 	 * unmap it now. */
+ 	iscsi_tcp_segment_unmap(&tcp_conn->in.segment);
++	read_unlock(&sk->sk_callback_lock);
+ }
+ 
+ static void iscsi_sw_tcp_state_change(struct sock *sk)
+@@ -157,8 +164,11 @@ static void iscsi_sw_tcp_state_change(struct sock *sk)
+ 	void (*old_state_change)(struct sock *);
+ 
+ 	read_lock(&sk->sk_callback_lock);
+-
+-	conn = (struct iscsi_conn*)sk->sk_user_data;
++	conn = sk->sk_user_data;
++	if (!conn) {
++		read_unlock(&sk->sk_callback_lock);
++		return;
++	}
+ 	session = conn->session;
+ 
+ 	iscsi_sw_sk_state_check(sk);
+@@ -178,11 +188,25 @@ static void iscsi_sw_tcp_state_change(struct sock *sk)
+  **/
+ static void iscsi_sw_tcp_write_space(struct sock *sk)
+ {
+-	struct iscsi_conn *conn = (struct iscsi_conn*)sk->sk_user_data;
+-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+-	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
++	struct iscsi_conn *conn;
++	struct iscsi_tcp_conn *tcp_conn;
++	struct iscsi_sw_tcp_conn *tcp_sw_conn;
++	void (*old_write_space)(struct sock *);
++
++	read_lock_bh(&sk->sk_callback_lock);
++	conn = sk->sk_user_data;
++	if (!conn) {
++		read_unlock_bh(&sk->sk_callback_lock);
++		return;
++	}
++
++	tcp_conn = conn->dd_data;
++	tcp_sw_conn = tcp_conn->dd_data;
++	old_write_space = tcp_sw_conn->old_write_space;
++	read_unlock_bh(&sk->sk_callback_lock);
++
++	old_write_space(sk);
+ 
+-	tcp_sw_conn->old_write_space(sk);
+ 	ISCSI_SW_TCP_DBG(conn, "iscsi_write_space\n");
+ 	iscsi_conn_queue_work(conn);
+ }
+@@ -592,20 +616,17 @@ static void iscsi_sw_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+ 	/* userspace may have goofed up and not bound us */
+ 	if (!sock)
+ 		return;
+-	/*
+-	 * Make sure our recv side is stopped.
+-	 * Older tools called conn stop before ep_disconnect
+-	 * so IO could still be coming in.
+-	 */
+-	write_lock_bh(&tcp_sw_conn->sock->sk->sk_callback_lock);
+-	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
+-	write_unlock_bh(&tcp_sw_conn->sock->sk->sk_callback_lock);
+ 
+ 	sock->sk->sk_err = EIO;
+ 	wake_up_interruptible(sk_sleep(sock->sk));
+ 
+-	iscsi_conn_stop(cls_conn, flag);
++	/* stop xmit side */
++	iscsi_suspend_tx(conn);
++
++	/* stop recv side and release socket */
+ 	iscsi_sw_tcp_release_conn(conn);
++
++	iscsi_conn_stop(cls_conn, flag);
+ }
+ 
+ static int

commit f457a46f179df41b0f6d80dee33b6e629945f276
+Author: Mike Christie 
+Date:   Fri Jun 24 15:11:53 2011 -0500
+
+    [SCSI] iscsi_ibft, be2iscsi, iscsi_boot: fix boot kobj data lifetime management
+    
+    be2iscsi passes the boot functions its phba object which is
+    allocated in the shost, but iscsi_ibft passes in a object
+    allocated for each item to display. The problem is that
+    iscsi_boot_sysfs was managing the lifetime of the object
+    passed in and doing a kfree on release. This causes a double
+    free for be2iscsi which frees the shost in its pci_remove.
+    
+    This patch fixes the problem by adding a release callback
+    which the drivers can call kfree or a put() type of function
+    (needed for be2iscsi which will do a get/put on the shost).
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c
+index ce33f4626957..c811cb107904 100644
+--- a/drivers/firmware/iscsi_ibft.c
++++ b/drivers/firmware/iscsi_ibft.c
+@@ -566,6 +566,11 @@ static mode_t __init ibft_check_initiator_for(void *data, int type)
+ 	return rc;
+ }
+ 
++static void ibft_kobj_release(void *data)
++{
++	kfree(data);
++}
++
+ /*
+  * Helper function for ibft_register_kobjects.
+  */
+@@ -595,7 +600,8 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header,
+ 		boot_kobj = iscsi_boot_create_initiator(boot_kset, hdr->index,
+ 						ibft_kobj,
+ 						ibft_attr_show_initiator,
+-						ibft_check_initiator_for);
++						ibft_check_initiator_for,
++						ibft_kobj_release);
+ 		if (!boot_kobj) {
+ 			rc = -ENOMEM;
+ 			goto free_ibft_obj;
+@@ -610,7 +616,8 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header,
+ 		boot_kobj = iscsi_boot_create_ethernet(boot_kset, hdr->index,
+ 						       ibft_kobj,
+ 						       ibft_attr_show_nic,
+-						       ibft_check_nic_for);
++						       ibft_check_nic_for,
++						       ibft_kobj_release);
+ 		if (!boot_kobj) {
+ 			rc = -ENOMEM;
+ 			goto free_ibft_obj;
+@@ -625,7 +632,8 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header,
+ 		boot_kobj = iscsi_boot_create_target(boot_kset, hdr->index,
+ 						     ibft_kobj,
+ 						     ibft_attr_show_target,
+-						     ibft_check_tgt_for);
++						     ibft_check_tgt_for,
++						     ibft_kobj_release);
+ 		if (!boot_kobj) {
+ 			rc = -ENOMEM;
+ 			goto free_ibft_obj;
+diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
+index 2e214390c63b..0a9bdfa3d939 100644
+--- a/drivers/scsi/be2iscsi/be_main.c
++++ b/drivers/scsi/be2iscsi/be_main.c
+@@ -215,73 +215,62 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
+ static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf)
+ {
+ 	struct beiscsi_hba *phba = data;
++	struct mgmt_session_info *boot_sess = &phba->boot_sess;
++	struct mgmt_conn_info *boot_conn = &boot_sess->conn_list[0];
+ 	char *str = buf;
+ 	int rc;
+ 
+ 	switch (type) {
+ 	case ISCSI_BOOT_TGT_NAME:
+ 		rc = sprintf(buf, "%.*s\n",
+-				(int)strlen(phba->boot_sess.target_name),
+-				(char *)&phba->boot_sess.target_name);
++			    (int)strlen(boot_sess->target_name),
++			    (char *)&boot_sess->target_name);
+ 		break;
+ 	case ISCSI_BOOT_TGT_IP_ADDR:
+-		if (phba->boot_sess.conn_list[0].dest_ipaddr.ip_type == 0x1)
++		if (boot_conn->dest_ipaddr.ip_type == 0x1)
+ 			rc = sprintf(buf, "%pI4\n",
+-				(char *)&phba->boot_sess.conn_list[0].
+-				dest_ipaddr.ip_address);
++				(char *)&boot_conn->dest_ipaddr.ip_address);
+ 		else
+ 			rc = sprintf(str, "%pI6\n",
+-				(char *)&phba->boot_sess.conn_list[0].
+-				dest_ipaddr.ip_address);
++				(char *)&boot_conn->dest_ipaddr.ip_address);
+ 		break;
+ 	case ISCSI_BOOT_TGT_PORT:
+-		rc = sprintf(str, "%d\n", phba->boot_sess.conn_list[0].
+-				  dest_port);
++		rc = sprintf(str, "%d\n", boot_conn->dest_port);
+ 		break;
+ 
+ 	case ISCSI_BOOT_TGT_CHAP_NAME:
+ 		rc = sprintf(str,  "%.*s\n",
+-				      phba->boot_sess.conn_list[0].
+-				      negotiated_login_options.auth_data.chap.
+-				      target_chap_name_length,
+-				      (char *)&phba->boot_sess.conn_list[0].
+-				      negotiated_login_options.auth_data.chap.
+-				      target_chap_name);
++			     boot_conn->negotiated_login_options.auth_data.chap.
++			     target_chap_name_length,
++			     (char *)&boot_conn->negotiated_login_options.
++			     auth_data.chap.target_chap_name);
+ 		break;
+ 	case ISCSI_BOOT_TGT_CHAP_SECRET:
+ 		rc = sprintf(str,  "%.*s\n",
+-				      phba->boot_sess.conn_list[0].
+-				      negotiated_login_options.auth_data.chap.
+-				      target_secret_length,
+-				      (char *)&phba->boot_sess.conn_list[0].
+-				      negotiated_login_options.auth_data.chap.
+-				      target_secret);
+-
++			     boot_conn->negotiated_login_options.auth_data.chap.
++			     target_secret_length,
++			     (char *)&boot_conn->negotiated_login_options.
++			     auth_data.chap.target_secret);
+ 		break;
+ 	case ISCSI_BOOT_TGT_REV_CHAP_NAME:
+ 		rc = sprintf(str,  "%.*s\n",
+-				      phba->boot_sess.conn_list[0].
+-				      negotiated_login_options.auth_data.chap.
+-				      intr_chap_name_length,
+-				      (char *)&phba->boot_sess.conn_list[0].
+-				      negotiated_login_options.auth_data.chap.
+-				      intr_chap_name);
+-
++			     boot_conn->negotiated_login_options.auth_data.chap.
++			     intr_chap_name_length,
++			     (char *)&boot_conn->negotiated_login_options.
++			     auth_data.chap.intr_chap_name);
+ 		break;
+ 	case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
+-			rc = sprintf(str,  "%.*s\n",
+-				      phba->boot_sess.conn_list[0].
+-				      negotiated_login_options.auth_data.chap.
+-				      intr_secret_length,
+-				      (char *)&phba->boot_sess.conn_list[0].
+-				      negotiated_login_options.auth_data.chap.
+-				      intr_secret);
++		rc = sprintf(str,  "%.*s\n",
++			     boot_conn->negotiated_login_options.auth_data.chap.
++			     intr_secret_length,
++			     (char *)&boot_conn->negotiated_login_options.
++			     auth_data.chap.intr_secret);
+ 		break;
+ 	case ISCSI_BOOT_TGT_FLAGS:
+-			rc = sprintf(str, "2\n");
++		rc = sprintf(str, "2\n");
+ 		break;
+ 	case ISCSI_BOOT_TGT_NIC_ASSOC:
+-			rc = sprintf(str, "0\n");
++		rc = sprintf(str, "0\n");
+ 		break;
+ 	default:
+ 		rc = -ENOSYS;
+@@ -315,10 +304,10 @@ static ssize_t beiscsi_show_boot_eth_info(void *data, int type, char *buf)
+ 
+ 	switch (type) {
+ 	case ISCSI_BOOT_ETH_FLAGS:
+-			rc = sprintf(str, "2\n");
++		rc = sprintf(str, "2\n");
+ 		break;
+ 	case ISCSI_BOOT_ETH_INDEX:
+-			rc = sprintf(str, "0\n");
++		rc = sprintf(str, "0\n");
+ 		break;
+ 	case ISCSI_BOOT_ETH_MAC:
+ 		rc  = beiscsi_get_macaddr(buf, phba);
+@@ -391,39 +380,6 @@ static mode_t beiscsi_eth_get_attr_visibility(void *data, int type)
+ 	return rc;
+ }
+ 
+-static int beiscsi_setup_boot_info(struct beiscsi_hba *phba)
+-{
+-	struct iscsi_boot_kobj *boot_kobj;
+-
+-	phba->boot_kset = iscsi_boot_create_host_kset(phba->shost->host_no);
+-	if (!phba->boot_kset)
+-		return -ENOMEM;
+-
+-	/* get boot info using mgmt cmd */
+-	boot_kobj = iscsi_boot_create_target(phba->boot_kset, 0, phba,
+-					     beiscsi_show_boot_tgt_info,
+-					     beiscsi_tgt_get_attr_visibility);
+-	if (!boot_kobj)
+-		goto free_kset;
+-
+-	boot_kobj = iscsi_boot_create_initiator(phba->boot_kset, 0, phba,
+-					     beiscsi_show_boot_ini_info,
+-					     beiscsi_ini_get_attr_visibility);
+-	if (!boot_kobj)
+-		goto free_kset;
+-
+-	boot_kobj = iscsi_boot_create_ethernet(phba->boot_kset, 0, phba,
+-					     beiscsi_show_boot_eth_info,
+-					     beiscsi_eth_get_attr_visibility);
+-	if (!boot_kobj)
+-		goto free_kset;
+-	return 0;
+-
+-free_kset:
+-	iscsi_boot_destroy_kset(phba->boot_kset);
+-	return -ENOMEM;
+-}
+-
+ /*------------------- PCI Driver operations and data ----------------- */
+ static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = {
+ 	{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },
+@@ -482,14 +438,6 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev)
+ 	if (iscsi_host_add(shost, &phba->pcidev->dev))
+ 		goto free_devices;
+ 
+-	if (beiscsi_setup_boot_info(phba))
+-		/*
+-		 * log error but continue, because we may not be using
+-		 * iscsi boot.
+-		 */
+-		shost_printk(KERN_ERR, phba->shost, "Could not set up "
+-		"iSCSI boot info.");
+-
+ 	return phba;
+ 
+ free_devices:
+@@ -3510,6 +3458,7 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
+ 	unsigned int tag, wrb_num;
+ 	unsigned short status, extd_status;
+ 	struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
++	int ret = -ENOMEM;
+ 
+ 	tag = beiscsi_get_boot_target(phba);
+ 	if (!tag) {
+@@ -3534,8 +3483,7 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
+ 	boot_resp = embedded_payload(wrb);
+ 
+ 	if (boot_resp->boot_session_handle < 0) {
+-		printk(KERN_ERR "No Boot Session for this pci_func,"
+-			"session Hndl = %d\n", boot_resp->boot_session_handle);
++		shost_printk(KERN_INFO, phba->shost, "No Boot Session.\n");
+ 		return -ENXIO;
+ 	}
+ 
+@@ -3573,14 +3521,70 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
+ 	wrb = queue_get_wrb(mccq, wrb_num);
+ 	free_mcc_tag(&phba->ctrl, tag);
+ 	session_resp = nonemb_cmd.va ;
++
+ 	memcpy(&phba->boot_sess, &session_resp->session_info,
+ 	       sizeof(struct mgmt_session_info));
+-	pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
+-		    nonemb_cmd.va, nonemb_cmd.dma);
+-	return 0;
++	ret = 0;
++
+ boot_freemem:
+ 	pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
+ 		    nonemb_cmd.va, nonemb_cmd.dma);
++	return ret;
++}
++
++static void beiscsi_boot_release(void *data)
++{
++	struct beiscsi_hba *phba = data;
++
++	scsi_host_put(phba->shost);
++}
++
++static int beiscsi_setup_boot_info(struct beiscsi_hba *phba)
++{
++	struct iscsi_boot_kobj *boot_kobj;
++
++	/* get boot info using mgmt cmd */
++	if (beiscsi_get_boot_info(phba))
++		/* Try to see if we can carry on without this */
++		return 0;
++
++	phba->boot_kset = iscsi_boot_create_host_kset(phba->shost->host_no);
++	if (!phba->boot_kset)
++		return -ENOMEM;
++
++	/* get a ref because the show function will ref the phba */
++	if (!scsi_host_get(phba->shost))
++		goto free_kset;
++	boot_kobj = iscsi_boot_create_target(phba->boot_kset, 0, phba,
++					     beiscsi_show_boot_tgt_info,
++					     beiscsi_tgt_get_attr_visibility,
++					     beiscsi_boot_release);
++	if (!boot_kobj)
++		goto put_shost;
++
++	if (!scsi_host_get(phba->shost))
++		goto free_kset;
++	boot_kobj = iscsi_boot_create_initiator(phba->boot_kset, 0, phba,
++						beiscsi_show_boot_ini_info,
++						beiscsi_ini_get_attr_visibility,
++						beiscsi_boot_release);
++	if (!boot_kobj)
++		goto put_shost;
++
++	if (!scsi_host_get(phba->shost))
++		goto free_kset;
++	boot_kobj = iscsi_boot_create_ethernet(phba->boot_kset, 0, phba,
++					       beiscsi_show_boot_eth_info,
++					       beiscsi_eth_get_attr_visibility,
++					       beiscsi_boot_release);
++	if (!boot_kobj)
++		goto put_shost;
++	return 0;
++
++put_shost:
++	scsi_host_put(phba->shost);
++free_kset:
++	iscsi_boot_destroy_kset(phba->boot_kset);
+ 	return -ENOMEM;
+ }
+ 
+@@ -4307,11 +4311,15 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
+ 		goto free_blkenbld;
+ 	}
+ 	hwi_enable_intr(phba);
+-	ret = beiscsi_get_boot_info(phba);
+-	if (ret < 0) {
+-		shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
+-			     "No Boot Devices !!!!!\n");
+-	}
++
++	if (beiscsi_setup_boot_info(phba))
++		/*
++		 * log error but continue, because we may not be using
++		 * iscsi boot.
++		 */
++		shost_printk(KERN_ERR, phba->shost, "Could not set up "
++			     "iSCSI boot info.");
++
+ 	SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED\n\n\n");
+ 	return 0;
+ 
+diff --git a/drivers/scsi/iscsi_boot_sysfs.c b/drivers/scsi/iscsi_boot_sysfs.c
+index 4274ce93d8f2..89700cbca16e 100644
+--- a/drivers/scsi/iscsi_boot_sysfs.c
++++ b/drivers/scsi/iscsi_boot_sysfs.c
+@@ -64,7 +64,8 @@ static void iscsi_boot_kobj_release(struct kobject *kobj)
+ 	struct iscsi_boot_kobj *boot_kobj =
+ 			container_of(kobj, struct iscsi_boot_kobj, kobj);
+ 
+-	kfree(boot_kobj->data);
++	if (boot_kobj->release)
++		boot_kobj->release(boot_kobj->data);
+ 	kfree(boot_kobj);
+ }
+ 
+@@ -305,7 +306,8 @@ iscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset,
+ 		       struct attribute_group *attr_group,
+ 		       const char *name, int index, void *data,
+ 		       ssize_t (*show) (void *data, int type, char *buf),
+-		       mode_t (*is_visible) (void *data, int type))
++		       mode_t (*is_visible) (void *data, int type),
++		       void (*release) (void *data))
+ {
+ 	struct iscsi_boot_kobj *boot_kobj;
+ 
+@@ -323,6 +325,7 @@ iscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset,
+ 	boot_kobj->data = data;
+ 	boot_kobj->show = show;
+ 	boot_kobj->is_visible = is_visible;
++	boot_kobj->release = release;
+ 
+ 	if (sysfs_create_group(&boot_kobj->kobj, attr_group)) {
+ 		/*
+@@ -331,7 +334,7 @@ iscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset,
+ 		 * the boot kobj was not setup and the normal release
+ 		 * path is not being run.
+ 		 */
+-		boot_kobj->data = NULL;
++		boot_kobj->release = NULL;
+ 		kobject_put(&boot_kobj->kobj);
+ 		return NULL;
+ 	}
+@@ -357,6 +360,7 @@ static void iscsi_boot_remove_kobj(struct iscsi_boot_kobj *boot_kobj)
+  * @data: driver specific data for target
+  * @show: attr show function
+  * @is_visible: attr visibility function
++ * @release: release function
+  *
+  * Note: The boot sysfs lib will free the data passed in for the caller
+  * when all refs to the target kobject have been released.
+@@ -365,10 +369,12 @@ struct iscsi_boot_kobj *
+ iscsi_boot_create_target(struct iscsi_boot_kset *boot_kset, int index,
+ 			 void *data,
+ 			 ssize_t (*show) (void *data, int type, char *buf),
+-			 mode_t (*is_visible) (void *data, int type))
++			 mode_t (*is_visible) (void *data, int type),
++			 void (*release) (void *data))
+ {
+ 	return iscsi_boot_create_kobj(boot_kset, &iscsi_boot_target_attr_group,
+-				      "target%d", index, data, show, is_visible);
++				      "target%d", index, data, show, is_visible,
++				      release);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_boot_create_target);
+ 
+@@ -379,6 +385,7 @@ EXPORT_SYMBOL_GPL(iscsi_boot_create_target);
+  * @data: driver specific data
+  * @show: attr show function
+  * @is_visible: attr visibility function
++ * @release: release function
+  *
+  * Note: The boot sysfs lib will free the data passed in for the caller
+  * when all refs to the initiator kobject have been released.
+@@ -387,12 +394,13 @@ struct iscsi_boot_kobj *
+ iscsi_boot_create_initiator(struct iscsi_boot_kset *boot_kset, int index,
+ 			    void *data,
+ 			    ssize_t (*show) (void *data, int type, char *buf),
+-			    mode_t (*is_visible) (void *data, int type))
++			    mode_t (*is_visible) (void *data, int type),
++			    void (*release) (void *data))
+ {
+ 	return iscsi_boot_create_kobj(boot_kset,
+ 				      &iscsi_boot_initiator_attr_group,
+ 				      "initiator", index, data, show,
+-				      is_visible);
++				      is_visible, release);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_boot_create_initiator);
+ 
+@@ -403,6 +411,7 @@ EXPORT_SYMBOL_GPL(iscsi_boot_create_initiator);
+  * @data: driver specific data
+  * @show: attr show function
+  * @is_visible: attr visibility function
++ * @release: release function
+  *
+  * Note: The boot sysfs lib will free the data passed in for the caller
+  * when all refs to the ethernet kobject have been released.
+@@ -411,12 +420,13 @@ struct iscsi_boot_kobj *
+ iscsi_boot_create_ethernet(struct iscsi_boot_kset *boot_kset, int index,
+ 			   void *data,
+ 			   ssize_t (*show) (void *data, int type, char *buf),
+-			   mode_t (*is_visible) (void *data, int type))
++			   mode_t (*is_visible) (void *data, int type),
++			   void (*release) (void *data))
+ {
+ 	return iscsi_boot_create_kobj(boot_kset,
+ 				      &iscsi_boot_ethernet_attr_group,
+ 				      "ethernet%d", index, data, show,
+-				      is_visible);
++				      is_visible, release);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_boot_create_ethernet);
+ 
+diff --git a/include/linux/iscsi_boot_sysfs.h b/include/linux/iscsi_boot_sysfs.h
+index f1e6c184f14f..f0a2f8b0aa13 100644
+--- a/include/linux/iscsi_boot_sysfs.h
++++ b/include/linux/iscsi_boot_sysfs.h
+@@ -92,6 +92,13 @@ struct iscsi_boot_kobj {
+ 	 * properties.
+ 	 */
+ 	mode_t (*is_visible) (void *data, int type);
++
++	/*
++	 * Driver specific release function.
++	 *
++	 * The function should free the data passed in.
++	 */
++	void (*release) (void *data);
+ };
+ 
+ struct iscsi_boot_kset {
+@@ -103,18 +110,21 @@ struct iscsi_boot_kobj *
+ iscsi_boot_create_initiator(struct iscsi_boot_kset *boot_kset, int index,
+ 			    void *data,
+ 			    ssize_t (*show) (void *data, int type, char *buf),
+-			    mode_t (*is_visible) (void *data, int type));
++			    mode_t (*is_visible) (void *data, int type),
++			    void (*release) (void *data));
+ 
+ struct iscsi_boot_kobj *
+ iscsi_boot_create_ethernet(struct iscsi_boot_kset *boot_kset, int index,
+ 			   void *data,
+ 			   ssize_t (*show) (void *data, int type, char *buf),
+-			   mode_t (*is_visible) (void *data, int type));
++			   mode_t (*is_visible) (void *data, int type),
++			   void (*release) (void *data));
+ struct iscsi_boot_kobj *
+ iscsi_boot_create_target(struct iscsi_boot_kset *boot_kset, int index,
+ 			 void *data,
+ 			 ssize_t (*show) (void *data, int type, char *buf),
+-			 mode_t (*is_visible) (void *data, int type));
++			 mode_t (*is_visible) (void *data, int type),
++			 void (*release) (void *data));
+ 
+ struct iscsi_boot_kset *iscsi_boot_create_kset(const char *set_name);
+ struct iscsi_boot_kset *iscsi_boot_create_host_kset(unsigned int hostno);

commit 9d04516310aaef3970c642a54531a52123001178
+Author: Mike Christie 
+Date:   Fri Jun 24 15:11:52 2011 -0500
+
+    [SCSI] iscsi_boot_sysfs: have this module check for null on destruction
+    
+    This moves the check for NULL boot_sets to the iscsi_boot_sysfs
+    module instead of having the drivers do it.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
+index 7b967ed48962..2e214390c63b 100644
+--- a/drivers/scsi/be2iscsi/be_main.c
++++ b/drivers/scsi/be2iscsi/be_main.c
+@@ -420,8 +420,7 @@ static int beiscsi_setup_boot_info(struct beiscsi_hba *phba)
+ 	return 0;
+ 
+ free_kset:
+-	if (phba->boot_kset)
+-		iscsi_boot_destroy_kset(phba->boot_kset);
++	iscsi_boot_destroy_kset(phba->boot_kset);
+ 	return -ENOMEM;
+ }
+ 
+@@ -4149,8 +4148,7 @@ static void beiscsi_remove(struct pci_dev *pcidev)
+ 			    phba->ctrl.mbox_mem_alloced.size,
+ 			    phba->ctrl.mbox_mem_alloced.va,
+ 			    phba->ctrl.mbox_mem_alloced.dma);
+-	if (phba->boot_kset)
+-		iscsi_boot_destroy_kset(phba->boot_kset);
++	iscsi_boot_destroy_kset(phba->boot_kset);
+ 	iscsi_host_remove(phba->shost);
+ 	pci_dev_put(phba->pcidev);
+ 	iscsi_host_free(phba->shost);
+diff --git a/drivers/scsi/iscsi_boot_sysfs.c b/drivers/scsi/iscsi_boot_sysfs.c
+index df6bff7366cf..4274ce93d8f2 100644
+--- a/drivers/scsi/iscsi_boot_sysfs.c
++++ b/drivers/scsi/iscsi_boot_sysfs.c
+@@ -472,6 +472,9 @@ void iscsi_boot_destroy_kset(struct iscsi_boot_kset *boot_kset)
+ {
+ 	struct iscsi_boot_kobj *boot_kobj, *tmp_kobj;
+ 
++	if (!boot_kset)
++		return;
++
+ 	list_for_each_entry_safe(boot_kobj, tmp_kobj,
+ 				 &boot_kset->kobj_list, list)
+ 		iscsi_boot_remove_kobj(boot_kobj);

commit 140363500ddadad0c09cb512cc0c96a4d3efa053
+Author: Mike Christie 
+Date:   Thu Apr 14 23:50:57 2011 -0400
+
+    iscsi_ibft: search for broadcom specific ibft sign (v2)
+    
+    Broadcom iscsi offload firmware uses a non standard ibft sign of "BIFT".
+    When we added support for boot, the anaconda team and I were using
+    older firmware (I guess 4 years old), so boot does not work on current
+    cards.
+    
+    This patch modifies the ibft search code to search for "BIFT" along
+    with the other possible values.
+    
+    Broadcom has tested the patch and reported it works with their
+    firmware. Mike has tested Chelsio and Intel cards.
+    
+    [v2:
+    - Add ACPI_SIG_IBFT to ibft_signs
+    - replace break with goto in find_ibft_in_mem innner loop.]
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Peter Jones 
+    Signed-off-by: Konrad Rzeszutek Wilk 
+
+diff --git a/drivers/firmware/iscsi_ibft_find.c b/drivers/firmware/iscsi_ibft_find.c
+index 2192456dfd68..f032e446fc11 100644
+--- a/drivers/firmware/iscsi_ibft_find.c
++++ b/drivers/firmware/iscsi_ibft_find.c
+@@ -42,7 +42,20 @@
+ struct acpi_table_ibft *ibft_addr;
+ EXPORT_SYMBOL_GPL(ibft_addr);
+ 
+-#define IBFT_SIGN "iBFT"
++static const struct {
++	char *sign;
++} ibft_signs[] = {
++#ifdef CONFIG_ACPI
++	/*
++	 * One spec says "IBFT", the other says "iBFT". We have to check
++	 * for both.
++	 */
++	{ ACPI_SIG_IBFT },
++#endif
++	{ "iBFT" },
++	{ "BIFT" },	/* Broadcom iSCSI Offload */
++};
++
+ #define IBFT_SIGN_LEN 4
+ #define IBFT_START 0x80000 /* 512kB */
+ #define IBFT_END 0x100000 /* 1MB */
+@@ -62,6 +75,7 @@ static int __init find_ibft_in_mem(void)
+ 	unsigned long pos;
+ 	unsigned int len = 0;
+ 	void *virt;
++	int i;
+ 
+ 	for (pos = IBFT_START; pos < IBFT_END; pos += 16) {
+ 		/* The table can't be inside the VGA BIOS reserved space,
+@@ -69,18 +83,23 @@ static int __init find_ibft_in_mem(void)
+ 		if (pos == VGA_MEM)
+ 			pos += VGA_SIZE;
+ 		virt = isa_bus_to_virt(pos);
+-		if (memcmp(virt, IBFT_SIGN, IBFT_SIGN_LEN) == 0) {
+-			unsigned long *addr =
+-			    (unsigned long *)isa_bus_to_virt(pos + 4);
+-			len = *addr;
+-			/* if the length of the table extends past 1M,
+-			 * the table cannot be valid. */
+-			if (pos + len <= (IBFT_END-1)) {
+-				ibft_addr = (struct acpi_table_ibft *)virt;
+-				break;
++
++		for (i = 0; i < ARRAY_SIZE(ibft_signs); i++) {
++			if (memcmp(virt, ibft_signs[i].sign, IBFT_SIGN_LEN) ==
++			    0) {
++				unsigned long *addr =
++				    (unsigned long *)isa_bus_to_virt(pos + 4);
++				len = *addr;
++				/* if the length of the table extends past 1M,
++				 * the table cannot be valid. */
++				if (pos + len <= (IBFT_END-1)) {
++					ibft_addr = (struct acpi_table_ibft *)virt;
++					goto done;
++				}
+ 			}
+ 		}
+ 	}
++done:
+ 	return len;
+ }
+ /*
+@@ -89,18 +108,12 @@ static int __init find_ibft_in_mem(void)
+  */
+ unsigned long __init find_ibft_region(unsigned long *sizep)
+ {
+-
++	int i;
+ 	ibft_addr = NULL;
+ 
+ #ifdef CONFIG_ACPI
+-	/*
+-	 * One spec says "IBFT", the other says "iBFT". We have to check
+-	 * for both.
+-	 */
+-	if (!ibft_addr)
+-		acpi_table_parse(ACPI_SIG_IBFT, acpi_find_ibft);
+-	if (!ibft_addr)
+-		acpi_table_parse(IBFT_SIGN, acpi_find_ibft);
++	for (i = 0; i < ARRAY_SIZE(ibft_signs) && !ibft_addr; i++)
++		acpi_table_parse(ibft_signs[i].sign, acpi_find_ibft);
+ #endif /* CONFIG_ACPI */
+ 
+ 	/* iBFT 1.03 section 1.4.3.1 mandates that UEFI machines will

commit 70c7c88a1a65ca683eb7f3fe3ce79c72f29d845e
+Author: Mike Christie 
+Date:   Thu Mar 17 16:22:17 2011 -0500
+
+    [SCSI] libiscsi_tcp: use kmap in xmit path
+    
+    The xmit path can sleep with a page kmapped in the network
+    xmit code while it waits for space to open up, so we have to use
+    kmap instead of kmap atomic in that path.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
+index 8eeb39ffa37f..e98ae33f1295 100644
+--- a/drivers/scsi/libiscsi_tcp.c
++++ b/drivers/scsi/libiscsi_tcp.c
+@@ -132,14 +132,25 @@ static void iscsi_tcp_segment_map(struct iscsi_segment *segment, int recv)
+ 	if (page_count(sg_page(sg)) >= 1 && !recv)
+ 		return;
+ 
+-	segment->sg_mapped = kmap_atomic(sg_page(sg), KM_SOFTIRQ0);
++	if (recv) {
++		segment->atomic_mapped = true;
++		segment->sg_mapped = kmap_atomic(sg_page(sg), KM_SOFTIRQ0);
++	} else {
++		segment->atomic_mapped = false;
++		/* the xmit path can sleep with the page mapped so use kmap */
++		segment->sg_mapped = kmap(sg_page(sg));
++	}
++
+ 	segment->data = segment->sg_mapped + sg->offset + segment->sg_offset;
+ }
+ 
+ void iscsi_tcp_segment_unmap(struct iscsi_segment *segment)
+ {
+ 	if (segment->sg_mapped) {
+-		kunmap_atomic(segment->sg_mapped, KM_SOFTIRQ0);
++		if (segment->atomic_mapped)
++			kunmap_atomic(segment->sg_mapped, KM_SOFTIRQ0);
++		else
++			kunmap(sg_page(segment->sg));
+ 		segment->sg_mapped = NULL;
+ 		segment->data = NULL;
+ 	}
+diff --git a/include/scsi/libiscsi_tcp.h b/include/scsi/libiscsi_tcp.h
+index 741ae7ed4394..e6b9fd2eea34 100644
+--- a/include/scsi/libiscsi_tcp.h
++++ b/include/scsi/libiscsi_tcp.h
+@@ -47,6 +47,7 @@ struct iscsi_segment {
+ 	struct scatterlist	*sg;
+ 	void			*sg_mapped;
+ 	unsigned int		sg_offset;
++	bool			atomic_mapped;
+ 
+ 	iscsi_segment_done_fn_t	*done;
+ };

commit 3496343df5062d36354a106f19c9688a6ecf9734
+Author: Mike Christie 
+Date:   Fri Feb 25 14:04:28 2011 -0600
+
+    [SCSI] lpfc: block target when port queueing limit is hit
+    
+    Instead of blocking the entire host when the port's
+    queueing limit is hit, we should only block the port's
+    target. This will allow IO to other ports to execute.
+    
+    Signed-off-by: Mike Christie 
+    Acked-by: James Smart  
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
+index ff20abdc5095..bf34178b80bf 100644
+--- a/drivers/scsi/lpfc/lpfc_scsi.c
++++ b/drivers/scsi/lpfc/lpfc_scsi.c
+@@ -3062,7 +3062,7 @@ lpfc_queuecommand_lck(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
+ 		goto out_fail_command;
+ 	}
+ 	if (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth)
+-		goto out_host_busy;
++		goto out_tgt_busy;
+ 
+ 	lpfc_cmd = lpfc_get_scsi_buf(phba, ndlp);
+ 	if (lpfc_cmd == NULL) {
+@@ -3179,6 +3179,9 @@ lpfc_queuecommand_lck(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
+  out_host_busy:
+ 	return SCSI_MLQUEUE_HOST_BUSY;
+ 
++ out_tgt_busy:
++	return SCSI_MLQUEUE_TARGET_BUSY;
++
+  out_fail_command:
+ 	done(cmnd);
+ 	return 0;

commit f55ca84d92d0c249ce4f4b8d493657a59c359c5d
+Author: Mike Christie 
+Date:   Fri Feb 25 14:04:27 2011 -0600
+
+    [SCSI] lpfc: force retry in queuecommand when port is transitioning
+    
+    If the port takes a while to transition we could exhaust
+    the retries when using DID_TRANSPORT_DISRUPTED. For this
+    case we do not want to use any of the cmd's
+    retries, because if the command was running then when
+    it got failed the retry counter was already incremented.
+    And if this is the first time we are seeing the command,
+    (it got queued because it slipped through during the race)
+    then it should not have its retries incremented. The
+    fc class will decide the correct handling later.
+    
+    Signed-off-by: Mike Christie 
+    Acked-by: James Smart  
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
+index 1255b9d1b1b0..ff20abdc5095 100644
+--- a/drivers/scsi/lpfc/lpfc_scsi.c
++++ b/drivers/scsi/lpfc/lpfc_scsi.c
+@@ -3058,7 +3058,7 @@ lpfc_queuecommand_lck(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
+ 	 * transport is still transitioning.
+ 	 */
+ 	if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
+-		cmnd->result = ScsiResult(DID_TRANSPORT_DISRUPTED, 0);
++		cmnd->result = ScsiResult(DID_IMM_RETRY, 0);
+ 		goto out_fail_command;
+ 	}
+ 	if (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth)

commit c7f7fd5b7ea114e0f85fc4f2a853f6564410588d
+Author: Mike Christie 
+Date:   Wed Feb 16 15:04:41 2011 -0600
+
+    [SCSI] be2iscsi: fix null ptr ref in conn get param
+    
+    The ep_disconnect function could be freeing the ep
+    while beiscsi_conn_get_param is running. This has
+    the driver use the get ep param callback instead
+    of the get conn param to fix this.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
+index eaaa8813067d..868cc5590145 100644
+--- a/drivers/scsi/be2iscsi/be_iscsi.c
++++ b/drivers/scsi/be2iscsi/be_iscsi.c
+@@ -210,28 +210,20 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
+ }
+ 
+ /**
+- * beiscsi_conn_get_param - get the iscsi parameter
+- * @cls_conn: pointer to iscsi cls conn
++ * beiscsi_ep_get_param - get the iscsi parameter
++ * @ep: pointer to iscsi ep
+  * @param: parameter type identifier
+  * @buf: buffer pointer
+  *
+  * returns iscsi parameter
+  */
+-int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
++int beiscsi_ep_get_param(struct iscsi_endpoint *ep,
+ 			   enum iscsi_param param, char *buf)
+ {
+-	struct beiscsi_endpoint *beiscsi_ep;
+-	struct iscsi_conn *conn = cls_conn->dd_data;
+-	struct beiscsi_conn *beiscsi_conn = conn->dd_data;
++	struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
+ 	int len = 0;
+ 
+ 	SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_get_param, param= %d\n", param);
+-	beiscsi_ep = beiscsi_conn->ep;
+-	if (!beiscsi_ep) {
+-		SE_DEBUG(DBG_LVL_1,
+-			 "In beiscsi_conn_get_param , no beiscsi_ep\n");
+-		return -ENODEV;
+-	}
+ 
+ 	switch (param) {
+ 	case ISCSI_PARAM_CONN_PORT:
+@@ -244,7 +236,7 @@ int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ 			len = sprintf(buf, "%pI6\n", &beiscsi_ep->dst6_addr);
+ 		break;
+ 	default:
+-		return iscsi_conn_get_param(cls_conn, param, buf);
++		return -ENOSYS;
+ 	}
+ 	return len;
+ }
+diff --git a/drivers/scsi/be2iscsi/be_iscsi.h b/drivers/scsi/be2iscsi/be_iscsi.h
+index 8950a702b9f4..9c532797c29e 100644
+--- a/drivers/scsi/be2iscsi/be_iscsi.h
++++ b/drivers/scsi/be2iscsi/be_iscsi.h
+@@ -48,8 +48,8 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
+ 		      struct iscsi_cls_conn *cls_conn,
+ 		      uint64_t transport_fd, int is_leading);
+ 
+-int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+-			   enum iscsi_param param, char *buf);
++int beiscsi_ep_get_param(struct iscsi_endpoint *ep, enum iscsi_param param,
++			 char *buf);
+ 
+ int beiscsi_get_host_param(struct Scsi_Host *shost,
+ 			   enum iscsi_host_param param, char *buf);
+diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
+index 79cefbe31367..bd50145ab71b 100644
+--- a/drivers/scsi/be2iscsi/be_main.c
++++ b/drivers/scsi/be2iscsi/be_main.c
+@@ -4384,7 +4384,7 @@ struct iscsi_transport beiscsi_iscsi_transport = {
+ 	.bind_conn = beiscsi_conn_bind,
+ 	.destroy_conn = iscsi_conn_teardown,
+ 	.set_param = beiscsi_set_param,
+-	.get_conn_param = beiscsi_conn_get_param,
++	.get_conn_param = iscsi_conn_get_param,
+ 	.get_session_param = iscsi_session_get_param,
+ 	.get_host_param = beiscsi_get_host_param,
+ 	.start_conn = beiscsi_conn_start,
+@@ -4395,6 +4395,7 @@ struct iscsi_transport beiscsi_iscsi_transport = {
+ 	.alloc_pdu = beiscsi_alloc_pdu,
+ 	.parse_pdu_itt = beiscsi_parse_pdu,
+ 	.get_stats = beiscsi_conn_get_stats,
++	.get_ep_param = beiscsi_ep_get_param,
+ 	.ep_connect = beiscsi_ep_connect,
+ 	.ep_poll = beiscsi_ep_poll,
+ 	.ep_disconnect = beiscsi_ep_disconnect,

commit 7c53c6f89d7a6487986c51cd73ae9a9be338a8f4
+Author: Mike Christie 
+Date:   Wed Feb 16 15:04:40 2011 -0600
+
+    [SCSI] iser: export addr and port
+    
+    This pactch has iser export the address and port
+    of the endpoint.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 7b2fc98e2f2b..8db008de5392 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -532,6 +532,29 @@ iscsi_iser_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *s
+ 	stats->custom[3].value = conn->fmr_unalign_cnt;
+ }
+ 
++static int iscsi_iser_get_ep_param(struct iscsi_endpoint *ep,
++				   enum iscsi_param param, char *buf)
++{
++	struct iser_conn *ib_conn = ep->dd_data;
++	int len;
++
++	switch (param) {
++	case ISCSI_PARAM_CONN_PORT:
++	case ISCSI_PARAM_CONN_ADDRESS:
++		if (!ib_conn || !ib_conn->cma_id)
++			return -ENOTCONN;
++
++		return iscsi_conn_get_addr_param((struct sockaddr_storage *)
++					&ib_conn->cma_id->route.addr.dst_addr,
++					param, buf);
++		break;
++	default:
++		return -ENOSYS;
++	}
++
++	return len;
++}
++
+ static struct iscsi_endpoint *
+ iscsi_iser_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
+ 		      int non_blocking)
+@@ -637,6 +660,8 @@ static struct iscsi_transport iscsi_iser_transport = {
+ 				  ISCSI_MAX_BURST |
+ 				  ISCSI_PDU_INORDER_EN |
+ 				  ISCSI_DATASEQ_INORDER_EN |
++				  ISCSI_CONN_PORT |
++				  ISCSI_CONN_ADDRESS |
+ 				  ISCSI_EXP_STATSN |
+ 				  ISCSI_PERSISTENT_PORT |
+ 				  ISCSI_PERSISTENT_ADDRESS |
+@@ -659,6 +684,7 @@ static struct iscsi_transport iscsi_iser_transport = {
+ 	.destroy_conn           = iscsi_iser_conn_destroy,
+ 	.set_param              = iscsi_iser_set_param,
+ 	.get_conn_param		= iscsi_conn_get_param,
++	.get_ep_param		= iscsi_iser_get_ep_param,
+ 	.get_session_param	= iscsi_session_get_param,
+ 	.start_conn             = iscsi_iser_conn_start,
+ 	.stop_conn              = iscsi_iser_conn_stop,

commit d8585bcd7da071f4278710f1c39e18dfe7cb0280
+Author: Mike Christie 
+Date:   Wed Feb 16 15:04:39 2011 -0600
+
+    [SCSI] bnx2i: fix null ptr ref in conn get param
+    
+    bnx2i has some checks to try and make sure the ep
+    is not destroyed while the addr/port is getting
+    read. However, if after this check:
+    
+    if (!(bnx2i_conn && bnx2i_conn->ep && bnx2i_conn->ep->hba))
+            goto out;
+    
+    bnx2i_conn->ep is cleared by ep_disconnect then we will
+    oops.
+    
+    This patches fixes the problem by having the driver
+    use the get_ep_param callback instead of get_conn_param.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
+index 05bb8086069a..1809f9ccc4ce 100644
+--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
++++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
+@@ -1458,42 +1458,40 @@ static void bnx2i_conn_destroy(struct iscsi_cls_conn *cls_conn)
+ 
+ 
+ /**
+- * bnx2i_conn_get_param - return iscsi connection parameter to caller
+- * @cls_conn:	pointer to iscsi cls conn
++ * bnx2i_ep_get_param - return iscsi ep parameter to caller
++ * @ep:		pointer to iscsi endpoint
+  * @param:	parameter type identifier
+  * @buf: 	buffer pointer
+  *
+- * returns iSCSI connection parameters
++ * returns iSCSI ep parameters
+  */
+-static int bnx2i_conn_get_param(struct iscsi_cls_conn *cls_conn,
+-				enum iscsi_param param, char *buf)
++static int bnx2i_ep_get_param(struct iscsi_endpoint *ep,
++			      enum iscsi_param param, char *buf)
+ {
+-	struct iscsi_conn *conn = cls_conn->dd_data;
+-	struct bnx2i_conn *bnx2i_conn = conn->dd_data;
+-	int len = 0;
++	struct bnx2i_endpoint *bnx2i_ep = ep->dd_data;
++	struct bnx2i_hba *hba = bnx2i_ep->hba;
++	int len = -ENOTCONN;
+ 
+-	if (!(bnx2i_conn && bnx2i_conn->ep && bnx2i_conn->ep->hba))
+-		goto out;
++	if (!hba)
++		return -ENOTCONN;
+ 
+ 	switch (param) {
+ 	case ISCSI_PARAM_CONN_PORT:
+-		mutex_lock(&bnx2i_conn->ep->hba->net_dev_lock);
+-		if (bnx2i_conn->ep->cm_sk)
+-			len = sprintf(buf, "%hu\n",
+-				      bnx2i_conn->ep->cm_sk->dst_port);
+-		mutex_unlock(&bnx2i_conn->ep->hba->net_dev_lock);
++		mutex_lock(&hba->net_dev_lock);
++		if (bnx2i_ep->cm_sk)
++			len = sprintf(buf, "%hu\n", bnx2i_ep->cm_sk->dst_port);
++		mutex_unlock(&hba->net_dev_lock);
+ 		break;
+ 	case ISCSI_PARAM_CONN_ADDRESS:
+-		mutex_lock(&bnx2i_conn->ep->hba->net_dev_lock);
+-		if (bnx2i_conn->ep->cm_sk)
+-			len = sprintf(buf, "%pI4\n",
+-				      &bnx2i_conn->ep->cm_sk->dst_ip);
+-		mutex_unlock(&bnx2i_conn->ep->hba->net_dev_lock);
++		mutex_lock(&hba->net_dev_lock);
++		if (bnx2i_ep->cm_sk)
++			len = sprintf(buf, "%pI4\n", &bnx2i_ep->cm_sk->dst_ip);
++		mutex_unlock(&hba->net_dev_lock);
+ 		break;
+ 	default:
+-		return iscsi_conn_get_param(cls_conn, param, buf);
++		return -ENOSYS;
+ 	}
+-out:
++
+ 	return len;
+ }
+ 
+@@ -2204,7 +2202,7 @@ struct iscsi_transport bnx2i_iscsi_transport = {
+ 	.bind_conn		= bnx2i_conn_bind,
+ 	.destroy_conn		= bnx2i_conn_destroy,
+ 	.set_param		= iscsi_set_param,
+-	.get_conn_param		= bnx2i_conn_get_param,
++	.get_conn_param		= iscsi_conn_get_param,
+ 	.get_session_param	= iscsi_session_get_param,
+ 	.get_host_param		= bnx2i_host_get_param,
+ 	.start_conn		= bnx2i_conn_start,
+@@ -2213,6 +2211,7 @@ struct iscsi_transport bnx2i_iscsi_transport = {
+ 	.xmit_task		= bnx2i_task_xmit,
+ 	.get_stats		= bnx2i_conn_get_stats,
+ 	/* TCP connect - disconnect - option-2 interface calls */
++	.get_ep_param		= bnx2i_ep_get_param,
+ 	.ep_connect		= bnx2i_ep_connect,
+ 	.ep_poll		= bnx2i_ep_poll,
+ 	.ep_disconnect		= bnx2i_ep_disconnect,

commit c71b9b669e1243623f7ed4332877d3f2beafc6ab
+Author: Mike Christie 
+Date:   Wed Feb 16 15:04:38 2011 -0600
+
+    [SCSI] cxgbi: convert to use iscsi_conn_get_addr_param
+    
+    This has cxgbi use the iscsi_conn_get_addr_param helper
+    and the get ep callback.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
+index 69a6769c633e..fc2cdb62f53b 100644
+--- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
++++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
+@@ -137,7 +137,7 @@ static struct iscsi_transport cxgb3i_iscsi_transport = {
+ 	.destroy_conn	= iscsi_tcp_conn_teardown,
+ 	.start_conn	= iscsi_conn_start,
+ 	.stop_conn	= iscsi_conn_stop,
+-	.get_conn_param	= cxgbi_get_conn_param,
++	.get_conn_param	= iscsi_conn_get_param,
+ 	.set_param	= cxgbi_set_conn_param,
+ 	.get_stats	= cxgbi_get_conn_stats,
+ 	/* pdu xmit req from user space */
+@@ -152,6 +152,7 @@ static struct iscsi_transport cxgb3i_iscsi_transport = {
+ 	.xmit_pdu	= cxgbi_conn_xmit_pdu,
+ 	.parse_pdu_itt	= cxgbi_parse_pdu_itt,
+ 	/* TCP connect/disconnect */
++	.get_ep_param	= cxgbi_get_ep_param,
+ 	.ep_connect	= cxgbi_ep_connect,
+ 	.ep_poll	= cxgbi_ep_poll,
+ 	.ep_disconnect	= cxgbi_ep_disconnect,
+diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+index 719aa71f5b10..f3a4cd7cf782 100644
+--- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
++++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+@@ -138,7 +138,7 @@ static struct iscsi_transport cxgb4i_iscsi_transport = {
+ 	.destroy_conn	= iscsi_tcp_conn_teardown,
+ 	.start_conn		= iscsi_conn_start,
+ 	.stop_conn		= iscsi_conn_stop,
+-	.get_conn_param	= cxgbi_get_conn_param,
++	.get_conn_param	= iscsi_conn_get_param,
+ 	.set_param	= cxgbi_set_conn_param,
+ 	.get_stats	= cxgbi_get_conn_stats,
+ 	/* pdu xmit req from user space */
+@@ -153,6 +153,7 @@ static struct iscsi_transport cxgb4i_iscsi_transport = {
+ 	.xmit_pdu	= cxgbi_conn_xmit_pdu,
+ 	.parse_pdu_itt	= cxgbi_parse_pdu_itt,
+ 	/* TCP connect/disconnect */
++	.get_ep_param	= cxgbi_get_ep_param,
+ 	.ep_connect	= cxgbi_ep_connect,
+ 	.ep_poll	= cxgbi_ep_poll,
+ 	.ep_disconnect	= cxgbi_ep_disconnect,
+diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c
+index b2acdef3dcb7..fedf1be278ff 100644
+--- a/drivers/scsi/cxgbi/libcxgbi.c
++++ b/drivers/scsi/cxgbi/libcxgbi.c
+@@ -543,6 +543,7 @@ static struct cxgbi_sock *cxgbi_check_route(struct sockaddr *dst_addr)
+ 	csk->dst = dst;
+ 	csk->daddr.sin_addr.s_addr = daddr->sin_addr.s_addr;
+ 	csk->daddr.sin_port = daddr->sin_port;
++	csk->daddr.sin_family = daddr->sin_family;
+ 	csk->saddr.sin_addr.s_addr = rt->rt_src;
+ 
+ 	return csk;
+@@ -2200,32 +2201,34 @@ int cxgbi_set_conn_param(struct iscsi_cls_conn *cls_conn,
+ }
+ EXPORT_SYMBOL_GPL(cxgbi_set_conn_param);
+ 
+-int cxgbi_get_conn_param(struct iscsi_cls_conn *cls_conn,
+-			enum iscsi_param param, char *buf)
++int cxgbi_get_ep_param(struct iscsi_endpoint *ep, enum iscsi_param param,
++		       char *buf)
+ {
+-	struct iscsi_conn *iconn = cls_conn->dd_data;
++	struct cxgbi_endpoint *cep = ep->dd_data;
++	struct cxgbi_sock *csk;
+ 	int len;
+ 
+ 	log_debug(1 << CXGBI_DBG_ISCSI,
+-		"cls_conn 0x%p, param %d.\n", cls_conn, param);
++		"cls_conn 0x%p, param %d.\n", ep, param);
+ 
+ 	switch (param) {
+ 	case ISCSI_PARAM_CONN_PORT:
+-		spin_lock_bh(&iconn->session->lock);
+-		len = sprintf(buf, "%hu\n", iconn->portal_port);
+-		spin_unlock_bh(&iconn->session->lock);
+-		break;
+ 	case ISCSI_PARAM_CONN_ADDRESS:
+-		spin_lock_bh(&iconn->session->lock);
+-		len = sprintf(buf, "%s\n", iconn->portal_address);
+-		spin_unlock_bh(&iconn->session->lock);
+-		break;
++		if (!cep)
++			return -ENOTCONN;
++
++		csk = cep->csk;
++		if (!csk)
++			return -ENOTCONN;
++
++		return iscsi_conn_get_addr_param((struct sockaddr_storage *)
++						 &csk->daddr, param, buf);
+ 	default:
+-		return iscsi_conn_get_param(cls_conn, param, buf);
++		return -ENOSYS;
+ 	}
+ 	return len;
+ }
+-EXPORT_SYMBOL_GPL(cxgbi_get_conn_param);
++EXPORT_SYMBOL_GPL(cxgbi_get_ep_param);
+ 
+ struct iscsi_cls_conn *
+ cxgbi_create_conn(struct iscsi_cls_session *cls_session, u32 cid)
+@@ -2292,11 +2295,6 @@ int cxgbi_bind_conn(struct iscsi_cls_session *cls_session,
+ 	cxgbi_conn_max_xmit_dlength(conn);
+ 	cxgbi_conn_max_recv_dlength(conn);
+ 
+-	spin_lock_bh(&conn->session->lock);
+-	sprintf(conn->portal_address, "%pI4", &csk->daddr.sin_addr.s_addr);
+-	conn->portal_port = ntohs(csk->daddr.sin_port);
+-	spin_unlock_bh(&conn->session->lock);
+-
+ 	log_debug(1 << CXGBI_DBG_ISCSI,
+ 		"cls 0x%p,0x%p, ep 0x%p, cconn 0x%p, csk 0x%p.\n",
+ 		cls_session, cls_conn, ep, cconn, csk);
+diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h
+index 23cbc5854503..0a20fd5f7102 100644
+--- a/drivers/scsi/cxgbi/libcxgbi.h
++++ b/drivers/scsi/cxgbi/libcxgbi.h
+@@ -712,7 +712,7 @@ void cxgbi_cleanup_task(struct iscsi_task *task);
+ void cxgbi_get_conn_stats(struct iscsi_cls_conn *, struct iscsi_stats *);
+ int cxgbi_set_conn_param(struct iscsi_cls_conn *,
+ 			enum iscsi_param, char *, int);
+-int cxgbi_get_conn_param(struct iscsi_cls_conn *, enum iscsi_param, char *);
++int cxgbi_get_ep_param(struct iscsi_endpoint *ep, enum iscsi_param, char *);
+ struct iscsi_cls_conn *cxgbi_create_conn(struct iscsi_cls_session *, u32);
+ int cxgbi_bind_conn(struct iscsi_cls_session *,
+ 			struct iscsi_cls_conn *, u64, int);
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 4bef19fb3a65..0f4367751b71 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -212,9 +212,6 @@ struct iscsi_conn {
+ 	/* values userspace uses to id a conn */
+ 	int			persistent_port;
+ 	char			*persistent_address;
+-	/* remote portal currently connected to */
+-	int			portal_port;
+-	char			portal_address[ISCSI_ADDRESS_BUF_LEN];
+ 
+ 	/* MIB-statistics */
+ 	uint64_t		txdata_octets;
+@@ -319,9 +316,6 @@ struct iscsi_host {
+ 	/* hw address or netdev iscsi connection is bound to */
+ 	char			*hwaddress;
+ 	char			*netdev;
+-	/* local address */
+-	int			local_port;
+-	char			local_address[ISCSI_ADDRESS_BUF_LEN];
+ 
+ 	wait_queue_head_t	session_removal_wq;
+ 	/* protects sessions and state */

commit 289324b0c6007171d67bf1ab0827355ae3374773
+Author: Mike Christie 
+Date:   Wed Feb 16 15:04:37 2011 -0600
+
+    [SCSI] iscsi class: add callout to get iscsi_endpoint values
+    
+    For drivers using the ep callbacks the addr and port
+    are attached to the endpoint instead of the conn.
+    This adds a callout to the iscsi_transport to get
+    ep values. It also adds locking around the get
+    param call to make sure that ep_disconnect does
+    not free the LLD's ep interconnect structs from
+    under us (the ep has a refcount so it will not
+    go away but the LLD may have structs from other
+    subsystems that are not allocated in the ep so
+    we need to protect them from getting freed).
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index a631e58894f1..b4218390941e 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -1782,13 +1782,48 @@ iscsi_conn_attr(data_digest, ISCSI_PARAM_DATADGST_EN);
+ iscsi_conn_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN);
+ iscsi_conn_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN);
+ iscsi_conn_attr(persistent_port, ISCSI_PARAM_PERSISTENT_PORT);
+-iscsi_conn_attr(port, ISCSI_PARAM_CONN_PORT);
+ iscsi_conn_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN);
+ iscsi_conn_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS);
+-iscsi_conn_attr(address, ISCSI_PARAM_CONN_ADDRESS);
+ iscsi_conn_attr(ping_tmo, ISCSI_PARAM_PING_TMO);
+ iscsi_conn_attr(recv_tmo, ISCSI_PARAM_RECV_TMO);
+ 
++#define iscsi_conn_ep_attr_show(param)					\
++static ssize_t show_conn_ep_param_##param(struct device *dev,		\
++					  struct device_attribute *attr,\
++					  char *buf)			\
++{									\
++	struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev->parent);	\
++	struct iscsi_transport *t = conn->transport;			\
++	struct iscsi_endpoint *ep;					\
++	ssize_t rc;							\
++									\
++	/*								\
++	 * Need to make sure ep_disconnect does not free the LLD's	\
++	 * interconnect resources while we are trying to read them.	\
++	 */								\
++	mutex_lock(&conn->ep_mutex);					\
++	ep = conn->ep;							\
++	if (!ep && t->ep_connect) {					\
++		mutex_unlock(&conn->ep_mutex);				\
++		return -ENOTCONN;					\
++	}								\
++									\
++	if (ep)								\
++		rc = t->get_ep_param(ep, param, buf);			\
++	else								\
++		rc = t->get_conn_param(conn, param, buf);		\
++	mutex_unlock(&conn->ep_mutex);					\
++	return rc;							\
++}
++
++#define iscsi_conn_ep_attr(field, param)				\
++	iscsi_conn_ep_attr_show(param)					\
++static ISCSI_CLASS_ATTR(conn, field, S_IRUGO,				\
++			show_conn_ep_param_##param, NULL);
++
++iscsi_conn_ep_attr(address, ISCSI_PARAM_CONN_ADDRESS);
++iscsi_conn_ep_attr(port, ISCSI_PARAM_CONN_PORT);
++
+ /*
+  * iSCSI session attrs
+  */
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 00e5bf7c9de6..bf8f52965675 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -101,6 +101,8 @@ struct iscsi_transport {
+ 	void (*destroy_conn) (struct iscsi_cls_conn *conn);
+ 	int (*set_param) (struct iscsi_cls_conn *conn, enum iscsi_param param,
+ 			  char *buf, int buflen);
++	int (*get_ep_param) (struct iscsi_endpoint *ep, enum iscsi_param param,
++			     char *buf);
+ 	int (*get_conn_param) (struct iscsi_cls_conn *conn,
+ 			       enum iscsi_param param, char *buf);
+ 	int (*get_session_param) (struct iscsi_cls_session *session,

commit a79af8a64d395bd89de8695a5ea5e1a7f01f02a8
+Author: Mike Christie 
+Date:   Wed Feb 16 15:04:36 2011 -0600
+
+    [SCSI] iscsi_tcp: use iscsi_conn_get_addr_param libiscsi function
+    
+    This has iscsi_tcp use the iscsi_conn_get_addr_param
+    libiscsi function. It also drops the use of the libiscsi
+    session portal buffers, so they can be removed in
+    the next patches. Instead of copying the values
+    at bind time we get them during get() time. If we are
+    not connected userspace will now get -ENOTCONN,
+    so it knows that connection is disconnected instead
+    of a possible stale value.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index fec47de72535..a860452a8f71 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -608,54 +608,12 @@ static void iscsi_sw_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+ 	iscsi_sw_tcp_release_conn(conn);
+ }
+ 
+-static int iscsi_sw_tcp_get_addr(struct iscsi_conn *conn, struct socket *sock,
+-				 char *buf, int *port,
+-				 int (*getname)(struct socket *,
+-						struct sockaddr *,
+-						int *addrlen))
+-{
+-	struct sockaddr_storage *addr;
+-	struct sockaddr_in6 *sin6;
+-	struct sockaddr_in *sin;
+-	int rc = 0, len;
+-
+-	addr = kmalloc(sizeof(*addr), GFP_KERNEL);
+-	if (!addr)
+-		return -ENOMEM;
+-
+-	if (getname(sock, (struct sockaddr *) addr, &len)) {
+-		rc = -ENODEV;
+-		goto free_addr;
+-	}
+-
+-	switch (addr->ss_family) {
+-	case AF_INET:
+-		sin = (struct sockaddr_in *)addr;
+-		spin_lock_bh(&conn->session->lock);
+-		sprintf(buf, "%pI4", &sin->sin_addr.s_addr);
+-		*port = be16_to_cpu(sin->sin_port);
+-		spin_unlock_bh(&conn->session->lock);
+-		break;
+-	case AF_INET6:
+-		sin6 = (struct sockaddr_in6 *)addr;
+-		spin_lock_bh(&conn->session->lock);
+-		sprintf(buf, "%pI6", &sin6->sin6_addr);
+-		*port = be16_to_cpu(sin6->sin6_port);
+-		spin_unlock_bh(&conn->session->lock);
+-		break;
+-	}
+-free_addr:
+-	kfree(addr);
+-	return rc;
+-}
+-
+ static int
+ iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session,
+ 		       struct iscsi_cls_conn *cls_conn, uint64_t transport_eph,
+ 		       int is_leading)
+ {
+-	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+-	struct iscsi_host *ihost = shost_priv(shost);
++	struct iscsi_session *session = cls_session->dd_data;
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
+@@ -670,27 +628,15 @@ iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session,
+ 				  "sockfd_lookup failed %d\n", err);
+ 		return -EEXIST;
+ 	}
+-	/*
+-	 * copy these values now because if we drop the session
+-	 * userspace may still want to query the values since we will
+-	 * be using them for the reconnect
+-	 */
+-	err = iscsi_sw_tcp_get_addr(conn, sock, conn->portal_address,
+-				    &conn->portal_port, kernel_getpeername);
+-	if (err)
+-		goto free_socket;
+-
+-	err = iscsi_sw_tcp_get_addr(conn, sock, ihost->local_address,
+-				    &ihost->local_port, kernel_getsockname);
+-	if (err)
+-		goto free_socket;
+ 
+ 	err = iscsi_conn_bind(cls_session, cls_conn, is_leading);
+ 	if (err)
+ 		goto free_socket;
+ 
++	spin_lock_bh(&session->lock);
+ 	/* bind iSCSI connection and socket */
+ 	tcp_sw_conn->sock = sock;
++	spin_unlock_bh(&session->lock);
+ 
+ 	/* setup Socket parameters */
+ 	sk = sock->sk;
+@@ -752,24 +698,74 @@ static int iscsi_sw_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ 				       enum iscsi_param param, char *buf)
+ {
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+-	int len;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
++	struct sockaddr_in6 addr;
++	int rc, len;
+ 
+ 	switch(param) {
+ 	case ISCSI_PARAM_CONN_PORT:
+-		spin_lock_bh(&conn->session->lock);
+-		len = sprintf(buf, "%hu\n", conn->portal_port);
+-		spin_unlock_bh(&conn->session->lock);
+-		break;
+ 	case ISCSI_PARAM_CONN_ADDRESS:
+ 		spin_lock_bh(&conn->session->lock);
+-		len = sprintf(buf, "%s\n", conn->portal_address);
++		if (!tcp_sw_conn || !tcp_sw_conn->sock) {
++			spin_unlock_bh(&conn->session->lock);
++			return -ENOTCONN;
++		}
++		rc = kernel_getpeername(tcp_sw_conn->sock,
++					(struct sockaddr *)&addr, &len);
+ 		spin_unlock_bh(&conn->session->lock);
+-		break;
++		if (rc)
++			return rc;
++
++		return iscsi_conn_get_addr_param((struct sockaddr_storage *)
++						 &addr, param, buf);
+ 	default:
+ 		return iscsi_conn_get_param(cls_conn, param, buf);
+ 	}
+ 
+-	return len;
++	return 0;
++}
++
++static int iscsi_sw_tcp_host_get_param(struct Scsi_Host *shost,
++				       enum iscsi_host_param param, char *buf)
++{
++	struct iscsi_sw_tcp_host *tcp_sw_host = iscsi_host_priv(shost);
++	struct iscsi_session *session = tcp_sw_host->session;
++	struct iscsi_conn *conn;
++	struct iscsi_tcp_conn *tcp_conn;
++	struct iscsi_sw_tcp_conn *tcp_sw_conn;
++	struct sockaddr_in6 addr;
++	int rc, len;
++
++	switch (param) {
++	case ISCSI_HOST_PARAM_IPADDRESS:
++		spin_lock_bh(&session->lock);
++		conn = session->leadconn;
++		if (!conn) {
++			spin_unlock_bh(&session->lock);
++			return -ENOTCONN;
++		}
++		tcp_conn = conn->dd_data;
++
++		tcp_sw_conn = tcp_conn->dd_data;
++		if (!tcp_sw_conn->sock) {
++			spin_unlock_bh(&session->lock);
++			return -ENOTCONN;
++		}
++
++		rc = kernel_getsockname(tcp_sw_conn->sock,
++					(struct sockaddr *)&addr, &len);
++		spin_unlock_bh(&session->lock);
++		if (rc)
++			return rc;
++
++		return iscsi_conn_get_addr_param((struct sockaddr_storage *)
++						 &addr, param, buf);
++	default:
++		return iscsi_host_get_param(shost, param, buf);
++	}
++
++	return 0;
+ }
+ 
+ static void
+@@ -797,6 +793,7 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
+ {
+ 	struct iscsi_cls_session *cls_session;
+ 	struct iscsi_session *session;
++	struct iscsi_sw_tcp_host *tcp_sw_host;
+ 	struct Scsi_Host *shost;
+ 
+ 	if (ep) {
+@@ -804,7 +801,8 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
+ 		return NULL;
+ 	}
+ 
+-	shost = iscsi_host_alloc(&iscsi_sw_tcp_sht, 0, 1);
++	shost = iscsi_host_alloc(&iscsi_sw_tcp_sht,
++				 sizeof(struct iscsi_sw_tcp_host), 1);
+ 	if (!shost)
+ 		return NULL;
+ 	shost->transportt = iscsi_sw_tcp_scsi_transport;
+@@ -825,6 +823,8 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
+ 	if (!cls_session)
+ 		goto remove_host;
+ 	session = cls_session->dd_data;
++	tcp_sw_host = iscsi_host_priv(shost);
++	tcp_sw_host->session = session;
+ 
+ 	shost->can_queue = session->scsi_cmds_max;
+ 	if (iscsi_tcp_r2tpool_alloc(session))
+@@ -929,7 +929,7 @@ static struct iscsi_transport iscsi_sw_tcp_transport = {
+ 	.start_conn		= iscsi_conn_start,
+ 	.stop_conn		= iscsi_sw_tcp_conn_stop,
+ 	/* iscsi host params */
+-	.get_host_param		= iscsi_host_get_param,
++	.get_host_param		= iscsi_sw_tcp_host_get_param,
+ 	.set_host_param		= iscsi_host_set_param,
+ 	/* IO */
+ 	.send_pdu		= iscsi_conn_send_pdu,
+diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
+index 94644bad0ed7..666fe09378fa 100644
+--- a/drivers/scsi/iscsi_tcp.h
++++ b/drivers/scsi/iscsi_tcp.h
+@@ -55,6 +55,10 @@ struct iscsi_sw_tcp_conn {
+ 	ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
+ };
+ 
++struct iscsi_sw_tcp_host {
++	struct iscsi_session	*session;
++};
++
+ struct iscsi_sw_tcp_hdrbuf {
+ 	struct iscsi_hdr	hdrbuf;
+ 	char			hdrextbuf[ISCSI_MAX_AHS_SIZE +

commit 00f3708e6ed1698d6aee3901ea991197e31a8007
+Author: Mike Christie 
+Date:   Wed Feb 16 15:04:35 2011 -0600
+
+    [SCSI] libiscsi: add helper to convert addr to string
+    
+    This adds a helper to convert a addr struct to
+    a string. This will be used by the drivers in
+    the next patches.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index da8b61543ee4..0c550d5b9133 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -3352,6 +3352,47 @@ int iscsi_session_get_param(struct iscsi_cls_session *cls_session,
+ }
+ EXPORT_SYMBOL_GPL(iscsi_session_get_param);
+ 
++int iscsi_conn_get_addr_param(struct sockaddr_storage *addr,
++			      enum iscsi_param param, char *buf)
++{
++	struct sockaddr_in6 *sin6 = NULL;
++	struct sockaddr_in *sin = NULL;
++	int len;
++
++	switch (addr->ss_family) {
++	case AF_INET:
++		sin = (struct sockaddr_in *)addr;
++		break;
++	case AF_INET6:
++		sin6 = (struct sockaddr_in6 *)addr;
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	switch (param) {
++	case ISCSI_PARAM_CONN_ADDRESS:
++	case ISCSI_HOST_PARAM_IPADDRESS:
++		if (sin)
++			len = sprintf(buf, "%pI4\n", &sin->sin_addr.s_addr);
++		else
++			len = sprintf(buf, "%pI6\n", &sin6->sin6_addr);
++		break;
++	case ISCSI_PARAM_CONN_PORT:
++		if (sin)
++			len = sprintf(buf, "%hu\n", be16_to_cpu(sin->sin_port));
++		else
++			len = sprintf(buf, "%hu\n",
++				      be16_to_cpu(sin6->sin6_port));
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	return len;
++}
++EXPORT_SYMBOL_GPL(iscsi_conn_get_addr_param);
++
+ int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ 			 enum iscsi_param param, char *buf)
+ {
+@@ -3416,9 +3457,6 @@ int iscsi_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param,
+ 	case ISCSI_HOST_PARAM_INITIATOR_NAME:
+ 		len = sprintf(buf, "%s\n", ihost->initiatorname);
+ 		break;
+-	case ISCSI_HOST_PARAM_IPADDRESS:
+-		len = sprintf(buf, "%s\n", ihost->local_address);
+-		break;
+ 	default:
+ 		return -ENOSYS;
+ 	}
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 748382b32b52..4bef19fb3a65 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -394,6 +394,8 @@ extern void iscsi_session_failure(struct iscsi_session *session,
+ 				  enum iscsi_err err);
+ extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ 				enum iscsi_param param, char *buf);
++extern int iscsi_conn_get_addr_param(struct sockaddr_storage *addr,
++				     enum iscsi_param param, char *buf);
+ extern void iscsi_suspend_tx(struct iscsi_conn *conn);
+ extern void iscsi_suspend_queue(struct iscsi_conn *conn);
+ extern void iscsi_conn_queue_work(struct iscsi_conn *conn);

commit bbc5261b2cb5e69754c935ea2466fb22775f0e48
+Author: Mike Christie 
+Date:   Wed Feb 16 15:04:34 2011 -0600
+
+    [SCSI] iscsi class: remove unused active variable
+    
+    The active variable on the iscsi_cls_conn is not used
+    so this patch removes it.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 4e09b68a0789..a631e58894f1 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -976,7 +976,6 @@ iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid)
+ 
+ 	spin_lock_irqsave(&connlock, flags);
+ 	list_add(&conn->conn_list, &connlist);
+-	conn->active = 1;
+ 	spin_unlock_irqrestore(&connlock, flags);
+ 
+ 	ISCSI_DBG_TRANS_CONN(conn, "Completed conn creation\n");
+@@ -1002,7 +1001,6 @@ int iscsi_destroy_conn(struct iscsi_cls_conn *conn)
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&connlock, flags);
+-	conn->active = 0;
+ 	list_del(&conn->conn_list);
+ 	spin_unlock_irqrestore(&connlock, flags);
+ 
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index b9ba349ef257..00e5bf7c9de6 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -163,7 +163,6 @@ struct iscsi_cls_conn {
+ 	struct mutex ep_mutex;
+ 	struct iscsi_endpoint *ep;
+ 
+-	int active;			/* must be accessed with the connlock */
+ 	struct device dev;		/* sysfs transport/container device */
+ };
+ 

commit 22a39fbbfecfea703b686a4626a631d706ccb3ee
+Author: Mike Christie 
+Date:   Wed Feb 16 15:04:33 2011 -0600
+
+    [SCSI] iscsi: fix iscsi_endpoint leak
+    
+    When iscsid restarts it does not know the connection's
+    endpoint, so it is getting leaked. This fixes the problem
+    by having the iscsi class force a disconnect before a
+    new connection is bound.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index f905ecb5704d..4e09b68a0789 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -954,6 +954,7 @@ iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid)
+ 	if (dd_size)
+ 		conn->dd_data = &conn[1];
+ 
++	mutex_init(&conn->ep_mutex);
+ 	INIT_LIST_HEAD(&conn->conn_list);
+ 	conn->transport = transport;
+ 	conn->cid = cid;
+@@ -1430,6 +1431,29 @@ static int iscsi_if_ep_connect(struct iscsi_transport *transport,
+ 	return err;
+ }
+ 
++static int iscsi_if_ep_disconnect(struct iscsi_transport *transport,
++				  u64 ep_handle)
++{
++	struct iscsi_cls_conn *conn;
++	struct iscsi_endpoint *ep;
++
++	if (!transport->ep_disconnect)
++		return -EINVAL;
++
++	ep = iscsi_lookup_endpoint(ep_handle);
++	if (!ep)
++		return -EINVAL;
++	conn = ep->conn;
++	if (conn) {
++		mutex_lock(&conn->ep_mutex);
++		conn->ep = NULL;
++		mutex_unlock(&conn->ep_mutex);
++	}
++
++	transport->ep_disconnect(ep);
++	return 0;
++}
++
+ static int
+ iscsi_if_transport_ep(struct iscsi_transport *transport,
+ 		      struct iscsi_uevent *ev, int msg_type)
+@@ -1454,14 +1478,8 @@ iscsi_if_transport_ep(struct iscsi_transport *transport,
+ 						   ev->u.ep_poll.timeout_ms);
+ 		break;
+ 	case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
+-		if (!transport->ep_disconnect)
+-			return -EINVAL;
+-
+-		ep = iscsi_lookup_endpoint(ev->u.ep_disconnect.ep_handle);
+-		if (!ep)
+-			return -EINVAL;
+-
+-		transport->ep_disconnect(ep);
++		rc = iscsi_if_ep_disconnect(transport,
++					    ev->u.ep_disconnect.ep_handle);
+ 		break;
+ 	}
+ 	return rc;
+@@ -1609,12 +1627,31 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
+ 		session = iscsi_session_lookup(ev->u.b_conn.sid);
+ 		conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid);
+ 
+-		if (session && conn)
+-			ev->r.retcode =	transport->bind_conn(session, conn,
+-					ev->u.b_conn.transport_eph,
+-					ev->u.b_conn.is_leading);
+-		else
++		if (conn && conn->ep)
++			iscsi_if_ep_disconnect(transport, conn->ep->id);
++
++		if (!session || !conn) {
+ 			err = -EINVAL;
++			break;
++		}
++
++		ev->r.retcode =	transport->bind_conn(session, conn,
++						ev->u.b_conn.transport_eph,
++						ev->u.b_conn.is_leading);
++		if (ev->r.retcode || !transport->ep_connect)
++			break;
++
++		ep = iscsi_lookup_endpoint(ev->u.b_conn.transport_eph);
++		if (ep) {
++			ep->conn = conn;
++
++			mutex_lock(&conn->ep_mutex);
++			conn->ep = ep;
++			mutex_unlock(&conn->ep_mutex);
++		} else
++			iscsi_cls_conn_printk(KERN_ERR, conn,
++					      "Could not set ep conn "
++					      "binding\n");
+ 		break;
+ 	case ISCSI_UEVENT_SET_PARAM:
+ 		err = iscsi_set_param(transport, ev);
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 7fff94b3b2a8..b9ba349ef257 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -160,6 +160,8 @@ struct iscsi_cls_conn {
+ 	void *dd_data;			/* LLD private data */
+ 	struct iscsi_transport *transport;
+ 	uint32_t cid;			/* connection id */
++	struct mutex ep_mutex;
++	struct iscsi_endpoint *ep;
+ 
+ 	int active;			/* must be accessed with the connlock */
+ 	struct device dev;		/* sysfs transport/container device */
+@@ -222,6 +224,7 @@ struct iscsi_endpoint {
+ 	void *dd_data;			/* LLD private data */
+ 	struct device dev;
+ 	uint64_t id;
++	struct iscsi_cls_conn *conn;
+ };
+ 
+ /*

commit fdafd4dfc7bbdd40a4692192b77299b28c8a948f
+Author: Mike Christie 
+Date:   Wed Feb 16 15:04:32 2011 -0600
+
+    [SCSI] cxgbi: enable TEXT PDU support
+    
+    cxgb3i and cxgb4i support TEXT PDU offloading, so set
+    the bits to enable it.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
+index e2362b97f329..69a6769c633e 100644
+--- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
++++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
+@@ -105,7 +105,7 @@ static struct iscsi_transport cxgb3i_iscsi_transport = {
+ 	/* owner and name should be set already */
+ 	.caps		= CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST
+ 				| CAP_DATADGST | CAP_DIGEST_OFFLOAD |
+-				CAP_PADDING_OFFLOAD,
++				CAP_PADDING_OFFLOAD | CAP_TEXT_NEGO,
+ 	.param_mask	= ISCSI_MAX_RECV_DLENGTH | ISCSI_MAX_XMIT_DLENGTH |
+ 				ISCSI_HDRDGST_EN | ISCSI_DATADGST_EN |
+ 				ISCSI_INITIAL_R2T_EN | ISCSI_MAX_R2T |
+diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+index 5b1f0785dafd..719aa71f5b10 100644
+--- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
++++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+@@ -106,7 +106,7 @@ static struct iscsi_transport cxgb4i_iscsi_transport = {
+ 	.name		= DRV_MODULE_NAME,
+ 	.caps		= CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST |
+ 				CAP_DATADGST | CAP_DIGEST_OFFLOAD |
+-				CAP_PADDING_OFFLOAD,
++				CAP_PADDING_OFFLOAD | CAP_TEXT_NEGO,
+ 	.param_mask	= ISCSI_MAX_RECV_DLENGTH | ISCSI_MAX_XMIT_DLENGTH |
+ 				ISCSI_HDRDGST_EN | ISCSI_DATADGST_EN |
+ 				ISCSI_INITIAL_R2T_EN | ISCSI_MAX_R2T |

commit bfcf72e4426da2fd8f8081a641385ffc3ccc2282
+Author: Mike Christie 
+Date:   Fri Dec 31 02:22:22 2010 -0600
+
+    [SCSI] libiscsi: use bh locking instead of irq with session lock
+    
+    The session lock is taken in threads, timers, and bottom halves
+    like softirqs and tasklets. All the code but
+    iscsi_conn/session_failure take the session lock with the spin_lock_bh
+    call. This was done because I thought some offload drivers
+    would be calling these functions from a irq. They never did,
+    so this patch has iscsi_conn/session_failure use the bh
+    locking.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 1def8e101249..da8b61543ee4 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1338,17 +1338,16 @@ void iscsi_session_failure(struct iscsi_session *session,
+ {
+ 	struct iscsi_conn *conn;
+ 	struct device *dev;
+-	unsigned long flags;
+ 
+-	spin_lock_irqsave(&session->lock, flags);
++	spin_lock_bh(&session->lock);
+ 	conn = session->leadconn;
+ 	if (session->state == ISCSI_STATE_TERMINATE || !conn) {
+-		spin_unlock_irqrestore(&session->lock, flags);
++		spin_unlock_bh(&session->lock);
+ 		return;
+ 	}
+ 
+ 	dev = get_device(&conn->cls_conn->dev);
+-	spin_unlock_irqrestore(&session->lock, flags);
++	spin_unlock_bh(&session->lock);
+ 	if (!dev)
+ 	        return;
+ 	/*
+@@ -1367,17 +1366,16 @@ EXPORT_SYMBOL_GPL(iscsi_session_failure);
+ void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
+ {
+ 	struct iscsi_session *session = conn->session;
+-	unsigned long flags;
+ 
+-	spin_lock_irqsave(&session->lock, flags);
++	spin_lock_bh(&session->lock);
+ 	if (session->state == ISCSI_STATE_FAILED) {
+-		spin_unlock_irqrestore(&session->lock, flags);
++		spin_unlock_bh(&session->lock);
+ 		return;
+ 	}
+ 
+ 	if (conn->stop_stage == 0)
+ 		session->state = ISCSI_STATE_FAILED;
+-	spin_unlock_irqrestore(&session->lock, flags);
++	spin_unlock_bh(&session->lock);
+ 
+ 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+ 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);

commit f41d472179a0d7c8e8160c85180ab1124947068e
+Author: Mike Christie 
+Date:   Fri Dec 31 02:22:21 2010 -0600
+
+    [SCSI] libiscsi: do not take host lock in queuecommand
+    
+    iscsi_tcp, ib_iser, cxgb*, be2iscsi and bnx2i do not use
+    the host lock and do not take the session lock against
+    a irq, so this patch drops the DEF_SCSI_QCMD use. Instead
+    we just take the session lock and disable bhs.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 3eddab0774e4..1def8e101249 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -505,6 +505,7 @@ static void iscsi_free_task(struct iscsi_task *task)
+ 	struct iscsi_conn *conn = task->conn;
+ 	struct iscsi_session *session = conn->session;
+ 	struct scsi_cmnd *sc = task->sc;
++	int oldstate = task->state;
+ 
+ 	ISCSI_DBG_SESSION(session, "freeing task itt 0x%x state %d sc %p\n",
+ 			  task->itt, task->state, task->sc);
+@@ -525,10 +526,10 @@ static void iscsi_free_task(struct iscsi_task *task)
+ 		/* SCSI eh reuses commands to verify us */
+ 		sc->SCp.ptr = NULL;
+ 		/*
+-		 * queue command may call this to free the task, but
+-		 * not have setup the sc callback
++		 * queue command may call this to free the task, so
++		 * it will decide how to return sc to scsi-ml.
+ 		 */
+-		if (sc->scsi_done)
++		if (oldstate != ISCSI_TASK_REQUEUE_SCSIQ)
+ 			sc->scsi_done(sc);
+ 	}
+ }
+@@ -572,7 +573,8 @@ static void iscsi_complete_task(struct iscsi_task *task, int state)
+ 			  task->itt, task->state, task->sc);
+ 	if (task->state == ISCSI_TASK_COMPLETED ||
+ 	    task->state == ISCSI_TASK_ABRT_TMF ||
+-	    task->state == ISCSI_TASK_ABRT_SESS_RECOV)
++	    task->state == ISCSI_TASK_ABRT_SESS_RECOV ||
++	    task->state == ISCSI_TASK_REQUEUE_SCSIQ)
+ 		return;
+ 	WARN_ON_ONCE(task->state == ISCSI_TASK_FREE);
+ 	task->state = state;
+@@ -1600,27 +1602,23 @@ enum {
+ 	FAILURE_SESSION_NOT_READY,
+ };
+ 
+-static int iscsi_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
++int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc)
+ {
+ 	struct iscsi_cls_session *cls_session;
+-	struct Scsi_Host *host;
+ 	struct iscsi_host *ihost;
+ 	int reason = 0;
+ 	struct iscsi_session *session;
+ 	struct iscsi_conn *conn;
+ 	struct iscsi_task *task = NULL;
+ 
+-	sc->scsi_done = done;
+ 	sc->result = 0;
+ 	sc->SCp.ptr = NULL;
+ 
+-	host = sc->device->host;
+ 	ihost = shost_priv(host);
+-	spin_unlock(host->host_lock);
+ 
+ 	cls_session = starget_to_session(scsi_target(sc->device));
+ 	session = cls_session->dd_data;
+-	spin_lock(&session->lock);
++	spin_lock_bh(&session->lock);
+ 
+ 	reason = iscsi_session_chkready(cls_session);
+ 	if (reason) {
+@@ -1706,25 +1704,21 @@ static int iscsi_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi
+ 	}
+ 
+ 	session->queued_cmdsn++;
+-	spin_unlock(&session->lock);
+-	spin_lock(host->host_lock);
++	spin_unlock_bh(&session->lock);
+ 	return 0;
+ 
+ prepd_reject:
+-	sc->scsi_done = NULL;
+-	iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
++	iscsi_complete_task(task, ISCSI_TASK_REQUEUE_SCSIQ);
+ reject:
+-	spin_unlock(&session->lock);
++	spin_unlock_bh(&session->lock);
+ 	ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n",
+ 			  sc->cmnd[0], reason);
+-	spin_lock(host->host_lock);
+ 	return SCSI_MLQUEUE_TARGET_BUSY;
+ 
+ prepd_fault:
+-	sc->scsi_done = NULL;
+-	iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
++	iscsi_complete_task(task, ISCSI_TASK_REQUEUE_SCSIQ);
+ fault:
+-	spin_unlock(&session->lock);
++	spin_unlock_bh(&session->lock);
+ 	ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n",
+ 			  sc->cmnd[0], reason);
+ 	if (!scsi_bidi_cmnd(sc))
+@@ -1733,12 +1727,9 @@ static int iscsi_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi
+ 		scsi_out(sc)->resid = scsi_out(sc)->length;
+ 		scsi_in(sc)->resid = scsi_in(sc)->length;
+ 	}
+-	done(sc);
+-	spin_lock(host->host_lock);
++	sc->scsi_done(sc);
+ 	return 0;
+ }
+-
+-DEF_SCSI_QCMD(iscsi_queuecommand)
+ EXPORT_SYMBOL_GPL(iscsi_queuecommand);
+ 
+ int iscsi_change_queue_depth(struct scsi_device *sdev, int depth, int reason)
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 68e951d79f0b..748382b32b52 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -89,6 +89,7 @@ enum {
+ 	ISCSI_TASK_RUNNING,
+ 	ISCSI_TASK_ABRT_TMF,		/* aborted due to TMF */
+ 	ISCSI_TASK_ABRT_SESS_RECOV,	/* aborted due to session recovery */
++	ISCSI_TASK_REQUEUE_SCSIQ,	/* qcmd requeueing to scsi-ml */
+ };
+ 
+ struct iscsi_r2t_info {
+@@ -341,7 +342,7 @@ extern int iscsi_eh_abort(struct scsi_cmnd *sc);
+ extern int iscsi_eh_recover_target(struct scsi_cmnd *sc);
+ extern int iscsi_eh_session_reset(struct scsi_cmnd *sc);
+ extern int iscsi_eh_device_reset(struct scsi_cmnd *sc);
+-extern int iscsi_queuecommand(struct Scsi_Host *h, struct scsi_cmnd *sc);
++extern int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc);
+ 
+ /*
+  * iSCSI host helpers.

commit 1227633a441363642cdbaf38c4241d071e917095
+Author: Mike Christie 
+Date:   Fri Dec 31 02:22:20 2010 -0600
+
+    [SCSI] be2iscsi: fix null ptr when accessing task hdr
+    
+    If alloc_pdu fails then the task->hdr pointer may not be
+    set. This adds a check for this case in the cleanup callback.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
+index be07ca06177e..79cefbe31367 100644
+--- a/drivers/scsi/be2iscsi/be_main.c
++++ b/drivers/scsi/be2iscsi/be_main.c
+@@ -3914,7 +3914,8 @@ static void beiscsi_cleanup_task(struct iscsi_task *task)
+ 			io_task->psgl_handle = NULL;
+ 		}
+ 	} else {
+-		if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN)
++		if (task->hdr &&
++		   ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN))
+ 			return;
+ 		if (io_task->psgl_handle) {
+ 			spin_lock(&phba->mgmt_sgl_lock);

commit bc7accec8788ada4f459461194c2b8fad94ed239
+Author: Mike Christie 
+Date:   Fri Dec 31 02:22:19 2010 -0600
+
+    [SCSI] be2iscsi: fix gfp use in alloc_pdu
+    
+    The pdu allication callout is called from a spin lock
+    and in the IO path so we cannot use GFP_KERNEL. This
+    has the driver use GFP_ATOMIC.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
+index 75a85aa9e882..be07ca06177e 100644
+--- a/drivers/scsi/be2iscsi/be_main.c
++++ b/drivers/scsi/be2iscsi/be_main.c
+@@ -3785,7 +3785,7 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
+ 	dma_addr_t paddr;
+ 
+ 	io_task->cmd_bhs = pci_pool_alloc(beiscsi_sess->bhs_pool,
+-					  GFP_KERNEL, &paddr);
++					  GFP_ATOMIC, &paddr);
+ 	if (!io_task->cmd_bhs)
+ 		return -ENOMEM;
+ 	io_task->bhs_pa.u.a64.address = paddr;

commit df4da5cdfca05b37b366b9c69925b68586969c1c
+Author: Mike Christie 
+Date:   Fri Dec 31 02:22:18 2010 -0600
+
+    [SCSI] libiscsi: add more informative failure message during iscsi scsi eh
+    
+    This adds a more informative error code and message
+    for the iscsi scsi eh session drop paths. This allows
+    you to distinguish if the session was dropped due to
+    a connection failure vs the iscsi layer dropping
+    the session due to scsi eh failure processing.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 7551abe40900..3eddab0774e4 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1796,9 +1796,9 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn,
+ 				      NULL, 0);
+ 	if (!task) {
+ 		spin_unlock_bh(&session->lock);
++		iscsi_conn_printk(KERN_ERR, conn, "Could not send TMF.\n");
+ 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ 		spin_lock_bh(&session->lock);
+-		ISCSI_DBG_EH(session, "tmf exec failure\n");
+ 		return -EPERM;
+ 	}
+ 	conn->tmfcmd_pdus_cnt++;
+@@ -2203,7 +2203,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 		goto success_unlocked;
+ 	case TMF_TIMEDOUT:
+ 		spin_unlock_bh(&session->lock);
+-		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
++		iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST);
+ 		goto failed_unlocked;
+ 	case TMF_NOT_FOUND:
+ 		if (!sc->SCp.ptr) {
+@@ -2290,7 +2290,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc)
+ 		break;
+ 	case TMF_TIMEDOUT:
+ 		spin_unlock_bh(&session->lock);
+-		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
++		iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST);
+ 		goto done;
+ 	default:
+ 		conn->tmf_state = TMF_INITIAL;
+@@ -2371,7 +2371,7 @@ int iscsi_eh_session_reset(struct scsi_cmnd *sc)
+ 	 * we drop the lock here but the leadconn cannot be destoyed while
+ 	 * we are in the scsi eh
+ 	 */
+-	iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
++	iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST);
+ 
+ 	ISCSI_DBG_EH(session, "wait for relogin\n");
+ 	wait_event_interruptible(conn->ehwait,
+@@ -2453,7 +2453,7 @@ int iscsi_eh_target_reset(struct scsi_cmnd *sc)
+ 		break;
+ 	case TMF_TIMEDOUT:
+ 		spin_unlock_bh(&session->lock);
+-		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
++		iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST);
+ 		goto done;
+ 	default:
+ 		conn->tmf_state = TMF_INITIAL;
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index a8631acd37c3..c3e1cbcc2ad2 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -263,6 +263,7 @@ enum iscsi_err {
+ 	ISCSI_ERR_INVALID_HOST		= ISCSI_ERR_BASE + 18,
+ 	ISCSI_ERR_XMIT_FAILED		= ISCSI_ERR_BASE + 19,
+ 	ISCSI_ERR_TCP_CONN_CLOSE	= ISCSI_ERR_BASE + 20,
++	ISCSI_ERR_SCSI_EH_SESSION_RST	= ISCSI_ERR_BASE + 21,
+ };
+ 
+ /*

commit a1e0063d0c015145946981262f8d5f9758d8a895
+Author: Mike Christie 
+Date:   Tue Oct 26 05:45:30 2010 -0700
+
+    [SCSI] qla4xxx: Fix cmd check in qla4xxx_cmd_wait
+    
+    If the command has timedout then the block layer has called
+    blk_mark_rq_complete. If qla4xxx_cmd_wait is then called
+    from qla4xxx_eh_host_reset, we will always fail, because if
+    the driver calls scsi_done then the the block layer will fail
+    at blk_complete_request's blk_mark_rq_complete call instead of
+    calling the normal completion path including the function,
+    blk_queue_end_tag, which releases the tag.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Vikas Chaudhary 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index f1c58eb26ba2..f4cd846abf6d 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -881,7 +881,13 @@ static int qla4xxx_cmd_wait(struct scsi_qla_host *ha)
+ 		/* Find a command that hasn't completed. */
+ 		for (index = 0; index < ha->host->can_queue; index++) {
+ 			cmd = scsi_host_find_tag(ha->host, index);
+-			if (cmd != NULL)
++			/*
++			 * We cannot just check if the index is valid,
++			 * becase if we are run from the scsi eh, then
++			 * the scsi/block layer is going to prevent
++			 * the tag from being released.
++			 */
++			if (cmd != NULL && CMD_SP(cmd))
+ 				break;
+ 		}
+ 		spin_unlock_irqrestore(&ha->hardware_lock, flags);

commit 170babc3721997b7808193221f94926df44f3d1e
+Author: Mike Christie 
+Date:   Fri Oct 15 11:27:47 2010 -0700
+
+    [SCSI] qla2xxx: Drop srb reference before waiting for completion.
+    
+    This patch fixes a regression introduced by commit
+    083a469db4ecf3b286a96b5b722c37fc1affe0be
+    
+    qla2xxx_eh_wait_on_command() is waiting for an srb to
+    complete, which will never happen as the routine took
+    a reference to the srb previously and will only drop it
+    after this function. So every command abort will fail.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Giridhar Malavali 
+    Signed-off-by: Madhuranath Iyengar 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
+index 05977e736f76..02232deaf82d 100644
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -830,62 +830,44 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
+ {
+ 	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
+ 	srb_t *sp;
+-	int ret, i;
++	int ret;
+ 	unsigned int id, lun;
+ 	unsigned long flags;
+ 	int wait = 0;
+ 	struct qla_hw_data *ha = vha->hw;
+-	struct req_que *req = vha->req;
+-	srb_t *spt;
+-	int got_ref = 0;
+ 
+ 	fc_block_scsi_eh(cmd);
+ 
+ 	if (!CMD_SP(cmd))
+ 		return SUCCESS;
+ 
+-	ret = SUCCESS;
+-
+ 	id = cmd->device->id;
+ 	lun = cmd->device->lun;
+-	spt = (srb_t *) CMD_SP(cmd);
+-	if (!spt)
+-		return SUCCESS;
+ 
+-	/* Check active list for command command. */
+ 	spin_lock_irqsave(&ha->hardware_lock, flags);
+-	for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) {
+-		sp = req->outstanding_cmds[i];
+-
+-		if (sp == NULL)
+-			continue;
+-		if ((sp->ctx) && !(sp->flags & SRB_FCP_CMND_DMA_VALID) &&
+-		    !IS_PROT_IO(sp))
+-			continue;
+-		if (sp->cmd != cmd)
+-			continue;
++	sp = (srb_t *) CMD_SP(cmd);
++	if (!sp) {
++		spin_unlock_irqrestore(&ha->hardware_lock, flags);
++		return SUCCESS;
++	}
+ 
+-		DEBUG2(printk("%s(%ld): aborting sp %p from RISC.",
+-		    __func__, vha->host_no, sp));
++	DEBUG2(printk("%s(%ld): aborting sp %p from RISC.",
++	    __func__, vha->host_no, sp));
+ 
+-		/* Get a reference to the sp and drop the lock.*/
+-		sp_get(sp);
+-		got_ref++;
++	/* Get a reference to the sp and drop the lock.*/
++	sp_get(sp);
+ 
+-		spin_unlock_irqrestore(&ha->hardware_lock, flags);
+-		if (ha->isp_ops->abort_command(sp)) {
+-			DEBUG2(printk("%s(%ld): abort_command "
+-			"mbx failed.\n", __func__, vha->host_no));
+-			ret = FAILED;
+-		} else {
+-			DEBUG3(printk("%s(%ld): abort_command "
+-			"mbx success.\n", __func__, vha->host_no));
+-			wait = 1;
+-		}
+-		spin_lock_irqsave(&ha->hardware_lock, flags);
+-		break;
+-	}
+ 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
++	if (ha->isp_ops->abort_command(sp)) {
++		DEBUG2(printk("%s(%ld): abort_command "
++		"mbx failed.\n", __func__, vha->host_no));
++		ret = FAILED;
++	} else {
++		DEBUG3(printk("%s(%ld): abort_command "
++		"mbx success.\n", __func__, vha->host_no));
++		wait = 1;
++	}
++	qla2x00_sp_compl(ha, sp);
+ 
+ 	/* Wait for the command to be returned. */
+ 	if (wait) {
+@@ -897,9 +879,6 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
+ 		}
+ 	}
+ 
+-	if (got_ref)
+-		qla2x00_sp_compl(ha, sp);
+-
+ 	qla_printk(KERN_INFO, ha,
+ 	    "scsi(%ld:%d:%d): Abort command issued -- %d %x.\n",
+ 	    vha->host_no, id, lun, wait, ret);

commit 73b4376477672a4336cba5f26ede2e277511ce70
+Author: Mike Christie 
+Date:   Fri Oct 8 17:12:10 2010 -0700
+
+    [SCSI] libfc: fix setting of rport dev loss
+    
+    There does not seem to be a reason why libfc adds a 5
+    second delay to the user requested value for the dev loss
+    tmo. There also does not seem to be a reason to allow
+    setting it to 0 (or really close).
+    
+    This patch removes the extra 5 sec delay, and for 0 it
+    sets it to 1 like other fc drivers. We should actually
+    be able to set it to 0 since the queue_delayed_work API
+    will just call queue_work, but other drivers set it to 1 in
+    that case.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Robert Love 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
+index b9f2286fe0cb..a84ef13ed74a 100644
+--- a/drivers/scsi/libfc/fc_rport.c
++++ b/drivers/scsi/libfc/fc_rport.c
+@@ -196,9 +196,9 @@ static const char *fc_rport_state(struct fc_rport_priv *rdata)
+ void fc_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout)
+ {
+ 	if (timeout)
+-		rport->dev_loss_tmo = timeout + 5;
++		rport->dev_loss_tmo = timeout;
+ 	else
+-		rport->dev_loss_tmo = 30;
++		rport->dev_loss_tmo = 1;
+ }
+ EXPORT_SYMBOL(fc_set_rport_loss_tmo);
+ 

commit 92b3e5bbbebe86dd0071ccf23c1b21031f74bf56
+Author: Mike Christie 
+Date:   Wed Oct 6 22:51:17 2010 -0700
+
+    [SCSI] qla4xxx: grab hardware_lock in eh_abort before accessing srb
+    
+    grab hardware_lock in eh_abort before accessing srb to avoid
+    race between command completion and get refcount on srb.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Vikas Chaudhary 
+    Signed-off-by: Ravi Anand 
+    Reviewed-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index 4b6cdb68a52a..f1c58eb26ba2 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -2006,6 +2006,7 @@ static int qla4xxx_eh_abort(struct scsi_cmnd *cmd)
+ 	unsigned int id = cmd->device->id;
+ 	unsigned int lun = cmd->device->lun;
+ 	unsigned long serial = cmd->serial_number;
++	unsigned long flags;
+ 	struct srb *srb = NULL;
+ 	int ret = SUCCESS;
+ 	int wait = 0;
+@@ -2014,12 +2015,14 @@ static int qla4xxx_eh_abort(struct scsi_cmnd *cmd)
+ 	    "scsi%ld:%d:%d: Abort command issued cmd=%p, pid=%ld\n",
+ 	    ha->host_no, id, lun, cmd, serial);
+ 
++	spin_lock_irqsave(&ha->hardware_lock, flags);
+ 	srb = (struct srb *) CMD_SP(cmd);
+-
+-	if (!srb)
++	if (!srb) {
++		spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ 		return SUCCESS;
+-
++	}
+ 	kref_get(&srb->srb_ref);
++	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ 
+ 	if (qla4xxx_abort_task(ha, srb) != QLA_SUCCESS) {
+ 		DEBUG3(printk("scsi%ld:%d:%d: Abort_task mbx failed.\n",

commit 986fe6c7f50974e871b8ab5a800f5310ea25b361
+Author: Mike Christie 
+Date:   Wed Oct 6 03:10:59 2010 -0500
+
+    [SCSI] Fix regressions in scsi_internal_device_block
+    
+    Deleting a SCSI device on a blocked fc_remote_port (before
+    fast_io_fail_tmo fires) results in a hanging thread:
+    
+      STACK:
+      0 schedule+1108 [0x5cac48]
+      1 schedule_timeout+528 [0x5cb7fc]
+      2 wait_for_common+266 [0x5ca6be]
+      3 blk_execute_rq+160 [0x354054]
+      4 scsi_execute+324 [0x3b7ef4]
+      5 scsi_execute_req+162 [0x3b80ca]
+      6 sd_sync_cache+138 [0x3cf662]
+      7 sd_shutdown+138 [0x3cf91a]
+      8 sd_remove+112 [0x3cfe4c]
+      9 __device_release_driver+124 [0x3a08b8]
+    10 device_release_driver+60 [0x3a0a5c]
+    11 bus_remove_device+266 [0x39fa76]
+    12 device_del+340 [0x39d818]
+    13 __scsi_remove_device+204 [0x3bcc48]
+    14 scsi_remove_device+66 [0x3bcc8e]
+    15 sysfs_schedule_callback_work+50 [0x260d66]
+    16 worker_thread+622 [0x162326]
+    17 kthread+160 [0x1680b0]
+    18 kernel_thread_starter+6 [0x10aaea]
+    
+    During the delete, the SCSI device is in moved to SDEV_CANCEL.  When
+    the FC transport class later calls scsi_target_unblock, this has no
+    effect, since scsi_internal_device_unblock ignores SCSI devics in this
+    state.
+    
+    It looks like all these are regressions caused by:
+    5c10e63c943b4c67561ddc6bf61e01d4141f881f
+    [SCSI] limit state transitions in scsi_internal_device_unblock
+    
+    Fix by rejecting offline and cancel in the state transition.
+    
+    Signed-off-by: Christof Schmitt 
+    [jejb: Original patch by Christof Schmitt, modified by Mike Christie]
+    Cc: Stable Tree 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index 8041fe1ab179..eafeeda6e194 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -2438,7 +2438,8 @@ scsi_internal_device_unblock(struct scsi_device *sdev)
+ 		sdev->sdev_state = SDEV_RUNNING;
+ 	else if (sdev->sdev_state == SDEV_CREATED_BLOCK)
+ 		sdev->sdev_state = SDEV_CREATED;
+-	else
++	else if (sdev->sdev_state != SDEV_CANCEL &&
++		 sdev->sdev_state != SDEV_OFFLINE)
+ 		return -EINVAL;
+ 
+ 	spin_lock_irqsave(q->queue_lock, flags);

commit 43ca910a9c90566308f39f51ac03a55f94a5f83c
+Author: Mike Christie 
+Date:   Wed Sep 15 16:52:32 2010 -0500
+
+    [SCSI] fc class: add fc host dev loss sysfs file
+    
+    This adds a fc host dev loss sysfs file. Instead of
+    calling into the driver using the get_host_def_dev_loss_tmo
+    callback, we allow drivers to init the dev loss like is done
+    for other fc host params, and then the fc class will handle
+    updating the value if the user writes to the new sysfs file.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
+index 78486d540652..998c01be3234 100644
+--- a/drivers/scsi/scsi_transport_fc.c
++++ b/drivers/scsi/scsi_transport_fc.c
+@@ -52,6 +52,25 @@ static int fc_bsg_rportadd(struct Scsi_Host *, struct fc_rport *);
+ static void fc_bsg_remove(struct request_queue *);
+ static void fc_bsg_goose_queue(struct fc_rport *);
+ 
++/*
++ * Module Parameters
++ */
++
++/*
++ * dev_loss_tmo: the default number of seconds that the FC transport
++ *   should insulate the loss of a remote port.
++ *   The maximum will be capped by the value of SCSI_DEVICE_BLOCK_MAX_TIMEOUT.
++ */
++static unsigned int fc_dev_loss_tmo = 60;		/* seconds */
++
++module_param_named(dev_loss_tmo, fc_dev_loss_tmo, uint, S_IRUGO|S_IWUSR);
++MODULE_PARM_DESC(dev_loss_tmo,
++		 "Maximum number of seconds that the FC transport should"
++		 " insulate the loss of a remote port. Once this value is"
++		 " exceeded, the scsi target is removed. Value should be"
++		 " between 1 and SCSI_DEVICE_BLOCK_MAX_TIMEOUT if"
++		 " fast_io_fail_tmo is not set.");
++
+ /*
+  * Redefine so that we can have same named attributes in the
+  * sdev/starget/host objects.
+@@ -408,6 +427,7 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev,
+ 	if (!fc_host->work_q)
+ 		return -ENOMEM;
+ 
++	fc_host->dev_loss_tmo = fc_dev_loss_tmo;
+ 	snprintf(fc_host->devloss_work_q_name,
+ 		 sizeof(fc_host->devloss_work_q_name),
+ 		 "fc_dl_%d", shost->host_no);
+@@ -461,25 +481,6 @@ static DECLARE_TRANSPORT_CLASS(fc_vport_class,
+ 			       NULL,
+ 			       NULL);
+ 
+-/*
+- * Module Parameters
+- */
+-
+-/*
+- * dev_loss_tmo: the default number of seconds that the FC transport
+- *   should insulate the loss of a remote port.
+- *   The maximum will be capped by the value of SCSI_DEVICE_BLOCK_MAX_TIMEOUT.
+- */
+-static unsigned int fc_dev_loss_tmo = 60;		/* seconds */
+-
+-module_param_named(dev_loss_tmo, fc_dev_loss_tmo, uint, S_IRUGO|S_IWUSR);
+-MODULE_PARM_DESC(dev_loss_tmo,
+-		 "Maximum number of seconds that the FC transport should"
+-		 " insulate the loss of a remote port. Once this value is"
+-		 " exceeded, the scsi target is removed. Value should be"
+-		 " between 1 and SCSI_DEVICE_BLOCK_MAX_TIMEOUT if"
+-		 " fast_io_fail_tmo is not set.");
+-
+ /*
+  * Netlink Infrastructure
+  */
+@@ -830,24 +831,32 @@ static FC_DEVICE_ATTR(rport, supported_classes, S_IRUGO,
+ /*
+  * dev_loss_tmo attribute
+  */
+-fc_rport_show_function(dev_loss_tmo, "%d\n", 20, )
+-static ssize_t
+-store_fc_rport_dev_loss_tmo(struct device *dev, struct device_attribute *attr,
+-			    const char *buf, size_t count)
++static int fc_str_to_dev_loss(const char *buf, unsigned long *val)
++{
++	char *cp;
++
++	*val = simple_strtoul(buf, &cp, 0);
++	if ((*cp && (*cp != '\n')) || (*val < 0))
++		return -EINVAL;
++	/*
++	 * Check for overflow; dev_loss_tmo is u32
++	 */
++	if (*val > UINT_MAX)
++		return -EINVAL;
++
++	return 0;
++}
++
++static int fc_rport_set_dev_loss_tmo(struct fc_rport *rport,
++				     unsigned long val)
+ {
+-	unsigned long val;
+-	struct fc_rport *rport = transport_class_to_rport(dev);
+ 	struct Scsi_Host *shost = rport_to_shost(rport);
+ 	struct fc_internal *i = to_fc_internal(shost->transportt);
+-	char *cp;
++
+ 	if ((rport->port_state == FC_PORTSTATE_BLOCKED) ||
+ 	    (rport->port_state == FC_PORTSTATE_DELETED) ||
+ 	    (rport->port_state == FC_PORTSTATE_NOTPRESENT))
+ 		return -EBUSY;
+-	val = simple_strtoul(buf, &cp, 0);
+-	if ((*cp && (*cp != '\n')) || (val < 0))
+-		return -EINVAL;
+-
+ 	/*
+ 	 * Check for overflow; dev_loss_tmo is u32
+ 	 */
+@@ -863,6 +872,25 @@ store_fc_rport_dev_loss_tmo(struct device *dev, struct device_attribute *attr,
+ 		return -EINVAL;
+ 
+ 	i->f->set_rport_dev_loss_tmo(rport, val);
++	return 0;
++}
++
++fc_rport_show_function(dev_loss_tmo, "%d\n", 20, )
++static ssize_t
++store_fc_rport_dev_loss_tmo(struct device *dev, struct device_attribute *attr,
++			    const char *buf, size_t count)
++{
++	struct fc_rport *rport = transport_class_to_rport(dev);
++	unsigned long val;
++	int rc;
++
++	rc = fc_str_to_dev_loss(buf, &val);
++	if (rc)
++		return rc;
++
++	rc = fc_rport_set_dev_loss_tmo(rport, val);
++	if (rc)
++		return rc;
+ 	return count;
+ }
+ static FC_DEVICE_ATTR(rport, dev_loss_tmo, S_IRUGO | S_IWUSR,
+@@ -1608,8 +1636,35 @@ store_fc_private_host_issue_lip(struct device *dev,
+ static FC_DEVICE_ATTR(host, issue_lip, S_IWUSR, NULL,
+ 			store_fc_private_host_issue_lip);
+ 
+-fc_private_host_rd_attr(npiv_vports_inuse, "%u\n", 20);
++static ssize_t
++store_fc_private_host_dev_loss_tmo(struct device *dev,
++				   struct device_attribute *attr,
++				   const char *buf, size_t count)
++{
++	struct Scsi_Host *shost = transport_class_to_shost(dev);
++	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
++	struct fc_rport *rport;
++	unsigned long val, flags;
++	int rc;
++
++	rc = fc_str_to_dev_loss(buf, &val);
++	if (rc)
++		return rc;
++
++	fc_host_dev_loss_tmo(shost) = val;
++	spin_lock_irqsave(shost->host_lock, flags);
++	list_for_each_entry(rport, &fc_host->rports, peers)
++		fc_rport_set_dev_loss_tmo(rport, val);
++	spin_unlock_irqrestore(shost->host_lock, flags);
++	return count;
++}
+ 
++fc_private_host_show_function(dev_loss_tmo, "%d\n", 20, );
++static FC_DEVICE_ATTR(host, dev_loss_tmo, S_IRUGO | S_IWUSR,
++		      show_fc_host_dev_loss_tmo,
++		      store_fc_private_host_dev_loss_tmo);
++
++fc_private_host_rd_attr(npiv_vports_inuse, "%u\n", 20);
+ 
+ /*
+  * Host Statistics Management
+@@ -2165,6 +2220,7 @@ fc_attach_transport(struct fc_function_template *ft)
+ 	SETUP_HOST_ATTRIBUTE_RW(system_hostname);
+ 
+ 	/* Transport-managed attributes */
++	SETUP_PRIVATE_HOST_ATTRIBUTE_RW(dev_loss_tmo);
+ 	SETUP_PRIVATE_HOST_ATTRIBUTE_RW(tgtid_bind_type);
+ 	if (ft->issue_fc_host_lip)
+ 		SETUP_PRIVATE_HOST_ATTRIBUTE_RW(issue_lip);
+@@ -2525,11 +2581,7 @@ fc_rport_create(struct Scsi_Host *shost, int channel,
+ 
+ 	rport->maxframe_size = -1;
+ 	rport->supported_classes = FC_COS_UNSPECIFIED;
+-	if (fci->f->get_host_def_dev_loss_tmo) {
+-		fci->f->get_host_def_dev_loss_tmo(shost);
+-		rport->dev_loss_tmo = fc_host_def_dev_loss_tmo(shost);
+-	} else
+-		rport->dev_loss_tmo = fc_dev_loss_tmo;
++	rport->dev_loss_tmo = fc_host->dev_loss_tmo;
+ 	memcpy(&rport->node_name, &ids->node_name, sizeof(rport->node_name));
+ 	memcpy(&rport->port_name, &ids->port_name, sizeof(rport->port_name));
+ 	rport->port_id = ids->port_id;
+diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
+index 9f98fca9b763..59816fe31e68 100644
+--- a/include/scsi/scsi_transport_fc.h
++++ b/include/scsi/scsi_transport_fc.h
+@@ -496,7 +496,7 @@ struct fc_host_attrs {
+ 	u64 fabric_name;
+ 	char symbolic_name[FC_SYMBOLIC_NAME_SIZE];
+ 	char system_hostname[FC_SYMBOLIC_NAME_SIZE];
+-	u32 def_dev_loss_tmo;
++	u32 dev_loss_tmo;
+ 
+ 	/* Private (Transport-managed) Attributes */
+ 	enum fc_tgtid_binding_type  tgtid_bind_type;
+@@ -581,8 +581,8 @@ struct fc_host_attrs {
+ 	(((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q_name)
+ #define fc_host_devloss_work_q(x) \
+ 	(((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q)
+-#define fc_host_def_dev_loss_tmo(x) \
+-	(((struct fc_host_attrs *)(x)->shost_data)->def_dev_loss_tmo)
++#define fc_host_dev_loss_tmo(x) \
++	(((struct fc_host_attrs *)(x)->shost_data)->dev_loss_tmo)
+ 
+ 
+ struct fc_bsg_buffer {
+@@ -643,7 +643,6 @@ struct fc_function_template {
+ 	void	(*get_host_fabric_name)(struct Scsi_Host *);
+ 	void	(*get_host_symbolic_name)(struct Scsi_Host *);
+ 	void	(*set_host_system_hostname)(struct Scsi_Host *);
+-	void	(*get_host_def_dev_loss_tmo)(struct Scsi_Host *);
+ 
+ 	struct fc_host_statistics * (*get_fc_host_stats)(struct Scsi_Host *);
+ 	void	(*reset_fc_host_stats)(struct Scsi_Host *);

commit 0af5d708aae3aef1f98a1c689007b92db2c10277
+Author: Mike Christie 
+Date:   Wed Sep 15 16:52:31 2010 -0500
+
+    [SCSI] lpfc: prep for fc host dev loss tmo support
+    
+    This removes the driver's get_host_def_dev_loss_tmo
+    callback and just has the driver set the dev loss
+    using the fc class fc_host_dev_loss_tmo macro like is
+    done for other fc params.
+    
+    It also adds compat support for the driver's existing
+    dev loss and nodev sysfs and modparams.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
+index 87c2b6b858f7..f6efc6fe86d7 100644
+--- a/drivers/scsi/lpfc/lpfc_attr.c
++++ b/drivers/scsi/lpfc/lpfc_attr.c
+@@ -2159,6 +2159,11 @@ lpfc_nodev_tmo_set(struct lpfc_vport *vport, int val)
+ 	if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) {
+ 		vport->cfg_nodev_tmo = val;
+ 		vport->cfg_devloss_tmo = val;
++		/*
++		 * For compat: set the fc_host dev loss so new rports
++		 * will get the value.
++		 */
++		fc_host_dev_loss_tmo(lpfc_shost_from_vport(vport)) = val;
+ 		lpfc_update_rport_devloss_tmo(vport);
+ 		return 0;
+ 	}
+@@ -2208,6 +2213,7 @@ lpfc_devloss_tmo_set(struct lpfc_vport *vport, int val)
+ 		vport->cfg_nodev_tmo = val;
+ 		vport->cfg_devloss_tmo = val;
+ 		vport->dev_loss_tmo_changed = 1;
++		fc_host_dev_loss_tmo(lpfc_shost_from_vport(vport)) = val;
+ 		lpfc_update_rport_devloss_tmo(vport);
+ 		return 0;
+ 	}
+@@ -4370,14 +4376,6 @@ lpfc_get_starget_port_name(struct scsi_target *starget)
+ 		ndlp ? wwn_to_u64(ndlp->nlp_portname.u.wwn) : 0;
+ }
+ 
+-static void
+-lpfc_get_host_def_loss_tmo(struct Scsi_Host *shost)
+-{
+-        struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-
+-	fc_host_def_dev_loss_tmo(shost) = vport->cfg_devloss_tmo;
+-}
+-
+ /**
+  * lpfc_set_rport_loss_tmo - Set the rport dev loss tmo
+  * @rport: fc rport address.
+@@ -4486,7 +4484,6 @@ struct fc_function_template lpfc_transport_functions = {
+ 	.get_host_fabric_name = lpfc_get_host_fabric_name,
+ 	.show_host_fabric_name = 1,
+ 
+-	.get_host_def_dev_loss_tmo = lpfc_get_host_def_loss_tmo,
+ 	/*
+ 	 * The LPFC driver treats linkdown handling as target loss events
+ 	 * so there are no sysfs handlers for link_down_tmo.
+@@ -4554,7 +4551,6 @@ struct fc_function_template lpfc_vport_transport_functions = {
+ 	.get_host_fabric_name = lpfc_get_host_fabric_name,
+ 	.show_host_fabric_name = 1,
+ 
+-	.get_host_def_dev_loss_tmo = lpfc_get_host_def_loss_tmo,
+ 	/*
+ 	 * The LPFC driver treats linkdown handling as target loss events
+ 	 * so there are no sysfs handlers for link_down_tmo.
+diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
+index da9ba06ad583..87a4d09a6641 100644
+--- a/drivers/scsi/lpfc/lpfc_init.c
++++ b/drivers/scsi/lpfc/lpfc_init.c
+@@ -2817,6 +2817,8 @@ void lpfc_host_attrib_init(struct Scsi_Host *shost)
+ 		(((uint32_t) vport->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) |
+ 		(uint32_t) vport->fc_sparam.cmn.bbRcvSizeLsb;
+ 
++	fc_host_dev_loss_tmo(shost) = vport->cfg_devloss_tmo;
++
+ 	/* This value is also unchanging */
+ 	memset(fc_host_active_fc4s(shost), 0,
+ 	       sizeof(fc_host_active_fc4s(shost)));

commit d2b5f10e5b93633a40d9263383b914f06019f00b
+Author: Mike Christie 
+Date:   Wed Sep 15 16:52:30 2010 -0500
+
+    [SCSI] qla2xxx: prep for fc host dev loss tmo support
+    
+    This removes the driver's get_host_def_dev_loss_tmo
+    callback and just has the driver set the dev loss
+    using the fc class fc_host_dev_loss_tmo macro like is
+    done for other fc params.
+    
+    Signed-off-by: Mike Christie 
+    Acked-by: Andrew Vasquez 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
+index c9781050c9ed..029fe6b9d463 100644
+--- a/drivers/scsi/qla2xxx/qla_attr.c
++++ b/drivers/scsi/qla2xxx/qla_attr.c
+@@ -1529,15 +1529,6 @@ qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
+ 		rport->dev_loss_tmo = 1;
+ }
+ 
+-static void
+-qla2x00_get_host_def_loss_tmo(struct Scsi_Host *shost)
+-{
+-	scsi_qla_host_t *vha = shost_priv(shost);
+-	struct qla_hw_data *ha = vha->hw;
+-
+-	fc_host_def_dev_loss_tmo(shost) = ha->port_down_retry_count;
+-}
+-
+ static void
+ qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport)
+ {
+@@ -1785,6 +1776,7 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
+ 	}
+ 
+ 	/* initialize attributes */
++	fc_host_dev_loss_tmo(vha->host) = ha->port_down_retry_count;
+ 	fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name);
+ 	fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name);
+ 	fc_host_supported_classes(vha->host) =
+@@ -1912,7 +1904,6 @@ struct fc_function_template qla2xxx_transport_functions = {
+ 	.show_host_fabric_name = 1,
+ 	.get_host_port_state = qla2x00_get_host_port_state,
+ 	.show_host_port_state = 1,
+-	.get_host_def_dev_loss_tmo = qla2x00_get_host_def_loss_tmo,
+ 
+ 	.dd_fcrport_size = sizeof(struct fc_port *),
+ 	.show_rport_supported_classes = 1,
+@@ -1959,7 +1950,6 @@ struct fc_function_template qla2xxx_transport_vport_functions = {
+ 	.show_host_fabric_name = 1,
+ 	.get_host_port_state = qla2x00_get_host_port_state,
+ 	.show_host_port_state = 1,
+-	.get_host_def_dev_loss_tmo = qla2x00_get_host_def_loss_tmo,
+ 
+ 	.dd_fcrport_size = sizeof(struct fc_port *),
+ 	.show_rport_supported_classes = 1,
+@@ -1988,6 +1978,7 @@ qla2x00_init_host_attr(scsi_qla_host_t *vha)
+ 	struct qla_hw_data *ha = vha->hw;
+ 	u32 speed = FC_PORTSPEED_UNKNOWN;
+ 
++	fc_host_dev_loss_tmo(vha->host) = ha->port_down_retry_count;
+ 	fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name);
+ 	fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name);
+ 	fc_host_supported_classes(vha->host) = FC_COS_CLASS3;

commit a5110f2983bdf931d9819f88505775b16de8b99e
+Author: Mike Christie 
+Date:   Wed Sep 15 16:52:29 2010 -0500
+
+    [SCSI] ibmvfc: prep for fc host dev loss tmo support
+    
+    This removes the driver's get_host_def_dev_loss_tmo
+    callback and just has the driver set the dev loss
+    using the fc class fc_host_dev_loss_tmo macro like is
+    done for other fc params.
+    
+    This patch also removes the module dev loss param.
+    To override the value the fc host sysfs value being
+    added in the fc class patch can be used instead of the driver
+    module param.
+    
+    Signed-off-by: Mike Christie 
+    Acked-by: Brian King 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
+index b1512e9d1b9d..f033bf39690f 100644
+--- a/drivers/scsi/ibmvscsi/ibmvfc.c
++++ b/drivers/scsi/ibmvscsi/ibmvfc.c
+@@ -50,7 +50,6 @@ static unsigned int max_lun = IBMVFC_MAX_LUN;
+ static unsigned int max_targets = IBMVFC_MAX_TARGETS;
+ static unsigned int max_requests = IBMVFC_MAX_REQUESTS_DEFAULT;
+ static unsigned int disc_threads = IBMVFC_MAX_DISC_THREADS;
+-static unsigned int dev_loss_tmo = IBMVFC_DEV_LOSS_TMO;
+ static unsigned int ibmvfc_debug = IBMVFC_DEBUG;
+ static unsigned int log_level = IBMVFC_DEFAULT_LOG_LEVEL;
+ static LIST_HEAD(ibmvfc_head);
+@@ -84,11 +83,6 @@ MODULE_PARM_DESC(disc_threads, "Number of device discovery threads to use. "
+ module_param_named(debug, ibmvfc_debug, uint, S_IRUGO | S_IWUSR);
+ MODULE_PARM_DESC(debug, "Enable driver debug information. "
+ 		 "[Default=" __stringify(IBMVFC_DEBUG) "]");
+-module_param_named(dev_loss_tmo, dev_loss_tmo, uint, S_IRUGO | S_IWUSR);
+-MODULE_PARM_DESC(dev_loss_tmo, "Maximum number of seconds that the FC "
+-		 "transport should insulate the loss of a remote port. Once this "
+-		 "value is exceeded, the scsi target is removed. "
+-		 "[Default=" __stringify(IBMVFC_DEV_LOSS_TMO) "]");
+ module_param_named(log_level, log_level, uint, 0);
+ MODULE_PARM_DESC(log_level, "Set to 0 - 4 for increasing verbosity of device driver. "
+ 		 "[Default=" __stringify(IBMVFC_DEFAULT_LOG_LEVEL) "]");
+@@ -1030,11 +1024,6 @@ static void ibmvfc_get_host_port_state(struct Scsi_Host *shost)
+ 	spin_unlock_irqrestore(shost->host_lock, flags);
+ }
+ 
+-static void ibmvfc_set_host_def_dev_loss_tmo(struct Scsi_Host *shost)
+-{
+-	fc_host_def_dev_loss_tmo(shost) = dev_loss_tmo;
+-}
+-
+ /**
+  * ibmvfc_set_rport_dev_loss_tmo - Set rport's device loss timeout
+  * @rport:		rport struct
+@@ -4772,6 +4761,8 @@ static int ibmvfc_probe(struct vio_dev *vdev, const struct vio_device_id *id)
+ 	if ((rc = scsi_add_host(shost, dev)))
+ 		goto release_event_pool;
+ 
++	fc_host_dev_loss_tmo(shost) = IBMVFC_DEV_LOSS_TMO;
++
+ 	if ((rc = ibmvfc_create_trace_file(&shost->shost_dev.kobj,
+ 					   &ibmvfc_trace_attr))) {
+ 		dev_err(dev, "Failed to create trace file. rc=%d\n", rc);
+@@ -4917,8 +4908,6 @@ static struct fc_function_template ibmvfc_transport_functions = {
+ 	.get_host_speed = ibmvfc_get_host_speed,
+ 	.show_host_speed = 1,
+ 
+-	.get_host_def_dev_loss_tmo = ibmvfc_set_host_def_dev_loss_tmo,
+-
+ 	.issue_fc_host_lip = ibmvfc_issue_fc_host_lip,
+ 	.terminate_rport_io = ibmvfc_terminate_rport_io,
+ 

commit 485868208ee833628d49f81b4609001749d92d56
+Author: Mike Christie 
+Date:   Wed Sep 15 16:52:28 2010 -0500
+
+    [SCSI] fnic: prep for fc host dev loss tmo support
+    
+    This removes the driver's get_host_def_dev_loss_tmo
+    callback and just has the driver set the dev loss
+    using the fc class fc_host_dev_loss_tmo macro like is
+    done for other fc params.
+    
+    This also adds a set rport dev loss function so the
+    fc class host dev loss tmp sysfs support being added
+    in the fc class patch can update rports.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
+index df91a61591b2..bb63f1a1f808 100644
+--- a/drivers/scsi/fnic/fnic_main.c
++++ b/drivers/scsi/fnic/fnic_main.c
+@@ -110,12 +110,12 @@ static struct scsi_host_template fnic_host_template = {
+ };
+ 
+ static void
+-fnic_get_host_def_loss_tmo(struct Scsi_Host *shost)
++fnic_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout)
+ {
+-	struct fc_lport *lp = shost_priv(shost);
+-	struct fnic *fnic = lport_priv(lp);
+-
+-	fc_host_def_dev_loss_tmo(shost) = fnic->config.port_down_timeout / 1000;
++	if (timeout)
++		rport->dev_loss_tmo = timeout;
++	else
++		rport->dev_loss_tmo = 1;
+ }
+ 
+ static void fnic_get_host_speed(struct Scsi_Host *shost);
+@@ -145,9 +145,9 @@ static struct fc_function_template fnic_fc_functions = {
+ 	.show_starget_port_name = 1,
+ 	.show_starget_port_id = 1,
+ 	.show_rport_dev_loss_tmo = 1,
++	.set_rport_dev_loss_tmo = fnic_set_rport_dev_loss_tmo,
+ 	.issue_fc_host_lip = fnic_reset,
+ 	.get_fc_host_stats = fnic_get_stats,
+-	.get_host_def_dev_loss_tmo = fnic_get_host_def_loss_tmo,
+ 	.dd_fcrport_size = sizeof(struct fc_rport_libfc_priv),
+ 	.terminate_rport_io = fnic_terminate_rport_io,
+ 	.bsg_request = fc_lport_bsg_request,
+@@ -712,6 +712,7 @@ static int __devinit fnic_probe(struct pci_dev *pdev,
+ 		goto err_out_free_exch_mgr;
+ 	}
+ 	fc_host_maxframe_size(lp->host) = lp->mfs;
++	fc_host_dev_loss_tmo(lp->host) = fnic->config.port_down_timeout / 1000;
+ 
+ 	sprintf(fc_host_symbolic_name(lp->host),
+ 		DRV_NAME " v" DRV_VERSION " over %s", fnic->name);

commit da99e307aa508fba6fbedc3699e7df64e284d2c5
+Author: Mike Christie 
+Date:   Fri Aug 6 03:02:41 2010 -0500
+
+    [SCSI] ibmvfc: do not reset dev_loss_tmo in slave callout
+    
+    This fixes a bug where the driver was resetting the
+    rport dev_loss_tmo when devices were added by adding
+    support for the get_host_def_dev_loss_tmo callout.
+    
+    Patch has only been compile tested.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
+index 9f75a6d519a2..a5dd9b4a0ae8 100644
+--- a/drivers/scsi/ibmvscsi/ibmvfc.c
++++ b/drivers/scsi/ibmvscsi/ibmvfc.c
+@@ -1030,6 +1030,11 @@ static void ibmvfc_get_host_port_state(struct Scsi_Host *shost)
+ 	spin_unlock_irqrestore(shost->host_lock, flags);
+ }
+ 
++static void ibmvfc_set_host_def_dev_loss_tmo(struct Scsi_Host *shost)
++{
++	fc_host_def_dev_loss_tmo(shost) = dev_loss_tmo;
++}
++
+ /**
+  * ibmvfc_set_rport_dev_loss_tmo - Set rport's device loss timeout
+  * @rport:		rport struct
+@@ -2788,7 +2793,6 @@ static int ibmvfc_target_alloc(struct scsi_target *starget)
+ static int ibmvfc_slave_configure(struct scsi_device *sdev)
+ {
+ 	struct Scsi_Host *shost = sdev->host;
+-	struct fc_rport *rport = starget_to_rport(sdev->sdev_target);
+ 	unsigned long flags = 0;
+ 
+ 	spin_lock_irqsave(shost->host_lock, flags);
+@@ -2800,8 +2804,6 @@ static int ibmvfc_slave_configure(struct scsi_device *sdev)
+ 		scsi_activate_tcq(sdev, sdev->queue_depth);
+ 	} else
+ 		scsi_deactivate_tcq(sdev, sdev->queue_depth);
+-
+-	rport->dev_loss_tmo = dev_loss_tmo;
+ 	spin_unlock_irqrestore(shost->host_lock, flags);
+ 	return 0;
+ }
+@@ -4889,6 +4891,8 @@ static struct fc_function_template ibmvfc_transport_functions = {
+ 	.get_host_speed = ibmvfc_get_host_speed,
+ 	.show_host_speed = 1,
+ 
++	.get_host_def_dev_loss_tmo = ibmvfc_set_host_def_dev_loss_tmo,
++
+ 	.issue_fc_host_lip = ibmvfc_issue_fc_host_lip,
+ 	.terminate_rport_io = ibmvfc_terminate_rport_io,
+ 

commit 8196a934eea3810be6243b307b336136d63bbc48
+Author: Mike Christie 
+Date:   Fri Aug 6 03:02:40 2010 -0500
+
+    [SCSI] fnic: do not reset dev_loss_tmo in slave callout
+    
+    This fixes a bug where the driver was resetting the
+    rport dev_loss_tmo when devices were added by adding
+    support for the get_host_def_dev_loss_tmo callout.
+    
+    Patch has only been compile tested.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
+index 9eb7a9ebccae..df91a61591b2 100644
+--- a/drivers/scsi/fnic/fnic_main.c
++++ b/drivers/scsi/fnic/fnic_main.c
+@@ -80,8 +80,6 @@ static struct libfc_function_template fnic_transport_template = {
+ static int fnic_slave_alloc(struct scsi_device *sdev)
+ {
+ 	struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
+-	struct fc_lport *lp = shost_priv(sdev->host);
+-	struct fnic *fnic = lport_priv(lp);
+ 
+ 	sdev->tagged_supported = 1;
+ 
+@@ -89,8 +87,6 @@ static int fnic_slave_alloc(struct scsi_device *sdev)
+ 		return -ENXIO;
+ 
+ 	scsi_activate_tcq(sdev, FNIC_DFLT_QUEUE_DEPTH);
+-	rport->dev_loss_tmo = fnic->config.port_down_timeout / 1000;
+-
+ 	return 0;
+ }
+ 
+@@ -113,6 +109,15 @@ static struct scsi_host_template fnic_host_template = {
+ 	.shost_attrs = fnic_attrs,
+ };
+ 
++static void
++fnic_get_host_def_loss_tmo(struct Scsi_Host *shost)
++{
++	struct fc_lport *lp = shost_priv(shost);
++	struct fnic *fnic = lport_priv(lp);
++
++	fc_host_def_dev_loss_tmo(shost) = fnic->config.port_down_timeout / 1000;
++}
++
+ static void fnic_get_host_speed(struct Scsi_Host *shost);
+ static struct scsi_transport_template *fnic_fc_transport;
+ static struct fc_host_statistics *fnic_get_stats(struct Scsi_Host *);
+@@ -142,6 +147,7 @@ static struct fc_function_template fnic_fc_functions = {
+ 	.show_rport_dev_loss_tmo = 1,
+ 	.issue_fc_host_lip = fnic_reset,
+ 	.get_fc_host_stats = fnic_get_stats,
++	.get_host_def_dev_loss_tmo = fnic_get_host_def_loss_tmo,
+ 	.dd_fcrport_size = sizeof(struct fc_rport_libfc_priv),
+ 	.terminate_rport_io = fnic_terminate_rport_io,
+ 	.bsg_request = fc_lport_bsg_request,

commit 143beaa811aa3cfc4ae8b4a2092f232ad78b33da
+Author: Mike Christie 
+Date:   Fri Aug 6 03:02:39 2010 -0500
+
+    [SCSI] lpfc: do not reset dev_loss_tmo in slave callout
+    
+    This fixes a bug where the driver was resetting the
+    rport dev_loss_tmo when devices were added by adding
+    support for the get_host_def_dev_loss_tmo callout.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
+index 23ce45708335..87c2b6b858f7 100644
+--- a/drivers/scsi/lpfc/lpfc_attr.c
++++ b/drivers/scsi/lpfc/lpfc_attr.c
+@@ -4370,6 +4370,14 @@ lpfc_get_starget_port_name(struct scsi_target *starget)
+ 		ndlp ? wwn_to_u64(ndlp->nlp_portname.u.wwn) : 0;
+ }
+ 
++static void
++lpfc_get_host_def_loss_tmo(struct Scsi_Host *shost)
++{
++        struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
++
++	fc_host_def_dev_loss_tmo(shost) = vport->cfg_devloss_tmo;
++}
++
+ /**
+  * lpfc_set_rport_loss_tmo - Set the rport dev loss tmo
+  * @rport: fc rport address.
+@@ -4478,6 +4486,7 @@ struct fc_function_template lpfc_transport_functions = {
+ 	.get_host_fabric_name = lpfc_get_host_fabric_name,
+ 	.show_host_fabric_name = 1,
+ 
++	.get_host_def_dev_loss_tmo = lpfc_get_host_def_loss_tmo,
+ 	/*
+ 	 * The LPFC driver treats linkdown handling as target loss events
+ 	 * so there are no sysfs handlers for link_down_tmo.
+@@ -4545,6 +4554,7 @@ struct fc_function_template lpfc_vport_transport_functions = {
+ 	.get_host_fabric_name = lpfc_get_host_fabric_name,
+ 	.show_host_fabric_name = 1,
+ 
++	.get_host_def_dev_loss_tmo = lpfc_get_host_def_loss_tmo,
+ 	/*
+ 	 * The LPFC driver treats linkdown handling as target loss events
+ 	 * so there are no sysfs handlers for link_down_tmo.
+diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
+index 2e51aa6b45b3..6e331c73170e 100644
+--- a/drivers/scsi/lpfc/lpfc_scsi.c
++++ b/drivers/scsi/lpfc/lpfc_scsi.c
+@@ -3656,7 +3656,6 @@ lpfc_slave_alloc(struct scsi_device *sdev)
+  *
+  * This routine configures following items
+  *   - Tag command queuing support for @sdev if supported.
+- *   - Dev loss time out value of fc_rport.
+  *   - Enable SLI polling for fcp ring if ENABLE_FCP_RING_POLLING flag is set.
+  *
+  * Return codes:
+@@ -3667,21 +3666,12 @@ lpfc_slave_configure(struct scsi_device *sdev)
+ {
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+-	struct fc_rport   *rport = starget_to_rport(sdev->sdev_target);
+ 
+ 	if (sdev->tagged_supported)
+ 		scsi_activate_tcq(sdev, vport->cfg_lun_queue_depth);
+ 	else
+ 		scsi_deactivate_tcq(sdev, vport->cfg_lun_queue_depth);
+ 
+-	/*
+-	 * Initialize the fc transport attributes for the target
+-	 * containing this scsi device.  Also note that the driver's
+-	 * target pointer is stored in the starget_data for the
+-	 * driver's sysfs entry point functions.
+-	 */
+-	rport->dev_loss_tmo = vport->cfg_devloss_tmo;
+-
+ 	if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
+ 		lpfc_sli_handle_fast_ring_event(phba,
+ 			&phba->sli.ring[LPFC_FCP_RING], HA_R0RE_REQ);

commit a74bdf4661441d79a700f7ab3fc6d225ea2cf409
+Author: Mike Christie 
+Date:   Fri Aug 6 03:02:38 2010 -0500
+
+    [SCSI] qla2xxx: do not reset dev_loss_tmo in slave callout
+    
+    This fixes a bug where the driver was resetting the
+    rport dev_loss_tmo when devices were added by adding
+    support for the get_host_def_dev_loss_tmo callout.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
+index 420238cc794e..679a4326811c 100644
+--- a/drivers/scsi/qla2xxx/qla_attr.c
++++ b/drivers/scsi/qla2xxx/qla_attr.c
+@@ -1529,6 +1529,15 @@ qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
+ 		rport->dev_loss_tmo = 1;
+ }
+ 
++static void
++qla2x00_get_host_def_loss_tmo(struct Scsi_Host *shost)
++{
++	scsi_qla_host_t *vha = shost_priv(shost);
++	struct qla_hw_data *ha = vha->hw;
++
++	fc_host_def_dev_loss_tmo(shost) = ha->port_down_retry_count;
++}
++
+ static void
+ qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport)
+ {
+@@ -1903,6 +1912,7 @@ struct fc_function_template qla2xxx_transport_functions = {
+ 	.show_host_fabric_name = 1,
+ 	.get_host_port_state = qla2x00_get_host_port_state,
+ 	.show_host_port_state = 1,
++	.get_host_def_dev_loss_tmo = qla2x00_get_host_def_loss_tmo,
+ 
+ 	.dd_fcrport_size = sizeof(struct fc_port *),
+ 	.show_rport_supported_classes = 1,
+@@ -1949,6 +1959,7 @@ struct fc_function_template qla2xxx_transport_vport_functions = {
+ 	.show_host_fabric_name = 1,
+ 	.get_host_port_state = qla2x00_get_host_port_state,
+ 	.show_host_port_state = 1,
++	.get_host_def_dev_loss_tmo = qla2x00_get_host_def_loss_tmo,
+ 
+ 	.dd_fcrport_size = sizeof(struct fc_port *),
+ 	.show_rport_supported_classes = 1,
+diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
+index 8c80b49ac1c4..30b05229af26 100644
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -1295,17 +1295,12 @@ static int
+ qla2xxx_slave_configure(struct scsi_device *sdev)
+ {
+ 	scsi_qla_host_t *vha = shost_priv(sdev->host);
+-	struct qla_hw_data *ha = vha->hw;
+-	struct fc_rport *rport = starget_to_rport(sdev->sdev_target);
+ 	struct req_que *req = vha->req;
+ 
+ 	if (sdev->tagged_supported)
+ 		scsi_activate_tcq(sdev, req->max_q_depth);
+ 	else
+ 		scsi_deactivate_tcq(sdev, req->max_q_depth);
+-
+-	rport->dev_loss_tmo = ha->port_down_retry_count;
+-
+ 	return 0;
+ }
+ 

commit b8ef3204f460912a46659cdc74d237adbe705053
+Author: Mike Christie 
+Date:   Fri Aug 6 03:02:37 2010 -0500
+
+    [SCSI] fc class: add fc host default default dev loss setting
+    
+    This patch adds a fc_host setting to store the
+    default dev_loss_tmo. It is used if the driver
+    has a callack to get the value from the LLD. If
+    the callback is not set, then we use the fc class
+    module default value.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
+index d7e470a06180..9f0f7d9c7422 100644
+--- a/drivers/scsi/scsi_transport_fc.c
++++ b/drivers/scsi/scsi_transport_fc.c
+@@ -2525,7 +2525,11 @@ fc_rport_create(struct Scsi_Host *shost, int channel,
+ 
+ 	rport->maxframe_size = -1;
+ 	rport->supported_classes = FC_COS_UNSPECIFIED;
+-	rport->dev_loss_tmo = fc_dev_loss_tmo;
++	if (fci->f->get_host_def_dev_loss_tmo) {
++		fci->f->get_host_def_dev_loss_tmo(shost);
++		rport->dev_loss_tmo = fc_host_def_dev_loss_tmo(shost);
++	} else
++		rport->dev_loss_tmo = fc_dev_loss_tmo;
+ 	memcpy(&rport->node_name, &ids->node_name, sizeof(rport->node_name));
+ 	memcpy(&rport->port_name, &ids->port_name, sizeof(rport->port_name));
+ 	rport->port_id = ids->port_id;
+diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
+index 87d81b3ce564..9f98fca9b763 100644
+--- a/include/scsi/scsi_transport_fc.h
++++ b/include/scsi/scsi_transport_fc.h
+@@ -496,6 +496,7 @@ struct fc_host_attrs {
+ 	u64 fabric_name;
+ 	char symbolic_name[FC_SYMBOLIC_NAME_SIZE];
+ 	char system_hostname[FC_SYMBOLIC_NAME_SIZE];
++	u32 def_dev_loss_tmo;
+ 
+ 	/* Private (Transport-managed) Attributes */
+ 	enum fc_tgtid_binding_type  tgtid_bind_type;
+@@ -580,6 +581,8 @@ struct fc_host_attrs {
+ 	(((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q_name)
+ #define fc_host_devloss_work_q(x) \
+ 	(((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q)
++#define fc_host_def_dev_loss_tmo(x) \
++	(((struct fc_host_attrs *)(x)->shost_data)->def_dev_loss_tmo)
+ 
+ 
+ struct fc_bsg_buffer {
+@@ -640,6 +643,7 @@ struct fc_function_template {
+ 	void	(*get_host_fabric_name)(struct Scsi_Host *);
+ 	void	(*get_host_symbolic_name)(struct Scsi_Host *);
+ 	void	(*set_host_system_hostname)(struct Scsi_Host *);
++	void	(*get_host_def_dev_loss_tmo)(struct Scsi_Host *);
+ 
+ 	struct fc_host_statistics * (*get_fc_host_stats)(struct Scsi_Host *);
+ 	void	(*reset_fc_host_stats)(struct Scsi_Host *);

commit be948fc30dabc347e4fba4daf4da9fd83d2abf49
+Author: Mike Christie 
+Date:   Mon Aug 2 16:02:24 2010 -0500
+
+    [SCSI] libfc: call fc_remote_port_chkready under the host lock.
+    
+    The rport port state and flags are set under the host lock,
+    so this patch calls fc_remote_port_chkready with the host lock
+    held like is also done in the other fc drivers.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
+index eac4d09314eb..c797f6b48f05 100644
+--- a/drivers/scsi/libfc/fc_fcp.c
++++ b/drivers/scsi/libfc/fc_fcp.c
+@@ -1765,14 +1765,14 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))
+ 	struct fcoe_dev_stats *stats;
+ 
+ 	lport = shost_priv(sc_cmd->device->host);
+-	spin_unlock_irq(lport->host->host_lock);
+ 
+ 	rval = fc_remote_port_chkready(rport);
+ 	if (rval) {
+ 		sc_cmd->result = rval;
+ 		done(sc_cmd);
+-		goto out;
++		return 0;
+ 	}
++	spin_unlock_irq(lport->host->host_lock);
+ 
+ 	if (!*(struct fc_remote_port **)rport->dd_data) {
+ 		/*

commit aab7a8fd19d0c2f7fcac4d07616899655e326dfe
+Author: Mike Christie 
+Date:   Mon Aug 2 12:46:12 2010 -0500
+
+    [SCSI] iscsi boot: mv iscsi_boot_sysfs to drivers/scsi
+    
+    iscsi_boot_sysfs does not depend on firmware. Any iscsi driver
+    can use it. This patch moves iscsi_boot_sysfs to the scsi
+    dir, so that it can be used on any arch with any driver.
+    
+    Signed-off-by: Mike Christie 
+    Acked-by: Konrad Rzeszutek Wilk 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
+index a6c670b8ce52..f7cff381a4b8 100644
+--- a/drivers/firmware/Kconfig
++++ b/drivers/firmware/Kconfig
+@@ -122,14 +122,6 @@ config ISCSI_IBFT_FIND
+ 	  is necessary for iSCSI Boot Firmware Table Attributes module to work
+ 	  properly.
+ 
+-config ISCSI_BOOT_SYSFS
+-	tristate "iSCSI Boot Sysfs Interface"
+-	default	n
+-	help
+-	  This option enables support for exposing iSCSI boot information
+-	  via sysfs to userspace. If you wish to export this information,
+-	  say Y. Otherwise, say N.
+-
+ config ISCSI_IBFT
+ 	tristate "iSCSI Boot Firmware Table Attributes module"
+ 	select ISCSI_BOOT_SYSFS
+diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
+index 5fe7e1662922..1c3c17343dbe 100644
+--- a/drivers/firmware/Makefile
++++ b/drivers/firmware/Makefile
+@@ -10,5 +10,4 @@ obj-$(CONFIG_DCDBAS)		+= dcdbas.o
+ obj-$(CONFIG_DMIID)		+= dmi-id.o
+ obj-$(CONFIG_ISCSI_IBFT_FIND)	+= iscsi_ibft_find.o
+ obj-$(CONFIG_ISCSI_IBFT)	+= iscsi_ibft.o
+-obj-$(CONFIG_ISCSI_BOOT_SYSFS)	+= iscsi_boot_sysfs.o
+ obj-$(CONFIG_FIRMWARE_MEMMAP)	+= memmap.o
+diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
+index 158284f05732..a479b3b7ea90 100644
+--- a/drivers/scsi/Kconfig
++++ b/drivers/scsi/Kconfig
+@@ -370,6 +370,14 @@ config ISCSI_TCP
+ 
+ 	 http://open-iscsi.org
+ 
++config ISCSI_BOOT_SYSFS
++	tristate "iSCSI Boot Sysfs Interface"
++	default	n
++	help
++	  This option enables support for exposing iSCSI boot information
++	  via sysfs to userspace. If you wish to export this information,
++	  say Y. Otherwise, say N.
++
+ source "drivers/scsi/cxgb3i/Kconfig"
+ source "drivers/scsi/bnx2i/Kconfig"
+ source "drivers/scsi/be2iscsi/Kconfig"
+diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
+index 2a3fca2eca6a..2703c6ec5e36 100644
+--- a/drivers/scsi/Makefile
++++ b/drivers/scsi/Makefile
+@@ -42,6 +42,7 @@ obj-$(CONFIG_FCOE)		+= fcoe/
+ obj-$(CONFIG_FCOE_FNIC)		+= fnic/
+ obj-$(CONFIG_ISCSI_TCP) 	+= libiscsi.o	libiscsi_tcp.o iscsi_tcp.o
+ obj-$(CONFIG_INFINIBAND_ISER) 	+= libiscsi.o
++obj-$(CONFIG_ISCSI_BOOT_SYSFS)	+= iscsi_boot_sysfs.o
+ obj-$(CONFIG_SCSI_A4000T)	+= 53c700.o	a4000t.o
+ obj-$(CONFIG_SCSI_ZORRO7XX)	+= 53c700.o	zorro7xx.o
+ obj-$(CONFIG_A3000_SCSI)	+= a3000.o	wd33c93.o
+diff --git a/drivers/firmware/iscsi_boot_sysfs.c b/drivers/scsi/iscsi_boot_sysfs.c
+similarity index 100%
+rename from drivers/firmware/iscsi_boot_sysfs.c
+rename to drivers/scsi/iscsi_boot_sysfs.c

commit c01be6dcb2b5cce4feaf48035be6395e5cd7d47c
+Author: Mike Christie 
+Date:   Thu Jul 22 16:59:49 2010 +0530
+
+    [SCSI] iscsi_transport: wait on session in error handler path
+    
+    wait for session to come online in eh_device_reset_handler
+    and eh_target_reset_handler
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Vikas Chaudhary 
+    Signed-off-by: Ravi Anand 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index 821384147a41..5529b2a39741 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -2020,6 +2020,11 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd)
+ 	if (!ddb_entry)
+ 		return ret;
+ 
++	ret = iscsi_block_scsi_eh(cmd);
++	if (ret)
++		return ret;
++	ret = FAILED;
++
+ 	ql4_printk(KERN_INFO, ha,
+ 		   "scsi%ld:%d:%d:%d: DEVICE RESET ISSUED.\n", ha->host_no,
+ 		   cmd->device->channel, cmd->device->id, cmd->device->lun);
+@@ -2072,11 +2077,15 @@ static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd)
+ {
+ 	struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
+ 	struct ddb_entry *ddb_entry = cmd->device->hostdata;
+-	int stat;
++	int stat, ret;
+ 
+ 	if (!ddb_entry)
+ 		return FAILED;
+ 
++	ret = iscsi_block_scsi_eh(cmd);
++	if (ret)
++		return ret;
++
+ 	starget_printk(KERN_INFO, scsi_target(cmd->device),
+ 		       "WARM TARGET RESET ISSUED.\n");
+ 
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index d4b96623aa59..e84026def1f4 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -30,6 +30,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #define ISCSI_SESSION_ATTRS 23
+ #define ISCSI_CONN_ATTRS 13
+@@ -534,6 +535,37 @@ static void iscsi_scan_session(struct work_struct *work)
+ 	atomic_dec(&ihost->nr_scans);
+ }
+ 
++/**
++ * iscsi_block_scsi_eh - block scsi eh until session state has transistioned
++ * cmd: scsi cmd passed to scsi eh handler
++ *
++ * If the session is down this function will wait for the recovery
++ * timer to fire or for the session to be logged back in. If the
++ * recovery timer fires then FAST_IO_FAIL is returned. The caller
++ * should pass this error value to the scsi eh.
++ */
++int iscsi_block_scsi_eh(struct scsi_cmnd *cmd)
++{
++	struct iscsi_cls_session *session =
++			starget_to_session(scsi_target(cmd->device));
++	unsigned long flags;
++	int ret = 0;
++
++	spin_lock_irqsave(&session->lock, flags);
++	while (session->state != ISCSI_SESSION_LOGGED_IN) {
++		if (session->state == ISCSI_SESSION_FREE) {
++			ret = FAST_IO_FAIL;
++			break;
++		}
++		spin_unlock_irqrestore(&session->lock, flags);
++		msleep(1000);
++		spin_lock_irqsave(&session->lock, flags);
++	}
++	spin_unlock_irqrestore(&session->lock, flags);
++	return ret;
++}
++EXPORT_SYMBOL_GPL(iscsi_block_scsi_eh);
++
+ static void session_recovery_timedout(struct work_struct *work)
+ {
+ 	struct iscsi_cls_session *session =
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 349c7f30720d..7fff94b3b2a8 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -32,6 +32,7 @@ struct scsi_transport_template;
+ struct iscsi_transport;
+ struct iscsi_endpoint;
+ struct Scsi_Host;
++struct scsi_cmnd;
+ struct iscsi_cls_conn;
+ struct iscsi_conn;
+ struct iscsi_task;
+@@ -255,5 +256,6 @@ extern int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time);
+ extern struct iscsi_endpoint *iscsi_create_endpoint(int dd_size);
+ extern void iscsi_destroy_endpoint(struct iscsi_endpoint *ep);
+ extern struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle);
++extern int iscsi_block_scsi_eh(struct scsi_cmnd *cmd);
+ 
+ #endif

commit 6e49949c5e9e04d64e16df3723dd3f5bd25a29e2
+Author: Mike Christie 
+Date:   Sun Apr 25 07:03:57 2010 -0500
+
+    [SCSI] Log msg when getting Unit Attention
+    
+    If the user accidentally changes LUN mappings or it occurs
+    due to a bug, then it can cause data corruption that can take
+    months and months to track down. This patch adds a log
+    message when getting REPORT_LUNS_DATA_CHANGED and it adds
+    a generic message for other Unit Attentions with asc == 0x3f.
+    
+    We are working on adding support for handling of these errors,
+    but I think until then we should at least log a message so
+    tracking down problems as a result of one of these changes
+    is a little easier.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
+index a5d630f5f519..c60cffbefa3c 100644
+--- a/drivers/scsi/scsi_error.c
++++ b/drivers/scsi/scsi_error.c
+@@ -307,6 +307,19 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
+ 		    (sshdr.asc == 0x04) && (sshdr.ascq == 0x02))
+ 			return FAILED;
+ 
++		if (sshdr.asc == 0x3f && sshdr.ascq == 0x0e)
++			scmd_printk(KERN_WARNING, scmd,
++				    "Warning! Received an indication that the "
++				    "LUN assignments on this target have "
++				    "changed. The Linux SCSI layer does not "
++				    "automatically remap LUN assignments.\n");
++		else if (sshdr.asc == 0x3f)
++			scmd_printk(KERN_WARNING, scmd,
++				    "Warning! Received an indication that the "
++				    "operating parameters on this target have "
++				    "changed. The Linux SCSI layer does not "
++				    "automatically adjust these parameters.\n");
++
+ 		if (blk_barrier_rq(scmd->request))
+ 			/*
+ 			 * barrier requests should always retry on UA

commit fa95d206e4a4fb549bdb9fe71091417f4912178f
+Author: Mike Christie 
+Date:   Wed Jun 9 03:30:08 2010 -0500
+
+    [SCSI] be2iscsi: fix disconnection cleanup
+    
+    This patch fixes 4 bugs in the connection connect/disconnect
+    cleanup path.
+    
+    1. If beiscsi_open_conn fails beiscsi_free_ep was always being
+    called, and if beiscsi_open_conn failed because beiscsi_get_cid
+    failed then we would free an unallocated cid.
+    
+    2. If beiscsi_ep_connect failed due to a beiscsi_open_conn failure
+    it was leaking iscsi_endpoints.
+    
+    3. beiscsi_ep_disconnect was leaking iscsi_endpoints.
+    beiscsi_ep_disconnect should free the iscsi_endpoint. We cannot
+    do it in beiscsi_conn_stop because that is only called for
+    iscsi connection cleanup. If beiscsi_ep_connect returns
+    success, but then the poll function fails or the connect
+    times out then beiscsi_ep_disconnect will be called to clean
+    up the ep. The conn_stop callout will not be called in that path.
+    
+    4. beiscsi_conn_stop was freeing the iscsi_endpoint then accessing
+    it a couple lines later.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
+index c3928cb8b042..454027ccbf16 100644
+--- a/drivers/scsi/be2iscsi/be_iscsi.c
++++ b/drivers/scsi/be2iscsi/be_iscsi.c
+@@ -441,6 +441,31 @@ static int beiscsi_get_cid(struct beiscsi_hba *phba)
+ 	return cid;
+ }
+ 
++/**
++ * beiscsi_put_cid - Free the cid
++ * @phba: The phba for which the cid is being freed
++ * @cid: The cid to free
++ */
++static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid)
++{
++	phba->avlbl_cids++;
++	phba->cid_array[phba->cid_free++] = cid;
++	if (phba->cid_free == phba->params.cxns_per_ctrl)
++		phba->cid_free = 0;
++}
++
++/**
++ * beiscsi_free_ep - free endpoint
++ * @ep:	pointer to iscsi endpoint structure
++ */
++static void beiscsi_free_ep(struct beiscsi_endpoint *beiscsi_ep)
++{
++	struct beiscsi_hba *phba = beiscsi_ep->phba;
++
++	beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
++	beiscsi_ep->phba = NULL;
++}
++
+ /**
+  * beiscsi_open_conn - Ask FW to open a TCP connection
+  * @ep:	endpoint to be used
+@@ -475,7 +500,7 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
+ 	if (beiscsi_ep->ep_cid > (phba->fw_config.iscsi_cid_start +
+ 				  phba->params.cxns_per_ctrl * 2)) {
+ 		SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n");
+-		return ret;
++		goto free_ep;
+ 	}
+ 
+ 	beiscsi_ep->cid_vld = 0;
+@@ -493,10 +518,10 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
+ 	status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
+ 	if (status || extd_status) {
+ 		SE_DEBUG(DBG_LVL_1, "mgmt_open_connection Failed"
+-				    " status = %d extd_status = %d \n",
++				    " status = %d extd_status = %d\n",
+ 				    status, extd_status);
+ 		free_mcc_tag(&phba->ctrl, tag);
+-		return -1;
++		goto free_ep;
+ 	} else {
+ 		wrb = queue_get_wrb(mccq, wrb_num);
+ 		free_mcc_tag(&phba->ctrl, tag);
+@@ -508,31 +533,10 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
+ 		SE_DEBUG(DBG_LVL_8, "mgmt_open_connection Success\n");
+ 	}
+ 	return 0;
+-}
+-
+-/**
+- * beiscsi_put_cid - Free the cid
+- * @phba: The phba for which the cid is being freed
+- * @cid: The cid to free
+- */
+-static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid)
+-{
+-	phba->avlbl_cids++;
+-	phba->cid_array[phba->cid_free++] = cid;
+-	if (phba->cid_free == phba->params.cxns_per_ctrl)
+-		phba->cid_free = 0;
+-}
+-
+-/**
+- * beiscsi_free_ep - free endpoint
+- * @ep:	pointer to iscsi endpoint structure
+- */
+-static void beiscsi_free_ep(struct beiscsi_endpoint *beiscsi_ep)
+-{
+-	struct beiscsi_hba *phba = beiscsi_ep->phba;
+ 
+-	beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
+-	beiscsi_ep->phba = NULL;
++free_ep:
++	beiscsi_free_ep(beiscsi_ep);
++	return -1;
+ }
+ 
+ /**
+@@ -585,7 +589,7 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
+ 	return ep;
+ 
+ free_ep:
+-	beiscsi_free_ep(beiscsi_ep);
++	iscsi_destroy_endpoint(ep);
+ 	return ERR_PTR(ret);
+ }
+ 
+@@ -631,30 +635,6 @@ static int beiscsi_close_conn(struct  beiscsi_endpoint *beiscsi_ep, int flag)
+ 	return ret;
+ }
+ 
+-/**
+- * beiscsi_ep_disconnect - Tears down the TCP connection
+- * @ep:	endpoint to be used
+- *
+- * Tears down the TCP connection
+- */
+-void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
+-{
+-	struct beiscsi_conn *beiscsi_conn;
+-	struct beiscsi_endpoint *beiscsi_ep;
+-	struct beiscsi_hba *phba;
+-
+-	beiscsi_ep = ep->dd_data;
+-	phba = beiscsi_ep->phba;
+-	SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_disconnect for ep_cid = %d\n",
+-			     beiscsi_ep->ep_cid);
+-
+-	if (beiscsi_ep->conn) {
+-		beiscsi_conn = beiscsi_ep->conn;
+-		iscsi_suspend_queue(beiscsi_conn->conn);
+-	}
+-
+-}
+-
+ /**
+  * beiscsi_unbind_conn_to_cid - Unbind the beiscsi_conn from phba conn table
+  * @phba: The phba instance
+@@ -673,28 +653,35 @@ static int beiscsi_unbind_conn_to_cid(struct beiscsi_hba *phba,
+ }
+ 
+ /**
+- * beiscsi_conn_stop - Invalidate and stop the connection
+- * @cls_conn: pointer to get iscsi_conn
+- * @flag: The type of connection closure
++ * beiscsi_ep_disconnect - Tears down the TCP connection
++ * @ep:	endpoint to be used
++ *
++ * Tears down the TCP connection
+  */
+-void beiscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
++void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
+ {
+-	struct iscsi_conn *conn = cls_conn->dd_data;
+-	struct beiscsi_conn *beiscsi_conn = conn->dd_data;
++	struct beiscsi_conn *beiscsi_conn;
+ 	struct beiscsi_endpoint *beiscsi_ep;
+-	struct iscsi_session *session = conn->session;
+-	struct Scsi_Host *shost = iscsi_session_to_shost(session->cls_session);
+-	struct beiscsi_hba *phba = iscsi_host_priv(shost);
++	struct beiscsi_hba *phba;
+ 	unsigned int tag;
+ 	unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH;
+ 
+-	beiscsi_ep = beiscsi_conn->ep;
+-	if (!beiscsi_ep) {
+-		SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop , no beiscsi_ep\n");
++	beiscsi_ep = ep->dd_data;
++	phba = beiscsi_ep->phba;
++	SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_disconnect for ep_cid = %d\n",
++			     beiscsi_ep->ep_cid);
++
++	if (!beiscsi_ep->conn) {
++		SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_disconnect, no "
++			 "beiscsi_ep\n");
+ 		return;
+ 	}
+-	SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop  ep_cid = %d\n",
+-			     beiscsi_ep->ep_cid);
++	beiscsi_conn = beiscsi_ep->conn;
++	iscsi_suspend_queue(beiscsi_conn->conn);
++
++	SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_disconnect ep_cid = %d\n",
++		 beiscsi_ep->ep_cid);
++
+ 	tag = mgmt_invalidate_connection(phba, beiscsi_ep,
+ 					    beiscsi_ep->ep_cid, 1,
+ 					    savecfg_flag);
+@@ -707,9 +694,9 @@ void beiscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+ 					 phba->ctrl.mcc_numtag[tag]);
+ 		free_mcc_tag(&phba->ctrl, tag);
+ 	}
++
+ 	beiscsi_close_conn(beiscsi_ep, CONNECTION_UPLOAD_GRACEFUL);
+ 	beiscsi_free_ep(beiscsi_ep);
+-	iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep);
+ 	beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid);
+-	iscsi_conn_stop(cls_conn, flag);
++	iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep);
+ }
+diff --git a/drivers/scsi/be2iscsi/be_iscsi.h b/drivers/scsi/be2iscsi/be_iscsi.h
+index 1f512c28cbf9..870cdb2a73e4 100644
+--- a/drivers/scsi/be2iscsi/be_iscsi.h
++++ b/drivers/scsi/be2iscsi/be_iscsi.h
+@@ -59,8 +59,6 @@ int beiscsi_set_param(struct iscsi_cls_conn *cls_conn,
+ 
+ int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn);
+ 
+-void beiscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag);
+-
+ struct iscsi_endpoint *beiscsi_ep_connect(struct Scsi_Host *shost,
+ 					  struct sockaddr *dst_addr,
+ 					  int non_blocking);
+diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
+index dd5b105f8f47..854414551bb0 100644
+--- a/drivers/scsi/be2iscsi/be_main.c
++++ b/drivers/scsi/be2iscsi/be_main.c
+@@ -3955,7 +3955,7 @@ struct iscsi_transport beiscsi_iscsi_transport = {
+ 	.get_session_param = iscsi_session_get_param,
+ 	.get_host_param = beiscsi_get_host_param,
+ 	.start_conn = beiscsi_conn_start,
+-	.stop_conn = beiscsi_conn_stop,
++	.stop_conn = iscsi_conn_stop,
+ 	.send_pdu = iscsi_conn_send_pdu,
+ 	.xmit_task = beiscsi_task_xmit,
+ 	.cleanup_task = beiscsi_cleanup_task,

commit 8c38a2951026e6b428d3ce6e518d123c35becd18
+Author: Mike Christie 
+Date:   Fri May 21 18:24:16 2010 -0500
+
+    [SCSI] iscsi_tcp: remove sk_sleep check
+    
+    There is no need to call sk_sleep before calling wake_up_interruptible,
+    because the wait_queue_head is now with the socket.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index bf55d3057413..fec47de72535 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -601,10 +601,8 @@ static void iscsi_sw_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+ 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
+ 	write_unlock_bh(&tcp_sw_conn->sock->sk->sk_callback_lock);
+ 
+-	if (sk_sleep(sock->sk)) {
+-		sock->sk->sk_err = EIO;
+-		wake_up_interruptible(sk_sleep(sock->sk));
+-	}
++	sock->sk->sk_err = EIO;
++	wake_up_interruptible(sk_sleep(sock->sk));
+ 
+ 	iscsi_conn_stop(cls_conn, flag);
+ 	iscsi_sw_tcp_release_conn(conn);

commit b33a84a384776fb2593dac4d77c72050f9e181b0
+Author: Mike Christie 
+Date:   Mon Apr 12 18:06:18 2010 +0000
+
+    ibft: convert iscsi_ibft module to iscsi boot lib
+    
+    This patch just converts the iscsi_ibft module to the
+    iscsi boot sysfs lib module.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Konrad Rzeszutek Wilk 
+    Signed-off-by: Peter Jones 
+
+diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
+index 571d2182613d..a6c670b8ce52 100644
+--- a/drivers/firmware/Kconfig
++++ b/drivers/firmware/Kconfig
+@@ -132,6 +132,7 @@ config ISCSI_BOOT_SYSFS
+ 
+ config ISCSI_IBFT
+ 	tristate "iSCSI Boot Firmware Table Attributes module"
++	select ISCSI_BOOT_SYSFS
+ 	depends on ISCSI_IBFT_FIND
+ 	default	n
+ 	help
+diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c
+index b3ab24f9d78f..4f04ec0410a0 100644
+--- a/drivers/firmware/iscsi_ibft.c
++++ b/drivers/firmware/iscsi_ibft.c
+@@ -82,6 +82,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #define IBFT_ISCSI_VERSION "0.5.0"
+ #define IBFT_ISCSI_DATE "2010-Feb-25"
+@@ -169,74 +170,6 @@ enum ibft_id {
+ 	id_end_marker,
+ };
+ 
+-/*
+- * We do not support the other types, hence the usage of NULL.
+- * This maps to the enum ibft_id.
+- */
+-static const char *ibft_id_names[] =
+-	{NULL, NULL, "initiator", "ethernet%d", "target%d", NULL, NULL};
+-
+-/*
+- * The text attributes names for each of the kobjects.
+-*/
+-enum ibft_eth_properties_enum {
+-	ibft_eth_index,
+-	ibft_eth_flags,
+-	ibft_eth_ip_addr,
+-	ibft_eth_subnet_mask,
+-	ibft_eth_origin,
+-	ibft_eth_gateway,
+-	ibft_eth_primary_dns,
+-	ibft_eth_secondary_dns,
+-	ibft_eth_dhcp,
+-	ibft_eth_vlan,
+-	ibft_eth_mac,
+-	/* ibft_eth_pci_bdf - this is replaced by link to the device itself. */
+-	ibft_eth_hostname,
+-	ibft_eth_end_marker,
+-};
+-
+-static const char *ibft_eth_properties[] =
+-	{"index", "flags", "ip-addr", "subnet-mask", "origin", "gateway",
+-	"primary-dns", "secondary-dns", "dhcp", "vlan", "mac", "hostname",
+-	NULL};
+-
+-enum ibft_tgt_properties_enum {
+-	ibft_tgt_index,
+-	ibft_tgt_flags,
+-	ibft_tgt_ip_addr,
+-	ibft_tgt_port,
+-	ibft_tgt_lun,
+-	ibft_tgt_chap_type,
+-	ibft_tgt_nic_assoc,
+-	ibft_tgt_name,
+-	ibft_tgt_chap_name,
+-	ibft_tgt_chap_secret,
+-	ibft_tgt_rev_chap_name,
+-	ibft_tgt_rev_chap_secret,
+-	ibft_tgt_end_marker,
+-};
+-
+-static const char *ibft_tgt_properties[] =
+-	{"index", "flags", "ip-addr", "port", "lun", "chap-type", "nic-assoc",
+-	"target-name", "chap-name", "chap-secret", "rev-chap-name",
+-	"rev-chap-name-secret", NULL};
+-
+-enum ibft_initiator_properties_enum {
+-	ibft_init_index,
+-	ibft_init_flags,
+-	ibft_init_isns_server,
+-	ibft_init_slp_server,
+-	ibft_init_pri_radius_server,
+-	ibft_init_sec_radius_server,
+-	ibft_init_initiator_name,
+-	ibft_init_end_marker,
+-};
+-
+-static const char *ibft_initiator_properties[] =
+-	{"index", "flags", "isns-server", "slp-server", "pri-radius-server",
+-	"sec-radius-server", "initiator-name", NULL};
+-
+ /*
+  * The kobject and attribute structures.
+  */
+@@ -249,29 +182,9 @@ struct ibft_kobject {
+ 		struct ibft_tgt *tgt;
+ 		struct ibft_hdr *hdr;
+ 	};
+-	struct kobject kobj;
+-	struct list_head node;
+ };
+ 
+-struct ibft_attribute {
+-	struct attribute attr;
+-	ssize_t (*show) (struct  ibft_kobject *entry,
+-			 struct ibft_attribute *attr, char *buf);
+-	union {
+-		struct ibft_initiator *initiator;
+-		struct ibft_nic *nic;
+-		struct ibft_tgt *tgt;
+-		struct ibft_hdr *hdr;
+-	};
+-	struct kobject *kobj;
+-	int type; /* The enum of the type. This can be any value of:
+-		ibft_eth_properties_enum, ibft_tgt_properties_enum,
+-		or ibft_initiator_properties_enum. */
+-	struct list_head node;
+-};
+-
+-static LIST_HEAD(ibft_attr_list);
+-static LIST_HEAD(ibft_kobject_list);
++static struct iscsi_boot_kset *boot_kset;
+ 
+ static const char nulls[16];
+ 
+@@ -310,35 +223,27 @@ static ssize_t sprintf_string(char *str, int len, char *buf)
+ static int ibft_verify_hdr(char *t, struct ibft_hdr *hdr, int id, int length)
+ {
+ 	if (hdr->id != id) {
+-		printk(KERN_ERR "iBFT error: We expected the " \
++		printk(KERN_ERR "iBFT error: We expected the %s " \
+ 				"field header.id to have %d but " \
+-				"found %d instead!\n", id, hdr->id);
++				"found %d instead!\n", t, id, hdr->id);
+ 		return -ENODEV;
+ 	}
+ 	if (hdr->length != length) {
+-		printk(KERN_ERR "iBFT error: We expected the " \
++		printk(KERN_ERR "iBFT error: We expected the %s " \
+ 				"field header.length to have %d but " \
+-				"found %d instead!\n", length, hdr->length);
++				"found %d instead!\n", t, length, hdr->length);
+ 		return -ENODEV;
+ 	}
+ 
+ 	return 0;
+ }
+ 
+-static void ibft_release(struct kobject *kobj)
+-{
+-	struct ibft_kobject *ibft =
+-		container_of(kobj, struct ibft_kobject, kobj);
+-	kfree(ibft);
+-}
+-
+ /*
+  *  Routines for parsing the iBFT data to be human readable.
+  */
+-static ssize_t ibft_attr_show_initiator(struct ibft_kobject *entry,
+-					struct ibft_attribute *attr,
+-					char *buf)
++static ssize_t ibft_attr_show_initiator(void *data, int type, char *buf)
+ {
++	struct ibft_kobject *entry = data;
+ 	struct ibft_initiator *initiator = entry->initiator;
+ 	void *ibft_loc = entry->header;
+ 	char *str = buf;
+@@ -346,26 +251,26 @@ static ssize_t ibft_attr_show_initiator(struct ibft_kobject *entry,
+ 	if (!initiator)
+ 		return 0;
+ 
+-	switch (attr->type) {
+-	case ibft_init_index:
++	switch (type) {
++	case ISCSI_BOOT_INI_INDEX:
+ 		str += sprintf(str, "%d\n", initiator->hdr.index);
+ 		break;
+-	case ibft_init_flags:
++	case ISCSI_BOOT_INI_FLAGS:
+ 		str += sprintf(str, "%d\n", initiator->hdr.flags);
+ 		break;
+-	case ibft_init_isns_server:
++	case ISCSI_BOOT_INI_ISNS_SERVER:
+ 		str += sprintf_ipaddr(str, initiator->isns_server);
+ 		break;
+-	case ibft_init_slp_server:
++	case ISCSI_BOOT_INI_SLP_SERVER:
+ 		str += sprintf_ipaddr(str, initiator->slp_server);
+ 		break;
+-	case ibft_init_pri_radius_server:
++	case ISCSI_BOOT_INI_PRI_RADIUS_SERVER:
+ 		str += sprintf_ipaddr(str, initiator->pri_radius_server);
+ 		break;
+-	case ibft_init_sec_radius_server:
++	case ISCSI_BOOT_INI_SEC_RADIUS_SERVER:
+ 		str += sprintf_ipaddr(str, initiator->sec_radius_server);
+ 		break;
+-	case ibft_init_initiator_name:
++	case ISCSI_BOOT_INI_INITIATOR_NAME:
+ 		str += sprintf_string(str, initiator->initiator_name_len,
+ 				      (char *)ibft_loc +
+ 				      initiator->initiator_name_off);
+@@ -377,10 +282,9 @@ static ssize_t ibft_attr_show_initiator(struct ibft_kobject *entry,
+ 	return str - buf;
+ }
+ 
+-static ssize_t ibft_attr_show_nic(struct ibft_kobject *entry,
+-				  struct ibft_attribute *attr,
+-				  char *buf)
++static ssize_t ibft_attr_show_nic(void *data, int type, char *buf)
+ {
++	struct ibft_kobject *entry = data;
+ 	struct ibft_nic *nic = entry->nic;
+ 	void *ibft_loc = entry->header;
+ 	char *str = buf;
+@@ -389,42 +293,42 @@ static ssize_t ibft_attr_show_nic(struct ibft_kobject *entry,
+ 	if (!nic)
+ 		return 0;
+ 
+-	switch (attr->type) {
+-	case ibft_eth_index:
++	switch (type) {
++	case ISCSI_BOOT_ETH_INDEX:
+ 		str += sprintf(str, "%d\n", nic->hdr.index);
+ 		break;
+-	case ibft_eth_flags:
++	case ISCSI_BOOT_ETH_FLAGS:
+ 		str += sprintf(str, "%d\n", nic->hdr.flags);
+ 		break;
+-	case ibft_eth_ip_addr:
++	case ISCSI_BOOT_ETH_IP_ADDR:
+ 		str += sprintf_ipaddr(str, nic->ip_addr);
+ 		break;
+-	case ibft_eth_subnet_mask:
++	case ISCSI_BOOT_ETH_SUBNET_MASK:
+ 		val = cpu_to_be32(~((1 << (32-nic->subnet_mask_prefix))-1));
+ 		str += sprintf(str, "%pI4", &val);
+ 		break;
+-	case ibft_eth_origin:
++	case ISCSI_BOOT_ETH_ORIGIN:
+ 		str += sprintf(str, "%d\n", nic->origin);
+ 		break;
+-	case ibft_eth_gateway:
++	case ISCSI_BOOT_ETH_GATEWAY:
+ 		str += sprintf_ipaddr(str, nic->gateway);
+ 		break;
+-	case ibft_eth_primary_dns:
++	case ISCSI_BOOT_ETH_PRIMARY_DNS:
+ 		str += sprintf_ipaddr(str, nic->primary_dns);
+ 		break;
+-	case ibft_eth_secondary_dns:
++	case ISCSI_BOOT_ETH_SECONDARY_DNS:
+ 		str += sprintf_ipaddr(str, nic->secondary_dns);
+ 		break;
+-	case ibft_eth_dhcp:
++	case ISCSI_BOOT_ETH_DHCP:
+ 		str += sprintf_ipaddr(str, nic->dhcp);
+ 		break;
+-	case ibft_eth_vlan:
++	case ISCSI_BOOT_ETH_VLAN:
+ 		str += sprintf(str, "%d\n", nic->vlan);
+ 		break;
+-	case ibft_eth_mac:
++	case ISCSI_BOOT_ETH_MAC:
+ 		str += sprintf(str, "%pM\n", nic->mac);
+ 		break;
+-	case ibft_eth_hostname:
++	case ISCSI_BOOT_ETH_HOSTNAME:
+ 		str += sprintf_string(str, nic->hostname_len,
+ 				      (char *)ibft_loc + nic->hostname_off);
+ 		break;
+@@ -435,10 +339,9 @@ static ssize_t ibft_attr_show_nic(struct ibft_kobject *entry,
+ 	return str - buf;
+ };
+ 
+-static ssize_t ibft_attr_show_target(struct ibft_kobject *entry,
+-				     struct ibft_attribute *attr,
+-				     char *buf)
++static ssize_t ibft_attr_show_target(void *data, int type, char *buf)
+ {
++	struct ibft_kobject *entry = data;
+ 	struct ibft_tgt *tgt = entry->tgt;
+ 	void *ibft_loc = entry->header;
+ 	char *str = buf;
+@@ -447,48 +350,48 @@ static ssize_t ibft_attr_show_target(struct ibft_kobject *entry,
+ 	if (!tgt)
+ 		return 0;
+ 
+-	switch (attr->type) {
+-	case ibft_tgt_index:
++	switch (type) {
++	case ISCSI_BOOT_TGT_INDEX:
+ 		str += sprintf(str, "%d\n", tgt->hdr.index);
+ 		break;
+-	case ibft_tgt_flags:
++	case ISCSI_BOOT_TGT_FLAGS:
+ 		str += sprintf(str, "%d\n", tgt->hdr.flags);
+ 		break;
+-	case ibft_tgt_ip_addr:
++	case ISCSI_BOOT_TGT_IP_ADDR:
+ 		str += sprintf_ipaddr(str, tgt->ip_addr);
+ 		break;
+-	case ibft_tgt_port:
++	case ISCSI_BOOT_TGT_PORT:
+ 		str += sprintf(str, "%d\n", tgt->port);
+ 		break;
+-	case ibft_tgt_lun:
++	case ISCSI_BOOT_TGT_LUN:
+ 		for (i = 0; i < 8; i++)
+ 			str += sprintf(str, "%x", (u8)tgt->lun[i]);
+ 		str += sprintf(str, "\n");
+ 		break;
+-	case ibft_tgt_nic_assoc:
++	case ISCSI_BOOT_TGT_NIC_ASSOC:
+ 		str += sprintf(str, "%d\n", tgt->nic_assoc);
+ 		break;
+-	case ibft_tgt_chap_type:
++	case ISCSI_BOOT_TGT_CHAP_TYPE:
+ 		str += sprintf(str, "%d\n", tgt->chap_type);
+ 		break;
+-	case ibft_tgt_name:
++	case ISCSI_BOOT_TGT_NAME:
+ 		str += sprintf_string(str, tgt->tgt_name_len,
+ 				      (char *)ibft_loc + tgt->tgt_name_off);
+ 		break;
+-	case ibft_tgt_chap_name:
++	case ISCSI_BOOT_TGT_CHAP_NAME:
+ 		str += sprintf_string(str, tgt->chap_name_len,
+ 				      (char *)ibft_loc + tgt->chap_name_off);
+ 		break;
+-	case ibft_tgt_chap_secret:
++	case ISCSI_BOOT_TGT_CHAP_SECRET:
+ 		str += sprintf_string(str, tgt->chap_secret_len,
+ 				      (char *)ibft_loc + tgt->chap_secret_off);
+ 		break;
+-	case ibft_tgt_rev_chap_name:
++	case ISCSI_BOOT_TGT_REV_CHAP_NAME:
+ 		str += sprintf_string(str, tgt->rev_chap_name_len,
+ 				      (char *)ibft_loc +
+ 				      tgt->rev_chap_name_off);
+ 		break;
+-	case ibft_tgt_rev_chap_secret:
++	case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
+ 		str += sprintf_string(str, tgt->rev_chap_secret_len,
+ 				      (char *)ibft_loc +
+ 				      tgt->rev_chap_secret_off);
+@@ -500,40 +403,6 @@ static ssize_t ibft_attr_show_target(struct ibft_kobject *entry,
+ 	return str - buf;
+ }
+ 
+-/*
+- * The routine called for all sysfs attributes.
+- */
+-static ssize_t ibft_show_attribute(struct kobject *kobj,
+-				    struct attribute *attr,
+-				    char *buf)
+-{
+-	struct ibft_kobject *dev =
+-		container_of(kobj, struct ibft_kobject, kobj);
+-	struct ibft_attribute *ibft_attr =
+-		container_of(attr, struct ibft_attribute, attr);
+-	ssize_t ret = -EIO;
+-	char *str = buf;
+-
+-	if (!capable(CAP_SYS_ADMIN))
+-		return -EACCES;
+-
+-	if (ibft_attr->show)
+-		ret = ibft_attr->show(dev, ibft_attr, str);
+-
+-	return ret;
+-}
+-
+-static const struct sysfs_ops ibft_attr_ops = {
+-	.show = ibft_show_attribute,
+-};
+-
+-static struct kobj_type ibft_ktype = {
+-	.release = ibft_release,
+-	.sysfs_ops = &ibft_attr_ops,
+-};
+-
+-static struct kset *ibft_kset;
+-
+ static int __init ibft_check_device(void)
+ {
+ 	int len;
+@@ -560,13 +429,150 @@ static int __init ibft_check_device(void)
+ 	return 0;
+ }
+ 
++/*
++ * Helper routiners to check to determine if the entry is valid
++ * in the proper iBFT structure.
++ */
++static mode_t ibft_check_nic_for(void *data, int type)
++{
++	struct ibft_kobject *entry = data;
++	struct ibft_nic *nic = entry->nic;
++	mode_t rc = 0;
++
++	switch (type) {
++	case ISCSI_BOOT_ETH_INDEX:
++	case ISCSI_BOOT_ETH_FLAGS:
++		rc = S_IRUGO;
++		break;
++	case ISCSI_BOOT_ETH_IP_ADDR:
++		if (memcmp(nic->ip_addr, nulls, sizeof(nic->ip_addr)))
++			rc = S_IRUGO;
++		break;
++	case ISCSI_BOOT_ETH_SUBNET_MASK:
++		if (nic->subnet_mask_prefix)
++			rc = S_IRUGO;
++		break;
++	case ISCSI_BOOT_ETH_ORIGIN:
++		rc = S_IRUGO;
++		break;
++	case ISCSI_BOOT_ETH_GATEWAY:
++		if (memcmp(nic->gateway, nulls, sizeof(nic->gateway)))
++			rc = S_IRUGO;
++		break;
++	case ISCSI_BOOT_ETH_PRIMARY_DNS:
++		if (memcmp(nic->primary_dns, nulls,
++			   sizeof(nic->primary_dns)))
++			rc = S_IRUGO;
++		break;
++	case ISCSI_BOOT_ETH_SECONDARY_DNS:
++		if (memcmp(nic->secondary_dns, nulls,
++			   sizeof(nic->secondary_dns)))
++			rc = S_IRUGO;
++		break;
++	case ISCSI_BOOT_ETH_DHCP:
++		if (memcmp(nic->dhcp, nulls, sizeof(nic->dhcp)))
++			rc = S_IRUGO;
++		break;
++	case ISCSI_BOOT_ETH_VLAN:
++	case ISCSI_BOOT_ETH_MAC:
++		rc = S_IRUGO;
++		break;
++	case ISCSI_BOOT_ETH_HOSTNAME:
++		if (nic->hostname_off)
++			rc = S_IRUGO;
++		break;
++	default:
++		break;
++	}
++
++	return rc;
++}
++
++static mode_t __init ibft_check_tgt_for(void *data, int type)
++{
++	struct ibft_kobject *entry = data;
++	struct ibft_tgt *tgt = entry->tgt;
++	mode_t rc = 0;
++
++	switch (type) {
++	case ISCSI_BOOT_TGT_INDEX:
++	case ISCSI_BOOT_TGT_FLAGS:
++	case ISCSI_BOOT_TGT_IP_ADDR:
++	case ISCSI_BOOT_TGT_PORT:
++	case ISCSI_BOOT_TGT_LUN:
++	case ISCSI_BOOT_TGT_NIC_ASSOC:
++	case ISCSI_BOOT_TGT_CHAP_TYPE:
++		rc = S_IRUGO;
++	case ISCSI_BOOT_TGT_NAME:
++		if (tgt->tgt_name_len)
++			rc = S_IRUGO;
++		break;
++	case ISCSI_BOOT_TGT_CHAP_NAME:
++	case ISCSI_BOOT_TGT_CHAP_SECRET:
++		if (tgt->chap_name_len)
++			rc = S_IRUGO;
++		break;
++	case ISCSI_BOOT_TGT_REV_CHAP_NAME:
++	case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
++		if (tgt->rev_chap_name_len)
++			rc = S_IRUGO;
++		break;
++	default:
++		break;
++	}
++
++	return rc;
++}
++
++static mode_t __init ibft_check_initiator_for(void *data, int type)
++{
++	struct ibft_kobject *entry = data;
++	struct ibft_initiator *init = entry->initiator;
++	mode_t rc = 0;
++
++	switch (type) {
++	case ISCSI_BOOT_INI_INDEX:
++	case ISCSI_BOOT_INI_FLAGS:
++		rc = S_IRUGO;
++		break;
++	case ISCSI_BOOT_INI_ISNS_SERVER:
++		if (memcmp(init->isns_server, nulls,
++			   sizeof(init->isns_server)))
++			rc = S_IRUGO;
++		break;
++	case ISCSI_BOOT_INI_SLP_SERVER:
++		if (memcmp(init->slp_server, nulls,
++			   sizeof(init->slp_server)))
++			rc = S_IRUGO;
++		break;
++	case ISCSI_BOOT_INI_PRI_RADIUS_SERVER:
++		if (memcmp(init->pri_radius_server, nulls,
++			   sizeof(init->pri_radius_server)))
++			rc = S_IRUGO;
++		break;
++	case ISCSI_BOOT_INI_SEC_RADIUS_SERVER:
++		if (memcmp(init->sec_radius_server, nulls,
++			   sizeof(init->sec_radius_server)))
++			rc = S_IRUGO;
++		break;
++	case ISCSI_BOOT_INI_INITIATOR_NAME:
++		if (init->initiator_name_len)
++			rc = S_IRUGO;
++		break;
++	default:
++		break;
++	}
++
++	return rc;
++}
++
+ /*
+  * Helper function for ibft_register_kobjects.
+  */
+ static int __init ibft_create_kobject(struct acpi_table_ibft *header,
+-				       struct ibft_hdr *hdr,
+-				       struct list_head *list)
++				      struct ibft_hdr *hdr)
+ {
++	struct iscsi_boot_kobj *boot_kobj = NULL;
+ 	struct ibft_kobject *ibft_kobj = NULL;
+ 	struct ibft_nic *nic = (struct ibft_nic *)hdr;
+ 	struct pci_dev *pci_dev;
+@@ -583,14 +589,47 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header,
+ 	case id_initiator:
+ 		rc = ibft_verify_hdr("initiator", hdr, id_initiator,
+ 				     sizeof(*ibft_kobj->initiator));
++		if (rc)
++			break;
++
++		boot_kobj = iscsi_boot_create_initiator(boot_kset, hdr->index,
++						ibft_kobj,
++						ibft_attr_show_initiator,
++						ibft_check_initiator_for);
++		if (!boot_kobj) {
++			rc = -ENOMEM;
++			goto free_ibft_obj;
++		}
+ 		break;
+ 	case id_nic:
+ 		rc = ibft_verify_hdr("ethernet", hdr, id_nic,
+ 				     sizeof(*ibft_kobj->nic));
++		if (rc)
++			break;
++
++		boot_kobj = iscsi_boot_create_ethernet(boot_kset, hdr->index,
++						       ibft_kobj,
++						       ibft_attr_show_nic,
++						       ibft_check_nic_for);
++		if (!boot_kobj) {
++			rc = -ENOMEM;
++			goto free_ibft_obj;
++		}
+ 		break;
+ 	case id_target:
+ 		rc = ibft_verify_hdr("target", hdr, id_target,
+ 				     sizeof(*ibft_kobj->tgt));
++		if (rc)
++			break;
++
++		boot_kobj = iscsi_boot_create_target(boot_kset, hdr->index,
++						     ibft_kobj,
++						     ibft_attr_show_target,
++						     ibft_check_tgt_for);
++		if (!boot_kobj) {
++			rc = -ENOMEM;
++			goto free_ibft_obj;
++		}
+ 		break;
+ 	case id_reserved:
+ 	case id_control:
+@@ -608,22 +647,10 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header,
+ 
+ 	if (rc) {
+ 		/* Skip adding this kobject, but exit with non-fatal error. */
+-		kfree(ibft_kobj);
+-		goto out_invalid_struct;
+-	}
+-
+-	ibft_kobj->kobj.kset = ibft_kset;
+-
+-	rc = kobject_init_and_add(&ibft_kobj->kobj, &ibft_ktype,
+-				  NULL, ibft_id_names[hdr->id], hdr->index);
+-
+-	if (rc) {
+-		kfree(ibft_kobj);
+-		goto out;
++		rc = 0;
++		goto free_ibft_obj;
+ 	}
+ 
+-	kobject_uevent(&ibft_kobj->kobj, KOBJ_ADD);
+-
+ 	if (hdr->id == id_nic) {
+ 		/*
+ 		* We don't search for the device in other domains than
+@@ -634,19 +661,16 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header,
+ 		pci_dev = pci_get_bus_and_slot((nic->pci_bdf & 0xff00) >> 8,
+ 					       (nic->pci_bdf & 0xff));
+ 		if (pci_dev) {
+-			rc = sysfs_create_link(&ibft_kobj->kobj,
++			rc = sysfs_create_link(&boot_kobj->kobj,
+ 					       &pci_dev->dev.kobj, "device");
+ 			pci_dev_put(pci_dev);
+ 		}
+ 	}
++	return 0;
+ 
+-	/* Nothing broke so lets add it to the list. */
+-	list_add_tail(&ibft_kobj->node, list);
+-out:
++free_ibft_obj:
++	kfree(ibft_kobj);
+ 	return rc;
+-out_invalid_struct:
+-	/* Unsupported structs are skipped. */
+-	return 0;
+ }
+ 
+ /*
+@@ -654,8 +678,7 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header,
+  * found add them on the passed-in list. We do not support the other
+  * fields at this point, so they are skipped.
+  */
+-static int __init ibft_register_kobjects(struct acpi_table_ibft *header,
+-					  struct list_head *list)
++static int __init ibft_register_kobjects(struct acpi_table_ibft *header)
+ {
+ 	struct ibft_control *control = NULL;
+ 	void *ptr, *end;
+@@ -680,8 +703,7 @@ static int __init ibft_register_kobjects(struct acpi_table_ibft *header,
+ 		if (offset && offset < header->header.length &&
+ 						offset < eot_offset) {
+ 			rc = ibft_create_kobject(header,
+-						 (void *)header + offset,
+-						 list);
++						 (void *)header + offset);
+ 			if (rc)
+ 				break;
+ 		}
+@@ -690,240 +712,28 @@ static int __init ibft_register_kobjects(struct acpi_table_ibft *header,
+ 	return rc;
+ }
+ 
+-static void ibft_unregister(struct list_head *attr_list,
+-			     struct list_head *kobj_list)
++static void ibft_unregister(void)
+ {
+-	struct ibft_kobject *data = NULL, *n;
+-	struct ibft_attribute *attr = NULL, *m;
+-
+-	list_for_each_entry_safe(attr, m, attr_list, node) {
+-		sysfs_remove_file(attr->kobj, &attr->attr);
+-		list_del(&attr->node);
+-		kfree(attr);
++	struct iscsi_boot_kobj *boot_kobj, *tmp_kobj;
++	struct ibft_kobject *ibft_kobj;
++
++	list_for_each_entry_safe(boot_kobj, tmp_kobj,
++				 &boot_kset->kobj_list, list) {
++		ibft_kobj = boot_kobj->data;
++		if (ibft_kobj->hdr->id == id_nic)
++			sysfs_remove_link(&boot_kobj->kobj, "device");
+ 	};
+-	list_del_init(attr_list);
+-
+-	list_for_each_entry_safe(data, n, kobj_list, node) {
+-		list_del(&data->node);
+-		if (data->hdr->id == id_nic)
+-			sysfs_remove_link(&data->kobj, "device");
+-		kobject_put(&data->kobj);
+-	};
+-	list_del_init(kobj_list);
+ }
+ 
+-static int __init ibft_create_attribute(struct ibft_kobject *kobj_data,
+-					 int type,
+-					 const char *name,
+-					 ssize_t (*show)(struct ibft_kobject *,
+-							 struct ibft_attribute*,
+-							 char *buf),
+-					 struct list_head *list)
++static void ibft_cleanup(void)
+ {
+-	struct ibft_attribute *attr = NULL;
+-	struct ibft_hdr *hdr = kobj_data->hdr;
+-
+-	attr = kmalloc(sizeof(*attr), GFP_KERNEL);
+-	if (!attr)
+-		return -ENOMEM;
+-
+-	attr->attr.name = name;
+-	attr->attr.mode = S_IRUSR;
+-
+-	attr->hdr = hdr;
+-	attr->show = show;
+-	attr->kobj = &kobj_data->kobj;
+-	attr->type = type;
+-
+-	list_add_tail(&attr->node, list);
+-
+-	return 0;
+-}
+-
+-/*
+- * Helper routiners to check to determine if the entry is valid
+- * in the proper iBFT structure.
+- */
+-static int __init ibft_check_nic_for(struct ibft_nic *nic, int entry)
+-{
+-	int rc = 0;
+-
+-	switch (entry) {
+-	case ibft_eth_index:
+-	case ibft_eth_flags:
+-		rc = 1;
+-		break;
+-	case ibft_eth_ip_addr:
+-		if (memcmp(nic->ip_addr, nulls, sizeof(nic->ip_addr)))
+-			rc = 1;
+-		break;
+-	case ibft_eth_subnet_mask:
+-		if (nic->subnet_mask_prefix)
+-			rc = 1;
+-		break;
+-	case ibft_eth_origin:
+-		rc = 1;
+-		break;
+-	case ibft_eth_gateway:
+-		if (memcmp(nic->gateway, nulls, sizeof(nic->gateway)))
+-			rc = 1;
+-		break;
+-	case ibft_eth_primary_dns:
+-		if (memcmp(nic->primary_dns, nulls,
+-			   sizeof(nic->primary_dns)))
+-			rc = 1;
+-		break;
+-	case ibft_eth_secondary_dns:
+-		if (memcmp(nic->secondary_dns, nulls,
+-			   sizeof(nic->secondary_dns)))
+-			rc = 1;
+-		break;
+-	case ibft_eth_dhcp:
+-		if (memcmp(nic->dhcp, nulls, sizeof(nic->dhcp)))
+-			rc = 1;
+-		break;
+-	case ibft_eth_vlan:
+-	case ibft_eth_mac:
+-		rc = 1;
+-		break;
+-	case ibft_eth_hostname:
+-		if (nic->hostname_off)
+-			rc = 1;
+-		break;
+-	default:
+-		break;
+-	}
+-
+-	return rc;
++	ibft_unregister();
++	iscsi_boot_destroy_kset(boot_kset);
+ }
+ 
+-static int __init ibft_check_tgt_for(struct ibft_tgt *tgt, int entry)
+-{
+-	int rc = 0;
+-
+-	switch (entry) {
+-	case ibft_tgt_index:
+-	case ibft_tgt_flags:
+-	case ibft_tgt_ip_addr:
+-	case ibft_tgt_port:
+-	case ibft_tgt_lun:
+-	case ibft_tgt_nic_assoc:
+-	case ibft_tgt_chap_type:
+-		rc = 1;
+-	case ibft_tgt_name:
+-		if (tgt->tgt_name_len)
+-			rc = 1;
+-		break;
+-	case ibft_tgt_chap_name:
+-	case ibft_tgt_chap_secret:
+-		if (tgt->chap_name_len)
+-			rc = 1;
+-		break;
+-	case ibft_tgt_rev_chap_name:
+-	case ibft_tgt_rev_chap_secret:
+-		if (tgt->rev_chap_name_len)
+-			rc = 1;
+-		break;
+-	default:
+-		break;
+-	}
+-
+-	return rc;
+-}
+-
+-static int __init ibft_check_initiator_for(struct ibft_initiator *init,
+-					    int entry)
+-{
+-	int rc = 0;
+-
+-	switch (entry) {
+-	case ibft_init_index:
+-	case ibft_init_flags:
+-		rc = 1;
+-		break;
+-	case ibft_init_isns_server:
+-		if (memcmp(init->isns_server, nulls,
+-			   sizeof(init->isns_server)))
+-			rc = 1;
+-		break;
+-	case ibft_init_slp_server:
+-		if (memcmp(init->slp_server, nulls,
+-			   sizeof(init->slp_server)))
+-			rc = 1;
+-		break;
+-	case ibft_init_pri_radius_server:
+-		if (memcmp(init->pri_radius_server, nulls,
+-			   sizeof(init->pri_radius_server)))
+-			rc = 1;
+-		break;
+-	case ibft_init_sec_radius_server:
+-		if (memcmp(init->sec_radius_server, nulls,
+-			   sizeof(init->sec_radius_server)))
+-			rc = 1;
+-		break;
+-	case ibft_init_initiator_name:
+-		if (init->initiator_name_len)
+-			rc = 1;
+-		break;
+-	default:
+-		break;
+-	}
+-
+-	return rc;
+-}
+-
+-/*
+- *  Register the attributes for all of the kobjects.
+- */
+-static int __init ibft_register_attributes(struct list_head *kobject_list,
+-					    struct list_head *attr_list)
++static void __exit ibft_exit(void)
+ {
+-	int rc = 0, i = 0;
+-	struct ibft_kobject *data = NULL;
+-	struct ibft_attribute *attr = NULL, *m;
+-
+-	list_for_each_entry(data, kobject_list, node) {
+-		switch (data->hdr->id) {
+-		case id_nic:
+-			for (i = 0; i < ibft_eth_end_marker && !rc; i++)
+-				if (ibft_check_nic_for(data->nic, i))
+-					rc = ibft_create_attribute(data, i,
+-						ibft_eth_properties[i],
+-						ibft_attr_show_nic, attr_list);
+-			break;
+-		case id_target:
+-			for (i = 0; i < ibft_tgt_end_marker && !rc; i++)
+-				if (ibft_check_tgt_for(data->tgt, i))
+-					rc = ibft_create_attribute(data, i,
+-						ibft_tgt_properties[i],
+-						ibft_attr_show_target,
+-						attr_list);
+-			break;
+-		case id_initiator:
+-			for (i = 0; i < ibft_init_end_marker && !rc; i++)
+-				if (ibft_check_initiator_for(
+-					data->initiator, i))
+-					rc = ibft_create_attribute(data, i,
+-						ibft_initiator_properties[i],
+-						ibft_attr_show_initiator,
+-						attr_list);
+-			break;
+-		default:
+-			break;
+-		}
+-		if (rc)
+-			break;
+-	}
+-	list_for_each_entry_safe(attr, m, attr_list, node) {
+-		rc = sysfs_create_file(attr->kobj, &attr->attr);
+-		if (rc) {
+-			list_del(&attr->node);
+-			kfree(attr);
+-			break;
+-		}
+-	}
+-
+-	return rc;
++	ibft_cleanup();
+ }
+ 
+ /*
+@@ -933,26 +743,20 @@ static int __init ibft_init(void)
+ {
+ 	int rc = 0;
+ 
+-	ibft_kset = kset_create_and_add("ibft", NULL, firmware_kobj);
+-	if (!ibft_kset)
+-		return -ENOMEM;
+-
+ 	if (ibft_addr) {
+ 		printk(KERN_INFO "iBFT detected at 0x%llx.\n",
+ 		       (u64)isa_virt_to_bus(ibft_addr));
+ 
+ 		rc = ibft_check_device();
+ 		if (rc)
+-			goto out_firmware_unregister;
++			return rc;
+ 
+-		/* Scan the IBFT for data and register the kobjects. */
+-		rc = ibft_register_kobjects(ibft_addr, &ibft_kobject_list);
+-		if (rc)
+-			goto out_free;
++		boot_kset = iscsi_boot_create_kset("ibft");
++		if (!boot_kset)
++			return -ENOMEM;
+ 
+-		/* Register the attributes */
+-		rc = ibft_register_attributes(&ibft_kobject_list,
+-					      &ibft_attr_list);
++		/* Scan the IBFT for data and register the kobjects. */
++		rc = ibft_register_kobjects(ibft_addr);
+ 		if (rc)
+ 			goto out_free;
+ 	} else
+@@ -961,17 +765,9 @@ static int __init ibft_init(void)
+ 	return 0;
+ 
+ out_free:
+-	ibft_unregister(&ibft_attr_list, &ibft_kobject_list);
+-out_firmware_unregister:
+-	kset_unregister(ibft_kset);
++	ibft_cleanup();
+ 	return rc;
+ }
+ 
+-static void __exit ibft_exit(void)
+-{
+-	ibft_unregister(&ibft_attr_list, &ibft_kobject_list);
+-	kset_unregister(ibft_kset);
+-}
+-
+ module_init(ibft_init);
+ module_exit(ibft_exit);

commit ba4ee30c6c797de148dcc7254cf6d531aba71d9b
+Author: Mike Christie 
+Date:   Mon Apr 12 18:06:17 2010 +0000
+
+    ibft: separate ibft parsing from sysfs interface
+    
+    Not all iscsi drivers support ibft. For drivers like be2iscsi
+    that do not but are bootable through a vendor firmware specific
+    format/process this patch moves the sysfs interface from the ibft code
+    to a lib module. This then allows userspace tools to search for iscsi boot
+    info in a common place and in a common format.
+    
+    ibft iscsi boot info is exported in the same place as it was
+    before: /sys/firmware/ibft.
+    
+    vendor/fw boot info gets export in /sys/firmware/iscsi_bootX, where X is the
+    scsi host number of the HBA. Underneath these parent dirs, the
+    target, ethernet, and initiator dirs are the same as they were before.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Konrad Rzeszutek Wilk 
+    Signed-off-by: Peter Jones 
+
+diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
+index 1b03ba1d0834..571d2182613d 100644
+--- a/drivers/firmware/Kconfig
++++ b/drivers/firmware/Kconfig
+@@ -122,6 +122,14 @@ config ISCSI_IBFT_FIND
+ 	  is necessary for iSCSI Boot Firmware Table Attributes module to work
+ 	  properly.
+ 
++config ISCSI_BOOT_SYSFS
++	tristate "iSCSI Boot Sysfs Interface"
++	default	n
++	help
++	  This option enables support for exposing iSCSI boot information
++	  via sysfs to userspace. If you wish to export this information,
++	  say Y. Otherwise, say N.
++
+ config ISCSI_IBFT
+ 	tristate "iSCSI Boot Firmware Table Attributes module"
+ 	depends on ISCSI_IBFT_FIND
+diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
+index 1c3c17343dbe..5fe7e1662922 100644
+--- a/drivers/firmware/Makefile
++++ b/drivers/firmware/Makefile
+@@ -10,4 +10,5 @@ obj-$(CONFIG_DCDBAS)		+= dcdbas.o
+ obj-$(CONFIG_DMIID)		+= dmi-id.o
+ obj-$(CONFIG_ISCSI_IBFT_FIND)	+= iscsi_ibft_find.o
+ obj-$(CONFIG_ISCSI_IBFT)	+= iscsi_ibft.o
++obj-$(CONFIG_ISCSI_BOOT_SYSFS)	+= iscsi_boot_sysfs.o
+ obj-$(CONFIG_FIRMWARE_MEMMAP)	+= memmap.o
+diff --git a/drivers/firmware/iscsi_boot_sysfs.c b/drivers/firmware/iscsi_boot_sysfs.c
+new file mode 100644
+index 000000000000..df6bff7366cf
+--- /dev/null
++++ b/drivers/firmware/iscsi_boot_sysfs.c
+@@ -0,0 +1,481 @@
++/*
++ * Export the iSCSI boot info to userland via sysfs.
++ *
++ * Copyright (C) 2010 Red Hat, Inc.  All rights reserved.
++ * Copyright (C) 2010 Mike Christie
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License v2.0 as published by
++ * the Free Software Foundation
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++
++MODULE_AUTHOR("Mike Christie ");
++MODULE_DESCRIPTION("sysfs interface and helpers to export iSCSI boot information");
++MODULE_LICENSE("GPL");
++/*
++ * The kobject and attribute structures.
++ */
++struct iscsi_boot_attr {
++	struct attribute attr;
++	int type;
++	ssize_t (*show) (void *data, int type, char *buf);
++};
++
++/*
++ * The routine called for all sysfs attributes.
++ */
++static ssize_t iscsi_boot_show_attribute(struct kobject *kobj,
++					 struct attribute *attr, char *buf)
++{
++	struct iscsi_boot_kobj *boot_kobj =
++			container_of(kobj, struct iscsi_boot_kobj, kobj);
++	struct iscsi_boot_attr *boot_attr =
++			container_of(attr, struct iscsi_boot_attr, attr);
++	ssize_t ret = -EIO;
++	char *str = buf;
++
++	if (!capable(CAP_SYS_ADMIN))
++		return -EACCES;
++
++	if (boot_kobj->show)
++		ret = boot_kobj->show(boot_kobj->data, boot_attr->type, str);
++	return ret;
++}
++
++static const struct sysfs_ops iscsi_boot_attr_ops = {
++	.show = iscsi_boot_show_attribute,
++};
++
++static void iscsi_boot_kobj_release(struct kobject *kobj)
++{
++	struct iscsi_boot_kobj *boot_kobj =
++			container_of(kobj, struct iscsi_boot_kobj, kobj);
++
++	kfree(boot_kobj->data);
++	kfree(boot_kobj);
++}
++
++static struct kobj_type iscsi_boot_ktype = {
++	.release = iscsi_boot_kobj_release,
++	.sysfs_ops = &iscsi_boot_attr_ops,
++};
++
++#define iscsi_boot_rd_attr(fnname, sysfs_name, attr_type)		\
++static struct iscsi_boot_attr iscsi_boot_attr_##fnname = {	\
++	.attr	= { .name = __stringify(sysfs_name), .mode = 0444 },	\
++	.type	= attr_type,						\
++}
++
++/* Target attrs */
++iscsi_boot_rd_attr(tgt_index, index, ISCSI_BOOT_TGT_INDEX);
++iscsi_boot_rd_attr(tgt_flags, flags, ISCSI_BOOT_TGT_FLAGS);
++iscsi_boot_rd_attr(tgt_ip, ip-addr, ISCSI_BOOT_TGT_IP_ADDR);
++iscsi_boot_rd_attr(tgt_port, port, ISCSI_BOOT_TGT_PORT);
++iscsi_boot_rd_attr(tgt_lun, lun, ISCSI_BOOT_TGT_LUN);
++iscsi_boot_rd_attr(tgt_chap, chap-type, ISCSI_BOOT_TGT_CHAP_TYPE);
++iscsi_boot_rd_attr(tgt_nic, nic-assoc, ISCSI_BOOT_TGT_NIC_ASSOC);
++iscsi_boot_rd_attr(tgt_name, target-name, ISCSI_BOOT_TGT_NAME);
++iscsi_boot_rd_attr(tgt_chap_name, chap-name, ISCSI_BOOT_TGT_CHAP_NAME);
++iscsi_boot_rd_attr(tgt_chap_secret, chap-secret, ISCSI_BOOT_TGT_CHAP_SECRET);
++iscsi_boot_rd_attr(tgt_chap_rev_name, rev-chap-name,
++		   ISCSI_BOOT_TGT_REV_CHAP_NAME);
++iscsi_boot_rd_attr(tgt_chap_rev_secret, rev-chap-name-secret,
++		   ISCSI_BOOT_TGT_REV_CHAP_SECRET);
++
++static struct attribute *target_attrs[] = {
++	&iscsi_boot_attr_tgt_index.attr,
++	&iscsi_boot_attr_tgt_flags.attr,
++	&iscsi_boot_attr_tgt_ip.attr,
++	&iscsi_boot_attr_tgt_port.attr,
++	&iscsi_boot_attr_tgt_lun.attr,
++	&iscsi_boot_attr_tgt_chap.attr,
++	&iscsi_boot_attr_tgt_nic.attr,
++	&iscsi_boot_attr_tgt_name.attr,
++	&iscsi_boot_attr_tgt_chap_name.attr,
++	&iscsi_boot_attr_tgt_chap_secret.attr,
++	&iscsi_boot_attr_tgt_chap_rev_name.attr,
++	&iscsi_boot_attr_tgt_chap_rev_secret.attr,
++	NULL
++};
++
++static mode_t iscsi_boot_tgt_attr_is_visible(struct kobject *kobj,
++					     struct attribute *attr, int i)
++{
++	struct iscsi_boot_kobj *boot_kobj =
++			container_of(kobj, struct iscsi_boot_kobj, kobj);
++
++	if (attr ==  &iscsi_boot_attr_tgt_index.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_TGT_INDEX);
++	else if (attr == &iscsi_boot_attr_tgt_flags.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_TGT_FLAGS);
++	else if (attr == &iscsi_boot_attr_tgt_ip.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					      ISCSI_BOOT_TGT_IP_ADDR);
++	else if (attr == &iscsi_boot_attr_tgt_port.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					      ISCSI_BOOT_TGT_PORT);
++	else if (attr == &iscsi_boot_attr_tgt_lun.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					      ISCSI_BOOT_TGT_LUN);
++	else if (attr == &iscsi_boot_attr_tgt_chap.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_TGT_CHAP_TYPE);
++	else if (attr == &iscsi_boot_attr_tgt_nic.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_TGT_NIC_ASSOC);
++	else if (attr == &iscsi_boot_attr_tgt_name.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_TGT_NAME);
++	else if (attr == &iscsi_boot_attr_tgt_chap_name.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_TGT_CHAP_NAME);
++	else if (attr == &iscsi_boot_attr_tgt_chap_secret.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_TGT_CHAP_SECRET);
++	else if (attr == &iscsi_boot_attr_tgt_chap_rev_name.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_TGT_REV_CHAP_NAME);
++	else if (attr == &iscsi_boot_attr_tgt_chap_rev_secret.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_TGT_REV_CHAP_SECRET);
++	return 0;
++}
++
++static struct attribute_group iscsi_boot_target_attr_group = {
++	.attrs = target_attrs,
++	.is_visible = iscsi_boot_tgt_attr_is_visible,
++};
++
++/* Ethernet attrs */
++iscsi_boot_rd_attr(eth_index, index, ISCSI_BOOT_ETH_INDEX);
++iscsi_boot_rd_attr(eth_flags, flags, ISCSI_BOOT_ETH_FLAGS);
++iscsi_boot_rd_attr(eth_ip, ip-addr, ISCSI_BOOT_ETH_IP_ADDR);
++iscsi_boot_rd_attr(eth_subnet, subnet-mask, ISCSI_BOOT_ETH_SUBNET_MASK);
++iscsi_boot_rd_attr(eth_origin, origin, ISCSI_BOOT_ETH_ORIGIN);
++iscsi_boot_rd_attr(eth_gateway, gateway, ISCSI_BOOT_ETH_GATEWAY);
++iscsi_boot_rd_attr(eth_primary_dns, primary-dns, ISCSI_BOOT_ETH_PRIMARY_DNS);
++iscsi_boot_rd_attr(eth_secondary_dns, secondary-dns,
++		   ISCSI_BOOT_ETH_SECONDARY_DNS);
++iscsi_boot_rd_attr(eth_dhcp, dhcp, ISCSI_BOOT_ETH_DHCP);
++iscsi_boot_rd_attr(eth_vlan, vlan, ISCSI_BOOT_ETH_VLAN);
++iscsi_boot_rd_attr(eth_mac, mac, ISCSI_BOOT_ETH_MAC);
++iscsi_boot_rd_attr(eth_hostname, hostname, ISCSI_BOOT_ETH_HOSTNAME);
++
++static struct attribute *ethernet_attrs[] = {
++	&iscsi_boot_attr_eth_index.attr,
++	&iscsi_boot_attr_eth_flags.attr,
++	&iscsi_boot_attr_eth_ip.attr,
++	&iscsi_boot_attr_eth_subnet.attr,
++	&iscsi_boot_attr_eth_origin.attr,
++	&iscsi_boot_attr_eth_gateway.attr,
++	&iscsi_boot_attr_eth_primary_dns.attr,
++	&iscsi_boot_attr_eth_secondary_dns.attr,
++	&iscsi_boot_attr_eth_dhcp.attr,
++	&iscsi_boot_attr_eth_vlan.attr,
++	&iscsi_boot_attr_eth_mac.attr,
++	&iscsi_boot_attr_eth_hostname.attr,
++	NULL
++};
++
++static mode_t iscsi_boot_eth_attr_is_visible(struct kobject *kobj,
++					     struct attribute *attr, int i)
++{
++	struct iscsi_boot_kobj *boot_kobj =
++			container_of(kobj, struct iscsi_boot_kobj, kobj);
++
++	if (attr ==  &iscsi_boot_attr_eth_index.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_ETH_INDEX);
++	else if (attr ==  &iscsi_boot_attr_eth_flags.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_ETH_FLAGS);
++	else if (attr ==  &iscsi_boot_attr_eth_ip.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_ETH_IP_ADDR);
++	else if (attr ==  &iscsi_boot_attr_eth_subnet.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_ETH_SUBNET_MASK);
++	else if (attr ==  &iscsi_boot_attr_eth_origin.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_ETH_ORIGIN);
++	else if (attr ==  &iscsi_boot_attr_eth_gateway.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_ETH_GATEWAY);
++	else if (attr ==  &iscsi_boot_attr_eth_primary_dns.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_ETH_PRIMARY_DNS);
++	else if (attr ==  &iscsi_boot_attr_eth_secondary_dns.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_ETH_SECONDARY_DNS);
++	else if (attr ==  &iscsi_boot_attr_eth_dhcp.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_ETH_DHCP);
++	else if (attr ==  &iscsi_boot_attr_eth_vlan.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_ETH_VLAN);
++	else if (attr ==  &iscsi_boot_attr_eth_mac.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_ETH_MAC);
++	else if (attr ==  &iscsi_boot_attr_eth_hostname.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_ETH_HOSTNAME);
++	return 0;
++}
++
++static struct attribute_group iscsi_boot_ethernet_attr_group = {
++	.attrs = ethernet_attrs,
++	.is_visible = iscsi_boot_eth_attr_is_visible,
++};
++
++/* Initiator attrs */
++iscsi_boot_rd_attr(ini_index, index, ISCSI_BOOT_INI_INDEX);
++iscsi_boot_rd_attr(ini_flags, flags, ISCSI_BOOT_INI_FLAGS);
++iscsi_boot_rd_attr(ini_isns, isns-server, ISCSI_BOOT_INI_ISNS_SERVER);
++iscsi_boot_rd_attr(ini_slp, slp-server, ISCSI_BOOT_INI_SLP_SERVER);
++iscsi_boot_rd_attr(ini_primary_radius, pri-radius-server,
++		   ISCSI_BOOT_INI_PRI_RADIUS_SERVER);
++iscsi_boot_rd_attr(ini_secondary_radius, sec-radius-server,
++		   ISCSI_BOOT_INI_SEC_RADIUS_SERVER);
++iscsi_boot_rd_attr(ini_name, initiator-name, ISCSI_BOOT_INI_INITIATOR_NAME);
++
++static struct attribute *initiator_attrs[] = {
++	&iscsi_boot_attr_ini_index.attr,
++	&iscsi_boot_attr_ini_flags.attr,
++	&iscsi_boot_attr_ini_isns.attr,
++	&iscsi_boot_attr_ini_slp.attr,
++	&iscsi_boot_attr_ini_primary_radius.attr,
++	&iscsi_boot_attr_ini_secondary_radius.attr,
++	&iscsi_boot_attr_ini_name.attr,
++	NULL
++};
++
++static mode_t iscsi_boot_ini_attr_is_visible(struct kobject *kobj,
++					     struct attribute *attr, int i)
++{
++	struct iscsi_boot_kobj *boot_kobj =
++			container_of(kobj, struct iscsi_boot_kobj, kobj);
++
++	if (attr ==  &iscsi_boot_attr_ini_index.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_INI_INDEX);
++	if (attr ==  &iscsi_boot_attr_ini_flags.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_INI_FLAGS);
++	if (attr ==  &iscsi_boot_attr_ini_isns.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_INI_ISNS_SERVER);
++	if (attr ==  &iscsi_boot_attr_ini_slp.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_INI_SLP_SERVER);
++	if (attr ==  &iscsi_boot_attr_ini_primary_radius.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_INI_PRI_RADIUS_SERVER);
++	if (attr ==  &iscsi_boot_attr_ini_secondary_radius.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_INI_SEC_RADIUS_SERVER);
++	if (attr ==  &iscsi_boot_attr_ini_name.attr)
++		return boot_kobj->is_visible(boot_kobj->data,
++					     ISCSI_BOOT_INI_INITIATOR_NAME);
++
++	return 0;
++}
++
++static struct attribute_group iscsi_boot_initiator_attr_group = {
++	.attrs = initiator_attrs,
++	.is_visible = iscsi_boot_ini_attr_is_visible,
++};
++
++static struct iscsi_boot_kobj *
++iscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset,
++		       struct attribute_group *attr_group,
++		       const char *name, int index, void *data,
++		       ssize_t (*show) (void *data, int type, char *buf),
++		       mode_t (*is_visible) (void *data, int type))
++{
++	struct iscsi_boot_kobj *boot_kobj;
++
++	boot_kobj = kzalloc(sizeof(*boot_kobj), GFP_KERNEL);
++	if (!boot_kobj)
++		return NULL;
++	INIT_LIST_HEAD(&boot_kobj->list);
++
++	boot_kobj->kobj.kset = boot_kset->kset;
++	if (kobject_init_and_add(&boot_kobj->kobj, &iscsi_boot_ktype,
++				 NULL, name, index)) {
++		kfree(boot_kobj);
++		return NULL;
++	}
++	boot_kobj->data = data;
++	boot_kobj->show = show;
++	boot_kobj->is_visible = is_visible;
++
++	if (sysfs_create_group(&boot_kobj->kobj, attr_group)) {
++		/*
++		 * We do not want to free this because the caller
++		 * will assume that since the creation call failed
++		 * the boot kobj was not setup and the normal release
++		 * path is not being run.
++		 */
++		boot_kobj->data = NULL;
++		kobject_put(&boot_kobj->kobj);
++		return NULL;
++	}
++	boot_kobj->attr_group = attr_group;
++
++	kobject_uevent(&boot_kobj->kobj, KOBJ_ADD);
++	/* Nothing broke so lets add it to the list. */
++	list_add_tail(&boot_kobj->list, &boot_kset->kobj_list);
++	return boot_kobj;
++}
++
++static void iscsi_boot_remove_kobj(struct iscsi_boot_kobj *boot_kobj)
++{
++	list_del(&boot_kobj->list);
++	sysfs_remove_group(&boot_kobj->kobj, boot_kobj->attr_group);
++	kobject_put(&boot_kobj->kobj);
++}
++
++/**
++ * iscsi_boot_create_target() - create boot target sysfs dir
++ * @boot_kset: boot kset
++ * @index: the target id
++ * @data: driver specific data for target
++ * @show: attr show function
++ * @is_visible: attr visibility function
++ *
++ * Note: The boot sysfs lib will free the data passed in for the caller
++ * when all refs to the target kobject have been released.
++ */
++struct iscsi_boot_kobj *
++iscsi_boot_create_target(struct iscsi_boot_kset *boot_kset, int index,
++			 void *data,
++			 ssize_t (*show) (void *data, int type, char *buf),
++			 mode_t (*is_visible) (void *data, int type))
++{
++	return iscsi_boot_create_kobj(boot_kset, &iscsi_boot_target_attr_group,
++				      "target%d", index, data, show, is_visible);
++}
++EXPORT_SYMBOL_GPL(iscsi_boot_create_target);
++
++/**
++ * iscsi_boot_create_initiator() - create boot initiator sysfs dir
++ * @boot_kset: boot kset
++ * @index: the initiator id
++ * @data: driver specific data
++ * @show: attr show function
++ * @is_visible: attr visibility function
++ *
++ * Note: The boot sysfs lib will free the data passed in for the caller
++ * when all refs to the initiator kobject have been released.
++ */
++struct iscsi_boot_kobj *
++iscsi_boot_create_initiator(struct iscsi_boot_kset *boot_kset, int index,
++			    void *data,
++			    ssize_t (*show) (void *data, int type, char *buf),
++			    mode_t (*is_visible) (void *data, int type))
++{
++	return iscsi_boot_create_kobj(boot_kset,
++				      &iscsi_boot_initiator_attr_group,
++				      "initiator", index, data, show,
++				      is_visible);
++}
++EXPORT_SYMBOL_GPL(iscsi_boot_create_initiator);
++
++/**
++ * iscsi_boot_create_ethernet() - create boot ethernet sysfs dir
++ * @boot_kset: boot kset
++ * @index: the ethernet device id
++ * @data: driver specific data
++ * @show: attr show function
++ * @is_visible: attr visibility function
++ *
++ * Note: The boot sysfs lib will free the data passed in for the caller
++ * when all refs to the ethernet kobject have been released.
++ */
++struct iscsi_boot_kobj *
++iscsi_boot_create_ethernet(struct iscsi_boot_kset *boot_kset, int index,
++			   void *data,
++			   ssize_t (*show) (void *data, int type, char *buf),
++			   mode_t (*is_visible) (void *data, int type))
++{
++	return iscsi_boot_create_kobj(boot_kset,
++				      &iscsi_boot_ethernet_attr_group,
++				      "ethernet%d", index, data, show,
++				      is_visible);
++}
++EXPORT_SYMBOL_GPL(iscsi_boot_create_ethernet);
++
++/**
++ * iscsi_boot_create_kset() - creates root sysfs tree
++ * @set_name: name of root dir
++ */
++struct iscsi_boot_kset *iscsi_boot_create_kset(const char *set_name)
++{
++	struct iscsi_boot_kset *boot_kset;
++
++	boot_kset = kzalloc(sizeof(*boot_kset), GFP_KERNEL);
++	if (!boot_kset)
++		return NULL;
++
++	boot_kset->kset = kset_create_and_add(set_name, NULL, firmware_kobj);
++	if (!boot_kset->kset) {
++		kfree(boot_kset);
++		return NULL;
++	}
++
++	INIT_LIST_HEAD(&boot_kset->kobj_list);
++	return boot_kset;
++}
++EXPORT_SYMBOL_GPL(iscsi_boot_create_kset);
++
++/**
++ * iscsi_boot_create_host_kset() - creates root sysfs tree for a scsi host
++ * @hostno: host number of scsi host
++ */
++struct iscsi_boot_kset *iscsi_boot_create_host_kset(unsigned int hostno)
++{
++	struct iscsi_boot_kset *boot_kset;
++	char *set_name;
++
++	set_name = kasprintf(GFP_KERNEL, "iscsi_boot%u", hostno);
++	if (!set_name)
++		return NULL;
++
++	boot_kset = iscsi_boot_create_kset(set_name);
++	kfree(set_name);
++	return boot_kset;
++}
++EXPORT_SYMBOL_GPL(iscsi_boot_create_host_kset);
++
++/**
++ * iscsi_boot_destroy_kset() - destroy kset and kobjects under it
++ * @boot_kset: boot kset
++ *
++ * This will remove the kset and kobjects and attrs under it.
++ */
++void iscsi_boot_destroy_kset(struct iscsi_boot_kset *boot_kset)
++{
++	struct iscsi_boot_kobj *boot_kobj, *tmp_kobj;
++
++	list_for_each_entry_safe(boot_kobj, tmp_kobj,
++				 &boot_kset->kobj_list, list)
++		iscsi_boot_remove_kobj(boot_kobj);
++
++	kset_unregister(boot_kset->kset);
++}
++EXPORT_SYMBOL_GPL(iscsi_boot_destroy_kset);
+diff --git a/include/linux/iscsi_boot_sysfs.h b/include/linux/iscsi_boot_sysfs.h
+new file mode 100644
+index 000000000000..f1e6c184f14f
+--- /dev/null
++++ b/include/linux/iscsi_boot_sysfs.h
+@@ -0,0 +1,123 @@
++/*
++ * Export the iSCSI boot info to userland via sysfs.
++ *
++ * Copyright (C) 2010 Red Hat, Inc.  All rights reserved.
++ * Copyright (C) 2010 Mike Christie
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License v2.0 as published by
++ * the Free Software Foundation
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ */
++#ifndef _ISCSI_BOOT_SYSFS_
++#define _ISCSI_BOOT_SYSFS_
++
++/*
++ * The text attributes names for each of the kobjects.
++*/
++enum iscsi_boot_eth_properties_enum {
++	ISCSI_BOOT_ETH_INDEX,
++	ISCSI_BOOT_ETH_FLAGS,
++	ISCSI_BOOT_ETH_IP_ADDR,
++	ISCSI_BOOT_ETH_SUBNET_MASK,
++	ISCSI_BOOT_ETH_ORIGIN,
++	ISCSI_BOOT_ETH_GATEWAY,
++	ISCSI_BOOT_ETH_PRIMARY_DNS,
++	ISCSI_BOOT_ETH_SECONDARY_DNS,
++	ISCSI_BOOT_ETH_DHCP,
++	ISCSI_BOOT_ETH_VLAN,
++	ISCSI_BOOT_ETH_MAC,
++	/* eth_pci_bdf - this is replaced by link to the device itself. */
++	ISCSI_BOOT_ETH_HOSTNAME,
++	ISCSI_BOOT_ETH_END_MARKER,
++};
++
++enum iscsi_boot_tgt_properties_enum {
++	ISCSI_BOOT_TGT_INDEX,
++	ISCSI_BOOT_TGT_FLAGS,
++	ISCSI_BOOT_TGT_IP_ADDR,
++	ISCSI_BOOT_TGT_PORT,
++	ISCSI_BOOT_TGT_LUN,
++	ISCSI_BOOT_TGT_CHAP_TYPE,
++	ISCSI_BOOT_TGT_NIC_ASSOC,
++	ISCSI_BOOT_TGT_NAME,
++	ISCSI_BOOT_TGT_CHAP_NAME,
++	ISCSI_BOOT_TGT_CHAP_SECRET,
++	ISCSI_BOOT_TGT_REV_CHAP_NAME,
++	ISCSI_BOOT_TGT_REV_CHAP_SECRET,
++	ISCSI_BOOT_TGT_END_MARKER,
++};
++
++enum iscsi_boot_initiator_properties_enum {
++	ISCSI_BOOT_INI_INDEX,
++	ISCSI_BOOT_INI_FLAGS,
++	ISCSI_BOOT_INI_ISNS_SERVER,
++	ISCSI_BOOT_INI_SLP_SERVER,
++	ISCSI_BOOT_INI_PRI_RADIUS_SERVER,
++	ISCSI_BOOT_INI_SEC_RADIUS_SERVER,
++	ISCSI_BOOT_INI_INITIATOR_NAME,
++	ISCSI_BOOT_INI_END_MARKER,
++};
++
++struct attribute_group;
++
++struct iscsi_boot_kobj {
++	struct kobject kobj;
++	struct attribute_group *attr_group;
++	struct list_head list;
++
++	/*
++	 * Pointer to store driver specific info. If set this will
++	 * be freed for the LLD when the kobj release function is called.
++	 */
++	void *data;
++	/*
++	 * Driver specific show function.
++	 *
++	 * The enum of the type. This can be any value of the above
++	 * properties.
++	 */
++	ssize_t (*show) (void *data, int type, char *buf);
++
++	/*
++	 * Drivers specific visibility function.
++	 * The function should return if they the attr should be readable
++	 * writable or should not be shown.
++	 *
++	 * The enum of the type. This can be any value of the above
++	 * properties.
++	 */
++	mode_t (*is_visible) (void *data, int type);
++};
++
++struct iscsi_boot_kset {
++	struct list_head kobj_list;
++	struct kset *kset;
++};
++
++struct iscsi_boot_kobj *
++iscsi_boot_create_initiator(struct iscsi_boot_kset *boot_kset, int index,
++			    void *data,
++			    ssize_t (*show) (void *data, int type, char *buf),
++			    mode_t (*is_visible) (void *data, int type));
++
++struct iscsi_boot_kobj *
++iscsi_boot_create_ethernet(struct iscsi_boot_kset *boot_kset, int index,
++			   void *data,
++			   ssize_t (*show) (void *data, int type, char *buf),
++			   mode_t (*is_visible) (void *data, int type));
++struct iscsi_boot_kobj *
++iscsi_boot_create_target(struct iscsi_boot_kset *boot_kset, int index,
++			 void *data,
++			 ssize_t (*show) (void *data, int type, char *buf),
++			 mode_t (*is_visible) (void *data, int type));
++
++struct iscsi_boot_kset *iscsi_boot_create_kset(const char *set_name);
++struct iscsi_boot_kset *iscsi_boot_create_host_kset(unsigned int hostno);
++void iscsi_boot_destroy_kset(struct iscsi_boot_kset *boot_kset);
++
++#endif

commit 96b1f96dcab87756c0a1e7ba76bc5dc2add82b88
+Author: Mike Christie 
+Date:   Sat Apr 24 16:21:19 2010 -0500
+
+    [SCSI] libiscsi: regression: fix header digest errors
+    
+    This fixes a regression introduced with this commit:
+    
+    commit d3305f3407fa3e9452079ec6cc8379067456e4aa
+    Author: Mike Christie 
+    Date:   Thu Aug 20 15:10:58 2009 -0500
+    
+        [SCSI] libiscsi: don't increment cmdsn if cmd is not sent
+    
+    in 2.6.32.
+    
+    When I moved the hdr->cmdsn after init_task, I added
+    a bug when header digests are used. The problem is
+    that the LLD may calculate the header digest in init_task,
+    so if we then set the cmdsn after the init_task call we
+    change what the digest will be calculated by the target.
+    
+    Signed-off-by: Mike Christie 
+    Cc: Stable Tree 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 6d5ae4474bb3..633e09036357 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -471,12 +471,12 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
+ 
+ 	WARN_ON(hdrlength >= 256);
+ 	hdr->hlength = hdrlength & 0xFF;
++	hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn);
+ 
+ 	if (session->tt->init_task && session->tt->init_task(task))
+ 		return -EIO;
+ 
+ 	task->state = ISCSI_TASK_RUNNING;
+-	hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn);
+ 	session->cmdsn++;
+ 
+ 	conn->scsicmd_pdus_cnt++;

commit 5738d4449c1baf05e8345684d12371f76296473d
+Author: Mike Christie 
+Date:   Fri Apr 9 22:07:37 2010 -0500
+
+    [SCSI] scsi_dh_emc: request flag cleanup
+    
+    blk_get_request sets the cmd_flags, so we should not and do not
+    need to set them. If we did set them to a different value then
+    it can cause a oops in the elevator code.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c
+index e8a0bc3efd49..6faf472f7537 100644
+--- a/drivers/scsi/device_handler/scsi_dh_emc.c
++++ b/drivers/scsi/device_handler/scsi_dh_emc.c
+@@ -285,13 +285,11 @@ static struct request *get_req(struct scsi_device *sdev, int cmd,
+ 	switch (cmd) {
+ 	case MODE_SELECT:
+ 		len = sizeof(short_trespass);
+-		rq->cmd_flags |= REQ_RW;
+ 		rq->cmd[1] = 0x10;
+ 		rq->cmd[4] = len;
+ 		break;
+ 	case MODE_SELECT_10:
+ 		len = sizeof(long_trespass);
+-		rq->cmd_flags |= REQ_RW;
+ 		rq->cmd[1] = 0x10;
+ 		rq->cmd[8] = len;
+ 		break;

commit d7d05548a62c87ee55b0c81933669177f885aa8d
+Author: Mike Christie 
+Date:   Wed Mar 31 14:41:35 2010 -0500
+
+    [SCSI] iscsi_tcp: fix relogin/shutdown hang
+    
+    When I made this patch:
+    b64e77f70b8c11766e967e3485331a9e6ef01390
+    it was to solve a problem where we were already on the waitqueue
+    becuase a connection problem/logout caused us to be on there
+    when we were cleaning up the session. If we happen to get
+    on queue for more normal reasons like their just does not happen
+    to be any send space at the same time we are closing the connection
+    we hit a race and get stuck in the wait.
+    
+    We should not check if the waitqueue is active
+    because we could race with the network code. If
+    the network xmit code is just about to enter the
+    prepare to wait when we check for the waitqueue to
+    be active then we will miss each other and the
+    network code will fall into the wait and we will
+    not run wake_up.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 0ee725ced511..02143af7c1af 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -599,7 +599,7 @@ static void iscsi_sw_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+ 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
+ 	write_unlock_bh(&tcp_sw_conn->sock->sk->sk_callback_lock);
+ 
+-	if (sock->sk->sk_sleep && waitqueue_active(sock->sk->sk_sleep)) {
++	if (sock->sk->sk_sleep) {
+ 		sock->sk->sk_err = EIO;
+ 		wake_up_interruptible(sock->sk->sk_sleep);
+ 	}

commit 4ae0a6c15efcc37e94e3f30e3533bdec03c53126
+Author: Mike Christie 
+Date:   Tue Mar 9 14:14:51 2010 -0600
+
+    [SCSI] libiscsi: Fix recovery slowdown regression
+    
+    We could be failing/stopping a connection due to libiscsi starting
+    recovery/cleanup, but the xmit path or scsi eh thread path
+    could be dropping the connection at the same time.
+    
+    As a result the session->state gets set to failed instead of in
+    recovery. We end up not blocking the session
+    and so the replacement timeout never gets started and we only end up
+    failing the IO when scsi_softirq_done sees that the
+    cmd has been running for (cmd->allowed + 1) * rq->timeout secs.
+    
+    We used to fail the IO right away so users are seeing a long
+    delay when using dm-multipath. This problem was added in
+    2.6.28.
+    
+    Signed-off-by: Mike Christie 
+    Cc: stable@kernel.org
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 685eaec53218..7688b8f83e98 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -3087,14 +3087,15 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ 		session->state = ISCSI_STATE_TERMINATE;
+ 	else if (conn->stop_stage != STOP_CONN_RECOVER)
+ 		session->state = ISCSI_STATE_IN_RECOVERY;
++
++	old_stop_stage = conn->stop_stage;
++	conn->stop_stage = flag;
+ 	spin_unlock_bh(&session->lock);
+ 
+ 	del_timer_sync(&conn->transport_timer);
+ 	iscsi_suspend_tx(conn);
+ 
+ 	spin_lock_bh(&session->lock);
+-	old_stop_stage = conn->stop_stage;
+-	conn->stop_stage = flag;
+ 	conn->c_stage = ISCSI_CONN_STOPPED;
+ 	spin_unlock_bh(&session->lock);
+ 

commit cd4a8814d44672bd2c8f04a472121bfbe193809c
+Author: Mike Christie 
+Date:   Thu Feb 18 17:32:03 2010 -0600
+
+    [SCSI] scsi_dh_alua: add netapp to dev list
+    
+    Newer Netapp target software supports ALUA, so
+    this patch adds them to the scsi_dev_alua dev list.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
+index 4f0d0138f48b..ee372bf55332 100644
+--- a/drivers/scsi/device_handler/scsi_dh_alua.c
++++ b/drivers/scsi/device_handler/scsi_dh_alua.c
+@@ -717,6 +717,7 @@ static const struct scsi_dh_devlist alua_dev_list[] = {
+ 	{"IBM", "2145" },
+ 	{"Pillar", "Axiom" },
+ 	{"Intel", "Multi-Flex"},
++	{"NETAPP", "LUN"},
+ 	{NULL, NULL}
+ };
+ 

commit b3925514f6f6878e3f671fb6990874e731a26d02
+Author: Mike Christie 
+Date:   Wed Feb 10 16:51:48 2010 -0600
+
+    [SCSI] qla4xxx: fix compile warning due to invalid extHwConfig
+    
+    If the nvram is invalid qla4xxx tries to set Asuint32_t
+    based on the card type. If the card type is not listed
+    then Asuint32_t is going to be gargabe. This just fixes
+    that if/elseif by adding a else to catch the case for
+    new hardware that might not be listed yet.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
+index af8c3233e8ae..92329a461c68 100644
+--- a/drivers/scsi/qla4xxx/ql4_init.c
++++ b/drivers/scsi/qla4xxx/ql4_init.c
+@@ -844,10 +844,10 @@ static int qla4xxx_config_nvram(struct scsi_qla_host *ha)
+ 	DEBUG2(printk("scsi%ld: %s: Get EEProm parameters \n", ha->host_no,
+ 		      __func__));
+ 	if (ql4xxx_lock_flash(ha) != QLA_SUCCESS)
+-		return (QLA_ERROR);
++		return QLA_ERROR;
+ 	if (ql4xxx_lock_nvram(ha) != QLA_SUCCESS) {
+ 		ql4xxx_unlock_flash(ha);
+-		return (QLA_ERROR);
++		return QLA_ERROR;
+ 	}
+ 
+ 	/* Get EEPRom Parameters from NVRAM and validate */
+@@ -858,20 +858,18 @@ static int qla4xxx_config_nvram(struct scsi_qla_host *ha)
+ 			rd_nvram_word(ha, eeprom_ext_hw_conf_offset(ha));
+ 		spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ 	} else {
+-		/*
+-		 * QLogic adapters should always have a valid NVRAM.
+-		 * If not valid, do not load.
+-		 */
+ 		dev_warn(&ha->pdev->dev,
+ 			   "scsi%ld: %s: EEProm checksum invalid.  "
+ 			   "Please update your EEPROM\n", ha->host_no,
+ 			   __func__);
+ 
+-		/* set defaults */
++		/* Attempt to set defaults */
+ 		if (is_qla4010(ha))
+ 			extHwConfig.Asuint32_t = 0x1912;
+ 		else if (is_qla4022(ha) | is_qla4032(ha))
+ 			extHwConfig.Asuint32_t = 0x0023;
++		else
++			return QLA_ERROR;
+ 	}
+ 	DEBUG(printk("scsi%ld: %s: Setting extHwConfig to 0xFFFF%04x\n",
+ 		     ha->host_no, __func__, extHwConfig.Asuint32_t));
+@@ -884,7 +882,7 @@ static int qla4xxx_config_nvram(struct scsi_qla_host *ha)
+ 	ql4xxx_unlock_nvram(ha);
+ 	ql4xxx_unlock_flash(ha);
+ 
+-	return (QLA_SUCCESS);
++	return QLA_SUCCESS;
+ }
+ 
+ static void qla4x00_pci_config(struct scsi_qla_host *ha)

commit b64e77f70b8c11766e967e3485331a9e6ef01390
+Author: Mike Christie 
+Date:   Wed Feb 10 16:51:47 2010 -0600
+
+    [SCSI] iscsi_tcp: wake xmit thread when killing session
+    
+    If the connection is bad, then the xmit thread could
+    end up waiting a long time (up to sendtmeo seconds) in
+    tcp_sendpage. This patch has us set the sk_error and
+    wake up the xmit thread so we can quickly fail.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 517da3fd89d3..8a89ba900588 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -584,9 +584,10 @@ static void iscsi_sw_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
++	struct socket *sock = tcp_sw_conn->sock;
+ 
+ 	/* userspace may have goofed up and not bound us */
+-	if (!tcp_sw_conn->sock)
++	if (!sock)
+ 		return;
+ 	/*
+ 	 * Make sure our recv side is stopped.
+@@ -597,6 +598,11 @@ static void iscsi_sw_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+ 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
+ 	write_unlock_bh(&tcp_sw_conn->sock->sk->sk_callback_lock);
+ 
++	if (sock->sk->sk_sleep && waitqueue_active(sock->sk->sk_sleep)) {
++		sock->sk->sk_err = EIO;
++		wake_up_interruptible(sock->sk->sk_sleep);
++	}
++
+ 	iscsi_conn_stop(cls_conn, flag);
+ 	iscsi_sw_tcp_release_conn(conn);
+ }

commit 9f9127fd0cfac1ccbcf4a9456b3d36bc6971355e
+Author: Mike Christie 
+Date:   Wed Feb 10 16:51:46 2010 -0600
+
+    [SCSI] bnx2i: set change_queue_depth function
+    
+    No reason that we cannot set the change_queue_depth
+    function for bnx2i. We just forgot to when the
+    driver was created.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
+index 51709cb9a93e..1c4d1215769d 100644
+--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
++++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
+@@ -1990,6 +1990,7 @@ static struct scsi_host_template bnx2i_host_template = {
+ 	.eh_abort_handler	= iscsi_eh_abort,
+ 	.eh_device_reset_handler = iscsi_eh_device_reset,
+ 	.eh_target_reset_handler = iscsi_eh_target_reset,
++	.change_queue_depth	= iscsi_change_queue_depth,
+ 	.can_queue		= 1024,
+ 	.max_sectors		= 127,
+ 	.cmd_per_lun		= 32,

commit 92ed4d69934a1281abcc10c6a82274a04651a260
+Author: Mike Christie 
+Date:   Wed Feb 10 16:51:45 2010 -0600
+
+    [SCSI] libiscsi: reset cmd timer if cmds are making progress
+    
+    This patch resets the cmd timer if cmds started before
+    the timedout command are making progress. The idea is
+    that the cmd probably timed out because we are trying
+    to exeucte too many commands. If it turns out that the
+    device the IO timedout on was bad or the cmd just got
+    screwed up but other IO/devs were ok then we will
+    will figure this out when the cmds ahead of the timed
+    out one complete ok.
+    
+    This also fixes a bug where we were sort of detecting
+    this by setting the last_timeout and last_xfer to the
+    same value when the task was allocated. That caught
+    the case where we never got to send any IO for it. However,
+    if the problem had started right before we started the
+    new task, then we were forced to wait an extra cmd
+    timeout seconds to start the scsi eh.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index c28a712fd4db..703eb6a88790 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1919,10 +1919,11 @@ static int iscsi_has_ping_timed_out(struct iscsi_conn *conn)
+ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
+ {
+ 	enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED;
+-	struct iscsi_task *task = NULL;
++	struct iscsi_task *task = NULL, *running_task;
+ 	struct iscsi_cls_session *cls_session;
+ 	struct iscsi_session *session;
+ 	struct iscsi_conn *conn;
++	int i;
+ 
+ 	cls_session = starget_to_session(scsi_target(sc->device));
+ 	session = cls_session->dd_data;
+@@ -1947,8 +1948,15 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
+ 	}
+ 
+ 	task = (struct iscsi_task *)sc->SCp.ptr;
+-	if (!task)
++	if (!task) {
++		/*
++		 * Raced with completion. Just reset timer, and let it
++		 * complete normally
++		 */
++		rc = BLK_EH_RESET_TIMER;
+ 		goto done;
++	}
++
+ 	/*
+ 	 * If we have sent (at least queued to the network layer) a pdu or
+ 	 * recvd one for the task since the last timeout ask for
+@@ -1956,10 +1964,10 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
+ 	 * we can check if it is the task or connection when we send the
+ 	 * nop as a ping.
+ 	 */
+-	if (time_after_eq(task->last_xfer, task->last_timeout)) {
++	if (time_after(task->last_xfer, task->last_timeout)) {
+ 		ISCSI_DBG_EH(session, "Command making progress. Asking "
+ 			     "scsi-ml for more time to complete. "
+-			     "Last data recv at %lu. Last timeout was at "
++			     "Last data xfer at %lu. Last timeout was at "
+ 			     "%lu\n.", task->last_xfer, task->last_timeout);
+ 		task->have_checked_conn = false;
+ 		rc = BLK_EH_RESET_TIMER;
+@@ -1977,6 +1985,43 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
+ 		goto done;
+ 	}
+ 
++	for (i = 0; i < conn->session->cmds_max; i++) {
++		running_task = conn->session->cmds[i];
++		if (!running_task->sc || running_task == task ||
++		     running_task->state != ISCSI_TASK_RUNNING)
++			continue;
++
++		/*
++		 * Only check if cmds started before this one have made
++		 * progress, or this could never fail
++		 */
++		if (time_after(running_task->sc->jiffies_at_alloc,
++			       task->sc->jiffies_at_alloc))
++			continue;
++
++		if (time_after(running_task->last_xfer, task->last_timeout)) {
++			/*
++			 * This task has not made progress, but a task
++			 * started before us has transferred data since
++			 * we started/last-checked. We could be queueing
++			 * too many tasks or the LU is bad.
++			 *
++			 * If the device is bad the cmds ahead of us on
++			 * other devs will complete, and this loop will
++			 * eventually fail starting the scsi eh.
++			 */
++			ISCSI_DBG_EH(session, "Command has not made progress "
++				     "but commands ahead of it have. "
++				     "Asking scsi-ml for more time to "
++				     "complete. Our last xfer vs running task "
++				     "last xfer %lu/%lu. Last check %lu.\n",
++				     task->last_xfer, running_task->last_xfer,
++				     task->last_timeout);
++			rc = BLK_EH_RESET_TIMER;
++			goto done;
++		}
++	}
++
+ 	/* Assumes nop timeout is shorter than scsi cmd timeout */
+ 	if (task->have_checked_conn)
+ 		goto done;

commit 9010b94636312c7fb12b591ef09e915f8f80bbd5
+Author: Mike Christie 
+Date:   Wed Feb 10 16:51:44 2010 -0600
+
+    [SCSI] cxgb3i: check for setup netdev
+    
+    If the netdev has not been setup when the host is, we will oops when
+    the iscsi layer calls into the driver and a it tries to reference the
+    netdev in hba->ndev.
+    
+    This can happen if the iscsi driver is loaded before ifup is
+    done. This patch just adds a check, so we can gracefully fail the
+    operation.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+index 1fd89b229c87..412853c65372 100644
+--- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
++++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+@@ -708,6 +708,12 @@ static int cxgb3i_host_set_param(struct Scsi_Host *shost,
+ {
+ 	struct cxgb3i_hba *hba = iscsi_host_priv(shost);
+ 
++	if (!hba->ndev) {
++		shost_printk(KERN_ERR, shost, "Could not set host param. "
++			     "Netdev for host not set.\n");
++		return -ENODEV;
++	}
++
+ 	cxgb3i_api_debug("param %d, buf %s.\n", param, buf);
+ 
+ 	switch (param) {
+@@ -738,6 +744,12 @@ static int cxgb3i_host_get_param(struct Scsi_Host *shost,
+ 	struct cxgb3i_hba *hba = iscsi_host_priv(shost);
+ 	int len = 0;
+ 
++	if (!hba->ndev) {
++		shost_printk(KERN_ERR, shost, "Could not set host param. "
++			     "Netdev for host not set.\n");
++		return -ENODEV;
++	}
++
+ 	cxgb3i_api_debug("hba %s, param %d.\n", hba->ndev->name, param);
+ 
+ 	switch (param) {

commit fee099b278894a1c7383a08cb3c62a5b62a134e8
+Author: Mike Christie 
+Date:   Tue Jan 12 22:48:00 2010 -0600
+
+    [SCSI] iscsi_tcp regression: remove bogus warn on in write path
+    
+    An empty r2tqueue is a valid state. It just means that we have
+    processed all that there was to do. This patch removes the WARN_ON
+    that was added when the kfifo changes were merged.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
+index db6856c138fc..4ad87fd74ddd 100644
+--- a/drivers/scsi/libiscsi_tcp.c
++++ b/drivers/scsi/libiscsi_tcp.c
+@@ -992,12 +992,10 @@ static struct iscsi_r2t_info *iscsi_tcp_get_curr_r2t(struct iscsi_task *task)
+ 		if (r2t == NULL) {
+ 			if (kfifo_out(&tcp_task->r2tqueue,
+ 			    (void *)&tcp_task->r2t, sizeof(void *)) !=
+-			    sizeof(void *)) {
+-				WARN_ONCE(1, "unexpected fifo state");
++			    sizeof(void *))
+ 				r2t = NULL;
+-			}
+-
+-			r2t = tcp_task->r2t;
++			else
++				r2t = tcp_task->r2t;
+ 		}
+ 		spin_unlock_bh(&session->lock);
+ 	}

commit 48de68a40aef032a2e198437f4781a83bfb938db
+Author: Mike Christie 
+Date:   Tue Nov 17 21:25:16 2009 -0600
+
+    [SCSI] fc class: fix fc_transport_init error handling
+    
+    If transport_class_register fails we should unregister any
+    registered classes, or we will leak memory or other
+    resources.
+    
+    I did a quick modprobe of scsi_transport_fc to test the
+    patch.
+    
+    Signed-off-by: Mike Christie 
+    Cc: Stable Tree 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
+index 6531c91501be..ddfcecd5099f 100644
+--- a/drivers/scsi/scsi_transport_fc.c
++++ b/drivers/scsi/scsi_transport_fc.c
+@@ -649,11 +649,22 @@ static __init int fc_transport_init(void)
+ 		return error;
+ 	error = transport_class_register(&fc_vport_class);
+ 	if (error)
+-		return error;
++		goto unreg_host_class;
+ 	error = transport_class_register(&fc_rport_class);
+ 	if (error)
+-		return error;
+-	return transport_class_register(&fc_transport_class);
++		goto unreg_vport_class;
++	error = transport_class_register(&fc_transport_class);
++	if (error)
++		goto unreg_rport_class;
++	return 0;
++
++unreg_rport_class:
++	transport_class_unregister(&fc_rport_class);
++unreg_vport_class:
++	transport_class_unregister(&fc_vport_class);
++unreg_host_class:
++	transport_class_unregister(&fc_host_class);
++	return error;
+ }
+ 
+ static void __exit fc_transport_exit(void)

commit 1796e72291b2b6aafaec5954e666d0b5a95da935
+Author: Mike Christie 
+Date:   Wed Nov 11 16:34:36 2009 -0600
+
+    [SCSI] libiscsi: hook into ramp up/down handling
+    
+    It is rare to get a queue full with iscsi, because targets seem to
+    just reduce the iscsi cmd window. However, there is at least
+    one iscsi target that will throw a queue full when overloaded.
+    This hooks the iscsi code in to the ramp up/down code, so we
+    can handle it.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 07ec997c5d4f..b7689f3d05f5 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1739,10 +1739,19 @@ EXPORT_SYMBOL_GPL(iscsi_queuecommand);
+ 
+ int iscsi_change_queue_depth(struct scsi_device *sdev, int depth, int reason)
+ {
+-	if (reason != SCSI_QDEPTH_DEFAULT)
++	switch (reason) {
++	case SCSI_QDEPTH_DEFAULT:
++		scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
++		break;
++	case SCSI_QDEPTH_QFULL:
++		scsi_track_queue_full(sdev, depth);
++		break;
++	case SCSI_QDEPTH_RAMP_UP:
++		scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
++		break;
++	default:
+ 		return -EOPNOTSUPP;
+-
+-	scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
++	}
+ 	return sdev->queue_depth;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_change_queue_depth);

commit b20d038dff877566694181578c49c31616d622cd
+Author: Mike Christie 
+Date:   Wed Nov 11 16:34:35 2009 -0600
+
+    [SCSI] iser: set tgt and lu reset timeout
+    
+    When iser enabled lu reset support it did not set the
+    bit to allow userspace to get/set the timeout. This
+    sets the tgt and lu reset timeout bits.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index add9188663ff..5f7a6fca0a4d 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -625,6 +625,7 @@ static struct iscsi_transport iscsi_iser_transport = {
+ 				  ISCSI_USERNAME | ISCSI_PASSWORD |
+ 				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+ 				  ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
++				  ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
+ 				  ISCSI_PING_TMO | ISCSI_RECV_TMO |
+ 				  ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS |

commit fdd46dcbe4468a1f47a2cc9be442d11c3d21dd68
+Author: Mike Christie 
+Date:   Wed Nov 11 16:34:34 2009 -0600
+
+    [SCSI] iscsi class: modify handling of replacement timeout
+    
+    This patch modifies the replacement/recovery_timeout so it works
+    more like the fc fast io fail tmo.
+    
+    If userspace tries to set the replacement/recovery_timeout to less than
+    zero, we will turn off the forced recovery cleanup.
+    
+    If userspace sets the value to 0 then we will force the recovery
+    cleanup immediately.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index dc04ca124a69..ea3892e7e0f7 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -627,8 +627,10 @@ static void __iscsi_block_session(struct work_struct *work)
+ 	spin_unlock_irqrestore(&session->lock, flags);
+ 	scsi_target_block(&session->dev);
+ 	ISCSI_DBG_TRANS_SESSION(session, "Completed SCSI target blocking\n");
+-	queue_delayed_work(iscsi_eh_timer_workq, &session->recovery_work,
+-			   session->recovery_tmo * HZ);
++	if (session->recovery_tmo >= 0)
++		queue_delayed_work(iscsi_eh_timer_workq,
++				   &session->recovery_work,
++				   session->recovery_tmo * HZ);
+ }
+ 
+ void iscsi_block_session(struct iscsi_cls_session *session)
+@@ -1348,8 +1350,7 @@ iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+ 	switch (ev->u.set_param.param) {
+ 	case ISCSI_PARAM_SESS_RECOVERY_TMO:
+ 		sscanf(data, "%d", &value);
+-		if (value != 0)
+-			session->recovery_tmo = value;
++		session->recovery_tmo = value;
+ 		break;
+ 	default:
+ 		err = transport->set_param(conn, ev->u.set_param.param,

commit 3fe5ae8b4c4d3a82c755074878da7ddb9dde381e
+Author: Mike Christie 
+Date:   Wed Nov 11 16:34:33 2009 -0600
+
+    [SCSI] libiscsi: add warm target reset tmf support
+    
+    This implements warm target reset tmf support for
+    the scsi-ml target reset callback. Previously we would
+    just drop the session in that callback. This patch will
+    now try a target reset and if that fails drop the session.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
+index d15df07ba783..1a557fa77888 100644
+--- a/drivers/scsi/be2iscsi/be_main.c
++++ b/drivers/scsi/be2iscsi/be_main.c
+@@ -3859,7 +3859,7 @@ struct iscsi_transport beiscsi_iscsi_transport = {
+ 		ISCSI_USERNAME | ISCSI_PASSWORD |
+ 		ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+ 		ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+-		ISCSI_LU_RESET_TMO |
++		ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
+ 		ISCSI_PING_TMO | ISCSI_RECV_TMO |
+ 		ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
+ 	.host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
+index 89e84c302aa0..070118a8f184 100644
+--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
++++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
+@@ -2028,7 +2028,7 @@ struct iscsi_transport bnx2i_iscsi_transport = {
+ 				  ISCSI_USERNAME | ISCSI_PASSWORD |
+ 				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+ 				  ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+-				  ISCSI_LU_RESET_TMO |
++				  ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
+ 				  ISCSI_PING_TMO | ISCSI_RECV_TMO |
+ 				  ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_NETDEV_NAME,
+diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+index 2631bddd255e..969c83162cc4 100644
+--- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
++++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+@@ -937,7 +937,7 @@ static struct iscsi_transport cxgb3i_iscsi_transport = {
+ 				ISCSI_USERNAME | ISCSI_PASSWORD |
+ 				ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+ 				ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+-				ISCSI_LU_RESET_TMO |
++				ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
+ 				ISCSI_PING_TMO | ISCSI_RECV_TMO |
+ 				ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index edc49ca49cea..517da3fd89d3 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -903,7 +903,7 @@ static struct iscsi_transport iscsi_sw_tcp_transport = {
+ 				  ISCSI_USERNAME | ISCSI_PASSWORD |
+ 				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+ 				  ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+-				  ISCSI_LU_RESET_TMO |
++				  ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
+ 				  ISCSI_PING_TMO | ISCSI_RECV_TMO |
+ 				  ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index b6ffdc5512cd..07ec997c5d4f 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -298,17 +298,18 @@ static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode)
+ 		hdr_lun = scsilun_to_int((struct scsi_lun *)tmf->lun);
+ 		if (hdr_lun != task->sc->device->lun)
+ 			return 0;
+-
++		/* fall through */
++	case ISCSI_TM_FUNC_TARGET_WARM_RESET:
+ 		/*
+ 		 * Fail all SCSI cmd PDUs
+ 		 */
+ 		if (opcode != ISCSI_OP_SCSI_DATA_OUT) {
+ 			iscsi_conn_printk(KERN_INFO, conn,
+ 					  "task [op %x/%x itt "
+-					  "0x%x/0x%x lun %u] "
++					  "0x%x/0x%x] "
+ 					  "rejected.\n",
+ 					  task->hdr->opcode, opcode,
+-					  task->itt, task->hdr_itt, hdr_lun);
++					  task->itt, task->hdr_itt);
+ 			return -EACCES;
+ 		}
+ 		/*
+@@ -318,10 +319,9 @@ static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode)
+ 		if (conn->session->fast_abort) {
+ 			iscsi_conn_printk(KERN_INFO, conn,
+ 					  "task [op %x/%x itt "
+-					  "0x%x/0x%x lun %u] "
+-					  "fast abort.\n",
++					  "0x%x/0x%x] fast abort.\n",
+ 					  task->hdr->opcode, opcode,
+-					  task->itt, task->hdr_itt, hdr_lun);
++					  task->itt, task->hdr_itt);
+ 			return -EACCES;
+ 		}
+ 		break;
+@@ -1757,72 +1757,6 @@ int iscsi_target_alloc(struct scsi_target *starget)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_target_alloc);
+ 
+-void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session)
+-{
+-	struct iscsi_session *session = cls_session->dd_data;
+-
+-	spin_lock_bh(&session->lock);
+-	if (session->state != ISCSI_STATE_LOGGED_IN) {
+-		session->state = ISCSI_STATE_RECOVERY_FAILED;
+-		if (session->leadconn)
+-			wake_up(&session->leadconn->ehwait);
+-	}
+-	spin_unlock_bh(&session->lock);
+-}
+-EXPORT_SYMBOL_GPL(iscsi_session_recovery_timedout);
+-
+-int iscsi_eh_target_reset(struct scsi_cmnd *sc)
+-{
+-	struct iscsi_cls_session *cls_session;
+-	struct iscsi_session *session;
+-	struct iscsi_conn *conn;
+-
+-	cls_session = starget_to_session(scsi_target(sc->device));
+-	session = cls_session->dd_data;
+-	conn = session->leadconn;
+-
+-	mutex_lock(&session->eh_mutex);
+-	spin_lock_bh(&session->lock);
+-	if (session->state == ISCSI_STATE_TERMINATE) {
+-failed:
+-		ISCSI_DBG_EH(session,
+-			     "failing target reset: Could not log back into "
+-			     "target [age %d]\n",
+-			     session->age);
+-		spin_unlock_bh(&session->lock);
+-		mutex_unlock(&session->eh_mutex);
+-		return FAILED;
+-	}
+-
+-	spin_unlock_bh(&session->lock);
+-	mutex_unlock(&session->eh_mutex);
+-	/*
+-	 * we drop the lock here but the leadconn cannot be destoyed while
+-	 * we are in the scsi eh
+-	 */
+-	iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+-
+-	ISCSI_DBG_EH(session, "wait for relogin\n");
+-	wait_event_interruptible(conn->ehwait,
+-				 session->state == ISCSI_STATE_TERMINATE ||
+-				 session->state == ISCSI_STATE_LOGGED_IN ||
+-				 session->state == ISCSI_STATE_RECOVERY_FAILED);
+-	if (signal_pending(current))
+-		flush_signals(current);
+-
+-	mutex_lock(&session->eh_mutex);
+-	spin_lock_bh(&session->lock);
+-	if (session->state == ISCSI_STATE_LOGGED_IN) {
+-		ISCSI_DBG_EH(session,
+-			     "target reset succeeded\n");
+-	} else
+-		goto failed;
+-	spin_unlock_bh(&session->lock);
+-	mutex_unlock(&session->eh_mutex);
+-	return SUCCESS;
+-}
+-EXPORT_SYMBOL_GPL(iscsi_eh_target_reset);
+-
+ static void iscsi_tmf_timedout(unsigned long data)
+ {
+ 	struct iscsi_conn *conn = (struct iscsi_conn *)data;
+@@ -2329,6 +2263,172 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_eh_device_reset);
+ 
++void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session)
++{
++	struct iscsi_session *session = cls_session->dd_data;
++
++	spin_lock_bh(&session->lock);
++	if (session->state != ISCSI_STATE_LOGGED_IN) {
++		session->state = ISCSI_STATE_RECOVERY_FAILED;
++		if (session->leadconn)
++			wake_up(&session->leadconn->ehwait);
++	}
++	spin_unlock_bh(&session->lock);
++}
++EXPORT_SYMBOL_GPL(iscsi_session_recovery_timedout);
++
++/**
++ * iscsi_eh_session_reset - drop session and attempt relogin
++ * @sc: scsi command
++ *
++ * This function will wait for a relogin, session termination from
++ * userspace, or a recovery/replacement timeout.
++ */
++static int iscsi_eh_session_reset(struct scsi_cmnd *sc)
++{
++	struct iscsi_cls_session *cls_session;
++	struct iscsi_session *session;
++	struct iscsi_conn *conn;
++
++	cls_session = starget_to_session(scsi_target(sc->device));
++	session = cls_session->dd_data;
++	conn = session->leadconn;
++
++	mutex_lock(&session->eh_mutex);
++	spin_lock_bh(&session->lock);
++	if (session->state == ISCSI_STATE_TERMINATE) {
++failed:
++		ISCSI_DBG_EH(session,
++			     "failing session reset: Could not log back into "
++			     "%s, %s [age %d]\n", session->targetname,
++			     conn->persistent_address, session->age);
++		spin_unlock_bh(&session->lock);
++		mutex_unlock(&session->eh_mutex);
++		return FAILED;
++	}
++
++	spin_unlock_bh(&session->lock);
++	mutex_unlock(&session->eh_mutex);
++	/*
++	 * we drop the lock here but the leadconn cannot be destoyed while
++	 * we are in the scsi eh
++	 */
++	iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
++
++	ISCSI_DBG_EH(session, "wait for relogin\n");
++	wait_event_interruptible(conn->ehwait,
++				 session->state == ISCSI_STATE_TERMINATE ||
++				 session->state == ISCSI_STATE_LOGGED_IN ||
++				 session->state == ISCSI_STATE_RECOVERY_FAILED);
++	if (signal_pending(current))
++		flush_signals(current);
++
++	mutex_lock(&session->eh_mutex);
++	spin_lock_bh(&session->lock);
++	if (session->state == ISCSI_STATE_LOGGED_IN) {
++		ISCSI_DBG_EH(session,
++			     "session reset succeeded for %s,%s\n",
++			     session->targetname, conn->persistent_address);
++	} else
++		goto failed;
++	spin_unlock_bh(&session->lock);
++	mutex_unlock(&session->eh_mutex);
++	return SUCCESS;
++}
++
++static void iscsi_prep_tgt_reset_pdu(struct scsi_cmnd *sc, struct iscsi_tm *hdr)
++{
++	memset(hdr, 0, sizeof(*hdr));
++	hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE;
++	hdr->flags = ISCSI_TM_FUNC_TARGET_WARM_RESET & ISCSI_FLAG_TM_FUNC_MASK;
++	hdr->flags |= ISCSI_FLAG_CMD_FINAL;
++	hdr->rtt = RESERVED_ITT;
++}
++
++/**
++ * iscsi_eh_target_reset - reset target
++ * @sc: scsi command
++ *
++ * This will attempt to send a warm target reset. If that fails
++ * then we will drop the session and attempt ERL0 recovery.
++ */
++int iscsi_eh_target_reset(struct scsi_cmnd *sc)
++{
++	struct iscsi_cls_session *cls_session;
++	struct iscsi_session *session;
++	struct iscsi_conn *conn;
++	struct iscsi_tm *hdr;
++	int rc = FAILED;
++
++	cls_session = starget_to_session(scsi_target(sc->device));
++	session = cls_session->dd_data;
++
++	ISCSI_DBG_EH(session, "tgt Reset [sc %p tgt %s]\n", sc,
++		     session->targetname);
++
++	mutex_lock(&session->eh_mutex);
++	spin_lock_bh(&session->lock);
++	/*
++	 * Just check if we are not logged in. We cannot check for
++	 * the phase because the reset could come from a ioctl.
++	 */
++	if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN)
++		goto unlock;
++	conn = session->leadconn;
++
++	/* only have one tmf outstanding at a time */
++	if (conn->tmf_state != TMF_INITIAL)
++		goto unlock;
++	conn->tmf_state = TMF_QUEUED;
++
++	hdr = &conn->tmhdr;
++	iscsi_prep_tgt_reset_pdu(sc, hdr);
++
++	if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age,
++				    session->tgt_reset_timeout)) {
++		rc = FAILED;
++		goto unlock;
++	}
++
++	switch (conn->tmf_state) {
++	case TMF_SUCCESS:
++		break;
++	case TMF_TIMEDOUT:
++		spin_unlock_bh(&session->lock);
++		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
++		goto done;
++	default:
++		conn->tmf_state = TMF_INITIAL;
++		goto unlock;
++	}
++
++	rc = SUCCESS;
++	spin_unlock_bh(&session->lock);
++
++	iscsi_suspend_tx(conn);
++
++	spin_lock_bh(&session->lock);
++	memset(hdr, 0, sizeof(*hdr));
++	fail_scsi_tasks(conn, -1, DID_ERROR);
++	conn->tmf_state = TMF_INITIAL;
++	spin_unlock_bh(&session->lock);
++
++	iscsi_start_tx(conn);
++	goto done;
++
++unlock:
++	spin_unlock_bh(&session->lock);
++done:
++	ISCSI_DBG_EH(session, "tgt %s reset result = %s\n", session->targetname,
++		     rc == SUCCESS ? "SUCCESS" : "FAILED");
++	mutex_unlock(&session->eh_mutex);
++
++	if (rc == FAILED)
++		rc = iscsi_eh_session_reset(sc);
++	return rc;
++}
++EXPORT_SYMBOL_GPL(iscsi_eh_target_reset);
++
+ /*
+  * Pre-allocate a pool of @max items of @item_size. By default, the pool
+  * should be accessed via kfifo_{get,put} on q->queue.
+@@ -2595,6 +2695,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
+ 	session->host = shost;
+ 	session->state = ISCSI_STATE_FREE;
+ 	session->fast_abort = 1;
++	session->tgt_reset_timeout = 30;
+ 	session->lu_reset_timeout = 15;
+ 	session->abort_timeout = 10;
+ 	session->scsi_cmds_max = scsi_cmds;
+@@ -3033,6 +3134,9 @@ int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
+ 	case ISCSI_PARAM_LU_RESET_TMO:
+ 		sscanf(buf, "%d", &session->lu_reset_timeout);
+ 		break;
++	case ISCSI_PARAM_TGT_RESET_TMO:
++		sscanf(buf, "%d", &session->tgt_reset_timeout);
++		break;
+ 	case ISCSI_PARAM_PING_TMO:
+ 		sscanf(buf, "%d", &conn->ping_timeout);
+ 		break;
+@@ -3132,6 +3236,9 @@ int iscsi_session_get_param(struct iscsi_cls_session *cls_session,
+ 	case ISCSI_PARAM_LU_RESET_TMO:
+ 		len = sprintf(buf, "%d\n", session->lu_reset_timeout);
+ 		break;
++	case ISCSI_PARAM_TGT_RESET_TMO:
++		len = sprintf(buf, "%d\n", session->tgt_reset_timeout);
++		break;
+ 	case ISCSI_PARAM_INITIAL_R2T_EN:
+ 		len = sprintf(buf, "%d\n", session->initial_r2t_en);
+ 		break;
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index ad897df36615..dc04ca124a69 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -30,7 +30,7 @@
+ #include 
+ #include 
+ 
+-#define ISCSI_SESSION_ATTRS 21
++#define ISCSI_SESSION_ATTRS 22
+ #define ISCSI_CONN_ATTRS 13
+ #define ISCSI_HOST_ATTRS 4
+ 
+@@ -1759,6 +1759,7 @@ iscsi_session_attr(password_in, ISCSI_PARAM_PASSWORD_IN, 1);
+ iscsi_session_attr(fast_abort, ISCSI_PARAM_FAST_ABORT, 0);
+ iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0);
+ iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 0);
++iscsi_session_attr(tgt_reset_tmo, ISCSI_PARAM_TGT_RESET_TMO, 0);
+ iscsi_session_attr(ifacename, ISCSI_PARAM_IFACE_NAME, 0);
+ iscsi_session_attr(initiatorname, ISCSI_PARAM_INITIATOR_NAME, 0)
+ 
+@@ -2000,6 +2001,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 	SETUP_SESSION_RD_ATTR(fast_abort, ISCSI_FAST_ABORT);
+ 	SETUP_SESSION_RD_ATTR(abort_tmo, ISCSI_ABORT_TMO);
+ 	SETUP_SESSION_RD_ATTR(lu_reset_tmo,ISCSI_LU_RESET_TMO);
++	SETUP_SESSION_RD_ATTR(tgt_reset_tmo,ISCSI_TGT_RESET_TMO);
+ 	SETUP_SESSION_RD_ATTR(ifacename, ISCSI_IFACE_NAME);
+ 	SETUP_SESSION_RD_ATTR(initiatorname, ISCSI_INITIATOR_NAME);
+ 	SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo);
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index d67dda2b6aa0..66d377b9c72b 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -311,6 +311,8 @@ enum iscsi_param {
+ 	ISCSI_PARAM_IFACE_NAME,
+ 	ISCSI_PARAM_ISID,
+ 	ISCSI_PARAM_INITIATOR_NAME,
++
++	ISCSI_PARAM_TGT_RESET_TMO,
+ 	/* must always be last */
+ 	ISCSI_PARAM_MAX,
+ };
+@@ -350,6 +352,7 @@ enum iscsi_param {
+ #define ISCSI_IFACE_NAME		(1ULL << ISCSI_PARAM_IFACE_NAME)
+ #define ISCSI_ISID			(1ULL << ISCSI_PARAM_ISID)
+ #define ISCSI_INITIATOR_NAME		(1ULL << ISCSI_PARAM_INITIATOR_NAME)
++#define ISCSI_TGT_RESET_TMO		(1ULL << ISCSI_PARAM_TGT_RESET_TMO)
+ 
+ /* iSCSI HBA params */
+ enum iscsi_host_param {
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 2db2bc26b1e9..7394e3bc8f4b 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -267,6 +267,7 @@ struct iscsi_session {
+ 	/* configuration */
+ 	int			abort_timeout;
+ 	int			lu_reset_timeout;
++	int			tgt_reset_timeout;
+ 	int			initial_r2t_en;
+ 	unsigned		max_r2t;
+ 	int			imm_data_en;

commit 5d12c05e29fc8715e3e32f57a8cced9290d87c55
+Author: Mike Christie 
+Date:   Wed Nov 11 16:34:32 2009 -0600
+
+    [SCSI] libiscsi: Check TMF state before sending PDU
+    
+    Patch and mail from both MikeC and HannesR:
+    
+    Before we're trying to send a PDU we have to check whether a TMF
+    is active. If so and if the PDU will be affected by the TMF
+    we should allow only Data-out PDUs to be sent.
+    
+    If fast_abort is set, no Data-out PDUs will be sent while
+    a LUN reset is being processed for a affected LUN.
+    
+    fast_abort is now ingored during a ABORT TASK tmf. We will not
+    send any Data-outs for a task if the task is being aborted.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Hannes Reinecke 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 8c29480fc02b..b6ffdc5512cd 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -265,6 +265,88 @@ static int iscsi_prep_bidi_ahs(struct iscsi_task *task)
+ 	return 0;
+ }
+ 
++/**
++ * iscsi_check_tmf_restrictions - check if a task is affected by TMF
++ * @task: iscsi task
++ * @opcode: opcode to check for
++ *
++ * During TMF a task has to be checked if it's affected.
++ * All unrelated I/O can be passed through, but I/O to the
++ * affected LUN should be restricted.
++ * If 'fast_abort' is set we won't be sending any I/O to the
++ * affected LUN.
++ * Otherwise the target is waiting for all TTTs to be completed,
++ * so we have to send all outstanding Data-Out PDUs to the target.
++ */
++static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode)
++{
++	struct iscsi_conn *conn = task->conn;
++	struct iscsi_tm *tmf = &conn->tmhdr;
++	unsigned int hdr_lun;
++
++	if (conn->tmf_state == TMF_INITIAL)
++		return 0;
++
++	if ((tmf->opcode & ISCSI_OPCODE_MASK) != ISCSI_OP_SCSI_TMFUNC)
++		return 0;
++
++	switch (ISCSI_TM_FUNC_VALUE(tmf)) {
++	case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET:
++		/*
++		 * Allow PDUs for unrelated LUNs
++		 */
++		hdr_lun = scsilun_to_int((struct scsi_lun *)tmf->lun);
++		if (hdr_lun != task->sc->device->lun)
++			return 0;
++
++		/*
++		 * Fail all SCSI cmd PDUs
++		 */
++		if (opcode != ISCSI_OP_SCSI_DATA_OUT) {
++			iscsi_conn_printk(KERN_INFO, conn,
++					  "task [op %x/%x itt "
++					  "0x%x/0x%x lun %u] "
++					  "rejected.\n",
++					  task->hdr->opcode, opcode,
++					  task->itt, task->hdr_itt, hdr_lun);
++			return -EACCES;
++		}
++		/*
++		 * And also all data-out PDUs in response to R2T
++		 * if fast_abort is set.
++		 */
++		if (conn->session->fast_abort) {
++			iscsi_conn_printk(KERN_INFO, conn,
++					  "task [op %x/%x itt "
++					  "0x%x/0x%x lun %u] "
++					  "fast abort.\n",
++					  task->hdr->opcode, opcode,
++					  task->itt, task->hdr_itt, hdr_lun);
++			return -EACCES;
++		}
++		break;
++	case ISCSI_TM_FUNC_ABORT_TASK:
++		/*
++		 * the caller has already checked if the task
++		 * they want to abort was in the pending queue so if
++		 * we are here the cmd pdu has gone out already, and
++		 * we will only hit this for data-outs
++		 */
++		if (opcode == ISCSI_OP_SCSI_DATA_OUT &&
++		    task->hdr_itt == tmf->rtt) {
++			ISCSI_DBG_SESSION(conn->session,
++					  "Preventing task %x/%x from sending "
++					  "data-out due to abort task in "
++					  "progress\n", task->itt,
++					  task->hdr_itt);
++			return -EACCES;
++		}
++		break;
++	}
++
++	return 0;
++}
++
+ /**
+  * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu
+  * @task: iscsi task
+@@ -282,6 +364,10 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
+ 	itt_t itt;
+ 	int rc;
+ 
++	rc = iscsi_check_tmf_restrictions(task, ISCSI_OP_SCSI_CMD);
++	if (rc)
++		return rc;
++
+ 	if (conn->session->tt->alloc_pdu) {
+ 		rc = conn->session->tt->alloc_pdu(task, ISCSI_OP_SCSI_CMD);
+ 		if (rc)
+@@ -1366,6 +1452,7 @@ EXPORT_SYMBOL_GPL(iscsi_requeue_task);
+  **/
+ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ {
++	struct iscsi_task *task;
+ 	int rc = 0;
+ 
+ 	spin_lock_bh(&conn->session->lock);
+@@ -1403,11 +1490,8 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 
+ 	/* process pending command queue */
+ 	while (!list_empty(&conn->cmdqueue)) {
+-		if (conn->tmf_state == TMF_QUEUED)
+-			break;
+-
+-		conn->task = list_entry(conn->cmdqueue.next,
+-					 struct iscsi_task, running);
++		conn->task = list_entry(conn->cmdqueue.next, struct iscsi_task,
++					running);
+ 		list_del_init(&conn->task->running);
+ 		if (conn->session->state == ISCSI_STATE_LOGGING_OUT) {
+ 			fail_scsi_task(conn->task, DID_IMM_RETRY);
+@@ -1415,7 +1499,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 		}
+ 		rc = iscsi_prep_scsi_cmd_pdu(conn->task);
+ 		if (rc) {
+-			if (rc == -ENOMEM) {
++			if (rc == -ENOMEM || rc == -EACCES) {
+ 				list_add_tail(&conn->task->running,
+ 					      &conn->cmdqueue);
+ 				conn->task = NULL;
+@@ -1437,17 +1521,18 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 	}
+ 
+ 	while (!list_empty(&conn->requeue)) {
+-		if (conn->session->fast_abort && conn->tmf_state != TMF_INITIAL)
+-			break;
+-
+ 		/*
+ 		 * we always do fastlogout - conn stop code will clean up.
+ 		 */
+ 		if (conn->session->state == ISCSI_STATE_LOGGING_OUT)
+ 			break;
+ 
+-		conn->task = list_entry(conn->requeue.next,
+-					 struct iscsi_task, running);
++		task = list_entry(conn->requeue.next, struct iscsi_task,
++				  running);
++		if (iscsi_check_tmf_restrictions(task, ISCSI_OP_SCSI_DATA_OUT))
++			break;
++
++		conn->task = task;
+ 		list_del_init(&conn->task->running);
+ 		conn->task->state = ISCSI_TASK_RUNNING;
+ 		rc = iscsi_xmit_task(conn);
+@@ -1600,7 +1685,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 	if (!ihost->workq) {
+ 		reason = iscsi_prep_scsi_cmd_pdu(task);
+ 		if (reason) {
+-			if (reason == -ENOMEM) {
++			if (reason == -ENOMEM ||  reason == -EACCES) {
+ 				reason = FAILURE_OOM;
+ 				goto prepd_reject;
+ 			} else {
+@@ -2120,6 +2205,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 		spin_lock_bh(&session->lock);
+ 		fail_scsi_task(task, DID_ABORT);
+ 		conn->tmf_state = TMF_INITIAL;
++		memset(hdr, 0, sizeof(*hdr));
+ 		spin_unlock_bh(&session->lock);
+ 		iscsi_start_tx(conn);
+ 		goto success_unlocked;
+@@ -2130,6 +2216,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 	case TMF_NOT_FOUND:
+ 		if (!sc->SCp.ptr) {
+ 			conn->tmf_state = TMF_INITIAL;
++			memset(hdr, 0, sizeof(*hdr));
+ 			/* task completed before tmf abort response */
+ 			ISCSI_DBG_EH(session, "sc completed while abort	in "
+ 					      "progress\n");
+@@ -2224,6 +2311,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc)
+ 	iscsi_suspend_tx(conn);
+ 
+ 	spin_lock_bh(&session->lock);
++	memset(hdr, 0, sizeof(*hdr));
+ 	fail_scsi_tasks(conn, sc->device->lun, DID_ERROR);
+ 	conn->tmf_state = TMF_INITIAL;
+ 	spin_unlock_bh(&session->lock);
+@@ -2868,6 +2956,7 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ 	spin_lock_bh(&session->lock);
+ 	fail_scsi_tasks(conn, -1, DID_TRANSPORT_DISRUPTED);
+ 	fail_mgmt_tasks(session, conn);
++	memset(&conn->tmhdr, 0, sizeof(conn->tmhdr));
+ 	spin_unlock_bh(&session->lock);
+ 	mutex_unlock(&session->eh_mutex);
+ }
+diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h
+index f2a2c1169486..dd0a52cea95a 100644
+--- a/include/scsi/iscsi_proto.h
++++ b/include/scsi/iscsi_proto.h
+@@ -279,6 +279,8 @@ struct iscsi_tm {
+ #define ISCSI_TM_FUNC_TARGET_COLD_RESET		7
+ #define ISCSI_TM_FUNC_TASK_REASSIGN		8
+ 
++#define ISCSI_TM_FUNC_VALUE(hdr) ((hdr)->flags & ISCSI_FLAG_TM_FUNC_MASK)
++
+ /* SCSI Task Management Response Header */
+ struct iscsi_tm_rsp {
+ 	uint8_t opcode;

commit 4f704dc03297406ea5d53b85c4666c60f69000bf
+Author: Mike Christie 
+Date:   Wed Nov 11 16:34:31 2009 -0600
+
+    [SCSI] libiscsi: fix login/text checks in pdu injection code
+    
+    For some reason we used to check for the the immediate bit
+    set and the opcocde in many places instead of just masking
+    the opcode. In the passthrough code this is a problem
+    because userspace may or may not have set the immediate bit
+    and it does not have to. This fixes up the opcode checks
+    in the passthrough code, so we mask off the opcode then
+    check against the iscsi proto definition like is done in
+    other places.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 67d0f3fc8ac0..8c29480fc02b 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -577,12 +577,12 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn,
+ 	struct iscsi_session *session = conn->session;
+ 	struct iscsi_hdr *hdr = task->hdr;
+ 	struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr;
++	uint8_t opcode = hdr->opcode & ISCSI_OPCODE_MASK;
+ 
+ 	if (conn->session->state == ISCSI_STATE_LOGGING_OUT)
+ 		return -ENOTCONN;
+ 
+-	if (hdr->opcode != (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) &&
+-	    hdr->opcode != (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE))
++	if (opcode != ISCSI_OP_LOGIN && opcode != ISCSI_OP_TEXT)
+ 		nop->exp_statsn = cpu_to_be32(conn->exp_statsn);
+ 	/*
+ 	 * pre-format CmdSN for outgoing PDU.
+@@ -590,9 +590,12 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn,
+ 	nop->cmdsn = cpu_to_be32(session->cmdsn);
+ 	if (hdr->itt != RESERVED_ITT) {
+ 		/*
+-		 * TODO: We always use immediate, so we never hit this.
++		 * TODO: We always use immediate for normal session pdus.
+ 		 * If we start to send tmfs or nops as non-immediate then
+ 		 * we should start checking the cmdsn numbers for mgmt tasks.
++		 *
++		 * During discovery sessions iscsid sends TEXT as non immediate,
++		 * but we always only send one PDU at a time.
+ 		 */
+ 		if (conn->c_stage == ISCSI_CONN_STARTED &&
+ 		    !(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
+@@ -620,22 +623,28 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ {
+ 	struct iscsi_session *session = conn->session;
+ 	struct iscsi_host *ihost = shost_priv(session->host);
++	uint8_t opcode = hdr->opcode & ISCSI_OPCODE_MASK;
+ 	struct iscsi_task *task;
+ 	itt_t itt;
+ 
+ 	if (session->state == ISCSI_STATE_TERMINATE)
+ 		return NULL;
+ 
+-	if (hdr->opcode == (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) ||
+-	    hdr->opcode == (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE))
++	if (opcode == ISCSI_OP_LOGIN || opcode == ISCSI_OP_TEXT) {
+ 		/*
+ 		 * Login and Text are sent serially, in
+ 		 * request-followed-by-response sequence.
+ 		 * Same task can be used. Same ITT must be used.
+ 		 * Note that login_task is preallocated at conn_create().
+ 		 */
++		if (conn->login_task->state != ISCSI_TASK_FREE) {
++			iscsi_conn_printk(KERN_ERR, conn, "Login/Text in "
++					  "progress. Cannot start new task.\n");
++			return NULL;
++		}
++
+ 		task = conn->login_task;
+-	else {
++	} else {
+ 		if (session->state != ISCSI_STATE_LOGGED_IN)
+ 			return NULL;
+ 

commit 24246de77503978cfcd7e76f06404e60e399992f
+Author: Mike Christie 
+Date:   Wed Nov 11 16:34:30 2009 -0600
+
+    [SCSI] bnx2i: use common iscsi suspend queue
+    
+    This just has bnx2i use the iscsi_suspend_queue helper.
+    
+    The suspend works as follows:
+    
+    When ep_poll has succeeed iscsid will call conn_bind, the LLD will
+    then call iscsi_conn_bind which will clear the suspend bit.
+    When ep_disconnect is called (or if there is a conn error) we set
+    the suspend bit. For the ep_disconnect case I  added a helper
+    in the previous kernel that will take the session lock to make sure
+    iscsi_queuecommand/xmit_task is not running and it will set
+    the suspend bit.
+    
+    Signed-off-by: Mike Christie 
+    Acked-by: Anil Veerabhadrappa 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h
+index 5edde1a8c04d..2b973f3c2eb2 100644
+--- a/drivers/scsi/bnx2i/bnx2i.h
++++ b/drivers/scsi/bnx2i/bnx2i.h
+@@ -232,7 +232,6 @@ struct bnx2i_conn {
+ 	struct iscsi_cls_conn *cls_conn;
+ 	struct bnx2i_hba *hba;
+ 	struct completion cmd_cleanup_cmpl;
+-	int is_bound;
+ 
+ 	u32 iscsi_conn_cid;
+ #define BNX2I_CID_RESERVED	0x5AFF
+diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
+index cafb888c2376..89e84c302aa0 100644
+--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
++++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
+@@ -1161,9 +1161,6 @@ static int bnx2i_task_xmit(struct iscsi_task *task)
+ 	struct bnx2i_cmd *cmd = task->dd_data;
+ 	struct iscsi_cmd *hdr = (struct iscsi_cmd *) task->hdr;
+ 
+-	if (!bnx2i_conn->is_bound)
+-		return -ENOTCONN;
+-
+ 	/*
+ 	 * If there is no scsi_cmnd this must be a mgmt task
+ 	 */
+@@ -1371,7 +1368,6 @@ static int bnx2i_conn_bind(struct iscsi_cls_session *cls_session,
+ 	bnx2i_conn->ep = bnx2i_ep;
+ 	bnx2i_conn->iscsi_conn_cid = bnx2i_ep->ep_iscsi_cid;
+ 	bnx2i_conn->fw_cid = bnx2i_ep->ep_cid;
+-	bnx2i_conn->is_bound = 1;
+ 
+ 	ret_code = bnx2i_bind_conn_to_iscsi_cid(hba, bnx2i_conn,
+ 						bnx2i_ep->ep_iscsi_cid);
+@@ -1896,9 +1892,7 @@ static void bnx2i_ep_disconnect(struct iscsi_endpoint *ep)
+ 		conn = bnx2i_conn->cls_conn->dd_data;
+ 		session = conn->session;
+ 
+-		spin_lock_bh(&session->lock);
+-		bnx2i_conn->is_bound = 0;
+-		spin_unlock_bh(&session->lock);
++		iscsi_suspend_queue(conn);
+ 	}
+ 
+ 	hba = bnx2i_ep->hba;

commit 3f9daedfcb197d784c6e7ecd731e3aa9859bc951
+Author: Mike Christie 
+Date:   Thu Nov 5 11:37:28 2009 -0600
+
+    [SCSI] add scsi target reset support to scsi ioctl
+    
+    The scsi ioctl code path was missing scsi target reset
+    support. This patch just adds it.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
+index b98f763931c5..d9564fb04f62 100644
+--- a/drivers/scsi/scsi_ioctl.c
++++ b/drivers/scsi/scsi_ioctl.c
+@@ -308,6 +308,9 @@ int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd,
+ 		case SG_SCSI_RESET_DEVICE:
+ 			val = SCSI_TRY_RESET_DEVICE;
+ 			break;
++		case SG_SCSI_RESET_TARGET:
++			val = SCSI_TRY_RESET_TARGET;
++			break;
+ 		case SG_SCSI_RESET_BUS:
+ 			val = SCSI_TRY_RESET_BUS;
+ 			break;

commit 2bc1c59dbdefdb6f9767e06efb86bbdb2923a8be
+Author: Mike Christie 
+Date:   Thu Nov 5 11:18:09 2009 -0600
+
+    [SCSI] fc class: fail fast bsg requests
+    
+    If the port state is blocked and the fast io fail tmo has
+    fired then this patch will fail bsg requests immediately.
+    This is needed if userspace is sending IOs to test the transport
+    like with fcping, so it will not have to wait for the dev loss tmo.
+    With this patch he bsg req fast io fail code behaves like the normal
+    and sg io/passthrough fast io fail.
+    
+    Signed-off-by: Mike Christie 
+    Acked-By: James Smart 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
+index 3ce56b3b2cd7..600502aa3b61 100644
+--- a/drivers/scsi/scsi_transport_fc.c
++++ b/drivers/scsi/scsi_transport_fc.c
+@@ -3809,8 +3809,9 @@ fc_bsg_request_handler(struct request_queue *q, struct Scsi_Host *shost,
+ 		return;
+ 
+ 	while (!blk_queue_plugged(q)) {
+-		if (rport && (rport->port_state == FC_PORTSTATE_BLOCKED))
+-				break;
++		if (rport && (rport->port_state == FC_PORTSTATE_BLOCKED) &&
++		    !(rport->flags & FC_RPORT_FAST_FAIL_TIMEDOUT))
++			break;
+ 
+ 		req = blk_fetch_request(q);
+ 		if (!req)

commit 349e11faa84ebdd6e484572cfe66f2cf4cb483a1
+Author: Mike Christie 
+Date:   Tue Nov 3 11:49:54 2009 -0800
+
+    [SCSI] libfc: do not use DID_NO_CONNECT for pkt alloc failures.
+    
+    DID_NO_CONNECT is not a nice value to use for pkt alloc failures,
+    because you can probably retry and IO will become available again.
+    For the device reset callout, we do not want to set the scsi command
+    result for the above reason, and because we do not need to set
+    the scsi_cmd->result in this path. We and other drivers do not set it
+    for success for example, and we do not set it for other failure.
+    And scsi-ml does not send every command through this path, and it is
+    not expecting us to use the scsi_cmnd struct like a cmd coming thruogh
+    queuecommand. I think it is more for storage in case we need a cmd
+    struct for a tmf and to give us certain params like the LUN.
+    
+    Patch was made over scsi-misc today.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Robert Love 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
+index 4bfab4f0ccb3..db252e2722d0 100644
+--- a/drivers/scsi/libfc/fc_fcp.c
++++ b/drivers/scsi/libfc/fc_fcp.c
+@@ -2029,7 +2029,6 @@ int fc_eh_device_reset(struct scsi_cmnd *sc_cmd)
+ 	fsp = fc_fcp_pkt_alloc(lport, GFP_NOIO);
+ 	if (fsp == NULL) {
+ 		printk(KERN_WARNING "libfc: could not allocate scsi_pkt\n");
+-		sc_cmd->result = DID_NO_CONNECT << 16;
+ 		goto out;
+ 	}
+ 

commit 5c20848a096fb1880ded99816be79d78ca1cd696
+Author: Mike Christie 
+Date:   Thu Oct 15 17:46:50 2009 -0700
+
+    [SCSI] libfc: convert to scsi_track_queue_full
+    
+    This converts the libfc using scsi_track_queue_full to
+    track the queue full from the change_queue_depth callback.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Vasu Dev 
+    Acked-by: Robert Love 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
+index beaab818d8de..c0dc8e151c65 100644
+--- a/drivers/scsi/libfc/fc_fcp.c
++++ b/drivers/scsi/libfc/fc_fcp.c
+@@ -1815,21 +1815,6 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
+ 			sc_cmd->result = DID_OK << 16;
+ 			if (fsp->scsi_resid)
+ 				CMD_RESID_LEN(sc_cmd) = fsp->scsi_resid;
+-		} else if (fsp->cdb_status == QUEUE_FULL) {
+-			struct scsi_device *tmp_sdev;
+-			struct scsi_device *sdev = sc_cmd->device;
+-
+-			shost_for_each_device(tmp_sdev, sdev->host) {
+-				if (tmp_sdev->id != sdev->id)
+-					continue;
+-
+-				if (tmp_sdev->queue_depth > 1) {
+-					scsi_track_queue_full(tmp_sdev,
+-							      tmp_sdev->
+-							      queue_depth - 1);
+-				}
+-			}
+-			sc_cmd->result = (DID_OK << 16) | fsp->cdb_status;
+ 		} else {
+ 			/*
+ 			 * transport level I/O was ok but scsi
+@@ -2066,10 +2051,16 @@ EXPORT_SYMBOL(fc_slave_alloc);
+ 
+ int fc_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
+ {
+-	if (reason != SCSI_QDEPTH_DEFAULT)
++	switch (reason) {
++	case SCSI_QDEPTH_DEFAULT:
++		scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
++		break;
++	case SCSI_QDEPTH_QFULL:
++		scsi_track_queue_full(sdev, qdepth);
++		break;
++	default:
+ 		return -EOPNOTSUPP;
+-
+-	scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
++	}
+ 	return sdev->queue_depth;
+ }
+ EXPORT_SYMBOL(fc_change_queue_depth);

commit 42a6a91833f1e0f5ee5b5ef98e9f00167b615f46
+Author: Mike Christie 
+Date:   Thu Oct 15 17:46:44 2009 -0700
+
+    [SCSI] scsi error: have scsi-ml call change_queue_depth to handle QUEUE_FULL
+    
+    This has scsi-ml call the change_queue_depth functions when
+    we get a QUEUE_FULL. It will only change the queue depth if
+    change_queue_depth is set because the LLD may have to
+    modify some internal resources, so I thought this would
+    be the safest route.
+    
+    Signed-off-by: Mike Christie 
+    
+    -v2
+    Limits change_queue_depth to only all luns of target by adding
+    channel check while iterating for all luns of Scsi_Host. This is
+    same as currently qla2xxx FC HBA does on QUEUE_FULL event.
+    
+    Signed-off-by: Vasu Dev 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
+index 1b0060b791e8..7b1e20fee906 100644
+--- a/drivers/scsi/scsi_error.c
++++ b/drivers/scsi/scsi_error.c
+@@ -331,6 +331,28 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
+ 	}
+ }
+ 
++static void scsi_handle_queue_full(struct scsi_device *sdev)
++{
++	struct scsi_host_template *sht = sdev->host->hostt;
++	struct scsi_device *tmp_sdev;
++
++	if (!sht->change_queue_depth)
++		return;
++
++	shost_for_each_device(tmp_sdev, sdev->host) {
++		if (tmp_sdev->channel != sdev->channel ||
++		    tmp_sdev->id != sdev->id)
++			continue;
++		/*
++		 * We do not know the number of commands that were at
++		 * the device when we got the queue full so we start
++		 * from the highest possible value and work our way down.
++		 */
++		sht->change_queue_depth(tmp_sdev, tmp_sdev->queue_depth - 1,
++					SCSI_QDEPTH_QFULL);
++	}
++}
++
+ /**
+  * scsi_eh_completed_normally - Disposition a eh cmd on return from LLD.
+  * @scmd:	SCSI cmd to examine.
+@@ -387,8 +409,10 @@ static int scsi_eh_completed_normally(struct scsi_cmnd *scmd)
+ 		 * let issuer deal with this, it could be just fine
+ 		 */
+ 		return SUCCESS;
+-	case BUSY:
+ 	case QUEUE_FULL:
++		scsi_handle_queue_full(scmd->device);
++		/* fall through */
++	case BUSY:
+ 	default:
+ 		return FAILED;
+ 	}
+@@ -1387,6 +1411,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
+ 	 */
+ 	switch (status_byte(scmd->result)) {
+ 	case QUEUE_FULL:
++		scsi_handle_queue_full(scmd->device);
+ 		/*
+ 		 * the case of trying to send too many commands to a
+ 		 * tagged queueing device.

commit e881a172dac4d9ea3b2a1540041d872963c269bd
+Author: Mike Christie 
+Date:   Thu Oct 15 17:46:39 2009 -0700
+
+    [SCSI] modify change_queue_depth to take in reason why it is being called
+    
+    This patch modifies scsi_host_template->change_queue_depth so that
+    it takes an argument indicating why it is being called. This will be
+    used so that if a LLD needs to do some extra processing when
+    handling queue fulls or later ramp ups, it can do so.
+    
+    This is a simple port of the drivers setting a change_queue_depth
+    callback. In the patch I just have these LLDs adjust the queue depth
+    if the user was requesting it.
+    
+    Signed-off-by: Mike Christie 
+    
+    [Vasu.Dev: v2
+            Also converted pmcraid_change_queue_depth and then verified
+    all modules compile  using "make allmodconfig" for any new build
+    warnings on X86_64.
+    
+            Updated original description after combing two original
+    patches from Mike to make this patch git bisectable.]
+    Signed-off-by: Vasu Dev 
+    [jejb: fixed up 53c700]
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
+index b4ee28dec521..5d52c2fcd076 100644
+--- a/drivers/ata/libata-scsi.c
++++ b/drivers/ata/libata-scsi.c
+@@ -1208,6 +1208,7 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev)
+  *	ata_scsi_change_queue_depth - SCSI callback for queue depth config
+  *	@sdev: SCSI device to configure queue depth for
+  *	@queue_depth: new queue depth
++ *	@reason: calling context
+  *
+  *	This is libata standard hostt->change_queue_depth callback.
+  *	SCSI will call into this callback when user tries to set queue
+@@ -1219,12 +1220,16 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev)
+  *	RETURNS:
+  *	Newly configured queue depth.
+  */
+-int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth)
++int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth,
++				int reason)
+ {
+ 	struct ata_port *ap = ata_shost_to_port(sdev->host);
+ 	struct ata_device *dev;
+ 	unsigned long flags;
+ 
++	if (reason != SCSI_QDEPTH_DEFAULT)
++		return -EOPNOTSUPP;
++
+ 	if (queue_depth < 1 || queue_depth == sdev->queue_depth)
+ 		return sdev->queue_depth;
+ 
+diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
+index 1eb4e020eb5c..0c82d335c55d 100644
+--- a/drivers/ata/sata_nv.c
++++ b/drivers/ata/sata_nv.c
+@@ -1975,7 +1975,7 @@ static int nv_swncq_slave_config(struct scsi_device *sdev)
+ 	ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
+ 
+ 	if (strncmp(model_num, "Maxtor", 6) == 0) {
+-		ata_scsi_change_queue_depth(sdev, 1);
++		ata_scsi_change_queue_depth(sdev, 1, SCSI_QDEPTH_DEFAULT);
+ 		ata_dev_printk(dev, KERN_NOTICE,
+ 			"Disabling SWNCQ mode (depth %x)\n", sdev->queue_depth);
+ 	}
+diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
+index f68ec48a881e..57752751712b 100644
+--- a/drivers/message/fusion/mptscsih.c
++++ b/drivers/message/fusion/mptscsih.c
+@@ -2351,11 +2351,12 @@ mptscsih_slave_destroy(struct scsi_device *sdev)
+  *	mptscsih_change_queue_depth - This function will set a devices queue depth
+  *	@sdev: per scsi_device pointer
+  *	@qdepth: requested queue depth
++ *	@reason: calling context
+  *
+  *	Adding support for new 'change_queue_depth' api.
+ */
+ int
+-mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
++mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
+ {
+ 	MPT_SCSI_HOST		*hd = shost_priv(sdev->host);
+ 	VirtTarget 		*vtarget;
+@@ -2367,6 +2368,9 @@ mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
+ 	starget = scsi_target(sdev);
+ 	vtarget = starget->hostdata;
+ 
++	if (reason != SCSI_QDEPTH_DEFAULT)
++		return -EOPNOTSUPP;
++
+ 	if (ioc->bus_type == SPI) {
+ 		if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
+ 			max_depth = 1;
+@@ -2433,7 +2437,8 @@ mptscsih_slave_configure(struct scsi_device *sdev)
+ 		    ioc->name, vtarget->negoFlags, vtarget->maxOffset,
+ 		    vtarget->minSyncFactor));
+ 
+-	mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
++	mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH,
++				    SCSI_QDEPTH_DEFAULT);
+ 	dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+ 		"tagged %d, simple %d, ordered %d\n",
+ 		ioc->name,sdev->tagged_supported, sdev->simple_tags,
+diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
+index e0b33e04a33b..45a5ff3eff61 100644
+--- a/drivers/message/fusion/mptscsih.h
++++ b/drivers/message/fusion/mptscsih.h
+@@ -128,7 +128,8 @@ extern int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_F
+ extern int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
+ extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
+ extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
+-extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth);
++extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth,
++				       int reason);
+ extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id);
+ extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id);
+ extern struct device_attribute *mptscsih_host_attrs[];
+diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
+index 0e1a34627a2e..ad1154701729 100644
+--- a/drivers/s390/scsi/zfcp_scsi.c
++++ b/drivers/s390/scsi/zfcp_scsi.c
+@@ -29,8 +29,12 @@ char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *fcp_rsp_iu)
+ 	return fcp_sns_info_ptr;
+ }
+ 
+-static int zfcp_scsi_change_queue_depth(struct scsi_device *sdev, int depth)
++static int zfcp_scsi_change_queue_depth(struct scsi_device *sdev, int depth,
++					int reason)
+ {
++	if (reason != SCSI_QDEPTH_DEFAULT)
++		return -EOPNOTSUPP;
++
+ 	scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
+ 	return sdev->queue_depth;
+ }
+diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
+index 36c21b19e5d7..2d16d49fd3cd 100644
+--- a/drivers/scsi/3w-9xxx.c
++++ b/drivers/scsi/3w-9xxx.c
+@@ -186,8 +186,12 @@ static ssize_t twa_show_stats(struct device *dev,
+ } /* End twa_show_stats() */
+ 
+ /* This function will set a devices queue depth */
+-static int twa_change_queue_depth(struct scsi_device *sdev, int queue_depth)
++static int twa_change_queue_depth(struct scsi_device *sdev, int queue_depth,
++				  int reason)
+ {
++	if (reason != SCSI_QDEPTH_DEFAULT)
++		return -EOPNOTSUPP;
++
+ 	if (queue_depth > TW_Q_LENGTH-2)
+ 		queue_depth = TW_Q_LENGTH-2;
+ 	scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
+diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
+index faa0fcfed71e..d224294c38fb 100644
+--- a/drivers/scsi/3w-xxxx.c
++++ b/drivers/scsi/3w-xxxx.c
+@@ -521,8 +521,12 @@ static ssize_t tw_show_stats(struct device *dev, struct device_attribute *attr,
+ } /* End tw_show_stats() */
+ 
+ /* This function will set a devices queue depth */
+-static int tw_change_queue_depth(struct scsi_device *sdev, int queue_depth)
++static int tw_change_queue_depth(struct scsi_device *sdev, int queue_depth,
++				 int reason)
+ {
++	if (reason != SCSI_QDEPTH_DEFAULT)
++		return -EOPNOTSUPP;
++
+ 	if (queue_depth > TW_Q_LENGTH-2)
+ 		queue_depth = TW_Q_LENGTH-2;
+ 	scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
+diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
+index f5a9addb7050..6c60a8060c58 100644
+--- a/drivers/scsi/53c700.c
++++ b/drivers/scsi/53c700.c
+@@ -175,7 +175,7 @@ STATIC void NCR_700_chip_reset(struct Scsi_Host *host);
+ STATIC int NCR_700_slave_alloc(struct scsi_device *SDpnt);
+ STATIC int NCR_700_slave_configure(struct scsi_device *SDpnt);
+ STATIC void NCR_700_slave_destroy(struct scsi_device *SDpnt);
+-static int NCR_700_change_queue_depth(struct scsi_device *SDpnt, int depth);
++static int NCR_700_change_queue_depth(struct scsi_device *SDpnt, int depth, int reason);
+ static int NCR_700_change_queue_type(struct scsi_device *SDpnt, int depth);
+ 
+ STATIC struct device_attribute *NCR_700_dev_attrs[];
+@@ -2082,8 +2082,11 @@ NCR_700_slave_destroy(struct scsi_device *SDp)
+ }
+ 
+ static int
+-NCR_700_change_queue_depth(struct scsi_device *SDp, int depth)
++NCR_700_change_queue_depth(struct scsi_device *SDp, int depth, int reason)
+ {
++	if (reason != SCSI_QDEPTH_DEFAULT)
++		return -EOPNOTSUPP;
++
+ 	if (depth > NCR_700_MAX_TAGS)
+ 		depth = NCR_700_MAX_TAGS;
+ 
+diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
+index 9b97c3e016fe..e9373a2d14fa 100644
+--- a/drivers/scsi/aacraid/linit.c
++++ b/drivers/scsi/aacraid/linit.c
+@@ -472,8 +472,12 @@ static int aac_slave_configure(struct scsi_device *sdev)
+  *	total capacity and the queue depth supported by the target device.
+  */
+ 
+-static int aac_change_queue_depth(struct scsi_device *sdev, int depth)
++static int aac_change_queue_depth(struct scsi_device *sdev, int depth,
++				  int reason)
+ {
++	if (reason != SCSI_QDEPTH_DEFAULT)
++		return -EOPNOTSUPP;
++
+ 	if (sdev->tagged_supported && (sdev->type == TYPE_DISK) &&
+ 	    (sdev_channel(sdev) == CONTAINER_CHANNEL)) {
+ 		struct scsi_device * dev;
+diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
+index 80aac01b5a6f..47d5d19f8c92 100644
+--- a/drivers/scsi/arcmsr/arcmsr_hba.c
++++ b/drivers/scsi/arcmsr/arcmsr_hba.c
+@@ -98,8 +98,11 @@ static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb);
+ static const char *arcmsr_info(struct Scsi_Host *);
+ static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb);
+ static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev,
+-								int queue_depth)
++					  int queue_depth, int reason)
+ {
++	if (reason != SCSI_QDEPTH_DEFAULT)
++		return -EOPNOTSUPP;
++
+ 	if (queue_depth > ARCMSR_MAX_CMD_PERLUN)
+ 		queue_depth = ARCMSR_MAX_CMD_PERLUN;
+ 	scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
+diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
+index a0e7e711ff9d..901a3daeb36b 100644
+--- a/drivers/scsi/hptiop.c
++++ b/drivers/scsi/hptiop.c
+@@ -861,10 +861,13 @@ static int hptiop_reset(struct scsi_cmnd *scp)
+ }
+ 
+ static int hptiop_adjust_disk_queue_depth(struct scsi_device *sdev,
+-						int queue_depth)
++					  int queue_depth, int reason)
+ {
+ 	struct hptiop_hba *hba = (struct hptiop_hba *)sdev->host->hostdata;
+ 
++	if (reason != SCSI_QDEPTH_DEFAULT)
++		return -EOPNOTSUPP;
++
+ 	if (queue_depth > hba->max_requests)
+ 		queue_depth = hba->max_requests;
+ 	scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
+diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
+index bc9beb8c587c..87b536a97cb4 100644
+--- a/drivers/scsi/ibmvscsi/ibmvfc.c
++++ b/drivers/scsi/ibmvscsi/ibmvfc.c
+@@ -2764,12 +2764,17 @@ static int ibmvfc_slave_configure(struct scsi_device *sdev)
+  * ibmvfc_change_queue_depth - Change the device's queue depth
+  * @sdev:	scsi device struct
+  * @qdepth:	depth to set
++ * @reason:	calling context
+  *
+  * Return value:
+  * 	actual depth set
+  **/
+-static int ibmvfc_change_queue_depth(struct scsi_device *sdev, int qdepth)
++static int ibmvfc_change_queue_depth(struct scsi_device *sdev, int qdepth,
++				     int reason)
+ {
++	if (reason != SCSI_QDEPTH_DEFAULT)
++		return -EOPNOTSUPP;
++
+ 	if (qdepth > IBMVFC_MAX_CMDS_PER_LUN)
+ 		qdepth = IBMVFC_MAX_CMDS_PER_LUN;
+ 
+diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
+index d9b0e9d31983..e475b7957c2d 100644
+--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
++++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
+@@ -1637,12 +1637,17 @@ static int ibmvscsi_slave_configure(struct scsi_device *sdev)
+  * ibmvscsi_change_queue_depth - Change the device's queue depth
+  * @sdev:	scsi device struct
+  * @qdepth:	depth to set
++ * @reason:	calling context
+  *
+  * Return value:
+  * 	actual depth set
+  **/
+-static int ibmvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth)
++static int ibmvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth,
++				       int reason)
+ {
++	if (reason != SCSI_QDEPTH_DEFAULT)
++		return -EOPNOTSUPP;
++
+ 	if (qdepth > IBMVSCSI_MAX_CMDS_PER_LUN)
+ 		qdepth = IBMVSCSI_MAX_CMDS_PER_LUN;
+ 
+diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
+index 5f045505a1f4..d40d5c79fff1 100644
+--- a/drivers/scsi/ipr.c
++++ b/drivers/scsi/ipr.c
+@@ -3367,16 +3367,21 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg) { return 0; };
+  * ipr_change_queue_depth - Change the device's queue depth
+  * @sdev:	scsi device struct
+  * @qdepth:	depth to set
++ * @reason:	calling context
+  *
+  * Return value:
+  * 	actual depth set
+  **/
+-static int ipr_change_queue_depth(struct scsi_device *sdev, int qdepth)
++static int ipr_change_queue_depth(struct scsi_device *sdev, int qdepth,
++				  int reason)
+ {
+ 	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata;
+ 	struct ipr_resource_entry *res;
+ 	unsigned long lock_flags = 0;
+ 
++	if (reason != SCSI_QDEPTH_DEFAULT)
++		return -EOPNOTSUPP;
++
+ 	spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+ 	res = (struct ipr_resource_entry *)sdev->hostdata;
+ 
+diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
+index a67f53a5026c..beaab818d8de 100644
+--- a/drivers/scsi/libfc/fc_fcp.c
++++ b/drivers/scsi/libfc/fc_fcp.c
+@@ -2064,8 +2064,11 @@ int fc_slave_alloc(struct scsi_device *sdev)
+ }
+ EXPORT_SYMBOL(fc_slave_alloc);
+ 
+-int fc_change_queue_depth(struct scsi_device *sdev, int qdepth)
++int fc_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
+ {
++	if (reason != SCSI_QDEPTH_DEFAULT)
++		return -EOPNOTSUPP;
++
+ 	scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
+ 	return sdev->queue_depth;
+ }
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index f1a4246f890c..67d0f3fc8ac0 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1643,8 +1643,11 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ }
+ EXPORT_SYMBOL_GPL(iscsi_queuecommand);
+ 
+-int iscsi_change_queue_depth(struct scsi_device *sdev, int depth)
++int iscsi_change_queue_depth(struct scsi_device *sdev, int depth, int reason)
+ {
++	if (reason != SCSI_QDEPTH_DEFAULT)
++		return -EOPNOTSUPP;
++
+ 	scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
+ 	return sdev->queue_depth;
+ }
+diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
+index 1c558d3bce18..14b13196b22d 100644
+--- a/drivers/scsi/libsas/sas_scsi_host.c
++++ b/drivers/scsi/libsas/sas_scsi_host.c
+@@ -820,10 +820,14 @@ void sas_slave_destroy(struct scsi_device *scsi_dev)
+ 		ata_port_disable(dev->sata_dev.ap);
+ }
+ 
+-int sas_change_queue_depth(struct scsi_device *scsi_dev, int new_depth)
++int sas_change_queue_depth(struct scsi_device *scsi_dev, int new_depth,
++			   int reason)
+ {
+ 	int res = min(new_depth, SAS_MAX_QD);
+ 
++	if (reason != SCSI_QDEPTH_DEFAULT)
++		return -EOPNOTSUPP;
++
+ 	if (scsi_dev->tagged_supported)
+ 		scsi_adjust_queue_depth(scsi_dev, scsi_get_tag_type(scsi_dev),
+ 					res);
+diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
+index 234f0b7eb21c..fd181c2a8ae4 100644
+--- a/drivers/scsi/megaraid/megaraid_mbox.c
++++ b/drivers/scsi/megaraid/megaraid_mbox.c
+@@ -335,12 +335,17 @@ static struct device_attribute *megaraid_sdev_attrs[] = {
+  * megaraid_change_queue_depth - Change the device's queue depth
+  * @sdev:	scsi device struct
+  * @qdepth:	depth to set
++ * @reason:	calling context
+  *
+  * Return value:
+  * 	actual depth set
+  */
+-static int megaraid_change_queue_depth(struct scsi_device *sdev, int qdepth)
++static int megaraid_change_queue_depth(struct scsi_device *sdev, int qdepth,
++				       int reason)
+ {
++	if (reason != SCSI_QDEPTH_DEFAULT)
++		return -EOPNOTSUPP;
++
+ 	if (qdepth > MBOX_MAX_SCSI_CMDS)
+ 		qdepth = MBOX_MAX_SCSI_CMDS;
+ 	scsi_adjust_queue_depth(sdev, 0, qdepth);
+diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+index 8dc682f00fd2..55ee014a7e08 100644
+--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
++++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+@@ -1099,11 +1099,12 @@ _scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc,
+  * _scsih_change_queue_depth - setting device queue depth
+  * @sdev: scsi device struct
+  * @qdepth: requested queue depth
++ * @reason: calling context
+  *
+  * Returns queue depth.
+  */
+ static int
+-_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
++_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
+ {
+ 	struct Scsi_Host *shost = sdev->host;
+ 	int max_depth;
+@@ -1114,6 +1115,9 @@ _scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
+ 	struct _sas_device *sas_device;
+ 	unsigned long flags;
+ 
++	if (reason != SCSI_QDEPTH_DEFAULT)
++		return -EOPNOTSUPP;
++
+ 	max_depth = shost->can_queue;
+ 
+ 	/* limit max device queue for SATA to 32 */
+@@ -1569,7 +1573,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
+ 		    r_level, raid_device->handle,
+ 		    (unsigned long long)raid_device->wwid,
+ 		    raid_device->num_pds, ds);
+-		_scsih_change_queue_depth(sdev, qdepth);
++		_scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
+ 		return 0;
+ 	}
+ 
+@@ -1615,7 +1619,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
+ 			_scsih_display_sata_capabilities(ioc, sas_device, sdev);
+ 	}
+ 
+-	_scsih_change_queue_depth(sdev, qdepth);
++	_scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
+ 
+ 	if (ssp_target)
+ 		sas_read_port_mode_page(sdev);
+diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c
+index f7c70e2a8224..86d158ee3572 100644
+--- a/drivers/scsi/pmcraid.c
++++ b/drivers/scsi/pmcraid.c
+@@ -278,12 +278,17 @@ static void pmcraid_slave_destroy(struct scsi_device *scsi_dev)
+  * pmcraid_change_queue_depth - Change the device's queue depth
+  * @scsi_dev: scsi device struct
+  * @depth: depth to set
++ * @reason: calling context
+  *
+  * Return value
+  * 	actual depth set
+  */
+-static int pmcraid_change_queue_depth(struct scsi_device *scsi_dev, int depth)
++static int pmcraid_change_queue_depth(struct scsi_device *scsi_dev, int depth,
++				      int reason)
+ {
++	if (reason != SCSI_QDEPTH_DEFAULT)
++		return -EOPNOTSUPP;
++
+ 	if (depth > PMCRAID_MAX_CMD_PER_LUN)
+ 		depth = PMCRAID_MAX_CMD_PER_LUN;
+ 
+diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
+index ecf2a40d70be..d69744a62fe4 100644
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -138,7 +138,7 @@ static int qla2xxx_eh_target_reset(struct scsi_cmnd *);
+ static int qla2xxx_eh_bus_reset(struct scsi_cmnd *);
+ static int qla2xxx_eh_host_reset(struct scsi_cmnd *);
+ 
+-static int qla2x00_change_queue_depth(struct scsi_device *, int);
++static int qla2x00_change_queue_depth(struct scsi_device *, int, int);
+ static int qla2x00_change_queue_type(struct scsi_device *, int);
+ 
+ struct scsi_host_template qla2xxx_driver_template = {
+@@ -1235,8 +1235,11 @@ qla2xxx_slave_destroy(struct scsi_device *sdev)
+ }
+ 
+ static int
+-qla2x00_change_queue_depth(struct scsi_device *sdev, int qdepth)
++qla2x00_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
+ {
++	if (reason != SCSI_QDEPTH_DEFAULT)
++		return -EOPNOTSUPP;
++
+ 	scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
+ 	return sdev->queue_depth;
+ }
+diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
+index 5c7eb63a19d1..a48782866b22 100644
+--- a/drivers/scsi/scsi_sysfs.c
++++ b/drivers/scsi/scsi_sysfs.c
+@@ -766,7 +766,8 @@ sdev_store_queue_depth_rw(struct device *dev, struct device_attribute *attr,
+ 	if (depth < 1)
+ 		return -EINVAL;
+ 
+-	retval = sht->change_queue_depth(sdev, depth);
++	retval = sht->change_queue_depth(sdev, depth,
++					 SCSI_QDEPTH_DEFAULT);
+ 	if (retval < 0)
+ 		return retval;
+ 
+diff --git a/include/linux/libata.h b/include/linux/libata.h
+index 87698640c091..85df383fd4bd 100644
+--- a/include/linux/libata.h
++++ b/include/linux/libata.h
+@@ -1023,7 +1023,7 @@ extern int ata_std_bios_param(struct scsi_device *sdev,
+ extern int ata_scsi_slave_config(struct scsi_device *sdev);
+ extern void ata_scsi_slave_destroy(struct scsi_device *sdev);
+ extern int ata_scsi_change_queue_depth(struct scsi_device *sdev,
+-				       int queue_depth);
++				       int queue_depth, int reason);
+ extern struct ata_device *ata_dev_pair(struct ata_device *adev);
+ extern int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev);
+ 
+diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
+index 1662d73d85a7..9617f9365e45 100644
+--- a/include/scsi/libfc.h
++++ b/include/scsi/libfc.h
+@@ -919,7 +919,7 @@ int fc_slave_alloc(struct scsi_device *sdev);
+ /*
+  * Adjust the queue depth.
+  */
+-int fc_change_queue_depth(struct scsi_device *sdev, int qdepth);
++int fc_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason);
+ 
+ /*
+  * Change the tag type.
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index a72edd4eceec..2db2bc26b1e9 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -333,7 +333,8 @@ struct iscsi_host {
+ /*
+  * scsi host template
+  */
+-extern int iscsi_change_queue_depth(struct scsi_device *sdev, int depth);
++extern int iscsi_change_queue_depth(struct scsi_device *sdev, int depth,
++				    int reason);
+ extern int iscsi_eh_abort(struct scsi_cmnd *sc);
+ extern int iscsi_eh_target_reset(struct scsi_cmnd *sc);
+ extern int iscsi_eh_device_reset(struct scsi_cmnd *sc);
+diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
+index e78d3b62d8ec..9eaa3f05f954 100644
+--- a/include/scsi/libsas.h
++++ b/include/scsi/libsas.h
+@@ -634,7 +634,8 @@ extern int sas_target_alloc(struct scsi_target *);
+ extern int sas_slave_alloc(struct scsi_device *);
+ extern int sas_slave_configure(struct scsi_device *);
+ extern void sas_slave_destroy(struct scsi_device *);
+-extern int sas_change_queue_depth(struct scsi_device *, int new_depth);
++extern int sas_change_queue_depth(struct scsi_device *, int new_depth,
++				  int reason);
+ extern int sas_change_queue_type(struct scsi_device *, int qt);
+ extern int sas_bios_param(struct scsi_device *,
+ 			  struct block_device *,
+diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
+index 6e728b176904..603054d8f40c 100644
+--- a/include/scsi/scsi_host.h
++++ b/include/scsi/scsi_host.h
+@@ -43,6 +43,12 @@ struct blk_queue_tags;
+ #define DISABLE_CLUSTERING 0
+ #define ENABLE_CLUSTERING 1
+ 
++enum {
++	SCSI_QDEPTH_DEFAULT,	/* default requested change, e.g. from sysfs */
++	SCSI_QDEPTH_QFULL,	/* scsi-ml requested due to queue full */
++	SCSI_QDEPTH_RAMP_UP,	/* scsi-ml requested due to threshhold event */
++};
++
+ struct scsi_host_template {
+ 	struct module *module;
+ 	const char *name;
+@@ -294,7 +300,7 @@ struct scsi_host_template {
+ 	 *
+ 	 * Status: OPTIONAL
+ 	 */
+-	int (* change_queue_depth)(struct scsi_device *, int);
++	int (* change_queue_depth)(struct scsi_device *, int, int);
+ 
+ 	/*
+ 	 * Fill in this function to allow the changing of tag types

commit 8eca355fa8af660557fbdd5506bde1392eee9bfe
+Author: Mike Christie 
+Date:   Wed Oct 21 16:27:44 2009 -0700
+
+    [SCSI] fcoe: initialize return value in fcoe_destroy
+    
+    When doing echo ethX > /sys..../destroy I am getting
+    errors when the tear down succeeds. It looks like the
+    reason for this is because the rc var is not getting set
+    when the destruction works. This just sets it to zero.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Robert Love 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
+index 7c898875838f..8702c8d728dd 100644
+--- a/drivers/scsi/fcoe/fcoe.c
++++ b/drivers/scsi/fcoe/fcoe.c
+@@ -1631,7 +1631,7 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
+ {
+ 	struct fcoe_interface *fcoe;
+ 	struct net_device *netdev;
+-	int rc;
++	int rc = 0;
+ 
+ 	mutex_lock(&fcoe_config_mutex);
+ #ifdef CONFIG_FCOE_MODULE

commit ad63082626f99651d261ccd8698ce4e997362f7e
+Author: Mike Christie 
+Date:   Mon Sep 28 15:50:52 2009 -0500
+
+    [SCSI] fix propogation of integrity errors
+    
+    When the Integrity check is done in scsi_io_completion it will
+    set error to -EILSEQ. However, at this point error is no longer
+    used, and blk_end_request_err has -EIO hardcoded.
+    
+    It looks like there was just porting mistake with this patch
+    http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=3e695f89c5debb735e4ff051e9e58d8fb4e95110
+    and we meant to send error upwards, so this patch changes the hard
+    coded EIO to the error variable.
+    
+    I have only boot tested this patch.
+    
+    Signed-off-by: Mike Christie 
+    Acked-by: Martin K. Petersen 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index 5987da857103..108655230b59 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -898,7 +898,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
+ 				scsi_print_sense("", cmd);
+ 			scsi_print_command(cmd);
+ 		}
+-		if (blk_end_request_err(req, -EIO))
++		if (blk_end_request_err(req, error))
+ 			scsi_requeue_command(q, cmd);
+ 		else
+ 			scsi_next_command(cmd);

commit 661134ad3765348ecd6150a92e736bf28ba40f80
+Author: Mike Christie 
+Date:   Sat Sep 5 07:35:33 2009 +0530
+
+    [SCSI] libiscsi, bnx2i: make bound ep check common
+    
+    bnx2i currently has a check for if a ep is properly bound, so if
+    iscsi_queuecommand/xmit_task is called while there is no ep
+    we will not queue IO.
+    
+    be2iscsi sends IO from queuecommand/xmit_task like how bnx2i does
+    and needs a similar test. This patch has us just use the suspend_bit
+    test for this.
+    
+    When ep_poll has succeeed iscsid will call conn_bind, the LLD will
+    then call iscsi_conn_bind which will clear the suspend bit.
+    When ep_disconnect is called (or if there is a conn error) we set
+    the suspend bit. For the ep_disconnect case I am adding a helper
+    in this patch that will take the session lock to make sure
+    iscsi_queuecommand/xmit_task is not running and it will set
+    the suspend bit.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Jayamohan Kallickal 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 67b2a2b00286..8dc73c489a17 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1571,6 +1571,12 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 		goto fault;
+ 	}
+ 
++	if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) {
++		reason = FAILURE_SESSION_IN_RECOVERY;
++		sc->result = DID_REQUEUE;
++		goto fault;
++	}
++
+ 	if (iscsi_check_cmdsn_window_closed(conn)) {
+ 		reason = FAILURE_WINDOW_CLOSED;
+ 		goto reject;
+@@ -1810,6 +1816,33 @@ static void fail_scsi_tasks(struct iscsi_conn *conn, unsigned lun,
+ 	}
+ }
+ 
++/**
++ * iscsi_suspend_queue - suspend iscsi_queuecommand
++ * @conn: iscsi conn to stop queueing IO on
++ *
++ * This grabs the session lock to make sure no one is in
++ * xmit_task/queuecommand, and then sets suspend to prevent
++ * new commands from being queued. This only needs to be called
++ * by offload drivers that need to sync a path like ep disconnect
++ * with the iscsi_queuecommand/xmit_task. To start IO again libiscsi
++ * will call iscsi_start_tx and iscsi_unblock_session when in FFP.
++ */
++void iscsi_suspend_queue(struct iscsi_conn *conn)
++{
++	spin_lock_bh(&conn->session->lock);
++	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
++	spin_unlock_bh(&conn->session->lock);
++}
++EXPORT_SYMBOL_GPL(iscsi_suspend_queue);
++
++/**
++ * iscsi_suspend_tx - suspend iscsi_data_xmit
++ * @conn: iscsi conn tp stop processing IO on.
++ *
++ * This function sets the suspend bit to prevent iscsi_data_xmit
++ * from sending new IO, and if work is queued on the xmit thread
++ * it will wait for it to be completed.
++ */
+ void iscsi_suspend_tx(struct iscsi_conn *conn)
+ {
+ 	struct Scsi_Host *shost = conn->session->host;
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 439c8b75cb69..887e57e3e223 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -390,6 +390,7 @@ extern void iscsi_session_failure(struct iscsi_session *session,
+ extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ 				enum iscsi_param param, char *buf);
+ extern void iscsi_suspend_tx(struct iscsi_conn *conn);
++extern void iscsi_suspend_queue(struct iscsi_conn *conn);
+ extern void iscsi_conn_queue_work(struct iscsi_conn *conn);
+ 
+ #define iscsi_conn_printk(prefix, _c, fmt, a...) \

commit 4c0ba5d2593b5156327263f3ef6d7399dc0717b8
+Author: Mike Christie 
+Date:   Sat Sep 5 07:34:23 2009 +0530
+
+    [SCSI] libiscsi: add completion function for drivers that do not need pdu processing
+    
+    beiscsi does not need the iscsi scsi cmd processing. It does not
+    even get this info on the completion path. This adds a function
+    to just update the sequencing numbers and complete a task.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Jayamohan Kallickal 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index a7ee4bb40708..67b2a2b00286 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -109,12 +109,9 @@ inline void iscsi_conn_queue_work(struct iscsi_conn *conn)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_conn_queue_work);
+ 
+-void
+-iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
++static void __iscsi_update_cmdsn(struct iscsi_session *session,
++				 uint32_t exp_cmdsn, uint32_t max_cmdsn)
+ {
+-	uint32_t max_cmdsn = be32_to_cpu(hdr->max_cmdsn);
+-	uint32_t exp_cmdsn = be32_to_cpu(hdr->exp_cmdsn);
+-
+ 	/*
+ 	 * standard specifies this check for when to update expected and
+ 	 * max sequence numbers
+@@ -138,6 +135,12 @@ iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
+ 			iscsi_conn_queue_work(session->leadconn);
+ 	}
+ }
++
++void iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
++{
++	__iscsi_update_cmdsn(session, be32_to_cpu(hdr->exp_cmdsn),
++			     be32_to_cpu(hdr->max_cmdsn));
++}
+ EXPORT_SYMBOL_GPL(iscsi_update_cmdsn);
+ 
+ /**
+@@ -499,6 +502,31 @@ static void iscsi_complete_task(struct iscsi_task *task, int state)
+ 	__iscsi_put_task(task);
+ }
+ 
++/**
++ * iscsi_complete_scsi_task - finish scsi task normally
++ * @task: iscsi task for scsi cmd
++ * @exp_cmdsn: expected cmd sn in cpu format
++ * @max_cmdsn: max cmd sn in cpu format
++ *
++ * This is used when drivers do not need or cannot perform
++ * lower level pdu processing.
++ *
++ * Called with session lock
++ */
++void iscsi_complete_scsi_task(struct iscsi_task *task,
++			      uint32_t exp_cmdsn, uint32_t max_cmdsn)
++{
++	struct iscsi_conn *conn = task->conn;
++
++	ISCSI_DBG_SESSION(conn->session, "[itt 0x%x]\n", task->itt);
++
++	conn->last_recv = jiffies;
++	__iscsi_update_cmdsn(conn->session, exp_cmdsn, max_cmdsn);
++	iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
++}
++EXPORT_SYMBOL_GPL(iscsi_complete_scsi_task);
++
++
+ /*
+  * session lock must be held and if not called for a task that is
+  * still pending or from the xmit thread, then xmit thread must
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 61afeb59a836..439c8b75cb69 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -415,6 +415,8 @@ extern struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *, itt_t);
+ extern void iscsi_requeue_task(struct iscsi_task *task);
+ extern void iscsi_put_task(struct iscsi_task *task);
+ extern void __iscsi_get_task(struct iscsi_task *task);
++extern void iscsi_complete_scsi_task(struct iscsi_task *task,
++				     uint32_t exp_cmdsn, uint32_t max_cmdsn);
+ 
+ /*
+  * generic helpers

commit 70b31c152dc49ef70bd2b34ad53ccbd9bb4116d4
+Author: Mike Christie 
+Date:   Thu Aug 20 15:11:03 2009 -0500
+
+    [SCSI] libiscsi, iscsi_tcp: check suspend bit before each call to xmit_task
+    
+    If we had multiple tasks on the cmd or requeue  lists, and iscsi_tcp
+    returns a error, the write_space function can still run and queue
+    iscsi_data_xmit. If it was a legetimate problem and iscsi_conn_failure
+    was run but we raced and iscsi_data_xmit was run first it could miss
+    the suspend bit checks, and start trying to send data again and hit
+    another timeout. A similar problem is present when using cxgb3i.
+    
+    This has libiscsi check the suspend bit before calling the xmit
+    task callout, so we at least do not try sending multiple tasks
+    (one could be sent).
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 1d7a8b7e8a75..a7ee4bb40708 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1280,6 +1280,9 @@ static int iscsi_xmit_task(struct iscsi_conn *conn)
+ 	struct iscsi_task *task = conn->task;
+ 	int rc;
+ 
++	if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx))
++		return -ENODATA;
++
+ 	__iscsi_get_task(task);
+ 	spin_unlock_bh(&conn->session->lock);
+ 	rc = conn->session->tt->xmit_task(task);
+@@ -1329,7 +1332,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 	int rc = 0;
+ 
+ 	spin_lock_bh(&conn->session->lock);
+-	if (unlikely(conn->suspend_tx)) {
++	if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) {
+ 		ISCSI_DBG_SESSION(conn->session, "Tx suspended!\n");
+ 		spin_unlock_bh(&conn->session->lock);
+ 		return -ENODATA;
+@@ -1338,7 +1341,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 	if (conn->task) {
+ 		rc = iscsi_xmit_task(conn);
+ 	        if (rc)
+-		        goto again;
++		        goto done;
+ 	}
+ 
+ 	/*
+@@ -1358,7 +1361,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 		}
+ 		rc = iscsi_xmit_task(conn);
+ 		if (rc)
+-			goto again;
++			goto done;
+ 	}
+ 
+ 	/* process pending command queue */
+@@ -1379,14 +1382,14 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 				list_add_tail(&conn->task->running,
+ 					      &conn->cmdqueue);
+ 				conn->task = NULL;
+-				goto again;
++				goto done;
+ 			} else
+ 				fail_scsi_task(conn->task, DID_ABORT);
+ 			continue;
+ 		}
+ 		rc = iscsi_xmit_task(conn);
+ 		if (rc)
+-			goto again;
++			goto done;
+ 		/*
+ 		 * we could continuously get new task requests so
+ 		 * we need to check the mgmt queue for nops that need to
+@@ -1412,16 +1415,14 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 		conn->task->state = ISCSI_TASK_RUNNING;
+ 		rc = iscsi_xmit_task(conn);
+ 		if (rc)
+-			goto again;
++			goto done;
+ 		if (!list_empty(&conn->mgmtqueue))
+ 			goto check_mgmt;
+ 	}
+ 	spin_unlock_bh(&conn->session->lock);
+ 	return -ENODATA;
+ 
+-again:
+-	if (unlikely(conn->suspend_tx))
+-		rc = -ENODATA;
++done:
+ 	spin_unlock_bh(&conn->session->lock);
+ 	return rc;
+ }

commit d1af8a328755f51c9b76157a8692e56520d3fd94
+Author: Mike Christie 
+Date:   Thu Aug 20 15:11:02 2009 -0500
+
+    [SCSI] iscsi_tcp: add new conn error to indicate tcp conn closed
+    
+    If a target closed the connection, we will detect it in the
+    state_changed or data_ready callout. This adds a new conn
+    error value to use for this problem, so it is not confused
+    with when the initiator throws a conn error and drops
+    the connection.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index c7e2ff24ee9e..2b1b834a098b 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -109,11 +109,14 @@ static int iscsi_sw_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+  */
+ static inline int iscsi_sw_sk_state_check(struct sock *sk)
+ {
+-	if ((sk->sk_state == TCP_CLOSE_WAIT ||
+-	     sk->sk_state == TCP_CLOSE) &&
+-	    !atomic_read(&sk->sk_rmem_alloc))
+-		return -ECONNRESET;
++	struct iscsi_conn *conn = (struct iscsi_conn*)sk->sk_user_data;
+ 
++	if ((sk->sk_state == TCP_CLOSE_WAIT || sk->sk_state == TCP_CLOSE) &&
++	    !atomic_read(&sk->sk_rmem_alloc)) {
++		ISCSI_SW_TCP_DBG(conn, "TCP_CLOSE|TCP_CLOSE_WAIT\n");
++		iscsi_conn_failure(conn, ISCSI_ERR_TCP_CONN_CLOSE);
++		return -ECONNRESET;
++	}
+ 	return 0;
+ }
+ 
+@@ -135,11 +138,7 @@ static void iscsi_sw_tcp_data_ready(struct sock *sk, int flag)
+ 	rd_desc.count = 1;
+ 	tcp_read_sock(sk, &rd_desc, iscsi_sw_tcp_recv);
+ 
+-	if (iscsi_sw_sk_state_check(sk) < 0) {
+-		ISCSI_SW_TCP_DBG(conn, "iscsi_tcp_data_ready: "
+-				 "TCP_CLOSE|TCP_CLOSE_WAIT\n");
+-		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+-	}
++	iscsi_sw_sk_state_check(sk);
+ 
+ 	read_unlock(&sk->sk_callback_lock);
+ 
+@@ -161,11 +160,7 @@ static void iscsi_sw_tcp_state_change(struct sock *sk)
+ 	conn = (struct iscsi_conn*)sk->sk_user_data;
+ 	session = conn->session;
+ 
+-	if (iscsi_sw_sk_state_check(sk) < 0) {
+-		ISCSI_SW_TCP_DBG(conn, "iscsi_tcp_state_change: "
+-				 "TCP_CLOSE|TCP_CLOSE_WAIT\n");
+-		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+-	}
++	iscsi_sw_sk_state_check(sk);
+ 
+ 	tcp_conn = conn->dd_data;
+ 	tcp_sw_conn = tcp_conn->dd_data;
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index 4426f00da5ff..d67dda2b6aa0 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -262,6 +262,7 @@ enum iscsi_err {
+ 	ISCSI_ERR_NO_SCSI_CMD		= ISCSI_ERR_BASE + 17,
+ 	ISCSI_ERR_INVALID_HOST		= ISCSI_ERR_BASE + 18,
+ 	ISCSI_ERR_XMIT_FAILED		= ISCSI_ERR_BASE + 19,
++	ISCSI_ERR_TCP_CONN_CLOSE	= ISCSI_ERR_BASE + 20,
+ };
+ 
+ /*

commit 632248aab3170004e24512a4378fc6d9d7f3b4ac
+Author: Mike Christie 
+Date:   Thu Aug 20 15:11:01 2009 -0500
+
+    [SCSI] iscsi class: Add logging to scsi_transport_iscsi.c
+    
+    Logging for connections and sessions in the scsi_transport_iscsi module
+    is now controlled by module parameters.
+    
+    Signed-off-by: Erez Zilber 
+    [Mike Christie: newline fixups and modification of some dbg statements]
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index b47240ca4b19..ad897df36615 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -36,6 +36,38 @@
+ 
+ #define ISCSI_TRANSPORT_VERSION "2.0-870"
+ 
++static int dbg_session;
++module_param_named(debug_session, dbg_session, int,
++		   S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(debug_session,
++		 "Turn on debugging for sessions in scsi_transport_iscsi "
++		 "module. Set to 1 to turn on, and zero to turn off. Default "
++		 "is off.");
++
++static int dbg_conn;
++module_param_named(debug_conn, dbg_conn, int,
++		   S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(debug_conn,
++		 "Turn on debugging for connections in scsi_transport_iscsi "
++		 "module. Set to 1 to turn on, and zero to turn off. Default "
++		 "is off.");
++
++#define ISCSI_DBG_TRANS_SESSION(_session, dbg_fmt, arg...)		\
++	do {								\
++		if (dbg_session)					\
++			iscsi_cls_session_printk(KERN_INFO, _session,	\
++						 "%s: " dbg_fmt,	\
++						 __func__, ##arg);	\
++	} while (0);
++
++#define ISCSI_DBG_TRANS_CONN(_conn, dbg_fmt, arg...)			\
++	do {								\
++		if (dbg_conn)						\
++			iscsi_cls_conn_printk(KERN_INFO, _conn,		\
++					      "%s: " dbg_fmt,		\
++					      __func__, ##arg);	\
++	} while (0);
++
+ struct iscsi_internal {
+ 	struct scsi_transport_template t;
+ 	struct iscsi_transport *iscsi_transport;
+@@ -377,6 +409,7 @@ static void iscsi_session_release(struct device *dev)
+ 
+ 	shost = iscsi_session_to_shost(session);
+ 	scsi_host_put(shost);
++	ISCSI_DBG_TRANS_SESSION(session, "Completing session release\n");
+ 	kfree(session);
+ }
+ 
+@@ -441,6 +474,9 @@ static int iscsi_user_scan_session(struct device *dev, void *data)
+ 		return 0;
+ 
+ 	session = iscsi_dev_to_session(dev);
++
++	ISCSI_DBG_TRANS_SESSION(session, "Scanning session\n");
++
+ 	shost = iscsi_session_to_shost(session);
+ 	ihost = shost->shost_data;
+ 
+@@ -448,8 +484,7 @@ static int iscsi_user_scan_session(struct device *dev, void *data)
+ 	spin_lock_irqsave(&session->lock, flags);
+ 	if (session->state != ISCSI_SESSION_LOGGED_IN) {
+ 		spin_unlock_irqrestore(&session->lock, flags);
+-		mutex_unlock(&ihost->mutex);
+-		return 0;
++		goto user_scan_exit;
+ 	}
+ 	id = session->target_id;
+ 	spin_unlock_irqrestore(&session->lock, flags);
+@@ -462,7 +497,10 @@ static int iscsi_user_scan_session(struct device *dev, void *data)
+ 			scsi_scan_target(&session->dev, 0, id,
+ 					 scan_data->lun, 1);
+ 	}
++
++user_scan_exit:
+ 	mutex_unlock(&ihost->mutex);
++	ISCSI_DBG_TRANS_SESSION(session, "Completed session scan\n");
+ 	return 0;
+ }
+ 
+@@ -522,7 +560,9 @@ static void session_recovery_timedout(struct work_struct *work)
+ 	if (session->transport->session_recovery_timedout)
+ 		session->transport->session_recovery_timedout(session);
+ 
++	ISCSI_DBG_TRANS_SESSION(session, "Unblocking SCSI target\n");
+ 	scsi_target_unblock(&session->dev);
++	ISCSI_DBG_TRANS_SESSION(session, "Completed unblocking SCSI target\n");
+ }
+ 
+ static void __iscsi_unblock_session(struct work_struct *work)
+@@ -534,6 +574,7 @@ static void __iscsi_unblock_session(struct work_struct *work)
+ 	struct iscsi_cls_host *ihost = shost->shost_data;
+ 	unsigned long flags;
+ 
++	ISCSI_DBG_TRANS_SESSION(session, "Unblocking session\n");
+ 	/*
+ 	 * The recovery and unblock work get run from the same workqueue,
+ 	 * so try to cancel it if it was going to run after this unblock.
+@@ -553,6 +594,7 @@ static void __iscsi_unblock_session(struct work_struct *work)
+ 		if (scsi_queue_work(shost, &session->scan_work))
+ 			atomic_inc(&ihost->nr_scans);
+ 	}
++	ISCSI_DBG_TRANS_SESSION(session, "Completed unblocking session\n");
+ }
+ 
+ /**
+@@ -579,10 +621,12 @@ static void __iscsi_block_session(struct work_struct *work)
+ 				     block_work);
+ 	unsigned long flags;
+ 
++	ISCSI_DBG_TRANS_SESSION(session, "Blocking session\n");
+ 	spin_lock_irqsave(&session->lock, flags);
+ 	session->state = ISCSI_SESSION_FAILED;
+ 	spin_unlock_irqrestore(&session->lock, flags);
+ 	scsi_target_block(&session->dev);
++	ISCSI_DBG_TRANS_SESSION(session, "Completed SCSI target blocking\n");
+ 	queue_delayed_work(iscsi_eh_timer_workq, &session->recovery_work,
+ 			   session->recovery_tmo * HZ);
+ }
+@@ -602,6 +646,8 @@ static void __iscsi_unbind_session(struct work_struct *work)
+ 	struct iscsi_cls_host *ihost = shost->shost_data;
+ 	unsigned long flags;
+ 
++	ISCSI_DBG_TRANS_SESSION(session, "Unbinding session\n");
++
+ 	/* Prevent new scans and make sure scanning is not in progress */
+ 	mutex_lock(&ihost->mutex);
+ 	spin_lock_irqsave(&session->lock, flags);
+@@ -616,6 +662,7 @@ static void __iscsi_unbind_session(struct work_struct *work)
+ 
+ 	scsi_remove_target(&session->dev);
+ 	iscsi_session_event(session, ISCSI_KEVENT_UNBIND_SESSION);
++	ISCSI_DBG_TRANS_SESSION(session, "Completed target removal\n");
+ }
+ 
+ struct iscsi_cls_session *
+@@ -647,6 +694,8 @@ iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
+ 	device_initialize(&session->dev);
+ 	if (dd_size)
+ 		session->dd_data = &session[1];
++
++	ISCSI_DBG_TRANS_SESSION(session, "Completed session allocation\n");
+ 	return session;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_alloc_session);
+@@ -712,6 +761,7 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
+ 	spin_unlock_irqrestore(&sesslock, flags);
+ 
+ 	iscsi_session_event(session, ISCSI_KEVENT_CREATE_SESSION);
++	ISCSI_DBG_TRANS_SESSION(session, "Completed session adding\n");
+ 	return 0;
+ 
+ release_host:
+@@ -752,6 +802,7 @@ static void iscsi_conn_release(struct device *dev)
+ 	struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev);
+ 	struct device *parent = conn->dev.parent;
+ 
++	ISCSI_DBG_TRANS_CONN(conn, "Releasing conn\n");
+ 	kfree(conn);
+ 	put_device(parent);
+ }
+@@ -774,6 +825,8 @@ void iscsi_remove_session(struct iscsi_cls_session *session)
+ 	unsigned long flags;
+ 	int err;
+ 
++	ISCSI_DBG_TRANS_SESSION(session, "Removing session\n");
++
+ 	spin_lock_irqsave(&sesslock, flags);
+ 	list_del(&session->sess_list);
+ 	spin_unlock_irqrestore(&sesslock, flags);
+@@ -807,12 +860,15 @@ void iscsi_remove_session(struct iscsi_cls_session *session)
+ 					 "for session. Error %d.\n", err);
+ 
+ 	transport_unregister_device(&session->dev);
++
++	ISCSI_DBG_TRANS_SESSION(session, "Completing session removal\n");
+ 	device_del(&session->dev);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_remove_session);
+ 
+ void iscsi_free_session(struct iscsi_cls_session *session)
+ {
++	ISCSI_DBG_TRANS_SESSION(session, "Freeing session\n");
+ 	iscsi_session_event(session, ISCSI_KEVENT_DESTROY_SESSION);
+ 	put_device(&session->dev);
+ }
+@@ -828,6 +884,7 @@ EXPORT_SYMBOL_GPL(iscsi_free_session);
+ int iscsi_destroy_session(struct iscsi_cls_session *session)
+ {
+ 	iscsi_remove_session(session);
++	ISCSI_DBG_TRANS_SESSION(session, "Completing session destruction\n");
+ 	iscsi_free_session(session);
+ 	return 0;
+ }
+@@ -885,6 +942,8 @@ iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid)
+ 	list_add(&conn->conn_list, &connlist);
+ 	conn->active = 1;
+ 	spin_unlock_irqrestore(&connlock, flags);
++
++	ISCSI_DBG_TRANS_CONN(conn, "Completed conn creation\n");
+ 	return conn;
+ 
+ release_parent_ref:
+@@ -912,6 +971,7 @@ int iscsi_destroy_conn(struct iscsi_cls_conn *conn)
+ 	spin_unlock_irqrestore(&connlock, flags);
+ 
+ 	transport_unregister_device(&conn->dev);
++	ISCSI_DBG_TRANS_CONN(conn, "Completing conn destruction\n");
+ 	device_unregister(&conn->dev);
+ 	return 0;
+ }
+@@ -1200,6 +1260,9 @@ int iscsi_session_event(struct iscsi_cls_session *session,
+ 					 "Cannot notify userspace of session "
+ 					 "event %u. Check iscsi daemon\n",
+ 					 event);
++
++	ISCSI_DBG_TRANS_SESSION(session, "Completed handling event %d rc %d\n",
++				event, rc);
+ 	return rc;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_session_event);
+@@ -1221,6 +1284,8 @@ iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_endpoint *ep,
+ 	shost = iscsi_session_to_shost(session);
+ 	ev->r.c_session_ret.host_no = shost->host_no;
+ 	ev->r.c_session_ret.sid = session->sid;
++	ISCSI_DBG_TRANS_SESSION(session,
++				"Completed creating transport session\n");
+ 	return 0;
+ }
+ 
+@@ -1246,6 +1311,8 @@ iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+ 
+ 	ev->r.c_conn_ret.sid = session->sid;
+ 	ev->r.c_conn_ret.cid = conn->cid;
++
++	ISCSI_DBG_TRANS_CONN(conn, "Completed creating transport conn\n");
+ 	return 0;
+ }
+ 
+@@ -1258,8 +1325,10 @@ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev
+ 	if (!conn)
+ 		return -EINVAL;
+ 
++	ISCSI_DBG_TRANS_CONN(conn, "Destroying transport conn\n");
+ 	if (transport->destroy_conn)
+ 		transport->destroy_conn(conn);
++
+ 	return 0;
+ }
+ 

commit b06fc73a9ebd352065dd4dd3139fb53ed72ac970
+Author: Mike Christie 
+Date:   Thu Aug 20 15:11:00 2009 -0500
+
+    [SCSI] qla4xxx: Removed residual from overrun debug print
+    
+    The residual variable is only valid for udnerrun so do
+    not print it out for the overrun case.
+    
+    Signed-off-by: Karen Higgins 
+    [Mike Christie: Fix coding style issues in patch]
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c
+index 8025ee16588e..c196d55eae39 100644
+--- a/drivers/scsi/qla4xxx/ql4_isr.c
++++ b/drivers/scsi/qla4xxx/ql4_isr.c
+@@ -227,11 +227,11 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
+ 	case SCS_DATA_UNDERRUN:
+ 	case SCS_DATA_OVERRUN:
+ 		if ((sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) ||
+-			(sts_entry->completionStatus == SCS_DATA_OVERRUN)) {
+-			DEBUG2(printk("scsi%ld:%d:%d:%d: %s: " "Data overrun, "
+-				      "residual = 0x%x\n", ha->host_no,
++		     (sts_entry->completionStatus == SCS_DATA_OVERRUN)) {
++			DEBUG2(printk("scsi%ld:%d:%d:%d: %s: " "Data overrun\n",
++				      ha->host_no,
+ 				      cmd->device->channel, cmd->device->id,
+-				      cmd->device->lun, __func__, residual));
++				      cmd->device->lun, __func__));
+ 
+ 			cmd->result = DID_ERROR << 16;
+ 			break;

commit 8afa1439fcff58da8f28c1d083046f229f6ab3de
+Author: Mike Christie 
+Date:   Thu Aug 20 15:10:59 2009 -0500
+
+    [SCSI] libiscsi: handle immediate command rejections
+    
+    If we sent multiple pdus as immediate the target could be
+    rejecting some and we have just been dropping the rejection
+    notification. This adds code to handle nop-out rejections,
+    so if a nop-out was sent as a ping and rejected we do not
+    mark the connection bad. Instead we just clean up the timers
+    since we have pdu making a rount trip we know the connection
+    is good.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index c68cb53a984b..1d7a8b7e8a75 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -857,27 +857,102 @@ static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
+ 	}
+ }
+ 
++static int iscsi_nop_out_rsp(struct iscsi_task *task,
++			     struct iscsi_nopin *nop, char *data, int datalen)
++{
++	struct iscsi_conn *conn = task->conn;
++	int rc = 0;
++
++	if (conn->ping_task != task) {
++		/*
++		 * If this is not in response to one of our
++		 * nops then it must be from userspace.
++		 */
++		if (iscsi_recv_pdu(conn->cls_conn, (struct iscsi_hdr *)nop,
++				   data, datalen))
++			rc = ISCSI_ERR_CONN_FAILED;
++	} else
++		mod_timer(&conn->transport_timer, jiffies + conn->recv_timeout);
++	iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
++	return rc;
++}
++
+ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			       char *data, int datalen)
+ {
+ 	struct iscsi_reject *reject = (struct iscsi_reject *)hdr;
+ 	struct iscsi_hdr rejected_pdu;
++	int opcode, rc = 0;
+ 
+ 	conn->exp_statsn = be32_to_cpu(reject->statsn) + 1;
+ 
+-	if (reject->reason == ISCSI_REASON_DATA_DIGEST_ERROR) {
+-		if (ntoh24(reject->dlength) > datalen)
+-			return ISCSI_ERR_PROTO;
++	if (ntoh24(reject->dlength) > datalen ||
++	    ntoh24(reject->dlength) < sizeof(struct iscsi_hdr)) {
++		iscsi_conn_printk(KERN_ERR, conn, "Cannot handle rejected "
++				  "pdu. Invalid data length (pdu dlength "
++				  "%u, datalen %d\n", ntoh24(reject->dlength),
++				  datalen);
++		return ISCSI_ERR_PROTO;
++	}
++	memcpy(&rejected_pdu, data, sizeof(struct iscsi_hdr));
++	opcode = rejected_pdu.opcode & ISCSI_OPCODE_MASK;
+ 
+-		if (ntoh24(reject->dlength) >= sizeof(struct iscsi_hdr)) {
+-			memcpy(&rejected_pdu, data, sizeof(struct iscsi_hdr));
+-			iscsi_conn_printk(KERN_ERR, conn,
+-					  "pdu (op 0x%x) rejected "
+-					  "due to DataDigest error.\n",
+-					  rejected_pdu.opcode);
++	switch (reject->reason) {
++	case ISCSI_REASON_DATA_DIGEST_ERROR:
++		iscsi_conn_printk(KERN_ERR, conn,
++				  "pdu (op 0x%x itt 0x%x) rejected "
++				  "due to DataDigest error.\n",
++				  rejected_pdu.itt, opcode);
++		break;
++	case ISCSI_REASON_IMM_CMD_REJECT:
++		iscsi_conn_printk(KERN_ERR, conn,
++				  "pdu (op 0x%x itt 0x%x) rejected. Too many "
++				  "immediate commands.\n",
++				  rejected_pdu.itt, opcode);
++		/*
++		 * We only send one TMF at a time so if the target could not
++		 * handle it, then it should get fixed (RFC mandates that
++		 * a target can handle one immediate TMF per conn).
++		 *
++		 * For nops-outs, we could have sent more than one if
++		 * the target is sending us lots of nop-ins
++		 */
++		if (opcode != ISCSI_OP_NOOP_OUT)
++			return 0;
++
++		 if (rejected_pdu.itt == cpu_to_be32(ISCSI_RESERVED_TAG))
++			/*
++			 * nop-out in response to target's nop-out rejected.
++			 * Just resend.
++			 */
++			iscsi_send_nopout(conn,
++					  (struct iscsi_nopin*)&rejected_pdu);
++		else {
++			struct iscsi_task *task;
++			/*
++			 * Our nop as ping got dropped. We know the target
++			 * and transport are ok so just clean up
++			 */
++			task = iscsi_itt_to_task(conn, rejected_pdu.itt);
++			if (!task) {
++				iscsi_conn_printk(KERN_ERR, conn,
++						 "Invalid pdu reject. Could "
++						 "not lookup rejected task.\n");
++				rc = ISCSI_ERR_BAD_ITT;
++			} else
++				rc = iscsi_nop_out_rsp(task,
++					(struct iscsi_nopin*)&rejected_pdu,
++					NULL, 0);
+ 		}
++		break;
++	default:
++		iscsi_conn_printk(KERN_ERR, conn,
++				  "pdu (op 0x%x itt 0x%x) rejected. Reason "
++				  "code 0x%x\n", rejected_pdu.itt,
++				  rejected_pdu.opcode, reject->reason);
++		break;
+ 	}
+-	return 0;
++	return rc;
+ }
+ 
+ /**
+@@ -1038,15 +1113,8 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		}
+ 		conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
+ 
+-		if (conn->ping_task != task)
+-			/*
+-			 * If this is not in response to one of our
+-			 * nops then it must be from userspace.
+-			 */
+-			goto recv_pdu;
+-
+-		mod_timer(&conn->transport_timer, jiffies + conn->recv_timeout);
+-		iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
++		rc = iscsi_nop_out_rsp(task, (struct iscsi_nopin*)hdr,
++				       data, datalen);
+ 		break;
+ 	default:
+ 		rc = ISCSI_ERR_BAD_OPCODE;

commit d3305f3407fa3e9452079ec6cc8379067456e4aa
+Author: Mike Christie 
+Date:   Thu Aug 20 15:10:58 2009 -0500
+
+    [SCSI] libiscsi: don't increment cmdsn if cmd is not sent
+    
+    We increment session->cmdsn at the top of iscsi_prep_scsi_cmd_pdu, but
+    if the prep  ecb or prep bidi or init_task calls fails then we leave the
+    session->cmdsn incremented. This moves the cmdsn manipulation to the end
+    of the function when we know it has succeeded.
+    
+    It also adds a session->cmdsn--; in queuecommand for if a driver like
+    bnx2i tries to send a a task from that context but it fails. We do not
+    have to do this in the xmit thread context because that code will retry
+    the same task if the initial call fails.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index a751f6230c22..c68cb53a984b 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -301,8 +301,6 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
+ 	hdr->flags = ISCSI_ATTR_SIMPLE;
+ 	int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
+ 	memcpy(task->lun, hdr->lun, sizeof(task->lun));
+-	hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn);
+-	session->cmdsn++;
+ 	hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
+ 	cmd_len = sc->cmd_len;
+ 	if (cmd_len < ISCSI_CDB_SIZE)
+@@ -388,6 +386,8 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
+ 		return -EIO;
+ 
+ 	task->state = ISCSI_TASK_RUNNING;
++	hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn);
++	session->cmdsn++;
+ 
+ 	conn->scsicmd_pdus_cnt++;
+ 	ISCSI_DBG_SESSION(session, "iscsi prep [%s cid %d sc %p cdb 0x%x "
+@@ -1497,6 +1497,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 			}
+ 		}
+ 		if (session->tt->xmit_task(task)) {
++			session->cmdsn--;
+ 			reason = FAILURE_SESSION_NOT_READY;
+ 			goto prepd_reject;
+ 		}

commit 3c0d1d94aa516cad50274fe1aa9f745957b67a65
+Author: Mike Christie 
+Date:   Tue Jul 28 23:08:06 2009 -0500
+
+    [SCSI] ALUA: send STPG if explicit and implicit is supported
+    
+    alua_activate only sends a STPG if only explicit is suppored.
+    As a result, for EMC targets that support both we end up doing
+    a implicit failover when X commands are finally sent to
+    the other SP.
+    
+    This patch does a AND on the h->tpgs, so we do a explicit failover
+    right away.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
+index dba154c8ff64..b5cdefaf2608 100644
+--- a/drivers/scsi/device_handler/scsi_dh_alua.c
++++ b/drivers/scsi/device_handler/scsi_dh_alua.c
+@@ -663,7 +663,7 @@ static int alua_activate(struct scsi_device *sdev)
+ 			goto out;
+ 	}
+ 
+-	if (h->tpgs == TPGS_MODE_EXPLICIT && h->state != TPGS_STATE_OPTIMIZED)
++	if (h->tpgs & TPGS_MODE_EXPLICIT && h->state != TPGS_STATE_OPTIMIZED)
+ 		err = alua_stpg(sdev, TPGS_STATE_OPTIMIZED, h);
+ 
+ out:

commit 5c656af7e4edfe44c85034d6fa7002909f9c3c59
+Author: Mike Christie 
+Date:   Wed Jul 15 15:02:59 2009 -0500
+
+    [SCSI] qla4xxx: add timeout handler
+    
+    Recently dm-multipath began calling blk_abort_queue. This causes all the
+    commands/request running on the path to have the timeout function called.
+    If a path does go down, and the LLD returns DID_*, dm-multpiath will eventually
+    get this error and begin to call the cmd timeout handler. qla4xxx currently
+    does not set a timed out handler and so the default one could return
+    BLK_EH_NOT_HANDLED and end up firing the scsi eh and stopping IO to all
+    paths on the host when only one path is affected.
+    
+    For software and offload iscsi we have a timed out handler already.
+    This patch adds a driver specific one to qla4xxx because there
+    are some ddb->state and session->state and command completion races
+    that are better handled in the LLD.
+    
+    This also handles the problem where if the session is down,
+    we do not need the scsi eh to run until the transport code
+    has tried to reconnect us.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index ec9da6ce8489..6841883b3611 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -66,6 +66,7 @@ static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess,
+ static int qla4xxx_host_get_param(struct Scsi_Host *shost,
+ 				  enum iscsi_host_param param, char *buf);
+ static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session);
++static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc);
+ 
+ /*
+  * SCSI host template entry points
+@@ -89,6 +90,7 @@ static struct scsi_host_template qla4xxx_driver_template = {
+ 	.eh_device_reset_handler = qla4xxx_eh_device_reset,
+ 	.eh_target_reset_handler = qla4xxx_eh_target_reset,
+ 	.eh_host_reset_handler	= qla4xxx_eh_host_reset,
++	.eh_timed_out		= qla4xxx_eh_cmd_timed_out,
+ 
+ 	.slave_configure	= qla4xxx_slave_configure,
+ 	.slave_alloc		= qla4xxx_slave_alloc,
+@@ -124,6 +126,21 @@ static struct iscsi_transport qla4xxx_iscsi_transport = {
+ 
+ static struct scsi_transport_template *qla4xxx_scsi_transport;
+ 
++static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc)
++{
++	struct iscsi_cls_session *session;
++	struct ddb_entry *ddb_entry;
++
++	session = starget_to_session(scsi_target(sc->device));
++	ddb_entry = session->dd_data;
++
++	/* if we are not logged in then the LLD is going to clean up the cmd */
++	if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE)
++		return BLK_EH_RESET_TIMER;
++	else
++		return BLK_EH_NOT_HANDLED;
++}
++
+ static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session)
+ {
+ 	struct ddb_entry *ddb_entry = session->dd_data;

commit 6187c242089d334102be76427a5a020240e6c19a
+Author: Mike Christie 
+Date:   Wed Jul 15 15:02:57 2009 -0500
+
+    [SCSI] libiscsi: disable bh in and abort handler.
+    
+    The session lock can be held in the scsi eh thread or the completion
+    paths run from the net softirq. This disables bhs in iscsi_eh_abort when
+    taking the session lock.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 716cc344c5df..a751f6230c22 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1974,10 +1974,10 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 		 * good and have never sent us a successful tmf response
+ 		 * then sent more data for the cmd.
+ 		 */
+-		spin_lock(&session->lock);
++		spin_lock_bh(&session->lock);
+ 		fail_scsi_task(task, DID_ABORT);
+ 		conn->tmf_state = TMF_INITIAL;
+-		spin_unlock(&session->lock);
++		spin_unlock_bh(&session->lock);
+ 		iscsi_start_tx(conn);
+ 		goto success_unlocked;
+ 	case TMF_TIMEDOUT:

commit 32382492eb18e8e20be382a1743d0c08469d1e84
+Author: Mike Christie 
+Date:   Mon Jun 15 22:11:09 2009 -0500
+
+    iscsi_tcp: propogate EAGAIN from sendpage to libiscsi
+    
+    The net layer might return -EAGAIN because it could not
+    get space/mem within the sock sndtimeo or becuase the tcp/ip
+    connection was down. For the latter we do not want to retry
+    because the conn/session should just be shutdown and restarted.
+    libiscsi knows the state of the session recovery so propogate
+    this error to that layer. It will either do iscsi recovery
+    or have us retry the operation. Right now if we have partially
+    sent a pdu we would always retry the IO xmit slowing down
+    recovery.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index b7c092d63bbe..518dbd91df85 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -253,8 +253,6 @@ static int iscsi_sw_tcp_xmit_segment(struct iscsi_tcp_conn *tcp_conn,
+ 
+ 		if (r < 0) {
+ 			iscsi_tcp_segment_unmap(segment);
+-			if (copied || r == -EAGAIN)
+-				break;
+ 			return r;
+ 		}
+ 		copied += r;
+@@ -275,11 +273,17 @@ static int iscsi_sw_tcp_xmit(struct iscsi_conn *conn)
+ 
+ 	while (1) {
+ 		rc = iscsi_sw_tcp_xmit_segment(tcp_conn, segment);
+-		if (rc < 0) {
++		/*
++		 * We may not have been able to send data because the conn
++		 * is getting stopped. libiscsi will know so propogate err
++		 * for it to do the right thing.
++		 */
++		if (rc == -EAGAIN)
++			return rc;
++		else if (rc < 0) {
+ 			rc = ISCSI_ERR_XMIT_FAILED;
+ 			goto error;
+-		}
+-		if (rc == 0)
++		} else if (rc == 0)
+ 			break;
+ 
+ 		consumed += rc;

commit d355e57d58193b89283b0c8153649f0427b0bdad
+Author: Mike Christie 
+Date:   Mon Jun 15 22:11:08 2009 -0500
+
+    libiscsi: don't run scsi eh if iscsi task is making progress
+    
+    If we are sending or receiving data for the task successfully do
+    not run the scsi eh, because we know the task is making progress.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 59908aead531..b55b7991d5fa 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -954,6 +954,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		task = iscsi_itt_to_ctask(conn, hdr->itt);
+ 		if (!task)
+ 			return ISCSI_ERR_BAD_ITT;
++		task->last_xfer = jiffies;
+ 		break;
+ 	case ISCSI_OP_R2T:
+ 		/*
+@@ -1192,10 +1193,12 @@ static int iscsi_xmit_task(struct iscsi_conn *conn)
+ 	spin_unlock_bh(&conn->session->lock);
+ 	rc = conn->session->tt->xmit_task(task);
+ 	spin_lock_bh(&conn->session->lock);
+-	__iscsi_put_task(task);
+-	if (!rc)
++	if (!rc) {
+ 		/* done with this task */
++		task->last_xfer = jiffies;
+ 		conn->task = NULL;
++	}
++	__iscsi_put_task(task);
+ 	return rc;
+ }
+ 
+@@ -1361,6 +1364,9 @@ static inline struct iscsi_task *iscsi_alloc_task(struct iscsi_conn *conn,
+ 	task->state = ISCSI_TASK_PENDING;
+ 	task->conn = conn;
+ 	task->sc = sc;
++	task->have_checked_conn = false;
++	task->last_timeout = jiffies;
++	task->last_xfer = jiffies;
+ 	INIT_LIST_HEAD(&task->running);
+ 	return task;
+ }
+@@ -1716,17 +1722,18 @@ static int iscsi_has_ping_timed_out(struct iscsi_conn *conn)
+ 		return 0;
+ }
+ 
+-static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
++static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
+ {
++	enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED;
++	struct iscsi_task *task = NULL;
+ 	struct iscsi_cls_session *cls_session;
+ 	struct iscsi_session *session;
+ 	struct iscsi_conn *conn;
+-	enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED;
+ 
+-	cls_session = starget_to_session(scsi_target(scmd->device));
++	cls_session = starget_to_session(scsi_target(sc->device));
+ 	session = cls_session->dd_data;
+ 
+-	ISCSI_DBG_SESSION(session, "scsi cmd %p timedout\n", scmd);
++	ISCSI_DBG_SESSION(session, "scsi cmd %p timedout\n", sc);
+ 
+ 	spin_lock(&session->lock);
+ 	if (session->state != ISCSI_STATE_LOGGED_IN) {
+@@ -1745,6 +1752,26 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
+ 		goto done;
+ 	}
+ 
++	task = (struct iscsi_task *)sc->SCp.ptr;
++	if (!task)
++		goto done;
++	/*
++	 * If we have sent (at least queued to the network layer) a pdu or
++	 * recvd one for the task since the last timeout ask for
++	 * more time. If on the next timeout we have not made progress
++	 * we can check if it is the task or connection when we send the
++	 * nop as a ping.
++	 */
++	if (time_after_eq(task->last_xfer, task->last_timeout)) {
++		ISCSI_DBG_CONN(conn, "Command making progress. Asking "
++			       "scsi-ml for more time to complete. "
++			       "Last data recv at %lu. Last timeout was at "
++			       "%lu\n.", task->last_xfer, task->last_timeout);
++		task->have_checked_conn = false;
++		rc = BLK_EH_RESET_TIMER;
++		goto done;
++	}
++
+ 	if (!conn->recv_timeout && !conn->ping_timeout)
+ 		goto done;
+ 	/*
+@@ -1755,20 +1782,29 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
+ 		rc = BLK_EH_RESET_TIMER;
+ 		goto done;
+ 	}
++
++	/* Assumes nop timeout is shorter than scsi cmd timeout */
++	if (task->have_checked_conn)
++		goto done;
++
+ 	/*
+-	 * if we are about to check the transport then give the command
+-	 * more time
++	 * Checking the transport already or nop from a cmd timeout still
++	 * running
+ 	 */
+-	if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ),
+-			   jiffies)) {
++	if (conn->ping_task) {
++		task->have_checked_conn = true;
+ 		rc = BLK_EH_RESET_TIMER;
+ 		goto done;
+ 	}
+ 
+-	/* if in the middle of checking the transport then give us more time */
+-	if (conn->ping_task)
+-		rc = BLK_EH_RESET_TIMER;
++	/* Make sure there is a transport check done */
++	iscsi_send_nopout(conn, NULL);
++	task->have_checked_conn = true;
++	rc = BLK_EH_RESET_TIMER;
++
+ done:
++	if (task)
++		task->last_timeout = jiffies;
+ 	spin_unlock(&session->lock);
+ 	ISCSI_DBG_SESSION(session, "return %s\n", rc == BLK_EH_RESET_TIMER ?
+ 			  "timer reset" : "nh");
+diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
+index 2bc07090321d..2e0746d70303 100644
+--- a/drivers/scsi/libiscsi_tcp.c
++++ b/drivers/scsi/libiscsi_tcp.c
+@@ -686,6 +686,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 				     "offset=%d, datalen=%d)\n",
+ 				      tcp_task->data_offset,
+ 				      tcp_conn->in.datalen);
++			task->last_xfer = jiffies;
+ 			rc = iscsi_segment_seek_sg(&tcp_conn->in.segment,
+ 						   sdb->table.sgl,
+ 						   sdb->table.nents,
+@@ -713,9 +714,10 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 			rc = ISCSI_ERR_BAD_ITT;
+ 		else if (ahslen)
+ 			rc = ISCSI_ERR_AHSLEN;
+-		else if (task->sc->sc_data_direction == DMA_TO_DEVICE)
++		else if (task->sc->sc_data_direction == DMA_TO_DEVICE) {
++			task->last_xfer = jiffies;
+ 			rc = iscsi_tcp_r2t_rsp(conn, task);
+-		else
++		} else
+ 			rc = ISCSI_ERR_PROTO;
+ 		spin_unlock(&conn->session->lock);
+ 		break;
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 196525cd402f..61afeb59a836 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -125,6 +125,10 @@ struct iscsi_task {
+ 	struct scsi_cmnd	*sc;		/* associated SCSI cmd*/
+ 	struct iscsi_conn	*conn;		/* used connection    */
+ 
++	/* data processing tracking */
++	unsigned long		last_xfer;
++	unsigned long		last_timeout;
++	bool			have_checked_conn;
+ 	/* state set/tested under session->lock */
+ 	int			state;
+ 	atomic_t		refcount;

commit d5e6054a0a097527b3920a8a0aefe7f830c014fd
+Author: Mike Christie 
+Date:   Wed May 6 10:52:23 2009 -0700
+
+    [SCSI] libfc: use DID_ERROR when we have internall aborted command
+    
+    If we aborted a command, because it timed out we should not use
+    DID_ABORT. It will fail the command right away back to the upper
+    layer. We want to use something that indicated that the problem
+    did not complete normally, but it was not a fatal problem.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
+index 521f996f9b13..ad8b747837b0 100644
+--- a/drivers/scsi/libfc/fc_fcp.c
++++ b/drivers/scsi/libfc/fc_fcp.c
+@@ -1896,7 +1896,7 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
+ 		sc_cmd->result = (DID_ERROR << 16) | fsp->cdb_status;
+ 		break;
+ 	case FC_CMD_ABORTED:
+-		sc_cmd->result = (DID_ABORT << 16) | fsp->io_status;
++		sc_cmd->result = (DID_ERROR << 16) | fsp->io_status;
+ 		break;
+ 	case FC_CMD_TIME_OUT:
+ 		sc_cmd->result = (DID_BUS_BUSY << 16) | fsp->io_status;

commit 4421c9ebeeacf3d9c4e6aa558e1a777178e71add
+Author: Mike Christie 
+Date:   Wed May 13 17:57:50 2009 -0500
+
+    [SCSI] libiscsi: add debug printks for iscsi command completion path
+    
+    This patch just adds some debug statements for the abort
+    and completion paths.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index b00be6c3efc1..59908aead531 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -393,10 +393,12 @@ static void iscsi_free_task(struct iscsi_task *task)
+ 	struct iscsi_session *session = conn->session;
+ 	struct scsi_cmnd *sc = task->sc;
+ 
++	ISCSI_DBG_SESSION(session, "freeing task itt 0x%x state %d sc %p\n",
++			  task->itt, task->state, task->sc);
++
+ 	session->tt->cleanup_task(task);
+ 	task->state = ISCSI_TASK_FREE;
+ 	task->sc = NULL;
+-
+ 	/*
+ 	 * login task is preallocated so do not free
+ 	 */
+@@ -451,6 +453,9 @@ static void iscsi_complete_task(struct iscsi_task *task, int state)
+ {
+ 	struct iscsi_conn *conn = task->conn;
+ 
++	ISCSI_DBG_SESSION(conn->session,
++			  "complete task itt 0x%x state %d sc %p\n",
++			  task->itt, task->state, task->sc);
+ 	if (task->state == ISCSI_TASK_COMPLETED ||
+ 	    task->state == ISCSI_TASK_ABRT_TMF ||
+ 	    task->state == ISCSI_TASK_ABRT_SESS_RECOV)
+@@ -1836,6 +1841,8 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 	cls_session = starget_to_session(scsi_target(sc->device));
+ 	session = cls_session->dd_data;
+ 
++	ISCSI_DBG_SESSION(session, "aborting sc %p\n", sc);
++
+ 	mutex_lock(&session->eh_mutex);
+ 	spin_lock_bh(&session->lock);
+ 	/*
+@@ -1858,6 +1865,8 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 	    sc->SCp.phase != session->age) {
+ 		spin_unlock_bh(&session->lock);
+ 		mutex_unlock(&session->eh_mutex);
++		ISCSI_DBG_SESSION(session, "failing abort due to dropped "
++				  "session.\n");
+ 		return FAILED;
+ 	}
+ 

commit b3cd5050bf8eb32ceecee129cac7c59e6f1668c4
+Author: Mike Christie 
+Date:   Wed May 13 17:57:49 2009 -0500
+
+    [SCSI] libiscsi: add task aborted state
+    
+    If a task did not complete normally due to a TMF, libiscsi will
+    now complete the task with the state ISCSI_TASK_ABRT_TMF. Drivers
+    like bnx2i that need to free resources if a command did not complete normally
+    can then check the task state. If a driver does not need to send
+    a special command if we have dropped the session then they can check
+    for ISCSI_TASK_ABRT_SESS_RECOV.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index ffbe0c76bc11..0ba6ec876296 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -257,11 +257,8 @@ static void iscsi_iser_cleanup_task(struct iscsi_task *task)
+ {
+ 	struct iscsi_iser_task *iser_task = task->dd_data;
+ 
+-	/*
+-	 * mgmt tasks do not need special cleanup and we do not
+-	 * allocate anything in the init task callout
+-	 */
+-	if (!task->sc || task->state == ISCSI_TASK_PENDING)
++	/* mgmt tasks do not need special cleanup */
++	if (!task->sc)
+ 		return;
+ 
+ 	if (iser_task->status == ISER_TASK_STATUS_STARTED) {
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index dafa054537f6..b00be6c3efc1 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -443,18 +443,20 @@ EXPORT_SYMBOL_GPL(iscsi_put_task);
+ /**
+  * iscsi_complete_task - finish a task
+  * @task: iscsi cmd task
++ * @state: state to complete task with
+  *
+  * Must be called with session lock.
+  */
+-static void iscsi_complete_task(struct iscsi_task *task)
++static void iscsi_complete_task(struct iscsi_task *task, int state)
+ {
+ 	struct iscsi_conn *conn = task->conn;
+ 
+-	if (task->state == ISCSI_TASK_COMPLETED)
++	if (task->state == ISCSI_TASK_COMPLETED ||
++	    task->state == ISCSI_TASK_ABRT_TMF ||
++	    task->state == ISCSI_TASK_ABRT_SESS_RECOV)
+ 		return;
+ 	WARN_ON_ONCE(task->state == ISCSI_TASK_FREE);
+-
+-	task->state = ISCSI_TASK_COMPLETED;
++	task->state = state;
+ 
+ 	if (!list_empty(&task->running))
+ 		list_del_init(&task->running);
+@@ -478,6 +480,7 @@ static void fail_scsi_task(struct iscsi_task *task, int err)
+ {
+ 	struct iscsi_conn *conn = task->conn;
+ 	struct scsi_cmnd *sc;
++	int state;
+ 
+ 	/*
+ 	 * if a command completes and we get a successful tmf response
+@@ -488,14 +491,20 @@ static void fail_scsi_task(struct iscsi_task *task, int err)
+ 	if (!sc)
+ 		return;
+ 
+-	if (task->state == ISCSI_TASK_PENDING)
++	if (task->state == ISCSI_TASK_PENDING) {
+ 		/*
+ 		 * cmd never made it to the xmit thread, so we should not count
+ 		 * the cmd in the sequencing
+ 		 */
+ 		conn->session->queued_cmdsn--;
++		/* it was never sent so just complete like normal */
++		state = ISCSI_TASK_COMPLETED;
++	} else if (err == DID_TRANSPORT_DISRUPTED)
++		state = ISCSI_TASK_ABRT_SESS_RECOV;
++	else
++		state = ISCSI_TASK_ABRT_TMF;
+ 
+-	sc->result = err;
++	sc->result = err << 16;
+ 	if (!scsi_bidi_cmnd(sc))
+ 		scsi_set_resid(sc, scsi_bufflen(sc));
+ 	else {
+@@ -503,7 +512,7 @@ static void fail_scsi_task(struct iscsi_task *task, int err)
+ 		scsi_in(sc)->resid = scsi_in(sc)->length;
+ 	}
+ 
+-	iscsi_complete_task(task);
++	iscsi_complete_task(task, state);
+ }
+ 
+ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn,
+@@ -731,7 +740,7 @@ static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	ISCSI_DBG_SESSION(session, "cmd rsp done [sc %p res %d itt 0x%x]\n",
+ 			  sc, sc->result, task->itt);
+ 	conn->scsirsp_pdus_cnt++;
+-	iscsi_complete_task(task);
++	iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
+ }
+ 
+ /**
+@@ -769,7 +778,7 @@ iscsi_data_in_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			  "[sc %p res %d itt 0x%x]\n",
+ 			  sc, sc->result, task->itt);
+ 	conn->scsirsp_pdus_cnt++;
+-	iscsi_complete_task(task);
++	iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
+ }
+ 
+ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+@@ -990,7 +999,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		}
+ 
+ 		iscsi_tmf_rsp(conn, hdr);
+-		iscsi_complete_task(task);
++		iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
+ 		break;
+ 	case ISCSI_OP_NOOP_IN:
+ 		iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
+@@ -1008,7 +1017,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			goto recv_pdu;
+ 
+ 		mod_timer(&conn->transport_timer, jiffies + conn->recv_timeout);
+-		iscsi_complete_task(task);
++		iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
+ 		break;
+ 	default:
+ 		rc = ISCSI_ERR_BAD_OPCODE;
+@@ -1020,7 +1029,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ recv_pdu:
+ 	if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen))
+ 		rc = ISCSI_ERR_CONN_FAILED;
+-	iscsi_complete_task(task);
++	iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
+ 	return rc;
+ }
+ EXPORT_SYMBOL_GPL(__iscsi_complete_pdu);
+@@ -1262,7 +1271,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 					 struct iscsi_task, running);
+ 		list_del_init(&conn->task->running);
+ 		if (conn->session->state == ISCSI_STATE_LOGGING_OUT) {
+-			fail_scsi_task(conn->task, DID_IMM_RETRY << 16);
++			fail_scsi_task(conn->task, DID_IMM_RETRY);
+ 			continue;
+ 		}
+ 		rc = iscsi_prep_scsi_cmd_pdu(conn->task);
+@@ -1273,7 +1282,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 				conn->task = NULL;
+ 				goto again;
+ 			} else
+-				fail_scsi_task(conn->task, DID_ABORT << 16);
++				fail_scsi_task(conn->task, DID_ABORT);
+ 			continue;
+ 		}
+ 		rc = iscsi_xmit_task(conn);
+@@ -1469,7 +1478,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 
+ prepd_reject:
+ 	sc->scsi_done = NULL;
+-	iscsi_complete_task(task);
++	iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
+ reject:
+ 	spin_unlock(&session->lock);
+ 	ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n",
+@@ -1479,7 +1488,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 
+ prepd_fault:
+ 	sc->scsi_done = NULL;
+-	iscsi_complete_task(task);
++	iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
+ fault:
+ 	spin_unlock(&session->lock);
+ 	ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n",
+@@ -1665,7 +1674,7 @@ static void fail_scsi_tasks(struct iscsi_conn *conn, unsigned lun,
+ 		ISCSI_DBG_SESSION(conn->session,
+ 				  "failing sc %p itt 0x%x state %d\n",
+ 				  task->sc, task->itt, task->state);
+-		fail_scsi_task(task, error << 16);
++		fail_scsi_task(task, error);
+ 	}
+ }
+ 
+@@ -1868,7 +1877,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 	}
+ 
+ 	if (task->state == ISCSI_TASK_PENDING) {
+-		fail_scsi_task(task, DID_ABORT << 16);
++		fail_scsi_task(task, DID_ABORT);
+ 		goto success;
+ 	}
+ 
+@@ -1899,7 +1908,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 		 * then sent more data for the cmd.
+ 		 */
+ 		spin_lock(&session->lock);
+-		fail_scsi_task(task, DID_ABORT << 16);
++		fail_scsi_task(task, DID_ABORT);
+ 		conn->tmf_state = TMF_INITIAL;
+ 		spin_unlock(&session->lock);
+ 		iscsi_start_tx(conn);
+@@ -2572,7 +2581,7 @@ static void
+ fail_mgmt_tasks(struct iscsi_session *session, struct iscsi_conn *conn)
+ {
+ 	struct iscsi_task *task;
+-	int i;
++	int i, state;
+ 
+ 	for (i = 0; i < conn->session->cmds_max; i++) {
+ 		task = conn->session->cmds[i];
+@@ -2585,7 +2594,11 @@ fail_mgmt_tasks(struct iscsi_session *session, struct iscsi_conn *conn)
+ 		ISCSI_DBG_SESSION(conn->session,
+ 				  "failing mgmt itt 0x%x state %d\n",
+ 				  task->itt, task->state);
+-		iscsi_complete_task(task);
++		state = ISCSI_TASK_ABRT_SESS_RECOV;
++		if (task->state == ISCSI_TASK_PENDING)
++			state = ISCSI_TASK_COMPLETED;
++		iscsi_complete_task(task, state);
++
+ 	}
+ }
+ 
+@@ -2642,10 +2655,7 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ 	 * flush queues.
+ 	 */
+ 	spin_lock_bh(&session->lock);
+-	if (flag == STOP_CONN_RECOVER)
+-		fail_scsi_tasks(conn, -1, DID_TRANSPORT_DISRUPTED);
+-	else
+-		fail_scsi_tasks(conn, -1, DID_ERROR);
++	fail_scsi_tasks(conn, -1, DID_TRANSPORT_DISRUPTED);
+ 	fail_mgmt_tasks(session, conn);
+ 	spin_unlock_bh(&session->lock);
+ 	mutex_unlock(&session->eh_mutex);
+diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
+index b84a1d853f29..2bc07090321d 100644
+--- a/drivers/scsi/libiscsi_tcp.c
++++ b/drivers/scsi/libiscsi_tcp.c
+@@ -440,8 +440,8 @@ void iscsi_tcp_cleanup_task(struct iscsi_task *task)
+ 	struct iscsi_tcp_task *tcp_task = task->dd_data;
+ 	struct iscsi_r2t_info *r2t;
+ 
+-	/* nothing to do for mgmt or pending tasks */
+-	if (!task->sc || task->state == ISCSI_TASK_PENDING)
++	/* nothing to do for mgmt */
++	if (!task->sc)
+ 		return;
+ 
+ 	/* flush task's r2t queues */
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index facae71183a5..196525cd402f 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -86,6 +86,8 @@ enum {
+ 	ISCSI_TASK_COMPLETED,
+ 	ISCSI_TASK_PENDING,
+ 	ISCSI_TASK_RUNNING,
++	ISCSI_TASK_ABRT_TMF,		/* aborted due to TMF */
++	ISCSI_TASK_ABRT_SESS_RECOV,	/* aborted due to session recovery */
+ };
+ 
+ struct iscsi_r2t_info {

commit 1336aed10b8af791378b017f0fa8da4e5b827b8d
+Author: Mike Christie 
+Date:   Wed May 13 17:57:48 2009 -0500
+
+    [SCSI] libiscsi: check if iscsi host has work queue before queueing work
+    
+    Instead of having libiscsi check if the offload bit is set, have
+    it check if the lld created a work queue. I think this is more
+    clear.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 57eb3af40e96..dafa054537f6 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -81,7 +81,8 @@ inline void iscsi_conn_queue_work(struct iscsi_conn *conn)
+ 	struct Scsi_Host *shost = conn->session->host;
+ 	struct iscsi_host *ihost = shost_priv(shost);
+ 
+-	queue_work(ihost->workq, &conn->xmitwork);
++	if (ihost->workq)
++		queue_work(ihost->workq, &conn->xmitwork);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_conn_queue_work);
+ 
+@@ -110,10 +111,8 @@ iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
+ 		 * xmit thread
+ 		 */
+ 		if (!list_empty(&session->leadconn->cmdqueue) ||
+-		    !list_empty(&session->leadconn->mgmtqueue)) {
+-			if (!(session->tt->caps & CAP_DATA_PATH_OFFLOAD))
+-				iscsi_conn_queue_work(session->leadconn);
+-		}
++		    !list_empty(&session->leadconn->mgmtqueue))
++			iscsi_conn_queue_work(session->leadconn);
+ 	}
+ }
+ EXPORT_SYMBOL_GPL(iscsi_update_cmdsn);
+@@ -555,6 +554,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		      char *data, uint32_t data_size)
+ {
+ 	struct iscsi_session *session = conn->session;
++	struct iscsi_host *ihost = shost_priv(session->host);
+ 	struct iscsi_task *task;
+ 	itt_t itt;
+ 
+@@ -618,7 +618,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 						   task->conn->session->age);
+ 	}
+ 
+-	if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) {
++	if (!ihost->workq) {
+ 		if (iscsi_prep_mgmt_task(conn, task))
+ 			goto free_task;
+ 
+@@ -1368,6 +1368,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ {
+ 	struct iscsi_cls_session *cls_session;
+ 	struct Scsi_Host *host;
++	struct iscsi_host *ihost;
+ 	int reason = 0;
+ 	struct iscsi_session *session;
+ 	struct iscsi_conn *conn;
+@@ -1378,6 +1379,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 	sc->SCp.ptr = NULL;
+ 
+ 	host = sc->device->host;
++	ihost = shost_priv(host);
+ 	spin_unlock(host->host_lock);
+ 
+ 	cls_session = starget_to_session(scsi_target(sc->device));
+@@ -1440,7 +1442,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 		goto reject;
+ 	}
+ 
+-	if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) {
++	if (!ihost->workq) {
+ 		reason = iscsi_prep_scsi_cmd_pdu(task);
+ 		if (reason) {
+ 			if (reason == -ENOMEM) {
+@@ -1673,7 +1675,7 @@ void iscsi_suspend_tx(struct iscsi_conn *conn)
+ 	struct iscsi_host *ihost = shost_priv(shost);
+ 
+ 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+-	if (!(conn->session->tt->caps & CAP_DATA_PATH_OFFLOAD))
++	if (ihost->workq)
+ 		flush_workqueue(ihost->workq);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_suspend_tx);
+@@ -1681,8 +1683,7 @@ EXPORT_SYMBOL_GPL(iscsi_suspend_tx);
+ static void iscsi_start_tx(struct iscsi_conn *conn)
+ {
+ 	clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+-	if (!(conn->session->tt->caps & CAP_DATA_PATH_OFFLOAD))
+-		iscsi_conn_queue_work(conn);
++	iscsi_conn_queue_work(conn);
+ }
+ 
+ /*

commit 301e0f7e4d78e956c58b66888e134dbdb44ea28e
+Author: Mike Christie 
+Date:   Wed May 13 17:57:47 2009 -0500
+
+    [SCSI] libiscsi: don't let io sit in queue when session has failed
+    
+    If the session is failed, but we have not yet fully transitioned
+    to the recovery stage we were still queueuing IO. The idea is
+    that for some failures we can recvover at the command level
+    and still continue to execute other IO. Well, we never have
+    added the recovery within a command code, so queueing up IO here
+    just creates the possibility that it might time time out so
+    this just has us requeue the IO the scsi layer for now.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index a9d7e520e551..57eb3af40e96 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1390,13 +1390,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 		goto fault;
+ 	}
+ 
+-	/*
+-	 * ISCSI_STATE_FAILED is a temp. state. The recovery
+-	 * code will decide what is best to do with command queued
+-	 * during this time
+-	 */
+-	if (session->state != ISCSI_STATE_LOGGED_IN &&
+-	    session->state != ISCSI_STATE_FAILED) {
++	if (session->state != ISCSI_STATE_LOGGED_IN) {
+ 		/*
+ 		 * to handle the race between when we set the recovery state
+ 		 * and block the session we requeue here (commands could
+@@ -1404,12 +1398,15 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 		 * up because the block code is not locked)
+ 		 */
+ 		switch (session->state) {
++		case ISCSI_STATE_FAILED:
+ 		case ISCSI_STATE_IN_RECOVERY:
+ 			reason = FAILURE_SESSION_IN_RECOVERY;
+-			goto reject;
++			sc->result = DID_IMM_RETRY << 16;
++			break;
+ 		case ISCSI_STATE_LOGGING_OUT:
+ 			reason = FAILURE_SESSION_LOGGING_OUT;
+-			goto reject;
++			sc->result = DID_IMM_RETRY << 16;
++			break;
+ 		case ISCSI_STATE_RECOVERY_FAILED:
+ 			reason = FAILURE_SESSION_RECOVERY_TIMEOUT;
+ 			sc->result = DID_TRANSPORT_FAILFAST << 16;

commit 3bbaaad95fd38dedb7c66a601f14825b4e0c5a59
+Author: Mike Christie 
+Date:   Wed May 13 17:57:46 2009 -0500
+
+    [SCSI] libiscsi: handle cleanup task races
+    
+    bnx2i needs to send a hardware specific cleanup command if
+    a command has not completed normally (iscsi/scsi response from
+    target), and the session is still ok (this is the case when we
+    send a TMF to stop the command).
+    
+    At this time it will need to drop the session lock. The problem
+    with the current code is that fail_all_commands assumes we
+    will hold the lock the entire time, so it uses list_for_each_entry_safe.
+    If while bnx2i drops the session lock multiple cmds complete then
+    list_for_each_entry_safe will not handle this correctly.
+    
+    This patch removes the running lists and just has us loop over
+    the cmds array (in later patches we will then replace that
+    array with a block tag map at the session level). It also fixes
+    up the completion path so that if the TMF code and the normal recv
+    path were completing the same command then they both do not try
+    to do release the refcount taken when the task is queued.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index c648bd328a21..a9d7e520e551 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -109,7 +109,7 @@ iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
+ 		 * if the window closed with IO queued, then kick the
+ 		 * xmit thread
+ 		 */
+-		if (!list_empty(&session->leadconn->xmitqueue) ||
++		if (!list_empty(&session->leadconn->cmdqueue) ||
+ 		    !list_empty(&session->leadconn->mgmtqueue)) {
+ 			if (!(session->tt->caps & CAP_DATA_PATH_OFFLOAD))
+ 				iscsi_conn_queue_work(session->leadconn);
+@@ -366,7 +366,6 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
+ 		return -EIO;
+ 
+ 	task->state = ISCSI_TASK_RUNNING;
+-	list_move_tail(&task->running, &conn->run_list);
+ 
+ 	conn->scsicmd_pdus_cnt++;
+ 	ISCSI_DBG_SESSION(session, "iscsi prep [%s cid %d sc %p cdb 0x%x "
+@@ -382,26 +381,23 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
+ }
+ 
+ /**
+- * iscsi_complete_command - finish a task
++ * iscsi_free_task - free a task
+  * @task: iscsi cmd task
+  *
+  * Must be called with session lock.
+  * This function returns the scsi command to scsi-ml or cleans
+  * up mgmt tasks then returns the task to the pool.
+  */
+-static void iscsi_complete_command(struct iscsi_task *task)
++static void iscsi_free_task(struct iscsi_task *task)
+ {
+ 	struct iscsi_conn *conn = task->conn;
+ 	struct iscsi_session *session = conn->session;
+ 	struct scsi_cmnd *sc = task->sc;
+ 
+ 	session->tt->cleanup_task(task);
+-	list_del_init(&task->running);
+-	task->state = ISCSI_TASK_COMPLETED;
++	task->state = ISCSI_TASK_FREE;
+ 	task->sc = NULL;
+ 
+-	if (conn->task == task)
+-		conn->task = NULL;
+ 	/*
+ 	 * login task is preallocated so do not free
+ 	 */
+@@ -410,9 +406,6 @@ static void iscsi_complete_command(struct iscsi_task *task)
+ 
+ 	__kfifo_put(session->cmdpool.queue, (void*)&task, sizeof(void*));
+ 
+-	if (conn->ping_task == task)
+-		conn->ping_task = NULL;
+-
+ 	if (sc) {
+ 		task->sc = NULL;
+ 		/* SCSI eh reuses commands to verify us */
+@@ -435,7 +428,7 @@ EXPORT_SYMBOL_GPL(__iscsi_get_task);
+ static void __iscsi_put_task(struct iscsi_task *task)
+ {
+ 	if (atomic_dec_and_test(&task->refcount))
+-		iscsi_complete_command(task);
++		iscsi_free_task(task);
+ }
+ 
+ void iscsi_put_task(struct iscsi_task *task)
+@@ -448,14 +441,50 @@ void iscsi_put_task(struct iscsi_task *task)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_put_task);
+ 
++/**
++ * iscsi_complete_task - finish a task
++ * @task: iscsi cmd task
++ *
++ * Must be called with session lock.
++ */
++static void iscsi_complete_task(struct iscsi_task *task)
++{
++	struct iscsi_conn *conn = task->conn;
++
++	if (task->state == ISCSI_TASK_COMPLETED)
++		return;
++	WARN_ON_ONCE(task->state == ISCSI_TASK_FREE);
++
++	task->state = ISCSI_TASK_COMPLETED;
++
++	if (!list_empty(&task->running))
++		list_del_init(&task->running);
++
++	if (conn->task == task)
++		conn->task = NULL;
++
++	if (conn->ping_task == task)
++		conn->ping_task = NULL;
++
++	/* release get from queueing */
++	__iscsi_put_task(task);
++}
++
+ /*
+- * session lock must be held
++ * session lock must be held and if not called for a task that is
++ * still pending or from the xmit thread, then xmit thread must
++ * be suspended.
+  */
+-static void fail_command(struct iscsi_conn *conn, struct iscsi_task *task,
+-			 int err)
++static void fail_scsi_task(struct iscsi_task *task, int err)
+ {
++	struct iscsi_conn *conn = task->conn;
+ 	struct scsi_cmnd *sc;
+ 
++	/*
++	 * if a command completes and we get a successful tmf response
++	 * we will hit this because the scsi eh abort code does not take
++	 * a ref to the task.
++	 */
+ 	sc = task->sc;
+ 	if (!sc)
+ 		return;
+@@ -475,10 +504,7 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_task *task,
+ 		scsi_in(sc)->resid = scsi_in(sc)->length;
+ 	}
+ 
+-	if (conn->task == task)
+-		conn->task = NULL;
+-	/* release ref from queuecommand */
+-	__iscsi_put_task(task);
++	iscsi_complete_task(task);
+ }
+ 
+ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn,
+@@ -518,7 +544,6 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn,
+ 		session->state = ISCSI_STATE_LOGGING_OUT;
+ 
+ 	task->state = ISCSI_TASK_RUNNING;
+-	list_move_tail(&task->running, &conn->mgmt_run_list);
+ 	ISCSI_DBG_SESSION(session, "mgmtpdu [op 0x%x hdr->itt 0x%x "
+ 			  "datalen %d]\n", hdr->opcode & ISCSI_OPCODE_MASK,
+ 			  hdr->itt, task->data_count);
+@@ -564,6 +589,8 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	atomic_set(&task->refcount, 1);
+ 	task->conn = conn;
+ 	task->sc = NULL;
++	INIT_LIST_HEAD(&task->running);
++	task->state = ISCSI_TASK_PENDING;
+ 
+ 	if (data_size) {
+ 		memcpy(task->data, data, data_size);
+@@ -575,7 +602,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		if (conn->session->tt->alloc_pdu(task, hdr->opcode)) {
+ 			iscsi_conn_printk(KERN_ERR, conn, "Could not allocate "
+ 					 "pdu for mgmt task.\n");
+-			goto requeue_task;
++			goto free_task;
+ 		}
+ 	}
+ 
+@@ -591,30 +618,22 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 						   task->conn->session->age);
+ 	}
+ 
+-	INIT_LIST_HEAD(&task->running);
+-	list_add_tail(&task->running, &conn->mgmtqueue);
+-
+ 	if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) {
+ 		if (iscsi_prep_mgmt_task(conn, task))
+ 			goto free_task;
+ 
+ 		if (session->tt->xmit_task(task))
+ 			goto free_task;
+-
+-	} else
++	} else {
++		list_add_tail(&task->running, &conn->mgmtqueue);
+ 		iscsi_conn_queue_work(conn);
++	}
+ 
+ 	return task;
+ 
+ free_task:
+ 	__iscsi_put_task(task);
+ 	return NULL;
+-
+-requeue_task:
+-	if (task != conn->login_task)
+-		__kfifo_put(session->cmdpool.queue, (void*)&task,
+-			    sizeof(void*));
+-	return NULL;
+ }
+ 
+ int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
+@@ -709,11 +728,10 @@ static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+ 	}
+ out:
+-	ISCSI_DBG_SESSION(session, "done [sc %p res %d itt 0x%x]\n",
++	ISCSI_DBG_SESSION(session, "cmd rsp done [sc %p res %d itt 0x%x]\n",
+ 			  sc, sc->result, task->itt);
+ 	conn->scsirsp_pdus_cnt++;
+-
+-	__iscsi_put_task(task);
++	iscsi_complete_task(task);
+ }
+ 
+ /**
+@@ -747,8 +765,11 @@ iscsi_data_in_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+ 	}
+ 
++	ISCSI_DBG_SESSION(conn->session, "data in with status done "
++			  "[sc %p res %d itt 0x%x]\n",
++			  sc, sc->result, task->itt);
+ 	conn->scsirsp_pdus_cnt++;
+-	__iscsi_put_task(task);
++	iscsi_complete_task(task);
+ }
+ 
+ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+@@ -969,7 +990,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		}
+ 
+ 		iscsi_tmf_rsp(conn, hdr);
+-		__iscsi_put_task(task);
++		iscsi_complete_task(task);
+ 		break;
+ 	case ISCSI_OP_NOOP_IN:
+ 		iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
+@@ -987,7 +1008,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			goto recv_pdu;
+ 
+ 		mod_timer(&conn->transport_timer, jiffies + conn->recv_timeout);
+-		__iscsi_put_task(task);
++		iscsi_complete_task(task);
+ 		break;
+ 	default:
+ 		rc = ISCSI_ERR_BAD_OPCODE;
+@@ -999,7 +1020,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ recv_pdu:
+ 	if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen))
+ 		rc = ISCSI_ERR_CONN_FAILED;
+-	__iscsi_put_task(task);
++	iscsi_complete_task(task);
+ 	return rc;
+ }
+ EXPORT_SYMBOL_GPL(__iscsi_complete_pdu);
+@@ -1176,7 +1197,12 @@ void iscsi_requeue_task(struct iscsi_task *task)
+ {
+ 	struct iscsi_conn *conn = task->conn;
+ 
+-	list_move_tail(&task->running, &conn->requeue);
++	/*
++	 * this may be on the requeue list already if the xmit_task callout
++	 * is handling the r2ts while we are adding new ones
++	 */
++	if (list_empty(&task->running))
++		list_add_tail(&task->running, &conn->requeue);
+ 	iscsi_conn_queue_work(conn);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_requeue_task);
+@@ -1216,6 +1242,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 	while (!list_empty(&conn->mgmtqueue)) {
+ 		conn->task = list_entry(conn->mgmtqueue.next,
+ 					 struct iscsi_task, running);
++		list_del_init(&conn->task->running);
+ 		if (iscsi_prep_mgmt_task(conn, conn->task)) {
+ 			__iscsi_put_task(conn->task);
+ 			conn->task = NULL;
+@@ -1227,23 +1254,26 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 	}
+ 
+ 	/* process pending command queue */
+-	while (!list_empty(&conn->xmitqueue)) {
++	while (!list_empty(&conn->cmdqueue)) {
+ 		if (conn->tmf_state == TMF_QUEUED)
+ 			break;
+ 
+-		conn->task = list_entry(conn->xmitqueue.next,
++		conn->task = list_entry(conn->cmdqueue.next,
+ 					 struct iscsi_task, running);
++		list_del_init(&conn->task->running);
+ 		if (conn->session->state == ISCSI_STATE_LOGGING_OUT) {
+-			fail_command(conn, conn->task, DID_IMM_RETRY << 16);
++			fail_scsi_task(conn->task, DID_IMM_RETRY << 16);
+ 			continue;
+ 		}
+ 		rc = iscsi_prep_scsi_cmd_pdu(conn->task);
+ 		if (rc) {
+ 			if (rc == -ENOMEM) {
++				list_add_tail(&conn->task->running,
++					      &conn->cmdqueue);
+ 				conn->task = NULL;
+ 				goto again;
+ 			} else
+-				fail_command(conn, conn->task, DID_ABORT << 16);
++				fail_scsi_task(conn->task, DID_ABORT << 16);
+ 			continue;
+ 		}
+ 		rc = iscsi_xmit_task(conn);
+@@ -1270,8 +1300,8 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 
+ 		conn->task = list_entry(conn->requeue.next,
+ 					 struct iscsi_task, running);
++		list_del_init(&conn->task->running);
+ 		conn->task->state = ISCSI_TASK_RUNNING;
+-		list_move_tail(conn->requeue.next, &conn->run_list);
+ 		rc = iscsi_xmit_task(conn);
+ 		if (rc)
+ 			goto again;
+@@ -1412,7 +1442,6 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 		reason = FAILURE_OOM;
+ 		goto reject;
+ 	}
+-	list_add_tail(&task->running, &conn->xmitqueue);
+ 
+ 	if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) {
+ 		reason = iscsi_prep_scsi_cmd_pdu(task);
+@@ -1429,8 +1458,10 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 			reason = FAILURE_SESSION_NOT_READY;
+ 			goto prepd_reject;
+ 		}
+-	} else
++	} else {
++		list_add_tail(&task->running, &conn->cmdqueue);
+ 		iscsi_conn_queue_work(conn);
++	}
+ 
+ 	session->queued_cmdsn++;
+ 	spin_unlock(&session->lock);
+@@ -1439,7 +1470,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 
+ prepd_reject:
+ 	sc->scsi_done = NULL;
+-	iscsi_complete_command(task);
++	iscsi_complete_task(task);
+ reject:
+ 	spin_unlock(&session->lock);
+ 	ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n",
+@@ -1449,7 +1480,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 
+ prepd_fault:
+ 	sc->scsi_done = NULL;
+-	iscsi_complete_command(task);
++	iscsi_complete_task(task);
+ fault:
+ 	spin_unlock(&session->lock);
+ 	ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n",
+@@ -1618,44 +1649,24 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn,
+  * Fail commands. session lock held and recv side suspended and xmit
+  * thread flushed
+  */
+-static void fail_all_commands(struct iscsi_conn *conn, unsigned lun,
+-			      int error)
++static void fail_scsi_tasks(struct iscsi_conn *conn, unsigned lun,
++			    int error)
+ {
+-	struct iscsi_task *task, *tmp;
+-
+-	if (conn->task) {
+-		if (lun == -1 ||
+-		    (conn->task->sc && conn->task->sc->device->lun == lun))
+-			conn->task = NULL;
+-	}
++	struct iscsi_task *task;
++	int i;
+ 
+-	/* flush pending */
+-	list_for_each_entry_safe(task, tmp, &conn->xmitqueue, running) {
+-		if (lun == task->sc->device->lun || lun == -1) {
+-			ISCSI_DBG_SESSION(conn->session,
+-					  "failing pending sc %p itt 0x%x\n",
+-					  task->sc, task->itt);
+-			fail_command(conn, task, error << 16);
+-		}
+-	}
++	for (i = 0; i < conn->session->cmds_max; i++) {
++		task = conn->session->cmds[i];
++		if (!task->sc || task->state == ISCSI_TASK_FREE)
++			continue;
+ 
+-	list_for_each_entry_safe(task, tmp, &conn->requeue, running) {
+-		if (lun == task->sc->device->lun || lun == -1) {
+-			ISCSI_DBG_SESSION(conn->session,
+-					  "failing requeued sc %p itt 0x%x\n",
+-					  task->sc, task->itt);
+-			fail_command(conn, task, error << 16);
+-		}
+-	}
++		if (lun != -1 && lun != task->sc->device->lun)
++			continue;
+ 
+-	/* fail all other running */
+-	list_for_each_entry_safe(task, tmp, &conn->run_list, running) {
+-		if (lun == task->sc->device->lun || lun == -1) {
+-			ISCSI_DBG_SESSION(conn->session,
+-					 "failing in progress sc %p itt 0x%x\n",
+-					 task->sc, task->itt);
+-			fail_command(conn, task, error << 16);
+-		}
++		ISCSI_DBG_SESSION(conn->session,
++				  "failing sc %p itt 0x%x state %d\n",
++				  task->sc, task->itt, task->state);
++		fail_scsi_task(task, error << 16);
+ 	}
+ }
+ 
+@@ -1859,7 +1870,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 	}
+ 
+ 	if (task->state == ISCSI_TASK_PENDING) {
+-		fail_command(conn, task, DID_ABORT << 16);
++		fail_scsi_task(task, DID_ABORT << 16);
+ 		goto success;
+ 	}
+ 
+@@ -1890,7 +1901,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 		 * then sent more data for the cmd.
+ 		 */
+ 		spin_lock(&session->lock);
+-		fail_command(conn, task, DID_ABORT << 16);
++		fail_scsi_task(task, DID_ABORT << 16);
+ 		conn->tmf_state = TMF_INITIAL;
+ 		spin_unlock(&session->lock);
+ 		iscsi_start_tx(conn);
+@@ -1997,7 +2008,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc)
+ 	iscsi_suspend_tx(conn);
+ 
+ 	spin_lock_bh(&session->lock);
+-	fail_all_commands(conn, sc->device->lun, DID_ERROR);
++	fail_scsi_tasks(conn, sc->device->lun, DID_ERROR);
+ 	conn->tmf_state = TMF_INITIAL;
+ 	spin_unlock_bh(&session->lock);
+ 
+@@ -2304,6 +2315,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
+ 		if (cmd_task_size)
+ 			task->dd_data = &task[1];
+ 		task->itt = cmd_i;
++		task->state = ISCSI_TASK_FREE;
+ 		INIT_LIST_HEAD(&task->running);
+ 	}
+ 
+@@ -2390,10 +2402,8 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size,
+ 	conn->transport_timer.data = (unsigned long)conn;
+ 	conn->transport_timer.function = iscsi_check_transport_timeouts;
+ 
+-	INIT_LIST_HEAD(&conn->run_list);
+-	INIT_LIST_HEAD(&conn->mgmt_run_list);
+ 	INIT_LIST_HEAD(&conn->mgmtqueue);
+-	INIT_LIST_HEAD(&conn->xmitqueue);
++	INIT_LIST_HEAD(&conn->cmdqueue);
+ 	INIT_LIST_HEAD(&conn->requeue);
+ 	INIT_WORK(&conn->xmitwork, iscsi_xmitworker);
+ 
+@@ -2561,27 +2571,24 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
+ EXPORT_SYMBOL_GPL(iscsi_conn_start);
+ 
+ static void
+-flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn)
++fail_mgmt_tasks(struct iscsi_session *session, struct iscsi_conn *conn)
+ {
+-	struct iscsi_task *task, *tmp;
++	struct iscsi_task *task;
++	int i;
+ 
+-	/* handle pending */
+-	list_for_each_entry_safe(task, tmp, &conn->mgmtqueue, running) {
+-		ISCSI_DBG_SESSION(session, "flushing pending mgmt task "
+-				  "itt 0x%x\n", task->itt);
+-		/* release ref from prep task */
+-		__iscsi_put_task(task);
+-	}
++	for (i = 0; i < conn->session->cmds_max; i++) {
++		task = conn->session->cmds[i];
++		if (task->sc)
++			continue;
+ 
+-	/* handle running */
+-	list_for_each_entry_safe(task, tmp, &conn->mgmt_run_list, running) {
+-		ISCSI_DBG_SESSION(session, "flushing running mgmt task "
+-				  "itt 0x%x\n", task->itt);
+-		/* release ref from prep task */
+-		__iscsi_put_task(task);
+-	}
++		if (task->state == ISCSI_TASK_FREE)
++			continue;
+ 
+-	conn->task = NULL;
++		ISCSI_DBG_SESSION(conn->session,
++				  "failing mgmt itt 0x%x state %d\n",
++				  task->itt, task->state);
++		iscsi_complete_task(task);
++	}
+ }
+ 
+ static void iscsi_start_session_recovery(struct iscsi_session *session,
+@@ -2638,10 +2645,10 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ 	 */
+ 	spin_lock_bh(&session->lock);
+ 	if (flag == STOP_CONN_RECOVER)
+-		fail_all_commands(conn, -1, DID_TRANSPORT_DISRUPTED);
++		fail_scsi_tasks(conn, -1, DID_TRANSPORT_DISRUPTED);
+ 	else
+-		fail_all_commands(conn, -1, DID_ERROR);
+-	flush_control_queues(session, conn);
++		fail_scsi_tasks(conn, -1, DID_ERROR);
++	fail_mgmt_tasks(session, conn);
+ 	spin_unlock_bh(&session->lock);
+ 	mutex_unlock(&session->eh_mutex);
+ }
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 88d33a46efa5..facae71183a5 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -82,6 +82,7 @@ enum {
+ 
+ 
+ enum {
++	ISCSI_TASK_FREE,
+ 	ISCSI_TASK_COMPLETED,
+ 	ISCSI_TASK_PENDING,
+ 	ISCSI_TASK_RUNNING,
+@@ -181,9 +182,7 @@ struct iscsi_conn {
+ 
+ 	/* xmit */
+ 	struct list_head	mgmtqueue;	/* mgmt (control) xmit queue */
+-	struct list_head	mgmt_run_list;	/* list of control tasks */
+-	struct list_head	xmitqueue;	/* data-path cmd queue */
+-	struct list_head	run_list;	/* list of cmds in progress */
++	struct list_head	cmdqueue;	/* data-path cmd queue */
+ 	struct list_head	requeue;	/* tasks needing another run */
+ 	struct work_struct	xmitwork;	/* per-conn. xmit workqueue */
+ 	unsigned long		suspend_tx;	/* suspend Tx */

commit 4c48a82935f833d94fcf44c2b0c5d2922acfc77a
+Author: Mike Christie 
+Date:   Wed May 13 17:57:45 2009 -0500
+
+    [SCSI] libiscsi: fix iscsi transport checks to account for slower links
+    
+    If we have not got any pdus for recv_timeout seconds, then we will
+    send a iscsi ping/nop to make sure the target is still around. The
+    problem is if this is a slow link, and the ping got queued after
+    the data for a data_out (read), then the transport code could think
+    the ping has failed when it is just slowly making its way through
+    the network. This patch has us check if we are making progress while
+    the nop is outstanding. If we are still reading in data, then we
+    do not fail the session at that time.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 212fe2027a8c..c648bd328a21 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1677,6 +1677,22 @@ static void iscsi_start_tx(struct iscsi_conn *conn)
+ 		iscsi_conn_queue_work(conn);
+ }
+ 
++/*
++ * We want to make sure a ping is in flight. It has timed out.
++ * And we are not busy processing a pdu that is making
++ * progress but got started before the ping and is taking a while
++ * to complete so the ping is just stuck behind it in a queue.
++ */
++static int iscsi_has_ping_timed_out(struct iscsi_conn *conn)
++{
++	if (conn->ping_task &&
++	    time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) +
++			   (conn->ping_timeout * HZ), jiffies))
++		return 1;
++	else
++		return 0;
++}
++
+ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
+ {
+ 	struct iscsi_cls_session *cls_session;
+@@ -1712,16 +1728,20 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
+ 	 * if the ping timedout then we are in the middle of cleaning up
+ 	 * and can let the iscsi eh handle it
+ 	 */
+-	if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) +
+-			    (conn->ping_timeout * HZ), jiffies))
++	if (iscsi_has_ping_timed_out(conn)) {
+ 		rc = BLK_EH_RESET_TIMER;
++		goto done;
++	}
+ 	/*
+ 	 * if we are about to check the transport then give the command
+ 	 * more time
+ 	 */
+ 	if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ),
+-			   jiffies))
++			   jiffies)) {
+ 		rc = BLK_EH_RESET_TIMER;
++		goto done;
++	}
++
+ 	/* if in the middle of checking the transport then give us more time */
+ 	if (conn->ping_task)
+ 		rc = BLK_EH_RESET_TIMER;
+@@ -1748,13 +1768,13 @@ static void iscsi_check_transport_timeouts(unsigned long data)
+ 
+ 	recv_timeout *= HZ;
+ 	last_recv = conn->last_recv;
+-	if (conn->ping_task &&
+-	    time_before_eq(conn->last_ping + (conn->ping_timeout * HZ),
+-			   jiffies)) {
++
++	if (iscsi_has_ping_timed_out(conn)) {
+ 		iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs "
+-				  "expired, last rx %lu, last ping %lu, "
+-				  "now %lu\n", conn->ping_timeout, last_recv,
+-				  conn->last_ping, jiffies);
++				  "expired, recv timeout %d, last rx %lu, "
++				  "last ping %lu, now %lu\n",
++				  conn->ping_timeout, conn->recv_timeout,
++				  last_recv, conn->last_ping, jiffies);
+ 		spin_unlock(&session->lock);
+ 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ 		return;

commit d1acfae514425d680912907c6554852f1e258551
+Author: Mike Christie 
+Date:   Wed May 13 17:57:44 2009 -0500
+
+    [SCSI] libiscsi_tcp: update recv tracking for each skb instead of iscsi pdu
+    
+    Everytime we read in a pdu libiscsi will update a tracking field.
+    It uses this to decide when to check if the transport might be bad.
+    If we have not got data in recv_timeout seconds then we will
+    send a iscsi ping/nop.
+    
+    If we are on a slow link then it could take a while to read in all
+    the data for a data_in. In that case we might send a ping/nop when
+    we do not need to or we might drop a session thinking it is bad
+    when the lower layer is making forward progress on it.
+    
+    This patch has libiscsi_tcp update the recv tracking for each skb
+    (basically network packet from our point of view) instead of the
+    entire iscsi pdu+data, so we account for these cases where data is
+    coming in slowly.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
+index db93cd0dfdb6..b84a1d853f29 100644
+--- a/drivers/scsi/libiscsi_tcp.c
++++ b/drivers/scsi/libiscsi_tcp.c
+@@ -863,6 +863,12 @@ int iscsi_tcp_recv_skb(struct iscsi_conn *conn, struct sk_buff *skb,
+ 	int rc = 0;
+ 
+ 	ISCSI_DBG_TCP(conn, "in %d bytes\n", skb->len - offset);
++	/*
++	 * Update for each skb instead of pdu, because over slow networks a
++	 * data_in's data could take a while to read in. We also want to
++	 * account for r2ts.
++	 */
++	conn->last_recv = jiffies;
+ 
+ 	if (unlikely(conn->suspend_rx)) {
+ 		ISCSI_DBG_TCP(conn, "Rx suspended!\n");

commit 26013ad4c43f49a038a6489c35e9b901491339fe
+Author: Mike Christie 
+Date:   Wed May 13 17:57:43 2009 -0500
+
+    [SCSI] libiscsi: fix nop response/reply and session cleanup race
+    
+    If we are responding to a nop from the target by sending our nop,
+    and the session is getting torn down, then iscsi_start_session_recovery
+    could set the conn stop bits while the recv path is sending the nop
+    response and we will hit the bug ons in __iscsi_conn_send_pdu.
+    
+    This has us check the state in __iscsi_conn_send_pdu and fail all
+    incoming mgmt IO if we are  not logged in and if the pdu is not login
+    related. It also changes the ordering of the setting of conn stop state
+    bits so they are set after the session state is set (both are set under
+    the session lock).
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 047543cd3fc1..212fe2027a8c 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -546,6 +546,9 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		 */
+ 		task = conn->login_task;
+ 	else {
++		if (session->state != ISCSI_STATE_LOGGED_IN)
++			return NULL;
++
+ 		BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
+ 		BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
+ 
+@@ -2566,8 +2569,6 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ {
+ 	int old_stop_stage;
+ 
+-	del_timer_sync(&conn->transport_timer);
+-
+ 	mutex_lock(&session->eh_mutex);
+ 	spin_lock_bh(&session->lock);
+ 	if (conn->stop_stage == STOP_CONN_TERM) {
+@@ -2585,13 +2586,17 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ 		session->state = ISCSI_STATE_TERMINATE;
+ 	else if (conn->stop_stage != STOP_CONN_RECOVER)
+ 		session->state = ISCSI_STATE_IN_RECOVERY;
++	spin_unlock_bh(&session->lock);
+ 
++	del_timer_sync(&conn->transport_timer);
++	iscsi_suspend_tx(conn);
++
++	spin_lock_bh(&session->lock);
+ 	old_stop_stage = conn->stop_stage;
+ 	conn->stop_stage = flag;
+ 	conn->c_stage = ISCSI_CONN_STOPPED;
+ 	spin_unlock_bh(&session->lock);
+ 
+-	iscsi_suspend_tx(conn);
+ 	/*
+ 	 * for connection level recovery we should not calculate
+ 	 * header digest. conn->hdr_size used for optimization

commit edbc9aa0580c0aca96ac8d11bfb2defa81d91bb3
+Author: Mike Christie 
+Date:   Wed May 13 17:57:42 2009 -0500
+
+    [SCSI] libiscsi: have iscsi_data_in_rsp call iscsi_update_cmdsn
+    
+    This has iscsi_data_in_rsp call iscsi_update_cmdsn when a pdu is
+    completed like is done for other pdu's that are don.
+    
+    For libiscsi_tcp, this means that it calls iscsi_update_cmdsn when
+    it is handling the pdu internally to only transfer data, but if there is
+    status then it does not need to call it since the completion handling
+    will do it.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index a6e6eef04fed..047543cd3fc1 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -729,6 +729,7 @@ iscsi_data_in_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	if (!(rhdr->flags & ISCSI_FLAG_DATA_STATUS))
+ 		return;
+ 
++	iscsi_update_cmdsn(conn->session, (struct iscsi_nopin *)hdr);
+ 	sc->result = (DID_OK << 16) | rhdr->cmd_status;
+ 	conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
+ 	if (rhdr->flags & (ISCSI_FLAG_DATA_UNDERFLOW |
+diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
+index b579ca9f4836..db93cd0dfdb6 100644
+--- a/drivers/scsi/libiscsi_tcp.c
++++ b/drivers/scsi/libiscsi_tcp.c
+@@ -473,7 +473,13 @@ static int iscsi_tcp_data_in(struct iscsi_conn *conn, struct iscsi_task *task)
+ 	int datasn = be32_to_cpu(rhdr->datasn);
+ 	unsigned total_in_length = scsi_in(task->sc)->length;
+ 
+-	iscsi_update_cmdsn(conn->session, (struct iscsi_nopin*)rhdr);
++	/*
++	 * lib iscsi will update this in the completion handling if there
++	 * is status.
++	 */
++	if (!(rhdr->flags & ISCSI_FLAG_DATA_STATUS))
++		iscsi_update_cmdsn(conn->session, (struct iscsi_nopin*)rhdr);
++
+ 	if (tcp_conn->in.datalen == 0)
+ 		return 0;
+ 

commit 8f9256cea10ca43ac80f66e176643eb41db34244
+Author: Mike Christie 
+Date:   Wed May 13 17:57:41 2009 -0500
+
+    [SCSI] libiscsi: export iscsi_itt_to_task for bnx2i
+    
+    bnx2i needs to be able to look up mgmt task like login and nop, because
+    it does some processing of them on the completion path. This exports
+    iscsi_itt_to_task so it can look up the task.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index b4aaf2e5fe7a..a6e6eef04fed 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -828,7 +828,7 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+  *
+  * The session lock must be held.
+  */
+-static struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *conn, itt_t itt)
++struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *conn, itt_t itt)
+ {
+ 	struct iscsi_session *session = conn->session;
+ 	int i;
+@@ -845,6 +845,7 @@ static struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *conn, itt_t itt)
+ 
+ 	return session->cmds[i];
+ }
++EXPORT_SYMBOL_GPL(iscsi_itt_to_task);
+ 
+ /**
+  * __iscsi_complete_pdu - complete pdu
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 0289f5745fb9..88d33a46efa5 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -406,6 +406,7 @@ extern int __iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *,
+ 				char *, int);
+ extern int iscsi_verify_itt(struct iscsi_conn *, itt_t);
+ extern struct iscsi_task *iscsi_itt_to_ctask(struct iscsi_conn *, itt_t);
++extern struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *, itt_t);
+ extern void iscsi_requeue_task(struct iscsi_task *task);
+ extern void iscsi_put_task(struct iscsi_task *task);
+ extern void __iscsi_get_task(struct iscsi_task *task);

commit 5700b1af93388544843a453e3c68f8f928bd1e88
+Author: Mike Christie 
+Date:   Wed May 13 17:57:40 2009 -0500
+
+    [SCSI] libiscsi: handle param allocation failures
+    
+    If we could not allocate the initiator name or some other id like
+    the hwaddress or netdev, then userspace could deal with the failure
+    by just running in a dregraded mode.
+    
+    Now we want to be able to switch values for the params and we
+    want some feedback, so this patch will check if a string like
+    the initiatorname could not be allocated and return an error.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 11bc3e1fbd5a..b4aaf2e5fe7a 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -2656,6 +2656,23 @@ int iscsi_conn_bind(struct iscsi_cls_session *cls_session,
+ }
+ EXPORT_SYMBOL_GPL(iscsi_conn_bind);
+ 
++static int iscsi_switch_str_param(char **param, char *new_val_buf)
++{
++	char *new_val;
++
++	if (*param) {
++		if (!strcmp(*param, new_val_buf))
++			return 0;
++	}
++
++	new_val = kstrdup(new_val_buf, GFP_NOIO);
++	if (!new_val)
++		return -ENOMEM;
++
++	kfree(*param);
++	*param = new_val;
++	return 0;
++}
+ 
+ int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
+ 		    enum iscsi_param param, char *buf, int buflen)
+@@ -2728,38 +2745,15 @@ int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
+ 		sscanf(buf, "%u", &conn->exp_statsn);
+ 		break;
+ 	case ISCSI_PARAM_USERNAME:
+-		kfree(session->username);
+-		session->username = kstrdup(buf, GFP_KERNEL);
+-		if (!session->username)
+-			return -ENOMEM;
+-		break;
++		return iscsi_switch_str_param(&session->username, buf);
+ 	case ISCSI_PARAM_USERNAME_IN:
+-		kfree(session->username_in);
+-		session->username_in = kstrdup(buf, GFP_KERNEL);
+-		if (!session->username_in)
+-			return -ENOMEM;
+-		break;
++		return iscsi_switch_str_param(&session->username_in, buf);
+ 	case ISCSI_PARAM_PASSWORD:
+-		kfree(session->password);
+-		session->password = kstrdup(buf, GFP_KERNEL);
+-		if (!session->password)
+-			return -ENOMEM;
+-		break;
++		return iscsi_switch_str_param(&session->password, buf);
+ 	case ISCSI_PARAM_PASSWORD_IN:
+-		kfree(session->password_in);
+-		session->password_in = kstrdup(buf, GFP_KERNEL);
+-		if (!session->password_in)
+-			return -ENOMEM;
+-		break;
++		return iscsi_switch_str_param(&session->password_in, buf);
+ 	case ISCSI_PARAM_TARGET_NAME:
+-		/* this should not change between logins */
+-		if (session->targetname)
+-			break;
+-
+-		session->targetname = kstrdup(buf, GFP_KERNEL);
+-		if (!session->targetname)
+-			return -ENOMEM;
+-		break;
++		return iscsi_switch_str_param(&session->targetname, buf);
+ 	case ISCSI_PARAM_TPGT:
+ 		sscanf(buf, "%d", &session->tpgt);
+ 		break;
+@@ -2767,25 +2761,11 @@ int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
+ 		sscanf(buf, "%d", &conn->persistent_port);
+ 		break;
+ 	case ISCSI_PARAM_PERSISTENT_ADDRESS:
+-		/*
+-		 * this is the address returned in discovery so it should
+-		 * not change between logins.
+-		 */
+-		if (conn->persistent_address)
+-			break;
+-
+-		conn->persistent_address = kstrdup(buf, GFP_KERNEL);
+-		if (!conn->persistent_address)
+-			return -ENOMEM;
+-		break;
++		return iscsi_switch_str_param(&conn->persistent_address, buf);
+ 	case ISCSI_PARAM_IFACE_NAME:
+-		if (!session->ifacename)
+-			session->ifacename = kstrdup(buf, GFP_KERNEL);
+-		break;
++		return iscsi_switch_str_param(&session->ifacename, buf);
+ 	case ISCSI_PARAM_INITIATOR_NAME:
+-		if (!session->initiatorname)
+-			session->initiatorname = kstrdup(buf, GFP_KERNEL);
+-		break;
++		return iscsi_switch_str_param(&session->initiatorname, buf);
+ 	default:
+ 		return -ENOSYS;
+ 	}
+@@ -2856,10 +2836,7 @@ int iscsi_session_get_param(struct iscsi_cls_session *cls_session,
+ 		len = sprintf(buf, "%s\n", session->ifacename);
+ 		break;
+ 	case ISCSI_PARAM_INITIATOR_NAME:
+-		if (!session->initiatorname)
+-			len = sprintf(buf, "%s\n", "unknown");
+-		else
+-			len = sprintf(buf, "%s\n", session->initiatorname);
++		len = sprintf(buf, "%s\n", session->initiatorname);
+ 		break;
+ 	default:
+ 		return -ENOSYS;
+@@ -2925,29 +2902,16 @@ int iscsi_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param,
+ 
+ 	switch (param) {
+ 	case ISCSI_HOST_PARAM_NETDEV_NAME:
+-		if (!ihost->netdev)
+-			len = sprintf(buf, "%s\n", "default");
+-		else
+-			len = sprintf(buf, "%s\n", ihost->netdev);
++		len = sprintf(buf, "%s\n", ihost->netdev);
+ 		break;
+ 	case ISCSI_HOST_PARAM_HWADDRESS:
+-		if (!ihost->hwaddress)
+-			len = sprintf(buf, "%s\n", "default");
+-		else
+-			len = sprintf(buf, "%s\n", ihost->hwaddress);
++		len = sprintf(buf, "%s\n", ihost->hwaddress);
+ 		break;
+ 	case ISCSI_HOST_PARAM_INITIATOR_NAME:
+-		if (!ihost->initiatorname)
+-			len = sprintf(buf, "%s\n", "unknown");
+-		else
+-			len = sprintf(buf, "%s\n", ihost->initiatorname);
++		len = sprintf(buf, "%s\n", ihost->initiatorname);
+ 		break;
+ 	case ISCSI_HOST_PARAM_IPADDRESS:
+-		if (!strlen(ihost->local_address))
+-			len = sprintf(buf, "%s\n", "unknown");
+-		else
+-			len = sprintf(buf, "%s\n",
+-				      ihost->local_address);
++		len = sprintf(buf, "%s\n", ihost->local_address);
+ 		break;
+ 	default:
+ 		return -ENOSYS;
+@@ -2964,17 +2928,11 @@ int iscsi_host_set_param(struct Scsi_Host *shost, enum iscsi_host_param param,
+ 
+ 	switch (param) {
+ 	case ISCSI_HOST_PARAM_NETDEV_NAME:
+-		if (!ihost->netdev)
+-			ihost->netdev = kstrdup(buf, GFP_KERNEL);
+-		break;
++		return iscsi_switch_str_param(&ihost->netdev, buf);
+ 	case ISCSI_HOST_PARAM_HWADDRESS:
+-		if (!ihost->hwaddress)
+-			ihost->hwaddress = kstrdup(buf, GFP_KERNEL);
+-		break;
++		return iscsi_switch_str_param(&ihost->hwaddress, buf);
+ 	case ISCSI_HOST_PARAM_INITIATOR_NAME:
+-		if (!ihost->initiatorname)
+-			ihost->initiatorname = kstrdup(buf, GFP_KERNEL);
+-		break;
++		return iscsi_switch_str_param(&ihost->initiatorname, buf);
+ 	default:
+ 		return -ENOSYS;
+ 	}

commit 184b57c630c86d35b7f92d4b6545fdf07647c5d5
+Author: Mike Christie 
+Date:   Wed May 13 17:57:39 2009 -0500
+
+    [SCSI] libiscsi: check of LLD has a alloc pdu callout.
+    
+    bnx2i does not have one. It currently preallocates the bdt
+    when the session is setup.
+    
+    We probably want to change that to a dma pool, then allocate from
+    the pool in the alloc pdu. Until then check if there is a alloc
+    pdu callout.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index e72b4ad47d35..11bc3e1fbd5a 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -257,9 +257,11 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
+ 	itt_t itt;
+ 	int rc;
+ 
+-	rc = conn->session->tt->alloc_pdu(task, ISCSI_OP_SCSI_CMD);
+-	if (rc)
+-		return rc;
++	if (conn->session->tt->alloc_pdu) {
++		rc = conn->session->tt->alloc_pdu(task, ISCSI_OP_SCSI_CMD);
++		if (rc)
++			return rc;
++	}
+ 	hdr = (struct iscsi_cmd *) task->hdr;
+ 	itt = hdr->itt;
+ 	memset(hdr, 0, sizeof(*hdr));
+@@ -566,11 +568,14 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	} else
+ 		task->data_count = 0;
+ 
+-	if (conn->session->tt->alloc_pdu(task, hdr->opcode)) {
+-		iscsi_conn_printk(KERN_ERR, conn, "Could not allocate "
+-				 "pdu for mgmt task.\n");
+-		goto requeue_task;
++	if (conn->session->tt->alloc_pdu) {
++		if (conn->session->tt->alloc_pdu(task, hdr->opcode)) {
++			iscsi_conn_printk(KERN_ERR, conn, "Could not allocate "
++					 "pdu for mgmt task.\n");
++			goto requeue_task;
++		}
+ 	}
++
+ 	itt = task->hdr->itt;
+ 	task->hdr_len = sizeof(struct iscsi_hdr);
+ 	memcpy(task->hdr, hdr, sizeof(struct iscsi_hdr));

commit 10eb0f013c63c71c82ede77945a5f390c10cfda6
+Author: Mike Christie 
+Date:   Wed May 13 17:57:38 2009 -0500
+
+    [SCSI] iscsi: pass ep connect shost
+    
+    When we create the tcp/ip connection by calling ep_connect, we currently
+    just go by the routing table info.
+    
+    I think there are two problems with this.
+    
+    1. Some drivers do not have access to a routing table. Some drivers like
+    qla4xxx do not even know about other ports.
+    
+    2. If you have two initiator ports on the same subnet, the user may have
+    set things up so that session1 was supposed to be run through port1. and
+    session2 was supposed to be run through port2. It looks like we could
+    end with both sessions going through one of the ports.
+    
+    Fixes for cxgb3i from Karen Xie.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 75223f50de58..ffbe0c76bc11 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -517,7 +517,8 @@ iscsi_iser_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *s
+ }
+ 
+ static struct iscsi_endpoint *
+-iscsi_iser_ep_connect(struct sockaddr *dst_addr, int non_blocking)
++iscsi_iser_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
++		      int non_blocking)
+ {
+ 	int err;
+ 	struct iser_conn *ib_conn;
+diff --git a/drivers/scsi/cxgb3i/cxgb3i.h b/drivers/scsi/cxgb3i/cxgb3i.h
+index 59b0958d2d11..e3133b58e594 100644
+--- a/drivers/scsi/cxgb3i/cxgb3i.h
++++ b/drivers/scsi/cxgb3i/cxgb3i.h
+@@ -144,7 +144,6 @@ struct cxgb3i_adapter *cxgb3i_adapter_find_by_tdev(struct t3cdev *);
+ void cxgb3i_adapter_open(struct t3cdev *);
+ void cxgb3i_adapter_close(struct t3cdev *);
+ 
+-struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *);
+ struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *,
+ 				       struct net_device *);
+ void cxgb3i_hba_host_remove(struct cxgb3i_hba *);
+diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+index 9212400b9b13..04a43744aedf 100644
+--- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
++++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+@@ -178,7 +178,7 @@ void cxgb3i_adapter_close(struct t3cdev *t3dev)
+  * cxgb3i_hba_find_by_netdev - find the cxgb3i_hba structure via net_device
+  * @t3dev: t3cdev adapter
+  */
+-struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *ndev)
++static struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *ndev)
+ {
+ 	struct cxgb3i_adapter *snic;
+ 	int i;
+@@ -261,20 +261,27 @@ void cxgb3i_hba_host_remove(struct cxgb3i_hba *hba)
+ 
+ /**
+  * cxgb3i_ep_connect - establish TCP connection to target portal
++ * @shost:		scsi host to use
+  * @dst_addr:		target IP address
+  * @non_blocking:	blocking or non-blocking call
+  *
+  * Initiates a TCP/IP connection to the dst_addr
+  */
+-static struct iscsi_endpoint *cxgb3i_ep_connect(struct sockaddr *dst_addr,
++static struct iscsi_endpoint *cxgb3i_ep_connect(struct Scsi_Host *shost,
++						struct sockaddr *dst_addr,
+ 						int non_blocking)
+ {
+ 	struct iscsi_endpoint *ep;
+ 	struct cxgb3i_endpoint *cep;
+-	struct cxgb3i_hba *hba;
++	struct cxgb3i_hba *hba = NULL;
+ 	struct s3_conn *c3cn = NULL;
+ 	int err = 0;
+ 
++	if (shost)
++		hba = iscsi_host_priv(shost);
++
++	cxgb3i_api_debug("shost 0x%p, hba 0x%p.\n", shost, hba);
++
+ 	c3cn = cxgb3i_c3cn_create();
+ 	if (!c3cn) {
+ 		cxgb3i_log_info("ep connect OOM.\n");
+@@ -282,17 +289,27 @@ static struct iscsi_endpoint *cxgb3i_ep_connect(struct sockaddr *dst_addr,
+ 		goto release_conn;
+ 	}
+ 
+-	err = cxgb3i_c3cn_connect(c3cn, (struct sockaddr_in *)dst_addr);
++	err = cxgb3i_c3cn_connect(hba ? hba->ndev : NULL, c3cn,
++				 (struct sockaddr_in *)dst_addr);
+ 	if (err < 0) {
+ 		cxgb3i_log_info("ep connect failed.\n");
+ 		goto release_conn;
+ 	}
++
+ 	hba = cxgb3i_hba_find_by_netdev(c3cn->dst_cache->dev);
+ 	if (!hba) {
+ 		err = -ENOSPC;
+ 		cxgb3i_log_info("NOT going through cxgbi device.\n");
+ 		goto release_conn;
+ 	}
++
++	if (shost && hba != iscsi_host_priv(shost)) {
++		err = -ENOSPC;
++		cxgb3i_log_info("Could not connect through request host%u\n",
++				shost->host_no);
++		goto release_conn;
++	}
++
+ 	if (c3cn_is_closing(c3cn)) {
+ 		err = -ENOSPC;
+ 		cxgb3i_log_info("ep connect unable to connect.\n");
+diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.c b/drivers/scsi/cxgb3i/cxgb3i_offload.c
+index e11c9c180f39..c1d5be4adf9c 100644
+--- a/drivers/scsi/cxgb3i/cxgb3i_offload.c
++++ b/drivers/scsi/cxgb3i/cxgb3i_offload.c
+@@ -1479,12 +1479,13 @@ static struct net_device *cxgb3_egress_dev(struct net_device *root_dev,
+ 	return NULL;
+ }
+ 
+-static struct rtable *find_route(__be32 saddr, __be32 daddr,
++static struct rtable *find_route(struct net_device *dev,
++				 __be32 saddr, __be32 daddr,
+ 				 __be16 sport, __be16 dport)
+ {
+ 	struct rtable *rt;
+ 	struct flowi fl = {
+-		.oif = 0,
++		.oif = dev ? dev->ifindex : 0,
+ 		.nl_u = {
+ 			 .ip4_u = {
+ 				   .daddr = daddr,
+@@ -1573,36 +1574,40 @@ static int initiate_act_open(struct s3_conn *c3cn, struct net_device *dev)
+  *
+  * return 0 if active open request is sent, < 0 otherwise.
+  */
+-int cxgb3i_c3cn_connect(struct s3_conn *c3cn, struct sockaddr_in *usin)
++int cxgb3i_c3cn_connect(struct net_device *dev, struct s3_conn *c3cn,
++			struct sockaddr_in *usin)
+ {
+ 	struct rtable *rt;
+-	struct net_device *dev;
+ 	struct cxgb3i_sdev_data *cdata;
+ 	struct t3cdev *cdev;
+ 	__be32 sipv4;
+ 	int err;
+ 
++	c3cn_conn_debug("c3cn 0x%p, dev 0x%p.\n", c3cn, dev);
++
+ 	if (usin->sin_family != AF_INET)
+ 		return -EAFNOSUPPORT;
+ 
+ 	c3cn->daddr.sin_port = usin->sin_port;
+ 	c3cn->daddr.sin_addr.s_addr = usin->sin_addr.s_addr;
+ 
+-	rt = find_route(c3cn->saddr.sin_addr.s_addr,
++	rt = find_route(dev, c3cn->saddr.sin_addr.s_addr,
+ 			c3cn->daddr.sin_addr.s_addr,
+ 			c3cn->saddr.sin_port,
+ 			c3cn->daddr.sin_port);
+ 	if (rt == NULL) {
+-		c3cn_conn_debug("NO route to 0x%x, port %u.\n",
++		c3cn_conn_debug("NO route to 0x%x, port %u, dev %s.\n",
+ 				c3cn->daddr.sin_addr.s_addr,
+-				ntohs(c3cn->daddr.sin_port));
++				ntohs(c3cn->daddr.sin_port),
++				dev ? dev->name : "any");
+ 		return -ENETUNREACH;
+ 	}
+ 
+ 	if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
+-		c3cn_conn_debug("multi-cast route to 0x%x, port %u.\n",
++		c3cn_conn_debug("multi-cast route to 0x%x, port %u, dev %s.\n",
+ 				c3cn->daddr.sin_addr.s_addr,
+-				ntohs(c3cn->daddr.sin_port));
++				ntohs(c3cn->daddr.sin_port),
++				dev ? dev->name : "any");
+ 		ip_rt_put(rt);
+ 		return -ENETUNREACH;
+ 	}
+diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.h b/drivers/scsi/cxgb3i/cxgb3i_offload.h
+index ebfca960c0a9..6a1d86b1fafe 100644
+--- a/drivers/scsi/cxgb3i/cxgb3i_offload.h
++++ b/drivers/scsi/cxgb3i/cxgb3i_offload.h
+@@ -169,7 +169,8 @@ void cxgb3i_sdev_add(struct t3cdev *, struct cxgb3_client *);
+ void cxgb3i_sdev_remove(struct t3cdev *);
+ 
+ struct s3_conn *cxgb3i_c3cn_create(void);
+-int cxgb3i_c3cn_connect(struct s3_conn *, struct sockaddr_in *);
++int cxgb3i_c3cn_connect(struct net_device *, struct s3_conn *,
++			struct sockaddr_in *);
+ void cxgb3i_c3cn_rx_credits(struct s3_conn *, int);
+ int cxgb3i_c3cn_send_pdus(struct s3_conn *, struct sk_buff *);
+ void cxgb3i_c3cn_release(struct s3_conn *);
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 0a2ce7b6325c..d69a53aa406f 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -1268,26 +1268,54 @@ iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+ 	return err;
+ }
+ 
++static int iscsi_if_ep_connect(struct iscsi_transport *transport,
++			       struct iscsi_uevent *ev, int msg_type)
++{
++	struct iscsi_endpoint *ep;
++	struct sockaddr *dst_addr;
++	struct Scsi_Host *shost = NULL;
++	int non_blocking, err = 0;
++
++	if (!transport->ep_connect)
++		return -EINVAL;
++
++	if (msg_type == ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST) {
++		shost = scsi_host_lookup(ev->u.ep_connect_through_host.host_no);
++		if (!shost) {
++			printk(KERN_ERR "ep connect failed. Could not find "
++			       "host no %u\n",
++			       ev->u.ep_connect_through_host.host_no);
++			return -ENODEV;
++		}
++		non_blocking = ev->u.ep_connect_through_host.non_blocking;
++	} else
++		non_blocking = ev->u.ep_connect.non_blocking;
++
++	dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
++	ep = transport->ep_connect(shost, dst_addr, non_blocking);
++	if (IS_ERR(ep)) {
++		err = PTR_ERR(ep);
++		goto release_host;
++	}
++
++	ev->r.ep_connect_ret.handle = ep->id;
++release_host:
++	if (shost)
++		scsi_host_put(shost);
++	return err;
++}
++
+ static int
+ iscsi_if_transport_ep(struct iscsi_transport *transport,
+ 		      struct iscsi_uevent *ev, int msg_type)
+ {
+ 	struct iscsi_endpoint *ep;
+-	struct sockaddr *dst_addr;
+ 	int rc = 0;
+ 
+ 	switch (msg_type) {
++	case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST:
+ 	case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
+-		if (!transport->ep_connect)
+-			return -EINVAL;
+-
+-		dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
+-		ep = transport->ep_connect(dst_addr,
+-					   ev->u.ep_connect.non_blocking);
+-		if (IS_ERR(ep))
+-			return PTR_ERR(ep);
+-
+-		ev->r.ep_connect_ret.handle = ep->id;
++		rc = iscsi_if_ep_connect(transport, ev, msg_type);
+ 		break;
+ 	case ISCSI_UEVENT_TRANSPORT_EP_POLL:
+ 		if (!transport->ep_poll)
+@@ -1469,6 +1497,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 	case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
+ 	case ISCSI_UEVENT_TRANSPORT_EP_POLL:
+ 	case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
++	case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST:
+ 		err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type);
+ 		break;
+ 	case ISCSI_UEVENT_TGT_DSCVR:
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index d0ed5226f8c4..2c1a4af9eafb 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -50,7 +50,8 @@ enum iscsi_uevent_e {
+ 	ISCSI_UEVENT_TGT_DSCVR		= UEVENT_BASE + 15,
+ 	ISCSI_UEVENT_SET_HOST_PARAM	= UEVENT_BASE + 16,
+ 	ISCSI_UEVENT_UNBIND_SESSION	= UEVENT_BASE + 17,
+-	ISCSI_UEVENT_CREATE_BOUND_SESSION	= UEVENT_BASE + 18,
++	ISCSI_UEVENT_CREATE_BOUND_SESSION		= UEVENT_BASE + 18,
++	ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST	= UEVENT_BASE + 19,
+ 
+ 	/* up events */
+ 	ISCSI_KEVENT_RECV_PDU		= KEVENT_BASE + 1,
+@@ -131,6 +132,10 @@ struct iscsi_uevent {
+ 		struct msg_transport_connect {
+ 			uint32_t	non_blocking;
+ 		} ep_connect;
++		struct msg_transport_connect_through_host {
++			uint32_t	host_no;
++			uint32_t	non_blocking;
++		} ep_connect_through_host;
+ 		struct msg_transport_poll {
+ 			uint64_t	ep_handle;
+ 			uint32_t	timeout_ms;
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 457588e1119b..8cb7a31d9961 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -126,7 +126,8 @@ struct iscsi_transport {
+ 			       int *index, int *age);
+ 
+ 	void (*session_recovery_timedout) (struct iscsi_cls_session *session);
+-	struct iscsi_endpoint *(*ep_connect) (struct sockaddr *dst_addr,
++	struct iscsi_endpoint *(*ep_connect) (struct Scsi_Host *shost,
++					      struct sockaddr *dst_addr,
+ 					      int non_blocking);
+ 	int (*ep_poll) (struct iscsi_endpoint *ep, int timeout_ms);
+ 	void (*ep_disconnect) (struct iscsi_endpoint *ep);

commit 1393109f23f8ad753a60a3e461c6caa96d8524f3
+Author: Mike Christie 
+Date:   Tue Apr 21 15:32:34 2009 -0500
+
+    [SCSI] cxgb3i: fix cpu use abuse during writes
+    
+    When doing a lot (128) of large writes (256K) we can hit the cxgb3_snd_win
+    check pretty easily. The driver's xmit thread then takes 100% of the cpu.
+    
+    The driver should not be returning -EAGAIN for this problem. It should
+    be returing -ENOBUFS, then when the window is opened again it should
+    queue the xmit thread (it already wakes the xmit thread).
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.c b/drivers/scsi/cxgb3i/cxgb3i_offload.c
+index 4d8654cdbdae..e11c9c180f39 100644
+--- a/drivers/scsi/cxgb3i/cxgb3i_offload.c
++++ b/drivers/scsi/cxgb3i/cxgb3i_offload.c
+@@ -1737,7 +1737,7 @@ int cxgb3i_c3cn_send_pdus(struct s3_conn *c3cn, struct sk_buff *skb)
+ 		c3cn_tx_debug("c3cn 0x%p, snd %u - %u > %u.\n",
+ 				c3cn, c3cn->write_seq, c3cn->snd_una,
+ 				cxgb3_snd_win);
+-		err = -EAGAIN;
++		err = -ENOBUFS;
+ 		goto out_err;
+ 	}
+ 
+@@ -1775,6 +1775,8 @@ int cxgb3i_c3cn_send_pdus(struct s3_conn *c3cn, struct sk_buff *skb)
+ out_err:
+ 	if (copied == 0 && err == -EPIPE)
+ 		copied = c3cn->err ? c3cn->err : -EPIPE;
++	else
++		copied = err;
+ 	goto done;
+ }
+ 
+diff --git a/drivers/scsi/cxgb3i/cxgb3i_pdu.c b/drivers/scsi/cxgb3i/cxgb3i_pdu.c
+index 7eebc9a7cb35..709105071177 100644
+--- a/drivers/scsi/cxgb3i/cxgb3i_pdu.c
++++ b/drivers/scsi/cxgb3i/cxgb3i_pdu.c
+@@ -400,17 +400,18 @@ int cxgb3i_conn_xmit_pdu(struct iscsi_task *task)
+ 		return 0;
+ 	}
+ 
+-	if (err < 0 && err != -EAGAIN) {
+-		kfree_skb(skb);
+-		cxgb3i_tx_debug("itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n",
+-				task->itt, skb, skb->len, skb->data_len, err);
+-		iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err);
+-		iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED);
++	if (err == -EAGAIN || err == -ENOBUFS) {
++		/* reset skb to send when we are called again */
++		tdata->skb = skb;
+ 		return err;
+ 	}
+-	/* reset skb to send when we are called again */
+-	tdata->skb = skb;
+-	return -EAGAIN;
++
++	kfree_skb(skb);
++	cxgb3i_tx_debug("itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n",
++			task->itt, skb, skb->len, skb->data_len, err);
++	iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err);
++	iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED);
++	return err;
+ }
+ 
+ int cxgb3i_pdu_init(void)

commit dd0af9f94e54efb13ee050ebac11909215ef02c2
+Author: Mike Christie 
+Date:   Tue Apr 21 15:32:33 2009 -0500
+
+    [SCSI] cxgb3i: fix can_queue and cmd_per_lun initialization
+    
+    cxgb3i was setting can_queue to only 128 commands, and was
+    setting the can_queue and cmd_per_lun to the same value.
+    
+    This sets the can_queue to 1024 commands, and sets the cmd_per_lun
+    to a safer default of 32.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/cxgb3i/cxgb3i.h b/drivers/scsi/cxgb3i/cxgb3i.h
+index d362860e7504..59b0958d2d11 100644
+--- a/drivers/scsi/cxgb3i/cxgb3i.h
++++ b/drivers/scsi/cxgb3i/cxgb3i.h
+@@ -34,7 +34,7 @@
+ #include "cxgb3i_offload.h"
+ #include "cxgb3i_ddp.h"
+ 
+-#define CXGB3I_SCSI_QDEPTH_DFLT	128
++#define CXGB3I_SCSI_HOST_QDEPTH 1024
+ #define CXGB3I_MAX_TARGET	CXGB3I_MAX_CONN
+ #define CXGB3I_MAX_LUN		512
+ #define ISCSI_PDU_NONPAYLOAD_MAX \
+diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+index b3ca3a05f0d9..9212400b9b13 100644
+--- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
++++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+@@ -876,10 +876,10 @@ static struct scsi_host_template cxgb3i_host_template = {
+ 	.proc_name		= "cxgb3i",
+ 	.queuecommand		= iscsi_queuecommand,
+ 	.change_queue_depth	= iscsi_change_queue_depth,
+-	.can_queue		= CXGB3I_SCSI_QDEPTH_DFLT - 1,
++	.can_queue		= CXGB3I_SCSI_HOST_QDEPTH,
+ 	.sg_tablesize		= SG_ALL,
+ 	.max_sectors		= 0xFFFF,
+-	.cmd_per_lun		= CXGB3I_SCSI_QDEPTH_DFLT,
++	.cmd_per_lun		= ISCSI_DEF_CMD_PER_LUN,
+ 	.eh_abort_handler	= iscsi_eh_abort,
+ 	.eh_device_reset_handler = iscsi_eh_device_reset,
+ 	.eh_target_reset_handler = iscsi_eh_target_reset,

commit 6b5d6c443a9b4fd71b633cef66b5db4de8a85787
+Author: Mike Christie 
+Date:   Tue Apr 21 15:32:32 2009 -0500
+
+    [SCSI] cxgb3i, iser, iscsi_tcp: set target can queue
+    
+    Set target can queue limit to the number of preallocated
+    session tasks we have.
+    
+    This along with the cxgb3i can_queue patch will fix a throughput
+    problem where it could only queue one LU worth of data at a time.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 13d7674b293d..75223f50de58 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -599,6 +599,7 @@ static struct scsi_host_template iscsi_iser_sht = {
+ 	.eh_abort_handler       = iscsi_eh_abort,
+ 	.eh_device_reset_handler= iscsi_eh_device_reset,
+ 	.eh_target_reset_handler= iscsi_eh_target_reset,
++	.target_alloc		= iscsi_target_alloc,
+ 	.use_clustering         = DISABLE_CLUSTERING,
+ 	.proc_name              = "iscsi_iser",
+ 	.this_id                = -1,
+diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+index fff8e4327644..b3ca3a05f0d9 100644
+--- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
++++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+@@ -883,6 +883,7 @@ static struct scsi_host_template cxgb3i_host_template = {
+ 	.eh_abort_handler	= iscsi_eh_abort,
+ 	.eh_device_reset_handler = iscsi_eh_device_reset,
+ 	.eh_target_reset_handler = iscsi_eh_target_reset,
++	.target_alloc		= iscsi_target_alloc,
+ 	.use_clustering		= DISABLE_CLUSTERING,
+ 	.this_id		= -1,
+ };
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index f97fc7e9de79..b7c092d63bbe 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -851,6 +851,7 @@ static struct scsi_host_template iscsi_sw_tcp_sht = {
+ 	.use_clustering         = DISABLE_CLUSTERING,
+ 	.slave_alloc            = iscsi_sw_tcp_slave_alloc,
+ 	.slave_configure        = iscsi_sw_tcp_slave_configure,
++	.target_alloc		= iscsi_target_alloc,
+ 	.proc_name		= "iscsi_tcp",
+ 	.this_id		= -1,
+ };
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 689628359169..e72b4ad47d35 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1463,6 +1463,16 @@ int iscsi_change_queue_depth(struct scsi_device *sdev, int depth)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_change_queue_depth);
+ 
++int iscsi_target_alloc(struct scsi_target *starget)
++{
++	struct iscsi_cls_session *cls_session = starget_to_session(starget);
++	struct iscsi_session *session = cls_session->dd_data;
++
++	starget->can_queue = session->scsi_cmds_max;
++	return 0;
++}
++EXPORT_SYMBOL_GPL(iscsi_target_alloc);
++
+ void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session)
+ {
+ 	struct iscsi_session *session = cls_session->dd_data;
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 7ffaed2f94dd..0289f5745fb9 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -36,6 +36,7 @@ struct scsi_transport_template;
+ struct scsi_host_template;
+ struct scsi_device;
+ struct Scsi_Host;
++struct scsi_target;
+ struct scsi_cmnd;
+ struct socket;
+ struct iscsi_transport;
+@@ -350,6 +351,7 @@ extern struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
+ 					  bool xmit_can_sleep);
+ extern void iscsi_host_remove(struct Scsi_Host *shost);
+ extern void iscsi_host_free(struct Scsi_Host *shost);
++extern int iscsi_target_alloc(struct scsi_target *starget);
+ 
+ /*
+  * session management

commit 9a6510eb3f030cedba32664498a610dc6d084d46
+Author: Mike Christie 
+Date:   Tue Apr 21 15:32:31 2009 -0500
+
+    [SCSI] iscsi_tcp: don't fire conn error if pdu init fails
+    
+    If a command's scsi cmd pdu setup fails then we can just fail
+    the IO to the scsi layer. If a DATA_OUT for a R2T fails then
+    we will want to drop the session, because it means we got a
+    bad request from the target (iscsi protocol error).
+    
+    This patch has us propogate the error upwards so libiscsi_tcp
+    or libiscsi can decide what the best action is to take. It
+    also fixes a bug where we could try to grab the session lock
+    while holding it, because if iscsi_tcp drops the session in the
+    pdu setup callout the session lock is held when setting up the
+    scsi cmd pdu.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index b3e5e08e44ab..f97fc7e9de79 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -463,7 +463,7 @@ static int iscsi_sw_tcp_pdu_init(struct iscsi_task *task,
+ 	}
+ 
+ 	if (err) {
+-		iscsi_conn_failure(conn, err);
++		/* got invalid offset/len */
+ 		return -EIO;
+ 	}
+ 	return 0;
+diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
+index 91f8ce4d8d08..b579ca9f4836 100644
+--- a/drivers/scsi/libiscsi_tcp.c
++++ b/drivers/scsi/libiscsi_tcp.c
+@@ -1036,8 +1036,11 @@ int iscsi_tcp_task_xmit(struct iscsi_task *task)
+ 
+ 	rc = conn->session->tt->init_pdu(task, r2t->data_offset + r2t->sent,
+ 					 r2t->data_count);
+-	if (rc)
++	if (rc) {
++		iscsi_conn_failure(conn, ISCSI_ERR_XMIT_FAILED);
+ 		return rc;
++	}
++
+ 	r2t->sent += r2t->data_count;
+ 	goto flush;
+ }

commit b4efdd586bc08cdf5977cad0a90091f44546a930
+Author: Mike Christie 
+Date:   Thu Apr 9 15:57:10 2009 -0500
+
+    [SCSI] fix q->lock not held warning when target is busy
+    
+    We cannot call blk_plug_device from scsi_target_queue_ready
+    because the q lock is not held. And we do not need to call
+    it from there because when we return 0, the scsi_request_fn
+    not_ready handling will plug the queue for us if needed.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index d1cb64ad1a3f..bb218c8b6e98 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -1291,10 +1291,8 @@ static inline int scsi_target_queue_ready(struct Scsi_Host *shost,
+ 		if (--starget->target_blocked == 0) {
+ 			SCSI_LOG_MLQUEUE(3, starget_printk(KERN_INFO, starget,
+ 					 "unblocking target at zero depth\n"));
+-		} else {
+-			blk_plug_device(sdev->request_queue);
++		} else
+ 			return 0;
+-		}
+ 	}
+ 
+ 	if (scsi_target_is_busy(starget)) {

commit 5b2639d59afe0a30e1b955b23c52ee9099888058
+Author: Mike Christie 
+Date:   Wed Apr 1 13:11:28 2009 -0500
+
+    [SCSI] cxgb3i: call ddp release function directly
+    
+    cxgb3i_ddp_cleanup just calls ddp_release directly so there is
+    no reason for the wrapper. This patch just renames ddp_release
+    to cxgb3i_ddp_cleanup and removes the old wrapper function.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.c b/drivers/scsi/cxgb3i/cxgb3i_ddp.c
+index 275d2da443be..d06a661c209f 100644
+--- a/drivers/scsi/cxgb3i/cxgb3i_ddp.c
++++ b/drivers/scsi/cxgb3i/cxgb3i_ddp.c
+@@ -587,12 +587,12 @@ int cxgb3i_adapter_ddp_info(struct t3cdev *tdev,
+ }
+ 
+ /**
+- * ddp_release - release the cxgb3 adapter's ddp resource
++ * cxgb3i_ddp_cleanup - release the cxgb3 adapter's ddp resource
+  * @tdev: t3cdev adapter
+  * release all the resource held by the ddp pagepod manager for a given
+  * adapter if needed
+  */
+-static void ddp_release(struct t3cdev *tdev)
++void cxgb3i_ddp_cleanup(struct t3cdev *tdev)
+ {
+ 	int i = 0;
+ 	struct cxgb3i_ddp_info *ddp = (struct cxgb3i_ddp_info *)tdev->ulp_iscsi;
+@@ -714,11 +714,3 @@ void cxgb3i_ddp_init(struct t3cdev *tdev)
+ 	}
+ 	ddp_init(tdev);
+ }
+-
+-/**
+- * cxgb3i_ddp_cleaup - clean up ddp function
+- */
+-void cxgb3i_ddp_cleanup(struct t3cdev *tdev)
+-{
+-	ddp_release(tdev);
+-}

commit ed6f7744f90a0efc6874f2ab93e4e593741079c9
+Author: Mike Christie 
+Date:   Wed Apr 1 13:11:25 2009 -0500
+
+    [SCSI] cxgb3i: re-read ddp settings information after chip reset
+    
+    Orignally from Karen Xie, but merge conflicts/errors fixed up by
+    Mike Christie.
+    
+    Signed-off-by: Karen Xie 
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/cxgb3i/cxgb3i.h b/drivers/scsi/cxgb3i/cxgb3i.h
+index 0942227aa7ba..d362860e7504 100644
+--- a/drivers/scsi/cxgb3i/cxgb3i.h
++++ b/drivers/scsi/cxgb3i/cxgb3i.h
+@@ -141,7 +141,7 @@ int cxgb3i_iscsi_init(void);
+ void cxgb3i_iscsi_cleanup(void);
+ 
+ struct cxgb3i_adapter *cxgb3i_adapter_find_by_tdev(struct t3cdev *);
+-struct cxgb3i_adapter *cxgb3i_adapter_open(struct t3cdev *);
++void cxgb3i_adapter_open(struct t3cdev *);
+ void cxgb3i_adapter_close(struct t3cdev *);
+ 
+ struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *);
+diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+index ff6bfd66733f..fff8e4327644 100644
+--- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
++++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+@@ -71,37 +71,34 @@ struct cxgb3i_adapter *cxgb3i_adapter_find_by_tdev(struct t3cdev *tdev)
+ 	return NULL;
+ }
+ 
+-/**
+- * cxgb3i_adapter_open - init a s3 adapter structure and any h/w settings
+- * @t3dev: t3cdev adapter
+- * return the resulting cxgb3i_adapter struct
+- */
+-struct cxgb3i_adapter *cxgb3i_adapter_open(struct t3cdev *t3dev)
++static inline int adapter_update(struct cxgb3i_adapter *snic)
+ {
+-	struct cxgb3i_adapter *snic;
+-	struct adapter *adapter = tdev2adap(t3dev);
+-	int i;
++	cxgb3i_log_info("snic 0x%p, t3dev 0x%p, updating.\n",
++			snic, snic->tdev);
++	return cxgb3i_adapter_ddp_info(snic->tdev, &snic->tag_format,
++					&snic->tx_max_size,
++					&snic->rx_max_size);
++}
+ 
+-	snic = kzalloc(sizeof(*snic), GFP_KERNEL);
+-	if (!snic) {
+-		cxgb3i_api_debug("cxgb3 %s, OOM.\n", t3dev->name);
+-		return NULL;
+-	}
+-	spin_lock_init(&snic->lock);
++static int adapter_add(struct cxgb3i_adapter *snic)
++{
++	struct t3cdev *t3dev = snic->tdev;
++	struct adapter *adapter = tdev2adap(t3dev);
++	int i, err;
+ 
+-	snic->tdev = t3dev;
+ 	snic->pdev = adapter->pdev;
+ 	snic->tag_format.sw_bits = sw_tag_idx_bits + sw_tag_age_bits;
+ 
+-	if (cxgb3i_adapter_ddp_init(t3dev, &snic->tag_format,
++	err = cxgb3i_adapter_ddp_info(t3dev, &snic->tag_format,
+ 				    &snic->tx_max_size,
+-				    &snic->rx_max_size) < 0)
+-		goto free_snic;
++				    &snic->rx_max_size);
++	if (err < 0)
++		return err;
+ 
+ 	for_each_port(adapter, i) {
+ 		snic->hba[i] = cxgb3i_hba_host_add(snic, adapter->port[i]);
+ 		if (!snic->hba[i])
+-			goto ulp_cleanup;
++			return -EINVAL;
+ 	}
+ 	snic->hba_cnt = adapter->params.nports;
+ 
+@@ -110,13 +107,40 @@ struct cxgb3i_adapter *cxgb3i_adapter_open(struct t3cdev *t3dev)
+ 	list_add_tail(&snic->list_head, &cxgb3i_snic_list);
+ 	write_unlock(&cxgb3i_snic_rwlock);
+ 
+-	return snic;
++	cxgb3i_log_info("t3dev 0x%p open, snic 0x%p, %u scsi hosts added.\n",
++			t3dev, snic, snic->hba_cnt);
++	return 0;
++}
+ 
+-ulp_cleanup:
+-	cxgb3i_adapter_ddp_cleanup(t3dev);
+-free_snic:
+-	kfree(snic);
+-	return NULL;
++/**
++ * cxgb3i_adapter_open - init a s3 adapter structure and any h/w settings
++ * @t3dev: t3cdev adapter
++ */
++void cxgb3i_adapter_open(struct t3cdev *t3dev)
++{
++	struct cxgb3i_adapter *snic = cxgb3i_adapter_find_by_tdev(t3dev);
++	int err;
++
++	if (snic)
++		err = adapter_update(snic);
++	else {
++		snic = kzalloc(sizeof(*snic), GFP_KERNEL);
++		if (snic) {
++			spin_lock_init(&snic->lock);
++			snic->tdev = t3dev;
++			err = adapter_add(snic);
++		} else
++			err = -ENOMEM;
++	}
++
++	if (err < 0) {
++		cxgb3i_log_info("snic 0x%p, f 0x%x, t3dev 0x%p open, err %d.\n",
++				snic, snic ? snic->flags : 0, t3dev, err);
++		if (snic) {
++			snic->flags &= ~CXGB3I_ADAPTER_FLAG_RESET;
++			cxgb3i_adapter_close(t3dev);
++		}
++	}
+ }
+ 
+ /**
+@@ -125,31 +149,29 @@ struct cxgb3i_adapter *cxgb3i_adapter_open(struct t3cdev *t3dev)
+  */
+ void cxgb3i_adapter_close(struct t3cdev *t3dev)
+ {
++	struct cxgb3i_adapter *snic = cxgb3i_adapter_find_by_tdev(t3dev);
+ 	int i;
+-	struct cxgb3i_adapter *snic;
++
++	if (!snic || snic->flags & CXGB3I_ADAPTER_FLAG_RESET) {
++		cxgb3i_log_info("t3dev 0x%p close, snic 0x%p, f 0x%x.\n",
++				t3dev, snic, snic ? snic->flags : 0);
++		return;
++	}
+ 
+ 	/* remove from the list */
+ 	write_lock(&cxgb3i_snic_rwlock);
+-	list_for_each_entry(snic, &cxgb3i_snic_list, list_head) {
+-		if (snic->tdev == t3dev) {
+-			list_del(&snic->list_head);
+-			break;
+-		}
+-	}
++	list_del(&snic->list_head);
+ 	write_unlock(&cxgb3i_snic_rwlock);
+ 
+-	if (snic) {
+-		for (i = 0; i < snic->hba_cnt; i++) {
+-			if (snic->hba[i]) {
+-				cxgb3i_hba_host_remove(snic->hba[i]);
+-				snic->hba[i] = NULL;
+-			}
++	for (i = 0; i < snic->hba_cnt; i++) {
++		if (snic->hba[i]) {
++			cxgb3i_hba_host_remove(snic->hba[i]);
++			snic->hba[i] = NULL;
+ 		}
+-
+-		/* release ddp resources */
+-		cxgb3i_adapter_ddp_cleanup(snic->tdev);
+-		kfree(snic);
+ 	}
++	cxgb3i_log_info("t3dev 0x%p close, snic 0x%p, %u scsi hosts removed.\n",
++			t3dev, snic, snic->hba_cnt);
++	kfree(snic);
+ }
+ 
+ /**
+@@ -189,7 +211,8 @@ struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *snic,
+ 	shost = iscsi_host_alloc(&cxgb3i_host_template,
+ 				 sizeof(struct cxgb3i_hba), 1);
+ 	if (!shost) {
+-		cxgb3i_log_info("iscsi_host_alloc failed.\n");
++		cxgb3i_log_info("snic 0x%p, ndev 0x%p, host_alloc failed.\n",
++				snic, ndev);
+ 		return NULL;
+ 	}
+ 
+@@ -207,7 +230,8 @@ struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *snic,
+ 	pci_dev_get(snic->pdev);
+ 	err = iscsi_host_add(shost, &snic->pdev->dev);
+ 	if (err) {
+-		cxgb3i_log_info("iscsi_host_add failed.\n");
++		cxgb3i_log_info("snic 0x%p, ndev 0x%p, host_add failed.\n",
++				snic, ndev);
+ 		goto pci_dev_put;
+ 	}
+ 

commit 728996829b3e2a3bbacb7390e6c040dd839cdf21
+Author: Mike Christie 
+Date:   Thu Mar 5 14:46:07 2009 -0600
+
+    [SCSI] libiscsi: fix possbile null ptr session command cleanup
+    
+    If the iscsi eh fires when the current task is a nop, then
+    the task->sc pointer is null. fail_all_commands could
+    then try to do task->sc->device and oops. We actually do
+    not need to access the curr task in this path, because
+    if it is a cmd task the fail_command call will handle
+    this and if it is mgmt task then the flush of the mgmt
+    queues will handle that.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index d07017911139..dfaa8adf099e 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1603,8 +1603,11 @@ static void fail_all_commands(struct iscsi_conn *conn, unsigned lun,
+ {
+ 	struct iscsi_task *task, *tmp;
+ 
+-	if (conn->task && (conn->task->sc->device->lun == lun || lun == -1))
+-		conn->task = NULL;
++	if (conn->task) {
++		if (lun == -1 ||
++		    (conn->task->sc && conn->task->sc->device->lun == lun))
++			conn->task = NULL;
++	}
+ 
+ 	/* flush pending */
+ 	list_for_each_entry_safe(task, tmp, &conn->xmitqueue, running) {

commit 5e7facb77ff4b6961d936773fb1f175f7abf76b7
+Author: Mike Christie 
+Date:   Thu Mar 5 14:46:06 2009 -0600
+
+    [SCSI] iscsi class: remove host no argument from session creation callout
+    
+    We do not need to have llds set the host no for the session's
+    parent, because we know the session's parent is going to be
+    the host. This removes it from the session creation callback
+    and converts the drivers.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 6c61ed12f299..13d7674b293d 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -397,7 +397,7 @@ static void iscsi_iser_session_destroy(struct iscsi_cls_session *cls_session)
+ static struct iscsi_cls_session *
+ iscsi_iser_session_create(struct iscsi_endpoint *ep,
+ 			  uint16_t cmds_max, uint16_t qdepth,
+-			  uint32_t initial_cmdsn, uint32_t *hostno)
++			  uint32_t initial_cmdsn)
+ {
+ 	struct iscsi_cls_session *cls_session;
+ 	struct iscsi_session *session;
+@@ -423,7 +423,6 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep,
+ 	if (iscsi_host_add(shost,
+ 			   ep ? ib_conn->device->ib_device->dma_device : NULL))
+ 		goto free_host;
+-	*hostno = shost->host_no;
+ 
+ 	/*
+ 	 * we do not support setting can_queue cmd_per_lun from userspace yet
+diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+index 307f55e329f5..ae4a93090725 100644
+--- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
++++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+@@ -334,13 +334,12 @@ static void cxgb3i_ep_disconnect(struct iscsi_endpoint *ep)
+  * @cmds_max:		max # of commands
+  * @qdepth:		scsi queue depth
+  * @initial_cmdsn:	initial iscsi CMDSN for this session
+- * @host_no:		pointer to return host no
+  *
+  * Creates a new iSCSI session
+  */
+ static struct iscsi_cls_session *
+ cxgb3i_session_create(struct iscsi_endpoint *ep, u16 cmds_max, u16 qdepth,
+-		      u32 initial_cmdsn, u32 *host_no)
++		      u32 initial_cmdsn)
+ {
+ 	struct cxgb3i_endpoint *cep;
+ 	struct cxgb3i_hba *hba;
+@@ -359,8 +358,6 @@ cxgb3i_session_create(struct iscsi_endpoint *ep, u16 cmds_max, u16 qdepth,
+ 	cxgb3i_api_debug("ep 0x%p, cep 0x%p, hba 0x%p.\n", ep, cep, hba);
+ 	BUG_ON(hba != iscsi_host_priv(shost));
+ 
+-	*host_no = shost->host_no;
+-
+ 	cls_session = iscsi_session_setup(&cxgb3i_iscsi_transport, shost,
+ 					  cmds_max,
+ 					  sizeof(struct iscsi_tcp_task) +
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index ad8676c98c68..b3e5e08e44ab 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -765,8 +765,7 @@ iscsi_sw_tcp_conn_get_stats(struct iscsi_cls_conn *cls_conn,
+ 
+ static struct iscsi_cls_session *
+ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
+-			    uint16_t qdepth, uint32_t initial_cmdsn,
+-			    uint32_t *hostno)
++			    uint16_t qdepth, uint32_t initial_cmdsn)
+ {
+ 	struct iscsi_cls_session *cls_session;
+ 	struct iscsi_session *session;
+@@ -789,7 +788,6 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
+ 
+ 	if (iscsi_host_add(shost, NULL))
+ 		goto free_host;
+-	*hostno = shost->host_no;
+ 
+ 	cls_session = iscsi_session_setup(&iscsi_sw_tcp_transport, shost,
+ 					  cmds_max,
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 4f22f9e37c5a..2340e2c5c021 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -1197,14 +1197,15 @@ iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_endpoint *ep,
+ {
+ 	struct iscsi_transport *transport = priv->iscsi_transport;
+ 	struct iscsi_cls_session *session;
+-	uint32_t host_no;
++	struct Scsi_Host *shost;
+ 
+ 	session = transport->create_session(ep, cmds_max, queue_depth,
+-					    initial_cmdsn, &host_no);
++					    initial_cmdsn);
+ 	if (!session)
+ 		return -ENOMEM;
+ 
+-	ev->r.c_session_ret.host_no = host_no;
++	shost = iscsi_session_to_shost(session);
++	ev->r.c_session_ret.host_no = shost->host_no;
+ 	ev->r.c_session_ret.sid = session->sid;
+ 	return 0;
+ }
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index ac29fbd35544..457588e1119b 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -88,7 +88,7 @@ struct iscsi_transport {
+ 	uint64_t host_param_mask;
+ 	struct iscsi_cls_session *(*create_session) (struct iscsi_endpoint *ep,
+ 					uint16_t cmds_max, uint16_t qdepth,
+-					uint32_t sn, uint32_t *hn);
++					uint32_t sn);
+ 	void (*destroy_session) (struct iscsi_cls_session *session);
+ 	struct iscsi_cls_conn *(*create_conn) (struct iscsi_cls_session *sess,
+ 				uint32_t cid);

commit 40a06e755d8524cd0b24f795e8bdce5ad19fc41b
+Author: Mike Christie 
+Date:   Thu Mar 5 14:46:05 2009 -0600
+
+    [SCSI] libiscsi: pass session failure a session struct
+    
+    The api for conn and session failures is akward because
+    one takes a conn from the lib and one takes a session
+    from the class. This syncs up the interfaces to use
+    structs from the lib.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index d12f9794fcd0..d07017911139 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1069,10 +1069,9 @@ struct iscsi_task *iscsi_itt_to_ctask(struct iscsi_conn *conn, itt_t itt)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_itt_to_ctask);
+ 
+-void iscsi_session_failure(struct iscsi_cls_session *cls_session,
++void iscsi_session_failure(struct iscsi_session *session,
+ 			   enum iscsi_err err)
+ {
+-	struct iscsi_session *session = cls_session->dd_data;
+ 	struct iscsi_conn *conn;
+ 	struct device *dev;
+ 	unsigned long flags;
+@@ -2097,7 +2096,7 @@ EXPORT_SYMBOL_GPL(iscsi_host_alloc);
+ 
+ static void iscsi_notify_host_removed(struct iscsi_cls_session *cls_session)
+ {
+-	iscsi_session_failure(cls_session, ISCSI_ERR_INVALID_HOST);
++	iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_INVALID_HOST);
+ }
+ 
+ /**
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 84eded91b945..7ffaed2f94dd 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -378,7 +378,7 @@ extern void iscsi_conn_stop(struct iscsi_cls_conn *, int);
+ extern int iscsi_conn_bind(struct iscsi_cls_session *, struct iscsi_cls_conn *,
+ 			   int);
+ extern void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err);
+-extern void iscsi_session_failure(struct iscsi_cls_session *cls_session,
++extern void iscsi_session_failure(struct iscsi_session *session,
+ 				  enum iscsi_err err);
+ extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ 				enum iscsi_param param, char *buf);

commit 4d1083509a69a36cc1394f188b7b8956e5526a16
+Author: Mike Christie 
+Date:   Thu Mar 5 14:46:04 2009 -0600
+
+    [SCSI] iscsi lib: remove qdepth param from iscsi host allocation
+    
+    The qdepth setting was useful when we needed libiscsi to verify
+    the setting. Now we just need to make sure if older tools
+    passed in zero then we need to set some default.
+    
+    So this patch just has us use the sht->cmd_per_lun or if
+    for LLD does a host per session then we can set it on per
+    host basis.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index a50cd53e2753..6c61ed12f299 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -404,7 +404,7 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep,
+ 	struct Scsi_Host *shost;
+ 	struct iser_conn *ib_conn;
+ 
+-	shost = iscsi_host_alloc(&iscsi_iser_sht, 0, ISER_DEF_CMD_PER_LUN, 1);
++	shost = iscsi_host_alloc(&iscsi_iser_sht, 0, 1);
+ 	if (!shost)
+ 		return NULL;
+ 	shost->transportt = iscsi_iser_scsi_transport;
+diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+index f6ed9c62efb0..307f55e329f5 100644
+--- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
++++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+@@ -170,8 +170,7 @@ struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *snic,
+ 	int err;
+ 
+ 	shost = iscsi_host_alloc(&cxgb3i_host_template,
+-				 sizeof(struct cxgb3i_hba),
+-				 CXGB3I_SCSI_QDEPTH_DFLT, 1);
++				 sizeof(struct cxgb3i_hba), 1);
+ 	if (!shost) {
+ 		cxgb3i_log_info("iscsi_host_alloc failed.\n");
+ 		return NULL;
+@@ -843,7 +842,7 @@ static struct scsi_host_template cxgb3i_host_template = {
+ 	.can_queue		= CXGB3I_SCSI_QDEPTH_DFLT - 1,
+ 	.sg_tablesize		= SG_ALL,
+ 	.max_sectors		= 0xFFFF,
+-	.cmd_per_lun		= ISCSI_DEF_CMD_PER_LUN,
++	.cmd_per_lun		= CXGB3I_SCSI_QDEPTH_DFLT,
+ 	.eh_abort_handler	= iscsi_eh_abort,
+ 	.eh_device_reset_handler = iscsi_eh_device_reset,
+ 	.eh_target_reset_handler = iscsi_eh_target_reset,
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 79a706a94c68..ad8676c98c68 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -777,10 +777,11 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
+ 		return NULL;
+ 	}
+ 
+-	shost = iscsi_host_alloc(&iscsi_sw_tcp_sht, 0, qdepth, 1);
++	shost = iscsi_host_alloc(&iscsi_sw_tcp_sht, 0, 1);
+ 	if (!shost)
+ 		return NULL;
+ 	shost->transportt = iscsi_sw_tcp_scsi_transport;
++	shost->cmd_per_lun = qdepth;
+ 	shost->max_lun = iscsi_max_lun;
+ 	shost->max_id = 0;
+ 	shost->max_channel = 0;
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index ff891543df22..d12f9794fcd0 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -2046,6 +2046,9 @@ int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev)
+ 	if (!shost->can_queue)
+ 		shost->can_queue = ISCSI_DEF_XMIT_CMDS_MAX;
+ 
++	if (!shost->cmd_per_lun)
++		shost->cmd_per_lun = ISCSI_DEF_CMD_PER_LUN;
++
+ 	if (!shost->transportt->eh_timed_out)
+ 		shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out;
+ 	return scsi_add_host(shost, pdev);
+@@ -2056,15 +2059,13 @@ EXPORT_SYMBOL_GPL(iscsi_host_add);
+  * iscsi_host_alloc - allocate a host and driver data
+  * @sht: scsi host template
+  * @dd_data_size: driver host data size
+- * @qdepth: default device queue depth
+  * @xmit_can_sleep: bool indicating if LLD will queue IO from a work queue
+  *
+  * This should be called by partial offload and software iscsi drivers.
+  * To access the driver specific memory use the iscsi_host_priv() macro.
+  */
+ struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
+-				   int dd_data_size, uint16_t qdepth,
+-				   bool xmit_can_sleep)
++				   int dd_data_size, bool xmit_can_sleep)
+ {
+ 	struct Scsi_Host *shost;
+ 	struct iscsi_host *ihost;
+@@ -2072,10 +2073,6 @@ struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
+ 	shost = scsi_host_alloc(sht, sizeof(struct iscsi_host) + dd_data_size);
+ 	if (!shost)
+ 		return NULL;
+-
+-	if (qdepth == 0)
+-		qdepth = ISCSI_DEF_CMD_PER_LUN;
+-	shost->cmd_per_lun = qdepth;
+ 	ihost = shost_priv(shost);
+ 
+ 	if (xmit_can_sleep) {
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index b0b8a6992497..84eded91b945 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -346,7 +346,7 @@ extern int iscsi_host_get_param(struct Scsi_Host *shost,
+ 				enum iscsi_host_param param, char *buf);
+ extern int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev);
+ extern struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
+-					  int dd_data_size, uint16_t qdepth,
++					  int dd_data_size,
+ 					  bool xmit_can_sleep);
+ extern void iscsi_host_remove(struct Scsi_Host *shost);
+ extern void iscsi_host_free(struct Scsi_Host *shost);

commit 32ae763e3fce4192cd008956a340353a2e5c3192
+Author: Mike Christie 
+Date:   Thu Mar 5 14:46:03 2009 -0600
+
+    [SCSI] iscsi lib: have lib create work queue for transmitting IO
+    
+    We were using the shost work queue which ended up being
+    a little akward since all iscsi hosts need a thread for
+    scanning, but only drivers hooked into libiscsi need
+    a workqueue for transmitting. So this patch moves the
+    xmit workqueue to the lib.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 5f79c0a5faf3..a50cd53e2753 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -404,7 +404,7 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep,
+ 	struct Scsi_Host *shost;
+ 	struct iser_conn *ib_conn;
+ 
+-	shost = iscsi_host_alloc(&iscsi_iser_sht, 0, ISER_DEF_CMD_PER_LUN);
++	shost = iscsi_host_alloc(&iscsi_iser_sht, 0, ISER_DEF_CMD_PER_LUN, 1);
+ 	if (!shost)
+ 		return NULL;
+ 	shost->transportt = iscsi_iser_scsi_transport;
+diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
+index e209cb8dd948..9de640200ad3 100644
+--- a/drivers/infiniband/ulp/iser/iser_initiator.c
++++ b/drivers/infiniband/ulp/iser/iser_initiator.c
+@@ -661,7 +661,7 @@ void iser_snd_completion(struct iser_desc *tx_desc)
+ 
+ 	if (resume_tx) {
+ 		iser_dbg("%ld resuming tx\n",jiffies);
+-		scsi_queue_work(conn->session->host, &conn->xmitwork);
++		iscsi_conn_queue_work(conn);
+ 	}
+ 
+ 	if (tx_desc->type == ISCSI_TX_CONTROL) {
+diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+index fa2a44f37b36..f6ed9c62efb0 100644
+--- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
++++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+@@ -171,7 +171,7 @@ struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *snic,
+ 
+ 	shost = iscsi_host_alloc(&cxgb3i_host_template,
+ 				 sizeof(struct cxgb3i_hba),
+-				 CXGB3I_SCSI_QDEPTH_DFLT);
++				 CXGB3I_SCSI_QDEPTH_DFLT, 1);
+ 	if (!shost) {
+ 		cxgb3i_log_info("iscsi_host_alloc failed.\n");
+ 		return NULL;
+diff --git a/drivers/scsi/cxgb3i/cxgb3i_pdu.c b/drivers/scsi/cxgb3i/cxgb3i_pdu.c
+index 17115c230d65..7eebc9a7cb35 100644
+--- a/drivers/scsi/cxgb3i/cxgb3i_pdu.c
++++ b/drivers/scsi/cxgb3i/cxgb3i_pdu.c
+@@ -479,7 +479,7 @@ void cxgb3i_conn_tx_open(struct s3_conn *c3cn)
+ 	cxgb3i_tx_debug("cn 0x%p.\n", c3cn);
+ 	if (conn) {
+ 		cxgb3i_tx_debug("cn 0x%p, cid %d.\n", c3cn, conn->id);
+-		scsi_queue_work(conn->session->host, &conn->xmitwork);
++		iscsi_conn_queue_work(conn);
+ 	}
+ }
+ 
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 9c2e52792bdc..79a706a94c68 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -166,7 +166,7 @@ static void iscsi_sw_tcp_write_space(struct sock *sk)
+ 
+ 	tcp_sw_conn->old_write_space(sk);
+ 	ISCSI_SW_TCP_DBG(conn, "iscsi_write_space\n");
+-	scsi_queue_work(conn->session->host, &conn->xmitwork);
++	iscsi_conn_queue_work(conn);
+ }
+ 
+ static void iscsi_sw_tcp_conn_set_callbacks(struct iscsi_conn *conn)
+@@ -777,7 +777,7 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
+ 		return NULL;
+ 	}
+ 
+-	shost = iscsi_host_alloc(&iscsi_sw_tcp_sht, 0, qdepth);
++	shost = iscsi_host_alloc(&iscsi_sw_tcp_sht, 0, qdepth, 1);
+ 	if (!shost)
+ 		return NULL;
+ 	shost->transportt = iscsi_sw_tcp_scsi_transport;
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index a5168a673503..ff891543df22 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -76,6 +76,15 @@ static int iscsi_sna_lte(u32 n1, u32 n2)
+ 			    (n1 > n2 && (n2 - n1 < SNA32_CHECK)));
+ }
+ 
++inline void iscsi_conn_queue_work(struct iscsi_conn *conn)
++{
++	struct Scsi_Host *shost = conn->session->host;
++	struct iscsi_host *ihost = shost_priv(shost);
++
++	queue_work(ihost->workq, &conn->xmitwork);
++}
++EXPORT_SYMBOL_GPL(iscsi_conn_queue_work);
++
+ void
+ iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
+ {
+@@ -103,8 +112,7 @@ iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
+ 		if (!list_empty(&session->leadconn->xmitqueue) ||
+ 		    !list_empty(&session->leadconn->mgmtqueue)) {
+ 			if (!(session->tt->caps & CAP_DATA_PATH_OFFLOAD))
+-				scsi_queue_work(session->host,
+-						&session->leadconn->xmitwork);
++				iscsi_conn_queue_work(session->leadconn);
+ 		}
+ 	}
+ }
+@@ -586,7 +594,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			goto free_task;
+ 
+ 	} else
+-		scsi_queue_work(conn->session->host, &conn->xmitwork);
++		iscsi_conn_queue_work(conn);
+ 
+ 	return task;
+ 
+@@ -1160,7 +1168,7 @@ void iscsi_requeue_task(struct iscsi_task *task)
+ 	struct iscsi_conn *conn = task->conn;
+ 
+ 	list_move_tail(&task->running, &conn->requeue);
+-	scsi_queue_work(conn->session->host, &conn->xmitwork);
++	iscsi_conn_queue_work(conn);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_requeue_task);
+ 
+@@ -1413,7 +1421,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 			goto prepd_reject;
+ 		}
+ 	} else
+-		scsi_queue_work(session->host, &conn->xmitwork);
++		iscsi_conn_queue_work(conn);
+ 
+ 	session->queued_cmdsn++;
+ 	spin_unlock(&session->lock);
+@@ -1631,9 +1639,12 @@ static void fail_all_commands(struct iscsi_conn *conn, unsigned lun,
+ 
+ void iscsi_suspend_tx(struct iscsi_conn *conn)
+ {
++	struct Scsi_Host *shost = conn->session->host;
++	struct iscsi_host *ihost = shost_priv(shost);
++
+ 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+ 	if (!(conn->session->tt->caps & CAP_DATA_PATH_OFFLOAD))
+-		scsi_flush_work(conn->session->host);
++		flush_workqueue(ihost->workq);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_suspend_tx);
+ 
+@@ -1641,7 +1652,7 @@ static void iscsi_start_tx(struct iscsi_conn *conn)
+ {
+ 	clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+ 	if (!(conn->session->tt->caps & CAP_DATA_PATH_OFFLOAD))
+-		scsi_queue_work(conn->session->host, &conn->xmitwork);
++		iscsi_conn_queue_work(conn);
+ }
+ 
+ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
+@@ -2046,12 +2057,14 @@ EXPORT_SYMBOL_GPL(iscsi_host_add);
+  * @sht: scsi host template
+  * @dd_data_size: driver host data size
+  * @qdepth: default device queue depth
++ * @xmit_can_sleep: bool indicating if LLD will queue IO from a work queue
+  *
+  * This should be called by partial offload and software iscsi drivers.
+  * To access the driver specific memory use the iscsi_host_priv() macro.
+  */
+ struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
+-				   int dd_data_size, uint16_t qdepth)
++				   int dd_data_size, uint16_t qdepth,
++				   bool xmit_can_sleep)
+ {
+ 	struct Scsi_Host *shost;
+ 	struct iscsi_host *ihost;
+@@ -2063,13 +2076,25 @@ struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
+ 	if (qdepth == 0)
+ 		qdepth = ISCSI_DEF_CMD_PER_LUN;
+ 	shost->cmd_per_lun = qdepth;
+-
+ 	ihost = shost_priv(shost);
++
++	if (xmit_can_sleep) {
++		snprintf(ihost->workq_name, sizeof(ihost->workq_name),
++			"iscsi_q_%d", shost->host_no);
++		ihost->workq = create_singlethread_workqueue(ihost->workq_name);
++		if (!ihost->workq)
++			goto free_host;
++	}
++
+ 	spin_lock_init(&ihost->lock);
+ 	ihost->state = ISCSI_HOST_SETUP;
+ 	ihost->num_sessions = 0;
+ 	init_waitqueue_head(&ihost->session_removal_wq);
+ 	return shost;
++
++free_host:
++	scsi_host_put(shost);
++	return NULL;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_host_alloc);
+ 
+@@ -2101,6 +2126,8 @@ void iscsi_host_remove(struct Scsi_Host *shost)
+ 		flush_signals(current);
+ 
+ 	scsi_remove_host(shost);
++	if (ihost->workq)
++		destroy_workqueue(ihost->workq);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_host_remove);
+ 
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 898de4a73727..b0b8a6992497 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -318,6 +318,9 @@ struct iscsi_host {
+ 	spinlock_t		lock;
+ 	int			num_sessions;
+ 	int			state;
++
++	struct workqueue_struct	*workq;
++	char			workq_name[20];
+ };
+ 
+ /*
+@@ -343,7 +346,8 @@ extern int iscsi_host_get_param(struct Scsi_Host *shost,
+ 				enum iscsi_host_param param, char *buf);
+ extern int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev);
+ extern struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
+-					  int dd_data_size, uint16_t qdepth);
++					  int dd_data_size, uint16_t qdepth,
++					  bool xmit_can_sleep);
+ extern void iscsi_host_remove(struct Scsi_Host *shost);
+ extern void iscsi_host_free(struct Scsi_Host *shost);
+ 
+@@ -379,6 +383,7 @@ extern void iscsi_session_failure(struct iscsi_cls_session *cls_session,
+ extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ 				enum iscsi_param param, char *buf);
+ extern void iscsi_suspend_tx(struct iscsi_conn *conn);
++extern void iscsi_conn_queue_work(struct iscsi_conn *conn);
+ 
+ #define iscsi_conn_printk(prefix, _c, fmt, a...) \
+ 	iscsi_cls_conn_printk(prefix, ((struct iscsi_conn *)_c)->cls_conn, \

commit 06d25af4edb60f9e9c7e74d342a6963a32e3392f
+Author: Mike Christie 
+Date:   Thu Mar 5 14:46:02 2009 -0600
+
+    [SCSI] iscsi class: fix lock dep warning on logout
+    
+    We never should hit the lock up that is spit out when
+    lock dep is on and we logout. But we have been using the
+    shost work queue in a odd way. This patch has us use the
+    work queue for scanning instead of creating our own,
+    and this ends up also killing the lock dep warnings.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 75c9297694cb..4f22f9e37c5a 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -246,30 +246,13 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+ 	memset(ihost, 0, sizeof(*ihost));
+ 	atomic_set(&ihost->nr_scans, 0);
+ 	mutex_init(&ihost->mutex);
+-
+-	snprintf(ihost->scan_workq_name, sizeof(ihost->scan_workq_name),
+-		 "iscsi_scan_%d", shost->host_no);
+-	ihost->scan_workq = create_singlethread_workqueue(
+-						ihost->scan_workq_name);
+-	if (!ihost->scan_workq)
+-		return -ENOMEM;
+-	return 0;
+-}
+-
+-static int iscsi_remove_host(struct transport_container *tc, struct device *dev,
+-			     struct device *cdev)
+-{
+-	struct Scsi_Host *shost = dev_to_shost(dev);
+-	struct iscsi_cls_host *ihost = shost->shost_data;
+-
+-	destroy_workqueue(ihost->scan_workq);
+ 	return 0;
+ }
+ 
+ static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
+ 			       "iscsi_host",
+ 			       iscsi_setup_host,
+-			       iscsi_remove_host,
++			       NULL,
+ 			       NULL);
+ 
+ static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
+@@ -568,7 +551,7 @@ static void __iscsi_unblock_session(struct work_struct *work)
+ 	 * scanning from userspace).
+ 	 */
+ 	if (shost->hostt->scan_finished) {
+-		if (queue_work(ihost->scan_workq, &session->scan_work))
++		if (scsi_queue_work(shost, &session->scan_work))
+ 			atomic_inc(&ihost->nr_scans);
+ 	}
+ }
+@@ -636,14 +619,6 @@ static void __iscsi_unbind_session(struct work_struct *work)
+ 	iscsi_session_event(session, ISCSI_KEVENT_UNBIND_SESSION);
+ }
+ 
+-static int iscsi_unbind_session(struct iscsi_cls_session *session)
+-{
+-	struct Scsi_Host *shost = iscsi_session_to_shost(session);
+-	struct iscsi_cls_host *ihost = shost->shost_data;
+-
+-	return queue_work(ihost->scan_workq, &session->unbind_work);
+-}
+-
+ struct iscsi_cls_session *
+ iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
+ 		    int dd_size)
+@@ -796,7 +771,6 @@ static int iscsi_iter_destroy_conn_fn(struct device *dev, void *data)
+ void iscsi_remove_session(struct iscsi_cls_session *session)
+ {
+ 	struct Scsi_Host *shost = iscsi_session_to_shost(session);
+-	struct iscsi_cls_host *ihost = shost->shost_data;
+ 	unsigned long flags;
+ 	int err;
+ 
+@@ -821,7 +795,7 @@ void iscsi_remove_session(struct iscsi_cls_session *session)
+ 
+ 	scsi_target_unblock(&session->dev);
+ 	/* flush running scans then delete devices */
+-	flush_workqueue(ihost->scan_workq);
++	scsi_flush_work(shost);
+ 	__iscsi_unbind_session(&session->unbind_work);
+ 
+ 	/* hw iscsi may not have removed all connections from session */
+@@ -1447,7 +1421,8 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 	case ISCSI_UEVENT_UNBIND_SESSION:
+ 		session = iscsi_session_lookup(ev->u.d_session.sid);
+ 		if (session)
+-			iscsi_unbind_session(session);
++			scsi_queue_work(iscsi_session_to_shost(session),
++					&session->unbind_work);
+ 		else
+ 			err = -EINVAL;
+ 		break;
+@@ -1809,8 +1784,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 	priv->daemon_pid = -1;
+ 	priv->iscsi_transport = tt;
+ 	priv->t.user_scan = iscsi_user_scan;
+-	if (!(tt->caps & CAP_DATA_PATH_OFFLOAD))
+-		priv->t.create_work_queue = 1;
++	priv->t.create_work_queue = 1;
+ 
+ 	priv->dev.class = &iscsi_transport_class;
+ 	dev_set_name(&priv->dev, "%s", tt->name);
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index b50aabe2861e..ac29fbd35544 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -206,8 +206,6 @@ struct iscsi_cls_session {
+ struct iscsi_cls_host {
+ 	atomic_t nr_scans;
+ 	struct mutex mutex;
+-	struct workqueue_struct *scan_workq;
+-	char scan_workq_name[20];
+ };
+ 
+ extern void iscsi_host_for_each_session(struct Scsi_Host *shost,

commit e28f3d5b51ed07d822f135cd941b01e2d485270e
+Author: Mike Christie 
+Date:   Thu Mar 5 14:46:01 2009 -0600
+
+    [SCSI] libiscsi: don't cap queue depth in iscsi modules
+    
+    There is no need to cap the queue depth in the modules. We set
+    this in userspace and can do that there. For performance testing
+    with ram based targets, this is helpful since we can have very
+    high queue depths.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 4338f54c41fa..5f79c0a5faf3 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -404,7 +404,7 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep,
+ 	struct Scsi_Host *shost;
+ 	struct iser_conn *ib_conn;
+ 
+-	shost = iscsi_host_alloc(&iscsi_iser_sht, 0, ISCSI_MAX_CMD_PER_LUN);
++	shost = iscsi_host_alloc(&iscsi_iser_sht, 0, ISER_DEF_CMD_PER_LUN);
+ 	if (!shost)
+ 		return NULL;
+ 	shost->transportt = iscsi_iser_scsi_transport;
+@@ -596,7 +596,7 @@ static struct scsi_host_template iscsi_iser_sht = {
+ 	.change_queue_depth	= iscsi_change_queue_depth,
+ 	.sg_tablesize           = ISCSI_ISER_SG_TABLESIZE,
+ 	.max_sectors		= 1024,
+-	.cmd_per_lun            = ISCSI_MAX_CMD_PER_LUN,
++	.cmd_per_lun            = ISER_DEF_CMD_PER_LUN,
+ 	.eh_abort_handler       = iscsi_eh_abort,
+ 	.eh_device_reset_handler= iscsi_eh_device_reset,
+ 	.eh_target_reset_handler= iscsi_eh_target_reset,
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
+index 861119593f2b..9d529cae1f0d 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
+@@ -93,7 +93,7 @@
+ 
+ 					/* support upto 512KB in one RDMA */
+ #define ISCSI_ISER_SG_TABLESIZE         (0x80000 >> SHIFT_4K)
+-#define ISCSI_ISER_MAX_LUN		256
++#define ISER_DEF_CMD_PER_LUN		128
+ 
+ /* QP settings */
+ /* Maximal bounds on received asynchronous PDUs */
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 701457cca08a..a5168a673503 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1451,8 +1451,6 @@ EXPORT_SYMBOL_GPL(iscsi_queuecommand);
+ 
+ int iscsi_change_queue_depth(struct scsi_device *sdev, int depth)
+ {
+-	if (depth > ISCSI_MAX_CMD_PER_LUN)
+-		depth = ISCSI_MAX_CMD_PER_LUN;
+ 	scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
+ 	return sdev->queue_depth;
+ }
+@@ -2062,13 +2060,8 @@ struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
+ 	if (!shost)
+ 		return NULL;
+ 
+-	if (qdepth > ISCSI_MAX_CMD_PER_LUN || qdepth < 1) {
+-		if (qdepth != 0)
+-			printk(KERN_ERR "iscsi: invalid queue depth of %d. "
+-			       "Queue depth must be between 1 and %d.\n",
+-			       qdepth, ISCSI_MAX_CMD_PER_LUN);
++	if (qdepth == 0)
+ 		qdepth = ISCSI_DEF_CMD_PER_LUN;
+-	}
+ 	shost->cmd_per_lun = qdepth;
+ 
+ 	ihost = shost_priv(shost);
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 67542aa3aedc..898de4a73727 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -48,8 +48,7 @@ struct device;
+ #define ISCSI_DEF_XMIT_CMDS_MAX	128	/* must be power of 2 */
+ #define ISCSI_MGMT_CMDS_MAX	15
+ 
+-#define ISCSI_DEF_CMD_PER_LUN		32
+-#define ISCSI_MAX_CMD_PER_LUN		128
++#define ISCSI_DEF_CMD_PER_LUN	32
+ 
+ /* Task Mgmt states */
+ enum {

commit c93f87c727ad4e6a5d94cfab219b1492ccc5ca5e
+Author: Mike Christie 
+Date:   Thu Mar 5 14:46:00 2009 -0600
+
+    [SCSI] iscsi_tcp: replace scsi_debug/tcp_debug logging with iscsi conn logging
+    
+    This makes the logging a compile time option and replaces
+    the tcp_debug macro with a iscsi connection one that prints
+    out a driver model id prefix.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 5a08ca48fb3a..9c2e52792bdc 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -48,13 +48,6 @@ MODULE_AUTHOR("Mike Christie , "
+ 	      "Alex Aizman ");
+ MODULE_DESCRIPTION("iSCSI/TCP data-path");
+ MODULE_LICENSE("GPL");
+-#undef DEBUG_TCP
+-
+-#ifdef DEBUG_TCP
+-#define debug_tcp(fmt...) printk(KERN_INFO "tcp: " fmt)
+-#else
+-#define debug_tcp(fmt...)
+-#endif
+ 
+ static struct scsi_transport_template *iscsi_sw_tcp_scsi_transport;
+ static struct scsi_host_template iscsi_sw_tcp_sht;
+@@ -63,6 +56,21 @@ static struct iscsi_transport iscsi_sw_tcp_transport;
+ static unsigned int iscsi_max_lun = 512;
+ module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
+ 
++static int iscsi_sw_tcp_dbg;
++module_param_named(debug_iscsi_tcp, iscsi_sw_tcp_dbg, int,
++		   S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(debug_iscsi_tcp, "Turn on debugging for iscsi_tcp module "
++		 "Set to 1 to turn on, and zero to turn off. Default is off.");
++
++#define ISCSI_SW_TCP_DBG(_conn, dbg_fmt, arg...)		\
++	do {							\
++		if (iscsi_sw_tcp_dbg)				\
++			iscsi_conn_printk(KERN_INFO, _conn,	\
++					     "%s " dbg_fmt,	\
++					     __func__, ##arg);	\
++	} while (0);
++
++
+ /**
+  * iscsi_sw_tcp_recv - TCP receive in sendfile fashion
+  * @rd_desc: read descriptor
+@@ -77,7 +85,7 @@ static int iscsi_sw_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 	unsigned int consumed, total_consumed = 0;
+ 	int status;
+ 
+-	debug_tcp("in %d bytes\n", skb->len - offset);
++	ISCSI_SW_TCP_DBG(conn, "in %d bytes\n", skb->len - offset);
+ 
+ 	do {
+ 		status = 0;
+@@ -86,7 +94,8 @@ static int iscsi_sw_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 		total_consumed += consumed;
+ 	} while (consumed != 0 && status != ISCSI_TCP_SKB_DONE);
+ 
+-	debug_tcp("read %d bytes status %d\n", skb->len - offset, status);
++	ISCSI_SW_TCP_DBG(conn, "read %d bytes status %d\n",
++			 skb->len - offset, status);
+ 	return total_consumed;
+ }
+ 
+@@ -131,7 +140,8 @@ static void iscsi_sw_tcp_state_change(struct sock *sk)
+ 	if ((sk->sk_state == TCP_CLOSE_WAIT ||
+ 	     sk->sk_state == TCP_CLOSE) &&
+ 	    !atomic_read(&sk->sk_rmem_alloc)) {
+-		debug_tcp("iscsi_tcp_state_change: TCP_CLOSE|TCP_CLOSE_WAIT\n");
++		ISCSI_SW_TCP_DBG(conn, "iscsi_tcp_state_change: "
++				 "TCP_CLOSE|TCP_CLOSE_WAIT\n");
+ 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ 	}
+ 
+@@ -155,7 +165,7 @@ static void iscsi_sw_tcp_write_space(struct sock *sk)
+ 	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
+ 
+ 	tcp_sw_conn->old_write_space(sk);
+-	debug_tcp("iscsi_write_space: cid %d\n", conn->id);
++	ISCSI_SW_TCP_DBG(conn, "iscsi_write_space\n");
+ 	scsi_queue_work(conn->session->host, &conn->xmitwork);
+ }
+ 
+@@ -283,7 +293,7 @@ static int iscsi_sw_tcp_xmit(struct iscsi_conn *conn)
+ 		}
+ 	}
+ 
+-	debug_tcp("xmit %d bytes\n", consumed);
++	ISCSI_SW_TCP_DBG(conn, "xmit %d bytes\n", consumed);
+ 
+ 	conn->txdata_octets += consumed;
+ 	return consumed;
+@@ -291,7 +301,7 @@ static int iscsi_sw_tcp_xmit(struct iscsi_conn *conn)
+ error:
+ 	/* Transmit error. We could initiate error recovery
+ 	 * here. */
+-	debug_tcp("Error sending PDU, errno=%d\n", rc);
++	ISCSI_SW_TCP_DBG(conn, "Error sending PDU, errno=%d\n", rc);
+ 	iscsi_conn_failure(conn, rc);
+ 	return -EIO;
+ }
+@@ -334,9 +344,10 @@ static int iscsi_sw_tcp_send_hdr_done(struct iscsi_tcp_conn *tcp_conn,
+ 	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
+ 
+ 	tcp_sw_conn->out.segment = tcp_sw_conn->out.data_segment;
+-	debug_tcp("Header done. Next segment size %u total_size %u\n",
+-		  tcp_sw_conn->out.segment.size,
+-		  tcp_sw_conn->out.segment.total_size);
++	ISCSI_SW_TCP_DBG(tcp_conn->iscsi_conn,
++			 "Header done. Next segment size %u total_size %u\n",
++			 tcp_sw_conn->out.segment.size,
++			 tcp_sw_conn->out.segment.total_size);
+ 	return 0;
+ }
+ 
+@@ -346,8 +357,8 @@ static void iscsi_sw_tcp_send_hdr_prep(struct iscsi_conn *conn, void *hdr,
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
+ 
+-	debug_tcp("%s(%p%s)\n", __func__, tcp_conn,
+-			conn->hdrdgst_en? ", digest enabled" : "");
++	ISCSI_SW_TCP_DBG(conn, "%s\n", conn->hdrdgst_en ?
++			 "digest enabled" : "digest disabled");
+ 
+ 	/* Clear the data segment - needs to be filled in by the
+ 	 * caller using iscsi_tcp_send_data_prep() */
+@@ -389,9 +400,9 @@ iscsi_sw_tcp_send_data_prep(struct iscsi_conn *conn, struct scatterlist *sg,
+ 	struct hash_desc *tx_hash = NULL;
+ 	unsigned int hdr_spec_len;
+ 
+-	debug_tcp("%s(%p, offset=%d, datalen=%d%s)\n", __func__,
+-			tcp_conn, offset, len,
+-			conn->datadgst_en? ", digest enabled" : "");
++	ISCSI_SW_TCP_DBG(conn, "offset=%d, datalen=%d %s\n", offset, len,
++			 conn->datadgst_en ?
++			 "digest enabled" : "digest disabled");
+ 
+ 	/* Make sure the datalen matches what the caller
+ 	   said he would send. */
+@@ -415,8 +426,8 @@ iscsi_sw_tcp_send_linear_data_prep(struct iscsi_conn *conn, void *data,
+ 	struct hash_desc *tx_hash = NULL;
+ 	unsigned int hdr_spec_len;
+ 
+-	debug_tcp("%s(%p, datalen=%d%s)\n", __func__, tcp_conn, len,
+-		  conn->datadgst_en? ", digest enabled" : "");
++	ISCSI_SW_TCP_DBG(conn, "datalen=%zd %s\n", len, conn->datadgst_en ?
++			 "digest enabled" : "digest disabled");
+ 
+ 	/* Make sure the datalen matches what the caller
+ 	   said he would send. */

commit 0ab1c2529e6a70e1b3c63fe9c6b41d4049758a8e
+Author: Mike Christie 
+Date:   Thu Mar 5 14:45:59 2009 -0600
+
+    [SCSI] libiscsi_tcp: replace tcp_debug/scsi_debug logging with session/conn logging
+    
+    This makes the logging a compile time option and replaces
+    the scsi_debug and tcp_debug macro with session and connection ones
+    that print out a driver model id prefix.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
+index e7705d3532c9..91f8ce4d8d08 100644
+--- a/drivers/scsi/libiscsi_tcp.c
++++ b/drivers/scsi/libiscsi_tcp.c
+@@ -49,13 +49,21 @@ MODULE_AUTHOR("Mike Christie , "
+ 	      "Alex Aizman ");
+ MODULE_DESCRIPTION("iSCSI/TCP data-path");
+ MODULE_LICENSE("GPL");
+-#undef DEBUG_TCP
+ 
+-#ifdef DEBUG_TCP
+-#define debug_tcp(fmt...) printk(KERN_INFO "tcp: " fmt)
+-#else
+-#define debug_tcp(fmt...)
+-#endif
++static int iscsi_dbg_libtcp;
++module_param_named(debug_libiscsi_tcp, iscsi_dbg_libtcp, int,
++		   S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(debug_libiscsi_tcp, "Turn on debugging for libiscsi_tcp "
++		 "module. Set to 1 to turn on, and zero to turn off. Default "
++		 "is off.");
++
++#define ISCSI_DBG_TCP(_conn, dbg_fmt, arg...)			\
++	do {							\
++		if (iscsi_dbg_libtcp)				\
++			iscsi_conn_printk(KERN_INFO, _conn,	\
++					     "%s " dbg_fmt,	\
++					     __func__, ##arg);	\
++	} while (0);
+ 
+ static int iscsi_tcp_hdr_recv_done(struct iscsi_tcp_conn *tcp_conn,
+ 				   struct iscsi_segment *segment);
+@@ -123,18 +131,13 @@ static void iscsi_tcp_segment_map(struct iscsi_segment *segment, int recv)
+ 	if (page_count(sg_page(sg)) >= 1 && !recv)
+ 		return;
+ 
+-	debug_tcp("iscsi_tcp_segment_map %s %p\n", recv ? "recv" : "xmit",
+-		  segment);
+ 	segment->sg_mapped = kmap_atomic(sg_page(sg), KM_SOFTIRQ0);
+ 	segment->data = segment->sg_mapped + sg->offset + segment->sg_offset;
+ }
+ 
+ void iscsi_tcp_segment_unmap(struct iscsi_segment *segment)
+ {
+-	debug_tcp("iscsi_tcp_segment_unmap %p\n", segment);
+-
+ 	if (segment->sg_mapped) {
+-		debug_tcp("iscsi_tcp_segment_unmap valid\n");
+ 		kunmap_atomic(segment->sg_mapped, KM_SOFTIRQ0);
+ 		segment->sg_mapped = NULL;
+ 		segment->data = NULL;
+@@ -180,8 +183,9 @@ int iscsi_tcp_segment_done(struct iscsi_tcp_conn *tcp_conn,
+ 	struct scatterlist sg;
+ 	unsigned int pad;
+ 
+-	debug_tcp("copied %u %u size %u %s\n", segment->copied, copied,
+-		  segment->size, recv ? "recv" : "xmit");
++	ISCSI_DBG_TCP(tcp_conn->iscsi_conn, "copied %u %u size %u %s\n",
++		      segment->copied, copied, segment->size,
++		      recv ? "recv" : "xmit");
+ 	if (segment->hash && copied) {
+ 		/*
+ 		 * If a segment is kmapd we must unmap it before sending
+@@ -214,8 +218,8 @@ int iscsi_tcp_segment_done(struct iscsi_tcp_conn *tcp_conn,
+ 	iscsi_tcp_segment_unmap(segment);
+ 
+ 	/* Do we have more scatterlist entries? */
+-	debug_tcp("total copied %u total size %u\n", segment->total_copied,
+-		   segment->total_size);
++	ISCSI_DBG_TCP(tcp_conn->iscsi_conn, "total copied %u total size %u\n",
++		      segment->total_copied, segment->total_size);
+ 	if (segment->total_copied < segment->total_size) {
+ 		/* Proceed to the next entry in the scatterlist. */
+ 		iscsi_tcp_segment_init_sg(segment, sg_next(segment->sg),
+@@ -229,7 +233,8 @@ int iscsi_tcp_segment_done(struct iscsi_tcp_conn *tcp_conn,
+ 	if (!(tcp_conn->iscsi_conn->session->tt->caps & CAP_PADDING_OFFLOAD)) {
+ 		pad = iscsi_padding(segment->total_copied);
+ 		if (pad != 0) {
+-			debug_tcp("consume %d pad bytes\n", pad);
++			ISCSI_DBG_TCP(tcp_conn->iscsi_conn,
++				      "consume %d pad bytes\n", pad);
+ 			segment->total_size += pad;
+ 			segment->size = pad;
+ 			segment->data = segment->padbuf;
+@@ -278,13 +283,13 @@ iscsi_tcp_segment_recv(struct iscsi_tcp_conn *tcp_conn,
+ 
+ 	while (!iscsi_tcp_segment_done(tcp_conn, segment, 1, copy)) {
+ 		if (copied == len) {
+-			debug_tcp("iscsi_tcp_segment_recv copied %d bytes\n",
+-				  len);
++			ISCSI_DBG_TCP(tcp_conn->iscsi_conn,
++				      "copied %d bytes\n", len);
+ 			break;
+ 		}
+ 
+ 		copy = min(len - copied, segment->size - segment->copied);
+-		debug_tcp("iscsi_tcp_segment_recv copying %d\n", copy);
++		ISCSI_DBG_TCP(tcp_conn->iscsi_conn, "copying %d\n", copy);
+ 		memcpy(segment->data + segment->copied, ptr + copied, copy);
+ 		copied += copy;
+ 	}
+@@ -311,7 +316,7 @@ iscsi_tcp_dgst_verify(struct iscsi_tcp_conn *tcp_conn,
+ 
+ 	if (memcmp(segment->recv_digest, segment->digest,
+ 		   segment->digest_len)) {
+-		debug_scsi("digest mismatch\n");
++		ISCSI_DBG_TCP(tcp_conn->iscsi_conn, "digest mismatch\n");
+ 		return 0;
+ 	}
+ 
+@@ -355,12 +360,8 @@ iscsi_segment_seek_sg(struct iscsi_segment *segment,
+ 	struct scatterlist *sg;
+ 	unsigned int i;
+ 
+-	debug_scsi("iscsi_segment_seek_sg offset %u size %llu\n",
+-		  offset, size);
+ 	__iscsi_segment_init(segment, size, done, hash);
+ 	for_each_sg(sg_list, sg, sg_count, i) {
+-		debug_scsi("sg %d, len %u offset %u\n", i, sg->length,
+-			   sg->offset);
+ 		if (offset < sg->length) {
+ 			iscsi_tcp_segment_init_sg(segment, sg, offset);
+ 			return 0;
+@@ -382,8 +383,9 @@ EXPORT_SYMBOL_GPL(iscsi_segment_seek_sg);
+  */
+ void iscsi_tcp_hdr_recv_prep(struct iscsi_tcp_conn *tcp_conn)
+ {
+-	debug_tcp("iscsi_tcp_hdr_recv_prep(%p%s)\n", tcp_conn,
+-		  tcp_conn->iscsi_conn->hdrdgst_en ? ", digest enabled" : "");
++	ISCSI_DBG_TCP(tcp_conn->iscsi_conn,
++		      "(%s)\n", tcp_conn->iscsi_conn->hdrdgst_en ?
++		      "digest enabled" : "digest disabled");
+ 	iscsi_segment_init_linear(&tcp_conn->in.segment,
+ 				tcp_conn->in.hdr_buf, sizeof(struct iscsi_hdr),
+ 				iscsi_tcp_hdr_recv_done, NULL);
+@@ -446,7 +448,7 @@ void iscsi_tcp_cleanup_task(struct iscsi_task *task)
+ 	while (__kfifo_get(tcp_task->r2tqueue, (void*)&r2t, sizeof(void*))) {
+ 		__kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
+ 			    sizeof(void*));
+-		debug_scsi("iscsi_tcp_cleanup_task pending r2t dropped\n");
++		ISCSI_DBG_TCP(task->conn, "pending r2t dropped\n");
+ 	}
+ 
+ 	r2t = tcp_task->r2t;
+@@ -476,8 +478,8 @@ static int iscsi_tcp_data_in(struct iscsi_conn *conn, struct iscsi_task *task)
+ 		return 0;
+ 
+ 	if (tcp_task->exp_datasn != datasn) {
+-		debug_tcp("%s: task->exp_datasn(%d) != rhdr->datasn(%d)\n",
+-		          __func__, tcp_task->exp_datasn, datasn);
++		ISCSI_DBG_TCP(conn, "task->exp_datasn(%d) != rhdr->datasn(%d)"
++			      "\n", tcp_task->exp_datasn, datasn);
+ 		return ISCSI_ERR_DATASN;
+ 	}
+ 
+@@ -485,9 +487,9 @@ static int iscsi_tcp_data_in(struct iscsi_conn *conn, struct iscsi_task *task)
+ 
+ 	tcp_task->data_offset = be32_to_cpu(rhdr->offset);
+ 	if (tcp_task->data_offset + tcp_conn->in.datalen > total_in_length) {
+-		debug_tcp("%s: data_offset(%d) + data_len(%d) > total_length_in(%d)\n",
+-		          __func__, tcp_task->data_offset,
+-		          tcp_conn->in.datalen, total_in_length);
++		ISCSI_DBG_TCP(conn, "data_offset(%d) + data_len(%d) > "
++			      "total_length_in(%d)\n", tcp_task->data_offset,
++			      tcp_conn->in.datalen, total_in_length);
+ 		return ISCSI_ERR_DATA_OFFSET;
+ 	}
+ 
+@@ -518,8 +520,8 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
+ 	}
+ 
+ 	if (tcp_task->exp_datasn != r2tsn){
+-		debug_tcp("%s: task->exp_datasn(%d) != rhdr->r2tsn(%d)\n",
+-		          __func__, tcp_task->exp_datasn, r2tsn);
++		ISCSI_DBG_TCP(conn, "task->exp_datasn(%d) != rhdr->r2tsn(%d)\n",
++			      tcp_task->exp_datasn, r2tsn);
+ 		return ISCSI_ERR_R2TSN;
+ 	}
+ 
+@@ -552,9 +554,9 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
+ 	}
+ 
+ 	if (r2t->data_length > session->max_burst)
+-		debug_scsi("invalid R2T with data len %u and max burst %u."
+-			   "Attempting to execute request.\n",
+-			    r2t->data_length, session->max_burst);
++		ISCSI_DBG_TCP(conn, "invalid R2T with data len %u and max "
++			      "burst %u. Attempting to execute request.\n",
++			      r2t->data_length, session->max_burst);
+ 
+ 	r2t->data_offset = be32_to_cpu(rhdr->data_offset);
+ 	if (r2t->data_offset + r2t->data_length > scsi_out(task->sc)->length) {
+@@ -641,8 +643,8 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 	if (rc)
+ 		return rc;
+ 
+-	debug_tcp("opcode 0x%x ahslen %d datalen %d\n",
+-		  opcode, ahslen, tcp_conn->in.datalen);
++	ISCSI_DBG_TCP(conn, "opcode 0x%x ahslen %d datalen %d\n",
++		      opcode, ahslen, tcp_conn->in.datalen);
+ 
+ 	switch(opcode) {
+ 	case ISCSI_OP_SCSI_DATA_IN:
+@@ -674,10 +676,10 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 			    !(conn->session->tt->caps & CAP_DIGEST_OFFLOAD))
+ 				rx_hash = tcp_conn->rx_hash;
+ 
+-			debug_tcp("iscsi_tcp_begin_data_in(%p, offset=%d, "
+-				  "datalen=%d)\n", tcp_conn,
+-				  tcp_task->data_offset,
+-				  tcp_conn->in.datalen);
++			ISCSI_DBG_TCP(conn, "iscsi_tcp_begin_data_in( "
++				     "offset=%d, datalen=%d)\n",
++				      tcp_task->data_offset,
++				      tcp_conn->in.datalen);
+ 			rc = iscsi_segment_seek_sg(&tcp_conn->in.segment,
+ 						   sdb->table.sgl,
+ 						   sdb->table.nents,
+@@ -854,10 +856,10 @@ int iscsi_tcp_recv_skb(struct iscsi_conn *conn, struct sk_buff *skb,
+ 	unsigned int consumed = 0;
+ 	int rc = 0;
+ 
+-	debug_tcp("in %d bytes\n", skb->len - offset);
++	ISCSI_DBG_TCP(conn, "in %d bytes\n", skb->len - offset);
+ 
+ 	if (unlikely(conn->suspend_rx)) {
+-		debug_tcp("conn %d Rx suspended!\n", conn->id);
++		ISCSI_DBG_TCP(conn, "Rx suspended!\n");
+ 		*status = ISCSI_TCP_SUSPENDED;
+ 		return 0;
+ 	}
+@@ -874,15 +876,16 @@ int iscsi_tcp_recv_skb(struct iscsi_conn *conn, struct sk_buff *skb,
+ 
+ 		avail = skb_seq_read(consumed, &ptr, &seq);
+ 		if (avail == 0) {
+-			debug_tcp("no more data avail. Consumed %d\n",
+-				  consumed);
++			ISCSI_DBG_TCP(conn, "no more data avail. Consumed %d\n",
++				      consumed);
+ 			*status = ISCSI_TCP_SKB_DONE;
+ 			skb_abort_seq_read(&seq);
+ 			goto skb_done;
+ 		}
+ 		BUG_ON(segment->copied >= segment->size);
+ 
+-		debug_tcp("skb %p ptr=%p avail=%u\n", skb, ptr, avail);
++		ISCSI_DBG_TCP(conn, "skb %p ptr=%p avail=%u\n", skb, ptr,
++			      avail);
+ 		rc = iscsi_tcp_segment_recv(tcp_conn, segment, ptr, avail);
+ 		BUG_ON(rc == 0);
+ 		consumed += rc;
+@@ -895,11 +898,11 @@ int iscsi_tcp_recv_skb(struct iscsi_conn *conn, struct sk_buff *skb,
+ 
+ segment_done:
+ 	*status = ISCSI_TCP_SEGMENT_DONE;
+-	debug_tcp("segment done\n");
++	ISCSI_DBG_TCP(conn, "segment done\n");
+ 	rc = segment->done(tcp_conn, segment);
+ 	if (rc != 0) {
+ 		*status = ISCSI_TCP_CONN_ERR;
+-		debug_tcp("Error receiving PDU, errno=%d\n", rc);
++		ISCSI_DBG_TCP(conn, "Error receiving PDU, errno=%d\n", rc);
+ 		iscsi_conn_failure(conn, rc);
+ 		return 0;
+ 	}
+@@ -929,8 +932,7 @@ int iscsi_tcp_task_init(struct iscsi_task *task)
+ 		 * mgmt tasks do not have a scatterlist since they come
+ 		 * in from the iscsi interface.
+ 		 */
+-		debug_scsi("mtask deq [cid %d itt 0x%x]\n", conn->id,
+-			   task->itt);
++		ISCSI_DBG_TCP(conn, "mtask deq [itt 0x%x]\n", task->itt);
+ 
+ 		return conn->session->tt->init_pdu(task, 0, task->data_count);
+ 	}
+@@ -939,9 +941,8 @@ int iscsi_tcp_task_init(struct iscsi_task *task)
+ 	tcp_task->exp_datasn = 0;
+ 
+ 	/* Prepare PDU, optionally w/ immediate data */
+-	debug_scsi("task deq [cid %d itt 0x%x imm %d unsol %d]\n",
+-		    conn->id, task->itt, task->imm_count,
+-		    task->unsol_r2t.data_length);
++	ISCSI_DBG_TCP(conn, "task deq [itt 0x%x imm %d unsol %d]\n",
++		      task->itt, task->imm_count, task->unsol_r2t.data_length);
+ 
+ 	err = conn->session->tt->init_pdu(task, 0, task->imm_count);
+ 	if (err)
+@@ -965,7 +966,8 @@ static struct iscsi_r2t_info *iscsi_tcp_get_curr_r2t(struct iscsi_task *task)
+ 			r2t = tcp_task->r2t;
+ 			/* Continue with this R2T? */
+ 			if (r2t->data_length <= r2t->sent) {
+-				debug_scsi("  done with r2t %p\n", r2t);
++				ISCSI_DBG_TCP(task->conn,
++					      "  done with r2t %p\n", r2t);
+ 				__kfifo_put(tcp_task->r2tpool.queue,
+ 					    (void *)&tcp_task->r2t,
+ 					    sizeof(void *));
+@@ -1019,7 +1021,7 @@ int iscsi_tcp_task_xmit(struct iscsi_task *task)
+ 	r2t = iscsi_tcp_get_curr_r2t(task);
+ 	if (r2t == NULL) {
+ 		/* Waiting for more R2Ts to arrive. */
+-		debug_tcp("no R2Ts yet\n");
++		ISCSI_DBG_TCP(conn, "no R2Ts yet\n");
+ 		return 0;
+ 	}
+ 
+@@ -1028,9 +1030,9 @@ int iscsi_tcp_task_xmit(struct iscsi_task *task)
+ 		return rc;
+ 	iscsi_prep_data_out_pdu(task, r2t, (struct iscsi_data *) task->hdr);
+ 
+-	debug_scsi("sol dout %p [dsn %d itt 0x%x doff %d dlen %d]\n",
+-		   r2t, r2t->datasn - 1, task->hdr->itt,
+-		   r2t->data_offset + r2t->sent, r2t->data_count);
++	ISCSI_DBG_TCP(conn, "sol dout %p [dsn %d itt 0x%x doff %d dlen %d]\n",
++		      r2t, r2t->datasn - 1, task->hdr->itt,
++		      r2t->data_offset + r2t->sent, r2t->data_count);
+ 
+ 	rc = conn->session->tt->init_pdu(task, r2t->data_offset + r2t->sent,
+ 					 r2t->data_count);

commit 1b2c7af877f427a2b25583c9033616c9ebd30aed
+Author: Mike Christie 
+Date:   Thu Mar 5 14:45:58 2009 -0600
+
+    [SCSI] libiscsi: replace scsi_debug logging with session/conn logging
+    
+    This makes the logging a compile time option and replaces
+    the scsi_debug macro with session and connection ones
+    that print out a driver model id prefix.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index c33e28fd49bc..701457cca08a 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -38,6 +38,28 @@
+ #include 
+ #include 
+ 
++static int iscsi_dbg_lib;
++module_param_named(debug_libiscsi, iscsi_dbg_lib, int, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(debug_libiscsi, "Turn on debugging for libiscsi module. "
++		 "Set to 1 to turn on, and zero to turn off. Default "
++		 "is off.");
++
++#define ISCSI_DBG_CONN(_conn, dbg_fmt, arg...)			\
++	do {							\
++		if (iscsi_dbg_lib)				\
++			iscsi_conn_printk(KERN_INFO, _conn,	\
++					     "%s " dbg_fmt,	\
++					     __func__, ##arg);	\
++	} while (0);
++
++#define ISCSI_DBG_SESSION(_session, dbg_fmt, arg...)			\
++	do {								\
++		if (iscsi_dbg_lib)					\
++			iscsi_session_printk(KERN_INFO, _session,	\
++					     "%s " dbg_fmt,		\
++					     __func__, ##arg);		\
++	} while (0);
++
+ /* Serial Number Arithmetic, 32 bits, less than, RFC1982 */
+ #define SNA32_CHECK 2147483648UL
+ 
+@@ -176,10 +198,11 @@ static int iscsi_prep_ecdb_ahs(struct iscsi_task *task)
+ 	ecdb_ahdr->reserved = 0;
+ 	memcpy(ecdb_ahdr->ecdb, cmd->cmnd + ISCSI_CDB_SIZE, rlen);
+ 
+-	debug_scsi("iscsi_prep_ecdb_ahs: varlen_cdb_len %d "
+-		   "rlen %d pad_len %d ahs_length %d iscsi_headers_size %u\n",
+-		   cmd->cmd_len, rlen, pad_len, ahslength, task->hdr_len);
+-
++	ISCSI_DBG_SESSION(task->conn->session,
++			  "iscsi_prep_ecdb_ahs: varlen_cdb_len %d "
++		          "rlen %d pad_len %d ahs_length %d iscsi_headers_size "
++		          "%u\n", cmd->cmd_len, rlen, pad_len, ahslength,
++		          task->hdr_len);
+ 	return 0;
+ }
+ 
+@@ -201,10 +224,11 @@ static int iscsi_prep_bidi_ahs(struct iscsi_task *task)
+ 	rlen_ahdr->reserved = 0;
+ 	rlen_ahdr->read_length = cpu_to_be32(scsi_in(sc)->length);
+ 
+-	debug_scsi("bidi-in rlen_ahdr->read_length(%d) "
+-		   "rlen_ahdr->ahslength(%d)\n",
+-		   be32_to_cpu(rlen_ahdr->read_length),
+-		   be16_to_cpu(rlen_ahdr->ahslength));
++	ISCSI_DBG_SESSION(task->conn->session,
++			  "bidi-in rlen_ahdr->read_length(%d) "
++		          "rlen_ahdr->ahslength(%d)\n",
++		          be32_to_cpu(rlen_ahdr->read_length),
++		          be16_to_cpu(rlen_ahdr->ahslength));
+ 	return 0;
+ }
+ 
+@@ -335,13 +359,15 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
+ 	list_move_tail(&task->running, &conn->run_list);
+ 
+ 	conn->scsicmd_pdus_cnt++;
+-	debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x len %d "
+-		   "bidi_len %d cmdsn %d win %d]\n", scsi_bidi_cmnd(sc) ?
+-		   "bidirectional" : sc->sc_data_direction == DMA_TO_DEVICE ?
+-		   "write" : "read", conn->id, sc, sc->cmnd[0], task->itt,
+-		   scsi_bufflen(sc),
+-		   scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0,
+-		   session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
++	ISCSI_DBG_SESSION(session, "iscsi prep [%s cid %d sc %p cdb 0x%x "
++			  "itt 0x%x len %d bidi_len %d cmdsn %d win %d]\n",
++			  scsi_bidi_cmnd(sc) ? "bidirectional" :
++			  sc->sc_data_direction == DMA_TO_DEVICE ?
++			  "write" : "read", conn->id, sc, sc->cmnd[0],
++			  task->itt, scsi_bufflen(sc),
++			  scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0,
++			  session->cmdsn,
++			  session->max_cmdsn - session->exp_cmdsn + 1);
+ 	return 0;
+ }
+ 
+@@ -483,9 +509,9 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn,
+ 
+ 	task->state = ISCSI_TASK_RUNNING;
+ 	list_move_tail(&task->running, &conn->mgmt_run_list);
+-	debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n",
+-		   hdr->opcode & ISCSI_OPCODE_MASK, hdr->itt,
+-		   task->data_count);
++	ISCSI_DBG_SESSION(session, "mgmtpdu [op 0x%x hdr->itt 0x%x "
++			  "datalen %d]\n", hdr->opcode & ISCSI_OPCODE_MASK,
++			  hdr->itt, task->data_count);
+ 	return 0;
+ }
+ 
+@@ -637,8 +663,9 @@ static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 
+ 		memcpy(sc->sense_buffer, data + 2,
+ 		       min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
+-		debug_scsi("copied %d bytes of sense\n",
+-			   min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
++		ISCSI_DBG_SESSION(session, "copied %d bytes of sense\n",
++				  min_t(uint16_t, senselen,
++				  SCSI_SENSE_BUFFERSIZE));
+ 	}
+ 
+ 	if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW |
+@@ -666,8 +693,8 @@ static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+ 	}
+ out:
+-	debug_scsi("done [sc %lx res %d itt 0x%x]\n",
+-		   (long)sc, sc->result, task->itt);
++	ISCSI_DBG_SESSION(session, "done [sc %p res %d itt 0x%x]\n",
++			  sc, sc->result, task->itt);
+ 	conn->scsirsp_pdus_cnt++;
+ 
+ 	__iscsi_put_task(task);
+@@ -835,8 +862,8 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	else
+ 		itt = ~0U;
+ 
+-	debug_scsi("[op 0x%x cid %d itt 0x%x len %d]\n",
+-		   opcode, conn->id, itt, datalen);
++	ISCSI_DBG_SESSION(session, "[op 0x%x cid %d itt 0x%x len %d]\n",
++			  opcode, conn->id, itt, datalen);
+ 
+ 	if (itt == ~0U) {
+ 		iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
+@@ -1095,10 +1122,10 @@ static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn)
+ 	 * Check for iSCSI window and take care of CmdSN wrap-around
+ 	 */
+ 	if (!iscsi_sna_lte(session->queued_cmdsn, session->max_cmdsn)) {
+-		debug_scsi("iSCSI CmdSN closed. ExpCmdSn %u MaxCmdSN %u "
+-			   "CmdSN %u/%u\n", session->exp_cmdsn,
+-			   session->max_cmdsn, session->cmdsn,
+-			   session->queued_cmdsn);
++		ISCSI_DBG_SESSION(session, "iSCSI CmdSN closed. ExpCmdSn "
++				  "%u MaxCmdSN %u CmdSN %u/%u\n",
++				  session->exp_cmdsn, session->max_cmdsn,
++				  session->cmdsn, session->queued_cmdsn);
+ 		return -ENOSPC;
+ 	}
+ 	return 0;
+@@ -1152,7 +1179,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 
+ 	spin_lock_bh(&conn->session->lock);
+ 	if (unlikely(conn->suspend_tx)) {
+-		debug_scsi("conn %d Tx suspended!\n", conn->id);
++		ISCSI_DBG_SESSION(conn->session, "Tx suspended!\n");
+ 		spin_unlock_bh(&conn->session->lock);
+ 		return -ENODATA;
+ 	}
+@@ -1398,7 +1425,8 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 	iscsi_complete_command(task);
+ reject:
+ 	spin_unlock(&session->lock);
+-	debug_scsi("cmd 0x%x rejected (%d)\n", sc->cmnd[0], reason);
++	ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n",
++			  sc->cmnd[0], reason);
+ 	spin_lock(host->host_lock);
+ 	return SCSI_MLQUEUE_TARGET_BUSY;
+ 
+@@ -1407,7 +1435,8 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 	iscsi_complete_command(task);
+ fault:
+ 	spin_unlock(&session->lock);
+-	debug_scsi("iscsi: cmd 0x%x is not queued (%d)\n", sc->cmnd[0], reason);
++	ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n",
++			  sc->cmnd[0], reason);
+ 	if (!scsi_bidi_cmnd(sc))
+ 		scsi_set_resid(sc, scsi_bufflen(sc));
+ 	else {
+@@ -1457,8 +1486,10 @@ int iscsi_eh_target_reset(struct scsi_cmnd *sc)
+ 	spin_lock_bh(&session->lock);
+ 	if (session->state == ISCSI_STATE_TERMINATE) {
+ failed:
+-		debug_scsi("failing target reset: session terminated "
+-			   "[CID %d age %d]\n", conn->id, session->age);
++		iscsi_session_printk(KERN_INFO, session,
++				     "failing target reset: Could not log "
++				     "back into target [age %d]\n",
++				     session->age);
+ 		spin_unlock_bh(&session->lock);
+ 		mutex_unlock(&session->eh_mutex);
+ 		return FAILED;
+@@ -1472,7 +1503,7 @@ int iscsi_eh_target_reset(struct scsi_cmnd *sc)
+ 	 */
+ 	iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ 
+-	debug_scsi("iscsi_eh_target_reset wait for relogin\n");
++	ISCSI_DBG_SESSION(session, "wait for relogin\n");
+ 	wait_event_interruptible(conn->ehwait,
+ 				 session->state == ISCSI_STATE_TERMINATE ||
+ 				 session->state == ISCSI_STATE_LOGGED_IN ||
+@@ -1501,7 +1532,7 @@ static void iscsi_tmf_timedout(unsigned long data)
+ 	spin_lock(&session->lock);
+ 	if (conn->tmf_state == TMF_QUEUED) {
+ 		conn->tmf_state = TMF_TIMEDOUT;
+-		debug_scsi("tmf timedout\n");
++		ISCSI_DBG_SESSION(session, "tmf timedout\n");
+ 		/* unblock eh_abort() */
+ 		wake_up(&conn->ehwait);
+ 	}
+@@ -1521,7 +1552,7 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn,
+ 		spin_unlock_bh(&session->lock);
+ 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ 		spin_lock_bh(&session->lock);
+-		debug_scsi("tmf exec failure\n");
++		ISCSI_DBG_SESSION(session, "tmf exec failure\n");
+ 		return -EPERM;
+ 	}
+ 	conn->tmfcmd_pdus_cnt++;
+@@ -1529,7 +1560,7 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn,
+ 	conn->tmf_timer.function = iscsi_tmf_timedout;
+ 	conn->tmf_timer.data = (unsigned long)conn;
+ 	add_timer(&conn->tmf_timer);
+-	debug_scsi("tmf set timeout\n");
++	ISCSI_DBG_SESSION(session, "tmf set timeout\n");
+ 
+ 	spin_unlock_bh(&session->lock);
+ 	mutex_unlock(&session->eh_mutex);
+@@ -1573,16 +1604,18 @@ static void fail_all_commands(struct iscsi_conn *conn, unsigned lun,
+ 	/* flush pending */
+ 	list_for_each_entry_safe(task, tmp, &conn->xmitqueue, running) {
+ 		if (lun == task->sc->device->lun || lun == -1) {
+-			debug_scsi("failing pending sc %p itt 0x%x\n",
+-				   task->sc, task->itt);
++			ISCSI_DBG_SESSION(conn->session,
++					  "failing pending sc %p itt 0x%x\n",
++					  task->sc, task->itt);
+ 			fail_command(conn, task, error << 16);
+ 		}
+ 	}
+ 
+ 	list_for_each_entry_safe(task, tmp, &conn->requeue, running) {
+ 		if (lun == task->sc->device->lun || lun == -1) {
+-			debug_scsi("failing requeued sc %p itt 0x%x\n",
+-				   task->sc, task->itt);
++			ISCSI_DBG_SESSION(conn->session,
++					  "failing requeued sc %p itt 0x%x\n",
++					  task->sc, task->itt);
+ 			fail_command(conn, task, error << 16);
+ 		}
+ 	}
+@@ -1590,8 +1623,9 @@ static void fail_all_commands(struct iscsi_conn *conn, unsigned lun,
+ 	/* fail all other running */
+ 	list_for_each_entry_safe(task, tmp, &conn->run_list, running) {
+ 		if (lun == task->sc->device->lun || lun == -1) {
+-			debug_scsi("failing in progress sc %p itt 0x%x\n",
+-				   task->sc, task->itt);
++			ISCSI_DBG_SESSION(conn->session,
++					 "failing in progress sc %p itt 0x%x\n",
++					 task->sc, task->itt);
+ 			fail_command(conn, task, error << 16);
+ 		}
+ 	}
+@@ -1622,7 +1656,7 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
+ 	cls_session = starget_to_session(scsi_target(scmd->device));
+ 	session = cls_session->dd_data;
+ 
+-	debug_scsi("scsi cmd %p timedout\n", scmd);
++	ISCSI_DBG_SESSION(session, "scsi cmd %p timedout\n", scmd);
+ 
+ 	spin_lock(&session->lock);
+ 	if (session->state != ISCSI_STATE_LOGGED_IN) {
+@@ -1662,8 +1696,8 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
+ 		rc = BLK_EH_RESET_TIMER;
+ done:
+ 	spin_unlock(&session->lock);
+-	debug_scsi("return %s\n", rc == BLK_EH_RESET_TIMER ?
+-					"timer reset" : "nh");
++	ISCSI_DBG_SESSION(session, "return %s\n", rc == BLK_EH_RESET_TIMER ?
++			  "timer reset" : "nh");
+ 	return rc;
+ }
+ 
+@@ -1697,13 +1731,13 @@ static void iscsi_check_transport_timeouts(unsigned long data)
+ 
+ 	if (time_before_eq(last_recv + recv_timeout, jiffies)) {
+ 		/* send a ping to try to provoke some traffic */
+-		debug_scsi("Sending nopout as ping on conn %p\n", conn);
++		ISCSI_DBG_CONN(conn, "Sending nopout as ping\n");
+ 		iscsi_send_nopout(conn, NULL);
+ 		next_timeout = conn->last_ping + (conn->ping_timeout * HZ);
+ 	} else
+ 		next_timeout = last_recv + recv_timeout;
+ 
+-	debug_scsi("Setting next tmo %lu\n", next_timeout);
++	ISCSI_DBG_CONN(conn, "Setting next tmo %lu\n", next_timeout);
+ 	mod_timer(&conn->transport_timer, next_timeout);
+ done:
+ 	spin_unlock(&session->lock);
+@@ -1740,7 +1774,8 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 	 * got the command.
+ 	 */
+ 	if (!sc->SCp.ptr) {
+-		debug_scsi("sc never reached iscsi layer or it completed.\n");
++		ISCSI_DBG_SESSION(session, "sc never reached iscsi layer or "
++				  "it completed.\n");
+ 		spin_unlock_bh(&session->lock);
+ 		mutex_unlock(&session->eh_mutex);
+ 		return SUCCESS;
+@@ -1762,11 +1797,13 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 	age = session->age;
+ 
+ 	task = (struct iscsi_task *)sc->SCp.ptr;
+-	debug_scsi("aborting [sc %p itt 0x%x]\n", sc, task->itt);
++	ISCSI_DBG_SESSION(session, "aborting [sc %p itt 0x%x]\n",
++			  sc, task->itt);
+ 
+ 	/* task completed before time out */
+ 	if (!task->sc) {
+-		debug_scsi("sc completed while abort in progress\n");
++		ISCSI_DBG_SESSION(session, "sc completed while abort in "
++				  "progress\n");
+ 		goto success;
+ 	}
+ 
+@@ -1815,7 +1852,8 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 		if (!sc->SCp.ptr) {
+ 			conn->tmf_state = TMF_INITIAL;
+ 			/* task completed before tmf abort response */
+-			debug_scsi("sc completed while abort in progress\n");
++			ISCSI_DBG_SESSION(session, "sc completed while abort "
++					  "in progress\n");
+ 			goto success;
+ 		}
+ 		/* fall through */
+@@ -1827,15 +1865,16 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ success:
+ 	spin_unlock_bh(&session->lock);
+ success_unlocked:
+-	debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, task->itt);
++	ISCSI_DBG_SESSION(session, "abort success [sc %p itt 0x%x]\n",
++			  sc, task->itt);
+ 	mutex_unlock(&session->eh_mutex);
+ 	return SUCCESS;
+ 
+ failed:
+ 	spin_unlock_bh(&session->lock);
+ failed_unlocked:
+-	debug_scsi("abort failed [sc %p itt 0x%x]\n", sc,
+-		    task ? task->itt : 0);
++	ISCSI_DBG_SESSION(session, "abort failed [sc %p itt 0x%x]\n", sc,
++			  task ? task->itt : 0);
+ 	mutex_unlock(&session->eh_mutex);
+ 	return FAILED;
+ }
+@@ -1862,7 +1901,8 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc)
+ 	cls_session = starget_to_session(scsi_target(sc->device));
+ 	session = cls_session->dd_data;
+ 
+-	debug_scsi("LU Reset [sc %p lun %u]\n", sc, sc->device->lun);
++	ISCSI_DBG_SESSION(session, "LU Reset [sc %p lun %u]\n",
++			  sc, sc->device->lun);
+ 
+ 	mutex_lock(&session->eh_mutex);
+ 	spin_lock_bh(&session->lock);
+@@ -1916,8 +1956,8 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc)
+ unlock:
+ 	spin_unlock_bh(&session->lock);
+ done:
+-	debug_scsi("iscsi_eh_device_reset %s\n",
+-		  rc == SUCCESS ? "SUCCESS" : "FAILED");
++	ISCSI_DBG_SESSION(session, "dev reset result = %s\n",
++			 rc == SUCCESS ? "SUCCESS" : "FAILED");
+ 	mutex_unlock(&session->eh_mutex);
+ 	return rc;
+ }
+@@ -2466,14 +2506,16 @@ flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn)
+ 
+ 	/* handle pending */
+ 	list_for_each_entry_safe(task, tmp, &conn->mgmtqueue, running) {
+-		debug_scsi("flushing pending mgmt task itt 0x%x\n", task->itt);
++		ISCSI_DBG_SESSION(session, "flushing pending mgmt task "
++				  "itt 0x%x\n", task->itt);
+ 		/* release ref from prep task */
+ 		__iscsi_put_task(task);
+ 	}
+ 
+ 	/* handle running */
+ 	list_for_each_entry_safe(task, tmp, &conn->mgmt_run_list, running) {
+-		debug_scsi("flushing running mgmt task itt 0x%x\n", task->itt);
++		ISCSI_DBG_SESSION(session, "flushing running mgmt task "
++				  "itt 0x%x\n", task->itt);
+ 		/* release ref from prep task */
+ 		__iscsi_put_task(task);
+ 	}
+@@ -2523,7 +2565,7 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ 		conn->datadgst_en = 0;
+ 		if (session->state == ISCSI_STATE_IN_RECOVERY &&
+ 		    old_stop_stage != STOP_CONN_RECOVER) {
+-			debug_scsi("blocking session\n");
++			ISCSI_DBG_SESSION(session, "blocking session\n");
+ 			iscsi_block_session(session->cls_session);
+ 		}
+ 	}
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 7360e1916e75..67542aa3aedc 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -45,13 +45,6 @@ struct iscsi_session;
+ struct iscsi_nopin;
+ struct device;
+ 
+-/* #define DEBUG_SCSI */
+-#ifdef DEBUG_SCSI
+-#define debug_scsi(fmt...) printk(KERN_INFO "iscsi: " fmt)
+-#else
+-#define debug_scsi(fmt...)
+-#endif
+-
+ #define ISCSI_DEF_XMIT_CMDS_MAX	128	/* must be power of 2 */
+ #define ISCSI_MGMT_CMDS_MAX	15
+ 

commit 48a237a26db0a31404c83a88e984b37a30ddcf5a
+Author: Mike Christie 
+Date:   Thu Mar 5 14:45:57 2009 -0600
+
+    [SCSI] iser: have iser use its own logging
+    
+    iser has its own logging inrfastrucutre. Convert it to use
+    it instead of libiscsi.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 12876392516e..4338f54c41fa 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -168,7 +168,7 @@ iscsi_iser_mtask_xmit(struct iscsi_conn *conn, struct iscsi_task *task)
+ {
+ 	int error = 0;
+ 
+-	debug_scsi("task deq [cid %d itt 0x%x]\n", conn->id, task->itt);
++	iser_dbg("task deq [cid %d itt 0x%x]\n", conn->id, task->itt);
+ 
+ 	error = iser_send_control(conn, task);
+ 
+@@ -195,7 +195,7 @@ iscsi_iser_task_xmit_unsol_data(struct iscsi_conn *conn,
+ 	/* Send data-out PDUs while there's still unsolicited data to send */
+ 	while (iscsi_task_has_unsol_data(task)) {
+ 		iscsi_prep_data_out_pdu(task, r2t, &hdr);
+-		debug_scsi("Sending data-out: itt 0x%x, data count %d\n",
++		iser_dbg("Sending data-out: itt 0x%x, data count %d\n",
+ 			   hdr.itt, r2t->data_count);
+ 
+ 		/* the buffer description has been passed with the command */
+@@ -206,7 +206,7 @@ iscsi_iser_task_xmit_unsol_data(struct iscsi_conn *conn,
+ 			goto iscsi_iser_task_xmit_unsol_data_exit;
+ 		}
+ 		r2t->sent += r2t->data_count;
+-		debug_scsi("Need to send %d more as data-out PDUs\n",
++		iser_dbg("Need to send %d more as data-out PDUs\n",
+ 			   r2t->data_length - r2t->sent);
+ 	}
+ 
+@@ -227,12 +227,12 @@ iscsi_iser_task_xmit(struct iscsi_task *task)
+ 	if (task->sc->sc_data_direction == DMA_TO_DEVICE) {
+ 		BUG_ON(scsi_bufflen(task->sc) == 0);
+ 
+-		debug_scsi("cmd [itt %x total %d imm %d unsol_data %d\n",
++		iser_dbg("cmd [itt %x total %d imm %d unsol_data %d\n",
+ 			   task->itt, scsi_bufflen(task->sc),
+ 			   task->imm_count, task->unsol_r2t.data_length);
+ 	}
+ 
+-	debug_scsi("task deq [cid %d itt 0x%x]\n",
++	iser_dbg("task deq [cid %d itt 0x%x]\n",
+ 		   conn->id, task->itt);
+ 
+ 	/* Send the cmd PDU */

commit 308cec14e6710b4d5b70e9778ce117be8371735d
+Author: Mike Christie 
+Date:   Fri Feb 6 12:06:20 2009 -0600
+
+    [SCSI] libiscsi: Fix scsi command timeout oops in iscsi_eh_timed_out
+    
+    Yanling Qi from LSI found the root cause of the panic, below is his
+    analysis:
+    
+    Problem description: the open iscsi driver installs eh_timed_out handler
+    to the
+    blank_transport_template of the scsi middle level that causes panic of
+    timed
+    out command of other host
+    
+    Here are the details
+    
+    Iscsi Session creation
+    
+    During iscsi session creation time, the iscsi_tcp_session_create() of
+    iscsi_tpc.c will create a scsi-host for the session. See the statement
+    marked
+    with the label A. The statement B replaces the shost->transportt point
+    with a
+    local struct variable.
+    
+    static struct iscsi_cls_session *
+    iscsi_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
+                             uint16_t qdepth, uint32_t initial_cmdsn,
+                             uint32_t *hostno)
+    {
+            struct iscsi_cls_session *cls_session;
+            struct iscsi_session *session;
+            struct Scsi_Host *shost;
+            int cmd_i;
+            if (ep) {
+                    printk(KERN_ERR "iscsi_tcp: invalid ep %p.\n", ep);
+                    return NULL;
+            }
+    
+    A        shost = iscsi_host_alloc(&iscsi_sht, 0, qdepth);
+    
+            if (!shost)
+    
+                    return NULL;
+    
+    B         shost->transportt = iscsi_tcp_scsi_transport;
+    
+            shost->max_lun = iscsi_max_lun;
+    
+    Please note the scsi host is allocated by invoking isccsi_host_alloc()
+    in
+    libiscsi.c
+    
+    Polluting the middle level blank_transport_template in
+    iscsi_host_alloc() of
+    libiscsi.c
+    
+    The iscsi_host_alloc() invokes the middle level function
+    scsi_host_alloc() in
+    hosts.c for allocating a scsi_host. Then the statement marked with C
+    assigns
+    the iscsi_eh_cmd_timed_out handler to the eh_timed_out callback
+    function.
+    
+    struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
+    
+                                       int dd_data_size, uint16_t qdepth)
+    
+    {
+            struct Scsi_Host *shost;
+            struct iscsi_host *ihost;
+            shost = scsi_host_alloc(sht, sizeof(struct iscsi_host) +
+    dd_data_size);
+            if (!shost)
+                    return NULL;
+    
+     C      shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out;
+    
+    Please note the shost->transport is the middle level
+    blank_transport_template
+    as shown in the code segment below. We see two problems here. 1.
+    iscsi_eh_cmd_timed_out is installed to the blank_transport_template that
+    will
+    cause some body else problem. 2. iscsi_eh_cmd_timed_out will never be
+    invoked
+    when iscsi command gets timeout because the statement B resets the
+    pointer.
+    
+    Middle level blank_transport_template
+    
+    In the middle level function scsi_host_alloc() of hosts.c, the middle
+    level
+    assigns a blank_transport_template for those hosts not implementing its
+    transport layer. All HBAs without supporting a specific scsi_transport
+    will
+    share the middle level blank_transport_template. Please see the
+    statement D
+    
+    struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int
+    privsize)
+    
+    {
+            struct Scsi_Host *shost;
+            gfp_t gfp_mask = GFP_KERNEL;
+            int rval;
+            if (sht->unchecked_isa_dma && privsize)
+                    gfp_mask |= __GFP_DMA;
+    
+             shost = kzalloc(sizeof(struct Scsi_Host) + privsize, gfp_mask);
+            if (!shost)
+                    return NULL;
+    
+            shost->host_lock = &shost->default_lock;
+    
+            spin_lock_init(shost->host_lock);
+    
+            shost->shost_state = SHOST_CREATED;
+    
+            INIT_LIST_HEAD(&shost->__devices);
+    
+            INIT_LIST_HEAD(&shost->__targets);
+    
+            INIT_LIST_HEAD(&shost->eh_cmd_q);
+    
+            INIT_LIST_HEAD(&shost->starved_list);
+    
+            init_waitqueue_head(&shost->host_wait);
+    
+            mutex_init(&shost->scan_mutex);
+    
+            shost->host_no = scsi_host_next_hn++; /* XXX(hch): still racy */
+    
+            shost->dma_channel = 0xff;
+    
+            /* These three are default values which can be overridden */
+    
+            shost->max_channel = 0;
+    
+            shost->max_id = 8;
+    
+            shost->max_lun = 8;
+    
+            /* Give each shost a default transportt */
+    
+     D       shost->transportt = &blank_transport_template;
+    
+    Why we see panic at iscsi_eh_cmd_timed_out()
+    
+    The mpp virtual HBA doesn’t have a specific scsi_transport. Therefore,
+    the
+    blank_transport_template will be assigned to the virtual host of the MPP
+    virtual HBA by SCSI middle level. Please note that the statement C has
+    assigned
+    iscsi-transport eh_timedout handler to the blank_transport_template.
+    When a mpp
+    virtual command gets timedout, the iscsi_eh_cmd_timed_out() will be
+    invoked to
+    handle mpp virtual command timeout from the middle level
+    scsi_times_out()
+    function of the scsi_error.c.
+    
+    enum blk_eh_timer_return scsi_times_out(struct request *req)
+    
+    {
+    
+            struct scsi_cmnd *scmd = req->special;
+    
+            enum blk_eh_timer_return (*eh_timed_out)(struct scsi_cmnd *);
+    
+            enum blk_eh_timer_return rtn = BLK_EH_NOT_HANDLED;
+    
+            scsi_log_completion(scmd, TIMEOUT_ERROR);
+    
+            if (scmd->device->host->transportt->eh_timed_out)
+    
+     E               eh_timed_out =
+    scmd->device->host->transportt->eh_timed_out;
+    
+            else if (scmd->device->host->hostt->eh_timed_out)
+    
+                    eh_timed_out = scmd->device->host->hostt->eh_timed_out;
+    
+            else
+    
+                    eh_timed_out = NULL;
+    
+            if (eh_timed_out) {
+    
+                    rtn = eh_timed_out(scmd);
+    
+    It is very easy to understand why we get panic in the
+    iscsi_eh_cmd_timed_out().
+    A scsi_cmnd from a no-iscsi device definitely can not resolve out a
+    session and
+    session->lock. The panic can be happed anywhere during the differencing.
+    
+    static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd
+    *scmd)
+    
+    {
+    
+            struct iscsi_cls_session *cls_session;
+    
+            struct iscsi_session *session;
+    
+            struct iscsi_conn *conn;
+    
+            enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED;
+    
+            cls_session = starget_to_session(scsi_target(scmd->device));
+    
+            session = cls_session->dd_data;
+    
+            debug_scsi("scsi cmd %p timedout\n", scmd);
+    
+            spin_lock(&session->lock);
+    
+    This patch fixes the problem by moving the setting of the
+    iscsi_eh_cmd_timed_out to iscsi_add_host, which is after the LLDs
+    have set their transport template to shost->transportt.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 257c24115de9..809d32d95c76 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1998,6 +1998,8 @@ int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev)
+ 	if (!shost->can_queue)
+ 		shost->can_queue = ISCSI_DEF_XMIT_CMDS_MAX;
+ 
++	if (!shost->transportt->eh_timed_out)
++		shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out;
+ 	return scsi_add_host(shost, pdev);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_host_add);
+@@ -2020,7 +2022,6 @@ struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
+ 	shost = scsi_host_alloc(sht, sizeof(struct iscsi_host) + dd_data_size);
+ 	if (!shost)
+ 		return NULL;
+-	shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out;
+ 
+ 	if (qdepth > ISCSI_MAX_CMD_PER_LUN || qdepth < 1) {
+ 		if (qdepth != 0)

commit 41bbdbebbbe7e06871d25f51c2eb1d6466bb9e5f
+Author: Mike Christie 
+Date:   Fri Jan 16 12:36:52 2009 -0600
+
+    [SCSI] qla4xxx: do not reuse session when connecting to different target port
+    
+    qla4xxx does not check the I_T nexus values correctly
+    so it ends up creating one session to the target. If
+    a portal should disappear or they should be reported
+    in different order the driver will think it is already
+    logged in when it could now be speaking to a different
+    target portal or accessing it through a different
+    initiator port (iscsi initiator port is not tied to
+    hardware and is just the initiator name plus isid
+    so you could end up with multiple ports through one
+    host).
+    
+    This patch has the driver check the iscsi scsi port
+    values when matching sessions (we do not check
+    the initiator name because that is static). It results
+    in a portal from each target portal group getting
+    logged into instead of just one per target. In the future
+    the firmware should hopefully send us notification of other
+    sessions that are created to other portals within the
+    same tpgt and the sessions should have different isids.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
+index d6be0762eb91..b586f27c3bd4 100644
+--- a/drivers/scsi/qla4xxx/ql4_def.h
++++ b/drivers/scsi/qla4xxx/ql4_def.h
+@@ -244,6 +244,7 @@ struct ddb_entry {
+ 	uint8_t ip_addr[ISCSI_IPADDR_SIZE];
+ 	uint8_t iscsi_name[ISCSI_NAME_SIZE];	/* 72 x48 */
+ 	uint8_t iscsi_alias[0x20];
++	uint8_t isid[6];
+ };
+ 
+ /*
+diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
+index 109c5f5985ec..af8c3233e8ae 100644
+--- a/drivers/scsi/qla4xxx/ql4_init.c
++++ b/drivers/scsi/qla4xxx/ql4_init.c
+@@ -342,8 +342,12 @@ static struct ddb_entry* qla4xxx_get_ddb_entry(struct scsi_qla_host *ha,
+ 	DEBUG2(printk("scsi%ld: %s: Looking for ddb[%d]\n", ha->host_no,
+ 		      __func__, fw_ddb_index));
+ 	list_for_each_entry(ddb_entry, &ha->ddb_list, list) {
+-		if (memcmp(ddb_entry->iscsi_name, fw_ddb_entry->iscsi_name,
+-			   ISCSI_NAME_SIZE) == 0) {
++		if ((memcmp(ddb_entry->iscsi_name, fw_ddb_entry->iscsi_name,
++			   ISCSI_NAME_SIZE) == 0) &&
++			(ddb_entry->tpgt ==
++				le32_to_cpu(fw_ddb_entry->tgt_portal_grp)) &&
++			(memcmp(ddb_entry->isid, fw_ddb_entry->isid,
++				sizeof(ddb_entry->isid)) == 0)) {
+ 			found++;
+ 			break;
+ 		}
+@@ -430,6 +434,8 @@ static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha,
+ 
+ 	ddb_entry->port = le16_to_cpu(fw_ddb_entry->port);
+ 	ddb_entry->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp);
++	memcpy(ddb_entry->isid, fw_ddb_entry->isid, sizeof(ddb_entry->isid));
++
+ 	memcpy(&ddb_entry->iscsi_name[0], &fw_ddb_entry->iscsi_name[0],
+ 	       min(sizeof(ddb_entry->iscsi_name),
+ 		   sizeof(fw_ddb_entry->iscsi_name)));

commit 2f5899a39dcffb404c9a3d06ad438aff3e03bf04
+Author: Mike Christie 
+Date:   Fri Jan 16 12:36:51 2009 -0600
+
+    [SCSI] libiscsi: fix iscsi pool leak
+    
+    I am not sure what happened. It looks like we have always leaked
+    the q->queue that is allocated from the kfifo_init call. nab finally
+    noticed that we were leaking and this patch fixes it by adding a
+    kfree call to iscsi_pool_free. kfifo_free is not used per kfifo_init's
+    instructions to use kfree.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 7225b6e2029e..257c24115de9 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1981,6 +1981,7 @@ void iscsi_pool_free(struct iscsi_pool *q)
+ 		kfree(q->pool[i]);
+ 	if (q->pool)
+ 		kfree(q->pool);
++	kfree(q->queue);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_pool_free);
+ 

commit 6df19a791bdd5d820cccd8c7a12679888ae62099
+Author: Mike Christie 
+Date:   Tue Dec 2 00:32:16 2008 -0600
+
+    [SCSI] libiscsi_tcp: support padding offload
+    
+    cxgb3i does not offload the processing of the header,
+    but it will always process the padding. This patch
+    adds a padding offload flag to detect when the LLD
+    supports this.
+    
+    The patch also modifies the header processing so that
+    we do not try to read/bypass the header dugest in the
+    skb. cxgb3i will not include it with the header like
+    with other offload cards.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index de5c9b3e51fb..23808dfe22ba 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -194,7 +194,7 @@ iscsi_sw_tcp_conn_restore_callbacks(struct iscsi_sw_tcp_conn *tcp_sw_conn)
+ 
+ /**
+  * iscsi_sw_tcp_xmit_segment - transmit segment
+- * @tcp_sw_conn: the iSCSI TCP connection
++ * @tcp_conn: the iSCSI TCP connection
+  * @segment: the buffer to transmnit
+  *
+  * This function transmits as much of the buffer as
+@@ -205,14 +205,15 @@ iscsi_sw_tcp_conn_restore_callbacks(struct iscsi_sw_tcp_conn *tcp_sw_conn)
+  * hash as it goes. When the entire segment has been transmitted,
+  * it will retrieve the hash value and send it as well.
+  */
+-static int iscsi_sw_tcp_xmit_segment(struct iscsi_sw_tcp_conn *tcp_sw_conn,
++static int iscsi_sw_tcp_xmit_segment(struct iscsi_tcp_conn *tcp_conn,
+ 				     struct iscsi_segment *segment)
+ {
++	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
+ 	struct socket *sk = tcp_sw_conn->sock;
+ 	unsigned int copied = 0;
+ 	int r = 0;
+ 
+-	while (!iscsi_tcp_segment_done(segment, 0, r)) {
++	while (!iscsi_tcp_segment_done(tcp_conn, segment, 0, r)) {
+ 		struct scatterlist *sg;
+ 		unsigned int offset, copy;
+ 		int flags = 0;
+@@ -263,7 +264,7 @@ static int iscsi_sw_tcp_xmit(struct iscsi_conn *conn)
+ 	int rc = 0;
+ 
+ 	while (1) {
+-		rc = iscsi_sw_tcp_xmit_segment(tcp_sw_conn, segment);
++		rc = iscsi_sw_tcp_xmit_segment(tcp_conn, segment);
+ 		if (rc < 0) {
+ 			rc = ISCSI_ERR_XMIT_FAILED;
+ 			goto error;
+diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
+index 9df6b3436e4a..a745f91d2928 100644
+--- a/drivers/scsi/libiscsi_tcp.c
++++ b/drivers/scsi/libiscsi_tcp.c
+@@ -159,6 +159,7 @@ iscsi_tcp_segment_splice_digest(struct iscsi_segment *segment, void *digest)
+ 
+ /**
+  * iscsi_tcp_segment_done - check whether the segment is complete
++ * @tcp_conn: iscsi tcp connection
+  * @segment: iscsi segment to check
+  * @recv: set to one of this is called from the recv path
+  * @copied: number of bytes copied
+@@ -172,7 +173,8 @@ iscsi_tcp_segment_splice_digest(struct iscsi_segment *segment, void *digest)
+  *
+  * This function must be re-entrant.
+  */
+-int iscsi_tcp_segment_done(struct iscsi_segment *segment, int recv,
++int iscsi_tcp_segment_done(struct iscsi_tcp_conn *tcp_conn,
++			   struct iscsi_segment *segment, int recv,
+ 			   unsigned copied)
+ {
+ 	static unsigned char padbuf[ISCSI_PAD_LEN];
+@@ -225,13 +227,15 @@ int iscsi_tcp_segment_done(struct iscsi_segment *segment, int recv,
+ 	}
+ 
+ 	/* Do we need to handle padding? */
+-	pad = iscsi_padding(segment->total_copied);
+-	if (pad != 0) {
+-		debug_tcp("consume %d pad bytes\n", pad);
+-		segment->total_size += pad;
+-		segment->size = pad;
+-		segment->data = padbuf;
+-		return 0;
++	if (!(tcp_conn->iscsi_conn->session->tt->caps & CAP_PADDING_OFFLOAD)) {
++		pad = iscsi_padding(segment->total_copied);
++		if (pad != 0) {
++			debug_tcp("consume %d pad bytes\n", pad);
++			segment->total_size += pad;
++			segment->size = pad;
++			segment->data = padbuf;
++			return 0;
++		}
+ 	}
+ 
+ 	/*
+@@ -273,7 +277,7 @@ iscsi_tcp_segment_recv(struct iscsi_tcp_conn *tcp_conn,
+ {
+ 	unsigned int copy = 0, copied = 0;
+ 
+-	while (!iscsi_tcp_segment_done(segment, 1, copy)) {
++	while (!iscsi_tcp_segment_done(tcp_conn, segment, 1, copy)) {
+ 		if (copied == len) {
+ 			debug_tcp("iscsi_tcp_segment_recv copied %d bytes\n",
+ 				  len);
+@@ -794,7 +798,8 @@ iscsi_tcp_hdr_recv_done(struct iscsi_tcp_conn *tcp_conn,
+ 	/* We're done processing the header. See if we're doing
+ 	 * header digests; if so, set up the recv_digest buffer
+ 	 * and go back for more. */
+-	if (conn->hdrdgst_en) {
++	if (conn->hdrdgst_en &&
++	    !(conn->session->tt->caps & CAP_DIGEST_OFFLOAD)) {
+ 		if (segment->digest_len == 0) {
+ 			/*
+ 			 * Even if we offload the digest processing we
+@@ -806,14 +811,12 @@ iscsi_tcp_hdr_recv_done(struct iscsi_tcp_conn *tcp_conn,
+ 			return 0;
+ 		}
+ 
+-		if (!(conn->session->tt->caps & CAP_DIGEST_OFFLOAD)) {
+-			iscsi_tcp_dgst_header(tcp_conn->rx_hash, hdr,
+-				segment->total_copied - ISCSI_DIGEST_SIZE,
+-				segment->digest);
++		iscsi_tcp_dgst_header(tcp_conn->rx_hash, hdr,
++				      segment->total_copied - ISCSI_DIGEST_SIZE,
++				      segment->digest);
+ 
+-			if (!iscsi_tcp_dgst_verify(tcp_conn, segment))
+-				return ISCSI_ERR_HDR_DGST;
+-		}
++		if (!iscsi_tcp_dgst_verify(tcp_conn, segment))
++			return ISCSI_ERR_HDR_DGST;
+ 	}
+ 
+ 	tcp_conn->in.hdr = hdr;
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index 8e008c96e795..d0ed5226f8c4 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -336,6 +336,8 @@ enum iscsi_host_param {
+ #define CAP_SENDTARGETS_OFFLOAD	0x400	/* offload discovery process */
+ #define CAP_DATA_PATH_OFFLOAD	0x800	/* offload entire IO path */
+ #define CAP_DIGEST_OFFLOAD	0x1000	/* offload hdr and data digests */
++#define CAP_PADDING_OFFLOAD	0x2000	/* offload padding insertion, removal,
++					 and verification */
+ 
+ /*
+  * These flags describes reason of stop_conn() call
+diff --git a/include/scsi/libiscsi_tcp.h b/include/scsi/libiscsi_tcp.h
+index e6bf8ef276bb..83e32f6d7859 100644
+--- a/include/scsi/libiscsi_tcp.h
++++ b/include/scsi/libiscsi_tcp.h
+@@ -99,7 +99,8 @@ extern int iscsi_tcp_task_xmit(struct iscsi_task *task);
+ 
+ /* segment helpers */
+ extern int iscsi_tcp_recv_segment_is_hdr(struct iscsi_tcp_conn *tcp_conn);
+-extern int iscsi_tcp_segment_done(struct iscsi_segment *segment, int recv,
++extern int iscsi_tcp_segment_done(struct iscsi_tcp_conn *tcp_conn,
++				  struct iscsi_segment *segment, int recv,
+ 				  unsigned copied);
+ extern void iscsi_tcp_segment_unmap(struct iscsi_segment *segment);
+ 

commit ae15f80172d95f978b60d40408353943d5bc099b
+Author: Mike Christie 
+Date:   Tue Dec 2 00:32:15 2008 -0600
+
+    [SCSI] libiscsi: handle init task failures.
+    
+    Mgmt setup used to not fail so we did not have to check
+    the return value. Now with cxgb3i it can so this has us
+    pass up a error.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index ddf53978f0be..7225b6e2029e 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -475,8 +475,8 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn,
+ 		}
+ 	}
+ 
+-	if (session->tt->init_task)
+-		session->tt->init_task(task);
++	if (session->tt->init_task && session->tt->init_task(task))
++		return -EIO;
+ 
+ 	if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT)
+ 		session->state = ISCSI_STATE_LOGGING_OUT;

commit 2ff79d52d56eebcffd83e9327b89d7daedf1e897
+Author: Mike Christie 
+Date:   Tue Dec 2 00:32:14 2008 -0600
+
+    [SCSI] libiscsi: pass opcode into alloc_pdu callout
+    
+    We do not need to allocate a itt for data_out, so this
+    passes the opcode to the alloc_pdu callout.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 78bf5e4538cb..12876392516e 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -119,7 +119,7 @@ iscsi_iser_recv(struct iscsi_conn *conn,
+ 	iscsi_conn_failure(conn, rc);
+ }
+ 
+-static int iscsi_iser_pdu_alloc(struct iscsi_task *task)
++static int iscsi_iser_pdu_alloc(struct iscsi_task *task, uint8_t opcode)
+ {
+ 	struct iscsi_iser_task *iser_task = task->dd_data;
+ 
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 07d9eb14721b..de5c9b3e51fb 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -457,7 +457,7 @@ static int iscsi_sw_tcp_pdu_init(struct iscsi_task *task,
+ 	return 0;
+ }
+ 
+-static int iscsi_sw_tcp_pdu_alloc(struct iscsi_task *task)
++static int iscsi_sw_tcp_pdu_alloc(struct iscsi_task *task, uint8_t opcode)
+ {
+ 	struct iscsi_tcp_task *tcp_task = task->dd_data;
+ 
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 6c4034b1561c..ddf53978f0be 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -225,13 +225,18 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
+ 	itt_t itt;
+ 	int rc;
+ 
+-	rc = conn->session->tt->alloc_pdu(task);
++	rc = conn->session->tt->alloc_pdu(task, ISCSI_OP_SCSI_CMD);
+ 	if (rc)
+ 		return rc;
+ 	hdr = (struct iscsi_cmd *) task->hdr;
+ 	itt = hdr->itt;
+ 	memset(hdr, 0, sizeof(*hdr));
+ 
++	if (session->tt->parse_pdu_itt)
++		hdr->itt = task->hdr_itt = itt;
++	else
++		hdr->itt = task->hdr_itt = build_itt(task->itt,
++						     task->conn->session->age);
+ 	task->hdr_len = 0;
+ 	rc = iscsi_add_hdr(task, sizeof(*hdr));
+ 	if (rc)
+@@ -240,11 +245,6 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
+ 	hdr->flags = ISCSI_ATTR_SIMPLE;
+ 	int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
+ 	memcpy(task->lun, hdr->lun, sizeof(task->lun));
+-	if (session->tt->parse_pdu_itt)
+-		hdr->itt = task->hdr_itt = itt;
+-	else
+-		hdr->itt = task->hdr_itt = build_itt(task->itt,
+-						     task->conn->session->age);
+ 	hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn);
+ 	session->cmdsn++;
+ 	hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
+@@ -532,7 +532,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	} else
+ 		task->data_count = 0;
+ 
+-	if (conn->session->tt->alloc_pdu(task)) {
++	if (conn->session->tt->alloc_pdu(task, hdr->opcode)) {
+ 		iscsi_conn_printk(KERN_ERR, conn, "Could not allocate "
+ 				 "pdu for mgmt task.\n");
+ 		goto requeue_task;
+diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
+index e86508936314..9df6b3436e4a 100644
+--- a/drivers/scsi/libiscsi_tcp.c
++++ b/drivers/scsi/libiscsi_tcp.c
+@@ -1021,7 +1021,7 @@ int iscsi_tcp_task_xmit(struct iscsi_task *task)
+ 		return 0;
+ 	}
+ 
+-	rc = conn->session->tt->alloc_pdu(task);
++	rc = conn->session->tt->alloc_pdu(task, ISCSI_OP_SCSI_DATA_OUT);
+ 	if (rc)
+ 		return rc;
+ 	iscsi_prep_data_out_pdu(task, r2t, (struct iscsi_data *) task->hdr);
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index e13cb20f1eae..b50aabe2861e 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -118,7 +118,7 @@ struct iscsi_transport {
+ 	int (*xmit_task) (struct iscsi_task *task);
+ 	void (*cleanup_task) (struct iscsi_task *task);
+ 
+-	int (*alloc_pdu) (struct iscsi_task *task);
++	int (*alloc_pdu) (struct iscsi_task *task, uint8_t opcode);
+ 	int (*xmit_pdu) (struct iscsi_task *task);
+ 	int (*init_pdu) (struct iscsi_task *task, unsigned int offset,
+ 			 unsigned int count);

commit 262ef63627977acb7d8dd38c4f0f290bf49fbbfd
+Author: Mike Christie 
+Date:   Tue Dec 2 00:32:13 2008 -0600
+
+    [SCSI] libiscsi: allow drivers to modify the itt sent to the target
+    
+    bnx2i and cxgb3i need to encode LLD info in the itt so that
+    the firmware/hardware can process the pdu. This patch allows
+    the LLDs to encode info in the task->hdr->itt that they
+    setup in the alloc_pdu callout (any resources that are allocated
+    can be freed with the pdu in the cleanup_task callout). If
+    the LLD encodes info in the itt they should implement a
+    parse_pdu_itt callout. If parse_pdu_itt is not implemented
+    libiscsi will do the right thing for the LLD.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index c1bb74052aed..6c4034b1561c 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -222,12 +222,14 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
+ 	struct scsi_cmnd *sc = task->sc;
+ 	struct iscsi_cmd *hdr;
+ 	unsigned hdrlength, cmd_len;
++	itt_t itt;
+ 	int rc;
+ 
+ 	rc = conn->session->tt->alloc_pdu(task);
+ 	if (rc)
+ 		return rc;
+ 	hdr = (struct iscsi_cmd *) task->hdr;
++	itt = hdr->itt;
+ 	memset(hdr, 0, sizeof(*hdr));
+ 
+ 	task->hdr_len = 0;
+@@ -238,7 +240,11 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
+ 	hdr->flags = ISCSI_ATTR_SIMPLE;
+ 	int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
+ 	memcpy(task->lun, hdr->lun, sizeof(task->lun));
+-	hdr->itt = task->hdr_itt = build_itt(task->itt, session->age);
++	if (session->tt->parse_pdu_itt)
++		hdr->itt = task->hdr_itt = itt;
++	else
++		hdr->itt = task->hdr_itt = build_itt(task->itt,
++						     task->conn->session->age);
+ 	hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn);
+ 	session->cmdsn++;
+ 	hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
+@@ -457,7 +463,6 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn,
+ 	 */
+ 	nop->cmdsn = cpu_to_be32(session->cmdsn);
+ 	if (hdr->itt != RESERVED_ITT) {
+-		hdr->itt = build_itt(task->itt, session->age);
+ 		/*
+ 		 * TODO: We always use immediate, so we never hit this.
+ 		 * If we start to send tmfs or nops as non-immediate then
+@@ -490,6 +495,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ {
+ 	struct iscsi_session *session = conn->session;
+ 	struct iscsi_task *task;
++	itt_t itt;
+ 
+ 	if (session->state == ISCSI_STATE_TERMINATE)
+ 		return NULL;
+@@ -531,9 +537,18 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 				 "pdu for mgmt task.\n");
+ 		goto requeue_task;
+ 	}
++	itt = task->hdr->itt;
+ 	task->hdr_len = sizeof(struct iscsi_hdr);
+-
+ 	memcpy(task->hdr, hdr, sizeof(struct iscsi_hdr));
++
++	if (hdr->itt != RESERVED_ITT) {
++		if (session->tt->parse_pdu_itt)
++			task->hdr->itt = itt;
++		else
++			task->hdr->itt = build_itt(task->itt,
++						   task->conn->session->age);
++	}
++
+ 	INIT_LIST_HEAD(&task->running);
+ 	list_add_tail(&task->running, &conn->mgmtqueue);
+ 
+@@ -745,7 +760,6 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ {
+ 	struct iscsi_reject *reject = (struct iscsi_reject *)hdr;
+ 	struct iscsi_hdr rejected_pdu;
+-	uint32_t itt;
+ 
+ 	conn->exp_statsn = be32_to_cpu(reject->statsn) + 1;
+ 
+@@ -755,10 +769,9 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 
+ 		if (ntoh24(reject->dlength) >= sizeof(struct iscsi_hdr)) {
+ 			memcpy(&rejected_pdu, data, sizeof(struct iscsi_hdr));
+-			itt = get_itt(rejected_pdu.itt);
+ 			iscsi_conn_printk(KERN_ERR, conn,
+-					  "itt 0x%x had pdu (op 0x%x) rejected "
+-					  "due to DataDigest error.\n", itt,
++					  "pdu (op 0x%x) rejected "
++					  "due to DataDigest error.\n",
+ 					  rejected_pdu.opcode);
+ 		}
+ 	}
+@@ -778,12 +791,15 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ static struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *conn, itt_t itt)
+ {
+ 	struct iscsi_session *session = conn->session;
+-	uint32_t i;
++	int i;
+ 
+ 	if (itt == RESERVED_ITT)
+ 		return NULL;
+ 
+-	i = get_itt(itt);
++	if (session->tt->parse_pdu_itt)
++		session->tt->parse_pdu_itt(conn, itt, &i, NULL);
++	else
++		i = get_itt(itt);
+ 	if (i >= session->cmds_max)
+ 		return NULL;
+ 
+@@ -958,20 +974,25 @@ EXPORT_SYMBOL_GPL(iscsi_complete_pdu);
+ int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt)
+ {
+ 	struct iscsi_session *session = conn->session;
+-	uint32_t i;
++	int age = 0, i = 0;
+ 
+ 	if (itt == RESERVED_ITT)
+ 		return 0;
+ 
+-	if (((__force u32)itt & ISCSI_AGE_MASK) !=
+-	    (session->age << ISCSI_AGE_SHIFT)) {
++	if (session->tt->parse_pdu_itt)
++		session->tt->parse_pdu_itt(conn, itt, &i, &age);
++	else {
++		i = get_itt(itt);
++		age = ((__force u32)itt >> ISCSI_AGE_SHIFT) & ISCSI_AGE_MASK;
++	}
++
++	if (age != session->age) {
+ 		iscsi_conn_printk(KERN_ERR, conn,
+ 				  "received itt %x expected session age (%x)\n",
+ 				  (__force u32)itt, session->age);
+ 		return ISCSI_ERR_BAD_ITT;
+ 	}
+ 
+-	i = get_itt(itt);
+ 	if (i >= session->cmds_max) {
+ 		iscsi_conn_printk(KERN_ERR, conn,
+ 				  "received invalid itt index %u (max cmds "
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 51500573c0b8..7360e1916e75 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -30,6 +30,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ struct scsi_transport_template;
+ struct scsi_host_template;
+@@ -70,12 +71,12 @@ enum {
+ /* Connection suspend "bit" */
+ #define ISCSI_SUSPEND_BIT		1
+ 
+-#define ISCSI_ITT_MASK			(0x1fff)
++#define ISCSI_ITT_MASK			0x1fff
+ #define ISCSI_TOTAL_CMDS_MAX		4096
+ /* this must be a power of two greater than ISCSI_MGMT_CMDS_MAX */
+ #define ISCSI_TOTAL_CMDS_MIN		16
+ #define ISCSI_AGE_SHIFT			28
+-#define ISCSI_AGE_MASK			(0xf << ISCSI_AGE_SHIFT)
++#define ISCSI_AGE_MASK			0xf
+ 
+ #define ISCSI_ADDRESS_BUF_LEN		64
+ 
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index c928234c018f..e13cb20f1eae 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -122,6 +122,9 @@ struct iscsi_transport {
+ 	int (*xmit_pdu) (struct iscsi_task *task);
+ 	int (*init_pdu) (struct iscsi_task *task, unsigned int offset,
+ 			 unsigned int count);
++	void (*parse_pdu_itt) (struct iscsi_conn *conn, itt_t itt,
++			       int *index, int *age);
++
+ 	void (*session_recovery_timedout) (struct iscsi_cls_session *session);
+ 	struct iscsi_endpoint *(*ep_connect) (struct sockaddr *dst_addr,
+ 					      int non_blocking);

commit 38e1a8f5479d7d75a68d797c7159f5b7e2ef44e4
+Author: Mike Christie 
+Date:   Tue Dec 2 00:32:12 2008 -0600
+
+    [SCSI] iscsi_tcp: hook iscsi_tcp into new libiscsi_tcp module
+    
+    This hooks iscsi_tcp into the libiscsi_tcp module and removes
+    code that is now in libiscsi_tcp.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
+index 72fd5043cfa1..b89aedfa9ed7 100644
+--- a/drivers/scsi/Makefile
++++ b/drivers/scsi/Makefile
+@@ -36,7 +36,7 @@ obj-$(CONFIG_SCSI_SAS_LIBSAS)	+= libsas/
+ obj-$(CONFIG_SCSI_SRP_ATTRS)	+= scsi_transport_srp.o
+ obj-$(CONFIG_SCSI_DH)		+= device_handler/
+ 
+-obj-$(CONFIG_ISCSI_TCP) 	+= libiscsi.o	iscsi_tcp.o
++obj-$(CONFIG_ISCSI_TCP) 	+= libiscsi.o	libiscsi_tcp.o iscsi_tcp.o
+ obj-$(CONFIG_INFINIBAND_ISER) 	+= libiscsi.o
+ obj-$(CONFIG_SCSI_A4000T)	+= 53c700.o	a4000t.o
+ obj-$(CONFIG_SCSI_ZORRO7XX)	+= 53c700.o	zorro7xx.o
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 97f3f68aeb64..07d9eb14721b 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -27,7 +27,6 @@
+  */
+ 
+ #include 
+-#include 
+ #include 
+ #include 
+ #include 
+@@ -44,12 +43,12 @@
+ 
+ #include "iscsi_tcp.h"
+ 
+-MODULE_AUTHOR("Dmitry Yusupov , "
++MODULE_AUTHOR("Mike Christie , "
++	      "Dmitry Yusupov , "
+ 	      "Alex Aizman ");
+ MODULE_DESCRIPTION("iSCSI/TCP data-path");
+ MODULE_LICENSE("GPL");
+ #undef DEBUG_TCP
+-#define DEBUG_ASSERT
+ 
+ #ifdef DEBUG_TCP
+ #define debug_tcp(fmt...) printk(KERN_INFO "tcp: " fmt)
+@@ -57,924 +56,22 @@ MODULE_LICENSE("GPL");
+ #define debug_tcp(fmt...)
+ #endif
+ 
+-static struct scsi_transport_template *iscsi_tcp_scsi_transport;
+-static struct scsi_host_template iscsi_sht;
+-static struct iscsi_transport iscsi_tcp_transport;
++static struct scsi_transport_template *iscsi_sw_tcp_scsi_transport;
++static struct scsi_host_template iscsi_sw_tcp_sht;
++static struct iscsi_transport iscsi_sw_tcp_transport;
+ 
+ static unsigned int iscsi_max_lun = 512;
+ module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
+ 
+-static int iscsi_tcp_hdr_recv_done(struct iscsi_tcp_conn *tcp_conn,
+-				   struct iscsi_segment *segment);
+-
+-/*
+- * Scatterlist handling: inside the iscsi_segment, we
+- * remember an index into the scatterlist, and set data/size
+- * to the current scatterlist entry. For highmem pages, we
+- * kmap as needed.
+- *
+- * Note that the page is unmapped when we return from
+- * TCP's data_ready handler, so we may end up mapping and
+- * unmapping the same page repeatedly. The whole reason
+- * for this is that we shouldn't keep the page mapped
+- * outside the softirq.
+- */
+-
+-/**
+- * iscsi_tcp_segment_init_sg - init indicated scatterlist entry
+- * @segment: the buffer object
+- * @sg: scatterlist
+- * @offset: byte offset into that sg entry
+- *
+- * This function sets up the segment so that subsequent
+- * data is copied to the indicated sg entry, at the given
+- * offset.
+- */
+-static inline void
+-iscsi_tcp_segment_init_sg(struct iscsi_segment *segment,
+-			  struct scatterlist *sg, unsigned int offset)
+-{
+-	segment->sg = sg;
+-	segment->sg_offset = offset;
+-	segment->size = min(sg->length - offset,
+-			    segment->total_size - segment->total_copied);
+-	segment->data = NULL;
+-}
+-
+-/**
+- * iscsi_tcp_segment_map - map the current S/G page
+- * @segment: iscsi_segment
+- * @recv: 1 if called from recv path
+- *
+- * We only need to possibly kmap data if scatter lists are being used,
+- * because the iscsi passthrough and internal IO paths will never use high
+- * mem pages.
+- */
+-static inline void
+-iscsi_tcp_segment_map(struct iscsi_segment *segment, int recv)
+-{
+-	struct scatterlist *sg;
+-
+-	if (segment->data != NULL || !segment->sg)
+-		return;
+-
+-	sg = segment->sg;
+-	BUG_ON(segment->sg_mapped);
+-	BUG_ON(sg->length == 0);
+-
+-	/*
+-	 * If the page count is greater than one it is ok to send
+-	 * to the network layer's zero copy send path. If not we
+-	 * have to go the slow sendmsg path. We always map for the
+-	 * recv path.
+-	 */
+-	if (page_count(sg_page(sg)) >= 1 && !recv)
+-		return;
+-
+-	debug_tcp("iscsi_tcp_segment_map %s %p\n", recv ? "recv" : "xmit",
+-		  segment);
+-	segment->sg_mapped = kmap_atomic(sg_page(sg), KM_SOFTIRQ0);
+-	segment->data = segment->sg_mapped + sg->offset + segment->sg_offset;
+-}
+-
+-static inline void
+-iscsi_tcp_segment_unmap(struct iscsi_segment *segment)
+-{
+-	debug_tcp("iscsi_tcp_segment_unmap %p\n", segment);
+-
+-	if (segment->sg_mapped) {
+-		debug_tcp("iscsi_tcp_segment_unmap valid\n");
+-		kunmap_atomic(segment->sg_mapped, KM_SOFTIRQ0);
+-		segment->sg_mapped = NULL;
+-		segment->data = NULL;
+-	}
+-}
+-
+-/*
+- * Splice the digest buffer into the buffer
+- */
+-static inline void
+-iscsi_tcp_segment_splice_digest(struct iscsi_segment *segment, void *digest)
+-{
+-	segment->data = digest;
+-	segment->digest_len = ISCSI_DIGEST_SIZE;
+-	segment->total_size += ISCSI_DIGEST_SIZE;
+-	segment->size = ISCSI_DIGEST_SIZE;
+-	segment->copied = 0;
+-	segment->sg = NULL;
+-	segment->hash = NULL;
+-}
+-
+-/**
+- * iscsi_tcp_segment_done - check whether the segment is complete
+- * @segment: iscsi segment to check
+- * @recv: set to one of this is called from the recv path
+- * @copied: number of bytes copied
+- *
+- * Check if we're done receiving this segment. If the receive
+- * buffer is full but we expect more data, move on to the
+- * next entry in the scatterlist.
+- *
+- * If the amount of data we received isn't a multiple of 4,
+- * we will transparently receive the pad bytes, too.
+- *
+- * This function must be re-entrant.
+- */
+-static inline int
+-iscsi_tcp_segment_done(struct iscsi_segment *segment, int recv, unsigned copied)
+-{
+-	static unsigned char padbuf[ISCSI_PAD_LEN];
+-	struct scatterlist sg;
+-	unsigned int pad;
+-
+-	debug_tcp("copied %u %u size %u %s\n", segment->copied, copied,
+-		  segment->size, recv ? "recv" : "xmit");
+-	if (segment->hash && copied) {
+-		/*
+-		 * If a segment is kmapd we must unmap it before sending
+-		 * to the crypto layer since that will try to kmap it again.
+-		 */
+-		iscsi_tcp_segment_unmap(segment);
+-
+-		if (!segment->data) {
+-			sg_init_table(&sg, 1);
+-			sg_set_page(&sg, sg_page(segment->sg), copied,
+-				    segment->copied + segment->sg_offset +
+-							segment->sg->offset);
+-		} else
+-			sg_init_one(&sg, segment->data + segment->copied,
+-				    copied);
+-		crypto_hash_update(segment->hash, &sg, copied);
+-	}
+-
+-	segment->copied += copied;
+-	if (segment->copied < segment->size) {
+-		iscsi_tcp_segment_map(segment, recv);
+-		return 0;
+-	}
+-
+-	segment->total_copied += segment->copied;
+-	segment->copied = 0;
+-	segment->size = 0;
+-
+-	/* Unmap the current scatterlist page, if there is one. */
+-	iscsi_tcp_segment_unmap(segment);
+-
+-	/* Do we have more scatterlist entries? */
+-	debug_tcp("total copied %u total size %u\n", segment->total_copied,
+-		   segment->total_size);
+-	if (segment->total_copied < segment->total_size) {
+-		/* Proceed to the next entry in the scatterlist. */
+-		iscsi_tcp_segment_init_sg(segment, sg_next(segment->sg),
+-					  0);
+-		iscsi_tcp_segment_map(segment, recv);
+-		BUG_ON(segment->size == 0);
+-		return 0;
+-	}
+-
+-	/* Do we need to handle padding? */
+-	pad = iscsi_padding(segment->total_copied);
+-	if (pad != 0) {
+-		debug_tcp("consume %d pad bytes\n", pad);
+-		segment->total_size += pad;
+-		segment->size = pad;
+-		segment->data = padbuf;
+-		return 0;
+-	}
+-
+-	/*
+-	 * Set us up for transferring the data digest. hdr digest
+-	 * is completely handled in hdr done function.
+-	 */
+-	if (segment->hash) {
+-		crypto_hash_final(segment->hash, segment->digest);
+-		iscsi_tcp_segment_splice_digest(segment,
+-				 recv ? segment->recv_digest : segment->digest);
+-		return 0;
+-	}
+-
+-	return 1;
+-}
+-
+ /**
+- * iscsi_tcp_xmit_segment - transmit segment
+- * @tcp_conn: the iSCSI TCP connection
+- * @segment: the buffer to transmnit
+- *
+- * This function transmits as much of the buffer as
+- * the network layer will accept, and returns the number of
+- * bytes transmitted.
+- *
+- * If CRC hashing is enabled, the function will compute the
+- * hash as it goes. When the entire segment has been transmitted,
+- * it will retrieve the hash value and send it as well.
+- */
+-static int
+-iscsi_tcp_xmit_segment(struct iscsi_tcp_conn *tcp_conn,
+-		       struct iscsi_segment *segment)
+-{
+-	struct socket *sk = tcp_conn->sock;
+-	unsigned int copied = 0;
+-	int r = 0;
+-
+-	while (!iscsi_tcp_segment_done(segment, 0, r)) {
+-		struct scatterlist *sg;
+-		unsigned int offset, copy;
+-		int flags = 0;
+-
+-		r = 0;
+-		offset = segment->copied;
+-		copy = segment->size - offset;
+-
+-		if (segment->total_copied + segment->size < segment->total_size)
+-			flags |= MSG_MORE;
+-
+-		/* Use sendpage if we can; else fall back to sendmsg */
+-		if (!segment->data) {
+-			sg = segment->sg;
+-			offset += segment->sg_offset + sg->offset;
+-			r = tcp_conn->sendpage(sk, sg_page(sg), offset, copy,
+-					       flags);
+-		} else {
+-			struct msghdr msg = { .msg_flags = flags };
+-			struct kvec iov = {
+-				.iov_base = segment->data + offset,
+-				.iov_len = copy
+-			};
+-
+-			r = kernel_sendmsg(sk, &msg, &iov, 1, copy);
+-		}
+-
+-		if (r < 0) {
+-			iscsi_tcp_segment_unmap(segment);
+-			if (copied || r == -EAGAIN)
+-				break;
+-			return r;
+-		}
+-		copied += r;
+-	}
+-	return copied;
+-}
+-
+-/**
+- * iscsi_tcp_segment_recv - copy data to segment
+- * @tcp_conn: the iSCSI TCP connection
+- * @segment: the buffer to copy to
+- * @ptr: data pointer
+- * @len: amount of data available
+- *
+- * This function copies up to @len bytes to the
+- * given buffer, and returns the number of bytes
+- * consumed, which can actually be less than @len.
+- *
+- * If hash digest is enabled, the function will update the
+- * hash while copying.
+- * Combining these two operations doesn't buy us a lot (yet),
+- * but in the future we could implement combined copy+crc,
+- * just way we do for network layer checksums.
+- */
+-static int
+-iscsi_tcp_segment_recv(struct iscsi_tcp_conn *tcp_conn,
+-		       struct iscsi_segment *segment, const void *ptr,
+-		       unsigned int len)
+-{
+-	unsigned int copy = 0, copied = 0;
+-
+-	while (!iscsi_tcp_segment_done(segment, 1, copy)) {
+-		if (copied == len) {
+-			debug_tcp("iscsi_tcp_segment_recv copied %d bytes\n",
+-				  len);
+-			break;
+-		}
+-
+-		copy = min(len - copied, segment->size - segment->copied);
+-		debug_tcp("iscsi_tcp_segment_recv copying %d\n", copy);
+-		memcpy(segment->data + segment->copied, ptr + copied, copy);
+-		copied += copy;
+-	}
+-	return copied;
+-}
+-
+-static inline void
+-iscsi_tcp_dgst_header(struct hash_desc *hash, const void *hdr, size_t hdrlen,
+-		      unsigned char digest[ISCSI_DIGEST_SIZE])
+-{
+-	struct scatterlist sg;
+-
+-	sg_init_one(&sg, hdr, hdrlen);
+-	crypto_hash_digest(hash, &sg, hdrlen, digest);
+-}
+-
+-static inline int
+-iscsi_tcp_dgst_verify(struct iscsi_tcp_conn *tcp_conn,
+-		      struct iscsi_segment *segment)
+-{
+-	if (!segment->digest_len)
+-		return 1;
+-
+-	if (memcmp(segment->recv_digest, segment->digest,
+-		   segment->digest_len)) {
+-		debug_scsi("digest mismatch\n");
+-		return 0;
+-	}
+-
+-	return 1;
+-}
+-
+-/*
+- * Helper function to set up segment buffer
+- */
+-static inline void
+-__iscsi_segment_init(struct iscsi_segment *segment, size_t size,
+-		     iscsi_segment_done_fn_t *done, struct hash_desc *hash)
+-{
+-	memset(segment, 0, sizeof(*segment));
+-	segment->total_size = size;
+-	segment->done = done;
+-
+-	if (hash) {
+-		segment->hash = hash;
+-		crypto_hash_init(hash);
+-	}
+-}
+-
+-static inline void
+-iscsi_segment_init_linear(struct iscsi_segment *segment, void *data,
+-			  size_t size, iscsi_segment_done_fn_t *done,
+-			  struct hash_desc *hash)
+-{
+-	__iscsi_segment_init(segment, size, done, hash);
+-	segment->data = data;
+-	segment->size = size;
+-}
+-
+-static inline int
+-iscsi_segment_seek_sg(struct iscsi_segment *segment,
+-		      struct scatterlist *sg_list, unsigned int sg_count,
+-		      unsigned int offset, size_t size,
+-		      iscsi_segment_done_fn_t *done, struct hash_desc *hash)
+-{
+-	struct scatterlist *sg;
+-	unsigned int i;
+-
+-	debug_scsi("iscsi_segment_seek_sg offset %u size %llu\n",
+-		  offset, size);
+-	__iscsi_segment_init(segment, size, done, hash);
+-	for_each_sg(sg_list, sg, sg_count, i) {
+-		debug_scsi("sg %d, len %u offset %u\n", i, sg->length,
+-			   sg->offset);
+-		if (offset < sg->length) {
+-			iscsi_tcp_segment_init_sg(segment, sg, offset);
+-			return 0;
+-		}
+-		offset -= sg->length;
+-	}
+-
+-	return ISCSI_ERR_DATA_OFFSET;
+-}
+-
+-/**
+- * iscsi_tcp_hdr_recv_prep - prep segment for hdr reception
+- * @tcp_conn: iscsi connection to prep for
+- *
+- * This function always passes NULL for the hash argument, because when this
+- * function is called we do not yet know the final size of the header and want
+- * to delay the digest processing until we know that.
+- */
+-static void
+-iscsi_tcp_hdr_recv_prep(struct iscsi_tcp_conn *tcp_conn)
+-{
+-	debug_tcp("iscsi_tcp_hdr_recv_prep(%p%s)\n", tcp_conn,
+-		  tcp_conn->iscsi_conn->hdrdgst_en ? ", digest enabled" : "");
+-	iscsi_segment_init_linear(&tcp_conn->in.segment,
+-				tcp_conn->in.hdr_buf, sizeof(struct iscsi_hdr),
+-				iscsi_tcp_hdr_recv_done, NULL);
+-}
+-
+-/*
+- * Handle incoming reply to any other type of command
+- */
+-static int
+-iscsi_tcp_data_recv_done(struct iscsi_tcp_conn *tcp_conn,
+-			 struct iscsi_segment *segment)
+-{
+-	struct iscsi_conn *conn = tcp_conn->iscsi_conn;
+-	int rc = 0;
+-
+-	if (!iscsi_tcp_dgst_verify(tcp_conn, segment))
+-		return ISCSI_ERR_DATA_DGST;
+-
+-	rc = iscsi_complete_pdu(conn, tcp_conn->in.hdr,
+-			conn->data, tcp_conn->in.datalen);
+-	if (rc)
+-		return rc;
+-
+-	iscsi_tcp_hdr_recv_prep(tcp_conn);
+-	return 0;
+-}
+-
+-static void
+-iscsi_tcp_data_recv_prep(struct iscsi_tcp_conn *tcp_conn)
+-{
+-	struct iscsi_conn *conn = tcp_conn->iscsi_conn;
+-	struct hash_desc *rx_hash = NULL;
+-
+-	if (conn->datadgst_en &
+-	    !(conn->session->tt->caps & CAP_DIGEST_OFFLOAD))
+-		rx_hash = &tcp_conn->rx_hash;
+-
+-	iscsi_segment_init_linear(&tcp_conn->in.segment,
+-				conn->data, tcp_conn->in.datalen,
+-				iscsi_tcp_data_recv_done, rx_hash);
+-}
+-
+-/*
+- * must be called with session lock
+- */
+-static void iscsi_tcp_cleanup_task(struct iscsi_task *task)
+-{
+-	struct iscsi_tcp_task *tcp_task = task->dd_data;
+-	struct iscsi_r2t_info *r2t;
+-
+-	/* nothing to do for mgmt or pending tasks */
+-	if (!task->sc || task->state == ISCSI_TASK_PENDING)
+-		return;
+-
+-	/* flush task's r2t queues */
+-	while (__kfifo_get(tcp_task->r2tqueue, (void*)&r2t, sizeof(void*))) {
+-		__kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
+-			    sizeof(void*));
+-		debug_scsi("iscsi_tcp_cleanup_task pending r2t dropped\n");
+-	}
+-
+-	r2t = tcp_task->r2t;
+-	if (r2t != NULL) {
+-		__kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
+-			    sizeof(void*));
+-		tcp_task->r2t = NULL;
+-	}
+-}
+-
+-/**
+- * iscsi_tcp_data_in - SCSI Data-In Response processing
+- * @conn: iscsi connection
+- * @task: scsi command task
+- */
+-static int iscsi_tcp_data_in(struct iscsi_conn *conn, struct iscsi_task *task)
+-{
+-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+-	struct iscsi_tcp_task *tcp_task = task->dd_data;
+-	struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)tcp_conn->in.hdr;
+-	int datasn = be32_to_cpu(rhdr->datasn);
+-	unsigned total_in_length = scsi_in(task->sc)->length;
+-
+-	iscsi_update_cmdsn(conn->session, (struct iscsi_nopin*)rhdr);
+-	if (tcp_conn->in.datalen == 0)
+-		return 0;
+-
+-	if (tcp_task->exp_datasn != datasn) {
+-		debug_tcp("%s: task->exp_datasn(%d) != rhdr->datasn(%d)\n",
+-		          __func__, tcp_task->exp_datasn, datasn);
+-		return ISCSI_ERR_DATASN;
+-	}
+-
+-	tcp_task->exp_datasn++;
+-
+-	tcp_task->data_offset = be32_to_cpu(rhdr->offset);
+-	if (tcp_task->data_offset + tcp_conn->in.datalen > total_in_length) {
+-		debug_tcp("%s: data_offset(%d) + data_len(%d) > total_length_in(%d)\n",
+-		          __func__, tcp_task->data_offset,
+-		          tcp_conn->in.datalen, total_in_length);
+-		return ISCSI_ERR_DATA_OFFSET;
+-	}
+-
+-	conn->datain_pdus_cnt++;
+-	return 0;
+-}
+-
+-/**
+- * iscsi_tcp_r2t_rsp - iSCSI R2T Response processing
+- * @conn: iscsi connection
+- * @task: scsi command task
+- */
+-static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
+-{
+-	struct iscsi_session *session = conn->session;
+-	struct iscsi_tcp_task *tcp_task = task->dd_data;
+-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+-	struct iscsi_r2t_rsp *rhdr = (struct iscsi_r2t_rsp *)tcp_conn->in.hdr;
+-	struct iscsi_r2t_info *r2t;
+-	int r2tsn = be32_to_cpu(rhdr->r2tsn);
+-	int rc;
+-
+-	if (tcp_conn->in.datalen) {
+-		iscsi_conn_printk(KERN_ERR, conn,
+-				  "invalid R2t with datalen %d\n",
+-				  tcp_conn->in.datalen);
+-		return ISCSI_ERR_DATALEN;
+-	}
+-
+-	if (tcp_task->exp_datasn != r2tsn){
+-		debug_tcp("%s: task->exp_datasn(%d) != rhdr->r2tsn(%d)\n",
+-		          __func__, tcp_task->exp_datasn, r2tsn);
+-		return ISCSI_ERR_R2TSN;
+-	}
+-
+-	/* fill-in new R2T associated with the task */
+-	iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
+-
+-	if (!task->sc || session->state != ISCSI_STATE_LOGGED_IN) {
+-		iscsi_conn_printk(KERN_INFO, conn,
+-				  "dropping R2T itt %d in recovery.\n",
+-				  task->itt);
+-		return 0;
+-	}
+-
+-	rc = __kfifo_get(tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*));
+-	if (!rc) {
+-		iscsi_conn_printk(KERN_ERR, conn, "Could not allocate R2T. "
+-				  "Target has sent more R2Ts than it "
+-				  "negotiated for or driver has has leaked.\n");
+-		return ISCSI_ERR_PROTO;
+-	}
+-
+-	r2t->exp_statsn = rhdr->statsn;
+-	r2t->data_length = be32_to_cpu(rhdr->data_length);
+-	if (r2t->data_length == 0) {
+-		iscsi_conn_printk(KERN_ERR, conn,
+-				  "invalid R2T with zero data len\n");
+-		__kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
+-			    sizeof(void*));
+-		return ISCSI_ERR_DATALEN;
+-	}
+-
+-	if (r2t->data_length > session->max_burst)
+-		debug_scsi("invalid R2T with data len %u and max burst %u."
+-			   "Attempting to execute request.\n",
+-			    r2t->data_length, session->max_burst);
+-
+-	r2t->data_offset = be32_to_cpu(rhdr->data_offset);
+-	if (r2t->data_offset + r2t->data_length > scsi_out(task->sc)->length) {
+-		iscsi_conn_printk(KERN_ERR, conn,
+-				  "invalid R2T with data len %u at offset %u "
+-				  "and total length %d\n", r2t->data_length,
+-				  r2t->data_offset, scsi_out(task->sc)->length);
+-		__kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
+-			    sizeof(void*));
+-		return ISCSI_ERR_DATALEN;
+-	}
+-
+-	r2t->ttt = rhdr->ttt; /* no flip */
+-	r2t->datasn = 0;
+-	r2t->sent = 0;
+-
+-	tcp_task->exp_datasn = r2tsn + 1;
+-	__kfifo_put(tcp_task->r2tqueue, (void*)&r2t, sizeof(void*));
+-	conn->r2t_pdus_cnt++;
+-
+-	iscsi_requeue_task(task);
+-	return 0;
+-}
+-
+-/*
+- * Handle incoming reply to DataIn command
+- */
+-static int
+-iscsi_tcp_process_data_in(struct iscsi_tcp_conn *tcp_conn,
+-			  struct iscsi_segment *segment)
+-{
+-	struct iscsi_conn *conn = tcp_conn->iscsi_conn;
+-	struct iscsi_hdr *hdr = tcp_conn->in.hdr;
+-	int rc;
+-
+-	if (!iscsi_tcp_dgst_verify(tcp_conn, segment))
+-		return ISCSI_ERR_DATA_DGST;
+-
+-	/* check for non-exceptional status */
+-	if (hdr->flags & ISCSI_FLAG_DATA_STATUS) {
+-		rc = iscsi_complete_pdu(conn, tcp_conn->in.hdr, NULL, 0);
+-		if (rc)
+-			return rc;
+-	}
+-
+-	iscsi_tcp_hdr_recv_prep(tcp_conn);
+-	return 0;
+-}
+-
+-/**
+- * iscsi_tcp_hdr_dissect - process PDU header
+- * @conn: iSCSI connection
+- * @hdr: PDU header
+- *
+- * This function analyzes the header of the PDU received,
+- * and performs several sanity checks. If the PDU is accompanied
+- * by data, the receive buffer is set up to copy the incoming data
+- * to the correct location.
+- */
+-static int
+-iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+-{
+-	int rc = 0, opcode, ahslen;
+-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+-	struct iscsi_task *task;
+-
+-	/* verify PDU length */
+-	tcp_conn->in.datalen = ntoh24(hdr->dlength);
+-	if (tcp_conn->in.datalen > conn->max_recv_dlength) {
+-		iscsi_conn_printk(KERN_ERR, conn,
+-				  "iscsi_tcp: datalen %d > %d\n",
+-				  tcp_conn->in.datalen, conn->max_recv_dlength);
+-		return ISCSI_ERR_DATALEN;
+-	}
+-
+-	/* Additional header segments. So far, we don't
+-	 * process additional headers.
+-	 */
+-	ahslen = hdr->hlength << 2;
+-
+-	opcode = hdr->opcode & ISCSI_OPCODE_MASK;
+-	/* verify itt (itt encoding: age+cid+itt) */
+-	rc = iscsi_verify_itt(conn, hdr->itt);
+-	if (rc)
+-		return rc;
+-
+-	debug_tcp("opcode 0x%x ahslen %d datalen %d\n",
+-		  opcode, ahslen, tcp_conn->in.datalen);
+-
+-	switch(opcode) {
+-	case ISCSI_OP_SCSI_DATA_IN:
+-		spin_lock(&conn->session->lock);
+-		task = iscsi_itt_to_ctask(conn, hdr->itt);
+-		if (!task)
+-			rc = ISCSI_ERR_BAD_ITT;
+-		else
+-			rc = iscsi_tcp_data_in(conn, task);
+-		if (rc) {
+-			spin_unlock(&conn->session->lock);
+-			break;
+-		}
+-
+-		if (tcp_conn->in.datalen) {
+-			struct iscsi_tcp_task *tcp_task = task->dd_data;
+-			struct hash_desc *rx_hash = NULL;
+-			struct scsi_data_buffer *sdb = scsi_in(task->sc);
+-
+-			/*
+-			 * Setup copy of Data-In into the Scsi_Cmnd
+-			 * Scatterlist case:
+-			 * We set up the iscsi_segment to point to the next
+-			 * scatterlist entry to copy to. As we go along,
+-			 * we move on to the next scatterlist entry and
+-			 * update the digest per-entry.
+-			 */
+-			if (conn->datadgst_en &&
+-			    !(conn->session->tt->caps & CAP_DIGEST_OFFLOAD))
+-				rx_hash = &tcp_conn->rx_hash;
+-
+-			debug_tcp("iscsi_tcp_begin_data_in(%p, offset=%d, "
+-				  "datalen=%d)\n", tcp_conn,
+-				  tcp_task->data_offset,
+-				  tcp_conn->in.datalen);
+-			rc = iscsi_segment_seek_sg(&tcp_conn->in.segment,
+-						   sdb->table.sgl,
+-						   sdb->table.nents,
+-						   tcp_task->data_offset,
+-						   tcp_conn->in.datalen,
+-						   iscsi_tcp_process_data_in,
+-						   rx_hash);
+-			spin_unlock(&conn->session->lock);
+-			return rc;
+-		}
+-		rc = __iscsi_complete_pdu(conn, hdr, NULL, 0);
+-		spin_unlock(&conn->session->lock);
+-		break;
+-	case ISCSI_OP_SCSI_CMD_RSP:
+-		if (tcp_conn->in.datalen) {
+-			iscsi_tcp_data_recv_prep(tcp_conn);
+-			return 0;
+-		}
+-		rc = iscsi_complete_pdu(conn, hdr, NULL, 0);
+-		break;
+-	case ISCSI_OP_R2T:
+-		spin_lock(&conn->session->lock);
+-		task = iscsi_itt_to_ctask(conn, hdr->itt);
+-		if (!task)
+-			rc = ISCSI_ERR_BAD_ITT;
+-		else if (ahslen)
+-			rc = ISCSI_ERR_AHSLEN;
+-		else if (task->sc->sc_data_direction == DMA_TO_DEVICE)
+-			rc = iscsi_tcp_r2t_rsp(conn, task);
+-		else
+-			rc = ISCSI_ERR_PROTO;
+-		spin_unlock(&conn->session->lock);
+-		break;
+-	case ISCSI_OP_LOGIN_RSP:
+-	case ISCSI_OP_TEXT_RSP:
+-	case ISCSI_OP_REJECT:
+-	case ISCSI_OP_ASYNC_EVENT:
+-		/*
+-		 * It is possible that we could get a PDU with a buffer larger
+-		 * than 8K, but there are no targets that currently do this.
+-		 * For now we fail until we find a vendor that needs it
+-		 */
+-		if (ISCSI_DEF_MAX_RECV_SEG_LEN < tcp_conn->in.datalen) {
+-			iscsi_conn_printk(KERN_ERR, conn,
+-					  "iscsi_tcp: received buffer of "
+-					  "len %u but conn buffer is only %u "
+-					  "(opcode %0x)\n",
+-					  tcp_conn->in.datalen,
+-					  ISCSI_DEF_MAX_RECV_SEG_LEN, opcode);
+-			rc = ISCSI_ERR_PROTO;
+-			break;
+-		}
+-
+-		/* If there's data coming in with the response,
+-		 * receive it to the connection's buffer.
+-		 */
+-		if (tcp_conn->in.datalen) {
+-			iscsi_tcp_data_recv_prep(tcp_conn);
+-			return 0;
+-		}
+-	/* fall through */
+-	case ISCSI_OP_LOGOUT_RSP:
+-	case ISCSI_OP_NOOP_IN:
+-	case ISCSI_OP_SCSI_TMFUNC_RSP:
+-		rc = iscsi_complete_pdu(conn, hdr, NULL, 0);
+-		break;
+-	default:
+-		rc = ISCSI_ERR_BAD_OPCODE;
+-		break;
+-	}
+-
+-	if (rc == 0) {
+-		/* Anything that comes with data should have
+-		 * been handled above. */
+-		if (tcp_conn->in.datalen)
+-			return ISCSI_ERR_PROTO;
+-		iscsi_tcp_hdr_recv_prep(tcp_conn);
+-	}
+-
+-	return rc;
+-}
+-
+-/**
+- * iscsi_tcp_hdr_recv_done - process PDU header
+- *
+- * This is the callback invoked when the PDU header has
+- * been received. If the header is followed by additional
+- * header segments, we go back for more data.
+- */
+-static int
+-iscsi_tcp_hdr_recv_done(struct iscsi_tcp_conn *tcp_conn,
+-			struct iscsi_segment *segment)
+-{
+-	struct iscsi_conn *conn = tcp_conn->iscsi_conn;
+-	struct iscsi_hdr *hdr;
+-
+-	/* Check if there are additional header segments
+-	 * *prior* to computing the digest, because we
+-	 * may need to go back to the caller for more.
+-	 */
+-	hdr = (struct iscsi_hdr *) tcp_conn->in.hdr_buf;
+-	if (segment->copied == sizeof(struct iscsi_hdr) && hdr->hlength) {
+-		/* Bump the header length - the caller will
+-		 * just loop around and get the AHS for us, and
+-		 * call again. */
+-		unsigned int ahslen = hdr->hlength << 2;
+-
+-		/* Make sure we don't overflow */
+-		if (sizeof(*hdr) + ahslen > sizeof(tcp_conn->in.hdr_buf))
+-			return ISCSI_ERR_AHSLEN;
+-
+-		segment->total_size += ahslen;
+-		segment->size += ahslen;
+-		return 0;
+-	}
+-
+-	/* We're done processing the header. See if we're doing
+-	 * header digests; if so, set up the recv_digest buffer
+-	 * and go back for more. */
+-	if (conn->hdrdgst_en) {
+-		if (segment->digest_len == 0) {
+-			/*
+-			 * Even if we offload the digest processing we
+-			 * splice it in so we can increment the skb/segment
+-			 * counters in preparation for the data segment.
+-			 */
+-			iscsi_tcp_segment_splice_digest(segment,
+-							segment->recv_digest);
+-			return 0;
+-		}
+-
+-		if (!(conn->session->tt->caps & CAP_DIGEST_OFFLOAD)) {
+-			iscsi_tcp_dgst_header(&tcp_conn->rx_hash, hdr,
+-				segment->total_copied - ISCSI_DIGEST_SIZE,
+-				segment->digest);
+-
+-			if (!iscsi_tcp_dgst_verify(tcp_conn, segment))
+-				return ISCSI_ERR_HDR_DGST;
+-		}
+-	}
+-
+-	tcp_conn->in.hdr = hdr;
+-	return iscsi_tcp_hdr_dissect(conn, hdr);
+-}
+-
+-inline int iscsi_tcp_recv_segment_is_hdr(struct iscsi_tcp_conn *tcp_conn)
+-{
+-	return tcp_conn->in.segment.done == iscsi_tcp_hdr_recv_done;
+-}
+-
+-enum {
+-	ISCSI_TCP_SEGMENT_DONE,		/* curr seg has been processed */
+-	ISCSI_TCP_SKB_DONE,		/* skb is out of data */
+-	ISCSI_TCP_CONN_ERR,		/* iscsi layer has fired a conn err */
+-	ISCSI_TCP_SUSPENDED,		/* conn is suspended */
+-};
+-
+-/**
+- * iscsi_tcp_recv_skb - Process skb
+- * @conn: iscsi connection
+- * @skb: network buffer with header and/or data segment
+- * @offset: offset in skb
+- * @offload: bool indicating if transfer was offloaded
+- */
+-int iscsi_tcp_recv_skb(struct iscsi_conn *conn, struct sk_buff *skb,
+-		       unsigned int offset, bool offloaded, int *status)
+-{
+-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+-	struct iscsi_segment *segment = &tcp_conn->in.segment;
+-	struct skb_seq_state seq;
+-	unsigned int consumed = 0;
+-	int rc = 0;
+-
+-	debug_tcp("in %d bytes\n", skb->len - offset);
+-
+-	if (unlikely(conn->suspend_rx)) {
+-		debug_tcp("conn %d Rx suspended!\n", conn->id);
+-		*status = ISCSI_TCP_SUSPENDED;
+-		return 0;
+-	}
+-
+-	if (offloaded) {
+-		segment->total_copied = segment->total_size;
+-		goto segment_done;
+-	}
+-
+-	skb_prepare_seq_read(skb, offset, skb->len, &seq);
+-	while (1) {
+-		unsigned int avail;
+-		const u8 *ptr;
+-
+-		avail = skb_seq_read(consumed, &ptr, &seq);
+-		if (avail == 0) {
+-			debug_tcp("no more data avail. Consumed %d\n",
+-				  consumed);
+-			*status = ISCSI_TCP_SKB_DONE;
+-			skb_abort_seq_read(&seq);
+-			goto skb_done;
+-		}
+-		BUG_ON(segment->copied >= segment->size);
+-
+-		debug_tcp("skb %p ptr=%p avail=%u\n", skb, ptr, avail);
+-		rc = iscsi_tcp_segment_recv(tcp_conn, segment, ptr, avail);
+-		BUG_ON(rc == 0);
+-		consumed += rc;
+-
+-		if (segment->total_copied >= segment->total_size) {
+-			skb_abort_seq_read(&seq);
+-			goto segment_done;
+-		}
+-	}
+-
+-segment_done:
+-	*status = ISCSI_TCP_SEGMENT_DONE;
+-	debug_tcp("segment done\n");
+-	rc = segment->done(tcp_conn, segment);
+-	if (rc != 0) {
+-		*status = ISCSI_TCP_CONN_ERR;
+-		debug_tcp("Error receiving PDU, errno=%d\n", rc);
+-		iscsi_conn_failure(conn, rc);
+-		return 0;
+-	}
+-	/* The done() functions sets up the next segment. */
+-
+-skb_done:
+-	conn->rxdata_octets += consumed;
+-	return consumed;
+-}
+-EXPORT_SYMBOL_GPL(iscsi_tcp_recv_skb);
+-
+-/**
+- * iscsi_tcp_recv - TCP receive in sendfile fashion
++ * iscsi_sw_tcp_recv - TCP receive in sendfile fashion
+  * @rd_desc: read descriptor
+  * @skb: socket buffer
+  * @offset: offset in skb
+  * @len: skb->len - offset
+- **/
+-static int
+-iscsi_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+-	       unsigned int offset, size_t len)
++ */
++static int iscsi_sw_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
++			     unsigned int offset, size_t len)
+ {
+ 	struct iscsi_conn *conn = rd_desc->arg.data;
+ 	unsigned int consumed, total_consumed = 0;
+@@ -993,8 +90,7 @@ iscsi_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 	return total_consumed;
+ }
+ 
+-static void
+-iscsi_tcp_data_ready(struct sock *sk, int flag)
++static void iscsi_sw_tcp_data_ready(struct sock *sk, int flag)
+ {
+ 	struct iscsi_conn *conn = sk->sk_user_data;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+@@ -1010,7 +106,7 @@ iscsi_tcp_data_ready(struct sock *sk, int flag)
+ 	 */
+ 	rd_desc.arg.data = conn;
+ 	rd_desc.count = 1;
+-	tcp_read_sock(sk, &rd_desc, iscsi_tcp_recv);
++	tcp_read_sock(sk, &rd_desc, iscsi_sw_tcp_recv);
+ 
+ 	read_unlock(&sk->sk_callback_lock);
+ 
+@@ -1019,10 +115,10 @@ iscsi_tcp_data_ready(struct sock *sk, int flag)
+ 	iscsi_tcp_segment_unmap(&tcp_conn->in.segment);
+ }
+ 
+-static void
+-iscsi_tcp_state_change(struct sock *sk)
++static void iscsi_sw_tcp_state_change(struct sock *sk)
+ {
+ 	struct iscsi_tcp_conn *tcp_conn;
++	struct iscsi_sw_tcp_conn *tcp_sw_conn;
+ 	struct iscsi_conn *conn;
+ 	struct iscsi_session *session;
+ 	void (*old_state_change)(struct sock *);
+@@ -1040,7 +136,8 @@ iscsi_tcp_state_change(struct sock *sk)
+ 	}
+ 
+ 	tcp_conn = conn->dd_data;
+-	old_state_change = tcp_conn->old_state_change;
++	tcp_sw_conn = tcp_conn->dd_data;
++	old_state_change = tcp_sw_conn->old_state_change;
+ 
+ 	read_unlock(&sk->sk_callback_lock);
+ 
+@@ -1051,59 +148,122 @@ iscsi_tcp_state_change(struct sock *sk)
+  * iscsi_write_space - Called when more output buffer space is available
+  * @sk: socket space is available for
+  **/
+-static void iscsi_tcp_write_space(struct sock *sk)
++static void iscsi_sw_tcp_write_space(struct sock *sk)
+ {
+ 	struct iscsi_conn *conn = (struct iscsi_conn*)sk->sk_user_data;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
+ 
+-	tcp_conn->old_write_space(sk);
++	tcp_sw_conn->old_write_space(sk);
+ 	debug_tcp("iscsi_write_space: cid %d\n", conn->id);
+ 	scsi_queue_work(conn->session->host, &conn->xmitwork);
+ }
+ 
+-static void iscsi_tcp_conn_set_callbacks(struct iscsi_conn *conn)
++static void iscsi_sw_tcp_conn_set_callbacks(struct iscsi_conn *conn)
+ {
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+-	struct sock *sk = tcp_conn->sock->sk;
++	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
++	struct sock *sk = tcp_sw_conn->sock->sk;
+ 
+ 	/* assign new callbacks */
+ 	write_lock_bh(&sk->sk_callback_lock);
+ 	sk->sk_user_data = conn;
+-	tcp_conn->old_data_ready = sk->sk_data_ready;
+-	tcp_conn->old_state_change = sk->sk_state_change;
+-	tcp_conn->old_write_space = sk->sk_write_space;
+-	sk->sk_data_ready = iscsi_tcp_data_ready;
+-	sk->sk_state_change = iscsi_tcp_state_change;
+-	sk->sk_write_space = iscsi_tcp_write_space;
++	tcp_sw_conn->old_data_ready = sk->sk_data_ready;
++	tcp_sw_conn->old_state_change = sk->sk_state_change;
++	tcp_sw_conn->old_write_space = sk->sk_write_space;
++	sk->sk_data_ready = iscsi_sw_tcp_data_ready;
++	sk->sk_state_change = iscsi_sw_tcp_state_change;
++	sk->sk_write_space = iscsi_sw_tcp_write_space;
+ 	write_unlock_bh(&sk->sk_callback_lock);
+ }
+ 
+-static void iscsi_conn_restore_callbacks(struct iscsi_tcp_conn *tcp_conn)
++static void
++iscsi_sw_tcp_conn_restore_callbacks(struct iscsi_sw_tcp_conn *tcp_sw_conn)
+ {
+-	struct sock *sk = tcp_conn->sock->sk;
++	struct sock *sk = tcp_sw_conn->sock->sk;
+ 
+ 	/* restore socket callbacks, see also: iscsi_conn_set_callbacks() */
+ 	write_lock_bh(&sk->sk_callback_lock);
+ 	sk->sk_user_data    = NULL;
+-	sk->sk_data_ready   = tcp_conn->old_data_ready;
+-	sk->sk_state_change = tcp_conn->old_state_change;
+-	sk->sk_write_space  = tcp_conn->old_write_space;
++	sk->sk_data_ready   = tcp_sw_conn->old_data_ready;
++	sk->sk_state_change = tcp_sw_conn->old_state_change;
++	sk->sk_write_space  = tcp_sw_conn->old_write_space;
+ 	sk->sk_no_check	 = 0;
+ 	write_unlock_bh(&sk->sk_callback_lock);
+ }
+ 
+ /**
+- * iscsi_tcp_xmit - TCP transmit
++ * iscsi_sw_tcp_xmit_segment - transmit segment
++ * @tcp_sw_conn: the iSCSI TCP connection
++ * @segment: the buffer to transmnit
++ *
++ * This function transmits as much of the buffer as
++ * the network layer will accept, and returns the number of
++ * bytes transmitted.
++ *
++ * If CRC hashing is enabled, the function will compute the
++ * hash as it goes. When the entire segment has been transmitted,
++ * it will retrieve the hash value and send it as well.
++ */
++static int iscsi_sw_tcp_xmit_segment(struct iscsi_sw_tcp_conn *tcp_sw_conn,
++				     struct iscsi_segment *segment)
++{
++	struct socket *sk = tcp_sw_conn->sock;
++	unsigned int copied = 0;
++	int r = 0;
++
++	while (!iscsi_tcp_segment_done(segment, 0, r)) {
++		struct scatterlist *sg;
++		unsigned int offset, copy;
++		int flags = 0;
++
++		r = 0;
++		offset = segment->copied;
++		copy = segment->size - offset;
++
++		if (segment->total_copied + segment->size < segment->total_size)
++			flags |= MSG_MORE;
++
++		/* Use sendpage if we can; else fall back to sendmsg */
++		if (!segment->data) {
++			sg = segment->sg;
++			offset += segment->sg_offset + sg->offset;
++			r = tcp_sw_conn->sendpage(sk, sg_page(sg), offset,
++						  copy, flags);
++		} else {
++			struct msghdr msg = { .msg_flags = flags };
++			struct kvec iov = {
++				.iov_base = segment->data + offset,
++				.iov_len = copy
++			};
++
++			r = kernel_sendmsg(sk, &msg, &iov, 1, copy);
++		}
++
++		if (r < 0) {
++			iscsi_tcp_segment_unmap(segment);
++			if (copied || r == -EAGAIN)
++				break;
++			return r;
++		}
++		copied += r;
++	}
++	return copied;
++}
++
++/**
++ * iscsi_sw_tcp_xmit - TCP transmit
+  **/
+-static int iscsi_tcp_xmit(struct iscsi_conn *conn)
++static int iscsi_sw_tcp_xmit(struct iscsi_conn *conn)
+ {
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+-	struct iscsi_segment *segment = &tcp_conn->out.segment;
++	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
++	struct iscsi_segment *segment = &tcp_sw_conn->out.segment;
+ 	unsigned int consumed = 0;
+ 	int rc = 0;
+ 
+ 	while (1) {
+-		rc = iscsi_tcp_xmit_segment(tcp_conn, segment);
++		rc = iscsi_sw_tcp_xmit_segment(tcp_sw_conn, segment);
+ 		if (rc < 0) {
+ 			rc = ISCSI_ERR_XMIT_FAILED;
+ 			goto error;
+@@ -1138,22 +298,22 @@ static int iscsi_tcp_xmit(struct iscsi_conn *conn)
+ /**
+  * iscsi_tcp_xmit_qlen - return the number of bytes queued for xmit
+  */
+-static inline int
+-iscsi_tcp_xmit_qlen(struct iscsi_conn *conn)
++static inline int iscsi_sw_tcp_xmit_qlen(struct iscsi_conn *conn)
+ {
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+-	struct iscsi_segment *segment = &tcp_conn->out.segment;
++	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
++	struct iscsi_segment *segment = &tcp_sw_conn->out.segment;
+ 
+ 	return segment->total_copied - segment->total_size;
+ }
+ 
+-static int iscsi_tcp_flush(struct iscsi_task *task)
++static int iscsi_sw_tcp_pdu_xmit(struct iscsi_task *task)
+ {
+ 	struct iscsi_conn *conn = task->conn;
+ 	int rc;
+ 
+-	while (iscsi_tcp_xmit_qlen(conn)) {
+-		rc = iscsi_tcp_xmit(conn);
++	while (iscsi_sw_tcp_xmit_qlen(conn)) {
++		rc = iscsi_sw_tcp_xmit(conn);
+ 		if (rc == 0)
+ 			return -EAGAIN;
+ 		if (rc < 0)
+@@ -1167,27 +327,31 @@ static int iscsi_tcp_flush(struct iscsi_task *task)
+  * This is called when we're done sending the header.
+  * Simply copy the data_segment to the send segment, and return.
+  */
+-static int
+-iscsi_tcp_send_hdr_done(struct iscsi_tcp_conn *tcp_conn,
+-			struct iscsi_segment *segment)
++static int iscsi_sw_tcp_send_hdr_done(struct iscsi_tcp_conn *tcp_conn,
++				      struct iscsi_segment *segment)
+ {
+-	tcp_conn->out.segment = tcp_conn->out.data_segment;
++	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
++
++	tcp_sw_conn->out.segment = tcp_sw_conn->out.data_segment;
+ 	debug_tcp("Header done. Next segment size %u total_size %u\n",
+-		  tcp_conn->out.segment.size, tcp_conn->out.segment.total_size);
++		  tcp_sw_conn->out.segment.size,
++		  tcp_sw_conn->out.segment.total_size);
+ 	return 0;
+ }
+ 
+-static void
+-iscsi_tcp_send_hdr_prep(struct iscsi_conn *conn, void *hdr, size_t hdrlen)
++static void iscsi_sw_tcp_send_hdr_prep(struct iscsi_conn *conn, void *hdr,
++				       size_t hdrlen)
+ {
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
+ 
+ 	debug_tcp("%s(%p%s)\n", __func__, tcp_conn,
+ 			conn->hdrdgst_en? ", digest enabled" : "");
+ 
+ 	/* Clear the data segment - needs to be filled in by the
+ 	 * caller using iscsi_tcp_send_data_prep() */
+-	memset(&tcp_conn->out.data_segment, 0, sizeof(struct iscsi_segment));
++	memset(&tcp_sw_conn->out.data_segment, 0,
++	       sizeof(struct iscsi_segment));
+ 
+ 	/* If header digest is enabled, compute the CRC and
+ 	 * place the digest into the same buffer. We make
+@@ -1195,7 +359,7 @@ iscsi_tcp_send_hdr_prep(struct iscsi_conn *conn, void *hdr, size_t hdrlen)
+ 	 * sufficient room.
+ 	 */
+ 	if (conn->hdrdgst_en) {
+-		iscsi_tcp_dgst_header(&tcp_conn->tx_hash, hdr, hdrlen,
++		iscsi_tcp_dgst_header(&tcp_sw_conn->tx_hash, hdr, hdrlen,
+ 				      hdr + hdrlen);
+ 		hdrlen += ISCSI_DIGEST_SIZE;
+ 	}
+@@ -1203,10 +367,10 @@ iscsi_tcp_send_hdr_prep(struct iscsi_conn *conn, void *hdr, size_t hdrlen)
+ 	/* Remember header pointer for later, when we need
+ 	 * to decide whether there's a payload to go along
+ 	 * with the header. */
+-	tcp_conn->out.hdr = hdr;
++	tcp_sw_conn->out.hdr = hdr;
+ 
+-	iscsi_segment_init_linear(&tcp_conn->out.segment, hdr, hdrlen,
+-				iscsi_tcp_send_hdr_done, NULL);
++	iscsi_segment_init_linear(&tcp_sw_conn->out.segment, hdr, hdrlen,
++				  iscsi_sw_tcp_send_hdr_done, NULL);
+ }
+ 
+ /*
+@@ -1215,11 +379,12 @@ iscsi_tcp_send_hdr_prep(struct iscsi_conn *conn, void *hdr, size_t hdrlen)
+  * of by the iscsi_segment routines.
+  */
+ static int
+-iscsi_tcp_send_data_prep(struct iscsi_conn *conn, struct scatterlist *sg,
+-			 unsigned int count, unsigned int offset,
+-			 unsigned int len)
++iscsi_sw_tcp_send_data_prep(struct iscsi_conn *conn, struct scatterlist *sg,
++			    unsigned int count, unsigned int offset,
++			    unsigned int len)
+ {
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
+ 	struct hash_desc *tx_hash = NULL;
+ 	unsigned int hdr_spec_len;
+ 
+@@ -1229,22 +394,23 @@ iscsi_tcp_send_data_prep(struct iscsi_conn *conn, struct scatterlist *sg,
+ 
+ 	/* Make sure the datalen matches what the caller
+ 	   said he would send. */
+-	hdr_spec_len = ntoh24(tcp_conn->out.hdr->dlength);
++	hdr_spec_len = ntoh24(tcp_sw_conn->out.hdr->dlength);
+ 	WARN_ON(iscsi_padded(len) != iscsi_padded(hdr_spec_len));
+ 
+ 	if (conn->datadgst_en)
+-		tx_hash = &tcp_conn->tx_hash;
++		tx_hash = &tcp_sw_conn->tx_hash;
+ 
+-	return iscsi_segment_seek_sg(&tcp_conn->out.data_segment,
+-				   sg, count, offset, len,
+-				   NULL, tx_hash);
++	return iscsi_segment_seek_sg(&tcp_sw_conn->out.data_segment,
++				     sg, count, offset, len,
++				     NULL, tx_hash);
+ }
+ 
+ static void
+-iscsi_tcp_send_linear_data_prepare(struct iscsi_conn *conn, void *data,
++iscsi_sw_tcp_send_linear_data_prep(struct iscsi_conn *conn, void *data,
+ 				   size_t len)
+ {
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
+ 	struct hash_desc *tx_hash = NULL;
+ 	unsigned int hdr_spec_len;
+ 
+@@ -1253,34 +419,35 @@ iscsi_tcp_send_linear_data_prepare(struct iscsi_conn *conn, void *data,
+ 
+ 	/* Make sure the datalen matches what the caller
+ 	   said he would send. */
+-	hdr_spec_len = ntoh24(tcp_conn->out.hdr->dlength);
++	hdr_spec_len = ntoh24(tcp_sw_conn->out.hdr->dlength);
+ 	WARN_ON(iscsi_padded(len) != iscsi_padded(hdr_spec_len));
+ 
+ 	if (conn->datadgst_en)
+-		tx_hash = &tcp_conn->tx_hash;
++		tx_hash = &tcp_sw_conn->tx_hash;
+ 
+-	iscsi_segment_init_linear(&tcp_conn->out.data_segment,
++	iscsi_segment_init_linear(&tcp_sw_conn->out.data_segment,
+ 				data, len, NULL, tx_hash);
+ }
+ 
+-static int iscsi_tcp_pdu_init(struct iscsi_task *task,
+-			      unsigned int offset, unsigned int count)
++static int iscsi_sw_tcp_pdu_init(struct iscsi_task *task,
++				 unsigned int offset, unsigned int count)
+ {
+ 	struct iscsi_conn *conn = task->conn;
+ 	int err = 0;
+ 
+-	iscsi_tcp_send_hdr_prep(conn, task->hdr, task->hdr_len);
++	iscsi_sw_tcp_send_hdr_prep(conn, task->hdr, task->hdr_len);
+ 
+ 	if (!count)
+ 		return 0;
+ 
+ 	if (!task->sc)
+-		iscsi_tcp_send_linear_data_prepare(conn, task->data, count);
++		iscsi_sw_tcp_send_linear_data_prep(conn, task->data, count);
+ 	else {
+ 		struct scsi_data_buffer *sdb = scsi_out(task->sc);
+ 
+-		err = iscsi_tcp_send_data_prep(conn, sdb->table.sgl,
+-					       sdb->table.nents, offset, count);
++		err = iscsi_sw_tcp_send_data_prep(conn, sdb->table.sgl,
++						  sdb->table.nents, offset,
++						  count);
+ 	}
+ 
+ 	if (err) {
+@@ -1290,251 +457,122 @@ static int iscsi_tcp_pdu_init(struct iscsi_task *task,
+ 	return 0;
+ }
+ 
+-static int iscsi_tcp_pdu_alloc(struct iscsi_task *task)
+-{
+-	struct iscsi_tcp_task *tcp_task = task->dd_data;
+-
+-	task->hdr = &tcp_task->hdr.hdrbuf;
+-	task->hdr_max = sizeof(tcp_task->hdr) - ISCSI_DIGEST_SIZE;
+-	return 0;
+-}
+-
+-/**
+- * iscsi_tcp_task - Initialize iSCSI SCSI_READ or SCSI_WRITE commands
+- * @conn: iscsi connection
+- * @task: scsi command task
+- * @sc: scsi command
+- **/
+-static int iscsi_tcp_task_init(struct iscsi_task *task)
++static int iscsi_sw_tcp_pdu_alloc(struct iscsi_task *task)
+ {
+ 	struct iscsi_tcp_task *tcp_task = task->dd_data;
+-	struct iscsi_conn *conn = task->conn;
+-	struct scsi_cmnd *sc = task->sc;
+-	int err;
+ 
+-	if (!sc) {
+-		/*
+-		 * mgmt tasks do not have a scatterlist since they come
+-		 * in from the iscsi interface.
+-		 */
+-		debug_scsi("mtask deq [cid %d itt 0x%x]\n", conn->id,
+-			   task->itt);
+-
+-		return conn->session->tt->init_pdu(task, 0, task->data_count);
+-	}
+-
+-	BUG_ON(__kfifo_len(tcp_task->r2tqueue));
+-	tcp_task->exp_datasn = 0;
+-
+-	/* Prepare PDU, optionally w/ immediate data */
+-	debug_scsi("task deq [cid %d itt 0x%x imm %d unsol %d]\n",
+-		    conn->id, task->itt, task->imm_count,
+-		    task->unsol_r2t.data_length);
+-
+-	err = conn->session->tt->init_pdu(task, 0, task->imm_count);
+-	if (err)
+-		return err;
+-	task->imm_count = 0;
++	task->hdr = task->dd_data + sizeof(*tcp_task);
++	task->hdr_max = sizeof(struct iscsi_sw_tcp_hdrbuf) - ISCSI_DIGEST_SIZE;
+ 	return 0;
+ }
+ 
+-static struct iscsi_r2t_info *iscsi_tcp_get_curr_r2t(struct iscsi_task *task)
+-{
+-	struct iscsi_session *session = task->conn->session;
+-	struct iscsi_tcp_task *tcp_task = task->dd_data;
+-	struct iscsi_r2t_info *r2t = NULL;
+-
+-	if (iscsi_task_has_unsol_data(task))
+-		r2t = &task->unsol_r2t;
+-	else {
+-		spin_lock_bh(&session->lock);
+-		if (tcp_task->r2t) {
+-			r2t = tcp_task->r2t;
+-			/* Continue with this R2T? */
+-			if (r2t->data_length <= r2t->sent) {
+-				debug_scsi("  done with r2t %p\n", r2t);
+-				__kfifo_put(tcp_task->r2tpool.queue,
+-					    (void *)&tcp_task->r2t,
+-					    sizeof(void *));
+-				tcp_task->r2t = r2t = NULL;
+-			}
+-		}
+-
+-		if (r2t == NULL) {
+-			__kfifo_get(tcp_task->r2tqueue,
+-				    (void *)&tcp_task->r2t, sizeof(void *));
+-			r2t = tcp_task->r2t;
+-		}
+-		spin_unlock_bh(&session->lock);
+-	}
+-
+-	return r2t;
+-}
+-
+-/*
+- * iscsi_tcp_task_xmit - xmit normal PDU task
+- * @task: iscsi command task
+- *
+- * We're expected to return 0 when everything was transmitted succesfully,
+- * -EAGAIN if there's still data in the queue, or != 0 for any other kind
+- * of error.
+- */
+-static int iscsi_tcp_task_xmit(struct iscsi_task *task)
+-{
+-	struct iscsi_conn *conn = task->conn;
+-	struct iscsi_session *session = conn->session;
+-	struct iscsi_r2t_info *r2t;
+-	int rc = 0;
+-
+-flush:
+-	/* Flush any pending data first. */
+-	rc = session->tt->xmit_pdu(task);
+-	if (rc < 0)
+-		return rc;
+-
+-	/* mgmt command */
+-	if (!task->sc) {
+-		if (task->hdr->itt == RESERVED_ITT)
+-			iscsi_put_task(task);
+-		return 0;
+-	}
+-
+-	/* Are we done already? */
+-	if (task->sc->sc_data_direction != DMA_TO_DEVICE)
+-		return 0;
+-
+-	r2t = iscsi_tcp_get_curr_r2t(task);
+-	if (r2t == NULL) {
+-		/* Waiting for more R2Ts to arrive. */
+-		debug_tcp("no R2Ts yet\n");
+-		return 0;
+-	}
+-
+-	rc = conn->session->tt->alloc_pdu(task);
+-	if (rc)
+-		return rc;
+-	iscsi_prep_data_out_pdu(task, r2t, (struct iscsi_data *) task->hdr);
+-
+-	debug_scsi("sol dout %p [dsn %d itt 0x%x doff %d dlen %d]\n",
+-		   r2t, r2t->datasn - 1, task->hdr->itt,
+-		   r2t->data_offset + r2t->sent, r2t->data_count);
+-
+-	rc = conn->session->tt->init_pdu(task, r2t->data_offset + r2t->sent,
+-					 r2t->data_count);
+-	if (rc)
+-		return rc;
+-	r2t->sent += r2t->data_count;
+-	goto flush;
+-}
+-
+ static struct iscsi_cls_conn *
+-iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
++iscsi_sw_tcp_conn_create(struct iscsi_cls_session *cls_session,
++			 uint32_t conn_idx)
+ {
+ 	struct iscsi_conn *conn;
+ 	struct iscsi_cls_conn *cls_conn;
+ 	struct iscsi_tcp_conn *tcp_conn;
++	struct iscsi_sw_tcp_conn *tcp_sw_conn;
+ 
+-	cls_conn = iscsi_conn_setup(cls_session, sizeof(*tcp_conn), conn_idx);
++	cls_conn = iscsi_tcp_conn_setup(cls_session, sizeof(*tcp_sw_conn),
++					conn_idx);
+ 	if (!cls_conn)
+ 		return NULL;
+ 	conn = cls_conn->dd_data;
+-	/*
+-	 * due to strange issues with iser these are not set
+-	 * in iscsi_conn_setup
+-	 */
+-	conn->max_recv_dlength = ISCSI_DEF_MAX_RECV_SEG_LEN;
+-
+ 	tcp_conn = conn->dd_data;
+-	tcp_conn->iscsi_conn = conn;
++	tcp_sw_conn = tcp_conn->dd_data;
+ 
+-	tcp_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0,
+-						  CRYPTO_ALG_ASYNC);
+-	tcp_conn->tx_hash.flags = 0;
+-	if (IS_ERR(tcp_conn->tx_hash.tfm))
++	tcp_sw_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0,
++						     CRYPTO_ALG_ASYNC);
++	tcp_sw_conn->tx_hash.flags = 0;
++	if (IS_ERR(tcp_sw_conn->tx_hash.tfm))
+ 		goto free_conn;
+ 
+-	tcp_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0,
+-						  CRYPTO_ALG_ASYNC);
+-	tcp_conn->rx_hash.flags = 0;
+-	if (IS_ERR(tcp_conn->rx_hash.tfm))
++	tcp_sw_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0,
++						     CRYPTO_ALG_ASYNC);
++	tcp_sw_conn->rx_hash.flags = 0;
++	if (IS_ERR(tcp_sw_conn->rx_hash.tfm))
+ 		goto free_tx_tfm;
++	tcp_conn->rx_hash = &tcp_sw_conn->rx_hash;
+ 
+ 	return cls_conn;
+ 
+ free_tx_tfm:
+-	crypto_free_hash(tcp_conn->tx_hash.tfm);
++	crypto_free_hash(tcp_sw_conn->tx_hash.tfm);
+ free_conn:
+ 	iscsi_conn_printk(KERN_ERR, conn,
+ 			  "Could not create connection due to crc32c "
+ 			  "loading error. Make sure the crc32c "
+ 			  "module is built as a module or into the "
+ 			  "kernel\n");
+-	iscsi_conn_teardown(cls_conn);
++	iscsi_tcp_conn_teardown(cls_conn);
+ 	return NULL;
+ }
+ 
+-static void
+-iscsi_tcp_release_conn(struct iscsi_conn *conn)
++static void iscsi_sw_tcp_release_conn(struct iscsi_conn *conn)
+ {
+ 	struct iscsi_session *session = conn->session;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+-	struct socket *sock = tcp_conn->sock;
++	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
++	struct socket *sock = tcp_sw_conn->sock;
+ 
+ 	if (!sock)
+ 		return;
+ 
+ 	sock_hold(sock->sk);
+-	iscsi_conn_restore_callbacks(tcp_conn);
++	iscsi_sw_tcp_conn_restore_callbacks(tcp_sw_conn);
+ 	sock_put(sock->sk);
+ 
+ 	spin_lock_bh(&session->lock);
+-	tcp_conn->sock = NULL;
++	tcp_sw_conn->sock = NULL;
+ 	spin_unlock_bh(&session->lock);
+ 	sockfd_put(sock);
+ }
+ 
+-static void
+-iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn)
++static void iscsi_sw_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn)
+ {
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
+ 
+-	iscsi_tcp_release_conn(conn);
++	iscsi_sw_tcp_release_conn(conn);
+ 
+-	if (tcp_conn->tx_hash.tfm)
+-		crypto_free_hash(tcp_conn->tx_hash.tfm);
+-	if (tcp_conn->rx_hash.tfm)
+-		crypto_free_hash(tcp_conn->rx_hash.tfm);
++	if (tcp_sw_conn->tx_hash.tfm)
++		crypto_free_hash(tcp_sw_conn->tx_hash.tfm);
++	if (tcp_sw_conn->rx_hash.tfm)
++		crypto_free_hash(tcp_sw_conn->rx_hash.tfm);
+ 
+-	iscsi_conn_teardown(cls_conn);
++	iscsi_tcp_conn_teardown(cls_conn);
+ }
+ 
+-static void
+-iscsi_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
++static void iscsi_sw_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+ {
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
+ 
+ 	/* userspace may have goofed up and not bound us */
+-	if (!tcp_conn->sock)
++	if (!tcp_sw_conn->sock)
+ 		return;
+ 	/*
+ 	 * Make sure our recv side is stopped.
+ 	 * Older tools called conn stop before ep_disconnect
+ 	 * so IO could still be coming in.
+ 	 */
+-	write_lock_bh(&tcp_conn->sock->sk->sk_callback_lock);
++	write_lock_bh(&tcp_sw_conn->sock->sk->sk_callback_lock);
+ 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
+-	write_unlock_bh(&tcp_conn->sock->sk->sk_callback_lock);
++	write_unlock_bh(&tcp_sw_conn->sock->sk->sk_callback_lock);
+ 
+ 	iscsi_conn_stop(cls_conn, flag);
+-	iscsi_tcp_release_conn(conn);
++	iscsi_sw_tcp_release_conn(conn);
+ }
+ 
+-static int iscsi_tcp_get_addr(struct iscsi_conn *conn, struct socket *sock,
+-			      char *buf, int *port,
+-			      int (*getname)(struct socket *, struct sockaddr *,
+-					int *addrlen))
++static int iscsi_sw_tcp_get_addr(struct iscsi_conn *conn, struct socket *sock,
++				 char *buf, int *port,
++				 int (*getname)(struct socket *,
++						struct sockaddr *,
++						int *addrlen))
+ {
+ 	struct sockaddr_storage *addr;
+ 	struct sockaddr_in6 *sin6;
+@@ -1572,14 +610,15 @@ static int iscsi_tcp_get_addr(struct iscsi_conn *conn, struct socket *sock,
+ }
+ 
+ static int
+-iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
+-		    struct iscsi_cls_conn *cls_conn, uint64_t transport_eph,
+-		    int is_leading)
++iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session,
++		       struct iscsi_cls_conn *cls_conn, uint64_t transport_eph,
++		       int is_leading)
+ {
+ 	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+ 	struct iscsi_host *ihost = shost_priv(shost);
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
+ 	struct sock *sk;
+ 	struct socket *sock;
+ 	int err;
+@@ -1596,13 +635,13 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
+ 	 * userspace may still want to query the values since we will
+ 	 * be using them for the reconnect
+ 	 */
+-	err = iscsi_tcp_get_addr(conn, sock, conn->portal_address,
+-				 &conn->portal_port, kernel_getpeername);
++	err = iscsi_sw_tcp_get_addr(conn, sock, conn->portal_address,
++				    &conn->portal_port, kernel_getpeername);
+ 	if (err)
+ 		goto free_socket;
+ 
+-	err = iscsi_tcp_get_addr(conn, sock, ihost->local_address,
+-				&ihost->local_port, kernel_getsockname);
++	err = iscsi_sw_tcp_get_addr(conn, sock, ihost->local_address,
++				    &ihost->local_port, kernel_getsockname);
+ 	if (err)
+ 		goto free_socket;
+ 
+@@ -1611,7 +650,7 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
+ 		goto free_socket;
+ 
+ 	/* bind iSCSI connection and socket */
+-	tcp_conn->sock = sock;
++	tcp_sw_conn->sock = sock;
+ 
+ 	/* setup Socket parameters */
+ 	sk = sock->sk;
+@@ -1619,8 +658,8 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
+ 	sk->sk_sndtimeo = 15 * HZ; /* FIXME: make it configurable */
+ 	sk->sk_allocation = GFP_ATOMIC;
+ 
+-	iscsi_tcp_conn_set_callbacks(conn);
+-	tcp_conn->sendpage = tcp_conn->sock->ops->sendpage;
++	iscsi_sw_tcp_conn_set_callbacks(conn);
++	tcp_sw_conn->sendpage = tcp_sw_conn->sock->ops->sendpage;
+ 	/*
+ 	 * set receive state machine into initial state
+ 	 */
+@@ -1632,75 +671,14 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
+ 	return err;
+ }
+ 
+-static int
+-iscsi_r2tpool_alloc(struct iscsi_session *session)
+-{
+-	int i;
+-	int cmd_i;
+-
+-	/*
+-	 * initialize per-task: R2T pool and xmit queue
+-	 */
+-	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
+-	        struct iscsi_task *task = session->cmds[cmd_i];
+-		struct iscsi_tcp_task *tcp_task = task->dd_data;
+-
+-		/*
+-		 * pre-allocated x2 as much r2ts to handle race when
+-		 * target acks DataOut faster than we data_xmit() queues
+-		 * could replenish r2tqueue.
+-		 */
+-
+-		/* R2T pool */
+-		if (iscsi_pool_init(&tcp_task->r2tpool,
+-				    session->max_r2t * 2, NULL,
+-				    sizeof(struct iscsi_r2t_info))) {
+-			goto r2t_alloc_fail;
+-		}
+-
+-		/* R2T xmit queue */
+-		tcp_task->r2tqueue = kfifo_alloc(
+-		      session->max_r2t * 4 * sizeof(void*), GFP_KERNEL, NULL);
+-		if (tcp_task->r2tqueue == ERR_PTR(-ENOMEM)) {
+-			iscsi_pool_free(&tcp_task->r2tpool);
+-			goto r2t_alloc_fail;
+-		}
+-	}
+-
+-	return 0;
+-
+-r2t_alloc_fail:
+-	for (i = 0; i < cmd_i; i++) {
+-		struct iscsi_task *task = session->cmds[i];
+-		struct iscsi_tcp_task *tcp_task = task->dd_data;
+-
+-		kfifo_free(tcp_task->r2tqueue);
+-		iscsi_pool_free(&tcp_task->r2tpool);
+-	}
+-	return -ENOMEM;
+-}
+-
+-static void
+-iscsi_r2tpool_free(struct iscsi_session *session)
+-{
+-	int i;
+-
+-	for (i = 0; i < session->cmds_max; i++) {
+-		struct iscsi_task *task = session->cmds[i];
+-		struct iscsi_tcp_task *tcp_task = task->dd_data;
+-
+-		kfifo_free(tcp_task->r2tqueue);
+-		iscsi_pool_free(&tcp_task->r2tpool);
+-	}
+-}
+-
+-static int
+-iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
+-		     char *buf, int buflen)
++static int iscsi_sw_tcp_conn_set_param(struct iscsi_cls_conn *cls_conn,
++				       enum iscsi_param param, char *buf,
++				       int buflen)
+ {
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	struct iscsi_session *session = conn->session;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
+ 	int value;
+ 
+ 	switch(param) {
+@@ -1709,8 +687,8 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
+ 		break;
+ 	case ISCSI_PARAM_DATADGST_EN:
+ 		iscsi_set_param(cls_conn, param, buf, buflen);
+-		tcp_conn->sendpage = conn->datadgst_en ?
+-			sock_no_sendpage : tcp_conn->sock->ops->sendpage;
++		tcp_sw_conn->sendpage = conn->datadgst_en ?
++			sock_no_sendpage : tcp_sw_conn->sock->ops->sendpage;
+ 		break;
+ 	case ISCSI_PARAM_MAX_R2T:
+ 		sscanf(buf, "%d", &value);
+@@ -1718,9 +696,9 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
+ 			return -EINVAL;
+ 		if (session->max_r2t == value)
+ 			break;
+-		iscsi_r2tpool_free(session);
++		iscsi_tcp_r2tpool_free(session);
+ 		iscsi_set_param(cls_conn, param, buf, buflen);
+-		if (iscsi_r2tpool_alloc(session))
++		if (iscsi_tcp_r2tpool_alloc(session))
+ 			return -ENOMEM;
+ 		break;
+ 	default:
+@@ -1730,9 +708,8 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
+ 	return 0;
+ }
+ 
+-static int
+-iscsi_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,
+-			 enum iscsi_param param, char *buf)
++static int iscsi_sw_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,
++				       enum iscsi_param param, char *buf)
+ {
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	int len;
+@@ -1756,33 +733,28 @@ iscsi_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ }
+ 
+ static void
+-iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats)
++iscsi_sw_tcp_conn_get_stats(struct iscsi_cls_conn *cls_conn,
++			    struct iscsi_stats *stats)
+ {
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
+ 
+-	stats->txdata_octets = conn->txdata_octets;
+-	stats->rxdata_octets = conn->rxdata_octets;
+-	stats->scsicmd_pdus = conn->scsicmd_pdus_cnt;
+-	stats->dataout_pdus = conn->dataout_pdus_cnt;
+-	stats->scsirsp_pdus = conn->scsirsp_pdus_cnt;
+-	stats->datain_pdus = conn->datain_pdus_cnt;
+-	stats->r2t_pdus = conn->r2t_pdus_cnt;
+-	stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
+-	stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
+ 	stats->custom_length = 3;
+ 	strcpy(stats->custom[0].desc, "tx_sendpage_failures");
+-	stats->custom[0].value = tcp_conn->sendpage_failures_cnt;
++	stats->custom[0].value = tcp_sw_conn->sendpage_failures_cnt;
+ 	strcpy(stats->custom[1].desc, "rx_discontiguous_hdr");
+-	stats->custom[1].value = tcp_conn->discontiguous_hdr_cnt;
++	stats->custom[1].value = tcp_sw_conn->discontiguous_hdr_cnt;
+ 	strcpy(stats->custom[2].desc, "eh_abort_cnt");
+ 	stats->custom[2].value = conn->eh_abort_cnt;
++
++	iscsi_tcp_conn_get_stats(cls_conn, stats);
+ }
+ 
+ static struct iscsi_cls_session *
+-iscsi_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
+-			 uint16_t qdepth, uint32_t initial_cmdsn,
+-			 uint32_t *hostno)
++iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
++			    uint16_t qdepth, uint32_t initial_cmdsn,
++			    uint32_t *hostno)
+ {
+ 	struct iscsi_cls_session *cls_session;
+ 	struct iscsi_session *session;
+@@ -1793,10 +765,10 @@ iscsi_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
+ 		return NULL;
+ 	}
+ 
+-	shost = iscsi_host_alloc(&iscsi_sht, 0, qdepth);
++	shost = iscsi_host_alloc(&iscsi_sw_tcp_sht, 0, qdepth);
+ 	if (!shost)
+ 		return NULL;
+-	shost->transportt = iscsi_tcp_scsi_transport;
++	shost->transportt = iscsi_sw_tcp_scsi_transport;
+ 	shost->max_lun = iscsi_max_lun;
+ 	shost->max_id = 0;
+ 	shost->max_channel = 0;
+@@ -1806,15 +778,17 @@ iscsi_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
+ 		goto free_host;
+ 	*hostno = shost->host_no;
+ 
+-	cls_session = iscsi_session_setup(&iscsi_tcp_transport, shost, cmds_max,
+-					  sizeof(struct iscsi_tcp_task),
++	cls_session = iscsi_session_setup(&iscsi_sw_tcp_transport, shost,
++					  cmds_max,
++					  sizeof(struct iscsi_tcp_task) +
++					  sizeof(struct iscsi_sw_tcp_hdrbuf),
+ 					  initial_cmdsn, 0);
+ 	if (!cls_session)
+ 		goto remove_host;
+ 	session = cls_session->dd_data;
+ 
+ 	shost->can_queue = session->scsi_cmds_max;
+-	if (iscsi_r2tpool_alloc(session))
++	if (iscsi_tcp_r2tpool_alloc(session))
+ 		goto remove_session;
+ 	return cls_session;
+ 
+@@ -1827,25 +801,25 @@ iscsi_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
+ 	return NULL;
+ }
+ 
+-static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session)
++static void iscsi_sw_tcp_session_destroy(struct iscsi_cls_session *cls_session)
+ {
+ 	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+ 
+-	iscsi_r2tpool_free(cls_session->dd_data);
++	iscsi_tcp_r2tpool_free(cls_session->dd_data);
+ 	iscsi_session_teardown(cls_session);
+ 
+ 	iscsi_host_remove(shost);
+ 	iscsi_host_free(shost);
+ }
+ 
+-static int iscsi_tcp_slave_configure(struct scsi_device *sdev)
++static int iscsi_sw_tcp_slave_configure(struct scsi_device *sdev)
+ {
+ 	blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_ANY);
+ 	blk_queue_dma_alignment(sdev->request_queue, 0);
+ 	return 0;
+ }
+ 
+-static struct scsi_host_template iscsi_sht = {
++static struct scsi_host_template iscsi_sw_tcp_sht = {
+ 	.module			= THIS_MODULE,
+ 	.name			= "iSCSI Initiator over TCP/IP",
+ 	.queuecommand           = iscsi_queuecommand,
+@@ -1858,12 +832,12 @@ static struct scsi_host_template iscsi_sht = {
+ 	.eh_device_reset_handler= iscsi_eh_device_reset,
+ 	.eh_target_reset_handler= iscsi_eh_target_reset,
+ 	.use_clustering         = DISABLE_CLUSTERING,
+-	.slave_configure        = iscsi_tcp_slave_configure,
++	.slave_configure        = iscsi_sw_tcp_slave_configure,
+ 	.proc_name		= "iscsi_tcp",
+ 	.this_id		= -1,
+ };
+ 
+-static struct iscsi_transport iscsi_tcp_transport = {
++static struct iscsi_transport iscsi_sw_tcp_transport = {
+ 	.owner			= THIS_MODULE,
+ 	.name			= "tcp",
+ 	.caps			= CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST
+@@ -1896,37 +870,36 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 				  ISCSI_HOST_INITIATOR_NAME |
+ 				  ISCSI_HOST_NETDEV_NAME,
+ 	/* session management */
+-	.create_session		= iscsi_tcp_session_create,
+-	.destroy_session	= iscsi_tcp_session_destroy,
++	.create_session		= iscsi_sw_tcp_session_create,
++	.destroy_session	= iscsi_sw_tcp_session_destroy,
+ 	/* connection management */
+-	.create_conn		= iscsi_tcp_conn_create,
+-	.bind_conn		= iscsi_tcp_conn_bind,
+-	.destroy_conn		= iscsi_tcp_conn_destroy,
+-	.set_param		= iscsi_conn_set_param,
+-	.get_conn_param		= iscsi_tcp_conn_get_param,
++	.create_conn		= iscsi_sw_tcp_conn_create,
++	.bind_conn		= iscsi_sw_tcp_conn_bind,
++	.destroy_conn		= iscsi_sw_tcp_conn_destroy,
++	.set_param		= iscsi_sw_tcp_conn_set_param,
++	.get_conn_param		= iscsi_sw_tcp_conn_get_param,
+ 	.get_session_param	= iscsi_session_get_param,
+ 	.start_conn		= iscsi_conn_start,
+-	.stop_conn		= iscsi_tcp_conn_stop,
++	.stop_conn		= iscsi_sw_tcp_conn_stop,
+ 	/* iscsi host params */
+ 	.get_host_param		= iscsi_host_get_param,
+ 	.set_host_param		= iscsi_host_set_param,
+ 	/* IO */
+ 	.send_pdu		= iscsi_conn_send_pdu,
+-	.get_stats		= iscsi_conn_get_stats,
++	.get_stats		= iscsi_sw_tcp_conn_get_stats,
+ 	/* iscsi task/cmd helpers */
+ 	.init_task		= iscsi_tcp_task_init,
+ 	.xmit_task		= iscsi_tcp_task_xmit,
+ 	.cleanup_task		= iscsi_tcp_cleanup_task,
+ 	/* low level pdu helpers */
+-	.xmit_pdu		= iscsi_tcp_flush,
+-	.init_pdu		= iscsi_tcp_pdu_init,
+-	.alloc_pdu		= iscsi_tcp_pdu_alloc,
++	.xmit_pdu		= iscsi_sw_tcp_pdu_xmit,
++	.init_pdu		= iscsi_sw_tcp_pdu_init,
++	.alloc_pdu		= iscsi_sw_tcp_pdu_alloc,
+ 	/* recovery */
+ 	.session_recovery_timedout = iscsi_session_recovery_timedout,
+ };
+ 
+-static int __init
+-iscsi_tcp_init(void)
++static int __init iscsi_sw_tcp_init(void)
+ {
+ 	if (iscsi_max_lun < 1) {
+ 		printk(KERN_ERR "iscsi_tcp: Invalid max_lun value of %u\n",
+@@ -1934,19 +907,18 @@ iscsi_tcp_init(void)
+ 		return -EINVAL;
+ 	}
+ 
+-	iscsi_tcp_scsi_transport = iscsi_register_transport(
+-							&iscsi_tcp_transport);
+-	if (!iscsi_tcp_scsi_transport)
++	iscsi_sw_tcp_scsi_transport = iscsi_register_transport(
++						&iscsi_sw_tcp_transport);
++	if (!iscsi_sw_tcp_scsi_transport)
+ 		return -ENODEV;
+ 
+ 	return 0;
+ }
+ 
+-static void __exit
+-iscsi_tcp_exit(void)
++static void __exit iscsi_sw_tcp_exit(void)
+ {
+-	iscsi_unregister_transport(&iscsi_tcp_transport);
++	iscsi_unregister_transport(&iscsi_sw_tcp_transport);
+ }
+ 
+-module_init(iscsi_tcp_init);
+-module_exit(iscsi_tcp_exit);
++module_init(iscsi_sw_tcp_init);
++module_exit(iscsi_sw_tcp_exit);
+diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
+index 0ed47733c75f..ca6b7bc64de0 100644
+--- a/drivers/scsi/iscsi_tcp.h
++++ b/drivers/scsi/iscsi_tcp.h
+@@ -19,67 +19,27 @@
+  * See the file COPYING included with this distribution for more details.
+  */
+ 
+-#ifndef ISCSI_TCP_H
+-#define ISCSI_TCP_H
++#ifndef ISCSI_SW_TCP_H
++#define ISCSI_SW_TCP_H
+ 
+ #include 
++#include 
+ 
+-struct crypto_hash;
+ struct socket;
+ struct iscsi_tcp_conn;
+-struct iscsi_segment;
+-
+-typedef int iscsi_segment_done_fn_t(struct iscsi_tcp_conn *,
+-				    struct iscsi_segment *);
+-
+-struct iscsi_segment {
+-	unsigned char		*data;
+-	unsigned int		size;
+-	unsigned int		copied;
+-	unsigned int		total_size;
+-	unsigned int		total_copied;
+-
+-	struct hash_desc	*hash;
+-	unsigned char		recv_digest[ISCSI_DIGEST_SIZE];
+-	unsigned char		digest[ISCSI_DIGEST_SIZE];
+-	unsigned int		digest_len;
+-
+-	struct scatterlist	*sg;
+-	void			*sg_mapped;
+-	unsigned int		sg_offset;
+-
+-	iscsi_segment_done_fn_t	*done;
+-};
+-
+-/* Socket connection recieve helper */
+-struct iscsi_tcp_recv {
+-	struct iscsi_hdr	*hdr;
+-	struct iscsi_segment	segment;
+-
+-	/* Allocate buffer for BHS + AHS */
+-	uint32_t		hdr_buf[64];
+-
+-	/* copied and flipped values */
+-	int			datalen;
+-};
+ 
+ /* Socket connection send helper */
+-struct iscsi_tcp_send {
++struct iscsi_sw_tcp_send {
+ 	struct iscsi_hdr	*hdr;
+ 	struct iscsi_segment	segment;
+ 	struct iscsi_segment	data_segment;
+ };
+ 
+-struct iscsi_tcp_conn {
++struct iscsi_sw_tcp_conn {
+ 	struct iscsi_conn	*iscsi_conn;
+ 	struct socket		*sock;
+-	int			stop_stage;	/* conn_stop() flag: *
+-						 * stop to recover,  *
+-						 * stop to terminate */
+-	/* control data */
+-	struct iscsi_tcp_recv	in;		/* TCP receive context */
+-	struct iscsi_tcp_send	out;		/* TCP send context */
+ 
++	struct iscsi_sw_tcp_send out;
+ 	/* old values for socket callbacks */
+ 	void			(*old_data_ready)(struct sock *, int);
+ 	void			(*old_state_change)(struct sock *);
+@@ -93,24 +53,13 @@ struct iscsi_tcp_conn {
+ 	uint32_t		sendpage_failures_cnt;
+ 	uint32_t		discontiguous_hdr_cnt;
+ 
+-	int			error;
+-
+ 	ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
+ };
+ 
+-struct iscsi_tcp_task {
+-	struct iscsi_hdr_buff {
+-		struct iscsi_hdr	hdrbuf;
+-		char			hdrextbuf[ISCSI_MAX_AHS_SIZE +
++struct iscsi_sw_tcp_hdrbuf {
++	struct iscsi_hdr	hdrbuf;
++	char			hdrextbuf[ISCSI_MAX_AHS_SIZE +
+ 		                                  ISCSI_DIGEST_SIZE];
+-	} hdr;
+-
+-	int			sent;
+-	uint32_t		exp_datasn;	/* expected target's R2TSN/DataSN */
+-	int			data_offset;
+-	struct iscsi_r2t_info	*r2t;		/* in progress solict R2T */
+-	struct iscsi_pool	r2tpool;
+-	struct kfifo		*r2tqueue;
+ };
+ 
+-#endif /* ISCSI_H */
++#endif /* ISCSI_SW_TCP_H */

commit a081c13e39b5c17052a7b46fafa61019c4c110ff
+Author: Mike Christie 
+Date:   Tue Dec 2 00:32:11 2008 -0600
+
+    [SCSI] iscsi_tcp: split module into lib and lld
+    
+    As explained in the previous mails, cxgb3i needs iscsi_tcp's
+    r2t/data_out and data_in procesing so this just moves functions
+    that both drivers want to use to a new module libiscsi_tcp. The
+    next patch will hook iscsi_tcp in.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
+new file mode 100644
+index 000000000000..e86508936314
+--- /dev/null
++++ b/drivers/scsi/libiscsi_tcp.c
+@@ -0,0 +1,1160 @@
++/*
++ * iSCSI over TCP/IP Data-Path lib
++ *
++ * Copyright (C) 2004 Dmitry Yusupov
++ * Copyright (C) 2004 Alex Aizman
++ * Copyright (C) 2005 - 2006 Mike Christie
++ * Copyright (C) 2006 Red Hat, Inc.  All rights reserved.
++ * maintained by open-iscsi@googlegroups.com
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published
++ * by the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * See the file COPYING included with this distribution for more details.
++ *
++ * Credits:
++ *	Christoph Hellwig
++ *	FUJITA Tomonori
++ *	Arne Redlich
++ *	Zhenyu Wang
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include "iscsi_tcp.h"
++
++MODULE_AUTHOR("Mike Christie , "
++	      "Dmitry Yusupov , "
++	      "Alex Aizman ");
++MODULE_DESCRIPTION("iSCSI/TCP data-path");
++MODULE_LICENSE("GPL");
++#undef DEBUG_TCP
++
++#ifdef DEBUG_TCP
++#define debug_tcp(fmt...) printk(KERN_INFO "tcp: " fmt)
++#else
++#define debug_tcp(fmt...)
++#endif
++
++static int iscsi_tcp_hdr_recv_done(struct iscsi_tcp_conn *tcp_conn,
++				   struct iscsi_segment *segment);
++
++/*
++ * Scatterlist handling: inside the iscsi_segment, we
++ * remember an index into the scatterlist, and set data/size
++ * to the current scatterlist entry. For highmem pages, we
++ * kmap as needed.
++ *
++ * Note that the page is unmapped when we return from
++ * TCP's data_ready handler, so we may end up mapping and
++ * unmapping the same page repeatedly. The whole reason
++ * for this is that we shouldn't keep the page mapped
++ * outside the softirq.
++ */
++
++/**
++ * iscsi_tcp_segment_init_sg - init indicated scatterlist entry
++ * @segment: the buffer object
++ * @sg: scatterlist
++ * @offset: byte offset into that sg entry
++ *
++ * This function sets up the segment so that subsequent
++ * data is copied to the indicated sg entry, at the given
++ * offset.
++ */
++static inline void
++iscsi_tcp_segment_init_sg(struct iscsi_segment *segment,
++			  struct scatterlist *sg, unsigned int offset)
++{
++	segment->sg = sg;
++	segment->sg_offset = offset;
++	segment->size = min(sg->length - offset,
++			    segment->total_size - segment->total_copied);
++	segment->data = NULL;
++}
++
++/**
++ * iscsi_tcp_segment_map - map the current S/G page
++ * @segment: iscsi_segment
++ * @recv: 1 if called from recv path
++ *
++ * We only need to possibly kmap data if scatter lists are being used,
++ * because the iscsi passthrough and internal IO paths will never use high
++ * mem pages.
++ */
++static void iscsi_tcp_segment_map(struct iscsi_segment *segment, int recv)
++{
++	struct scatterlist *sg;
++
++	if (segment->data != NULL || !segment->sg)
++		return;
++
++	sg = segment->sg;
++	BUG_ON(segment->sg_mapped);
++	BUG_ON(sg->length == 0);
++
++	/*
++	 * If the page count is greater than one it is ok to send
++	 * to the network layer's zero copy send path. If not we
++	 * have to go the slow sendmsg path. We always map for the
++	 * recv path.
++	 */
++	if (page_count(sg_page(sg)) >= 1 && !recv)
++		return;
++
++	debug_tcp("iscsi_tcp_segment_map %s %p\n", recv ? "recv" : "xmit",
++		  segment);
++	segment->sg_mapped = kmap_atomic(sg_page(sg), KM_SOFTIRQ0);
++	segment->data = segment->sg_mapped + sg->offset + segment->sg_offset;
++}
++
++void iscsi_tcp_segment_unmap(struct iscsi_segment *segment)
++{
++	debug_tcp("iscsi_tcp_segment_unmap %p\n", segment);
++
++	if (segment->sg_mapped) {
++		debug_tcp("iscsi_tcp_segment_unmap valid\n");
++		kunmap_atomic(segment->sg_mapped, KM_SOFTIRQ0);
++		segment->sg_mapped = NULL;
++		segment->data = NULL;
++	}
++}
++EXPORT_SYMBOL_GPL(iscsi_tcp_segment_unmap);
++
++/*
++ * Splice the digest buffer into the buffer
++ */
++static inline void
++iscsi_tcp_segment_splice_digest(struct iscsi_segment *segment, void *digest)
++{
++	segment->data = digest;
++	segment->digest_len = ISCSI_DIGEST_SIZE;
++	segment->total_size += ISCSI_DIGEST_SIZE;
++	segment->size = ISCSI_DIGEST_SIZE;
++	segment->copied = 0;
++	segment->sg = NULL;
++	segment->hash = NULL;
++}
++
++/**
++ * iscsi_tcp_segment_done - check whether the segment is complete
++ * @segment: iscsi segment to check
++ * @recv: set to one of this is called from the recv path
++ * @copied: number of bytes copied
++ *
++ * Check if we're done receiving this segment. If the receive
++ * buffer is full but we expect more data, move on to the
++ * next entry in the scatterlist.
++ *
++ * If the amount of data we received isn't a multiple of 4,
++ * we will transparently receive the pad bytes, too.
++ *
++ * This function must be re-entrant.
++ */
++int iscsi_tcp_segment_done(struct iscsi_segment *segment, int recv,
++			   unsigned copied)
++{
++	static unsigned char padbuf[ISCSI_PAD_LEN];
++	struct scatterlist sg;
++	unsigned int pad;
++
++	debug_tcp("copied %u %u size %u %s\n", segment->copied, copied,
++		  segment->size, recv ? "recv" : "xmit");
++	if (segment->hash && copied) {
++		/*
++		 * If a segment is kmapd we must unmap it before sending
++		 * to the crypto layer since that will try to kmap it again.
++		 */
++		iscsi_tcp_segment_unmap(segment);
++
++		if (!segment->data) {
++			sg_init_table(&sg, 1);
++			sg_set_page(&sg, sg_page(segment->sg), copied,
++				    segment->copied + segment->sg_offset +
++							segment->sg->offset);
++		} else
++			sg_init_one(&sg, segment->data + segment->copied,
++				    copied);
++		crypto_hash_update(segment->hash, &sg, copied);
++	}
++
++	segment->copied += copied;
++	if (segment->copied < segment->size) {
++		iscsi_tcp_segment_map(segment, recv);
++		return 0;
++	}
++
++	segment->total_copied += segment->copied;
++	segment->copied = 0;
++	segment->size = 0;
++
++	/* Unmap the current scatterlist page, if there is one. */
++	iscsi_tcp_segment_unmap(segment);
++
++	/* Do we have more scatterlist entries? */
++	debug_tcp("total copied %u total size %u\n", segment->total_copied,
++		   segment->total_size);
++	if (segment->total_copied < segment->total_size) {
++		/* Proceed to the next entry in the scatterlist. */
++		iscsi_tcp_segment_init_sg(segment, sg_next(segment->sg),
++					  0);
++		iscsi_tcp_segment_map(segment, recv);
++		BUG_ON(segment->size == 0);
++		return 0;
++	}
++
++	/* Do we need to handle padding? */
++	pad = iscsi_padding(segment->total_copied);
++	if (pad != 0) {
++		debug_tcp("consume %d pad bytes\n", pad);
++		segment->total_size += pad;
++		segment->size = pad;
++		segment->data = padbuf;
++		return 0;
++	}
++
++	/*
++	 * Set us up for transferring the data digest. hdr digest
++	 * is completely handled in hdr done function.
++	 */
++	if (segment->hash) {
++		crypto_hash_final(segment->hash, segment->digest);
++		iscsi_tcp_segment_splice_digest(segment,
++				 recv ? segment->recv_digest : segment->digest);
++		return 0;
++	}
++
++	return 1;
++}
++EXPORT_SYMBOL_GPL(iscsi_tcp_segment_done);
++
++/**
++ * iscsi_tcp_segment_recv - copy data to segment
++ * @tcp_conn: the iSCSI TCP connection
++ * @segment: the buffer to copy to
++ * @ptr: data pointer
++ * @len: amount of data available
++ *
++ * This function copies up to @len bytes to the
++ * given buffer, and returns the number of bytes
++ * consumed, which can actually be less than @len.
++ *
++ * If hash digest is enabled, the function will update the
++ * hash while copying.
++ * Combining these two operations doesn't buy us a lot (yet),
++ * but in the future we could implement combined copy+crc,
++ * just way we do for network layer checksums.
++ */
++static int
++iscsi_tcp_segment_recv(struct iscsi_tcp_conn *tcp_conn,
++		       struct iscsi_segment *segment, const void *ptr,
++		       unsigned int len)
++{
++	unsigned int copy = 0, copied = 0;
++
++	while (!iscsi_tcp_segment_done(segment, 1, copy)) {
++		if (copied == len) {
++			debug_tcp("iscsi_tcp_segment_recv copied %d bytes\n",
++				  len);
++			break;
++		}
++
++		copy = min(len - copied, segment->size - segment->copied);
++		debug_tcp("iscsi_tcp_segment_recv copying %d\n", copy);
++		memcpy(segment->data + segment->copied, ptr + copied, copy);
++		copied += copy;
++	}
++	return copied;
++}
++
++inline void
++iscsi_tcp_dgst_header(struct hash_desc *hash, const void *hdr, size_t hdrlen,
++		      unsigned char digest[ISCSI_DIGEST_SIZE])
++{
++	struct scatterlist sg;
++
++	sg_init_one(&sg, hdr, hdrlen);
++	crypto_hash_digest(hash, &sg, hdrlen, digest);
++}
++EXPORT_SYMBOL_GPL(iscsi_tcp_dgst_header);
++
++static inline int
++iscsi_tcp_dgst_verify(struct iscsi_tcp_conn *tcp_conn,
++		      struct iscsi_segment *segment)
++{
++	if (!segment->digest_len)
++		return 1;
++
++	if (memcmp(segment->recv_digest, segment->digest,
++		   segment->digest_len)) {
++		debug_scsi("digest mismatch\n");
++		return 0;
++	}
++
++	return 1;
++}
++
++/*
++ * Helper function to set up segment buffer
++ */
++static inline void
++__iscsi_segment_init(struct iscsi_segment *segment, size_t size,
++		     iscsi_segment_done_fn_t *done, struct hash_desc *hash)
++{
++	memset(segment, 0, sizeof(*segment));
++	segment->total_size = size;
++	segment->done = done;
++
++	if (hash) {
++		segment->hash = hash;
++		crypto_hash_init(hash);
++	}
++}
++
++inline void
++iscsi_segment_init_linear(struct iscsi_segment *segment, void *data,
++			  size_t size, iscsi_segment_done_fn_t *done,
++			  struct hash_desc *hash)
++{
++	__iscsi_segment_init(segment, size, done, hash);
++	segment->data = data;
++	segment->size = size;
++}
++EXPORT_SYMBOL_GPL(iscsi_segment_init_linear);
++
++inline int
++iscsi_segment_seek_sg(struct iscsi_segment *segment,
++		      struct scatterlist *sg_list, unsigned int sg_count,
++		      unsigned int offset, size_t size,
++		      iscsi_segment_done_fn_t *done, struct hash_desc *hash)
++{
++	struct scatterlist *sg;
++	unsigned int i;
++
++	debug_scsi("iscsi_segment_seek_sg offset %u size %llu\n",
++		  offset, size);
++	__iscsi_segment_init(segment, size, done, hash);
++	for_each_sg(sg_list, sg, sg_count, i) {
++		debug_scsi("sg %d, len %u offset %u\n", i, sg->length,
++			   sg->offset);
++		if (offset < sg->length) {
++			iscsi_tcp_segment_init_sg(segment, sg, offset);
++			return 0;
++		}
++		offset -= sg->length;
++	}
++
++	return ISCSI_ERR_DATA_OFFSET;
++}
++EXPORT_SYMBOL_GPL(iscsi_segment_seek_sg);
++
++/**
++ * iscsi_tcp_hdr_recv_prep - prep segment for hdr reception
++ * @tcp_conn: iscsi connection to prep for
++ *
++ * This function always passes NULL for the hash argument, because when this
++ * function is called we do not yet know the final size of the header and want
++ * to delay the digest processing until we know that.
++ */
++void iscsi_tcp_hdr_recv_prep(struct iscsi_tcp_conn *tcp_conn)
++{
++	debug_tcp("iscsi_tcp_hdr_recv_prep(%p%s)\n", tcp_conn,
++		  tcp_conn->iscsi_conn->hdrdgst_en ? ", digest enabled" : "");
++	iscsi_segment_init_linear(&tcp_conn->in.segment,
++				tcp_conn->in.hdr_buf, sizeof(struct iscsi_hdr),
++				iscsi_tcp_hdr_recv_done, NULL);
++}
++EXPORT_SYMBOL_GPL(iscsi_tcp_hdr_recv_prep);
++
++/*
++ * Handle incoming reply to any other type of command
++ */
++static int
++iscsi_tcp_data_recv_done(struct iscsi_tcp_conn *tcp_conn,
++			 struct iscsi_segment *segment)
++{
++	struct iscsi_conn *conn = tcp_conn->iscsi_conn;
++	int rc = 0;
++
++	if (!iscsi_tcp_dgst_verify(tcp_conn, segment))
++		return ISCSI_ERR_DATA_DGST;
++
++	rc = iscsi_complete_pdu(conn, tcp_conn->in.hdr,
++			conn->data, tcp_conn->in.datalen);
++	if (rc)
++		return rc;
++
++	iscsi_tcp_hdr_recv_prep(tcp_conn);
++	return 0;
++}
++
++static void
++iscsi_tcp_data_recv_prep(struct iscsi_tcp_conn *tcp_conn)
++{
++	struct iscsi_conn *conn = tcp_conn->iscsi_conn;
++	struct hash_desc *rx_hash = NULL;
++
++	if (conn->datadgst_en &
++	    !(conn->session->tt->caps & CAP_DIGEST_OFFLOAD))
++		rx_hash = tcp_conn->rx_hash;
++
++	iscsi_segment_init_linear(&tcp_conn->in.segment,
++				conn->data, tcp_conn->in.datalen,
++				iscsi_tcp_data_recv_done, rx_hash);
++}
++
++/**
++ * iscsi_tcp_cleanup_task - free tcp_task resources
++ * @task: iscsi task
++ *
++ * must be called with session lock
++ */
++void iscsi_tcp_cleanup_task(struct iscsi_task *task)
++{
++	struct iscsi_tcp_task *tcp_task = task->dd_data;
++	struct iscsi_r2t_info *r2t;
++
++	/* nothing to do for mgmt or pending tasks */
++	if (!task->sc || task->state == ISCSI_TASK_PENDING)
++		return;
++
++	/* flush task's r2t queues */
++	while (__kfifo_get(tcp_task->r2tqueue, (void*)&r2t, sizeof(void*))) {
++		__kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
++			    sizeof(void*));
++		debug_scsi("iscsi_tcp_cleanup_task pending r2t dropped\n");
++	}
++
++	r2t = tcp_task->r2t;
++	if (r2t != NULL) {
++		__kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
++			    sizeof(void*));
++		tcp_task->r2t = NULL;
++	}
++}
++EXPORT_SYMBOL_GPL(iscsi_tcp_cleanup_task);
++
++/**
++ * iscsi_tcp_data_in - SCSI Data-In Response processing
++ * @conn: iscsi connection
++ * @task: scsi command task
++ */
++static int iscsi_tcp_data_in(struct iscsi_conn *conn, struct iscsi_task *task)
++{
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	struct iscsi_tcp_task *tcp_task = task->dd_data;
++	struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)tcp_conn->in.hdr;
++	int datasn = be32_to_cpu(rhdr->datasn);
++	unsigned total_in_length = scsi_in(task->sc)->length;
++
++	iscsi_update_cmdsn(conn->session, (struct iscsi_nopin*)rhdr);
++	if (tcp_conn->in.datalen == 0)
++		return 0;
++
++	if (tcp_task->exp_datasn != datasn) {
++		debug_tcp("%s: task->exp_datasn(%d) != rhdr->datasn(%d)\n",
++		          __func__, tcp_task->exp_datasn, datasn);
++		return ISCSI_ERR_DATASN;
++	}
++
++	tcp_task->exp_datasn++;
++
++	tcp_task->data_offset = be32_to_cpu(rhdr->offset);
++	if (tcp_task->data_offset + tcp_conn->in.datalen > total_in_length) {
++		debug_tcp("%s: data_offset(%d) + data_len(%d) > total_length_in(%d)\n",
++		          __func__, tcp_task->data_offset,
++		          tcp_conn->in.datalen, total_in_length);
++		return ISCSI_ERR_DATA_OFFSET;
++	}
++
++	conn->datain_pdus_cnt++;
++	return 0;
++}
++
++/**
++ * iscsi_tcp_r2t_rsp - iSCSI R2T Response processing
++ * @conn: iscsi connection
++ * @task: scsi command task
++ */
++static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
++{
++	struct iscsi_session *session = conn->session;
++	struct iscsi_tcp_task *tcp_task = task->dd_data;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	struct iscsi_r2t_rsp *rhdr = (struct iscsi_r2t_rsp *)tcp_conn->in.hdr;
++	struct iscsi_r2t_info *r2t;
++	int r2tsn = be32_to_cpu(rhdr->r2tsn);
++	int rc;
++
++	if (tcp_conn->in.datalen) {
++		iscsi_conn_printk(KERN_ERR, conn,
++				  "invalid R2t with datalen %d\n",
++				  tcp_conn->in.datalen);
++		return ISCSI_ERR_DATALEN;
++	}
++
++	if (tcp_task->exp_datasn != r2tsn){
++		debug_tcp("%s: task->exp_datasn(%d) != rhdr->r2tsn(%d)\n",
++		          __func__, tcp_task->exp_datasn, r2tsn);
++		return ISCSI_ERR_R2TSN;
++	}
++
++	/* fill-in new R2T associated with the task */
++	iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
++
++	if (!task->sc || session->state != ISCSI_STATE_LOGGED_IN) {
++		iscsi_conn_printk(KERN_INFO, conn,
++				  "dropping R2T itt %d in recovery.\n",
++				  task->itt);
++		return 0;
++	}
++
++	rc = __kfifo_get(tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*));
++	if (!rc) {
++		iscsi_conn_printk(KERN_ERR, conn, "Could not allocate R2T. "
++				  "Target has sent more R2Ts than it "
++				  "negotiated for or driver has has leaked.\n");
++		return ISCSI_ERR_PROTO;
++	}
++
++	r2t->exp_statsn = rhdr->statsn;
++	r2t->data_length = be32_to_cpu(rhdr->data_length);
++	if (r2t->data_length == 0) {
++		iscsi_conn_printk(KERN_ERR, conn,
++				  "invalid R2T with zero data len\n");
++		__kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
++			    sizeof(void*));
++		return ISCSI_ERR_DATALEN;
++	}
++
++	if (r2t->data_length > session->max_burst)
++		debug_scsi("invalid R2T with data len %u and max burst %u."
++			   "Attempting to execute request.\n",
++			    r2t->data_length, session->max_burst);
++
++	r2t->data_offset = be32_to_cpu(rhdr->data_offset);
++	if (r2t->data_offset + r2t->data_length > scsi_out(task->sc)->length) {
++		iscsi_conn_printk(KERN_ERR, conn,
++				  "invalid R2T with data len %u at offset %u "
++				  "and total length %d\n", r2t->data_length,
++				  r2t->data_offset, scsi_out(task->sc)->length);
++		__kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
++			    sizeof(void*));
++		return ISCSI_ERR_DATALEN;
++	}
++
++	r2t->ttt = rhdr->ttt; /* no flip */
++	r2t->datasn = 0;
++	r2t->sent = 0;
++
++	tcp_task->exp_datasn = r2tsn + 1;
++	__kfifo_put(tcp_task->r2tqueue, (void*)&r2t, sizeof(void*));
++	conn->r2t_pdus_cnt++;
++
++	iscsi_requeue_task(task);
++	return 0;
++}
++
++/*
++ * Handle incoming reply to DataIn command
++ */
++static int
++iscsi_tcp_process_data_in(struct iscsi_tcp_conn *tcp_conn,
++			  struct iscsi_segment *segment)
++{
++	struct iscsi_conn *conn = tcp_conn->iscsi_conn;
++	struct iscsi_hdr *hdr = tcp_conn->in.hdr;
++	int rc;
++
++	if (!iscsi_tcp_dgst_verify(tcp_conn, segment))
++		return ISCSI_ERR_DATA_DGST;
++
++	/* check for non-exceptional status */
++	if (hdr->flags & ISCSI_FLAG_DATA_STATUS) {
++		rc = iscsi_complete_pdu(conn, tcp_conn->in.hdr, NULL, 0);
++		if (rc)
++			return rc;
++	}
++
++	iscsi_tcp_hdr_recv_prep(tcp_conn);
++	return 0;
++}
++
++/**
++ * iscsi_tcp_hdr_dissect - process PDU header
++ * @conn: iSCSI connection
++ * @hdr: PDU header
++ *
++ * This function analyzes the header of the PDU received,
++ * and performs several sanity checks. If the PDU is accompanied
++ * by data, the receive buffer is set up to copy the incoming data
++ * to the correct location.
++ */
++static int
++iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
++{
++	int rc = 0, opcode, ahslen;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	struct iscsi_task *task;
++
++	/* verify PDU length */
++	tcp_conn->in.datalen = ntoh24(hdr->dlength);
++	if (tcp_conn->in.datalen > conn->max_recv_dlength) {
++		iscsi_conn_printk(KERN_ERR, conn,
++				  "iscsi_tcp: datalen %d > %d\n",
++				  tcp_conn->in.datalen, conn->max_recv_dlength);
++		return ISCSI_ERR_DATALEN;
++	}
++
++	/* Additional header segments. So far, we don't
++	 * process additional headers.
++	 */
++	ahslen = hdr->hlength << 2;
++
++	opcode = hdr->opcode & ISCSI_OPCODE_MASK;
++	/* verify itt (itt encoding: age+cid+itt) */
++	rc = iscsi_verify_itt(conn, hdr->itt);
++	if (rc)
++		return rc;
++
++	debug_tcp("opcode 0x%x ahslen %d datalen %d\n",
++		  opcode, ahslen, tcp_conn->in.datalen);
++
++	switch(opcode) {
++	case ISCSI_OP_SCSI_DATA_IN:
++		spin_lock(&conn->session->lock);
++		task = iscsi_itt_to_ctask(conn, hdr->itt);
++		if (!task)
++			rc = ISCSI_ERR_BAD_ITT;
++		else
++			rc = iscsi_tcp_data_in(conn, task);
++		if (rc) {
++			spin_unlock(&conn->session->lock);
++			break;
++		}
++
++		if (tcp_conn->in.datalen) {
++			struct iscsi_tcp_task *tcp_task = task->dd_data;
++			struct hash_desc *rx_hash = NULL;
++			struct scsi_data_buffer *sdb = scsi_in(task->sc);
++
++			/*
++			 * Setup copy of Data-In into the Scsi_Cmnd
++			 * Scatterlist case:
++			 * We set up the iscsi_segment to point to the next
++			 * scatterlist entry to copy to. As we go along,
++			 * we move on to the next scatterlist entry and
++			 * update the digest per-entry.
++			 */
++			if (conn->datadgst_en &&
++			    !(conn->session->tt->caps & CAP_DIGEST_OFFLOAD))
++				rx_hash = tcp_conn->rx_hash;
++
++			debug_tcp("iscsi_tcp_begin_data_in(%p, offset=%d, "
++				  "datalen=%d)\n", tcp_conn,
++				  tcp_task->data_offset,
++				  tcp_conn->in.datalen);
++			rc = iscsi_segment_seek_sg(&tcp_conn->in.segment,
++						   sdb->table.sgl,
++						   sdb->table.nents,
++						   tcp_task->data_offset,
++						   tcp_conn->in.datalen,
++						   iscsi_tcp_process_data_in,
++						   rx_hash);
++			spin_unlock(&conn->session->lock);
++			return rc;
++		}
++		rc = __iscsi_complete_pdu(conn, hdr, NULL, 0);
++		spin_unlock(&conn->session->lock);
++		break;
++	case ISCSI_OP_SCSI_CMD_RSP:
++		if (tcp_conn->in.datalen) {
++			iscsi_tcp_data_recv_prep(tcp_conn);
++			return 0;
++		}
++		rc = iscsi_complete_pdu(conn, hdr, NULL, 0);
++		break;
++	case ISCSI_OP_R2T:
++		spin_lock(&conn->session->lock);
++		task = iscsi_itt_to_ctask(conn, hdr->itt);
++		if (!task)
++			rc = ISCSI_ERR_BAD_ITT;
++		else if (ahslen)
++			rc = ISCSI_ERR_AHSLEN;
++		else if (task->sc->sc_data_direction == DMA_TO_DEVICE)
++			rc = iscsi_tcp_r2t_rsp(conn, task);
++		else
++			rc = ISCSI_ERR_PROTO;
++		spin_unlock(&conn->session->lock);
++		break;
++	case ISCSI_OP_LOGIN_RSP:
++	case ISCSI_OP_TEXT_RSP:
++	case ISCSI_OP_REJECT:
++	case ISCSI_OP_ASYNC_EVENT:
++		/*
++		 * It is possible that we could get a PDU with a buffer larger
++		 * than 8K, but there are no targets that currently do this.
++		 * For now we fail until we find a vendor that needs it
++		 */
++		if (ISCSI_DEF_MAX_RECV_SEG_LEN < tcp_conn->in.datalen) {
++			iscsi_conn_printk(KERN_ERR, conn,
++					  "iscsi_tcp: received buffer of "
++					  "len %u but conn buffer is only %u "
++					  "(opcode %0x)\n",
++					  tcp_conn->in.datalen,
++					  ISCSI_DEF_MAX_RECV_SEG_LEN, opcode);
++			rc = ISCSI_ERR_PROTO;
++			break;
++		}
++
++		/* If there's data coming in with the response,
++		 * receive it to the connection's buffer.
++		 */
++		if (tcp_conn->in.datalen) {
++			iscsi_tcp_data_recv_prep(tcp_conn);
++			return 0;
++		}
++	/* fall through */
++	case ISCSI_OP_LOGOUT_RSP:
++	case ISCSI_OP_NOOP_IN:
++	case ISCSI_OP_SCSI_TMFUNC_RSP:
++		rc = iscsi_complete_pdu(conn, hdr, NULL, 0);
++		break;
++	default:
++		rc = ISCSI_ERR_BAD_OPCODE;
++		break;
++	}
++
++	if (rc == 0) {
++		/* Anything that comes with data should have
++		 * been handled above. */
++		if (tcp_conn->in.datalen)
++			return ISCSI_ERR_PROTO;
++		iscsi_tcp_hdr_recv_prep(tcp_conn);
++	}
++
++	return rc;
++}
++
++/**
++ * iscsi_tcp_hdr_recv_done - process PDU header
++ *
++ * This is the callback invoked when the PDU header has
++ * been received. If the header is followed by additional
++ * header segments, we go back for more data.
++ */
++static int
++iscsi_tcp_hdr_recv_done(struct iscsi_tcp_conn *tcp_conn,
++			struct iscsi_segment *segment)
++{
++	struct iscsi_conn *conn = tcp_conn->iscsi_conn;
++	struct iscsi_hdr *hdr;
++
++	/* Check if there are additional header segments
++	 * *prior* to computing the digest, because we
++	 * may need to go back to the caller for more.
++	 */
++	hdr = (struct iscsi_hdr *) tcp_conn->in.hdr_buf;
++	if (segment->copied == sizeof(struct iscsi_hdr) && hdr->hlength) {
++		/* Bump the header length - the caller will
++		 * just loop around and get the AHS for us, and
++		 * call again. */
++		unsigned int ahslen = hdr->hlength << 2;
++
++		/* Make sure we don't overflow */
++		if (sizeof(*hdr) + ahslen > sizeof(tcp_conn->in.hdr_buf))
++			return ISCSI_ERR_AHSLEN;
++
++		segment->total_size += ahslen;
++		segment->size += ahslen;
++		return 0;
++	}
++
++	/* We're done processing the header. See if we're doing
++	 * header digests; if so, set up the recv_digest buffer
++	 * and go back for more. */
++	if (conn->hdrdgst_en) {
++		if (segment->digest_len == 0) {
++			/*
++			 * Even if we offload the digest processing we
++			 * splice it in so we can increment the skb/segment
++			 * counters in preparation for the data segment.
++			 */
++			iscsi_tcp_segment_splice_digest(segment,
++							segment->recv_digest);
++			return 0;
++		}
++
++		if (!(conn->session->tt->caps & CAP_DIGEST_OFFLOAD)) {
++			iscsi_tcp_dgst_header(tcp_conn->rx_hash, hdr,
++				segment->total_copied - ISCSI_DIGEST_SIZE,
++				segment->digest);
++
++			if (!iscsi_tcp_dgst_verify(tcp_conn, segment))
++				return ISCSI_ERR_HDR_DGST;
++		}
++	}
++
++	tcp_conn->in.hdr = hdr;
++	return iscsi_tcp_hdr_dissect(conn, hdr);
++}
++
++/**
++ * iscsi_tcp_recv_segment_is_hdr - tests if we are reading in a header
++ * @tcp_conn: iscsi tcp conn
++ *
++ * returns non zero if we are currently processing or setup to process
++ * a header.
++ */
++inline int iscsi_tcp_recv_segment_is_hdr(struct iscsi_tcp_conn *tcp_conn)
++{
++	return tcp_conn->in.segment.done == iscsi_tcp_hdr_recv_done;
++}
++EXPORT_SYMBOL_GPL(iscsi_tcp_recv_segment_is_hdr);
++
++/**
++ * iscsi_tcp_recv_skb - Process skb
++ * @conn: iscsi connection
++ * @skb: network buffer with header and/or data segment
++ * @offset: offset in skb
++ * @offload: bool indicating if transfer was offloaded
++ *
++ * Will return status of transfer in status. And will return
++ * number of bytes copied.
++ */
++int iscsi_tcp_recv_skb(struct iscsi_conn *conn, struct sk_buff *skb,
++		       unsigned int offset, bool offloaded, int *status)
++{
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	struct iscsi_segment *segment = &tcp_conn->in.segment;
++	struct skb_seq_state seq;
++	unsigned int consumed = 0;
++	int rc = 0;
++
++	debug_tcp("in %d bytes\n", skb->len - offset);
++
++	if (unlikely(conn->suspend_rx)) {
++		debug_tcp("conn %d Rx suspended!\n", conn->id);
++		*status = ISCSI_TCP_SUSPENDED;
++		return 0;
++	}
++
++	if (offloaded) {
++		segment->total_copied = segment->total_size;
++		goto segment_done;
++	}
++
++	skb_prepare_seq_read(skb, offset, skb->len, &seq);
++	while (1) {
++		unsigned int avail;
++		const u8 *ptr;
++
++		avail = skb_seq_read(consumed, &ptr, &seq);
++		if (avail == 0) {
++			debug_tcp("no more data avail. Consumed %d\n",
++				  consumed);
++			*status = ISCSI_TCP_SKB_DONE;
++			skb_abort_seq_read(&seq);
++			goto skb_done;
++		}
++		BUG_ON(segment->copied >= segment->size);
++
++		debug_tcp("skb %p ptr=%p avail=%u\n", skb, ptr, avail);
++		rc = iscsi_tcp_segment_recv(tcp_conn, segment, ptr, avail);
++		BUG_ON(rc == 0);
++		consumed += rc;
++
++		if (segment->total_copied >= segment->total_size) {
++			skb_abort_seq_read(&seq);
++			goto segment_done;
++		}
++	}
++
++segment_done:
++	*status = ISCSI_TCP_SEGMENT_DONE;
++	debug_tcp("segment done\n");
++	rc = segment->done(tcp_conn, segment);
++	if (rc != 0) {
++		*status = ISCSI_TCP_CONN_ERR;
++		debug_tcp("Error receiving PDU, errno=%d\n", rc);
++		iscsi_conn_failure(conn, rc);
++		return 0;
++	}
++	/* The done() functions sets up the next segment. */
++
++skb_done:
++	conn->rxdata_octets += consumed;
++	return consumed;
++}
++EXPORT_SYMBOL_GPL(iscsi_tcp_recv_skb);
++
++/**
++ * iscsi_tcp_task_init - Initialize iSCSI SCSI_READ or SCSI_WRITE commands
++ * @conn: iscsi connection
++ * @task: scsi command task
++ * @sc: scsi command
++ */
++int iscsi_tcp_task_init(struct iscsi_task *task)
++{
++	struct iscsi_tcp_task *tcp_task = task->dd_data;
++	struct iscsi_conn *conn = task->conn;
++	struct scsi_cmnd *sc = task->sc;
++	int err;
++
++	if (!sc) {
++		/*
++		 * mgmt tasks do not have a scatterlist since they come
++		 * in from the iscsi interface.
++		 */
++		debug_scsi("mtask deq [cid %d itt 0x%x]\n", conn->id,
++			   task->itt);
++
++		return conn->session->tt->init_pdu(task, 0, task->data_count);
++	}
++
++	BUG_ON(__kfifo_len(tcp_task->r2tqueue));
++	tcp_task->exp_datasn = 0;
++
++	/* Prepare PDU, optionally w/ immediate data */
++	debug_scsi("task deq [cid %d itt 0x%x imm %d unsol %d]\n",
++		    conn->id, task->itt, task->imm_count,
++		    task->unsol_r2t.data_length);
++
++	err = conn->session->tt->init_pdu(task, 0, task->imm_count);
++	if (err)
++		return err;
++	task->imm_count = 0;
++	return 0;
++}
++EXPORT_SYMBOL_GPL(iscsi_tcp_task_init);
++
++static struct iscsi_r2t_info *iscsi_tcp_get_curr_r2t(struct iscsi_task *task)
++{
++	struct iscsi_session *session = task->conn->session;
++	struct iscsi_tcp_task *tcp_task = task->dd_data;
++	struct iscsi_r2t_info *r2t = NULL;
++
++	if (iscsi_task_has_unsol_data(task))
++		r2t = &task->unsol_r2t;
++	else {
++		spin_lock_bh(&session->lock);
++		if (tcp_task->r2t) {
++			r2t = tcp_task->r2t;
++			/* Continue with this R2T? */
++			if (r2t->data_length <= r2t->sent) {
++				debug_scsi("  done with r2t %p\n", r2t);
++				__kfifo_put(tcp_task->r2tpool.queue,
++					    (void *)&tcp_task->r2t,
++					    sizeof(void *));
++				tcp_task->r2t = r2t = NULL;
++			}
++		}
++
++		if (r2t == NULL) {
++			__kfifo_get(tcp_task->r2tqueue,
++				    (void *)&tcp_task->r2t, sizeof(void *));
++			r2t = tcp_task->r2t;
++		}
++		spin_unlock_bh(&session->lock);
++	}
++
++	return r2t;
++}
++
++/**
++ * iscsi_tcp_task_xmit - xmit normal PDU task
++ * @task: iscsi command task
++ *
++ * We're expected to return 0 when everything was transmitted succesfully,
++ * -EAGAIN if there's still data in the queue, or != 0 for any other kind
++ * of error.
++ */
++int iscsi_tcp_task_xmit(struct iscsi_task *task)
++{
++	struct iscsi_conn *conn = task->conn;
++	struct iscsi_session *session = conn->session;
++	struct iscsi_r2t_info *r2t;
++	int rc = 0;
++
++flush:
++	/* Flush any pending data first. */
++	rc = session->tt->xmit_pdu(task);
++	if (rc < 0)
++		return rc;
++
++	/* mgmt command */
++	if (!task->sc) {
++		if (task->hdr->itt == RESERVED_ITT)
++			iscsi_put_task(task);
++		return 0;
++	}
++
++	/* Are we done already? */
++	if (task->sc->sc_data_direction != DMA_TO_DEVICE)
++		return 0;
++
++	r2t = iscsi_tcp_get_curr_r2t(task);
++	if (r2t == NULL) {
++		/* Waiting for more R2Ts to arrive. */
++		debug_tcp("no R2Ts yet\n");
++		return 0;
++	}
++
++	rc = conn->session->tt->alloc_pdu(task);
++	if (rc)
++		return rc;
++	iscsi_prep_data_out_pdu(task, r2t, (struct iscsi_data *) task->hdr);
++
++	debug_scsi("sol dout %p [dsn %d itt 0x%x doff %d dlen %d]\n",
++		   r2t, r2t->datasn - 1, task->hdr->itt,
++		   r2t->data_offset + r2t->sent, r2t->data_count);
++
++	rc = conn->session->tt->init_pdu(task, r2t->data_offset + r2t->sent,
++					 r2t->data_count);
++	if (rc)
++		return rc;
++	r2t->sent += r2t->data_count;
++	goto flush;
++}
++EXPORT_SYMBOL_GPL(iscsi_tcp_task_xmit);
++
++struct iscsi_cls_conn *
++iscsi_tcp_conn_setup(struct iscsi_cls_session *cls_session, int dd_data_size,
++		      uint32_t conn_idx)
++
++{
++	struct iscsi_conn *conn;
++	struct iscsi_cls_conn *cls_conn;
++	struct iscsi_tcp_conn *tcp_conn;
++
++	cls_conn = iscsi_conn_setup(cls_session, sizeof(*tcp_conn), conn_idx);
++	if (!cls_conn)
++		return NULL;
++	conn = cls_conn->dd_data;
++	/*
++	 * due to strange issues with iser these are not set
++	 * in iscsi_conn_setup
++	 */
++	conn->max_recv_dlength = ISCSI_DEF_MAX_RECV_SEG_LEN;
++
++	tcp_conn = conn->dd_data;
++	tcp_conn->iscsi_conn = conn;
++
++	tcp_conn->dd_data = kzalloc(dd_data_size, GFP_KERNEL);
++	if (!tcp_conn->dd_data) {
++		iscsi_conn_teardown(cls_conn);
++		return NULL;
++	}
++	return cls_conn;
++}
++EXPORT_SYMBOL_GPL(iscsi_tcp_conn_setup);
++
++void iscsi_tcp_conn_teardown(struct iscsi_cls_conn *cls_conn)
++{
++	struct iscsi_conn *conn = cls_conn->dd_data;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++
++	kfree(tcp_conn->dd_data);
++	iscsi_conn_teardown(cls_conn);
++}
++EXPORT_SYMBOL_GPL(iscsi_tcp_conn_teardown);
++
++int iscsi_tcp_r2tpool_alloc(struct iscsi_session *session)
++{
++	int i;
++	int cmd_i;
++
++	/*
++	 * initialize per-task: R2T pool and xmit queue
++	 */
++	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
++	        struct iscsi_task *task = session->cmds[cmd_i];
++		struct iscsi_tcp_task *tcp_task = task->dd_data;
++
++		/*
++		 * pre-allocated x2 as much r2ts to handle race when
++		 * target acks DataOut faster than we data_xmit() queues
++		 * could replenish r2tqueue.
++		 */
++
++		/* R2T pool */
++		if (iscsi_pool_init(&tcp_task->r2tpool,
++				    session->max_r2t * 2, NULL,
++				    sizeof(struct iscsi_r2t_info))) {
++			goto r2t_alloc_fail;
++		}
++
++		/* R2T xmit queue */
++		tcp_task->r2tqueue = kfifo_alloc(
++		      session->max_r2t * 4 * sizeof(void*), GFP_KERNEL, NULL);
++		if (tcp_task->r2tqueue == ERR_PTR(-ENOMEM)) {
++			iscsi_pool_free(&tcp_task->r2tpool);
++			goto r2t_alloc_fail;
++		}
++	}
++
++	return 0;
++
++r2t_alloc_fail:
++	for (i = 0; i < cmd_i; i++) {
++		struct iscsi_task *task = session->cmds[i];
++		struct iscsi_tcp_task *tcp_task = task->dd_data;
++
++		kfifo_free(tcp_task->r2tqueue);
++		iscsi_pool_free(&tcp_task->r2tpool);
++	}
++	return -ENOMEM;
++}
++EXPORT_SYMBOL_GPL(iscsi_tcp_r2tpool_alloc);
++
++void iscsi_tcp_r2tpool_free(struct iscsi_session *session)
++{
++	int i;
++
++	for (i = 0; i < session->cmds_max; i++) {
++		struct iscsi_task *task = session->cmds[i];
++		struct iscsi_tcp_task *tcp_task = task->dd_data;
++
++		kfifo_free(tcp_task->r2tqueue);
++		iscsi_pool_free(&tcp_task->r2tpool);
++	}
++}
++EXPORT_SYMBOL_GPL(iscsi_tcp_r2tpool_free);
++
++void iscsi_tcp_conn_get_stats(struct iscsi_cls_conn *cls_conn,
++			      struct iscsi_stats *stats)
++{
++	struct iscsi_conn *conn = cls_conn->dd_data;
++
++	stats->txdata_octets = conn->txdata_octets;
++	stats->rxdata_octets = conn->rxdata_octets;
++	stats->scsicmd_pdus = conn->scsicmd_pdus_cnt;
++	stats->dataout_pdus = conn->dataout_pdus_cnt;
++	stats->scsirsp_pdus = conn->scsirsp_pdus_cnt;
++	stats->datain_pdus = conn->datain_pdus_cnt;
++	stats->r2t_pdus = conn->r2t_pdus_cnt;
++	stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
++	stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
++}
++EXPORT_SYMBOL_GPL(iscsi_tcp_conn_get_stats);
+diff --git a/include/scsi/libiscsi_tcp.h b/include/scsi/libiscsi_tcp.h
+new file mode 100644
+index 000000000000..e6bf8ef276bb
+--- /dev/null
++++ b/include/scsi/libiscsi_tcp.h
+@@ -0,0 +1,131 @@
++/*
++ * iSCSI over TCP/IP Data-Path lib
++ *
++ * Copyright (C) 2008 Mike Christie
++ * Copyright (C) 2008 Red Hat, Inc.  All rights reserved.
++ * maintained by open-iscsi@googlegroups.com
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published
++ * by the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * See the file COPYING included with this distribution for more details.
++ */
++
++#ifndef LIBISCSI_TCP_H
++#define LIBISCSI_TCP_H
++
++#include 
++
++struct iscsi_tcp_conn;
++struct iscsi_segment;
++struct sk_buff;
++struct hash_desc;
++
++typedef int iscsi_segment_done_fn_t(struct iscsi_tcp_conn *,
++				    struct iscsi_segment *);
++
++struct iscsi_segment {
++	unsigned char		*data;
++	unsigned int		size;
++	unsigned int		copied;
++	unsigned int		total_size;
++	unsigned int		total_copied;
++
++	struct hash_desc	*hash;
++	unsigned char		recv_digest[ISCSI_DIGEST_SIZE];
++	unsigned char		digest[ISCSI_DIGEST_SIZE];
++	unsigned int		digest_len;
++
++	struct scatterlist	*sg;
++	void			*sg_mapped;
++	unsigned int		sg_offset;
++
++	iscsi_segment_done_fn_t	*done;
++};
++
++/* Socket connection recieve helper */
++struct iscsi_tcp_recv {
++	struct iscsi_hdr	*hdr;
++	struct iscsi_segment	segment;
++
++	/* Allocate buffer for BHS + AHS */
++	uint32_t		hdr_buf[64];
++
++	/* copied and flipped values */
++	int			datalen;
++};
++
++struct iscsi_tcp_conn {
++	struct iscsi_conn	*iscsi_conn;
++	void			*dd_data;
++	int			stop_stage;	/* conn_stop() flag: *
++						 * stop to recover,  *
++						 * stop to terminate */
++	/* control data */
++	struct iscsi_tcp_recv	in;		/* TCP receive context */
++	/* CRC32C (Rx) LLD should set this is they do not offload */
++	struct hash_desc	*rx_hash;
++};
++
++struct iscsi_tcp_task {
++	uint32_t		exp_datasn;	/* expected target's R2TSN/DataSN */
++	int			data_offset;
++	struct iscsi_r2t_info	*r2t;		/* in progress solict R2T */
++	struct iscsi_pool	r2tpool;
++	struct kfifo		*r2tqueue;
++	void			*dd_data;
++};
++
++enum {
++	ISCSI_TCP_SEGMENT_DONE,		/* curr seg has been processed */
++	ISCSI_TCP_SKB_DONE,		/* skb is out of data */
++	ISCSI_TCP_CONN_ERR,		/* iscsi layer has fired a conn err */
++	ISCSI_TCP_SUSPENDED,		/* conn is suspended */
++};
++
++extern void iscsi_tcp_hdr_recv_prep(struct iscsi_tcp_conn *tcp_conn);
++extern int iscsi_tcp_recv_skb(struct iscsi_conn *conn, struct sk_buff *skb,
++			      unsigned int offset, bool offloaded, int *status);
++extern void iscsi_tcp_cleanup_task(struct iscsi_task *task);
++extern int iscsi_tcp_task_init(struct iscsi_task *task);
++extern int iscsi_tcp_task_xmit(struct iscsi_task *task);
++
++/* segment helpers */
++extern int iscsi_tcp_recv_segment_is_hdr(struct iscsi_tcp_conn *tcp_conn);
++extern int iscsi_tcp_segment_done(struct iscsi_segment *segment, int recv,
++				  unsigned copied);
++extern void iscsi_tcp_segment_unmap(struct iscsi_segment *segment);
++
++extern void iscsi_segment_init_linear(struct iscsi_segment *segment,
++				      void *data, size_t size,
++				      iscsi_segment_done_fn_t *done,
++				      struct hash_desc *hash);
++extern int
++iscsi_segment_seek_sg(struct iscsi_segment *segment,
++		      struct scatterlist *sg_list, unsigned int sg_count,
++		      unsigned int offset, size_t size,
++		      iscsi_segment_done_fn_t *done, struct hash_desc *hash);
++
++/* digest helpers */
++extern void iscsi_tcp_dgst_header(struct hash_desc *hash, const void *hdr,
++				  size_t hdrlen,
++				  unsigned char digest[ISCSI_DIGEST_SIZE]);
++extern struct iscsi_cls_conn *
++iscsi_tcp_conn_setup(struct iscsi_cls_session *cls_session, int dd_data_size,
++		     uint32_t conn_idx);
++extern void iscsi_tcp_conn_teardown(struct iscsi_cls_conn *cls_conn);
++
++/* misc helpers */
++extern int iscsi_tcp_r2tpool_alloc(struct iscsi_session *session);
++extern void iscsi_tcp_r2tpool_free(struct iscsi_session *session);
++
++extern void iscsi_tcp_conn_get_stats(struct iscsi_cls_conn *cls_conn,
++				     struct iscsi_stats *stats);
++#endif /* LIBISCSI_TCP_H */

commit 30b4915015c112547e930cadf734d875aec8438d
+Author: Mike Christie 
+Date:   Tue Dec 2 00:32:10 2008 -0600
+
+    [SCSI] iscsi_tcp: add iscsi_tcp prefix to iscsi_tcp functions
+    
+    Add iscsi_tcp prefix to most functions. Some are not changed
+    becuase they are going to move in the next patch.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index e6ae4e648343..97f3f68aeb64 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -516,12 +516,11 @@ static void iscsi_tcp_cleanup_task(struct iscsi_task *task)
+ }
+ 
+ /**
+- * iscsi_data_in - SCSI Data-In Response processing
++ * iscsi_tcp_data_in - SCSI Data-In Response processing
+  * @conn: iscsi connection
+  * @task: scsi command task
+- **/
+-static int
+-iscsi_data_in(struct iscsi_conn *conn, struct iscsi_task *task)
++ */
++static int iscsi_tcp_data_in(struct iscsi_conn *conn, struct iscsi_task *task)
+ {
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	struct iscsi_tcp_task *tcp_task = task->dd_data;
+@@ -554,12 +553,11 @@ iscsi_data_in(struct iscsi_conn *conn, struct iscsi_task *task)
+ }
+ 
+ /**
+- * iscsi_r2t_rsp - iSCSI R2T Response processing
++ * iscsi_tcp_r2t_rsp - iSCSI R2T Response processing
+  * @conn: iscsi connection
+  * @task: scsi command task
+- **/
+-static int
+-iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
++ */
++static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
+ {
+ 	struct iscsi_session *session = conn->session;
+ 	struct iscsi_tcp_task *tcp_task = task->dd_data;
+@@ -710,7 +708,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 		if (!task)
+ 			rc = ISCSI_ERR_BAD_ITT;
+ 		else
+-			rc = iscsi_data_in(conn, task);
++			rc = iscsi_tcp_data_in(conn, task);
+ 		if (rc) {
+ 			spin_unlock(&conn->session->lock);
+ 			break;
+@@ -765,7 +763,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 		else if (ahslen)
+ 			rc = ISCSI_ERR_AHSLEN;
+ 		else if (task->sc->sc_data_direction == DMA_TO_DEVICE)
+-			rc = iscsi_r2t_rsp(conn, task);
++			rc = iscsi_tcp_r2t_rsp(conn, task);
+ 		else
+ 			rc = ISCSI_ERR_PROTO;
+ 		spin_unlock(&conn->session->lock);
+@@ -1053,8 +1051,7 @@ iscsi_tcp_state_change(struct sock *sk)
+  * iscsi_write_space - Called when more output buffer space is available
+  * @sk: socket space is available for
+  **/
+-static void
+-iscsi_write_space(struct sock *sk)
++static void iscsi_tcp_write_space(struct sock *sk)
+ {
+ 	struct iscsi_conn *conn = (struct iscsi_conn*)sk->sk_user_data;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+@@ -1064,8 +1061,7 @@ iscsi_write_space(struct sock *sk)
+ 	scsi_queue_work(conn->session->host, &conn->xmitwork);
+ }
+ 
+-static void
+-iscsi_conn_set_callbacks(struct iscsi_conn *conn)
++static void iscsi_tcp_conn_set_callbacks(struct iscsi_conn *conn)
+ {
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	struct sock *sk = tcp_conn->sock->sk;
+@@ -1078,12 +1074,11 @@ iscsi_conn_set_callbacks(struct iscsi_conn *conn)
+ 	tcp_conn->old_write_space = sk->sk_write_space;
+ 	sk->sk_data_ready = iscsi_tcp_data_ready;
+ 	sk->sk_state_change = iscsi_tcp_state_change;
+-	sk->sk_write_space = iscsi_write_space;
++	sk->sk_write_space = iscsi_tcp_write_space;
+ 	write_unlock_bh(&sk->sk_callback_lock);
+ }
+ 
+-static void
+-iscsi_conn_restore_callbacks(struct iscsi_tcp_conn *tcp_conn)
++static void iscsi_conn_restore_callbacks(struct iscsi_tcp_conn *tcp_conn)
+ {
+ 	struct sock *sk = tcp_conn->sock->sk;
+ 
+@@ -1098,10 +1093,9 @@ iscsi_conn_restore_callbacks(struct iscsi_tcp_conn *tcp_conn)
+ }
+ 
+ /**
+- * iscsi_xmit - TCP transmit
++ * iscsi_tcp_xmit - TCP transmit
+  **/
+-static int
+-iscsi_xmit(struct iscsi_conn *conn)
++static int iscsi_tcp_xmit(struct iscsi_conn *conn)
+ {
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	struct iscsi_segment *segment = &tcp_conn->out.segment;
+@@ -1159,7 +1153,7 @@ static int iscsi_tcp_flush(struct iscsi_task *task)
+ 	int rc;
+ 
+ 	while (iscsi_tcp_xmit_qlen(conn)) {
+-		rc = iscsi_xmit(conn);
++		rc = iscsi_tcp_xmit(conn);
+ 		if (rc == 0)
+ 			return -EAGAIN;
+ 		if (rc < 0)
+@@ -1625,7 +1619,7 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
+ 	sk->sk_sndtimeo = 15 * HZ; /* FIXME: make it configurable */
+ 	sk->sk_allocation = GFP_ATOMIC;
+ 
+-	iscsi_conn_set_callbacks(conn);
++	iscsi_tcp_conn_set_callbacks(conn);
+ 	tcp_conn->sendpage = tcp_conn->sock->ops->sendpage;
+ 	/*
+ 	 * set receive state machine into initial state

commit cfeb2cf957ca5b4e557b53fb91ccc52f442f6dbe
+Author: Mike Christie 
+Date:   Tue Dec 2 00:32:09 2008 -0600
+
+    [SCSI] libiscsi: change login data buffer allocation
+    
+    This modifies the login buffer allocation to use __get_free_pages.
+    It will allow drivers that want to send this data with zero copy
+    operations to easily line things up on page boundaries.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 80cbcdce7fa3..c1bb74052aed 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -2284,7 +2284,8 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size,
+ 	}
+ 	spin_unlock_bh(&session->lock);
+ 
+-	data = kmalloc(ISCSI_DEF_MAX_RECV_SEG_LEN, GFP_KERNEL);
++	data = (char *) __get_free_pages(GFP_KERNEL,
++					 get_order(ISCSI_DEF_MAX_RECV_SEG_LEN));
+ 	if (!data)
+ 		goto login_task_data_alloc_fail;
+ 	conn->login_task->data = conn->data = data;
+@@ -2355,7 +2356,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
+ 	iscsi_suspend_tx(conn);
+ 
+ 	spin_lock_bh(&session->lock);
+-	kfree(conn->data);
++	free_pages((unsigned long) conn->data,
++		   get_order(ISCSI_DEF_MAX_RECV_SEG_LEN));
+ 	kfree(conn->persistent_address);
+ 	__kfifo_put(session->cmdpool.queue, (void*)&conn->login_task,
+ 		    sizeof(void*));

commit e2bac7c55e43c9018f2f4daf15437e836b26e709
+Author: Mike Christie 
+Date:   Tue Dec 2 00:32:08 2008 -0600
+
+    [SCSI] iscsi_tcp: remove unused r2t handling
+    
+    libiscsi's iscsi_prep_data_out_pdu now handles what
+    iscsi_tcp's helpers were so we can remove iscsi_tcp's helpers.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 97bad5ce5834..e6ae4e648343 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -553,48 +553,6 @@ iscsi_data_in(struct iscsi_conn *conn, struct iscsi_task *task)
+ 	return 0;
+ }
+ 
+-/**
+- * iscsi_solicit_data_init - initialize first Data-Out
+- * @conn: iscsi connection
+- * @task: scsi command task
+- * @r2t: R2T info
+- *
+- * Notes:
+- *	Initialize first Data-Out within this R2T sequence and finds
+- *	proper data_offset within this SCSI command.
+- *
+- *	This function is called with connection lock taken.
+- **/
+-static void
+-iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_task *task,
+-			struct iscsi_r2t_info *r2t)
+-{
+-	struct iscsi_data *hdr;
+-
+-	hdr = &r2t->dtask.hdr;
+-	memset(hdr, 0, sizeof(struct iscsi_data));
+-	hdr->ttt = r2t->ttt;
+-	hdr->datasn = cpu_to_be32(r2t->solicit_datasn);
+-	r2t->solicit_datasn++;
+-	hdr->opcode = ISCSI_OP_SCSI_DATA_OUT;
+-	memcpy(hdr->lun, task->hdr->lun, sizeof(hdr->lun));
+-	hdr->itt = task->hdr->itt;
+-	hdr->exp_statsn = r2t->exp_statsn;
+-	hdr->offset = cpu_to_be32(r2t->data_offset);
+-	if (r2t->data_length > conn->max_xmit_dlength) {
+-		hton24(hdr->dlength, conn->max_xmit_dlength);
+-		r2t->data_count = conn->max_xmit_dlength;
+-		hdr->flags = 0;
+-	} else {
+-		hton24(hdr->dlength, r2t->data_length);
+-		r2t->data_count = r2t->data_length;
+-		hdr->flags = ISCSI_FLAG_CMD_FINAL;
+-	}
+-	conn->dataout_pdus_cnt++;
+-
+-	r2t->sent = 0;
+-}
+-
+ /**
+  * iscsi_r2t_rsp - iSCSI R2T Response processing
+  * @conn: iscsi connection
+@@ -1311,55 +1269,6 @@ iscsi_tcp_send_linear_data_prepare(struct iscsi_conn *conn, void *data,
+ 				data, len, NULL, tx_hash);
+ }
+ 
+-/**
+- * iscsi_solicit_data_cont - initialize next Data-Out
+- * @conn: iscsi connection
+- * @task: scsi command task
+- * @r2t: R2T info
+- * @left: bytes left to transfer
+- *
+- * Notes:
+- *	Initialize next Data-Out within this R2T sequence and continue
+- *	to process next Scatter-Gather element(if any) of this SCSI command.
+- *
+- *	Called under connection lock.
+- **/
+-static int
+-iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_task *task,
+-			struct iscsi_r2t_info *r2t)
+-{
+-	struct iscsi_data *hdr;
+-	int new_offset, left;
+-
+-	BUG_ON(r2t->data_length - r2t->sent < 0);
+-	left = r2t->data_length - r2t->sent;
+-	if (left == 0)
+-		return 0;
+-
+-	hdr = &r2t->dtask.hdr;
+-	memset(hdr, 0, sizeof(struct iscsi_data));
+-	hdr->ttt = r2t->ttt;
+-	hdr->datasn = cpu_to_be32(r2t->solicit_datasn);
+-	r2t->solicit_datasn++;
+-	hdr->opcode = ISCSI_OP_SCSI_DATA_OUT;
+-	memcpy(hdr->lun, task->hdr->lun, sizeof(hdr->lun));
+-	hdr->itt = task->hdr->itt;
+-	hdr->exp_statsn = r2t->exp_statsn;
+-	new_offset = r2t->data_offset + r2t->sent;
+-	hdr->offset = cpu_to_be32(new_offset);
+-	if (left > conn->max_xmit_dlength) {
+-		hton24(hdr->dlength, conn->max_xmit_dlength);
+-		r2t->data_count = conn->max_xmit_dlength;
+-	} else {
+-		hton24(hdr->dlength, left);
+-		r2t->data_count = left;
+-		hdr->flags = ISCSI_FLAG_CMD_FINAL;
+-	}
+-
+-	conn->dataout_pdus_cnt++;
+-	return 1;
+-}
+-
+ static int iscsi_tcp_pdu_init(struct iscsi_task *task,
+ 			      unsigned int offset, unsigned int count)
+ {

commit e5a7efeffdcc3062ade5208d16c278d8d484f82a
+Author: Mike Christie 
+Date:   Tue Dec 2 00:32:07 2008 -0600
+
+    [SCSI] iscsi_tcp: convert to new alloc_hdr api
+    
+    This converts iscsi_tcp to the new api and modifies how
+    it handles r2ts.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 464de780d953..97bad5ce5834 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -57,13 +57,6 @@ MODULE_LICENSE("GPL");
+ #define debug_tcp(fmt...)
+ #endif
+ 
+-#ifndef DEBUG_ASSERT
+-#ifdef BUG_ON
+-#undef BUG_ON
+-#endif
+-#define BUG_ON(expr)
+-#endif
+-
+ static struct scsi_transport_template *iscsi_tcp_scsi_transport;
+ static struct scsi_host_template iscsi_sht;
+ static struct iscsi_transport iscsi_tcp_transport;
+@@ -498,14 +491,13 @@ iscsi_tcp_data_recv_prep(struct iscsi_tcp_conn *tcp_conn)
+ /*
+  * must be called with session lock
+  */
+-static void
+-iscsi_tcp_cleanup_task(struct iscsi_conn *conn, struct iscsi_task *task)
++static void iscsi_tcp_cleanup_task(struct iscsi_task *task)
+ {
+ 	struct iscsi_tcp_task *tcp_task = task->dd_data;
+ 	struct iscsi_r2t_info *r2t;
+ 
+-	/* nothing to do for mgmt tasks */
+-	if (!task->sc)
++	/* nothing to do for mgmt or pending tasks */
++	if (!task->sc || task->state == ISCSI_TASK_PENDING)
+ 		return;
+ 
+ 	/* flush task's r2t queues */
+@@ -611,11 +603,11 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_task *task,
+ static int
+ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
+ {
+-	struct iscsi_r2t_info *r2t;
+ 	struct iscsi_session *session = conn->session;
+ 	struct iscsi_tcp_task *tcp_task = task->dd_data;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	struct iscsi_r2t_rsp *rhdr = (struct iscsi_r2t_rsp *)tcp_conn->in.hdr;
++	struct iscsi_r2t_info *r2t;
+ 	int r2tsn = be32_to_cpu(rhdr->r2tsn);
+ 	int rc;
+ 
+@@ -643,7 +635,12 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
+ 	}
+ 
+ 	rc = __kfifo_get(tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*));
+-	BUG_ON(!rc);
++	if (!rc) {
++		iscsi_conn_printk(KERN_ERR, conn, "Could not allocate R2T. "
++				  "Target has sent more R2Ts than it "
++				  "negotiated for or driver has has leaked.\n");
++		return ISCSI_ERR_PROTO;
++	}
+ 
+ 	r2t->exp_statsn = rhdr->statsn;
+ 	r2t->data_length = be32_to_cpu(rhdr->data_length);
+@@ -672,9 +669,8 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
+ 	}
+ 
+ 	r2t->ttt = rhdr->ttt; /* no flip */
+-	r2t->solicit_datasn = 0;
+-
+-	iscsi_solicit_data_init(conn, task, r2t);
++	r2t->datasn = 0;
++	r2t->sent = 0;
+ 
+ 	tcp_task->exp_datasn = r2tsn + 1;
+ 	__kfifo_put(tcp_task->r2tqueue, (void*)&r2t, sizeof(void*));
+@@ -1199,9 +1195,9 @@ iscsi_tcp_xmit_qlen(struct iscsi_conn *conn)
+ 	return segment->total_copied - segment->total_size;
+ }
+ 
+-static inline int
+-iscsi_tcp_flush(struct iscsi_conn *conn)
++static int iscsi_tcp_flush(struct iscsi_task *task)
+ {
++	struct iscsi_conn *conn = task->conn;
+ 	int rc;
+ 
+ 	while (iscsi_tcp_xmit_qlen(conn)) {
+@@ -1364,14 +1360,49 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_task *task,
+ 	return 1;
+ }
+ 
++static int iscsi_tcp_pdu_init(struct iscsi_task *task,
++			      unsigned int offset, unsigned int count)
++{
++	struct iscsi_conn *conn = task->conn;
++	int err = 0;
++
++	iscsi_tcp_send_hdr_prep(conn, task->hdr, task->hdr_len);
++
++	if (!count)
++		return 0;
++
++	if (!task->sc)
++		iscsi_tcp_send_linear_data_prepare(conn, task->data, count);
++	else {
++		struct scsi_data_buffer *sdb = scsi_out(task->sc);
++
++		err = iscsi_tcp_send_data_prep(conn, sdb->table.sgl,
++					       sdb->table.nents, offset, count);
++	}
++
++	if (err) {
++		iscsi_conn_failure(conn, err);
++		return -EIO;
++	}
++	return 0;
++}
++
++static int iscsi_tcp_pdu_alloc(struct iscsi_task *task)
++{
++	struct iscsi_tcp_task *tcp_task = task->dd_data;
++
++	task->hdr = &tcp_task->hdr.hdrbuf;
++	task->hdr_max = sizeof(tcp_task->hdr) - ISCSI_DIGEST_SIZE;
++	return 0;
++}
++
+ /**
+  * iscsi_tcp_task - Initialize iSCSI SCSI_READ or SCSI_WRITE commands
+  * @conn: iscsi connection
+  * @task: scsi command task
+  * @sc: scsi command
+  **/
+-static int
+-iscsi_tcp_task_init(struct iscsi_task *task)
++static int iscsi_tcp_task_init(struct iscsi_task *task)
+ {
+ 	struct iscsi_tcp_task *tcp_task = task->dd_data;
+ 	struct iscsi_conn *conn = task->conn;
+@@ -1386,40 +1417,57 @@ iscsi_tcp_task_init(struct iscsi_task *task)
+ 		debug_scsi("mtask deq [cid %d itt 0x%x]\n", conn->id,
+ 			   task->itt);
+ 
+-		/* Prepare PDU, optionally w/ immediate data */
+-		iscsi_tcp_send_hdr_prep(conn, task->hdr, sizeof(*task->hdr));
+-
+-		/* If we have immediate data, attach a payload */
+-		if (task->data_count)
+-			iscsi_tcp_send_linear_data_prepare(conn, task->data,
+-							   task->data_count);
+-		return 0;
++		return conn->session->tt->init_pdu(task, 0, task->data_count);
+ 	}
+ 
+ 	BUG_ON(__kfifo_len(tcp_task->r2tqueue));
+-	tcp_task->sent = 0;
+ 	tcp_task->exp_datasn = 0;
+ 
+ 	/* Prepare PDU, optionally w/ immediate data */
+ 	debug_scsi("task deq [cid %d itt 0x%x imm %d unsol %d]\n",
+ 		    conn->id, task->itt, task->imm_count,
+-		    task->unsol_count);
+-	iscsi_tcp_send_hdr_prep(conn, task->hdr, task->hdr_len);
++		    task->unsol_r2t.data_length);
+ 
+-	if (!task->imm_count)
+-		return 0;
+-
+-	/* If we have immediate data, attach a payload */
+-	err = iscsi_tcp_send_data_prep(conn, scsi_out(sc)->table.sgl,
+-				       scsi_out(sc)->table.nents,
+-				       0, task->imm_count);
++	err = conn->session->tt->init_pdu(task, 0, task->imm_count);
+ 	if (err)
+ 		return err;
+-	tcp_task->sent += task->imm_count;
+ 	task->imm_count = 0;
+ 	return 0;
+ }
+ 
++static struct iscsi_r2t_info *iscsi_tcp_get_curr_r2t(struct iscsi_task *task)
++{
++	struct iscsi_session *session = task->conn->session;
++	struct iscsi_tcp_task *tcp_task = task->dd_data;
++	struct iscsi_r2t_info *r2t = NULL;
++
++	if (iscsi_task_has_unsol_data(task))
++		r2t = &task->unsol_r2t;
++	else {
++		spin_lock_bh(&session->lock);
++		if (tcp_task->r2t) {
++			r2t = tcp_task->r2t;
++			/* Continue with this R2T? */
++			if (r2t->data_length <= r2t->sent) {
++				debug_scsi("  done with r2t %p\n", r2t);
++				__kfifo_put(tcp_task->r2tpool.queue,
++					    (void *)&tcp_task->r2t,
++					    sizeof(void *));
++				tcp_task->r2t = r2t = NULL;
++			}
++		}
++
++		if (r2t == NULL) {
++			__kfifo_get(tcp_task->r2tqueue,
++				    (void *)&tcp_task->r2t, sizeof(void *));
++			r2t = tcp_task->r2t;
++		}
++		spin_unlock_bh(&session->lock);
++	}
++
++	return r2t;
++}
++
+ /*
+  * iscsi_tcp_task_xmit - xmit normal PDU task
+  * @task: iscsi command task
+@@ -1428,108 +1476,52 @@ iscsi_tcp_task_init(struct iscsi_task *task)
+  * -EAGAIN if there's still data in the queue, or != 0 for any other kind
+  * of error.
+  */
+-static int
+-iscsi_tcp_task_xmit(struct iscsi_task *task)
++static int iscsi_tcp_task_xmit(struct iscsi_task *task)
+ {
+ 	struct iscsi_conn *conn = task->conn;
+-	struct iscsi_tcp_task *tcp_task = task->dd_data;
+-	struct scsi_cmnd *sc = task->sc;
+-	struct scsi_data_buffer *sdb;
++	struct iscsi_session *session = conn->session;
++	struct iscsi_r2t_info *r2t;
+ 	int rc = 0;
+ 
+ flush:
+ 	/* Flush any pending data first. */
+-	rc = iscsi_tcp_flush(conn);
++	rc = session->tt->xmit_pdu(task);
+ 	if (rc < 0)
+ 		return rc;
+ 
+ 	/* mgmt command */
+-	if (!sc) {
++	if (!task->sc) {
+ 		if (task->hdr->itt == RESERVED_ITT)
+ 			iscsi_put_task(task);
+ 		return 0;
+ 	}
+ 
+ 	/* Are we done already? */
+-	if (sc->sc_data_direction != DMA_TO_DEVICE)
++	if (task->sc->sc_data_direction != DMA_TO_DEVICE)
+ 		return 0;
+ 
+-	sdb = scsi_out(sc);
+-	if (task->unsol_count != 0) {
+-		struct iscsi_data *hdr = &tcp_task->unsol_dtask.hdr;
+-
+-		/* Prepare a header for the unsolicited PDU.
+-		 * The amount of data we want to send will be
+-		 * in task->data_count.
+-		 * FIXME: return the data count instead.
+-		 */
+-		iscsi_prep_unsolicit_data_pdu(task, hdr);
+-
+-		debug_tcp("unsol dout [itt 0x%x doff %d dlen %d]\n",
+-				task->itt, tcp_task->sent, task->data_count);
+-
+-		iscsi_tcp_send_hdr_prep(conn, hdr, sizeof(*hdr));
+-		rc = iscsi_tcp_send_data_prep(conn, sdb->table.sgl,
+-					      sdb->table.nents, tcp_task->sent,
+-					      task->data_count);
+-		if (rc)
+-			goto fail;
+-		tcp_task->sent += task->data_count;
+-		task->unsol_count -= task->data_count;
+-		goto flush;
+-	} else {
+-		struct iscsi_session *session = conn->session;
+-		struct iscsi_r2t_info *r2t;
+-
+-		/* All unsolicited PDUs sent. Check for solicited PDUs.
+-		 */
+-		spin_lock_bh(&session->lock);
+-		r2t = tcp_task->r2t;
+-		if (r2t != NULL) {
+-			/* Continue with this R2T? */
+-			if (!iscsi_solicit_data_cont(conn, task, r2t)) {
+-				debug_scsi("  done with r2t %p\n", r2t);
+-
+-				__kfifo_put(tcp_task->r2tpool.queue,
+-					    (void*)&r2t, sizeof(void*));
+-				tcp_task->r2t = r2t = NULL;
+-			}
+-		}
+-
+-		if (r2t == NULL) {
+-			__kfifo_get(tcp_task->r2tqueue, (void*)&tcp_task->r2t,
+-				    sizeof(void*));
+-			r2t = tcp_task->r2t;
+-		}
+-		spin_unlock_bh(&session->lock);
+-
++	r2t = iscsi_tcp_get_curr_r2t(task);
++	if (r2t == NULL) {
+ 		/* Waiting for more R2Ts to arrive. */
+-		if (r2t == NULL) {
+-			debug_tcp("no R2Ts yet\n");
+-			return 0;
+-		}
++		debug_tcp("no R2Ts yet\n");
++		return 0;
++	}
+ 
+-		debug_scsi("sol dout %p [dsn %d itt 0x%x doff %d dlen %d]\n",
+-			r2t, r2t->solicit_datasn - 1, task->itt,
+-			r2t->data_offset + r2t->sent, r2t->data_count);
++	rc = conn->session->tt->alloc_pdu(task);
++	if (rc)
++		return rc;
++	iscsi_prep_data_out_pdu(task, r2t, (struct iscsi_data *) task->hdr);
+ 
+-		iscsi_tcp_send_hdr_prep(conn, &r2t->dtask.hdr,
+-					sizeof(struct iscsi_hdr));
++	debug_scsi("sol dout %p [dsn %d itt 0x%x doff %d dlen %d]\n",
++		   r2t, r2t->datasn - 1, task->hdr->itt,
++		   r2t->data_offset + r2t->sent, r2t->data_count);
+ 
+-		rc = iscsi_tcp_send_data_prep(conn, sdb->table.sgl,
+-					      sdb->table.nents,
+-					      r2t->data_offset + r2t->sent,
+-					      r2t->data_count);
+-		if (rc)
+-			goto fail;
+-		tcp_task->sent += r2t->data_count;
+-		r2t->sent += r2t->data_count;
+-		goto flush;
+-	}
+-	return 0;
+-fail:
+-	iscsi_conn_failure(conn, rc);
+-	return -EIO;
++	rc = conn->session->tt->init_pdu(task, r2t->data_offset + r2t->sent,
++					 r2t->data_count);
++	if (rc)
++		return rc;
++	r2t->sent += r2t->data_count;
++	goto flush;
+ }
+ 
+ static struct iscsi_cls_conn *
+@@ -1751,13 +1743,14 @@ iscsi_r2tpool_alloc(struct iscsi_session *session)
+ 		struct iscsi_tcp_task *tcp_task = task->dd_data;
+ 
+ 		/*
+-		 * pre-allocated x4 as much r2ts to handle race when
++		 * pre-allocated x2 as much r2ts to handle race when
+ 		 * target acks DataOut faster than we data_xmit() queues
+ 		 * could replenish r2tqueue.
+ 		 */
+ 
+ 		/* R2T pool */
+-		if (iscsi_pool_init(&tcp_task->r2tpool, session->max_r2t * 4, NULL,
++		if (iscsi_pool_init(&tcp_task->r2tpool,
++				    session->max_r2t * 2, NULL,
+ 				    sizeof(struct iscsi_r2t_info))) {
+ 			goto r2t_alloc_fail;
+ 		}
+@@ -1891,7 +1884,6 @@ iscsi_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
+ 	struct iscsi_cls_session *cls_session;
+ 	struct iscsi_session *session;
+ 	struct Scsi_Host *shost;
+-	int cmd_i;
+ 
+ 	if (ep) {
+ 		printk(KERN_ERR "iscsi_tcp: invalid ep %p.\n", ep);
+@@ -1919,14 +1911,6 @@ iscsi_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
+ 	session = cls_session->dd_data;
+ 
+ 	shost->can_queue = session->scsi_cmds_max;
+-	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
+-		struct iscsi_task *task = session->cmds[cmd_i];
+-		struct iscsi_tcp_task *tcp_task = task->dd_data;
+-
+-		task->hdr = &tcp_task->hdr.cmd_hdr;
+-		task->hdr_max = sizeof(tcp_task->hdr) - ISCSI_DIGEST_SIZE;
+-	}
+-
+ 	if (iscsi_r2tpool_alloc(session))
+ 		goto remove_session;
+ 	return cls_session;
+@@ -2026,9 +2010,14 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 	/* IO */
+ 	.send_pdu		= iscsi_conn_send_pdu,
+ 	.get_stats		= iscsi_conn_get_stats,
++	/* iscsi task/cmd helpers */
+ 	.init_task		= iscsi_tcp_task_init,
+ 	.xmit_task		= iscsi_tcp_task_xmit,
+ 	.cleanup_task		= iscsi_tcp_cleanup_task,
++	/* low level pdu helpers */
++	.xmit_pdu		= iscsi_tcp_flush,
++	.init_pdu		= iscsi_tcp_pdu_init,
++	.alloc_pdu		= iscsi_tcp_pdu_alloc,
+ 	/* recovery */
+ 	.session_recovery_timedout = iscsi_session_recovery_timedout,
+ };
+diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
+index 498d8ca39848..0ed47733c75f 100644
+--- a/drivers/scsi/iscsi_tcp.h
++++ b/drivers/scsi/iscsi_tcp.h
+@@ -98,25 +98,9 @@ struct iscsi_tcp_conn {
+ 	ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
+ };
+ 
+-struct iscsi_data_task {
+-	struct iscsi_data	hdr;			/* PDU */
+-	char			hdrext[ISCSI_DIGEST_SIZE];/* Header-Digest */
+-};
+-
+-struct iscsi_r2t_info {
+-	__be32			ttt;		/* copied from R2T */
+-	__be32			exp_statsn;	/* copied from R2T */
+-	uint32_t		data_length;	/* copied from R2T */
+-	uint32_t		data_offset;	/* copied from R2T */
+-	int			sent;		/* R2T sequence progress */
+-	int			data_count;	/* DATA-Out payload progress */
+-	int			solicit_datasn;
+-	struct iscsi_data_task	dtask;		/* Data-Out header buf */
+-};
+-
+ struct iscsi_tcp_task {
+ 	struct iscsi_hdr_buff {
+-		struct iscsi_cmd	cmd_hdr;
++		struct iscsi_hdr	hdrbuf;
+ 		char			hdrextbuf[ISCSI_MAX_AHS_SIZE +
+ 		                                  ISCSI_DIGEST_SIZE];
+ 	} hdr;
+@@ -124,10 +108,9 @@ struct iscsi_tcp_task {
+ 	int			sent;
+ 	uint32_t		exp_datasn;	/* expected target's R2TSN/DataSN */
+ 	int			data_offset;
+-	struct iscsi_r2t_info	*r2t;		/* in progress R2T    */
++	struct iscsi_r2t_info	*r2t;		/* in progress solict R2T */
+ 	struct iscsi_pool	r2tpool;
+ 	struct kfifo		*r2tqueue;
+-	struct iscsi_data_task	unsol_dtask;	/* Data-Out header buf */
+ };
+ 
+ #endif /* ISCSI_H */

commit 0f9c7449ce050759d10424048b96d1bd0d59dcc1
+Author: Mike Christie 
+Date:   Tue Dec 2 00:32:06 2008 -0600
+
+    [SCSI] iser: convert iser to new alloc_pdu api
+    
+    This just converts iser to new alloc_pdu api. It still
+    preallocates the pdu, so there is no difference.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 1e5b6446231d..78bf5e4538cb 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -119,6 +119,14 @@ iscsi_iser_recv(struct iscsi_conn *conn,
+ 	iscsi_conn_failure(conn, rc);
+ }
+ 
++static int iscsi_iser_pdu_alloc(struct iscsi_task *task)
++{
++	struct iscsi_iser_task *iser_task = task->dd_data;
++
++	task->hdr = (struct iscsi_hdr *)&iser_task->desc.iscsi_header;
++	task->hdr_max = sizeof(iser_task->desc.iscsi_header);
++	return 0;
++}
+ 
+ /**
+  * iscsi_iser_task_init - Initialize task
+@@ -180,25 +188,26 @@ static int
+ iscsi_iser_task_xmit_unsol_data(struct iscsi_conn *conn,
+ 				 struct iscsi_task *task)
+ {
+-	struct iscsi_data  hdr;
++	struct iscsi_r2t_info *r2t = &task->unsol_r2t;
++	struct iscsi_data hdr;
+ 	int error = 0;
+ 
+ 	/* Send data-out PDUs while there's still unsolicited data to send */
+-	while (task->unsol_count > 0) {
+-		iscsi_prep_unsolicit_data_pdu(task, &hdr);
++	while (iscsi_task_has_unsol_data(task)) {
++		iscsi_prep_data_out_pdu(task, r2t, &hdr);
+ 		debug_scsi("Sending data-out: itt 0x%x, data count %d\n",
+-			   hdr.itt, task->data_count);
++			   hdr.itt, r2t->data_count);
+ 
+ 		/* the buffer description has been passed with the command */
+ 		/* Send the command */
+ 		error = iser_send_data_out(conn, task, &hdr);
+ 		if (error) {
+-			task->unsol_datasn--;
++			r2t->datasn--;
+ 			goto iscsi_iser_task_xmit_unsol_data_exit;
+ 		}
+-		task->unsol_count -= task->data_count;
++		r2t->sent += r2t->data_count;
+ 		debug_scsi("Need to send %d more as data-out PDUs\n",
+-			   task->unsol_count);
++			   r2t->data_length - r2t->sent);
+ 	}
+ 
+ iscsi_iser_task_xmit_unsol_data_exit:
+@@ -220,7 +229,7 @@ iscsi_iser_task_xmit(struct iscsi_task *task)
+ 
+ 		debug_scsi("cmd [itt %x total %d imm %d unsol_data %d\n",
+ 			   task->itt, scsi_bufflen(task->sc),
+-			   task->imm_count, task->unsol_count);
++			   task->imm_count, task->unsol_r2t.data_length);
+ 	}
+ 
+ 	debug_scsi("task deq [cid %d itt 0x%x]\n",
+@@ -235,7 +244,7 @@ iscsi_iser_task_xmit(struct iscsi_task *task)
+ 	}
+ 
+ 	/* Send unsolicited data-out PDU(s) if necessary */
+-	if (task->unsol_count)
++	if (iscsi_task_has_unsol_data(task))
+ 		error = iscsi_iser_task_xmit_unsol_data(conn, task);
+ 
+  iscsi_iser_task_xmit_exit:
+@@ -244,13 +253,15 @@ iscsi_iser_task_xmit(struct iscsi_task *task)
+ 	return error;
+ }
+ 
+-static void
+-iscsi_iser_cleanup_task(struct iscsi_conn *conn, struct iscsi_task *task)
++static void iscsi_iser_cleanup_task(struct iscsi_task *task)
+ {
+ 	struct iscsi_iser_task *iser_task = task->dd_data;
+ 
+-	/* mgmt tasks do not need special cleanup */
+-	if (!task->sc)
++	/*
++	 * mgmt tasks do not need special cleanup and we do not
++	 * allocate anything in the init task callout
++	 */
++	if (!task->sc || task->state == ISCSI_TASK_PENDING)
+ 		return;
+ 
+ 	if (iser_task->status == ISER_TASK_STATUS_STARTED) {
+@@ -391,9 +402,6 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep,
+ 	struct iscsi_cls_session *cls_session;
+ 	struct iscsi_session *session;
+ 	struct Scsi_Host *shost;
+-	int i;
+-	struct iscsi_task *task;
+-	struct iscsi_iser_task *iser_task;
+ 	struct iser_conn *ib_conn;
+ 
+ 	shost = iscsi_host_alloc(&iscsi_iser_sht, 0, ISCSI_MAX_CMD_PER_LUN);
+@@ -430,13 +438,6 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep,
+ 	session = cls_session->dd_data;
+ 
+ 	shost->can_queue = session->scsi_cmds_max;
+-	/* libiscsi setup itts, data and pool so just set desc fields */
+-	for (i = 0; i < session->cmds_max; i++) {
+-		task = session->cmds[i];
+-		iser_task = task->dd_data;
+-		task->hdr = (struct iscsi_cmd *)&iser_task->desc.iscsi_header;
+-		task->hdr_max = sizeof(iser_task->desc.iscsi_header);
+-	}
+ 	return cls_session;
+ 
+ remove_host:
+@@ -652,6 +653,7 @@ static struct iscsi_transport iscsi_iser_transport = {
+ 	.init_task		= iscsi_iser_task_init,
+ 	.xmit_task		= iscsi_iser_task_xmit,
+ 	.cleanup_task		= iscsi_iser_cleanup_task,
++	.alloc_pdu		= iscsi_iser_pdu_alloc,
+ 	/* recovery */
+ 	.session_recovery_timedout = iscsi_session_recovery_timedout,
+ 
+diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
+index ed1aff21b7ea..e209cb8dd948 100644
+--- a/drivers/infiniband/ulp/iser/iser_initiator.c
++++ b/drivers/infiniband/ulp/iser/iser_initiator.c
+@@ -353,8 +353,7 @@ int iser_send_command(struct iscsi_conn *conn,
+ 	unsigned long edtl;
+ 	int err = 0;
+ 	struct iser_data_buf *data_buf;
+-
+-	struct iscsi_cmd *hdr =  task->hdr;
++	struct iscsi_cmd *hdr =  (struct iscsi_cmd *)task->hdr;
+ 	struct scsi_cmnd *sc  =  task->sc;
+ 
+ 	if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) {
+@@ -393,7 +392,7 @@ int iser_send_command(struct iscsi_conn *conn,
+ 		err = iser_prepare_write_cmd(task,
+ 					     task->imm_count,
+ 				             task->imm_count +
+-					     task->unsol_count,
++					     task->unsol_r2t.data_length,
+ 					     edtl);
+ 		if (err)
+ 			goto send_command_error;

commit 577577da6d197ea3dcf3ee19c4f902fbd3a9390a
+Author: Mike Christie 
+Date:   Tue Dec 2 00:32:05 2008 -0600
+
+    [SCSI] libiscsi: prepare libiscsi for new offload engines by modifying unsol data code
+    
+    cxgb3i offloads data transfers. It does not offload the entire scsi/iscsi
+    procssing like qla4xxx and it does not offload the iscsi sequence
+    processing like how bnx2i does. cxgb3i relies on iscsi_tcp for the
+    seqeunce handling so this changes how we transfer unsolicitied data by
+    adding a common r2t struct and helpers.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 3fdee7370ccc..80cbcdce7fa3 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -88,34 +88,47 @@ iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_update_cmdsn);
+ 
+-void iscsi_prep_unsolicit_data_pdu(struct iscsi_task *task,
+-				   struct iscsi_data *hdr)
++/**
++ * iscsi_prep_data_out_pdu - initialize Data-Out
++ * @task: scsi command task
++ * @r2t: R2T info
++ * @hdr: iscsi data in pdu
++ *
++ * Notes:
++ *	Initialize Data-Out within this R2T sequence and finds
++ *	proper data_offset within this SCSI command.
++ *
++ *	This function is called with connection lock taken.
++ **/
++void iscsi_prep_data_out_pdu(struct iscsi_task *task, struct iscsi_r2t_info *r2t,
++			   struct iscsi_data *hdr)
+ {
+ 	struct iscsi_conn *conn = task->conn;
++	unsigned int left = r2t->data_length - r2t->sent;
++
++	task->hdr_len = sizeof(struct iscsi_data);
+ 
+ 	memset(hdr, 0, sizeof(struct iscsi_data));
+-	hdr->ttt = cpu_to_be32(ISCSI_RESERVED_TAG);
+-	hdr->datasn = cpu_to_be32(task->unsol_datasn);
+-	task->unsol_datasn++;
++	hdr->ttt = r2t->ttt;
++	hdr->datasn = cpu_to_be32(r2t->datasn);
++	r2t->datasn++;
+ 	hdr->opcode = ISCSI_OP_SCSI_DATA_OUT;
+-	memcpy(hdr->lun, task->hdr->lun, sizeof(hdr->lun));
+-
+-	hdr->itt = task->hdr->itt;
+-	hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
+-	hdr->offset = cpu_to_be32(task->unsol_offset);
+-
+-	if (task->unsol_count > conn->max_xmit_dlength) {
++	memcpy(hdr->lun, task->lun, sizeof(hdr->lun));
++	hdr->itt = task->hdr_itt;
++	hdr->exp_statsn = r2t->exp_statsn;
++	hdr->offset = cpu_to_be32(r2t->data_offset + r2t->sent);
++	if (left > conn->max_xmit_dlength) {
+ 		hton24(hdr->dlength, conn->max_xmit_dlength);
+-		task->data_count = conn->max_xmit_dlength;
+-		task->unsol_offset += task->data_count;
++		r2t->data_count = conn->max_xmit_dlength;
+ 		hdr->flags = 0;
+ 	} else {
+-		hton24(hdr->dlength, task->unsol_count);
+-		task->data_count = task->unsol_count;
++		hton24(hdr->dlength, left);
++		r2t->data_count = left;
+ 		hdr->flags = ISCSI_FLAG_CMD_FINAL;
+ 	}
++	conn->dataout_pdus_cnt++;
+ }
+-EXPORT_SYMBOL_GPL(iscsi_prep_unsolicit_data_pdu);
++EXPORT_SYMBOL_GPL(iscsi_prep_data_out_pdu);
+ 
+ static int iscsi_add_hdr(struct iscsi_task *task, unsigned len)
+ {
+@@ -206,11 +219,17 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
+ {
+ 	struct iscsi_conn *conn = task->conn;
+ 	struct iscsi_session *session = conn->session;
+-	struct iscsi_cmd *hdr = task->hdr;
+ 	struct scsi_cmnd *sc = task->sc;
++	struct iscsi_cmd *hdr;
+ 	unsigned hdrlength, cmd_len;
+ 	int rc;
+ 
++	rc = conn->session->tt->alloc_pdu(task);
++	if (rc)
++		return rc;
++	hdr = (struct iscsi_cmd *) task->hdr;
++	memset(hdr, 0, sizeof(*hdr));
++
+ 	task->hdr_len = 0;
+ 	rc = iscsi_add_hdr(task, sizeof(*hdr));
+ 	if (rc)
+@@ -218,8 +237,9 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
+ 	hdr->opcode = ISCSI_OP_SCSI_CMD;
+ 	hdr->flags = ISCSI_ATTR_SIMPLE;
+ 	int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
+-	hdr->itt = build_itt(task->itt, session->age);
+-	hdr->cmdsn = cpu_to_be32(session->cmdsn);
++	memcpy(task->lun, hdr->lun, sizeof(task->lun));
++	hdr->itt = task->hdr_itt = build_itt(task->itt, session->age);
++	hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn);
+ 	session->cmdsn++;
+ 	hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
+ 	cmd_len = sc->cmd_len;
+@@ -242,6 +262,8 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
+ 	}
+ 	if (sc->sc_data_direction == DMA_TO_DEVICE) {
+ 		unsigned out_len = scsi_out(sc)->length;
++		struct iscsi_r2t_info *r2t = &task->unsol_r2t;
++
+ 		hdr->data_length = cpu_to_be32(out_len);
+ 		hdr->flags |= ISCSI_FLAG_CMD_WRITE;
+ 		/*
+@@ -254,13 +276,11 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
+ 		 *			without	R2T ack right after
+ 		 *			immediate data
+ 		 *
+-		 *	r2t_data_count	bytes to be sent via R2T ack's
++		 *	r2t data_length bytes to be sent via R2T ack's
+ 		 *
+ 		 *      pad_count       bytes to be sent as zero-padding
+ 		 */
+-		task->unsol_count = 0;
+-		task->unsol_offset = 0;
+-		task->unsol_datasn = 0;
++		memset(r2t, 0, sizeof(*r2t));
+ 
+ 		if (session->imm_data_en) {
+ 			if (out_len >= session->first_burst)
+@@ -274,12 +294,14 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
+ 			zero_data(hdr->dlength);
+ 
+ 		if (!session->initial_r2t_en) {
+-			task->unsol_count = min(session->first_burst, out_len)
+-							     - task->imm_count;
+-			task->unsol_offset = task->imm_count;
++			r2t->data_length = min(session->first_burst, out_len) -
++					       task->imm_count;
++			r2t->data_offset = task->imm_count;
++			r2t->ttt = cpu_to_be32(ISCSI_RESERVED_TAG);
++			r2t->exp_statsn = cpu_to_be32(conn->exp_statsn);
+ 		}
+ 
+-		if (!task->unsol_count)
++		if (!task->unsol_r2t.data_length)
+ 			/* No unsolicit Data-Out's */
+ 			hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+ 	} else {
+@@ -300,8 +322,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
+ 	WARN_ON(hdrlength >= 256);
+ 	hdr->hlength = hdrlength & 0xFF;
+ 
+-	if (conn->session->tt->init_task &&
+-	    conn->session->tt->init_task(task))
++	if (session->tt->init_task && session->tt->init_task(task))
+ 		return -EIO;
+ 
+ 	task->state = ISCSI_TASK_RUNNING;
+@@ -332,6 +353,7 @@ static void iscsi_complete_command(struct iscsi_task *task)
+ 	struct iscsi_session *session = conn->session;
+ 	struct scsi_cmnd *sc = task->sc;
+ 
++	session->tt->cleanup_task(task);
+ 	list_del_init(&task->running);
+ 	task->state = ISCSI_TASK_COMPLETED;
+ 	task->sc = NULL;
+@@ -402,8 +424,6 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_task *task,
+ 		 * the cmd in the sequencing
+ 		 */
+ 		conn->session->queued_cmdsn--;
+-	else
+-		conn->session->tt->cleanup_task(conn, task);
+ 
+ 	sc->result = err;
+ 	if (!scsi_bidi_cmnd(sc))
+@@ -423,7 +443,7 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn,
+ 				struct iscsi_task *task)
+ {
+ 	struct iscsi_session *session = conn->session;
+-	struct iscsi_hdr *hdr = (struct iscsi_hdr *)task->hdr;
++	struct iscsi_hdr *hdr = task->hdr;
+ 	struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr;
+ 
+ 	if (conn->session->state == ISCSI_STATE_LOGGING_OUT)
+@@ -456,6 +476,7 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn,
+ 	if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT)
+ 		session->state = ISCSI_STATE_LOGGING_OUT;
+ 
++	task->state = ISCSI_TASK_RUNNING;
+ 	list_move_tail(&task->running, &conn->mgmt_run_list);
+ 	debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n",
+ 		   hdr->opcode & ISCSI_OPCODE_MASK, hdr->itt,
+@@ -505,23 +526,38 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	} else
+ 		task->data_count = 0;
+ 
++	if (conn->session->tt->alloc_pdu(task)) {
++		iscsi_conn_printk(KERN_ERR, conn, "Could not allocate "
++				 "pdu for mgmt task.\n");
++		goto requeue_task;
++	}
++	task->hdr_len = sizeof(struct iscsi_hdr);
++
+ 	memcpy(task->hdr, hdr, sizeof(struct iscsi_hdr));
+ 	INIT_LIST_HEAD(&task->running);
+ 	list_add_tail(&task->running, &conn->mgmtqueue);
+ 
+ 	if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) {
+-		if (iscsi_prep_mgmt_task(conn, task)) {
+-			__iscsi_put_task(task);
+-			return NULL;
+-		}
++		if (iscsi_prep_mgmt_task(conn, task))
++			goto free_task;
+ 
+ 		if (session->tt->xmit_task(task))
+-			task = NULL;
++			goto free_task;
+ 
+ 	} else
+ 		scsi_queue_work(conn->session->host, &conn->xmitwork);
+ 
+ 	return task;
++
++free_task:
++	__iscsi_put_task(task);
++	return NULL;
++
++requeue_task:
++	if (task != conn->login_task)
++		__kfifo_put(session->cmdpool.queue, (void*)&task,
++			    sizeof(void*));
++	return NULL;
+ }
+ 
+ int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
+@@ -1136,8 +1172,13 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 			fail_command(conn, conn->task, DID_IMM_RETRY << 16);
+ 			continue;
+ 		}
+-		if (iscsi_prep_scsi_cmd_pdu(conn->task)) {
+-			fail_command(conn, conn->task, DID_ABORT << 16);
++		rc = iscsi_prep_scsi_cmd_pdu(conn->task);
++		if (rc) {
++			if (rc == -ENOMEM) {
++				conn->task = NULL;
++				goto again;
++			} else
++				fail_command(conn, conn->task, DID_ABORT << 16);
+ 			continue;
+ 		}
+ 		rc = iscsi_xmit_task(conn);
+@@ -1195,6 +1236,26 @@ static void iscsi_xmitworker(struct work_struct *work)
+ 	} while (rc >= 0 || rc == -EAGAIN);
+ }
+ 
++static inline struct iscsi_task *iscsi_alloc_task(struct iscsi_conn *conn,
++						  struct scsi_cmnd *sc)
++{
++	struct iscsi_task *task;
++
++	if (!__kfifo_get(conn->session->cmdpool.queue,
++			 (void *) &task, sizeof(void *)))
++		return NULL;
++
++	sc->SCp.phase = conn->session->age;
++	sc->SCp.ptr = (char *) task;
++
++	atomic_set(&task->refcount, 1);
++	task->state = ISCSI_TASK_PENDING;
++	task->conn = conn;
++	task->sc = sc;
++	INIT_LIST_HEAD(&task->running);
++	return task;
++}
++
+ enum {
+ 	FAILURE_BAD_HOST = 1,
+ 	FAILURE_SESSION_FAILED,
+@@ -1281,33 +1342,27 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 		goto reject;
+ 	}
+ 
+-	if (!__kfifo_get(session->cmdpool.queue, (void*)&task,
+-			 sizeof(void*))) {
++	task = iscsi_alloc_task(conn, sc);
++	if (!task) {
+ 		reason = FAILURE_OOM;
+ 		goto reject;
+ 	}
+-	sc->SCp.phase = session->age;
+-	sc->SCp.ptr = (char *)task;
+-
+-	atomic_set(&task->refcount, 1);
+-	task->state = ISCSI_TASK_PENDING;
+-	task->conn = conn;
+-	task->sc = sc;
+-	INIT_LIST_HEAD(&task->running);
+ 	list_add_tail(&task->running, &conn->xmitqueue);
+ 
+ 	if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) {
+-		if (iscsi_prep_scsi_cmd_pdu(task)) {
+-			sc->result = DID_ABORT << 16;
+-			sc->scsi_done = NULL;
+-			iscsi_complete_command(task);
+-			goto fault;
++		reason = iscsi_prep_scsi_cmd_pdu(task);
++		if (reason) {
++			if (reason == -ENOMEM) {
++				reason = FAILURE_OOM;
++				goto prepd_reject;
++			} else {
++				sc->result = DID_ABORT << 16;
++				goto prepd_fault;
++			}
+ 		}
+ 		if (session->tt->xmit_task(task)) {
+-			sc->scsi_done = NULL;
+-			iscsi_complete_command(task);
+ 			reason = FAILURE_SESSION_NOT_READY;
+-			goto reject;
++			goto prepd_reject;
+ 		}
+ 	} else
+ 		scsi_queue_work(session->host, &conn->xmitwork);
+@@ -1317,12 +1372,18 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 	spin_lock(host->host_lock);
+ 	return 0;
+ 
++prepd_reject:
++	sc->scsi_done = NULL;
++	iscsi_complete_command(task);
+ reject:
+ 	spin_unlock(&session->lock);
+ 	debug_scsi("cmd 0x%x rejected (%d)\n", sc->cmnd[0], reason);
+ 	spin_lock(host->host_lock);
+ 	return SCSI_MLQUEUE_TARGET_BUSY;
+ 
++prepd_fault:
++	sc->scsi_done = NULL;
++	iscsi_complete_command(task);
+ fault:
+ 	spin_unlock(&session->lock);
+ 	debug_scsi("iscsi: cmd 0x%x is not queued (%d)\n", sc->cmnd[0], reason);
+@@ -1634,9 +1695,9 @@ static void iscsi_prep_abort_task_pdu(struct iscsi_task *task,
+ 	hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE;
+ 	hdr->flags = ISCSI_TM_FUNC_ABORT_TASK & ISCSI_FLAG_TM_FUNC_MASK;
+ 	hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+-	memcpy(hdr->lun, task->hdr->lun, sizeof(hdr->lun));
+-	hdr->rtt = task->hdr->itt;
+-	hdr->refcmdsn = task->hdr->cmdsn;
++	memcpy(hdr->lun, task->lun, sizeof(hdr->lun));
++	hdr->rtt = task->hdr_itt;
++	hdr->refcmdsn = task->cmdsn;
+ }
+ 
+ int iscsi_eh_abort(struct scsi_cmnd *sc)
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 61e53f14f7e1..51500573c0b8 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -93,24 +93,38 @@ enum {
+ 	ISCSI_TASK_RUNNING,
+ };
+ 
++struct iscsi_r2t_info {
++	__be32			ttt;		/* copied from R2T */
++	__be32			exp_statsn;	/* copied from R2T */
++	uint32_t		data_length;	/* copied from R2T */
++	uint32_t		data_offset;	/* copied from R2T */
++	int			data_count;	/* DATA-Out payload progress */
++	int			datasn;
++	/* LLDs should set/update these values */
++	int			sent;		/* R2T sequence progress */
++};
++
+ struct iscsi_task {
+ 	/*
+ 	 * Because LLDs allocate their hdr differently, this is a pointer
+ 	 * and length to that storage. It must be setup at session
+ 	 * creation time.
+ 	 */
+-	struct iscsi_cmd	*hdr;
++	struct iscsi_hdr	*hdr;
+ 	unsigned short		hdr_max;
+ 	unsigned short		hdr_len;	/* accumulated size of hdr used */
++	/* copied values in case we need to send tmfs */
++	itt_t			hdr_itt;
++	__be32			cmdsn;
++	uint8_t			lun[8];
++
+ 	int			itt;		/* this ITT */
+ 
+-	uint32_t		unsol_datasn;
+ 	unsigned		imm_count;	/* imm-data (bytes)   */
+-	unsigned		unsol_count;	/* unsolicited (bytes)*/
+ 	/* offset in unsolicited stream (bytes); */
+-	unsigned		unsol_offset;
+-	unsigned		data_count;	/* remaining Data-Out */
++	struct iscsi_r2t_info	unsol_r2t;
+ 	char			*data;		/* mgmt payload */
++	unsigned		data_count;
+ 	struct scsi_cmnd	*sc;		/* associated SCSI cmd*/
+ 	struct iscsi_conn	*conn;		/* used connection    */
+ 
+@@ -121,6 +135,11 @@ struct iscsi_task {
+ 	void			*dd_data;	/* driver/transport data */
+ };
+ 
++static inline int iscsi_task_has_unsol_data(struct iscsi_task *task)
++{
++	return task->unsol_r2t.data_length > task->unsol_r2t.sent;
++}
++
+ static inline void* iscsi_next_hdr(struct iscsi_task *task)
+ {
+ 	return (void*)task->hdr + task->hdr_len;
+@@ -376,8 +395,9 @@ extern void iscsi_suspend_tx(struct iscsi_conn *conn);
+  * pdu and task processing
+  */
+ extern void iscsi_update_cmdsn(struct iscsi_session *, struct iscsi_nopin *);
+-extern void iscsi_prep_unsolicit_data_pdu(struct iscsi_task *,
+-					struct iscsi_data *hdr);
++extern void iscsi_prep_data_out_pdu(struct iscsi_task *task,
++				    struct iscsi_r2t_info *r2t,
++				    struct iscsi_data *hdr);
+ extern int iscsi_conn_send_pdu(struct iscsi_cls_conn *, struct iscsi_hdr *,
+ 				char *, uint32_t);
+ extern int iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *,
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index c667cc396545..c928234c018f 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -113,10 +113,15 @@ struct iscsi_transport {
+ 			 char *data, uint32_t data_size);
+ 	void (*get_stats) (struct iscsi_cls_conn *conn,
+ 			   struct iscsi_stats *stats);
++
+ 	int (*init_task) (struct iscsi_task *task);
+ 	int (*xmit_task) (struct iscsi_task *task);
+-	void (*cleanup_task) (struct iscsi_conn *conn,
+-				  struct iscsi_task *task);
++	void (*cleanup_task) (struct iscsi_task *task);
++
++	int (*alloc_pdu) (struct iscsi_task *task);
++	int (*xmit_pdu) (struct iscsi_task *task);
++	int (*init_pdu) (struct iscsi_task *task, unsigned int offset,
++			 unsigned int count);
+ 	void (*session_recovery_timedout) (struct iscsi_cls_session *session);
+ 	struct iscsi_endpoint *(*ep_connect) (struct sockaddr *dst_addr,
+ 					      int non_blocking);

commit 63c62f1cb980241513c82cacd5b9f878527c6647
+Author: Mike Christie 
+Date:   Tue Dec 2 00:32:04 2008 -0600
+
+    [SCSI] iscsi_tcp: prepare helpers for LLDs that can offload some operations
+    
+    cxgb3i is unlike qla4xxx and bnx2i in that it does not offload entire
+    scsi commands or iscsi sequences. Instead it only offloads the transfer
+    of a ISCSI DATA_IN pdu's data, the digests and padding. This patch fixes up the
+    iscsi tcp recv path so that it exports its skb recv processing so
+    cxgb3i and other drivers can call them. All they have to do is pass
+    the function the skb with the hdr or data pdu header and this function
+    will do the rest.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index e11bce6ab63c..464de780d953 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -486,7 +486,8 @@ iscsi_tcp_data_recv_prep(struct iscsi_tcp_conn *tcp_conn)
+ 	struct iscsi_conn *conn = tcp_conn->iscsi_conn;
+ 	struct hash_desc *rx_hash = NULL;
+ 
+-	if (conn->datadgst_en)
++	if (conn->datadgst_en &
++	    !(conn->session->tt->caps & CAP_DIGEST_OFFLOAD))
+ 		rx_hash = &tcp_conn->rx_hash;
+ 
+ 	iscsi_segment_init_linear(&tcp_conn->in.segment,
+@@ -774,7 +775,8 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 			 * we move on to the next scatterlist entry and
+ 			 * update the digest per-entry.
+ 			 */
+-			if (conn->datadgst_en)
++			if (conn->datadgst_en &&
++			    !(conn->session->tt->caps & CAP_DIGEST_OFFLOAD))
+ 				rx_hash = &tcp_conn->rx_hash;
+ 
+ 			debug_tcp("iscsi_tcp_begin_data_in(%p, offset=%d, "
+@@ -902,34 +904,52 @@ iscsi_tcp_hdr_recv_done(struct iscsi_tcp_conn *tcp_conn,
+ 	 * and go back for more. */
+ 	if (conn->hdrdgst_en) {
+ 		if (segment->digest_len == 0) {
++			/*
++			 * Even if we offload the digest processing we
++			 * splice it in so we can increment the skb/segment
++			 * counters in preparation for the data segment.
++			 */
+ 			iscsi_tcp_segment_splice_digest(segment,
+ 							segment->recv_digest);
+ 			return 0;
+ 		}
+-		iscsi_tcp_dgst_header(&tcp_conn->rx_hash, hdr,
+-				      segment->total_copied - ISCSI_DIGEST_SIZE,
+-				      segment->digest);
+ 
+-		if (!iscsi_tcp_dgst_verify(tcp_conn, segment))
+-			return ISCSI_ERR_HDR_DGST;
++		if (!(conn->session->tt->caps & CAP_DIGEST_OFFLOAD)) {
++			iscsi_tcp_dgst_header(&tcp_conn->rx_hash, hdr,
++				segment->total_copied - ISCSI_DIGEST_SIZE,
++				segment->digest);
++
++			if (!iscsi_tcp_dgst_verify(tcp_conn, segment))
++				return ISCSI_ERR_HDR_DGST;
++		}
+ 	}
+ 
+ 	tcp_conn->in.hdr = hdr;
+ 	return iscsi_tcp_hdr_dissect(conn, hdr);
+ }
+ 
++inline int iscsi_tcp_recv_segment_is_hdr(struct iscsi_tcp_conn *tcp_conn)
++{
++	return tcp_conn->in.segment.done == iscsi_tcp_hdr_recv_done;
++}
++
++enum {
++	ISCSI_TCP_SEGMENT_DONE,		/* curr seg has been processed */
++	ISCSI_TCP_SKB_DONE,		/* skb is out of data */
++	ISCSI_TCP_CONN_ERR,		/* iscsi layer has fired a conn err */
++	ISCSI_TCP_SUSPENDED,		/* conn is suspended */
++};
++
+ /**
+- * iscsi_tcp_recv - TCP receive in sendfile fashion
+- * @rd_desc: read descriptor
+- * @skb: socket buffer
++ * iscsi_tcp_recv_skb - Process skb
++ * @conn: iscsi connection
++ * @skb: network buffer with header and/or data segment
+  * @offset: offset in skb
+- * @len: skb->len - offset
+- **/
+-static int
+-iscsi_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+-	       unsigned int offset, size_t len)
++ * @offload: bool indicating if transfer was offloaded
++ */
++int iscsi_tcp_recv_skb(struct iscsi_conn *conn, struct sk_buff *skb,
++		       unsigned int offset, bool offloaded, int *status)
+ {
+-	struct iscsi_conn *conn = rd_desc->arg.data;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	struct iscsi_segment *segment = &tcp_conn->in.segment;
+ 	struct skb_seq_state seq;
+@@ -940,9 +960,15 @@ iscsi_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 
+ 	if (unlikely(conn->suspend_rx)) {
+ 		debug_tcp("conn %d Rx suspended!\n", conn->id);
++		*status = ISCSI_TCP_SUSPENDED;
+ 		return 0;
+ 	}
+ 
++	if (offloaded) {
++		segment->total_copied = segment->total_size;
++		goto segment_done;
++	}
++
+ 	skb_prepare_seq_read(skb, offset, skb->len, &seq);
+ 	while (1) {
+ 		unsigned int avail;
+@@ -952,7 +978,9 @@ iscsi_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 		if (avail == 0) {
+ 			debug_tcp("no more data avail. Consumed %d\n",
+ 				  consumed);
+-			break;
++			*status = ISCSI_TCP_SKB_DONE;
++			skb_abort_seq_read(&seq);
++			goto skb_done;
+ 		}
+ 		BUG_ON(segment->copied >= segment->size);
+ 
+@@ -962,25 +990,55 @@ iscsi_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 		consumed += rc;
+ 
+ 		if (segment->total_copied >= segment->total_size) {
+-			debug_tcp("segment done\n");
+-			rc = segment->done(tcp_conn, segment);
+-			if (rc != 0) {
+-				skb_abort_seq_read(&seq);
+-				goto error;
+-			}
+-
+-			/* The done() functions sets up the
+-			 * next segment. */
++			skb_abort_seq_read(&seq);
++			goto segment_done;
+ 		}
+ 	}
+-	skb_abort_seq_read(&seq);
++
++segment_done:
++	*status = ISCSI_TCP_SEGMENT_DONE;
++	debug_tcp("segment done\n");
++	rc = segment->done(tcp_conn, segment);
++	if (rc != 0) {
++		*status = ISCSI_TCP_CONN_ERR;
++		debug_tcp("Error receiving PDU, errno=%d\n", rc);
++		iscsi_conn_failure(conn, rc);
++		return 0;
++	}
++	/* The done() functions sets up the next segment. */
++
++skb_done:
+ 	conn->rxdata_octets += consumed;
+ 	return consumed;
++}
++EXPORT_SYMBOL_GPL(iscsi_tcp_recv_skb);
+ 
+-error:
+-	debug_tcp("Error receiving PDU, errno=%d\n", rc);
+-	iscsi_conn_failure(conn, rc);
+-	return 0;
++/**
++ * iscsi_tcp_recv - TCP receive in sendfile fashion
++ * @rd_desc: read descriptor
++ * @skb: socket buffer
++ * @offset: offset in skb
++ * @len: skb->len - offset
++ **/
++static int
++iscsi_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
++	       unsigned int offset, size_t len)
++{
++	struct iscsi_conn *conn = rd_desc->arg.data;
++	unsigned int consumed, total_consumed = 0;
++	int status;
++
++	debug_tcp("in %d bytes\n", skb->len - offset);
++
++	do {
++		status = 0;
++		consumed = iscsi_tcp_recv_skb(conn, skb, offset, 0, &status);
++		offset += consumed;
++		total_consumed += consumed;
++	} while (consumed != 0 && status != ISCSI_TCP_SKB_DONE);
++
++	debug_tcp("read %d bytes status %d\n", skb->len - offset, status);
++	return total_consumed;
+ }
+ 
+ static void
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index 0c9514de5df7..8e008c96e795 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -333,8 +333,9 @@ enum iscsi_host_param {
+ #define CAP_TEXT_NEGO		0x80
+ #define CAP_MARKERS		0x100
+ #define CAP_FW_DB		0x200
+-#define CAP_SENDTARGETS_OFFLOAD	0x400
+-#define CAP_DATA_PATH_OFFLOAD	0x800
++#define CAP_SENDTARGETS_OFFLOAD	0x400	/* offload discovery process */
++#define CAP_DATA_PATH_OFFLOAD	0x800	/* offload entire IO path */
++#define CAP_DIGEST_OFFLOAD	0x1000	/* offload hdr and data digests */
+ 
+ /*
+  * These flags describes reason of stop_conn() call

commit d3acf0226debeae22d87808f8f298386bd08e391
+Author: Mike Christie 
+Date:   Mon Dec 1 12:13:00 2008 -0600
+
+    [SCSI] libiscsi REGRESSION: fix passthrough support with older iscsi tools
+    
+    This regression was added in 2.6.27, when the mtask and ctask were
+    merged into the the common task struct. The patch applies to
+    scsi-rc-fixes, but also applies to 2.6.27 with some offsets.
+    
+    The problem is that __iscsi_conn_send_pdu assumes that userspace was
+    not sending nops with the format it is checking for in the "if" below.
+    It turns out that older userspace tools are. This patch moves the
+    setting of the internal ping_task tracker (it tracks libiscsi current
+    outstanding nop) to iscsi_send_nopout which is only used by kernel callers.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 801c7cf54d2e..3fdee7370ccc 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -489,12 +489,6 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		if (!__kfifo_get(session->cmdpool.queue,
+ 				 (void*)&task, sizeof(void*)))
+ 			return NULL;
+-
+-		if ((hdr->opcode == (ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE)) &&
+-		     hdr->ttt == RESERVED_ITT) {
+-			conn->ping_task = task;
+-			conn->last_ping = jiffies;
+-		}
+ 	}
+ 	/*
+ 	 * released in complete pdu for task we expect a response for, and
+@@ -703,6 +697,11 @@ static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
+ 	task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0);
+ 	if (!task)
+ 		iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n");
++	else if (!rhdr) {
++		/* only track our nops */
++		conn->ping_task = task;
++		conn->last_ping = jiffies;
++	}
+ }
+ 
+ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr,

commit 2a3a59e5c977654d3aad5bc11cc0aca2303a7f44
+Author: Mike Christie 
+Date:   Tue Nov 11 13:42:35 2008 -0600
+
+    [SCSI] Fix hang in starved list processing
+    
+    Close possible infinite loop with interrupts off when devices are
+    added back to the starved list.
+    
+    Fixes: http://bugzilla.kernel.org/show_bug.cgi?id=11898
+    
+    Reported-by: 
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index f5d3b96890dc..fa45a1a66867 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -567,15 +567,18 @@ static inline int scsi_host_is_busy(struct Scsi_Host *shost)
+  */
+ static void scsi_run_queue(struct request_queue *q)
+ {
+-	struct scsi_device *starved_head = NULL, *sdev = q->queuedata;
++	struct scsi_device *sdev = q->queuedata;
+ 	struct Scsi_Host *shost = sdev->host;
++	LIST_HEAD(starved_list);
+ 	unsigned long flags;
+ 
+ 	if (scsi_target(sdev)->single_lun)
+ 		scsi_single_lun_run(sdev);
+ 
+ 	spin_lock_irqsave(shost->host_lock, flags);
+-	while (!list_empty(&shost->starved_list) && !scsi_host_is_busy(shost)) {
++	list_splice_init(&shost->starved_list, &starved_list);
++
++	while (!list_empty(&starved_list)) {
+ 		int flagset;
+ 
+ 		/*
+@@ -588,24 +591,18 @@ static void scsi_run_queue(struct request_queue *q)
+ 		 * scsi_request_fn must get the host_lock before checking
+ 		 * or modifying starved_list or starved_entry.
+ 		 */
+-		sdev = list_entry(shost->starved_list.next,
+-					  struct scsi_device, starved_entry);
+-		/*
+-		 * The *queue_ready functions can add a device back onto the
+-		 * starved list's tail, so we must check for a infinite loop.
+-		 */
+-		if (sdev == starved_head)
++		if (scsi_host_is_busy(shost))
+ 			break;
+-		if (!starved_head)
+-			starved_head = sdev;
+ 
++		sdev = list_entry(starved_list.next,
++				  struct scsi_device, starved_entry);
++		list_del_init(&sdev->starved_entry);
+ 		if (scsi_target_is_busy(scsi_target(sdev))) {
+ 			list_move_tail(&sdev->starved_entry,
+ 				       &shost->starved_list);
+ 			continue;
+ 		}
+ 
+-		list_del_init(&sdev->starved_entry);
+ 		spin_unlock(shost->host_lock);
+ 
+ 		spin_lock(sdev->request_queue->queue_lock);
+@@ -621,6 +618,8 @@ static void scsi_run_queue(struct request_queue *q)
+ 
+ 		spin_lock(shost->host_lock);
+ 	}
++	/* put any unprocessed entries back */
++	list_splice(&starved_list, &shost->starved_list);
+ 	spin_unlock_irqrestore(shost->host_lock, flags);
+ 
+ 	blk_run_queue(q);

commit a343914831a8e29d89af3b26495ab1136a9e3153
+Author: Mike Christie 
+Date:   Wed Sep 24 11:46:15 2008 -0500
+
+    libiscsi: fix locking in iscsi_eh_device_reset
+    
+    We must be using the bh spin locking functions in
+    iscsi_eh_device_reset becuase the session lock interacts with
+    a thread and softirq.
+    
+    This patch also fixes up a bogus comment and check in fail_command,
+    because no one drops the lock (bnx2i did but it is not going
+    upstream yet and there were other refcount changes for that).
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 5aa0db150436..801c7cf54d2e 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -404,11 +404,6 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_task *task,
+ 		conn->session->queued_cmdsn--;
+ 	else
+ 		conn->session->tt->cleanup_task(conn, task);
+-	/*
+-	 * Check if cleanup_task dropped the lock and the command completed,
+-	 */
+-	if (!task->sc)
+-		return;
+ 
+ 	sc->result = err;
+ 	if (!scsi_bidi_cmnd(sc))
+@@ -1829,10 +1824,10 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc)
+ 
+ 	iscsi_suspend_tx(conn);
+ 
+-	spin_lock(&session->lock);
++	spin_lock_bh(&session->lock);
+ 	fail_all_commands(conn, sc->device->lun, DID_ERROR);
+ 	conn->tmf_state = TMF_INITIAL;
+-	spin_unlock(&session->lock);
++	spin_unlock_bh(&session->lock);
+ 
+ 	iscsi_start_tx(conn);
+ 	goto done;

commit 87cd9eab2dfbdf7d367d7ab30e88176d7b08b83e
+Author: Mike Christie 
+Date:   Wed Sep 24 11:46:14 2008 -0500
+
+    libiscsi: check reason why we are stopping iscsi session to determine error value
+    
+    Some wires got crossed on some patches and I messed up in the code
+    below when rebuilding a patch. We want to be checking if flag
+    equaled the value indicating if we killing the session due to
+    final logout or if we just trying to relogin.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index e3e57cce4886..5aa0db150436 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -2453,7 +2453,7 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ 	 * flush queues.
+ 	 */
+ 	spin_lock_bh(&session->lock);
+-	if (STOP_CONN_RECOVER)
++	if (flag == STOP_CONN_RECOVER)
+ 		fail_all_commands(conn, -1, DID_TRANSPORT_DISRUPTED);
+ 	else
+ 		fail_all_commands(conn, -1, DID_ERROR);

commit 6f481e3cefeb33094e87af176587e6a3027f104e
+Author: Mike Christie 
+Date:   Wed Sep 24 11:46:13 2008 -0500
+
+    [SCSI] iscsi_tcp: return a descriptive error value during connection errors
+    
+    The segment->done functions return a iscsi error value which gives
+    a lot more info than conn failed, so this patch has us return
+    that value. I also add a new one for xmit failures.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 4f096de81525..ed6c54cae7b1 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -979,7 +979,7 @@ iscsi_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 
+ error:
+ 	debug_tcp("Error receiving PDU, errno=%d\n", rc);
+-	iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
++	iscsi_conn_failure(conn, rc);
+ 	return 0;
+ }
+ 
+@@ -1098,8 +1098,10 @@ iscsi_xmit(struct iscsi_conn *conn)
+ 
+ 	while (1) {
+ 		rc = iscsi_tcp_xmit_segment(tcp_conn, segment);
+-		if (rc < 0)
++		if (rc < 0) {
++			rc = ISCSI_ERR_XMIT_FAILED;
+ 			goto error;
++		}
+ 		if (rc == 0)
+ 			break;
+ 
+@@ -1108,7 +1110,7 @@ iscsi_xmit(struct iscsi_conn *conn)
+ 		if (segment->total_copied >= segment->total_size) {
+ 			if (segment->done != NULL) {
+ 				rc = segment->done(tcp_conn, segment);
+-				if (rc < 0)
++				if (rc != 0)
+ 					goto error;
+ 			}
+ 		}
+@@ -1123,8 +1125,8 @@ iscsi_xmit(struct iscsi_conn *conn)
+ 	/* Transmit error. We could initiate error recovery
+ 	 * here. */
+ 	debug_tcp("Error sending PDU, errno=%d\n", rc);
+-	iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+-	return rc;
++	iscsi_conn_failure(conn, rc);
++	return -EIO;
+ }
+ 
+ /**
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index f274d248a91f..0c9514de5df7 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -214,6 +214,7 @@ enum iscsi_err {
+ 	ISCSI_ERR_PARAM_NOT_FOUND	= ISCSI_ERR_BASE + 16,
+ 	ISCSI_ERR_NO_SCSI_CMD		= ISCSI_ERR_BASE + 17,
+ 	ISCSI_ERR_INVALID_HOST		= ISCSI_ERR_BASE + 18,
++	ISCSI_ERR_XMIT_FAILED		= ISCSI_ERR_BASE + 19,
+ };
+ 
+ /*

commit 8e12452549ba2dfa17db97bc495172fac221a7ab
+Author: Mike Christie 
+Date:   Wed Sep 24 11:46:12 2008 -0500
+
+    [SCSI] libiscsi: rename host reset to target reset
+    
+    I had this in my patchset to add target reset support, but
+    it got dropped due to patching conflicts. This initial patch
+    just renames the function and users. We are actually just
+    dropping the session, and so this does not have anything to do
+    with the host exactly. It does for software iscsi because
+    we allocate a host per session, but for cxgb3i this makes no
+    sense.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 0474da173eb1..1e5b6446231d 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -598,7 +598,7 @@ static struct scsi_host_template iscsi_iser_sht = {
+ 	.cmd_per_lun            = ISCSI_MAX_CMD_PER_LUN,
+ 	.eh_abort_handler       = iscsi_eh_abort,
+ 	.eh_device_reset_handler= iscsi_eh_device_reset,
+-	.eh_host_reset_handler	= iscsi_eh_host_reset,
++	.eh_target_reset_handler= iscsi_eh_target_reset,
+ 	.use_clustering         = DISABLE_CLUSTERING,
+ 	.proc_name              = "iscsi_iser",
+ 	.this_id                = -1,
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 752f42884cc1..4f096de81525 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -1909,7 +1909,7 @@ static struct scsi_host_template iscsi_sht = {
+ 	.cmd_per_lun		= ISCSI_DEF_CMD_PER_LUN,
+ 	.eh_abort_handler       = iscsi_eh_abort,
+ 	.eh_device_reset_handler= iscsi_eh_device_reset,
+-	.eh_host_reset_handler	= iscsi_eh_host_reset,
++	.eh_target_reset_handler= iscsi_eh_target_reset,
+ 	.use_clustering         = DISABLE_CLUSTERING,
+ 	.slave_configure        = iscsi_tcp_slave_configure,
+ 	.proc_name		= "iscsi_tcp",
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 390781894be9..e3e57cce4886 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1367,7 +1367,7 @@ void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_session_recovery_timedout);
+ 
+-int iscsi_eh_host_reset(struct scsi_cmnd *sc)
++int iscsi_eh_target_reset(struct scsi_cmnd *sc)
+ {
+ 	struct iscsi_cls_session *cls_session;
+ 	struct iscsi_session *session;
+@@ -1381,7 +1381,7 @@ int iscsi_eh_host_reset(struct scsi_cmnd *sc)
+ 	spin_lock_bh(&session->lock);
+ 	if (session->state == ISCSI_STATE_TERMINATE) {
+ failed:
+-		debug_scsi("failing host reset: session terminated "
++		debug_scsi("failing target reset: session terminated "
+ 			   "[CID %d age %d]\n", conn->id, session->age);
+ 		spin_unlock_bh(&session->lock);
+ 		mutex_unlock(&session->eh_mutex);
+@@ -1396,7 +1396,7 @@ int iscsi_eh_host_reset(struct scsi_cmnd *sc)
+ 	 */
+ 	iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ 
+-	debug_scsi("iscsi_eh_host_reset wait for relogin\n");
++	debug_scsi("iscsi_eh_target_reset wait for relogin\n");
+ 	wait_event_interruptible(conn->ehwait,
+ 				 session->state == ISCSI_STATE_TERMINATE ||
+ 				 session->state == ISCSI_STATE_LOGGED_IN ||
+@@ -1408,14 +1408,14 @@ int iscsi_eh_host_reset(struct scsi_cmnd *sc)
+ 	spin_lock_bh(&session->lock);
+ 	if (session->state == ISCSI_STATE_LOGGED_IN)
+ 		iscsi_session_printk(KERN_INFO, session,
+-				     "host reset succeeded\n");
++				     "target reset succeeded\n");
+ 	else
+ 		goto failed;
+ 	spin_unlock_bh(&session->lock);
+ 	mutex_unlock(&session->eh_mutex);
+ 	return SUCCESS;
+ }
+-EXPORT_SYMBOL_GPL(iscsi_eh_host_reset);
++EXPORT_SYMBOL_GPL(iscsi_eh_target_reset);
+ 
+ static void iscsi_tmf_timedout(unsigned long data)
+ {
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 7d8cd159f592..61e53f14f7e1 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -313,7 +313,7 @@ struct iscsi_host {
+  */
+ extern int iscsi_change_queue_depth(struct scsi_device *sdev, int depth);
+ extern int iscsi_eh_abort(struct scsi_cmnd *sc);
+-extern int iscsi_eh_host_reset(struct scsi_cmnd *sc);
++extern int iscsi_eh_target_reset(struct scsi_cmnd *sc);
+ extern int iscsi_eh_device_reset(struct scsi_cmnd *sc);
+ extern int iscsi_queuecommand(struct scsi_cmnd *sc,
+ 			      void (*done)(struct scsi_cmnd *));

commit 21536062d98938dfcfbae593a26c154e359749dc
+Author: Mike Christie 
+Date:   Wed Sep 24 11:46:11 2008 -0500
+
+    [SCSI] iscsi class: fix endpoint id handling
+    
+    Some endpoint code was using unsigned int and some
+    was using uint64_t. This converts it all to uint64_t.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index f9e45f83e467..4a803ebaf508 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -138,7 +138,7 @@ static ssize_t
+ show_ep_handle(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+ 	struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
+-	return sprintf(buf, "%u\n", ep->id);
++	return sprintf(buf, "%llu\n", (unsigned long long) ep->id);
+ }
+ static ISCSI_ATTR(ep, handle, S_IRUGO, show_ep_handle, NULL);
+ 
+@@ -156,7 +156,7 @@ static struct attribute_group iscsi_endpoint_group = {
+ static int iscsi_match_epid(struct device *dev, void *data)
+ {
+ 	struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
+-	unsigned int *epid = (unsigned int *) data;
++	uint64_t *epid = (uint64_t *) data;
+ 
+ 	return *epid == ep->id;
+ }
+@@ -166,7 +166,7 @@ iscsi_create_endpoint(int dd_size)
+ {
+ 	struct device *dev;
+ 	struct iscsi_endpoint *ep;
+-	unsigned int id;
++	uint64_t id;
+ 	int err;
+ 
+ 	for (id = 1; id < ISCSI_MAX_EPID; id++) {
+@@ -187,7 +187,8 @@ iscsi_create_endpoint(int dd_size)
+ 
+ 	ep->id = id;
+ 	ep->dev.class = &iscsi_endpoint_class;
+-	snprintf(ep->dev.bus_id, BUS_ID_SIZE, "ep-%u", id);
++	snprintf(ep->dev.bus_id, BUS_ID_SIZE, "ep-%llu",
++		 (unsigned long long) id);
+ 	err = device_register(&ep->dev);
+         if (err)
+                 goto free_ep;
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 8749d4d8e244..c667cc396545 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -208,7 +208,7 @@ extern void iscsi_host_for_each_session(struct Scsi_Host *shost,
+ struct iscsi_endpoint {
+ 	void *dd_data;			/* LLD private data */
+ 	struct device dev;
+-	unsigned int id;
++	uint64_t id;
+ };
+ 
+ /*

commit e5bd7b54e93ef7151469a12b8c28d863b9f8a088
+Author: Mike Christie 
+Date:   Wed Sep 24 11:46:10 2008 -0500
+
+    [SCSI] libiscsi: Support drivers initiating session removal
+    
+    If the driver knows when hardware is removed like with cxgb3i,
+    bnx2i, qla4xxx and iser then we will want to remove the sessions/devices
+    that are bound to that device before removing the host.
+    
+    cxgb3i and in the future bnx2i will remove the host and that will
+    remove all the sessions on the hba. iser can call iscsi_kill_session
+    when it gets an event that indicates that a hca is removed.
+    And when qla4xxx is hooked in to the lib (it is only hooked into
+    the class right now) it can call iscsi remove host like the
+    partial offload card drivers.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 5a1cf2580e16..0474da173eb1 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -378,6 +378,7 @@ static void iscsi_iser_session_destroy(struct iscsi_cls_session *cls_session)
+ {
+ 	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+ 
++	iscsi_session_teardown(cls_session);
+ 	iscsi_host_remove(shost);
+ 	iscsi_host_free(shost);
+ }
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index e960f00da93a..752f42884cc1 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -1885,6 +1885,7 @@ static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session)
+ 	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+ 
+ 	iscsi_r2tpool_free(cls_session->dd_data);
++	iscsi_session_teardown(cls_session);
+ 
+ 	iscsi_host_remove(shost);
+ 	iscsi_host_free(shost);
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index f9539af28f02..390781894be9 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -983,6 +983,38 @@ struct iscsi_task *iscsi_itt_to_ctask(struct iscsi_conn *conn, itt_t itt)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_itt_to_ctask);
+ 
++void iscsi_session_failure(struct iscsi_cls_session *cls_session,
++			   enum iscsi_err err)
++{
++	struct iscsi_session *session = cls_session->dd_data;
++	struct iscsi_conn *conn;
++	struct device *dev;
++	unsigned long flags;
++
++	spin_lock_irqsave(&session->lock, flags);
++	conn = session->leadconn;
++	if (session->state == ISCSI_STATE_TERMINATE || !conn) {
++		spin_unlock_irqrestore(&session->lock, flags);
++		return;
++	}
++
++	dev = get_device(&conn->cls_conn->dev);
++	spin_unlock_irqrestore(&session->lock, flags);
++	if (!dev)
++	        return;
++	/*
++	 * if the host is being removed bypass the connection
++	 * recovery initialization because we are going to kill
++	 * the session.
++	 */
++	if (err == ISCSI_ERR_INVALID_HOST)
++		iscsi_conn_error_event(conn->cls_conn, err);
++	else
++		iscsi_conn_failure(conn, err);
++	put_device(dev);
++}
++EXPORT_SYMBOL_GPL(iscsi_session_failure);
++
+ void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
+ {
+ 	struct iscsi_session *session = conn->session;
+@@ -997,9 +1029,10 @@ void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
+ 	if (conn->stop_stage == 0)
+ 		session->state = ISCSI_STATE_FAILED;
+ 	spin_unlock_irqrestore(&session->lock, flags);
++
+ 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+ 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
+-	iscsi_conn_error(conn->cls_conn, err);
++	iscsi_conn_error_event(conn->cls_conn, err);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_conn_failure);
+ 
+@@ -1905,6 +1938,7 @@ struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
+ 				   int dd_data_size, uint16_t qdepth)
+ {
+ 	struct Scsi_Host *shost;
++	struct iscsi_host *ihost;
+ 
+ 	shost = scsi_host_alloc(sht, sizeof(struct iscsi_host) + dd_data_size);
+ 	if (!shost)
+@@ -1919,22 +1953,43 @@ struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
+ 		qdepth = ISCSI_DEF_CMD_PER_LUN;
+ 	}
+ 	shost->cmd_per_lun = qdepth;
++
++	ihost = shost_priv(shost);
++	spin_lock_init(&ihost->lock);
++	ihost->state = ISCSI_HOST_SETUP;
++	ihost->num_sessions = 0;
++	init_waitqueue_head(&ihost->session_removal_wq);
+ 	return shost;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_host_alloc);
+ 
++static void iscsi_notify_host_removed(struct iscsi_cls_session *cls_session)
++{
++	iscsi_session_failure(cls_session, ISCSI_ERR_INVALID_HOST);
++}
++
+ /**
+  * iscsi_host_remove - remove host and sessions
+  * @shost: scsi host
+  *
+- * This will also remove any sessions attached to the host, but if userspace
+- * is managing the session at the same time this will break. TODO: add
+- * refcounting to the netlink iscsi interface so a rmmod or host hot unplug
+- * does not remove the memory from under us.
++ * If there are any sessions left, this will initiate the removal and wait
++ * for the completion.
+  */
+ void iscsi_host_remove(struct Scsi_Host *shost)
+ {
+-	iscsi_host_for_each_session(shost, iscsi_session_teardown);
++	struct iscsi_host *ihost = shost_priv(shost);
++	unsigned long flags;
++
++	spin_lock_irqsave(&ihost->lock, flags);
++	ihost->state = ISCSI_HOST_REMOVED;
++	spin_unlock_irqrestore(&ihost->lock, flags);
++
++	iscsi_host_for_each_session(shost, iscsi_notify_host_removed);
++	wait_event_interruptible(ihost->session_removal_wq,
++				 ihost->num_sessions == 0);
++	if (signal_pending(current))
++		flush_signals(current);
++
+ 	scsi_remove_host(shost);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_host_remove);
+@@ -1950,6 +2005,27 @@ void iscsi_host_free(struct Scsi_Host *shost)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_host_free);
+ 
++static void iscsi_host_dec_session_cnt(struct Scsi_Host *shost)
++{
++	struct iscsi_host *ihost = shost_priv(shost);
++	unsigned long flags;
++
++	shost = scsi_host_get(shost);
++	if (!shost) {
++		printk(KERN_ERR "Invalid state. Cannot notify host removal "
++		      "of session teardown event because host already "
++		      "removed.\n");
++		return;
++	}
++
++	spin_lock_irqsave(&ihost->lock, flags);
++	ihost->num_sessions--;
++	if (ihost->num_sessions == 0)
++		wake_up(&ihost->session_removal_wq);
++	spin_unlock_irqrestore(&ihost->lock, flags);
++	scsi_host_put(shost);
++}
++
+ /**
+  * iscsi_session_setup - create iscsi cls session and host and session
+  * @iscsit: iscsi transport template
+@@ -1970,9 +2046,19 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
+ 		    uint16_t cmds_max, int cmd_task_size,
+ 		    uint32_t initial_cmdsn, unsigned int id)
+ {
++	struct iscsi_host *ihost = shost_priv(shost);
+ 	struct iscsi_session *session;
+ 	struct iscsi_cls_session *cls_session;
+ 	int cmd_i, scsi_cmds, total_cmds = cmds_max;
++	unsigned long flags;
++
++	spin_lock_irqsave(&ihost->lock, flags);
++	if (ihost->state == ISCSI_HOST_REMOVED) {
++		spin_unlock_irqrestore(&ihost->lock, flags);
++		return NULL;
++	}
++	ihost->num_sessions++;
++	spin_unlock_irqrestore(&ihost->lock, flags);
+ 
+ 	if (!total_cmds)
+ 		total_cmds = ISCSI_DEF_XMIT_CMDS_MAX;
+@@ -1985,7 +2071,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
+ 		printk(KERN_ERR "iscsi: invalid can_queue of %d. can_queue "
+ 		       "must be a power of two that is at least %d.\n",
+ 		       total_cmds, ISCSI_TOTAL_CMDS_MIN);
+-		return NULL;
++		goto dec_session_count;
+ 	}
+ 
+ 	if (total_cmds > ISCSI_TOTAL_CMDS_MAX) {
+@@ -2009,7 +2095,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
+ 	cls_session = iscsi_alloc_session(shost, iscsit,
+ 					  sizeof(struct iscsi_session));
+ 	if (!cls_session)
+-		return NULL;
++		goto dec_session_count;
+ 	session = cls_session->dd_data;
+ 	session->cls_session = cls_session;
+ 	session->host = shost;
+@@ -2048,6 +2134,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
+ 
+ 	if (iscsi_add_session(cls_session, id))
+ 		goto cls_session_fail;
++
+ 	return cls_session;
+ 
+ cls_session_fail:
+@@ -2056,6 +2143,8 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
+ 	iscsi_pool_free(&session->cmdpool);
+ cmdpool_alloc_fail:
+ 	iscsi_free_session(cls_session);
++dec_session_count:
++	iscsi_host_dec_session_cnt(shost);
+ 	return NULL;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_session_setup);
+@@ -2071,6 +2160,7 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+ {
+ 	struct iscsi_session *session = cls_session->dd_data;
+ 	struct module *owner = cls_session->transport->owner;
++	struct Scsi_Host *shost = session->host;
+ 
+ 	iscsi_pool_free(&session->cmdpool);
+ 
+@@ -2083,6 +2173,7 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+ 	kfree(session->ifacename);
+ 
+ 	iscsi_destroy_session(cls_session);
++	iscsi_host_dec_session_cnt(shost);
+ 	module_put(owner);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_session_teardown);
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index 4255b36ff968..db7ea3bb4e83 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -353,7 +353,7 @@ void qla4xxx_mark_device_missing(struct scsi_qla_host *ha,
+ 		      ha->host_no, ddb_entry->bus, ddb_entry->target,
+ 		      ddb_entry->fw_ddb_index));
+ 	iscsi_block_session(ddb_entry->sess);
+-	iscsi_conn_error(ddb_entry->conn, ISCSI_ERR_CONN_FAILED);
++	iscsi_conn_error_event(ddb_entry->conn, ISCSI_ERR_CONN_FAILED);
+ }
+ 
+ static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha,
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index cbaae48f47ed..f9e45f83e467 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -1010,7 +1010,7 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
+ 
+ 	skb = alloc_skb(len, GFP_ATOMIC);
+ 	if (!skb) {
+-		iscsi_conn_error(conn, ISCSI_ERR_CONN_FAILED);
++		iscsi_conn_error_event(conn, ISCSI_ERR_CONN_FAILED);
+ 		iscsi_cls_conn_printk(KERN_ERR, conn, "can not deliver "
+ 				      "control PDU: OOM\n");
+ 		return -ENOMEM;
+@@ -1031,7 +1031,7 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
+ }
+ EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
+ 
+-void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
++void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error)
+ {
+ 	struct nlmsghdr	*nlh;
+ 	struct sk_buff	*skb;
+@@ -1063,7 +1063,7 @@ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
+ 	iscsi_cls_conn_printk(KERN_INFO, conn, "detected conn error (%d)\n",
+ 			      error);
+ }
+-EXPORT_SYMBOL_GPL(iscsi_conn_error);
++EXPORT_SYMBOL_GPL(iscsi_conn_error_event);
+ 
+ static int
+ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi,
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index 16be12f1cbe8..f274d248a91f 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -213,6 +213,7 @@ enum iscsi_err {
+ 	ISCSI_ERR_DATA_DGST		= ISCSI_ERR_BASE + 15,
+ 	ISCSI_ERR_PARAM_NOT_FOUND	= ISCSI_ERR_BASE + 16,
+ 	ISCSI_ERR_NO_SCSI_CMD		= ISCSI_ERR_BASE + 17,
++	ISCSI_ERR_INVALID_HOST		= ISCSI_ERR_BASE + 18,
+ };
+ 
+ /*
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 5e75bb7f311c..7d8cd159f592 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -287,6 +287,11 @@ struct iscsi_session {
+ 	struct iscsi_pool	cmdpool;	/* PDU's pool */
+ };
+ 
++enum {
++	ISCSI_HOST_SETUP,
++	ISCSI_HOST_REMOVED,
++};
++
+ struct iscsi_host {
+ 	char			*initiatorname;
+ 	/* hw address or netdev iscsi connection is bound to */
+@@ -295,6 +300,12 @@ struct iscsi_host {
+ 	/* local address */
+ 	int			local_port;
+ 	char			local_address[ISCSI_ADDRESS_BUF_LEN];
++
++	wait_queue_head_t	session_removal_wq;
++	/* protects sessions and state */
++	spinlock_t		lock;
++	int			num_sessions;
++	int			state;
+ };
+ 
+ /*
+@@ -351,6 +362,8 @@ extern void iscsi_conn_stop(struct iscsi_cls_conn *, int);
+ extern int iscsi_conn_bind(struct iscsi_cls_session *, struct iscsi_cls_conn *,
+ 			   int);
+ extern void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err);
++extern void iscsi_session_failure(struct iscsi_cls_session *cls_session,
++				  enum iscsi_err err);
+ extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ 				enum iscsi_param param, char *buf);
+ extern void iscsi_suspend_tx(struct iscsi_conn *conn);
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 8b6c91df4c7a..8749d4d8e244 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -135,7 +135,8 @@ extern int iscsi_unregister_transport(struct iscsi_transport *tt);
+ /*
+  * control plane upcalls
+  */
+-extern void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error);
++extern void iscsi_conn_error_event(struct iscsi_cls_conn *conn,
++				   enum iscsi_err error);
+ extern int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
+ 			  char *data, uint32_t data_size);
+ 

commit 1d9edf0270cb5a434d32e95279ce9493581906b3
+Author: Mike Christie 
+Date:   Wed Sep 24 11:46:09 2008 -0500
+
+    [SCSI] libiscsi: fix data corruption when target has to resend data-in packets
+    
+    iscsi_tcp was updating the exp_statsn (exp_statsn acknowledges
+    status and tells the target it is ok to let the resources for
+    a iscsi pdu to be reused) before it got all the data for pdu read
+    into OS buffers. Data corruption was occuring if something happens
+    to a packet and the network layer requests a retransmit, and the
+    initiator has told the target about the udpated exp_statsn ack,
+    then the target may be sending data from a buffer it has reused
+    for a new iscsi pdu. This fixes the problem by having the LLD
+    (iscsi_tcp in this case) just handle the transferring of data, and
+    has libiscsi handle the processing of status (libiscsi completion
+    processing is done after LLD data transfers are complete).
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 2a2f0094570f..e960f00da93a 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -523,22 +523,20 @@ iscsi_tcp_cleanup_task(struct iscsi_conn *conn, struct iscsi_task *task)
+ }
+ 
+ /**
+- * iscsi_data_rsp - SCSI Data-In Response processing
++ * iscsi_data_in - SCSI Data-In Response processing
+  * @conn: iscsi connection
+  * @task: scsi command task
+  **/
+ static int
+-iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
++iscsi_data_in(struct iscsi_conn *conn, struct iscsi_task *task)
+ {
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	struct iscsi_tcp_task *tcp_task = task->dd_data;
+ 	struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)tcp_conn->in.hdr;
+-	struct iscsi_session *session = conn->session;
+-	struct scsi_cmnd *sc = task->sc;
+ 	int datasn = be32_to_cpu(rhdr->datasn);
+-	unsigned total_in_length = scsi_in(sc)->length;
++	unsigned total_in_length = scsi_in(task->sc)->length;
+ 
+-	iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
++	iscsi_update_cmdsn(conn->session, (struct iscsi_nopin*)rhdr);
+ 	if (tcp_conn->in.datalen == 0)
+ 		return 0;
+ 
+@@ -558,23 +556,6 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
+ 		return ISCSI_ERR_DATA_OFFSET;
+ 	}
+ 
+-	if (rhdr->flags & ISCSI_FLAG_DATA_STATUS) {
+-		sc->result = (DID_OK << 16) | rhdr->cmd_status;
+-		conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
+-		if (rhdr->flags & (ISCSI_FLAG_DATA_UNDERFLOW |
+-		                   ISCSI_FLAG_DATA_OVERFLOW)) {
+-			int res_count = be32_to_cpu(rhdr->residual_count);
+-
+-			if (res_count > 0 &&
+-			    (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
+-			     res_count <= total_in_length))
+-				scsi_in(sc)->resid = res_count;
+-			else
+-				sc->result = (DID_BAD_TARGET << 16) |
+-					rhdr->cmd_status;
+-		}
+-	}
+-
+ 	conn->datain_pdus_cnt++;
+ 	return 0;
+ }
+@@ -774,7 +755,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 		if (!task)
+ 			rc = ISCSI_ERR_BAD_ITT;
+ 		else
+-			rc = iscsi_data_rsp(conn, task);
++			rc = iscsi_data_in(conn, task);
+ 		if (rc) {
+ 			spin_unlock(&conn->session->lock);
+ 			break;
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 0e8f26baca6e..f9539af28f02 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -633,6 +633,40 @@ static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	__iscsi_put_task(task);
+ }
+ 
++/**
++ * iscsi_data_in_rsp - SCSI Data-In Response processing
++ * @conn: iscsi connection
++ * @hdr:  iscsi pdu
++ * @task: scsi command task
++ **/
++static void
++iscsi_data_in_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
++		  struct iscsi_task *task)
++{
++	struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)hdr;
++	struct scsi_cmnd *sc = task->sc;
++
++	if (!(rhdr->flags & ISCSI_FLAG_DATA_STATUS))
++		return;
++
++	sc->result = (DID_OK << 16) | rhdr->cmd_status;
++	conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
++	if (rhdr->flags & (ISCSI_FLAG_DATA_UNDERFLOW |
++	                   ISCSI_FLAG_DATA_OVERFLOW)) {
++		int res_count = be32_to_cpu(rhdr->residual_count);
++
++		if (res_count > 0 &&
++		    (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
++		     res_count <= scsi_in(sc)->length))
++			scsi_in(sc)->resid = res_count;
++		else
++			sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
++	}
++
++	conn->scsirsp_pdus_cnt++;
++	__iscsi_put_task(task);
++}
++
+ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ {
+ 	struct iscsi_tm_rsp *tmf = (struct iscsi_tm_rsp *)hdr;
+@@ -818,12 +852,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		iscsi_scsi_cmd_rsp(conn, hdr, task, data, datalen);
+ 		break;
+ 	case ISCSI_OP_SCSI_DATA_IN:
+-		if (hdr->flags & ISCSI_FLAG_DATA_STATUS) {
+-			conn->scsirsp_pdus_cnt++;
+-			iscsi_update_cmdsn(session,
+-					   (struct iscsi_nopin*) hdr);
+-			__iscsi_put_task(task);
+-		}
++		iscsi_data_in_rsp(conn, hdr, task);
+ 		break;
+ 	case ISCSI_OP_LOGOUT_RSP:
+ 		iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);

commit 64f84bc1cf49aa5e0c4b945b434e5d4b74e0831d
+Author: Mike Christie 
+Date:   Sat Sep 6 08:39:16 2008 -0500
+
+    [SCSI] scsi_dh_alua: remove REQ_NOMERGE
+    
+    We do not need to set REQ_NOMERGE because when the module calls
+    blk_execute_rq -> blk_execute_rq_nowait, blk_execute_rq_nowait sets
+    it for us. This brings all the modules in sync for those bits.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
+index cb8aa3b58c22..e356b43753ff 100644
+--- a/drivers/scsi/device_handler/scsi_dh_alua.c
++++ b/drivers/scsi/device_handler/scsi_dh_alua.c
+@@ -110,7 +110,7 @@ static struct request *get_alua_req(struct scsi_device *sdev,
+ 
+ 	rq->cmd_type = REQ_TYPE_BLOCK_PC;
+ 	rq->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
+-			 REQ_FAILFAST_DRIVER | REQ_NOMERGE;
++			 REQ_FAILFAST_DRIVER;
+ 	rq->retries = ALUA_FAILOVER_RETRIES;
+ 	rq->timeout = ALUA_FAILOVER_TIMEOUT;
+ 

commit 4a27446f3e39b06c28d1c8e31d33a5340826ed5c
+Author: Mike Christie 
+Date:   Tue Aug 19 18:45:31 2008 -0500
+
+    [SCSI] modify scsi to handle new fail fast flags.
+    
+    This checks the errors the scsi-ml determined were retryable
+    and returns if we should fast fail it based on the request
+    fail fast flags.
+    
+    Without the patch, drivers like lpfc, qla2xxx and fcoe would return
+    DID_ERROR for what it determines is a temporary communication problem.
+    There is no loss of connectivity at that time and the driver thinks
+    that it would be fast to retry at the driver level. SCSI-ml will however
+    sees fast fail on the request and DID_ERROR and will fast fail the io.
+    This will then cause dm-multipath to fail the path and possibley switch
+    target controllers when we should be retrying at the scsi layer.
+    
+    We also were fast failing device errors to dm multiapth when
+    unless the scsi_dh modules think otherwis we want to retry at
+    the scsi layer because multipath can only retry the IO like scsi
+    should have done. multipath is a little dumber though because it
+    does not what the error was for and assumes that it should fail
+    the paths.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
+index 5bf8be21a165..ad019ece2139 100644
+--- a/drivers/scsi/scsi_error.c
++++ b/drivers/scsi/scsi_error.c
+@@ -1218,6 +1218,40 @@ static void scsi_eh_offline_sdevs(struct list_head *work_q,
+ 	return;
+ }
+ 
++/**
++ * scsi_noretry_cmd - determinte if command should be failed fast
++ * @scmd:	SCSI cmd to examine.
++ */
++int scsi_noretry_cmd(struct scsi_cmnd *scmd)
++{
++	switch (host_byte(scmd->result)) {
++	case DID_OK:
++		break;
++	case DID_BUS_BUSY:
++		return blk_failfast_transport(scmd->request);
++	case DID_PARITY:
++		return blk_failfast_dev(scmd->request);
++	case DID_ERROR:
++		if (msg_byte(scmd->result) == COMMAND_COMPLETE &&
++		    status_byte(scmd->result) == RESERVATION_CONFLICT)
++			return 0;
++		/* fall through */
++	case DID_SOFT_ERROR:
++		return blk_failfast_driver(scmd->request);
++	}
++
++	switch (status_byte(scmd->result)) {
++	case CHECK_CONDITION:
++		/*
++		 * assume caller has checked sense and determinted
++		 * the check condition was retryable.
++		 */
++		return blk_failfast_dev(scmd->request);
++	}
++
++	return 0;
++}
++
+ /**
+  * scsi_decide_disposition - Disposition a cmd on return from LLD.
+  * @scmd:	SCSI cmd to examine.
+@@ -1396,7 +1430,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
+ 	 * even if the request is marked fast fail, we still requeue
+ 	 * for queue congestion conditions (QUEUE_FULL or BUSY) */
+ 	if ((++scmd->retries) <= scmd->allowed
+-	    && !blk_noretry_request(scmd->request)) {
++	    && !scsi_noretry_cmd(scmd)) {
+ 		return NEEDS_RETRY;
+ 	} else {
+ 		/*
+@@ -1521,7 +1555,7 @@ void scsi_eh_flush_done_q(struct list_head *done_q)
+ 	list_for_each_entry_safe(scmd, next, done_q, eh_entry) {
+ 		list_del_init(&scmd->eh_entry);
+ 		if (scsi_device_online(scmd->device) &&
+-		    !blk_noretry_request(scmd->request) &&
++		    !scsi_noretry_cmd(scmd) &&
+ 		    (++scmd->retries <= scmd->allowed)) {
+ 			SCSI_LOG_ERROR_RECOVERY(3, printk("%s: flush"
+ 							  " retry cmd: %p\n",
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index 91c74c55aa5e..e5a9526d2037 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -706,7 +706,7 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int error,
+ 			leftover = req->data_len;
+ 
+ 		/* kill remainder if no retrys */
+-		if (error && blk_noretry_request(req))
++		if (error && scsi_noretry_cmd(cmd))
+ 			blk_end_request(req, error, leftover);
+ 		else {
+ 			if (requeue) {
+diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
+index 6cddd5dd323c..e1850904ff73 100644
+--- a/drivers/scsi/scsi_priv.h
++++ b/drivers/scsi/scsi_priv.h
+@@ -59,6 +59,7 @@ void scsi_eh_ready_devs(struct Scsi_Host *shost,
+ 			struct list_head *done_q);
+ int scsi_eh_get_sense(struct list_head *work_q,
+ 		      struct list_head *done_q);
++int scsi_noretry_cmd(struct scsi_cmnd *scmd);
+ 
+ /* scsi_lib.c */
+ extern int scsi_maybe_unblock_host(struct scsi_device *sdev);

commit 6000a368cd8e6da1caf101411bdb494cd6fb8b09
+Author: Mike Christie 
+Date:   Tue Aug 19 18:45:30 2008 -0500
+
+    [SCSI] block: separate failfast into multiple bits.
+    
+    Multipath is best at handling transport errors. If it gets a device
+    error then there is not much the multipath layer can do. It will just
+    access the same device but from a different path.
+    
+    This patch breaks up failfast into device, transport and driver errors.
+    The multipath layers (md and dm mutlipath) only ask the lower levels to
+    fast fail transport errors. The user of failfast, read ahead, will ask
+    to fast fail on all errors.
+    
+    Note that blk_noretry_request will return true if any failfast bit
+    is set. This allows drivers that do not support the multipath failfast
+    bits to continue to fail on any failfast error like before. Drivers
+    like scsi that are able to fail fast specific errors can check
+    for the specific fail fast type. In the next patch I will convert
+    scsi.
+    
+    Signed-off-by: Mike Christie 
+    Cc: Jens Axboe 
+    Signed-off-by: James Bottomley 
+
+diff --git a/block/blk-core.c b/block/blk-core.c
+index 2d053b584410..9e79a485e4f3 100644
+--- a/block/blk-core.c
++++ b/block/blk-core.c
+@@ -1075,8 +1075,15 @@ void init_request_from_bio(struct request *req, struct bio *bio)
+ 	/*
+ 	 * inherit FAILFAST from bio (for read-ahead, and explicit FAILFAST)
+ 	 */
+-	if (bio_rw_ahead(bio) || bio_failfast(bio))
+-		req->cmd_flags |= REQ_FAILFAST;
++	if (bio_rw_ahead(bio))
++		req->cmd_flags |= (REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
++				   REQ_FAILFAST_DRIVER);
++	if (bio_failfast_dev(bio))
++		req->cmd_flags |= REQ_FAILFAST_DEV;
++	if (bio_failfast_transport(bio))
++		req->cmd_flags |= REQ_FAILFAST_TRANSPORT;
++	if (bio_failfast_driver(bio))
++		req->cmd_flags |= REQ_FAILFAST_DRIVER;
+ 
+ 	/*
+ 	 * REQ_BARRIER implies no merging, but lets make it explicit
+diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
+index 103304c1e3b0..9bf3460c5540 100644
+--- a/drivers/md/dm-mpath.c
++++ b/drivers/md/dm-mpath.c
+@@ -849,7 +849,7 @@ static int multipath_map(struct dm_target *ti, struct bio *bio,
+ 	dm_bio_record(&mpio->details, bio);
+ 
+ 	map_context->ptr = mpio;
+-	bio->bi_rw |= (1 << BIO_RW_FAILFAST);
++	bio->bi_rw |= (1 << BIO_RW_FAILFAST_TRANSPORT);
+ 	r = map_io(m, bio, mpio, 0);
+ 	if (r < 0 || r == DM_MAPIO_REQUEUE)
+ 		mempool_free(mpio, m->mpio_pool);
+diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
+index 8bb8794129b3..7ae33ebaf7ec 100644
+--- a/drivers/md/multipath.c
++++ b/drivers/md/multipath.c
+@@ -176,7 +176,7 @@ static int multipath_make_request (struct request_queue *q, struct bio * bio)
+ 	mp_bh->bio = *bio;
+ 	mp_bh->bio.bi_sector += multipath->rdev->data_offset;
+ 	mp_bh->bio.bi_bdev = multipath->rdev->bdev;
+-	mp_bh->bio.bi_rw |= (1 << BIO_RW_FAILFAST);
++	mp_bh->bio.bi_rw |= (1 << BIO_RW_FAILFAST_TRANSPORT);
+ 	mp_bh->bio.bi_end_io = multipath_end_request;
+ 	mp_bh->bio.bi_private = mp_bh;
+ 	generic_make_request(&mp_bh->bio);
+@@ -402,7 +402,7 @@ static void multipathd (mddev_t *mddev)
+ 			*bio = *(mp_bh->master_bio);
+ 			bio->bi_sector += conf->multipaths[mp_bh->path].rdev->data_offset;
+ 			bio->bi_bdev = conf->multipaths[mp_bh->path].rdev->bdev;
+-			bio->bi_rw |= (1 << BIO_RW_FAILFAST);
++			bio->bi_rw |= (1 << BIO_RW_FAILFAST_TRANSPORT);
+ 			bio->bi_end_io = multipath_end_request;
+ 			bio->bi_private = mp_bh;
+ 			generic_make_request(bio);
+diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
+index 85fcb4371054..7844461a995b 100644
+--- a/drivers/s390/block/dasd_diag.c
++++ b/drivers/s390/block/dasd_diag.c
+@@ -544,7 +544,7 @@ static struct dasd_ccw_req *dasd_diag_build_cp(struct dasd_device *memdev,
+ 	}
+ 	cqr->retries = DIAG_MAX_RETRIES;
+ 	cqr->buildclk = get_clock();
+-	if (req->cmd_flags & REQ_FAILFAST)
++	if (blk_noretry_request(req))
+ 		set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
+ 	cqr->startdev = memdev;
+ 	cqr->memdev = memdev;
+diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
+index 49f9d221e23d..2e60d5f968c8 100644
+--- a/drivers/s390/block/dasd_eckd.c
++++ b/drivers/s390/block/dasd_eckd.c
+@@ -1700,7 +1700,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev,
+ 			recid++;
+ 		}
+ 	}
+-	if (req->cmd_flags & REQ_FAILFAST)
++	if (blk_noretry_request(req))
+ 		set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
+ 	cqr->startdev = startdev;
+ 	cqr->memdev = startdev;
+diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
+index 93d9b6452a94..7d442aeff3d1 100644
+--- a/drivers/s390/block/dasd_fba.c
++++ b/drivers/s390/block/dasd_fba.c
+@@ -355,7 +355,7 @@ static struct dasd_ccw_req *dasd_fba_build_cp(struct dasd_device * memdev,
+ 			recid++;
+ 		}
+ 	}
+-	if (req->cmd_flags & REQ_FAILFAST)
++	if (blk_noretry_request(req))
+ 		set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
+ 	cqr->startdev = memdev;
+ 	cqr->memdev = memdev;
+diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
+index 708e475896b9..cb8aa3b58c22 100644
+--- a/drivers/scsi/device_handler/scsi_dh_alua.c
++++ b/drivers/scsi/device_handler/scsi_dh_alua.c
+@@ -109,7 +109,8 @@ static struct request *get_alua_req(struct scsi_device *sdev,
+ 	}
+ 
+ 	rq->cmd_type = REQ_TYPE_BLOCK_PC;
+-	rq->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE;
++	rq->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
++			 REQ_FAILFAST_DRIVER | REQ_NOMERGE;
+ 	rq->retries = ALUA_FAILOVER_RETRIES;
+ 	rq->timeout = ALUA_FAILOVER_TIMEOUT;
+ 
+diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c
+index 8f45570a8a01..0e572d2c5b0a 100644
+--- a/drivers/scsi/device_handler/scsi_dh_emc.c
++++ b/drivers/scsi/device_handler/scsi_dh_emc.c
+@@ -303,7 +303,8 @@ static struct request *get_req(struct scsi_device *sdev, int cmd,
+ 
+ 	rq->cmd[4] = len;
+ 	rq->cmd_type = REQ_TYPE_BLOCK_PC;
+-	rq->cmd_flags |= REQ_FAILFAST;
++	rq->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
++			 REQ_FAILFAST_DRIVER;
+ 	rq->timeout = CLARIION_TIMEOUT;
+ 	rq->retries = CLARIION_RETRIES;
+ 
+diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
+index 5e93c88ad66b..9aec4ca64e56 100644
+--- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c
++++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
+@@ -112,7 +112,8 @@ static int hp_sw_tur(struct scsi_device *sdev, struct hp_sw_dh_data *h)
+ 		return SCSI_DH_RES_TEMP_UNAVAIL;
+ 
+ 	req->cmd_type = REQ_TYPE_BLOCK_PC;
+-	req->cmd_flags |= REQ_FAILFAST;
++	req->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
++			  REQ_FAILFAST_DRIVER;
+ 	req->cmd_len = COMMAND_SIZE(TEST_UNIT_READY);
+ 	req->cmd[0] = TEST_UNIT_READY;
+ 	req->timeout = HP_SW_TIMEOUT;
+@@ -204,7 +205,8 @@ static int hp_sw_start_stop(struct scsi_device *sdev, struct hp_sw_dh_data *h)
+ 		return SCSI_DH_RES_TEMP_UNAVAIL;
+ 
+ 	req->cmd_type = REQ_TYPE_BLOCK_PC;
+-	req->cmd_flags |= REQ_FAILFAST;
++	req->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
++			  REQ_FAILFAST_DRIVER;
+ 	req->cmd_len = COMMAND_SIZE(START_STOP);
+ 	req->cmd[0] = START_STOP;
+ 	req->cmd[4] = 1;	/* Start spin cycle */
+diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c
+index 50bf95f3b5c4..a43c3ed4df28 100644
+--- a/drivers/scsi/device_handler/scsi_dh_rdac.c
++++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
+@@ -226,7 +226,8 @@ static struct request *get_rdac_req(struct scsi_device *sdev,
+ 	}
+ 
+ 	rq->cmd_type = REQ_TYPE_BLOCK_PC;
+-	rq->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE;
++	rq->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
++			 REQ_FAILFAST_DRIVER;
+ 	rq->retries = RDAC_RETRIES;
+ 	rq->timeout = RDAC_TIMEOUT;
+ 
+diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
+index b29360ed0bdc..7c2d28924d2a 100644
+--- a/drivers/scsi/scsi_transport_spi.c
++++ b/drivers/scsi/scsi_transport_spi.c
+@@ -109,7 +109,9 @@ static int spi_execute(struct scsi_device *sdev, const void *cmd,
+ 	for(i = 0; i < DV_RETRIES; i++) {
+ 		result = scsi_execute(sdev, cmd, dir, buffer, bufflen,
+ 				      sense, DV_TIMEOUT, /* retries */ 1,
+-				      REQ_FAILFAST);
++				      REQ_FAILFAST_DEV |
++				      REQ_FAILFAST_TRANSPORT |
++				      REQ_FAILFAST_DRIVER);
+ 		if (result & DRIVER_SENSE) {
+ 			struct scsi_sense_hdr sshdr_tmp;
+ 			if (!sshdr)
+diff --git a/include/linux/bio.h b/include/linux/bio.h
+index ff5b4cf9e2da..1beda208cbfb 100644
+--- a/include/linux/bio.h
++++ b/include/linux/bio.h
+@@ -129,25 +129,30 @@ struct bio {
+  * bit 2 -- barrier
+  *	Insert a serialization point in the IO queue, forcing previously
+  *	submitted IO to be completed before this oen is issued.
+- * bit 3 -- fail fast, don't want low level driver retries
+- * bit 4 -- synchronous I/O hint: the block layer will unplug immediately
++ * bit 3 -- synchronous I/O hint: the block layer will unplug immediately
+  *	Note that this does NOT indicate that the IO itself is sync, just
+  *	that the block layer will not postpone issue of this IO by plugging.
+- * bit 5 -- metadata request
++ * bit 4 -- metadata request
+  *	Used for tracing to differentiate metadata and data IO. May also
+  *	get some preferential treatment in the IO scheduler
+- * bit 6 -- discard sectors
++ * bit 5 -- discard sectors
+  *	Informs the lower level device that this range of sectors is no longer
+  *	used by the file system and may thus be freed by the device. Used
+  *	for flash based storage.
++ * bit 6 -- fail fast device errors
++ * bit 7 -- fail fast transport errors
++ * bit 8 -- fail fast driver errors
++ *	Don't want driver retries for any fast fail whatever the reason.
+  */
+ #define BIO_RW		0	/* Must match RW in req flags (blkdev.h) */
+ #define BIO_RW_AHEAD	1	/* Must match FAILFAST in req flags */
+ #define BIO_RW_BARRIER	2
+-#define BIO_RW_FAILFAST	3
+-#define BIO_RW_SYNC	4
+-#define BIO_RW_META	5
+-#define BIO_RW_DISCARD	6
++#define BIO_RW_SYNC	3
++#define BIO_RW_META	4
++#define BIO_RW_DISCARD	5
++#define BIO_RW_FAILFAST_DEV		6
++#define BIO_RW_FAILFAST_TRANSPORT	7
++#define BIO_RW_FAILFAST_DRIVER		8
+ 
+ /*
+  * upper 16 bits of bi_rw define the io priority of this bio
+@@ -174,7 +179,10 @@ struct bio {
+ #define bio_sectors(bio)	((bio)->bi_size >> 9)
+ #define bio_barrier(bio)	((bio)->bi_rw & (1 << BIO_RW_BARRIER))
+ #define bio_sync(bio)		((bio)->bi_rw & (1 << BIO_RW_SYNC))
+-#define bio_failfast(bio)	((bio)->bi_rw & (1 << BIO_RW_FAILFAST))
++#define bio_failfast_dev(bio)	((bio)->bi_rw &	(1 << BIO_RW_FAILFAST_DEV))
++#define bio_failfast_transport(bio)	\
++	((bio)->bi_rw & (1 << BIO_RW_FAILFAST_TRANSPORT))
++#define bio_failfast_driver(bio) ((bio)->bi_rw & (1 << BIO_RW_FAILFAST_DRIVER))
+ #define bio_rw_ahead(bio)	((bio)->bi_rw & (1 << BIO_RW_AHEAD))
+ #define bio_rw_meta(bio)	((bio)->bi_rw & (1 << BIO_RW_META))
+ #define bio_discard(bio)	((bio)->bi_rw & (1 << BIO_RW_DISCARD))
+diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
+index a92d9e4ea96e..f3491d225268 100644
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -87,7 +87,9 @@ enum {
+  */
+ enum rq_flag_bits {
+ 	__REQ_RW,		/* not set, read. set, write */
+-	__REQ_FAILFAST,		/* no low level driver retries */
++	__REQ_FAILFAST_DEV,	/* no driver retries of device errors */
++	__REQ_FAILFAST_TRANSPORT, /* no driver retries of transport errors */
++	__REQ_FAILFAST_DRIVER,	/* no driver retries of driver errors */
+ 	__REQ_DISCARD,		/* request to discard sectors */
+ 	__REQ_SORTED,		/* elevator knows about this request */
+ 	__REQ_SOFTBARRIER,	/* may not be passed by ioscheduler */
+@@ -111,8 +113,10 @@ enum rq_flag_bits {
+ };
+ 
+ #define REQ_RW		(1 << __REQ_RW)
++#define REQ_FAILFAST_DEV	(1 << __REQ_FAILFAST_DEV)
++#define REQ_FAILFAST_TRANSPORT	(1 << __REQ_FAILFAST_TRANSPORT)
++#define REQ_FAILFAST_DRIVER	(1 << __REQ_FAILFAST_DRIVER)
+ #define REQ_DISCARD	(1 << __REQ_DISCARD)
+-#define REQ_FAILFAST	(1 << __REQ_FAILFAST)
+ #define REQ_SORTED	(1 << __REQ_SORTED)
+ #define REQ_SOFTBARRIER	(1 << __REQ_SOFTBARRIER)
+ #define REQ_HARDBARRIER	(1 << __REQ_HARDBARRIER)
+@@ -560,7 +564,12 @@ enum {
+ #define blk_special_request(rq)	((rq)->cmd_type == REQ_TYPE_SPECIAL)
+ #define blk_sense_request(rq)	((rq)->cmd_type == REQ_TYPE_SENSE)
+ 
+-#define blk_noretry_request(rq)	((rq)->cmd_flags & REQ_FAILFAST)
++#define blk_failfast_dev(rq)	((rq)->cmd_flags & REQ_FAILFAST_DEV)
++#define blk_failfast_transport(rq) ((rq)->cmd_flags & REQ_FAILFAST_TRANSPORT)
++#define blk_failfast_driver(rq)	((rq)->cmd_flags & REQ_FAILFAST_DRIVER)
++#define blk_noretry_request(rq)	(blk_failfast_dev(rq) ||	\
++				 blk_failfast_transport(rq) ||	\
++				 blk_failfast_driver(rq))
+ #define blk_rq_started(rq)	((rq)->cmd_flags & REQ_STARTED)
+ 
+ #define blk_account_rq(rq)	(blk_rq_started(rq) && (blk_fs_request(rq) || blk_discard_rq(rq))) 

commit 056a44834950ffa51fafa6c76a720fa32e86851a
+Author: Mike Christie 
+Date:   Tue Aug 19 18:45:29 2008 -0500
+
+    [SCSI] qla2xxx: use new host byte transport errors.
+    
+    This has qla2xxx use the new transport error values instead of
+    DID_BUS_BUSY. I am not sure if all the errors
+    in qla_isr.c I changed are transport related. We end up blocking/deleting
+    the rport for all of them so it is better to use the new transport error since
+    the fc classs will decide when to fail the IO.
+    
+    With this patch if I pull a cable then IO that had reached
+    the driver, will be failed with DID_TRANSPORT_DISRUPTED (not including
+    tape). The fc class will then fail the IO when the fast io fail tmo
+    has fired, and the driver will flush any other commands running.
+    
+    Signed-off-by: Mike Christie 
+    Cc: Andrew Vasquez 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
+index fc4bfa7f839c..a76efd99d007 100644
+--- a/drivers/scsi/qla2xxx/qla_isr.c
++++ b/drivers/scsi/qla2xxx/qla_isr.c
+@@ -1187,7 +1187,12 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
+ 		    cp->serial_number, comp_status,
+ 		    atomic_read(&fcport->state)));
+ 
+-		cp->result = DID_BUS_BUSY << 16;
++		/*
++		 * We are going to have the fc class block the rport
++		 * while we try to recover so instruct the mid layer
++		 * to requeue until the class decides how to handle this.
++		 */
++		cp->result = DID_TRANSPORT_DISRUPTED << 16;
+ 		if (atomic_read(&fcport->state) == FCS_ONLINE)
+ 			qla2x00_mark_device_lost(fcport->ha, fcport, 1, 1);
+ 		break;
+@@ -1214,7 +1219,12 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
+ 		break;
+ 
+ 	case CS_TIMEOUT:
+-		cp->result = DID_BUS_BUSY << 16;
++		/*
++		 * We are going to have the fc class block the rport
++		 * while we try to recover so instruct the mid layer
++		 * to requeue until the class decides how to handle this.
++		 */
++		cp->result = DID_TRANSPORT_DISRUPTED << 16;
+ 
+ 		if (IS_FWI2_CAPABLE(ha)) {
+ 			DEBUG2(printk(KERN_INFO

commit f46e307da925a7b71a0018c0510cdc6e588b87fc
+Author: Mike Christie 
+Date:   Tue Aug 19 18:45:27 2008 -0500
+
+    [SCSI] fc class: Add support for new transport errors
+    
+    If the target is blocked and fast io fail tmo has not fired
+    then we requeue with DID_TRANSPORT_DISRUPTED. Once that
+    tmo fires we fail with DID_TRANSPORT_FAILFAST.
+    
+    v2
+    - seperate from
+    "fc class: unblock target after calling terminate callback"
+    to make it easier to review.
+    - Add JamesS's ack from list.
+    v2
+    - initial patch
+    
+    Signed-off-by: Mike Christie 
+    Acked-by: James Smart 
+    Signed-off-by: James Bottomley 
+
+diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
+index fb8d01370663..49d8913c4f86 100644
+--- a/include/scsi/scsi_transport_fc.h
++++ b/include/scsi/scsi_transport_fc.h
+@@ -679,15 +679,15 @@ fc_remote_port_chkready(struct fc_rport *rport)
+ 		if (rport->roles & FC_PORT_ROLE_FCP_TARGET)
+ 			result = 0;
+ 		else if (rport->flags & FC_RPORT_DEVLOSS_PENDING)
+-			result = DID_IMM_RETRY << 16;
++			result = DID_TRANSPORT_DISRUPTED << 16;
+ 		else
+ 			result = DID_NO_CONNECT << 16;
+ 		break;
+ 	case FC_PORTSTATE_BLOCKED:
+ 		if (rport->flags & FC_RPORT_FAST_FAIL_TIMEDOUT)
+-			result = DID_NO_CONNECT << 16;
++			result = DID_TRANSPORT_FAILFAST << 16;
+ 		else
+-			result = DID_IMM_RETRY << 16;
++			result = DID_TRANSPORT_DISRUPTED << 16;
+ 		break;
+ 	default:
+ 		result = DID_NO_CONNECT << 16;

commit 56d7fcfa815564b40a1b0ec7a30ea8cb3bc0713e
+Author: Mike Christie 
+Date:   Tue Aug 19 18:45:26 2008 -0500
+
+    [SCSI] iscsi class, libiscsi and qla4xxx: convert to new transport host byte values
+    
+    This patch converts the iscsi drivers to the new host byte values.
+    
+    v2
+    Drop some conversions. Want to avoid conflicts with other patches.
+    v1
+    initial patch.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 521dbf7e521d..0e8f26baca6e 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1200,7 +1200,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 			goto reject;
+ 		case ISCSI_STATE_RECOVERY_FAILED:
+ 			reason = FAILURE_SESSION_RECOVERY_TIMEOUT;
+-			sc->result = DID_NO_CONNECT << 16;
++			sc->result = DID_TRANSPORT_FAILFAST << 16;
+ 			break;
+ 		case ISCSI_STATE_TERMINATE:
+ 			reason = FAILURE_SESSION_TERMINATE;
+@@ -2333,8 +2333,10 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ 	 * flush queues.
+ 	 */
+ 	spin_lock_bh(&session->lock);
+-	fail_all_commands(conn, -1,
+-			STOP_CONN_RECOVER ? DID_BUS_BUSY : DID_ERROR);
++	if (STOP_CONN_RECOVER)
++		fail_all_commands(conn, -1, DID_TRANSPORT_DISRUPTED);
++	else
++		fail_all_commands(conn, -1, DID_ERROR);
+ 	flush_control_queues(session, conn);
+ 	spin_unlock_bh(&session->lock);
+ 	mutex_unlock(&session->eh_mutex);
+diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c
+index a91a57c57bff..799120fcb9be 100644
+--- a/drivers/scsi/qla4xxx/ql4_isr.c
++++ b/drivers/scsi/qla4xxx/ql4_isr.c
+@@ -139,7 +139,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
+ 			      ha->host_no, cmd->device->channel,
+ 			      cmd->device->id, cmd->device->lun));
+ 
+-		cmd->result = DID_BUS_BUSY << 16;
++		cmd->result = DID_TRANSPORT_DISRUPTED << 16;
+ 
+ 		/*
+ 		 * Mark device missing so that we won't continue to send
+@@ -243,7 +243,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
+ 		if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE)
+ 			qla4xxx_mark_device_missing(ha, ddb_entry);
+ 
+-		cmd->result = DID_BUS_BUSY << 16;
++		cmd->result = DID_TRANSPORT_DISRUPTED << 16;
+ 		break;
+ 
+ 	case SCS_QUEUE_FULL:
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 0ce5f7cdfe2a..cbaae48f47ed 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -374,10 +374,10 @@ int iscsi_session_chkready(struct iscsi_cls_session *session)
+ 		err = 0;
+ 		break;
+ 	case ISCSI_SESSION_FAILED:
+-		err = DID_IMM_RETRY << 16;
++		err = DID_TRANSPORT_DISRUPTED << 16;
+ 		break;
+ 	case ISCSI_SESSION_FREE:
+-		err = DID_NO_CONNECT << 16;
++		err = DID_TRANSPORT_FAILFAST << 16;
+ 		break;
+ 	default:
+ 		err = DID_NO_CONNECT << 16;

commit a4dfaa6f2e55b736adf2719133996f7e7dc309bc
+Author: Mike Christie 
+Date:   Tue Aug 19 18:45:25 2008 -0500
+
+    [SCSI] scsi: add transport host byte errors (v3)
+    
+    Currently, if there is a transport problem the iscsi drivers will return
+    outstanding commands (commands being exeucted by the driver/fw/hw) with
+    DID_BUS_BUSY and block the session so no new commands can be queued.
+    Commands that are caught between the failure handling and blocking are
+    failed with DID_IMM_RETRY or one of the scsi ml queuecommand return values.
+    When the recovery_timeout fires, the iscsi drivers then fail IO with
+    DID_NO_CONNECT.
+    
+    For fcp, some drivers will fail some outstanding IO (disk but possibly not
+    tape) with DID_BUS_BUSY or DID_ERROR or some other value that causes a retry
+    and hits the scsi_error.c failfast check, block the rport, and commands
+    caught in the race are failed with DID_IMM_RETRY. Other drivers, may
+    hold onto all IO and wait for the terminate_rport_io or dev_loss_tmo_callbk
+    to be called.
+    
+    The following patches attempt to unify what upper layers will see drivers
+    like multipath can make a good guess. This relies on drivers being
+    hooked into their transport class.
+    
+    This first patch just defines two new host byte errors so drivers can
+    return the same value for when a rport/session is blocked and for
+    when the fast_io_fail_tmo fires.
+    
+    The idea is that if the LLD/class detects a problem and is going to block
+    a rport/session, then if the LLD wants or must return the command to scsi-ml,
+    then it can return it with DID_TRANSPORT_DISRUPTED. This will requeue
+    the IO into the same scsi queue it came from, until the fast io fail timer
+    fires and the class decides what to do.
+    
+    When using multipath and the fast_io_fail_tmo fires then the class
+    can fail commands with DID_TRANSPORT_FAILFAST or drivers can use
+    DID_TRANSPORT_FAILFAST in their terminate_rport_io callbacks or
+    the equivlent in iscsi if we ever implement more advanced recovery methods.
+    A LLD, like lpfc, could continue to return DID_ERROR and then it will hit
+    the normal failfast path, so drivers do not have fully be ported to
+    work better. The point of the patches is that upper layers will
+    not see a failure that could be recovered from while the rport/session is
+    blocked until fast_io_fail_tmo/recovery_timeout fires.
+    
+    V3
+    Remove some comments.
+    V2
+    Fixed patch/diff errors and renamed DID_TRANSPORT_BLOCKED to
+    DID_TRANSPORT_DISRUPTED.
+    V1
+    initial patch.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
+index 9785d7384199..4003deefb7d8 100644
+--- a/drivers/scsi/constants.c
++++ b/drivers/scsi/constants.c
+@@ -1364,7 +1364,8 @@ EXPORT_SYMBOL(scsi_print_sense);
+ static const char * const hostbyte_table[]={
+ "DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT", "DID_BAD_TARGET",
+ "DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR",
+-"DID_PASSTHROUGH", "DID_SOFT_ERROR", "DID_IMM_RETRY", "DID_REQUEUE"};
++"DID_PASSTHROUGH", "DID_SOFT_ERROR", "DID_IMM_RETRY", "DID_REQUEUE",
++"DID_TRANSPORT_DISRUPTED", "DID_TRANSPORT_FAILFAST" };
+ #define NUM_HOSTBYTE_STRS ARRAY_SIZE(hostbyte_table)
+ 
+ static const char * const driverbyte_table[]={
+diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
+index fecefa05cb62..5bf8be21a165 100644
+--- a/drivers/scsi/scsi_error.c
++++ b/drivers/scsi/scsi_error.c
+@@ -1290,7 +1290,20 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
+ 
+ 	case DID_REQUEUE:
+ 		return ADD_TO_MLQUEUE;
+-
++	case DID_TRANSPORT_DISRUPTED:
++		/*
++		 * LLD/transport was disrupted during processing of the IO.
++		 * The transport class is now blocked/blocking,
++		 * and the transport will decide what to do with the IO
++		 * based on its timers and recovery capablilities.
++		 */
++		return ADD_TO_MLQUEUE;
++	case DID_TRANSPORT_FAILFAST:
++		/*
++		 * The transport decided to failfast the IO (most likely
++		 * the fast io fail tmo fired), so send IO directly upwards.
++		 */
++		return SUCCESS;
+ 	case DID_ERROR:
+ 		if (msg_byte(scmd->result) == COMMAND_COMPLETE &&
+ 		    status_byte(scmd->result) == RESERVATION_CONFLICT)
+diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
+index 3a5662b2817e..a109165714d6 100644
+--- a/include/scsi/scsi.h
++++ b/include/scsi/scsi.h
+@@ -381,6 +381,11 @@ static inline int scsi_is_wlun(unsigned int lun)
+ #define DID_IMM_RETRY   0x0c	/* Retry without decrementing retry count  */
+ #define DID_REQUEUE	0x0d	/* Requeue command (no immediate retry) also
+ 				 * without decrementing the retry count	   */
++#define DID_TRANSPORT_DISRUPTED 0x0e /* Transport error disrupted execution
++				      * and the driver blocked the port to
++				      * recover the link. Transport class will
++				      * retry or fail IO */
++#define DID_TRANSPORT_FAILFAST	0x0f /* Transport class fastfailed the io */
+ #define DRIVER_OK       0x00	/* Driver status                           */
+ 
+ /*

commit 9cc328f502eacfcc52ab1c1bf9a7729cf12f14be
+Author: Mike Christie 
+Date:   Tue Aug 19 18:45:24 2008 -0500
+
+    [SCSI] ibmvfc, qla2xxx, lpfc: remove scsi_target_unblock calls in terminate callbacks
+    
+    The fc class now calls scsi_target_unblock after calling the
+    terminate callback, so this patch removes the calls from the
+    drivers.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
+index 4e0b7c8eb32e..7650707a40de 100644
+--- a/drivers/scsi/ibmvscsi/ibmvfc.c
++++ b/drivers/scsi/ibmvscsi/ibmvfc.c
+@@ -2031,8 +2031,6 @@ static void ibmvfc_terminate_rport_io(struct fc_rport *rport)
+ 		spin_unlock_irqrestore(shost->host_lock, flags);
+ 	} else
+ 		ibmvfc_issue_fc_host_lip(shost);
+-
+-	scsi_target_unblock(&rport->dev);
+ 	LEAVE;
+ }
+ 
+diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
+index a98d11bf3576..aaf398e5c93f 100644
+--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
++++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
+@@ -88,14 +88,6 @@ lpfc_terminate_rport_io(struct fc_rport *rport)
+ 			&phba->sli.ring[phba->sli.fcp_ring],
+ 			ndlp->nlp_sid, 0, LPFC_CTX_TGT);
+ 	}
+-
+-	/*
+-	 * A device is normally blocked for rediscovery and unblocked when
+-	 * devloss timeout happens.  In case a vport is removed or driver
+-	 * unloaded before devloss timeout happens, we need to unblock here.
+-	 */
+-	scsi_target_unblock(&rport->dev);
+-	return;
+ }
+ 
+ /*
+diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
+index 0ddfe7106b3b..ed731968f15f 100644
+--- a/drivers/scsi/qla2xxx/qla_attr.c
++++ b/drivers/scsi/qla2xxx/qla_attr.c
+@@ -1006,7 +1006,6 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
+ 	}
+ 
+ 	qla2x00_abort_fcport_cmds(fcport);
+-	scsi_target_unblock(&rport->dev);
+ }
+ 
+ static int

commit fff9d40ce0eb4b46f3e186823ceab6bc02c3e5d3
+Author: Mike Christie 
+Date:   Tue Aug 19 18:45:23 2008 -0500
+
+    [SCSI] fc class: unblock target after calling terminate callback (take 2)
+    
+    When we block a rport and the driver implements the terminate
+    callback we will fail IO that was running quickly. However
+    IO that was in the scsi_device/block queue sits there until
+    the dev_loss_tmo fires, and this can make it look like IO is
+    lost because new IO will get executed but that IO stuck in
+    the blocked queue sits there for some time longer.
+    
+    With this patch when the fast io fail tmo fires, we will
+    fail the blocked IO and any new IO. This patch also allows
+    all drivers to partially support the fast io fail tmo. If the
+    terminate io callback is not implemented, we will still fail blocked
+    IO and any new IO, so multipath can handle that.
+    
+    This patch also allows the fc and iscsi classes to implement the
+    same behavior. The timers are just unfornately named differently.
+    
+    This patch also fixes the problem where drivers were unblocking
+    the target in their terminate callback, which was needed for
+    rport removal, but for fast io fail timeout it would cause
+    IO to bounce arround the scsi/block layer and the LLD queuecommand.
+    And it for drivers that could have IO stuck but did not have
+    a terminate callback the unblock calls in the class will fix
+    them.
+    
+    v2.
+    - fix up bit setting style to meet JamesS's pref.
+    - Broke out new host byte error changes to make it easier to read.
+    - added JamesS's ack from list.
+    v1
+    - initial patch
+    
+    Signed-off-by: Mike Christie 
+    Acked-by: James Smart 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
+index d5f7653bb94b..1e71abf0607a 100644
+--- a/drivers/scsi/scsi_transport_fc.c
++++ b/drivers/scsi/scsi_transport_fc.c
+@@ -2133,8 +2133,7 @@ fc_attach_transport(struct fc_function_template *ft)
+ 	SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(roles);
+ 	SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(port_state);
+ 	SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(scsi_target_id);
+-	if (ft->terminate_rport_io)
+-		SETUP_PRIVATE_RPORT_ATTRIBUTE_RW(fast_io_fail_tmo);
++	SETUP_PRIVATE_RPORT_ATTRIBUTE_RW(fast_io_fail_tmo);
+ 
+ 	BUG_ON(count > FC_RPORT_NUM_ATTRS);
+ 
+@@ -2328,6 +2327,22 @@ fc_remove_host(struct Scsi_Host *shost)
+ }
+ EXPORT_SYMBOL(fc_remove_host);
+ 
++static void fc_terminate_rport_io(struct fc_rport *rport)
++{
++	struct Scsi_Host *shost = rport_to_shost(rport);
++	struct fc_internal *i = to_fc_internal(shost->transportt);
++
++	/* Involve the LLDD if possible to terminate all io on the rport. */
++	if (i->f->terminate_rport_io)
++		i->f->terminate_rport_io(rport);
++
++	/*
++	 * must unblock to flush queued IO. The caller will have set
++	 * the port_state or flags, so that fc_remote_port_chkready will
++	 * fail IO.
++	 */
++	scsi_target_unblock(&rport->dev);
++}
+ 
+ /**
+  * fc_starget_delete - called to delete the scsi decendents of an rport
+@@ -2340,13 +2355,8 @@ fc_starget_delete(struct work_struct *work)
+ {
+ 	struct fc_rport *rport =
+ 		container_of(work, struct fc_rport, stgt_delete_work);
+-	struct Scsi_Host *shost = rport_to_shost(rport);
+-	struct fc_internal *i = to_fc_internal(shost->transportt);
+-
+-	/* Involve the LLDD if possible to terminate all io on the rport. */
+-	if (i->f->terminate_rport_io)
+-		i->f->terminate_rport_io(rport);
+ 
++	fc_terminate_rport_io(rport);
+ 	scsi_remove_target(&rport->dev);
+ }
+ 
+@@ -2372,10 +2382,7 @@ fc_rport_final_delete(struct work_struct *work)
+ 	if (rport->flags & FC_RPORT_SCAN_PENDING)
+ 		scsi_flush_work(shost);
+ 
+-	/* involve the LLDD to terminate all pending i/o */
+-	if (i->f->terminate_rport_io)
+-		i->f->terminate_rport_io(rport);
+-
++	fc_terminate_rport_io(rport);
+ 	/*
+ 	 * Cancel any outstanding timers. These should really exist
+ 	 * only when rmmod'ing the LLDD and we're asking for
+@@ -2639,7 +2646,8 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
+ 
+ 				spin_lock_irqsave(shost->host_lock, flags);
+ 
+-				rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
++				rport->flags &= ~(FC_RPORT_FAST_FAIL_TIMEDOUT |
++						  FC_RPORT_DEVLOSS_PENDING);
+ 
+ 				/* if target, initiate a scan */
+ 				if (rport->scsi_target_id != -1) {
+@@ -2702,6 +2710,7 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
+ 			rport->port_id = ids->port_id;
+ 			rport->roles = ids->roles;
+ 			rport->port_state = FC_PORTSTATE_ONLINE;
++			rport->flags &= ~FC_RPORT_FAST_FAIL_TIMEDOUT;
+ 
+ 			if (fci->f->dd_fcrport_size)
+ 				memset(rport->dd_data, 0,
+@@ -2784,7 +2793,6 @@ void
+ fc_remote_port_delete(struct fc_rport  *rport)
+ {
+ 	struct Scsi_Host *shost = rport_to_shost(rport);
+-	struct fc_internal *i = to_fc_internal(shost->transportt);
+ 	int timeout = rport->dev_loss_tmo;
+ 	unsigned long flags;
+ 
+@@ -2830,7 +2838,7 @@ fc_remote_port_delete(struct fc_rport  *rport)
+ 
+ 	/* see if we need to kill io faster than waiting for device loss */
+ 	if ((rport->fast_io_fail_tmo != -1) &&
+-	    (rport->fast_io_fail_tmo < timeout) && (i->f->terminate_rport_io))
++	    (rport->fast_io_fail_tmo < timeout))
+ 		fc_queue_devloss_work(shost, &rport->fail_io_work,
+ 					rport->fast_io_fail_tmo * HZ);
+ 
+@@ -2906,7 +2914,8 @@ fc_remote_port_rolechg(struct fc_rport  *rport, u32 roles)
+ 			fc_flush_devloss(shost);
+ 
+ 		spin_lock_irqsave(shost->host_lock, flags);
+-		rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
++		rport->flags &= ~(FC_RPORT_FAST_FAIL_TIMEDOUT |
++				  FC_RPORT_DEVLOSS_PENDING);
+ 		spin_unlock_irqrestore(shost->host_lock, flags);
+ 
+ 		/* ensure any stgt delete functions are done */
+@@ -3001,6 +3010,7 @@ fc_timeout_deleted_rport(struct work_struct *work)
+ 	rport->supported_classes = FC_COS_UNSPECIFIED;
+ 	rport->roles = FC_PORT_ROLE_UNKNOWN;
+ 	rport->port_state = FC_PORTSTATE_NOTPRESENT;
++	rport->flags &= ~FC_RPORT_FAST_FAIL_TIMEDOUT;
+ 
+ 	/* remove the identifiers that aren't used in the consisting binding */
+ 	switch (fc_host->tgtid_bind_type) {
+@@ -3043,13 +3053,12 @@ fc_timeout_fail_rport_io(struct work_struct *work)
+ {
+ 	struct fc_rport *rport =
+ 		container_of(work, struct fc_rport, fail_io_work.work);
+-	struct Scsi_Host *shost = rport_to_shost(rport);
+-	struct fc_internal *i = to_fc_internal(shost->transportt);
+ 
+ 	if (rport->port_state != FC_PORTSTATE_BLOCKED)
+ 		return;
+ 
+-	i->f->terminate_rport_io(rport);
++	rport->flags |= FC_RPORT_FAST_FAIL_TIMEDOUT;
++	fc_terminate_rport_io(rport);
+ }
+ 
+ /**
+diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
+index 21018a4df452..fb8d01370663 100644
+--- a/include/scsi/scsi_transport_fc.h
++++ b/include/scsi/scsi_transport_fc.h
+@@ -357,6 +357,7 @@ struct fc_rport {	/* aka fc_starget_attrs */
+ /* bit field values for struct fc_rport "flags" field: */
+ #define FC_RPORT_DEVLOSS_PENDING	0x01
+ #define FC_RPORT_SCAN_PENDING		0x02
++#define FC_RPORT_FAST_FAIL_TIMEDOUT	0x03
+ 
+ #define	dev_to_rport(d)				\
+ 	container_of(d, struct fc_rport, dev)
+@@ -683,7 +684,10 @@ fc_remote_port_chkready(struct fc_rport *rport)
+ 			result = DID_NO_CONNECT << 16;
+ 		break;
+ 	case FC_PORTSTATE_BLOCKED:
+-		result = DID_IMM_RETRY << 16;
++		if (rport->flags & FC_RPORT_FAST_FAIL_TIMEDOUT)
++			result = DID_NO_CONNECT << 16;
++		else
++			result = DID_IMM_RETRY << 16;
+ 		break;
+ 	default:
+ 		result = DID_NO_CONNECT << 16;

commit a93ce0244f2e94dd48e0b4a2742a4e3bf196ab53
+Author: Mike Christie 
+Date:   Sun Aug 17 15:24:41 2008 -0500
+
+    [SCSI] lpfc: use SCSI_MLQUEUE_TARGET_BUSY when catching the rport transition race
+    
+    We do want to call right back into the queuecommand during the race,
+    so we can just use SCSI_MLQUEUE_TARGET_BUSY.
+    
+    Signed-off-by: Mike Christie 
+    Acked-by: James Smart 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
+index 1bcebbd3dfac..a22bdf9548a6 100644
+--- a/drivers/scsi/lpfc/lpfc_scsi.c
++++ b/drivers/scsi/lpfc/lpfc_scsi.c
+@@ -966,10 +966,9 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
+ 	 * Catch race where our node has transitioned, but the
+ 	 * transport is still transitioning.
+ 	 */
+-	if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
+-		cmnd->result = ScsiResult(DID_BUS_BUSY, 0);
+-		goto out_fail_command;
+-	}
++	if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
++		goto out_target_busy;
++
+ 	lpfc_cmd = lpfc_get_scsi_buf(phba);
+ 	if (lpfc_cmd == NULL) {
+ 		lpfc_adjust_queue_depth(phba);
+@@ -1014,6 +1013,8 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
+ 	lpfc_release_scsi_buf(phba, lpfc_cmd);
+  out_host_busy:
+ 	return SCSI_MLQUEUE_HOST_BUSY;
++ out_target_busy:
++	return SCSI_MLQUEUE_TARGET_BUSY;
+ 
+  out_fail_command:
+ 	done(cmnd);

commit d6d13ee19da6d291c99f980dcb76f6b7dc676804
+Author: Mike Christie 
+Date:   Sun Aug 17 15:24:43 2008 -0500
+
+    [SCSI] libiscsi: Use SCSI_MLQUEUE_TARGET_BUSY
+    
+    For the conditions below we do not want the queuecommand
+    function to call us right back, so return SCSI_MLQUEUE_TARGET_BUSY.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index da7b67d30d9a..521dbf7e521d 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1194,12 +1194,10 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 		switch (session->state) {
+ 		case ISCSI_STATE_IN_RECOVERY:
+ 			reason = FAILURE_SESSION_IN_RECOVERY;
+-			sc->result = DID_IMM_RETRY << 16;
+-			break;
++			goto reject;
+ 		case ISCSI_STATE_LOGGING_OUT:
+ 			reason = FAILURE_SESSION_LOGGING_OUT;
+-			sc->result = DID_IMM_RETRY << 16;
+-			break;
++			goto reject;
+ 		case ISCSI_STATE_RECOVERY_FAILED:
+ 			reason = FAILURE_SESSION_RECOVERY_TIMEOUT;
+ 			sc->result = DID_NO_CONNECT << 16;
+@@ -1267,7 +1265,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 	spin_unlock(&session->lock);
+ 	debug_scsi("cmd 0x%x rejected (%d)\n", sc->cmnd[0], reason);
+ 	spin_lock(host->host_lock);
+-	return SCSI_MLQUEUE_HOST_BUSY;
++	return SCSI_MLQUEUE_TARGET_BUSY;
+ 
+ fault:
+ 	spin_unlock(&session->lock);

commit 7b594131c4f38edeb13d8c6c0147949173c47013
+Author: Mike Christie 
+Date:   Sun Aug 17 15:24:40 2008 -0500
+
+    [SCSI] qla2xxx: return SCSI_MLQUEUE_TARGET_BUSY when driver has detected rport error or race
+    
+    If the fcport is not online then we do not want to block IO to all ports on
+    the host. We just want to stop IO on port not online, so we should be using
+    the SCSI_MLQUEUE_TARGET_BUSY return value.
+    
+    For the case where we race with the rport memset initialization
+    we do not want the queuecommand to be called again so we can just use
+    SCSI_MLQUEUE_TARGET_BUSY for this.
+    
+    Signed-off-by: Mike Christie 
+    Acked-by: Andrew Vasquez 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
+index 3433441b956a..2aed4721c0d0 100644
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -394,10 +394,8 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
+ 	}
+ 
+ 	/* Close window on fcport/rport state-transitioning. */
+-	if (fcport->drport) {
+-		cmd->result = DID_IMM_RETRY << 16;
+-		goto qc_fail_command;
+-	}
++	if (fcport->drport)
++		goto qc_target_busy;
+ 
+ 	if (atomic_read(&fcport->state) != FCS_ONLINE) {
+ 		if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
+@@ -405,7 +403,7 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
+ 			cmd->result = DID_NO_CONNECT << 16;
+ 			goto qc_fail_command;
+ 		}
+-		goto qc_host_busy;
++		goto qc_target_busy;
+ 	}
+ 
+ 	spin_unlock_irq(ha->host->host_lock);
+@@ -428,10 +426,11 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
+ 
+ qc_host_busy_lock:
+ 	spin_lock_irq(ha->host->host_lock);
+-
+-qc_host_busy:
+ 	return SCSI_MLQUEUE_HOST_BUSY;
+ 
++qc_target_busy:
++	return SCSI_MLQUEUE_TARGET_BUSY;
++
+ qc_fail_command:
+ 	done(cmd);
+ 
+@@ -461,10 +460,8 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
+ 	}
+ 
+ 	/* Close window on fcport/rport state-transitioning. */
+-	if (fcport->drport) {
+-		cmd->result = DID_IMM_RETRY << 16;
+-		goto qc24_fail_command;
+-	}
++	if (fcport->drport)
++		goto qc24_target_busy;
+ 
+ 	if (atomic_read(&fcport->state) != FCS_ONLINE) {
+ 		if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
+@@ -472,7 +469,7 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
+ 			cmd->result = DID_NO_CONNECT << 16;
+ 			goto qc24_fail_command;
+ 		}
+-		goto qc24_host_busy;
++		goto qc24_target_busy;
+ 	}
+ 
+ 	spin_unlock_irq(ha->host->host_lock);
+@@ -495,10 +492,11 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
+ 
+ qc24_host_busy_lock:
+ 	spin_lock_irq(ha->host->host_lock);
+-
+-qc24_host_busy:
+ 	return SCSI_MLQUEUE_HOST_BUSY;
+ 
++qc24_target_busy:
++	return SCSI_MLQUEUE_TARGET_BUSY;
++
+ qc24_fail_command:
+ 	done(cmd);
+ 

commit c5e98e912c5423a0ec2eed7aa1064578d44f8a8e
+Author: Mike Christie 
+Date:   Sun Aug 17 15:24:39 2008 -0500
+
+    [SCSI] qla4xxx: return SCSI_MLQUEUE_TARGET_BUSY when driver has detected session error
+    
+    When qla4xxx begins recovery and the iscsi class is firing up to handle
+    it, we need to retrn SCSI_MLQUEUE_TARGET_BUSY from the driver instead
+    of host busy, because the session recovery only affects the one target.
+    
+    Signed-off-by: Mike Christie 
+    Acked-by: David C Somayajulu 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index de8279ad7d89..4255b36ff968 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -439,7 +439,7 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
+ 			cmd->result = DID_NO_CONNECT << 16;
+ 			goto qc_fail_command;
+ 		}
+-		goto qc_host_busy;
++		return SCSI_MLQUEUE_TARGET_BUSY;
+ 	}
+ 
+ 	if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags))

commit f0c0a376d0fcd4c5579ecf5e95f88387cba85211
+Author: Mike Christie 
+Date:   Sun Aug 17 15:24:38 2008 -0500
+
+    [SCSI] Add helper code so transport classes/driver can control queueing (v3)
+    
+    SCSI-ml manages the queueing limits for the device and host, but
+    does not do so at the target level. However something something similar
+    can come in userful when a driver is transitioning a transport object to
+    the the blocked state, becuase at that time we do not want to queue
+    io and we do not want the queuecommand to be called again.
+    
+    The patch adds code similar to the exisiting SCSI_ML_*BUSY handlers.
+    You can now return SCSI_MLQUEUE_TARGET_BUSY when we hit
+    a transport level queueing issue like the hw cannot allocate some
+    resource at the iscsi session/connection level, or the target has temporarily
+    closed or shrunk the queueing window, or if we are transitioning
+    to the blocked state.
+    
+    bnx2i, when they rework their firmware according to netdev
+    developers requests, will also need to be able to limit queueing at this
+    level. bnx2i will hook into libiscsi, but will allocate a scsi host per
+    netdevice/hba, so unlike pure software iscsi/iser which is allocating
+    a host per session, it cannot set the scsi_host->can_queue and return
+    SCSI_MLQUEUE_HOST_BUSY to reflect queueing limits on the transport.
+    
+    The iscsi class/driver can also set a scsi_target->can_queue value which
+    reflects the max commands the driver/class can support. For iscsi this
+    reflects the number of commands we can support for each session due to
+    session/connection hw limits, driver limits, and to also reflect the
+    session/targets's queueing window.
+    
+    Changes:
+    v1 - initial patch.
+    v2 - Fix scsi_run_queue handling of multiple blocked targets.
+    Previously we would break from the main loop if a device was added back on
+    the starved list. We now run over the list and check if any target is
+    blocked.
+    v3 - Rediff for scsi-misc.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
+index 2ac3cb2b9081..f8b79d401d58 100644
+--- a/drivers/scsi/scsi.c
++++ b/drivers/scsi/scsi.c
+@@ -754,8 +754,12 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
+ 	}
+ 	spin_unlock_irqrestore(host->host_lock, flags);
+ 	if (rtn) {
+-		scsi_queue_insert(cmd, (rtn == SCSI_MLQUEUE_DEVICE_BUSY) ?
+-						rtn : SCSI_MLQUEUE_HOST_BUSY);
++		if (rtn != SCSI_MLQUEUE_DEVICE_BUSY &&
++		    rtn != SCSI_MLQUEUE_TARGET_BUSY)
++			rtn = SCSI_MLQUEUE_HOST_BUSY;
++
++		scsi_queue_insert(cmd, rtn);
++
+ 		SCSI_LOG_MLQUEUE(3,
+ 		    printk("queuecommand : request rejected\n"));
+ 	}
+@@ -800,6 +804,7 @@ static struct scsi_driver *scsi_cmd_to_driver(struct scsi_cmnd *cmd)
+ void scsi_finish_command(struct scsi_cmnd *cmd)
+ {
+ 	struct scsi_device *sdev = cmd->device;
++	struct scsi_target *starget = scsi_target(sdev);
+ 	struct Scsi_Host *shost = sdev->host;
+ 	struct scsi_driver *drv;
+ 	unsigned int good_bytes;
+@@ -815,6 +820,7 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
+ 	 * XXX(hch): What about locking?
+          */
+         shost->host_blocked = 0;
++	starget->target_blocked = 0;
+         sdev->device_blocked = 0;
+ 
+ 	/*
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index 98ee55ced592..91c74c55aa5e 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -114,6 +114,7 @@ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
+ {
+ 	struct Scsi_Host *host = cmd->device->host;
+ 	struct scsi_device *device = cmd->device;
++	struct scsi_target *starget = scsi_target(device);
+ 	struct request_queue *q = device->request_queue;
+ 	unsigned long flags;
+ 
+@@ -133,10 +134,17 @@ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
+ 	 * if a command is requeued with no other commands outstanding
+ 	 * either for the device or for the host.
+ 	 */
+-	if (reason == SCSI_MLQUEUE_HOST_BUSY)
++	switch (reason) {
++	case SCSI_MLQUEUE_HOST_BUSY:
+ 		host->host_blocked = host->max_host_blocked;
+-	else if (reason == SCSI_MLQUEUE_DEVICE_BUSY)
++		break;
++	case SCSI_MLQUEUE_DEVICE_BUSY:
+ 		device->device_blocked = device->max_device_blocked;
++		break;
++	case SCSI_MLQUEUE_TARGET_BUSY:
++		starget->target_blocked = starget->max_target_blocked;
++		break;
++	}
+ 
+ 	/*
+ 	 * Decrement the counters, since these commands are no longer
+@@ -460,10 +468,12 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd)
+ void scsi_device_unbusy(struct scsi_device *sdev)
+ {
+ 	struct Scsi_Host *shost = sdev->host;
++	struct scsi_target *starget = scsi_target(sdev);
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(shost->host_lock, flags);
+ 	shost->host_busy--;
++	starget->target_busy--;
+ 	if (unlikely(scsi_host_in_recovery(shost) &&
+ 		     (shost->host_failed || shost->host_eh_scheduled)))
+ 		scsi_eh_wakeup(shost);
+@@ -519,6 +529,13 @@ static void scsi_single_lun_run(struct scsi_device *current_sdev)
+ 	spin_unlock_irqrestore(shost->host_lock, flags);
+ }
+ 
++static inline int scsi_target_is_busy(struct scsi_target *starget)
++{
++	return ((starget->can_queue > 0 &&
++		 starget->target_busy >= starget->can_queue) ||
++		 starget->target_blocked);
++}
++
+ /*
+  * Function:	scsi_run_queue()
+  *
+@@ -533,7 +550,7 @@ static void scsi_single_lun_run(struct scsi_device *current_sdev)
+  */
+ static void scsi_run_queue(struct request_queue *q)
+ {
+-	struct scsi_device *sdev = q->queuedata;
++	struct scsi_device *starved_head = NULL, *sdev = q->queuedata;
+ 	struct Scsi_Host *shost = sdev->host;
+ 	unsigned long flags;
+ 
+@@ -560,6 +577,21 @@ static void scsi_run_queue(struct request_queue *q)
+ 		 */
+ 		sdev = list_entry(shost->starved_list.next,
+ 					  struct scsi_device, starved_entry);
++		/*
++		 * The *queue_ready functions can add a device back onto the
++		 * starved list's tail, so we must check for a infinite loop.
++		 */
++		if (sdev == starved_head)
++			break;
++		if (!starved_head)
++			starved_head = sdev;
++
++		if (scsi_target_is_busy(scsi_target(sdev))) {
++			list_move_tail(&sdev->starved_entry,
++				       &shost->starved_list);
++			continue;
++		}
++
+ 		list_del_init(&sdev->starved_entry);
+ 		spin_unlock(shost->host_lock);
+ 
+@@ -575,13 +607,6 @@ static void scsi_run_queue(struct request_queue *q)
+ 		spin_unlock(sdev->request_queue->queue_lock);
+ 
+ 		spin_lock(shost->host_lock);
+-		if (unlikely(!list_empty(&sdev->starved_entry)))
+-			/*
+-			 * sdev lost a race, and was put back on the
+-			 * starved list. This is unlikely but without this
+-			 * in theory we could loop forever.
+-			 */
+-			break;
+ 	}
+ 	spin_unlock_irqrestore(shost->host_lock, flags);
+ 
+@@ -1344,6 +1369,52 @@ static inline int scsi_dev_queue_ready(struct request_queue *q,
+ 	return 1;
+ }
+ 
++
++/*
++ * scsi_target_queue_ready: checks if there we can send commands to target
++ * @sdev: scsi device on starget to check.
++ *
++ * Called with the host lock held.
++ */
++static inline int scsi_target_queue_ready(struct Scsi_Host *shost,
++					   struct scsi_device *sdev)
++{
++	struct scsi_target *starget = scsi_target(sdev);
++
++	if (starget->single_lun) {
++		if (starget->starget_sdev_user &&
++		    starget->starget_sdev_user != sdev)
++			return 0;
++		starget->starget_sdev_user = sdev;
++	}
++
++	if (starget->target_busy == 0 && starget->target_blocked) {
++		/*
++		 * unblock after target_blocked iterates to zero
++		 */
++		if (--starget->target_blocked == 0) {
++			SCSI_LOG_MLQUEUE(3, starget_printk(KERN_INFO, starget,
++					 "unblocking target at zero depth\n"));
++		} else {
++			blk_plug_device(sdev->request_queue);
++			return 0;
++		}
++	}
++
++	if (scsi_target_is_busy(starget)) {
++		if (list_empty(&sdev->starved_entry)) {
++			list_add_tail(&sdev->starved_entry,
++				      &shost->starved_list);
++			return 0;
++		}
++	}
++
++	/* We're OK to process the command, so we can't be starved */
++	if (!list_empty(&sdev->starved_entry))
++		list_del_init(&sdev->starved_entry);
++	return 1;
++}
++
+ /*
+  * scsi_host_queue_ready: if we can send requests to shost, return 1 else
+  * return 0. We must end up running the queue again whenever 0 is
+@@ -1390,6 +1461,7 @@ static void scsi_kill_request(struct request *req, struct request_queue *q)
+ {
+ 	struct scsi_cmnd *cmd = req->special;
+ 	struct scsi_device *sdev = cmd->device;
++	struct scsi_target *starget = scsi_target(sdev);
+ 	struct Scsi_Host *shost = sdev->host;
+ 
+ 	blkdev_dequeue_request(req);
+@@ -1413,6 +1485,7 @@ static void scsi_kill_request(struct request *req, struct request_queue *q)
+ 	spin_unlock(sdev->request_queue->queue_lock);
+ 	spin_lock(shost->host_lock);
+ 	shost->host_busy++;
++	starget->target_busy++;
+ 	spin_unlock(shost->host_lock);
+ 	spin_lock(sdev->request_queue->queue_lock);
+ 
+@@ -1550,14 +1623,13 @@ static void scsi_request_fn(struct request_queue *q)
+ 			goto not_ready;
+ 		}
+ 
++		if (!scsi_target_queue_ready(shost, sdev))
++			goto not_ready;
++
+ 		if (!scsi_host_queue_ready(q, shost, sdev))
+ 			goto not_ready;
+-		if (scsi_target(sdev)->single_lun) {
+-			if (scsi_target(sdev)->starget_sdev_user &&
+-			    scsi_target(sdev)->starget_sdev_user != sdev)
+-				goto not_ready;
+-			scsi_target(sdev)->starget_sdev_user = sdev;
+-		}
++
++		scsi_target(sdev)->target_busy++;
+ 		shost->host_busy++;
+ 
+ 		/*
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+index 334862e26a1b..b14dc02c3ded 100644
+--- a/drivers/scsi/scsi_scan.c
++++ b/drivers/scsi/scsi_scan.c
+@@ -419,6 +419,7 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
+ 	dev->type = &scsi_target_type;
+ 	starget->id = id;
+ 	starget->channel = channel;
++	starget->can_queue = 0;
+ 	INIT_LIST_HEAD(&starget->siblings);
+ 	INIT_LIST_HEAD(&starget->devices);
+ 	starget->state = STARGET_CREATED;
+diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
+index 192f8716aa9e..3a5662b2817e 100644
+--- a/include/scsi/scsi.h
++++ b/include/scsi/scsi.h
+@@ -426,6 +426,7 @@ static inline int scsi_is_wlun(unsigned int lun)
+ #define SCSI_MLQUEUE_HOST_BUSY   0x1055
+ #define SCSI_MLQUEUE_DEVICE_BUSY 0x1056
+ #define SCSI_MLQUEUE_EH_RETRY    0x1057
++#define SCSI_MLQUEUE_TARGET_BUSY 0x1058
+ 
+ /*
+  *  Use these to separate status msg and our bytes
+diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
+index b49e725be039..a37a8148a310 100644
+--- a/include/scsi/scsi_device.h
++++ b/include/scsi/scsi_device.h
+@@ -238,6 +238,16 @@ struct scsi_target {
+ 						 * for the device at a time. */
+ 	unsigned int		pdt_1f_for_no_lun;	/* PDT = 0x1f */
+ 						/* means no lun present */
++	/* commands actually active on LLD. protected by host lock. */
++	unsigned int		target_busy;
++	/*
++	 * LLDs should set this in the slave_alloc host template callout.
++	 * If set to zero then there is not limit.
++	 */
++	unsigned int		can_queue;
++	unsigned int		target_blocked;
++	unsigned int		max_target_blocked;
++#define SCSI_DEFAULT_TARGET_BLOCKED	3
+ 
+ 	char			scsi_level;
+ 	struct execute_work	ew;

commit ac26d41dee65167109e7cdcd0289b44ca61cd741
+Author: Mike Christie 
+Date:   Sat Sep 6 08:39:15 2008 -0500
+
+    [SCSI] libiscsi: return error passed in during iscsi recovery
+    
+    Due to patch building error on my side, we are still passing DID_BUS_BUSY
+    for commands that are running, when we want to return whatever the caller
+    of fail_all_commands wanted. This replaces the hardcoded error code with
+    the value that is passed in.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 299e075a7b34..0b7457d558f7 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1456,7 +1456,7 @@ static void fail_all_commands(struct iscsi_conn *conn, unsigned lun,
+ 		if (lun == task->sc->device->lun || lun == -1) {
+ 			debug_scsi("failing in progress sc %p itt 0x%x\n",
+ 				   task->sc, task->itt);
+-			fail_command(conn, task, DID_BUS_BUSY << 16);
++			fail_command(conn, task, error << 16);
+ 		}
+ 	}
+ }

commit bb8fb4e6840ecebdc61f7ebd0653187e7128dde5
+Author: Mike Christie 
+Date:   Tue Sep 2 14:36:07 2008 -0700
+
+    ibft: fix target info parsing in ibft module
+    
+    I got this patch through Red Hat's bugzilla from the bug submitter and
+    patch creator.  I have just fixed it up so it applies without fuzz to
+    upstream kernels.
+    
+    Original patch and description from Shyam kumar Iyer:
+    
+    The issue [ibft module not displaying targets with short names] is because
+    of an offset calculatation error in the iscsi_ibft.c code.  Due to this
+    error directory structure for the target in /sys/firmware/ibft does not
+    get created and so the initiator is unable to connect to the target.
+    
+    Note that this bug surfaced only with an name that had a short section at
+    the end.  eg: "iqn.1984-05.com.dell:dell".  It did not surface when the
+    iqn's had a longer section at the end.  eg:
+    "iqn.2001-04.com.example:storage.disk2.sys1.xyz"
+    
+    So, the eot_offset was calculated such that an extra 48 bytes i.e.  the
+    size of the ibft_header which has already been accounted was subtracted
+    twice.
+    
+    This was not evident with longer iqn names because they would overshoot
+    the total ibft length more than 48 bytes and thus would escape the bug.
+    
+    Signed-off-by: Shyam Kumar Iyer 
+    Signed-off-by: Mike Christie 
+    Cc: Konrad Rzeszutek 
+    Cc: Peter Jones 
+    Cc: James Bottomley 
+    Cc: Greg Kroah-Hartman 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c
+index 8024e3bfd877..b91ef63126ed 100644
+--- a/drivers/firmware/iscsi_ibft.c
++++ b/drivers/firmware/iscsi_ibft.c
+@@ -669,8 +669,7 @@ static int __init ibft_register_kobjects(struct ibft_table_header *header,
+ 
+ 	control = (void *)header + sizeof(*header);
+ 	end = (void *)control + control->hdr.length;
+-	eot_offset = (void *)header + header->length -
+-		     (void *)control - sizeof(*header);
++	eot_offset = (void *)header + header->length - (void *)control;
+ 	rc = ibft_verify_hdr("control", (struct ibft_hdr *)control, id_control,
+ 			     sizeof(*control));
+ 

commit 6bd522f6a226f435508433d24e0de4619e016a9d
+Author: Mike Christie 
+Date:   Tue Jul 22 15:34:38 2008 -0500
+
+    [SCSI] scsi_lib: use blk_rq_tagged in scsi_request_fn
+    
+    I goofed and did not see the macro for checking if a request is tagged.
+    This patch has us use blk_rq_tagged instead of digging into the req->tag.
+    
+    Patch was made over scsi-misc.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index a20730c48020..6d62be664d55 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -1533,7 +1533,7 @@ static void scsi_request_fn(struct request_queue *q)
+ 		 * we add the dev to the starved list so it eventually gets
+ 		 * a run when a tag is freed.
+ 		 */
+-		if (blk_queue_tagged(q) && (req->tag == -1)) {
++		if (blk_queue_tagged(q) && !blk_rq_tagged(req)) {
+ 			if (list_empty(&sdev->starved_entry))
+ 				list_add_tail(&sdev->starved_entry,
+ 					      &shost->starved_list);

commit ecefe8a97577d6c1a68d14ab6fb19bce99448af2
+Author: Mike Christie 
+Date:   Fri Jul 11 19:50:35 2008 -0500
+
+    [SCSI] fix shared tag map tag allocation
+    
+    When drivers use a shared tag map we can end up with more requests
+    than tags, because the tag map is shost->can_queue tags and there
+    can be sdevs * sdev->queue_depth requests. In scsi_request_fn
+    if tag allocation fails we just drop down to just dequeueing the
+    tag without a tag. The problem is that drivers using the shared tag
+    map rely on a valid tag always being set, because it will use the
+    tag number to lookup commands later.
+    
+    This patch has us check if we got a valid tag when the host lock
+    is held right before we check if the host queue is ready. We do the
+    check here because to allocate the tag we need the q lock, but
+    if the tag is bad we want to add the device/q onto the starved list
+    which requires the host lock.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index 88d1b5f44e59..fe77ccacf319 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -1497,6 +1497,21 @@ static void scsi_request_fn(struct request_queue *q)
+ 		}
+ 		spin_lock(shost->host_lock);
+ 
++		/*
++		 * We hit this when the driver is using a host wide
++		 * tag map. For device level tag maps the queue_depth check
++		 * in the device ready fn would prevent us from trying
++		 * to allocate a tag. Since the map is a shared host resource
++		 * we add the dev to the starved list so it eventually gets
++		 * a run when a tag is freed.
++		 */
++		if (blk_queue_tagged(q) && (req->tag == -1)) {
++			if (list_empty(&sdev->starved_entry))
++				list_add_tail(&sdev->starved_entry,
++					      &shost->starved_list);
++			goto not_ready;
++		}
++
+ 		if (!scsi_host_queue_ready(q, shost, sdev))
+ 			goto not_ready;
+ 		if (scsi_target(sdev)->single_lun) {

commit 5d90027fb579eee41ec1b61f23195ed2fdd51da2
+Author: Mike Christie 
+Date:   Fri Jul 11 19:50:34 2008 -0500
+
+    [SCSI] stex: fix queue depth setting
+    
+    We want to set the queue depth to something reasonable - not
+    the can_queue.
+    
+    Signed-off-by: Mike Christie 
+    Cc: Ed Lin 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
+index f308a0308829..3790906a77d1 100644
+--- a/drivers/scsi/stex.c
++++ b/drivers/scsi/stex.c
+@@ -467,7 +467,7 @@ stex_slave_alloc(struct scsi_device *sdev)
+ 	/* Cheat: usually extracted from Inquiry data */
+ 	sdev->tagged_supported = 1;
+ 
+-	scsi_activate_tcq(sdev, sdev->host->can_queue);
++	scsi_activate_tcq(sdev, ST_CMD_PER_LUN);
+ 
+ 	return 0;
+ }

commit d510d965e17a81d4d41c03a3927f6ef450b73ff5
+Author: Mike Christie 
+Date:   Fri Jul 11 19:50:33 2008 -0500
+
+    [SCSI] qla4xxx: fix queue depth setting
+    
+    We want to set the queue depth to something reasonable - not
+    the can_queue.
+    
+    Signed-off-by: Mike Christie 
+    Cc: David Somayajulu 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index 5822dd595826..88bebb13bc52 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -46,6 +46,8 @@ MODULE_PARM_DESC(ql4xextended_error_logging,
+ 
+ int ql4_mod_unload = 0;
+ 
++#define QL4_DEF_QDEPTH 32
++
+ /*
+  * SCSI host template entry points
+  */
+@@ -1387,7 +1389,7 @@ static int qla4xxx_slave_alloc(struct scsi_device *sdev)
+ 
+ 	sdev->hostdata = ddb;
+ 	sdev->tagged_supported = 1;
+-	scsi_activate_tcq(sdev, sdev->host->can_queue);
++	scsi_activate_tcq(sdev, QL4_DEF_QDEPTH);
+ 	return 0;
+ }
+ 

commit 885ace9e2f120439043ffa1bb72a2fa1f3afc645
+Author: Mike Christie 
+Date:   Fri Jul 11 19:50:32 2008 -0500
+
+    [SCSI] fix shared tag map setup
+    
+    Currently qla4xxx and stex pass in their can_queue values into
+    scsi_activate_tcq because they wanted the tag map that large.
+    The problem with this is that it ends up also setting the queue
+    depth to that large value. All we want to do this in this case
+    is set the device queue depth and the other device settings.
+    We do not need to touch the tag map sizing because the drivers
+    had setup that map according to their can_queue limits when the
+    shared map was created.
+    
+    The scsi mid layer in request_fn will then handle the case where we
+    have more requests than available tags when it checks the host
+    queue ready function.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
+index 36c92f961e15..5276e73c58fc 100644
+--- a/drivers/scsi/scsi.c
++++ b/drivers/scsi/scsi.c
+@@ -902,11 +902,20 @@ void scsi_adjust_queue_depth(struct scsi_device *sdev, int tagged, int tags)
+ 
+ 	spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
+ 
+-	/* Check to see if the queue is managed by the block layer.
+-	 * If it is, and we fail to adjust the depth, exit. */
+-	if (blk_queue_tagged(sdev->request_queue) &&
+-	    blk_queue_resize_tags(sdev->request_queue, tags) != 0)
+-		goto out;
++	/*
++	 * Check to see if the queue is managed by the block layer.
++	 * If it is, and we fail to adjust the depth, exit.
++	 *
++	 * Do not resize the tag map if it is a host wide share bqt,
++	 * because the size should be the hosts's can_queue. If there
++	 * is more IO than the LLD's can_queue (so there are not enuogh
++	 * tags) request_fn's host queue ready check will handle it.
++	 */
++	if (!sdev->host->bqt) {
++		if (blk_queue_tagged(sdev->request_queue) &&
++		    blk_queue_resize_tags(sdev->request_queue, tags) != 0)
++			goto out;
++	}
+ 
+ 	sdev->queue_depth = tags;
+ 	switch (tagged) {

commit f80f868ec463b0463b332cdb704fe5438f013f98
+Author: Mike Christie 
+Date:   Mon Jun 16 10:11:35 2008 -0500
+
+    [SCSI] iscsi class: fix endpoint leak
+    
+    class_find_device gets a ref to the device so we must release it.
+    The class will serialize access to the ep so we do not have to worry
+    about a remove racing with the callers access, so we can simplify the
+    use and drop the ref right away.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 8e34f3c08575..3af7cbcc5c5d 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -219,6 +219,7 @@ EXPORT_SYMBOL_GPL(iscsi_destroy_endpoint);
+ 
+ struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
+ {
++	struct iscsi_endpoint *ep;
+ 	struct device *dev;
+ 
+ 	dev = class_find_device(&iscsi_endpoint_class, &handle,
+@@ -226,7 +227,13 @@ struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
+ 	if (!dev)
+ 		return NULL;
+ 
+-	return iscsi_dev_to_endpoint(dev);
++	ep = iscsi_dev_to_endpoint(dev);
++	/*
++	 * we can drop this now because the interface will prevent
++	 * removals and lookups from racing.
++	 */
++	put_device(dev);
++	return ep;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint);
+ 

commit 4c2133c82385c31dd3eed76b07da1e986eb00294
+Author: Mike Christie 
+Date:   Mon Jun 16 10:11:34 2008 -0500
+
+    [SCSI] iscsi class: update version number
+    
+    Update iscsi class version number.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index bc0f74d4ea09..8e34f3c08575 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -34,7 +34,7 @@
+ #define ISCSI_CONN_ATTRS 13
+ #define ISCSI_HOST_ATTRS 4
+ 
+-#define ISCSI_TRANSPORT_VERSION "2.0-869"
++#define ISCSI_TRANSPORT_VERSION "2.0-870"
+ 
+ struct iscsi_internal {
+ 	int daemon_pid;

commit 8e9a20cee4511be4560f9c858d9994eb6913731e
+Author: Mike Christie 
+Date:   Mon Jun 16 10:11:33 2008 -0500
+
+    [SCSI] libiscsi, iscsi_tcp, ib_iser: fix setting of can_queue with old tools.
+    
+    This patch fixes two bugs that are related.
+    
+    1. Old tools did not set can_queue/cmds_max. This patch modifies
+    libiscsi so that when we add the host we catch this and set it
+    to the default.
+    
+    2. iscsi_tcp thought that the scsi command that was passed to
+    the eh functions needed a iscsi_cmd_task allocated for it. It
+    only needed a mgmt task, and now it does not matter since it
+    all comes from the same pool and libiscsi handles this for the
+    drivers. ib_iser had copied iscsi_tcp's code and set can_queue
+    to its max - 1 to handle this. So this patch removes the max -1,
+    and just sets it to the max.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index c02eabd383a1..a56931e03976 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -595,7 +595,6 @@ static struct scsi_host_template iscsi_iser_sht = {
+ 	.name                   = "iSCSI Initiator over iSER, v." DRV_VER,
+ 	.queuecommand           = iscsi_queuecommand,
+ 	.change_queue_depth	= iscsi_change_queue_depth,
+-	.can_queue		= ISCSI_DEF_XMIT_CMDS_MAX - 1,
+ 	.sg_tablesize           = ISCSI_ISER_SG_TABLESIZE,
+ 	.max_sectors		= 1024,
+ 	.cmd_per_lun            = ISCSI_MAX_CMD_PER_LUN,
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 0bd8b3dc3c19..2a2f0094570f 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -1865,7 +1865,6 @@ iscsi_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
+ 	shost->max_id = 0;
+ 	shost->max_channel = 0;
+ 	shost->max_cmd_len = SCSI_MAX_VARLEN_CDB_SIZE;
+-	shost->can_queue = cmds_max;
+ 
+ 	if (iscsi_host_add(shost, NULL))
+ 		goto free_host;
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 8b4e412a0974..299e075a7b34 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1857,6 +1857,9 @@ EXPORT_SYMBOL_GPL(iscsi_pool_free);
+  */
+ int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev)
+ {
++	if (!shost->can_queue)
++		shost->can_queue = ISCSI_DEF_XMIT_CMDS_MAX;
++
+ 	return scsi_add_host(shost, pdev);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_host_add);
+@@ -1942,6 +1945,9 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
+ 	struct iscsi_session *session;
+ 	struct iscsi_cls_session *cls_session;
+ 	int cmd_i, scsi_cmds, total_cmds = cmds_max;
++
++	if (!total_cmds)
++		total_cmds = ISCSI_DEF_XMIT_CMDS_MAX;
+ 	/*
+ 	 * The iscsi layer needs some tasks for nop handling and tmfs,
+ 	 * so the cmds_max must at least be greater than ISCSI_MGMT_CMDS_MAX

commit c95fddc729fafb43f420747027eeb998c2e5e798
+Author: Mike Christie 
+Date:   Mon Jun 16 10:11:32 2008 -0500
+
+    [SCSI] iscsi class: fix refcount leak
+    
+    Must do a module_out if the endpoint lookup fails.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 9fd5c6d87ed1..bc0f74d4ea09 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -1422,8 +1422,10 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 		break;
+ 	case ISCSI_UEVENT_CREATE_BOUND_SESSION:
+ 		ep = iscsi_lookup_endpoint(ev->u.c_bound_session.ep_handle);
+-		if (!ep)
+-			return -EINVAL;
++		if (!ep) {
++			err = -EINVAL;
++			break;
++		}
+ 
+ 		err = iscsi_if_create_session(priv, ep, ev,
+ 					ev->u.c_bound_session.initial_cmdsn,

commit 913e5bf435617aa529919a4f7567f849f9f35f9f
+Author: Mike Christie 
+Date:   Wed May 21 15:54:18 2008 -0500
+
+    [SCSI] libiscsi, iser, tcp: remove recv_lock
+    
+    The recv lock was defined so the iscsi layer could block
+    the recv path from processing IO during recovery. It
+    turns out iser just set a lock to that pointer which was pointless.
+    
+    We now disconnect the transport connection before doing recovery
+    so we do not need the recv lock. For iscsi_tcp we still stop
+    the recv path incase older tools are being used.
+    
+    This patch also has iscsi_itt_to_ctask user grab the session lock
+    and has the caller access the task with the lock or get a ref
+    to it in case the target is broken and sends a tmf success response
+    then sends data or a response for the command that was supposed to
+    be affected bty the tmf.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 08edbaf89223..c02eabd383a1 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -281,9 +281,6 @@ iscsi_iser_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ 	conn->max_recv_dlength = 128;
+ 
+ 	iser_conn = conn->dd_data;
+-	/* currently this is the only field which need to be initiated */
+-	rwlock_init(&iser_conn->lock);
+-
+ 	conn->dd_data = iser_conn;
+ 	iser_conn->iscsi_conn = conn;
+ 
+@@ -342,9 +339,6 @@ iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session,
+ 	ib_conn->iser_conn = iser_conn;
+ 	iser_conn->ib_conn  = ib_conn;
+ 	iser_conn_get(ib_conn);
+-
+-	conn->recv_lock = &iser_conn->lock;
+-
+ 	return 0;
+ }
+ 
+@@ -355,12 +349,18 @@ iscsi_iser_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+ 	struct iscsi_iser_conn *iser_conn = conn->dd_data;
+ 	struct iser_conn *ib_conn = iser_conn->ib_conn;
+ 
+-	iscsi_conn_stop(cls_conn, flag);
+ 	/*
+-	 * There is no unbind event so the stop callback
+-	 * must release the ref from the bind.
++	 * Userspace may have goofed up and not bound the connection or
++	 * might have only partially setup the connection.
+ 	 */
+-	iser_conn_put(ib_conn);
++	if (ib_conn) {
++		iscsi_conn_stop(cls_conn, flag);
++		/*
++		 * There is no unbind event so the stop callback
++		 * must release the ref from the bind.
++		 */
++		iser_conn_put(ib_conn);
++	}
+ 	iser_conn->ib_conn = NULL;
+ }
+ 
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
+index cdf48763b082..a547edeea969 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
+@@ -263,8 +263,6 @@ struct iser_conn {
+ struct iscsi_iser_conn {
+ 	struct iscsi_conn            *iscsi_conn;/* ptr to iscsi conn */
+ 	struct iser_conn             *ib_conn;   /* iSER IB conn      */
+-
+-	rwlock_t		     lock;
+ };
+ 
+ struct iscsi_iser_task {
+diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
+index 35af60a23c61..c36083922134 100644
+--- a/drivers/infiniband/ulp/iser/iser_initiator.c
++++ b/drivers/infiniband/ulp/iser/iser_initiator.c
+@@ -558,7 +558,12 @@ void iser_rcv_completion(struct iser_desc *rx_desc,
+ 	opcode = hdr->opcode & ISCSI_OPCODE_MASK;
+ 
+ 	if (opcode == ISCSI_OP_SCSI_CMD_RSP) {
++		spin_lock(&conn->iscsi_conn->session->lock);
+ 		task = iscsi_itt_to_ctask(conn->iscsi_conn, hdr->itt);
++		if (task)
++			__iscsi_get_task(task);
++		spin_unlock(&conn->iscsi_conn->session->lock);
++
+ 		if (!task)
+ 			iser_err("itt can't be matched to task!!! "
+ 				 "conn %p opcode %d itt %d\n",
+@@ -568,6 +573,7 @@ void iser_rcv_completion(struct iser_desc *rx_desc,
+ 			iser_dbg("itt %d task %p\n",hdr->itt, task);
+ 			iser_task->status = ISER_TASK_STATUS_COMPLETED;
+ 			iser_task_rdma_finalize(iser_task);
++			iscsi_put_task(task);
+ 		}
+ 	}
+ 	iser_dto_buffs_release(dto);
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 7552dd8a88f3..91cb1fd523f0 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -741,7 +741,6 @@ static int
+ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ {
+ 	int rc = 0, opcode, ahslen;
+-	struct iscsi_session *session = conn->session;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	struct iscsi_task *task;
+ 
+@@ -770,17 +769,17 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 
+ 	switch(opcode) {
+ 	case ISCSI_OP_SCSI_DATA_IN:
++		spin_lock(&conn->session->lock);
+ 		task = iscsi_itt_to_ctask(conn, hdr->itt);
+ 		if (!task)
+-			return ISCSI_ERR_BAD_ITT;
+-		if (!task->sc)
+-			return ISCSI_ERR_NO_SCSI_CMD;
++			rc = ISCSI_ERR_BAD_ITT;
++		else
++			rc = iscsi_data_rsp(conn, task);
++		if (rc) {
++			spin_unlock(&conn->session->lock);
++			break;
++		}
+ 
+-		spin_lock(&conn->session->lock);
+-		rc = iscsi_data_rsp(conn, task);
+-		spin_unlock(&conn->session->lock);
+-		if (rc)
+-			return rc;
+ 		if (tcp_conn->in.datalen) {
+ 			struct iscsi_tcp_task *tcp_task = task->dd_data;
+ 			struct hash_desc *rx_hash = NULL;
+@@ -801,15 +800,19 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 				  "datalen=%d)\n", tcp_conn,
+ 				  tcp_task->data_offset,
+ 				  tcp_conn->in.datalen);
+-			return iscsi_segment_seek_sg(&tcp_conn->in.segment,
+-						     sdb->table.sgl,
+-						     sdb->table.nents,
+-						     tcp_task->data_offset,
+-						     tcp_conn->in.datalen,
+-						     iscsi_tcp_process_data_in,
+-						     rx_hash);
++			rc = iscsi_segment_seek_sg(&tcp_conn->in.segment,
++						   sdb->table.sgl,
++						   sdb->table.nents,
++						   tcp_task->data_offset,
++						   tcp_conn->in.datalen,
++						   iscsi_tcp_process_data_in,
++						   rx_hash);
++			spin_unlock(&conn->session->lock);
++			return rc;
+ 		}
+-		/* fall through */
++		rc = __iscsi_complete_pdu(conn, hdr, NULL, 0);
++		spin_unlock(&conn->session->lock);
++		break;
+ 	case ISCSI_OP_SCSI_CMD_RSP:
+ 		if (tcp_conn->in.datalen) {
+ 			iscsi_tcp_data_recv_prep(tcp_conn);
+@@ -818,20 +821,17 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 		rc = iscsi_complete_pdu(conn, hdr, NULL, 0);
+ 		break;
+ 	case ISCSI_OP_R2T:
++		spin_lock(&conn->session->lock);
+ 		task = iscsi_itt_to_ctask(conn, hdr->itt);
+ 		if (!task)
+-			return ISCSI_ERR_BAD_ITT;
+-		if (!task->sc)
+-			return ISCSI_ERR_NO_SCSI_CMD;
+-
+-		if (ahslen)
++			rc = ISCSI_ERR_BAD_ITT;
++		else if (ahslen)
+ 			rc = ISCSI_ERR_AHSLEN;
+-		else if (task->sc->sc_data_direction == DMA_TO_DEVICE) {
+-			spin_lock(&session->lock);
++		else if (task->sc->sc_data_direction == DMA_TO_DEVICE)
+ 			rc = iscsi_r2t_rsp(conn, task);
+-			spin_unlock(&session->lock);
+-		} else
++		else
+ 			rc = ISCSI_ERR_PROTO;
++		spin_unlock(&conn->session->lock);
+ 		break;
+ 	case ISCSI_OP_LOGIN_RSP:
+ 	case ISCSI_OP_TEXT_RSP:
+@@ -1553,7 +1553,6 @@ iscsi_tcp_release_conn(struct iscsi_conn *conn)
+ 
+ 	spin_lock_bh(&session->lock);
+ 	tcp_conn->sock = NULL;
+-	conn->recv_lock = NULL;
+ 	spin_unlock_bh(&session->lock);
+ 	sockfd_put(sock);
+ }
+@@ -1578,6 +1577,19 @@ static void
+ iscsi_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+ {
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++
++	/* userspace may have goofed up and not bound us */
++	if (!tcp_conn->sock)
++		return;
++	/*
++	 * Make sure our recv side is stopped.
++	 * Older tools called conn stop before ep_disconnect
++	 * so IO could still be coming in.
++	 */
++	write_lock_bh(&tcp_conn->sock->sk->sk_callback_lock);
++	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
++	write_unlock_bh(&tcp_conn->sock->sk->sk_callback_lock);
+ 
+ 	iscsi_conn_stop(cls_conn, flag);
+ 	iscsi_tcp_release_conn(conn);
+@@ -1671,13 +1683,6 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
+ 	sk->sk_sndtimeo = 15 * HZ; /* FIXME: make it configurable */
+ 	sk->sk_allocation = GFP_ATOMIC;
+ 
+-	/* FIXME: disable Nagle's algorithm */
+-
+-	/*
+-	 * Intercept TCP callbacks for sendfile like receive
+-	 * processing.
+-	 */
+-	conn->recv_lock = &sk->sk_callback_lock;
+ 	iscsi_conn_set_callbacks(conn);
+ 	tcp_conn->sendpage = tcp_conn->sock->ops->sendpage;
+ 	/*
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index c723e60f02b0..9c267b440444 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -362,10 +362,11 @@ static void iscsi_complete_command(struct iscsi_task *task)
+ 	}
+ }
+ 
+-static void __iscsi_get_task(struct iscsi_task *task)
++void __iscsi_get_task(struct iscsi_task *task)
+ {
+ 	atomic_inc(&task->refcount);
+ }
++EXPORT_SYMBOL_GPL(__iscsi_get_task);
+ 
+ static void __iscsi_put_task(struct iscsi_task *task)
+ {
+@@ -403,9 +404,13 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_task *task,
+ 		conn->session->queued_cmdsn--;
+ 	else
+ 		conn->session->tt->cleanup_task(conn, task);
++	/*
++	 * Check if cleanup_task dropped the lock and the command completed,
++	 */
++	if (!task->sc)
++		return;
+ 
+ 	sc->result = err;
+-
+ 	if (!scsi_bidi_cmnd(sc))
+ 		scsi_set_resid(sc, scsi_bufflen(sc));
+ 	else {
+@@ -696,6 +701,31 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	return 0;
+ }
+ 
++/**
++ * iscsi_itt_to_task - look up task by itt
++ * @conn: iscsi connection
++ * @itt: itt
++ *
++ * This should be used for mgmt tasks like login and nops, or if
++ * the LDD's itt space does not include the session age.
++ *
++ * The session lock must be held.
++ */
++static struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *conn, itt_t itt)
++{
++	struct iscsi_session *session = conn->session;
++	uint32_t i;
++
++	if (itt == RESERVED_ITT)
++		return NULL;
++
++	i = get_itt(itt);
++	if (i >= session->cmds_max)
++		return NULL;
++
++	return session->cmds[i];
++}
++
+ /**
+  * __iscsi_complete_pdu - complete pdu
+  * @conn: iscsi conn
+@@ -707,8 +737,8 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+  * queuecommand or send generic. session lock must be held and verify
+  * itt must have been called.
+  */
+-static int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+-				char *data, int datalen)
++int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
++			 char *data, int datalen)
+ {
+ 	struct iscsi_session *session = conn->session;
+ 	int opcode = hdr->opcode & ISCSI_OPCODE_MASK, rc = 0;
+@@ -758,22 +788,36 @@ static int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		goto out;
+ 	}
+ 
+-	task = session->cmds[itt];
+ 	switch(opcode) {
+ 	case ISCSI_OP_SCSI_CMD_RSP:
+-		if (!task->sc) {
+-			rc = ISCSI_ERR_NO_SCSI_CMD;
+-			break;
+-		}
+-		BUG_ON((void*)task != task->sc->SCp.ptr);
++	case ISCSI_OP_SCSI_DATA_IN:
++		task = iscsi_itt_to_ctask(conn, hdr->itt);
++		if (!task)
++			return ISCSI_ERR_BAD_ITT;
++		break;
++	case ISCSI_OP_R2T:
++		/*
++		 * LLD handles R2Ts if they need to.
++		 */
++		return 0;
++	case ISCSI_OP_LOGOUT_RSP:
++	case ISCSI_OP_LOGIN_RSP:
++	case ISCSI_OP_TEXT_RSP:
++	case ISCSI_OP_SCSI_TMFUNC_RSP:
++	case ISCSI_OP_NOOP_IN:
++		task = iscsi_itt_to_task(conn, hdr->itt);
++		if (!task)
++			return ISCSI_ERR_BAD_ITT;
++		break;
++	default:
++		return ISCSI_ERR_BAD_OPCODE;
++	}
++
++	switch(opcode) {
++	case ISCSI_OP_SCSI_CMD_RSP:
+ 		iscsi_scsi_cmd_rsp(conn, hdr, task, data, datalen);
+ 		break;
+ 	case ISCSI_OP_SCSI_DATA_IN:
+-		if (!task->sc) {
+-			rc = ISCSI_ERR_NO_SCSI_CMD;
+-			break;
+-		}
+-		BUG_ON((void*)task != task->sc->SCp.ptr);
+ 		if (hdr->flags & ISCSI_FLAG_DATA_STATUS) {
+ 			conn->scsirsp_pdus_cnt++;
+ 			iscsi_update_cmdsn(session,
+@@ -781,9 +825,6 @@ static int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			__iscsi_put_task(task);
+ 		}
+ 		break;
+-	case ISCSI_OP_R2T:
+-		/* LLD handles this for now */
+-		break;
+ 	case ISCSI_OP_LOGOUT_RSP:
+ 		iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
+ 		if (datalen) {
+@@ -841,6 +882,7 @@ static int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	__iscsi_put_task(task);
+ 	return rc;
+ }
++EXPORT_SYMBOL_GPL(__iscsi_complete_pdu);
+ 
+ int iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		       char *data, int datalen)
+@@ -857,7 +899,6 @@ EXPORT_SYMBOL_GPL(iscsi_complete_pdu);
+ int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt)
+ {
+ 	struct iscsi_session *session = conn->session;
+-	struct iscsi_task *task;
+ 	uint32_t i;
+ 
+ 	if (itt == RESERVED_ITT)
+@@ -867,8 +908,7 @@ int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt)
+ 	    (session->age << ISCSI_AGE_SHIFT)) {
+ 		iscsi_conn_printk(KERN_ERR, conn,
+ 				  "received itt %x expected session age (%x)\n",
+-				  (__force u32)itt,
+-				  session->age & ISCSI_AGE_MASK);
++				  (__force u32)itt, session->age);
+ 		return ISCSI_ERR_BAD_ITT;
+ 	}
+ 
+@@ -879,42 +919,36 @@ int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt)
+ 				   "%u.\n", i, session->cmds_max);
+ 		return ISCSI_ERR_BAD_ITT;
+ 	}
+-
+-	task = session->cmds[i];
+-	if (task->sc && task->sc->SCp.phase != session->age) {
+-		iscsi_conn_printk(KERN_ERR, conn,
+-				  "iscsi: task's session age %d, "
+-				  "expected %d\n", task->sc->SCp.phase,
+-				  session->age);
+-		return ISCSI_ERR_SESSION_FAILED;
+-	}
+ 	return 0;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_verify_itt);
+ 
+-struct iscsi_task *
+-iscsi_itt_to_ctask(struct iscsi_conn *conn, itt_t itt)
++/**
++ * iscsi_itt_to_ctask - look up ctask by itt
++ * @conn: iscsi connection
++ * @itt: itt
++ *
++ * This should be used for cmd tasks.
++ *
++ * The session lock must be held.
++ */
++struct iscsi_task *iscsi_itt_to_ctask(struct iscsi_conn *conn, itt_t itt)
+ {
+-	struct iscsi_session *session = conn->session;
+ 	struct iscsi_task *task;
+-	uint32_t i;
+ 
+ 	if (iscsi_verify_itt(conn, itt))
+ 		return NULL;
+ 
+-	if (itt == RESERVED_ITT)
++	task = iscsi_itt_to_task(conn, itt);
++	if (!task || !task->sc)
+ 		return NULL;
+ 
+-	i = get_itt(itt);
+-	if (i >= session->cmds_max)
+-		return NULL;
+-
+-	task = session->cmds[i];
+-	if (!task->sc)
+-		return NULL;
+-
+-	if (task->sc->SCp.phase != session->age)
++	if (task->sc->SCp.phase != conn->session->age) {
++		iscsi_session_printk(KERN_ERR, conn->session,
++				  "task's session age %d, expected %d\n",
++				  task->sc->SCp.phase, conn->session->age);
+ 		return NULL;
++	}
+ 
+ 	return task;
+ }
+@@ -1620,16 +1654,20 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 	switch (conn->tmf_state) {
+ 	case TMF_SUCCESS:
+ 		spin_unlock_bh(&session->lock);
++		/*
++		 * stop tx side incase the target had sent a abort rsp but
++		 * the initiator was still writing out data.
++		 */
+ 		iscsi_suspend_tx(conn);
+ 		/*
+-		 * clean up task if aborted. grab the recv lock as a writer
++		 * we do not stop the recv side because targets have been
++		 * good and have never sent us a successful tmf response
++		 * then sent more data for the cmd.
+ 		 */
+-		write_lock_bh(conn->recv_lock);
+ 		spin_lock(&session->lock);
+ 		fail_command(conn, task, DID_ABORT << 16);
+ 		conn->tmf_state = TMF_INITIAL;
+ 		spin_unlock(&session->lock);
+-		write_unlock_bh(conn->recv_lock);
+ 		iscsi_start_tx(conn);
+ 		goto success_unlocked;
+ 	case TMF_TIMEDOUT:
+@@ -1729,13 +1767,11 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc)
+ 	spin_unlock_bh(&session->lock);
+ 
+ 	iscsi_suspend_tx(conn);
+-	/* need to grab the recv lock then session lock */
+-	write_lock_bh(conn->recv_lock);
++
+ 	spin_lock(&session->lock);
+ 	fail_all_commands(conn, sc->device->lun, DID_ERROR);
+ 	conn->tmf_state = TMF_INITIAL;
+ 	spin_unlock(&session->lock);
+-	write_unlock_bh(conn->recv_lock);
+ 
+ 	iscsi_start_tx(conn);
+ 	goto done;
+@@ -2256,17 +2292,6 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ 		return;
+ 	}
+ 
+-	/*
+-	 * The LLD either freed/unset the lock on us, or userspace called
+-	 * stop but did not create a proper connection (connection was never
+-	 * bound or it was unbound then stop was called).
+-	 */
+-	if (!conn->recv_lock) {
+-		spin_unlock_bh(&session->lock);
+-		mutex_unlock(&session->eh_mutex);
+-		return;
+-	}
+-
+ 	/*
+ 	 * When this is called for the in_login state, we only want to clean
+ 	 * up the login task and connection. We do not need to block and set
+@@ -2283,11 +2308,6 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ 	spin_unlock_bh(&session->lock);
+ 
+ 	iscsi_suspend_tx(conn);
+-
+-	write_lock_bh(conn->recv_lock);
+-	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
+-	write_unlock_bh(conn->recv_lock);
+-
+ 	/*
+ 	 * for connection level recovery we should not calculate
+ 	 * header digest. conn->hdr_size used for optimization
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 5bf0187e7520..5e75bb7f311c 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -138,11 +138,6 @@ struct iscsi_conn {
+ 	struct iscsi_cls_conn	*cls_conn;	/* ptr to class connection */
+ 	void			*dd_data;	/* iscsi_transport data */
+ 	struct iscsi_session	*session;	/* parent session */
+-	/*
+-	 * LLDs should set this lock. It protects the transport recv
+-	 * code
+-	 */
+-	rwlock_t		*recv_lock;
+ 	/*
+ 	 * conn_stop() flag: stop to recover, stop to terminate
+ 	 */
+@@ -374,10 +369,13 @@ extern int iscsi_conn_send_pdu(struct iscsi_cls_conn *, struct iscsi_hdr *,
+ 				char *, uint32_t);
+ extern int iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *,
+ 			      char *, int);
++extern int __iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *,
++				char *, int);
+ extern int iscsi_verify_itt(struct iscsi_conn *, itt_t);
+ extern struct iscsi_task *iscsi_itt_to_ctask(struct iscsi_conn *, itt_t);
+ extern void iscsi_requeue_task(struct iscsi_task *task);
+ extern void iscsi_put_task(struct iscsi_task *task);
++extern void __iscsi_get_task(struct iscsi_task *task);
+ 
+ /*
+  * generic helpers

commit 3cf7b233ffc45d4fc381221f74d24f10e692c4ea
+Author: Mike Christie 
+Date:   Wed May 21 15:54:17 2008 -0500
+
+    [SCSI] libiscsi: fix cmds_max setting
+    
+    Drivers expect that the cmds_max value they pass to the iscsi layer
+    is the max scsi commands  + mgmt tasks. This patch implements that
+    and fixes some checks for nr cmd limits.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index c1af2aa8e4e0..c723e60f02b0 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1893,29 +1893,48 @@ EXPORT_SYMBOL_GPL(iscsi_host_free);
+  *
+  * This can be used by software iscsi_transports that allocate
+  * a session per scsi host.
++ *
++ * Callers should set cmds_max to the largest total numer (mgmt + scsi) of
++ * tasks they support. The iscsi layer reserves ISCSI_MGMT_CMDS_MAX tasks
++ * for nop handling and login/logout requests.
+  */
+ struct iscsi_cls_session *
+ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
+-		    uint16_t scsi_cmds_max, int cmd_task_size,
++		    uint16_t cmds_max, int cmd_task_size,
+ 		    uint32_t initial_cmdsn, unsigned int id)
+ {
+ 	struct iscsi_session *session;
+ 	struct iscsi_cls_session *cls_session;
+-	int cmd_i, cmds_max;
+-
++	int cmd_i, scsi_cmds, total_cmds = cmds_max;
+ 	/*
+-	 * The iscsi layer needs some tasks for nop handling and tmfs.
++	 * The iscsi layer needs some tasks for nop handling and tmfs,
++	 * so the cmds_max must at least be greater than ISCSI_MGMT_CMDS_MAX
++	 * + 1 command for scsi IO.
+ 	 */
+-	if (scsi_cmds_max < 1)
+-		scsi_cmds_max = ISCSI_MGMT_CMDS_MAX;
+-	if ((scsi_cmds_max + ISCSI_MGMT_CMDS_MAX) >= ISCSI_MGMT_ITT_OFFSET) {
+-		printk(KERN_ERR "iscsi: invalid can_queue of %d. "
+-		       "can_queue must be less than %d.\n",
+-		       scsi_cmds_max,
+-		       ISCSI_MGMT_ITT_OFFSET - ISCSI_MGMT_CMDS_MAX);
+-		scsi_cmds_max = ISCSI_DEF_XMIT_CMDS_MAX;
++	if (total_cmds < ISCSI_TOTAL_CMDS_MIN) {
++		printk(KERN_ERR "iscsi: invalid can_queue of %d. can_queue "
++		       "must be a power of two that is at least %d.\n",
++		       total_cmds, ISCSI_TOTAL_CMDS_MIN);
++		return NULL;
++	}
++
++	if (total_cmds > ISCSI_TOTAL_CMDS_MAX) {
++		printk(KERN_ERR "iscsi: invalid can_queue of %d. can_queue "
++		       "must be a power of 2 less than or equal to %d.\n",
++		       cmds_max, ISCSI_TOTAL_CMDS_MAX);
++		total_cmds = ISCSI_TOTAL_CMDS_MAX;
++	}
++
++	if (!is_power_of_2(total_cmds)) {
++		printk(KERN_ERR "iscsi: invalid can_queue of %d. can_queue "
++		       "must be a power of 2.\n", total_cmds);
++		total_cmds = rounddown_pow_of_two(total_cmds);
++		if (total_cmds < ISCSI_TOTAL_CMDS_MIN)
++			return NULL;
++		printk(KERN_INFO "iscsi: Rounding can_queue to %d.\n",
++		       total_cmds);
+ 	}
+-	cmds_max = roundup_pow_of_two(scsi_cmds_max + ISCSI_MGMT_CMDS_MAX);
++	scsi_cmds = total_cmds - ISCSI_MGMT_CMDS_MAX;
+ 
+ 	cls_session = iscsi_alloc_session(shost, iscsit,
+ 					  sizeof(struct iscsi_session));
+@@ -1928,8 +1947,8 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
+ 	session->fast_abort = 1;
+ 	session->lu_reset_timeout = 15;
+ 	session->abort_timeout = 10;
+-	session->scsi_cmds_max = scsi_cmds_max;
+-	session->cmds_max = cmds_max;
++	session->scsi_cmds_max = scsi_cmds;
++	session->cmds_max = total_cmds;
+ 	session->queued_cmdsn = session->cmdsn = initial_cmdsn;
+ 	session->exp_cmdsn = initial_cmdsn + 1;
+ 	session->max_cmdsn = initial_cmdsn + 1;
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 21cfb1d5483f..5bf0187e7520 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -52,9 +52,7 @@ struct device;
+ #endif
+ 
+ #define ISCSI_DEF_XMIT_CMDS_MAX	128	/* must be power of 2 */
+-#define ISCSI_MGMT_CMDS_MAX	16	/* must be power of 2 */
+-
+-#define ISCSI_MGMT_ITT_OFFSET	0xa00
++#define ISCSI_MGMT_CMDS_MAX	15
+ 
+ #define ISCSI_DEF_CMD_PER_LUN		32
+ #define ISCSI_MAX_CMD_PER_LUN		128
+@@ -72,7 +70,10 @@ enum {
+ /* Connection suspend "bit" */
+ #define ISCSI_SUSPEND_BIT		1
+ 
+-#define ISCSI_ITT_MASK			(0xfff)
++#define ISCSI_ITT_MASK			(0x1fff)
++#define ISCSI_TOTAL_CMDS_MAX		4096
++/* this must be a power of two greater than ISCSI_MGMT_CMDS_MAX */
++#define ISCSI_TOTAL_CMDS_MIN		16
+ #define ISCSI_AGE_SHIFT			28
+ #define ISCSI_AGE_MASK			(0xf << ISCSI_AGE_SHIFT)
+ 

commit 88dfd340b9dece8fcaa1a2d4c782338926c017f7
+Author: Mike Christie 
+Date:   Wed May 21 15:54:16 2008 -0500
+
+    [SCSI] iscsi class: Add session initiatorname and ifacename sysfs attrs.
+    
+    This adds two new attrs used for creating initiator ports and
+    binding sessions to hardware.
+    
+    The session level initiatorname:
+    
+    Since bnx2i does a scsi_host per host device, we need to add the
+    iface initiator port settings on the session, so we can create
+    multiple initiator ports (each with different inames) per device/scsi_host.
+    
+    The current iname reflects that qla4xxx can have one iname per hba, and we are
+    allocating a host per session for software. The iname on the host will
+    remain so we can export and set the hba level qla4xxx setting.
+    
+    The ifacename attr:
+    
+    To bind a session to a some peice of hardware in userspace we maintain
+    some mappings, but during boot or iscsid restart (iscsid contains the user
+    space part of the driver) we need to be able to figure out which of those
+    host mappings abstractions maps to certain sessions. This patch adds
+    a ifacename attr, which userspace can set to id the host side of the
+    endpoint across pivot_roots and iscsid restarts.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 42e95b833092..08edbaf89223 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -629,7 +629,8 @@ static struct iscsi_transport iscsi_iser_transport = {
+ 				  ISCSI_USERNAME | ISCSI_PASSWORD |
+ 				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+ 				  ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+-				  ISCSI_PING_TMO | ISCSI_RECV_TMO,
++				  ISCSI_PING_TMO | ISCSI_RECV_TMO |
++				  ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS |
+ 				  ISCSI_HOST_NETDEV_NAME |
+ 				  ISCSI_HOST_INITIATOR_NAME,
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 92d031959002..7552dd8a88f3 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -1957,7 +1957,8 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+ 				  ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+ 				  ISCSI_LU_RESET_TMO |
+-				  ISCSI_PING_TMO | ISCSI_RECV_TMO,
++				  ISCSI_PING_TMO | ISCSI_RECV_TMO |
++				  ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+ 				  ISCSI_HOST_INITIATOR_NAME |
+ 				  ISCSI_HOST_NETDEV_NAME,
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index e88b726ab2e0..c1af2aa8e4e0 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1990,6 +1990,8 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+ 	kfree(session->username);
+ 	kfree(session->username_in);
+ 	kfree(session->targetname);
++	kfree(session->initiatorname);
++	kfree(session->ifacename);
+ 
+ 	iscsi_destroy_session(cls_session);
+ 	module_put(owner);
+@@ -2453,6 +2455,14 @@ int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
+ 		if (!conn->persistent_address)
+ 			return -ENOMEM;
+ 		break;
++	case ISCSI_PARAM_IFACE_NAME:
++		if (!session->ifacename)
++			session->ifacename = kstrdup(buf, GFP_KERNEL);
++		break;
++	case ISCSI_PARAM_INITIATOR_NAME:
++		if (!session->initiatorname)
++			session->initiatorname = kstrdup(buf, GFP_KERNEL);
++		break;
+ 	default:
+ 		return -ENOSYS;
+ 	}
+@@ -2519,6 +2529,15 @@ int iscsi_session_get_param(struct iscsi_cls_session *cls_session,
+ 	case ISCSI_PARAM_PASSWORD_IN:
+ 		len = sprintf(buf, "%s\n", session->password_in);
+ 		break;
++	case ISCSI_PARAM_IFACE_NAME:
++		len = sprintf(buf, "%s\n", session->ifacename);
++		break;
++	case ISCSI_PARAM_INITIATOR_NAME:
++		if (!session->initiatorname)
++			len = sprintf(buf, "%s\n", "unknown");
++		else
++			len = sprintf(buf, "%s\n", session->initiatorname);
++		break;
+ 	default:
+ 		return -ENOSYS;
+ 	}
+@@ -2606,6 +2625,7 @@ int iscsi_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param,
+ 		else
+ 			len = sprintf(buf, "%s\n",
+ 				      ihost->local_address);
++		break;
+ 	default:
+ 		return -ENOSYS;
+ 	}
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index c3c07ccccca7..9fd5c6d87ed1 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -30,7 +30,7 @@
+ #include 
+ #include 
+ 
+-#define ISCSI_SESSION_ATTRS 19
++#define ISCSI_SESSION_ATTRS 21
+ #define ISCSI_CONN_ATTRS 13
+ #define ISCSI_HOST_ATTRS 4
+ 
+@@ -1634,6 +1634,8 @@ iscsi_session_attr(password_in, ISCSI_PARAM_PASSWORD_IN, 1);
+ iscsi_session_attr(fast_abort, ISCSI_PARAM_FAST_ABORT, 0);
+ iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0);
+ iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 0);
++iscsi_session_attr(ifacename, ISCSI_PARAM_IFACE_NAME, 0);
++iscsi_session_attr(initiatorname, ISCSI_PARAM_INITIATOR_NAME, 0)
+ 
+ static ssize_t
+ show_priv_session_state(struct device *dev, struct device_attribute *attr,
+@@ -1875,6 +1877,8 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 	SETUP_SESSION_RD_ATTR(fast_abort, ISCSI_FAST_ABORT);
+ 	SETUP_SESSION_RD_ATTR(abort_tmo, ISCSI_ABORT_TMO);
+ 	SETUP_SESSION_RD_ATTR(lu_reset_tmo,ISCSI_LU_RESET_TMO);
++	SETUP_SESSION_RD_ATTR(ifacename, ISCSI_IFACE_NAME);
++	SETUP_SESSION_RD_ATTR(initiatorname, ISCSI_INITIATOR_NAME);
+ 	SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo);
+ 	SETUP_PRIV_SESSION_RD_ATTR(state);
+ 
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index a0f13a280e71..16be12f1cbe8 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -257,42 +257,49 @@ enum iscsi_param {
+ 
+ 	ISCSI_PARAM_PING_TMO,
+ 	ISCSI_PARAM_RECV_TMO,
++
++	ISCSI_PARAM_IFACE_NAME,
++	ISCSI_PARAM_ISID,
++	ISCSI_PARAM_INITIATOR_NAME,
+ 	/* must always be last */
+ 	ISCSI_PARAM_MAX,
+ };
+ 
+-#define ISCSI_MAX_RECV_DLENGTH		(1 << ISCSI_PARAM_MAX_RECV_DLENGTH)
+-#define ISCSI_MAX_XMIT_DLENGTH		(1 << ISCSI_PARAM_MAX_XMIT_DLENGTH)
+-#define ISCSI_HDRDGST_EN		(1 << ISCSI_PARAM_HDRDGST_EN)
+-#define ISCSI_DATADGST_EN		(1 << ISCSI_PARAM_DATADGST_EN)
+-#define ISCSI_INITIAL_R2T_EN		(1 << ISCSI_PARAM_INITIAL_R2T_EN)
+-#define ISCSI_MAX_R2T			(1 << ISCSI_PARAM_MAX_R2T)
+-#define ISCSI_IMM_DATA_EN		(1 << ISCSI_PARAM_IMM_DATA_EN)
+-#define ISCSI_FIRST_BURST		(1 << ISCSI_PARAM_FIRST_BURST)
+-#define ISCSI_MAX_BURST			(1 << ISCSI_PARAM_MAX_BURST)
+-#define ISCSI_PDU_INORDER_EN		(1 << ISCSI_PARAM_PDU_INORDER_EN)
+-#define ISCSI_DATASEQ_INORDER_EN	(1 << ISCSI_PARAM_DATASEQ_INORDER_EN)
+-#define ISCSI_ERL			(1 << ISCSI_PARAM_ERL)
+-#define ISCSI_IFMARKER_EN		(1 << ISCSI_PARAM_IFMARKER_EN)
+-#define ISCSI_OFMARKER_EN		(1 << ISCSI_PARAM_OFMARKER_EN)
+-#define ISCSI_EXP_STATSN		(1 << ISCSI_PARAM_EXP_STATSN)
+-#define ISCSI_TARGET_NAME		(1 << ISCSI_PARAM_TARGET_NAME)
+-#define ISCSI_TPGT			(1 << ISCSI_PARAM_TPGT)
+-#define ISCSI_PERSISTENT_ADDRESS	(1 << ISCSI_PARAM_PERSISTENT_ADDRESS)
+-#define ISCSI_PERSISTENT_PORT		(1 << ISCSI_PARAM_PERSISTENT_PORT)
+-#define ISCSI_SESS_RECOVERY_TMO		(1 << ISCSI_PARAM_SESS_RECOVERY_TMO)
+-#define ISCSI_CONN_PORT			(1 << ISCSI_PARAM_CONN_PORT)
+-#define ISCSI_CONN_ADDRESS		(1 << ISCSI_PARAM_CONN_ADDRESS)
+-#define ISCSI_USERNAME			(1 << ISCSI_PARAM_USERNAME)
+-#define ISCSI_USERNAME_IN		(1 << ISCSI_PARAM_USERNAME_IN)
+-#define ISCSI_PASSWORD			(1 << ISCSI_PARAM_PASSWORD)
+-#define ISCSI_PASSWORD_IN		(1 << ISCSI_PARAM_PASSWORD_IN)
+-#define ISCSI_FAST_ABORT		(1 << ISCSI_PARAM_FAST_ABORT)
+-#define ISCSI_ABORT_TMO			(1 << ISCSI_PARAM_ABORT_TMO)
+-#define ISCSI_LU_RESET_TMO		(1 << ISCSI_PARAM_LU_RESET_TMO)
+-#define ISCSI_HOST_RESET_TMO		(1 << ISCSI_PARAM_HOST_RESET_TMO)
+-#define ISCSI_PING_TMO			(1 << ISCSI_PARAM_PING_TMO)
+-#define ISCSI_RECV_TMO			(1 << ISCSI_PARAM_RECV_TMO)
++#define ISCSI_MAX_RECV_DLENGTH		(1ULL << ISCSI_PARAM_MAX_RECV_DLENGTH)
++#define ISCSI_MAX_XMIT_DLENGTH		(1ULL << ISCSI_PARAM_MAX_XMIT_DLENGTH)
++#define ISCSI_HDRDGST_EN		(1ULL << ISCSI_PARAM_HDRDGST_EN)
++#define ISCSI_DATADGST_EN		(1ULL << ISCSI_PARAM_DATADGST_EN)
++#define ISCSI_INITIAL_R2T_EN		(1ULL << ISCSI_PARAM_INITIAL_R2T_EN)
++#define ISCSI_MAX_R2T			(1ULL << ISCSI_PARAM_MAX_R2T)
++#define ISCSI_IMM_DATA_EN		(1ULL << ISCSI_PARAM_IMM_DATA_EN)
++#define ISCSI_FIRST_BURST		(1ULL << ISCSI_PARAM_FIRST_BURST)
++#define ISCSI_MAX_BURST			(1ULL << ISCSI_PARAM_MAX_BURST)
++#define ISCSI_PDU_INORDER_EN		(1ULL << ISCSI_PARAM_PDU_INORDER_EN)
++#define ISCSI_DATASEQ_INORDER_EN	(1ULL << ISCSI_PARAM_DATASEQ_INORDER_EN)
++#define ISCSI_ERL			(1ULL << ISCSI_PARAM_ERL)
++#define ISCSI_IFMARKER_EN		(1ULL << ISCSI_PARAM_IFMARKER_EN)
++#define ISCSI_OFMARKER_EN		(1ULL << ISCSI_PARAM_OFMARKER_EN)
++#define ISCSI_EXP_STATSN		(1ULL << ISCSI_PARAM_EXP_STATSN)
++#define ISCSI_TARGET_NAME		(1ULL << ISCSI_PARAM_TARGET_NAME)
++#define ISCSI_TPGT			(1ULL << ISCSI_PARAM_TPGT)
++#define ISCSI_PERSISTENT_ADDRESS	(1ULL << ISCSI_PARAM_PERSISTENT_ADDRESS)
++#define ISCSI_PERSISTENT_PORT		(1ULL << ISCSI_PARAM_PERSISTENT_PORT)
++#define ISCSI_SESS_RECOVERY_TMO		(1ULL << ISCSI_PARAM_SESS_RECOVERY_TMO)
++#define ISCSI_CONN_PORT			(1ULL << ISCSI_PARAM_CONN_PORT)
++#define ISCSI_CONN_ADDRESS		(1ULL << ISCSI_PARAM_CONN_ADDRESS)
++#define ISCSI_USERNAME			(1ULL << ISCSI_PARAM_USERNAME)
++#define ISCSI_USERNAME_IN		(1ULL << ISCSI_PARAM_USERNAME_IN)
++#define ISCSI_PASSWORD			(1ULL << ISCSI_PARAM_PASSWORD)
++#define ISCSI_PASSWORD_IN		(1ULL << ISCSI_PARAM_PASSWORD_IN)
++#define ISCSI_FAST_ABORT		(1ULL << ISCSI_PARAM_FAST_ABORT)
++#define ISCSI_ABORT_TMO			(1ULL << ISCSI_PARAM_ABORT_TMO)
++#define ISCSI_LU_RESET_TMO		(1ULL << ISCSI_PARAM_LU_RESET_TMO)
++#define ISCSI_HOST_RESET_TMO		(1ULL << ISCSI_PARAM_HOST_RESET_TMO)
++#define ISCSI_PING_TMO			(1ULL << ISCSI_PARAM_PING_TMO)
++#define ISCSI_RECV_TMO			(1ULL << ISCSI_PARAM_RECV_TMO)
++#define ISCSI_IFACE_NAME		(1ULL << ISCSI_PARAM_IFACE_NAME)
++#define ISCSI_ISID			(1ULL << ISCSI_PARAM_ISID)
++#define ISCSI_INITIATOR_NAME		(1ULL << ISCSI_PARAM_INITIATOR_NAME)
+ 
+ /* iSCSI HBA params */
+ enum iscsi_host_param {
+@@ -303,10 +310,10 @@ enum iscsi_host_param {
+ 	ISCSI_HOST_PARAM_MAX,
+ };
+ 
+-#define ISCSI_HOST_HWADDRESS		(1 << ISCSI_HOST_PARAM_HWADDRESS)
+-#define ISCSI_HOST_INITIATOR_NAME	(1 << ISCSI_HOST_PARAM_INITIATOR_NAME)
+-#define ISCSI_HOST_NETDEV_NAME		(1 << ISCSI_HOST_PARAM_NETDEV_NAME)
+-#define ISCSI_HOST_IPADDRESS		(1 << ISCSI_HOST_PARAM_IPADDRESS)
++#define ISCSI_HOST_HWADDRESS		(1ULL << ISCSI_HOST_PARAM_HWADDRESS)
++#define ISCSI_HOST_INITIATOR_NAME	(1ULL << ISCSI_HOST_PARAM_INITIATOR_NAME)
++#define ISCSI_HOST_NETDEV_NAME		(1ULL << ISCSI_HOST_PARAM_NETDEV_NAME)
++#define ISCSI_HOST_IPADDRESS		(1ULL << ISCSI_HOST_PARAM_IPADDRESS)
+ 
+ #define iscsi_ptr(_handle) ((void*)(unsigned long)_handle)
+ #define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr)
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 13c92d7ba969..21cfb1d5483f 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -270,6 +270,8 @@ struct iscsi_session {
+ 	char			*password;
+ 	char			*password_in;
+ 	char			*targetname;
++	char			*ifacename;
++	char			*initiatorname;
+ 	/* control data */
+ 	struct iscsi_transport	*tt;
+ 	struct Scsi_Host	*host;

commit 06520edea0fc7007985fa4cd51560149feb3f442
+Author: Mike Christie 
+Date:   Wed May 21 15:54:15 2008 -0500
+
+    [SCSI] iscsi_tcp: hook iscsi_tcp into iscsi_endpoint code
+    
+    iscsi_tcp creates its ep in userspace using sockets because
+    it is virtual, so we just check if we are sent a ep and fail
+    if we are.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index aa3c7f0c550d..92d031959002 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -1838,17 +1838,17 @@ iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats)
+ }
+ 
+ static struct iscsi_cls_session *
+-iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max,
++iscsi_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
+ 			 uint16_t qdepth, uint32_t initial_cmdsn,
+ 			 uint32_t *hostno)
+ {
+ 	struct iscsi_cls_session *cls_session;
+ 	struct iscsi_session *session;
++	struct Scsi_Host *shost;
+ 	int cmd_i;
+ 
+-	if (shost) {
+-		printk(KERN_ERR "iscsi_tcp: invalid shost %d.\n",
+-		       shost->host_no);
++	if (ep) {
++		printk(KERN_ERR "iscsi_tcp: invalid ep %p.\n", ep);
+ 		return NULL;
+ 	}
+ 

commit 412eeafa0a51a8d86545d0be637bf84e4374fccf
+Author: Mike Christie 
+Date:   Wed May 21 15:54:14 2008 -0500
+
+    [SCSI] iser: Modify iser to take a iscsi_endpoint struct in ep callouts and session setup
+    
+    This hooks iser into the iscsi endpoint code. Previously it handled the
+    lookup and allocation. This has been made generic so bnx2i and iser can
+    share it. It also allows us to pass iser the leading conn's ep, so we
+    know the ib_deivce being used and can set it as the scsi_host's parent.
+    And that allows scsi-ml to set the dma_mask based on those values.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 3a89039e9a96..42e95b833092 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -262,24 +262,6 @@ iscsi_iser_cleanup_task(struct iscsi_conn *conn, struct iscsi_task *task)
+ 	}
+ }
+ 
+-static struct iser_conn *
+-iscsi_iser_ib_conn_lookup(__u64 ep_handle)
+-{
+-	struct iser_conn *ib_conn;
+-	struct iser_conn *uib_conn = (struct iser_conn *)(unsigned long)ep_handle;
+-
+-	mutex_lock(&ig.connlist_mutex);
+-	list_for_each_entry(ib_conn, &ig.connlist, conn_list) {
+-		if (ib_conn == uib_conn) {
+-			mutex_unlock(&ig.connlist_mutex);
+-			return ib_conn;
+-		}
+-	}
+-	mutex_unlock(&ig.connlist_mutex);
+-	iser_err("no conn exists for eph %llx\n",(unsigned long long)ep_handle);
+-	return NULL;
+-}
+-
+ static struct iscsi_cls_conn *
+ iscsi_iser_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ {
+@@ -335,6 +317,7 @@ iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session,
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	struct iscsi_iser_conn *iser_conn;
+ 	struct iser_conn *ib_conn;
++	struct iscsi_endpoint *ep;
+ 	int error;
+ 
+ 	error = iscsi_conn_bind(cls_session, cls_conn, is_leading);
+@@ -343,12 +326,14 @@ iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session,
+ 
+ 	/* the transport ep handle comes from user space so it must be
+ 	 * verified against the global ib connections list */
+-	ib_conn = iscsi_iser_ib_conn_lookup(transport_eph);
+-	if (!ib_conn) {
++	ep = iscsi_lookup_endpoint(transport_eph);
++	if (!ep) {
+ 		iser_err("can't bind eph %llx\n",
+ 			 (unsigned long long)transport_eph);
+ 		return -EINVAL;
+ 	}
++	ib_conn = ep->dd_data;
++
+ 	/* binds the iSER connection retrieved from the previously
+ 	 * connected ep_handle to the iSCSI layer connection. exchanges
+ 	 * connection pointers */
+@@ -401,21 +386,17 @@ static void iscsi_iser_session_destroy(struct iscsi_cls_session *cls_session)
+ }
+ 
+ static struct iscsi_cls_session *
+-iscsi_iser_session_create(struct Scsi_Host *shost,
++iscsi_iser_session_create(struct iscsi_endpoint *ep,
+ 			  uint16_t cmds_max, uint16_t qdepth,
+ 			  uint32_t initial_cmdsn, uint32_t *hostno)
+ {
+ 	struct iscsi_cls_session *cls_session;
+ 	struct iscsi_session *session;
++	struct Scsi_Host *shost;
+ 	int i;
+ 	struct iscsi_task *task;
+ 	struct iscsi_iser_task *iser_task;
+-
+-	if (shost) {
+-		printk(KERN_ERR "iscsi_tcp: invalid shost %d.\n",
+-		       shost->host_no);
+-		return NULL;
+-	}
++	struct iser_conn *ib_conn;
+ 
+ 	shost = iscsi_host_alloc(&iscsi_iser_sht, 0, ISCSI_MAX_CMD_PER_LUN);
+ 	if (!shost)
+@@ -426,7 +407,15 @@ iscsi_iser_session_create(struct Scsi_Host *shost,
+ 	shost->max_channel = 0;
+ 	shost->max_cmd_len = 16;
+ 
+-	if (iscsi_host_add(shost, NULL))
++	/*
++	 * older userspace tools (before 2.0-870) did not pass us
++	 * the leading conn's ep so this will be NULL;
++	 */
++	if (ep)
++		ib_conn = ep->dd_data;
++
++	if (iscsi_host_add(shost,
++			   ep ? ib_conn->device->ib_device->dma_device : NULL))
+ 		goto free_host;
+ 	*hostno = shost->host_no;
+ 
+@@ -529,34 +518,37 @@ iscsi_iser_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *s
+ 	stats->custom[3].value = conn->fmr_unalign_cnt;
+ }
+ 
+-static int
+-iscsi_iser_ep_connect(struct sockaddr *dst_addr, int non_blocking,
+-		      __u64 *ep_handle)
++static struct iscsi_endpoint *
++iscsi_iser_ep_connect(struct sockaddr *dst_addr, int non_blocking)
+ {
+ 	int err;
+ 	struct iser_conn *ib_conn;
++	struct iscsi_endpoint *ep;
+ 
+-	err = iser_conn_init(&ib_conn);
+-	if (err)
+-		goto out;
++	ep = iscsi_create_endpoint(sizeof(*ib_conn));
++	if (!ep)
++		return ERR_PTR(-ENOMEM);
+ 
+-	err = iser_connect(ib_conn, NULL, (struct sockaddr_in *)dst_addr, non_blocking);
+-	if (!err)
+-		*ep_handle = (__u64)(unsigned long)ib_conn;
++	ib_conn = ep->dd_data;
++	ib_conn->ep = ep;
++	iser_conn_init(ib_conn);
+ 
+-out:
+-	return err;
++	err = iser_connect(ib_conn, NULL, (struct sockaddr_in *)dst_addr,
++			   non_blocking);
++	if (err) {
++		iscsi_destroy_endpoint(ep);
++		return ERR_PTR(err);
++	}
++	return ep;
+ }
+ 
+ static int
+-iscsi_iser_ep_poll(__u64 ep_handle, int timeout_ms)
++iscsi_iser_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
+ {
+-	struct iser_conn *ib_conn = iscsi_iser_ib_conn_lookup(ep_handle);
++	struct iser_conn *ib_conn;
+ 	int rc;
+ 
+-	if (!ib_conn)
+-		return -EINVAL;
+-
++	ib_conn = ep->dd_data;
+ 	rc = wait_event_interruptible_timeout(ib_conn->wait,
+ 			     ib_conn->state == ISER_CONN_UP,
+ 			     msecs_to_jiffies(timeout_ms));
+@@ -578,14 +570,11 @@ iscsi_iser_ep_poll(__u64 ep_handle, int timeout_ms)
+ }
+ 
+ static void
+-iscsi_iser_ep_disconnect(__u64 ep_handle)
++iscsi_iser_ep_disconnect(struct iscsi_endpoint *ep)
+ {
+ 	struct iser_conn *ib_conn;
+ 
+-	ib_conn = iscsi_iser_ib_conn_lookup(ep_handle);
+-	if (!ib_conn)
+-		return;
+-
++	ib_conn = ep->dd_data;
+ 	if (ib_conn->iser_conn)
+ 		/*
+ 		 * Must suspend xmit path if the ep is bound to the
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
+index 05431f270fe8..cdf48763b082 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
+@@ -174,6 +174,7 @@ struct iser_data_buf {
+ struct iser_device;
+ struct iscsi_iser_conn;
+ struct iscsi_iser_task;
++struct iscsi_endpoint;
+ 
+ struct iser_mem_reg {
+ 	u32  lkey;
+@@ -241,6 +242,7 @@ struct iser_device {
+ 
+ struct iser_conn {
+ 	struct iscsi_iser_conn       *iser_conn; /* iser conn for upcalls  */
++	struct iscsi_endpoint	     *ep;
+ 	enum iser_ib_conn_state	     state;	    /* rdma connection state   */
+ 	atomic_t		     refcount;
+ 	spinlock_t		     lock;	    /* used for state changes  */
+@@ -313,7 +315,7 @@ void iscsi_iser_recv(struct iscsi_conn *conn,
+ 		     char                   *rx_data,
+ 		     int                    rx_data_len);
+ 
+-int  iser_conn_init(struct iser_conn **ib_conn);
++void iser_conn_init(struct iser_conn *ib_conn);
+ 
+ void iser_conn_get(struct iser_conn *ib_conn);
+ 
+diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
+index 5daed2bd710e..81b45d4d9aa9 100644
+--- a/drivers/infiniband/ulp/iser/iser_verbs.c
++++ b/drivers/infiniband/ulp/iser/iser_verbs.c
+@@ -325,7 +325,7 @@ static void iser_conn_release(struct iser_conn *ib_conn)
+ 		iser_device_try_release(device);
+ 	if (ib_conn->iser_conn)
+ 		ib_conn->iser_conn->ib_conn = NULL;
+-	kfree(ib_conn);
++	iscsi_destroy_endpoint(ib_conn->ep);
+ }
+ 
+ void iser_conn_get(struct iser_conn *ib_conn)
+@@ -494,15 +494,8 @@ static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *eve
+ 	return ret;
+ }
+ 
+-int iser_conn_init(struct iser_conn **ibconn)
++void iser_conn_init(struct iser_conn *ib_conn)
+ {
+-	struct iser_conn *ib_conn;
+-
+-	ib_conn = kzalloc(sizeof *ib_conn, GFP_KERNEL);
+-	if (!ib_conn) {
+-		iser_err("can't alloc memory for struct iser_conn\n");
+-		return -ENOMEM;
+-	}
+ 	ib_conn->state = ISER_CONN_INIT;
+ 	init_waitqueue_head(&ib_conn->wait);
+ 	atomic_set(&ib_conn->post_recv_buf_count, 0);
+@@ -510,9 +503,6 @@ int iser_conn_init(struct iser_conn **ibconn)
+ 	atomic_set(&ib_conn->refcount, 1);
+ 	INIT_LIST_HEAD(&ib_conn->conn_list);
+ 	spin_lock_init(&ib_conn->lock);
+-
+-	*ibconn = ib_conn;
+-	return 0;
+ }
+ 
+  /**

commit d82ff9be733a2e6da4f6c2ab4e9216f3f536503d
+Author: Mike Christie 
+Date:   Wed May 21 15:54:13 2008 -0500
+
+    [SCSI] iscsi class: add endpoint class
+    
+    Add sysfs representation for the endpoint, so userspace can match the
+    host and session to the endpoint. This will allow us to set the host's
+    parent correctly at host creation time.
+    
+    The next patches will convert tcp and iser, and fix iser's dma_mask
+    bug.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index ac9d298f54e7..c3c07ccccca7 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -33,6 +33,7 @@
+ #define ISCSI_SESSION_ATTRS 19
+ #define ISCSI_CONN_ATTRS 13
+ #define ISCSI_HOST_ATTRS 4
++
+ #define ISCSI_TRANSPORT_VERSION "2.0-869"
+ 
+ struct iscsi_internal {
+@@ -112,6 +113,123 @@ static struct attribute_group iscsi_transport_group = {
+ 	.attrs = iscsi_transport_attrs,
+ };
+ 
++/*
++ * iSCSI endpoint attrs
++ */
++#define iscsi_dev_to_endpoint(_dev) \
++	container_of(_dev, struct iscsi_endpoint, dev)
++
++#define ISCSI_ATTR(_prefix,_name,_mode,_show,_store)	\
++struct device_attribute dev_attr_##_prefix##_##_name =	\
++        __ATTR(_name,_mode,_show,_store)
++
++static void iscsi_endpoint_release(struct device *dev)
++{
++	struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
++	kfree(ep);
++}
++
++static struct class iscsi_endpoint_class = {
++	.name = "iscsi_endpoint",
++	.dev_release = iscsi_endpoint_release,
++};
++
++static ssize_t
++show_ep_handle(struct device *dev, struct device_attribute *attr, char *buf)
++{
++	struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
++	return sprintf(buf, "%u\n", ep->id);
++}
++static ISCSI_ATTR(ep, handle, S_IRUGO, show_ep_handle, NULL);
++
++static struct attribute *iscsi_endpoint_attrs[] = {
++	&dev_attr_ep_handle.attr,
++	NULL,
++};
++
++static struct attribute_group iscsi_endpoint_group = {
++	.attrs = iscsi_endpoint_attrs,
++};
++
++#define ISCSI_MAX_EPID -1
++
++static int iscsi_match_epid(struct device *dev, void *data)
++{
++	struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
++	unsigned int *epid = (unsigned int *) data;
++
++	return *epid == ep->id;
++}
++
++struct iscsi_endpoint *
++iscsi_create_endpoint(int dd_size)
++{
++	struct device *dev;
++	struct iscsi_endpoint *ep;
++	unsigned int id;
++	int err;
++
++	for (id = 1; id < ISCSI_MAX_EPID; id++) {
++		dev = class_find_device(&iscsi_endpoint_class, &id,
++					iscsi_match_epid);
++		if (!dev)
++			break;
++	}
++	if (id == ISCSI_MAX_EPID) {
++		printk(KERN_ERR "Too many connections. Max supported %u\n",
++		       ISCSI_MAX_EPID - 1);
++		return NULL;
++	}
++
++	ep = kzalloc(sizeof(*ep) + dd_size, GFP_KERNEL);
++	if (!ep)
++		return NULL;
++
++	ep->id = id;
++	ep->dev.class = &iscsi_endpoint_class;
++	snprintf(ep->dev.bus_id, BUS_ID_SIZE, "ep-%u", id);
++	err = device_register(&ep->dev);
++        if (err)
++                goto free_ep;
++
++	err = sysfs_create_group(&ep->dev.kobj, &iscsi_endpoint_group);
++	if (err)
++		goto unregister_dev;
++
++	if (dd_size)
++		ep->dd_data = &ep[1];
++	return ep;
++
++unregister_dev:
++	device_unregister(&ep->dev);
++	return NULL;
++
++free_ep:
++	kfree(ep);
++	return NULL;
++}
++EXPORT_SYMBOL_GPL(iscsi_create_endpoint);
++
++void iscsi_destroy_endpoint(struct iscsi_endpoint *ep)
++{
++	sysfs_remove_group(&ep->dev.kobj, &iscsi_endpoint_group);
++	device_unregister(&ep->dev);
++}
++EXPORT_SYMBOL_GPL(iscsi_destroy_endpoint);
++
++struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
++{
++	struct device *dev;
++
++	dev = class_find_device(&iscsi_endpoint_class, &handle,
++				iscsi_match_epid);
++	if (!dev)
++		return NULL;
++
++	return iscsi_dev_to_endpoint(dev);
++}
++EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint);
++
+ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+ 			    struct device *cdev)
+ {
+@@ -1094,33 +1212,16 @@ int iscsi_session_event(struct iscsi_cls_session *session,
+ EXPORT_SYMBOL_GPL(iscsi_session_event);
+ 
+ static int
+-iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev,
+-			uint32_t host_no, uint32_t initial_cmdsn,
++iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_endpoint *ep,
++			struct iscsi_uevent *ev, uint32_t initial_cmdsn,
+ 			uint16_t cmds_max, uint16_t queue_depth)
+ {
+ 	struct iscsi_transport *transport = priv->iscsi_transport;
+ 	struct iscsi_cls_session *session;
+-	struct Scsi_Host *shost = NULL;
++	uint32_t host_no;
+ 
+-	/*
+-	 * Software iscsi allocates a host per session, but
+-	 * offload drivers (and possibly iser one day) allocate a host per
+-	 * hba/nic/rnic. Offload will match a host here, but software will
+-	 * return a new hostno after the create_session callback has returned.
+-	 */
+-	if (host_no != UINT_MAX) {
+-		shost = scsi_host_lookup(host_no);
+-		if (IS_ERR(shost)) {
+-			printk(KERN_ERR "Could not find host no %u to "
+-			       "create session\n", host_no);
+-			return -ENODEV;
+-		}
+-	}
+-
+-	session = transport->create_session(shost, cmds_max, queue_depth,
++	session = transport->create_session(ep, cmds_max, queue_depth,
+ 					    initial_cmdsn, &host_no);
+-	if (shost)
+-		scsi_host_put(shost);
+ 	if (!session)
+ 		return -ENOMEM;
+ 
+@@ -1199,6 +1300,7 @@ static int
+ iscsi_if_transport_ep(struct iscsi_transport *transport,
+ 		      struct iscsi_uevent *ev, int msg_type)
+ {
++	struct iscsi_endpoint *ep;
+ 	struct sockaddr *dst_addr;
+ 	int rc = 0;
+ 
+@@ -1208,22 +1310,33 @@ iscsi_if_transport_ep(struct iscsi_transport *transport,
+ 			return -EINVAL;
+ 
+ 		dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
+-		rc = transport->ep_connect(dst_addr,
+-					   ev->u.ep_connect.non_blocking,
+-					   &ev->r.ep_connect_ret.handle);
++		ep = transport->ep_connect(dst_addr,
++					   ev->u.ep_connect.non_blocking);
++		if (IS_ERR(ep))
++			return PTR_ERR(ep);
++
++		ev->r.ep_connect_ret.handle = ep->id;
+ 		break;
+ 	case ISCSI_UEVENT_TRANSPORT_EP_POLL:
+ 		if (!transport->ep_poll)
+ 			return -EINVAL;
+ 
+-		ev->r.retcode = transport->ep_poll(ev->u.ep_poll.ep_handle,
++		ep = iscsi_lookup_endpoint(ev->u.ep_poll.ep_handle);
++		if (!ep)
++			return -EINVAL;
++
++		ev->r.retcode = transport->ep_poll(ep,
+ 						   ev->u.ep_poll.timeout_ms);
+ 		break;
+ 	case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
+ 		if (!transport->ep_disconnect)
+ 			return -EINVAL;
+ 
+-		transport->ep_disconnect(ev->u.ep_disconnect.ep_handle);
++		ep = iscsi_lookup_endpoint(ev->u.ep_disconnect.ep_handle);
++		if (!ep)
++			return -EINVAL;
++
++		transport->ep_disconnect(ep);
+ 		break;
+ 	}
+ 	return rc;
+@@ -1283,12 +1396,12 @@ static int
+ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ {
+ 	int err = 0;
+-	uint32_t host_no = UINT_MAX;
+ 	struct iscsi_uevent *ev = NLMSG_DATA(nlh);
+ 	struct iscsi_transport *transport = NULL;
+ 	struct iscsi_internal *priv;
+ 	struct iscsi_cls_session *session;
+ 	struct iscsi_cls_conn *conn;
++	struct iscsi_endpoint *ep = NULL;
+ 
+ 	priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle));
+ 	if (!priv)
+@@ -1302,14 +1415,17 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 
+ 	switch (nlh->nlmsg_type) {
+ 	case ISCSI_UEVENT_CREATE_SESSION:
+-		err = iscsi_if_create_session(priv, ev, host_no,
++		err = iscsi_if_create_session(priv, ep, ev,
+ 					      ev->u.c_session.initial_cmdsn,
+ 					      ev->u.c_session.cmds_max,
+ 					      ev->u.c_session.queue_depth);
+ 		break;
+ 	case ISCSI_UEVENT_CREATE_BOUND_SESSION:
+-		err = iscsi_if_create_session(priv, ev,
+-					ev->u.c_bound_session.host_no,
++		ep = iscsi_lookup_endpoint(ev->u.c_bound_session.ep_handle);
++		if (!ep)
++			return -EINVAL;
++
++		err = iscsi_if_create_session(priv, ep, ev,
+ 					ev->u.c_bound_session.initial_cmdsn,
+ 					ev->u.c_bound_session.cmds_max,
+ 					ev->u.c_bound_session.queue_depth);
+@@ -1774,6 +1890,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 
+ unregister_dev:
+ 	device_unregister(&priv->dev);
++	return NULL;
+ free_priv:
+ 	kfree(priv);
+ 	return NULL;
+@@ -1821,10 +1938,14 @@ static __init int iscsi_transport_init(void)
+ 	if (err)
+ 		return err;
+ 
+-	err = transport_class_register(&iscsi_host_class);
++	err = class_register(&iscsi_endpoint_class);
+ 	if (err)
+ 		goto unregister_transport_class;
+ 
++	err = transport_class_register(&iscsi_host_class);
++	if (err)
++		goto unregister_endpoint_class;
++
+ 	err = transport_class_register(&iscsi_connection_class);
+ 	if (err)
+ 		goto unregister_host_class;
+@@ -1833,8 +1954,8 @@ static __init int iscsi_transport_init(void)
+ 	if (err)
+ 		goto unregister_conn_class;
+ 
+-	nls = netlink_kernel_create(&init_net, NETLINK_ISCSI, 1, iscsi_if_rx, NULL,
+-			THIS_MODULE);
++	nls = netlink_kernel_create(&init_net, NETLINK_ISCSI, 1, iscsi_if_rx,
++				    NULL, THIS_MODULE);
+ 	if (!nls) {
+ 		err = -ENOBUFS;
+ 		goto unregister_session_class;
+@@ -1854,6 +1975,8 @@ static __init int iscsi_transport_init(void)
+ 	transport_class_unregister(&iscsi_connection_class);
+ unregister_host_class:
+ 	transport_class_unregister(&iscsi_host_class);
++unregister_endpoint_class:
++	class_unregister(&iscsi_endpoint_class);
+ unregister_transport_class:
+ 	class_unregister(&iscsi_transport_class);
+ 	return err;
+@@ -1866,6 +1989,7 @@ static void __exit iscsi_transport_exit(void)
+ 	transport_class_unregister(&iscsi_connection_class);
+ 	transport_class_unregister(&iscsi_session_class);
+ 	transport_class_unregister(&iscsi_host_class);
++	class_unregister(&iscsi_endpoint_class);
+ 	class_unregister(&iscsi_transport_class);
+ }
+ 
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index 801a677777cc..a0f13a280e71 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -80,7 +80,7 @@ struct iscsi_uevent {
+ 			uint16_t	queue_depth;
+ 		} c_session;
+ 		struct msg_create_bound_session {
+-			uint32_t	host_no;
++			uint64_t	ep_handle;
+ 			uint32_t	initial_cmdsn;
+ 			uint16_t	cmds_max;
+ 			uint16_t	queue_depth;
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index d6b823195563..f5444e033cc9 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -30,6 +30,7 @@
+ 
+ struct scsi_transport_template;
+ struct iscsi_transport;
++struct iscsi_endpoint;
+ struct Scsi_Host;
+ struct iscsi_cls_conn;
+ struct iscsi_conn;
+@@ -85,7 +86,7 @@ struct iscsi_transport {
+ 	/* LLD sets this to indicate what values it can export to sysfs */
+ 	uint64_t param_mask;
+ 	uint64_t host_param_mask;
+-	struct iscsi_cls_session *(*create_session) (struct Scsi_Host *shost,
++	struct iscsi_cls_session *(*create_session) (struct iscsi_endpoint *ep,
+ 					uint16_t cmds_max, uint16_t qdepth,
+ 					uint32_t sn, uint32_t *hn);
+ 	void (*destroy_session) (struct iscsi_cls_session *session);
+@@ -117,10 +118,10 @@ struct iscsi_transport {
+ 	void (*cleanup_task) (struct iscsi_conn *conn,
+ 				  struct iscsi_task *task);
+ 	void (*session_recovery_timedout) (struct iscsi_cls_session *session);
+-	int (*ep_connect) (struct sockaddr *dst_addr, int non_blocking,
+-			   uint64_t *ep_handle);
+-	int (*ep_poll) (uint64_t ep_handle, int timeout_ms);
+-	void (*ep_disconnect) (uint64_t ep_handle);
++	struct iscsi_endpoint *(*ep_connect) (struct sockaddr *dst_addr,
++					      int non_blocking);
++	int (*ep_poll) (struct iscsi_endpoint *ep, int timeout_ms);
++	void (*ep_disconnect) (struct iscsi_endpoint *ep);
+ 	int (*tgt_dscvr) (struct Scsi_Host *shost, enum iscsi_tgt_dscvr type,
+ 			  uint32_t enable, struct sockaddr *dst_addr);
+ };
+@@ -203,6 +204,11 @@ struct iscsi_cls_host {
+ extern void iscsi_host_for_each_session(struct Scsi_Host *shost,
+ 				void (*fn)(struct iscsi_cls_session *));
+ 
++struct iscsi_endpoint {
++	void *dd_data;			/* LLD private data */
++	struct device dev;
++	unsigned int id;
++};
+ 
+ /*
+  * session and connection functions that can be used by HW iSCSI LLDs
+@@ -233,5 +239,8 @@ extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn);
+ extern void iscsi_unblock_session(struct iscsi_cls_session *session);
+ extern void iscsi_block_session(struct iscsi_cls_session *session);
+ extern int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time);
++extern struct iscsi_endpoint *iscsi_create_endpoint(int dd_size);
++extern void iscsi_destroy_endpoint(struct iscsi_endpoint *ep);
++extern struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle);
+ 
+ #endif

commit 7970634b81a6e3561954517bca42615542c4535b
+Author: Mike Christie 
+Date:   Wed May 21 15:54:12 2008 -0500
+
+    [SCSI] iscsi class: user device_for_each_child instead of duplicating session list
+    
+    Currently we duplicate the list of sessions, because we were using the
+    test for if a session was on the host list to indicate if the session
+    was bound or unbound. We can instead use the target_id and fix up
+    the class so that drivers like bnx2i do not have to manage the target id
+    space.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 86d9c42f0d33..3a89039e9a96 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -437,7 +437,7 @@ iscsi_iser_session_create(struct Scsi_Host *shost,
+ 	cls_session = iscsi_session_setup(&iscsi_iser_transport, shost,
+ 					  ISCSI_DEF_XMIT_CMDS_MAX,
+ 					  sizeof(struct iscsi_iser_task),
+-					  initial_cmdsn);
++					  initial_cmdsn, 0);
+ 	if (!cls_session)
+ 		goto remove_host;
+ 	session = cls_session->dd_data;
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 33cd0ca7cc8d..aa3c7f0c550d 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -1868,7 +1868,7 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max,
+ 
+ 	cls_session = iscsi_session_setup(&iscsi_tcp_transport, shost, cmds_max,
+ 					  sizeof(struct iscsi_tcp_task),
+-					  initial_cmdsn);
++					  initial_cmdsn, 0);
+ 	if (!cls_session)
+ 		goto remove_host;
+ 	session = cls_session->dd_data;
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 92ee6d94aaf9..e88b726ab2e0 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1897,7 +1897,7 @@ EXPORT_SYMBOL_GPL(iscsi_host_free);
+ struct iscsi_cls_session *
+ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
+ 		    uint16_t scsi_cmds_max, int cmd_task_size,
+-		    uint32_t initial_cmdsn)
++		    uint32_t initial_cmdsn, unsigned int id)
+ {
+ 	struct iscsi_session *session;
+ 	struct iscsi_cls_session *cls_session;
+@@ -1957,7 +1957,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
+ 	if (!try_module_get(iscsit->owner))
+ 		goto module_get_fail;
+ 
+-	if (iscsi_add_session(cls_session, 0))
++	if (iscsi_add_session(cls_session, id))
+ 		goto cls_session_fail;
+ 	return cls_session;
+ 
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 6b8516a0970b..ac9d298f54e7 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -119,9 +119,8 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+ 	struct iscsi_cls_host *ihost = shost->shost_data;
+ 
+ 	memset(ihost, 0, sizeof(*ihost));
+-	INIT_LIST_HEAD(&ihost->sessions);
+-	mutex_init(&ihost->mutex);
+ 	atomic_set(&ihost->nr_scans, 0);
++	mutex_init(&ihost->mutex);
+ 
+ 	snprintf(ihost->scan_workq_name, KOBJ_NAME_LEN, "iscsi_scan_%d",
+ 		shost->host_no);
+@@ -316,42 +315,76 @@ int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_scan_finished);
+ 
+-static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
+-			   uint id, uint lun)
++struct iscsi_scan_data {
++	unsigned int channel;
++	unsigned int id;
++	unsigned int lun;
++};
++
++static int iscsi_user_scan_session(struct device *dev, void *data)
+ {
+-	struct iscsi_cls_host *ihost = shost->shost_data;
++	struct iscsi_scan_data *scan_data = data;
+ 	struct iscsi_cls_session *session;
++	struct Scsi_Host *shost;
++	struct iscsi_cls_host *ihost;
++	unsigned long flags;
++	unsigned int id;
++
++	if (!iscsi_is_session_dev(dev))
++		return 0;
++
++	session = iscsi_dev_to_session(dev);
++	shost = iscsi_session_to_shost(session);
++	ihost = shost->shost_data;
+ 
+ 	mutex_lock(&ihost->mutex);
+-	list_for_each_entry(session, &ihost->sessions, host_list) {
+-		if ((channel == SCAN_WILD_CARD || channel == 0) &&
+-		    (id == SCAN_WILD_CARD || id == session->target_id))
+-			scsi_scan_target(&session->dev, 0,
+-					 session->target_id, lun, 1);
++	spin_lock_irqsave(&session->lock, flags);
++	if (session->state != ISCSI_SESSION_LOGGED_IN) {
++		spin_unlock_irqrestore(&session->lock, flags);
++		mutex_unlock(&ihost->mutex);
++		return 0;
+ 	}
+-	mutex_unlock(&ihost->mutex);
++	id = session->target_id;
++	spin_unlock_irqrestore(&session->lock, flags);
+ 
++	if (id != ISCSI_MAX_TARGET) {
++		if ((scan_data->channel == SCAN_WILD_CARD ||
++		     scan_data->channel == 0) &&
++		    (scan_data->id == SCAN_WILD_CARD ||
++		     scan_data->id == id))
++			scsi_scan_target(&session->dev, 0, id,
++					 scan_data->lun, 1);
++	}
++	mutex_unlock(&ihost->mutex);
+ 	return 0;
+ }
+ 
++static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
++			   uint id, uint lun)
++{
++	struct iscsi_scan_data scan_data;
++
++	scan_data.channel = channel;
++	scan_data.id = id;
++	scan_data.lun = lun;
++
++	return device_for_each_child(&shost->shost_gendev, &scan_data,
++				     iscsi_user_scan_session);
++}
++
+ static void iscsi_scan_session(struct work_struct *work)
+ {
+ 	struct iscsi_cls_session *session =
+ 			container_of(work, struct iscsi_cls_session, scan_work);
+ 	struct Scsi_Host *shost = iscsi_session_to_shost(session);
+ 	struct iscsi_cls_host *ihost = shost->shost_data;
+-	unsigned long flags;
++	struct iscsi_scan_data scan_data;
+ 
+-	spin_lock_irqsave(&session->lock, flags);
+-	if (session->state != ISCSI_SESSION_LOGGED_IN) {
+-		spin_unlock_irqrestore(&session->lock, flags);
+-		goto done;
+-	}
+-	spin_unlock_irqrestore(&session->lock, flags);
++	scan_data.channel = 0;
++	scan_data.id = SCAN_WILD_CARD;
++	scan_data.lun = SCAN_WILD_CARD;
+ 
+-	scsi_scan_target(&session->dev, 0, session->target_id,
+-			 SCAN_WILD_CARD, 1);
+-done:
++	iscsi_user_scan_session(&session->dev, &scan_data);
+ 	atomic_dec(&ihost->nr_scans);
+ }
+ 
+@@ -460,14 +493,18 @@ static void __iscsi_unbind_session(struct work_struct *work)
+ 				     unbind_work);
+ 	struct Scsi_Host *shost = iscsi_session_to_shost(session);
+ 	struct iscsi_cls_host *ihost = shost->shost_data;
++	unsigned long flags;
+ 
+ 	/* Prevent new scans and make sure scanning is not in progress */
+ 	mutex_lock(&ihost->mutex);
+-	if (list_empty(&session->host_list)) {
++	spin_lock_irqsave(&session->lock, flags);
++	if (session->target_id == ISCSI_MAX_TARGET) {
++		spin_unlock_irqrestore(&session->lock, flags);
+ 		mutex_unlock(&ihost->mutex);
+ 		return;
+ 	}
+-	list_del_init(&session->host_list);
++	session->target_id = ISCSI_MAX_TARGET;
++	spin_unlock_irqrestore(&session->lock, flags);
+ 	mutex_unlock(&ihost->mutex);
+ 
+ 	scsi_remove_target(&session->dev);
+@@ -497,7 +534,6 @@ iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
+ 	session->recovery_tmo = 120;
+ 	session->state = ISCSI_SESSION_FREE;
+ 	INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout);
+-	INIT_LIST_HEAD(&session->host_list);
+ 	INIT_LIST_HEAD(&session->sess_list);
+ 	INIT_WORK(&session->unblock_work, __iscsi_unblock_session);
+ 	INIT_WORK(&session->block_work, __iscsi_block_session);
+@@ -516,16 +552,51 @@ iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
+ }
+ EXPORT_SYMBOL_GPL(iscsi_alloc_session);
+ 
++static int iscsi_get_next_target_id(struct device *dev, void *data)
++{
++	struct iscsi_cls_session *session;
++	unsigned long flags;
++	int err = 0;
++
++	if (!iscsi_is_session_dev(dev))
++		return 0;
++
++	session = iscsi_dev_to_session(dev);
++	spin_lock_irqsave(&session->lock, flags);
++	if (*((unsigned int *) data) == session->target_id)
++		err = -EEXIST;
++	spin_unlock_irqrestore(&session->lock, flags);
++	return err;
++}
++
+ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
+ {
+ 	struct Scsi_Host *shost = iscsi_session_to_shost(session);
+ 	struct iscsi_cls_host *ihost;
+ 	unsigned long flags;
++	unsigned int id = target_id;
+ 	int err;
+ 
+ 	ihost = shost->shost_data;
+ 	session->sid = atomic_add_return(1, &iscsi_session_nr);
+-	session->target_id = target_id;
++
++	if (id == ISCSI_MAX_TARGET) {
++		for (id = 0; id < ISCSI_MAX_TARGET; id++) {
++			err = device_for_each_child(&shost->shost_gendev, &id,
++						    iscsi_get_next_target_id);
++			if (!err)
++				break;
++		}
++
++		if (id == ISCSI_MAX_TARGET) {
++			iscsi_cls_session_printk(KERN_ERR, session,
++						 "Too many iscsi targets. Max "
++						 "number of targets is %d.\n",
++						 ISCSI_MAX_TARGET - 1);
++			goto release_host;
++		}
++	}
++	session->target_id = id;
+ 
+ 	snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u",
+ 		 session->sid);
+@@ -541,10 +612,6 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
+ 	list_add(&session->sess_list, &sesslist);
+ 	spin_unlock_irqrestore(&sesslock, flags);
+ 
+-	mutex_lock(&ihost->mutex);
+-	list_add(&session->host_list, &ihost->sessions);
+-	mutex_unlock(&ihost->mutex);
+-
+ 	iscsi_session_event(session, ISCSI_KEVENT_CREATE_SESSION);
+ 	return 0;
+ 
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 176353c117b6..13c92d7ba969 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -331,7 +331,7 @@ extern void iscsi_host_free(struct Scsi_Host *shost);
+  */
+ extern struct iscsi_cls_session *
+ iscsi_session_setup(struct iscsi_transport *, struct Scsi_Host *shost,
+-		    uint16_t, int, uint32_t);
++		    uint16_t, int, uint32_t, unsigned int);
+ extern void iscsi_session_teardown(struct iscsi_cls_session *);
+ extern void iscsi_session_recovery_timedout(struct iscsi_cls_session *);
+ extern int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 0553240796e9..d6b823195563 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -161,9 +161,10 @@ enum {
+ 	ISCSI_SESSION_FREE,
+ };
+ 
++#define ISCSI_MAX_TARGET -1
++
+ struct iscsi_cls_session {
+ 	struct list_head sess_list;		/* item in session_list */
+-	struct list_head host_list;
+ 	struct iscsi_transport *transport;
+ 	spinlock_t lock;
+ 	struct work_struct block_work;
+@@ -175,7 +176,7 @@ struct iscsi_cls_session {
+ 	int recovery_tmo;
+ 	struct delayed_work recovery_work;
+ 
+-	int target_id;
++	unsigned int target_id;
+ 
+ 	int state;
+ 	int sid;				/* session id */
+@@ -193,7 +194,6 @@ struct iscsi_cls_session {
+ 	iscsi_dev_to_session(_stgt->dev.parent)
+ 
+ struct iscsi_cls_host {
+-	struct list_head sessions;
+ 	atomic_t nr_scans;
+ 	struct mutex mutex;
+ 	struct workqueue_struct *scan_workq;

commit 2261ec3d686e35c1a6088ab7f00a1d02b528b994
+Author: Mike Christie 
+Date:   Wed May 21 15:54:11 2008 -0500
+
+    [SCSI] iser: handle iscsi_cmd_task rename
+    
+    This handles the iscsi_cmd_task rename and renames
+    the iser cmd task to iser task.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index baecca1ed42a..86d9c42f0d33 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -124,33 +124,33 @@ iscsi_iser_recv(struct iscsi_conn *conn,
+ 
+ 
+ /**
+- * iscsi_iser_task_init - Initialize ctask
+- * @ctask: iscsi ctask
++ * iscsi_iser_task_init - Initialize task
++ * @task: iscsi task
+  *
+- * Initialize the ctask for the scsi command or mgmt command.
++ * Initialize the task for the scsi command or mgmt command.
+  */
+ static int
+-iscsi_iser_task_init(struct iscsi_cmd_task *ctask)
++iscsi_iser_task_init(struct iscsi_task *task)
+ {
+-	struct iscsi_iser_conn *iser_conn  = ctask->conn->dd_data;
+-	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
++	struct iscsi_iser_conn *iser_conn  = task->conn->dd_data;
++	struct iscsi_iser_task *iser_task = task->dd_data;
+ 
+-	/* mgmt ctask */
+-	if (!ctask->sc) {
+-		iser_ctask->desc.data = ctask->data;
++	/* mgmt task */
++	if (!task->sc) {
++		iser_task->desc.data = task->data;
+ 		return 0;
+ 	}
+ 
+-	iser_ctask->command_sent = 0;
+-	iser_ctask->iser_conn    = iser_conn;
+-	iser_ctask_rdma_init(iser_ctask);
++	iser_task->command_sent = 0;
++	iser_task->iser_conn    = iser_conn;
++	iser_task_rdma_init(iser_task);
+ 	return 0;
+ }
+ 
+ /**
+- * iscsi_iser_mtask_xmit - xmit management(immediate) ctask
++ * iscsi_iser_mtask_xmit - xmit management(immediate) task
+  * @conn: iscsi connection
+- * @ctask: ctask management ctask
++ * @task: task management task
+  *
+  * Notes:
+  *	The function can return -EAGAIN in which case caller must
+@@ -159,19 +159,19 @@ iscsi_iser_task_init(struct iscsi_cmd_task *ctask)
+  *
+  **/
+ static int
+-iscsi_iser_mtask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
++iscsi_iser_mtask_xmit(struct iscsi_conn *conn, struct iscsi_task *task)
+ {
+ 	int error = 0;
+ 
+-	debug_scsi("ctask deq [cid %d itt 0x%x]\n", conn->id, ctask->itt);
++	debug_scsi("task deq [cid %d itt 0x%x]\n", conn->id, task->itt);
+ 
+-	error = iser_send_control(conn, ctask);
++	error = iser_send_control(conn, task);
+ 
+-	/* since iser xmits control with zero copy, ctasks can not be recycled
++	/* since iser xmits control with zero copy, tasks can not be recycled
+ 	 * right after sending them.
+ 	 * The recycling scheme is based on whether a response is expected
+-	 * - if yes, the ctask is recycled at iscsi_complete_pdu
+-	 * - if no,  the ctask is recycled at iser_snd_completion
++	 * - if yes, the task is recycled at iscsi_complete_pdu
++	 * - if no,  the task is recycled at iser_snd_completion
+ 	 */
+ 	if (error && error != -ENOBUFS)
+ 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+@@ -181,27 +181,27 @@ iscsi_iser_mtask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 
+ static int
+ iscsi_iser_task_xmit_unsol_data(struct iscsi_conn *conn,
+-				 struct iscsi_cmd_task *ctask)
++				 struct iscsi_task *task)
+ {
+ 	struct iscsi_data  hdr;
+ 	int error = 0;
+ 
+ 	/* Send data-out PDUs while there's still unsolicited data to send */
+-	while (ctask->unsol_count > 0) {
+-		iscsi_prep_unsolicit_data_pdu(ctask, &hdr);
++	while (task->unsol_count > 0) {
++		iscsi_prep_unsolicit_data_pdu(task, &hdr);
+ 		debug_scsi("Sending data-out: itt 0x%x, data count %d\n",
+-			   hdr.itt, ctask->data_count);
++			   hdr.itt, task->data_count);
+ 
+ 		/* the buffer description has been passed with the command */
+ 		/* Send the command */
+-		error = iser_send_data_out(conn, ctask, &hdr);
++		error = iser_send_data_out(conn, task, &hdr);
+ 		if (error) {
+-			ctask->unsol_datasn--;
++			task->unsol_datasn--;
+ 			goto iscsi_iser_task_xmit_unsol_data_exit;
+ 		}
+-		ctask->unsol_count -= ctask->data_count;
++		task->unsol_count -= task->data_count;
+ 		debug_scsi("Need to send %d more as data-out PDUs\n",
+-			   ctask->unsol_count);
++			   task->unsol_count);
+ 	}
+ 
+ iscsi_iser_task_xmit_unsol_data_exit:
+@@ -209,37 +209,37 @@ iscsi_iser_task_xmit_unsol_data(struct iscsi_conn *conn,
+ }
+ 
+ static int
+-iscsi_iser_task_xmit(struct iscsi_cmd_task *ctask)
++iscsi_iser_task_xmit(struct iscsi_task *task)
+ {
+-	struct iscsi_conn *conn = ctask->conn;
+-	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
++	struct iscsi_conn *conn = task->conn;
++	struct iscsi_iser_task *iser_task = task->dd_data;
+ 	int error = 0;
+ 
+-	if (!ctask->sc)
+-		return iscsi_iser_mtask_xmit(conn, ctask);
++	if (!task->sc)
++		return iscsi_iser_mtask_xmit(conn, task);
+ 
+-	if (ctask->sc->sc_data_direction == DMA_TO_DEVICE) {
+-		BUG_ON(scsi_bufflen(ctask->sc) == 0);
++	if (task->sc->sc_data_direction == DMA_TO_DEVICE) {
++		BUG_ON(scsi_bufflen(task->sc) == 0);
+ 
+ 		debug_scsi("cmd [itt %x total %d imm %d unsol_data %d\n",
+-			   ctask->itt, scsi_bufflen(ctask->sc),
+-			   ctask->imm_count, ctask->unsol_count);
++			   task->itt, scsi_bufflen(task->sc),
++			   task->imm_count, task->unsol_count);
+ 	}
+ 
+-	debug_scsi("ctask deq [cid %d itt 0x%x]\n",
+-		   conn->id, ctask->itt);
++	debug_scsi("task deq [cid %d itt 0x%x]\n",
++		   conn->id, task->itt);
+ 
+ 	/* Send the cmd PDU */
+-	if (!iser_ctask->command_sent) {
+-		error = iser_send_command(conn, ctask);
++	if (!iser_task->command_sent) {
++		error = iser_send_command(conn, task);
+ 		if (error)
+ 			goto iscsi_iser_task_xmit_exit;
+-		iser_ctask->command_sent = 1;
++		iser_task->command_sent = 1;
+ 	}
+ 
+ 	/* Send unsolicited data-out PDU(s) if necessary */
+-	if (ctask->unsol_count)
+-		error = iscsi_iser_task_xmit_unsol_data(conn, ctask);
++	if (task->unsol_count)
++		error = iscsi_iser_task_xmit_unsol_data(conn, task);
+ 
+  iscsi_iser_task_xmit_exit:
+ 	if (error && error != -ENOBUFS)
+@@ -248,17 +248,17 @@ iscsi_iser_task_xmit(struct iscsi_cmd_task *ctask)
+ }
+ 
+ static void
+-iscsi_iser_cleanup_task(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
++iscsi_iser_cleanup_task(struct iscsi_conn *conn, struct iscsi_task *task)
+ {
+-	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
++	struct iscsi_iser_task *iser_task = task->dd_data;
+ 
+ 	/* mgmt tasks do not need special cleanup */
+-	if (!ctask->sc)
++	if (!task->sc)
+ 		return;
+ 
+-	if (iser_ctask->status == ISER_TASK_STATUS_STARTED) {
+-		iser_ctask->status = ISER_TASK_STATUS_COMPLETED;
+-		iser_ctask_rdma_finalize(iser_ctask);
++	if (iser_task->status == ISER_TASK_STATUS_STARTED) {
++		iser_task->status = ISER_TASK_STATUS_COMPLETED;
++		iser_task_rdma_finalize(iser_task);
+ 	}
+ }
+ 
+@@ -408,8 +408,8 @@ iscsi_iser_session_create(struct Scsi_Host *shost,
+ 	struct iscsi_cls_session *cls_session;
+ 	struct iscsi_session *session;
+ 	int i;
+-	struct iscsi_cmd_task *ctask;
+-	struct iscsi_iser_cmd_task *iser_ctask;
++	struct iscsi_task *task;
++	struct iscsi_iser_task *iser_task;
+ 
+ 	if (shost) {
+ 		printk(KERN_ERR "iscsi_tcp: invalid shost %d.\n",
+@@ -436,7 +436,7 @@ iscsi_iser_session_create(struct Scsi_Host *shost,
+ 	 */
+ 	cls_session = iscsi_session_setup(&iscsi_iser_transport, shost,
+ 					  ISCSI_DEF_XMIT_CMDS_MAX,
+-					  sizeof(struct iscsi_iser_cmd_task),
++					  sizeof(struct iscsi_iser_task),
+ 					  initial_cmdsn);
+ 	if (!cls_session)
+ 		goto remove_host;
+@@ -445,10 +445,10 @@ iscsi_iser_session_create(struct Scsi_Host *shost,
+ 	shost->can_queue = session->scsi_cmds_max;
+ 	/* libiscsi setup itts, data and pool so just set desc fields */
+ 	for (i = 0; i < session->cmds_max; i++) {
+-		ctask = session->cmds[i];
+-		iser_ctask = ctask->dd_data;
+-		ctask->hdr = (struct iscsi_cmd *)&iser_ctask->desc.iscsi_header;
+-		ctask->hdr_max = sizeof(iser_ctask->desc.iscsi_header);
++		task = session->cmds[i];
++		iser_task = task->dd_data;
++		task->hdr = (struct iscsi_cmd *)&iser_task->desc.iscsi_header;
++		task->hdr_max = sizeof(iser_task->desc.iscsi_header);
+ 	}
+ 	return cls_session;
+ 
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
+index 96a600f127c8..05431f270fe8 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
+@@ -173,7 +173,7 @@ struct iser_data_buf {
+ /* fwd declarations */
+ struct iser_device;
+ struct iscsi_iser_conn;
+-struct iscsi_iser_cmd_task;
++struct iscsi_iser_task;
+ 
+ struct iser_mem_reg {
+ 	u32  lkey;
+@@ -197,7 +197,7 @@ struct iser_regd_buf {
+ #define MAX_REGD_BUF_VECTOR_LEN	2
+ 
+ struct iser_dto {
+-	struct iscsi_iser_cmd_task *ctask;
++	struct iscsi_iser_task *task;
+ 	struct iser_conn *ib_conn;
+ 	int                        notify_enable;
+ 
+@@ -265,7 +265,7 @@ struct iscsi_iser_conn {
+ 	rwlock_t		     lock;
+ };
+ 
+-struct iscsi_iser_cmd_task {
++struct iscsi_iser_task {
+ 	struct iser_desc             desc;
+ 	struct iscsi_iser_conn	     *iser_conn;
+ 	enum iser_task_status 	     status;
+@@ -299,13 +299,13 @@ extern int iser_debug_level;
+ int iser_conn_set_full_featured_mode(struct iscsi_conn *conn);
+ 
+ int iser_send_control(struct iscsi_conn *conn,
+-		      struct iscsi_cmd_task *ctask);
++		      struct iscsi_task *task);
+ 
+ int iser_send_command(struct iscsi_conn *conn,
+-		      struct iscsi_cmd_task *ctask);
++		      struct iscsi_task *task);
+ 
+ int iser_send_data_out(struct iscsi_conn *conn,
+-		       struct iscsi_cmd_task *ctask,
++		       struct iscsi_task *task,
+ 		       struct iscsi_data *hdr);
+ 
+ void iscsi_iser_recv(struct iscsi_conn *conn,
+@@ -326,9 +326,9 @@ void iser_rcv_completion(struct iser_desc *desc,
+ 
+ void iser_snd_completion(struct iser_desc *desc);
+ 
+-void iser_ctask_rdma_init(struct iscsi_iser_cmd_task *ctask);
++void iser_task_rdma_init(struct iscsi_iser_task *task);
+ 
+-void iser_ctask_rdma_finalize(struct iscsi_iser_cmd_task *ctask);
++void iser_task_rdma_finalize(struct iscsi_iser_task *task);
+ 
+ void iser_dto_buffs_release(struct iser_dto *dto);
+ 
+@@ -338,10 +338,10 @@ void iser_reg_single(struct iser_device      *device,
+ 		     struct iser_regd_buf    *regd_buf,
+ 		     enum dma_data_direction direction);
+ 
+-void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_cmd_task *ctask,
++void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_task *task,
+ 				     enum iser_data_dir         cmd_dir);
+ 
+-int  iser_reg_rdma_mem(struct iscsi_iser_cmd_task *ctask,
++int  iser_reg_rdma_mem(struct iscsi_iser_task *task,
+ 		       enum   iser_data_dir        cmd_dir);
+ 
+ int  iser_connect(struct iser_conn   *ib_conn,
+@@ -361,10 +361,10 @@ int  iser_post_send(struct iser_desc *tx_desc);
+ int iser_conn_state_comp(struct iser_conn *ib_conn,
+ 			 enum iser_ib_conn_state comp);
+ 
+-int iser_dma_map_task_data(struct iscsi_iser_cmd_task *iser_ctask,
++int iser_dma_map_task_data(struct iscsi_iser_task *iser_task,
+ 			    struct iser_data_buf       *data,
+ 			    enum   iser_data_dir       iser_dir,
+ 			    enum   dma_data_direction  dma_dir);
+ 
+-void iser_dma_unmap_task_data(struct iscsi_iser_cmd_task *iser_ctask);
++void iser_dma_unmap_task_data(struct iscsi_iser_task *iser_task);
+ #endif
+diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
+index 4ea78fbeee95..35af60a23c61 100644
+--- a/drivers/infiniband/ulp/iser/iser_initiator.c
++++ b/drivers/infiniband/ulp/iser/iser_initiator.c
+@@ -66,46 +66,46 @@ static void iser_dto_add_regd_buff(struct iser_dto *dto,
+ 
+ /* Register user buffer memory and initialize passive rdma
+  *  dto descriptor. Total data size is stored in
+- *  iser_ctask->data[ISER_DIR_IN].data_len
++ *  iser_task->data[ISER_DIR_IN].data_len
+  */
+-static int iser_prepare_read_cmd(struct iscsi_cmd_task *ctask,
++static int iser_prepare_read_cmd(struct iscsi_task *task,
+ 				 unsigned int edtl)
+ 
+ {
+-	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
++	struct iscsi_iser_task *iser_task = task->dd_data;
+ 	struct iser_regd_buf *regd_buf;
+ 	int err;
+-	struct iser_hdr *hdr = &iser_ctask->desc.iser_header;
+-	struct iser_data_buf *buf_in = &iser_ctask->data[ISER_DIR_IN];
++	struct iser_hdr *hdr = &iser_task->desc.iser_header;
++	struct iser_data_buf *buf_in = &iser_task->data[ISER_DIR_IN];
+ 
+-	err = iser_dma_map_task_data(iser_ctask,
++	err = iser_dma_map_task_data(iser_task,
+ 				     buf_in,
+ 				     ISER_DIR_IN,
+ 				     DMA_FROM_DEVICE);
+ 	if (err)
+ 		return err;
+ 
+-	if (edtl > iser_ctask->data[ISER_DIR_IN].data_len) {
++	if (edtl > iser_task->data[ISER_DIR_IN].data_len) {
+ 		iser_err("Total data length: %ld, less than EDTL: "
+ 			 "%d, in READ cmd BHS itt: %d, conn: 0x%p\n",
+-			 iser_ctask->data[ISER_DIR_IN].data_len, edtl,
+-			 ctask->itt, iser_ctask->iser_conn);
++			 iser_task->data[ISER_DIR_IN].data_len, edtl,
++			 task->itt, iser_task->iser_conn);
+ 		return -EINVAL;
+ 	}
+ 
+-	err = iser_reg_rdma_mem(iser_ctask,ISER_DIR_IN);
++	err = iser_reg_rdma_mem(iser_task,ISER_DIR_IN);
+ 	if (err) {
+ 		iser_err("Failed to set up Data-IN RDMA\n");
+ 		return err;
+ 	}
+-	regd_buf = &iser_ctask->rdma_regd[ISER_DIR_IN];
++	regd_buf = &iser_task->rdma_regd[ISER_DIR_IN];
+ 
+ 	hdr->flags    |= ISER_RSV;
+ 	hdr->read_stag = cpu_to_be32(regd_buf->reg.rkey);
+ 	hdr->read_va   = cpu_to_be64(regd_buf->reg.va);
+ 
+ 	iser_dbg("Cmd itt:%d READ tags RKEY:%#.4X VA:%#llX\n",
+-		 ctask->itt, regd_buf->reg.rkey,
++		 task->itt, regd_buf->reg.rkey,
+ 		 (unsigned long long)regd_buf->reg.va);
+ 
+ 	return 0;
+@@ -113,43 +113,43 @@ static int iser_prepare_read_cmd(struct iscsi_cmd_task *ctask,
+ 
+ /* Register user buffer memory and initialize passive rdma
+  *  dto descriptor. Total data size is stored in
+- *  ctask->data[ISER_DIR_OUT].data_len
++ *  task->data[ISER_DIR_OUT].data_len
+  */
+ static int
+-iser_prepare_write_cmd(struct iscsi_cmd_task *ctask,
++iser_prepare_write_cmd(struct iscsi_task *task,
+ 		       unsigned int imm_sz,
+ 		       unsigned int unsol_sz,
+ 		       unsigned int edtl)
+ {
+-	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
++	struct iscsi_iser_task *iser_task = task->dd_data;
+ 	struct iser_regd_buf *regd_buf;
+ 	int err;
+-	struct iser_dto *send_dto = &iser_ctask->desc.dto;
+-	struct iser_hdr *hdr = &iser_ctask->desc.iser_header;
+-	struct iser_data_buf *buf_out = &iser_ctask->data[ISER_DIR_OUT];
++	struct iser_dto *send_dto = &iser_task->desc.dto;
++	struct iser_hdr *hdr = &iser_task->desc.iser_header;
++	struct iser_data_buf *buf_out = &iser_task->data[ISER_DIR_OUT];
+ 
+-	err = iser_dma_map_task_data(iser_ctask,
++	err = iser_dma_map_task_data(iser_task,
+ 				     buf_out,
+ 				     ISER_DIR_OUT,
+ 				     DMA_TO_DEVICE);
+ 	if (err)
+ 		return err;
+ 
+-	if (edtl > iser_ctask->data[ISER_DIR_OUT].data_len) {
++	if (edtl > iser_task->data[ISER_DIR_OUT].data_len) {
+ 		iser_err("Total data length: %ld, less than EDTL: %d, "
+ 			 "in WRITE cmd BHS itt: %d, conn: 0x%p\n",
+-			 iser_ctask->data[ISER_DIR_OUT].data_len,
+-			 edtl, ctask->itt, ctask->conn);
++			 iser_task->data[ISER_DIR_OUT].data_len,
++			 edtl, task->itt, task->conn);
+ 		return -EINVAL;
+ 	}
+ 
+-	err = iser_reg_rdma_mem(iser_ctask,ISER_DIR_OUT);
++	err = iser_reg_rdma_mem(iser_task,ISER_DIR_OUT);
+ 	if (err != 0) {
+ 		iser_err("Failed to register write cmd RDMA mem\n");
+ 		return err;
+ 	}
+ 
+-	regd_buf = &iser_ctask->rdma_regd[ISER_DIR_OUT];
++	regd_buf = &iser_task->rdma_regd[ISER_DIR_OUT];
+ 
+ 	if (unsol_sz < edtl) {
+ 		hdr->flags     |= ISER_WSV;
+@@ -158,13 +158,13 @@ iser_prepare_write_cmd(struct iscsi_cmd_task *ctask,
+ 
+ 		iser_dbg("Cmd itt:%d, WRITE tags, RKEY:%#.4X "
+ 			 "VA:%#llX + unsol:%d\n",
+-			 ctask->itt, regd_buf->reg.rkey,
++			 task->itt, regd_buf->reg.rkey,
+ 			 (unsigned long long)regd_buf->reg.va, unsol_sz);
+ 	}
+ 
+ 	if (imm_sz > 0) {
+ 		iser_dbg("Cmd itt:%d, WRITE, adding imm.data sz: %d\n",
+-			 ctask->itt, imm_sz);
++			 task->itt, imm_sz);
+ 		iser_dto_add_regd_buff(send_dto,
+ 				       regd_buf,
+ 				       0,
+@@ -300,13 +300,13 @@ int iser_conn_set_full_featured_mode(struct iscsi_conn *conn)
+ }
+ 
+ static int
+-iser_check_xmit(struct iscsi_conn *conn, void *ctask)
++iser_check_xmit(struct iscsi_conn *conn, void *task)
+ {
+ 	struct iscsi_iser_conn *iser_conn = conn->dd_data;
+ 
+ 	if (atomic_read(&iser_conn->ib_conn->post_send_buf_count) ==
+ 	    ISER_QP_MAX_REQ_DTOS) {
+-		iser_dbg("%ld can't xmit ctask %p\n",jiffies,ctask);
++		iser_dbg("%ld can't xmit task %p\n",jiffies,task);
+ 		return -ENOBUFS;
+ 	}
+ 	return 0;
+@@ -317,37 +317,37 @@ iser_check_xmit(struct iscsi_conn *conn, void *ctask)
+  * iser_send_command - send command PDU
+  */
+ int iser_send_command(struct iscsi_conn *conn,
+-		      struct iscsi_cmd_task *ctask)
++		      struct iscsi_task *task)
+ {
+ 	struct iscsi_iser_conn *iser_conn = conn->dd_data;
+-	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
++	struct iscsi_iser_task *iser_task = task->dd_data;
+ 	struct iser_dto *send_dto = NULL;
+ 	unsigned long edtl;
+ 	int err = 0;
+ 	struct iser_data_buf *data_buf;
+ 
+-	struct iscsi_cmd *hdr =  ctask->hdr;
+-	struct scsi_cmnd *sc  =  ctask->sc;
++	struct iscsi_cmd *hdr =  task->hdr;
++	struct scsi_cmnd *sc  =  task->sc;
+ 
+ 	if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) {
+ 		iser_err("Failed to send, conn: 0x%p is not up\n", iser_conn->ib_conn);
+ 		return -EPERM;
+ 	}
+-	if (iser_check_xmit(conn, ctask))
++	if (iser_check_xmit(conn, task))
+ 		return -ENOBUFS;
+ 
+ 	edtl = ntohl(hdr->data_length);
+ 
+ 	/* build the tx desc regd header and add it to the tx desc dto */
+-	iser_ctask->desc.type = ISCSI_TX_SCSI_COMMAND;
+-	send_dto = &iser_ctask->desc.dto;
+-	send_dto->ctask = iser_ctask;
+-	iser_create_send_desc(iser_conn, &iser_ctask->desc);
++	iser_task->desc.type = ISCSI_TX_SCSI_COMMAND;
++	send_dto = &iser_task->desc.dto;
++	send_dto->task = iser_task;
++	iser_create_send_desc(iser_conn, &iser_task->desc);
+ 
+ 	if (hdr->flags & ISCSI_FLAG_CMD_READ)
+-		data_buf = &iser_ctask->data[ISER_DIR_IN];
++		data_buf = &iser_task->data[ISER_DIR_IN];
+ 	else
+-		data_buf = &iser_ctask->data[ISER_DIR_OUT];
++		data_buf = &iser_task->data[ISER_DIR_OUT];
+ 
+ 	if (scsi_sg_count(sc)) { /* using a scatter list */
+ 		data_buf->buf  = scsi_sglist(sc);
+@@ -357,15 +357,15 @@ int iser_send_command(struct iscsi_conn *conn,
+ 	data_buf->data_len = scsi_bufflen(sc);
+ 
+ 	if (hdr->flags & ISCSI_FLAG_CMD_READ) {
+-		err = iser_prepare_read_cmd(ctask, edtl);
++		err = iser_prepare_read_cmd(task, edtl);
+ 		if (err)
+ 			goto send_command_error;
+ 	}
+ 	if (hdr->flags & ISCSI_FLAG_CMD_WRITE) {
+-		err = iser_prepare_write_cmd(ctask,
+-					     ctask->imm_count,
+-				             ctask->imm_count +
+-					     ctask->unsol_count,
++		err = iser_prepare_write_cmd(task,
++					     task->imm_count,
++				             task->imm_count +
++					     task->unsol_count,
+ 					     edtl);
+ 		if (err)
+ 			goto send_command_error;
+@@ -380,15 +380,15 @@ int iser_send_command(struct iscsi_conn *conn,
+ 		goto send_command_error;
+ 	}
+ 
+-	iser_ctask->status = ISER_TASK_STATUS_STARTED;
++	iser_task->status = ISER_TASK_STATUS_STARTED;
+ 
+-	err = iser_post_send(&iser_ctask->desc);
++	err = iser_post_send(&iser_task->desc);
+ 	if (!err)
+ 		return 0;
+ 
+ send_command_error:
+ 	iser_dto_buffs_release(send_dto);
+-	iser_err("conn %p failed ctask->itt %d err %d\n",conn, ctask->itt, err);
++	iser_err("conn %p failed task->itt %d err %d\n",conn, task->itt, err);
+ 	return err;
+ }
+ 
+@@ -396,11 +396,11 @@ int iser_send_command(struct iscsi_conn *conn,
+  * iser_send_data_out - send data out PDU
+  */
+ int iser_send_data_out(struct iscsi_conn *conn,
+-		       struct iscsi_cmd_task *ctask,
++		       struct iscsi_task *task,
+ 		       struct iscsi_data *hdr)
+ {
+ 	struct iscsi_iser_conn *iser_conn = conn->dd_data;
+-	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
++	struct iscsi_iser_task *iser_task = task->dd_data;
+ 	struct iser_desc *tx_desc = NULL;
+ 	struct iser_dto *send_dto = NULL;
+ 	unsigned long buf_offset;
+@@ -413,7 +413,7 @@ int iser_send_data_out(struct iscsi_conn *conn,
+ 		return -EPERM;
+ 	}
+ 
+-	if (iser_check_xmit(conn, ctask))
++	if (iser_check_xmit(conn, task))
+ 		return -ENOBUFS;
+ 
+ 	itt = (__force uint32_t)hdr->itt;
+@@ -434,7 +434,7 @@ int iser_send_data_out(struct iscsi_conn *conn,
+ 
+ 	/* build the tx desc regd header and add it to the tx desc dto */
+ 	send_dto = &tx_desc->dto;
+-	send_dto->ctask = iser_ctask;
++	send_dto->task = iser_task;
+ 	iser_create_send_desc(iser_conn, tx_desc);
+ 
+ 	iser_reg_single(iser_conn->ib_conn->device,
+@@ -442,15 +442,15 @@ int iser_send_data_out(struct iscsi_conn *conn,
+ 
+ 	/* all data was registered for RDMA, we can use the lkey */
+ 	iser_dto_add_regd_buff(send_dto,
+-			       &iser_ctask->rdma_regd[ISER_DIR_OUT],
++			       &iser_task->rdma_regd[ISER_DIR_OUT],
+ 			       buf_offset,
+ 			       data_seg_len);
+ 
+-	if (buf_offset + data_seg_len > iser_ctask->data[ISER_DIR_OUT].data_len) {
++	if (buf_offset + data_seg_len > iser_task->data[ISER_DIR_OUT].data_len) {
+ 		iser_err("Offset:%ld & DSL:%ld in Data-Out "
+ 			 "inconsistent with total len:%ld, itt:%d\n",
+ 			 buf_offset, data_seg_len,
+-			 iser_ctask->data[ISER_DIR_OUT].data_len, itt);
++			 iser_task->data[ISER_DIR_OUT].data_len, itt);
+ 		err = -EINVAL;
+ 		goto send_data_out_error;
+ 	}
+@@ -470,11 +470,11 @@ int iser_send_data_out(struct iscsi_conn *conn,
+ }
+ 
+ int iser_send_control(struct iscsi_conn *conn,
+-		      struct iscsi_cmd_task *ctask)
++		      struct iscsi_task *task)
+ {
+ 	struct iscsi_iser_conn *iser_conn = conn->dd_data;
+-	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
+-	struct iser_desc *mdesc = &iser_ctask->desc;
++	struct iscsi_iser_task *iser_task = task->dd_data;
++	struct iser_desc *mdesc = &iser_task->desc;
+ 	struct iser_dto *send_dto = NULL;
+ 	unsigned long data_seg_len;
+ 	int err = 0;
+@@ -486,27 +486,27 @@ int iser_send_control(struct iscsi_conn *conn,
+ 		return -EPERM;
+ 	}
+ 
+-	if (iser_check_xmit(conn, ctask))
++	if (iser_check_xmit(conn, task))
+ 		return -ENOBUFS;
+ 
+ 	/* build the tx desc regd header and add it to the tx desc dto */
+ 	mdesc->type = ISCSI_TX_CONTROL;
+ 	send_dto = &mdesc->dto;
+-	send_dto->ctask = NULL;
++	send_dto->task = NULL;
+ 	iser_create_send_desc(iser_conn, mdesc);
+ 
+ 	device = iser_conn->ib_conn->device;
+ 
+ 	iser_reg_single(device, send_dto->regd[0], DMA_TO_DEVICE);
+ 
+-	data_seg_len = ntoh24(ctask->hdr->dlength);
++	data_seg_len = ntoh24(task->hdr->dlength);
+ 
+ 	if (data_seg_len > 0) {
+ 		regd_buf = &mdesc->data_regd_buf;
+ 		memset(regd_buf, 0, sizeof(struct iser_regd_buf));
+ 		regd_buf->device = device;
+-		regd_buf->virt_addr = ctask->data;
+-		regd_buf->data_size = ctask->data_count;
++		regd_buf->virt_addr = task->data;
++		regd_buf->data_size = task->data_count;
+ 		iser_reg_single(device, regd_buf,
+ 				DMA_TO_DEVICE);
+ 		iser_dto_add_regd_buff(send_dto, regd_buf,
+@@ -538,8 +538,8 @@ void iser_rcv_completion(struct iser_desc *rx_desc,
+ {
+ 	struct iser_dto *dto = &rx_desc->dto;
+ 	struct iscsi_iser_conn *conn = dto->ib_conn->iser_conn;
+-	struct iscsi_cmd_task *ctask;
+-	struct iscsi_iser_cmd_task *iser_ctask;
++	struct iscsi_task *task;
++	struct iscsi_iser_task *iser_task;
+ 	struct iscsi_hdr *hdr;
+ 	char   *rx_data = NULL;
+ 	int     rx_data_len = 0;
+@@ -558,16 +558,16 @@ void iser_rcv_completion(struct iser_desc *rx_desc,
+ 	opcode = hdr->opcode & ISCSI_OPCODE_MASK;
+ 
+ 	if (opcode == ISCSI_OP_SCSI_CMD_RSP) {
+-		ctask = iscsi_itt_to_ctask(conn->iscsi_conn, hdr->itt);
+-		if (!ctask)
+-			iser_err("itt can't be matched to ctask!!! "
++		task = iscsi_itt_to_ctask(conn->iscsi_conn, hdr->itt);
++		if (!task)
++			iser_err("itt can't be matched to task!!! "
+ 				 "conn %p opcode %d itt %d\n",
+ 				 conn->iscsi_conn, opcode, hdr->itt);
+ 		else {
+-			iser_ctask = ctask->dd_data;
+-			iser_dbg("itt %d ctask %p\n",hdr->itt, ctask);
+-			iser_ctask->status = ISER_TASK_STATUS_COMPLETED;
+-			iser_ctask_rdma_finalize(iser_ctask);
++			iser_task = task->dd_data;
++			iser_dbg("itt %d task %p\n",hdr->itt, task);
++			iser_task->status = ISER_TASK_STATUS_COMPLETED;
++			iser_task_rdma_finalize(iser_task);
+ 		}
+ 	}
+ 	iser_dto_buffs_release(dto);
+@@ -578,7 +578,7 @@ void iser_rcv_completion(struct iser_desc *rx_desc,
+ 	kmem_cache_free(ig.desc_cache, rx_desc);
+ 
+ 	/* decrementing conn->post_recv_buf_count only --after-- freeing the   *
+-	 * ctask eliminates the need to worry on ctasks which are completed in   *
++	 * task eliminates the need to worry on tasks which are completed in   *
+ 	 * parallel to the execution of iser_conn_term. So the code that waits *
+ 	 * for the posted rx bufs refcount to become zero handles everything   */
+ 	atomic_dec(&conn->ib_conn->post_recv_buf_count);
+@@ -590,7 +590,7 @@ void iser_snd_completion(struct iser_desc *tx_desc)
+ 	struct iser_conn       *ib_conn = dto->ib_conn;
+ 	struct iscsi_iser_conn *iser_conn = ib_conn->iser_conn;
+ 	struct iscsi_conn      *conn = iser_conn->iscsi_conn;
+-	struct iscsi_cmd_task *ctask;
++	struct iscsi_task *task;
+ 	int resume_tx = 0;
+ 
+ 	iser_dbg("Initiator, Data sent dto=0x%p\n", dto);
+@@ -613,31 +613,31 @@ void iser_snd_completion(struct iser_desc *tx_desc)
+ 
+ 	if (tx_desc->type == ISCSI_TX_CONTROL) {
+ 		/* this arithmetic is legal by libiscsi dd_data allocation */
+-		ctask = (void *) ((long)(void *)tx_desc -
+-				  sizeof(struct iscsi_cmd_task));
+-		if (ctask->hdr->itt == RESERVED_ITT)
+-			iscsi_put_ctask(ctask);
++		task = (void *) ((long)(void *)tx_desc -
++				  sizeof(struct iscsi_task));
++		if (task->hdr->itt == RESERVED_ITT)
++			iscsi_put_task(task);
+ 	}
+ }
+ 
+-void iser_ctask_rdma_init(struct iscsi_iser_cmd_task *iser_ctask)
++void iser_task_rdma_init(struct iscsi_iser_task *iser_task)
+ 
+ {
+-	iser_ctask->status = ISER_TASK_STATUS_INIT;
++	iser_task->status = ISER_TASK_STATUS_INIT;
+ 
+-	iser_ctask->dir[ISER_DIR_IN] = 0;
+-	iser_ctask->dir[ISER_DIR_OUT] = 0;
++	iser_task->dir[ISER_DIR_IN] = 0;
++	iser_task->dir[ISER_DIR_OUT] = 0;
+ 
+-	iser_ctask->data[ISER_DIR_IN].data_len  = 0;
+-	iser_ctask->data[ISER_DIR_OUT].data_len = 0;
++	iser_task->data[ISER_DIR_IN].data_len  = 0;
++	iser_task->data[ISER_DIR_OUT].data_len = 0;
+ 
+-	memset(&iser_ctask->rdma_regd[ISER_DIR_IN], 0,
++	memset(&iser_task->rdma_regd[ISER_DIR_IN], 0,
+ 	       sizeof(struct iser_regd_buf));
+-	memset(&iser_ctask->rdma_regd[ISER_DIR_OUT], 0,
++	memset(&iser_task->rdma_regd[ISER_DIR_OUT], 0,
+ 	       sizeof(struct iser_regd_buf));
+ }
+ 
+-void iser_ctask_rdma_finalize(struct iscsi_iser_cmd_task *iser_ctask)
++void iser_task_rdma_finalize(struct iscsi_iser_task *iser_task)
+ {
+ 	int deferred;
+ 	int is_rdma_aligned = 1;
+@@ -646,17 +646,17 @@ void iser_ctask_rdma_finalize(struct iscsi_iser_cmd_task *iser_ctask)
+ 	/* if we were reading, copy back to unaligned sglist,
+ 	 * anyway dma_unmap and free the copy
+ 	 */
+-	if (iser_ctask->data_copy[ISER_DIR_IN].copy_buf != NULL) {
++	if (iser_task->data_copy[ISER_DIR_IN].copy_buf != NULL) {
+ 		is_rdma_aligned = 0;
+-		iser_finalize_rdma_unaligned_sg(iser_ctask, ISER_DIR_IN);
++		iser_finalize_rdma_unaligned_sg(iser_task, ISER_DIR_IN);
+ 	}
+-	if (iser_ctask->data_copy[ISER_DIR_OUT].copy_buf != NULL) {
++	if (iser_task->data_copy[ISER_DIR_OUT].copy_buf != NULL) {
+ 		is_rdma_aligned = 0;
+-		iser_finalize_rdma_unaligned_sg(iser_ctask, ISER_DIR_OUT);
++		iser_finalize_rdma_unaligned_sg(iser_task, ISER_DIR_OUT);
+ 	}
+ 
+-	if (iser_ctask->dir[ISER_DIR_IN]) {
+-		regd = &iser_ctask->rdma_regd[ISER_DIR_IN];
++	if (iser_task->dir[ISER_DIR_IN]) {
++		regd = &iser_task->rdma_regd[ISER_DIR_IN];
+ 		deferred = iser_regd_buff_release(regd);
+ 		if (deferred) {
+ 			iser_err("%d references remain for BUF-IN rdma reg\n",
+@@ -664,8 +664,8 @@ void iser_ctask_rdma_finalize(struct iscsi_iser_cmd_task *iser_ctask)
+ 		}
+ 	}
+ 
+-	if (iser_ctask->dir[ISER_DIR_OUT]) {
+-		regd = &iser_ctask->rdma_regd[ISER_DIR_OUT];
++	if (iser_task->dir[ISER_DIR_OUT]) {
++		regd = &iser_task->rdma_regd[ISER_DIR_OUT];
+ 		deferred = iser_regd_buff_release(regd);
+ 		if (deferred) {
+ 			iser_err("%d references remain for BUF-OUT rdma reg\n",
+@@ -675,7 +675,7 @@ void iser_ctask_rdma_finalize(struct iscsi_iser_cmd_task *iser_ctask)
+ 
+        /* if the data was unaligned, it was already unmapped and then copied */
+        if (is_rdma_aligned)
+-		iser_dma_unmap_task_data(iser_ctask);
++		iser_dma_unmap_task_data(iser_task);
+ }
+ 
+ void iser_dto_buffs_release(struct iser_dto *dto)
+diff --git a/drivers/infiniband/ulp/iser/iser_memory.c b/drivers/infiniband/ulp/iser/iser_memory.c
+index cac50c4dc159..48f2a601fc27 100644
+--- a/drivers/infiniband/ulp/iser/iser_memory.c
++++ b/drivers/infiniband/ulp/iser/iser_memory.c
+@@ -101,13 +101,13 @@ void iser_reg_single(struct iser_device *device,
+ /**
+  * iser_start_rdma_unaligned_sg
+  */
+-static int iser_start_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask,
++static int iser_start_rdma_unaligned_sg(struct iscsi_iser_task *iser_task,
+ 					enum iser_data_dir cmd_dir)
+ {
+ 	int dma_nents;
+ 	struct ib_device *dev;
+ 	char *mem = NULL;
+-	struct iser_data_buf *data = &iser_ctask->data[cmd_dir];
++	struct iser_data_buf *data = &iser_task->data[cmd_dir];
+ 	unsigned long  cmd_data_len = data->data_len;
+ 
+ 	if (cmd_data_len > ISER_KMALLOC_THRESHOLD)
+@@ -140,37 +140,37 @@ static int iser_start_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask,
+ 		}
+ 	}
+ 
+-	sg_init_one(&iser_ctask->data_copy[cmd_dir].sg_single, mem, cmd_data_len);
+-	iser_ctask->data_copy[cmd_dir].buf  =
+-		&iser_ctask->data_copy[cmd_dir].sg_single;
+-	iser_ctask->data_copy[cmd_dir].size = 1;
++	sg_init_one(&iser_task->data_copy[cmd_dir].sg_single, mem, cmd_data_len);
++	iser_task->data_copy[cmd_dir].buf  =
++		&iser_task->data_copy[cmd_dir].sg_single;
++	iser_task->data_copy[cmd_dir].size = 1;
+ 
+-	iser_ctask->data_copy[cmd_dir].copy_buf  = mem;
++	iser_task->data_copy[cmd_dir].copy_buf  = mem;
+ 
+-	dev = iser_ctask->iser_conn->ib_conn->device->ib_device;
++	dev = iser_task->iser_conn->ib_conn->device->ib_device;
+ 	dma_nents = ib_dma_map_sg(dev,
+-				  &iser_ctask->data_copy[cmd_dir].sg_single,
++				  &iser_task->data_copy[cmd_dir].sg_single,
+ 				  1,
+ 				  (cmd_dir == ISER_DIR_OUT) ?
+ 				  DMA_TO_DEVICE : DMA_FROM_DEVICE);
+ 	BUG_ON(dma_nents == 0);
+ 
+-	iser_ctask->data_copy[cmd_dir].dma_nents = dma_nents;
++	iser_task->data_copy[cmd_dir].dma_nents = dma_nents;
+ 	return 0;
+ }
+ 
+ /**
+  * iser_finalize_rdma_unaligned_sg
+  */
+-void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask,
++void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_task *iser_task,
+ 				     enum iser_data_dir         cmd_dir)
+ {
+ 	struct ib_device *dev;
+ 	struct iser_data_buf *mem_copy;
+ 	unsigned long  cmd_data_len;
+ 
+-	dev = iser_ctask->iser_conn->ib_conn->device->ib_device;
+-	mem_copy = &iser_ctask->data_copy[cmd_dir];
++	dev = iser_task->iser_conn->ib_conn->device->ib_device;
++	mem_copy = &iser_task->data_copy[cmd_dir];
+ 
+ 	ib_dma_unmap_sg(dev, &mem_copy->sg_single, 1,
+ 			(cmd_dir == ISER_DIR_OUT) ?
+@@ -186,8 +186,8 @@ void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask,
+ 		/* copy back read RDMA to unaligned sg */
+ 		mem	= mem_copy->copy_buf;
+ 
+-		sgl	= (struct scatterlist *)iser_ctask->data[ISER_DIR_IN].buf;
+-		sg_size = iser_ctask->data[ISER_DIR_IN].size;
++		sgl	= (struct scatterlist *)iser_task->data[ISER_DIR_IN].buf;
++		sg_size = iser_task->data[ISER_DIR_IN].size;
+ 
+ 		p = mem;
+ 		for_each_sg(sgl, sg, sg_size, i) {
+@@ -200,7 +200,7 @@ void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask,
+ 		}
+ 	}
+ 
+-	cmd_data_len = iser_ctask->data[cmd_dir].data_len;
++	cmd_data_len = iser_task->data[cmd_dir].data_len;
+ 
+ 	if (cmd_data_len > ISER_KMALLOC_THRESHOLD)
+ 		free_pages((unsigned long)mem_copy->copy_buf,
+@@ -378,15 +378,15 @@ static void iser_page_vec_build(struct iser_data_buf *data,
+ 	}
+ }
+ 
+-int iser_dma_map_task_data(struct iscsi_iser_cmd_task *iser_ctask,
+-			    struct iser_data_buf       *data,
+-			    enum   iser_data_dir       iser_dir,
+-			    enum   dma_data_direction  dma_dir)
++int iser_dma_map_task_data(struct iscsi_iser_task *iser_task,
++			    struct iser_data_buf *data,
++			    enum iser_data_dir iser_dir,
++			    enum dma_data_direction dma_dir)
+ {
+ 	struct ib_device *dev;
+ 
+-	iser_ctask->dir[iser_dir] = 1;
+-	dev = iser_ctask->iser_conn->ib_conn->device->ib_device;
++	iser_task->dir[iser_dir] = 1;
++	dev = iser_task->iser_conn->ib_conn->device->ib_device;
+ 
+ 	data->dma_nents = ib_dma_map_sg(dev, data->buf, data->size, dma_dir);
+ 	if (data->dma_nents == 0) {
+@@ -396,20 +396,20 @@ int iser_dma_map_task_data(struct iscsi_iser_cmd_task *iser_ctask,
+ 	return 0;
+ }
+ 
+-void iser_dma_unmap_task_data(struct iscsi_iser_cmd_task *iser_ctask)
++void iser_dma_unmap_task_data(struct iscsi_iser_task *iser_task)
+ {
+ 	struct ib_device *dev;
+ 	struct iser_data_buf *data;
+ 
+-	dev = iser_ctask->iser_conn->ib_conn->device->ib_device;
++	dev = iser_task->iser_conn->ib_conn->device->ib_device;
+ 
+-	if (iser_ctask->dir[ISER_DIR_IN]) {
+-		data = &iser_ctask->data[ISER_DIR_IN];
++	if (iser_task->dir[ISER_DIR_IN]) {
++		data = &iser_task->data[ISER_DIR_IN];
+ 		ib_dma_unmap_sg(dev, data->buf, data->size, DMA_FROM_DEVICE);
+ 	}
+ 
+-	if (iser_ctask->dir[ISER_DIR_OUT]) {
+-		data = &iser_ctask->data[ISER_DIR_OUT];
++	if (iser_task->dir[ISER_DIR_OUT]) {
++		data = &iser_task->data[ISER_DIR_OUT];
+ 		ib_dma_unmap_sg(dev, data->buf, data->size, DMA_TO_DEVICE);
+ 	}
+ }
+@@ -420,21 +420,21 @@ void iser_dma_unmap_task_data(struct iscsi_iser_cmd_task *iser_ctask)
+  *
+  * returns 0 on success, errno code on failure
+  */
+-int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask,
++int iser_reg_rdma_mem(struct iscsi_iser_task *iser_task,
+ 		      enum   iser_data_dir        cmd_dir)
+ {
+-	struct iscsi_conn    *iscsi_conn = iser_ctask->iser_conn->iscsi_conn;
+-	struct iser_conn     *ib_conn = iser_ctask->iser_conn->ib_conn;
++	struct iscsi_conn    *iscsi_conn = iser_task->iser_conn->iscsi_conn;
++	struct iser_conn     *ib_conn = iser_task->iser_conn->ib_conn;
+ 	struct iser_device   *device = ib_conn->device;
+ 	struct ib_device     *ibdev = device->ib_device;
+-	struct iser_data_buf *mem = &iser_ctask->data[cmd_dir];
++	struct iser_data_buf *mem = &iser_task->data[cmd_dir];
+ 	struct iser_regd_buf *regd_buf;
+ 	int aligned_len;
+ 	int err;
+ 	int i;
+ 	struct scatterlist *sg;
+ 
+-	regd_buf = &iser_ctask->rdma_regd[cmd_dir];
++	regd_buf = &iser_task->rdma_regd[cmd_dir];
+ 
+ 	aligned_len = iser_data_buf_aligned_len(mem, ibdev);
+ 	if (aligned_len != mem->dma_nents) {
+@@ -444,13 +444,13 @@ int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask,
+ 		iser_data_buf_dump(mem, ibdev);
+ 
+ 		/* unmap the command data before accessing it */
+-		iser_dma_unmap_task_data(iser_ctask);
++		iser_dma_unmap_task_data(iser_task);
+ 
+ 		/* allocate copy buf, if we are writing, copy the */
+ 		/* unaligned scatterlist, dma map the copy        */
+-		if (iser_start_rdma_unaligned_sg(iser_ctask, cmd_dir) != 0)
++		if (iser_start_rdma_unaligned_sg(iser_task, cmd_dir) != 0)
+ 				return -ENOMEM;
+-		mem = &iser_ctask->data_copy[cmd_dir];
++		mem = &iser_task->data_copy[cmd_dir];
+ 	}
+ 
+ 	/* if there a single dma entry, FMR is not needed */
+@@ -474,8 +474,9 @@ int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask,
+ 		err = iser_reg_page_vec(ib_conn, ib_conn->page_vec, ®d_buf->reg);
+ 		if (err) {
+ 			iser_data_buf_dump(mem, ibdev);
+-			iser_err("mem->dma_nents = %d (dlength = 0x%x)\n", mem->dma_nents,
+-				 ntoh24(iser_ctask->desc.iscsi_header.dlength));
++			iser_err("mem->dma_nents = %d (dlength = 0x%x)\n",
++				 mem->dma_nents,
++				 ntoh24(iser_task->desc.iscsi_header.dlength));
+ 			iser_err("page_vec: data_size = 0x%x, length = %d, offset = 0x%x\n",
+ 				 ib_conn->page_vec->data_size, ib_conn->page_vec->length,
+ 				 ib_conn->page_vec->offset);

commit 135a8ad4e09309d36dcb8b5c7f55db0b6a15b2d6
+Author: Mike Christie 
+Date:   Wed May 21 15:54:10 2008 -0500
+
+    [SCSI] iscsi_tcp: handle iscsi_cmd_task rename
+    
+    This converts iscsi_tcp to use the iscsi_task name.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 517bad160bea..33cd0ca7cc8d 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -498,43 +498,43 @@ iscsi_tcp_data_recv_prep(struct iscsi_tcp_conn *tcp_conn)
+  * must be called with session lock
+  */
+ static void
+-iscsi_tcp_cleanup_task(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
++iscsi_tcp_cleanup_task(struct iscsi_conn *conn, struct iscsi_task *task)
+ {
+-	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++	struct iscsi_tcp_task *tcp_task = task->dd_data;
+ 	struct iscsi_r2t_info *r2t;
+ 
+-	/* nothing to do for mgmt ctasks */
+-	if (!ctask->sc)
++	/* nothing to do for mgmt tasks */
++	if (!task->sc)
+ 		return;
+ 
+-	/* flush ctask's r2t queues */
+-	while (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) {
+-		__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
++	/* flush task's r2t queues */
++	while (__kfifo_get(tcp_task->r2tqueue, (void*)&r2t, sizeof(void*))) {
++		__kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
+ 			    sizeof(void*));
+-		debug_scsi("iscsi_tcp_cleanup_ctask pending r2t dropped\n");
++		debug_scsi("iscsi_tcp_cleanup_task pending r2t dropped\n");
+ 	}
+ 
+-	r2t = tcp_ctask->r2t;
++	r2t = tcp_task->r2t;
+ 	if (r2t != NULL) {
+-		__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
++		__kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
+ 			    sizeof(void*));
+-		tcp_ctask->r2t = NULL;
++		tcp_task->r2t = NULL;
+ 	}
+ }
+ 
+ /**
+  * iscsi_data_rsp - SCSI Data-In Response processing
+  * @conn: iscsi connection
+- * @ctask: scsi command ctask
++ * @task: scsi command task
+  **/
+ static int
+-iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
++iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
+ {
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+-	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++	struct iscsi_tcp_task *tcp_task = task->dd_data;
+ 	struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)tcp_conn->in.hdr;
+ 	struct iscsi_session *session = conn->session;
+-	struct scsi_cmnd *sc = ctask->sc;
++	struct scsi_cmnd *sc = task->sc;
+ 	int datasn = be32_to_cpu(rhdr->datasn);
+ 	unsigned total_in_length = scsi_in(sc)->length;
+ 
+@@ -542,18 +542,18 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	if (tcp_conn->in.datalen == 0)
+ 		return 0;
+ 
+-	if (tcp_ctask->exp_datasn != datasn) {
+-		debug_tcp("%s: ctask->exp_datasn(%d) != rhdr->datasn(%d)\n",
+-		          __FUNCTION__, tcp_ctask->exp_datasn, datasn);
++	if (tcp_task->exp_datasn != datasn) {
++		debug_tcp("%s: task->exp_datasn(%d) != rhdr->datasn(%d)\n",
++		          __FUNCTION__, tcp_task->exp_datasn, datasn);
+ 		return ISCSI_ERR_DATASN;
+ 	}
+ 
+-	tcp_ctask->exp_datasn++;
++	tcp_task->exp_datasn++;
+ 
+-	tcp_ctask->data_offset = be32_to_cpu(rhdr->offset);
+-	if (tcp_ctask->data_offset + tcp_conn->in.datalen > total_in_length) {
++	tcp_task->data_offset = be32_to_cpu(rhdr->offset);
++	if (tcp_task->data_offset + tcp_conn->in.datalen > total_in_length) {
+ 		debug_tcp("%s: data_offset(%d) + data_len(%d) > total_length_in(%d)\n",
+-		          __FUNCTION__, tcp_ctask->data_offset,
++		          __FUNCTION__, tcp_task->data_offset,
+ 		          tcp_conn->in.datalen, total_in_length);
+ 		return ISCSI_ERR_DATA_OFFSET;
+ 	}
+@@ -582,7 +582,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ /**
+  * iscsi_solicit_data_init - initialize first Data-Out
+  * @conn: iscsi connection
+- * @ctask: scsi command ctask
++ * @task: scsi command task
+  * @r2t: R2T info
+  *
+  * Notes:
+@@ -592,7 +592,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+  *	This function is called with connection lock taken.
+  **/
+ static void
+-iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
++iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_task *task,
+ 			struct iscsi_r2t_info *r2t)
+ {
+ 	struct iscsi_data *hdr;
+@@ -603,8 +603,8 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 	hdr->datasn = cpu_to_be32(r2t->solicit_datasn);
+ 	r2t->solicit_datasn++;
+ 	hdr->opcode = ISCSI_OP_SCSI_DATA_OUT;
+-	memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun));
+-	hdr->itt = ctask->hdr->itt;
++	memcpy(hdr->lun, task->hdr->lun, sizeof(hdr->lun));
++	hdr->itt = task->hdr->itt;
+ 	hdr->exp_statsn = r2t->exp_statsn;
+ 	hdr->offset = cpu_to_be32(r2t->data_offset);
+ 	if (r2t->data_length > conn->max_xmit_dlength) {
+@@ -624,14 +624,14 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ /**
+  * iscsi_r2t_rsp - iSCSI R2T Response processing
+  * @conn: iscsi connection
+- * @ctask: scsi command ctask
++ * @task: scsi command task
+  **/
+ static int
+-iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
++iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
+ {
+ 	struct iscsi_r2t_info *r2t;
+ 	struct iscsi_session *session = conn->session;
+-	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++	struct iscsi_tcp_task *tcp_task = task->dd_data;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	struct iscsi_r2t_rsp *rhdr = (struct iscsi_r2t_rsp *)tcp_conn->in.hdr;
+ 	int r2tsn = be32_to_cpu(rhdr->r2tsn);
+@@ -644,23 +644,23 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 		return ISCSI_ERR_DATALEN;
+ 	}
+ 
+-	if (tcp_ctask->exp_datasn != r2tsn){
+-		debug_tcp("%s: ctask->exp_datasn(%d) != rhdr->r2tsn(%d)\n",
+-		          __FUNCTION__, tcp_ctask->exp_datasn, r2tsn);
++	if (tcp_task->exp_datasn != r2tsn){
++		debug_tcp("%s: task->exp_datasn(%d) != rhdr->r2tsn(%d)\n",
++		          __FUNCTION__, tcp_task->exp_datasn, r2tsn);
+ 		return ISCSI_ERR_R2TSN;
+ 	}
+ 
+-	/* fill-in new R2T associated with the ctask */
++	/* fill-in new R2T associated with the task */
+ 	iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
+ 
+-	if (!ctask->sc || session->state != ISCSI_STATE_LOGGED_IN) {
++	if (!task->sc || session->state != ISCSI_STATE_LOGGED_IN) {
+ 		iscsi_conn_printk(KERN_INFO, conn,
+ 				  "dropping R2T itt %d in recovery.\n",
+-				  ctask->itt);
++				  task->itt);
+ 		return 0;
+ 	}
+ 
+-	rc = __kfifo_get(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*));
++	rc = __kfifo_get(tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*));
+ 	BUG_ON(!rc);
+ 
+ 	r2t->exp_statsn = rhdr->statsn;
+@@ -668,7 +668,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	if (r2t->data_length == 0) {
+ 		iscsi_conn_printk(KERN_ERR, conn,
+ 				  "invalid R2T with zero data len\n");
+-		__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
++		__kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
+ 			    sizeof(void*));
+ 		return ISCSI_ERR_DATALEN;
+ 	}
+@@ -679,12 +679,12 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 			    r2t->data_length, session->max_burst);
+ 
+ 	r2t->data_offset = be32_to_cpu(rhdr->data_offset);
+-	if (r2t->data_offset + r2t->data_length > scsi_out(ctask->sc)->length) {
++	if (r2t->data_offset + r2t->data_length > scsi_out(task->sc)->length) {
+ 		iscsi_conn_printk(KERN_ERR, conn,
+ 				  "invalid R2T with data len %u at offset %u "
+ 				  "and total length %d\n", r2t->data_length,
+-				  r2t->data_offset, scsi_out(ctask->sc)->length);
+-		__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
++				  r2t->data_offset, scsi_out(task->sc)->length);
++		__kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
+ 			    sizeof(void*));
+ 		return ISCSI_ERR_DATALEN;
+ 	}
+@@ -692,13 +692,13 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	r2t->ttt = rhdr->ttt; /* no flip */
+ 	r2t->solicit_datasn = 0;
+ 
+-	iscsi_solicit_data_init(conn, ctask, r2t);
++	iscsi_solicit_data_init(conn, task, r2t);
+ 
+-	tcp_ctask->exp_datasn = r2tsn + 1;
+-	__kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*));
++	tcp_task->exp_datasn = r2tsn + 1;
++	__kfifo_put(tcp_task->r2tqueue, (void*)&r2t, sizeof(void*));
+ 	conn->r2t_pdus_cnt++;
+ 
+-	iscsi_requeue_ctask(ctask);
++	iscsi_requeue_task(task);
+ 	return 0;
+ }
+ 
+@@ -743,7 +743,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 	int rc = 0, opcode, ahslen;
+ 	struct iscsi_session *session = conn->session;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+-	struct iscsi_cmd_task *ctask;
++	struct iscsi_task *task;
+ 
+ 	/* verify PDU length */
+ 	tcp_conn->in.datalen = ntoh24(hdr->dlength);
+@@ -770,21 +770,21 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 
+ 	switch(opcode) {
+ 	case ISCSI_OP_SCSI_DATA_IN:
+-		ctask = iscsi_itt_to_ctask(conn, hdr->itt);
+-		if (!ctask)
++		task = iscsi_itt_to_ctask(conn, hdr->itt);
++		if (!task)
+ 			return ISCSI_ERR_BAD_ITT;
+-		if (!ctask->sc)
++		if (!task->sc)
+ 			return ISCSI_ERR_NO_SCSI_CMD;
+ 
+ 		spin_lock(&conn->session->lock);
+-		rc = iscsi_data_rsp(conn, ctask);
++		rc = iscsi_data_rsp(conn, task);
+ 		spin_unlock(&conn->session->lock);
+ 		if (rc)
+ 			return rc;
+ 		if (tcp_conn->in.datalen) {
+-			struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++			struct iscsi_tcp_task *tcp_task = task->dd_data;
+ 			struct hash_desc *rx_hash = NULL;
+-			struct scsi_data_buffer *sdb = scsi_in(ctask->sc);
++			struct scsi_data_buffer *sdb = scsi_in(task->sc);
+ 
+ 			/*
+ 			 * Setup copy of Data-In into the Scsi_Cmnd
+@@ -799,12 +799,12 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 
+ 			debug_tcp("iscsi_tcp_begin_data_in(%p, offset=%d, "
+ 				  "datalen=%d)\n", tcp_conn,
+-				  tcp_ctask->data_offset,
++				  tcp_task->data_offset,
+ 				  tcp_conn->in.datalen);
+ 			return iscsi_segment_seek_sg(&tcp_conn->in.segment,
+ 						     sdb->table.sgl,
+ 						     sdb->table.nents,
+-						     tcp_ctask->data_offset,
++						     tcp_task->data_offset,
+ 						     tcp_conn->in.datalen,
+ 						     iscsi_tcp_process_data_in,
+ 						     rx_hash);
+@@ -818,17 +818,17 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 		rc = iscsi_complete_pdu(conn, hdr, NULL, 0);
+ 		break;
+ 	case ISCSI_OP_R2T:
+-		ctask = iscsi_itt_to_ctask(conn, hdr->itt);
+-		if (!ctask)
++		task = iscsi_itt_to_ctask(conn, hdr->itt);
++		if (!task)
+ 			return ISCSI_ERR_BAD_ITT;
+-		if (!ctask->sc)
++		if (!task->sc)
+ 			return ISCSI_ERR_NO_SCSI_CMD;
+ 
+ 		if (ahslen)
+ 			rc = ISCSI_ERR_AHSLEN;
+-		else if (ctask->sc->sc_data_direction == DMA_TO_DEVICE) {
++		else if (task->sc->sc_data_direction == DMA_TO_DEVICE) {
+ 			spin_lock(&session->lock);
+-			rc = iscsi_r2t_rsp(conn, ctask);
++			rc = iscsi_r2t_rsp(conn, task);
+ 			spin_unlock(&session->lock);
+ 		} else
+ 			rc = ISCSI_ERR_PROTO;
+@@ -1202,7 +1202,7 @@ iscsi_tcp_send_hdr_prep(struct iscsi_conn *conn, void *hdr, size_t hdrlen)
+ 
+ 	/* If header digest is enabled, compute the CRC and
+ 	 * place the digest into the same buffer. We make
+-	 * sure that both iscsi_tcp_cmd_task and mctask have
++	 * sure that both iscsi_tcp_task and mtask have
+ 	 * sufficient room.
+ 	 */
+ 	if (conn->hdrdgst_en) {
+@@ -1277,7 +1277,7 @@ iscsi_tcp_send_linear_data_prepare(struct iscsi_conn *conn, void *data,
+ /**
+  * iscsi_solicit_data_cont - initialize next Data-Out
+  * @conn: iscsi connection
+- * @ctask: scsi command ctask
++ * @task: scsi command task
+  * @r2t: R2T info
+  * @left: bytes left to transfer
+  *
+@@ -1288,7 +1288,7 @@ iscsi_tcp_send_linear_data_prepare(struct iscsi_conn *conn, void *data,
+  *	Called under connection lock.
+  **/
+ static int
+-iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
++iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_task *task,
+ 			struct iscsi_r2t_info *r2t)
+ {
+ 	struct iscsi_data *hdr;
+@@ -1305,8 +1305,8 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 	hdr->datasn = cpu_to_be32(r2t->solicit_datasn);
+ 	r2t->solicit_datasn++;
+ 	hdr->opcode = ISCSI_OP_SCSI_DATA_OUT;
+-	memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun));
+-	hdr->itt = ctask->hdr->itt;
++	memcpy(hdr->lun, task->hdr->lun, sizeof(hdr->lun));
++	hdr->itt = task->hdr->itt;
+ 	hdr->exp_statsn = r2t->exp_statsn;
+ 	new_offset = r2t->data_offset + r2t->sent;
+ 	hdr->offset = cpu_to_be32(new_offset);
+@@ -1326,73 +1326,73 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ /**
+  * iscsi_tcp_task - Initialize iSCSI SCSI_READ or SCSI_WRITE commands
+  * @conn: iscsi connection
+- * @ctask: scsi command ctask
++ * @task: scsi command task
+  * @sc: scsi command
+  **/
+ static int
+-iscsi_tcp_task_init(struct iscsi_cmd_task *ctask)
++iscsi_tcp_task_init(struct iscsi_task *task)
+ {
+-	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+-	struct iscsi_conn *conn = ctask->conn;
+-	struct scsi_cmnd *sc = ctask->sc;
++	struct iscsi_tcp_task *tcp_task = task->dd_data;
++	struct iscsi_conn *conn = task->conn;
++	struct scsi_cmnd *sc = task->sc;
+ 	int err;
+ 
+ 	if (!sc) {
+ 		/*
+-		 * mgmt ctasks do not have a scatterlist since they come
++		 * mgmt tasks do not have a scatterlist since they come
+ 		 * in from the iscsi interface.
+ 		 */
+-		debug_scsi("mctask deq [cid %d itt 0x%x]\n", conn->id,
+-			   ctask->itt);
++		debug_scsi("mtask deq [cid %d itt 0x%x]\n", conn->id,
++			   task->itt);
+ 
+ 		/* Prepare PDU, optionally w/ immediate data */
+-		iscsi_tcp_send_hdr_prep(conn, ctask->hdr, sizeof(*ctask->hdr));
++		iscsi_tcp_send_hdr_prep(conn, task->hdr, sizeof(*task->hdr));
+ 
+ 		/* If we have immediate data, attach a payload */
+-		if (ctask->data_count)
+-			iscsi_tcp_send_linear_data_prepare(conn, ctask->data,
+-							   ctask->data_count);
++		if (task->data_count)
++			iscsi_tcp_send_linear_data_prepare(conn, task->data,
++							   task->data_count);
+ 		return 0;
+ 	}
+ 
+-	BUG_ON(__kfifo_len(tcp_ctask->r2tqueue));
+-	tcp_ctask->sent = 0;
+-	tcp_ctask->exp_datasn = 0;
++	BUG_ON(__kfifo_len(tcp_task->r2tqueue));
++	tcp_task->sent = 0;
++	tcp_task->exp_datasn = 0;
+ 
+ 	/* Prepare PDU, optionally w/ immediate data */
+-	debug_scsi("ctask deq [cid %d itt 0x%x imm %d unsol %d]\n",
+-		    conn->id, ctask->itt, ctask->imm_count,
+-		    ctask->unsol_count);
+-	iscsi_tcp_send_hdr_prep(conn, ctask->hdr, ctask->hdr_len);
++	debug_scsi("task deq [cid %d itt 0x%x imm %d unsol %d]\n",
++		    conn->id, task->itt, task->imm_count,
++		    task->unsol_count);
++	iscsi_tcp_send_hdr_prep(conn, task->hdr, task->hdr_len);
+ 
+-	if (!ctask->imm_count)
++	if (!task->imm_count)
+ 		return 0;
+ 
+ 	/* If we have immediate data, attach a payload */
+ 	err = iscsi_tcp_send_data_prep(conn, scsi_out(sc)->table.sgl,
+ 				       scsi_out(sc)->table.nents,
+-				       0, ctask->imm_count);
++				       0, task->imm_count);
+ 	if (err)
+ 		return err;
+-	tcp_ctask->sent += ctask->imm_count;
+-	ctask->imm_count = 0;
++	tcp_task->sent += task->imm_count;
++	task->imm_count = 0;
+ 	return 0;
+ }
+ 
+ /*
+- * iscsi_tcp_task_xmit - xmit normal PDU ctask
+- * @ctask: iscsi command ctask
++ * iscsi_tcp_task_xmit - xmit normal PDU task
++ * @task: iscsi command task
+  *
+  * We're expected to return 0 when everything was transmitted succesfully,
+  * -EAGAIN if there's still data in the queue, or != 0 for any other kind
+  * of error.
+  */
+ static int
+-iscsi_tcp_task_xmit(struct iscsi_cmd_task *ctask)
++iscsi_tcp_task_xmit(struct iscsi_task *task)
+ {
+-	struct iscsi_conn *conn = ctask->conn;
+-	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+-	struct scsi_cmnd *sc = ctask->sc;
++	struct iscsi_conn *conn = task->conn;
++	struct iscsi_tcp_task *tcp_task = task->dd_data;
++	struct scsi_cmnd *sc = task->sc;
+ 	struct scsi_data_buffer *sdb;
+ 	int rc = 0;
+ 
+@@ -1404,8 +1404,8 @@ iscsi_tcp_task_xmit(struct iscsi_cmd_task *ctask)
+ 
+ 	/* mgmt command */
+ 	if (!sc) {
+-		if (ctask->hdr->itt == RESERVED_ITT)
+-			iscsi_put_ctask(ctask);
++		if (task->hdr->itt == RESERVED_ITT)
++			iscsi_put_task(task);
+ 		return 0;
+ 	}
+ 
+@@ -1414,27 +1414,27 @@ iscsi_tcp_task_xmit(struct iscsi_cmd_task *ctask)
+ 		return 0;
+ 
+ 	sdb = scsi_out(sc);
+-	if (ctask->unsol_count != 0) {
+-		struct iscsi_data *hdr = &tcp_ctask->unsol_dtask.hdr;
++	if (task->unsol_count != 0) {
++		struct iscsi_data *hdr = &tcp_task->unsol_dtask.hdr;
+ 
+ 		/* Prepare a header for the unsolicited PDU.
+ 		 * The amount of data we want to send will be
+-		 * in ctask->data_count.
++		 * in task->data_count.
+ 		 * FIXME: return the data count instead.
+ 		 */
+-		iscsi_prep_unsolicit_data_pdu(ctask, hdr);
++		iscsi_prep_unsolicit_data_pdu(task, hdr);
+ 
+ 		debug_tcp("unsol dout [itt 0x%x doff %d dlen %d]\n",
+-				ctask->itt, tcp_ctask->sent, ctask->data_count);
++				task->itt, tcp_task->sent, task->data_count);
+ 
+ 		iscsi_tcp_send_hdr_prep(conn, hdr, sizeof(*hdr));
+ 		rc = iscsi_tcp_send_data_prep(conn, sdb->table.sgl,
+-					      sdb->table.nents, tcp_ctask->sent,
+-					      ctask->data_count);
++					      sdb->table.nents, tcp_task->sent,
++					      task->data_count);
+ 		if (rc)
+ 			goto fail;
+-		tcp_ctask->sent += ctask->data_count;
+-		ctask->unsol_count -= ctask->data_count;
++		tcp_task->sent += task->data_count;
++		task->unsol_count -= task->data_count;
+ 		goto flush;
+ 	} else {
+ 		struct iscsi_session *session = conn->session;
+@@ -1443,22 +1443,22 @@ iscsi_tcp_task_xmit(struct iscsi_cmd_task *ctask)
+ 		/* All unsolicited PDUs sent. Check for solicited PDUs.
+ 		 */
+ 		spin_lock_bh(&session->lock);
+-		r2t = tcp_ctask->r2t;
++		r2t = tcp_task->r2t;
+ 		if (r2t != NULL) {
+ 			/* Continue with this R2T? */
+-			if (!iscsi_solicit_data_cont(conn, ctask, r2t)) {
++			if (!iscsi_solicit_data_cont(conn, task, r2t)) {
+ 				debug_scsi("  done with r2t %p\n", r2t);
+ 
+-				__kfifo_put(tcp_ctask->r2tpool.queue,
++				__kfifo_put(tcp_task->r2tpool.queue,
+ 					    (void*)&r2t, sizeof(void*));
+-				tcp_ctask->r2t = r2t = NULL;
++				tcp_task->r2t = r2t = NULL;
+ 			}
+ 		}
+ 
+ 		if (r2t == NULL) {
+-			__kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t,
++			__kfifo_get(tcp_task->r2tqueue, (void*)&tcp_task->r2t,
+ 				    sizeof(void*));
+-			r2t = tcp_ctask->r2t;
++			r2t = tcp_task->r2t;
+ 		}
+ 		spin_unlock_bh(&session->lock);
+ 
+@@ -1469,7 +1469,7 @@ iscsi_tcp_task_xmit(struct iscsi_cmd_task *ctask)
+ 		}
+ 
+ 		debug_scsi("sol dout %p [dsn %d itt 0x%x doff %d dlen %d]\n",
+-			r2t, r2t->solicit_datasn - 1, ctask->itt,
++			r2t, r2t->solicit_datasn - 1, task->itt,
+ 			r2t->data_offset + r2t->sent, r2t->data_count);
+ 
+ 		iscsi_tcp_send_hdr_prep(conn, &r2t->dtask.hdr,
+@@ -1481,7 +1481,7 @@ iscsi_tcp_task_xmit(struct iscsi_cmd_task *ctask)
+ 					      r2t->data_count);
+ 		if (rc)
+ 			goto fail;
+-		tcp_ctask->sent += r2t->data_count;
++		tcp_task->sent += r2t->data_count;
+ 		r2t->sent += r2t->data_count;
+ 		goto flush;
+ 	}
+@@ -1698,11 +1698,11 @@ iscsi_r2tpool_alloc(struct iscsi_session *session)
+ 	int cmd_i;
+ 
+ 	/*
+-	 * initialize per-ctask: R2T pool and xmit queue
++	 * initialize per-task: R2T pool and xmit queue
+ 	 */
+ 	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
+-	        struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
+-		struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++	        struct iscsi_task *task = session->cmds[cmd_i];
++		struct iscsi_tcp_task *tcp_task = task->dd_data;
+ 
+ 		/*
+ 		 * pre-allocated x4 as much r2ts to handle race when
+@@ -1711,16 +1711,16 @@ iscsi_r2tpool_alloc(struct iscsi_session *session)
+ 		 */
+ 
+ 		/* R2T pool */
+-		if (iscsi_pool_init(&tcp_ctask->r2tpool, session->max_r2t * 4, NULL,
++		if (iscsi_pool_init(&tcp_task->r2tpool, session->max_r2t * 4, NULL,
+ 				    sizeof(struct iscsi_r2t_info))) {
+ 			goto r2t_alloc_fail;
+ 		}
+ 
+ 		/* R2T xmit queue */
+-		tcp_ctask->r2tqueue = kfifo_alloc(
++		tcp_task->r2tqueue = kfifo_alloc(
+ 		      session->max_r2t * 4 * sizeof(void*), GFP_KERNEL, NULL);
+-		if (tcp_ctask->r2tqueue == ERR_PTR(-ENOMEM)) {
+-			iscsi_pool_free(&tcp_ctask->r2tpool);
++		if (tcp_task->r2tqueue == ERR_PTR(-ENOMEM)) {
++			iscsi_pool_free(&tcp_task->r2tpool);
+ 			goto r2t_alloc_fail;
+ 		}
+ 	}
+@@ -1729,11 +1729,11 @@ iscsi_r2tpool_alloc(struct iscsi_session *session)
+ 
+ r2t_alloc_fail:
+ 	for (i = 0; i < cmd_i; i++) {
+-		struct iscsi_cmd_task *ctask = session->cmds[i];
+-		struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++		struct iscsi_task *task = session->cmds[i];
++		struct iscsi_tcp_task *tcp_task = task->dd_data;
+ 
+-		kfifo_free(tcp_ctask->r2tqueue);
+-		iscsi_pool_free(&tcp_ctask->r2tpool);
++		kfifo_free(tcp_task->r2tqueue);
++		iscsi_pool_free(&tcp_task->r2tpool);
+ 	}
+ 	return -ENOMEM;
+ }
+@@ -1744,11 +1744,11 @@ iscsi_r2tpool_free(struct iscsi_session *session)
+ 	int i;
+ 
+ 	for (i = 0; i < session->cmds_max; i++) {
+-		struct iscsi_cmd_task *ctask = session->cmds[i];
+-		struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++		struct iscsi_task *task = session->cmds[i];
++		struct iscsi_tcp_task *tcp_task = task->dd_data;
+ 
+-		kfifo_free(tcp_ctask->r2tqueue);
+-		iscsi_pool_free(&tcp_ctask->r2tpool);
++		kfifo_free(tcp_task->r2tqueue);
++		iscsi_pool_free(&tcp_task->r2tpool);
+ 	}
+ }
+ 
+@@ -1867,7 +1867,7 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max,
+ 	*hostno = shost->host_no;
+ 
+ 	cls_session = iscsi_session_setup(&iscsi_tcp_transport, shost, cmds_max,
+-					  sizeof(struct iscsi_tcp_cmd_task),
++					  sizeof(struct iscsi_tcp_task),
+ 					  initial_cmdsn);
+ 	if (!cls_session)
+ 		goto remove_host;
+@@ -1875,11 +1875,11 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max,
+ 
+ 	shost->can_queue = session->scsi_cmds_max;
+ 	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
+-		struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
+-		struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++		struct iscsi_task *task = session->cmds[cmd_i];
++		struct iscsi_tcp_task *tcp_task = task->dd_data;
+ 
+-		ctask->hdr = &tcp_ctask->hdr.cmd_hdr;
+-		ctask->hdr_max = sizeof(tcp_ctask->hdr) - ISCSI_DIGEST_SIZE;
++		task->hdr = &tcp_task->hdr.cmd_hdr;
++		task->hdr_max = sizeof(tcp_task->hdr) - ISCSI_DIGEST_SIZE;
+ 	}
+ 
+ 	if (iscsi_r2tpool_alloc(session))
+diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
+index c9c8633c41a6..498d8ca39848 100644
+--- a/drivers/scsi/iscsi_tcp.h
++++ b/drivers/scsi/iscsi_tcp.h
+@@ -114,7 +114,7 @@ struct iscsi_r2t_info {
+ 	struct iscsi_data_task	dtask;		/* Data-Out header buf */
+ };
+ 
+-struct iscsi_tcp_cmd_task {
++struct iscsi_tcp_task {
+ 	struct iscsi_hdr_buff {
+ 		struct iscsi_cmd	cmd_hdr;
+ 		char			hdrextbuf[ISCSI_MAX_AHS_SIZE +

commit 9c19a7d0387124a508d2cdb38ebf8cd484631ad0
+Author: Mike Christie 
+Date:   Wed May 21 15:54:09 2008 -0500
+
+    [SCSI] libiscsi: rename iscsi_cmd_task to iscsi_task
+    
+    This is the second part of the iscsi task merging, and
+    all it does it rename iscsi_cmd_task to iscsi_task and
+    mtask/ctask to just task.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index ef92b1b0f16e..92ee6d94aaf9 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -88,61 +88,61 @@ iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_update_cmdsn);
+ 
+-void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *ctask,
++void iscsi_prep_unsolicit_data_pdu(struct iscsi_task *task,
+ 				   struct iscsi_data *hdr)
+ {
+-	struct iscsi_conn *conn = ctask->conn;
++	struct iscsi_conn *conn = task->conn;
+ 
+ 	memset(hdr, 0, sizeof(struct iscsi_data));
+ 	hdr->ttt = cpu_to_be32(ISCSI_RESERVED_TAG);
+-	hdr->datasn = cpu_to_be32(ctask->unsol_datasn);
+-	ctask->unsol_datasn++;
++	hdr->datasn = cpu_to_be32(task->unsol_datasn);
++	task->unsol_datasn++;
+ 	hdr->opcode = ISCSI_OP_SCSI_DATA_OUT;
+-	memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun));
++	memcpy(hdr->lun, task->hdr->lun, sizeof(hdr->lun));
+ 
+-	hdr->itt = ctask->hdr->itt;
++	hdr->itt = task->hdr->itt;
+ 	hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
+-	hdr->offset = cpu_to_be32(ctask->unsol_offset);
++	hdr->offset = cpu_to_be32(task->unsol_offset);
+ 
+-	if (ctask->unsol_count > conn->max_xmit_dlength) {
++	if (task->unsol_count > conn->max_xmit_dlength) {
+ 		hton24(hdr->dlength, conn->max_xmit_dlength);
+-		ctask->data_count = conn->max_xmit_dlength;
+-		ctask->unsol_offset += ctask->data_count;
++		task->data_count = conn->max_xmit_dlength;
++		task->unsol_offset += task->data_count;
+ 		hdr->flags = 0;
+ 	} else {
+-		hton24(hdr->dlength, ctask->unsol_count);
+-		ctask->data_count = ctask->unsol_count;
++		hton24(hdr->dlength, task->unsol_count);
++		task->data_count = task->unsol_count;
+ 		hdr->flags = ISCSI_FLAG_CMD_FINAL;
+ 	}
+ }
+ EXPORT_SYMBOL_GPL(iscsi_prep_unsolicit_data_pdu);
+ 
+-static int iscsi_add_hdr(struct iscsi_cmd_task *ctask, unsigned len)
++static int iscsi_add_hdr(struct iscsi_task *task, unsigned len)
+ {
+-	unsigned exp_len = ctask->hdr_len + len;
++	unsigned exp_len = task->hdr_len + len;
+ 
+-	if (exp_len > ctask->hdr_max) {
++	if (exp_len > task->hdr_max) {
+ 		WARN_ON(1);
+ 		return -EINVAL;
+ 	}
+ 
+ 	WARN_ON(len & (ISCSI_PAD_LEN - 1)); /* caller must pad the AHS */
+-	ctask->hdr_len = exp_len;
++	task->hdr_len = exp_len;
+ 	return 0;
+ }
+ 
+ /*
+  * make an extended cdb AHS
+  */
+-static int iscsi_prep_ecdb_ahs(struct iscsi_cmd_task *ctask)
++static int iscsi_prep_ecdb_ahs(struct iscsi_task *task)
+ {
+-	struct scsi_cmnd *cmd = ctask->sc;
++	struct scsi_cmnd *cmd = task->sc;
+ 	unsigned rlen, pad_len;
+ 	unsigned short ahslength;
+ 	struct iscsi_ecdb_ahdr *ecdb_ahdr;
+ 	int rc;
+ 
+-	ecdb_ahdr = iscsi_next_hdr(ctask);
++	ecdb_ahdr = iscsi_next_hdr(task);
+ 	rlen = cmd->cmd_len - ISCSI_CDB_SIZE;
+ 
+ 	BUG_ON(rlen > sizeof(ecdb_ahdr->ecdb));
+@@ -150,7 +150,7 @@ static int iscsi_prep_ecdb_ahs(struct iscsi_cmd_task *ctask)
+ 
+ 	pad_len = iscsi_padding(rlen);
+ 
+-	rc = iscsi_add_hdr(ctask, sizeof(ecdb_ahdr->ahslength) +
++	rc = iscsi_add_hdr(task, sizeof(ecdb_ahdr->ahslength) +
+ 	                   sizeof(ecdb_ahdr->ahstype) + ahslength + pad_len);
+ 	if (rc)
+ 		return rc;
+@@ -165,19 +165,19 @@ static int iscsi_prep_ecdb_ahs(struct iscsi_cmd_task *ctask)
+ 
+ 	debug_scsi("iscsi_prep_ecdb_ahs: varlen_cdb_len %d "
+ 		   "rlen %d pad_len %d ahs_length %d iscsi_headers_size %u\n",
+-		   cmd->cmd_len, rlen, pad_len, ahslength, ctask->hdr_len);
++		   cmd->cmd_len, rlen, pad_len, ahslength, task->hdr_len);
+ 
+ 	return 0;
+ }
+ 
+-static int iscsi_prep_bidi_ahs(struct iscsi_cmd_task *ctask)
++static int iscsi_prep_bidi_ahs(struct iscsi_task *task)
+ {
+-	struct scsi_cmnd *sc = ctask->sc;
++	struct scsi_cmnd *sc = task->sc;
+ 	struct iscsi_rlength_ahdr *rlen_ahdr;
+ 	int rc;
+ 
+-	rlen_ahdr = iscsi_next_hdr(ctask);
+-	rc = iscsi_add_hdr(ctask, sizeof(*rlen_ahdr));
++	rlen_ahdr = iscsi_next_hdr(task);
++	rc = iscsi_add_hdr(task, sizeof(*rlen_ahdr));
+ 	if (rc)
+ 		return rc;
+ 
+@@ -197,28 +197,28 @@ static int iscsi_prep_bidi_ahs(struct iscsi_cmd_task *ctask)
+ 
+ /**
+  * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu
+- * @ctask: iscsi task
++ * @task: iscsi task
+  *
+  * Prep basic iSCSI PDU fields for a scsi cmd pdu. The LLD should set
+  * fields like dlength or final based on how much data it sends
+  */
+-static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
++static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
+ {
+-	struct iscsi_conn *conn = ctask->conn;
++	struct iscsi_conn *conn = task->conn;
+ 	struct iscsi_session *session = conn->session;
+-	struct iscsi_cmd *hdr = ctask->hdr;
+-	struct scsi_cmnd *sc = ctask->sc;
++	struct iscsi_cmd *hdr = task->hdr;
++	struct scsi_cmnd *sc = task->sc;
+ 	unsigned hdrlength, cmd_len;
+ 	int rc;
+ 
+-	ctask->hdr_len = 0;
+-	rc = iscsi_add_hdr(ctask, sizeof(*hdr));
++	task->hdr_len = 0;
++	rc = iscsi_add_hdr(task, sizeof(*hdr));
+ 	if (rc)
+ 		return rc;
+ 	hdr->opcode = ISCSI_OP_SCSI_CMD;
+ 	hdr->flags = ISCSI_ATTR_SIMPLE;
+ 	int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
+-	hdr->itt = build_itt(ctask->itt, session->age);
++	hdr->itt = build_itt(task->itt, session->age);
+ 	hdr->cmdsn = cpu_to_be32(session->cmdsn);
+ 	session->cmdsn++;
+ 	hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
+@@ -226,17 +226,17 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ 	if (cmd_len < ISCSI_CDB_SIZE)
+ 		memset(&hdr->cdb[cmd_len], 0, ISCSI_CDB_SIZE - cmd_len);
+ 	else if (cmd_len > ISCSI_CDB_SIZE) {
+-		rc = iscsi_prep_ecdb_ahs(ctask);
++		rc = iscsi_prep_ecdb_ahs(task);
+ 		if (rc)
+ 			return rc;
+ 		cmd_len = ISCSI_CDB_SIZE;
+ 	}
+ 	memcpy(hdr->cdb, sc->cmnd, cmd_len);
+ 
+-	ctask->imm_count = 0;
++	task->imm_count = 0;
+ 	if (scsi_bidi_cmnd(sc)) {
+ 		hdr->flags |= ISCSI_FLAG_CMD_READ;
+-		rc = iscsi_prep_bidi_ahs(ctask);
++		rc = iscsi_prep_bidi_ahs(task);
+ 		if (rc)
+ 			return rc;
+ 	}
+@@ -258,28 +258,28 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ 		 *
+ 		 *      pad_count       bytes to be sent as zero-padding
+ 		 */
+-		ctask->unsol_count = 0;
+-		ctask->unsol_offset = 0;
+-		ctask->unsol_datasn = 0;
++		task->unsol_count = 0;
++		task->unsol_offset = 0;
++		task->unsol_datasn = 0;
+ 
+ 		if (session->imm_data_en) {
+ 			if (out_len >= session->first_burst)
+-				ctask->imm_count = min(session->first_burst,
++				task->imm_count = min(session->first_burst,
+ 							conn->max_xmit_dlength);
+ 			else
+-				ctask->imm_count = min(out_len,
++				task->imm_count = min(out_len,
+ 							conn->max_xmit_dlength);
+-			hton24(hdr->dlength, ctask->imm_count);
++			hton24(hdr->dlength, task->imm_count);
+ 		} else
+ 			zero_data(hdr->dlength);
+ 
+ 		if (!session->initial_r2t_en) {
+-			ctask->unsol_count = min(session->first_burst, out_len)
+-							     - ctask->imm_count;
+-			ctask->unsol_offset = ctask->imm_count;
++			task->unsol_count = min(session->first_burst, out_len)
++							     - task->imm_count;
++			task->unsol_offset = task->imm_count;
+ 		}
+ 
+-		if (!ctask->unsol_count)
++		if (!task->unsol_count)
+ 			/* No unsolicit Data-Out's */
+ 			hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+ 	} else {
+@@ -292,7 +292,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ 	}
+ 
+ 	/* calculate size of additional header segments (AHSs) */
+-	hdrlength = ctask->hdr_len - sizeof(*hdr);
++	hdrlength = task->hdr_len - sizeof(*hdr);
+ 
+ 	WARN_ON(hdrlength & (ISCSI_PAD_LEN-1));
+ 	hdrlength /= ISCSI_PAD_LEN;
+@@ -301,17 +301,17 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ 	hdr->hlength = hdrlength & 0xFF;
+ 
+ 	if (conn->session->tt->init_task &&
+-	    conn->session->tt->init_task(ctask))
++	    conn->session->tt->init_task(task))
+ 		return -EIO;
+ 
+-	ctask->state = ISCSI_TASK_RUNNING;
+-	list_move_tail(&ctask->running, &conn->run_list);
++	task->state = ISCSI_TASK_RUNNING;
++	list_move_tail(&task->running, &conn->run_list);
+ 
+ 	conn->scsicmd_pdus_cnt++;
+ 	debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x len %d "
+ 		   "bidi_len %d cmdsn %d win %d]\n", scsi_bidi_cmnd(sc) ?
+ 		   "bidirectional" : sc->sc_data_direction == DMA_TO_DEVICE ?
+-		   "write" : "read", conn->id, sc, sc->cmnd[0], ctask->itt,
++		   "write" : "read", conn->id, sc, sc->cmnd[0], task->itt,
+ 		   scsi_bufflen(sc),
+ 		   scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0,
+ 		   session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
+@@ -320,37 +320,37 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ 
+ /**
+  * iscsi_complete_command - finish a task
+- * @ctask: iscsi cmd task
++ * @task: iscsi cmd task
+  *
+  * Must be called with session lock.
+  * This function returns the scsi command to scsi-ml or cleans
+  * up mgmt tasks then returns the task to the pool.
+  */
+-static void iscsi_complete_command(struct iscsi_cmd_task *ctask)
++static void iscsi_complete_command(struct iscsi_task *task)
+ {
+-	struct iscsi_conn *conn = ctask->conn;
++	struct iscsi_conn *conn = task->conn;
+ 	struct iscsi_session *session = conn->session;
+-	struct scsi_cmnd *sc = ctask->sc;
++	struct scsi_cmnd *sc = task->sc;
+ 
+-	list_del_init(&ctask->running);
+-	ctask->state = ISCSI_TASK_COMPLETED;
+-	ctask->sc = NULL;
++	list_del_init(&task->running);
++	task->state = ISCSI_TASK_COMPLETED;
++	task->sc = NULL;
+ 
+-	if (conn->ctask == ctask)
+-		conn->ctask = NULL;
++	if (conn->task == task)
++		conn->task = NULL;
+ 	/*
+-	 * login ctask is preallocated so do not free
++	 * login task is preallocated so do not free
+ 	 */
+-	if (conn->login_ctask == ctask)
++	if (conn->login_task == task)
+ 		return;
+ 
+-	__kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*));
++	__kfifo_put(session->cmdpool.queue, (void*)&task, sizeof(void*));
+ 
+-	if (conn->ping_ctask == ctask)
+-		conn->ping_ctask = NULL;
++	if (conn->ping_task == task)
++		conn->ping_task = NULL;
+ 
+ 	if (sc) {
+-		ctask->sc = NULL;
++		task->sc = NULL;
+ 		/* SCSI eh reuses commands to verify us */
+ 		sc->SCp.ptr = NULL;
+ 		/*
+@@ -362,47 +362,47 @@ static void iscsi_complete_command(struct iscsi_cmd_task *ctask)
+ 	}
+ }
+ 
+-static void __iscsi_get_ctask(struct iscsi_cmd_task *ctask)
++static void __iscsi_get_task(struct iscsi_task *task)
+ {
+-	atomic_inc(&ctask->refcount);
++	atomic_inc(&task->refcount);
+ }
+ 
+-static void __iscsi_put_ctask(struct iscsi_cmd_task *ctask)
++static void __iscsi_put_task(struct iscsi_task *task)
+ {
+-	if (atomic_dec_and_test(&ctask->refcount))
+-		iscsi_complete_command(ctask);
++	if (atomic_dec_and_test(&task->refcount))
++		iscsi_complete_command(task);
+ }
+ 
+-void iscsi_put_ctask(struct iscsi_cmd_task *ctask)
++void iscsi_put_task(struct iscsi_task *task)
+ {
+-	struct iscsi_session *session = ctask->conn->session;
++	struct iscsi_session *session = task->conn->session;
+ 
+ 	spin_lock_bh(&session->lock);
+-	__iscsi_put_ctask(ctask);
++	__iscsi_put_task(task);
+ 	spin_unlock_bh(&session->lock);
+ }
+-EXPORT_SYMBOL_GPL(iscsi_put_ctask);
++EXPORT_SYMBOL_GPL(iscsi_put_task);
+ 
+ /*
+  * session lock must be held
+  */
+-static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
++static void fail_command(struct iscsi_conn *conn, struct iscsi_task *task,
+ 			 int err)
+ {
+ 	struct scsi_cmnd *sc;
+ 
+-	sc = ctask->sc;
++	sc = task->sc;
+ 	if (!sc)
+ 		return;
+ 
+-	if (ctask->state == ISCSI_TASK_PENDING)
++	if (task->state == ISCSI_TASK_PENDING)
+ 		/*
+ 		 * cmd never made it to the xmit thread, so we should not count
+ 		 * the cmd in the sequencing
+ 		 */
+ 		conn->session->queued_cmdsn--;
+ 	else
+-		conn->session->tt->cleanup_task(conn, ctask);
++		conn->session->tt->cleanup_task(conn, task);
+ 
+ 	sc->result = err;
+ 
+@@ -413,17 +413,17 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 		scsi_in(sc)->resid = scsi_in(sc)->length;
+ 	}
+ 
+-	if (conn->ctask == ctask)
+-		conn->ctask = NULL;
++	if (conn->task == task)
++		conn->task = NULL;
+ 	/* release ref from queuecommand */
+-	__iscsi_put_ctask(ctask);
++	__iscsi_put_task(task);
+ }
+ 
+ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn,
+-				struct iscsi_cmd_task *ctask)
++				struct iscsi_task *task)
+ {
+ 	struct iscsi_session *session = conn->session;
+-	struct iscsi_hdr *hdr = (struct iscsi_hdr *)ctask->hdr;
++	struct iscsi_hdr *hdr = (struct iscsi_hdr *)task->hdr;
+ 	struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr;
+ 
+ 	if (conn->session->state == ISCSI_STATE_LOGGING_OUT)
+@@ -437,7 +437,7 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn,
+ 	 */
+ 	nop->cmdsn = cpu_to_be32(session->cmdsn);
+ 	if (hdr->itt != RESERVED_ITT) {
+-		hdr->itt = build_itt(ctask->itt, session->age);
++		hdr->itt = build_itt(task->itt, session->age);
+ 		/*
+ 		 * TODO: We always use immediate, so we never hit this.
+ 		 * If we start to send tmfs or nops as non-immediate then
+@@ -451,24 +451,24 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn,
+ 	}
+ 
+ 	if (session->tt->init_task)
+-		session->tt->init_task(ctask);
++		session->tt->init_task(task);
+ 
+ 	if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT)
+ 		session->state = ISCSI_STATE_LOGGING_OUT;
+ 
+-	list_move_tail(&ctask->running, &conn->mgmt_run_list);
++	list_move_tail(&task->running, &conn->mgmt_run_list);
+ 	debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n",
+ 		   hdr->opcode & ISCSI_OPCODE_MASK, hdr->itt,
+-		   ctask->data_count);
++		   task->data_count);
+ 	return 0;
+ }
+ 
+-static struct iscsi_cmd_task *
++static struct iscsi_task *
+ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		      char *data, uint32_t data_size)
+ {
+ 	struct iscsi_session *session = conn->session;
+-	struct iscsi_cmd_task *ctask;
++	struct iscsi_task *task;
+ 
+ 	if (session->state == ISCSI_STATE_TERMINATE)
+ 		return NULL;
+@@ -481,18 +481,18 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		 * Same task can be used. Same ITT must be used.
+ 		 * Note that login_task is preallocated at conn_create().
+ 		 */
+-		ctask = conn->login_ctask;
++		task = conn->login_task;
+ 	else {
+ 		BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
+ 		BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
+ 
+ 		if (!__kfifo_get(session->cmdpool.queue,
+-				 (void*)&ctask, sizeof(void*)))
++				 (void*)&task, sizeof(void*)))
+ 			return NULL;
+ 
+ 		if ((hdr->opcode == (ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE)) &&
+ 		     hdr->ttt == RESERVED_ITT) {
+-			conn->ping_ctask = ctask;
++			conn->ping_task = task;
+ 			conn->last_ping = jiffies;
+ 		}
+ 	}
+@@ -501,33 +501,33 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	 * released by the lld when it has transmitted the task for
+ 	 * pdus we do not expect a response for.
+ 	 */
+-	atomic_set(&ctask->refcount, 1);
+-	ctask->conn = conn;
+-	ctask->sc = NULL;
++	atomic_set(&task->refcount, 1);
++	task->conn = conn;
++	task->sc = NULL;
+ 
+ 	if (data_size) {
+-		memcpy(ctask->data, data, data_size);
+-		ctask->data_count = data_size;
++		memcpy(task->data, data, data_size);
++		task->data_count = data_size;
+ 	} else
+-		ctask->data_count = 0;
++		task->data_count = 0;
+ 
+-	memcpy(ctask->hdr, hdr, sizeof(struct iscsi_hdr));
+-	INIT_LIST_HEAD(&ctask->running);
+-	list_add_tail(&ctask->running, &conn->mgmtqueue);
++	memcpy(task->hdr, hdr, sizeof(struct iscsi_hdr));
++	INIT_LIST_HEAD(&task->running);
++	list_add_tail(&task->running, &conn->mgmtqueue);
+ 
+ 	if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) {
+-		if (iscsi_prep_mgmt_task(conn, ctask)) {
+-			__iscsi_put_ctask(ctask);
++		if (iscsi_prep_mgmt_task(conn, task)) {
++			__iscsi_put_task(task);
+ 			return NULL;
+ 		}
+ 
+-		if (session->tt->xmit_task(ctask))
+-			ctask = NULL;
++		if (session->tt->xmit_task(task))
++			task = NULL;
+ 
+ 	} else
+ 		scsi_queue_work(conn->session->host, &conn->xmitwork);
+ 
+-	return ctask;
++	return task;
+ }
+ 
+ int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
+@@ -549,20 +549,20 @@ EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu);
+  * iscsi_cmd_rsp - SCSI Command Response processing
+  * @conn: iscsi connection
+  * @hdr: iscsi header
+- * @ctask: scsi command task
++ * @task: scsi command task
+  * @data: cmd data buffer
+  * @datalen: len of buffer
+  *
+  * iscsi_cmd_rsp sets up the scsi_cmnd fields based on the PDU and
+- * then completes the command and ctask.
++ * then completes the command and task.
+  **/
+ static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+-			       struct iscsi_cmd_task *ctask, char *data,
++			       struct iscsi_task *task, char *data,
+ 			       int datalen)
+ {
+ 	struct iscsi_cmd_rsp *rhdr = (struct iscsi_cmd_rsp *)hdr;
+ 	struct iscsi_session *session = conn->session;
+-	struct scsi_cmnd *sc = ctask->sc;
++	struct scsi_cmnd *sc = task->sc;
+ 
+ 	iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
+ 	conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
+@@ -622,10 +622,10 @@ static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	}
+ out:
+ 	debug_scsi("done [sc %lx res %d itt 0x%x]\n",
+-		   (long)sc, sc->result, ctask->itt);
++		   (long)sc, sc->result, task->itt);
+ 	conn->scsirsp_pdus_cnt++;
+ 
+-	__iscsi_put_ctask(ctask);
++	__iscsi_put_task(task);
+ }
+ 
+ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+@@ -650,9 +650,9 @@ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
+ {
+         struct iscsi_nopout hdr;
+-	struct iscsi_cmd_task *ctask;
++	struct iscsi_task *task;
+ 
+-	if (!rhdr && conn->ping_ctask)
++	if (!rhdr && conn->ping_task)
+ 		return;
+ 
+ 	memset(&hdr, 0, sizeof(struct iscsi_nopout));
+@@ -666,8 +666,8 @@ static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
+ 	} else
+ 		hdr.ttt = RESERVED_ITT;
+ 
+-	ctask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0);
+-	if (!ctask)
++	task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0);
++	if (!task)
+ 		iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n");
+ }
+ 
+@@ -712,7 +712,7 @@ static int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ {
+ 	struct iscsi_session *session = conn->session;
+ 	int opcode = hdr->opcode & ISCSI_OPCODE_MASK, rc = 0;
+-	struct iscsi_cmd_task *ctask;
++	struct iscsi_task *task;
+ 	uint32_t itt;
+ 
+ 	conn->last_recv = jiffies;
+@@ -758,27 +758,27 @@ static int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		goto out;
+ 	}
+ 
+-	ctask = session->cmds[itt];
++	task = session->cmds[itt];
+ 	switch(opcode) {
+ 	case ISCSI_OP_SCSI_CMD_RSP:
+-		if (!ctask->sc) {
++		if (!task->sc) {
+ 			rc = ISCSI_ERR_NO_SCSI_CMD;
+ 			break;
+ 		}
+-		BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
+-		iscsi_scsi_cmd_rsp(conn, hdr, ctask, data, datalen);
++		BUG_ON((void*)task != task->sc->SCp.ptr);
++		iscsi_scsi_cmd_rsp(conn, hdr, task, data, datalen);
+ 		break;
+ 	case ISCSI_OP_SCSI_DATA_IN:
+-		if (!ctask->sc) {
++		if (!task->sc) {
+ 			rc = ISCSI_ERR_NO_SCSI_CMD;
+ 			break;
+ 		}
+-		BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
++		BUG_ON((void*)task != task->sc->SCp.ptr);
+ 		if (hdr->flags & ISCSI_FLAG_DATA_STATUS) {
+ 			conn->scsirsp_pdus_cnt++;
+ 			iscsi_update_cmdsn(session,
+ 					   (struct iscsi_nopin*) hdr);
+-			__iscsi_put_ctask(ctask);
++			__iscsi_put_task(task);
+ 		}
+ 		break;
+ 	case ISCSI_OP_R2T:
+@@ -808,7 +808,7 @@ static int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		}
+ 
+ 		iscsi_tmf_rsp(conn, hdr);
+-		__iscsi_put_ctask(ctask);
++		__iscsi_put_task(task);
+ 		break;
+ 	case ISCSI_OP_NOOP_IN:
+ 		iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
+@@ -818,13 +818,15 @@ static int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		}
+ 		conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
+ 
+-		if (conn->ping_ctask != ctask)
++		if (conn->ping_task != task)
+ 			/*
+ 			 * If this is not in response to one of our
+ 			 * nops then it must be from userspace.
+ 			 */
+ 			goto recv_pdu;
+-		__iscsi_put_ctask(ctask);
++
++		mod_timer(&conn->transport_timer, jiffies + conn->recv_timeout);
++		__iscsi_put_task(task);
+ 		break;
+ 	default:
+ 		rc = ISCSI_ERR_BAD_OPCODE;
+@@ -836,7 +838,7 @@ static int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ recv_pdu:
+ 	if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen))
+ 		rc = ISCSI_ERR_CONN_FAILED;
+-	__iscsi_put_ctask(ctask);
++	__iscsi_put_task(task);
+ 	return rc;
+ }
+ 
+@@ -855,7 +857,7 @@ EXPORT_SYMBOL_GPL(iscsi_complete_pdu);
+ int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt)
+ {
+ 	struct iscsi_session *session = conn->session;
+-	struct iscsi_cmd_task *ctask;
++	struct iscsi_task *task;
+ 	uint32_t i;
+ 
+ 	if (itt == RESERVED_ITT)
+@@ -878,11 +880,11 @@ int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt)
+ 		return ISCSI_ERR_BAD_ITT;
+ 	}
+ 
+-	ctask = session->cmds[i];
+-	if (ctask->sc && ctask->sc->SCp.phase != session->age) {
++	task = session->cmds[i];
++	if (task->sc && task->sc->SCp.phase != session->age) {
+ 		iscsi_conn_printk(KERN_ERR, conn,
+-				  "iscsi: ctask's session age %d, "
+-				  "expected %d\n", ctask->sc->SCp.phase,
++				  "iscsi: task's session age %d, "
++				  "expected %d\n", task->sc->SCp.phase,
+ 				  session->age);
+ 		return ISCSI_ERR_SESSION_FAILED;
+ 	}
+@@ -890,11 +892,11 @@ int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_verify_itt);
+ 
+-struct iscsi_cmd_task *
++struct iscsi_task *
+ iscsi_itt_to_ctask(struct iscsi_conn *conn, itt_t itt)
+ {
+ 	struct iscsi_session *session = conn->session;
+-	struct iscsi_cmd_task *ctask;
++	struct iscsi_task *task;
+ 	uint32_t i;
+ 
+ 	if (iscsi_verify_itt(conn, itt))
+@@ -907,14 +909,14 @@ iscsi_itt_to_ctask(struct iscsi_conn *conn, itt_t itt)
+ 	if (i >= session->cmds_max)
+ 		return NULL;
+ 
+-	ctask = session->cmds[i];
+-	if (!ctask->sc)
++	task = session->cmds[i];
++	if (!task->sc)
+ 		return NULL;
+ 
+-	if (ctask->sc->SCp.phase != session->age)
++	if (task->sc->SCp.phase != session->age)
+ 		return NULL;
+ 
+-	return ctask;
++	return task;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_itt_to_ctask);
+ 
+@@ -955,38 +957,38 @@ static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn)
+ 	return 0;
+ }
+ 
+-static int iscsi_xmit_ctask(struct iscsi_conn *conn)
++static int iscsi_xmit_task(struct iscsi_conn *conn)
+ {
+-	struct iscsi_cmd_task *ctask = conn->ctask;
++	struct iscsi_task *task = conn->task;
+ 	int rc;
+ 
+-	__iscsi_get_ctask(ctask);
++	__iscsi_get_task(task);
+ 	spin_unlock_bh(&conn->session->lock);
+-	rc = conn->session->tt->xmit_task(ctask);
++	rc = conn->session->tt->xmit_task(task);
+ 	spin_lock_bh(&conn->session->lock);
+-	__iscsi_put_ctask(ctask);
++	__iscsi_put_task(task);
+ 	if (!rc)
+-		/* done with this ctask */
+-		conn->ctask = NULL;
++		/* done with this task */
++		conn->task = NULL;
+ 	return rc;
+ }
+ 
+ /**
+- * iscsi_requeue_ctask - requeue ctask to run from session workqueue
+- * @ctask: ctask to requeue
++ * iscsi_requeue_task - requeue task to run from session workqueue
++ * @task: task to requeue
+  *
+- * LLDs that need to run a ctask from the session workqueue should call
++ * LLDs that need to run a task from the session workqueue should call
+  * this. The session lock must be held. This should only be called
+  * by software drivers.
+  */
+-void iscsi_requeue_ctask(struct iscsi_cmd_task *ctask)
++void iscsi_requeue_task(struct iscsi_task *task)
+ {
+-	struct iscsi_conn *conn = ctask->conn;
++	struct iscsi_conn *conn = task->conn;
+ 
+-	list_move_tail(&ctask->running, &conn->requeue);
++	list_move_tail(&task->running, &conn->requeue);
+ 	scsi_queue_work(conn->session->host, &conn->xmitwork);
+ }
+-EXPORT_SYMBOL_GPL(iscsi_requeue_ctask);
++EXPORT_SYMBOL_GPL(iscsi_requeue_task);
+ 
+ /**
+  * iscsi_data_xmit - xmit any command into the scheduled connection
+@@ -1008,8 +1010,8 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 		return -ENODATA;
+ 	}
+ 
+-	if (conn->ctask) {
+-		rc = iscsi_xmit_ctask(conn);
++	if (conn->task) {
++		rc = iscsi_xmit_task(conn);
+ 	        if (rc)
+ 		        goto again;
+ 	}
+@@ -1021,14 +1023,14 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 	 */
+ check_mgmt:
+ 	while (!list_empty(&conn->mgmtqueue)) {
+-		conn->ctask = list_entry(conn->mgmtqueue.next,
+-					 struct iscsi_cmd_task, running);
+-		if (iscsi_prep_mgmt_task(conn, conn->ctask)) {
+-			__iscsi_put_ctask(conn->ctask);
+-			conn->ctask = NULL;
++		conn->task = list_entry(conn->mgmtqueue.next,
++					 struct iscsi_task, running);
++		if (iscsi_prep_mgmt_task(conn, conn->task)) {
++			__iscsi_put_task(conn->task);
++			conn->task = NULL;
+ 			continue;
+ 		}
+-		rc = iscsi_xmit_ctask(conn);
++		rc = iscsi_xmit_task(conn);
+ 		if (rc)
+ 			goto again;
+ 	}
+@@ -1038,21 +1040,21 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 		if (conn->tmf_state == TMF_QUEUED)
+ 			break;
+ 
+-		conn->ctask = list_entry(conn->xmitqueue.next,
+-					 struct iscsi_cmd_task, running);
++		conn->task = list_entry(conn->xmitqueue.next,
++					 struct iscsi_task, running);
+ 		if (conn->session->state == ISCSI_STATE_LOGGING_OUT) {
+-			fail_command(conn, conn->ctask, DID_IMM_RETRY << 16);
++			fail_command(conn, conn->task, DID_IMM_RETRY << 16);
+ 			continue;
+ 		}
+-		if (iscsi_prep_scsi_cmd_pdu(conn->ctask)) {
+-			fail_command(conn, conn->ctask, DID_ABORT << 16);
++		if (iscsi_prep_scsi_cmd_pdu(conn->task)) {
++			fail_command(conn, conn->task, DID_ABORT << 16);
+ 			continue;
+ 		}
+-		rc = iscsi_xmit_ctask(conn);
++		rc = iscsi_xmit_task(conn);
+ 		if (rc)
+ 			goto again;
+ 		/*
+-		 * we could continuously get new ctask requests so
++		 * we could continuously get new task requests so
+ 		 * we need to check the mgmt queue for nops that need to
+ 		 * be sent to aviod starvation
+ 		 */
+@@ -1070,11 +1072,11 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 		if (conn->session->state == ISCSI_STATE_LOGGING_OUT)
+ 			break;
+ 
+-		conn->ctask = list_entry(conn->requeue.next,
+-					 struct iscsi_cmd_task, running);
+-		conn->ctask->state = ISCSI_TASK_RUNNING;
++		conn->task = list_entry(conn->requeue.next,
++					 struct iscsi_task, running);
++		conn->task->state = ISCSI_TASK_RUNNING;
+ 		list_move_tail(conn->requeue.next, &conn->run_list);
+-		rc = iscsi_xmit_ctask(conn);
++		rc = iscsi_xmit_task(conn);
+ 		if (rc)
+ 			goto again;
+ 		if (!list_empty(&conn->mgmtqueue))
+@@ -1123,7 +1125,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 	int reason = 0;
+ 	struct iscsi_session *session;
+ 	struct iscsi_conn *conn;
+-	struct iscsi_cmd_task *ctask = NULL;
++	struct iscsi_task *task = NULL;
+ 
+ 	sc->scsi_done = done;
+ 	sc->result = 0;
+@@ -1191,31 +1193,31 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 		goto reject;
+ 	}
+ 
+-	if (!__kfifo_get(session->cmdpool.queue, (void*)&ctask,
++	if (!__kfifo_get(session->cmdpool.queue, (void*)&task,
+ 			 sizeof(void*))) {
+ 		reason = FAILURE_OOM;
+ 		goto reject;
+ 	}
+ 	sc->SCp.phase = session->age;
+-	sc->SCp.ptr = (char *)ctask;
++	sc->SCp.ptr = (char *)task;
+ 
+-	atomic_set(&ctask->refcount, 1);
+-	ctask->state = ISCSI_TASK_PENDING;
+-	ctask->conn = conn;
+-	ctask->sc = sc;
+-	INIT_LIST_HEAD(&ctask->running);
+-	list_add_tail(&ctask->running, &conn->xmitqueue);
++	atomic_set(&task->refcount, 1);
++	task->state = ISCSI_TASK_PENDING;
++	task->conn = conn;
++	task->sc = sc;
++	INIT_LIST_HEAD(&task->running);
++	list_add_tail(&task->running, &conn->xmitqueue);
+ 
+ 	if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) {
+-		if (iscsi_prep_scsi_cmd_pdu(ctask)) {
++		if (iscsi_prep_scsi_cmd_pdu(task)) {
+ 			sc->result = DID_ABORT << 16;
+ 			sc->scsi_done = NULL;
+-			iscsi_complete_command(ctask);
++			iscsi_complete_command(task);
+ 			goto fault;
+ 		}
+-		if (session->tt->xmit_task(ctask)) {
++		if (session->tt->xmit_task(task)) {
+ 			sc->scsi_done = NULL;
+-			iscsi_complete_command(ctask);
++			iscsi_complete_command(task);
+ 			reason = FAILURE_SESSION_NOT_READY;
+ 			goto reject;
+ 		}
+@@ -1336,16 +1338,16 @@ static void iscsi_tmf_timedout(unsigned long data)
+ 	spin_unlock(&session->lock);
+ }
+ 
+-static int iscsi_exec_ctask_mgmt_fn(struct iscsi_conn *conn,
++static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn,
+ 				   struct iscsi_tm *hdr, int age,
+ 				   int timeout)
+ {
+ 	struct iscsi_session *session = conn->session;
+-	struct iscsi_cmd_task *ctask;
++	struct iscsi_task *task;
+ 
+-	ctask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr,
++	task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr,
+ 				      NULL, 0);
+-	if (!ctask) {
++	if (!task) {
+ 		spin_unlock_bh(&session->lock);
+ 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ 		spin_lock_bh(&session->lock);
+@@ -1379,7 +1381,7 @@ static int iscsi_exec_ctask_mgmt_fn(struct iscsi_conn *conn,
+ 
+ 	mutex_lock(&session->eh_mutex);
+ 	spin_lock_bh(&session->lock);
+-	/* if the session drops it will clean up the ctask */
++	/* if the session drops it will clean up the task */
+ 	if (age != session->age ||
+ 	    session->state != ISCSI_STATE_LOGGED_IN)
+ 		return -ENOTCONN;
+@@ -1393,34 +1395,34 @@ static int iscsi_exec_ctask_mgmt_fn(struct iscsi_conn *conn,
+ static void fail_all_commands(struct iscsi_conn *conn, unsigned lun,
+ 			      int error)
+ {
+-	struct iscsi_cmd_task *ctask, *tmp;
++	struct iscsi_task *task, *tmp;
+ 
+-	if (conn->ctask && (conn->ctask->sc->device->lun == lun || lun == -1))
+-		conn->ctask = NULL;
++	if (conn->task && (conn->task->sc->device->lun == lun || lun == -1))
++		conn->task = NULL;
+ 
+ 	/* flush pending */
+-	list_for_each_entry_safe(ctask, tmp, &conn->xmitqueue, running) {
+-		if (lun == ctask->sc->device->lun || lun == -1) {
++	list_for_each_entry_safe(task, tmp, &conn->xmitqueue, running) {
++		if (lun == task->sc->device->lun || lun == -1) {
+ 			debug_scsi("failing pending sc %p itt 0x%x\n",
+-				   ctask->sc, ctask->itt);
+-			fail_command(conn, ctask, error << 16);
++				   task->sc, task->itt);
++			fail_command(conn, task, error << 16);
+ 		}
+ 	}
+ 
+-	list_for_each_entry_safe(ctask, tmp, &conn->requeue, running) {
+-		if (lun == ctask->sc->device->lun || lun == -1) {
++	list_for_each_entry_safe(task, tmp, &conn->requeue, running) {
++		if (lun == task->sc->device->lun || lun == -1) {
+ 			debug_scsi("failing requeued sc %p itt 0x%x\n",
+-				   ctask->sc, ctask->itt);
+-			fail_command(conn, ctask, error << 16);
++				   task->sc, task->itt);
++			fail_command(conn, task, error << 16);
+ 		}
+ 	}
+ 
+ 	/* fail all other running */
+-	list_for_each_entry_safe(ctask, tmp, &conn->run_list, running) {
+-		if (lun == ctask->sc->device->lun || lun == -1) {
++	list_for_each_entry_safe(task, tmp, &conn->run_list, running) {
++		if (lun == task->sc->device->lun || lun == -1) {
+ 			debug_scsi("failing in progress sc %p itt 0x%x\n",
+-				   ctask->sc, ctask->itt);
+-			fail_command(conn, ctask, DID_BUS_BUSY << 16);
++				   task->sc, task->itt);
++			fail_command(conn, task, DID_BUS_BUSY << 16);
+ 		}
+ 	}
+ }
+@@ -1486,7 +1488,7 @@ static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
+ 			   jiffies))
+ 		rc = EH_RESET_TIMER;
+ 	/* if in the middle of checking the transport then give us more time */
+-	if (conn->ping_ctask)
++	if (conn->ping_task)
+ 		rc = EH_RESET_TIMER;
+ done:
+ 	spin_unlock(&session->lock);
+@@ -1510,7 +1512,7 @@ static void iscsi_check_transport_timeouts(unsigned long data)
+ 
+ 	recv_timeout *= HZ;
+ 	last_recv = conn->last_recv;
+-	if (conn->ping_ctask &&
++	if (conn->ping_task &&
+ 	    time_before_eq(conn->last_ping + (conn->ping_timeout * HZ),
+ 			   jiffies)) {
+ 		iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs "
+@@ -1536,16 +1538,16 @@ static void iscsi_check_transport_timeouts(unsigned long data)
+ 	spin_unlock(&session->lock);
+ }
+ 
+-static void iscsi_prep_abort_ctask_pdu(struct iscsi_cmd_task *ctask,
++static void iscsi_prep_abort_task_pdu(struct iscsi_task *task,
+ 				      struct iscsi_tm *hdr)
+ {
+ 	memset(hdr, 0, sizeof(*hdr));
+ 	hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE;
+ 	hdr->flags = ISCSI_TM_FUNC_ABORT_TASK & ISCSI_FLAG_TM_FUNC_MASK;
+ 	hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+-	memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun));
+-	hdr->rtt = ctask->hdr->itt;
+-	hdr->refcmdsn = ctask->hdr->cmdsn;
++	memcpy(hdr->lun, task->hdr->lun, sizeof(hdr->lun));
++	hdr->rtt = task->hdr->itt;
++	hdr->refcmdsn = task->hdr->cmdsn;
+ }
+ 
+ int iscsi_eh_abort(struct scsi_cmnd *sc)
+@@ -1553,7 +1555,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 	struct iscsi_cls_session *cls_session;
+ 	struct iscsi_session *session;
+ 	struct iscsi_conn *conn;
+-	struct iscsi_cmd_task *ctask;
++	struct iscsi_task *task;
+ 	struct iscsi_tm *hdr;
+ 	int rc, age;
+ 
+@@ -1588,17 +1590,17 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 	conn->eh_abort_cnt++;
+ 	age = session->age;
+ 
+-	ctask = (struct iscsi_cmd_task *)sc->SCp.ptr;
+-	debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt);
++	task = (struct iscsi_task *)sc->SCp.ptr;
++	debug_scsi("aborting [sc %p itt 0x%x]\n", sc, task->itt);
+ 
+-	/* ctask completed before time out */
+-	if (!ctask->sc) {
++	/* task completed before time out */
++	if (!task->sc) {
+ 		debug_scsi("sc completed while abort in progress\n");
+ 		goto success;
+ 	}
+ 
+-	if (ctask->state == ISCSI_TASK_PENDING) {
+-		fail_command(conn, ctask, DID_ABORT << 16);
++	if (task->state == ISCSI_TASK_PENDING) {
++		fail_command(conn, task, DID_ABORT << 16);
+ 		goto success;
+ 	}
+ 
+@@ -1608,9 +1610,9 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 	conn->tmf_state = TMF_QUEUED;
+ 
+ 	hdr = &conn->tmhdr;
+-	iscsi_prep_abort_ctask_pdu(ctask, hdr);
++	iscsi_prep_abort_task_pdu(task, hdr);
+ 
+-	if (iscsi_exec_ctask_mgmt_fn(conn, hdr, age, session->abort_timeout)) {
++	if (iscsi_exec_task_mgmt_fn(conn, hdr, age, session->abort_timeout)) {
+ 		rc = FAILED;
+ 		goto failed;
+ 	}
+@@ -1620,11 +1622,11 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 		spin_unlock_bh(&session->lock);
+ 		iscsi_suspend_tx(conn);
+ 		/*
+-		 * clean up ctask if aborted. grab the recv lock as a writer
++		 * clean up task if aborted. grab the recv lock as a writer
+ 		 */
+ 		write_lock_bh(conn->recv_lock);
+ 		spin_lock(&session->lock);
+-		fail_command(conn, ctask, DID_ABORT << 16);
++		fail_command(conn, task, DID_ABORT << 16);
+ 		conn->tmf_state = TMF_INITIAL;
+ 		spin_unlock(&session->lock);
+ 		write_unlock_bh(conn->recv_lock);
+@@ -1637,7 +1639,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 	case TMF_NOT_FOUND:
+ 		if (!sc->SCp.ptr) {
+ 			conn->tmf_state = TMF_INITIAL;
+-			/* ctask completed before tmf abort response */
++			/* task completed before tmf abort response */
+ 			debug_scsi("sc completed while abort in progress\n");
+ 			goto success;
+ 		}
+@@ -1650,7 +1652,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ success:
+ 	spin_unlock_bh(&session->lock);
+ success_unlocked:
+-	debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
++	debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, task->itt);
+ 	mutex_unlock(&session->eh_mutex);
+ 	return SUCCESS;
+ 
+@@ -1658,7 +1660,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 	spin_unlock_bh(&session->lock);
+ failed_unlocked:
+ 	debug_scsi("abort failed [sc %p itt 0x%x]\n", sc,
+-		    ctask ? ctask->itt : 0);
++		    task ? task->itt : 0);
+ 	mutex_unlock(&session->eh_mutex);
+ 	return FAILED;
+ }
+@@ -1705,7 +1707,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc)
+ 	hdr = &conn->tmhdr;
+ 	iscsi_prep_lun_reset_pdu(sc, hdr);
+ 
+-	if (iscsi_exec_ctask_mgmt_fn(conn, hdr, session->age,
++	if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age,
+ 				    session->lu_reset_timeout)) {
+ 		rc = FAILED;
+ 		goto unlock;
+@@ -1886,7 +1888,7 @@ EXPORT_SYMBOL_GPL(iscsi_host_free);
+  * @iscsit: iscsi transport template
+  * @shost: scsi host
+  * @cmds_max: session can queue
+- * @cmd_ctask_size: LLD ctask private data size
++ * @cmd_task_size: LLD task private data size
+  * @initial_cmdsn: initial CmdSN
+  *
+  * This can be used by software iscsi_transports that allocate
+@@ -1894,7 +1896,7 @@ EXPORT_SYMBOL_GPL(iscsi_host_free);
+  */
+ struct iscsi_cls_session *
+ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
+-		    uint16_t scsi_cmds_max, int cmd_ctask_size,
++		    uint16_t scsi_cmds_max, int cmd_task_size,
+ 		    uint32_t initial_cmdsn)
+ {
+ 	struct iscsi_session *session;
+@@ -1902,7 +1904,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
+ 	int cmd_i, cmds_max;
+ 
+ 	/*
+-	 * The iscsi layer needs some ctasks for nop handling and tmfs.
++	 * The iscsi layer needs some tasks for nop handling and tmfs.
+ 	 */
+ 	if (scsi_cmds_max < 1)
+ 		scsi_cmds_max = ISCSI_MGMT_CMDS_MAX;
+@@ -1939,17 +1941,17 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
+ 	/* initialize SCSI PDU commands pool */
+ 	if (iscsi_pool_init(&session->cmdpool, session->cmds_max,
+ 			    (void***)&session->cmds,
+-			    cmd_ctask_size + sizeof(struct iscsi_cmd_task)))
++			    cmd_task_size + sizeof(struct iscsi_task)))
+ 		goto cmdpool_alloc_fail;
+ 
+ 	/* pre-format cmds pool with ITT */
+ 	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
+-		struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
++		struct iscsi_task *task = session->cmds[cmd_i];
+ 
+-		if (cmd_ctask_size)
+-			ctask->dd_data = &ctask[1];
+-		ctask->itt = cmd_i;
+-		INIT_LIST_HEAD(&ctask->running);
++		if (cmd_task_size)
++			task->dd_data = &task[1];
++		task->itt = cmd_i;
++		INIT_LIST_HEAD(&task->running);
+ 	}
+ 
+ 	if (!try_module_get(iscsit->owner))
+@@ -2035,30 +2037,30 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size,
+ 	INIT_LIST_HEAD(&conn->requeue);
+ 	INIT_WORK(&conn->xmitwork, iscsi_xmitworker);
+ 
+-	/* allocate login_ctask used for the login/text sequences */
++	/* allocate login_task used for the login/text sequences */
+ 	spin_lock_bh(&session->lock);
+ 	if (!__kfifo_get(session->cmdpool.queue,
+-                         (void*)&conn->login_ctask,
++                         (void*)&conn->login_task,
+ 			 sizeof(void*))) {
+ 		spin_unlock_bh(&session->lock);
+-		goto login_ctask_alloc_fail;
++		goto login_task_alloc_fail;
+ 	}
+ 	spin_unlock_bh(&session->lock);
+ 
+ 	data = kmalloc(ISCSI_DEF_MAX_RECV_SEG_LEN, GFP_KERNEL);
+ 	if (!data)
+-		goto login_ctask_data_alloc_fail;
+-	conn->login_ctask->data = conn->data = data;
++		goto login_task_data_alloc_fail;
++	conn->login_task->data = conn->data = data;
+ 
+ 	init_timer(&conn->tmf_timer);
+ 	init_waitqueue_head(&conn->ehwait);
+ 
+ 	return cls_conn;
+ 
+-login_ctask_data_alloc_fail:
+-	__kfifo_put(session->cmdpool.queue, (void*)&conn->login_ctask,
++login_task_data_alloc_fail:
++	__kfifo_put(session->cmdpool.queue, (void*)&conn->login_task,
+ 		    sizeof(void*));
+-login_ctask_alloc_fail:
++login_task_alloc_fail:
+ 	iscsi_destroy_conn(cls_conn);
+ 	return NULL;
+ }
+@@ -2118,7 +2120,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
+ 	spin_lock_bh(&session->lock);
+ 	kfree(conn->data);
+ 	kfree(conn->persistent_address);
+-	__kfifo_put(session->cmdpool.queue, (void*)&conn->login_ctask,
++	__kfifo_put(session->cmdpool.queue, (void*)&conn->login_task,
+ 		    sizeof(void*));
+ 	if (session->leadconn == conn)
+ 		session->leadconn = NULL;
+@@ -2199,23 +2201,23 @@ EXPORT_SYMBOL_GPL(iscsi_conn_start);
+ static void
+ flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn)
+ {
+-	struct iscsi_cmd_task *ctask, *tmp;
++	struct iscsi_task *task, *tmp;
+ 
+ 	/* handle pending */
+-	list_for_each_entry_safe(ctask, tmp, &conn->mgmtqueue, running) {
+-		debug_scsi("flushing pending mgmt ctask itt 0x%x\n", ctask->itt);
+-		/* release ref from prep ctask */
+-		__iscsi_put_ctask(ctask);
++	list_for_each_entry_safe(task, tmp, &conn->mgmtqueue, running) {
++		debug_scsi("flushing pending mgmt task itt 0x%x\n", task->itt);
++		/* release ref from prep task */
++		__iscsi_put_task(task);
+ 	}
+ 
+ 	/* handle running */
+-	list_for_each_entry_safe(ctask, tmp, &conn->mgmt_run_list, running) {
+-		debug_scsi("flushing running mgmt ctask itt 0x%x\n", ctask->itt);
+-		/* release ref from prep ctask */
+-		__iscsi_put_ctask(ctask);
++	list_for_each_entry_safe(task, tmp, &conn->mgmt_run_list, running) {
++		debug_scsi("flushing running mgmt task itt 0x%x\n", task->itt);
++		/* release ref from prep task */
++		__iscsi_put_task(task);
+ 	}
+ 
+-	conn->ctask = NULL;
++	conn->task = NULL;
+ }
+ 
+ static void iscsi_start_session_recovery(struct iscsi_session *session,
+@@ -2246,7 +2248,7 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ 
+ 	/*
+ 	 * When this is called for the in_login state, we only want to clean
+-	 * up the login ctask and connection. We do not need to block and set
++	 * up the login task and connection. We do not need to block and set
+ 	 * the recovery state again
+ 	 */
+ 	if (flag == STOP_CONN_TERM)
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index d1c36759b350..176353c117b6 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -92,7 +92,7 @@ enum {
+ 	ISCSI_TASK_RUNNING,
+ };
+ 
+-struct iscsi_cmd_task {
++struct iscsi_task {
+ 	/*
+ 	 * Because LLDs allocate their hdr differently, this is a pointer
+ 	 * and length to that storage. It must be setup at session
+@@ -120,9 +120,9 @@ struct iscsi_cmd_task {
+ 	void			*dd_data;	/* driver/transport data */
+ };
+ 
+-static inline void* iscsi_next_hdr(struct iscsi_cmd_task *ctask)
++static inline void* iscsi_next_hdr(struct iscsi_task *task)
+ {
+-	return (void*)ctask->hdr + ctask->hdr_len;
++	return (void*)task->hdr + task->hdr_len;
+ }
+ 
+ /* Connection's states */
+@@ -151,7 +151,7 @@ struct iscsi_conn {
+ 	unsigned long		last_ping;
+ 	int			ping_timeout;
+ 	int			recv_timeout;
+-	struct iscsi_cmd_task 	*ping_ctask;
++	struct iscsi_task 	*ping_task;
+ 
+ 	/* iSCSI connection-wide sequencing */
+ 	uint32_t		exp_statsn;
+@@ -167,8 +167,8 @@ struct iscsi_conn {
+ 	 * should always fit in this buffer
+ 	 */
+ 	char			*data;
+-	struct iscsi_cmd_task 	*login_ctask;	/* mtask used for login/text */
+-	struct iscsi_cmd_task	*ctask;		/* xmit task in progress */
++	struct iscsi_task 	*login_task;	/* mtask used for login/text */
++	struct iscsi_task	*task;		/* xmit task in progress */
+ 
+ 	/* xmit */
+ 	struct list_head	mgmtqueue;	/* mgmt (control) xmit queue */
+@@ -285,7 +285,7 @@ struct iscsi_session {
+ 
+ 	int			scsi_cmds_max; 	/* max scsi commands */
+ 	int			cmds_max;	/* size of cmds array */
+-	struct iscsi_cmd_task	**cmds;		/* Original Cmds arr */
++	struct iscsi_task	**cmds;		/* Original Cmds arr */
+ 	struct iscsi_pool	cmdpool;	/* PDU's pool */
+ };
+ 
+@@ -365,16 +365,16 @@ extern void iscsi_suspend_tx(struct iscsi_conn *conn);
+  * pdu and task processing
+  */
+ extern void iscsi_update_cmdsn(struct iscsi_session *, struct iscsi_nopin *);
+-extern void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *,
++extern void iscsi_prep_unsolicit_data_pdu(struct iscsi_task *,
+ 					struct iscsi_data *hdr);
+ extern int iscsi_conn_send_pdu(struct iscsi_cls_conn *, struct iscsi_hdr *,
+ 				char *, uint32_t);
+ extern int iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *,
+ 			      char *, int);
+ extern int iscsi_verify_itt(struct iscsi_conn *, itt_t);
+-extern struct iscsi_cmd_task *iscsi_itt_to_ctask(struct iscsi_conn *, itt_t);
+-extern void iscsi_requeue_ctask(struct iscsi_cmd_task *ctask);
+-extern void iscsi_put_ctask(struct iscsi_cmd_task *ctask);
++extern struct iscsi_task *iscsi_itt_to_ctask(struct iscsi_conn *, itt_t);
++extern void iscsi_requeue_task(struct iscsi_task *task);
++extern void iscsi_put_task(struct iscsi_task *task);
+ 
+ /*
+  * generic helpers
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 3f24503dfdf9..0553240796e9 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -33,7 +33,7 @@ struct iscsi_transport;
+ struct Scsi_Host;
+ struct iscsi_cls_conn;
+ struct iscsi_conn;
+-struct iscsi_cmd_task;
++struct iscsi_task;
+ struct sockaddr;
+ 
+ /**
+@@ -112,10 +112,10 @@ struct iscsi_transport {
+ 			 char *data, uint32_t data_size);
+ 	void (*get_stats) (struct iscsi_cls_conn *conn,
+ 			   struct iscsi_stats *stats);
+-	int (*init_task) (struct iscsi_cmd_task *task);
+-	int (*xmit_task) (struct iscsi_cmd_task *task);
++	int (*init_task) (struct iscsi_task *task);
++	int (*xmit_task) (struct iscsi_task *task);
+ 	void (*cleanup_task) (struct iscsi_conn *conn,
+-				  struct iscsi_cmd_task *task);
++				  struct iscsi_task *task);
+ 	void (*session_recovery_timedout) (struct iscsi_cls_session *session);
+ 	int (*ep_connect) (struct sockaddr *dst_addr, int non_blocking,
+ 			   uint64_t *ep_handle);

commit 2747fdb25726caa1a89229f43d99ca50af72576a
+Author: Mike Christie 
+Date:   Wed May 21 15:54:08 2008 -0500
+
+    [SCSI] iser: convert ib_iser to support merged tasks
+    
+    Convert ib_iser to support merged tasks.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 7b1468869066..baecca1ed42a 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -124,15 +124,23 @@ iscsi_iser_recv(struct iscsi_conn *conn,
+ 
+ 
+ /**
+- * iscsi_iser_cmd_init - Initialize iSCSI SCSI_READ or SCSI_WRITE commands
++ * iscsi_iser_task_init - Initialize ctask
++ * @ctask: iscsi ctask
+  *
+- **/
++ * Initialize the ctask for the scsi command or mgmt command.
++ */
+ static int
+-iscsi_iser_cmd_init(struct iscsi_cmd_task *ctask)
++iscsi_iser_task_init(struct iscsi_cmd_task *ctask)
+ {
+-	struct iscsi_iser_conn     *iser_conn  = ctask->conn->dd_data;
++	struct iscsi_iser_conn *iser_conn  = ctask->conn->dd_data;
+ 	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
+ 
++	/* mgmt ctask */
++	if (!ctask->sc) {
++		iser_ctask->desc.data = ctask->data;
++		return 0;
++	}
++
+ 	iser_ctask->command_sent = 0;
+ 	iser_ctask->iser_conn    = iser_conn;
+ 	iser_ctask_rdma_init(iser_ctask);
+@@ -140,9 +148,9 @@ iscsi_iser_cmd_init(struct iscsi_cmd_task *ctask)
+ }
+ 
+ /**
+- * iscsi_mtask_xmit - xmit management(immediate) task
++ * iscsi_iser_mtask_xmit - xmit management(immediate) ctask
+  * @conn: iscsi connection
+- * @mtask: task management task
++ * @ctask: ctask management ctask
+  *
+  * Notes:
+  *	The function can return -EAGAIN in which case caller must
+@@ -151,20 +159,19 @@ iscsi_iser_cmd_init(struct iscsi_cmd_task *ctask)
+  *
+  **/
+ static int
+-iscsi_iser_mtask_xmit(struct iscsi_conn *conn,
+-		      struct iscsi_mgmt_task *mtask)
++iscsi_iser_mtask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+ 	int error = 0;
+ 
+-	debug_scsi("mtask deq [cid %d itt 0x%x]\n", conn->id, mtask->itt);
++	debug_scsi("ctask deq [cid %d itt 0x%x]\n", conn->id, ctask->itt);
+ 
+-	error = iser_send_control(conn, mtask);
++	error = iser_send_control(conn, ctask);
+ 
+-	/* since iser xmits control with zero copy, mtasks can not be recycled
++	/* since iser xmits control with zero copy, ctasks can not be recycled
+ 	 * right after sending them.
+ 	 * The recycling scheme is based on whether a response is expected
+-	 * - if yes, the mtask is recycled at iscsi_complete_pdu
+-	 * - if no,  the mtask is recycled at iser_snd_completion
++	 * - if yes, the ctask is recycled at iscsi_complete_pdu
++	 * - if no,  the ctask is recycled at iser_snd_completion
+ 	 */
+ 	if (error && error != -ENOBUFS)
+ 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+@@ -173,7 +180,7 @@ iscsi_iser_mtask_xmit(struct iscsi_conn *conn,
+ }
+ 
+ static int
+-iscsi_iser_ctask_xmit_unsol_data(struct iscsi_conn *conn,
++iscsi_iser_task_xmit_unsol_data(struct iscsi_conn *conn,
+ 				 struct iscsi_cmd_task *ctask)
+ {
+ 	struct iscsi_data  hdr;
+@@ -190,24 +197,27 @@ iscsi_iser_ctask_xmit_unsol_data(struct iscsi_conn *conn,
+ 		error = iser_send_data_out(conn, ctask, &hdr);
+ 		if (error) {
+ 			ctask->unsol_datasn--;
+-			goto iscsi_iser_ctask_xmit_unsol_data_exit;
++			goto iscsi_iser_task_xmit_unsol_data_exit;
+ 		}
+ 		ctask->unsol_count -= ctask->data_count;
+ 		debug_scsi("Need to send %d more as data-out PDUs\n",
+ 			   ctask->unsol_count);
+ 	}
+ 
+-iscsi_iser_ctask_xmit_unsol_data_exit:
++iscsi_iser_task_xmit_unsol_data_exit:
+ 	return error;
+ }
+ 
+ static int
+-iscsi_iser_ctask_xmit(struct iscsi_conn *conn,
+-		      struct iscsi_cmd_task *ctask)
++iscsi_iser_task_xmit(struct iscsi_cmd_task *ctask)
+ {
++	struct iscsi_conn *conn = ctask->conn;
+ 	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
+ 	int error = 0;
+ 
++	if (!ctask->sc)
++		return iscsi_iser_mtask_xmit(conn, ctask);
++
+ 	if (ctask->sc->sc_data_direction == DMA_TO_DEVICE) {
+ 		BUG_ON(scsi_bufflen(ctask->sc) == 0);
+ 
+@@ -223,25 +233,29 @@ iscsi_iser_ctask_xmit(struct iscsi_conn *conn,
+ 	if (!iser_ctask->command_sent) {
+ 		error = iser_send_command(conn, ctask);
+ 		if (error)
+-			goto iscsi_iser_ctask_xmit_exit;
++			goto iscsi_iser_task_xmit_exit;
+ 		iser_ctask->command_sent = 1;
+ 	}
+ 
+ 	/* Send unsolicited data-out PDU(s) if necessary */
+ 	if (ctask->unsol_count)
+-		error = iscsi_iser_ctask_xmit_unsol_data(conn, ctask);
++		error = iscsi_iser_task_xmit_unsol_data(conn, ctask);
+ 
+- iscsi_iser_ctask_xmit_exit:
++ iscsi_iser_task_xmit_exit:
+ 	if (error && error != -ENOBUFS)
+ 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ 	return error;
+ }
+ 
+ static void
+-iscsi_iser_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
++iscsi_iser_cleanup_task(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+ 	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
+ 
++	/* mgmt tasks do not need special cleanup */
++	if (!ctask->sc)
++		return;
++
+ 	if (iser_ctask->status == ISER_TASK_STATUS_STARTED) {
+ 		iser_ctask->status = ISER_TASK_STATUS_COMPLETED;
+ 		iser_ctask_rdma_finalize(iser_ctask);
+@@ -394,10 +408,8 @@ iscsi_iser_session_create(struct Scsi_Host *shost,
+ 	struct iscsi_cls_session *cls_session;
+ 	struct iscsi_session *session;
+ 	int i;
+-	struct iscsi_cmd_task  *ctask;
+-	struct iscsi_mgmt_task *mtask;
++	struct iscsi_cmd_task *ctask;
+ 	struct iscsi_iser_cmd_task *iser_ctask;
+-	struct iser_desc *desc;
+ 
+ 	if (shost) {
+ 		printk(KERN_ERR "iscsi_tcp: invalid shost %d.\n",
+@@ -425,28 +437,19 @@ iscsi_iser_session_create(struct Scsi_Host *shost,
+ 	cls_session = iscsi_session_setup(&iscsi_iser_transport, shost,
+ 					  ISCSI_DEF_XMIT_CMDS_MAX,
+ 					  sizeof(struct iscsi_iser_cmd_task),
+-					  sizeof(struct iser_desc),
+ 					  initial_cmdsn);
+ 	if (!cls_session)
+ 		goto remove_host;
+ 	session = cls_session->dd_data;
+ 
+-	shost->can_queue = session->cmds_max;
++	shost->can_queue = session->scsi_cmds_max;
+ 	/* libiscsi setup itts, data and pool so just set desc fields */
+ 	for (i = 0; i < session->cmds_max; i++) {
+-		ctask      = session->cmds[i];
++		ctask = session->cmds[i];
+ 		iser_ctask = ctask->dd_data;
+ 		ctask->hdr = (struct iscsi_cmd *)&iser_ctask->desc.iscsi_header;
+ 		ctask->hdr_max = sizeof(iser_ctask->desc.iscsi_header);
+ 	}
+-
+-	for (i = 0; i < session->mgmtpool_max; i++) {
+-		mtask      = session->mgmt_cmds[i];
+-		desc       = mtask->dd_data;
+-		mtask->hdr = &desc->iscsi_header;
+-		desc->data = mtask->data;
+-	}
+-
+ 	return cls_session;
+ 
+ remove_host:
+@@ -659,10 +662,9 @@ static struct iscsi_transport iscsi_iser_transport = {
+ 	/* IO */
+ 	.send_pdu		= iscsi_conn_send_pdu,
+ 	.get_stats		= iscsi_iser_conn_get_stats,
+-	.init_cmd_task		= iscsi_iser_cmd_init,
+-	.xmit_cmd_task		= iscsi_iser_ctask_xmit,
+-	.xmit_mgmt_task		= iscsi_iser_mtask_xmit,
+-	.cleanup_cmd_task	= iscsi_iser_cleanup_ctask,
++	.init_task		= iscsi_iser_task_init,
++	.xmit_task		= iscsi_iser_task_xmit,
++	.cleanup_task		= iscsi_iser_cleanup_task,
+ 	/* recovery */
+ 	.session_recovery_timedout = iscsi_session_recovery_timedout,
+ 
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
+index bd5c1a554ea6..96a600f127c8 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
+@@ -298,15 +298,15 @@ extern int iser_debug_level;
+ /* allocate connection resources needed for rdma functionality */
+ int iser_conn_set_full_featured_mode(struct iscsi_conn *conn);
+ 
+-int iser_send_control(struct iscsi_conn      *conn,
+-		      struct iscsi_mgmt_task *mtask);
++int iser_send_control(struct iscsi_conn *conn,
++		      struct iscsi_cmd_task *ctask);
+ 
+-int iser_send_command(struct iscsi_conn      *conn,
+-		      struct iscsi_cmd_task  *ctask);
++int iser_send_command(struct iscsi_conn *conn,
++		      struct iscsi_cmd_task *ctask);
+ 
+-int iser_send_data_out(struct iscsi_conn     *conn,
++int iser_send_data_out(struct iscsi_conn *conn,
+ 		       struct iscsi_cmd_task *ctask,
+-		       struct iscsi_data          *hdr);
++		       struct iscsi_data *hdr);
+ 
+ void iscsi_iser_recv(struct iscsi_conn *conn,
+ 		     struct iscsi_hdr       *hdr,
+@@ -326,7 +326,7 @@ void iser_rcv_completion(struct iser_desc *desc,
+ 
+ void iser_snd_completion(struct iser_desc *desc);
+ 
+-void iser_ctask_rdma_init(struct iscsi_iser_cmd_task     *ctask);
++void iser_ctask_rdma_init(struct iscsi_iser_cmd_task *ctask);
+ 
+ void iser_ctask_rdma_finalize(struct iscsi_iser_cmd_task *ctask);
+ 
+diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
+index b82a5f2d4d37..4ea78fbeee95 100644
+--- a/drivers/infiniband/ulp/iser/iser_initiator.c
++++ b/drivers/infiniband/ulp/iser/iser_initiator.c
+@@ -300,13 +300,13 @@ int iser_conn_set_full_featured_mode(struct iscsi_conn *conn)
+ }
+ 
+ static int
+-iser_check_xmit(struct iscsi_conn *conn, void *task)
++iser_check_xmit(struct iscsi_conn *conn, void *ctask)
+ {
+ 	struct iscsi_iser_conn *iser_conn = conn->dd_data;
+ 
+ 	if (atomic_read(&iser_conn->ib_conn->post_send_buf_count) ==
+ 	    ISER_QP_MAX_REQ_DTOS) {
+-		iser_dbg("%ld can't xmit task %p\n",jiffies,task);
++		iser_dbg("%ld can't xmit ctask %p\n",jiffies,ctask);
+ 		return -ENOBUFS;
+ 	}
+ 	return 0;
+@@ -316,7 +316,7 @@ iser_check_xmit(struct iscsi_conn *conn, void *task)
+ /**
+  * iser_send_command - send command PDU
+  */
+-int iser_send_command(struct iscsi_conn     *conn,
++int iser_send_command(struct iscsi_conn *conn,
+ 		      struct iscsi_cmd_task *ctask)
+ {
+ 	struct iscsi_iser_conn *iser_conn = conn->dd_data;
+@@ -395,7 +395,7 @@ int iser_send_command(struct iscsi_conn     *conn,
+ /**
+  * iser_send_data_out - send data out PDU
+  */
+-int iser_send_data_out(struct iscsi_conn     *conn,
++int iser_send_data_out(struct iscsi_conn *conn,
+ 		       struct iscsi_cmd_task *ctask,
+ 		       struct iscsi_data *hdr)
+ {
+@@ -470,10 +470,11 @@ int iser_send_data_out(struct iscsi_conn     *conn,
+ }
+ 
+ int iser_send_control(struct iscsi_conn *conn,
+-		      struct iscsi_mgmt_task *mtask)
++		      struct iscsi_cmd_task *ctask)
+ {
+ 	struct iscsi_iser_conn *iser_conn = conn->dd_data;
+-	struct iser_desc *mdesc = mtask->dd_data;
++	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
++	struct iser_desc *mdesc = &iser_ctask->desc;
+ 	struct iser_dto *send_dto = NULL;
+ 	unsigned long data_seg_len;
+ 	int err = 0;
+@@ -485,7 +486,7 @@ int iser_send_control(struct iscsi_conn *conn,
+ 		return -EPERM;
+ 	}
+ 
+-	if (iser_check_xmit(conn,mtask))
++	if (iser_check_xmit(conn, ctask))
+ 		return -ENOBUFS;
+ 
+ 	/* build the tx desc regd header and add it to the tx desc dto */
+@@ -498,14 +499,14 @@ int iser_send_control(struct iscsi_conn *conn,
+ 
+ 	iser_reg_single(device, send_dto->regd[0], DMA_TO_DEVICE);
+ 
+-	data_seg_len = ntoh24(mtask->hdr->dlength);
++	data_seg_len = ntoh24(ctask->hdr->dlength);
+ 
+ 	if (data_seg_len > 0) {
+ 		regd_buf = &mdesc->data_regd_buf;
+ 		memset(regd_buf, 0, sizeof(struct iser_regd_buf));
+ 		regd_buf->device = device;
+-		regd_buf->virt_addr = mtask->data;
+-		regd_buf->data_size = mtask->data_count;
++		regd_buf->virt_addr = ctask->data;
++		regd_buf->data_size = ctask->data_count;
+ 		iser_reg_single(device, regd_buf,
+ 				DMA_TO_DEVICE);
+ 		iser_dto_add_regd_buff(send_dto, regd_buf,
+@@ -535,7 +536,7 @@ int iser_send_control(struct iscsi_conn *conn,
+ void iser_rcv_completion(struct iser_desc *rx_desc,
+ 			 unsigned long dto_xfer_len)
+ {
+-	struct iser_dto        *dto = &rx_desc->dto;
++	struct iser_dto *dto = &rx_desc->dto;
+ 	struct iscsi_iser_conn *conn = dto->ib_conn->iser_conn;
+ 	struct iscsi_cmd_task *ctask;
+ 	struct iscsi_iser_cmd_task *iser_ctask;
+@@ -559,7 +560,7 @@ void iser_rcv_completion(struct iser_desc *rx_desc,
+ 	if (opcode == ISCSI_OP_SCSI_CMD_RSP) {
+ 		ctask = iscsi_itt_to_ctask(conn->iscsi_conn, hdr->itt);
+ 		if (!ctask)
+-			iser_err("itt can't be matched to task!!! "
++			iser_err("itt can't be matched to ctask!!! "
+ 				 "conn %p opcode %d itt %d\n",
+ 				 conn->iscsi_conn, opcode, hdr->itt);
+ 		else {
+@@ -577,7 +578,7 @@ void iser_rcv_completion(struct iser_desc *rx_desc,
+ 	kmem_cache_free(ig.desc_cache, rx_desc);
+ 
+ 	/* decrementing conn->post_recv_buf_count only --after-- freeing the   *
+-	 * task eliminates the need to worry on tasks which are completed in   *
++	 * ctask eliminates the need to worry on ctasks which are completed in   *
+ 	 * parallel to the execution of iser_conn_term. So the code that waits *
+ 	 * for the posted rx bufs refcount to become zero handles everything   */
+ 	atomic_dec(&conn->ib_conn->post_recv_buf_count);
+@@ -589,7 +590,7 @@ void iser_snd_completion(struct iser_desc *tx_desc)
+ 	struct iser_conn       *ib_conn = dto->ib_conn;
+ 	struct iscsi_iser_conn *iser_conn = ib_conn->iser_conn;
+ 	struct iscsi_conn      *conn = iser_conn->iscsi_conn;
+-	struct iscsi_mgmt_task *mtask;
++	struct iscsi_cmd_task *ctask;
+ 	int resume_tx = 0;
+ 
+ 	iser_dbg("Initiator, Data sent dto=0x%p\n", dto);
+@@ -612,15 +613,10 @@ void iser_snd_completion(struct iser_desc *tx_desc)
+ 
+ 	if (tx_desc->type == ISCSI_TX_CONTROL) {
+ 		/* this arithmetic is legal by libiscsi dd_data allocation */
+-		mtask = (void *) ((long)(void *)tx_desc -
+-				  sizeof(struct iscsi_mgmt_task));
+-		if (mtask->hdr->itt == RESERVED_ITT) {
+-			struct iscsi_session *session = conn->session;
+-
+-			spin_lock(&conn->session->lock);
+-			iscsi_free_mgmt_task(conn, mtask);
+-			spin_unlock(&session->lock);
+-		}
++		ctask = (void *) ((long)(void *)tx_desc -
++				  sizeof(struct iscsi_cmd_task));
++		if (ctask->hdr->itt == RESERVED_ITT)
++			iscsi_put_ctask(ctask);
+ 	}
+ }
+ 

commit fbc514b4e262bc0596faae8640ebc0b9142a1cdd
+Author: Mike Christie 
+Date:   Wed May 21 15:54:07 2008 -0500
+
+    [SCSI] iscsi_tcp: convert iscsi_tcp to support merged tasks
+    
+    Convert iscsi_tcp to support merged tasks.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index f2a08f7ed902..517bad160bea 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -498,11 +498,15 @@ iscsi_tcp_data_recv_prep(struct iscsi_tcp_conn *tcp_conn)
+  * must be called with session lock
+  */
+ static void
+-iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
++iscsi_tcp_cleanup_task(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	struct iscsi_r2t_info *r2t;
+ 
++	/* nothing to do for mgmt ctasks */
++	if (!ctask->sc)
++		return;
++
+ 	/* flush ctask's r2t queues */
+ 	while (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) {
+ 		__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
+@@ -521,7 +525,7 @@ iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ /**
+  * iscsi_data_rsp - SCSI Data-In Response processing
+  * @conn: iscsi connection
+- * @ctask: scsi command task
++ * @ctask: scsi command ctask
+  **/
+ static int
+ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+@@ -578,7 +582,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ /**
+  * iscsi_solicit_data_init - initialize first Data-Out
+  * @conn: iscsi connection
+- * @ctask: scsi command task
++ * @ctask: scsi command ctask
+  * @r2t: R2T info
+  *
+  * Notes:
+@@ -620,7 +624,7 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ /**
+  * iscsi_r2t_rsp - iSCSI R2T Response processing
+  * @conn: iscsi connection
+- * @ctask: scsi command task
++ * @ctask: scsi command ctask
+  **/
+ static int
+ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+@@ -646,7 +650,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 		return ISCSI_ERR_R2TSN;
+ 	}
+ 
+-	/* fill-in new R2T associated with the task */
++	/* fill-in new R2T associated with the ctask */
+ 	iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
+ 
+ 	if (!ctask->sc || session->state != ISCSI_STATE_LOGGED_IN) {
+@@ -769,6 +773,8 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 		ctask = iscsi_itt_to_ctask(conn, hdr->itt);
+ 		if (!ctask)
+ 			return ISCSI_ERR_BAD_ITT;
++		if (!ctask->sc)
++			return ISCSI_ERR_NO_SCSI_CMD;
+ 
+ 		spin_lock(&conn->session->lock);
+ 		rc = iscsi_data_rsp(conn, ctask);
+@@ -815,6 +821,8 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 		ctask = iscsi_itt_to_ctask(conn, hdr->itt);
+ 		if (!ctask)
+ 			return ISCSI_ERR_BAD_ITT;
++		if (!ctask->sc)
++			return ISCSI_ERR_NO_SCSI_CMD;
+ 
+ 		if (ahslen)
+ 			rc = ISCSI_ERR_AHSLEN;
+@@ -1194,7 +1202,7 @@ iscsi_tcp_send_hdr_prep(struct iscsi_conn *conn, void *hdr, size_t hdrlen)
+ 
+ 	/* If header digest is enabled, compute the CRC and
+ 	 * place the digest into the same buffer. We make
+-	 * sure that both iscsi_tcp_ctask and mtask have
++	 * sure that both iscsi_tcp_cmd_task and mctask have
+ 	 * sufficient room.
+ 	 */
+ 	if (conn->hdrdgst_en) {
+@@ -1269,7 +1277,7 @@ iscsi_tcp_send_linear_data_prepare(struct iscsi_conn *conn, void *data,
+ /**
+  * iscsi_solicit_data_cont - initialize next Data-Out
+  * @conn: iscsi connection
+- * @ctask: scsi command task
++ * @ctask: scsi command ctask
+  * @r2t: R2T info
+  * @left: bytes left to transfer
+  *
+@@ -1316,19 +1324,37 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ }
+ 
+ /**
+- * iscsi_tcp_ctask - Initialize iSCSI SCSI_READ or SCSI_WRITE commands
++ * iscsi_tcp_task - Initialize iSCSI SCSI_READ or SCSI_WRITE commands
+  * @conn: iscsi connection
+- * @ctask: scsi command task
++ * @ctask: scsi command ctask
+  * @sc: scsi command
+  **/
+ static int
+-iscsi_tcp_ctask_init(struct iscsi_cmd_task *ctask)
++iscsi_tcp_task_init(struct iscsi_cmd_task *ctask)
+ {
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	struct iscsi_conn *conn = ctask->conn;
+ 	struct scsi_cmnd *sc = ctask->sc;
+ 	int err;
+ 
++	if (!sc) {
++		/*
++		 * mgmt ctasks do not have a scatterlist since they come
++		 * in from the iscsi interface.
++		 */
++		debug_scsi("mctask deq [cid %d itt 0x%x]\n", conn->id,
++			   ctask->itt);
++
++		/* Prepare PDU, optionally w/ immediate data */
++		iscsi_tcp_send_hdr_prep(conn, ctask->hdr, sizeof(*ctask->hdr));
++
++		/* If we have immediate data, attach a payload */
++		if (ctask->data_count)
++			iscsi_tcp_send_linear_data_prepare(conn, ctask->data,
++							   ctask->data_count);
++		return 0;
++	}
++
+ 	BUG_ON(__kfifo_len(tcp_ctask->r2tqueue));
+ 	tcp_ctask->sent = 0;
+ 	tcp_ctask->exp_datasn = 0;
+@@ -1353,52 +1379,21 @@ iscsi_tcp_ctask_init(struct iscsi_cmd_task *ctask)
+ 	return 0;
+ }
+ 
+-/**
+- * iscsi_tcp_mtask_xmit - xmit management(immediate) task
+- * @conn: iscsi connection
+- * @mtask: task management task
+- *
+- * Notes:
+- *	The function can return -EAGAIN in which case caller must
+- *	call it again later, or recover. '0' return code means successful
+- *	xmit.
+- **/
+-static int
+-iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
+-{
+-	int rc;
+-
+-	/* Flush any pending data first. */
+-	rc = iscsi_tcp_flush(conn);
+-	if (rc < 0)
+-		return rc;
+-
+-	if (mtask->hdr->itt == RESERVED_ITT) {
+-		struct iscsi_session *session = conn->session;
+-
+-		spin_lock_bh(&session->lock);
+-		iscsi_free_mgmt_task(conn, mtask);
+-		spin_unlock_bh(&session->lock);
+-	}
+-
+-	return 0;
+-}
+-
+ /*
+- * iscsi_tcp_ctask_xmit - xmit normal PDU task
+- * @conn: iscsi connection
+- * @ctask: iscsi command task
++ * iscsi_tcp_task_xmit - xmit normal PDU ctask
++ * @ctask: iscsi command ctask
+  *
+  * We're expected to return 0 when everything was transmitted succesfully,
+  * -EAGAIN if there's still data in the queue, or != 0 for any other kind
+  * of error.
+  */
+ static int
+-iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
++iscsi_tcp_task_xmit(struct iscsi_cmd_task *ctask)
+ {
++	struct iscsi_conn *conn = ctask->conn;
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	struct scsi_cmnd *sc = ctask->sc;
+-	struct scsi_data_buffer *sdb = scsi_out(sc);
++	struct scsi_data_buffer *sdb;
+ 	int rc = 0;
+ 
+ flush:
+@@ -1407,10 +1402,18 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	if (rc < 0)
+ 		return rc;
+ 
++	/* mgmt command */
++	if (!sc) {
++		if (ctask->hdr->itt == RESERVED_ITT)
++			iscsi_put_ctask(ctask);
++		return 0;
++	}
++
+ 	/* Are we done already? */
+ 	if (sc->sc_data_direction != DMA_TO_DEVICE)
+ 		return 0;
+ 
++	sdb = scsi_out(sc);
+ 	if (ctask->unsol_count != 0) {
+ 		struct iscsi_data *hdr = &tcp_ctask->unsol_dtask.hdr;
+ 
+@@ -1688,21 +1691,6 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
+ 	return err;
+ }
+ 
+-/* called with host lock */
+-static void
+-iscsi_tcp_mtask_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
+-{
+-	debug_scsi("mtask deq [cid %d itt 0x%x]\n", conn->id, mtask->itt);
+-
+-	/* Prepare PDU, optionally w/ immediate data */
+-	iscsi_tcp_send_hdr_prep(conn, mtask->hdr, sizeof(*mtask->hdr));
+-
+-	/* If we have immediate data, attach a payload */
+-	if (mtask->data_count)
+-		iscsi_tcp_send_linear_data_prepare(conn, mtask->data,
+-						   mtask->data_count);
+-}
+-
+ static int
+ iscsi_r2tpool_alloc(struct iscsi_session *session)
+ {
+@@ -1710,7 +1698,7 @@ iscsi_r2tpool_alloc(struct iscsi_session *session)
+ 	int cmd_i;
+ 
+ 	/*
+-	 * initialize per-task: R2T pool and xmit queue
++	 * initialize per-ctask: R2T pool and xmit queue
+ 	 */
+ 	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
+ 	        struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
+@@ -1880,13 +1868,12 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max,
+ 
+ 	cls_session = iscsi_session_setup(&iscsi_tcp_transport, shost, cmds_max,
+ 					  sizeof(struct iscsi_tcp_cmd_task),
+-					  sizeof(struct iscsi_tcp_mgmt_task),
+ 					  initial_cmdsn);
+ 	if (!cls_session)
+ 		goto remove_host;
+ 	session = cls_session->dd_data;
+ 
+-	shost->can_queue = session->cmds_max;
++	shost->can_queue = session->scsi_cmds_max;
+ 	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
+ 		struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
+ 		struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+@@ -1895,13 +1882,6 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max,
+ 		ctask->hdr_max = sizeof(tcp_ctask->hdr) - ISCSI_DIGEST_SIZE;
+ 	}
+ 
+-	for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) {
+-		struct iscsi_mgmt_task *mtask = session->mgmt_cmds[cmd_i];
+-		struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data;
+-
+-		mtask->hdr = (struct iscsi_hdr *) &tcp_mtask->hdr;
+-	}
+-
+ 	if (iscsi_r2tpool_alloc(session))
+ 		goto remove_session;
+ 	return cls_session;
+@@ -1999,11 +1979,9 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 	/* IO */
+ 	.send_pdu		= iscsi_conn_send_pdu,
+ 	.get_stats		= iscsi_conn_get_stats,
+-	.init_cmd_task		= iscsi_tcp_ctask_init,
+-	.init_mgmt_task		= iscsi_tcp_mtask_init,
+-	.xmit_cmd_task		= iscsi_tcp_ctask_xmit,
+-	.xmit_mgmt_task		= iscsi_tcp_mtask_xmit,
+-	.cleanup_cmd_task	= iscsi_tcp_cleanup_ctask,
++	.init_task		= iscsi_tcp_task_init,
++	.xmit_task		= iscsi_tcp_task_xmit,
++	.cleanup_task		= iscsi_tcp_cleanup_task,
+ 	/* recovery */
+ 	.session_recovery_timedout = iscsi_session_recovery_timedout,
+ };
+diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
+index ed0b991d1e72..c9c8633c41a6 100644
+--- a/drivers/scsi/iscsi_tcp.h
++++ b/drivers/scsi/iscsi_tcp.h
+@@ -103,11 +103,6 @@ struct iscsi_data_task {
+ 	char			hdrext[ISCSI_DIGEST_SIZE];/* Header-Digest */
+ };
+ 
+-struct iscsi_tcp_mgmt_task {
+-	struct iscsi_hdr	hdr;
+-	char			hdrext[ISCSI_DIGEST_SIZE]; /* Header-Digest */
+-};
+-
+ struct iscsi_r2t_info {
+ 	__be32			ttt;		/* copied from R2T */
+ 	__be32			exp_statsn;	/* copied from R2T */

commit 3e5c28ad0391389959ccae81c938c7533efb3490
+Author: Mike Christie 
+Date:   Wed May 21 15:54:06 2008 -0500
+
+    [SCSI] libiscsi: merge iscsi_mgmt_task and iscsi_cmd_task
+    
+    There is no need to have the mgmt and cmd tasks separate
+    structs. It used to save a lot of memory when we overprealocated
+    memory for tasks, but the next patches will set up the
+    driver so in the future they can use a mempool or some other
+    common scsi command allocator and common tagging.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 1e605de07cff..ef92b1b0f16e 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -197,7 +197,7 @@ static int iscsi_prep_bidi_ahs(struct iscsi_cmd_task *ctask)
+ 
+ /**
+  * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu
+- * @ctask: iscsi cmd task
++ * @ctask: iscsi task
+  *
+  * Prep basic iSCSI PDU fields for a scsi cmd pdu. The LLD should set
+  * fields like dlength or final based on how much data it sends
+@@ -300,31 +300,31 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ 	WARN_ON(hdrlength >= 256);
+ 	hdr->hlength = hdrlength & 0xFF;
+ 
+-	if (conn->session->tt->init_cmd_task &&
+-	    conn->session->tt->init_cmd_task(ctask))
++	if (conn->session->tt->init_task &&
++	    conn->session->tt->init_task(ctask))
+ 		return -EIO;
+ 
+ 	ctask->state = ISCSI_TASK_RUNNING;
+ 	list_move_tail(&ctask->running, &conn->run_list);
+ 
+ 	conn->scsicmd_pdus_cnt++;
+-	debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x "
+-		"len %d bidi_len %d cmdsn %d win %d]\n",
+-		scsi_bidi_cmnd(sc) ? "bidirectional" :
+-		     sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
+-		conn->id, sc, sc->cmnd[0], ctask->itt,
+-		scsi_bufflen(sc), scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0,
+-		session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
++	debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x len %d "
++		   "bidi_len %d cmdsn %d win %d]\n", scsi_bidi_cmnd(sc) ?
++		   "bidirectional" : sc->sc_data_direction == DMA_TO_DEVICE ?
++		   "write" : "read", conn->id, sc, sc->cmnd[0], ctask->itt,
++		   scsi_bufflen(sc),
++		   scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0,
++		   session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
+ 	return 0;
+ }
+ 
+ /**
+- * iscsi_complete_command - return command back to scsi-ml
++ * iscsi_complete_command - finish a task
+  * @ctask: iscsi cmd task
+  *
+  * Must be called with session lock.
+- * This function returns the scsi command to scsi-ml and returns
+- * the cmd task to the pool of available cmd tasks.
++ * This function returns the scsi command to scsi-ml or cleans
++ * up mgmt tasks then returns the task to the pool.
+  */
+ static void iscsi_complete_command(struct iscsi_cmd_task *ctask)
+ {
+@@ -332,17 +332,34 @@ static void iscsi_complete_command(struct iscsi_cmd_task *ctask)
+ 	struct iscsi_session *session = conn->session;
+ 	struct scsi_cmnd *sc = ctask->sc;
+ 
++	list_del_init(&ctask->running);
+ 	ctask->state = ISCSI_TASK_COMPLETED;
+ 	ctask->sc = NULL;
+-	/* SCSI eh reuses commands to verify us */
+-	sc->SCp.ptr = NULL;
++
+ 	if (conn->ctask == ctask)
+ 		conn->ctask = NULL;
+-	list_del_init(&ctask->running);
++	/*
++	 * login ctask is preallocated so do not free
++	 */
++	if (conn->login_ctask == ctask)
++		return;
++
+ 	__kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*));
+ 
+-	if (sc->scsi_done)
+-		sc->scsi_done(sc);
++	if (conn->ping_ctask == ctask)
++		conn->ping_ctask = NULL;
++
++	if (sc) {
++		ctask->sc = NULL;
++		/* SCSI eh reuses commands to verify us */
++		sc->SCp.ptr = NULL;
++		/*
++		 * queue command may call this to free the task, but
++		 * not have setup the sc callback
++		 */
++		if (sc->scsi_done)
++			sc->scsi_done(sc);
++	}
+ }
+ 
+ static void __iscsi_get_ctask(struct iscsi_cmd_task *ctask)
+@@ -356,6 +373,16 @@ static void __iscsi_put_ctask(struct iscsi_cmd_task *ctask)
+ 		iscsi_complete_command(ctask);
+ }
+ 
++void iscsi_put_ctask(struct iscsi_cmd_task *ctask)
++{
++	struct iscsi_session *session = ctask->conn->session;
++
++	spin_lock_bh(&session->lock);
++	__iscsi_put_ctask(ctask);
++	spin_unlock_bh(&session->lock);
++}
++EXPORT_SYMBOL_GPL(iscsi_put_ctask);
++
+ /*
+  * session lock must be held
+  */
+@@ -375,47 +402,28 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 		 */
+ 		conn->session->queued_cmdsn--;
+ 	else
+-		conn->session->tt->cleanup_cmd_task(conn, ctask);
++		conn->session->tt->cleanup_task(conn, ctask);
+ 
+ 	sc->result = err;
++
+ 	if (!scsi_bidi_cmnd(sc))
+ 		scsi_set_resid(sc, scsi_bufflen(sc));
+ 	else {
+ 		scsi_out(sc)->resid = scsi_out(sc)->length;
+ 		scsi_in(sc)->resid = scsi_in(sc)->length;
+ 	}
++
+ 	if (conn->ctask == ctask)
+ 		conn->ctask = NULL;
+ 	/* release ref from queuecommand */
+ 	__iscsi_put_ctask(ctask);
+ }
+ 
+-/**
+- * iscsi_free_mgmt_task - return mgmt task back to pool
+- * @conn: iscsi connection
+- * @mtask: mtask
+- *
+- * Must be called with session lock.
+- */
+-void iscsi_free_mgmt_task(struct iscsi_conn *conn,
+-			  struct iscsi_mgmt_task *mtask)
+-{
+-	list_del_init(&mtask->running);
+-	if (conn->login_mtask == mtask)
+-		return;
+-
+-	if (conn->ping_mtask == mtask)
+-		conn->ping_mtask = NULL;
+-	__kfifo_put(conn->session->mgmtpool.queue,
+-		    (void*)&mtask, sizeof(void*));
+-}
+-EXPORT_SYMBOL_GPL(iscsi_free_mgmt_task);
+-
+-static int iscsi_prep_mtask(struct iscsi_conn *conn,
+-			    struct iscsi_mgmt_task *mtask)
++static int iscsi_prep_mgmt_task(struct iscsi_conn *conn,
++				struct iscsi_cmd_task *ctask)
+ {
+ 	struct iscsi_session *session = conn->session;
+-	struct iscsi_hdr *hdr = mtask->hdr;
++	struct iscsi_hdr *hdr = (struct iscsi_hdr *)ctask->hdr;
+ 	struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr;
+ 
+ 	if (conn->session->state == ISCSI_STATE_LOGGING_OUT)
+@@ -429,7 +437,7 @@ static int iscsi_prep_mtask(struct iscsi_conn *conn,
+ 	 */
+ 	nop->cmdsn = cpu_to_be32(session->cmdsn);
+ 	if (hdr->itt != RESERVED_ITT) {
+-		hdr->itt = build_itt(mtask->itt, session->age);
++		hdr->itt = build_itt(ctask->itt, session->age);
+ 		/*
+ 		 * TODO: We always use immediate, so we never hit this.
+ 		 * If we start to send tmfs or nops as non-immediate then
+@@ -442,25 +450,25 @@ static int iscsi_prep_mtask(struct iscsi_conn *conn,
+ 		}
+ 	}
+ 
+-	if (session->tt->init_mgmt_task)
+-		session->tt->init_mgmt_task(conn, mtask);
++	if (session->tt->init_task)
++		session->tt->init_task(ctask);
+ 
+ 	if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT)
+ 		session->state = ISCSI_STATE_LOGGING_OUT;
+ 
+-	list_move_tail(&mtask->running, &conn->mgmt_run_list);
++	list_move_tail(&ctask->running, &conn->mgmt_run_list);
+ 	debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n",
+ 		   hdr->opcode & ISCSI_OPCODE_MASK, hdr->itt,
+-		   mtask->data_count);
++		   ctask->data_count);
+ 	return 0;
+ }
+ 
+-static struct iscsi_mgmt_task *
++static struct iscsi_cmd_task *
+ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		      char *data, uint32_t data_size)
+ {
+ 	struct iscsi_session *session = conn->session;
+-	struct iscsi_mgmt_task *mtask;
++	struct iscsi_cmd_task *ctask;
+ 
+ 	if (session->state == ISCSI_STATE_TERMINATE)
+ 		return NULL;
+@@ -470,48 +478,56 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		/*
+ 		 * Login and Text are sent serially, in
+ 		 * request-followed-by-response sequence.
+-		 * Same mtask can be used. Same ITT must be used.
+-		 * Note that login_mtask is preallocated at conn_create().
++		 * Same task can be used. Same ITT must be used.
++		 * Note that login_task is preallocated at conn_create().
+ 		 */
+-		mtask = conn->login_mtask;
++		ctask = conn->login_ctask;
+ 	else {
+ 		BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
+ 		BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
+ 
+-		if (!__kfifo_get(session->mgmtpool.queue,
+-				 (void*)&mtask, sizeof(void*)))
++		if (!__kfifo_get(session->cmdpool.queue,
++				 (void*)&ctask, sizeof(void*)))
+ 			return NULL;
+ 
+ 		if ((hdr->opcode == (ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE)) &&
+ 		     hdr->ttt == RESERVED_ITT) {
+-			conn->ping_mtask = mtask;
++			conn->ping_ctask = ctask;
+ 			conn->last_ping = jiffies;
+ 		}
+ 	}
++	/*
++	 * released in complete pdu for task we expect a response for, and
++	 * released by the lld when it has transmitted the task for
++	 * pdus we do not expect a response for.
++	 */
++	atomic_set(&ctask->refcount, 1);
++	ctask->conn = conn;
++	ctask->sc = NULL;
+ 
+ 	if (data_size) {
+-		memcpy(mtask->data, data, data_size);
+-		mtask->data_count = data_size;
++		memcpy(ctask->data, data, data_size);
++		ctask->data_count = data_size;
+ 	} else
+-		mtask->data_count = 0;
++		ctask->data_count = 0;
+ 
+-	memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr));
+-	INIT_LIST_HEAD(&mtask->running);
+-	list_add_tail(&mtask->running, &conn->mgmtqueue);
++	memcpy(ctask->hdr, hdr, sizeof(struct iscsi_hdr));
++	INIT_LIST_HEAD(&ctask->running);
++	list_add_tail(&ctask->running, &conn->mgmtqueue);
+ 
+ 	if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) {
+-		if (iscsi_prep_mtask(conn, mtask)) {
+-			iscsi_free_mgmt_task(conn, mtask);
++		if (iscsi_prep_mgmt_task(conn, ctask)) {
++			__iscsi_put_ctask(ctask);
+ 			return NULL;
+ 		}
+ 
+-		if (session->tt->xmit_mgmt_task(conn, mtask))
+-			mtask = NULL;
++		if (session->tt->xmit_task(ctask))
++			ctask = NULL;
+ 
+ 	} else
+ 		scsi_queue_work(conn->session->host, &conn->xmitwork);
+ 
+-	return mtask;
++	return ctask;
+ }
+ 
+ int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
+@@ -538,7 +554,7 @@ EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu);
+  * @datalen: len of buffer
+  *
+  * iscsi_cmd_rsp sets up the scsi_cmnd fields based on the PDU and
+- * then completes the command and task.
++ * then completes the command and ctask.
+  **/
+ static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			       struct iscsi_cmd_task *ctask, char *data,
+@@ -634,9 +650,9 @@ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
+ {
+         struct iscsi_nopout hdr;
+-	struct iscsi_mgmt_task *mtask;
++	struct iscsi_cmd_task *ctask;
+ 
+-	if (!rhdr && conn->ping_mtask)
++	if (!rhdr && conn->ping_ctask)
+ 		return;
+ 
+ 	memset(&hdr, 0, sizeof(struct iscsi_nopout));
+@@ -650,8 +666,8 @@ static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
+ 	} else
+ 		hdr.ttt = RESERVED_ITT;
+ 
+-	mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0);
+-	if (!mtask)
++	ctask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0);
++	if (!ctask)
+ 		iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n");
+ }
+ 
+@@ -697,7 +713,6 @@ static int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	struct iscsi_session *session = conn->session;
+ 	int opcode = hdr->opcode & ISCSI_OPCODE_MASK, rc = 0;
+ 	struct iscsi_cmd_task *ctask;
+-	struct iscsi_mgmt_task *mtask;
+ 	uint32_t itt;
+ 
+ 	conn->last_recv = jiffies;
+@@ -710,93 +725,10 @@ static int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	else
+ 		itt = ~0U;
+ 
+-	if (itt < session->cmds_max) {
+-		ctask = session->cmds[itt];
+-
+-		debug_scsi("cmdrsp [op 0x%x cid %d itt 0x%x len %d]\n",
+-			   opcode, conn->id, ctask->itt, datalen);
+-
+-		switch(opcode) {
+-		case ISCSI_OP_SCSI_CMD_RSP:
+-			BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
+-			iscsi_scsi_cmd_rsp(conn, hdr, ctask, data,
+-					   datalen);
+-			break;
+-		case ISCSI_OP_SCSI_DATA_IN:
+-			BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
+-			if (hdr->flags & ISCSI_FLAG_DATA_STATUS) {
+-				conn->scsirsp_pdus_cnt++;
+-				__iscsi_put_ctask(ctask);
+-			}
+-			break;
+-		case ISCSI_OP_R2T:
+-			/* LLD handles this for now */
+-			break;
+-		default:
+-			rc = ISCSI_ERR_BAD_OPCODE;
+-			break;
+-		}
+-	} else if (itt >= ISCSI_MGMT_ITT_OFFSET &&
+-		   itt < ISCSI_MGMT_ITT_OFFSET + session->mgmtpool_max) {
+-		mtask = session->mgmt_cmds[itt - ISCSI_MGMT_ITT_OFFSET];
+-
+-		debug_scsi("immrsp [op 0x%x cid %d itt 0x%x len %d]\n",
+-			   opcode, conn->id, mtask->itt, datalen);
++	debug_scsi("[op 0x%x cid %d itt 0x%x len %d]\n",
++		   opcode, conn->id, itt, datalen);
+ 
+-		iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
+-		switch(opcode) {
+-		case ISCSI_OP_LOGOUT_RSP:
+-			if (datalen) {
+-				rc = ISCSI_ERR_PROTO;
+-				break;
+-			}
+-			conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
+-			/* fall through */
+-		case ISCSI_OP_LOGIN_RSP:
+-		case ISCSI_OP_TEXT_RSP:
+-			/*
+-			 * login related PDU's exp_statsn is handled in
+-			 * userspace
+-			 */
+-			if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen))
+-				rc = ISCSI_ERR_CONN_FAILED;
+-			iscsi_free_mgmt_task(conn, mtask);
+-			break;
+-		case ISCSI_OP_SCSI_TMFUNC_RSP:
+-			if (datalen) {
+-				rc = ISCSI_ERR_PROTO;
+-				break;
+-			}
+-
+-			iscsi_tmf_rsp(conn, hdr);
+-			iscsi_free_mgmt_task(conn, mtask);
+-			break;
+-		case ISCSI_OP_NOOP_IN:
+-			if (hdr->ttt != cpu_to_be32(ISCSI_RESERVED_TAG) ||
+-			    datalen) {
+-				rc = ISCSI_ERR_PROTO;
+-				break;
+-			}
+-			conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
+-
+-			if (conn->ping_mtask != mtask) {
+-				/*
+-				 * If this is not in response to one of our
+-				 * nops then it must be from userspace.
+-				 */
+-				if (iscsi_recv_pdu(conn->cls_conn, hdr, data,
+-						   datalen))
+-					rc = ISCSI_ERR_CONN_FAILED;
+-			} else
+-				mod_timer(&conn->transport_timer,
+-					  jiffies + conn->recv_timeout);
+-			iscsi_free_mgmt_task(conn, mtask);
+-			break;
+-		default:
+-			rc = ISCSI_ERR_BAD_OPCODE;
+-			break;
+-		}
+-	} else if (itt == ~0U) {
++	if (itt == ~0U) {
+ 		iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
+ 
+ 		switch(opcode) {
+@@ -823,9 +755,88 @@ static int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			rc = ISCSI_ERR_BAD_OPCODE;
+ 			break;
+ 		}
+-	} else
+-		rc = ISCSI_ERR_BAD_ITT;
++		goto out;
++	}
++
++	ctask = session->cmds[itt];
++	switch(opcode) {
++	case ISCSI_OP_SCSI_CMD_RSP:
++		if (!ctask->sc) {
++			rc = ISCSI_ERR_NO_SCSI_CMD;
++			break;
++		}
++		BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
++		iscsi_scsi_cmd_rsp(conn, hdr, ctask, data, datalen);
++		break;
++	case ISCSI_OP_SCSI_DATA_IN:
++		if (!ctask->sc) {
++			rc = ISCSI_ERR_NO_SCSI_CMD;
++			break;
++		}
++		BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
++		if (hdr->flags & ISCSI_FLAG_DATA_STATUS) {
++			conn->scsirsp_pdus_cnt++;
++			iscsi_update_cmdsn(session,
++					   (struct iscsi_nopin*) hdr);
++			__iscsi_put_ctask(ctask);
++		}
++		break;
++	case ISCSI_OP_R2T:
++		/* LLD handles this for now */
++		break;
++	case ISCSI_OP_LOGOUT_RSP:
++		iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
++		if (datalen) {
++			rc = ISCSI_ERR_PROTO;
++			break;
++		}
++		conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
++		goto recv_pdu;
++	case ISCSI_OP_LOGIN_RSP:
++	case ISCSI_OP_TEXT_RSP:
++		iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
++		/*
++		 * login related PDU's exp_statsn is handled in
++		 * userspace
++		 */
++		goto recv_pdu;
++	case ISCSI_OP_SCSI_TMFUNC_RSP:
++		iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
++		if (datalen) {
++			rc = ISCSI_ERR_PROTO;
++			break;
++		}
++
++		iscsi_tmf_rsp(conn, hdr);
++		__iscsi_put_ctask(ctask);
++		break;
++	case ISCSI_OP_NOOP_IN:
++		iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
++		if (hdr->ttt != cpu_to_be32(ISCSI_RESERVED_TAG) || datalen) {
++			rc = ISCSI_ERR_PROTO;
++			break;
++		}
++		conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
++
++		if (conn->ping_ctask != ctask)
++			/*
++			 * If this is not in response to one of our
++			 * nops then it must be from userspace.
++			 */
++			goto recv_pdu;
++		__iscsi_put_ctask(ctask);
++		break;
++	default:
++		rc = ISCSI_ERR_BAD_OPCODE;
++		break;
++	}
+ 
++out:
++	return rc;
++recv_pdu:
++	if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen))
++		rc = ISCSI_ERR_CONN_FAILED;
++	__iscsi_put_ctask(ctask);
+ 	return rc;
+ }
+ 
+@@ -845,6 +856,7 @@ int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt)
+ {
+ 	struct iscsi_session *session = conn->session;
+ 	struct iscsi_cmd_task *ctask;
++	uint32_t i;
+ 
+ 	if (itt == RESERVED_ITT)
+ 		return 0;
+@@ -858,25 +870,22 @@ int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt)
+ 		return ISCSI_ERR_BAD_ITT;
+ 	}
+ 
+-	if (itt < session->cmds_max) {
+-		ctask = session->cmds[itt];
+-
+-		if (!ctask->sc) {
+-			iscsi_conn_printk(KERN_INFO, conn, "dropping ctask "
+-					  "with itt 0x%x\n", ctask->itt);
+-			/* force drop */
+-			return ISCSI_ERR_NO_SCSI_CMD;
+-		}
+-
+-		if (ctask->sc->SCp.phase != session->age) {
+-			iscsi_conn_printk(KERN_ERR, conn,
+-					  "iscsi: ctask's session age %d, "
+-					  "expected %d\n", ctask->sc->SCp.phase,
+-					  session->age);
+-			return ISCSI_ERR_SESSION_FAILED;
+-		}
++	i = get_itt(itt);
++	if (i >= session->cmds_max) {
++		iscsi_conn_printk(KERN_ERR, conn,
++				  "received invalid itt index %u (max cmds "
++				   "%u.\n", i, session->cmds_max);
++		return ISCSI_ERR_BAD_ITT;
+ 	}
+ 
++	ctask = session->cmds[i];
++	if (ctask->sc && ctask->sc->SCp.phase != session->age) {
++		iscsi_conn_printk(KERN_ERR, conn,
++				  "iscsi: ctask's session age %d, "
++				  "expected %d\n", ctask->sc->SCp.phase,
++				  session->age);
++		return ISCSI_ERR_SESSION_FAILED;
++	}
+ 	return 0;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_verify_itt);
+@@ -929,20 +938,6 @@ void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_conn_failure);
+ 
+-static int iscsi_xmit_mtask(struct iscsi_conn *conn)
+-{
+-	int rc;
+-
+-	spin_unlock_bh(&conn->session->lock);
+-	rc = conn->session->tt->xmit_mgmt_task(conn, conn->mtask);
+-	spin_lock_bh(&conn->session->lock);
+-	if (rc)
+-		return rc;
+-	/* done with this in-progress mtask */
+-	conn->mtask = NULL;
+-	return 0;
+-}
+-
+ static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn)
+ {
+ 	struct iscsi_session *session = conn->session;
+@@ -967,7 +962,7 @@ static int iscsi_xmit_ctask(struct iscsi_conn *conn)
+ 
+ 	__iscsi_get_ctask(ctask);
+ 	spin_unlock_bh(&conn->session->lock);
+-	rc = conn->session->tt->xmit_cmd_task(conn, ctask);
++	rc = conn->session->tt->xmit_task(ctask);
+ 	spin_lock_bh(&conn->session->lock);
+ 	__iscsi_put_ctask(ctask);
+ 	if (!rc)
+@@ -1015,12 +1010,6 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 
+ 	if (conn->ctask) {
+ 		rc = iscsi_xmit_ctask(conn);
+-		if (rc)
+-			goto again;
+-	}
+-
+-	if (conn->mtask) {
+-		rc = iscsi_xmit_mtask(conn);
+ 	        if (rc)
+ 		        goto again;
+ 	}
+@@ -1032,14 +1021,14 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 	 */
+ check_mgmt:
+ 	while (!list_empty(&conn->mgmtqueue)) {
+-		conn->mtask = list_entry(conn->mgmtqueue.next,
+-					 struct iscsi_mgmt_task, running);
+-		if (iscsi_prep_mtask(conn, conn->mtask)) {
+-			iscsi_free_mgmt_task(conn, conn->mtask);
+-			conn->mtask = NULL;
++		conn->ctask = list_entry(conn->mgmtqueue.next,
++					 struct iscsi_cmd_task, running);
++		if (iscsi_prep_mgmt_task(conn, conn->ctask)) {
++			__iscsi_put_ctask(conn->ctask);
++			conn->ctask = NULL;
+ 			continue;
+ 		}
+-		rc = iscsi_xmit_mtask(conn);
++		rc = iscsi_xmit_ctask(conn);
+ 		if (rc)
+ 			goto again;
+ 	}
+@@ -1224,7 +1213,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 			iscsi_complete_command(ctask);
+ 			goto fault;
+ 		}
+-		if (session->tt->xmit_cmd_task(conn, ctask)) {
++		if (session->tt->xmit_task(ctask)) {
+ 			sc->scsi_done = NULL;
+ 			iscsi_complete_command(ctask);
+ 			reason = FAILURE_SESSION_NOT_READY;
+@@ -1347,16 +1336,16 @@ static void iscsi_tmf_timedout(unsigned long data)
+ 	spin_unlock(&session->lock);
+ }
+ 
+-static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn,
++static int iscsi_exec_ctask_mgmt_fn(struct iscsi_conn *conn,
+ 				   struct iscsi_tm *hdr, int age,
+ 				   int timeout)
+ {
+ 	struct iscsi_session *session = conn->session;
+-	struct iscsi_mgmt_task *mtask;
++	struct iscsi_cmd_task *ctask;
+ 
+-	mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr,
++	ctask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr,
+ 				      NULL, 0);
+-	if (!mtask) {
++	if (!ctask) {
+ 		spin_unlock_bh(&session->lock);
+ 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ 		spin_lock_bh(&session->lock);
+@@ -1390,7 +1379,7 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn,
+ 
+ 	mutex_lock(&session->eh_mutex);
+ 	spin_lock_bh(&session->lock);
+-	/* if the session drops it will clean up the mtask */
++	/* if the session drops it will clean up the ctask */
+ 	if (age != session->age ||
+ 	    session->state != ISCSI_STATE_LOGGED_IN)
+ 		return -ENOTCONN;
+@@ -1497,7 +1486,7 @@ static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
+ 			   jiffies))
+ 		rc = EH_RESET_TIMER;
+ 	/* if in the middle of checking the transport then give us more time */
+-	if (conn->ping_mtask)
++	if (conn->ping_ctask)
+ 		rc = EH_RESET_TIMER;
+ done:
+ 	spin_unlock(&session->lock);
+@@ -1521,7 +1510,7 @@ static void iscsi_check_transport_timeouts(unsigned long data)
+ 
+ 	recv_timeout *= HZ;
+ 	last_recv = conn->last_recv;
+-	if (conn->ping_mtask &&
++	if (conn->ping_ctask &&
+ 	    time_before_eq(conn->last_ping + (conn->ping_timeout * HZ),
+ 			   jiffies)) {
+ 		iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs "
+@@ -1547,7 +1536,7 @@ static void iscsi_check_transport_timeouts(unsigned long data)
+ 	spin_unlock(&session->lock);
+ }
+ 
+-static void iscsi_prep_abort_task_pdu(struct iscsi_cmd_task *ctask,
++static void iscsi_prep_abort_ctask_pdu(struct iscsi_cmd_task *ctask,
+ 				      struct iscsi_tm *hdr)
+ {
+ 	memset(hdr, 0, sizeof(*hdr));
+@@ -1619,9 +1608,9 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 	conn->tmf_state = TMF_QUEUED;
+ 
+ 	hdr = &conn->tmhdr;
+-	iscsi_prep_abort_task_pdu(ctask, hdr);
++	iscsi_prep_abort_ctask_pdu(ctask, hdr);
+ 
+-	if (iscsi_exec_task_mgmt_fn(conn, hdr, age, session->abort_timeout)) {
++	if (iscsi_exec_ctask_mgmt_fn(conn, hdr, age, session->abort_timeout)) {
+ 		rc = FAILED;
+ 		goto failed;
+ 	}
+@@ -1631,7 +1620,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 		spin_unlock_bh(&session->lock);
+ 		iscsi_suspend_tx(conn);
+ 		/*
+-		 * clean up task if aborted. grab the recv lock as a writer
++		 * clean up ctask if aborted. grab the recv lock as a writer
+ 		 */
+ 		write_lock_bh(conn->recv_lock);
+ 		spin_lock(&session->lock);
+@@ -1716,7 +1705,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc)
+ 	hdr = &conn->tmhdr;
+ 	iscsi_prep_lun_reset_pdu(sc, hdr);
+ 
+-	if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age,
++	if (iscsi_exec_ctask_mgmt_fn(conn, hdr, session->age,
+ 				    session->lu_reset_timeout)) {
+ 		rc = FAILED;
+ 		goto unlock;
+@@ -1897,8 +1886,7 @@ EXPORT_SYMBOL_GPL(iscsi_host_free);
+  * @iscsit: iscsi transport template
+  * @shost: scsi host
+  * @cmds_max: session can queue
+- * @cmd_task_size: LLD ctask private data size
+- * @mgmt_task_size: LLD mtask private data size
++ * @cmd_ctask_size: LLD ctask private data size
+  * @initial_cmdsn: initial CmdSN
+  *
+  * This can be used by software iscsi_transports that allocate
+@@ -1906,22 +1894,26 @@ EXPORT_SYMBOL_GPL(iscsi_host_free);
+  */
+ struct iscsi_cls_session *
+ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
+-		    uint16_t cmds_max, int cmd_task_size, int mgmt_task_size,
++		    uint16_t scsi_cmds_max, int cmd_ctask_size,
+ 		    uint32_t initial_cmdsn)
+ {
+ 	struct iscsi_session *session;
+ 	struct iscsi_cls_session *cls_session;
+-	int cmd_i;
++	int cmd_i, cmds_max;
+ 
+-	if (!is_power_of_2(cmds_max) || cmds_max >= ISCSI_MGMT_ITT_OFFSET ||
+-	    cmds_max < 2) {
+-		if (cmds_max != 0)
+-			printk(KERN_ERR "iscsi: invalid can_queue of %d. "
+-			       "can_queue must be a power of 2 and between "
+-			       "2 and %d - setting to %d.\n", cmds_max,
+-			       ISCSI_MGMT_ITT_OFFSET, ISCSI_DEF_XMIT_CMDS_MAX);
+-		cmds_max = ISCSI_DEF_XMIT_CMDS_MAX;
++	/*
++	 * The iscsi layer needs some ctasks for nop handling and tmfs.
++	 */
++	if (scsi_cmds_max < 1)
++		scsi_cmds_max = ISCSI_MGMT_CMDS_MAX;
++	if ((scsi_cmds_max + ISCSI_MGMT_CMDS_MAX) >= ISCSI_MGMT_ITT_OFFSET) {
++		printk(KERN_ERR "iscsi: invalid can_queue of %d. "
++		       "can_queue must be less than %d.\n",
++		       scsi_cmds_max,
++		       ISCSI_MGMT_ITT_OFFSET - ISCSI_MGMT_CMDS_MAX);
++		scsi_cmds_max = ISCSI_DEF_XMIT_CMDS_MAX;
+ 	}
++	cmds_max = roundup_pow_of_two(scsi_cmds_max + ISCSI_MGMT_CMDS_MAX);
+ 
+ 	cls_session = iscsi_alloc_session(shost, iscsit,
+ 					  sizeof(struct iscsi_session));
+@@ -1934,7 +1926,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
+ 	session->fast_abort = 1;
+ 	session->lu_reset_timeout = 15;
+ 	session->abort_timeout = 10;
+-	session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
++	session->scsi_cmds_max = scsi_cmds_max;
+ 	session->cmds_max = cmds_max;
+ 	session->queued_cmdsn = session->cmdsn = initial_cmdsn;
+ 	session->exp_cmdsn = initial_cmdsn + 1;
+@@ -1947,36 +1939,19 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
+ 	/* initialize SCSI PDU commands pool */
+ 	if (iscsi_pool_init(&session->cmdpool, session->cmds_max,
+ 			    (void***)&session->cmds,
+-			    cmd_task_size + sizeof(struct iscsi_cmd_task)))
++			    cmd_ctask_size + sizeof(struct iscsi_cmd_task)))
+ 		goto cmdpool_alloc_fail;
+ 
+ 	/* pre-format cmds pool with ITT */
+ 	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
+ 		struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
+ 
+-		if (cmd_task_size)
++		if (cmd_ctask_size)
+ 			ctask->dd_data = &ctask[1];
+ 		ctask->itt = cmd_i;
+ 		INIT_LIST_HEAD(&ctask->running);
+ 	}
+ 
+-	/* initialize immediate command pool */
+-	if (iscsi_pool_init(&session->mgmtpool, session->mgmtpool_max,
+-			   (void***)&session->mgmt_cmds,
+-			   mgmt_task_size + sizeof(struct iscsi_mgmt_task)))
+-		goto mgmtpool_alloc_fail;
+-
+-
+-	/* pre-format immediate cmds pool with ITT */
+-	for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) {
+-		struct iscsi_mgmt_task *mtask = session->mgmt_cmds[cmd_i];
+-
+-		if (mgmt_task_size)
+-			mtask->dd_data = &mtask[1];
+-		mtask->itt = ISCSI_MGMT_ITT_OFFSET + cmd_i;
+-		INIT_LIST_HEAD(&mtask->running);
+-	}
+-
+ 	if (!try_module_get(iscsit->owner))
+ 		goto module_get_fail;
+ 
+@@ -1987,8 +1962,6 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
+ cls_session_fail:
+ 	module_put(iscsit->owner);
+ module_get_fail:
+-	iscsi_pool_free(&session->mgmtpool);
+-mgmtpool_alloc_fail:
+ 	iscsi_pool_free(&session->cmdpool);
+ cmdpool_alloc_fail:
+ 	iscsi_free_session(cls_session);
+@@ -2008,7 +1981,6 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+ 	struct iscsi_session *session = cls_session->dd_data;
+ 	struct module *owner = cls_session->transport->owner;
+ 
+-	iscsi_pool_free(&session->mgmtpool);
+ 	iscsi_pool_free(&session->cmdpool);
+ 
+ 	kfree(session->password);
+@@ -2063,30 +2035,30 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size,
+ 	INIT_LIST_HEAD(&conn->requeue);
+ 	INIT_WORK(&conn->xmitwork, iscsi_xmitworker);
+ 
+-	/* allocate login_mtask used for the login/text sequences */
++	/* allocate login_ctask used for the login/text sequences */
+ 	spin_lock_bh(&session->lock);
+-	if (!__kfifo_get(session->mgmtpool.queue,
+-                         (void*)&conn->login_mtask,
++	if (!__kfifo_get(session->cmdpool.queue,
++                         (void*)&conn->login_ctask,
+ 			 sizeof(void*))) {
+ 		spin_unlock_bh(&session->lock);
+-		goto login_mtask_alloc_fail;
++		goto login_ctask_alloc_fail;
+ 	}
+ 	spin_unlock_bh(&session->lock);
+ 
+ 	data = kmalloc(ISCSI_DEF_MAX_RECV_SEG_LEN, GFP_KERNEL);
+ 	if (!data)
+-		goto login_mtask_data_alloc_fail;
+-	conn->login_mtask->data = conn->data = data;
++		goto login_ctask_data_alloc_fail;
++	conn->login_ctask->data = conn->data = data;
+ 
+ 	init_timer(&conn->tmf_timer);
+ 	init_waitqueue_head(&conn->ehwait);
+ 
+ 	return cls_conn;
+ 
+-login_mtask_data_alloc_fail:
+-	__kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask,
++login_ctask_data_alloc_fail:
++	__kfifo_put(session->cmdpool.queue, (void*)&conn->login_ctask,
+ 		    sizeof(void*));
+-login_mtask_alloc_fail:
++login_ctask_alloc_fail:
+ 	iscsi_destroy_conn(cls_conn);
+ 	return NULL;
+ }
+@@ -2146,7 +2118,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
+ 	spin_lock_bh(&session->lock);
+ 	kfree(conn->data);
+ 	kfree(conn->persistent_address);
+-	__kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask,
++	__kfifo_put(session->cmdpool.queue, (void*)&conn->login_ctask,
+ 		    sizeof(void*));
+ 	if (session->leadconn == conn)
+ 		session->leadconn = NULL;
+@@ -2227,21 +2199,23 @@ EXPORT_SYMBOL_GPL(iscsi_conn_start);
+ static void
+ flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn)
+ {
+-	struct iscsi_mgmt_task *mtask, *tmp;
++	struct iscsi_cmd_task *ctask, *tmp;
+ 
+ 	/* handle pending */
+-	list_for_each_entry_safe(mtask, tmp, &conn->mgmtqueue, running) {
+-		debug_scsi("flushing pending mgmt task itt 0x%x\n", mtask->itt);
+-		iscsi_free_mgmt_task(conn, mtask);
++	list_for_each_entry_safe(ctask, tmp, &conn->mgmtqueue, running) {
++		debug_scsi("flushing pending mgmt ctask itt 0x%x\n", ctask->itt);
++		/* release ref from prep ctask */
++		__iscsi_put_ctask(ctask);
+ 	}
+ 
+ 	/* handle running */
+-	list_for_each_entry_safe(mtask, tmp, &conn->mgmt_run_list, running) {
+-		debug_scsi("flushing running mgmt task itt 0x%x\n", mtask->itt);
+-		iscsi_free_mgmt_task(conn, mtask);
++	list_for_each_entry_safe(ctask, tmp, &conn->mgmt_run_list, running) {
++		debug_scsi("flushing running mgmt ctask itt 0x%x\n", ctask->itt);
++		/* release ref from prep ctask */
++		__iscsi_put_ctask(ctask);
+ 	}
+ 
+-	conn->mtask = NULL;
++	conn->ctask = NULL;
+ }
+ 
+ static void iscsi_start_session_recovery(struct iscsi_session *session,
+@@ -2272,7 +2246,7 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ 
+ 	/*
+ 	 * When this is called for the in_login state, we only want to clean
+-	 * up the login task and connection. We do not need to block and set
++	 * up the login ctask and connection. We do not need to block and set
+ 	 * the recovery state again
+ 	 */
+ 	if (flag == STOP_CONN_TERM)
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 9be6a70faff5..d1c36759b350 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -85,18 +85,6 @@ enum {
+ 	ISCSI_DIGEST_SIZE = sizeof(__u32),
+ };
+ 
+-struct iscsi_mgmt_task {
+-	/*
+-	 * Becuae LLDs allocate their hdr differently, this is a pointer to
+-	 * that storage. It must be setup at session creation time.
+-	 */
+-	struct iscsi_hdr	*hdr;
+-	char			*data;		/* mgmt payload */
+-	unsigned		data_count;	/* counts data to be sent */
+-	uint32_t		itt;		/* this ITT */
+-	void			*dd_data;	/* driver/transport data */
+-	struct list_head	running;
+-};
+ 
+ enum {
+ 	ISCSI_TASK_COMPLETED,
+@@ -121,6 +109,7 @@ struct iscsi_cmd_task {
+ 	/* offset in unsolicited stream (bytes); */
+ 	unsigned		unsol_offset;
+ 	unsigned		data_count;	/* remaining Data-Out */
++	char			*data;		/* mgmt payload */
+ 	struct scsi_cmnd	*sc;		/* associated SCSI cmd*/
+ 	struct iscsi_conn	*conn;		/* used connection    */
+ 
+@@ -162,7 +151,7 @@ struct iscsi_conn {
+ 	unsigned long		last_ping;
+ 	int			ping_timeout;
+ 	int			recv_timeout;
+-	struct iscsi_mgmt_task	*ping_mtask;
++	struct iscsi_cmd_task 	*ping_ctask;
+ 
+ 	/* iSCSI connection-wide sequencing */
+ 	uint32_t		exp_statsn;
+@@ -178,9 +167,8 @@ struct iscsi_conn {
+ 	 * should always fit in this buffer
+ 	 */
+ 	char			*data;
+-	struct iscsi_mgmt_task	*login_mtask;	/* mtask used for login/text */
+-	struct iscsi_mgmt_task	*mtask;		/* xmit mtask in progress */
+-	struct iscsi_cmd_task	*ctask;		/* xmit ctask in progress */
++	struct iscsi_cmd_task 	*login_ctask;	/* mtask used for login/text */
++	struct iscsi_cmd_task	*ctask;		/* xmit task in progress */
+ 
+ 	/* xmit */
+ 	struct list_head	mgmtqueue;	/* mgmt (control) xmit queue */
+@@ -295,12 +283,10 @@ struct iscsi_session {
+ 	int			state;		/* session state           */
+ 	int			age;		/* counts session re-opens */
+ 
++	int			scsi_cmds_max; 	/* max scsi commands */
+ 	int			cmds_max;	/* size of cmds array */
+ 	struct iscsi_cmd_task	**cmds;		/* Original Cmds arr */
+ 	struct iscsi_pool	cmdpool;	/* PDU's pool */
+-	int			mgmtpool_max;	/* size of mgmt array */
+-	struct iscsi_mgmt_task	**mgmt_cmds;	/* Original mgmt arr */
+-	struct iscsi_pool	mgmtpool;	/* Mgmt PDU's pool */
+ };
+ 
+ struct iscsi_host {
+@@ -345,7 +331,7 @@ extern void iscsi_host_free(struct Scsi_Host *shost);
+  */
+ extern struct iscsi_cls_session *
+ iscsi_session_setup(struct iscsi_transport *, struct Scsi_Host *shost,
+-		    uint16_t, int, int, uint32_t);
++		    uint16_t, int, uint32_t);
+ extern void iscsi_session_teardown(struct iscsi_cls_session *);
+ extern void iscsi_session_recovery_timedout(struct iscsi_cls_session *);
+ extern int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
+@@ -388,8 +374,7 @@ extern int iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *,
+ extern int iscsi_verify_itt(struct iscsi_conn *, itt_t);
+ extern struct iscsi_cmd_task *iscsi_itt_to_ctask(struct iscsi_conn *, itt_t);
+ extern void iscsi_requeue_ctask(struct iscsi_cmd_task *ctask);
+-extern void iscsi_free_mgmt_task(struct iscsi_conn *conn,
+-				 struct iscsi_mgmt_task *mtask);
++extern void iscsi_put_ctask(struct iscsi_cmd_task *ctask);
+ 
+ /*
+  * generic helpers
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 4028f121d548..3f24503dfdf9 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -34,7 +34,6 @@ struct Scsi_Host;
+ struct iscsi_cls_conn;
+ struct iscsi_conn;
+ struct iscsi_cmd_task;
+-struct iscsi_mgmt_task;
+ struct sockaddr;
+ 
+ /**
+@@ -58,19 +57,22 @@ struct sockaddr;
+  * @stop_conn:		suspend/recover/terminate connection
+  * @send_pdu:		send iSCSI PDU, Login, Logout, NOP-Out, Reject, Text.
+  * @session_recovery_timedout: notify LLD a block during recovery timed out
+- * @init_cmd_task:	Initialize a iscsi_cmd_task and any internal structs.
+- *			Called from queuecommand with session lock held.
+- * @init_mgmt_task:	Initialize a iscsi_mgmt_task and any internal structs.
+- *			Called from iscsi_conn_send_generic with xmitmutex.
+- * @xmit_cmd_task:	Requests LLD to transfer cmd task. Returns 0 or the
++ * @init_task:		Initialize a iscsi_task and any internal structs.
++ *			When offloading the data path, this is called from
++ *			queuecommand with the session lock, or from the
++ *			iscsi_conn_send_pdu context with the session lock.
++ *			When not offloading the data path, this is called
++ *			from the scsi work queue without the session lock.
++ * @xmit_task		Requests LLD to transfer cmd task. Returns 0 or the
+  *			the number of bytes transferred on success, and -Exyz
+- *			value on error.
+- * @xmit_mgmt_task:	Requests LLD to transfer mgmt task. Returns 0 or the
+- *			the number of bytes transferred on success, and -Exyz
+- *			value on error.
+- * @cleanup_cmd_task:	requests LLD to fail cmd task. Called with xmitmutex
+- *			and session->lock after the connection has been
+- *			suspended and terminated during recovery. If called
++ *			value on error. When offloading the data path, this
++ *			is called from queuecommand with the session lock, or
++ *			from the iscsi_conn_send_pdu context with the session
++ *			lock. When not offloading the data path, this is called
++ *			from the scsi work queue without the session lock.
++ * @cleanup_task:	requests LLD to fail task. Called with session lock
++ *			and after the connection has been suspended and
++ *			terminated during recovery. If called
+  *			from abort task then connection is not suspended
+  *			or terminated but sk_callback_lock is held
+  *
+@@ -110,15 +112,10 @@ struct iscsi_transport {
+ 			 char *data, uint32_t data_size);
+ 	void (*get_stats) (struct iscsi_cls_conn *conn,
+ 			   struct iscsi_stats *stats);
+-	int (*init_cmd_task) (struct iscsi_cmd_task *ctask);
+-	void (*init_mgmt_task) (struct iscsi_conn *conn,
+-				struct iscsi_mgmt_task *mtask);
+-	int (*xmit_cmd_task) (struct iscsi_conn *conn,
+-			      struct iscsi_cmd_task *ctask);
+-	void (*cleanup_cmd_task) (struct iscsi_conn *conn,
+-				  struct iscsi_cmd_task *ctask);
+-	int (*xmit_mgmt_task) (struct iscsi_conn *conn,
+-			       struct iscsi_mgmt_task *mtask);
++	int (*init_task) (struct iscsi_cmd_task *task);
++	int (*xmit_task) (struct iscsi_cmd_task *task);
++	void (*cleanup_task) (struct iscsi_conn *conn,
++				  struct iscsi_cmd_task *task);
+ 	void (*session_recovery_timedout) (struct iscsi_cls_session *session);
+ 	int (*ep_connect) (struct sockaddr *dst_addr, int non_blocking,
+ 			   uint64_t *ep_handle);

commit 052d014485d2ce5bb7fa8dd0df875dafd1db77df
+Author: Mike Christie 
+Date:   Wed May 21 15:54:05 2008 -0500
+
+    [SCSI] libiscsi: modify libiscsi so it supports offloaded data paths
+    
+    This patch modifies libiscsi, so drivers like bnx2i and iser can execute
+    a command from queuecommand/send_pdu instead of having to be queued to
+    be run in a workq.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 4bc63c4b3c10..1e605de07cff 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -79,9 +79,11 @@ iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
+ 		 * xmit thread
+ 		 */
+ 		if (!list_empty(&session->leadconn->xmitqueue) ||
+-		    !list_empty(&session->leadconn->mgmtqueue))
+-			scsi_queue_work(session->host,
+-					&session->leadconn->xmitwork);
++		    !list_empty(&session->leadconn->mgmtqueue)) {
++			if (!(session->tt->caps & CAP_DATA_PATH_OFFLOAD))
++				scsi_queue_work(session->host,
++						&session->leadconn->xmitwork);
++		}
+ 	}
+ }
+ EXPORT_SYMBOL_GPL(iscsi_update_cmdsn);
+@@ -298,8 +300,12 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ 	WARN_ON(hdrlength >= 256);
+ 	hdr->hlength = hdrlength & 0xFF;
+ 
+-	if (conn->session->tt->init_cmd_task(conn->ctask))
+-		return EIO;
++	if (conn->session->tt->init_cmd_task &&
++	    conn->session->tt->init_cmd_task(ctask))
++		return -EIO;
++
++	ctask->state = ISCSI_TASK_RUNNING;
++	list_move_tail(&ctask->running, &conn->run_list);
+ 
+ 	conn->scsicmd_pdus_cnt++;
+ 	debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x "
+@@ -334,7 +340,9 @@ static void iscsi_complete_command(struct iscsi_cmd_task *ctask)
+ 		conn->ctask = NULL;
+ 	list_del_init(&ctask->running);
+ 	__kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*));
+-	sc->scsi_done(sc);
++
++	if (sc->scsi_done)
++		sc->scsi_done(sc);
+ }
+ 
+ static void __iscsi_get_ctask(struct iscsi_cmd_task *ctask)
+@@ -403,6 +411,50 @@ void iscsi_free_mgmt_task(struct iscsi_conn *conn,
+ }
+ EXPORT_SYMBOL_GPL(iscsi_free_mgmt_task);
+ 
++static int iscsi_prep_mtask(struct iscsi_conn *conn,
++			    struct iscsi_mgmt_task *mtask)
++{
++	struct iscsi_session *session = conn->session;
++	struct iscsi_hdr *hdr = mtask->hdr;
++	struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr;
++
++	if (conn->session->state == ISCSI_STATE_LOGGING_OUT)
++		return -ENOTCONN;
++
++	if (hdr->opcode != (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) &&
++	    hdr->opcode != (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE))
++		nop->exp_statsn = cpu_to_be32(conn->exp_statsn);
++	/*
++	 * pre-format CmdSN for outgoing PDU.
++	 */
++	nop->cmdsn = cpu_to_be32(session->cmdsn);
++	if (hdr->itt != RESERVED_ITT) {
++		hdr->itt = build_itt(mtask->itt, session->age);
++		/*
++		 * TODO: We always use immediate, so we never hit this.
++		 * If we start to send tmfs or nops as non-immediate then
++		 * we should start checking the cmdsn numbers for mgmt tasks.
++		 */
++		if (conn->c_stage == ISCSI_CONN_STARTED &&
++		    !(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
++			session->queued_cmdsn++;
++			session->cmdsn++;
++		}
++	}
++
++	if (session->tt->init_mgmt_task)
++		session->tt->init_mgmt_task(conn, mtask);
++
++	if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT)
++		session->state = ISCSI_STATE_LOGGING_OUT;
++
++	list_move_tail(&mtask->running, &conn->mgmt_run_list);
++	debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n",
++		   hdr->opcode & ISCSI_OPCODE_MASK, hdr->itt,
++		   mtask->data_count);
++	return 0;
++}
++
+ static struct iscsi_mgmt_task *
+ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		      char *data, uint32_t data_size)
+@@ -429,6 +481,12 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		if (!__kfifo_get(session->mgmtpool.queue,
+ 				 (void*)&mtask, sizeof(void*)))
+ 			return NULL;
++
++		if ((hdr->opcode == (ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE)) &&
++		     hdr->ttt == RESERVED_ITT) {
++			conn->ping_mtask = mtask;
++			conn->last_ping = jiffies;
++		}
+ 	}
+ 
+ 	if (data_size) {
+@@ -440,6 +498,19 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr));
+ 	INIT_LIST_HEAD(&mtask->running);
+ 	list_add_tail(&mtask->running, &conn->mgmtqueue);
++
++	if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) {
++		if (iscsi_prep_mtask(conn, mtask)) {
++			iscsi_free_mgmt_task(conn, mtask);
++			return NULL;
++		}
++
++		if (session->tt->xmit_mgmt_task(conn, mtask))
++			mtask = NULL;
++
++	} else
++		scsi_queue_work(conn->session->host, &conn->xmitwork);
++
+ 	return mtask;
+ }
+ 
+@@ -454,7 +525,6 @@ int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
+ 	if (!__iscsi_conn_send_pdu(conn, hdr, data, data_size))
+ 		err = -EPERM;
+ 	spin_unlock_bh(&session->lock);
+-	scsi_queue_work(session->host, &conn->xmitwork);
+ 	return err;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu);
+@@ -581,17 +651,8 @@ static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
+ 		hdr.ttt = RESERVED_ITT;
+ 
+ 	mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0);
+-	if (!mtask) {
++	if (!mtask)
+ 		iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n");
+-		return;
+-	}
+-
+-	/* only track our nops */
+-	if (!rhdr) {
+-		conn->ping_mtask = mtask;
+-		conn->last_ping = jiffies;
+-	}
+-	scsi_queue_work(conn->session->host, &conn->xmitwork);
+ }
+ 
+ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+@@ -868,56 +929,15 @@ void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_conn_failure);
+ 
+-static void iscsi_prep_mtask(struct iscsi_conn *conn,
+-			     struct iscsi_mgmt_task *mtask)
+-{
+-	struct iscsi_session *session = conn->session;
+-	struct iscsi_hdr *hdr = mtask->hdr;
+-	struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr;
+-
+-	if (hdr->opcode != (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) &&
+-	    hdr->opcode != (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE))
+-		nop->exp_statsn = cpu_to_be32(conn->exp_statsn);
+-	/*
+-	 * pre-format CmdSN for outgoing PDU.
+-	 */
+-	nop->cmdsn = cpu_to_be32(session->cmdsn);
+-	if (hdr->itt != RESERVED_ITT) {
+-		hdr->itt = build_itt(mtask->itt, session->age);
+-		/*
+-		 * TODO: We always use immediate, so we never hit this.
+-		 * If we start to send tmfs or nops as non-immediate then
+-		 * we should start checking the cmdsn numbers for mgmt tasks.
+-		 */
+-		if (conn->c_stage == ISCSI_CONN_STARTED &&
+-		    !(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
+-			session->queued_cmdsn++;
+-			session->cmdsn++;
+-		}
+-	}
+-
+-	if (session->tt->init_mgmt_task)
+-		session->tt->init_mgmt_task(conn, mtask);
+-
+-	debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n",
+-		   hdr->opcode & ISCSI_OPCODE_MASK, hdr->itt,
+-		   mtask->data_count);
+-}
+-
+ static int iscsi_xmit_mtask(struct iscsi_conn *conn)
+ {
+-	struct iscsi_hdr *hdr = conn->mtask->hdr;
+ 	int rc;
+ 
+-	if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT)
+-		conn->session->state = ISCSI_STATE_LOGGING_OUT;
+ 	spin_unlock_bh(&conn->session->lock);
+-
+ 	rc = conn->session->tt->xmit_mgmt_task(conn, conn->mtask);
+ 	spin_lock_bh(&conn->session->lock);
+ 	if (rc)
+ 		return rc;
+-
+ 	/* done with this in-progress mtask */
+ 	conn->mtask = NULL;
+ 	return 0;
+@@ -961,7 +981,8 @@ static int iscsi_xmit_ctask(struct iscsi_conn *conn)
+  * @ctask: ctask to requeue
+  *
+  * LLDs that need to run a ctask from the session workqueue should call
+- * this. The session lock must be held.
++ * this. The session lock must be held. This should only be called
++ * by software drivers.
+  */
+ void iscsi_requeue_ctask(struct iscsi_cmd_task *ctask)
+ {
+@@ -1013,14 +1034,11 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 	while (!list_empty(&conn->mgmtqueue)) {
+ 		conn->mtask = list_entry(conn->mgmtqueue.next,
+ 					 struct iscsi_mgmt_task, running);
+-		if (conn->session->state == ISCSI_STATE_LOGGING_OUT) {
++		if (iscsi_prep_mtask(conn, conn->mtask)) {
+ 			iscsi_free_mgmt_task(conn, conn->mtask);
+ 			conn->mtask = NULL;
+ 			continue;
+ 		}
+-
+-		iscsi_prep_mtask(conn, conn->mtask);
+-		list_move_tail(conn->mgmtqueue.next, &conn->mgmt_run_list);
+ 		rc = iscsi_xmit_mtask(conn);
+ 		if (rc)
+ 			goto again;
+@@ -1041,9 +1059,6 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 			fail_command(conn, conn->ctask, DID_ABORT << 16);
+ 			continue;
+ 		}
+-
+-		conn->ctask->state = ISCSI_TASK_RUNNING;
+-		list_move_tail(conn->xmitqueue.next, &conn->run_list);
+ 		rc = iscsi_xmit_ctask(conn);
+ 		if (rc)
+ 			goto again;
+@@ -1192,8 +1207,6 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 		reason = FAILURE_OOM;
+ 		goto reject;
+ 	}
+-	session->queued_cmdsn++;
+-
+ 	sc->SCp.phase = session->age;
+ 	sc->SCp.ptr = (char *)ctask;
+ 
+@@ -1202,11 +1215,26 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 	ctask->conn = conn;
+ 	ctask->sc = sc;
+ 	INIT_LIST_HEAD(&ctask->running);
+-
+ 	list_add_tail(&ctask->running, &conn->xmitqueue);
+-	spin_unlock(&session->lock);
+ 
+-	scsi_queue_work(host, &conn->xmitwork);
++	if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) {
++		if (iscsi_prep_scsi_cmd_pdu(ctask)) {
++			sc->result = DID_ABORT << 16;
++			sc->scsi_done = NULL;
++			iscsi_complete_command(ctask);
++			goto fault;
++		}
++		if (session->tt->xmit_cmd_task(conn, ctask)) {
++			sc->scsi_done = NULL;
++			iscsi_complete_command(ctask);
++			reason = FAILURE_SESSION_NOT_READY;
++			goto reject;
++		}
++	} else
++		scsi_queue_work(session->host, &conn->xmitwork);
++
++	session->queued_cmdsn++;
++	spin_unlock(&session->lock);
+ 	spin_lock(host->host_lock);
+ 	return 0;
+ 
+@@ -1225,7 +1253,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 		scsi_out(sc)->resid = scsi_out(sc)->length;
+ 		scsi_in(sc)->resid = scsi_in(sc)->length;
+ 	}
+-	sc->scsi_done(sc);
++	done(sc);
+ 	spin_lock(host->host_lock);
+ 	return 0;
+ }
+@@ -1344,7 +1372,6 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn,
+ 
+ 	spin_unlock_bh(&session->lock);
+ 	mutex_unlock(&session->eh_mutex);
+-	scsi_queue_work(session->host, &conn->xmitwork);
+ 
+ 	/*
+ 	 * block eh thread until:
+@@ -1412,14 +1439,16 @@ static void fail_all_commands(struct iscsi_conn *conn, unsigned lun,
+ void iscsi_suspend_tx(struct iscsi_conn *conn)
+ {
+ 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+-	scsi_flush_work(conn->session->host);
++	if (!(conn->session->tt->caps & CAP_DATA_PATH_OFFLOAD))
++		scsi_flush_work(conn->session->host);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_suspend_tx);
+ 
+ static void iscsi_start_tx(struct iscsi_conn *conn)
+ {
+ 	clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+-	scsi_queue_work(conn->session->host, &conn->xmitwork);
++	if (!(conn->session->tt->caps & CAP_DATA_PATH_OFFLOAD))
++		scsi_queue_work(conn->session->host, &conn->xmitwork);
+ }
+ 
+ static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)

commit 0af967f5d4f2dd1e00618d34ac988037d37a6c3b
+Author: Mike Christie 
+Date:   Wed May 21 15:54:04 2008 -0500
+
+    [SCSI] libiscsi, iscsi_tcp, iser: add session cmds array accessor
+    
+    Currently to get a ctask from the session cmd array, you have to
+    know to use the itt modifier. To make this easier on LLDs and
+    so in the future we can easilly kill the session array and use
+    the host shared map instead, this patch adds a nice wrapper
+    to strip the itt into a session->cmds index and return a ctask.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 8a1bfb7277c8..7b1468869066 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -98,7 +98,6 @@ iscsi_iser_recv(struct iscsi_conn *conn,
+ 		struct iscsi_hdr *hdr, char *rx_data, int rx_data_len)
+ {
+ 	int rc = 0;
+-	uint32_t ret_itt;
+ 	int datalen;
+ 	int ahslen;
+ 
+@@ -114,12 +113,7 @@ iscsi_iser_recv(struct iscsi_conn *conn,
+ 	/* read AHS */
+ 	ahslen = hdr->hlength * 4;
+ 
+-	/* verify itt (itt encoding: age+cid+itt) */
+-	rc = iscsi_verify_itt(conn, hdr, &ret_itt);
+-
+-	if (!rc)
+-		rc = iscsi_complete_pdu(conn, hdr, rx_data, rx_data_len);
+-
++	rc = iscsi_complete_pdu(conn, hdr, rx_data, rx_data_len);
+ 	if (rc && rc != ISCSI_ERR_NO_SCSI_CMD)
+ 		goto error;
+ 
+diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
+index 08dc81c46f41..b82a5f2d4d37 100644
+--- a/drivers/infiniband/ulp/iser/iser_initiator.c
++++ b/drivers/infiniband/ulp/iser/iser_initiator.c
+@@ -537,13 +537,11 @@ void iser_rcv_completion(struct iser_desc *rx_desc,
+ {
+ 	struct iser_dto        *dto = &rx_desc->dto;
+ 	struct iscsi_iser_conn *conn = dto->ib_conn->iser_conn;
+-	struct iscsi_session *session = conn->iscsi_conn->session;
+ 	struct iscsi_cmd_task *ctask;
+ 	struct iscsi_iser_cmd_task *iser_ctask;
+ 	struct iscsi_hdr *hdr;
+ 	char   *rx_data = NULL;
+ 	int     rx_data_len = 0;
+-	unsigned int itt;
+ 	unsigned char opcode;
+ 
+ 	hdr = &rx_desc->iscsi_header;
+@@ -559,19 +557,18 @@ void iser_rcv_completion(struct iser_desc *rx_desc,
+ 	opcode = hdr->opcode & ISCSI_OPCODE_MASK;
+ 
+ 	if (opcode == ISCSI_OP_SCSI_CMD_RSP) {
+-	        itt = get_itt(hdr->itt); /* mask out cid and age bits */
+-		if (!(itt < session->cmds_max))
++		ctask = iscsi_itt_to_ctask(conn->iscsi_conn, hdr->itt);
++		if (!ctask)
+ 			iser_err("itt can't be matched to task!!! "
+-				 "conn %p opcode %d cmds_max %d itt %d\n",
+-				 conn->iscsi_conn,opcode,session->cmds_max,itt);
+-		/* use the mapping given with the cmds array indexed by itt */
+-		ctask = (struct iscsi_cmd_task *)session->cmds[itt];
+-		iser_ctask = ctask->dd_data;
+-		iser_dbg("itt %d ctask %p\n",itt,ctask);
+-		iser_ctask->status = ISER_TASK_STATUS_COMPLETED;
+-		iser_ctask_rdma_finalize(iser_ctask);
++				 "conn %p opcode %d itt %d\n",
++				 conn->iscsi_conn, opcode, hdr->itt);
++		else {
++			iser_ctask = ctask->dd_data;
++			iser_dbg("itt %d ctask %p\n",hdr->itt, ctask);
++			iser_ctask->status = ISER_TASK_STATUS_COMPLETED;
++			iser_ctask_rdma_finalize(iser_ctask);
++		}
+ 	}
+-
+ 	iser_dto_buffs_release(dto);
+ 
+ 	iscsi_iser_recv(conn->iscsi_conn, hdr, rx_data, rx_data_len);
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index dfaf9fa57340..f2a08f7ed902 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -740,7 +740,6 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 	struct iscsi_session *session = conn->session;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	struct iscsi_cmd_task *ctask;
+-	uint32_t itt;
+ 
+ 	/* verify PDU length */
+ 	tcp_conn->in.datalen = ntoh24(hdr->dlength);
+@@ -758,7 +757,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 
+ 	opcode = hdr->opcode & ISCSI_OPCODE_MASK;
+ 	/* verify itt (itt encoding: age+cid+itt) */
+-	rc = iscsi_verify_itt(conn, hdr, &itt);
++	rc = iscsi_verify_itt(conn, hdr->itt);
+ 	if (rc)
+ 		return rc;
+ 
+@@ -767,7 +766,10 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 
+ 	switch(opcode) {
+ 	case ISCSI_OP_SCSI_DATA_IN:
+-		ctask = session->cmds[itt];
++		ctask = iscsi_itt_to_ctask(conn, hdr->itt);
++		if (!ctask)
++			return ISCSI_ERR_BAD_ITT;
++
+ 		spin_lock(&conn->session->lock);
+ 		rc = iscsi_data_rsp(conn, ctask);
+ 		spin_unlock(&conn->session->lock);
+@@ -810,7 +812,10 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 		rc = iscsi_complete_pdu(conn, hdr, NULL, 0);
+ 		break;
+ 	case ISCSI_OP_R2T:
+-		ctask = session->cmds[itt];
++		ctask = iscsi_itt_to_ctask(conn, hdr->itt);
++		if (!ctask)
++			return ISCSI_ERR_BAD_ITT;
++
+ 		if (ahslen)
+ 			rc = ISCSI_ERR_AHSLEN;
+ 		else if (ctask->sc->sc_data_direction == DMA_TO_DEVICE) {
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 79bc49fd7f12..4bc63c4b3c10 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -640,6 +640,10 @@ static int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	uint32_t itt;
+ 
+ 	conn->last_recv = jiffies;
++	rc = iscsi_verify_itt(conn, hdr->itt);
++	if (rc)
++		return rc;
++
+ 	if (hdr->itt != RESERVED_ITT)
+ 		itt = get_itt(hdr->itt);
+ 	else
+@@ -776,27 +780,22 @@ int iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ }
+ EXPORT_SYMBOL_GPL(iscsi_complete_pdu);
+ 
+-/* verify itt (itt encoding: age+cid+itt) */
+-int iscsi_verify_itt(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+-		     uint32_t *ret_itt)
++int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt)
+ {
+ 	struct iscsi_session *session = conn->session;
+ 	struct iscsi_cmd_task *ctask;
+-	uint32_t itt;
+ 
+-	if (hdr->itt != RESERVED_ITT) {
+-		if (((__force u32)hdr->itt & ISCSI_AGE_MASK) !=
+-		    (session->age << ISCSI_AGE_SHIFT)) {
+-			iscsi_conn_printk(KERN_ERR, conn,
+-					  "received itt %x expected session "
+-					  "age (%x)\n", (__force u32)hdr->itt,
+-					  session->age & ISCSI_AGE_MASK);
+-			return ISCSI_ERR_BAD_ITT;
+-		}
++	if (itt == RESERVED_ITT)
++		return 0;
+ 
+-		itt = get_itt(hdr->itt);
+-	} else
+-		itt = ~0U;
++	if (((__force u32)itt & ISCSI_AGE_MASK) !=
++	    (session->age << ISCSI_AGE_SHIFT)) {
++		iscsi_conn_printk(KERN_ERR, conn,
++				  "received itt %x expected session age (%x)\n",
++				  (__force u32)itt,
++				  session->age & ISCSI_AGE_MASK);
++		return ISCSI_ERR_BAD_ITT;
++	}
+ 
+ 	if (itt < session->cmds_max) {
+ 		ctask = session->cmds[itt];
+@@ -817,11 +816,38 @@ int iscsi_verify_itt(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		}
+ 	}
+ 
+-	*ret_itt = itt;
+ 	return 0;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_verify_itt);
+ 
++struct iscsi_cmd_task *
++iscsi_itt_to_ctask(struct iscsi_conn *conn, itt_t itt)
++{
++	struct iscsi_session *session = conn->session;
++	struct iscsi_cmd_task *ctask;
++	uint32_t i;
++
++	if (iscsi_verify_itt(conn, itt))
++		return NULL;
++
++	if (itt == RESERVED_ITT)
++		return NULL;
++
++	i = get_itt(itt);
++	if (i >= session->cmds_max)
++		return NULL;
++
++	ctask = session->cmds[i];
++	if (!ctask->sc)
++		return NULL;
++
++	if (ctask->sc->SCp.phase != session->age)
++		return NULL;
++
++	return ctask;
++}
++EXPORT_SYMBOL_GPL(iscsi_itt_to_ctask);
++
+ void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
+ {
+ 	struct iscsi_session *session = conn->session;
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index f54aeb1e8ae3..9be6a70faff5 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -385,8 +385,8 @@ extern int iscsi_conn_send_pdu(struct iscsi_cls_conn *, struct iscsi_hdr *,
+ 				char *, uint32_t);
+ extern int iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *,
+ 			      char *, int);
+-extern int iscsi_verify_itt(struct iscsi_conn *, struct iscsi_hdr *,
+-			    uint32_t *);
++extern int iscsi_verify_itt(struct iscsi_conn *, itt_t);
++extern struct iscsi_cmd_task *iscsi_itt_to_ctask(struct iscsi_conn *, itt_t);
+ extern void iscsi_requeue_ctask(struct iscsi_cmd_task *ctask);
+ extern void iscsi_free_mgmt_task(struct iscsi_conn *conn,
+ 				 struct iscsi_mgmt_task *mtask);

commit b40977d95fb3a1898ace6a7d97e4ed1a33a440a4
+Author: Mike Christie 
+Date:   Wed May 21 15:54:03 2008 -0500
+
+    [SCSI] iser: fix handling of scsi cmnds during recovery.
+    
+    After the stop_conn callback has returned the LLD should not
+    touch the scsi cmds. iscsi_tcp and libiscsi use the
+    conn->recv_lock and suspend_rx field to halt recv path
+    processing, but iser does not have any protection.
+    
+    This patch modifies iser so that userspace can just
+    call the ep_disconnect callback, which will halt
+    all recv IO, before calling the stop_conn callback so
+    we do not have to worry about the conn->recv_lock and
+    suspend rx field. iser just needs to stop the send side
+    from accessing the ib conn.
+    
+    Fixup to handle when the ep poll fails and ep disconnect
+    is called from Erez.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 9b34946eb00d..8a1bfb7277c8 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -305,10 +305,18 @@ iscsi_iser_conn_destroy(struct iscsi_cls_conn *cls_conn)
+ {
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	struct iscsi_iser_conn *iser_conn = conn->dd_data;
++	struct iser_conn *ib_conn = iser_conn->ib_conn;
+ 
+-	if (iser_conn->ib_conn)
+-		iser_conn->ib_conn->iser_conn = NULL;
+ 	iscsi_conn_teardown(cls_conn);
++	/*
++	 * Userspace will normally call the stop callback and
++	 * already have freed the ib_conn, but if it goofed up then
++	 * we free it here.
++	 */
++	if (ib_conn) {
++		ib_conn->iser_conn = NULL;
++		iser_conn_put(ib_conn);
++	}
+ }
+ 
+ static int
+@@ -340,12 +348,29 @@ iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session,
+ 	iser_conn = conn->dd_data;
+ 	ib_conn->iser_conn = iser_conn;
+ 	iser_conn->ib_conn  = ib_conn;
++	iser_conn_get(ib_conn);
+ 
+ 	conn->recv_lock = &iser_conn->lock;
+ 
+ 	return 0;
+ }
+ 
++static void
++iscsi_iser_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
++{
++	struct iscsi_conn *conn = cls_conn->dd_data;
++	struct iscsi_iser_conn *iser_conn = conn->dd_data;
++	struct iser_conn *ib_conn = iser_conn->ib_conn;
++
++	iscsi_conn_stop(cls_conn, flag);
++	/*
++	 * There is no unbind event so the stop callback
++	 * must release the ref from the bind.
++	 */
++	iser_conn_put(ib_conn);
++	iser_conn->ib_conn = NULL;
++}
++
+ static int
+ iscsi_iser_conn_start(struct iscsi_cls_conn *cls_conn)
+ {
+@@ -564,6 +589,17 @@ iscsi_iser_ep_disconnect(__u64 ep_handle)
+ 	if (!ib_conn)
+ 		return;
+ 
++	if (ib_conn->iser_conn)
++		/*
++		 * Must suspend xmit path if the ep is bound to the
++		 * iscsi_conn, so we know we are not accessing the ib_conn
++		 * when we free it.
++		 *
++		 * This may not be bound if the ep poll failed.
++		 */
++		iscsi_suspend_tx(ib_conn->iser_conn->iscsi_conn);
++
++
+ 	iser_err("ib conn %p state %d\n",ib_conn, ib_conn->state);
+ 	iser_conn_terminate(ib_conn);
+ }
+@@ -622,7 +658,7 @@ static struct iscsi_transport iscsi_iser_transport = {
+ 	.get_conn_param		= iscsi_conn_get_param,
+ 	.get_session_param	= iscsi_session_get_param,
+ 	.start_conn             = iscsi_iser_conn_start,
+-	.stop_conn              = iscsi_conn_stop,
++	.stop_conn              = iscsi_iser_conn_stop,
+ 	/* iscsi host params */
+ 	.get_host_param		= iscsi_host_get_param,
+ 	.set_host_param		= iscsi_host_set_param,
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
+index 66a2f30ada01..bd5c1a554ea6 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
+@@ -242,6 +242,7 @@ struct iser_device {
+ struct iser_conn {
+ 	struct iscsi_iser_conn       *iser_conn; /* iser conn for upcalls  */
+ 	enum iser_ib_conn_state	     state;	    /* rdma connection state   */
++	atomic_t		     refcount;
+ 	spinlock_t		     lock;	    /* used for state changes  */
+ 	struct iser_device           *device;       /* device context          */
+ 	struct rdma_cm_id            *cma_id;       /* CMA ID		       */
+@@ -314,6 +315,10 @@ void iscsi_iser_recv(struct iscsi_conn *conn,
+ 
+ int  iser_conn_init(struct iser_conn **ib_conn);
+ 
++void iser_conn_get(struct iser_conn *ib_conn);
++
++void iser_conn_put(struct iser_conn *ib_conn);
++
+ void iser_conn_terminate(struct iser_conn *ib_conn);
+ 
+ void iser_rcv_completion(struct iser_desc *desc,
+diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
+index d19cfe605ebb..5daed2bd710e 100644
+--- a/drivers/infiniband/ulp/iser/iser_verbs.c
++++ b/drivers/infiniband/ulp/iser/iser_verbs.c
+@@ -328,6 +328,17 @@ static void iser_conn_release(struct iser_conn *ib_conn)
+ 	kfree(ib_conn);
+ }
+ 
++void iser_conn_get(struct iser_conn *ib_conn)
++{
++	atomic_inc(&ib_conn->refcount);
++}
++
++void iser_conn_put(struct iser_conn *ib_conn)
++{
++	if (atomic_dec_and_test(&ib_conn->refcount))
++		iser_conn_release(ib_conn);
++}
++
+ /**
+  * triggers start of the disconnect procedures and wait for them to be done
+  */
+@@ -349,7 +360,7 @@ void iser_conn_terminate(struct iser_conn *ib_conn)
+ 	wait_event_interruptible(ib_conn->wait,
+ 				 ib_conn->state == ISER_CONN_DOWN);
+ 
+-	iser_conn_release(ib_conn);
++	iser_conn_put(ib_conn);
+ }
+ 
+ static void iser_connect_error(struct rdma_cm_id *cma_id)
+@@ -496,6 +507,7 @@ int iser_conn_init(struct iser_conn **ibconn)
+ 	init_waitqueue_head(&ib_conn->wait);
+ 	atomic_set(&ib_conn->post_recv_buf_count, 0);
+ 	atomic_set(&ib_conn->post_send_buf_count, 0);
++	atomic_set(&ib_conn->refcount, 1);
+ 	INIT_LIST_HEAD(&ib_conn->conn_list);
+ 	spin_lock_init(&ib_conn->lock);
+ 
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 784a935fad4a..79bc49fd7f12 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1383,11 +1383,12 @@ static void fail_all_commands(struct iscsi_conn *conn, unsigned lun,
+ 	}
+ }
+ 
+-static void iscsi_suspend_tx(struct iscsi_conn *conn)
++void iscsi_suspend_tx(struct iscsi_conn *conn)
+ {
+ 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+ 	scsi_flush_work(conn->session->host);
+ }
++EXPORT_SYMBOL_GPL(iscsi_suspend_tx);
+ 
+ static void iscsi_start_tx(struct iscsi_conn *conn)
+ {

commit 5af3e91d232b7e022f258202f72ebb79b8b0c706
+Author: Mike Christie 
+Date:   Wed May 21 15:54:02 2008 -0500
+
+    [SCSI] iscsi: modify iscsi printk so it can take driver data pointers
+    
+    Some drivers want to be able to just pass in the driver data pointers
+    to the iscsi objects. To enable this we need the iscsi printk macro
+    to cast the object.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 4e1c14f20ddd..f54aeb1e8ae3 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -369,9 +369,11 @@ extern int iscsi_conn_bind(struct iscsi_cls_session *, struct iscsi_cls_conn *,
+ extern void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err);
+ extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ 				enum iscsi_param param, char *buf);
++extern void iscsi_suspend_tx(struct iscsi_conn *conn);
+ 
+ #define iscsi_conn_printk(prefix, _c, fmt, a...) \
+-	iscsi_cls_conn_printk(prefix, _c->cls_conn, fmt, ##a)
++	iscsi_cls_conn_printk(prefix, ((struct iscsi_conn *)_c)->cls_conn, \
++			      fmt, ##a)
+ 
+ /*
+  * pdu and task processing

commit 5d91e209fb21fb9cc765729d4c6a85a9fb6c9187
+Author: Mike Christie 
+Date:   Wed May 21 15:54:01 2008 -0500
+
+    [SCSI] iscsi: remove session/conn_data_size from iscsi_transport
+    
+    This removes the session and conn data_size fields from the iscsi_transport.
+    Just pass in the value like with host allocation. This patch also makes
+    it so the LLD iscsi_conn data is allocated with the iscsi_cls_conn.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 62e35e503e49..9b34946eb00d 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -279,7 +279,7 @@ iscsi_iser_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ 	struct iscsi_cls_conn *cls_conn;
+ 	struct iscsi_iser_conn *iser_conn;
+ 
+-	cls_conn = iscsi_conn_setup(cls_session, conn_idx);
++	cls_conn = iscsi_conn_setup(cls_session, sizeof(*iser_conn), conn_idx);
+ 	if (!cls_conn)
+ 		return NULL;
+ 	conn = cls_conn->dd_data;
+@@ -290,10 +290,7 @@ iscsi_iser_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ 	 */
+ 	conn->max_recv_dlength = 128;
+ 
+-	iser_conn = kzalloc(sizeof(*iser_conn), GFP_KERNEL);
+-	if (!iser_conn)
+-		goto conn_alloc_fail;
+-
++	iser_conn = conn->dd_data;
+ 	/* currently this is the only field which need to be initiated */
+ 	rwlock_init(&iser_conn->lock);
+ 
+@@ -301,10 +298,6 @@ iscsi_iser_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ 	iser_conn->iscsi_conn = conn;
+ 
+ 	return cls_conn;
+-
+-conn_alloc_fail:
+-	iscsi_conn_teardown(cls_conn);
+-	return NULL;
+ }
+ 
+ static void
+@@ -313,10 +306,9 @@ iscsi_iser_conn_destroy(struct iscsi_cls_conn *cls_conn)
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	struct iscsi_iser_conn *iser_conn = conn->dd_data;
+ 
+-	iscsi_conn_teardown(cls_conn);
+ 	if (iser_conn->ib_conn)
+ 		iser_conn->ib_conn->iser_conn = NULL;
+-	kfree(iser_conn);
++	iscsi_conn_teardown(cls_conn);
+ }
+ 
+ static int
+@@ -619,8 +611,6 @@ static struct iscsi_transport iscsi_iser_transport = {
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS |
+ 				  ISCSI_HOST_NETDEV_NAME |
+ 				  ISCSI_HOST_INITIATOR_NAME,
+-	.conndata_size		= sizeof(struct iscsi_conn),
+-	.sessiondata_size	= sizeof(struct iscsi_session),
+ 	/* session management */
+ 	.create_session         = iscsi_iser_session_create,
+ 	.destroy_session        = iscsi_iser_session_destroy,
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index e19d92f2d753..dfaf9fa57340 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -1490,7 +1490,7 @@ iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ 	struct iscsi_cls_conn *cls_conn;
+ 	struct iscsi_tcp_conn *tcp_conn;
+ 
+-	cls_conn = iscsi_conn_setup(cls_session, conn_idx);
++	cls_conn = iscsi_conn_setup(cls_session, sizeof(*tcp_conn), conn_idx);
+ 	if (!cls_conn)
+ 		return NULL;
+ 	conn = cls_conn->dd_data;
+@@ -1500,18 +1500,14 @@ iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ 	 */
+ 	conn->max_recv_dlength = ISCSI_DEF_MAX_RECV_SEG_LEN;
+ 
+-	tcp_conn = kzalloc(sizeof(*tcp_conn), GFP_KERNEL);
+-	if (!tcp_conn)
+-		goto tcp_conn_alloc_fail;
+-
+-	conn->dd_data = tcp_conn;
++	tcp_conn = conn->dd_data;
+ 	tcp_conn->iscsi_conn = conn;
+ 
+ 	tcp_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0,
+ 						  CRYPTO_ALG_ASYNC);
+ 	tcp_conn->tx_hash.flags = 0;
+ 	if (IS_ERR(tcp_conn->tx_hash.tfm))
+-		goto free_tcp_conn;
++		goto free_conn;
+ 
+ 	tcp_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0,
+ 						  CRYPTO_ALG_ASYNC);
+@@ -1523,14 +1519,12 @@ iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ 
+ free_tx_tfm:
+ 	crypto_free_hash(tcp_conn->tx_hash.tfm);
+-free_tcp_conn:
++free_conn:
+ 	iscsi_conn_printk(KERN_ERR, conn,
+ 			  "Could not create connection due to crc32c "
+ 			  "loading error. Make sure the crc32c "
+ 			  "module is built as a module or into the "
+ 			  "kernel\n");
+-	kfree(tcp_conn);
+-tcp_conn_alloc_fail:
+ 	iscsi_conn_teardown(cls_conn);
+ 	return NULL;
+ }
+@@ -1563,14 +1557,13 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn)
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 
+ 	iscsi_tcp_release_conn(conn);
+-	iscsi_conn_teardown(cls_conn);
+ 
+ 	if (tcp_conn->tx_hash.tfm)
+ 		crypto_free_hash(tcp_conn->tx_hash.tfm);
+ 	if (tcp_conn->rx_hash.tfm)
+ 		crypto_free_hash(tcp_conn->rx_hash.tfm);
+ 
+-	kfree(tcp_conn);
++	iscsi_conn_teardown(cls_conn);
+ }
+ 
+ static void
+@@ -1983,8 +1976,6 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+ 				  ISCSI_HOST_INITIATOR_NAME |
+ 				  ISCSI_HOST_NETDEV_NAME,
+-	.conndata_size		= sizeof(struct iscsi_conn),
+-	.sessiondata_size	= sizeof(struct iscsi_session),
+ 	/* session management */
+ 	.create_session		= iscsi_tcp_session_create,
+ 	.destroy_session	= iscsi_tcp_session_destroy,
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 73c37c04ca66..784a935fad4a 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1867,7 +1867,8 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
+ 		cmds_max = ISCSI_DEF_XMIT_CMDS_MAX;
+ 	}
+ 
+-	cls_session = iscsi_alloc_session(shost, iscsit);
++	cls_session = iscsi_alloc_session(shost, iscsit,
++					  sizeof(struct iscsi_session));
+ 	if (!cls_session)
+ 		return NULL;
+ 	session = cls_session->dd_data;
+@@ -1968,22 +1969,26 @@ EXPORT_SYMBOL_GPL(iscsi_session_teardown);
+ /**
+  * iscsi_conn_setup - create iscsi_cls_conn and iscsi_conn
+  * @cls_session: iscsi_cls_session
++ * @dd_size: private driver data size
+  * @conn_idx: cid
+- **/
++ */
+ struct iscsi_cls_conn *
+-iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
++iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size,
++		 uint32_t conn_idx)
+ {
+ 	struct iscsi_session *session = cls_session->dd_data;
+ 	struct iscsi_conn *conn;
+ 	struct iscsi_cls_conn *cls_conn;
+ 	char *data;
+ 
+-	cls_conn = iscsi_create_conn(cls_session, conn_idx);
++	cls_conn = iscsi_create_conn(cls_session, sizeof(*conn) + dd_size,
++				     conn_idx);
+ 	if (!cls_conn)
+ 		return NULL;
+ 	conn = cls_conn->dd_data;
+-	memset(conn, 0, sizeof(*conn));
++	memset(conn, 0, sizeof(*conn) + dd_size);
+ 
++	conn->dd_data = cls_conn->dd_data + sizeof(*conn);
+ 	conn->session = session;
+ 	conn->cls_conn = cls_conn;
+ 	conn->c_stage = ISCSI_CONN_INITIAL_STAGE;
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index 6c6ee0f34995..5822dd595826 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -113,8 +113,6 @@ static struct iscsi_transport qla4xxx_iscsi_transport = {
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS |
+ 				  ISCSI_HOST_IPADDRESS |
+ 				  ISCSI_HOST_INITIATOR_NAME,
+-	.sessiondata_size	= sizeof(struct ddb_entry),
+-
+ 	.tgt_dscvr		= qla4xxx_tgt_dscvr,
+ 	.get_conn_param		= qla4xxx_conn_get_param,
+ 	.get_session_param	= qla4xxx_sess_get_param,
+@@ -274,7 +272,7 @@ int qla4xxx_add_sess(struct ddb_entry *ddb_entry)
+ 		return err;
+ 	}
+ 
+-	ddb_entry->conn = iscsi_create_conn(ddb_entry->sess, 0);
++	ddb_entry->conn = iscsi_create_conn(ddb_entry->sess, 0, 0);
+ 	if (!ddb_entry->conn) {
+ 		iscsi_remove_session(ddb_entry->sess);
+ 		DEBUG2(printk(KERN_ERR "Could not add connection.\n"));
+@@ -291,7 +289,8 @@ struct ddb_entry *qla4xxx_alloc_sess(struct scsi_qla_host *ha)
+ 	struct ddb_entry *ddb_entry;
+ 	struct iscsi_cls_session *sess;
+ 
+-	sess = iscsi_alloc_session(ha->host, &qla4xxx_iscsi_transport);
++	sess = iscsi_alloc_session(ha->host, &qla4xxx_iscsi_transport,
++				   sizeof(struct ddb_entry));
+ 	if (!sess)
+ 		return NULL;
+ 
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 6fdaa2ee6632..6b8516a0970b 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -483,12 +483,12 @@ static int iscsi_unbind_session(struct iscsi_cls_session *session)
+ }
+ 
+ struct iscsi_cls_session *
+-iscsi_alloc_session(struct Scsi_Host *shost,
+-		    struct iscsi_transport *transport)
++iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
++		    int dd_size)
+ {
+ 	struct iscsi_cls_session *session;
+ 
+-	session = kzalloc(sizeof(*session) + transport->sessiondata_size,
++	session = kzalloc(sizeof(*session) + dd_size,
+ 			  GFP_KERNEL);
+ 	if (!session)
+ 		return NULL;
+@@ -510,7 +510,7 @@ iscsi_alloc_session(struct Scsi_Host *shost,
+ 	session->dev.parent = &shost->shost_gendev;
+ 	session->dev.release = iscsi_session_release;
+ 	device_initialize(&session->dev);
+-	if (transport->sessiondata_size)
++	if (dd_size)
+ 		session->dd_data = &session[1];
+ 	return session;
+ }
+@@ -558,18 +558,18 @@ EXPORT_SYMBOL_GPL(iscsi_add_session);
+  * iscsi_create_session - create iscsi class session
+  * @shost: scsi host
+  * @transport: iscsi transport
++ * @dd_size: private driver data size
+  * @target_id: which target
+  *
+  * This can be called from a LLD or iscsi_transport.
+  */
+ struct iscsi_cls_session *
+-iscsi_create_session(struct Scsi_Host *shost,
+-		     struct iscsi_transport *transport,
+-		     unsigned int target_id)
++iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
++		     int dd_size, unsigned int target_id)
+ {
+ 	struct iscsi_cls_session *session;
+ 
+-	session = iscsi_alloc_session(shost, transport);
++	session = iscsi_alloc_session(shost, transport, dd_size);
+ 	if (!session)
+ 		return NULL;
+ 
+@@ -671,6 +671,7 @@ EXPORT_SYMBOL_GPL(iscsi_destroy_session);
+ /**
+  * iscsi_create_conn - create iscsi class connection
+  * @session: iscsi cls session
++ * @dd_size: private driver data size
+  * @cid: connection id
+  *
+  * This can be called from a LLD or iscsi_transport. The connection
+@@ -683,18 +684,17 @@ EXPORT_SYMBOL_GPL(iscsi_destroy_session);
+  * non-zero.
+  */
+ struct iscsi_cls_conn *
+-iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid)
++iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid)
+ {
+ 	struct iscsi_transport *transport = session->transport;
+ 	struct iscsi_cls_conn *conn;
+ 	unsigned long flags;
+ 	int err;
+ 
+-	conn = kzalloc(sizeof(*conn) + transport->conndata_size, GFP_KERNEL);
++	conn = kzalloc(sizeof(*conn) + dd_size, GFP_KERNEL);
+ 	if (!conn)
+ 		return NULL;
+-
+-	if (transport->conndata_size)
++	if (dd_size)
+ 		conn->dd_data = &conn[1];
+ 
+ 	INIT_LIST_HEAD(&conn->conn_list);
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 9a26d715a953..4e1c14f20ddd 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -313,8 +313,6 @@ struct iscsi_host {
+ 	char			local_address[ISCSI_ADDRESS_BUF_LEN];
+ };
+ 
+-#define iscsi_host_priv(_shost) \
+-	(shost_priv(_shost) + sizeof(struct iscsi_host))
+ /*
+  * scsi host template
+  */
+@@ -325,10 +323,12 @@ extern int iscsi_eh_device_reset(struct scsi_cmnd *sc);
+ extern int iscsi_queuecommand(struct scsi_cmnd *sc,
+ 			      void (*done)(struct scsi_cmnd *));
+ 
+-
+ /*
+  * iSCSI host helpers.
+  */
++#define iscsi_host_priv(_shost) \
++	(shost_priv(_shost) + sizeof(struct iscsi_host))
++
+ extern int iscsi_host_set_param(struct Scsi_Host *shost,
+ 				enum iscsi_host_param param, char *buf,
+ 				int buflen);
+@@ -360,7 +360,7 @@ extern int iscsi_session_get_param(struct iscsi_cls_session *cls_session,
+  * connection management
+  */
+ extern struct iscsi_cls_conn *iscsi_conn_setup(struct iscsi_cls_session *,
+-					       uint32_t);
++					       int, uint32_t);
+ extern void iscsi_conn_teardown(struct iscsi_cls_conn *);
+ extern int iscsi_conn_start(struct iscsi_cls_conn *);
+ extern void iscsi_conn_stop(struct iscsi_cls_conn *, int);
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 761f62da7cc8..4028f121d548 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -83,10 +83,6 @@ struct iscsi_transport {
+ 	/* LLD sets this to indicate what values it can export to sysfs */
+ 	uint64_t param_mask;
+ 	uint64_t host_param_mask;
+-	/* LLD connection data size */
+-	int conndata_size;
+-	/* LLD session data size */
+-	int sessiondata_size;
+ 	struct iscsi_cls_session *(*create_session) (struct Scsi_Host *shost,
+ 					uint16_t cmds_max, uint16_t qdepth,
+ 					uint32_t sn, uint32_t *hn);
+@@ -222,19 +218,20 @@ extern void iscsi_host_for_each_session(struct Scsi_Host *shost,
+ 
+ extern int iscsi_session_chkready(struct iscsi_cls_session *session);
+ extern struct iscsi_cls_session *iscsi_alloc_session(struct Scsi_Host *shost,
+-					struct iscsi_transport *transport);
++				struct iscsi_transport *transport, int dd_size);
+ extern int iscsi_add_session(struct iscsi_cls_session *session,
+ 			     unsigned int target_id);
+ extern int iscsi_session_event(struct iscsi_cls_session *session,
+ 			       enum iscsi_uevent_e event);
+ extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost,
+ 						struct iscsi_transport *t,
++						int dd_size,
+ 						unsigned int target_id);
+ extern void iscsi_remove_session(struct iscsi_cls_session *session);
+ extern void iscsi_free_session(struct iscsi_cls_session *session);
+ extern int iscsi_destroy_session(struct iscsi_cls_session *session);
+ extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess,
+-					    uint32_t cid);
++						int dd_size, uint32_t cid);
+ extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn);
+ extern void iscsi_unblock_session(struct iscsi_cls_session *session);
+ extern void iscsi_block_session(struct iscsi_cls_session *session);

commit a4804cd6eb19318ae8d08ea967cfeaaf5c5b68a6
+Author: Mike Christie 
+Date:   Wed May 21 15:54:00 2008 -0500
+
+    [SCSI] iscsi: add iscsi host helpers
+    
+    This finishes the host/session unbinding, by adding some helpers
+    to add and remove hosts and the session they manage.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 5a750042e2b2..62e35e503e49 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -371,10 +371,8 @@ static void iscsi_iser_session_destroy(struct iscsi_cls_session *cls_session)
+ {
+ 	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+ 
+-	iscsi_session_teardown(cls_session);
+-	scsi_remove_host(shost);
+-	iscsi_host_teardown(shost);
+-	scsi_host_put(shost);
++	iscsi_host_remove(shost);
++	iscsi_host_free(shost);
+ }
+ 
+ static struct iscsi_cls_session *
+@@ -396,7 +394,7 @@ iscsi_iser_session_create(struct Scsi_Host *shost,
+ 		return NULL;
+ 	}
+ 
+-	shost = scsi_host_alloc(&iscsi_iser_sht, 0);
++	shost = iscsi_host_alloc(&iscsi_iser_sht, 0, ISCSI_MAX_CMD_PER_LUN);
+ 	if (!shost)
+ 		return NULL;
+ 	shost->transportt = iscsi_iser_scsi_transport;
+@@ -405,9 +403,7 @@ iscsi_iser_session_create(struct Scsi_Host *shost,
+ 	shost->max_channel = 0;
+ 	shost->max_cmd_len = 16;
+ 
+-	iscsi_host_setup(shost, qdepth);
+-
+-	if (scsi_add_host(shost, NULL))
++	if (iscsi_host_add(shost, NULL))
+ 		goto free_host;
+ 	*hostno = shost->host_no;
+ 
+@@ -443,10 +439,9 @@ iscsi_iser_session_create(struct Scsi_Host *shost,
+ 	return cls_session;
+ 
+ remove_host:
+-	scsi_remove_host(shost);
++	iscsi_host_remove(shost);
+ free_host:
+-	iscsi_host_teardown(shost);
+-	scsi_host_put(shost);
++	iscsi_host_free(shost);
+ 	return NULL;
+ }
+ 
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 8cdcaf33fb4e..e19d92f2d753 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -1866,7 +1866,7 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max,
+ 		return NULL;
+ 	}
+ 
+-	shost = scsi_host_alloc(&iscsi_sht, sizeof(struct iscsi_host));
++	shost = iscsi_host_alloc(&iscsi_sht, 0, qdepth);
+ 	if (!shost)
+ 		return NULL;
+ 	shost->transportt = iscsi_tcp_scsi_transport;
+@@ -1874,10 +1874,9 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max,
+ 	shost->max_id = 0;
+ 	shost->max_channel = 0;
+ 	shost->max_cmd_len = 16;
++	shost->can_queue = cmds_max;
+ 
+-	iscsi_host_setup(shost, qdepth);
+-
+-	if (scsi_add_host(shost, NULL))
++	if (iscsi_host_add(shost, NULL))
+ 		goto free_host;
+ 	*hostno = shost->host_no;
+ 
+@@ -1912,10 +1911,9 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max,
+ remove_session:
+ 	iscsi_session_teardown(cls_session);
+ remove_host:
+-	scsi_remove_host(shost);
++	iscsi_host_remove(shost);
+ free_host:
+-	iscsi_host_teardown(shost);
+-	scsi_host_put(shost);
++	iscsi_host_free(shost);
+ 	return NULL;
+ }
+ 
+@@ -1924,11 +1922,9 @@ static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session)
+ 	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+ 
+ 	iscsi_r2tpool_free(cls_session->dd_data);
+-	iscsi_session_teardown(cls_session);
+ 
+-	scsi_remove_host(shost);
+-	iscsi_host_teardown(shost);
+-	scsi_host_put(shost);
++	iscsi_host_remove(shost);
++	iscsi_host_free(shost);
+ }
+ 
+ static int iscsi_tcp_slave_configure(struct scsi_device *sdev)
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 64b1dd827366..73c37c04ca66 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1764,8 +1764,39 @@ void iscsi_pool_free(struct iscsi_pool *q)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_pool_free);
+ 
+-void iscsi_host_setup(struct Scsi_Host *shost, uint16_t qdepth)
++/**
++ * iscsi_host_add - add host to system
++ * @shost: scsi host
++ * @pdev: parent device
++ *
++ * This should be called by partial offload and software iscsi drivers
++ * to add a host to the system.
++ */
++int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev)
++{
++	return scsi_add_host(shost, pdev);
++}
++EXPORT_SYMBOL_GPL(iscsi_host_add);
++
++/**
++ * iscsi_host_alloc - allocate a host and driver data
++ * @sht: scsi host template
++ * @dd_data_size: driver host data size
++ * @qdepth: default device queue depth
++ *
++ * This should be called by partial offload and software iscsi drivers.
++ * To access the driver specific memory use the iscsi_host_priv() macro.
++ */
++struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
++				   int dd_data_size, uint16_t qdepth)
+ {
++	struct Scsi_Host *shost;
++
++	shost = scsi_host_alloc(sht, sizeof(struct iscsi_host) + dd_data_size);
++	if (!shost)
++		return NULL;
++	shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out;
++
+ 	if (qdepth > ISCSI_MAX_CMD_PER_LUN || qdepth < 1) {
+ 		if (qdepth != 0)
+ 			printk(KERN_ERR "iscsi: invalid queue depth of %d. "
+@@ -1773,22 +1804,37 @@ void iscsi_host_setup(struct Scsi_Host *shost, uint16_t qdepth)
+ 			       qdepth, ISCSI_MAX_CMD_PER_LUN);
+ 		qdepth = ISCSI_DEF_CMD_PER_LUN;
+ 	}
+-
+-	shost->transportt->create_work_queue = 1;
+-	shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out;
+ 	shost->cmd_per_lun = qdepth;
++	return shost;
++}
++EXPORT_SYMBOL_GPL(iscsi_host_alloc);
++
++/**
++ * iscsi_host_remove - remove host and sessions
++ * @shost: scsi host
++ *
++ * This will also remove any sessions attached to the host, but if userspace
++ * is managing the session at the same time this will break. TODO: add
++ * refcounting to the netlink iscsi interface so a rmmod or host hot unplug
++ * does not remove the memory from under us.
++ */
++void iscsi_host_remove(struct Scsi_Host *shost)
++{
++	iscsi_host_for_each_session(shost, iscsi_session_teardown);
++	scsi_remove_host(shost);
+ }
+-EXPORT_SYMBOL_GPL(iscsi_host_setup);
++EXPORT_SYMBOL_GPL(iscsi_host_remove);
+ 
+-void iscsi_host_teardown(struct Scsi_Host *shost)
++void iscsi_host_free(struct Scsi_Host *shost)
+ {
+ 	struct iscsi_host *ihost = shost_priv(shost);
+ 
+ 	kfree(ihost->netdev);
+ 	kfree(ihost->hwaddress);
+ 	kfree(ihost->initiatorname);
++	scsi_host_put(shost);
+ }
+-EXPORT_SYMBOL_GPL(iscsi_host_teardown);
++EXPORT_SYMBOL_GPL(iscsi_host_free);
+ 
+ /**
+  * iscsi_session_setup - create iscsi cls session and host and session
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 9c00a157b485..6fdaa2ee6632 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -279,6 +279,24 @@ static int iscsi_is_session_dev(const struct device *dev)
+ 	return dev->release == iscsi_session_release;
+ }
+ 
++static int iscsi_iter_session_fn(struct device *dev, void *data)
++{
++	void (* fn) (struct iscsi_cls_session *) = data;
++
++	if (!iscsi_is_session_dev(dev))
++		return 0;
++	fn(iscsi_dev_to_session(dev));
++	return 0;
++}
++
++void iscsi_host_for_each_session(struct Scsi_Host *shost,
++				 void (*fn)(struct iscsi_cls_session *))
++{
++	device_for_each_child(&shost->shost_gendev, fn,
++			      iscsi_iter_session_fn);
++}
++EXPORT_SYMBOL_GPL(iscsi_host_for_each_session);
++
+ /**
+  * iscsi_scan_finished - helper to report when running scans are done
+  * @shost: scsi host
+@@ -1599,6 +1617,8 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 	priv->daemon_pid = -1;
+ 	priv->iscsi_transport = tt;
+ 	priv->t.user_scan = iscsi_user_scan;
++	if (!(tt->caps & CAP_DATA_PATH_OFFLOAD))
++		priv->t.create_work_queue = 1;
+ 
+ 	priv->dev.class = &iscsi_transport_class;
+ 	snprintf(priv->dev.bus_id, BUS_ID_SIZE, "%s", tt->name);
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 8a6271c20935..9a26d715a953 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -32,6 +32,7 @@
+ #include 
+ 
+ struct scsi_transport_template;
++struct scsi_host_template;
+ struct scsi_device;
+ struct Scsi_Host;
+ struct scsi_cmnd;
+@@ -41,6 +42,7 @@ struct iscsi_cls_session;
+ struct iscsi_cls_conn;
+ struct iscsi_session;
+ struct iscsi_nopin;
++struct device;
+ 
+ /* #define DEBUG_SCSI */
+ #ifdef DEBUG_SCSI
+@@ -311,6 +313,8 @@ struct iscsi_host {
+ 	char			local_address[ISCSI_ADDRESS_BUF_LEN];
+ };
+ 
++#define iscsi_host_priv(_shost) \
++	(shost_priv(_shost) + sizeof(struct iscsi_host))
+ /*
+  * scsi host template
+  */
+@@ -330,8 +334,11 @@ extern int iscsi_host_set_param(struct Scsi_Host *shost,
+ 				int buflen);
+ extern int iscsi_host_get_param(struct Scsi_Host *shost,
+ 				enum iscsi_host_param param, char *buf);
+-extern void iscsi_host_setup(struct Scsi_Host *shost, uint16_t qdepth);
+-extern void iscsi_host_teardown(struct Scsi_Host *shost);
++extern int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev);
++extern struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
++					  int dd_data_size, uint16_t qdepth);
++extern void iscsi_host_remove(struct Scsi_Host *shost);
++extern void iscsi_host_free(struct Scsi_Host *shost);
+ 
+ /*
+  * session management
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 702eda2904d7..761f62da7cc8 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -207,6 +207,10 @@ struct iscsi_cls_host {
+ 	char scan_workq_name[KOBJ_NAME_LEN];
+ };
+ 
++extern void iscsi_host_for_each_session(struct Scsi_Host *shost,
++				void (*fn)(struct iscsi_cls_session *));
++
++
+ /*
+  * session and connection functions that can be used by HW iSCSI LLDs
+  */

commit 756135215ec743be6fdce2bdebe8cdb9f8a231f6
+Author: Mike Christie 
+Date:   Wed May 21 15:53:59 2008 -0500
+
+    [SCSI] iscsi: remove session and host binding in libiscsi
+    
+    bnx2i allocates a host per netdevice but will use libiscsi,
+    so this unbinds the session from the host in that code.
+    
+    This will also be useful for the iser parent device dma settings
+    fixes.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 32f5d5e79abf..5a750042e2b2 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -74,6 +74,10 @@
+ 
+ #include "iscsi_iser.h"
+ 
++static struct scsi_host_template iscsi_iser_sht;
++static struct iscsi_transport iscsi_iser_transport;
++static struct scsi_transport_template *iscsi_iser_scsi_transport;
++
+ static unsigned int iscsi_max_lun = 512;
+ module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
+ 
+@@ -363,40 +367,64 @@ iscsi_iser_conn_start(struct iscsi_cls_conn *cls_conn)
+ 	return iscsi_conn_start(cls_conn);
+ }
+ 
+-static struct iscsi_transport iscsi_iser_transport;
++static void iscsi_iser_session_destroy(struct iscsi_cls_session *cls_session)
++{
++	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
++
++	iscsi_session_teardown(cls_session);
++	scsi_remove_host(shost);
++	iscsi_host_teardown(shost);
++	scsi_host_put(shost);
++}
+ 
+ static struct iscsi_cls_session *
+-iscsi_iser_session_create(struct iscsi_transport *iscsit,
+-			 struct scsi_transport_template *scsit,
+-			 struct Scsi_Host *shost,
+-			 uint16_t cmds_max, uint16_t qdepth,
+-			 uint32_t initial_cmdsn, uint32_t *hostno)
++iscsi_iser_session_create(struct Scsi_Host *shost,
++			  uint16_t cmds_max, uint16_t qdepth,
++			  uint32_t initial_cmdsn, uint32_t *hostno)
+ {
+ 	struct iscsi_cls_session *cls_session;
+ 	struct iscsi_session *session;
+ 	int i;
+-	uint32_t hn;
+ 	struct iscsi_cmd_task  *ctask;
+ 	struct iscsi_mgmt_task *mtask;
+ 	struct iscsi_iser_cmd_task *iser_ctask;
+ 	struct iser_desc *desc;
+ 
++	if (shost) {
++		printk(KERN_ERR "iscsi_tcp: invalid shost %d.\n",
++		       shost->host_no);
++		return NULL;
++	}
++
++	shost = scsi_host_alloc(&iscsi_iser_sht, 0);
++	if (!shost)
++		return NULL;
++	shost->transportt = iscsi_iser_scsi_transport;
++	shost->max_lun = iscsi_max_lun;
++	shost->max_id = 0;
++	shost->max_channel = 0;
++	shost->max_cmd_len = 16;
++
++	iscsi_host_setup(shost, qdepth);
++
++	if (scsi_add_host(shost, NULL))
++		goto free_host;
++	*hostno = shost->host_no;
++
+ 	/*
+ 	 * we do not support setting can_queue cmd_per_lun from userspace yet
+ 	 * because we preallocate so many resources
+ 	 */
+-	cls_session = iscsi_session_setup(iscsit, scsit,
++	cls_session = iscsi_session_setup(&iscsi_iser_transport, shost,
+ 					  ISCSI_DEF_XMIT_CMDS_MAX,
+-					  ISCSI_MAX_CMD_PER_LUN,
+ 					  sizeof(struct iscsi_iser_cmd_task),
+ 					  sizeof(struct iser_desc),
+-					  initial_cmdsn, &hn);
++					  initial_cmdsn);
+ 	if (!cls_session)
+-	return NULL;
+-
+-	*hostno = hn;
+-	session = class_to_transport_session(cls_session);
++		goto remove_host;
++	session = cls_session->dd_data;
+ 
++	shost->can_queue = session->cmds_max;
+ 	/* libiscsi setup itts, data and pool so just set desc fields */
+ 	for (i = 0; i < session->cmds_max; i++) {
+ 		ctask      = session->cmds[i];
+@@ -413,6 +441,13 @@ iscsi_iser_session_create(struct iscsi_transport *iscsit,
+ 	}
+ 
+ 	return cls_session;
++
++remove_host:
++	scsi_remove_host(shost);
++free_host:
++	iscsi_host_teardown(shost);
++	scsi_host_put(shost);
++	return NULL;
+ }
+ 
+ static int
+@@ -589,12 +624,11 @@ static struct iscsi_transport iscsi_iser_transport = {
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS |
+ 				  ISCSI_HOST_NETDEV_NAME |
+ 				  ISCSI_HOST_INITIATOR_NAME,
+-	.host_template          = &iscsi_iser_sht,
+ 	.conndata_size		= sizeof(struct iscsi_conn),
+-	.max_lun                = ISCSI_ISER_MAX_LUN,
++	.sessiondata_size	= sizeof(struct iscsi_session),
+ 	/* session management */
+ 	.create_session         = iscsi_iser_session_create,
+-	.destroy_session        = iscsi_session_teardown,
++	.destroy_session        = iscsi_iser_session_destroy,
+ 	/* connection management */
+ 	.create_conn            = iscsi_iser_conn_create,
+ 	.bind_conn              = iscsi_iser_conn_bind,
+@@ -633,8 +667,6 @@ static int __init iser_init(void)
+ 		return -EINVAL;
+ 	}
+ 
+-	iscsi_iser_transport.max_lun = iscsi_max_lun;
+-
+ 	memset(&ig, 0, sizeof(struct iser_global));
+ 
+ 	ig.desc_cache = kmem_cache_create("iser_descriptors",
+@@ -650,7 +682,9 @@ static int __init iser_init(void)
+ 	mutex_init(&ig.connlist_mutex);
+ 	INIT_LIST_HEAD(&ig.connlist);
+ 
+-	if (!iscsi_register_transport(&iscsi_iser_transport)) {
++	iscsi_iser_scsi_transport = iscsi_register_transport(
++							&iscsi_iser_transport);
++	if (!iscsi_iser_scsi_transport) {
+ 		iser_err("iscsi_register_transport failed\n");
+ 		err = -EINVAL;
+ 		goto register_transport_failure;
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index aecadbdce9df..8cdcaf33fb4e 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -64,6 +64,10 @@ MODULE_LICENSE("GPL");
+ #define BUG_ON(expr)
+ #endif
+ 
++static struct scsi_transport_template *iscsi_tcp_scsi_transport;
++static struct scsi_host_template iscsi_sht;
++static struct iscsi_transport iscsi_tcp_transport;
++
+ static unsigned int iscsi_max_lun = 512;
+ module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
+ 
+@@ -1623,6 +1627,8 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
+ 		    struct iscsi_cls_conn *cls_conn, uint64_t transport_eph,
+ 		    int is_leading)
+ {
++	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
++	struct iscsi_host *ihost = shost_priv(shost);
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	struct sock *sk;
+@@ -1646,8 +1652,8 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
+ 	if (err)
+ 		goto free_socket;
+ 
+-	err = iscsi_tcp_get_addr(conn, sock, conn->local_address,
+-				&conn->local_port, kernel_getsockname);
++	err = iscsi_tcp_get_addr(conn, sock, ihost->local_address,
++				&ihost->local_port, kernel_getsockname);
+ 	if (err)
+ 		goto free_socket;
+ 
+@@ -1821,29 +1827,6 @@ iscsi_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ 	return len;
+ }
+ 
+-static int
+-iscsi_tcp_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param,
+-			 char *buf)
+-{
+-        struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+-	int len;
+-
+-	switch (param) {
+-	case ISCSI_HOST_PARAM_IPADDRESS:
+-		spin_lock_bh(&session->lock);
+-		if (!session->leadconn)
+-			len = -ENODEV;
+-		else
+-			len = sprintf(buf, "%s\n",
+-				     session->leadconn->local_address);
+-		spin_unlock_bh(&session->lock);
+-		break;
+-	default:
+-		return iscsi_host_get_param(shost, param, buf);
+-	}
+-	return len;
+-}
+-
+ static void
+ iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats)
+ {
+@@ -1869,26 +1852,44 @@ iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats)
+ }
+ 
+ static struct iscsi_cls_session *
+-iscsi_tcp_session_create(struct iscsi_transport *iscsit,
+-			 struct scsi_transport_template *scsit,
+-			 struct Scsi_Host *shost, uint16_t cmds_max,
++iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max,
+ 			 uint16_t qdepth, uint32_t initial_cmdsn,
+ 			 uint32_t *hostno)
+ {
+ 	struct iscsi_cls_session *cls_session;
+ 	struct iscsi_session *session;
+-	uint32_t hn;
+ 	int cmd_i;
+ 
+-	cls_session = iscsi_session_setup(iscsit, scsit, cmds_max, qdepth,
+-					 sizeof(struct iscsi_tcp_cmd_task),
+-					 sizeof(struct iscsi_tcp_mgmt_task),
+-					 initial_cmdsn, &hn);
+-	if (!cls_session)
++	if (shost) {
++		printk(KERN_ERR "iscsi_tcp: invalid shost %d.\n",
++		       shost->host_no);
++		return NULL;
++	}
++
++	shost = scsi_host_alloc(&iscsi_sht, sizeof(struct iscsi_host));
++	if (!shost)
+ 		return NULL;
+-	*hostno = hn;
++	shost->transportt = iscsi_tcp_scsi_transport;
++	shost->max_lun = iscsi_max_lun;
++	shost->max_id = 0;
++	shost->max_channel = 0;
++	shost->max_cmd_len = 16;
++
++	iscsi_host_setup(shost, qdepth);
++
++	if (scsi_add_host(shost, NULL))
++		goto free_host;
++	*hostno = shost->host_no;
++
++	cls_session = iscsi_session_setup(&iscsi_tcp_transport, shost, cmds_max,
++					  sizeof(struct iscsi_tcp_cmd_task),
++					  sizeof(struct iscsi_tcp_mgmt_task),
++					  initial_cmdsn);
++	if (!cls_session)
++		goto remove_host;
++	session = cls_session->dd_data;
+ 
+-	session = class_to_transport_session(cls_session);
++	shost->can_queue = session->cmds_max;
+ 	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
+ 		struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
+ 		struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+@@ -1904,20 +1905,30 @@ iscsi_tcp_session_create(struct iscsi_transport *iscsit,
+ 		mtask->hdr = (struct iscsi_hdr *) &tcp_mtask->hdr;
+ 	}
+ 
+-	if (iscsi_r2tpool_alloc(class_to_transport_session(cls_session)))
+-		goto r2tpool_alloc_fail;
+-
++	if (iscsi_r2tpool_alloc(session))
++		goto remove_session;
+ 	return cls_session;
+ 
+-r2tpool_alloc_fail:
++remove_session:
+ 	iscsi_session_teardown(cls_session);
++remove_host:
++	scsi_remove_host(shost);
++free_host:
++	iscsi_host_teardown(shost);
++	scsi_host_put(shost);
+ 	return NULL;
+ }
+ 
+ static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session)
+ {
+-	iscsi_r2tpool_free(class_to_transport_session(cls_session));
++	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
++
++	iscsi_r2tpool_free(cls_session->dd_data);
+ 	iscsi_session_teardown(cls_session);
++
++	scsi_remove_host(shost);
++	iscsi_host_teardown(shost);
++	scsi_host_put(shost);
+ }
+ 
+ static int iscsi_tcp_slave_configure(struct scsi_device *sdev)
+@@ -1976,8 +1987,8 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+ 				  ISCSI_HOST_INITIATOR_NAME |
+ 				  ISCSI_HOST_NETDEV_NAME,
+-	.host_template		= &iscsi_sht,
+ 	.conndata_size		= sizeof(struct iscsi_conn),
++	.sessiondata_size	= sizeof(struct iscsi_session),
+ 	/* session management */
+ 	.create_session		= iscsi_tcp_session_create,
+ 	.destroy_session	= iscsi_tcp_session_destroy,
+@@ -1991,7 +2002,7 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 	.start_conn		= iscsi_conn_start,
+ 	.stop_conn		= iscsi_tcp_conn_stop,
+ 	/* iscsi host params */
+-	.get_host_param		= iscsi_tcp_host_get_param,
++	.get_host_param		= iscsi_host_get_param,
+ 	.set_host_param		= iscsi_host_set_param,
+ 	/* IO */
+ 	.send_pdu		= iscsi_conn_send_pdu,
+@@ -2013,9 +2024,10 @@ iscsi_tcp_init(void)
+ 		       iscsi_max_lun);
+ 		return -EINVAL;
+ 	}
+-	iscsi_tcp_transport.max_lun = iscsi_max_lun;
+ 
+-	if (!iscsi_register_transport(&iscsi_tcp_transport))
++	iscsi_tcp_scsi_transport = iscsi_register_transport(
++							&iscsi_tcp_transport);
++	if (!iscsi_tcp_scsi_transport)
+ 		return -ENODEV;
+ 
+ 	return 0;
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 01a1a4d36f21..64b1dd827366 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -38,14 +38,6 @@
+ #include 
+ #include 
+ 
+-struct iscsi_session *
+-class_to_transport_session(struct iscsi_cls_session *cls_session)
+-{
+-	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+-	return iscsi_hostdata(shost->hostdata);
+-}
+-EXPORT_SYMBOL_GPL(class_to_transport_session);
+-
+ /* Serial Number Arithmetic, 32 bits, less than, RFC1982 */
+ #define SNA32_CHECK 2147483648UL
+ 
+@@ -1096,6 +1088,7 @@ enum {
+ 
+ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ {
++	struct iscsi_cls_session *cls_session;
+ 	struct Scsi_Host *host;
+ 	int reason = 0;
+ 	struct iscsi_session *session;
+@@ -1109,10 +1102,11 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 	host = sc->device->host;
+ 	spin_unlock(host->host_lock);
+ 
+-	session = iscsi_hostdata(host->hostdata);
++	cls_session = starget_to_session(scsi_target(sc->device));
++	session = cls_session->dd_data;
+ 	spin_lock(&session->lock);
+ 
+-	reason = iscsi_session_chkready(session_to_cls(session));
++	reason = iscsi_session_chkready(cls_session);
+ 	if (reason) {
+ 		sc->result = reason;
+ 		goto fault;
+@@ -1222,7 +1216,7 @@ EXPORT_SYMBOL_GPL(iscsi_change_queue_depth);
+ 
+ void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session)
+ {
+-	struct iscsi_session *session = class_to_transport_session(cls_session);
++	struct iscsi_session *session = cls_session->dd_data;
+ 
+ 	spin_lock_bh(&session->lock);
+ 	if (session->state != ISCSI_STATE_LOGGED_IN) {
+@@ -1236,9 +1230,13 @@ EXPORT_SYMBOL_GPL(iscsi_session_recovery_timedout);
+ 
+ int iscsi_eh_host_reset(struct scsi_cmnd *sc)
+ {
+-	struct Scsi_Host *host = sc->device->host;
+-	struct iscsi_session *session = iscsi_hostdata(host->hostdata);
+-	struct iscsi_conn *conn = session->leadconn;
++	struct iscsi_cls_session *cls_session;
++	struct iscsi_session *session;
++	struct iscsi_conn *conn;
++
++	cls_session = starget_to_session(scsi_target(sc->device));
++	session = cls_session->dd_data;
++	conn = session->leadconn;
+ 
+ 	mutex_lock(&session->eh_mutex);
+ 	spin_lock_bh(&session->lock);
+@@ -1405,7 +1403,7 @@ static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
+ 	enum scsi_eh_timer_return rc = EH_NOT_HANDLED;
+ 
+ 	cls_session = starget_to_session(scsi_target(scmd->device));
+-	session = class_to_transport_session(cls_session);
++	session = cls_session->dd_data;
+ 
+ 	debug_scsi("scsi cmd %p timedout\n", scmd);
+ 
+@@ -1507,13 +1505,16 @@ static void iscsi_prep_abort_task_pdu(struct iscsi_cmd_task *ctask,
+ 
+ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ {
+-	struct Scsi_Host *host = sc->device->host;
+-	struct iscsi_session *session = iscsi_hostdata(host->hostdata);
++	struct iscsi_cls_session *cls_session;
++	struct iscsi_session *session;
+ 	struct iscsi_conn *conn;
+ 	struct iscsi_cmd_task *ctask;
+ 	struct iscsi_tm *hdr;
+ 	int rc, age;
+ 
++	cls_session = starget_to_session(scsi_target(sc->device));
++	session = cls_session->dd_data;
++
+ 	mutex_lock(&session->eh_mutex);
+ 	spin_lock_bh(&session->lock);
+ 	/*
+@@ -1630,12 +1631,15 @@ static void iscsi_prep_lun_reset_pdu(struct scsi_cmnd *sc, struct iscsi_tm *hdr)
+ 
+ int iscsi_eh_device_reset(struct scsi_cmnd *sc)
+ {
+-	struct Scsi_Host *host = sc->device->host;
+-	struct iscsi_session *session = iscsi_hostdata(host->hostdata);
++	struct iscsi_cls_session *cls_session;
++	struct iscsi_session *session;
+ 	struct iscsi_conn *conn;
+ 	struct iscsi_tm *hdr;
+ 	int rc = FAILED;
+ 
++	cls_session = starget_to_session(scsi_target(sc->device));
++	session = cls_session->dd_data;
++
+ 	debug_scsi("LU Reset [sc %p lun %u]\n", sc, sc->device->lun);
+ 
+ 	mutex_lock(&session->eh_mutex);
+@@ -1760,55 +1764,53 @@ void iscsi_pool_free(struct iscsi_pool *q)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_pool_free);
+ 
+-/*
+- * iSCSI Session's hostdata organization:
+- *
+- *    *------------------* <== hostdata_session(host->hostdata)
+- *    | ptr to class sess|
+- *    |------------------| <== iscsi_hostdata(host->hostdata)
+- *    | iscsi_session    |
+- *    *------------------*
+- */
++void iscsi_host_setup(struct Scsi_Host *shost, uint16_t qdepth)
++{
++	if (qdepth > ISCSI_MAX_CMD_PER_LUN || qdepth < 1) {
++		if (qdepth != 0)
++			printk(KERN_ERR "iscsi: invalid queue depth of %d. "
++			       "Queue depth must be between 1 and %d.\n",
++			       qdepth, ISCSI_MAX_CMD_PER_LUN);
++		qdepth = ISCSI_DEF_CMD_PER_LUN;
++	}
++
++	shost->transportt->create_work_queue = 1;
++	shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out;
++	shost->cmd_per_lun = qdepth;
++}
++EXPORT_SYMBOL_GPL(iscsi_host_setup);
+ 
+-#define hostdata_privsize(_sz)	(sizeof(unsigned long) + _sz + \
+-				 _sz % sizeof(unsigned long))
++void iscsi_host_teardown(struct Scsi_Host *shost)
++{
++	struct iscsi_host *ihost = shost_priv(shost);
+ 
+-#define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata))
++	kfree(ihost->netdev);
++	kfree(ihost->hwaddress);
++	kfree(ihost->initiatorname);
++}
++EXPORT_SYMBOL_GPL(iscsi_host_teardown);
+ 
+ /**
+  * iscsi_session_setup - create iscsi cls session and host and session
+- * @scsit: scsi transport template
+  * @iscsit: iscsi transport template
+- * @cmds_max: scsi host can queue
+- * @qdepth: scsi host cmds per lun
++ * @shost: scsi host
++ * @cmds_max: session can queue
+  * @cmd_task_size: LLD ctask private data size
+  * @mgmt_task_size: LLD mtask private data size
+  * @initial_cmdsn: initial CmdSN
+- * @hostno: host no allocated
+  *
+  * This can be used by software iscsi_transports that allocate
+  * a session per scsi host.
+- **/
++ */
+ struct iscsi_cls_session *
+-iscsi_session_setup(struct iscsi_transport *iscsit,
+-		    struct scsi_transport_template *scsit,
+-		    uint16_t cmds_max, uint16_t qdepth,
+-		    int cmd_task_size, int mgmt_task_size,
+-		    uint32_t initial_cmdsn, uint32_t *hostno)
++iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
++		    uint16_t cmds_max, int cmd_task_size, int mgmt_task_size,
++		    uint32_t initial_cmdsn)
+ {
+-	struct Scsi_Host *shost;
+ 	struct iscsi_session *session;
+ 	struct iscsi_cls_session *cls_session;
+ 	int cmd_i;
+ 
+-	if (qdepth > ISCSI_MAX_CMD_PER_LUN || qdepth < 1) {
+-		if (qdepth != 0)
+-			printk(KERN_ERR "iscsi: invalid queue depth of %d. "
+-			      "Queue depth must be between 1 and %d.\n",
+-			      qdepth, ISCSI_MAX_CMD_PER_LUN);
+-		qdepth = ISCSI_DEF_CMD_PER_LUN;
+-	}
+-
+ 	if (!is_power_of_2(cmds_max) || cmds_max >= ISCSI_MGMT_ITT_OFFSET ||
+ 	    cmds_max < 2) {
+ 		if (cmds_max != 0)
+@@ -1819,25 +1821,11 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
+ 		cmds_max = ISCSI_DEF_XMIT_CMDS_MAX;
+ 	}
+ 
+-	shost = scsi_host_alloc(iscsit->host_template,
+-				hostdata_privsize(sizeof(*session)));
+-	if (!shost)
++	cls_session = iscsi_alloc_session(shost, iscsit);
++	if (!cls_session)
+ 		return NULL;
+-
+-	/* the iscsi layer takes one task for reserve */
+-	shost->can_queue = cmds_max - 1;
+-	shost->cmd_per_lun = qdepth;
+-	shost->max_id = 1;
+-	shost->max_channel = 0;
+-	shost->max_lun = iscsit->max_lun;
+-	shost->max_cmd_len = 16;
+-	shost->transportt = scsit;
+-	shost->transportt->create_work_queue = 1;
+-	shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out;
+-	*hostno = shost->host_no;
+-
+-	session = iscsi_hostdata(shost->hostdata);
+-	memset(session, 0, sizeof(struct iscsi_session));
++	session = cls_session->dd_data;
++	session->cls_session = cls_session;
+ 	session->host = shost;
+ 	session->state = ISCSI_STATE_FREE;
+ 	session->fast_abort = 1;
+@@ -1851,6 +1839,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
+ 	session->max_r2t = 1;
+ 	session->tt = iscsit;
+ 	mutex_init(&session->eh_mutex);
++	spin_lock_init(&session->lock);
+ 
+ 	/* initialize SCSI PDU commands pool */
+ 	if (iscsi_pool_init(&session->cmdpool, session->cmds_max,
+@@ -1868,8 +1857,6 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
+ 		INIT_LIST_HEAD(&ctask->running);
+ 	}
+ 
+-	spin_lock_init(&session->lock);
+-
+ 	/* initialize immediate command pool */
+ 	if (iscsi_pool_init(&session->mgmtpool, session->mgmtpool_max,
+ 			   (void***)&session->mgmt_cmds,
+@@ -1887,49 +1874,37 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
+ 		INIT_LIST_HEAD(&mtask->running);
+ 	}
+ 
+-	if (scsi_add_host(shost, NULL))
+-		goto add_host_fail;
+-
+ 	if (!try_module_get(iscsit->owner))
+-		goto cls_session_fail;
+-
+-	cls_session = iscsi_create_session(shost, iscsit, 0);
+-	if (!cls_session)
+-		goto module_put;
+-	*(unsigned long*)shost->hostdata = (unsigned long)cls_session;
++		goto module_get_fail;
+ 
++	if (iscsi_add_session(cls_session, 0))
++		goto cls_session_fail;
+ 	return cls_session;
+ 
+-module_put:
+-	module_put(iscsit->owner);
+ cls_session_fail:
+-	scsi_remove_host(shost);
+-add_host_fail:
++	module_put(iscsit->owner);
++module_get_fail:
+ 	iscsi_pool_free(&session->mgmtpool);
+ mgmtpool_alloc_fail:
+ 	iscsi_pool_free(&session->cmdpool);
+ cmdpool_alloc_fail:
+-	scsi_host_put(shost);
++	iscsi_free_session(cls_session);
+ 	return NULL;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_session_setup);
+ 
+ /**
+  * iscsi_session_teardown - destroy session, host, and cls_session
+- * shost: scsi host
++ * @cls_session: iscsi session
+  *
+- * This can be used by software iscsi_transports that allocate
+- * a session per scsi host.
+- **/
++ * The driver must have called iscsi_remove_session before
++ * calling this.
++ */
+ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+ {
+-	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+-	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
++	struct iscsi_session *session = cls_session->dd_data;
+ 	struct module *owner = cls_session->transport->owner;
+ 
+-	iscsi_remove_session(cls_session);
+-	scsi_remove_host(shost);
+-
+ 	iscsi_pool_free(&session->mgmtpool);
+ 	iscsi_pool_free(&session->cmdpool);
+ 
+@@ -1938,12 +1913,8 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+ 	kfree(session->username);
+ 	kfree(session->username_in);
+ 	kfree(session->targetname);
+-	kfree(session->netdev);
+-	kfree(session->hwaddress);
+-	kfree(session->initiatorname);
+ 
+-	iscsi_free_session(cls_session);
+-	scsi_host_put(shost);
++	iscsi_destroy_session(cls_session);
+ 	module_put(owner);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_session_teardown);
+@@ -1956,7 +1927,7 @@ EXPORT_SYMBOL_GPL(iscsi_session_teardown);
+ struct iscsi_cls_conn *
+ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ {
+-	struct iscsi_session *session = class_to_transport_session(cls_session);
++	struct iscsi_session *session = cls_session->dd_data;
+ 	struct iscsi_conn *conn;
+ 	struct iscsi_cls_conn *cls_conn;
+ 	char *data;
+@@ -2140,7 +2111,7 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
+ 	}
+ 	spin_unlock_bh(&session->lock);
+ 
+-	iscsi_unblock_session(session_to_cls(session));
++	iscsi_unblock_session(session->cls_session);
+ 	wake_up(&conn->ehwait);
+ 	return 0;
+ }
+@@ -2225,7 +2196,7 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ 		if (session->state == ISCSI_STATE_IN_RECOVERY &&
+ 		    old_stop_stage != STOP_CONN_RECOVER) {
+ 			debug_scsi("blocking session\n");
+-			iscsi_block_session(session_to_cls(session));
++			iscsi_block_session(session->cls_session);
+ 		}
+ 	}
+ 
+@@ -2260,7 +2231,7 @@ EXPORT_SYMBOL_GPL(iscsi_conn_stop);
+ int iscsi_conn_bind(struct iscsi_cls_session *cls_session,
+ 		    struct iscsi_cls_conn *cls_conn, int is_leading)
+ {
+-	struct iscsi_session *session = class_to_transport_session(cls_session);
++	struct iscsi_session *session = cls_session->dd_data;
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+ 
+ 	spin_lock_bh(&session->lock);
+@@ -2410,8 +2381,7 @@ EXPORT_SYMBOL_GPL(iscsi_set_param);
+ int iscsi_session_get_param(struct iscsi_cls_session *cls_session,
+ 			    enum iscsi_param param, char *buf)
+ {
+-	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+-	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
++	struct iscsi_session *session = cls_session->dd_data;
+ 	int len;
+ 
+ 	switch(param) {
+@@ -2525,29 +2495,34 @@ EXPORT_SYMBOL_GPL(iscsi_conn_get_param);
+ int iscsi_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param,
+ 			 char *buf)
+ {
+-	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
++	struct iscsi_host *ihost = shost_priv(shost);
+ 	int len;
+ 
+ 	switch (param) {
+ 	case ISCSI_HOST_PARAM_NETDEV_NAME:
+-		if (!session->netdev)
++		if (!ihost->netdev)
+ 			len = sprintf(buf, "%s\n", "default");
+ 		else
+-			len = sprintf(buf, "%s\n", session->netdev);
++			len = sprintf(buf, "%s\n", ihost->netdev);
+ 		break;
+ 	case ISCSI_HOST_PARAM_HWADDRESS:
+-		if (!session->hwaddress)
++		if (!ihost->hwaddress)
+ 			len = sprintf(buf, "%s\n", "default");
+ 		else
+-			len = sprintf(buf, "%s\n", session->hwaddress);
++			len = sprintf(buf, "%s\n", ihost->hwaddress);
+ 		break;
+ 	case ISCSI_HOST_PARAM_INITIATOR_NAME:
+-		if (!session->initiatorname)
++		if (!ihost->initiatorname)
+ 			len = sprintf(buf, "%s\n", "unknown");
+ 		else
+-			len = sprintf(buf, "%s\n", session->initiatorname);
++			len = sprintf(buf, "%s\n", ihost->initiatorname);
+ 		break;
+-
++	case ISCSI_HOST_PARAM_IPADDRESS:
++		if (!strlen(ihost->local_address))
++			len = sprintf(buf, "%s\n", "unknown");
++		else
++			len = sprintf(buf, "%s\n",
++				      ihost->local_address);
+ 	default:
+ 		return -ENOSYS;
+ 	}
+@@ -2559,20 +2534,20 @@ EXPORT_SYMBOL_GPL(iscsi_host_get_param);
+ int iscsi_host_set_param(struct Scsi_Host *shost, enum iscsi_host_param param,
+ 			 char *buf, int buflen)
+ {
+-	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
++	struct iscsi_host *ihost = shost_priv(shost);
+ 
+ 	switch (param) {
+ 	case ISCSI_HOST_PARAM_NETDEV_NAME:
+-		if (!session->netdev)
+-			session->netdev = kstrdup(buf, GFP_KERNEL);
++		if (!ihost->netdev)
++			ihost->netdev = kstrdup(buf, GFP_KERNEL);
+ 		break;
+ 	case ISCSI_HOST_PARAM_HWADDRESS:
+-		if (!session->hwaddress)
+-			session->hwaddress = kstrdup(buf, GFP_KERNEL);
++		if (!ihost->hwaddress)
++			ihost->hwaddress = kstrdup(buf, GFP_KERNEL);
+ 		break;
+ 	case ISCSI_HOST_PARAM_INITIATOR_NAME:
+-		if (!session->initiatorname)
+-			session->initiatorname = kstrdup(buf, GFP_KERNEL);
++		if (!ihost->initiatorname)
++			ihost->initiatorname = kstrdup(buf, GFP_KERNEL);
+ 		break;
+ 	default:
+ 		return -ENOSYS;
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index 0c786944d2c2..6c6ee0f34995 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -114,7 +114,6 @@ static struct iscsi_transport qla4xxx_iscsi_transport = {
+ 				  ISCSI_HOST_IPADDRESS |
+ 				  ISCSI_HOST_INITIATOR_NAME,
+ 	.sessiondata_size	= sizeof(struct ddb_entry),
+-	.host_template		= &qla4xxx_driver_template,
+ 
+ 	.tgt_dscvr		= qla4xxx_tgt_dscvr,
+ 	.get_conn_param		= qla4xxx_conn_get_param,
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 5577a60bec4e..9c00a157b485 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -101,12 +101,10 @@ show_transport_##name(struct device *dev, 				\
+ static DEVICE_ATTR(name, S_IRUGO, show_transport_##name, NULL);
+ 
+ show_transport_attr(caps, "0x%x");
+-show_transport_attr(max_lun, "%d");
+ 
+ static struct attribute *iscsi_transport_attrs[] = {
+ 	&dev_attr_handle.attr,
+ 	&dev_attr_caps.attr,
+-	&dev_attr_max_lun.attr,
+ 	NULL,
+ };
+ 
+@@ -1034,8 +1032,7 @@ iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev,
+ 		}
+ 	}
+ 
+-	session = transport->create_session(transport, &priv->t, shost,
+-					    cmds_max, queue_depth,
++	session = transport->create_session(shost, cmds_max, queue_depth,
+ 					    initial_cmdsn, &host_no);
+ 	if (shost)
+ 		scsi_host_put(shost);
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index 1883c85cd3ee..801a677777cc 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -310,13 +310,6 @@ enum iscsi_host_param {
+ 
+ #define iscsi_ptr(_handle) ((void*)(unsigned long)_handle)
+ #define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr)
+-#define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata))
+-
+-/**
+- * iscsi_hostdata - get LLD hostdata from scsi_host
+- * @_hostdata: pointer to scsi host's hostdata
+- **/
+-#define iscsi_hostdata(_hostdata) ((void*)_hostdata + sizeof(unsigned long))
+ 
+ /*
+  * These flags presents iSCSI Data-Path capabilities.
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index f24cf0246739..8a6271c20935 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -209,9 +209,6 @@ struct iscsi_conn {
+ 	/* remote portal currently connected to */
+ 	int			portal_port;
+ 	char			portal_address[ISCSI_ADDRESS_BUF_LEN];
+-	/* local address */
+-	int			local_port;
+-	char			local_address[ISCSI_ADDRESS_BUF_LEN];
+ 
+ 	/* MIB-statistics */
+ 	uint64_t		txdata_octets;
+@@ -247,6 +244,7 @@ enum {
+ };
+ 
+ struct iscsi_session {
++	struct iscsi_cls_session *cls_session;
+ 	/*
+ 	 * Syncs up the scsi eh thread with the iscsi eh thread when sending
+ 	 * task management functions. This must be taken before the session
+@@ -282,10 +280,6 @@ struct iscsi_session {
+ 	char			*password;
+ 	char			*password_in;
+ 	char			*targetname;
+-	char			*initiatorname;
+-	/* hw address or netdev iscsi connection is bound to */
+-	char			*hwaddress;
+-	char			*netdev;
+ 	/* control data */
+ 	struct iscsi_transport	*tt;
+ 	struct Scsi_Host	*host;
+@@ -307,6 +301,16 @@ struct iscsi_session {
+ 	struct iscsi_pool	mgmtpool;	/* Mgmt PDU's pool */
+ };
+ 
++struct iscsi_host {
++	char			*initiatorname;
++	/* hw address or netdev iscsi connection is bound to */
++	char			*hwaddress;
++	char			*netdev;
++	/* local address */
++	int			local_port;
++	char			local_address[ISCSI_ADDRESS_BUF_LEN];
++};
++
+ /*
+  * scsi host template
+  */
+@@ -326,27 +330,24 @@ extern int iscsi_host_set_param(struct Scsi_Host *shost,
+ 				int buflen);
+ extern int iscsi_host_get_param(struct Scsi_Host *shost,
+ 				enum iscsi_host_param param, char *buf);
++extern void iscsi_host_setup(struct Scsi_Host *shost, uint16_t qdepth);
++extern void iscsi_host_teardown(struct Scsi_Host *shost);
+ 
+ /*
+  * session management
+  */
+ extern struct iscsi_cls_session *
+-iscsi_session_setup(struct iscsi_transport *, struct scsi_transport_template *,
+-		    uint16_t, uint16_t, int, int, uint32_t, uint32_t *);
++iscsi_session_setup(struct iscsi_transport *, struct Scsi_Host *shost,
++		    uint16_t, int, int, uint32_t);
+ extern void iscsi_session_teardown(struct iscsi_cls_session *);
+-extern struct iscsi_session *class_to_transport_session(struct iscsi_cls_session *);
+ extern void iscsi_session_recovery_timedout(struct iscsi_cls_session *);
+ extern int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
+ 			   enum iscsi_param param, char *buf, int buflen);
+ extern int iscsi_session_get_param(struct iscsi_cls_session *cls_session,
+ 				   enum iscsi_param param, char *buf);
+ 
+-#define session_to_cls(_sess) \
+-	hostdata_session(_sess->host->hostdata)
+-
+ #define iscsi_session_printk(prefix, _sess, fmt, a...)	\
+-	iscsi_cls_session_printk(prefix,		\
+-		(struct iscsi_cls_session *)session_to_cls(_sess), fmt, ##a)
++	iscsi_cls_session_printk(prefix, _sess->cls_session, fmt, ##a)
+ 
+ /*
+  * connection management
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 728702292a80..702eda2904d7 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -83,15 +83,13 @@ struct iscsi_transport {
+ 	/* LLD sets this to indicate what values it can export to sysfs */
+ 	uint64_t param_mask;
+ 	uint64_t host_param_mask;
+-	struct scsi_host_template *host_template;
+ 	/* LLD connection data size */
+ 	int conndata_size;
+ 	/* LLD session data size */
+ 	int sessiondata_size;
+-	int max_lun;
+-	struct iscsi_cls_session *(*create_session) (struct iscsi_transport *it,
+-		struct scsi_transport_template *t, struct Scsi_Host *shost,
+-		uint16_t cmds_max, uint16_t qdepth, uint32_t sn, uint32_t *hn);
++	struct iscsi_cls_session *(*create_session) (struct Scsi_Host *shost,
++					uint16_t cmds_max, uint16_t qdepth,
++					uint32_t sn, uint32_t *hn);
+ 	void (*destroy_session) (struct iscsi_cls_session *session);
+ 	struct iscsi_cls_conn *(*create_conn) (struct iscsi_cls_session *sess,
+ 				uint32_t cid);

commit 32c6e1b9a2e27076b7070a9ec56a9e5437ebd725
+Author: Mike Christie 
+Date:   Wed May 21 15:53:58 2008 -0500
+
+    [SCSI] iscsi class: rename iscsi_host to iscsi_cls_host
+    
+    This renames the iscsi_host to iscsi_cls_host to match the other
+    structs, because libiscsi wants to use the iscsi_host name in
+    the future.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index e6a090e9c8a4..5577a60bec4e 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -114,13 +114,11 @@ static struct attribute_group iscsi_transport_group = {
+ 	.attrs = iscsi_transport_attrs,
+ };
+ 
+-
+-
+ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+ 			    struct device *cdev)
+ {
+ 	struct Scsi_Host *shost = dev_to_shost(dev);
+-	struct iscsi_host *ihost = shost->shost_data;
++	struct iscsi_cls_host *ihost = shost->shost_data;
+ 
+ 	memset(ihost, 0, sizeof(*ihost));
+ 	INIT_LIST_HEAD(&ihost->sessions);
+@@ -140,7 +138,7 @@ static int iscsi_remove_host(struct transport_container *tc, struct device *dev,
+ 			     struct device *cdev)
+ {
+ 	struct Scsi_Host *shost = dev_to_shost(dev);
+-	struct iscsi_host *ihost = shost->shost_data;
++	struct iscsi_cls_host *ihost = shost->shost_data;
+ 
+ 	destroy_workqueue(ihost->scan_workq);
+ 	return 0;
+@@ -293,7 +291,7 @@ static int iscsi_is_session_dev(const struct device *dev)
+  */
+ int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time)
+ {
+-	struct iscsi_host *ihost = shost->shost_data;
++	struct iscsi_cls_host *ihost = shost->shost_data;
+ 	/*
+ 	 * qla4xxx will have kicked off some session unblocks before calling
+ 	 * scsi_scan_host, so just wait for them to complete.
+@@ -305,7 +303,7 @@ EXPORT_SYMBOL_GPL(iscsi_scan_finished);
+ static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
+ 			   uint id, uint lun)
+ {
+-	struct iscsi_host *ihost = shost->shost_data;
++	struct iscsi_cls_host *ihost = shost->shost_data;
+ 	struct iscsi_cls_session *session;
+ 
+ 	mutex_lock(&ihost->mutex);
+@@ -325,7 +323,7 @@ static void iscsi_scan_session(struct work_struct *work)
+ 	struct iscsi_cls_session *session =
+ 			container_of(work, struct iscsi_cls_session, scan_work);
+ 	struct Scsi_Host *shost = iscsi_session_to_shost(session);
+-	struct iscsi_host *ihost = shost->shost_data;
++	struct iscsi_cls_host *ihost = shost->shost_data;
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&session->lock, flags);
+@@ -377,7 +375,7 @@ static void __iscsi_unblock_session(struct work_struct *work)
+ 			container_of(work, struct iscsi_cls_session,
+ 				     unblock_work);
+ 	struct Scsi_Host *shost = iscsi_session_to_shost(session);
+-	struct iscsi_host *ihost = shost->shost_data;
++	struct iscsi_cls_host *ihost = shost->shost_data;
+ 	unsigned long flags;
+ 
+ 	/*
+@@ -445,7 +443,7 @@ static void __iscsi_unbind_session(struct work_struct *work)
+ 			container_of(work, struct iscsi_cls_session,
+ 				     unbind_work);
+ 	struct Scsi_Host *shost = iscsi_session_to_shost(session);
+-	struct iscsi_host *ihost = shost->shost_data;
++	struct iscsi_cls_host *ihost = shost->shost_data;
+ 
+ 	/* Prevent new scans and make sure scanning is not in progress */
+ 	mutex_lock(&ihost->mutex);
+@@ -463,7 +461,7 @@ static void __iscsi_unbind_session(struct work_struct *work)
+ static int iscsi_unbind_session(struct iscsi_cls_session *session)
+ {
+ 	struct Scsi_Host *shost = iscsi_session_to_shost(session);
+-	struct iscsi_host *ihost = shost->shost_data;
++	struct iscsi_cls_host *ihost = shost->shost_data;
+ 
+ 	return queue_work(ihost->scan_workq, &session->unbind_work);
+ }
+@@ -505,7 +503,7 @@ EXPORT_SYMBOL_GPL(iscsi_alloc_session);
+ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
+ {
+ 	struct Scsi_Host *shost = iscsi_session_to_shost(session);
+-	struct iscsi_host *ihost;
++	struct iscsi_cls_host *ihost;
+ 	unsigned long flags;
+ 	int err;
+ 
+@@ -591,7 +589,7 @@ static int iscsi_iter_destroy_conn_fn(struct device *dev, void *data)
+ void iscsi_remove_session(struct iscsi_cls_session *session)
+ {
+ 	struct Scsi_Host *shost = iscsi_session_to_shost(session);
+-	struct iscsi_host *ihost = shost->shost_data;
++	struct iscsi_cls_host *ihost = shost->shost_data;
+ 	unsigned long flags;
+ 	int err;
+ 
+@@ -1619,7 +1617,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 	priv->t.host_attrs.ac.attrs = &priv->host_attrs[0];
+ 	priv->t.host_attrs.ac.class = &iscsi_host_class.class;
+ 	priv->t.host_attrs.ac.match = iscsi_host_match;
+-	priv->t.host_size = sizeof(struct iscsi_host);
++	priv->t.host_size = sizeof(struct iscsi_cls_host);
+ 	transport_container_register(&priv->t.host_attrs);
+ 
+ 	SETUP_HOST_RD_ATTR(netdev, ISCSI_HOST_NETDEV_NAME);
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index afed70ec2aa5..728702292a80 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -201,7 +201,7 @@ struct iscsi_cls_session {
+ #define starget_to_session(_stgt) \
+ 	iscsi_dev_to_session(_stgt->dev.parent)
+ 
+-struct iscsi_host {
++struct iscsi_cls_host {
+ 	struct list_head sessions;
+ 	atomic_t nr_scans;
+ 	struct mutex mutex;

commit d3826721b198001c55353b1c54e10843068aae63
+Author: Mike Christie 
+Date:   Wed May 21 15:53:57 2008 -0500
+
+    [SCSI] iscsi class, iscsi drivers: remove unused iscsi_transport attrs
+    
+    max_cmd_len and max_conn are not really used. max_cmd_len is
+    always 16 and can be set by the LLD. max_conn is always one
+    since we do not support MCS.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index efc121986c50..32f5d5e79abf 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -592,7 +592,6 @@ static struct iscsi_transport iscsi_iser_transport = {
+ 	.host_template          = &iscsi_iser_sht,
+ 	.conndata_size		= sizeof(struct iscsi_conn),
+ 	.max_lun                = ISCSI_ISER_MAX_LUN,
+-	.max_cmd_len            = ISCSI_ISER_MAX_CMD_LEN,
+ 	/* session management */
+ 	.create_session         = iscsi_iser_session_create,
+ 	.destroy_session        = iscsi_session_teardown,
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
+index a8c1b300e34d..66a2f30ada01 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
+@@ -96,7 +96,6 @@
+ 					/* support upto 512KB in one RDMA */
+ #define ISCSI_ISER_SG_TABLESIZE         (0x80000 >> SHIFT_4K)
+ #define ISCSI_ISER_MAX_LUN		256
+-#define ISCSI_ISER_MAX_CMD_LEN		16
+ 
+ /* QP settings */
+ /* Maximal bounds on received asynchronous PDUs */
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 81c421a7d477..aecadbdce9df 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -1978,8 +1978,6 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 				  ISCSI_HOST_NETDEV_NAME,
+ 	.host_template		= &iscsi_sht,
+ 	.conndata_size		= sizeof(struct iscsi_conn),
+-	.max_conn		= 1,
+-	.max_cmd_len		= 16,
+ 	/* session management */
+ 	.create_session		= iscsi_tcp_session_create,
+ 	.destroy_session	= iscsi_tcp_session_destroy,
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index b43bf1d60dac..01a1a4d36f21 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1830,7 +1830,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
+ 	shost->max_id = 1;
+ 	shost->max_channel = 0;
+ 	shost->max_lun = iscsit->max_lun;
+-	shost->max_cmd_len = iscsit->max_cmd_len;
++	shost->max_cmd_len = 16;
+ 	shost->transportt = scsit;
+ 	shost->transportt->create_work_queue = 1;
+ 	shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out;
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 2a6669d967cb..e6a090e9c8a4 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -102,15 +102,11 @@ static DEVICE_ATTR(name, S_IRUGO, show_transport_##name, NULL);
+ 
+ show_transport_attr(caps, "0x%x");
+ show_transport_attr(max_lun, "%d");
+-show_transport_attr(max_conn, "%d");
+-show_transport_attr(max_cmd_len, "%d");
+ 
+ static struct attribute *iscsi_transport_attrs[] = {
+ 	&dev_attr_handle.attr,
+ 	&dev_attr_caps.attr,
+ 	&dev_attr_max_lun.attr,
+-	&dev_attr_max_conn.attr,
+-	&dev_attr_max_cmd_len.attr,
+ 	NULL,
+ };
+ 
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 02a852000be7..afed70ec2aa5 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -89,8 +89,6 @@ struct iscsi_transport {
+ 	/* LLD session data size */
+ 	int sessiondata_size;
+ 	int max_lun;
+-	unsigned int max_conn;
+-	unsigned int max_cmd_len;
+ 	struct iscsi_cls_session *(*create_session) (struct iscsi_transport *it,
+ 		struct scsi_transport_template *t, struct Scsi_Host *shost,
+ 		uint16_t cmds_max, uint16_t qdepth, uint32_t sn, uint32_t *hn);

commit 40753caa364bfba60ebd5e2a8bdf366ef175d03c
+Author: Mike Christie 
+Date:   Wed May 21 15:53:56 2008 -0500
+
+    [SCSI] iscsi class, iscsi_tcp/iser: add host arg to session creation
+    
+    iscsi offload (bnx2i and qla4xx) allocate a scsi host per hba,
+    so the session creation path needs a shost/host_no argument.
+    Software iscsi/iser will follow the same behabior as before
+    where it allcoates a host per session, but in the future iser
+    will probably look more like bnx2i where the host's parent is
+    the hardware (rnic for iser and for bnx2i it is the nic), because
+    it does not use a socket layer like how iscsi_tcp does.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index aeb58cae9a3f..efc121986c50 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -368,6 +368,7 @@ static struct iscsi_transport iscsi_iser_transport;
+ static struct iscsi_cls_session *
+ iscsi_iser_session_create(struct iscsi_transport *iscsit,
+ 			 struct scsi_transport_template *scsit,
++			 struct Scsi_Host *shost,
+ 			 uint16_t cmds_max, uint16_t qdepth,
+ 			 uint32_t initial_cmdsn, uint32_t *hostno)
+ {
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 72b9b2a0eba3..81c421a7d477 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -1871,8 +1871,9 @@ iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats)
+ static struct iscsi_cls_session *
+ iscsi_tcp_session_create(struct iscsi_transport *iscsit,
+ 			 struct scsi_transport_template *scsit,
+-			 uint16_t cmds_max, uint16_t qdepth,
+-			 uint32_t initial_cmdsn, uint32_t *hostno)
++			 struct Scsi_Host *shost, uint16_t cmds_max,
++			 uint16_t qdepth, uint32_t initial_cmdsn,
++			 uint32_t *hostno)
+ {
+ 	struct iscsi_cls_session *cls_session;
+ 	struct iscsi_session *session;
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 65d1737eb664..2a6669d967cb 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -1017,21 +1017,38 @@ int iscsi_session_event(struct iscsi_cls_session *session,
+ EXPORT_SYMBOL_GPL(iscsi_session_event);
+ 
+ static int
+-iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
++iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev,
++			uint32_t host_no, uint32_t initial_cmdsn,
++			uint16_t cmds_max, uint16_t queue_depth)
+ {
+ 	struct iscsi_transport *transport = priv->iscsi_transport;
+ 	struct iscsi_cls_session *session;
+-	uint32_t hostno;
++	struct Scsi_Host *shost = NULL;
+ 
+-	session = transport->create_session(transport, &priv->t,
+-					    ev->u.c_session.cmds_max,
+-					    ev->u.c_session.queue_depth,
+-					    ev->u.c_session.initial_cmdsn,
+-					    &hostno);
++	/*
++	 * Software iscsi allocates a host per session, but
++	 * offload drivers (and possibly iser one day) allocate a host per
++	 * hba/nic/rnic. Offload will match a host here, but software will
++	 * return a new hostno after the create_session callback has returned.
++	 */
++	if (host_no != UINT_MAX) {
++		shost = scsi_host_lookup(host_no);
++		if (IS_ERR(shost)) {
++			printk(KERN_ERR "Could not find host no %u to "
++			       "create session\n", host_no);
++			return -ENODEV;
++		}
++	}
++
++	session = transport->create_session(transport, &priv->t, shost,
++					    cmds_max, queue_depth,
++					    initial_cmdsn, &host_no);
++	if (shost)
++		scsi_host_put(shost);
+ 	if (!session)
+ 		return -ENOMEM;
+ 
+-	ev->r.c_session_ret.host_no = hostno;
++	ev->r.c_session_ret.host_no = host_no;
+ 	ev->r.c_session_ret.sid = session->sid;
+ 	return 0;
+ }
+@@ -1190,6 +1207,7 @@ static int
+ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ {
+ 	int err = 0;
++	uint32_t host_no = UINT_MAX;
+ 	struct iscsi_uevent *ev = NLMSG_DATA(nlh);
+ 	struct iscsi_transport *transport = NULL;
+ 	struct iscsi_internal *priv;
+@@ -1208,7 +1226,17 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 
+ 	switch (nlh->nlmsg_type) {
+ 	case ISCSI_UEVENT_CREATE_SESSION:
+-		err = iscsi_if_create_session(priv, ev);
++		err = iscsi_if_create_session(priv, ev, host_no,
++					      ev->u.c_session.initial_cmdsn,
++					      ev->u.c_session.cmds_max,
++					      ev->u.c_session.queue_depth);
++		break;
++	case ISCSI_UEVENT_CREATE_BOUND_SESSION:
++		err = iscsi_if_create_session(priv, ev,
++					ev->u.c_bound_session.host_no,
++					ev->u.c_bound_session.initial_cmdsn,
++					ev->u.c_bound_session.cmds_max,
++					ev->u.c_bound_session.queue_depth);
+ 		break;
+ 	case ISCSI_UEVENT_DESTROY_SESSION:
+ 		session = iscsi_session_lookup(ev->u.d_session.sid);
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index e19e58423166..1883c85cd3ee 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -50,6 +50,7 @@ enum iscsi_uevent_e {
+ 	ISCSI_UEVENT_TGT_DSCVR		= UEVENT_BASE + 15,
+ 	ISCSI_UEVENT_SET_HOST_PARAM	= UEVENT_BASE + 16,
+ 	ISCSI_UEVENT_UNBIND_SESSION	= UEVENT_BASE + 17,
++	ISCSI_UEVENT_CREATE_BOUND_SESSION	= UEVENT_BASE + 18,
+ 
+ 	/* up events */
+ 	ISCSI_KEVENT_RECV_PDU		= KEVENT_BASE + 1,
+@@ -78,6 +79,12 @@ struct iscsi_uevent {
+ 			uint16_t	cmds_max;
+ 			uint16_t	queue_depth;
+ 		} c_session;
++		struct msg_create_bound_session {
++			uint32_t	host_no;
++			uint32_t	initial_cmdsn;
++			uint16_t	cmds_max;
++			uint16_t	queue_depth;
++		} c_bound_session;
+ 		struct msg_destroy_session {
+ 			uint32_t	sid;
+ 		} d_session;
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index cd3ca63d4fb1..f24cf0246739 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -24,6 +24,7 @@
+ #define LIBISCSI_H
+ 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index aab1eae2ec4c..02a852000be7 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -92,8 +92,8 @@ struct iscsi_transport {
+ 	unsigned int max_conn;
+ 	unsigned int max_cmd_len;
+ 	struct iscsi_cls_session *(*create_session) (struct iscsi_transport *it,
+-		struct scsi_transport_template *t, uint16_t, uint16_t,
+-		uint32_t sn, uint32_t *hn);
++		struct scsi_transport_template *t, struct Scsi_Host *shost,
++		uint16_t cmds_max, uint16_t qdepth, uint32_t sn, uint32_t *hn);
+ 	void (*destroy_session) (struct iscsi_cls_session *session);
+ 	struct iscsi_cls_conn *(*create_conn) (struct iscsi_cls_session *sess,
+ 				uint32_t cid);

commit 3ed7897242b7efe977f3a8d06d4e5a4ebe28b10e
+Author: Mike Christie 
+Date:   Wed Jun 11 19:21:00 2008 -0500
+
+    [SCSI] scsi_host regression: fix scsi host leak
+    
+    commit 9c7701088a61cc0cf8a6e1c68d1e74e3cc2ee0b7
+    Author: Dave Young 
+    Date:   Tue Jan 22 14:01:34 2008 +0800
+    
+        scsi: use class iteration api
+    
+    Isn't a correct replacement for the original hand rolled host
+    lookup. The problem is that class_find_child would get a reference to
+    the host's class device which is never released.  Since the host class
+    device holds a reference to the host gendev, the host can never be
+    freed.
+    
+    In 2.6.26 we started using class_find_device, and this function also
+    gets a reference to the device, so we end up with an extra ref
+    and the host will not get released.
+    
+    This patch adds a put_device to balance the class_find_device() get. I
+    kept the scsi_host_get in scsi_host_lookup, because the target layer
+    is using scsi_host_lookup and it looks like it needs the SHOST_DEL
+    check.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
+index 3690360d7a79..c6457bfc8a49 100644
+--- a/drivers/scsi/hosts.c
++++ b/drivers/scsi/hosts.c
+@@ -456,6 +456,10 @@ static int __scsi_host_match(struct device *dev, void *data)
+  *
+  * Return value:
+  *	A pointer to located Scsi_Host or NULL.
++ *
++ *	The caller must do a scsi_host_put() to drop the reference
++ *	that scsi_host_get() took. The put_device() below dropped
++ *	the reference from class_find_device().
+  **/
+ struct Scsi_Host *scsi_host_lookup(unsigned short hostnum)
+ {
+@@ -463,9 +467,10 @@ struct Scsi_Host *scsi_host_lookup(unsigned short hostnum)
+ 	struct Scsi_Host *shost = ERR_PTR(-ENXIO);
+ 
+ 	cdev = class_find_device(&shost_class, &hostnum, __scsi_host_match);
+-	if (cdev)
++	if (cdev) {
+ 		shost = scsi_host_get(class_to_shost(cdev));
+-
++		put_device(cdev);
++	}
+ 	return shost;
+ }
+ EXPORT_SYMBOL(scsi_host_lookup);

commit f6dd337ee4c440f29a873da3779eb3af44bd1623
+Author: Mike Christie 
+Date:   Thu May 1 14:49:59 2008 -0700
+
+    [SCSI] scsi_dh: add hp sw device handler
+    
+    This patch provides the device handler to support the older hp boxes
+    which cannot be upgraded.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Chandra Seetharaman 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/device_handler/Kconfig b/drivers/scsi/device_handler/Kconfig
+index 404f37732627..61578d84fa6e 100644
+--- a/drivers/scsi/device_handler/Kconfig
++++ b/drivers/scsi/device_handler/Kconfig
+@@ -16,3 +16,11 @@ config SCSI_DH_RDAC
+ 	depends on SCSI_DH
+ 	help
+ 	If you have a LSI RDAC select y. Otherwise, say N.
++
++config SCSI_DH_HP_SW
++	tristate "HP/COMPAQ MSA Device Handler"
++	depends on SCSI_DH
++	help
++	If you have a HP/COMPAQ MSA device that requires START_STOP to
++	be sent to start it and cannot upgrade the firmware then select y.
++	Otherwise, say N.
+diff --git a/drivers/scsi/device_handler/Makefile b/drivers/scsi/device_handler/Makefile
+index 1a42b3498318..08ec1943f19e 100644
+--- a/drivers/scsi/device_handler/Makefile
++++ b/drivers/scsi/device_handler/Makefile
+@@ -3,3 +3,4 @@
+ #
+ obj-$(CONFIG_SCSI_DH)		+= scsi_dh.o
+ obj-$(CONFIG_SCSI_DH_RDAC)	+= scsi_dh_rdac.o
++obj-$(CONFIG_SCSI_DH_HP_SW)	+= scsi_dh_hp_sw.o
+diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
+new file mode 100644
+index 000000000000..12ceab7b3662
+--- /dev/null
++++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
+@@ -0,0 +1,202 @@
++/*
++ * Basic HP/COMPAQ MSA 1000 support. This is only needed if your HW cannot be
++ * upgraded.
++ *
++ * Copyright (C) 2006 Red Hat, Inc.  All rights reserved.
++ * Copyright (C) 2006 Mike Christie
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include 
++#include 
++#include 
++#include 
++
++#define HP_SW_NAME	"hp_sw"
++
++#define HP_SW_TIMEOUT (60 * HZ)
++#define HP_SW_RETRIES 3
++
++struct hp_sw_dh_data {
++	unsigned char sense[SCSI_SENSE_BUFFERSIZE];
++	int retries;
++};
++
++static inline struct hp_sw_dh_data *get_hp_sw_data(struct scsi_device *sdev)
++{
++	struct scsi_dh_data *scsi_dh_data = sdev->scsi_dh_data;
++	BUG_ON(scsi_dh_data == NULL);
++	return ((struct hp_sw_dh_data *) scsi_dh_data->buf);
++}
++
++static int hp_sw_done(struct scsi_device *sdev)
++{
++	struct hp_sw_dh_data *h = get_hp_sw_data(sdev);
++	struct scsi_sense_hdr sshdr;
++	int rc;
++
++	sdev_printk(KERN_INFO, sdev, "hp_sw_done\n");
++
++	rc = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE, &sshdr);
++	if (!rc)
++		goto done;
++	switch (sshdr.sense_key) {
++	case NOT_READY:
++		if ((sshdr.asc == 0x04) && (sshdr.ascq == 3)) {
++			rc = SCSI_DH_RETRY;
++			h->retries++;
++			break;
++		}
++		/* fall through */
++	default:
++		h->retries++;
++		rc = SCSI_DH_IMM_RETRY;
++	}
++
++done:
++	if (rc == SCSI_DH_OK || rc == SCSI_DH_IO)
++		h->retries = 0;
++	else if (h->retries > HP_SW_RETRIES) {
++		h->retries = 0;
++		rc = SCSI_DH_IO;
++	}
++	return rc;
++}
++
++static int hp_sw_activate(struct scsi_device *sdev)
++{
++	struct hp_sw_dh_data *h = get_hp_sw_data(sdev);
++	struct request *req;
++	int ret = SCSI_DH_RES_TEMP_UNAVAIL;
++
++	req = blk_get_request(sdev->request_queue, WRITE, GFP_ATOMIC);
++	if (!req)
++		goto done;
++
++	sdev_printk(KERN_INFO, sdev, "sending START_STOP.");
++
++	req->cmd_type = REQ_TYPE_BLOCK_PC;
++	req->cmd_flags |= REQ_FAILFAST;
++	req->cmd_len = COMMAND_SIZE(START_STOP);
++	memset(req->cmd, 0, MAX_COMMAND_SIZE);
++	req->cmd[0] = START_STOP;
++	req->cmd[4] = 1;	/* Start spin cycle */
++	req->timeout = HP_SW_TIMEOUT;
++	req->sense = h->sense;
++	memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE);
++	req->sense_len = 0;
++
++	ret = blk_execute_rq(req->q, NULL, req, 1);
++	if (!ret) /* SUCCESS */
++		ret = hp_sw_done(sdev);
++	else
++		ret = SCSI_DH_IO;
++done:
++	return ret;
++}
++
++static const struct {
++	char *vendor;
++	char *model;
++} hp_sw_dh_data_list[] = {
++	{"COMPAQ", "MSA"},
++	{"HP", "HSV"},
++	{"DEC", "HSG80"},
++	{NULL, NULL},
++};
++
++static int hp_sw_bus_notify(struct notifier_block *, unsigned long, void *);
++
++static struct scsi_device_handler hp_sw_dh = {
++	.name		= HP_SW_NAME,
++	.module		= THIS_MODULE,
++	.nb.notifier_call = hp_sw_bus_notify,
++	.activate	= hp_sw_activate,
++};
++
++static int hp_sw_bus_notify(struct notifier_block *nb,
++			    unsigned long action, void *data)
++{
++	struct device *dev = data;
++	struct scsi_device *sdev = to_scsi_device(dev);
++	struct scsi_dh_data *scsi_dh_data;
++	int i, found = 0;
++	unsigned long flags;
++
++	if (action == BUS_NOTIFY_ADD_DEVICE) {
++		for (i = 0; hp_sw_dh_data_list[i].vendor; i++) {
++			if (!strncmp(sdev->vendor, hp_sw_dh_data_list[i].vendor,
++				     strlen(hp_sw_dh_data_list[i].vendor)) &&
++			    !strncmp(sdev->model, hp_sw_dh_data_list[i].model,
++				     strlen(hp_sw_dh_data_list[i].model))) {
++				found = 1;
++				break;
++			}
++		}
++		if (!found)
++			goto out;
++
++		scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
++				+ sizeof(struct hp_sw_dh_data) , GFP_KERNEL);
++		if (!scsi_dh_data) {
++			sdev_printk(KERN_ERR, sdev, "Attach Failed %s.\n",
++				    HP_SW_NAME);
++			goto out;
++		}
++
++		scsi_dh_data->scsi_dh = &hp_sw_dh;
++		spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
++		sdev->scsi_dh_data = scsi_dh_data;
++		spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
++		try_module_get(THIS_MODULE);
++
++		sdev_printk(KERN_NOTICE, sdev, "Attached %s.\n", HP_SW_NAME);
++	} else if (action == BUS_NOTIFY_DEL_DEVICE) {
++		if (sdev->scsi_dh_data == NULL ||
++				sdev->scsi_dh_data->scsi_dh != &hp_sw_dh)
++			goto out;
++
++		spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
++		scsi_dh_data = sdev->scsi_dh_data;
++		sdev->scsi_dh_data = NULL;
++		spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
++		module_put(THIS_MODULE);
++
++		sdev_printk(KERN_NOTICE, sdev, "Dettached %s.\n", HP_SW_NAME);
++
++		kfree(scsi_dh_data);
++	}
++
++out:
++	return 0;
++}
++
++static int __init hp_sw_init(void)
++{
++	return scsi_register_device_handler(&hp_sw_dh);
++}
++
++static void __exit hp_sw_exit(void)
++{
++	scsi_unregister_device_handler(&hp_sw_dh);
++}
++
++module_init(hp_sw_init);
++module_exit(hp_sw_exit);
++
++MODULE_DESCRIPTION("HP MSA 1000");
++MODULE_AUTHOR("Mike Christie 
commit c8611f975403dd20e6503aff8aded5dcb718f75b
+Author: Mike Christie 
+Date:   Thu May 8 20:15:34 2008 -0500
+
+    [SCSI] libiscsi regression in 2.6.25: fix setting of recv timer
+    
+    If the ping tmo is longer than the recv tmo then we could miss a window
+    where we were supposed to check the recv tmo. This happens because
+    the ping code will set the next timeout for the ping timeout, and if the
+    ping executes quickly there will be a long chunk of time before the
+    timer wakes up again.
+    
+    This patch has the ping processing code kick off a recv
+    tmo check when getting a nop in response to our ping.
+    
+    Signed-off-by: Mike Christie 
+    Cc: Stable Tree 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 98164f3c3517..b43bf1d60dac 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -730,7 +730,9 @@ static int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 				if (iscsi_recv_pdu(conn->cls_conn, hdr, data,
+ 						   datalen))
+ 					rc = ISCSI_ERR_CONN_FAILED;
+-			}
++			} else
++				mod_timer(&conn->transport_timer,
++					  jiffies + conn->recv_timeout);
+ 			iscsi_free_mgmt_task(conn, mtask);
+ 			break;
+ 		default:
+@@ -1478,11 +1480,9 @@ static void iscsi_check_transport_timeouts(unsigned long data)
+ 	}
+ 
+ 	if (time_before_eq(last_recv + recv_timeout, jiffies)) {
+-		if (time_before_eq(conn->last_ping, last_recv)) {
+-			/* send a ping to try to provoke some traffic */
+-			debug_scsi("Sending nopout as ping on conn %p\n", conn);
+-			iscsi_send_nopout(conn, NULL);
+-		}
++		/* send a ping to try to provoke some traffic */
++		debug_scsi("Sending nopout as ping on conn %p\n", conn);
++		iscsi_send_nopout(conn, NULL);
+ 		next_timeout = conn->last_ping + (conn->ping_timeout * HZ);
+ 	} else
+ 		next_timeout = last_recv + recv_timeout;

commit 4cf1043593db6a337f10e006c23c69e5fc93e722
+Author: Mike Christie 
+Date:   Wed May 7 20:43:52 2008 -0500
+
+    [SCSI] libiscsi regression in 2.6.25: fix nop timer handling
+    
+    The following patch fixes a bug in the iscsi nop processing.
+    The target sends iscsi nops to ping the initiator and the
+    initiator has to send nops to reply and can send nops to
+    ping the target.
+    
+    In 2.6.25 we moved the nop processing to the kernel to handle
+    problems when the userspace daemon is not up, but the target
+    is pinging us, and to handle when scsi commands timeout, but
+    the transport may be the cause (we can send a nop to check
+    the transport). When we added this code we added a bug where
+    if the transport timer wakes at the exact same time we are supposed to check
+    for a nop timeout we drop the session instead of checking the transport.
+    
+    This patch checks if a iscsi ping is outstanding and if the ping has
+    timed out, to determine if we need to signal a connection problem.
+    
+    Signed-off-by: Mike Christie 
+    Cc: Stable Tree 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 010c1b9b178c..98164f3c3517 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1453,19 +1453,20 @@ static void iscsi_check_transport_timeouts(unsigned long data)
+ {
+ 	struct iscsi_conn *conn = (struct iscsi_conn *)data;
+ 	struct iscsi_session *session = conn->session;
+-	unsigned long timeout, next_timeout = 0, last_recv;
++	unsigned long recv_timeout, next_timeout = 0, last_recv;
+ 
+ 	spin_lock(&session->lock);
+ 	if (session->state != ISCSI_STATE_LOGGED_IN)
+ 		goto done;
+ 
+-	timeout = conn->recv_timeout;
+-	if (!timeout)
++	recv_timeout = conn->recv_timeout;
++	if (!recv_timeout)
+ 		goto done;
+ 
+-	timeout *= HZ;
++	recv_timeout *= HZ;
+ 	last_recv = conn->last_recv;
+-	if (time_before_eq(last_recv + timeout + (conn->ping_timeout * HZ),
++	if (conn->ping_mtask &&
++	    time_before_eq(conn->last_ping + (conn->ping_timeout * HZ),
+ 			   jiffies)) {
+ 		iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs "
+ 				  "expired, last rx %lu, last ping %lu, "
+@@ -1476,15 +1477,15 @@ static void iscsi_check_transport_timeouts(unsigned long data)
+ 		return;
+ 	}
+ 
+-	if (time_before_eq(last_recv + timeout, jiffies)) {
++	if (time_before_eq(last_recv + recv_timeout, jiffies)) {
+ 		if (time_before_eq(conn->last_ping, last_recv)) {
+ 			/* send a ping to try to provoke some traffic */
+ 			debug_scsi("Sending nopout as ping on conn %p\n", conn);
+ 			iscsi_send_nopout(conn, NULL);
+ 		}
+-		next_timeout = last_recv + timeout + (conn->ping_timeout * HZ);
++		next_timeout = conn->last_ping + (conn->ping_timeout * HZ);
+ 	} else
+-		next_timeout = last_recv + timeout;
++		next_timeout = last_recv + recv_timeout;
+ 
+ 	debug_scsi("Setting next tmo %lu\n", next_timeout);
+ 	mod_timer(&conn->transport_timer, next_timeout);

commit ce5450392fa3ab54f0a84aa3b7589f8d6f2a58af
+Author: Mike Christie 
+Date:   Fri Feb 29 18:25:20 2008 -0600
+
+    [SCSI] qla4xxx: Add target reset functionality
+    
+    This patch adds target reset functionalty.
+    
+    Signed-off-by: Mike Christie 
+    Acked-by: David Somayajulu 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
+index fe415ec85655..ed8ee66a7da5 100644
+--- a/drivers/scsi/qla4xxx/ql4_fw.h
++++ b/drivers/scsi/qla4xxx/ql4_fw.h
+@@ -216,6 +216,7 @@ union external_hw_config_reg {
+ #define MBOX_CMD_ABOUT_FW			0x0009
+ #define MBOX_CMD_PING				0x000B
+ #define MBOX_CMD_LUN_RESET			0x0016
++#define MBOX_CMD_TARGET_WARM_RESET		0x0017
+ #define MBOX_CMD_GET_MANAGEMENT_DATA		0x001E
+ #define MBOX_CMD_GET_FW_STATUS			0x001F
+ #define MBOX_CMD_SET_ISNS_SERVICE		0x0021
+diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
+index a3608e028bf6..b403a17106c5 100644
+--- a/drivers/scsi/qla4xxx/ql4_glbl.h
++++ b/drivers/scsi/qla4xxx/ql4_glbl.h
+@@ -27,6 +27,8 @@ int qla4xxx_relogin_device(struct scsi_qla_host * ha,
+ 			   struct ddb_entry * ddb_entry);
+ int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,
+ 		      int lun);
++int qla4xxx_reset_target(struct scsi_qla_host * ha,
++			 struct ddb_entry * ddb_entry);
+ int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,
+ 		      uint32_t offset, uint32_t len);
+ int qla4xxx_get_firmware_status(struct scsi_qla_host * ha);
+diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
+index 35cd73c72a68..c577d79bd7e8 100644
+--- a/drivers/scsi/qla4xxx/ql4_mbx.c
++++ b/drivers/scsi/qla4xxx/ql4_mbx.c
+@@ -713,6 +713,45 @@ int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,
+ 	return status;
+ }
+ 
++/**
++ * qla4xxx_reset_target - issues target Reset
++ * @ha: Pointer to host adapter structure.
++ * @db_entry: Pointer to device database entry
++ * @un_entry: Pointer to lun entry structure
++ *
++ * This routine performs a TARGET RESET on the specified target.
++ * The caller must ensure that the ddb_entry pointers
++ * are valid before calling this routine.
++ **/
++int qla4xxx_reset_target(struct scsi_qla_host *ha,
++			 struct ddb_entry *ddb_entry)
++{
++	uint32_t mbox_cmd[MBOX_REG_COUNT];
++	uint32_t mbox_sts[MBOX_REG_COUNT];
++	int status = QLA_SUCCESS;
++
++	DEBUG2(printk("scsi%ld:%d: target reset issued\n", ha->host_no,
++		      ddb_entry->os_target_id));
++
++	/*
++	 * Send target reset command to ISP, so that the ISP will return all
++	 * outstanding requests with RESET status
++	 */
++	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
++	memset(&mbox_sts, 0, sizeof(mbox_sts));
++
++	mbox_cmd[0] = MBOX_CMD_TARGET_WARM_RESET;
++	mbox_cmd[1] = ddb_entry->fw_ddb_index;
++	mbox_cmd[5] = 0x01;	/* Immediate Command Enable */
++
++	qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
++				&mbox_sts[0]);
++	if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE &&
++	    mbox_sts[0] != MBOX_STS_COMMAND_ERROR)
++		status = QLA_ERROR;
++
++	return status;
++}
+ 
+ int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,
+ 		      uint32_t offset, uint32_t len)
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index 8b92f348f02c..31e605caf0f1 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -71,6 +71,7 @@ static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session);
+ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
+ 				void (*done) (struct scsi_cmnd *));
+ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd);
++static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd);
+ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd);
+ static int qla4xxx_slave_alloc(struct scsi_device *device);
+ static int qla4xxx_slave_configure(struct scsi_device *device);
+@@ -84,6 +85,7 @@ static struct scsi_host_template qla4xxx_driver_template = {
+ 	.queuecommand		= qla4xxx_queuecommand,
+ 
+ 	.eh_device_reset_handler = qla4xxx_eh_device_reset,
++	.eh_target_reset_handler = qla4xxx_eh_target_reset,
+ 	.eh_host_reset_handler	= qla4xxx_eh_host_reset,
+ 
+ 	.slave_configure	= qla4xxx_slave_configure,
+@@ -1482,7 +1484,7 @@ static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha)
+ }
+ 
+ /**
+- * qla4xxx_eh_wait_for_active_target_commands - wait for active cmds to finish.
++ * qla4xxx_eh_wait_for_commands - wait for active cmds to finish.
+  * @ha: pointer to to HBA
+  * @t: target id
+  * @l: lun id
+@@ -1490,20 +1492,22 @@ static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha)
+  * This function waits for all outstanding commands to a lun to complete. It
+  * returns 0 if all pending commands are returned and 1 otherwise.
+  **/
+-static int qla4xxx_eh_wait_for_active_target_commands(struct scsi_qla_host *ha,
+-						 int t, int l)
++static int qla4xxx_eh_wait_for_commands(struct scsi_qla_host *ha,
++					struct scsi_target *stgt,
++					struct scsi_device *sdev)
+ {
+ 	int cnt;
+ 	int status = 0;
+ 	struct scsi_cmnd *cmd;
+ 
+ 	/*
+-	 * Waiting for all commands for the designated target in the active
+-	 * array
++	 * Waiting for all commands for the designated target or dev
++	 * in the active array
+ 	 */
+ 	for (cnt = 0; cnt < ha->host->can_queue; cnt++) {
+ 		cmd = scsi_host_find_tag(ha->host, cnt);
+-		if (cmd && cmd->device->id == t && cmd->device->lun == l) {
++		if (cmd && stgt == scsi_target(cmd->device) &&
++		    (!sdev || sdev == cmd->device)) {
+ 			if (!qla4xxx_eh_wait_on_command(ha, cmd)) {
+ 				status++;
+ 				break;
+@@ -1551,19 +1555,12 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd)
+ 	/* Send marker. */
+ 	ha->marker_needed = 1;
+ 
+-	/*
+-	 * If we are coming down the EH path, wait for all commands to complete
+-	 * for the device.
+-	 */
+-	if (cmd->device->host->shost_state == SHOST_RECOVERY) {
+-		if (qla4xxx_eh_wait_for_active_target_commands(ha,
+-							  cmd->device->id,
+-							  cmd->device->lun)){
+-			dev_info(&ha->pdev->dev,
+-				   "DEVICE RESET FAILED - waiting for "
+-				   "commands.\n");
+-			goto eh_dev_reset_done;
+-		}
++	if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device),
++					 cmd->device)) {
++		dev_info(&ha->pdev->dev,
++			   "DEVICE RESET FAILED - waiting for "
++			   "commands.\n");
++		goto eh_dev_reset_done;
+ 	}
+ 
+ 	dev_info(&ha->pdev->dev,
+@@ -1578,6 +1575,53 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd)
+ 	return ret;
+ }
+ 
++/**
++ * qla4xxx_eh_target_reset - callback for target reset.
++ * @cmd: Pointer to Linux's SCSI command structure
++ *
++ * This routine is called by the Linux OS to reset the target.
++ **/
++static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd)
++{
++	struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
++	struct ddb_entry *ddb_entry = cmd->device->hostdata;
++	int stat;
++
++	if (!ddb_entry)
++		return FAILED;
++
++	starget_printk(KERN_INFO, scsi_target(cmd->device),
++		       "WARM TARGET RESET ISSUED.\n");
++
++	DEBUG2(printk(KERN_INFO
++		      "scsi%ld: TARGET_DEVICE_RESET cmd=%p jiffies = 0x%lx, "
++		      "to=%x,dpc_flags=%lx, status=%x allowed=%d\n",
++		      ha->host_no, cmd, jiffies, cmd->timeout_per_command / HZ,
++		      ha->dpc_flags, cmd->result, cmd->allowed));
++
++	stat = qla4xxx_reset_target(ha, ddb_entry);
++	if (stat != QLA_SUCCESS) {
++		starget_printk(KERN_INFO, scsi_target(cmd->device),
++			       "WARM TARGET RESET FAILED.\n");
++		return FAILED;
++	}
++
++	/* Send marker. */
++	ha->marker_needed = 1;
++
++	if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device),
++					 NULL)) {
++		starget_printk(KERN_INFO, scsi_target(cmd->device),
++			       "WARM TARGET DEVICE RESET FAILED - "
++			       "waiting for commands.\n");
++		return FAILED;
++	}
++
++	starget_printk(KERN_INFO, scsi_target(cmd->device),
++		       "WARM TARGET RESET SUCCEEDED.\n");
++	return SUCCESS;
++}
++
+ /**
+  * qla4xxx_eh_host_reset - kernel callback
+  * @cmd: Pointer to Linux's SCSI command structure

commit 30bd7df8ced23eefec87a5cda96dc99b002ed9da
+Author: Mike Christie 
+Date:   Fri Feb 29 18:25:19 2008 -0600
+
+    [SCSI] scsi_error: add target reset handler
+    
+    The problem is that serveral drivers are sending a target reset from the
+    device reset handler, and if we have multiple devices a target reset gets
+    sent for each device when only one would be sufficient. And if we do a target
+    reset it affects all the commands on the target so the device reset handler
+    code only cleaning up one devices's commands makes programming the driver a
+    little more difficult than it should be.
+    
+    This patch adds a target reset handler, which drivers can use to send
+    a target reset. If successful it cleans up the commands for a devices
+    accessed through that starget.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
+index 045a0868fc7b..1221d2ca0c64 100644
+--- a/drivers/scsi/scsi_error.c
++++ b/drivers/scsi/scsi_error.c
+@@ -524,6 +524,41 @@ static int scsi_try_bus_reset(struct scsi_cmnd *scmd)
+ 	return rtn;
+ }
+ 
++static void __scsi_report_device_reset(struct scsi_device *sdev, void *data)
++{
++	sdev->was_reset = 1;
++	sdev->expecting_cc_ua = 1;
++}
++
++/**
++ * scsi_try_target_reset - Ask host to perform a target reset
++ * @scmd:	SCSI cmd used to send a target reset
++ *
++ * Notes:
++ *    There is no timeout for this operation.  if this operation is
++ *    unreliable for a given host, then the host itself needs to put a
++ *    timer on it, and set the host back to a consistent state prior to
++ *    returning.
++ */
++static int scsi_try_target_reset(struct scsi_cmnd *scmd)
++{
++	unsigned long flags;
++	int rtn;
++
++	if (!scmd->device->host->hostt->eh_target_reset_handler)
++		return FAILED;
++
++	rtn = scmd->device->host->hostt->eh_target_reset_handler(scmd);
++	if (rtn == SUCCESS) {
++		spin_lock_irqsave(scmd->device->host->host_lock, flags);
++		__starget_for_each_device(scsi_target(scmd->device), NULL,
++					  __scsi_report_device_reset);
++		spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
++	}
++
++	return rtn;
++}
++
+ /**
+  * scsi_try_bus_device_reset - Ask host to perform a BDR on a dev
+  * @scmd:	SCSI cmd used to send BDR
+@@ -542,11 +577,8 @@ static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd)
+ 		return FAILED;
+ 
+ 	rtn = scmd->device->host->hostt->eh_device_reset_handler(scmd);
+-	if (rtn == SUCCESS) {
+-		scmd->device->was_reset = 1;
+-		scmd->device->expecting_cc_ua = 1;
+-	}
+-
++	if (rtn == SUCCESS)
++		__scsi_report_device_reset(scmd->device, NULL);
+ 	return rtn;
+ }
+ 
+@@ -584,8 +616,9 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
+ {
+ 	if (__scsi_try_to_abort_cmd(scmd) != SUCCESS)
+ 		if (scsi_try_bus_device_reset(scmd) != SUCCESS)
+-			if (scsi_try_bus_reset(scmd) != SUCCESS)
+-				scsi_try_host_reset(scmd);
++			if (scsi_try_target_reset(scmd) != SUCCESS)
++				if (scsi_try_bus_reset(scmd) != SUCCESS)
++					scsi_try_host_reset(scmd);
+ }
+ 
+ /**
+@@ -1059,6 +1092,56 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost,
+ 	return list_empty(work_q);
+ }
+ 
++/**
++ * scsi_eh_target_reset - send target reset if needed
++ * @shost:	scsi host being recovered.
++ * @work_q:     &list_head for pending commands.
++ * @done_q:	&list_head for processed commands.
++ *
++ * Notes:
++ *    Try a target reset.
++ */
++static int scsi_eh_target_reset(struct Scsi_Host *shost,
++				struct list_head *work_q,
++				struct list_head *done_q)
++{
++	struct scsi_cmnd *scmd, *tgtr_scmd, *next;
++	unsigned int id;
++	int rtn;
++
++	for (id = 0; id <= shost->max_id; id++) {
++		tgtr_scmd = NULL;
++		list_for_each_entry(scmd, work_q, eh_entry) {
++			if (id == scmd_id(scmd)) {
++				tgtr_scmd = scmd;
++				break;
++			}
++		}
++		if (!tgtr_scmd)
++			continue;
++
++		SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending target reset "
++						  "to target %d\n",
++						  current->comm, id));
++		rtn = scsi_try_target_reset(tgtr_scmd);
++		if (rtn == SUCCESS) {
++			list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
++				if (id == scmd_id(scmd))
++					if (!scsi_device_online(scmd->device) ||
++					    !scsi_eh_tur(tgtr_scmd))
++						scsi_eh_finish_cmd(scmd,
++								   done_q);
++			}
++		} else
++			SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Target reset"
++							  " failed target: "
++							  "%d\n",
++							  current->comm, id));
++	}
++
++	return list_empty(work_q);
++}
++
+ /**
+  * scsi_eh_bus_reset - send a bus reset 
+  * @shost:	&scsi host being recovered.
+@@ -1447,9 +1530,11 @@ void scsi_eh_ready_devs(struct Scsi_Host *shost,
+ {
+ 	if (!scsi_eh_stu(shost, work_q, done_q))
+ 		if (!scsi_eh_bus_device_reset(shost, work_q, done_q))
+-			if (!scsi_eh_bus_reset(shost, work_q, done_q))
+-				if (!scsi_eh_host_reset(work_q, done_q))
+-					scsi_eh_offline_sdevs(work_q, done_q);
++			if (!scsi_eh_target_reset(shost, work_q, done_q))
++				if (!scsi_eh_bus_reset(shost, work_q, done_q))
++					if (!scsi_eh_host_reset(work_q, done_q))
++						scsi_eh_offline_sdevs(work_q,
++								      done_q);
+ }
+ EXPORT_SYMBOL_GPL(scsi_eh_ready_devs);
+ 
+@@ -1619,10 +1704,8 @@ void scsi_report_bus_reset(struct Scsi_Host *shost, int channel)
+ 	struct scsi_device *sdev;
+ 
+ 	__shost_for_each_device(sdev, shost) {
+-		if (channel == sdev_channel(sdev)) {
+-			sdev->was_reset = 1;
+-			sdev->expecting_cc_ua = 1;
+-		}
++		if (channel == sdev_channel(sdev))
++			__scsi_report_device_reset(sdev, NULL);
+ 	}
+ }
+ EXPORT_SYMBOL(scsi_report_bus_reset);
+@@ -1655,10 +1738,8 @@ void scsi_report_device_reset(struct Scsi_Host *shost, int channel, int target)
+ 
+ 	__shost_for_each_device(sdev, shost) {
+ 		if (channel == sdev_channel(sdev) &&
+-		    target == sdev_id(sdev)) {
+-			sdev->was_reset = 1;
+-			sdev->expecting_cc_ua = 1;
+-		}
++		    target == sdev_id(sdev))
++			__scsi_report_device_reset(sdev, NULL);
+ 	}
+ }
+ EXPORT_SYMBOL(scsi_report_device_reset);
+@@ -1714,6 +1795,11 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
+ 		if (rtn == SUCCESS)
+ 			break;
+ 		/* FALLTHROUGH */
++	case SCSI_TRY_RESET_TARGET:
++		rtn = scsi_try_target_reset(scmd);
++		if (rtn == SUCCESS)
++			break;
++		/* FALLTHROUGH */
+ 	case SCSI_TRY_RESET_BUS:
+ 		rtn = scsi_try_bus_reset(scmd);
+ 		if (rtn == SUCCESS)
+diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h
+index 25071d5d9bf8..37a7614f62f4 100644
+--- a/include/scsi/scsi_eh.h
++++ b/include/scsi/scsi_eh.h
+@@ -64,6 +64,7 @@ extern int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len,
+ #define SCSI_TRY_RESET_DEVICE	1
+ #define SCSI_TRY_RESET_BUS	2
+ #define SCSI_TRY_RESET_HOST	3
++#define SCSI_TRY_RESET_TARGET	4
+ 
+ extern int scsi_reset_provider(struct scsi_device *, int);
+ 
+diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
+index 530ff4c553f8..49132862bfaa 100644
+--- a/include/scsi/scsi_host.h
++++ b/include/scsi/scsi_host.h
+@@ -172,6 +172,7 @@ struct scsi_host_template {
+ 	 */
+ 	int (* eh_abort_handler)(struct scsi_cmnd *);
+ 	int (* eh_device_reset_handler)(struct scsi_cmnd *);
++	int (* eh_target_reset_handler)(struct scsi_cmnd *);
+ 	int (* eh_bus_reset_handler)(struct scsi_cmnd *);
+ 	int (* eh_host_reset_handler)(struct scsi_cmnd *);
+ 

commit 4b6f5b3a993cbe34b4280f252bccc76967c185c8
+Author: Mike Christie 
+Date:   Tue Mar 11 00:36:51 2008 -0500
+
+    [SCSI] fix bsg queue oops with iscsi logout
+    
+    Delay bsg unregistration, because we want to wait until all the request/cmds
+    have released their reference.
+    
+    Signed-off-by: Mike Christie 
+    Acked-by: FUJITA Tomonori 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
+index ed83cdb6e67d..b9b09a704584 100644
+--- a/drivers/scsi/scsi_sysfs.c
++++ b/drivers/scsi/scsi_sysfs.c
+@@ -294,6 +294,7 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work)
+ 	}
+ 
+ 	if (sdev->request_queue) {
++		bsg_unregister_queue(sdev->request_queue);
+ 		sdev->request_queue->queuedata = NULL;
+ 		/* user context needed to free queue */
+ 		scsi_free_queue(sdev->request_queue);
+@@ -857,7 +858,6 @@ void __scsi_remove_device(struct scsi_device *sdev)
+ 	if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0)
+ 		return;
+ 
+-	bsg_unregister_queue(sdev->request_queue);
+ 	class_device_unregister(&sdev->sdev_classdev);
+ 	transport_remove_device(dev);
+ 	device_del(dev);

commit 45ab33b6c190c4a8c58f1d13be2ff89ee62024ba
+Author: Mike Christie 
+Date:   Tue Mar 4 13:26:55 2008 -0600
+
+    [SCSI] iscsi class: regression - fix races with state manipulation and blocking/unblocking
+    
+    For qla4xxx, we could be starting a session, but some error (network,
+    target, IO from a device that got started, etc) could cause the session
+    to fail and curring the block/unblock and state manipulation could race
+    with each other. This patch just has those operations done in the
+    single threaded iscsi eh work queue, so that way they are serialized.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index dfb026b95a6a..ca7bb6f63bde 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -373,24 +373,25 @@ static void session_recovery_timedout(struct work_struct *work)
+ 	scsi_target_unblock(&session->dev);
+ }
+ 
+-static void __iscsi_unblock_session(struct iscsi_cls_session *session)
+-{
+-	if (!cancel_delayed_work(&session->recovery_work))
+-		flush_workqueue(iscsi_eh_timer_workq);
+-	scsi_target_unblock(&session->dev);
+-}
+-
+-void iscsi_unblock_session(struct iscsi_cls_session *session)
++static void __iscsi_unblock_session(struct work_struct *work)
+ {
++	struct iscsi_cls_session *session =
++			container_of(work, struct iscsi_cls_session,
++				     unblock_work);
+ 	struct Scsi_Host *shost = iscsi_session_to_shost(session);
+ 	struct iscsi_host *ihost = shost->shost_data;
+ 	unsigned long flags;
+ 
++	/*
++	 * The recovery and unblock work get run from the same workqueue,
++	 * so try to cancel it if it was going to run after this unblock.
++	 */
++	cancel_delayed_work(&session->recovery_work);
+ 	spin_lock_irqsave(&session->lock, flags);
+ 	session->state = ISCSI_SESSION_LOGGED_IN;
+ 	spin_unlock_irqrestore(&session->lock, flags);
+-
+-	__iscsi_unblock_session(session);
++	/* start IO */
++	scsi_target_unblock(&session->dev);
+ 	/*
+ 	 * Only do kernel scanning if the driver is properly hooked into
+ 	 * the async scanning code (drivers like iscsi_tcp do login and
+@@ -401,20 +402,43 @@ void iscsi_unblock_session(struct iscsi_cls_session *session)
+ 			atomic_inc(&ihost->nr_scans);
+ 	}
+ }
++
++/**
++ * iscsi_unblock_session - set a session as logged in and start IO.
++ * @session: iscsi session
++ *
++ * Mark a session as ready to accept IO.
++ */
++void iscsi_unblock_session(struct iscsi_cls_session *session)
++{
++	queue_work(iscsi_eh_timer_workq, &session->unblock_work);
++	/*
++	 * make sure all the events have completed before tell the driver
++	 * it is safe
++	 */
++	flush_workqueue(iscsi_eh_timer_workq);
++}
+ EXPORT_SYMBOL_GPL(iscsi_unblock_session);
+ 
+-void iscsi_block_session(struct iscsi_cls_session *session)
++static void __iscsi_block_session(struct work_struct *work)
+ {
++	struct iscsi_cls_session *session =
++			container_of(work, struct iscsi_cls_session,
++				     block_work);
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&session->lock, flags);
+ 	session->state = ISCSI_SESSION_FAILED;
+ 	spin_unlock_irqrestore(&session->lock, flags);
+-
+ 	scsi_target_block(&session->dev);
+ 	queue_delayed_work(iscsi_eh_timer_workq, &session->recovery_work,
+ 			   session->recovery_tmo * HZ);
+ }
++
++void iscsi_block_session(struct iscsi_cls_session *session)
++{
++	queue_work(iscsi_eh_timer_workq, &session->block_work);
++}
+ EXPORT_SYMBOL_GPL(iscsi_block_session);
+ 
+ static void __iscsi_unbind_session(struct work_struct *work)
+@@ -463,6 +487,8 @@ iscsi_alloc_session(struct Scsi_Host *shost,
+ 	INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout);
+ 	INIT_LIST_HEAD(&session->host_list);
+ 	INIT_LIST_HEAD(&session->sess_list);
++	INIT_WORK(&session->unblock_work, __iscsi_unblock_session);
++	INIT_WORK(&session->block_work, __iscsi_block_session);
+ 	INIT_WORK(&session->unbind_work, __iscsi_unbind_session);
+ 	INIT_WORK(&session->scan_work, iscsi_scan_session);
+ 	spin_lock_init(&session->lock);
+@@ -575,24 +601,25 @@ void iscsi_remove_session(struct iscsi_cls_session *session)
+ 	list_del(&session->sess_list);
+ 	spin_unlock_irqrestore(&sesslock, flags);
+ 
++	/* make sure there are no blocks/unblocks queued */
++	flush_workqueue(iscsi_eh_timer_workq);
++	/* make sure the timedout callout is not running */
++	if (!cancel_delayed_work(&session->recovery_work))
++		flush_workqueue(iscsi_eh_timer_workq);
+ 	/*
+ 	 * If we are blocked let commands flow again. The lld or iscsi
+ 	 * layer should set up the queuecommand to fail commands.
++	 * We assume that LLD will not be calling block/unblock while
++	 * removing the session.
+ 	 */
+ 	spin_lock_irqsave(&session->lock, flags);
+ 	session->state = ISCSI_SESSION_FREE;
+ 	spin_unlock_irqrestore(&session->lock, flags);
+-	__iscsi_unblock_session(session);
+-	__iscsi_unbind_session(&session->unbind_work);
+ 
+-	/* flush running scans */
++	scsi_target_unblock(&session->dev);
++	/* flush running scans then delete devices */
+ 	flush_workqueue(ihost->scan_workq);
+-	/*
+-	 * If the session dropped while removing devices then we need to make
+-	 * sure it is not blocked
+-	 */
+-	if (!cancel_delayed_work(&session->recovery_work))
+-		flush_workqueue(iscsi_eh_timer_workq);
++	__iscsi_unbind_session(&session->unbind_work);
+ 
+ 	/* hw iscsi may not have removed all connections from session */
+ 	err = device_for_each_child(&session->dev, NULL,
+@@ -802,23 +829,16 @@ EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
+ 
+ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
+ {
+-	struct iscsi_cls_session *session = iscsi_conn_to_session(conn);
+ 	struct nlmsghdr	*nlh;
+ 	struct sk_buff	*skb;
+ 	struct iscsi_uevent *ev;
+ 	struct iscsi_internal *priv;
+ 	int len = NLMSG_SPACE(sizeof(*ev));
+-	unsigned long flags;
+ 
+ 	priv = iscsi_if_transport_lookup(conn->transport);
+ 	if (!priv)
+ 		return;
+ 
+-	spin_lock_irqsave(&session->lock, flags);
+-	if (session->state == ISCSI_SESSION_LOGGED_IN)
+-		session->state = ISCSI_SESSION_FAILED;
+-	spin_unlock_irqrestore(&session->lock, flags);
+-
+ 	skb = alloc_skb(len, GFP_ATOMIC);
+ 	if (!skb) {
+ 		iscsi_cls_conn_printk(KERN_ERR, conn, "gracefully ignored "
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index dbc96ef4cc72..aab1eae2ec4c 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -177,6 +177,8 @@ struct iscsi_cls_session {
+ 	struct list_head host_list;
+ 	struct iscsi_transport *transport;
+ 	spinlock_t lock;
++	struct work_struct block_work;
++	struct work_struct unblock_work;
+ 	struct work_struct scan_work;
+ 	struct work_struct unbind_work;
+ 

commit 024f801f528220edc89275a724ea00cd18c5ebb7
+Author: Mike Christie 
+Date:   Tue Mar 4 13:26:54 2008 -0600
+
+    [SCSI] qla4xxx: regression - add start scan callout
+    
+    We are seeing EXIST errors from sysfs during device addition.
+    We need a start scan callout so we do not start scanning sessions
+    found during hba setup, before the async scsi scan code is ready.
+    
+    Signed-off-by: Mike Christie 
+    Acked-by: David C Somayajulu 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index 10a233e65bc9..8b92f348f02c 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -75,6 +75,7 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd);
+ static int qla4xxx_slave_alloc(struct scsi_device *device);
+ static int qla4xxx_slave_configure(struct scsi_device *device);
+ static void qla4xxx_slave_destroy(struct scsi_device *sdev);
++static void qla4xxx_scan_start(struct Scsi_Host *shost);
+ 
+ static struct scsi_host_template qla4xxx_driver_template = {
+ 	.module			= THIS_MODULE,
+@@ -90,6 +91,7 @@ static struct scsi_host_template qla4xxx_driver_template = {
+ 	.slave_destroy		= qla4xxx_slave_destroy,
+ 
+ 	.scan_finished		= iscsi_scan_finished,
++	.scan_start		= qla4xxx_scan_start,
+ 
+ 	.this_id		= -1,
+ 	.cmd_per_lun		= 3,
+@@ -299,6 +301,18 @@ struct ddb_entry *qla4xxx_alloc_sess(struct scsi_qla_host *ha)
+ 	return ddb_entry;
+ }
+ 
++static void qla4xxx_scan_start(struct Scsi_Host *shost)
++{
++	struct scsi_qla_host *ha = shost_priv(shost);
++	struct ddb_entry *ddb_entry, *ddbtemp;
++
++	/* finish setup of sessions that were already setup in firmware */
++	list_for_each_entry_safe(ddb_entry, ddbtemp, &ha->ddb_list, list) {
++		if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE)
++			qla4xxx_add_sess(ddb_entry);
++	}
++}
++
+ /*
+  * Timer routines
+  */
+@@ -1178,7 +1192,6 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
+ 	int ret = -ENODEV, status;
+ 	struct Scsi_Host *host;
+ 	struct scsi_qla_host *ha;
+-	struct ddb_entry *ddb_entry, *ddbtemp;
+ 	uint8_t init_retry_count = 0;
+ 	char buf[34];
+ 
+@@ -1297,13 +1310,6 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
+ 	if (ret)
+ 		goto probe_failed;
+ 
+-	/* Update transport device information for all devices. */
+-	list_for_each_entry_safe(ddb_entry, ddbtemp, &ha->ddb_list, list) {
+-		if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE)
+-			if (qla4xxx_add_sess(ddb_entry))
+-				goto remove_host;
+-	}
+-
+ 	printk(KERN_INFO
+ 	       " QLogic iSCSI HBA Driver version: %s\n"
+ 	       "  QLogic ISP%04x @ %s, host#=%ld, fw=%02d.%02d.%02d.%02d\n",
+@@ -1313,10 +1319,6 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
+ 	scsi_scan_host(host);
+ 	return 0;
+ 
+-remove_host:
+-	qla4xxx_free_ddb_list(ha);
+-	scsi_remove_host(host);
+-
+ probe_failed:
+ 	qla4xxx_free_adapter(ha);
+ 	scsi_host_put(ha->host);

commit 50a29aec9c47d26e869df83ef1d69e3b63c83bf4
+Author: Mike Christie 
+Date:   Tue Mar 4 13:26:53 2008 -0600
+
+    [SCSI] qla4xxx: fix host reset dpc race
+    
+    The host reset callout could be starting to reset the hba at the same
+    time the dpc thread is. This creates lots of problems because they both
+    want to do wierd things with the firmware and interrupts, etc.
+    
+    This patch just has the host reset function fully shutdown the dpc
+    thread before resetting the hba.
+    
+    This patch also moves the setting of the session online bit to fix
+    a potential race with the dpc thread and iscsi recovery thread.
+    
+    Signed-off-by: Mike Christie 
+    Acked-by: David C Somayajulu 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
+index 10b3b9a620f3..109c5f5985ec 100644
+--- a/drivers/scsi/qla4xxx/ql4_init.c
++++ b/drivers/scsi/qla4xxx/ql4_init.c
+@@ -1299,9 +1299,9 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha,
+ 	ddb_entry->fw_ddb_device_state = state;
+ 	/* Device is back online. */
+ 	if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) {
++		atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
+ 		atomic_set(&ddb_entry->port_down_timer,
+ 			   ha->port_down_retry_count);
+-		atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
+ 		atomic_set(&ddb_entry->relogin_retry_count, 0);
+ 		atomic_set(&ddb_entry->relogin_timer, 0);
+ 		clear_bit(DF_RELOGIN, &ddb_entry->flags);
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index c3c59d763037..10a233e65bc9 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -864,8 +864,9 @@ static void qla4xxx_flush_active_srbs(struct scsi_qla_host *ha)
+  * qla4xxx_recover_adapter - recovers adapter after a fatal error
+  * @ha: Pointer to host adapter structure.
+  * @renew_ddb_list: Indicates what to do with the adapter's ddb list
+- *	after adapter recovery has completed.
+- *	0=preserve ddb list, 1=destroy and rebuild ddb list
++ *
++ * renew_ddb_list value can be 0=preserve ddb list, 1=destroy and rebuild
++ * ddb list.
+  **/
+ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha,
+ 				uint8_t renew_ddb_list)
+@@ -874,6 +875,7 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha,
+ 
+ 	/* Stall incoming I/O until we are done */
+ 	clear_bit(AF_ONLINE, &ha->flags);
++
+ 	DEBUG2(printk("scsi%ld: %s calling qla4xxx_cmd_wait\n", ha->host_no,
+ 		      __func__));
+ 
+@@ -1600,9 +1602,12 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd)
+ 		return FAILED;
+ 	}
+ 
+-	if (qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST) == QLA_SUCCESS) {
++	/* make sure the dpc thread is stopped while we reset the hba */
++	clear_bit(AF_ONLINE, &ha->flags);
++	flush_workqueue(ha->dpc_thread);
++
++	if (qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST) == QLA_SUCCESS)
+ 		return_status = SUCCESS;
+-	}
+ 
+ 	dev_info(&ha->pdev->dev, "HOST RESET %s.\n",
+ 		   return_status == FAILED ? "FAILED" : "SUCCEDED");

commit 31ed0bf439a15363c28c7a239f52eb127cb6feb3
+Author: Mike Christie 
+Date:   Tue Feb 26 12:35:23 2008 -0600
+
+    [SCSI] iscsi regression: check for zero max session cmds
+    
+    The old tools did not set max session cmds. This is a regression.
+    I removed the check when merging the power of 2 patch.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 59f8445eab0d..bdd7de7da39a 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1708,8 +1708,8 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
+ 		qdepth = ISCSI_DEF_CMD_PER_LUN;
+ 	}
+ 
+-	if (!is_power_of_2(cmds_max) ||
+-	    cmds_max >= ISCSI_MGMT_ITT_OFFSET) {
++	if (!is_power_of_2(cmds_max) || cmds_max >= ISCSI_MGMT_ITT_OFFSET ||
++	    cmds_max < 2) {
+ 		if (cmds_max != 0)
+ 			printk(KERN_ERR "iscsi: invalid can_queue of %d. "
+ 			       "can_queue must be a power of 2 and between "
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 9981682d5302..dfb026b95a6a 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -33,7 +33,7 @@
+ #define ISCSI_SESSION_ATTRS 19
+ #define ISCSI_CONN_ATTRS 13
+ #define ISCSI_HOST_ATTRS 4
+-#define ISCSI_TRANSPORT_VERSION "2.0-868"
++#define ISCSI_TRANSPORT_VERSION "2.0-869"
+ 
+ struct iscsi_internal {
+ 	int daemon_pid;

commit 4c851879312702456c7fbd594f19a7a9d991c252
+Author: Mike Christie 
+Date:   Thu Jan 31 13:36:54 2008 -0600
+
+    [SCSI] iscsi: bump version to 2.0-868
+    
+    Set iscsi version to 2.0-868
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 8e73ff02fb74..fac7534f3ec4 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -33,7 +33,7 @@
+ #define ISCSI_SESSION_ATTRS 19
+ #define ISCSI_CONN_ATTRS 13
+ #define ISCSI_HOST_ATTRS 4
+-#define ISCSI_TRANSPORT_VERSION "2.0-867"
++#define ISCSI_TRANSPORT_VERSION "2.0-868"
+ 
+ struct iscsi_internal {
+ 	int daemon_pid;

commit 8b1d03434ee44b08c57f50403eaeab099facebf5
+Author: Mike Christie 
+Date:   Thu Jan 31 13:36:53 2008 -0600
+
+    [SCSI] libiscsi: fix session age rollover and remove cid encoding
+    
+    The session age mask is only 4 bits, but session->age is 32. When
+    it gets larger then 15 and we try to or the bits some bits get
+    dropped and the check for session age in iscsi_verify_itt is useless.
+    
+    The ISCSI_CID_MASK related bits are also useless since cid is always
+    one.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 10ba76285852..59f8445eab0d 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -160,7 +160,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ 	hdr->opcode = ISCSI_OP_SCSI_CMD;
+ 	hdr->flags = ISCSI_ATTR_SIMPLE;
+ 	int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
+-	hdr->itt = build_itt(ctask->itt, conn->id, session->age);
++	hdr->itt = build_itt(ctask->itt, session->age);
+ 	hdr->data_length = cpu_to_be32(scsi_bufflen(sc));
+ 	hdr->cmdsn = cpu_to_be32(session->cmdsn);
+ 	session->cmdsn++;
+@@ -705,14 +705,6 @@ int iscsi_verify_itt(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			return ISCSI_ERR_BAD_ITT;
+ 		}
+ 
+-		if (((__force u32)hdr->itt & ISCSI_CID_MASK) !=
+-		    (conn->id << ISCSI_CID_SHIFT)) {
+-			iscsi_conn_printk(KERN_ERR, conn,
+-					  "iscsi: received itt %x, expected "
+-					  "CID (%x)\n",
+-					  (__force u32)hdr->itt, conn->id);
+-			return ISCSI_ERR_BAD_ITT;
+-		}
+ 		itt = get_itt(hdr->itt);
+ 	} else
+ 		itt = ~0U;
+@@ -776,7 +768,7 @@ static void iscsi_prep_mtask(struct iscsi_conn *conn,
+ 	 */
+ 	nop->cmdsn = cpu_to_be32(session->cmdsn);
+ 	if (hdr->itt != RESERVED_ITT) {
+-		hdr->itt = build_itt(mtask->itt, conn->id, session->age);
++		hdr->itt = build_itt(mtask->itt, session->age);
+ 		/*
+ 		 * TODO: We always use immediate, so we never hit this.
+ 		 * If we start to send tmfs or nops as non-immediate then
+@@ -2036,6 +2028,8 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
+ 		conn->stop_stage = 0;
+ 		conn->tmf_state = TMF_INITIAL;
+ 		session->age++;
++		if (session->age == 16)
++			session->age = 0;
+ 		break;
+ 	case STOP_CONN_TERM:
+ 		conn->stop_stage = 0;
+diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h
+index 318a909e7ae1..5ffec8ad6964 100644
+--- a/include/scsi/iscsi_proto.h
++++ b/include/scsi/iscsi_proto.h
+@@ -45,8 +45,8 @@
+ /* initiator tags; opaque for target */
+ typedef uint32_t __bitwise__ itt_t;
+ /* below makes sense only for initiator that created this tag */
+-#define build_itt(itt, id, age) ((__force itt_t)\
+-	((itt) | ((id) << ISCSI_CID_SHIFT) | ((age) << ISCSI_AGE_SHIFT)))
++#define build_itt(itt, age) ((__force itt_t)\
++	((itt) | ((age) << ISCSI_AGE_SHIFT)))
+ #define get_itt(itt) ((__force uint32_t)(itt_t)(itt) & ISCSI_ITT_MASK)
+ #define RESERVED_ITT ((__force itt_t)0xffffffff)
+ 
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 5784e4ff8edc..7b90b63fb5c7 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -70,8 +70,6 @@ enum {
+ #define ISCSI_SUSPEND_BIT		1
+ 
+ #define ISCSI_ITT_MASK			(0xfff)
+-#define ISCSI_CID_SHIFT			12
+-#define ISCSI_CID_MASK			(0xffff << ISCSI_CID_SHIFT)
+ #define ISCSI_AGE_SHIFT			28
+ #define ISCSI_AGE_MASK			(0xf << ISCSI_AGE_SHIFT)
+ 

commit 322d739da83bbff0309c202181f79c08d9534880
+Author: Mike Christie 
+Date:   Thu Jan 31 13:36:52 2008 -0600
+
+    [SCSI] iscsi: fix up iscsi printk prefix
+    
+    Some iscsi class messages have the dev_printk prefix and some libiscsi
+    and iscsi_tcp messages have "iscsi" or the module name as a prefix which
+    is normally pretty useless when trying to figure out which session
+    or connection the message is attached to. This patch adds iscsi lib
+    and class dev_printks so all messages have a common prefix that
+    can be used to figure out which object printed it.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index b6f99dfbb038..8a178674cb18 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -629,8 +629,9 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	int rc;
+ 
+ 	if (tcp_conn->in.datalen) {
+-		printk(KERN_ERR "iscsi_tcp: invalid R2t with datalen %d\n",
+-		       tcp_conn->in.datalen);
++		iscsi_conn_printk(KERN_ERR, conn,
++				  "invalid R2t with datalen %d\n",
++				  tcp_conn->in.datalen);
+ 		return ISCSI_ERR_DATALEN;
+ 	}
+ 
+@@ -644,8 +645,9 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
+ 
+ 	if (!ctask->sc || session->state != ISCSI_STATE_LOGGED_IN) {
+-		printk(KERN_INFO "iscsi_tcp: dropping R2T itt %d in "
+-		       "recovery...\n", ctask->itt);
++		iscsi_conn_printk(KERN_INFO, conn,
++				  "dropping R2T itt %d in recovery.\n",
++				  ctask->itt);
+ 		return 0;
+ 	}
+ 
+@@ -655,7 +657,8 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	r2t->exp_statsn = rhdr->statsn;
+ 	r2t->data_length = be32_to_cpu(rhdr->data_length);
+ 	if (r2t->data_length == 0) {
+-		printk(KERN_ERR "iscsi_tcp: invalid R2T with zero data len\n");
++		iscsi_conn_printk(KERN_ERR, conn,
++				  "invalid R2T with zero data len\n");
+ 		__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
+ 			    sizeof(void*));
+ 		return ISCSI_ERR_DATALEN;
+@@ -668,9 +671,10 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 
+ 	r2t->data_offset = be32_to_cpu(rhdr->data_offset);
+ 	if (r2t->data_offset + r2t->data_length > scsi_bufflen(ctask->sc)) {
+-		printk(KERN_ERR "iscsi_tcp: invalid R2T with data len %u at "
+-		       "offset %u and total length %d\n", r2t->data_length,
+-		       r2t->data_offset, scsi_bufflen(ctask->sc));
++		iscsi_conn_printk(KERN_ERR, conn,
++				  "invalid R2T with data len %u at offset %u "
++				  "and total length %d\n", r2t->data_length,
++				  r2t->data_offset, scsi_bufflen(ctask->sc));
+ 		__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
+ 			    sizeof(void*));
+ 		return ISCSI_ERR_DATALEN;
+@@ -736,8 +740,9 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 	/* verify PDU length */
+ 	tcp_conn->in.datalen = ntoh24(hdr->dlength);
+ 	if (tcp_conn->in.datalen > conn->max_recv_dlength) {
+-		printk(KERN_ERR "iscsi_tcp: datalen %d > %d\n",
+-		       tcp_conn->in.datalen, conn->max_recv_dlength);
++		iscsi_conn_printk(KERN_ERR, conn,
++				  "iscsi_tcp: datalen %d > %d\n",
++				  tcp_conn->in.datalen, conn->max_recv_dlength);
+ 		return ISCSI_ERR_DATALEN;
+ 	}
+ 
+@@ -819,10 +824,12 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 		 * For now we fail until we find a vendor that needs it
+ 		 */
+ 		if (ISCSI_DEF_MAX_RECV_SEG_LEN < tcp_conn->in.datalen) {
+-			printk(KERN_ERR "iscsi_tcp: received buffer of len %u "
+-			      "but conn buffer is only %u (opcode %0x)\n",
+-			      tcp_conn->in.datalen,
+-			      ISCSI_DEF_MAX_RECV_SEG_LEN, opcode);
++			iscsi_conn_printk(KERN_ERR, conn,
++					  "iscsi_tcp: received buffer of "
++					  "len %u but conn buffer is only %u "
++					  "(opcode %0x)\n",
++					  tcp_conn->in.datalen,
++					  ISCSI_DEF_MAX_RECV_SEG_LEN, opcode);
+ 			rc = ISCSI_ERR_PROTO;
+ 			break;
+ 		}
+@@ -1496,30 +1503,25 @@ iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ 	tcp_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0,
+ 						  CRYPTO_ALG_ASYNC);
+ 	tcp_conn->tx_hash.flags = 0;
+-	if (IS_ERR(tcp_conn->tx_hash.tfm)) {
+-		printk(KERN_ERR "Could not create connection due to crc32c "
+-		       "loading error %ld. Make sure the crc32c module is "
+-		       "built as a module or into the kernel\n",
+-			PTR_ERR(tcp_conn->tx_hash.tfm));
++	if (IS_ERR(tcp_conn->tx_hash.tfm))
+ 		goto free_tcp_conn;
+-	}
+ 
+ 	tcp_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0,
+ 						  CRYPTO_ALG_ASYNC);
+ 	tcp_conn->rx_hash.flags = 0;
+-	if (IS_ERR(tcp_conn->rx_hash.tfm)) {
+-		printk(KERN_ERR "Could not create connection due to crc32c "
+-		       "loading error %ld. Make sure the crc32c module is "
+-		       "built as a module or into the kernel\n",
+-			PTR_ERR(tcp_conn->rx_hash.tfm));
++	if (IS_ERR(tcp_conn->rx_hash.tfm))
+ 		goto free_tx_tfm;
+-	}
+ 
+ 	return cls_conn;
+ 
+ free_tx_tfm:
+ 	crypto_free_hash(tcp_conn->tx_hash.tfm);
+ free_tcp_conn:
++	iscsi_conn_printk(KERN_ERR, conn,
++			  "Could not create connection due to crc32c "
++			  "loading error. Make sure the crc32c "
++			  "module is built as a module or into the "
++			  "kernel\n");
+ 	kfree(tcp_conn);
+ tcp_conn_alloc_fail:
+ 	iscsi_conn_teardown(cls_conn);
+@@ -1627,7 +1629,8 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
+ 	/* lookup for existing socket */
+ 	sock = sockfd_lookup((int)transport_eph, &err);
+ 	if (!sock) {
+-		printk(KERN_ERR "iscsi_tcp: sockfd_lookup failed %d\n", err);
++		iscsi_conn_printk(KERN_ERR, conn,
++				  "sockfd_lookup failed %d\n", err);
+ 		return -EEXIST;
+ 	}
+ 	/*
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index b2a1ec8725b8..10ba76285852 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -416,8 +416,9 @@ static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 
+ 		if (datalen < 2) {
+ invalid_datalen:
+-			printk(KERN_ERR "iscsi: Got CHECK_CONDITION but "
+-			       "invalid data buffer size of %d\n", datalen);
++			iscsi_conn_printk(KERN_ERR,  conn,
++					 "Got CHECK_CONDITION but invalid data "
++					 "buffer size of %d\n", datalen);
+ 			sc->result = DID_BAD_TARGET << 16;
+ 			goto out;
+ 		}
+@@ -494,7 +495,7 @@ static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
+ 
+ 	mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0);
+ 	if (!mtask) {
+-		printk(KERN_ERR "Could not send nopout\n");
++		iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n");
+ 		return;
+ 	}
+ 
+@@ -522,9 +523,10 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		if (ntoh24(reject->dlength) >= sizeof(struct iscsi_hdr)) {
+ 			memcpy(&rejected_pdu, data, sizeof(struct iscsi_hdr));
+ 			itt = get_itt(rejected_pdu.itt);
+-			printk(KERN_ERR "itt 0x%x had pdu (op 0x%x) rejected "
+-				"due to DataDigest error.\n", itt,
+-				rejected_pdu.opcode);
++			iscsi_conn_printk(KERN_ERR, conn,
++					  "itt 0x%x had pdu (op 0x%x) rejected "
++					  "due to DataDigest error.\n", itt,
++					  rejected_pdu.opcode);
+ 		}
+ 	}
+ 	return 0;
+@@ -696,16 +698,19 @@ int iscsi_verify_itt(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	if (hdr->itt != RESERVED_ITT) {
+ 		if (((__force u32)hdr->itt & ISCSI_AGE_MASK) !=
+ 		    (session->age << ISCSI_AGE_SHIFT)) {
+-			printk(KERN_ERR "iscsi: received itt %x expected "
+-				"session age (%x)\n", (__force u32)hdr->itt,
+-				session->age & ISCSI_AGE_MASK);
++			iscsi_conn_printk(KERN_ERR, conn,
++					  "received itt %x expected session "
++					  "age (%x)\n", (__force u32)hdr->itt,
++					  session->age & ISCSI_AGE_MASK);
+ 			return ISCSI_ERR_BAD_ITT;
+ 		}
+ 
+ 		if (((__force u32)hdr->itt & ISCSI_CID_MASK) !=
+ 		    (conn->id << ISCSI_CID_SHIFT)) {
+-			printk(KERN_ERR "iscsi: received itt %x, expected "
+-				"CID (%x)\n", (__force u32)hdr->itt, conn->id);
++			iscsi_conn_printk(KERN_ERR, conn,
++					  "iscsi: received itt %x, expected "
++					  "CID (%x)\n",
++					  (__force u32)hdr->itt, conn->id);
+ 			return ISCSI_ERR_BAD_ITT;
+ 		}
+ 		itt = get_itt(hdr->itt);
+@@ -716,16 +721,17 @@ int iscsi_verify_itt(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		ctask = session->cmds[itt];
+ 
+ 		if (!ctask->sc) {
+-			printk(KERN_INFO "iscsi: dropping ctask with "
+-			       "itt 0x%x\n", ctask->itt);
++			iscsi_conn_printk(KERN_INFO, conn, "dropping ctask "
++					  "with itt 0x%x\n", ctask->itt);
+ 			/* force drop */
+ 			return ISCSI_ERR_NO_SCSI_CMD;
+ 		}
+ 
+ 		if (ctask->sc->SCp.phase != session->age) {
+-			printk(KERN_ERR "iscsi: ctask's session age %d, "
+-				"expected %d\n", ctask->sc->SCp.phase,
+-				session->age);
++			iscsi_conn_printk(KERN_ERR, conn,
++					  "iscsi: ctask's session age %d, "
++					  "expected %d\n", ctask->sc->SCp.phase,
++					  session->age);
+ 			return ISCSI_ERR_SESSION_FAILED;
+ 		}
+ 	}
+@@ -1170,7 +1176,8 @@ int iscsi_eh_host_reset(struct scsi_cmnd *sc)
+ 	mutex_lock(&session->eh_mutex);
+ 	spin_lock_bh(&session->lock);
+ 	if (session->state == ISCSI_STATE_LOGGED_IN)
+-		printk(KERN_INFO "iscsi: host reset succeeded\n");
++		iscsi_session_printk(KERN_INFO, session,
++				     "host reset succeeded\n");
+ 	else
+ 		goto failed;
+ 	spin_unlock_bh(&session->lock);
+@@ -1368,10 +1375,10 @@ static void iscsi_check_transport_timeouts(unsigned long data)
+ 	last_recv = conn->last_recv;
+ 	if (time_before_eq(last_recv + timeout + (conn->ping_timeout * HZ),
+ 			   jiffies)) {
+-		printk(KERN_ERR "ping timeout of %d secs expired, "
+-		       "last rx %lu, last ping %lu, now %lu\n",
+-		       conn->ping_timeout, last_recv,
+-		       conn->last_ping, jiffies);
++		iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs "
++				  "expired, last rx %lu, last ping %lu, "
++				  "now %lu\n", conn->ping_timeout, last_recv,
++				  conn->last_ping, jiffies);
+ 		spin_unlock(&session->lock);
+ 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ 		return;
+@@ -1952,9 +1959,10 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
+ 		}
+ 		spin_unlock_irqrestore(session->host->host_lock, flags);
+ 		msleep_interruptible(500);
+-		printk(KERN_INFO "iscsi: scsi conn_destroy(): host_busy %d "
+-		       "host_failed %d\n", session->host->host_busy,
+-		       session->host->host_failed);
++		iscsi_conn_printk(KERN_INFO, conn, "iscsi conn_destroy(): "
++				  "host_busy %d host_failed %d\n",
++				  session->host->host_busy,
++				  session->host->host_failed);
+ 		/*
+ 		 * force eh_abort() to unblock
+ 		 */
+@@ -1983,27 +1991,28 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
+ 	struct iscsi_session *session = conn->session;
+ 
+ 	if (!session) {
+-		printk(KERN_ERR "iscsi: can't start unbound connection\n");
++		iscsi_conn_printk(KERN_ERR, conn,
++				  "can't start unbound connection\n");
+ 		return -EPERM;
+ 	}
+ 
+ 	if ((session->imm_data_en || !session->initial_r2t_en) &&
+ 	     session->first_burst > session->max_burst) {
+-		printk("iscsi: invalid burst lengths: "
+-		       "first_burst %d max_burst %d\n",
+-		       session->first_burst, session->max_burst);
++		iscsi_conn_printk(KERN_INFO, conn, "invalid burst lengths: "
++				  "first_burst %d max_burst %d\n",
++				  session->first_burst, session->max_burst);
+ 		return -EINVAL;
+ 	}
+ 
+ 	if (conn->ping_timeout && !conn->recv_timeout) {
+-		printk(KERN_ERR "iscsi: invalid recv timeout of zero "
+-		      "Using 5 seconds\n.");
++		iscsi_conn_printk(KERN_ERR, conn, "invalid recv timeout of "
++				  "zero. Using 5 seconds\n.");
+ 		conn->recv_timeout = 5;
+ 	}
+ 
+ 	if (conn->recv_timeout && !conn->ping_timeout) {
+-		printk(KERN_ERR "iscsi: invalid ping timeout of zero "
+-		      "Using 5 seconds.\n");
++		iscsi_conn_printk(KERN_ERR, conn, "invalid ping timeout of "
++				  "zero. Using 5 seconds.\n");
+ 		conn->ping_timeout = 5;
+ 	}
+ 
+@@ -2147,7 +2156,8 @@ void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+ 		iscsi_start_session_recovery(session, conn, flag);
+ 		break;
+ 	default:
+-		printk(KERN_ERR "iscsi: invalid stop flag %d\n", flag);
++		iscsi_conn_printk(KERN_ERR, conn,
++				  "invalid stop flag %d\n", flag);
+ 	}
+ }
+ EXPORT_SYMBOL_GPL(iscsi_conn_stop);
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 35834bf4ba86..8e73ff02fb74 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -350,8 +350,9 @@ static void session_recovery_timedout(struct work_struct *work)
+ 			     recovery_work.work);
+ 	unsigned long flags;
+ 
+-	dev_printk(KERN_INFO, &session->dev, "iscsi: session recovery timed "
+-		  "out after %d secs\n", session->recovery_tmo);
++	iscsi_cls_session_printk(KERN_INFO, session,
++				 "session recovery timed out after %d secs\n",
++				 session->recovery_tmo);
+ 
+ 	spin_lock_irqsave(&session->lock, flags);
+ 	switch (session->state) {
+@@ -492,8 +493,8 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
+ 		 session->sid);
+ 	err = device_add(&session->dev);
+ 	if (err) {
+-		dev_printk(KERN_ERR, &session->dev, "iscsi: could not "
+-			   "register session's dev\n");
++		iscsi_cls_session_printk(KERN_ERR, session,
++					 "could not register session's dev\n");
+ 		goto release_host;
+ 	}
+ 	transport_register_device(&session->dev);
+@@ -597,8 +598,9 @@ void iscsi_remove_session(struct iscsi_cls_session *session)
+ 	err = device_for_each_child(&session->dev, NULL,
+ 				    iscsi_iter_destroy_conn_fn);
+ 	if (err)
+-		dev_printk(KERN_ERR, &session->dev, "iscsi: Could not delete "
+-			   "all connections for session. Error %d.\n", err);
++		iscsi_cls_session_printk(KERN_ERR, session,
++					 "Could not delete all connections "
++					 "for session. Error %d.\n", err);
+ 
+ 	transport_unregister_device(&session->dev);
+ 	device_del(&session->dev);
+@@ -670,8 +672,8 @@ iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid)
+ 	conn->dev.release = iscsi_conn_release;
+ 	err = device_register(&conn->dev);
+ 	if (err) {
+-		dev_printk(KERN_ERR, &conn->dev, "iscsi: could not register "
+-			   "connection's dev\n");
++		iscsi_cls_session_printk(KERN_ERR, session, "could not "
++					 "register connection's dev\n");
+ 		goto release_parent_ref;
+ 	}
+ 	transport_register_device(&conn->dev);
+@@ -778,8 +780,8 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
+ 	skb = alloc_skb(len, GFP_ATOMIC);
+ 	if (!skb) {
+ 		iscsi_conn_error(conn, ISCSI_ERR_CONN_FAILED);
+-		dev_printk(KERN_ERR, &conn->dev, "iscsi: can not deliver "
+-			   "control PDU: OOM\n");
++		iscsi_cls_conn_printk(KERN_ERR, conn, "can not deliver "
++				      "control PDU: OOM\n");
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -819,8 +821,8 @@ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
+ 
+ 	skb = alloc_skb(len, GFP_ATOMIC);
+ 	if (!skb) {
+-		dev_printk(KERN_ERR, &conn->dev, "iscsi: gracefully ignored "
+-			  "conn error (%d)\n", error);
++		iscsi_cls_conn_printk(KERN_ERR, conn, "gracefully ignored "
++				      "conn error (%d)\n", error);
+ 		return;
+ 	}
+ 
+@@ -834,8 +836,8 @@ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
+ 
+ 	iscsi_broadcast_skb(skb, GFP_ATOMIC);
+ 
+-	dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n",
+-		   error);
++	iscsi_cls_conn_printk(KERN_INFO, conn, "detected conn error (%d)\n",
++			      error);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_conn_error);
+ 
+@@ -890,8 +892,8 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
+ 
+ 		skbstat = alloc_skb(len, GFP_ATOMIC);
+ 		if (!skbstat) {
+-			dev_printk(KERN_ERR, &conn->dev, "iscsi: can not "
+-				   "deliver stats: OOM\n");
++			iscsi_cls_conn_printk(KERN_ERR, conn, "can not "
++					      "deliver stats: OOM\n");
+ 			return -ENOMEM;
+ 		}
+ 
+@@ -947,8 +949,9 @@ int iscsi_session_event(struct iscsi_cls_session *session,
+ 
+ 	skb = alloc_skb(len, GFP_KERNEL);
+ 	if (!skb) {
+-		dev_printk(KERN_ERR, &session->dev, "Cannot notify userspace "
+-			  "of session event %u\n", event);
++		iscsi_cls_session_printk(KERN_ERR, session,
++					 "Cannot notify userspace of session "
++					 "event %u\n", event);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -971,8 +974,8 @@ int iscsi_session_event(struct iscsi_cls_session *session,
+ 		ev->r.unbind_session.sid = session->sid;
+ 		break;
+ 	default:
+-		dev_printk(KERN_ERR, &session->dev, "Invalid event %u.\n",
+-			   event);
++		iscsi_cls_session_printk(KERN_ERR, session, "Invalid event "
++					 "%u.\n", event);
+ 		kfree_skb(skb);
+ 		return -EINVAL;
+ 	}
+@@ -983,8 +986,10 @@ int iscsi_session_event(struct iscsi_cls_session *session,
+ 	 */
+ 	rc = iscsi_broadcast_skb(skb, GFP_KERNEL);
+ 	if (rc < 0)
+-		dev_printk(KERN_ERR, &session->dev, "Cannot notify userspace "
+-			  "of session event %u. Check iscsi daemon\n", event);
++		iscsi_cls_session_printk(KERN_ERR, session,
++					 "Cannot notify userspace of session "
++					 "event %u. Check iscsi daemon\n",
++					 event);
+ 	return rc;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_session_event);
+@@ -1017,16 +1022,15 @@ iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+ 
+ 	session = iscsi_session_lookup(ev->u.c_conn.sid);
+ 	if (!session) {
+-		printk(KERN_ERR "iscsi: invalid session %d\n",
++		printk(KERN_ERR "iscsi: invalid session %d.\n",
+ 		       ev->u.c_conn.sid);
+ 		return -EINVAL;
+ 	}
+ 
+ 	conn = transport->create_conn(session, ev->u.c_conn.cid);
+ 	if (!conn) {
+-		printk(KERN_ERR "iscsi: couldn't create a new "
+-			   "connection for session %d\n",
+-			   session->sid);
++		iscsi_cls_session_printk(KERN_ERR, session,
++					 "couldn't create a new connection.");
+ 		return -ENOMEM;
+ 	}
+ 
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 278011fb3c2f..5784e4ff8edc 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -344,6 +344,10 @@ extern int iscsi_session_get_param(struct iscsi_cls_session *cls_session,
+ #define session_to_cls(_sess) \
+ 	hostdata_session(_sess->host->hostdata)
+ 
++#define iscsi_session_printk(prefix, _sess, fmt, a...)	\
++	iscsi_cls_session_printk(prefix,		\
++		(struct iscsi_cls_session *)session_to_cls(_sess), fmt, ##a)
++
+ /*
+  * connection management
+  */
+@@ -358,6 +362,9 @@ extern void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err);
+ extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ 				enum iscsi_param param, char *buf);
+ 
++#define iscsi_conn_printk(prefix, _c, fmt, a...) \
++	iscsi_cls_conn_printk(prefix, _c->cls_conn, fmt, ##a)
++
+ /*
+  * pdu and task processing
+  */
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 83693ba09c29..dbc96ef4cc72 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -212,6 +212,12 @@ struct iscsi_host {
+ /*
+  * session and connection functions that can be used by HW iSCSI LLDs
+  */
++#define iscsi_cls_session_printk(prefix, _cls_session, fmt, a...) \
++	dev_printk(prefix, &(_cls_session)->dev, fmt, ##a)
++
++#define iscsi_cls_conn_printk(prefix, _cls_conn, fmt, a...) \
++	dev_printk(prefix, &(_cls_conn)->dev, fmt, ##a)
++
+ extern int iscsi_session_chkready(struct iscsi_cls_session *session);
+ extern struct iscsi_cls_session *iscsi_alloc_session(struct Scsi_Host *shost,
+ 					struct iscsi_transport *transport);

commit c238c3bba9b422a9b453c75e157b416204f22a71
+Author: Mike Christie 
+Date:   Thu Jan 31 13:36:51 2008 -0600
+
+    [SCSI] iscsi class: fix iscsi conn attr counter
+    
+    There are 13 iscsi conn attrs, but since the IF/OF markers were not being
+    used we did not notice that we forgot to increment the ISCSI_CONN_ATTRS
+    counter.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index af1799723e7b..35834bf4ba86 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -31,7 +31,7 @@
+ #include 
+ 
+ #define ISCSI_SESSION_ATTRS 19
+-#define ISCSI_CONN_ATTRS 11
++#define ISCSI_CONN_ATTRS 13
+ #define ISCSI_HOST_ATTRS 4
+ #define ISCSI_TRANSPORT_VERSION "2.0-867"
+ 

commit ad294e9cd11d029fc0d09ab129fba5bea46de0dc
+Author: Mike Christie 
+Date:   Thu Jan 31 13:36:50 2008 -0600
+
+    [SCSI] libiscsi: fix setting of nop timer
+    
+    If we rollover then we could get a next_timeout of zero, so we need
+    to set the new timer to that value.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index c8c00e173414..b2a1ec8725b8 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1384,14 +1384,11 @@ static void iscsi_check_transport_timeouts(unsigned long data)
+ 			iscsi_send_nopout(conn, NULL);
+ 		}
+ 		next_timeout = last_recv + timeout + (conn->ping_timeout * HZ);
+-	} else {
++	} else
+ 		next_timeout = last_recv + timeout;
+-	}
+ 
+-	if (next_timeout) {
+-		debug_scsi("Setting next tmo %lu\n", next_timeout);
+-		mod_timer(&conn->transport_timer, next_timeout);
+-	}
++	debug_scsi("Setting next tmo %lu\n", next_timeout);
++	mod_timer(&conn->transport_timer, next_timeout);
+ done:
+ 	spin_unlock(&session->lock);
+ }

commit 921601b7031f8a2c71f49f1b965ee00ebbca6886
+Author: Mike Christie 
+Date:   Thu Jan 31 13:36:49 2008 -0600
+
+    [SCSI] qla4xxx: add async scan support
+    
+    qla4xxx has the old school startup/probe where it finds presetup sessions
+    in its flash and then attempts to log into them before returning from the
+    probe. This however, makes it very simple to add a iscsi class scan finished
+    helper which the driver can use.
+    
+    In future patches Dave or I will rip apart the driver to make it more
+    like qla2xxx, but for now this is a very simple two line patch which
+    fixes the problem of trying to figure out when the initial sessions
+    are done being scanned.
+    
+    Signed-off-by: Mike Christie 
+    Cc: David Somayajulu 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index d4dd149b466f..c3c59d763037 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -89,6 +89,8 @@ static struct scsi_host_template qla4xxx_driver_template = {
+ 	.slave_alloc		= qla4xxx_slave_alloc,
+ 	.slave_destroy		= qla4xxx_slave_destroy,
+ 
++	.scan_finished		= iscsi_scan_finished,
++
+ 	.this_id		= -1,
+ 	.cmd_per_lun		= 3,
+ 	.use_clustering		= ENABLE_CLUSTERING,
+@@ -1306,7 +1308,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
+ 	       qla4xxx_version_str, ha->pdev->device, pci_name(ha->pdev),
+ 	       ha->host_no, ha->firmware_version[0], ha->firmware_version[1],
+ 	       ha->patch_number, ha->build_number);
+-
++	scsi_scan_host(host);
+ 	return 0;
+ 
+ remove_host:

commit 8aae18adb240a9eb1999b8245c56522cbefc9047
+Author: Mike Christie 
+Date:   Thu Jan 31 13:36:48 2008 -0600
+
+    [SCSI] iscsi class: add async scan helper
+    
+    In qla4xxx's probe it will call the iscsi session setup functions
+    for session that got setup on the initial start. This then makes
+    it easy for the iscsi class to export a helper which indicates
+    when those scans are done.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index af88955d0ec1..af1799723e7b 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -127,6 +127,7 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+ 	memset(ihost, 0, sizeof(*ihost));
+ 	INIT_LIST_HEAD(&ihost->sessions);
+ 	mutex_init(&ihost->mutex);
++	atomic_set(&ihost->nr_scans, 0);
+ 
+ 	snprintf(ihost->scan_workq_name, KOBJ_NAME_LEN, "iscsi_scan_%d",
+ 		shost->host_no);
+@@ -284,6 +285,25 @@ static int iscsi_is_session_dev(const struct device *dev)
+ 	return dev->release == iscsi_session_release;
+ }
+ 
++/**
++ * iscsi_scan_finished - helper to report when running scans are done
++ * @shost: scsi host
++ * @time: scan run time
++ *
++ * This function can be used by drives like qla4xxx to report to the scsi
++ * layer when the scans it kicked off at module load time are done.
++ */
++int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time)
++{
++	struct iscsi_host *ihost = shost->shost_data;
++	/*
++	 * qla4xxx will have kicked off some session unblocks before calling
++	 * scsi_scan_host, so just wait for them to complete.
++	 */
++	return !atomic_read(&ihost->nr_scans);
++}
++EXPORT_SYMBOL_GPL(iscsi_scan_finished);
++
+ static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
+ 			   uint id, uint lun)
+ {
+@@ -306,17 +326,21 @@ static void iscsi_scan_session(struct work_struct *work)
+ {
+ 	struct iscsi_cls_session *session =
+ 			container_of(work, struct iscsi_cls_session, scan_work);
++	struct Scsi_Host *shost = iscsi_session_to_shost(session);
++	struct iscsi_host *ihost = shost->shost_data;
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&session->lock, flags);
+ 	if (session->state != ISCSI_SESSION_LOGGED_IN) {
+ 		spin_unlock_irqrestore(&session->lock, flags);
+-		return;
++		goto done;
+ 	}
+ 	spin_unlock_irqrestore(&session->lock, flags);
+ 
+ 	scsi_scan_target(&session->dev, 0, session->target_id,
+ 			 SCAN_WILD_CARD, 1);
++done:
++	atomic_dec(&ihost->nr_scans);
+ }
+ 
+ static void session_recovery_timedout(struct work_struct *work)
+@@ -366,7 +390,15 @@ void iscsi_unblock_session(struct iscsi_cls_session *session)
+ 	spin_unlock_irqrestore(&session->lock, flags);
+ 
+ 	__iscsi_unblock_session(session);
+-	queue_work(ihost->scan_workq, &session->scan_work);
++	/*
++	 * Only do kernel scanning if the driver is properly hooked into
++	 * the async scanning code (drivers like iscsi_tcp do login and
++	 * scanning from userspace).
++	 */
++	if (shost->hostt->scan_finished) {
++		if (queue_work(ihost->scan_workq, &session->scan_work))
++			atomic_inc(&ihost->nr_scans);
++	}
+ }
+ EXPORT_SYMBOL_GPL(iscsi_unblock_session);
+ 
+@@ -550,7 +582,7 @@ void iscsi_remove_session(struct iscsi_cls_session *session)
+ 	session->state = ISCSI_SESSION_FREE;
+ 	spin_unlock_irqrestore(&session->lock, flags);
+ 	__iscsi_unblock_session(session);
+-	iscsi_unbind_session(session);
++	__iscsi_unbind_session(&session->unbind_work);
+ 
+ 	/* flush running scans */
+ 	flush_workqueue(ihost->scan_workq);
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 1f0ec46b4f87..83693ba09c29 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -203,6 +203,7 @@ struct iscsi_cls_session {
+ 
+ struct iscsi_host {
+ 	struct list_head sessions;
++	atomic_t nr_scans;
+ 	struct mutex mutex;
+ 	struct workqueue_struct *scan_workq;
+ 	char scan_workq_name[KOBJ_NAME_LEN];
+@@ -229,6 +230,6 @@ extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess,
+ extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn);
+ extern void iscsi_unblock_session(struct iscsi_cls_session *session);
+ extern void iscsi_block_session(struct iscsi_cls_session *session);
+-
++extern int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time);
+ 
+ #endif

commit 568d303b5b3f0f6432ae8f56ecdb0beb2341288e
+Author: Mike Christie 
+Date:   Thu Jan 31 13:36:47 2008 -0600
+
+    [SCSI] qla4xxx: fix recovery timer and session unblock race
+    
+    If qla4xxx is resetting up a session and the recovery timer
+    fires we do not want to just set it to dead, because
+    the dpc thread could have just set it to online and is in the
+    middle of resetting it up.
+    
+    Signed-off-by: Mike Christie 
+    Cc: David Somayajulu 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index 437d169a9814..d4dd149b466f 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -124,16 +124,19 @@ static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session)
+ 	struct ddb_entry *ddb_entry = session->dd_data;
+ 	struct scsi_qla_host *ha = ddb_entry->ha;
+ 
+-	DEBUG2(printk("scsi%ld: %s: index [%d] port down retry count of (%d) "
+-		      "secs exhausted, marking device DEAD.\n", ha->host_no,
+-		      __func__, ddb_entry->fw_ddb_index,
+-		      ha->port_down_retry_count));
++	if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) {
++		atomic_set(&ddb_entry->state, DDB_STATE_DEAD);
+ 
+-	atomic_set(&ddb_entry->state, DDB_STATE_DEAD);
++		DEBUG2(printk("scsi%ld: %s: index [%d] port down retry count "
++			      "of (%d) secs exhausted, marking device DEAD.\n",
++			      ha->host_no, __func__, ddb_entry->fw_ddb_index,
++			      ha->port_down_retry_count));
+ 
+-	DEBUG2(printk("scsi%ld: %s: scheduling dpc routine - dpc flags = "
+-		      "0x%lx\n", ha->host_no, __func__, ha->dpc_flags));
+-	queue_work(ha->dpc_thread, &ha->dpc_work);
++		DEBUG2(printk("scsi%ld: %s: scheduling dpc routine - dpc "
++			      "flags = 0x%lx\n",
++			      ha->host_no, __func__, ha->dpc_flags));
++		queue_work(ha->dpc_thread, &ha->dpc_work);
++	}
+ }
+ 
+ static int qla4xxx_host_get_param(struct Scsi_Host *shost,

commit bd976f62cd6c6dda1ce57bf3e84447e94844868a
+Author: Mike Christie 
+Date:   Thu Jan 31 13:36:46 2008 -0600
+
+    [SCSI] iscsi class: add session scanning
+    
+    This just adds iscsi session scanning which works like fc rport scanning.
+    The future patches will hook the drivers into Mathew Wilcox's async
+    scanning infrastructure, so userspace does not have to special case
+    iscsi and so userspace does not have to make a extra special case for
+    hardware iscsi root scanning.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index f876b0ae521a..af88955d0ec1 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -128,11 +128,11 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+ 	INIT_LIST_HEAD(&ihost->sessions);
+ 	mutex_init(&ihost->mutex);
+ 
+-	snprintf(ihost->unbind_workq_name, KOBJ_NAME_LEN, "iscsi_unbind_%d",
++	snprintf(ihost->scan_workq_name, KOBJ_NAME_LEN, "iscsi_scan_%d",
+ 		shost->host_no);
+-	ihost->unbind_workq = create_singlethread_workqueue(
+-						ihost->unbind_workq_name);
+-	if (!ihost->unbind_workq)
++	ihost->scan_workq = create_singlethread_workqueue(
++						ihost->scan_workq_name);
++	if (!ihost->scan_workq)
+ 		return -ENOMEM;
+ 	return 0;
+ }
+@@ -143,7 +143,7 @@ static int iscsi_remove_host(struct transport_container *tc, struct device *dev,
+ 	struct Scsi_Host *shost = dev_to_shost(dev);
+ 	struct iscsi_host *ihost = shost->shost_data;
+ 
+-	destroy_workqueue(ihost->unbind_workq);
++	destroy_workqueue(ihost->scan_workq);
+ 	return 0;
+ }
+ 
+@@ -302,6 +302,23 @@ static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
+ 	return 0;
+ }
+ 
++static void iscsi_scan_session(struct work_struct *work)
++{
++	struct iscsi_cls_session *session =
++			container_of(work, struct iscsi_cls_session, scan_work);
++	unsigned long flags;
++
++	spin_lock_irqsave(&session->lock, flags);
++	if (session->state != ISCSI_SESSION_LOGGED_IN) {
++		spin_unlock_irqrestore(&session->lock, flags);
++		return;
++	}
++	spin_unlock_irqrestore(&session->lock, flags);
++
++	scsi_scan_target(&session->dev, 0, session->target_id,
++			 SCAN_WILD_CARD, 1);
++}
++
+ static void session_recovery_timedout(struct work_struct *work)
+ {
+ 	struct iscsi_cls_session *session =
+@@ -340,6 +357,8 @@ void __iscsi_unblock_session(struct iscsi_cls_session *session)
+ 
+ void iscsi_unblock_session(struct iscsi_cls_session *session)
+ {
++	struct Scsi_Host *shost = iscsi_session_to_shost(session);
++	struct iscsi_host *ihost = shost->shost_data;
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&session->lock, flags);
+@@ -347,6 +366,7 @@ void iscsi_unblock_session(struct iscsi_cls_session *session)
+ 	spin_unlock_irqrestore(&session->lock, flags);
+ 
+ 	__iscsi_unblock_session(session);
++	queue_work(ihost->scan_workq, &session->scan_work);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_unblock_session);
+ 
+@@ -390,7 +410,7 @@ static int iscsi_unbind_session(struct iscsi_cls_session *session)
+ 	struct Scsi_Host *shost = iscsi_session_to_shost(session);
+ 	struct iscsi_host *ihost = shost->shost_data;
+ 
+-	return queue_work(ihost->unbind_workq, &session->unbind_work);
++	return queue_work(ihost->scan_workq, &session->unbind_work);
+ }
+ 
+ struct iscsi_cls_session *
+@@ -411,6 +431,7 @@ iscsi_alloc_session(struct Scsi_Host *shost,
+ 	INIT_LIST_HEAD(&session->host_list);
+ 	INIT_LIST_HEAD(&session->sess_list);
+ 	INIT_WORK(&session->unbind_work, __iscsi_unbind_session);
++	INIT_WORK(&session->scan_work, iscsi_scan_session);
+ 	spin_lock_init(&session->lock);
+ 
+ 	/* this is released in the dev's release function */
+@@ -530,13 +551,15 @@ void iscsi_remove_session(struct iscsi_cls_session *session)
+ 	spin_unlock_irqrestore(&session->lock, flags);
+ 	__iscsi_unblock_session(session);
+ 	iscsi_unbind_session(session);
++
++	/* flush running scans */
++	flush_workqueue(ihost->scan_workq);
+ 	/*
+ 	 * If the session dropped while removing devices then we need to make
+ 	 * sure it is not blocked
+ 	 */
+ 	if (!cancel_delayed_work(&session->recovery_work))
+ 		flush_workqueue(iscsi_eh_timer_workq);
+-	flush_workqueue(ihost->unbind_workq);
+ 
+ 	/* hw iscsi may not have removed all connections from session */
+ 	err = device_for_each_child(&session->dev, NULL,
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 0e869d9a3856..1f0ec46b4f87 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -177,11 +177,12 @@ struct iscsi_cls_session {
+ 	struct list_head host_list;
+ 	struct iscsi_transport *transport;
+ 	spinlock_t lock;
++	struct work_struct scan_work;
++	struct work_struct unbind_work;
+ 
+ 	/* recovery fields */
+ 	int recovery_tmo;
+ 	struct delayed_work recovery_work;
+-	struct work_struct unbind_work;
+ 
+ 	int target_id;
+ 
+@@ -203,8 +204,8 @@ struct iscsi_cls_session {
+ struct iscsi_host {
+ 	struct list_head sessions;
+ 	struct mutex mutex;
+-	struct workqueue_struct *unbind_workq;
+-	char unbind_workq_name[KOBJ_NAME_LEN];
++	struct workqueue_struct *scan_workq;
++	char scan_workq_name[KOBJ_NAME_LEN];
+ };
+ 
+ /*

commit 7fb1921b07a83f71a77f806a2a7d2dd721ea641b
+Author: Mike Christie 
+Date:   Thu Jan 31 13:36:45 2008 -0600
+
+    [SCSI] qla4xxx: use iscsi class session state check ready
+    
+    This has qla4xxx use the iscsi class's check ready function
+    in the queue command function, so all iscsi drivers return the
+    same error value for common problems.
+    
+    Signed-off-by: Mike Christie 
+    Cc: David Somayajulu 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index a87fb9f00ac4..437d169a9814 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -398,9 +398,21 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
+ {
+ 	struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
+ 	struct ddb_entry *ddb_entry = cmd->device->hostdata;
++	struct iscsi_cls_session *sess = ddb_entry->sess;
+ 	struct srb *srb;
+ 	int rval;
+ 
++	if (!sess) {
++		cmd->result = DID_IMM_RETRY << 16;
++		goto qc_fail_command;
++	}
++
++	rval = iscsi_session_chkready(sess);
++	if (rval) {
++		cmd->result = rval;
++		goto qc_fail_command;
++	}
++
+ 	if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) {
+ 		if (atomic_read(&ddb_entry->state) == DDB_STATE_DEAD) {
+ 			cmd->result = DID_NO_CONNECT << 16;

commit b635930de91be0a217292e3fe381af273e5ffaf7
+Author: Mike Christie 
+Date:   Thu Jan 31 13:36:44 2008 -0600
+
+    [SCSI] qla4xxx: directly call iscsi recovery functions
+    
+    Qla4xxx can just call the iscsi recovery functions directly.
+    There is no need for userspace to do this for qla4xxx, because
+    we do not use the mutex to iterate over devices anymore and iscsi_block
+    /unblock_session can be called from interrupt context or the dpc thread.
+    And having userspace do this just creates uneeded headaches for qla4xxx root
+    situations where the session may experience problems. For example
+    during the kernel shutdown the scsi layer wants to send sync caches, but at
+    this time userspace is not up (iscsid is not running), so we cannot
+    recover from the problem.
+    
+    Signed-off-by: Mike Christie 
+    Cc: David Somayajulu 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
+index 49925f92555e..10b3b9a620f3 100644
+--- a/drivers/scsi/qla4xxx/ql4_init.c
++++ b/drivers/scsi/qla4xxx/ql4_init.c
+@@ -1306,6 +1306,7 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha,
+ 		atomic_set(&ddb_entry->relogin_timer, 0);
+ 		clear_bit(DF_RELOGIN, &ddb_entry->flags);
+ 		clear_bit(DF_NO_RELOGIN, &ddb_entry->flags);
++		iscsi_unblock_session(ddb_entry->sess);
+ 		iscsi_session_event(ddb_entry->sess,
+ 				    ISCSI_KEVENT_CREATE_SESSION);
+ 		/*
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index 2e2b9fedffcc..a87fb9f00ac4 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -63,8 +63,6 @@ static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess,
+ 				  enum iscsi_param param, char *buf);
+ static int qla4xxx_host_get_param(struct Scsi_Host *shost,
+ 				  enum iscsi_host_param param, char *buf);
+-static void qla4xxx_conn_stop(struct iscsi_cls_conn *conn, int flag);
+-static int qla4xxx_conn_start(struct iscsi_cls_conn *conn);
+ static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session);
+ 
+ /*
+@@ -116,8 +114,6 @@ static struct iscsi_transport qla4xxx_iscsi_transport = {
+ 	.get_conn_param		= qla4xxx_conn_get_param,
+ 	.get_session_param	= qla4xxx_sess_get_param,
+ 	.get_host_param		= qla4xxx_host_get_param,
+-	.start_conn		= qla4xxx_conn_start,
+-	.stop_conn		= qla4xxx_conn_stop,
+ 	.session_recovery_timedout = qla4xxx_recovery_timedout,
+ };
+ 
+@@ -140,38 +136,6 @@ static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session)
+ 	queue_work(ha->dpc_thread, &ha->dpc_work);
+ }
+ 
+-static int qla4xxx_conn_start(struct iscsi_cls_conn *conn)
+-{
+-	struct iscsi_cls_session *session;
+-	struct ddb_entry *ddb_entry;
+-
+-	session = iscsi_dev_to_session(conn->dev.parent);
+-	ddb_entry = session->dd_data;
+-
+-	DEBUG2(printk("scsi%ld: %s: index [%d] starting conn\n",
+-		      ddb_entry->ha->host_no, __func__,
+-		      ddb_entry->fw_ddb_index));
+-	iscsi_unblock_session(session);
+-	return 0;
+-}
+-
+-static void qla4xxx_conn_stop(struct iscsi_cls_conn *conn, int flag)
+-{
+-	struct iscsi_cls_session *session;
+-	struct ddb_entry *ddb_entry;
+-
+-	session = iscsi_dev_to_session(conn->dev.parent);
+-	ddb_entry = session->dd_data;
+-
+-	DEBUG2(printk("scsi%ld: %s: index [%d] stopping conn\n",
+-		      ddb_entry->ha->host_no, __func__,
+-		      ddb_entry->fw_ddb_index));
+-	if (flag == STOP_CONN_RECOVER)
+-		iscsi_block_session(session);
+-	else
+-		printk(KERN_ERR "iscsi: invalid stop flag %d\n", flag);
+-}
+-
+ static int qla4xxx_host_get_param(struct Scsi_Host *shost,
+ 				  enum iscsi_host_param param, char *buf)
+ {
+@@ -308,6 +272,9 @@ int qla4xxx_add_sess(struct ddb_entry *ddb_entry)
+ 		DEBUG2(printk(KERN_ERR "Could not add connection.\n"));
+ 		return -ENOMEM;
+ 	}
++
++	/* finally ready to go */
++	iscsi_unblock_session(ddb_entry->sess);
+ 	return 0;
+ }
+ 
+@@ -364,6 +331,7 @@ void qla4xxx_mark_device_missing(struct scsi_qla_host *ha,
+ 	DEBUG3(printk("scsi%d:%d:%d: index [%d] marked MISSING\n",
+ 		      ha->host_no, ddb_entry->bus, ddb_entry->target,
+ 		      ddb_entry->fw_ddb_index));
++	iscsi_block_session(ddb_entry->sess);
+ 	iscsi_conn_error(ddb_entry->conn, ISCSI_ERR_CONN_FAILED);
+ }
+ 

commit 6eabafbe6616266e8de61980a7dac5ecc1ba1113
+Author: Mike Christie 
+Date:   Thu Jan 31 13:36:43 2008 -0600
+
+    [SCSI] iscsi class, libiscsi: add iscsi sysfs session state file
+    
+    This adds a iscsi session state file which exports the session
+    state for both software and hardware iscsi. It also hooks libiscsi
+    in.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index e7942628ac4a..c8c00e173414 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -996,6 +996,7 @@ enum {
+ 	FAILURE_SESSION_IN_RECOVERY,
+ 	FAILURE_SESSION_RECOVERY_TIMEOUT,
+ 	FAILURE_SESSION_LOGGING_OUT,
++	FAILURE_SESSION_NOT_READY,
+ };
+ 
+ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+@@ -1016,6 +1017,12 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 	session = iscsi_hostdata(host->hostdata);
+ 	spin_lock(&session->lock);
+ 
++	reason = iscsi_session_chkready(session_to_cls(session));
++	if (reason) {
++		sc->result = reason;
++		goto fault;
++	}
++
+ 	/*
+ 	 * ISCSI_STATE_FAILED is a temp. state. The recovery
+ 	 * code will decide what is best to do with command queued
+@@ -1032,18 +1039,23 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 		switch (session->state) {
+ 		case ISCSI_STATE_IN_RECOVERY:
+ 			reason = FAILURE_SESSION_IN_RECOVERY;
+-			goto reject;
++			sc->result = DID_IMM_RETRY << 16;
++			break;
+ 		case ISCSI_STATE_LOGGING_OUT:
+ 			reason = FAILURE_SESSION_LOGGING_OUT;
+-			goto reject;
++			sc->result = DID_IMM_RETRY << 16;
++			break;
+ 		case ISCSI_STATE_RECOVERY_FAILED:
+ 			reason = FAILURE_SESSION_RECOVERY_TIMEOUT;
++			sc->result = DID_NO_CONNECT << 16;
+ 			break;
+ 		case ISCSI_STATE_TERMINATE:
+ 			reason = FAILURE_SESSION_TERMINATE;
++			sc->result = DID_NO_CONNECT << 16;
+ 			break;
+ 		default:
+ 			reason = FAILURE_SESSION_FREED;
++			sc->result = DID_NO_CONNECT << 16;
+ 		}
+ 		goto fault;
+ 	}
+@@ -1051,6 +1063,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 	conn = session->leadconn;
+ 	if (!conn) {
+ 		reason = FAILURE_SESSION_FREED;
++		sc->result = DID_NO_CONNECT << 16;
+ 		goto fault;
+ 	}
+ 
+@@ -1090,9 +1103,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 
+ fault:
+ 	spin_unlock(&session->lock);
+-	printk(KERN_ERR "iscsi: cmd 0x%x is not queued (%d)\n",
+-	       sc->cmnd[0], reason);
+-	sc->result = (DID_NO_CONNECT << 16);
++	debug_scsi("iscsi: cmd 0x%x is not queued (%d)\n", sc->cmnd[0], reason);
+ 	scsi_set_resid(sc, scsi_bufflen(sc));
+ 	sc->scsi_done(sc);
+ 	spin_lock(host->host_lock);
+@@ -1238,7 +1249,8 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn,
+  * Fail commands. session lock held and recv side suspended and xmit
+  * thread flushed
+  */
+-static void fail_all_commands(struct iscsi_conn *conn, unsigned lun)
++static void fail_all_commands(struct iscsi_conn *conn, unsigned lun,
++			      int error)
+ {
+ 	struct iscsi_cmd_task *ctask, *tmp;
+ 
+@@ -1250,7 +1262,7 @@ static void fail_all_commands(struct iscsi_conn *conn, unsigned lun)
+ 		if (lun == ctask->sc->device->lun || lun == -1) {
+ 			debug_scsi("failing pending sc %p itt 0x%x\n",
+ 				   ctask->sc, ctask->itt);
+-			fail_command(conn, ctask, DID_BUS_BUSY << 16);
++			fail_command(conn, ctask, error << 16);
+ 		}
+ 	}
+ 
+@@ -1258,7 +1270,7 @@ static void fail_all_commands(struct iscsi_conn *conn, unsigned lun)
+ 		if (lun == ctask->sc->device->lun || lun == -1) {
+ 			debug_scsi("failing requeued sc %p itt 0x%x\n",
+ 				   ctask->sc, ctask->itt);
+-			fail_command(conn, ctask, DID_BUS_BUSY << 16);
++			fail_command(conn, ctask, error << 16);
+ 		}
+ 	}
+ 
+@@ -1572,7 +1584,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc)
+ 	/* need to grab the recv lock then session lock */
+ 	write_lock_bh(conn->recv_lock);
+ 	spin_lock(&session->lock);
+-	fail_all_commands(conn, sc->device->lun);
++	fail_all_commands(conn, sc->device->lun, DID_ERROR);
+ 	conn->tmf_state = TMF_INITIAL;
+ 	spin_unlock(&session->lock);
+ 	write_unlock_bh(conn->recv_lock);
+@@ -2018,11 +2030,7 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
+ 		conn->stop_stage = 0;
+ 		conn->tmf_state = TMF_INITIAL;
+ 		session->age++;
+-		spin_unlock_bh(&session->lock);
+-
+-		iscsi_unblock_session(session_to_cls(session));
+-		wake_up(&conn->ehwait);
+-		return 0;
++		break;
+ 	case STOP_CONN_TERM:
+ 		conn->stop_stage = 0;
+ 		break;
+@@ -2031,6 +2039,8 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
+ 	}
+ 	spin_unlock_bh(&session->lock);
+ 
++	iscsi_unblock_session(session_to_cls(session));
++	wake_up(&conn->ehwait);
+ 	return 0;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_conn_start);
+@@ -2122,7 +2132,8 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ 	 * flush queues.
+ 	 */
+ 	spin_lock_bh(&session->lock);
+-	fail_all_commands(conn, -1);
++	fail_all_commands(conn, -1,
++			STOP_CONN_RECOVER ? DID_BUS_BUSY : DID_ERROR);
+ 	flush_control_queues(session, conn);
+ 	spin_unlock_bh(&session->lock);
+ 	mutex_unlock(&session->eh_mutex);
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 0d7b4e79415c..f876b0ae521a 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -30,7 +30,7 @@
+ #include 
+ #include 
+ 
+-#define ISCSI_SESSION_ATTRS 18
++#define ISCSI_SESSION_ATTRS 19
+ #define ISCSI_CONN_ATTRS 11
+ #define ISCSI_HOST_ATTRS 4
+ #define ISCSI_TRANSPORT_VERSION "2.0-867"
+@@ -221,6 +221,54 @@ static struct iscsi_cls_conn *iscsi_conn_lookup(uint32_t sid, uint32_t cid)
+  * The following functions can be used by LLDs that allocate
+  * their own scsi_hosts or by software iscsi LLDs
+  */
++static struct {
++	int value;
++	char *name;
++} iscsi_session_state_names[] = {
++	{ ISCSI_SESSION_LOGGED_IN,	"LOGGED_IN" },
++	{ ISCSI_SESSION_FAILED,		"FAILED" },
++	{ ISCSI_SESSION_FREE,		"FREE" },
++};
++
++const char *iscsi_session_state_name(int state)
++{
++	int i;
++	char *name = NULL;
++
++	for (i = 0; i < ARRAY_SIZE(iscsi_session_state_names); i++) {
++		if (iscsi_session_state_names[i].value == state) {
++			name = iscsi_session_state_names[i].name;
++			break;
++		}
++	}
++	return name;
++}
++
++int iscsi_session_chkready(struct iscsi_cls_session *session)
++{
++	unsigned long flags;
++	int err;
++
++	spin_lock_irqsave(&session->lock, flags);
++	switch (session->state) {
++	case ISCSI_SESSION_LOGGED_IN:
++		err = 0;
++		break;
++	case ISCSI_SESSION_FAILED:
++		err = DID_IMM_RETRY << 16;
++		break;
++	case ISCSI_SESSION_FREE:
++		err = DID_NO_CONNECT << 16;
++		break;
++	default:
++		err = DID_NO_CONNECT << 16;
++		break;
++	}
++	spin_unlock_irqrestore(&session->lock, flags);
++	return err;
++}
++EXPORT_SYMBOL_GPL(iscsi_session_chkready);
++
+ static void iscsi_session_release(struct device *dev)
+ {
+ 	struct iscsi_cls_session *session = iscsi_dev_to_session(dev);
+@@ -259,26 +307,57 @@ static void session_recovery_timedout(struct work_struct *work)
+ 	struct iscsi_cls_session *session =
+ 		container_of(work, struct iscsi_cls_session,
+ 			     recovery_work.work);
++	unsigned long flags;
+ 
+ 	dev_printk(KERN_INFO, &session->dev, "iscsi: session recovery timed "
+ 		  "out after %d secs\n", session->recovery_tmo);
+ 
++	spin_lock_irqsave(&session->lock, flags);
++	switch (session->state) {
++	case ISCSI_SESSION_FAILED:
++		session->state = ISCSI_SESSION_FREE;
++		break;
++	case ISCSI_SESSION_LOGGED_IN:
++	case ISCSI_SESSION_FREE:
++		/* we raced with the unblock's flush */
++		spin_unlock_irqrestore(&session->lock, flags);
++		return;
++	}
++	spin_unlock_irqrestore(&session->lock, flags);
++
+ 	if (session->transport->session_recovery_timedout)
+ 		session->transport->session_recovery_timedout(session);
+ 
+ 	scsi_target_unblock(&session->dev);
+ }
+ 
+-void iscsi_unblock_session(struct iscsi_cls_session *session)
++void __iscsi_unblock_session(struct iscsi_cls_session *session)
+ {
+ 	if (!cancel_delayed_work(&session->recovery_work))
+ 		flush_workqueue(iscsi_eh_timer_workq);
+ 	scsi_target_unblock(&session->dev);
+ }
++
++void iscsi_unblock_session(struct iscsi_cls_session *session)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&session->lock, flags);
++	session->state = ISCSI_SESSION_LOGGED_IN;
++	spin_unlock_irqrestore(&session->lock, flags);
++
++	__iscsi_unblock_session(session);
++}
+ EXPORT_SYMBOL_GPL(iscsi_unblock_session);
+ 
+ void iscsi_block_session(struct iscsi_cls_session *session)
+ {
++	unsigned long flags;
++
++	spin_lock_irqsave(&session->lock, flags);
++	session->state = ISCSI_SESSION_FAILED;
++	spin_unlock_irqrestore(&session->lock, flags);
++
+ 	scsi_target_block(&session->dev);
+ 	queue_delayed_work(iscsi_eh_timer_workq, &session->recovery_work,
+ 			   session->recovery_tmo * HZ);
+@@ -327,10 +406,12 @@ iscsi_alloc_session(struct Scsi_Host *shost,
+ 
+ 	session->transport = transport;
+ 	session->recovery_tmo = 120;
++	session->state = ISCSI_SESSION_FREE;
+ 	INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout);
+ 	INIT_LIST_HEAD(&session->host_list);
+ 	INIT_LIST_HEAD(&session->sess_list);
+ 	INIT_WORK(&session->unbind_work, __iscsi_unbind_session);
++	spin_lock_init(&session->lock);
+ 
+ 	/* this is released in the dev's release function */
+ 	scsi_host_get(shost);
+@@ -444,7 +525,10 @@ void iscsi_remove_session(struct iscsi_cls_session *session)
+ 	 * If we are blocked let commands flow again. The lld or iscsi
+ 	 * layer should set up the queuecommand to fail commands.
+ 	 */
+-	iscsi_unblock_session(session);
++	spin_lock_irqsave(&session->lock, flags);
++	session->state = ISCSI_SESSION_FREE;
++	spin_unlock_irqrestore(&session->lock, flags);
++	__iscsi_unblock_session(session);
+ 	iscsi_unbind_session(session);
+ 	/*
+ 	 * If the session dropped while removing devices then we need to make
+@@ -661,16 +745,23 @@ EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
+ 
+ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
+ {
++	struct iscsi_cls_session *session = iscsi_conn_to_session(conn);
+ 	struct nlmsghdr	*nlh;
+ 	struct sk_buff	*skb;
+ 	struct iscsi_uevent *ev;
+ 	struct iscsi_internal *priv;
+ 	int len = NLMSG_SPACE(sizeof(*ev));
++	unsigned long flags;
+ 
+ 	priv = iscsi_if_transport_lookup(conn->transport);
+ 	if (!priv)
+ 		return;
+ 
++	spin_lock_irqsave(&session->lock, flags);
++	if (session->state == ISCSI_SESSION_LOGGED_IN)
++		session->state = ISCSI_SESSION_FAILED;
++	spin_unlock_irqrestore(&session->lock, flags);
++
+ 	skb = alloc_skb(len, GFP_ATOMIC);
+ 	if (!skb) {
+ 		dev_printk(KERN_ERR, &conn->dev, "iscsi: gracefully ignored "
+@@ -1246,6 +1337,15 @@ iscsi_session_attr(fast_abort, ISCSI_PARAM_FAST_ABORT, 0);
+ iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0);
+ iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 0);
+ 
++static ssize_t
++show_priv_session_state(struct class_device *cdev, char *buf)
++{
++	struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev);
++	return sprintf(buf, "%s\n", iscsi_session_state_name(session->state));
++}
++static ISCSI_CLASS_ATTR(priv_sess, state, S_IRUGO, show_priv_session_state,
++			NULL);
++
+ #define iscsi_priv_session_attr_show(field, format)			\
+ static ssize_t								\
+ show_priv_session_##field(struct class_device *cdev, char *buf)		\
+@@ -1472,6 +1572,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 	SETUP_SESSION_RD_ATTR(abort_tmo, ISCSI_ABORT_TMO);
+ 	SETUP_SESSION_RD_ATTR(lu_reset_tmo,ISCSI_LU_RESET_TMO);
+ 	SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo);
++	SETUP_PRIV_SESSION_RD_ATTR(state);
+ 
+ 	BUG_ON(count > ISCSI_SESSION_ATTRS);
+ 	priv->session_attrs[count] = NULL;
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 71eda24114e9..278011fb3c2f 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -135,6 +135,14 @@ static inline void* iscsi_next_hdr(struct iscsi_cmd_task *ctask)
+ 	return (void*)ctask->hdr + ctask->hdr_len;
+ }
+ 
++/* Connection's states */
++enum {
++	ISCSI_CONN_INITIAL_STAGE,
++	ISCSI_CONN_STARTED,
++	ISCSI_CONN_STOPPED,
++	ISCSI_CONN_CLEANUP_WAIT,
++};
++
+ struct iscsi_conn {
+ 	struct iscsi_cls_conn	*cls_conn;	/* ptr to class connection */
+ 	void			*dd_data;	/* iscsi_transport data */
+@@ -227,6 +235,17 @@ struct iscsi_pool {
+ 	int			max;		/* Max number of elements */
+ };
+ 
++/* Session's states */
++enum {
++	ISCSI_STATE_FREE = 1,
++	ISCSI_STATE_LOGGED_IN,
++	ISCSI_STATE_FAILED,
++	ISCSI_STATE_TERMINATE,
++	ISCSI_STATE_IN_RECOVERY,
++	ISCSI_STATE_RECOVERY_FAILED,
++	ISCSI_STATE_LOGGING_OUT,
++};
++
+ struct iscsi_session {
+ 	/*
+ 	 * Syncs up the scsi eh thread with the iscsi eh thread when sending
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 404f11d331d6..0e869d9a3856 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -149,13 +149,6 @@ extern void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error);
+ extern int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
+ 			  char *data, uint32_t data_size);
+ 
+-
+-/* Connection's states */
+-#define ISCSI_CONN_INITIAL_STAGE	0
+-#define ISCSI_CONN_STARTED		1
+-#define ISCSI_CONN_STOPPED		2
+-#define ISCSI_CONN_CLEANUP_WAIT		3
+-
+ struct iscsi_cls_conn {
+ 	struct list_head conn_list;	/* item in connlist */
+ 	void *dd_data;			/* LLD private data */
+@@ -169,19 +162,21 @@ struct iscsi_cls_conn {
+ #define iscsi_dev_to_conn(_dev) \
+ 	container_of(_dev, struct iscsi_cls_conn, dev)
+ 
+-/* Session's states */
+-#define ISCSI_STATE_FREE		1
+-#define ISCSI_STATE_LOGGED_IN		2
+-#define ISCSI_STATE_FAILED		3
+-#define ISCSI_STATE_TERMINATE		4
+-#define ISCSI_STATE_IN_RECOVERY		5
+-#define ISCSI_STATE_RECOVERY_FAILED	6
+-#define ISCSI_STATE_LOGGING_OUT		7
++#define iscsi_conn_to_session(_conn) \
++	iscsi_dev_to_session(_conn->dev.parent)
++
++/* iscsi class session state */
++enum {
++	ISCSI_SESSION_LOGGED_IN,
++	ISCSI_SESSION_FAILED,
++	ISCSI_SESSION_FREE,
++};
+ 
+ struct iscsi_cls_session {
+ 	struct list_head sess_list;		/* item in session_list */
+ 	struct list_head host_list;
+ 	struct iscsi_transport *transport;
++	spinlock_t lock;
+ 
+ 	/* recovery fields */
+ 	int recovery_tmo;
+@@ -190,6 +185,7 @@ struct iscsi_cls_session {
+ 
+ 	int target_id;
+ 
++	int state;
+ 	int sid;				/* session id */
+ 	void *dd_data;				/* LLD private data */
+ 	struct device dev;	/* sysfs transport/container device */
+@@ -214,6 +210,7 @@ struct iscsi_host {
+ /*
+  * session and connection functions that can be used by HW iSCSI LLDs
+  */
++extern int iscsi_session_chkready(struct iscsi_cls_session *session);
+ extern struct iscsi_cls_session *iscsi_alloc_session(struct Scsi_Host *shost,
+ 					struct iscsi_transport *transport);
+ extern int iscsi_add_session(struct iscsi_cls_session *session,

commit 103962380ec3d86e675fc735e3e2b2fc8decaae9
+Author: Mike Christie 
+Date:   Thu Dec 13 12:43:43 2007 -0600
+
+    [SCSI] iscsi class: bump version
+    
+    Update version.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 358559991f4f..ef0e74264880 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -33,7 +33,7 @@
+ #define ISCSI_SESSION_ATTRS 18
+ #define ISCSI_CONN_ATTRS 11
+ #define ISCSI_HOST_ATTRS 4
+-#define ISCSI_TRANSPORT_VERSION "2.0-724"
++#define ISCSI_TRANSPORT_VERSION "2.0-867"
+ 
+ struct iscsi_internal {
+ 	int daemon_pid;

commit df93ffcd748ce41e7b716c3056ae511939bb745e
+Author: Mike Christie 
+Date:   Thu Dec 13 12:43:42 2007 -0600
+
+    [SCSI] iscsi_tcp: fix setting of r2t
+    
+    If we negotiate for X r2ts we have to use only X r2ts. We cannot
+    round up (we could send less though). It is ok to fail if it
+    is not something the driver can handle, so this patch just does
+    that.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index edebdf27af9b..e5be5fd4ef58 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -1774,12 +1774,12 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
+ 		break;
+ 	case ISCSI_PARAM_MAX_R2T:
+ 		sscanf(buf, "%d", &value);
+-		if (session->max_r2t == roundup_pow_of_two(value))
++		if (value <= 0 || !is_power_of_2(value))
++			return -EINVAL;
++		if (session->max_r2t == value)
+ 			break;
+ 		iscsi_r2tpool_free(session);
+ 		iscsi_set_param(cls_conn, param, buf, buflen);
+-		if (session->max_r2t & (session->max_r2t - 1))
+-			session->max_r2t = roundup_pow_of_two(session->max_r2t);
+ 		if (iscsi_r2tpool_alloc(session))
+ 			return -ENOMEM;
+ 		break;

commit 4545a88fc1ae2c0cd1da6e35f3adcbc56ff27b07
+Author: Mike Christie 
+Date:   Thu Dec 13 12:43:40 2007 -0600
+
+    [SCSI] iscsi_tcp: hold lock during data rsp processing
+    
+    iscsi_data_rsp needs to hold the sesison lock when it calls
+    iscsi_update_cmdsn.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 84c4a5026bcb..edebdf27af9b 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -641,13 +641,11 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	}
+ 
+ 	/* fill-in new R2T associated with the task */
+-	spin_lock(&session->lock);
+ 	iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
+ 
+ 	if (!ctask->sc || session->state != ISCSI_STATE_LOGGED_IN) {
+ 		printk(KERN_INFO "iscsi_tcp: dropping R2T itt %d in "
+ 		       "recovery...\n", ctask->itt);
+-		spin_unlock(&session->lock);
+ 		return 0;
+ 	}
+ 
+@@ -660,7 +658,6 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 		printk(KERN_ERR "iscsi_tcp: invalid R2T with zero data len\n");
+ 		__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
+ 			    sizeof(void*));
+-		spin_unlock(&session->lock);
+ 		return ISCSI_ERR_DATALEN;
+ 	}
+ 
+@@ -676,7 +673,6 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 		       r2t->data_offset, scsi_bufflen(ctask->sc));
+ 		__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
+ 			    sizeof(void*));
+-		spin_unlock(&session->lock);
+ 		return ISCSI_ERR_DATALEN;
+ 	}
+ 
+@@ -690,8 +686,6 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	conn->r2t_pdus_cnt++;
+ 
+ 	iscsi_requeue_ctask(ctask);
+-	spin_unlock(&session->lock);
+-
+ 	return 0;
+ }
+ 
+@@ -764,7 +758,9 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 	switch(opcode) {
+ 	case ISCSI_OP_SCSI_DATA_IN:
+ 		ctask = session->cmds[itt];
++		spin_lock(&conn->session->lock);
+ 		rc = iscsi_data_rsp(conn, ctask);
++		spin_unlock(&conn->session->lock);
+ 		if (rc)
+ 			return rc;
+ 		if (tcp_conn->in.datalen) {
+@@ -806,9 +802,11 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 		ctask = session->cmds[itt];
+ 		if (ahslen)
+ 			rc = ISCSI_ERR_AHSLEN;
+-		else if (ctask->sc->sc_data_direction == DMA_TO_DEVICE)
++		else if (ctask->sc->sc_data_direction == DMA_TO_DEVICE) {
++			spin_lock(&session->lock);
+ 			rc = iscsi_r2t_rsp(conn, ctask);
+-		else
++			spin_unlock(&session->lock);
++		} else
+ 			rc = ISCSI_ERR_PROTO;
+ 		break;
+ 	case ISCSI_OP_LOGIN_RSP:

commit 66bbe0ce11c7ebe20cd1d4b5d271b2e124e223c5
+Author: Mike Christie 
+Date:   Thu Dec 13 12:43:39 2007 -0600
+
+    [SCSI] iscsi_tcp: enable sg chaining
+    
+    The previous patches converted iscsi_tcp to support sg chaining.
+    This patch sets the proper flags and sets sg_table size to
+    4096. This allows fs io to be capped at max_sectors, but passthrough
+    IO to be limited by some other part of the kernel.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 65df908019fd..84c4a5026bcb 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -1928,13 +1928,14 @@ static struct scsi_host_template iscsi_sht = {
+ 	.queuecommand           = iscsi_queuecommand,
+ 	.change_queue_depth	= iscsi_change_queue_depth,
+ 	.can_queue		= ISCSI_DEF_XMIT_CMDS_MAX - 1,
+-	.sg_tablesize		= ISCSI_SG_TABLESIZE,
++	.sg_tablesize		= 4096,
+ 	.max_sectors		= 0xFFFF,
+ 	.cmd_per_lun		= ISCSI_DEF_CMD_PER_LUN,
+ 	.eh_abort_handler       = iscsi_eh_abort,
+ 	.eh_device_reset_handler= iscsi_eh_device_reset,
+ 	.eh_host_reset_handler	= iscsi_eh_host_reset,
+ 	.use_clustering         = DISABLE_CLUSTERING,
++	.use_sg_chaining	= ENABLE_SG_CHAINING,
+ 	.slave_configure        = iscsi_tcp_slave_configure,
+ 	.proc_name		= "iscsi_tcp",
+ 	.this_id		= -1,
+@@ -1974,7 +1975,7 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 	.host_template		= &iscsi_sht,
+ 	.conndata_size		= sizeof(struct iscsi_conn),
+ 	.max_conn		= 1,
+-	.max_cmd_len		= ISCSI_TCP_MAX_CMD_LEN,
++	.max_cmd_len		= 16,
+ 	/* session management */
+ 	.create_session		= iscsi_tcp_session_create,
+ 	.destroy_session	= iscsi_tcp_session_destroy,
+diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
+index 893cd2e1701e..ed0b991d1e72 100644
+--- a/drivers/scsi/iscsi_tcp.h
++++ b/drivers/scsi/iscsi_tcp.h
+@@ -24,9 +24,6 @@
+ 
+ #include 
+ 
+-#define ISCSI_SG_TABLESIZE		SG_ALL
+-#define ISCSI_TCP_MAX_CMD_LEN		16
+-
+ struct crypto_hash;
+ struct socket;
+ struct iscsi_tcp_conn;

commit 4cd49ea1330c946db00a28819b766062716aa857
+Author: Mike Christie 
+Date:   Thu Dec 13 12:43:38 2007 -0600
+
+    [SCSI] libiscsi, iscsi class: set tmf to a safe default and export in sysfs
+    
+    Older tools will not be setting the tmf time outs since they
+    did not exists, so set them to a safe default.
+    
+    And export abort and lu reset timeout values in sysfs.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index f15df8d75fd8..6573223cb346 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1732,6 +1732,8 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
+ 	session->host = shost;
+ 	session->state = ISCSI_STATE_FREE;
+ 	session->fast_abort = 1;
++	session->lu_reset_timeout = 15;
++	session->abort_timeout = 10;
+ 	session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
+ 	session->cmds_max = cmds_max;
+ 	session->queued_cmdsn = session->cmdsn = initial_cmdsn;
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 36aa50e45ec7..358559991f4f 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -30,7 +30,7 @@
+ #include 
+ #include 
+ 
+-#define ISCSI_SESSION_ATTRS 16
++#define ISCSI_SESSION_ATTRS 18
+ #define ISCSI_CONN_ATTRS 11
+ #define ISCSI_HOST_ATTRS 4
+ #define ISCSI_TRANSPORT_VERSION "2.0-724"
+@@ -1242,7 +1242,9 @@ iscsi_session_attr(username, ISCSI_PARAM_USERNAME, 1);
+ iscsi_session_attr(username_in, ISCSI_PARAM_USERNAME_IN, 1);
+ iscsi_session_attr(password, ISCSI_PARAM_PASSWORD, 1);
+ iscsi_session_attr(password_in, ISCSI_PARAM_PASSWORD_IN, 1);
+-iscsi_session_attr(fast_abort, ISCSI_PARAM_FAST_ABORT, 1);
++iscsi_session_attr(fast_abort, ISCSI_PARAM_FAST_ABORT, 0);
++iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0);
++iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 0);
+ 
+ #define iscsi_priv_session_attr_show(field, format)			\
+ static ssize_t								\
+@@ -1467,6 +1469,8 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 	SETUP_SESSION_RD_ATTR(username, ISCSI_PASSWORD);
+ 	SETUP_SESSION_RD_ATTR(username_in, ISCSI_PASSWORD_IN);
+ 	SETUP_SESSION_RD_ATTR(fast_abort, ISCSI_FAST_ABORT);
++	SETUP_SESSION_RD_ATTR(abort_tmo, ISCSI_ABORT_TMO);
++	SETUP_SESSION_RD_ATTR(lu_reset_tmo,ISCSI_LU_RESET_TMO);
+ 	SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo);
+ 
+ 	BUG_ON(count > ISCSI_SESSION_ATTRS);

commit 7a53dc52a5f218bf306b875bf0610e851d5a8268
+Author: Mike Christie 
+Date:   Thu Dec 13 12:43:37 2007 -0600
+
+    [SCSI] iscsi_tcp: drop session when itt does not match any command
+    
+    A target should never send us a itt that does not match a running
+    task. If it does we do not really know what is coming down after the header,
+    unless we evaluate the hdr and do some guessing sometimes. However,
+    even if we know what is coming we probably do not have buffers for it or we
+    cannot respond (if it is a r2t for example), so just drop the session.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index ecba606e6521..65df908019fd 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -755,11 +755,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 	opcode = hdr->opcode & ISCSI_OPCODE_MASK;
+ 	/* verify itt (itt encoding: age+cid+itt) */
+ 	rc = iscsi_verify_itt(conn, hdr, &itt);
+-	if (rc == ISCSI_ERR_NO_SCSI_CMD) {
+-		/* XXX: what does this do? */
+-		tcp_conn->in.datalen = 0; /* force drop */
+-		return 0;
+-	} else if (rc)
++	if (rc)
+ 		return rc;
+ 
+ 	debug_tcp("opcode 0x%x ahslen %d datalen %d\n",

commit 1040c99d9fd9de2bf00efae6d91014f890575bdb
+Author: Mike Christie 
+Date:   Thu Dec 13 12:43:34 2007 -0600
+
+    [SCSI] libiscsi: Drop host lock in queuecommand
+    
+    The driver does not need the host lock in queuecommand so drop it.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 4461317e617f..b0bc8c3b0ecb 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1010,8 +1010,9 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 	sc->SCp.ptr = NULL;
+ 
+ 	host = sc->device->host;
+-	session = iscsi_hostdata(host->hostdata);
++	spin_unlock(host->host_lock);
+ 
++	session = iscsi_hostdata(host->hostdata);
+ 	spin_lock(&session->lock);
+ 
+ 	/*
+@@ -1077,11 +1078,13 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 	spin_unlock(&session->lock);
+ 
+ 	scsi_queue_work(host, &conn->xmitwork);
++	spin_lock(host->host_lock);
+ 	return 0;
+ 
+ reject:
+ 	spin_unlock(&session->lock);
+ 	debug_scsi("cmd 0x%x rejected (%d)\n", sc->cmnd[0], reason);
++	spin_lock(host->host_lock);
+ 	return SCSI_MLQUEUE_HOST_BUSY;
+ 
+ fault:
+@@ -1091,6 +1094,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 	sc->result = (DID_NO_CONNECT << 16);
+ 	scsi_set_resid(sc, scsi_bufflen(sc));
+ 	sc->scsi_done(sc);
++	spin_lock(host->host_lock);
+ 	return 0;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_queuecommand);

commit c1635cb786dbadd16fd6e6959dd3b41ae2f2831a
+Author: Mike Christie 
+Date:   Thu Dec 13 12:43:33 2007 -0600
+
+    [SCSI] libiscsi: clear conn->ctask when task is completed early
+    
+    If the current ctask is failed early, we legt the conn->ctask pointer
+    pointing to a invalid task. When the xmit thread would send data for
+    it, we would then oops.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index b17081bed128..4461317e617f 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -248,13 +248,16 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+  */
+ static void iscsi_complete_command(struct iscsi_cmd_task *ctask)
+ {
+-	struct iscsi_session *session = ctask->conn->session;
++	struct iscsi_conn *conn = ctask->conn;
++	struct iscsi_session *session = conn->session;
+ 	struct scsi_cmnd *sc = ctask->sc;
+ 
+ 	ctask->state = ISCSI_TASK_COMPLETED;
+ 	ctask->sc = NULL;
+ 	/* SCSI eh reuses commands to verify us */
+ 	sc->SCp.ptr = NULL;
++	if (conn->ctask == ctask)
++		conn->ctask = NULL;
+ 	list_del_init(&ctask->running);
+ 	__kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*));
+ 	sc->scsi_done(sc);

commit 9000bcd649b26aef4c35d2941f8a65f05bbb9ee1
+Author: Mike Christie 
+Date:   Thu Dec 13 12:43:32 2007 -0600
+
+    [SCSI] libiscsi: Do not fail commands immediately during logout
+    
+    If the target requests a logout, then we do not want
+    to fail commands to scsi-ml right away. This patch just
+    fails in pending commands for a requeue immediately, and then lets
+    iscsid handle running commands like normal recovery.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 96883614ba08..b17081bed128 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -917,7 +917,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 		conn->ctask = list_entry(conn->xmitqueue.next,
+ 					 struct iscsi_cmd_task, running);
+ 		if (conn->session->state == ISCSI_STATE_LOGGING_OUT) {
+-			fail_command(conn, conn->ctask, DID_NO_CONNECT << 16);
++			fail_command(conn, conn->ctask, DID_IMM_RETRY << 16);
+ 			continue;
+ 		}
+ 		if (iscsi_prep_scsi_cmd_pdu(conn->ctask)) {
+@@ -1024,21 +1024,19 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 		 * be entering our queuecommand while a block is starting
+ 		 * up because the block code is not locked)
+ 		 */
+-		if (session->state == ISCSI_STATE_IN_RECOVERY) {
++		switch (session->state) {
++		case ISCSI_STATE_IN_RECOVERY:
+ 			reason = FAILURE_SESSION_IN_RECOVERY;
+ 			goto reject;
+-		}
+-
+-		switch (session->state) {
++		case ISCSI_STATE_LOGGING_OUT:
++			reason = FAILURE_SESSION_LOGGING_OUT;
++			goto reject;
+ 		case ISCSI_STATE_RECOVERY_FAILED:
+ 			reason = FAILURE_SESSION_RECOVERY_TIMEOUT;
+ 			break;
+ 		case ISCSI_STATE_TERMINATE:
+ 			reason = FAILURE_SESSION_TERMINATE;
+ 			break;
+-		case ISCSI_STATE_LOGGING_OUT:
+-			reason = FAILURE_SESSION_LOGGING_OUT;
+-			break;
+ 		default:
+ 			reason = FAILURE_SESSION_FREED;
+ 		}

commit f6d5180c78780d63b0577edeb3ce41eeb3e93eea
+Author: Mike Christie 
+Date:   Thu Dec 13 12:43:30 2007 -0600
+
+    [SCSI] libiscsi: fix nop handling
+    
+    During root boot and shutdown the target could send us nops.
+    At this time iscsid cannot be running, so the target will drop
+    the session and the boot or shutdown will hang.
+    
+    To handle this and allow us to better control when to check the network
+    this patch moves the nop handling to the kernel.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index a2622f4bd858..265606422278 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -577,7 +577,9 @@ static struct iscsi_transport iscsi_iser_transport = {
+ 				  ISCSI_PERSISTENT_ADDRESS |
+ 				  ISCSI_TARGET_NAME | ISCSI_TPGT |
+ 				  ISCSI_USERNAME | ISCSI_PASSWORD |
+-				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN,
++				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
++				  ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
++				  ISCSI_PING_TMO | ISCSI_RECV_TMO,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS |
+ 				  ISCSI_HOST_NETDEV_NAME |
+ 				  ISCSI_HOST_INITIATOR_NAME,
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 90eae8e0d978..9b418522c9bf 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -2246,7 +2246,9 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 				  ISCSI_TARGET_NAME | ISCSI_TPGT |
+ 				  ISCSI_USERNAME | ISCSI_PASSWORD |
+ 				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+-				  ISCSI_FAST_ABORT,
++				  ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
++				  ISCSI_LU_RESET_TMO |
++				  ISCSI_PING_TMO | ISCSI_RECV_TMO,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+ 				  ISCSI_HOST_INITIATOR_NAME |
+ 				  ISCSI_HOST_NETDEV_NAME,
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 5205ef2c29b2..96883614ba08 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -313,11 +313,70 @@ void iscsi_free_mgmt_task(struct iscsi_conn *conn,
+ 	list_del_init(&mtask->running);
+ 	if (conn->login_mtask == mtask)
+ 		return;
++
++	if (conn->ping_mtask == mtask)
++		conn->ping_mtask = NULL;
+ 	__kfifo_put(conn->session->mgmtpool.queue,
+ 		    (void*)&mtask, sizeof(void*));
+ }
+ EXPORT_SYMBOL_GPL(iscsi_free_mgmt_task);
+ 
++static struct iscsi_mgmt_task *
++__iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
++		      char *data, uint32_t data_size)
++{
++	struct iscsi_session *session = conn->session;
++	struct iscsi_mgmt_task *mtask;
++
++	if (session->state == ISCSI_STATE_TERMINATE)
++		return NULL;
++
++	if (hdr->opcode == (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) ||
++	    hdr->opcode == (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE))
++		/*
++		 * Login and Text are sent serially, in
++		 * request-followed-by-response sequence.
++		 * Same mtask can be used. Same ITT must be used.
++		 * Note that login_mtask is preallocated at conn_create().
++		 */
++		mtask = conn->login_mtask;
++	else {
++		BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
++		BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
++
++		if (!__kfifo_get(session->mgmtpool.queue,
++				 (void*)&mtask, sizeof(void*)))
++			return NULL;
++	}
++
++	if (data_size) {
++		memcpy(mtask->data, data, data_size);
++		mtask->data_count = data_size;
++	} else
++		mtask->data_count = 0;
++
++	memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr));
++	INIT_LIST_HEAD(&mtask->running);
++	list_add_tail(&mtask->running, &conn->mgmtqueue);
++	return mtask;
++}
++
++int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
++			char *data, uint32_t data_size)
++{
++	struct iscsi_conn *conn = cls_conn->dd_data;
++	struct iscsi_session *session = conn->session;
++	int err = 0;
++
++	spin_lock_bh(&session->lock);
++	if (!__iscsi_conn_send_pdu(conn, hdr, data, data_size))
++		err = -EPERM;
++	spin_unlock_bh(&session->lock);
++	scsi_queue_work(session->host, &conn->xmitwork);
++	return err;
++}
++EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu);
++
+ /**
+  * iscsi_cmd_rsp - SCSI Command Response processing
+  * @conn: iscsi connection
+@@ -409,6 +468,39 @@ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 	wake_up(&conn->ehwait);
+ }
+ 
++static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
++{
++        struct iscsi_nopout hdr;
++	struct iscsi_mgmt_task *mtask;
++
++	if (!rhdr && conn->ping_mtask)
++		return;
++
++	memset(&hdr, 0, sizeof(struct iscsi_nopout));
++	hdr.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE;
++	hdr.flags = ISCSI_FLAG_CMD_FINAL;
++
++	if (rhdr) {
++		memcpy(hdr.lun, rhdr->lun, 8);
++		hdr.ttt = rhdr->ttt;
++		hdr.itt = RESERVED_ITT;
++	} else
++		hdr.ttt = RESERVED_ITT;
++
++	mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0);
++	if (!mtask) {
++		printk(KERN_ERR "Could not send nopout\n");
++		return;
++	}
++
++	/* only track our nops */
++	if (!rhdr) {
++		conn->ping_mtask = mtask;
++		conn->last_ping = jiffies;
++	}
++	scsi_queue_work(conn->session->host, &conn->xmitwork);
++}
++
+ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			       char *data, int datalen)
+ {
+@@ -453,6 +545,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	struct iscsi_mgmt_task *mtask;
+ 	uint32_t itt;
+ 
++	conn->last_recv = jiffies;
+ 	if (hdr->itt != RESERVED_ITT)
+ 		itt = get_itt(hdr->itt);
+ 	else
+@@ -520,14 +613,22 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			iscsi_free_mgmt_task(conn, mtask);
+ 			break;
+ 		case ISCSI_OP_NOOP_IN:
+-			if (hdr->ttt != cpu_to_be32(ISCSI_RESERVED_TAG) || datalen) {
++			if (hdr->ttt != cpu_to_be32(ISCSI_RESERVED_TAG) ||
++			    datalen) {
+ 				rc = ISCSI_ERR_PROTO;
+ 				break;
+ 			}
+ 			conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
+ 
+-			if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen))
+-				rc = ISCSI_ERR_CONN_FAILED;
++			if (conn->ping_mtask != mtask) {
++				/*
++				 * If this is not in response to one of our
++				 * nops then it must be from userspace.
++				 */
++				if (iscsi_recv_pdu(conn->cls_conn, hdr, data,
++						   datalen))
++					rc = ISCSI_ERR_CONN_FAILED;
++			}
+ 			iscsi_free_mgmt_task(conn, mtask);
+ 			break;
+ 		default:
+@@ -547,8 +648,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			if (hdr->ttt == cpu_to_be32(ISCSI_RESERVED_TAG))
+ 				break;
+ 
+-			if (iscsi_recv_pdu(conn->cls_conn, hdr, NULL, 0))
+-				rc = ISCSI_ERR_CONN_FAILED;
++			iscsi_send_nopout(conn, (struct iscsi_nopin*)hdr);
+ 			break;
+ 		case ISCSI_OP_REJECT:
+ 			rc = iscsi_handle_reject(conn, hdr, data, datalen);
+@@ -1003,62 +1103,6 @@ int iscsi_change_queue_depth(struct scsi_device *sdev, int depth)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_change_queue_depth);
+ 
+-static struct iscsi_mgmt_task *
+-__iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+-		      char *data, uint32_t data_size)
+-{
+-	struct iscsi_session *session = conn->session;
+-	struct iscsi_mgmt_task *mtask;
+-
+-	if (session->state == ISCSI_STATE_TERMINATE)
+-		return NULL;
+-
+-	if (hdr->opcode == (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) ||
+-	    hdr->opcode == (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE))
+-		/*
+-		 * Login and Text are sent serially, in
+-		 * request-followed-by-response sequence.
+-		 * Same mtask can be used. Same ITT must be used.
+-		 * Note that login_mtask is preallocated at conn_create().
+-		 */
+-		mtask = conn->login_mtask;
+-	else {
+-		BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
+-		BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
+-
+-		if (!__kfifo_get(session->mgmtpool.queue,
+-				 (void*)&mtask, sizeof(void*)))
+-			return NULL;
+-	}
+-
+-	if (data_size) {
+-		memcpy(mtask->data, data, data_size);
+-		mtask->data_count = data_size;
+-	} else
+-		mtask->data_count = 0;
+-
+-	memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr));
+-	INIT_LIST_HEAD(&mtask->running);
+-	list_add_tail(&mtask->running, &conn->mgmtqueue);
+-	return mtask;
+-}
+-
+-int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
+-			char *data, uint32_t data_size)
+-{
+-	struct iscsi_conn *conn = cls_conn->dd_data;
+-	struct iscsi_session *session = conn->session;
+-	int err = 0;
+-
+-	spin_lock_bh(&session->lock);
+-	if (!__iscsi_conn_send_pdu(conn, hdr, data, data_size))
+-		err = -EPERM;
+-	spin_unlock_bh(&session->lock);
+-	scsi_queue_work(session->host, &conn->xmitwork);
+-	return err;
+-}
+-EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu);
+-
+ void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session)
+ {
+ 	struct iscsi_session *session = class_to_transport_session(cls_session);
+@@ -1134,7 +1178,8 @@ static void iscsi_tmf_timedout(unsigned long data)
+ }
+ 
+ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn,
+-				   struct iscsi_tm *hdr, int age)
++				   struct iscsi_tm *hdr, int age,
++				   int timeout)
+ {
+ 	struct iscsi_session *session = conn->session;
+ 	struct iscsi_mgmt_task *mtask;
+@@ -1149,7 +1194,7 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn,
+ 		return -EPERM;
+ 	}
+ 	conn->tmfcmd_pdus_cnt++;
+-	conn->tmf_timer.expires = 30 * HZ + jiffies;
++	conn->tmf_timer.expires = timeout * HZ + jiffies;
+ 	conn->tmf_timer.function = iscsi_tmf_timedout;
+ 	conn->tmf_timer.data = (unsigned long)conn;
+ 	add_timer(&conn->tmf_timer);
+@@ -1233,6 +1278,106 @@ static void iscsi_start_tx(struct iscsi_conn *conn)
+ 	scsi_queue_work(conn->session->host, &conn->xmitwork);
+ }
+ 
++static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
++{
++	struct iscsi_cls_session *cls_session;
++	struct iscsi_session *session;
++	struct iscsi_conn *conn;
++	enum scsi_eh_timer_return rc = EH_NOT_HANDLED;
++
++	cls_session = starget_to_session(scsi_target(scmd->device));
++	session = class_to_transport_session(cls_session);
++
++	debug_scsi("scsi cmd %p timedout\n", scmd);
++
++	spin_lock(&session->lock);
++	if (session->state != ISCSI_STATE_LOGGED_IN) {
++		/*
++		 * We are probably in the middle of iscsi recovery so let
++		 * that complete and handle the error.
++		 */
++		rc = EH_RESET_TIMER;
++		goto done;
++	}
++
++	conn = session->leadconn;
++	if (!conn) {
++		/* In the middle of shuting down */
++		rc = EH_RESET_TIMER;
++		goto done;
++	}
++
++	if (!conn->recv_timeout && !conn->ping_timeout)
++		goto done;
++	/*
++	 * if the ping timedout then we are in the middle of cleaning up
++	 * and can let the iscsi eh handle it
++	 */
++	if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) +
++			    (conn->ping_timeout * HZ), jiffies))
++		rc = EH_RESET_TIMER;
++	/*
++	 * if we are about to check the transport then give the command
++	 * more time
++	 */
++	if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ),
++			   jiffies))
++		rc = EH_RESET_TIMER;
++	/* if in the middle of checking the transport then give us more time */
++	if (conn->ping_mtask)
++		rc = EH_RESET_TIMER;
++done:
++	spin_unlock(&session->lock);
++	debug_scsi("return %s\n", rc == EH_RESET_TIMER ? "timer reset" : "nh");
++	return rc;
++}
++
++static void iscsi_check_transport_timeouts(unsigned long data)
++{
++	struct iscsi_conn *conn = (struct iscsi_conn *)data;
++	struct iscsi_session *session = conn->session;
++	unsigned long timeout, next_timeout = 0, last_recv;
++
++	spin_lock(&session->lock);
++	if (session->state != ISCSI_STATE_LOGGED_IN)
++		goto done;
++
++	timeout = conn->recv_timeout;
++	if (!timeout)
++		goto done;
++
++	timeout *= HZ;
++	last_recv = conn->last_recv;
++	if (time_before_eq(last_recv + timeout + (conn->ping_timeout * HZ),
++			   jiffies)) {
++		printk(KERN_ERR "ping timeout of %d secs expired, "
++		       "last rx %lu, last ping %lu, now %lu\n",
++		       conn->ping_timeout, last_recv,
++		       conn->last_ping, jiffies);
++		spin_unlock(&session->lock);
++		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
++		return;
++	}
++
++	if (time_before_eq(last_recv + timeout, jiffies)) {
++		if (time_before_eq(conn->last_ping, last_recv)) {
++			/* send a ping to try to provoke some traffic */
++			debug_scsi("Sending nopout as ping on conn %p\n", conn);
++			iscsi_send_nopout(conn, NULL);
++		}
++		next_timeout = last_recv + timeout + (conn->ping_timeout * HZ);
++	} else {
++		next_timeout = last_recv + timeout;
++	}
++
++	if (next_timeout) {
++		debug_scsi("Setting next tmo %lu\n", next_timeout);
++		mod_timer(&conn->transport_timer, next_timeout);
++	}
++done:
++	spin_unlock(&session->lock);
++}
++
+ static void iscsi_prep_abort_task_pdu(struct iscsi_cmd_task *ctask,
+ 				      struct iscsi_tm *hdr)
+ {
+@@ -1304,7 +1449,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 	hdr = &conn->tmhdr;
+ 	iscsi_prep_abort_task_pdu(ctask, hdr);
+ 
+-	if (iscsi_exec_task_mgmt_fn(conn, hdr, age)) {
++	if (iscsi_exec_task_mgmt_fn(conn, hdr, age, session->abort_timeout)) {
+ 		rc = FAILED;
+ 		goto failed;
+ 	}
+@@ -1365,7 +1510,7 @@ static void iscsi_prep_lun_reset_pdu(struct scsi_cmnd *sc, struct iscsi_tm *hdr)
+ 	hdr->flags = ISCSI_TM_FUNC_LOGICAL_UNIT_RESET & ISCSI_FLAG_TM_FUNC_MASK;
+ 	hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+ 	int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
+-	hdr->rtt = ISCSI_RESERVED_TAG;
++	hdr->rtt = RESERVED_ITT;
+ }
+ 
+ int iscsi_eh_device_reset(struct scsi_cmnd *sc)
+@@ -1396,7 +1541,8 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc)
+ 	hdr = &conn->tmhdr;
+ 	iscsi_prep_lun_reset_pdu(sc, hdr);
+ 
+-	if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age)) {
++	if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age,
++				    session->lu_reset_timeout)) {
+ 		rc = FAILED;
+ 		goto unlock;
+ 	}
+@@ -1572,12 +1718,14 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
+ 	shost->max_cmd_len = iscsit->max_cmd_len;
+ 	shost->transportt = scsit;
+ 	shost->transportt->create_work_queue = 1;
++	shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out;
+ 	*hostno = shost->host_no;
+ 
+ 	session = iscsi_hostdata(shost->hostdata);
+ 	memset(session, 0, sizeof(struct iscsi_session));
+ 	session->host = shost;
+ 	session->state = ISCSI_STATE_FREE;
++	session->fast_abort = 1;
+ 	session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
+ 	session->cmds_max = cmds_max;
+ 	session->queued_cmdsn = session->cmdsn = initial_cmdsn;
+@@ -1708,6 +1856,11 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ 	conn->id = conn_idx;
+ 	conn->exp_statsn = 0;
+ 	conn->tmf_state = TMF_INITIAL;
++
++	init_timer(&conn->transport_timer);
++	conn->transport_timer.data = (unsigned long)conn;
++	conn->transport_timer.function = iscsi_check_transport_timeouts;
++
+ 	INIT_LIST_HEAD(&conn->run_list);
+ 	INIT_LIST_HEAD(&conn->mgmt_run_list);
+ 	INIT_LIST_HEAD(&conn->mgmtqueue);
+@@ -1757,6 +1910,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
+ 	struct iscsi_session *session = conn->session;
+ 	unsigned long flags;
+ 
++	del_timer_sync(&conn->transport_timer);
++
+ 	spin_lock_bh(&session->lock);
+ 	conn->c_stage = ISCSI_CONN_CLEANUP_WAIT;
+ 	if (session->leadconn == conn) {
+@@ -1823,11 +1978,29 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
+ 		return -EINVAL;
+ 	}
+ 
++	if (conn->ping_timeout && !conn->recv_timeout) {
++		printk(KERN_ERR "iscsi: invalid recv timeout of zero "
++		      "Using 5 seconds\n.");
++		conn->recv_timeout = 5;
++	}
++
++	if (conn->recv_timeout && !conn->ping_timeout) {
++		printk(KERN_ERR "iscsi: invalid ping timeout of zero "
++		      "Using 5 seconds.\n");
++		conn->ping_timeout = 5;
++	}
++
+ 	spin_lock_bh(&session->lock);
+ 	conn->c_stage = ISCSI_CONN_STARTED;
+ 	session->state = ISCSI_STATE_LOGGED_IN;
+ 	session->queued_cmdsn = session->cmdsn;
+ 
++	conn->last_recv = jiffies;
++	conn->last_ping = jiffies;
++	if (conn->recv_timeout && conn->ping_timeout)
++		mod_timer(&conn->transport_timer,
++			  jiffies + (conn->recv_timeout * HZ));
++
+ 	switch(conn->stop_stage) {
+ 	case STOP_CONN_RECOVER:
+ 		/*
+@@ -1879,6 +2052,8 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ {
+ 	int old_stop_stage;
+ 
++	del_timer_sync(&conn->transport_timer);
++
+ 	mutex_lock(&session->eh_mutex);
+ 	spin_lock_bh(&session->lock);
+ 	if (conn->stop_stage == STOP_CONN_TERM) {
+@@ -1993,6 +2168,18 @@ int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
+ 	case ISCSI_PARAM_FAST_ABORT:
+ 		sscanf(buf, "%d", &session->fast_abort);
+ 		break;
++	case ISCSI_PARAM_ABORT_TMO:
++		sscanf(buf, "%d", &session->abort_timeout);
++		break;
++	case ISCSI_PARAM_LU_RESET_TMO:
++		sscanf(buf, "%d", &session->lu_reset_timeout);
++		break;
++	case ISCSI_PARAM_PING_TMO:
++		sscanf(buf, "%d", &conn->ping_timeout);
++		break;
++	case ISCSI_PARAM_RECV_TMO:
++		sscanf(buf, "%d", &conn->recv_timeout);
++		break;
+ 	case ISCSI_PARAM_MAX_RECV_DLENGTH:
+ 		sscanf(buf, "%d", &conn->max_recv_dlength);
+ 		break;
+@@ -2110,6 +2297,12 @@ int iscsi_session_get_param(struct iscsi_cls_session *cls_session,
+ 	case ISCSI_PARAM_FAST_ABORT:
+ 		len = sprintf(buf, "%d\n", session->fast_abort);
+ 		break;
++	case ISCSI_PARAM_ABORT_TMO:
++		len = sprintf(buf, "%d\n", session->abort_timeout);
++		break;
++	case ISCSI_PARAM_LU_RESET_TMO:
++		len = sprintf(buf, "%d\n", session->lu_reset_timeout);
++		break;
+ 	case ISCSI_PARAM_INITIAL_R2T_EN:
+ 		len = sprintf(buf, "%d\n", session->initial_r2t_en);
+ 		break;
+@@ -2167,6 +2360,12 @@ int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ 	int len;
+ 
+ 	switch(param) {
++	case ISCSI_PARAM_PING_TMO:
++		len = sprintf(buf, "%u\n", conn->ping_timeout);
++		break;
++	case ISCSI_PARAM_RECV_TMO:
++		len = sprintf(buf, "%u\n", conn->recv_timeout);
++		break;
+ 	case ISCSI_PARAM_MAX_RECV_DLENGTH:
+ 		len = sprintf(buf, "%u\n", conn->max_recv_dlength);
+ 		break;
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index b82139dc4830..36aa50e45ec7 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -1202,6 +1202,8 @@ iscsi_conn_attr(port, ISCSI_PARAM_CONN_PORT);
+ iscsi_conn_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN);
+ iscsi_conn_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS);
+ iscsi_conn_attr(address, ISCSI_PARAM_CONN_ADDRESS);
++iscsi_conn_attr(ping_tmo, ISCSI_PARAM_PING_TMO);
++iscsi_conn_attr(recv_tmo, ISCSI_PARAM_RECV_TMO);
+ 
+ #define iscsi_cdev_to_session(_cdev) \
+ 	iscsi_dev_to_session(_cdev->dev)
+@@ -1437,6 +1439,8 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 	SETUP_CONN_RD_ATTR(exp_statsn, ISCSI_EXP_STATSN);
+ 	SETUP_CONN_RD_ATTR(persistent_address, ISCSI_PERSISTENT_ADDRESS);
+ 	SETUP_CONN_RD_ATTR(persistent_port, ISCSI_PERSISTENT_PORT);
++	SETUP_CONN_RD_ATTR(ping_tmo, ISCSI_PING_TMO);
++	SETUP_CONN_RD_ATTR(recv_tmo, ISCSI_RECV_TMO);
+ 
+ 	BUG_ON(count > ISCSI_CONN_ATTRS);
+ 	priv->conn_attrs[count] = NULL;
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index 8a4426df6c3a..e19e58423166 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -244,6 +244,12 @@ enum iscsi_param {
+ 	ISCSI_PARAM_PASSWORD_IN,
+ 
+ 	ISCSI_PARAM_FAST_ABORT,
++	ISCSI_PARAM_ABORT_TMO,
++	ISCSI_PARAM_LU_RESET_TMO,
++	ISCSI_PARAM_HOST_RESET_TMO,
++
++	ISCSI_PARAM_PING_TMO,
++	ISCSI_PARAM_RECV_TMO,
+ 	/* must always be last */
+ 	ISCSI_PARAM_MAX,
+ };
+@@ -275,6 +281,11 @@ enum iscsi_param {
+ #define ISCSI_PASSWORD			(1 << ISCSI_PARAM_PASSWORD)
+ #define ISCSI_PASSWORD_IN		(1 << ISCSI_PARAM_PASSWORD_IN)
+ #define ISCSI_FAST_ABORT		(1 << ISCSI_PARAM_FAST_ABORT)
++#define ISCSI_ABORT_TMO			(1 << ISCSI_PARAM_ABORT_TMO)
++#define ISCSI_LU_RESET_TMO		(1 << ISCSI_PARAM_LU_RESET_TMO)
++#define ISCSI_HOST_RESET_TMO		(1 << ISCSI_PARAM_HOST_RESET_TMO)
++#define ISCSI_PING_TMO			(1 << ISCSI_PARAM_PING_TMO)
++#define ISCSI_RECV_TMO			(1 << ISCSI_PARAM_RECV_TMO)
+ 
+ /* iSCSI HBA params */
+ enum iscsi_host_param {
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index d68f74523f2e..889f51fabab9 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -148,6 +148,12 @@ struct iscsi_conn {
+ 	 * conn_stop() flag: stop to recover, stop to terminate
+ 	 */
+         int			stop_stage;
++	struct timer_list	transport_timer;
++	unsigned long		last_recv;
++	unsigned long		last_ping;
++	int			ping_timeout;
++	int			recv_timeout;
++	struct iscsi_mgmt_task	*ping_mtask;
+ 
+ 	/* iSCSI connection-wide sequencing */
+ 	uint32_t		exp_statsn;
+@@ -238,6 +244,8 @@ struct iscsi_session {
+ 	uint32_t		queued_cmdsn;
+ 
+ 	/* configuration */
++	int			abort_timeout;
++	int			lu_reset_timeout;
+ 	int			initial_r2t_en;
+ 	unsigned		max_r2t;
+ 	int			imm_data_en;

commit 2697478903d0ad8bdbf868b1346ae4b891662bb1
+Author: Mike Christie 
+Date:   Thu Dec 13 12:43:29 2007 -0600
+
+    [SCSI] libiscsi: fix shutdown
+    
+    We were using the device delete sysfs file to remove each device
+    then logout. Now in 2.6.21 this will not work because
+    the sysfs delete file returns immediately and does not wait for
+    the device removal to complete. This causes a hang if a cache sync
+    is needed during shutdown. Before .21, that approach had other
+    problems, so this patch fixes the shutdown code so that we remove the target
+    and unbind the session before logging out and shut down the session
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 441e351b4456..5205ef2c29b2 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1662,7 +1662,7 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+ 	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+ 	struct module *owner = cls_session->transport->owner;
+ 
+-	iscsi_unblock_session(cls_session);
++	iscsi_remove_session(cls_session);
+ 	scsi_remove_host(shost);
+ 
+ 	iscsi_pool_free(&session->mgmtpool);
+@@ -1677,7 +1677,7 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+ 	kfree(session->hwaddress);
+ 	kfree(session->initiatorname);
+ 
+-	iscsi_destroy_session(cls_session);
++	iscsi_free_session(cls_session);
+ 	scsi_host_put(shost);
+ 	module_put(owner);
+ }
+diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
+index d692c713416a..cbe0a17ced5f 100644
+--- a/drivers/scsi/qla4xxx/ql4_init.c
++++ b/drivers/scsi/qla4xxx/ql4_init.c
+@@ -5,6 +5,7 @@
+  * See LICENSE.qla4xxx for copyright and licensing details.
+  */
+ 
++#include 
+ #include "ql4_def.h"
+ #include "ql4_glbl.h"
+ #include "ql4_dbg.h"
+@@ -1305,7 +1306,8 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha,
+ 		atomic_set(&ddb_entry->relogin_timer, 0);
+ 		clear_bit(DF_RELOGIN, &ddb_entry->flags);
+ 		clear_bit(DF_NO_RELOGIN, &ddb_entry->flags);
+-		iscsi_if_create_session_done(ddb_entry->conn);
++		iscsi_session_event(ddb_entry->sess,
++				    ISCSI_KEVENT_CREATE_SESSION);
+ 		/*
+ 		 * Change the lun state to READY in case the lun TIMEOUT before
+ 		 * the device came back.
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index 89460d27c689..f55b9f7d9396 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -298,8 +298,7 @@ void qla4xxx_destroy_sess(struct ddb_entry *ddb_entry)
+ 		return;
+ 
+ 	if (ddb_entry->conn) {
+-		iscsi_if_destroy_session_done(ddb_entry->conn);
+-		iscsi_destroy_conn(ddb_entry->conn);
++		atomic_set(&ddb_entry->state, DDB_STATE_DEAD);
+ 		iscsi_remove_session(ddb_entry->sess);
+ 	}
+ 	iscsi_free_session(ddb_entry->sess);
+@@ -309,6 +308,7 @@ int qla4xxx_add_sess(struct ddb_entry *ddb_entry)
+ {
+ 	int err;
+ 
++	ddb_entry->sess->recovery_tmo = ddb_entry->ha->port_down_retry_count;
+ 	err = iscsi_add_session(ddb_entry->sess, ddb_entry->fw_ddb_index);
+ 	if (err) {
+ 		DEBUG2(printk(KERN_ERR "Could not add session.\n"));
+@@ -321,9 +321,6 @@ int qla4xxx_add_sess(struct ddb_entry *ddb_entry)
+ 		DEBUG2(printk(KERN_ERR "Could not add connection.\n"));
+ 		return -ENOMEM;
+ 	}
+-
+-	ddb_entry->sess->recovery_tmo = ddb_entry->ha->port_down_retry_count;
+-	iscsi_if_create_session_done(ddb_entry->conn);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 9cc2cc8e87b3..b82139dc4830 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -116,6 +116,8 @@ static struct attribute_group iscsi_transport_group = {
+ 	.attrs = iscsi_transport_attrs,
+ };
+ 
++
++
+ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+ 			    struct class_device *cdev)
+ {
+@@ -125,13 +127,30 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+ 	memset(ihost, 0, sizeof(*ihost));
+ 	INIT_LIST_HEAD(&ihost->sessions);
+ 	mutex_init(&ihost->mutex);
++
++	snprintf(ihost->unbind_workq_name, KOBJ_NAME_LEN, "iscsi_unbind_%d",
++		shost->host_no);
++	ihost->unbind_workq = create_singlethread_workqueue(
++						ihost->unbind_workq_name);
++	if (!ihost->unbind_workq)
++		return -ENOMEM;
++	return 0;
++}
++
++static int iscsi_remove_host(struct transport_container *tc, struct device *dev,
++			     struct class_device *cdev)
++{
++	struct Scsi_Host *shost = dev_to_shost(dev);
++	struct iscsi_host *ihost = shost->shost_data;
++
++	destroy_workqueue(ihost->unbind_workq);
+ 	return 0;
+ }
+ 
+ static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
+ 			       "iscsi_host",
+ 			       iscsi_setup_host,
+-			       NULL,
++			       iscsi_remove_host,
+ 			       NULL);
+ 
+ static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
+@@ -266,6 +285,35 @@ void iscsi_block_session(struct iscsi_cls_session *session)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_block_session);
+ 
++static void __iscsi_unbind_session(struct work_struct *work)
++{
++	struct iscsi_cls_session *session =
++			container_of(work, struct iscsi_cls_session,
++				     unbind_work);
++	struct Scsi_Host *shost = iscsi_session_to_shost(session);
++	struct iscsi_host *ihost = shost->shost_data;
++
++	/* Prevent new scans and make sure scanning is not in progress */
++	mutex_lock(&ihost->mutex);
++	if (list_empty(&session->host_list)) {
++		mutex_unlock(&ihost->mutex);
++		return;
++	}
++	list_del_init(&session->host_list);
++	mutex_unlock(&ihost->mutex);
++
++	scsi_remove_target(&session->dev);
++	iscsi_session_event(session, ISCSI_KEVENT_UNBIND_SESSION);
++}
++
++static int iscsi_unbind_session(struct iscsi_cls_session *session)
++{
++	struct Scsi_Host *shost = iscsi_session_to_shost(session);
++	struct iscsi_host *ihost = shost->shost_data;
++
++	return queue_work(ihost->unbind_workq, &session->unbind_work);
++}
++
+ struct iscsi_cls_session *
+ iscsi_alloc_session(struct Scsi_Host *shost,
+ 		    struct iscsi_transport *transport)
+@@ -282,6 +330,7 @@ iscsi_alloc_session(struct Scsi_Host *shost,
+ 	INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout);
+ 	INIT_LIST_HEAD(&session->host_list);
+ 	INIT_LIST_HEAD(&session->sess_list);
++	INIT_WORK(&session->unbind_work, __iscsi_unbind_session);
+ 
+ 	/* this is released in the dev's release function */
+ 	scsi_host_get(shost);
+@@ -298,6 +347,7 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
+ {
+ 	struct Scsi_Host *shost = iscsi_session_to_shost(session);
+ 	struct iscsi_host *ihost;
++	unsigned long flags;
+ 	int err;
+ 
+ 	ihost = shost->shost_data;
+@@ -314,9 +364,15 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
+ 	}
+ 	transport_register_device(&session->dev);
+ 
++	spin_lock_irqsave(&sesslock, flags);
++	list_add(&session->sess_list, &sesslist);
++	spin_unlock_irqrestore(&sesslock, flags);
++
+ 	mutex_lock(&ihost->mutex);
+ 	list_add(&session->host_list, &ihost->sessions);
+ 	mutex_unlock(&ihost->mutex);
++
++	iscsi_session_event(session, ISCSI_KEVENT_CREATE_SESSION);
+ 	return 0;
+ 
+ release_host:
+@@ -352,19 +408,58 @@ iscsi_create_session(struct Scsi_Host *shost,
+ }
+ EXPORT_SYMBOL_GPL(iscsi_create_session);
+ 
++static void iscsi_conn_release(struct device *dev)
++{
++	struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev);
++	struct device *parent = conn->dev.parent;
++
++	kfree(conn);
++	put_device(parent);
++}
++
++static int iscsi_is_conn_dev(const struct device *dev)
++{
++	return dev->release == iscsi_conn_release;
++}
++
++static int iscsi_iter_destroy_conn_fn(struct device *dev, void *data)
++{
++	if (!iscsi_is_conn_dev(dev))
++		return 0;
++	return iscsi_destroy_conn(iscsi_dev_to_conn(dev));
++}
++
+ void iscsi_remove_session(struct iscsi_cls_session *session)
+ {
+ 	struct Scsi_Host *shost = iscsi_session_to_shost(session);
+ 	struct iscsi_host *ihost = shost->shost_data;
++	unsigned long flags;
++	int err;
++
++	spin_lock_irqsave(&sesslock, flags);
++	list_del(&session->sess_list);
++	spin_unlock_irqrestore(&sesslock, flags);
+ 
++	/*
++	 * If we are blocked let commands flow again. The lld or iscsi
++	 * layer should set up the queuecommand to fail commands.
++	 */
++	iscsi_unblock_session(session);
++	iscsi_unbind_session(session);
++	/*
++	 * If the session dropped while removing devices then we need to make
++	 * sure it is not blocked
++	 */
+ 	if (!cancel_delayed_work(&session->recovery_work))
+ 		flush_workqueue(iscsi_eh_timer_workq);
++	flush_workqueue(ihost->unbind_workq);
+ 
+-	mutex_lock(&ihost->mutex);
+-	list_del(&session->host_list);
+-	mutex_unlock(&ihost->mutex);
+-
+-	scsi_remove_target(&session->dev);
++	/* hw iscsi may not have removed all connections from session */
++	err = device_for_each_child(&session->dev, NULL,
++				    iscsi_iter_destroy_conn_fn);
++	if (err)
++		dev_printk(KERN_ERR, &session->dev, "iscsi: Could not delete "
++			   "all connections for session. Error %d.\n", err);
+ 
+ 	transport_unregister_device(&session->dev);
+ 	device_del(&session->dev);
+@@ -373,9 +468,9 @@ EXPORT_SYMBOL_GPL(iscsi_remove_session);
+ 
+ void iscsi_free_session(struct iscsi_cls_session *session)
+ {
++	iscsi_session_event(session, ISCSI_KEVENT_DESTROY_SESSION);
+ 	put_device(&session->dev);
+ }
+-
+ EXPORT_SYMBOL_GPL(iscsi_free_session);
+ 
+ /**
+@@ -393,20 +488,6 @@ int iscsi_destroy_session(struct iscsi_cls_session *session)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_destroy_session);
+ 
+-static void iscsi_conn_release(struct device *dev)
+-{
+-	struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev);
+-	struct device *parent = conn->dev.parent;
+-
+-	kfree(conn);
+-	put_device(parent);
+-}
+-
+-static int iscsi_is_conn_dev(const struct device *dev)
+-{
+-	return dev->release == iscsi_conn_release;
+-}
+-
+ /**
+  * iscsi_create_conn - create iscsi class connection
+  * @session: iscsi cls session
+@@ -426,6 +507,7 @@ iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid)
+ {
+ 	struct iscsi_transport *transport = session->transport;
+ 	struct iscsi_cls_conn *conn;
++	unsigned long flags;
+ 	int err;
+ 
+ 	conn = kzalloc(sizeof(*conn) + transport->conndata_size, GFP_KERNEL);
+@@ -454,6 +536,11 @@ iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid)
+ 		goto release_parent_ref;
+ 	}
+ 	transport_register_device(&conn->dev);
++
++	spin_lock_irqsave(&connlock, flags);
++	list_add(&conn->conn_list, &connlist);
++	conn->active = 1;
++	spin_unlock_irqrestore(&connlock, flags);
+ 	return conn;
+ 
+ release_parent_ref:
+@@ -469,15 +556,21 @@ EXPORT_SYMBOL_GPL(iscsi_create_conn);
+  * iscsi_destroy_conn - destroy iscsi class connection
+  * @conn: iscsi cls session
+  *
+- * This can be called from an LLD or iscsi_transport.
++ * This can be called from a LLD or iscsi_transport.
+  */
+ int iscsi_destroy_conn(struct iscsi_cls_conn *conn)
+ {
++	unsigned long flags;
++
++	spin_lock_irqsave(&connlock, flags);
++	conn->active = 0;
++	list_del(&conn->conn_list);
++	spin_unlock_irqrestore(&connlock, flags);
++
+ 	transport_unregister_device(&conn->dev);
+ 	device_unregister(&conn->dev);
+ 	return 0;
+ }
+-
+ EXPORT_SYMBOL_GPL(iscsi_destroy_conn);
+ 
+ /*
+@@ -687,132 +780,74 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
+ }
+ 
+ /**
+- * iscsi_if_destroy_session_done - send session destr. completion event
+- * @conn: last connection for session
+- *
+- * This is called by HW iscsi LLDs to notify userpsace that its HW has
+- * removed a session.
++ * iscsi_session_event - send session destr. completion event
++ * @session: iscsi class session
++ * @event: type of event
+  */
+-int iscsi_if_destroy_session_done(struct iscsi_cls_conn *conn)
++int iscsi_session_event(struct iscsi_cls_session *session,
++			enum iscsi_uevent_e event)
+ {
+ 	struct iscsi_internal *priv;
+-	struct iscsi_cls_session *session;
+ 	struct Scsi_Host *shost;
+ 	struct iscsi_uevent *ev;
+ 	struct sk_buff  *skb;
+ 	struct nlmsghdr *nlh;
+-	unsigned long flags;
+ 	int rc, len = NLMSG_SPACE(sizeof(*ev));
+ 
+-	priv = iscsi_if_transport_lookup(conn->transport);
++	priv = iscsi_if_transport_lookup(session->transport);
+ 	if (!priv)
+ 		return -EINVAL;
+-
+-	session = iscsi_dev_to_session(conn->dev.parent);
+ 	shost = iscsi_session_to_shost(session);
+ 
+ 	skb = alloc_skb(len, GFP_KERNEL);
+ 	if (!skb) {
+-		dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
+-			  "session creation event\n");
++		dev_printk(KERN_ERR, &session->dev, "Cannot notify userspace "
++			  "of session event %u\n", event);
+ 		return -ENOMEM;
+ 	}
+ 
+ 	nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
+ 	ev = NLMSG_DATA(nlh);
+-	ev->transport_handle = iscsi_handle(conn->transport);
+-	ev->type = ISCSI_KEVENT_DESTROY_SESSION;
+-	ev->r.d_session.host_no = shost->host_no;
+-	ev->r.d_session.sid = session->sid;
+-
+-	/*
+-	 * this will occur if the daemon is not up, so we just warn
+-	 * the user and when the daemon is restarted it will handle it
+-	 */
+-	rc = iscsi_broadcast_skb(skb, GFP_KERNEL);
+-	if (rc < 0)
+-		dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
+-			  "session destruction event. Check iscsi daemon\n");
+-
+-	spin_lock_irqsave(&sesslock, flags);
+-	list_del(&session->sess_list);
+-	spin_unlock_irqrestore(&sesslock, flags);
+-
+-	spin_lock_irqsave(&connlock, flags);
+-	conn->active = 0;
+-	list_del(&conn->conn_list);
+-	spin_unlock_irqrestore(&connlock, flags);
+-
+-	return rc;
+-}
+-EXPORT_SYMBOL_GPL(iscsi_if_destroy_session_done);
+-
+-/**
+- * iscsi_if_create_session_done - send session creation completion event
+- * @conn: leading connection for session
+- *
+- * This is called by HW iscsi LLDs to notify userpsace that its HW has
+- * created a session or a existing session is back in the logged in state.
+- */
+-int iscsi_if_create_session_done(struct iscsi_cls_conn *conn)
+-{
+-	struct iscsi_internal *priv;
+-	struct iscsi_cls_session *session;
+-	struct Scsi_Host *shost;
+-	struct iscsi_uevent *ev;
+-	struct sk_buff  *skb;
+-	struct nlmsghdr *nlh;
+-	unsigned long flags;
+-	int rc, len = NLMSG_SPACE(sizeof(*ev));
++	ev->transport_handle = iscsi_handle(session->transport);
+ 
+-	priv = iscsi_if_transport_lookup(conn->transport);
+-	if (!priv)
++	ev->type = event;
++	switch (event) {
++	case ISCSI_KEVENT_DESTROY_SESSION:
++		ev->r.d_session.host_no = shost->host_no;
++		ev->r.d_session.sid = session->sid;
++		break;
++	case ISCSI_KEVENT_CREATE_SESSION:
++		ev->r.c_session_ret.host_no = shost->host_no;
++		ev->r.c_session_ret.sid = session->sid;
++		break;
++	case ISCSI_KEVENT_UNBIND_SESSION:
++		ev->r.unbind_session.host_no = shost->host_no;
++		ev->r.unbind_session.sid = session->sid;
++		break;
++	default:
++		dev_printk(KERN_ERR, &session->dev, "Invalid event %u.\n",
++			   event);
++		kfree_skb(skb);
+ 		return -EINVAL;
+-
+-	session = iscsi_dev_to_session(conn->dev.parent);
+-	shost = iscsi_session_to_shost(session);
+-
+-	skb = alloc_skb(len, GFP_KERNEL);
+-	if (!skb) {
+-		dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
+-			  "session creation event\n");
+-		return -ENOMEM;
+ 	}
+ 
+-	nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
+-	ev = NLMSG_DATA(nlh);
+-	ev->transport_handle = iscsi_handle(conn->transport);
+-	ev->type = ISCSI_UEVENT_CREATE_SESSION;
+-	ev->r.c_session_ret.host_no = shost->host_no;
+-	ev->r.c_session_ret.sid = session->sid;
+-
+ 	/*
+ 	 * this will occur if the daemon is not up, so we just warn
+ 	 * the user and when the daemon is restarted it will handle it
+ 	 */
+ 	rc = iscsi_broadcast_skb(skb, GFP_KERNEL);
+ 	if (rc < 0)
+-		dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
+-			  "session creation event. Check iscsi daemon\n");
+-
+-	spin_lock_irqsave(&sesslock, flags);
+-	list_add(&session->sess_list, &sesslist);
+-	spin_unlock_irqrestore(&sesslock, flags);
+-
+-	spin_lock_irqsave(&connlock, flags);
+-	list_add(&conn->conn_list, &connlist);
+-	conn->active = 1;
+-	spin_unlock_irqrestore(&connlock, flags);
++		dev_printk(KERN_ERR, &session->dev, "Cannot notify userspace "
++			  "of session event %u. Check iscsi daemon\n", event);
+ 	return rc;
+ }
+-EXPORT_SYMBOL_GPL(iscsi_if_create_session_done);
++EXPORT_SYMBOL_GPL(iscsi_session_event);
+ 
+ static int
+ iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
+ {
+ 	struct iscsi_transport *transport = priv->iscsi_transport;
+ 	struct iscsi_cls_session *session;
+-	unsigned long flags;
+ 	uint32_t hostno;
+ 
+ 	session = transport->create_session(transport, &priv->t,
+@@ -823,10 +858,6 @@ iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
+ 	if (!session)
+ 		return -ENOMEM;
+ 
+-	spin_lock_irqsave(&sesslock, flags);
+-	list_add(&session->sess_list, &sesslist);
+-	spin_unlock_irqrestore(&sesslock, flags);
+-
+ 	ev->r.c_session_ret.host_no = hostno;
+ 	ev->r.c_session_ret.sid = session->sid;
+ 	return 0;
+@@ -837,7 +868,6 @@ iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+ {
+ 	struct iscsi_cls_conn *conn;
+ 	struct iscsi_cls_session *session;
+-	unsigned long flags;
+ 
+ 	session = iscsi_session_lookup(ev->u.c_conn.sid);
+ 	if (!session) {
+@@ -856,28 +886,17 @@ iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+ 
+ 	ev->r.c_conn_ret.sid = session->sid;
+ 	ev->r.c_conn_ret.cid = conn->cid;
+-
+-	spin_lock_irqsave(&connlock, flags);
+-	list_add(&conn->conn_list, &connlist);
+-	conn->active = 1;
+-	spin_unlock_irqrestore(&connlock, flags);
+-
+ 	return 0;
+ }
+ 
+ static int
+ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+ {
+-	unsigned long flags;
+ 	struct iscsi_cls_conn *conn;
+ 
+ 	conn = iscsi_conn_lookup(ev->u.d_conn.sid, ev->u.d_conn.cid);
+ 	if (!conn)
+ 		return -EINVAL;
+-	spin_lock_irqsave(&connlock, flags);
+-	conn->active = 0;
+-	list_del(&conn->conn_list);
+-	spin_unlock_irqrestore(&connlock, flags);
+ 
+ 	if (transport->destroy_conn)
+ 		transport->destroy_conn(conn);
+@@ -1004,7 +1023,6 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 	struct iscsi_internal *priv;
+ 	struct iscsi_cls_session *session;
+ 	struct iscsi_cls_conn *conn;
+-	unsigned long flags;
+ 
+ 	priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle));
+ 	if (!priv)
+@@ -1022,13 +1040,16 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 		break;
+ 	case ISCSI_UEVENT_DESTROY_SESSION:
+ 		session = iscsi_session_lookup(ev->u.d_session.sid);
+-		if (session) {
+-			spin_lock_irqsave(&sesslock, flags);
+-			list_del(&session->sess_list);
+-			spin_unlock_irqrestore(&sesslock, flags);
+-
++		if (session)
+ 			transport->destroy_session(session);
+-		} else
++		else
++			err = -EINVAL;
++		break;
++	case ISCSI_UEVENT_UNBIND_SESSION:
++		session = iscsi_session_lookup(ev->u.d_session.sid);
++		if (session)
++			iscsi_unbind_session(session);
++		else
+ 			err = -EINVAL;
+ 		break;
+ 	case ISCSI_UEVENT_CREATE_CONN:
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index bff0b1f7857b..8a4426df6c3a 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -49,12 +49,15 @@ enum iscsi_uevent_e {
+ 
+ 	ISCSI_UEVENT_TGT_DSCVR		= UEVENT_BASE + 15,
+ 	ISCSI_UEVENT_SET_HOST_PARAM	= UEVENT_BASE + 16,
++	ISCSI_UEVENT_UNBIND_SESSION	= UEVENT_BASE + 17,
+ 
+ 	/* up events */
+ 	ISCSI_KEVENT_RECV_PDU		= KEVENT_BASE + 1,
+ 	ISCSI_KEVENT_CONN_ERROR		= KEVENT_BASE + 2,
+ 	ISCSI_KEVENT_IF_ERROR		= KEVENT_BASE + 3,
+ 	ISCSI_KEVENT_DESTROY_SESSION	= KEVENT_BASE + 4,
++	ISCSI_KEVENT_UNBIND_SESSION	= KEVENT_BASE + 5,
++	ISCSI_KEVENT_CREATE_SESSION	= KEVENT_BASE + 6,
+ };
+ 
+ enum iscsi_tgt_dscvr {
+@@ -156,6 +159,10 @@ struct iscsi_uevent {
+ 			uint32_t	sid;
+ 			uint32_t	cid;
+ 		} c_conn_ret;
++		struct msg_unbind_session {
++			uint32_t	sid;
++			uint32_t	host_no;
++		} unbind_session;
+ 		struct msg_recv_req {
+ 			uint32_t	sid;
+ 			uint32_t	cid;
+diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h
+index 6947082eee6d..318a909e7ae1 100644
+--- a/include/scsi/iscsi_proto.h
++++ b/include/scsi/iscsi_proto.h
+@@ -21,6 +21,8 @@
+ #ifndef ISCSI_PROTO_H
+ #define ISCSI_PROTO_H
+ 
++#include 
++
+ #define ISCSI_DRAFT20_VERSION	0x00
+ 
+ /* default iSCSI listen port for incoming connections */
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index b8d97bd20f6e..093b4036f8db 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -186,6 +186,7 @@ struct iscsi_cls_session {
+ 	/* recovery fields */
+ 	int recovery_tmo;
+ 	struct delayed_work recovery_work;
++	struct work_struct unbind_work;
+ 
+ 	int target_id;
+ 
+@@ -206,6 +207,8 @@ struct iscsi_cls_session {
+ struct iscsi_host {
+ 	struct list_head sessions;
+ 	struct mutex mutex;
++	struct workqueue_struct *unbind_workq;
++	char unbind_workq_name[KOBJ_NAME_LEN];
+ };
+ 
+ /*
+@@ -215,8 +218,8 @@ extern struct iscsi_cls_session *iscsi_alloc_session(struct Scsi_Host *shost,
+ 					struct iscsi_transport *transport);
+ extern int iscsi_add_session(struct iscsi_cls_session *session,
+ 			     unsigned int target_id);
+-extern int iscsi_if_create_session_done(struct iscsi_cls_conn *conn);
+-extern int iscsi_if_destroy_session_done(struct iscsi_cls_conn *conn);
++extern int iscsi_session_event(struct iscsi_cls_session *session,
++			       enum iscsi_uevent_e event);
+ extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost,
+ 						struct iscsi_transport *t,
+ 						unsigned int target_id);

commit bc436b278776d22eb10e7e75bf3e5257d14550a9
+Author: Mike Christie 
+Date:   Thu Dec 13 12:43:28 2007 -0600
+
+    [SCSI] libiscsi: grab eh_mutex during host reset
+    
+    I thought we may not need the eh mutex during host reset, but that is wrong
+    with the new shutdown code. When start_session_recovery sets the state to
+    terminate then drops the session lock. The scsi eh thread could then grab the
+    session lock see that we are terminating and then return failed to scsi-ml.
+    scsi-ml's eh then owns the command and will do whatever it wants
+    with it. But then the iscsi eh thread could grab the session lock
+    and want to complete the scsi commands that we in the LLD, but
+    it no longer owns them and kaboom.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index b7a2b9ad3a97..441e351b4456 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1079,17 +1079,19 @@ int iscsi_eh_host_reset(struct scsi_cmnd *sc)
+ 	struct iscsi_session *session = iscsi_hostdata(host->hostdata);
+ 	struct iscsi_conn *conn = session->leadconn;
+ 
++	mutex_lock(&session->eh_mutex);
+ 	spin_lock_bh(&session->lock);
+ 	if (session->state == ISCSI_STATE_TERMINATE) {
+ failed:
+ 		debug_scsi("failing host reset: session terminated "
+ 			   "[CID %d age %d]\n", conn->id, session->age);
+ 		spin_unlock_bh(&session->lock);
++		mutex_unlock(&session->eh_mutex);
+ 		return FAILED;
+ 	}
+ 
+ 	spin_unlock_bh(&session->lock);
+-
++	mutex_unlock(&session->eh_mutex);
+ 	/*
+ 	 * we drop the lock here but the leadconn cannot be destoyed while
+ 	 * we are in the scsi eh
+@@ -1104,13 +1106,14 @@ int iscsi_eh_host_reset(struct scsi_cmnd *sc)
+ 	if (signal_pending(current))
+ 		flush_signals(current);
+ 
++	mutex_lock(&session->eh_mutex);
+ 	spin_lock_bh(&session->lock);
+ 	if (session->state == ISCSI_STATE_LOGGED_IN)
+ 		printk(KERN_INFO "iscsi: host reset succeeded\n");
+ 	else
+ 		goto failed;
+ 	spin_unlock_bh(&session->lock);
+-
++	mutex_unlock(&session->eh_mutex);
+ 	return SUCCESS;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_eh_host_reset);

commit d8bf541e657824cb03effd726ac96e2f4dcf58a5
+Author: Mike Christie 
+Date:   Thu Dec 13 12:43:27 2007 -0600
+
+    [SCSI] iscsi class: Use our own workq instead of common system one.
+    
+    There is just too much going on through the common workq and
+    something like a scsi device removal through sysfs affects
+    how long it will take to recover the transport, mark it as
+    failed, or shut it down gracefully.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 75d3069ecaa0..9cc2cc8e87b3 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -50,6 +50,7 @@ struct iscsi_internal {
+ };
+ 
+ static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
++static struct workqueue_struct *iscsi_eh_timer_workq;
+ 
+ /*
+  * list of registered transports and lock that must
+@@ -252,7 +253,7 @@ static void session_recovery_timedout(struct work_struct *work)
+ void iscsi_unblock_session(struct iscsi_cls_session *session)
+ {
+ 	if (!cancel_delayed_work(&session->recovery_work))
+-		flush_scheduled_work();
++		flush_workqueue(iscsi_eh_timer_workq);
+ 	scsi_target_unblock(&session->dev);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_unblock_session);
+@@ -260,8 +261,8 @@ EXPORT_SYMBOL_GPL(iscsi_unblock_session);
+ void iscsi_block_session(struct iscsi_cls_session *session)
+ {
+ 	scsi_target_block(&session->dev);
+-	schedule_delayed_work(&session->recovery_work,
+-			     session->recovery_tmo * HZ);
++	queue_delayed_work(iscsi_eh_timer_workq, &session->recovery_work,
++			   session->recovery_tmo * HZ);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_block_session);
+ 
+@@ -357,7 +358,7 @@ void iscsi_remove_session(struct iscsi_cls_session *session)
+ 	struct iscsi_host *ihost = shost->shost_data;
+ 
+ 	if (!cancel_delayed_work(&session->recovery_work))
+-		flush_scheduled_work();
++		flush_workqueue(iscsi_eh_timer_workq);
+ 
+ 	mutex_lock(&ihost->mutex);
+ 	list_del(&session->host_list);
+@@ -1521,8 +1522,14 @@ static __init int iscsi_transport_init(void)
+ 		goto unregister_session_class;
+ 	}
+ 
++	iscsi_eh_timer_workq = create_singlethread_workqueue("iscsi_eh");
++	if (!iscsi_eh_timer_workq)
++		goto release_nls;
++
+ 	return 0;
+ 
++release_nls:
++	sock_release(nls->sk_socket);
+ unregister_session_class:
+ 	transport_class_unregister(&iscsi_session_class);
+ unregister_conn_class:
+@@ -1536,6 +1543,7 @@ static __init int iscsi_transport_init(void)
+ 
+ static void __exit iscsi_transport_exit(void)
+ {
++	destroy_workqueue(iscsi_eh_timer_workq);
+ 	sock_release(nls->sk_socket);
+ 	transport_class_unregister(&iscsi_connection_class);
+ 	transport_class_unregister(&iscsi_session_class);

commit b3a7ea8d50f6028964b468d13a095dfb2508b2fb
+Author: Mike Christie 
+Date:   Thu Dec 13 12:43:26 2007 -0600
+
+    [SCSI] libiscsi: do not block session during logout
+    
+    There is not need to block the session during logout. Since
+    we are going to fail the commands that were blocked just fail them
+    immediately instead.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
+index a6f2303ed14a..47f716ca0026 100644
+--- a/drivers/infiniband/ulp/iser/iser_initiator.c
++++ b/drivers/infiniband/ulp/iser/iser_initiator.c
+@@ -621,9 +621,7 @@ void iser_snd_completion(struct iser_desc *tx_desc)
+ 			struct iscsi_session *session = conn->session;
+ 
+ 			spin_lock(&conn->session->lock);
+-			list_del(&mtask->running);
+-			__kfifo_put(session->mgmtpool.queue, (void*)&mtask,
+-				    sizeof(void*));
++			iscsi_free_mgmt_task(conn, mtask);
+ 			spin_unlock(&session->lock);
+ 		}
+ 	}
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index f79a457099e6..90eae8e0d978 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -1349,9 +1349,7 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
+ 		struct iscsi_session *session = conn->session;
+ 
+ 		spin_lock_bh(&session->lock);
+-		list_del(&conn->mtask->running);
+-		__kfifo_put(session->mgmtpool.queue, (void*)&conn->mtask,
+-			    sizeof(void*));
++		iscsi_free_mgmt_task(conn, mtask);
+ 		spin_unlock_bh(&session->lock);
+ 	}
+ 	return 0;
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index d43f909a022c..b7a2b9ad3a97 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -37,9 +37,6 @@
+ #include 
+ #include 
+ 
+-static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+-			 int err);
+-
+ struct iscsi_session *
+ class_to_transport_session(struct iscsi_cls_session *cls_session)
+ {
+@@ -274,6 +271,53 @@ static void __iscsi_put_ctask(struct iscsi_cmd_task *ctask)
+ 		iscsi_complete_command(ctask);
+ }
+ 
++/*
++ * session lock must be held
++ */
++static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
++			 int err)
++{
++	struct scsi_cmnd *sc;
++
++	sc = ctask->sc;
++	if (!sc)
++		return;
++
++	if (ctask->state == ISCSI_TASK_PENDING)
++		/*
++		 * cmd never made it to the xmit thread, so we should not count
++		 * the cmd in the sequencing
++		 */
++		conn->session->queued_cmdsn--;
++	else
++		conn->session->tt->cleanup_cmd_task(conn, ctask);
++
++	sc->result = err;
++	scsi_set_resid(sc, scsi_bufflen(sc));
++	if (conn->ctask == ctask)
++		conn->ctask = NULL;
++	/* release ref from queuecommand */
++	__iscsi_put_ctask(ctask);
++}
++
++/**
++ * iscsi_free_mgmt_task - return mgmt task back to pool
++ * @conn: iscsi connection
++ * @mtask: mtask
++ *
++ * Must be called with session lock.
++ */
++void iscsi_free_mgmt_task(struct iscsi_conn *conn,
++			  struct iscsi_mgmt_task *mtask)
++{
++	list_del_init(&mtask->running);
++	if (conn->login_mtask == mtask)
++		return;
++	__kfifo_put(conn->session->mgmtpool.queue,
++		    (void*)&mtask, sizeof(void*));
++}
++EXPORT_SYMBOL_GPL(iscsi_free_mgmt_task);
++
+ /**
+  * iscsi_cmd_rsp - SCSI Command Response processing
+  * @conn: iscsi connection
+@@ -464,10 +508,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			 */
+ 			if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen))
+ 				rc = ISCSI_ERR_CONN_FAILED;
+-			list_del_init(&mtask->running);
+-			if (conn->login_mtask != mtask)
+-				__kfifo_put(session->mgmtpool.queue,
+-					    (void*)&mtask, sizeof(void*));
++			iscsi_free_mgmt_task(conn, mtask);
+ 			break;
+ 		case ISCSI_OP_SCSI_TMFUNC_RSP:
+ 			if (datalen) {
+@@ -476,6 +517,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			}
+ 
+ 			iscsi_tmf_rsp(conn, hdr);
++			iscsi_free_mgmt_task(conn, mtask);
+ 			break;
+ 		case ISCSI_OP_NOOP_IN:
+ 			if (hdr->ttt != cpu_to_be32(ISCSI_RESERVED_TAG) || datalen) {
+@@ -486,9 +528,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 
+ 			if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen))
+ 				rc = ISCSI_ERR_CONN_FAILED;
+-			list_del_init(&mtask->running);
+-			__kfifo_put(session->mgmtpool.queue,
+-				    (void*)&mtask, sizeof(void*));
++			iscsi_free_mgmt_task(conn, mtask);
+ 			break;
+ 		default:
+ 			rc = ISCSI_ERR_BAD_OPCODE;
+@@ -650,14 +690,12 @@ static void iscsi_prep_mtask(struct iscsi_conn *conn,
+ static int iscsi_xmit_mtask(struct iscsi_conn *conn)
+ {
+ 	struct iscsi_hdr *hdr = conn->mtask->hdr;
+-	int rc, was_logout = 0;
++	int rc;
+ 
++	if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT)
++		conn->session->state = ISCSI_STATE_LOGGING_OUT;
+ 	spin_unlock_bh(&conn->session->lock);
+-	if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) {
+-		conn->session->state = ISCSI_STATE_IN_RECOVERY;
+-		iscsi_block_session(session_to_cls(conn->session));
+-		was_logout = 1;
+-	}
++
+ 	rc = conn->session->tt->xmit_mgmt_task(conn, conn->mtask);
+ 	spin_lock_bh(&conn->session->lock);
+ 	if (rc)
+@@ -665,11 +703,6 @@ static int iscsi_xmit_mtask(struct iscsi_conn *conn)
+ 
+ 	/* done with this in-progress mtask */
+ 	conn->mtask = NULL;
+-
+-	if (was_logout) {
+-		set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+-		return -ENODATA;
+-	}
+ 	return 0;
+ }
+ 
+@@ -763,6 +796,12 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 	while (!list_empty(&conn->mgmtqueue)) {
+ 		conn->mtask = list_entry(conn->mgmtqueue.next,
+ 					 struct iscsi_mgmt_task, running);
++		if (conn->session->state == ISCSI_STATE_LOGGING_OUT) {
++			iscsi_free_mgmt_task(conn, conn->mtask);
++			conn->mtask = NULL;
++			continue;
++		}
++
+ 		iscsi_prep_mtask(conn, conn->mtask);
+ 		list_move_tail(conn->mgmtqueue.next, &conn->mgmt_run_list);
+ 		rc = iscsi_xmit_mtask(conn);
+@@ -777,6 +816,10 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 
+ 		conn->ctask = list_entry(conn->xmitqueue.next,
+ 					 struct iscsi_cmd_task, running);
++		if (conn->session->state == ISCSI_STATE_LOGGING_OUT) {
++			fail_command(conn, conn->ctask, DID_NO_CONNECT << 16);
++			continue;
++		}
+ 		if (iscsi_prep_scsi_cmd_pdu(conn->ctask)) {
+ 			fail_command(conn, conn->ctask, DID_ABORT << 16);
+ 			continue;
+@@ -800,6 +843,12 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 		if (conn->session->fast_abort && conn->tmf_state != TMF_INITIAL)
+ 			break;
+ 
++		/*
++		 * we always do fastlogout - conn stop code will clean up.
++		 */
++		if (conn->session->state == ISCSI_STATE_LOGGING_OUT)
++			break;
++
+ 		conn->ctask = list_entry(conn->requeue.next,
+ 					 struct iscsi_cmd_task, running);
+ 		conn->ctask->state = ISCSI_TASK_RUNNING;
+@@ -842,6 +891,7 @@ enum {
+ 	FAILURE_SESSION_TERMINATE,
+ 	FAILURE_SESSION_IN_RECOVERY,
+ 	FAILURE_SESSION_RECOVERY_TIMEOUT,
++	FAILURE_SESSION_LOGGING_OUT,
+ };
+ 
+ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+@@ -879,12 +929,19 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 			goto reject;
+ 		}
+ 
+-		if (session->state == ISCSI_STATE_RECOVERY_FAILED)
++		switch (session->state) {
++		case ISCSI_STATE_RECOVERY_FAILED:
+ 			reason = FAILURE_SESSION_RECOVERY_TIMEOUT;
+-		else if (session->state == ISCSI_STATE_TERMINATE)
++			break;
++		case ISCSI_STATE_TERMINATE:
+ 			reason = FAILURE_SESSION_TERMINATE;
+-		else
++			break;
++		case ISCSI_STATE_LOGGING_OUT:
++			reason = FAILURE_SESSION_LOGGING_OUT;
++			break;
++		default:
+ 			reason = FAILURE_SESSION_FREED;
++		}
+ 		goto fault;
+ 	}
+ 
+@@ -1120,44 +1177,9 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn,
+ 	if (age != session->age ||
+ 	    session->state != ISCSI_STATE_LOGGED_IN)
+ 		return -ENOTCONN;
+-
+-	if (!list_empty(&mtask->running)) {
+-		list_del_init(&mtask->running);
+-		__kfifo_put(session->mgmtpool.queue, (void*)&mtask,
+-			    sizeof(void*));
+-	}
+ 	return 0;
+ }
+ 
+-/*
+- * session lock must be held
+- */
+-static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+-			 int err)
+-{
+-	struct scsi_cmnd *sc;
+-
+-	sc = ctask->sc;
+-	if (!sc)
+-		return;
+-
+-	if (ctask->state == ISCSI_TASK_PENDING)
+-		/*
+-		 * cmd never made it to the xmit thread, so we should not count
+-		 * the cmd in the sequencing
+-		 */
+-		conn->session->queued_cmdsn--;
+-	else
+-		conn->session->tt->cleanup_cmd_task(conn, ctask);
+-
+-	sc->result = err;
+-	scsi_set_resid(sc, scsi_bufflen(sc));
+-	if (conn->ctask == ctask)
+-		conn->ctask = NULL;
+-	/* release ref from queuecommand */
+-	__iscsi_put_ctask(ctask);
+-}
+-
+ /*
+  * Fail commands. session lock held and recv side suspended and xmit
+  * thread flushed
+@@ -1837,22 +1859,13 @@ flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn)
+ 	/* handle pending */
+ 	list_for_each_entry_safe(mtask, tmp, &conn->mgmtqueue, running) {
+ 		debug_scsi("flushing pending mgmt task itt 0x%x\n", mtask->itt);
+-		list_del_init(&mtask->running);
+-		if (mtask == conn->login_mtask)
+-			continue;
+-		__kfifo_put(session->mgmtpool.queue, (void*)&mtask,
+-			    sizeof(void*));
++		iscsi_free_mgmt_task(conn, mtask);
+ 	}
+ 
+ 	/* handle running */
+ 	list_for_each_entry_safe(mtask, tmp, &conn->mgmt_run_list, running) {
+ 		debug_scsi("flushing running mgmt task itt 0x%x\n", mtask->itt);
+-		list_del_init(&mtask->running);
+-
+-		if (mtask == conn->login_mtask)
+-			continue;
+-		__kfifo_put(session->mgmtpool.queue, (void*)&mtask,
+-			   sizeof(void*));
++		iscsi_free_mgmt_task(conn, mtask);
+ 	}
+ 
+ 	conn->mtask = NULL;
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 4b3e3c15121a..d68f74523f2e 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -346,6 +346,8 @@ extern int __iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *,
+ extern int iscsi_verify_itt(struct iscsi_conn *, struct iscsi_hdr *,
+ 			    uint32_t *);
+ extern void iscsi_requeue_ctask(struct iscsi_cmd_task *ctask);
++extern void iscsi_free_mgmt_task(struct iscsi_conn *conn,
++				 struct iscsi_mgmt_task *mtask);
+ 
+ /*
+  * generic helpers
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 7ff6199cbd55..b8d97bd20f6e 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -176,6 +176,7 @@ struct iscsi_cls_conn {
+ #define ISCSI_STATE_TERMINATE		4
+ #define ISCSI_STATE_IN_RECOVERY		5
+ #define ISCSI_STATE_RECOVERY_FAILED	6
++#define ISCSI_STATE_LOGGING_OUT		7
+ 
+ struct iscsi_cls_session {
+ 	struct list_head sess_list;		/* item in session_list */

commit 843c0a8a76078cf961b244b839683d0667313740
+Author: Mike Christie 
+Date:   Thu Dec 13 12:43:20 2007 -0600
+
+    [SCSI] libiscsi, iscsi_tcp: add device support
+    
+    This patch adds logical unit reset support. This should work for ib_iser,
+    but I have not finished testing that driver so it is not hooked in yet.
+    
+    This patch also temporarily reverts the iscsi_tcp r2t write out patch.
+    That code is completely rewritten in this patchset.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index bad8dacafd10..2eadb6d0ad8b 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -220,12 +220,6 @@ iscsi_iser_ctask_xmit(struct iscsi_conn *conn,
+ 	debug_scsi("ctask deq [cid %d itt 0x%x]\n",
+ 		   conn->id, ctask->itt);
+ 
+-	/*
+-	 * serialize with TMF AbortTask
+-	 */
+-	if (ctask->mtask)
+-		return error;
+-
+ 	/* Send the cmd PDU */
+ 	if (!iser_ctask->command_sent) {
+ 		error = iser_send_command(conn, ctask);
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 57ce2251abc8..4b226b88b68a 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -197,7 +197,7 @@ iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	if (unlikely(!sc))
+ 		return;
+ 
+-	tcp_ctask->xmstate = XMSTATE_VALUE_IDLE;
++	tcp_ctask->xmstate = XMSTATE_IDLE;
+ 	tcp_ctask->r2t = NULL;
+ }
+ 
+@@ -369,8 +369,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	spin_lock(&session->lock);
+ 	iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
+ 
+-	if (!ctask->sc || ctask->mtask ||
+-	     session->state != ISCSI_STATE_LOGGED_IN) {
++	if (!ctask->sc || session->state != ISCSI_STATE_LOGGED_IN) {
+ 		printk(KERN_INFO "iscsi_tcp: dropping R2T itt %d in "
+ 		       "recovery...\n", ctask->itt);
+ 		spin_unlock(&session->lock);
+@@ -409,11 +408,10 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 
+ 	tcp_ctask->exp_datasn = r2tsn + 1;
+ 	__kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*));
+-	set_bit(XMSTATE_BIT_SOL_HDR_INIT, &tcp_ctask->xmstate);
+-	list_move_tail(&ctask->running, &conn->xmitqueue);
+-
+-	scsi_queue_work(session->host, &conn->xmitwork);
++	tcp_ctask->xmstate |= XMSTATE_SOL_HDR_INIT;
+ 	conn->r2t_pdus_cnt++;
++
++	iscsi_requeue_ctask(ctask);
+ 	spin_unlock(&session->lock);
+ 
+ 	return 0;
+@@ -1254,7 +1252,7 @@ static void iscsi_set_padding(struct iscsi_tcp_cmd_task *tcp_ctask,
+ 
+ 	tcp_ctask->pad_count = ISCSI_PAD_LEN - tcp_ctask->pad_count;
+ 	debug_scsi("write padding %d bytes\n", tcp_ctask->pad_count);
+-	set_bit(XMSTATE_BIT_W_PAD, &tcp_ctask->xmstate);
++	tcp_ctask->xmstate |= XMSTATE_W_PAD;
+ }
+ 
+ /**
+@@ -1269,7 +1267,7 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask)
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 
+ 	BUG_ON(__kfifo_len(tcp_ctask->r2tqueue));
+-	tcp_ctask->xmstate = 1 << XMSTATE_BIT_CMD_HDR_INIT;
++	tcp_ctask->xmstate = XMSTATE_CMD_HDR_INIT;
+ }
+ 
+ /**
+@@ -1283,10 +1281,10 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask)
+  *	xmit.
+  *
+  *	Management xmit state machine consists of these states:
+- *		XMSTATE_BIT_IMM_HDR_INIT - calculate digest of PDU Header
+- *		XMSTATE_BIT_IMM_HDR      - PDU Header xmit in progress
+- *		XMSTATE_BIT_IMM_DATA     - PDU Data xmit in progress
+- *		XMSTATE_VALUE_IDLE       - management PDU is done
++ *		XMSTATE_IMM_HDR_INIT	- calculate digest of PDU Header
++ *		XMSTATE_IMM_HDR 	- PDU Header xmit in progress
++ *		XMSTATE_IMM_DATA 	- PDU Data xmit in progress
++ *		XMSTATE_IDLE		- management PDU is done
+  **/
+ static int
+ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
+@@ -1297,12 +1295,12 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
+ 	debug_scsi("mtask deq [cid %d state %x itt 0x%x]\n",
+ 		conn->id, tcp_mtask->xmstate, mtask->itt);
+ 
+-	if (test_bit(XMSTATE_BIT_IMM_HDR_INIT, &tcp_mtask->xmstate)) {
++	if (tcp_mtask->xmstate & XMSTATE_IMM_HDR_INIT) {
+ 		iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr,
+ 				   sizeof(struct iscsi_hdr));
+ 
+ 		if (mtask->data_count) {
+-			set_bit(XMSTATE_BIT_IMM_DATA, &tcp_mtask->xmstate);
++			tcp_mtask->xmstate |= XMSTATE_IMM_DATA;
+ 			iscsi_buf_init_iov(&tcp_mtask->sendbuf,
+ 					   (char*)mtask->data,
+ 					   mtask->data_count);
+@@ -1315,20 +1313,21 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
+ 					(u8*)tcp_mtask->hdrext);
+ 
+ 		tcp_mtask->sent = 0;
+-		clear_bit(XMSTATE_BIT_IMM_HDR_INIT, &tcp_mtask->xmstate);
+-		set_bit(XMSTATE_BIT_IMM_HDR, &tcp_mtask->xmstate);
++		tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR_INIT;
++		tcp_mtask->xmstate |= XMSTATE_IMM_HDR;
+ 	}
+ 
+-	if (test_bit(XMSTATE_BIT_IMM_HDR, &tcp_mtask->xmstate)) {
++	if (tcp_mtask->xmstate & XMSTATE_IMM_HDR) {
+ 		rc = iscsi_sendhdr(conn, &tcp_mtask->headbuf,
+ 				   mtask->data_count);
+ 		if (rc)
+ 			return rc;
+-		clear_bit(XMSTATE_BIT_IMM_HDR, &tcp_mtask->xmstate);
++		tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR;
+ 	}
+ 
+-	if (test_and_clear_bit(XMSTATE_BIT_IMM_DATA, &tcp_mtask->xmstate)) {
++	if (tcp_mtask->xmstate & XMSTATE_IMM_DATA) {
+ 		BUG_ON(!mtask->data_count);
++		tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA;
+ 		/* FIXME: implement.
+ 		 * Virtual buffer could be spreaded across multiple pages...
+ 		 */
+@@ -1338,13 +1337,13 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
+ 			rc = iscsi_sendpage(conn, &tcp_mtask->sendbuf,
+ 					&mtask->data_count, &tcp_mtask->sent);
+ 			if (rc) {
+-				set_bit(XMSTATE_BIT_IMM_DATA, &tcp_mtask->xmstate);
++				tcp_mtask->xmstate |= XMSTATE_IMM_DATA;
+ 				return rc;
+ 			}
+ 		} while (mtask->data_count);
+ 	}
+ 
+-	BUG_ON(tcp_mtask->xmstate != XMSTATE_VALUE_IDLE);
++	BUG_ON(tcp_mtask->xmstate != XMSTATE_IDLE);
+ 	if (mtask->hdr->itt == RESERVED_ITT) {
+ 		struct iscsi_session *session = conn->session;
+ 
+@@ -1364,7 +1363,7 @@ iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	int rc = 0;
+ 
+-	if (test_bit(XMSTATE_BIT_CMD_HDR_INIT, &tcp_ctask->xmstate)) {
++	if (tcp_ctask->xmstate & XMSTATE_CMD_HDR_INIT) {
+ 		tcp_ctask->sent = 0;
+ 		tcp_ctask->sg_count = 0;
+ 		tcp_ctask->exp_datasn = 0;
+@@ -1389,21 +1388,21 @@ iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 		if (conn->hdrdgst_en)
+ 			iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
+ 					 (u8*)tcp_ctask->hdrext);
+-		clear_bit(XMSTATE_BIT_CMD_HDR_INIT, &tcp_ctask->xmstate);
+-		set_bit(XMSTATE_BIT_CMD_HDR_XMIT, &tcp_ctask->xmstate);
++		tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_INIT;
++		tcp_ctask->xmstate |= XMSTATE_CMD_HDR_XMIT;
+ 	}
+ 
+-	if (test_bit(XMSTATE_BIT_CMD_HDR_XMIT, &tcp_ctask->xmstate)) {
++	if (tcp_ctask->xmstate & XMSTATE_CMD_HDR_XMIT) {
+ 		rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count);
+ 		if (rc)
+ 			return rc;
+-		clear_bit(XMSTATE_BIT_CMD_HDR_XMIT, &tcp_ctask->xmstate);
++		tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_XMIT;
+ 
+ 		if (sc->sc_data_direction != DMA_TO_DEVICE)
+ 			return 0;
+ 
+ 		if (ctask->imm_count) {
+-			set_bit(XMSTATE_BIT_IMM_DATA, &tcp_ctask->xmstate);
++			tcp_ctask->xmstate |= XMSTATE_IMM_DATA;
+ 			iscsi_set_padding(tcp_ctask, ctask->imm_count);
+ 
+ 			if (ctask->conn->datadgst_en) {
+@@ -1413,10 +1412,9 @@ iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 			}
+ 		}
+ 
+-		if (ctask->unsol_count) {
+-			set_bit(XMSTATE_BIT_UNS_HDR, &tcp_ctask->xmstate);
+-			set_bit(XMSTATE_BIT_UNS_INIT, &tcp_ctask->xmstate);
+-		}
++		if (ctask->unsol_count)
++			tcp_ctask->xmstate |=
++					XMSTATE_UNS_HDR | XMSTATE_UNS_INIT;
+ 	}
+ 	return rc;
+ }
+@@ -1428,25 +1426,25 @@ iscsi_send_padding(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	int sent = 0, rc;
+ 
+-	if (test_bit(XMSTATE_BIT_W_PAD, &tcp_ctask->xmstate)) {
++	if (tcp_ctask->xmstate & XMSTATE_W_PAD) {
+ 		iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad,
+ 				   tcp_ctask->pad_count);
+ 		if (conn->datadgst_en)
+ 			crypto_hash_update(&tcp_conn->tx_hash,
+ 					   &tcp_ctask->sendbuf.sg,
+ 					   tcp_ctask->sendbuf.sg.length);
+-	} else if (!test_bit(XMSTATE_BIT_W_RESEND_PAD, &tcp_ctask->xmstate))
++	} else if (!(tcp_ctask->xmstate & XMSTATE_W_RESEND_PAD))
+ 		return 0;
+ 
+-	clear_bit(XMSTATE_BIT_W_PAD, &tcp_ctask->xmstate);
+-	clear_bit(XMSTATE_BIT_W_RESEND_PAD, &tcp_ctask->xmstate);
++	tcp_ctask->xmstate &= ~XMSTATE_W_PAD;
++	tcp_ctask->xmstate &= ~XMSTATE_W_RESEND_PAD;
+ 	debug_scsi("sending %d pad bytes for itt 0x%x\n",
+ 		   tcp_ctask->pad_count, ctask->itt);
+ 	rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count,
+ 			   &sent);
+ 	if (rc) {
+ 		debug_scsi("padding send failed %d\n", rc);
+-		set_bit(XMSTATE_BIT_W_RESEND_PAD, &tcp_ctask->xmstate);
++		tcp_ctask->xmstate |= XMSTATE_W_RESEND_PAD;
+ 	}
+ 	return rc;
+ }
+@@ -1465,11 +1463,11 @@ iscsi_send_digest(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 	tcp_ctask = ctask->dd_data;
+ 	tcp_conn = conn->dd_data;
+ 
+-	if (!test_bit(XMSTATE_BIT_W_RESEND_DATA_DIGEST, &tcp_ctask->xmstate)) {
++	if (!(tcp_ctask->xmstate & XMSTATE_W_RESEND_DATA_DIGEST)) {
+ 		crypto_hash_final(&tcp_conn->tx_hash, (u8*)digest);
+ 		iscsi_buf_init_iov(buf, (char*)digest, 4);
+ 	}
+-	clear_bit(XMSTATE_BIT_W_RESEND_DATA_DIGEST, &tcp_ctask->xmstate);
++	tcp_ctask->xmstate &= ~XMSTATE_W_RESEND_DATA_DIGEST;
+ 
+ 	rc = iscsi_sendpage(conn, buf, &tcp_ctask->digest_count, &sent);
+ 	if (!rc)
+@@ -1478,7 +1476,7 @@ iscsi_send_digest(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 	else {
+ 		debug_scsi("sending digest 0x%x failed for itt 0x%x!\n",
+ 			  *digest, ctask->itt);
+-		set_bit(XMSTATE_BIT_W_RESEND_DATA_DIGEST, &tcp_ctask->xmstate);
++		tcp_ctask->xmstate |= XMSTATE_W_RESEND_DATA_DIGEST;
+ 	}
+ 	return rc;
+ }
+@@ -1526,8 +1524,8 @@ iscsi_send_unsol_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	struct iscsi_data_task *dtask;
+ 	int rc;
+ 
+-	set_bit(XMSTATE_BIT_UNS_DATA, &tcp_ctask->xmstate);
+-	if (test_bit(XMSTATE_BIT_UNS_INIT, &tcp_ctask->xmstate)) {
++	tcp_ctask->xmstate |= XMSTATE_UNS_DATA;
++	if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) {
+ 		dtask = &tcp_ctask->unsol_dtask;
+ 
+ 		iscsi_prep_unsolicit_data_pdu(ctask, &dtask->hdr);
+@@ -1537,14 +1535,14 @@ iscsi_send_unsol_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 			iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
+ 					(u8*)dtask->hdrext);
+ 
+-		clear_bit(XMSTATE_BIT_UNS_INIT, &tcp_ctask->xmstate);
++		tcp_ctask->xmstate &= ~XMSTATE_UNS_INIT;
+ 		iscsi_set_padding(tcp_ctask, ctask->data_count);
+ 	}
+ 
+ 	rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->data_count);
+ 	if (rc) {
+-		clear_bit(XMSTATE_BIT_UNS_DATA, &tcp_ctask->xmstate);
+-		set_bit(XMSTATE_BIT_UNS_HDR, &tcp_ctask->xmstate);
++		tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA;
++		tcp_ctask->xmstate |= XMSTATE_UNS_HDR;
+ 		return rc;
+ 	}
+ 
+@@ -1565,15 +1563,16 @@ iscsi_send_unsol_pdu(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	int rc;
+ 
+-	if (test_and_clear_bit(XMSTATE_BIT_UNS_HDR, &tcp_ctask->xmstate)) {
++	if (tcp_ctask->xmstate & XMSTATE_UNS_HDR) {
+ 		BUG_ON(!ctask->unsol_count);
++		tcp_ctask->xmstate &= ~XMSTATE_UNS_HDR;
+ send_hdr:
+ 		rc = iscsi_send_unsol_hdr(conn, ctask);
+ 		if (rc)
+ 			return rc;
+ 	}
+ 
+-	if (test_bit(XMSTATE_BIT_UNS_DATA, &tcp_ctask->xmstate)) {
++	if (tcp_ctask->xmstate & XMSTATE_UNS_DATA) {
+ 		struct iscsi_data_task *dtask = &tcp_ctask->unsol_dtask;
+ 		int start = tcp_ctask->sent;
+ 
+@@ -1583,14 +1582,14 @@ iscsi_send_unsol_pdu(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 		ctask->unsol_count -= tcp_ctask->sent - start;
+ 		if (rc)
+ 			return rc;
+-		clear_bit(XMSTATE_BIT_UNS_DATA, &tcp_ctask->xmstate);
++		tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA;
+ 		/*
+ 		 * Done with the Data-Out. Next, check if we need
+ 		 * to send another unsolicited Data-Out.
+ 		 */
+ 		if (ctask->unsol_count) {
+ 			debug_scsi("sending more uns\n");
+-			set_bit(XMSTATE_BIT_UNS_INIT, &tcp_ctask->xmstate);
++			tcp_ctask->xmstate |= XMSTATE_UNS_INIT;
+ 			goto send_hdr;
+ 		}
+ 	}
+@@ -1606,7 +1605,7 @@ static int iscsi_send_sol_pdu(struct iscsi_conn *conn,
+ 	struct iscsi_data_task *dtask;
+ 	int left, rc;
+ 
+-	if (test_bit(XMSTATE_BIT_SOL_HDR_INIT, &tcp_ctask->xmstate)) {
++	if (tcp_ctask->xmstate & XMSTATE_SOL_HDR_INIT) {
+ 		if (!tcp_ctask->r2t) {
+ 			spin_lock_bh(&session->lock);
+ 			__kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t,
+@@ -1620,19 +1619,19 @@ static int iscsi_send_sol_pdu(struct iscsi_conn *conn,
+ 		if (conn->hdrdgst_en)
+ 			iscsi_hdr_digest(conn, &r2t->headbuf,
+ 					(u8*)dtask->hdrext);
+-		clear_bit(XMSTATE_BIT_SOL_HDR_INIT, &tcp_ctask->xmstate);
+-		set_bit(XMSTATE_BIT_SOL_HDR, &tcp_ctask->xmstate);
++		tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR_INIT;
++		tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
+ 	}
+ 
+-	if (test_bit(XMSTATE_BIT_SOL_HDR, &tcp_ctask->xmstate)) {
++	if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) {
+ 		r2t = tcp_ctask->r2t;
+ 		dtask = &r2t->dtask;
+ 
+ 		rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count);
+ 		if (rc)
+ 			return rc;
+-		clear_bit(XMSTATE_BIT_SOL_HDR, &tcp_ctask->xmstate);
+-		set_bit(XMSTATE_BIT_SOL_DATA, &tcp_ctask->xmstate);
++		tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
++		tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
+ 
+ 		if (conn->datadgst_en) {
+ 			iscsi_data_digest_init(conn->dd_data, tcp_ctask);
+@@ -1645,7 +1644,7 @@ static int iscsi_send_sol_pdu(struct iscsi_conn *conn,
+ 			r2t->sent);
+ 	}
+ 
+-	if (test_bit(XMSTATE_BIT_SOL_DATA, &tcp_ctask->xmstate)) {
++	if (tcp_ctask->xmstate & XMSTATE_SOL_DATA) {
+ 		r2t = tcp_ctask->r2t;
+ 		dtask = &r2t->dtask;
+ 
+@@ -1654,7 +1653,7 @@ static int iscsi_send_sol_pdu(struct iscsi_conn *conn,
+ 				     &dtask->digestbuf, &dtask->digest);
+ 		if (rc)
+ 			return rc;
+-		clear_bit(XMSTATE_BIT_SOL_DATA, &tcp_ctask->xmstate);
++		tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA;
+ 
+ 		/*
+ 		 * Done with this Data-Out. Next, check if we have
+@@ -1699,32 +1698,32 @@ static int iscsi_send_sol_pdu(struct iscsi_conn *conn,
+  *	xmit stages.
+  *
+  *iscsi_send_cmd_hdr()
+- *	XMSTATE_BIT_CMD_HDR_INIT - prepare Header and Data buffers Calculate
+- *	                           Header Digest
+- *	XMSTATE_BIT_CMD_HDR_XMIT - Transmit header in progress
++ *	XMSTATE_CMD_HDR_INIT - prepare Header and Data buffers Calculate
++ *	                       Header Digest
++ *	XMSTATE_CMD_HDR_XMIT - Transmit header in progress
+  *
+  *iscsi_send_padding
+- *	XMSTATE_BIT_W_PAD        - Prepare and send pading
+- *	XMSTATE_BIT_W_RESEND_PAD - retry send pading
++ *	XMSTATE_W_PAD        - Prepare and send pading
++ *	XMSTATE_W_RESEND_PAD - retry send pading
+  *
+  *iscsi_send_digest
+- *	XMSTATE_BIT_W_RESEND_DATA_DIGEST - Finalize and send Data Digest
+- *	XMSTATE_BIT_W_RESEND_DATA_DIGEST - retry sending digest
++ *	XMSTATE_W_RESEND_DATA_DIGEST - Finalize and send Data Digest
++ *	XMSTATE_W_RESEND_DATA_DIGEST - retry sending digest
+  *
+  *iscsi_send_unsol_hdr
+- *	XMSTATE_BIT_UNS_INIT     - prepare un-solicit data header and digest
+- *	XMSTATE_BIT_UNS_HDR      - send un-solicit header
++ *	XMSTATE_UNS_INIT     - prepare un-solicit data header and digest
++ *	XMSTATE_UNS_HDR      - send un-solicit header
+  *
+  *iscsi_send_unsol_pdu
+- *	XMSTATE_BIT_UNS_DATA     - send un-solicit data in progress
++ *	XMSTATE_UNS_DATA     - send un-solicit data in progress
+  *
+  *iscsi_send_sol_pdu
+- *	XMSTATE_BIT_SOL_HDR_INIT - solicit data header and digest initialize
+- *	XMSTATE_BIT_SOL_HDR      - send solicit header
+- *	XMSTATE_BIT_SOL_DATA     - send solicit data
++ *	XMSTATE_SOL_HDR_INIT - solicit data header and digest initialize
++ *	XMSTATE_SOL_HDR      - send solicit header
++ *	XMSTATE_SOL_DATA     - send solicit data
+  *
+  *iscsi_tcp_ctask_xmit
+- *	XMSTATE_BIT_IMM_DATA     - xmit managment data (??)
++ *	XMSTATE_IMM_DATA     - xmit managment data (??)
+  **/
+ static int
+ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+@@ -1741,13 +1740,13 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	if (ctask->sc->sc_data_direction != DMA_TO_DEVICE)
+ 		return 0;
+ 
+-	if (test_bit(XMSTATE_BIT_IMM_DATA, &tcp_ctask->xmstate)) {
++	if (tcp_ctask->xmstate & XMSTATE_IMM_DATA) {
+ 		rc = iscsi_send_data(ctask, &tcp_ctask->sendbuf, &tcp_ctask->sg,
+ 				     &tcp_ctask->sent, &ctask->imm_count,
+ 				     &tcp_ctask->immbuf, &tcp_ctask->immdigest);
+ 		if (rc)
+ 			return rc;
+-		clear_bit(XMSTATE_BIT_IMM_DATA, &tcp_ctask->xmstate);
++		tcp_ctask->xmstate &= ~XMSTATE_IMM_DATA;
+ 	}
+ 
+ 	rc = iscsi_send_unsol_pdu(conn, ctask);
+@@ -1980,7 +1979,7 @@ static void
+ iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
+ {
+ 	struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data;
+-	tcp_mtask->xmstate = 1 << XMSTATE_BIT_IMM_HDR_INIT;
++	tcp_mtask->xmstate = XMSTATE_IMM_HDR_INIT;
+ }
+ 
+ static int
+@@ -2226,6 +2225,7 @@ static struct scsi_host_template iscsi_sht = {
+ 	.max_sectors		= 0xFFFF,
+ 	.cmd_per_lun		= ISCSI_DEF_CMD_PER_LUN,
+ 	.eh_abort_handler       = iscsi_eh_abort,
++	.eh_device_reset_handler= iscsi_eh_device_reset,
+ 	.eh_host_reset_handler	= iscsi_eh_host_reset,
+ 	.use_clustering         = DISABLE_CLUSTERING,
+ 	.slave_configure        = iscsi_tcp_slave_configure,
+@@ -2257,7 +2257,8 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 				  ISCSI_PERSISTENT_ADDRESS |
+ 				  ISCSI_TARGET_NAME | ISCSI_TPGT |
+ 				  ISCSI_USERNAME | ISCSI_PASSWORD |
+-				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN,
++				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
++				  ISCSI_FAST_ABORT,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+ 				  ISCSI_HOST_INITIATOR_NAME |
+ 				  ISCSI_HOST_NETDEV_NAME,
+diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
+index 68c36cc8997e..7eba44df0a7f 100644
+--- a/drivers/scsi/iscsi_tcp.h
++++ b/drivers/scsi/iscsi_tcp.h
+@@ -32,21 +32,21 @@
+ #define IN_PROGRESS_PAD_RECV		0x4
+ 
+ /* xmit state machine */
+-#define XMSTATE_VALUE_IDLE			0
+-#define XMSTATE_BIT_CMD_HDR_INIT		0
+-#define XMSTATE_BIT_CMD_HDR_XMIT		1
+-#define XMSTATE_BIT_IMM_HDR			2
+-#define XMSTATE_BIT_IMM_DATA			3
+-#define XMSTATE_BIT_UNS_INIT			4
+-#define XMSTATE_BIT_UNS_HDR			5
+-#define XMSTATE_BIT_UNS_DATA			6
+-#define XMSTATE_BIT_SOL_HDR			7
+-#define XMSTATE_BIT_SOL_DATA			8
+-#define XMSTATE_BIT_W_PAD			9
+-#define XMSTATE_BIT_W_RESEND_PAD		10
+-#define XMSTATE_BIT_W_RESEND_DATA_DIGEST	11
+-#define XMSTATE_BIT_IMM_HDR_INIT		12
+-#define XMSTATE_BIT_SOL_HDR_INIT		13
++#define XMSTATE_IDLE			0x0
++#define XMSTATE_CMD_HDR_INIT		0x1
++#define XMSTATE_CMD_HDR_XMIT		0x2
++#define XMSTATE_IMM_HDR			0x4
++#define XMSTATE_IMM_DATA		0x8
++#define XMSTATE_UNS_INIT		0x10
++#define XMSTATE_UNS_HDR			0x20
++#define XMSTATE_UNS_DATA		0x40
++#define XMSTATE_SOL_HDR			0x80
++#define XMSTATE_SOL_DATA		0x100
++#define XMSTATE_W_PAD			0x200
++#define XMSTATE_W_RESEND_PAD		0x400
++#define XMSTATE_W_RESEND_DATA_DIGEST	0x800
++#define XMSTATE_IMM_HDR_INIT		0x1000
++#define XMSTATE_SOL_HDR_INIT		0x2000
+ 
+ #define ISCSI_PAD_LEN			4
+ #define ISCSI_SG_TABLESIZE		SG_ALL
+@@ -122,7 +122,7 @@ struct iscsi_data_task {
+ struct iscsi_tcp_mgmt_task {
+ 	struct iscsi_hdr	hdr;
+ 	char			hdrext[sizeof(__u32)]; /* Header-Digest */
+-	unsigned long		xmstate;	/* mgmt xmit progress */
++	int			xmstate;	/* mgmt xmit progress */
+ 	struct iscsi_buf	headbuf;	/* header buffer */
+ 	struct iscsi_buf	sendbuf;	/* in progress buffer */
+ 	int			sent;
+@@ -150,7 +150,7 @@ struct iscsi_tcp_cmd_task {
+ 	int			pad_count;		/* padded bytes */
+ 	struct iscsi_buf	headbuf;		/* header buf (xmit) */
+ 	struct iscsi_buf	sendbuf;		/* in progress buffer*/
+-	unsigned long		xmstate;		/* xmit xtate machine */
++	int			xmstate;		/* xmit xtate machine */
+ 	int			sent;
+ 	struct scatterlist	*sg;			/* per-cmd SG list  */
+ 	struct scatterlist	*bad_sg;		/* assert statement */
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 8b57af5baaec..176458f35316 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -86,7 +86,7 @@ iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
+ 		 * xmit thread
+ 		 */
+ 		if (!list_empty(&session->leadconn->xmitqueue) ||
+-		    __kfifo_len(session->leadconn->mgmtqueue))
++		    !list_empty(&session->leadconn->mgmtqueue))
+ 			scsi_queue_work(session->host,
+ 					&session->leadconn->xmitwork);
+ 	}
+@@ -318,15 +318,15 @@ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 	conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
+ 	conn->tmfrsp_pdus_cnt++;
+ 
+-	if (conn->tmabort_state != TMABORT_INITIAL)
++	if (conn->tmf_state != TMF_QUEUED)
+ 		return;
+ 
+ 	if (tmf->response == ISCSI_TMF_RSP_COMPLETE)
+-		conn->tmabort_state = TMABORT_SUCCESS;
++		conn->tmf_state = TMF_SUCCESS;
+ 	else if (tmf->response == ISCSI_TMF_RSP_NO_TASK)
+-		conn->tmabort_state = TMABORT_NOT_FOUND;
++		conn->tmf_state = TMF_NOT_FOUND;
+ 	else
+-		conn->tmabort_state = TMABORT_FAILED;
++		conn->tmf_state = TMF_FAILED;
+ 	wake_up(&conn->ehwait);
+ }
+ 
+@@ -429,7 +429,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			 */
+ 			if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen))
+ 				rc = ISCSI_ERR_CONN_FAILED;
+-			list_del(&mtask->running);
++			list_del_init(&mtask->running);
+ 			if (conn->login_mtask != mtask)
+ 				__kfifo_put(session->mgmtpool.queue,
+ 					    (void*)&mtask, sizeof(void*));
+@@ -451,10 +451,9 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 
+ 			if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen))
+ 				rc = ISCSI_ERR_CONN_FAILED;
+-			list_del(&mtask->running);
+-			if (conn->login_mtask != mtask)
+-				__kfifo_put(session->mgmtpool.queue,
+-					    (void*)&mtask, sizeof(void*));
++			list_del_init(&mtask->running);
++			__kfifo_put(session->mgmtpool.queue,
++				    (void*)&mtask, sizeof(void*));
+ 			break;
+ 		default:
+ 			rc = ISCSI_ERR_BAD_OPCODE;
+@@ -609,7 +608,8 @@ static void iscsi_prep_mtask(struct iscsi_conn *conn,
+ 		session->tt->init_mgmt_task(conn, mtask);
+ 
+ 	debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n",
+-		   hdr->opcode, hdr->itt, mtask->data_count);
++		   hdr->opcode & ISCSI_OPCODE_MASK, hdr->itt,
++		   mtask->data_count);
+ }
+ 
+ static int iscsi_xmit_mtask(struct iscsi_conn *conn)
+@@ -658,27 +658,35 @@ static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn)
+ static int iscsi_xmit_ctask(struct iscsi_conn *conn)
+ {
+ 	struct iscsi_cmd_task *ctask = conn->ctask;
+-	int rc = 0;
+-
+-	/*
+-	 * serialize with TMF AbortTask
+-	 */
+-	if (ctask->state == ISCSI_TASK_ABORTING)
+-		goto done;
++	int rc;
+ 
+ 	__iscsi_get_ctask(ctask);
+ 	spin_unlock_bh(&conn->session->lock);
+ 	rc = conn->session->tt->xmit_cmd_task(conn, ctask);
+ 	spin_lock_bh(&conn->session->lock);
+ 	__iscsi_put_ctask(ctask);
+-
+-done:
+ 	if (!rc)
+ 		/* done with this ctask */
+ 		conn->ctask = NULL;
+ 	return rc;
+ }
+ 
++/**
++ * iscsi_requeue_ctask - requeue ctask to run from session workqueue
++ * @ctask: ctask to requeue
++ *
++ * LLDs that need to run a ctask from the session workqueue should call
++ * this. The session lock must be held.
++ */
++void iscsi_requeue_ctask(struct iscsi_cmd_task *ctask)
++{
++	struct iscsi_conn *conn = ctask->conn;
++
++	list_move_tail(&ctask->running, &conn->requeue);
++	scsi_queue_work(conn->session->host, &conn->xmitwork);
++}
++EXPORT_SYMBOL_GPL(iscsi_requeue_ctask);
++
+ /**
+  * iscsi_data_xmit - xmit any command into the scheduled connection
+  * @conn: iscsi connection
+@@ -717,36 +725,27 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 	 * overflow us with nop-ins
+ 	 */
+ check_mgmt:
+-	while (__kfifo_get(conn->mgmtqueue, (void*)&conn->mtask,
+-			   sizeof(void*))) {
++	while (!list_empty(&conn->mgmtqueue)) {
++		conn->mtask = list_entry(conn->mgmtqueue.next,
++					 struct iscsi_mgmt_task, running);
+ 		iscsi_prep_mtask(conn, conn->mtask);
+-		list_add_tail(&conn->mtask->running, &conn->mgmt_run_list);
++		list_move_tail(conn->mgmtqueue.next, &conn->mgmt_run_list);
+ 		rc = iscsi_xmit_mtask(conn);
+ 		if (rc)
+ 			goto again;
+ 	}
+ 
+-	/* process command queue */
++	/* process pending command queue */
+ 	while (!list_empty(&conn->xmitqueue)) {
+-		/*
+-		 * iscsi tcp may readd the task to the xmitqueue to send
+-		 * write data
+-		 */
++		if (conn->tmf_state == TMF_QUEUED)
++			break;
++
+ 		conn->ctask = list_entry(conn->xmitqueue.next,
+ 					 struct iscsi_cmd_task, running);
+-		switch (conn->ctask->state) {
+-		case ISCSI_TASK_ABORTING:
+-			break;
+-		case ISCSI_TASK_PENDING:
+-			iscsi_prep_scsi_cmd_pdu(conn->ctask);
+-			conn->session->tt->init_cmd_task(conn->ctask);
+-			/* fall through */
+-		default:
+-			conn->ctask->state = ISCSI_TASK_RUNNING;
+-			break;
+-		}
++		iscsi_prep_scsi_cmd_pdu(conn->ctask);
++		conn->session->tt->init_cmd_task(conn->ctask);
++		conn->ctask->state = ISCSI_TASK_RUNNING;
+ 		list_move_tail(conn->xmitqueue.next, &conn->run_list);
+-
+ 		rc = iscsi_xmit_ctask(conn);
+ 		if (rc)
+ 			goto again;
+@@ -755,7 +754,22 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 		 * we need to check the mgmt queue for nops that need to
+ 		 * be sent to aviod starvation
+ 		 */
+-		if (__kfifo_len(conn->mgmtqueue))
++		if (!list_empty(&conn->mgmtqueue))
++			goto check_mgmt;
++	}
++
++	while (!list_empty(&conn->requeue)) {
++		if (conn->session->fast_abort && conn->tmf_state != TMF_INITIAL)
++			break;
++
++		conn->ctask = list_entry(conn->requeue.next,
++					 struct iscsi_cmd_task, running);
++		conn->ctask->state = ISCSI_TASK_RUNNING;
++		list_move_tail(conn->requeue.next, &conn->run_list);
++		rc = iscsi_xmit_ctask(conn);
++		if (rc)
++			goto again;
++		if (!list_empty(&conn->mgmtqueue))
+ 			goto check_mgmt;
+ 	}
+ 	spin_unlock_bh(&conn->session->lock);
+@@ -859,7 +873,6 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 
+ 	atomic_set(&ctask->refcount, 1);
+ 	ctask->state = ISCSI_TASK_PENDING;
+-	ctask->mtask = NULL;
+ 	ctask->conn = conn;
+ 	ctask->sc = sc;
+ 	INIT_LIST_HEAD(&ctask->running);
+@@ -929,9 +942,9 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	} else
+ 		mtask->data_count = 0;
+ 
+-	INIT_LIST_HEAD(&mtask->running);
+ 	memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr));
+-	__kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*));
++	INIT_LIST_HEAD(&mtask->running);
++	list_add_tail(&mtask->running, &conn->mgmtqueue);
+ 	return mtask;
+ }
+ 
+@@ -954,13 +967,12 @@ EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu);
+ void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session)
+ {
+ 	struct iscsi_session *session = class_to_transport_session(cls_session);
+-	struct iscsi_conn *conn = session->leadconn;
+ 
+ 	spin_lock_bh(&session->lock);
+ 	if (session->state != ISCSI_STATE_LOGGED_IN) {
+ 		session->state = ISCSI_STATE_RECOVERY_FAILED;
+-		if (conn)
+-			wake_up(&conn->ehwait);
++		if (session->leadconn)
++			wake_up(&session->leadconn->ehwait);
+ 	}
+ 	spin_unlock_bh(&session->lock);
+ }
+@@ -971,7 +983,6 @@ int iscsi_eh_host_reset(struct scsi_cmnd *sc)
+ 	struct Scsi_Host *host = sc->device->host;
+ 	struct iscsi_session *session = iscsi_hostdata(host->hostdata);
+ 	struct iscsi_conn *conn = session->leadconn;
+-	int fail_session = 0;
+ 
+ 	spin_lock_bh(&session->lock);
+ 	if (session->state == ISCSI_STATE_TERMINATE) {
+@@ -982,19 +993,13 @@ int iscsi_eh_host_reset(struct scsi_cmnd *sc)
+ 		return FAILED;
+ 	}
+ 
+-	if (sc->SCp.phase == session->age) {
+-		debug_scsi("failing connection CID %d due to SCSI host reset\n",
+-			   conn->id);
+-		fail_session = 1;
+-	}
+ 	spin_unlock_bh(&session->lock);
+ 
+ 	/*
+ 	 * we drop the lock here but the leadconn cannot be destoyed while
+ 	 * we are in the scsi eh
+ 	 */
+-	if (fail_session)
+-		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
++	iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ 
+ 	debug_scsi("iscsi_eh_host_reset wait for relogin\n");
+ 	wait_event_interruptible(conn->ehwait,
+@@ -1015,62 +1020,43 @@ int iscsi_eh_host_reset(struct scsi_cmnd *sc)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_eh_host_reset);
+ 
+-static void iscsi_tmabort_timedout(unsigned long data)
++static void iscsi_tmf_timedout(unsigned long data)
+ {
+-	struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)data;
+-	struct iscsi_conn *conn = ctask->conn;
++	struct iscsi_conn *conn = (struct iscsi_conn *)data;
+ 	struct iscsi_session *session = conn->session;
+ 
+ 	spin_lock(&session->lock);
+-	if (conn->tmabort_state == TMABORT_INITIAL) {
+-		conn->tmabort_state = TMABORT_TIMEDOUT;
+-		debug_scsi("tmabort timedout [sc %p itt 0x%x]\n",
+-			ctask->sc, ctask->itt);
++	if (conn->tmf_state == TMF_QUEUED) {
++		conn->tmf_state = TMF_TIMEDOUT;
++		debug_scsi("tmf timedout\n");
+ 		/* unblock eh_abort() */
+ 		wake_up(&conn->ehwait);
+ 	}
+ 	spin_unlock(&session->lock);
+ }
+ 
+-static int iscsi_exec_abort_task(struct scsi_cmnd *sc,
+-				 struct iscsi_cmd_task *ctask)
++static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn,
++				   struct iscsi_tm *hdr, int age)
+ {
+-	struct iscsi_conn *conn = ctask->conn;
+ 	struct iscsi_session *session = conn->session;
+-	struct iscsi_tm *hdr = &conn->tmhdr;
+-
+-	/*
+-	 * ctask timed out but session is OK requests must be serialized.
+-	 */
+-	memset(hdr, 0, sizeof(struct iscsi_tm));
+-	hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE;
+-	hdr->flags = ISCSI_TM_FUNC_ABORT_TASK;
+-	hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+-	memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun));
+-	hdr->rtt = ctask->hdr->itt;
+-	hdr->refcmdsn = ctask->hdr->cmdsn;
++	struct iscsi_mgmt_task *mtask;
+ 
+-	ctask->mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr,
+-					    NULL, 0);
+-	if (!ctask->mtask) {
++	mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr,
++				      NULL, 0);
++	if (!mtask) {
+ 		spin_unlock_bh(&session->lock);
+ 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+-		spin_lock_bh(&session->lock)
+-		debug_scsi("abort sent failure [itt 0x%x]\n", ctask->itt);
++		spin_lock_bh(&session->lock);
++		debug_scsi("tmf exec failure\n");
+ 		return -EPERM;
+ 	}
+-	ctask->state = ISCSI_TASK_ABORTING;
+-
+-	debug_scsi("abort sent [itt 0x%x]\n", ctask->itt);
++	conn->tmfcmd_pdus_cnt++;
++	conn->tmf_timer.expires = 30 * HZ + jiffies;
++	conn->tmf_timer.function = iscsi_tmf_timedout;
++	conn->tmf_timer.data = (unsigned long)conn;
++	add_timer(&conn->tmf_timer);
++	debug_scsi("tmf set timeout\n");
+ 
+-	if (conn->tmabort_state == TMABORT_INITIAL) {
+-		conn->tmfcmd_pdus_cnt++;
+-		conn->tmabort_timer.expires = 20*HZ + jiffies;
+-		conn->tmabort_timer.function = iscsi_tmabort_timedout;
+-		conn->tmabort_timer.data = (unsigned long)ctask;
+-		add_timer(&conn->tmabort_timer);
+-		debug_scsi("abort set timeout [itt 0x%x]\n", ctask->itt);
+-	}
+ 	spin_unlock_bh(&session->lock);
+ 	mutex_unlock(&session->eh_mutex);
+ 	scsi_queue_work(session->host, &conn->xmitwork);
+@@ -1078,61 +1064,30 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc,
+ 	/*
+ 	 * block eh thread until:
+ 	 *
+-	 * 1) abort response
+-	 * 2) abort timeout
++	 * 1) tmf response
++	 * 2) tmf timeout
+ 	 * 3) session is terminated or restarted or userspace has
+ 	 * given up on recovery
+ 	 */
+-	wait_event_interruptible(conn->ehwait,
+-				 sc->SCp.phase != session->age ||
++	wait_event_interruptible(conn->ehwait, age != session->age ||
+ 				 session->state != ISCSI_STATE_LOGGED_IN ||
+-				 conn->tmabort_state != TMABORT_INITIAL);
++				 conn->tmf_state != TMF_QUEUED);
+ 	if (signal_pending(current))
+ 		flush_signals(current);
+-	del_timer_sync(&conn->tmabort_timer);
++	del_timer_sync(&conn->tmf_timer);
++
+ 	mutex_lock(&session->eh_mutex);
+ 	spin_lock_bh(&session->lock);
+-	return 0;
+-}
+-
+-/*
+- * session lock must be held
+- */
+-static struct iscsi_mgmt_task *
+-iscsi_remove_mgmt_task(struct kfifo *fifo, uint32_t itt)
+-{
+-	int i, nr_tasks = __kfifo_len(fifo) / sizeof(void*);
+-	struct iscsi_mgmt_task *task;
+-
+-	debug_scsi("searching %d tasks\n", nr_tasks);
+-
+-	for (i = 0; i < nr_tasks; i++) {
+-		__kfifo_get(fifo, (void*)&task, sizeof(void*));
+-		debug_scsi("check task %u\n", task->itt);
+-
+-		if (task->itt == itt) {
+-			debug_scsi("matched task\n");
+-			return task;
+-		}
++	/* if the session drops it will clean up the mtask */
++	if (age != session->age ||
++	    session->state != ISCSI_STATE_LOGGED_IN)
++		return -ENOTCONN;
+ 
+-		__kfifo_put(fifo, (void*)&task, sizeof(void*));
++	if (!list_empty(&mtask->running)) {
++		list_del_init(&mtask->running);
++		__kfifo_put(session->mgmtpool.queue, (void*)&mtask,
++			    sizeof(void*));
+ 	}
+-	return NULL;
+-}
+-
+-static int iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask)
+-{
+-	struct iscsi_conn *conn = ctask->conn;
+-	struct iscsi_session *session = conn->session;
+-
+-	if (!ctask->mtask)
+-		return -EINVAL;
+-
+-	if (!iscsi_remove_mgmt_task(conn->mgmtqueue, ctask->mtask->itt))
+-		list_del(&ctask->mtask->running);
+-	__kfifo_put(session->mgmtpool.queue, (void*)&ctask->mtask,
+-		    sizeof(void*));
+-	ctask->mtask = NULL;
+ 	return 0;
+ }
+ 
+@@ -1156,7 +1111,6 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 		conn->session->queued_cmdsn--;
+ 	else
+ 		conn->session->tt->cleanup_cmd_task(conn, ctask);
+-	iscsi_ctask_mtask_cleanup(ctask);
+ 
+ 	sc->result = err;
+ 	scsi_set_resid(sc, scsi_bufflen(sc));
+@@ -1166,6 +1120,44 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 	__iscsi_put_ctask(ctask);
+ }
+ 
++/*
++ * Fail commands. session lock held and recv side suspended and xmit
++ * thread flushed
++ */
++static void fail_all_commands(struct iscsi_conn *conn, unsigned lun)
++{
++	struct iscsi_cmd_task *ctask, *tmp;
++
++	if (conn->ctask && (conn->ctask->sc->device->lun == lun || lun == -1))
++		conn->ctask = NULL;
++
++	/* flush pending */
++	list_for_each_entry_safe(ctask, tmp, &conn->xmitqueue, running) {
++		if (lun == ctask->sc->device->lun || lun == -1) {
++			debug_scsi("failing pending sc %p itt 0x%x\n",
++				   ctask->sc, ctask->itt);
++			fail_command(conn, ctask, DID_BUS_BUSY << 16);
++		}
++	}
++
++	list_for_each_entry_safe(ctask, tmp, &conn->requeue, running) {
++		if (lun == ctask->sc->device->lun || lun == -1) {
++			debug_scsi("failing requeued sc %p itt 0x%x\n",
++				   ctask->sc, ctask->itt);
++			fail_command(conn, ctask, DID_BUS_BUSY << 16);
++		}
++	}
++
++	/* fail all other running */
++	list_for_each_entry_safe(ctask, tmp, &conn->run_list, running) {
++		if (lun == ctask->sc->device->lun || lun == -1) {
++			debug_scsi("failing in progress sc %p itt 0x%x\n",
++				   ctask->sc, ctask->itt);
++			fail_command(conn, ctask, DID_BUS_BUSY << 16);
++		}
++	}
++}
++
+ static void iscsi_suspend_tx(struct iscsi_conn *conn)
+ {
+ 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+@@ -1178,13 +1170,26 @@ static void iscsi_start_tx(struct iscsi_conn *conn)
+ 	scsi_queue_work(conn->session->host, &conn->xmitwork);
+ }
+ 
++static void iscsi_prep_abort_task_pdu(struct iscsi_cmd_task *ctask,
++				      struct iscsi_tm *hdr)
++{
++	memset(hdr, 0, sizeof(*hdr));
++	hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE;
++	hdr->flags = ISCSI_TM_FUNC_ABORT_TASK & ISCSI_FLAG_TM_FUNC_MASK;
++	hdr->flags |= ISCSI_FLAG_CMD_FINAL;
++	memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun));
++	hdr->rtt = ctask->hdr->itt;
++	hdr->refcmdsn = ctask->hdr->cmdsn;
++}
++
+ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ {
+ 	struct Scsi_Host *host = sc->device->host;
+ 	struct iscsi_session *session = iscsi_hostdata(host->hostdata);
+-	struct iscsi_cmd_task *ctask;
+ 	struct iscsi_conn *conn;
+-	int rc;
++	struct iscsi_cmd_task *ctask;
++	struct iscsi_tm *hdr;
++	int rc, age;
+ 
+ 	mutex_lock(&session->eh_mutex);
+ 	spin_lock_bh(&session->lock);
+@@ -1199,19 +1204,23 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 		return SUCCESS;
+ 	}
+ 
+-	ctask = (struct iscsi_cmd_task *)sc->SCp.ptr;
+-	conn = ctask->conn;
+-
+-	conn->eh_abort_cnt++;
+-	debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt);
+-
+ 	/*
+ 	 * If we are not logged in or we have started a new session
+ 	 * then let the host reset code handle this
+ 	 */
+-	if (session->state != ISCSI_STATE_LOGGED_IN ||
+-	    sc->SCp.phase != session->age)
+-		goto failed;
++	if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN ||
++	    sc->SCp.phase != session->age) {
++		spin_unlock_bh(&session->lock);
++		mutex_unlock(&session->eh_mutex);
++		return FAILED;
++	}
++
++	conn = session->leadconn;
++	conn->eh_abort_cnt++;
++	age = session->age;
++
++	ctask = (struct iscsi_cmd_task *)sc->SCp.ptr;
++	debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt);
+ 
+ 	/* ctask completed before time out */
+ 	if (!ctask->sc) {
+@@ -1219,27 +1228,26 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 		goto success;
+ 	}
+ 
+-	/* what should we do here ? */
+-	if (conn->ctask == ctask) {
+-		printk(KERN_INFO "iscsi: sc %p itt 0x%x partially sent. "
+-		       "Failing abort\n", sc, ctask->itt);
+-		goto failed;
+-	}
+-
+ 	if (ctask->state == ISCSI_TASK_PENDING) {
+ 		fail_command(conn, ctask, DID_ABORT << 16);
+ 		goto success;
+ 	}
+ 
+-	conn->tmabort_state = TMABORT_INITIAL;
+-	rc = iscsi_exec_abort_task(sc, ctask);
+-	if (rc || sc->SCp.phase != session->age ||
+-	    session->state != ISCSI_STATE_LOGGED_IN)
++	/* only have one tmf outstanding at a time */
++	if (conn->tmf_state != TMF_INITIAL)
+ 		goto failed;
+-	iscsi_ctask_mtask_cleanup(ctask);
++	conn->tmf_state = TMF_QUEUED;
+ 
+-	switch (conn->tmabort_state) {
+-	case TMABORT_SUCCESS:
++	hdr = &conn->tmhdr;
++	iscsi_prep_abort_task_pdu(ctask, hdr);
++
++	if (iscsi_exec_task_mgmt_fn(conn, hdr, age)) {
++		rc = FAILED;
++		goto failed;
++	}
++
++	switch (conn->tmf_state) {
++	case TMF_SUCCESS:
+ 		spin_unlock_bh(&session->lock);
+ 		iscsi_suspend_tx(conn);
+ 		/*
+@@ -1248,22 +1256,26 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 		write_lock_bh(conn->recv_lock);
+ 		spin_lock(&session->lock);
+ 		fail_command(conn, ctask, DID_ABORT << 16);
++		conn->tmf_state = TMF_INITIAL;
+ 		spin_unlock(&session->lock);
+ 		write_unlock_bh(conn->recv_lock);
+ 		iscsi_start_tx(conn);
+ 		goto success_unlocked;
+-	case TMABORT_NOT_FOUND:
+-		if (!ctask->sc) {
++	case TMF_TIMEDOUT:
++		spin_unlock_bh(&session->lock);
++		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
++		goto failed_unlocked;
++	case TMF_NOT_FOUND:
++		if (!sc->SCp.ptr) {
++			conn->tmf_state = TMF_INITIAL;
+ 			/* ctask completed before tmf abort response */
+ 			debug_scsi("sc completed while abort in progress\n");
+ 			goto success;
+ 		}
+ 		/* fall through */
+ 	default:
+-		/* timedout or failed */
+-		spin_unlock_bh(&session->lock);
+-		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+-		goto failed_unlocked;
++		conn->tmf_state = TMF_INITIAL;
++		goto failed;
+ 	}
+ 
+ success:
+@@ -1276,12 +1288,93 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ failed:
+ 	spin_unlock_bh(&session->lock);
+ failed_unlocked:
+-	debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
++	debug_scsi("abort failed [sc %p itt 0x%x]\n", sc,
++		    ctask ? ctask->itt : 0);
+ 	mutex_unlock(&session->eh_mutex);
+ 	return FAILED;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_eh_abort);
+ 
++static void iscsi_prep_lun_reset_pdu(struct scsi_cmnd *sc, struct iscsi_tm *hdr)
++{
++	memset(hdr, 0, sizeof(*hdr));
++	hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE;
++	hdr->flags = ISCSI_TM_FUNC_LOGICAL_UNIT_RESET & ISCSI_FLAG_TM_FUNC_MASK;
++	hdr->flags |= ISCSI_FLAG_CMD_FINAL;
++	int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
++	hdr->rtt = ISCSI_RESERVED_TAG;
++}
++
++int iscsi_eh_device_reset(struct scsi_cmnd *sc)
++{
++	struct Scsi_Host *host = sc->device->host;
++	struct iscsi_session *session = iscsi_hostdata(host->hostdata);
++	struct iscsi_conn *conn;
++	struct iscsi_tm *hdr;
++	int rc = FAILED;
++
++	debug_scsi("LU Reset [sc %p lun %u]\n", sc, sc->device->lun);
++
++	mutex_lock(&session->eh_mutex);
++	spin_lock_bh(&session->lock);
++	/*
++	 * Just check if we are not logged in. We cannot check for
++	 * the phase because the reset could come from a ioctl.
++	 */
++	if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN)
++		goto unlock;
++	conn = session->leadconn;
++
++	/* only have one tmf outstanding at a time */
++	if (conn->tmf_state != TMF_INITIAL)
++		goto unlock;
++	conn->tmf_state = TMF_QUEUED;
++
++	hdr = &conn->tmhdr;
++	iscsi_prep_lun_reset_pdu(sc, hdr);
++
++	if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age)) {
++		rc = FAILED;
++		goto unlock;
++	}
++
++	switch (conn->tmf_state) {
++	case TMF_SUCCESS:
++		break;
++	case TMF_TIMEDOUT:
++		spin_unlock_bh(&session->lock);
++		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
++		goto done;
++	default:
++		conn->tmf_state = TMF_INITIAL;
++		goto unlock;
++	}
++
++	rc = SUCCESS;
++	spin_unlock_bh(&session->lock);
++
++	iscsi_suspend_tx(conn);
++	/* need to grab the recv lock then session lock */
++	write_lock_bh(conn->recv_lock);
++	spin_lock(&session->lock);
++	fail_all_commands(conn, sc->device->lun);
++	conn->tmf_state = TMF_INITIAL;
++	spin_unlock(&session->lock);
++	write_unlock_bh(conn->recv_lock);
++
++	iscsi_start_tx(conn);
++	goto done;
++
++unlock:
++	spin_unlock_bh(&session->lock);
++done:
++	debug_scsi("iscsi_eh_device_reset %s\n",
++		  rc == SUCCESS ? "SUCCESS" : "FAILED");
++	mutex_unlock(&session->eh_mutex);
++	return rc;
++}
++EXPORT_SYMBOL_GPL(iscsi_eh_device_reset);
++
+ int
+ iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size)
+ {
+@@ -1546,17 +1639,12 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ 	conn->c_stage = ISCSI_CONN_INITIAL_STAGE;
+ 	conn->id = conn_idx;
+ 	conn->exp_statsn = 0;
+-	conn->tmabort_state = TMABORT_INITIAL;
++	conn->tmf_state = TMF_INITIAL;
+ 	INIT_LIST_HEAD(&conn->run_list);
+ 	INIT_LIST_HEAD(&conn->mgmt_run_list);
++	INIT_LIST_HEAD(&conn->mgmtqueue);
+ 	INIT_LIST_HEAD(&conn->xmitqueue);
+-
+-	/* initialize general immediate & non-immediate PDU commands queue */
+-	conn->mgmtqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*),
+-			                GFP_KERNEL, NULL);
+-	if (conn->mgmtqueue == ERR_PTR(-ENOMEM))
+-		goto mgmtqueue_alloc_fail;
+-
++	INIT_LIST_HEAD(&conn->requeue);
+ 	INIT_WORK(&conn->xmitwork, iscsi_xmitworker);
+ 
+ 	/* allocate login_mtask used for the login/text sequences */
+@@ -1574,7 +1662,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ 		goto login_mtask_data_alloc_fail;
+ 	conn->login_mtask->data = conn->data = data;
+ 
+-	init_timer(&conn->tmabort_timer);
++	init_timer(&conn->tmf_timer);
+ 	init_waitqueue_head(&conn->ehwait);
+ 
+ 	return cls_conn;
+@@ -1583,8 +1671,6 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ 	__kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask,
+ 		    sizeof(void*));
+ login_mtask_alloc_fail:
+-	kfifo_free(conn->mgmtqueue);
+-mgmtqueue_alloc_fail:
+ 	iscsi_destroy_conn(cls_conn);
+ 	return NULL;
+ }
+@@ -1604,7 +1690,6 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
+ 	unsigned long flags;
+ 
+ 	spin_lock_bh(&session->lock);
+-	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+ 	conn->c_stage = ISCSI_CONN_CLEANUP_WAIT;
+ 	if (session->leadconn == conn) {
+ 		/*
+@@ -1637,7 +1722,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
+ 	}
+ 
+ 	/* flush queued up work because we free the connection below */
+-	scsi_flush_work(session->host);
++	iscsi_suspend_tx(conn);
+ 
+ 	spin_lock_bh(&session->lock);
+ 	kfree(conn->data);
+@@ -1648,8 +1733,6 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
+ 		session->leadconn = NULL;
+ 	spin_unlock_bh(&session->lock);
+ 
+-	kfifo_free(conn->mgmtqueue);
+-
+ 	iscsi_destroy_conn(cls_conn);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_conn_teardown);
+@@ -1684,7 +1767,7 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
+ 		 * commands after successful recovery
+ 		 */
+ 		conn->stop_stage = 0;
+-		conn->tmabort_state = TMABORT_INITIAL;
++		conn->tmf_state = TMF_INITIAL;
+ 		session->age++;
+ 		spin_unlock_bh(&session->lock);
+ 
+@@ -1709,10 +1792,11 @@ flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn)
+ 	struct iscsi_mgmt_task *mtask, *tmp;
+ 
+ 	/* handle pending */
+-	while (__kfifo_get(conn->mgmtqueue, (void*)&mtask, sizeof(void*))) {
++	list_for_each_entry_safe(mtask, tmp, &conn->mgmtqueue, running) {
++		debug_scsi("flushing pending mgmt task itt 0x%x\n", mtask->itt);
++		list_del_init(&mtask->running);
+ 		if (mtask == conn->login_mtask)
+ 			continue;
+-		debug_scsi("flushing pending mgmt task itt 0x%x\n", mtask->itt);
+ 		__kfifo_put(session->mgmtpool.queue, (void*)&mtask,
+ 			    sizeof(void*));
+ 	}
+@@ -1720,7 +1804,7 @@ flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn)
+ 	/* handle running */
+ 	list_for_each_entry_safe(mtask, tmp, &conn->mgmt_run_list, running) {
+ 		debug_scsi("flushing running mgmt task itt 0x%x\n", mtask->itt);
+-		list_del(&mtask->running);
++		list_del_init(&mtask->running);
+ 
+ 		if (mtask == conn->login_mtask)
+ 			continue;
+@@ -1731,28 +1815,6 @@ flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn)
+ 	conn->mtask = NULL;
+ }
+ 
+-/* Fail commands. Mutex and session lock held and recv side suspended */
+-static void fail_all_commands(struct iscsi_conn *conn)
+-{
+-	struct iscsi_cmd_task *ctask, *tmp;
+-
+-	/* flush pending */
+-	list_for_each_entry_safe(ctask, tmp, &conn->xmitqueue, running) {
+-		debug_scsi("failing pending sc %p itt 0x%x\n", ctask->sc,
+-			   ctask->itt);
+-		fail_command(conn, ctask, DID_BUS_BUSY << 16);
+-	}
+-
+-	/* fail all other running */
+-	list_for_each_entry_safe(ctask, tmp, &conn->run_list, running) {
+-		debug_scsi("failing in progress sc %p itt 0x%x\n",
+-			   ctask->sc, ctask->itt);
+-		fail_command(conn, ctask, DID_BUS_BUSY << 16);
+-	}
+-
+-	conn->ctask = NULL;
+-}
+-
+ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ 					 struct iscsi_conn *conn, int flag)
+ {
+@@ -1818,7 +1880,7 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ 	 * flush queues.
+ 	 */
+ 	spin_lock_bh(&session->lock);
+-	fail_all_commands(conn);
++	fail_all_commands(conn, -1);
+ 	flush_control_queues(session, conn);
+ 	spin_unlock_bh(&session->lock);
+ 	mutex_unlock(&session->eh_mutex);
+@@ -1869,6 +1931,9 @@ int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
+ 	uint32_t value;
+ 
+ 	switch(param) {
++	case ISCSI_PARAM_FAST_ABORT:
++		sscanf(buf, "%d", &session->fast_abort);
++		break;
+ 	case ISCSI_PARAM_MAX_RECV_DLENGTH:
+ 		sscanf(buf, "%d", &conn->max_recv_dlength);
+ 		break;
+@@ -1983,6 +2048,9 @@ int iscsi_session_get_param(struct iscsi_cls_session *cls_session,
+ 	int len;
+ 
+ 	switch(param) {
++	case ISCSI_PARAM_FAST_ABORT:
++		len = sprintf(buf, "%d\n", session->fast_abort);
++		break;
+ 	case ISCSI_PARAM_INITIAL_R2T_EN:
+ 		len = sprintf(buf, "%d\n", session->initial_r2t_en);
+ 		break;
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index cb48b80c0865..75d3069ecaa0 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -30,7 +30,7 @@
+ #include 
+ #include 
+ 
+-#define ISCSI_SESSION_ATTRS 15
++#define ISCSI_SESSION_ATTRS 16
+ #define ISCSI_CONN_ATTRS 11
+ #define ISCSI_HOST_ATTRS 4
+ #define ISCSI_TRANSPORT_VERSION "2.0-724"
+@@ -1218,6 +1218,7 @@ iscsi_session_attr(username, ISCSI_PARAM_USERNAME, 1);
+ iscsi_session_attr(username_in, ISCSI_PARAM_USERNAME_IN, 1);
+ iscsi_session_attr(password, ISCSI_PARAM_PASSWORD, 1);
+ iscsi_session_attr(password_in, ISCSI_PARAM_PASSWORD_IN, 1);
++iscsi_session_attr(fast_abort, ISCSI_PARAM_FAST_ABORT, 1);
+ 
+ #define iscsi_priv_session_attr_show(field, format)			\
+ static ssize_t								\
+@@ -1439,6 +1440,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 	SETUP_SESSION_RD_ATTR(password_in, ISCSI_USERNAME_IN);
+ 	SETUP_SESSION_RD_ATTR(username, ISCSI_PASSWORD);
+ 	SETUP_SESSION_RD_ATTR(username_in, ISCSI_PASSWORD_IN);
++	SETUP_SESSION_RD_ATTR(fast_abort, ISCSI_FAST_ABORT);
+ 	SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo);
+ 
+ 	BUG_ON(count > ISCSI_SESSION_ATTRS);
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index 50e907f42048..bff0b1f7857b 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -236,6 +236,7 @@ enum iscsi_param {
+ 	ISCSI_PARAM_PASSWORD,
+ 	ISCSI_PARAM_PASSWORD_IN,
+ 
++	ISCSI_PARAM_FAST_ABORT,
+ 	/* must always be last */
+ 	ISCSI_PARAM_MAX,
+ };
+@@ -266,6 +267,7 @@ enum iscsi_param {
+ #define ISCSI_USERNAME_IN		(1 << ISCSI_PARAM_USERNAME_IN)
+ #define ISCSI_PASSWORD			(1 << ISCSI_PARAM_PASSWORD)
+ #define ISCSI_PASSWORD_IN		(1 << ISCSI_PARAM_PASSWORD_IN)
++#define ISCSI_FAST_ABORT		(1 << ISCSI_PARAM_FAST_ABORT)
+ 
+ /* iSCSI HBA params */
+ enum iscsi_host_param {
+diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h
+index 8d1e4e8026fe..751c81eaa7f3 100644
+--- a/include/scsi/iscsi_proto.h
++++ b/include/scsi/iscsi_proto.h
+@@ -600,6 +600,8 @@ struct iscsi_reject {
+ #define ISCSI_MIN_MAX_BURST_LEN			512
+ #define ISCSI_MAX_MAX_BURST_LEN			16777215
+ 
++#define ISCSI_DEF_TIME2WAIT			2
++
+ /************************* RFC 3720 End *****************************/
+ 
+ #endif /* ISCSI_PROTO_H */
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index b4b31132618b..89429f433f85 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -57,11 +57,14 @@ struct iscsi_nopin;
+ #define ISCSI_MAX_CMD_PER_LUN		128
+ 
+ /* Task Mgmt states */
+-#define TMABORT_INITIAL			0x0
+-#define TMABORT_SUCCESS			0x1
+-#define TMABORT_FAILED			0x2
+-#define TMABORT_TIMEDOUT		0x3
+-#define TMABORT_NOT_FOUND		0x4
++enum {
++	TMF_INITIAL,
++	TMF_QUEUED,
++	TMF_SUCCESS,
++	TMF_FAILED,
++	TMF_TIMEDOUT,
++	TMF_NOT_FOUND,
++};
+ 
+ /* Connection suspend "bit" */
+ #define ISCSI_SUSPEND_BIT		1
+@@ -91,7 +94,6 @@ enum {
+ 	ISCSI_TASK_COMPLETED,
+ 	ISCSI_TASK_PENDING,
+ 	ISCSI_TASK_RUNNING,
+-	ISCSI_TASK_ABORTING,
+ };
+ 
+ struct iscsi_cmd_task {
+@@ -110,7 +112,6 @@ struct iscsi_cmd_task {
+ 	unsigned		data_count;	/* remaining Data-Out */
+ 	struct scsi_cmnd	*sc;		/* associated SCSI cmd*/
+ 	struct iscsi_conn	*conn;		/* used connection    */
+-	struct iscsi_mgmt_task	*mtask;		/* tmf mtask in progr */
+ 
+ 	/* state set/tested under session->lock */
+ 	int			state;
+@@ -152,10 +153,11 @@ struct iscsi_conn {
+ 	struct iscsi_cmd_task	*ctask;		/* xmit ctask in progress */
+ 
+ 	/* xmit */
+-	struct kfifo		*mgmtqueue;	/* mgmt (control) xmit queue */
++	struct list_head	mgmtqueue;	/* mgmt (control) xmit queue */
+ 	struct list_head	mgmt_run_list;	/* list of control tasks */
+ 	struct list_head	xmitqueue;	/* data-path cmd queue */
+ 	struct list_head	run_list;	/* list of cmds in progress */
++	struct list_head	requeue;	/* tasks needing another run */
+ 	struct work_struct	xmitwork;	/* per-conn. xmit workqueue */
+ 	unsigned long		suspend_tx;	/* suspend Tx */
+ 	unsigned long		suspend_rx;	/* suspend Rx */
+@@ -163,8 +165,8 @@ struct iscsi_conn {
+ 	/* abort */
+ 	wait_queue_head_t	ehwait;		/* used in eh_abort() */
+ 	struct iscsi_tm		tmhdr;
+-	struct timer_list	tmabort_timer;
+-	int			tmabort_state;	/* see TMABORT_INITIAL, etc.*/
++	struct timer_list	tmf_timer;
++	int			tmf_state;	/* see TMF_INITIAL, etc.*/
+ 
+ 	/* negotiated params */
+ 	unsigned		max_recv_dlength; /* initiator_max_recv_dsl*/
+@@ -231,6 +233,7 @@ struct iscsi_session {
+ 	int			pdu_inorder_en;
+ 	int			dataseq_inorder_en;
+ 	int			erl;
++	int			fast_abort;
+ 	int			tpgt;
+ 	char			*username;
+ 	char			*username_in;
+@@ -268,6 +271,7 @@ struct iscsi_session {
+ extern int iscsi_change_queue_depth(struct scsi_device *sdev, int depth);
+ extern int iscsi_eh_abort(struct scsi_cmnd *sc);
+ extern int iscsi_eh_host_reset(struct scsi_cmnd *sc);
++extern int iscsi_eh_device_reset(struct scsi_cmnd *sc);
+ extern int iscsi_queuecommand(struct scsi_cmnd *sc,
+ 			      void (*done)(struct scsi_cmnd *));
+ 
+@@ -326,6 +330,7 @@ extern int __iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *,
+ 				char *, int);
+ extern int iscsi_verify_itt(struct iscsi_conn *, struct iscsi_hdr *,
+ 			    uint32_t *);
++extern void iscsi_requeue_ctask(struct iscsi_cmd_task *ctask);
+ 
+ /*
+  * generic helpers

commit 14816b1e2b0eb24ef41dbe37dcb558338e54a603
+Author: Mike Christie 
+Date:   Wed Nov 28 16:22:06 2007 -0800
+
+    add Mike Christie to MAINTAINERS
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 6b30cb3eac78..ac425b5b4a40 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -2110,6 +2110,14 @@ L:	irda-users@lists.sourceforge.net (subscribers-only)
+ W:	http://irda.sourceforge.net/
+ S:	Maintained
+ 
++ISCSI
++P:	Mike Christie
++M:	michaelc@cs.wisc.edu
++L:	open-iscsi@googlegroups.com
++W:	www.open-iscsi.org
++T:	git kernel.org:/pub/scm/linux/kernel/mnc/linux-2.6-iscsi.git
++S:	Maintained
++
+ ISAPNP
+ P:	Jaroslav Kysela
+ M:	perex@perex.cz

commit bd441deaf341c524b28fd72831ebf6fef88f1c41
+Author: Mike Christie 
+Date:   Tue Mar 13 12:52:29 2007 -0500
+
+    [SCSI] fix write buffer length in scsi_req_map_sg()
+    
+    sg's may have setup a the buffer with a different length than
+    the transfer length so we should be using the bufflen passed
+    in as the request's data len.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index a417a6ff9f97..277f1b64e9ac 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -301,7 +301,7 @@ static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl,
+ {
+ 	struct request_queue *q = rq->q;
+ 	int nr_pages = (bufflen + sgl[0].offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
+-	unsigned int data_len = 0, len, bytes, off;
++	unsigned int data_len = bufflen, len, bytes, off;
+ 	struct page *page;
+ 	struct bio *bio = NULL;
+ 	int i, err, nr_vecs = 0;
+@@ -310,10 +310,15 @@ static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl,
+ 		page = sgl[i].page;
+ 		off = sgl[i].offset;
+ 		len = sgl[i].length;
+-		data_len += len;
+ 
+-		while (len > 0) {
++		while (len > 0 && data_len > 0) {
++			/*
++			 * sg sends a scatterlist that is larger than
++			 * the data_len it wants transferred for certain
++			 * IO sizes
++			 */
+ 			bytes = min_t(unsigned int, len, PAGE_SIZE - off);
++			bytes = min(bytes, data_len);
+ 
+ 			if (!bio) {
+ 				nr_vecs = min_t(int, BIO_MAX_PAGES, nr_pages);
+@@ -345,12 +350,13 @@ static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl,
+ 
+ 			page++;
+ 			len -= bytes;
++			data_len -=bytes;
+ 			off = 0;
+ 		}
+ 	}
+ 
+ 	rq->buffer = rq->data = NULL;
+-	rq->data_len = data_len;
++	rq->data_len = bufflen;
+ 	return 0;
+ 
+ free_bios:

commit 6724add1b5cfb020ba8f5532efe430d1ccd5fc30
+Author: Mike Christie 
+Date:   Wed Aug 15 01:38:30 2007 -0500
+
+    [SCSI] libiscsi: sync up iscsi and scsi eh's access to the connection
+    
+    The iscsi eh could be tearing down the session/connection while
+    the scsi eh is still sending task management functions. If when
+    we drop the session lock to grab the recv lock, the iscsi eh
+    tears down the connection we will oops.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index f5915d4d63d9..efceed451b46 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1056,7 +1056,9 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc,
+ 	ctask->mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr,
+ 					    NULL, 0);
+ 	if (!ctask->mtask) {
++		spin_unlock_bh(&session->lock);
+ 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
++		spin_lock_bh(&session->lock)
+ 		debug_scsi("abort sent failure [itt 0x%x]\n", ctask->itt);
+ 		return -EPERM;
+ 	}
+@@ -1073,6 +1075,7 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc,
+ 		debug_scsi("abort set timeout [itt 0x%x]\n", ctask->itt);
+ 	}
+ 	spin_unlock_bh(&session->lock);
++	mutex_unlock(&session->eh_mutex);
+ 	scsi_queue_work(session->host, &conn->xmitwork);
+ 
+ 	/*
+@@ -1090,6 +1093,7 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc,
+ 	if (signal_pending(current))
+ 		flush_signals(current);
+ 	del_timer_sync(&conn->tmabort_timer);
++	mutex_lock(&session->eh_mutex);
+ 	spin_lock_bh(&session->lock);
+ 	return 0;
+ }
+@@ -1165,31 +1169,45 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 	__iscsi_put_ctask(ctask);
+ }
+ 
++static void iscsi_suspend_tx(struct iscsi_conn *conn)
++{
++	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
++	scsi_flush_work(conn->session->host);
++}
++
++static void iscsi_start_tx(struct iscsi_conn *conn)
++{
++	clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
++	scsi_queue_work(conn->session->host, &conn->xmitwork);
++}
++
+ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ {
++	struct Scsi_Host *host = sc->device->host;
++	struct iscsi_session *session = iscsi_hostdata(host->hostdata);
+ 	struct iscsi_cmd_task *ctask;
+ 	struct iscsi_conn *conn;
+-	struct iscsi_session *session;
+ 	int rc;
+ 
++	mutex_lock(&session->eh_mutex);
++	spin_lock_bh(&session->lock);
+ 	/*
+ 	 * if session was ISCSI_STATE_IN_RECOVERY then we may not have
+ 	 * got the command.
+ 	 */
+ 	if (!sc->SCp.ptr) {
+ 		debug_scsi("sc never reached iscsi layer or it completed.\n");
++		spin_unlock_bh(&session->lock);
++		mutex_unlock(&session->eh_mutex);
+ 		return SUCCESS;
+ 	}
+ 
+ 	ctask = (struct iscsi_cmd_task *)sc->SCp.ptr;
+ 	conn = ctask->conn;
+-	session = conn->session;
+ 
+ 	conn->eh_abort_cnt++;
+ 	debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt);
+ 
+-	spin_lock_bh(&session->lock);
+-
+ 	/*
+ 	 * If we are not logged in or we have started a new session
+ 	 * then let the host reset code handle this
+@@ -1226,6 +1244,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 	switch (conn->tmabort_state) {
+ 	case TMABORT_SUCCESS:
+ 		spin_unlock_bh(&session->lock);
++		iscsi_suspend_tx(conn);
+ 		/*
+ 		 * clean up task if aborted. grab the recv lock as a writer
+ 		 */
+@@ -1234,11 +1253,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 		fail_command(conn, ctask, DID_ABORT << 16);
+ 		spin_unlock(&session->lock);
+ 		write_unlock_bh(conn->recv_lock);
+-		/*
+-		 * make sure xmit thread is not still touching the
+-		 * ctask/scsi_cmnd
+-		 */
+-		scsi_flush_work(session->host);
++		iscsi_start_tx(conn);
+ 		goto success_unlocked;
+ 	case TMABORT_NOT_FOUND:
+ 		if (!ctask->sc) {
+@@ -1258,12 +1273,14 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 	spin_unlock_bh(&session->lock);
+ success_unlocked:
+ 	debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
++	mutex_unlock(&session->eh_mutex);
+ 	return SUCCESS;
+ 
+ failed:
+ 	spin_unlock_bh(&session->lock);
+ failed_unlocked:
+ 	debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
++	mutex_unlock(&session->eh_mutex);
+ 	return FAILED;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_eh_abort);
+@@ -1410,6 +1427,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
+ 	session->max_cmdsn = initial_cmdsn + 1;
+ 	session->max_r2t = 1;
+ 	session->tt = iscsit;
++	mutex_init(&session->eh_mutex);
+ 
+ 	/* initialize SCSI PDU commands pool */
+ 	if (iscsi_pool_init(&session->cmdpool, session->cmds_max,
+@@ -1743,9 +1761,22 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ {
+ 	int old_stop_stage;
+ 
++	mutex_lock(&session->eh_mutex);
+ 	spin_lock_bh(&session->lock);
+ 	if (conn->stop_stage == STOP_CONN_TERM) {
+ 		spin_unlock_bh(&session->lock);
++		mutex_unlock(&session->eh_mutex);
++		return;
++	}
++
++	/*
++	 * The LLD either freed/unset the lock on us, or userspace called
++	 * stop but did not create a proper connection (connection was never
++	 * bound or it was unbound then stop was called).
++	 */
++	if (!conn->recv_lock) {
++		spin_unlock_bh(&session->lock);
++		mutex_unlock(&session->eh_mutex);
+ 		return;
+ 	}
+ 
+@@ -1762,9 +1793,9 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ 	old_stop_stage = conn->stop_stage;
+ 	conn->stop_stage = flag;
+ 	conn->c_stage = ISCSI_CONN_STOPPED;
+-	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+ 	spin_unlock_bh(&session->lock);
+-	scsi_flush_work(session->host);
++
++	iscsi_suspend_tx(conn);
+ 
+ 	write_lock_bh(conn->recv_lock);
+ 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
+@@ -1793,6 +1824,7 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ 	fail_all_commands(conn);
+ 	flush_control_queues(session, conn);
+ 	spin_unlock_bh(&session->lock);
++	mutex_unlock(&session->eh_mutex);
+ }
+ 
+ void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 007d442412e2..b4b31132618b 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -205,6 +205,13 @@ struct iscsi_queue {
+ };
+ 
+ struct iscsi_session {
++	/*
++	 * Syncs up the scsi eh thread with the iscsi eh thread when sending
++	 * task management functions. This must be taken before the session
++	 * and recv lock.
++	 */
++	struct mutex		eh_mutex;
++
+ 	/* iSCSI session-wide sequencing */
+ 	uint32_t		cmdsn;
+ 	uint32_t		exp_cmdsn;

commit 96809f1b15eddae2325b2ab78e6f931edc969074
+Author: Mike Christie 
+Date:   Wed Aug 15 01:38:29 2007 -0500
+
+    [SCSI] libiscsi: fix null ptr regression when aborting a command with data to transfer
+    
+    We do not want to send data if we are aborting a task. There is
+    a check in iscsi_xmit_ctask, but right before calling this we overwrite
+    the state so we always go right past the test. Sending data causes problems
+    because when we clean up from a successful abort the LLD assumes that
+    the task is not running.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 5606d1e62978..f5915d4d63d9 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -737,12 +737,19 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 		 */
+ 		conn->ctask = list_entry(conn->xmitqueue.next,
+ 					 struct iscsi_cmd_task, running);
+-		if (conn->ctask->state == ISCSI_TASK_PENDING) {
++		switch (conn->ctask->state) {
++		case ISCSI_TASK_ABORTING:
++			break;
++		case ISCSI_TASK_PENDING:
+ 			iscsi_prep_scsi_cmd_pdu(conn->ctask);
+ 			conn->session->tt->init_cmd_task(conn->ctask);
++			/* fall through */
++		default:
++			conn->ctask->state = ISCSI_TASK_RUNNING;
++			break;
+ 		}
+-		conn->ctask->state = ISCSI_TASK_RUNNING;
+ 		list_move_tail(conn->xmitqueue.next, &conn->run_list);
++
+ 		rc = iscsi_xmit_ctask(conn);
+ 		if (rc)
+ 			goto again;

commit b6d44fe9582b9d90a0b16f508ac08a90d899bf56
+Author: Mike Christie 
+Date:   Thu Jul 26 12:46:47 2007 -0500
+
+    [SCSI] iscsi_tcp: Turn off bounce buffers
+    
+    It was found by LSI that on setups with large amounts of memory
+    we were bouncing buffers when we did not need to. If the iscsi tcp
+    code touches the data buffer (or a helper does),
+    it will kmap the buffer. iscsi_tcp also does not interact with hardware,
+    so it does not have any hw dma restrictions. This patch sets the bounce
+    buffer settings for our device queue so buffers should not be bounced
+    because of a driver limit.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 93034b43effc..a21455d0274c 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -2216,6 +2216,7 @@ static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session)
+ 
+ static int iscsi_tcp_slave_configure(struct scsi_device *sdev)
+ {
++	blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_ANY);
+ 	blk_queue_dma_alignment(sdev->request_queue, 0);
+ 	return 0;
+ }

commit e07264071f7f2b02a2973cb28d9fdf5eb8866cc1
+Author: Mike Christie 
+Date:   Thu Jul 26 12:46:48 2007 -0500
+
+    [SCSI] libiscsi: fix cmd seqeunce number checking
+    
+    We should not be checking the cmd windown for just handling r2t responses.
+    And if the window closes in on us, always have scsi-ml requeue the command
+    from our queuecommand function.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 271a2d671b89..5606d1e62978 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -596,9 +596,16 @@ static void iscsi_prep_mtask(struct iscsi_conn *conn,
+ 	nop->cmdsn = cpu_to_be32(session->cmdsn);
+ 	if (hdr->itt != RESERVED_ITT) {
+ 		hdr->itt = build_itt(mtask->itt, conn->id, session->age);
++		/*
++		 * TODO: We always use immediate, so we never hit this.
++		 * If we start to send tmfs or nops as non-immediate then
++		 * we should start checking the cmdsn numbers for mgmt tasks.
++		 */
+ 		if (conn->c_stage == ISCSI_CONN_STARTED &&
+-		    !(hdr->opcode & ISCSI_OP_IMMEDIATE))
++		    !(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
++			session->queued_cmdsn++;
+ 			session->cmdsn++;
++		}
+ 	}
+ 
+ 	if (session->tt->init_mgmt_task)
+@@ -641,9 +648,11 @@ static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn)
+ 	/*
+ 	 * Check for iSCSI window and take care of CmdSN wrap-around
+ 	 */
+-	if (!iscsi_sna_lte(session->cmdsn, session->max_cmdsn)) {
+-		debug_scsi("iSCSI CmdSN closed. MaxCmdSN %u CmdSN %u\n",
+-			   session->max_cmdsn, session->cmdsn);
++	if (!iscsi_sna_lte(session->queued_cmdsn, session->max_cmdsn)) {
++		debug_scsi("iSCSI CmdSN closed. ExpCmdSn %u MaxCmdSN %u "
++			   "CmdSN %u/%u\n", session->exp_cmdsn,
++			   session->max_cmdsn, session->cmdsn,
++			   session->queued_cmdsn);
+ 		return -ENOSPC;
+ 	}
+ 	return 0;
+@@ -722,11 +731,6 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 
+ 	/* process command queue */
+ 	while (!list_empty(&conn->xmitqueue)) {
+-		rc = iscsi_check_cmdsn_window_closed(conn);
+-		if (rc) {
+-			spin_unlock_bh(&conn->session->lock);
+-			return rc;
+-		}
+ 		/*
+ 		 * iscsi tcp may readd the task to the xmitqueue to send
+ 		 * write data
+@@ -834,12 +838,6 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 		goto fault;
+ 	}
+ 
+-	/*
+-	 * We check this here and in data xmit, because if we get to the point
+-	 * that this check is hitting the window then we have enough IO in
+-	 * flight and enough IO waiting to be transmitted it is better
+-	 * to let the scsi/block layer queue up.
+-	 */
+ 	if (iscsi_check_cmdsn_window_closed(conn)) {
+ 		reason = FAILURE_WINDOW_CLOSED;
+ 		goto reject;
+@@ -850,6 +848,8 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 		reason = FAILURE_OOM;
+ 		goto reject;
+ 	}
++	session->queued_cmdsn++;
++
+ 	sc->SCp.phase = session->age;
+ 	sc->SCp.ptr = (char *)ctask;
+ 
+@@ -1140,7 +1140,13 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 	if (!sc)
+ 		return;
+ 
+-	if (ctask->state != ISCSI_TASK_PENDING)
++	if (ctask->state == ISCSI_TASK_PENDING)
++		/*
++		 * cmd never made it to the xmit thread, so we should not count
++		 * the cmd in the sequencing
++		 */
++		conn->session->queued_cmdsn--;
++	else
+ 		conn->session->tt->cleanup_cmd_task(conn, ctask);
+ 	iscsi_ctask_mtask_cleanup(ctask);
+ 
+@@ -1392,7 +1398,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
+ 	session->state = ISCSI_STATE_FREE;
+ 	session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
+ 	session->cmds_max = cmds_max;
+-	session->cmdsn = initial_cmdsn;
++	session->queued_cmdsn = session->cmdsn = initial_cmdsn;
+ 	session->exp_cmdsn = initial_cmdsn + 1;
+ 	session->max_cmdsn = initial_cmdsn + 1;
+ 	session->max_r2t = 1;
+@@ -1616,11 +1622,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
+ 	kfree(conn->persistent_address);
+ 	__kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask,
+ 		    sizeof(void*));
+-	if (session->leadconn == conn) {
++	if (session->leadconn == conn)
+ 		session->leadconn = NULL;
+-		/* no connections exits.. reset sequencing */
+-		session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1;
+-	}
+ 	spin_unlock_bh(&session->lock);
+ 
+ 	kfifo_free(conn->mgmtqueue);
+@@ -1650,6 +1653,7 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
+ 	spin_lock_bh(&session->lock);
+ 	conn->c_stage = ISCSI_CONN_STARTED;
+ 	session->state = ISCSI_STATE_LOGGED_IN;
++	session->queued_cmdsn = session->cmdsn;
+ 
+ 	switch(conn->stop_stage) {
+ 	case STOP_CONN_RECOVER:
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 3f631b08a1ab..007d442412e2 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -210,6 +210,9 @@ struct iscsi_session {
+ 	uint32_t		exp_cmdsn;
+ 	uint32_t		max_cmdsn;
+ 
++	/* This tracks the reqs queued into the initiator */
++	uint32_t		queued_cmdsn;
++
+ 	/* configuration */
+ 	int			initial_r2t_en;
+ 	unsigned		max_r2t;

commit 7974392c0b0d4e7a2a17ca3597d51a29b9841aa5
+Author: Mike Christie 
+Date:   Thu Jul 26 12:46:46 2007 -0500
+
+    [SCSI] iscsi_tcp, ib_iser Enable module refcounting for iscsi host template
+    
+    This prevents the iscsi modules from being unloaded while
+    there are active mounts from an iscsi target.
+    
+    Signed-off-by: Olaf Kirch 
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 5db314380271..bad8dacafd10 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -548,6 +548,7 @@ iscsi_iser_ep_disconnect(__u64 ep_handle)
+ }
+ 
+ static struct scsi_host_template iscsi_iser_sht = {
++	.module                 = THIS_MODULE,
+ 	.name                   = "iSCSI Initiator over iSER, v." DRV_VER,
+ 	.queuecommand           = iscsi_queuecommand,
+ 	.can_queue		= ISCSI_DEF_XMIT_CMDS_MAX - 1,
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 7829ab1e2fb4..93034b43effc 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -2221,6 +2221,7 @@ static int iscsi_tcp_slave_configure(struct scsi_device *sdev)
+ }
+ 
+ static struct scsi_host_template iscsi_sht = {
++	.module			= THIS_MODULE,
+ 	.name			= "iSCSI Initiator over TCP/IP",
+ 	.queuecommand           = iscsi_queuecommand,
+ 	.change_queue_depth	= iscsi_change_queue_depth,

commit 464bb99ea448dc2f017be9150a8be9ab1f021979
+Author: Mike Christie 
+Date:   Thu Jul 26 12:46:45 2007 -0500
+
+    [SCSI] libiscsi: make sure session is not blocked when removing host
+    
+    When we logout we block the session since we are not taking any more
+    commands, but when we call remove host we want to make sure any
+    IO that got queued up and blocked gets failed upwards quickly, so
+    we unblock the session and fail it.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 4d85ce100192..271a2d671b89 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1473,6 +1473,7 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+ 	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+ 	struct module *owner = cls_session->transport->owner;
+ 
++	iscsi_unblock_session(cls_session);
+ 	scsi_remove_host(shost);
+ 
+ 	iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);

commit d8196ed2181b4595eaf464a5bcbddb6c28649a39
+Author: Mike Christie 
+Date:   Wed May 30 12:57:25 2007 -0500
+
+    [SCSI] iscsi class, iscsi_tcp, iser, qla4xxx: add netdevname sysfs attr
+    
+    iSCSI must support software iscsi (iscsi_tcp, iser), hardware iscsi (qla4xxx),
+    and partial offload (broadcom). To be able to allow each stack or driver
+    or port (virtual or physical) to be able to log into the same target portal
+    we use the initiator tuple [[HWADDRESS | NETDEVNAME], INITIATOR_NAME] and
+    the target tuple [TARGETNAME, CONN_ADDRESS, CONN_PORT] to id a session.
+    This patch adds the netdev name, which is used by software iscsi when
+    it binds a session to a netdevice using the SO_BINDTODEVICE sock opt.
+    It cannot use HWADDRESS because if someone did vlans then the same netdevice
+    will have the same mac and the initiator,target id will not be unique.
+    
+    Signed-off-by: Mike Christie 
+    Cc: Roland Dreier 
+    Cc: David C Somayajulu 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index bed583c426e6..1bf173decade 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -583,6 +583,7 @@ static struct iscsi_transport iscsi_iser_transport = {
+ 				  ISCSI_USERNAME | ISCSI_PASSWORD |
+ 				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS |
++				  ISCSI_HOST_NETDEV_NAME |
+ 				  ISCSI_HOST_INITIATOR_NAME,
+ 	.host_template          = &iscsi_iser_sht,
+ 	.conndata_size		= sizeof(struct iscsi_conn),
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index da66fb524b5b..d5a6527b3b3d 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -2303,7 +2303,8 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 				  ISCSI_USERNAME | ISCSI_PASSWORD |
+ 				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+-				  ISCSI_HOST_INITIATOR_NAME,
++				  ISCSI_HOST_INITIATOR_NAME |
++				  ISCSI_HOST_NETDEV_NAME,
+ 	.host_template		= &iscsi_sht,
+ 	.conndata_size		= sizeof(struct iscsi_conn),
+ 	.max_conn		= 1,
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 1632866f52cc..865dd5739f0e 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1483,6 +1483,7 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+ 	kfree(session->username);
+ 	kfree(session->username_in);
+ 	kfree(session->targetname);
++	kfree(session->netdev);
+ 	kfree(session->hwaddress);
+ 	kfree(session->initiatorname);
+ 
+@@ -2040,6 +2041,12 @@ int iscsi_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param,
+ 	int len;
+ 
+ 	switch (param) {
++	case ISCSI_HOST_PARAM_NETDEV_NAME:
++		if (!session->netdev)
++			len = sprintf(buf, "%s\n", "default");
++		else
++			len = sprintf(buf, "%s\n", session->netdev);
++		break;
+ 	case ISCSI_HOST_PARAM_HWADDRESS:
+ 		if (!session->hwaddress)
+ 			len = sprintf(buf, "%s\n", "default");
+@@ -2067,6 +2074,10 @@ int iscsi_host_set_param(struct Scsi_Host *shost, enum iscsi_host_param param,
+ 	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+ 
+ 	switch (param) {
++	case ISCSI_HOST_PARAM_NETDEV_NAME:
++		if (!session->netdev)
++			session->netdev = kstrdup(buf, GFP_KERNEL);
++		break;
+ 	case ISCSI_HOST_PARAM_HWADDRESS:
+ 		if (!session->hwaddress)
+ 			session->hwaddress = kstrdup(buf, GFP_KERNEL);
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index b87b460832ea..e69160a7bc60 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -102,7 +102,8 @@ static struct scsi_host_template qla4xxx_driver_template = {
+ static struct iscsi_transport qla4xxx_iscsi_transport = {
+ 	.owner			= THIS_MODULE,
+ 	.name			= DRIVER_NAME,
+-	.caps			= CAP_FW_DB | CAP_SENDTARGETS_OFFLOAD,
++	.caps			= CAP_FW_DB | CAP_SENDTARGETS_OFFLOAD |
++				  CAP_DATA_PATH_OFFLOAD,
+ 	.param_mask		= ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS |
+ 				  ISCSI_TARGET_NAME | ISCSI_TPGT,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS |
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 9b54eea20560..34c1860a259d 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -32,7 +32,7 @@
+ 
+ #define ISCSI_SESSION_ATTRS 15
+ #define ISCSI_CONN_ATTRS 11
+-#define ISCSI_HOST_ATTRS 3
++#define ISCSI_HOST_ATTRS 4
+ #define ISCSI_TRANSPORT_VERSION "2.0-724"
+ 
+ struct iscsi_internal {
+@@ -1261,8 +1261,9 @@ show_host_param_##param(struct class_device *cdev, char *buf)		\
+ static ISCSI_CLASS_ATTR(host, field, S_IRUGO, show_host_param_##param,	\
+ 			NULL);
+ 
+-iscsi_host_attr(ipaddress, ISCSI_HOST_PARAM_IPADDRESS);
++iscsi_host_attr(netdev, ISCSI_HOST_PARAM_NETDEV_NAME);
+ iscsi_host_attr(hwaddress, ISCSI_HOST_PARAM_HWADDRESS);
++iscsi_host_attr(ipaddress, ISCSI_HOST_PARAM_IPADDRESS);
+ iscsi_host_attr(initiatorname, ISCSI_HOST_PARAM_INITIATOR_NAME);
+ 
+ #define SETUP_PRIV_SESSION_RD_ATTR(field)				\
+@@ -1399,6 +1400,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 	priv->t.host_size = sizeof(struct iscsi_host);
+ 	transport_container_register(&priv->t.host_attrs);
+ 
++	SETUP_HOST_RD_ATTR(netdev, ISCSI_HOST_NETDEV_NAME);
+ 	SETUP_HOST_RD_ATTR(ipaddress, ISCSI_HOST_IPADDRESS);
+ 	SETUP_HOST_RD_ATTR(hwaddress, ISCSI_HOST_HWADDRESS);
+ 	SETUP_HOST_RD_ATTR(initiatorname, ISCSI_HOST_INITIATOR_NAME);
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index 642998069e00..50e907f42048 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -271,12 +271,14 @@ enum iscsi_param {
+ enum iscsi_host_param {
+ 	ISCSI_HOST_PARAM_HWADDRESS,
+ 	ISCSI_HOST_PARAM_INITIATOR_NAME,
++	ISCSI_HOST_PARAM_NETDEV_NAME,
+ 	ISCSI_HOST_PARAM_IPADDRESS,
+ 	ISCSI_HOST_PARAM_MAX,
+ };
+ 
+ #define ISCSI_HOST_HWADDRESS		(1 << ISCSI_HOST_PARAM_HWADDRESS)
+ #define ISCSI_HOST_INITIATOR_NAME	(1 << ISCSI_HOST_PARAM_INITIATOR_NAME)
++#define ISCSI_HOST_NETDEV_NAME		(1 << ISCSI_HOST_PARAM_NETDEV_NAME)
+ #define ISCSI_HOST_IPADDRESS		(1 << ISCSI_HOST_PARAM_IPADDRESS)
+ 
+ #define iscsi_ptr(_handle) ((void*)(unsigned long)_handle)
+@@ -303,6 +305,7 @@ enum iscsi_host_param {
+ #define CAP_MARKERS		0x100
+ #define CAP_FW_DB		0x200
+ #define CAP_SENDTARGETS_OFFLOAD	0x400
++#define CAP_DATA_PATH_OFFLOAD	0x800
+ 
+ /*
+  * These flags describes reason of stop_conn() call
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index eea33f7b1544..3f631b08a1ab 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -228,8 +228,9 @@ struct iscsi_session {
+ 	char			*password_in;
+ 	char			*targetname;
+ 	char			*initiatorname;
+-	/* hw address being used for iscsi connection */
++	/* hw address or netdev iscsi connection is bound to */
+ 	char			*hwaddress;
++	char			*netdev;
+ 	/* control data */
+ 	struct iscsi_transport	*tt;
+ 	struct Scsi_Host	*host;

commit 2223696192c687f2853e42b7c1e0d3ef002081fd
+Author: Mike Christie 
+Date:   Wed May 30 12:57:24 2007 -0500
+
+    [SCSI] iscsi class, qla4xxx, iscsi_tcp: export local address
+    
+    This patch exports the local address for the session. For
+    qla4xxx this is the ip of the hba's port. For software
+    this is the src addr of the socket.
+    
+    Signed-off-by: Mike Christie 
+    Cc: David C Somayajulu 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 7ce177e30a53..da66fb524b5b 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -1870,18 +1870,22 @@ iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ static void
+ iscsi_tcp_release_conn(struct iscsi_conn *conn)
+ {
++	struct iscsi_session *session = conn->session;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	struct socket *sock = tcp_conn->sock;
+ 
+-	if (!tcp_conn->sock)
++	if (!sock)
+ 		return;
+ 
+-	sock_hold(tcp_conn->sock->sk);
++	sock_hold(sock->sk);
+ 	iscsi_conn_restore_callbacks(tcp_conn);
+-	sock_put(tcp_conn->sock->sk);
++	sock_put(sock->sk);
+ 
+-	sockfd_put(tcp_conn->sock);
++	spin_lock_bh(&session->lock);
+ 	tcp_conn->sock = NULL;
+ 	conn->recv_lock = NULL;
++	spin_unlock_bh(&session->lock);
++	sockfd_put(sock);
+ }
+ 
+ static void
+@@ -1912,6 +1916,46 @@ iscsi_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+ 	tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
+ }
+ 
++static int iscsi_tcp_get_addr(struct iscsi_conn *conn, struct socket *sock,
++			      char *buf, int *port,
++			      int (*getname)(struct socket *, struct sockaddr *,
++					int *addrlen))
++{
++	struct sockaddr_storage *addr;
++	struct sockaddr_in6 *sin6;
++	struct sockaddr_in *sin;
++	int rc = 0, len;
++
++	addr = kmalloc(GFP_KERNEL, sizeof(*addr));
++	if (!addr)
++		return -ENOMEM;
++
++	if (getname(sock, (struct sockaddr *) addr, &len)) {
++		rc = -ENODEV;
++		goto free_addr;
++	}
++
++	switch (addr->ss_family) {
++	case AF_INET:
++		sin = (struct sockaddr_in *)addr;
++		spin_lock_bh(&conn->session->lock);
++		sprintf(buf, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr));
++		*port = be16_to_cpu(sin->sin_port);
++		spin_unlock_bh(&conn->session->lock);
++		break;
++	case AF_INET6:
++		sin6 = (struct sockaddr_in6 *)addr;
++		spin_lock_bh(&conn->session->lock);
++		sprintf(buf, NIP6_FMT, NIP6(sin6->sin6_addr));
++		*port = be16_to_cpu(sin6->sin6_port);
++		spin_unlock_bh(&conn->session->lock);
++		break;
++	}
++free_addr:
++	kfree(addr);
++	return rc;
++}
++
+ static int
+ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
+ 		    struct iscsi_cls_conn *cls_conn, uint64_t transport_eph,
+@@ -1929,10 +1973,24 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
+ 		printk(KERN_ERR "iscsi_tcp: sockfd_lookup failed %d\n", err);
+ 		return -EEXIST;
+ 	}
++	/*
++	 * copy these values now because if we drop the session
++	 * userspace may still want to query the values since we will
++	 * be using them for the reconnect
++	 */
++	err = iscsi_tcp_get_addr(conn, sock, conn->portal_address,
++				 &conn->portal_port, kernel_getpeername);
++	if (err)
++		goto free_socket;
++
++	err = iscsi_tcp_get_addr(conn, sock, conn->local_address,
++				&conn->local_port, kernel_getsockname);
++	if (err)
++		goto free_socket;
+ 
+ 	err = iscsi_conn_bind(cls_session, cls_conn, is_leading);
+ 	if (err)
+-		return err;
++		goto free_socket;
+ 
+ 	/* bind iSCSI connection and socket */
+ 	tcp_conn->sock = sock;
+@@ -1956,8 +2014,11 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
+ 	 * set receive state machine into initial state
+ 	 */
+ 	tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
+-
+ 	return 0;
++
++free_socket:
++	sockfd_put(sock);
++	return err;
+ }
+ 
+ /* called with host lock */
+@@ -2077,33 +2138,18 @@ iscsi_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ 			 enum iscsi_param param, char *buf)
+ {
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+-	struct inet_sock *inet;
+-	struct ipv6_pinfo *np;
+-	struct sock *sk;
+ 	int len;
+ 
+ 	switch(param) {
+ 	case ISCSI_PARAM_CONN_PORT:
+-		if (!tcp_conn->sock)
+-			return -EINVAL;
+-
+-		inet = inet_sk(tcp_conn->sock->sk);
+-		len = sprintf(buf, "%hu\n", be16_to_cpu(inet->dport));
++		spin_lock_bh(&conn->session->lock);
++		len = sprintf(buf, "%hu\n", conn->portal_port);
++		spin_unlock_bh(&conn->session->lock);
+ 		break;
+ 	case ISCSI_PARAM_CONN_ADDRESS:
+-		if (!tcp_conn->sock)
+-			return -EINVAL;
+-
+-		sk = tcp_conn->sock->sk;
+-		if (sk->sk_family == PF_INET) {
+-			inet = inet_sk(sk);
+-			len = sprintf(buf, NIPQUAD_FMT "\n",
+-				      NIPQUAD(inet->daddr));
+-		} else {
+-			np = inet6_sk(sk);
+-			len = sprintf(buf, NIP6_FMT "\n", NIP6(np->daddr));
+-		}
++		spin_lock_bh(&conn->session->lock);
++		len = sprintf(buf, "%s\n", conn->portal_address);
++		spin_unlock_bh(&conn->session->lock);
+ 		break;
+ 	default:
+ 		return iscsi_conn_get_param(cls_conn, param, buf);
+@@ -2112,6 +2158,29 @@ iscsi_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ 	return len;
+ }
+ 
++static int
++iscsi_tcp_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param,
++			 char *buf)
++{
++        struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
++	int len;
++
++	switch (param) {
++	case ISCSI_HOST_PARAM_IPADDRESS:
++		spin_lock_bh(&session->lock);
++		if (!session->leadconn)
++			len = -ENODEV;
++		else
++			len = sprintf(buf, "%s\n",
++				     session->leadconn->local_address);
++		spin_unlock_bh(&session->lock);
++		break;
++	default:
++		return iscsi_host_get_param(shost, param, buf);
++	}
++	return len;
++}
++
+ static void
+ iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats)
+ {
+@@ -2233,7 +2302,7 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 				  ISCSI_TARGET_NAME | ISCSI_TPGT |
+ 				  ISCSI_USERNAME | ISCSI_PASSWORD |
+ 				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN,
+-	.host_param_mask	= ISCSI_HOST_HWADDRESS |
++	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+ 				  ISCSI_HOST_INITIATOR_NAME,
+ 	.host_template		= &iscsi_sht,
+ 	.conndata_size		= sizeof(struct iscsi_conn),
+@@ -2252,7 +2321,7 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 	.start_conn		= iscsi_conn_start,
+ 	.stop_conn		= iscsi_tcp_conn_stop,
+ 	/* iscsi host params */
+-	.get_host_param		= iscsi_host_get_param,
++	.get_host_param		= iscsi_tcp_host_get_param,
+ 	.set_host_param		= iscsi_host_set_param,
+ 	/* IO */
+ 	.send_pdu		= iscsi_conn_send_pdu,
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index 315ab691056f..b87b460832ea 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -106,6 +106,7 @@ static struct iscsi_transport qla4xxx_iscsi_transport = {
+ 	.param_mask		= ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS |
+ 				  ISCSI_TARGET_NAME | ISCSI_TPGT,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS |
++				  ISCSI_HOST_IPADDRESS |
+ 				  ISCSI_HOST_INITIATOR_NAME,
+ 	.sessiondata_size	= sizeof(struct ddb_entry),
+ 	.host_template		= &qla4xxx_driver_template,
+@@ -192,8 +193,13 @@ static int qla4xxx_host_get_param(struct Scsi_Host *shost,
+ 	case ISCSI_HOST_PARAM_HWADDRESS:
+ 		len = format_addr(buf, ha->my_mac, MAC_ADDR_LEN);
+ 		break;
++	case ISCSI_HOST_PARAM_IPADDRESS:
++		len = sprintf(buf, "%d.%d.%d.%d\n", ha->ip_address[0],
++			      ha->ip_address[1], ha->ip_address[2],
++			      ha->ip_address[3]);
++		break;
+ 	case ISCSI_HOST_PARAM_INITIATOR_NAME:
+-		len = sprintf(buf, ha->name_string);
++		len = sprintf(buf, "%s\n", ha->name_string);
+ 		break;
+ 	default:
+ 		return -ENOSYS;
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 859bd2100856..9b54eea20560 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -32,7 +32,7 @@
+ 
+ #define ISCSI_SESSION_ATTRS 15
+ #define ISCSI_CONN_ATTRS 11
+-#define ISCSI_HOST_ATTRS 2
++#define ISCSI_HOST_ATTRS 3
+ #define ISCSI_TRANSPORT_VERSION "2.0-724"
+ 
+ struct iscsi_internal {
+@@ -1261,6 +1261,7 @@ show_host_param_##param(struct class_device *cdev, char *buf)		\
+ static ISCSI_CLASS_ATTR(host, field, S_IRUGO, show_host_param_##param,	\
+ 			NULL);
+ 
++iscsi_host_attr(ipaddress, ISCSI_HOST_PARAM_IPADDRESS);
+ iscsi_host_attr(hwaddress, ISCSI_HOST_PARAM_HWADDRESS);
+ iscsi_host_attr(initiatorname, ISCSI_HOST_PARAM_INITIATOR_NAME);
+ 
+@@ -1398,6 +1399,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 	priv->t.host_size = sizeof(struct iscsi_host);
+ 	transport_container_register(&priv->t.host_attrs);
+ 
++	SETUP_HOST_RD_ATTR(ipaddress, ISCSI_HOST_IPADDRESS);
+ 	SETUP_HOST_RD_ATTR(hwaddress, ISCSI_HOST_HWADDRESS);
+ 	SETUP_HOST_RD_ATTR(initiatorname, ISCSI_HOST_INITIATOR_NAME);
+ 	BUG_ON(count > ISCSI_HOST_ATTRS);
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index 81a542506dfe..642998069e00 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -271,11 +271,13 @@ enum iscsi_param {
+ enum iscsi_host_param {
+ 	ISCSI_HOST_PARAM_HWADDRESS,
+ 	ISCSI_HOST_PARAM_INITIATOR_NAME,
++	ISCSI_HOST_PARAM_IPADDRESS,
+ 	ISCSI_HOST_PARAM_MAX,
+ };
+ 
+ #define ISCSI_HOST_HWADDRESS		(1 << ISCSI_HOST_PARAM_HWADDRESS)
+ #define ISCSI_HOST_INITIATOR_NAME	(1 << ISCSI_HOST_PARAM_INITIATOR_NAME)
++#define ISCSI_HOST_IPADDRESS		(1 << ISCSI_HOST_PARAM_IPADDRESS)
+ 
+ #define iscsi_ptr(_handle) ((void*)(unsigned long)_handle)
+ #define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr)
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 2f303a3b270e..eea33f7b1544 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -72,6 +72,8 @@ struct iscsi_nopin;
+ #define ISCSI_AGE_SHIFT			28
+ #define ISCSI_AGE_MASK			(0xf << ISCSI_AGE_SHIFT)
+ 
++#define ISCSI_ADDRESS_BUF_LEN		64
++
+ struct iscsi_mgmt_task {
+ 	/*
+ 	 * Becuae LLDs allocate their hdr differently, this is a pointer to
+@@ -174,6 +176,12 @@ struct iscsi_conn {
+ 	/* values userspace uses to id a conn */
+ 	int			persistent_port;
+ 	char			*persistent_address;
++	/* remote portal currently connected to */
++	int			portal_port;
++	char			portal_address[ISCSI_ADDRESS_BUF_LEN];
++	/* local address */
++	int			local_port;
++	char			local_address[ISCSI_ADDRESS_BUF_LEN];
+ 
+ 	/* MIB-statistics */
+ 	uint64_t		txdata_octets;

commit 4e7aba73f9f6e9fe6d3fa10d3fd63cd4882ba3d0
+Author: Mike Christie 
+Date:   Wed May 30 12:57:23 2007 -0500
+
+    [SCSI] iscsi_tcp: fix fd leak
+    
+    This patch should fix the file descriptor leak problem. A quick look
+    through the kernel shows that users of sockfd_lookup use sockfd_put to
+    release their handle. We were using sock_release which from the comments
+    and code look like it does not release the get() on the file from the
+    lookup.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 4e9f0d9a55ea..7ce177e30a53 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -29,6 +29,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -1878,7 +1879,7 @@ iscsi_tcp_release_conn(struct iscsi_conn *conn)
+ 	iscsi_conn_restore_callbacks(tcp_conn);
+ 	sock_put(tcp_conn->sock->sk);
+ 
+-	sock_release(tcp_conn->sock);
++	sockfd_put(tcp_conn->sock);
+ 	tcp_conn->sock = NULL;
+ 	conn->recv_lock = NULL;
+ }

commit 0ab823db869f1c9454c5b031a9b8f8812ccd0aa7
+Author: Mike Christie 
+Date:   Wed May 30 12:57:22 2007 -0500
+
+    [SCSI] qla4xxx: add iscsi_transport capps for fw capacilities
+    
+    Userspace will want to know what the driver/FW/HW capabilites
+    when it comes to some operations like if the hardware can
+    do discovery or if it can store iscsi info like what target
+    was used for boot. This patch adds some new caps so userspace
+    can tell if the driver supports hardware/fw based sendtargets
+    discovery and if the hardware has some flash which may be
+    holding or can contain some iscsi target info
+    .
+    Signed-off-by: Mike Christie 
+    Cc: David C Somayajulu 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index 7502bb4808d6..315ab691056f 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -102,6 +102,7 @@ static struct scsi_host_template qla4xxx_driver_template = {
+ static struct iscsi_transport qla4xxx_iscsi_transport = {
+ 	.owner			= THIS_MODULE,
+ 	.name			= DRIVER_NAME,
++	.caps			= CAP_FW_DB | CAP_SENDTARGETS_OFFLOAD,
+ 	.param_mask		= ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS |
+ 				  ISCSI_TARGET_NAME | ISCSI_TPGT,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS |
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index a046a329189c..81a542506dfe 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -299,6 +299,8 @@ enum iscsi_host_param {
+ #define CAP_MULTI_CONN		0x40
+ #define CAP_TEXT_NEGO		0x80
+ #define CAP_MARKERS		0x100
++#define CAP_FW_DB		0x200
++#define CAP_SENDTARGETS_OFFLOAD	0x400
+ 
+ /*
+  * These flags describes reason of stop_conn() call

commit d1d81c01f4bdd50577d9f89aa4a8e6344f63aa70
+Author: Mike Christie 
+Date:   Wed May 30 12:57:21 2007 -0500
+
+    [SCSI] iscsi_tcp: remove DMA alignment restriction
+    
+    Add a slave_configure function to iSCSI TCP to remove any DMA
+    alignment restriction.  This permits the use of direct IO from
+    arbitrary addresses.
+    
+    Signed-off-by: Pete Wyckoff 
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 6eaa2e3a9252..4e9f0d9a55ea 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -36,6 +36,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -2184,6 +2185,12 @@ static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session)
+ 	iscsi_session_teardown(cls_session);
+ }
+ 
++static int iscsi_tcp_slave_configure(struct scsi_device *sdev)
++{
++	blk_queue_dma_alignment(sdev->request_queue, 0);
++	return 0;
++}
++
+ static struct scsi_host_template iscsi_sht = {
+ 	.name			= "iSCSI Initiator over TCP/IP",
+ 	.queuecommand           = iscsi_queuecommand,
+@@ -2195,6 +2202,7 @@ static struct scsi_host_template iscsi_sht = {
+ 	.eh_abort_handler       = iscsi_eh_abort,
+ 	.eh_host_reset_handler	= iscsi_eh_host_reset,
+ 	.use_clustering         = DISABLE_CLUSTERING,
++	.slave_configure        = iscsi_tcp_slave_configure,
+ 	.proc_name		= "iscsi_tcp",
+ 	.this_id		= -1,
+ };

commit dbdb016d92603619d972082167c10b8c74e605cc
+Author: Mike Christie 
+Date:   Wed May 30 12:57:20 2007 -0500
+
+    [SCSI] iscsi_tcp: fix handling of data buffer padding
+    
+    If we got the padding, data and header in different skbs,
+    we were not handling the padding correctly because we attributed it
+    to the data's skb. This resulted in the initiator reading from
+    pad bytes + skb offset instead of the correct offset.
+    
+    If you could not connect with the open solaris target, this
+    will fix the lock up problem you were hitting.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index eca4d611dd49..6eaa2e3a9252 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -896,11 +896,27 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 		}
+ 	}
+ 
+-	if (tcp_conn->in_progress == IN_PROGRESS_DDIGEST_RECV) {
++	if (tcp_conn->in_progress == IN_PROGRESS_DDIGEST_RECV &&
++	    tcp_conn->in.copy) {
+ 		uint32_t recv_digest;
+ 
+ 		debug_tcp("extra data_recv offset %d copy %d\n",
+ 			  tcp_conn->in.offset, tcp_conn->in.copy);
++
++		if (!tcp_conn->data_copied) {
++			if (tcp_conn->in.padding) {
++				debug_tcp("padding -> %d\n",
++					  tcp_conn->in.padding);
++				memset(pad, 0, tcp_conn->in.padding);
++				sg_init_one(&sg, pad, tcp_conn->in.padding);
++				crypto_hash_update(&tcp_conn->rx_hash,
++						   &sg, sg.length);
++			}
++			crypto_hash_final(&tcp_conn->rx_hash,
++					  (u8 *) &tcp_conn->in.datadgst);
++			debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst);
++		}
++
+ 		rc = iscsi_tcp_copy(conn, sizeof(uint32_t));
+ 		if (rc) {
+ 			if (rc == -EAGAIN)
+@@ -925,8 +941,7 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 	}
+ 
+ 	if (tcp_conn->in_progress == IN_PROGRESS_DATA_RECV &&
+-	   tcp_conn->in.copy) {
+-
++	    tcp_conn->in.copy) {
+ 		debug_tcp("data_recv offset %d copy %d\n",
+ 		       tcp_conn->in.offset, tcp_conn->in.copy);
+ 
+@@ -937,24 +952,32 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 			iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ 			return 0;
+ 		}
+-		tcp_conn->in.copy -= tcp_conn->in.padding;
+-		tcp_conn->in.offset += tcp_conn->in.padding;
+-		if (conn->datadgst_en) {
+-			if (tcp_conn->in.padding) {
+-				debug_tcp("padding -> %d\n",
+-					  tcp_conn->in.padding);
+-				memset(pad, 0, tcp_conn->in.padding);
+-				sg_init_one(&sg, pad, tcp_conn->in.padding);
+-				crypto_hash_update(&tcp_conn->rx_hash,
+-						   &sg, sg.length);
+-			}
+-			crypto_hash_final(&tcp_conn->rx_hash,
+-					  (u8 *) &tcp_conn->in.datadgst);
+-			debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst);
++
++		if (tcp_conn->in.padding)
++			tcp_conn->in_progress = IN_PROGRESS_PAD_RECV;
++		else if (conn->datadgst_en)
+ 			tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV;
+-			tcp_conn->data_copied = 0;
+-		} else
++		else
++			tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
++		tcp_conn->data_copied = 0;
++	}
++
++	if (tcp_conn->in_progress == IN_PROGRESS_PAD_RECV &&
++	    tcp_conn->in.copy) {
++		int copylen = min(tcp_conn->in.padding - tcp_conn->data_copied,
++				  tcp_conn->in.copy);
++
++		tcp_conn->in.copy -= copylen;
++		tcp_conn->in.offset += copylen;
++		tcp_conn->data_copied += copylen;
++
++		if (tcp_conn->data_copied != tcp_conn->in.padding)
++			tcp_conn->in_progress = IN_PROGRESS_PAD_RECV;
++		else if (conn->datadgst_en)
++			tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV;
++		else
+ 			tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
++		tcp_conn->data_copied = 0;
+ 	}
+ 
+ 	debug_tcp("f, processed %d from out of %d padding %d\n",
+diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
+index b039160ebafd..7eba44df0a7f 100644
+--- a/drivers/scsi/iscsi_tcp.h
++++ b/drivers/scsi/iscsi_tcp.h
+@@ -29,6 +29,7 @@
+ #define IN_PROGRESS_HEADER_GATHER	0x1
+ #define IN_PROGRESS_DATA_RECV		0x2
+ #define IN_PROGRESS_DDIGEST_RECV	0x3
++#define IN_PROGRESS_PAD_RECV		0x4
+ 
+ /* xmit state machine */
+ #define XMSTATE_IDLE			0x0

commit 1548271ece9e9312fd5feb41fd58773b56a71d39
+Author: Mike Christie 
+Date:   Wed May 30 12:57:19 2007 -0500
+
+    [SCSI] libiscsi: make can_queue configurable
+    
+    This patch allows us to set can_queue and cmds_per_lun from userspace
+    when we create the session/host. From there we can set it on a per
+    target basis. The patch fully converts iscsi_tcp, but only hooks
+    up ib_iser for cmd_per_lun since it currently has a lots of preallocations
+    based on can_queue.
+    
+    Signed-off-by: Mike Christie 
+    Cc: Roland Dreier 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 9782190a9ee5..bed583c426e6 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -373,7 +373,8 @@ static struct iscsi_transport iscsi_iser_transport;
+ static struct iscsi_cls_session *
+ iscsi_iser_session_create(struct iscsi_transport *iscsit,
+ 			 struct scsi_transport_template *scsit,
+-			  uint32_t initial_cmdsn, uint32_t *hostno)
++			 uint16_t cmds_max, uint16_t qdepth,
++			 uint32_t initial_cmdsn, uint32_t *hostno)
+ {
+ 	struct iscsi_cls_session *cls_session;
+ 	struct iscsi_session *session;
+@@ -384,7 +385,13 @@ iscsi_iser_session_create(struct iscsi_transport *iscsit,
+ 	struct iscsi_iser_cmd_task *iser_ctask;
+ 	struct iser_desc *desc;
+ 
++	/*
++	 * we do not support setting can_queue cmd_per_lun from userspace yet
++	 * because we preallocate so many resources
++	 */
+ 	cls_session = iscsi_session_setup(iscsit, scsit,
++					  ISCSI_DEF_XMIT_CMDS_MAX,
++					  ISCSI_MAX_CMD_PER_LUN,
+ 					  sizeof(struct iscsi_iser_cmd_task),
+ 					  sizeof(struct iser_desc),
+ 					  initial_cmdsn, &hn);
+@@ -543,7 +550,7 @@ iscsi_iser_ep_disconnect(__u64 ep_handle)
+ static struct scsi_host_template iscsi_iser_sht = {
+ 	.name                   = "iSCSI Initiator over iSER, v." DRV_VER,
+ 	.queuecommand           = iscsi_queuecommand,
+-	.can_queue		= ISCSI_XMIT_CMDS_MAX - 1,
++	.can_queue		= ISCSI_DEF_XMIT_CMDS_MAX - 1,
+ 	.sg_tablesize           = ISCSI_ISER_SG_TABLESIZE,
+ 	.max_sectors		= 1024,
+ 	.cmd_per_lun            = ISCSI_MAX_CMD_PER_LUN,
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
+index 8960196ffb0f..e2353701e8bb 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
+@@ -98,7 +98,7 @@
+ #define ISER_MAX_TX_MISC_PDUS		6 /* NOOP_OUT(2), TEXT(1),         *
+ 					   * SCSI_TMFUNC(2), LOGOUT(1) */
+ 
+-#define ISER_QP_MAX_RECV_DTOS		(ISCSI_XMIT_CMDS_MAX + \
++#define ISER_QP_MAX_RECV_DTOS		(ISCSI_DEF_XMIT_CMDS_MAX + \
+ 					ISER_MAX_RX_MISC_PDUS    +  \
+ 					ISER_MAX_TX_MISC_PDUS)
+ 
+@@ -110,7 +110,7 @@
+ 
+ #define ISER_INFLIGHT_DATAOUTS		8
+ 
+-#define ISER_QP_MAX_REQ_DTOS		(ISCSI_XMIT_CMDS_MAX *    \
++#define ISER_QP_MAX_REQ_DTOS		(ISCSI_DEF_XMIT_CMDS_MAX *    \
+ 					(1 + ISER_INFLIGHT_DATAOUTS) + \
+ 					ISER_MAX_TX_MISC_PDUS        + \
+ 					ISER_MAX_RX_MISC_PDUS)
+diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
+index 3702e2375553..2044de1164ac 100644
+--- a/drivers/infiniband/ulp/iser/iser_verbs.c
++++ b/drivers/infiniband/ulp/iser/iser_verbs.c
+@@ -155,8 +155,8 @@ static int iser_create_ib_conn_res(struct iser_conn *ib_conn)
+ 	params.max_pages_per_fmr = ISCSI_ISER_SG_TABLESIZE + 1;
+ 	/* make the pool size twice the max number of SCSI commands *
+ 	 * the ML is expected to queue, watermark for unmap at 50%  */
+-	params.pool_size	 = ISCSI_XMIT_CMDS_MAX * 2;
+-	params.dirty_watermark	 = ISCSI_XMIT_CMDS_MAX;
++	params.pool_size	 = ISCSI_DEF_XMIT_CMDS_MAX * 2;
++	params.dirty_watermark	 = ISCSI_DEF_XMIT_CMDS_MAX;
+ 	params.cache		 = 0;
+ 	params.flush_function	 = NULL;
+ 	params.access		 = (IB_ACCESS_LOCAL_WRITE  |
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 8edcfddc0baf..eca4d611dd49 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -2114,6 +2114,7 @@ iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats)
+ static struct iscsi_cls_session *
+ iscsi_tcp_session_create(struct iscsi_transport *iscsit,
+ 			 struct scsi_transport_template *scsit,
++			 uint16_t cmds_max, uint16_t qdepth,
+ 			 uint32_t initial_cmdsn, uint32_t *hostno)
+ {
+ 	struct iscsi_cls_session *cls_session;
+@@ -2121,7 +2122,7 @@ iscsi_tcp_session_create(struct iscsi_transport *iscsit,
+ 	uint32_t hn;
+ 	int cmd_i;
+ 
+-	cls_session = iscsi_session_setup(iscsit, scsit,
++	cls_session = iscsi_session_setup(iscsit, scsit, cmds_max, qdepth,
+ 					 sizeof(struct iscsi_tcp_cmd_task),
+ 					 sizeof(struct iscsi_tcp_mgmt_task),
+ 					 initial_cmdsn, &hn);
+@@ -2164,7 +2165,7 @@ static struct scsi_host_template iscsi_sht = {
+ 	.name			= "iSCSI Initiator over TCP/IP",
+ 	.queuecommand           = iscsi_queuecommand,
+ 	.change_queue_depth	= iscsi_change_queue_depth,
+-	.can_queue		= ISCSI_XMIT_CMDS_MAX - 1,
++	.can_queue		= ISCSI_DEF_XMIT_CMDS_MAX - 1,
+ 	.sg_tablesize		= ISCSI_SG_TABLESIZE,
+ 	.max_sectors		= 0xFFFF,
+ 	.cmd_per_lun		= ISCSI_DEF_CMD_PER_LUN,
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 938f527cd81a..1632866f52cc 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1330,6 +1330,10 @@ EXPORT_SYMBOL_GPL(iscsi_pool_free);
+  * iscsi_session_setup - create iscsi cls session and host and session
+  * @scsit: scsi transport template
+  * @iscsit: iscsi transport template
++ * @cmds_max: scsi host can queue
++ * @qdepth: scsi host cmds per lun
++ * @cmd_task_size: LLD ctask private data size
++ * @mgmt_task_size: LLD mtask private data size
+  * @initial_cmdsn: initial CmdSN
+  * @hostno: host no allocated
+  *
+@@ -1339,6 +1343,7 @@ EXPORT_SYMBOL_GPL(iscsi_pool_free);
+ struct iscsi_cls_session *
+ iscsi_session_setup(struct iscsi_transport *iscsit,
+ 		    struct scsi_transport_template *scsit,
++		    uint16_t cmds_max, uint16_t qdepth,
+ 		    int cmd_task_size, int mgmt_task_size,
+ 		    uint32_t initial_cmdsn, uint32_t *hostno)
+ {
+@@ -1347,11 +1352,32 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
+ 	struct iscsi_cls_session *cls_session;
+ 	int cmd_i;
+ 
++	if (qdepth > ISCSI_MAX_CMD_PER_LUN || qdepth < 1) {
++		if (qdepth != 0)
++			printk(KERN_ERR "iscsi: invalid queue depth of %d. "
++			      "Queue depth must be between 1 and %d.\n",
++			      qdepth, ISCSI_MAX_CMD_PER_LUN);
++		qdepth = ISCSI_DEF_CMD_PER_LUN;
++	}
++
++	if (cmds_max < 2 || (cmds_max & (cmds_max - 1)) ||
++	    cmds_max >= ISCSI_MGMT_ITT_OFFSET) {
++		if (cmds_max != 0)
++			printk(KERN_ERR "iscsi: invalid can_queue of %d. "
++			       "can_queue must be a power of 2 and between "
++			       "2 and %d - setting to %d.\n", cmds_max,
++			       ISCSI_MGMT_ITT_OFFSET, ISCSI_DEF_XMIT_CMDS_MAX);
++		cmds_max = ISCSI_DEF_XMIT_CMDS_MAX;
++	}
++
+ 	shost = scsi_host_alloc(iscsit->host_template,
+ 				hostdata_privsize(sizeof(*session)));
+ 	if (!shost)
+ 		return NULL;
+ 
++	/* the iscsi layer takes one task for reserve */
++	shost->can_queue = cmds_max - 1;
++	shost->cmd_per_lun = qdepth;
+ 	shost->max_id = 1;
+ 	shost->max_channel = 0;
+ 	shost->max_lun = iscsit->max_lun;
+@@ -1365,7 +1391,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
+ 	session->host = shost;
+ 	session->state = ISCSI_STATE_FREE;
+ 	session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
+-	session->cmds_max = ISCSI_XMIT_CMDS_MAX;
++	session->cmds_max = cmds_max;
+ 	session->cmdsn = initial_cmdsn;
+ 	session->exp_cmdsn = initial_cmdsn + 1;
+ 	session->max_cmdsn = initial_cmdsn + 1;
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 341d4fb5c6f8..859bd2100856 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -814,6 +814,8 @@ iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
+ 	uint32_t hostno;
+ 
+ 	session = transport->create_session(transport, &priv->t,
++					    ev->u.c_session.cmds_max,
++					    ev->u.c_session.queue_depth,
+ 					    ev->u.c_session.initial_cmdsn,
+ 					    &hostno);
+ 	if (!session)
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index 1a18196d77f6..a046a329189c 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -72,6 +72,8 @@ struct iscsi_uevent {
+ 		/* messages u -> k */
+ 		struct msg_create_session {
+ 			uint32_t	initial_cmdsn;
++			uint16_t	cmds_max;
++			uint16_t	queue_depth;
+ 		} c_session;
+ 		struct msg_destroy_session {
+ 			uint32_t	sid;
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 8d48cf8f2e3f..2f303a3b270e 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -48,9 +48,8 @@ struct iscsi_nopin;
+ #define debug_scsi(fmt...)
+ #endif
+ 
+-#define ISCSI_XMIT_CMDS_MAX	128	/* must be power of 2 */
+-#define ISCSI_MGMT_CMDS_MAX	32	/* must be power of 2 */
+-#define ISCSI_CONN_MAX			1
++#define ISCSI_DEF_XMIT_CMDS_MAX	128	/* must be power of 2 */
++#define ISCSI_MGMT_CMDS_MAX	16	/* must be power of 2 */
+ 
+ #define ISCSI_MGMT_ITT_OFFSET	0xa00
+ 
+@@ -268,7 +267,7 @@ extern int iscsi_host_get_param(struct Scsi_Host *shost,
+  */
+ extern struct iscsi_cls_session *
+ iscsi_session_setup(struct iscsi_transport *, struct scsi_transport_template *,
+-		    int, int, uint32_t, uint32_t *);
++		    uint16_t, uint16_t, int, int, uint32_t, uint32_t *);
+ extern void iscsi_session_teardown(struct iscsi_cls_session *);
+ extern struct iscsi_session *class_to_transport_session(struct iscsi_cls_session *);
+ extern void iscsi_session_recovery_timedout(struct iscsi_cls_session *);
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index abc4068621d8..706c0cd36c14 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -90,7 +90,8 @@ struct iscsi_transport {
+ 	unsigned int max_conn;
+ 	unsigned int max_cmd_len;
+ 	struct iscsi_cls_session *(*create_session) (struct iscsi_transport *it,
+-		struct scsi_transport_template *t, uint32_t sn, uint32_t *hn);
++		struct scsi_transport_template *t, uint16_t, uint16_t,
++		uint32_t sn, uint32_t *hn);
+ 	void (*destroy_session) (struct iscsi_cls_session *session);
+ 	struct iscsi_cls_conn *(*create_conn) (struct iscsi_cls_session *sess,
+ 				uint32_t cid);

commit 77a23c21aaa723f6b0ffc4a701be8c8e5a32346d
+Author: Mike Christie 
+Date:   Wed May 30 12:57:18 2007 -0500
+
+    [SCSI] libiscsi: fix iscsi cmdsn allocation
+    
+    The cmdsn allocation and pdu transmit code can race, and we can end
+    up sending a pdu with cmdsn 10 before a pdu with 5. The target will
+    then fail the connection/session. This patch fixes the problem by
+    delaying the cmdsn allocation until we are about to send the pdu.
+    
+    This also removes the xmitmutex. We were using the connection xmitmutex
+    during error handling to handle races with mtask and ctask cleanup and
+    completion. For ctasks we now have nice refcounting and for the mtask,
+    if we hit the case where the mtask timesout and it is floating
+    around somewhere in the driver, we end up dropping the session.
+    And to handle session level cleanup, we use the xmit suspend bit
+    along with scsi_flush_queue and the session lock to make sure
+    that the xmit thread is not possibly transmitting a task while
+    we are trying to kill it.
+    
+    Signed-off-by: Mike Christie 
+    Cc: Roland Dreier 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 6c8cd09c58f0..9782190a9ee5 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -134,19 +134,9 @@ iscsi_iser_cmd_init(struct iscsi_cmd_task *ctask)
+ {
+ 	struct iscsi_iser_conn     *iser_conn  = ctask->conn->dd_data;
+ 	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
+-	struct scsi_cmnd  *sc = ctask->sc;
+ 
+ 	iser_ctask->command_sent = 0;
+ 	iser_ctask->iser_conn    = iser_conn;
+-
+-	if (sc->sc_data_direction == DMA_TO_DEVICE) {
+-		BUG_ON(sc->request_bufflen == 0);
+-
+-		debug_scsi("cmd [itt %x total %d imm %d unsol_data %d\n",
+-			   ctask->itt, sc->request_bufflen, ctask->imm_count,
+-			   ctask->unsol_count);
+-	}
+-
+ 	iser_ctask_rdma_init(iser_ctask);
+ }
+ 
+@@ -219,6 +209,14 @@ iscsi_iser_ctask_xmit(struct iscsi_conn *conn,
+ 	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
+ 	int error = 0;
+ 
++	if (ctask->sc->sc_data_direction == DMA_TO_DEVICE) {
++		BUG_ON(ctask->sc->request_bufflen == 0);
++
++		debug_scsi("cmd [itt %x total %d imm %d unsol_data %d\n",
++			   ctask->itt, ctask->sc->request_bufflen,
++			   ctask->imm_count, ctask->unsol_count);
++	}
++
+ 	debug_scsi("ctask deq [cid %d itt 0x%x]\n",
+ 		   conn->id, ctask->itt);
+ 
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 0afdca2224c2..8edcfddc0baf 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -34,7 +34,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+ #include 
+ #include 
+ #include 
+@@ -211,7 +210,6 @@ iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ static int
+ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+-	int rc;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)tcp_conn->in.hdr;
+@@ -219,9 +217,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	struct scsi_cmnd *sc = ctask->sc;
+ 	int datasn = be32_to_cpu(rhdr->datasn);
+ 
+-	rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr);
+-	if (rc)
+-		return rc;
++	iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
+ 	/*
+ 	 * setup Data-In byte counter (gets decremented..)
+ 	 */
+@@ -377,12 +373,10 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 		return ISCSI_ERR_R2TSN;
+ 	}
+ 
+-	rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr);
+-	if (rc)
+-		return rc;
+-
+ 	/* fill-in new R2T associated with the task */
+ 	spin_lock(&session->lock);
++	iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
++
+ 	if (!ctask->sc || ctask->mtask ||
+ 	     session->state != ISCSI_STATE_LOGGED_IN) {
+ 		printk(KERN_INFO "iscsi_tcp: dropping R2T itt %d in "
+@@ -1762,12 +1756,6 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	debug_scsi("ctask deq [cid %d xmstate %x itt 0x%x]\n",
+ 		conn->id, tcp_ctask->xmstate, ctask->itt);
+ 
+-	/*
+-	 * serialize with TMF AbortTask
+-	 */
+-	if (ctask->mtask)
+-		return rc;
+-
+ 	rc = iscsi_send_cmd_hdr(conn, ctask);
+ 	if (rc)
+ 		return rc;
+@@ -1949,8 +1937,7 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
+ 
+ /* called with host lock */
+ static void
+-iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask,
+-		    char *data, uint32_t data_size)
++iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
+ {
+ 	struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data;
+ 	tcp_mtask->xmstate = XMSTATE_IMM_HDR_INIT;
+@@ -2073,22 +2060,15 @@ iscsi_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ 
+ 	switch(param) {
+ 	case ISCSI_PARAM_CONN_PORT:
+-		mutex_lock(&conn->xmitmutex);
+-		if (!tcp_conn->sock) {
+-			mutex_unlock(&conn->xmitmutex);
++		if (!tcp_conn->sock)
+ 			return -EINVAL;
+-		}
+ 
+ 		inet = inet_sk(tcp_conn->sock->sk);
+ 		len = sprintf(buf, "%hu\n", be16_to_cpu(inet->dport));
+-		mutex_unlock(&conn->xmitmutex);
+ 		break;
+ 	case ISCSI_PARAM_CONN_ADDRESS:
+-		mutex_lock(&conn->xmitmutex);
+-		if (!tcp_conn->sock) {
+-			mutex_unlock(&conn->xmitmutex);
++		if (!tcp_conn->sock)
+ 			return -EINVAL;
+-		}
+ 
+ 		sk = tcp_conn->sock->sk;
+ 		if (sk->sk_family == PF_INET) {
+@@ -2099,7 +2079,6 @@ iscsi_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ 			np = inet6_sk(sk);
+ 			len = sprintf(buf, NIP6_FMT "\n", NIP6(np->daddr));
+ 		}
+-		mutex_unlock(&conn->xmitmutex);
+ 		break;
+ 	default:
+ 		return iscsi_conn_get_param(cls_conn, param, buf);
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 63f0a15d9887..938f527cd81a 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -22,7 +22,6 @@
+  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+  */
+ #include 
+-#include 
+ #include 
+ #include 
+ #include 
+@@ -46,27 +45,53 @@ class_to_transport_session(struct iscsi_cls_session *cls_session)
+ }
+ EXPORT_SYMBOL_GPL(class_to_transport_session);
+ 
+-#define INVALID_SN_DELTA	0xffff
++/* Serial Number Arithmetic, 32 bits, less than, RFC1982 */
++#define SNA32_CHECK 2147483648UL
+ 
+-int
+-iscsi_check_assign_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
++static int iscsi_sna_lt(u32 n1, u32 n2)
++{
++	return n1 != n2 && ((n1 < n2 && (n2 - n1 < SNA32_CHECK)) ||
++			    (n1 > n2 && (n2 - n1 < SNA32_CHECK)));
++}
++
++/* Serial Number Arithmetic, 32 bits, less than, RFC1982 */
++static int iscsi_sna_lte(u32 n1, u32 n2)
++{
++	return n1 == n2 || ((n1 < n2 && (n2 - n1 < SNA32_CHECK)) ||
++			    (n1 > n2 && (n2 - n1 < SNA32_CHECK)));
++}
++
++void
++iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
+ {
+ 	uint32_t max_cmdsn = be32_to_cpu(hdr->max_cmdsn);
+ 	uint32_t exp_cmdsn = be32_to_cpu(hdr->exp_cmdsn);
+ 
+-	if (max_cmdsn < exp_cmdsn -1 &&
+-	    max_cmdsn > exp_cmdsn - INVALID_SN_DELTA)
+-		return ISCSI_ERR_MAX_CMDSN;
+-	if (max_cmdsn > session->max_cmdsn ||
+-	    max_cmdsn < session->max_cmdsn - INVALID_SN_DELTA)
+-		session->max_cmdsn = max_cmdsn;
+-	if (exp_cmdsn > session->exp_cmdsn ||
+-	    exp_cmdsn < session->exp_cmdsn - INVALID_SN_DELTA)
++	/*
++	 * standard specifies this check for when to update expected and
++	 * max sequence numbers
++	 */
++	if (iscsi_sna_lt(max_cmdsn, exp_cmdsn - 1))
++		return;
++
++	if (exp_cmdsn != session->exp_cmdsn &&
++	    !iscsi_sna_lt(exp_cmdsn, session->exp_cmdsn))
+ 		session->exp_cmdsn = exp_cmdsn;
+ 
+-	return 0;
++	if (max_cmdsn != session->max_cmdsn &&
++	    !iscsi_sna_lt(max_cmdsn, session->max_cmdsn)) {
++		session->max_cmdsn = max_cmdsn;
++		/*
++		 * if the window closed with IO queued, then kick the
++		 * xmit thread
++		 */
++		if (!list_empty(&session->leadconn->xmitqueue) ||
++		    __kfifo_len(session->leadconn->mgmtqueue))
++			scsi_queue_work(session->host,
++					&session->leadconn->xmitwork);
++	}
+ }
+-EXPORT_SYMBOL_GPL(iscsi_check_assign_cmdsn);
++EXPORT_SYMBOL_GPL(iscsi_update_cmdsn);
+ 
+ void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *ctask,
+ 				   struct iscsi_data *hdr)
+@@ -175,8 +200,13 @@ static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ 	}
+ 
+ 	conn->scsicmd_pdus_cnt++;
++
++        debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x len %d "
++		"cmdsn %d win %d]\n",
++                sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
++                conn->id, sc, sc->cmnd[0], ctask->itt, sc->request_bufflen,
++                session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
+ }
+-EXPORT_SYMBOL_GPL(iscsi_prep_scsi_cmd_pdu);
+ 
+ /**
+  * iscsi_complete_command - return command back to scsi-ml
+@@ -205,26 +235,12 @@ static void __iscsi_get_ctask(struct iscsi_cmd_task *ctask)
+ 	atomic_inc(&ctask->refcount);
+ }
+ 
+-static void iscsi_get_ctask(struct iscsi_cmd_task *ctask)
+-{
+-	spin_lock_bh(&ctask->conn->session->lock);
+-	__iscsi_get_ctask(ctask);
+-	spin_unlock_bh(&ctask->conn->session->lock);
+-}
+-
+ static void __iscsi_put_ctask(struct iscsi_cmd_task *ctask)
+ {
+ 	if (atomic_dec_and_test(&ctask->refcount))
+ 		iscsi_complete_command(ctask);
+ }
+ 
+-static void iscsi_put_ctask(struct iscsi_cmd_task *ctask)
+-{
+-	spin_lock_bh(&ctask->conn->session->lock);
+-	__iscsi_put_ctask(ctask);
+-	spin_unlock_bh(&ctask->conn->session->lock);
+-}
+-
+ /**
+  * iscsi_cmd_rsp - SCSI Command Response processing
+  * @conn: iscsi connection
+@@ -236,21 +252,15 @@ static void iscsi_put_ctask(struct iscsi_cmd_task *ctask)
+  * iscsi_cmd_rsp sets up the scsi_cmnd fields based on the PDU and
+  * then completes the command and task.
+  **/
+-static int iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+-			      struct iscsi_cmd_task *ctask, char *data,
+-			      int datalen)
++static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
++			       struct iscsi_cmd_task *ctask, char *data,
++			       int datalen)
+ {
+-	int rc;
+ 	struct iscsi_cmd_rsp *rhdr = (struct iscsi_cmd_rsp *)hdr;
+ 	struct iscsi_session *session = conn->session;
+ 	struct scsi_cmnd *sc = ctask->sc;
+ 
+-	rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr);
+-	if (rc) {
+-		sc->result = DID_ERROR << 16;
+-		goto out;
+-	}
+-
++	iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
+ 	conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
+ 
+ 	sc->result = (DID_OK << 16) | rhdr->cmd_status;
+@@ -302,7 +312,6 @@ static int iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	conn->scsirsp_pdus_cnt++;
+ 
+ 	__iscsi_put_ctask(ctask);
+-	return rc;
+ }
+ 
+ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+@@ -382,8 +391,8 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		switch(opcode) {
+ 		case ISCSI_OP_SCSI_CMD_RSP:
+ 			BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
+-			rc = iscsi_scsi_cmd_rsp(conn, hdr, ctask, data,
+-						datalen);
++			iscsi_scsi_cmd_rsp(conn, hdr, ctask, data,
++					   datalen);
+ 			break;
+ 		case ISCSI_OP_SCSI_DATA_IN:
+ 			BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
+@@ -406,11 +415,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		debug_scsi("immrsp [op 0x%x cid %d itt 0x%x len %d]\n",
+ 			   opcode, conn->id, mtask->itt, datalen);
+ 
+-		rc = iscsi_check_assign_cmdsn(session,
+-					      (struct iscsi_nopin*)hdr);
+-		if (rc)
+-			goto done;
+-
++		iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
+ 		switch(opcode) {
+ 		case ISCSI_OP_LOGOUT_RSP:
+ 			if (datalen) {
+@@ -459,10 +464,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			break;
+ 		}
+ 	} else if (itt == ~0U) {
+-		rc = iscsi_check_assign_cmdsn(session,
+-					     (struct iscsi_nopin*)hdr);
+-		if (rc)
+-			goto done;
++		iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
+ 
+ 		switch(opcode) {
+ 		case ISCSI_OP_NOOP_IN:
+@@ -492,7 +494,6 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	} else
+ 		rc = ISCSI_ERR_BAD_ITT;
+ 
+-done:
+ 	return rc;
+ }
+ EXPORT_SYMBOL_GPL(__iscsi_complete_pdu);
+@@ -579,17 +580,47 @@ void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_conn_failure);
+ 
++static void iscsi_prep_mtask(struct iscsi_conn *conn,
++			     struct iscsi_mgmt_task *mtask)
++{
++	struct iscsi_session *session = conn->session;
++	struct iscsi_hdr *hdr = mtask->hdr;
++	struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr;
++
++	if (hdr->opcode != (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) &&
++	    hdr->opcode != (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE))
++		nop->exp_statsn = cpu_to_be32(conn->exp_statsn);
++	/*
++	 * pre-format CmdSN for outgoing PDU.
++	 */
++	nop->cmdsn = cpu_to_be32(session->cmdsn);
++	if (hdr->itt != RESERVED_ITT) {
++		hdr->itt = build_itt(mtask->itt, conn->id, session->age);
++		if (conn->c_stage == ISCSI_CONN_STARTED &&
++		    !(hdr->opcode & ISCSI_OP_IMMEDIATE))
++			session->cmdsn++;
++	}
++
++	if (session->tt->init_mgmt_task)
++		session->tt->init_mgmt_task(conn, mtask);
++
++	debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n",
++		   hdr->opcode, hdr->itt, mtask->data_count);
++}
++
+ static int iscsi_xmit_mtask(struct iscsi_conn *conn)
+ {
+ 	struct iscsi_hdr *hdr = conn->mtask->hdr;
+ 	int rc, was_logout = 0;
+ 
++	spin_unlock_bh(&conn->session->lock);
+ 	if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) {
+ 		conn->session->state = ISCSI_STATE_IN_RECOVERY;
+ 		iscsi_block_session(session_to_cls(conn->session));
+ 		was_logout = 1;
+ 	}
+ 	rc = conn->session->tt->xmit_mgmt_task(conn, conn->mtask);
++	spin_lock_bh(&conn->session->lock);
+ 	if (rc)
+ 		return rc;
+ 
+@@ -603,6 +634,45 @@ static int iscsi_xmit_mtask(struct iscsi_conn *conn)
+ 	return 0;
+ }
+ 
++static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn)
++{
++	struct iscsi_session *session = conn->session;
++
++	/*
++	 * Check for iSCSI window and take care of CmdSN wrap-around
++	 */
++	if (!iscsi_sna_lte(session->cmdsn, session->max_cmdsn)) {
++		debug_scsi("iSCSI CmdSN closed. MaxCmdSN %u CmdSN %u\n",
++			   session->max_cmdsn, session->cmdsn);
++		return -ENOSPC;
++	}
++	return 0;
++}
++
++static int iscsi_xmit_ctask(struct iscsi_conn *conn)
++{
++	struct iscsi_cmd_task *ctask = conn->ctask;
++	int rc = 0;
++
++	/*
++	 * serialize with TMF AbortTask
++	 */
++	if (ctask->state == ISCSI_TASK_ABORTING)
++		goto done;
++
++	__iscsi_get_ctask(ctask);
++	spin_unlock_bh(&conn->session->lock);
++	rc = conn->session->tt->xmit_cmd_task(conn, ctask);
++	spin_lock_bh(&conn->session->lock);
++	__iscsi_put_ctask(ctask);
++
++done:
++	if (!rc)
++		/* done with this ctask */
++		conn->ctask = NULL;
++	return rc;
++}
++
+ /**
+  * iscsi_data_xmit - xmit any command into the scheduled connection
+  * @conn: iscsi connection
+@@ -614,106 +684,79 @@ static int iscsi_xmit_mtask(struct iscsi_conn *conn)
+  **/
+ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ {
+-	struct iscsi_transport *tt;
+ 	int rc = 0;
+ 
++	spin_lock_bh(&conn->session->lock);
+ 	if (unlikely(conn->suspend_tx)) {
+ 		debug_scsi("conn %d Tx suspended!\n", conn->id);
++		spin_unlock_bh(&conn->session->lock);
+ 		return -ENODATA;
+ 	}
+-	tt = conn->session->tt;
+-
+-	/*
+-	 * Transmit in the following order:
+-	 *
+-	 * 1) un-finished xmit (ctask or mtask)
+-	 * 2) immediate control PDUs
+-	 * 3) write data
+-	 * 4) SCSI commands
+-	 * 5) non-immediate control PDUs
+-	 *
+-	 * No need to lock around __kfifo_get as long as
+-	 * there's one producer and one consumer.
+-	 */
+-
+-	BUG_ON(conn->ctask && conn->mtask);
+ 
+ 	if (conn->ctask) {
+-		iscsi_get_ctask(conn->ctask);
+-		rc = tt->xmit_cmd_task(conn, conn->ctask);
+-		iscsi_put_ctask(conn->ctask);
++		rc = iscsi_xmit_ctask(conn);
+ 		if (rc)
+ 			goto again;
+-		/* done with this in-progress ctask */
+-		conn->ctask = NULL;
+ 	}
++
+ 	if (conn->mtask) {
+ 		rc = iscsi_xmit_mtask(conn);
+ 	        if (rc)
+ 		        goto again;
+ 	}
+ 
+-	/* process immediate first */
+-        if (unlikely(__kfifo_len(conn->immqueue))) {
+-	        while (__kfifo_get(conn->immqueue, (void*)&conn->mtask,
+-			           sizeof(void*))) {
+-			spin_lock_bh(&conn->session->lock);
+-			list_add_tail(&conn->mtask->running,
+-				      &conn->mgmt_run_list);
+-			spin_unlock_bh(&conn->session->lock);
+-			rc = iscsi_xmit_mtask(conn);
+-		        if (rc)
+-			        goto again;
+-	        }
++	/*
++	 * process mgmt pdus like nops before commands since we should
++	 * only have one nop-out as a ping from us and targets should not
++	 * overflow us with nop-ins
++	 */
++check_mgmt:
++	while (__kfifo_get(conn->mgmtqueue, (void*)&conn->mtask,
++			   sizeof(void*))) {
++		iscsi_prep_mtask(conn, conn->mtask);
++		list_add_tail(&conn->mtask->running, &conn->mgmt_run_list);
++		rc = iscsi_xmit_mtask(conn);
++		if (rc)
++			goto again;
+ 	}
+ 
+ 	/* process command queue */
+-	spin_lock_bh(&conn->session->lock);
+ 	while (!list_empty(&conn->xmitqueue)) {
++		rc = iscsi_check_cmdsn_window_closed(conn);
++		if (rc) {
++			spin_unlock_bh(&conn->session->lock);
++			return rc;
++		}
+ 		/*
+ 		 * iscsi tcp may readd the task to the xmitqueue to send
+ 		 * write data
+ 		 */
+ 		conn->ctask = list_entry(conn->xmitqueue.next,
+ 					 struct iscsi_cmd_task, running);
++		if (conn->ctask->state == ISCSI_TASK_PENDING) {
++			iscsi_prep_scsi_cmd_pdu(conn->ctask);
++			conn->session->tt->init_cmd_task(conn->ctask);
++		}
+ 		conn->ctask->state = ISCSI_TASK_RUNNING;
+ 		list_move_tail(conn->xmitqueue.next, &conn->run_list);
+-		__iscsi_get_ctask(conn->ctask);
+-		spin_unlock_bh(&conn->session->lock);
+-
+-		rc = tt->xmit_cmd_task(conn, conn->ctask);
+-
+-		spin_lock_bh(&conn->session->lock);
+-		__iscsi_put_ctask(conn->ctask);
+-		if (rc) {
+-			spin_unlock_bh(&conn->session->lock);
++		rc = iscsi_xmit_ctask(conn);
++		if (rc)
+ 			goto again;
+-		}
++		/*
++		 * we could continuously get new ctask requests so
++		 * we need to check the mgmt queue for nops that need to
++		 * be sent to aviod starvation
++		 */
++		if (__kfifo_len(conn->mgmtqueue))
++			goto check_mgmt;
+ 	}
+ 	spin_unlock_bh(&conn->session->lock);
+-	/* done with this ctask */
+-	conn->ctask = NULL;
+-
+-	/* process the rest control plane PDUs, if any */
+-        if (unlikely(__kfifo_len(conn->mgmtqueue))) {
+-	        while (__kfifo_get(conn->mgmtqueue, (void*)&conn->mtask,
+-			           sizeof(void*))) {
+-			spin_lock_bh(&conn->session->lock);
+-			list_add_tail(&conn->mtask->running,
+-				      &conn->mgmt_run_list);
+-			spin_unlock_bh(&conn->session->lock);
+-			rc = iscsi_xmit_mtask(conn);
+-		        if (rc)
+-			        goto again;
+-	        }
+-	}
+-
+ 	return -ENODATA;
+ 
+ again:
+ 	if (unlikely(conn->suspend_tx))
+-		return -ENODATA;
+-
++		rc = -ENODATA;
++	spin_unlock_bh(&conn->session->lock);
+ 	return rc;
+ }
+ 
+@@ -725,11 +768,9 @@ static void iscsi_xmitworker(struct work_struct *work)
+ 	/*
+ 	 * serialize Xmit worker on a per-connection basis.
+ 	 */
+-	mutex_lock(&conn->xmitmutex);
+ 	do {
+ 		rc = iscsi_data_xmit(conn);
+ 	} while (rc >= 0 || rc == -EAGAIN);
+-	mutex_unlock(&conn->xmitmutex);
+ }
+ 
+ enum {
+@@ -787,20 +828,23 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 		goto fault;
+ 	}
+ 
+-	/*
+-	 * Check for iSCSI window and take care of CmdSN wrap-around
+-	 */
+-	if ((int)(session->max_cmdsn - session->cmdsn) < 0) {
+-		reason = FAILURE_WINDOW_CLOSED;
+-		goto reject;
+-	}
+-
+ 	conn = session->leadconn;
+ 	if (!conn) {
+ 		reason = FAILURE_SESSION_FREED;
+ 		goto fault;
+ 	}
+ 
++	/*
++	 * We check this here and in data xmit, because if we get to the point
++	 * that this check is hitting the window then we have enough IO in
++	 * flight and enough IO waiting to be transmitted it is better
++	 * to let the scsi/block layer queue up.
++	 */
++	if (iscsi_check_cmdsn_window_closed(conn)) {
++		reason = FAILURE_WINDOW_CLOSED;
++		goto reject;
++	}
++
+ 	if (!__kfifo_get(session->cmdpool.queue, (void*)&ctask,
+ 			 sizeof(void*))) {
+ 		reason = FAILURE_OOM;
+@@ -815,17 +859,8 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 	ctask->conn = conn;
+ 	ctask->sc = sc;
+ 	INIT_LIST_HEAD(&ctask->running);
+-	iscsi_prep_scsi_cmd_pdu(ctask);
+-
+-	session->tt->init_cmd_task(ctask);
+ 
+ 	list_add_tail(&ctask->running, &conn->xmitqueue);
+-	debug_scsi(
+-	       "ctask enq [%s cid %d sc %p cdb 0x%x itt 0x%x len %d cmdsn %d "
+-		"win %d]\n",
+-		sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
+-		conn->id, sc, sc->cmnd[0], ctask->itt, sc->request_bufflen,
+-		session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
+ 	spin_unlock(&session->lock);
+ 
+ 	scsi_queue_work(host, &conn->xmitwork);
+@@ -856,19 +891,16 @@ int iscsi_change_queue_depth(struct scsi_device *sdev, int depth)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_change_queue_depth);
+ 
+-static int
+-iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+-			char *data, uint32_t data_size)
++static struct iscsi_mgmt_task *
++__iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
++		      char *data, uint32_t data_size)
+ {
+ 	struct iscsi_session *session = conn->session;
+-	struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr;
+ 	struct iscsi_mgmt_task *mtask;
+ 
+-	spin_lock_bh(&session->lock);
+-	if (session->state == ISCSI_STATE_TERMINATE) {
+-		spin_unlock_bh(&session->lock);
+-		return -EPERM;
+-	}
++	if (session->state == ISCSI_STATE_TERMINATE)
++		return NULL;
++
+ 	if (hdr->opcode == (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) ||
+ 	    hdr->opcode == (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE))
+ 		/*
+@@ -882,27 +914,11 @@ iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
+ 		BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
+ 
+-		nop->exp_statsn = cpu_to_be32(conn->exp_statsn);
+ 		if (!__kfifo_get(session->mgmtpool.queue,
+-				 (void*)&mtask, sizeof(void*))) {
+-			spin_unlock_bh(&session->lock);
+-			return -ENOSPC;
+-		}
++				 (void*)&mtask, sizeof(void*)))
++			return NULL;
+ 	}
+ 
+-	/*
+-	 * pre-format CmdSN for outgoing PDU.
+-	 */
+-	if (hdr->itt != RESERVED_ITT) {
+-		hdr->itt = build_itt(mtask->itt, conn->id, session->age);
+-		nop->cmdsn = cpu_to_be32(session->cmdsn);
+-		if (conn->c_stage == ISCSI_CONN_STARTED &&
+-		    !(hdr->opcode & ISCSI_OP_IMMEDIATE))
+-			session->cmdsn++;
+-	} else
+-		/* do not advance CmdSN */
+-		nop->cmdsn = cpu_to_be32(session->cmdsn);
+-
+ 	if (data_size) {
+ 		memcpy(mtask->data, data, data_size);
+ 		mtask->data_count = data_size;
+@@ -911,38 +927,23 @@ iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 
+ 	INIT_LIST_HEAD(&mtask->running);
+ 	memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr));
+-	if (session->tt->init_mgmt_task)
+-		session->tt->init_mgmt_task(conn, mtask, data, data_size);
+-	spin_unlock_bh(&session->lock);
+-
+-	debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n",
+-		   hdr->opcode, hdr->itt, data_size);
+-
+-	/*
+-	 * since send_pdu() could be called at least from two contexts,
+-	 * we need to serialize __kfifo_put, so we don't have to take
+-	 * additional lock on fast data-path
+-	 */
+-        if (hdr->opcode & ISCSI_OP_IMMEDIATE)
+-	        __kfifo_put(conn->immqueue, (void*)&mtask, sizeof(void*));
+-	else
+-	        __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*));
+-
+-	scsi_queue_work(session->host, &conn->xmitwork);
+-	return 0;
++	__kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*));
++	return mtask;
+ }
+ 
+ int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
+ 			char *data, uint32_t data_size)
+ {
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+-	int rc;
+-
+-	mutex_lock(&conn->xmitmutex);
+-	rc = iscsi_conn_send_generic(conn, hdr, data, data_size);
+-	mutex_unlock(&conn->xmitmutex);
++	struct iscsi_session *session = conn->session;
++	int err = 0;
+ 
+-	return rc;
++	spin_lock_bh(&session->lock);
++	if (!__iscsi_conn_send_pdu(conn, hdr, data, data_size))
++		err = -EPERM;
++	spin_unlock_bh(&session->lock);
++	scsi_queue_work(session->host, &conn->xmitwork);
++	return err;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu);
+ 
+@@ -1027,14 +1028,12 @@ static void iscsi_tmabort_timedout(unsigned long data)
+ 	spin_unlock(&session->lock);
+ }
+ 
+-/* must be called with the mutex lock */
+ static int iscsi_exec_abort_task(struct scsi_cmnd *sc,
+ 				 struct iscsi_cmd_task *ctask)
+ {
+ 	struct iscsi_conn *conn = ctask->conn;
+ 	struct iscsi_session *session = conn->session;
+ 	struct iscsi_tm *hdr = &conn->tmhdr;
+-	int rc;
+ 
+ 	/*
+ 	 * ctask timed out but session is OK requests must be serialized.
+@@ -1047,32 +1046,27 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc,
+ 	hdr->rtt = ctask->hdr->itt;
+ 	hdr->refcmdsn = ctask->hdr->cmdsn;
+ 
+-	rc = iscsi_conn_send_generic(conn, (struct iscsi_hdr *)hdr,
+-				     NULL, 0);
+-	if (rc) {
++	ctask->mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr,
++					    NULL, 0);
++	if (!ctask->mtask) {
+ 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+-		debug_scsi("abort sent failure [itt 0x%x] %d\n", ctask->itt,
+-		           rc);
+-		return rc;
++		debug_scsi("abort sent failure [itt 0x%x]\n", ctask->itt);
++		return -EPERM;
+ 	}
++	ctask->state = ISCSI_TASK_ABORTING;
+ 
+ 	debug_scsi("abort sent [itt 0x%x]\n", ctask->itt);
+ 
+-	spin_lock_bh(&session->lock);
+-	ctask->mtask = (struct iscsi_mgmt_task *)
+-			session->mgmt_cmds[get_itt(hdr->itt) -
+-					ISCSI_MGMT_ITT_OFFSET];
+-
+ 	if (conn->tmabort_state == TMABORT_INITIAL) {
+ 		conn->tmfcmd_pdus_cnt++;
+-		conn->tmabort_timer.expires = 10*HZ + jiffies;
++		conn->tmabort_timer.expires = 20*HZ + jiffies;
+ 		conn->tmabort_timer.function = iscsi_tmabort_timedout;
+ 		conn->tmabort_timer.data = (unsigned long)ctask;
+ 		add_timer(&conn->tmabort_timer);
+ 		debug_scsi("abort set timeout [itt 0x%x]\n", ctask->itt);
+ 	}
+ 	spin_unlock_bh(&session->lock);
+-	mutex_unlock(&conn->xmitmutex);
++	scsi_queue_work(session->host, &conn->xmitwork);
+ 
+ 	/*
+ 	 * block eh thread until:
+@@ -1089,13 +1083,12 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc,
+ 	if (signal_pending(current))
+ 		flush_signals(current);
+ 	del_timer_sync(&conn->tmabort_timer);
+-
+-	mutex_lock(&conn->xmitmutex);
++	spin_lock_bh(&session->lock);
+ 	return 0;
+ }
+ 
+ /*
+- * xmit mutex and session lock must be held
++ * session lock must be held
+  */
+ static struct iscsi_mgmt_task *
+ iscsi_remove_mgmt_task(struct kfifo *fifo, uint32_t itt)
+@@ -1127,7 +1120,7 @@ static int iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask)
+ 	if (!ctask->mtask)
+ 		return -EINVAL;
+ 
+-	if (!iscsi_remove_mgmt_task(conn->immqueue, ctask->mtask->itt))
++	if (!iscsi_remove_mgmt_task(conn->mgmtqueue, ctask->mtask->itt))
+ 		list_del(&ctask->mtask->running);
+ 	__kfifo_put(session->mgmtpool.queue, (void*)&ctask->mtask,
+ 		    sizeof(void*));
+@@ -1136,7 +1129,7 @@ static int iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask)
+ }
+ 
+ /*
+- * session lock and xmitmutex must be held
++ * session lock must be held
+  */
+ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 			 int err)
+@@ -1147,11 +1140,14 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 	if (!sc)
+ 		return;
+ 
+-	conn->session->tt->cleanup_cmd_task(conn, ctask);
++	if (ctask->state != ISCSI_TASK_PENDING)
++		conn->session->tt->cleanup_cmd_task(conn, ctask);
+ 	iscsi_ctask_mtask_cleanup(ctask);
+ 
+ 	sc->result = err;
+ 	sc->resid = sc->request_bufflen;
++	if (conn->ctask == ctask)
++		conn->ctask = NULL;
+ 	/* release ref from queuecommand */
+ 	__iscsi_put_ctask(ctask);
+ }
+@@ -1179,7 +1175,6 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 	conn->eh_abort_cnt++;
+ 	debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt);
+ 
+-	mutex_lock(&conn->xmitmutex);
+ 	spin_lock_bh(&session->lock);
+ 
+ 	/*
+@@ -1192,9 +1187,8 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 
+ 	/* ctask completed before time out */
+ 	if (!ctask->sc) {
+-		spin_unlock_bh(&session->lock);
+ 		debug_scsi("sc completed while abort in progress\n");
+-		goto success_rel_mutex;
++		goto success;
+ 	}
+ 
+ 	/* what should we do here ? */
+@@ -1204,15 +1198,13 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 		goto failed;
+ 	}
+ 
+-	if (ctask->state == ISCSI_TASK_PENDING)
+-		goto success_cleanup;
++	if (ctask->state == ISCSI_TASK_PENDING) {
++		fail_command(conn, ctask, DID_ABORT << 16);
++		goto success;
++	}
+ 
+ 	conn->tmabort_state = TMABORT_INITIAL;
+-
+-	spin_unlock_bh(&session->lock);
+ 	rc = iscsi_exec_abort_task(sc, ctask);
+-	spin_lock_bh(&session->lock);
+-
+ 	if (rc || sc->SCp.phase != session->age ||
+ 	    session->state != ISCSI_STATE_LOGGED_IN)
+ 		goto failed;
+@@ -1220,45 +1212,44 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 
+ 	switch (conn->tmabort_state) {
+ 	case TMABORT_SUCCESS:
+-		goto success_cleanup;
++		spin_unlock_bh(&session->lock);
++		/*
++		 * clean up task if aborted. grab the recv lock as a writer
++		 */
++		write_lock_bh(conn->recv_lock);
++		spin_lock(&session->lock);
++		fail_command(conn, ctask, DID_ABORT << 16);
++		spin_unlock(&session->lock);
++		write_unlock_bh(conn->recv_lock);
++		/*
++		 * make sure xmit thread is not still touching the
++		 * ctask/scsi_cmnd
++		 */
++		scsi_flush_work(session->host);
++		goto success_unlocked;
+ 	case TMABORT_NOT_FOUND:
+ 		if (!ctask->sc) {
+ 			/* ctask completed before tmf abort response */
+-			spin_unlock_bh(&session->lock);
+ 			debug_scsi("sc completed while abort in progress\n");
+-			goto success_rel_mutex;
++			goto success;
+ 		}
+ 		/* fall through */
+ 	default:
+ 		/* timedout or failed */
+ 		spin_unlock_bh(&session->lock);
+ 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+-		spin_lock_bh(&session->lock);
+-		goto failed;
++		goto failed_unlocked;
+ 	}
+ 
+-success_cleanup:
+-	debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
++success:
+ 	spin_unlock_bh(&session->lock);
+-
+-	/*
+-	 * clean up task if aborted. we have the xmitmutex so grab
+-	 * the recv lock as a writer
+-	 */
+-	write_lock_bh(conn->recv_lock);
+-	spin_lock(&session->lock);
+-	fail_command(conn, ctask, DID_ABORT << 16);
+-	spin_unlock(&session->lock);
+-	write_unlock_bh(conn->recv_lock);
+-
+-success_rel_mutex:
+-	mutex_unlock(&conn->xmitmutex);
++success_unlocked:
++	debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
+ 	return SUCCESS;
+ 
+ failed:
+ 	spin_unlock_bh(&session->lock);
+-	mutex_unlock(&conn->xmitmutex);
+-
++failed_unlocked:
+ 	debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
+ 	return FAILED;
+ }
+@@ -1505,11 +1496,6 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ 	INIT_LIST_HEAD(&conn->xmitqueue);
+ 
+ 	/* initialize general immediate & non-immediate PDU commands queue */
+-	conn->immqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*),
+-			                GFP_KERNEL, NULL);
+-	if (conn->immqueue == ERR_PTR(-ENOMEM))
+-		goto immqueue_alloc_fail;
+-
+ 	conn->mgmtqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*),
+ 			                GFP_KERNEL, NULL);
+ 	if (conn->mgmtqueue == ERR_PTR(-ENOMEM))
+@@ -1533,7 +1519,6 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ 	conn->login_mtask->data = conn->data = data;
+ 
+ 	init_timer(&conn->tmabort_timer);
+-	mutex_init(&conn->xmitmutex);
+ 	init_waitqueue_head(&conn->ehwait);
+ 
+ 	return cls_conn;
+@@ -1544,8 +1529,6 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ login_mtask_alloc_fail:
+ 	kfifo_free(conn->mgmtqueue);
+ mgmtqueue_alloc_fail:
+-	kfifo_free(conn->immqueue);
+-immqueue_alloc_fail:
+ 	iscsi_destroy_conn(cls_conn);
+ 	return NULL;
+ }
+@@ -1564,10 +1547,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
+ 	struct iscsi_session *session = conn->session;
+ 	unsigned long flags;
+ 
+-	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+-	mutex_lock(&conn->xmitmutex);
+-
+ 	spin_lock_bh(&session->lock);
++	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+ 	conn->c_stage = ISCSI_CONN_CLEANUP_WAIT;
+ 	if (session->leadconn == conn) {
+ 		/*
+@@ -1578,8 +1559,6 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
+ 	}
+ 	spin_unlock_bh(&session->lock);
+ 
+-	mutex_unlock(&conn->xmitmutex);
+-
+ 	/*
+ 	 * Block until all in-progress commands for this connection
+ 	 * time out or fail.
+@@ -1616,7 +1595,6 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
+ 	}
+ 	spin_unlock_bh(&session->lock);
+ 
+-	kfifo_free(conn->immqueue);
+ 	kfifo_free(conn->mgmtqueue);
+ 
+ 	iscsi_destroy_conn(cls_conn);
+@@ -1677,8 +1655,7 @@ flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn)
+ 	struct iscsi_mgmt_task *mtask, *tmp;
+ 
+ 	/* handle pending */
+-	while (__kfifo_get(conn->immqueue, (void*)&mtask, sizeof(void*)) ||
+-	       __kfifo_get(conn->mgmtqueue, (void*)&mtask, sizeof(void*))) {
++	while (__kfifo_get(conn->mgmtqueue, (void*)&mtask, sizeof(void*))) {
+ 		if (mtask == conn->login_mtask)
+ 			continue;
+ 		debug_scsi("flushing pending mgmt task itt 0x%x\n", mtask->itt);
+@@ -1748,12 +1725,12 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ 	conn->c_stage = ISCSI_CONN_STOPPED;
+ 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+ 	spin_unlock_bh(&session->lock);
++	scsi_flush_work(session->host);
+ 
+ 	write_lock_bh(conn->recv_lock);
+ 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
+ 	write_unlock_bh(conn->recv_lock);
+ 
+-	mutex_lock(&conn->xmitmutex);
+ 	/*
+ 	 * for connection level recovery we should not calculate
+ 	 * header digest. conn->hdr_size used for optimization
+@@ -1777,8 +1754,6 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ 	fail_all_commands(conn);
+ 	flush_control_queues(session, conn);
+ 	spin_unlock_bh(&session->lock);
+-
+-	mutex_unlock(&conn->xmitmutex);
+ }
+ 
+ void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 61bc8f75b267..8d48cf8f2e3f 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -90,6 +90,7 @@ enum {
+ 	ISCSI_TASK_COMPLETED,
+ 	ISCSI_TASK_PENDING,
+ 	ISCSI_TASK_RUNNING,
++	ISCSI_TASK_ABORTING,
+ };
+ 
+ struct iscsi_cmd_task {
+@@ -150,18 +151,11 @@ struct iscsi_conn {
+ 	struct iscsi_cmd_task	*ctask;		/* xmit ctask in progress */
+ 
+ 	/* xmit */
+-	struct kfifo		*immqueue;	/* immediate xmit queue */
+ 	struct kfifo		*mgmtqueue;	/* mgmt (control) xmit queue */
+ 	struct list_head	mgmt_run_list;	/* list of control tasks */
+ 	struct list_head	xmitqueue;	/* data-path cmd queue */
+ 	struct list_head	run_list;	/* list of cmds in progress */
+ 	struct work_struct	xmitwork;	/* per-conn. xmit workqueue */
+-	/*
+-	 * serializes connection xmit, access to kfifos:
+-	 * xmitqueue, immqueue, mgmtqueue
+-	 */
+-	struct mutex		xmitmutex;
+-
+ 	unsigned long		suspend_tx;	/* suspend Tx */
+ 	unsigned long		suspend_rx;	/* suspend Rx */
+ 
+@@ -303,8 +297,7 @@ extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ /*
+  * pdu and task processing
+  */
+-extern int iscsi_check_assign_cmdsn(struct iscsi_session *,
+-				    struct iscsi_nopin *);
++extern void iscsi_update_cmdsn(struct iscsi_session *, struct iscsi_nopin *);
+ extern void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *,
+ 					struct iscsi_data *hdr);
+ extern int iscsi_conn_send_pdu(struct iscsi_cls_conn *, struct iscsi_hdr *,
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 1ac450b06909..abc4068621d8 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -117,8 +117,7 @@ struct iscsi_transport {
+ 			   struct iscsi_stats *stats);
+ 	void (*init_cmd_task) (struct iscsi_cmd_task *ctask);
+ 	void (*init_mgmt_task) (struct iscsi_conn *conn,
+-				struct iscsi_mgmt_task *mtask,
+-				char *data, uint32_t data_size);
++				struct iscsi_mgmt_task *mtask);
+ 	int (*xmit_cmd_task) (struct iscsi_conn *conn,
+ 			      struct iscsi_cmd_task *ctask);
+ 	void (*cleanup_cmd_task) (struct iscsi_conn *conn,

commit 218432c68085d6c2b04df57daaf105d2ffa2aa61
+Author: Mike Christie 
+Date:   Wed May 30 12:57:17 2007 -0500
+
+    [SCSI] iscsi tcp: fix iscsi xmit state machine
+    
+    If iscsi_tcp partially sends a header, it would recalculate the
+    header size and readd the size of the digest (if header digests
+    are used).This would cause us to send sizeof(digest) extra bytes
+    when we sent the rest of the header.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 1e722f5aabd4..0afdca2224c2 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -109,7 +109,7 @@ iscsi_hdr_digest(struct iscsi_conn *conn, struct iscsi_buf *buf,
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 
+ 	crypto_hash_digest(&tcp_conn->tx_hash, &buf->sg, buf->sg.length, crc);
+-	buf->sg.length = tcp_conn->hdr_size;
++	buf->sg.length += sizeof(u32);
+ }
+ 
+ static inline int
+@@ -423,7 +423,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 
+ 	tcp_ctask->exp_datasn = r2tsn + 1;
+ 	__kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*));
+-	tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
++	tcp_ctask->xmstate |= XMSTATE_SOL_HDR_INIT;
+ 	list_move_tail(&ctask->running, &conn->xmitqueue);
+ 
+ 	scsi_queue_work(session->host, &conn->xmitwork);
+@@ -1284,41 +1284,10 @@ static void iscsi_set_padding(struct iscsi_tcp_cmd_task *tcp_ctask,
+ static void
+ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask)
+ {
+-	struct scsi_cmnd *sc = ctask->sc;
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 
+ 	BUG_ON(__kfifo_len(tcp_ctask->r2tqueue));
+-
+-	tcp_ctask->sent = 0;
+-	tcp_ctask->sg_count = 0;
+-	tcp_ctask->exp_datasn = 0;
+-
+-	if (sc->sc_data_direction == DMA_TO_DEVICE) {
+-		tcp_ctask->xmstate = XMSTATE_W_HDR;
+-		BUG_ON(sc->request_bufflen == 0);
+-
+-		if (sc->use_sg) {
+-			struct scatterlist *sg = sc->request_buffer;
+-
+-			iscsi_buf_init_sg(&tcp_ctask->sendbuf, sg);
+-			tcp_ctask->sg = sg + 1;
+-			tcp_ctask->bad_sg = sg + sc->use_sg;
+-		} else {
+-			iscsi_buf_init_iov(&tcp_ctask->sendbuf,
+-					   sc->request_buffer,
+-					   sc->request_bufflen);
+-			tcp_ctask->sg = NULL;
+-			tcp_ctask->bad_sg = NULL;
+-		}
+-		debug_scsi("cmd [itt 0x%x total %d imm_data %d "
+-			   "unsol count %d, unsol offset %d]\n",
+-			   ctask->itt, sc->request_bufflen, ctask->imm_count,
+-			   ctask->unsol_count, ctask->unsol_offset);
+-	} else
+-		tcp_ctask->xmstate = XMSTATE_R_HDR;
+-
+-	iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)ctask->hdr,
+-			    sizeof(struct iscsi_hdr));
++	tcp_ctask->xmstate = XMSTATE_CMD_HDR_INIT;
+ }
+ 
+ /**
+@@ -1331,9 +1300,11 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask)
+  *	call it again later, or recover. '0' return code means successful
+  *	xmit.
+  *
+- *	Management xmit state machine consists of two states:
+- *		IN_PROGRESS_IMM_HEAD - PDU Header xmit in progress
+- *		IN_PROGRESS_IMM_DATA - PDU Data xmit in progress
++ *	Management xmit state machine consists of these states:
++ *		XMSTATE_IMM_HDR_INIT	- calculate digest of PDU Header
++ *		XMSTATE_IMM_HDR 	- PDU Header xmit in progress
++ *		XMSTATE_IMM_DATA 	- PDU Data xmit in progress
++ *		XMSTATE_IDLE		- management PDU is done
+  **/
+ static int
+ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
+@@ -1344,23 +1315,34 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
+ 	debug_scsi("mtask deq [cid %d state %x itt 0x%x]\n",
+ 		conn->id, tcp_mtask->xmstate, mtask->itt);
+ 
+-	if (tcp_mtask->xmstate & XMSTATE_IMM_HDR) {
+-		tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR;
+-		if (mtask->data_count)
++	if (tcp_mtask->xmstate & XMSTATE_IMM_HDR_INIT) {
++		iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr,
++				   sizeof(struct iscsi_hdr));
++
++		if (mtask->data_count) {
+ 			tcp_mtask->xmstate |= XMSTATE_IMM_DATA;
++			iscsi_buf_init_iov(&tcp_mtask->sendbuf,
++					   (char*)mtask->data,
++					   mtask->data_count);
++		}
++
+ 		if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE &&
+ 		    conn->stop_stage != STOP_CONN_RECOVER &&
+ 		    conn->hdrdgst_en)
+ 			iscsi_hdr_digest(conn, &tcp_mtask->headbuf,
+ 					(u8*)tcp_mtask->hdrext);
++
++		tcp_mtask->sent = 0;
++		tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR_INIT;
++		tcp_mtask->xmstate |= XMSTATE_IMM_HDR;
++	}
++
++	if (tcp_mtask->xmstate & XMSTATE_IMM_HDR) {
+ 		rc = iscsi_sendhdr(conn, &tcp_mtask->headbuf,
+ 				   mtask->data_count);
+-		if (rc) {
+-			tcp_mtask->xmstate |= XMSTATE_IMM_HDR;
+-			if (mtask->data_count)
+-				tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA;
++		if (rc)
+ 			return rc;
+-		}
++		tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR;
+ 	}
+ 
+ 	if (tcp_mtask->xmstate & XMSTATE_IMM_DATA) {
+@@ -1394,55 +1376,75 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
+ 	return 0;
+ }
+ 
+-static inline int
+-iscsi_send_read_hdr(struct iscsi_conn *conn,
+-		    struct iscsi_tcp_cmd_task *tcp_ctask)
++static int
++iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+-	int rc;
++	struct scsi_cmnd *sc = ctask->sc;
++	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++	int rc = 0;
+ 
+-	tcp_ctask->xmstate &= ~XMSTATE_R_HDR;
+-	if (conn->hdrdgst_en)
+-		iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
+-				 (u8*)tcp_ctask->hdrext);
+-	rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, 0);
+-	if (!rc) {
+-		BUG_ON(tcp_ctask->xmstate != XMSTATE_IDLE);
+-		return 0; /* wait for Data-In */
+-	}
+-	tcp_ctask->xmstate |= XMSTATE_R_HDR;
+-	return rc;
+-}
++	if (tcp_ctask->xmstate & XMSTATE_CMD_HDR_INIT) {
++		tcp_ctask->sent = 0;
++		tcp_ctask->sg_count = 0;
++		tcp_ctask->exp_datasn = 0;
++
++		if (sc->sc_data_direction == DMA_TO_DEVICE) {
++			if (sc->use_sg) {
++				struct scatterlist *sg = sc->request_buffer;
++
++				iscsi_buf_init_sg(&tcp_ctask->sendbuf, sg);
++				tcp_ctask->sg = sg + 1;
++				tcp_ctask->bad_sg = sg + sc->use_sg;
++			} else {
++				iscsi_buf_init_iov(&tcp_ctask->sendbuf,
++						   sc->request_buffer,
++						   sc->request_bufflen);
++				tcp_ctask->sg = NULL;
++				tcp_ctask->bad_sg = NULL;
++			}
+ 
+-static inline int
+-iscsi_send_write_hdr(struct iscsi_conn *conn,
+-		     struct iscsi_cmd_task *ctask)
+-{
+-	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+-	int rc;
++			debug_scsi("cmd [itt 0x%x total %d imm_data %d "
++				   "unsol count %d, unsol offset %d]\n",
++				   ctask->itt, sc->request_bufflen,
++				   ctask->imm_count, ctask->unsol_count,
++				   ctask->unsol_offset);
++		}
+ 
+-	tcp_ctask->xmstate &= ~XMSTATE_W_HDR;
+-	if (conn->hdrdgst_en)
+-		iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
+-				 (u8*)tcp_ctask->hdrext);
+-	rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count);
+-	if (rc) {
+-		tcp_ctask->xmstate |= XMSTATE_W_HDR;
+-		return rc;
++		iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)ctask->hdr,
++				  sizeof(struct iscsi_hdr));
++
++		if (conn->hdrdgst_en)
++			iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
++					 (u8*)tcp_ctask->hdrext);
++		tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_INIT;
++		tcp_ctask->xmstate |= XMSTATE_CMD_HDR_XMIT;
+ 	}
+ 
+-	if (ctask->imm_count) {
+-		tcp_ctask->xmstate |= XMSTATE_IMM_DATA;
+-		iscsi_set_padding(tcp_ctask, ctask->imm_count);
++	if (tcp_ctask->xmstate & XMSTATE_CMD_HDR_XMIT) {
++		rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count);
++		if (rc)
++			return rc;
++		tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_XMIT;
++
++		if (sc->sc_data_direction != DMA_TO_DEVICE)
++			return 0;
++
++		if (ctask->imm_count) {
++			tcp_ctask->xmstate |= XMSTATE_IMM_DATA;
++			iscsi_set_padding(tcp_ctask, ctask->imm_count);
+ 
+-		if (ctask->conn->datadgst_en) {
+-			iscsi_data_digest_init(ctask->conn->dd_data, tcp_ctask);
+-			tcp_ctask->immdigest = 0;
++			if (ctask->conn->datadgst_en) {
++				iscsi_data_digest_init(ctask->conn->dd_data,
++						       tcp_ctask);
++				tcp_ctask->immdigest = 0;
++			}
+ 		}
+-	}
+ 
+-	if (ctask->unsol_count)
+-		tcp_ctask->xmstate |= XMSTATE_UNS_HDR | XMSTATE_UNS_INIT;
+-	return 0;
++		if (ctask->unsol_count)
++			tcp_ctask->xmstate |=
++					XMSTATE_UNS_HDR | XMSTATE_UNS_INIT;
++	}
++	return rc;
+ }
+ 
+ static int
+@@ -1631,9 +1633,7 @@ static int iscsi_send_sol_pdu(struct iscsi_conn *conn,
+ 	struct iscsi_data_task *dtask;
+ 	int left, rc;
+ 
+-	if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) {
+-		tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
+-		tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
++	if (tcp_ctask->xmstate & XMSTATE_SOL_HDR_INIT) {
+ 		if (!tcp_ctask->r2t) {
+ 			spin_lock_bh(&session->lock);
+ 			__kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t,
+@@ -1647,12 +1647,19 @@ static int iscsi_send_sol_pdu(struct iscsi_conn *conn,
+ 		if (conn->hdrdgst_en)
+ 			iscsi_hdr_digest(conn, &r2t->headbuf,
+ 					(u8*)dtask->hdrext);
++		tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR_INIT;
++		tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
++	}
++
++	if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) {
++		r2t = tcp_ctask->r2t;
++		dtask = &r2t->dtask;
++
+ 		rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count);
+-		if (rc) {
+-			tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA;
+-			tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
++		if (rc)
+ 			return rc;
+-		}
++		tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
++		tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
+ 
+ 		if (conn->datadgst_en) {
+ 			iscsi_data_digest_init(conn->dd_data, tcp_ctask);
+@@ -1684,8 +1691,6 @@ static int iscsi_send_sol_pdu(struct iscsi_conn *conn,
+ 		left = r2t->data_length - r2t->sent;
+ 		if (left) {
+ 			iscsi_solicit_data_cont(conn, ctask, r2t, left);
+-			tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
+-			tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
+ 			goto send_hdr;
+ 		}
+ 
+@@ -1700,8 +1705,6 @@ static int iscsi_send_sol_pdu(struct iscsi_conn *conn,
+ 		if (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t,
+ 				sizeof(void*))) {
+ 			tcp_ctask->r2t = r2t;
+-			tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
+-			tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
+ 			spin_unlock_bh(&session->lock);
+ 			goto send_hdr;
+ 		}
+@@ -1710,6 +1713,46 @@ static int iscsi_send_sol_pdu(struct iscsi_conn *conn,
+ 	return 0;
+ }
+ 
++/**
++ * iscsi_tcp_ctask_xmit - xmit normal PDU task
++ * @conn: iscsi connection
++ * @ctask: iscsi command task
++ *
++ * Notes:
++ *	The function can return -EAGAIN in which case caller must
++ *	call it again later, or recover. '0' return code means successful
++ *	xmit.
++ *	The function is devided to logical helpers (above) for the different
++ *	xmit stages.
++ *
++ *iscsi_send_cmd_hdr()
++ *	XMSTATE_CMD_HDR_INIT - prepare Header and Data buffers Calculate
++ *	                       Header Digest
++ *	XMSTATE_CMD_HDR_XMIT - Transmit header in progress
++ *
++ *iscsi_send_padding
++ *	XMSTATE_W_PAD        - Prepare and send pading
++ *	XMSTATE_W_RESEND_PAD - retry send pading
++ *
++ *iscsi_send_digest
++ *	XMSTATE_W_RESEND_DATA_DIGEST - Finalize and send Data Digest
++ *	XMSTATE_W_RESEND_DATA_DIGEST - retry sending digest
++ *
++ *iscsi_send_unsol_hdr
++ *	XMSTATE_UNS_INIT     - prepare un-solicit data header and digest
++ *	XMSTATE_UNS_HDR      - send un-solicit header
++ *
++ *iscsi_send_unsol_pdu
++ *	XMSTATE_UNS_DATA     - send un-solicit data in progress
++ *
++ *iscsi_send_sol_pdu
++ *	XMSTATE_SOL_HDR_INIT - solicit data header and digest initialize
++ *	XMSTATE_SOL_HDR      - send solicit header
++ *	XMSTATE_SOL_DATA     - send solicit data
++ *
++ *iscsi_tcp_ctask_xmit
++ *	XMSTATE_IMM_DATA     - xmit managment data (??)
++ **/
+ static int
+ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+@@ -1725,14 +1768,11 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	if (ctask->mtask)
+ 		return rc;
+ 
+-	if (tcp_ctask->xmstate & XMSTATE_R_HDR)
+-		return iscsi_send_read_hdr(conn, tcp_ctask);
+-
+-	if (tcp_ctask->xmstate & XMSTATE_W_HDR) {
+-		rc = iscsi_send_write_hdr(conn, ctask);
+-		if (rc)
+-			return rc;
+-	}
++	rc = iscsi_send_cmd_hdr(conn, ctask);
++	if (rc)
++		return rc;
++	if (ctask->sc->sc_data_direction != DMA_TO_DEVICE)
++		return 0;
+ 
+ 	if (tcp_ctask->xmstate & XMSTATE_IMM_DATA) {
+ 		rc = iscsi_send_data(ctask, &tcp_ctask->sendbuf, &tcp_ctask->sg,
+@@ -1913,15 +1953,7 @@ iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask,
+ 		    char *data, uint32_t data_size)
+ {
+ 	struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data;
+-
+-	iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr,
+-			   sizeof(struct iscsi_hdr));
+-	tcp_mtask->xmstate = XMSTATE_IMM_HDR;
+-	tcp_mtask->sent = 0;
+-
+-	if (mtask->data_count)
+-		iscsi_buf_init_iov(&tcp_mtask->sendbuf, (char*)mtask->data,
+-				    mtask->data_count);
++	tcp_mtask->xmstate = XMSTATE_IMM_HDR_INIT;
+ }
+ 
+ static int
+diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
+index f909edbf61ee..b039160ebafd 100644
+--- a/drivers/scsi/iscsi_tcp.h
++++ b/drivers/scsi/iscsi_tcp.h
+@@ -32,8 +32,8 @@
+ 
+ /* xmit state machine */
+ #define XMSTATE_IDLE			0x0
+-#define XMSTATE_R_HDR			0x1
+-#define XMSTATE_W_HDR			0x2
++#define XMSTATE_CMD_HDR_INIT		0x1
++#define XMSTATE_CMD_HDR_XMIT		0x2
+ #define XMSTATE_IMM_HDR			0x4
+ #define XMSTATE_IMM_DATA		0x8
+ #define XMSTATE_UNS_INIT		0x10
+@@ -44,6 +44,8 @@
+ #define XMSTATE_W_PAD			0x200
+ #define XMSTATE_W_RESEND_PAD		0x400
+ #define XMSTATE_W_RESEND_DATA_DIGEST	0x800
++#define XMSTATE_IMM_HDR_INIT		0x1000
++#define XMSTATE_SOL_HDR_INIT		0x2000
+ 
+ #define ISCSI_PAD_LEN			4
+ #define ISCSI_SG_TABLESIZE		SG_ALL
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 63981edf9ab9..63f0a15d9887 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -125,6 +125,7 @@ static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ 			MAX_COMMAND_SIZE - sc->cmd_len);
+ 
+ 	ctask->data_count = 0;
++	ctask->imm_count = 0;
+ 	if (sc->sc_data_direction == DMA_TO_DEVICE) {
+ 		hdr->flags |= ISCSI_FLAG_CMD_WRITE;
+ 		/*
+@@ -141,7 +142,6 @@ static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ 		 *
+ 		 *      pad_count       bytes to be sent as zero-padding
+ 		 */
+-		ctask->imm_count = 0;
+ 		ctask->unsol_count = 0;
+ 		ctask->unsol_offset = 0;
+ 		ctask->unsol_datasn = 0;

commit b2c6416736b847b91950bd43cc5153e11a1f83ee
+Author: Mike Christie 
+Date:   Wed May 30 12:57:16 2007 -0500
+
+    [SCSI] iscsi class, iscsi_tcp, ib_iser: add sysfs chap file
+    
+    The attached patches add sysfs files for the chap settings
+    to the iscsi transport class, iscsi_tcp and ib_iser. This is
+    needed for software iscsi because there are times when iscsid
+    can die and it will need to reread the values it was using.
+    And it is needed by qla4xxx for basic management opertaions.
+    This patch does not hook in qla4xxx yet, because I am not sure
+    the mbx command to use.
+    
+    Signed-off-by: Mike Christie 
+    Cc: Roland Dreier 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 568f88bf7c91..6c8cd09c58f0 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -574,8 +574,9 @@ static struct iscsi_transport iscsi_iser_transport = {
+ 				  ISCSI_EXP_STATSN |
+ 				  ISCSI_PERSISTENT_PORT |
+ 				  ISCSI_PERSISTENT_ADDRESS |
+-				  ISCSI_TARGET_NAME |
+-				  ISCSI_TPGT,
++				  ISCSI_TARGET_NAME | ISCSI_TPGT |
++				  ISCSI_USERNAME | ISCSI_PASSWORD |
++				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS |
+ 				  ISCSI_HOST_INITIATOR_NAME,
+ 	.host_template          = &iscsi_iser_sht,
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index b2827d112cb0..1e722f5aabd4 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -2186,8 +2186,9 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 				  ISCSI_EXP_STATSN |
+ 				  ISCSI_PERSISTENT_PORT |
+ 				  ISCSI_PERSISTENT_ADDRESS |
+-				  ISCSI_TARGET_NAME |
+-				  ISCSI_TPGT,
++				  ISCSI_TARGET_NAME | ISCSI_TPGT |
++				  ISCSI_USERNAME | ISCSI_PASSWORD |
++				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN,
+ 	.host_param_mask	= ISCSI_HOST_HWADDRESS |
+ 				  ISCSI_HOST_INITIATOR_NAME,
+ 	.host_template		= &iscsi_sht,
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 0a9c64e9ce8b..63981edf9ab9 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1461,6 +1461,10 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+ 	iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
+ 	iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
+ 
++	kfree(session->password);
++	kfree(session->password_in);
++	kfree(session->username);
++	kfree(session->username_in);
+ 	kfree(session->targetname);
+ 	kfree(session->hwaddress);
+ 	kfree(session->initiatorname);
+@@ -1869,6 +1873,30 @@ int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
+ 	case ISCSI_PARAM_EXP_STATSN:
+ 		sscanf(buf, "%u", &conn->exp_statsn);
+ 		break;
++	case ISCSI_PARAM_USERNAME:
++		kfree(session->username);
++		session->username = kstrdup(buf, GFP_KERNEL);
++		if (!session->username)
++			return -ENOMEM;
++		break;
++	case ISCSI_PARAM_USERNAME_IN:
++		kfree(session->username_in);
++		session->username_in = kstrdup(buf, GFP_KERNEL);
++		if (!session->username_in)
++			return -ENOMEM;
++		break;
++	case ISCSI_PARAM_PASSWORD:
++		kfree(session->password);
++		session->password = kstrdup(buf, GFP_KERNEL);
++		if (!session->password)
++			return -ENOMEM;
++		break;
++	case ISCSI_PARAM_PASSWORD_IN:
++		kfree(session->password_in);
++		session->password_in = kstrdup(buf, GFP_KERNEL);
++		if (!session->password_in)
++			return -ENOMEM;
++		break;
+ 	case ISCSI_PARAM_TARGET_NAME:
+ 		/* this should not change between logins */
+ 		if (session->targetname)
+@@ -1942,6 +1970,18 @@ int iscsi_session_get_param(struct iscsi_cls_session *cls_session,
+ 	case ISCSI_PARAM_TPGT:
+ 		len = sprintf(buf, "%d\n", session->tpgt);
+ 		break;
++	case ISCSI_PARAM_USERNAME:
++		len = sprintf(buf, "%s\n", session->username);
++		break;
++	case ISCSI_PARAM_USERNAME_IN:
++		len = sprintf(buf, "%s\n", session->username_in);
++		break;
++	case ISCSI_PARAM_PASSWORD:
++		len = sprintf(buf, "%s\n", session->password);
++		break;
++	case ISCSI_PARAM_PASSWORD_IN:
++		len = sprintf(buf, "%s\n", session->password_in);
++		break;
+ 	default:
+ 		return -ENOSYS;
+ 	}
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 5ec2fbea8937..341d4fb5c6f8 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -30,7 +30,7 @@
+ #include 
+ #include 
+ 
+-#define ISCSI_SESSION_ATTRS 11
++#define ISCSI_SESSION_ATTRS 15
+ #define ISCSI_CONN_ATTRS 11
+ #define ISCSI_HOST_ATTRS 2
+ #define ISCSI_TRANSPORT_VERSION "2.0-724"
+@@ -1196,30 +1196,37 @@ iscsi_conn_attr(address, ISCSI_PARAM_CONN_ADDRESS);
+ /*
+  * iSCSI session attrs
+  */
+-#define iscsi_session_attr_show(param)					\
++#define iscsi_session_attr_show(param, perm)				\
+ static ssize_t								\
+ show_session_param_##param(struct class_device *cdev, char *buf)	\
+ {									\
+ 	struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
+ 	struct iscsi_transport *t = session->transport;			\
++									\
++	if (perm && !capable(CAP_SYS_ADMIN))				\
++		return -EACCES;						\
+ 	return t->get_session_param(session, param, buf);		\
+ }
+ 
+-#define iscsi_session_attr(field, param)				\
+-	iscsi_session_attr_show(param)					\
++#define iscsi_session_attr(field, param, perm)				\
++	iscsi_session_attr_show(param, perm)				\
+ static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_param_##param, \
+ 			NULL);
+ 
+-iscsi_session_attr(targetname, ISCSI_PARAM_TARGET_NAME);
+-iscsi_session_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN);
+-iscsi_session_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T);
+-iscsi_session_attr(immediate_data, ISCSI_PARAM_IMM_DATA_EN);
+-iscsi_session_attr(first_burst_len, ISCSI_PARAM_FIRST_BURST);
+-iscsi_session_attr(max_burst_len, ISCSI_PARAM_MAX_BURST);
+-iscsi_session_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN);
+-iscsi_session_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN);
+-iscsi_session_attr(erl, ISCSI_PARAM_ERL);
+-iscsi_session_attr(tpgt, ISCSI_PARAM_TPGT);
++iscsi_session_attr(targetname, ISCSI_PARAM_TARGET_NAME, 0);
++iscsi_session_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN, 0);
++iscsi_session_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T, 0);
++iscsi_session_attr(immediate_data, ISCSI_PARAM_IMM_DATA_EN, 0);
++iscsi_session_attr(first_burst_len, ISCSI_PARAM_FIRST_BURST, 0);
++iscsi_session_attr(max_burst_len, ISCSI_PARAM_MAX_BURST, 0);
++iscsi_session_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN, 0);
++iscsi_session_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN, 0);
++iscsi_session_attr(erl, ISCSI_PARAM_ERL, 0);
++iscsi_session_attr(tpgt, ISCSI_PARAM_TPGT, 0);
++iscsi_session_attr(username, ISCSI_PARAM_USERNAME, 1);
++iscsi_session_attr(username_in, ISCSI_PARAM_USERNAME_IN, 1);
++iscsi_session_attr(password, ISCSI_PARAM_PASSWORD, 1);
++iscsi_session_attr(password_in, ISCSI_PARAM_PASSWORD_IN, 1);
+ 
+ #define iscsi_priv_session_attr_show(field, format)			\
+ static ssize_t								\
+@@ -1433,6 +1440,10 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 	SETUP_SESSION_RD_ATTR(erl, ISCSI_ERL);
+ 	SETUP_SESSION_RD_ATTR(targetname, ISCSI_TARGET_NAME);
+ 	SETUP_SESSION_RD_ATTR(tpgt, ISCSI_TPGT);
++	SETUP_SESSION_RD_ATTR(password, ISCSI_USERNAME);
++	SETUP_SESSION_RD_ATTR(password_in, ISCSI_USERNAME_IN);
++	SETUP_SESSION_RD_ATTR(username, ISCSI_PASSWORD);
++	SETUP_SESSION_RD_ATTR(username_in, ISCSI_PASSWORD_IN);
+ 	SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo);
+ 
+ 	BUG_ON(count > ISCSI_SESSION_ATTRS);
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index e057c5d3703d..1a18196d77f6 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -229,6 +229,11 @@ enum iscsi_param {
+ 	ISCSI_PARAM_CONN_PORT,
+ 	ISCSI_PARAM_CONN_ADDRESS,
+ 
++	ISCSI_PARAM_USERNAME,
++	ISCSI_PARAM_USERNAME_IN,
++	ISCSI_PARAM_PASSWORD,
++	ISCSI_PARAM_PASSWORD_IN,
++
+ 	/* must always be last */
+ 	ISCSI_PARAM_MAX,
+ };
+@@ -255,6 +260,10 @@ enum iscsi_param {
+ #define ISCSI_SESS_RECOVERY_TMO		(1 << ISCSI_PARAM_SESS_RECOVERY_TMO)
+ #define ISCSI_CONN_PORT			(1 << ISCSI_PARAM_CONN_PORT)
+ #define ISCSI_CONN_ADDRESS		(1 << ISCSI_PARAM_CONN_ADDRESS)
++#define ISCSI_USERNAME			(1 << ISCSI_PARAM_USERNAME)
++#define ISCSI_USERNAME_IN		(1 << ISCSI_PARAM_USERNAME_IN)
++#define ISCSI_PASSWORD			(1 << ISCSI_PARAM_PASSWORD)
++#define ISCSI_PASSWORD_IN		(1 << ISCSI_PARAM_PASSWORD_IN)
+ 
+ /* iSCSI HBA params */
+ enum iscsi_host_param {
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 348265d4a27e..61bc8f75b267 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -221,6 +221,10 @@ struct iscsi_session {
+ 	int			dataseq_inorder_en;
+ 	int			erl;
+ 	int			tpgt;
++	char			*username;
++	char			*username_in;
++	char			*password;
++	char			*password_in;
+ 	char			*targetname;
+ 	char			*initiatorname;
+ 	/* hw address being used for iscsi connection */

commit 857ae0bdb72999936a28ce621e38e2e288c485da
+Author: Mike Christie 
+Date:   Wed May 30 12:57:15 2007 -0500
+
+    [SCSI] iscsi: Some fixes in preparation for bidirectional support - total_length
+    
+    - Remove shadow of request length from struct iscsi_cmd_task.
+    - change all users to use scsi_cmnd->request_bufflen directly
+    
+    (With bidi we will use scsi-ml API to retrieve in/out length)
+    
+    Signed-off-by: Boaz Harrosh 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Mike Christie 
+    Cc: Roland Dreier 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index e39d9a07bc5d..568f88bf7c91 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -140,10 +140,10 @@ iscsi_iser_cmd_init(struct iscsi_cmd_task *ctask)
+ 	iser_ctask->iser_conn    = iser_conn;
+ 
+ 	if (sc->sc_data_direction == DMA_TO_DEVICE) {
+-		BUG_ON(ctask->total_length == 0);
++		BUG_ON(sc->request_bufflen == 0);
+ 
+ 		debug_scsi("cmd [itt %x total %d imm %d unsol_data %d\n",
+-			   ctask->itt, ctask->total_length, ctask->imm_count,
++			   ctask->itt, sc->request_bufflen, ctask->imm_count,
+ 			   ctask->unsol_count);
+ 	}
+ 
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 17fc79c408a2..b2827d112cb0 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -216,6 +216,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)tcp_conn->in.hdr;
+ 	struct iscsi_session *session = conn->session;
++	struct scsi_cmnd *sc = ctask->sc;
+ 	int datasn = be32_to_cpu(rhdr->datasn);
+ 
+ 	rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr);
+@@ -238,12 +239,14 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	tcp_ctask->exp_datasn++;
+ 
+ 	tcp_ctask->data_offset = be32_to_cpu(rhdr->offset);
+-	if (tcp_ctask->data_offset + tcp_conn->in.datalen > ctask->total_length)
++	if (tcp_ctask->data_offset + tcp_conn->in.datalen > sc->request_bufflen) {
++		debug_tcp("%s: data_offset(%d) + data_len(%d) > total_length_in(%d)\n",
++		          __FUNCTION__, tcp_ctask->data_offset,
++		          tcp_conn->in.datalen, sc->request_bufflen);
+ 		return ISCSI_ERR_DATA_OFFSET;
++	}
+ 
+ 	if (rhdr->flags & ISCSI_FLAG_DATA_STATUS) {
+-		struct scsi_cmnd *sc = ctask->sc;
+-
+ 		conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
+ 		if (rhdr->flags & ISCSI_FLAG_DATA_UNDERFLOW) {
+ 			int res_count = be32_to_cpu(rhdr->residual_count);
+@@ -405,11 +408,11 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 			    r2t->data_length, session->max_burst);
+ 
+ 	r2t->data_offset = be32_to_cpu(rhdr->data_offset);
+-	if (r2t->data_offset + r2t->data_length > ctask->total_length) {
++	if (r2t->data_offset + r2t->data_length > ctask->sc->request_bufflen) {
+ 		spin_unlock(&session->lock);
+ 		printk(KERN_ERR "iscsi_tcp: invalid R2T with data len %u at "
+ 		       "offset %u and total length %d\n", r2t->data_length,
+-		       r2t->data_offset, ctask->total_length);
++		       r2t->data_offset, ctask->sc->request_bufflen);
+ 		return ISCSI_ERR_DATALEN;
+ 	}
+ 
+@@ -604,7 +607,7 @@ iscsi_ctask_copy(struct iscsi_tcp_conn *tcp_conn, struct iscsi_cmd_task *ctask,
+ {
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	int buf_left = buf_size - (tcp_conn->data_copied + offset);
+-	int size = min(tcp_conn->in.copy, buf_left);
++	unsigned size = min(tcp_conn->in.copy, buf_left);
+ 	int rc;
+ 
+ 	size = min(size, ctask->data_count);
+@@ -613,7 +616,7 @@ iscsi_ctask_copy(struct iscsi_tcp_conn *tcp_conn, struct iscsi_cmd_task *ctask,
+ 	       size, tcp_conn->in.offset, tcp_conn->in.copied);
+ 
+ 	BUG_ON(size <= 0);
+-	BUG_ON(tcp_ctask->sent + size > ctask->total_length);
++	BUG_ON(tcp_ctask->sent + size > ctask->sc->request_bufflen);
+ 
+ 	rc = skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset,
+ 			   (char*)buf + (offset + tcp_conn->data_copied), size);
+@@ -1292,7 +1295,7 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask)
+ 
+ 	if (sc->sc_data_direction == DMA_TO_DEVICE) {
+ 		tcp_ctask->xmstate = XMSTATE_W_HDR;
+-		BUG_ON(ctask->total_length == 0);
++		BUG_ON(sc->request_bufflen == 0);
+ 
+ 		if (sc->use_sg) {
+ 			struct scatterlist *sg = sc->request_buffer;
+@@ -1309,7 +1312,7 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask)
+ 		}
+ 		debug_scsi("cmd [itt 0x%x total %d imm_data %d "
+ 			   "unsol count %d, unsol offset %d]\n",
+-			   ctask->itt, ctask->total_length, ctask->imm_count,
++			   ctask->itt, sc->request_bufflen, ctask->imm_count,
+ 			   ctask->unsol_count, ctask->unsol_offset);
+ 	} else
+ 		tcp_ctask->xmstate = XMSTATE_R_HDR;
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index eb5113607958..0a9c64e9ce8b 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -147,19 +147,19 @@ static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ 		ctask->unsol_datasn = 0;
+ 
+ 		if (session->imm_data_en) {
+-			if (ctask->total_length >= session->first_burst)
++			if (sc->request_bufflen >= session->first_burst)
+ 				ctask->imm_count = min(session->first_burst,
+ 							conn->max_xmit_dlength);
+ 			else
+-				ctask->imm_count = min(ctask->total_length,
++				ctask->imm_count = min(sc->request_bufflen,
+ 							conn->max_xmit_dlength);
+ 			hton24(ctask->hdr->dlength, ctask->imm_count);
+ 		} else
+ 			zero_data(ctask->hdr->dlength);
+ 
+ 		if (!session->initial_r2t_en) {
+-			ctask->unsol_count = min(session->first_burst,
+-				ctask->total_length) - ctask->imm_count;
++			ctask->unsol_count = min((session->first_burst),
++				(sc->request_bufflen)) - ctask->imm_count;
+ 			ctask->unsol_offset = ctask->imm_count;
+ 		}
+ 
+@@ -815,7 +815,6 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 	ctask->conn = conn;
+ 	ctask->sc = sc;
+ 	INIT_LIST_HEAD(&ctask->running);
+-	ctask->total_length = sc->request_bufflen;
+ 	iscsi_prep_scsi_cmd_pdu(ctask);
+ 
+ 	session->tt->init_cmd_task(ctask);
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 61e069206ac5..348265d4a27e 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -80,7 +80,7 @@ struct iscsi_mgmt_task {
+ 	 */
+ 	struct iscsi_hdr	*hdr;
+ 	char			*data;		/* mgmt payload */
+-	int			data_count;	/* counts data to be sent */
++	unsigned		data_count;	/* counts data to be sent */
+ 	uint32_t		itt;		/* this ITT */
+ 	void			*dd_data;	/* driver/transport data */
+ 	struct list_head	running;
+@@ -101,13 +101,12 @@ struct iscsi_cmd_task {
+ 	int			itt;		/* this ITT */
+ 
+ 	uint32_t		unsol_datasn;
+-	int			imm_count;	/* imm-data (bytes)   */
+-	int			unsol_count;	/* unsolicited (bytes)*/
++	unsigned		imm_count;	/* imm-data (bytes)   */
++	unsigned		unsol_count;	/* unsolicited (bytes)*/
+ 	/* offset in unsolicited stream (bytes); */
+-	int			unsol_offset;
+-	int			data_count;	/* remaining Data-Out */
++	unsigned		unsol_offset;
++	unsigned		data_count;	/* remaining Data-Out */
+ 	struct scsi_cmnd	*sc;		/* associated SCSI cmd*/
+-	int			total_length;
+ 	struct iscsi_conn	*conn;		/* used connection    */
+ 	struct iscsi_mgmt_task	*mtask;		/* tmf mtask in progr */
+ 
+@@ -173,8 +172,8 @@ struct iscsi_conn {
+ 	int			tmabort_state;	/* see TMABORT_INITIAL, etc.*/
+ 
+ 	/* negotiated params */
+-	int			max_recv_dlength; /* initiator_max_recv_dsl*/
+-	int			max_xmit_dlength; /* target_max_recv_dsl */
++	unsigned		max_recv_dlength; /* initiator_max_recv_dsl*/
++	unsigned		max_xmit_dlength; /* target_max_recv_dsl */
+ 	int			hdrdgst_en;
+ 	int			datadgst_en;
+ 	int			ifmarker_en;
+@@ -212,10 +211,10 @@ struct iscsi_session {
+ 
+ 	/* configuration */
+ 	int			initial_r2t_en;
+-	int			max_r2t;
++	unsigned		max_r2t;
+ 	int			imm_data_en;
+-	int			first_burst;
+-	int			max_burst;
++	unsigned		first_burst;
++	unsigned		max_burst;
+ 	int			time2wait;
+ 	int			time2retain;
+ 	int			pdu_inorder_en;

commit d473cc7f15f64ab8a90c3d7288ef30f46785d8d5
+Author: Mike Christie 
+Date:   Wed May 30 12:57:14 2007 -0500
+
+    [SCSI] iscsi: Some fixes in preparation for bidirectional support - exp_datasn
+    
+    This patch fixes handling of expected datasn/r2tsn as received from
+    target. It is done according to: T10 rfc3720 section 3.2.2.3. Data Sequencing.
+    
+    . unify expected datasn/r2tsn into one counter
+    . calculate than check expected datasn/r2tsn. On error print a message
+      and fail the request. (TODO use iscsi retransmits)
+    . remove the FIXME   ;)
+    . avoid zero length memset
+    
+    Signed-off-by: Boaz Harrosh 
+    Signed-off-by: Benny Halevy 
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 8201e6c4d8a9..17fc79c408a2 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -229,10 +229,13 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	if (tcp_conn->in.datalen == 0)
+ 		return 0;
+ 
+-	if (ctask->datasn != datasn)
++	if (tcp_ctask->exp_datasn != datasn) {
++		debug_tcp("%s: ctask->exp_datasn(%d) != rhdr->datasn(%d)\n",
++		          __FUNCTION__, tcp_ctask->exp_datasn, datasn);
+ 		return ISCSI_ERR_DATASN;
++	}
+ 
+-	ctask->datasn++;
++	tcp_ctask->exp_datasn++;
+ 
+ 	tcp_ctask->data_offset = be32_to_cpu(rhdr->offset);
+ 	if (tcp_ctask->data_offset + tcp_conn->in.datalen > ctask->total_length)
+@@ -365,15 +368,16 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 		return ISCSI_ERR_DATALEN;
+ 	}
+ 
+-	if (tcp_ctask->exp_r2tsn && tcp_ctask->exp_r2tsn != r2tsn)
++	if (tcp_ctask->exp_datasn != r2tsn){
++		debug_tcp("%s: ctask->exp_datasn(%d) != rhdr->r2tsn(%d)\n",
++		          __FUNCTION__, tcp_ctask->exp_datasn, r2tsn);
+ 		return ISCSI_ERR_R2TSN;
++	}
+ 
+ 	rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr);
+ 	if (rc)
+ 		return rc;
+ 
+-	/* FIXME: use R2TSN to detect missing R2T */
+-
+ 	/* fill-in new R2T associated with the task */
+ 	spin_lock(&session->lock);
+ 	if (!ctask->sc || ctask->mtask ||
+@@ -414,7 +418,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 
+ 	iscsi_solicit_data_init(conn, ctask, r2t);
+ 
+-	tcp_ctask->exp_r2tsn = r2tsn + 1;
++	tcp_ctask->exp_datasn = r2tsn + 1;
+ 	__kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*));
+ 	tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
+ 	list_move_tail(&ctask->running, &conn->xmitqueue);
+@@ -1284,10 +1288,10 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask)
+ 
+ 	tcp_ctask->sent = 0;
+ 	tcp_ctask->sg_count = 0;
++	tcp_ctask->exp_datasn = 0;
+ 
+ 	if (sc->sc_data_direction == DMA_TO_DEVICE) {
+ 		tcp_ctask->xmstate = XMSTATE_W_HDR;
+-		tcp_ctask->exp_r2tsn = 0;
+ 		BUG_ON(ctask->total_length == 0);
+ 
+ 		if (sc->use_sg) {
+diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
+index 32736831790e..f909edbf61ee 100644
+--- a/drivers/scsi/iscsi_tcp.h
++++ b/drivers/scsi/iscsi_tcp.h
+@@ -152,7 +152,7 @@ struct iscsi_tcp_cmd_task {
+ 	struct scatterlist	*sg;			/* per-cmd SG list  */
+ 	struct scatterlist	*bad_sg;		/* assert statement */
+ 	int			sg_count;		/* SG's to process  */
+-	uint32_t		exp_r2tsn;
++	uint32_t		exp_datasn;		/* expected target's R2TSN/DataSN */
+ 	int			data_offset;
+ 	struct iscsi_r2t_info	*r2t;			/* in progress R2T    */
+ 	struct iscsi_queue	r2tpool;
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 5e6a42429c39..eb5113607958 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -120,7 +120,9 @@ static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+         session->cmdsn++;
+         hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
+         memcpy(hdr->cdb, sc->cmnd, sc->cmd_len);
+-        memset(&hdr->cdb[sc->cmd_len], 0, MAX_COMMAND_SIZE - sc->cmd_len);
++	if (sc->cmd_len < MAX_COMMAND_SIZE)
++		memset(&hdr->cdb[sc->cmd_len], 0,
++			MAX_COMMAND_SIZE - sc->cmd_len);
+ 
+ 	ctask->data_count = 0;
+ 	if (sc->sc_data_direction == DMA_TO_DEVICE) {
+@@ -165,7 +167,6 @@ static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ 			/* No unsolicit Data-Out's */
+ 			ctask->hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+ 	} else {
+-		ctask->datasn = 0;
+ 		hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+ 		zero_data(hdr->dlength);
+ 
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index deae90a56a0d..61e069206ac5 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -99,7 +99,6 @@ struct iscsi_cmd_task {
+ 	 */
+ 	struct iscsi_cmd	*hdr;
+ 	int			itt;		/* this ITT */
+-	int			datasn;		/* DataSN */
+ 
+ 	uint32_t		unsol_datasn;
+ 	int			imm_count;	/* imm-data (bytes)   */

commit 8ad5781ae9702a8f95cfdf30967752e4297613ee
+Author: Mike Christie 
+Date:   Wed May 30 12:57:13 2007 -0500
+
+    [SCSI] iscsi class, qla4xxx, iscsi_tcp, ib_iser: export/set initiator name
+    
+    For iscsi root boot, software iscsi needs to know what the BIOS/OF
+    initiator used for the initiator name so this puts it in sysfs
+    for userspace to be able to pick up.
+    
+    For hw iscsi, it is nice to see what the card is using.
+    
+    This patch adds the new param, and hooks in qla4xxx, iscsi_tcp, and ib_iser.
+    
+    Signed-off-by: Mike Christie 
+    Cc: Roland Dreier 
+    Cc: David C Somayajulu 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 2a99b7b6c906..e39d9a07bc5d 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -576,7 +576,8 @@ static struct iscsi_transport iscsi_iser_transport = {
+ 				  ISCSI_PERSISTENT_ADDRESS |
+ 				  ISCSI_TARGET_NAME |
+ 				  ISCSI_TPGT,
+-	.host_param_mask	= ISCSI_HOST_HWADDRESS,
++	.host_param_mask	= ISCSI_HOST_HWADDRESS |
++				  ISCSI_HOST_INITIATOR_NAME,
+ 	.host_template          = &iscsi_iser_sht,
+ 	.conndata_size		= sizeof(struct iscsi_conn),
+ 	.max_lun                = ISCSI_ISER_MAX_LUN,
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 9a42fc074b76..8201e6c4d8a9 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -2181,7 +2181,8 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 				  ISCSI_PERSISTENT_ADDRESS |
+ 				  ISCSI_TARGET_NAME |
+ 				  ISCSI_TPGT,
+-	.host_param_mask	= ISCSI_HOST_HWADDRESS,
++	.host_param_mask	= ISCSI_HOST_HWADDRESS |
++				  ISCSI_HOST_INITIATOR_NAME,
+ 	.host_template		= &iscsi_sht,
+ 	.conndata_size		= sizeof(struct iscsi_conn),
+ 	.max_conn		= 1,
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index d430e227e9b7..5e6a42429c39 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1463,6 +1463,7 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+ 
+ 	kfree(session->targetname);
+ 	kfree(session->hwaddress);
++	kfree(session->initiatorname);
+ 
+ 	iscsi_destroy_session(cls_session);
+ 	scsi_host_put(shost);
+@@ -2004,6 +2005,13 @@ int iscsi_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param,
+ 		else
+ 			len = sprintf(buf, "%s\n", session->hwaddress);
+ 		break;
++	case ISCSI_HOST_PARAM_INITIATOR_NAME:
++		if (!session->initiatorname)
++			len = sprintf(buf, "%s\n", "unknown");
++		else
++			len = sprintf(buf, "%s\n", session->initiatorname);
++		break;
++
+ 	default:
+ 		return -ENOSYS;
+ 	}
+@@ -2022,6 +2030,10 @@ int iscsi_host_set_param(struct Scsi_Host *shost, enum iscsi_host_param param,
+ 		if (!session->hwaddress)
+ 			session->hwaddress = kstrdup(buf, GFP_KERNEL);
+ 		break;
++	case ISCSI_HOST_PARAM_INITIATOR_NAME:
++		if (!session->initiatorname)
++			session->initiatorname = kstrdup(buf, GFP_KERNEL);
++		break;
+ 	default:
+ 		return -ENOSYS;
+ 	}
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index 29cd4b90ebed..7502bb4808d6 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -104,7 +104,8 @@ static struct iscsi_transport qla4xxx_iscsi_transport = {
+ 	.name			= DRIVER_NAME,
+ 	.param_mask		= ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS |
+ 				  ISCSI_TARGET_NAME | ISCSI_TPGT,
+-	.host_param_mask	= ISCSI_HOST_HWADDRESS,
++	.host_param_mask	= ISCSI_HOST_HWADDRESS |
++				  ISCSI_HOST_INITIATOR_NAME,
+ 	.sessiondata_size	= sizeof(struct ddb_entry),
+ 	.host_template		= &qla4xxx_driver_template,
+ 
+@@ -190,6 +191,9 @@ static int qla4xxx_host_get_param(struct Scsi_Host *shost,
+ 	case ISCSI_HOST_PARAM_HWADDRESS:
+ 		len = format_addr(buf, ha->my_mac, MAC_ADDR_LEN);
+ 		break;
++	case ISCSI_HOST_PARAM_INITIATOR_NAME:
++		len = sprintf(buf, ha->name_string);
++		break;
+ 	default:
+ 		return -ENOSYS;
+ 	}
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 3fd2da451fe1..5ec2fbea8937 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -32,7 +32,7 @@
+ 
+ #define ISCSI_SESSION_ATTRS 11
+ #define ISCSI_CONN_ATTRS 11
+-#define ISCSI_HOST_ATTRS 1
++#define ISCSI_HOST_ATTRS 2
+ #define ISCSI_TRANSPORT_VERSION "2.0-724"
+ 
+ struct iscsi_internal {
+@@ -1253,6 +1253,7 @@ static ISCSI_CLASS_ATTR(host, field, S_IRUGO, show_host_param_##param,	\
+ 			NULL);
+ 
+ iscsi_host_attr(hwaddress, ISCSI_HOST_PARAM_HWADDRESS);
++iscsi_host_attr(initiatorname, ISCSI_HOST_PARAM_INITIATOR_NAME);
+ 
+ #define SETUP_PRIV_SESSION_RD_ATTR(field)				\
+ do {									\
+@@ -1389,6 +1390,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 	transport_container_register(&priv->t.host_attrs);
+ 
+ 	SETUP_HOST_RD_ATTR(hwaddress, ISCSI_HOST_HWADDRESS);
++	SETUP_HOST_RD_ATTR(initiatorname, ISCSI_HOST_INITIATOR_NAME);
+ 	BUG_ON(count > ISCSI_HOST_ATTRS);
+ 	priv->host_attrs[count] = NULL;
+ 	count = 0;
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index 3d0372e30ca1..e057c5d3703d 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -259,10 +259,12 @@ enum iscsi_param {
+ /* iSCSI HBA params */
+ enum iscsi_host_param {
+ 	ISCSI_HOST_PARAM_HWADDRESS,
++	ISCSI_HOST_PARAM_INITIATOR_NAME,
+ 	ISCSI_HOST_PARAM_MAX,
+ };
+ 
+ #define ISCSI_HOST_HWADDRESS		(1 << ISCSI_HOST_PARAM_HWADDRESS)
++#define ISCSI_HOST_INITIATOR_NAME	(1 << ISCSI_HOST_PARAM_INITIATOR_NAME)
+ 
+ #define iscsi_ptr(_handle) ((void*)(unsigned long)_handle)
+ #define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr)
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index e202cc00c8e7..deae90a56a0d 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -224,6 +224,7 @@ struct iscsi_session {
+ 	int			erl;
+ 	int			tpgt;
+ 	char			*targetname;
++	char			*initiatorname;
+ 	/* hw address being used for iscsi connection */
+ 	char			*hwaddress;
+ 	/* control data */

commit 0801c242a33426fddc005c2f559a3d2fa6fca7eb
+Author: Mike Christie 
+Date:   Wed May 30 12:57:12 2007 -0500
+
+    [SCSI] libiscsi, iscsi_tcp, ib_iser : add sw iscsi host get/set params helpers
+    
+    iscsid and udev need to key off the hw address being
+    used so add some helpers for iser and iscsi tcp.
+    
+    Also convert them
+    
+    Signed-off-by: Mike Christie 
+    Cc: Roland Dreier 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index dd221eda3ea6..2a99b7b6c906 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -576,6 +576,7 @@ static struct iscsi_transport iscsi_iser_transport = {
+ 				  ISCSI_PERSISTENT_ADDRESS |
+ 				  ISCSI_TARGET_NAME |
+ 				  ISCSI_TPGT,
++	.host_param_mask	= ISCSI_HOST_HWADDRESS,
+ 	.host_template          = &iscsi_iser_sht,
+ 	.conndata_size		= sizeof(struct iscsi_conn),
+ 	.max_lun                = ISCSI_ISER_MAX_LUN,
+@@ -592,6 +593,9 @@ static struct iscsi_transport iscsi_iser_transport = {
+ 	.get_session_param	= iscsi_session_get_param,
+ 	.start_conn             = iscsi_iser_conn_start,
+ 	.stop_conn              = iscsi_conn_stop,
++	/* iscsi host params */
++	.get_host_param		= iscsi_host_get_param,
++	.set_host_param		= iscsi_host_set_param,
+ 	/* IO */
+ 	.send_pdu		= iscsi_conn_send_pdu,
+ 	.get_stats		= iscsi_iser_conn_get_stats,
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index c9a3abf9e7b6..9a42fc074b76 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -2181,6 +2181,7 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 				  ISCSI_PERSISTENT_ADDRESS |
+ 				  ISCSI_TARGET_NAME |
+ 				  ISCSI_TPGT,
++	.host_param_mask	= ISCSI_HOST_HWADDRESS,
+ 	.host_template		= &iscsi_sht,
+ 	.conndata_size		= sizeof(struct iscsi_conn),
+ 	.max_conn		= 1,
+@@ -2197,6 +2198,9 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 	.get_session_param	= iscsi_session_get_param,
+ 	.start_conn		= iscsi_conn_start,
+ 	.stop_conn		= iscsi_tcp_conn_stop,
++	/* iscsi host params */
++	.get_host_param		= iscsi_host_get_param,
++	.set_host_param		= iscsi_host_set_param,
+ 	/* IO */
+ 	.send_pdu		= iscsi_conn_send_pdu,
+ 	.get_stats		= iscsi_conn_get_stats,
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 3f5b9b445b29..d430e227e9b7 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1462,6 +1462,7 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+ 	iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
+ 
+ 	kfree(session->targetname);
++	kfree(session->hwaddress);
+ 
+ 	iscsi_destroy_session(cls_session);
+ 	scsi_host_put(shost);
+@@ -1990,6 +1991,45 @@ int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ }
+ EXPORT_SYMBOL_GPL(iscsi_conn_get_param);
+ 
++int iscsi_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param,
++			 char *buf)
++{
++	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
++	int len;
++
++	switch (param) {
++	case ISCSI_HOST_PARAM_HWADDRESS:
++		if (!session->hwaddress)
++			len = sprintf(buf, "%s\n", "default");
++		else
++			len = sprintf(buf, "%s\n", session->hwaddress);
++		break;
++	default:
++		return -ENOSYS;
++	}
++
++	return len;
++}
++EXPORT_SYMBOL_GPL(iscsi_host_get_param);
++
++int iscsi_host_set_param(struct Scsi_Host *shost, enum iscsi_host_param param,
++			 char *buf, int buflen)
++{
++	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
++
++	switch (param) {
++	case ISCSI_HOST_PARAM_HWADDRESS:
++		if (!session->hwaddress)
++			session->hwaddress = kstrdup(buf, GFP_KERNEL);
++		break;
++	default:
++		return -ENOSYS;
++	}
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(iscsi_host_set_param);
++
+ MODULE_AUTHOR("Mike Christie");
+ MODULE_DESCRIPTION("iSCSI library functions");
+ MODULE_LICENSE("GPL");
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index ea0816d4904d..e202cc00c8e7 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -224,7 +224,8 @@ struct iscsi_session {
+ 	int			erl;
+ 	int			tpgt;
+ 	char			*targetname;
+-
++	/* hw address being used for iscsi connection */
++	char			*hwaddress;
+ 	/* control data */
+ 	struct iscsi_transport	*tt;
+ 	struct Scsi_Host	*host;
+@@ -255,6 +256,16 @@ extern int iscsi_eh_host_reset(struct scsi_cmnd *sc);
+ extern int iscsi_queuecommand(struct scsi_cmnd *sc,
+ 			      void (*done)(struct scsi_cmnd *));
+ 
++
++/*
++ * iSCSI host helpers.
++ */
++extern int iscsi_host_set_param(struct Scsi_Host *shost,
++				enum iscsi_host_param param, char *buf,
++				int buflen);
++extern int iscsi_host_get_param(struct Scsi_Host *shost,
++				enum iscsi_host_param param, char *buf);
++
+ /*
+  * session management
+  */

commit 1d9bf13a9cf91f8faf221e98a64dd1157bcf5fa9
+Author: Mike Christie 
+Date:   Wed May 30 12:57:11 2007 -0500
+
+    [SCSI] iscsi class: add iscsi host set param event
+    
+    The iscsi class uses the set_param event to set session
+    and connection params. This patch adds a set_host_param
+    so we can set host level values.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 59287601bd41..3fd2da451fe1 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -967,6 +967,30 @@ iscsi_tgt_dscvr(struct iscsi_transport *transport,
+ 	return err;
+ }
+ 
++static int
++iscsi_set_host_param(struct iscsi_transport *transport,
++		     struct iscsi_uevent *ev)
++{
++	char *data = (char*)ev + sizeof(*ev);
++	struct Scsi_Host *shost;
++	int err;
++
++	if (!transport->set_host_param)
++		return -ENOSYS;
++
++	shost = scsi_host_lookup(ev->u.set_host_param.host_no);
++	if (IS_ERR(shost)) {
++		printk(KERN_ERR "set_host_param could not find host no %u\n",
++		       ev->u.set_host_param.host_no);
++		return -ENODEV;
++	}
++
++	err = transport->set_host_param(shost, ev->u.set_host_param.param,
++					data, ev->u.set_host_param.len);
++	scsi_host_put(shost);
++	return err;
++}
++
+ static int
+ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ {
+@@ -1058,8 +1082,11 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 	case ISCSI_UEVENT_TGT_DSCVR:
+ 		err = iscsi_tgt_dscvr(transport, ev);
+ 		break;
++	case ISCSI_UEVENT_SET_HOST_PARAM:
++		err = iscsi_set_host_param(transport, ev);
++		break;
+ 	default:
+-		err = -EINVAL;
++		err = -ENOSYS;
+ 		break;
+ 	}
+ 
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index fba211743729..3d0372e30ca1 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -48,6 +48,7 @@ enum iscsi_uevent_e {
+ 	ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT	= UEVENT_BASE + 14,
+ 
+ 	ISCSI_UEVENT_TGT_DSCVR		= UEVENT_BASE + 15,
++	ISCSI_UEVENT_SET_HOST_PARAM	= UEVENT_BASE + 16,
+ 
+ 	/* up events */
+ 	ISCSI_KEVENT_RECV_PDU		= KEVENT_BASE + 1,
+@@ -136,6 +137,11 @@ struct iscsi_uevent {
+ 			 */
+ 			uint32_t	enable;
+ 		} tgt_dscvr;
++		struct msg_set_host_param {
++			uint32_t	host_no;
++			uint32_t	param; /* enum iscsi_host_param */
++			uint32_t	len;
++		} set_host_param;
+ 	} u;
+ 	union {
+ 		/* messages k -> u */
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 902e69f0272c..1ac450b06909 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -108,6 +108,9 @@ struct iscsi_transport {
+ 				  enum iscsi_param param, char *buf);
+ 	int (*get_host_param) (struct Scsi_Host *shost,
+ 				enum iscsi_host_param param, char *buf);
++	int (*set_host_param) (struct Scsi_Host *shost,
++			       enum iscsi_host_param param, char *buf,
++			       int buflen);
+ 	int (*send_pdu) (struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
+ 			 char *data, uint32_t data_size);
+ 	void (*get_stats) (struct iscsi_cls_conn *conn,

commit 2174a04ee7d8304a270de183fbc58b36dd05b395
+Author: Mike Christie 
+Date:   Wed May 30 12:57:10 2007 -0500
+
+    [SCSI] iscsi_transport, qla4xxx: have class lookup host for drivers
+    
+    We are going to be adding more host level sysfs attrs and
+    set_params, so this patch has them take a scsi_host instead
+    of either a scsi_host or host no.
+    
+    Signed-off-by: Mike Christie 
+    Cc: David C Somayajulu 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index 01308e7ef2ae..29cd4b90ebed 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -54,8 +54,9 @@ static void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha);
+ /*
+  * iSCSI template entry points
+  */
+-static int qla4xxx_tgt_dscvr(enum iscsi_tgt_dscvr type, uint32_t host_no,
+-			     uint32_t enable, struct sockaddr *dst_addr);
++static int qla4xxx_tgt_dscvr(struct Scsi_Host *shost,
++			     enum iscsi_tgt_dscvr type, uint32_t enable,
++			     struct sockaddr *dst_addr);
+ static int qla4xxx_conn_get_param(struct iscsi_cls_conn *conn,
+ 				  enum iscsi_param param, char *buf);
+ static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess,
+@@ -243,21 +244,15 @@ static int qla4xxx_conn_get_param(struct iscsi_cls_conn *conn,
+ 	return len;
+ }
+ 
+-static int qla4xxx_tgt_dscvr(enum iscsi_tgt_dscvr type, uint32_t host_no,
+-			     uint32_t enable, struct sockaddr *dst_addr)
++static int qla4xxx_tgt_dscvr(struct Scsi_Host *shost,
++			     enum iscsi_tgt_dscvr type, uint32_t enable,
++			     struct sockaddr *dst_addr)
+ {
+ 	struct scsi_qla_host *ha;
+-	struct Scsi_Host *shost;
+ 	struct sockaddr_in *addr;
+ 	struct sockaddr_in6 *addr6;
+ 	int ret = 0;
+ 
+-	shost = scsi_host_lookup(host_no);
+-	if (IS_ERR(shost)) {
+-		printk(KERN_ERR "Could not find host no %u\n", host_no);
+-		return -ENODEV;
+-	}
+-
+ 	ha = (struct scsi_qla_host *) shost->hostdata;
+ 
+ 	switch (type) {
+@@ -281,8 +276,6 @@ static int qla4xxx_tgt_dscvr(enum iscsi_tgt_dscvr type, uint32_t host_no,
+ 	default:
+ 		ret = -ENOSYS;
+ 	}
+-
+-	scsi_host_put(shost);
+ 	return ret;
+ }
+ 
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 1ba98d255fac..59287601bd41 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -945,15 +945,26 @@ static int
+ iscsi_tgt_dscvr(struct iscsi_transport *transport,
+ 		struct iscsi_uevent *ev)
+ {
++	struct Scsi_Host *shost;
+ 	struct sockaddr *dst_addr;
++	int err;
+ 
+ 	if (!transport->tgt_dscvr)
+ 		return -EINVAL;
+ 
++	shost = scsi_host_lookup(ev->u.tgt_dscvr.host_no);
++	if (IS_ERR(shost)) {
++		printk(KERN_ERR "target discovery could not find host no %u\n",
++		       ev->u.tgt_dscvr.host_no);
++		return -ENODEV;
++	}
++
++
+ 	dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
+-	return transport->tgt_dscvr(ev->u.tgt_dscvr.type,
+-				    ev->u.tgt_dscvr.host_no,
+-				    ev->u.tgt_dscvr.enable, dst_addr);
++	err = transport->tgt_dscvr(shost, ev->u.tgt_dscvr.type,
++				   ev->u.tgt_dscvr.enable, dst_addr);
++	scsi_host_put(shost);
++	return err;
+ }
+ 
+ static int
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index e962c5357eef..902e69f0272c 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -127,7 +127,7 @@ struct iscsi_transport {
+ 			   uint64_t *ep_handle);
+ 	int (*ep_poll) (uint64_t ep_handle, int timeout_ms);
+ 	void (*ep_disconnect) (uint64_t ep_handle);
+-	int (*tgt_dscvr) (enum iscsi_tgt_dscvr type, uint32_t host_no,
++	int (*tgt_dscvr) (struct Scsi_Host *shost, enum iscsi_tgt_dscvr type,
+ 			  uint32_t enable, struct sockaddr *dst_addr);
+ };
+ 

commit aa1e93a2fe0392588220d491454e7752d0fdb251
+Author: Mike Christie 
+Date:   Wed May 30 12:57:09 2007 -0500
+
+    [SCSI] qla4xxx: export mac as hw address
+    
+    Export mac as hw address.
+    
+    Signed-off-by: Mike Christie 
+    Cc: David C Somayajulu 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index e09fc4241970..01308e7ef2ae 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -60,6 +60,8 @@ static int qla4xxx_conn_get_param(struct iscsi_cls_conn *conn,
+ 				  enum iscsi_param param, char *buf);
+ static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess,
+ 				  enum iscsi_param param, char *buf);
++static int qla4xxx_host_get_param(struct Scsi_Host *shost,
++				  enum iscsi_host_param param, char *buf);
+ static void qla4xxx_conn_stop(struct iscsi_cls_conn *conn, int flag);
+ static int qla4xxx_conn_start(struct iscsi_cls_conn *conn);
+ static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session);
+@@ -99,16 +101,16 @@ static struct scsi_host_template qla4xxx_driver_template = {
+ static struct iscsi_transport qla4xxx_iscsi_transport = {
+ 	.owner			= THIS_MODULE,
+ 	.name			= DRIVER_NAME,
+-	.param_mask		= ISCSI_CONN_PORT |
+-				  ISCSI_CONN_ADDRESS |
+-				  ISCSI_TARGET_NAME |
+-				  ISCSI_TPGT,
++	.param_mask		= ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS |
++				  ISCSI_TARGET_NAME | ISCSI_TPGT,
++	.host_param_mask	= ISCSI_HOST_HWADDRESS,
+ 	.sessiondata_size	= sizeof(struct ddb_entry),
+ 	.host_template		= &qla4xxx_driver_template,
+ 
+ 	.tgt_dscvr		= qla4xxx_tgt_dscvr,
+ 	.get_conn_param		= qla4xxx_conn_get_param,
+ 	.get_session_param	= qla4xxx_sess_get_param,
++	.get_host_param		= qla4xxx_host_get_param,
+ 	.start_conn		= qla4xxx_conn_start,
+ 	.stop_conn		= qla4xxx_conn_stop,
+ 	.session_recovery_timedout = qla4xxx_recovery_timedout,
+@@ -165,6 +167,35 @@ static void qla4xxx_conn_stop(struct iscsi_cls_conn *conn, int flag)
+ 		printk(KERN_ERR "iscsi: invalid stop flag %d\n", flag);
+ }
+ 
++static ssize_t format_addr(char *buf, const unsigned char *addr, int len)
++{
++	int i;
++	char *cp = buf;
++
++	for (i = 0; i < len; i++)
++		cp += sprintf(cp, "%02x%c", addr[i],
++			      i == (len - 1) ? '\n' : ':');
++	return cp - buf;
++}
++
++
++static int qla4xxx_host_get_param(struct Scsi_Host *shost,
++				  enum iscsi_host_param param, char *buf)
++{
++	struct scsi_qla_host *ha = to_qla_host(shost);
++	int len;
++
++	switch (param) {
++	case ISCSI_HOST_PARAM_HWADDRESS:
++		len = format_addr(buf, ha->my_mac, MAC_ADDR_LEN);
++		break;
++	default:
++		return -ENOSYS;
++	}
++
++	return len;
++}
++
+ static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess,
+ 				  enum iscsi_param param, char *buf)
+ {

commit 1819dc8143eff2a5850af274bcf8bcbc3e73ec76
+Author: Mike Christie 
+Date:   Wed May 30 12:57:08 2007 -0500
+
+    [SCSI] iscsi_transport: export hw address
+    
+    Add hw address sysfs file.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 4fbd8e1a0695..1ba98d255fac 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -32,7 +32,7 @@
+ 
+ #define ISCSI_SESSION_ATTRS 11
+ #define ISCSI_CONN_ATTRS 11
+-#define ISCSI_HOST_ATTRS 0
++#define ISCSI_HOST_ATTRS 1
+ #define ISCSI_TRANSPORT_VERSION "2.0-724"
+ 
+ struct iscsi_internal {
+@@ -1197,6 +1197,25 @@ static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO, show_priv_session_##field, \
+ 			NULL)
+ iscsi_priv_session_attr(recovery_tmo, "%d");
+ 
++/*
++ * iSCSI host attrs
++ */
++#define iscsi_host_attr_show(param)					\
++static ssize_t								\
++show_host_param_##param(struct class_device *cdev, char *buf)		\
++{									\
++	struct Scsi_Host *shost = transport_class_to_shost(cdev);	\
++	struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \
++	return priv->iscsi_transport->get_host_param(shost, param, buf); \
++}
++
++#define iscsi_host_attr(field, param)					\
++	iscsi_host_attr_show(param)					\
++static ISCSI_CLASS_ATTR(host, field, S_IRUGO, show_host_param_##param,	\
++			NULL);
++
++iscsi_host_attr(hwaddress, ISCSI_HOST_PARAM_HWADDRESS);
++
+ #define SETUP_PRIV_SESSION_RD_ATTR(field)				\
+ do {									\
+ 	priv->session_attrs[count] = &class_device_attr_priv_sess_##field; \
+@@ -1220,6 +1239,14 @@ do {									\
+ 	}								\
+ } while (0)
+ 
++#define SETUP_HOST_RD_ATTR(field, param_flag)				\
++do {									\
++	if (tt->host_param_mask & param_flag) {				\
++		priv->host_attrs[count] = &class_device_attr_host_##field; \
++		count++;						\
++	}								\
++} while (0)
++
+ static int iscsi_session_match(struct attribute_container *cont,
+ 			   struct device *dev)
+ {
+@@ -1321,9 +1348,13 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 	priv->t.host_attrs.ac.class = &iscsi_host_class.class;
+ 	priv->t.host_attrs.ac.match = iscsi_host_match;
+ 	priv->t.host_size = sizeof(struct iscsi_host);
+-	priv->host_attrs[0] = NULL;
+ 	transport_container_register(&priv->t.host_attrs);
+ 
++	SETUP_HOST_RD_ATTR(hwaddress, ISCSI_HOST_HWADDRESS);
++	BUG_ON(count > ISCSI_HOST_ATTRS);
++	priv->host_attrs[count] = NULL;
++	count = 0;
++
+ 	/* connection parameters */
+ 	priv->conn_cont.ac.attrs = &priv->conn_attrs[0];
+ 	priv->conn_cont.ac.class = &iscsi_connection_class.class;
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index 55ebf035e620..fba211743729 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -250,6 +250,14 @@ enum iscsi_param {
+ #define ISCSI_CONN_PORT			(1 << ISCSI_PARAM_CONN_PORT)
+ #define ISCSI_CONN_ADDRESS		(1 << ISCSI_PARAM_CONN_ADDRESS)
+ 
++/* iSCSI HBA params */
++enum iscsi_host_param {
++	ISCSI_HOST_PARAM_HWADDRESS,
++	ISCSI_HOST_PARAM_MAX,
++};
++
++#define ISCSI_HOST_HWADDRESS		(1 << ISCSI_HOST_PARAM_HWADDRESS)
++
+ #define iscsi_ptr(_handle) ((void*)(unsigned long)_handle)
+ #define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr)
+ #define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata))
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index d5c218ddc527..e962c5357eef 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -79,7 +79,8 @@ struct iscsi_transport {
+ 	char *name;
+ 	unsigned int caps;
+ 	/* LLD sets this to indicate what values it can export to sysfs */
+-	unsigned int param_mask;
++	uint64_t param_mask;
++	uint64_t host_param_mask;
+ 	struct scsi_host_template *host_template;
+ 	/* LLD connection data size */
+ 	int conndata_size;
+@@ -105,6 +106,8 @@ struct iscsi_transport {
+ 			       enum iscsi_param param, char *buf);
+ 	int (*get_session_param) (struct iscsi_cls_session *session,
+ 				  enum iscsi_param param, char *buf);
++	int (*get_host_param) (struct Scsi_Host *shost,
++				enum iscsi_host_param param, char *buf);
+ 	int (*send_pdu) (struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
+ 			 char *data, uint32_t data_size);
+ 	void (*get_stats) (struct iscsi_cls_conn *conn,

commit 239a7dc2fea4d079bc3090b5514497a5ced400d3
+Author: Mike Christie 
+Date:   Wed May 30 12:57:07 2007 -0500
+
+    [SCSI] iscsi_transport: Check iscsi interface skb allocation return value
+    
+    Let's not oops when we cannot allocate a skb! Add a check
+    for if alloc_skb fails.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index caf1836bbeca..4fbd8e1a0695 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -609,12 +609,10 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi,
+ 	int t = done ? NLMSG_DONE : type;
+ 
+ 	skb = alloc_skb(len, GFP_ATOMIC);
+-	/*
+-	 * FIXME:
+-	 * user is supposed to react on iferror == -ENOMEM;
+-	 * see iscsi_if_rx().
+-	 */
+-	BUG_ON(!skb);
++	if (!skb) {
++		printk(KERN_ERR "Could not allocate skb to send reply.\n");
++		return -ENOMEM;
++	}
+ 
+ 	nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0);
+ 	nlh->nlmsg_flags = flags;

commit 821de3a27bf33f11ec878562577c586cd5f83c64
+Author: Mike Christie 
+Date:   Tue May 8 19:12:23 2007 +0200
+
+    [PATCH] ll_rw_blk: fix missing bounce in blk_rq_map_kern()
+    
+    I think we might just need the blk_map_kern users now. For the async
+    execute I added the bounce code already and the block SG_IO has it
+    atleady. I think the blk_map_kern bounce code got dropped because we
+    thought the correct gfp_t would be passed in. But I think all we need is
+    the patch below and all the paths are take care of. The patch is not
+    tested. Patch was made against scsi-misc.
+    
+    The last place that is sending non sg commands may just be md/dm-emc.c
+    but that is is just waiting on alasdair to take some patches that fix
+    that and a bunch of junk in there including adding bounce support. If
+    the patch below is ok though and dm-emc finally gets converted then it
+    will have sg and bonce buffer support.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
+index 5873861e1dbb..d99d402953a3 100644
+--- a/block/ll_rw_blk.c
++++ b/block/ll_rw_blk.c
+@@ -2558,6 +2558,7 @@ int blk_rq_map_kern(request_queue_t *q, struct request *rq, void *kbuf,
+ 		bio->bi_rw |= (1 << BIO_RW);
+ 
+ 	blk_rq_bio_prep(q, rq, bio);
++	blk_queue_bounce(q, &rq->bio);
+ 	rq->buffer = rq->data = NULL;
+ 	return 0;
+ }

commit 181011e04a2a32f8d5df212254239ac9a3c8ab5e
+Author: Mike Christie 
+Date:   Sat Mar 3 09:55:54 2007 +0900
+
+    [SCSI] tgt: rm bio hacks in scsi tgt
+    
+    scsi tgt breaks up a command into multple scatterlists
+    if we cannot fit all the data in one. This was because
+    the block rq helpers did not support large requests and
+    because we can get a command of any old size so it is
+    hard to preallocate pages for scatterlist large enough
+    (we cannot really preallocate pages with the bio map
+    user path). In 2.6.20, we added large request support to
+    the block layer helper, blk_rq_map_user. And at LSF,
+    we talked about increasing SCSI_MAX_PHYS_SEGMENTS for
+    scsi tgt if we want to support really really :) large
+    (greater than 256 * PAGE_SIZE in the worst mapping case)
+    requests.
+    
+    The only target currently implemented does not even support
+    the multiple scatterlists stuff and only supports smaller
+    requests, so this patch just coverts scsi tgt to use
+    blk_rq_map_user.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: FUJITA Tomonori 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c
+index d402aff5f314..47c29a98c922 100644
+--- a/drivers/scsi/scsi_tgt_lib.c
++++ b/drivers/scsi/scsi_tgt_lib.c
+@@ -28,7 +28,6 @@
+ #include 
+ #include 
+ #include 
+-#include <../drivers/md/dm-bio-list.h>
+ 
+ #include "scsi_tgt_priv.h"
+ 
+@@ -42,9 +41,8 @@ static struct kmem_cache *scsi_tgt_cmd_cache;
+ struct scsi_tgt_cmd {
+ 	/* TODO replace work with James b's code */
+ 	struct work_struct work;
+-	/* TODO replace the lists with a large bio */
+-	struct bio_list xfer_done_list;
+-	struct bio_list xfer_list;
++	/* TODO fix limits of some drivers */
++	struct bio *bio;
+ 
+ 	struct list_head hash_list;
+ 	struct request *rq;
+@@ -93,7 +91,12 @@ struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost,
+ 	if (!tcmd)
+ 		goto put_dev;
+ 
+-	rq = blk_get_request(shost->uspace_req_q, write, gfp_mask);
++	/*
++	 * The blk helpers are used to the READ/WRITE requests
++	 * transfering data from a initiator point of view. Since
++	 * we are in target mode we want the opposite.
++	 */
++	rq = blk_get_request(shost->uspace_req_q, !write, gfp_mask);
+ 	if (!rq)
+ 		goto free_tcmd;
+ 
+@@ -111,8 +114,6 @@ struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost,
+ 	rq->cmd_flags |= REQ_TYPE_BLOCK_PC;
+ 	rq->end_io_data = tcmd;
+ 
+-	bio_list_init(&tcmd->xfer_list);
+-	bio_list_init(&tcmd->xfer_done_list);
+ 	tcmd->rq = rq;
+ 
+ 	return cmd;
+@@ -157,22 +158,6 @@ void scsi_host_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
+ }
+ EXPORT_SYMBOL_GPL(scsi_host_put_command);
+ 
+-static void scsi_unmap_user_pages(struct scsi_tgt_cmd *tcmd)
+-{
+-	struct bio *bio;
+-
+-	/* must call bio_endio in case bio was bounced */
+-	while ((bio = bio_list_pop(&tcmd->xfer_done_list))) {
+-		bio_endio(bio, bio->bi_size, 0);
+-		bio_unmap_user(bio);
+-	}
+-
+-	while ((bio = bio_list_pop(&tcmd->xfer_list))) {
+-		bio_endio(bio, bio->bi_size, 0);
+-		bio_unmap_user(bio);
+-	}
+-}
+-
+ static void cmd_hashlist_del(struct scsi_cmnd *cmd)
+ {
+ 	struct request_queue *q = cmd->request->q;
+@@ -185,6 +170,11 @@ static void cmd_hashlist_del(struct scsi_cmnd *cmd)
+ 	spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags);
+ }
+ 
++static void scsi_unmap_user_pages(struct scsi_tgt_cmd *tcmd)
++{
++	blk_rq_unmap_user(tcmd->bio);
++}
++
+ static void scsi_tgt_cmd_destroy(struct work_struct *work)
+ {
+ 	struct scsi_tgt_cmd *tcmd =
+@@ -193,16 +183,6 @@ static void scsi_tgt_cmd_destroy(struct work_struct *work)
+ 
+ 	dprintk("cmd %p %d %lu\n", cmd, cmd->sc_data_direction,
+ 		rq_data_dir(cmd->request));
+-	/*
+-	 * We fix rq->cmd_flags here since when we told bio_map_user
+-	 * to write vm for WRITE commands, blk_rq_bio_prep set
+-	 * rq_data_dir the flags to READ.
+-	 */
+-	if (cmd->sc_data_direction == DMA_TO_DEVICE)
+-		cmd->request->cmd_flags |= REQ_RW;
+-	else
+-		cmd->request->cmd_flags &= ~REQ_RW;
+-
+ 	scsi_unmap_user_pages(tcmd);
+ 	scsi_host_put_command(scsi_tgt_cmd_to_host(cmd), cmd);
+ }
+@@ -215,6 +195,7 @@ static void init_scsi_tgt_cmd(struct request *rq, struct scsi_tgt_cmd *tcmd,
+ 	struct list_head *head;
+ 
+ 	tcmd->tag = tag;
++	tcmd->bio = NULL;
+ 	INIT_WORK(&tcmd->work, scsi_tgt_cmd_destroy);
+ 	spin_lock_irqsave(&qdata->cmd_hash_lock, flags);
+ 	head = &qdata->cmd_hash[cmd_hashfn(tag)];
+@@ -419,52 +400,33 @@ static int scsi_map_user_pages(struct scsi_tgt_cmd *tcmd, struct scsi_cmnd *cmd,
+ 	struct request *rq = cmd->request;
+ 	void *uaddr = tcmd->buffer;
+ 	unsigned int len = tcmd->bufflen;
+-	struct bio *bio;
+ 	int err;
+ 
+-	while (len > 0) {
+-		dprintk("%lx %u\n", (unsigned long) uaddr, len);
+-		bio = bio_map_user(q, NULL, (unsigned long) uaddr, len, rw);
+-		if (IS_ERR(bio)) {
+-			err = PTR_ERR(bio);
+-			dprintk("fail to map %lx %u %d %x\n",
+-				(unsigned long) uaddr, len, err, cmd->cmnd[0]);
+-			goto unmap_bios;
+-		}
+-
+-		uaddr += bio->bi_size;
+-		len -= bio->bi_size;
+-
++	dprintk("%lx %u\n", (unsigned long) uaddr, len);
++	err = blk_rq_map_user(q, rq, uaddr, len);
++	if (err) {
+ 		/*
+-		 * The first bio is added and merged. We could probably
+-		 * try to add others using scsi_merge_bio() but for now
+-		 * we keep it simple. The first bio should be pretty large
+-		 * (either hitting the 1 MB bio pages limit or a queue limit)
+-		 * already but for really large IO we may want to try and
+-		 * merge these.
++		 * TODO: need to fixup sg_tablesize, max_segment_size,
++		 * max_sectors, etc for modern HW and software drivers
++		 * where this value is bogus.
++		 *
++		 * TODO2: we can alloc a reserve buffer of max size
++		 * we can handle and do the slow copy path for really large
++		 * IO.
+ 		 */
+-		if (!rq->bio) {
+-			blk_rq_bio_prep(q, rq, bio);
+-			rq->data_len = bio->bi_size;
+-		} else
+-			/* put list of bios to transfer in next go around */
+-			bio_list_add(&tcmd->xfer_list, bio);
++		eprintk("Could not handle request of size %u.\n", len);
++		return err;
+ 	}
+ 
+-	cmd->offset = 0;
++	tcmd->bio = rq->bio;
+ 	err = scsi_tgt_init_cmd(cmd, GFP_KERNEL);
+ 	if (err)
+-		goto unmap_bios;
++		goto unmap_rq;
+ 
+ 	return 0;
+ 
+-unmap_bios:
+-	if (rq->bio) {
+-		bio_unmap_user(rq->bio);
+-		while ((bio = bio_list_pop(&tcmd->xfer_list)))
+-			bio_unmap_user(bio);
+-	}
+-
++unmap_rq:
++	scsi_unmap_user_pages(tcmd);
+ 	return err;
+ }
+ 
+@@ -473,12 +435,10 @@ static int scsi_tgt_transfer_data(struct scsi_cmnd *);
+ static void scsi_tgt_data_transfer_done(struct scsi_cmnd *cmd)
+ {
+ 	struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data;
+-	struct bio *bio;
+ 	int err;
+ 
+ 	/* should we free resources here on error ? */
+ 	if (cmd->result) {
+-send_uspace_err:
+ 		err = scsi_tgt_uspace_send_status(cmd, tcmd->tag);
+ 		if (err <= 0)
+ 			/* the tgt uspace eh will have to pick this up */
+@@ -490,34 +450,8 @@ static void scsi_tgt_data_transfer_done(struct scsi_cmnd *cmd)
+ 		cmd, cmd->request_bufflen, tcmd->bufflen);
+ 
+ 	scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len);
+-	bio_list_add(&tcmd->xfer_done_list, cmd->request->bio);
+-
+ 	tcmd->buffer += cmd->request_bufflen;
+-	cmd->offset += cmd->request_bufflen;
+-
+-	if (!tcmd->xfer_list.head) {
+-		scsi_tgt_transfer_response(cmd);
+-		return;
+-	}
+-
+-	dprintk("cmd2 %p request_bufflen %u bufflen %u\n",
+-		cmd, cmd->request_bufflen, tcmd->bufflen);
+-
+-	bio = bio_list_pop(&tcmd->xfer_list);
+-	BUG_ON(!bio);
+-
+-	blk_rq_bio_prep(cmd->request->q, cmd->request, bio);
+-	cmd->request->data_len = bio->bi_size;
+-	err = scsi_tgt_init_cmd(cmd, GFP_ATOMIC);
+-	if (err) {
+-		cmd->result = DID_ERROR << 16;
+-		goto send_uspace_err;
+-	}
+-
+-	if (scsi_tgt_transfer_data(cmd)) {
+-		cmd->result = DID_NO_CONNECT << 16;
+-		goto send_uspace_err;
+-	}
++	scsi_tgt_transfer_response(cmd);
+ }
+ 
+ static int scsi_tgt_transfer_data(struct scsi_cmnd *cmd)
+@@ -617,8 +551,9 @@ int scsi_tgt_kspace_exec(int host_no, u64 tag, int result, u32 len,
+ 	}
+ 	cmd = rq->special;
+ 
+-	dprintk("cmd %p result %d len %d bufflen %u %lu %x\n", cmd,
+-		result, len, cmd->request_bufflen, rq_data_dir(rq), cmd->cmnd[0]);
++	dprintk("cmd %p scb %x result %d len %d bufflen %u %lu %x\n",
++		cmd, cmd->cmnd[0], result, len, cmd->request_bufflen,
++		rq_data_dir(rq), cmd->cmnd[0]);
+ 
+ 	if (result == TASK_ABORTED) {
+ 		scsi_tgt_abort_cmd(shost, cmd);
+diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
+index d6948d0e8cdb..a2e0c1032491 100644
+--- a/include/scsi/scsi_cmnd.h
++++ b/include/scsi/scsi_cmnd.h
+@@ -73,9 +73,6 @@ struct scsi_cmnd {
+ 	unsigned short use_sg;	/* Number of pieces of scatter-gather */
+ 	unsigned short sglist_len;	/* size of malloc'd scatter-gather list */
+ 
+-	/* offset in cmd we are at (for multi-transfer tgt cmds) */
+-	unsigned offset;
+-
+ 	unsigned underflow;	/* Return error if less than
+ 				   this amount is transferred */
+ 

commit 0f238418b6d41cdfc85f2f399848429ff6fbfbd0
+Author: Mike Christie 
+Date:   Wed Feb 28 17:32:21 2007 -0600
+
+    [SCSI] iscsi_tcp: print useful error message when iscsi crc23c allocation fails
+    
+    People do not read the README and seem to like to
+    unselect the crc32c module even though iscsi_tcp selects
+    it for them. This patch spits a error that tells the user
+    that they really do need the module. Hopefully, we will
+    get fewer people asking about this now.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 861cb9be40b0..c9a3abf9e7b6 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -1777,14 +1777,24 @@ iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ 	tcp_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0,
+ 						  CRYPTO_ALG_ASYNC);
+ 	tcp_conn->tx_hash.flags = 0;
+-	if (IS_ERR(tcp_conn->tx_hash.tfm))
++	if (IS_ERR(tcp_conn->tx_hash.tfm)) {
++		printk(KERN_ERR "Could not create connection due to crc32c "
++		       "loading error %ld. Make sure the crc32c module is "
++		       "built as a module or into the kernel\n",
++			PTR_ERR(tcp_conn->tx_hash.tfm));
+ 		goto free_tcp_conn;
++	}
+ 
+ 	tcp_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0,
+ 						  CRYPTO_ALG_ASYNC);
+ 	tcp_conn->rx_hash.flags = 0;
+-	if (IS_ERR(tcp_conn->rx_hash.tfm))
++	if (IS_ERR(tcp_conn->rx_hash.tfm)) {
++		printk(KERN_ERR "Could not create connection due to crc32c "
++		       "loading error %ld. Make sure the crc32c module is "
++		       "built as a module or into the kernel\n",
++			PTR_ERR(tcp_conn->rx_hash.tfm));
+ 		goto free_tx_tfm;
++	}
+ 
+ 	return cls_conn;
+ 

commit 8231f0eddbe425cc3b54f2d723bb03531925272e
+Author: Mike Christie 
+Date:   Wed Feb 28 17:32:20 2007 -0600
+
+    [SCSI] iscsi_tcp: increase max_sectors
+    
+    For a while now, the block layer has seperated max sectors
+    and max hw sectors. Software iscsi has no limit so this patch
+    increases max hw sectors, so we can support large pass through
+    commands.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 6fd084583491..861cb9be40b0 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -2138,6 +2138,7 @@ static struct scsi_host_template iscsi_sht = {
+ 	.change_queue_depth	= iscsi_change_queue_depth,
+ 	.can_queue		= ISCSI_XMIT_CMDS_MAX - 1,
+ 	.sg_tablesize		= ISCSI_SG_TABLESIZE,
++	.max_sectors		= 0xFFFF,
+ 	.cmd_per_lun		= ISCSI_DEF_CMD_PER_LUN,
+ 	.eh_abort_handler       = iscsi_eh_abort,
+ 	.eh_host_reset_handler	= iscsi_eh_host_reset,

commit 8eb00539d92187ade7e4cc24a1a36ab248ee8639
+Author: Mike Christie 
+Date:   Wed Feb 28 17:32:19 2007 -0600
+
+    [SCSI] libiscsi: use get_unaligned
+    
+    Dave Miller meantioned that the data buffer in a past
+    sense fixup patch was not gauranteed to be aligned
+    properly for ia64. This patch has libiscsi use get_unalinged
+    to make sure. There are a couple more places in the
+    digest handling we may need to do this, but we are in the middle
+    of fixing that code for big endien systems so just the sense
+    access is fixed here.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 04707d667c9d..3f5b9b445b29 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -25,6 +25,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -269,14 +270,14 @@ static int iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			goto out;
+ 		}
+ 
+-		senselen = be16_to_cpu(*(__be16 *)data);
++		senselen = be16_to_cpu(get_unaligned((__be16 *) data));
+ 		if (datalen < senselen)
+ 			goto invalid_datalen;
+ 
+ 		memcpy(sc->sense_buffer, data + 2,
+ 		       min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
+ 		debug_scsi("copied %d bytes of sense\n",
+-			   min(senselen, SCSI_SENSE_BUFFERSIZE));
++			   min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
+ 	}
+ 
+ 	if (sc->sc_data_direction == DMA_TO_DEVICE)

commit 41be14442213b6dbeea3cba2ed18a2923666278c
+Author: Mike Christie 
+Date:   Wed Feb 28 17:32:18 2007 -0600
+
+    [SCSI] iscsi transport: use atomic for session_nr allocations
+    
+    qla4xxx and iscsi_tcp or iser could be creating
+    sessions at the same time, so make session_nr id
+    allocation atomic.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index ce0d14af33c8..ff05c84479ca 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -49,7 +49,7 @@ struct iscsi_internal {
+ 	struct class_device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1];
+ };
+ 
+-static int iscsi_session_nr;	/* sysfs session id for next new session */
++static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
+ 
+ /*
+  * list of registered transports and lock that must
+@@ -300,7 +300,7 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
+ 	int err;
+ 
+ 	ihost = shost->shost_data;
+-	session->sid = iscsi_session_nr++;
++	session->sid = atomic_add_return(1, &iscsi_session_nr);
+ 	session->target_id = target_id;
+ 
+ 	snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u",
+@@ -1419,6 +1419,8 @@ static __init int iscsi_transport_init(void)
+ 	printk(KERN_INFO "Loading iSCSI transport class v%s.\n",
+ 		ISCSI_TRANSPORT_VERSION);
+ 
++	atomic_set(&iscsi_session_nr, 0);
++
+ 	err = class_register(&iscsi_transport_class);
+ 	if (err)
+ 		return err;

commit bf32ed33e97ac7905fa5a2bf49a634c2eaf62457
+Author: Mike Christie 
+Date:   Wed Feb 28 17:32:17 2007 -0600
+
+    [SCSI] iscsi: rename DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH
+    
+    This patch renames DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH to avoid
+    confusion with the drivers default values (DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH
+    is the iscsi RFC specific default).
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
+index 89e37283c836..3261bb327281 100644
+--- a/drivers/infiniband/ulp/iser/iser_initiator.c
++++ b/drivers/infiniband/ulp/iser/iser_initiator.c
+@@ -201,7 +201,7 @@ static int iser_post_receive_control(struct iscsi_conn *conn)
+ 	 * what's common for both schemes is that the connection is not started
+ 	 */
+ 	if (conn->c_stage != ISCSI_CONN_STARTED)
+-		rx_data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
++		rx_data_size = ISCSI_DEF_MAX_RECV_SEG_LEN;
+ 	else /* FIXME till user space sets conn->max_recv_dlength correctly */
+ 		rx_data_size = 128;
+ 
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 8f55e1431433..6fd084583491 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -527,12 +527,12 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *conn)
+ 		 * than 8K, but there are no targets that currently do this.
+ 		 * For now we fail until we find a vendor that needs it
+ 		 */
+-		if (DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH <
++		if (ISCSI_DEF_MAX_RECV_SEG_LEN <
+ 		    tcp_conn->in.datalen) {
+ 			printk(KERN_ERR "iscsi_tcp: received buffer of len %u "
+ 			      "but conn buffer is only %u (opcode %0x)\n",
+ 			      tcp_conn->in.datalen,
+-			      DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, opcode);
++			      ISCSI_DEF_MAX_RECV_SEG_LEN, opcode);
+ 			rc = ISCSI_ERR_PROTO;
+ 			break;
+ 		}
+@@ -1762,7 +1762,7 @@ iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ 	 * due to strange issues with iser these are not set
+ 	 * in iscsi_conn_setup
+ 	 */
+-	conn->max_recv_dlength = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
++	conn->max_recv_dlength = ISCSI_DEF_MAX_RECV_SEG_LEN;
+ 
+ 	tcp_conn = kzalloc(sizeof(*tcp_conn), GFP_KERNEL);
+ 	if (!tcp_conn)
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 0ad484f87b1d..04707d667c9d 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1520,7 +1520,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ 	}
+ 	spin_unlock_bh(&session->lock);
+ 
+-	data = kmalloc(DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, GFP_KERNEL);
++	data = kmalloc(ISCSI_DEF_MAX_RECV_SEG_LEN, GFP_KERNEL);
+ 	if (!data)
+ 		goto login_mtask_data_alloc_fail;
+ 	conn->login_mtask->data = conn->data = data;
+diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h
+index 4a44278ed768..8d1e4e8026fe 100644
+--- a/include/scsi/iscsi_proto.h
++++ b/include/scsi/iscsi_proto.h
+@@ -588,7 +588,17 @@ struct iscsi_reject {
+ #define VALUE_MAXLEN		255
+ #define TARGET_NAME_MAXLEN	VALUE_MAXLEN
+ 
+-#define DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH	8192
++#define ISCSI_DEF_MAX_RECV_SEG_LEN		8192
++#define ISCSI_MIN_MAX_RECV_SEG_LEN		512
++#define ISCSI_MAX_MAX_RECV_SEG_LEN		16777215
++
++#define ISCSI_DEF_FIRST_BURST_LEN		65536
++#define ISCSI_MIN_FIRST_BURST_LEN		512
++#define ISCSI_MAX_FIRST_BURST_LEN		16777215
++
++#define ISCSI_DEF_MAX_BURST_LEN			262144
++#define ISCSI_MIN_MAX_BURST_LEN			512
++#define ISCSI_MAX_MAX_BURST_LEN			16777215
+ 
+ /************************* RFC 3720 End *****************************/
+ 

commit 05db888a46866fd4eae643792c162e1a5c1a8612
+Author: Mike Christie 
+Date:   Wed Feb 28 17:32:16 2007 -0600
+
+    [SCSI] libiscsi: clear mtask
+    
+    Consolidate the mtask clearing code.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 6346a913c36e..0ad484f87b1d 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -577,7 +577,7 @@ void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_conn_failure);
+ 
+-static int iscsi_xmit_imm_task(struct iscsi_conn *conn)
++static int iscsi_xmit_mtask(struct iscsi_conn *conn)
+ {
+ 	struct iscsi_hdr *hdr = conn->mtask->hdr;
+ 	int rc, was_logout = 0;
+@@ -591,6 +591,9 @@ static int iscsi_xmit_imm_task(struct iscsi_conn *conn)
+ 	if (rc)
+ 		return rc;
+ 
++	/* done with this in-progress mtask */
++	conn->mtask = NULL;
++
+ 	if (was_logout) {
+ 		set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+ 		return -ENODATA;
+@@ -643,11 +646,9 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 		conn->ctask = NULL;
+ 	}
+ 	if (conn->mtask) {
+-		rc = iscsi_xmit_imm_task(conn);
++		rc = iscsi_xmit_mtask(conn);
+ 	        if (rc)
+ 		        goto again;
+-		/* done with this in-progress mtask */
+-		conn->mtask = NULL;
+ 	}
+ 
+ 	/* process immediate first */
+@@ -658,12 +659,10 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 			list_add_tail(&conn->mtask->running,
+ 				      &conn->mgmt_run_list);
+ 			spin_unlock_bh(&conn->session->lock);
+-			rc = iscsi_xmit_imm_task(conn);
++			rc = iscsi_xmit_mtask(conn);
+ 		        if (rc)
+ 			        goto again;
+ 	        }
+-		/* done with this mtask */
+-		conn->mtask = NULL;
+ 	}
+ 
+ 	/* process command queue */
+@@ -701,12 +700,10 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 			list_add_tail(&conn->mtask->running,
+ 				      &conn->mgmt_run_list);
+ 			spin_unlock_bh(&conn->session->lock);
+-		        rc = tt->xmit_mgmt_task(conn, conn->mtask);
+-			if (rc)
++			rc = iscsi_xmit_mtask(conn);
++		        if (rc)
+ 			        goto again;
+ 	        }
+-		/* done with this mtask */
+-		conn->mtask = NULL;
+ 	}
+ 
+ 	return -ENODATA;

commit 779ea1207b6a43943faa44f41be7311263315604
+Author: Mike Christie 
+Date:   Wed Feb 28 17:32:15 2007 -0600
+
+    [SCSI] libiscsi: flush work before freeing connection
+    
+    It's possible that we call iscsi_xmitworker after iscsi_conn_release
+    which causes a oops. This patch flushes the workqueue.
+    
+    Signed-off-by: FUJITA Tomonori 
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 7c75771c77ff..6346a913c36e 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1597,6 +1597,9 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
+ 		wake_up(&conn->ehwait);
+ 	}
+ 
++	/* flush queued up work because we free the connection below */
++	scsi_flush_work(session->host);
++
+ 	spin_lock_bh(&session->lock);
+ 	kfree(conn->data);
+ 	kfree(conn->persistent_address);

commit c0d4d573feed199b16094c072e7cb07afb01c598
+Author: Mike Christie 
+Date:   Mon Jan 29 21:18:38 2007 -0500
+
+    [PATCH] Fix SG_IO timeout jiffy conversion
+    
+    Commit 85e04e371b5a321b5df2bc3f8e0099a64fb087d7 cleaned up the timeout
+    conversion, but did it exactly the wrong way.  We get msecs from user
+    space, and should convert them into jiffies. Not the other way around.
+    
+    Here is a fix with the overflow check sg.c has added in.  This fixes DVD
+    burnign with Nero.
+    
+    Signed-off-by: Mike Christie 
+    [ "you'll be wanting a comma there" - Andrew ]
+    Cc: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
+index 2528a0c0dec8..65c6a3cba6d6 100644
+--- a/block/scsi_ioctl.c
++++ b/block/scsi_ioctl.c
+@@ -223,7 +223,7 @@ static int verify_command(struct file *file, unsigned char *cmd)
+ static int sg_io(struct file *file, request_queue_t *q,
+ 		struct gendisk *bd_disk, struct sg_io_hdr *hdr)
+ {
+-	unsigned long start_time;
++	unsigned long start_time, timeout;
+ 	int writing = 0, ret = 0;
+ 	struct request *rq;
+ 	char sense[SCSI_SENSE_BUFFERSIZE];
+@@ -271,7 +271,8 @@ static int sg_io(struct file *file, request_queue_t *q,
+ 
+ 	rq->cmd_type = REQ_TYPE_BLOCK_PC;
+ 
+-	rq->timeout = jiffies_to_msecs(hdr->timeout);
++	timeout = msecs_to_jiffies(hdr->timeout);
++	rq->timeout = (timeout < INT_MAX) ? timeout : INT_MAX;
+ 	if (!rq->timeout)
+ 		rq->timeout = q->sg_timeout;
+ 	if (!rq->timeout)

commit 9b80cb4be1f4181875e0cf274dc59f42964fdf1b
+Author: Mike Christie 
+Date:   Sun Dec 17 12:10:28 2006 -0600
+
+    [SCSI] libiscsi: fix senselen calculation
+    
+    Yanling Qi, noted that when the sense data length of
+    a check-condition is greater than 0x7f (127), senselen = (data[0] << 8)
+    | data[1] will become negative. It causes different kinds of panics from
+    GPF, spin_lock deadlock to spin_lock recursion.
+    
+    We were also swapping this value on big endien machines.
+    
+    This patch fixes both issues by using be16_to_cpu().
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index e11b23c641e2..d37048c96eab 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -260,7 +260,7 @@ static int iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	}
+ 
+ 	if (rhdr->cmd_status == SAM_STAT_CHECK_CONDITION) {
+-		int senselen;
++		uint16_t senselen;
+ 
+ 		if (datalen < 2) {
+ invalid_datalen:
+@@ -270,12 +270,12 @@ static int iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			goto out;
+ 		}
+ 
+-		senselen = (data[0] << 8) | data[1];
++		senselen = be16_to_cpu(*(uint16_t *)data);
+ 		if (datalen < senselen)
+ 			goto invalid_datalen;
+ 
+ 		memcpy(sc->sense_buffer, data + 2,
+-		       min(senselen, SCSI_SENSE_BUFFERSIZE));
++		       min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
+ 		debug_scsi("copied %d bytes of sense\n",
+ 			   min(senselen, SCSI_SENSE_BUFFERSIZE));
+ 	}

commit 0e75f9063f5c55fb0b0b546a7c356f8ec186825e
+Author: Mike Christie 
+Date:   Fri Dec 1 10:40:55 2006 +0100
+
+    [PATCH] block: support larger block pc requests
+    
+    This patch modifies blk_rq_map/unmap_user() and the cdrom and scsi_ioctl.c
+    users so that it supports requests larger than bio by chaining them together.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
+index 9eaee6640535..0f82e12f7b67 100644
+--- a/block/ll_rw_blk.c
++++ b/block/ll_rw_blk.c
+@@ -2322,6 +2322,84 @@ void blk_insert_request(request_queue_t *q, struct request *rq,
+ 
+ EXPORT_SYMBOL(blk_insert_request);
+ 
++static int __blk_rq_unmap_user(struct bio *bio)
++{
++	int ret = 0;
++
++	if (bio) {
++		if (bio_flagged(bio, BIO_USER_MAPPED))
++			bio_unmap_user(bio);
++		else
++			ret = bio_uncopy_user(bio);
++	}
++
++	return ret;
++}
++
++static int __blk_rq_map_user(request_queue_t *q, struct request *rq,
++			     void __user *ubuf, unsigned int len)
++{
++	unsigned long uaddr;
++	struct bio *bio, *orig_bio;
++	int reading, ret;
++
++	reading = rq_data_dir(rq) == READ;
++
++	/*
++	 * if alignment requirement is satisfied, map in user pages for
++	 * direct dma. else, set up kernel bounce buffers
++	 */
++	uaddr = (unsigned long) ubuf;
++	if (!(uaddr & queue_dma_alignment(q)) && !(len & queue_dma_alignment(q)))
++		bio = bio_map_user(q, NULL, uaddr, len, reading);
++	else
++		bio = bio_copy_user(q, uaddr, len, reading);
++
++	if (IS_ERR(bio)) {
++		return PTR_ERR(bio);
++	}
++
++	orig_bio = bio;
++	blk_queue_bounce(q, &bio);
++	/*
++	 * We link the bounce buffer in and could have to traverse it
++	 * later so we have to get a ref to prevent it from being freed
++	 */
++	bio_get(bio);
++
++	/*
++	 * for most (all? don't know of any) queues we could
++	 * skip grabbing the queue lock here. only drivers with
++	 * funky private ->back_merge_fn() function could be
++	 * problematic.
++	 */
++	spin_lock_irq(q->queue_lock);
++	if (!rq->bio)
++		blk_rq_bio_prep(q, rq, bio);
++	else if (!q->back_merge_fn(q, rq, bio)) {
++		ret = -EINVAL;
++		spin_unlock_irq(q->queue_lock);
++		goto unmap_bio;
++	} else {
++		rq->biotail->bi_next = bio;
++		rq->biotail = bio;
++
++		rq->nr_sectors += bio_sectors(bio);
++		rq->hard_nr_sectors = rq->nr_sectors;
++		rq->data_len += bio->bi_size;
++	}
++	spin_unlock_irq(q->queue_lock);
++
++	return bio->bi_size;
++
++unmap_bio:
++	/* if it was boucned we must call the end io function */
++	bio_endio(bio, bio->bi_size, 0);
++	__blk_rq_unmap_user(orig_bio);
++	bio_put(bio);
++	return ret;
++}
++
+ /**
+  * blk_rq_map_user - map user data to a request, for REQ_BLOCK_PC usage
+  * @q:		request queue where request should be inserted
+@@ -2343,42 +2421,44 @@ EXPORT_SYMBOL(blk_insert_request);
+  *    unmapping.
+  */
+ int blk_rq_map_user(request_queue_t *q, struct request *rq, void __user *ubuf,
+-		    unsigned int len)
++		    unsigned long len)
+ {
+-	unsigned long uaddr;
+-	struct bio *bio;
+-	int reading;
++	unsigned long bytes_read = 0;
++	int ret;
+ 
+ 	if (len > (q->max_hw_sectors << 9))
+ 		return -EINVAL;
+ 	if (!len || !ubuf)
+ 		return -EINVAL;
+ 
+-	reading = rq_data_dir(rq) == READ;
++	while (bytes_read != len) {
++		unsigned long map_len, end, start;
+ 
+-	/*
+-	 * if alignment requirement is satisfied, map in user pages for
+-	 * direct dma. else, set up kernel bounce buffers
+-	 */
+-	uaddr = (unsigned long) ubuf;
+-	if (!(uaddr & queue_dma_alignment(q)) && !(len & queue_dma_alignment(q)))
+-		bio = bio_map_user(q, NULL, uaddr, len, reading);
+-	else
+-		bio = bio_copy_user(q, uaddr, len, reading);
++		map_len = min_t(unsigned long, len - bytes_read, BIO_MAX_SIZE);
++		end = ((unsigned long)ubuf + map_len + PAGE_SIZE - 1)
++								>> PAGE_SHIFT;
++		start = (unsigned long)ubuf >> PAGE_SHIFT;
+ 
+-	if (!IS_ERR(bio)) {
+-		rq->bio = rq->biotail = bio;
+-		blk_rq_bio_prep(q, rq, bio);
++		/*
++		 * A bad offset could cause us to require BIO_MAX_PAGES + 1
++		 * pages. If this happens we just lower the requested
++		 * mapping len by a page so that we can fit
++		 */
++		if (end - start > BIO_MAX_PAGES)
++			map_len -= PAGE_SIZE;
+ 
+-		rq->buffer = rq->data = NULL;
+-		rq->data_len = len;
+-		return 0;
++		ret = __blk_rq_map_user(q, rq, ubuf, map_len);
++		if (ret < 0)
++			goto unmap_rq;
++		bytes_read += ret;
++		ubuf += ret;
+ 	}
+ 
+-	/*
+-	 * bio is the err-ptr
+-	 */
+-	return PTR_ERR(bio);
++	rq->buffer = rq->data = NULL;
++	return 0;
++unmap_rq:
++	blk_rq_unmap_user(rq);
++	return ret;
+ }
+ 
+ EXPORT_SYMBOL(blk_rq_map_user);
+@@ -2404,7 +2484,7 @@ EXPORT_SYMBOL(blk_rq_map_user);
+  *    unmapping.
+  */
+ int blk_rq_map_user_iov(request_queue_t *q, struct request *rq,
+-			struct sg_iovec *iov, int iov_count)
++			struct sg_iovec *iov, int iov_count, unsigned int len)
+ {
+ 	struct bio *bio;
+ 
+@@ -2418,10 +2498,15 @@ int blk_rq_map_user_iov(request_queue_t *q, struct request *rq,
+ 	if (IS_ERR(bio))
+ 		return PTR_ERR(bio);
+ 
+-	rq->bio = rq->biotail = bio;
++	if (bio->bi_size != len) {
++		bio_endio(bio, bio->bi_size, 0);
++		bio_unmap_user(bio);
++		return -EINVAL;
++	}
++
++	bio_get(bio);
+ 	blk_rq_bio_prep(q, rq, bio);
+ 	rq->buffer = rq->data = NULL;
+-	rq->data_len = bio->bi_size;
+ 	return 0;
+ }
+ 
+@@ -2429,23 +2514,26 @@ EXPORT_SYMBOL(blk_rq_map_user_iov);
+ 
+ /**
+  * blk_rq_unmap_user - unmap a request with user data
+- * @bio:	bio to be unmapped
+- * @ulen:	length of user buffer
++ * @rq:		rq to be unmapped
+  *
+  * Description:
+- *    Unmap a bio previously mapped by blk_rq_map_user().
++ *    Unmap a rq previously mapped by blk_rq_map_user().
++ *    rq->bio must be set to the original head of the request.
+  */
+-int blk_rq_unmap_user(struct bio *bio, unsigned int ulen)
++int blk_rq_unmap_user(struct request *rq)
+ {
+-	int ret = 0;
++	struct bio *bio, *mapped_bio;
+ 
+-	if (bio) {
+-		if (bio_flagged(bio, BIO_USER_MAPPED))
+-			bio_unmap_user(bio);
++	while ((bio = rq->bio)) {
++		if (bio_flagged(bio, BIO_BOUNCED))
++			mapped_bio = bio->bi_private;
+ 		else
+-			ret = bio_uncopy_user(bio);
+-	}
++			mapped_bio = bio;
+ 
++		__blk_rq_unmap_user(mapped_bio);
++		rq->bio = bio->bi_next;
++		bio_put(bio);
++	}
+ 	return 0;
+ }
+ 
+@@ -2476,11 +2564,8 @@ int blk_rq_map_kern(request_queue_t *q, struct request *rq, void *kbuf,
+ 	if (rq_data_dir(rq) == WRITE)
+ 		bio->bi_rw |= (1 << BIO_RW);
+ 
+-	rq->bio = rq->biotail = bio;
+ 	blk_rq_bio_prep(q, rq, bio);
+-
+ 	rq->buffer = rq->data = NULL;
+-	rq->data_len = len;
+ 	return 0;
+ }
+ 
+@@ -3495,6 +3580,7 @@ void blk_rq_bio_prep(request_queue_t *q, struct request *rq, struct bio *bio)
+ 	rq->hard_cur_sectors = rq->current_nr_sectors;
+ 	rq->hard_nr_sectors = rq->nr_sectors = bio_sectors(bio);
+ 	rq->buffer = bio_data(bio);
++	rq->data_len = bio->bi_size;
+ 
+ 	rq->bio = rq->biotail = bio;
+ }
+diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
+index e55a75621437..5493c2fbbab1 100644
+--- a/block/scsi_ioctl.c
++++ b/block/scsi_ioctl.c
+@@ -226,7 +226,6 @@ static int sg_io(struct file *file, request_queue_t *q,
+ 	unsigned long start_time;
+ 	int writing = 0, ret = 0;
+ 	struct request *rq;
+-	struct bio *bio;
+ 	char sense[SCSI_SENSE_BUFFERSIZE];
+ 	unsigned char cmd[BLK_MAX_CDB];
+ 
+@@ -258,30 +257,6 @@ static int sg_io(struct file *file, request_queue_t *q,
+ 	if (!rq)
+ 		return -ENOMEM;
+ 
+-	if (hdr->iovec_count) {
+-		const int size = sizeof(struct sg_iovec) * hdr->iovec_count;
+-		struct sg_iovec *iov;
+-
+-		iov = kmalloc(size, GFP_KERNEL);
+-		if (!iov) {
+-			ret = -ENOMEM;
+-			goto out;
+-		}
+-
+-		if (copy_from_user(iov, hdr->dxferp, size)) {
+-			kfree(iov);
+-			ret = -EFAULT;
+-			goto out;
+-		}
+-
+-		ret = blk_rq_map_user_iov(q, rq, iov, hdr->iovec_count);
+-		kfree(iov);
+-	} else if (hdr->dxfer_len)
+-		ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len);
+-
+-	if (ret)
+-		goto out;
+-
+ 	/*
+ 	 * fill in request structure
+ 	 */
+@@ -294,7 +269,6 @@ static int sg_io(struct file *file, request_queue_t *q,
+ 	rq->sense_len = 0;
+ 
+ 	rq->cmd_type = REQ_TYPE_BLOCK_PC;
+-	bio = rq->bio;
+ 
+ 	/*
+ 	 * bounce this after holding a reference to the original bio, it's
+@@ -309,6 +283,31 @@ static int sg_io(struct file *file, request_queue_t *q,
+ 	if (!rq->timeout)
+ 		rq->timeout = BLK_DEFAULT_TIMEOUT;
+ 
++	if (hdr->iovec_count) {
++		const int size = sizeof(struct sg_iovec) * hdr->iovec_count;
++		struct sg_iovec *iov;
++
++		iov = kmalloc(size, GFP_KERNEL);
++		if (!iov) {
++			ret = -ENOMEM;
++			goto out;
++		}
++
++		if (copy_from_user(iov, hdr->dxferp, size)) {
++			kfree(iov);
++			ret = -EFAULT;
++			goto out;
++		}
++
++		ret = blk_rq_map_user_iov(q, rq, iov, hdr->iovec_count,
++					  hdr->dxfer_len);
++		kfree(iov);
++	} else if (hdr->dxfer_len)
++		ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len);
++
++	if (ret)
++		goto out;
++
+ 	rq->retries = 0;
+ 
+ 	start_time = jiffies;
+@@ -339,7 +338,7 @@ static int sg_io(struct file *file, request_queue_t *q,
+ 			hdr->sb_len_wr = len;
+ 	}
+ 
+-	if (blk_rq_unmap_user(bio, hdr->dxfer_len))
++	if (blk_rq_unmap_user(rq))
+ 		ret = -EFAULT;
+ 
+ 	/* may not have succeeded, but output values written to control
+diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
+index 7ea0f48f8fa6..2df5cf4ec743 100644
+--- a/drivers/cdrom/cdrom.c
++++ b/drivers/cdrom/cdrom.c
+@@ -2133,16 +2133,14 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
+ 		rq->timeout = 60 * HZ;
+ 		bio = rq->bio;
+ 
+-		if (rq->bio)
+-			blk_queue_bounce(q, &rq->bio);
+-
+ 		if (blk_execute_rq(q, cdi->disk, rq, 0)) {
+ 			struct request_sense *s = rq->sense;
+ 			ret = -EIO;
+ 			cdi->last_sense = s->sense_key;
+ 		}
+ 
+-		if (blk_rq_unmap_user(bio, len))
++		rq->bio = bio;
++		if (blk_rq_unmap_user(rq))
+ 			ret = -EFAULT;
+ 
+ 		if (ret)
+diff --git a/fs/bio.c b/fs/bio.c
+index d91cfbf7ebc4..aa4d09bd4e71 100644
+--- a/fs/bio.c
++++ b/fs/bio.c
+@@ -560,10 +560,8 @@ struct bio *bio_copy_user(request_queue_t *q, unsigned long uaddr,
+ 			break;
+ 		}
+ 
+-		if (bio_add_pc_page(q, bio, page, bytes, 0) < bytes) {
+-			ret = -EINVAL;
++		if (bio_add_pc_page(q, bio, page, bytes, 0) < bytes)
+ 			break;
+-		}
+ 
+ 		len -= bytes;
+ 	}
+@@ -750,7 +748,6 @@ struct bio *bio_map_user_iov(request_queue_t *q, struct block_device *bdev,
+ 			     int write_to_vm)
+ {
+ 	struct bio *bio;
+-	int len = 0, i;
+ 
+ 	bio = __bio_map_user_iov(q, bdev, iov, iov_count, write_to_vm);
+ 
+@@ -765,18 +762,7 @@ struct bio *bio_map_user_iov(request_queue_t *q, struct block_device *bdev,
+ 	 */
+ 	bio_get(bio);
+ 
+-	for (i = 0; i < iov_count; i++)
+-		len += iov[i].iov_len;
+-
+-	if (bio->bi_size == len)
+-		return bio;
+-
+-	/*
+-	 * don't support partial mappings
+-	 */
+-	bio_endio(bio, bio->bi_size, 0);
+-	bio_unmap_user(bio);
+-	return ERR_PTR(-EINVAL);
++	return bio;
+ }
+ 
+ static void __bio_unmap_user(struct bio *bio)
+diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
+index 7bfcde2d5578..e1c7286165ff 100644
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -678,10 +678,11 @@ extern void __blk_stop_queue(request_queue_t *q);
+ extern void blk_run_queue(request_queue_t *);
+ extern void blk_start_queueing(request_queue_t *);
+ extern void blk_queue_activity_fn(request_queue_t *, activity_fn *, void *);
+-extern int blk_rq_map_user(request_queue_t *, struct request *, void __user *, unsigned int);
+-extern int blk_rq_unmap_user(struct bio *, unsigned int);
++extern int blk_rq_map_user(request_queue_t *, struct request *, void __user *, unsigned long);
++extern int blk_rq_unmap_user(struct request *);
+ extern int blk_rq_map_kern(request_queue_t *, struct request *, void *, unsigned int, gfp_t);
+-extern int blk_rq_map_user_iov(request_queue_t *, struct request *, struct sg_iovec *, int);
++extern int blk_rq_map_user_iov(request_queue_t *, struct request *,
++			       struct sg_iovec *, int, unsigned int);
+ extern int blk_execute_rq(request_queue_t *, struct gendisk *,
+ 			  struct request *, int);
+ extern void blk_execute_rq_nowait(request_queue_t *, struct gendisk *,

commit ad2d7225709b11da47e092634cbdf0591829ae9c
+Author: Mike Christie 
+Date:   Fri Dec 1 10:40:20 2006 +0100
+
+    [PATCH] block: kill length alignment test in bio_map_user()
+    
+    The target mode support is mapping in bios using bio_map_user. The
+    current targets do not need their len to be aligned with a queue limit
+    so this check is causing some problems. Note: pointers passed into the
+    kernel are properly aligned by usersapace tgt code so the uaddr check
+    in bio_map_user is ok.
+    
+    The major user, blk_bio_map_user checks for the len before mapping
+    so it is not affected by this patch.
+    
+    And the semi-newly added user blk_rq_map_user_iov has been failing
+    out when the len is not aligned properly so maybe people have been
+    good and not sending misaligned lens or that path is not used very
+    often and this change will not be very dangerous. st and sg do not
+    check the length and we have not seen any problem reports from those
+    wider used paths so this patch should be fairly safe - for mm
+    and wider testing at least.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: FUJITA Tomonori 
+    Signed-off-by: James Bottomley 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/fs/bio.c b/fs/bio.c
+index f95c8749499f..d91cfbf7ebc4 100644
+--- a/fs/bio.c
++++ b/fs/bio.c
+@@ -622,10 +622,9 @@ static struct bio *__bio_map_user_iov(request_queue_t *q,
+ 
+ 		nr_pages += end - start;
+ 		/*
+-		 * transfer and buffer must be aligned to at least hardsector
+-		 * size for now, in the future we can relax this restriction
++		 * buffer must be aligned to at least hardsector size for now
+ 		 */
+-		if ((uaddr & queue_dma_alignment(q)) || (len & queue_dma_alignment(q)))
++		if (uaddr & queue_dma_alignment(q))
+ 			return ERR_PTR(-EINVAL);
+ 	}
+ 

commit 82a0d7b5829ebd033b7f808c026ab43509913692
+Author: Mike Christie 
+Date:   Wed Nov 8 15:58:34 2006 -0600
+
+    [SCSI] iscsi class: update version
+    
+    Update version number
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 2d3baa99ca25..9b25124a989e 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -33,7 +33,7 @@
+ #define ISCSI_SESSION_ATTRS 11
+ #define ISCSI_CONN_ATTRS 11
+ #define ISCSI_HOST_ATTRS 0
+-#define ISCSI_TRANSPORT_VERSION "2.0-685"
++#define ISCSI_TRANSPORT_VERSION "2.0-724"
+ 
+ struct iscsi_internal {
+ 	int daemon_pid;

commit db37c505e5dfc1a26d6c82f1ce0c3ae06641c3e0
+Author: Mike Christie 
+Date:   Wed Nov 8 15:58:33 2006 -0600
+
+    [SCSI] iscsi_tcp: fix xmittask oops
+    
+    XMSTATE_SOL_HDR could be set when the xmit thread tests it, but there may
+    not be anything on the r2tqueue yet. Move the XMSTATE_SOL_HDR set
+    before the addition to the queue to make sure that when we pull something
+    off it it is valid. This does not add locks around the xmstate test or make
+    that a atmoic_t because this is a fast path and if it is set when we test it
+    we can handle it there without the overhead. Later on we check the xmitqueue
+    for all requests with the session lock so we will not miss it.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index c0b8b33e935c..d0b139cccbbc 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -415,8 +415,8 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	iscsi_solicit_data_init(conn, ctask, r2t);
+ 
+ 	tcp_ctask->exp_r2tsn = r2tsn + 1;
+-	tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
+ 	__kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*));
++	tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
+ 	list_move_tail(&ctask->running, &conn->xmitqueue);
+ 
+ 	scsi_queue_work(session->host, &conn->xmitwork);
+@@ -1627,9 +1627,12 @@ static int iscsi_send_sol_pdu(struct iscsi_conn *conn,
+ 	if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) {
+ 		tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
+ 		tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
+-		if (!tcp_ctask->r2t)
++		if (!tcp_ctask->r2t) {
++			spin_lock_bh(&session->lock);
+ 			__kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t,
+ 				    sizeof(void*));
++			spin_unlock_bh(&session->lock);
++		}
+ send_hdr:
+ 		r2t = tcp_ctask->r2t;
+ 		dtask = &r2t->dtask;

commit b5072ea0910e5c8c79b8313e0ef70ca763983dbf
+Author: Mike Christie 
+Date:   Mon Oct 16 18:09:42 2006 -0400
+
+    [SCSI] libiscsi: fix logout pdu processing
+    
+    According to the iscsi RFC, we cannot send other requests if
+    we have sent a logout pdu. This patch enforces this requirement
+    by blocking the session and suspending the send thread. Userspace
+    decides if we restart the connection or if we just free everything.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index f5a9560b357f..2865ebd557ef 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -578,6 +578,27 @@ void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_conn_failure);
+ 
++static int iscsi_xmit_imm_task(struct iscsi_conn *conn)
++{
++	struct iscsi_hdr *hdr = conn->mtask->hdr;
++	int rc, was_logout = 0;
++
++	if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) {
++		conn->session->state = ISCSI_STATE_IN_RECOVERY;
++		iscsi_block_session(session_to_cls(conn->session));
++		was_logout = 1;
++	}
++	rc = conn->session->tt->xmit_mgmt_task(conn, conn->mtask);
++	if (rc)
++		return rc;
++
++	if (was_logout) {
++		set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
++		return -ENODATA;
++	}
++	return 0;
++}
++
+ /**
+  * iscsi_data_xmit - xmit any command into the scheduled connection
+  * @conn: iscsi connection
+@@ -623,7 +644,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 		conn->ctask = NULL;
+ 	}
+ 	if (conn->mtask) {
+-		rc = tt->xmit_mgmt_task(conn, conn->mtask);
++		rc = iscsi_xmit_imm_task(conn);
+ 	        if (rc)
+ 		        goto again;
+ 		/* done with this in-progress mtask */
+@@ -638,7 +659,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 			list_add_tail(&conn->mtask->running,
+ 				      &conn->mgmt_run_list);
+ 			spin_unlock_bh(&conn->session->lock);
+-			rc = tt->xmit_mgmt_task(conn, conn->mtask);
++			rc = iscsi_xmit_imm_task(conn);
+ 		        if (rc)
+ 			        goto again;
+ 	        }

commit 5831c737f724aa6a655a908d202221f079f30036
+Author: Mike Christie 
+Date:   Mon Oct 16 18:09:41 2006 -0400
+
+    [SCSI] libiscsi: fix aen support
+    
+    We have been dropping the pdu. We should just send it to userspace
+    and let it handle it.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index e3a2ec253cf1..f5a9560b357f 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -481,8 +481,8 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			break;
+ 		case ISCSI_OP_ASYNC_EVENT:
+ 			conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
+-			/* we need sth like iscsi_async_event_rsp() */
+-			rc = ISCSI_ERR_BAD_OPCODE;
++			if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen))
++				rc = ISCSI_ERR_CONN_FAILED;
+ 			break;
+ 		default:
+ 			rc = ISCSI_ERR_BAD_OPCODE;

commit cd529a46e17b43976d05c1e2ece2676ec7941cc8
+Author: Mike Christie 
+Date:   Mon Oct 16 18:09:40 2006 -0400
+
+    [SCSI] libiscsi: fix missed iscsi_task_put in xmit error path
+    
+    from bhalevy@gmail.com:
+    
+    It looks like change 652 to libiscsi.c added some dead code around line
+    670
+                    if (rc) {
+                            spin_unlock_bh(&conn->session->lock);
+                            goto again;
+                    }
+    
+    since 5 lines above we goto again if (rc).
+    
+    It looks like the previous if (rc) should go away if we want to put the
+    ctask before
+    breaking out of the while loop with "goto again" (see following patch).
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 1000fe936791..e3a2ec253cf1 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -661,8 +661,6 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 		spin_unlock_bh(&conn->session->lock);
+ 
+ 		rc = tt->xmit_cmd_task(conn, conn->ctask);
+-		if (rc)
+-			goto again;
+ 
+ 		spin_lock_bh(&conn->session->lock);
+ 		__iscsi_put_ctask(conn->ctask);

commit 98644047916c24258fb47c3dab2bed8a44f53b83
+Author: Mike Christie 
+Date:   Mon Oct 16 18:09:39 2006 -0400
+
+    [SCSI] libiscsi: fix oops in connection create failure path
+    
+    If connection creation fails we end up calling list_del
+    on a invalid struct. This then causes an oops. We are not
+    acutally using the lists (old MCS code we thought might
+    be useful elsewhere) so this patch just removes that
+    code.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index c542d0e95e68..1000fe936791 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -778,6 +778,10 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 	}
+ 
+ 	conn = session->leadconn;
++	if (!conn) {
++		reason = FAILURE_SESSION_FREED;
++		goto fault;
++	}
+ 
+ 	if (!__kfifo_get(session->cmdpool.queue, (void*)&ctask,
+ 			 sizeof(void*))) {
+@@ -1377,7 +1381,6 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
+ 	}
+ 
+ 	spin_lock_init(&session->lock);
+-	INIT_LIST_HEAD(&session->connections);
+ 
+ 	/* initialize immediate command pool */
+ 	if (iscsi_pool_init(&session->mgmtpool, session->mgmtpool_max,
+@@ -1580,16 +1583,11 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
+ 	kfree(conn->persistent_address);
+ 	__kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask,
+ 		    sizeof(void*));
+-	list_del(&conn->item);
+-	if (list_empty(&session->connections))
++	if (session->leadconn == conn) {
+ 		session->leadconn = NULL;
+-	if (session->leadconn && session->leadconn == conn)
+-		session->leadconn = container_of(session->connections.next,
+-			struct iscsi_conn, item);
+-
+-	if (session->leadconn == NULL)
+ 		/* no connections exits.. reset sequencing */
+ 		session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1;
++	}
+ 	spin_unlock_bh(&session->lock);
+ 
+ 	kfifo_free(conn->immqueue);
+@@ -1777,32 +1775,12 @@ int iscsi_conn_bind(struct iscsi_cls_session *cls_session,
+ 		    struct iscsi_cls_conn *cls_conn, int is_leading)
+ {
+ 	struct iscsi_session *session = class_to_transport_session(cls_session);
+-	struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = cls_conn->dd_data;
++	struct iscsi_conn *conn = cls_conn->dd_data;
+ 
+-	/* lookup for existing connection */
+ 	spin_lock_bh(&session->lock);
+-	list_for_each_entry(tmp, &session->connections, item) {
+-		if (tmp == conn) {
+-			if (conn->c_stage != ISCSI_CONN_STOPPED ||
+-			    conn->stop_stage == STOP_CONN_TERM) {
+-				printk(KERN_ERR "iscsi: can't bind "
+-				       "non-stopped connection (%d:%d)\n",
+-				       conn->c_stage, conn->stop_stage);
+-				spin_unlock_bh(&session->lock);
+-				return -EIO;
+-			}
+-			break;
+-		}
+-	}
+-	if (tmp != conn) {
+-		/* bind new iSCSI connection to session */
+-		conn->session = session;
+-		list_add(&conn->item, &session->connections);
+-	}
+-	spin_unlock_bh(&session->lock);
+-
+ 	if (is_leading)
+ 		session->leadconn = conn;
++	spin_unlock_bh(&session->lock);
+ 
+ 	/*
+ 	 * Unblock xmitworker(), Login Phase will pass through.
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 401192e56e50..61eebec00a7b 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -136,7 +136,6 @@ struct iscsi_conn {
+ 
+ 	/* control data */
+ 	int			id;		/* CID */
+-	struct list_head	item;		/* maintains list of conns */
+ 	int			c_stage;	/* connection state */
+ 	/*
+ 	 * Preallocated buffer for pdus that have data but do not
+@@ -235,10 +234,8 @@ struct iscsi_session {
+ 						 * - mgmtpool,		   *
+ 						 * - r2tpool		   */
+ 	int			state;		/* session state           */
+-	struct list_head	item;
+ 	int			age;		/* counts session re-opens */
+ 
+-	struct list_head	connections;	/* list of connections */
+ 	int			cmds_max;	/* size of cmds array */
+ 	struct iscsi_cmd_task	**cmds;		/* Original Cmds arr */
+ 	struct iscsi_queue	cmdpool;	/* PDU's pool */

commit 43a145a3440c5c5f24ff2888801e40e2242187e6
+Author: Mike Christie 
+Date:   Mon Oct 16 18:09:38 2006 -0400
+
+    [SCSI] iscsi class: fix slab corruption during restart
+    
+    The transport class recv mempools are causing slab corruption.
+    We could hack around netlink's lack of mempool support like dm,
+    but it is just too ulgy (dm's hack is ugly enough :) when you need
+    to support broadcast.
+    
+    This patch removes the recv pools. We have not used them even when
+    we were allocting 20 MB per session and the system only had 64 MBs.
+    And we have no pools on the send side and have been ok there. When
+    Peter's work gets merged we can use that since the network guys
+    are in favor of that approach and are not going to add mempools
+    everywhere.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 7b0019cccce3..2d3baa99ca25 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -21,7 +21,6 @@
+  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+  */
+ #include 
+-#include 
+ #include 
+ #include 
+ #include 
+@@ -149,30 +148,6 @@ static DECLARE_TRANSPORT_CLASS(iscsi_connection_class,
+ static struct sock *nls;
+ static DEFINE_MUTEX(rx_queue_mutex);
+ 
+-struct mempool_zone {
+-	mempool_t *pool;
+-	atomic_t allocated;
+-	int size;
+-	int hiwat;
+-	struct list_head freequeue;
+-	spinlock_t freelock;
+-};
+-
+-static struct mempool_zone *z_reply;
+-
+-/*
+- * Z_MAX_* - actual mempool size allocated at the mempool_zone_init() time
+- * Z_HIWAT_* - zone's high watermark when if_error bit will be set to -ENOMEM
+- *             so daemon will notice OOM on NETLINK tranposrt level and will
+- *             be able to predict or change operational behavior
+- */
+-#define Z_MAX_REPLY	8
+-#define Z_HIWAT_REPLY	6
+-#define Z_MAX_PDU	8
+-#define Z_HIWAT_PDU	6
+-#define Z_MAX_ERROR	16
+-#define Z_HIWAT_ERROR	12
+-
+ static LIST_HEAD(sesslist);
+ static DEFINE_SPINLOCK(sesslock);
+ static LIST_HEAD(connlist);
+@@ -414,59 +389,11 @@ int iscsi_destroy_session(struct iscsi_cls_session *session)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_destroy_session);
+ 
+-static void mempool_zone_destroy(struct mempool_zone *zp)
+-{
+-	mempool_destroy(zp->pool);
+-	kfree(zp);
+-}
+-
+-static void*
+-mempool_zone_alloc_skb(gfp_t gfp_mask, void *pool_data)
+-{
+-	struct mempool_zone *zone = pool_data;
+-
+-	return alloc_skb(zone->size, gfp_mask);
+-}
+-
+-static void
+-mempool_zone_free_skb(void *element, void *pool_data)
+-{
+-	kfree_skb(element);
+-}
+-
+-static struct mempool_zone *
+-mempool_zone_init(unsigned max, unsigned size, unsigned hiwat)
+-{
+-	struct mempool_zone *zp;
+-
+-	zp = kzalloc(sizeof(*zp), GFP_KERNEL);
+-	if (!zp)
+-		return NULL;
+-
+-	zp->size = size;
+-	zp->hiwat = hiwat;
+-	INIT_LIST_HEAD(&zp->freequeue);
+-	spin_lock_init(&zp->freelock);
+-	atomic_set(&zp->allocated, 0);
+-
+-	zp->pool = mempool_create(max, mempool_zone_alloc_skb,
+-				  mempool_zone_free_skb, zp);
+-	if (!zp->pool) {
+-		kfree(zp);
+-		return NULL;
+-	}
+-
+-	return zp;
+-}
+-
+ static void iscsi_conn_release(struct device *dev)
+ {
+ 	struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev);
+ 	struct device *parent = conn->dev.parent;
+ 
+-	mempool_zone_destroy(conn->z_pdu);
+-	mempool_zone_destroy(conn->z_error);
+-
+ 	kfree(conn);
+ 	put_device(parent);
+ }
+@@ -476,31 +403,6 @@ static int iscsi_is_conn_dev(const struct device *dev)
+ 	return dev->release == iscsi_conn_release;
+ }
+ 
+-static int iscsi_create_event_pools(struct iscsi_cls_conn *conn)
+-{
+-	conn->z_pdu = mempool_zone_init(Z_MAX_PDU,
+-			NLMSG_SPACE(sizeof(struct iscsi_uevent) +
+-				    sizeof(struct iscsi_hdr) +
+-				    DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH),
+-			Z_HIWAT_PDU);
+-	if (!conn->z_pdu) {
+-		dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
+-			   "pdu zone for new conn\n");
+-		return -ENOMEM;
+-	}
+-
+-	conn->z_error = mempool_zone_init(Z_MAX_ERROR,
+-			NLMSG_SPACE(sizeof(struct iscsi_uevent)),
+-			Z_HIWAT_ERROR);
+-	if (!conn->z_error) {
+-		dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
+-			   "error zone for new conn\n");
+-		mempool_zone_destroy(conn->z_pdu);
+-		return -ENOMEM;
+-	}
+-	return 0;
+-}
+-
+ /**
+  * iscsi_create_conn - create iscsi class connection
+  * @session: iscsi cls session
+@@ -533,12 +435,9 @@ iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid)
+ 	conn->transport = transport;
+ 	conn->cid = cid;
+ 
+-	if (iscsi_create_event_pools(conn))
+-		goto free_conn;
+-
+ 	/* this is released in the dev's release function */
+ 	if (!get_device(&session->dev))
+-		goto free_conn_pools;
++		goto free_conn;
+ 
+ 	snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
+ 		 session->sid, cid);
+@@ -555,8 +454,6 @@ iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid)
+ 
+ release_parent_ref:
+ 	put_device(&session->dev);
+-free_conn_pools:
+-
+ free_conn:
+ 	kfree(conn);
+ 	return NULL;
+@@ -599,81 +496,31 @@ iscsi_if_transport_lookup(struct iscsi_transport *tt)
+ 	return NULL;
+ }
+ 
+-static inline struct list_head *skb_to_lh(struct sk_buff *skb)
+-{
+-	return (struct list_head *)&skb->cb;
+-}
+-
+-static void
+-mempool_zone_complete(struct mempool_zone *zone)
+-{
+-	unsigned long flags;
+-	struct list_head *lh, *n;
+-
+-	spin_lock_irqsave(&zone->freelock, flags);
+-	list_for_each_safe(lh, n, &zone->freequeue) {
+-		struct sk_buff *skb = (struct sk_buff *)((char *)lh -
+-				offsetof(struct sk_buff, cb));
+-		if (!skb_shared(skb)) {
+-			list_del(skb_to_lh(skb));
+-			mempool_free(skb, zone->pool);
+-			atomic_dec(&zone->allocated);
+-		}
+-	}
+-	spin_unlock_irqrestore(&zone->freelock, flags);
+-}
+-
+-static struct sk_buff*
+-mempool_zone_get_skb(struct mempool_zone *zone)
+-{
+-	struct sk_buff *skb;
+-
+-	skb = mempool_alloc(zone->pool, GFP_ATOMIC);
+-	if (skb)
+-		atomic_inc(&zone->allocated);
+-	return skb;
+-}
+-
+ static int
+-iscsi_broadcast_skb(struct mempool_zone *zone, struct sk_buff *skb, gfp_t gfp)
++iscsi_broadcast_skb(struct sk_buff *skb, gfp_t gfp)
+ {
+-	unsigned long flags;
+ 	int rc;
+ 
+-	skb_get(skb);
+ 	rc = netlink_broadcast(nls, skb, 0, 1, gfp);
+ 	if (rc < 0) {
+-		mempool_free(skb, zone->pool);
+ 		printk(KERN_ERR "iscsi: can not broadcast skb (%d)\n", rc);
+ 		return rc;
+ 	}
+ 
+-	spin_lock_irqsave(&zone->freelock, flags);
+-	INIT_LIST_HEAD(skb_to_lh(skb));
+-	list_add(skb_to_lh(skb), &zone->freequeue);
+-	spin_unlock_irqrestore(&zone->freelock, flags);
+ 	return 0;
+ }
+ 
+ static int
+-iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb, int pid)
++iscsi_unicast_skb(struct sk_buff *skb, int pid)
+ {
+-	unsigned long flags;
+ 	int rc;
+ 
+-	skb_get(skb);
+ 	rc = netlink_unicast(nls, skb, pid, MSG_DONTWAIT);
+ 	if (rc < 0) {
+-		mempool_free(skb, zone->pool);
+ 		printk(KERN_ERR "iscsi: can not unicast skb (%d)\n", rc);
+ 		return rc;
+ 	}
+ 
+-	spin_lock_irqsave(&zone->freelock, flags);
+-	INIT_LIST_HEAD(skb_to_lh(skb));
+-	list_add(skb_to_lh(skb), &zone->freequeue);
+-	spin_unlock_irqrestore(&zone->freelock, flags);
+-
+ 	return 0;
+ }
+ 
+@@ -692,9 +539,7 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
+ 	if (!priv)
+ 		return -EINVAL;
+ 
+-	mempool_zone_complete(conn->z_pdu);
+-
+-	skb = mempool_zone_get_skb(conn->z_pdu);
++	skb = alloc_skb(len, GFP_ATOMIC);
+ 	if (!skb) {
+ 		iscsi_conn_error(conn, ISCSI_ERR_CONN_FAILED);
+ 		dev_printk(KERN_ERR, &conn->dev, "iscsi: can not deliver "
+@@ -707,15 +552,13 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
+ 	memset(ev, 0, sizeof(*ev));
+ 	ev->transport_handle = iscsi_handle(conn->transport);
+ 	ev->type = ISCSI_KEVENT_RECV_PDU;
+-	if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
+-		ev->iferror = -ENOMEM;
+ 	ev->r.recv_req.cid = conn->cid;
+ 	ev->r.recv_req.sid = iscsi_conn_get_sid(conn);
+ 	pdu = (char*)ev + sizeof(*ev);
+ 	memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
+ 	memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
+ 
+-	return iscsi_unicast_skb(conn->z_pdu, skb, priv->daemon_pid);
++	return iscsi_unicast_skb(skb, priv->daemon_pid);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
+ 
+@@ -731,9 +574,7 @@ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
+ 	if (!priv)
+ 		return;
+ 
+-	mempool_zone_complete(conn->z_error);
+-
+-	skb = mempool_zone_get_skb(conn->z_error);
++	skb = alloc_skb(len, GFP_ATOMIC);
+ 	if (!skb) {
+ 		dev_printk(KERN_ERR, &conn->dev, "iscsi: gracefully ignored "
+ 			  "conn error (%d)\n", error);
+@@ -744,13 +585,11 @@ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
+ 	ev = NLMSG_DATA(nlh);
+ 	ev->transport_handle = iscsi_handle(conn->transport);
+ 	ev->type = ISCSI_KEVENT_CONN_ERROR;
+-	if (atomic_read(&conn->z_error->allocated) >= conn->z_error->hiwat)
+-		ev->iferror = -ENOMEM;
+ 	ev->r.connerror.error = error;
+ 	ev->r.connerror.cid = conn->cid;
+ 	ev->r.connerror.sid = iscsi_conn_get_sid(conn);
+ 
+-	iscsi_broadcast_skb(conn->z_error, skb, GFP_ATOMIC);
++	iscsi_broadcast_skb(skb, GFP_ATOMIC);
+ 
+ 	dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n",
+ 		   error);
+@@ -767,9 +606,7 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi,
+ 	int flags = multi ? NLM_F_MULTI : 0;
+ 	int t = done ? NLMSG_DONE : type;
+ 
+-	mempool_zone_complete(z_reply);
+-
+-	skb = mempool_zone_get_skb(z_reply);
++	skb = alloc_skb(len, GFP_ATOMIC);
+ 	/*
+ 	 * FIXME:
+ 	 * user is supposed to react on iferror == -ENOMEM;
+@@ -780,7 +617,7 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi,
+ 	nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0);
+ 	nlh->nlmsg_flags = flags;
+ 	memcpy(NLMSG_DATA(nlh), payload, size);
+-	return iscsi_unicast_skb(z_reply, skb, pid);
++	return iscsi_unicast_skb(skb, pid);
+ }
+ 
+ static int
+@@ -810,9 +647,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
+ 	do {
+ 		int actual_size;
+ 
+-		mempool_zone_complete(conn->z_pdu);
+-
+-		skbstat = mempool_zone_get_skb(conn->z_pdu);
++		skbstat = alloc_skb(len, GFP_ATOMIC);
+ 		if (!skbstat) {
+ 			dev_printk(KERN_ERR, &conn->dev, "iscsi: can not "
+ 				   "deliver stats: OOM\n");
+@@ -825,8 +660,6 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
+ 		memset(evstat, 0, sizeof(*evstat));
+ 		evstat->transport_handle = iscsi_handle(conn->transport);
+ 		evstat->type = nlh->nlmsg_type;
+-		if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
+-			evstat->iferror = -ENOMEM;
+ 		evstat->u.get_stats.cid =
+ 			ev->u.get_stats.cid;
+ 		evstat->u.get_stats.sid =
+@@ -845,7 +678,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
+ 		skb_trim(skbstat, NLMSG_ALIGN(actual_size));
+ 		nlhstat->nlmsg_len = actual_size;
+ 
+-		err = iscsi_unicast_skb(conn->z_pdu, skbstat, priv->daemon_pid);
++		err = iscsi_unicast_skb(skbstat, priv->daemon_pid);
+ 	} while (err < 0 && err != -ECONNREFUSED);
+ 
+ 	return err;
+@@ -876,9 +709,7 @@ int iscsi_if_destroy_session_done(struct iscsi_cls_conn *conn)
+ 	session = iscsi_dev_to_session(conn->dev.parent);
+ 	shost = iscsi_session_to_shost(session);
+ 
+-	mempool_zone_complete(conn->z_pdu);
+-
+-	skb = mempool_zone_get_skb(conn->z_pdu);
++	skb = alloc_skb(len, GFP_KERNEL);
+ 	if (!skb) {
+ 		dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
+ 			  "session creation event\n");
+@@ -896,7 +727,7 @@ int iscsi_if_destroy_session_done(struct iscsi_cls_conn *conn)
+ 	 * this will occur if the daemon is not up, so we just warn
+ 	 * the user and when the daemon is restarted it will handle it
+ 	 */
+-	rc = iscsi_broadcast_skb(conn->z_pdu, skb, GFP_KERNEL);
++	rc = iscsi_broadcast_skb(skb, GFP_KERNEL);
+ 	if (rc < 0)
+ 		dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
+ 			  "session destruction event. Check iscsi daemon\n");
+@@ -939,9 +770,7 @@ int iscsi_if_create_session_done(struct iscsi_cls_conn *conn)
+ 	session = iscsi_dev_to_session(conn->dev.parent);
+ 	shost = iscsi_session_to_shost(session);
+ 
+-	mempool_zone_complete(conn->z_pdu);
+-
+-	skb = mempool_zone_get_skb(conn->z_pdu);
++	skb = alloc_skb(len, GFP_KERNEL);
+ 	if (!skb) {
+ 		dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
+ 			  "session creation event\n");
+@@ -959,7 +788,7 @@ int iscsi_if_create_session_done(struct iscsi_cls_conn *conn)
+ 	 * this will occur if the daemon is not up, so we just warn
+ 	 * the user and when the daemon is restarted it will handle it
+ 	 */
+-	rc = iscsi_broadcast_skb(conn->z_pdu, skb, GFP_KERNEL);
++	rc = iscsi_broadcast_skb(skb, GFP_KERNEL);
+ 	if (rc < 0)
+ 		dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
+ 			  "session creation event. Check iscsi daemon\n");
+@@ -1278,9 +1107,6 @@ iscsi_if_rx(struct sock *sk, int len)
+ 				err = iscsi_if_send_reply(
+ 					NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq,
+ 					nlh->nlmsg_type, 0, 0, ev, sizeof(*ev));
+-				if (atomic_read(&z_reply->allocated) >=
+-						z_reply->hiwat)
+-					ev->iferror = -ENOMEM;
+ 			} while (err < 0 && err != -ECONNREFUSED);
+ 			skb_pull(skb, rlen);
+ 		}
+@@ -1584,32 +1410,6 @@ int iscsi_unregister_transport(struct iscsi_transport *tt)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_unregister_transport);
+ 
+-static int
+-iscsi_rcv_nl_event(struct notifier_block *this, unsigned long event, void *ptr)
+-{
+-	struct netlink_notify *n = ptr;
+-
+-	if (event == NETLINK_URELEASE &&
+-	    n->protocol == NETLINK_ISCSI && n->pid) {
+-		struct iscsi_cls_conn *conn;
+-		unsigned long flags;
+-
+-		mempool_zone_complete(z_reply);
+-		spin_lock_irqsave(&connlock, flags);
+-		list_for_each_entry(conn, &connlist, conn_list) {
+-			mempool_zone_complete(conn->z_error);
+-			mempool_zone_complete(conn->z_pdu);
+-		}
+-		spin_unlock_irqrestore(&connlock, flags);
+-	}
+-
+-	return NOTIFY_DONE;
+-}
+-
+-static struct notifier_block iscsi_nl_notifier = {
+-	.notifier_call	= iscsi_rcv_nl_event,
+-};
+-
+ static __init int iscsi_transport_init(void)
+ {
+ 	int err;
+@@ -1633,25 +1433,15 @@ static __init int iscsi_transport_init(void)
+ 	if (err)
+ 		goto unregister_conn_class;
+ 
+-	err = netlink_register_notifier(&iscsi_nl_notifier);
+-	if (err)
+-		goto unregister_session_class;
+-
+ 	nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx,
+ 			THIS_MODULE);
+ 	if (!nls) {
+ 		err = -ENOBUFS;
+-		goto unregister_notifier;
++		goto unregister_session_class;
+ 	}
+ 
+-	z_reply = mempool_zone_init(Z_MAX_REPLY,
+-		NLMSG_SPACE(sizeof(struct iscsi_uevent)), Z_HIWAT_REPLY);
+-	if (z_reply)
+-		return 0;
++	return 0;
+ 
+-	sock_release(nls->sk_socket);
+-unregister_notifier:
+-	netlink_unregister_notifier(&iscsi_nl_notifier);
+ unregister_session_class:
+ 	transport_class_unregister(&iscsi_session_class);
+ unregister_conn_class:
+@@ -1665,9 +1455,7 @@ static __init int iscsi_transport_init(void)
+ 
+ static void __exit iscsi_transport_exit(void)
+ {
+-	mempool_zone_destroy(z_reply);
+ 	sock_release(nls->sk_socket);
+-	netlink_unregister_notifier(&iscsi_nl_notifier);
+ 	transport_class_unregister(&iscsi_connection_class);
+ 	transport_class_unregister(&iscsi_session_class);
+ 	transport_class_unregister(&iscsi_host_class);
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 39e833260bd0..4b95c89c95c9 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -29,7 +29,6 @@
+ struct scsi_transport_template;
+ struct iscsi_transport;
+ struct Scsi_Host;
+-struct mempool_zone;
+ struct iscsi_cls_conn;
+ struct iscsi_conn;
+ struct iscsi_cmd_task;
+@@ -157,9 +156,6 @@ struct iscsi_cls_conn {
+ 
+ 	int active;			/* must be accessed with the connlock */
+ 	struct device dev;		/* sysfs transport/container device */
+-	struct mempool_zone *z_error;
+-	struct mempool_zone *z_pdu;
+-	struct list_head freequeue;
+ };
+ 
+ #define iscsi_dev_to_conn(_dev) \

commit f70cfa9bef432d7aeb4e35c093ac27fd6f071d7e
+Author: Mike Christie 
+Date:   Sat Sep 30 20:42:31 2006 -0400
+
+    [SCSI] scsi_devinfo: scsi2 HP and Hitachi entries
+    
+    When SCSI-2 they can support luns past 7 and sparse luns.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
+index dc1e1eb8c526..ce63044b1ec8 100644
+--- a/drivers/scsi/scsi_devinfo.c
++++ b/drivers/scsi/scsi_devinfo.c
+@@ -162,6 +162,11 @@ static struct {
+ 	{"HITACHI", "DF600", "*", BLIST_SPARSELUN},
+ 	{"HITACHI", "DISK-SUBSYSTEM", "*", BLIST_ATTACH_PQ3 | BLIST_SPARSELUN | BLIST_LARGELUN},
+ 	{"HITACHI", "OPEN-E", "*", BLIST_ATTACH_PQ3 | BLIST_SPARSELUN | BLIST_LARGELUN},
++	{"HITACHI", "OP-C-", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
++	{"HITACHI", "3380-", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
++	{"HITACHI", "3390-", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
++	{"HITACHI", "6586-", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
++	{"HITACHI", "6588-", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+ 	{"HP", "A6189A", NULL, BLIST_SPARSELUN | BLIST_LARGELUN},	/* HP VA7400 */
+ 	{"HP", "OPEN-", "*", BLIST_REPORTLUN2}, /* HP XP Arrays */
+ 	{"HP", "NetRAID-4M", NULL, BLIST_FORCELUN},
+@@ -169,6 +174,14 @@ static struct {
+ 	{"HP", "C1557A", NULL, BLIST_FORCELUN},
+ 	{"HP", "C3323-300", "4269", BLIST_NOTQ},
+ 	{"HP", "C5713A", NULL, BLIST_NOREPORTLUN},
++	{"HP", "DF400", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
++	{"HP", "DF500", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
++	{"HP", "DF600", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
++	{"HP", "OP-C-", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
++	{"HP", "3380-", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
++	{"HP", "3390-", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
++	{"HP", "6586-", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
++	{"HP", "6588-", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+ 	{"IBM", "AuSaV1S2", NULL, BLIST_FORCELUN},
+ 	{"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+ 	{"IBM", "2105", NULL, BLIST_RETRY_HWERROR},

commit 12427d99489966185dc12a0b6f725d682a3277ca
+Author: Mike Christie 
+Date:   Sat Sep 30 20:42:30 2006 -0400
+
+    [SCSI] scsi_devinfo: add nec iStorage
+    
+    support the report luns opcode
+    .
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
+index f6aadbd9b95f..dc1e1eb8c526 100644
+--- a/drivers/scsi/scsi_devinfo.c
++++ b/drivers/scsi/scsi_devinfo.c
+@@ -189,6 +189,7 @@ static struct {
+ 	{"NAKAMICH", "MJ-4.8S", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
+ 	{"NAKAMICH", "MJ-5.16S", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
+ 	{"NEC", "PD-1 ODX654P", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
++	{"NEC", "iStorage", NULL, BLIST_REPORTLUN2},
+ 	{"NRC", "MBR-7", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
+ 	{"NRC", "MBR-7.4", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
+ 	{"PIONEER", "CD-ROM DRM-600", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},

commit 5f619c5ba509994c9203bfd18f5246b4457e2c22
+Author: Mike Christie 
+Date:   Sat Sep 30 20:42:29 2006 -0400
+
+    [SCSI] scsi_devinfo: add Tornado
+    
+    This is from RHEL4. I do not have any info from our bugzilla. All
+    I could find was something like this thread
+    http://lkml.org/lkml/2005/1/7/346
+    
+    Report lun for linux does not work. It may be our lun format code or
+    it may be the device. It is probably not worth it to add anything
+    special for this device, so the patch just adds BLIST_NOREPORTLUN.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
+index cbf733b4e8ae..f6aadbd9b95f 100644
+--- a/drivers/scsi/scsi_devinfo.c
++++ b/drivers/scsi/scsi_devinfo.c
+@@ -211,6 +211,7 @@ static struct {
+ 	{"SUN", "T300", "*", BLIST_SPARSELUN},
+ 	{"SUN", "T4", "*", BLIST_SPARSELUN},
+ 	{"TEXEL", "CD-ROM", "1.06", BLIST_BORKEN},
++	{"Tornado-", "F4", "*", BLIST_NOREPORTLUN},
+ 	{"TOSHIBA", "CDROM", NULL, BLIST_ISROM},
+ 	{"TOSHIBA", "CD-ROM", NULL, BLIST_ISROM},
+ 	{"USB2.0", "SMARTMEDIA/XD", NULL, BLIST_FORCELUN | BLIST_INQUIRY_36},

commit 3441afc672bc9bfc137ae7717ac1db4b9c28cc8b
+Author: Mike Christie 
+Date:   Sat Sep 30 20:42:28 2006 -0400
+
+    [SCSI] scsi_devinfo: add EMC Invista
+    
+    This is from RHEL4. This box can support
+    scsi2 and can also support BLIST_SPARSELUN | BLIST_LARGELUN.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
+index 3d0429bc14ab..cbf733b4e8ae 100644
+--- a/drivers/scsi/scsi_devinfo.c
++++ b/drivers/scsi/scsi_devinfo.c
+@@ -150,6 +150,7 @@ static struct {
+ 	{"DELL", "PERCRAID", NULL, BLIST_FORCELUN},
+ 	{"DGC", "RAID", NULL, BLIST_SPARSELUN},	/* Dell PV 650F, storage on LUN 0 */
+ 	{"DGC", "DISK", NULL, BLIST_SPARSELUN},	/* Dell PV 650F, no storage on LUN 0 */
++	{"EMC",  "Invista", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+ 	{"EMC", "SYMMETRIX", NULL, BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_FORCELUN},
+ 	{"EMULEX", "MD21/S2     ESDI", NULL, BLIST_SINGLELUN},
+ 	{"FSC", "CentricStor", "*", BLIST_SPARSELUN | BLIST_LARGELUN},

commit 01dfc7fc56f4b7ec0e5344ab44fcf673ebfbf7fa
+Author: Mike Christie 
+Date:   Thu Aug 31 18:09:35 2006 -0400
+
+    [SCSI] iscsi class: update version
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 2ecd14188574..7b0019cccce3 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -34,7 +34,7 @@
+ #define ISCSI_SESSION_ATTRS 11
+ #define ISCSI_CONN_ATTRS 11
+ #define ISCSI_HOST_ATTRS 0
+-#define ISCSI_TRANSPORT_VERSION "1.1-646"
++#define ISCSI_TRANSPORT_VERSION "2.0-685"
+ 
+ struct iscsi_internal {
+ 	int daemon_pid;

commit e648f63c6520d6e572573149c16a64d2c5ad7ec5
+Author: Mike Christie 
+Date:   Thu Aug 31 18:09:34 2006 -0400
+
+    [SCSI] libiscsi: don't call into lld to cleanup task
+    
+    In the normal IO path we should not be calling back
+    into the LLD since the LLD will have cleaned up the
+    task before or after calling complete pdu.
+    
+    For the fail_command path we still need to do this
+    to force the cleanup.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 12b5c1800740..c542d0e95e68 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -213,12 +213,8 @@ static void iscsi_get_ctask(struct iscsi_cmd_task *ctask)
+ 
+ static void __iscsi_put_ctask(struct iscsi_cmd_task *ctask)
+ {
+-	struct iscsi_conn *conn = ctask->conn;
+-
+-	if (atomic_dec_and_test(&ctask->refcount)) {
+-		conn->session->tt->cleanup_cmd_task(conn, ctask);
++	if (atomic_dec_and_test(&ctask->refcount))
+ 		iscsi_complete_command(ctask);
+-	}
+ }
+ 
+ static void iscsi_put_ctask(struct iscsi_cmd_task *ctask)
+@@ -1129,10 +1125,13 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 	sc = ctask->sc;
+ 	if (!sc)
+ 		return;
++
++	conn->session->tt->cleanup_cmd_task(conn, ctask);
+ 	iscsi_ctask_mtask_cleanup(ctask);
+ 
+ 	sc->result = err;
+ 	sc->resid = sc->request_bufflen;
++	/* release ref from queuecommand */
+ 	__iscsi_put_ctask(ctask);
+ }
+ 

commit f47f2cf5d4acf929a3aaa6957c3fc4622c358703
+Author: Mike Christie 
+Date:   Thu Aug 31 18:09:33 2006 -0400
+
+    [SCSI] libiscsi: check that command ptr is set before accessing it
+    
+    If the scsi eh sends a TUR and the session is down we could
+    return SCSI_ML_HOST_BUSY. scsi eh will ignore this and send
+    ask us to abort the command and we blindly accesst the
+    command ptr.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 864c6284e83c..12b5c1800740 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -192,6 +192,8 @@ static void iscsi_complete_command(struct iscsi_cmd_task *ctask)
+ 
+ 	ctask->state = ISCSI_TASK_COMPLETED;
+ 	ctask->sc = NULL;
++	/* SCSI eh reuses commands to verify us */
++	sc->SCp.ptr = NULL;
+ 	list_del_init(&ctask->running);
+ 	__kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*));
+ 	sc->scsi_done(sc);
+@@ -737,6 +739,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 
+ 	sc->scsi_done = done;
+ 	sc->result = 0;
++	sc->SCp.ptr = NULL;
+ 
+ 	host = sc->device->host;
+ 	session = iscsi_hostdata(host->hostdata);
+@@ -801,9 +804,10 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 
+ 	list_add_tail(&ctask->running, &conn->xmitqueue);
+ 	debug_scsi(
+-	       "ctask enq [%s cid %d sc %lx itt 0x%x len %d cmdsn %d win %d]\n",
++	       "ctask enq [%s cid %d sc %p cdb 0x%x itt 0x%x len %d cmdsn %d "
++		"win %d]\n",
+ 		sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
+-		conn->id, (long)sc, ctask->itt, sc->request_bufflen,
++		conn->id, sc, sc->cmnd[0], ctask->itt, sc->request_bufflen,
+ 		session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
+ 	spin_unlock(&session->lock);
+ 
+@@ -1134,11 +1138,24 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 
+ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ {
+-	struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr;
+-	struct iscsi_conn *conn = ctask->conn;
+-	struct iscsi_session *session = conn->session;
++	struct iscsi_cmd_task *ctask;
++	struct iscsi_conn *conn;
++	struct iscsi_session *session;
+ 	int rc;
+ 
++	/*
++	 * if session was ISCSI_STATE_IN_RECOVERY then we may not have
++	 * got the command.
++	 */
++	if (!sc->SCp.ptr) {
++		debug_scsi("sc never reached iscsi layer or it completed.\n");
++		return SUCCESS;
++	}
++
++	ctask = (struct iscsi_cmd_task *)sc->SCp.ptr;
++	conn = ctask->conn;
++	session = conn->session;
++
+ 	conn->eh_abort_cnt++;
+ 	debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt);
+ 

commit ca5186842a6d85e982e3d572ecd407453d0c5116
+Author: Mike Christie 
+Date:   Thu Aug 31 18:09:32 2006 -0400
+
+    [SCSI] iscsi_tcp: fix partial digest recv
+    
+    When a digest is spread across two network buffers, we currently
+    ignore this and try to check the digest with the partial buffer.
+    Or course this fails. This patch has use iscsi_tcp_copy to
+    copy the whole digest before testing it.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 5d292d0b65ec..d91e8949c71e 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -648,10 +648,9 @@ iscsi_ctask_copy(struct iscsi_tcp_conn *tcp_conn, struct iscsi_cmd_task *ctask,
+  *	byte counters.
+  **/
+ static inline int
+-iscsi_tcp_copy(struct iscsi_conn *conn)
++iscsi_tcp_copy(struct iscsi_conn *conn, int buf_size)
+ {
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+-	int buf_size = tcp_conn->in.datalen;
+ 	int buf_left = buf_size - tcp_conn->data_copied;
+ 	int size = min(tcp_conn->in.copy, buf_left);
+ 	int rc;
+@@ -812,7 +811,7 @@ iscsi_data_recv(struct iscsi_conn *conn)
+ 		 * Collect data segment to the connection's data
+ 		 * placeholder
+ 		 */
+-		if (iscsi_tcp_copy(conn)) {
++		if (iscsi_tcp_copy(conn, tcp_conn->in.datalen)) {
+ 			rc = -EAGAIN;
+ 			goto exit;
+ 		}
+@@ -899,10 +898,15 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 
+ 		debug_tcp("extra data_recv offset %d copy %d\n",
+ 			  tcp_conn->in.offset, tcp_conn->in.copy);
+-		skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset,
+-				&recv_digest, 4);
+-		tcp_conn->in.offset += 4;
+-		tcp_conn->in.copy -= 4;
++		rc = iscsi_tcp_copy(conn, sizeof(uint32_t));
++		if (rc) {
++			if (rc == -EAGAIN)
++				goto again;
++			iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
++			return 0;
++		}
++
++		memcpy(&recv_digest, conn->data, sizeof(uint32_t));
+ 		if (recv_digest != tcp_conn->in.datadgst) {
+ 			debug_tcp("iscsi_tcp: data digest error!"
+ 				  "0x%x != 0x%x\n", recv_digest,
+@@ -942,9 +946,10 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 						     &sg, 1);
+ 			}
+ 			crypto_digest_final(tcp_conn->rx_tfm,
+-					    (u8 *) & tcp_conn->in.datadgst);
++					    (u8 *) &tcp_conn->in.datadgst);
+ 			debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst);
+ 			tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV;
++			tcp_conn->data_copied = 0;
+ 		} else
+ 			tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
+ 	}

commit db98ccde0881b8247acb52dece6d94ed770a7aa5
+Author: Mike Christie 
+Date:   Thu Aug 31 18:09:31 2006 -0400
+
+    [SCSI] libiscsi: only check burst lengths when sending unsol data
+    
+    The first burst length is only relevant if immedate data = Yes
+    or if Initial R2T is No
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index fb65311c81dd..864c6284e83c 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1593,7 +1593,8 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
+ 		return -EPERM;
+ 	}
+ 
+-	if (session->first_burst > session->max_burst) {
++	if ((session->imm_data_en || !session->initial_r2t_en) &&
++	     session->first_burst > session->max_burst) {
+ 		printk("iscsi: invalid burst lengths: "
+ 		       "first_burst %d max_burst %d\n",
+ 		       session->first_burst, session->max_burst);

commit d5390f5f788f01788e9dfd41ad516a2908901610
+Author: Mike Christie 
+Date:   Thu Aug 31 18:09:30 2006 -0400
+
+    [SCSI] iscsi_tcp: update header size during relogin
+    
+    When we relogin to a target, we have not yet negotiated digests
+    so we must reset the hdr_size var.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 541912a5b886..5d292d0b65ec 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -1827,9 +1827,11 @@ static void
+ iscsi_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+ {
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 
+ 	iscsi_conn_stop(cls_conn, flag);
+ 	iscsi_tcp_release_conn(conn);
++	tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
+ }
+ 
+ static int

commit 753e7d3866748799e4a8769cd27ea7202654211b
+Author: Mike Christie 
+Date:   Thu Aug 31 18:09:29 2006 -0400
+
+    [SCSI] iscsi_tcp: fix header resend
+    
+    This patch built over the last ones fixes a bug in the partial header
+    resend code, where we add on another 4 bytes to the send length on the resend.
+    We want just the header plus digest.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 82399f71028d..541912a5b886 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -109,7 +109,7 @@ iscsi_hdr_digest(struct iscsi_conn *conn, struct iscsi_buf *buf,
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 
+ 	crypto_digest_digest(tcp_conn->tx_tfm, &buf->sg, 1, crc);
+-	buf->sg.length += sizeof(uint32_t);
++	buf->sg.length = tcp_conn->hdr_size;
+ }
+ 
+ static inline int

commit dd8c0d958621e3137f3e3302f7b8952041a4a1d7
+Author: Mike Christie 
+Date:   Thu Aug 31 18:09:28 2006 -0400
+
+    [SCSI] scsi_tcp: rm data rx and tx tfms
+    
+    We currently allocated seperate tfms for data and header digests. There
+    is no reason for this since we can never calculate a rx header and
+    digest at the same time. Same for sends. So this patch removes the data
+    tfms and has the send and recv sides use the rx_tfm or tx_tfm.
+    
+    I also made the connection creation code preallocate the tfms because I
+    thought I hit a bug where I changed the digests settings during a
+    relogin but could not allocate the tfm and then we just failed.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 290c1d76cd40..82399f71028d 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -693,7 +693,7 @@ iscsi_recv_digest_update(struct iscsi_tcp_conn *tcp_conn, char* buf, int len)
+ 	struct scatterlist tmp;
+ 
+ 	sg_init_one(&tmp, buf, len);
+-	crypto_digest_update(tcp_conn->data_rx_tfm, &tmp, 1);
++	crypto_digest_update(tcp_conn->rx_tfm, &tmp, 1);
+ }
+ 
+ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
+@@ -748,11 +748,11 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
+ 			if (conn->datadgst_en) {
+ 				if (!offset)
+ 					crypto_digest_update(
+-							tcp_conn->data_rx_tfm,
++							tcp_conn->rx_tfm,
+ 							&sg[i], 1);
+ 				else
+ 					partial_sg_digest_update(
+-							tcp_conn->data_rx_tfm,
++							tcp_conn->rx_tfm,
+ 							&sg[i],
+ 							sg[i].offset + offset,
+ 							sg[i].length - offset);
+@@ -766,7 +766,7 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
+ 				/*
+ 				 * data-in is complete, but buffer not...
+ 				 */
+-				partial_sg_digest_update(tcp_conn->data_rx_tfm,
++				partial_sg_digest_update(tcp_conn->rx_tfm,
+ 						&sg[i],
+ 						sg[i].offset, sg[i].length-rc);
+ 			rc = 0;
+@@ -885,10 +885,8 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 		 */
+ 		rc = iscsi_tcp_hdr_recv(conn);
+ 		if (!rc && tcp_conn->in.datalen) {
+-			if (conn->datadgst_en) {
+-				BUG_ON(!tcp_conn->data_rx_tfm);
+-				crypto_digest_init(tcp_conn->data_rx_tfm);
+-			}
++			if (conn->datadgst_en)
++				crypto_digest_init(tcp_conn->rx_tfm);
+ 			tcp_conn->in_progress = IN_PROGRESS_DATA_RECV;
+ 		} else if (rc) {
+ 			iscsi_conn_failure(conn, rc);
+@@ -940,10 +938,10 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 					  tcp_conn->in.padding);
+ 				memset(pad, 0, tcp_conn->in.padding);
+ 				sg_init_one(&sg, pad, tcp_conn->in.padding);
+-				crypto_digest_update(tcp_conn->data_rx_tfm,
++				crypto_digest_update(tcp_conn->rx_tfm,
+ 						     &sg, 1);
+ 			}
+-			crypto_digest_final(tcp_conn->data_rx_tfm,
++			crypto_digest_final(tcp_conn->rx_tfm,
+ 					    (u8 *) & tcp_conn->in.datadgst);
+ 			debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst);
+ 			tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV;
+@@ -1188,7 +1186,7 @@ static inline void
+ iscsi_data_digest_init(struct iscsi_tcp_conn *tcp_conn,
+ 		      struct iscsi_tcp_cmd_task *tcp_ctask)
+ {
+-	crypto_digest_init(tcp_conn->data_tx_tfm);
++	crypto_digest_init(tcp_conn->tx_tfm);
+ 	tcp_ctask->digest_count = 4;
+ }
+ 
+@@ -1444,7 +1442,7 @@ iscsi_send_padding(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 		iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad,
+ 				   tcp_ctask->pad_count);
+ 		if (conn->datadgst_en)
+-			crypto_digest_update(tcp_conn->data_tx_tfm,
++			crypto_digest_update(tcp_conn->tx_tfm,
+ 					     &tcp_ctask->sendbuf.sg, 1);
+ 	} else if (!(tcp_ctask->xmstate & XMSTATE_W_RESEND_PAD))
+ 		return 0;
+@@ -1477,7 +1475,7 @@ iscsi_send_digest(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 	tcp_conn = conn->dd_data;
+ 
+ 	if (!(tcp_ctask->xmstate & XMSTATE_W_RESEND_DATA_DIGEST)) {
+-		crypto_digest_final(tcp_conn->data_tx_tfm, (u8*)digest);
++		crypto_digest_final(tcp_conn->tx_tfm, (u8*)digest);
+ 		iscsi_buf_init_iov(buf, (char*)digest, 4);
+ 	}
+ 	tcp_ctask->xmstate &= ~XMSTATE_W_RESEND_DATA_DIGEST;
+@@ -1511,7 +1509,7 @@ iscsi_send_data(struct iscsi_cmd_task *ctask, struct iscsi_buf *sendbuf,
+ 		rc = iscsi_sendpage(conn, sendbuf, count, &buf_sent);
+ 		*sent = *sent + buf_sent;
+ 		if (buf_sent && conn->datadgst_en)
+-			partial_sg_digest_update(tcp_conn->data_tx_tfm,
++			partial_sg_digest_update(tcp_conn->tx_tfm,
+ 				&sendbuf->sg, sendbuf->sg.offset + offset,
+ 				buf_sent);
+ 		if (!iscsi_buf_left(sendbuf) && *sg != tcp_ctask->bad_sg) {
+@@ -1547,10 +1545,6 @@ iscsi_send_unsol_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 		if (conn->hdrdgst_en)
+ 			iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
+ 					(u8*)dtask->hdrext);
+-		if (conn->datadgst_en) {
+-			iscsi_data_digest_init(ctask->conn->dd_data, tcp_ctask);
+-			dtask->digest = 0;
+-		}
+ 
+ 		tcp_ctask->xmstate &= ~XMSTATE_UNS_INIT;
+ 		iscsi_set_padding(tcp_ctask, ctask->data_count);
+@@ -1563,6 +1557,12 @@ iscsi_send_unsol_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 		return rc;
+ 	}
+ 
++	if (conn->datadgst_en) {
++		dtask = &tcp_ctask->unsol_dtask;
++		iscsi_data_digest_init(ctask->conn->dd_data, tcp_ctask);
++		dtask->digest = 0;
++	}
++
+ 	debug_scsi("uns dout [itt 0x%x dlen %d sent %d]\n",
+ 		   ctask->itt, ctask->unsol_count, tcp_ctask->sent);
+ 	return 0;
+@@ -1629,12 +1629,6 @@ static int iscsi_send_sol_pdu(struct iscsi_conn *conn,
+ 		if (conn->hdrdgst_en)
+ 			iscsi_hdr_digest(conn, &r2t->headbuf,
+ 					(u8*)dtask->hdrext);
+-
+-		if (conn->datadgst_en) {
+-			iscsi_data_digest_init(conn->dd_data, tcp_ctask);
+-			dtask->digest = 0;
+-		}
+-
+ 		rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count);
+ 		if (rc) {
+ 			tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA;
+@@ -1642,6 +1636,11 @@ static int iscsi_send_sol_pdu(struct iscsi_conn *conn,
+ 			return rc;
+ 		}
+ 
++		if (conn->datadgst_en) {
++			iscsi_data_digest_init(conn->dd_data, tcp_ctask);
++			dtask->digest = 0;
++		}
++
+ 		iscsi_set_padding(tcp_ctask, r2t->data_count);
+ 		debug_scsi("sol dout [dsn %d itt 0x%x dlen %d sent %d]\n",
+ 			r2t->solicit_datasn - 1, ctask->itt, r2t->data_count,
+@@ -1764,8 +1763,20 @@ iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ 	/* initial operational parameters */
+ 	tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
+ 
++	tcp_conn->tx_tfm = crypto_alloc_tfm("crc32c", 0);
++	if (!tcp_conn->tx_tfm)
++		goto free_tcp_conn;
++
++	tcp_conn->rx_tfm = crypto_alloc_tfm("crc32c", 0);
++	if (!tcp_conn->rx_tfm)
++		goto free_tx_tfm;
++
+ 	return cls_conn;
+ 
++free_tx_tfm:
++	crypto_free_tfm(tcp_conn->tx_tfm);
++free_tcp_conn:
++	kfree(tcp_conn);
+ tcp_conn_alloc_fail:
+ 	iscsi_conn_teardown(cls_conn);
+ 	return NULL;
+@@ -1807,10 +1818,6 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn)
+ 			crypto_free_tfm(tcp_conn->tx_tfm);
+ 		if (tcp_conn->rx_tfm)
+ 			crypto_free_tfm(tcp_conn->rx_tfm);
+-		if (tcp_conn->data_tx_tfm)
+-			crypto_free_tfm(tcp_conn->data_tx_tfm);
+-		if (tcp_conn->data_rx_tfm)
+-			crypto_free_tfm(tcp_conn->data_rx_tfm);
+ 	}
+ 
+ 	kfree(tcp_conn);
+@@ -1968,48 +1975,11 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
+ 	case ISCSI_PARAM_HDRDGST_EN:
+ 		iscsi_set_param(cls_conn, param, buf, buflen);
+ 		tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
+-		if (conn->hdrdgst_en) {
++		if (conn->hdrdgst_en)
+ 			tcp_conn->hdr_size += sizeof(__u32);
+-			if (!tcp_conn->tx_tfm)
+-				tcp_conn->tx_tfm = crypto_alloc_tfm("crc32c",
+-								    0);
+-			if (!tcp_conn->tx_tfm)
+-				return -ENOMEM;
+-			if (!tcp_conn->rx_tfm)
+-				tcp_conn->rx_tfm = crypto_alloc_tfm("crc32c",
+-								    0);
+-			if (!tcp_conn->rx_tfm) {
+-				crypto_free_tfm(tcp_conn->tx_tfm);
+-				return -ENOMEM;
+-			}
+-		} else {
+-			if (tcp_conn->tx_tfm)
+-				crypto_free_tfm(tcp_conn->tx_tfm);
+-			if (tcp_conn->rx_tfm)
+-				crypto_free_tfm(tcp_conn->rx_tfm);
+-		}
+ 		break;
+ 	case ISCSI_PARAM_DATADGST_EN:
+ 		iscsi_set_param(cls_conn, param, buf, buflen);
+-		if (conn->datadgst_en) {
+-			if (!tcp_conn->data_tx_tfm)
+-				tcp_conn->data_tx_tfm =
+-				    crypto_alloc_tfm("crc32c", 0);
+-			if (!tcp_conn->data_tx_tfm)
+-				return -ENOMEM;
+-			if (!tcp_conn->data_rx_tfm)
+-				tcp_conn->data_rx_tfm =
+-				    crypto_alloc_tfm("crc32c", 0);
+-			if (!tcp_conn->data_rx_tfm) {
+-				crypto_free_tfm(tcp_conn->data_tx_tfm);
+-				return -ENOMEM;
+-			}
+-		} else {
+-			if (tcp_conn->data_tx_tfm)
+-				crypto_free_tfm(tcp_conn->data_tx_tfm);
+-			if (tcp_conn->data_rx_tfm)
+-				crypto_free_tfm(tcp_conn->data_rx_tfm);
+-		}
+ 		tcp_conn->sendpage = conn->datadgst_en ?
+ 			sock_no_sendpage : tcp_conn->sock->ops->sendpage;
+ 		break;
+diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
+index 7e40e94d9fdc..609f4778d125 100644
+--- a/drivers/scsi/iscsi_tcp.h
++++ b/drivers/scsi/iscsi_tcp.h
+@@ -81,10 +81,6 @@ struct iscsi_tcp_conn {
+ 						 * stop to terminate */
+ 	/* iSCSI connection-wide sequencing */
+ 	int			hdr_size;	/* PDU header size */
+-
+-	struct crypto_tfm	*rx_tfm;	/* CRC32C (Rx) */
+-	struct crypto_tfm	*data_rx_tfm;	/* CRC32C (Rx) for data */
+-
+ 	/* control data */
+ 	struct iscsi_tcp_recv	in;		/* TCP receive context */
+ 	int			in_progress;	/* connection state machine */
+@@ -94,9 +90,9 @@ struct iscsi_tcp_conn {
+ 	void			(*old_state_change)(struct sock *);
+ 	void			(*old_write_space)(struct sock *);
+ 
+-	/* xmit */
++	/* data and header digests */
+ 	struct crypto_tfm	*tx_tfm;	/* CRC32C (Tx) */
+-	struct crypto_tfm	*data_tx_tfm;	/* CRC32C (Tx) for data */
++	struct crypto_tfm	*rx_tfm;	/* CRC32C (Rx) */
+ 
+ 	/* MIB custom statistics */
+ 	uint32_t		sendpage_failures_cnt;

commit 62f383003c22cd34920d0412465eddcb1223da0d
+Author: Mike Christie 
+Date:   Thu Aug 31 18:09:27 2006 -0400
+
+    [SCSI] iscsi_tcp: fix padding, data digests, and IO at weird offsets
+    
+    iscsi_tcp calculates padding by using the expected transfer length. This
+    has the problem where if we have immediate data = no and initial R2T =
+    yes, and the transfer length ended up needing padding then we send:
+    
+    1. header
+    2. padding which should have gone after data
+    3. data
+    
+    Besides this bug, we also assume the target will always ask for nice
+    transfer lengths and the first burst length will always be a nice value.
+    As far as I can tell form the RFC this is not a requirement. It would be
+    silly to do this, but if someone did it we will end doing bad things.
+    
+    Finally the last bug in that bit of code is in our handling of the
+    recalculation of data digests when we do not send a whole iscsi_buf in
+    one try. The bug here is that we call crypto_digest_final on a
+    iscsi_sendpage error, then when we send the rest of the iscsi_buf, we
+    doiscsi_data_digest_init and this causes the previous data digest to be
+    lost.
+    
+    And to make matters worse, some of these bugs are replicated over and
+    over and over again for immediate data, solicited data and unsolicited
+    data. So the attached patch made over the iscsi git tree (see
+    kernel.org/git for details) which I updated today to include the patches
+    I said I merged, consolidates the sending of data, padding and digests
+    and calculation of data digests and fixes the above bugs.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index d6927f1a6b65..290c1d76cd40 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -281,7 +281,6 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ {
+ 	struct iscsi_data *hdr;
+ 	struct scsi_cmnd *sc = ctask->sc;
+-	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 
+ 	hdr = &r2t->dtask.hdr;
+ 	memset(hdr, 0, sizeof(struct iscsi_data));
+@@ -336,10 +335,12 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 			sg_count += sg->length;
+ 		}
+ 		BUG_ON(r2t->sg == NULL);
+-	} else
+-		iscsi_buf_init_iov(&tcp_ctask->sendbuf,
++	} else {
++		iscsi_buf_init_iov(&r2t->sendbuf,
+ 			    (char*)sc->request_buffer + r2t->data_offset,
+ 			    r2t->data_count);
++		r2t->sg = NULL;
++	}
+ }
+ 
+ /**
+@@ -503,7 +504,6 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *conn)
+ 			goto copy_hdr;
+ 
+ 		spin_lock(&session->lock);
+-		iscsi_tcp_cleanup_ctask(conn, tcp_conn->in.ctask);
+ 		rc = __iscsi_complete_pdu(conn, hdr, NULL, 0);
+ 		spin_unlock(&session->lock);
+ 		break;
+@@ -676,15 +676,15 @@ iscsi_tcp_copy(struct iscsi_conn *conn)
+ }
+ 
+ static inline void
+-partial_sg_digest_update(struct iscsi_tcp_conn *tcp_conn,
+-			 struct scatterlist *sg, int offset, int length)
++partial_sg_digest_update(struct crypto_tfm *tfm, struct scatterlist *sg,
++			 int offset, int length)
+ {
+ 	struct scatterlist temp;
+ 
+ 	memcpy(&temp, sg, sizeof(struct scatterlist));
+ 	temp.offset = offset;
+ 	temp.length = length;
+-	crypto_digest_update(tcp_conn->data_rx_tfm, &temp, 1);
++	crypto_digest_update(tfm, &temp, 1);
+ }
+ 
+ static void
+@@ -751,7 +751,8 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
+ 							tcp_conn->data_rx_tfm,
+ 							&sg[i], 1);
+ 				else
+-					partial_sg_digest_update(tcp_conn,
++					partial_sg_digest_update(
++							tcp_conn->data_rx_tfm,
+ 							&sg[i],
+ 							sg[i].offset + offset,
+ 							sg[i].length - offset);
+@@ -765,7 +766,8 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
+ 				/*
+ 				 * data-in is complete, but buffer not...
+ 				 */
+-				partial_sg_digest_update(tcp_conn, &sg[i],
++				partial_sg_digest_update(tcp_conn->data_rx_tfm,
++						&sg[i],
+ 						sg[i].offset, sg[i].length-rc);
+ 			rc = 0;
+ 			break;
+@@ -783,7 +785,6 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
+ 			   (long)sc, sc->result, ctask->itt,
+ 			   tcp_conn->in.hdr->flags);
+ 		spin_lock(&conn->session->lock);
+-		iscsi_tcp_cleanup_ctask(conn, ctask);
+ 		__iscsi_complete_pdu(conn, tcp_conn->in.hdr, NULL, 0);
+ 		spin_unlock(&conn->session->lock);
+ 	}
+@@ -803,9 +804,6 @@ iscsi_data_recv(struct iscsi_conn *conn)
+ 		rc = iscsi_scsi_data_in(conn);
+ 		break;
+ 	case ISCSI_OP_SCSI_CMD_RSP:
+-		spin_lock(&conn->session->lock);
+-		iscsi_tcp_cleanup_ctask(conn, tcp_conn->in.ctask);
+-		spin_unlock(&conn->session->lock);
+ 	case ISCSI_OP_TEXT_RSP:
+ 	case ISCSI_OP_LOGIN_RSP:
+ 	case ISCSI_OP_ASYNC_EVENT:
+@@ -1188,37 +1186,12 @@ iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf,
+ 
+ static inline void
+ iscsi_data_digest_init(struct iscsi_tcp_conn *tcp_conn,
+-		      struct iscsi_cmd_task *ctask)
++		      struct iscsi_tcp_cmd_task *tcp_ctask)
+ {
+-	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+-
+-	BUG_ON(!tcp_conn->data_tx_tfm);
+ 	crypto_digest_init(tcp_conn->data_tx_tfm);
+ 	tcp_ctask->digest_count = 4;
+ }
+ 
+-static int
+-iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+-			struct iscsi_buf *buf, uint32_t *digest, int final)
+-{
+-	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+-	int rc = 0;
+-	int sent = 0;
+-
+-	if (final)
+-		crypto_digest_final(tcp_conn->data_tx_tfm, (u8*)digest);
+-
+-	iscsi_buf_init_iov(buf, (char*)digest, 4);
+-	rc = iscsi_sendpage(conn, buf, &tcp_ctask->digest_count, &sent);
+-	if (rc) {
+-		tcp_ctask->datadigest = *digest;
+-		tcp_ctask->xmstate |= XMSTATE_DATA_DIGEST;
+-	} else
+-		tcp_ctask->digest_count = 4;
+-	return rc;
+-}
+-
+ /**
+  * iscsi_solicit_data_cont - initialize next Data-Out
+  * @conn: iscsi connection
+@@ -1236,7 +1209,6 @@ static void
+ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 			struct iscsi_r2t_info *r2t, int left)
+ {
+-	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	struct iscsi_data *hdr;
+ 	struct scsi_cmnd *sc = ctask->sc;
+ 	int new_offset;
+@@ -1265,14 +1237,30 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 	iscsi_buf_init_iov(&r2t->headbuf, (char*)hdr,
+ 			   sizeof(struct iscsi_hdr));
+ 
+-	if (sc->use_sg && !iscsi_buf_left(&r2t->sendbuf)) {
+-		BUG_ON(tcp_ctask->bad_sg == r2t->sg);
++	if (iscsi_buf_left(&r2t->sendbuf))
++		return;
++
++	if (sc->use_sg) {
+ 		iscsi_buf_init_sg(&r2t->sendbuf, r2t->sg);
+ 		r2t->sg += 1;
+-	} else
+-		iscsi_buf_init_iov(&tcp_ctask->sendbuf,
++	} else {
++		iscsi_buf_init_iov(&r2t->sendbuf,
+ 			    (char*)sc->request_buffer + new_offset,
+ 			    r2t->data_count);
++		r2t->sg = NULL;
++	}
++}
++
++static void iscsi_set_padding(struct iscsi_tcp_cmd_task *tcp_ctask,
++			      unsigned long len)
++{
++	tcp_ctask->pad_count = len & (ISCSI_PAD_LEN - 1);
++	if (!tcp_ctask->pad_count)
++		return;
++
++	tcp_ctask->pad_count = ISCSI_PAD_LEN - tcp_ctask->pad_count;
++	debug_scsi("write padding %d bytes\n", tcp_ctask->pad_count);
++	tcp_ctask->xmstate |= XMSTATE_W_PAD;
+ }
+ 
+ /**
+@@ -1300,31 +1288,16 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask)
+ 		if (sc->use_sg) {
+ 			struct scatterlist *sg = sc->request_buffer;
+ 
+-			iscsi_buf_init_sg(&tcp_ctask->sendbuf,
+-					  &sg[tcp_ctask->sg_count++]);
+-			tcp_ctask->sg = sg;
++			iscsi_buf_init_sg(&tcp_ctask->sendbuf, sg);
++			tcp_ctask->sg = sg + 1;
+ 			tcp_ctask->bad_sg = sg + sc->use_sg;
+-		} else
++		} else {
+ 			iscsi_buf_init_iov(&tcp_ctask->sendbuf,
+ 					   sc->request_buffer,
+ 					   sc->request_bufflen);
+-
+-		if (ctask->imm_count)
+-			tcp_ctask->xmstate |= XMSTATE_IMM_DATA;
+-
+-		tcp_ctask->pad_count = ctask->total_length & (ISCSI_PAD_LEN-1);
+-		if (tcp_ctask->pad_count) {
+-			tcp_ctask->pad_count = ISCSI_PAD_LEN -
+-							tcp_ctask->pad_count;
+-			debug_scsi("write padding %d bytes\n",
+-				   tcp_ctask->pad_count);
+-			tcp_ctask->xmstate |= XMSTATE_W_PAD;
++			tcp_ctask->sg = NULL;
++			tcp_ctask->bad_sg = NULL;
+ 		}
+-
+-		if (ctask->unsol_count)
+-			tcp_ctask->xmstate |= XMSTATE_UNS_HDR |
+-						XMSTATE_UNS_INIT;
+-
+ 		debug_scsi("cmd [itt 0x%x total %d imm_data %d "
+ 			   "unsol count %d, unsol offset %d]\n",
+ 			   ctask->itt, ctask->total_length, ctask->imm_count,
+@@ -1410,8 +1383,8 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
+ }
+ 
+ static inline int
+-handle_xmstate_r_hdr(struct iscsi_conn *conn,
+-		     struct iscsi_tcp_cmd_task *tcp_ctask)
++iscsi_send_read_hdr(struct iscsi_conn *conn,
++		    struct iscsi_tcp_cmd_task *tcp_ctask)
+ {
+ 	int rc;
+ 
+@@ -1429,7 +1402,7 @@ handle_xmstate_r_hdr(struct iscsi_conn *conn,
+ }
+ 
+ static inline int
+-handle_xmstate_w_hdr(struct iscsi_conn *conn,
++iscsi_send_write_hdr(struct iscsi_conn *conn,
+ 		     struct iscsi_cmd_task *ctask)
+ {
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+@@ -1440,85 +1413,125 @@ handle_xmstate_w_hdr(struct iscsi_conn *conn,
+ 		iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
+ 				 (u8*)tcp_ctask->hdrext);
+ 	rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count);
+-	if (rc)
++	if (rc) {
+ 		tcp_ctask->xmstate |= XMSTATE_W_HDR;
+-	return rc;
++		return rc;
++	}
++
++	if (ctask->imm_count) {
++		tcp_ctask->xmstate |= XMSTATE_IMM_DATA;
++		iscsi_set_padding(tcp_ctask, ctask->imm_count);
++
++		if (ctask->conn->datadgst_en) {
++			iscsi_data_digest_init(ctask->conn->dd_data, tcp_ctask);
++			tcp_ctask->immdigest = 0;
++		}
++	}
++
++	if (ctask->unsol_count)
++		tcp_ctask->xmstate |= XMSTATE_UNS_HDR | XMSTATE_UNS_INIT;
++	return 0;
+ }
+ 
+-static inline int
+-handle_xmstate_data_digest(struct iscsi_conn *conn,
+-			   struct iscsi_cmd_task *ctask)
++static int
++iscsi_send_padding(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+-	int rc;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	int sent = 0, rc;
+ 
+-	tcp_ctask->xmstate &= ~XMSTATE_DATA_DIGEST;
+-	debug_tcp("resent data digest 0x%x\n", tcp_ctask->datadigest);
+-	rc = iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf,
+-				    &tcp_ctask->datadigest, 0);
++	if (tcp_ctask->xmstate & XMSTATE_W_PAD) {
++		iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad,
++				   tcp_ctask->pad_count);
++		if (conn->datadgst_en)
++			crypto_digest_update(tcp_conn->data_tx_tfm,
++					     &tcp_ctask->sendbuf.sg, 1);
++	} else if (!(tcp_ctask->xmstate & XMSTATE_W_RESEND_PAD))
++		return 0;
++
++	tcp_ctask->xmstate &= ~XMSTATE_W_PAD;
++	tcp_ctask->xmstate &= ~XMSTATE_W_RESEND_PAD;
++	debug_scsi("sending %d pad bytes for itt 0x%x\n",
++		   tcp_ctask->pad_count, ctask->itt);
++	rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count,
++			   &sent);
+ 	if (rc) {
+-		tcp_ctask->xmstate |= XMSTATE_DATA_DIGEST;
+-		debug_tcp("resent data digest 0x%x fail!\n",
+-			  tcp_ctask->datadigest);
++		debug_scsi("padding send failed %d\n", rc);
++		tcp_ctask->xmstate |= XMSTATE_W_RESEND_PAD;
+ 	}
+-
+ 	return rc;
+ }
+ 
+-static inline int
+-handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
++static int
++iscsi_send_digest(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
++			struct iscsi_buf *buf, uint32_t *digest)
+ {
+-	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+-	int rc;
++	struct iscsi_tcp_cmd_task *tcp_ctask;
++	struct iscsi_tcp_conn *tcp_conn;
++	int rc, sent = 0;
+ 
+-	BUG_ON(!ctask->imm_count);
+-	tcp_ctask->xmstate &= ~XMSTATE_IMM_DATA;
++	if (!conn->datadgst_en)
++		return 0;
+ 
+-	if (conn->datadgst_en) {
+-		iscsi_data_digest_init(tcp_conn, ctask);
+-		tcp_ctask->immdigest = 0;
+-	}
++	tcp_ctask = ctask->dd_data;
++	tcp_conn = conn->dd_data;
+ 
+-	for (;;) {
+-		rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf,
+-				   &ctask->imm_count, &tcp_ctask->sent);
+-		if (rc) {
+-			tcp_ctask->xmstate |= XMSTATE_IMM_DATA;
+-			if (conn->datadgst_en) {
+-				crypto_digest_final(tcp_conn->data_tx_tfm,
+-						(u8*)&tcp_ctask->immdigest);
+-				debug_tcp("tx imm sendpage fail 0x%x\n",
+-					  tcp_ctask->datadigest);
+-			}
+-			return rc;
+-		}
+-		if (conn->datadgst_en)
+-			crypto_digest_update(tcp_conn->data_tx_tfm,
+-					     &tcp_ctask->sendbuf.sg, 1);
++	if (!(tcp_ctask->xmstate & XMSTATE_W_RESEND_DATA_DIGEST)) {
++		crypto_digest_final(tcp_conn->data_tx_tfm, (u8*)digest);
++		iscsi_buf_init_iov(buf, (char*)digest, 4);
++	}
++	tcp_ctask->xmstate &= ~XMSTATE_W_RESEND_DATA_DIGEST;
+ 
+-		if (!ctask->imm_count)
+-			break;
+-		iscsi_buf_init_sg(&tcp_ctask->sendbuf,
+-				  &tcp_ctask->sg[tcp_ctask->sg_count++]);
++	rc = iscsi_sendpage(conn, buf, &tcp_ctask->digest_count, &sent);
++	if (!rc)
++		debug_scsi("sent digest 0x%x for itt 0x%x\n", *digest,
++			  ctask->itt);
++	else {
++		debug_scsi("sending digest 0x%x failed for itt 0x%x!\n",
++			  *digest, ctask->itt);
++		tcp_ctask->xmstate |= XMSTATE_W_RESEND_DATA_DIGEST;
+ 	}
++	return rc;
++}
+ 
+-	if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) {
+-		rc = iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf,
+-				            &tcp_ctask->immdigest, 1);
+-		if (rc) {
+-			debug_tcp("sending imm digest 0x%x fail!\n",
+-				  tcp_ctask->immdigest);
+-			return rc;
++static int
++iscsi_send_data(struct iscsi_cmd_task *ctask, struct iscsi_buf *sendbuf,
++		struct scatterlist **sg, int *sent, int *count,
++		struct iscsi_buf *digestbuf, uint32_t *digest)
++{
++	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++	struct iscsi_conn *conn = ctask->conn;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	int rc, buf_sent, offset;
++
++	while (*count) {
++		buf_sent = 0;
++		offset = sendbuf->sent;
++
++		rc = iscsi_sendpage(conn, sendbuf, count, &buf_sent);
++		*sent = *sent + buf_sent;
++		if (buf_sent && conn->datadgst_en)
++			partial_sg_digest_update(tcp_conn->data_tx_tfm,
++				&sendbuf->sg, sendbuf->sg.offset + offset,
++				buf_sent);
++		if (!iscsi_buf_left(sendbuf) && *sg != tcp_ctask->bad_sg) {
++			iscsi_buf_init_sg(sendbuf, *sg);
++			*sg = *sg + 1;
+ 		}
+-		debug_tcp("sending imm digest 0x%x\n", tcp_ctask->immdigest);
++
++		if (rc)
++			return rc;
+ 	}
+ 
+-	return 0;
++	rc = iscsi_send_padding(conn, ctask);
++	if (rc)
++		return rc;
++
++	return iscsi_send_digest(conn, ctask, digestbuf, digest);
+ }
+ 
+-static inline int
+-handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
++static int
++iscsi_send_unsol_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	struct iscsi_data_task *dtask;
+@@ -1526,14 +1539,21 @@ handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 
+ 	tcp_ctask->xmstate |= XMSTATE_UNS_DATA;
+ 	if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) {
+-		dtask = tcp_ctask->dtask = &tcp_ctask->unsol_dtask;
++		dtask = &tcp_ctask->unsol_dtask;
++
+ 		iscsi_prep_unsolicit_data_pdu(ctask, &dtask->hdr);
+ 		iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)&dtask->hdr,
+ 				   sizeof(struct iscsi_hdr));
+ 		if (conn->hdrdgst_en)
+ 			iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
+ 					(u8*)dtask->hdrext);
++		if (conn->datadgst_en) {
++			iscsi_data_digest_init(ctask->conn->dd_data, tcp_ctask);
++			dtask->digest = 0;
++		}
++
+ 		tcp_ctask->xmstate &= ~XMSTATE_UNS_INIT;
++		iscsi_set_padding(tcp_ctask, ctask->data_count);
+ 	}
+ 
+ 	rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->data_count);
+@@ -1548,247 +1568,128 @@ handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	return 0;
+ }
+ 
+-static inline int
+-handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
++static int
++iscsi_send_unsol_pdu(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+-	struct iscsi_data_task *dtask = tcp_ctask->dtask;
+-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	int rc;
+ 
+-	BUG_ON(!ctask->data_count);
+-	tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA;
+-
+-	if (conn->datadgst_en) {
+-		iscsi_data_digest_init(tcp_conn, ctask);
+-		dtask->digest = 0;
++	if (tcp_ctask->xmstate & XMSTATE_UNS_HDR) {
++		BUG_ON(!ctask->unsol_count);
++		tcp_ctask->xmstate &= ~XMSTATE_UNS_HDR;
++send_hdr:
++		rc = iscsi_send_unsol_hdr(conn, ctask);
++		if (rc)
++			return rc;
+ 	}
+ 
+-	for (;;) {
++	if (tcp_ctask->xmstate & XMSTATE_UNS_DATA) {
++		struct iscsi_data_task *dtask = &tcp_ctask->unsol_dtask;
+ 		int start = tcp_ctask->sent;
+ 
+-		rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf,
+-				   &ctask->data_count, &tcp_ctask->sent);
+-		if (rc) {
+-			ctask->unsol_count -= tcp_ctask->sent - start;
+-			tcp_ctask->xmstate |= XMSTATE_UNS_DATA;
+-			/* will continue with this ctask later.. */
+-			if (conn->datadgst_en) {
+-				crypto_digest_final(tcp_conn->data_tx_tfm,
+-						(u8 *)&dtask->digest);
+-				debug_tcp("tx uns data fail 0x%x\n",
+-					  dtask->digest);
+-			}
+-			return rc;
+-		}
+-
+-		BUG_ON(tcp_ctask->sent > ctask->total_length);
++		rc = iscsi_send_data(ctask, &tcp_ctask->sendbuf, &tcp_ctask->sg,
++				     &tcp_ctask->sent, &ctask->data_count,
++				     &dtask->digestbuf, &dtask->digest);
+ 		ctask->unsol_count -= tcp_ctask->sent - start;
+-
++		if (rc)
++			return rc;
++		tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA;
+ 		/*
+-		 * XXX:we may run here with un-initial sendbuf.
+-		 * so pass it
++		 * Done with the Data-Out. Next, check if we need
++		 * to send another unsolicited Data-Out.
+ 		 */
+-		if (conn->datadgst_en && tcp_ctask->sent - start > 0)
+-			crypto_digest_update(tcp_conn->data_tx_tfm,
+-					     &tcp_ctask->sendbuf.sg, 1);
+-
+-		if (!ctask->data_count)
+-			break;
+-		iscsi_buf_init_sg(&tcp_ctask->sendbuf,
+-				  &tcp_ctask->sg[tcp_ctask->sg_count++]);
+-	}
+-	BUG_ON(ctask->unsol_count < 0);
+-
+-	/*
+-	 * Done with the Data-Out. Next, check if we need
+-	 * to send another unsolicited Data-Out.
+-	 */
+-	if (ctask->unsol_count) {
+-		if (conn->datadgst_en) {
+-			rc = iscsi_digest_final_send(conn, ctask,
+-						    &dtask->digestbuf,
+-						    &dtask->digest, 1);
+-			if (rc) {
+-				debug_tcp("send uns digest 0x%x fail\n",
+-					  dtask->digest);
+-				return rc;
+-			}
+-			debug_tcp("sending uns digest 0x%x, more uns\n",
+-				  dtask->digest);
+-		}
+-		tcp_ctask->xmstate |= XMSTATE_UNS_INIT;
+-		return 1;
+-	}
+-
+-	if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) {
+-		rc = iscsi_digest_final_send(conn, ctask,
+-					    &dtask->digestbuf,
+-					    &dtask->digest, 1);
+-		if (rc) {
+-			debug_tcp("send last uns digest 0x%x fail\n",
+-				   dtask->digest);
+-			return rc;
++		if (ctask->unsol_count) {
++			debug_scsi("sending more uns\n");
++			tcp_ctask->xmstate |= XMSTATE_UNS_INIT;
++			goto send_hdr;
+ 		}
+-		debug_tcp("sending uns digest 0x%x\n",dtask->digest);
+ 	}
+-
+ 	return 0;
+ }
+ 
+-static inline int
+-handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
++static int iscsi_send_sol_pdu(struct iscsi_conn *conn,
++			      struct iscsi_cmd_task *ctask)
+ {
+-	struct iscsi_session *session = conn->session;
+-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+-	struct iscsi_r2t_info *r2t = tcp_ctask->r2t;
+-	struct iscsi_data_task *dtask = &r2t->dtask;
++	struct iscsi_session *session = conn->session;
++	struct iscsi_r2t_info *r2t;
++	struct iscsi_data_task *dtask;
+ 	int left, rc;
+ 
+-	tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA;
+-	tcp_ctask->dtask = dtask;
+-
+-	if (conn->datadgst_en) {
+-		iscsi_data_digest_init(tcp_conn, ctask);
+-		dtask->digest = 0;
+-	}
+-solicit_again:
+-	/*
+-	 * send Data-Out within this R2T sequence.
+-	 */
+-	if (!r2t->data_count)
+-		goto data_out_done;
+-
+-	rc = iscsi_sendpage(conn, &r2t->sendbuf, &r2t->data_count, &r2t->sent);
+-	if (rc) {
++	if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) {
++		tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
+ 		tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
+-		/* will continue with this ctask later.. */
+-		if (conn->datadgst_en) {
+-			crypto_digest_final(tcp_conn->data_tx_tfm,
+-					  (u8 *)&dtask->digest);
+-			debug_tcp("r2t data send fail 0x%x\n", dtask->digest);
+-		}
+-		return rc;
+-	}
++		if (!tcp_ctask->r2t)
++			__kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t,
++				    sizeof(void*));
++send_hdr:
++		r2t = tcp_ctask->r2t;
++		dtask = &r2t->dtask;
+ 
+-	BUG_ON(r2t->data_count < 0);
+-	if (conn->datadgst_en)
+-		crypto_digest_update(tcp_conn->data_tx_tfm, &r2t->sendbuf.sg,
+-				     1);
+-
+-	if (r2t->data_count) {
+-		BUG_ON(ctask->sc->use_sg == 0);
+-		if (!iscsi_buf_left(&r2t->sendbuf)) {
+-			BUG_ON(tcp_ctask->bad_sg == r2t->sg);
+-			iscsi_buf_init_sg(&r2t->sendbuf, r2t->sg);
+-			r2t->sg += 1;
+-		}
+-		goto solicit_again;
+-	}
++		if (conn->hdrdgst_en)
++			iscsi_hdr_digest(conn, &r2t->headbuf,
++					(u8*)dtask->hdrext);
+ 
+-data_out_done:
+-	/*
+-	 * Done with this Data-Out. Next, check if we have
+-	 * to send another Data-Out for this R2T.
+-	 */
+-	BUG_ON(r2t->data_length - r2t->sent < 0);
+-	left = r2t->data_length - r2t->sent;
+-	if (left) {
+ 		if (conn->datadgst_en) {
+-			rc = iscsi_digest_final_send(conn, ctask,
+-						    &dtask->digestbuf,
+-						    &dtask->digest, 1);
+-			if (rc) {
+-				debug_tcp("send r2t data digest 0x%x"
+-					  "fail\n", dtask->digest);
+-				return rc;
+-			}
+-			debug_tcp("r2t data send digest 0x%x\n",
+-				  dtask->digest);
++			iscsi_data_digest_init(conn->dd_data, tcp_ctask);
++			dtask->digest = 0;
+ 		}
+-		iscsi_solicit_data_cont(conn, ctask, r2t, left);
+-		tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
+-		tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
+-		return 1;
+-	}
+ 
+-	/*
+-	 * Done with this R2T. Check if there are more
+-	 * outstanding R2Ts ready to be processed.
+-	 */
+-	if (conn->datadgst_en) {
+-		rc = iscsi_digest_final_send(conn, ctask, &dtask->digestbuf,
+-					    &dtask->digest, 1);
++		rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count);
+ 		if (rc) {
+-			debug_tcp("send last r2t data digest 0x%x"
+-				  "fail\n", dtask->digest);
++			tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA;
++			tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
+ 			return rc;
+ 		}
+-		debug_tcp("r2t done dout digest 0x%x\n", dtask->digest);
+-	}
+ 
+-	tcp_ctask->r2t = NULL;
+-	spin_lock_bh(&session->lock);
+-	__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*));
+-	spin_unlock_bh(&session->lock);
+-	if (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) {
+-		tcp_ctask->r2t = r2t;
+-		tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
+-		tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
+-		return 1;
++		iscsi_set_padding(tcp_ctask, r2t->data_count);
++		debug_scsi("sol dout [dsn %d itt 0x%x dlen %d sent %d]\n",
++			r2t->solicit_datasn - 1, ctask->itt, r2t->data_count,
++			r2t->sent);
+ 	}
+ 
+-	return 0;
+-}
++	if (tcp_ctask->xmstate & XMSTATE_SOL_DATA) {
++		r2t = tcp_ctask->r2t;
++		dtask = &r2t->dtask;
+ 
+-static inline int
+-handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+-{
+-	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+-	struct iscsi_data_task *dtask = tcp_ctask->dtask;
+-	int sent = 0, rc;
++		rc = iscsi_send_data(ctask, &r2t->sendbuf, &r2t->sg,
++				     &r2t->sent, &r2t->data_count,
++				     &dtask->digestbuf, &dtask->digest);
++		if (rc)
++			return rc;
++		tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA;
+ 
+-	tcp_ctask->xmstate &= ~XMSTATE_W_PAD;
+-	iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad,
+-			    tcp_ctask->pad_count);
+-	rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count,
+-			   &sent);
+-	if (rc) {
+-		tcp_ctask->xmstate |= XMSTATE_W_PAD;
+-		return rc;
+-	}
++		/*
++		 * Done with this Data-Out. Next, check if we have
++		 * to send another Data-Out for this R2T.
++		 */
++		BUG_ON(r2t->data_length - r2t->sent < 0);
++		left = r2t->data_length - r2t->sent;
++		if (left) {
++			iscsi_solicit_data_cont(conn, ctask, r2t, left);
++			tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
++			tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
++			goto send_hdr;
++		}
+ 
+-	if (conn->datadgst_en) {
+-		crypto_digest_update(tcp_conn->data_tx_tfm,
+-				     &tcp_ctask->sendbuf.sg, 1);
+-		/* imm data? */
+-		if (!dtask) {
+-			rc = iscsi_digest_final_send(conn, ctask,
+-						    &tcp_ctask->immbuf,
+-						    &tcp_ctask->immdigest, 1);
+-			if (rc) {
+-				debug_tcp("send padding digest 0x%x"
+-					  "fail!\n", tcp_ctask->immdigest);
+-				return rc;
+-			}
+-			debug_tcp("done with padding, digest 0x%x\n",
+-				  tcp_ctask->datadigest);
+-		} else {
+-			rc = iscsi_digest_final_send(conn, ctask,
+-						    &dtask->digestbuf,
+-						    &dtask->digest, 1);
+-			if (rc) {
+-				debug_tcp("send padding digest 0x%x"
+-				          "fail\n", dtask->digest);
+-				return rc;
+-			}
+-			debug_tcp("done with padding, digest 0x%x\n",
+-				  dtask->digest);
++		/*
++		 * Done with this R2T. Check if there are more
++		 * outstanding R2Ts ready to be processed.
++		 */
++		spin_lock_bh(&session->lock);
++		tcp_ctask->r2t = NULL;
++		__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
++			    sizeof(void*));
++		if (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t,
++				sizeof(void*))) {
++			tcp_ctask->r2t = r2t;
++			tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
++			tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
++			spin_unlock_bh(&session->lock);
++			goto send_hdr;
+ 		}
++		spin_unlock_bh(&session->lock);
+ 	}
+-
+ 	return 0;
+ }
+ 
+@@ -1808,85 +1709,30 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 		return rc;
+ 
+ 	if (tcp_ctask->xmstate & XMSTATE_R_HDR)
+-		return handle_xmstate_r_hdr(conn, tcp_ctask);
++		return iscsi_send_read_hdr(conn, tcp_ctask);
+ 
+ 	if (tcp_ctask->xmstate & XMSTATE_W_HDR) {
+-		rc = handle_xmstate_w_hdr(conn, ctask);
+-		if (rc)
+-			return rc;
+-	}
+-
+-	/* XXX: for data digest xmit recover */
+-	if (tcp_ctask->xmstate & XMSTATE_DATA_DIGEST) {
+-		rc = handle_xmstate_data_digest(conn, ctask);
++		rc = iscsi_send_write_hdr(conn, ctask);
+ 		if (rc)
+ 			return rc;
+ 	}
+ 
+ 	if (tcp_ctask->xmstate & XMSTATE_IMM_DATA) {
+-		rc = handle_xmstate_imm_data(conn, ctask);
++		rc = iscsi_send_data(ctask, &tcp_ctask->sendbuf, &tcp_ctask->sg,
++				     &tcp_ctask->sent, &ctask->imm_count,
++				     &tcp_ctask->immbuf, &tcp_ctask->immdigest);
+ 		if (rc)
+ 			return rc;
++		tcp_ctask->xmstate &= ~XMSTATE_IMM_DATA;
+ 	}
+ 
+-	if (tcp_ctask->xmstate & XMSTATE_UNS_HDR) {
+-		BUG_ON(!ctask->unsol_count);
+-		tcp_ctask->xmstate &= ~XMSTATE_UNS_HDR;
+-unsolicit_head_again:
+-		rc = handle_xmstate_uns_hdr(conn, ctask);
+-		if (rc)
+-			return rc;
+-	}
+-
+-	if (tcp_ctask->xmstate & XMSTATE_UNS_DATA) {
+-		rc = handle_xmstate_uns_data(conn, ctask);
+-		if (rc == 1)
+-			goto unsolicit_head_again;
+-		else if (rc)
+-			return rc;
+-		goto done;
+-	}
+-
+-	if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) {
+-		struct iscsi_r2t_info *r2t;
+-
+-		tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
+-		tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
+-		if (!tcp_ctask->r2t)
+-			__kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t,
+-				    sizeof(void*));
+-solicit_head_again:
+-		r2t = tcp_ctask->r2t;
+-		if (conn->hdrdgst_en)
+-			iscsi_hdr_digest(conn, &r2t->headbuf,
+-					(u8*)r2t->dtask.hdrext);
+-		rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count);
+-		if (rc) {
+-			tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA;
+-			tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
+-			return rc;
+-		}
+-
+-		debug_scsi("sol dout [dsn %d itt 0x%x dlen %d sent %d]\n",
+-			r2t->solicit_datasn - 1, ctask->itt, r2t->data_count,
+-			r2t->sent);
+-	}
+-
+-	if (tcp_ctask->xmstate & XMSTATE_SOL_DATA) {
+-		rc = handle_xmstate_sol_data(conn, ctask);
+-		if (rc == 1)
+-			goto solicit_head_again;
+-		if (rc)
+-			return rc;
+-	}
++	rc = iscsi_send_unsol_pdu(conn, ctask);
++	if (rc)
++		return rc;
+ 
+-done:
+-	/*
+-	 * Last thing to check is whether we need to send write
+-	 * padding. Note that we check for xmstate equality, not just the bit.
+-	 */
+-	if (tcp_ctask->xmstate == XMSTATE_W_PAD)
+-		rc = handle_xmstate_w_pad(conn, ctask);
++	rc = iscsi_send_sol_pdu(conn, ctask);
++	if (rc)
++		return rc;
+ 
+ 	return rc;
+ }
+diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
+index aace8f70dfd7..7e40e94d9fdc 100644
+--- a/drivers/scsi/iscsi_tcp.h
++++ b/drivers/scsi/iscsi_tcp.h
+@@ -31,23 +31,21 @@
+ #define IN_PROGRESS_DDIGEST_RECV	0x3
+ 
+ /* xmit state machine */
+-#define	XMSTATE_IDLE			0x0
+-#define	XMSTATE_R_HDR			0x1
+-#define	XMSTATE_W_HDR			0x2
+-#define	XMSTATE_IMM_HDR			0x4
+-#define	XMSTATE_IMM_DATA		0x8
+-#define	XMSTATE_UNS_INIT		0x10
+-#define	XMSTATE_UNS_HDR			0x20
+-#define	XMSTATE_UNS_DATA		0x40
+-#define	XMSTATE_SOL_HDR			0x80
+-#define	XMSTATE_SOL_DATA		0x100
+-#define	XMSTATE_W_PAD			0x200
+-#define XMSTATE_DATA_DIGEST		0x400
+-
+-#define ISCSI_CONN_RCVBUF_MIN		262144
+-#define ISCSI_CONN_SNDBUF_MIN		262144
++#define XMSTATE_IDLE			0x0
++#define XMSTATE_R_HDR			0x1
++#define XMSTATE_W_HDR			0x2
++#define XMSTATE_IMM_HDR			0x4
++#define XMSTATE_IMM_DATA		0x8
++#define XMSTATE_UNS_INIT		0x10
++#define XMSTATE_UNS_HDR			0x20
++#define XMSTATE_UNS_DATA		0x40
++#define XMSTATE_SOL_HDR			0x80
++#define XMSTATE_SOL_DATA		0x100
++#define XMSTATE_W_PAD			0x200
++#define XMSTATE_W_RESEND_PAD		0x400
++#define XMSTATE_W_RESEND_DATA_DIGEST	0x800
++
+ #define ISCSI_PAD_LEN			4
+-#define ISCSI_R2T_MAX			16
+ #define ISCSI_SG_TABLESIZE		SG_ALL
+ #define ISCSI_TCP_MAX_CMD_LEN		16
+ 
+@@ -162,13 +160,10 @@ struct iscsi_tcp_cmd_task {
+ 	struct iscsi_queue	r2tpool;
+ 	struct kfifo		*r2tqueue;
+ 	struct iscsi_r2t_info	**r2ts;
+-	uint32_t		datadigest;		/* for recover digest */
+ 	int			digest_count;
+ 	uint32_t		immdigest;		/* for imm data */
+ 	struct iscsi_buf	immbuf;			/* for imm data digest */
+-	struct iscsi_data_task	*dtask;		/* data task in progress*/
+ 	struct iscsi_data_task	unsol_dtask;	/* unsol data task */
+-	int			digest_offset;	/* for partial buff digest */
+ };
+ 
+ #endif /* ISCSI_H */
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 9584cbc082fe..fb65311c81dd 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -325,6 +325,30 @@ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 	wake_up(&conn->ehwait);
+ }
+ 
++static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
++			       char *data, int datalen)
++{
++	struct iscsi_reject *reject = (struct iscsi_reject *)hdr;
++	struct iscsi_hdr rejected_pdu;
++	uint32_t itt;
++
++	conn->exp_statsn = be32_to_cpu(reject->statsn) + 1;
++
++	if (reject->reason == ISCSI_REASON_DATA_DIGEST_ERROR) {
++		if (ntoh24(reject->dlength) > datalen)
++			return ISCSI_ERR_PROTO;
++
++		if (ntoh24(reject->dlength) >= sizeof(struct iscsi_hdr)) {
++			memcpy(&rejected_pdu, data, sizeof(struct iscsi_hdr));
++			itt = rejected_pdu.itt & ISCSI_ITT_MASK;
++			printk(KERN_ERR "itt 0x%x had pdu (op 0x%x) rejected "
++				"due to DataDigest error.\n", itt,
++				rejected_pdu.opcode);
++		}
++	}
++	return 0;
++}
++
+ /**
+  * __iscsi_complete_pdu - complete pdu
+  * @conn: iscsi conn
+@@ -436,6 +460,11 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			break;
+ 		}
+ 	} else if (itt == ISCSI_RESERVED_TAG) {
++		rc = iscsi_check_assign_cmdsn(session,
++					     (struct iscsi_nopin*)hdr);
++		if (rc)
++			goto done;
++
+ 		switch(opcode) {
+ 		case ISCSI_OP_NOOP_IN:
+ 			if (datalen) {
+@@ -443,11 +472,6 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 				break;
+ 			}
+ 
+-			rc = iscsi_check_assign_cmdsn(session,
+-						 (struct iscsi_nopin*)hdr);
+-			if (rc)
+-				break;
+-
+ 			if (hdr->ttt == ISCSI_RESERVED_TAG)
+ 				break;
+ 
+@@ -455,7 +479,8 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 				rc = ISCSI_ERR_CONN_FAILED;
+ 			break;
+ 		case ISCSI_OP_REJECT:
+-			/* we need sth like iscsi_reject_rsp()*/
++			rc = iscsi_handle_reject(conn, hdr, data, datalen);
++			break;
+ 		case ISCSI_OP_ASYNC_EVENT:
+ 			conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
+ 			/* we need sth like iscsi_async_event_rsp() */

commit 98a9416af08385f8497e9c1595113a81aefa5d49
+Author: Mike Christie 
+Date:   Thu Aug 31 18:09:26 2006 -0400
+
+    [SCSI] attempt to complete r2t with data len greater than max burst
+    
+    A couple targets like string bean and MDS, send r2ts with
+    a data len greater than the max burst we agreed to. We
+    were being strict in our enforcing of the iscsi rfc in that
+    code path, but there is no driver limitation that prevents
+    us from fullfilling the request. To allow those targets
+    to work we will ignore the max_burst length and send as
+    much data as the target asks for assuming it has consciously
+    decided to override its max burst length.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index a97a3a4e99eb..d6927f1a6b65 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -358,8 +358,11 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	int r2tsn = be32_to_cpu(rhdr->r2tsn);
+ 	int rc;
+ 
+-	if (tcp_conn->in.datalen)
++	if (tcp_conn->in.datalen) {
++		printk(KERN_ERR "iscsi_tcp: invalid R2t with datalen %d\n",
++		       tcp_conn->in.datalen);
+ 		return ISCSI_ERR_DATALEN;
++	}
+ 
+ 	if (tcp_ctask->exp_r2tsn && tcp_ctask->exp_r2tsn != r2tsn)
+ 		return ISCSI_ERR_R2TSN;
+@@ -385,15 +388,23 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 
+ 	r2t->exp_statsn = rhdr->statsn;
+ 	r2t->data_length = be32_to_cpu(rhdr->data_length);
+-	if (r2t->data_length == 0 ||
+-	    r2t->data_length > session->max_burst) {
++	if (r2t->data_length == 0) {
++		printk(KERN_ERR "iscsi_tcp: invalid R2T with zero data len\n");
+ 		spin_unlock(&session->lock);
+ 		return ISCSI_ERR_DATALEN;
+ 	}
+ 
++	if (r2t->data_length > session->max_burst)
++		debug_scsi("invalid R2T with data len %u and max burst %u."
++			   "Attempting to execute request.\n",
++			    r2t->data_length, session->max_burst);
++
+ 	r2t->data_offset = be32_to_cpu(rhdr->data_offset);
+ 	if (r2t->data_offset + r2t->data_length > ctask->total_length) {
+ 		spin_unlock(&session->lock);
++		printk(KERN_ERR "iscsi_tcp: invalid R2T with data len %u at "
++		       "offset %u and total length %d\n", r2t->data_length,
++		       r2t->data_offset, ctask->total_length);
+ 		return ISCSI_ERR_DATALEN;
+ 	}
+ 

commit 60ecebf5a10e42f5e2d6e07eb9e24bdee8500b81
+Author: Mike Christie 
+Date:   Thu Aug 31 18:09:25 2006 -0400
+
+    [SCSI] add refcouting around ctask usage in main IO patch
+    
+    It is possible that a ctask could be completing and getting
+    cleaned up at the same time, we are finishing up the last
+    data transfer. This could then result in the data transfer
+    code using stale or invalid values. This patch adds a refcount
+    to the ctask. When the count goes to zero then we know the
+    transmit thread and recv thread or softirq are not touching
+    it and we can safely release it.
+    
+    The eh should not need to grab a reference because it only cleans
+    up a task if it has both the xmit mutex and recv lock (or recv
+    side suspended).
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index a7c6e70f4ef8..9584cbc082fe 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -179,16 +179,15 @@ EXPORT_SYMBOL_GPL(iscsi_prep_scsi_cmd_pdu);
+ 
+ /**
+  * iscsi_complete_command - return command back to scsi-ml
+- * @session: iscsi session
+  * @ctask: iscsi cmd task
+  *
+  * Must be called with session lock.
+  * This function returns the scsi command to scsi-ml and returns
+  * the cmd task to the pool of available cmd tasks.
+  */
+-static void iscsi_complete_command(struct iscsi_session *session,
+-				   struct iscsi_cmd_task *ctask)
++static void iscsi_complete_command(struct iscsi_cmd_task *ctask)
+ {
++	struct iscsi_session *session = ctask->conn->session;
+ 	struct scsi_cmnd *sc = ctask->sc;
+ 
+ 	ctask->state = ISCSI_TASK_COMPLETED;
+@@ -198,6 +197,35 @@ static void iscsi_complete_command(struct iscsi_session *session,
+ 	sc->scsi_done(sc);
+ }
+ 
++static void __iscsi_get_ctask(struct iscsi_cmd_task *ctask)
++{
++	atomic_inc(&ctask->refcount);
++}
++
++static void iscsi_get_ctask(struct iscsi_cmd_task *ctask)
++{
++	spin_lock_bh(&ctask->conn->session->lock);
++	__iscsi_get_ctask(ctask);
++	spin_unlock_bh(&ctask->conn->session->lock);
++}
++
++static void __iscsi_put_ctask(struct iscsi_cmd_task *ctask)
++{
++	struct iscsi_conn *conn = ctask->conn;
++
++	if (atomic_dec_and_test(&ctask->refcount)) {
++		conn->session->tt->cleanup_cmd_task(conn, ctask);
++		iscsi_complete_command(ctask);
++	}
++}
++
++static void iscsi_put_ctask(struct iscsi_cmd_task *ctask)
++{
++	spin_lock_bh(&ctask->conn->session->lock);
++	__iscsi_put_ctask(ctask);
++	spin_unlock_bh(&ctask->conn->session->lock);
++}
++
+ /**
+  * iscsi_cmd_rsp - SCSI Command Response processing
+  * @conn: iscsi connection
+@@ -274,7 +302,7 @@ static int iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		   (long)sc, sc->result, ctask->itt);
+ 	conn->scsirsp_pdus_cnt++;
+ 
+-	iscsi_complete_command(conn->session, ctask);
++	__iscsi_put_ctask(ctask);
+ 	return rc;
+ }
+ 
+@@ -338,7 +366,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
+ 			if (hdr->flags & ISCSI_FLAG_DATA_STATUS) {
+ 				conn->scsirsp_pdus_cnt++;
+-				iscsi_complete_command(session, ctask);
++				__iscsi_put_ctask(ctask);
+ 			}
+ 			break;
+ 		case ISCSI_OP_R2T:
+@@ -563,7 +591,9 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 	BUG_ON(conn->ctask && conn->mtask);
+ 
+ 	if (conn->ctask) {
++		iscsi_get_ctask(conn->ctask);
+ 		rc = tt->xmit_cmd_task(conn, conn->ctask);
++		iscsi_put_ctask(conn->ctask);
+ 		if (rc)
+ 			goto again;
+ 		/* done with this in-progress ctask */
+@@ -604,12 +634,19 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 					 struct iscsi_cmd_task, running);
+ 		conn->ctask->state = ISCSI_TASK_RUNNING;
+ 		list_move_tail(conn->xmitqueue.next, &conn->run_list);
++		__iscsi_get_ctask(conn->ctask);
+ 		spin_unlock_bh(&conn->session->lock);
+ 
+ 		rc = tt->xmit_cmd_task(conn, conn->ctask);
+ 		if (rc)
+ 			goto again;
++
+ 		spin_lock_bh(&conn->session->lock);
++		__iscsi_put_ctask(conn->ctask);
++		if (rc) {
++			spin_unlock_bh(&conn->session->lock);
++			goto again;
++		}
+ 	}
+ 	spin_unlock_bh(&conn->session->lock);
+ 	/* done with this ctask */
+@@ -659,6 +696,7 @@ enum {
+ 	FAILURE_SESSION_FAILED,
+ 	FAILURE_SESSION_FREED,
+ 	FAILURE_WINDOW_CLOSED,
++	FAILURE_OOM,
+ 	FAILURE_SESSION_TERMINATE,
+ 	FAILURE_SESSION_IN_RECOVERY,
+ 	FAILURE_SESSION_RECOVERY_TIMEOUT,
+@@ -717,10 +755,15 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 
+ 	conn = session->leadconn;
+ 
+-	__kfifo_get(session->cmdpool.queue, (void*)&ctask, sizeof(void*));
++	if (!__kfifo_get(session->cmdpool.queue, (void*)&ctask,
++			 sizeof(void*))) {
++		reason = FAILURE_OOM;
++		goto reject;
++	}
+ 	sc->SCp.phase = session->age;
+ 	sc->SCp.ptr = (char *)ctask;
+ 
++	atomic_set(&ctask->refcount, 1);
+ 	ctask->state = ISCSI_TASK_PENDING;
+ 	ctask->mtask = NULL;
+ 	ctask->conn = conn;
+@@ -1057,13 +1100,11 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 	sc = ctask->sc;
+ 	if (!sc)
+ 		return;
+-
+-	conn->session->tt->cleanup_cmd_task(conn, ctask);
+ 	iscsi_ctask_mtask_cleanup(ctask);
+ 
+ 	sc->result = err;
+ 	sc->resid = sc->request_bufflen;
+-	iscsi_complete_command(conn->session, ctask);
++	__iscsi_put_ctask(ctask);
+ }
+ 
+ int iscsi_eh_abort(struct scsi_cmnd *sc)
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 4900650bd081..401192e56e50 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -112,6 +112,7 @@ struct iscsi_cmd_task {
+ 
+ 	/* state set/tested under session->lock */
+ 	int			state;
++	atomic_t		refcount;
+ 	struct list_head	running;	/* running cmd list */
+ 	void			*dd_data;	/* driver/transport data */
+ };

commit ffd0436ed2e5a741c8d30062b489b989acf0a526
+Author: Mike Christie 
+Date:   Thu Aug 31 18:09:24 2006 -0400
+
+    [SCSI] libiscsi, iscsi_tcp, iscsi_iser: check that burst lengths are valid.
+    
+    iSCSI RFC states that the first burst length must be smaller than the
+    max burst length. We currently assume targets will be good, but that may
+    not be the case, so this patch adds a check.
+    
+    This patch also moves the unsol data out offset to the lib so the LLDs
+    do not have to track it.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 1437d7ee3b19..101e407eaa43 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -141,18 +141,11 @@ iscsi_iser_cmd_init(struct iscsi_cmd_task *ctask)
+ 
+ 	if (sc->sc_data_direction == DMA_TO_DEVICE) {
+ 		BUG_ON(ctask->total_length == 0);
+-		/* bytes to be sent via RDMA operations */
+-		iser_ctask->rdma_data_count = ctask->total_length -
+-					 ctask->imm_count -
+-					 ctask->unsol_count;
+ 
+-		debug_scsi("cmd [itt %x total %d imm %d unsol_data %d "
+-			   "rdma_data %d]\n",
++		debug_scsi("cmd [itt %x total %d imm %d unsol_data %d\n",
+ 			   ctask->itt, ctask->total_length, ctask->imm_count,
+-			   ctask->unsol_count, iser_ctask->rdma_data_count);
+-	} else
+-		/* bytes to be sent via RDMA operations */
+-		iser_ctask->rdma_data_count = ctask->total_length;
++			   ctask->unsol_count);
++	}
+ 
+ 	iser_ctask_rdma_init(iser_ctask);
+ }
+@@ -196,13 +189,10 @@ iscsi_iser_ctask_xmit_unsol_data(struct iscsi_conn *conn,
+ {
+ 	struct iscsi_data  hdr;
+ 	int error = 0;
+-	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
+ 
+ 	/* Send data-out PDUs while there's still unsolicited data to send */
+ 	while (ctask->unsol_count > 0) {
+-		iscsi_prep_unsolicit_data_pdu(ctask, &hdr,
+-					      iser_ctask->rdma_data_count);
+-
++		iscsi_prep_unsolicit_data_pdu(ctask, &hdr);
+ 		debug_scsi("Sending data-out: itt 0x%x, data count %d\n",
+ 			   hdr.itt, ctask->data_count);
+ 
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
+index 3350ba690cfe..7c3d0c96d889 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
+@@ -257,7 +257,6 @@ struct iscsi_iser_conn {
+ struct iscsi_iser_cmd_task {
+ 	struct iser_desc             desc;
+ 	struct iscsi_iser_conn	     *iser_conn;
+-	int			     rdma_data_count;/* RDMA bytes           */
+ 	enum iser_task_status 	     status;
+ 	int                          command_sent;  /* set if command  sent  */
+ 	int                          dir[ISER_DIRS_NUM];      /* set if dir use*/
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 058f094f945a..a97a3a4e99eb 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -1264,19 +1264,6 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 			    r2t->data_count);
+ }
+ 
+-static void
+-iscsi_unsolicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+-{
+-	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+-	struct iscsi_data_task *dtask;
+-
+-	dtask = tcp_ctask->dtask = &tcp_ctask->unsol_dtask;
+-	iscsi_prep_unsolicit_data_pdu(ctask, &dtask->hdr,
+-				      tcp_ctask->r2t_data_count);
+-	iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)&dtask->hdr,
+-			   sizeof(struct iscsi_hdr));
+-}
+-
+ /**
+  * iscsi_tcp_cmd_init - Initialize iSCSI SCSI_READ or SCSI_WRITE commands
+  * @conn: iscsi connection
+@@ -1326,14 +1313,11 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask)
+ 		if (ctask->unsol_count)
+ 			tcp_ctask->xmstate |= XMSTATE_UNS_HDR |
+ 						XMSTATE_UNS_INIT;
+-		tcp_ctask->r2t_data_count = ctask->total_length -
+-				    ctask->imm_count -
+-				    ctask->unsol_count;
+ 
+-		debug_scsi("cmd [itt 0x%x total %d imm %d imm_data %d "
+-			   "r2t_data %d]\n",
++		debug_scsi("cmd [itt 0x%x total %d imm_data %d "
++			   "unsol count %d, unsol offset %d]\n",
+ 			   ctask->itt, ctask->total_length, ctask->imm_count,
+-			   ctask->unsol_count, tcp_ctask->r2t_data_count);
++			   ctask->unsol_count, ctask->unsol_offset);
+ 	} else
+ 		tcp_ctask->xmstate = XMSTATE_R_HDR;
+ 
+@@ -1531,8 +1515,10 @@ handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 
+ 	tcp_ctask->xmstate |= XMSTATE_UNS_DATA;
+ 	if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) {
+-		iscsi_unsolicit_data_init(conn, ctask);
+-		dtask = tcp_ctask->dtask;
++		dtask = tcp_ctask->dtask = &tcp_ctask->unsol_dtask;
++		iscsi_prep_unsolicit_data_pdu(ctask, &dtask->hdr);
++		iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)&dtask->hdr,
++				   sizeof(struct iscsi_hdr));
+ 		if (conn->hdrdgst_en)
+ 			iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
+ 					(u8*)dtask->hdrext);
+@@ -1720,7 +1706,6 @@ handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	 * Done with this R2T. Check if there are more
+ 	 * outstanding R2Ts ready to be processed.
+ 	 */
+-	BUG_ON(tcp_ctask->r2t_data_count - r2t->data_length < 0);
+ 	if (conn->datadgst_en) {
+ 		rc = iscsi_digest_final_send(conn, ctask, &dtask->digestbuf,
+ 					    &dtask->digest, 1);
+@@ -1732,7 +1717,6 @@ handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 		debug_tcp("r2t done dout digest 0x%x\n", dtask->digest);
+ 	}
+ 
+-	tcp_ctask->r2t_data_count -= r2t->data_length;
+ 	tcp_ctask->r2t = NULL;
+ 	spin_lock_bh(&session->lock);
+ 	__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*));
+diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
+index 6a4ee704e46e..aace8f70dfd7 100644
+--- a/drivers/scsi/iscsi_tcp.h
++++ b/drivers/scsi/iscsi_tcp.h
+@@ -157,7 +157,6 @@ struct iscsi_tcp_cmd_task {
+ 	struct scatterlist	*bad_sg;		/* assert statement */
+ 	int			sg_count;		/* SG's to process  */
+ 	uint32_t		exp_r2tsn;
+-	int			r2t_data_count;		/* R2T Data-Out bytes */
+ 	int			data_offset;
+ 	struct iscsi_r2t_info	*r2t;			/* in progress R2T    */
+ 	struct iscsi_queue	r2tpool;
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 5884cd26d53a..a7c6e70f4ef8 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -68,8 +68,7 @@ iscsi_check_assign_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
+ EXPORT_SYMBOL_GPL(iscsi_check_assign_cmdsn);
+ 
+ void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *ctask,
+-				   struct iscsi_data *hdr,
+-				   int transport_data_cnt)
++				   struct iscsi_data *hdr)
+ {
+ 	struct iscsi_conn *conn = ctask->conn;
+ 
+@@ -82,14 +81,12 @@ void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *ctask,
+ 
+ 	hdr->itt = ctask->hdr->itt;
+ 	hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
+-
+-	hdr->offset = cpu_to_be32(ctask->total_length -
+-				  transport_data_cnt -
+-				  ctask->unsol_count);
++	hdr->offset = cpu_to_be32(ctask->unsol_offset);
+ 
+ 	if (ctask->unsol_count > conn->max_xmit_dlength) {
+ 		hton24(hdr->dlength, conn->max_xmit_dlength);
+ 		ctask->data_count = conn->max_xmit_dlength;
++		ctask->unsol_offset += ctask->data_count;
+ 		hdr->flags = 0;
+ 	} else {
+ 		hton24(hdr->dlength, ctask->unsol_count);
+@@ -125,6 +122,7 @@ static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+         memcpy(hdr->cdb, sc->cmnd, sc->cmd_len);
+         memset(&hdr->cdb[sc->cmd_len], 0, MAX_COMMAND_SIZE - sc->cmd_len);
+ 
++	ctask->data_count = 0;
+ 	if (sc->sc_data_direction == DMA_TO_DEVICE) {
+ 		hdr->flags |= ISCSI_FLAG_CMD_WRITE;
+ 		/*
+@@ -143,6 +141,7 @@ static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ 		 */
+ 		ctask->imm_count = 0;
+ 		ctask->unsol_count = 0;
++		ctask->unsol_offset = 0;
+ 		ctask->unsol_datasn = 0;
+ 
+ 		if (session->imm_data_en) {
+@@ -156,9 +155,12 @@ static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ 		} else
+ 			zero_data(ctask->hdr->dlength);
+ 
+-		if (!session->initial_r2t_en)
++		if (!session->initial_r2t_en) {
+ 			ctask->unsol_count = min(session->first_burst,
+ 				ctask->total_length) - ctask->imm_count;
++			ctask->unsol_offset = ctask->imm_count;
++		}
++
+ 		if (!ctask->unsol_count)
+ 			/* No unsolicit Data-Out's */
+ 			ctask->hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+@@ -1520,11 +1522,18 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	struct iscsi_session *session = conn->session;
+ 
+-	if (session == NULL) {
++	if (!session) {
+ 		printk(KERN_ERR "iscsi: can't start unbound connection\n");
+ 		return -EPERM;
+ 	}
+ 
++	if (session->first_burst > session->max_burst) {
++		printk("iscsi: invalid burst lengths: "
++		       "first_burst %d max_burst %d\n",
++		       session->first_burst, session->max_burst);
++		return -EINVAL;
++	}
++
+ 	spin_lock_bh(&session->lock);
+ 	conn->c_stage = ISCSI_CONN_STARTED;
+ 	session->state = ISCSI_STATE_LOGGED_IN;
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 41904f611d12..4900650bd081 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -102,6 +102,8 @@ struct iscsi_cmd_task {
+ 	uint32_t		unsol_datasn;
+ 	int			imm_count;	/* imm-data (bytes)   */
+ 	int			unsol_count;	/* unsolicited (bytes)*/
++	/* offset in unsolicited stream (bytes); */
++	int			unsol_offset;
+ 	int			data_count;	/* remaining Data-Out */
+ 	struct scsi_cmnd	*sc;		/* associated SCSI cmd*/
+ 	int			total_length;
+@@ -290,8 +292,7 @@ extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ extern int iscsi_check_assign_cmdsn(struct iscsi_session *,
+ 				    struct iscsi_nopin *);
+ extern void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *,
+-					struct iscsi_data *hdr,
+-					int transport_data_cnt);
++					struct iscsi_data *hdr);
+ extern int iscsi_conn_send_pdu(struct iscsi_cls_conn *, struct iscsi_hdr *,
+ 				char *, uint32_t);
+ extern int iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *,

commit 0db99e3359234be181590463184b9959059a9ea9
+Author: Mike Christie 
+Date:   Sat Aug 26 03:00:22 2006 -0400
+
+    [SCSI] fix scsi_send_eh_cmnd regression
+    
+    The callers of scsi_send_eh_cmnd are setting the cmnd buffer,
+    and then scsi_send_eh_cmnd is copying that updated buffer to
+    the old_cmnd variable. Then after the command runs, we end up
+    copying that old_cmnd var which has the new cmnd to the scsi
+    command buffer. When this command gets recent, all types of fun
+    things happen like getting TUR or START_STOP commands with
+    data and scatterlists.
+    
+    This patch made against scsi-rc-fixes, has the callers of
+    scsi_send_eh_cmnd pass in the command so scsi_send_eh_cmnd
+    can do the right thing. This should go into 2.6.18 since this
+    fixes a regression added when we removed some of the scsi_cmnd
+    fields and replaced them with local variables.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
+index 6a5b731bd5ba..a8ed5a22009d 100644
+--- a/drivers/scsi/scsi_error.c
++++ b/drivers/scsi/scsi_error.c
+@@ -460,7 +460,8 @@ static void scsi_eh_done(struct scsi_cmnd *scmd)
+  * Return value:
+  *    SUCCESS or FAILED or NEEDS_RETRY
+  **/
+-static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout, int copy_sense)
++static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
++			     int cmnd_size, int timeout, int copy_sense)
+ {
+ 	struct scsi_device *sdev = scmd->device;
+ 	struct Scsi_Host *shost = sdev->host;
+@@ -490,6 +491,9 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout, int copy_sense
+ 	old_cmd_len = scmd->cmd_len;
+ 	old_use_sg = scmd->use_sg;
+ 
++	memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
++	memcpy(scmd->cmnd, cmnd, cmnd_size);
++
+ 	if (copy_sense) {
+ 		int gfp_mask = GFP_ATOMIC;
+ 
+@@ -610,8 +614,7 @@ static int scsi_request_sense(struct scsi_cmnd *scmd)
+ 	static unsigned char generic_sense[6] =
+ 		{REQUEST_SENSE, 0, 0, 0, 252, 0};
+ 
+-	memcpy(scmd->cmnd, generic_sense, sizeof(generic_sense));
+-	return scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT, 1);
++	return scsi_send_eh_cmnd(scmd, generic_sense, 6, SENSE_TIMEOUT, 1);
+ }
+ 
+ /**
+@@ -736,10 +739,7 @@ static int scsi_eh_tur(struct scsi_cmnd *scmd)
+ 	int retry_cnt = 1, rtn;
+ 
+ retry_tur:
+-	memcpy(scmd->cmnd, tur_command, sizeof(tur_command));
+-
+-
+-	rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT, 0);
++	rtn = scsi_send_eh_cmnd(scmd, tur_command, 6, SENSE_TIMEOUT, 0);
+ 
+ 	SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd %p rtn %x\n",
+ 		__FUNCTION__, scmd, rtn));
+@@ -839,8 +839,8 @@ static int scsi_eh_try_stu(struct scsi_cmnd *scmd)
+ 	if (scmd->device->allow_restart) {
+ 		int rtn;
+ 
+-		memcpy(scmd->cmnd, stu_command, sizeof(stu_command));
+-		rtn = scsi_send_eh_cmnd(scmd, START_UNIT_TIMEOUT, 0);
++		rtn = scsi_send_eh_cmnd(scmd, stu_command, 6,
++					START_UNIT_TIMEOUT, 0);
+ 		if (rtn == SUCCESS)
+ 			return 0;
+ 	}

commit f4246b33c774bb4330eb6286beed6d3c9f4373c4
+Author: Mike Christie 
+Date:   Mon Jul 24 15:47:54 2006 -0500
+
+    [SCSI] iscsi bugfixes: update and move version number
+    
+    The version info is useful for iscsi tcp, iser and qla4xxx so move to
+    transport class.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 33534f686434..058f094f945a 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -43,13 +43,10 @@
+ 
+ #include "iscsi_tcp.h"
+ 
+-#define ISCSI_TCP_VERSION "1.0-595"
+-
+ MODULE_AUTHOR("Dmitry Yusupov , "
+ 	      "Alex Aizman ");
+ MODULE_DESCRIPTION("iSCSI/TCP data-path");
+ MODULE_LICENSE("GPL");
+-MODULE_VERSION(ISCSI_TCP_VERSION);
+ /* #define DEBUG_TCP */
+ #define DEBUG_ASSERT
+ 
+@@ -2317,8 +2314,7 @@ static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session)
+ }
+ 
+ static struct scsi_host_template iscsi_sht = {
+-	.name			= "iSCSI Initiator over TCP/IP, v"
+-				  ISCSI_TCP_VERSION,
++	.name			= "iSCSI Initiator over TCP/IP",
+ 	.queuecommand           = iscsi_queuecommand,
+ 	.change_queue_depth	= iscsi_change_queue_depth,
+ 	.can_queue		= ISCSI_XMIT_CMDS_MAX - 1,
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 30a47c133091..2ecd14188574 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -34,6 +34,7 @@
+ #define ISCSI_SESSION_ATTRS 11
+ #define ISCSI_CONN_ATTRS 11
+ #define ISCSI_HOST_ATTRS 0
++#define ISCSI_TRANSPORT_VERSION "1.1-646"
+ 
+ struct iscsi_internal {
+ 	int daemon_pid;
+@@ -1613,6 +1614,9 @@ static __init int iscsi_transport_init(void)
+ {
+ 	int err;
+ 
++	printk(KERN_INFO "Loading iSCSI transport class v%s.",
++		ISCSI_TRANSPORT_VERSION);
++
+ 	err = class_register(&iscsi_transport_class);
+ 	if (err)
+ 		return err;
+@@ -1678,3 +1682,4 @@ MODULE_AUTHOR("Mike Christie , "
+ 	      "Alex Aizman ");
+ MODULE_DESCRIPTION("iSCSI Transport Interface");
+ MODULE_LICENSE("GPL");
++MODULE_VERSION(ISCSI_TRANSPORT_VERSION);

commit f3ff0c3627df90aa28be98803b10289bb348e4e6
+Author: Mike Christie 
+Date:   Mon Jul 24 15:47:50 2006 -0500
+
+    [SCSI] iscsi bugfixes: fix mem leaks in libiscsi
+    
+    We were leaking some strings. This patch just frees them.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index c628c63c51a8..5884cd26d53a 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1357,6 +1357,8 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+ 	iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
+ 	iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
+ 
++	kfree(session->targetname);
++
+ 	iscsi_destroy_session(cls_session);
+ 	scsi_host_put(shost);
+ 	module_put(owner);
+@@ -1491,6 +1493,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
+ 
+ 	spin_lock_bh(&session->lock);
+ 	kfree(conn->data);
++	kfree(conn->persistent_address);
+ 	__kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask,
+ 		    sizeof(void*));
+ 	list_del(&conn->item);

commit 40527afea1a3b18ee5754e17d6f807176e03f1f2
+Author: Mike Christie 
+Date:   Mon Jul 24 15:47:45 2006 -0500
+
+    [SCSI] iscsi bugfixes: pass errors from complete_pdu to caller
+    
+    Must pass ISCSI_ERR values from the recv path and propogate them
+    upwards.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index aa20adc79f02..33534f686434 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -885,7 +885,7 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 			}
+ 			tcp_conn->in_progress = IN_PROGRESS_DATA_RECV;
+ 		} else if (rc) {
+-			iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
++			iscsi_conn_failure(conn, rc);
+ 			return 0;
+ 		}
+ 	}
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 03b3dee49009..c628c63c51a8 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -372,7 +372,8 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			 * login related PDU's exp_statsn is handled in
+ 			 * userspace
+ 			 */
+-			rc = iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen);
++			if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen))
++				rc = ISCSI_ERR_CONN_FAILED;
+ 			list_del(&mtask->running);
+ 			if (conn->login_mtask != mtask)
+ 				__kfifo_put(session->mgmtpool.queue,
+@@ -393,7 +394,8 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			}
+ 			conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
+ 
+-			rc = iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen);
++			if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen))
++				rc = ISCSI_ERR_CONN_FAILED;
+ 			list_del(&mtask->running);
+ 			if (conn->login_mtask != mtask)
+ 				__kfifo_put(session->mgmtpool.queue,
+@@ -406,14 +408,21 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	} else if (itt == ISCSI_RESERVED_TAG) {
+ 		switch(opcode) {
+ 		case ISCSI_OP_NOOP_IN:
+-			if (!datalen) {
+-				rc = iscsi_check_assign_cmdsn(session,
+-						 (struct iscsi_nopin*)hdr);
+-				if (!rc && hdr->ttt != ISCSI_RESERVED_TAG)
+-					rc = iscsi_recv_pdu(conn->cls_conn,
+-							    hdr, NULL, 0);
+-			} else
++			if (datalen) {
+ 				rc = ISCSI_ERR_PROTO;
++				break;
++			}
++
++			rc = iscsi_check_assign_cmdsn(session,
++						 (struct iscsi_nopin*)hdr);
++			if (rc)
++				break;
++
++			if (hdr->ttt == ISCSI_RESERVED_TAG)
++				break;
++
++			if (iscsi_recv_pdu(conn->cls_conn, hdr, NULL, 0))
++				rc = ISCSI_ERR_CONN_FAILED;
+ 			break;
+ 		case ISCSI_OP_REJECT:
+ 			/* we need sth like iscsi_reject_rsp()*/

commit c8dc1e523b0f1e6dd71cdabd8c7d7587c6dc27f9
+Author: Mike Christie 
+Date:   Mon Jul 24 15:47:39 2006 -0500
+
+    [SCSI] iscsi bugfixes: reduce memory allocations
+    
+    We currently try to allocate a max_recv_data_segment_length
+    which can be very large (default is 64K), and common uses
+    are up to 1MB. It is very very difficult to allocte this
+    much contiguous memory and it turns out we never even use it.
+    We really only need a couple of pages, so this patch has us
+    allocates just what we know what we need today.
+    
+    Later if vendors start adding vendor specific data and
+    we need to handle large buffers we can do this, but for
+    the last 4 years we have not seen anyone do this or request
+    it.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index b6c68be6b866..aa20adc79f02 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -511,13 +511,28 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *conn)
+ 		break;
+ 	case ISCSI_OP_LOGIN_RSP:
+ 	case ISCSI_OP_TEXT_RSP:
+-	case ISCSI_OP_LOGOUT_RSP:
+-	case ISCSI_OP_NOOP_IN:
+ 	case ISCSI_OP_REJECT:
+ 	case ISCSI_OP_ASYNC_EVENT:
++		/*
++		 * It is possible that we could get a PDU with a buffer larger
++		 * than 8K, but there are no targets that currently do this.
++		 * For now we fail until we find a vendor that needs it
++		 */
++		if (DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH <
++		    tcp_conn->in.datalen) {
++			printk(KERN_ERR "iscsi_tcp: received buffer of len %u "
++			      "but conn buffer is only %u (opcode %0x)\n",
++			      tcp_conn->in.datalen,
++			      DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, opcode);
++			rc = ISCSI_ERR_PROTO;
++			break;
++		}
++
+ 		if (tcp_conn->in.datalen)
+ 			goto copy_hdr;
+ 	/* fall through */
++	case ISCSI_OP_LOGOUT_RSP:
++	case ISCSI_OP_NOOP_IN:
+ 	case ISCSI_OP_SCSI_TMFUNC_RSP:
+ 		rc = iscsi_complete_pdu(conn, hdr, NULL, 0);
+ 		break;
+@@ -625,9 +640,9 @@ iscsi_ctask_copy(struct iscsi_tcp_conn *tcp_conn, struct iscsi_cmd_task *ctask,
+  *	byte counters.
+  **/
+ static inline int
+-iscsi_tcp_copy(struct iscsi_tcp_conn *tcp_conn)
++iscsi_tcp_copy(struct iscsi_conn *conn)
+ {
+-	void *buf = tcp_conn->data;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	int buf_size = tcp_conn->in.datalen;
+ 	int buf_left = buf_size - tcp_conn->data_copied;
+ 	int size = min(tcp_conn->in.copy, buf_left);
+@@ -638,7 +653,7 @@ iscsi_tcp_copy(struct iscsi_tcp_conn *tcp_conn)
+ 	BUG_ON(size <= 0);
+ 
+ 	rc = skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset,
+-			   (char*)buf + tcp_conn->data_copied, size);
++			   (char*)conn->data + tcp_conn->data_copied, size);
+ 	BUG_ON(rc);
+ 
+ 	tcp_conn->in.offset += size;
+@@ -785,22 +800,21 @@ iscsi_data_recv(struct iscsi_conn *conn)
+ 		spin_unlock(&conn->session->lock);
+ 	case ISCSI_OP_TEXT_RSP:
+ 	case ISCSI_OP_LOGIN_RSP:
+-	case ISCSI_OP_NOOP_IN:
+ 	case ISCSI_OP_ASYNC_EVENT:
+ 	case ISCSI_OP_REJECT:
+ 		/*
+ 		 * Collect data segment to the connection's data
+ 		 * placeholder
+ 		 */
+-		if (iscsi_tcp_copy(tcp_conn)) {
++		if (iscsi_tcp_copy(conn)) {
+ 			rc = -EAGAIN;
+ 			goto exit;
+ 		}
+ 
+-		rc = iscsi_complete_pdu(conn, tcp_conn->in.hdr, tcp_conn->data,
++		rc = iscsi_complete_pdu(conn, tcp_conn->in.hdr, conn->data,
+ 					tcp_conn->in.datalen);
+ 		if (!rc && conn->datadgst_en && opcode != ISCSI_OP_LOGIN_RSP)
+-			iscsi_recv_digest_update(tcp_conn, tcp_conn->data,
++			iscsi_recv_digest_update(tcp_conn, conn->data,
+ 			  			tcp_conn->in.datalen);
+ 		break;
+ 	default:
+@@ -1911,21 +1925,9 @@ iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ 	tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
+ 	/* initial operational parameters */
+ 	tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
+-	tcp_conn->data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
+-
+-	/* allocate initial PDU receive place holder */
+-	if (tcp_conn->data_size <= PAGE_SIZE)
+-		tcp_conn->data = kmalloc(tcp_conn->data_size, GFP_KERNEL);
+-	else
+-		tcp_conn->data = (void*)__get_free_pages(GFP_KERNEL,
+-					get_order(tcp_conn->data_size));
+-	if (!tcp_conn->data)
+-		goto max_recv_dlenght_alloc_fail;
+ 
+ 	return cls_conn;
+ 
+-max_recv_dlenght_alloc_fail:
+-	kfree(tcp_conn);
+ tcp_conn_alloc_fail:
+ 	iscsi_conn_teardown(cls_conn);
+ 	return NULL;
+@@ -1973,12 +1975,6 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn)
+ 			crypto_free_tfm(tcp_conn->data_rx_tfm);
+ 	}
+ 
+-	/* free conn->data, size = MaxRecvDataSegmentLength */
+-	if (tcp_conn->data_size <= PAGE_SIZE)
+-		kfree(tcp_conn->data);
+-	else
+-		free_pages((unsigned long)tcp_conn->data,
+-			   get_order(tcp_conn->data_size));
+ 	kfree(tcp_conn);
+ }
+ 
+@@ -2131,39 +2127,6 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
+ 	int value;
+ 
+ 	switch(param) {
+-	case ISCSI_PARAM_MAX_RECV_DLENGTH: {
+-		char *saveptr = tcp_conn->data;
+-		gfp_t flags = GFP_KERNEL;
+-
+-		sscanf(buf, "%d", &value);
+-		if (tcp_conn->data_size >= value) {
+-			iscsi_set_param(cls_conn, param, buf, buflen);
+-			break;
+-		}
+-
+-		spin_lock_bh(&session->lock);
+-		if (conn->stop_stage == STOP_CONN_RECOVER)
+-			flags = GFP_ATOMIC;
+-		spin_unlock_bh(&session->lock);
+-
+-		if (value <= PAGE_SIZE)
+-			tcp_conn->data = kmalloc(value, flags);
+-		else
+-			tcp_conn->data = (void*)__get_free_pages(flags,
+-							     get_order(value));
+-		if (tcp_conn->data == NULL) {
+-			tcp_conn->data = saveptr;
+-			return -ENOMEM;
+-		}
+-		if (tcp_conn->data_size <= PAGE_SIZE)
+-			kfree(saveptr);
+-		else
+-			free_pages((unsigned long)saveptr,
+-				   get_order(tcp_conn->data_size));
+-		iscsi_set_param(cls_conn, param, buf, buflen);
+-		tcp_conn->data_size = value;
+-		break;
+-		}
+ 	case ISCSI_PARAM_HDRDGST_EN:
+ 		iscsi_set_param(cls_conn, param, buf, buflen);
+ 		tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
+diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
+index 808302832e68..6a4ee704e46e 100644
+--- a/drivers/scsi/iscsi_tcp.h
++++ b/drivers/scsi/iscsi_tcp.h
+@@ -78,8 +78,6 @@ struct iscsi_tcp_conn {
+ 	char			hdrext[4*sizeof(__u16) +
+ 				    sizeof(__u32)];
+ 	int			data_copied;
+-	char			*data;		/* data placeholder */
+-	int			data_size;	/* actual recv_dlength */
+ 	int			stop_stage;	/* conn_stop() flag: *
+ 						 * stop to recover,  *
+ 						 * stop to terminate */
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index c989bc6180b3..03b3dee49009 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -360,6 +360,10 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 
+ 		switch(opcode) {
+ 		case ISCSI_OP_LOGOUT_RSP:
++			if (datalen) {
++				rc = ISCSI_ERR_PROTO;
++				break;
++			}
+ 			conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
+ 			/* fall through */
+ 		case ISCSI_OP_LOGIN_RSP:
+@@ -383,7 +387,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			iscsi_tmf_rsp(conn, hdr);
+ 			break;
+ 		case ISCSI_OP_NOOP_IN:
+-			if (hdr->ttt != ISCSI_RESERVED_TAG) {
++			if (hdr->ttt != ISCSI_RESERVED_TAG || datalen) {
+ 				rc = ISCSI_ERR_PROTO;
+ 				break;
+ 			}
+@@ -1405,7 +1409,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ 	data = kmalloc(DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, GFP_KERNEL);
+ 	if (!data)
+ 		goto login_mtask_data_alloc_fail;
+-	conn->login_mtask->data = data;
++	conn->login_mtask->data = conn->data = data;
+ 
+ 	init_timer(&conn->tmabort_timer);
+ 	mutex_init(&conn->xmitmutex);
+@@ -1477,7 +1481,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
+ 	}
+ 
+ 	spin_lock_bh(&session->lock);
+-	kfree(conn->login_mtask->data);
++	kfree(conn->data);
+ 	__kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask,
+ 		    sizeof(void*));
+ 	list_del(&conn->item);
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 3f69f7e58f89..41904f611d12 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -135,6 +135,14 @@ struct iscsi_conn {
+ 	int			id;		/* CID */
+ 	struct list_head	item;		/* maintains list of conns */
+ 	int			c_stage;	/* connection state */
++	/*
++	 * Preallocated buffer for pdus that have data but do not
++	 * originate from scsi-ml. We never have two pdus using the
++	 * buffer at the same time. It is only allocated to
++	 * the default max recv size because the pdus we support
++	 * should always fit in this buffer
++	 */
++	char			*data;
+ 	struct iscsi_mgmt_task	*login_mtask;	/* mtask used for login/text */
+ 	struct iscsi_mgmt_task	*mtask;		/* xmit mtask in progress */
+ 	struct iscsi_cmd_task	*ctask;		/* xmit ctask in progress */

commit 9aaa2b4621280b6de1ecfb6dd7cd5cbe59fd1264
+Author: Mike Christie 
+Date:   Mon Jul 24 15:47:34 2006 -0500
+
+    [SCSI] iscsi bugfixes: dont use GFP_KERNEL for sending errors
+    
+    iscsi_tcp can send error events from soft irq context so we
+    cannot use GFP_KERNEL.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 7b9e8fa1a4e0..30a47c133091 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -634,13 +634,13 @@ mempool_zone_get_skb(struct mempool_zone *zone)
+ }
+ 
+ static int
+-iscsi_broadcast_skb(struct mempool_zone *zone, struct sk_buff *skb)
++iscsi_broadcast_skb(struct mempool_zone *zone, struct sk_buff *skb, gfp_t gfp)
+ {
+ 	unsigned long flags;
+ 	int rc;
+ 
+ 	skb_get(skb);
+-	rc = netlink_broadcast(nls, skb, 0, 1, GFP_KERNEL);
++	rc = netlink_broadcast(nls, skb, 0, 1, gfp);
+ 	if (rc < 0) {
+ 		mempool_free(skb, zone->pool);
+ 		printk(KERN_ERR "iscsi: can not broadcast skb (%d)\n", rc);
+@@ -749,7 +749,7 @@ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
+ 	ev->r.connerror.cid = conn->cid;
+ 	ev->r.connerror.sid = iscsi_conn_get_sid(conn);
+ 
+-	iscsi_broadcast_skb(conn->z_error, skb);
++	iscsi_broadcast_skb(conn->z_error, skb, GFP_ATOMIC);
+ 
+ 	dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n",
+ 		   error);
+@@ -895,7 +895,7 @@ int iscsi_if_destroy_session_done(struct iscsi_cls_conn *conn)
+ 	 * this will occur if the daemon is not up, so we just warn
+ 	 * the user and when the daemon is restarted it will handle it
+ 	 */
+-	rc = iscsi_broadcast_skb(conn->z_pdu, skb);
++	rc = iscsi_broadcast_skb(conn->z_pdu, skb, GFP_KERNEL);
+ 	if (rc < 0)
+ 		dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
+ 			  "session destruction event. Check iscsi daemon\n");
+@@ -958,7 +958,7 @@ int iscsi_if_create_session_done(struct iscsi_cls_conn *conn)
+ 	 * this will occur if the daemon is not up, so we just warn
+ 	 * the user and when the daemon is restarted it will handle it
+ 	 */
+-	rc = iscsi_broadcast_skb(conn->z_pdu, skb);
++	rc = iscsi_broadcast_skb(conn->z_pdu, skb, GFP_KERNEL);
+ 	if (rc < 0)
+ 		dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
+ 			  "session creation event. Check iscsi daemon\n");

commit 63f75cc8a7e6ce453e38a7b90cdcae83d63f1ea7
+Author: Mike Christie 
+Date:   Mon Jul 24 15:47:29 2006 -0500
+
+    [SCSI] iscsi bugfixes: fix oops when removing session
+    
+    We are touching the cls_session after we have freed
+    it. This causes a oops.
+    
+    Signed-off-by: Or Gerlitz  
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 36f520b9260e..c989bc6180b3 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1337,6 +1337,7 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+ {
+ 	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+ 	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
++	struct module *owner = cls_session->transport->owner;
+ 
+ 	scsi_remove_host(shost);
+ 
+@@ -1345,7 +1346,7 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+ 
+ 	iscsi_destroy_session(cls_session);
+ 	scsi_host_put(shost);
+-	module_put(cls_session->transport->owner);
++	module_put(owner);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_session_teardown);
+ 

commit 1c83469d36a9dd30dbf1fb9fc5ca3be3a0e64ff4
+Author: Mike Christie 
+Date:   Mon Jul 24 15:47:26 2006 -0500
+
+    [SCSI] iscsi bugfixes: fix oops when iser is flushing io
+    
+    When we enter recovery and flush the running commands
+    we cannot freee the connection before flushing the commands.
+    Some commands may have a reference to the connection
+    that needs to be released before. iscsi_stop was forcing
+    the term and suspend too early and was causing a oops
+    in iser, so this patch removes those callbacks all together
+    and allows the LLD to handle that detail.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 34b0da5cfa0a..1437d7ee3b19 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -378,21 +378,6 @@ iscsi_iser_conn_start(struct iscsi_cls_conn *cls_conn)
+ 	return iser_conn_set_full_featured_mode(conn);
+ }
+ 
+-static void
+-iscsi_iser_conn_terminate(struct iscsi_conn *conn)
+-{
+-	struct iscsi_iser_conn *iser_conn = conn->dd_data;
+-	struct iser_conn *ib_conn = iser_conn->ib_conn;
+-
+-	BUG_ON(!ib_conn);
+-	/* starts conn teardown process, waits until all previously   *
+-	 * posted buffers get flushed, deallocates all conn resources */
+-	iser_conn_terminate(ib_conn);
+-	iser_conn->ib_conn = NULL;
+-	conn->recv_lock = NULL;
+-}
+-
+-
+ static struct iscsi_transport iscsi_iser_transport;
+ 
+ static struct iscsi_cls_session *
+@@ -555,13 +540,13 @@ iscsi_iser_ep_poll(__u64 ep_handle, int timeout_ms)
+ static void
+ iscsi_iser_ep_disconnect(__u64 ep_handle)
+ {
+-	struct iser_conn *ib_conn = iscsi_iser_ib_conn_lookup(ep_handle);
++	struct iser_conn *ib_conn;
+ 
++	ib_conn = iscsi_iser_ib_conn_lookup(ep_handle);
+ 	if (!ib_conn)
+ 		return;
+ 
+ 	iser_err("ib conn %p state %d\n",ib_conn, ib_conn->state);
+-
+ 	iser_conn_terminate(ib_conn);
+ }
+ 
+@@ -614,9 +599,6 @@ static struct iscsi_transport iscsi_iser_transport = {
+ 	.get_session_param	= iscsi_session_get_param,
+ 	.start_conn             = iscsi_iser_conn_start,
+ 	.stop_conn              = iscsi_conn_stop,
+-	/* these are called as part of conn recovery */
+-	.suspend_conn_recv	= NULL, /* FIXME is/how this relvant to iser? */
+-	.terminate_conn		= iscsi_iser_conn_terminate,
+ 	/* IO */
+ 	.send_pdu		= iscsi_conn_send_pdu,
+ 	.get_stats		= iscsi_iser_conn_get_stats,
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 7d784596a1ea..b6c68be6b866 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -1040,9 +1040,8 @@ iscsi_conn_set_callbacks(struct iscsi_conn *conn)
+ }
+ 
+ static void
+-iscsi_conn_restore_callbacks(struct iscsi_conn *conn)
++iscsi_conn_restore_callbacks(struct iscsi_tcp_conn *tcp_conn)
+ {
+-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	struct sock *sk = tcp_conn->sock->sk;
+ 
+ 	/* restore socket callbacks, see also: iscsi_conn_set_callbacks() */
+@@ -1932,6 +1931,23 @@ iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ 	return NULL;
+ }
+ 
++static void
++iscsi_tcp_release_conn(struct iscsi_conn *conn)
++{
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++
++	if (!tcp_conn->sock)
++		return;
++
++	sock_hold(tcp_conn->sock->sk);
++	iscsi_conn_restore_callbacks(tcp_conn);
++	sock_put(tcp_conn->sock->sk);
++
++	sock_release(tcp_conn->sock);
++	tcp_conn->sock = NULL;
++	conn->recv_lock = NULL;
++}
++
+ static void
+ iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn)
+ {
+@@ -1942,6 +1958,7 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn)
+ 	if (conn->hdrdgst_en || conn->datadgst_en)
+ 		digest = 1;
+ 
++	iscsi_tcp_release_conn(conn);
+ 	iscsi_conn_teardown(cls_conn);
+ 
+ 	/* now free tcp_conn */
+@@ -1965,6 +1982,15 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn)
+ 	kfree(tcp_conn);
+ }
+ 
++static void
++iscsi_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
++{
++	struct iscsi_conn *conn = cls_conn->dd_data;
++
++	iscsi_conn_stop(cls_conn, flag);
++	iscsi_tcp_release_conn(conn);
++}
++
+ static int
+ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
+ 		    struct iscsi_cls_conn *cls_conn, uint64_t transport_eph,
+@@ -2013,38 +2039,6 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
+ 	return 0;
+ }
+ 
+-static void
+-iscsi_tcp_suspend_conn_rx(struct iscsi_conn *conn)
+-{
+-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+-	struct sock *sk;
+-
+-	if (!tcp_conn->sock)
+-		return;
+-
+-	sk = tcp_conn->sock->sk;
+-	write_lock_bh(&sk->sk_callback_lock);
+-	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
+-	write_unlock_bh(&sk->sk_callback_lock);
+-}
+-
+-static void
+-iscsi_tcp_terminate_conn(struct iscsi_conn *conn)
+-{
+-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+-
+-	if (!tcp_conn->sock)
+-		return;
+-
+-	sock_hold(tcp_conn->sock->sk);
+-	iscsi_conn_restore_callbacks(conn);
+-	sock_put(tcp_conn->sock->sk);
+-
+-	sock_release(tcp_conn->sock);
+-	tcp_conn->sock = NULL;
+-	conn->recv_lock = NULL;
+-}
+-
+ /* called with host lock */
+ static void
+ iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask,
+@@ -2413,10 +2407,7 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 	.get_conn_param		= iscsi_tcp_conn_get_param,
+ 	.get_session_param	= iscsi_session_get_param,
+ 	.start_conn		= iscsi_conn_start,
+-	.stop_conn		= iscsi_conn_stop,
+-	/* these are called as part of conn recovery */
+-	.suspend_conn_recv	= iscsi_tcp_suspend_conn_rx,
+-	.terminate_conn		= iscsi_tcp_terminate_conn,
++	.stop_conn		= iscsi_tcp_conn_stop,
+ 	/* IO */
+ 	.send_pdu		= iscsi_conn_send_pdu,
+ 	.get_stats		= iscsi_conn_get_stats,
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 4e2ca8f7d9a1..36f520b9260e 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1440,12 +1440,6 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
+ 
+ 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+ 	mutex_lock(&conn->xmitmutex);
+-	if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE) {
+-		if (session->tt->suspend_conn_recv)
+-			session->tt->suspend_conn_recv(conn);
+-
+-		session->tt->terminate_conn(conn);
+-	}
+ 
+ 	spin_lock_bh(&session->lock);
+ 	conn->c_stage = ISCSI_CONN_CLEANUP_WAIT;
+@@ -1622,8 +1616,9 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+ 	spin_unlock_bh(&session->lock);
+ 
+-	if (session->tt->suspend_conn_recv)
+-		session->tt->suspend_conn_recv(conn);
++	write_lock_bh(conn->recv_lock);
++	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
++	write_unlock_bh(conn->recv_lock);
+ 
+ 	mutex_lock(&conn->xmitmutex);
+ 	/*
+@@ -1642,7 +1637,6 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ 		}
+ 	}
+ 
+-	session->tt->terminate_conn(conn);
+ 	/*
+ 	 * flush queues.
+ 	 */
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 5a3df1d7085f..39e833260bd0 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -57,8 +57,6 @@ struct sockaddr;
+  * @stop_conn:		suspend/recover/terminate connection
+  * @send_pdu:		send iSCSI PDU, Login, Logout, NOP-Out, Reject, Text.
+  * @session_recovery_timedout: notify LLD a block during recovery timed out
+- * @suspend_conn_recv:	susepend the recv side of the connection
+- * @termincate_conn:	destroy socket connection. Called with mutex lock.
+  * @init_cmd_task:	Initialize a iscsi_cmd_task and any internal structs.
+  *			Called from queuecommand with session lock held.
+  * @init_mgmt_task:	Initialize a iscsi_mgmt_task and any internal structs.
+@@ -112,8 +110,6 @@ struct iscsi_transport {
+ 			 char *data, uint32_t data_size);
+ 	void (*get_stats) (struct iscsi_cls_conn *conn,
+ 			   struct iscsi_stats *stats);
+-	void (*suspend_conn_recv) (struct iscsi_conn *conn);
+-	void (*terminate_conn) (struct iscsi_conn *conn);
+ 	void (*init_cmd_task) (struct iscsi_cmd_task *ctask);
+ 	void (*init_mgmt_task) (struct iscsi_conn *conn,
+ 				struct iscsi_mgmt_task *mtask,

commit 7ea8b82847293c2311cf08fc3ed31ab0e452a27e
+Author: Mike Christie 
+Date:   Mon Jul 24 15:47:22 2006 -0500
+
+    [SCSI] iscsi bugfixes: fix abort handling
+    
+    Abort handler fixes.
+    
+    If a connection is dropped and reconnected while an abort is
+    running then we should assume the recovery code will clean up
+    the abort. Not doing so causes a oops.
+    
+    And if a command completes then we get the status for the abort, we do not
+    need to call into the LLD to cleanup the resources. Doing this causes
+    and oops in iser because it ends up freeing some resources twice.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 1a8cd20f484f..4e2ca8f7d9a1 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -276,6 +276,25 @@ static int iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	return rc;
+ }
+ 
++static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
++{
++	struct iscsi_tm_rsp *tmf = (struct iscsi_tm_rsp *)hdr;
++
++	conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
++	conn->tmfrsp_pdus_cnt++;
++
++	if (conn->tmabort_state != TMABORT_INITIAL)
++		return;
++
++	if (tmf->response == ISCSI_TMF_RSP_COMPLETE)
++		conn->tmabort_state = TMABORT_SUCCESS;
++	else if (tmf->response == ISCSI_TMF_RSP_NO_TASK)
++		conn->tmabort_state = TMABORT_NOT_FOUND;
++	else
++		conn->tmabort_state = TMABORT_FAILED;
++	wake_up(&conn->ehwait);
++}
++
+ /**
+  * __iscsi_complete_pdu - complete pdu
+  * @conn: iscsi conn
+@@ -361,16 +380,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 				break;
+ 			}
+ 
+-			conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
+-			conn->tmfrsp_pdus_cnt++;
+-			if (conn->tmabort_state == TMABORT_INITIAL) {
+-				conn->tmabort_state =
+-					((struct iscsi_tm_rsp *)hdr)->
+-					response == ISCSI_TMF_RSP_COMPLETE ?
+-						TMABORT_SUCCESS:TMABORT_FAILED;
+-				/* unblock eh_abort() */
+-				wake_up(&conn->ehwait);
+-			}
++			iscsi_tmf_rsp(conn, hdr);
+ 			break;
+ 		case ISCSI_OP_NOOP_IN:
+ 			if (hdr->ttt != ISCSI_RESERVED_TAG) {
+@@ -1029,12 +1039,13 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ {
+ 	struct scsi_cmnd *sc;
+ 
+-	conn->session->tt->cleanup_cmd_task(conn, ctask);
+-	iscsi_ctask_mtask_cleanup(ctask);
+-
+ 	sc = ctask->sc;
+ 	if (!sc)
+ 		return;
++
++	conn->session->tt->cleanup_cmd_task(conn, ctask);
++	iscsi_ctask_mtask_cleanup(ctask);
++
+ 	sc->result = err;
+ 	sc->resid = sc->request_bufflen;
+ 	iscsi_complete_command(conn->session, ctask);
+@@ -1062,8 +1073,11 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 		goto failed;
+ 
+ 	/* ctask completed before time out */
+-	if (!ctask->sc)
+-		goto success;
++	if (!ctask->sc) {
++		spin_unlock_bh(&session->lock);
++		debug_scsi("sc completed while abort in progress\n");
++		goto success_rel_mutex;
++	}
+ 
+ 	/* what should we do here ? */
+ 	if (conn->ctask == ctask) {
+@@ -1073,7 +1087,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 	}
+ 
+ 	if (ctask->state == ISCSI_TASK_PENDING)
+-		goto success;
++		goto success_cleanup;
+ 
+ 	conn->tmabort_state = TMABORT_INITIAL;
+ 
+@@ -1081,25 +1095,31 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 	rc = iscsi_exec_abort_task(sc, ctask);
+ 	spin_lock_bh(&session->lock);
+ 
+-	iscsi_ctask_mtask_cleanup(ctask);
+ 	if (rc || sc->SCp.phase != session->age ||
+ 	    session->state != ISCSI_STATE_LOGGED_IN)
+ 		goto failed;
++	iscsi_ctask_mtask_cleanup(ctask);
+ 
+-	/* ctask completed before tmf abort response */
+-	if (!ctask->sc) {
+-		debug_scsi("sc completed while abort in progress\n");
+-		goto success;
+-	}
+-
+-	if (conn->tmabort_state != TMABORT_SUCCESS) {
++	switch (conn->tmabort_state) {
++	case TMABORT_SUCCESS:
++		goto success_cleanup;
++	case TMABORT_NOT_FOUND:
++		if (!ctask->sc) {
++			/* ctask completed before tmf abort response */
++			spin_unlock_bh(&session->lock);
++			debug_scsi("sc completed while abort in progress\n");
++			goto success_rel_mutex;
++		}
++		/* fall through */
++	default:
++		/* timedout or failed */
+ 		spin_unlock_bh(&session->lock);
+ 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ 		spin_lock_bh(&session->lock);
+ 		goto failed;
+ 	}
+ 
+-success:
++success_cleanup:
+ 	debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
+ 	spin_unlock_bh(&session->lock);
+ 
+@@ -1113,6 +1133,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 	spin_unlock(&session->lock);
+ 	write_unlock_bh(conn->recv_lock);
+ 
++success_rel_mutex:
+ 	mutex_unlock(&conn->xmitmutex);
+ 	return SUCCESS;
+ 
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index e71d6e96eca6..3f69f7e58f89 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -60,6 +60,7 @@ struct iscsi_nopin;
+ #define TMABORT_SUCCESS			0x1
+ #define TMABORT_FAILED			0x2
+ #define TMABORT_TIMEDOUT		0x3
++#define TMABORT_NOT_FOUND		0x4
+ 
+ /* Connection suspend "bit" */
+ #define ISCSI_SUSPEND_BIT		1

commit 275fd7d129fdd16d1dc0ec6a8d60bd6b72a76e31
+Author: Mike Christie 
+Date:   Mon Jul 24 15:47:17 2006 -0500
+
+    [SCSI] iscsi bugfixes: handle data rsp errors
+    
+    if iscsi_data_rsp fails we must bail out. Since the pdu values like
+    data length are invalid we cannot continue to process the data since
+    it could over run buffers.
+    
+    This fixes a bug with cisco 5428s where that target is sending
+    too much data.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index ab324d984b8d..7d784596a1ea 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -486,6 +486,8 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *conn)
+ 	case ISCSI_OP_SCSI_DATA_IN:
+ 		tcp_conn->in.ctask = session->cmds[itt];
+ 		rc = iscsi_data_rsp(conn, tcp_conn->in.ctask);
++		if (rc)
++			return rc;
+ 		/* fall through */
+ 	case ISCSI_OP_SCSI_CMD_RSP:
+ 		tcp_conn->in.ctask = session->cmds[itt];
+@@ -532,7 +534,7 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *conn)
+ 	 * skbs to complete the command then we have to copy the header
+ 	 * for later use
+ 	 */
+-	if (tcp_conn->in.zero_copy_hdr && tcp_conn->in.copy <
++	if (tcp_conn->in.zero_copy_hdr && tcp_conn->in.copy <=
+ 	   (tcp_conn->in.datalen + tcp_conn->in.padding +
+ 	    (conn->datadgst_en ? 4 : 0))) {
+ 		debug_tcp("Copying header for later use. in.copy %d in.datalen"

commit b6c395ed0387c824ddf125d3b74b576a2575c149
+Author: Mike Christie 
+Date:   Mon Jul 24 15:47:15 2006 -0500
+
+    [SCSI] iscsi bugfixes: fix r2t handling
+    
+    The iscsi tcp code can pluck multiple rt2s from the tasks's r2tqueue
+    in the xmit code. This can result in the task being queued on the xmit queue
+    but gettting completed at the same time.
+    
+    This patch fixes the above bug by making the fifo a list so
+    we always remove the entry on the list del.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 88dafdf45c47..ab324d984b8d 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -185,11 +185,19 @@ iscsi_hdr_extract(struct iscsi_tcp_conn *tcp_conn)
+  * must be called with session lock
+  */
+ static void
+-__iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
++iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++	struct iscsi_r2t_info *r2t;
+ 	struct scsi_cmnd *sc;
+ 
++	/* flush ctask's r2t queues */
++	while (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) {
++		__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
++			    sizeof(void*));
++		debug_scsi("iscsi_tcp_cleanup_ctask pending r2t dropped\n");
++	}
++
+ 	sc = ctask->sc;
+ 	if (unlikely(!sc))
+ 		return;
+@@ -374,6 +382,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 		spin_unlock(&session->lock);
+ 		return 0;
+ 	}
++
+ 	rc = __kfifo_get(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*));
+ 	BUG_ON(!rc);
+ 
+@@ -399,7 +408,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	tcp_ctask->exp_r2tsn = r2tsn + 1;
+ 	tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
+ 	__kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*));
+-	__kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*));
++	list_move_tail(&ctask->running, &conn->xmitqueue);
+ 
+ 	scsi_queue_work(session->host, &conn->xmitwork);
+ 	conn->r2t_pdus_cnt++;
+@@ -484,7 +493,7 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *conn)
+ 			goto copy_hdr;
+ 
+ 		spin_lock(&session->lock);
+-		__iscsi_ctask_cleanup(conn, tcp_conn->in.ctask);
++		iscsi_tcp_cleanup_ctask(conn, tcp_conn->in.ctask);
+ 		rc = __iscsi_complete_pdu(conn, hdr, NULL, 0);
+ 		spin_unlock(&session->lock);
+ 		break;
+@@ -745,10 +754,11 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
+ done:
+ 	/* check for non-exceptional status */
+ 	if (tcp_conn->in.hdr->flags & ISCSI_FLAG_DATA_STATUS) {
+-		debug_scsi("done [sc %lx res %d itt 0x%x]\n",
+-			   (long)sc, sc->result, ctask->itt);
++		debug_scsi("done [sc %lx res %d itt 0x%x flags 0x%x]\n",
++			   (long)sc, sc->result, ctask->itt,
++			   tcp_conn->in.hdr->flags);
+ 		spin_lock(&conn->session->lock);
+-		__iscsi_ctask_cleanup(conn, ctask);
++		iscsi_tcp_cleanup_ctask(conn, ctask);
+ 		__iscsi_complete_pdu(conn, tcp_conn->in.hdr, NULL, 0);
+ 		spin_unlock(&conn->session->lock);
+ 	}
+@@ -769,7 +779,7 @@ iscsi_data_recv(struct iscsi_conn *conn)
+ 		break;
+ 	case ISCSI_OP_SCSI_CMD_RSP:
+ 		spin_lock(&conn->session->lock);
+-		__iscsi_ctask_cleanup(conn, tcp_conn->in.ctask);
++		iscsi_tcp_cleanup_ctask(conn, tcp_conn->in.ctask);
+ 		spin_unlock(&conn->session->lock);
+ 	case ISCSI_OP_TEXT_RSP:
+ 	case ISCSI_OP_LOGIN_RSP:
+@@ -1308,7 +1318,7 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask)
+ 				    ctask->imm_count -
+ 				    ctask->unsol_count;
+ 
+-		debug_scsi("cmd [itt %x total %d imm %d imm_data %d "
++		debug_scsi("cmd [itt 0x%x total %d imm %d imm_data %d "
+ 			   "r2t_data %d]\n",
+ 			   ctask->itt, ctask->total_length, ctask->imm_count,
+ 			   ctask->unsol_count, tcp_ctask->r2t_data_count);
+@@ -1636,7 +1646,7 @@ handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	}
+ solicit_again:
+ 	/*
+-	 * send Data-Out whitnin this R2T sequence.
++	 * send Data-Out within this R2T sequence.
+ 	 */
+ 	if (!r2t->data_count)
+ 		goto data_out_done;
+@@ -1731,7 +1741,7 @@ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	struct iscsi_data_task *dtask = tcp_ctask->dtask;
+-	int sent, rc;
++	int sent = 0, rc;
+ 
+ 	tcp_ctask->xmstate &= ~XMSTATE_W_PAD;
+ 	iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad,
+@@ -2001,20 +2011,6 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
+ 	return 0;
+ }
+ 
+-static void
+-iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+-{
+-	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+-	struct iscsi_r2t_info *r2t;
+-
+-	/* flush ctask's r2t queues */
+-	while (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*)))
+-		__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
+-			    sizeof(void*));
+-
+-	__iscsi_ctask_cleanup(conn, ctask);
+-}
+-
+ static void
+ iscsi_tcp_suspend_conn_rx(struct iscsi_conn *conn)
+ {
+@@ -2057,6 +2053,7 @@ iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask,
+ 	iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr,
+ 			   sizeof(struct iscsi_hdr));
+ 	tcp_mtask->xmstate = XMSTATE_IMM_HDR;
++	tcp_mtask->sent = 0;
+ 
+ 	if (mtask->data_count)
+ 		iscsi_buf_init_iov(&tcp_mtask->sendbuf, (char*)mtask->data,
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 7e6e031cc41b..1a8cd20f484f 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -189,6 +189,7 @@ static void iscsi_complete_command(struct iscsi_session *session,
+ {
+ 	struct scsi_cmnd *sc = ctask->sc;
+ 
++	ctask->state = ISCSI_TASK_COMPLETED;
+ 	ctask->sc = NULL;
+ 	list_del_init(&ctask->running);
+ 	__kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*));
+@@ -568,20 +569,24 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 	}
+ 
+ 	/* process command queue */
+-	while (__kfifo_get(conn->xmitqueue, (void*)&conn->ctask,
+-			   sizeof(void*))) {
++	spin_lock_bh(&conn->session->lock);
++	while (!list_empty(&conn->xmitqueue)) {
+ 		/*
+ 		 * iscsi tcp may readd the task to the xmitqueue to send
+ 		 * write data
+ 		 */
+-		spin_lock_bh(&conn->session->lock);
+-		if (list_empty(&conn->ctask->running))
+-			list_add_tail(&conn->ctask->running, &conn->run_list);
++		conn->ctask = list_entry(conn->xmitqueue.next,
++					 struct iscsi_cmd_task, running);
++		conn->ctask->state = ISCSI_TASK_RUNNING;
++		list_move_tail(conn->xmitqueue.next, &conn->run_list);
+ 		spin_unlock_bh(&conn->session->lock);
++
+ 		rc = tt->xmit_cmd_task(conn, conn->ctask);
+ 		if (rc)
+ 			goto again;
++		spin_lock_bh(&conn->session->lock);
+ 	}
++	spin_unlock_bh(&conn->session->lock);
+ 	/* done with this ctask */
+ 	conn->ctask = NULL;
+ 
+@@ -691,6 +696,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 	sc->SCp.phase = session->age;
+ 	sc->SCp.ptr = (char *)ctask;
+ 
++	ctask->state = ISCSI_TASK_PENDING;
+ 	ctask->mtask = NULL;
+ 	ctask->conn = conn;
+ 	ctask->sc = sc;
+@@ -700,7 +706,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 
+ 	session->tt->init_cmd_task(ctask);
+ 
+-	__kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*));
++	list_add_tail(&ctask->running, &conn->xmitqueue);
+ 	debug_scsi(
+ 	       "ctask enq [%s cid %d sc %lx itt 0x%x len %d cmdsn %d win %d]\n",
+ 		sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
+@@ -977,31 +983,27 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc,
+ /*
+  * xmit mutex and session lock must be held
+  */
+-#define iscsi_remove_task(tasktype)					\
+-static struct iscsi_##tasktype *					\
+-iscsi_remove_##tasktype(struct kfifo *fifo, uint32_t itt)		\
+-{									\
+-	int i, nr_tasks = __kfifo_len(fifo) / sizeof(void*);		\
+-	struct iscsi_##tasktype *task;					\
+-									\
+-	debug_scsi("searching %d tasks\n", nr_tasks);			\
+-									\
+-	for (i = 0; i < nr_tasks; i++) {				\
+-		__kfifo_get(fifo, (void*)&task, sizeof(void*));		\
+-		debug_scsi("check task %u\n", task->itt);		\
+-									\
+-		if (task->itt == itt) {					\
+-			debug_scsi("matched task\n");			\
+-			return task;					\
+-		}							\
+-									\
+-		__kfifo_put(fifo, (void*)&task, sizeof(void*));		\
+-	}								\
+-	return NULL;							\
+-}
++static struct iscsi_mgmt_task *
++iscsi_remove_mgmt_task(struct kfifo *fifo, uint32_t itt)
++{
++	int i, nr_tasks = __kfifo_len(fifo) / sizeof(void*);
++	struct iscsi_mgmt_task *task;
++
++	debug_scsi("searching %d tasks\n", nr_tasks);
++
++	for (i = 0; i < nr_tasks; i++) {
++		__kfifo_get(fifo, (void*)&task, sizeof(void*));
++		debug_scsi("check task %u\n", task->itt);
++
++		if (task->itt == itt) {
++			debug_scsi("matched task\n");
++			return task;
++		}
+ 
+-iscsi_remove_task(mgmt_task);
+-iscsi_remove_task(cmd_task);
++		__kfifo_put(fifo, (void*)&task, sizeof(void*));
++	}
++	return NULL;
++}
+ 
+ static int iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask)
+ {
+@@ -1043,7 +1045,6 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 	struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr;
+ 	struct iscsi_conn *conn = ctask->conn;
+ 	struct iscsi_session *session = conn->session;
+-	struct iscsi_cmd_task *pending_ctask;
+ 	int rc;
+ 
+ 	conn->eh_abort_cnt++;
+@@ -1071,17 +1072,8 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
+ 		goto failed;
+ 	}
+ 
+-	/* check for the easy pending cmd abort */
+-	pending_ctask = iscsi_remove_cmd_task(conn->xmitqueue, ctask->itt);
+-	if (pending_ctask) {
+-		/* iscsi_tcp queues write transfers on the xmitqueue */
+-		if (list_empty(&pending_ctask->running)) {
+-			debug_scsi("found pending task\n");
+-			goto success;
+-		} else
+-			__kfifo_put(conn->xmitqueue, (void*)&pending_ctask,
+-				    sizeof(void*));
+-	}
++	if (ctask->state == ISCSI_TASK_PENDING)
++		goto success;
+ 
+ 	conn->tmabort_state = TMABORT_INITIAL;
+ 
+@@ -1263,6 +1255,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
+ 		if (cmd_task_size)
+ 			ctask->dd_data = &ctask[1];
+ 		ctask->itt = cmd_i;
++		INIT_LIST_HEAD(&ctask->running);
+ 	}
+ 
+ 	spin_lock_init(&session->lock);
+@@ -1282,6 +1275,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
+ 		if (mgmt_task_size)
+ 			mtask->dd_data = &mtask[1];
+ 		mtask->itt = ISCSI_MGMT_ITT_OFFSET + cmd_i;
++		INIT_LIST_HEAD(&mtask->running);
+ 	}
+ 
+ 	if (scsi_add_host(shost, NULL))
+@@ -1361,12 +1355,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ 	conn->tmabort_state = TMABORT_INITIAL;
+ 	INIT_LIST_HEAD(&conn->run_list);
+ 	INIT_LIST_HEAD(&conn->mgmt_run_list);
+-
+-	/* initialize general xmit PDU commands queue */
+-	conn->xmitqueue = kfifo_alloc(session->cmds_max * sizeof(void*),
+-					GFP_KERNEL, NULL);
+-	if (conn->xmitqueue == ERR_PTR(-ENOMEM))
+-		goto xmitqueue_alloc_fail;
++	INIT_LIST_HEAD(&conn->xmitqueue);
+ 
+ 	/* initialize general immediate & non-immediate PDU commands queue */
+ 	conn->immqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*),
+@@ -1410,8 +1399,6 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ mgmtqueue_alloc_fail:
+ 	kfifo_free(conn->immqueue);
+ immqueue_alloc_fail:
+-	kfifo_free(conn->xmitqueue);
+-xmitqueue_alloc_fail:
+ 	iscsi_destroy_conn(cls_conn);
+ 	return NULL;
+ }
+@@ -1489,7 +1476,6 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
+ 		session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1;
+ 	spin_unlock_bh(&session->lock);
+ 
+-	kfifo_free(conn->xmitqueue);
+ 	kfifo_free(conn->immqueue);
+ 	kfifo_free(conn->mgmtqueue);
+ 
+@@ -1572,7 +1558,7 @@ static void fail_all_commands(struct iscsi_conn *conn)
+ 	struct iscsi_cmd_task *ctask, *tmp;
+ 
+ 	/* flush pending */
+-	while (__kfifo_get(conn->xmitqueue, (void*)&ctask, sizeof(void*))) {
++	list_for_each_entry_safe(ctask, tmp, &conn->xmitqueue, running) {
+ 		debug_scsi("failing pending sc %p itt 0x%x\n", ctask->sc,
+ 			   ctask->itt);
+ 		fail_command(conn, ctask, DID_BUS_BUSY << 16);
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index ba2760802ded..e71d6e96eca6 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -83,6 +83,12 @@ struct iscsi_mgmt_task {
+ 	struct list_head	running;
+ };
+ 
++enum {
++	ISCSI_TASK_COMPLETED,
++	ISCSI_TASK_PENDING,
++	ISCSI_TASK_RUNNING,
++};
++
+ struct iscsi_cmd_task {
+ 	/*
+ 	 * Becuae LLDs allocate their hdr differently, this is a pointer to
+@@ -101,6 +107,8 @@ struct iscsi_cmd_task {
+ 	struct iscsi_conn	*conn;		/* used connection    */
+ 	struct iscsi_mgmt_task	*mtask;		/* tmf mtask in progr */
+ 
++	/* state set/tested under session->lock */
++	int			state;
+ 	struct list_head	running;	/* running cmd list */
+ 	void			*dd_data;	/* driver/transport data */
+ };
+@@ -134,7 +142,7 @@ struct iscsi_conn {
+ 	struct kfifo		*immqueue;	/* immediate xmit queue */
+ 	struct kfifo		*mgmtqueue;	/* mgmt (control) xmit queue */
+ 	struct list_head	mgmt_run_list;	/* list of control tasks */
+-	struct kfifo		*xmitqueue;	/* data-path cmd queue */
++	struct list_head	xmitqueue;	/* data-path cmd queue */
+ 	struct list_head	run_list;	/* list of cmds in progress */
+ 	struct work_struct	xmitwork;	/* per-conn. xmit workqueue */
+ 	/*

commit d82967c70658a408ea6cae5dc989ba8b2c0999e1
+Author: Mike Christie 
+Date:   Mon Jul 24 15:47:11 2006 -0500
+
+    [SCSI] iscsi bugfixes: send correct error values to userspace
+    
+    In the xmit patch we are sending a -EXXX value to iscsi_conn_failure
+    which is causing userspace to get confused.
+    
+    We should be sending a ISCSI_ERR_* value that userspace understands.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 848fb2aa4ca3..88dafdf45c47 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -843,7 +843,7 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 		       if (rc == -EAGAIN)
+ 				goto nomore;
+ 		       else {
+-				iscsi_conn_failure(conn, rc);
++				iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ 				return 0;
+ 		       }
+ 		}
+@@ -859,7 +859,7 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 			}
+ 			tcp_conn->in_progress = IN_PROGRESS_DATA_RECV;
+ 		} else if (rc) {
+-			iscsi_conn_failure(conn, rc);
++			iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ 			return 0;
+ 		}
+ 	}
+@@ -897,7 +897,7 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 		if (rc) {
+ 			if (rc == -EAGAIN)
+ 				goto again;
+-			iscsi_conn_failure(conn, rc);
++			iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ 			return 0;
+ 		}
+ 		tcp_conn->in.copy -= tcp_conn->in.padding;

commit 53cb8a1f45e06a2627a6d89b151cccb95fa45cbf
+Author: Mike Christie 
+Date:   Wed Jun 28 12:00:32 2006 -0500
+
+    [SCSI] iscsi: add async notification of session events
+    
+    This patch adds or modifies the transport class functions
+    used to notify userspace of session state events.
+    
+    We modify the session addition up event and add a destruction event
+    to notify userspace of session creation, relogin and destruction.
+    
+    And we modify the conn error event to be sent by broadcast
+    since multiple listeners may want to listen for it.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 7963c0538de5..7b9e8fa1a4e0 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -413,11 +413,59 @@ int iscsi_destroy_session(struct iscsi_cls_session *session)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_destroy_session);
+ 
++static void mempool_zone_destroy(struct mempool_zone *zp)
++{
++	mempool_destroy(zp->pool);
++	kfree(zp);
++}
++
++static void*
++mempool_zone_alloc_skb(gfp_t gfp_mask, void *pool_data)
++{
++	struct mempool_zone *zone = pool_data;
++
++	return alloc_skb(zone->size, gfp_mask);
++}
++
++static void
++mempool_zone_free_skb(void *element, void *pool_data)
++{
++	kfree_skb(element);
++}
++
++static struct mempool_zone *
++mempool_zone_init(unsigned max, unsigned size, unsigned hiwat)
++{
++	struct mempool_zone *zp;
++
++	zp = kzalloc(sizeof(*zp), GFP_KERNEL);
++	if (!zp)
++		return NULL;
++
++	zp->size = size;
++	zp->hiwat = hiwat;
++	INIT_LIST_HEAD(&zp->freequeue);
++	spin_lock_init(&zp->freelock);
++	atomic_set(&zp->allocated, 0);
++
++	zp->pool = mempool_create(max, mempool_zone_alloc_skb,
++				  mempool_zone_free_skb, zp);
++	if (!zp->pool) {
++		kfree(zp);
++		return NULL;
++	}
++
++	return zp;
++}
++
+ static void iscsi_conn_release(struct device *dev)
+ {
+ 	struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev);
+ 	struct device *parent = conn->dev.parent;
+ 
++	mempool_zone_destroy(conn->z_pdu);
++	mempool_zone_destroy(conn->z_error);
++
+ 	kfree(conn);
+ 	put_device(parent);
+ }
+@@ -427,6 +475,31 @@ static int iscsi_is_conn_dev(const struct device *dev)
+ 	return dev->release == iscsi_conn_release;
+ }
+ 
++static int iscsi_create_event_pools(struct iscsi_cls_conn *conn)
++{
++	conn->z_pdu = mempool_zone_init(Z_MAX_PDU,
++			NLMSG_SPACE(sizeof(struct iscsi_uevent) +
++				    sizeof(struct iscsi_hdr) +
++				    DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH),
++			Z_HIWAT_PDU);
++	if (!conn->z_pdu) {
++		dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
++			   "pdu zone for new conn\n");
++		return -ENOMEM;
++	}
++
++	conn->z_error = mempool_zone_init(Z_MAX_ERROR,
++			NLMSG_SPACE(sizeof(struct iscsi_uevent)),
++			Z_HIWAT_ERROR);
++	if (!conn->z_error) {
++		dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
++			   "error zone for new conn\n");
++		mempool_zone_destroy(conn->z_pdu);
++		return -ENOMEM;
++	}
++	return 0;
++}
++
+ /**
+  * iscsi_create_conn - create iscsi class connection
+  * @session: iscsi cls session
+@@ -459,9 +532,12 @@ iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid)
+ 	conn->transport = transport;
+ 	conn->cid = cid;
+ 
++	if (iscsi_create_event_pools(conn))
++		goto free_conn;
++
+ 	/* this is released in the dev's release function */
+ 	if (!get_device(&session->dev))
+-		goto free_conn;
++		goto free_conn_pools;
+ 
+ 	snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
+ 		 session->sid, cid);
+@@ -478,6 +554,8 @@ iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid)
+ 
+ release_parent_ref:
+ 	put_device(&session->dev);
++free_conn_pools:
++
+ free_conn:
+ 	kfree(conn);
+ 	return NULL;
+@@ -525,20 +603,6 @@ static inline struct list_head *skb_to_lh(struct sk_buff *skb)
+ 	return (struct list_head *)&skb->cb;
+ }
+ 
+-static void*
+-mempool_zone_alloc_skb(gfp_t gfp_mask, void *pool_data)
+-{
+-	struct mempool_zone *zone = pool_data;
+-
+-	return alloc_skb(zone->size, gfp_mask);
+-}
+-
+-static void
+-mempool_zone_free_skb(void *element, void *pool_data)
+-{
+-	kfree_skb(element);
+-}
+-
+ static void
+ mempool_zone_complete(struct mempool_zone *zone)
+ {
+@@ -558,37 +622,6 @@ mempool_zone_complete(struct mempool_zone *zone)
+ 	spin_unlock_irqrestore(&zone->freelock, flags);
+ }
+ 
+-static struct mempool_zone *
+-mempool_zone_init(unsigned max, unsigned size, unsigned hiwat)
+-{
+-	struct mempool_zone *zp;
+-
+-	zp = kzalloc(sizeof(*zp), GFP_KERNEL);
+-	if (!zp)
+-		return NULL;
+-
+-	zp->size = size;
+-	zp->hiwat = hiwat;
+-	INIT_LIST_HEAD(&zp->freequeue);
+-	spin_lock_init(&zp->freelock);
+-	atomic_set(&zp->allocated, 0);
+-
+-	zp->pool = mempool_create(max, mempool_zone_alloc_skb,
+-				  mempool_zone_free_skb, zp);
+-	if (!zp->pool) {
+-		kfree(zp);
+-		return NULL;
+-	}
+-
+-	return zp;
+-}
+-
+-static void mempool_zone_destroy(struct mempool_zone *zp)
+-{
+-	mempool_destroy(zp->pool);
+-	kfree(zp);
+-}
+-
+ static struct sk_buff*
+ mempool_zone_get_skb(struct mempool_zone *zone)
+ {
+@@ -600,6 +633,27 @@ mempool_zone_get_skb(struct mempool_zone *zone)
+ 	return skb;
+ }
+ 
++static int
++iscsi_broadcast_skb(struct mempool_zone *zone, struct sk_buff *skb)
++{
++	unsigned long flags;
++	int rc;
++
++	skb_get(skb);
++	rc = netlink_broadcast(nls, skb, 0, 1, GFP_KERNEL);
++	if (rc < 0) {
++		mempool_free(skb, zone->pool);
++		printk(KERN_ERR "iscsi: can not broadcast skb (%d)\n", rc);
++		return rc;
++	}
++
++	spin_lock_irqsave(&zone->freelock, flags);
++	INIT_LIST_HEAD(skb_to_lh(skb));
++	list_add(skb_to_lh(skb), &zone->freequeue);
++	spin_unlock_irqrestore(&zone->freelock, flags);
++	return 0;
++}
++
+ static int
+ iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb, int pid)
+ {
+@@ -695,7 +749,7 @@ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
+ 	ev->r.connerror.cid = conn->cid;
+ 	ev->r.connerror.sid = iscsi_conn_get_sid(conn);
+ 
+-	iscsi_unicast_skb(conn->z_error, skb, priv->daemon_pid);
++	iscsi_broadcast_skb(conn->z_error, skb);
+ 
+ 	dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n",
+ 		   error);
+@@ -796,6 +850,131 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
+ 	return err;
+ }
+ 
++/**
++ * iscsi_if_destroy_session_done - send session destr. completion event
++ * @conn: last connection for session
++ *
++ * This is called by HW iscsi LLDs to notify userpsace that its HW has
++ * removed a session.
++ **/
++int iscsi_if_destroy_session_done(struct iscsi_cls_conn *conn)
++{
++	struct iscsi_internal *priv;
++	struct iscsi_cls_session *session;
++	struct Scsi_Host *shost;
++	struct iscsi_uevent *ev;
++	struct sk_buff  *skb;
++	struct nlmsghdr *nlh;
++	unsigned long flags;
++	int rc, len = NLMSG_SPACE(sizeof(*ev));
++
++	priv = iscsi_if_transport_lookup(conn->transport);
++	if (!priv)
++		return -EINVAL;
++
++	session = iscsi_dev_to_session(conn->dev.parent);
++	shost = iscsi_session_to_shost(session);
++
++	mempool_zone_complete(conn->z_pdu);
++
++	skb = mempool_zone_get_skb(conn->z_pdu);
++	if (!skb) {
++		dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
++			  "session creation event\n");
++		return -ENOMEM;
++	}
++
++	nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
++	ev = NLMSG_DATA(nlh);
++	ev->transport_handle = iscsi_handle(conn->transport);
++	ev->type = ISCSI_KEVENT_DESTROY_SESSION;
++	ev->r.d_session.host_no = shost->host_no;
++	ev->r.d_session.sid = session->sid;
++
++	/*
++	 * this will occur if the daemon is not up, so we just warn
++	 * the user and when the daemon is restarted it will handle it
++	 */
++	rc = iscsi_broadcast_skb(conn->z_pdu, skb);
++	if (rc < 0)
++		dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
++			  "session destruction event. Check iscsi daemon\n");
++
++	spin_lock_irqsave(&sesslock, flags);
++	list_del(&session->sess_list);
++	spin_unlock_irqrestore(&sesslock, flags);
++
++	spin_lock_irqsave(&connlock, flags);
++	conn->active = 0;
++	list_del(&conn->conn_list);
++	spin_unlock_irqrestore(&connlock, flags);
++
++	return rc;
++}
++EXPORT_SYMBOL_GPL(iscsi_if_destroy_session_done);
++
++/**
++ * iscsi_if_create_session_done - send session creation completion event
++ * @conn: leading connection for session
++ *
++ * This is called by HW iscsi LLDs to notify userpsace that its HW has
++ * created a session or a existing session is back in the logged in state.
++ **/
++int iscsi_if_create_session_done(struct iscsi_cls_conn *conn)
++{
++	struct iscsi_internal *priv;
++	struct iscsi_cls_session *session;
++	struct Scsi_Host *shost;
++	struct iscsi_uevent *ev;
++	struct sk_buff  *skb;
++	struct nlmsghdr *nlh;
++	unsigned long flags;
++	int rc, len = NLMSG_SPACE(sizeof(*ev));
++
++	priv = iscsi_if_transport_lookup(conn->transport);
++	if (!priv)
++		return -EINVAL;
++
++	session = iscsi_dev_to_session(conn->dev.parent);
++	shost = iscsi_session_to_shost(session);
++
++	mempool_zone_complete(conn->z_pdu);
++
++	skb = mempool_zone_get_skb(conn->z_pdu);
++	if (!skb) {
++		dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
++			  "session creation event\n");
++		return -ENOMEM;
++	}
++
++	nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
++	ev = NLMSG_DATA(nlh);
++	ev->transport_handle = iscsi_handle(conn->transport);
++	ev->type = ISCSI_UEVENT_CREATE_SESSION;
++	ev->r.c_session_ret.host_no = shost->host_no;
++	ev->r.c_session_ret.sid = session->sid;
++
++	/*
++	 * this will occur if the daemon is not up, so we just warn
++	 * the user and when the daemon is restarted it will handle it
++	 */
++	rc = iscsi_broadcast_skb(conn->z_pdu, skb);
++	if (rc < 0)
++		dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
++			  "session creation event. Check iscsi daemon\n");
++
++	spin_lock_irqsave(&sesslock, flags);
++	list_add(&session->sess_list, &sesslist);
++	spin_unlock_irqrestore(&sesslock, flags);
++
++	spin_lock_irqsave(&connlock, flags);
++	list_add(&conn->conn_list, &connlist);
++	conn->active = 1;
++	spin_unlock_irqrestore(&connlock, flags);
++	return rc;
++}
++EXPORT_SYMBOL_GPL(iscsi_if_create_session_done);
++
+ static int
+ iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
+ {
+@@ -841,26 +1020,6 @@ iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+ 		return -ENOMEM;
+ 	}
+ 
+-	conn->z_pdu = mempool_zone_init(Z_MAX_PDU,
+-			NLMSG_SPACE(sizeof(struct iscsi_uevent) +
+-				    sizeof(struct iscsi_hdr) +
+-				    DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH),
+-			Z_HIWAT_PDU);
+-	if (!conn->z_pdu) {
+-		dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
+-			   "pdu zone for new conn\n");
+-		goto destroy_conn;
+-	}
+-
+-	conn->z_error = mempool_zone_init(Z_MAX_ERROR,
+-			NLMSG_SPACE(sizeof(struct iscsi_uevent)),
+-			Z_HIWAT_ERROR);
+-	if (!conn->z_error) {
+-		dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
+-			   "error zone for new conn\n");
+-		goto free_pdu_pool;
+-	}
+-
+ 	ev->r.c_conn_ret.sid = session->sid;
+ 	ev->r.c_conn_ret.cid = conn->cid;
+ 
+@@ -870,13 +1029,6 @@ iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+ 	spin_unlock_irqrestore(&connlock, flags);
+ 
+ 	return 0;
+-
+-free_pdu_pool:
+-	mempool_zone_destroy(conn->z_pdu);
+-destroy_conn:
+-	if (transport->destroy_conn)
+-		transport->destroy_conn(conn->dd_data);
+-	return -ENOMEM;
+ }
+ 
+ static int
+@@ -884,7 +1036,6 @@ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev
+ {
+ 	unsigned long flags;
+ 	struct iscsi_cls_conn *conn;
+-	struct mempool_zone *z_error, *z_pdu;
+ 
+ 	conn = iscsi_conn_lookup(ev->u.d_conn.sid, ev->u.d_conn.cid);
+ 	if (!conn)
+@@ -894,15 +1045,8 @@ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev
+ 	list_del(&conn->conn_list);
+ 	spin_unlock_irqrestore(&connlock, flags);
+ 
+-	z_pdu = conn->z_pdu;
+-	z_error = conn->z_error;
+-
+ 	if (transport->destroy_conn)
+ 		transport->destroy_conn(conn);
+-
+-	mempool_zone_destroy(z_pdu);
+-	mempool_zone_destroy(z_error);
+-
+ 	return 0;
+ }
+ 
+@@ -1331,6 +1475,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 	if (!priv)
+ 		return NULL;
+ 	INIT_LIST_HEAD(&priv->list);
++	priv->daemon_pid = -1;
+ 	priv->iscsi_transport = tt;
+ 	priv->t.user_scan = iscsi_user_scan;
+ 
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index 8813f0f4c624..55ebf035e620 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -53,6 +53,7 @@ enum iscsi_uevent_e {
+ 	ISCSI_KEVENT_RECV_PDU		= KEVENT_BASE + 1,
+ 	ISCSI_KEVENT_CONN_ERROR		= KEVENT_BASE + 2,
+ 	ISCSI_KEVENT_IF_ERROR		= KEVENT_BASE + 3,
++	ISCSI_KEVENT_DESTROY_SESSION	= KEVENT_BASE + 4,
+ };
+ 
+ enum iscsi_tgt_dscvr {
+@@ -157,27 +158,13 @@ struct iscsi_uevent {
+ 			uint32_t	cid;
+ 			uint32_t	error; /* enum iscsi_err */
+ 		} connerror;
++		struct msg_session_destroyed {
++			uint32_t	host_no;
++			uint32_t	sid;
++		} d_session;
+ 		struct msg_transport_connect_ret {
+ 			uint64_t	handle;
+ 		} ep_connect_ret;
+-		struct msg_tgt_dscvr_ret {
+-			/*
+-			 * session/connection pair used to reference
+-			 * the connection to server
+-			 */
+-			uint32_t	sid;
+-			uint32_t	cid;
+-			union {
+-				struct isns {
+-					/* port # for conn to iSNS server */
+-					uint16_t isns_port;
+-					/* listening port to receive SCNs */
+-					uint16_t scn_port;
+-					/* listening port to receive ESIs */
+-					uint16_t esi_port;
+-				} isns_attrib;
+-			} u;
+-		} tgt_dscvr_ret;
+ 	} r;
+ } __attribute__ ((aligned (sizeof(uint64_t))));
+ 
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index f7b0db5f2f5b..5a3df1d7085f 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -214,6 +214,8 @@ extern struct iscsi_cls_session *iscsi_alloc_session(struct Scsi_Host *shost,
+ 					struct iscsi_transport *transport);
+ extern int iscsi_add_session(struct iscsi_cls_session *session,
+ 			     unsigned int target_id);
++extern int iscsi_if_create_session_done(struct iscsi_cls_conn *conn);
++extern int iscsi_if_destroy_session_done(struct iscsi_cls_conn *conn);
+ extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost,
+ 						struct iscsi_transport *t,
+ 						unsigned int target_id);
+@@ -226,4 +228,5 @@ extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn);
+ extern void iscsi_unblock_session(struct iscsi_cls_session *session);
+ extern void iscsi_block_session(struct iscsi_cls_session *session);
+ 
++
+ #endif

commit 6a8a0d3621745279a131d95f0204dc9ddac60d55
+Author: Mike Christie 
+Date:   Wed Jun 28 12:00:31 2006 -0500
+
+    [SCSI] iscsi: pass target nr to session creation
+    
+    So the drivers do not use the channel numbers, but some do
+    use the target numbers. We were just adding some goofy
+    variable that just increases for the target nr. This is useless
+    for software iscsi because it is always zero. And for qla4xxx
+    the target nr is actually the index of the target/session
+    in its FW or FLASH tables. We needed to expose this to userspace
+    so apps could access those numbers so this patch just adds the
+    target nr to the iscsi session creation functions. This way
+    when qla4xxx's Hw thinks a session is at target nr 4
+    in its hw, it is exposed as that number in sysfs.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 499e79f0cac5..7e6e031cc41b 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1290,7 +1290,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
+ 	if (!try_module_get(iscsit->owner))
+ 		goto cls_session_fail;
+ 
+-	cls_session = iscsi_create_session(shost, iscsit);
++	cls_session = iscsi_create_session(shost, iscsit, 0);
+ 	if (!cls_session)
+ 		goto module_put;
+ 	*(unsigned long*)shost->hostdata = (unsigned long)cls_session;
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index f39da0cf5f18..7963c0538de5 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -304,6 +304,8 @@ iscsi_alloc_session(struct Scsi_Host *shost,
+ 	INIT_LIST_HEAD(&session->host_list);
+ 	INIT_LIST_HEAD(&session->sess_list);
+ 
++	/* this is released in the dev's release function */
++	scsi_host_get(shost);
+ 	session->dev.parent = &shost->shost_gendev;
+ 	session->dev.release = iscsi_session_release;
+ 	device_initialize(&session->dev);
+@@ -313,18 +315,15 @@ iscsi_alloc_session(struct Scsi_Host *shost,
+ }
+ EXPORT_SYMBOL_GPL(iscsi_alloc_session);
+ 
+-int iscsi_add_session(struct iscsi_cls_session *session)
++int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
+ {
+ 	struct Scsi_Host *shost = iscsi_session_to_shost(session);
+ 	struct iscsi_host *ihost;
+ 	int err;
+ 
+-	/* this is released in the dev's release function */
+-	scsi_host_get(shost);
+ 	ihost = shost->shost_data;
+-
+ 	session->sid = iscsi_session_nr++;
+-	session->target_id = ihost->next_target_id++;
++	session->target_id = target_id;
+ 
+ 	snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u",
+ 		 session->sid);
+@@ -356,7 +355,8 @@ EXPORT_SYMBOL_GPL(iscsi_add_session);
+  **/
+ struct iscsi_cls_session *
+ iscsi_create_session(struct Scsi_Host *shost,
+-		     struct iscsi_transport *transport)
++		     struct iscsi_transport *transport,
++		     unsigned int target_id)
+ {
+ 	struct iscsi_cls_session *session;
+ 
+@@ -364,7 +364,7 @@ iscsi_create_session(struct Scsi_Host *shost,
+ 	if (!session)
+ 		return NULL;
+ 
+-	if (iscsi_add_session(session)) {
++	if (iscsi_add_session(session, target_id)) {
+ 		iscsi_free_session(session);
+ 		return NULL;
+ 	}
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 53493d591355..f7b0db5f2f5b 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -203,7 +203,6 @@ struct iscsi_cls_session {
+ 	iscsi_dev_to_session(_stgt->dev.parent)
+ 
+ struct iscsi_host {
+-	int next_target_id;
+ 	struct list_head sessions;
+ 	struct mutex mutex;
+ };
+@@ -213,9 +212,11 @@ struct iscsi_host {
+  */
+ extern struct iscsi_cls_session *iscsi_alloc_session(struct Scsi_Host *shost,
+ 					struct iscsi_transport *transport);
+-extern int iscsi_add_session(struct iscsi_cls_session *session);
++extern int iscsi_add_session(struct iscsi_cls_session *session,
++			     unsigned int target_id);
+ extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost,
+-						struct iscsi_transport *t);
++						struct iscsi_transport *t,
++						unsigned int target_id);
+ extern void iscsi_remove_session(struct iscsi_cls_session *session);
+ extern void iscsi_free_session(struct iscsi_cls_session *session);
+ extern int iscsi_destroy_session(struct iscsi_cls_session *session);

commit 8434aa8b6fe5af27a33b8aa830c24e3680356c83
+Author: Mike Christie 
+Date:   Wed Jun 28 12:00:30 2006 -0500
+
+    [SCSI] iscsi: break up session creation into two stages
+    
+    qla4xxx is initialized in two steps like other HW drivers.
+    It allocates the host, sets up the HW, then adds the host.
+    For iscsi part of HW setup is setting up persistent iscsi
+    sessions. At that time, the interupts are off and the driver
+    is not completely set up so we just want to allocate them.
+    We do not want to add them to sysfs and expose them to userspace
+    because userspace could try to do lots of fun things with them
+    like scanning and at that time the driver is not ready.
+    
+    So this patch breakes up the session creation like other
+    functions that use the driver model in two the alloc
+    and add parts. When the driver is ready, it can then add
+    the sessions and userspace can begin using them.
+    
+    This also fixes a bug in the addition error patch where
+    we forgot to do a get on the session.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index c0ec502835ee..f39da0cf5f18 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -287,20 +287,11 @@ void iscsi_block_session(struct iscsi_cls_session *session)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_block_session);
+ 
+-/**
+- * iscsi_create_session - create iscsi class session
+- * @shost: scsi host
+- * @transport: iscsi transport
+- *
+- * This can be called from a LLD or iscsi_transport.
+- **/
+ struct iscsi_cls_session *
+-iscsi_create_session(struct Scsi_Host *shost,
+-		     struct iscsi_transport *transport)
++iscsi_alloc_session(struct Scsi_Host *shost,
++		    struct iscsi_transport *transport)
+ {
+-	struct iscsi_host *ihost;
+ 	struct iscsi_cls_session *session;
+-	int err;
+ 
+ 	session = kzalloc(sizeof(*session) + transport->sessiondata_size,
+ 			  GFP_KERNEL);
+@@ -313,8 +304,20 @@ iscsi_create_session(struct Scsi_Host *shost,
+ 	INIT_LIST_HEAD(&session->host_list);
+ 	INIT_LIST_HEAD(&session->sess_list);
+ 
++	session->dev.parent = &shost->shost_gendev;
++	session->dev.release = iscsi_session_release;
++	device_initialize(&session->dev);
+ 	if (transport->sessiondata_size)
+ 		session->dd_data = &session[1];
++	return session;
++}
++EXPORT_SYMBOL_GPL(iscsi_alloc_session);
++
++int iscsi_add_session(struct iscsi_cls_session *session)
++{
++	struct Scsi_Host *shost = iscsi_session_to_shost(session);
++	struct iscsi_host *ihost;
++	int err;
+ 
+ 	/* this is released in the dev's release function */
+ 	scsi_host_get(shost);
+@@ -325,37 +328,51 @@ iscsi_create_session(struct Scsi_Host *shost,
+ 
+ 	snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u",
+ 		 session->sid);
+-	session->dev.parent = &shost->shost_gendev;
+-	session->dev.release = iscsi_session_release;
+-	err = device_register(&session->dev);
++	err = device_add(&session->dev);
+ 	if (err) {
+ 		dev_printk(KERN_ERR, &session->dev, "iscsi: could not "
+ 			   "register session's dev\n");
+-		goto free_session;
++		goto release_host;
+ 	}
+ 	transport_register_device(&session->dev);
+ 
+ 	mutex_lock(&ihost->mutex);
+ 	list_add(&session->host_list, &ihost->sessions);
+ 	mutex_unlock(&ihost->mutex);
++	return 0;
+ 
+-	return session;
+-
+-free_session:
+-	kfree(session);
+-	return NULL;
++release_host:
++	scsi_host_put(shost);
++	return err;
+ }
+-
+-EXPORT_SYMBOL_GPL(iscsi_create_session);
++EXPORT_SYMBOL_GPL(iscsi_add_session);
+ 
+ /**
+- * iscsi_destroy_session - destroy iscsi session
+- * @session: iscsi_session
++ * iscsi_create_session - create iscsi class session
++ * @shost: scsi host
++ * @transport: iscsi transport
+  *
+- * Can be called by a LLD or iscsi_transport. There must not be
+- * any running connections.
++ * This can be called from a LLD or iscsi_transport.
+  **/
+-int iscsi_destroy_session(struct iscsi_cls_session *session)
++struct iscsi_cls_session *
++iscsi_create_session(struct Scsi_Host *shost,
++		     struct iscsi_transport *transport)
++{
++	struct iscsi_cls_session *session;
++
++	session = iscsi_alloc_session(shost, transport);
++	if (!session)
++		return NULL;
++
++	if (iscsi_add_session(session)) {
++		iscsi_free_session(session);
++		return NULL;
++	}
++	return session;
++}
++EXPORT_SYMBOL_GPL(iscsi_create_session);
++
++void iscsi_remove_session(struct iscsi_cls_session *session)
+ {
+ 	struct Scsi_Host *shost = iscsi_session_to_shost(session);
+ 	struct iscsi_host *ihost = shost->shost_data;
+@@ -367,11 +384,33 @@ int iscsi_destroy_session(struct iscsi_cls_session *session)
+ 	list_del(&session->host_list);
+ 	mutex_unlock(&ihost->mutex);
+ 
++	scsi_remove_target(&session->dev);
++
+ 	transport_unregister_device(&session->dev);
+-	device_unregister(&session->dev);
+-	return 0;
++	device_del(&session->dev);
+ }
++EXPORT_SYMBOL_GPL(iscsi_remove_session);
+ 
++void iscsi_free_session(struct iscsi_cls_session *session)
++{
++	put_device(&session->dev);
++}
++
++EXPORT_SYMBOL_GPL(iscsi_free_session);
++
++/**
++ * iscsi_destroy_session - destroy iscsi session
++ * @session: iscsi_session
++ *
++ * Can be called by a LLD or iscsi_transport. There must not be
++ * any running connections.
++ **/
++int iscsi_destroy_session(struct iscsi_cls_session *session)
++{
++	iscsi_remove_session(session);
++	iscsi_free_session(session);
++	return 0;
++}
+ EXPORT_SYMBOL_GPL(iscsi_destroy_session);
+ 
+ static void iscsi_conn_release(struct device *dev)
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 2e3cb37af047..53493d591355 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -199,6 +199,9 @@ struct iscsi_cls_session {
+ #define iscsi_session_to_shost(_session) \
+ 	dev_to_shost(_session->dev.parent)
+ 
++#define starget_to_session(_stgt) \
++	iscsi_dev_to_session(_stgt->dev.parent)
++
+ struct iscsi_host {
+ 	int next_target_id;
+ 	struct list_head sessions;
+@@ -208,8 +211,13 @@ struct iscsi_host {
+ /*
+  * session and connection functions that can be used by HW iSCSI LLDs
+  */
++extern struct iscsi_cls_session *iscsi_alloc_session(struct Scsi_Host *shost,
++					struct iscsi_transport *transport);
++extern int iscsi_add_session(struct iscsi_cls_session *session);
+ extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost,
+ 						struct iscsi_transport *t);
++extern void iscsi_remove_session(struct iscsi_cls_session *session);
++extern void iscsi_free_session(struct iscsi_cls_session *session);
+ extern int iscsi_destroy_session(struct iscsi_cls_session *session);
+ extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess,
+ 					    uint32_t cid);

commit e6f3b63f50b4bb9fdc9025e0c3994acd265ad3a2
+Author: Mike Christie 
+Date:   Wed Jun 28 12:00:29 2006 -0500
+
+    [SCSI] iscsi: rm channel usage from iscsi
+    
+    I do not remember what I was thinking when we added the channel
+    as a argument to the session create function. It was probably
+    due to too much cut and paste work from the FC transport class.
+    
+    The channel is meaningless for iscsi drivers so this patch drops
+    its usage everywhere in the iscsi related code.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 7e6e031cc41b..499e79f0cac5 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1290,7 +1290,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
+ 	if (!try_module_get(iscsit->owner))
+ 		goto cls_session_fail;
+ 
+-	cls_session = iscsi_create_session(shost, iscsit, 0);
++	cls_session = iscsi_create_session(shost, iscsit);
+ 	if (!cls_session)
+ 		goto module_put;
+ 	*(unsigned long*)shost->hostdata = (unsigned long)cls_session;
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 8717ff51ba4b..c0ec502835ee 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -248,10 +248,9 @@ static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
+ 
+ 	mutex_lock(&ihost->mutex);
+ 	list_for_each_entry(session, &ihost->sessions, host_list) {
+-		if ((channel == SCAN_WILD_CARD ||
+-		     channel == session->channel) &&
++		if ((channel == SCAN_WILD_CARD || channel == 0) &&
+ 		    (id == SCAN_WILD_CARD || id == session->target_id))
+-			scsi_scan_target(&session->dev, session->channel,
++			scsi_scan_target(&session->dev, 0,
+ 					 session->target_id, lun, 1);
+ 	}
+ 	mutex_unlock(&ihost->mutex);
+@@ -297,7 +296,7 @@ EXPORT_SYMBOL_GPL(iscsi_block_session);
+  **/
+ struct iscsi_cls_session *
+ iscsi_create_session(struct Scsi_Host *shost,
+-		     struct iscsi_transport *transport, int channel)
++		     struct iscsi_transport *transport)
+ {
+ 	struct iscsi_host *ihost;
+ 	struct iscsi_cls_session *session;
+@@ -322,7 +321,6 @@ iscsi_create_session(struct Scsi_Host *shost,
+ 	ihost = shost->shost_data;
+ 
+ 	session->sid = iscsi_session_nr++;
+-	session->channel = channel;
+ 	session->target_id = ihost->next_target_id++;
+ 
+ 	snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u",
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 05397058a9b8..2e3cb37af047 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -187,7 +187,6 @@ struct iscsi_cls_session {
+ 	struct work_struct recovery_work;
+ 
+ 	int target_id;
+-	int channel;
+ 
+ 	int sid;				/* session id */
+ 	void *dd_data;				/* LLD private data */
+@@ -210,7 +209,7 @@ struct iscsi_host {
+  * session and connection functions that can be used by HW iSCSI LLDs
+  */
+ extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost,
+-				struct iscsi_transport *t, int channel);
++						struct iscsi_transport *t);
+ extern int iscsi_destroy_session(struct iscsi_cls_session *session);
+ extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess,
+ 					    uint32_t cid);

commit f53a88da18e3c04c3ade07bc5eff520ee4259c3e
+Author: Mike Christie 
+Date:   Wed Jun 28 12:00:27 2006 -0500
+
+    [SCSI] iscsi: fix session refcouting
+    
+    iscsi_tcp and iser cannot be rmmod from the kernel when sessions
+    are running because session removal is driven from userspace. For
+    those modules we get a module reference when a session is
+    created then drop it when the session is removed.
+    
+    For qla4xxx, they can jsut remove the sessions from the pci remove
+    function like normal HW drivers, so this patch moves the module
+    reference from the transport class functions shared by all
+    drivers to the libiscsi functions only used be software iscsi
+    modules.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 7c76a989b218..7e6e031cc41b 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1287,13 +1287,18 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
+ 	if (scsi_add_host(shost, NULL))
+ 		goto add_host_fail;
+ 
++	if (!try_module_get(iscsit->owner))
++		goto cls_session_fail;
++
+ 	cls_session = iscsi_create_session(shost, iscsit, 0);
+ 	if (!cls_session)
+-		goto cls_session_fail;
++		goto module_put;
+ 	*(unsigned long*)shost->hostdata = (unsigned long)cls_session;
+ 
+ 	return cls_session;
+ 
++module_put:
++	module_put(iscsit->owner);
+ cls_session_fail:
+ 	scsi_remove_host(shost);
+ add_host_fail:
+@@ -1325,6 +1330,7 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+ 
+ 	iscsi_destroy_session(cls_session);
+ 	scsi_host_put(shost);
++	module_put(cls_session->transport->owner);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_session_teardown);
+ 
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 147c854e1d4d..8717ff51ba4b 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -228,13 +228,11 @@ static struct iscsi_cls_conn *iscsi_conn_lookup(uint32_t sid, uint32_t cid)
+ static void iscsi_session_release(struct device *dev)
+ {
+ 	struct iscsi_cls_session *session = iscsi_dev_to_session(dev);
+-	struct iscsi_transport *transport = session->transport;
+ 	struct Scsi_Host *shost;
+ 
+ 	shost = iscsi_session_to_shost(session);
+ 	scsi_host_put(shost);
+ 	kfree(session);
+-	module_put(transport->owner);
+ }
+ 
+ static int iscsi_is_session_dev(const struct device *dev)
+@@ -305,13 +303,11 @@ iscsi_create_session(struct Scsi_Host *shost,
+ 	struct iscsi_cls_session *session;
+ 	int err;
+ 
+-	if (!try_module_get(transport->owner))
+-		return NULL;
+-
+ 	session = kzalloc(sizeof(*session) + transport->sessiondata_size,
+ 			  GFP_KERNEL);
+ 	if (!session)
+-		goto module_put;
++		return NULL;
++
+ 	session->transport = transport;
+ 	session->recovery_tmo = 120;
+ 	INIT_WORK(&session->recovery_work, session_recovery_timedout, session);
+@@ -349,8 +345,6 @@ iscsi_create_session(struct Scsi_Host *shost,
+ 
+ free_session:
+ 	kfree(session);
+-module_put:
+-	module_put(transport->owner);
+ 	return NULL;
+ }
+ 

commit 5c75b7fcf0c0e3921391fd93f5fa58ec9a6c428f
+Author: Mike Christie 
+Date:   Wed Jun 28 12:00:26 2006 -0500
+
+    [SCSI] iscsi: convert iscsi_tcp to new set/get param fns
+    
+    Convert iscsi_tcp to new lib functions.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index b4743a9ecc80..848fb2aa4ca3 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -2130,19 +2130,21 @@ iscsi_r2tpool_free(struct iscsi_session *session)
+ 
+ static int
+ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
+-		     uint32_t value)
++		     char *buf, int buflen)
+ {
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	struct iscsi_session *session = conn->session;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	int value;
+ 
+ 	switch(param) {
+ 	case ISCSI_PARAM_MAX_RECV_DLENGTH: {
+ 		char *saveptr = tcp_conn->data;
+ 		gfp_t flags = GFP_KERNEL;
+ 
++		sscanf(buf, "%d", &value);
+ 		if (tcp_conn->data_size >= value) {
+-			conn->max_recv_dlength = value;
++			iscsi_set_param(cls_conn, param, buf, buflen);
+ 			break;
+ 		}
+ 
+@@ -2165,15 +2167,12 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
+ 		else
+ 			free_pages((unsigned long)saveptr,
+ 				   get_order(tcp_conn->data_size));
+-		conn->max_recv_dlength = value;
++		iscsi_set_param(cls_conn, param, buf, buflen);
+ 		tcp_conn->data_size = value;
+-		}
+-		break;
+-	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+-		conn->max_xmit_dlength =  value;
+ 		break;
++		}
+ 	case ISCSI_PARAM_HDRDGST_EN:
+-		conn->hdrdgst_en = value;
++		iscsi_set_param(cls_conn, param, buf, buflen);
+ 		tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
+ 		if (conn->hdrdgst_en) {
+ 			tcp_conn->hdr_size += sizeof(__u32);
+@@ -2197,7 +2196,7 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
+ 		}
+ 		break;
+ 	case ISCSI_PARAM_DATADGST_EN:
+-		conn->datadgst_en = value;
++		iscsi_set_param(cls_conn, param, buf, buflen);
+ 		if (conn->datadgst_en) {
+ 			if (!tcp_conn->data_tx_tfm)
+ 				tcp_conn->data_tx_tfm =
+@@ -2220,121 +2219,36 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
+ 		tcp_conn->sendpage = conn->datadgst_en ?
+ 			sock_no_sendpage : tcp_conn->sock->ops->sendpage;
+ 		break;
+-	case ISCSI_PARAM_INITIAL_R2T_EN:
+-		session->initial_r2t_en = value;
+-		break;
+ 	case ISCSI_PARAM_MAX_R2T:
++		sscanf(buf, "%d", &value);
+ 		if (session->max_r2t == roundup_pow_of_two(value))
+ 			break;
+ 		iscsi_r2tpool_free(session);
+-		session->max_r2t = value;
++		iscsi_set_param(cls_conn, param, buf, buflen);
+ 		if (session->max_r2t & (session->max_r2t - 1))
+ 			session->max_r2t = roundup_pow_of_two(session->max_r2t);
+ 		if (iscsi_r2tpool_alloc(session))
+ 			return -ENOMEM;
+ 		break;
+-	case ISCSI_PARAM_IMM_DATA_EN:
+-		session->imm_data_en = value;
+-		break;
+-	case ISCSI_PARAM_FIRST_BURST:
+-		session->first_burst = value;
+-		break;
+-	case ISCSI_PARAM_MAX_BURST:
+-		session->max_burst = value;
+-		break;
+-	case ISCSI_PARAM_PDU_INORDER_EN:
+-		session->pdu_inorder_en = value;
+-		break;
+-	case ISCSI_PARAM_DATASEQ_INORDER_EN:
+-		session->dataseq_inorder_en = value;
+-		break;
+-	case ISCSI_PARAM_ERL:
+-		session->erl = value;
+-		break;
+-	case ISCSI_PARAM_IFMARKER_EN:
+-		BUG_ON(value);
+-		session->ifmarker_en = value;
+-		break;
+-	case ISCSI_PARAM_OFMARKER_EN:
+-		BUG_ON(value);
+-		session->ofmarker_en = value;
+-		break;
+-	case ISCSI_PARAM_EXP_STATSN:
+-		conn->exp_statsn = value;
+-		break;
+-	default:
+-		break;
+-	}
+-
+-	return 0;
+-}
+-
+-static int
+-iscsi_session_get_param(struct iscsi_cls_session *cls_session,
+-			enum iscsi_param param, uint32_t *value)
+-{
+-	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+-	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+-
+-	switch(param) {
+-	case ISCSI_PARAM_INITIAL_R2T_EN:
+-		*value = session->initial_r2t_en;
+-		break;
+-	case ISCSI_PARAM_MAX_R2T:
+-		*value = session->max_r2t;
+-		break;
+-	case ISCSI_PARAM_IMM_DATA_EN:
+-		*value = session->imm_data_en;
+-		break;
+-	case ISCSI_PARAM_FIRST_BURST:
+-		*value = session->first_burst;
+-		break;
+-	case ISCSI_PARAM_MAX_BURST:
+-		*value = session->max_burst;
+-		break;
+-	case ISCSI_PARAM_PDU_INORDER_EN:
+-		*value = session->pdu_inorder_en;
+-		break;
+-	case ISCSI_PARAM_DATASEQ_INORDER_EN:
+-		*value = session->dataseq_inorder_en;
+-		break;
+-	case ISCSI_PARAM_ERL:
+-		*value = session->erl;
+-		break;
+-	case ISCSI_PARAM_IFMARKER_EN:
+-		*value = session->ifmarker_en;
+-		break;
+-	case ISCSI_PARAM_OFMARKER_EN:
+-		*value = session->ofmarker_en;
+-		break;
+ 	default:
+-		return -EINVAL;
++		return iscsi_set_param(cls_conn, param, buf, buflen);
+ 	}
+ 
+ 	return 0;
+ }
+ 
+ static int
+-iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+-		     enum iscsi_param param, uint32_t *value)
++iscsi_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,
++			 enum iscsi_param param, char *buf)
+ {
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	struct inet_sock *inet;
++	struct ipv6_pinfo *np;
++	struct sock *sk;
++	int len;
+ 
+ 	switch(param) {
+-	case ISCSI_PARAM_MAX_RECV_DLENGTH:
+-		*value = conn->max_recv_dlength;
+-		break;
+-	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+-		*value = conn->max_xmit_dlength;
+-		break;
+-	case ISCSI_PARAM_HDRDGST_EN:
+-		*value = conn->hdrdgst_en;
+-		break;
+-	case ISCSI_PARAM_DATADGST_EN:
+-		*value = conn->datadgst_en;
+-		break;
+ 	case ISCSI_PARAM_CONN_PORT:
+ 		mutex_lock(&conn->xmitmutex);
+ 		if (!tcp_conn->sock) {
+@@ -2343,30 +2257,9 @@ iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ 		}
+ 
+ 		inet = inet_sk(tcp_conn->sock->sk);
+-		*value = be16_to_cpu(inet->dport);
++		len = sprintf(buf, "%hu\n", be16_to_cpu(inet->dport));
+ 		mutex_unlock(&conn->xmitmutex);
+-	case ISCSI_PARAM_EXP_STATSN:
+-		*value = conn->exp_statsn;
+ 		break;
+-	default:
+-		return -EINVAL;
+-	}
+-
+-	return 0;
+-}
+-
+-static int
+-iscsi_conn_get_str_param(struct iscsi_cls_conn *cls_conn,
+-			 enum iscsi_param param, char *buf)
+-{
+-	struct iscsi_conn *conn = cls_conn->dd_data;
+-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+-	struct sock *sk;
+-	struct inet_sock *inet;
+-	struct ipv6_pinfo *np;
+-	int len = 0;
+-
+-	switch (param) {
+ 	case ISCSI_PARAM_CONN_ADDRESS:
+ 		mutex_lock(&conn->xmitmutex);
+ 		if (!tcp_conn->sock) {
+@@ -2388,7 +2281,7 @@ iscsi_conn_get_str_param(struct iscsi_cls_conn *cls_conn,
+ 		mutex_unlock(&conn->xmitmutex);
+ 		break;
+ 	default:
+-		return -EINVAL;
++		return iscsi_conn_get_param(cls_conn, param, buf);
+ 	}
+ 
+ 	return len;
+@@ -2501,7 +2394,11 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 				  ISCSI_ERL |
+ 				  ISCSI_CONN_PORT |
+ 				  ISCSI_CONN_ADDRESS |
+-				  ISCSI_EXP_STATSN,
++				  ISCSI_EXP_STATSN |
++				  ISCSI_PERSISTENT_PORT |
++				  ISCSI_PERSISTENT_ADDRESS |
++				  ISCSI_TARGET_NAME |
++				  ISCSI_TPGT,
+ 	.host_template		= &iscsi_sht,
+ 	.conndata_size		= sizeof(struct iscsi_conn),
+ 	.max_conn		= 1,
+@@ -2514,8 +2411,7 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 	.bind_conn		= iscsi_tcp_conn_bind,
+ 	.destroy_conn		= iscsi_tcp_conn_destroy,
+ 	.set_param		= iscsi_conn_set_param,
+-	.get_conn_param		= iscsi_conn_get_param,
+-	.get_conn_str_param	= iscsi_conn_get_str_param,
++	.get_conn_param		= iscsi_tcp_conn_get_param,
+ 	.get_session_param	= iscsi_session_get_param,
+ 	.start_conn		= iscsi_conn_start,
+ 	.stop_conn		= iscsi_conn_stop,

commit 358ff019b89aa530ab6c0dd139d8089c932b103f
+Author: Mike Christie 
+Date:   Wed Jun 28 12:00:25 2006 -0500
+
+    [SCSI] iscsi: convert iser to new set/get param fns
+    
+    Convert iser to libiscsi get/set param functions.
+    Fix bugs in it returning old error return values and
+    have it expose exp_statsn.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 4c3f2de2a06e..d277fdff5dc1 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -438,159 +438,50 @@ iscsi_iser_session_create(struct iscsi_transport *iscsit,
+ }
+ 
+ static int
+-iscsi_iser_conn_set_param(struct iscsi_cls_conn *cls_conn,
+-			  enum iscsi_param param, uint32_t value)
++iscsi_iser_set_param(struct iscsi_cls_conn *cls_conn,
++		     enum iscsi_param param, char *buf, int buflen)
+ {
+-	struct iscsi_conn *conn = cls_conn->dd_data;
+-	struct iscsi_session *session = conn->session;
+-
+-	spin_lock_bh(&session->lock);
+-	if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE &&
+-	    conn->stop_stage != STOP_CONN_RECOVER) {
+-		printk(KERN_ERR "iscsi_iser: can not change parameter [%d]\n",
+-		       param);
+-		spin_unlock_bh(&session->lock);
+-		return 0;
+-	}
+-	spin_unlock_bh(&session->lock);
++	int value;
+ 
+ 	switch (param) {
+ 	case ISCSI_PARAM_MAX_RECV_DLENGTH:
+ 		/* TBD */
+ 		break;
+-	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+-		conn->max_xmit_dlength =  value;
+-		break;
+ 	case ISCSI_PARAM_HDRDGST_EN:
++		sscanf(buf, "%d", &value);
+ 		if (value) {
+ 			printk(KERN_ERR "DataDigest wasn't negotiated to None");
+ 			return -EPROTO;
+ 		}
+ 		break;
+ 	case ISCSI_PARAM_DATADGST_EN:
++		sscanf(buf, "%d", &value);
+ 		if (value) {
+ 			printk(KERN_ERR "DataDigest wasn't negotiated to None");
+ 			return -EPROTO;
+ 		}
+ 		break;
+-	case ISCSI_PARAM_INITIAL_R2T_EN:
+-		session->initial_r2t_en = value;
+-		break;
+-	case ISCSI_PARAM_IMM_DATA_EN:
+-		session->imm_data_en = value;
+-		break;
+-	case ISCSI_PARAM_FIRST_BURST:
+-		session->first_burst = value;
+-		break;
+-	case ISCSI_PARAM_MAX_BURST:
+-		session->max_burst = value;
+-		break;
+-	case ISCSI_PARAM_PDU_INORDER_EN:
+-		session->pdu_inorder_en = value;
+-		break;
+-	case ISCSI_PARAM_DATASEQ_INORDER_EN:
+-		session->dataseq_inorder_en = value;
+-		break;
+-	case ISCSI_PARAM_ERL:
+-		session->erl = value;
+-		break;
+ 	case ISCSI_PARAM_IFMARKER_EN:
++		sscanf(buf, "%d", &value);
+ 		if (value) {
+ 			printk(KERN_ERR "IFMarker wasn't negotiated to No");
+ 			return -EPROTO;
+ 		}
+ 		break;
+ 	case ISCSI_PARAM_OFMARKER_EN:
++		sscanf(buf, "%d", &value);
+ 		if (value) {
+ 			printk(KERN_ERR "OFMarker wasn't negotiated to No");
+ 			return -EPROTO;
+ 		}
+ 		break;
+ 	default:
+-		break;
+-	}
+-
+-	return 0;
+-}
+-
+-static int
+-iscsi_iser_session_get_param(struct iscsi_cls_session *cls_session,
+-			     enum iscsi_param param, uint32_t *value)
+-{
+-	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+-	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+-
+-	switch (param) {
+-	case ISCSI_PARAM_INITIAL_R2T_EN:
+-		*value = session->initial_r2t_en;
+-		break;
+-	case ISCSI_PARAM_MAX_R2T:
+-		*value = session->max_r2t;
+-		break;
+-	case ISCSI_PARAM_IMM_DATA_EN:
+-		*value = session->imm_data_en;
+-		break;
+-	case ISCSI_PARAM_FIRST_BURST:
+-		*value = session->first_burst;
+-		break;
+-	case ISCSI_PARAM_MAX_BURST:
+-		*value = session->max_burst;
+-		break;
+-	case ISCSI_PARAM_PDU_INORDER_EN:
+-		*value = session->pdu_inorder_en;
+-		break;
+-	case ISCSI_PARAM_DATASEQ_INORDER_EN:
+-		*value = session->dataseq_inorder_en;
+-		break;
+-	case ISCSI_PARAM_ERL:
+-		*value = session->erl;
+-		break;
+-	case ISCSI_PARAM_IFMARKER_EN:
+-		*value = 0;
+-		break;
+-	case ISCSI_PARAM_OFMARKER_EN:
+-		*value = 0;
+-		break;
+-	default:
+-		return ISCSI_ERR_PARAM_NOT_FOUND;
+-	}
+-
+-	return 0;
+-}
+-
+-static int
+-iscsi_iser_conn_get_param(struct iscsi_cls_conn *cls_conn,
+-			  enum iscsi_param param, uint32_t *value)
+-{
+-	struct iscsi_conn *conn = cls_conn->dd_data;
+-
+-	switch(param) {
+-	case ISCSI_PARAM_MAX_RECV_DLENGTH:
+-		*value = conn->max_recv_dlength;
+-		break;
+-	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+-		*value = conn->max_xmit_dlength;
+-		break;
+-	case ISCSI_PARAM_HDRDGST_EN:
+-		*value = 0;
+-		break;
+-	case ISCSI_PARAM_DATADGST_EN:
+-		*value = 0;
+-		break;
+-	/*case ISCSI_PARAM_TARGET_RECV_DLENGTH:
+-		*value = conn->target_recv_dlength;
+-		break;
+-	case ISCSI_PARAM_INITIATOR_RECV_DLENGTH:
+-		*value = conn->initiator_recv_dlength;
+-		break;*/
+-	default:
+-		return ISCSI_ERR_PARAM_NOT_FOUND;
++		return iscsi_set_param(cls_conn, param, buf, buflen);
+ 	}
+ 
+ 	return 0;
+ }
+ 
+-
+ static void
+ iscsi_iser_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats)
+ {
+@@ -702,7 +593,12 @@ static struct iscsi_transport iscsi_iser_transport = {
+ 				  ISCSI_FIRST_BURST |
+ 				  ISCSI_MAX_BURST |
+ 				  ISCSI_PDU_INORDER_EN |
+-				  ISCSI_DATASEQ_INORDER_EN,
++				  ISCSI_DATASEQ_INORDER_EN |
++				  ISCSI_EXP_STATSN |
++				  ISCSI_PERSISTENT_PORT |
++				  ISCSI_PERSISTENT_ADDRESS |
++				  ISCSI_TARGET_NAME |
++				  ISCSI_TPGT,
+ 	.host_template          = &iscsi_iser_sht,
+ 	.conndata_size		= sizeof(struct iscsi_conn),
+ 	.max_lun                = ISCSI_ISER_MAX_LUN,
+@@ -714,9 +610,9 @@ static struct iscsi_transport iscsi_iser_transport = {
+ 	.create_conn            = iscsi_iser_conn_create,
+ 	.bind_conn              = iscsi_iser_conn_bind,
+ 	.destroy_conn           = iscsi_iser_conn_destroy,
+-	.set_param              = iscsi_iser_conn_set_param,
+-	.get_conn_param		= iscsi_iser_conn_get_param,
+-	.get_session_param	= iscsi_iser_session_get_param,
++	.set_param              = iscsi_iser_set_param,
++	.get_conn_param		= iscsi_conn_get_param,
++	.get_session_param	= iscsi_session_get_param,
+ 	.start_conn             = iscsi_iser_conn_start,
+ 	.stop_conn              = iscsi_conn_stop,
+ 	/* these are called as part of conn recovery */

commit a54a52caad4bd6166cb7fa64e4e93031fa2fda5d
+Author: Mike Christie 
+Date:   Wed Jun 28 12:00:23 2006 -0500
+
+    [SCSI] iscsi: fixup set/get param functions
+    
+    Reduce duplication in the software iscsi_transport modules by
+    adding a libiscsi function to handle the common grunt work.
+    
+    This also has the drivers return specifc -EXXX values for different
+    errors so userspace can finally handle them in a sane way.
+    
+    Also just pass the sysfs buffers to the drivers so HW iscsi can
+    get/set its string values, like targetname, and initiatorname.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 2673a11a9495..7c76a989b218 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1697,6 +1697,185 @@ int iscsi_conn_bind(struct iscsi_cls_session *cls_session,
+ }
+ EXPORT_SYMBOL_GPL(iscsi_conn_bind);
+ 
++
++int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
++		    enum iscsi_param param, char *buf, int buflen)
++{
++	struct iscsi_conn *conn = cls_conn->dd_data;
++	struct iscsi_session *session = conn->session;
++	uint32_t value;
++
++	switch(param) {
++	case ISCSI_PARAM_MAX_RECV_DLENGTH:
++		sscanf(buf, "%d", &conn->max_recv_dlength);
++		break;
++	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
++		sscanf(buf, "%d", &conn->max_xmit_dlength);
++		break;
++	case ISCSI_PARAM_HDRDGST_EN:
++		sscanf(buf, "%d", &conn->hdrdgst_en);
++		break;
++	case ISCSI_PARAM_DATADGST_EN:
++		sscanf(buf, "%d", &conn->datadgst_en);
++		break;
++	case ISCSI_PARAM_INITIAL_R2T_EN:
++		sscanf(buf, "%d", &session->initial_r2t_en);
++		break;
++	case ISCSI_PARAM_MAX_R2T:
++		sscanf(buf, "%d", &session->max_r2t);
++		break;
++	case ISCSI_PARAM_IMM_DATA_EN:
++		sscanf(buf, "%d", &session->imm_data_en);
++		break;
++	case ISCSI_PARAM_FIRST_BURST:
++		sscanf(buf, "%d", &session->first_burst);
++		break;
++	case ISCSI_PARAM_MAX_BURST:
++		sscanf(buf, "%d", &session->max_burst);
++		break;
++	case ISCSI_PARAM_PDU_INORDER_EN:
++		sscanf(buf, "%d", &session->pdu_inorder_en);
++		break;
++	case ISCSI_PARAM_DATASEQ_INORDER_EN:
++		sscanf(buf, "%d", &session->dataseq_inorder_en);
++		break;
++	case ISCSI_PARAM_ERL:
++		sscanf(buf, "%d", &session->erl);
++		break;
++	case ISCSI_PARAM_IFMARKER_EN:
++		sscanf(buf, "%d", &value);
++		BUG_ON(value);
++		break;
++	case ISCSI_PARAM_OFMARKER_EN:
++		sscanf(buf, "%d", &value);
++		BUG_ON(value);
++		break;
++	case ISCSI_PARAM_EXP_STATSN:
++		sscanf(buf, "%u", &conn->exp_statsn);
++		break;
++	case ISCSI_PARAM_TARGET_NAME:
++		/* this should not change between logins */
++		if (session->targetname)
++			break;
++
++		session->targetname = kstrdup(buf, GFP_KERNEL);
++		if (!session->targetname)
++			return -ENOMEM;
++		break;
++	case ISCSI_PARAM_TPGT:
++		sscanf(buf, "%d", &session->tpgt);
++		break;
++	case ISCSI_PARAM_PERSISTENT_PORT:
++		sscanf(buf, "%d", &conn->persistent_port);
++		break;
++	case ISCSI_PARAM_PERSISTENT_ADDRESS:
++		/*
++		 * this is the address returned in discovery so it should
++		 * not change between logins.
++		 */
++		if (conn->persistent_address)
++			break;
++
++		conn->persistent_address = kstrdup(buf, GFP_KERNEL);
++		if (!conn->persistent_address)
++			return -ENOMEM;
++		break;
++	default:
++		return -ENOSYS;
++	}
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(iscsi_set_param);
++
++int iscsi_session_get_param(struct iscsi_cls_session *cls_session,
++			    enum iscsi_param param, char *buf)
++{
++	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
++	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
++	int len;
++
++	switch(param) {
++	case ISCSI_PARAM_INITIAL_R2T_EN:
++		len = sprintf(buf, "%d\n", session->initial_r2t_en);
++		break;
++	case ISCSI_PARAM_MAX_R2T:
++		len = sprintf(buf, "%hu\n", session->max_r2t);
++		break;
++	case ISCSI_PARAM_IMM_DATA_EN:
++		len = sprintf(buf, "%d\n", session->imm_data_en);
++		break;
++	case ISCSI_PARAM_FIRST_BURST:
++		len = sprintf(buf, "%u\n", session->first_burst);
++		break;
++	case ISCSI_PARAM_MAX_BURST:
++		len = sprintf(buf, "%u\n", session->max_burst);
++		break;
++	case ISCSI_PARAM_PDU_INORDER_EN:
++		len = sprintf(buf, "%d\n", session->pdu_inorder_en);
++		break;
++	case ISCSI_PARAM_DATASEQ_INORDER_EN:
++		len = sprintf(buf, "%d\n", session->dataseq_inorder_en);
++		break;
++	case ISCSI_PARAM_ERL:
++		len = sprintf(buf, "%d\n", session->erl);
++		break;
++	case ISCSI_PARAM_TARGET_NAME:
++		len = sprintf(buf, "%s\n", session->targetname);
++		break;
++	case ISCSI_PARAM_TPGT:
++		len = sprintf(buf, "%d\n", session->tpgt);
++		break;
++	default:
++		return -ENOSYS;
++	}
++
++	return len;
++}
++EXPORT_SYMBOL_GPL(iscsi_session_get_param);
++
++int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
++			 enum iscsi_param param, char *buf)
++{
++	struct iscsi_conn *conn = cls_conn->dd_data;
++	int len;
++
++	switch(param) {
++	case ISCSI_PARAM_MAX_RECV_DLENGTH:
++		len = sprintf(buf, "%u\n", conn->max_recv_dlength);
++		break;
++	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
++		len = sprintf(buf, "%u\n", conn->max_xmit_dlength);
++		break;
++	case ISCSI_PARAM_HDRDGST_EN:
++		len = sprintf(buf, "%d\n", conn->hdrdgst_en);
++		break;
++	case ISCSI_PARAM_DATADGST_EN:
++		len = sprintf(buf, "%d\n", conn->datadgst_en);
++		break;
++	case ISCSI_PARAM_IFMARKER_EN:
++		len = sprintf(buf, "%d\n", conn->ifmarker_en);
++		break;
++	case ISCSI_PARAM_OFMARKER_EN:
++		len = sprintf(buf, "%d\n", conn->ofmarker_en);
++		break;
++	case ISCSI_PARAM_EXP_STATSN:
++		len = sprintf(buf, "%u\n", conn->exp_statsn);
++		break;
++	case ISCSI_PARAM_PERSISTENT_PORT:
++		len = sprintf(buf, "%d\n", conn->persistent_port);
++		break;
++	case ISCSI_PARAM_PERSISTENT_ADDRESS:
++		len = sprintf(buf, "%s\n", conn->persistent_address);
++		break;
++	default:
++		return -ENOSYS;
++	}
++
++	return len;
++}
++EXPORT_SYMBOL_GPL(iscsi_conn_get_param);
++
+ MODULE_AUTHOR("Mike Christie");
+ MODULE_DESCRIPTION("iSCSI library functions");
+ MODULE_LICENSE("GPL");
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 99e76d458290..147c854e1d4d 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -233,7 +233,6 @@ static void iscsi_session_release(struct device *dev)
+ 
+ 	shost = iscsi_session_to_shost(session);
+ 	scsi_host_put(shost);
+-	kfree(session->targetname);
+ 	kfree(session);
+ 	module_put(transport->owner);
+ }
+@@ -388,7 +387,6 @@ static void iscsi_conn_release(struct device *dev)
+ 	struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev);
+ 	struct device *parent = conn->dev.parent;
+ 
+-	kfree(conn->persistent_address);
+ 	kfree(conn);
+ 	put_device(parent);
+ }
+@@ -877,23 +875,13 @@ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev
+ 	return 0;
+ }
+ 
+-static void
+-iscsi_copy_param(struct iscsi_uevent *ev, uint32_t *value, char *data)
+-{
+-	if (ev->u.set_param.len != sizeof(uint32_t))
+-		BUG();
+-	memcpy(value, data, min_t(uint32_t, sizeof(uint32_t),
+-		ev->u.set_param.len));
+-}
+-
+ static int
+ iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+ {
+ 	char *data = (char*)ev + sizeof(*ev);
+ 	struct iscsi_cls_conn *conn;
+ 	struct iscsi_cls_session *session;
+-	int err = 0;
+-	uint32_t value = 0;
++	int err = 0, value = 0;
+ 
+ 	session = iscsi_session_lookup(ev->u.set_param.sid);
+ 	conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid);
+@@ -902,42 +890,13 @@ iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+ 
+ 	switch (ev->u.set_param.param) {
+ 	case ISCSI_PARAM_SESS_RECOVERY_TMO:
+-		iscsi_copy_param(ev, &value, data);
++		sscanf(data, "%d", &value);
+ 		if (value != 0)
+ 			session->recovery_tmo = value;
+ 		break;
+-	case ISCSI_PARAM_TARGET_NAME:
+-		/* this should not change between logins */
+-		if (session->targetname)
+-			return 0;
+-
+-		session->targetname = kstrdup(data, GFP_KERNEL);
+-		if (!session->targetname)
+-			return -ENOMEM;
+-		break;
+-	case ISCSI_PARAM_TPGT:
+-		iscsi_copy_param(ev, &value, data);
+-		session->tpgt = value;
+-		break;
+-	case ISCSI_PARAM_PERSISTENT_PORT:
+-		iscsi_copy_param(ev, &value, data);
+-		conn->persistent_port = value;
+-		break;
+-	case ISCSI_PARAM_PERSISTENT_ADDRESS:
+-		/*
+-		 * this is the address returned in discovery so it should
+-		 * not change between logins.
+-		 */
+-		if (conn->persistent_address)
+-			return 0;
+-
+-		conn->persistent_address = kstrdup(data, GFP_KERNEL);
+-		if (!conn->persistent_address)
+-			return -ENOMEM;
+-		break;
+ 	default:
+-		iscsi_copy_param(ev, &value, data);
+-		err = transport->set_param(conn, ev->u.set_param.param, value);
++		err = transport->set_param(conn, ev->u.set_param.param,
++					   data, ev->u.set_param.len);
+ 	}
+ 
+ 	return err;
+@@ -1165,49 +1124,31 @@ struct class_device_attribute class_device_attr_##_prefix##_##_name =	\
+ /*
+  * iSCSI connection attrs
+  */
+-#define iscsi_conn_int_attr_show(param, format)				\
++#define iscsi_conn_attr_show(param)					\
+ static ssize_t								\
+-show_conn_int_param_##param(struct class_device *cdev, char *buf)	\
++show_conn_param_##param(struct class_device *cdev, char *buf)		\
+ {									\
+-	uint32_t value = 0;						\
+ 	struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev);		\
+ 	struct iscsi_transport *t = conn->transport;			\
+-									\
+-	t->get_conn_param(conn, param, &value);				\
+-	return snprintf(buf, 20, format"\n", value);			\
++	return t->get_conn_param(conn, param, buf);			\
+ }
+ 
+-#define iscsi_conn_int_attr(field, param, format)			\
+-	iscsi_conn_int_attr_show(param, format)				\
+-static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_int_param_##param, \
++#define iscsi_conn_attr(field, param)					\
++	iscsi_conn_attr_show(param)					\
++static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_param_##param,	\
+ 			NULL);
+ 
+-iscsi_conn_int_attr(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH, "%u");
+-iscsi_conn_int_attr(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH, "%u");
+-iscsi_conn_int_attr(header_digest, ISCSI_PARAM_HDRDGST_EN, "%d");
+-iscsi_conn_int_attr(data_digest, ISCSI_PARAM_DATADGST_EN, "%d");
+-iscsi_conn_int_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN, "%d");
+-iscsi_conn_int_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN, "%d");
+-iscsi_conn_int_attr(persistent_port, ISCSI_PARAM_PERSISTENT_PORT, "%d");
+-iscsi_conn_int_attr(port, ISCSI_PARAM_CONN_PORT, "%d");
+-iscsi_conn_int_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN, "%u");
+-
+-#define iscsi_conn_str_attr_show(param)					\
+-static ssize_t								\
+-show_conn_str_param_##param(struct class_device *cdev, char *buf)	\
+-{									\
+-	struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev);		\
+-	struct iscsi_transport *t = conn->transport;			\
+-	return t->get_conn_str_param(conn, param, buf);			\
+-}
+-
+-#define iscsi_conn_str_attr(field, param)				\
+-	iscsi_conn_str_attr_show(param)					\
+-static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_str_param_##param, \
+-			NULL);
+-
+-iscsi_conn_str_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS);
+-iscsi_conn_str_attr(address, ISCSI_PARAM_CONN_ADDRESS);
++iscsi_conn_attr(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH);
++iscsi_conn_attr(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH);
++iscsi_conn_attr(header_digest, ISCSI_PARAM_HDRDGST_EN);
++iscsi_conn_attr(data_digest, ISCSI_PARAM_DATADGST_EN);
++iscsi_conn_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN);
++iscsi_conn_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN);
++iscsi_conn_attr(persistent_port, ISCSI_PARAM_PERSISTENT_PORT);
++iscsi_conn_attr(port, ISCSI_PARAM_CONN_PORT);
++iscsi_conn_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN);
++iscsi_conn_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS);
++iscsi_conn_attr(address, ISCSI_PARAM_CONN_ADDRESS);
+ 
+ #define iscsi_cdev_to_session(_cdev) \
+ 	iscsi_dev_to_session(_cdev->dev)
+@@ -1215,61 +1156,36 @@ iscsi_conn_str_attr(address, ISCSI_PARAM_CONN_ADDRESS);
+ /*
+  * iSCSI session attrs
+  */
+-#define iscsi_session_int_attr_show(param, format)			\
+-static ssize_t								\
+-show_session_int_param_##param(struct class_device *cdev, char *buf)	\
+-{									\
+-	uint32_t value = 0;						\
+-	struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev);	\
+-	struct iscsi_transport *t = session->transport;			\
+-									\
+-	t->get_session_param(session, param, &value);			\
+-	return snprintf(buf, 20, format"\n", value);			\
+-}
+-
+-#define iscsi_session_int_attr(field, param, format)			\
+-	iscsi_session_int_attr_show(param, format)			\
+-static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_int_param_##param, \
+-			NULL);
+-
+-iscsi_session_int_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN, "%d");
+-iscsi_session_int_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T, "%hu");
+-iscsi_session_int_attr(immediate_data, ISCSI_PARAM_IMM_DATA_EN, "%d");
+-iscsi_session_int_attr(first_burst_len, ISCSI_PARAM_FIRST_BURST, "%u");
+-iscsi_session_int_attr(max_burst_len, ISCSI_PARAM_MAX_BURST, "%u");
+-iscsi_session_int_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN, "%d");
+-iscsi_session_int_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN, "%d");
+-iscsi_session_int_attr(erl, ISCSI_PARAM_ERL, "%d");
+-iscsi_session_int_attr(tpgt, ISCSI_PARAM_TPGT, "%d");
+-
+-#define iscsi_session_str_attr_show(param)				\
++#define iscsi_session_attr_show(param)					\
+ static ssize_t								\
+-show_session_str_param_##param(struct class_device *cdev, char *buf)	\
++show_session_param_##param(struct class_device *cdev, char *buf)	\
+ {									\
+ 	struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
+ 	struct iscsi_transport *t = session->transport;			\
+-	return t->get_session_str_param(session, param, buf);		\
++	return t->get_session_param(session, param, buf);		\
+ }
+ 
+-#define iscsi_session_str_attr(field, param)				\
+-	iscsi_session_str_attr_show(param)				\
+-static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_str_param_##param, \
++#define iscsi_session_attr(field, param)				\
++	iscsi_session_attr_show(param)					\
++static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_param_##param, \
+ 			NULL);
+ 
+-iscsi_session_str_attr(targetname, ISCSI_PARAM_TARGET_NAME);
++iscsi_session_attr(targetname, ISCSI_PARAM_TARGET_NAME);
++iscsi_session_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN);
++iscsi_session_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T);
++iscsi_session_attr(immediate_data, ISCSI_PARAM_IMM_DATA_EN);
++iscsi_session_attr(first_burst_len, ISCSI_PARAM_FIRST_BURST);
++iscsi_session_attr(max_burst_len, ISCSI_PARAM_MAX_BURST);
++iscsi_session_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN);
++iscsi_session_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN);
++iscsi_session_attr(erl, ISCSI_PARAM_ERL);
++iscsi_session_attr(tpgt, ISCSI_PARAM_TPGT);
+ 
+-/*
+- * Private session and conn attrs. userspace uses several iscsi values
+- * to identify each session between reboots. Some of these values may not
+- * be present in the iscsi_transport/LLD driver becuase userspace handles
+- * login (and failback for login redirect) so for these type of drivers
+- * the class manages the attrs and values for the iscsi_transport/LLD
+- */
+ #define iscsi_priv_session_attr_show(field, format)			\
+ static ssize_t								\
+-show_priv_session_##field(struct class_device *cdev, char *buf)	\
++show_priv_session_##field(struct class_device *cdev, char *buf)		\
+ {									\
+-	struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
++	struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev);\
+ 	return sprintf(buf, format"\n", session->field);		\
+ }
+ 
+@@ -1277,31 +1193,15 @@ show_priv_session_##field(struct class_device *cdev, char *buf)	\
+ 	iscsi_priv_session_attr_show(field, format)			\
+ static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO, show_priv_session_##field, \
+ 			NULL)
+-iscsi_priv_session_attr(targetname, "%s");
+-iscsi_priv_session_attr(tpgt, "%d");
+ iscsi_priv_session_attr(recovery_tmo, "%d");
+ 
+-#define iscsi_priv_conn_attr_show(field, format)			\
+-static ssize_t								\
+-show_priv_conn_##field(struct class_device *cdev, char *buf)		\
+-{									\
+-	struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev);		\
+-	return sprintf(buf, format"\n", conn->field);			\
+-}
+-
+-#define iscsi_priv_conn_attr(field, format)				\
+-	iscsi_priv_conn_attr_show(field, format)			\
+-static ISCSI_CLASS_ATTR(priv_conn, field, S_IRUGO, show_priv_conn_##field, \
+-			NULL)
+-iscsi_priv_conn_attr(persistent_address, "%s");
+-iscsi_priv_conn_attr(persistent_port, "%d");
+-
+ #define SETUP_PRIV_SESSION_RD_ATTR(field)				\
+ do {									\
+ 	priv->session_attrs[count] = &class_device_attr_priv_sess_##field; \
+ 	count++;							\
+ } while (0)
+ 
++
+ #define SETUP_SESSION_RD_ATTR(field, param_flag)			\
+ do {									\
+ 	if (tt->param_mask & param_flag) {				\
+@@ -1310,12 +1210,6 @@ do {									\
+ 	}								\
+ } while (0)
+ 
+-#define SETUP_PRIV_CONN_RD_ATTR(field)					\
+-do {									\
+-	priv->conn_attrs[count] = &class_device_attr_priv_conn_##field; \
+-	count++;							\
+-} while (0)
+-
+ #define SETUP_CONN_RD_ATTR(field, param_flag)				\
+ do {									\
+ 	if (tt->param_mask & param_flag) {				\
+@@ -1442,16 +1336,8 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 	SETUP_CONN_RD_ATTR(address, ISCSI_CONN_ADDRESS);
+ 	SETUP_CONN_RD_ATTR(port, ISCSI_CONN_PORT);
+ 	SETUP_CONN_RD_ATTR(exp_statsn, ISCSI_EXP_STATSN);
+-
+-	if (tt->param_mask & ISCSI_PERSISTENT_ADDRESS)
+-		SETUP_CONN_RD_ATTR(persistent_address, ISCSI_PERSISTENT_ADDRESS);
+-	else
+-		SETUP_PRIV_CONN_RD_ATTR(persistent_address);
+-
+-	if (tt->param_mask & ISCSI_PERSISTENT_PORT)
+-		SETUP_CONN_RD_ATTR(persistent_port, ISCSI_PERSISTENT_PORT);
+-	else
+-		SETUP_PRIV_CONN_RD_ATTR(persistent_port);
++	SETUP_CONN_RD_ATTR(persistent_address, ISCSI_PERSISTENT_ADDRESS);
++	SETUP_CONN_RD_ATTR(persistent_port, ISCSI_PERSISTENT_PORT);
+ 
+ 	BUG_ON(count > ISCSI_CONN_ATTRS);
+ 	priv->conn_attrs[count] = NULL;
+@@ -1471,18 +1357,10 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 	SETUP_SESSION_RD_ATTR(data_pdu_in_order, ISCSI_PDU_INORDER_EN);
+ 	SETUP_SESSION_RD_ATTR(data_seq_in_order, ISCSI_DATASEQ_INORDER_EN);
+ 	SETUP_SESSION_RD_ATTR(erl, ISCSI_ERL);
++	SETUP_SESSION_RD_ATTR(targetname, ISCSI_TARGET_NAME);
++	SETUP_SESSION_RD_ATTR(tpgt, ISCSI_TPGT);
+ 	SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo);
+ 
+-	if (tt->param_mask & ISCSI_TARGET_NAME)
+-		SETUP_SESSION_RD_ATTR(targetname, ISCSI_TARGET_NAME);
+-	else
+-		SETUP_PRIV_SESSION_RD_ATTR(targetname);
+-
+-	if (tt->param_mask & ISCSI_TPGT)
+-		SETUP_SESSION_RD_ATTR(tpgt, ISCSI_TPGT);
+-	else
+-		SETUP_PRIV_SESSION_RD_ATTR(tpgt);
+-
+ 	BUG_ON(count > ISCSI_SESSION_ATTRS);
+ 	priv->session_attrs[count] = NULL;
+ 
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index cbf7e58bd6f9..ba2760802ded 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -157,6 +157,11 @@ struct iscsi_conn {
+ 	int			max_xmit_dlength; /* target_max_recv_dsl */
+ 	int			hdrdgst_en;
+ 	int			datadgst_en;
++	int			ifmarker_en;
++	int			ofmarker_en;
++	/* values userspace uses to id a conn */
++	int			persistent_port;
++	char			*persistent_address;
+ 
+ 	/* MIB-statistics */
+ 	uint64_t		txdata_octets;
+@@ -196,8 +201,8 @@ struct iscsi_session {
+ 	int			pdu_inorder_en;
+ 	int			dataseq_inorder_en;
+ 	int			erl;
+-	int			ifmarker_en;
+-	int			ofmarker_en;
++	int			tpgt;
++	char			*targetname;
+ 
+ 	/* control data */
+ 	struct iscsi_transport	*tt;
+@@ -240,6 +245,10 @@ iscsi_session_setup(struct iscsi_transport *, struct scsi_transport_template *,
+ extern void iscsi_session_teardown(struct iscsi_cls_session *);
+ extern struct iscsi_session *class_to_transport_session(struct iscsi_cls_session *);
+ extern void iscsi_session_recovery_timedout(struct iscsi_cls_session *);
++extern int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
++			   enum iscsi_param param, char *buf, int buflen);
++extern int iscsi_session_get_param(struct iscsi_cls_session *cls_session,
++				   enum iscsi_param param, char *buf);
+ 
+ #define session_to_cls(_sess) \
+ 	hostdata_session(_sess->host->hostdata)
+@@ -255,6 +264,8 @@ extern void iscsi_conn_stop(struct iscsi_cls_conn *, int);
+ extern int iscsi_conn_bind(struct iscsi_cls_session *, struct iscsi_cls_conn *,
+ 			   int);
+ extern void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err);
++extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
++				enum iscsi_param param, char *buf);
+ 
+ /*
+  * pdu and task processing
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index b95151aec602..05397058a9b8 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -34,6 +34,7 @@ struct iscsi_cls_conn;
+ struct iscsi_conn;
+ struct iscsi_cmd_task;
+ struct iscsi_mgmt_task;
++struct sockaddr;
+ 
+ /**
+  * struct iscsi_transport - iSCSI Transport template
+@@ -46,7 +47,12 @@ struct iscsi_mgmt_task;
+  * @bind_conn:		associate this connection with existing iSCSI session
+  *			and specified transport descriptor
+  * @destroy_conn:	destroy inactive iSCSI connection
+- * @set_param:		set iSCSI Data-Path operational parameter
++ * @set_param:		set iSCSI parameter. Return 0 on success, -ENODATA
++ *			when param is not supported, and a -Exx value on other
++ *			error.
++ * @get_param		get iSCSI parameter. Must return number of bytes
++ *			copied to buffer on success, -ENODATA when param
++ *			is not supported, and a -Exx value on other error
+  * @start_conn:		set connection to be operational
+  * @stop_conn:		suspend/recover/terminate connection
+  * @send_pdu:		send iSCSI PDU, Login, Logout, NOP-Out, Reject, Text.
+@@ -97,15 +103,11 @@ struct iscsi_transport {
+ 	void (*stop_conn) (struct iscsi_cls_conn *conn, int flag);
+ 	void (*destroy_conn) (struct iscsi_cls_conn *conn);
+ 	int (*set_param) (struct iscsi_cls_conn *conn, enum iscsi_param param,
+-			  uint32_t value);
++			  char *buf, int buflen);
+ 	int (*get_conn_param) (struct iscsi_cls_conn *conn,
+-			       enum iscsi_param param, uint32_t *value);
++			       enum iscsi_param param, char *buf);
+ 	int (*get_session_param) (struct iscsi_cls_session *session,
+-				  enum iscsi_param param, uint32_t *value);
+-	int (*get_conn_str_param) (struct iscsi_cls_conn *conn,
+-				   enum iscsi_param param, char *buf);
+-	int (*get_session_str_param) (struct iscsi_cls_session *session,
+-				      enum iscsi_param param, char *buf);
++				  enum iscsi_param param, char *buf);
+ 	int (*send_pdu) (struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
+ 			 char *data, uint32_t data_size);
+ 	void (*get_stats) (struct iscsi_cls_conn *conn,
+@@ -157,13 +159,6 @@ struct iscsi_cls_conn {
+ 	struct iscsi_transport *transport;
+ 	uint32_t cid;			/* connection id */
+ 
+-	/* portal/group values we got during discovery */
+-	char *persistent_address;
+-	int persistent_port;
+-	/* portal/group values we are currently using */
+-	char *address;
+-	int port;
+-
+ 	int active;			/* must be accessed with the connlock */
+ 	struct device dev;		/* sysfs transport/container device */
+ 	struct mempool_zone *z_error;
+@@ -187,10 +182,6 @@ struct iscsi_cls_session {
+ 	struct list_head host_list;
+ 	struct iscsi_transport *transport;
+ 
+-	/* iSCSI values used as unique id by userspace. */
+-	char *targetname;
+-	int tpgt;
+-
+ 	/* recovery fields */
+ 	int recovery_tmo;
+ 	struct work_struct recovery_work;

commit 01cb225dad8da2e717356fab03240e2f4a8d01bf
+Author: Mike Christie 
+Date:   Wed Jun 28 12:00:22 2006 -0500
+
+    [SCSI] iscsi: add target discvery event to transport class
+    
+    Patch from david.somayajulu@qlogic.com:
+    
+    Add target discovery event. We may have a setup where the iscsi traffic
+    is on a different netowrk than the other network traffic. In this case
+    we will want to do discovery though the iscsi card. This patch adds
+    a event to the transport class that can be used by hw iscsi cards that
+    support this.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 5569fdcfd621..99e76d458290 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -977,6 +977,21 @@ iscsi_if_transport_ep(struct iscsi_transport *transport,
+ 	return rc;
+ }
+ 
++static int
++iscsi_tgt_dscvr(struct iscsi_transport *transport,
++		struct iscsi_uevent *ev)
++{
++	struct sockaddr *dst_addr;
++
++	if (!transport->tgt_dscvr)
++		return -EINVAL;
++
++	dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
++	return transport->tgt_dscvr(ev->u.tgt_dscvr.type,
++				    ev->u.tgt_dscvr.host_no,
++				    ev->u.tgt_dscvr.enable, dst_addr);
++}
++
+ static int
+ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ {
+@@ -1065,6 +1080,9 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 	case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
+ 		err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type);
+ 		break;
++	case ISCSI_UEVENT_TGT_DSCVR:
++		err = iscsi_tgt_dscvr(transport, ev);
++		break;
+ 	default:
+ 		err = -EINVAL;
+ 		break;
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index 253797c60095..8813f0f4c624 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -47,12 +47,20 @@ enum iscsi_uevent_e {
+ 	ISCSI_UEVENT_TRANSPORT_EP_POLL		= UEVENT_BASE + 13,
+ 	ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT	= UEVENT_BASE + 14,
+ 
++	ISCSI_UEVENT_TGT_DSCVR		= UEVENT_BASE + 15,
++
+ 	/* up events */
+ 	ISCSI_KEVENT_RECV_PDU		= KEVENT_BASE + 1,
+ 	ISCSI_KEVENT_CONN_ERROR		= KEVENT_BASE + 2,
+ 	ISCSI_KEVENT_IF_ERROR		= KEVENT_BASE + 3,
+ };
+ 
++enum iscsi_tgt_dscvr {
++	ISCSI_TGT_DSCVR_SEND_TARGETS	= 1,
++	ISCSI_TGT_DSCVR_ISNS		= 2,
++	ISCSI_TGT_DSCVR_SLP		= 3,
++};
++
+ struct iscsi_uevent {
+ 	uint32_t type; /* k/u events type */
+ 	uint32_t iferror; /* carries interface or resource errors */
+@@ -116,6 +124,17 @@ struct iscsi_uevent {
+ 		struct msg_transport_disconnect {
+ 			uint64_t	ep_handle;
+ 		} ep_disconnect;
++		struct msg_tgt_dscvr {
++			enum iscsi_tgt_dscvr	type;
++			uint32_t	host_no;
++			/*
++ 			 * enable = 1 to establish a new connection
++			 * with the server. enable = 0 to disconnect
++			 * from the server. Used primarily to switch
++			 * from one iSNS server to another.
++			 */
++			uint32_t	enable;
++		} tgt_dscvr;
+ 	} u;
+ 	union {
+ 		/* messages k -> u */
+@@ -141,6 +160,24 @@ struct iscsi_uevent {
+ 		struct msg_transport_connect_ret {
+ 			uint64_t	handle;
+ 		} ep_connect_ret;
++		struct msg_tgt_dscvr_ret {
++			/*
++			 * session/connection pair used to reference
++			 * the connection to server
++			 */
++			uint32_t	sid;
++			uint32_t	cid;
++			union {
++				struct isns {
++					/* port # for conn to iSNS server */
++					uint16_t isns_port;
++					/* listening port to receive SCNs */
++					uint16_t scn_port;
++					/* listening port to receive ESIs */
++					uint16_t esi_port;
++				} isns_attrib;
++			} u;
++		} tgt_dscvr_ret;
+ 	} r;
+ } __attribute__ ((aligned (sizeof(uint64_t))));
+ 
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index b684426a5900..b95151aec602 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -127,6 +127,8 @@ struct iscsi_transport {
+ 			   uint64_t *ep_handle);
+ 	int (*ep_poll) (uint64_t ep_handle, int timeout_ms);
+ 	void (*ep_disconnect) (uint64_t ep_handle);
++	int (*tgt_dscvr) (enum iscsi_tgt_dscvr type, uint32_t host_no,
++			  uint32_t enable, struct sockaddr *dst_addr);
+ };
+ 
+ /*

commit f70e9c5f91f1d2d9ce79dc45221540e25b4e4ac0
+Author: Mike Christie 
+Date:   Tue May 30 01:04:51 2006 -0500
+
+    [SCSI] iscsi: update version to 1.0-595
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 7fa85937a99f..b4743a9ecc80 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -43,7 +43,7 @@
+ 
+ #include "iscsi_tcp.h"
+ 
+-#define ISCSI_TCP_VERSION "1.0-574"
++#define ISCSI_TCP_VERSION "1.0-595"
+ 
+ MODULE_AUTHOR("Dmitry Yusupov , "
+ 	      "Alex Aizman ");

commit 3219e5294150aee7d389e19029f49b44fb6b5c9f
+Author: Mike Christie 
+Date:   Tue May 30 00:37:28 2006 -0500
+
+    [SCSI] iscsi: fix writepsace race
+    
+    We can race and misset the suspend bit if iscsi_write_space is
+    called then iscsi_send returns with a failure indicating
+    there is no space.
+    
+    To handle this this patch returns a error upwards allowing xmitworker
+    to decide if we need to try and transmit again. For the no
+    write space case xmitworker will not retry, and instead
+    let iscsi_write_space queue it back up if needed (this relies
+    on the work queue code to properly requeue us if needed).
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 2abda804a924..7fa85937a99f 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -1006,7 +1006,6 @@ iscsi_write_space(struct sock *sk)
+ 
+ 	tcp_conn->old_write_space(sk);
+ 	debug_tcp("iscsi_write_space: cid %d\n", conn->id);
+-	clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+ 	scsi_queue_work(conn->session->host, &conn->xmitwork);
+ }
+ 
+@@ -1056,7 +1055,7 @@ iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags)
+ {
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	struct socket *sk = tcp_conn->sock;
+-	int offset = buf->sg.offset + buf->sent;
++	int offset = buf->sg.offset + buf->sent, res;
+ 
+ 	/*
+ 	 * if we got use_sg=0 or are sending something we kmallocd
+@@ -1067,10 +1066,22 @@ iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags)
+ 	 * slab case.
+ 	 */
+ 	if (buf->use_sendmsg)
+-		return sock_no_sendpage(sk, buf->sg.page, offset, size, flags);
++		res = sock_no_sendpage(sk, buf->sg.page, offset, size, flags);
+ 	else
+-		return tcp_conn->sendpage(sk, buf->sg.page, offset, size,
+-					  flags);
++		res = tcp_conn->sendpage(sk, buf->sg.page, offset, size, flags);
++
++	if (res >= 0) {
++		conn->txdata_octets += res;
++		buf->sent += res;
++		return res;
++	}
++
++	tcp_conn->sendpage_failures_cnt++;
++	if (res == -EAGAIN)
++		res = -ENOBUFS;
++	else
++		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
++	return res;
+ }
+ 
+ /**
+@@ -1085,7 +1096,6 @@ iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags)
+ static inline int
+ iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen)
+ {
+-	struct iscsi_tcp_conn *tcp_conn;
+ 	int flags = 0; /* MSG_DONTWAIT; */
+ 	int res, size;
+ 
+@@ -1097,17 +1107,10 @@ iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen)
+ 	res = iscsi_send(conn, buf, size, flags);
+ 	debug_tcp("sendhdr %d bytes, sent %d res %d\n", size, buf->sent, res);
+ 	if (res >= 0) {
+-		conn->txdata_octets += res;
+-		buf->sent += res;
+ 		if (size != res)
+ 			return -EAGAIN;
+ 		return 0;
+-	} else if (res == -EAGAIN) {
+-		tcp_conn = conn->dd_data;
+-		tcp_conn->sendpage_failures_cnt++;
+-		set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+-	} else if (res == -EPIPE)
+-		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
++	}
+ 
+ 	return res;
+ }
+@@ -1126,7 +1129,6 @@ static inline int
+ iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf,
+ 	       int *count, int *sent)
+ {
+-	struct iscsi_tcp_conn *tcp_conn;
+ 	int flags = 0; /* MSG_DONTWAIT; */
+ 	int res, size;
+ 
+@@ -1141,19 +1143,12 @@ iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf,
+ 	debug_tcp("sendpage: %d bytes, sent %d left %d sent %d res %d\n",
+ 		  size, buf->sent, *count, *sent, res);
+ 	if (res >= 0) {
+-		conn->txdata_octets += res;
+-		buf->sent += res;
+ 		*count -= res;
+ 		*sent += res;
+ 		if (size != res)
+ 			return -EAGAIN;
+ 		return 0;
+-	} else if (res == -EAGAIN) {
+-		tcp_conn = conn->dd_data;
+-		tcp_conn->sendpage_failures_cnt++;
+-		set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+-	} else if (res == -EPIPE)
+-		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
++	}
+ 
+ 	return res;
+ }
+@@ -1342,6 +1337,7 @@ static int
+ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
+ {
+ 	struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data;
++	int rc;
+ 
+ 	debug_scsi("mtask deq [cid %d state %x itt 0x%x]\n",
+ 		conn->id, tcp_mtask->xmstate, mtask->itt);
+@@ -1355,12 +1351,13 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
+ 		    conn->hdrdgst_en)
+ 			iscsi_hdr_digest(conn, &tcp_mtask->headbuf,
+ 					(u8*)tcp_mtask->hdrext);
+-		if (iscsi_sendhdr(conn, &tcp_mtask->headbuf,
+-				  mtask->data_count)) {
++		rc = iscsi_sendhdr(conn, &tcp_mtask->headbuf,
++				   mtask->data_count);
++		if (rc) {
+ 			tcp_mtask->xmstate |= XMSTATE_IMM_HDR;
+ 			if (mtask->data_count)
+ 				tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA;
+-			return -EAGAIN;
++			return rc;
+ 		}
+ 	}
+ 
+@@ -1371,10 +1368,13 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
+ 		 * Virtual buffer could be spreaded across multiple pages...
+ 		 */
+ 		do {
+-			if (iscsi_sendpage(conn, &tcp_mtask->sendbuf,
+-				   &mtask->data_count, &tcp_mtask->sent)) {
++			int rc;
++
++			rc = iscsi_sendpage(conn, &tcp_mtask->sendbuf,
++					&mtask->data_count, &tcp_mtask->sent);
++			if (rc) {
+ 				tcp_mtask->xmstate |= XMSTATE_IMM_DATA;
+-				return -EAGAIN;
++				return rc;
+ 			}
+ 		} while (mtask->data_count);
+ 	}
+@@ -1396,16 +1396,19 @@ static inline int
+ handle_xmstate_r_hdr(struct iscsi_conn *conn,
+ 		     struct iscsi_tcp_cmd_task *tcp_ctask)
+ {
++	int rc;
++
+ 	tcp_ctask->xmstate &= ~XMSTATE_R_HDR;
+ 	if (conn->hdrdgst_en)
+ 		iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
+ 				 (u8*)tcp_ctask->hdrext);
+-	if (!iscsi_sendhdr(conn, &tcp_ctask->headbuf, 0)) {
++	rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, 0);
++	if (!rc) {
+ 		BUG_ON(tcp_ctask->xmstate != XMSTATE_IDLE);
+ 		return 0; /* wait for Data-In */
+ 	}
+ 	tcp_ctask->xmstate |= XMSTATE_R_HDR;
+-	return -EAGAIN;
++	return rc;
+ }
+ 
+ static inline int
+@@ -1413,16 +1416,16 @@ handle_xmstate_w_hdr(struct iscsi_conn *conn,
+ 		     struct iscsi_cmd_task *ctask)
+ {
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++	int rc;
+ 
+ 	tcp_ctask->xmstate &= ~XMSTATE_W_HDR;
+ 	if (conn->hdrdgst_en)
+ 		iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
+ 				 (u8*)tcp_ctask->hdrext);
+-	if (iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count)) {
++	rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count);
++	if (rc)
+ 		tcp_ctask->xmstate |= XMSTATE_W_HDR;
+-		return -EAGAIN;
+-	}
+-	return 0;
++	return rc;
+ }
+ 
+ static inline int
+@@ -1430,17 +1433,19 @@ handle_xmstate_data_digest(struct iscsi_conn *conn,
+ 			   struct iscsi_cmd_task *ctask)
+ {
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++	int rc;
+ 
+ 	tcp_ctask->xmstate &= ~XMSTATE_DATA_DIGEST;
+ 	debug_tcp("resent data digest 0x%x\n", tcp_ctask->datadigest);
+-	if (iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf,
+-				    &tcp_ctask->datadigest, 0)) {
++	rc = iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf,
++				    &tcp_ctask->datadigest, 0);
++	if (rc) {
+ 		tcp_ctask->xmstate |= XMSTATE_DATA_DIGEST;
+ 		debug_tcp("resent data digest 0x%x fail!\n",
+ 			  tcp_ctask->datadigest);
+-		return -EAGAIN;
+ 	}
+-	return 0;
++
++	return rc;
+ }
+ 
+ static inline int
+@@ -1448,6 +1453,7 @@ handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	int rc;
+ 
+ 	BUG_ON(!ctask->imm_count);
+ 	tcp_ctask->xmstate &= ~XMSTATE_IMM_DATA;
+@@ -1458,8 +1464,9 @@ handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	}
+ 
+ 	for (;;) {
+-		if (iscsi_sendpage(conn, &tcp_ctask->sendbuf, &ctask->imm_count,
+-				   &tcp_ctask->sent)) {
++		rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf,
++				   &ctask->imm_count, &tcp_ctask->sent);
++		if (rc) {
+ 			tcp_ctask->xmstate |= XMSTATE_IMM_DATA;
+ 			if (conn->datadgst_en) {
+ 				crypto_digest_final(tcp_conn->data_tx_tfm,
+@@ -1467,7 +1474,7 @@ handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 				debug_tcp("tx imm sendpage fail 0x%x\n",
+ 					  tcp_ctask->datadigest);
+ 			}
+-			return -EAGAIN;
++			return rc;
+ 		}
+ 		if (conn->datadgst_en)
+ 			crypto_digest_update(tcp_conn->data_tx_tfm,
+@@ -1480,11 +1487,12 @@ handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	}
+ 
+ 	if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) {
+-		if (iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf,
+-				            &tcp_ctask->immdigest, 1)) {
++		rc = iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf,
++				            &tcp_ctask->immdigest, 1);
++		if (rc) {
+ 			debug_tcp("sending imm digest 0x%x fail!\n",
+ 				  tcp_ctask->immdigest);
+-			return -EAGAIN;
++			return rc;
+ 		}
+ 		debug_tcp("sending imm digest 0x%x\n", tcp_ctask->immdigest);
+ 	}
+@@ -1497,6 +1505,7 @@ handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	struct iscsi_data_task *dtask;
++	int rc;
+ 
+ 	tcp_ctask->xmstate |= XMSTATE_UNS_DATA;
+ 	if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) {
+@@ -1507,10 +1516,12 @@ handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 					(u8*)dtask->hdrext);
+ 		tcp_ctask->xmstate &= ~XMSTATE_UNS_INIT;
+ 	}
+-	if (iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->data_count)) {
++
++	rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->data_count);
++	if (rc) {
+ 		tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA;
+ 		tcp_ctask->xmstate |= XMSTATE_UNS_HDR;
+-		return -EAGAIN;
++		return rc;
+ 	}
+ 
+ 	debug_scsi("uns dout [itt 0x%x dlen %d sent %d]\n",
+@@ -1524,6 +1535,7 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	struct iscsi_data_task *dtask = tcp_ctask->dtask;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	int rc;
+ 
+ 	BUG_ON(!ctask->data_count);
+ 	tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA;
+@@ -1536,8 +1548,9 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	for (;;) {
+ 		int start = tcp_ctask->sent;
+ 
+-		if (iscsi_sendpage(conn, &tcp_ctask->sendbuf,
+-				   &ctask->data_count, &tcp_ctask->sent)) {
++		rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf,
++				   &ctask->data_count, &tcp_ctask->sent);
++		if (rc) {
+ 			ctask->unsol_count -= tcp_ctask->sent - start;
+ 			tcp_ctask->xmstate |= XMSTATE_UNS_DATA;
+ 			/* will continue with this ctask later.. */
+@@ -1547,7 +1560,7 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 				debug_tcp("tx uns data fail 0x%x\n",
+ 					  dtask->digest);
+ 			}
+-			return -EAGAIN;
++			return rc;
+ 		}
+ 
+ 		BUG_ON(tcp_ctask->sent > ctask->total_length);
+@@ -1574,12 +1587,13 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	 */
+ 	if (ctask->unsol_count) {
+ 		if (conn->datadgst_en) {
+-			if (iscsi_digest_final_send(conn, ctask,
++			rc = iscsi_digest_final_send(conn, ctask,
+ 						    &dtask->digestbuf,
+-						    &dtask->digest, 1)) {
++						    &dtask->digest, 1);
++			if (rc) {
+ 				debug_tcp("send uns digest 0x%x fail\n",
+ 					  dtask->digest);
+-				return -EAGAIN;
++				return rc;
+ 			}
+ 			debug_tcp("sending uns digest 0x%x, more uns\n",
+ 				  dtask->digest);
+@@ -1589,12 +1603,13 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	}
+ 
+ 	if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) {
+-		if (iscsi_digest_final_send(conn, ctask,
++		rc = iscsi_digest_final_send(conn, ctask,
+ 					    &dtask->digestbuf,
+-					    &dtask->digest, 1)) {
++					    &dtask->digest, 1);
++		if (rc) {
+ 			debug_tcp("send last uns digest 0x%x fail\n",
+ 				   dtask->digest);
+-			return -EAGAIN;
++			return rc;
+ 		}
+ 		debug_tcp("sending uns digest 0x%x\n",dtask->digest);
+ 	}
+@@ -1610,7 +1625,7 @@ handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	struct iscsi_r2t_info *r2t = tcp_ctask->r2t;
+ 	struct iscsi_data_task *dtask = &r2t->dtask;
+-	int left;
++	int left, rc;
+ 
+ 	tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA;
+ 	tcp_ctask->dtask = dtask;
+@@ -1626,7 +1641,8 @@ handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	if (!r2t->data_count)
+ 		goto data_out_done;
+ 
+-	if (iscsi_sendpage(conn, &r2t->sendbuf, &r2t->data_count, &r2t->sent)) {
++	rc = iscsi_sendpage(conn, &r2t->sendbuf, &r2t->data_count, &r2t->sent);
++	if (rc) {
+ 		tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
+ 		/* will continue with this ctask later.. */
+ 		if (conn->datadgst_en) {
+@@ -1634,7 +1650,7 @@ handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 					  (u8 *)&dtask->digest);
+ 			debug_tcp("r2t data send fail 0x%x\n", dtask->digest);
+ 		}
+-		return -EAGAIN;
++		return rc;
+ 	}
+ 
+ 	BUG_ON(r2t->data_count < 0);
+@@ -1661,12 +1677,13 @@ handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	left = r2t->data_length - r2t->sent;
+ 	if (left) {
+ 		if (conn->datadgst_en) {
+-			if (iscsi_digest_final_send(conn, ctask,
++			rc = iscsi_digest_final_send(conn, ctask,
+ 						    &dtask->digestbuf,
+-						    &dtask->digest, 1)) {
++						    &dtask->digest, 1);
++			if (rc) {
+ 				debug_tcp("send r2t data digest 0x%x"
+ 					  "fail\n", dtask->digest);
+-				return -EAGAIN;
++				return rc;
+ 			}
+ 			debug_tcp("r2t data send digest 0x%x\n",
+ 				  dtask->digest);
+@@ -1683,11 +1700,12 @@ handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	 */
+ 	BUG_ON(tcp_ctask->r2t_data_count - r2t->data_length < 0);
+ 	if (conn->datadgst_en) {
+-		if (iscsi_digest_final_send(conn, ctask, &dtask->digestbuf,
+-					    &dtask->digest, 1)) {
++		rc = iscsi_digest_final_send(conn, ctask, &dtask->digestbuf,
++					    &dtask->digest, 1);
++		if (rc) {
+ 			debug_tcp("send last r2t data digest 0x%x"
+ 				  "fail\n", dtask->digest);
+-			return -EAGAIN;
++			return rc;
+ 		}
+ 		debug_tcp("r2t done dout digest 0x%x\n", dtask->digest);
+ 	}
+@@ -1713,15 +1731,16 @@ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	struct iscsi_data_task *dtask = tcp_ctask->dtask;
+-	int sent;
++	int sent, rc;
+ 
+ 	tcp_ctask->xmstate &= ~XMSTATE_W_PAD;
+ 	iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad,
+ 			    tcp_ctask->pad_count);
+-	if (iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count,
+-			   &sent)) {
++	rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count,
++			   &sent);
++	if (rc) {
+ 		tcp_ctask->xmstate |= XMSTATE_W_PAD;
+-		return -EAGAIN;
++		return rc;
+ 	}
+ 
+ 	if (conn->datadgst_en) {
+@@ -1729,22 +1748,24 @@ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 				     &tcp_ctask->sendbuf.sg, 1);
+ 		/* imm data? */
+ 		if (!dtask) {
+-			if (iscsi_digest_final_send(conn, ctask,
++			rc = iscsi_digest_final_send(conn, ctask,
+ 						    &tcp_ctask->immbuf,
+-						    &tcp_ctask->immdigest, 1)) {
++						    &tcp_ctask->immdigest, 1);
++			if (rc) {
+ 				debug_tcp("send padding digest 0x%x"
+ 					  "fail!\n", tcp_ctask->immdigest);
+-				return -EAGAIN;
++				return rc;
+ 			}
+ 			debug_tcp("done with padding, digest 0x%x\n",
+ 				  tcp_ctask->datadigest);
+ 		} else {
+-			if (iscsi_digest_final_send(conn, ctask,
++			rc = iscsi_digest_final_send(conn, ctask,
+ 						    &dtask->digestbuf,
+-						    &dtask->digest, 1)) {
++						    &dtask->digest, 1);
++			if (rc) {
+ 				debug_tcp("send padding digest 0x%x"
+ 				          "fail\n", dtask->digest);
+-				return -EAGAIN;
++				return rc;
+ 			}
+ 			debug_tcp("done with padding, digest 0x%x\n",
+ 				  dtask->digest);
+@@ -1769,10 +1790,8 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	if (ctask->mtask)
+ 		return rc;
+ 
+-	if (tcp_ctask->xmstate & XMSTATE_R_HDR) {
+-		rc = handle_xmstate_r_hdr(conn, tcp_ctask);
+-		return rc;
+-	}
++	if (tcp_ctask->xmstate & XMSTATE_R_HDR)
++		return handle_xmstate_r_hdr(conn, tcp_ctask);
+ 
+ 	if (tcp_ctask->xmstate & XMSTATE_W_HDR) {
+ 		rc = handle_xmstate_w_hdr(conn, ctask);
+@@ -1824,10 +1843,11 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 		if (conn->hdrdgst_en)
+ 			iscsi_hdr_digest(conn, &r2t->headbuf,
+ 					(u8*)r2t->dtask.hdrext);
+-		if (iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count)) {
++		rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count);
++		if (rc) {
+ 			tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA;
+ 			tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
+-			return -EAGAIN;
++			return rc;
+ 		}
+ 
+ 		debug_scsi("sol dout [dsn %d itt 0x%x dlen %d sent %d]\n",
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 256b87a85978..2673a11a9495 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -513,10 +513,11 @@ EXPORT_SYMBOL_GPL(iscsi_conn_failure);
+ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ {
+ 	struct iscsi_transport *tt;
++	int rc = 0;
+ 
+ 	if (unlikely(conn->suspend_tx)) {
+ 		debug_scsi("conn %d Tx suspended!\n", conn->id);
+-		return 0;
++		return -ENODATA;
+ 	}
+ 	tt = conn->session->tt;
+ 
+@@ -536,13 +537,15 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 	BUG_ON(conn->ctask && conn->mtask);
+ 
+ 	if (conn->ctask) {
+-		if (tt->xmit_cmd_task(conn, conn->ctask))
++		rc = tt->xmit_cmd_task(conn, conn->ctask);
++		if (rc)
+ 			goto again;
+ 		/* done with this in-progress ctask */
+ 		conn->ctask = NULL;
+ 	}
+ 	if (conn->mtask) {
+-	        if (tt->xmit_mgmt_task(conn, conn->mtask))
++		rc = tt->xmit_mgmt_task(conn, conn->mtask);
++	        if (rc)
+ 		        goto again;
+ 		/* done with this in-progress mtask */
+ 		conn->mtask = NULL;
+@@ -556,7 +559,8 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 			list_add_tail(&conn->mtask->running,
+ 				      &conn->mgmt_run_list);
+ 			spin_unlock_bh(&conn->session->lock);
+-		        if (tt->xmit_mgmt_task(conn, conn->mtask))
++			rc = tt->xmit_mgmt_task(conn, conn->mtask);
++		        if (rc)
+ 			        goto again;
+ 	        }
+ 		/* done with this mtask */
+@@ -574,7 +578,8 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 		if (list_empty(&conn->ctask->running))
+ 			list_add_tail(&conn->ctask->running, &conn->run_list);
+ 		spin_unlock_bh(&conn->session->lock);
+-		if (tt->xmit_cmd_task(conn, conn->ctask))
++		rc = tt->xmit_cmd_task(conn, conn->ctask);
++		if (rc)
+ 			goto again;
+ 	}
+ 	/* done with this ctask */
+@@ -588,32 +593,34 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 			list_add_tail(&conn->mtask->running,
+ 				      &conn->mgmt_run_list);
+ 			spin_unlock_bh(&conn->session->lock);
+-		        if (tt->xmit_mgmt_task(conn, conn->mtask))
++		        rc = tt->xmit_mgmt_task(conn, conn->mtask);
++			if (rc)
+ 			        goto again;
+ 	        }
+ 		/* done with this mtask */
+ 		conn->mtask = NULL;
+ 	}
+ 
+-	return 0;
++	return -ENODATA;
+ 
+ again:
+ 	if (unlikely(conn->suspend_tx))
+-		return 0;
++		return -ENODATA;
+ 
+-	return -EAGAIN;
++	return rc;
+ }
+ 
+ static void iscsi_xmitworker(void *data)
+ {
+ 	struct iscsi_conn *conn = data;
+-
++	int rc;
+ 	/*
+ 	 * serialize Xmit worker on a per-connection basis.
+ 	 */
+ 	mutex_lock(&conn->xmitmutex);
+-	if (iscsi_data_xmit(conn))
+-		scsi_queue_work(conn->session->host, &conn->xmitwork);
++	do {
++		rc = iscsi_data_xmit(conn);
++	} while (rc >= 0 || rc == -EAGAIN);
+ 	mutex_unlock(&conn->xmitmutex);
+ }
+ 
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 92129b97d31e..b684426a5900 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -57,8 +57,12 @@ struct iscsi_mgmt_task;
+  *			Called from queuecommand with session lock held.
+  * @init_mgmt_task:	Initialize a iscsi_mgmt_task and any internal structs.
+  *			Called from iscsi_conn_send_generic with xmitmutex.
+- * @xmit_cmd_task:	requests LLD to transfer cmd task
+- * @xmit_mgmt_task:	requests LLD to transfer mgmt task
++ * @xmit_cmd_task:	Requests LLD to transfer cmd task. Returns 0 or the
++ *			the number of bytes transferred on success, and -Exyz
++ *			value on error.
++ * @xmit_mgmt_task:	Requests LLD to transfer mgmt task. Returns 0 or the
++ *			the number of bytes transferred on success, and -Exyz
++ *			value on error.
+  * @cleanup_cmd_task:	requests LLD to fail cmd task. Called with xmitmutex
+  *			and session->lock after the connection has been
+  *			suspended and terminated during recovery. If called

commit 040515f53c09047c76ad074dc6a280984dc84b04
+Author: Mike Christie 
+Date:   Tue May 30 00:37:25 2006 -0500
+
+    [SCSI] iscsi: return task found during search
+    
+    from davidw@netapp.com:
+    
+    remove task type should return a task on success.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index a223413e1564..256b87a85978 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -985,7 +985,7 @@ iscsi_remove_##tasktype(struct kfifo *fifo, uint32_t itt)		\
+ 									\
+ 		if (task->itt == itt) {					\
+ 			debug_scsi("matched task\n");			\
+-			break;						\
++			return task;					\
+ 		}							\
+ 									\
+ 		__kfifo_put(fifo, (void*)&task, sizeof(void*));		\

commit 994442e807782d68bb1d3ae34044f95990411a22
+Author: Mike Christie 
+Date:   Tue May 30 00:37:22 2006 -0500
+
+    [SCSI] iscsi: fix run list corruption
+    
+    from davidw@netapp.com:
+    
+    We must grab the session lock when modifying the running lists.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 963002598995..a223413e1564 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -552,8 +552,10 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+         if (unlikely(__kfifo_len(conn->immqueue))) {
+ 	        while (__kfifo_get(conn->immqueue, (void*)&conn->mtask,
+ 			           sizeof(void*))) {
++			spin_lock_bh(&conn->session->lock);
+ 			list_add_tail(&conn->mtask->running,
+ 				      &conn->mgmt_run_list);
++			spin_unlock_bh(&conn->session->lock);
+ 		        if (tt->xmit_mgmt_task(conn, conn->mtask))
+ 			        goto again;
+ 	        }
+@@ -568,8 +570,10 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ 		 * iscsi tcp may readd the task to the xmitqueue to send
+ 		 * write data
+ 		 */
++		spin_lock_bh(&conn->session->lock);
+ 		if (list_empty(&conn->ctask->running))
+ 			list_add_tail(&conn->ctask->running, &conn->run_list);
++		spin_unlock_bh(&conn->session->lock);
+ 		if (tt->xmit_cmd_task(conn, conn->ctask))
+ 			goto again;
+ 	}
+@@ -580,8 +584,10 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
+         if (unlikely(__kfifo_len(conn->mgmtqueue))) {
+ 	        while (__kfifo_get(conn->mgmtqueue, (void*)&conn->mtask,
+ 			           sizeof(void*))) {
++			spin_lock_bh(&conn->session->lock);
+ 			list_add_tail(&conn->mtask->running,
+ 				      &conn->mgmt_run_list);
++			spin_unlock_bh(&conn->session->lock);
+ 		        if (tt->xmit_mgmt_task(conn, conn->mtask))
+ 			        goto again;
+ 	        }

commit 67a611149b2ac5f4af1e36bfffbfe3198cd3712c
+Author: Mike Christie 
+Date:   Tue May 30 00:37:20 2006 -0500
+
+    [SCSI] iscsi: don't switch states when just cleaning up
+    
+    If recovery failed or we are in recovery only overwrite the state
+    if we are going to terminate the session or if we logged back in.
+    
+    STOP_CONN_SUSPEND and conn_cnt are not used. We only support
+    a single connection session ATM, so cleanup that code while
+    we are working around it.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index c66faee07ca5..2abda804a924 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -1955,30 +1955,28 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
+ 	if (err)
+ 		return err;
+ 
+-	if (conn->stop_stage != STOP_CONN_SUSPEND) {
+-		/* bind iSCSI connection and socket */
+-		tcp_conn->sock = sock;
++	/* bind iSCSI connection and socket */
++	tcp_conn->sock = sock;
+ 
+-		/* setup Socket parameters */
+-		sk = sock->sk;
+-		sk->sk_reuse = 1;
+-		sk->sk_sndtimeo = 15 * HZ; /* FIXME: make it configurable */
+-		sk->sk_allocation = GFP_ATOMIC;
++	/* setup Socket parameters */
++	sk = sock->sk;
++	sk->sk_reuse = 1;
++	sk->sk_sndtimeo = 15 * HZ; /* FIXME: make it configurable */
++	sk->sk_allocation = GFP_ATOMIC;
+ 
+-		/* FIXME: disable Nagle's algorithm */
++	/* FIXME: disable Nagle's algorithm */
+ 
+-		/*
+-		 * Intercept TCP callbacks for sendfile like receive
+-		 * processing.
+-		 */
+-		conn->recv_lock = &sk->sk_callback_lock;
+-		iscsi_conn_set_callbacks(conn);
+-		tcp_conn->sendpage = tcp_conn->sock->ops->sendpage;
+-		/*
+-		 * set receive state machine into initial state
+-		 */
+-		tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
+-	}
++	/*
++	 * Intercept TCP callbacks for sendfile like receive
++	 * processing.
++	 */
++	conn->recv_lock = &sk->sk_callback_lock;
++	iscsi_conn_set_callbacks(conn);
++	tcp_conn->sendpage = tcp_conn->sock->ops->sendpage;
++	/*
++	 * set receive state machine into initial state
++	 */
++	tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
+ 
+ 	return 0;
+ }
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index d810acae45f7..963002598995 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -492,7 +492,7 @@ void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
+ 		return;
+ 	}
+ 
+-	if (session->conn_cnt == 1 || session->leadconn == conn)
++	if (conn->stop_stage == 0)
+ 		session->state = ISCSI_STATE_FAILED;
+ 	spin_unlock_irqrestore(&session->lock, flags);
+ 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+@@ -652,7 +652,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 		 */
+ 		if (session->state == ISCSI_STATE_IN_RECOVERY) {
+ 			reason = FAILURE_SESSION_IN_RECOVERY;
+-			goto fault;
++			goto reject;
+ 		}
+ 
+ 		if (session->state == ISCSI_STATE_RECOVERY_FAILED)
+@@ -1411,8 +1411,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
+ 	struct iscsi_session *session = conn->session;
+ 	unsigned long flags;
+ 
+-	mutex_lock(&conn->xmitmutex);
+ 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
++	mutex_lock(&conn->xmitmutex);
+ 	if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE) {
+ 		if (session->tt->suspend_conn_recv)
+ 			session->tt->suspend_conn_recv(conn);
+@@ -1498,7 +1498,6 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
+ 		 * unblock eh_abort() if it is blocked. re-try all
+ 		 * commands after successful recovery
+ 		 */
+-		session->conn_cnt++;
+ 		conn->stop_stage = 0;
+ 		conn->tmabort_state = TMABORT_INITIAL;
+ 		session->age++;
+@@ -1508,13 +1507,7 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
+ 		wake_up(&conn->ehwait);
+ 		return 0;
+ 	case STOP_CONN_TERM:
+-		session->conn_cnt++;
+-		conn->stop_stage = 0;
+-		break;
+-	case STOP_CONN_SUSPEND:
+ 		conn->stop_stage = 0;
+-		clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
+-		clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+ 		break;
+ 	default:
+ 		break;
+@@ -1589,28 +1582,24 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ 
+ 	/*
+ 	 * When this is called for the in_login state, we only want to clean
+-	 * up the login task and connection.
++	 * up the login task and connection. We do not need to block and set
++	 * the recovery state again
+ 	 */
+-	if (conn->stop_stage != STOP_CONN_RECOVER)
+-		session->conn_cnt--;
++	if (flag == STOP_CONN_TERM)
++		session->state = ISCSI_STATE_TERMINATE;
++	else if (conn->stop_stage != STOP_CONN_RECOVER)
++		session->state = ISCSI_STATE_IN_RECOVERY;
+ 
+ 	old_stop_stage = conn->stop_stage;
+ 	conn->stop_stage = flag;
++	conn->c_stage = ISCSI_CONN_STOPPED;
++	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+ 	spin_unlock_bh(&session->lock);
+ 
+ 	if (session->tt->suspend_conn_recv)
+ 		session->tt->suspend_conn_recv(conn);
+ 
+ 	mutex_lock(&conn->xmitmutex);
+-	spin_lock_bh(&session->lock);
+-	conn->c_stage = ISCSI_CONN_STOPPED;
+-	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+-
+-	if (session->conn_cnt == 0 || session->leadconn == conn)
+-		session->state = ISCSI_STATE_IN_RECOVERY;
+-
+-	spin_unlock_bh(&session->lock);
+-
+ 	/*
+ 	 * for connection level recovery we should not calculate
+ 	 * header digest. conn->hdr_size used for optimization
+@@ -1620,13 +1609,11 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
+ 	if (flag == STOP_CONN_RECOVER) {
+ 		conn->hdrdgst_en = 0;
+ 		conn->datadgst_en = 0;
+-		/*
+-		 * if this is called from the eh and and from userspace
+-		 * then we only need to block once.
+-		 */
+ 		if (session->state == ISCSI_STATE_IN_RECOVERY &&
+-		    old_stop_stage != STOP_CONN_RECOVER)
++		    old_stop_stage != STOP_CONN_RECOVER) {
++			debug_scsi("blocking session\n");
+ 			iscsi_block_session(session_to_cls(session));
++		}
+ 	}
+ 
+ 	session->tt->terminate_conn(conn);
+@@ -1651,20 +1638,6 @@ void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+ 	case STOP_CONN_TERM:
+ 		iscsi_start_session_recovery(session, conn, flag);
+ 		break;
+-	case STOP_CONN_SUSPEND:
+-		if (session->tt->suspend_conn_recv)
+-			session->tt->suspend_conn_recv(conn);
+-
+-		mutex_lock(&conn->xmitmutex);
+-		spin_lock_bh(&session->lock);
+-
+-		conn->stop_stage = flag;
+-		conn->c_stage = ISCSI_CONN_STOPPED;
+-		set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+-
+-		spin_unlock_bh(&session->lock);
+-		mutex_unlock(&conn->xmitmutex);
+-		break;
+ 	default:
+ 		printk(KERN_ERR "iscsi: invalid stop flag %d\n", flag);
+ 	}
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 17b28f08b692..cbf7e58bd6f9 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -211,7 +211,6 @@ struct iscsi_session {
+ 						 * - r2tpool		   */
+ 	int			state;		/* session state           */
+ 	struct list_head	item;
+-	int			conn_cnt;
+ 	int			age;		/* counts session re-opens */
+ 
+ 	struct list_head	connections;	/* list of connections */

commit e0ecae8da26d94dd878ff1d939c5aa4224df18a4
+Author: Mike Christie 
+Date:   Thu May 18 20:31:43 2006 -0500
+
+    [SCSI] iscsi: update version
+    
+    update version
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 08357a6c7e09..c66faee07ca5 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -43,11 +43,13 @@
+ 
+ #include "iscsi_tcp.h"
+ 
++#define ISCSI_TCP_VERSION "1.0-574"
++
+ MODULE_AUTHOR("Dmitry Yusupov , "
+ 	      "Alex Aizman ");
+ MODULE_DESCRIPTION("iSCSI/TCP data-path");
+ MODULE_LICENSE("GPL");
+-MODULE_VERSION("0:4.445");
++MODULE_VERSION(ISCSI_TCP_VERSION);
+ /* #define DEBUG_TCP */
+ #define DEBUG_ASSERT
+ 
+@@ -2448,8 +2450,8 @@ static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session)
+ }
+ 
+ static struct scsi_host_template iscsi_sht = {
+-	.name			= "iSCSI Initiator over TCP/IP, v."
+-				  ISCSI_VERSION_STR,
++	.name			= "iSCSI Initiator over TCP/IP, v"
++				  ISCSI_TCP_VERSION,
+ 	.queuecommand           = iscsi_queuecommand,
+ 	.change_queue_depth	= iscsi_change_queue_depth,
+ 	.can_queue		= ISCSI_XMIT_CMDS_MAX - 1,
+diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h
+index 4feda05fdf25..02f6e4b9e693 100644
+--- a/include/scsi/iscsi_proto.h
++++ b/include/scsi/iscsi_proto.h
+@@ -21,8 +21,6 @@
+ #ifndef ISCSI_PROTO_H
+ #define ISCSI_PROTO_H
+ 
+-#define ISCSI_VERSION_STR	"0.3"
+-#define ISCSI_DATE_STR		"22-Apr-2005"
+ #define ISCSI_DRAFT20_VERSION	0x00
+ 
+ /* default iSCSI listen port for incoming connections */

commit 656cffc95f0cb8211aa75eaca249e6ff4f59ec83
+Author: Mike Christie 
+Date:   Thu May 18 20:31:42 2006 -0500
+
+    [SCSI] iscsi: fix command requeues during iscsi recovery
+    
+    Do not flush queues then block session. This will cause commands
+    to needlessly swing around on us and remove goofy
+    recovery_failed field and replace with state value.
+    
+    And do not start recovery from within the host reset function.
+    This causeis too many problems becuase open-iscsi was desinged to
+    call out to userspace then have userpscae decide if we should
+    go into recovery or kill the session.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 580c0505603c..d810acae45f7 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -487,6 +487,11 @@ void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&session->lock, flags);
++	if (session->state == ISCSI_STATE_FAILED) {
++		spin_unlock_irqrestore(&session->lock, flags);
++		return;
++	}
++
+ 	if (session->conn_cnt == 1 || session->leadconn == conn)
+ 		session->state = ISCSI_STATE_FAILED;
+ 	spin_unlock_irqrestore(&session->lock, flags);
+@@ -612,6 +617,7 @@ enum {
+ 	FAILURE_SESSION_FREED,
+ 	FAILURE_WINDOW_CLOSED,
+ 	FAILURE_SESSION_TERMINATE,
++	FAILURE_SESSION_IN_RECOVERY,
+ 	FAILURE_SESSION_RECOVERY_TIMEOUT,
+ };
+ 
+@@ -631,18 +637,30 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 
+ 	spin_lock(&session->lock);
+ 
+-	if (session->state != ISCSI_STATE_LOGGED_IN) {
+-		if (session->recovery_failed) {
+-			reason = FAILURE_SESSION_RECOVERY_TIMEOUT;
+-			goto fault;
+-		} else if (session->state == ISCSI_STATE_FAILED) {
+-			reason = FAILURE_SESSION_FAILED;
+-			goto reject;
+-		} else if (session->state == ISCSI_STATE_TERMINATE) {
+-			reason = FAILURE_SESSION_TERMINATE;
++	/*
++	 * ISCSI_STATE_FAILED is a temp. state. The recovery
++	 * code will decide what is best to do with command queued
++	 * during this time
++	 */
++	if (session->state != ISCSI_STATE_LOGGED_IN &&
++	    session->state != ISCSI_STATE_FAILED) {
++		/*
++		 * to handle the race between when we set the recovery state
++		 * and block the session we requeue here (commands could
++		 * be entering our queuecommand while a block is starting
++		 * up because the block code is not locked)
++		 */
++		if (session->state == ISCSI_STATE_IN_RECOVERY) {
++			reason = FAILURE_SESSION_IN_RECOVERY;
+ 			goto fault;
+ 		}
+-		reason = FAILURE_SESSION_FREED;
++
++		if (session->state == ISCSI_STATE_RECOVERY_FAILED)
++			reason = FAILURE_SESSION_RECOVERY_TIMEOUT;
++		else if (session->state == ISCSI_STATE_TERMINATE)
++			reason = FAILURE_SESSION_TERMINATE;
++		else
++			reason = FAILURE_SESSION_FREED;
+ 		goto fault;
+ 	}
+ 
+@@ -728,8 +746,8 @@ iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		 */
+ 		mtask = conn->login_mtask;
+ 	else {
+-	        BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
+-	        BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
++		BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
++		BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
+ 
+ 		nop->exp_statsn = cpu_to_be32(conn->exp_statsn);
+ 		if (!__kfifo_get(session->mgmtpool.queue,
+@@ -803,7 +821,7 @@ void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session)
+ 
+ 	spin_lock_bh(&session->lock);
+ 	if (session->state != ISCSI_STATE_LOGGED_IN) {
+-		session->recovery_failed = 1;
++		session->state = ISCSI_STATE_RECOVERY_FAILED;
+ 		if (conn)
+ 			wake_up(&conn->ehwait);
+ 	}
+@@ -838,20 +856,14 @@ int iscsi_eh_host_reset(struct scsi_cmnd *sc)
+ 	 * we drop the lock here but the leadconn cannot be destoyed while
+ 	 * we are in the scsi eh
+ 	 */
+-	if (fail_session) {
++	if (fail_session)
+ 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+-		/*
+-		 * if userspace cannot respond then we must kick this off
+-		 * here for it
+-		 */
+-		iscsi_start_session_recovery(session, conn, STOP_CONN_RECOVER);
+-	}
+ 
+ 	debug_scsi("iscsi_eh_host_reset wait for relogin\n");
+ 	wait_event_interruptible(conn->ehwait,
+ 				 session->state == ISCSI_STATE_TERMINATE ||
+ 				 session->state == ISCSI_STATE_LOGGED_IN ||
+-				 session->recovery_failed);
++				 session->state == ISCSI_STATE_RECOVERY_FAILED);
+ 	if (signal_pending(current))
+ 		flush_signals(current);
+ 
+@@ -940,8 +952,7 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc,
+ 	wait_event_interruptible(conn->ehwait,
+ 				 sc->SCp.phase != session->age ||
+ 				 session->state != ISCSI_STATE_LOGGED_IN ||
+-				 conn->tmabort_state != TMABORT_INITIAL ||
+-				 session->recovery_failed);
++				 conn->tmabort_state != TMABORT_INITIAL);
+ 	if (signal_pending(current))
+ 		flush_signals(current);
+ 	del_timer_sync(&conn->tmabort_timer);
+@@ -1491,7 +1502,6 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
+ 		conn->stop_stage = 0;
+ 		conn->tmabort_state = TMABORT_INITIAL;
+ 		session->age++;
+-		session->recovery_failed = 0;
+ 		spin_unlock_bh(&session->lock);
+ 
+ 		iscsi_unblock_session(session_to_cls(session));
+@@ -1566,8 +1576,8 @@ static void fail_all_commands(struct iscsi_conn *conn)
+ 	conn->ctask = NULL;
+ }
+ 
+-void iscsi_start_session_recovery(struct iscsi_session *session,
+-				  struct iscsi_conn *conn, int flag)
++static void iscsi_start_session_recovery(struct iscsi_session *session,
++					 struct iscsi_conn *conn, int flag)
+ {
+ 	int old_stop_stage;
+ 
+@@ -1597,19 +1607,10 @@ void iscsi_start_session_recovery(struct iscsi_session *session,
+ 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+ 
+ 	if (session->conn_cnt == 0 || session->leadconn == conn)
+-		session->state = ISCSI_STATE_FAILED;
++		session->state = ISCSI_STATE_IN_RECOVERY;
+ 
+ 	spin_unlock_bh(&session->lock);
+ 
+-	session->tt->terminate_conn(conn);
+-	/*
+-	 * flush queues.
+-	 */
+-	spin_lock_bh(&session->lock);
+-	fail_all_commands(conn);
+-	flush_control_queues(session, conn);
+-	spin_unlock_bh(&session->lock);
+-
+ 	/*
+ 	 * for connection level recovery we should not calculate
+ 	 * header digest. conn->hdr_size used for optimization
+@@ -1619,18 +1620,26 @@ void iscsi_start_session_recovery(struct iscsi_session *session,
+ 	if (flag == STOP_CONN_RECOVER) {
+ 		conn->hdrdgst_en = 0;
+ 		conn->datadgst_en = 0;
+-
+ 		/*
+ 		 * if this is called from the eh and and from userspace
+ 		 * then we only need to block once.
+ 		 */
+-		if (session->state == ISCSI_STATE_FAILED &&
++		if (session->state == ISCSI_STATE_IN_RECOVERY &&
+ 		    old_stop_stage != STOP_CONN_RECOVER)
+ 			iscsi_block_session(session_to_cls(session));
+ 	}
++
++	session->tt->terminate_conn(conn);
++	/*
++	 * flush queues.
++	 */
++	spin_lock_bh(&session->lock);
++	fail_all_commands(conn);
++	flush_control_queues(session, conn);
++	spin_unlock_bh(&session->lock);
++
+ 	mutex_unlock(&conn->xmitmutex);
+ }
+-EXPORT_SYMBOL_GPL(iscsi_start_session_recovery);
+ 
+ void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+ {
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 2dba929a2a05..17b28f08b692 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -210,7 +210,6 @@ struct iscsi_session {
+ 						 * - mgmtpool,		   *
+ 						 * - r2tpool		   */
+ 	int			state;		/* session state           */
+-	int			recovery_failed;
+ 	struct list_head	item;
+ 	int			conn_cnt;
+ 	int			age;		/* counts session re-opens */
+@@ -241,8 +240,6 @@ iscsi_session_setup(struct iscsi_transport *, struct scsi_transport_template *,
+ 		    int, int, uint32_t, uint32_t *);
+ extern void iscsi_session_teardown(struct iscsi_cls_session *);
+ extern struct iscsi_session *class_to_transport_session(struct iscsi_cls_session *);
+-extern void iscsi_start_session_recovery(struct iscsi_session *,
+-					struct iscsi_conn *, int);
+ extern void iscsi_session_recovery_timedout(struct iscsi_cls_session *);
+ 
+ #define session_to_cls(_sess) \
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index c9e9475c6dff..92129b97d31e 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -173,6 +173,8 @@ struct iscsi_cls_conn {
+ #define ISCSI_STATE_LOGGED_IN		2
+ #define ISCSI_STATE_FAILED		3
+ #define ISCSI_STATE_TERMINATE		4
++#define ISCSI_STATE_IN_RECOVERY		5
++#define ISCSI_STATE_RECOVERY_FAILED	6
+ 
+ struct iscsi_cls_session {
+ 	struct list_head sess_list;		/* item in session_list */

commit 790f39a2d5f03623b027f340b945f135d006ceba
+Author: Mike Christie 
+Date:   Thu May 18 20:31:39 2006 -0500
+
+    [SCSI] iscsi: support mutiple daemons
+    
+    Patch from david.somayajulu@qlogic.com and cleaned up by Tomo.
+    
+    qla4xxx is going to have a different daemon so this patch
+    just routes the events to the right daemon.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 44adafac861f..5569fdcfd621 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -36,6 +36,7 @@
+ #define ISCSI_HOST_ATTRS 0
+ 
+ struct iscsi_internal {
++	int daemon_pid;
+ 	struct scsi_transport_template t;
+ 	struct iscsi_transport *iscsi_transport;
+ 	struct list_head list;
+@@ -145,7 +146,6 @@ static DECLARE_TRANSPORT_CLASS(iscsi_connection_class,
+ 			       NULL);
+ 
+ static struct sock *nls;
+-static int daemon_pid;
+ static DEFINE_MUTEX(rx_queue_mutex);
+ 
+ struct mempool_zone {
+@@ -572,13 +572,13 @@ mempool_zone_get_skb(struct mempool_zone *zone)
+ }
+ 
+ static int
+-iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb)
++iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb, int pid)
+ {
+ 	unsigned long flags;
+ 	int rc;
+ 
+ 	skb_get(skb);
+-	rc = netlink_unicast(nls, skb, daemon_pid, MSG_DONTWAIT);
++	rc = netlink_unicast(nls, skb, pid, MSG_DONTWAIT);
+ 	if (rc < 0) {
+ 		mempool_free(skb, zone->pool);
+ 		printk(KERN_ERR "iscsi: can not unicast skb (%d)\n", rc);
+@@ -600,9 +600,14 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
+ 	struct sk_buff *skb;
+ 	struct iscsi_uevent *ev;
+ 	char *pdu;
++	struct iscsi_internal *priv;
+ 	int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) +
+ 			      data_size);
+ 
++	priv = iscsi_if_transport_lookup(conn->transport);
++	if (!priv)
++		return -EINVAL;
++
+ 	mempool_zone_complete(conn->z_pdu);
+ 
+ 	skb = mempool_zone_get_skb(conn->z_pdu);
+@@ -613,7 +618,7 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
+ 		return -ENOMEM;
+ 	}
+ 
+-	nlh = __nlmsg_put(skb, daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
++	nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
+ 	ev = NLMSG_DATA(nlh);
+ 	memset(ev, 0, sizeof(*ev));
+ 	ev->transport_handle = iscsi_handle(conn->transport);
+@@ -626,7 +631,7 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
+ 	memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
+ 	memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
+ 
+-	return iscsi_unicast_skb(conn->z_pdu, skb);
++	return iscsi_unicast_skb(conn->z_pdu, skb, priv->daemon_pid);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
+ 
+@@ -635,8 +640,13 @@ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
+ 	struct nlmsghdr	*nlh;
+ 	struct sk_buff	*skb;
+ 	struct iscsi_uevent *ev;
++	struct iscsi_internal *priv;
+ 	int len = NLMSG_SPACE(sizeof(*ev));
+ 
++	priv = iscsi_if_transport_lookup(conn->transport);
++	if (!priv)
++		return;
++
+ 	mempool_zone_complete(conn->z_error);
+ 
+ 	skb = mempool_zone_get_skb(conn->z_error);
+@@ -646,7 +656,7 @@ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
+ 		return;
+ 	}
+ 
+-	nlh = __nlmsg_put(skb, daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
++	nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
+ 	ev = NLMSG_DATA(nlh);
+ 	ev->transport_handle = iscsi_handle(conn->transport);
+ 	ev->type = ISCSI_KEVENT_CONN_ERROR;
+@@ -656,7 +666,7 @@ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
+ 	ev->r.connerror.cid = conn->cid;
+ 	ev->r.connerror.sid = iscsi_conn_get_sid(conn);
+ 
+-	iscsi_unicast_skb(conn->z_error, skb);
++	iscsi_unicast_skb(conn->z_error, skb, priv->daemon_pid);
+ 
+ 	dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n",
+ 		   error);
+@@ -686,7 +696,7 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi,
+ 	nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0);
+ 	nlh->nlmsg_flags = flags;
+ 	memcpy(NLMSG_DATA(nlh), payload, size);
+-	return iscsi_unicast_skb(z_reply, skb);
++	return iscsi_unicast_skb(z_reply, skb, pid);
+ }
+ 
+ static int
+@@ -698,12 +708,17 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
+ 	struct iscsi_cls_conn *conn;
+ 	struct nlmsghdr	*nlhstat;
+ 	struct iscsi_uevent *evstat;
++	struct iscsi_internal *priv;
+ 	int len = NLMSG_SPACE(sizeof(*ev) +
+ 			      sizeof(struct iscsi_stats) +
+ 			      sizeof(struct iscsi_stats_custom) *
+ 			      ISCSI_STATS_CUSTOM_MAX);
+ 	int err = 0;
+ 
++	priv = iscsi_if_transport_lookup(transport);
++	if (!priv)
++		return -EINVAL;
++
+ 	conn = iscsi_conn_lookup(ev->u.get_stats.sid, ev->u.get_stats.cid);
+ 	if (!conn)
+ 		return -EEXIST;
+@@ -720,7 +735,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
+ 			return -ENOMEM;
+ 		}
+ 
+-		nlhstat = __nlmsg_put(skbstat, daemon_pid, 0, 0,
++		nlhstat = __nlmsg_put(skbstat, priv->daemon_pid, 0, 0,
+ 				      (len - sizeof(*nlhstat)), 0);
+ 		evstat = NLMSG_DATA(nlhstat);
+ 		memset(evstat, 0, sizeof(*evstat));
+@@ -746,7 +761,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
+ 		skb_trim(skbstat, NLMSG_ALIGN(actual_size));
+ 		nlhstat->nlmsg_len = actual_size;
+ 
+-		err = iscsi_unicast_skb(conn->z_pdu, skbstat);
++		err = iscsi_unicast_skb(conn->z_pdu, skbstat, priv->daemon_pid);
+ 	} while (err < 0 && err != -ECONNREFUSED);
+ 
+ 	return err;
+@@ -981,6 +996,8 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 	if (!try_module_get(transport->owner))
+ 		return -EINVAL;
+ 
++	priv->daemon_pid = NETLINK_CREDS(skb)->pid;
++
+ 	switch (nlh->nlmsg_type) {
+ 	case ISCSI_UEVENT_CREATE_SESSION:
+ 		err = iscsi_if_create_session(priv, ev);
+@@ -1073,7 +1090,6 @@ iscsi_if_rx(struct sock *sk, int len)
+ 			skb_pull(skb, skb->len);
+ 			goto free_skb;
+ 		}
+-		daemon_pid = NETLINK_CREDS(skb)->pid;
+ 
+ 		while (skb->len >= NLMSG_SPACE(0)) {
+ 			int err;

commit ffbfe92533810bf1bb76fd275400825ef8898ed9
+Author: Mike Christie 
+Date:   Thu May 18 20:31:36 2006 -0500
+
+    [SCSI] iscsi: kill dtask mempools
+    
+    Discovered by steven@hayter.me.uk and patch by michaelc@cs.wisc.edu
+    
+    The dtask mempool is reserving 261120 items per session! Since we are now
+    sending headers with sendmsg there is no reason for the mempool and that
+    was causing us to us carzy amounts of mem. We can preallicate a header in
+    the r2t and task struct and reuse them
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 7c2ed7bb7e94..08357a6c7e09 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -67,9 +67,6 @@ MODULE_VERSION("0:4.445");
+ static unsigned int iscsi_max_lun = 512;
+ module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
+ 
+-/* global data */
+-static kmem_cache_t *taskcache;
+-
+ static inline void
+ iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size)
+ {
+@@ -195,16 +192,6 @@ __iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	if (unlikely(!sc))
+ 		return;
+ 
+-	if (sc->sc_data_direction == DMA_TO_DEVICE) {
+-		struct iscsi_data_task *dtask, *n;
+-
+-		/* WRITE: cleanup Data-Out's if any */
+-		list_for_each_entry_safe(dtask, n, &tcp_ctask->dataqueue,
+-					 item) {
+-			list_del(&dtask->item);
+-			mempool_free(dtask, tcp_ctask->datapool);
+-		}
+-	}
+ 	tcp_ctask->xmstate = XMSTATE_IDLE;
+ 	tcp_ctask->r2t = NULL;
+ }
+@@ -286,14 +273,10 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 			struct iscsi_r2t_info *r2t)
+ {
+ 	struct iscsi_data *hdr;
+-	struct iscsi_data_task *dtask;
+ 	struct scsi_cmnd *sc = ctask->sc;
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 
+-	dtask = mempool_alloc(tcp_ctask->datapool, GFP_ATOMIC);
+-	BUG_ON(!dtask);
+-	INIT_LIST_HEAD(&dtask->item);
+-	hdr = &dtask->hdr;
++	hdr = &r2t->dtask.hdr;
+ 	memset(hdr, 0, sizeof(struct iscsi_data));
+ 	hdr->ttt = r2t->ttt;
+ 	hdr->datasn = cpu_to_be32(r2t->solicit_datasn);
+@@ -319,8 +302,6 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 	iscsi_buf_init_iov(&r2t->headbuf, (char*)hdr,
+ 			   sizeof(struct iscsi_hdr));
+ 
+-	r2t->dtask = dtask;
+-
+ 	if (sc->use_sg) {
+ 		int i, sg_count = 0;
+ 		struct scatterlist *sg = sc->request_buffer;
+@@ -352,8 +333,6 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 		iscsi_buf_init_iov(&tcp_ctask->sendbuf,
+ 			    (char*)sc->request_buffer + r2t->data_offset,
+ 			    r2t->data_count);
+-
+-	list_add(&dtask->item, &tcp_ctask->dataqueue);
+ }
+ 
+ /**
+@@ -1229,14 +1208,10 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ {
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	struct iscsi_data *hdr;
+-	struct iscsi_data_task *dtask;
+ 	struct scsi_cmnd *sc = ctask->sc;
+ 	int new_offset;
+ 
+-	dtask = mempool_alloc(tcp_ctask->datapool, GFP_ATOMIC);
+-	BUG_ON(!dtask);
+-	INIT_LIST_HEAD(&dtask->item);
+-	hdr = &dtask->hdr;
++	hdr = &r2t->dtask.hdr;
+ 	memset(hdr, 0, sizeof(struct iscsi_data));
+ 	hdr->ttt = r2t->ttt;
+ 	hdr->datasn = cpu_to_be32(r2t->solicit_datasn);
+@@ -1260,8 +1235,6 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 	iscsi_buf_init_iov(&r2t->headbuf, (char*)hdr,
+ 			   sizeof(struct iscsi_hdr));
+ 
+-	r2t->dtask = dtask;
+-
+ 	if (sc->use_sg && !iscsi_buf_left(&r2t->sendbuf)) {
+ 		BUG_ON(tcp_ctask->bad_sg == r2t->sg);
+ 		iscsi_buf_init_sg(&r2t->sendbuf, r2t->sg);
+@@ -1270,8 +1243,6 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 		iscsi_buf_init_iov(&tcp_ctask->sendbuf,
+ 			    (char*)sc->request_buffer + new_offset,
+ 			    r2t->data_count);
+-
+-	list_add(&dtask->item, &tcp_ctask->dataqueue);
+ }
+ 
+ static void
+@@ -1280,17 +1251,11 @@ iscsi_unsolicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	struct iscsi_data_task *dtask;
+ 
+-	dtask = mempool_alloc(tcp_ctask->datapool, GFP_ATOMIC);
+-	BUG_ON(!dtask);
+-	INIT_LIST_HEAD(&dtask->item);
+-
++	dtask = tcp_ctask->dtask = &tcp_ctask->unsol_dtask;
+ 	iscsi_prep_unsolicit_data_pdu(ctask, &dtask->hdr,
+ 				      tcp_ctask->r2t_data_count);
+ 	iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)&dtask->hdr,
+ 			   sizeof(struct iscsi_hdr));
+-
+-	list_add(&dtask->item, &tcp_ctask->dataqueue);
+-	tcp_ctask->dtask = dtask;
+ }
+ 
+ /**
+@@ -1534,7 +1499,6 @@ handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	tcp_ctask->xmstate |= XMSTATE_UNS_DATA;
+ 	if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) {
+ 		iscsi_unsolicit_data_init(conn, ctask);
+-		BUG_ON(!tcp_ctask->dtask);
+ 		dtask = tcp_ctask->dtask;
+ 		if (conn->hdrdgst_en)
+ 			iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
+@@ -1643,7 +1607,7 @@ handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	struct iscsi_r2t_info *r2t = tcp_ctask->r2t;
+-	struct iscsi_data_task *dtask = r2t->dtask;
++	struct iscsi_data_task *dtask = &r2t->dtask;
+ 	int left;
+ 
+ 	tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA;
+@@ -1857,7 +1821,7 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 		r2t = tcp_ctask->r2t;
+ 		if (conn->hdrdgst_en)
+ 			iscsi_hdr_digest(conn, &r2t->headbuf,
+-					(u8*)r2t->dtask->hdrext);
++					(u8*)r2t->dtask.hdrext);
+ 		if (iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count)) {
+ 			tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA;
+ 			tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
+@@ -2113,21 +2077,6 @@ iscsi_r2tpool_alloc(struct iscsi_session *session)
+ 					(void**)tcp_ctask->r2ts);
+ 			goto r2t_alloc_fail;
+ 		}
+-
+-		/*
+-		 * number of
+-		 * Data-Out PDU's within R2T-sequence can be quite big;
+-		 * using mempool
+-		 */
+-		tcp_ctask->datapool = mempool_create_slab_pool(ISCSI_DTASK_DEFAULT_MAX,
+-							       taskcache);
+-		if (tcp_ctask->datapool == NULL) {
+-			kfifo_free(tcp_ctask->r2tqueue);
+-			iscsi_pool_free(&tcp_ctask->r2tpool,
+-					(void**)tcp_ctask->r2ts);
+-			goto r2t_alloc_fail;
+-		}
+-		INIT_LIST_HEAD(&tcp_ctask->dataqueue);
+ 	}
+ 
+ 	return 0;
+@@ -2137,7 +2086,6 @@ iscsi_r2tpool_alloc(struct iscsi_session *session)
+ 		struct iscsi_cmd_task *ctask = session->cmds[i];
+ 		struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 
+-		mempool_destroy(tcp_ctask->datapool);
+ 		kfifo_free(tcp_ctask->r2tqueue);
+ 		iscsi_pool_free(&tcp_ctask->r2tpool,
+ 				(void**)tcp_ctask->r2ts);
+@@ -2154,7 +2102,6 @@ iscsi_r2tpool_free(struct iscsi_session *session)
+ 		struct iscsi_cmd_task *ctask = session->cmds[i];
+ 		struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 
+-		mempool_destroy(tcp_ctask->datapool);
+ 		kfifo_free(tcp_ctask->r2tqueue);
+ 		iscsi_pool_free(&tcp_ctask->r2tpool,
+ 				(void**)tcp_ctask->r2ts);
+@@ -2496,21 +2443,6 @@ iscsi_tcp_session_create(struct iscsi_transport *iscsit,
+ 
+ static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session)
+ {
+-	struct iscsi_session *session = class_to_transport_session(cls_session);
+-	struct iscsi_data_task *dtask, *n;
+-	int cmd_i;
+-
+-	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
+-		struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
+-		struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+-
+-		list_for_each_entry_safe(dtask, n, &tcp_ctask->dataqueue,
+-					 item) {
+-			list_del(&dtask->item);
+-			mempool_free(dtask, tcp_ctask->datapool);
+-		}
+-	}
+-
+ 	iscsi_r2tpool_free(class_to_transport_session(cls_session));
+ 	iscsi_session_teardown(cls_session);
+ }
+@@ -2592,14 +2524,8 @@ iscsi_tcp_init(void)
+ 	}
+ 	iscsi_tcp_transport.max_lun = iscsi_max_lun;
+ 
+-	taskcache = kmem_cache_create("iscsi_taskcache",
+-			sizeof(struct iscsi_data_task), 0,
+-			SLAB_HWCACHE_ALIGN, NULL, NULL);
+-	if (!taskcache)
+-		return -ENOMEM;
+-
+ 	if (!iscsi_register_transport(&iscsi_tcp_transport))
+-		kmem_cache_destroy(taskcache);
++		return -ENODEV;
+ 
+ 	return 0;
+ }
+@@ -2608,7 +2534,6 @@ static void __exit
+ iscsi_tcp_exit(void)
+ {
+ 	iscsi_unregister_transport(&iscsi_tcp_transport);
+-	kmem_cache_destroy(taskcache);
+ }
+ 
+ module_init(iscsi_tcp_init);
+diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
+index c5918854d595..808302832e68 100644
+--- a/drivers/scsi/iscsi_tcp.h
++++ b/drivers/scsi/iscsi_tcp.h
+@@ -118,11 +118,9 @@ struct iscsi_buf {
+ struct iscsi_data_task {
+ 	struct iscsi_data	hdr;			/* PDU */
+ 	char			hdrext[sizeof(__u32)];	/* Header-Digest */
+-	struct list_head	item;			/* data queue item */
+ 	struct iscsi_buf	digestbuf;		/* digest buffer */
+ 	uint32_t		digest;			/* data digest */
+ };
+-#define ISCSI_DTASK_DEFAULT_MAX	ISCSI_SG_TABLESIZE * PAGE_SIZE / 512
+ 
+ struct iscsi_tcp_mgmt_task {
+ 	struct iscsi_hdr	hdr;
+@@ -144,7 +142,7 @@ struct iscsi_r2t_info {
+ 	int			data_count;	/* DATA-Out payload progress */
+ 	struct scatterlist	*sg;		/* per-R2T SG list */
+ 	int			solicit_datasn;
+-	struct iscsi_data_task   *dtask;        /* which data task */
++	struct iscsi_data_task   dtask;        /* which data task */
+ };
+ 
+ struct iscsi_tcp_cmd_task {
+@@ -167,14 +165,13 @@ struct iscsi_tcp_cmd_task {
+ 	struct iscsi_queue	r2tpool;
+ 	struct kfifo		*r2tqueue;
+ 	struct iscsi_r2t_info	**r2ts;
+-	struct list_head	dataqueue;		/* Data-Out dataqueue */
+-	mempool_t		*datapool;
+ 	uint32_t		datadigest;		/* for recover digest */
+ 	int			digest_count;
+ 	uint32_t		immdigest;		/* for imm data */
+ 	struct iscsi_buf	immbuf;			/* for imm data digest */
+-	struct iscsi_data_task   *dtask;		/* data task in progress*/
+-	int			digest_offset;		/* for partial buff digest */
++	struct iscsi_data_task	*dtask;		/* data task in progress*/
++	struct iscsi_data_task	unsol_dtask;	/* unsol data task */
++	int			digest_offset;	/* for partial buff digest */
+ };
+ 
+ #endif /* ISCSI_H */

commit d36ab6f3212053b260214bc915687765e2fd1178
+Author: Mike Christie 
+Date:   Thu May 18 20:31:34 2006 -0500
+
+    [SCSI] iscsi: only preallocate login buffer
+    
+    We only use the mtask data buffer for login tasks so we do not
+    need to preallocate a buffer for every mtask. This saves
+    8 * 31 KB.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 4750d4888100..580c0505603c 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1258,15 +1258,6 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
+ 		if (mgmt_task_size)
+ 			mtask->dd_data = &mtask[1];
+ 		mtask->itt = ISCSI_MGMT_ITT_OFFSET + cmd_i;
+-		mtask->data = kmalloc(DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH,
+-				     GFP_KERNEL);
+-		if (!mtask->data) {
+-			int j;
+-
+-			for (j = 0; j < cmd_i; j++)
+-				kfree(session->mgmt_cmds[j]->data);
+-			goto immdata_alloc_fail;
+-		}
+ 	}
+ 
+ 	if (scsi_add_host(shost, NULL))
+@@ -1282,9 +1273,6 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
+ cls_session_fail:
+ 	scsi_remove_host(shost);
+ add_host_fail:
+-	for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++)
+-		kfree(session->mgmt_cmds[cmd_i]->data);
+-immdata_alloc_fail:
+ 	iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
+ mgmtpool_alloc_fail:
+ 	iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
+@@ -1305,13 +1293,9 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+ {
+ 	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+ 	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+-	int cmd_i;
+ 
+ 	scsi_remove_host(shost);
+ 
+-	for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++)
+-		kfree(session->mgmt_cmds[cmd_i]->data);
+-
+ 	iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
+ 	iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
+ 
+@@ -1331,6 +1315,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ 	struct iscsi_session *session = class_to_transport_session(cls_session);
+ 	struct iscsi_conn *conn;
+ 	struct iscsi_cls_conn *cls_conn;
++	char *data;
+ 
+ 	cls_conn = iscsi_create_conn(cls_session, conn_idx);
+ 	if (!cls_conn)
+@@ -1376,12 +1361,20 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ 	}
+ 	spin_unlock_bh(&session->lock);
+ 
++	data = kmalloc(DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, GFP_KERNEL);
++	if (!data)
++		goto login_mtask_data_alloc_fail;
++	conn->login_mtask->data = data;
++
+ 	init_timer(&conn->tmabort_timer);
+ 	mutex_init(&conn->xmitmutex);
+ 	init_waitqueue_head(&conn->ehwait);
+ 
+ 	return cls_conn;
+ 
++login_mtask_data_alloc_fail:
++	__kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask,
++		    sizeof(void*));
+ login_mtask_alloc_fail:
+ 	kfifo_free(conn->mgmtqueue);
+ mgmtqueue_alloc_fail:
+@@ -1451,6 +1444,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
+ 	}
+ 
+ 	spin_lock_bh(&session->lock);
++	kfree(conn->login_mtask->data);
+ 	__kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask,
+ 		    sizeof(void*));
+ 	list_del(&conn->item);

commit 6e458cc943dd494ac68b570418f187883e555362
+Author: Mike Christie 
+Date:   Thu May 18 20:31:31 2006 -0500
+
+    [SCSI] iscsi: dont use sendpage for iscsi headers
+    
+    From Zhen and ported by Mike:
+    
+    Don't use sendpage for the headers. sendpage for the pdu headers
+    does not seem to have a performance impact, makes life harder
+    for mutiple data pdus to be in flight and still trips up some
+    network cards when it is from slab mem.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index d94038eafb9b..7c2ed7bb7e94 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -70,14 +70,6 @@ module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
+ /* global data */
+ static kmem_cache_t *taskcache;
+ 
+-static inline void
+-iscsi_buf_init_virt(struct iscsi_buf *ibuf, char *vbuf, int size)
+-{
+-	sg_init_one(&ibuf->sg, (u8 *)vbuf, size);
+-	ibuf->sent = 0;
+-	ibuf->use_sendmsg = 0;
+-}
+-
+ static inline void
+ iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size)
+ {
+@@ -324,7 +316,7 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 
+ 	r2t->sent = 0;
+ 
+-	iscsi_buf_init_virt(&r2t->headbuf, (char*)hdr,
++	iscsi_buf_init_iov(&r2t->headbuf, (char*)hdr,
+ 			   sizeof(struct iscsi_hdr));
+ 
+ 	r2t->dtask = dtask;
+@@ -1208,7 +1200,7 @@ iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 	if (final)
+ 		crypto_digest_final(tcp_conn->data_tx_tfm, (u8*)digest);
+ 
+-	iscsi_buf_init_virt(buf, (char*)digest, 4);
++	iscsi_buf_init_iov(buf, (char*)digest, 4);
+ 	rc = iscsi_sendpage(conn, buf, &tcp_ctask->digest_count, &sent);
+ 	if (rc) {
+ 		tcp_ctask->datadigest = *digest;
+@@ -1265,7 +1257,7 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 	}
+ 	conn->dataout_pdus_cnt++;
+ 
+-	iscsi_buf_init_virt(&r2t->headbuf, (char*)hdr,
++	iscsi_buf_init_iov(&r2t->headbuf, (char*)hdr,
+ 			   sizeof(struct iscsi_hdr));
+ 
+ 	r2t->dtask = dtask;
+@@ -1294,7 +1286,7 @@ iscsi_unsolicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 
+ 	iscsi_prep_unsolicit_data_pdu(ctask, &dtask->hdr,
+ 				      tcp_ctask->r2t_data_count);
+-	iscsi_buf_init_virt(&tcp_ctask->headbuf, (char*)&dtask->hdr,
++	iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)&dtask->hdr,
+ 			   sizeof(struct iscsi_hdr));
+ 
+ 	list_add(&dtask->item, &tcp_ctask->dataqueue);
+@@ -1361,7 +1353,7 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask)
+ 	} else
+ 		tcp_ctask->xmstate = XMSTATE_R_HDR;
+ 
+-	iscsi_buf_init_virt(&tcp_ctask->headbuf, (char*)ctask->hdr,
++	iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)ctask->hdr,
+ 			    sizeof(struct iscsi_hdr));
+ }
+ 
+@@ -1758,7 +1750,7 @@ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	int sent;
+ 
+ 	tcp_ctask->xmstate &= ~XMSTATE_W_PAD;
+-	iscsi_buf_init_virt(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad,
++	iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad,
+ 			    tcp_ctask->pad_count);
+ 	if (iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count,
+ 			   &sent)) {
+@@ -2078,8 +2070,8 @@ iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask,
+ {
+ 	struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data;
+ 
+-	iscsi_buf_init_virt(&tcp_mtask->headbuf, (char*)mtask->hdr,
+-				    sizeof(struct iscsi_hdr));
++	iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr,
++			   sizeof(struct iscsi_hdr));
+ 	tcp_mtask->xmstate = XMSTATE_IMM_HDR;
+ 
+ 	if (mtask->data_count)

commit 665b44aee34e9f2c64558df4ec01d40576e45651
+Author: Mike Christie 
+Date:   Tue May 2 19:46:49 2006 -0500
+
+    [SCSI] iscsi: dequeue all buffers from queue
+    
+    debugged by wrwhitehead@novell.com
+    patch and analysis by fujita.tomonori@lab.ntt.co.jp
+    
+    Only tcp_read_sock and recv_actor (iscsi_tcp_data_recv for us) see
+    desc.count. It is is used just for permitting tcp_read_sock to read
+    the portion of data in the socket.
+    
+    When iscsi_tcp_data_recv sees a partial header, it sets
+    desc.count. However, it is possible that the next skb (containing the
+    rest of the header) still does not come. So I'm not sure that this
+    scheme is completely correct.
+    
+    Ideally, we should use the exact length of the data in the socket for
+    desc.count. However, it is not so simple (see SIOCINQ in
+    tcp_ioctl). So I think that iscsi_tcp_data_recv can just stop playing
+    with desc.count and tell tcp_read_sock to read the all skbs. As
+    proposed already, if iscsi_tcp_data_ready sets desc.count to
+    non-zero, tcp_read_sock does that.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index c0ce6ab81a9d..d94038eafb9b 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -922,11 +922,8 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 
+ 		rc = iscsi_data_recv(conn);
+ 		if (rc) {
+-			if (rc == -EAGAIN) {
+-				rd_desc->count = tcp_conn->in.datalen -
+-						tcp_conn->in.ctask->data_count;
++			if (rc == -EAGAIN)
+ 				goto again;
+-			}
+ 			iscsi_conn_failure(conn, rc);
+ 			return 0;
+ 		}
+@@ -983,9 +980,14 @@ iscsi_tcp_data_ready(struct sock *sk, int flag)
+ 
+ 	read_lock(&sk->sk_callback_lock);
+ 
+-	/* use rd_desc to pass 'conn' to iscsi_tcp_data_recv */
++	/*
++	 * Use rd_desc to pass 'conn' to iscsi_tcp_data_recv.
++	 * We set count to 1 because we want the network layer to
++	 * hand us all the skbs that are available. iscsi_tcp_data_recv
++	 * handled pdus that cross buffers or pdus that still need data.
++	 */
+ 	rd_desc.arg.data = conn;
+-	rd_desc.count = 0;
++	rd_desc.count = 1;
+ 	tcp_read_sock(sk, &rd_desc, iscsi_tcp_data_recv);
+ 
+ 	read_unlock(&sk->sk_callback_lock);

commit 8d2860b3c3e933304f49171770658c00ed26fd79
+Author: Mike Christie 
+Date:   Tue May 2 19:46:47 2006 -0500
+
+    [SCSI] iscsi: increment expstatsn during login
+    
+    debugged by Ming and Rohan:
+    
+    The problem Ming and Rohan debugged was that during a normal session
+    login, open-iscsi is not incrementing the exp_statsn counter. It was
+    stuck at zero. From the RFC, it looks like if the login response PDU has
+    a successful status then we should be incrementing that value. Also from
+    the RFC, it looks like if when we drop a connection then reconnect, we
+    should be using the exp_statsn from the old connection in the next
+    relogin attempt.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 41f4bb557ea6..c0ce6ab81a9d 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -2298,6 +2298,9 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
+ 		BUG_ON(value);
+ 		session->ofmarker_en = value;
+ 		break;
++	case ISCSI_PARAM_EXP_STATSN:
++		conn->exp_statsn = value;
++		break;
+ 	default:
+ 		break;
+ 	}
+@@ -2381,6 +2384,9 @@ iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ 		inet = inet_sk(tcp_conn->sock->sk);
+ 		*value = be16_to_cpu(inet->dport);
+ 		mutex_unlock(&conn->xmitmutex);
++	case ISCSI_PARAM_EXP_STATSN:
++		*value = conn->exp_statsn;
++		break;
+ 	default:
+ 		return -EINVAL;
+ 	}
+@@ -2548,7 +2554,8 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 				  ISCSI_DATASEQ_INORDER_EN |
+ 				  ISCSI_ERL |
+ 				  ISCSI_CONN_PORT |
+-				  ISCSI_CONN_ADDRESS,
++				  ISCSI_CONN_ADDRESS |
++				  ISCSI_EXP_STATSN,
+ 	.host_template		= &iscsi_sht,
+ 	.conndata_size		= sizeof(struct iscsi_conn),
+ 	.max_conn		= 1,
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index a99f2ef44e87..4750d4888100 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -333,15 +333,21 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		debug_scsi("immrsp [op 0x%x cid %d itt 0x%x len %d]\n",
+ 			   opcode, conn->id, mtask->itt, datalen);
+ 
++		rc = iscsi_check_assign_cmdsn(session,
++					      (struct iscsi_nopin*)hdr);
++		if (rc)
++			goto done;
++
+ 		switch(opcode) {
++		case ISCSI_OP_LOGOUT_RSP:
++			conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
++			/* fall through */
+ 		case ISCSI_OP_LOGIN_RSP:
+ 		case ISCSI_OP_TEXT_RSP:
+-		case ISCSI_OP_LOGOUT_RSP:
+-			rc = iscsi_check_assign_cmdsn(session,
+-						 (struct iscsi_nopin*)hdr);
+-			if (rc)
+-				break;
+-
++			/*
++			 * login related PDU's exp_statsn is handled in
++			 * userspace
++			 */
+ 			rc = iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen);
+ 			list_del(&mtask->running);
+ 			if (conn->login_mtask != mtask)
+@@ -349,15 +355,12 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 					    (void*)&mtask, sizeof(void*));
+ 			break;
+ 		case ISCSI_OP_SCSI_TMFUNC_RSP:
+-			rc = iscsi_check_assign_cmdsn(session,
+-						 (struct iscsi_nopin*)hdr);
+-			if (rc)
+-				break;
+-
+ 			if (datalen) {
+ 				rc = ISCSI_ERR_PROTO;
+ 				break;
+ 			}
++
++			conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
+ 			conn->tmfrsp_pdus_cnt++;
+ 			if (conn->tmabort_state == TMABORT_INITIAL) {
+ 				conn->tmabort_state =
+@@ -373,10 +376,6 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 				rc = ISCSI_ERR_PROTO;
+ 				break;
+ 			}
+-			rc = iscsi_check_assign_cmdsn(session,
+-						(struct iscsi_nopin*)hdr);
+-			if (rc)
+-				break;
+ 			conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
+ 
+ 			rc = iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen);
+@@ -404,6 +403,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		case ISCSI_OP_REJECT:
+ 			/* we need sth like iscsi_reject_rsp()*/
+ 		case ISCSI_OP_ASYNC_EVENT:
++			conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
+ 			/* we need sth like iscsi_async_event_rsp() */
+ 			rc = ISCSI_ERR_BAD_OPCODE;
+ 			break;
+@@ -414,6 +414,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	} else
+ 		rc = ISCSI_ERR_BAD_ITT;
+ 
++done:
+ 	return rc;
+ }
+ EXPORT_SYMBOL_GPL(__iscsi_complete_pdu);
+@@ -730,6 +731,7 @@ iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	        BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
+ 	        BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
+ 
++		nop->exp_statsn = cpu_to_be32(conn->exp_statsn);
+ 		if (!__kfifo_get(session->mgmtpool.queue,
+ 				 (void*)&mtask, sizeof(void*))) {
+ 			spin_unlock_bh(&session->lock);
+@@ -738,7 +740,7 @@ iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	}
+ 
+ 	/*
+-	 * pre-format CmdSN and ExpStatSN for outgoing PDU.
++	 * pre-format CmdSN for outgoing PDU.
+ 	 */
+ 	if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) {
+ 		hdr->itt = mtask->itt | (conn->id << ISCSI_CID_SHIFT) |
+@@ -751,8 +753,6 @@ iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 		/* do not advance CmdSN */
+ 		nop->cmdsn = cpu_to_be32(session->cmdsn);
+ 
+-	nop->exp_statsn = cpu_to_be32(conn->exp_statsn);
+-
+ 	if (data_size) {
+ 		memcpy(mtask->data, data, data_size);
+ 		mtask->data_count = data_size;
+@@ -1647,7 +1647,7 @@ void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+ 	case STOP_CONN_RECOVER:
+ 	case STOP_CONN_TERM:
+ 		iscsi_start_session_recovery(session, conn, flag);
+-		return;
++		break;
+ 	case STOP_CONN_SUSPEND:
+ 		if (session->tt->suspend_conn_recv)
+ 			session->tt->suspend_conn_recv(conn);
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 1b96f7c4ce7a..44adafac861f 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -32,7 +32,7 @@
+ #include 
+ 
+ #define ISCSI_SESSION_ATTRS 11
+-#define ISCSI_CONN_ATTRS 10
++#define ISCSI_CONN_ATTRS 11
+ #define ISCSI_HOST_ATTRS 0
+ 
+ struct iscsi_internal {
+@@ -1156,6 +1156,7 @@ iscsi_conn_int_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN, "%d");
+ iscsi_conn_int_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN, "%d");
+ iscsi_conn_int_attr(persistent_port, ISCSI_PARAM_PERSISTENT_PORT, "%d");
+ iscsi_conn_int_attr(port, ISCSI_PARAM_CONN_PORT, "%d");
++iscsi_conn_int_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN, "%u");
+ 
+ #define iscsi_conn_str_attr_show(param)					\
+ static ssize_t								\
+@@ -1406,6 +1407,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 	SETUP_CONN_RD_ATTR(ofmarker, ISCSI_OFMARKER_EN);
+ 	SETUP_CONN_RD_ATTR(address, ISCSI_CONN_ADDRESS);
+ 	SETUP_CONN_RD_ATTR(port, ISCSI_CONN_PORT);
++	SETUP_CONN_RD_ATTR(exp_statsn, ISCSI_EXP_STATSN);
+ 
+ 	if (tt->param_mask & ISCSI_PERSISTENT_ADDRESS)
+ 		SETUP_CONN_RD_ATTR(persistent_address, ISCSI_PERSISTENT_ADDRESS);
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index feff74e544b7..253797c60095 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -188,6 +188,7 @@ enum iscsi_param {
+ 	ISCSI_PARAM_ERL,
+ 	ISCSI_PARAM_IFMARKER_EN,
+ 	ISCSI_PARAM_OFMARKER_EN,
++	ISCSI_PARAM_EXP_STATSN,
+ 	ISCSI_PARAM_TARGET_NAME,
+ 	ISCSI_PARAM_TPGT,
+ 	ISCSI_PARAM_PERSISTENT_ADDRESS,
+@@ -216,6 +217,7 @@ enum iscsi_param {
+ #define ISCSI_ERL			(1 << ISCSI_PARAM_ERL)
+ #define ISCSI_IFMARKER_EN		(1 << ISCSI_PARAM_IFMARKER_EN)
+ #define ISCSI_OFMARKER_EN		(1 << ISCSI_PARAM_OFMARKER_EN)
++#define ISCSI_EXP_STATSN		(1 << ISCSI_PARAM_EXP_STATSN)
+ #define ISCSI_TARGET_NAME		(1 << ISCSI_PARAM_TARGET_NAME)
+ #define ISCSI_TPGT			(1 << ISCSI_PARAM_TPGT)
+ #define ISCSI_PERSISTENT_ADDRESS	(1 << ISCSI_PARAM_PERSISTENT_ADDRESS)

commit ed2abc7ff19dc99c6242a70f8578a17b2ff0d0ce
+Author: Mike Christie 
+Date:   Tue May 2 19:46:40 2006 -0500
+
+    [SCSI] iscsi: fix manamgement task oops
+    
+    from patmans@us.ibm.com and michaelc@cs.wisc.edu
+    
+    Fix bugs when forcing a mgmt task to fail and allow
+    session recovery to cleanup the session/connection
+    of any running mgmt tasks. When called during
+    the in login state.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 274a1374ab64..8c51f6c36661 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1538,10 +1538,11 @@ flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn)
+ 	/* handle running */
+ 	list_for_each_entry_safe(mtask, tmp, &conn->mgmt_run_list, running) {
+ 		debug_scsi("flushing running mgmt task itt 0x%x\n", mtask->itt);
++		list_del(&mtask->running);
++
+ 		if (mtask == conn->login_mtask)
+ 			continue;
+-		list_del(&mtask->running);
+-		__kfifo_put(session->mgmtpool.queue, (void*)&conn->mtask,
++		__kfifo_put(session->mgmtpool.queue, (void*)&mtask,
+ 			   sizeof(void*));
+ 	}
+ 
+@@ -1573,12 +1574,22 @@ static void fail_all_commands(struct iscsi_conn *conn)
+ void iscsi_start_session_recovery(struct iscsi_session *session,
+ 				  struct iscsi_conn *conn, int flag)
+ {
++	int old_stop_stage;
++
+ 	spin_lock_bh(&session->lock);
+-	if (conn->stop_stage == STOP_CONN_RECOVER ||
+-	    conn->stop_stage == STOP_CONN_TERM) {
++	if (conn->stop_stage == STOP_CONN_TERM) {
+ 		spin_unlock_bh(&session->lock);
+ 		return;
+ 	}
++
++	/*
++	 * When this is called for the in_login state, we only want to clean
++	 * up the login task and connection.
++	 */
++	if (conn->stop_stage != STOP_CONN_RECOVER)
++		session->conn_cnt--;
++
++	old_stop_stage = conn->stop_stage;
+ 	conn->stop_stage = flag;
+ 	spin_unlock_bh(&session->lock);
+ 
+@@ -1590,7 +1601,6 @@ void iscsi_start_session_recovery(struct iscsi_session *session,
+ 	conn->c_stage = ISCSI_CONN_STOPPED;
+ 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+ 
+-	session->conn_cnt--;
+ 	if (session->conn_cnt == 0 || session->leadconn == conn)
+ 		session->state = ISCSI_STATE_FAILED;
+ 
+@@ -1615,7 +1625,12 @@ void iscsi_start_session_recovery(struct iscsi_session *session,
+ 		conn->hdrdgst_en = 0;
+ 		conn->datadgst_en = 0;
+ 
+-		if (session->state == ISCSI_STATE_FAILED)
++		/*
++		 * if this is called from the eh and and from userspace
++		 * then we only need to block once.
++		 */
++		if (session->state == ISCSI_STATE_FAILED &&
++		    old_stop_stage != STOP_CONN_RECOVER)
+ 			iscsi_block_session(session_to_cls(session));
+ 	}
+ 	mutex_unlock(&conn->xmitmutex);

commit 5bb0b55a3283369f1cd8ac76a6d8bda8e7a77055
+Author: Mike Christie 
+Date:   Thu Apr 6 21:26:46 2006 -0500
+
+    [SCSI] iscsi: convert iscsi tcp to libiscsi
+    
+    This just converts iscsi_tcp to the lib
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index aca3e23b1b9e..fe00a3f6d204 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -3,7 +3,8 @@
+  *
+  * Copyright (C) 2004 Dmitry Yusupov
+  * Copyright (C) 2004 Alex Aizman
+- * Copyright (C) 2005 Mike Christie
++ * Copyright (C) 2005 - 2006 Mike Christie
++ * Copyright (C) 2006 Red Hat, Inc.  All rights reserved.
+  * maintained by open-iscsi@googlegroups.com
+  *
+  * This program is free software; you can redistribute it and/or modify
+@@ -36,10 +37,6 @@
+ #include 
+ #include 
+ #include 
+-#include 
+-#include 
+-#include 
+-#include 
+ #include 
+ #include 
+ #include 
+@@ -52,21 +49,14 @@ MODULE_DESCRIPTION("iSCSI/TCP data-path");
+ MODULE_LICENSE("GPL");
+ MODULE_VERSION("0:4.445");
+ /* #define DEBUG_TCP */
+-/* #define DEBUG_SCSI */
+ #define DEBUG_ASSERT
+ 
+ #ifdef DEBUG_TCP
+-#define debug_tcp(fmt...) printk(KERN_DEBUG "tcp: " fmt)
++#define debug_tcp(fmt...) printk(KERN_INFO "tcp: " fmt)
+ #else
+ #define debug_tcp(fmt...)
+ #endif
+ 
+-#ifdef DEBUG_SCSI
+-#define debug_scsi(fmt...) printk(KERN_DEBUG "scsi: " fmt)
+-#else
+-#define debug_scsi(fmt...)
+-#endif
+-
+ #ifndef DEBUG_ASSERT
+ #ifdef BUG_ON
+ #undef BUG_ON
+@@ -74,17 +64,12 @@ MODULE_VERSION("0:4.445");
+ #define BUG_ON(expr)
+ #endif
+ 
+-#define INVALID_SN_DELTA	0xffff
+-
+ static unsigned int iscsi_max_lun = 512;
+ module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
+ 
+ /* global data */
+ static kmem_cache_t *taskcache;
+ 
+-#define session_to_cls(_sess) \
+-	hostdata_session(_sess->host->hostdata)
+-
+ static inline void
+ iscsi_buf_init_virt(struct iscsi_buf *ibuf, char *vbuf, int size)
+ {
+@@ -133,68 +118,39 @@ static inline void
+ iscsi_hdr_digest(struct iscsi_conn *conn, struct iscsi_buf *buf,
+ 		 u8* crc)
+ {
+-	crypto_digest_digest(conn->tx_tfm, &buf->sg, 1, crc);
+-	buf->sg.length += sizeof(uint32_t);
+-}
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 
+-static void
+-iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
+-{
+-	struct iscsi_session *session = conn->session;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&session->lock, flags);
+-	if (session->conn_cnt == 1 || session->leadconn == conn)
+-		session->state = ISCSI_STATE_FAILED;
+-	spin_unlock_irqrestore(&session->lock, flags);
+-	set_bit(SUSPEND_BIT, &conn->suspend_tx);
+-	set_bit(SUSPEND_BIT, &conn->suspend_rx);
+-	iscsi_conn_error(conn->cls_conn, err);
++	crypto_digest_digest(tcp_conn->tx_tfm, &buf->sg, 1, crc);
++	buf->sg.length += sizeof(uint32_t);
+ }
+ 
+ static inline int
+-iscsi_check_assign_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
++iscsi_hdr_extract(struct iscsi_tcp_conn *tcp_conn)
+ {
+-	uint32_t max_cmdsn = be32_to_cpu(hdr->max_cmdsn);
+-	uint32_t exp_cmdsn = be32_to_cpu(hdr->exp_cmdsn);
+-
+-	if (max_cmdsn < exp_cmdsn -1 &&
+-	    max_cmdsn > exp_cmdsn - INVALID_SN_DELTA)
+-		return ISCSI_ERR_MAX_CMDSN;
+-	if (max_cmdsn > session->max_cmdsn ||
+-	    max_cmdsn < session->max_cmdsn - INVALID_SN_DELTA)
+-		session->max_cmdsn = max_cmdsn;
+-	if (exp_cmdsn > session->exp_cmdsn ||
+-	    exp_cmdsn < session->exp_cmdsn - INVALID_SN_DELTA)
+-		session->exp_cmdsn = exp_cmdsn;
+-
+-	return 0;
+-}
++	struct sk_buff *skb = tcp_conn->in.skb;
+ 
+-static inline int
+-iscsi_hdr_extract(struct iscsi_conn *conn)
+-{
+-	struct sk_buff *skb = conn->in.skb;
++	tcp_conn->in.zero_copy_hdr = 0;
+ 
+-	if (conn->in.copy >= conn->hdr_size &&
+-	    conn->in_progress == IN_PROGRESS_WAIT_HEADER) {
++	if (tcp_conn->in.copy >= tcp_conn->hdr_size &&
++	    tcp_conn->in_progress == IN_PROGRESS_WAIT_HEADER) {
+ 		/*
+ 		 * Zero-copy PDU Header: using connection context
+ 		 * to store header pointer.
+ 		 */
+ 		if (skb_shinfo(skb)->frag_list == NULL &&
+-		    !skb_shinfo(skb)->nr_frags)
+-			conn->in.hdr = (struct iscsi_hdr *)
+-				((char*)skb->data + conn->in.offset);
+-		else {
++		    !skb_shinfo(skb)->nr_frags) {
++			tcp_conn->in.hdr = (struct iscsi_hdr *)
++				((char*)skb->data + tcp_conn->in.offset);
++			tcp_conn->in.zero_copy_hdr = 1;
++		} else {
+ 			/* ignoring return code since we checked
+ 			 * in.copy before */
+-			skb_copy_bits(skb, conn->in.offset,
+-				&conn->hdr, conn->hdr_size);
+-			conn->in.hdr = &conn->hdr;
++			skb_copy_bits(skb, tcp_conn->in.offset,
++				&tcp_conn->hdr, tcp_conn->hdr_size);
++			tcp_conn->in.hdr = &tcp_conn->hdr;
+ 		}
+-		conn->in.offset += conn->hdr_size;
+-		conn->in.copy -= conn->hdr_size;
++		tcp_conn->in.offset += tcp_conn->hdr_size;
++		tcp_conn->in.copy -= tcp_conn->hdr_size;
+ 	} else {
+ 		int hdr_remains;
+ 		int copylen;
+@@ -204,30 +160,31 @@ iscsi_hdr_extract(struct iscsi_conn *conn)
+ 		 * copying it... This'll happen quite rarely.
+ 		 */
+ 
+-		if (conn->in_progress == IN_PROGRESS_WAIT_HEADER)
+-			conn->in.hdr_offset = 0;
++		if (tcp_conn->in_progress == IN_PROGRESS_WAIT_HEADER)
++			tcp_conn->in.hdr_offset = 0;
+ 
+-		hdr_remains = conn->hdr_size - conn->in.hdr_offset;
++		hdr_remains = tcp_conn->hdr_size - tcp_conn->in.hdr_offset;
+ 		BUG_ON(hdr_remains <= 0);
+ 
+-		copylen = min(conn->in.copy, hdr_remains);
+-		skb_copy_bits(skb, conn->in.offset,
+-			(char*)&conn->hdr + conn->in.hdr_offset, copylen);
++		copylen = min(tcp_conn->in.copy, hdr_remains);
++		skb_copy_bits(skb, tcp_conn->in.offset,
++			(char*)&tcp_conn->hdr + tcp_conn->in.hdr_offset,
++			copylen);
+ 
+ 		debug_tcp("PDU gather offset %d bytes %d in.offset %d "
+-		       "in.copy %d\n", conn->in.hdr_offset, copylen,
+-		       conn->in.offset, conn->in.copy);
++		       "in.copy %d\n", tcp_conn->in.hdr_offset, copylen,
++		       tcp_conn->in.offset, tcp_conn->in.copy);
+ 
+-		conn->in.offset += copylen;
+-		conn->in.copy -= copylen;
++		tcp_conn->in.offset += copylen;
++		tcp_conn->in.copy -= copylen;
+ 		if (copylen < hdr_remains)  {
+-			conn->in_progress = IN_PROGRESS_HEADER_GATHER;
+-			conn->in.hdr_offset += copylen;
++			tcp_conn->in_progress = IN_PROGRESS_HEADER_GATHER;
++			tcp_conn->in.hdr_offset += copylen;
+ 		        return -EAGAIN;
+ 		}
+-		conn->in.hdr = &conn->hdr;
+-		conn->discontiguous_hdr_cnt++;
+-	        conn->in_progress = IN_PROGRESS_WAIT_HEADER;
++		tcp_conn->in.hdr = &tcp_conn->hdr;
++		tcp_conn->discontiguous_hdr_cnt++;
++	        tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
+ 	}
+ 
+ 	return 0;
+@@ -239,7 +196,7 @@ iscsi_hdr_extract(struct iscsi_conn *conn)
+ static void
+ __iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+-	struct iscsi_session *session = conn->session;
++	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	struct scsi_cmnd *sc;
+ 
+ 	sc = ctask->sc;
+@@ -248,88 +205,16 @@ __iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 
+ 	if (sc->sc_data_direction == DMA_TO_DEVICE) {
+ 		struct iscsi_data_task *dtask, *n;
++
+ 		/* WRITE: cleanup Data-Out's if any */
+-		list_for_each_entry_safe(dtask, n, &ctask->dataqueue, item) {
++		list_for_each_entry_safe(dtask, n, &tcp_ctask->dataqueue,
++					 item) {
+ 			list_del(&dtask->item);
+-			mempool_free(dtask, ctask->datapool);
++			mempool_free(dtask, tcp_ctask->datapool);
+ 		}
+ 	}
+-	ctask->xmstate = XMSTATE_IDLE;
+-	ctask->r2t = NULL;
+-	ctask->sc = NULL;
+-	list_del(&ctask->running);
+-
+-	__kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*));
+-
+-	sc->scsi_done(sc);
+-}
+-
+-static void
+-iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+-{
+-	struct iscsi_session *session = conn->session;
+-
+-	spin_lock(&session->lock);
+-	__iscsi_ctask_cleanup(conn, ctask);
+-	spin_unlock(&session->lock);
+-}
+-
+-/**
+- * iscsi_cmd_rsp - SCSI Command Response processing
+- * @conn: iscsi connection
+- * @ctask: scsi command task
+- **/
+-static int
+-iscsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+-{
+-	int rc;
+-	struct iscsi_cmd_rsp *rhdr = (struct iscsi_cmd_rsp *)conn->in.hdr;
+-	struct iscsi_session *session = conn->session;
+-	struct scsi_cmnd *sc = ctask->sc;
+-
+-	rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr);
+-	if (rc) {
+-		sc->result = (DID_ERROR << 16);
+-		goto out;
+-	}
+-
+-	conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
+-
+-	sc->result = (DID_OK << 16) | rhdr->cmd_status;
+-
+-	if (rhdr->response != ISCSI_STATUS_CMD_COMPLETED) {
+-		sc->result = (DID_ERROR << 16);
+-		goto out;
+-	}
+-
+-	if (rhdr->cmd_status == SAM_STAT_CHECK_CONDITION && conn->senselen) {
+-		int sensecopy = min(conn->senselen, SCSI_SENSE_BUFFERSIZE);
+-
+-		memcpy(sc->sense_buffer, conn->data + 2, sensecopy);
+-		debug_scsi("copied %d bytes of sense\n", sensecopy);
+-	}
+-
+-	if (sc->sc_data_direction == DMA_TO_DEVICE)
+-		goto out;
+-
+-	if (rhdr->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
+-		int res_count = be32_to_cpu(rhdr->residual_count);
+-
+-		if (res_count > 0 && res_count <= sc->request_bufflen)
+-			sc->resid = res_count;
+-		else
+-			sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+-	} else if (rhdr->flags & ISCSI_FLAG_CMD_BIDI_UNDERFLOW)
+-		sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+-	else if (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW)
+-		sc->resid = be32_to_cpu(rhdr->residual_count);
+-
+-out:
+-	debug_scsi("done [sc %lx res %d itt 0x%x]\n",
+-		   (long)sc, sc->result, ctask->itt);
+-	conn->scsirsp_pdus_cnt++;
+-	iscsi_ctask_cleanup(conn, ctask);
+-	return rc;
++	tcp_ctask->xmstate = XMSTATE_IDLE;
++	tcp_ctask->r2t = NULL;
+ }
+ 
+ /**
+@@ -341,7 +226,9 @@ static int
+ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+ 	int rc;
+-	struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)conn->in.hdr;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++	struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)tcp_conn->in.hdr;
+ 	struct iscsi_session *session = conn->session;
+ 	int datasn = be32_to_cpu(rhdr->datasn);
+ 
+@@ -351,9 +238,9 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	/*
+ 	 * setup Data-In byte counter (gets decremented..)
+ 	 */
+-	ctask->data_count = conn->in.datalen;
++	ctask->data_count = tcp_conn->in.datalen;
+ 
+-	if (conn->in.datalen == 0)
++	if (tcp_conn->in.datalen == 0)
+ 		return 0;
+ 
+ 	if (ctask->datasn != datasn)
+@@ -361,8 +248,8 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 
+ 	ctask->datasn++;
+ 
+-	ctask->data_offset = be32_to_cpu(rhdr->offset);
+-	if (ctask->data_offset + conn->in.datalen > ctask->total_length)
++	tcp_ctask->data_offset = be32_to_cpu(rhdr->offset);
++	if (tcp_ctask->data_offset + tcp_conn->in.datalen > ctask->total_length)
+ 		return ISCSI_ERR_DATA_OFFSET;
+ 
+ 	if (rhdr->flags & ISCSI_FLAG_DATA_STATUS) {
+@@ -409,8 +296,9 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 	struct iscsi_data *hdr;
+ 	struct iscsi_data_task *dtask;
+ 	struct scsi_cmnd *sc = ctask->sc;
++	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 
+-	dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC);
++	dtask = mempool_alloc(tcp_ctask->datapool, GFP_ATOMIC);
+ 	BUG_ON(!dtask);
+ 	INIT_LIST_HEAD(&dtask->item);
+ 	hdr = &dtask->hdr;
+@@ -419,8 +307,8 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 	hdr->datasn = cpu_to_be32(r2t->solicit_datasn);
+ 	r2t->solicit_datasn++;
+ 	hdr->opcode = ISCSI_OP_SCSI_DATA_OUT;
+-	memcpy(hdr->lun, ctask->hdr.lun, sizeof(hdr->lun));
+-	hdr->itt = ctask->hdr.itt;
++	memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun));
++	hdr->itt = ctask->hdr->itt;
+ 	hdr->exp_statsn = r2t->exp_statsn;
+ 	hdr->offset = cpu_to_be32(r2t->data_offset);
+ 	if (r2t->data_length > conn->max_xmit_dlength) {
+@@ -469,11 +357,11 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 		}
+ 		BUG_ON(r2t->sg == NULL);
+ 	} else
+-		iscsi_buf_init_iov(&ctask->sendbuf,
++		iscsi_buf_init_iov(&tcp_ctask->sendbuf,
+ 			    (char*)sc->request_buffer + r2t->data_offset,
+ 			    r2t->data_count);
+ 
+-	list_add(&dtask->item, &ctask->dataqueue);
++	list_add(&dtask->item, &tcp_ctask->dataqueue);
+ }
+ 
+ /**
+@@ -486,17 +374,16 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+ 	struct iscsi_r2t_info *r2t;
+ 	struct iscsi_session *session = conn->session;
+-	struct iscsi_r2t_rsp *rhdr = (struct iscsi_r2t_rsp *)conn->in.hdr;
++	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	struct iscsi_r2t_rsp *rhdr = (struct iscsi_r2t_rsp *)tcp_conn->in.hdr;
+ 	int r2tsn = be32_to_cpu(rhdr->r2tsn);
+ 	int rc;
+ 
+-	if (conn->in.ahslen)
+-		return ISCSI_ERR_AHSLEN;
+-
+-	if (conn->in.datalen)
++	if (tcp_conn->in.datalen)
+ 		return ISCSI_ERR_DATALEN;
+ 
+-	if (ctask->exp_r2tsn && ctask->exp_r2tsn != r2tsn)
++	if (tcp_ctask->exp_r2tsn && tcp_ctask->exp_r2tsn != r2tsn)
+ 		return ISCSI_ERR_R2TSN;
+ 
+ 	rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr);
+@@ -514,7 +401,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 		spin_unlock(&session->lock);
+ 		return 0;
+ 	}
+-	rc = __kfifo_get(ctask->r2tpool.queue, (void*)&r2t, sizeof(void*));
++	rc = __kfifo_get(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*));
+ 	BUG_ON(!rc);
+ 
+ 	r2t->exp_statsn = rhdr->statsn;
+@@ -536,10 +423,10 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 
+ 	iscsi_solicit_data_init(conn, ctask, r2t);
+ 
+-	ctask->exp_r2tsn = r2tsn + 1;
+-	ctask->xmstate |= XMSTATE_SOL_HDR;
+-	__kfifo_put(ctask->r2tqueue, (void*)&r2t, sizeof(void*));
+-	__kfifo_put(conn->writequeue, (void*)&ctask, sizeof(void*));
++	tcp_ctask->exp_r2tsn = r2tsn + 1;
++	tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
++	__kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*));
++	__kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*));
+ 
+ 	scsi_queue_work(session->host, &conn->xmitwork);
+ 	conn->r2t_pdus_cnt++;
+@@ -549,256 +436,136 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ }
+ 
+ static int
+-iscsi_hdr_recv(struct iscsi_conn *conn)
++iscsi_tcp_hdr_recv(struct iscsi_conn *conn)
+ {
+-	int rc = 0;
++	int rc = 0, opcode, ahslen;
+ 	struct iscsi_hdr *hdr;
+-	struct iscsi_cmd_task *ctask;
+ 	struct iscsi_session *session = conn->session;
+-	uint32_t cdgst, rdgst = 0;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	uint32_t cdgst, rdgst = 0, itt;
+ 
+-	hdr = conn->in.hdr;
++	hdr = tcp_conn->in.hdr;
+ 
+ 	/* verify PDU length */
+-	conn->in.datalen = ntoh24(hdr->dlength);
+-	if (conn->in.datalen > conn->max_recv_dlength) {
++	tcp_conn->in.datalen = ntoh24(hdr->dlength);
++	if (tcp_conn->in.datalen > conn->max_recv_dlength) {
+ 		printk(KERN_ERR "iscsi_tcp: datalen %d > %d\n",
+-		       conn->in.datalen, conn->max_recv_dlength);
++		       tcp_conn->in.datalen, conn->max_recv_dlength);
+ 		return ISCSI_ERR_DATALEN;
+ 	}
+-	conn->data_copied = 0;
++	tcp_conn->data_copied = 0;
+ 
+ 	/* read AHS */
+-	conn->in.ahslen = hdr->hlength * 4;
+-	conn->in.offset += conn->in.ahslen;
+-	conn->in.copy -= conn->in.ahslen;
+-	if (conn->in.copy < 0) {
++	ahslen = hdr->hlength << 2;
++	tcp_conn->in.offset += ahslen;
++	tcp_conn->in.copy -= ahslen;
++	if (tcp_conn->in.copy < 0) {
+ 		printk(KERN_ERR "iscsi_tcp: can't handle AHS with length "
+-		       "%d bytes\n", conn->in.ahslen);
++		       "%d bytes\n", ahslen);
+ 		return ISCSI_ERR_AHSLEN;
+ 	}
+ 
+ 	/* calculate read padding */
+-	conn->in.padding = conn->in.datalen & (ISCSI_PAD_LEN-1);
+-	if (conn->in.padding) {
+-		conn->in.padding = ISCSI_PAD_LEN - conn->in.padding;
+-		debug_scsi("read padding %d bytes\n", conn->in.padding);
++	tcp_conn->in.padding = tcp_conn->in.datalen & (ISCSI_PAD_LEN-1);
++	if (tcp_conn->in.padding) {
++		tcp_conn->in.padding = ISCSI_PAD_LEN - tcp_conn->in.padding;
++		debug_scsi("read padding %d bytes\n", tcp_conn->in.padding);
+ 	}
+ 
+ 	if (conn->hdrdgst_en) {
+ 		struct scatterlist sg;
+ 
+ 		sg_init_one(&sg, (u8 *)hdr,
+-			    sizeof(struct iscsi_hdr) + conn->in.ahslen);
+-		crypto_digest_digest(conn->rx_tfm, &sg, 1, (u8 *)&cdgst);
++			    sizeof(struct iscsi_hdr) + ahslen);
++		crypto_digest_digest(tcp_conn->rx_tfm, &sg, 1, (u8 *)&cdgst);
+ 		rdgst = *(uint32_t*)((char*)hdr + sizeof(struct iscsi_hdr) +
+-				     conn->in.ahslen);
++				     ahslen);
+ 		if (cdgst != rdgst) {
+-			printk(KERN_ERR "iscsi_tcp: itt %x: hdrdgst error "
+-			       "recv 0x%x calc 0x%x\n", conn->in.itt, rdgst,
+-			       cdgst);
++			printk(KERN_ERR "iscsi_tcp: hdrdgst error "
++			       "recv 0x%x calc 0x%x\n", rdgst, cdgst);
+ 			return ISCSI_ERR_HDR_DGST;
+ 		}
+ 	}
+ 
+-	/* save opcode for later */
+-	conn->in.opcode = hdr->opcode & ISCSI_OPCODE_MASK;
+-
++	opcode = hdr->opcode & ISCSI_OPCODE_MASK;
+ 	/* verify itt (itt encoding: age+cid+itt) */
+-	if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) {
+-		if ((hdr->itt & AGE_MASK) !=
+-				(session->age << AGE_SHIFT)) {
+-			printk(KERN_ERR "iscsi_tcp: received itt %x expected "
+-				"session age (%x)\n", hdr->itt,
+-				session->age & AGE_MASK);
+-			return ISCSI_ERR_BAD_ITT;
+-		}
+-
+-		if ((hdr->itt & CID_MASK) != (conn->id << CID_SHIFT)) {
+-			printk(KERN_ERR "iscsi_tcp: received itt %x, expected "
+-				"CID (%x)\n", hdr->itt, conn->id);
+-			return ISCSI_ERR_BAD_ITT;
+-		}
+-		conn->in.itt = hdr->itt & ITT_MASK;
+-	} else
+-		conn->in.itt = hdr->itt;
++	rc = iscsi_verify_itt(conn, hdr, &itt);
++	if (rc == ISCSI_ERR_NO_SCSI_CMD) {
++		tcp_conn->in.datalen = 0; /* force drop */
++		return 0;
++	} else if (rc)
++		return rc;
+ 
+ 	debug_tcp("opcode 0x%x offset %d copy %d ahslen %d datalen %d\n",
+-		  hdr->opcode, conn->in.offset, conn->in.copy,
+-		  conn->in.ahslen, conn->in.datalen);
+-
+-	if (conn->in.itt < session->cmds_max) {
+-		ctask = (struct iscsi_cmd_task *)session->cmds[conn->in.itt];
+-
+-		if (!ctask->sc) {
+-			printk(KERN_INFO "iscsi_tcp: dropping ctask with "
+-			       "itt 0x%x\n", ctask->itt);
+-			conn->in.datalen = 0; /* force drop */
+-			return 0;
+-		}
+-
+-		if (ctask->sc->SCp.phase != session->age) {
+-			printk(KERN_ERR "iscsi_tcp: ctask's session age %d, "
+-				"expected %d\n", ctask->sc->SCp.phase,
+-				session->age);
+-			return ISCSI_ERR_SESSION_FAILED;
+-		}
+-
+-		conn->in.ctask = ctask;
+-
+-		debug_scsi("rsp [op 0x%x cid %d sc %lx itt 0x%x len %d]\n",
+-			   hdr->opcode, conn->id, (long)ctask->sc,
+-			   ctask->itt, conn->in.datalen);
+-
+-		switch(conn->in.opcode) {
+-		case ISCSI_OP_SCSI_CMD_RSP:
+-			BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
+-			if (!conn->in.datalen)
+-				rc = iscsi_cmd_rsp(conn, ctask);
+-			else
+-				/*
+-				 * got sense or response data; copying PDU
+-				 * Header to the connection's header
+-				 * placeholder
+-				 */
+-				memcpy(&conn->hdr, hdr,
+-				       sizeof(struct iscsi_hdr));
+-			break;
+-		case ISCSI_OP_SCSI_DATA_IN:
+-			BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
+-			/* save flags for non-exceptional status */
+-			conn->in.flags = hdr->flags;
+-			/* save cmd_status for sense data */
+-			conn->in.cmd_status =
+-				((struct iscsi_data_rsp*)hdr)->cmd_status;
+-			rc = iscsi_data_rsp(conn, ctask);
+-			break;
+-		case ISCSI_OP_R2T:
+-			BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
+-			if (ctask->sc->sc_data_direction == DMA_TO_DEVICE)
+-				rc = iscsi_r2t_rsp(conn, ctask);
+-			else
+-				rc = ISCSI_ERR_PROTO;
+-			break;
+-		default:
+-			rc = ISCSI_ERR_BAD_OPCODE;
+-			break;
+-		}
+-	} else if (conn->in.itt >= ISCSI_MGMT_ITT_OFFSET &&
+-		   conn->in.itt < ISCSI_MGMT_ITT_OFFSET +
+-					session->mgmtpool_max) {
+-		struct iscsi_mgmt_task *mtask = (struct iscsi_mgmt_task *)
+-					session->mgmt_cmds[conn->in.itt -
+-						ISCSI_MGMT_ITT_OFFSET];
+-
+-		debug_scsi("immrsp [op 0x%x cid %d itt 0x%x len %d]\n",
+-			   conn->in.opcode, conn->id, mtask->itt,
+-			   conn->in.datalen);
+-
+-		switch(conn->in.opcode) {
+-		case ISCSI_OP_LOGIN_RSP:
+-		case ISCSI_OP_TEXT_RSP:
+-		case ISCSI_OP_LOGOUT_RSP:
+-			rc = iscsi_check_assign_cmdsn(session,
+-						 (struct iscsi_nopin*)hdr);
+-			if (rc)
+-				break;
++		  opcode, tcp_conn->in.offset, tcp_conn->in.copy,
++		  ahslen, tcp_conn->in.datalen);
+ 
+-			if (!conn->in.datalen) {
+-				rc = iscsi_recv_pdu(conn->cls_conn, hdr,
+-						    NULL, 0);
+-				if (conn->login_mtask != mtask) {
+-					spin_lock(&session->lock);
+-					__kfifo_put(session->mgmtpool.queue,
+-					    (void*)&mtask, sizeof(void*));
+-					spin_unlock(&session->lock);
+-				}
+-			}
+-			break;
+-		case ISCSI_OP_SCSI_TMFUNC_RSP:
+-			rc = iscsi_check_assign_cmdsn(session,
+-						 (struct iscsi_nopin*)hdr);
+-			if (rc)
+-				break;
++	switch(opcode) {
++	case ISCSI_OP_SCSI_DATA_IN:
++		tcp_conn->in.ctask = session->cmds[itt];
++		rc = iscsi_data_rsp(conn, tcp_conn->in.ctask);
++		/* fall through */
++	case ISCSI_OP_SCSI_CMD_RSP:
++		tcp_conn->in.ctask = session->cmds[itt];
++		if (tcp_conn->in.datalen)
++			goto copy_hdr;
+ 
+-			if (conn->in.datalen || conn->in.ahslen) {
+-				rc = ISCSI_ERR_PROTO;
+-				break;
+-			}
+-			conn->tmfrsp_pdus_cnt++;
+-			spin_lock(&session->lock);
+-			if (conn->tmabort_state == TMABORT_INITIAL) {
+-				conn->tmabort_state =
+-					((struct iscsi_tm_rsp *)hdr)->
+-					response == ISCSI_TMF_RSP_COMPLETE ?
+-						TMABORT_SUCCESS:TMABORT_FAILED;
+-				/* unblock eh_abort() */
+-				wake_up(&conn->ehwait);
+-			}
+-			spin_unlock(&session->lock);
+-			break;
+-		case ISCSI_OP_NOOP_IN:
+-			if (hdr->ttt != ISCSI_RESERVED_TAG) {
+-				rc = ISCSI_ERR_PROTO;
+-				break;
+-			}
+-			rc = iscsi_check_assign_cmdsn(session,
+-						(struct iscsi_nopin*)hdr);
+-			if (rc)
+-				break;
+-			conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
+-
+-			if (!conn->in.datalen) {
+-				struct iscsi_mgmt_task *mtask;
+-
+-				rc = iscsi_recv_pdu(conn->cls_conn, hdr,
+-						    NULL, 0);
+-				mtask = (struct iscsi_mgmt_task *)
+-					session->mgmt_cmds[conn->in.itt -
+-							ISCSI_MGMT_ITT_OFFSET];
+-				if (conn->login_mtask != mtask) {
+-					spin_lock(&session->lock);
+-					__kfifo_put(session->mgmtpool.queue,
+-						  (void*)&mtask, sizeof(void*));
+-					spin_unlock(&session->lock);
+-				}
+-			}
+-			break;
+-		default:
+-			rc = ISCSI_ERR_BAD_OPCODE;
+-			break;
+-		}
+-	} else if (conn->in.itt == ISCSI_RESERVED_TAG) {
+-		switch(conn->in.opcode) {
+-		case ISCSI_OP_NOOP_IN:
+-			if (!conn->in.datalen) {
+-				rc = iscsi_check_assign_cmdsn(session,
+-						 (struct iscsi_nopin*)hdr);
+-				if (!rc && hdr->ttt != ISCSI_RESERVED_TAG)
+-					rc = iscsi_recv_pdu(conn->cls_conn,
+-							    hdr, NULL, 0);
+-			} else
+-				rc = ISCSI_ERR_PROTO;
+-			break;
+-		case ISCSI_OP_REJECT:
+-			/* we need sth like iscsi_reject_rsp()*/
+-		case ISCSI_OP_ASYNC_EVENT:
+-			/* we need sth like iscsi_async_event_rsp() */
+-			rc = ISCSI_ERR_BAD_OPCODE;
+-			break;
+-		default:
+-			rc = ISCSI_ERR_BAD_OPCODE;
+-			break;
+-		}
+-	} else
+-		rc = ISCSI_ERR_BAD_ITT;
++		spin_lock(&session->lock);
++		__iscsi_ctask_cleanup(conn, tcp_conn->in.ctask);
++		rc = __iscsi_complete_pdu(conn, hdr, NULL, 0);
++		spin_unlock(&session->lock);
++		break;
++	case ISCSI_OP_R2T:
++		tcp_conn->in.ctask = session->cmds[itt];
++		if (ahslen)
++			rc = ISCSI_ERR_AHSLEN;
++		else if (tcp_conn->in.ctask->sc->sc_data_direction ==
++								DMA_TO_DEVICE)
++			rc = iscsi_r2t_rsp(conn, tcp_conn->in.ctask);
++		else
++			rc = ISCSI_ERR_PROTO;
++		break;
++	case ISCSI_OP_LOGIN_RSP:
++	case ISCSI_OP_TEXT_RSP:
++	case ISCSI_OP_LOGOUT_RSP:
++	case ISCSI_OP_NOOP_IN:
++	case ISCSI_OP_REJECT:
++	case ISCSI_OP_ASYNC_EVENT:
++		if (tcp_conn->in.datalen)
++			goto copy_hdr;
++	/* fall through */
++	case ISCSI_OP_SCSI_TMFUNC_RSP:
++		rc = iscsi_complete_pdu(conn, hdr, NULL, 0);
++		break;
++	default:
++		rc = ISCSI_ERR_BAD_OPCODE;
++		break;
++	}
+ 
+ 	return rc;
++
++copy_hdr:
++	/*
++	 * if we did zero copy for the header but we will need multiple
++	 * skbs to complete the command then we have to copy the header
++	 * for later use
++	 */
++	if (tcp_conn->in.zero_copy_hdr && tcp_conn->in.copy <
++	   (tcp_conn->in.datalen + tcp_conn->in.padding +
++	    (conn->datadgst_en ? 4 : 0))) {
++		debug_tcp("Copying header for later use. in.copy %d in.datalen"
++			  " %d\n", tcp_conn->in.copy, tcp_conn->in.datalen);
++		memcpy(&tcp_conn->hdr, tcp_conn->in.hdr,
++		       sizeof(struct iscsi_hdr));
++		tcp_conn->in.hdr = &tcp_conn->hdr;
++		tcp_conn->in.zero_copy_hdr = 0;
++	}
++	return 0;
+ }
+ 
+ /**
+  * iscsi_ctask_copy - copy skb bits to the destanation cmd task
+- * @conn: iscsi connection
++ * @conn: iscsi tcp connection
+  * @ctask: scsi command task
+  * @buf: buffer to copy to
+  * @buf_size: size of buffer
+@@ -820,110 +587,113 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
+  *	buf_left		left to copy from in progress buffer
+  **/
+ static inline int
+-iscsi_ctask_copy(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
++iscsi_ctask_copy(struct iscsi_tcp_conn *tcp_conn, struct iscsi_cmd_task *ctask,
+ 		void *buf, int buf_size, int offset)
+ {
+-	int buf_left = buf_size - (conn->data_copied + offset);
+-	int size = min(conn->in.copy, buf_left);
++	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++	int buf_left = buf_size - (tcp_conn->data_copied + offset);
++	int size = min(tcp_conn->in.copy, buf_left);
+ 	int rc;
+ 
+ 	size = min(size, ctask->data_count);
+ 
+ 	debug_tcp("ctask_copy %d bytes at offset %d copied %d\n",
+-	       size, conn->in.offset, conn->in.copied);
++	       size, tcp_conn->in.offset, tcp_conn->in.copied);
+ 
+ 	BUG_ON(size <= 0);
+-	BUG_ON(ctask->sent + size > ctask->total_length);
++	BUG_ON(tcp_ctask->sent + size > ctask->total_length);
+ 
+-	rc = skb_copy_bits(conn->in.skb, conn->in.offset,
+-			   (char*)buf + (offset + conn->data_copied), size);
++	rc = skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset,
++			   (char*)buf + (offset + tcp_conn->data_copied), size);
+ 	/* must fit into skb->len */
+ 	BUG_ON(rc);
+ 
+-	conn->in.offset += size;
+-	conn->in.copy -= size;
+-	conn->in.copied += size;
+-	conn->data_copied += size;
+-	ctask->sent += size;
++	tcp_conn->in.offset += size;
++	tcp_conn->in.copy -= size;
++	tcp_conn->in.copied += size;
++	tcp_conn->data_copied += size;
++	tcp_ctask->sent += size;
+ 	ctask->data_count -= size;
+ 
+-	BUG_ON(conn->in.copy < 0);
++	BUG_ON(tcp_conn->in.copy < 0);
+ 	BUG_ON(ctask->data_count < 0);
+ 
+-	if (buf_size != (conn->data_copied + offset)) {
++	if (buf_size != (tcp_conn->data_copied + offset)) {
+ 		if (!ctask->data_count) {
+-			BUG_ON(buf_size - conn->data_copied < 0);
++			BUG_ON(buf_size - tcp_conn->data_copied < 0);
+ 			/* done with this PDU */
+-			return buf_size - conn->data_copied;
++			return buf_size - tcp_conn->data_copied;
+ 		}
+ 		return -EAGAIN;
+ 	}
+ 
+ 	/* done with this buffer or with both - PDU and buffer */
+-	conn->data_copied = 0;
++	tcp_conn->data_copied = 0;
+ 	return 0;
+ }
+ 
+ /**
+  * iscsi_tcp_copy - copy skb bits to the destanation buffer
+- * @conn: iscsi connection
+- * @buf: buffer to copy to
+- * @buf_size: number of bytes to copy
++ * @conn: iscsi tcp connection
+  *
+  * Notes:
+  *	The function calls skb_copy_bits() and updates per-connection
+  *	byte counters.
+  **/
+ static inline int
+-iscsi_tcp_copy(struct iscsi_conn *conn, void *buf, int buf_size)
++iscsi_tcp_copy(struct iscsi_tcp_conn *tcp_conn)
+ {
+-	int buf_left = buf_size - conn->data_copied;
+-	int size = min(conn->in.copy, buf_left);
++	void *buf = tcp_conn->data;
++	int buf_size = tcp_conn->in.datalen;
++	int buf_left = buf_size - tcp_conn->data_copied;
++	int size = min(tcp_conn->in.copy, buf_left);
+ 	int rc;
+ 
+ 	debug_tcp("tcp_copy %d bytes at offset %d copied %d\n",
+-	       size, conn->in.offset, conn->data_copied);
++	       size, tcp_conn->in.offset, tcp_conn->data_copied);
+ 	BUG_ON(size <= 0);
+ 
+-	rc = skb_copy_bits(conn->in.skb, conn->in.offset,
+-			   (char*)buf + conn->data_copied, size);
++	rc = skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset,
++			   (char*)buf + tcp_conn->data_copied, size);
+ 	BUG_ON(rc);
+ 
+-	conn->in.offset += size;
+-	conn->in.copy -= size;
+-	conn->in.copied += size;
+-	conn->data_copied += size;
++	tcp_conn->in.offset += size;
++	tcp_conn->in.copy -= size;
++	tcp_conn->in.copied += size;
++	tcp_conn->data_copied += size;
+ 
+-	if (buf_size != conn->data_copied)
++	if (buf_size != tcp_conn->data_copied)
+ 		return -EAGAIN;
+ 
+ 	return 0;
+ }
+ 
+ static inline void
+-partial_sg_digest_update(struct iscsi_conn *conn, struct scatterlist *sg,
+-			 int offset, int length)
++partial_sg_digest_update(struct iscsi_tcp_conn *tcp_conn,
++			 struct scatterlist *sg, int offset, int length)
+ {
+ 	struct scatterlist temp;
+ 
+ 	memcpy(&temp, sg, sizeof(struct scatterlist));
+ 	temp.offset = offset;
+ 	temp.length = length;
+-	crypto_digest_update(conn->data_rx_tfm, &temp, 1);
++	crypto_digest_update(tcp_conn->data_rx_tfm, &temp, 1);
+ }
+ 
+ static void
+-iscsi_recv_digest_update(struct iscsi_conn *conn, char* buf, int len)
++iscsi_recv_digest_update(struct iscsi_tcp_conn *tcp_conn, char* buf, int len)
+ {
+ 	struct scatterlist tmp;
+ 
+ 	sg_init_one(&tmp, buf, len);
+-	crypto_digest_update(conn->data_rx_tfm, &tmp, 1);
++	crypto_digest_update(tcp_conn->data_rx_tfm, &tmp, 1);
+ }
+ 
+ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
+ {
+-	struct iscsi_cmd_task *ctask = conn->in.ctask;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	struct iscsi_cmd_task *ctask = tcp_conn->in.ctask;
++	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	struct scsi_cmnd *sc = ctask->sc;
+ 	struct scatterlist *sg;
+ 	int i, offset, rc = 0;
+@@ -935,31 +705,33 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
+ 	 */
+ 	if (!sc->use_sg) {
+ 		i = ctask->data_count;
+-		rc = iscsi_ctask_copy(conn, ctask, sc->request_buffer,
+-				      sc->request_bufflen, ctask->data_offset);
++		rc = iscsi_ctask_copy(tcp_conn, ctask, sc->request_buffer,
++				      sc->request_bufflen,
++				      tcp_ctask->data_offset);
+ 		if (rc == -EAGAIN)
+ 			return rc;
+ 		if (conn->datadgst_en)
+-			iscsi_recv_digest_update(conn, sc->request_buffer, i);
++			iscsi_recv_digest_update(tcp_conn, sc->request_buffer,
++						 i);
+ 		rc = 0;
+ 		goto done;
+ 	}
+ 
+-	offset = ctask->data_offset;
++	offset = tcp_ctask->data_offset;
+ 	sg = sc->request_buffer;
+ 
+-	if (ctask->data_offset)
+-		for (i = 0; i < ctask->sg_count; i++)
++	if (tcp_ctask->data_offset)
++		for (i = 0; i < tcp_ctask->sg_count; i++)
+ 			offset -= sg[i].length;
+ 	/* we've passed through partial sg*/
+ 	if (offset < 0)
+ 		offset = 0;
+ 
+-	for (i = ctask->sg_count; i < sc->use_sg; i++) {
++	for (i = tcp_ctask->sg_count; i < sc->use_sg; i++) {
+ 		char *dest;
+ 
+ 		dest = kmap_atomic(sg[i].page, KM_SOFTIRQ0);
+-		rc = iscsi_ctask_copy(conn, ctask, dest + sg[i].offset,
++		rc = iscsi_ctask_copy(tcp_conn, ctask, dest + sg[i].offset,
+ 				      sg[i].length, offset);
+ 		kunmap_atomic(dest, KM_SOFTIRQ0);
+ 		if (rc == -EAGAIN)
+@@ -968,15 +740,17 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
+ 		if (!rc) {
+ 			if (conn->datadgst_en) {
+ 				if (!offset)
+-					crypto_digest_update(conn->data_rx_tfm,
+-							     &sg[i], 1);
++					crypto_digest_update(
++							tcp_conn->data_rx_tfm,
++							&sg[i], 1);
+ 				else
+-					partial_sg_digest_update(conn, &sg[i],
++					partial_sg_digest_update(tcp_conn,
++							&sg[i],
+ 							sg[i].offset + offset,
+ 							sg[i].length - offset);
+ 			}
+ 			offset = 0;
+-			ctask->sg_count++;
++			tcp_ctask->sg_count++;
+ 		}
+ 
+ 		if (!ctask->data_count) {
+@@ -984,24 +758,26 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
+ 				/*
+ 				 * data-in is complete, but buffer not...
+ 				 */
+-				partial_sg_digest_update(conn, &sg[i],
++				partial_sg_digest_update(tcp_conn, &sg[i],
+ 						sg[i].offset, sg[i].length-rc);
+ 			rc = 0;
+ 			break;
+ 		}
+ 
+-		if (!conn->in.copy)
++		if (!tcp_conn->in.copy)
+ 			return -EAGAIN;
+ 	}
+ 	BUG_ON(ctask->data_count);
+ 
+ done:
+ 	/* check for non-exceptional status */
+-	if (conn->in.flags & ISCSI_FLAG_DATA_STATUS) {
++	if (tcp_conn->in.hdr->flags & ISCSI_FLAG_DATA_STATUS) {
+ 		debug_scsi("done [sc %lx res %d itt 0x%x]\n",
+ 			   (long)sc, sc->result, ctask->itt);
+-		conn->scsirsp_pdus_cnt++;
+-		iscsi_ctask_cleanup(conn, ctask);
++		spin_lock(&conn->session->lock);
++		__iscsi_ctask_cleanup(conn, ctask);
++		__iscsi_complete_pdu(conn, tcp_conn->in.hdr, NULL, 0);
++		spin_unlock(&conn->session->lock);
+ 	}
+ 
+ 	return rc;
+@@ -1010,71 +786,38 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
+ static int
+ iscsi_data_recv(struct iscsi_conn *conn)
+ {
+-	struct iscsi_session *session = conn->session;
+-	int rc = 0;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	int rc = 0, opcode;
+ 
+-	switch(conn->in.opcode) {
++	opcode = tcp_conn->in.hdr->opcode & ISCSI_OPCODE_MASK;
++	switch (opcode) {
+ 	case ISCSI_OP_SCSI_DATA_IN:
+ 		rc = iscsi_scsi_data_in(conn);
+ 		break;
+-	case ISCSI_OP_SCSI_CMD_RSP: {
+-		/*
+-		 * SCSI Sense Data:
+-		 * copying the entire Data Segment.
+-		 */
+-		if (iscsi_tcp_copy(conn, conn->data, conn->in.datalen)) {
+-			rc = -EAGAIN;
+-			goto exit;
+-		}
+-
+-		/*
+-		 * check for sense
+-		 */
+-		conn->in.hdr = &conn->hdr;
+-		conn->senselen = (conn->data[0] << 8) | conn->data[1];
+-		rc = iscsi_cmd_rsp(conn, conn->in.ctask);
+-		if (!rc && conn->datadgst_en)
+-			iscsi_recv_digest_update(conn, conn->data,
+-						 conn->in.datalen);
+-	}
+-	break;
++	case ISCSI_OP_SCSI_CMD_RSP:
++		spin_lock(&conn->session->lock);
++		__iscsi_ctask_cleanup(conn, tcp_conn->in.ctask);
++		spin_unlock(&conn->session->lock);
+ 	case ISCSI_OP_TEXT_RSP:
+ 	case ISCSI_OP_LOGIN_RSP:
+-	case ISCSI_OP_NOOP_IN: {
+-		struct iscsi_mgmt_task *mtask = NULL;
+-
+-		if (conn->in.itt != ISCSI_RESERVED_TAG)
+-			mtask = (struct iscsi_mgmt_task *)
+-				session->mgmt_cmds[conn->in.itt -
+-					ISCSI_MGMT_ITT_OFFSET];
+-
++	case ISCSI_OP_NOOP_IN:
++	case ISCSI_OP_ASYNC_EVENT:
++	case ISCSI_OP_REJECT:
+ 		/*
+ 		 * Collect data segment to the connection's data
+ 		 * placeholder
+ 		 */
+-		if (iscsi_tcp_copy(conn, conn->data, conn->in.datalen)) {
++		if (iscsi_tcp_copy(tcp_conn)) {
+ 			rc = -EAGAIN;
+ 			goto exit;
+ 		}
+ 
+-		rc = iscsi_recv_pdu(conn->cls_conn, conn->in.hdr,
+-				    conn->data, conn->in.datalen);
+-
+-		if (!rc && conn->datadgst_en &&
+-			conn->in.opcode != ISCSI_OP_LOGIN_RSP)
+-			iscsi_recv_digest_update(conn, conn->data,
+-			  			conn->in.datalen);
+-
+-		if (mtask && conn->login_mtask != mtask) {
+-			spin_lock(&session->lock);
+-			__kfifo_put(session->mgmtpool.queue, (void*)&mtask,
+-				    sizeof(void*));
+-			spin_unlock(&session->lock);
+-		}
+-	}
+-	break;
+-	case ISCSI_OP_ASYNC_EVENT:
+-	case ISCSI_OP_REJECT:
++		rc = iscsi_complete_pdu(conn, tcp_conn->in.hdr, tcp_conn->data,
++					tcp_conn->in.datalen);
++		if (!rc && conn->datadgst_en && opcode != ISCSI_OP_LOGIN_RSP)
++			iscsi_recv_digest_update(tcp_conn, tcp_conn->data,
++			  			tcp_conn->in.datalen);
++		break;
+ 	default:
+ 		BUG_ON(1);
+ 	}
+@@ -1095,6 +838,7 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ {
+ 	int rc;
+ 	struct iscsi_conn *conn = rd_desc->arg.data;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	int processed;
+ 	char pad[ISCSI_PAD_LEN];
+ 	struct scatterlist sg;
+@@ -1103,15 +847,15 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 	 * Save current SKB and its offset in the corresponding
+ 	 * connection context.
+ 	 */
+-	conn->in.copy = skb->len - offset;
+-	conn->in.offset = offset;
+-	conn->in.skb = skb;
+-	conn->in.len = conn->in.copy;
+-	BUG_ON(conn->in.copy <= 0);
+-	debug_tcp("in %d bytes\n", conn->in.copy);
++	tcp_conn->in.copy = skb->len - offset;
++	tcp_conn->in.offset = offset;
++	tcp_conn->in.skb = skb;
++	tcp_conn->in.len = tcp_conn->in.copy;
++	BUG_ON(tcp_conn->in.copy <= 0);
++	debug_tcp("in %d bytes\n", tcp_conn->in.copy);
+ 
+ more:
+-	conn->in.copied = 0;
++	tcp_conn->in.copied = 0;
+ 	rc = 0;
+ 
+ 	if (unlikely(conn->suspend_rx)) {
+@@ -1119,9 +863,9 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 		return 0;
+ 	}
+ 
+-	if (conn->in_progress == IN_PROGRESS_WAIT_HEADER ||
+-	    conn->in_progress == IN_PROGRESS_HEADER_GATHER) {
+-		rc = iscsi_hdr_extract(conn);
++	if (tcp_conn->in_progress == IN_PROGRESS_WAIT_HEADER ||
++	    tcp_conn->in_progress == IN_PROGRESS_HEADER_GATHER) {
++		rc = iscsi_hdr_extract(tcp_conn);
+ 		if (rc) {
+ 		       if (rc == -EAGAIN)
+ 				goto nomore;
+@@ -1134,90 +878,94 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 		/*
+ 		 * Verify and process incoming PDU header.
+ 		 */
+-		rc = iscsi_hdr_recv(conn);
+-		if (!rc && conn->in.datalen) {
++		rc = iscsi_tcp_hdr_recv(conn);
++		if (!rc && tcp_conn->in.datalen) {
+ 			if (conn->datadgst_en) {
+-				BUG_ON(!conn->data_rx_tfm);
+-				crypto_digest_init(conn->data_rx_tfm);
++				BUG_ON(!tcp_conn->data_rx_tfm);
++				crypto_digest_init(tcp_conn->data_rx_tfm);
+ 			}
+-			conn->in_progress = IN_PROGRESS_DATA_RECV;
++			tcp_conn->in_progress = IN_PROGRESS_DATA_RECV;
+ 		} else if (rc) {
+ 			iscsi_conn_failure(conn, rc);
+ 			return 0;
+ 		}
+ 	}
+ 
+-	if (conn->in_progress == IN_PROGRESS_DDIGEST_RECV) {
++	if (tcp_conn->in_progress == IN_PROGRESS_DDIGEST_RECV) {
+ 		uint32_t recv_digest;
++
+ 		debug_tcp("extra data_recv offset %d copy %d\n",
+-			  conn->in.offset, conn->in.copy);
+-		skb_copy_bits(conn->in.skb, conn->in.offset,
++			  tcp_conn->in.offset, tcp_conn->in.copy);
++		skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset,
+ 				&recv_digest, 4);
+-		conn->in.offset += 4;
+-		conn->in.copy -= 4;
+-		if (recv_digest != conn->in.datadgst) {
++		tcp_conn->in.offset += 4;
++		tcp_conn->in.copy -= 4;
++		if (recv_digest != tcp_conn->in.datadgst) {
+ 			debug_tcp("iscsi_tcp: data digest error!"
+ 				  "0x%x != 0x%x\n", recv_digest,
+-				  conn->in.datadgst);
++				  tcp_conn->in.datadgst);
+ 			iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST);
+ 			return 0;
+ 		} else {
+ 			debug_tcp("iscsi_tcp: data digest match!"
+ 				  "0x%x == 0x%x\n", recv_digest,
+-				  conn->in.datadgst);
+-			conn->in_progress = IN_PROGRESS_WAIT_HEADER;
++				  tcp_conn->in.datadgst);
++			tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
+ 		}
+ 	}
+ 
+-	if (conn->in_progress == IN_PROGRESS_DATA_RECV && conn->in.copy) {
++	if (tcp_conn->in_progress == IN_PROGRESS_DATA_RECV &&
++	   tcp_conn->in.copy) {
+ 
+ 		debug_tcp("data_recv offset %d copy %d\n",
+-		       conn->in.offset, conn->in.copy);
++		       tcp_conn->in.offset, tcp_conn->in.copy);
+ 
+ 		rc = iscsi_data_recv(conn);
+ 		if (rc) {
+ 			if (rc == -EAGAIN) {
+-				rd_desc->count = conn->in.datalen -
+-						conn->in.ctask->data_count;
++				rd_desc->count = tcp_conn->in.datalen -
++						tcp_conn->in.ctask->data_count;
+ 				goto again;
+ 			}
+ 			iscsi_conn_failure(conn, rc);
+ 			return 0;
+ 		}
+-		conn->in.copy -= conn->in.padding;
+-		conn->in.offset += conn->in.padding;
++		tcp_conn->in.copy -= tcp_conn->in.padding;
++		tcp_conn->in.offset += tcp_conn->in.padding;
+ 		if (conn->datadgst_en) {
+-			if (conn->in.padding) {
+-				debug_tcp("padding -> %d\n", conn->in.padding);
+-				memset(pad, 0, conn->in.padding);
+-				sg_init_one(&sg, pad, conn->in.padding);
+-				crypto_digest_update(conn->data_rx_tfm, &sg, 1);
++			if (tcp_conn->in.padding) {
++				debug_tcp("padding -> %d\n",
++					  tcp_conn->in.padding);
++				memset(pad, 0, tcp_conn->in.padding);
++				sg_init_one(&sg, pad, tcp_conn->in.padding);
++				crypto_digest_update(tcp_conn->data_rx_tfm,
++						     &sg, 1);
+ 			}
+-			crypto_digest_final(conn->data_rx_tfm,
+-					    (u8 *) & conn->in.datadgst);
+-			debug_tcp("rx digest 0x%x\n", conn->in.datadgst);
+-			conn->in_progress = IN_PROGRESS_DDIGEST_RECV;
++			crypto_digest_final(tcp_conn->data_rx_tfm,
++					    (u8 *) & tcp_conn->in.datadgst);
++			debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst);
++			tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV;
+ 		} else
+-			conn->in_progress = IN_PROGRESS_WAIT_HEADER;
++			tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
+ 	}
+ 
+ 	debug_tcp("f, processed %d from out of %d padding %d\n",
+-	       conn->in.offset - offset, (int)len, conn->in.padding);
+-	BUG_ON(conn->in.offset - offset > len);
++	       tcp_conn->in.offset - offset, (int)len, tcp_conn->in.padding);
++	BUG_ON(tcp_conn->in.offset - offset > len);
+ 
+-	if (conn->in.offset - offset != len) {
++	if (tcp_conn->in.offset - offset != len) {
+ 		debug_tcp("continue to process %d bytes\n",
+-		       (int)len - (conn->in.offset - offset));
++		       (int)len - (tcp_conn->in.offset - offset));
+ 		goto more;
+ 	}
+ 
+ nomore:
+-	processed = conn->in.offset - offset;
++	processed = tcp_conn->in.offset - offset;
+ 	BUG_ON(processed == 0);
+ 	return processed;
+ 
+ again:
+-	processed = conn->in.offset - offset;
++	processed = tcp_conn->in.offset - offset;
+ 	debug_tcp("c, processed %d from out of %d rd_desc_cnt %d\n",
+ 	          processed, (int)len, (int)rd_desc->count);
+ 	BUG_ON(processed == 0);
+@@ -1246,6 +994,7 @@ iscsi_tcp_data_ready(struct sock *sk, int flag)
+ static void
+ iscsi_tcp_state_change(struct sock *sk)
+ {
++	struct iscsi_tcp_conn *tcp_conn;
+ 	struct iscsi_conn *conn;
+ 	struct iscsi_session *session;
+ 	void (*old_state_change)(struct sock *);
+@@ -1262,7 +1011,8 @@ iscsi_tcp_state_change(struct sock *sk)
+ 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ 	}
+ 
+-	old_state_change = conn->old_state_change;
++	tcp_conn = conn->dd_data;
++	old_state_change = tcp_conn->old_state_change;
+ 
+ 	read_unlock(&sk->sk_callback_lock);
+ 
+@@ -1277,23 +1027,26 @@ static void
+ iscsi_write_space(struct sock *sk)
+ {
+ 	struct iscsi_conn *conn = (struct iscsi_conn*)sk->sk_user_data;
+-	conn->old_write_space(sk);
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++
++	tcp_conn->old_write_space(sk);
+ 	debug_tcp("iscsi_write_space: cid %d\n", conn->id);
+-	clear_bit(SUSPEND_BIT, &conn->suspend_tx);
++	clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+ 	scsi_queue_work(conn->session->host, &conn->xmitwork);
+ }
+ 
+ static void
+ iscsi_conn_set_callbacks(struct iscsi_conn *conn)
+ {
+-	struct sock *sk = conn->sock->sk;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	struct sock *sk = tcp_conn->sock->sk;
+ 
+ 	/* assign new callbacks */
+ 	write_lock_bh(&sk->sk_callback_lock);
+ 	sk->sk_user_data = conn;
+-	conn->old_data_ready = sk->sk_data_ready;
+-	conn->old_state_change = sk->sk_state_change;
+-	conn->old_write_space = sk->sk_write_space;
++	tcp_conn->old_data_ready = sk->sk_data_ready;
++	tcp_conn->old_state_change = sk->sk_state_change;
++	tcp_conn->old_write_space = sk->sk_write_space;
+ 	sk->sk_data_ready = iscsi_tcp_data_ready;
+ 	sk->sk_state_change = iscsi_tcp_state_change;
+ 	sk->sk_write_space = iscsi_write_space;
+@@ -1303,14 +1056,15 @@ iscsi_conn_set_callbacks(struct iscsi_conn *conn)
+ static void
+ iscsi_conn_restore_callbacks(struct iscsi_conn *conn)
+ {
+-	struct sock *sk = conn->sock->sk;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	struct sock *sk = tcp_conn->sock->sk;
+ 
+ 	/* restore socket callbacks, see also: iscsi_conn_set_callbacks() */
+ 	write_lock_bh(&sk->sk_callback_lock);
+ 	sk->sk_user_data    = NULL;
+-	sk->sk_data_ready   = conn->old_data_ready;
+-	sk->sk_state_change = conn->old_state_change;
+-	sk->sk_write_space  = conn->old_write_space;
++	sk->sk_data_ready   = tcp_conn->old_data_ready;
++	sk->sk_state_change = tcp_conn->old_state_change;
++	sk->sk_write_space  = tcp_conn->old_write_space;
+ 	sk->sk_no_check	 = 0;
+ 	write_unlock_bh(&sk->sk_callback_lock);
+ }
+@@ -1325,7 +1079,8 @@ iscsi_conn_restore_callbacks(struct iscsi_conn *conn)
+ static inline int
+ iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags)
+ {
+-	struct socket *sk = conn->sock;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	struct socket *sk = tcp_conn->sock;
+ 	int offset = buf->sg.offset + buf->sent;
+ 
+ 	/*
+@@ -1339,7 +1094,8 @@ iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags)
+ 	if (buf->use_sendmsg)
+ 		return sock_no_sendpage(sk, buf->sg.page, offset, size, flags);
+ 	else
+-		return conn->sendpage(sk, buf->sg.page, offset, size, flags);
++		return tcp_conn->sendpage(sk, buf->sg.page, offset, size,
++					  flags);
+ }
+ 
+ /**
+@@ -1354,6 +1110,7 @@ iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags)
+ static inline int
+ iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen)
+ {
++	struct iscsi_tcp_conn *tcp_conn;
+ 	int flags = 0; /* MSG_DONTWAIT; */
+ 	int res, size;
+ 
+@@ -1371,8 +1128,9 @@ iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen)
+ 			return -EAGAIN;
+ 		return 0;
+ 	} else if (res == -EAGAIN) {
+-		conn->sendpage_failures_cnt++;
+-		set_bit(SUSPEND_BIT, &conn->suspend_tx);
++		tcp_conn = conn->dd_data;
++		tcp_conn->sendpage_failures_cnt++;
++		set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+ 	} else if (res == -EPIPE)
+ 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ 
+@@ -1393,6 +1151,7 @@ static inline int
+ iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf,
+ 	       int *count, int *sent)
+ {
++	struct iscsi_tcp_conn *tcp_conn;
+ 	int flags = 0; /* MSG_DONTWAIT; */
+ 	int res, size;
+ 
+@@ -1415,8 +1174,9 @@ iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf,
+ 			return -EAGAIN;
+ 		return 0;
+ 	} else if (res == -EAGAIN) {
+-		conn->sendpage_failures_cnt++;
+-		set_bit(SUSPEND_BIT, &conn->suspend_tx);
++		tcp_conn = conn->dd_data;
++		tcp_conn->sendpage_failures_cnt++;
++		set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+ 	} else if (res == -EPIPE)
+ 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ 
+@@ -1424,30 +1184,35 @@ iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf,
+ }
+ 
+ static inline void
+-iscsi_data_digest_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
++iscsi_data_digest_init(struct iscsi_tcp_conn *tcp_conn,
++		      struct iscsi_cmd_task *ctask)
+ {
+-	BUG_ON(!conn->data_tx_tfm);
+-	crypto_digest_init(conn->data_tx_tfm);
+-	ctask->digest_count = 4;
++	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++
++	BUG_ON(!tcp_conn->data_tx_tfm);
++	crypto_digest_init(tcp_conn->data_tx_tfm);
++	tcp_ctask->digest_count = 4;
+ }
+ 
+ static int
+ iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 			struct iscsi_buf *buf, uint32_t *digest, int final)
+ {
++	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	int rc = 0;
+ 	int sent = 0;
+ 
+ 	if (final)
+-		crypto_digest_final(conn->data_tx_tfm, (u8*)digest);
++		crypto_digest_final(tcp_conn->data_tx_tfm, (u8*)digest);
+ 
+ 	iscsi_buf_init_virt(buf, (char*)digest, 4);
+-	rc = iscsi_sendpage(conn, buf, &ctask->digest_count, &sent);
++	rc = iscsi_sendpage(conn, buf, &tcp_ctask->digest_count, &sent);
+ 	if (rc) {
+-		ctask->datadigest = *digest;
+-		ctask->xmstate |= XMSTATE_DATA_DIGEST;
++		tcp_ctask->datadigest = *digest;
++		tcp_ctask->xmstate |= XMSTATE_DATA_DIGEST;
+ 	} else
+-		ctask->digest_count = 4;
++		tcp_ctask->digest_count = 4;
+ 	return rc;
+ }
+ 
+@@ -1468,12 +1233,13 @@ static void
+ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 			struct iscsi_r2t_info *r2t, int left)
+ {
++	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	struct iscsi_data *hdr;
+ 	struct iscsi_data_task *dtask;
+ 	struct scsi_cmnd *sc = ctask->sc;
+ 	int new_offset;
+ 
+-	dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC);
++	dtask = mempool_alloc(tcp_ctask->datapool, GFP_ATOMIC);
+ 	BUG_ON(!dtask);
+ 	INIT_LIST_HEAD(&dtask->item);
+ 	hdr = &dtask->hdr;
+@@ -1482,8 +1248,8 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 	hdr->datasn = cpu_to_be32(r2t->solicit_datasn);
+ 	r2t->solicit_datasn++;
+ 	hdr->opcode = ISCSI_OP_SCSI_DATA_OUT;
+-	memcpy(hdr->lun, ctask->hdr.lun, sizeof(hdr->lun));
+-	hdr->itt = ctask->hdr.itt;
++	memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun));
++	hdr->itt = ctask->hdr->itt;
+ 	hdr->exp_statsn = r2t->exp_statsn;
+ 	new_offset = r2t->data_offset + r2t->sent;
+ 	hdr->offset = cpu_to_be32(new_offset);
+@@ -1503,177 +1269,102 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 	r2t->dtask = dtask;
+ 
+ 	if (sc->use_sg && !iscsi_buf_left(&r2t->sendbuf)) {
+-		BUG_ON(ctask->bad_sg == r2t->sg);
++		BUG_ON(tcp_ctask->bad_sg == r2t->sg);
+ 		iscsi_buf_init_sg(&r2t->sendbuf, r2t->sg);
+ 		r2t->sg += 1;
+ 	} else
+-		iscsi_buf_init_iov(&ctask->sendbuf,
++		iscsi_buf_init_iov(&tcp_ctask->sendbuf,
+ 			    (char*)sc->request_buffer + new_offset,
+ 			    r2t->data_count);
+ 
+-	list_add(&dtask->item, &ctask->dataqueue);
++	list_add(&dtask->item, &tcp_ctask->dataqueue);
+ }
+ 
+ static void
+ iscsi_unsolicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+-	struct iscsi_data *hdr;
++	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	struct iscsi_data_task *dtask;
+ 
+-	dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC);
++	dtask = mempool_alloc(tcp_ctask->datapool, GFP_ATOMIC);
+ 	BUG_ON(!dtask);
+ 	INIT_LIST_HEAD(&dtask->item);
+-	hdr = &dtask->hdr;
+-	memset(hdr, 0, sizeof(struct iscsi_data));
+-	hdr->ttt = cpu_to_be32(ISCSI_RESERVED_TAG);
+-	hdr->datasn = cpu_to_be32(ctask->unsol_datasn);
+-	ctask->unsol_datasn++;
+-	hdr->opcode = ISCSI_OP_SCSI_DATA_OUT;
+-	memcpy(hdr->lun, ctask->hdr.lun, sizeof(hdr->lun));
+-	hdr->itt = ctask->hdr.itt;
+-	hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
+-	hdr->offset = cpu_to_be32(ctask->total_length -
+-				  ctask->r2t_data_count -
+-				  ctask->unsol_count);
+-	if (ctask->unsol_count > conn->max_xmit_dlength) {
+-		hton24(hdr->dlength, conn->max_xmit_dlength);
+-		ctask->data_count = conn->max_xmit_dlength;
+-		hdr->flags = 0;
+-	} else {
+-		hton24(hdr->dlength, ctask->unsol_count);
+-		ctask->data_count = ctask->unsol_count;
+-		hdr->flags = ISCSI_FLAG_CMD_FINAL;
+-	}
+ 
+-	iscsi_buf_init_virt(&ctask->headbuf, (char*)hdr,
++	iscsi_prep_unsolicit_data_pdu(ctask, &dtask->hdr,
++				      tcp_ctask->r2t_data_count);
++	iscsi_buf_init_virt(&tcp_ctask->headbuf, (char*)&dtask->hdr,
+ 			   sizeof(struct iscsi_hdr));
+ 
+-	list_add(&dtask->item, &ctask->dataqueue);
+-
+-	ctask->dtask = dtask;
++	list_add(&dtask->item, &tcp_ctask->dataqueue);
++	tcp_ctask->dtask = dtask;
+ }
+ 
+ /**
+- * iscsi_cmd_init - Initialize iSCSI SCSI_READ or SCSI_WRITE commands
++ * iscsi_tcp_cmd_init - Initialize iSCSI SCSI_READ or SCSI_WRITE commands
+  * @conn: iscsi connection
+  * @ctask: scsi command task
+  * @sc: scsi command
+  **/
+ static void
+-iscsi_cmd_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+-		struct scsi_cmnd *sc)
++iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask)
+ {
+-	struct iscsi_session *session = conn->session;
+-
+-	BUG_ON(__kfifo_len(ctask->r2tqueue));
+-
+-	INIT_LIST_HEAD(&ctask->running);
+-	ctask->sc = sc;
+-	ctask->conn = conn;
+-	ctask->hdr.opcode = ISCSI_OP_SCSI_CMD;
+-	ctask->hdr.flags = ISCSI_ATTR_SIMPLE;
+-	int_to_scsilun(sc->device->lun, (struct scsi_lun *)ctask->hdr.lun);
+-	ctask->hdr.itt = ctask->itt | (conn->id << CID_SHIFT) |
+-			 (session->age << AGE_SHIFT);
+-	ctask->hdr.data_length = cpu_to_be32(sc->request_bufflen);
+-	ctask->hdr.cmdsn = cpu_to_be32(session->cmdsn); session->cmdsn++;
+-	ctask->hdr.exp_statsn = cpu_to_be32(conn->exp_statsn);
+-	memcpy(ctask->hdr.cdb, sc->cmnd, sc->cmd_len);
+-	memset(&ctask->hdr.cdb[sc->cmd_len], 0, MAX_COMMAND_SIZE - sc->cmd_len);
++	struct scsi_cmnd *sc = ctask->sc;
++	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 
+-	ctask->mtask = NULL;
+-	ctask->sent = 0;
+-	ctask->sg_count = 0;
++	BUG_ON(__kfifo_len(tcp_ctask->r2tqueue));
+ 
+-	ctask->total_length = sc->request_bufflen;
++	tcp_ctask->sent = 0;
++	tcp_ctask->sg_count = 0;
+ 
+ 	if (sc->sc_data_direction == DMA_TO_DEVICE) {
+-		ctask->exp_r2tsn = 0;
+-		ctask->hdr.flags |= ISCSI_FLAG_CMD_WRITE;
++		tcp_ctask->xmstate = XMSTATE_W_HDR;
++		tcp_ctask->exp_r2tsn = 0;
+ 		BUG_ON(ctask->total_length == 0);
++
+ 		if (sc->use_sg) {
+ 			struct scatterlist *sg = sc->request_buffer;
+ 
+-			iscsi_buf_init_sg(&ctask->sendbuf,
+-					  &sg[ctask->sg_count++]);
+-			ctask->sg = sg;
+-			ctask->bad_sg = sg + sc->use_sg;
+-		} else {
+-			iscsi_buf_init_iov(&ctask->sendbuf, sc->request_buffer,
+-					sc->request_bufflen);
+-		}
++			iscsi_buf_init_sg(&tcp_ctask->sendbuf,
++					  &sg[tcp_ctask->sg_count++]);
++			tcp_ctask->sg = sg;
++			tcp_ctask->bad_sg = sg + sc->use_sg;
++		} else
++			iscsi_buf_init_iov(&tcp_ctask->sendbuf,
++					   sc->request_buffer,
++					   sc->request_bufflen);
+ 
+-		/*
+-		 * Write counters:
+-		 *
+-		 *	imm_count	bytes to be sent right after
+-		 *			SCSI PDU Header
+-		 *
+-		 *	unsol_count	bytes(as Data-Out) to be sent
+-		 *			without	R2T ack right after
+-		 *			immediate data
+-		 *
+-		 *	r2t_data_count	bytes to be sent via R2T ack's
+-		 *
+-		 *      pad_count       bytes to be sent as zero-padding
+-		 */
+-		ctask->imm_count = 0;
+-		ctask->unsol_count = 0;
+-		ctask->unsol_datasn = 0;
+-		ctask->xmstate = XMSTATE_W_HDR;
+-		/* calculate write padding */
+-		ctask->pad_count = ctask->total_length & (ISCSI_PAD_LEN-1);
+-		if (ctask->pad_count) {
+-			ctask->pad_count = ISCSI_PAD_LEN - ctask->pad_count;
++		if (ctask->imm_count)
++			tcp_ctask->xmstate |= XMSTATE_IMM_DATA;
++
++		tcp_ctask->pad_count = ctask->total_length & (ISCSI_PAD_LEN-1);
++		if (tcp_ctask->pad_count) {
++			tcp_ctask->pad_count = ISCSI_PAD_LEN -
++							tcp_ctask->pad_count;
+ 			debug_scsi("write padding %d bytes\n",
+-				ctask->pad_count);
+-			ctask->xmstate |= XMSTATE_W_PAD;
++				   tcp_ctask->pad_count);
++			tcp_ctask->xmstate |= XMSTATE_W_PAD;
+ 		}
+-		if (session->imm_data_en) {
+-			if (ctask->total_length >= session->first_burst)
+-				ctask->imm_count = min(session->first_burst,
+-							conn->max_xmit_dlength);
+-			else
+-				ctask->imm_count = min(ctask->total_length,
+-							conn->max_xmit_dlength);
+-			hton24(ctask->hdr.dlength, ctask->imm_count);
+-			ctask->xmstate |= XMSTATE_IMM_DATA;
+-		} else
+-			zero_data(ctask->hdr.dlength);
+-
+-		if (!session->initial_r2t_en)
+-			ctask->unsol_count = min(session->first_burst,
+-				ctask->total_length) - ctask->imm_count;
+-		if (!ctask->unsol_count)
+-			/* No unsolicit Data-Out's */
+-			ctask->hdr.flags |= ISCSI_FLAG_CMD_FINAL;
+-		else
+-			ctask->xmstate |= XMSTATE_UNS_HDR | XMSTATE_UNS_INIT;
+ 
+-		ctask->r2t_data_count = ctask->total_length -
++		if (ctask->unsol_count)
++			tcp_ctask->xmstate |= XMSTATE_UNS_HDR |
++						XMSTATE_UNS_INIT;
++		tcp_ctask->r2t_data_count = ctask->total_length -
+ 				    ctask->imm_count -
+ 				    ctask->unsol_count;
+ 
+ 		debug_scsi("cmd [itt %x total %d imm %d imm_data %d "
+ 			   "r2t_data %d]\n",
+ 			   ctask->itt, ctask->total_length, ctask->imm_count,
+-			   ctask->unsol_count, ctask->r2t_data_count);
+-	} else {
+-		ctask->hdr.flags |= ISCSI_FLAG_CMD_FINAL;
+-		if (sc->sc_data_direction == DMA_FROM_DEVICE)
+-			ctask->hdr.flags |= ISCSI_FLAG_CMD_READ;
+-		ctask->datasn = 0;
+-		ctask->xmstate = XMSTATE_R_HDR;
+-		zero_data(ctask->hdr.dlength);
+-	}
++			   ctask->unsol_count, tcp_ctask->r2t_data_count);
++	} else
++		tcp_ctask->xmstate = XMSTATE_R_HDR;
+ 
+-	iscsi_buf_init_virt(&ctask->headbuf, (char*)&ctask->hdr,
++	iscsi_buf_init_virt(&tcp_ctask->headbuf, (char*)ctask->hdr,
+ 			    sizeof(struct iscsi_hdr));
+-	conn->scsicmd_pdus_cnt++;
+ }
+ 
+ /**
+- * iscsi_mtask_xmit - xmit management(immediate) task
++ * iscsi_tcp_mtask_xmit - xmit management(immediate) task
+  * @conn: iscsi connection
+  * @mtask: task management task
+  *
+@@ -1687,70 +1378,87 @@ iscsi_cmd_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+  *		IN_PROGRESS_IMM_DATA - PDU Data xmit in progress
+  **/
+ static int
+-iscsi_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
++iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
+ {
++	struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data;
+ 
+ 	debug_scsi("mtask deq [cid %d state %x itt 0x%x]\n",
+-		conn->id, mtask->xmstate, mtask->itt);
++		conn->id, tcp_mtask->xmstate, mtask->itt);
+ 
+-	if (mtask->xmstate & XMSTATE_IMM_HDR) {
+-		mtask->xmstate &= ~XMSTATE_IMM_HDR;
++	if (tcp_mtask->xmstate & XMSTATE_IMM_HDR) {
++		tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR;
+ 		if (mtask->data_count)
+-			mtask->xmstate |= XMSTATE_IMM_DATA;
++			tcp_mtask->xmstate |= XMSTATE_IMM_DATA;
+ 		if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE &&
+ 		    conn->stop_stage != STOP_CONN_RECOVER &&
+ 		    conn->hdrdgst_en)
+-			iscsi_hdr_digest(conn, &mtask->headbuf,
+-					(u8*)mtask->hdrext);
+-		if (iscsi_sendhdr(conn, &mtask->headbuf, mtask->data_count)) {
+-			mtask->xmstate |= XMSTATE_IMM_HDR;
++			iscsi_hdr_digest(conn, &tcp_mtask->headbuf,
++					(u8*)tcp_mtask->hdrext);
++		if (iscsi_sendhdr(conn, &tcp_mtask->headbuf,
++				  mtask->data_count)) {
++			tcp_mtask->xmstate |= XMSTATE_IMM_HDR;
+ 			if (mtask->data_count)
+-				mtask->xmstate &= ~XMSTATE_IMM_DATA;
++				tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA;
+ 			return -EAGAIN;
+ 		}
+ 	}
+ 
+-	if (mtask->xmstate & XMSTATE_IMM_DATA) {
++	if (tcp_mtask->xmstate & XMSTATE_IMM_DATA) {
+ 		BUG_ON(!mtask->data_count);
+-		mtask->xmstate &= ~XMSTATE_IMM_DATA;
++		tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA;
+ 		/* FIXME: implement.
+ 		 * Virtual buffer could be spreaded across multiple pages...
+ 		 */
+ 		do {
+-			if (iscsi_sendpage(conn, &mtask->sendbuf,
+-				   &mtask->data_count, &mtask->sent)) {
+-				mtask->xmstate |= XMSTATE_IMM_DATA;
++			if (iscsi_sendpage(conn, &tcp_mtask->sendbuf,
++				   &mtask->data_count, &tcp_mtask->sent)) {
++				tcp_mtask->xmstate |= XMSTATE_IMM_DATA;
+ 				return -EAGAIN;
+ 			}
+ 		} while (mtask->data_count);
+ 	}
+ 
+-	BUG_ON(mtask->xmstate != XMSTATE_IDLE);
++	BUG_ON(tcp_mtask->xmstate != XMSTATE_IDLE);
++	if (mtask->hdr->itt == cpu_to_be32(ISCSI_RESERVED_TAG)) {
++		struct iscsi_session *session = conn->session;
++
++		spin_lock_bh(&session->lock);
++		list_del(&conn->mtask->running);
++		__kfifo_put(session->mgmtpool.queue, (void*)&conn->mtask,
++			    sizeof(void*));
++		spin_unlock_bh(&session->lock);
++	}
+ 	return 0;
+ }
+ 
+ static inline int
+-handle_xmstate_r_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
++handle_xmstate_r_hdr(struct iscsi_conn *conn,
++		     struct iscsi_tcp_cmd_task *tcp_ctask)
+ {
+-	ctask->xmstate &= ~XMSTATE_R_HDR;
++	tcp_ctask->xmstate &= ~XMSTATE_R_HDR;
+ 	if (conn->hdrdgst_en)
+-		iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext);
+-	if (!iscsi_sendhdr(conn, &ctask->headbuf, 0)) {
+-		BUG_ON(ctask->xmstate != XMSTATE_IDLE);
++		iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
++				 (u8*)tcp_ctask->hdrext);
++	if (!iscsi_sendhdr(conn, &tcp_ctask->headbuf, 0)) {
++		BUG_ON(tcp_ctask->xmstate != XMSTATE_IDLE);
+ 		return 0; /* wait for Data-In */
+ 	}
+-	ctask->xmstate |= XMSTATE_R_HDR;
++	tcp_ctask->xmstate |= XMSTATE_R_HDR;
+ 	return -EAGAIN;
+ }
+ 
+ static inline int
+-handle_xmstate_w_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
++handle_xmstate_w_hdr(struct iscsi_conn *conn,
++		     struct iscsi_cmd_task *ctask)
+ {
+-	ctask->xmstate &= ~XMSTATE_W_HDR;
++	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++
++	tcp_ctask->xmstate &= ~XMSTATE_W_HDR;
+ 	if (conn->hdrdgst_en)
+-		iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext);
+-	if (iscsi_sendhdr(conn, &ctask->headbuf, ctask->imm_count)) {
+-		ctask->xmstate |= XMSTATE_W_HDR;
++		iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
++				 (u8*)tcp_ctask->hdrext);
++	if (iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count)) {
++		tcp_ctask->xmstate |= XMSTATE_W_HDR;
+ 		return -EAGAIN;
+ 	}
+ 	return 0;
+@@ -1760,13 +1468,15 @@ static inline int
+ handle_xmstate_data_digest(struct iscsi_conn *conn,
+ 			   struct iscsi_cmd_task *ctask)
+ {
+-	ctask->xmstate &= ~XMSTATE_DATA_DIGEST;
+-	debug_tcp("resent data digest 0x%x\n", ctask->datadigest);
+-	if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf,
+-				    &ctask->datadigest, 0)) {
+-		ctask->xmstate |= XMSTATE_DATA_DIGEST;
++	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++
++	tcp_ctask->xmstate &= ~XMSTATE_DATA_DIGEST;
++	debug_tcp("resent data digest 0x%x\n", tcp_ctask->datadigest);
++	if (iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf,
++				    &tcp_ctask->datadigest, 0)) {
++		tcp_ctask->xmstate |= XMSTATE_DATA_DIGEST;
+ 		debug_tcp("resent data digest 0x%x fail!\n",
+-			  ctask->datadigest);
++			  tcp_ctask->datadigest);
+ 		return -EAGAIN;
+ 	}
+ 	return 0;
+@@ -1775,44 +1485,47 @@ handle_xmstate_data_digest(struct iscsi_conn *conn,
+ static inline int
+ handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
++	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++
+ 	BUG_ON(!ctask->imm_count);
+-	ctask->xmstate &= ~XMSTATE_IMM_DATA;
++	tcp_ctask->xmstate &= ~XMSTATE_IMM_DATA;
+ 
+ 	if (conn->datadgst_en) {
+-		iscsi_data_digest_init(conn, ctask);
+-		ctask->immdigest = 0;
++		iscsi_data_digest_init(tcp_conn, ctask);
++		tcp_ctask->immdigest = 0;
+ 	}
+ 
+ 	for (;;) {
+-		if (iscsi_sendpage(conn, &ctask->sendbuf, &ctask->imm_count,
+-				   &ctask->sent)) {
+-			ctask->xmstate |= XMSTATE_IMM_DATA;
++		if (iscsi_sendpage(conn, &tcp_ctask->sendbuf, &ctask->imm_count,
++				   &tcp_ctask->sent)) {
++			tcp_ctask->xmstate |= XMSTATE_IMM_DATA;
+ 			if (conn->datadgst_en) {
+-				crypto_digest_final(conn->data_tx_tfm,
+-						(u8*)&ctask->immdigest);
++				crypto_digest_final(tcp_conn->data_tx_tfm,
++						(u8*)&tcp_ctask->immdigest);
+ 				debug_tcp("tx imm sendpage fail 0x%x\n",
+-					  ctask->datadigest);
++					  tcp_ctask->datadigest);
+ 			}
+ 			return -EAGAIN;
+ 		}
+ 		if (conn->datadgst_en)
+-			crypto_digest_update(conn->data_tx_tfm,
+-					     &ctask->sendbuf.sg, 1);
++			crypto_digest_update(tcp_conn->data_tx_tfm,
++					     &tcp_ctask->sendbuf.sg, 1);
+ 
+ 		if (!ctask->imm_count)
+ 			break;
+-		iscsi_buf_init_sg(&ctask->sendbuf,
+-				  &ctask->sg[ctask->sg_count++]);
++		iscsi_buf_init_sg(&tcp_ctask->sendbuf,
++				  &tcp_ctask->sg[tcp_ctask->sg_count++]);
+ 	}
+ 
+-	if (conn->datadgst_en && !(ctask->xmstate & XMSTATE_W_PAD)) {
+-		if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf,
+-				            &ctask->immdigest, 1)) {
++	if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) {
++		if (iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf,
++				            &tcp_ctask->immdigest, 1)) {
+ 			debug_tcp("sending imm digest 0x%x fail!\n",
+-				  ctask->immdigest);
++				  tcp_ctask->immdigest);
+ 			return -EAGAIN;
+ 		}
+-		debug_tcp("sending imm digest 0x%x\n", ctask->immdigest);
++		debug_tcp("sending imm digest 0x%x\n", tcp_ctask->immdigest);
+ 	}
+ 
+ 	return 0;
+@@ -1821,52 +1534,55 @@ handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ static inline int
+ handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
++	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	struct iscsi_data_task *dtask;
+ 
+-	ctask->xmstate |= XMSTATE_UNS_DATA;
+-	if (ctask->xmstate & XMSTATE_UNS_INIT) {
++	tcp_ctask->xmstate |= XMSTATE_UNS_DATA;
++	if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) {
+ 		iscsi_unsolicit_data_init(conn, ctask);
+-		BUG_ON(!ctask->dtask);
+-		dtask = ctask->dtask;
++		BUG_ON(!tcp_ctask->dtask);
++		dtask = tcp_ctask->dtask;
+ 		if (conn->hdrdgst_en)
+-			iscsi_hdr_digest(conn, &ctask->headbuf,
++			iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
+ 					(u8*)dtask->hdrext);
+-		ctask->xmstate &= ~XMSTATE_UNS_INIT;
++		tcp_ctask->xmstate &= ~XMSTATE_UNS_INIT;
+ 	}
+-	if (iscsi_sendhdr(conn, &ctask->headbuf, ctask->data_count)) {
+-		ctask->xmstate &= ~XMSTATE_UNS_DATA;
+-		ctask->xmstate |= XMSTATE_UNS_HDR;
++	if (iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->data_count)) {
++		tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA;
++		tcp_ctask->xmstate |= XMSTATE_UNS_HDR;
+ 		return -EAGAIN;
+ 	}
+ 
+ 	debug_scsi("uns dout [itt 0x%x dlen %d sent %d]\n",
+-		   ctask->itt, ctask->unsol_count, ctask->sent);
++		   ctask->itt, ctask->unsol_count, tcp_ctask->sent);
+ 	return 0;
+ }
+ 
+ static inline int
+ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+-	struct iscsi_data_task *dtask = ctask->dtask;
++	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++	struct iscsi_data_task *dtask = tcp_ctask->dtask;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 
+ 	BUG_ON(!ctask->data_count);
+-	ctask->xmstate &= ~XMSTATE_UNS_DATA;
++	tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA;
+ 
+ 	if (conn->datadgst_en) {
+-		iscsi_data_digest_init(conn, ctask);
++		iscsi_data_digest_init(tcp_conn, ctask);
+ 		dtask->digest = 0;
+ 	}
+ 
+ 	for (;;) {
+-		int start = ctask->sent;
++		int start = tcp_ctask->sent;
+ 
+-		if (iscsi_sendpage(conn, &ctask->sendbuf, &ctask->data_count,
+-				   &ctask->sent)) {
+-			ctask->unsol_count -= ctask->sent - start;
+-			ctask->xmstate |= XMSTATE_UNS_DATA;
++		if (iscsi_sendpage(conn, &tcp_ctask->sendbuf,
++				   &ctask->data_count, &tcp_ctask->sent)) {
++			ctask->unsol_count -= tcp_ctask->sent - start;
++			tcp_ctask->xmstate |= XMSTATE_UNS_DATA;
+ 			/* will continue with this ctask later.. */
+ 			if (conn->datadgst_en) {
+-				crypto_digest_final(conn->data_tx_tfm,
++				crypto_digest_final(tcp_conn->data_tx_tfm,
+ 						(u8 *)&dtask->digest);
+ 				debug_tcp("tx uns data fail 0x%x\n",
+ 					  dtask->digest);
+@@ -1874,21 +1590,21 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 			return -EAGAIN;
+ 		}
+ 
+-		BUG_ON(ctask->sent > ctask->total_length);
+-		ctask->unsol_count -= ctask->sent - start;
++		BUG_ON(tcp_ctask->sent > ctask->total_length);
++		ctask->unsol_count -= tcp_ctask->sent - start;
+ 
+ 		/*
+ 		 * XXX:we may run here with un-initial sendbuf.
+ 		 * so pass it
+ 		 */
+-		if (conn->datadgst_en && ctask->sent - start > 0)
+-			crypto_digest_update(conn->data_tx_tfm,
+-					     &ctask->sendbuf.sg, 1);
++		if (conn->datadgst_en && tcp_ctask->sent - start > 0)
++			crypto_digest_update(tcp_conn->data_tx_tfm,
++					     &tcp_ctask->sendbuf.sg, 1);
+ 
+ 		if (!ctask->data_count)
+ 			break;
+-		iscsi_buf_init_sg(&ctask->sendbuf,
+-				  &ctask->sg[ctask->sg_count++]);
++		iscsi_buf_init_sg(&tcp_ctask->sendbuf,
++				  &tcp_ctask->sg[tcp_ctask->sg_count++]);
+ 	}
+ 	BUG_ON(ctask->unsol_count < 0);
+ 
+@@ -1908,11 +1624,11 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 			debug_tcp("sending uns digest 0x%x, more uns\n",
+ 				  dtask->digest);
+ 		}
+-		ctask->xmstate |= XMSTATE_UNS_INIT;
++		tcp_ctask->xmstate |= XMSTATE_UNS_INIT;
+ 		return 1;
+ 	}
+ 
+-	if (conn->datadgst_en && !(ctask->xmstate & XMSTATE_W_PAD)) {
++	if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) {
+ 		if (iscsi_digest_final_send(conn, ctask,
+ 					    &dtask->digestbuf,
+ 					    &dtask->digest, 1)) {
+@@ -1930,15 +1646,17 @@ static inline int
+ handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+ 	struct iscsi_session *session = conn->session;
+-	struct iscsi_r2t_info *r2t = ctask->r2t;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++	struct iscsi_r2t_info *r2t = tcp_ctask->r2t;
+ 	struct iscsi_data_task *dtask = r2t->dtask;
+ 	int left;
+ 
+-	ctask->xmstate &= ~XMSTATE_SOL_DATA;
+-	ctask->dtask = dtask;
++	tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA;
++	tcp_ctask->dtask = dtask;
+ 
+ 	if (conn->datadgst_en) {
+-		iscsi_data_digest_init(conn, ctask);
++		iscsi_data_digest_init(tcp_conn, ctask);
+ 		dtask->digest = 0;
+ 	}
+ solicit_again:
+@@ -1949,10 +1667,10 @@ handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 		goto data_out_done;
+ 
+ 	if (iscsi_sendpage(conn, &r2t->sendbuf, &r2t->data_count, &r2t->sent)) {
+-		ctask->xmstate |= XMSTATE_SOL_DATA;
++		tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
+ 		/* will continue with this ctask later.. */
+ 		if (conn->datadgst_en) {
+-			crypto_digest_final(conn->data_tx_tfm,
++			crypto_digest_final(tcp_conn->data_tx_tfm,
+ 					  (u8 *)&dtask->digest);
+ 			debug_tcp("r2t data send fail 0x%x\n", dtask->digest);
+ 		}
+@@ -1961,12 +1679,13 @@ handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 
+ 	BUG_ON(r2t->data_count < 0);
+ 	if (conn->datadgst_en)
+-		crypto_digest_update(conn->data_tx_tfm, &r2t->sendbuf.sg, 1);
++		crypto_digest_update(tcp_conn->data_tx_tfm, &r2t->sendbuf.sg,
++				     1);
+ 
+ 	if (r2t->data_count) {
+ 		BUG_ON(ctask->sc->use_sg == 0);
+ 		if (!iscsi_buf_left(&r2t->sendbuf)) {
+-			BUG_ON(ctask->bad_sg == r2t->sg);
++			BUG_ON(tcp_ctask->bad_sg == r2t->sg);
+ 			iscsi_buf_init_sg(&r2t->sendbuf, r2t->sg);
+ 			r2t->sg += 1;
+ 		}
+@@ -1993,8 +1712,8 @@ handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 				  dtask->digest);
+ 		}
+ 		iscsi_solicit_data_cont(conn, ctask, r2t, left);
+-		ctask->xmstate |= XMSTATE_SOL_DATA;
+-		ctask->xmstate &= ~XMSTATE_SOL_HDR;
++		tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
++		tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
+ 		return 1;
+ 	}
+ 
+@@ -2002,7 +1721,7 @@ handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	 * Done with this R2T. Check if there are more
+ 	 * outstanding R2Ts ready to be processed.
+ 	 */
+-	BUG_ON(ctask->r2t_data_count - r2t->data_length < 0);
++	BUG_ON(tcp_ctask->r2t_data_count - r2t->data_length < 0);
+ 	if (conn->datadgst_en) {
+ 		if (iscsi_digest_final_send(conn, ctask, &dtask->digestbuf,
+ 					    &dtask->digest, 1)) {
+@@ -2013,15 +1732,15 @@ handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 		debug_tcp("r2t done dout digest 0x%x\n", dtask->digest);
+ 	}
+ 
+-	ctask->r2t_data_count -= r2t->data_length;
+-	ctask->r2t = NULL;
++	tcp_ctask->r2t_data_count -= r2t->data_length;
++	tcp_ctask->r2t = NULL;
+ 	spin_lock_bh(&session->lock);
+-	__kfifo_put(ctask->r2tpool.queue, (void*)&r2t, sizeof(void*));
++	__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*));
+ 	spin_unlock_bh(&session->lock);
+-	if (__kfifo_get(ctask->r2tqueue, (void*)&r2t, sizeof(void*))) {
+-		ctask->r2t = r2t;
+-		ctask->xmstate |= XMSTATE_SOL_DATA;
+-		ctask->xmstate &= ~XMSTATE_SOL_HDR;
++	if (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) {
++		tcp_ctask->r2t = r2t;
++		tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
++		tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
+ 		return 1;
+ 	}
+ 
+@@ -2031,29 +1750,34 @@ handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ static inline int
+ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+-	struct iscsi_data_task *dtask = ctask->dtask;
++	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	struct iscsi_data_task *dtask = tcp_ctask->dtask;
+ 	int sent;
+ 
+-	ctask->xmstate &= ~XMSTATE_W_PAD;
+-	iscsi_buf_init_virt(&ctask->sendbuf, (char*)&ctask->pad,
+-			    ctask->pad_count);
+-	if (iscsi_sendpage(conn, &ctask->sendbuf, &ctask->pad_count, &sent)) {
+-		ctask->xmstate |= XMSTATE_W_PAD;
++	tcp_ctask->xmstate &= ~XMSTATE_W_PAD;
++	iscsi_buf_init_virt(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad,
++			    tcp_ctask->pad_count);
++	if (iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count,
++			   &sent)) {
++		tcp_ctask->xmstate |= XMSTATE_W_PAD;
+ 		return -EAGAIN;
+ 	}
+ 
+ 	if (conn->datadgst_en) {
+-		crypto_digest_update(conn->data_tx_tfm, &ctask->sendbuf.sg, 1);
++		crypto_digest_update(tcp_conn->data_tx_tfm,
++				     &tcp_ctask->sendbuf.sg, 1);
+ 		/* imm data? */
+ 		if (!dtask) {
+-			if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf,
+-						    &ctask->immdigest, 1)) {
++			if (iscsi_digest_final_send(conn, ctask,
++						    &tcp_ctask->immbuf,
++						    &tcp_ctask->immdigest, 1)) {
+ 				debug_tcp("send padding digest 0x%x"
+-					  "fail!\n", ctask->immdigest);
++					  "fail!\n", tcp_ctask->immdigest);
+ 				return -EAGAIN;
+ 			}
+ 			debug_tcp("done with padding, digest 0x%x\n",
+-				  ctask->datadigest);
++				  tcp_ctask->datadigest);
+ 		} else {
+ 			if (iscsi_digest_final_send(conn, ctask,
+ 						    &dtask->digestbuf,
+@@ -2071,12 +1795,13 @@ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ }
+ 
+ static int
+-iscsi_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
++iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
++	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	int rc = 0;
+ 
+ 	debug_scsi("ctask deq [cid %d xmstate %x itt 0x%x]\n",
+-		conn->id, ctask->xmstate, ctask->itt);
++		conn->id, tcp_ctask->xmstate, ctask->itt);
+ 
+ 	/*
+ 	 * serialize with TMF AbortTask
+@@ -2084,40 +1809,40 @@ iscsi_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	if (ctask->mtask)
+ 		return rc;
+ 
+-	if (ctask->xmstate & XMSTATE_R_HDR) {
+-		rc = handle_xmstate_r_hdr(conn, ctask);
++	if (tcp_ctask->xmstate & XMSTATE_R_HDR) {
++		rc = handle_xmstate_r_hdr(conn, tcp_ctask);
+ 		return rc;
+ 	}
+ 
+-	if (ctask->xmstate & XMSTATE_W_HDR) {
++	if (tcp_ctask->xmstate & XMSTATE_W_HDR) {
+ 		rc = handle_xmstate_w_hdr(conn, ctask);
+ 		if (rc)
+ 			return rc;
+ 	}
+ 
+ 	/* XXX: for data digest xmit recover */
+-	if (ctask->xmstate & XMSTATE_DATA_DIGEST) {
++	if (tcp_ctask->xmstate & XMSTATE_DATA_DIGEST) {
+ 		rc = handle_xmstate_data_digest(conn, ctask);
+ 		if (rc)
+ 			return rc;
+ 	}
+ 
+-	if (ctask->xmstate & XMSTATE_IMM_DATA) {
++	if (tcp_ctask->xmstate & XMSTATE_IMM_DATA) {
+ 		rc = handle_xmstate_imm_data(conn, ctask);
+ 		if (rc)
+ 			return rc;
+ 	}
+ 
+-	if (ctask->xmstate & XMSTATE_UNS_HDR) {
++	if (tcp_ctask->xmstate & XMSTATE_UNS_HDR) {
+ 		BUG_ON(!ctask->unsol_count);
+-		ctask->xmstate &= ~XMSTATE_UNS_HDR;
++		tcp_ctask->xmstate &= ~XMSTATE_UNS_HDR;
+ unsolicit_head_again:
+ 		rc = handle_xmstate_uns_hdr(conn, ctask);
+ 		if (rc)
+ 			return rc;
+ 	}
+ 
+-	if (ctask->xmstate & XMSTATE_UNS_DATA) {
++	if (tcp_ctask->xmstate & XMSTATE_UNS_DATA) {
+ 		rc = handle_xmstate_uns_data(conn, ctask);
+ 		if (rc == 1)
+ 			goto unsolicit_head_again;
+@@ -2126,22 +1851,22 @@ iscsi_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 		goto done;
+ 	}
+ 
+-	if (ctask->xmstate & XMSTATE_SOL_HDR) {
++	if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) {
+ 		struct iscsi_r2t_info *r2t;
+ 
+-		ctask->xmstate &= ~XMSTATE_SOL_HDR;
+-		ctask->xmstate |= XMSTATE_SOL_DATA;
+-		if (!ctask->r2t)
+-			__kfifo_get(ctask->r2tqueue, (void*)&ctask->r2t,
++		tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
++		tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
++		if (!tcp_ctask->r2t)
++			__kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t,
+ 				    sizeof(void*));
+ solicit_head_again:
+-		r2t = ctask->r2t;
++		r2t = tcp_ctask->r2t;
+ 		if (conn->hdrdgst_en)
+ 			iscsi_hdr_digest(conn, &r2t->headbuf,
+ 					(u8*)r2t->dtask->hdrext);
+ 		if (iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count)) {
+-			ctask->xmstate &= ~XMSTATE_SOL_DATA;
+-			ctask->xmstate |= XMSTATE_SOL_HDR;
++			tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA;
++			tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
+ 			return -EAGAIN;
+ 		}
+ 
+@@ -2150,7 +1875,7 @@ iscsi_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 			r2t->sent);
+ 	}
+ 
+-	if (ctask->xmstate & XMSTATE_SOL_DATA) {
++	if (tcp_ctask->xmstate & XMSTATE_SOL_DATA) {
+ 		rc = handle_xmstate_sol_data(conn, ctask);
+ 		if (rc == 1)
+ 			goto solicit_head_again;
+@@ -2163,529 +1888,116 @@ iscsi_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	 * Last thing to check is whether we need to send write
+ 	 * padding. Note that we check for xmstate equality, not just the bit.
+ 	 */
+-	if (ctask->xmstate == XMSTATE_W_PAD)
++	if (tcp_ctask->xmstate == XMSTATE_W_PAD)
+ 		rc = handle_xmstate_w_pad(conn, ctask);
+ 
+ 	return rc;
+ }
+ 
+-/**
+- * iscsi_data_xmit - xmit any command into the scheduled connection
+- * @conn: iscsi connection
+- *
+- * Notes:
+- *	The function can return -EAGAIN in which case the caller must
+- *	re-schedule it again later or recover. '0' return code means
+- *	successful xmit.
+- **/
+-static int
+-iscsi_data_xmit(struct iscsi_conn *conn)
++static struct iscsi_cls_conn *
++iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ {
+-	if (unlikely(conn->suspend_tx)) {
+-		debug_tcp("conn %d Tx suspended!\n", conn->id);
+-		return 0;
+-	}
++	struct iscsi_conn *conn;
++	struct iscsi_cls_conn *cls_conn;
++	struct iscsi_tcp_conn *tcp_conn;
+ 
++	cls_conn = iscsi_conn_setup(cls_session, conn_idx);
++	if (!cls_conn)
++		return NULL;
++	conn = cls_conn->dd_data;
+ 	/*
+-	 * Transmit in the following order:
+-	 *
+-	 * 1) un-finished xmit (ctask or mtask)
+-	 * 2) immediate control PDUs
+-	 * 3) write data
+-	 * 4) SCSI commands
+-	 * 5) non-immediate control PDUs
+-	 *
+-	 * No need to lock around __kfifo_get as long as
+-	 * there's one producer and one consumer.
++	 * due to strange issues with iser these are not set
++	 * in iscsi_conn_setup
+ 	 */
++	conn->max_recv_dlength = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
+ 
+-	BUG_ON(conn->ctask && conn->mtask);
+-
+-	if (conn->ctask) {
+-		if (iscsi_ctask_xmit(conn, conn->ctask))
+-			goto again;
+-		/* done with this in-progress ctask */
+-		conn->ctask = NULL;
+-	}
+-	if (conn->mtask) {
+-	        if (iscsi_mtask_xmit(conn, conn->mtask))
+-		        goto again;
+-		/* done with this in-progress mtask */
+-		conn->mtask = NULL;
+-	}
+-
+-	/* process immediate first */
+-        if (unlikely(__kfifo_len(conn->immqueue))) {
+-		struct iscsi_session *session = conn->session;
+-	        while (__kfifo_get(conn->immqueue, (void*)&conn->mtask,
+-			           sizeof(void*))) {
+-		        if (iscsi_mtask_xmit(conn, conn->mtask))
+-			        goto again;
+-
+-		        if (conn->mtask->hdr.itt ==
+-					cpu_to_be32(ISCSI_RESERVED_TAG)) {
+-			        spin_lock_bh(&session->lock);
+-			        __kfifo_put(session->mgmtpool.queue,
+-					    (void*)&conn->mtask, sizeof(void*));
+-			        spin_unlock_bh(&session->lock);
+-		        }
+-	        }
+-		/* done with this mtask */
+-		conn->mtask = NULL;
+-	}
+-
+-	/* process write queue */
+-	while (__kfifo_get(conn->writequeue, (void*)&conn->ctask,
+-			   sizeof(void*))) {
+-		if (iscsi_ctask_xmit(conn, conn->ctask))
+-			goto again;
+-	}
+-
+-	/* process command queue */
+-	while (__kfifo_get(conn->xmitqueue, (void*)&conn->ctask,
+-			   sizeof(void*))) {
+-		list_add_tail(&conn->ctask->running, &conn->run_list);
+-		if (iscsi_ctask_xmit(conn, conn->ctask))
+-			goto again;
+-	}
+-	/* done with this ctask */
+-	conn->ctask = NULL;
+-
+-	/* process the rest control plane PDUs, if any */
+-        if (unlikely(__kfifo_len(conn->mgmtqueue))) {
+-		struct iscsi_session *session = conn->session;
+-
+-	        while (__kfifo_get(conn->mgmtqueue, (void*)&conn->mtask,
+-			           sizeof(void*))) {
+-		        if (iscsi_mtask_xmit(conn, conn->mtask))
+-			        goto again;
++	tcp_conn = kzalloc(sizeof(*tcp_conn), GFP_KERNEL);
++	if (!tcp_conn)
++		goto tcp_conn_alloc_fail;
+ 
+-		        if (conn->mtask->hdr.itt ==
+-					cpu_to_be32(ISCSI_RESERVED_TAG)) {
+-			        spin_lock_bh(&session->lock);
+-			        __kfifo_put(session->mgmtpool.queue,
+-					    (void*)&conn->mtask,
+-				            sizeof(void*));
+-			        spin_unlock_bh(&session->lock);
+-		        }
+-	        }
+-		/* done with this mtask */
+-		conn->mtask = NULL;
+-	}
++	conn->dd_data = tcp_conn;
++	tcp_conn->iscsi_conn = conn;
++	tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
++	/* initial operational parameters */
++	tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
++	tcp_conn->data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
+ 
+-	return 0;
++	/* allocate initial PDU receive place holder */
++	if (tcp_conn->data_size <= PAGE_SIZE)
++		tcp_conn->data = kmalloc(tcp_conn->data_size, GFP_KERNEL);
++	else
++		tcp_conn->data = (void*)__get_free_pages(GFP_KERNEL,
++					get_order(tcp_conn->data_size));
++	if (!tcp_conn->data)
++		goto max_recv_dlenght_alloc_fail;
+ 
+-again:
+-	if (unlikely(conn->suspend_tx))
+-		return 0;
++	return cls_conn;
+ 
+-	return -EAGAIN;
++max_recv_dlenght_alloc_fail:
++	kfree(tcp_conn);
++tcp_conn_alloc_fail:
++	iscsi_conn_teardown(cls_conn);
++	return NULL;
+ }
+ 
+ static void
+-iscsi_xmitworker(void *data)
++iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn)
+ {
+-	struct iscsi_conn *conn = data;
+-
+-	/*
+-	 * serialize Xmit worker on a per-connection basis.
+-	 */
+-	mutex_lock(&conn->xmitmutex);
+-	if (iscsi_data_xmit(conn))
+-		scsi_queue_work(conn->session->host, &conn->xmitwork);
+-	mutex_unlock(&conn->xmitmutex);
+-}
++	struct iscsi_conn *conn = cls_conn->dd_data;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	int digest = 0;
+ 
+-enum {
+-	FAILURE_BAD_HOST = 1,
+-	FAILURE_SESSION_FAILED,
+-	FAILURE_SESSION_FREED,
+-	FAILURE_WINDOW_CLOSED,
+-	FAILURE_SESSION_TERMINATE,
+-	FAILURE_SESSION_RECOVERY_TIMEOUT,
+-};
++	if (conn->hdrdgst_en || conn->datadgst_en)
++		digest = 1;
+ 
+-static int
+-iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+-{
+-	struct Scsi_Host *host;
+-	int reason = 0;
+-	struct iscsi_session *session;
+-	struct iscsi_conn *conn = NULL;
+-	struct iscsi_cmd_task *ctask = NULL;
++	iscsi_conn_teardown(cls_conn);
+ 
+-	sc->scsi_done = done;
+-	sc->result = 0;
++	/* now free tcp_conn */
++	if (digest) {
++		if (tcp_conn->tx_tfm)
++			crypto_free_tfm(tcp_conn->tx_tfm);
++		if (tcp_conn->rx_tfm)
++			crypto_free_tfm(tcp_conn->rx_tfm);
++		if (tcp_conn->data_tx_tfm)
++			crypto_free_tfm(tcp_conn->data_tx_tfm);
++		if (tcp_conn->data_rx_tfm)
++			crypto_free_tfm(tcp_conn->data_rx_tfm);
++	}
+ 
+-	host = sc->device->host;
+-	session = iscsi_hostdata(host->hostdata);
++	/* free conn->data, size = MaxRecvDataSegmentLength */
++	if (tcp_conn->data_size <= PAGE_SIZE)
++		kfree(tcp_conn->data);
++	else
++		free_pages((unsigned long)tcp_conn->data,
++			   get_order(tcp_conn->data_size));
++	kfree(tcp_conn);
++}
+ 
+-	spin_lock(&session->lock);
++static int
++iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
++		    struct iscsi_cls_conn *cls_conn, uint32_t transport_fd,
++		    int is_leading)
++{
++	struct iscsi_conn *conn = cls_conn->dd_data;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++	struct sock *sk;
++	struct socket *sock;
++	int err;
+ 
+-	if (session->state != ISCSI_STATE_LOGGED_IN) {
+-		if (session->recovery_failed) {
+-			reason = FAILURE_SESSION_RECOVERY_TIMEOUT;
+-			goto fault;
+-		} else if (session->state == ISCSI_STATE_FAILED) {
+-			reason = FAILURE_SESSION_FAILED;
+-			goto reject;
+-		} else if (session->state == ISCSI_STATE_TERMINATE) {
+-			reason = FAILURE_SESSION_TERMINATE;
+-			goto fault;
+-		}
+-		reason = FAILURE_SESSION_FREED;
+-		goto fault;
++	/* lookup for existing socket */
++	sock = sockfd_lookup(transport_fd, &err);
++	if (!sock) {
++		printk(KERN_ERR "iscsi_tcp: sockfd_lookup failed %d\n", err);
++		return -EEXIST;
+ 	}
+ 
+-	/*
+-	 * Check for iSCSI window and take care of CmdSN wrap-around
+-	 */
+-	if ((int)(session->max_cmdsn - session->cmdsn) < 0) {
+-		reason = FAILURE_WINDOW_CLOSED;
+-		goto reject;
+-	}
++	err = iscsi_conn_bind(cls_session, cls_conn, is_leading);
++	if (err)
++		return err;
+ 
+-	conn = session->leadconn;
+-
+-	__kfifo_get(session->cmdpool.queue, (void*)&ctask, sizeof(void*));
+-	BUG_ON(ctask->sc);
+-
+-	sc->SCp.phase = session->age;
+-	sc->SCp.ptr = (char*)ctask;
+-	iscsi_cmd_init(conn, ctask, sc);
+-
+-	__kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*));
+-	debug_scsi(
+-	       "ctask enq [%s cid %d sc %lx itt 0x%x len %d cmdsn %d win %d]\n",
+-		sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
+-		conn->id, (long)sc, ctask->itt, sc->request_bufflen,
+-		session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
+-	spin_unlock(&session->lock);
+-
+-	scsi_queue_work(host, &conn->xmitwork);
+-	return 0;
+-
+-reject:
+-	spin_unlock(&session->lock);
+-	debug_scsi("cmd 0x%x rejected (%d)\n", sc->cmnd[0], reason);
+-	return SCSI_MLQUEUE_HOST_BUSY;
+-
+-fault:
+-	spin_unlock(&session->lock);
+-	printk(KERN_ERR "iscsi_tcp: cmd 0x%x is not queued (%d)\n",
+-	       sc->cmnd[0], reason);
+-	sc->result = (DID_NO_CONNECT << 16);
+-	sc->resid = sc->request_bufflen;
+-	sc->scsi_done(sc);
+-	return 0;
+-}
+-
+-static int
+-iscsi_change_queue_depth(struct scsi_device *sdev, int depth)
+-{
+-	if (depth > ISCSI_MAX_CMD_PER_LUN)
+-		depth = ISCSI_MAX_CMD_PER_LUN;
+-	scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
+-	return sdev->queue_depth;
+-}
+-
+-static int
+-iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size)
+-{
+-	int i;
+-
+-	*items = kmalloc(max * sizeof(void*), GFP_KERNEL);
+-	if (*items == NULL)
+-		return -ENOMEM;
+-
+-	q->max = max;
+-	q->pool = kmalloc(max * sizeof(void*), GFP_KERNEL);
+-	if (q->pool == NULL) {
+-		kfree(*items);
+-		return -ENOMEM;
+-	}
+-
+-	q->queue = kfifo_init((void*)q->pool, max * sizeof(void*),
+-			      GFP_KERNEL, NULL);
+-	if (q->queue == ERR_PTR(-ENOMEM)) {
+-		kfree(q->pool);
+-		kfree(*items);
+-		return -ENOMEM;
+-	}
+-
+-	for (i = 0; i < max; i++) {
+-		q->pool[i] = kmalloc(item_size, GFP_KERNEL);
+-		if (q->pool[i] == NULL) {
+-			int j;
+-
+-			for (j = 0; j < i; j++)
+-				kfree(q->pool[j]);
+-
+-			kfifo_free(q->queue);
+-			kfree(q->pool);
+-			kfree(*items);
+-			return -ENOMEM;
+-		}
+-		memset(q->pool[i], 0, item_size);
+-		(*items)[i] = q->pool[i];
+-		__kfifo_put(q->queue, (void*)&q->pool[i], sizeof(void*));
+-	}
+-	return 0;
+-}
+-
+-static void
+-iscsi_pool_free(struct iscsi_queue *q, void **items)
+-{
+-	int i;
+-
+-	for (i = 0; i < q->max; i++)
+-		kfree(items[i]);
+-	kfree(q->pool);
+-	kfree(items);
+-}
+-
+-static struct iscsi_cls_conn *
+-iscsi_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+-{
+-	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+-	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+-	struct iscsi_conn *conn;
+-	struct iscsi_cls_conn *cls_conn;
+-
+-	cls_conn = iscsi_create_conn(cls_session, conn_idx);
+-	if (!cls_conn)
+-		return NULL;
+-	conn = cls_conn->dd_data;
+-	memset(conn, 0, sizeof(*conn));
+-
+-	conn->cls_conn = cls_conn;
+-	conn->c_stage = ISCSI_CONN_INITIAL_STAGE;
+-	conn->in_progress = IN_PROGRESS_WAIT_HEADER;
+-	conn->id = conn_idx;
+-	conn->exp_statsn = 0;
+-	conn->tmabort_state = TMABORT_INITIAL;
+-	INIT_LIST_HEAD(&conn->run_list);
+-
+-	/* initial operational parameters */
+-	conn->hdr_size = sizeof(struct iscsi_hdr);
+-	conn->data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
+-	conn->max_recv_dlength = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
+-
+-	/* initialize general xmit PDU commands queue */
+-	conn->xmitqueue = kfifo_alloc(session->cmds_max * sizeof(void*),
+-					GFP_KERNEL, NULL);
+-	if (conn->xmitqueue == ERR_PTR(-ENOMEM))
+-		goto xmitqueue_alloc_fail;
+-
+-	/* initialize write response PDU commands queue */
+-	conn->writequeue = kfifo_alloc(session->cmds_max * sizeof(void*),
+-					GFP_KERNEL, NULL);
+-	if (conn->writequeue == ERR_PTR(-ENOMEM))
+-		goto writequeue_alloc_fail;
+-
+-	/* initialize general immediate & non-immediate PDU commands queue */
+-	conn->immqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*),
+-			                GFP_KERNEL, NULL);
+-	if (conn->immqueue == ERR_PTR(-ENOMEM))
+-		goto immqueue_alloc_fail;
+-
+-	conn->mgmtqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*),
+-			                GFP_KERNEL, NULL);
+-	if (conn->mgmtqueue == ERR_PTR(-ENOMEM))
+-		goto mgmtqueue_alloc_fail;
+-
+-	INIT_WORK(&conn->xmitwork, iscsi_xmitworker, conn);
+-
+-	/* allocate login_mtask used for the login/text sequences */
+-	spin_lock_bh(&session->lock);
+-	if (!__kfifo_get(session->mgmtpool.queue,
+-                         (void*)&conn->login_mtask,
+-			 sizeof(void*))) {
+-		spin_unlock_bh(&session->lock);
+-		goto login_mtask_alloc_fail;
+-	}
+-	spin_unlock_bh(&session->lock);
+-
+-	/* allocate initial PDU receive place holder */
+-	if (conn->data_size <= PAGE_SIZE)
+-		conn->data = kmalloc(conn->data_size, GFP_KERNEL);
+-	else
+-		conn->data = (void*)__get_free_pages(GFP_KERNEL,
+-					get_order(conn->data_size));
+-	if (!conn->data)
+-		goto max_recv_dlenght_alloc_fail;
+-
+-	init_timer(&conn->tmabort_timer);
+-	mutex_init(&conn->xmitmutex);
+-	init_waitqueue_head(&conn->ehwait);
+-
+-	return cls_conn;
+-
+-max_recv_dlenght_alloc_fail:
+-	spin_lock_bh(&session->lock);
+-	__kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask,
+-		    sizeof(void*));
+-	spin_unlock_bh(&session->lock);
+-login_mtask_alloc_fail:
+-	kfifo_free(conn->mgmtqueue);
+-mgmtqueue_alloc_fail:
+-	kfifo_free(conn->immqueue);
+-immqueue_alloc_fail:
+-	kfifo_free(conn->writequeue);
+-writequeue_alloc_fail:
+-	kfifo_free(conn->xmitqueue);
+-xmitqueue_alloc_fail:
+-	iscsi_destroy_conn(cls_conn);
+-	return NULL;
+-}
+-
+-static void
+-iscsi_conn_destroy(struct iscsi_cls_conn *cls_conn)
+-{
+-	struct iscsi_conn *conn = cls_conn->dd_data;
+-	struct iscsi_session *session = conn->session;
+-	unsigned long flags;
+-
+-	mutex_lock(&conn->xmitmutex);
+-	set_bit(SUSPEND_BIT, &conn->suspend_tx);
+-	if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE && conn->sock) {
+-		struct sock *sk = conn->sock->sk;
+-
+-		/*
+-		 * conn_start() has never been called!
+-		 * need to cleanup the socket.
+-		 */
+-		write_lock_bh(&sk->sk_callback_lock);
+-		set_bit(SUSPEND_BIT, &conn->suspend_rx);
+-		write_unlock_bh(&sk->sk_callback_lock);
+-
+-		sock_hold(conn->sock->sk);
+-		iscsi_conn_restore_callbacks(conn);
+-		sock_put(conn->sock->sk);
+-		sock_release(conn->sock);
+-		conn->sock = NULL;
+-	}
+-
+-	spin_lock_bh(&session->lock);
+-	conn->c_stage = ISCSI_CONN_CLEANUP_WAIT;
+-	if (session->leadconn == conn) {
+-		/*
+-		 * leading connection? then give up on recovery.
+-		 */
+-		session->state = ISCSI_STATE_TERMINATE;
+-		wake_up(&conn->ehwait);
+-	}
+-	spin_unlock_bh(&session->lock);
+-
+-	mutex_unlock(&conn->xmitmutex);
+-
+-	/*
+-	 * Block until all in-progress commands for this connection
+-	 * time out or fail.
+-	 */
+-	for (;;) {
+-		spin_lock_irqsave(session->host->host_lock, flags);
+-		if (!session->host->host_busy) { /* OK for ERL == 0 */
+-			spin_unlock_irqrestore(session->host->host_lock, flags);
+-			break;
+-		}
+-		spin_unlock_irqrestore(session->host->host_lock, flags);
+-		msleep_interruptible(500);
+-		printk("conn_destroy(): host_busy %d host_failed %d\n",
+-			session->host->host_busy, session->host->host_failed);
+-		/*
+-		 * force eh_abort() to unblock
+-		 */
+-		wake_up(&conn->ehwait);
+-	}
+-
+-	/* now free crypto */
+-	if (conn->hdrdgst_en || conn->datadgst_en) {
+-		if (conn->tx_tfm)
+-			crypto_free_tfm(conn->tx_tfm);
+-		if (conn->rx_tfm)
+-			crypto_free_tfm(conn->rx_tfm);
+-		if (conn->data_tx_tfm)
+-			crypto_free_tfm(conn->data_tx_tfm);
+-		if (conn->data_rx_tfm)
+-			crypto_free_tfm(conn->data_rx_tfm);
+-	}
+-
+-	/* free conn->data, size = MaxRecvDataSegmentLength */
+-	if (conn->data_size <= PAGE_SIZE)
+-		kfree(conn->data);
+-	else
+-		free_pages((unsigned long)conn->data,
+-					get_order(conn->data_size));
+-
+-	spin_lock_bh(&session->lock);
+-	__kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask,
+-		    sizeof(void*));
+-	list_del(&conn->item);
+-	if (list_empty(&session->connections))
+-		session->leadconn = NULL;
+-	if (session->leadconn && session->leadconn == conn)
+-		session->leadconn = container_of(session->connections.next,
+-			struct iscsi_conn, item);
+-
+-	if (session->leadconn == NULL)
+-		/* none connections exits.. reset sequencing */
+-		session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1;
+-	spin_unlock_bh(&session->lock);
+-
+-	kfifo_free(conn->xmitqueue);
+-	kfifo_free(conn->writequeue);
+-	kfifo_free(conn->immqueue);
+-	kfifo_free(conn->mgmtqueue);
+-
+-	iscsi_destroy_conn(cls_conn);
+-}
+-
+-static int
+-iscsi_conn_bind(struct iscsi_cls_session *cls_session,
+-		struct iscsi_cls_conn *cls_conn, uint32_t transport_fd,
+-		int is_leading)
+-{
+-	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+-	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+-	struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = cls_conn->dd_data;
+-	struct sock *sk;
+-	struct socket *sock;
+-	int err;
+-
+-	/* lookup for existing socket */
+-	sock = sockfd_lookup(transport_fd, &err);
+-	if (!sock) {
+-		printk(KERN_ERR "iscsi_tcp: sockfd_lookup failed %d\n", err);
+-		return -EEXIST;
+-	}
+-
+-	/* lookup for existing connection */
+-	spin_lock_bh(&session->lock);
+-	list_for_each_entry(tmp, &session->connections, item) {
+-		if (tmp == conn) {
+-			if (conn->c_stage != ISCSI_CONN_STOPPED ||
+-			    conn->stop_stage == STOP_CONN_TERM) {
+-				printk(KERN_ERR "iscsi_tcp: can't bind "
+-				       "non-stopped connection (%d:%d)\n",
+-				       conn->c_stage, conn->stop_stage);
+-				spin_unlock_bh(&session->lock);
+-				return -EIO;
+-			}
+-			break;
+-		}
+-	}
+-	if (tmp != conn) {
+-		/* bind new iSCSI connection to session */
+-		conn->session = session;
+-
+-		list_add(&conn->item, &session->connections);
+-	}
+-	spin_unlock_bh(&session->lock);
+-
+-	if (conn->stop_stage != STOP_CONN_SUSPEND) {
+-		/* bind iSCSI connection and socket */
+-		conn->sock = sock;
++	if (conn->stop_stage != STOP_CONN_SUSPEND) {
++		/* bind iSCSI connection and socket */
++		tcp_conn->sock = sock;
+ 
+ 		/* setup Socket parameters */
+ 		sk = sock->sk;
+@@ -2699,608 +2011,78 @@ iscsi_conn_bind(struct iscsi_cls_session *cls_session,
+ 		 * Intercept TCP callbacks for sendfile like receive
+ 		 * processing.
+ 		 */
++		conn->recv_lock = &sk->sk_callback_lock;
+ 		iscsi_conn_set_callbacks(conn);
+-
+-		conn->sendpage = conn->sock->ops->sendpage;
+-
++		tcp_conn->sendpage = tcp_conn->sock->ops->sendpage;
+ 		/*
+ 		 * set receive state machine into initial state
+ 		 */
+-		conn->in_progress = IN_PROGRESS_WAIT_HEADER;
++		tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
+ 	}
+ 
+-	if (is_leading)
+-		session->leadconn = conn;
+-
+-	/*
+-	 * Unblock xmitworker(), Login Phase will pass through.
+-	 */
+-	clear_bit(SUSPEND_BIT, &conn->suspend_rx);
+-	clear_bit(SUSPEND_BIT, &conn->suspend_tx);
+-
+ 	return 0;
+ }
+ 
+ static void
+-iscsi_session_recovery_timedout(struct iscsi_cls_session *csession)
+-{
+-	struct Scsi_Host *shost = iscsi_session_to_shost(csession);
+-	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+-	struct iscsi_conn *conn = session->leadconn;
+-
+-	spin_lock_bh(&session->lock);
+-	if (session->state != ISCSI_STATE_LOGGED_IN) {
+-		session->recovery_failed = 1;
+-		if (conn)
+-			wake_up(&conn->ehwait);
+-	}
+-	spin_unlock_bh(&session->lock);
+-}
+-
+-static int
+-iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
+-{
+-	struct iscsi_conn *conn = cls_conn->dd_data;
+-	struct iscsi_session *session = conn->session;
+-	struct sock *sk;
+-
+-	/* FF phase warming up... */
+-
+-	if (session == NULL) {
+-		printk(KERN_ERR "iscsi_tcp: can't start unbound connection\n");
+-		return -EPERM;
+-	}
+-
+-	sk = conn->sock->sk;
+-	write_lock_bh(&sk->sk_callback_lock);
+-	spin_lock_bh(&session->lock);
+-	conn->c_stage = ISCSI_CONN_STARTED;
+-	session->state = ISCSI_STATE_LOGGED_IN;
+-
+-	switch(conn->stop_stage) {
+-	case STOP_CONN_RECOVER:
+-		/*
+-		 * unblock eh_abort() if it is blocked. re-try all
+-		 * commands after successful recovery
+-		 */
+-		session->conn_cnt++;
+-		conn->stop_stage = 0;
+-		conn->tmabort_state = TMABORT_INITIAL;
+-		session->age++;
+-		session->recovery_failed = 0;
+-		spin_unlock_bh(&session->lock);
+-		write_unlock_bh(&sk->sk_callback_lock);
+-
+-		iscsi_unblock_session(session_to_cls(session));
+-		wake_up(&conn->ehwait);
+-		return 0;
+-	case STOP_CONN_TERM:
+-		session->conn_cnt++;
+-		conn->stop_stage = 0;
+-		break;
+-	case STOP_CONN_SUSPEND:
+-		conn->stop_stage = 0;
+-		clear_bit(SUSPEND_BIT, &conn->suspend_rx);
+-		clear_bit(SUSPEND_BIT, &conn->suspend_tx);
+-		break;
+-	default:
+-		break;
+-	}
+-	spin_unlock_bh(&session->lock);
+-	write_unlock_bh(&sk->sk_callback_lock);
+-
+-	return 0;
+-}
+-
+-static int
+-iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask)
+-{
+-	struct iscsi_conn *conn = ctask->conn;
+-	struct iscsi_session *session = conn->session;
+-	struct iscsi_mgmt_task *mtask;
+-
+-	if (!ctask->mtask)
+-		return -EINVAL;
+-
+-	while (__kfifo_get(conn->immqueue, (void*)&mtask, sizeof(void*))) {
+-		if (mtask == ctask->mtask)
+-			break;
+-		__kfifo_put(conn->immqueue, (void*)&mtask, sizeof(void*));
+-	}
+-
+-	__kfifo_put(session->mgmtpool.queue, (void*)&ctask->mtask,
+-		    sizeof(void*));
+-	ctask->mtask = NULL;
+-	return 0;
+-}
+-
+-static void
+-fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, int err)
++iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
++	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	struct iscsi_r2t_info *r2t;
+-	struct scsi_cmnd *sc;
+ 
+ 	/* flush ctask's r2t queues */
+-	while (__kfifo_get(ctask->r2tqueue, (void*)&r2t, sizeof(void*)))
+-		__kfifo_put(ctask->r2tpool.queue, (void*)&r2t, sizeof(void*));
+-
+-	iscsi_ctask_mtask_cleanup(ctask);
+-
+-	sc = ctask->sc;
+-	if (!sc)
+-		return;
+-
+-	sc->result = err;
+-	sc->resid = sc->request_bufflen;
+-
+-	__iscsi_ctask_cleanup(conn, ctask);
+-}
+-
+-/* Fail commands. Mutex and session lock held */
+-static void
+-fail_all_commands(struct iscsi_session *session, struct iscsi_conn *conn)
+-{
+-	struct iscsi_cmd_task *ctask, *tmp;
+-
+-	/* flush pending */
+-	while (__kfifo_get(conn->xmitqueue, (void*)&ctask, sizeof(void*))) {
+-		debug_scsi("failing pending sc %p itt 0x%x\n", ctask->sc,
+-			   ctask->itt);
+-		fail_command(conn, ctask, DID_BUS_BUSY << 16);
+-	}
+-
+-	/* fail running */
+-	list_for_each_entry_safe(ctask, tmp, &conn->run_list, running) {
+-		debug_scsi("failing in progress sc %p itt 0x%x\n",
+-			   ctask->sc, ctask->itt);
+-		fail_command(conn, ctask, DID_BUS_BUSY << 16);
+-	}
+-
+-	conn->ctask = NULL;
+-}
+-
+-static void
+-flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn)
+-{
+-	struct iscsi_mgmt_task *mtask;
+-
+-	/* TODO: handle running pdus */
+-	while (__kfifo_get(conn->immqueue, (void*)&mtask, sizeof(void*)) ||
+-	       __kfifo_get(conn->mgmtqueue, (void*)&mtask, sizeof(void*))) {
+-		if (mtask == conn->login_mtask)
+-			continue;
+-		__kfifo_put(session->mgmtpool.queue, (void*)&mtask,
++	while (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*)))
++		__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
+ 			    sizeof(void*));
+-	}
+ 
+-	if (conn->mtask && conn->mtask != conn->login_mtask)
+-		__kfifo_put(session->mgmtpool.queue, (void*)&conn->mtask,
+-			    sizeof(void*));
+-	conn->mtask = NULL;
++	__iscsi_ctask_cleanup(conn, ctask);
+ }
+ 
+ static void
+-iscsi_suspend_conn_rx(struct iscsi_conn *conn)
++iscsi_tcp_suspend_conn_rx(struct iscsi_conn *conn)
+ {
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	struct sock *sk;
+ 
+-	BUG_ON(!conn->sock);
+-	sk = conn->sock->sk;
++	if (!tcp_conn->sock)
++		return;
++
++	sk = tcp_conn->sock->sk;
+ 	write_lock_bh(&sk->sk_callback_lock);
+-	set_bit(SUSPEND_BIT, &conn->suspend_rx);
++	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
+ 	write_unlock_bh(&sk->sk_callback_lock);
+ }
+ 
+ static void
+-iscsi_start_session_recovery(struct iscsi_session *session,
+-			     struct iscsi_conn *conn, int flag)
++iscsi_tcp_terminate_conn(struct iscsi_conn *conn)
+ {
+-	spin_lock_bh(&session->lock);
+-	if (conn->stop_stage == STOP_CONN_RECOVER ||
+-	    conn->stop_stage == STOP_CONN_TERM) {
+-		spin_unlock_bh(&session->lock);
+-		return;
+-	}
+-	conn->stop_stage = flag;
+-	spin_unlock_bh(&session->lock);
+-
+-	iscsi_suspend_conn_rx(conn);
+-
+-	mutex_lock(&conn->xmitmutex);
+-	spin_lock_bh(&session->lock);
+-	conn->c_stage = ISCSI_CONN_STOPPED;
+-	set_bit(SUSPEND_BIT, &conn->suspend_tx);
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 
+-	session->conn_cnt--;
+-	if (session->conn_cnt == 0 || session->leadconn == conn)
+-		session->state = ISCSI_STATE_FAILED;
+-
+-	spin_unlock_bh(&session->lock);
++	if (!tcp_conn->sock)
++		return;
+ 
+-	/*
+-	 * Socket must go now.
+-	 */
+-	sock_hold(conn->sock->sk);
++	sock_hold(tcp_conn->sock->sk);
+ 	iscsi_conn_restore_callbacks(conn);
+-	sock_put(conn->sock->sk);
++	sock_put(tcp_conn->sock->sk);
+ 
+-	/*
+-	 * flush queues.
+-	 */
+-	spin_lock_bh(&session->lock);
+-	fail_all_commands(session, conn);
+-	flush_control_queues(session, conn);
+-	spin_unlock_bh(&session->lock);
+-
+-	/*
+-	 * release socket only after we stopped data_xmit()
+-	 * activity and flushed all outstandings
+-	 */
+-	sock_release(conn->sock);
+-	conn->sock = NULL;
+-
+-	/*
+-	 * for connection level recovery we should not calculate
+-	 * header digest. conn->hdr_size used for optimization
+-	 * in hdr_extract() and will be re-negotiated at
+-	 * set_param() time.
+-	 */
+-	if (flag == STOP_CONN_RECOVER) {
+-		conn->hdr_size = sizeof(struct iscsi_hdr);
+-		conn->hdrdgst_en = 0;
+-		conn->datadgst_en = 0;
+-
+-		if (session->state == ISCSI_STATE_FAILED)
+-			iscsi_block_session(session_to_cls(session));
+-	}
+-	mutex_unlock(&conn->xmitmutex);
++	sock_release(tcp_conn->sock);
++	tcp_conn->sock = NULL;
++	conn->recv_lock = NULL;
+ }
+ 
++/* called with host lock */
+ static void
+-iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+-{
+-	struct iscsi_conn *conn = cls_conn->dd_data;
+-	struct iscsi_session *session = conn->session;
+-
+-	switch (flag) {
+-	case STOP_CONN_RECOVER:
+-	case STOP_CONN_TERM:
+-		iscsi_start_session_recovery(session, conn, flag);
+-		return;
+-	case STOP_CONN_SUSPEND:
+-		iscsi_suspend_conn_rx(conn);
+-
+-		mutex_lock(&conn->xmitmutex);
+-		spin_lock_bh(&session->lock);
+-
+-		conn->stop_stage = flag;
+-		conn->c_stage = ISCSI_CONN_STOPPED;
+-		set_bit(SUSPEND_BIT, &conn->suspend_tx);
+-
+-		spin_unlock_bh(&session->lock);
+-		mutex_unlock(&conn->xmitmutex);
+-		break;
+-	default:
+-		printk(KERN_ERR "invalid stop flag %d\n", flag);
+-	}
+-}
+-
+-static int
+-iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+-			char *data, uint32_t data_size)
++iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask,
++		    char *data, uint32_t data_size)
+ {
+-	struct iscsi_session *session = conn->session;
+-	struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr;
+-	struct iscsi_mgmt_task *mtask;
+-
+-	spin_lock_bh(&session->lock);
+-	if (session->state == ISCSI_STATE_TERMINATE) {
+-		spin_unlock_bh(&session->lock);
+-		return -EPERM;
+-	}
+-	if (hdr->opcode == (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) ||
+-	    hdr->opcode == (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE))
+-		/*
+-		 * Login and Text are sent serially, in
+-		 * request-followed-by-response sequence.
+-		 * Same mtask can be used. Same ITT must be used.
+-		 * Note that login_mtask is preallocated at conn_create().
+-		 */
+-		mtask = conn->login_mtask;
+-	else {
+-	        BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
+-	        BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
+-
+-		if (!__kfifo_get(session->mgmtpool.queue,
+-				 (void*)&mtask, sizeof(void*))) {
+-			spin_unlock_bh(&session->lock);
+-			return -ENOSPC;
+-		}
+-	}
++	struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data;
+ 
+-	/*
+-	 * pre-format CmdSN and ExpStatSN for outgoing PDU.
+-	 */
+-	if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) {
+-		hdr->itt = mtask->itt | (conn->id << CID_SHIFT) |
+-			   (session->age << AGE_SHIFT);
+-		nop->cmdsn = cpu_to_be32(session->cmdsn);
+-		if (conn->c_stage == ISCSI_CONN_STARTED &&
+-		    !(hdr->opcode & ISCSI_OP_IMMEDIATE))
+-			session->cmdsn++;
+-	} else
+-		/* do not advance CmdSN */
+-		nop->cmdsn = cpu_to_be32(session->cmdsn);
+-
+-	nop->exp_statsn = cpu_to_be32(conn->exp_statsn);
+-
+-	memcpy(&mtask->hdr, hdr, sizeof(struct iscsi_hdr));
+-
+-	iscsi_buf_init_virt(&mtask->headbuf, (char*)&mtask->hdr,
++	iscsi_buf_init_virt(&tcp_mtask->headbuf, (char*)mtask->hdr,
+ 				    sizeof(struct iscsi_hdr));
++	tcp_mtask->xmstate = XMSTATE_IMM_HDR;
+ 
+-	spin_unlock_bh(&session->lock);
+-
+-	if (data_size) {
+-		memcpy(mtask->data, data, data_size);
+-		mtask->data_count = data_size;
+-	} else
+-		mtask->data_count = 0;
+-
+-	mtask->xmstate = XMSTATE_IMM_HDR;
+-
+-	if (mtask->data_count) {
+-		iscsi_buf_init_iov(&mtask->sendbuf, (char*)mtask->data,
++	if (mtask->data_count)
++		iscsi_buf_init_iov(&tcp_mtask->sendbuf, (char*)mtask->data,
+ 				    mtask->data_count);
+-	}
+-
+-	debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n",
+-		   hdr->opcode, hdr->itt, data_size);
+-
+-	/*
+-	 * since send_pdu() could be called at least from two contexts,
+-	 * we need to serialize __kfifo_put, so we don't have to take
+-	 * additional lock on fast data-path
+-	 */
+-        if (hdr->opcode & ISCSI_OP_IMMEDIATE)
+-	        __kfifo_put(conn->immqueue, (void*)&mtask, sizeof(void*));
+-	else
+-	        __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*));
+-
+-	scsi_queue_work(session->host, &conn->xmitwork);
+-	return 0;
+-}
+-
+-static int
+-iscsi_eh_host_reset(struct scsi_cmnd *sc)
+-{
+-	struct Scsi_Host *host = sc->device->host;
+-	struct iscsi_session *session = iscsi_hostdata(host->hostdata);
+-	struct iscsi_conn *conn = session->leadconn;
+-	int fail_session = 0;
+-
+-	spin_lock_bh(&session->lock);
+-	if (session->state == ISCSI_STATE_TERMINATE) {
+-failed:
+-		debug_scsi("failing host reset: session terminated "
+-			   "[CID %d age %d]", conn->id, session->age);
+-		spin_unlock_bh(&session->lock);
+-		return FAILED;
+-	}
+-
+-	if (sc->SCp.phase == session->age) {
+-		debug_scsi("failing connection CID %d due to SCSI host reset",
+-			   conn->id);
+-		fail_session = 1;
+-	}
+-	spin_unlock_bh(&session->lock);
+-
+-	/*
+-	 * we drop the lock here but the leadconn cannot be destoyed while
+-	 * we are in the scsi eh
+-	 */
+-	if (fail_session) {
+-		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+-		/*
+-		 * if userspace cannot respond then we must kick this off
+-		 * here for it
+-		 */
+-		iscsi_start_session_recovery(session, conn, STOP_CONN_RECOVER);
+-	}
+-
+-	debug_scsi("iscsi_eh_host_reset wait for relogin\n");
+-	wait_event_interruptible(conn->ehwait,
+-				 session->state == ISCSI_STATE_TERMINATE ||
+-				 session->state == ISCSI_STATE_LOGGED_IN ||
+-				 session->recovery_failed);
+-	if (signal_pending(current))
+-		flush_signals(current);
+-
+-	spin_lock_bh(&session->lock);
+-	if (session->state == ISCSI_STATE_LOGGED_IN)
+-		printk(KERN_INFO "host reset succeeded\n");
+-	else
+-		goto failed;
+-	spin_unlock_bh(&session->lock);
+-
+-	return SUCCESS;
+-}
+-
+-static void
+-iscsi_tmabort_timedout(unsigned long data)
+-{
+-	struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)data;
+-	struct iscsi_conn *conn = ctask->conn;
+-	struct iscsi_session *session = conn->session;
+-
+-	spin_lock(&session->lock);
+-	if (conn->tmabort_state == TMABORT_INITIAL) {
+-		conn->tmabort_state = TMABORT_TIMEDOUT;
+-		debug_scsi("tmabort timedout [sc %lx itt 0x%x]\n",
+-			(long)ctask->sc, ctask->itt);
+-		/* unblock eh_abort() */
+-		wake_up(&conn->ehwait);
+-	}
+-	spin_unlock(&session->lock);
+-}
+-
+-/* must be called with the mutex lock */
+-static int
+-iscsi_exec_abort_task(struct scsi_cmnd *sc, struct iscsi_cmd_task *ctask)
+-{
+-	struct iscsi_conn *conn = ctask->conn;
+-	struct iscsi_session *session = conn->session;
+-	struct iscsi_tm *hdr = &conn->tmhdr;
+-	int rc;
+-
+-	/*
+-	 * ctask timed out but session is OK requests must be serialized.
+-	 */
+-	memset(hdr, 0, sizeof(struct iscsi_tm));
+-	hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE;
+-	hdr->flags = ISCSI_TM_FUNC_ABORT_TASK;
+-	hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+-	memcpy(hdr->lun, ctask->hdr.lun, sizeof(hdr->lun));
+-	hdr->rtt = ctask->hdr.itt;
+-	hdr->refcmdsn = ctask->hdr.cmdsn;
+-
+-	rc = iscsi_conn_send_generic(conn, (struct iscsi_hdr *)hdr,
+-				     NULL, 0);
+-	if (rc) {
+-		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+-		debug_scsi("abort sent failure [itt 0x%x] %d", ctask->itt, rc);
+-		return rc;
+-	}
+-
+-	debug_scsi("abort sent [itt 0x%x]\n", ctask->itt);
+-
+-	spin_lock_bh(&session->lock);
+-	ctask->mtask = (struct iscsi_mgmt_task *)
+-			session->mgmt_cmds[(hdr->itt & ITT_MASK) -
+-					ISCSI_MGMT_ITT_OFFSET];
+-
+-	if (conn->tmabort_state == TMABORT_INITIAL) {
+-		conn->tmfcmd_pdus_cnt++;
+-		conn->tmabort_timer.expires = 10*HZ + jiffies;
+-		conn->tmabort_timer.function = iscsi_tmabort_timedout;
+-		conn->tmabort_timer.data = (unsigned long)ctask;
+-		add_timer(&conn->tmabort_timer);
+-		debug_scsi("abort set timeout [itt 0x%x]", ctask->itt);
+-	}
+-	spin_unlock_bh(&session->lock);
+-	mutex_unlock(&conn->xmitmutex);
+-
+-	/*
+-	 * block eh thread until:
+-	 *
+-	 * 1) abort response
+-	 * 2) abort timeout
+-	 * 3) session is terminated or restarted or userspace has
+-	 * given up on recovery
+-	 */
+-	wait_event_interruptible(conn->ehwait,
+-				 sc->SCp.phase != session->age ||
+-				 session->state != ISCSI_STATE_LOGGED_IN ||
+-				 conn->tmabort_state != TMABORT_INITIAL ||
+-				 session->recovery_failed);
+-	if (signal_pending(current))
+-		flush_signals(current);
+-	del_timer_sync(&conn->tmabort_timer);
+-
+-	mutex_lock(&conn->xmitmutex);
+-	return 0;
+-}
+-
+-static int
+-iscsi_eh_abort(struct scsi_cmnd *sc)
+-{
+-	struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr;
+-	struct iscsi_cmd_task *tmp_ctask;
+-	struct iscsi_conn *conn = ctask->conn;
+-	struct iscsi_session *session = conn->session;
+-	int rc;
+-
+-	conn->eh_abort_cnt++;
+-	debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt);
+-
+-	mutex_lock(&conn->xmitmutex);
+-	spin_lock_bh(&session->lock);
+-
+-	/*
+-	 * If we are not logged in or we have started a new session
+-	 * then let the host reset code handle this
+-	 */
+-	if (session->state != ISCSI_STATE_LOGGED_IN ||
+-	    sc->SCp.phase != session->age)
+-		goto failed;
+-
+-	/* ctask completed before time out */
+-	if (!ctask->sc)
+-		goto success;
+-
+-	/* what should we do here ? */
+-	if (conn->ctask == ctask) {
+-		printk(KERN_INFO "sc %p itt 0x%x partially sent. Failing "
+-		       "abort\n", sc, ctask->itt);
+-		goto failed;
+-	}
+-
+-	/* check for the easy pending cmd abort */
+-	while (__kfifo_get(conn->xmitqueue, (void*)&tmp_ctask, sizeof(void*))) {
+-		if (tmp_ctask->itt == ctask->itt) {
+-			debug_scsi("found pending task\n");
+-			goto success;
+-		}
+-		__kfifo_put(conn->xmitqueue, (void*)&tmp_ctask, sizeof(void*));
+-	}
+-
+-	conn->tmabort_state = TMABORT_INITIAL;
+-
+-	spin_unlock_bh(&session->lock);
+-	rc = iscsi_exec_abort_task(sc, ctask);
+-	spin_lock_bh(&session->lock);
+-
+-	iscsi_ctask_mtask_cleanup(ctask);
+-	if (rc || sc->SCp.phase != session->age ||
+-	    session->state != ISCSI_STATE_LOGGED_IN)
+-		goto failed;
+-
+-	/* ctask completed before tmf abort response */
+-	if (!ctask->sc) {
+-		debug_scsi("sc completed while abort in progress\n");
+-		goto success;
+-	}
+-
+-	if (conn->tmabort_state != TMABORT_SUCCESS) {
+-		spin_unlock_bh(&session->lock);
+-		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+-		spin_lock_bh(&session->lock);
+-		goto failed;
+-	}
+-
+-success:
+-	debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
+-	spin_unlock_bh(&session->lock);
+-
+-	/* clean up task if aborted */
+-	if (conn->sock) {
+-		struct sock *sk = conn->sock->sk;
+-
+-		write_lock_bh(&sk->sk_callback_lock);
+-		spin_lock(&session->lock);
+-		fail_command(conn, ctask, DRIVER_TIMEOUT << 24);
+-		spin_unlock(&session->lock);
+-		write_unlock_bh(&sk->sk_callback_lock);
+-	}
+-	mutex_unlock(&conn->xmitmutex);
+-	return SUCCESS;
+-
+-failed:
+-	spin_unlock_bh(&session->lock);
+-	mutex_unlock(&conn->xmitmutex);
+-
+-	debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
+-	return FAILED;
+ }
+ 
+ static int
+@@ -3314,6 +2096,7 @@ iscsi_r2tpool_alloc(struct iscsi_session *session)
+ 	 */
+ 	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
+ 	        struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
++		struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 
+ 		/*
+ 		 * pre-allocated x4 as much r2ts to handle race when
+@@ -3322,16 +2105,18 @@ iscsi_r2tpool_alloc(struct iscsi_session *session)
+ 		 */
+ 
+ 		/* R2T pool */
+-		if (iscsi_pool_init(&ctask->r2tpool, session->max_r2t * 4,
+-			(void***)&ctask->r2ts, sizeof(struct iscsi_r2t_info))) {
++		if (iscsi_pool_init(&tcp_ctask->r2tpool, session->max_r2t * 4,
++				    (void***)&tcp_ctask->r2ts,
++				    sizeof(struct iscsi_r2t_info))) {
+ 			goto r2t_alloc_fail;
+ 		}
+ 
+ 		/* R2T xmit queue */
+-		ctask->r2tqueue = kfifo_alloc(
++		tcp_ctask->r2tqueue = kfifo_alloc(
+ 		      session->max_r2t * 4 * sizeof(void*), GFP_KERNEL, NULL);
+-		if (ctask->r2tqueue == ERR_PTR(-ENOMEM)) {
+-			iscsi_pool_free(&ctask->r2tpool, (void**)ctask->r2ts);
++		if (tcp_ctask->r2tqueue == ERR_PTR(-ENOMEM)) {
++			iscsi_pool_free(&tcp_ctask->r2tpool,
++					(void**)tcp_ctask->r2ts);
+ 			goto r2t_alloc_fail;
+ 		}
+ 
+@@ -3340,24 +2125,28 @@ iscsi_r2tpool_alloc(struct iscsi_session *session)
+ 		 * Data-Out PDU's within R2T-sequence can be quite big;
+ 		 * using mempool
+ 		 */
+-		ctask->datapool = mempool_create_slab_pool(ISCSI_DTASK_DEFAULT_MAX,
+-							   taskcache);
+-		if (ctask->datapool == NULL) {
+-			kfifo_free(ctask->r2tqueue);
+-			iscsi_pool_free(&ctask->r2tpool, (void**)ctask->r2ts);
++		tcp_ctask->datapool = mempool_create_slab_pool(ISCSI_DTASK_DEFAULT_MAX,
++							       taskcache);
++		if (tcp_ctask->datapool == NULL) {
++			kfifo_free(tcp_ctask->r2tqueue);
++			iscsi_pool_free(&tcp_ctask->r2tpool,
++					(void**)tcp_ctask->r2ts);
+ 			goto r2t_alloc_fail;
+ 		}
+-		INIT_LIST_HEAD(&ctask->dataqueue);
++		INIT_LIST_HEAD(&tcp_ctask->dataqueue);
+ 	}
+ 
+ 	return 0;
+ 
+ r2t_alloc_fail:
+ 	for (i = 0; i < cmd_i; i++) {
+-		mempool_destroy(session->cmds[i]->datapool);
+-		kfifo_free(session->cmds[i]->r2tqueue);
+-		iscsi_pool_free(&session->cmds[i]->r2tpool,
+-				(void**)session->cmds[i]->r2ts);
++		struct iscsi_cmd_task *ctask = session->cmds[i];
++		struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++
++		mempool_destroy(tcp_ctask->datapool);
++		kfifo_free(tcp_ctask->r2tqueue);
++		iscsi_pool_free(&tcp_ctask->r2tpool,
++				(void**)tcp_ctask->r2ts);
+ 	}
+ 	return -ENOMEM;
+ }
+@@ -3368,128 +2157,14 @@ iscsi_r2tpool_free(struct iscsi_session *session)
+ 	int i;
+ 
+ 	for (i = 0; i < session->cmds_max; i++) {
+-		mempool_destroy(session->cmds[i]->datapool);
+-		kfifo_free(session->cmds[i]->r2tqueue);
+-		iscsi_pool_free(&session->cmds[i]->r2tpool,
+-				(void**)session->cmds[i]->r2ts);
+-	}
+-}
++		struct iscsi_cmd_task *ctask = session->cmds[i];
++		struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 
+-static struct scsi_host_template iscsi_sht = {
+-	.name			= "iSCSI Initiator over TCP/IP, v."
+-				  ISCSI_VERSION_STR,
+-	.queuecommand           = iscsi_queuecommand,
+-	.change_queue_depth	= iscsi_change_queue_depth,
+-	.can_queue		= ISCSI_XMIT_CMDS_MAX - 1,
+-	.sg_tablesize		= ISCSI_SG_TABLESIZE,
+-	.cmd_per_lun		= ISCSI_DEF_CMD_PER_LUN,
+-	.eh_abort_handler       = iscsi_eh_abort,
+-	.eh_host_reset_handler	= iscsi_eh_host_reset,
+-	.use_clustering         = DISABLE_CLUSTERING,
+-	.proc_name		= "iscsi_tcp",
+-	.this_id		= -1,
+-};
+-
+-static struct iscsi_transport iscsi_tcp_transport;
+-
+-static struct iscsi_cls_session *
+-iscsi_session_create(struct scsi_transport_template *scsit,
+-		     uint32_t initial_cmdsn, uint32_t *hostno)
+-{
+-	struct Scsi_Host *shost;
+-	struct iscsi_session *session;
+-	int cmd_i;
+-
+-	shost = iscsi_transport_create_session(scsit, &iscsi_tcp_transport);
+-	if (!shost)
+-		return NULL; 
+-
+-	session = iscsi_hostdata(shost->hostdata);
+-	memset(session, 0, sizeof(struct iscsi_session));
+-	session->host = shost;
+-	session->state = ISCSI_STATE_FREE;
+-	session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
+-	session->cmds_max = ISCSI_XMIT_CMDS_MAX;
+-	session->cmdsn = initial_cmdsn;
+-	session->exp_cmdsn = initial_cmdsn + 1;
+-	session->max_cmdsn = initial_cmdsn + 1;
+-	session->max_r2t = 1;
+-
+-	*hostno = shost->host_no;
+-
+-	/* initialize SCSI PDU commands pool */
+-	if (iscsi_pool_init(&session->cmdpool, session->cmds_max,
+-		(void***)&session->cmds, sizeof(struct iscsi_cmd_task)))
+-		goto cmdpool_alloc_fail;
+-
+-	/* pre-format cmds pool with ITT */
+-	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++)
+-		session->cmds[cmd_i]->itt = cmd_i;
+-
+-	spin_lock_init(&session->lock);
+-	INIT_LIST_HEAD(&session->connections);
+-
+-	/* initialize immediate command pool */
+-	if (iscsi_pool_init(&session->mgmtpool, session->mgmtpool_max,
+-		(void***)&session->mgmt_cmds, sizeof(struct iscsi_mgmt_task)))
+-		goto mgmtpool_alloc_fail;
+-
+-
+-	/* pre-format immediate cmds pool with ITT */
+-	for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) {
+-		session->mgmt_cmds[cmd_i]->itt = ISCSI_MGMT_ITT_OFFSET + cmd_i;
+-		session->mgmt_cmds[cmd_i]->data = kmalloc(
+-			DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, GFP_KERNEL);
+-		if (!session->mgmt_cmds[cmd_i]->data) {
+-			int j;
+-
+-			for (j = 0; j < cmd_i; j++)
+-				kfree(session->mgmt_cmds[j]->data);
+-			goto immdata_alloc_fail;
+-		}
++		mempool_destroy(tcp_ctask->datapool);
++		kfifo_free(tcp_ctask->r2tqueue);
++		iscsi_pool_free(&tcp_ctask->r2tpool,
++				(void**)tcp_ctask->r2ts);
+ 	}
+-
+-	if (iscsi_r2tpool_alloc(session))
+-		goto r2tpool_alloc_fail;
+-
+-	return hostdata_session(shost->hostdata);
+-
+-r2tpool_alloc_fail:
+-	for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++)
+-		kfree(session->mgmt_cmds[cmd_i]->data);
+-immdata_alloc_fail:
+-	iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
+-mgmtpool_alloc_fail:
+-	iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
+-cmdpool_alloc_fail:
+-	iscsi_transport_destroy_session(shost);
+-	return NULL;
+-}
+-
+-static void
+-iscsi_session_destroy(struct iscsi_cls_session *cls_session)
+-{
+-	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+-	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+-	int cmd_i;
+-	struct iscsi_data_task *dtask, *n;
+-
+-	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
+-		struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
+-		list_for_each_entry_safe(dtask, n, &ctask->dataqueue, item) {
+-			list_del(&dtask->item);
+-			mempool_free(dtask, ctask->datapool);
+-		}
+-	}
+-
+-	for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++)
+-		kfree(session->mgmt_cmds[cmd_i]->data);
+-
+-	iscsi_r2tpool_free(session);
+-	iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
+-	iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
+-
+-	iscsi_transport_destroy_session(shost);
+ }
+ 
+ static int
+@@ -3498,13 +2173,14 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
+ {
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	struct iscsi_session *session = conn->session;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 
+ 	switch(param) {
+ 	case ISCSI_PARAM_MAX_RECV_DLENGTH: {
+-		char *saveptr = conn->data;
++		char *saveptr = tcp_conn->data;
+ 		gfp_t flags = GFP_KERNEL;
+ 
+-		if (conn->data_size >= value) {
++		if (tcp_conn->data_size >= value) {
+ 			conn->max_recv_dlength = value;
+ 			break;
+ 		}
+@@ -3515,21 +2191,21 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
+ 		spin_unlock_bh(&session->lock);
+ 
+ 		if (value <= PAGE_SIZE)
+-			conn->data = kmalloc(value, flags);
++			tcp_conn->data = kmalloc(value, flags);
+ 		else
+-			conn->data = (void*)__get_free_pages(flags,
++			tcp_conn->data = (void*)__get_free_pages(flags,
+ 							     get_order(value));
+-		if (conn->data == NULL) {
+-			conn->data = saveptr;
++		if (tcp_conn->data == NULL) {
++			tcp_conn->data = saveptr;
+ 			return -ENOMEM;
+ 		}
+-		if (conn->data_size <= PAGE_SIZE)
++		if (tcp_conn->data_size <= PAGE_SIZE)
+ 			kfree(saveptr);
+ 		else
+ 			free_pages((unsigned long)saveptr,
+-				   get_order(conn->data_size));
++				   get_order(tcp_conn->data_size));
+ 		conn->max_recv_dlength = value;
+-		conn->data_size = value;
++		tcp_conn->data_size = value;
+ 		}
+ 		break;
+ 	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+@@ -3537,49 +2213,51 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
+ 		break;
+ 	case ISCSI_PARAM_HDRDGST_EN:
+ 		conn->hdrdgst_en = value;
+-		conn->hdr_size = sizeof(struct iscsi_hdr);
++		tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
+ 		if (conn->hdrdgst_en) {
+-			conn->hdr_size += sizeof(__u32);
+-			if (!conn->tx_tfm)
+-				conn->tx_tfm = crypto_alloc_tfm("crc32c", 0);
+-			if (!conn->tx_tfm)
++			tcp_conn->hdr_size += sizeof(__u32);
++			if (!tcp_conn->tx_tfm)
++				tcp_conn->tx_tfm = crypto_alloc_tfm("crc32c",
++								    0);
++			if (!tcp_conn->tx_tfm)
+ 				return -ENOMEM;
+-			if (!conn->rx_tfm)
+-				conn->rx_tfm = crypto_alloc_tfm("crc32c", 0);
+-			if (!conn->rx_tfm) {
+-				crypto_free_tfm(conn->tx_tfm);
++			if (!tcp_conn->rx_tfm)
++				tcp_conn->rx_tfm = crypto_alloc_tfm("crc32c",
++								    0);
++			if (!tcp_conn->rx_tfm) {
++				crypto_free_tfm(tcp_conn->tx_tfm);
+ 				return -ENOMEM;
+ 			}
+ 		} else {
+-			if (conn->tx_tfm)
+-				crypto_free_tfm(conn->tx_tfm);
+-			if (conn->rx_tfm)
+-				crypto_free_tfm(conn->rx_tfm);
++			if (tcp_conn->tx_tfm)
++				crypto_free_tfm(tcp_conn->tx_tfm);
++			if (tcp_conn->rx_tfm)
++				crypto_free_tfm(tcp_conn->rx_tfm);
+ 		}
+ 		break;
+ 	case ISCSI_PARAM_DATADGST_EN:
+ 		conn->datadgst_en = value;
+ 		if (conn->datadgst_en) {
+-			if (!conn->data_tx_tfm)
+-				conn->data_tx_tfm =
++			if (!tcp_conn->data_tx_tfm)
++				tcp_conn->data_tx_tfm =
+ 				    crypto_alloc_tfm("crc32c", 0);
+-			if (!conn->data_tx_tfm)
++			if (!tcp_conn->data_tx_tfm)
+ 				return -ENOMEM;
+-			if (!conn->data_rx_tfm)
+-				conn->data_rx_tfm =
++			if (!tcp_conn->data_rx_tfm)
++				tcp_conn->data_rx_tfm =
+ 				    crypto_alloc_tfm("crc32c", 0);
+-			if (!conn->data_rx_tfm) {
+-				crypto_free_tfm(conn->data_tx_tfm);
++			if (!tcp_conn->data_rx_tfm) {
++				crypto_free_tfm(tcp_conn->data_tx_tfm);
+ 				return -ENOMEM;
+ 			}
+ 		} else {
+-			if (conn->data_tx_tfm)
+-				crypto_free_tfm(conn->data_tx_tfm);
+-			if (conn->data_rx_tfm)
+-				crypto_free_tfm(conn->data_rx_tfm);
++			if (tcp_conn->data_tx_tfm)
++				crypto_free_tfm(tcp_conn->data_tx_tfm);
++			if (tcp_conn->data_rx_tfm)
++				crypto_free_tfm(tcp_conn->data_rx_tfm);
+ 		}
+-		conn->sendpage = conn->datadgst_en ?
+-			sock_no_sendpage : conn->sock->ops->sendpage;
++		tcp_conn->sendpage = conn->datadgst_en ?
++			sock_no_sendpage : tcp_conn->sock->ops->sendpage;
+ 		break;
+ 	case ISCSI_PARAM_INITIAL_R2T_EN:
+ 		session->initial_r2t_en = value;
+@@ -3677,6 +2355,7 @@ iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ 		     enum iscsi_param param, uint32_t *value)
+ {
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	struct inet_sock *inet;
+ 
+ 	switch(param) {
+@@ -3694,12 +2373,12 @@ iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ 		break;
+ 	case ISCSI_PARAM_CONN_PORT:
+ 		mutex_lock(&conn->xmitmutex);
+-		if (!conn->sock) {
++		if (!tcp_conn->sock) {
+ 			mutex_unlock(&conn->xmitmutex);
+ 			return -EINVAL;
+ 		}
+ 
+-		inet = inet_sk(conn->sock->sk);
++		inet = inet_sk(tcp_conn->sock->sk);
+ 		*value = be16_to_cpu(inet->dport);
+ 		mutex_unlock(&conn->xmitmutex);
+ 	default:
+@@ -3714,6 +2393,7 @@ iscsi_conn_get_str_param(struct iscsi_cls_conn *cls_conn,
+ 			 enum iscsi_param param, char *buf)
+ {
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 	struct sock *sk;
+ 	struct inet_sock *inet;
+ 	struct ipv6_pinfo *np;
+@@ -3722,12 +2402,12 @@ iscsi_conn_get_str_param(struct iscsi_cls_conn *cls_conn,
+ 	switch (param) {
+ 	case ISCSI_PARAM_CONN_ADDRESS:
+ 		mutex_lock(&conn->xmitmutex);
+-		if (!conn->sock) {
++		if (!tcp_conn->sock) {
+ 			mutex_unlock(&conn->xmitmutex);
+ 			return -EINVAL;
+ 		}
+ 
+-		sk = conn->sock->sk;
++		sk = tcp_conn->sock->sk;
+ 		if (sk->sk_family == PF_INET) {
+ 			inet = inet_sk(sk);
+ 			len = sprintf(buf, "%u.%u.%u.%u\n",
+@@ -3751,6 +2431,7 @@ static void
+ iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats)
+ {
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
++	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ 
+ 	stats->txdata_octets = conn->txdata_octets;
+ 	stats->rxdata_octets = conn->rxdata_octets;
+@@ -3763,27 +2444,92 @@ iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats)
+ 	stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
+ 	stats->custom_length = 3;
+ 	strcpy(stats->custom[0].desc, "tx_sendpage_failures");
+-	stats->custom[0].value = conn->sendpage_failures_cnt;
++	stats->custom[0].value = tcp_conn->sendpage_failures_cnt;
+ 	strcpy(stats->custom[1].desc, "rx_discontiguous_hdr");
+-	stats->custom[1].value = conn->discontiguous_hdr_cnt;
++	stats->custom[1].value = tcp_conn->discontiguous_hdr_cnt;
+ 	strcpy(stats->custom[2].desc, "eh_abort_cnt");
+ 	stats->custom[2].value = conn->eh_abort_cnt;
+ }
+ 
+-static int
+-iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
+-		    char *data, uint32_t data_size)
++static struct iscsi_cls_session *
++iscsi_tcp_session_create(struct iscsi_transport *iscsit,
++			 struct scsi_transport_template *scsit,
++			 uint32_t initial_cmdsn, uint32_t *hostno)
+ {
+-	struct iscsi_conn *conn = cls_conn->dd_data;
+-	int rc;
++	struct iscsi_cls_session *cls_session;
++	struct iscsi_session *session;
++	uint32_t hn;
++	int cmd_i;
+ 
+-	mutex_lock(&conn->xmitmutex);
+-	rc = iscsi_conn_send_generic(conn, hdr, data, data_size);
+-	mutex_unlock(&conn->xmitmutex);
++	cls_session = iscsi_session_setup(iscsit, scsit,
++					 sizeof(struct iscsi_tcp_cmd_task),
++					 sizeof(struct iscsi_tcp_mgmt_task),
++					 initial_cmdsn, &hn);
++	if (!cls_session)
++		return NULL;
++	*hostno = hn;
+ 
+-	return rc;
++	session = class_to_transport_session(cls_session);
++	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
++		struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
++		struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++
++		ctask->hdr = &tcp_ctask->hdr;
++	}
++
++	for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) {
++		struct iscsi_mgmt_task *mtask = session->mgmt_cmds[cmd_i];
++		struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data;
++
++		mtask->hdr = &tcp_mtask->hdr;
++	}
++
++	if (iscsi_r2tpool_alloc(class_to_transport_session(cls_session)))
++		goto r2tpool_alloc_fail;
++
++	return cls_session;
++
++r2tpool_alloc_fail:
++	iscsi_session_teardown(cls_session);
++	return NULL;
++}
++
++static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session)
++{
++	struct iscsi_session *session = class_to_transport_session(cls_session);
++	struct iscsi_data_task *dtask, *n;
++	int cmd_i;
++
++	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
++		struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
++		struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++
++		list_for_each_entry_safe(dtask, n, &tcp_ctask->dataqueue,
++					 item) {
++			list_del(&dtask->item);
++			mempool_free(dtask, tcp_ctask->datapool);
++		}
++	}
++
++	iscsi_r2tpool_free(class_to_transport_session(cls_session));
++	iscsi_session_teardown(cls_session);
+ }
+ 
++static struct scsi_host_template iscsi_sht = {
++	.name			= "iSCSI Initiator over TCP/IP, v."
++				  ISCSI_VERSION_STR,
++	.queuecommand           = iscsi_queuecommand,
++	.change_queue_depth	= iscsi_change_queue_depth,
++	.can_queue		= ISCSI_XMIT_CMDS_MAX - 1,
++	.sg_tablesize		= ISCSI_SG_TABLESIZE,
++	.cmd_per_lun		= ISCSI_DEF_CMD_PER_LUN,
++	.eh_abort_handler       = iscsi_eh_abort,
++	.eh_host_reset_handler	= iscsi_eh_host_reset,
++	.use_clustering         = DISABLE_CLUSTERING,
++	.proc_name		= "iscsi_tcp",
++	.this_id		= -1,
++};
++
+ static struct iscsi_transport iscsi_tcp_transport = {
+ 	.owner			= THIS_MODULE,
+ 	.name			= "tcp",
+@@ -3804,23 +2550,34 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 				  ISCSI_CONN_PORT |
+ 				  ISCSI_CONN_ADDRESS,
+ 	.host_template		= &iscsi_sht,
+-	.hostdata_size		= sizeof(struct iscsi_session),
+ 	.conndata_size		= sizeof(struct iscsi_conn),
+ 	.max_conn		= 1,
+ 	.max_cmd_len		= ISCSI_TCP_MAX_CMD_LEN,
+-	.create_session		= iscsi_session_create,
+-	.destroy_session	= iscsi_session_destroy,
+-	.create_conn		= iscsi_conn_create,
+-	.bind_conn		= iscsi_conn_bind,
+-	.destroy_conn		= iscsi_conn_destroy,
++	/* session management */
++	.create_session		= iscsi_tcp_session_create,
++	.destroy_session	= iscsi_tcp_session_destroy,
++	/* connection management */
++	.create_conn		= iscsi_tcp_conn_create,
++	.bind_conn		= iscsi_tcp_conn_bind,
++	.destroy_conn		= iscsi_tcp_conn_destroy,
+ 	.set_param		= iscsi_conn_set_param,
+ 	.get_conn_param		= iscsi_conn_get_param,
+ 	.get_conn_str_param	= iscsi_conn_get_str_param,
+ 	.get_session_param	= iscsi_session_get_param,
+ 	.start_conn		= iscsi_conn_start,
+ 	.stop_conn		= iscsi_conn_stop,
++	/* these are called as part of conn recovery */
++	.suspend_conn_recv	= iscsi_tcp_suspend_conn_rx,
++	.terminate_conn		= iscsi_tcp_terminate_conn,
++	/* IO */
+ 	.send_pdu		= iscsi_conn_send_pdu,
+ 	.get_stats		= iscsi_conn_get_stats,
++	.init_cmd_task		= iscsi_tcp_cmd_init,
++	.init_mgmt_task		= iscsi_tcp_mgmt_init,
++	.xmit_cmd_task		= iscsi_tcp_ctask_xmit,
++	.xmit_mgmt_task		= iscsi_tcp_mtask_xmit,
++	.cleanup_cmd_task	= iscsi_tcp_cleanup_ctask,
++	/* recovery */
+ 	.session_recovery_timedout = iscsi_session_recovery_timedout,
+ };
+ 
+diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
+index 12ef64179b4c..c5918854d595 100644
+--- a/drivers/scsi/iscsi_tcp.h
++++ b/drivers/scsi/iscsi_tcp.h
+@@ -2,7 +2,8 @@
+  * iSCSI Initiator TCP Transport
+  * Copyright (C) 2004 Dmitry Yusupov
+  * Copyright (C) 2004 Alex Aizman
+- * Copyright (C) 2005 Mike Christie
++ * Copyright (C) 2005 - 2006 Mike Christie
++ * Copyright (C) 2006 Red Hat, Inc.  All rights reserved.
+  * maintained by open-iscsi@googlegroups.com
+  *
+  * This program is free software; you can redistribute it and/or modify
+@@ -21,20 +22,7 @@
+ #ifndef ISCSI_TCP_H
+ #define ISCSI_TCP_H
+ 
+-/* Session's states */
+-#define ISCSI_STATE_FREE		1
+-#define ISCSI_STATE_LOGGED_IN		2
+-#define ISCSI_STATE_FAILED		3
+-#define ISCSI_STATE_TERMINATE		4
+-
+-/* Connection's states */
+-#define ISCSI_CONN_INITIAL_STAGE	0
+-#define ISCSI_CONN_STARTED		1
+-#define ISCSI_CONN_STOPPED		2
+-#define ISCSI_CONN_CLEANUP_WAIT		3
+-
+-/* Connection suspend "bit" */
+-#define SUSPEND_BIT			1
++#include 
+ 
+ /* Socket's Receive state machine */
+ #define IN_PROGRESS_WAIT_HEADER		0x0
+@@ -42,12 +30,6 @@
+ #define IN_PROGRESS_DATA_RECV		0x2
+ #define IN_PROGRESS_DDIGEST_RECV	0x3
+ 
+-/* Task Mgmt states */
+-#define	TMABORT_INITIAL			0x0
+-#define	TMABORT_SUCCESS			0x1
+-#define	TMABORT_FAILED			0x2
+-#define	TMABORT_TIMEDOUT		0x3
+-
+ /* xmit state machine */
+ #define	XMSTATE_IDLE			0x0
+ #define	XMSTATE_R_HDR			0x1
+@@ -62,34 +44,14 @@
+ #define	XMSTATE_W_PAD			0x200
+ #define XMSTATE_DATA_DIGEST		0x400
+ 
+-#define ISCSI_CONN_MAX			1
+ #define ISCSI_CONN_RCVBUF_MIN		262144
+ #define ISCSI_CONN_SNDBUF_MIN		262144
+ #define ISCSI_PAD_LEN			4
+ #define ISCSI_R2T_MAX			16
+-#define ISCSI_XMIT_CMDS_MAX		128	/* must be power of 2 */
+-#define ISCSI_MGMT_CMDS_MAX		32	/* must be power of 2 */
+-#define ISCSI_MGMT_ITT_OFFSET		0xa00
+ #define ISCSI_SG_TABLESIZE		SG_ALL
+-#define ISCSI_DEF_CMD_PER_LUN		32
+-#define ISCSI_MAX_CMD_PER_LUN		128
+ #define ISCSI_TCP_MAX_CMD_LEN		16
+ 
+-#define ITT_MASK			(0xfff)
+-#define CID_SHIFT			12
+-#define CID_MASK			(0xffff<
commit 7996a778ff8c717cb1a7a294475c59cc8f1e9fb8
+Author: Mike Christie 
+Date:   Thu Apr 6 21:13:41 2006 -0500
+
+    [SCSI] iscsi: add libiscsi
+    
+    There is a lot of code duplcited between iscsi_tcp
+    and the upcoming iscsi_iser driver. This patch puts
+    the duplicated code in a lib. There is more code
+    to move around but this takes care of the
+    basics. For iscsi_offload if they use the lib we will
+    probably move some things around. For example in the
+    queuecommand we will not assume that the LLD wants
+    to do queue_work, but it is better to handle that
+    later when we know for sure what iscsi_offload looks
+    like (we could probably do this for iscsi_iser though to).
+    
+    Ideally I would like to get the iscsi_transports modules
+    to a place where all they really have to do is put data
+    on the wire, but how to do that will hopefully be more clear
+    when we see other modules like iscsi_offload. Or maybe
+    iscsi_offload will not use the lib and it will just be
+    iscsi_iser and iscsi_tcp and maybe the iscsi_tcp_tgt if that
+    is allowed in mainline.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
+index e513c3158ad9..efdff61c5808 100644
+--- a/drivers/scsi/Makefile
++++ b/drivers/scsi/Makefile
+@@ -33,7 +33,7 @@ obj-$(CONFIG_SCSI_FC_ATTRS) 	+= scsi_transport_fc.o
+ obj-$(CONFIG_SCSI_ISCSI_ATTRS)	+= scsi_transport_iscsi.o
+ obj-$(CONFIG_SCSI_SAS_ATTRS)	+= scsi_transport_sas.o
+ 
+-obj-$(CONFIG_ISCSI_TCP) 	+= iscsi_tcp.o
++obj-$(CONFIG_ISCSI_TCP) 	+= libiscsi.o	iscsi_tcp.o
+ obj-$(CONFIG_SCSI_AMIGA7XX)	+= amiga7xx.o	53c7xx.o
+ obj-$(CONFIG_A3000_SCSI)	+= a3000.o	wd33c93.o
+ obj-$(CONFIG_A2091_SCSI)	+= a2091.o	wd33c93.o
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+new file mode 100644
+index 000000000000..274a1374ab64
+--- /dev/null
++++ b/drivers/scsi/libiscsi.c
+@@ -0,0 +1,1697 @@
++/*
++ * iSCSI lib functions
++ *
++ * Copyright (C) 2006 Red Hat, Inc.  All rights reserved.
++ * Copyright (C) 2004 - 2006 Mike Christie
++ * Copyright (C) 2004 - 2005 Dmitry Yusupov
++ * Copyright (C) 2004 - 2005 Alex Aizman
++ * maintained by open-iscsi@googlegroups.com
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++struct iscsi_session *
++class_to_transport_session(struct iscsi_cls_session *cls_session)
++{
++	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
++	return iscsi_hostdata(shost->hostdata);
++}
++EXPORT_SYMBOL_GPL(class_to_transport_session);
++
++#define INVALID_SN_DELTA	0xffff
++
++int
++iscsi_check_assign_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
++{
++	uint32_t max_cmdsn = be32_to_cpu(hdr->max_cmdsn);
++	uint32_t exp_cmdsn = be32_to_cpu(hdr->exp_cmdsn);
++
++	if (max_cmdsn < exp_cmdsn -1 &&
++	    max_cmdsn > exp_cmdsn - INVALID_SN_DELTA)
++		return ISCSI_ERR_MAX_CMDSN;
++	if (max_cmdsn > session->max_cmdsn ||
++	    max_cmdsn < session->max_cmdsn - INVALID_SN_DELTA)
++		session->max_cmdsn = max_cmdsn;
++	if (exp_cmdsn > session->exp_cmdsn ||
++	    exp_cmdsn < session->exp_cmdsn - INVALID_SN_DELTA)
++		session->exp_cmdsn = exp_cmdsn;
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(iscsi_check_assign_cmdsn);
++
++void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *ctask,
++				   struct iscsi_data *hdr,
++				   int transport_data_cnt)
++{
++	struct iscsi_conn *conn = ctask->conn;
++
++	memset(hdr, 0, sizeof(struct iscsi_data));
++	hdr->ttt = cpu_to_be32(ISCSI_RESERVED_TAG);
++	hdr->datasn = cpu_to_be32(ctask->unsol_datasn);
++	ctask->unsol_datasn++;
++	hdr->opcode = ISCSI_OP_SCSI_DATA_OUT;
++	memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun));
++
++	hdr->itt = ctask->hdr->itt;
++	hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
++
++	hdr->offset = cpu_to_be32(ctask->total_length -
++				  transport_data_cnt -
++				  ctask->unsol_count);
++
++	if (ctask->unsol_count > conn->max_xmit_dlength) {
++		hton24(hdr->dlength, conn->max_xmit_dlength);
++		ctask->data_count = conn->max_xmit_dlength;
++		hdr->flags = 0;
++	} else {
++		hton24(hdr->dlength, ctask->unsol_count);
++		ctask->data_count = ctask->unsol_count;
++		hdr->flags = ISCSI_FLAG_CMD_FINAL;
++	}
++}
++EXPORT_SYMBOL_GPL(iscsi_prep_unsolicit_data_pdu);
++
++/**
++ * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu
++ * @ctask: iscsi cmd task
++ *
++ * Prep basic iSCSI PDU fields for a scsi cmd pdu. The LLD should set
++ * fields like dlength or final based on how much data it sends
++ */
++static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
++{
++	struct iscsi_conn *conn = ctask->conn;
++	struct iscsi_session *session = conn->session;
++	struct iscsi_cmd *hdr = ctask->hdr;
++	struct scsi_cmnd *sc = ctask->sc;
++
++        hdr->opcode = ISCSI_OP_SCSI_CMD;
++        hdr->flags = ISCSI_ATTR_SIMPLE;
++        int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
++        hdr->itt = ctask->itt | (conn->id << ISCSI_CID_SHIFT) |
++                         (session->age << ISCSI_AGE_SHIFT);
++        hdr->data_length = cpu_to_be32(sc->request_bufflen);
++        hdr->cmdsn = cpu_to_be32(session->cmdsn);
++        session->cmdsn++;
++        hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
++        memcpy(hdr->cdb, sc->cmnd, sc->cmd_len);
++        memset(&hdr->cdb[sc->cmd_len], 0, MAX_COMMAND_SIZE - sc->cmd_len);
++
++	if (sc->sc_data_direction == DMA_TO_DEVICE) {
++		hdr->flags |= ISCSI_FLAG_CMD_WRITE;
++		/*
++		 * Write counters:
++		 *
++		 *	imm_count	bytes to be sent right after
++		 *			SCSI PDU Header
++		 *
++		 *	unsol_count	bytes(as Data-Out) to be sent
++		 *			without	R2T ack right after
++		 *			immediate data
++		 *
++		 *	r2t_data_count	bytes to be sent via R2T ack's
++		 *
++		 *      pad_count       bytes to be sent as zero-padding
++		 */
++		ctask->imm_count = 0;
++		ctask->unsol_count = 0;
++		ctask->unsol_datasn = 0;
++
++		if (session->imm_data_en) {
++			if (ctask->total_length >= session->first_burst)
++				ctask->imm_count = min(session->first_burst,
++							conn->max_xmit_dlength);
++			else
++				ctask->imm_count = min(ctask->total_length,
++							conn->max_xmit_dlength);
++			hton24(ctask->hdr->dlength, ctask->imm_count);
++		} else
++			zero_data(ctask->hdr->dlength);
++
++		if (!session->initial_r2t_en)
++			ctask->unsol_count = min(session->first_burst,
++				ctask->total_length) - ctask->imm_count;
++		if (!ctask->unsol_count)
++			/* No unsolicit Data-Out's */
++			ctask->hdr->flags |= ISCSI_FLAG_CMD_FINAL;
++	} else {
++		ctask->datasn = 0;
++		hdr->flags |= ISCSI_FLAG_CMD_FINAL;
++		zero_data(hdr->dlength);
++
++		if (sc->sc_data_direction == DMA_FROM_DEVICE)
++			hdr->flags |= ISCSI_FLAG_CMD_READ;
++	}
++
++	conn->scsicmd_pdus_cnt++;
++}
++EXPORT_SYMBOL_GPL(iscsi_prep_scsi_cmd_pdu);
++
++/**
++ * iscsi_complete_command - return command back to scsi-ml
++ * @session: iscsi session
++ * @ctask: iscsi cmd task
++ *
++ * Must be called with session lock.
++ * This function returns the scsi command to scsi-ml and returns
++ * the cmd task to the pool of available cmd tasks.
++ */
++static void iscsi_complete_command(struct iscsi_session *session,
++				   struct iscsi_cmd_task *ctask)
++{
++	struct scsi_cmnd *sc = ctask->sc;
++
++	ctask->sc = NULL;
++	list_del_init(&ctask->running);
++	__kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*));
++	sc->scsi_done(sc);
++}
++
++/**
++ * iscsi_cmd_rsp - SCSI Command Response processing
++ * @conn: iscsi connection
++ * @hdr: iscsi header
++ * @ctask: scsi command task
++ * @data: cmd data buffer
++ * @datalen: len of buffer
++ *
++ * iscsi_cmd_rsp sets up the scsi_cmnd fields based on the PDU and
++ * then completes the command and task.
++ **/
++static int iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
++			      struct iscsi_cmd_task *ctask, char *data,
++			      int datalen)
++{
++	int rc;
++	struct iscsi_cmd_rsp *rhdr = (struct iscsi_cmd_rsp *)hdr;
++	struct iscsi_session *session = conn->session;
++	struct scsi_cmnd *sc = ctask->sc;
++
++	rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr);
++	if (rc) {
++		sc->result = DID_ERROR << 16;
++		goto out;
++	}
++
++	conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
++
++	sc->result = (DID_OK << 16) | rhdr->cmd_status;
++
++	if (rhdr->response != ISCSI_STATUS_CMD_COMPLETED) {
++		sc->result = DID_ERROR << 16;
++		goto out;
++	}
++
++	if (rhdr->cmd_status == SAM_STAT_CHECK_CONDITION) {
++		int senselen;
++
++		if (datalen < 2) {
++invalid_datalen:
++			printk(KERN_ERR "Got CHECK_CONDITION but invalid "
++			       "data buffer size of %d\n", datalen);
++			sc->result = DID_BAD_TARGET << 16;
++			goto out;
++		}
++
++		senselen = (data[0] << 8) | data[1];
++		if (datalen < senselen)
++			goto invalid_datalen;
++
++		memcpy(sc->sense_buffer, data + 2,
++		       min(senselen, SCSI_SENSE_BUFFERSIZE));
++		debug_scsi("copied %d bytes of sense\n",
++			   min(senselen, SCSI_SENSE_BUFFERSIZE));
++	}
++
++	if (sc->sc_data_direction == DMA_TO_DEVICE)
++		goto out;
++
++	if (rhdr->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
++		int res_count = be32_to_cpu(rhdr->residual_count);
++
++		if (res_count > 0 && res_count <= sc->request_bufflen)
++			sc->resid = res_count;
++		else
++			sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
++	} else if (rhdr->flags & ISCSI_FLAG_CMD_BIDI_UNDERFLOW)
++		sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
++	else if (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW)
++		sc->resid = be32_to_cpu(rhdr->residual_count);
++
++out:
++	debug_scsi("done [sc %lx res %d itt 0x%x]\n",
++		   (long)sc, sc->result, ctask->itt);
++	conn->scsirsp_pdus_cnt++;
++
++	iscsi_complete_command(conn->session, ctask);
++	return rc;
++}
++
++/**
++ * __iscsi_complete_pdu - complete pdu
++ * @conn: iscsi conn
++ * @hdr: iscsi header
++ * @data: data buffer
++ * @datalen: len of data buffer
++ *
++ * Completes pdu processing by freeing any resources allocated at
++ * queuecommand or send generic. session lock must be held and verify
++ * itt must have been called.
++ */
++int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
++			 char *data, int datalen)
++{
++	struct iscsi_session *session = conn->session;
++	int opcode = hdr->opcode & ISCSI_OPCODE_MASK, rc = 0;
++	struct iscsi_cmd_task *ctask;
++	struct iscsi_mgmt_task *mtask;
++	uint32_t itt;
++
++	if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG))
++		itt = hdr->itt & ISCSI_ITT_MASK;
++	else
++		itt = hdr->itt;
++
++	if (itt < session->cmds_max) {
++		ctask = session->cmds[itt];
++
++		debug_scsi("cmdrsp [op 0x%x cid %d itt 0x%x len %d]\n",
++			   opcode, conn->id, ctask->itt, datalen);
++
++		switch(opcode) {
++		case ISCSI_OP_SCSI_CMD_RSP:
++			BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
++			rc = iscsi_scsi_cmd_rsp(conn, hdr, ctask, data,
++						datalen);
++			break;
++		case ISCSI_OP_SCSI_DATA_IN:
++			BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
++			if (hdr->flags & ISCSI_FLAG_DATA_STATUS) {
++				conn->scsirsp_pdus_cnt++;
++				iscsi_complete_command(session, ctask);
++			}
++			break;
++		case ISCSI_OP_R2T:
++			/* LLD handles this for now */
++			break;
++		default:
++			rc = ISCSI_ERR_BAD_OPCODE;
++			break;
++		}
++	} else if (itt >= ISCSI_MGMT_ITT_OFFSET &&
++		   itt < ISCSI_MGMT_ITT_OFFSET + session->mgmtpool_max) {
++		mtask = session->mgmt_cmds[itt - ISCSI_MGMT_ITT_OFFSET];
++
++		debug_scsi("immrsp [op 0x%x cid %d itt 0x%x len %d]\n",
++			   opcode, conn->id, mtask->itt, datalen);
++
++		switch(opcode) {
++		case ISCSI_OP_LOGIN_RSP:
++		case ISCSI_OP_TEXT_RSP:
++		case ISCSI_OP_LOGOUT_RSP:
++			rc = iscsi_check_assign_cmdsn(session,
++						 (struct iscsi_nopin*)hdr);
++			if (rc)
++				break;
++
++			rc = iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen);
++			list_del(&mtask->running);
++			if (conn->login_mtask != mtask)
++				__kfifo_put(session->mgmtpool.queue,
++					    (void*)&mtask, sizeof(void*));
++			break;
++		case ISCSI_OP_SCSI_TMFUNC_RSP:
++			rc = iscsi_check_assign_cmdsn(session,
++						 (struct iscsi_nopin*)hdr);
++			if (rc)
++				break;
++
++			if (datalen) {
++				rc = ISCSI_ERR_PROTO;
++				break;
++			}
++			conn->tmfrsp_pdus_cnt++;
++			if (conn->tmabort_state == TMABORT_INITIAL) {
++				conn->tmabort_state =
++					((struct iscsi_tm_rsp *)hdr)->
++					response == ISCSI_TMF_RSP_COMPLETE ?
++						TMABORT_SUCCESS:TMABORT_FAILED;
++				/* unblock eh_abort() */
++				wake_up(&conn->ehwait);
++			}
++			break;
++		case ISCSI_OP_NOOP_IN:
++			if (hdr->ttt != ISCSI_RESERVED_TAG) {
++				rc = ISCSI_ERR_PROTO;
++				break;
++			}
++			rc = iscsi_check_assign_cmdsn(session,
++						(struct iscsi_nopin*)hdr);
++			if (rc)
++				break;
++			conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
++
++			rc = iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen);
++			list_del(&mtask->running);
++			if (conn->login_mtask != mtask)
++				__kfifo_put(session->mgmtpool.queue,
++					    (void*)&mtask, sizeof(void*));
++			break;
++		default:
++			rc = ISCSI_ERR_BAD_OPCODE;
++			break;
++		}
++	} else if (itt == ISCSI_RESERVED_TAG) {
++		switch(opcode) {
++		case ISCSI_OP_NOOP_IN:
++			if (!datalen) {
++				rc = iscsi_check_assign_cmdsn(session,
++						 (struct iscsi_nopin*)hdr);
++				if (!rc && hdr->ttt != ISCSI_RESERVED_TAG)
++					rc = iscsi_recv_pdu(conn->cls_conn,
++							    hdr, NULL, 0);
++			} else
++				rc = ISCSI_ERR_PROTO;
++			break;
++		case ISCSI_OP_REJECT:
++			/* we need sth like iscsi_reject_rsp()*/
++		case ISCSI_OP_ASYNC_EVENT:
++			/* we need sth like iscsi_async_event_rsp() */
++			rc = ISCSI_ERR_BAD_OPCODE;
++			break;
++		default:
++			rc = ISCSI_ERR_BAD_OPCODE;
++			break;
++		}
++	} else
++		rc = ISCSI_ERR_BAD_ITT;
++
++	return rc;
++}
++EXPORT_SYMBOL_GPL(__iscsi_complete_pdu);
++
++int iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
++		       char *data, int datalen)
++{
++	int rc;
++
++	spin_lock(&conn->session->lock);
++	rc = __iscsi_complete_pdu(conn, hdr, data, datalen);
++	spin_unlock(&conn->session->lock);
++	return rc;
++}
++EXPORT_SYMBOL_GPL(iscsi_complete_pdu);
++
++/* verify itt (itt encoding: age+cid+itt) */
++int iscsi_verify_itt(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
++		     uint32_t *ret_itt)
++{
++	struct iscsi_session *session = conn->session;
++	struct iscsi_cmd_task *ctask;
++	uint32_t itt;
++
++	if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) {
++		if ((hdr->itt & ISCSI_AGE_MASK) !=
++		    (session->age << ISCSI_AGE_SHIFT)) {
++			printk(KERN_ERR "iscsi_tcp: received itt %x expected "
++				"session age (%x)\n", hdr->itt,
++				session->age & ISCSI_AGE_MASK);
++			return ISCSI_ERR_BAD_ITT;
++		}
++
++		if ((hdr->itt & ISCSI_CID_MASK) !=
++		    (conn->id << ISCSI_CID_SHIFT)) {
++			printk(KERN_ERR "iscsi_tcp: received itt %x, expected "
++				"CID (%x)\n", hdr->itt, conn->id);
++			return ISCSI_ERR_BAD_ITT;
++		}
++		itt = hdr->itt & ISCSI_ITT_MASK;
++	} else
++		itt = hdr->itt;
++
++	if (itt < session->cmds_max) {
++		ctask = session->cmds[itt];
++
++		if (!ctask->sc) {
++			printk(KERN_INFO "iscsi_tcp: dropping ctask with "
++			       "itt 0x%x\n", ctask->itt);
++			/* force drop */
++			return ISCSI_ERR_NO_SCSI_CMD;
++		}
++
++		if (ctask->sc->SCp.phase != session->age) {
++			printk(KERN_ERR "iscsi_tcp: ctask's session age %d, "
++				"expected %d\n", ctask->sc->SCp.phase,
++				session->age);
++			return ISCSI_ERR_SESSION_FAILED;
++		}
++	}
++
++	*ret_itt = itt;
++	return 0;
++}
++EXPORT_SYMBOL_GPL(iscsi_verify_itt);
++
++void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
++{
++	struct iscsi_session *session = conn->session;
++	unsigned long flags;
++
++	spin_lock_irqsave(&session->lock, flags);
++	if (session->conn_cnt == 1 || session->leadconn == conn)
++		session->state = ISCSI_STATE_FAILED;
++	spin_unlock_irqrestore(&session->lock, flags);
++	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
++	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
++	iscsi_conn_error(conn->cls_conn, err);
++}
++EXPORT_SYMBOL_GPL(iscsi_conn_failure);
++
++/**
++ * iscsi_data_xmit - xmit any command into the scheduled connection
++ * @conn: iscsi connection
++ *
++ * Notes:
++ *	The function can return -EAGAIN in which case the caller must
++ *	re-schedule it again later or recover. '0' return code means
++ *	successful xmit.
++ **/
++static int iscsi_data_xmit(struct iscsi_conn *conn)
++{
++	struct iscsi_transport *tt;
++
++	if (unlikely(conn->suspend_tx)) {
++		debug_scsi("conn %d Tx suspended!\n", conn->id);
++		return 0;
++	}
++	tt = conn->session->tt;
++
++	/*
++	 * Transmit in the following order:
++	 *
++	 * 1) un-finished xmit (ctask or mtask)
++	 * 2) immediate control PDUs
++	 * 3) write data
++	 * 4) SCSI commands
++	 * 5) non-immediate control PDUs
++	 *
++	 * No need to lock around __kfifo_get as long as
++	 * there's one producer and one consumer.
++	 */
++
++	BUG_ON(conn->ctask && conn->mtask);
++
++	if (conn->ctask) {
++		if (tt->xmit_cmd_task(conn, conn->ctask))
++			goto again;
++		/* done with this in-progress ctask */
++		conn->ctask = NULL;
++	}
++	if (conn->mtask) {
++	        if (tt->xmit_mgmt_task(conn, conn->mtask))
++		        goto again;
++		/* done with this in-progress mtask */
++		conn->mtask = NULL;
++	}
++
++	/* process immediate first */
++        if (unlikely(__kfifo_len(conn->immqueue))) {
++	        while (__kfifo_get(conn->immqueue, (void*)&conn->mtask,
++			           sizeof(void*))) {
++			list_add_tail(&conn->mtask->running,
++				      &conn->mgmt_run_list);
++		        if (tt->xmit_mgmt_task(conn, conn->mtask))
++			        goto again;
++	        }
++		/* done with this mtask */
++		conn->mtask = NULL;
++	}
++
++	/* process command queue */
++	while (__kfifo_get(conn->xmitqueue, (void*)&conn->ctask,
++			   sizeof(void*))) {
++		/*
++		 * iscsi tcp may readd the task to the xmitqueue to send
++		 * write data
++		 */
++		if (list_empty(&conn->ctask->running))
++			list_add_tail(&conn->ctask->running, &conn->run_list);
++		if (tt->xmit_cmd_task(conn, conn->ctask))
++			goto again;
++	}
++	/* done with this ctask */
++	conn->ctask = NULL;
++
++	/* process the rest control plane PDUs, if any */
++        if (unlikely(__kfifo_len(conn->mgmtqueue))) {
++	        while (__kfifo_get(conn->mgmtqueue, (void*)&conn->mtask,
++			           sizeof(void*))) {
++			list_add_tail(&conn->mtask->running,
++				      &conn->mgmt_run_list);
++		        if (tt->xmit_mgmt_task(conn, conn->mtask))
++			        goto again;
++	        }
++		/* done with this mtask */
++		conn->mtask = NULL;
++	}
++
++	return 0;
++
++again:
++	if (unlikely(conn->suspend_tx))
++		return 0;
++
++	return -EAGAIN;
++}
++
++static void iscsi_xmitworker(void *data)
++{
++	struct iscsi_conn *conn = data;
++
++	/*
++	 * serialize Xmit worker on a per-connection basis.
++	 */
++	mutex_lock(&conn->xmitmutex);
++	if (iscsi_data_xmit(conn))
++		scsi_queue_work(conn->session->host, &conn->xmitwork);
++	mutex_unlock(&conn->xmitmutex);
++}
++
++enum {
++	FAILURE_BAD_HOST = 1,
++	FAILURE_SESSION_FAILED,
++	FAILURE_SESSION_FREED,
++	FAILURE_WINDOW_CLOSED,
++	FAILURE_SESSION_TERMINATE,
++	FAILURE_SESSION_RECOVERY_TIMEOUT,
++};
++
++int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
++{
++	struct Scsi_Host *host;
++	int reason = 0;
++	struct iscsi_session *session;
++	struct iscsi_conn *conn;
++	struct iscsi_cmd_task *ctask = NULL;
++
++	sc->scsi_done = done;
++	sc->result = 0;
++
++	host = sc->device->host;
++	session = iscsi_hostdata(host->hostdata);
++
++	spin_lock(&session->lock);
++
++	if (session->state != ISCSI_STATE_LOGGED_IN) {
++		if (session->recovery_failed) {
++			reason = FAILURE_SESSION_RECOVERY_TIMEOUT;
++			goto fault;
++		} else if (session->state == ISCSI_STATE_FAILED) {
++			reason = FAILURE_SESSION_FAILED;
++			goto reject;
++		} else if (session->state == ISCSI_STATE_TERMINATE) {
++			reason = FAILURE_SESSION_TERMINATE;
++			goto fault;
++		}
++		reason = FAILURE_SESSION_FREED;
++		goto fault;
++	}
++
++	/*
++	 * Check for iSCSI window and take care of CmdSN wrap-around
++	 */
++	if ((int)(session->max_cmdsn - session->cmdsn) < 0) {
++		reason = FAILURE_WINDOW_CLOSED;
++		goto reject;
++	}
++
++	conn = session->leadconn;
++
++	__kfifo_get(session->cmdpool.queue, (void*)&ctask, sizeof(void*));
++	sc->SCp.phase = session->age;
++	sc->SCp.ptr = (char *)ctask;
++
++	ctask->mtask = NULL;
++	ctask->conn = conn;
++	ctask->sc = sc;
++	INIT_LIST_HEAD(&ctask->running);
++	ctask->total_length = sc->request_bufflen;
++	iscsi_prep_scsi_cmd_pdu(ctask);
++
++	session->tt->init_cmd_task(ctask);
++
++	__kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*));
++	debug_scsi(
++	       "ctask enq [%s cid %d sc %lx itt 0x%x len %d cmdsn %d win %d]\n",
++		sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
++		conn->id, (long)sc, ctask->itt, sc->request_bufflen,
++		session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
++	spin_unlock(&session->lock);
++
++	scsi_queue_work(host, &conn->xmitwork);
++	return 0;
++
++reject:
++	spin_unlock(&session->lock);
++	debug_scsi("cmd 0x%x rejected (%d)\n", sc->cmnd[0], reason);
++	return SCSI_MLQUEUE_HOST_BUSY;
++
++fault:
++	spin_unlock(&session->lock);
++	printk(KERN_ERR "iscsi_tcp: cmd 0x%x is not queued (%d)\n",
++	       sc->cmnd[0], reason);
++	sc->result = (DID_NO_CONNECT << 16);
++	sc->resid = sc->request_bufflen;
++	sc->scsi_done(sc);
++	return 0;
++}
++EXPORT_SYMBOL_GPL(iscsi_queuecommand);
++
++int iscsi_change_queue_depth(struct scsi_device *sdev, int depth)
++{
++	if (depth > ISCSI_MAX_CMD_PER_LUN)
++		depth = ISCSI_MAX_CMD_PER_LUN;
++	scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
++	return sdev->queue_depth;
++}
++EXPORT_SYMBOL_GPL(iscsi_change_queue_depth);
++
++static int
++iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
++			char *data, uint32_t data_size)
++{
++	struct iscsi_session *session = conn->session;
++	struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr;
++	struct iscsi_mgmt_task *mtask;
++
++	spin_lock_bh(&session->lock);
++	if (session->state == ISCSI_STATE_TERMINATE) {
++		spin_unlock_bh(&session->lock);
++		return -EPERM;
++	}
++	if (hdr->opcode == (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) ||
++	    hdr->opcode == (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE))
++		/*
++		 * Login and Text are sent serially, in
++		 * request-followed-by-response sequence.
++		 * Same mtask can be used. Same ITT must be used.
++		 * Note that login_mtask is preallocated at conn_create().
++		 */
++		mtask = conn->login_mtask;
++	else {
++	        BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
++	        BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
++
++		if (!__kfifo_get(session->mgmtpool.queue,
++				 (void*)&mtask, sizeof(void*))) {
++			spin_unlock_bh(&session->lock);
++			return -ENOSPC;
++		}
++	}
++
++	/*
++	 * pre-format CmdSN and ExpStatSN for outgoing PDU.
++	 */
++	if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) {
++		hdr->itt = mtask->itt | (conn->id << ISCSI_CID_SHIFT) |
++			   (session->age << ISCSI_AGE_SHIFT);
++		nop->cmdsn = cpu_to_be32(session->cmdsn);
++		if (conn->c_stage == ISCSI_CONN_STARTED &&
++		    !(hdr->opcode & ISCSI_OP_IMMEDIATE))
++			session->cmdsn++;
++	} else
++		/* do not advance CmdSN */
++		nop->cmdsn = cpu_to_be32(session->cmdsn);
++
++	nop->exp_statsn = cpu_to_be32(conn->exp_statsn);
++
++	if (data_size) {
++		memcpy(mtask->data, data, data_size);
++		mtask->data_count = data_size;
++	} else
++		mtask->data_count = 0;
++
++	INIT_LIST_HEAD(&mtask->running);
++	memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr));
++	if (session->tt->init_mgmt_task)
++		session->tt->init_mgmt_task(conn, mtask, data, data_size);
++	spin_unlock_bh(&session->lock);
++
++	debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n",
++		   hdr->opcode, hdr->itt, data_size);
++
++	/*
++	 * since send_pdu() could be called at least from two contexts,
++	 * we need to serialize __kfifo_put, so we don't have to take
++	 * additional lock on fast data-path
++	 */
++        if (hdr->opcode & ISCSI_OP_IMMEDIATE)
++	        __kfifo_put(conn->immqueue, (void*)&mtask, sizeof(void*));
++	else
++	        __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*));
++
++	scsi_queue_work(session->host, &conn->xmitwork);
++	return 0;
++}
++
++int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
++			char *data, uint32_t data_size)
++{
++	struct iscsi_conn *conn = cls_conn->dd_data;
++	int rc;
++
++	mutex_lock(&conn->xmitmutex);
++	rc = iscsi_conn_send_generic(conn, hdr, data, data_size);
++	mutex_unlock(&conn->xmitmutex);
++
++	return rc;
++}
++EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu);
++
++void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session)
++{
++	struct iscsi_session *session = class_to_transport_session(cls_session);
++	struct iscsi_conn *conn = session->leadconn;
++
++	spin_lock_bh(&session->lock);
++	if (session->state != ISCSI_STATE_LOGGED_IN) {
++		session->recovery_failed = 1;
++		if (conn)
++			wake_up(&conn->ehwait);
++	}
++	spin_unlock_bh(&session->lock);
++}
++EXPORT_SYMBOL_GPL(iscsi_session_recovery_timedout);
++
++int iscsi_eh_host_reset(struct scsi_cmnd *sc)
++{
++	struct Scsi_Host *host = sc->device->host;
++	struct iscsi_session *session = iscsi_hostdata(host->hostdata);
++	struct iscsi_conn *conn = session->leadconn;
++	int fail_session = 0;
++
++	spin_lock_bh(&session->lock);
++	if (session->state == ISCSI_STATE_TERMINATE) {
++failed:
++		debug_scsi("failing host reset: session terminated "
++			   "[CID %d age %d]", conn->id, session->age);
++		spin_unlock_bh(&session->lock);
++		return FAILED;
++	}
++
++	if (sc->SCp.phase == session->age) {
++		debug_scsi("failing connection CID %d due to SCSI host reset",
++			   conn->id);
++		fail_session = 1;
++	}
++	spin_unlock_bh(&session->lock);
++
++	/*
++	 * we drop the lock here but the leadconn cannot be destoyed while
++	 * we are in the scsi eh
++	 */
++	if (fail_session) {
++		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
++		/*
++		 * if userspace cannot respond then we must kick this off
++		 * here for it
++		 */
++		iscsi_start_session_recovery(session, conn, STOP_CONN_RECOVER);
++	}
++
++	debug_scsi("iscsi_eh_host_reset wait for relogin\n");
++	wait_event_interruptible(conn->ehwait,
++				 session->state == ISCSI_STATE_TERMINATE ||
++				 session->state == ISCSI_STATE_LOGGED_IN ||
++				 session->recovery_failed);
++	if (signal_pending(current))
++		flush_signals(current);
++
++	spin_lock_bh(&session->lock);
++	if (session->state == ISCSI_STATE_LOGGED_IN)
++		printk(KERN_INFO "host reset succeeded\n");
++	else
++		goto failed;
++	spin_unlock_bh(&session->lock);
++
++	return SUCCESS;
++}
++EXPORT_SYMBOL_GPL(iscsi_eh_host_reset);
++
++static void iscsi_tmabort_timedout(unsigned long data)
++{
++	struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)data;
++	struct iscsi_conn *conn = ctask->conn;
++	struct iscsi_session *session = conn->session;
++
++	spin_lock(&session->lock);
++	if (conn->tmabort_state == TMABORT_INITIAL) {
++		conn->tmabort_state = TMABORT_TIMEDOUT;
++		debug_scsi("tmabort timedout [sc %p itt 0x%x]\n",
++			ctask->sc, ctask->itt);
++		/* unblock eh_abort() */
++		wake_up(&conn->ehwait);
++	}
++	spin_unlock(&session->lock);
++}
++
++/* must be called with the mutex lock */
++static int iscsi_exec_abort_task(struct scsi_cmnd *sc,
++				 struct iscsi_cmd_task *ctask)
++{
++	struct iscsi_conn *conn = ctask->conn;
++	struct iscsi_session *session = conn->session;
++	struct iscsi_tm *hdr = &conn->tmhdr;
++	int rc;
++
++	/*
++	 * ctask timed out but session is OK requests must be serialized.
++	 */
++	memset(hdr, 0, sizeof(struct iscsi_tm));
++	hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE;
++	hdr->flags = ISCSI_TM_FUNC_ABORT_TASK;
++	hdr->flags |= ISCSI_FLAG_CMD_FINAL;
++	memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun));
++	hdr->rtt = ctask->hdr->itt;
++	hdr->refcmdsn = ctask->hdr->cmdsn;
++
++	rc = iscsi_conn_send_generic(conn, (struct iscsi_hdr *)hdr,
++				     NULL, 0);
++	if (rc) {
++		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
++		debug_scsi("abort sent failure [itt 0x%x] %d", ctask->itt, rc);
++		return rc;
++	}
++
++	debug_scsi("abort sent [itt 0x%x]\n", ctask->itt);
++
++	spin_lock_bh(&session->lock);
++	ctask->mtask = (struct iscsi_mgmt_task *)
++			session->mgmt_cmds[(hdr->itt & ISCSI_ITT_MASK) -
++					ISCSI_MGMT_ITT_OFFSET];
++
++	if (conn->tmabort_state == TMABORT_INITIAL) {
++		conn->tmfcmd_pdus_cnt++;
++		conn->tmabort_timer.expires = 10*HZ + jiffies;
++		conn->tmabort_timer.function = iscsi_tmabort_timedout;
++		conn->tmabort_timer.data = (unsigned long)ctask;
++		add_timer(&conn->tmabort_timer);
++		debug_scsi("abort set timeout [itt 0x%x]", ctask->itt);
++	}
++	spin_unlock_bh(&session->lock);
++	mutex_unlock(&conn->xmitmutex);
++
++	/*
++	 * block eh thread until:
++	 *
++	 * 1) abort response
++	 * 2) abort timeout
++	 * 3) session is terminated or restarted or userspace has
++	 * given up on recovery
++	 */
++	wait_event_interruptible(conn->ehwait,
++				 sc->SCp.phase != session->age ||
++				 session->state != ISCSI_STATE_LOGGED_IN ||
++				 conn->tmabort_state != TMABORT_INITIAL ||
++				 session->recovery_failed);
++	if (signal_pending(current))
++		flush_signals(current);
++	del_timer_sync(&conn->tmabort_timer);
++
++	mutex_lock(&conn->xmitmutex);
++	return 0;
++}
++
++/*
++ * xmit mutex and session lock must be held
++ */
++#define iscsi_remove_task(tasktype)					\
++static struct iscsi_##tasktype *					\
++iscsi_remove_##tasktype(struct kfifo *fifo, uint32_t itt)		\
++{									\
++	int i, nr_tasks = __kfifo_len(fifo) / sizeof(void*);		\
++	struct iscsi_##tasktype *task;					\
++									\
++	debug_scsi("searching %d tasks\n", nr_tasks);			\
++									\
++	for (i = 0; i < nr_tasks; i++) {				\
++		__kfifo_get(fifo, (void*)&task, sizeof(void*));		\
++		debug_scsi("check task %u\n", task->itt);		\
++									\
++		if (task->itt == itt) {					\
++			debug_scsi("matched task\n");			\
++			break;						\
++		}							\
++									\
++		__kfifo_put(fifo, (void*)&task, sizeof(void*));		\
++	}								\
++	return NULL;							\
++}
++
++iscsi_remove_task(mgmt_task);
++iscsi_remove_task(cmd_task);
++
++static int iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask)
++{
++	struct iscsi_conn *conn = ctask->conn;
++	struct iscsi_session *session = conn->session;
++
++	if (!ctask->mtask)
++		return -EINVAL;
++
++	if (!iscsi_remove_mgmt_task(conn->immqueue, ctask->mtask->itt))
++		list_del(&ctask->mtask->running);
++	__kfifo_put(session->mgmtpool.queue, (void*)&ctask->mtask,
++		    sizeof(void*));
++	ctask->mtask = NULL;
++	return 0;
++}
++
++/*
++ * session lock and xmitmutex must be held
++ */
++static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
++			 int err)
++{
++	struct scsi_cmnd *sc;
++
++	conn->session->tt->cleanup_cmd_task(conn, ctask);
++	iscsi_ctask_mtask_cleanup(ctask);
++
++	sc = ctask->sc;
++	if (!sc)
++		return;
++	sc->result = err;
++	sc->resid = sc->request_bufflen;
++	iscsi_complete_command(conn->session, ctask);
++}
++
++int iscsi_eh_abort(struct scsi_cmnd *sc)
++{
++	struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr;
++	struct iscsi_conn *conn = ctask->conn;
++	struct iscsi_session *session = conn->session;
++	struct iscsi_cmd_task *pending_ctask;
++	int rc;
++
++	conn->eh_abort_cnt++;
++	debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt);
++
++	mutex_lock(&conn->xmitmutex);
++	spin_lock_bh(&session->lock);
++
++	/*
++	 * If we are not logged in or we have started a new session
++	 * then let the host reset code handle this
++	 */
++	if (session->state != ISCSI_STATE_LOGGED_IN ||
++	    sc->SCp.phase != session->age)
++		goto failed;
++
++	/* ctask completed before time out */
++	if (!ctask->sc)
++		goto success;
++
++	/* what should we do here ? */
++	if (conn->ctask == ctask) {
++		printk(KERN_INFO "sc %p itt 0x%x partially sent. Failing "
++		       "abort\n", sc, ctask->itt);
++		goto failed;
++	}
++
++	/* check for the easy pending cmd abort */
++	pending_ctask = iscsi_remove_cmd_task(conn->xmitqueue, ctask->itt);
++	if (pending_ctask) {
++		/* iscsi_tcp queues write transfers on the xmitqueue */
++		if (list_empty(&pending_ctask->running)) {
++			debug_scsi("found pending task\n");
++			goto success;
++		} else
++			__kfifo_put(conn->xmitqueue, (void*)&pending_ctask,
++				    sizeof(void*));
++	}
++
++	conn->tmabort_state = TMABORT_INITIAL;
++
++	spin_unlock_bh(&session->lock);
++	rc = iscsi_exec_abort_task(sc, ctask);
++	spin_lock_bh(&session->lock);
++
++	iscsi_ctask_mtask_cleanup(ctask);
++	if (rc || sc->SCp.phase != session->age ||
++	    session->state != ISCSI_STATE_LOGGED_IN)
++		goto failed;
++
++	/* ctask completed before tmf abort response */
++	if (!ctask->sc) {
++		debug_scsi("sc completed while abort in progress\n");
++		goto success;
++	}
++
++	if (conn->tmabort_state != TMABORT_SUCCESS) {
++		spin_unlock_bh(&session->lock);
++		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
++		spin_lock_bh(&session->lock);
++		goto failed;
++	}
++
++success:
++	debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
++	spin_unlock_bh(&session->lock);
++
++	/*
++	 * clean up task if aborted. we have the xmitmutex so grab
++	 * the recv lock as a writer
++	 */
++	write_lock_bh(conn->recv_lock);
++	spin_lock(&session->lock);
++	fail_command(conn, ctask, DID_ABORT << 16);
++	spin_unlock(&session->lock);
++	write_unlock_bh(conn->recv_lock);
++
++	mutex_unlock(&conn->xmitmutex);
++	return SUCCESS;
++
++failed:
++	spin_unlock_bh(&session->lock);
++	mutex_unlock(&conn->xmitmutex);
++
++	debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
++	return FAILED;
++}
++EXPORT_SYMBOL_GPL(iscsi_eh_abort);
++
++int
++iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size)
++{
++	int i;
++
++	*items = kmalloc(max * sizeof(void*), GFP_KERNEL);
++	if (*items == NULL)
++		return -ENOMEM;
++
++	q->max = max;
++	q->pool = kmalloc(max * sizeof(void*), GFP_KERNEL);
++	if (q->pool == NULL) {
++		kfree(*items);
++		return -ENOMEM;
++	}
++
++	q->queue = kfifo_init((void*)q->pool, max * sizeof(void*),
++			      GFP_KERNEL, NULL);
++	if (q->queue == ERR_PTR(-ENOMEM)) {
++		kfree(q->pool);
++		kfree(*items);
++		return -ENOMEM;
++	}
++
++	for (i = 0; i < max; i++) {
++		q->pool[i] = kmalloc(item_size, GFP_KERNEL);
++		if (q->pool[i] == NULL) {
++			int j;
++
++			for (j = 0; j < i; j++)
++				kfree(q->pool[j]);
++
++			kfifo_free(q->queue);
++			kfree(q->pool);
++			kfree(*items);
++			return -ENOMEM;
++		}
++		memset(q->pool[i], 0, item_size);
++		(*items)[i] = q->pool[i];
++		__kfifo_put(q->queue, (void*)&q->pool[i], sizeof(void*));
++	}
++	return 0;
++}
++EXPORT_SYMBOL_GPL(iscsi_pool_init);
++
++void iscsi_pool_free(struct iscsi_queue *q, void **items)
++{
++	int i;
++
++	for (i = 0; i < q->max; i++)
++		kfree(items[i]);
++	kfree(q->pool);
++	kfree(items);
++}
++EXPORT_SYMBOL_GPL(iscsi_pool_free);
++
++/*
++ * iSCSI Session's hostdata organization:
++ *
++ *    *------------------* <== hostdata_session(host->hostdata)
++ *    | ptr to class sess|
++ *    |------------------| <== iscsi_hostdata(host->hostdata)
++ *    | iscsi_session    |
++ *    *------------------*
++ */
++
++#define hostdata_privsize(_sz)	(sizeof(unsigned long) + _sz + \
++				 _sz % sizeof(unsigned long))
++
++#define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata))
++
++/**
++ * iscsi_session_setup - create iscsi cls session and host and session
++ * @scsit: scsi transport template
++ * @iscsit: iscsi transport template
++ * @initial_cmdsn: initial CmdSN
++ * @hostno: host no allocated
++ *
++ * This can be used by software iscsi_transports that allocate
++ * a session per scsi host.
++ **/
++struct iscsi_cls_session *
++iscsi_session_setup(struct iscsi_transport *iscsit,
++		    struct scsi_transport_template *scsit,
++		    int cmd_task_size, int mgmt_task_size,
++		    uint32_t initial_cmdsn, uint32_t *hostno)
++{
++	struct Scsi_Host *shost;
++	struct iscsi_session *session;
++	struct iscsi_cls_session *cls_session;
++	int cmd_i;
++
++	shost = scsi_host_alloc(iscsit->host_template,
++				hostdata_privsize(sizeof(*session)));
++	if (!shost)
++		return NULL;
++
++	shost->max_id = 1;
++	shost->max_channel = 0;
++	shost->max_lun = iscsit->max_lun;
++	shost->max_cmd_len = iscsit->max_cmd_len;
++	shost->transportt = scsit;
++	shost->transportt->create_work_queue = 1;
++	*hostno = shost->host_no;
++
++	session = iscsi_hostdata(shost->hostdata);
++	memset(session, 0, sizeof(struct iscsi_session));
++	session->host = shost;
++	session->state = ISCSI_STATE_FREE;
++	session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
++	session->cmds_max = ISCSI_XMIT_CMDS_MAX;
++	session->cmdsn = initial_cmdsn;
++	session->exp_cmdsn = initial_cmdsn + 1;
++	session->max_cmdsn = initial_cmdsn + 1;
++	session->max_r2t = 1;
++	session->tt = iscsit;
++
++	/* initialize SCSI PDU commands pool */
++	if (iscsi_pool_init(&session->cmdpool, session->cmds_max,
++			    (void***)&session->cmds,
++			    cmd_task_size + sizeof(struct iscsi_cmd_task)))
++		goto cmdpool_alloc_fail;
++
++	/* pre-format cmds pool with ITT */
++	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
++		struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
++
++		if (cmd_task_size)
++			ctask->dd_data = &ctask[1];
++		ctask->itt = cmd_i;
++	}
++
++	spin_lock_init(&session->lock);
++	INIT_LIST_HEAD(&session->connections);
++
++	/* initialize immediate command pool */
++	if (iscsi_pool_init(&session->mgmtpool, session->mgmtpool_max,
++			   (void***)&session->mgmt_cmds,
++			   mgmt_task_size + sizeof(struct iscsi_mgmt_task)))
++		goto mgmtpool_alloc_fail;
++
++
++	/* pre-format immediate cmds pool with ITT */
++	for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) {
++		struct iscsi_mgmt_task *mtask = session->mgmt_cmds[cmd_i];
++
++		if (mgmt_task_size)
++			mtask->dd_data = &mtask[1];
++		mtask->itt = ISCSI_MGMT_ITT_OFFSET + cmd_i;
++		mtask->data = kmalloc(DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH,
++				     GFP_KERNEL);
++		if (!mtask->data) {
++			int j;
++
++			for (j = 0; j < cmd_i; j++)
++				kfree(session->mgmt_cmds[j]->data);
++			goto immdata_alloc_fail;
++		}
++	}
++
++	if (scsi_add_host(shost, NULL))
++		goto add_host_fail;
++
++	cls_session = iscsi_create_session(shost, iscsit, 0);
++	if (!cls_session)
++		goto cls_session_fail;
++	*(unsigned long*)shost->hostdata = (unsigned long)cls_session;
++
++	return cls_session;
++
++cls_session_fail:
++	scsi_remove_host(shost);
++add_host_fail:
++	for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++)
++		kfree(session->mgmt_cmds[cmd_i]->data);
++immdata_alloc_fail:
++	iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
++mgmtpool_alloc_fail:
++	iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
++cmdpool_alloc_fail:
++	scsi_host_put(shost);
++	return NULL;
++}
++EXPORT_SYMBOL_GPL(iscsi_session_setup);
++
++/**
++ * iscsi_session_teardown - destroy session, host, and cls_session
++ * shost: scsi host
++ *
++ * This can be used by software iscsi_transports that allocate
++ * a session per scsi host.
++ **/
++void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
++{
++	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
++	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
++	int cmd_i;
++
++	scsi_remove_host(shost);
++
++	for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++)
++		kfree(session->mgmt_cmds[cmd_i]->data);
++
++	iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
++	iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
++
++	iscsi_destroy_session(cls_session);
++	scsi_host_put(shost);
++}
++EXPORT_SYMBOL_GPL(iscsi_session_teardown);
++
++/**
++ * iscsi_conn_setup - create iscsi_cls_conn and iscsi_conn
++ * @cls_session: iscsi_cls_session
++ * @conn_idx: cid
++ **/
++struct iscsi_cls_conn *
++iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
++{
++	struct iscsi_session *session = class_to_transport_session(cls_session);
++	struct iscsi_conn *conn;
++	struct iscsi_cls_conn *cls_conn;
++
++	cls_conn = iscsi_create_conn(cls_session, conn_idx);
++	if (!cls_conn)
++		return NULL;
++	conn = cls_conn->dd_data;
++	memset(conn, 0, sizeof(*conn));
++
++	conn->session = session;
++	conn->cls_conn = cls_conn;
++	conn->c_stage = ISCSI_CONN_INITIAL_STAGE;
++	conn->id = conn_idx;
++	conn->exp_statsn = 0;
++	conn->tmabort_state = TMABORT_INITIAL;
++	INIT_LIST_HEAD(&conn->run_list);
++	INIT_LIST_HEAD(&conn->mgmt_run_list);
++
++	/* initialize general xmit PDU commands queue */
++	conn->xmitqueue = kfifo_alloc(session->cmds_max * sizeof(void*),
++					GFP_KERNEL, NULL);
++	if (conn->xmitqueue == ERR_PTR(-ENOMEM))
++		goto xmitqueue_alloc_fail;
++
++	/* initialize general immediate & non-immediate PDU commands queue */
++	conn->immqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*),
++			                GFP_KERNEL, NULL);
++	if (conn->immqueue == ERR_PTR(-ENOMEM))
++		goto immqueue_alloc_fail;
++
++	conn->mgmtqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*),
++			                GFP_KERNEL, NULL);
++	if (conn->mgmtqueue == ERR_PTR(-ENOMEM))
++		goto mgmtqueue_alloc_fail;
++
++	INIT_WORK(&conn->xmitwork, iscsi_xmitworker, conn);
++
++	/* allocate login_mtask used for the login/text sequences */
++	spin_lock_bh(&session->lock);
++	if (!__kfifo_get(session->mgmtpool.queue,
++                         (void*)&conn->login_mtask,
++			 sizeof(void*))) {
++		spin_unlock_bh(&session->lock);
++		goto login_mtask_alloc_fail;
++	}
++	spin_unlock_bh(&session->lock);
++
++	init_timer(&conn->tmabort_timer);
++	mutex_init(&conn->xmitmutex);
++	init_waitqueue_head(&conn->ehwait);
++
++	return cls_conn;
++
++login_mtask_alloc_fail:
++	kfifo_free(conn->mgmtqueue);
++mgmtqueue_alloc_fail:
++	kfifo_free(conn->immqueue);
++immqueue_alloc_fail:
++	kfifo_free(conn->xmitqueue);
++xmitqueue_alloc_fail:
++	iscsi_destroy_conn(cls_conn);
++	return NULL;
++}
++EXPORT_SYMBOL_GPL(iscsi_conn_setup);
++
++/**
++ * iscsi_conn_teardown - teardown iscsi connection
++ * cls_conn: iscsi class connection
++ *
++ * TODO: we may need to make this into a two step process
++ * like scsi-mls remove + put host
++ */
++void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
++{
++	struct iscsi_conn *conn = cls_conn->dd_data;
++	struct iscsi_session *session = conn->session;
++	unsigned long flags;
++
++	mutex_lock(&conn->xmitmutex);
++	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
++	if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE) {
++		if (session->tt->suspend_conn_recv)
++			session->tt->suspend_conn_recv(conn);
++
++		session->tt->terminate_conn(conn);
++	}
++
++	spin_lock_bh(&session->lock);
++	conn->c_stage = ISCSI_CONN_CLEANUP_WAIT;
++	if (session->leadconn == conn) {
++		/*
++		 * leading connection? then give up on recovery.
++		 */
++		session->state = ISCSI_STATE_TERMINATE;
++		wake_up(&conn->ehwait);
++	}
++	spin_unlock_bh(&session->lock);
++
++	mutex_unlock(&conn->xmitmutex);
++
++	/*
++	 * Block until all in-progress commands for this connection
++	 * time out or fail.
++	 */
++	for (;;) {
++		spin_lock_irqsave(session->host->host_lock, flags);
++		if (!session->host->host_busy) { /* OK for ERL == 0 */
++			spin_unlock_irqrestore(session->host->host_lock, flags);
++			break;
++		}
++		spin_unlock_irqrestore(session->host->host_lock, flags);
++		msleep_interruptible(500);
++		printk("conn_destroy(): host_busy %d host_failed %d\n",
++			session->host->host_busy, session->host->host_failed);
++		/*
++		 * force eh_abort() to unblock
++		 */
++		wake_up(&conn->ehwait);
++	}
++
++	spin_lock_bh(&session->lock);
++	__kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask,
++		    sizeof(void*));
++	list_del(&conn->item);
++	if (list_empty(&session->connections))
++		session->leadconn = NULL;
++	if (session->leadconn && session->leadconn == conn)
++		session->leadconn = container_of(session->connections.next,
++			struct iscsi_conn, item);
++
++	if (session->leadconn == NULL)
++		/* no connections exits.. reset sequencing */
++		session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1;
++	spin_unlock_bh(&session->lock);
++
++	kfifo_free(conn->xmitqueue);
++	kfifo_free(conn->immqueue);
++	kfifo_free(conn->mgmtqueue);
++
++	iscsi_destroy_conn(cls_conn);
++}
++EXPORT_SYMBOL_GPL(iscsi_conn_teardown);
++
++int iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
++{
++	struct iscsi_conn *conn = cls_conn->dd_data;
++	struct iscsi_session *session = conn->session;
++
++	if (session == NULL) {
++		printk(KERN_ERR "iscsi: can't start unbound connection\n");
++		return -EPERM;
++	}
++
++	spin_lock_bh(&session->lock);
++	conn->c_stage = ISCSI_CONN_STARTED;
++	session->state = ISCSI_STATE_LOGGED_IN;
++
++	switch(conn->stop_stage) {
++	case STOP_CONN_RECOVER:
++		/*
++		 * unblock eh_abort() if it is blocked. re-try all
++		 * commands after successful recovery
++		 */
++		session->conn_cnt++;
++		conn->stop_stage = 0;
++		conn->tmabort_state = TMABORT_INITIAL;
++		session->age++;
++		session->recovery_failed = 0;
++		spin_unlock_bh(&session->lock);
++
++		iscsi_unblock_session(session_to_cls(session));
++		wake_up(&conn->ehwait);
++		return 0;
++	case STOP_CONN_TERM:
++		session->conn_cnt++;
++		conn->stop_stage = 0;
++		break;
++	case STOP_CONN_SUSPEND:
++		conn->stop_stage = 0;
++		clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
++		clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
++		break;
++	default:
++		break;
++	}
++	spin_unlock_bh(&session->lock);
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(iscsi_conn_start);
++
++static void
++flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn)
++{
++	struct iscsi_mgmt_task *mtask, *tmp;
++
++	/* handle pending */
++	while (__kfifo_get(conn->immqueue, (void*)&mtask, sizeof(void*)) ||
++	       __kfifo_get(conn->mgmtqueue, (void*)&mtask, sizeof(void*))) {
++		if (mtask == conn->login_mtask)
++			continue;
++		debug_scsi("flushing pending mgmt task itt 0x%x\n", mtask->itt);
++		__kfifo_put(session->mgmtpool.queue, (void*)&mtask,
++			    sizeof(void*));
++	}
++
++	/* handle running */
++	list_for_each_entry_safe(mtask, tmp, &conn->mgmt_run_list, running) {
++		debug_scsi("flushing running mgmt task itt 0x%x\n", mtask->itt);
++		if (mtask == conn->login_mtask)
++			continue;
++		list_del(&mtask->running);
++		__kfifo_put(session->mgmtpool.queue, (void*)&conn->mtask,
++			   sizeof(void*));
++	}
++
++	conn->mtask = NULL;
++}
++
++/* Fail commands. Mutex and session lock held and recv side suspended */
++static void fail_all_commands(struct iscsi_conn *conn)
++{
++	struct iscsi_cmd_task *ctask, *tmp;
++
++	/* flush pending */
++	while (__kfifo_get(conn->xmitqueue, (void*)&ctask, sizeof(void*))) {
++		debug_scsi("failing pending sc %p itt 0x%x\n", ctask->sc,
++			   ctask->itt);
++		fail_command(conn, ctask, DID_BUS_BUSY << 16);
++	}
++
++	/* fail all other running */
++	list_for_each_entry_safe(ctask, tmp, &conn->run_list, running) {
++		debug_scsi("failing in progress sc %p itt 0x%x\n",
++			   ctask->sc, ctask->itt);
++		fail_command(conn, ctask, DID_BUS_BUSY << 16);
++	}
++
++	conn->ctask = NULL;
++}
++
++void iscsi_start_session_recovery(struct iscsi_session *session,
++				  struct iscsi_conn *conn, int flag)
++{
++	spin_lock_bh(&session->lock);
++	if (conn->stop_stage == STOP_CONN_RECOVER ||
++	    conn->stop_stage == STOP_CONN_TERM) {
++		spin_unlock_bh(&session->lock);
++		return;
++	}
++	conn->stop_stage = flag;
++	spin_unlock_bh(&session->lock);
++
++	if (session->tt->suspend_conn_recv)
++		session->tt->suspend_conn_recv(conn);
++
++	mutex_lock(&conn->xmitmutex);
++	spin_lock_bh(&session->lock);
++	conn->c_stage = ISCSI_CONN_STOPPED;
++	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
++
++	session->conn_cnt--;
++	if (session->conn_cnt == 0 || session->leadconn == conn)
++		session->state = ISCSI_STATE_FAILED;
++
++	spin_unlock_bh(&session->lock);
++
++	session->tt->terminate_conn(conn);
++	/*
++	 * flush queues.
++	 */
++	spin_lock_bh(&session->lock);
++	fail_all_commands(conn);
++	flush_control_queues(session, conn);
++	spin_unlock_bh(&session->lock);
++
++	/*
++	 * for connection level recovery we should not calculate
++	 * header digest. conn->hdr_size used for optimization
++	 * in hdr_extract() and will be re-negotiated at
++	 * set_param() time.
++	 */
++	if (flag == STOP_CONN_RECOVER) {
++		conn->hdrdgst_en = 0;
++		conn->datadgst_en = 0;
++
++		if (session->state == ISCSI_STATE_FAILED)
++			iscsi_block_session(session_to_cls(session));
++	}
++	mutex_unlock(&conn->xmitmutex);
++}
++EXPORT_SYMBOL_GPL(iscsi_start_session_recovery);
++
++void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
++{
++	struct iscsi_conn *conn = cls_conn->dd_data;
++	struct iscsi_session *session = conn->session;
++
++	switch (flag) {
++	case STOP_CONN_RECOVER:
++	case STOP_CONN_TERM:
++		iscsi_start_session_recovery(session, conn, flag);
++		return;
++	case STOP_CONN_SUSPEND:
++		if (session->tt->suspend_conn_recv)
++			session->tt->suspend_conn_recv(conn);
++
++		mutex_lock(&conn->xmitmutex);
++		spin_lock_bh(&session->lock);
++
++		conn->stop_stage = flag;
++		conn->c_stage = ISCSI_CONN_STOPPED;
++		set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
++
++		spin_unlock_bh(&session->lock);
++		mutex_unlock(&conn->xmitmutex);
++		break;
++	default:
++		printk(KERN_ERR "invalid stop flag %d\n", flag);
++	}
++}
++EXPORT_SYMBOL_GPL(iscsi_conn_stop);
++
++int iscsi_conn_bind(struct iscsi_cls_session *cls_session,
++		    struct iscsi_cls_conn *cls_conn, int is_leading)
++{
++	struct iscsi_session *session = class_to_transport_session(cls_session);
++	struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = cls_conn->dd_data;
++
++	/* lookup for existing connection */
++	spin_lock_bh(&session->lock);
++	list_for_each_entry(tmp, &session->connections, item) {
++		if (tmp == conn) {
++			if (conn->c_stage != ISCSI_CONN_STOPPED ||
++			    conn->stop_stage == STOP_CONN_TERM) {
++				printk(KERN_ERR "iscsi_tcp: can't bind "
++				       "non-stopped connection (%d:%d)\n",
++				       conn->c_stage, conn->stop_stage);
++				spin_unlock_bh(&session->lock);
++				return -EIO;
++			}
++			break;
++		}
++	}
++	if (tmp != conn) {
++		/* bind new iSCSI connection to session */
++		conn->session = session;
++		list_add(&conn->item, &session->connections);
++	}
++	spin_unlock_bh(&session->lock);
++
++	if (is_leading)
++		session->leadconn = conn;
++
++	/*
++	 * Unblock xmitworker(), Login Phase will pass through.
++	 */
++	clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
++	clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
++	return 0;
++}
++EXPORT_SYMBOL_GPL(iscsi_conn_bind);
++
++MODULE_AUTHOR("Mike Christie");
++MODULE_DESCRIPTION("iSCSI library functions");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index e2b67e34d92e..bc9071d2d212 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -471,106 +471,6 @@ int iscsi_destroy_conn(struct iscsi_cls_conn *conn)
+ 
+ EXPORT_SYMBOL_GPL(iscsi_destroy_conn);
+ 
+-/*
+- * These functions are used only by software iscsi_transports
+- * which do not allocate and more their scsi_hosts since this
+- * is initiated from userspace.
+- */
+-
+-/*
+- * iSCSI Session's hostdata organization:
+- *
+- *    *------------------* <== hostdata_session(host->hostdata)
+- *    | ptr to class sess|
+- *    |------------------| <== iscsi_hostdata(host->hostdata)
+- *    | transport's data |
+- *    *------------------*
+- */
+-
+-#define hostdata_privsize(_t)	(sizeof(unsigned long) + _t->hostdata_size + \
+-				 _t->hostdata_size % sizeof(unsigned long))
+-
+-#define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata))
+-
+-/**
+- * iscsi_transport_create_session - create iscsi cls session and host
+- * scsit: scsi transport template
+- * transport: iscsi transport template
+- *
+- * This can be used by software iscsi_transports that allocate
+- * a session per scsi host.
+- **/
+-struct Scsi_Host *
+-iscsi_transport_create_session(struct scsi_transport_template *scsit,
+-			       struct iscsi_transport *transport)
+-{
+-	struct iscsi_cls_session *session;
+-	struct Scsi_Host *shost;
+-	unsigned long flags;
+-
+-	shost = scsi_host_alloc(transport->host_template,
+-				hostdata_privsize(transport));
+-	if (!shost) {
+-		printk(KERN_ERR "iscsi: can not allocate SCSI host for "
+-			"session\n");
+-		return NULL;
+-	}
+-
+-	shost->max_id = 1;
+-	shost->max_channel = 0;
+-	shost->max_lun = transport->max_lun;
+-	shost->max_cmd_len = transport->max_cmd_len;
+-	shost->transportt = scsit;
+-	shost->transportt->create_work_queue = 1;
+-
+-	if (scsi_add_host(shost, NULL))
+-		goto free_host;
+-
+-	session = iscsi_create_session(shost, transport, 0);
+-	if (!session)
+-		goto remove_host;
+-
+-	*(unsigned long*)shost->hostdata = (unsigned long)session;
+-	spin_lock_irqsave(&sesslock, flags);
+-	list_add(&session->sess_list, &sesslist);
+-	spin_unlock_irqrestore(&sesslock, flags);
+-	return shost;
+-
+-remove_host:
+-	scsi_remove_host(shost);
+-free_host:
+-	scsi_host_put(shost);
+-	return NULL;
+-}
+-
+-EXPORT_SYMBOL_GPL(iscsi_transport_create_session);
+-
+-/**
+- * iscsi_transport_destroy_session - destroy session and scsi host
+- * shost: scsi host
+- *
+- * This can be used by software iscsi_transports that allocate
+- * a session per scsi host.
+- **/
+-int iscsi_transport_destroy_session(struct Scsi_Host *shost)
+-{
+-	struct iscsi_cls_session *session;
+-	unsigned long flags;
+-
+-	session = hostdata_session(shost->hostdata);
+-	spin_lock_irqsave(&sesslock, flags);
+-	list_del(&session->sess_list);
+-	spin_unlock_irqrestore(&sesslock, flags);
+-	iscsi_destroy_session(session);
+-
+-	scsi_remove_host(shost);
+-	/* ref from host alloc */
+-	scsi_host_put(shost);
+-	return 0;
+-}
+-
+-EXPORT_SYMBOL_GPL(iscsi_transport_destroy_session);
+-
+ /*
+  * iscsi interface functions
+  */
+@@ -857,14 +757,19 @@ iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
+ {
+ 	struct iscsi_transport *transport = priv->iscsi_transport;
+ 	struct iscsi_cls_session *session;
++	unsigned long flags;
+ 	uint32_t hostno;
+ 
+-	session = transport->create_session(&priv->t,
++	session = transport->create_session(transport, &priv->t,
+ 					    ev->u.c_session.initial_cmdsn,
+ 					    &hostno);
+ 	if (!session)
+ 		return -ENOMEM;
+ 
++	spin_lock_irqsave(&sesslock, flags);
++	list_add(&session->sess_list, &sesslist);
++	spin_unlock_irqrestore(&sesslock, flags);
++
+ 	ev->r.c_session_ret.host_no = hostno;
+ 	ev->r.c_session_ret.sid = session->sid;
+ 	return 0;
+@@ -1032,6 +937,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 	struct iscsi_internal *priv;
+ 	struct iscsi_cls_session *session;
+ 	struct iscsi_cls_conn *conn;
++	unsigned long flags;
+ 
+ 	priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle));
+ 	if (!priv)
+@@ -1047,9 +953,13 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 		break;
+ 	case ISCSI_UEVENT_DESTROY_SESSION:
+ 		session = iscsi_session_lookup(ev->u.d_session.sid);
+-		if (session)
++		if (session) {
++			spin_lock_irqsave(&sesslock, flags);
++			list_del(&session->sess_list);
++			spin_unlock_irqrestore(&sesslock, flags);
++
+ 			transport->destroy_session(session);
+-		else
++		} else
+ 			err = -EINVAL;
+ 		break;
+ 	case ISCSI_UEVENT_CREATE_CONN:
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index eebe2b15161b..47524c726ee8 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -148,7 +148,8 @@ enum iscsi_err {
+ 	ISCSI_ERR_SESSION_FAILED	= ISCSI_ERR_BASE + 13,
+ 	ISCSI_ERR_HDR_DGST		= ISCSI_ERR_BASE + 14,
+ 	ISCSI_ERR_DATA_DGST		= ISCSI_ERR_BASE + 15,
+-	ISCSI_ERR_PARAM_NOT_FOUND	= ISCSI_ERR_BASE + 16
++	ISCSI_ERR_PARAM_NOT_FOUND	= ISCSI_ERR_BASE + 16,
++	ISCSI_ERR_NO_SCSI_CMD		= ISCSI_ERR_BASE + 17,
+ };
+ 
+ /*
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+new file mode 100644
+index 000000000000..830700a4ed69
+--- /dev/null
++++ b/include/scsi/libiscsi.h
+@@ -0,0 +1,286 @@
++/*
++ * iSCSI lib definitions
++ *
++ * Copyright (C) 2006 Red Hat, Inc.  All rights reserved.
++ * Copyright (C) 2004 - 2006 Mike Christie
++ * Copyright (C) 2004 - 2005 Dmitry Yusupov
++ * Copyright (C) 2004 - 2005 Alex Aizman
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++#ifndef LIBISCSI_H
++#define LIBISCSI_H
++
++#include 
++#include 
++#include 
++#include 
++
++struct scsi_transport_template;
++struct scsi_device;
++struct Scsi_Host;
++struct scsi_cmnd;
++struct socket;
++struct iscsi_transport;
++struct iscsi_cls_session;
++struct iscsi_cls_conn;
++struct iscsi_session;
++struct iscsi_nopin;
++
++/* #define DEBUG_SCSI */
++#ifdef DEBUG_SCSI
++#define debug_scsi(fmt...) printk(KERN_INFO "scsi: " fmt)
++#else
++#define debug_scsi(fmt...)
++#endif
++
++#define ISCSI_XMIT_CMDS_MAX	128	/* must be power of 2 */
++#define ISCSI_MGMT_CMDS_MAX	32	/* must be power of 2 */
++#define ISCSI_CONN_MAX			1
++
++#define ISCSI_MGMT_ITT_OFFSET	0xa00
++
++#define ISCSI_DEF_CMD_PER_LUN		32
++#define ISCSI_MAX_CMD_PER_LUN		128
++
++/* Task Mgmt states */
++#define TMABORT_INITIAL			0x0
++#define TMABORT_SUCCESS			0x1
++#define TMABORT_FAILED			0x2
++#define TMABORT_TIMEDOUT		0x3
++
++/* Connection suspend "bit" */
++#define ISCSI_SUSPEND_BIT		1
++
++#define ISCSI_ITT_MASK			(0xfff)
++#define ISCSI_CID_SHIFT			12
++#define ISCSI_CID_MASK			(0xffff << ISCSI_CID_SHIFT)
++#define ISCSI_AGE_SHIFT			28
++#define ISCSI_AGE_MASK			(0xf << ISCSI_AGE_SHIFT)
++
++struct iscsi_mgmt_task {
++	/*
++	 * Becuae LLDs allocate their hdr differently, this is a pointer to
++	 * that storage. It must be setup at session creation time.
++	 */
++	struct iscsi_hdr	*hdr;
++	char			*data;		/* mgmt payload */
++	int			data_count;	/* counts data to be sent */
++	uint32_t		itt;		/* this ITT */
++	void			*dd_data;	/* driver/transport data */
++	struct list_head	running;
++};
++
++struct iscsi_cmd_task {
++	/*
++	 * Becuae LLDs allocate their hdr differently, this is a pointer to
++	 * that storage. It must be setup at session creation time.
++	 */
++	struct iscsi_cmd	*hdr;
++	int			itt;		/* this ITT */
++	int			datasn;		/* DataSN */
++
++	uint32_t		unsol_datasn;
++	int			imm_count;	/* imm-data (bytes)   */
++	int			unsol_count;	/* unsolicited (bytes)*/
++	int			data_count;	/* remaining Data-Out */
++	struct scsi_cmnd	*sc;		/* associated SCSI cmd*/
++	int			total_length;
++	struct iscsi_conn	*conn;		/* used connection    */
++	struct iscsi_mgmt_task	*mtask;		/* tmf mtask in progr */
++
++	struct list_head	running;	/* running cmd list */
++	void			*dd_data;	/* driver/transport data */
++};
++
++struct iscsi_conn {
++	struct iscsi_cls_conn	*cls_conn;	/* ptr to class connection */
++	void			*dd_data;	/* iscsi_transport data */
++	struct iscsi_session	*session;	/* parent session */
++	/*
++	 * LLDs should set this lock. It protects the transport recv
++	 * code
++	 */
++	rwlock_t		*recv_lock;
++	/*
++	 * conn_stop() flag: stop to recover, stop to terminate
++	 */
++        int			stop_stage;
++
++	/* iSCSI connection-wide sequencing */
++	uint32_t		exp_statsn;
++
++	/* control data */
++	int			id;		/* CID */
++	struct list_head	item;		/* maintains list of conns */
++	int			c_stage;	/* connection state */
++	struct iscsi_mgmt_task	*login_mtask;	/* mtask used for login/text */
++	struct iscsi_mgmt_task	*mtask;		/* xmit mtask in progress */
++	struct iscsi_cmd_task	*ctask;		/* xmit ctask in progress */
++
++	/* xmit */
++	struct kfifo		*immqueue;	/* immediate xmit queue */
++	struct kfifo		*mgmtqueue;	/* mgmt (control) xmit queue */
++	struct list_head	mgmt_run_list;	/* list of control tasks */
++	struct kfifo		*xmitqueue;	/* data-path cmd queue */
++	struct list_head	run_list;	/* list of cmds in progress */
++	struct work_struct	xmitwork;	/* per-conn. xmit workqueue */
++	/*
++	 * serializes connection xmit, access to kfifos:
++	 * xmitqueue, immqueue, mgmtqueue
++	 */
++	struct mutex		xmitmutex;
++
++	unsigned long		suspend_tx;	/* suspend Tx */
++	unsigned long		suspend_rx;	/* suspend Rx */
++
++	/* abort */
++	wait_queue_head_t	ehwait;		/* used in eh_abort() */
++	struct iscsi_tm		tmhdr;
++	struct timer_list	tmabort_timer;
++	int			tmabort_state;	/* see TMABORT_INITIAL, etc.*/
++
++	/* negotiated params */
++	int			max_recv_dlength; /* initiator_max_recv_dsl*/
++	int			max_xmit_dlength; /* target_max_recv_dsl */
++	int			hdrdgst_en;
++	int			datadgst_en;
++
++	/* MIB-statistics */
++	uint64_t		txdata_octets;
++	uint64_t		rxdata_octets;
++	uint32_t		scsicmd_pdus_cnt;
++	uint32_t		dataout_pdus_cnt;
++	uint32_t		scsirsp_pdus_cnt;
++	uint32_t		datain_pdus_cnt;
++	uint32_t		r2t_pdus_cnt;
++	uint32_t		tmfcmd_pdus_cnt;
++	int32_t			tmfrsp_pdus_cnt;
++
++	/* custom statistics */
++	uint32_t		eh_abort_cnt;
++};
++
++struct iscsi_queue {
++	struct kfifo		*queue;		/* FIFO Queue */
++	void			**pool;		/* Pool of elements */
++	int			max;		/* Max number of elements */
++};
++
++struct iscsi_session {
++	/* iSCSI session-wide sequencing */
++	uint32_t		cmdsn;
++	uint32_t		exp_cmdsn;
++	uint32_t		max_cmdsn;
++
++	/* configuration */
++	int			initial_r2t_en;
++	int			max_r2t;
++	int			imm_data_en;
++	int			first_burst;
++	int			max_burst;
++	int			time2wait;
++	int			time2retain;
++	int			pdu_inorder_en;
++	int			dataseq_inorder_en;
++	int			erl;
++	int			ifmarker_en;
++	int			ofmarker_en;
++
++	/* control data */
++	struct iscsi_transport	*tt;
++	struct Scsi_Host	*host;
++	struct iscsi_conn	*leadconn;	/* leading connection */
++	spinlock_t		lock;		/* protects session state, *
++						 * sequence numbers,       *
++						 * session resources:      *
++						 * - cmdpool,		   *
++						 * - mgmtpool,		   *
++						 * - r2tpool		   */
++	int			state;		/* session state           */
++	int			recovery_failed;
++	struct list_head	item;
++	int			conn_cnt;
++	int			age;		/* counts session re-opens */
++
++	struct list_head	connections;	/* list of connections */
++	int			cmds_max;	/* size of cmds array */
++	struct iscsi_cmd_task	**cmds;		/* Original Cmds arr */
++	struct iscsi_queue	cmdpool;	/* PDU's pool */
++	int			mgmtpool_max;	/* size of mgmt array */
++	struct iscsi_mgmt_task	**mgmt_cmds;	/* Original mgmt arr */
++	struct iscsi_queue	mgmtpool;	/* Mgmt PDU's pool */
++};
++
++/*
++ * scsi host template
++ */
++extern int iscsi_change_queue_depth(struct scsi_device *sdev, int depth);
++extern int iscsi_eh_abort(struct scsi_cmnd *sc);
++extern int iscsi_eh_host_reset(struct scsi_cmnd *sc);
++extern int iscsi_queuecommand(struct scsi_cmnd *sc,
++			      void (*done)(struct scsi_cmnd *));
++
++/*
++ * session management
++ */
++extern struct iscsi_cls_session *
++iscsi_session_setup(struct iscsi_transport *, struct scsi_transport_template *,
++		    int, int, uint32_t, uint32_t *);
++extern void iscsi_session_teardown(struct iscsi_cls_session *);
++extern struct iscsi_session *class_to_transport_session(struct iscsi_cls_session *);
++extern void iscsi_start_session_recovery(struct iscsi_session *,
++					struct iscsi_conn *, int);
++extern void iscsi_session_recovery_timedout(struct iscsi_cls_session *);
++
++#define session_to_cls(_sess) \
++	hostdata_session(_sess->host->hostdata)
++
++/*
++ * connection management
++ */
++extern struct iscsi_cls_conn *iscsi_conn_setup(struct iscsi_cls_session *,
++					       uint32_t);
++extern void iscsi_conn_teardown(struct iscsi_cls_conn *);
++extern int iscsi_conn_start(struct iscsi_cls_conn *);
++extern void iscsi_conn_stop(struct iscsi_cls_conn *, int);
++extern int iscsi_conn_bind(struct iscsi_cls_session *, struct iscsi_cls_conn *,
++			   int);
++extern void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err);
++
++/*
++ * pdu and task processing
++ */
++extern int iscsi_check_assign_cmdsn(struct iscsi_session *,
++				    struct iscsi_nopin *);
++extern void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *,
++					struct iscsi_data *hdr,
++					int transport_data_cnt);
++extern int iscsi_conn_send_pdu(struct iscsi_cls_conn *, struct iscsi_hdr *,
++				char *, uint32_t);
++extern int iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *,
++			      char *, int);
++extern int __iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *,
++				char *, int);
++extern int iscsi_verify_itt(struct iscsi_conn *, struct iscsi_hdr *,
++			    uint32_t *);
++
++/*
++ * generic helpers
++ */
++extern void iscsi_pool_free(struct iscsi_queue *, void **);
++extern int iscsi_pool_init(struct iscsi_queue *, int, void ***, int);
++
++#endif
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 9d2b99159ee7..b332d6e839fe 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -2,7 +2,7 @@
+  * iSCSI transport class definitions
+  *
+  * Copyright (C) IBM Corporation, 2004
+- * Copyright (C) Mike Christie, 2004 - 2005
++ * Copyright (C) Mike Christie, 2004 - 2006
+  * Copyright (C) Dmitry Yusupov, 2004 - 2005
+  * Copyright (C) Alex Aizman, 2004 - 2005
+  *
+@@ -27,9 +27,13 @@
+ #include 
+ 
+ struct scsi_transport_template;
++struct iscsi_transport;
+ struct Scsi_Host;
+ struct mempool_zone;
+ struct iscsi_cls_conn;
++struct iscsi_conn;
++struct iscsi_cmd_task;
++struct iscsi_mgmt_task;
+ 
+ /**
+  * struct iscsi_transport - iSCSI Transport template
+@@ -46,6 +50,20 @@ struct iscsi_cls_conn;
+  * @start_conn:		set connection to be operational
+  * @stop_conn:		suspend/recover/terminate connection
+  * @send_pdu:		send iSCSI PDU, Login, Logout, NOP-Out, Reject, Text.
++ * @session_recovery_timedout: notify LLD a block during recovery timed out
++ * @suspend_conn_recv:	susepend the recv side of the connection
++ * @termincate_conn:	destroy socket connection. Called with mutex lock.
++ * @init_cmd_task:	Initialize a iscsi_cmd_task and any internal structs.
++ *			Called from queuecommand with session lock held.
++ * @init_mgmt_task:	Initialize a iscsi_mgmt_task and any internal structs.
++ *			Called from iscsi_conn_send_generic with xmitmutex.
++ * @xmit_cmd_task:	requests LLD to transfer cmd task
++ * @xmit_mgmt_task:	requests LLD to transfer mgmt task
++ * @cleanup_cmd_task:	requests LLD to fail cmd task. Called with xmitmutex
++ *			and session->lock after the connection has been
++ *			suspended and terminated during recovery. If called
++ *			from abort task then connection is not suspended
++ *			or terminated but sk_callback_lock is held
+  *
+  * Template API provided by iSCSI Transport
+  */
+@@ -56,8 +74,6 @@ struct iscsi_transport {
+ 	/* LLD sets this to indicate what values it can export to sysfs */
+ 	unsigned int param_mask;
+ 	struct scsi_host_template *host_template;
+-	/* LLD session/scsi_host data size */
+-	int hostdata_size;
+ 	/* LLD connection data size */
+ 	int conndata_size;
+ 	/* LLD session data size */
+@@ -65,8 +81,8 @@ struct iscsi_transport {
+ 	int max_lun;
+ 	unsigned int max_conn;
+ 	unsigned int max_cmd_len;
+-	struct iscsi_cls_session *(*create_session)
+-		(struct scsi_transport_template *t, uint32_t sn, uint32_t *hn);
++	struct iscsi_cls_session *(*create_session) (struct iscsi_transport *it,
++		struct scsi_transport_template *t, uint32_t sn, uint32_t *hn);
+ 	void (*destroy_session) (struct iscsi_cls_session *session);
+ 	struct iscsi_cls_conn *(*create_conn) (struct iscsi_cls_session *sess,
+ 				uint32_t cid);
+@@ -90,6 +106,18 @@ struct iscsi_transport {
+ 			 char *data, uint32_t data_size);
+ 	void (*get_stats) (struct iscsi_cls_conn *conn,
+ 			   struct iscsi_stats *stats);
++	void (*suspend_conn_recv) (struct iscsi_conn *conn);
++	void (*terminate_conn) (struct iscsi_conn *conn);
++	void (*init_cmd_task) (struct iscsi_cmd_task *ctask);
++	void (*init_mgmt_task) (struct iscsi_conn *conn,
++				struct iscsi_mgmt_task *mtask,
++				char *data, uint32_t data_size);
++	int (*xmit_cmd_task) (struct iscsi_conn *conn,
++			      struct iscsi_cmd_task *ctask);
++	void (*cleanup_cmd_task) (struct iscsi_conn *conn,
++				  struct iscsi_cmd_task *ctask);
++	int (*xmit_mgmt_task) (struct iscsi_conn *conn,
++			       struct iscsi_mgmt_task *mtask);
+ 	void (*session_recovery_timedout) (struct iscsi_cls_session *session);
+ };
+ 
+@@ -106,6 +134,13 @@ extern void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error);
+ extern int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
+ 			  char *data, uint32_t data_size);
+ 
++
++/* Connection's states */
++#define ISCSI_CONN_INITIAL_STAGE	0
++#define ISCSI_CONN_STARTED		1
++#define ISCSI_CONN_STOPPED		2
++#define ISCSI_CONN_CLEANUP_WAIT		3
++
+ struct iscsi_cls_conn {
+ 	struct list_head conn_list;	/* item in connlist */
+ 	void *dd_data;			/* LLD private data */
+@@ -129,6 +164,12 @@ struct iscsi_cls_conn {
+ #define iscsi_dev_to_conn(_dev) \
+ 	container_of(_dev, struct iscsi_cls_conn, dev)
+ 
++/* Session's states */
++#define ISCSI_STATE_FREE		1
++#define ISCSI_STATE_LOGGED_IN		2
++#define ISCSI_STATE_FAILED		3
++#define ISCSI_STATE_TERMINATE		4
++
+ struct iscsi_cls_session {
+ 	struct list_head sess_list;		/* item in session_list */
+ 	struct list_head host_list;
+@@ -174,12 +215,4 @@ extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn);
+ extern void iscsi_unblock_session(struct iscsi_cls_session *session);
+ extern void iscsi_block_session(struct iscsi_cls_session *session);
+ 
+-/*
+- * session functions used by software iscsi
+- */
+-extern struct Scsi_Host *
+-iscsi_transport_create_session(struct scsi_transport_template *scsit,
+-                               struct iscsi_transport *transport);
+-extern int iscsi_transport_destroy_session(struct Scsi_Host *shost);
+-
+ #endif

commit 30a6c65236f9d26e3325cae468f330b833a3878c
+Author: Mike Christie 
+Date:   Thu Apr 6 21:13:39 2006 -0500
+
+    [SCSI] iscsi: fix up iscsi eh
+    
+    The current iscsi_tcp eh is not nicely setup for dm-multipath
+    and performs some extra task management functions when they
+    are not needed.
+    
+    The attached patch:
+    
+    - Fixes the TMF issues. If a session is rebuilt
+    then we do not send aborts.
+    
+    - Fixes the problem where if the host reset fired, we would
+    return SUCCESS even though we had not really done anything
+    yet. This ends up causing problem with scsi_error.c's TUR.
+    
+    - If someone has turned on the userspace nop daemon code to try
+    and detect network problems before the scsi command timeout
+    we can now drop and clean up the session before the scsi command
+    timesout and fires the eh speeding up the time it takes for a
+    command to go from one patch to another. For network problems
+    we fail the command with DID_BUS_BUSY so if failfast is set
+    scsi_decide_disposition fails the command up to dm for it to
+    try on another path.
+    
+    - And we had to add some basic iscsi session block code. Previously
+    if we were trying to repair a session we would retrun a MLQUEUE code
+    in the queuecommand. This worked but it was not the most efficient
+    or pretty thing to do since it would take a while to relogin
+    to the target. For iscsi_tcp/open-iscsi a lot of the iscsi error handler
+    is in userspace the block code is pretty bare. We will be
+    adding to that for qla4xxx.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 6e510f3cfbf6..aca3e23b1b9e 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -82,6 +82,9 @@ module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
+ /* global data */
+ static kmem_cache_t *taskcache;
+ 
++#define session_to_cls(_sess) \
++	hostdata_session(_sess->host->hostdata)
++
+ static inline void
+ iscsi_buf_init_virt(struct iscsi_buf *ibuf, char *vbuf, int size)
+ {
+@@ -230,17 +233,19 @@ iscsi_hdr_extract(struct iscsi_conn *conn)
+ 	return 0;
+ }
+ 
+-static inline void
+-iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
++/*
++ * must be called with session lock
++ */
++static void
++__iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+-	struct scsi_cmnd *sc = ctask->sc;
+ 	struct iscsi_session *session = conn->session;
++	struct scsi_cmnd *sc;
+ 
+-	spin_lock(&session->lock);
+-	if (unlikely(!sc)) {
+-		spin_unlock(&session->lock);
++	sc = ctask->sc;
++	if (unlikely(!sc))
+ 		return;
+-	}
++
+ 	if (sc->sc_data_direction == DMA_TO_DEVICE) {
+ 		struct iscsi_data_task *dtask, *n;
+ 		/* WRITE: cleanup Data-Out's if any */
+@@ -252,7 +257,20 @@ iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	ctask->xmstate = XMSTATE_IDLE;
+ 	ctask->r2t = NULL;
+ 	ctask->sc = NULL;
++	list_del(&ctask->running);
++
+ 	__kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*));
++
++	sc->scsi_done(sc);
++}
++
++static void
++iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
++{
++	struct iscsi_session *session = conn->session;
++
++	spin_lock(&session->lock);
++	__iscsi_ctask_cleanup(conn, ctask);
+ 	spin_unlock(&session->lock);
+ }
+ 
+@@ -311,7 +329,6 @@ iscsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 		   (long)sc, sc->result, ctask->itt);
+ 	conn->scsirsp_pdus_cnt++;
+ 	iscsi_ctask_cleanup(conn, ctask);
+-	sc->scsi_done(sc);
+ 	return rc;
+ }
+ 
+@@ -395,6 +412,7 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 
+ 	dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC);
+ 	BUG_ON(!dtask);
++	INIT_LIST_HEAD(&dtask->item);
+ 	hdr = &dtask->hdr;
+ 	memset(hdr, 0, sizeof(struct iscsi_data));
+ 	hdr->ttt = r2t->ttt;
+@@ -710,8 +728,6 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
+ 			conn->tmfrsp_pdus_cnt++;
+ 			spin_lock(&session->lock);
+ 			if (conn->tmabort_state == TMABORT_INITIAL) {
+-				__kfifo_put(session->mgmtpool.queue,
+-						(void*)&mtask, sizeof(void*));
+ 				conn->tmabort_state =
+ 					((struct iscsi_tm_rsp *)hdr)->
+ 					response == ISCSI_TMF_RSP_COMPLETE ?
+@@ -986,7 +1002,6 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
+ 			   (long)sc, sc->result, ctask->itt);
+ 		conn->scsirsp_pdus_cnt++;
+ 		iscsi_ctask_cleanup(conn, ctask);
+-		sc->scsi_done(sc);
+ 	}
+ 
+ 	return rc;
+@@ -1460,6 +1475,7 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 
+ 	dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC);
+ 	BUG_ON(!dtask);
++	INIT_LIST_HEAD(&dtask->item);
+ 	hdr = &dtask->hdr;
+ 	memset(hdr, 0, sizeof(struct iscsi_data));
+ 	hdr->ttt = r2t->ttt;
+@@ -1506,6 +1522,7 @@ iscsi_unsolicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 
+ 	dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC);
+ 	BUG_ON(!dtask);
++	INIT_LIST_HEAD(&dtask->item);
+ 	hdr = &dtask->hdr;
+ 	memset(hdr, 0, sizeof(struct iscsi_data));
+ 	hdr->ttt = cpu_to_be32(ISCSI_RESERVED_TAG);
+@@ -1550,6 +1567,7 @@ iscsi_cmd_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 
+ 	BUG_ON(__kfifo_len(ctask->r2tqueue));
+ 
++	INIT_LIST_HEAD(&ctask->running);
+ 	ctask->sc = sc;
+ 	ctask->conn = conn;
+ 	ctask->hdr.opcode = ISCSI_OP_SCSI_CMD;
+@@ -1680,7 +1698,7 @@ iscsi_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
+ 		if (mtask->data_count)
+ 			mtask->xmstate |= XMSTATE_IMM_DATA;
+ 		if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE &&
+-	    	    conn->stop_stage != STOP_CONN_RECOVER &&
++		    conn->stop_stage != STOP_CONN_RECOVER &&
+ 		    conn->hdrdgst_en)
+ 			iscsi_hdr_digest(conn, &mtask->headbuf,
+ 					(u8*)mtask->hdrext);
+@@ -2226,6 +2244,7 @@ iscsi_data_xmit(struct iscsi_conn *conn)
+ 	/* process command queue */
+ 	while (__kfifo_get(conn->xmitqueue, (void*)&conn->ctask,
+ 			   sizeof(void*))) {
++		list_add_tail(&conn->ctask->running, &conn->run_list);
+ 		if (iscsi_ctask_xmit(conn, conn->ctask))
+ 			goto again;
+ 	}
+@@ -2277,11 +2296,14 @@ iscsi_xmitworker(void *data)
+ 	mutex_unlock(&conn->xmitmutex);
+ }
+ 
+-#define FAILURE_BAD_HOST		1
+-#define FAILURE_SESSION_FAILED		2
+-#define FAILURE_SESSION_FREED		3
+-#define FAILURE_WINDOW_CLOSED		4
+-#define FAILURE_SESSION_TERMINATE	5
++enum {
++	FAILURE_BAD_HOST = 1,
++	FAILURE_SESSION_FAILED,
++	FAILURE_SESSION_FREED,
++	FAILURE_WINDOW_CLOSED,
++	FAILURE_SESSION_TERMINATE,
++	FAILURE_SESSION_RECOVERY_TIMEOUT,
++};
+ 
+ static int
+ iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+@@ -2297,12 +2319,14 @@ iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 
+ 	host = sc->device->host;
+ 	session = iscsi_hostdata(host->hostdata);
+-	BUG_ON(host != session->host);
+ 
+ 	spin_lock(&session->lock);
+ 
+ 	if (session->state != ISCSI_STATE_LOGGED_IN) {
+-		if (session->state == ISCSI_STATE_FAILED) {
++		if (session->recovery_failed) {
++			reason = FAILURE_SESSION_RECOVERY_TIMEOUT;
++			goto fault;
++		} else if (session->state == ISCSI_STATE_FAILED) {
+ 			reason = FAILURE_SESSION_FAILED;
+ 			goto reject;
+ 		} else if (session->state == ISCSI_STATE_TERMINATE) {
+@@ -2350,11 +2374,6 @@ iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 	spin_unlock(&session->lock);
+ 	printk(KERN_ERR "iscsi_tcp: cmd 0x%x is not queued (%d)\n",
+ 	       sc->cmnd[0], reason);
+-	sc->sense_buffer[0] = 0x70;
+-	sc->sense_buffer[2] = NOT_READY;
+-	sc->sense_buffer[7] = 0x6;
+-	sc->sense_buffer[12] = 0x08;
+-	sc->sense_buffer[13] = 0x00;
+ 	sc->result = (DID_NO_CONNECT << 16);
+ 	sc->resid = sc->request_bufflen;
+ 	sc->scsi_done(sc);
+@@ -2445,6 +2464,7 @@ iscsi_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ 	conn->id = conn_idx;
+ 	conn->exp_statsn = 0;
+ 	conn->tmabort_state = TMABORT_INITIAL;
++	INIT_LIST_HEAD(&conn->run_list);
+ 
+ 	/* initial operational parameters */
+ 	conn->hdr_size = sizeof(struct iscsi_hdr);
+@@ -2701,6 +2721,22 @@ iscsi_conn_bind(struct iscsi_cls_session *cls_session,
+ 	return 0;
+ }
+ 
++static void
++iscsi_session_recovery_timedout(struct iscsi_cls_session *csession)
++{
++	struct Scsi_Host *shost = iscsi_session_to_shost(csession);
++	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
++	struct iscsi_conn *conn = session->leadconn;
++
++	spin_lock_bh(&session->lock);
++	if (session->state != ISCSI_STATE_LOGGED_IN) {
++		session->recovery_failed = 1;
++		if (conn)
++			wake_up(&conn->ehwait);
++	}
++	spin_unlock_bh(&session->lock);
++}
++
+ static int
+ iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
+ {
+@@ -2716,7 +2752,6 @@ iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
+ 	}
+ 
+ 	sk = conn->sock->sk;
+-
+ 	write_lock_bh(&sk->sk_callback_lock);
+ 	spin_lock_bh(&session->lock);
+ 	conn->c_stage = ISCSI_CONN_STARTED;
+@@ -2732,8 +2767,13 @@ iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
+ 		conn->stop_stage = 0;
+ 		conn->tmabort_state = TMABORT_INITIAL;
+ 		session->age++;
++		session->recovery_failed = 0;
++		spin_unlock_bh(&session->lock);
++		write_unlock_bh(&sk->sk_callback_lock);
++
++		iscsi_unblock_session(session_to_cls(session));
+ 		wake_up(&conn->ehwait);
+-		break;
++		return 0;
+ 	case STOP_CONN_TERM:
+ 		session->conn_cnt++;
+ 		conn->stop_stage = 0;
+@@ -2752,105 +2792,199 @@ iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
+ 	return 0;
+ }
+ 
+-static void
+-iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
++static int
++iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask)
+ {
+-	struct iscsi_conn *conn = cls_conn->dd_data;
++	struct iscsi_conn *conn = ctask->conn;
+ 	struct iscsi_session *session = conn->session;
++	struct iscsi_mgmt_task *mtask;
++
++	if (!ctask->mtask)
++		return -EINVAL;
++
++	while (__kfifo_get(conn->immqueue, (void*)&mtask, sizeof(void*))) {
++		if (mtask == ctask->mtask)
++			break;
++		__kfifo_put(conn->immqueue, (void*)&mtask, sizeof(void*));
++	}
++
++	__kfifo_put(session->mgmtpool.queue, (void*)&ctask->mtask,
++		    sizeof(void*));
++	ctask->mtask = NULL;
++	return 0;
++}
++
++static void
++fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, int err)
++{
++	struct iscsi_r2t_info *r2t;
++	struct scsi_cmnd *sc;
++
++	/* flush ctask's r2t queues */
++	while (__kfifo_get(ctask->r2tqueue, (void*)&r2t, sizeof(void*)))
++		__kfifo_put(ctask->r2tpool.queue, (void*)&r2t, sizeof(void*));
++
++	iscsi_ctask_mtask_cleanup(ctask);
++
++	sc = ctask->sc;
++	if (!sc)
++		return;
++
++	sc->result = err;
++	sc->resid = sc->request_bufflen;
++
++	__iscsi_ctask_cleanup(conn, ctask);
++}
++
++/* Fail commands. Mutex and session lock held */
++static void
++fail_all_commands(struct iscsi_session *session, struct iscsi_conn *conn)
++{
++	struct iscsi_cmd_task *ctask, *tmp;
++
++	/* flush pending */
++	while (__kfifo_get(conn->xmitqueue, (void*)&ctask, sizeof(void*))) {
++		debug_scsi("failing pending sc %p itt 0x%x\n", ctask->sc,
++			   ctask->itt);
++		fail_command(conn, ctask, DID_BUS_BUSY << 16);
++	}
++
++	/* fail running */
++	list_for_each_entry_safe(ctask, tmp, &conn->run_list, running) {
++		debug_scsi("failing in progress sc %p itt 0x%x\n",
++			   ctask->sc, ctask->itt);
++		fail_command(conn, ctask, DID_BUS_BUSY << 16);
++	}
++
++	conn->ctask = NULL;
++}
++
++static void
++flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn)
++{
++	struct iscsi_mgmt_task *mtask;
++
++	/* TODO: handle running pdus */
++	while (__kfifo_get(conn->immqueue, (void*)&mtask, sizeof(void*)) ||
++	       __kfifo_get(conn->mgmtqueue, (void*)&mtask, sizeof(void*))) {
++		if (mtask == conn->login_mtask)
++			continue;
++		__kfifo_put(session->mgmtpool.queue, (void*)&mtask,
++			    sizeof(void*));
++	}
++
++	if (conn->mtask && conn->mtask != conn->login_mtask)
++		__kfifo_put(session->mgmtpool.queue, (void*)&conn->mtask,
++			    sizeof(void*));
++	conn->mtask = NULL;
++}
++
++static void
++iscsi_suspend_conn_rx(struct iscsi_conn *conn)
++{
+ 	struct sock *sk;
+-	unsigned long flags;
+ 
+ 	BUG_ON(!conn->sock);
+ 	sk = conn->sock->sk;
+ 	write_lock_bh(&sk->sk_callback_lock);
+ 	set_bit(SUSPEND_BIT, &conn->suspend_rx);
+ 	write_unlock_bh(&sk->sk_callback_lock);
++}
+ 
+-	mutex_lock(&conn->xmitmutex);
+-
+-	spin_lock_irqsave(session->host->host_lock, flags);
+-	spin_lock(&session->lock);
++static void
++iscsi_start_session_recovery(struct iscsi_session *session,
++			     struct iscsi_conn *conn, int flag)
++{
++	spin_lock_bh(&session->lock);
++	if (conn->stop_stage == STOP_CONN_RECOVER ||
++	    conn->stop_stage == STOP_CONN_TERM) {
++		spin_unlock_bh(&session->lock);
++		return;
++	}
+ 	conn->stop_stage = flag;
++	spin_unlock_bh(&session->lock);
++
++	iscsi_suspend_conn_rx(conn);
++
++	mutex_lock(&conn->xmitmutex);
++	spin_lock_bh(&session->lock);
+ 	conn->c_stage = ISCSI_CONN_STOPPED;
+ 	set_bit(SUSPEND_BIT, &conn->suspend_tx);
+ 
+-	if (flag != STOP_CONN_SUSPEND)
+-		session->conn_cnt--;
+-
++	session->conn_cnt--;
+ 	if (session->conn_cnt == 0 || session->leadconn == conn)
+ 		session->state = ISCSI_STATE_FAILED;
+ 
+-	spin_unlock(&session->lock);
+-	spin_unlock_irqrestore(session->host->host_lock, flags);
+-
+-	if (flag == STOP_CONN_TERM || flag == STOP_CONN_RECOVER) {
+-		struct iscsi_cmd_task *ctask;
+-		struct iscsi_mgmt_task *mtask;
++	spin_unlock_bh(&session->lock);
+ 
+-		/*
+-		 * Socket must go now.
+-		 */
+-		sock_hold(conn->sock->sk);
+-		iscsi_conn_restore_callbacks(conn);
+-		sock_put(conn->sock->sk);
++	/*
++	 * Socket must go now.
++	 */
++	sock_hold(conn->sock->sk);
++	iscsi_conn_restore_callbacks(conn);
++	sock_put(conn->sock->sk);
+ 
+-		/*
+-		 * flush xmit queues.
+-		 */
+-		spin_lock_bh(&session->lock);
+-		while (__kfifo_get(conn->writequeue, (void*)&ctask,
+-			    sizeof(void*)) ||
+-			__kfifo_get(conn->xmitqueue, (void*)&ctask,
+-			    sizeof(void*))) {
+-			struct iscsi_r2t_info *r2t;
+-
+-			/*
+-			 * flush ctask's r2t queues
+-			 */
+-			while (__kfifo_get(ctask->r2tqueue, (void*)&r2t,
+-				sizeof(void*)))
+-				__kfifo_put(ctask->r2tpool.queue, (void*)&r2t,
+-					    sizeof(void*));
++	/*
++	 * flush queues.
++	 */
++	spin_lock_bh(&session->lock);
++	fail_all_commands(session, conn);
++	flush_control_queues(session, conn);
++	spin_unlock_bh(&session->lock);
+ 
+-			spin_unlock_bh(&session->lock);
+-			local_bh_disable();
+-			iscsi_ctask_cleanup(conn, ctask);
+-			local_bh_enable();
+-			spin_lock_bh(&session->lock);
+-		}
+-		conn->ctask = NULL;
+-		while (__kfifo_get(conn->immqueue, (void*)&mtask,
+-			   sizeof(void*)) ||
+-			__kfifo_get(conn->mgmtqueue, (void*)&mtask,
+-			   sizeof(void*))) {
+-			__kfifo_put(session->mgmtpool.queue,
+-				    (void*)&mtask, sizeof(void*));
+-		}
+-		conn->mtask = NULL;
+-		spin_unlock_bh(&session->lock);
++	/*
++	 * release socket only after we stopped data_xmit()
++	 * activity and flushed all outstandings
++	 */
++	sock_release(conn->sock);
++	conn->sock = NULL;
+ 
+-		/*
+-		 * release socket only after we stopped data_xmit()
+-		 * activity and flushed all outstandings
+-		 */
+-		sock_release(conn->sock);
+-		conn->sock = NULL;
++	/*
++	 * for connection level recovery we should not calculate
++	 * header digest. conn->hdr_size used for optimization
++	 * in hdr_extract() and will be re-negotiated at
++	 * set_param() time.
++	 */
++	if (flag == STOP_CONN_RECOVER) {
++		conn->hdr_size = sizeof(struct iscsi_hdr);
++		conn->hdrdgst_en = 0;
++		conn->datadgst_en = 0;
+ 
+-		/*
+-		 * for connection level recovery we should not calculate
+-		 * header digest. conn->hdr_size used for optimization
+-		 * in hdr_extract() and will be re-negotiated at
+-		 * set_param() time.
+-		 */
+-		if (flag == STOP_CONN_RECOVER) {
+-			conn->hdr_size = sizeof(struct iscsi_hdr);
+-			conn->hdrdgst_en = 0;
+-			conn->datadgst_en = 0;
+-		}
++		if (session->state == ISCSI_STATE_FAILED)
++			iscsi_block_session(session_to_cls(session));
+ 	}
+ 	mutex_unlock(&conn->xmitmutex);
+ }
+ 
++static void
++iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
++{
++	struct iscsi_conn *conn = cls_conn->dd_data;
++	struct iscsi_session *session = conn->session;
++
++	switch (flag) {
++	case STOP_CONN_RECOVER:
++	case STOP_CONN_TERM:
++		iscsi_start_session_recovery(session, conn, flag);
++		return;
++	case STOP_CONN_SUSPEND:
++		iscsi_suspend_conn_rx(conn);
++
++		mutex_lock(&conn->xmitmutex);
++		spin_lock_bh(&session->lock);
++
++		conn->stop_stage = flag;
++		conn->c_stage = ISCSI_CONN_STOPPED;
++		set_bit(SUSPEND_BIT, &conn->suspend_tx);
++
++		spin_unlock_bh(&session->lock);
++		mutex_unlock(&conn->xmitmutex);
++		break;
++	default:
++		printk(KERN_ERR "invalid stop flag %d\n", flag);
++	}
++}
++
+ static int
+ iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 			char *data, uint32_t data_size)
+@@ -2940,23 +3074,54 @@ iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ static int
+ iscsi_eh_host_reset(struct scsi_cmnd *sc)
+ {
+-	struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr;
+-	struct iscsi_conn *conn = ctask->conn;
+-	struct iscsi_session *session = conn->session;
++	struct Scsi_Host *host = sc->device->host;
++	struct iscsi_session *session = iscsi_hostdata(host->hostdata);
++	struct iscsi_conn *conn = session->leadconn;
++	int fail_session = 0;
+ 
+ 	spin_lock_bh(&session->lock);
+ 	if (session->state == ISCSI_STATE_TERMINATE) {
++failed:
+ 		debug_scsi("failing host reset: session terminated "
+ 			   "[CID %d age %d]", conn->id, session->age);
+ 		spin_unlock_bh(&session->lock);
+ 		return FAILED;
+ 	}
++
++	if (sc->SCp.phase == session->age) {
++		debug_scsi("failing connection CID %d due to SCSI host reset",
++			   conn->id);
++		fail_session = 1;
++	}
+ 	spin_unlock_bh(&session->lock);
+ 
+-	debug_scsi("failing connection CID %d due to SCSI host reset "
+-		   "[itt 0x%x age %d]", conn->id, ctask->itt,
+-		   session->age);
+-	iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
++	/*
++	 * we drop the lock here but the leadconn cannot be destoyed while
++	 * we are in the scsi eh
++	 */
++	if (fail_session) {
++		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
++		/*
++		 * if userspace cannot respond then we must kick this off
++		 * here for it
++		 */
++		iscsi_start_session_recovery(session, conn, STOP_CONN_RECOVER);
++	}
++
++	debug_scsi("iscsi_eh_host_reset wait for relogin\n");
++	wait_event_interruptible(conn->ehwait,
++				 session->state == ISCSI_STATE_TERMINATE ||
++				 session->state == ISCSI_STATE_LOGGED_IN ||
++				 session->recovery_failed);
++	if (signal_pending(current))
++		flush_signals(current);
++
++	spin_lock_bh(&session->lock);
++	if (session->state == ISCSI_STATE_LOGGED_IN)
++		printk(KERN_INFO "host reset succeeded\n");
++	else
++		goto failed;
++	spin_unlock_bh(&session->lock);
+ 
+ 	return SUCCESS;
+ }
+@@ -2970,8 +3135,6 @@ iscsi_tmabort_timedout(unsigned long data)
+ 
+ 	spin_lock(&session->lock);
+ 	if (conn->tmabort_state == TMABORT_INITIAL) {
+-		__kfifo_put(session->mgmtpool.queue,
+-				(void*)&ctask->mtask, sizeof(void*));
+ 		conn->tmabort_state = TMABORT_TIMEDOUT;
+ 		debug_scsi("tmabort timedout [sc %lx itt 0x%x]\n",
+ 			(long)ctask->sc, ctask->itt);
+@@ -2981,186 +3144,163 @@ iscsi_tmabort_timedout(unsigned long data)
+ 	spin_unlock(&session->lock);
+ }
+ 
++/* must be called with the mutex lock */
+ static int
+-iscsi_eh_abort(struct scsi_cmnd *sc)
++iscsi_exec_abort_task(struct scsi_cmnd *sc, struct iscsi_cmd_task *ctask)
+ {
+-	int rc;
+-	struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr;
+ 	struct iscsi_conn *conn = ctask->conn;
+ 	struct iscsi_session *session = conn->session;
+-
+-	conn->eh_abort_cnt++;
+-	debug_scsi("aborting [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
++	struct iscsi_tm *hdr = &conn->tmhdr;
++	int rc;
+ 
+ 	/*
+-	 * two cases for ERL=0 here:
+-	 *
+-	 * 1) connection-level failure;
+-	 * 2) recovery due protocol error;
++	 * ctask timed out but session is OK requests must be serialized.
+ 	 */
+-	mutex_lock(&conn->xmitmutex);
+-	spin_lock_bh(&session->lock);
+-	if (session->state != ISCSI_STATE_LOGGED_IN) {
+-		if (session->state == ISCSI_STATE_TERMINATE) {
+-			spin_unlock_bh(&session->lock);
+-			mutex_unlock(&conn->xmitmutex);
+-			goto failed;
+-		}
+-		spin_unlock_bh(&session->lock);
+-	} else {
+-		struct iscsi_tm *hdr = &conn->tmhdr;
++	memset(hdr, 0, sizeof(struct iscsi_tm));
++	hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE;
++	hdr->flags = ISCSI_TM_FUNC_ABORT_TASK;
++	hdr->flags |= ISCSI_FLAG_CMD_FINAL;
++	memcpy(hdr->lun, ctask->hdr.lun, sizeof(hdr->lun));
++	hdr->rtt = ctask->hdr.itt;
++	hdr->refcmdsn = ctask->hdr.cmdsn;
+ 
+-		/*
+-		 * Still LOGGED_IN...
+-		 */
++	rc = iscsi_conn_send_generic(conn, (struct iscsi_hdr *)hdr,
++				     NULL, 0);
++	if (rc) {
++		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
++		debug_scsi("abort sent failure [itt 0x%x] %d", ctask->itt, rc);
++		return rc;
++	}
+ 
+-		if (!ctask->sc || sc->SCp.phase != session->age) {
+-			/*
+-			 * 1) ctask completed before time out. But session
+-			 *    is still ok => Happy Retry.
+-			 * 2) session was re-open during time out of ctask.
+-			 */
+-			spin_unlock_bh(&session->lock);
+-			mutex_unlock(&conn->xmitmutex);
+-			goto success;
+-		}
+-		conn->tmabort_state = TMABORT_INITIAL;
+-		spin_unlock_bh(&session->lock);
++	debug_scsi("abort sent [itt 0x%x]\n", ctask->itt);
+ 
+-		/*
+-		 * ctask timed out but session is OK
+-		 * ERL=0 requires task mgmt abort to be issued on each
+-		 * failed command. requests must be serialized.
+-		 */
+-		memset(hdr, 0, sizeof(struct iscsi_tm));
+-		hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE;
+-		hdr->flags = ISCSI_TM_FUNC_ABORT_TASK;
+-		hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+-		memcpy(hdr->lun, ctask->hdr.lun, sizeof(hdr->lun));
+-		hdr->rtt = ctask->hdr.itt;
+-		hdr->refcmdsn = ctask->hdr.cmdsn;
+-
+-		rc = iscsi_conn_send_generic(conn, (struct iscsi_hdr *)hdr,
+-					     NULL, 0);
+-		if (rc) {
+-			iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+-			debug_scsi("abort sent failure [itt 0x%x]", ctask->itt);
+-		} else {
+-			struct iscsi_r2t_info *r2t;
+-
+-			/*
+-			 * TMF abort vs. TMF response race logic
+-			 */
+-			spin_lock_bh(&session->lock);
+-			ctask->mtask = (struct iscsi_mgmt_task *)
+-				session->mgmt_cmds[(hdr->itt & ITT_MASK) -
+-							ISCSI_MGMT_ITT_OFFSET];
+-			/*
+-			 * have to flush r2tqueue to avoid r2t leaks
+-			 */
+-			while (__kfifo_get(ctask->r2tqueue, (void*)&r2t,
+-				sizeof(void*))) {
+-				__kfifo_put(ctask->r2tpool.queue, (void*)&r2t,
+-					sizeof(void*));
+-			}
+-			if (conn->tmabort_state == TMABORT_INITIAL) {
+-				conn->tmfcmd_pdus_cnt++;
+-				conn->tmabort_timer.expires = 3*HZ + jiffies;
+-				conn->tmabort_timer.function =
+-						iscsi_tmabort_timedout;
+-				conn->tmabort_timer.data = (unsigned long)ctask;
+-				add_timer(&conn->tmabort_timer);
+-				debug_scsi("abort sent [itt 0x%x]", ctask->itt);
+-			} else {
+-				if (!ctask->sc ||
+-				    conn->tmabort_state == TMABORT_SUCCESS) {
+-					conn->tmabort_state = TMABORT_INITIAL;
+-					spin_unlock_bh(&session->lock);
+-					mutex_unlock(&conn->xmitmutex);
+-					goto success;
+-				}
+-				conn->tmabort_state = TMABORT_INITIAL;
+-				iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+-			}
+-			spin_unlock_bh(&session->lock);
+-		}
++	spin_lock_bh(&session->lock);
++	ctask->mtask = (struct iscsi_mgmt_task *)
++			session->mgmt_cmds[(hdr->itt & ITT_MASK) -
++					ISCSI_MGMT_ITT_OFFSET];
++
++	if (conn->tmabort_state == TMABORT_INITIAL) {
++		conn->tmfcmd_pdus_cnt++;
++		conn->tmabort_timer.expires = 10*HZ + jiffies;
++		conn->tmabort_timer.function = iscsi_tmabort_timedout;
++		conn->tmabort_timer.data = (unsigned long)ctask;
++		add_timer(&conn->tmabort_timer);
++		debug_scsi("abort set timeout [itt 0x%x]", ctask->itt);
+ 	}
++	spin_unlock_bh(&session->lock);
+ 	mutex_unlock(&conn->xmitmutex);
+ 
+-
+ 	/*
+ 	 * block eh thread until:
+ 	 *
+-	 * 1) abort response;
+-	 * 2) abort timeout;
+-	 * 3) session re-opened;
+-	 * 4) session terminated;
++	 * 1) abort response
++	 * 2) abort timeout
++	 * 3) session is terminated or restarted or userspace has
++	 * given up on recovery
+ 	 */
+-	for (;;) {
+-		int p_state = session->state;
+-
+-		rc = wait_event_interruptible(conn->ehwait,
+-			(p_state == ISCSI_STATE_LOGGED_IN ?
+-			 (session->state == ISCSI_STATE_TERMINATE ||
+-			  conn->tmabort_state != TMABORT_INITIAL) :
+-			 (session->state == ISCSI_STATE_TERMINATE ||
+-			  session->state == ISCSI_STATE_LOGGED_IN)));
+-		if (rc) {
+-			/* shutdown.. */
+-			session->state = ISCSI_STATE_TERMINATE;
+-			goto failed;
+-		}
++	wait_event_interruptible(conn->ehwait,
++				 sc->SCp.phase != session->age ||
++				 session->state != ISCSI_STATE_LOGGED_IN ||
++				 conn->tmabort_state != TMABORT_INITIAL ||
++				 session->recovery_failed);
++	if (signal_pending(current))
++		flush_signals(current);
++	del_timer_sync(&conn->tmabort_timer);
+ 
+-		if (signal_pending(current))
+-			flush_signals(current);
++	mutex_lock(&conn->xmitmutex);
++	return 0;
++}
+ 
+-		if (session->state == ISCSI_STATE_TERMINATE)
+-			goto failed;
++static int
++iscsi_eh_abort(struct scsi_cmnd *sc)
++{
++	struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr;
++	struct iscsi_cmd_task *tmp_ctask;
++	struct iscsi_conn *conn = ctask->conn;
++	struct iscsi_session *session = conn->session;
++	int rc;
+ 
+-		spin_lock_bh(&session->lock);
+-		if (sc->SCp.phase == session->age &&
+-		   (conn->tmabort_state == TMABORT_TIMEDOUT ||
+-		    conn->tmabort_state == TMABORT_FAILED)) {
+-			conn->tmabort_state = TMABORT_INITIAL;
+-			if (!ctask->sc) {
+-				/*
+-				 * ctask completed before tmf abort response or
+-				 * time out.
+-				 * But session is still ok => Happy Retry.
+-				 */
+-				spin_unlock_bh(&session->lock);
+-				break;
+-			}
+-			spin_unlock_bh(&session->lock);
+-			iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+-			continue;
++	conn->eh_abort_cnt++;
++	debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt);
++
++	mutex_lock(&conn->xmitmutex);
++	spin_lock_bh(&session->lock);
++
++	/*
++	 * If we are not logged in or we have started a new session
++	 * then let the host reset code handle this
++	 */
++	if (session->state != ISCSI_STATE_LOGGED_IN ||
++	    sc->SCp.phase != session->age)
++		goto failed;
++
++	/* ctask completed before time out */
++	if (!ctask->sc)
++		goto success;
++
++	/* what should we do here ? */
++	if (conn->ctask == ctask) {
++		printk(KERN_INFO "sc %p itt 0x%x partially sent. Failing "
++		       "abort\n", sc, ctask->itt);
++		goto failed;
++	}
++
++	/* check for the easy pending cmd abort */
++	while (__kfifo_get(conn->xmitqueue, (void*)&tmp_ctask, sizeof(void*))) {
++		if (tmp_ctask->itt == ctask->itt) {
++			debug_scsi("found pending task\n");
++			goto success;
+ 		}
++		__kfifo_put(conn->xmitqueue, (void*)&tmp_ctask, sizeof(void*));
++	}
++
++	conn->tmabort_state = TMABORT_INITIAL;
++
++	spin_unlock_bh(&session->lock);
++	rc = iscsi_exec_abort_task(sc, ctask);
++	spin_lock_bh(&session->lock);
++
++	iscsi_ctask_mtask_cleanup(ctask);
++	if (rc || sc->SCp.phase != session->age ||
++	    session->state != ISCSI_STATE_LOGGED_IN)
++		goto failed;
++
++	/* ctask completed before tmf abort response */
++	if (!ctask->sc) {
++		debug_scsi("sc completed while abort in progress\n");
++		goto success;
++	}
++
++	if (conn->tmabort_state != TMABORT_SUCCESS) {
+ 		spin_unlock_bh(&session->lock);
+-		break;
++		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
++		spin_lock_bh(&session->lock);
++		goto failed;
+ 	}
+ 
+ success:
+ 	debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
+-	rc = SUCCESS;
+-	goto exit;
+-
+-failed:
+-	debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
+-	rc = FAILED;
+-
+-exit:
+-	del_timer_sync(&conn->tmabort_timer);
++	spin_unlock_bh(&session->lock);
+ 
+-	mutex_lock(&conn->xmitmutex);
++	/* clean up task if aborted */
+ 	if (conn->sock) {
+ 		struct sock *sk = conn->sock->sk;
+ 
+ 		write_lock_bh(&sk->sk_callback_lock);
+-		iscsi_ctask_cleanup(conn, ctask);
++		spin_lock(&session->lock);
++		fail_command(conn, ctask, DRIVER_TIMEOUT << 24);
++		spin_unlock(&session->lock);
+ 		write_unlock_bh(&sk->sk_callback_lock);
+ 	}
+ 	mutex_unlock(&conn->xmitmutex);
+-	return rc;
++	return SUCCESS;
++
++failed:
++	spin_unlock_bh(&session->lock);
++	mutex_unlock(&conn->xmitmutex);
++
++	debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
++	return FAILED;
+ }
+ 
+ static int
+@@ -3359,16 +3499,6 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	struct iscsi_session *session = conn->session;
+ 
+-	spin_lock_bh(&session->lock);
+-	if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE &&
+-	    conn->stop_stage != STOP_CONN_RECOVER) {
+-		printk(KERN_ERR "iscsi_tcp: can not change parameter [%d]\n",
+-		       param);
+-		spin_unlock_bh(&session->lock);
+-		return 0;
+-	}
+-	spin_unlock_bh(&session->lock);
+-
+ 	switch(param) {
+ 	case ISCSI_PARAM_MAX_RECV_DLENGTH: {
+ 		char *saveptr = conn->data;
+@@ -3691,6 +3821,7 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 	.stop_conn		= iscsi_conn_stop,
+ 	.send_pdu		= iscsi_conn_send_pdu,
+ 	.get_stats		= iscsi_conn_get_stats,
++	.session_recovery_timedout = iscsi_session_recovery_timedout,
+ };
+ 
+ static int __init
+diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
+index ba26741ac154..12ef64179b4c 100644
+--- a/drivers/scsi/iscsi_tcp.h
++++ b/drivers/scsi/iscsi_tcp.h
+@@ -159,6 +159,7 @@ struct iscsi_conn {
+ 	struct kfifo		*immqueue;	/* immediate xmit queue */
+ 	struct kfifo		*mgmtqueue;	/* mgmt (control) xmit queue */
+ 	struct kfifo		*xmitqueue;	/* data-path cmd queue */
++	struct list_head	run_list;	/* list of cmds in progress */
+ 	struct work_struct	xmitwork;	/* per-conn. xmit workqueue */
+ 	struct mutex		xmitmutex;	/* serializes connection xmit,
+ 						 * access to kfifos:	  *
+@@ -228,6 +229,7 @@ struct iscsi_session {
+ 						 * - mgmtpool,		   *
+ 						 * - r2tpool		   */
+ 	int			state;		/* session state           */
++	int			recovery_failed;
+ 	struct list_head	item;
+ 	void			*auth_client;
+ 	int			conn_cnt;
+@@ -310,6 +312,7 @@ struct iscsi_cmd_task {
+ 	struct iscsi_conn	*conn;			/* used connection    */
+ 	struct iscsi_mgmt_task	*mtask;			/* tmf mtask in progr */
+ 
++	struct list_head	running;		/* running cmd list */
+ 	struct iscsi_r2t_info	*r2t;			/* in progress R2T    */
+ 	struct iscsi_queue	r2tpool;
+ 	struct kfifo		*r2tqueue;
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 72a71ebc9d03..e2b67e34d92e 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -31,17 +31,17 @@
+ #include 
+ #include 
+ 
+-#define ISCSI_SESSION_ATTRS 10
++#define ISCSI_SESSION_ATTRS 11
+ #define ISCSI_CONN_ATTRS 10
++#define ISCSI_HOST_ATTRS 0
+ 
+ struct iscsi_internal {
+ 	struct scsi_transport_template t;
+ 	struct iscsi_transport *iscsi_transport;
+ 	struct list_head list;
+ 	struct class_device cdev;
+-	/*
+-	 * We do not have any private or other attrs.
+-	 */
++
++	struct class_device_attribute *host_attrs[ISCSI_HOST_ATTRS + 1];
+ 	struct transport_container conn_cont;
+ 	struct class_device_attribute *conn_attrs[ISCSI_CONN_ATTRS + 1];
+ 	struct transport_container session_cont;
+@@ -114,6 +114,24 @@ static struct attribute_group iscsi_transport_group = {
+ 	.attrs = iscsi_transport_attrs,
+ };
+ 
++static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
++			    struct class_device *cdev)
++{
++	struct Scsi_Host *shost = dev_to_shost(dev);
++	struct iscsi_host *ihost = shost->shost_data;
++
++	memset(ihost, 0, sizeof(*ihost));
++	INIT_LIST_HEAD(&ihost->sessions);
++	mutex_init(&ihost->mutex);
++	return 0;
++}
++
++static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
++			       "iscsi_host",
++			       iscsi_setup_host,
++			       NULL,
++			       NULL);
++
+ static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
+ 			       "iscsi_session",
+ 			       NULL,
+@@ -225,6 +243,54 @@ static int iscsi_is_session_dev(const struct device *dev)
+ 	return dev->release == iscsi_session_release;
+ }
+ 
++static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
++			   uint id, uint lun)
++{
++	struct iscsi_host *ihost = shost->shost_data;
++	struct iscsi_cls_session *session;
++
++	mutex_lock(&ihost->mutex);
++	list_for_each_entry(session, &ihost->sessions, host_list) {
++		if ((channel == SCAN_WILD_CARD ||
++		     channel == session->channel) &&
++		    (id == SCAN_WILD_CARD || id == session->target_id))
++			scsi_scan_target(&session->dev, session->channel,
++					 session->target_id, lun, 1);
++	}
++	mutex_unlock(&ihost->mutex);
++
++	return 0;
++}
++
++static void session_recovery_timedout(void *data)
++{
++	struct iscsi_cls_session *session = data;
++
++	dev_printk(KERN_INFO, &session->dev, "session recovery timed out "
++		  "after %d secs\n", session->recovery_tmo);
++
++	if (session->transport->session_recovery_timedout)
++		session->transport->session_recovery_timedout(session);
++
++	scsi_target_unblock(&session->dev);
++}
++
++void iscsi_unblock_session(struct iscsi_cls_session *session)
++{
++	if (!cancel_delayed_work(&session->recovery_work))
++		flush_scheduled_work();
++	scsi_target_unblock(&session->dev);
++}
++EXPORT_SYMBOL_GPL(iscsi_unblock_session);
++
++void iscsi_block_session(struct iscsi_cls_session *session)
++{
++	scsi_target_block(&session->dev);
++	schedule_delayed_work(&session->recovery_work,
++			     session->recovery_tmo * HZ);
++}
++EXPORT_SYMBOL_GPL(iscsi_block_session);
++
+ /**
+  * iscsi_create_session - create iscsi class session
+  * @shost: scsi host
+@@ -233,8 +299,10 @@ static int iscsi_is_session_dev(const struct device *dev)
+  * This can be called from a LLD or iscsi_transport.
+  **/
+ struct iscsi_cls_session *
+-iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport)
++iscsi_create_session(struct Scsi_Host *shost,
++		     struct iscsi_transport *transport, int channel)
+ {
++	struct iscsi_host *ihost;
+ 	struct iscsi_cls_session *session;
+ 	int err;
+ 
+@@ -246,13 +314,22 @@ iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport)
+ 	if (!session)
+ 		goto module_put;
+ 	session->transport = transport;
++	session->recovery_tmo = 120;
++	INIT_WORK(&session->recovery_work, session_recovery_timedout, session);
++	INIT_LIST_HEAD(&session->host_list);
++	INIT_LIST_HEAD(&session->sess_list);
+ 
+ 	if (transport->sessiondata_size)
+ 		session->dd_data = &session[1];
+ 
+ 	/* this is released in the dev's release function */
+ 	scsi_host_get(shost);
++	ihost = shost->shost_data;
++
+ 	session->sid = iscsi_session_nr++;
++	session->channel = channel;
++	session->target_id = ihost->next_target_id++;
++
+ 	snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u",
+ 		 session->sid);
+ 	session->dev.parent = &shost->shost_gendev;
+@@ -265,6 +342,10 @@ iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport)
+ 	}
+ 	transport_register_device(&session->dev);
+ 
++	mutex_lock(&ihost->mutex);
++	list_add(&session->host_list, &ihost->sessions);
++	mutex_unlock(&ihost->mutex);
++
+ 	return session;
+ 
+ free_session:
+@@ -285,6 +366,16 @@ EXPORT_SYMBOL_GPL(iscsi_create_session);
+  **/
+ int iscsi_destroy_session(struct iscsi_cls_session *session)
+ {
++	struct Scsi_Host *shost = iscsi_session_to_shost(session);
++	struct iscsi_host *ihost = shost->shost_data;
++
++	if (!cancel_delayed_work(&session->recovery_work))
++		flush_scheduled_work();
++
++	mutex_lock(&ihost->mutex);
++	list_del(&session->host_list);
++	mutex_unlock(&ihost->mutex);
++
+ 	transport_unregister_device(&session->dev);
+ 	device_unregister(&session->dev);
+ 	return 0;
+@@ -435,7 +526,7 @@ iscsi_transport_create_session(struct scsi_transport_template *scsit,
+ 	if (scsi_add_host(shost, NULL))
+ 		goto free_host;
+ 
+-	session = iscsi_create_session(shost, transport);
++	session = iscsi_create_session(shost, transport, 0);
+ 	if (!session)
+ 		goto remove_host;
+ 
+@@ -466,12 +557,13 @@ int iscsi_transport_destroy_session(struct Scsi_Host *shost)
+ 	struct iscsi_cls_session *session;
+ 	unsigned long flags;
+ 
+-	scsi_remove_host(shost);
+ 	session = hostdata_session(shost->hostdata);
+ 	spin_lock_irqsave(&sesslock, flags);
+ 	list_del(&session->sess_list);
+ 	spin_unlock_irqrestore(&sesslock, flags);
+ 	iscsi_destroy_session(session);
++
++	scsi_remove_host(shost);
+ 	/* ref from host alloc */
+ 	scsi_host_put(shost);
+ 	return 0;
+@@ -594,6 +686,7 @@ iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb)
+ 	}
+ 
+ 	spin_lock_irqsave(&zone->freelock, flags);
++	INIT_LIST_HEAD(skb_to_lh(skb));
+ 	list_add(skb_to_lh(skb), &zone->freequeue);
+ 	spin_unlock_irqrestore(&zone->freelock, flags);
+ 
+@@ -888,6 +981,11 @@ iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+ 		return -EINVAL;
+ 
+ 	switch (ev->u.set_param.param) {
++	case ISCSI_PARAM_SESS_RECOVERY_TMO:
++		iscsi_copy_param(ev, &value, data);
++		if (value != 0)
++			session->recovery_tmo = value;
++		break;
+ 	case ISCSI_PARAM_TARGET_NAME:
+ 		/* this should not change between logins */
+ 		if (session->targetname)
+@@ -980,7 +1078,6 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 			ev->r.retcode = transport->start_conn(conn);
+ 		else
+ 			err = -EINVAL;
+-
+ 		break;
+ 	case ISCSI_UEVENT_STOP_CONN:
+ 		conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ev->u.stop_conn.cid);
+@@ -1198,6 +1295,7 @@ static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO, show_priv_session_##field, \
+ 			NULL)
+ iscsi_priv_session_attr(targetname, "%s");
+ iscsi_priv_session_attr(tpgt, "%d");
++iscsi_priv_session_attr(recovery_tmo, "%d");
+ 
+ #define iscsi_priv_conn_attr_show(field, format)			\
+ static ssize_t								\
+@@ -1289,6 +1387,24 @@ static int iscsi_conn_match(struct attribute_container *cont,
+ 	return &priv->conn_cont.ac == cont;
+ }
+ 
++static int iscsi_host_match(struct attribute_container *cont,
++			    struct device *dev)
++{
++	struct Scsi_Host *shost;
++	struct iscsi_internal *priv;
++
++	if (!scsi_is_host_device(dev))
++		return 0;
++
++	shost = dev_to_shost(dev);
++	if (!shost->transportt  ||
++	    shost->transportt->host_attrs.ac.class != &iscsi_host_class.class)
++		return 0;
++
++        priv = to_iscsi_internal(shost->transportt);
++        return &priv->t.host_attrs.ac == cont;
++}
++
+ struct scsi_transport_template *
+ iscsi_register_transport(struct iscsi_transport *tt)
+ {
+@@ -1307,6 +1423,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 		return NULL;
+ 	INIT_LIST_HEAD(&priv->list);
+ 	priv->iscsi_transport = tt;
++	priv->t.user_scan = iscsi_user_scan;
+ 
+ 	priv->cdev.class = &iscsi_transport_class;
+ 	snprintf(priv->cdev.class_id, BUS_ID_SIZE, "%s", tt->name);
+@@ -1318,6 +1435,14 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 	if (err)
+ 		goto unregister_cdev;
+ 
++	/* host parameters */
++	priv->t.host_attrs.ac.attrs = &priv->host_attrs[0];
++	priv->t.host_attrs.ac.class = &iscsi_host_class.class;
++	priv->t.host_attrs.ac.match = iscsi_host_match;
++	priv->t.host_size = sizeof(struct iscsi_host);
++	priv->host_attrs[0] = NULL;
++	transport_container_register(&priv->t.host_attrs);
++
+ 	/* connection parameters */
+ 	priv->conn_cont.ac.attrs = &priv->conn_attrs[0];
+ 	priv->conn_cont.ac.class = &iscsi_connection_class.class;
+@@ -1361,6 +1486,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 	SETUP_SESSION_RD_ATTR(data_pdu_in_order, ISCSI_PDU_INORDER_EN);
+ 	SETUP_SESSION_RD_ATTR(data_seq_in_order, ISCSI_DATASEQ_INORDER_EN);
+ 	SETUP_SESSION_RD_ATTR(erl, ISCSI_ERL);
++	SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo);
+ 
+ 	if (tt->param_mask & ISCSI_TARGET_NAME)
+ 		SETUP_SESSION_RD_ATTR(targetname, ISCSI_TARGET_NAME);
+@@ -1408,6 +1534,7 @@ int iscsi_unregister_transport(struct iscsi_transport *tt)
+ 
+ 	transport_container_unregister(&priv->conn_cont);
+ 	transport_container_unregister(&priv->session_cont);
++	transport_container_unregister(&priv->t.host_attrs);
+ 
+ 	sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group);
+ 	class_device_unregister(&priv->cdev);
+@@ -1451,10 +1578,14 @@ static __init int iscsi_transport_init(void)
+ 	if (err)
+ 		return err;
+ 
+-	err = transport_class_register(&iscsi_connection_class);
++	err = transport_class_register(&iscsi_host_class);
+ 	if (err)
+ 		goto unregister_transport_class;
+ 
++	err = transport_class_register(&iscsi_connection_class);
++	if (err)
++		goto unregister_host_class;
++
+ 	err = transport_class_register(&iscsi_session_class);
+ 	if (err)
+ 		goto unregister_conn_class;
+@@ -1482,6 +1613,8 @@ static __init int iscsi_transport_init(void)
+ 	transport_class_unregister(&iscsi_session_class);
+ unregister_conn_class:
+ 	transport_class_unregister(&iscsi_connection_class);
++unregister_host_class:
++	transport_class_unregister(&iscsi_host_class);
+ unregister_transport_class:
+ 	class_unregister(&iscsi_transport_class);
+ 	return err;
+@@ -1494,6 +1627,7 @@ static void __exit iscsi_transport_exit(void)
+ 	netlink_unregister_notifier(&iscsi_nl_notifier);
+ 	transport_class_unregister(&iscsi_connection_class);
+ 	transport_class_unregister(&iscsi_session_class);
++	transport_class_unregister(&iscsi_host_class);
+ 	class_unregister(&iscsi_transport_class);
+ }
+ 
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index 2c3a89b64e71..eebe2b15161b 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -174,6 +174,7 @@ enum iscsi_param {
+ 	ISCSI_PARAM_TPGT,
+ 	ISCSI_PARAM_PERSISTENT_ADDRESS,
+ 	ISCSI_PARAM_PERSISTENT_PORT,
++	ISCSI_PARAM_SESS_RECOVERY_TMO,
+ 
+ 	/* pased in through bind conn using transport_fd */
+ 	ISCSI_PARAM_CONN_PORT,
+@@ -201,6 +202,7 @@ enum iscsi_param {
+ #define ISCSI_TPGT			(1 << ISCSI_PARAM_TPGT)
+ #define ISCSI_PERSISTENT_ADDRESS	(1 << ISCSI_PARAM_PERSISTENT_ADDRESS)
+ #define ISCSI_PERSISTENT_PORT		(1 << ISCSI_PARAM_PERSISTENT_PORT)
++#define ISCSI_SESS_RECOVERY_TMO		(1 << ISCSI_PARAM_SESS_RECOVERY_TMO)
+ #define ISCSI_CONN_PORT			(1 << ISCSI_PARAM_CONN_PORT)
+ #define ISCSI_CONN_ADDRESS		(1 << ISCSI_PARAM_CONN_ADDRESS)
+ 
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 4b200645c84b..9d2b99159ee7 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -90,6 +90,7 @@ struct iscsi_transport {
+ 			 char *data, uint32_t data_size);
+ 	void (*get_stats) (struct iscsi_cls_conn *conn,
+ 			   struct iscsi_stats *stats);
++	void (*session_recovery_timedout) (struct iscsi_cls_session *session);
+ };
+ 
+ /*
+@@ -130,12 +131,20 @@ struct iscsi_cls_conn {
+ 
+ struct iscsi_cls_session {
+ 	struct list_head sess_list;		/* item in session_list */
++	struct list_head host_list;
+ 	struct iscsi_transport *transport;
+ 
+ 	/* iSCSI values used as unique id by userspace. */
+ 	char *targetname;
+ 	int tpgt;
+ 
++	/* recovery fields */
++	int recovery_tmo;
++	struct work_struct recovery_work;
++
++	int target_id;
++	int channel;
++
+ 	int sid;				/* session id */
+ 	void *dd_data;				/* LLD private data */
+ 	struct device dev;	/* sysfs transport/container device */
+@@ -147,15 +156,23 @@ struct iscsi_cls_session {
+ #define iscsi_session_to_shost(_session) \
+ 	dev_to_shost(_session->dev.parent)
+ 
++struct iscsi_host {
++	int next_target_id;
++	struct list_head sessions;
++	struct mutex mutex;
++};
++
+ /*
+  * session and connection functions that can be used by HW iSCSI LLDs
+  */
+ extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost,
+-				struct iscsi_transport *t);
++				struct iscsi_transport *t, int channel);
+ extern int iscsi_destroy_session(struct iscsi_cls_session *session);
+ extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess,
+ 					    uint32_t cid);
+ extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn);
++extern void iscsi_unblock_session(struct iscsi_cls_session *session);
++extern void iscsi_block_session(struct iscsi_cls_session *session);
+ 
+ /*
+  * session functions used by software iscsi

commit fd7255f51a13ea915099c7e488001dfbbeb05104
+Author: Mike Christie 
+Date:   Thu Apr 6 21:13:36 2006 -0500
+
+    [SCSI] iscsi: add sysfs attrs for uspace sync up
+    
+    For iscsi boot when going from initramfs to the real root we
+    need to stop the userpsace iscsi daemon. To later restart it
+    iscsid needs to be able to rebuild itself and part of that
+    process is matching a session running the kernel with the
+    iscsid representation. To do this the attached patch
+    adds several required iscsi values. If the LLD does not provide
+    them becuase, login is done in userspace, then the transport
+    class and userspace set ths up for the LLD.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 6ecb4baa37e2..6e510f3cfbf6 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -3536,7 +3536,7 @@ iscsi_session_get_param(struct iscsi_cls_session *cls_session,
+ 		*value = session->ofmarker_en;
+ 		break;
+ 	default:
+-		return ISCSI_ERR_PARAM_NOT_FOUND;
++		return -EINVAL;
+ 	}
+ 
+ 	return 0;
+@@ -3547,6 +3547,7 @@ iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ 		     enum iscsi_param param, uint32_t *value)
+ {
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
++	struct inet_sock *inet;
+ 
+ 	switch(param) {
+ 	case ISCSI_PARAM_MAX_RECV_DLENGTH:
+@@ -3561,13 +3562,61 @@ iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+ 	case ISCSI_PARAM_DATADGST_EN:
+ 		*value = conn->datadgst_en;
+ 		break;
++	case ISCSI_PARAM_CONN_PORT:
++		mutex_lock(&conn->xmitmutex);
++		if (!conn->sock) {
++			mutex_unlock(&conn->xmitmutex);
++			return -EINVAL;
++		}
++
++		inet = inet_sk(conn->sock->sk);
++		*value = be16_to_cpu(inet->dport);
++		mutex_unlock(&conn->xmitmutex);
+ 	default:
+-		return ISCSI_ERR_PARAM_NOT_FOUND;
++		return -EINVAL;
+ 	}
+ 
+ 	return 0;
+ }
+ 
++static int
++iscsi_conn_get_str_param(struct iscsi_cls_conn *cls_conn,
++			 enum iscsi_param param, char *buf)
++{
++	struct iscsi_conn *conn = cls_conn->dd_data;
++	struct sock *sk;
++	struct inet_sock *inet;
++	struct ipv6_pinfo *np;
++	int len = 0;
++
++	switch (param) {
++	case ISCSI_PARAM_CONN_ADDRESS:
++		mutex_lock(&conn->xmitmutex);
++		if (!conn->sock) {
++			mutex_unlock(&conn->xmitmutex);
++			return -EINVAL;
++		}
++
++		sk = conn->sock->sk;
++		if (sk->sk_family == PF_INET) {
++			inet = inet_sk(sk);
++			len = sprintf(buf, "%u.%u.%u.%u\n",
++				      NIPQUAD(inet->daddr));
++		} else {
++			np = inet6_sk(sk);
++			len = sprintf(buf,
++				"%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
++				NIP6(np->daddr));
++		}
++		mutex_unlock(&conn->xmitmutex);
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	return len;
++}
++
+ static void
+ iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats)
+ {
+@@ -3610,6 +3659,20 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 	.name			= "tcp",
+ 	.caps			= CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST
+ 				  | CAP_DATADGST,
++	.param_mask		= ISCSI_MAX_RECV_DLENGTH |
++				  ISCSI_MAX_XMIT_DLENGTH |
++				  ISCSI_HDRDGST_EN |
++				  ISCSI_DATADGST_EN |
++				  ISCSI_INITIAL_R2T_EN |
++				  ISCSI_MAX_R2T |
++				  ISCSI_IMM_DATA_EN |
++				  ISCSI_FIRST_BURST |
++				  ISCSI_MAX_BURST |
++				  ISCSI_PDU_INORDER_EN |
++				  ISCSI_DATASEQ_INORDER_EN |
++				  ISCSI_ERL |
++				  ISCSI_CONN_PORT |
++				  ISCSI_CONN_ADDRESS,
+ 	.host_template		= &iscsi_sht,
+ 	.hostdata_size		= sizeof(struct iscsi_session),
+ 	.conndata_size		= sizeof(struct iscsi_conn),
+@@ -3622,6 +3685,7 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 	.destroy_conn		= iscsi_conn_destroy,
+ 	.set_param		= iscsi_conn_set_param,
+ 	.get_conn_param		= iscsi_conn_get_param,
++	.get_conn_str_param	= iscsi_conn_get_str_param,
+ 	.get_session_param	= iscsi_session_get_param,
+ 	.start_conn		= iscsi_conn_start,
+ 	.stop_conn		= iscsi_conn_stop,
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 10ff0f0210ba..72a71ebc9d03 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -31,21 +31,13 @@
+ #include 
+ #include 
+ 
+-#define ISCSI_SESSION_ATTRS 8
+-#define ISCSI_CONN_ATTRS 6
++#define ISCSI_SESSION_ATTRS 10
++#define ISCSI_CONN_ATTRS 10
+ 
+ struct iscsi_internal {
+ 	struct scsi_transport_template t;
+ 	struct iscsi_transport *iscsi_transport;
+ 	struct list_head list;
+-	/*
+-	 * based on transport capabilities, at register time we set these
+-	 * bits to tell the transport class it wants attributes displayed
+-	 * in sysfs or that it can support different iSCSI Data-Path
+-	 * capabilities
+-	 */
+-	uint32_t param_mask;
+-
+ 	struct class_device cdev;
+ 	/*
+ 	 * We do not have any private or other attrs.
+@@ -223,6 +215,7 @@ static void iscsi_session_release(struct device *dev)
+ 
+ 	shost = iscsi_session_to_shost(session);
+ 	scsi_host_put(shost);
++	kfree(session->targetname);
+ 	kfree(session);
+ 	module_put(transport->owner);
+ }
+@@ -304,6 +297,7 @@ static void iscsi_conn_release(struct device *dev)
+ 	struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev);
+ 	struct device *parent = conn->dev.parent;
+ 
++	kfree(conn->persistent_address);
+ 	kfree(conn);
+ 	put_device(parent);
+ }
+@@ -870,6 +864,67 @@ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev
+ 	return 0;
+ }
+ 
++static void
++iscsi_copy_param(struct iscsi_uevent *ev, uint32_t *value, char *data)
++{
++	if (ev->u.set_param.len != sizeof(uint32_t))
++		BUG();
++	memcpy(value, data, min_t(uint32_t, sizeof(uint32_t),
++		ev->u.set_param.len));
++}
++
++static int
++iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
++{
++	char *data = (char*)ev + sizeof(*ev);
++	struct iscsi_cls_conn *conn;
++	struct iscsi_cls_session *session;
++	int err = 0;
++	uint32_t value = 0;
++
++	session = iscsi_session_lookup(ev->u.set_param.sid);
++	conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid);
++	if (!conn || !session)
++		return -EINVAL;
++
++	switch (ev->u.set_param.param) {
++	case ISCSI_PARAM_TARGET_NAME:
++		/* this should not change between logins */
++		if (session->targetname)
++			return 0;
++
++		session->targetname = kstrdup(data, GFP_KERNEL);
++		if (!session->targetname)
++			return -ENOMEM;
++		break;
++	case ISCSI_PARAM_TPGT:
++		iscsi_copy_param(ev, &value, data);
++		session->tpgt = value;
++		break;
++	case ISCSI_PARAM_PERSISTENT_PORT:
++		iscsi_copy_param(ev, &value, data);
++		conn->persistent_port = value;
++		break;
++	case ISCSI_PARAM_PERSISTENT_ADDRESS:
++		/*
++		 * this is the address returned in discovery so it should
++		 * not change between logins.
++		 */
++		if (conn->persistent_address)
++			return 0;
++
++		conn->persistent_address = kstrdup(data, GFP_KERNEL);
++		if (!conn->persistent_address)
++			return -ENOMEM;
++		break;
++	default:
++		iscsi_copy_param(ev, &value, data);
++		err = transport->set_param(conn, ev->u.set_param.param, value);
++	}
++
++	return err;
++}
++
+ static int
+ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ {
+@@ -917,12 +972,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 			err = -EINVAL;
+ 		break;
+ 	case ISCSI_UEVENT_SET_PARAM:
+-		conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid);
+-		if (conn)
+-			ev->r.retcode =	transport->set_param(conn,
+-				ev->u.set_param.param, ev->u.set_param.value);
+-		else
+-			err = -EINVAL;
++		err = iscsi_set_param(transport, ev);
+ 		break;
+ 	case ISCSI_UEVENT_START_CONN:
+ 		conn = iscsi_conn_lookup(ev->u.start_conn.sid, ev->u.start_conn.cid);
+@@ -1028,6 +1078,10 @@ iscsi_if_rx(struct sock *sk, int len)
+ #define iscsi_cdev_to_conn(_cdev) \
+ 	iscsi_dev_to_conn(_cdev->dev)
+ 
++#define ISCSI_CLASS_ATTR(_prefix,_name,_mode,_show,_store)		\
++struct class_device_attribute class_device_attr_##_prefix##_##_name =	\
++	__ATTR(_name,_mode,_show,_store)
++
+ /*
+  * iSCSI connection attrs
+  */
+@@ -1045,7 +1099,8 @@ show_conn_int_param_##param(struct class_device *cdev, char *buf)	\
+ 
+ #define iscsi_conn_int_attr(field, param, format)			\
+ 	iscsi_conn_int_attr_show(param, format)				\
+-static CLASS_DEVICE_ATTR(field, S_IRUGO, show_conn_int_param_##param, NULL);
++static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_int_param_##param, \
++			NULL);
+ 
+ iscsi_conn_int_attr(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH, "%u");
+ iscsi_conn_int_attr(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH, "%u");
+@@ -1053,6 +1108,25 @@ iscsi_conn_int_attr(header_digest, ISCSI_PARAM_HDRDGST_EN, "%d");
+ iscsi_conn_int_attr(data_digest, ISCSI_PARAM_DATADGST_EN, "%d");
+ iscsi_conn_int_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN, "%d");
+ iscsi_conn_int_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN, "%d");
++iscsi_conn_int_attr(persistent_port, ISCSI_PARAM_PERSISTENT_PORT, "%d");
++iscsi_conn_int_attr(port, ISCSI_PARAM_CONN_PORT, "%d");
++
++#define iscsi_conn_str_attr_show(param)					\
++static ssize_t								\
++show_conn_str_param_##param(struct class_device *cdev, char *buf)	\
++{									\
++	struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev);		\
++	struct iscsi_transport *t = conn->transport;			\
++	return t->get_conn_str_param(conn, param, buf);			\
++}
++
++#define iscsi_conn_str_attr(field, param)				\
++	iscsi_conn_str_attr_show(param)					\
++static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_str_param_##param, \
++			NULL);
++
++iscsi_conn_str_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS);
++iscsi_conn_str_attr(address, ISCSI_PARAM_CONN_ADDRESS);
+ 
+ #define iscsi_cdev_to_session(_cdev) \
+ 	iscsi_dev_to_session(_cdev->dev)
+@@ -1074,7 +1148,8 @@ show_session_int_param_##param(struct class_device *cdev, char *buf)	\
+ 
+ #define iscsi_session_int_attr(field, param, format)			\
+ 	iscsi_session_int_attr_show(param, format)			\
+-static CLASS_DEVICE_ATTR(field, S_IRUGO, show_session_int_param_##param, NULL);
++static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_int_param_##param, \
++			NULL);
+ 
+ iscsi_session_int_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN, "%d");
+ iscsi_session_int_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T, "%hu");
+@@ -1084,18 +1159,88 @@ iscsi_session_int_attr(max_burst_len, ISCSI_PARAM_MAX_BURST, "%u");
+ iscsi_session_int_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN, "%d");
+ iscsi_session_int_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN, "%d");
+ iscsi_session_int_attr(erl, ISCSI_PARAM_ERL, "%d");
++iscsi_session_int_attr(tpgt, ISCSI_PARAM_TPGT, "%d");
+ 
+-#define SETUP_SESSION_RD_ATTR(field, param)				\
+-	if (priv->param_mask & (1 << param)) {				\
+-		priv->session_attrs[count] = &class_device_attr_##field;\
+-		count++;						\
+-	}
++#define iscsi_session_str_attr_show(param)				\
++static ssize_t								\
++show_session_str_param_##param(struct class_device *cdev, char *buf)	\
++{									\
++	struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
++	struct iscsi_transport *t = session->transport;			\
++	return t->get_session_str_param(session, param, buf);		\
++}
++
++#define iscsi_session_str_attr(field, param)				\
++	iscsi_session_str_attr_show(param)				\
++static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_str_param_##param, \
++			NULL);
++
++iscsi_session_str_attr(targetname, ISCSI_PARAM_TARGET_NAME);
+ 
+-#define SETUP_CONN_RD_ATTR(field, param)				\
+-	if (priv->param_mask & (1 << param)) {				\
+-		priv->conn_attrs[count] = &class_device_attr_##field;	\
++/*
++ * Private session and conn attrs. userspace uses several iscsi values
++ * to identify each session between reboots. Some of these values may not
++ * be present in the iscsi_transport/LLD driver becuase userspace handles
++ * login (and failback for login redirect) so for these type of drivers
++ * the class manages the attrs and values for the iscsi_transport/LLD
++ */
++#define iscsi_priv_session_attr_show(field, format)			\
++static ssize_t								\
++show_priv_session_##field(struct class_device *cdev, char *buf)	\
++{									\
++	struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
++	return sprintf(buf, format"\n", session->field);		\
++}
++
++#define iscsi_priv_session_attr(field, format)				\
++	iscsi_priv_session_attr_show(field, format)			\
++static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO, show_priv_session_##field, \
++			NULL)
++iscsi_priv_session_attr(targetname, "%s");
++iscsi_priv_session_attr(tpgt, "%d");
++
++#define iscsi_priv_conn_attr_show(field, format)			\
++static ssize_t								\
++show_priv_conn_##field(struct class_device *cdev, char *buf)		\
++{									\
++	struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev);		\
++	return sprintf(buf, format"\n", conn->field);			\
++}
++
++#define iscsi_priv_conn_attr(field, format)				\
++	iscsi_priv_conn_attr_show(field, format)			\
++static ISCSI_CLASS_ATTR(priv_conn, field, S_IRUGO, show_priv_conn_##field, \
++			NULL)
++iscsi_priv_conn_attr(persistent_address, "%s");
++iscsi_priv_conn_attr(persistent_port, "%d");
++
++#define SETUP_PRIV_SESSION_RD_ATTR(field)				\
++do {									\
++	priv->session_attrs[count] = &class_device_attr_priv_sess_##field; \
++	count++;							\
++} while (0)
++
++#define SETUP_SESSION_RD_ATTR(field, param_flag)			\
++do {									\
++	if (tt->param_mask & param_flag) {				\
++		priv->session_attrs[count] = &class_device_attr_sess_##field; \
+ 		count++;						\
+-	}
++	}								\
++} while (0)
++
++#define SETUP_PRIV_CONN_RD_ATTR(field)					\
++do {									\
++	priv->conn_attrs[count] = &class_device_attr_priv_conn_##field; \
++	count++;							\
++} while (0)
++
++#define SETUP_CONN_RD_ATTR(field, param_flag)				\
++do {									\
++	if (tt->param_mask & param_flag) {				\
++		priv->conn_attrs[count] = &class_device_attr_conn_##field; \
++		count++;						\
++	}								\
++} while (0)
+ 
+ static int iscsi_session_match(struct attribute_container *cont,
+ 			   struct device *dev)
+@@ -1173,31 +1318,30 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 	if (err)
+ 		goto unregister_cdev;
+ 
+-	/* setup parameters mask */
+-	priv->param_mask = 0xFFFFFFFF;
+-	if (!(tt->caps & CAP_MULTI_R2T))
+-		priv->param_mask &= ~(1 << ISCSI_PARAM_MAX_R2T);
+-	if (!(tt->caps & CAP_HDRDGST))
+-		priv->param_mask &= ~(1 << ISCSI_PARAM_HDRDGST_EN);
+-	if (!(tt->caps & CAP_DATADGST))
+-		priv->param_mask &= ~(1 << ISCSI_PARAM_DATADGST_EN);
+-	if (!(tt->caps & CAP_MARKERS)) {
+-		priv->param_mask &= ~(1 << ISCSI_PARAM_IFMARKER_EN);
+-		priv->param_mask &= ~(1 << ISCSI_PARAM_OFMARKER_EN);
+-	}
+-
+ 	/* connection parameters */
+ 	priv->conn_cont.ac.attrs = &priv->conn_attrs[0];
+ 	priv->conn_cont.ac.class = &iscsi_connection_class.class;
+ 	priv->conn_cont.ac.match = iscsi_conn_match;
+ 	transport_container_register(&priv->conn_cont);
+ 
+-	SETUP_CONN_RD_ATTR(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH);
+-	SETUP_CONN_RD_ATTR(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH);
+-	SETUP_CONN_RD_ATTR(header_digest, ISCSI_PARAM_HDRDGST_EN);
+-	SETUP_CONN_RD_ATTR(data_digest, ISCSI_PARAM_DATADGST_EN);
+-	SETUP_CONN_RD_ATTR(ifmarker, ISCSI_PARAM_IFMARKER_EN);
+-	SETUP_CONN_RD_ATTR(ofmarker, ISCSI_PARAM_OFMARKER_EN);
++	SETUP_CONN_RD_ATTR(max_recv_dlength, ISCSI_MAX_RECV_DLENGTH);
++	SETUP_CONN_RD_ATTR(max_xmit_dlength, ISCSI_MAX_XMIT_DLENGTH);
++	SETUP_CONN_RD_ATTR(header_digest, ISCSI_HDRDGST_EN);
++	SETUP_CONN_RD_ATTR(data_digest, ISCSI_DATADGST_EN);
++	SETUP_CONN_RD_ATTR(ifmarker, ISCSI_IFMARKER_EN);
++	SETUP_CONN_RD_ATTR(ofmarker, ISCSI_OFMARKER_EN);
++	SETUP_CONN_RD_ATTR(address, ISCSI_CONN_ADDRESS);
++	SETUP_CONN_RD_ATTR(port, ISCSI_CONN_PORT);
++
++	if (tt->param_mask & ISCSI_PERSISTENT_ADDRESS)
++		SETUP_CONN_RD_ATTR(persistent_address, ISCSI_PERSISTENT_ADDRESS);
++	else
++		SETUP_PRIV_CONN_RD_ATTR(persistent_address);
++
++	if (tt->param_mask & ISCSI_PERSISTENT_PORT)
++		SETUP_CONN_RD_ATTR(persistent_port, ISCSI_PERSISTENT_PORT);
++	else
++		SETUP_PRIV_CONN_RD_ATTR(persistent_port);
+ 
+ 	BUG_ON(count > ISCSI_CONN_ATTRS);
+ 	priv->conn_attrs[count] = NULL;
+@@ -1209,14 +1353,24 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 	priv->session_cont.ac.match = iscsi_session_match;
+ 	transport_container_register(&priv->session_cont);
+ 
+-	SETUP_SESSION_RD_ATTR(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN);
+-	SETUP_SESSION_RD_ATTR(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T);
+-	SETUP_SESSION_RD_ATTR(immediate_data, ISCSI_PARAM_IMM_DATA_EN);
+-	SETUP_SESSION_RD_ATTR(first_burst_len, ISCSI_PARAM_FIRST_BURST);
+-	SETUP_SESSION_RD_ATTR(max_burst_len, ISCSI_PARAM_MAX_BURST);
+-	SETUP_SESSION_RD_ATTR(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN);
+-	SETUP_SESSION_RD_ATTR(data_seq_in_order,ISCSI_PARAM_DATASEQ_INORDER_EN)
+-	SETUP_SESSION_RD_ATTR(erl, ISCSI_PARAM_ERL);
++	SETUP_SESSION_RD_ATTR(initial_r2t, ISCSI_INITIAL_R2T_EN);
++	SETUP_SESSION_RD_ATTR(max_outstanding_r2t, ISCSI_MAX_R2T);
++	SETUP_SESSION_RD_ATTR(immediate_data, ISCSI_IMM_DATA_EN);
++	SETUP_SESSION_RD_ATTR(first_burst_len, ISCSI_FIRST_BURST);
++	SETUP_SESSION_RD_ATTR(max_burst_len, ISCSI_MAX_BURST);
++	SETUP_SESSION_RD_ATTR(data_pdu_in_order, ISCSI_PDU_INORDER_EN);
++	SETUP_SESSION_RD_ATTR(data_seq_in_order, ISCSI_DATASEQ_INORDER_EN);
++	SETUP_SESSION_RD_ATTR(erl, ISCSI_ERL);
++
++	if (tt->param_mask & ISCSI_TARGET_NAME)
++		SETUP_SESSION_RD_ATTR(targetname, ISCSI_TARGET_NAME);
++	else
++		SETUP_PRIV_SESSION_RD_ATTR(targetname);
++
++	if (tt->param_mask & ISCSI_TPGT)
++		SETUP_SESSION_RD_ATTR(tpgt, ISCSI_TPGT);
++	else
++		SETUP_PRIV_SESSION_RD_ATTR(tpgt);
+ 
+ 	BUG_ON(count > ISCSI_SESSION_ATTRS);
+ 	priv->session_attrs[count] = NULL;
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index 933a91b1474e..2c3a89b64e71 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -86,7 +86,7 @@ struct iscsi_uevent {
+ 			uint32_t	sid;
+ 			uint32_t	cid;
+ 			uint32_t	param; /* enum iscsi_param */
+-			uint32_t	value;
++			uint32_t	len;
+ 		} set_param;
+ 		struct msg_start_conn {
+ 			uint32_t	sid;
+@@ -155,22 +155,54 @@ enum iscsi_err {
+  * iSCSI Parameters (RFC3720)
+  */
+ enum iscsi_param {
+-	ISCSI_PARAM_MAX_RECV_DLENGTH	= 0,
+-	ISCSI_PARAM_MAX_XMIT_DLENGTH	= 1,
+-	ISCSI_PARAM_HDRDGST_EN		= 2,
+-	ISCSI_PARAM_DATADGST_EN		= 3,
+-	ISCSI_PARAM_INITIAL_R2T_EN	= 4,
+-	ISCSI_PARAM_MAX_R2T		= 5,
+-	ISCSI_PARAM_IMM_DATA_EN		= 6,
+-	ISCSI_PARAM_FIRST_BURST		= 7,
+-	ISCSI_PARAM_MAX_BURST		= 8,
+-	ISCSI_PARAM_PDU_INORDER_EN	= 9,
+-	ISCSI_PARAM_DATASEQ_INORDER_EN	= 10,
+-	ISCSI_PARAM_ERL			= 11,
+-	ISCSI_PARAM_IFMARKER_EN		= 12,
+-	ISCSI_PARAM_OFMARKER_EN		= 13,
++	/* passed in using netlink set param */
++	ISCSI_PARAM_MAX_RECV_DLENGTH,
++	ISCSI_PARAM_MAX_XMIT_DLENGTH,
++	ISCSI_PARAM_HDRDGST_EN,
++	ISCSI_PARAM_DATADGST_EN,
++	ISCSI_PARAM_INITIAL_R2T_EN,
++	ISCSI_PARAM_MAX_R2T,
++	ISCSI_PARAM_IMM_DATA_EN,
++	ISCSI_PARAM_FIRST_BURST,
++	ISCSI_PARAM_MAX_BURST,
++	ISCSI_PARAM_PDU_INORDER_EN,
++	ISCSI_PARAM_DATASEQ_INORDER_EN,
++	ISCSI_PARAM_ERL,
++	ISCSI_PARAM_IFMARKER_EN,
++	ISCSI_PARAM_OFMARKER_EN,
++	ISCSI_PARAM_TARGET_NAME,
++	ISCSI_PARAM_TPGT,
++	ISCSI_PARAM_PERSISTENT_ADDRESS,
++	ISCSI_PARAM_PERSISTENT_PORT,
++
++	/* pased in through bind conn using transport_fd */
++	ISCSI_PARAM_CONN_PORT,
++	ISCSI_PARAM_CONN_ADDRESS,
++
++	/* must always be last */
++	ISCSI_PARAM_MAX,
+ };
+-#define ISCSI_PARAM_MAX			14
++
++#define ISCSI_MAX_RECV_DLENGTH		(1 << ISCSI_PARAM_MAX_RECV_DLENGTH)
++#define ISCSI_MAX_XMIT_DLENGTH		(1 << ISCSI_PARAM_MAX_XMIT_DLENGTH)
++#define ISCSI_HDRDGST_EN		(1 << ISCSI_PARAM_HDRDGST_EN)
++#define ISCSI_DATADGST_EN		(1 << ISCSI_PARAM_DATADGST_EN)
++#define ISCSI_INITIAL_R2T_EN		(1 << ISCSI_PARAM_INITIAL_R2T_EN)
++#define ISCSI_MAX_R2T			(1 << ISCSI_PARAM_MAX_R2T)
++#define ISCSI_IMM_DATA_EN		(1 << ISCSI_PARAM_IMM_DATA_EN)
++#define ISCSI_FIRST_BURST		(1 << ISCSI_PARAM_FIRST_BURST)
++#define ISCSI_MAX_BURST			(1 << ISCSI_PARAM_MAX_BURST)
++#define ISCSI_PDU_INORDER_EN		(1 << ISCSI_PARAM_PDU_INORDER_EN)
++#define ISCSI_DATASEQ_INORDER_EN	(1 << ISCSI_PARAM_DATASEQ_INORDER_EN)
++#define ISCSI_ERL			(1 << ISCSI_PARAM_ERL)
++#define ISCSI_IFMARKER_EN		(1 << ISCSI_PARAM_IFMARKER_EN)
++#define ISCSI_OFMARKER_EN		(1 << ISCSI_PARAM_OFMARKER_EN)
++#define ISCSI_TARGET_NAME		(1 << ISCSI_PARAM_TARGET_NAME)
++#define ISCSI_TPGT			(1 << ISCSI_PARAM_TPGT)
++#define ISCSI_PERSISTENT_ADDRESS	(1 << ISCSI_PARAM_PERSISTENT_ADDRESS)
++#define ISCSI_PERSISTENT_PORT		(1 << ISCSI_PARAM_PERSISTENT_PORT)
++#define ISCSI_CONN_PORT			(1 << ISCSI_PARAM_CONN_PORT)
++#define ISCSI_CONN_ADDRESS		(1 << ISCSI_PARAM_CONN_ADDRESS)
+ 
+ #define iscsi_ptr(_handle) ((void*)(unsigned long)_handle)
+ #define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr)
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 631463cd4892..4b200645c84b 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -53,11 +53,11 @@ struct iscsi_transport {
+ 	struct module *owner;
+ 	char *name;
+ 	unsigned int caps;
++	/* LLD sets this to indicate what values it can export to sysfs */
++	unsigned int param_mask;
+ 	struct scsi_host_template *host_template;
+ 	/* LLD session/scsi_host data size */
+ 	int hostdata_size;
+-	/* LLD iscsi_host data size */
+-	int ihostdata_size;
+ 	/* LLD connection data size */
+ 	int conndata_size;
+ 	/* LLD session data size */
+@@ -79,10 +79,13 @@ struct iscsi_transport {
+ 	int (*set_param) (struct iscsi_cls_conn *conn, enum iscsi_param param,
+ 			  uint32_t value);
+ 	int (*get_conn_param) (struct iscsi_cls_conn *conn,
+-			       enum iscsi_param param,
+-			       uint32_t *value);
++			       enum iscsi_param param, uint32_t *value);
+ 	int (*get_session_param) (struct iscsi_cls_session *session,
+ 				  enum iscsi_param param, uint32_t *value);
++	int (*get_conn_str_param) (struct iscsi_cls_conn *conn,
++				   enum iscsi_param param, char *buf);
++	int (*get_session_str_param) (struct iscsi_cls_session *session,
++				      enum iscsi_param param, char *buf);
+ 	int (*send_pdu) (struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
+ 			 char *data, uint32_t data_size);
+ 	void (*get_stats) (struct iscsi_cls_conn *conn,
+@@ -107,6 +110,14 @@ struct iscsi_cls_conn {
+ 	void *dd_data;			/* LLD private data */
+ 	struct iscsi_transport *transport;
+ 	uint32_t cid;			/* connection id */
++
++	/* portal/group values we got during discovery */
++	char *persistent_address;
++	int persistent_port;
++	/* portal/group values we are currently using */
++	char *address;
++	int port;
++
+ 	int active;			/* must be accessed with the connlock */
+ 	struct device dev;		/* sysfs transport/container device */
+ 	struct mempool_zone *z_error;
+@@ -120,6 +131,11 @@ struct iscsi_cls_conn {
+ struct iscsi_cls_session {
+ 	struct list_head sess_list;		/* item in session_list */
+ 	struct iscsi_transport *transport;
++
++	/* iSCSI values used as unique id by userspace. */
++	char *targetname;
++	int tpgt;
++
+ 	int sid;				/* session id */
+ 	void *dd_data;				/* LLD private data */
+ 	struct device dev;	/* sysfs transport/container device */

commit b5c7a12dc29ae0990d9e867749bdd717a3160325
+Author: Mike Christie 
+Date:   Thu Apr 6 21:13:33 2006 -0500
+
+    [SCSI] iscsi: rm kernel iscsi handles usage for session and connection
+    
+    from hare@suse.de and michaelc@cs.wisc.edu
+    
+    hw iscsi like qla4xxx does not allocate a host per session and
+    for userspace it is difficult to restart iscsid using the
+    "iscsi handles" for the session and connection, so this
+    patch just has the class or userspace allocate the id for
+    the session and connection.
+    
+    Note: this breaks userspace and requires users to upgrade to the newest
+    open-iscsi tools. Sorry about his but open-iscsi is still too new to
+    say we have a stable user-kernel api and we were not good nough
+    designers to know that other hw iscsi drivers and iscsid itself would
+    need such changes. Actually we sorta did but at the time we did not
+    have the HW available to us so we could only guess.
+    
+    Luckily, the only tools hooking into the class are the open-iscsi ones
+    or other tools like iscsitart hook into the open-iscsi engine from
+    userspace or prgroams like anaconda call our tools so they are not affected.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 2068b66822b7..6ecb4baa37e2 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -3254,7 +3254,7 @@ static struct iscsi_transport iscsi_tcp_transport;
+ 
+ static struct iscsi_cls_session *
+ iscsi_session_create(struct scsi_transport_template *scsit,
+-		     uint32_t initial_cmdsn, uint32_t *sid)
++		     uint32_t initial_cmdsn, uint32_t *hostno)
+ {
+ 	struct Scsi_Host *shost;
+ 	struct iscsi_session *session;
+@@ -3274,7 +3274,8 @@ iscsi_session_create(struct scsi_transport_template *scsit,
+ 	session->exp_cmdsn = initial_cmdsn + 1;
+ 	session->max_cmdsn = initial_cmdsn + 1;
+ 	session->max_r2t = 1;
+-	*sid = shost->host_no;
++
++	*hostno = shost->host_no;
+ 
+ 	/* initialize SCSI PDU commands pool */
+ 	if (iscsi_pool_init(&session->cmdpool, session->cmds_max,
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 2730d507e585..10ff0f0210ba 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -56,6 +56,8 @@ struct iscsi_internal {
+ 	struct class_device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1];
+ };
+ 
++static int iscsi_session_nr;	/* sysfs session id for next new session */
++
+ /*
+  * list of registered transports and lock that must
+  * be held while accessing list. The iscsi_transport_lock must
+@@ -165,14 +167,23 @@ static DEFINE_SPINLOCK(sesslock);
+ static LIST_HEAD(connlist);
+ static DEFINE_SPINLOCK(connlock);
+ 
+-static struct iscsi_cls_session *iscsi_session_lookup(uint64_t handle)
++static uint32_t iscsi_conn_get_sid(struct iscsi_cls_conn *conn)
++{
++	struct iscsi_cls_session *sess = iscsi_dev_to_session(conn->dev.parent);
++	return sess->sid;
++}
++
++/*
++ * Returns the matching session to a given sid
++ */
++static struct iscsi_cls_session *iscsi_session_lookup(uint32_t sid)
+ {
+ 	unsigned long flags;
+ 	struct iscsi_cls_session *sess;
+ 
+ 	spin_lock_irqsave(&sesslock, flags);
+ 	list_for_each_entry(sess, &sesslist, sess_list) {
+-		if (sess == iscsi_ptr(handle)) {
++		if (sess->sid == sid) {
+ 			spin_unlock_irqrestore(&sesslock, flags);
+ 			return sess;
+ 		}
+@@ -181,14 +192,17 @@ static struct iscsi_cls_session *iscsi_session_lookup(uint64_t handle)
+ 	return NULL;
+ }
+ 
+-static struct iscsi_cls_conn *iscsi_conn_lookup(uint64_t handle)
++/*
++ * Returns the matching connection to a given sid / cid tuple
++ */
++static struct iscsi_cls_conn *iscsi_conn_lookup(uint32_t sid, uint32_t cid)
+ {
+ 	unsigned long flags;
+ 	struct iscsi_cls_conn *conn;
+ 
+ 	spin_lock_irqsave(&connlock, flags);
+ 	list_for_each_entry(conn, &connlist, conn_list) {
+-		if (conn == iscsi_ptr(handle)) {
++		if ((conn->cid == cid) && (iscsi_conn_get_sid(conn) == sid)) {
+ 			spin_unlock_irqrestore(&connlock, flags);
+ 			return conn;
+ 		}
+@@ -223,7 +237,7 @@ static int iscsi_is_session_dev(const struct device *dev)
+  * @shost: scsi host
+  * @transport: iscsi transport
+  *
+- * This can be called from a LLD or iscsi_transport
++ * This can be called from a LLD or iscsi_transport.
+  **/
+ struct iscsi_cls_session *
+ iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport)
+@@ -234,14 +248,20 @@ iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport)
+ 	if (!try_module_get(transport->owner))
+ 		return NULL;
+ 
+-	session = kzalloc(sizeof(*session), GFP_KERNEL);
++	session = kzalloc(sizeof(*session) + transport->sessiondata_size,
++			  GFP_KERNEL);
+ 	if (!session)
+ 		goto module_put;
+ 	session->transport = transport;
+ 
++	if (transport->sessiondata_size)
++		session->dd_data = &session[1];
++
+ 	/* this is released in the dev's release function */
+ 	scsi_host_get(shost);
+-	snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", shost->host_no);
++	session->sid = iscsi_session_nr++;
++	snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u",
++		 session->sid);
+ 	session->dev.parent = &shost->shost_gendev;
+ 	session->dev.release = iscsi_session_release;
+ 	err = device_register(&session->dev);
+@@ -301,12 +321,16 @@ static int iscsi_is_conn_dev(const struct device *dev)
+  * This can be called from a LLD or iscsi_transport. The connection
+  * is child of the session so cid must be unique for all connections
+  * on the session.
++ *
++ * Since we do not support MCS, cid will normally be zero. In some cases
++ * for software iscsi we could be trying to preallocate a connection struct
++ * in which case there could be two connection structs and cid would be
++ * non-zero.
+  **/
+ struct iscsi_cls_conn *
+ iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid)
+ {
+ 	struct iscsi_transport *transport = session->transport;
+-	struct Scsi_Host *shost = iscsi_session_to_shost(session);
+ 	struct iscsi_cls_conn *conn;
+ 	int err;
+ 
+@@ -319,12 +343,14 @@ iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid)
+ 
+ 	INIT_LIST_HEAD(&conn->conn_list);
+ 	conn->transport = transport;
++	conn->cid = cid;
+ 
+ 	/* this is released in the dev's release function */
+ 	if (!get_device(&session->dev))
+ 		goto free_conn;
++
+ 	snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
+-		 shost->host_no, cid);
++		 session->sid, cid);
+ 	conn->dev.parent = &session->dev;
+ 	conn->dev.release = iscsi_conn_release;
+ 	err = device_register(&conn->dev);
+@@ -607,7 +633,8 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
+ 	ev->type = ISCSI_KEVENT_RECV_PDU;
+ 	if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
+ 		ev->iferror = -ENOMEM;
+-	ev->r.recv_req.conn_handle = iscsi_handle(conn);
++	ev->r.recv_req.cid = conn->cid;
++	ev->r.recv_req.sid = iscsi_conn_get_sid(conn);
+ 	pdu = (char*)ev + sizeof(*ev);
+ 	memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
+ 	memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
+@@ -639,7 +666,8 @@ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
+ 	if (atomic_read(&conn->z_error->allocated) >= conn->z_error->hiwat)
+ 		ev->iferror = -ENOMEM;
+ 	ev->r.connerror.error = error;
+-	ev->r.connerror.conn_handle = iscsi_handle(conn);
++	ev->r.connerror.cid = conn->cid;
++	ev->r.connerror.sid = iscsi_conn_get_sid(conn);
+ 
+ 	iscsi_unicast_skb(conn->z_error, skb);
+ 
+@@ -689,7 +717,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
+ 			      ISCSI_STATS_CUSTOM_MAX);
+ 	int err = 0;
+ 
+-	conn = iscsi_conn_lookup(ev->u.get_stats.conn_handle);
++	conn = iscsi_conn_lookup(ev->u.get_stats.sid, ev->u.get_stats.cid);
+ 	if (!conn)
+ 		return -EEXIST;
+ 
+@@ -713,8 +741,10 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
+ 		evstat->type = nlh->nlmsg_type;
+ 		if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
+ 			evstat->iferror = -ENOMEM;
+-		evstat->u.get_stats.conn_handle =
+-			ev->u.get_stats.conn_handle;
++		evstat->u.get_stats.cid =
++			ev->u.get_stats.cid;
++		evstat->u.get_stats.sid =
++			ev->u.get_stats.sid;
+ 		stats = (struct iscsi_stats *)
+ 			((char*)evstat + sizeof(*evstat));
+ 		memset(stats, 0, sizeof(*stats));
+@@ -740,16 +770,16 @@ iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
+ {
+ 	struct iscsi_transport *transport = priv->iscsi_transport;
+ 	struct iscsi_cls_session *session;
+-	uint32_t sid;
++	uint32_t hostno;
+ 
+ 	session = transport->create_session(&priv->t,
+ 					    ev->u.c_session.initial_cmdsn,
+-					    &sid);
++					    &hostno);
+ 	if (!session)
+ 		return -ENOMEM;
+ 
+-	ev->r.c_session_ret.session_handle = iscsi_handle(session);
+-	ev->r.c_session_ret.sid = sid;
++	ev->r.c_session_ret.host_no = hostno;
++	ev->r.c_session_ret.sid = session->sid;
+ 	return 0;
+ }
+ 
+@@ -760,13 +790,20 @@ iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+ 	struct iscsi_cls_session *session;
+ 	unsigned long flags;
+ 
+-	session = iscsi_session_lookup(ev->u.c_conn.session_handle);
+-	if (!session)
++	session = iscsi_session_lookup(ev->u.c_conn.sid);
++	if (!session) {
++		printk(KERN_ERR "iscsi: invalid session %d\n",
++		       ev->u.c_conn.sid);
+ 		return -EINVAL;
++	}
+ 
+ 	conn = transport->create_conn(session, ev->u.c_conn.cid);
+-	if (!conn)
++	if (!conn) {
++		printk(KERN_ERR "iscsi: couldn't create a new "
++			   "connection for session %d\n",
++			   session->sid);
+ 		return -ENOMEM;
++	}
+ 
+ 	conn->z_pdu = mempool_zone_init(Z_MAX_PDU,
+ 			NLMSG_SPACE(sizeof(struct iscsi_uevent) +
+@@ -788,7 +825,8 @@ iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+ 		goto free_pdu_pool;
+ 	}
+ 
+-	ev->r.handle = iscsi_handle(conn);
++	ev->r.c_conn_ret.sid = session->sid;
++	ev->r.c_conn_ret.cid = conn->cid;
+ 
+ 	spin_lock_irqsave(&connlock, flags);
+ 	list_add(&conn->conn_list, &connlist);
+@@ -812,7 +850,7 @@ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev
+ 	struct iscsi_cls_conn *conn;
+ 	struct mempool_zone *z_error, *z_pdu;
+ 
+-	conn = iscsi_conn_lookup(ev->u.d_conn.conn_handle);
++	conn = iscsi_conn_lookup(ev->u.d_conn.sid, ev->u.d_conn.cid);
+ 	if (!conn)
+ 		return -EINVAL;
+ 	spin_lock_irqsave(&connlock, flags);
+@@ -855,7 +893,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 		err = iscsi_if_create_session(priv, ev);
+ 		break;
+ 	case ISCSI_UEVENT_DESTROY_SESSION:
+-		session = iscsi_session_lookup(ev->u.d_session.session_handle);
++		session = iscsi_session_lookup(ev->u.d_session.sid);
+ 		if (session)
+ 			transport->destroy_session(session);
+ 		else
+@@ -868,8 +906,8 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 		err = iscsi_if_destroy_conn(transport, ev);
+ 		break;
+ 	case ISCSI_UEVENT_BIND_CONN:
+-		session = iscsi_session_lookup(ev->u.b_conn.session_handle);
+-		conn = iscsi_conn_lookup(ev->u.b_conn.conn_handle);
++		session = iscsi_session_lookup(ev->u.b_conn.sid);
++		conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid);
+ 
+ 		if (session && conn)
+ 			ev->r.retcode =	transport->bind_conn(session, conn,
+@@ -879,7 +917,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 			err = -EINVAL;
+ 		break;
+ 	case ISCSI_UEVENT_SET_PARAM:
+-		conn = iscsi_conn_lookup(ev->u.set_param.conn_handle);
++		conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid);
+ 		if (conn)
+ 			ev->r.retcode =	transport->set_param(conn,
+ 				ev->u.set_param.param, ev->u.set_param.value);
+@@ -887,7 +925,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 			err = -EINVAL;
+ 		break;
+ 	case ISCSI_UEVENT_START_CONN:
+-		conn = iscsi_conn_lookup(ev->u.start_conn.conn_handle);
++		conn = iscsi_conn_lookup(ev->u.start_conn.sid, ev->u.start_conn.cid);
+ 		if (conn)
+ 			ev->r.retcode = transport->start_conn(conn);
+ 		else
+@@ -895,14 +933,14 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 
+ 		break;
+ 	case ISCSI_UEVENT_STOP_CONN:
+-		conn = iscsi_conn_lookup(ev->u.stop_conn.conn_handle);
++		conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ev->u.stop_conn.cid);
+ 		if (conn)
+ 			transport->stop_conn(conn, ev->u.stop_conn.flag);
+ 		else
+ 			err = -EINVAL;
+ 		break;
+ 	case ISCSI_UEVENT_SEND_PDU:
+-		conn = iscsi_conn_lookup(ev->u.send_pdu.conn_handle);
++		conn = iscsi_conn_lookup(ev->u.send_pdu.sid, ev->u.send_pdu.cid);
+ 		if (conn)
+ 			ev->r.retcode =	transport->send_pdu(conn,
+ 				(struct iscsi_hdr*)((char*)ev + sizeof(*ev)),
+@@ -923,9 +961,11 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 	return err;
+ }
+ 
+-/* Get message from skb (based on rtnetlink_rcv_skb).  Each message is
+- * processed by iscsi_if_recv_msg.  Malformed skbs with wrong length are
+- * or invalid creds discarded silently.  */
++/*
++ * Get message from skb (based on rtnetlink_rcv_skb).  Each message is
++ * processed by iscsi_if_recv_msg.  Malformed skbs with wrong lengths or
++ * invalid creds are discarded silently.
++ */
+ static void
+ iscsi_if_rx(struct sock *sk, int len)
+ {
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index e5618b90996e..933a91b1474e 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -60,59 +60,68 @@ struct iscsi_uevent {
+ 			uint32_t	initial_cmdsn;
+ 		} c_session;
+ 		struct msg_destroy_session {
+-			uint64_t	session_handle;
+ 			uint32_t	sid;
+ 		} d_session;
+ 		struct msg_create_conn {
+-			uint64_t	session_handle;
+-			uint32_t	cid;
+ 			uint32_t	sid;
++			uint32_t	cid;
+ 		} c_conn;
+ 		struct msg_bind_conn {
+-			uint64_t	session_handle;
+-			uint64_t	conn_handle;
++			uint32_t	sid;
++			uint32_t	cid;
+ 			uint32_t	transport_fd;
+ 			uint32_t	is_leading;
+ 		} b_conn;
+ 		struct msg_destroy_conn {
+-			uint64_t	conn_handle;
++			uint32_t	sid;
+ 			uint32_t	cid;
+ 		} d_conn;
+ 		struct msg_send_pdu {
++			uint32_t	sid;
++			uint32_t	cid;
+ 			uint32_t	hdr_size;
+ 			uint32_t	data_size;
+-			uint64_t	conn_handle;
+ 		} send_pdu;
+ 		struct msg_set_param {
+-			uint64_t	conn_handle;
++			uint32_t	sid;
++			uint32_t	cid;
+ 			uint32_t	param; /* enum iscsi_param */
+ 			uint32_t	value;
+ 		} set_param;
+ 		struct msg_start_conn {
+-			uint64_t	conn_handle;
++			uint32_t	sid;
++			uint32_t	cid;
+ 		} start_conn;
+ 		struct msg_stop_conn {
++			uint32_t	sid;
++			uint32_t	cid;
+ 			uint64_t	conn_handle;
+ 			uint32_t	flag;
+ 		} stop_conn;
+ 		struct msg_get_stats {
+-			uint64_t	conn_handle;
++			uint32_t	sid;
++			uint32_t	cid;
+ 		} get_stats;
+ 	} u;
+ 	union {
+ 		/* messages k -> u */
+-		uint64_t		handle;
+ 		int			retcode;
+ 		struct msg_create_session_ret {
+-			uint64_t	session_handle;
+ 			uint32_t	sid;
++			uint32_t	host_no;
+ 		} c_session_ret;
++		struct msg_create_conn_ret {
++			uint32_t	sid;
++			uint32_t	cid;
++		} c_conn_ret;
+ 		struct msg_recv_req {
++			uint32_t	sid;
++			uint32_t	cid;
+ 			uint64_t	recv_handle;
+-			uint64_t	conn_handle;
+ 		} recv_req;
+ 		struct msg_conn_error {
+-			uint64_t	conn_handle;
++			uint32_t	sid;
++			uint32_t	cid;
+ 			uint32_t	error; /* enum iscsi_err */
+ 		} connerror;
+ 	} r;
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index b41cf077e54b..631463cd4892 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -60,11 +60,13 @@ struct iscsi_transport {
+ 	int ihostdata_size;
+ 	/* LLD connection data size */
+ 	int conndata_size;
++	/* LLD session data size */
++	int sessiondata_size;
+ 	int max_lun;
+ 	unsigned int max_conn;
+ 	unsigned int max_cmd_len;
+ 	struct iscsi_cls_session *(*create_session)
+-		(struct scsi_transport_template *t, uint32_t sn, uint32_t *sid);
++		(struct scsi_transport_template *t, uint32_t sn, uint32_t *hn);
+ 	void (*destroy_session) (struct iscsi_cls_session *session);
+ 	struct iscsi_cls_conn *(*create_conn) (struct iscsi_cls_session *sess,
+ 				uint32_t cid);
+@@ -104,6 +106,7 @@ struct iscsi_cls_conn {
+ 	struct list_head conn_list;	/* item in connlist */
+ 	void *dd_data;			/* LLD private data */
+ 	struct iscsi_transport *transport;
++	uint32_t cid;			/* connection id */
+ 	int active;			/* must be accessed with the connlock */
+ 	struct device dev;		/* sysfs transport/container device */
+ 	struct mempool_zone *z_error;
+@@ -117,6 +120,8 @@ struct iscsi_cls_conn {
+ struct iscsi_cls_session {
+ 	struct list_head sess_list;		/* item in session_list */
+ 	struct iscsi_transport *transport;
++	int sid;				/* session id */
++	void *dd_data;				/* LLD private data */
+ 	struct device dev;	/* sysfs transport/container device */
+ };
+ 

commit 18c49b8cd69c360735df2cc6eeeb2593c01a81e8
+Author: Mike Christie 
+Date:   Wed Mar 22 16:04:38 2006 -0600
+
+    [SCSI] fix sg leak when scsi_execute_async fails
+    
+    Doug found a bug where if scsi_execute_async fails, we are leaking
+    sg resources. scsi_do_req never failed so we did not have to handle
+    that case before.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
+index fcf9243dfa7d..bfa86b378fb9 100644
+--- a/drivers/scsi/sg.c
++++ b/drivers/scsi/sg.c
+@@ -748,6 +748,7 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
+ 		/*
+ 		 * most likely out of mem, but could also be a bad map
+ 		 */
++		sg_finish_rem_req(srp);
+ 		return -ENOMEM;
+ 	} else
+ 		return 0;

commit 28832e83379afd0b0e83b78ac317290c79ebd496
+Author: Mike Christie 
+Date:   Wed Mar 8 11:19:51 2006 +0100
+
+    [PATCH] update max_sectors documentation
+    
+    The max_sectors has been split into max_hw_sectors and max_sectors for some
+    time. A patch to have blk_queue_max_sectors enforce this was sent by
+    me and it broke IDE. This patch updates the documentation.
+    
+    Signed-off-by: Jens Axboe 
+
+diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt
+index 8e63831971d5..f989a9e839b4 100644
+--- a/Documentation/block/biodoc.txt
++++ b/Documentation/block/biodoc.txt
+@@ -132,8 +132,18 @@ Some new queue property settings:
+ 		limit. No highmem default.
+ 
+ 	blk_queue_max_sectors(q, max_sectors)
+-		Maximum size request you can handle in units of 512 byte
+-		sectors. 255 default.
++		Sets two variables that limit the size of the request.
++
++		- The request queue's max_sectors, which is a soft size in
++		in units of 512 byte sectors, and could be dynamically varied
++		by the core kernel.
++
++		- The request queue's max_hw_sectors, which is a hard limit
++		and reflects the maximum size request a driver can handle
++		in units of 512 byte sectors.
++
++		The default for both max_sectors and max_hw_sectors is
++		255. The upper limit of max_sectors is 1024.
+ 
+ 	blk_queue_max_phys_segments(q, max_segments)
+ 		Maximum physical segments you can handle in a request. 128

commit ba3af0aff042caa1f41b5f7164cab37c717b8811
+Author: Mike Christie 
+Date:   Wed Feb 22 02:11:59 2006 -0600
+
+    [SCSI] don't call ips_eh_reset in ips_queue to avoid deadlock
+    
+    When the locking was changed in the eh code ips_eh_reset was changed
+    so that it was a wraper around __ips_eh_reset and all ips_eh_reset
+    does is grab the host lock and then calls __ips_eh_reset.
+    
+    In the queuecommand, ips_queue is called with the host_lock held so if
+    it calls ips_eh_reset we will have a problem. This patch just has
+    ips_queue call __ips_eh_reset.
+    
+    Patch is only compile tested. I do not have the HW.
+    
+    Signed-off-by: Mike Christie 
+    Acked-by: Hammer, Jack 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
+index 86c546164da9..481708d527ae 100644
+--- a/drivers/scsi/ips.c
++++ b/drivers/scsi/ips.c
+@@ -1146,7 +1146,7 @@ ips_queue(Scsi_Cmnd * SC, void (*done) (Scsi_Cmnd *))
+ 				return (0);
+ 			}
+ 			ha->ioctl_reset = 1;	/* This reset request is from an IOCTL */
+-			ips_eh_reset(SC);
++			__ips_eh_reset(SC);
+ 			SC->result = DID_OK << 16;
+ 			SC->scsi_done(SC);
+ 			return (0);

commit b5b81016538cf84a10c80438b7aa750dd375ba93
+Author: Mike Christie 
+Date:   Wed Feb 1 21:07:14 2006 -0600
+
+    [SCSI] iscsi update: rm unused sessions list
+    
+    rm unused sessions list.
+    
+    This patch is last becuase I was not sure if this patchset was
+    going to be applied over the kmalloc2kzalloc one by JesS. If it
+    is then this patch will not apply and can be dropped for now. I will
+    resend later when things setttle down.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 55860d26f999..71e54a64adca 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -38,10 +38,6 @@ struct iscsi_internal {
+ 	struct scsi_transport_template t;
+ 	struct iscsi_transport *iscsi_transport;
+ 	struct list_head list;
+-	/*
+-	 * List of sessions for this transport
+-	 */
+-	struct list_head sessions;
+ 	/*
+ 	 * based on transport capabilities, at register time we set these
+ 	 * bits to tell the transport class it wants attributes displayed
+@@ -1126,7 +1122,6 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 		return NULL;
+ 	memset(priv, 0, sizeof(*priv));
+ 	INIT_LIST_HEAD(&priv->list);
+-	INIT_LIST_HEAD(&priv->sessions);
+ 	priv->iscsi_transport = tt;
+ 
+ 	priv->cdev.class = &iscsi_transport_class;

commit 28e5554df63085be3b8bd2aee6ddbc479f0d136e
+Author: Mike Christie 
+Date:   Wed Feb 1 21:07:11 2006 -0600
+
+    [SCSI] iscsi update: use gfp_t
+    
+    Use gfp_t. I accidentally removed this in our last update.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 7fb69183c72d..55860d26f999 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -489,7 +489,7 @@ static inline struct list_head *skb_to_lh(struct sk_buff *skb)
+ }
+ 
+ static void*
+-mempool_zone_alloc_skb(unsigned int gfp_mask, void *pool_data)
++mempool_zone_alloc_skb(gfp_t gfp_mask, void *pool_data)
+ {
+ 	struct mempool_zone *zone = pool_data;
+ 

commit b36ae07cb7757bd3eabd13c79844083dccac2f77
+Author: Mike Christie 
+Date:   Wed Feb 1 21:07:09 2006 -0600
+
+    [SCSI] iscsi update: fix mgmt pool err path release
+    
+    >From ogerlitz@voltaire.com:
+    
+    mgmtpool shoild be frees in immdata_alloc_fail label.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 579eecfd186e..ff79e68b347c 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -3316,8 +3316,8 @@ iscsi_session_create(struct scsi_transport_template *scsit,
+ r2tpool_alloc_fail:
+ 	for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++)
+ 		kfree(session->mgmt_cmds[cmd_i]->data);
+-	iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
+ immdata_alloc_fail:
++	iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
+ mgmtpool_alloc_fail:
+ 	iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
+ cmdpool_alloc_fail:

commit 351f739e68e97a0316136a5bda145b952d99a989
+Author: Mike Christie 
+Date:   Wed Feb 1 21:07:06 2006 -0600
+
+    [SCSI] iscsi update: set correct state at creation time
+    
+    >From erezz@voltaire.com:
+    
+    We are still in ISCSI_STATE_FREE state at create time. The addition
+    of the first connection puts us in ISCSI_STATE_LOGGED_IN.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 0cd78b1d1aaa..579eecfd186e 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -3267,7 +3267,7 @@ iscsi_session_create(struct scsi_transport_template *scsit,
+ 	session = iscsi_hostdata(shost->hostdata);
+ 	memset(session, 0, sizeof(struct iscsi_session));
+ 	session->host = shost;
+-	session->state = ISCSI_STATE_LOGGED_IN;
++	session->state = ISCSI_STATE_FREE;
+ 	session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
+ 	session->cmds_max = ISCSI_XMIT_CMDS_MAX;
+ 	session->cmdsn = initial_cmdsn;

commit 1fd459e367657f595ddf192b9a46298e18d4fc13
+Author: Mike Christie 
+Date:   Wed Feb 1 21:07:03 2006 -0600
+
+    [SCSI] iscsi update: rm conn lock
+    
+    >From erezz@voltaire.com:
+    
+    rm conn->lock since it is not used anymore. The dataqueue is protected
+    by the session lock and xmitmutex.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index d07d309ac026..0cd78b1d1aaa 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -244,12 +244,10 @@ iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	if (sc->sc_data_direction == DMA_TO_DEVICE) {
+ 		struct iscsi_data_task *dtask, *n;
+ 		/* WRITE: cleanup Data-Out's if any */
+-		spin_lock(&conn->lock);
+ 		list_for_each_entry_safe(dtask, n, &ctask->dataqueue, item) {
+ 			list_del(&dtask->item);
+ 			mempool_free(dtask, ctask->datapool);
+ 		}
+-		spin_unlock(&conn->lock);
+ 	}
+ 	ctask->xmstate = XMSTATE_IDLE;
+ 	ctask->r2t = NULL;
+@@ -2453,8 +2451,6 @@ iscsi_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ 	conn->data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
+ 	conn->max_recv_dlength = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
+ 
+-	spin_lock_init(&conn->lock);
+-
+ 	/* initialize general xmit PDU commands queue */
+ 	conn->xmitqueue = kfifo_alloc(session->cmds_max * sizeof(void*),
+ 					GFP_KERNEL, NULL);
+diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
+index 6766b817db2d..ba26741ac154 100644
+--- a/drivers/scsi/iscsi_tcp.h
++++ b/drivers/scsi/iscsi_tcp.h
+@@ -146,7 +146,6 @@ struct iscsi_conn {
+ 	struct iscsi_mgmt_task	*login_mtask;	/* mtask used for login/text */
+ 	struct iscsi_mgmt_task	*mtask;		/* xmit mtask in progress */
+ 	struct iscsi_cmd_task	*ctask;		/* xmit ctask in progress */
+-	spinlock_t		lock;		/* FIXME: to be removed */
+ 
+ 	/* old values for socket callbacks */
+ 	void			(*old_data_ready)(struct sock *, int);

commit ee7f8e405342722e42c15fe8e841a679f8951eea
+Author: Mike Christie 
+Date:   Wed Feb 1 21:07:01 2006 -0600
+
+    [SCSI] iscsi update: set deamon pid earlier
+    
+    >From michaelc@cs.wisc.edu:
+    
+    If the transport lookup fails we set the daemon pid too late.
+    This can cause us deadlock since the netlink code will think we
+    meant to call back into our iscsi_if_rx function.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 448fd78777f9..7fb69183c72d 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -846,9 +846,6 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 	struct iscsi_cls_session *session;
+ 	struct iscsi_cls_conn *conn;
+ 
+-	if (NETLINK_CREDS(skb)->uid)
+-		return -EPERM;
+-
+ 	priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle));
+ 	if (!priv)
+ 		return -EINVAL;
+@@ -857,8 +854,6 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 	if (!try_module_get(transport->owner))
+ 		return -EINVAL;
+ 
+-	daemon_pid = NETLINK_CREDS(skb)->pid;
+-
+ 	switch (nlh->nlmsg_type) {
+ 	case ISCSI_UEVENT_CREATE_SESSION:
+ 		err = iscsi_if_create_session(priv, ev);
+@@ -934,7 +929,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 
+ /* Get message from skb (based on rtnetlink_rcv_skb).  Each message is
+  * processed by iscsi_if_recv_msg.  Malformed skbs with wrong length are
+- * discarded silently.  */
++ * or invalid creds discarded silently.  */
+ static void
+ iscsi_if_rx(struct sock *sk, int len)
+ {
+@@ -942,6 +937,12 @@ iscsi_if_rx(struct sock *sk, int len)
+ 
+ 	mutex_lock(&rx_queue_mutex);
+ 	while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
++		if (NETLINK_CREDS(skb)->uid) {
++			skb_pull(skb, skb->len);
++			goto free_skb;
++		}
++		daemon_pid = NETLINK_CREDS(skb)->pid;
++
+ 		while (skb->len >= NLMSG_SPACE(0)) {
+ 			int err;
+ 			uint32_t rlen;
+@@ -953,10 +954,12 @@ iscsi_if_rx(struct sock *sk, int len)
+ 			    skb->len < nlh->nlmsg_len) {
+ 				break;
+ 			}
++
+ 			ev = NLMSG_DATA(nlh);
+ 			rlen = NLMSG_ALIGN(nlh->nlmsg_len);
+ 			if (rlen > skb->len)
+ 				rlen = skb->len;
++
+ 			err = iscsi_if_recv_msg(skb, nlh);
+ 			if (err) {
+ 				ev->type = ISCSI_KEVENT_IF_ERROR;
+@@ -980,6 +983,7 @@ iscsi_if_rx(struct sock *sk, int len)
+ 			} while (err < 0 && err != -ECONNREFUSED);
+ 			skb_pull(skb, rlen);
+ 		}
++free_skb:
+ 		kfree_skb(skb);
+ 	}
+ 	mutex_unlock(&rx_queue_mutex);

commit 142e301fc818de9b116706835cd9fc864e73f203
+Author: Mike Christie 
+Date:   Wed Feb 1 21:06:58 2006 -0600
+
+    [SCSI] iscsi update: setup pool before using
+    
+    >From andmike@us.ibm.com:
+    
+     Ensure that pool data is setup prior to calling mempool_create as it will
+     call the the alloc function during create.
+    
+    Signed-off-by: Mike Anderson 
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 79ca29ee1aee..448fd78777f9 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -530,6 +530,12 @@ mempool_zone_init(unsigned max, unsigned size, unsigned hiwat)
+ 	if (!zp)
+ 		return NULL;
+ 
++	zp->size = size;
++	zp->hiwat = hiwat;
++	INIT_LIST_HEAD(&zp->freequeue);
++	spin_lock_init(&zp->freelock);
++	atomic_set(&zp->allocated, 0);
++
+ 	zp->pool = mempool_create(max, mempool_zone_alloc_skb,
+ 				  mempool_zone_free_skb, zp);
+ 	if (!zp->pool) {
+@@ -537,13 +543,6 @@ mempool_zone_init(unsigned max, unsigned size, unsigned hiwat)
+ 		return NULL;
+ 	}
+ 
+-	zp->size = size;
+-	zp->hiwat = hiwat;
+-
+-	INIT_LIST_HEAD(&zp->freequeue);
+-	spin_lock_init(&zp->freelock);
+-	atomic_set(&zp->allocated, 0);
+-
+ 	return zp;
+ }
+ 

commit 5b940adf5b341b12dbb94e7cbdb416b35f52017b
+Author: Mike Christie 
+Date:   Wed Feb 1 21:06:56 2006 -0600
+
+    [SCSI] iscsi update: pass correct skb to skb_trim
+    
+    >From da-x@monatomic.org:
+    
+    Wrong skb is passed to skb_trim in iscsi_if_get_stats.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index b61868587dca..79ca29ee1aee 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -680,8 +680,7 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi,
+ }
+ 
+ static int
+-iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
+-		   struct nlmsghdr *nlh)
++iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
+ {
+ 	struct iscsi_uevent *ev = NLMSG_DATA(nlh);
+ 	struct iscsi_stats *stats;
+@@ -732,7 +731,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
+ 					  stats->custom_length);
+ 		actual_size -= sizeof(*nlhstat);
+ 		actual_size = NLMSG_LENGTH(actual_size);
+-		skb_trim(skb, NLMSG_ALIGN(actual_size));
++		skb_trim(skbstat, NLMSG_ALIGN(actual_size));
+ 		nlhstat->nlmsg_len = actual_size;
+ 
+ 		err = iscsi_unicast_skb(conn->z_pdu, skbstat);
+@@ -923,7 +922,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 			err = -EINVAL;
+ 		break;
+ 	case ISCSI_UEVENT_GET_STATS:
+-		err = iscsi_if_get_stats(transport, skb, nlh);
++		err = iscsi_if_get_stats(transport, nlh);
+ 		break;
+ 	default:
+ 		err = -EINVAL;

commit 7b7232f3fb5ecd7c30cb52df368070cc5f5ca614
+Author: Mike Christie 
+Date:   Wed Feb 1 21:06:49 2006 -0600
+
+    [SCSI] iscsi update: cleanup iscsi class interface
+    
+    From:
+    michaelc@cs.wisc.edu
+    fujita.tomonori@lab.ntt.co.jp
+    da-x@monatomic.org
+    
+    and err path fixup from:
+    ogerlitz@voltaire.com
+    
+    This patch cleans up that interface by having the lld and class
+    pass a iscsi_cls_session or iscsi_cls_conn between each other when
+    the function is used by HW and SW iscsi llds. This way the lld
+    does not have to remember if it has to send a handle or pointer
+    and a handle or pointer to connection, session or host.
+    
+    This also has the class verify the session handle that gets passed from
+    userspace instead of using the pointer passed into the kernel directly.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 780bfcc67096..d07d309ac026 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -146,7 +146,7 @@ iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
+ 	spin_unlock_irqrestore(&session->lock, flags);
+ 	set_bit(SUSPEND_BIT, &conn->suspend_tx);
+ 	set_bit(SUSPEND_BIT, &conn->suspend_rx);
+-	iscsi_conn_error(iscsi_handle(conn), err);
++	iscsi_conn_error(conn->cls_conn, err);
+ }
+ 
+ static inline int
+@@ -689,7 +689,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
+ 				break;
+ 
+ 			if (!conn->in.datalen) {
+-				rc = iscsi_recv_pdu(iscsi_handle(conn), hdr,
++				rc = iscsi_recv_pdu(conn->cls_conn, hdr,
+ 						    NULL, 0);
+ 				if (conn->login_mtask != mtask) {
+ 					spin_lock(&session->lock);
+@@ -737,7 +737,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
+ 			if (!conn->in.datalen) {
+ 				struct iscsi_mgmt_task *mtask;
+ 
+-				rc = iscsi_recv_pdu(iscsi_handle(conn), hdr,
++				rc = iscsi_recv_pdu(conn->cls_conn, hdr,
+ 						    NULL, 0);
+ 				mtask = (struct iscsi_mgmt_task *)
+ 					session->mgmt_cmds[conn->in.itt -
+@@ -761,7 +761,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
+ 				rc = iscsi_check_assign_cmdsn(session,
+ 						 (struct iscsi_nopin*)hdr);
+ 				if (!rc && hdr->ttt != ISCSI_RESERVED_TAG)
+-					rc = iscsi_recv_pdu(iscsi_handle(conn),
++					rc = iscsi_recv_pdu(conn->cls_conn,
+ 							    hdr, NULL, 0);
+ 			} else
+ 				rc = ISCSI_ERR_PROTO;
+@@ -1044,7 +1044,7 @@ iscsi_data_recv(struct iscsi_conn *conn)
+ 			goto exit;
+ 		}
+ 
+-		rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr,
++		rc = iscsi_recv_pdu(conn->cls_conn, conn->in.hdr,
+ 				    conn->data, conn->in.datalen);
+ 
+ 		if (!rc && conn->datadgst_en &&
+@@ -2428,19 +2428,20 @@ iscsi_pool_free(struct iscsi_queue *q, void **items)
+ }
+ 
+ static struct iscsi_cls_conn *
+-iscsi_conn_create(struct Scsi_Host *shost, uint32_t conn_idx)
++iscsi_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+ {
++	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+ 	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+ 	struct iscsi_conn *conn;
+ 	struct iscsi_cls_conn *cls_conn;
+ 
+-	cls_conn = iscsi_create_conn(hostdata_session(shost->hostdata),
+-				     conn_idx);
++	cls_conn = iscsi_create_conn(cls_session, conn_idx);
+ 	if (!cls_conn)
+ 		return NULL;
+ 	conn = cls_conn->dd_data;
++	memset(conn, 0, sizeof(*conn));
+ 
+-	memset(conn, 0, sizeof(struct iscsi_conn));
++	conn->cls_conn = cls_conn;
+ 	conn->c_stage = ISCSI_CONN_INITIAL_STAGE;
+ 	conn->in_progress = IN_PROGRESS_WAIT_HEADER;
+ 	conn->id = conn_idx;
+@@ -2625,11 +2626,13 @@ iscsi_conn_destroy(struct iscsi_cls_conn *cls_conn)
+ }
+ 
+ static int
+-iscsi_conn_bind(iscsi_sessionh_t sessionh, iscsi_connh_t connh,
+-		uint32_t transport_fd, int is_leading)
++iscsi_conn_bind(struct iscsi_cls_session *cls_session,
++		struct iscsi_cls_conn *cls_conn, uint32_t transport_fd,
++		int is_leading)
+ {
+-	struct iscsi_session *session = iscsi_ptr(sessionh);
+-	struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = iscsi_ptr(connh);
++	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
++	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
++	struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = cls_conn->dd_data;
+ 	struct sock *sk;
+ 	struct socket *sock;
+ 	int err;
+@@ -2703,9 +2706,9 @@ iscsi_conn_bind(iscsi_sessionh_t sessionh, iscsi_connh_t connh,
+ }
+ 
+ static int
+-iscsi_conn_start(iscsi_connh_t connh)
++iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
+ {
+-	struct iscsi_conn *conn = iscsi_ptr(connh);
++	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	struct iscsi_session *session = conn->session;
+ 	struct sock *sk;
+ 
+@@ -2754,9 +2757,9 @@ iscsi_conn_start(iscsi_connh_t connh)
+ }
+ 
+ static void
+-iscsi_conn_stop(iscsi_connh_t connh, int flag)
++iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+ {
+-	struct iscsi_conn *conn = iscsi_ptr(connh);
++	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	struct iscsi_session *session = conn->session;
+ 	struct sock *sk;
+ 	unsigned long flags;
+@@ -3253,9 +3256,9 @@ static struct scsi_host_template iscsi_sht = {
+ 
+ static struct iscsi_transport iscsi_tcp_transport;
+ 
+-static struct Scsi_Host *
++static struct iscsi_cls_session *
+ iscsi_session_create(struct scsi_transport_template *scsit,
+-		     uint32_t initial_cmdsn)
++		     uint32_t initial_cmdsn, uint32_t *sid)
+ {
+ 	struct Scsi_Host *shost;
+ 	struct iscsi_session *session;
+@@ -3275,6 +3278,7 @@ iscsi_session_create(struct scsi_transport_template *scsit,
+ 	session->exp_cmdsn = initial_cmdsn + 1;
+ 	session->max_cmdsn = initial_cmdsn + 1;
+ 	session->max_r2t = 1;
++	*sid = shost->host_no;
+ 
+ 	/* initialize SCSI PDU commands pool */
+ 	if (iscsi_pool_init(&session->cmdpool, session->cmds_max,
+@@ -3311,7 +3315,7 @@ iscsi_session_create(struct scsi_transport_template *scsit,
+ 	if (iscsi_r2tpool_alloc(session))
+ 		goto r2tpool_alloc_fail;
+ 
+-	return shost;
++	return hostdata_session(shost->hostdata);
+ 
+ r2tpool_alloc_fail:
+ 	for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++)
+@@ -3321,12 +3325,14 @@ iscsi_session_create(struct scsi_transport_template *scsit,
+ mgmtpool_alloc_fail:
+ 	iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
+ cmdpool_alloc_fail:
++	iscsi_transport_destroy_session(shost);
+ 	return NULL;
+ }
+ 
+ static void
+-iscsi_session_destroy(struct Scsi_Host *shost)
++iscsi_session_destroy(struct iscsi_cls_session *cls_session)
+ {
++	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+ 	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+ 	int cmd_i;
+ 	struct iscsi_data_task *dtask, *n;
+@@ -3350,10 +3356,10 @@ iscsi_session_destroy(struct Scsi_Host *shost)
+ }
+ 
+ static int
+-iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param,
++iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
+ 		     uint32_t value)
+ {
+-	struct iscsi_conn *conn = iscsi_ptr(connh);
++	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	struct iscsi_session *session = conn->session;
+ 
+ 	spin_lock_bh(&session->lock);
+@@ -3495,9 +3501,10 @@ iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param,
+ }
+ 
+ static int
+-iscsi_session_get_param(struct Scsi_Host *shost,
++iscsi_session_get_param(struct iscsi_cls_session *cls_session,
+ 			enum iscsi_param param, uint32_t *value)
+ {
++	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+ 	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+ 
+ 	switch(param) {
+@@ -3539,9 +3546,10 @@ iscsi_session_get_param(struct Scsi_Host *shost,
+ }
+ 
+ static int
+-iscsi_conn_get_param(void *data, enum iscsi_param param, uint32_t *value)
++iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
++		     enum iscsi_param param, uint32_t *value)
+ {
+-	struct iscsi_conn *conn = data;
++	struct iscsi_conn *conn = cls_conn->dd_data;
+ 
+ 	switch(param) {
+ 	case ISCSI_PARAM_MAX_RECV_DLENGTH:
+@@ -3564,9 +3572,9 @@ iscsi_conn_get_param(void *data, enum iscsi_param param, uint32_t *value)
+ }
+ 
+ static void
+-iscsi_conn_get_stats(iscsi_connh_t connh, struct iscsi_stats *stats)
++iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats)
+ {
+-	struct iscsi_conn *conn = iscsi_ptr(connh);
++	struct iscsi_conn *conn = cls_conn->dd_data;
+ 
+ 	stats->txdata_octets = conn->txdata_octets;
+ 	stats->rxdata_octets = conn->rxdata_octets;
+@@ -3587,10 +3595,10 @@ iscsi_conn_get_stats(iscsi_connh_t connh, struct iscsi_stats *stats)
+ }
+ 
+ static int
+-iscsi_conn_send_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr, char *data,
+-		    uint32_t data_size)
++iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
++		    char *data, uint32_t data_size)
+ {
+-	struct iscsi_conn *conn = iscsi_ptr(connh);
++	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	int rc;
+ 
+ 	mutex_lock(&conn->xmitmutex);
+diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
+index f95e61b76f70..6766b817db2d 100644
+--- a/drivers/scsi/iscsi_tcp.h
++++ b/drivers/scsi/iscsi_tcp.h
+@@ -113,7 +113,10 @@ struct iscsi_tcp_recv {
+ 	int			datadgst;
+ };
+ 
++struct iscsi_cls_conn;
++
+ struct iscsi_conn {
++	struct iscsi_cls_conn	*cls_conn;	/* ptr to class connection */
+ 	struct iscsi_hdr	hdr;		/* header placeholder */
+ 	char			hdrext[4*sizeof(__u16) +
+ 				    sizeof(__u32)];
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 59a1c9d9d3bd..b61868587dca 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -164,9 +164,43 @@ static struct mempool_zone *z_reply;
+ #define Z_MAX_ERROR	16
+ #define Z_HIWAT_ERROR	12
+ 
++static LIST_HEAD(sesslist);
++static DEFINE_SPINLOCK(sesslock);
+ static LIST_HEAD(connlist);
+ static DEFINE_SPINLOCK(connlock);
+ 
++static struct iscsi_cls_session *iscsi_session_lookup(uint64_t handle)
++{
++	unsigned long flags;
++	struct iscsi_cls_session *sess;
++
++	spin_lock_irqsave(&sesslock, flags);
++	list_for_each_entry(sess, &sesslist, sess_list) {
++		if (sess == iscsi_ptr(handle)) {
++			spin_unlock_irqrestore(&sesslock, flags);
++			return sess;
++		}
++	}
++	spin_unlock_irqrestore(&sesslock, flags);
++	return NULL;
++}
++
++static struct iscsi_cls_conn *iscsi_conn_lookup(uint64_t handle)
++{
++	unsigned long flags;
++	struct iscsi_cls_conn *conn;
++
++	spin_lock_irqsave(&connlock, flags);
++	list_for_each_entry(conn, &connlist, conn_list) {
++		if (conn == iscsi_ptr(handle)) {
++			spin_unlock_irqrestore(&connlock, flags);
++			return conn;
++		}
++	}
++	spin_unlock_irqrestore(&connlock, flags);
++	return NULL;
++}
++
+ /*
+  * The following functions can be used by LLDs that allocate
+  * their own scsi_hosts or by software iscsi LLDs
+@@ -365,6 +399,7 @@ iscsi_transport_create_session(struct scsi_transport_template *scsit,
+ {
+ 	struct iscsi_cls_session *session;
+ 	struct Scsi_Host *shost;
++	unsigned long flags;
+ 
+ 	shost = scsi_host_alloc(transport->host_template,
+ 				hostdata_privsize(transport));
+@@ -389,6 +424,9 @@ iscsi_transport_create_session(struct scsi_transport_template *scsit,
+ 		goto remove_host;
+ 
+ 	*(unsigned long*)shost->hostdata = (unsigned long)session;
++	spin_lock_irqsave(&sesslock, flags);
++	list_add(&session->sess_list, &sesslist);
++	spin_unlock_irqrestore(&sesslock, flags);
+ 	return shost;
+ 
+ remove_host:
+@@ -410,9 +448,13 @@ EXPORT_SYMBOL_GPL(iscsi_transport_create_session);
+ int iscsi_transport_destroy_session(struct Scsi_Host *shost)
+ {
+ 	struct iscsi_cls_session *session;
++	unsigned long flags;
+ 
+ 	scsi_remove_host(shost);
+ 	session = hostdata_session(shost->hostdata);
++	spin_lock_irqsave(&sesslock, flags);
++	list_del(&session->sess_list);
++	spin_unlock_irqrestore(&sesslock, flags);
+ 	iscsi_destroy_session(session);
+ 	/* ref from host alloc */
+ 	scsi_host_put(shost);
+@@ -424,22 +466,6 @@ EXPORT_SYMBOL_GPL(iscsi_transport_destroy_session);
+ /*
+  * iscsi interface functions
+  */
+-static struct iscsi_cls_conn*
+-iscsi_if_find_conn(uint64_t key)
+-{
+-	unsigned long flags;
+-	struct iscsi_cls_conn *conn;
+-
+-	spin_lock_irqsave(&connlock, flags);
+-	list_for_each_entry(conn, &connlist, conn_list)
+-		if (conn->connh == key) {
+-			spin_unlock_irqrestore(&connlock, flags);
+-			return conn;
+-		}
+-	spin_unlock_irqrestore(&connlock, flags);
+-	return NULL;
+-}
+-
+ static struct iscsi_internal *
+ iscsi_if_transport_lookup(struct iscsi_transport *tt)
+ {
+@@ -559,25 +585,21 @@ iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb)
+ 	return 0;
+ }
+ 
+-int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
++int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
+ 		   char *data, uint32_t data_size)
+ {
+ 	struct nlmsghdr	*nlh;
+ 	struct sk_buff *skb;
+ 	struct iscsi_uevent *ev;
+-	struct iscsi_cls_conn *conn;
+ 	char *pdu;
+ 	int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) +
+ 			      data_size);
+ 
+-	conn = iscsi_if_find_conn(connh);
+-	BUG_ON(!conn);
+-
+ 	mempool_zone_complete(conn->z_pdu);
+ 
+ 	skb = mempool_zone_get_skb(conn->z_pdu);
+ 	if (!skb) {
+-		iscsi_conn_error(connh, ISCSI_ERR_CONN_FAILED);
++		iscsi_conn_error(conn, ISCSI_ERR_CONN_FAILED);
+ 		dev_printk(KERN_ERR, &conn->dev, "iscsi: can not deliver "
+ 			   "control PDU: OOM\n");
+ 		return -ENOMEM;
+@@ -590,7 +612,7 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
+ 	ev->type = ISCSI_KEVENT_RECV_PDU;
+ 	if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
+ 		ev->iferror = -ENOMEM;
+-	ev->r.recv_req.conn_handle = connh;
++	ev->r.recv_req.conn_handle = iscsi_handle(conn);
+ 	pdu = (char*)ev + sizeof(*ev);
+ 	memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
+ 	memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
+@@ -599,17 +621,13 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
+ }
+ EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
+ 
+-void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error)
++void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
+ {
+ 	struct nlmsghdr	*nlh;
+ 	struct sk_buff	*skb;
+ 	struct iscsi_uevent *ev;
+-	struct iscsi_cls_conn *conn;
+ 	int len = NLMSG_SPACE(sizeof(*ev));
+ 
+-	conn = iscsi_if_find_conn(connh);
+-	BUG_ON(!conn);
+-
+ 	mempool_zone_complete(conn->z_error);
+ 
+ 	skb = mempool_zone_get_skb(conn->z_error);
+@@ -626,7 +644,7 @@ void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error)
+ 	if (atomic_read(&conn->z_error->allocated) >= conn->z_error->hiwat)
+ 		ev->iferror = -ENOMEM;
+ 	ev->r.connerror.error = error;
+-	ev->r.connerror.conn_handle = connh;
++	ev->r.connerror.conn_handle = iscsi_handle(conn);
+ 
+ 	iscsi_unicast_skb(conn->z_error, skb);
+ 
+@@ -677,7 +695,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
+ 			      ISCSI_STATS_CUSTOM_MAX);
+ 	int err = 0;
+ 
+-	conn = iscsi_if_find_conn(ev->u.get_stats.conn_handle);
++	conn = iscsi_conn_lookup(ev->u.get_stats.conn_handle);
+ 	if (!conn)
+ 		return -EEXIST;
+ 
+@@ -707,7 +725,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
+ 			((char*)evstat + sizeof(*evstat));
+ 		memset(stats, 0, sizeof(*stats));
+ 
+-		transport->get_stats(ev->u.get_stats.conn_handle, stats);
++		transport->get_stats(conn, stats);
+ 		actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) +
+ 					  sizeof(struct iscsi_stats) +
+ 					  sizeof(struct iscsi_stats_custom) *
+@@ -727,58 +745,34 @@ static int
+ iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
+ {
+ 	struct iscsi_transport *transport = priv->iscsi_transport;
+-	struct Scsi_Host *shost;
+-
+-	if (!transport->create_session)
+-		return -EINVAL;
++	struct iscsi_cls_session *session;
++	uint32_t sid;
+ 
+-	shost = transport->create_session(&priv->t,
+-					  ev->u.c_session.initial_cmdsn);
+-	if (!shost)
++	session = transport->create_session(&priv->t,
++					    ev->u.c_session.initial_cmdsn,
++					    &sid);
++	if (!session)
+ 		return -ENOMEM;
+ 
+-	ev->r.c_session_ret.session_handle = iscsi_handle(iscsi_hostdata(shost->hostdata));
+-	ev->r.c_session_ret.sid = shost->host_no;
++	ev->r.c_session_ret.session_handle = iscsi_handle(session);
++	ev->r.c_session_ret.sid = sid;
+ 	return 0;
+ }
+ 
+ static int
+-iscsi_if_destroy_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
++iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+ {
+-	struct iscsi_transport *transport = priv->iscsi_transport;
+-
+-	struct Scsi_Host *shost;
+-
+-	if (!transport->destroy_session)
+-		return -EINVAL;
+-
+-	shost = scsi_host_lookup(ev->u.d_session.sid);
+-	if (shost == ERR_PTR(-ENXIO))
+-		return -EEXIST;
+-
+-	if (transport->destroy_session)
+-		transport->destroy_session(shost);
+-        /* ref from host lookup */
+-        scsi_host_put(shost);
+-	return 0;
+-}
+-
+-static int
+-iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev){
+-	struct Scsi_Host *shost;
+ 	struct iscsi_cls_conn *conn;
++	struct iscsi_cls_session *session;
+ 	unsigned long flags;
+ 
+-	if (!transport->create_conn)
++	session = iscsi_session_lookup(ev->u.c_conn.session_handle);
++	if (!session)
+ 		return -EINVAL;
+ 
+-	shost = scsi_host_lookup(ev->u.c_conn.sid);
+-	if (shost == ERR_PTR(-ENXIO))
+-		return -EEXIST;
+-
+-	conn = transport->create_conn(shost, ev->u.c_conn.cid);
++	conn = transport->create_conn(session, ev->u.c_conn.cid);
+ 	if (!conn)
+-		goto release_ref;
++		return -ENOMEM;
+ 
+ 	conn->z_pdu = mempool_zone_init(Z_MAX_PDU,
+ 			NLMSG_SPACE(sizeof(struct iscsi_uevent) +
+@@ -800,14 +794,13 @@ iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+ 		goto free_pdu_pool;
+ 	}
+ 
+-	ev->r.handle = conn->connh = iscsi_handle(conn->dd_data);
++	ev->r.handle = iscsi_handle(conn);
+ 
+ 	spin_lock_irqsave(&connlock, flags);
+ 	list_add(&conn->conn_list, &connlist);
+ 	conn->active = 1;
+ 	spin_unlock_irqrestore(&connlock, flags);
+ 
+-	scsi_host_put(shost);
+ 	return 0;
+ 
+ free_pdu_pool:
+@@ -815,8 +808,6 @@ iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+ destroy_conn:
+ 	if (transport->destroy_conn)
+ 		transport->destroy_conn(conn->dd_data);
+-release_ref:
+-	scsi_host_put(shost);
+ 	return -ENOMEM;
+ }
+ 
+@@ -827,13 +818,9 @@ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev
+ 	struct iscsi_cls_conn *conn;
+ 	struct mempool_zone *z_error, *z_pdu;
+ 
+-	conn = iscsi_if_find_conn(ev->u.d_conn.conn_handle);
++	conn = iscsi_conn_lookup(ev->u.d_conn.conn_handle);
+ 	if (!conn)
+-		return -EEXIST;
+-
+-	if (!transport->destroy_conn)
+ 		return -EINVAL;
+-
+ 	spin_lock_irqsave(&connlock, flags);
+ 	conn->active = 0;
+ 	list_del(&conn->conn_list);
+@@ -858,6 +845,8 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 	struct iscsi_uevent *ev = NLMSG_DATA(nlh);
+ 	struct iscsi_transport *transport = NULL;
+ 	struct iscsi_internal *priv;
++	struct iscsi_cls_session *session;
++	struct iscsi_cls_conn *conn;
+ 
+ 	if (NETLINK_CREDS(skb)->uid)
+ 		return -EPERM;
+@@ -867,6 +856,9 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 		return -EINVAL;
+ 	transport = priv->iscsi_transport;
+ 
++	if (!try_module_get(transport->owner))
++		return -EINVAL;
++
+ 	daemon_pid = NETLINK_CREDS(skb)->pid;
+ 
+ 	switch (nlh->nlmsg_type) {
+@@ -874,7 +866,11 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 		err = iscsi_if_create_session(priv, ev);
+ 		break;
+ 	case ISCSI_UEVENT_DESTROY_SESSION:
+-		err = iscsi_if_destroy_session(priv, ev);
++		session = iscsi_session_lookup(ev->u.d_session.session_handle);
++		if (session)
++			transport->destroy_session(session);
++		else
++			err = -EINVAL;
+ 		break;
+ 	case ISCSI_UEVENT_CREATE_CONN:
+ 		err = iscsi_if_create_conn(transport, ev);
+@@ -883,41 +879,48 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 		err = iscsi_if_destroy_conn(transport, ev);
+ 		break;
+ 	case ISCSI_UEVENT_BIND_CONN:
+-		if (!iscsi_if_find_conn(ev->u.b_conn.conn_handle))
+-			return -EEXIST;
+-		ev->r.retcode = transport->bind_conn(
+-			ev->u.b_conn.session_handle,
+-			ev->u.b_conn.conn_handle,
+-			ev->u.b_conn.transport_fd,
+-			ev->u.b_conn.is_leading);
++		session = iscsi_session_lookup(ev->u.b_conn.session_handle);
++		conn = iscsi_conn_lookup(ev->u.b_conn.conn_handle);
++
++		if (session && conn)
++			ev->r.retcode =	transport->bind_conn(session, conn,
++					ev->u.b_conn.transport_fd,
++					ev->u.b_conn.is_leading);
++		else
++			err = -EINVAL;
+ 		break;
+ 	case ISCSI_UEVENT_SET_PARAM:
+-		if (!iscsi_if_find_conn(ev->u.set_param.conn_handle))
+-			return -EEXIST;
+-		ev->r.retcode = transport->set_param(
+-			ev->u.set_param.conn_handle,
+-			ev->u.set_param.param, ev->u.set_param.value);
++		conn = iscsi_conn_lookup(ev->u.set_param.conn_handle);
++		if (conn)
++			ev->r.retcode =	transport->set_param(conn,
++				ev->u.set_param.param, ev->u.set_param.value);
++		else
++			err = -EINVAL;
+ 		break;
+ 	case ISCSI_UEVENT_START_CONN:
+-		if (!iscsi_if_find_conn(ev->u.start_conn.conn_handle))
+-			return -EEXIST;
+-		ev->r.retcode = transport->start_conn(
+-			ev->u.start_conn.conn_handle);
++		conn = iscsi_conn_lookup(ev->u.start_conn.conn_handle);
++		if (conn)
++			ev->r.retcode = transport->start_conn(conn);
++		else
++			err = -EINVAL;
++
+ 		break;
+ 	case ISCSI_UEVENT_STOP_CONN:
+-		if (!iscsi_if_find_conn(ev->u.stop_conn.conn_handle))
+-			return -EEXIST;
+-		transport->stop_conn(ev->u.stop_conn.conn_handle,
+-			ev->u.stop_conn.flag);
++		conn = iscsi_conn_lookup(ev->u.stop_conn.conn_handle);
++		if (conn)
++			transport->stop_conn(conn, ev->u.stop_conn.flag);
++		else
++			err = -EINVAL;
+ 		break;
+ 	case ISCSI_UEVENT_SEND_PDU:
+-		if (!iscsi_if_find_conn(ev->u.send_pdu.conn_handle))
+-			return -EEXIST;
+-		ev->r.retcode = transport->send_pdu(
+-		       ev->u.send_pdu.conn_handle,
+-		       (struct iscsi_hdr*)((char*)ev + sizeof(*ev)),
+-		       (char*)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size,
+-			ev->u.send_pdu.data_size);
++		conn = iscsi_conn_lookup(ev->u.send_pdu.conn_handle);
++		if (conn)
++			ev->r.retcode =	transport->send_pdu(conn,
++				(struct iscsi_hdr*)((char*)ev + sizeof(*ev)),
++				(char*)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size,
++				ev->u.send_pdu.data_size);
++		else
++			err = -EINVAL;
+ 		break;
+ 	case ISCSI_UEVENT_GET_STATS:
+ 		err = iscsi_if_get_stats(transport, skb, nlh);
+@@ -927,6 +930,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 		break;
+ 	}
+ 
++	module_put(transport->owner);
+ 	return err;
+ }
+ 
+@@ -997,7 +1001,7 @@ show_conn_int_param_##param(struct class_device *cdev, char *buf)	\
+ 	struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev);		\
+ 	struct iscsi_transport *t = conn->transport;			\
+ 									\
+-	t->get_conn_param(conn->dd_data, param, &value);		\
++	t->get_conn_param(conn, param, &value);				\
+ 	return snprintf(buf, 20, format"\n", value);			\
+ }
+ 
+@@ -1024,10 +1028,9 @@ show_session_int_param_##param(struct class_device *cdev, char *buf)	\
+ {									\
+ 	uint32_t value = 0;						\
+ 	struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev);	\
+-	struct Scsi_Host *shost = iscsi_session_to_shost(session);	\
+ 	struct iscsi_transport *t = session->transport;			\
+ 									\
+-	t->get_session_param(shost, param, &value);			\
++	t->get_session_param(session, param, &value);			\
+ 	return snprintf(buf, 20, format"\n", value);			\
+ }
+ 
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index 3e5cb5ab2d34..e5618b90996e 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -163,9 +163,6 @@ enum iscsi_param {
+ };
+ #define ISCSI_PARAM_MAX			14
+ 
+-typedef uint64_t iscsi_sessionh_t;	/* iSCSI Data-Path session handle */
+-typedef uint64_t iscsi_connh_t;		/* iSCSI Data-Path connection handle */
+-
+ #define iscsi_ptr(_handle) ((void*)(unsigned long)_handle)
+ #define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr)
+ #define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata))
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 16602a547a63..b41cf077e54b 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -63,25 +63,28 @@ struct iscsi_transport {
+ 	int max_lun;
+ 	unsigned int max_conn;
+ 	unsigned int max_cmd_len;
+-	struct Scsi_Host *(*create_session) (struct scsi_transport_template *t,
+-					     uint32_t initial_cmdsn);
+-	void (*destroy_session) (struct Scsi_Host *shost);
+-	struct iscsi_cls_conn *(*create_conn) (struct Scsi_Host *shost,
++	struct iscsi_cls_session *(*create_session)
++		(struct scsi_transport_template *t, uint32_t sn, uint32_t *sid);
++	void (*destroy_session) (struct iscsi_cls_session *session);
++	struct iscsi_cls_conn *(*create_conn) (struct iscsi_cls_session *sess,
+ 				uint32_t cid);
+-	int (*bind_conn) (iscsi_sessionh_t session, iscsi_connh_t conn,
++	int (*bind_conn) (struct iscsi_cls_session *session,
++			  struct iscsi_cls_conn *cls_conn,
+ 			  uint32_t transport_fd, int is_leading);
+-	int (*start_conn) (iscsi_connh_t conn);
+-	void (*stop_conn) (iscsi_connh_t conn, int flag);
++	int (*start_conn) (struct iscsi_cls_conn *conn);
++	void (*stop_conn) (struct iscsi_cls_conn *conn, int flag);
+ 	void (*destroy_conn) (struct iscsi_cls_conn *conn);
+-	int (*set_param) (iscsi_connh_t conn, enum iscsi_param param,
++	int (*set_param) (struct iscsi_cls_conn *conn, enum iscsi_param param,
+ 			  uint32_t value);
+-	int (*get_conn_param) (void *conndata, enum iscsi_param param,
++	int (*get_conn_param) (struct iscsi_cls_conn *conn,
++			       enum iscsi_param param,
+ 			       uint32_t *value);
+-	int (*get_session_param) (struct Scsi_Host *shost,
++	int (*get_session_param) (struct iscsi_cls_session *session,
+ 				  enum iscsi_param param, uint32_t *value);
+-	int (*send_pdu) (iscsi_connh_t conn, struct iscsi_hdr *hdr,
++	int (*send_pdu) (struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
+ 			 char *data, uint32_t data_size);
+-	void (*get_stats) (iscsi_connh_t conn, struct iscsi_stats *stats);
++	void (*get_stats) (struct iscsi_cls_conn *conn,
++			   struct iscsi_stats *stats);
+ };
+ 
+ /*
+@@ -93,15 +96,14 @@ extern int iscsi_unregister_transport(struct iscsi_transport *tt);
+ /*
+  * control plane upcalls
+  */
+-extern void iscsi_conn_error(iscsi_connh_t conn, enum iscsi_err error);
+-extern int iscsi_recv_pdu(iscsi_connh_t conn, struct iscsi_hdr *hdr,
++extern void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error);
++extern int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
+ 			  char *data, uint32_t data_size);
+ 
+ struct iscsi_cls_conn {
+ 	struct list_head conn_list;	/* item in connlist */
+ 	void *dd_data;			/* LLD private data */
+ 	struct iscsi_transport *transport;
+-	iscsi_connh_t connh;
+ 	int active;			/* must be accessed with the connlock */
+ 	struct device dev;		/* sysfs transport/container device */
+ 	struct mempool_zone *z_error;
+@@ -113,7 +115,7 @@ struct iscsi_cls_conn {
+ 	container_of(_dev, struct iscsi_cls_conn, dev)
+ 
+ struct iscsi_cls_session {
+-	struct list_head list;	/* item in session_list */
++	struct list_head sess_list;		/* item in session_list */
+ 	struct iscsi_transport *transport;
+ 	struct device dev;	/* sysfs transport/container device */
+ };

commit a1e80c20e1ac751dbdd88dee989e9a19c22c4a84
+Author: Mike Christie 
+Date:   Fri Jan 13 18:05:56 2006 -0600
+
+    [SCSI] iscsi: use pageslab
+    
+    From: FUJITA Tomonori  and zhenyu.z.wang@intel.com:
+    
+    We cannot handle filesystems like XFS becuase of the pages they
+    are sending us. We had thought page_count could be used to
+    work around this, but the correct test is for PageSlab.
+    
+    The proper solution is to figure out what type of pages
+    filesystems can use so we do not have to add tests like
+    this or handle it in the block layer for all network block drivers
+    but the issue still has not been resolved on fs-devel
+    so we are sending this patch as a temporary fix.
+    
+    This is last patch just in case it is Nakd with the explanation
+    that we need to push the correct fix through fs-devel, mm
+    or the block layer. The rest of the patchset can live without
+    the patch, but the driver will not work with filesystems like
+    XFS.
+    
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 4e4b1061a5e9..1b495afe6d17 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -109,7 +109,7 @@ iscsi_buf_init_sg(struct iscsi_buf *ibuf, struct scatterlist *sg)
+ 	/*
+ 	 * Fastpath: sg element fits into single page
+ 	 */
+-	if (sg->length + sg->offset <= PAGE_SIZE && page_count(sg->page) >= 2)
++	if (sg->length + sg->offset <= PAGE_SIZE && !PageSlab(sg->page))
+ 		ibuf->use_sendmsg = 0;
+ 	else
+ 		ibuf->use_sendmsg = 1;

commit 55e3299d9eca01fb2351c5d37e222872b7c6e0af
+Author: Mike Christie 
+Date:   Fri Jan 13 18:05:53 2006 -0600
+
+    [SCSI] iscsi: fix 4k stack iscsi setups
+    
+    When we run the xmit code from queuecomand the stack trace
+    gets too deep. The patch runs the xmit code from the scsi_host
+    work queue. This fixes 4k stack and xfs support and should
+    fix the st and sg stack usage bugs.
+    
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index e31d350e6b67..4e4b1061a5e9 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -525,7 +525,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	__kfifo_put(ctask->r2tqueue, (void*)&r2t, sizeof(void*));
+ 	__kfifo_put(conn->writequeue, (void*)&ctask, sizeof(void*));
+ 
+-	schedule_work(&conn->xmitwork);
++	scsi_queue_work(session->host, &conn->xmitwork);
+ 	conn->r2t_pdus_cnt++;
+ 	spin_unlock(&session->lock);
+ 
+@@ -1267,7 +1267,7 @@ iscsi_write_space(struct sock *sk)
+ 	conn->old_write_space(sk);
+ 	debug_tcp("iscsi_write_space: cid %d\n", conn->id);
+ 	clear_bit(SUSPEND_BIT, &conn->suspend_tx);
+-	schedule_work(&conn->xmitwork);
++	scsi_queue_work(conn->session->host, &conn->xmitwork);
+ }
+ 
+ static void
+@@ -2275,7 +2275,7 @@ iscsi_xmitworker(void *data)
+ 	 */
+ 	mutex_lock(&conn->xmitmutex);
+ 	if (iscsi_data_xmit(conn))
+-		schedule_work(&conn->xmitwork);
++		scsi_queue_work(conn->session->host, &conn->xmitwork);
+ 	mutex_unlock(&conn->xmitmutex);
+ }
+ 
+@@ -2340,15 +2340,7 @@ iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 		session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
+ 	spin_unlock(&session->lock);
+ 
+-        if (!in_interrupt() && mutex_trylock(&conn->xmitmutex)) {
+-		spin_unlock_irq(host->host_lock);
+-		if (iscsi_data_xmit(conn))
+-			schedule_work(&conn->xmitwork);
+-		mutex_unlock(&conn->xmitmutex);
+-		spin_lock_irq(host->host_lock);
+-	} else
+-		schedule_work(&conn->xmitwork);
+-
++	scsi_queue_work(host, &conn->xmitwork);
+ 	return 0;
+ 
+ reject:
+@@ -2942,8 +2934,7 @@ iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 	else
+ 	        __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*));
+ 
+-	schedule_work(&conn->xmitwork);
+-
++	scsi_queue_work(session->host, &conn->xmitwork);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 45e31635a595..59a1c9d9d3bd 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -379,6 +379,7 @@ iscsi_transport_create_session(struct scsi_transport_template *scsit,
+ 	shost->max_lun = transport->max_lun;
+ 	shost->max_cmd_len = transport->max_cmd_len;
+ 	shost->transportt = scsit;
++	shost->transportt->create_work_queue = 1;
+ 
+ 	if (scsi_add_host(shost, NULL))
+ 		goto free_host;

commit 7b8631b53bea286b68847a939b87135198335b66
+Author: Mike Christie 
+Date:   Fri Jan 13 18:05:50 2006 -0600
+
+    [SCSI] iscsi: seperate iscsi interface from setup functions
+    
+    This is the second version of the patch to address Christoph's comments.
+    Instead of doing the lib, I just kept everything in scsi_trnapsort_iscsi.c
+    like the FC and SPI class. This was becuase the driver model and sysfs
+    class is tied to the session and connection setup so separating did not
+    buy very much at this time.
+    
+    The reason for this patch was becuase HW iscsi LLDs like qla4xxx cannot
+    use the iscsi class becuase the scsi_host was tied to the interface and
+    class code. This patch just seperates the session from scsi host so
+    that LLDs that allocate the host per some resource like pci device
+    can still use the class.
+    
+    This is also fixes a couple refcount bugs that can be triggered
+    when users have a sysfs file open, close the session, then
+    read or write to the file.
+    
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 0acc4b235d9b..e31d350e6b67 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -2435,17 +2435,20 @@ iscsi_pool_free(struct iscsi_queue *q, void **items)
+ 	kfree(items);
+ }
+ 
+-static iscsi_connh_t
+-iscsi_conn_create(iscsi_sessionh_t sessionh, uint32_t conn_idx)
++static struct iscsi_cls_conn *
++iscsi_conn_create(struct Scsi_Host *shost, uint32_t conn_idx)
+ {
+-	struct iscsi_session *session = iscsi_ptr(sessionh);
+-	struct iscsi_conn *conn = NULL;
++	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
++	struct iscsi_conn *conn;
++	struct iscsi_cls_conn *cls_conn;
+ 
+-	conn = kmalloc(sizeof(struct iscsi_conn), GFP_KERNEL);
+-	if (conn == NULL)
+-		goto conn_alloc_fail;
+-	memset(conn, 0, sizeof(struct iscsi_conn));
++	cls_conn = iscsi_create_conn(hostdata_session(shost->hostdata),
++				     conn_idx);
++	if (!cls_conn)
++		return NULL;
++	conn = cls_conn->dd_data;
+ 
++	memset(conn, 0, sizeof(struct iscsi_conn));
+ 	conn->c_stage = ISCSI_CONN_INITIAL_STAGE;
+ 	conn->in_progress = IN_PROGRESS_WAIT_HEADER;
+ 	conn->id = conn_idx;
+@@ -2507,7 +2510,7 @@ iscsi_conn_create(iscsi_sessionh_t sessionh, uint32_t conn_idx)
+ 	mutex_init(&conn->xmitmutex);
+ 	init_waitqueue_head(&conn->ehwait);
+ 
+-	return iscsi_handle(conn);
++	return cls_conn;
+ 
+ max_recv_dlenght_alloc_fail:
+ 	spin_lock_bh(&session->lock);
+@@ -2523,15 +2526,14 @@ iscsi_conn_create(iscsi_sessionh_t sessionh, uint32_t conn_idx)
+ writequeue_alloc_fail:
+ 	kfifo_free(conn->xmitqueue);
+ xmitqueue_alloc_fail:
+-	kfree(conn);
+-conn_alloc_fail:
+-	return iscsi_handle(NULL);
++	iscsi_destroy_conn(cls_conn);
++	return NULL;
+ }
+ 
+ static void
+-iscsi_conn_destroy(iscsi_connh_t connh)
++iscsi_conn_destroy(struct iscsi_cls_conn *cls_conn)
+ {
+-	struct iscsi_conn *conn = iscsi_ptr(connh);
++	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	struct iscsi_session *session = conn->session;
+ 	unsigned long flags;
+ 
+@@ -2626,7 +2628,8 @@ iscsi_conn_destroy(iscsi_connh_t connh)
+ 	kfifo_free(conn->writequeue);
+ 	kfifo_free(conn->immqueue);
+ 	kfifo_free(conn->mgmtqueue);
+-	kfree(conn);
++
++	iscsi_destroy_conn(cls_conn);
+ }
+ 
+ static int
+@@ -3257,17 +3260,23 @@ static struct scsi_host_template iscsi_sht = {
+ 	.this_id		= -1,
+ };
+ 
+-static iscsi_sessionh_t
+-iscsi_session_create(uint32_t initial_cmdsn, struct Scsi_Host *host)
++static struct iscsi_transport iscsi_tcp_transport;
++
++static struct Scsi_Host *
++iscsi_session_create(struct scsi_transport_template *scsit,
++		     uint32_t initial_cmdsn)
+ {
+-	int cmd_i;
++	struct Scsi_Host *shost;
+ 	struct iscsi_session *session;
++	int cmd_i;
+ 
+-	session = iscsi_hostdata(host->hostdata);
+-	memset(session, 0, sizeof(struct iscsi_session));
++	shost = iscsi_transport_create_session(scsit, &iscsi_tcp_transport);
++	if (!shost)
++		return NULL; 
+ 
+-	session->host = host;
+-	session->id = host->host_no;
++	session = iscsi_hostdata(shost->hostdata);
++	memset(session, 0, sizeof(struct iscsi_session));
++	session->host = shost;
+ 	session->state = ISCSI_STATE_LOGGED_IN;
+ 	session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
+ 	session->cmds_max = ISCSI_XMIT_CMDS_MAX;
+@@ -3311,7 +3320,7 @@ iscsi_session_create(uint32_t initial_cmdsn, struct Scsi_Host *host)
+ 	if (iscsi_r2tpool_alloc(session))
+ 		goto r2tpool_alloc_fail;
+ 
+-	return iscsi_handle(session);
++	return shost;
+ 
+ r2tpool_alloc_fail:
+ 	for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++)
+@@ -3321,15 +3330,15 @@ iscsi_session_create(uint32_t initial_cmdsn, struct Scsi_Host *host)
+ mgmtpool_alloc_fail:
+ 	iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
+ cmdpool_alloc_fail:
+-	return iscsi_handle(NULL);
++	return NULL;
+ }
+ 
+ static void
+-iscsi_session_destroy(iscsi_sessionh_t sessionh)
++iscsi_session_destroy(struct Scsi_Host *shost)
+ {
++	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+ 	int cmd_i;
+ 	struct iscsi_data_task *dtask, *n;
+-	struct iscsi_session *session = iscsi_ptr(sessionh);
+ 
+ 	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
+ 		struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
+@@ -3345,6 +3354,8 @@ iscsi_session_destroy(iscsi_sessionh_t sessionh)
+ 	iscsi_r2tpool_free(session);
+ 	iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
+ 	iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
++
++	iscsi_transport_destroy_session(shost);
+ }
+ 
+ static int
+@@ -3493,25 +3504,12 @@ iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param,
+ }
+ 
+ static int
+-iscsi_conn_get_param(iscsi_connh_t connh, enum iscsi_param param,
+-		     uint32_t *value)
++iscsi_session_get_param(struct Scsi_Host *shost,
++			enum iscsi_param param, uint32_t *value)
+ {
+-	struct iscsi_conn *conn = iscsi_ptr(connh);
+-	struct iscsi_session *session = conn->session;
++	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+ 
+ 	switch(param) {
+-	case ISCSI_PARAM_MAX_RECV_DLENGTH:
+-		*value = conn->max_recv_dlength;
+-		break;
+-	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+-		*value = conn->max_xmit_dlength;
+-		break;
+-	case ISCSI_PARAM_HDRDGST_EN:
+-		*value = conn->hdrdgst_en;
+-		break;
+-	case ISCSI_PARAM_DATADGST_EN:
+-		*value = conn->datadgst_en;
+-		break;
+ 	case ISCSI_PARAM_INITIAL_R2T_EN:
+ 		*value = session->initial_r2t_en;
+ 		break;
+@@ -3549,6 +3547,31 @@ iscsi_conn_get_param(iscsi_connh_t connh, enum iscsi_param param,
+ 	return 0;
+ }
+ 
++static int
++iscsi_conn_get_param(void *data, enum iscsi_param param, uint32_t *value)
++{
++	struct iscsi_conn *conn = data;
++
++	switch(param) {
++	case ISCSI_PARAM_MAX_RECV_DLENGTH:
++		*value = conn->max_recv_dlength;
++		break;
++	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
++		*value = conn->max_xmit_dlength;
++		break;
++	case ISCSI_PARAM_HDRDGST_EN:
++		*value = conn->hdrdgst_en;
++		break;
++	case ISCSI_PARAM_DATADGST_EN:
++		*value = conn->datadgst_en;
++		break;
++	default:
++		return ISCSI_ERR_PARAM_NOT_FOUND;
++	}
++
++	return 0;
++}
++
+ static void
+ iscsi_conn_get_stats(iscsi_connh_t connh, struct iscsi_stats *stats)
+ {
+@@ -3593,6 +3616,7 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 				  | CAP_DATADGST,
+ 	.host_template		= &iscsi_sht,
+ 	.hostdata_size		= sizeof(struct iscsi_session),
++	.conndata_size		= sizeof(struct iscsi_conn),
+ 	.max_conn		= 1,
+ 	.max_cmd_len		= ISCSI_TCP_MAX_CMD_LEN,
+ 	.create_session		= iscsi_session_create,
+@@ -3601,7 +3625,8 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ 	.bind_conn		= iscsi_conn_bind,
+ 	.destroy_conn		= iscsi_conn_destroy,
+ 	.set_param		= iscsi_conn_set_param,
+-	.get_param		= iscsi_conn_get_param,
++	.get_conn_param		= iscsi_conn_get_param,
++	.get_session_param	= iscsi_session_get_param,
+ 	.start_conn		= iscsi_conn_start,
+ 	.stop_conn		= iscsi_conn_stop,
+ 	.send_pdu		= iscsi_conn_send_pdu,
+@@ -3611,8 +3636,6 @@ static struct iscsi_transport iscsi_tcp_transport = {
+ static int __init
+ iscsi_tcp_init(void)
+ {
+-	int error;
+-
+ 	if (iscsi_max_lun < 1) {
+ 		printk(KERN_ERR "Invalid max_lun value of %u\n", iscsi_max_lun);
+ 		return -EINVAL;
+@@ -3625,11 +3648,10 @@ iscsi_tcp_init(void)
+ 	if (!taskcache)
+ 		return -ENOMEM;
+ 
+-	error = iscsi_register_transport(&iscsi_tcp_transport);
+-	if (error)
++	if (!iscsi_register_transport(&iscsi_tcp_transport))
+ 		kmem_cache_destroy(taskcache);
+ 
+-	return error;
++	return 0;
+ }
+ 
+ static void __exit
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 50ed88f98f46..45e31635a595 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -21,12 +21,9 @@
+  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+  */
+ #include 
+-#include 
+-#include 
+ #include 
+ #include 
+ #include 
+-
+ #include 
+ #include 
+ #include 
+@@ -45,11 +42,6 @@ struct iscsi_internal {
+ 	 * List of sessions for this transport
+ 	 */
+ 	struct list_head sessions;
+-	/*
+-	 * lock to serialize access to the sessions list which must
+-	 * be taken after the rx_queue_mutex
+-	 */
+-	spinlock_t session_lock;
+ 	/*
+ 	 * based on transport capabilities, at register time we set these
+ 	 * bits to tell the transport class it wants attributes displayed
+@@ -157,7 +149,7 @@ struct mempool_zone {
+ 	spinlock_t freelock;
+ };
+ 
+-static struct mempool_zone z_reply;
++static struct mempool_zone *z_reply;
+ 
+ /*
+  * Z_MAX_* - actual mempool size allocated at the mempool_zone_init() time
+@@ -172,50 +164,270 @@ static struct mempool_zone z_reply;
+ #define Z_MAX_ERROR	16
+ #define Z_HIWAT_ERROR	12
+ 
+-struct iscsi_if_conn {
+-	struct list_head conn_list;	/* item in connlist */
+-	struct list_head session_list;	/* item in session->connections */
+-	iscsi_connh_t connh;
+-	int active;			/* must be accessed with the connlock */
+-	struct Scsi_Host *host;		/* originated shost */
+-	struct device dev;		/* sysfs transport/container device */
+-	struct iscsi_transport *transport;
+-	struct mempool_zone z_error;
+-	struct mempool_zone z_pdu;
+-	struct list_head freequeue;
+-};
++static LIST_HEAD(connlist);
++static DEFINE_SPINLOCK(connlock);
+ 
+-#define iscsi_dev_to_if_conn(_dev) \
+-	container_of(_dev, struct iscsi_if_conn, dev)
++/*
++ * The following functions can be used by LLDs that allocate
++ * their own scsi_hosts or by software iscsi LLDs
++ */
++static void iscsi_session_release(struct device *dev)
++{
++	struct iscsi_cls_session *session = iscsi_dev_to_session(dev);
++	struct iscsi_transport *transport = session->transport;
++	struct Scsi_Host *shost;
+ 
+-#define iscsi_cdev_to_if_conn(_cdev) \
+-	iscsi_dev_to_if_conn(_cdev->dev)
++	shost = iscsi_session_to_shost(session);
++	scsi_host_put(shost);
++	kfree(session);
++	module_put(transport->owner);
++}
+ 
+-static LIST_HEAD(connlist);
+-static DEFINE_SPINLOCK(connlock);
++static int iscsi_is_session_dev(const struct device *dev)
++{
++	return dev->release == iscsi_session_release;
++}
+ 
+-struct iscsi_if_session {
+-	struct list_head list;	/* item in session_list */
+-	struct list_head connections;
+-	iscsi_sessionh_t sessionh;
+-	struct iscsi_transport *transport;
+-	struct device dev;	/* sysfs transport/container device */
+-};
++/**
++ * iscsi_create_session - create iscsi class session
++ * @shost: scsi host
++ * @transport: iscsi transport
++ *
++ * This can be called from a LLD or iscsi_transport
++ **/
++struct iscsi_cls_session *
++iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport)
++{
++	struct iscsi_cls_session *session;
++	int err;
++
++	if (!try_module_get(transport->owner))
++		return NULL;
++
++	session = kzalloc(sizeof(*session), GFP_KERNEL);
++	if (!session)
++		goto module_put;
++	session->transport = transport;
++
++	/* this is released in the dev's release function */
++	scsi_host_get(shost);
++	snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", shost->host_no);
++	session->dev.parent = &shost->shost_gendev;
++	session->dev.release = iscsi_session_release;
++	err = device_register(&session->dev);
++	if (err) {
++		dev_printk(KERN_ERR, &session->dev, "iscsi: could not "
++			   "register session's dev\n");
++		goto free_session;
++	}
++	transport_register_device(&session->dev);
++
++	return session;
++
++free_session:
++	kfree(session);
++module_put:
++	module_put(transport->owner);
++	return NULL;
++}
++
++EXPORT_SYMBOL_GPL(iscsi_create_session);
++
++/**
++ * iscsi_destroy_session - destroy iscsi session
++ * @session: iscsi_session
++ *
++ * Can be called by a LLD or iscsi_transport. There must not be
++ * any running connections.
++ **/
++int iscsi_destroy_session(struct iscsi_cls_session *session)
++{
++	transport_unregister_device(&session->dev);
++	device_unregister(&session->dev);
++	return 0;
++}
++
++EXPORT_SYMBOL_GPL(iscsi_destroy_session);
++
++static void iscsi_conn_release(struct device *dev)
++{
++	struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev);
++	struct device *parent = conn->dev.parent;
++
++	kfree(conn);
++	put_device(parent);
++}
++
++static int iscsi_is_conn_dev(const struct device *dev)
++{
++	return dev->release == iscsi_conn_release;
++}
++
++/**
++ * iscsi_create_conn - create iscsi class connection
++ * @session: iscsi cls session
++ * @cid: connection id
++ *
++ * This can be called from a LLD or iscsi_transport. The connection
++ * is child of the session so cid must be unique for all connections
++ * on the session.
++ **/
++struct iscsi_cls_conn *
++iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid)
++{
++	struct iscsi_transport *transport = session->transport;
++	struct Scsi_Host *shost = iscsi_session_to_shost(session);
++	struct iscsi_cls_conn *conn;
++	int err;
++
++	conn = kzalloc(sizeof(*conn) + transport->conndata_size, GFP_KERNEL);
++	if (!conn)
++		return NULL;
++
++	if (transport->conndata_size)
++		conn->dd_data = &conn[1];
++
++	INIT_LIST_HEAD(&conn->conn_list);
++	conn->transport = transport;
++
++	/* this is released in the dev's release function */
++	if (!get_device(&session->dev))
++		goto free_conn;
++	snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
++		 shost->host_no, cid);
++	conn->dev.parent = &session->dev;
++	conn->dev.release = iscsi_conn_release;
++	err = device_register(&conn->dev);
++	if (err) {
++		dev_printk(KERN_ERR, &conn->dev, "iscsi: could not register "
++			   "connection's dev\n");
++		goto release_parent_ref;
++	}
++	transport_register_device(&conn->dev);
++	return conn;
++
++release_parent_ref:
++	put_device(&session->dev);
++free_conn:
++	kfree(conn);
++	return NULL;
++}
++
++EXPORT_SYMBOL_GPL(iscsi_create_conn);
++
++/**
++ * iscsi_destroy_conn - destroy iscsi class connection
++ * @session: iscsi cls session
++ *
++ * This can be called from a LLD or iscsi_transport.
++ **/
++int iscsi_destroy_conn(struct iscsi_cls_conn *conn)
++{
++	transport_unregister_device(&conn->dev);
++	device_unregister(&conn->dev);
++	return 0;
++}
++
++EXPORT_SYMBOL_GPL(iscsi_destroy_conn);
++
++/*
++ * These functions are used only by software iscsi_transports
++ * which do not allocate and more their scsi_hosts since this
++ * is initiated from userspace.
++ */
++
++/*
++ * iSCSI Session's hostdata organization:
++ *
++ *    *------------------* <== hostdata_session(host->hostdata)
++ *    | ptr to class sess|
++ *    |------------------| <== iscsi_hostdata(host->hostdata)
++ *    | transport's data |
++ *    *------------------*
++ */
++
++#define hostdata_privsize(_t)	(sizeof(unsigned long) + _t->hostdata_size + \
++				 _t->hostdata_size % sizeof(unsigned long))
++
++#define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata))
++
++/**
++ * iscsi_transport_create_session - create iscsi cls session and host
++ * scsit: scsi transport template
++ * transport: iscsi transport template
++ *
++ * This can be used by software iscsi_transports that allocate
++ * a session per scsi host.
++ **/
++struct Scsi_Host *
++iscsi_transport_create_session(struct scsi_transport_template *scsit,
++			       struct iscsi_transport *transport)
++{
++	struct iscsi_cls_session *session;
++	struct Scsi_Host *shost;
++
++	shost = scsi_host_alloc(transport->host_template,
++				hostdata_privsize(transport));
++	if (!shost) {
++		printk(KERN_ERR "iscsi: can not allocate SCSI host for "
++			"session\n");
++		return NULL;
++	}
++
++	shost->max_id = 1;
++	shost->max_channel = 0;
++	shost->max_lun = transport->max_lun;
++	shost->max_cmd_len = transport->max_cmd_len;
++	shost->transportt = scsit;
++
++	if (scsi_add_host(shost, NULL))
++		goto free_host;
++
++	session = iscsi_create_session(shost, transport);
++	if (!session)
++		goto remove_host;
+ 
+-#define iscsi_dev_to_if_session(_dev) \
+-	container_of(_dev, struct iscsi_if_session, dev)
++	*(unsigned long*)shost->hostdata = (unsigned long)session;
++	return shost;
++
++remove_host:
++	scsi_remove_host(shost);
++free_host:
++	scsi_host_put(shost);
++	return NULL;
++}
+ 
+-#define iscsi_cdev_to_if_session(_cdev) \
+-	iscsi_dev_to_if_session(_cdev->dev)
++EXPORT_SYMBOL_GPL(iscsi_transport_create_session);
+ 
+-#define iscsi_if_session_to_shost(_session) \
+-	dev_to_shost(_session->dev.parent)
++/**
++ * iscsi_transport_destroy_session - destroy session and scsi host
++ * shost: scsi host
++ *
++ * This can be used by software iscsi_transports that allocate
++ * a session per scsi host.
++ **/
++int iscsi_transport_destroy_session(struct Scsi_Host *shost)
++{
++	struct iscsi_cls_session *session;
+ 
+-static struct iscsi_if_conn*
++	scsi_remove_host(shost);
++	session = hostdata_session(shost->hostdata);
++	iscsi_destroy_session(session);
++	/* ref from host alloc */
++	scsi_host_put(shost);
++	return 0;
++}
++
++EXPORT_SYMBOL_GPL(iscsi_transport_destroy_session);
++
++/*
++ * iscsi interface functions
++ */
++static struct iscsi_cls_conn*
+ iscsi_if_find_conn(uint64_t key)
+ {
+ 	unsigned long flags;
+-	struct iscsi_if_conn *conn;
++	struct iscsi_cls_conn *conn;
+ 
+ 	spin_lock_irqsave(&connlock, flags);
+ 	list_for_each_entry(conn, &connlist, conn_list)
+@@ -250,7 +462,7 @@ static inline struct list_head *skb_to_lh(struct sk_buff *skb)
+ }
+ 
+ static void*
+-mempool_zone_alloc_skb(gfp_t gfp_mask, void *pool_data)
++mempool_zone_alloc_skb(unsigned int gfp_mask, void *pool_data)
+ {
+ 	struct mempool_zone *zone = pool_data;
+ 
+@@ -282,14 +494,21 @@ mempool_zone_complete(struct mempool_zone *zone)
+ 	spin_unlock_irqrestore(&zone->freelock, flags);
+ }
+ 
+-static int
+-mempool_zone_init(struct mempool_zone *zp, unsigned max, unsigned size,
+-		unsigned hiwat)
++static struct mempool_zone *
++mempool_zone_init(unsigned max, unsigned size, unsigned hiwat)
+ {
++	struct mempool_zone *zp;
++
++	zp = kzalloc(sizeof(*zp), GFP_KERNEL);
++	if (!zp)
++		return NULL;
++
+ 	zp->pool = mempool_create(max, mempool_zone_alloc_skb,
+ 				  mempool_zone_free_skb, zp);
+-	if (!zp->pool)
+-		return -ENOMEM;
++	if (!zp->pool) {
++		kfree(zp);
++		return NULL;
++	}
+ 
+ 	zp->size = size;
+ 	zp->hiwat = hiwat;
+@@ -298,9 +517,14 @@ mempool_zone_init(struct mempool_zone *zp, unsigned max, unsigned size,
+ 	spin_lock_init(&zp->freelock);
+ 	atomic_set(&zp->allocated, 0);
+ 
+-	return 0;
++	return zp;
+ }
+ 
++static void mempool_zone_destroy(struct mempool_zone *zp)
++{
++	mempool_destroy(zp->pool);
++	kfree(zp);
++}
+ 
+ static struct sk_buff*
+ mempool_zone_get_skb(struct mempool_zone *zone)
+@@ -340,7 +564,7 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
+ 	struct nlmsghdr	*nlh;
+ 	struct sk_buff *skb;
+ 	struct iscsi_uevent *ev;
+-	struct iscsi_if_conn *conn;
++	struct iscsi_cls_conn *conn;
+ 	char *pdu;
+ 	int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) +
+ 			      data_size);
+@@ -348,13 +572,13 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
+ 	conn = iscsi_if_find_conn(connh);
+ 	BUG_ON(!conn);
+ 
+-	mempool_zone_complete(&conn->z_pdu);
++	mempool_zone_complete(conn->z_pdu);
+ 
+-	skb = mempool_zone_get_skb(&conn->z_pdu);
++	skb = mempool_zone_get_skb(conn->z_pdu);
+ 	if (!skb) {
+ 		iscsi_conn_error(connh, ISCSI_ERR_CONN_FAILED);
+-		printk(KERN_ERR "iscsi%d: can not deliver control PDU: OOM\n",
+-		       conn->host->host_no);
++		dev_printk(KERN_ERR, &conn->dev, "iscsi: can not deliver "
++			   "control PDU: OOM\n");
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -363,14 +587,14 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
+ 	memset(ev, 0, sizeof(*ev));
+ 	ev->transport_handle = iscsi_handle(conn->transport);
+ 	ev->type = ISCSI_KEVENT_RECV_PDU;
+-	if (atomic_read(&conn->z_pdu.allocated) >= conn->z_pdu.hiwat)
++	if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
+ 		ev->iferror = -ENOMEM;
+ 	ev->r.recv_req.conn_handle = connh;
+ 	pdu = (char*)ev + sizeof(*ev);
+ 	memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
+ 	memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
+ 
+-	return iscsi_unicast_skb(&conn->z_pdu, skb);
++	return iscsi_unicast_skb(conn->z_pdu, skb);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
+ 
+@@ -379,18 +603,18 @@ void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error)
+ 	struct nlmsghdr	*nlh;
+ 	struct sk_buff	*skb;
+ 	struct iscsi_uevent *ev;
+-	struct iscsi_if_conn *conn;
++	struct iscsi_cls_conn *conn;
+ 	int len = NLMSG_SPACE(sizeof(*ev));
+ 
+ 	conn = iscsi_if_find_conn(connh);
+ 	BUG_ON(!conn);
+ 
+-	mempool_zone_complete(&conn->z_error);
++	mempool_zone_complete(conn->z_error);
+ 
+-	skb = mempool_zone_get_skb(&conn->z_error);
++	skb = mempool_zone_get_skb(conn->z_error);
+ 	if (!skb) {
+-		printk(KERN_ERR "iscsi%d: gracefully ignored conn error (%d)\n",
+-		       conn->host->host_no, error);
++		dev_printk(KERN_ERR, &conn->dev, "iscsi: gracefully ignored "
++			  "conn error (%d)\n", error);
+ 		return;
+ 	}
+ 
+@@ -398,15 +622,15 @@ void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error)
+ 	ev = NLMSG_DATA(nlh);
+ 	ev->transport_handle = iscsi_handle(conn->transport);
+ 	ev->type = ISCSI_KEVENT_CONN_ERROR;
+-	if (atomic_read(&conn->z_error.allocated) >= conn->z_error.hiwat)
++	if (atomic_read(&conn->z_error->allocated) >= conn->z_error->hiwat)
+ 		ev->iferror = -ENOMEM;
+ 	ev->r.connerror.error = error;
+ 	ev->r.connerror.conn_handle = connh;
+ 
+-	iscsi_unicast_skb(&conn->z_error, skb);
++	iscsi_unicast_skb(conn->z_error, skb);
+ 
+-	printk(KERN_INFO "iscsi%d: detected conn error (%d)\n",
+-	       conn->host->host_no, error);
++	dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n",
++		   error);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_conn_error);
+ 
+@@ -420,9 +644,9 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi,
+ 	int flags = multi ? NLM_F_MULTI : 0;
+ 	int t = done ? NLMSG_DONE : type;
+ 
+-	mempool_zone_complete(&z_reply);
++	mempool_zone_complete(z_reply);
+ 
+-	skb = mempool_zone_get_skb(&z_reply);
++	skb = mempool_zone_get_skb(z_reply);
+ 	/*
+ 	 * FIXME:
+ 	 * user is supposed to react on iferror == -ENOMEM;
+@@ -433,366 +657,197 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi,
+ 	nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0);
+ 	nlh->nlmsg_flags = flags;
+ 	memcpy(NLMSG_DATA(nlh), payload, size);
+-	return iscsi_unicast_skb(&z_reply, skb);
++	return iscsi_unicast_skb(z_reply, skb);
+ }
+ 
+-/*
+- * iSCSI Session's hostdata organization:
+- *
+- *    *------------------* <== host->hostdata
+- *    | transport        |
+- *    |------------------| <== iscsi_hostdata(host->hostdata)
+- *    | transport's data |
+- *    |------------------| <== hostdata_session(host->hostdata)
+- *    | interface's data |
+- *    *------------------*
+- */
++static int
++iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
++		   struct nlmsghdr *nlh)
++{
++	struct iscsi_uevent *ev = NLMSG_DATA(nlh);
++	struct iscsi_stats *stats;
++	struct sk_buff *skbstat;
++	struct iscsi_cls_conn *conn;
++	struct nlmsghdr	*nlhstat;
++	struct iscsi_uevent *evstat;
++	int len = NLMSG_SPACE(sizeof(*ev) +
++			      sizeof(struct iscsi_stats) +
++			      sizeof(struct iscsi_stats_custom) *
++			      ISCSI_STATS_CUSTOM_MAX);
++	int err = 0;
+ 
+-#define hostdata_privsize(_t)	(sizeof(unsigned long) + _t->hostdata_size + \
+-				 _t->hostdata_size % sizeof(unsigned long) + \
+-				 sizeof(struct iscsi_if_session))
++	conn = iscsi_if_find_conn(ev->u.get_stats.conn_handle);
++	if (!conn)
++		return -EEXIST;
+ 
+-#define hostdata_session(_hostdata) ((void*)_hostdata + sizeof(unsigned long) + \
+-			((struct iscsi_transport *) \
+-			 iscsi_ptr(*(uint64_t *)_hostdata))->hostdata_size)
++	do {
++		int actual_size;
+ 
+-static void iscsi_if_session_dev_release(struct device *dev)
+-{
+-	struct iscsi_if_session *session = iscsi_dev_to_if_session(dev);
+-	struct iscsi_transport *transport = session->transport;
+-	struct Scsi_Host *shost = iscsi_if_session_to_shost(session);
+-	struct iscsi_if_conn *conn, *tmp;
+-	unsigned long flags;
++		mempool_zone_complete(conn->z_pdu);
+ 
+-	/* now free connections */
+-	spin_lock_irqsave(&connlock, flags);
+-	list_for_each_entry_safe(conn, tmp, &session->connections,
+-				 session_list) {
+-		list_del(&conn->session_list);
+-		mempool_destroy(conn->z_pdu.pool);
+-		mempool_destroy(conn->z_error.pool);
+-		kfree(conn);
+-	}
+-	spin_unlock_irqrestore(&connlock, flags);
+-	scsi_host_put(shost);
+-	module_put(transport->owner);
++		skbstat = mempool_zone_get_skb(conn->z_pdu);
++		if (!skbstat) {
++			dev_printk(KERN_ERR, &conn->dev, "iscsi: can not "
++				   "deliver stats: OOM\n");
++			return -ENOMEM;
++		}
++
++		nlhstat = __nlmsg_put(skbstat, daemon_pid, 0, 0,
++				      (len - sizeof(*nlhstat)), 0);
++		evstat = NLMSG_DATA(nlhstat);
++		memset(evstat, 0, sizeof(*evstat));
++		evstat->transport_handle = iscsi_handle(conn->transport);
++		evstat->type = nlh->nlmsg_type;
++		if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
++			evstat->iferror = -ENOMEM;
++		evstat->u.get_stats.conn_handle =
++			ev->u.get_stats.conn_handle;
++		stats = (struct iscsi_stats *)
++			((char*)evstat + sizeof(*evstat));
++		memset(stats, 0, sizeof(*stats));
++
++		transport->get_stats(ev->u.get_stats.conn_handle, stats);
++		actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) +
++					  sizeof(struct iscsi_stats) +
++					  sizeof(struct iscsi_stats_custom) *
++					  stats->custom_length);
++		actual_size -= sizeof(*nlhstat);
++		actual_size = NLMSG_LENGTH(actual_size);
++		skb_trim(skb, NLMSG_ALIGN(actual_size));
++		nlhstat->nlmsg_len = actual_size;
++
++		err = iscsi_unicast_skb(conn->z_pdu, skbstat);
++	} while (err < 0 && err != -ECONNREFUSED);
++
++	return err;
+ }
+ 
+ static int
+ iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
+ {
+ 	struct iscsi_transport *transport = priv->iscsi_transport;
+-	struct iscsi_if_session *session;
+ 	struct Scsi_Host *shost;
+-	unsigned long flags;
+-	int error;
+-
+-	if (!try_module_get(transport->owner))
+-		return -EPERM;
+ 
+-	shost = scsi_host_alloc(transport->host_template,
+-				hostdata_privsize(transport));
+-	if (!shost) {
+-		ev->r.c_session_ret.session_handle = iscsi_handle(NULL);
+-		printk(KERN_ERR "iscsi: can not allocate SCSI host for "
+-		       "session\n");
+-		error = -ENOMEM;
+-		goto out_module_put;
+-	}
+-	shost->max_id = 1;
+-	shost->max_channel = 0;
+-	shost->max_lun = transport->max_lun;
+-	shost->max_cmd_len = transport->max_cmd_len;
+-	shost->transportt = &priv->t;
+-
+-	/* store struct iscsi_transport in hostdata */
+-	*(uint64_t*)shost->hostdata = ev->transport_handle;
++	if (!transport->create_session)
++		return -EINVAL;
+ 
+-	ev->r.c_session_ret.session_handle = transport->create_session(
+-					ev->u.c_session.initial_cmdsn, shost);
+-	if (ev->r.c_session_ret.session_handle == iscsi_handle(NULL)) {
+-		error = 0;
+-		goto out_host_put;
+-	}
++	shost = transport->create_session(&priv->t,
++					  ev->u.c_session.initial_cmdsn);
++	if (!shost)
++		return -ENOMEM;
+ 
+-	/* host_no becomes assigned SID */
++	ev->r.c_session_ret.session_handle = iscsi_handle(iscsi_hostdata(shost->hostdata));
+ 	ev->r.c_session_ret.sid = shost->host_no;
+-	/* initialize session */
+-	session = hostdata_session(shost->hostdata);
+-	INIT_LIST_HEAD(&session->connections);
+-	INIT_LIST_HEAD(&session->list);
+-	session->sessionh = ev->r.c_session_ret.session_handle;
+-	session->transport = transport;
+-
+-	error = scsi_add_host(shost, NULL);
+-	if (error)
+-		goto out_destroy_session;
+-
+-	/*
+-	 * this is released in the dev's release function)
+-	 */
+-	scsi_host_get(shost);
+-	snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", shost->host_no);
+-	session->dev.parent = &shost->shost_gendev;
+-	session->dev.release = iscsi_if_session_dev_release;
+-	error = device_register(&session->dev);
+-	if (error) {
+-		printk(KERN_ERR "iscsi: could not register session%d's dev\n",
+-		       shost->host_no);
+-		goto out_remove_host;
+-	}
+-	transport_register_device(&session->dev);
+-
+-	/* add this session to the list of active sessions */
+-	spin_lock_irqsave(&priv->session_lock, flags);
+-	list_add(&session->list, &priv->sessions);
+-	spin_unlock_irqrestore(&priv->session_lock, flags);
+-
+ 	return 0;
+-
+-out_remove_host:
+-	scsi_remove_host(shost);
+-out_destroy_session:
+-	transport->destroy_session(ev->r.c_session_ret.session_handle);
+-	ev->r.c_session_ret.session_handle = iscsi_handle(NULL);
+-out_host_put:
+-	scsi_host_put(shost);
+-out_module_put:
+-	module_put(transport->owner);
+-	return error;
+ }
+ 
+ static int
+ iscsi_if_destroy_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
+ {
+ 	struct iscsi_transport *transport = priv->iscsi_transport;
++
+ 	struct Scsi_Host *shost;
+-	struct iscsi_if_session *session;
+-	unsigned long flags;
+-	struct iscsi_if_conn *conn;
+-	int error = 0;
++
++	if (!transport->destroy_session)
++		return -EINVAL;
+ 
+ 	shost = scsi_host_lookup(ev->u.d_session.sid);
+ 	if (shost == ERR_PTR(-ENXIO))
+ 		return -EEXIST;
+-	session = hostdata_session(shost->hostdata);
+ 
+-	/* check if we have active connections */
+-	spin_lock_irqsave(&connlock, flags);
+-	list_for_each_entry(conn, &session->connections, session_list) {
+-		if (conn->active) {
+-			printk(KERN_ERR "iscsi%d: can not destroy session: "
+-			       "has active connection (%p)\n",
+-			       shost->host_no, iscsi_ptr(conn->connh));
+-			spin_unlock_irqrestore(&connlock, flags);
+-			error = EIO;
+-			goto out_release_ref;
+-		}
+-	}
+-	spin_unlock_irqrestore(&connlock, flags);
+-
+-	scsi_remove_host(shost);
+-	transport->destroy_session(ev->u.d_session.session_handle);
+-	transport_unregister_device(&session->dev);
+-	device_unregister(&session->dev);
+-
+-	/* remove this session from the list of active sessions */
+-	spin_lock_irqsave(&priv->session_lock, flags);
+-	list_del(&session->list);
+-	spin_unlock_irqrestore(&priv->session_lock, flags);
+-
+-	/* ref from host alloc */
+-	scsi_host_put(shost);
+-out_release_ref:
+-	/* ref from host lookup */
+-	scsi_host_put(shost);
+-	return error;
+-}
+-
+-static void iscsi_if_conn_dev_release(struct device *dev)
+-{
+-	struct iscsi_if_conn *conn = iscsi_dev_to_if_conn(dev);
+-	struct Scsi_Host *shost = conn->host;
+-
+-	scsi_host_put(shost);
++	if (transport->destroy_session)
++		transport->destroy_session(shost);
++        /* ref from host lookup */
++        scsi_host_put(shost);
++	return 0;
+ }
+ 
+ static int
+-iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+-{
+-	struct iscsi_if_session *session;
++iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev){
+ 	struct Scsi_Host *shost;
+-	struct iscsi_if_conn *conn;
++	struct iscsi_cls_conn *conn;
+ 	unsigned long flags;
+-	int error;
++
++	if (!transport->create_conn)
++		return -EINVAL;
+ 
+ 	shost = scsi_host_lookup(ev->u.c_conn.sid);
+ 	if (shost == ERR_PTR(-ENXIO))
+ 		return -EEXIST;
+-	session = hostdata_session(shost->hostdata);
+ 
+-	conn = kmalloc(sizeof(struct iscsi_if_conn), GFP_KERNEL);
+-	if (!conn) {
+-		error = -ENOMEM;
+-		goto out_release_ref;
+-	}
+-	memset(conn, 0, sizeof(struct iscsi_if_conn));
+-	INIT_LIST_HEAD(&conn->session_list);
+-	INIT_LIST_HEAD(&conn->conn_list);
+-	conn->host = shost;
+-	conn->transport = transport;
++	conn = transport->create_conn(shost, ev->u.c_conn.cid);
++	if (!conn)
++		goto release_ref;
+ 
+-	error = mempool_zone_init(&conn->z_pdu, Z_MAX_PDU,
++	conn->z_pdu = mempool_zone_init(Z_MAX_PDU,
+ 			NLMSG_SPACE(sizeof(struct iscsi_uevent) +
+ 				    sizeof(struct iscsi_hdr) +
+ 				    DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH),
+ 			Z_HIWAT_PDU);
+-	if (error) {
+-		printk(KERN_ERR "iscsi%d: can not allocate pdu zone for new "
+-		       "conn\n", shost->host_no);
+-		goto out_free_conn;
++	if (!conn->z_pdu) {
++		dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
++			   "pdu zone for new conn\n");
++		goto destroy_conn;
+ 	}
+-	error = mempool_zone_init(&conn->z_error, Z_MAX_ERROR,
++
++	conn->z_error = mempool_zone_init(Z_MAX_ERROR,
+ 			NLMSG_SPACE(sizeof(struct iscsi_uevent)),
+ 			Z_HIWAT_ERROR);
+-	if (error) {
+-		printk(KERN_ERR "iscsi%d: can not allocate error zone for "
+-		       "new conn\n", shost->host_no);
+-		goto out_free_pdu_pool;
+-	}
+-
+-	ev->r.handle = transport->create_conn(ev->u.c_conn.session_handle,
+-					ev->u.c_conn.cid);
+-	if (!ev->r.handle) {
+-		error = -ENODEV;
+-		goto out_free_error_pool;
++	if (!conn->z_error) {
++		dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
++			   "error zone for new conn\n");
++		goto free_pdu_pool;
+ 	}
+ 
+-	conn->connh = ev->r.handle;
+-
+-	/*
+-	 * this is released in the dev's release function
+-	 */
+-	if (!scsi_host_get(shost))
+-		goto out_destroy_conn;
+-	snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
+-		 shost->host_no, ev->u.c_conn.cid);
+-	conn->dev.parent = &session->dev;
+-	conn->dev.release = iscsi_if_conn_dev_release;
+-	error = device_register(&conn->dev);
+-	if (error) {
+-		printk(KERN_ERR "iscsi%d: could not register connections%u "
+-		       "dev\n", shost->host_no, ev->u.c_conn.cid);
+-		goto out_release_parent_ref;
+-	}
+-	transport_register_device(&conn->dev);
++	ev->r.handle = conn->connh = iscsi_handle(conn->dd_data);
+ 
+ 	spin_lock_irqsave(&connlock, flags);
+ 	list_add(&conn->conn_list, &connlist);
+-	list_add(&conn->session_list, &session->connections);
+ 	conn->active = 1;
+ 	spin_unlock_irqrestore(&connlock, flags);
+ 
+ 	scsi_host_put(shost);
+ 	return 0;
+ 
+-out_release_parent_ref:
++free_pdu_pool:
++	mempool_zone_destroy(conn->z_pdu);
++destroy_conn:
++	if (transport->destroy_conn)
++		transport->destroy_conn(conn->dd_data);
++release_ref:
+ 	scsi_host_put(shost);
+-out_destroy_conn:
+-	transport->destroy_conn(ev->r.handle);
+-out_free_error_pool:
+-	mempool_destroy(conn->z_error.pool);
+-out_free_pdu_pool:
+-	mempool_destroy(conn->z_pdu.pool);
+-out_free_conn:
+-	kfree(conn);
+-out_release_ref:
+-	scsi_host_put(shost);
+-	return error;
++	return -ENOMEM;
+ }
+ 
+ static int
+ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+ {
+ 	unsigned long flags;
+-	struct iscsi_if_conn *conn;
++	struct iscsi_cls_conn *conn;
++	struct mempool_zone *z_error, *z_pdu;
+ 
+ 	conn = iscsi_if_find_conn(ev->u.d_conn.conn_handle);
+ 	if (!conn)
+ 		return -EEXIST;
+ 
+-	transport->destroy_conn(ev->u.d_conn.conn_handle);
++	if (!transport->destroy_conn)
++		return -EINVAL;
+ 
+ 	spin_lock_irqsave(&connlock, flags);
+ 	conn->active = 0;
+ 	list_del(&conn->conn_list);
+ 	spin_unlock_irqrestore(&connlock, flags);
+ 
+-	transport_unregister_device(&conn->dev);
+-	device_unregister(&conn->dev);
+-	return 0;
+-}
+-
+-static int
+-iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
+-		   struct nlmsghdr *nlh)
+-{
+-	struct iscsi_uevent *ev = NLMSG_DATA(nlh);
+-	struct iscsi_stats *stats;
+-	struct sk_buff *skbstat;
+-	struct iscsi_if_conn *conn;
+-	struct nlmsghdr	*nlhstat;
+-	struct iscsi_uevent *evstat;
+-	int len = NLMSG_SPACE(sizeof(*ev) +
+-			      sizeof(struct iscsi_stats) +
+-			      sizeof(struct iscsi_stats_custom) *
+-			      ISCSI_STATS_CUSTOM_MAX);
+-	int err = 0;
+-
+-	conn = iscsi_if_find_conn(ev->u.get_stats.conn_handle);
+-	if (!conn)
+-		return -EEXIST;
+-
+-	do {
+-		int actual_size;
+-
+-		mempool_zone_complete(&conn->z_pdu);
+-
+-		skbstat = mempool_zone_get_skb(&conn->z_pdu);
+-		if (!skbstat) {
+-			printk(KERN_ERR "iscsi%d: can not deliver stats: OOM\n",
+-			       conn->host->host_no);
+-			return -ENOMEM;
+-		}
+-
+-		nlhstat = __nlmsg_put(skbstat, daemon_pid, 0, 0,
+-				      (len - sizeof(*nlhstat)), 0);
+-		evstat = NLMSG_DATA(nlhstat);
+-		memset(evstat, 0, sizeof(*evstat));
+-		evstat->transport_handle = iscsi_handle(conn->transport);
+-		evstat->type = nlh->nlmsg_type;
+-		if (atomic_read(&conn->z_pdu.allocated) >= conn->z_pdu.hiwat)
+-			evstat->iferror = -ENOMEM;
+-		evstat->u.get_stats.conn_handle =
+-			ev->u.get_stats.conn_handle;
+-		stats = (struct iscsi_stats *)
+-			((char*)evstat + sizeof(*evstat));
+-		memset(stats, 0, sizeof(*stats));
++	z_pdu = conn->z_pdu;
++	z_error = conn->z_error;
+ 
+-		transport->get_stats(ev->u.get_stats.conn_handle, stats);
+-		actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) +
+-					  sizeof(struct iscsi_stats) +
+-					  sizeof(struct iscsi_stats_custom) *
+-					  stats->custom_length);
+-		actual_size -= sizeof(*nlhstat);
+-		actual_size = NLMSG_LENGTH(actual_size);
+-		skb_trim(skb, NLMSG_ALIGN(actual_size));
+-		nlhstat->nlmsg_len = actual_size;
++	if (transport->destroy_conn)
++		transport->destroy_conn(conn);
+ 
+-		err = iscsi_unicast_skb(&conn->z_pdu, skbstat);
+-	} while (err < 0 && err != -ECONNREFUSED);
++	mempool_zone_destroy(z_pdu);
++	mempool_zone_destroy(z_error);
+ 
+-	return err;
++	return 0;
+ }
+ 
+ static int
+@@ -916,8 +971,8 @@ iscsi_if_rx(struct sock *sk, int len)
+ 				err = iscsi_if_send_reply(
+ 					NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq,
+ 					nlh->nlmsg_type, 0, 0, ev, sizeof(*ev));
+-				if (atomic_read(&z_reply.allocated) >=
+-						z_reply.hiwat)
++				if (atomic_read(&z_reply->allocated) >=
++						z_reply->hiwat)
+ 					ev->iferror = -ENOMEM;
+ 			} while (err < 0 && err != -ECONNREFUSED);
+ 			skb_pull(skb, rlen);
+@@ -927,6 +982,9 @@ iscsi_if_rx(struct sock *sk, int len)
+ 	mutex_unlock(&rx_queue_mutex);
+ }
+ 
++#define iscsi_cdev_to_conn(_cdev) \
++	iscsi_dev_to_conn(_cdev->dev)
++
+ /*
+  * iSCSI connection attrs
+  */
+@@ -935,12 +993,10 @@ static ssize_t								\
+ show_conn_int_param_##param(struct class_device *cdev, char *buf)	\
+ {									\
+ 	uint32_t value = 0;						\
+-	struct iscsi_if_conn *conn = iscsi_cdev_to_if_conn(cdev);	\
+-	struct iscsi_internal *priv;					\
++	struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev);		\
++	struct iscsi_transport *t = conn->transport;			\
+ 									\
+-	priv = to_iscsi_internal(conn->host->transportt);		\
+-	if (priv->param_mask & (1 << param))				\
+-		priv->iscsi_transport->get_param(conn->connh, param, &value); \
++	t->get_conn_param(conn->dd_data, param, &value);		\
+ 	return snprintf(buf, 20, format"\n", value);			\
+ }
+ 
+@@ -955,6 +1011,9 @@ iscsi_conn_int_attr(data_digest, ISCSI_PARAM_DATADGST_EN, "%d");
+ iscsi_conn_int_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN, "%d");
+ iscsi_conn_int_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN, "%d");
+ 
++#define iscsi_cdev_to_session(_cdev) \
++	iscsi_dev_to_session(_cdev->dev)
++
+ /*
+  * iSCSI session attrs
+  */
+@@ -963,20 +1022,11 @@ static ssize_t								\
+ show_session_int_param_##param(struct class_device *cdev, char *buf)	\
+ {									\
+ 	uint32_t value = 0;						\
+-	struct iscsi_if_session *session = iscsi_cdev_to_if_session(cdev); \
+-	struct Scsi_Host *shost = iscsi_if_session_to_shost(session);	\
+-	struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \
+-	struct iscsi_if_conn *conn = NULL;				\
+-	unsigned long  flags;						\
+-									\
+-	spin_lock_irqsave(&connlock, flags);				\
+-	if (!list_empty(&session->connections))				\
+-		conn = list_entry(session->connections.next,		\
+-				  struct iscsi_if_conn, session_list);	\
+-	spin_unlock_irqrestore(&connlock, flags);			\
++	struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev);	\
++	struct Scsi_Host *shost = iscsi_session_to_shost(session);	\
++	struct iscsi_transport *t = session->transport;			\
+ 									\
+-	if (conn && (priv->param_mask & (1 << param)))			\
+-		priv->iscsi_transport->get_param(conn->connh, param, &value);\
++	t->get_session_param(shost, param, &value);			\
+ 	return snprintf(buf, 20, format"\n", value);			\
+ }
+ 
+@@ -1005,23 +1055,18 @@ iscsi_session_int_attr(erl, ISCSI_PARAM_ERL, "%d");
+ 		count++;						\
+ 	}
+ 
+-static int iscsi_is_session_dev(const struct device *dev)
+-{
+-	return dev->release == iscsi_if_session_dev_release;
+-}
+-
+ static int iscsi_session_match(struct attribute_container *cont,
+ 			   struct device *dev)
+ {
+-	struct iscsi_if_session *session;
++	struct iscsi_cls_session *session;
+ 	struct Scsi_Host *shost;
+ 	struct iscsi_internal *priv;
+ 
+ 	if (!iscsi_is_session_dev(dev))
+ 		return 0;
+ 
+-	session = iscsi_dev_to_if_session(dev);
+-	shost = iscsi_if_session_to_shost(session);
++	session = iscsi_dev_to_session(dev);
++	shost = iscsi_session_to_shost(session);
+ 	if (!shost->transportt)
+ 		return 0;
+ 
+@@ -1032,23 +1077,21 @@ static int iscsi_session_match(struct attribute_container *cont,
+ 	return &priv->session_cont.ac == cont;
+ }
+ 
+-static int iscsi_is_conn_dev(const struct device *dev)
+-{
+-	return dev->release == iscsi_if_conn_dev_release;
+-}
+-
+ static int iscsi_conn_match(struct attribute_container *cont,
+ 			   struct device *dev)
+ {
+-	struct iscsi_if_conn *conn;
++	struct iscsi_cls_session *session;
++	struct iscsi_cls_conn *conn;
+ 	struct Scsi_Host *shost;
+ 	struct iscsi_internal *priv;
+ 
+ 	if (!iscsi_is_conn_dev(dev))
+ 		return 0;
+ 
+-	conn = iscsi_dev_to_if_conn(dev);
+-	shost = conn->host;
++	conn = iscsi_dev_to_conn(dev);
++	session = iscsi_dev_to_session(conn->dev.parent);
++	shost = iscsi_session_to_shost(session);
++
+ 	if (!shost->transportt)
+ 		return 0;
+ 
+@@ -1059,7 +1102,8 @@ static int iscsi_conn_match(struct attribute_container *cont,
+ 	return &priv->conn_cont.ac == cont;
+ }
+ 
+-int iscsi_register_transport(struct iscsi_transport *tt)
++struct scsi_transport_template *
++iscsi_register_transport(struct iscsi_transport *tt)
+ {
+ 	struct iscsi_internal *priv;
+ 	unsigned long flags;
+@@ -1069,15 +1113,14 @@ int iscsi_register_transport(struct iscsi_transport *tt)
+ 
+ 	priv = iscsi_if_transport_lookup(tt);
+ 	if (priv)
+-		return -EEXIST;
++		return NULL;
+ 
+ 	priv = kmalloc(sizeof(*priv), GFP_KERNEL);
+ 	if (!priv)
+-		return -ENOMEM;
++		return NULL;
+ 	memset(priv, 0, sizeof(*priv));
+ 	INIT_LIST_HEAD(&priv->list);
+ 	INIT_LIST_HEAD(&priv->sessions);
+-	spin_lock_init(&priv->session_lock);
+ 	priv->iscsi_transport = tt;
+ 
+ 	priv->cdev.class = &iscsi_transport_class;
+@@ -1143,13 +1186,13 @@ int iscsi_register_transport(struct iscsi_transport *tt)
+ 	spin_unlock_irqrestore(&iscsi_transport_lock, flags);
+ 
+ 	printk(KERN_NOTICE "iscsi: registered transport (%s)\n", tt->name);
+-	return 0;
++	return &priv->t;
+ 
+ unregister_cdev:
+ 	class_device_unregister(&priv->cdev);
+ free_priv:
+ 	kfree(priv);
+-	return err;
++	return NULL;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_register_transport);
+ 
+@@ -1165,14 +1208,6 @@ int iscsi_unregister_transport(struct iscsi_transport *tt)
+ 	priv = iscsi_if_transport_lookup(tt);
+ 	BUG_ON (!priv);
+ 
+-	spin_lock_irqsave(&priv->session_lock, flags);
+-	if (!list_empty(&priv->sessions)) {
+-		spin_unlock_irqrestore(&priv->session_lock, flags);
+-		mutex_unlock(&rx_queue_mutex);
+-		return -EPERM;
+-	}
+-	spin_unlock_irqrestore(&priv->session_lock, flags);
+-
+ 	spin_lock_irqsave(&iscsi_transport_lock, flags);
+ 	list_del(&priv->list);
+ 	spin_unlock_irqrestore(&iscsi_transport_lock, flags);
+@@ -1195,14 +1230,14 @@ iscsi_rcv_nl_event(struct notifier_block *this, unsigned long event, void *ptr)
+ 
+ 	if (event == NETLINK_URELEASE &&
+ 	    n->protocol == NETLINK_ISCSI && n->pid) {
+-		struct iscsi_if_conn *conn;
++		struct iscsi_cls_conn *conn;
+ 		unsigned long flags;
+ 
+-		mempool_zone_complete(&z_reply);
++		mempool_zone_complete(z_reply);
+ 		spin_lock_irqsave(&connlock, flags);
+ 		list_for_each_entry(conn, &connlist, conn_list) {
+-			mempool_zone_complete(&conn->z_error);
+-			mempool_zone_complete(&conn->z_pdu);
++			mempool_zone_complete(conn->z_error);
++			mempool_zone_complete(conn->z_pdu);
+ 		}
+ 		spin_unlock_irqrestore(&connlock, flags);
+ 	}
+@@ -1235,15 +1270,15 @@ static __init int iscsi_transport_init(void)
+ 		goto unregister_session_class;
+ 
+ 	nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx,
+-				    THIS_MODULE);
++			THIS_MODULE);
+ 	if (!nls) {
+ 		err = -ENOBUFS;
+ 		goto unregister_notifier;
+ 	}
+ 
+-	err = mempool_zone_init(&z_reply, Z_MAX_REPLY,
++	z_reply = mempool_zone_init(Z_MAX_REPLY,
+ 		NLMSG_SPACE(sizeof(struct iscsi_uevent)), Z_HIWAT_REPLY);
+-	if (!err)
++	if (z_reply)
+ 		return 0;
+ 
+ 	sock_release(nls->sk_socket);
+@@ -1260,7 +1295,7 @@ static __init int iscsi_transport_init(void)
+ 
+ static void __exit iscsi_transport_exit(void)
+ {
+-	mempool_destroy(z_reply.pool);
++	mempool_zone_destroy(z_reply);
+ 	sock_release(nls->sk_socket);
+ 	netlink_unregister_notifier(&iscsi_nl_notifier);
+ 	transport_class_unregister(&iscsi_connection_class);
+diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
+index be1bc792ab18..3e5cb5ab2d34 100644
+--- a/include/scsi/iscsi_if.h
++++ b/include/scsi/iscsi_if.h
+@@ -168,6 +168,12 @@ typedef uint64_t iscsi_connh_t;		/* iSCSI Data-Path connection handle */
+ 
+ #define iscsi_ptr(_handle) ((void*)(unsigned long)_handle)
+ #define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr)
++#define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata))
++
++/**
++ * iscsi_hostdata - get LLD hostdata from scsi_host
++ * @_hostdata: pointer to scsi host's hostdata
++ **/
+ #define iscsi_hostdata(_hostdata) ((void*)_hostdata + sizeof(unsigned long))
+ 
+ /*
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index f25041c386ec..16602a547a63 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -23,8 +23,14 @@
+ #ifndef SCSI_TRANSPORT_ISCSI_H
+ #define SCSI_TRANSPORT_ISCSI_H
+ 
++#include 
+ #include 
+ 
++struct scsi_transport_template;
++struct Scsi_Host;
++struct mempool_zone;
++struct iscsi_cls_conn;
++
+ /**
+  * struct iscsi_transport - iSCSI Transport template
+  *
+@@ -48,23 +54,31 @@ struct iscsi_transport {
+ 	char *name;
+ 	unsigned int caps;
+ 	struct scsi_host_template *host_template;
++	/* LLD session/scsi_host data size */
+ 	int hostdata_size;
++	/* LLD iscsi_host data size */
++	int ihostdata_size;
++	/* LLD connection data size */
++	int conndata_size;
+ 	int max_lun;
+ 	unsigned int max_conn;
+ 	unsigned int max_cmd_len;
+-	iscsi_sessionh_t (*create_session) (uint32_t initial_cmdsn,
+-					    struct Scsi_Host *shost);
+-	void (*destroy_session) (iscsi_sessionh_t session);
+-	iscsi_connh_t (*create_conn) (iscsi_sessionh_t session, uint32_t cid);
++	struct Scsi_Host *(*create_session) (struct scsi_transport_template *t,
++					     uint32_t initial_cmdsn);
++	void (*destroy_session) (struct Scsi_Host *shost);
++	struct iscsi_cls_conn *(*create_conn) (struct Scsi_Host *shost,
++				uint32_t cid);
+ 	int (*bind_conn) (iscsi_sessionh_t session, iscsi_connh_t conn,
+ 			  uint32_t transport_fd, int is_leading);
+ 	int (*start_conn) (iscsi_connh_t conn);
+ 	void (*stop_conn) (iscsi_connh_t conn, int flag);
+-	void (*destroy_conn) (iscsi_connh_t conn);
++	void (*destroy_conn) (struct iscsi_cls_conn *conn);
+ 	int (*set_param) (iscsi_connh_t conn, enum iscsi_param param,
+ 			  uint32_t value);
+-	int (*get_param) (iscsi_connh_t conn, enum iscsi_param param,
+-			  uint32_t *value);
++	int (*get_conn_param) (void *conndata, enum iscsi_param param,
++			       uint32_t *value);
++	int (*get_session_param) (struct Scsi_Host *shost,
++				  enum iscsi_param param, uint32_t *value);
+ 	int (*send_pdu) (iscsi_connh_t conn, struct iscsi_hdr *hdr,
+ 			 char *data, uint32_t data_size);
+ 	void (*get_stats) (iscsi_connh_t conn, struct iscsi_stats *stats);
+@@ -73,7 +87,7 @@ struct iscsi_transport {
+ /*
+  * transport registration upcalls
+  */
+-extern int iscsi_register_transport(struct iscsi_transport *tt);
++extern struct scsi_transport_template *iscsi_register_transport(struct iscsi_transport *tt);
+ extern int iscsi_unregister_transport(struct iscsi_transport *tt);
+ 
+ /*
+@@ -83,4 +97,49 @@ extern void iscsi_conn_error(iscsi_connh_t conn, enum iscsi_err error);
+ extern int iscsi_recv_pdu(iscsi_connh_t conn, struct iscsi_hdr *hdr,
+ 			  char *data, uint32_t data_size);
+ 
++struct iscsi_cls_conn {
++	struct list_head conn_list;	/* item in connlist */
++	void *dd_data;			/* LLD private data */
++	struct iscsi_transport *transport;
++	iscsi_connh_t connh;
++	int active;			/* must be accessed with the connlock */
++	struct device dev;		/* sysfs transport/container device */
++	struct mempool_zone *z_error;
++	struct mempool_zone *z_pdu;
++	struct list_head freequeue;
++};
++
++#define iscsi_dev_to_conn(_dev) \
++	container_of(_dev, struct iscsi_cls_conn, dev)
++
++struct iscsi_cls_session {
++	struct list_head list;	/* item in session_list */
++	struct iscsi_transport *transport;
++	struct device dev;	/* sysfs transport/container device */
++};
++
++#define iscsi_dev_to_session(_dev) \
++	container_of(_dev, struct iscsi_cls_session, dev)
++
++#define iscsi_session_to_shost(_session) \
++	dev_to_shost(_session->dev.parent)
++
++/*
++ * session and connection functions that can be used by HW iSCSI LLDs
++ */
++extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost,
++				struct iscsi_transport *t);
++extern int iscsi_destroy_session(struct iscsi_cls_session *session);
++extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess,
++					    uint32_t cid);
++extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn);
++
++/*
++ * session functions used by software iscsi
++ */
++extern struct Scsi_Host *
++iscsi_transport_create_session(struct scsi_transport_template *scsit,
++                               struct iscsi_transport *transport);
++extern int iscsi_transport_destroy_session(struct Scsi_Host *shost);
++
+ #endif

commit 7cae5159dd2623300cf9820865bfbf6dcdb7c1b9
+Author: Mike Christie 
+Date:   Fri Jan 13 18:05:47 2006 -0600
+
+    [SCSI] iscsi: add high mem support
+    
+    From Mike Christie  and FUJITA Tomonori :
+    
+    We cannot use page_address becuase some pages could be highmem.
+    Instead, we can use sock_no_sendpage which does kmap for us.
+    
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 5e8b3135574c..0acc4b235d9b 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -87,35 +87,32 @@ iscsi_buf_init_virt(struct iscsi_buf *ibuf, char *vbuf, int size)
+ {
+ 	sg_init_one(&ibuf->sg, (u8 *)vbuf, size);
+ 	ibuf->sent = 0;
++	ibuf->use_sendmsg = 0;
+ }
+ 
+ static inline void
+ iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size)
+ {
+-	ibuf->sg.page = (void*)vbuf;
+-	ibuf->sg.offset = (unsigned int)-1;
++	ibuf->sg.page = virt_to_page(vbuf);
++	ibuf->sg.offset = offset_in_page(vbuf);
+ 	ibuf->sg.length = size;
+ 	ibuf->sent = 0;
+-}
+-
+-static inline void*
+-iscsi_buf_iov_base(struct iscsi_buf *ibuf)
+-{
+-	return (char*)ibuf->sg.page + ibuf->sent;
++	ibuf->use_sendmsg = 1;
+ }
+ 
+ static inline void
+ iscsi_buf_init_sg(struct iscsi_buf *ibuf, struct scatterlist *sg)
+ {
++	ibuf->sg.page = sg->page;
++	ibuf->sg.offset = sg->offset;
++	ibuf->sg.length = sg->length;
+ 	/*
+ 	 * Fastpath: sg element fits into single page
+ 	 */
+-	if (sg->length + sg->offset <= PAGE_SIZE && page_count(sg->page) >= 2) {
+-		ibuf->sg.page = sg->page;
+-		ibuf->sg.offset = sg->offset;
+-		ibuf->sg.length = sg->length;
+-	} else
+-		iscsi_buf_init_iov(ibuf, page_address(sg->page), sg->length);
++	if (sg->length + sg->offset <= PAGE_SIZE && page_count(sg->page) >= 2)
++		ibuf->use_sendmsg = 0;
++	else
++		ibuf->use_sendmsg = 1;
+ 	ibuf->sent = 0;
+ }
+ 
+@@ -1311,35 +1308,25 @@ iscsi_conn_restore_callbacks(struct iscsi_conn *conn)
+  * @buf: buffer to write from
+  * @size: actual size to write
+  * @flags: socket's flags
+- *
+- * Notes:
+- *	depending on buffer will use tcp_sendpage() or tcp_sendmsg().
+- *	buf->sg.offset == -1 tells us that buffer is non S/G and forces
+- *	to use tcp_sendmsg().
+  */
+ static inline int
+ iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags)
+ {
+ 	struct socket *sk = conn->sock;
+-	int res;
+-
+-	if ((int)buf->sg.offset >= 0) {
+-		int offset = buf->sg.offset + buf->sent;
+-
+-		res = conn->sendpage(sk, buf->sg.page, offset, size, flags);
+-	} else {
+-		struct msghdr msg;
+-
+-		buf->iov.iov_base = iscsi_buf_iov_base(buf);
+-		buf->iov.iov_len = size;
+-
+-		memset(&msg, 0, sizeof(struct msghdr));
+-
+-		/* tcp_sendmsg */
+-		res = kernel_sendmsg(sk, &msg, &buf->iov, 1, size);
+-	}
++	int offset = buf->sg.offset + buf->sent;
+ 
+-	return res;
++	/*
++	 * if we got use_sg=0 or are sending something we kmallocd
++	 * then we did not have to do kmap (kmap returns page_address)
++	 *
++	 * if we got use_sg > 0, but had to drop down, we do not
++	 * set clustering so this should only happen for that
++	 * slab case.
++	 */
++	if (buf->use_sendmsg)
++		return sock_no_sendpage(sk, buf->sg.page, offset, size, flags);
++	else
++		return conn->sendpage(sk, buf->sg.page, offset, size, flags);
+ }
+ 
+ /**
+@@ -1431,19 +1418,6 @@ iscsi_data_digest_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	ctask->digest_count = 4;
+ }
+ 
+-static inline void
+-iscsi_buf_data_digest_update(struct iscsi_conn *conn, struct iscsi_buf *buf)
+-{
+-	struct scatterlist sg;
+-
+-	if (buf->sg.offset != -1)
+-		crypto_digest_update(conn->data_tx_tfm, &buf->sg, 1);
+-	else {
+-		sg_init_one(&sg, (char *)buf->sg.page, buf->sg.length);
+-		crypto_digest_update(conn->data_tx_tfm, &sg, 1);
+-	}
+-}
+-
+ static inline int
+ iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 			struct iscsi_buf *buf, uint32_t *digest, int final)
+@@ -1806,7 +1780,8 @@ handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 			return -EAGAIN;
+ 		}
+ 		if (conn->datadgst_en)
+-			iscsi_buf_data_digest_update(conn, &ctask->sendbuf);
++			crypto_digest_update(conn->data_tx_tfm,
++					     &ctask->sendbuf.sg, 1);
+ 
+ 		if (!ctask->imm_count)
+ 			break;
+@@ -1891,7 +1866,8 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 		 * so pass it
+ 		 */
+ 		if (conn->datadgst_en && ctask->sent - start > 0)
+-			iscsi_buf_data_digest_update(conn, &ctask->sendbuf);
++			crypto_digest_update(conn->data_tx_tfm,
++					     &ctask->sendbuf.sg, 1);
+ 
+ 		if (!ctask->data_count)
+ 			break;
+@@ -1969,7 +1945,7 @@ handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 
+ 	BUG_ON(r2t->data_count < 0);
+ 	if (conn->datadgst_en)
+-		iscsi_buf_data_digest_update(conn, &r2t->sendbuf);
++		crypto_digest_update(conn->data_tx_tfm, &r2t->sendbuf.sg, 1);
+ 
+ 	if (r2t->data_count) {
+ 		BUG_ON(ctask->sc->use_sg == 0);
+@@ -2051,7 +2027,7 @@ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	}
+ 
+ 	if (conn->datadgst_en) {
+-		iscsi_buf_data_digest_update(conn, &ctask->sendbuf);
++		crypto_digest_update(conn->data_tx_tfm, &ctask->sendbuf.sg, 1);
+ 		/* imm data? */
+ 		if (!dtask) {
+ 			if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf,
+diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
+index c8bb5b0bcb4b..f95e61b76f70 100644
+--- a/drivers/scsi/iscsi_tcp.h
++++ b/drivers/scsi/iscsi_tcp.h
+@@ -242,8 +242,8 @@ struct iscsi_session {
+ 
+ struct iscsi_buf {
+ 	struct scatterlist	sg;
+-	struct kvec		iov;
+ 	unsigned int		sent;
++	char			use_sendmsg;
+ };
+ 
+ struct iscsi_data_task {

commit defd94b75409b983f94548ea2f52ff5787ddb848
+Author: Mike Christie 
+Date:   Mon Dec 5 02:37:06 2005 -0600
+
+    [SCSI] seperate max_sectors from max_hw_sectors
+    
+    - export __blk_put_request and blk_execute_rq_nowait
+    needed for async REQ_BLOCK_PC requests
+    - seperate max_hw_sectors and max_sectors for block/scsi_ioctl.c and
+    SG_IO bio.c helpers per Jens's last comments. Since block/scsi_ioctl.c SG_IO was
+    already testing against max_sectors and SCSI-ml was setting max_sectors and
+    max_hw_sectors to the same value this does not change any scsi SG_IO behavior. It only
+    prepares ll_rw_blk.c, scsi_ioctl.c and bio.c for when SCSI-ml begins to set
+    a valid max_hw_sectors for all LLDs. Today if a LLD does not set it
+    SCSI-ml sets it to a safe default and some LLDs set it to a artificial low
+    value to overcome memory and feedback issues.
+    
+    Note: Since we now cap max_sectors to BLK_DEF_MAX_SECTORS, which is 1024,
+    drivers that used to call blk_queue_max_sectors with a large value of
+    max_sectors will now see the fs requests capped to BLK_DEF_MAX_SECTORS.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
+index c525b5a2b598..d4beb9a89ee0 100644
+--- a/block/ll_rw_blk.c
++++ b/block/ll_rw_blk.c
+@@ -239,7 +239,7 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
+ 	q->backing_dev_info.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
+ 	q->backing_dev_info.state = 0;
+ 	q->backing_dev_info.capabilities = BDI_CAP_MAP_COPY;
+-	blk_queue_max_sectors(q, MAX_SECTORS);
++	blk_queue_max_sectors(q, SAFE_MAX_SECTORS);
+ 	blk_queue_hardsect_size(q, 512);
+ 	blk_queue_dma_alignment(q, 511);
+ 	blk_queue_congestion_threshold(q);
+@@ -555,7 +555,12 @@ void blk_queue_max_sectors(request_queue_t *q, unsigned short max_sectors)
+ 		printk("%s: set to minimum %d\n", __FUNCTION__, max_sectors);
+ 	}
+ 
+-	q->max_sectors = q->max_hw_sectors = max_sectors;
++	if (BLK_DEF_MAX_SECTORS > max_sectors)
++		q->max_hw_sectors = q->max_sectors = max_sectors;
++ 	else {
++		q->max_sectors = BLK_DEF_MAX_SECTORS;
++		q->max_hw_sectors = max_sectors;
++	}
+ }
+ 
+ EXPORT_SYMBOL(blk_queue_max_sectors);
+@@ -657,8 +662,8 @@ EXPORT_SYMBOL(blk_queue_hardsect_size);
+ void blk_queue_stack_limits(request_queue_t *t, request_queue_t *b)
+ {
+ 	/* zero is "infinity" */
+-	t->max_sectors = t->max_hw_sectors =
+-		min_not_zero(t->max_sectors,b->max_sectors);
++	t->max_sectors = min_not_zero(t->max_sectors,b->max_sectors);
++	t->max_hw_sectors = min_not_zero(t->max_hw_sectors,b->max_hw_sectors);
+ 
+ 	t->max_phys_segments = min(t->max_phys_segments,b->max_phys_segments);
+ 	t->max_hw_segments = min(t->max_hw_segments,b->max_hw_segments);
+@@ -1293,9 +1298,15 @@ static inline int ll_new_hw_segment(request_queue_t *q,
+ static int ll_back_merge_fn(request_queue_t *q, struct request *req, 
+ 			    struct bio *bio)
+ {
++	unsigned short max_sectors;
+ 	int len;
+ 
+-	if (req->nr_sectors + bio_sectors(bio) > q->max_sectors) {
++	if (unlikely(blk_pc_request(req)))
++		max_sectors = q->max_hw_sectors;
++	else
++		max_sectors = q->max_sectors;
++
++	if (req->nr_sectors + bio_sectors(bio) > max_sectors) {
+ 		req->flags |= REQ_NOMERGE;
+ 		if (req == q->last_merge)
+ 			q->last_merge = NULL;
+@@ -1325,9 +1336,16 @@ static int ll_back_merge_fn(request_queue_t *q, struct request *req,
+ static int ll_front_merge_fn(request_queue_t *q, struct request *req, 
+ 			     struct bio *bio)
+ {
++	unsigned short max_sectors;
+ 	int len;
+ 
+-	if (req->nr_sectors + bio_sectors(bio) > q->max_sectors) {
++	if (unlikely(blk_pc_request(req)))
++		max_sectors = q->max_hw_sectors;
++	else
++		max_sectors = q->max_sectors;
++
++
++	if (req->nr_sectors + bio_sectors(bio) > max_sectors) {
+ 		req->flags |= REQ_NOMERGE;
+ 		if (req == q->last_merge)
+ 			q->last_merge = NULL;
+@@ -2144,7 +2162,7 @@ int blk_rq_map_user(request_queue_t *q, struct request *rq, void __user *ubuf,
+ 	struct bio *bio;
+ 	int reading;
+ 
+-	if (len > (q->max_sectors << 9))
++	if (len > (q->max_hw_sectors << 9))
+ 		return -EINVAL;
+ 	if (!len || !ubuf)
+ 		return -EINVAL;
+@@ -2259,7 +2277,7 @@ int blk_rq_map_kern(request_queue_t *q, struct request *rq, void *kbuf,
+ {
+ 	struct bio *bio;
+ 
+-	if (len > (q->max_sectors << 9))
++	if (len > (q->max_hw_sectors << 9))
+ 		return -EINVAL;
+ 	if (!len || !kbuf)
+ 		return -EINVAL;
+diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
+index 382dea7b224c..4e390dfd3157 100644
+--- a/block/scsi_ioctl.c
++++ b/block/scsi_ioctl.c
+@@ -233,7 +233,7 @@ static int sg_io(struct file *file, request_queue_t *q,
+ 	if (verify_command(file, cmd))
+ 		return -EPERM;
+ 
+-	if (hdr->dxfer_len > (q->max_sectors << 9))
++	if (hdr->dxfer_len > (q->max_hw_sectors << 9))
+ 		return -EIO;
+ 
+ 	if (hdr->dxfer_len)
+diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
+index a6d3baa46f61..a6f2dc66c3db 100644
+--- a/drivers/md/dm-table.c
++++ b/drivers/md/dm-table.c
+@@ -638,7 +638,7 @@ int dm_split_args(int *argc, char ***argvp, char *input)
+ static void check_for_valid_limits(struct io_restrictions *rs)
+ {
+ 	if (!rs->max_sectors)
+-		rs->max_sectors = MAX_SECTORS;
++		rs->max_sectors = SAFE_MAX_SECTORS;
+ 	if (!rs->max_phys_segments)
+ 		rs->max_phys_segments = MAX_PHYS_SEGMENTS;
+ 	if (!rs->max_hw_segments)
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index 54a72f197487..14ad2a785a34 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -462,6 +462,7 @@ int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd,
+ 	req = blk_get_request(sdev->request_queue, write, gfp);
+ 	if (!req)
+ 		goto free_sense;
++	req->flags |= REQ_BLOCK_PC | REQ_QUIET;
+ 
+ 	if (use_sg)
+ 		err = scsi_req_map_sg(req, buffer, use_sg, bufflen, gfp);
+@@ -477,7 +478,6 @@ int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd,
+ 	req->sense_len = 0;
+ 	req->timeout = timeout;
+ 	req->retries = retries;
+-	req->flags |= REQ_BLOCK_PC | REQ_QUIET;
+ 	req->end_io_data = sioc;
+ 
+ 	sioc->data = privdata;
+diff --git a/fs/bio.c b/fs/bio.c
+index 4d21ee3873ec..38d3e8023a07 100644
+--- a/fs/bio.c
++++ b/fs/bio.c
+@@ -313,7 +313,8 @@ int bio_get_nr_vecs(struct block_device *bdev)
+ }
+ 
+ static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page
+-			  *page, unsigned int len, unsigned int offset)
++			  *page, unsigned int len, unsigned int offset,
++			  unsigned short max_sectors)
+ {
+ 	int retried_segments = 0;
+ 	struct bio_vec *bvec;
+@@ -327,7 +328,7 @@ static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page
+ 	if (bio->bi_vcnt >= bio->bi_max_vecs)
+ 		return 0;
+ 
+-	if (((bio->bi_size + len) >> 9) > q->max_sectors)
++	if (((bio->bi_size + len) >> 9) > max_sectors)
+ 		return 0;
+ 
+ 	/*
+@@ -401,7 +402,7 @@ static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page
+ int bio_add_pc_page(request_queue_t *q, struct bio *bio, struct page *page,
+ 		    unsigned int len, unsigned int offset)
+ {
+-	return __bio_add_page(q, bio, page, len, offset);
++	return __bio_add_page(q, bio, page, len, offset, q->max_hw_sectors);
+ }
+ 
+ /**
+@@ -420,8 +421,8 @@ int bio_add_pc_page(request_queue_t *q, struct bio *bio, struct page *page,
+ int bio_add_page(struct bio *bio, struct page *page, unsigned int len,
+ 		 unsigned int offset)
+ {
+-	return __bio_add_page(bdev_get_queue(bio->bi_bdev), bio, page,
+-			      len, offset);
++	struct request_queue *q = bdev_get_queue(bio->bi_bdev);
++	return __bio_add_page(q, bio, page, len, offset, q->max_sectors);
+ }
+ 
+ struct bio_map_data {
+@@ -533,7 +534,7 @@ struct bio *bio_copy_user(request_queue_t *q, unsigned long uaddr,
+ 			break;
+ 		}
+ 
+-		if (__bio_add_page(q, bio, page, bytes, 0) < bytes) {
++		if (bio_add_pc_page(q, bio, page, bytes, 0) < bytes) {
+ 			ret = -EINVAL;
+ 			break;
+ 		}
+@@ -647,7 +648,8 @@ static struct bio *__bio_map_user_iov(request_queue_t *q,
+ 			/*
+ 			 * sorry...
+ 			 */
+-			if (__bio_add_page(q, bio, pages[j], bytes, offset) < bytes)
++			if (bio_add_pc_page(q, bio, pages[j], bytes, offset) <
++					    bytes)
+ 				break;
+ 
+ 			len -= bytes;
+@@ -820,8 +822,8 @@ static struct bio *__bio_map_kern(request_queue_t *q, void *data,
+ 		if (bytes > len)
+ 			bytes = len;
+ 
+-		if (__bio_add_page(q, bio, virt_to_page(data), bytes,
+-				   offset) < bytes)
++		if (bio_add_pc_page(q, bio, virt_to_page(data), bytes,
++				    offset) < bytes)
+ 			break;
+ 
+ 		data += bytes;
+diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
+index 509e9a03a328..a18500d196e1 100644
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -702,7 +702,8 @@ extern int blkdev_issue_flush(struct block_device *, sector_t *);
+ 
+ #define MAX_PHYS_SEGMENTS 128
+ #define MAX_HW_SEGMENTS 128
+-#define MAX_SECTORS 255
++#define SAFE_MAX_SECTORS 255
++#define BLK_DEF_MAX_SECTORS 1024
+ 
+ #define MAX_SEGMENT_SIZE	65536
+ 

commit 8b05b773b6030de5b1bab1cbb0bf1ff8c34cdbe0
+Author: Mike Christie 
+Date:   Tue Nov 8 04:06:44 2005 -0600
+
+    [SCSI] convert st to use scsi_execute_async
+    
+    convert st to always send scatterlists and kill scsi_request
+    usage.
+    
+    This is the same as last time as it was posted, but with Kai's patches
+    merged and we now pass the bytes value to scsi_execute_async.
+    
+    TODO:
+    
+    - move DIO code to common place or make block layers usable for ULDs.
+    - move buffer allocation code to common place for all ULDs to use. And
+    make buffer allocation code handle all queue limits so we can find
+    out about problems before calling scsi_execute_async.
+    - move indirect (copy_to/from_user) paths commone place or make block
+    layers usable for ULDs.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
+index 053444b027d4..26e13dc7bcdb 100644
+--- a/drivers/scsi/st.c
++++ b/drivers/scsi/st.c
+@@ -50,7 +50,6 @@ static const char *verstr = "20050830";
+ #include 
+ #include 
+ #include 
+-#include 
+ #include 
+ 
+ 
+@@ -188,8 +187,6 @@ static int from_buffer(struct st_buffer *, char __user *, int);
+ static void move_buffer_data(struct st_buffer *, int);
+ static void buf_to_sg(struct st_buffer *, unsigned int);
+ 
+-static int st_map_user_pages(struct scatterlist *, const unsigned int, 
+-			     unsigned long, size_t, int, unsigned long);
+ static int sgl_map_user_pages(struct scatterlist *, const unsigned int, 
+ 			      unsigned long, size_t, int);
+ static int sgl_unmap_user_pages(struct scatterlist *, const unsigned int, int);
+@@ -313,12 +310,13 @@ static inline char *tape_name(struct scsi_tape *tape)
+ }
+ 
+ 
+-static void st_analyze_sense(struct scsi_request *SRpnt, struct st_cmdstatus *s)
++static void st_analyze_sense(struct st_request *SRpnt, struct st_cmdstatus *s)
+ {
+ 	const u8 *ucp;
+-	const u8 *sense = SRpnt->sr_sense_buffer;
++	const u8 *sense = SRpnt->sense;
+ 
+-	s->have_sense = scsi_request_normalize_sense(SRpnt, &s->sense_hdr);
++	s->have_sense = scsi_normalize_sense(SRpnt->sense,
++				SCSI_SENSE_BUFFERSIZE, &s->sense_hdr);
+ 	s->flags = 0;
+ 
+ 	if (s->have_sense) {
+@@ -345,9 +343,9 @@ static void st_analyze_sense(struct scsi_request *SRpnt, struct st_cmdstatus *s)
+ 
+ 
+ /* Convert the result to success code */
+-static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
++static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt)
+ {
+-	int result = SRpnt->sr_result;
++	int result = SRpnt->result;
+ 	u8 scode;
+ 	DEB(const char *stp;)
+ 	char *name = tape_name(STp);
+@@ -366,13 +364,12 @@ static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
+ 
+         DEB(
+         if (debugging) {
+-                printk(ST_DEB_MSG "%s: Error: %x, cmd: %x %x %x %x %x %x Len: %d\n",
++                printk(ST_DEB_MSG "%s: Error: %x, cmd: %x %x %x %x %x %x\n",
+ 		       name, result,
+-		       SRpnt->sr_cmnd[0], SRpnt->sr_cmnd[1], SRpnt->sr_cmnd[2],
+-		       SRpnt->sr_cmnd[3], SRpnt->sr_cmnd[4], SRpnt->sr_cmnd[5],
+-		       SRpnt->sr_bufflen);
++		       SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
++		       SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
+ 		if (cmdstatp->have_sense)
+-			scsi_print_req_sense("st", SRpnt);
++			 __scsi_print_sense("st", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
+ 	} ) /* end DEB */
+ 	if (!debugging) { /* Abnormal conditions for tape */
+ 		if (!cmdstatp->have_sense)
+@@ -386,20 +383,21 @@ static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
+ 			 /* scode != UNIT_ATTENTION && */
+ 			 scode != BLANK_CHECK &&
+ 			 scode != VOLUME_OVERFLOW &&
+-			 SRpnt->sr_cmnd[0] != MODE_SENSE &&
+-			 SRpnt->sr_cmnd[0] != TEST_UNIT_READY) {
++			 SRpnt->cmd[0] != MODE_SENSE &&
++			 SRpnt->cmd[0] != TEST_UNIT_READY) {
+ 				printk(KERN_WARNING "%s: Error with sense data: ", name);
+-				scsi_print_req_sense("st", SRpnt);
++				__scsi_print_sense("st", SRpnt->sense,
++						   SCSI_SENSE_BUFFERSIZE);
+ 		}
+ 	}
+ 
+ 	if (cmdstatp->fixed_format &&
+ 	    STp->cln_mode >= EXTENDED_SENSE_START) {  /* Only fixed format sense */
+ 		if (STp->cln_sense_value)
+-			STp->cleaning_req |= ((SRpnt->sr_sense_buffer[STp->cln_mode] &
++			STp->cleaning_req |= ((SRpnt->sense[STp->cln_mode] &
+ 					       STp->cln_sense_mask) == STp->cln_sense_value);
+ 		else
+-			STp->cleaning_req |= ((SRpnt->sr_sense_buffer[STp->cln_mode] &
++			STp->cleaning_req |= ((SRpnt->sense[STp->cln_mode] &
+ 					       STp->cln_sense_mask) != 0);
+ 	}
+ 	if (cmdstatp->have_sense &&
+@@ -411,8 +409,8 @@ static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
+ 	if (cmdstatp->have_sense &&
+ 	    scode == RECOVERED_ERROR
+ #if ST_RECOVERED_WRITE_FATAL
+-	    && SRpnt->sr_cmnd[0] != WRITE_6
+-	    && SRpnt->sr_cmnd[0] != WRITE_FILEMARKS
++	    && SRpnt->cmd[0] != WRITE_6
++	    && SRpnt->cmd[0] != WRITE_FILEMARKS
+ #endif
+ 	    ) {
+ 		STp->recover_count++;
+@@ -420,9 +418,9 @@ static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
+ 
+                 DEB(
+ 		if (debugging) {
+-			if (SRpnt->sr_cmnd[0] == READ_6)
++			if (SRpnt->cmd[0] == READ_6)
+ 				stp = "read";
+-			else if (SRpnt->sr_cmnd[0] == WRITE_6)
++			else if (SRpnt->cmd[0] == WRITE_6)
+ 				stp = "write";
+ 			else
+ 				stp = "ioctl";
+@@ -438,28 +436,37 @@ static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
+ 
+ 
+ /* Wakeup from interrupt */
+-static void st_sleep_done(struct scsi_cmnd * SCpnt)
++static void st_sleep_done(void *data, char *sense, int result, int resid)
+ {
+-	struct scsi_tape *STp = container_of(SCpnt->request->rq_disk->private_data,
+-					     struct scsi_tape, driver);
++	struct st_request *SRpnt = data;
++	struct scsi_tape *STp = SRpnt->stp;
+ 
+-	(STp->buffer)->cmdstat.midlevel_result = SCpnt->result;
+-	SCpnt->request->rq_status = RQ_SCSI_DONE;
++	memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE);
++	(STp->buffer)->cmdstat.midlevel_result = SRpnt->result = result;
+ 	DEB( STp->write_pending = 0; )
+ 
+-	if (SCpnt->request->waiting)
+-		complete(SCpnt->request->waiting);
++	if (SRpnt->waiting)
++		complete(SRpnt->waiting);
++}
++
++static struct st_request *st_allocate_request(void)
++{
++	return kzalloc(sizeof(struct st_request), GFP_KERNEL);
++}
++
++static void st_release_request(struct st_request *streq)
++{
++	kfree(streq);
+ }
+ 
+ /* Do the scsi command. Waits until command performed if do_wait is true.
+    Otherwise write_behind_check() is used to check that the command
+    has finished. */
+-static struct scsi_request *
+-st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd,
++static struct st_request *
++st_do_scsi(struct st_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd,
+ 	   int bytes, int direction, int timeout, int retries, int do_wait)
+ {
+ 	struct completion *waiting;
+-	unsigned char *bp;
+ 
+ 	/* if async, make sure there's no command outstanding */
+ 	if (!do_wait && ((STp->buffer)->last_SRpnt)) {
+@@ -473,7 +480,7 @@ st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *c
+ 	}
+ 
+ 	if (SRpnt == NULL) {
+-		SRpnt = scsi_allocate_request(STp->device, GFP_ATOMIC);
++		SRpnt = st_allocate_request();
+ 		if (SRpnt == NULL) {
+ 			DEBC( printk(KERN_ERR "%s: Can't get SCSI request.\n",
+ 				     tape_name(STp)); );
+@@ -483,6 +490,7 @@ st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *c
+ 				(STp->buffer)->syscall_result = (-EBUSY);
+ 			return NULL;
+ 		}
++		SRpnt->stp = STp;
+ 	}
+ 
+ 	/* If async IO, set last_SRpnt. This ptr tells write_behind_check
+@@ -492,32 +500,26 @@ st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *c
+ 
+ 	waiting = &STp->wait;
+ 	init_completion(waiting);
+-	SRpnt->sr_use_sg = STp->buffer->do_dio || (bytes > (STp->buffer)->frp[0].length);
+-	if (SRpnt->sr_use_sg) {
+-		if (!STp->buffer->do_dio)
+-			buf_to_sg(STp->buffer, bytes);
+-		SRpnt->sr_use_sg = (STp->buffer)->sg_segs;
+-		bp = (char *) &((STp->buffer)->sg[0]);
+-	} else
+-		bp = (STp->buffer)->b_data;
+-	SRpnt->sr_data_direction = direction;
+-	SRpnt->sr_cmd_len = 0;
+-	SRpnt->sr_request->waiting = waiting;
+-	SRpnt->sr_request->rq_status = RQ_SCSI_BUSY;
+-	SRpnt->sr_request->rq_disk = STp->disk;
+-	SRpnt->sr_request->end_io = blk_end_sync_rq;
+-	STp->buffer->cmdstat.have_sense = 0;
++	SRpnt->waiting = waiting;
+ 
+-	scsi_do_req(SRpnt, (void *) cmd, bp, bytes,
+-		    st_sleep_done, timeout, retries);
++	if (!STp->buffer->do_dio)
++		buf_to_sg(STp->buffer, bytes);
+ 
+-	if (do_wait) {
++	memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd));
++	STp->buffer->cmdstat.have_sense = 0;
++	STp->buffer->syscall_result = 0;
++
++	if (scsi_execute_async(STp->device, cmd, direction,
++			&((STp->buffer)->sg[0]), bytes, (STp->buffer)->sg_segs,
++			timeout, retries, SRpnt, st_sleep_done, GFP_KERNEL))
++		/* could not allocate the buffer or request was too large */
++		(STp->buffer)->syscall_result = (-EBUSY);
++	else if (do_wait) {
+ 		wait_for_completion(waiting);
+-		SRpnt->sr_request->waiting = NULL;
+-		if (SRpnt->sr_request->rq_status != RQ_SCSI_DONE)
+-			SRpnt->sr_result |= (DRIVER_ERROR << 24);
++		SRpnt->waiting = NULL;
+ 		(STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
+ 	}
++
+ 	return SRpnt;
+ }
+ 
+@@ -532,7 +534,7 @@ static int write_behind_check(struct scsi_tape * STp)
+ 	struct st_buffer *STbuffer;
+ 	struct st_partstat *STps;
+ 	struct st_cmdstatus *cmdstatp;
+-	struct scsi_request *SRpnt;
++	struct st_request *SRpnt;
+ 
+ 	STbuffer = STp->buffer;
+ 	if (!STbuffer->writing)
+@@ -548,12 +550,10 @@ static int write_behind_check(struct scsi_tape * STp)
+ 	wait_for_completion(&(STp->wait));
+ 	SRpnt = STbuffer->last_SRpnt;
+ 	STbuffer->last_SRpnt = NULL;
+-	SRpnt->sr_request->waiting = NULL;
+-	if (SRpnt->sr_request->rq_status != RQ_SCSI_DONE)
+-		SRpnt->sr_result |= (DRIVER_ERROR << 24);
++	SRpnt->waiting = NULL;
+ 
+ 	(STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
+-	scsi_release_request(SRpnt);
++	st_release_request(SRpnt);
+ 
+ 	STbuffer->buffer_bytes -= STbuffer->writing;
+ 	STps = &(STp->ps[STp->partition]);
+@@ -593,7 +593,7 @@ static int write_behind_check(struct scsi_tape * STp)
+    it messes up the block number). */
+ static int cross_eof(struct scsi_tape * STp, int forward)
+ {
+-	struct scsi_request *SRpnt;
++	struct st_request *SRpnt;
+ 	unsigned char cmd[MAX_COMMAND_SIZE];
+ 
+ 	cmd[0] = SPACE;
+@@ -613,7 +613,7 @@ static int cross_eof(struct scsi_tape * STp, int forward)
+ 	if (!SRpnt)
+ 		return (STp->buffer)->syscall_result;
+ 
+-	scsi_release_request(SRpnt);
++	st_release_request(SRpnt);
+ 	SRpnt = NULL;
+ 
+ 	if ((STp->buffer)->cmdstat.midlevel_result != 0)
+@@ -630,7 +630,7 @@ static int flush_write_buffer(struct scsi_tape * STp)
+ 	int offset, transfer, blks;
+ 	int result;
+ 	unsigned char cmd[MAX_COMMAND_SIZE];
+-	struct scsi_request *SRpnt;
++	struct st_request *SRpnt;
+ 	struct st_partstat *STps;
+ 
+ 	result = write_behind_check(STp);
+@@ -688,7 +688,7 @@ static int flush_write_buffer(struct scsi_tape * STp)
+ 			STp->dirty = 0;
+ 			(STp->buffer)->buffer_bytes = 0;
+ 		}
+-		scsi_release_request(SRpnt);
++		st_release_request(SRpnt);
+ 		SRpnt = NULL;
+ 	}
+ 	return result;
+@@ -785,7 +785,7 @@ static int set_mode_densblk(struct scsi_tape * STp, struct st_modedef * STm)
+ }
+ 
+ 
+-/* Lock or unlock the drive door. Don't use when scsi_request allocated. */
++/* Lock or unlock the drive door. Don't use when st_request allocated. */
+ static int do_door_lock(struct scsi_tape * STp, int do_lock)
+ {
+ 	int retval, cmd;
+@@ -844,7 +844,7 @@ static int test_ready(struct scsi_tape *STp, int do_wait)
+ 	int attentions, waits, max_wait, scode;
+ 	int retval = CHKRES_READY, new_session = 0;
+ 	unsigned char cmd[MAX_COMMAND_SIZE];
+-	struct scsi_request *SRpnt = NULL;
++	struct st_request *SRpnt = NULL;
+ 	struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
+ 
+ 	max_wait = do_wait ? ST_BLOCK_SECONDS : 0;
+@@ -903,7 +903,7 @@ static int test_ready(struct scsi_tape *STp, int do_wait)
+ 	}
+ 
+ 	if (SRpnt != NULL)
+-		scsi_release_request(SRpnt);
++		st_release_request(SRpnt);
+ 	return retval;
+ }
+ 
+@@ -918,7 +918,7 @@ static int check_tape(struct scsi_tape *STp, struct file *filp)
+ 	int i, retval, new_session = 0, do_wait;
+ 	unsigned char cmd[MAX_COMMAND_SIZE], saved_cleaning;
+ 	unsigned short st_flags = filp->f_flags;
+-	struct scsi_request *SRpnt = NULL;
++	struct st_request *SRpnt = NULL;
+ 	struct st_modedef *STm;
+ 	struct st_partstat *STps;
+ 	char *name = tape_name(STp);
+@@ -993,7 +993,7 @@ static int check_tape(struct scsi_tape *STp, struct file *filp)
+ 			goto err_out;
+ 		}
+ 
+-		if (!SRpnt->sr_result && !STp->buffer->cmdstat.have_sense) {
++		if (!SRpnt->result && !STp->buffer->cmdstat.have_sense) {
+ 			STp->max_block = ((STp->buffer)->b_data[1] << 16) |
+ 			    ((STp->buffer)->b_data[2] << 8) | (STp->buffer)->b_data[3];
+ 			STp->min_block = ((STp->buffer)->b_data[4] << 8) |
+@@ -1045,7 +1045,7 @@ static int check_tape(struct scsi_tape *STp, struct file *filp)
+ 		}
+ 		STp->drv_write_prot = ((STp->buffer)->b_data[2] & 0x80) != 0;
+ 	}
+-	scsi_release_request(SRpnt);
++	st_release_request(SRpnt);
+ 	SRpnt = NULL;
+         STp->inited = 1;
+ 
+@@ -1196,7 +1196,7 @@ static int st_flush(struct file *filp)
+ {
+ 	int result = 0, result2;
+ 	unsigned char cmd[MAX_COMMAND_SIZE];
+-	struct scsi_request *SRpnt;
++	struct st_request *SRpnt;
+ 	struct scsi_tape *STp = filp->private_data;
+ 	struct st_modedef *STm = &(STp->modes[STp->current_mode]);
+ 	struct st_partstat *STps = &(STp->ps[STp->partition]);
+@@ -1249,7 +1249,7 @@ static int st_flush(struct file *filp)
+ 		      cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) &&
+ 		     (!cmdstatp->remainder_valid || cmdstatp->uremainder64 == 0))) {
+ 			/* Write successful at EOM */
+-			scsi_release_request(SRpnt);
++			st_release_request(SRpnt);
+ 			SRpnt = NULL;
+ 			if (STps->drv_file >= 0)
+ 				STps->drv_file++;
+@@ -1259,7 +1259,7 @@ static int st_flush(struct file *filp)
+ 			STps->eof = ST_FM;
+ 		}
+ 		else { /* Write error */
+-			scsi_release_request(SRpnt);
++			st_release_request(SRpnt);
+ 			SRpnt = NULL;
+ 			printk(KERN_ERR "%s: Error on write filemark.\n", name);
+ 			if (result == 0)
+@@ -1400,11 +1400,11 @@ static int setup_buffering(struct scsi_tape *STp, const char __user *buf,
+ 		i = STp->try_dio && try_rdio;
+ 	else
+ 		i = STp->try_dio && try_wdio;
++
+ 	if (i && ((unsigned long)buf & queue_dma_alignment(
+ 					STp->device->request_queue)) == 0) {
+-		i = st_map_user_pages(&(STbp->sg[0]), STbp->use_sg,
+-				      (unsigned long)buf, count, (is_read ? READ : WRITE),
+-				      STp->max_pfn);
++		i = sgl_map_user_pages(&(STbp->sg[0]), STbp->use_sg,
++				      (unsigned long)buf, count, (is_read ? READ : WRITE));
+ 		if (i > 0) {
+ 			STbp->do_dio = i;
+ 			STbp->buffer_bytes = 0;   /* can be used as transfer counter */
+@@ -1472,7 +1472,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
+ 	int async_write;
+ 	unsigned char cmd[MAX_COMMAND_SIZE];
+ 	const char __user *b_point;
+-	struct scsi_request *SRpnt = NULL;
++	struct st_request *SRpnt = NULL;
+ 	struct scsi_tape *STp = filp->private_data;
+ 	struct st_modedef *STm;
+ 	struct st_partstat *STps;
+@@ -1624,7 +1624,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
+ 			retval = STbp->syscall_result;
+ 			goto out;
+ 		}
+-		if (async_write) {
++		if (async_write && !STbp->syscall_result) {
+ 			STbp->writing = transfer;
+ 			STp->dirty = !(STbp->writing ==
+ 				       STbp->buffer_bytes);
+@@ -1698,7 +1698,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
+ 			} else {
+ 				count += do_count;
+ 				STps->drv_block = (-1);		/* Too cautious? */
+-				retval = (-EIO);
++				retval = STbp->syscall_result;
+ 			}
+ 
+ 		}
+@@ -1728,7 +1728,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
+ 
+  out:
+ 	if (SRpnt != NULL)
+-		scsi_release_request(SRpnt);
++		st_release_request(SRpnt);
+ 	release_buffering(STp);
+ 	up(&STp->lock);
+ 
+@@ -1742,11 +1742,11 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
+    Does release user buffer mapping if it is set.
+ */
+ static long read_tape(struct scsi_tape *STp, long count,
+-		      struct scsi_request ** aSRpnt)
++		      struct st_request ** aSRpnt)
+ {
+ 	int transfer, blks, bytes;
+ 	unsigned char cmd[MAX_COMMAND_SIZE];
+-	struct scsi_request *SRpnt;
++	struct st_request *SRpnt;
+ 	struct st_modedef *STm;
+ 	struct st_partstat *STps;
+ 	struct st_buffer *STbp;
+@@ -1802,10 +1802,10 @@ static long read_tape(struct scsi_tape *STp, long count,
+ 		retval = 1;
+ 		DEBC(printk(ST_DEB_MSG "%s: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
+                             name,
+-                            SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[1],
+-                            SRpnt->sr_sense_buffer[2], SRpnt->sr_sense_buffer[3],
+-                            SRpnt->sr_sense_buffer[4], SRpnt->sr_sense_buffer[5],
+-                            SRpnt->sr_sense_buffer[6], SRpnt->sr_sense_buffer[7]));
++                            SRpnt->sense[0], SRpnt->sense[1],
++                            SRpnt->sense[2], SRpnt->sense[3],
++                            SRpnt->sense[4], SRpnt->sense[5],
++                            SRpnt->sense[6], SRpnt->sense[7]));
+ 		if (cmdstatp->have_sense) {
+ 
+ 			if (cmdstatp->sense_hdr.sense_key == BLANK_CHECK)
+@@ -1835,7 +1835,7 @@ static long read_tape(struct scsi_tape *STp, long count,
+ 						}
+ 						STbp->buffer_bytes = bytes - transfer;
+ 					} else {
+-						scsi_release_request(SRpnt);
++						st_release_request(SRpnt);
+ 						SRpnt = *aSRpnt = NULL;
+ 						if (transfer == blks) {	/* We did not get anything, error */
+ 							printk(KERN_NOTICE "%s: Incorrect block size.\n", name);
+@@ -1929,7 +1929,7 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
+ 	ssize_t retval = 0;
+ 	ssize_t i, transfer;
+ 	int special, do_dio = 0;
+-	struct scsi_request *SRpnt = NULL;
++	struct st_request *SRpnt = NULL;
+ 	struct scsi_tape *STp = filp->private_data;
+ 	struct st_modedef *STm;
+ 	struct st_partstat *STps;
+@@ -2054,7 +2054,7 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
+ 
+  out:
+ 	if (SRpnt != NULL) {
+-		scsi_release_request(SRpnt);
++		st_release_request(SRpnt);
+ 		SRpnt = NULL;
+ 	}
+ 	if (do_dio) {
+@@ -2284,7 +2284,7 @@ static int st_set_options(struct scsi_tape *STp, long options)
+ static int read_mode_page(struct scsi_tape *STp, int page, int omit_block_descs)
+ {
+ 	unsigned char cmd[MAX_COMMAND_SIZE];
+-	struct scsi_request *SRpnt = NULL;
++	struct st_request *SRpnt = NULL;
+ 
+ 	memset(cmd, 0, MAX_COMMAND_SIZE);
+ 	cmd[0] = MODE_SENSE;
+@@ -2298,7 +2298,7 @@ static int read_mode_page(struct scsi_tape *STp, int page, int omit_block_descs)
+ 	if (SRpnt == NULL)
+ 		return (STp->buffer)->syscall_result;
+ 
+-	scsi_release_request(SRpnt);
++	st_release_request(SRpnt);
+ 
+ 	return (STp->buffer)->syscall_result;
+ }
+@@ -2310,7 +2310,7 @@ static int write_mode_page(struct scsi_tape *STp, int page, int slow)
+ {
+ 	int pgo;
+ 	unsigned char cmd[MAX_COMMAND_SIZE];
+-	struct scsi_request *SRpnt = NULL;
++	struct st_request *SRpnt = NULL;
+ 
+ 	memset(cmd, 0, MAX_COMMAND_SIZE);
+ 	cmd[0] = MODE_SELECT;
+@@ -2329,7 +2329,7 @@ static int write_mode_page(struct scsi_tape *STp, int page, int slow)
+ 	if (SRpnt == NULL)
+ 		return (STp->buffer)->syscall_result;
+ 
+-	scsi_release_request(SRpnt);
++	st_release_request(SRpnt);
+ 
+ 	return (STp->buffer)->syscall_result;
+ }
+@@ -2412,7 +2412,7 @@ static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_cod
+ 	DEB( char *name = tape_name(STp); )
+ 	unsigned char cmd[MAX_COMMAND_SIZE];
+ 	struct st_partstat *STps;
+-	struct scsi_request *SRpnt;
++	struct st_request *SRpnt;
+ 
+ 	if (STp->ready != ST_READY && !load_code) {
+ 		if (STp->ready == ST_NO_TAPE)
+@@ -2455,7 +2455,7 @@ static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_cod
+ 		return (STp->buffer)->syscall_result;
+ 
+ 	retval = (STp->buffer)->syscall_result;
+-	scsi_release_request(SRpnt);
++	st_release_request(SRpnt);
+ 
+ 	if (!retval) {	/* SCSI command successful */
+ 
+@@ -2503,7 +2503,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
+ 	int ioctl_result;
+ 	int chg_eof = 1;
+ 	unsigned char cmd[MAX_COMMAND_SIZE];
+-	struct scsi_request *SRpnt;
++	struct st_request *SRpnt;
+ 	struct st_partstat *STps;
+ 	int fileno, blkno, at_sm, undone;
+ 	int datalen = 0, direction = DMA_NONE;
+@@ -2757,7 +2757,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
+ 	ioctl_result = (STp->buffer)->syscall_result;
+ 
+ 	if (!ioctl_result) {	/* SCSI command successful */
+-		scsi_release_request(SRpnt);
++		st_release_request(SRpnt);
+ 		SRpnt = NULL;
+ 		STps->drv_block = blkno;
+ 		STps->drv_file = fileno;
+@@ -2872,7 +2872,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
+ 				/* Try the other possible state of Page Format if not
+ 				   already tried */
+ 				STp->use_pf = !STp->use_pf | PF_TESTED;
+-				scsi_release_request(SRpnt);
++				st_release_request(SRpnt);
+ 				SRpnt = NULL;
+ 				return st_int_ioctl(STp, cmd_in, arg);
+ 			}
+@@ -2882,7 +2882,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
+ 		if (cmdstatp->sense_hdr.sense_key == BLANK_CHECK)
+ 			STps->eof = ST_EOD;
+ 
+-		scsi_release_request(SRpnt);
++		st_release_request(SRpnt);
+ 		SRpnt = NULL;
+ 	}
+ 
+@@ -2898,7 +2898,7 @@ static int get_location(struct scsi_tape *STp, unsigned int *block, int *partiti
+ {
+ 	int result;
+ 	unsigned char scmd[MAX_COMMAND_SIZE];
+-	struct scsi_request *SRpnt;
++	struct st_request *SRpnt;
+ 	DEB( char *name = tape_name(STp); )
+ 
+ 	if (STp->ready != ST_READY)
+@@ -2944,7 +2944,7 @@ static int get_location(struct scsi_tape *STp, unsigned int *block, int *partiti
+                 DEBC(printk(ST_DEB_MSG "%s: Got tape pos. blk %d part %d.\n", name,
+                             *block, *partition));
+ 	}
+-	scsi_release_request(SRpnt);
++	st_release_request(SRpnt);
+ 	SRpnt = NULL;
+ 
+ 	return result;
+@@ -2961,7 +2961,7 @@ static int set_location(struct scsi_tape *STp, unsigned int block, int partition
+ 	unsigned int blk;
+ 	int timeout;
+ 	unsigned char scmd[MAX_COMMAND_SIZE];
+-	struct scsi_request *SRpnt;
++	struct st_request *SRpnt;
+ 	DEB( char *name = tape_name(STp); )
+ 
+ 	if (STp->ready != ST_READY)
+@@ -3047,7 +3047,7 @@ static int set_location(struct scsi_tape *STp, unsigned int block, int partition
+ 		result = 0;
+ 	}
+ 
+-	scsi_release_request(SRpnt);
++	st_release_request(SRpnt);
+ 	SRpnt = NULL;
+ 
+ 	return result;
+@@ -3577,7 +3577,7 @@ static long st_compat_ioctl(struct file *file, unsigned int cmd, unsigned long a
+ static struct st_buffer *
+  new_tape_buffer(int from_initialization, int need_dma, int max_sg)
+ {
+-	int i, got = 0, segs = 0;
++	int i, got = 0;
+ 	gfp_t priority;
+ 	struct st_buffer *tb;
+ 
+@@ -3594,10 +3594,8 @@ static struct st_buffer *
+ 		return NULL;
+ 	}
+ 	memset(tb, 0, i);
+-	tb->frp_segs = tb->orig_frp_segs = segs;
++	tb->frp_segs = tb->orig_frp_segs = 0;
+ 	tb->use_sg = max_sg;
+-	if (segs > 0)
+-		tb->b_data = page_address(tb->sg[0].page);
+ 	tb->frp = (struct st_buf_fragment *)(&(tb->sg[0]) + max_sg);
+ 
+ 	tb->in_use = 1;
+@@ -3628,7 +3626,7 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm
+ 	priority = GFP_KERNEL | __GFP_NOWARN;
+ 	if (need_dma)
+ 		priority |= GFP_DMA;
+-	for (b_size = PAGE_SIZE, order=0;
++	for (b_size = PAGE_SIZE, order=0; order <= 6 &&
+ 	     b_size < new_size - STbuffer->buffer_size;
+ 	     order++, b_size *= 2)
+ 		;  /* empty */
+@@ -3670,6 +3668,7 @@ static void normalize_buffer(struct st_buffer * STbuffer)
+ 	}
+ 	STbuffer->frp_segs = STbuffer->orig_frp_segs;
+ 	STbuffer->frp_sg_current = 0;
++	STbuffer->sg_segs = 0;
+ }
+ 
+ 
+@@ -3882,7 +3881,6 @@ static int st_probe(struct device *dev)
+ 	struct st_buffer *buffer;
+ 	int i, j, mode, dev_num, error;
+ 	char *stp;
+-	u64 bounce_limit;
+ 
+ 	if (SDp->type != TYPE_TAPE)
+ 		return -ENODEV;
+@@ -3892,7 +3890,8 @@ static int st_probe(struct device *dev)
+ 		return -ENODEV;
+ 	}
+ 
+-	i = SDp->host->sg_tablesize;
++	i = min(SDp->request_queue->max_hw_segments,
++		SDp->request_queue->max_phys_segments);
+ 	if (st_max_sg_segs < i)
+ 		i = st_max_sg_segs;
+ 	buffer = new_tape_buffer(1, (SDp->host)->unchecked_isa_dma, i);
+@@ -3994,11 +3993,6 @@ static int st_probe(struct device *dev)
+ 	tpnt->long_timeout = ST_LONG_TIMEOUT;
+ 	tpnt->try_dio = try_direct_io && !SDp->host->unchecked_isa_dma;
+ 
+-	bounce_limit = scsi_calculate_bounce_limit(SDp->host) >> PAGE_SHIFT;
+-	if (bounce_limit > ULONG_MAX)
+-		bounce_limit = ULONG_MAX;
+-	tpnt->max_pfn = bounce_limit;
+-
+ 	for (i = 0; i < ST_NBR_MODES; i++) {
+ 		STm = &(tpnt->modes[i]);
+ 		STm->defined = 0;
+@@ -4077,9 +4071,9 @@ static int st_probe(struct device *dev)
+ 
+ 	sdev_printk(KERN_WARNING, SDp,
+ 		    "Attached scsi tape %s", tape_name(tpnt));
+-	printk(KERN_WARNING "%s: try direct i/o: %s (alignment %d B), max page reachable by HBA %lu\n",
++	printk(KERN_WARNING "%s: try direct i/o: %s (alignment %d B)\n",
+ 	       tape_name(tpnt), tpnt->try_dio ? "yes" : "no",
+-	       queue_dma_alignment(SDp->request_queue) + 1, tpnt->max_pfn);
++	       queue_dma_alignment(SDp->request_queue) + 1);
+ 
+ 	return 0;
+ 
+@@ -4411,34 +4405,6 @@ static void do_create_class_files(struct scsi_tape *STp, int dev_num, int mode)
+ 	return;
+ }
+ 
+-
+-/* Pin down user pages and put them into a scatter gather list. Returns <= 0 if
+-   - mapping of all pages not successful
+-   - any page is above max_pfn
+-   (i.e., either completely successful or fails)
+-*/
+-static int st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages, 
+-			     unsigned long uaddr, size_t count, int rw,
+-			     unsigned long max_pfn)
+-{
+-	int i, nr_pages;
+-
+-	nr_pages = sgl_map_user_pages(sgl, max_pages, uaddr, count, rw);
+-	if (nr_pages <= 0)
+-		return nr_pages;
+-
+-	for (i=0; i < nr_pages; i++) {
+-		if (page_to_pfn(sgl[i].page) > max_pfn)
+-			goto out_unmap;
+-	}
+-	return nr_pages;
+-
+- out_unmap:
+-	sgl_unmap_user_pages(sgl, nr_pages, 0);
+-	return 0;
+-}
+-
+-
+ /* The following functions may be useful for a larger audience. */
+ static int sgl_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages, 
+ 			      unsigned long uaddr, size_t count, int rw)
+diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h
+index 790acac160bc..411209048d74 100644
+--- a/drivers/scsi/st.h
++++ b/drivers/scsi/st.h
+@@ -4,6 +4,7 @@
+ 
+ #include 
+ #include 
++#include 
+ 
+ /* Descriptor for analyzed sense data */
+ struct st_cmdstatus {
+@@ -17,6 +18,17 @@ struct st_cmdstatus {
+ 	u8 deferred;
+ };
+ 
++struct scsi_tape;
++
++/* scsi tape command */
++struct st_request {
++	unsigned char cmd[MAX_COMMAND_SIZE];
++	unsigned char sense[SCSI_SENSE_BUFFERSIZE];
++	int result;
++	struct scsi_tape *stp;
++	struct completion *waiting;
++};
++
+ /* The tape buffer descriptor. */
+ struct st_buffer {
+ 	unsigned char in_use;
+@@ -28,7 +40,7 @@ struct st_buffer {
+ 	int read_pointer;
+ 	int writing;
+ 	int syscall_result;
+-	struct scsi_request *last_SRpnt;
++	struct st_request *last_SRpnt;
+ 	struct st_cmdstatus cmdstat;
+ 	unsigned char *b_data;
+ 	unsigned short use_sg;	/* zero or max number of s/g segments for this adapter */

commit d6b10348f9397943eb968419a2b7f08895e38472
+Author: Mike Christie 
+Date:   Tue Nov 8 04:06:41 2005 -0600
+
+    [SCSI] convert sg to scsi_execute_async
+    
+    Convert sg to always send scatterlists, and kill scsi_request usage.
+    
+    TODO:
+    
+    - move DIO code to common place or make block layers usable for ULDs.
+    - move buffer allocation code to common place for all ULDs to use. And
+    make buffer allocation code obey all queue limits so we can find
+    out about problems before calling scsi_execute_async. Currently, sg.c
+    could allocate a buffer that is too large, and send the request
+    to scsi_execute_async. scsi_execute_async will then check it against
+    all the queue limits and return a failure in this case. It would nicer
+    to know about the queue limit violation right away.
+    - move indirect (copy_to/from_user) paths commone place or make block
+    layers usable for ULDs.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
+index b55c2a8a547c..221e96e2620a 100644
+--- a/drivers/scsi/sg.c
++++ b/drivers/scsi/sg.c
+@@ -104,8 +104,6 @@ static int sg_allow_dio = SG_ALLOW_DIO_DEF;
+ static int sg_add(struct class_device *, struct class_interface *);
+ static void sg_remove(struct class_device *, struct class_interface *);
+ 
+-static Scsi_Request *dummy_cmdp;	/* only used for sizeof */
+-
+ static DEFINE_RWLOCK(sg_dev_arr_lock);	/* Also used to lock
+ 							   file descriptor list for device */
+ 
+@@ -119,7 +117,7 @@ typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info */
+ 	unsigned short sglist_len; /* size of malloc'd scatter-gather list ++ */
+ 	unsigned bufflen;	/* Size of (aggregate) data buffer */
+ 	unsigned b_malloc_len;	/* actual len malloc'ed in buffer */
+-	void *buffer;		/* Data buffer or scatter list (k_use_sg>0) */
++	struct scatterlist *buffer;/* scatter list */
+ 	char dio_in_use;	/* 0->indirect IO (or mmap), 1->dio */
+ 	unsigned char cmd_opcode; /* first byte of command */
+ } Sg_scatter_hold;
+@@ -128,12 +126,11 @@ struct sg_device;		/* forward declarations */
+ struct sg_fd;
+ 
+ typedef struct sg_request {	/* SG_MAX_QUEUE requests outstanding per file */
+-	Scsi_Request *my_cmdp;	/* != 0  when request with lower levels */
+ 	struct sg_request *nextrp;	/* NULL -> tail request (slist) */
+ 	struct sg_fd *parentfp;	/* NULL -> not in use */
+ 	Sg_scatter_hold data;	/* hold buffer, perhaps scatter list */
+ 	sg_io_hdr_t header;	/* scsi command+info, see  */
+-	unsigned char sense_b[sizeof (dummy_cmdp->sr_sense_buffer)];
++	unsigned char sense_b[SCSI_SENSE_BUFFERSIZE];
+ 	char res_used;		/* 1 -> using reserve buffer, 0 -> not ... */
+ 	char orphan;		/* 1 -> drop on sight, 0 -> normal */
+ 	char sg_io_owned;	/* 1 -> packet belongs to SG_IO */
+@@ -174,7 +171,8 @@ typedef struct sg_device { /* holds the state of each scsi generic device */
+ } Sg_device;
+ 
+ static int sg_fasync(int fd, struct file *filp, int mode);
+-static void sg_cmd_done(Scsi_Cmnd * SCpnt);	/* tasklet or soft irq callback */
++/* tasklet or soft irq callback */
++static void sg_cmd_done(void *data, char *sense, int result, int resid);
+ static int sg_start_req(Sg_request * srp);
+ static void sg_finish_rem_req(Sg_request * srp);
+ static int sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size);
+@@ -195,8 +193,8 @@ static void sg_remove_scat(Sg_scatter_hold * schp);
+ static void sg_build_reserve(Sg_fd * sfp, int req_size);
+ static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size);
+ static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp);
+-static char *sg_page_malloc(int rqSz, int lowDma, int *retSzp);
+-static void sg_page_free(char *buff, int size);
++static struct page *sg_page_malloc(int rqSz, int lowDma, int *retSzp);
++static void sg_page_free(struct page *page, int size);
+ static Sg_fd *sg_add_sfp(Sg_device * sdp, int dev);
+ static int sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp);
+ static void __sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp);
+@@ -207,7 +205,6 @@ static int sg_res_in_use(Sg_fd * sfp);
+ static int sg_allow_access(unsigned char opcode, char dev_type);
+ static int sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len);
+ static Sg_device *sg_get_dev(int dev);
+-static inline unsigned char *sg_scatg2virt(const struct scatterlist *sclp);
+ #ifdef CONFIG_SCSI_PROC_FS
+ static int sg_last_dev(void);
+ #endif
+@@ -226,6 +223,7 @@ sg_open(struct inode *inode, struct file *filp)
+ {
+ 	int dev = iminor(inode);
+ 	int flags = filp->f_flags;
++	struct request_queue *q;
+ 	Sg_device *sdp;
+ 	Sg_fd *sfp;
+ 	int res;
+@@ -287,7 +285,9 @@ sg_open(struct inode *inode, struct file *filp)
+ 	}
+ 	if (!sdp->headfp) {	/* no existing opens on this device */
+ 		sdp->sgdebug = 0;
+-		sdp->sg_tablesize = sdp->device->host->sg_tablesize;
++		q = sdp->device->request_queue;
++		sdp->sg_tablesize = min(q->max_hw_segments,
++					q->max_phys_segments);
+ 	}
+ 	if ((sfp = sg_add_sfp(sdp, dev)))
+ 		filp->private_data = sfp;
+@@ -340,6 +340,7 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
+ 		return -ENXIO;
+ 	SCSI_LOG_TIMEOUT(3, printk("sg_read: %s, count=%d\n",
+ 				   sdp->disk->disk_name, (int) count));
++
+ 	if (!access_ok(VERIFY_WRITE, buf, count))
+ 		return -EFAULT;
+ 	if (sfp->force_packid && (count >= SZ_SG_HEADER)) {
+@@ -491,7 +492,7 @@ sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp)
+ 	if ((hp->mx_sb_len > 0) && hp->sbp) {
+ 		if ((CHECK_CONDITION & hp->masked_status) ||
+ 		    (DRIVER_SENSE & hp->driver_status)) {
+-			int sb_len = sizeof (dummy_cmdp->sr_sense_buffer);
++			int sb_len = SCSI_SENSE_BUFFERSIZE;
+ 			sb_len = (hp->mx_sb_len > sb_len) ? sb_len : hp->mx_sb_len;
+ 			len = 8 + (int) srp->sense_b[7];	/* Additional sense length field */
+ 			len = (len > sb_len) ? sb_len : len;
+@@ -525,7 +526,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
+ 	Sg_request *srp;
+ 	struct sg_header old_hdr;
+ 	sg_io_hdr_t *hp;
+-	unsigned char cmnd[sizeof (dummy_cmdp->sr_cmnd)];
++	unsigned char cmnd[MAX_COMMAND_SIZE];
+ 
+ 	if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
+ 		return -ENXIO;
+@@ -624,7 +625,7 @@ sg_new_write(Sg_fd * sfp, const char __user *buf, size_t count,
+ 	int k;
+ 	Sg_request *srp;
+ 	sg_io_hdr_t *hp;
+-	unsigned char cmnd[sizeof (dummy_cmdp->sr_cmnd)];
++	unsigned char cmnd[MAX_COMMAND_SIZE];
+ 	int timeout;
+ 	unsigned long ul_timeout;
+ 
+@@ -692,11 +693,9 @@ static int
+ sg_common_write(Sg_fd * sfp, Sg_request * srp,
+ 		unsigned char *cmnd, int timeout, int blocking)
+ {
+-	int k;
+-	Scsi_Request *SRpnt;
++	int k, data_dir;
+ 	Sg_device *sdp = sfp->parentdp;
+ 	sg_io_hdr_t *hp = &srp->header;
+-	request_queue_t *q;
+ 
+ 	srp->data.cmd_opcode = cmnd[0];	/* hold opcode of command */
+ 	hp->status = 0;
+@@ -723,51 +722,36 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
+ 		sg_finish_rem_req(srp);
+ 		return -ENODEV;
+ 	}
+-	SRpnt = scsi_allocate_request(sdp->device, GFP_ATOMIC);
+-	if (SRpnt == NULL) {
+-		SCSI_LOG_TIMEOUT(1, printk("sg_write: no mem\n"));
+-		sg_finish_rem_req(srp);
+-		return -ENOMEM;
+-	}
+ 
+-	srp->my_cmdp = SRpnt;
+-	q = SRpnt->sr_device->request_queue;
+-	SRpnt->sr_request->rq_disk = sdp->disk;
+-	SRpnt->sr_sense_buffer[0] = 0;
+-	SRpnt->sr_cmd_len = hp->cmd_len;
+-	SRpnt->sr_use_sg = srp->data.k_use_sg;
+-	SRpnt->sr_sglist_len = srp->data.sglist_len;
+-	SRpnt->sr_bufflen = srp->data.bufflen;
+-	SRpnt->sr_underflow = 0;
+-	SRpnt->sr_buffer = srp->data.buffer;
+ 	switch (hp->dxfer_direction) {
+ 	case SG_DXFER_TO_FROM_DEV:
+ 	case SG_DXFER_FROM_DEV:
+-		SRpnt->sr_data_direction = DMA_FROM_DEVICE;
++		data_dir = DMA_FROM_DEVICE;
+ 		break;
+ 	case SG_DXFER_TO_DEV:
+-		SRpnt->sr_data_direction = DMA_TO_DEVICE;
++		data_dir = DMA_TO_DEVICE;
+ 		break;
+ 	case SG_DXFER_UNKNOWN:
+-		SRpnt->sr_data_direction = DMA_BIDIRECTIONAL;
++		data_dir = DMA_BIDIRECTIONAL;
+ 		break;
+ 	default:
+-		SRpnt->sr_data_direction = DMA_NONE;
++		data_dir = DMA_NONE;
+ 		break;
+ 	}
+-	SRpnt->upper_private_data = srp;
+-	srp->data.k_use_sg = 0;
+-	srp->data.sglist_len = 0;
+-	srp->data.bufflen = 0;
+-	srp->data.buffer = NULL;
+ 	hp->duration = jiffies_to_msecs(jiffies);
+ /* Now send everything of to mid-level. The next time we hear about this
+    packet is when sg_cmd_done() is called (i.e. a callback). */
+-	scsi_do_req(SRpnt, (void *) cmnd,
+-		    (void *) SRpnt->sr_buffer, hp->dxfer_len,
+-		    sg_cmd_done, timeout, SG_DEFAULT_RETRIES);
+-	/* dxfer_len overwrites SRpnt->sr_bufflen, hence need for b_malloc_len */
+-	return 0;
++	if (scsi_execute_async(sdp->device, cmnd, data_dir, srp->data.buffer,
++				hp->dxfer_len, srp->data.k_use_sg, timeout,
++				SG_DEFAULT_RETRIES, srp, sg_cmd_done,
++				GFP_ATOMIC)) {
++		SCSI_LOG_TIMEOUT(1, printk("sg_write: scsi_execute_async failed\n"));
++		/*
++		 * most likely out of mem, but could also be a bad map
++		 */
++		return -ENOMEM;
++	} else
++		return 0;
+ }
+ 
+ static int
+@@ -1156,45 +1140,22 @@ sg_fasync(int fd, struct file *filp, int mode)
+ 	return (retval < 0) ? retval : 0;
+ }
+ 
+-static inline unsigned char *
+-sg_scatg2virt(const struct scatterlist *sclp)
+-{
+-	return (sclp && sclp->page) ?
+-	    (unsigned char *) page_address(sclp->page) + sclp->offset : NULL;
+-}
+-
+ /* When startFinish==1 increments page counts for pages other than the 
+-   first of scatter gather elements obtained from __get_free_pages().
++   first of scatter gather elements obtained from alloc_pages().
+    When startFinish==0 decrements ... */
+ static void
+ sg_rb_correct4mmap(Sg_scatter_hold * rsv_schp, int startFinish)
+ {
+-	void *page_ptr;
++	struct scatterlist *sg = rsv_schp->buffer;
+ 	struct page *page;
+ 	int k, m;
+ 
+ 	SCSI_LOG_TIMEOUT(3, printk("sg_rb_correct4mmap: startFinish=%d, scatg=%d\n", 
+ 				   startFinish, rsv_schp->k_use_sg));
+ 	/* N.B. correction _not_ applied to base page of each allocation */
+-	if (rsv_schp->k_use_sg) {	/* reserve buffer is a scatter gather list */
+-		struct scatterlist *sclp = rsv_schp->buffer;
+-
+-		for (k = 0; k < rsv_schp->k_use_sg; ++k, ++sclp) {
+-			for (m = PAGE_SIZE; m < sclp->length; m += PAGE_SIZE) {
+-				page_ptr = sg_scatg2virt(sclp) + m;
+-				page = virt_to_page(page_ptr);
+-				if (startFinish)
+-					get_page(page);
+-				else {
+-					if (page_count(page) > 0)
+-						__put_page(page);
+-				}
+-			}
+-		}
+-	} else {		/* reserve buffer is just a single allocation */
+-		for (m = PAGE_SIZE; m < rsv_schp->bufflen; m += PAGE_SIZE) {
+-			page_ptr = (unsigned char *) rsv_schp->buffer + m;
+-			page = virt_to_page(page_ptr);
++	for (k = 0; k < rsv_schp->k_use_sg; ++k, ++sg) {
++		for (m = PAGE_SIZE; m < sg->length; m += PAGE_SIZE) {
++			page = sg->page;
+ 			if (startFinish)
+ 				get_page(page);
+ 			else {
+@@ -1210,9 +1171,10 @@ sg_vma_nopage(struct vm_area_struct *vma, unsigned long addr, int *type)
+ {
+ 	Sg_fd *sfp;
+ 	struct page *page = NOPAGE_SIGBUS;
+-	void *page_ptr = NULL;
+-	unsigned long offset;
++	unsigned long offset, len, sa;
+ 	Sg_scatter_hold *rsv_schp;
++	struct scatterlist *sg;
++	int k;
+ 
+ 	if ((NULL == vma) || (!(sfp = (Sg_fd *) vma->vm_private_data)))
+ 		return page;
+@@ -1222,30 +1184,21 @@ sg_vma_nopage(struct vm_area_struct *vma, unsigned long addr, int *type)
+ 		return page;
+ 	SCSI_LOG_TIMEOUT(3, printk("sg_vma_nopage: offset=%lu, scatg=%d\n",
+ 				   offset, rsv_schp->k_use_sg));
+-	if (rsv_schp->k_use_sg) {	/* reserve buffer is a scatter gather list */
+-		int k;
+-		unsigned long sa = vma->vm_start;
+-		unsigned long len;
+-		struct scatterlist *sclp = rsv_schp->buffer;
+-
+-		for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end);
+-		     ++k, ++sclp) {
+-			len = vma->vm_end - sa;
+-			len = (len < sclp->length) ? len : sclp->length;
+-			if (offset < len) {
+-				page_ptr = sg_scatg2virt(sclp) + offset;
+-				page = virt_to_page(page_ptr);
+-				get_page(page);	/* increment page count */
+-				break;
+-			}
+-			sa += len;
+-			offset -= len;
++	sg = rsv_schp->buffer;
++	sa = vma->vm_start;
++	for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end);
++	     ++k, ++sg) {
++		len = vma->vm_end - sa;
++		len = (len < sg->length) ? len : sg->length;
++		if (offset < len) {
++			page = sg->page;
++			get_page(page);	/* increment page count */
++			break;
+ 		}
+-	} else {		/* reserve buffer is just a single allocation */
+-		page_ptr = (unsigned char *) rsv_schp->buffer + offset;
+-		page = virt_to_page(page_ptr);
+-		get_page(page);	/* increment page count */
++		sa += len;
++		offset -= len;
+ 	}
++
+ 	if (type)
+ 		*type = VM_FAULT_MINOR;
+ 	return page;
+@@ -1259,8 +1212,10 @@ static int
+ sg_mmap(struct file *filp, struct vm_area_struct *vma)
+ {
+ 	Sg_fd *sfp;
+-	unsigned long req_sz;
++	unsigned long req_sz, len, sa;
+ 	Sg_scatter_hold *rsv_schp;
++	int k;
++	struct scatterlist *sg;
+ 
+ 	if ((!filp) || (!vma) || (!(sfp = (Sg_fd *) filp->private_data)))
+ 		return -ENXIO;
+@@ -1273,24 +1228,15 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma)
+ 	if (req_sz > rsv_schp->bufflen)
+ 		return -ENOMEM;	/* cannot map more than reserved buffer */
+ 
+-	if (rsv_schp->k_use_sg) { /* reserve buffer is a scatter gather list */
+-		int k;
+-		unsigned long sa = vma->vm_start;
+-		unsigned long len;
+-		struct scatterlist *sclp = rsv_schp->buffer;
+-
+-		for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end);
+-		     ++k, ++sclp) {
+-			if (0 != sclp->offset)
+-				return -EFAULT;	/* non page aligned memory ?? */
+-			len = vma->vm_end - sa;
+-			len = (len < sclp->length) ? len : sclp->length;
+-			sa += len;
+-		}
+-	} else {	/* reserve buffer is just a single allocation */
+-		if ((unsigned long) rsv_schp->buffer & (PAGE_SIZE - 1))
+-			return -EFAULT;	/* non page aligned memory ?? */
++	sa = vma->vm_start;
++	sg = rsv_schp->buffer;
++	for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end);
++	     ++k, ++sg) {
++		len = vma->vm_end - sa;
++		len = (len < sg->length) ? len : sg->length;
++		sa += len;
+ 	}
++
+ 	if (0 == sfp->mmap_called) {
+ 		sg_rb_correct4mmap(rsv_schp, 1);	/* do only once per fd lifetime */
+ 		sfp->mmap_called = 1;
+@@ -1304,21 +1250,16 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma)
+ /* This function is a "bottom half" handler that is called by the
+  * mid level when a command is completed (or has failed). */
+ static void
+-sg_cmd_done(Scsi_Cmnd * SCpnt)
++sg_cmd_done(void *data, char *sense, int result, int resid)
+ {
+-	Scsi_Request *SRpnt = NULL;
++	Sg_request *srp = data;
+ 	Sg_device *sdp = NULL;
+ 	Sg_fd *sfp;
+-	Sg_request *srp = NULL;
+ 	unsigned long iflags;
+ 	unsigned int ms;
+ 
+-	if (SCpnt && (SRpnt = SCpnt->sc_request))
+-		srp = (Sg_request *) SRpnt->upper_private_data;
+ 	if (NULL == srp) {
+ 		printk(KERN_ERR "sg_cmd_done: NULL request\n");
+-		if (SRpnt)
+-			scsi_release_request(SRpnt);
+ 		return;
+ 	}
+ 	sfp = srp->parentfp;
+@@ -1326,49 +1267,34 @@ sg_cmd_done(Scsi_Cmnd * SCpnt)
+ 		sdp = sfp->parentdp;
+ 	if ((NULL == sdp) || sdp->detached) {
+ 		printk(KERN_INFO "sg_cmd_done: device detached\n");
+-		scsi_release_request(SRpnt);
+ 		return;
+ 	}
+ 
+-	/* First transfer ownership of data buffers to sg_device object. */
+-	srp->data.k_use_sg = SRpnt->sr_use_sg;
+-	srp->data.sglist_len = SRpnt->sr_sglist_len;
+-	srp->data.bufflen = SRpnt->sr_bufflen;
+-	srp->data.buffer = SRpnt->sr_buffer;
+-	/* now clear out request structure */
+-	SRpnt->sr_use_sg = 0;
+-	SRpnt->sr_sglist_len = 0;
+-	SRpnt->sr_bufflen = 0;
+-	SRpnt->sr_buffer = NULL;
+-	SRpnt->sr_underflow = 0;
+-	SRpnt->sr_request->rq_disk = NULL; /* "sg" _disowns_ request blk */
+-
+-	srp->my_cmdp = NULL;
+ 
+ 	SCSI_LOG_TIMEOUT(4, printk("sg_cmd_done: %s, pack_id=%d, res=0x%x\n",
+-		sdp->disk->disk_name, srp->header.pack_id, (int) SRpnt->sr_result));
+-	srp->header.resid = SCpnt->resid;
++		sdp->disk->disk_name, srp->header.pack_id, result));
++	srp->header.resid = resid;
+ 	ms = jiffies_to_msecs(jiffies);
+ 	srp->header.duration = (ms > srp->header.duration) ?
+ 				(ms - srp->header.duration) : 0;
+-	if (0 != SRpnt->sr_result) {
++	if (0 != result) {
+ 		struct scsi_sense_hdr sshdr;
+ 
+-		memcpy(srp->sense_b, SRpnt->sr_sense_buffer,
+-		       sizeof (srp->sense_b));
+-		srp->header.status = 0xff & SRpnt->sr_result;
+-		srp->header.masked_status = status_byte(SRpnt->sr_result);
+-		srp->header.msg_status = msg_byte(SRpnt->sr_result);
+-		srp->header.host_status = host_byte(SRpnt->sr_result);
+-		srp->header.driver_status = driver_byte(SRpnt->sr_result);
++		memcpy(srp->sense_b, sense, sizeof (srp->sense_b));
++		srp->header.status = 0xff & result;
++		srp->header.masked_status = status_byte(result);
++		srp->header.msg_status = msg_byte(result);
++		srp->header.host_status = host_byte(result);
++		srp->header.driver_status = driver_byte(result);
+ 		if ((sdp->sgdebug > 0) &&
+ 		    ((CHECK_CONDITION == srp->header.masked_status) ||
+ 		     (COMMAND_TERMINATED == srp->header.masked_status)))
+-			scsi_print_req_sense("sg_cmd_done", SRpnt);
++			__scsi_print_sense("sg_cmd_done", sense,
++					   SCSI_SENSE_BUFFERSIZE);
+ 
+ 		/* Following if statement is a patch supplied by Eric Youngdale */
+-		if (driver_byte(SRpnt->sr_result) != 0
+-		    && scsi_command_normalize_sense(SCpnt, &sshdr)
++		if (driver_byte(result) != 0
++		    && scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, &sshdr)
+ 		    && !scsi_sense_is_deferred(&sshdr)
+ 		    && sshdr.sense_key == UNIT_ATTENTION
+ 		    && sdp->device->removable) {
+@@ -1379,8 +1305,6 @@ sg_cmd_done(Scsi_Cmnd * SCpnt)
+ 	}
+ 	/* Rely on write phase to clean out srp status values, so no "else" */
+ 
+-	scsi_release_request(SRpnt);
+-	SRpnt = NULL;
+ 	if (sfp->closed) {	/* whoops this fd already released, cleanup */
+ 		SCSI_LOG_TIMEOUT(1, printk("sg_cmd_done: already closed, freeing ...\n"));
+ 		sg_finish_rem_req(srp);
+@@ -1431,6 +1355,7 @@ static int sg_sysfs_valid = 0;
+ 
+ static int sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
+ {
++	struct request_queue *q = scsidp->request_queue;
+ 	Sg_device *sdp;
+ 	unsigned long iflags;
+ 	void *old_sg_dev_arr = NULL;
+@@ -1473,7 +1398,7 @@ static int sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
+ 	sdp->disk = disk;
+ 	sdp->device = scsidp;
+ 	init_waitqueue_head(&sdp->o_excl_wait);
+-	sdp->sg_tablesize = scsidp->host ? scsidp->host->sg_tablesize : 0;
++	sdp->sg_tablesize = min(q->max_hw_segments, q->max_phys_segments);
+ 
+ 	sg_nr_dev++;
+ 	sg_dev_arr[k] = sdp;
+@@ -1753,36 +1678,35 @@ sg_finish_rem_req(Sg_request * srp)
+ static int
+ sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, int tablesize)
+ {
+-	int ret_sz;
+-	int elem_sz = sizeof (struct scatterlist);
+-	int sg_bufflen = tablesize * elem_sz;
+-	int mx_sc_elems = tablesize;
++	int sg_bufflen = tablesize * sizeof(struct scatterlist);
++	unsigned int gfp_flags = GFP_ATOMIC | __GFP_NOWARN;
+ 
+-	schp->buffer = sg_page_malloc(sg_bufflen, sfp->low_dma, &ret_sz);
++	/*
++	 * TODO: test without low_dma, we should not need it since
++	 * the block layer will bounce the buffer for us
++	 *
++	 * XXX(hch): we shouldn't need GFP_DMA for the actual S/G list.
++	 */
++	if (sfp->low_dma)
++		 gfp_flags |= GFP_DMA;
++	schp->buffer = kzalloc(sg_bufflen, gfp_flags);
+ 	if (!schp->buffer)
+ 		return -ENOMEM;
+-	else if (ret_sz != sg_bufflen) {
+-		sg_bufflen = ret_sz;
+-		mx_sc_elems = sg_bufflen / elem_sz;
+-	}
+ 	schp->sglist_len = sg_bufflen;
+-	memset(schp->buffer, 0, sg_bufflen);
+-	return mx_sc_elems;	/* number of scat_gath elements allocated */
++	return tablesize;	/* number of scat_gath elements allocated */
+ }
+ 
+ #ifdef SG_ALLOW_DIO_CODE
+ /* vvvvvvvv  following code borrowed from st driver's direct IO vvvvvvvvv */
+-	/* hopefully this generic code will moved to a library */
++	/* TODO: hopefully we can use the generic block layer code */
+ 
+ /* Pin down user pages and put them into a scatter gather list. Returns <= 0 if
+    - mapping of all pages not successful
+-   - any page is above max_pfn
+    (i.e., either completely successful or fails)
+ */
+ static int 
+ st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages, 
+-	          unsigned long uaddr, size_t count, int rw,
+-	          unsigned long max_pfn)
++	          unsigned long uaddr, size_t count, int rw)
+ {
+ 	unsigned long end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ 	unsigned long start = uaddr >> PAGE_SHIFT;
+@@ -1828,21 +1752,17 @@ st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages,
+                  * probably wrong function for rw==WRITE
+                  */
+ 		flush_dcache_page(pages[i]);
+-		if (page_to_pfn(pages[i]) > max_pfn)
+-			goto out_unlock;
+ 		/* ?? Is locking needed? I don't think so */
+ 		/* if (TestSetPageLocked(pages[i]))
+ 		   goto out_unlock; */
+         }
+ 
+-	/* Populate the scatter/gather list */
+-	sgl[0].page = pages[0]; 
++	sgl[0].page = pages[0];
+ 	sgl[0].offset = uaddr & ~PAGE_MASK;
+ 	if (nr_pages > 1) {
+ 		sgl[0].length = PAGE_SIZE - sgl[0].offset;
+ 		count -= sgl[0].length;
+ 		for (i=1; i < nr_pages ; i++) {
+-			sgl[i].offset = 0;
+ 			sgl[i].page = pages[i]; 
+ 			sgl[i].length = count < PAGE_SIZE ? count : PAGE_SIZE;
+ 			count -= PAGE_SIZE;
+@@ -1855,10 +1775,6 @@ st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages,
+ 	kfree(pages);
+ 	return nr_pages;
+ 
+- out_unlock:
+-	/* for (j=0; j < i; j++)
+-	   unlock_page(pages[j]); */
+-	res = 0;
+  out_unmap:
+ 	if (res > 0) {
+ 		for (j=0; j < res; j++)
+@@ -1904,20 +1820,20 @@ sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len)
+ 	sg_io_hdr_t *hp = &srp->header;
+ 	Sg_scatter_hold *schp = &srp->data;
+ 	int sg_tablesize = sfp->parentdp->sg_tablesize;
+-	struct scatterlist *sgl;
+ 	int mx_sc_elems, res;
+ 	struct scsi_device *sdev = sfp->parentdp->device;
+ 
+ 	if (((unsigned long)hp->dxferp &
+ 			queue_dma_alignment(sdev->request_queue)) != 0)
+ 		return 1;
++
+ 	mx_sc_elems = sg_build_sgat(schp, sfp, sg_tablesize);
+         if (mx_sc_elems <= 0) {
+                 return 1;
+         }
+-	sgl = (struct scatterlist *)schp->buffer;
+-	res = st_map_user_pages(sgl, mx_sc_elems, (unsigned long)hp->dxferp, dxfer_len, 
+-				(SG_DXFER_TO_DEV == hp->dxfer_direction) ? 1 : 0, ULONG_MAX);
++	res = st_map_user_pages(schp->buffer, mx_sc_elems,
++				(unsigned long)hp->dxferp, dxfer_len, 
++				(SG_DXFER_TO_DEV == hp->dxfer_direction) ? 1 : 0);
+ 	if (res <= 0)
+ 		return 1;
+ 	schp->k_use_sg = res;
+@@ -1932,9 +1848,11 @@ sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len)
+ static int
+ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size)
+ {
+-	int ret_sz;
++	struct scatterlist *sg;
++	int ret_sz = 0, k, rem_sz, num, mx_sc_elems;
++	int sg_tablesize = sfp->parentdp->sg_tablesize;
+ 	int blk_size = buff_size;
+-	unsigned char *p = NULL;
++	struct page *p = NULL;
+ 
+ 	if ((blk_size < 0) || (!sfp))
+ 		return -EFAULT;
+@@ -1944,59 +1862,35 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size)
+ 	blk_size = (blk_size + SG_SECTOR_MSK) & (~SG_SECTOR_MSK);
+ 	SCSI_LOG_TIMEOUT(4, printk("sg_build_indirect: buff_size=%d, blk_size=%d\n",
+ 				   buff_size, blk_size));
+-	if (blk_size <= SG_SCATTER_SZ) {
+-		p = sg_page_malloc(blk_size, sfp->low_dma, &ret_sz);
+-		if (!p)
+-			return -ENOMEM;
+-		if (blk_size == ret_sz) {	/* got it on the first attempt */
+-			schp->k_use_sg = 0;
+-			schp->buffer = p;
+-			schp->bufflen = blk_size;
+-			schp->b_malloc_len = blk_size;
+-			return 0;
+-		}
+-	} else {
+-		p = sg_page_malloc(SG_SCATTER_SZ, sfp->low_dma, &ret_sz);
++
++	/* N.B. ret_sz carried into this block ... */
++	mx_sc_elems = sg_build_sgat(schp, sfp, sg_tablesize);
++	if (mx_sc_elems < 0)
++		return mx_sc_elems;	/* most likely -ENOMEM */
++
++	for (k = 0, sg = schp->buffer, rem_sz = blk_size;
++	     (rem_sz > 0) && (k < mx_sc_elems);
++	     ++k, rem_sz -= ret_sz, ++sg) {
++		
++		num = (rem_sz > SG_SCATTER_SZ) ? SG_SCATTER_SZ : rem_sz;
++		p = sg_page_malloc(num, sfp->low_dma, &ret_sz);
+ 		if (!p)
+ 			return -ENOMEM;
+-	}
+-/* Want some local declarations, so start new block ... */
+-	{			/* lets try and build a scatter gather list */
+-		struct scatterlist *sclp;
+-		int k, rem_sz, num;
+-		int mx_sc_elems;
+-		int sg_tablesize = sfp->parentdp->sg_tablesize;
+-		int first = 1;
+-
+-		/* N.B. ret_sz carried into this block ... */
+-		mx_sc_elems = sg_build_sgat(schp, sfp, sg_tablesize);
+-		if (mx_sc_elems < 0)
+-			return mx_sc_elems;	/* most likely -ENOMEM */
+-
+-		for (k = 0, sclp = schp->buffer, rem_sz = blk_size;
+-		     (rem_sz > 0) && (k < mx_sc_elems);
+-		     ++k, rem_sz -= ret_sz, ++sclp) {
+-			if (first)
+-				first = 0;
+-			else {
+-				num =
+-				    (rem_sz >
+-				     SG_SCATTER_SZ) ? SG_SCATTER_SZ : rem_sz;
+-				p = sg_page_malloc(num, sfp->low_dma, &ret_sz);
+-				if (!p)
+-					break;
+-			}
+-			sg_set_buf(sclp, p, ret_sz);
+-
+-			SCSI_LOG_TIMEOUT(5, printk("sg_build_build: k=%d, a=0x%p, len=%d\n",
+-					  k, sg_scatg2virt(sclp), ret_sz));
+-		}		/* end of for loop */
+-		schp->k_use_sg = k;
+-		SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k_use_sg=%d, rem_sz=%d\n", k, rem_sz));
+-		schp->bufflen = blk_size;
+-		if (rem_sz > 0)	/* must have failed */
+-			return -ENOMEM;
+-	}
++
++		sg->page = p;
++		sg->length = ret_sz;
++
++		SCSI_LOG_TIMEOUT(5, printk("sg_build_build: k=%d, a=0x%p, len=%d\n",
++				  k, p, ret_sz));
++	}		/* end of for loop */
++
++	schp->k_use_sg = k;
++	SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k_use_sg=%d, rem_sz=%d\n", k, rem_sz));
++
++	schp->bufflen = blk_size;
++	if (rem_sz > 0)	/* must have failed */
++		return -ENOMEM;
++
+ 	return 0;
+ }
+ 
+@@ -2005,6 +1899,7 @@ sg_write_xfer(Sg_request * srp)
+ {
+ 	sg_io_hdr_t *hp = &srp->header;
+ 	Sg_scatter_hold *schp = &srp->data;
++	struct scatterlist *sg = schp->buffer;
+ 	int num_xfer = 0;
+ 	int j, k, onum, usglen, ksglen, res;
+ 	int iovec_count = (int) hp->iovec_count;
+@@ -2033,63 +1928,45 @@ sg_write_xfer(Sg_request * srp)
+ 	} else
+ 		onum = 1;
+ 
+-	if (0 == schp->k_use_sg) {	/* kernel has single buffer */
+-		for (j = 0, p = schp->buffer; j < onum; ++j) {
+-			res = sg_u_iovec(hp, iovec_count, j, 1, &usglen, &up);
+-			if (res)
+-				return res;
+-			usglen = (num_xfer > usglen) ? usglen : num_xfer;
+-			if (__copy_from_user(p, up, usglen))
+-				return -EFAULT;
+-			p += usglen;
+-			num_xfer -= usglen;
+-			if (num_xfer <= 0)
+-				return 0;
+-		}
+-	} else {		/* kernel using scatter gather list */
+-		struct scatterlist *sclp = (struct scatterlist *) schp->buffer;
+-
+-		ksglen = (int) sclp->length;
+-		p = sg_scatg2virt(sclp);
+-		for (j = 0, k = 0; j < onum; ++j) {
+-			res = sg_u_iovec(hp, iovec_count, j, 1, &usglen, &up);
+-			if (res)
+-				return res;
+-
+-			for (; p; ++sclp, ksglen = (int) sclp->length,
+-				  p = sg_scatg2virt(sclp)) {
+-				if (usglen <= 0)
+-					break;
+-				if (ksglen > usglen) {
+-					if (usglen >= num_xfer) {
+-						if (__copy_from_user
+-						    (p, up, num_xfer))
+-							return -EFAULT;
+-						return 0;
+-					}
+-					if (__copy_from_user(p, up, usglen))
+-						return -EFAULT;
+-					p += usglen;
+-					ksglen -= usglen;
+-					break;
+-				} else {
+-					if (ksglen >= num_xfer) {
+-						if (__copy_from_user
+-						    (p, up, num_xfer))
+-							return -EFAULT;
+-						return 0;
+-					}
+-					if (__copy_from_user(p, up, ksglen))
++	ksglen = sg->length;
++	p = page_address(sg->page);
++	for (j = 0, k = 0; j < onum; ++j) {
++		res = sg_u_iovec(hp, iovec_count, j, 1, &usglen, &up);
++		if (res)
++			return res;
++
++		for (; p; ++sg, ksglen = sg->length,
++		     p = page_address(sg->page)) {
++			if (usglen <= 0)
++				break;
++			if (ksglen > usglen) {
++				if (usglen >= num_xfer) {
++					if (__copy_from_user(p, up, num_xfer))
+ 						return -EFAULT;
+-					up += ksglen;
+-					usglen -= ksglen;
++					return 0;
+ 				}
+-				++k;
+-				if (k >= schp->k_use_sg)
++				if (__copy_from_user(p, up, usglen))
++					return -EFAULT;
++				p += usglen;
++				ksglen -= usglen;
++				break;
++			} else {
++				if (ksglen >= num_xfer) {
++					if (__copy_from_user(p, up, num_xfer))
++						return -EFAULT;
+ 					return 0;
++				}
++				if (__copy_from_user(p, up, ksglen))
++					return -EFAULT;
++				up += ksglen;
++				usglen -= ksglen;
+ 			}
++			++k;
++			if (k >= schp->k_use_sg)
++				return 0;
+ 		}
+ 	}
++
+ 	return 0;
+ }
+ 
+@@ -2127,29 +2004,25 @@ sg_remove_scat(Sg_scatter_hold * schp)
+ {
+ 	SCSI_LOG_TIMEOUT(4, printk("sg_remove_scat: k_use_sg=%d\n", schp->k_use_sg));
+ 	if (schp->buffer && (schp->sglist_len > 0)) {
+-		struct scatterlist *sclp = (struct scatterlist *) schp->buffer;
++		struct scatterlist *sg = schp->buffer;
+ 
+ 		if (schp->dio_in_use) {
+ #ifdef SG_ALLOW_DIO_CODE
+-			st_unmap_user_pages(sclp, schp->k_use_sg, TRUE);
++			st_unmap_user_pages(sg, schp->k_use_sg, TRUE);
+ #endif
+ 		} else {
+ 			int k;
+ 
+-			for (k = 0; (k < schp->k_use_sg) && sg_scatg2virt(sclp);
+-			     ++k, ++sclp) {
++			for (k = 0; (k < schp->k_use_sg) && sg->page;
++			     ++k, ++sg) {
+ 				SCSI_LOG_TIMEOUT(5, printk(
+ 				    "sg_remove_scat: k=%d, a=0x%p, len=%d\n",
+-				    k, sg_scatg2virt(sclp), sclp->length));
+-				sg_page_free(sg_scatg2virt(sclp), sclp->length);
+-				sclp->page = NULL;
+-				sclp->offset = 0;
+-				sclp->length = 0;
++				    k, sg->page, sg->length));
++				sg_page_free(sg->page, sg->length);
+ 			}
+ 		}
+-		sg_page_free(schp->buffer, schp->sglist_len);
+-	} else if (schp->buffer)
+-		sg_page_free(schp->buffer, schp->b_malloc_len);
++		kfree(schp->buffer);
++	}
+ 	memset(schp, 0, sizeof (*schp));
+ }
+ 
+@@ -2158,6 +2031,7 @@ sg_read_xfer(Sg_request * srp)
+ {
+ 	sg_io_hdr_t *hp = &srp->header;
+ 	Sg_scatter_hold *schp = &srp->data;
++	struct scatterlist *sg = schp->buffer;
+ 	int num_xfer = 0;
+ 	int j, k, onum, usglen, ksglen, res;
+ 	int iovec_count = (int) hp->iovec_count;
+@@ -2186,63 +2060,45 @@ sg_read_xfer(Sg_request * srp)
+ 	} else
+ 		onum = 1;
+ 
+-	if (0 == schp->k_use_sg) {	/* kernel has single buffer */
+-		for (j = 0, p = schp->buffer; j < onum; ++j) {
+-			res = sg_u_iovec(hp, iovec_count, j, 0, &usglen, &up);
+-			if (res)
+-				return res;
+-			usglen = (num_xfer > usglen) ? usglen : num_xfer;
+-			if (__copy_to_user(up, p, usglen))
+-				return -EFAULT;
+-			p += usglen;
+-			num_xfer -= usglen;
+-			if (num_xfer <= 0)
+-				return 0;
+-		}
+-	} else {		/* kernel using scatter gather list */
+-		struct scatterlist *sclp = (struct scatterlist *) schp->buffer;
+-
+-		ksglen = (int) sclp->length;
+-		p = sg_scatg2virt(sclp);
+-		for (j = 0, k = 0; j < onum; ++j) {
+-			res = sg_u_iovec(hp, iovec_count, j, 0, &usglen, &up);
+-			if (res)
+-				return res;
+-
+-			for (; p; ++sclp, ksglen = (int) sclp->length,
+-				  p = sg_scatg2virt(sclp)) {
+-				if (usglen <= 0)
+-					break;
+-				if (ksglen > usglen) {
+-					if (usglen >= num_xfer) {
+-						if (__copy_to_user
+-						    (up, p, num_xfer))
+-							return -EFAULT;
+-						return 0;
+-					}
+-					if (__copy_to_user(up, p, usglen))
+-						return -EFAULT;
+-					p += usglen;
+-					ksglen -= usglen;
+-					break;
+-				} else {
+-					if (ksglen >= num_xfer) {
+-						if (__copy_to_user
+-						    (up, p, num_xfer))
+-							return -EFAULT;
+-						return 0;
+-					}
+-					if (__copy_to_user(up, p, ksglen))
++	p = page_address(sg->page);
++	ksglen = sg->length;
++	for (j = 0, k = 0; j < onum; ++j) {
++		res = sg_u_iovec(hp, iovec_count, j, 0, &usglen, &up);
++		if (res)
++			return res;
++
++		for (; p; ++sg, ksglen = sg->length,
++		     p = page_address(sg->page)) {
++			if (usglen <= 0)
++				break;
++			if (ksglen > usglen) {
++				if (usglen >= num_xfer) {
++					if (__copy_to_user(up, p, num_xfer))
+ 						return -EFAULT;
+-					up += ksglen;
+-					usglen -= ksglen;
++					return 0;
+ 				}
+-				++k;
+-				if (k >= schp->k_use_sg)
++				if (__copy_to_user(up, p, usglen))
++					return -EFAULT;
++				p += usglen;
++				ksglen -= usglen;
++				break;
++			} else {
++				if (ksglen >= num_xfer) {
++					if (__copy_to_user(up, p, num_xfer))
++						return -EFAULT;
+ 					return 0;
++				}
++				if (__copy_to_user(up, p, ksglen))
++					return -EFAULT;
++				up += ksglen;
++				usglen -= ksglen;
+ 			}
++			++k;
++			if (k >= schp->k_use_sg)
++				return 0;
+ 		}
+ 	}
++
+ 	return 0;
+ }
+ 
+@@ -2250,37 +2106,32 @@ static int
+ sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer)
+ {
+ 	Sg_scatter_hold *schp = &srp->data;
++	struct scatterlist *sg = schp->buffer;
++	int k, num;
+ 
+ 	SCSI_LOG_TIMEOUT(4, printk("sg_read_oxfer: num_read_xfer=%d\n",
+ 				   num_read_xfer));
+ 	if ((!outp) || (num_read_xfer <= 0))
+ 		return 0;
+-	if (schp->k_use_sg > 0) {
+-		int k, num;
+-		struct scatterlist *sclp = (struct scatterlist *) schp->buffer;
+-
+-		for (k = 0; (k < schp->k_use_sg) && sg_scatg2virt(sclp);
+-		     ++k, ++sclp) {
+-			num = (int) sclp->length;
+-			if (num > num_read_xfer) {
+-				if (__copy_to_user
+-				    (outp, sg_scatg2virt(sclp), num_read_xfer))
+-					return -EFAULT;
++
++	for (k = 0; (k < schp->k_use_sg) && sg->page; ++k, ++sg) {
++		num = sg->length;
++		if (num > num_read_xfer) {
++			if (__copy_to_user(outp, page_address(sg->page),
++					   num_read_xfer))
++				return -EFAULT;
++			break;
++		} else {
++			if (__copy_to_user(outp, page_address(sg->page),
++					   num))
++				return -EFAULT;
++			num_read_xfer -= num;
++			if (num_read_xfer <= 0)
+ 				break;
+-			} else {
+-				if (__copy_to_user
+-				    (outp, sg_scatg2virt(sclp), num))
+-					return -EFAULT;
+-				num_read_xfer -= num;
+-				if (num_read_xfer <= 0)
+-					break;
+-				outp += num;
+-			}
++			outp += num;
+ 		}
+-	} else {
+-		if (__copy_to_user(outp, schp->buffer, num_read_xfer))
+-			return -EFAULT;
+ 	}
++
+ 	return 0;
+ }
+ 
+@@ -2306,44 +2157,31 @@ sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size)
+ {
+ 	Sg_scatter_hold *req_schp = &srp->data;
+ 	Sg_scatter_hold *rsv_schp = &sfp->reserve;
++	struct scatterlist *sg = rsv_schp->buffer;
++	int k, num, rem;
+ 
+ 	srp->res_used = 1;
+ 	SCSI_LOG_TIMEOUT(4, printk("sg_link_reserve: size=%d\n", size));
+-	size = (size + 1) & (~1);	/* round to even for aha1542 */
+-	if (rsv_schp->k_use_sg > 0) {
+-		int k, num;
+-		int rem = size;
+-		struct scatterlist *sclp =
+-		    (struct scatterlist *) rsv_schp->buffer;
+-
+-		for (k = 0; k < rsv_schp->k_use_sg; ++k, ++sclp) {
+-			num = (int) sclp->length;
+-			if (rem <= num) {
+-				if (0 == k) {
+-					req_schp->k_use_sg = 0;
+-					req_schp->buffer = sg_scatg2virt(sclp);
+-				} else {
+-					sfp->save_scat_len = num;
+-					sclp->length = (unsigned) rem;
+-					req_schp->k_use_sg = k + 1;
+-					req_schp->sglist_len =
+-					    rsv_schp->sglist_len;
+-					req_schp->buffer = rsv_schp->buffer;
+-				}
+-				req_schp->bufflen = size;
+-				req_schp->b_malloc_len = rsv_schp->b_malloc_len;
+-				break;
+-			} else
+-				rem -= num;
+-		}
+-		if (k >= rsv_schp->k_use_sg)
+-			SCSI_LOG_TIMEOUT(1, printk("sg_link_reserve: BAD size\n"));
+-	} else {
+-		req_schp->k_use_sg = 0;
+-		req_schp->bufflen = size;
+-		req_schp->buffer = rsv_schp->buffer;
+-		req_schp->b_malloc_len = rsv_schp->b_malloc_len;
++	rem = size = (size + 1) & (~1);	/* round to even for aha1542 */
++
++	for (k = 0; k < rsv_schp->k_use_sg; ++k, ++sg) {
++		num = sg->length;
++		if (rem <= num) {
++			sfp->save_scat_len = num;
++			sg->length = rem;
++			req_schp->k_use_sg = k + 1;
++			req_schp->sglist_len = rsv_schp->sglist_len;
++			req_schp->buffer = rsv_schp->buffer;
++
++			req_schp->bufflen = size;
++			req_schp->b_malloc_len = rsv_schp->b_malloc_len;
++			break;
++		} else
++			rem -= num;
+ 	}
++
++	if (k >= rsv_schp->k_use_sg)
++		SCSI_LOG_TIMEOUT(1, printk("sg_link_reserve: BAD size\n"));
+ }
+ 
+ static void
+@@ -2355,11 +2193,10 @@ sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp)
+ 	SCSI_LOG_TIMEOUT(4, printk("sg_unlink_reserve: req->k_use_sg=%d\n",
+ 				   (int) req_schp->k_use_sg));
+ 	if ((rsv_schp->k_use_sg > 0) && (req_schp->k_use_sg > 0)) {
+-		struct scatterlist *sclp =
+-		    (struct scatterlist *) rsv_schp->buffer;
++		struct scatterlist *sg = rsv_schp->buffer;
+ 
+ 		if (sfp->save_scat_len > 0)
+-			(sclp + (req_schp->k_use_sg - 1))->length =
++			(sg + (req_schp->k_use_sg - 1))->length =
+ 			    (unsigned) sfp->save_scat_len;
+ 		else
+ 			SCSI_LOG_TIMEOUT(1, printk ("sg_unlink_reserve: BAD save_scat_len\n"));
+@@ -2445,7 +2282,6 @@ sg_add_request(Sg_fd * sfp)
+ 	if (resp) {
+ 		resp->nextrp = NULL;
+ 		resp->header.duration = jiffies_to_msecs(jiffies);
+-		resp->my_cmdp = NULL;
+ 	}
+ 	write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
+ 	return resp;
+@@ -2463,8 +2299,6 @@ sg_remove_request(Sg_fd * sfp, Sg_request * srp)
+ 	if ((!sfp) || (!srp) || (!sfp->headrp))
+ 		return res;
+ 	write_lock_irqsave(&sfp->rq_list_lock, iflags);
+-	if (srp->my_cmdp)
+-		srp->my_cmdp->upper_private_data = NULL;
+ 	prev_rp = sfp->headrp;
+ 	if (srp == prev_rp) {
+ 		sfp->headrp = prev_rp->nextrp;
+@@ -2507,10 +2341,10 @@ sg_add_sfp(Sg_device * sdp, int dev)
+ 	Sg_fd *sfp;
+ 	unsigned long iflags;
+ 
+-	sfp = (Sg_fd *) sg_page_malloc(sizeof (Sg_fd), 0, NULL);
++	sfp = kzalloc(sizeof(*sfp), GFP_ATOMIC | __GFP_NOWARN);
+ 	if (!sfp)
+ 		return NULL;
+-	memset(sfp, 0, sizeof (Sg_fd));
++
+ 	init_waitqueue_head(&sfp->read_wait);
+ 	rwlock_init(&sfp->rq_list_lock);
+ 
+@@ -2567,7 +2401,7 @@ __sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp)
+ 	}
+ 	sfp->parentdp = NULL;
+ 	SCSI_LOG_TIMEOUT(6, printk("__sg_remove_sfp:    sfp=0x%p\n", sfp));
+-	sg_page_free((char *) sfp, sizeof (Sg_fd));
++	kfree(sfp);
+ }
+ 
+ /* Returns 0 in normal case, 1 when detached and sdp object removed */
+@@ -2632,10 +2466,10 @@ sg_res_in_use(Sg_fd * sfp)
+ }
+ 
+ /* If retSzp==NULL want exact size or fail */
+-static char *
++static struct page *
+ sg_page_malloc(int rqSz, int lowDma, int *retSzp)
+ {
+-	char *resp = NULL;
++	struct page *resp = NULL;
+ 	gfp_t page_mask;
+ 	int order, a_size;
+ 	int resSz = rqSz;
+@@ -2650,11 +2484,11 @@ sg_page_malloc(int rqSz, int lowDma, int *retSzp)
+ 
+ 	for (order = 0, a_size = PAGE_SIZE; a_size < rqSz;
+ 	     order++, a_size <<= 1) ;
+-	resp = (char *) __get_free_pages(page_mask, order);
++	resp = alloc_pages(page_mask, order);
+ 	while ((!resp) && order && retSzp) {
+ 		--order;
+ 		a_size >>= 1;	/* divide by 2, until PAGE_SIZE */
+-		resp = (char *) __get_free_pages(page_mask, order);	/* try half */
++		resp =  alloc_pages(page_mask, order);	/* try half */
+ 		resSz = a_size;
+ 	}
+ 	if (resp) {
+@@ -2667,15 +2501,15 @@ sg_page_malloc(int rqSz, int lowDma, int *retSzp)
+ }
+ 
+ static void
+-sg_page_free(char *buff, int size)
++sg_page_free(struct page *page, int size)
+ {
+ 	int order, a_size;
+ 
+-	if (!buff)
++	if (!page)
+ 		return;
+ 	for (order = 0, a_size = PAGE_SIZE; a_size < size;
+ 	     order++, a_size <<= 1) ;
+-	free_pages((unsigned long) buff, order);
++	__free_pages(page, order);
+ }
+ 
+ #ifndef MAINTENANCE_IN_CMD
+@@ -3067,13 +2901,11 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
+ 					cp = "     ";
+ 			}
+ 			seq_printf(s, cp);
+-			blen = srp->my_cmdp ? 
+-				srp->my_cmdp->sr_bufflen : srp->data.bufflen;
+-			usg = srp->my_cmdp ? 
+-				srp->my_cmdp->sr_use_sg : srp->data.k_use_sg;
++			blen = srp->data.bufflen;
++			usg = srp->data.k_use_sg;
+ 			seq_printf(s, srp->done ? 
+ 				   ((1 == srp->done) ?  "rcv:" : "fin:")
+-				   : (srp->my_cmdp ? "act:" : "prior:"));
++				   : "act:");
+ 			seq_printf(s, " id=%d blen=%d",
+ 				   srp->header.pack_id, blen);
+ 			if (srp->done)

commit aa7b5cd750c766f66a92c9f78ba176bc77512b7e
+Author: Mike Christie 
+Date:   Fri Nov 11 05:31:41 2005 -0600
+
+    [SCSI] add kmemcache for scsi_io_context
+    
+    Add kmemcache of scsi io contexts.
+    
+    In the future when we finalize on where these functions will live
+    we can add a mempool for it and do a bioset for out REQ_BLOCK_PC
+    bios. This is needed becuase the dm-multipath handlers will
+    want to use the scsi_exectute* functions for failover and we cannot
+    have them and the bio device allocating from the same mempool.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index 3e136bfe4219..54a72f197487 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -306,6 +306,8 @@ struct scsi_io_context {
+ 	char sense[SCSI_SENSE_BUFFERSIZE];
+ };
+ 
++static kmem_cache_t *scsi_io_context_cache;
++
+ static void scsi_end_async(struct request *req)
+ {
+ 	struct scsi_io_context *sioc = req->end_io_data;
+@@ -313,7 +315,7 @@ static void scsi_end_async(struct request *req)
+ 	if (sioc->done)
+ 		sioc->done(sioc->data, sioc->sense, req->errors, req->data_len);
+ 
+-	kfree(sioc);
++	kmem_cache_free(scsi_io_context_cache, sioc);
+ 	__blk_put_request(req->q, req);
+ }
+ 
+@@ -452,9 +454,10 @@ int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd,
+ 	int err = 0;
+ 	int write = (data_direction == DMA_TO_DEVICE);
+ 
+-	sioc = kzalloc(sizeof(*sioc), gfp);
++	sioc = kmem_cache_alloc(scsi_io_context_cache, gfp);
+ 	if (!sioc)
+ 		return DRIVER_ERROR << 24;
++	memset(sioc, 0, sizeof(*sioc));
+ 
+ 	req = blk_get_request(sdev->request_queue, write, gfp);
+ 	if (!req)
+@@ -1765,6 +1768,14 @@ int __init scsi_init_queue(void)
+ {
+ 	int i;
+ 
++	scsi_io_context_cache = kmem_cache_create("scsi_io_context",
++					sizeof(struct scsi_io_context),
++					0, 0, NULL, NULL);
++	if (!scsi_io_context_cache) {
++		printk(KERN_ERR "SCSI: can't init scsi io context cache\n");
++		return -ENOMEM;
++	}
++
+ 	for (i = 0; i < SG_MEMPOOL_NR; i++) {
+ 		struct scsi_host_sg_pool *sgp = scsi_sg_pools + i;
+ 		int size = sgp->size * sizeof(struct scatterlist);
+@@ -1792,6 +1803,8 @@ void scsi_exit_queue(void)
+ {
+ 	int i;
+ 
++	kmem_cache_destroy(scsi_io_context_cache);
++
+ 	for (i = 0; i < SG_MEMPOOL_NR; i++) {
+ 		struct scsi_host_sg_pool *sgp = scsi_sg_pools + i;
+ 		mempool_destroy(sgp->pool);

commit 0d95716d6a1308c465d8c17ed1a217628936bb0c
+Author: Mike Christie 
+Date:   Fri Nov 11 05:31:40 2005 -0600
+
+    [SCSI] complete the whole command when it is REQ_BLOCK_PC
+    
+    sd does not allow scsi_io_completion to retry commands for
+    SG_IO requests, and it make sense that it should not happen for st
+    SG_IO commands too. If for st we hit the bottom of scsi_io_completion
+    we will probably screw things up pretty bad. This patch returns to the
+    block layer that the whole command completed and relies on the caller to check
+    the request errors field. For initialization commands like in sd, this adds
+    the previous behavior where scsi_io_completion did not process the error.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index 365843a1561f..3e136bfe4219 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -1247,7 +1247,13 @@ static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
+ static void scsi_generic_done(struct scsi_cmnd *cmd)
+ {
+ 	BUG_ON(!blk_pc_request(cmd->request));
+-	scsi_io_completion(cmd, cmd->result == 0 ? cmd->bufflen : 0, 0);
++	/*
++	 * This will complete the whole command with uptodate=1 so
++	 * as far as the block layer is concerned the command completed
++	 * successfully. Since this is a REQ_BLOCK_PC command the
++	 * caller should check the request's errors value
++	 */
++	scsi_io_completion(cmd, cmd->bufflen, 0);
+ }
+ 
+ static int scsi_prep_fn(struct request_queue *q, struct request *req)
+diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
+index 6d9078705c5b..053444b027d4 100644
+--- a/drivers/scsi/st.c
++++ b/drivers/scsi/st.c
+@@ -4185,7 +4185,11 @@ static void scsi_tape_release(struct kref *kref)
+ 
+ static void st_intr(struct scsi_cmnd *SCpnt)
+ {
+-	scsi_io_completion(SCpnt, (SCpnt->result ? 0: SCpnt->bufflen), 1);
++	/*
++	 * The caller should be checking the request's errors
++	 * value.
++	 */
++	scsi_io_completion(SCpnt, SCpnt->bufflen, 0);
+ }
+ 
+ /*

commit 17e01f216b611fc46956dcd9063aec4de75991e3
+Author: Mike Christie 
+Date:   Fri Nov 11 05:31:37 2005 -0600
+
+    [SCSI] add retries field to request for REQ_BLOCK_PC use
+    
+    For tape we need to control the retries. This patch adds a retries
+    counter on the request for REQ_BLOCK_PC commands originating from
+    scsi_execute* to use. REQ_BLOCK_PC commands comming from the block
+    layer SG_IO path continue to use the retires set in the ULD init_command.
+    (scsi_execute* does not set the gendisk so we do not execute
+    the init_command in that path).
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index eb0cfbfbcf8f..365843a1561f 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -259,6 +259,7 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
+ 	memcpy(req->cmd, cmd, req->cmd_len);
+ 	req->sense = sense;
+ 	req->sense_len = 0;
++	req->retries = retries;
+ 	req->timeout = timeout;
+ 	req->flags |= flags | REQ_BLOCK_PC | REQ_SPECIAL | REQ_QUIET;
+ 
+@@ -472,6 +473,7 @@ int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd,
+ 	req->sense = sioc->sense;
+ 	req->sense_len = 0;
+ 	req->timeout = timeout;
++	req->retries = retries;
+ 	req->flags |= REQ_BLOCK_PC | REQ_QUIET;
+ 	req->end_io_data = sioc;
+ 
+@@ -1393,7 +1395,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
+ 				cmd->sc_data_direction = DMA_NONE;
+ 			
+ 			cmd->transfersize = req->data_len;
+-			cmd->allowed = 3;
++			cmd->allowed = req->retries;
+ 			cmd->timeout_per_command = req->timeout;
+ 			cmd->done = scsi_generic_done;
+ 		}
+diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
+index 9a68716dcf75..509e9a03a328 100644
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -184,6 +184,7 @@ struct request {
+ 	void *sense;
+ 
+ 	unsigned int timeout;
++	int retries;
+ 
+ 	/*
+ 	 * For Power Management requests

commit 6e68af666f5336254b5715dca591026b7324499a
+Author: Mike Christie 
+Date:   Fri Nov 11 05:30:27 2005 -0600
+
+    [SCSI] Convert SCSI mid-layer to scsi_execute_async
+    
+    Add scsi helpers to create really-large-requests and convert
+    scsi-ml to scsi_execute_async().
+    
+    Per Jens's previous comments, I placed this function in scsi_lib.c.
+    I made it follow all the queue's limits - I think I did at least :), so
+    I removed the warning on the function header.
+    
+    I think the scsi_execute_* functions should eventually take a request_queue
+    and be placed some place where the dm-multipath hw_handler can use them
+    if that failover code is going to stay in the kernel. That conversion
+    patch will be sent in another mail though.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
+index 18c5d2523014..53ea62d3b53d 100644
+--- a/drivers/scsi/scsi_error.c
++++ b/drivers/scsi/scsi_error.c
+@@ -1314,23 +1314,6 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
+ 	}
+ }
+ 
+-/**
+- * scsi_eh_lock_done - done function for eh door lock request
+- * @scmd:	SCSI command block for the door lock request
+- *
+- * Notes:
+- * 	We completed the asynchronous door lock request, and it has either
+- * 	locked the door or failed.  We must free the command structures
+- * 	associated with this request.
+- **/
+-static void scsi_eh_lock_done(struct scsi_cmnd *scmd)
+-{
+-	struct scsi_request *sreq = scmd->sc_request;
+-
+-	scsi_release_request(sreq);
+-}
+-
+-
+ /**
+  * scsi_eh_lock_door - Prevent medium removal for the specified device
+  * @sdev:	SCSI device to prevent medium removal
+@@ -1353,29 +1336,17 @@ static void scsi_eh_lock_done(struct scsi_cmnd *scmd)
+  **/
+ static void scsi_eh_lock_door(struct scsi_device *sdev)
+ {
+-	struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL);
++	unsigned char cmnd[MAX_COMMAND_SIZE];
+ 
+-	if (unlikely(!sreq)) {
+-		printk(KERN_ERR "%s: request allocate failed,"
+-		       "prevent media removal cmd not sent\n", __FUNCTION__);
+-		return;
+-	}
++	cmnd[0] = ALLOW_MEDIUM_REMOVAL;
++	cmnd[1] = 0;
++	cmnd[2] = 0;
++	cmnd[3] = 0;
++	cmnd[4] = SCSI_REMOVAL_PREVENT;
++	cmnd[5] = 0;
+ 
+-	sreq->sr_cmnd[0] = ALLOW_MEDIUM_REMOVAL;
+-	sreq->sr_cmnd[1] = 0;
+-	sreq->sr_cmnd[2] = 0;
+-	sreq->sr_cmnd[3] = 0;
+-	sreq->sr_cmnd[4] = SCSI_REMOVAL_PREVENT;
+-	sreq->sr_cmnd[5] = 0;
+-	sreq->sr_data_direction = DMA_NONE;
+-	sreq->sr_bufflen = 0;
+-	sreq->sr_buffer = NULL;
+-	sreq->sr_allowed = 5;
+-	sreq->sr_done = scsi_eh_lock_done;
+-	sreq->sr_timeout_per_command = 10 * HZ;
+-	sreq->sr_cmd_len = COMMAND_SIZE(sreq->sr_cmnd[0]);
+-
+-	scsi_insert_special_req(sreq, 1);
++	scsi_execute_async(sdev, cmnd, DMA_NONE, NULL, 0, 0, 10 * HZ,
++			   5, NULL, NULL, GFP_KERNEL);
+ }
+ 
+ 
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index 1f2782767ca9..eb0cfbfbcf8f 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -63,39 +63,6 @@ static struct scsi_host_sg_pool scsi_sg_pools[] = {
+ }; 	
+ #undef SP
+ 
+-
+-/*
+- * Function:    scsi_insert_special_req()
+- *
+- * Purpose:     Insert pre-formed request into request queue.
+- *
+- * Arguments:   sreq	- request that is ready to be queued.
+- *              at_head	- boolean.  True if we should insert at head
+- *                        of queue, false if we should insert at tail.
+- *
+- * Lock status: Assumed that lock is not held upon entry.
+- *
+- * Returns:     Nothing
+- *
+- * Notes:       This function is called from character device and from
+- *              ioctl types of functions where the caller knows exactly
+- *              what SCSI command needs to be issued.   The idea is that
+- *              we merely inject the command into the queue (at the head
+- *              for now), and then call the queue request function to actually
+- *              process it.
+- */
+-int scsi_insert_special_req(struct scsi_request *sreq, int at_head)
+-{
+-	/*
+-	 * Because users of this function are apt to reuse requests with no
+-	 * modification, we have to sanitise the request flags here
+-	 */
+-	sreq->sr_request->flags &= ~REQ_DONTPREP;
+-	blk_insert_request(sreq->sr_device->request_queue, sreq->sr_request,
+-		       	   at_head, sreq);
+-	return 0;
+-}
+-
+ static void scsi_run_queue(struct request_queue *q);
+ 
+ /*
+@@ -249,8 +216,13 @@ void scsi_do_req(struct scsi_request *sreq, const void *cmnd,
+ 
+ 	/*
+ 	 * head injection *required* here otherwise quiesce won't work
++	 *
++	 * Because users of this function are apt to reuse requests with no
++	 * modification, we have to sanitise the request flags here
+ 	 */
+-	scsi_insert_special_req(sreq, 1);
++	sreq->sr_request->flags &= ~REQ_DONTPREP;
++	blk_insert_request(sreq->sr_device->request_queue, sreq->sr_request,
++		       	   1, sreq);
+ }
+ EXPORT_SYMBOL(scsi_do_req);
+ 
+@@ -327,6 +299,196 @@ int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
+ }
+ EXPORT_SYMBOL(scsi_execute_req);
+ 
++struct scsi_io_context {
++	void *data;
++	void (*done)(void *data, char *sense, int result, int resid);
++	char sense[SCSI_SENSE_BUFFERSIZE];
++};
++
++static void scsi_end_async(struct request *req)
++{
++	struct scsi_io_context *sioc = req->end_io_data;
++
++	if (sioc->done)
++		sioc->done(sioc->data, sioc->sense, req->errors, req->data_len);
++
++	kfree(sioc);
++	__blk_put_request(req->q, req);
++}
++
++static int scsi_merge_bio(struct request *rq, struct bio *bio)
++{
++	struct request_queue *q = rq->q;
++
++	bio->bi_flags &= ~(1 << BIO_SEG_VALID);
++	if (rq_data_dir(rq) == WRITE)
++		bio->bi_rw |= (1 << BIO_RW);
++	blk_queue_bounce(q, &bio);
++
++	if (!rq->bio)
++		blk_rq_bio_prep(q, rq, bio);
++	else if (!q->back_merge_fn(q, rq, bio))
++		return -EINVAL;
++	else {
++		rq->biotail->bi_next = bio;
++		rq->biotail = bio;
++		rq->hard_nr_sectors += bio_sectors(bio);
++		rq->nr_sectors = rq->hard_nr_sectors;
++	}
++
++	return 0;
++}
++
++static int scsi_bi_endio(struct bio *bio, unsigned int bytes_done, int error)
++{
++	if (bio->bi_size)
++		return 1;
++
++	bio_put(bio);
++	return 0;
++}
++
++/**
++ * scsi_req_map_sg - map a scatterlist into a request
++ * @rq:		request to fill
++ * @sg:		scatterlist
++ * @nsegs:	number of elements
++ * @bufflen:	len of buffer
++ * @gfp:	memory allocation flags
++ *
++ * scsi_req_map_sg maps a scatterlist into a request so that the
++ * request can be sent to the block layer. We do not trust the scatterlist
++ * sent to use, as some ULDs use that struct to only organize the pages.
++ */
++static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl,
++			   int nsegs, unsigned bufflen, gfp_t gfp)
++{
++	struct request_queue *q = rq->q;
++	int nr_pages = (bufflen + PAGE_SIZE - 1) >> PAGE_SHIFT;
++	unsigned int data_len = 0, len, bytes, off;
++	struct page *page;
++	struct bio *bio = NULL;
++	int i, err, nr_vecs = 0;
++
++	for (i = 0; i < nsegs; i++) {
++		page = sgl[i].page;
++		off = sgl[i].offset;
++		len = sgl[i].length;
++		data_len += len;
++
++		while (len > 0) {
++			bytes = min_t(unsigned int, len, PAGE_SIZE - off);
++
++			if (!bio) {
++				nr_vecs = min_t(int, BIO_MAX_PAGES, nr_pages);
++				nr_pages -= nr_vecs;
++
++				bio = bio_alloc(gfp, nr_vecs);
++				if (!bio) {
++					err = -ENOMEM;
++					goto free_bios;
++				}
++				bio->bi_end_io = scsi_bi_endio;
++			}
++
++			if (bio_add_pc_page(q, bio, page, bytes, off) !=
++			    bytes) {
++				bio_put(bio);
++				err = -EINVAL;
++				goto free_bios;
++			}
++
++			if (bio->bi_vcnt >= nr_vecs) {
++				err = scsi_merge_bio(rq, bio);
++				if (err) {
++					bio_endio(bio, bio->bi_size, 0);
++					goto free_bios;
++				}
++				bio = NULL;
++			}
++
++			page++;
++			len -= bytes;
++			off = 0;
++		}
++	}
++
++	rq->buffer = rq->data = NULL;
++	rq->data_len = data_len;
++	return 0;
++
++free_bios:
++	while ((bio = rq->bio) != NULL) {
++		rq->bio = bio->bi_next;
++		/*
++		 * call endio instead of bio_put incase it was bounced
++		 */
++		bio_endio(bio, bio->bi_size, 0);
++	}
++
++	return err;
++}
++
++/**
++ * scsi_execute_async - insert request
++ * @sdev:	scsi device
++ * @cmd:	scsi command
++ * @data_direction: data direction
++ * @buffer:	data buffer (this can be a kernel buffer or scatterlist)
++ * @bufflen:	len of buffer
++ * @use_sg:	if buffer is a scatterlist this is the number of elements
++ * @timeout:	request timeout in seconds
++ * @retries:	number of times to retry request
++ * @flags:	or into request flags
++ **/
++int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd,
++		       int data_direction, void *buffer, unsigned bufflen,
++		       int use_sg, int timeout, int retries, void *privdata,
++		       void (*done)(void *, char *, int, int), gfp_t gfp)
++{
++	struct request *req;
++	struct scsi_io_context *sioc;
++	int err = 0;
++	int write = (data_direction == DMA_TO_DEVICE);
++
++	sioc = kzalloc(sizeof(*sioc), gfp);
++	if (!sioc)
++		return DRIVER_ERROR << 24;
++
++	req = blk_get_request(sdev->request_queue, write, gfp);
++	if (!req)
++		goto free_sense;
++
++	if (use_sg)
++		err = scsi_req_map_sg(req, buffer, use_sg, bufflen, gfp);
++	else if (bufflen)
++		err = blk_rq_map_kern(req->q, req, buffer, bufflen, gfp);
++
++	if (err)
++		goto free_req;
++
++	req->cmd_len = COMMAND_SIZE(cmd[0]);
++	memcpy(req->cmd, cmd, req->cmd_len);
++	req->sense = sioc->sense;
++	req->sense_len = 0;
++	req->timeout = timeout;
++	req->flags |= REQ_BLOCK_PC | REQ_QUIET;
++	req->end_io_data = sioc;
++
++	sioc->data = privdata;
++	sioc->done = done;
++
++	blk_execute_rq_nowait(req->q, NULL, req, 1, scsi_end_async);
++	return 0;
++
++free_req:
++	blk_put_request(req);
++free_sense:
++	kfree(sioc);
++	return DRIVER_ERROR << 24;
++}
++EXPORT_SYMBOL_GPL(scsi_execute_async);
++
+ /*
+  * Function:    scsi_init_cmd_errh()
+  *
+diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
+index a8d121c8fbcd..f04e7e11f57a 100644
+--- a/drivers/scsi/scsi_priv.h
++++ b/drivers/scsi/scsi_priv.h
+@@ -40,7 +40,6 @@ extern void scsi_exit_hosts(void);
+ extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd);
+ extern int scsi_setup_command_freelist(struct Scsi_Host *shost);
+ extern void scsi_destroy_command_freelist(struct Scsi_Host *shost);
+-extern int scsi_insert_special_req(struct scsi_request *sreq, int);
+ extern void scsi_init_cmd_from_req(struct scsi_cmnd *cmd,
+ 		struct scsi_request *sreq);
+ extern void __scsi_release_request(struct scsi_request *sreq);
+diff --git a/fs/bio.c b/fs/bio.c
+index 460554b07ff9..4d21ee3873ec 100644
+--- a/fs/bio.c
++++ b/fs/bio.c
+@@ -385,6 +385,25 @@ static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page
+ 	return len;
+ }
+ 
++/**
++ *	bio_add_pc_page	-	attempt to add page to bio
++ *	@bio: destination bio
++ *	@page: page to add
++ *	@len: vec entry length
++ *	@offset: vec entry offset
++ *
++ *	Attempt to add a page to the bio_vec maplist. This can fail for a
++ *	number of reasons, such as the bio being full or target block
++ *	device limitations. The target block device must allow bio's
++ *      smaller than PAGE_SIZE, so it is always possible to add a single
++ *      page to an empty bio. This should only be used by REQ_PC bios.
++ */
++int bio_add_pc_page(request_queue_t *q, struct bio *bio, struct page *page,
++		    unsigned int len, unsigned int offset)
++{
++	return __bio_add_page(q, bio, page, len, offset);
++}
++
+ /**
+  *	bio_add_page	-	attempt to add page to bio
+  *	@bio: destination bio
+@@ -1228,6 +1247,7 @@ EXPORT_SYMBOL(bio_clone);
+ EXPORT_SYMBOL(bio_phys_segments);
+ EXPORT_SYMBOL(bio_hw_segments);
+ EXPORT_SYMBOL(bio_add_page);
++EXPORT_SYMBOL(bio_add_pc_page);
+ EXPORT_SYMBOL(bio_get_nr_vecs);
+ EXPORT_SYMBOL(bio_map_user);
+ EXPORT_SYMBOL(bio_unmap_user);
+diff --git a/include/linux/bio.h b/include/linux/bio.h
+index 685fd3720df5..b60ffe32cd21 100644
+--- a/include/linux/bio.h
++++ b/include/linux/bio.h
+@@ -292,6 +292,8 @@ extern struct bio *bio_clone(struct bio *, gfp_t);
+ extern void bio_init(struct bio *);
+ 
+ extern int bio_add_page(struct bio *, struct page *, unsigned int,unsigned int);
++extern int bio_add_pc_page(struct request_queue *, struct bio *, struct page *,
++			   unsigned int, unsigned int);
+ extern int bio_get_nr_vecs(struct block_device *);
+ extern struct bio *bio_map_user(struct request_queue *, struct block_device *,
+ 				unsigned long, unsigned int, int);
+diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
+index 063e32fe036c..e94ca4d36035 100644
+--- a/include/scsi/scsi_device.h
++++ b/include/scsi/scsi_device.h
+@@ -274,6 +274,12 @@ extern int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
+ extern int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
+ 			    int data_direction, void *buffer, unsigned bufflen,
+ 			    struct scsi_sense_hdr *, int timeout, int retries);
++extern int scsi_execute_async(struct scsi_device *sdev,
++			      const unsigned char *cmd, int data_direction,
++			      void *buffer, unsigned bufflen, int use_sg,
++			      int timeout, int retries, void *privdata,
++			      void (*done)(void *, char *, int, int),
++			      gfp_t gfp);
+ 
+ static inline unsigned int sdev_channel(struct scsi_device *sdev)
+ {

commit 6e39b69e7ea9205c5f80aeac3ef999ab8fb1a4cc
+Author: Mike Christie 
+Date:   Fri Nov 11 05:30:24 2005 -0600
+
+    [SCSI] export blk layer functions needed for blk_execute_rq_nowait
+    
+    To send async requests we need these two functions exported.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
+index 99c9ca6d5992..c525b5a2b598 100644
+--- a/block/ll_rw_blk.c
++++ b/block/ll_rw_blk.c
+@@ -2306,6 +2306,8 @@ void blk_execute_rq_nowait(request_queue_t *q, struct gendisk *bd_disk,
+ 	generic_unplug_device(q);
+ }
+ 
++EXPORT_SYMBOL_GPL(blk_execute_rq_nowait);
++
+ /**
+  * blk_execute_rq - insert a request into queue for execution
+  * @q:		queue to insert the request in
+@@ -2444,7 +2446,7 @@ void disk_round_stats(struct gendisk *disk)
+ /*
+  * queue lock must be held
+  */
+-static void __blk_put_request(request_queue_t *q, struct request *req)
++void __blk_put_request(request_queue_t *q, struct request *req)
+ {
+ 	struct request_list *rl = req->rl;
+ 
+@@ -2473,6 +2475,8 @@ static void __blk_put_request(request_queue_t *q, struct request *req)
+ 	}
+ }
+ 
++EXPORT_SYMBOL_GPL(__blk_put_request);
++
+ void blk_put_request(struct request *req)
+ {
+ 	unsigned long flags;
+diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
+index a33a31e71bbc..9a68716dcf75 100644
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -558,6 +558,7 @@ extern void blk_unregister_queue(struct gendisk *disk);
+ extern void register_disk(struct gendisk *dev);
+ extern void generic_make_request(struct bio *bio);
+ extern void blk_put_request(struct request *);
++extern void __blk_put_request(request_queue_t *, struct request *);
+ extern void blk_end_sync_rq(struct request *rq);
+ extern void blk_attempt_remerge(request_queue_t *, struct request *);
+ extern struct request *blk_get_request(request_queue_t *, int, gfp_t);
+@@ -579,6 +580,10 @@ extern int blk_rq_map_kern(request_queue_t *, struct request *, void *, unsigned
+ extern int blk_rq_map_user_iov(request_queue_t *, struct request *, struct sg_iovec *, int);
+ extern int blk_execute_rq(request_queue_t *, struct gendisk *,
+ 			  struct request *, int);
++extern void blk_execute_rq_nowait(request_queue_t *, struct gendisk *,
++				  struct request *, int,
++				  void (*done)(struct request *));
++
+ static inline request_queue_t *bdev_get_queue(struct block_device *bdev)
+ {
+ 	return bdev->bd_disk->queue;

commit 8a47cd340b4a299087f926ff2780d1eb08513f04
+Author: Mike Christie 
+Date:   Wed Nov 30 02:27:19 2005 -0600
+
+    [SCSI] iscsi: check header digests for mgmt tasks
+    
+    From Wang Zhenyu:
+    
+    check header digest for cmd and mgmt tasks
+    
+    Signed-off-by: Wang Zhenyu 
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index feb8731907c7..2d12355eed33 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -581,6 +581,12 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
+ 		crypto_digest_digest(conn->rx_tfm, &sg, 1, (u8 *)&cdgst);
+ 		rdgst = *(uint32_t*)((char*)hdr + sizeof(struct iscsi_hdr) +
+ 				     conn->in.ahslen);
++		if (cdgst != rdgst) {
++			printk(KERN_ERR "iscsi_tcp: itt %x: hdrdgst error "
++			       "recv 0x%x calc 0x%x\n", conn->in.itt, rdgst,
++			       cdgst);
++			return ISCSI_ERR_HDR_DGST;
++		}
+ 	}
+ 
+ 	/* save opcode for later */
+@@ -610,13 +616,6 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
+ 		  conn->in.ahslen, conn->in.datalen);
+ 
+ 	if (conn->in.itt < session->cmds_max) {
+-		if (conn->hdrdgst_en && cdgst != rdgst) {
+-			printk(KERN_ERR "iscsi_tcp: itt %x: hdrdgst error "
+-			       "recv 0x%x calc 0x%x\n", conn->in.itt, rdgst,
+-			       cdgst);
+-			return ISCSI_ERR_HDR_DGST;
+-		}
+-
+ 		ctask = (struct iscsi_cmd_task *)session->cmds[conn->in.itt];
+ 
+ 		if (!ctask->sc) {
+@@ -1128,8 +1127,7 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 		 */
+ 		rc = iscsi_hdr_recv(conn);
+ 		if (!rc && conn->in.datalen) {
+-			if (conn->datadgst_en &&
+-				conn->in.opcode != ISCSI_OP_LOGIN_RSP) {
++			if (conn->datadgst_en) {
+ 				BUG_ON(!conn->data_rx_tfm);
+ 				crypto_digest_init(conn->data_rx_tfm);
+ 			}
+@@ -1179,8 +1177,7 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 		}
+ 		conn->in.copy -= conn->in.padding;
+ 		conn->in.offset += conn->in.padding;
+-		if (conn->datadgst_en &&
+-			conn->in.opcode != ISCSI_OP_LOGIN_RSP) {
++		if (conn->datadgst_en) {
+ 			if (conn->in.padding) {
+ 				debug_tcp("padding -> %d\n", conn->in.padding);
+ 				memset(pad, 0, conn->in.padding);
+@@ -2875,8 +2872,11 @@ iscsi_conn_stop(iscsi_connh_t connh, int flag)
+ 		 * in hdr_extract() and will be re-negotiated at
+ 		 * set_param() time.
+ 		 */
+-		if (flag == STOP_CONN_RECOVER)
++		if (flag == STOP_CONN_RECOVER) {
+ 			conn->hdr_size = sizeof(struct iscsi_hdr);
++			conn->hdrdgst_en = 0;
++			conn->datadgst_en = 0;
++		}
+ 	}
+ 	up(&conn->xmitsema);
+ }

commit 4d841d6bd94d55642f8dbb11d6b672b3b50ff82e
+Author: Mike Christie 
+Date:   Tue Nov 29 23:13:01 2005 -0600
+
+    [SCSI] iscsi: update version
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 5b14c404069f..feb8731907c7 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -49,7 +49,7 @@ MODULE_AUTHOR("Dmitry Yusupov , "
+ 	      "Alex Aizman ");
+ MODULE_DESCRIPTION("iSCSI/TCP data-path");
+ MODULE_LICENSE("GPL");
+-MODULE_VERSION("0:4.409");
++MODULE_VERSION("0:4.445");
+ /* #define DEBUG_TCP */
+ /* #define DEBUG_SCSI */
+ #define DEBUG_ASSERT

commit 9e3961ba2be51a88c6223143568c80e0616d93ce
+Author: Mike Christie 
+Date:   Tue Nov 29 23:12:59 2005 -0600
+
+    [SCSI] iscsi: lower queue depth
+    
+    From Wang Zhenyu:
+    
+    High queue depth was a problem for some targets so make queue_depth adjustable
+    
+    From Mike Christie
+    
+    Make default queue_depth a little lower
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 83e2f8c8e496..5b14c404069f 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -2401,6 +2401,15 @@ iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 	return 0;
+ }
+ 
++static int
++iscsi_change_queue_depth(struct scsi_device *sdev, int depth)
++{
++	if (depth > ISCSI_MAX_CMD_PER_LUN)
++		depth = ISCSI_MAX_CMD_PER_LUN;
++	scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
++	return sdev->queue_depth;
++}
++
+ static int
+ iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size)
+ {
+@@ -3260,13 +3269,14 @@ iscsi_r2tpool_free(struct iscsi_session *session)
+ static struct scsi_host_template iscsi_sht = {
+ 	.name			= "iSCSI Initiator over TCP/IP, v."
+ 				  ISCSI_VERSION_STR,
+-        .queuecommand           = iscsi_queuecommand,
++	.queuecommand           = iscsi_queuecommand,
++	.change_queue_depth	= iscsi_change_queue_depth,
+ 	.can_queue		= ISCSI_XMIT_CMDS_MAX - 1,
+ 	.sg_tablesize		= ISCSI_SG_TABLESIZE,
+-	.cmd_per_lun		= ISCSI_CMD_PER_LUN,
+-        .eh_abort_handler       = iscsi_eh_abort,
+-        .eh_host_reset_handler	= iscsi_eh_host_reset,
+-        .use_clustering         = DISABLE_CLUSTERING,
++	.cmd_per_lun		= ISCSI_DEF_CMD_PER_LUN,
++	.eh_abort_handler       = iscsi_eh_abort,
++	.eh_host_reset_handler	= iscsi_eh_host_reset,
++	.use_clustering         = DISABLE_CLUSTERING,
+ 	.proc_name		= "iscsi_tcp",
+ 	.this_id		= -1,
+ };
+diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
+index d23ae68fae0d..855f2dfd18af 100644
+--- a/drivers/scsi/iscsi_tcp.h
++++ b/drivers/scsi/iscsi_tcp.h
+@@ -71,7 +71,8 @@
+ #define ISCSI_MGMT_CMDS_MAX		32	/* must be power of 2 */
+ #define ISCSI_MGMT_ITT_OFFSET		0xa00
+ #define ISCSI_SG_TABLESIZE		SG_ALL
+-#define ISCSI_CMD_PER_LUN		128
++#define ISCSI_DEF_CMD_PER_LUN		32
++#define ISCSI_MAX_CMD_PER_LUN		128
+ #define ISCSI_TCP_MAX_CMD_LEN		16
+ 
+ #define ITT_MASK			(0xfff)

commit f6cfba1d21e9e4afd80e2274aa4df3dc1bd0aab7
+Author: Mike Christie 
+Date:   Tue Nov 29 23:12:57 2005 -0600
+
+    [SCSI] iscsi: data digest calculation fix
+    
+    From Wang Zhenyu:
+    
+    data digest fix (the bug caused data corruption w/Wasabi StorageBuilder target)
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index e6991515ad2e..83e2f8c8e496 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -903,11 +903,20 @@ partial_sg_digest_update(struct iscsi_conn *conn, struct scatterlist *sg,
+ 	crypto_digest_update(conn->data_rx_tfm, &temp, 1);
+ }
+ 
++static void
++iscsi_recv_digest_update(struct iscsi_conn *conn, char* buf, int len)
++{
++	struct scatterlist tmp;
++
++	sg_init_one(&tmp, buf, len);
++	crypto_digest_update(conn->data_rx_tfm, &tmp, 1);
++}
++
+ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
+ {
+ 	struct iscsi_cmd_task *ctask = conn->in.ctask;
+ 	struct scsi_cmnd *sc = ctask->sc;
+-	struct scatterlist tmp, *sg;
++	struct scatterlist *sg;
+ 	int i, offset, rc = 0;
+ 
+ 	BUG_ON((void*)ctask != sc->SCp.ptr);
+@@ -921,10 +930,8 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
+ 				      sc->request_bufflen, ctask->data_offset);
+ 		if (rc == -EAGAIN)
+ 			return rc;
+-		if (conn->datadgst_en) {
+-			sg_init_one(&tmp, sc->request_buffer, i);
+-			crypto_digest_update(conn->data_rx_tfm, &tmp, 1);
+-		}
++		if (conn->datadgst_en) 
++			iscsi_recv_digest_update(conn, sc->request_buffer, i);
+ 		rc = 0;
+ 		goto done;
+ 	}
+@@ -1018,6 +1025,9 @@ iscsi_data_recv(struct iscsi_conn *conn)
+ 		conn->in.hdr = &conn->hdr;
+ 		conn->senselen = (conn->data[0] << 8) | conn->data[1];
+ 		rc = iscsi_cmd_rsp(conn, conn->in.ctask);
++		if (!rc && conn->datadgst_en) 
++			iscsi_recv_digest_update(conn, conn->data,
++						 conn->in.datalen);
+ 	}
+ 	break;
+ 	case ISCSI_OP_TEXT_RSP:
+@@ -1042,6 +1052,11 @@ iscsi_data_recv(struct iscsi_conn *conn)
+ 		rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr,
+ 				    conn->data, conn->in.datalen);
+ 
++		if (!rc && conn->datadgst_en && 
++			conn->in.opcode != ISCSI_OP_LOGIN_RSP)
++			iscsi_recv_digest_update(conn, conn->data,
++			  			conn->in.datalen);
++
+ 		if (mtask && conn->login_mtask != mtask) {
+ 			spin_lock(&session->lock);
+ 			__kfifo_put(session->mgmtpool.queue, (void*)&mtask,
+@@ -1050,6 +1065,8 @@ iscsi_data_recv(struct iscsi_conn *conn)
+ 		}
+ 	}
+ 	break;
++	case ISCSI_OP_ASYNC_EVENT:
++	case ISCSI_OP_REJECT:
+ 	default:
+ 		BUG_ON(1);
+ 	}
+@@ -1112,7 +1129,7 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 		rc = iscsi_hdr_recv(conn);
+ 		if (!rc && conn->in.datalen) {
+ 			if (conn->datadgst_en &&
+-			    conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) {
++				conn->in.opcode != ISCSI_OP_LOGIN_RSP) {
+ 				BUG_ON(!conn->data_rx_tfm);
+ 				crypto_digest_init(conn->data_rx_tfm);
+ 			}
+@@ -1124,26 +1141,24 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 	}
+ 
+ 	if (conn->in_progress == IN_PROGRESS_DDIGEST_RECV) {
++		uint32_t recv_digest;
+ 		debug_tcp("extra data_recv offset %d copy %d\n",
+ 			  conn->in.offset, conn->in.copy);
+-		if (conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) {
+-			uint32_t recv_digest;
+-			skb_copy_bits(conn->in.skb, conn->in.offset,
+-				      &recv_digest, 4);
+-			conn->in.offset += 4;
+-			conn->in.copy -= 4;
+-			if (recv_digest != conn->in.datadgst) {
+-				debug_tcp("iscsi_tcp: data digest error!"
+-					  "0x%x != 0x%x\n", recv_digest,
+-					  conn->in.datadgst);
+-				iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST);
+-				return 0;
+-			} else {
+-				debug_tcp("iscsi_tcp: data digest match!"
+-					  "0x%x == 0x%x\n", recv_digest,
+-					  conn->in.datadgst);
+-				conn->in_progress = IN_PROGRESS_WAIT_HEADER;
+-			}
++		skb_copy_bits(conn->in.skb, conn->in.offset,
++				&recv_digest, 4);
++		conn->in.offset += 4;
++		conn->in.copy -= 4;
++		if (recv_digest != conn->in.datadgst) {
++			debug_tcp("iscsi_tcp: data digest error!"
++				  "0x%x != 0x%x\n", recv_digest,
++				  conn->in.datadgst);
++			iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST);
++			return 0;
++		} else {
++			debug_tcp("iscsi_tcp: data digest match!"
++				  "0x%x == 0x%x\n", recv_digest,
++				  conn->in.datadgst);
++			conn->in_progress = IN_PROGRESS_WAIT_HEADER;
+ 		}
+ 	}
+ 
+@@ -1165,7 +1180,7 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 		conn->in.copy -= conn->in.padding;
+ 		conn->in.offset += conn->in.padding;
+ 		if (conn->datadgst_en &&
+-		    conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) {
++			conn->in.opcode != ISCSI_OP_LOGIN_RSP) {
+ 			if (conn->in.padding) {
+ 				debug_tcp("padding -> %d\n", conn->in.padding);
+ 				memset(pad, 0, conn->in.padding);

commit 733bb6a70cb351786f3c2290ab22f71b612e6893
+Author: Mike Christie 
+Date:   Tue Nov 29 23:12:54 2005 -0600
+
+    [SCSI] iscsi: iscsi response fix
+    
+    from Wang Zhenyu:
+    
+    Must check SCSI CMD and R2T response according to the spec
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index f12d605c7729..e6991515ad2e 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -642,9 +642,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
+ 		switch(conn->in.opcode) {
+ 		case ISCSI_OP_SCSI_CMD_RSP:
+ 			BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
+-			if (ctask->hdr.flags & ISCSI_FLAG_CMD_WRITE)
+-				rc = iscsi_cmd_rsp(conn, ctask);
+-			else if (!conn->in.datalen)
++			if (!conn->in.datalen)
+ 				rc = iscsi_cmd_rsp(conn, ctask);
+ 			else
+ 				/*
+@@ -666,8 +664,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
+ 			break;
+ 		case ISCSI_OP_R2T:
+ 			BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
+-			if (ctask->hdr.flags & ISCSI_FLAG_CMD_WRITE &&
+-			    ctask->sc->sc_data_direction == DMA_TO_DEVICE)
++			if (ctask->sc->sc_data_direction == DMA_TO_DEVICE)
+ 				rc = iscsi_r2t_rsp(conn, ctask);
+ 			else
+ 				rc = ISCSI_ERR_PROTO;

commit e6273993dbcb8d805dd868e2128c3503a3bb1964
+Author: Mike Christie 
+Date:   Tue Nov 29 23:12:49 2005 -0600
+
+    [SCSI] iscsi: redirect fix
+    
+    From tomof@acm.org:
+    
+    There is one more issue about Equallogic systems. They send
+    re-direction info with FIN. I think that the kernel module needs to
+    let iscsid to read data from the socket before killing it.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 0769e9482194..f12d605c7729 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -1237,8 +1237,9 @@ iscsi_tcp_state_change(struct sock *sk)
+ 	conn = (struct iscsi_conn*)sk->sk_user_data;
+ 	session = conn->session;
+ 
+-	if (sk->sk_state == TCP_CLOSE_WAIT ||
+-	    sk->sk_state == TCP_CLOSE) {
++	if ((sk->sk_state == TCP_CLOSE_WAIT ||
++	     sk->sk_state == TCP_CLOSE) &&
++	    !atomic_read(&sk->sk_rmem_alloc)) {
+ 		debug_tcp("iscsi_tcp_state_change: TCP_CLOSE|TCP_CLOSE_WAIT\n");
+ 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ 	}

commit 0d2f16559a9015c4daa8babfc443bf2b8740fbd9
+Author: Mike Christie 
+Date:   Tue Nov 29 23:12:46 2005 -0600
+
+    [SCSI] iscsi: opcode check fix
+    
+    Must check only valid opcode bits.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 4fea3e4edaa7..0769e9482194 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -584,7 +584,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
+ 	}
+ 
+ 	/* save opcode for later */
+-	conn->in.opcode = hdr->opcode;
++	conn->in.opcode = hdr->opcode & ISCSI_OPCODE_MASK;
+ 
+ 	/* verify itt (itt encoding: age+cid+itt) */
+ 	if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) {

commit 85837ebdd7bb3e96a60e9b4c6af6c60d1273bc67
+Author: Mike Christie 
+Date:   Fri Nov 11 16:38:53 2005 -0600
+
+    [PATCH] kill libata scsi_wait_req usage (make libata compile with scsi-misc changes)
+    
+    scsi_wait_req does not exist any more in the SCSI layer.  This patch
+    makes it so libata can compile again.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
+index 7e37f488f591..261be24e1df3 100644
+--- a/drivers/scsi/libata-scsi.c
++++ b/drivers/scsi/libata-scsi.c
+@@ -38,6 +38,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -147,7 +148,8 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
+ 	u8 scsi_cmd[MAX_COMMAND_SIZE];
+ 	u8 args[4], *argbuf = NULL;
+ 	int argsize = 0;
+-	struct scsi_request *sreq;
++	struct scsi_sense_hdr sshdr;
++	enum dma_data_direction data_dir;
+ 
+ 	if (NULL == (void *)arg)
+ 		return -EINVAL;
+@@ -155,10 +157,6 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
+ 	if (copy_from_user(args, arg, sizeof(args)))
+ 		return -EFAULT;
+ 
+-	sreq = scsi_allocate_request(scsidev, GFP_KERNEL);
+-	if (!sreq)
+-		return -EINTR;
+-
+ 	memset(scsi_cmd, 0, sizeof(scsi_cmd));
+ 
+ 	if (args[3]) {
+@@ -172,11 +170,11 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
+ 		scsi_cmd[1]  = (4 << 1); /* PIO Data-in */
+ 		scsi_cmd[2]  = 0x0e;     /* no off.line or cc, read from dev,
+ 		                            block count in sector count field */
+-		sreq->sr_data_direction = DMA_FROM_DEVICE;
++		data_dir = DMA_FROM_DEVICE;
+ 	} else {
+ 		scsi_cmd[1]  = (3 << 1); /* Non-data */
+ 		/* scsi_cmd[2] is already 0 -- no off.line, cc, or data xfer */
+-		sreq->sr_data_direction = DMA_NONE;
++		data_dir = DMA_NONE;
+ 	}
+ 
+ 	scsi_cmd[0] = ATA_16;
+@@ -194,9 +192,8 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
+ 
+ 	/* Good values for timeout and retries?  Values below
+ 	   from scsi_ioctl_send_command() for default case... */
+-	scsi_wait_req(sreq, scsi_cmd, argbuf, argsize, (10*HZ), 5);
+-
+-	if (sreq->sr_result) {
++	if (scsi_execute_req(scsidev, scsi_cmd, data_dir, argbuf, argsize,
++			     &sshdr, (10*HZ), 5)) {
+ 		rc = -EIO;
+ 		goto error;
+ 	}
+@@ -207,8 +204,6 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
+ 	 && copy_to_user((void *)(arg + sizeof(args)), argbuf, argsize))
+ 		rc = -EFAULT;
+ error:
+-	scsi_release_request(sreq);
+-
+ 	if (argbuf)
+ 		kfree(argbuf);
+ 
+@@ -231,7 +226,7 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
+ 	int rc = 0;
+ 	u8 scsi_cmd[MAX_COMMAND_SIZE];
+ 	u8 args[7];
+-	struct scsi_request *sreq;
++	struct scsi_sense_hdr sshdr;
+ 
+ 	if (NULL == (void *)arg)
+ 		return -EINVAL;
+@@ -250,26 +245,13 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
+ 	scsi_cmd[12] = args[5];
+ 	scsi_cmd[14] = args[0];
+ 
+-	sreq = scsi_allocate_request(scsidev, GFP_KERNEL);
+-	if (!sreq) {
+-		rc = -EINTR;
+-		goto error;
+-	}
+-
+-	sreq->sr_data_direction = DMA_NONE;
+ 	/* Good values for timeout and retries?  Values below
+-	   from scsi_ioctl_send_command() for default case... */
+-	scsi_wait_req(sreq, scsi_cmd, NULL, 0, (10*HZ), 5);
+-
+-	if (sreq->sr_result) {
++	   from scsi_ioctl_send_command() for default case... */	
++	if (scsi_execute_req(scsidev, scsi_cmd, DMA_NONE, NULL, 0, &sshdr,
++			     (10*HZ), 5))
+ 		rc = -EIO;
+-		goto error;
+-	}
+ 
+ 	/* Need code to retrieve data from check condition? */
+-
+-error:
+-	scsi_release_request(sreq);
+ 	return rc;
+ }
+ 

commit beb8abd9a958999e238c31814230368045b942b3
+Author: Mike Christie 
+Date:   Mon Sep 12 21:02:06 2005 -0500
+
+    [SCSI] iscsi: add module version
+    
+    From: michaelc@cs.wisc.edu
+    
+    I have a bad memory. I cannot remember what versions are which,
+    so add a module version to help.
+    
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 1d27caf3abe8..4fea3e4edaa7 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -49,7 +49,7 @@ MODULE_AUTHOR("Dmitry Yusupov , "
+ 	      "Alex Aizman ");
+ MODULE_DESCRIPTION("iSCSI/TCP data-path");
+ MODULE_LICENSE("GPL");
+-
++MODULE_VERSION("0:4.409");
+ /* #define DEBUG_TCP */
+ /* #define DEBUG_SCSI */
+ #define DEBUG_ASSERT

commit 9974487824570e7ac388390333ef5c4ca3ebc2da
+Author: Mike Christie 
+Date:   Mon Sep 12 21:02:04 2005 -0500
+
+    [SCSI] iscsi: fix nop-in handling
+    
+    From: zhenyu.z.wang@intel.com
+    
+    This add check to NOOP_IN's ttt, when it's ~0UL we should not send
+    NOOP_OUT by spec (plus some cleanup).
+    
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 13411ca3d648..1d27caf3abe8 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -672,34 +672,6 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
+ 			else
+ 				rc = ISCSI_ERR_PROTO;
+ 			break;
+-		case ISCSI_OP_NOOP_IN:
+-		case ISCSI_OP_TEXT_RSP:
+-		case ISCSI_OP_LOGOUT_RSP:
+-		case ISCSI_OP_ASYNC_EVENT:
+-		case ISCSI_OP_REJECT:
+-			rc = iscsi_check_assign_cmdsn(session,
+-						 (struct iscsi_nopin*)hdr);
+-			if (rc)
+-				break;
+-
+-			/* update ExpStatSN */
+-			conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
+-			if (!conn->in.datalen) {
+-				struct iscsi_mgmt_task *mtask;
+-
+-				rc = iscsi_recv_pdu(iscsi_handle(conn), hdr,
+-						    NULL, 0);
+-				mtask = (struct iscsi_mgmt_task *)
+-					session->mgmt_cmds[conn->in.itt -
+-						ISCSI_MGMT_ITT_OFFSET];
+-				if (conn->login_mtask != mtask) {
+-					spin_lock(&session->lock);
+-					__kfifo_put(session->mgmtpool.queue,
+-					    (void*)&mtask, sizeof(void*));
+-					spin_unlock(&session->lock);
+-				}
+-			}
+-			break;
+ 		default:
+ 			rc = ISCSI_ERR_BAD_OPCODE;
+ 			break;
+@@ -718,6 +690,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
+ 		switch(conn->in.opcode) {
+ 		case ISCSI_OP_LOGIN_RSP:
+ 		case ISCSI_OP_TEXT_RSP:
++		case ISCSI_OP_LOGOUT_RSP: 
+ 			rc = iscsi_check_assign_cmdsn(session,
+ 						 (struct iscsi_nopin*)hdr);
+ 			if (rc)
+@@ -758,20 +731,59 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
+ 			}
+ 			spin_unlock(&session->lock);
+ 			break;
++		case ISCSI_OP_NOOP_IN: 
++			if (hdr->ttt != ISCSI_RESERVED_TAG) {
++				rc = ISCSI_ERR_PROTO;
++				break;
++			}
++			rc = iscsi_check_assign_cmdsn(session, 
++						(struct iscsi_nopin*)hdr);
++			if (rc)
++				break;
++			conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
++
++			if (!conn->in.datalen) {
++				struct iscsi_mgmt_task *mtask;
++
++				rc = iscsi_recv_pdu(iscsi_handle(conn), hdr,
++						    NULL, 0);
++				mtask = (struct iscsi_mgmt_task *)
++					session->mgmt_cmds[conn->in.itt -
++							ISCSI_MGMT_ITT_OFFSET];
++				if (conn->login_mtask != mtask) {
++					spin_lock(&session->lock);
++					__kfifo_put(session->mgmtpool.queue,
++						  (void*)&mtask, sizeof(void*));
++					spin_unlock(&session->lock);
++				}
++			}
++			break;
+ 		default:
+ 			rc = ISCSI_ERR_BAD_OPCODE;
+ 			break;
+ 		}
+ 	} else if (conn->in.itt == ISCSI_RESERVED_TAG) {
+-		if (conn->in.opcode == ISCSI_OP_NOOP_IN && !conn->in.datalen) {
+-			rc = iscsi_check_assign_cmdsn(session,
++		switch(conn->in.opcode) {
++		case ISCSI_OP_NOOP_IN:
++			if (!conn->in.datalen) {
++				rc = iscsi_check_assign_cmdsn(session,
+ 						 (struct iscsi_nopin*)hdr);
+-			if (!rc)
+-				rc = iscsi_recv_pdu(iscsi_handle(conn),
+-						    hdr, NULL, 0);
+-		}
+-		else
++				if (!rc && hdr->ttt != ISCSI_RESERVED_TAG)
++					rc = iscsi_recv_pdu(iscsi_handle(conn),
++							    hdr, NULL, 0);
++			} else 
++				rc = ISCSI_ERR_PROTO;
++			break;
++		case ISCSI_OP_REJECT:
++			/* we need sth like iscsi_reject_rsp()*/
++		case ISCSI_OP_ASYNC_EVENT:
++			/* we need sth like iscsi_async_event_rsp() */
+ 			rc = ISCSI_ERR_BAD_OPCODE;
++			break;
++		default:
++			rc = ISCSI_ERR_BAD_OPCODE;
++			break;
++		}
+ 	} else
+ 		rc = ISCSI_ERR_BAD_ITT;
+ 

commit fa0a6957aa7d02addb08a231c8e7c77c2b8fcd20
+Author: Mike Christie 
+Date:   Mon Sep 12 21:01:57 2005 -0500
+
+    [SCSI] iscsi: rename some proto defs
+    
+    From: hare@suse.de
+    
+    for a proper alignment between open-iscsi and iscsitarget the
+    definitions in include/iscsi_proto.h do not match exactly.
+    
+    With this patch it's possible to have iscsitarget use
+    'include/iscsi_proto.h' instead of its own iscsi_hdr.h.
+    
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h
+index 8d3190480441..4feda05fdf25 100644
+--- a/include/scsi/iscsi_proto.h
++++ b/include/scsi/iscsi_proto.h
+@@ -548,9 +548,11 @@ struct iscsi_reject {
+ 	uint8_t flags;
+ 	uint8_t reason;
+ 	uint8_t rsvd2;
+-	uint8_t rsvd3;
++	uint8_t hlength;
+ 	uint8_t dlength[3];
+-	uint8_t rsvd4[16];
++	uint8_t rsvd3[8];
++	__be32  ffffffff;
++	uint8_t rsvd4[4];
+ 	__be32	statsn;
+ 	__be32	exp_cmdsn;
+ 	__be32	max_cmdsn;
+@@ -560,17 +562,17 @@ struct iscsi_reject {
+ };
+ 
+ /* Reason for Reject */
+-#define CMD_BEFORE_LOGIN	1
+-#define DATA_DIGEST_ERROR	2
+-#define DATA_SNACK_REJECT	3
+-#define ISCSI_PROTOCOL_ERROR	4
+-#define CMD_NOT_SUPPORTED	5
+-#define IMM_CMD_REJECT		6
+-#define TASK_IN_PROGRESS	7
+-#define INVALID_SNACK		8
+-#define BOOKMARK_REJECTED	9
+-#define BOOKMARK_NO_RESOURCES	10
+-#define NEGOTIATION_RESET	11
++#define ISCSI_REASON_CMD_BEFORE_LOGIN	1
++#define ISCSI_REASON_DATA_DIGEST_ERROR	2
++#define ISCSI_REASON_DATA_SNACK_REJECT	3
++#define ISCSI_REASON_PROTOCOL_ERROR	4
++#define ISCSI_REASON_CMD_NOT_SUPPORTED	5
++#define ISCSI_REASON_IMM_CMD_REJECT		6
++#define ISCSI_REASON_TASK_IN_PROGRESS	7
++#define ISCSI_REASON_INVALID_SNACK		8
++#define ISCSI_REASON_BOOKMARK_INVALID	9
++#define ISCSI_REASON_BOOKMARK_NO_RESOURCES	10
++#define ISCSI_REASON_NEGOTIATION_RESET	11
+ 
+ /* Max. number of Key=Value pairs in a text message */
+ #define MAX_KEY_VALUE_PAIRS	8192

commit 762e2bfac7bc5f21b04ff17138aac3c453fb6481
+Author: Mike Christie 
+Date:   Mon Sep 12 21:01:46 2005 -0500
+
+    [SCSI] iscsi: add newline to sysfs output
+    
+    From: tomof@acm.org
+    
+    trivial cleanup of show_transport_handle()
+    
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index e4fceca49e56..d010aeda9d62 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -97,7 +97,7 @@ static ssize_t
+ show_transport_handle(struct class_device *cdev, char *buf)
+ {
+ 	struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev);
+-	return sprintf(buf, "%llu", (unsigned long long)iscsi_handle(priv->iscsi_transport));
++	return sprintf(buf, "%llu\n", (unsigned long long)iscsi_handle(priv->iscsi_transport));
+ }
+ static CLASS_DEVICE_ATTR(handle, S_IRUGO, show_transport_handle, NULL);
+ 

commit 02cf9311ee4690373ebbe62a5986025c932bead0
+Author: Mike Christie 
+Date:   Mon Sep 12 21:01:41 2005 -0500
+
+    [SCSI] iscsi: fix ahs len
+    
+    From: tomof@acm.org
+    
+    Fix AHS Length
+    
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index baacf836083e..13411ca3d648 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -557,7 +557,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
+ 	conn->data_copied = 0;
+ 
+ 	/* read AHS */
+-	conn->in.ahslen = hdr->hlength*(4*sizeof(__u16));
++	conn->in.ahslen = hdr->hlength * 4;
+ 	conn->in.offset += conn->in.ahslen;
+ 	conn->in.copy -= conn->in.ahslen;
+ 	if (conn->in.copy < 0) {

commit baebc497b43a69d7280af226e08214c527220d45
+Author: Mike Christie 
+Date:   Mon Sep 12 21:01:38 2005 -0500
+
+    [SCSI] iscsi: update some iscsi proto defs
+    
+    From: michaelc@cs.wisc.edu
+    
+    Cleanup some iscsi_proto defs, add some missing values, and
+    fix some defs.
+    
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index bb0a5039d334..baacf836083e 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -751,7 +751,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
+ 						(void*)&mtask, sizeof(void*));
+ 				conn->tmabort_state =
+ 					((struct iscsi_tm_rsp *)hdr)->
+-					response == SCSI_TCP_TM_RESP_COMPLETE ?
++					response == ISCSI_TMF_RSP_COMPLETE ?
+ 						TMABORT_SUCCESS:TMABORT_FAILED;
+ 				/* unblock eh_abort() */
+ 				wake_up(&conn->ehwait);
+diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h
+index 6c08551c79f5..8d3190480441 100644
+--- a/include/scsi/iscsi_proto.h
++++ b/include/scsi/iscsi_proto.h
+@@ -56,7 +56,8 @@ struct iscsi_hdr {
+ 	__be32		ttt;		/* Target Task Tag */
+ 	__be32		statsn;
+ 	__be32		exp_statsn;
+-	uint8_t		other[16];
++	__be32		max_statsn;
++	uint8_t		other[12];
+ };
+ 
+ /************************* RFC 3720 Begin *****************************/
+@@ -78,6 +79,11 @@ struct iscsi_hdr {
+ #define ISCSI_OP_LOGOUT			0x06
+ #define ISCSI_OP_SNACK			0x10
+ 
++#define ISCSI_OP_VENDOR1_CMD		0x1c
++#define ISCSI_OP_VENDOR2_CMD		0x1d
++#define ISCSI_OP_VENDOR3_CMD		0x1e
++#define ISCSI_OP_VENDOR4_CMD		0x1f
++
+ /* Target Opcode values */
+ #define ISCSI_OP_NOOP_IN		0x20
+ #define ISCSI_OP_SCSI_CMD_RSP		0x21
+@@ -90,12 +96,20 @@ struct iscsi_hdr {
+ #define ISCSI_OP_ASYNC_EVENT		0x32
+ #define ISCSI_OP_REJECT			0x3f
+ 
++struct iscsi_ahs_hdr {
++	__be16 ahslength;
++	uint8_t ahstype;
++	uint8_t ahspec[5];
++};
++
++#define ISCSI_AHSTYPE_CDB		1
++#define ISCSI_AHSTYPE_RLENGTH		2
++
+ /* iSCSI PDU Header */
+ struct iscsi_cmd {
+ 	uint8_t opcode;
+ 	uint8_t flags;
+-	uint8_t rsvd2;
+-	uint8_t cmdrn;
++	__be16 rsvd2;
+ 	uint8_t hlength;
+ 	uint8_t dlength[3];
+ 	uint8_t lun[8];
+@@ -120,6 +134,13 @@ struct iscsi_cmd {
+ #define ISCSI_ATTR_HEAD_OF_QUEUE	3
+ #define ISCSI_ATTR_ACA			4
+ 
++struct iscsi_rlength_ahdr {
++	__be16 ahslength;
++	uint8_t ahstype;
++	uint8_t reserved;
++	__be32 read_length;
++};
++
+ /* SCSI Response Header */
+ struct iscsi_cmd_rsp {
+ 	uint8_t opcode;
+@@ -227,7 +248,7 @@ struct iscsi_tm {
+ 	uint8_t rsvd2[8];
+ };
+ 
+-#define ISCSI_FLAG_TASK_MGMT_FUNCTION_MASK	0x7F
++#define ISCSI_FLAG_TM_FUNC_MASK			0x7F
+ 
+ /* Function values */
+ #define ISCSI_TM_FUNC_ABORT_TASK		1
+@@ -257,14 +278,14 @@ struct iscsi_tm_rsp {
+ };
+ 
+ /* Response values */
+-#define SCSI_TCP_TM_RESP_COMPLETE	0x00
+-#define SCSI_TCP_TM_RESP_NO_TASK	0x01
+-#define SCSI_TCP_TM_RESP_NO_LUN		0x02
+-#define SCSI_TCP_TM_RESP_TASK_ALLEGIANT	0x03
+-#define SCSI_TCP_TM_RESP_NO_FAILOVER	0x04
+-#define SCSI_TCP_TM_RESP_NOT_SUPPORTED	0x05
+-#define SCSI_TCP_TM_RESP_AUTH_FAILED	0x06
+-#define SCSI_TCP_TM_RESP_REJECTED	0xff
++#define ISCSI_TMF_RSP_COMPLETE		0x00
++#define ISCSI_TMF_RSP_NO_TASK		0x01
++#define ISCSI_TMF_RSP_NO_LUN		0x02
++#define ISCSI_TMF_RSP_TASK_ALLEGIANT	0x03
++#define ISCSI_TMF_RSP_NO_FAILOVER	0x04
++#define ISCSI_TMF_RSP_NOT_SUPPORTED	0x05
++#define ISCSI_TMF_RSP_AUTH_FAILED	0x06
++#define ISCSI_TMF_RSP_REJECTED		0xff
+ 
+ /* Ready To Transfer Header */
+ struct iscsi_r2t_rsp {

commit bb052349798f775d4d7ed20ffcf1510287d8abe6
+Author: Mike Christie 
+Date:   Mon Sep 12 21:01:35 2005 -0500
+
+    [SCSI] iscsi: handle nonlinear skbs
+    
+    From: zhenyu.z.wang@intel.com
+    
+    Fix oops from nonlinear skb usage.
+    
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 8751f6015559..bb0a5039d334 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -1061,7 +1061,6 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ {
+ 	int rc;
+ 	struct iscsi_conn *conn = rd_desc->arg.data;
+-	int start = skb_headlen(skb);
+ 	int processed;
+ 	char pad[ISCSI_PAD_LEN];
+ 	struct scatterlist sg;
+@@ -1070,7 +1069,7 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+ 	 * Save current SKB and its offset in the corresponding
+ 	 * connection context.
+ 	 */
+-	conn->in.copy = start - offset;
++	conn->in.copy = skb->len - offset;
+ 	conn->in.offset = offset;
+ 	conn->in.skb = skb;
+ 	conn->in.len = conn->in.copy;

commit af973481f4a0902ad35726636c290f4794704948
+Author: Mike Christie 
+Date:   Mon Sep 12 21:01:32 2005 -0500
+
+    [SCSI] iscsi: preemt fix and cleanup
+    
+    From: zhenyu.z.wang@intel.com
+    
+    Delay the head digest update until xmit time, like data digest update.
+    [To make things cleaner and avoid prempt bug]
+    
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 584e51024fd6..8751f6015559 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -129,14 +129,11 @@ iscsi_buf_left(struct iscsi_buf *ibuf)
+ }
+ 
+ static inline void
+-iscsi_buf_init_hdr(struct iscsi_conn *conn, struct iscsi_buf *ibuf,
+-		   char *vbuf, u8 *crc)
++iscsi_hdr_digest(struct iscsi_conn *conn, struct iscsi_buf *buf,
++		 u8* crc)
+ {
+-	iscsi_buf_init_virt(ibuf, vbuf, sizeof(struct iscsi_hdr));
+-	if (conn->hdrdgst_en) {
+-		crypto_digest_digest(conn->tx_tfm, &ibuf->sg, 1, crc);
+-		ibuf->sg.length += sizeof(uint32_t);
+-	}
++	crypto_digest_digest(conn->tx_tfm, &buf->sg, 1, crc);
++	buf->sg.length += sizeof(uint32_t);
+ }
+ 
+ static void
+@@ -427,8 +424,8 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 
+ 	r2t->sent = 0;
+ 
+-	iscsi_buf_init_hdr(conn, &r2t->headbuf, (char*)hdr,
+-			   (u8 *)dtask->hdrext);
++	iscsi_buf_init_virt(&r2t->headbuf, (char*)hdr,
++			   sizeof(struct iscsi_hdr));
+ 
+ 	r2t->dtask = dtask;
+ 
+@@ -1494,8 +1491,8 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 	}
+ 	conn->dataout_pdus_cnt++;
+ 
+-	iscsi_buf_init_hdr(conn, &r2t->headbuf, (char*)hdr,
+-			   (u8 *)dtask->hdrext);
++	iscsi_buf_init_virt(&r2t->headbuf, (char*)hdr,
++			   sizeof(struct iscsi_hdr));
+ 
+ 	r2t->dtask = dtask;
+ 
+@@ -1541,8 +1538,8 @@ iscsi_unsolicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 		hdr->flags = ISCSI_FLAG_CMD_FINAL;
+ 	}
+ 
+-	iscsi_buf_init_hdr(conn, &ctask->headbuf, (char*)hdr,
+-			   (u8 *)dtask->hdrext);
++	iscsi_buf_init_virt(&ctask->headbuf, (char*)hdr,
++			   sizeof(struct iscsi_hdr));
+ 
+ 	list_add(&dtask->item, &ctask->dataqueue);
+ 
+@@ -1662,8 +1659,8 @@ iscsi_cmd_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 		zero_data(ctask->hdr.dlength);
+ 	}
+ 
+-	iscsi_buf_init_hdr(conn, &ctask->headbuf, (char*)&ctask->hdr,
+-			    (u8 *)ctask->hdrext);
++	iscsi_buf_init_virt(&ctask->headbuf, (char*)&ctask->hdr, 
++			    sizeof(struct iscsi_hdr));
+ 	conn->scsicmd_pdus_cnt++;
+ }
+ 
+@@ -1692,6 +1689,11 @@ iscsi_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
+ 		mtask->xmstate &= ~XMSTATE_IMM_HDR;
+ 		if (mtask->data_count)
+ 			mtask->xmstate |= XMSTATE_IMM_DATA;
++		if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE &&
++	    	    conn->stop_stage != STOP_CONN_RECOVER &&
++		    conn->hdrdgst_en)
++			iscsi_hdr_digest(conn, &mtask->headbuf,
++					(u8*)mtask->hdrext);
+ 		if (iscsi_sendhdr(conn, &mtask->headbuf, mtask->data_count)) {
+ 			mtask->xmstate |= XMSTATE_IMM_HDR;
+ 			if (mtask->data_count)
+@@ -1723,6 +1725,8 @@ static inline int
+ handle_xmstate_r_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+ 	ctask->xmstate &= ~XMSTATE_R_HDR;
++	if (conn->hdrdgst_en) 
++		iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext);
+ 	if (!iscsi_sendhdr(conn, &ctask->headbuf, 0)) {
+ 		BUG_ON(ctask->xmstate != XMSTATE_IDLE);
+ 		return 0; /* wait for Data-In */
+@@ -1735,6 +1739,8 @@ static inline int
+ handle_xmstate_w_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+ 	ctask->xmstate &= ~XMSTATE_W_HDR;
++	if (conn->hdrdgst_en) 
++		iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext);
+ 	if (iscsi_sendhdr(conn, &ctask->headbuf, ctask->imm_count)) {
+ 		ctask->xmstate |= XMSTATE_W_HDR;
+ 		return -EAGAIN;
+@@ -1813,7 +1819,9 @@ handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 		iscsi_unsolicit_data_init(conn, ctask);
+ 		BUG_ON(!ctask->dtask);
+ 		dtask = ctask->dtask;
+-
++		if (conn->hdrdgst_en)
++			iscsi_hdr_digest(conn, &ctask->headbuf,
++					(u8*)dtask->hdrext);
+ 		ctask->xmstate &= ~XMSTATE_UNS_INIT;
+ 	}
+ 	if (iscsi_sendhdr(conn, &ctask->headbuf, ctask->data_count)) {
+@@ -2118,7 +2126,9 @@ iscsi_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 				    sizeof(void*));
+ solicit_head_again:
+ 		r2t = ctask->r2t;
+-
++		if (conn->hdrdgst_en)
++			iscsi_hdr_digest(conn, &r2t->headbuf, 
++					(u8*)r2t->dtask->hdrext);
+ 		if (iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count)) {
+ 			ctask->xmstate &= ~XMSTATE_SOL_DATA;
+ 			ctask->xmstate |= XMSTATE_SOL_HDR;
+@@ -2889,14 +2899,8 @@ iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+ 
+ 	memcpy(&mtask->hdr, hdr, sizeof(struct iscsi_hdr));
+ 
+-	if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE ||
+-	    conn->stop_stage == STOP_CONN_RECOVER)
+-		iscsi_buf_init_virt(&mtask->headbuf, (char*)&mtask->hdr,
++	iscsi_buf_init_virt(&mtask->headbuf, (char*)&mtask->hdr,
+ 				    sizeof(struct iscsi_hdr));
+-	else
+-		/* this will update header digest */
+-		iscsi_buf_init_hdr(conn, &mtask->headbuf, (char*)&mtask->hdr,
+-				    (u8 *)mtask->hdrext);
+ 
+ 	spin_unlock_bh(&session->lock);
+ 

commit b13941f635c3119eb02dc29b5248066f934f76be
+Author: Mike Christie 
+Date:   Mon Sep 12 21:01:28 2005 -0500
+
+    [SCSI] iscsi: nodelay fix
+    
+    From: tomof@acm.org
+    
+    I'm not sure about this. I don't think that NODELAY option hurts
+    performance. However, open-iscsi does not use MSG_MORE properly with
+    sendpage, so NODELAY option hurts the open-iscsi performance.
+    
+    I've attached a patch to fix NODELAY and MSG_MORE problems and the
+    write performance results with disktest.
+    
+    I use Opteron boxes connected directly, Chelsio NICs, 1500-byte MTU,
+    64 KB I/O size, and the iSCSI parameters on open-iscsi web site.
+    
+    With only NODELAY fix, the performance drops, as you said. On the
+    other hand, NODELAY and MSG_MORE fixes improve the performance
+    overall.
+    
+    Signed-off-by: Alex Aizman 
+    Signed-off-by: Dmitry Yusupov 
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 810e5e59658f..584e51024fd6 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -1385,7 +1385,7 @@ iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf,
+ 	BUG_ON(buf->sent + size > buf->sg.length);
+ 	if (size > *count)
+ 		size = *count;
+-	if (buf->sent + size != buf->sg.length)
++	if (buf->sent + size != buf->sg.length || *count != size)
+ 		flags |= MSG_MORE;
+ 
+ 	res = iscsi_send(sk, buf, size, flags);

commit 6f16b5359ceb96780eac4178393b0e8a3c8aa1ea
+Author: Mike Christie 
+Date:   Sat Sep 10 16:45:35 2005 -0500
+
+    [SCSI] set error value when failing commands in prep_fn
+    
+    set DID_NO_CONNECT for the BLKPREP_KILL case and correct a few
+    BLKPREP_DEFER cases that weren't checking for the need to plug the
+    queue.
+    
+    Signed-Off-By: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index d8d984841534..863bb6495daa 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -1146,7 +1146,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
+ 	if (unlikely(!scsi_device_online(sdev))) {
+ 		printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to offline device\n",
+ 		       sdev->host->host_no, sdev->id, sdev->lun);
+-		return BLKPREP_KILL;
++		goto kill;
+ 	}
+ 	if (unlikely(sdev->sdev_state != SDEV_RUNNING)) {
+ 		/* OK, we're not in a running state don't prep
+@@ -1156,7 +1156,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
+ 			 * at all allowed down */
+ 			printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to dead device\n",
+ 			       sdev->host->host_no, sdev->id, sdev->lun);
+-			return BLKPREP_KILL;
++			goto kill;
+ 		}
+ 		/* OK, we only allow special commands (i.e. not
+ 		 * user initiated ones */
+@@ -1188,11 +1188,11 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
+ 		if(unlikely(specials_only) && !(req->flags & REQ_SPECIAL)) {
+ 			if(specials_only == SDEV_QUIESCE ||
+ 					specials_only == SDEV_BLOCK)
+-				return BLKPREP_DEFER;
++				goto defer;
+ 			
+ 			printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to device being removed\n",
+ 			       sdev->host->host_no, sdev->id, sdev->lun);
+-			return BLKPREP_KILL;
++			goto kill;
+ 		}
+ 			
+ 			
+@@ -1210,7 +1210,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
+ 		cmd->tag = req->tag;
+ 	} else {
+ 		blk_dump_rq_flags(req, "SCSI bad req");
+-		return BLKPREP_KILL;
++		goto kill;
+ 	}
+ 	
+ 	/* note the overloading of req->special.  When the tag
+@@ -1248,8 +1248,13 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
+ 		 * required).
+ 		 */
+ 		ret = scsi_init_io(cmd);
+-		if (ret)	/* BLKPREP_KILL return also releases the command */
+-			return ret;
++		switch(ret) {
++		case BLKPREP_KILL:
++			/* BLKPREP_KILL return also releases the command */
++			goto kill;
++		case BLKPREP_DEFER:
++			goto defer;
++		}
+ 		
+ 		/*
+ 		 * Initialize the actual SCSI command for this request.
+@@ -1259,7 +1264,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
+ 			if (unlikely(!drv->init_command(cmd))) {
+ 				scsi_release_buffers(cmd);
+ 				scsi_put_command(cmd);
+-				return BLKPREP_KILL;
++				goto kill;
+ 			}
+ 		} else {
+ 			memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd));
+@@ -1290,6 +1295,9 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
+ 	if (sdev->device_busy == 0)
+ 		blk_plug_device(q);
+ 	return BLKPREP_DEFER;
++ kill:
++	req->errors = DID_NO_CONNECT << 16;
++	return BLKPREP_KILL;
+ }
+ 
+ /*

commit b38d950d3aedf90c8b15b3c7c799b5eb53c47c45
+Author: John Lenz 
+Date:   Thu Sep 8 14:41:54 2005 +0100
+
+    [ARM] Add suspend/resume support to locomo.c
+    
+    This adds low-level suspend/resume support to locomo.c.
+    
+    Signed-off-by: Pavel Machek 
+    Signed-off-by: Russell King 
+
+diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
+index 51f430cc2fbf..2786f7c34b3f 100644
+--- a/arch/arm/common/locomo.c
++++ b/arch/arm/common/locomo.c
+@@ -541,6 +541,103 @@ locomo_init_one_child(struct locomo *lchip, struct locomo_dev_info *info)
+ 	return ret;
+ }
+ 
++#ifdef CONFIG_PM
++
++struct locomo_save_data {
++	u16	LCM_GPO;
++	u16	LCM_SPICT;
++	u16	LCM_GPE;
++	u16	LCM_ASD;
++	u16	LCM_SPIMD;
++};
++
++static int locomo_suspend(struct device *dev, u32 pm_message_t, u32 level)
++{
++	struct locomo *lchip = dev_get_drvdata(dev);
++	struct locomo_save_data *save;
++	unsigned long flags;
++
++	if (level != SUSPEND_DISABLE)
++		return 0;
++
++	save = kmalloc(sizeof(struct locomo_save_data), GFP_KERNEL);
++	if (!save)
++		return -ENOMEM;
++
++	dev->power.saved_state = (void *) save;
++
++	spin_lock_irqsave(&lchip->lock, flags);
++
++	save->LCM_GPO     = locomo_readl(lchip->base + LOCOMO_GPO);	/* GPIO */
++	locomo_writel(0x00, lchip->base + LOCOMO_GPO);
++	save->LCM_SPICT   = locomo_readl(lchip->base + LOCOMO_SPICT);	/* SPI */
++	locomo_writel(0x40, lchip->base + LOCOMO_SPICT);
++	save->LCM_GPE     = locomo_readl(lchip->base + LOCOMO_GPE);	/* GPIO */
++	locomo_writel(0x00, lchip->base + LOCOMO_GPE);
++	save->LCM_ASD     = locomo_readl(lchip->base + LOCOMO_ASD);	/* ADSTART */
++	locomo_writel(0x00, lchip->base + LOCOMO_ASD);
++	save->LCM_SPIMD   = locomo_readl(lchip->base + LOCOMO_SPIMD);	/* SPI */
++	locomo_writel(0x3C14, lchip->base + LOCOMO_SPIMD);
++
++	locomo_writel(0x00, lchip->base + LOCOMO_PAIF);
++	locomo_writel(0x00, lchip->base + LOCOMO_DAC);
++	locomo_writel(0x00, lchip->base + LOCOMO_BACKLIGHT + LOCOMO_TC);
++
++	if ( (locomo_readl(lchip->base + LOCOMO_LED + LOCOMO_LPT0) & 0x88) && (locomo_readl(lchip->base + LOCOMO_LED + LOCOMO_LPT1) & 0x88) )
++		locomo_writel(0x00, lchip->base + LOCOMO_C32K); 	/* CLK32 off */
++	else
++		/* 18MHz already enabled, so no wait */
++		locomo_writel(0xc1, lchip->base + LOCOMO_C32K); 	/* CLK32 on */
++
++	locomo_writel(0x00, lchip->base + LOCOMO_TADC);		/* 18MHz clock off*/
++	locomo_writel(0x00, lchip->base + LOCOMO_AUDIO + LOCOMO_ACC);			/* 22MHz/24MHz clock off */
++	locomo_writel(0x00, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);			/* FL */
++
++	spin_unlock_irqrestore(&lchip->lock, flags);
++
++	return 0;
++}
++
++static int locomo_resume(struct device *dev, u32 level)
++{
++	struct locomo *lchip = dev_get_drvdata(dev);
++	struct locomo_save_data *save;
++	unsigned long r;
++	unsigned long flags;
++	
++	if (level != RESUME_ENABLE)
++		return 0;
++
++	save = (struct locomo_save_data *) dev->power.saved_state;
++	if (!save)
++		return 0;
++
++	spin_lock_irqsave(&lchip->lock, flags);
++
++	locomo_writel(save->LCM_GPO, lchip->base + LOCOMO_GPO);
++	locomo_writel(save->LCM_SPICT, lchip->base + LOCOMO_SPICT);
++	locomo_writel(save->LCM_GPE, lchip->base + LOCOMO_GPE);
++	locomo_writel(save->LCM_ASD, lchip->base + LOCOMO_ASD);
++	locomo_writel(save->LCM_SPIMD, lchip->base + LOCOMO_SPIMD);
++
++	locomo_writel(0x00, lchip->base + LOCOMO_C32K);
++	locomo_writel(0x90, lchip->base + LOCOMO_TADC);
++
++	locomo_writel(0, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KSC);
++	r = locomo_readl(lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC);
++	r &= 0xFEFF;
++	locomo_writel(r, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC);
++	locomo_writel(0x1, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KCMD);
++
++	spin_unlock_irqrestore(&lchip->lock, flags);
++
++	dev->power.saved_state = NULL;
++	kfree(save);
++
++	return 0;
++}
++#endif
++
+ /**
+  *	locomo_probe - probe for a single LoCoMo chip.
+  *	@phys_addr: physical address of device.
+@@ -707,6 +804,10 @@ static struct device_driver locomo_device_driver = {
+ 	.bus		= &platform_bus_type,
+ 	.probe		= locomo_probe,
+ 	.remove		= locomo_remove,
++#ifdef CONFIG_PM
++	.suspend	= locomo_suspend,
++	.resume		= locomo_resume,
++#endif
+ };
+ 
+ /*

commit df46b9a44ceb5af2ea2351ce8e28ae7bd840b00f
+Author: Mike Christie 
+Date:   Mon Jun 20 14:04:44 2005 +0200
+
+    [PATCH] Add blk_rq_map_kern()
+    
+    Add blk_rq_map_kern which takes a kernel buffer and maps it into
+    a request and bio. This can be used by the dm hw_handlers, old
+    sg_scsi_ioctl, and one day scsi special requests so all requests
+    comming into scsi will have bios. All requests having bios
+    should allow scsi to use scatter lists for all IO and allow it
+    to use block layer functions.
+    
+    Signed-off-by: Jens Axboe 
+
+diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
+index f20eba22b14b..e30a3c93b70c 100644
+--- a/drivers/block/ll_rw_blk.c
++++ b/drivers/block/ll_rw_blk.c
+@@ -281,6 +281,7 @@ static inline void rq_init(request_queue_t *q, struct request *rq)
+ 	rq->special = NULL;
+ 	rq->data_len = 0;
+ 	rq->data = NULL;
++	rq->nr_phys_segments = 0;
+ 	rq->sense = NULL;
+ 	rq->end_io = NULL;
+ 	rq->end_io_data = NULL;
+@@ -2176,6 +2177,61 @@ int blk_rq_unmap_user(struct request *rq, struct bio *bio, unsigned int ulen)
+ 
+ EXPORT_SYMBOL(blk_rq_unmap_user);
+ 
++static int blk_rq_map_kern_endio(struct bio *bio, unsigned int bytes_done,
++				 int error)
++{
++	if (bio->bi_size)
++		return 1;
++
++	bio_put(bio);
++	return 0;
++}
++
++/**
++ * blk_rq_map_kern - map kernel data to a request, for REQ_BLOCK_PC usage
++ * @q:		request queue where request should be inserted
++ * @rw:		READ or WRITE data
++ * @kbuf:	the kernel buffer
++ * @len:	length of user data
++ */
++struct request *blk_rq_map_kern(request_queue_t *q, int rw, void *kbuf,
++				unsigned int len, unsigned int gfp_mask)
++{
++	struct request *rq;
++	struct bio *bio;
++
++	if (len > (q->max_sectors << 9))
++		return ERR_PTR(-EINVAL);
++	if ((!len && kbuf) || (len && !kbuf))
++		return ERR_PTR(-EINVAL);
++
++	rq = blk_get_request(q, rw, gfp_mask);
++	if (!rq)
++		return ERR_PTR(-ENOMEM);
++
++	bio = bio_map_kern(q, kbuf, len, gfp_mask);
++	if (!IS_ERR(bio)) {
++		if (rw)
++			bio->bi_rw |= (1 << BIO_RW);
++		bio->bi_end_io = blk_rq_map_kern_endio;
++
++		rq->bio = rq->biotail = bio;
++		blk_rq_bio_prep(q, rq, bio);
++
++		rq->buffer = rq->data = NULL;
++		rq->data_len = len;
++		return rq;
++	}
++
++	/*
++	 * bio is the err-ptr
++	 */
++	blk_put_request(rq);
++	return (struct request *) bio;
++}
++
++EXPORT_SYMBOL(blk_rq_map_kern);
++
+ /**
+  * blk_execute_rq - insert a request into queue for execution
+  * @q:		queue to insert the request in
+diff --git a/fs/bio.c b/fs/bio.c
+index 3a1472acc361..707b9af2dd01 100644
+--- a/fs/bio.c
++++ b/fs/bio.c
+@@ -701,6 +701,71 @@ void bio_unmap_user(struct bio *bio)
+ 	bio_put(bio);
+ }
+ 
++static struct bio *__bio_map_kern(request_queue_t *q, void *data,
++				  unsigned int len, unsigned int gfp_mask)
++{
++	unsigned long kaddr = (unsigned long)data;
++	unsigned long end = (kaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
++	unsigned long start = kaddr >> PAGE_SHIFT;
++	const int nr_pages = end - start;
++	int offset, i;
++	struct bio *bio;
++
++	bio = bio_alloc(gfp_mask, nr_pages);
++	if (!bio)
++		return ERR_PTR(-ENOMEM);
++
++	offset = offset_in_page(kaddr);
++	for (i = 0; i < nr_pages; i++) {
++		unsigned int bytes = PAGE_SIZE - offset;
++
++		if (len <= 0)
++			break;
++
++		if (bytes > len)
++			bytes = len;
++
++		if (__bio_add_page(q, bio, virt_to_page(data), bytes,
++				   offset) < bytes)
++			break;
++
++		data += bytes;
++		len -= bytes;
++		offset = 0;
++	}
++
++	return bio;
++}
++
++/**
++ *	bio_map_kern	-	map kernel address into bio
++ *	@q: the request_queue_t for the bio
++ *	@data: pointer to buffer to map
++ *	@len: length in bytes
++ *	@gfp_mask: allocation flags for bio allocation
++ *
++ *	Map the kernel address into a bio suitable for io to a block
++ *	device. Returns an error pointer in case of error.
++ */
++struct bio *bio_map_kern(request_queue_t *q, void *data, unsigned int len,
++			 unsigned int gfp_mask)
++{
++	struct bio *bio;
++
++	bio = __bio_map_kern(q, data, len, gfp_mask);
++	if (IS_ERR(bio))
++		return bio;
++
++	if (bio->bi_size == len)
++		return bio;
++
++	/*
++	 * Don't support partial mappings.
++	 */
++	bio_put(bio);
++	return ERR_PTR(-EINVAL);
++}
++
+ /*
+  * bio_set_pages_dirty() and bio_check_pages_dirty() are support functions
+  * for performing direct-IO in BIOs.
+@@ -1088,6 +1153,7 @@ EXPORT_SYMBOL(bio_add_page);
+ EXPORT_SYMBOL(bio_get_nr_vecs);
+ EXPORT_SYMBOL(bio_map_user);
+ EXPORT_SYMBOL(bio_unmap_user);
++EXPORT_SYMBOL(bio_map_kern);
+ EXPORT_SYMBOL(bio_pair_release);
+ EXPORT_SYMBOL(bio_split);
+ EXPORT_SYMBOL(bio_split_pool);
+diff --git a/include/linux/bio.h b/include/linux/bio.h
+index 038022763f09..1dd2bc2e84ae 100644
+--- a/include/linux/bio.h
++++ b/include/linux/bio.h
+@@ -282,6 +282,8 @@ extern int bio_get_nr_vecs(struct block_device *);
+ extern struct bio *bio_map_user(struct request_queue *, struct block_device *,
+ 				unsigned long, unsigned int, int);
+ extern void bio_unmap_user(struct bio *);
++extern struct bio *bio_map_kern(struct request_queue *, void *, unsigned int,
++				unsigned int);
+ extern void bio_set_pages_dirty(struct bio *bio);
+ extern void bio_check_pages_dirty(struct bio *bio);
+ extern struct bio *bio_copy_user(struct request_queue *, unsigned long, unsigned int, int);
+diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
+index 4a99b76c5a33..67339bc5f6bc 100644
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -560,6 +560,8 @@ extern void blk_run_queue(request_queue_t *);
+ extern void blk_queue_activity_fn(request_queue_t *, activity_fn *, void *);
+ extern struct request *blk_rq_map_user(request_queue_t *, int, void __user *, unsigned int);
+ extern int blk_rq_unmap_user(struct request *, struct bio *, unsigned int);
++extern struct request *blk_rq_map_kern(request_queue_t *, int, void *,
++					unsigned int, unsigned int);
+ extern int blk_execute_rq(request_queue_t *, struct gendisk *, struct request *);
+ 
+ static inline request_queue_t *bdev_get_queue(struct block_device *bdev)

commit 69b528936b702d4c13ffa0d14215a029dc754e50
+Author: Mike Christie 
+Date:   Sun May 1 14:47:15 2005 -0500
+
+    [SCSI] call correct scsi_done function in scsi_dispatch_cmd
+    
+    scsi_dispatch_cmd currently calls scsi_done when the device is in the
+    SDEV_DEL state, but at this point the command has not had a timer added
+    to it (this is done a couple lines down) so scsi_done just returns and
+    the command is lost. The attached patch made against 2.6.12-rc3 calls
+    __scsi_done in this case so the comamnd will be returned upwards.
+    
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
+index 05d2bd075fd4..184bcaeaf812 100644
+--- a/drivers/scsi/scsi.c
++++ b/drivers/scsi/scsi.c
+@@ -542,7 +542,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
+ 		 * that the device is no longer present */
+ 		cmd->result = DID_NO_CONNECT << 16;
+ 		atomic_inc(&cmd->device->iorequest_cnt);
+-		scsi_done(cmd);
++		__scsi_done(cmd);
+ 		/* return 0 (because the command has been processed) */
+ 		goto out;
+ 	}

commit c4ea95d7cd08d9ffd7fa75e6c5e0332d596dd11e
+Author: Daniel Forrest 
+Date:   Tue Dec 2 15:59:42 2014 -0800
+
+    mm: fix anon_vma_clone() error treatment
+    
+    Andrew Morton noticed that the error return from anon_vma_clone() was
+    being dropped and replaced with -ENOMEM (which is not itself a bug
+    because the only error return value from anon_vma_clone() is -ENOMEM).
+    
+    I did an audit of callers of anon_vma_clone() and discovered an actual
+    bug where the error return was being lost.  In __split_vma(), between
+    Linux 3.11 and 3.12 the code was changed so the err variable is used
+    before the call to anon_vma_clone() and the default initial value of
+    -ENOMEM is overwritten.  So a failure of anon_vma_clone() will return
+    success since err at this point is now zero.
+    
+    Below is a patch which fixes this bug and also propagates the error
+    return value from anon_vma_clone() in all cases.
+    
+    Fixes: ef0855d334e1 ("mm: mempolicy: turn vma_set_policy() into vma_dup_policy()")
+    Signed-off-by: Daniel Forrest 
+    Reviewed-by: Michal Hocko 
+    Cc: Konstantin Khlebnikov 
+    Cc: Andrea Arcangeli 
+    Cc: Rik van Riel 
+    Cc: Tim Hartrick 
+    Cc: Hugh Dickins 
+    Cc: Michel Lespinasse 
+    Cc: Vlastimil Babka 
+    Cc:     [3.12+]
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/mm/mmap.c b/mm/mmap.c
+index 87e82b38453c..ae919891a087 100644
+--- a/mm/mmap.c
++++ b/mm/mmap.c
+@@ -776,8 +776,11 @@ again:			remove_next = 1 + (end > next->vm_end);
+ 		 * shrinking vma had, to cover any anon pages imported.
+ 		 */
+ 		if (exporter && exporter->anon_vma && !importer->anon_vma) {
+-			if (anon_vma_clone(importer, exporter))
+-				return -ENOMEM;
++			int error;
++
++			error = anon_vma_clone(importer, exporter);
++			if (error)
++				return error;
+ 			importer->anon_vma = exporter->anon_vma;
+ 		}
+ 	}
+@@ -2469,7 +2472,8 @@ static int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
+ 	if (err)
+ 		goto out_free_vma;
+ 
+-	if (anon_vma_clone(new, vma))
++	err = anon_vma_clone(new, vma);
++	if (err)
+ 		goto out_free_mpol;
+ 
+ 	if (new->vm_file)
+diff --git a/mm/rmap.c b/mm/rmap.c
+index 19886fb2f13a..3e4c7213210c 100644
+--- a/mm/rmap.c
++++ b/mm/rmap.c
+@@ -274,6 +274,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
+ {
+ 	struct anon_vma_chain *avc;
+ 	struct anon_vma *anon_vma;
++	int error;
+ 
+ 	/* Don't bother if the parent process has no anon_vma here. */
+ 	if (!pvma->anon_vma)
+@@ -283,8 +284,9 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
+ 	 * First, attach the new VMA to the parent VMA's anon_vmas,
+ 	 * so rmap can find non-COWed pages in child processes.
+ 	 */
+-	if (anon_vma_clone(vma, pvma))
+-		return -ENOMEM;
++	error = anon_vma_clone(vma, pvma);
++	if (error)
++		return error;
+ 
+ 	/* Then add our own anon_vma. */
+ 	anon_vma = anon_vma_alloc();

commit 331552925d17ffa2f5c676e282d4fd37c852d9e3
+Author: Pete Wyckoff 
+Date:   Tue Feb 26 13:27:53 2008 -0500
+
+    IB/fmr_pool: Flush all dirty FMRs from ib_fmr_pool_flush()
+    
+    Commit a3cd7d90 ("IB/fmr_pool: ib_fmr_pool_flush() should flush all
+    dirty FMRs") caused a regression for iSER and was reverted in
+    e5507736.
+    
+    This change attempts to redo the original patch so that all used FMR
+    entries are flushed when ib_flush_fmr_pool() is called without
+    affecting the normal FMR pool cleaning thread.  Simply move used
+    entries from the clean list onto the dirty list in ib_flush_fmr_pool()
+    before letting the cleanup thread do its job.
+    
+    Signed-off-by: Pete Wyckoff 
+    Signed-off-by: Roland Dreier 
+
+diff --git a/drivers/infiniband/core/fmr_pool.c b/drivers/infiniband/core/fmr_pool.c
+index 4044fdf62cc2..06d502c06a4d 100644
+--- a/drivers/infiniband/core/fmr_pool.c
++++ b/drivers/infiniband/core/fmr_pool.c
+@@ -398,8 +398,23 @@ EXPORT_SYMBOL(ib_destroy_fmr_pool);
+  */
+ int ib_flush_fmr_pool(struct ib_fmr_pool *pool)
+ {
+-	int serial = atomic_inc_return(&pool->req_ser);
++	int serial;
++	struct ib_pool_fmr *fmr, *next;
++
++	/*
++	 * The free_list holds FMRs that may have been used
++	 * but have not been remapped enough times to be dirty.
++	 * Put them on the dirty list now so that the cleanup
++	 * thread will reap them too.
++	 */
++	spin_lock_irq(&pool->pool_lock);
++	list_for_each_entry_safe(fmr, next, &pool->free_list, list) {
++		if (fmr->remap_count > 0)
++			list_move(&fmr->list, &pool->dirty_list);
++	}
++	spin_unlock_irq(&pool->pool_lock);
+ 
++	serial = atomic_inc_return(&pool->req_ser);
+ 	wake_up_process(pool->thread);
+ 
+ 	if (wait_event_interruptible(pool->force_wait,

commit 35fb5340e3de5dff86923eb0cded748c3a6e05e7
+Author: Pete Wyckoff 
+Date:   Tue Feb 26 13:27:31 2008 -0500
+
+    Revert "IB/fmr_pool: ib_fmr_pool_flush() should flush all dirty FMRs"
+    
+    This reverts commit a3cd7d9070be417a21905c997ee32d756d999b38.
+    
+    The original commit breaks iSER reliably, making it complain:
+    
+        iser: iser_reg_page_vec:ib_fmr_pool_map_phys failed: -11
+    
+    The FMR cleanup thread runs ib_fmr_batch_release() as dirty entries
+    build up.  This commit causes clean but used FMR entries also to be
+    purged.  During that process, another thread can see that there are no
+    free FMRs and fail, even though there should always have been enough
+    available.
+    
+    Signed-off-by: Pete Wyckoff 
+    Signed-off-by: Roland Dreier 
+
+diff --git a/drivers/infiniband/core/fmr_pool.c b/drivers/infiniband/core/fmr_pool.c
+index 7f00347364f7..4044fdf62cc2 100644
+--- a/drivers/infiniband/core/fmr_pool.c
++++ b/drivers/infiniband/core/fmr_pool.c
+@@ -139,7 +139,7 @@ static inline struct ib_pool_fmr *ib_fmr_cache_lookup(struct ib_fmr_pool *pool,
+ static void ib_fmr_batch_release(struct ib_fmr_pool *pool)
+ {
+ 	int                 ret;
+-	struct ib_pool_fmr *fmr, *next;
++	struct ib_pool_fmr *fmr;
+ 	LIST_HEAD(unmap_list);
+ 	LIST_HEAD(fmr_list);
+ 
+@@ -158,20 +158,6 @@ static void ib_fmr_batch_release(struct ib_fmr_pool *pool)
+ #endif
+ 	}
+ 
+-	/*
+-	 * The free_list may hold FMRs that have been put there
+-	 * because they haven't reached the max_remap count.
+-	 * Invalidate their mapping as well.
+-	 */
+-	list_for_each_entry_safe(fmr, next, &pool->free_list, list) {
+-		if (fmr->remap_count == 0)
+-			continue;
+-		hlist_del_init(&fmr->cache_node);
+-		fmr->remap_count = 0;
+-		list_add_tail(&fmr->fmr->list, &fmr_list);
+-		list_move(&fmr->list, &unmap_list);
+-	}
+-
+ 	list_splice(&pool->dirty_list, &unmap_list);
+ 	INIT_LIST_HEAD(&pool->dirty_list);
+ 	pool->dirty_len = 0;
+@@ -384,6 +370,11 @@ void ib_destroy_fmr_pool(struct ib_fmr_pool *pool)
+ 
+ 	i = 0;
+ 	list_for_each_entry_safe(fmr, tmp, &pool->free_list, list) {
++		if (fmr->remap_count) {
++			INIT_LIST_HEAD(&fmr_list);
++			list_add_tail(&fmr->fmr->list, &fmr_list);
++			ib_unmap_fmr(&fmr_list);
++		}
+ 		ib_dealloc_fmr(fmr->fmr);
+ 		list_del(&fmr->list);
+ 		kfree(fmr);

commit 482eb689169948e9f4966fbae6be4d6bc0bfa818
+Author: Pete Wyckoff 
+Date:   Tue Jan 1 10:23:02 2008 -0500
+
+    block: allow queue dma_alignment of zero
+    
+    Let queue_dma_alignment return 0 if it was specifically set to 0.
+    This permits devices with no particular alignment restrictions to
+    use arbitrary user space buffers without copying.
+    
+    Signed-off-by: Pete Wyckoff 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
+index 49b7a4c31a6d..c7a3ab575c24 100644
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -836,12 +836,7 @@ static inline int bdev_hardsect_size(struct block_device *bdev)
+ 
+ static inline int queue_dma_alignment(struct request_queue *q)
+ {
+-	int retval = 511;
+-
+-	if (q && q->dma_alignment)
+-		retval = q->dma_alignment;
+-
+-	return retval;
++	return q ? q->dma_alignment : 511;
+ }
+ 
+ /* assumes size > 256 */

commit b22f687dd28a7a8886b918294b4d558ef175c07d
+Author: Pete Wyckoff 
+Date:   Tue Mar 13 16:53:28 2007 -0400
+
+    [SCSI] set resid in scsi_io_completion() even for check condition
+    
+    Some targets can return both valid data and sense information.
+    Always update the request data_len from the SCSI command residual.
+    Callers should interpret sense data to determine what parts of the
+    data are valid in case of a CHECK CONDITION status.
+    
+    Signed-off-by: Pete Wyckoff 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index 5f955707d902..be8e6558b89e 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -848,8 +848,8 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
+ 				memcpy(req->sense, cmd->sense_buffer,  len);
+ 				req->sense_len = len;
+ 			}
+-		} else
+-			req->data_len = cmd->resid;
++		}
++		req->data_len = cmd->resid;
+ 	}
+ 
+ 	/*

commit d6e24d1c8a197cc9c2a1568224474f4b7af50803
+Author: Pete Wyckoff 
+Date:   Wed Nov 8 15:58:32 2006 -0600
+
+    [SCSI] iscsi: add newlines to debug messages
+    
+    Some messages from debug_scsi do not have trailing newlines,
+    making console messages difficult to read.  Fix that.
+    
+    Signed-off-by: Pete Wyckoff 
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index 2865ebd557ef..5d8862189485 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -975,13 +975,13 @@ int iscsi_eh_host_reset(struct scsi_cmnd *sc)
+ 	if (session->state == ISCSI_STATE_TERMINATE) {
+ failed:
+ 		debug_scsi("failing host reset: session terminated "
+-			   "[CID %d age %d]", conn->id, session->age);
++			   "[CID %d age %d]\n", conn->id, session->age);
+ 		spin_unlock_bh(&session->lock);
+ 		return FAILED;
+ 	}
+ 
+ 	if (sc->SCp.phase == session->age) {
+-		debug_scsi("failing connection CID %d due to SCSI host reset",
++		debug_scsi("failing connection CID %d due to SCSI host reset\n",
+ 			   conn->id);
+ 		fail_session = 1;
+ 	}
+@@ -1054,7 +1054,8 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc,
+ 				     NULL, 0);
+ 	if (rc) {
+ 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+-		debug_scsi("abort sent failure [itt 0x%x] %d", ctask->itt, rc);
++		debug_scsi("abort sent failure [itt 0x%x] %d\n", ctask->itt,
++		           rc);
+ 		return rc;
+ 	}
+ 
+@@ -1071,7 +1072,7 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc,
+ 		conn->tmabort_timer.function = iscsi_tmabort_timedout;
+ 		conn->tmabort_timer.data = (unsigned long)ctask;
+ 		add_timer(&conn->tmabort_timer);
+-		debug_scsi("abort set timeout [itt 0x%x]", ctask->itt);
++		debug_scsi("abort set timeout [itt 0x%x]\n", ctask->itt);
+ 	}
+ 	spin_unlock_bh(&session->lock);
+ 	mutex_unlock(&conn->xmitmutex);

commit 534284a09b3f58cd92acd0652b7267ee142932ba
+Author: Pete Wyckoff 
+Date:   Wed Nov 8 15:58:31 2006 -0600
+
+    [SCSI] iscsi: always release crypto
+    
+    Unconditionally free crypto state, as it is always allocated during
+    TCP connection creation.  Without this, crypto structures leak and
+    crc32c module refcounts grow as connections are created and
+    destroyed.
+    
+    Signed-off-by: Pete Wyckoff 
+    Signed-off-by: Mike Christie 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 0a9dbc59663f..c0b8b33e935c 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -1816,21 +1816,14 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn)
+ {
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+-	int digest = 0;
+-
+-	if (conn->hdrdgst_en || conn->datadgst_en)
+-		digest = 1;
+ 
+ 	iscsi_tcp_release_conn(conn);
+ 	iscsi_conn_teardown(cls_conn);
+ 
+-	/* now free tcp_conn */
+-	if (digest) {
+-		if (tcp_conn->tx_hash.tfm)
+-			crypto_free_hash(tcp_conn->tx_hash.tfm);
+-		if (tcp_conn->rx_hash.tfm)
+-			crypto_free_hash(tcp_conn->rx_hash.tfm);
+-	}
++	if (tcp_conn->tx_hash.tfm)
++		crypto_free_hash(tcp_conn->tx_hash.tfm);
++	if (tcp_conn->rx_hash.tfm)
++		crypto_free_hash(tcp_conn->rx_hash.tfm);
+ 
+ 	kfree(tcp_conn);
+ }

commit d2e9117c7aa9544d910634e17e3519fd67155229
+Author: John Heffner 
+Date:   Wed Sep 12 10:44:19 2007 +0200
+
+    [NET]: Change type of owner in sock_lock_t to int, rename
+    
+    The type of owner in sock_lock_t is currently (struct sock_iocb *),
+    presumably for historical reasons.  It is never used as this type, only
+    tested as NULL or set to (void *)1.  For clarity, this changes it to type
+    int, and renames to owned, to avoid any possible type casting errors.
+    
+    Signed-off-by: John Heffner 
+    Signed-off-by: David S. Miller 
+
+diff --git a/include/net/sock.h b/include/net/sock.h
+index 802c670ba820..5ed9fa42b6e8 100644
+--- a/include/net/sock.h
++++ b/include/net/sock.h
+@@ -76,10 +76,9 @@
+  * between user contexts and software interrupt processing, whereas the
+  * mini-semaphore synchronizes multiple users amongst themselves.
+  */
+-struct sock_iocb;
+ typedef struct {
+ 	spinlock_t		slock;
+-	struct sock_iocb	*owner;
++	int			owned;
+ 	wait_queue_head_t	wq;
+ 	/*
+ 	 * We express the mutex-alike socket_lock semantics
+@@ -737,7 +736,7 @@ static inline int sk_stream_wmem_schedule(struct sock *sk, int size)
+  * Since ~2.3.5 it is also exclusive sleep lock serializing
+  * accesses from user process context.
+  */
+-#define sock_owned_by_user(sk)	((sk)->sk_lock.owner)
++#define sock_owned_by_user(sk)	((sk)->sk_lock.owned)
+ 
+ /*
+  * Macro so as to not evaluate some arguments when
+@@ -748,7 +747,7 @@ static inline int sk_stream_wmem_schedule(struct sock *sk, int size)
+  */
+ #define sock_lock_init_class_and_name(sk, sname, skey, name, key) 	\
+ do {									\
+-	sk->sk_lock.owner = NULL;					\
++	sk->sk_lock.owned = 0;					\
+ 	init_waitqueue_head(&sk->sk_lock.wq);				\
+ 	spin_lock_init(&(sk)->sk_lock.slock);				\
+ 	debug_check_no_locks_freed((void *)&(sk)->sk_lock,		\
+diff --git a/net/core/sock.c b/net/core/sock.c
+index 190de61cd648..beb924c248e8 100644
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -1585,9 +1585,9 @@ void fastcall lock_sock_nested(struct sock *sk, int subclass)
+ {
+ 	might_sleep();
+ 	spin_lock_bh(&sk->sk_lock.slock);
+-	if (sk->sk_lock.owner)
++	if (sk->sk_lock.owned)
+ 		__lock_sock(sk);
+-	sk->sk_lock.owner = (void *)1;
++	sk->sk_lock.owned = 1;
+ 	spin_unlock(&sk->sk_lock.slock);
+ 	/*
+ 	 * The sk_lock has mutex_lock() semantics here:
+@@ -1608,7 +1608,7 @@ void fastcall release_sock(struct sock *sk)
+ 	spin_lock_bh(&sk->sk_lock.slock);
+ 	if (sk->sk_backlog.tail)
+ 		__release_sock(sk);
+-	sk->sk_lock.owner = NULL;
++	sk->sk_lock.owned = 0;
+ 	if (waitqueue_active(&sk->sk_lock.wq))
+ 		wake_up(&sk->sk_lock.wq);
+ 	spin_unlock_bh(&sk->sk_lock.slock);

commit 02b3d34631831a19ee691516e233756b270eac6d
+Author: John Heffner 
+Date:   Wed Sep 12 10:42:12 2007 +0200
+
+    [NET] Cleanup: Use sock_owned_by_user() macro
+    
+    Changes asserts in sunrpc to use sock_owned_by_user() macro instead of
+    referencing sock_lock.owner directly.
+    
+    Signed-off-by: John Heffner 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
+index 406b3e687952..c75bffeb89eb 100644
+--- a/net/sunrpc/svcsock.c
++++ b/net/sunrpc/svcsock.c
+@@ -104,7 +104,7 @@ static struct lock_class_key svc_slock_key[2];
+ static inline void svc_reclassify_socket(struct socket *sock)
+ {
+ 	struct sock *sk = sock->sk;
+-	BUG_ON(sk->sk_lock.owner != NULL);
++	BUG_ON(sock_owned_by_user(sk));
+ 	switch (sk->sk_family) {
+ 	case AF_INET:
+ 		sock_lock_init_class_and_name(sk, "slock-AF_INET-NFSD",
+diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
+index 4ae7eed7f617..282efd447a61 100644
+--- a/net/sunrpc/xprtsock.c
++++ b/net/sunrpc/xprtsock.c
+@@ -1186,7 +1186,7 @@ static struct lock_class_key xs_slock_key[2];
+ static inline void xs_reclassify_socket(struct socket *sock)
+ {
+ 	struct sock *sk = sock->sk;
+-	BUG_ON(sk->sk_lock.owner != NULL);
++	BUG_ON(sock_owned_by_user(sk));
+ 	switch (sk->sk_family) {
+ 	case AF_INET:
+ 		sock_lock_init_class_and_name(sk, "slock-AF_INET-NFS",

commit 628a5c561890a9a9a74dea017873530584aab06e
+Author: John Heffner 
+Date:   Fri Apr 20 15:53:27 2007 -0700
+
+    [INET]: Add IP(V6)_PMTUDISC_RPOBE
+    
+    Add IP(V6)_PMTUDISC_PROBE value for IP(V6)_MTU_DISCOVER.  This option forces
+    us not to fragment, but does not make use of the kernel path MTU discovery.
+    That is, it allows for user-mode MTU probing (or, packetization-layer path
+    MTU discovery).  This is particularly useful for diagnostic utilities, like
+    traceroute/tracepath.
+    
+    Signed-off-by: John Heffner 
+    Signed-off-by: David S. Miller 
+
+diff --git a/include/linux/in.h b/include/linux/in.h
+index 1912e7c0bc26..3975cbf52f20 100644
+--- a/include/linux/in.h
++++ b/include/linux/in.h
+@@ -83,6 +83,7 @@ struct in_addr {
+ #define IP_PMTUDISC_DONT		0	/* Never send DF frames */
+ #define IP_PMTUDISC_WANT		1	/* Use per route hints	*/
+ #define IP_PMTUDISC_DO			2	/* Always DF		*/
++#define IP_PMTUDISC_PROBE		3       /* Ignore dst pmtu      */
+ 
+ #define IP_MULTICAST_IF			32
+ #define IP_MULTICAST_TTL 		33
+diff --git a/include/linux/in6.h b/include/linux/in6.h
+index 4e8350ae8869..d559fac4a26d 100644
+--- a/include/linux/in6.h
++++ b/include/linux/in6.h
+@@ -179,6 +179,7 @@ struct in6_flowlabel_req
+ #define IPV6_PMTUDISC_DONT		0
+ #define IPV6_PMTUDISC_WANT		1
+ #define IPV6_PMTUDISC_DO		2
++#define IPV6_PMTUDISC_PROBE		3
+ 
+ /* Flowlabel */
+ #define IPV6_FLOWLABEL_MGR	32
+diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
+index 34606eff8a05..534650cad3a8 100644
+--- a/net/ipv4/ip_output.c
++++ b/net/ipv4/ip_output.c
+@@ -189,6 +189,14 @@ static inline int ip_finish_output2(struct sk_buff *skb)
+ 	return -EINVAL;
+ }
+ 
++static inline int ip_skb_dst_mtu(struct sk_buff *skb)
++{
++	struct inet_sock *inet = skb->sk ? inet_sk(skb->sk) : NULL;
++
++	return (inet && inet->pmtudisc == IP_PMTUDISC_PROBE) ?
++	       skb->dst->dev->mtu : dst_mtu(skb->dst);
++}
++
+ static inline int ip_finish_output(struct sk_buff *skb)
+ {
+ #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM)
+@@ -198,7 +206,7 @@ static inline int ip_finish_output(struct sk_buff *skb)
+ 		return dst_output(skb);
+ 	}
+ #endif
+-	if (skb->len > dst_mtu(skb->dst) && !skb_is_gso(skb))
++	if (skb->len > ip_skb_dst_mtu(skb) && !skb_is_gso(skb))
+ 		return ip_fragment(skb, ip_finish_output2);
+ 	else
+ 		return ip_finish_output2(skb);
+@@ -422,7 +430,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
+ 	if (unlikely((iph->frag_off & htons(IP_DF)) && !skb->local_df)) {
+ 		IP_INC_STATS(IPSTATS_MIB_FRAGFAILS);
+ 		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
+-			  htonl(dst_mtu(&rt->u.dst)));
++			  htonl(ip_skb_dst_mtu(skb)));
+ 		kfree_skb(skb);
+ 		return -EMSGSIZE;
+ 	}
+@@ -787,7 +795,9 @@ int ip_append_data(struct sock *sk,
+ 			inet->cork.addr = ipc->addr;
+ 		}
+ 		dst_hold(&rt->u.dst);
+-		inet->cork.fragsize = mtu = dst_mtu(rt->u.dst.path);
++		inet->cork.fragsize = mtu = inet->pmtudisc == IP_PMTUDISC_PROBE ?
++					    rt->u.dst.dev->mtu :
++					    dst_mtu(rt->u.dst.path);
+ 		inet->cork.rt = rt;
+ 		inet->cork.length = 0;
+ 		sk->sk_sndmsg_page = NULL;
+@@ -1203,13 +1213,13 @@ int ip_push_pending_frames(struct sock *sk)
+ 	 * to fragment the frame generated here. No matter, what transforms
+ 	 * how transforms change size of the packet, it will come out.
+ 	 */
+-	if (inet->pmtudisc != IP_PMTUDISC_DO)
++	if (inet->pmtudisc < IP_PMTUDISC_DO)
+ 		skb->local_df = 1;
+ 
+ 	/* DF bit is set when we want to see DF on outgoing frames.
+ 	 * If local_df is set too, we still allow to fragment this frame
+ 	 * locally. */
+-	if (inet->pmtudisc == IP_PMTUDISC_DO ||
++	if (inet->pmtudisc >= IP_PMTUDISC_DO ||
+ 	    (skb->len <= dst_mtu(&rt->u.dst) &&
+ 	     ip_dont_fragment(sk, &rt->u.dst)))
+ 		df = htons(IP_DF);
+diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
+index c199d2311731..4d544573f48a 100644
+--- a/net/ipv4/ip_sockglue.c
++++ b/net/ipv4/ip_sockglue.c
+@@ -542,7 +542,7 @@ static int do_ip_setsockopt(struct sock *sk, int level,
+ 		inet->hdrincl = val ? 1 : 0;
+ 		break;
+ 	case IP_MTU_DISCOVER:
+-		if (val<0 || val>2)
++		if (val<0 || val>3)
+ 			goto e_inval;
+ 		inet->pmtudisc = val;
+ 		break;
+diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
+index 5a5b7d4ad31c..f508171bab73 100644
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -137,9 +137,17 @@ static int ip6_output2(struct sk_buff *skb)
+ 	return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb,NULL, skb->dev,ip6_output_finish);
+ }
+ 
++static inline int ip6_skb_dst_mtu(struct sk_buff *skb)
++{
++	struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL;
++
++	return (np && np->pmtudisc == IPV6_PMTUDISC_PROBE) ?
++	       skb->dst->dev->mtu : dst_mtu(skb->dst);
++}
++
+ int ip6_output(struct sk_buff *skb)
+ {
+-	if ((skb->len > dst_mtu(skb->dst) && !skb_is_gso(skb)) ||
++	if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) ||
+ 				dst_allfrag(skb->dst))
+ 		return ip6_fragment(skb, ip6_output2);
+ 	else
+@@ -566,7 +574,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
+ 	hlen = ip6_find_1stfragopt(skb, &prevhdr);
+ 	nexthdr = *prevhdr;
+ 
+-	mtu = dst_mtu(&rt->u.dst);
++	mtu = ip6_skb_dst_mtu(skb);
+ 
+ 	/* We must not fragment if the socket is set to force MTU discovery
+ 	 * or if the skb it not generated by a local socket.  (This last
+@@ -1063,7 +1071,8 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
+ 		inet->cork.fl = *fl;
+ 		np->cork.hop_limit = hlimit;
+ 		np->cork.tclass = tclass;
+-		mtu = dst_mtu(rt->u.dst.path);
++		mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ?
++		      rt->u.dst.dev->mtu : dst_mtu(rt->u.dst.path);
+ 		if (np->frag_size < mtu) {
+ 			if (np->frag_size)
+ 				mtu = np->frag_size;
+diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
+index da930fa089c9..aa3d07c52a8f 100644
+--- a/net/ipv6/ipv6_sockglue.c
++++ b/net/ipv6/ipv6_sockglue.c
+@@ -694,7 +694,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
+ 		retv = ip6_ra_control(sk, val, NULL);
+ 		break;
+ 	case IPV6_MTU_DISCOVER:
+-		if (val<0 || val>2)
++		if (val<0 || val>3)
+ 			goto e_inval;
+ 		np->pmtudisc = val;
+ 		retv = 0;

commit b881ef7603230550aa0150b22af94089f07ab00d
+Author: John Heffner 
+Date:   Fri Apr 20 15:52:39 2007 -0700
+
+    [IPV6]: MTU discovery check in ip6_fragment()
+    
+    Adds a check in ip6_fragment() mirroring ip_fragment() for packets
+    that we can't fragment, and sends an ICMP Packet Too Big message
+    in response.
+    
+    Signed-off-by: John Heffner 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
+index 4cfdad4e8356..5a5b7d4ad31c 100644
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -567,6 +567,19 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
+ 	nexthdr = *prevhdr;
+ 
+ 	mtu = dst_mtu(&rt->u.dst);
++
++	/* We must not fragment if the socket is set to force MTU discovery
++	 * or if the skb it not generated by a local socket.  (This last
++	 * check should be redundant, but it's free.)
++	 */
++	if (!np || np->pmtudisc >= IPV6_PMTUDISC_DO) {
++		skb->dev = skb->dst->dev;
++		icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev);
++		IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS);
++		kfree_skb(skb);
++		return -EMSGSIZE;
++	}
++
+ 	if (np && np->frag_size < mtu) {
+ 		if (np->frag_size)
+ 			mtu = np->frag_size;

commit 9af3912ec9e30509b76cb376abb65a4d8af27df3
+Author: John Heffner 
+Date:   Sun Mar 25 23:32:29 2007 -0700
+
+    [NET] Move DF check to ip_forward
+    
+    Do fragmentation check in ip_forward, similar to ipv6 forwarding.
+    
+    Signed-off-by: John Heffner 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c
+index 467ebedb99ba..61b30d100676 100644
+--- a/net/ipv4/ip_forward.c
++++ b/net/ipv4/ip_forward.c
+@@ -85,6 +85,14 @@ int ip_forward(struct sk_buff *skb)
+ 	if (opt->is_strictroute && rt->rt_dst != rt->rt_gateway)
+ 		goto sr_failed;
+ 
++	if (unlikely(skb->len > dst_mtu(&rt->u.dst) &&
++	             (ip_hdr(skb)->frag_off & htons(IP_DF))) && !skb->local_df) {
++		IP_INC_STATS(IPSTATS_MIB_FRAGFAILS);
++		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
++			  htonl(dst_mtu(&rt->u.dst)));
++		goto drop;
++	}
++
+ 	/* We are about to mangle packet. Copy it! */
+ 	if (skb_cow(skb, LL_RESERVED_SPACE(rt->u.dst.dev)+rt->u.dst.header_len))
+ 		goto drop;

commit 886236c1247ab5e2ad9c73f6e9a652e3ae3c8b07
+Author: John Heffner 
+Date:   Sun Mar 25 19:21:45 2007 -0700
+
+    [TCP]: Add RFC3742 Limited Slow-Start, controlled by variable sysctl_tcp_max_ssthresh.
+    
+    Signed-off-by: John Heffner 
+    Signed-off-by: David S. Miller 
+
+diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
+index 9a8970bf99a6..98e0fd241a25 100644
+--- a/include/linux/sysctl.h
++++ b/include/linux/sysctl.h
+@@ -438,6 +438,7 @@ enum
+ 	NET_CIPSOV4_RBM_STRICTVALID=121,
+ 	NET_TCP_AVAIL_CONG_CONTROL=122,
+ 	NET_TCP_ALLOWED_CONG_CONTROL=123,
++	NET_TCP_MAX_SSTHRESH=124,
+ };
+ 
+ enum {
+diff --git a/include/net/tcp.h b/include/net/tcp.h
+index 7fd6b77519c3..6d09f5085f6a 100644
+--- a/include/net/tcp.h
++++ b/include/net/tcp.h
+@@ -230,6 +230,7 @@ extern int sysctl_tcp_mtu_probing;
+ extern int sysctl_tcp_base_mss;
+ extern int sysctl_tcp_workaround_signed_windows;
+ extern int sysctl_tcp_slow_start_after_idle;
++extern int sysctl_tcp_max_ssthresh;
+ 
+ extern atomic_t tcp_memory_allocated;
+ extern atomic_t tcp_sockets_allocated;
+diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
+index 0aa304711a96..d68effe98e8d 100644
+--- a/net/ipv4/sysctl_net_ipv4.c
++++ b/net/ipv4/sysctl_net_ipv4.c
+@@ -803,6 +803,14 @@ ctl_table ipv4_table[] = {
+ 		.proc_handler   = &proc_allowed_congestion_control,
+ 		.strategy	= &strategy_allowed_congestion_control,
+ 	},
++	{
++		.ctl_name	= NET_TCP_MAX_SSTHRESH,
++		.procname	= "tcp_max_ssthresh",
++		.data		= &sysctl_tcp_max_ssthresh,
++		.maxlen		= sizeof(int),
++		.mode		= 0644,
++		.proc_handler	= &proc_dointvec,
++	},
+ 	{ .ctl_name = 0 }
+ };
+ 
+diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
+index 34ae3f13483a..ccd88407e0cd 100644
+--- a/net/ipv4/tcp_cong.c
++++ b/net/ipv4/tcp_cong.c
+@@ -12,6 +12,8 @@
+ #include 
+ #include 
+ 
++int sysctl_tcp_max_ssthresh = 0;
++
+ static DEFINE_SPINLOCK(tcp_cong_list_lock);
+ static LIST_HEAD(tcp_cong_list);
+ 
+@@ -274,10 +276,13 @@ int tcp_set_congestion_control(struct sock *sk, const char *name)
+ 
+ 
+ /*
+- * Linear increase during slow start
++ * Slow start (exponential increase) with
++ * RFC3742 Limited Slow Start (fast linear increase) support.
+  */
+ void tcp_slow_start(struct tcp_sock *tp)
+ {
++	int cnt = 0;
++
+ 	if (sysctl_tcp_abc) {
+ 		/* RFC3465: Slow Start
+ 		 * TCP sender SHOULD increase cwnd by the number of
+@@ -286,17 +291,25 @@ void tcp_slow_start(struct tcp_sock *tp)
+ 		 */
+ 		if (tp->bytes_acked < tp->mss_cache)
+ 			return;
+-
+-		/* We MAY increase by 2 if discovered delayed ack */
+-		if (sysctl_tcp_abc > 1 && tp->bytes_acked >= 2*tp->mss_cache) {
+-			if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+-				tp->snd_cwnd++;
+-		}
+ 	}
++
++	if (sysctl_tcp_max_ssthresh > 0 &&
++	    tp->snd_cwnd > sysctl_tcp_max_ssthresh)
++		cnt += sysctl_tcp_max_ssthresh>>1;
++	else
++		cnt += tp->snd_cwnd;
++
++	/* RFC3465: We MAY increase by 2 if discovered delayed ack */
++	if (sysctl_tcp_abc > 1 && tp->bytes_acked >= 2*tp->mss_cache)
++		cnt <<= 1;
+ 	tp->bytes_acked = 0;
+ 
+-	if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+-		tp->snd_cwnd++;
++	tp->snd_cwnd_cnt += cnt;
++	while (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
++		tp->snd_cwnd_cnt -= tp->snd_cwnd;
++		if (tp->snd_cwnd < tp->snd_cwnd_clamp)
++			tp->snd_cwnd++;
++	}
+ }
+ EXPORT_SYMBOL_GPL(tcp_slow_start);
+ 

commit 84565070e442583ec67fb08a5962c80203e491c3
+Author: John Heffner 
+Date:   Mon Apr 2 13:56:32 2007 -0700
+
+    [TCP]: Do receiver-side SWS avoidance for rcvbuf < MSS.
+    
+    Signed-off-by: John Heffner 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
+index dc151139b5af..688b95594f2e 100644
+--- a/net/ipv4/tcp_output.c
++++ b/net/ipv4/tcp_output.c
+@@ -1607,6 +1607,9 @@ u32 __tcp_select_window(struct sock *sk)
+ 		 */
+ 		if (window <= free_space - mss || window > free_space)
+ 			window = (free_space/mss)*mss;
++		else if (mss == full_space &&
++		         free_space > window + full_space/2)
++			window = free_space;
+ 	}
+ 
+ 	return window;

commit 53cdcc04c1e85d4e423b2822b66149b6f2e52c2c
+Author: John Heffner 
+Date:   Fri Mar 16 15:04:03 2007 -0700
+
+    [TCP]: Fix tcp_mem[] initialization.
+    
+    Change tcp_mem initialization function.  The fraction of total memory
+    is now a continuous function of memory size, and independent of page
+    size.
+    
+    Signed-off-by: John Heffner 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
+index 74c4d103ebc2..3834b10b5115 100644
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -2458,11 +2458,18 @@ void __init tcp_init(void)
+ 		sysctl_max_syn_backlog = 128;
+ 	}
+ 
+-	/* Allow no more than 3/4 kernel memory (usually less) allocated to TCP */
+-	sysctl_tcp_mem[0] = (1536 / sizeof (struct inet_bind_hashbucket)) << order;
+-	sysctl_tcp_mem[1] = sysctl_tcp_mem[0] * 4 / 3;
++	/* Set the pressure threshold to be a fraction of global memory that
++	 * is up to 1/2 at 256 MB, decreasing toward zero with the amount of
++	 * memory, with a floor of 128 pages.
++	 */
++	limit = min(nr_all_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT);
++	limit = (limit * (nr_all_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11);
++	limit = max(limit, 128UL);
++	sysctl_tcp_mem[0] = limit / 4 * 3;
++	sysctl_tcp_mem[1] = limit;
+ 	sysctl_tcp_mem[2] = sysctl_tcp_mem[0] * 2;
+ 
++	/* Set per-socket limits to no more than 1/128 the pressure threshold */
+ 	limit = ((unsigned long)sysctl_tcp_mem[1]) << (PAGE_SHIFT - 7);
+ 	max_share = min(4UL*1024*1024, limit);
+ 

commit 71599cd1c381d1b5f58c35653ac1d3627c6276db
+Author: John Heffner 
+Date:   Tue Feb 27 10:03:56 2007 -0800
+
+    [TCP]: Document several sysctls.
+    
+    This adds documentation for tcp_moderate_rcvbuf, tcp_no_metrics_save,
+    tcp_base_mss, and tcp_mtu_probing.
+    
+    Signed-off-by: John Heffner 
+    Signed-off-by: David S. Miller 
+
+diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
+index a0f6842368c3..d3aae1f9b4c1 100644
+--- a/Documentation/networking/ip-sysctl.txt
++++ b/Documentation/networking/ip-sysctl.txt
+@@ -147,6 +147,11 @@ tcp_available_congestion_control - STRING
+ 	More congestion control algorithms may be available as modules,
+ 	but not loaded.
+ 
++tcp_base_mss - INTEGER
++	The initial value of search_low to be used by Packetization Layer
++	Path MTU Discovery (MTU probing).  If MTU probing is enabled,
++	this is the inital MSS used by the connection.
++
+ tcp_congestion_control - STRING
+ 	Set the congestion control algorithm to be used for new
+ 	connections. The algorithm "reno" is always available, but
+@@ -243,6 +248,27 @@ tcp_mem - vector of 3 INTEGERs: min, pressure, max
+ 	Defaults are calculated at boot time from amount of available
+ 	memory.
+ 
++tcp_moderate_rcvbuf - BOOLEAN
++	If set, TCP performs receive buffer autotuning, attempting to
++	automatically size the buffer (no greater than tcp_rmem[2]) to
++	match the size required by the path for full throughput.  Enabled by
++	default.
++
++tcp_mtu_probing - INTEGER
++	Controls TCP Packetization-Layer Path MTU Discovery.  Takes three
++	values:
++	  0 - Disabled
++	  1 - Disabled by default, enabled when an ICMP black hole detected
++	  2 - Always enabled, use initial MSS of tcp_base_mss.
++
++tcp_no_metrics_save - BOOLEAN
++	By default, TCP saves various connection metrics in the route cache
++	when the connection closes, so that connections established in the
++	near future can use these to set initial conditions.  Usually, this
++	increases overall performance, but may sometimes cause performance
++	degredation.  If set, TCP will not cache metrics on closing
++	connections.
++
+ tcp_orphan_retries - INTEGER
+ 	How may times to retry before killing TCP connection, closed
+ 	by our side. Default value 7 corresponds to ~50sec-16min

commit 104439a8876a98eac1b6593907a3c7bc51e362fe
+Author: John Heffner 
+Date:   Mon Feb 5 17:53:11 2007 -0800
+
+    [TCP]: Don't apply FIN exception to full TSO segments.
+    
+    Signed-off-by: John Heffner 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
+index 975f4472af29..58b7111523f4 100644
+--- a/net/ipv4/tcp_output.c
++++ b/net/ipv4/tcp_output.c
+@@ -965,7 +965,8 @@ static inline unsigned int tcp_cwnd_test(struct tcp_sock *tp, struct sk_buff *sk
+ 	u32 in_flight, cwnd;
+ 
+ 	/* Don't be strict about the congestion window for the final FIN.  */
+-	if (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN)
++	if ((TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) &&
++	    tcp_skb_pcount(skb) == 1)
+ 		return 1;
+ 
+ 	in_flight = tcp_packets_in_flight(tp);

commit 52bf376c63eebe72e862a1a6e713976b038c3f50
+Author: John Heffner 
+Date:   Tue Nov 14 20:25:17 2006 -0800
+
+    [TCP]: Fix up sysctl_tcp_mem initialization.
+    
+    Fix up tcp_mem initial settings to take into account the size of the
+    hash entries (different on SMP and non-SMP systems).
+    
+    Signed-off-by: John Heffner 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
+index 4322318ab332..c05e8edaf544 100644
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -2316,9 +2316,10 @@ void __init tcp_init(void)
+ 		sysctl_max_syn_backlog = 128;
+ 	}
+ 
+-	sysctl_tcp_mem[0] =  768 << order;
+-	sysctl_tcp_mem[1] = 1024 << order;
+-	sysctl_tcp_mem[2] = 1536 << order;
++	/* Allow no more than 3/4 kernel memory (usually less) allocated to TCP */
++	sysctl_tcp_mem[0] = (1536 / sizeof (struct inet_bind_hashbucket)) << order;
++	sysctl_tcp_mem[1] = sysctl_tcp_mem[0] * 4 / 3;
++	sysctl_tcp_mem[2] = sysctl_tcp_mem[0] * 2;
+ 
+ 	limit = ((unsigned long)sysctl_tcp_mem[1]) << (PAGE_SHIFT - 7);
+ 	max_share = min(4UL*1024*1024, limit);

commit 9e950efa20dc8037c27509666cba6999da9368e8
+Author: John Heffner 
+Date:   Mon Nov 6 23:10:51 2006 -0800
+
+    [TCP]: Don't use highmem in tcp hash size calculation.
+    
+    This patch removes consideration of high memory when determining TCP
+    hash table sizes.  Taking into account high memory results in tcp_mem
+    values that are too large.
+    
+    Signed-off-by: John Heffner 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
+index 66e9a729f6df..4322318ab332 100644
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -2270,7 +2270,7 @@ void __init tcp_init(void)
+ 					thash_entries,
+ 					(num_physpages >= 128 * 1024) ?
+ 					13 : 15,
+-					HASH_HIGHMEM,
++					0,
+ 					&tcp_hashinfo.ehash_size,
+ 					NULL,
+ 					0);
+@@ -2286,7 +2286,7 @@ void __init tcp_init(void)
+ 					tcp_hashinfo.ehash_size,
+ 					(num_physpages >= 128 * 1024) ?
+ 					13 : 15,
+-					HASH_HIGHMEM,
++					0,
+ 					&tcp_hashinfo.bhash_size,
+ 					NULL,
+ 					64 * 1024);

commit ae8064ac32d07f609114d73928cdef803be87134
+Author: John Heffner 
+Date:   Wed Oct 18 20:36:48 2006 -0700
+
+    [TCP]: Bound TSO defer time
+    
+    This patch limits the amount of time you will defer sending a TSO segment
+    to less than two clock ticks, or the time between two acks, whichever is
+    longer.
+    
+    On slow links, deferring causes significant bursts.  See attached plots,
+    which show RTT through a 1 Mbps link with a 100 ms RTT and ~100 ms queue
+    for (a) non-TSO, (b) currnet TSO, and (c) patched TSO.  This burstiness
+    causes significant jitter, tends to overflow queues early (bad for short
+    queues), and makes delay-based congestion control more difficult.
+    
+    Deferring by a couple clock ticks I believe will have a relatively small
+    impact on performance.
+    
+    Signed-off-by: John Heffner 
+    Signed-off-by: David S. Miller 
+
+diff --git a/include/linux/tcp.h b/include/linux/tcp.h
+index 0e058a2d1c6d..2d36f6db3706 100644
+--- a/include/linux/tcp.h
++++ b/include/linux/tcp.h
+@@ -342,6 +342,8 @@ struct tcp_sock {
+ 
+ 	unsigned long last_synq_overflow; 
+ 
++	__u32	tso_deferred;
++
+ /* Receiver side RTT estimation */
+ 	struct {
+ 		__u32	rtt;
+diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
+index f22536e32cb1..ca406157724c 100644
+--- a/net/ipv4/tcp_output.c
++++ b/net/ipv4/tcp_output.c
+@@ -1096,10 +1096,14 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_
+ 	u32 send_win, cong_win, limit, in_flight;
+ 
+ 	if (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN)
+-		return 0;
++		goto send_now;
+ 
+ 	if (icsk->icsk_ca_state != TCP_CA_Open)
+-		return 0;
++		goto send_now;
++
++	/* Defer for less than two clock ticks. */
++	if (!tp->tso_deferred && ((jiffies<<1)>>1) - (tp->tso_deferred>>1) > 1)
++		goto send_now;
+ 
+ 	in_flight = tcp_packets_in_flight(tp);
+ 
+@@ -1115,7 +1119,7 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_
+ 
+ 	/* If a full-sized TSO skb can be sent, do it. */
+ 	if (limit >= 65536)
+-		return 0;
++		goto send_now;
+ 
+ 	if (sysctl_tcp_tso_win_divisor) {
+ 		u32 chunk = min(tp->snd_wnd, tp->snd_cwnd * tp->mss_cache);
+@@ -1125,7 +1129,7 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_
+ 		 */
+ 		chunk /= sysctl_tcp_tso_win_divisor;
+ 		if (limit >= chunk)
+-			return 0;
++			goto send_now;
+ 	} else {
+ 		/* Different approach, try not to defer past a single
+ 		 * ACK.  Receiver should ACK every other full sized
+@@ -1133,11 +1137,17 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_
+ 		 * then send now.
+ 		 */
+ 		if (limit > tcp_max_burst(tp) * tp->mss_cache)
+-			return 0;
++			goto send_now;
+ 	}
+ 
+ 	/* Ok, it looks like it is advisable to defer.  */
++	tp->tso_deferred = 1 | (jiffies<<1);
++
+ 	return 1;
++
++send_now:
++	tp->tso_deferred = 0;
++	return 0;
+ }
+ 
+ /* Create a new MTU probe if we are ready.

commit 8ea333eb5da3e3219f570220c56bca09f6f4d25a
+Author: John Heffner 
+Date:   Thu Sep 28 14:47:38 2006 -0700
+
+    [TCP]: Fix and simplify microsecond rtt sampling
+    
+    This changes the microsecond RTT sampling so that samples are taken in
+    the same way that RTT samples are taken for the RTO calculator: on the
+    last segment acknowledged, and only when the segment hasn't been
+    retransmitted.
+    
+    Signed-off-by: John Heffner 
+    Acked-by: Stephen Hemminger 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
+index 85c966316668..3f884cea14ff 100644
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -2239,13 +2239,12 @@ static int tcp_tso_acked(struct sock *sk, struct sk_buff *skb,
+ 	return acked;
+ }
+ 
+-static u32 tcp_usrtt(const struct sk_buff *skb)
++static u32 tcp_usrtt(struct timeval *tv)
+ {
+-	struct timeval tv, now;
++	struct timeval now;
+ 
+ 	do_gettimeofday(&now);
+-	skb_get_timestamp(skb, &tv);
+-	return (now.tv_sec - tv.tv_sec) * 1000000 + (now.tv_usec - tv.tv_usec);
++	return (now.tv_sec - tv->tv_sec) * 1000000 + (now.tv_usec - tv->tv_usec);
+ }
+ 
+ /* Remove acknowledged frames from the retransmission queue. */
+@@ -2260,6 +2259,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
+ 	u32 pkts_acked = 0;
+ 	void (*rtt_sample)(struct sock *sk, u32 usrtt)
+ 		= icsk->icsk_ca_ops->rtt_sample;
++	struct timeval tv;
+ 
+ 	while ((skb = skb_peek(&sk->sk_write_queue)) &&
+ 	       skb != sk->sk_send_head) {
+@@ -2308,8 +2308,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
+ 				seq_rtt = -1;
+ 			} else if (seq_rtt < 0) {
+ 				seq_rtt = now - scb->when;
+-				if (rtt_sample)
+-					(*rtt_sample)(sk, tcp_usrtt(skb));
++				skb_get_timestamp(skb, &tv);
+ 			}
+ 			if (sacked & TCPCB_SACKED_ACKED)
+ 				tp->sacked_out -= tcp_skb_pcount(skb);
+@@ -2322,8 +2321,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
+ 			}
+ 		} else if (seq_rtt < 0) {
+ 			seq_rtt = now - scb->when;
+-			if (rtt_sample)
+-				(*rtt_sample)(sk, tcp_usrtt(skb));
++			skb_get_timestamp(skb, &tv);
+ 		}
+ 		tcp_dec_pcount_approx(&tp->fackets_out, skb);
+ 		tcp_packets_out_dec(tp, skb);
+@@ -2335,6 +2333,8 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
+ 	if (acked&FLAG_ACKED) {
+ 		tcp_ack_update_rtt(sk, acked, seq_rtt);
+ 		tcp_ack_packets_out(sk, tp);
++		if (rtt_sample && !(acked & FLAG_RETRANS_DATA_ACKED))
++			(*rtt_sample)(sk, tcp_usrtt(&tv));
+ 
+ 		if (icsk->icsk_ca_ops->pkts_acked)
+ 			icsk->icsk_ca_ops->pkts_acked(sk, pkts_acked);

commit 5528e568a760442e0ec8fd2dea1f0791875a066b
+Author: John Heffner 
+Date:   Fri May 5 17:41:44 2006 -0700
+
+    [TCP]: Fix snd_cwnd adjustments in tcp_highspeed.c
+    
+    Xiaoliang (David) Wei wrote:
+    > Hi gurus,
+    >
+    >    I am reading the code of tcp_highspeed.c in the kernel and have a
+    > question on the hstcp_cong_avoid function, specifically the following
+    > AI part (line 136~143 in net/ipv4/tcp_highspeed.c ):
+    >
+    >                /* Do additive increase */
+    >                if (tp->snd_cwnd < tp->snd_cwnd_clamp) {
+    >                        tp->snd_cwnd_cnt += ca->ai;
+    >                        if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
+    >                                tp->snd_cwnd++;
+    >                                tp->snd_cwnd_cnt -= tp->snd_cwnd;
+    >                        }
+    >                }
+    >
+    >    In this part, when (tp->snd_cwnd_cnt == tp->snd_cwnd),
+    > snd_cwnd_cnt will be -1... snd_cwnd_cnt is defined as u16, will this
+    > small chance of getting -1 becomes a problem?
+    > Shall we change it by reversing the order of the cwnd++ and cwnd_cnt -=
+    > cwnd?
+    
+    Absolutely correct.  Thanks.
+    
+    Signed-off-by: John Heffner 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv4/tcp_highspeed.c b/net/ipv4/tcp_highspeed.c
+index e0e9d1383c7c..b72fa55dfb84 100644
+--- a/net/ipv4/tcp_highspeed.c
++++ b/net/ipv4/tcp_highspeed.c
+@@ -137,8 +137,8 @@ static void hstcp_cong_avoid(struct sock *sk, u32 adk, u32 rtt,
+ 		if (tp->snd_cwnd < tp->snd_cwnd_clamp) {
+ 			tp->snd_cwnd_cnt += ca->ai;
+ 			if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
+-				tp->snd_cwnd++;
+ 				tp->snd_cwnd_cnt -= tp->snd_cwnd;
++				tp->snd_cwnd++;
+ 			}
+ 		}
+ 	}

commit 7b4f4b5ebceab67ce440a61081a69f0265e17c2a
+Author: John Heffner 
+Date:   Sat Mar 25 01:34:07 2006 -0800
+
+    [TCP]: Set default max buffers from memory pool size
+    
+    This patch sets the maximum TCP buffer sizes (available to automatic
+    buffer tuning, not to setsockopt) based on the TCP memory pool size.
+    The maximum sndbuf and rcvbuf each will be up to 4 MB, but no more
+    than 1/128 of the memory pressure threshold.
+    
+    Signed-off-by: John Heffner 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
+index 4b0272c92d66..591e96dffc28 100644
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -276,8 +276,8 @@ atomic_t tcp_orphan_count = ATOMIC_INIT(0);
+ EXPORT_SYMBOL_GPL(tcp_orphan_count);
+ 
+ int sysctl_tcp_mem[3];
+-int sysctl_tcp_wmem[3] = { 4 * 1024, 16 * 1024, 128 * 1024 };
+-int sysctl_tcp_rmem[3] = { 4 * 1024, 87380, 87380 * 2 };
++int sysctl_tcp_wmem[3];
++int sysctl_tcp_rmem[3];
+ 
+ EXPORT_SYMBOL(sysctl_tcp_mem);
+ EXPORT_SYMBOL(sysctl_tcp_rmem);
+@@ -2081,7 +2081,8 @@ __setup("thash_entries=", set_thash_entries);
+ void __init tcp_init(void)
+ {
+ 	struct sk_buff *skb = NULL;
+-	int order, i;
++	unsigned long limit;
++	int order, i, max_share;
+ 
+ 	if (sizeof(struct tcp_skb_cb) > sizeof(skb->cb))
+ 		__skb_cb_too_small_for_tcp(sizeof(struct tcp_skb_cb),
+@@ -2155,12 +2156,16 @@ void __init tcp_init(void)
+ 	sysctl_tcp_mem[1] = 1024 << order;
+ 	sysctl_tcp_mem[2] = 1536 << order;
+ 
+-	if (order < 3) {
+-		sysctl_tcp_wmem[2] = 64 * 1024;
+-		sysctl_tcp_rmem[0] = PAGE_SIZE;
+-		sysctl_tcp_rmem[1] = 43689;
+-		sysctl_tcp_rmem[2] = 2 * 43689;
+-	}
++	limit = ((unsigned long)sysctl_tcp_mem[1]) << (PAGE_SHIFT - 7);
++	max_share = min(4UL*1024*1024, limit);
++
++	sysctl_tcp_wmem[0] = SK_STREAM_MEM_QUANTUM;
++	sysctl_tcp_wmem[1] = 16*1024;
++	sysctl_tcp_wmem[2] = max(64*1024, max_share);
++
++	sysctl_tcp_rmem[0] = SK_STREAM_MEM_QUANTUM;
++	sysctl_tcp_rmem[1] = 87380;
++	sysctl_tcp_rmem[2] = max(87380, max_share);
+ 
+ 	printk(KERN_INFO "TCP: Hash tables configured "
+ 	       "(established %d bind %d)\n",

commit 0e7b13685f9a06949ea3070c97c0f0085a08cd37
+Author: John Heffner 
+Date:   Mon Mar 20 21:32:58 2006 -0800
+
+    [TCP] mtu probing: move tcp-specific data out of inet_connection_sock
+    
+    This moves some TCP-specific MTU probing state out of
+    inet_connection_sock back to tcp_sock.
+    
+    Signed-off-by: John Heffner 
+    Signed-off-by: David S. Miller 
+
+diff --git a/include/linux/tcp.h b/include/linux/tcp.h
+index f2bb2396853f..542d39596bd8 100644
+--- a/include/linux/tcp.h
++++ b/include/linux/tcp.h
+@@ -343,6 +343,12 @@ struct tcp_sock {
+ 		__u32	seq;
+ 		__u32	time;
+ 	} rcvq_space;
++
++/* TCP-specific MTU probe information. */
++	struct {
++		__u32		  probe_seq_start;
++		__u32		  probe_seq_end;
++	} mtu_probe;
+ };
+ 
+ static inline struct tcp_sock *tcp_sk(const struct sock *sk)
+diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
+index b3abe33f4e5f..4e5a9ff99fc3 100644
+--- a/include/net/inet_connection_sock.h
++++ b/include/net/inet_connection_sock.h
+@@ -114,8 +114,6 @@ struct inet_connection_sock {
+ 
+ 		/* Information on the current probe. */
+ 		int		  probe_size;
+-		__u32		  probe_seq_start;
+-		__u32		  probe_seq_end;
+ 	} icsk_mtup;
+ 	u32			  icsk_ca_priv[16];
+ #define ICSK_CA_PRIV_SIZE	(16 * sizeof(u32))
+diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
+index 0ac388e3d01d..195d83584558 100644
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -2054,7 +2054,7 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
+ 		/* MTU probe failure: don't reduce cwnd */
+ 		if (icsk->icsk_ca_state < TCP_CA_CWR &&
+ 		    icsk->icsk_mtup.probe_size &&
+-		    tp->snd_una == icsk->icsk_mtup.probe_seq_start) {
++		    tp->snd_una == tp->mtu_probe.probe_seq_start) {
+ 			tcp_mtup_probe_failed(sk);
+ 			/* Restores the reduction we did in tcp_mtup_probe() */
+ 			tp->snd_cwnd++;
+@@ -2284,7 +2284,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
+ 
+ 		/* MTU probing checks */
+ 		if (icsk->icsk_mtup.probe_size) {
+-			if (!after(icsk->icsk_mtup.probe_seq_end, TCP_SKB_CB(skb)->end_seq)) {
++			if (!after(tp->mtu_probe.probe_seq_end, TCP_SKB_CB(skb)->end_seq)) {
+ 				tcp_mtup_probe_success(sk, skb);
+ 			}
+ 		}
+diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
+index 8197b5e12f1f..518e568b53f3 100644
+--- a/net/ipv4/tcp_output.c
++++ b/net/ipv4/tcp_output.c
+@@ -1238,8 +1238,8 @@ static int tcp_mtu_probe(struct sock *sk)
+ 		update_send_head(sk, tp, nskb);
+ 
+ 		icsk->icsk_mtup.probe_size = tcp_mss_to_mtu(sk, nskb->len);
+-		icsk->icsk_mtup.probe_seq_start = TCP_SKB_CB(nskb)->seq;
+-		icsk->icsk_mtup.probe_seq_end = TCP_SKB_CB(nskb)->end_seq;
++		tp->mtu_probe.probe_seq_start = TCP_SKB_CB(nskb)->seq;
++		tp->mtu_probe.probe_seq_end = TCP_SKB_CB(nskb)->end_seq;
+ 
+ 		return 1;
+ 	}

commit 5d424d5a674f782d0659a3b66d951f412901faee
+Author: John Heffner 
+Date:   Mon Mar 20 17:53:41 2006 -0800
+
+    [TCP]: MTU probing
+    
+    Implementation of packetization layer path mtu discovery for TCP, based on
+    the internet-draft currently found at
+    .
+    
+    Signed-off-by: John Heffner 
+    Signed-off-by: David S. Miller 
+
+diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
+index 8ad4beab2888..6e8880ea49e7 100644
+--- a/include/linux/sysctl.h
++++ b/include/linux/sysctl.h
+@@ -397,6 +397,8 @@ enum
+ 	NET_TCP_CONG_CONTROL=110,
+ 	NET_TCP_ABC=111,
+ 	NET_IPV4_IPFRAG_MAX_DIST=112,
++ 	NET_TCP_MTU_PROBING=113,
++	NET_TCP_BASE_MSS=114,
+ };
+ 
+ enum {
+diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
+index fa587c94e9d0..b3abe33f4e5f 100644
+--- a/include/net/inet_connection_sock.h
++++ b/include/net/inet_connection_sock.h
+@@ -72,6 +72,7 @@ struct inet_connection_sock_af_ops {
+  * @icsk_probes_out:	   unanswered 0 window probes
+  * @icsk_ext_hdr_len:	   Network protocol overhead (IP/IPv6 options)
+  * @icsk_ack:		   Delayed ACK control data
++ * @icsk_mtup;		   MTU probing control data
+  */
+ struct inet_connection_sock {
+ 	/* inet_sock has to be the first member! */
+@@ -104,6 +105,18 @@ struct inet_connection_sock {
+ 		__u16		  last_seg_size; /* Size of last incoming segment	   */
+ 		__u16		  rcv_mss;	 /* MSS used for delayed ACK decisions	   */ 
+ 	} icsk_ack;
++	struct {
++		int		  enabled;
++
++		/* Range of MTUs to search */
++		int		  search_high;
++		int		  search_low;
++
++		/* Information on the current probe. */
++		int		  probe_size;
++		__u32		  probe_seq_start;
++		__u32		  probe_seq_end;
++	} icsk_mtup;
+ 	u32			  icsk_ca_priv[16];
+ #define ICSK_CA_PRIV_SIZE	(16 * sizeof(u32))
+ };
+diff --git a/include/net/tcp.h b/include/net/tcp.h
+index 77f21c65bbca..16879fa560de 100644
+--- a/include/net/tcp.h
++++ b/include/net/tcp.h
+@@ -60,6 +60,9 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
+ /* Minimal RCV_MSS. */
+ #define TCP_MIN_RCVMSS		536U
+ 
++/* The least MTU to use for probing */
++#define TCP_BASE_MSS		512
++
+ /* After receiving this amount of duplicate ACKs fast retransmit starts. */
+ #define TCP_FASTRETRANS_THRESH 3
+ 
+@@ -219,6 +222,8 @@ extern int sysctl_tcp_nometrics_save;
+ extern int sysctl_tcp_moderate_rcvbuf;
+ extern int sysctl_tcp_tso_win_divisor;
+ extern int sysctl_tcp_abc;
++extern int sysctl_tcp_mtu_probing;
++extern int sysctl_tcp_base_mss;
+ 
+ extern atomic_t tcp_memory_allocated;
+ extern atomic_t tcp_sockets_allocated;
+@@ -447,6 +452,10 @@ extern int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
+ 
+ extern void tcp_initialize_rcv_mss(struct sock *sk);
+ 
++extern int tcp_mtu_to_mss(struct sock *sk, int pmtu);
++extern int tcp_mss_to_mtu(struct sock *sk, int mss);
++extern void tcp_mtup_init(struct sock *sk);
++
+ static inline void __tcp_fast_path_on(struct tcp_sock *tp, u32 snd_wnd)
+ {
+ 	tp->pred_flags = htonl((tp->tcp_header_len << 26) |
+diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
+index 16984d4a8a06..ebf2e0b363c4 100644
+--- a/net/ipv4/sysctl_net_ipv4.c
++++ b/net/ipv4/sysctl_net_ipv4.c
+@@ -664,6 +664,22 @@ ctl_table ipv4_table[] = {
+ 		.mode		= 0644,
+ 		.proc_handler	= &proc_dointvec,
+ 	},
++	{
++		.ctl_name	= NET_TCP_MTU_PROBING,
++		.procname	= "tcp_mtu_probing",
++		.data		= &sysctl_tcp_mtu_probing,
++		.maxlen		= sizeof(int),
++		.mode		= 0644,
++		.proc_handler	= &proc_dointvec,
++	},
++	{
++		.ctl_name	= NET_TCP_BASE_MSS,
++		.procname	= "tcp_base_mss",
++		.data		= &sysctl_tcp_base_mss,
++		.maxlen		= sizeof(int),
++		.mode		= 0644,
++		.proc_handler	= &proc_dointvec,
++	},
+ 
+ 	{ .ctl_name = 0 }
+ };
+diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
+index e9a54ae7d690..0ac388e3d01d 100644
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -1891,6 +1891,34 @@ static void tcp_try_to_open(struct sock *sk, struct tcp_sock *tp, int flag)
+ 	}
+ }
+ 
++static void tcp_mtup_probe_failed(struct sock *sk)
++{
++	struct inet_connection_sock *icsk = inet_csk(sk);
++
++	icsk->icsk_mtup.search_high = icsk->icsk_mtup.probe_size - 1;
++	icsk->icsk_mtup.probe_size = 0;
++}
++
++static void tcp_mtup_probe_success(struct sock *sk, struct sk_buff *skb)
++{
++	struct tcp_sock *tp = tcp_sk(sk);
++	struct inet_connection_sock *icsk = inet_csk(sk);
++
++	/* FIXME: breaks with very large cwnd */
++	tp->prior_ssthresh = tcp_current_ssthresh(sk);
++	tp->snd_cwnd = tp->snd_cwnd *
++		       tcp_mss_to_mtu(sk, tp->mss_cache) /
++		       icsk->icsk_mtup.probe_size;
++	tp->snd_cwnd_cnt = 0;
++	tp->snd_cwnd_stamp = tcp_time_stamp;
++	tp->rcv_ssthresh = tcp_current_ssthresh(sk);
++
++	icsk->icsk_mtup.search_low = icsk->icsk_mtup.probe_size;
++	icsk->icsk_mtup.probe_size = 0;
++	tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
++}
++
++
+ /* Process an event, which can update packets-in-flight not trivially.
+  * Main goal of this function is to calculate new estimate for left_out,
+  * taking into account both packets sitting in receiver's buffer and
+@@ -2023,6 +2051,17 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
+ 			return;
+ 		}
+ 
++		/* MTU probe failure: don't reduce cwnd */
++		if (icsk->icsk_ca_state < TCP_CA_CWR &&
++		    icsk->icsk_mtup.probe_size &&
++		    tp->snd_una == icsk->icsk_mtup.probe_seq_start) {
++			tcp_mtup_probe_failed(sk);
++			/* Restores the reduction we did in tcp_mtup_probe() */
++			tp->snd_cwnd++;
++			tcp_simple_retransmit(sk);
++			return;
++		}
++
+ 		/* Otherwise enter Recovery state */
+ 
+ 		if (IsReno(tp))
+@@ -2243,6 +2282,13 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
+ 			tp->retrans_stamp = 0;
+ 		}
+ 
++		/* MTU probing checks */
++		if (icsk->icsk_mtup.probe_size) {
++			if (!after(icsk->icsk_mtup.probe_seq_end, TCP_SKB_CB(skb)->end_seq)) {
++				tcp_mtup_probe_success(sk, skb);
++			}
++		}
++
+ 		if (sacked) {
+ 			if (sacked & TCPCB_RETRANS) {
+ 				if(sacked & TCPCB_SACKED_RETRANS)
+@@ -4101,6 +4147,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
+ 		if (tp->rx_opt.sack_ok && sysctl_tcp_fack)
+ 			tp->rx_opt.sack_ok |= 2;
+ 
++		tcp_mtup_init(sk);
+ 		tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
+ 		tcp_initialize_rcv_mss(sk);
+ 
+@@ -4211,6 +4258,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
+ 		if (tp->ecn_flags&TCP_ECN_OK)
+ 			sock_set_flag(sk, SOCK_NO_LARGESEND);
+ 
++		tcp_mtup_init(sk);
+ 		tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
+ 		tcp_initialize_rcv_mss(sk);
+ 
+@@ -4399,6 +4447,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
+ 				 */
+ 				tp->lsndtime = tcp_time_stamp;
+ 
++				tcp_mtup_init(sk);
+ 				tcp_initialize_rcv_mss(sk);
+ 				tcp_init_buffer_space(sk);
+ 				tcp_fast_path_on(tp);
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index 233bdf259965..57e7a26e8213 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -900,6 +900,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
+ 		inet_csk(newsk)->icsk_ext_hdr_len = newinet->opt->optlen;
+ 	newinet->id = newtp->write_seq ^ jiffies;
+ 
++	tcp_mtup_init(newsk);
+ 	tcp_sync_mss(newsk, dst_mtu(dst));
+ 	newtp->advmss = dst_metric(dst, RTAX_ADVMSS);
+ 	tcp_initialize_rcv_mss(newsk);
+diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
+index 9f498a6c8895..8197b5e12f1f 100644
+--- a/net/ipv4/tcp_output.c
++++ b/net/ipv4/tcp_output.c
+@@ -51,6 +51,12 @@ int sysctl_tcp_retrans_collapse = 1;
+  */
+ int sysctl_tcp_tso_win_divisor = 3;
+ 
++int sysctl_tcp_mtu_probing = 0;
++int sysctl_tcp_base_mss = 512;
++
++EXPORT_SYMBOL(sysctl_tcp_mtu_probing);
++EXPORT_SYMBOL(sysctl_tcp_base_mss);
++
+ static void update_send_head(struct sock *sk, struct tcp_sock *tp,
+ 			     struct sk_buff *skb)
+ {
+@@ -681,6 +687,62 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
+ 	return 0;
+ }
+ 
++/* Not accounting for SACKs here. */
++int tcp_mtu_to_mss(struct sock *sk, int pmtu)
++{
++	struct tcp_sock *tp = tcp_sk(sk);
++	struct inet_connection_sock *icsk = inet_csk(sk);
++	int mss_now;
++
++	/* Calculate base mss without TCP options:
++	   It is MMS_S - sizeof(tcphdr) of rfc1122
++	 */
++	mss_now = pmtu - icsk->icsk_af_ops->net_header_len - sizeof(struct tcphdr);
++
++	/* Clamp it (mss_clamp does not include tcp options) */
++	if (mss_now > tp->rx_opt.mss_clamp)
++		mss_now = tp->rx_opt.mss_clamp;
++
++	/* Now subtract optional transport overhead */
++	mss_now -= icsk->icsk_ext_hdr_len;
++
++	/* Then reserve room for full set of TCP options and 8 bytes of data */
++	if (mss_now < 48)
++		mss_now = 48;
++
++	/* Now subtract TCP options size, not including SACKs */
++	mss_now -= tp->tcp_header_len - sizeof(struct tcphdr);
++
++	return mss_now;
++}
++
++/* Inverse of above */
++int tcp_mss_to_mtu(struct sock *sk, int mss)
++{
++	struct tcp_sock *tp = tcp_sk(sk);
++	struct inet_connection_sock *icsk = inet_csk(sk);
++	int mtu;
++
++	mtu = mss +
++	      tp->tcp_header_len +
++	      icsk->icsk_ext_hdr_len +
++	      icsk->icsk_af_ops->net_header_len;
++
++	return mtu;
++}
++
++void tcp_mtup_init(struct sock *sk)
++{
++	struct tcp_sock *tp = tcp_sk(sk);
++	struct inet_connection_sock *icsk = inet_csk(sk);
++
++	icsk->icsk_mtup.enabled = sysctl_tcp_mtu_probing > 1;
++	icsk->icsk_mtup.search_high = tp->rx_opt.mss_clamp + sizeof(struct tcphdr) +
++	                       icsk->icsk_af_ops->net_header_len;
++	icsk->icsk_mtup.search_low = tcp_mss_to_mtu(sk, sysctl_tcp_base_mss);
++	icsk->icsk_mtup.probe_size = 0;
++}
++
+ /* This function synchronize snd mss to current pmtu/exthdr set.
+ 
+    tp->rx_opt.user_mss is mss set by user by TCP_MAXSEG. It does NOT counts
+@@ -708,25 +770,12 @@ unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu)
+ {
+ 	struct tcp_sock *tp = tcp_sk(sk);
+ 	struct inet_connection_sock *icsk = inet_csk(sk);
+-	/* Calculate base mss without TCP options:
+-	   It is MMS_S - sizeof(tcphdr) of rfc1122
+-	 */
+-	int mss_now = (pmtu - icsk->icsk_af_ops->net_header_len -
+-		       sizeof(struct tcphdr));
++	int mss_now;
+ 
+-	/* Clamp it (mss_clamp does not include tcp options) */
+-	if (mss_now > tp->rx_opt.mss_clamp)
+-		mss_now = tp->rx_opt.mss_clamp;
++	if (icsk->icsk_mtup.search_high > pmtu)
++		icsk->icsk_mtup.search_high = pmtu;
+ 
+-	/* Now subtract optional transport overhead */
+-	mss_now -= icsk->icsk_ext_hdr_len;
+-
+-	/* Then reserve room for full set of TCP options and 8 bytes of data */
+-	if (mss_now < 48)
+-		mss_now = 48;
+-
+-	/* Now subtract TCP options size, not including SACKs */
+-	mss_now -= tp->tcp_header_len - sizeof(struct tcphdr);
++	mss_now = tcp_mtu_to_mss(sk, pmtu);
+ 
+ 	/* Bound mss with half of window */
+ 	if (tp->max_window && mss_now > (tp->max_window>>1))
+@@ -734,6 +783,8 @@ unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu)
+ 
+ 	/* And store cached results */
+ 	icsk->icsk_pmtu_cookie = pmtu;
++	if (icsk->icsk_mtup.enabled)
++		mss_now = min(mss_now, tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_low));
+ 	tp->mss_cache = mss_now;
+ 
+ 	return mss_now;
+@@ -1063,6 +1114,140 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_
+ 	return 1;
+ }
+ 
++/* Create a new MTU probe if we are ready.
++ * Returns 0 if we should wait to probe (no cwnd available),
++ *         1 if a probe was sent,
++ *         -1 otherwise */
++static int tcp_mtu_probe(struct sock *sk)
++{
++	struct tcp_sock *tp = tcp_sk(sk);
++	struct inet_connection_sock *icsk = inet_csk(sk);
++	struct sk_buff *skb, *nskb, *next;
++	int len;
++	int probe_size;
++	unsigned int pif;
++	int copy;
++	int mss_now;
++
++	/* Not currently probing/verifying,
++	 * not in recovery,
++	 * have enough cwnd, and
++	 * not SACKing (the variable headers throw things off) */
++	if (!icsk->icsk_mtup.enabled ||
++	    icsk->icsk_mtup.probe_size ||
++	    inet_csk(sk)->icsk_ca_state != TCP_CA_Open ||
++	    tp->snd_cwnd < 11 ||
++	    tp->rx_opt.eff_sacks)
++		return -1;
++
++	/* Very simple search strategy: just double the MSS. */
++	mss_now = tcp_current_mss(sk, 0);
++	probe_size = 2*tp->mss_cache;
++	if (probe_size > tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_high)) {
++		/* TODO: set timer for probe_converge_event */
++		return -1;
++	}
++
++	/* Have enough data in the send queue to probe? */
++	len = 0;
++	if ((skb = sk->sk_send_head) == NULL)
++		return -1;
++	while ((len += skb->len) < probe_size && !tcp_skb_is_last(sk, skb))
++		skb = skb->next;
++	if (len < probe_size)
++		return -1;
++
++	/* Receive window check. */
++	if (after(TCP_SKB_CB(skb)->seq + probe_size, tp->snd_una + tp->snd_wnd)) {
++		if (tp->snd_wnd < probe_size)
++			return -1;
++		else
++			return 0;
++	}
++
++	/* Do we need to wait to drain cwnd? */
++	pif = tcp_packets_in_flight(tp);
++	if (pif + 2 > tp->snd_cwnd) {
++		/* With no packets in flight, don't stall. */
++		if (pif == 0)
++			return -1;
++		else
++			return 0;
++	}
++
++	/* We're allowed to probe.  Build it now. */
++	if ((nskb = sk_stream_alloc_skb(sk, probe_size, GFP_ATOMIC)) == NULL)
++		return -1;
++	sk_charge_skb(sk, nskb);
++
++	skb = sk->sk_send_head;
++	__skb_insert(nskb, skb->prev, skb, &sk->sk_write_queue);
++	sk->sk_send_head = nskb;
++
++	TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(skb)->seq;
++	TCP_SKB_CB(nskb)->end_seq = TCP_SKB_CB(skb)->seq + probe_size;
++	TCP_SKB_CB(nskb)->flags = TCPCB_FLAG_ACK;
++	TCP_SKB_CB(nskb)->sacked = 0;
++	nskb->csum = 0;
++	if (skb->ip_summed == CHECKSUM_HW)
++		nskb->ip_summed = CHECKSUM_HW;
++
++	len = 0;
++	while (len < probe_size) {
++		next = skb->next;
++
++		copy = min_t(int, skb->len, probe_size - len);
++		if (nskb->ip_summed)
++			skb_copy_bits(skb, 0, skb_put(nskb, copy), copy);
++		else
++			nskb->csum = skb_copy_and_csum_bits(skb, 0,
++			                 skb_put(nskb, copy), copy, nskb->csum);
++
++		if (skb->len <= copy) {
++			/* We've eaten all the data from this skb.
++			 * Throw it away. */
++			TCP_SKB_CB(nskb)->flags |= TCP_SKB_CB(skb)->flags;
++			__skb_unlink(skb, &sk->sk_write_queue);
++			sk_stream_free_skb(sk, skb);
++		} else {
++			TCP_SKB_CB(nskb)->flags |= TCP_SKB_CB(skb)->flags &
++			                           ~(TCPCB_FLAG_FIN|TCPCB_FLAG_PSH);
++			if (!skb_shinfo(skb)->nr_frags) {
++				skb_pull(skb, copy);
++				if (skb->ip_summed != CHECKSUM_HW)
++					skb->csum = csum_partial(skb->data, skb->len, 0);
++			} else {
++				__pskb_trim_head(skb, copy);
++				tcp_set_skb_tso_segs(sk, skb, mss_now);
++			}
++			TCP_SKB_CB(skb)->seq += copy;
++		}
++
++		len += copy;
++		skb = next;
++	}
++	tcp_init_tso_segs(sk, nskb, nskb->len);
++
++	/* We're ready to send.  If this fails, the probe will
++	 * be resegmented into mss-sized pieces by tcp_write_xmit(). */
++	TCP_SKB_CB(nskb)->when = tcp_time_stamp;
++	if (!tcp_transmit_skb(sk, nskb, 1, GFP_ATOMIC)) {
++		/* Decrement cwnd here because we are sending
++		* effectively two packets. */
++		tp->snd_cwnd--;
++		update_send_head(sk, tp, nskb);
++
++		icsk->icsk_mtup.probe_size = tcp_mss_to_mtu(sk, nskb->len);
++		icsk->icsk_mtup.probe_seq_start = TCP_SKB_CB(nskb)->seq;
++		icsk->icsk_mtup.probe_seq_end = TCP_SKB_CB(nskb)->end_seq;
++
++		return 1;
++	}
++
++	return -1;
++}
++
++
+ /* This routine writes packets to the network.  It advances the
+  * send_head.  This happens as incoming acks open up the remote
+  * window for us.
+@@ -1076,6 +1261,7 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle)
+ 	struct sk_buff *skb;
+ 	unsigned int tso_segs, sent_pkts;
+ 	int cwnd_quota;
++	int result;
+ 
+ 	/* If we are closed, the bytes will have to remain here.
+ 	 * In time closedown will finish, we empty the write queue and all
+@@ -1085,6 +1271,14 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle)
+ 		return 0;
+ 
+ 	sent_pkts = 0;
++
++	/* Do MTU probing. */
++	if ((result = tcp_mtu_probe(sk)) == 0) {
++		return 0;
++	} else if (result > 0) {
++		sent_pkts = 1;
++	}
++
+ 	while ((skb = sk->sk_send_head)) {
+ 		unsigned int limit;
+ 
+@@ -1455,9 +1649,15 @@ void tcp_simple_retransmit(struct sock *sk)
+ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
+ {
+ 	struct tcp_sock *tp = tcp_sk(sk);
++	struct inet_connection_sock *icsk = inet_csk(sk);
+  	unsigned int cur_mss = tcp_current_mss(sk, 0);
+ 	int err;
+ 
++	/* Inconslusive MTU probe */
++	if (icsk->icsk_mtup.probe_size) {
++		icsk->icsk_mtup.probe_size = 0;
++	}
++
+ 	/* Do not sent more than we queued. 1/4 is reserved for possible
+ 	 * copying overhead: fragmentation, tunneling, mangling etc.
+ 	 */
+@@ -1883,6 +2083,7 @@ static void tcp_connect_init(struct sock *sk)
+ 	if (tp->rx_opt.user_mss)
+ 		tp->rx_opt.mss_clamp = tp->rx_opt.user_mss;
+ 	tp->max_window = 0;
++	tcp_mtup_init(sk);
+ 	tcp_sync_mss(sk, dst_mtu(dst));
+ 
+ 	if (!tp->window_clamp)
+@@ -2180,3 +2381,4 @@ EXPORT_SYMBOL(tcp_make_synack);
+ EXPORT_SYMBOL(tcp_simple_retransmit);
+ EXPORT_SYMBOL(tcp_sync_mss);
+ EXPORT_SYMBOL(sysctl_tcp_tso_win_divisor);
++EXPORT_SYMBOL(tcp_mtup_init);
+diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
+index e1880959614a..7c1bde3cd6cb 100644
+--- a/net/ipv4/tcp_timer.c
++++ b/net/ipv4/tcp_timer.c
+@@ -119,8 +119,10 @@ static int tcp_orphan_retries(struct sock *sk, int alive)
+ /* A write timeout has occurred. Process the after effects. */
+ static int tcp_write_timeout(struct sock *sk)
+ {
+-	const struct inet_connection_sock *icsk = inet_csk(sk);
++	struct inet_connection_sock *icsk = inet_csk(sk);
++	struct tcp_sock *tp = tcp_sk(sk);
+ 	int retry_until;
++	int mss;
+ 
+ 	if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) {
+ 		if (icsk->icsk_retransmits)
+@@ -128,25 +130,19 @@ static int tcp_write_timeout(struct sock *sk)
+ 		retry_until = icsk->icsk_syn_retries ? : sysctl_tcp_syn_retries;
+ 	} else {
+ 		if (icsk->icsk_retransmits >= sysctl_tcp_retries1) {
+-			/* NOTE. draft-ietf-tcpimpl-pmtud-01.txt requires pmtu black
+-			   hole detection. :-(
+-
+-			   It is place to make it. It is not made. I do not want
+-			   to make it. It is disgusting. It does not work in any
+-			   case. Let me to cite the same draft, which requires for
+-			   us to implement this:
+-
+-   "The one security concern raised by this memo is that ICMP black holes
+-   are often caused by over-zealous security administrators who block
+-   all ICMP messages.  It is vitally important that those who design and
+-   deploy security systems understand the impact of strict filtering on
+-   upper-layer protocols.  The safest web site in the world is worthless
+-   if most TCP implementations cannot transfer data from it.  It would
+-   be far nicer to have all of the black holes fixed rather than fixing
+-   all of the TCP implementations."
+-
+-                           Golden words :-).
+-		   */
++			/* Black hole detection */
++			if (sysctl_tcp_mtu_probing) {
++				if (!icsk->icsk_mtup.enabled) {
++					icsk->icsk_mtup.enabled = 1;
++					tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
++				} else {
++					mss = min(sysctl_tcp_base_mss,
++					          tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_low)/2);
++					mss = max(mss, 68 - tp->tcp_header_len);
++					icsk->icsk_mtup.search_low = tcp_mss_to_mtu(sk, mss);
++					tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
++				}
++			}
+ 
+ 			dst_negative_advice(&sk->sk_dst_cache);
+ 		}
+diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
+index ca9cf6853755..14de50380f4e 100644
+--- a/net/ipv6/tcp_ipv6.c
++++ b/net/ipv6/tcp_ipv6.c
+@@ -987,6 +987,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
+ 		inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen +
+ 						     newnp->opt->opt_flen);
+ 
++	tcp_mtup_init(newsk);
+ 	tcp_sync_mss(newsk, dst_mtu(dst));
+ 	newtp->advmss = dst_metric(dst, RTAX_ADVMSS);
+ 	tcp_initialize_rcv_mss(newsk);

commit 6fcf9412de64056238a6295f21db7aa9c37a532e
+Author: John Heffner 
+Date:   Thu Feb 9 17:06:57 2006 -0800
+
+    [TCP]: rcvbuf lock when tcp_moderate_rcvbuf enabled
+    
+    The rcvbuf lock should probably be honored here.
+    
+    Signed-off-by: John Heffner 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
+index a97ed5416c28..e9a54ae7d690 100644
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -456,7 +456,8 @@ void tcp_rcv_space_adjust(struct sock *sk)
+ 
+ 		tp->rcvq_space.space = space;
+ 
+-		if (sysctl_tcp_moderate_rcvbuf) {
++		if (sysctl_tcp_moderate_rcvbuf &&
++		    !(sk->sk_userlocks & SOCK_RCVBUF_LOCK)) {
+ 			int new_clamp = space;
+ 
+ 			/* Receive space grows, normalize in order to

commit 326f36e9e7de362e09745ce6f84b65e7ccac33ba
+Author: John Heffner 
+Date:   Thu Nov 10 17:11:48 2005 -0800
+
+    [TCP]: receive buffer growth limiting with mixed MTU
+    
+    This is a patch for discussion addressing some receive buffer growing issues.
+    This is partially related to the thread "Possible BUG in IPv4 TCP window
+    handling..." last week.
+    
+    Specifically it addresses the problem of an interaction between rcvbuf
+    moderation (receiver autotuning) and rcv_ssthresh.  The problem occurs when
+    sending small packets to a receiver with a larger MTU.  (A very common case I
+    have is a host with a 1500 byte MTU sending to a host with a 9k MTU.)  In
+    such a case, the rcv_ssthresh code is targeting a window size corresponding
+    to filling up the current rcvbuf, not taking into account that the new rcvbuf
+    moderation may increase the rcvbuf size.
+    
+    One hunk makes rcv_ssthresh use tcp_rmem[2] as the size target rather than
+    rcvbuf.  The other changes the behavior when it overflows its memory bounds
+    with in-order data so that it tries to grow rcvbuf (the same as with
+    out-of-order data).
+    
+    These changes should help my problem of mixed MTUs, and should also help the
+    case from last week's thread I think.  (In both cases though you still need
+    tcp_rmem[2] to be set much larger than the TCP window.)  One question is if
+    this is too aggressive at trying to increase rcvbuf if it's under memory
+    stress.
+    
+    Orignally-from: John Heffner 
+    Signed-off-by: Stephen Hemminger 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
+index 4cb5e6f408dc..827cd4b9e867 100644
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -234,7 +234,7 @@ static int __tcp_grow_window(const struct sock *sk, struct tcp_sock *tp,
+ {
+ 	/* Optimize this! */
+ 	int truesize = tcp_win_from_space(skb->truesize)/2;
+-	int window = tcp_full_space(sk)/2;
++	int window = tcp_win_from_space(sysctl_tcp_rmem[2])/2;
+ 
+ 	while (tp->rcv_ssthresh <= window) {
+ 		if (truesize <= skb->len)
+@@ -327,37 +327,18 @@ static void tcp_init_buffer_space(struct sock *sk)
+ static void tcp_clamp_window(struct sock *sk, struct tcp_sock *tp)
+ {
+ 	struct inet_connection_sock *icsk = inet_csk(sk);
+-	struct sk_buff *skb;
+-	unsigned int app_win = tp->rcv_nxt - tp->copied_seq;
+-	int ofo_win = 0;
+ 
+ 	icsk->icsk_ack.quick = 0;
+ 
+-	skb_queue_walk(&tp->out_of_order_queue, skb) {
+-		ofo_win += skb->len;
+-	}
+-
+-	/* If overcommit is due to out of order segments,
+-	 * do not clamp window. Try to expand rcvbuf instead.
+-	 */
+-	if (ofo_win) {
+-		if (sk->sk_rcvbuf < sysctl_tcp_rmem[2] &&
+-		    !(sk->sk_userlocks & SOCK_RCVBUF_LOCK) &&
+-		    !tcp_memory_pressure &&
+-		    atomic_read(&tcp_memory_allocated) < sysctl_tcp_mem[0])
+-			sk->sk_rcvbuf = min(atomic_read(&sk->sk_rmem_alloc),
+-					    sysctl_tcp_rmem[2]);
++	if (sk->sk_rcvbuf < sysctl_tcp_rmem[2] &&
++	    !(sk->sk_userlocks & SOCK_RCVBUF_LOCK) &&
++	    !tcp_memory_pressure &&
++	    atomic_read(&tcp_memory_allocated) < sysctl_tcp_mem[0]) {
++		sk->sk_rcvbuf = min(atomic_read(&sk->sk_rmem_alloc),
++				    sysctl_tcp_rmem[2]);
+ 	}
+-	if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf) {
+-		app_win += ofo_win;
+-		if (atomic_read(&sk->sk_rmem_alloc) >= 2 * sk->sk_rcvbuf)
+-			app_win >>= 1;
+-		if (app_win > icsk->icsk_ack.rcv_mss)
+-			app_win -= icsk->icsk_ack.rcv_mss;
+-		app_win = max(app_win, 2U*tp->advmss);
+-
++	if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf)
+ 		tp->rcv_ssthresh = min(tp->window_clamp, 2U*tp->advmss);
+-	}
+ }
+ 
+ /* Receiver "autotuning" code.

commit 0e57976b6376f7fda6bef8b7dee2a3c8819ec9e9
+Author: John Heffner 
+Date:   Thu Jun 23 12:29:07 2005 -0700
+
+    [TCP]: Add Scalable TCP congestion control module.
+    
+    This patch implements Tom Kelly's Scalable TCP congestion control algorithm
+    for the modular framework.
+    
+    The algorithm has some nice scaling properties, and has been used a fair bit
+    in research, though is known to have significant fairness issues, so it's not
+    really suitable for general purpose use.
+    
+    Signed-off-by: John Heffner 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
+index 73a25b52bf7d..690e88ba2484 100644
+--- a/net/ipv4/Kconfig
++++ b/net/ipv4/Kconfig
+@@ -511,6 +511,15 @@ config TCP_CONG_VEGAS
+ 	window. TCP Vegas should provide less packet loss, but it is
+ 	not as aggressive as TCP Reno.
+ 
++config TCP_CONG_SCALABLE
++	tristate "Scalable TCP"
++	depends on INET && EXPERIMENTAL
++	default n
++	---help---
++	Scalable TCP is a sender-side only change to TCP which uses a
++	MIMD congestion control algorithm which has some nice scaling
++	properties, though is known to have fairness issues.
++	See http://www-lce.eng.cam.ac.uk/~ctk21/scalable/
+ 
+ endmenu
+ 
+diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
+index e96ed17deb96..5718cdb3a61e 100644
+--- a/net/ipv4/Makefile
++++ b/net/ipv4/Makefile
+@@ -37,6 +37,7 @@ obj-$(CONFIG_TCP_CONG_HSTCP) += tcp_highspeed.o
+ obj-$(CONFIG_TCP_CONG_HYBLA) += tcp_hybla.o
+ obj-$(CONFIG_TCP_CONG_HTCP) += tcp_htcp.o
+ obj-$(CONFIG_TCP_CONG_VEGAS) += tcp_vegas.o
++obj-$(CONFIG_TCP_CONG_SCALABLE) += tcp_scalable.o
+ 
+ obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
+ 		      xfrm4_output.o
+diff --git a/net/ipv4/tcp_scalable.c b/net/ipv4/tcp_scalable.c
+new file mode 100644
+index 000000000000..70e108e15c71
+--- /dev/null
++++ b/net/ipv4/tcp_scalable.c
+@@ -0,0 +1,68 @@
++/* Tom Kelly's Scalable TCP
++ *
++ * See htt://www-lce.eng.cam.ac.uk/~ctk21/scalable/
++ *
++ * John Heffner 
++ */
++
++#include 
++#include 
++#include 
++
++/* These factors derived from the recommended values in the aer:
++ * .01 and and 7/8. We use 50 instead of 100 to account for
++ * delayed ack.
++ */
++#define TCP_SCALABLE_AI_CNT	50U
++#define TCP_SCALABLE_MD_SCALE	3
++
++static void tcp_scalable_cong_avoid(struct tcp_sock *tp, u32 ack, u32 rtt,
++				    u32 in_flight, int flag)
++{
++	if (in_flight < tp->snd_cwnd)
++		return;
++
++	if (tp->snd_cwnd <= tp->snd_ssthresh) {
++		tp->snd_cwnd++;
++	} else {
++		tp->snd_cwnd_cnt++;
++		if (tp->snd_cwnd_cnt > min(tp->snd_cwnd, TCP_SCALABLE_AI_CNT)){
++			tp->snd_cwnd++;
++			tp->snd_cwnd_cnt = 0;
++		}
++	}
++	tp->snd_cwnd = min_t(u32, tp->snd_cwnd, tp->snd_cwnd_clamp);
++	tp->snd_cwnd_stamp = tcp_time_stamp;
++}
++
++static u32 tcp_scalable_ssthresh(struct tcp_sock *tp)
++{
++	return max(tp->snd_cwnd - (tp->snd_cwnd>>TCP_SCALABLE_MD_SCALE), 2U);
++}
++
++
++static struct tcp_congestion_ops tcp_scalable = {
++	.ssthresh	= tcp_scalable_ssthresh,
++	.cong_avoid	= tcp_scalable_cong_avoid,
++	.min_cwnd	= tcp_reno_min_cwnd,
++
++	.owner		= THIS_MODULE,
++	.name		= "scalable",
++};
++
++static int __init tcp_scalable_register(void)
++{
++	return tcp_register_congestion_control(&tcp_scalable);
++}
++
++static void __exit tcp_scalable_unregister(void)
++{
++	tcp_unregister_congestion_control(&tcp_scalable);
++}
++
++module_init(tcp_scalable_register);
++module_exit(tcp_scalable_unregister);
++
++MODULE_AUTHOR("John Heffner");
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Scalable TCP");

commit a628d29b56d3f420bf3ff1d7543a9caf3ce3b994
+Author: John Heffner 
+Date:   Thu Jun 23 12:24:58 2005 -0700
+
+    [TCP]: Add High Speed TCP congestion control module.
+    
+    Sally Floyd's high speed TCP congestion control.
+    This is useful for comparison and research.
+    
+    Signed-off-by: John Heffner 
+    Signed-off-by: Stephen Hemminger 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
+index adbe855d931a..910e25b65756 100644
+--- a/net/ipv4/Kconfig
++++ b/net/ipv4/Kconfig
+@@ -467,6 +467,17 @@ config TCP_CONG_WESTWOOD
+ 	TCP Westwood+ significantly increases fairness wrt TCP Reno in
+ 	wired networks and throughput over wireless links.
+ 
++config TCP_CONG_HSTCP
++	tristate "High Speed TCP"
++	depends on INET && EXPERIMENTAL
++	default n
++	---help---
++	Sally Floyd's High Speed TCP (RFC 3649) congestion control.
++	A modification to TCP's congestion control mechanism for use
++	with large congestion windows. A table indicates how much to
++	increase the congestion window by when an ACK is received.
++ 	For more detail	see http://www.icir.org/floyd/hstcp.html
++
+ endmenu
+ 
+ source "net/ipv4/ipvs/Kconfig"
+diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
+index dedfbe62a104..ddf5d7785bf4 100644
+--- a/net/ipv4/Makefile
++++ b/net/ipv4/Makefile
+@@ -33,6 +33,7 @@ obj-$(CONFIG_IP_TCPDIAG) += tcp_diag.o
+ obj-$(CONFIG_IP_ROUTE_MULTIPATH_CACHED) += multipath.o
+ obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o
+ obj-$(CONFIG_TCP_CONG_WESTWOOD) += tcp_westwood.o
++obj-$(CONFIG_TCP_CONG_HSTCP) += tcp_highspeed.o
+ 
+ obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
+ 		      xfrm4_output.o
+diff --git a/net/ipv4/tcp_highspeed.c b/net/ipv4/tcp_highspeed.c
+new file mode 100644
+index 000000000000..36c51f8136bf
+--- /dev/null
++++ b/net/ipv4/tcp_highspeed.c
+@@ -0,0 +1,181 @@
++/*
++ * Sally Floyd's High Speed TCP (RFC 3649) congestion control
++ *
++ * See http://www.icir.org/floyd/hstcp.html
++ *
++ * John Heffner 
++ */
++
++#include 
++#include 
++#include 
++
++
++/* From AIMD tables from RFC 3649 appendix B,
++ * with fixed-point MD scaled <<8.
++ */
++static const struct hstcp_aimd_val {
++        unsigned int cwnd;
++        unsigned int md;
++} hstcp_aimd_vals[] = {
++ {     38,  128, /*  0.50 */ },
++ {    118,  112, /*  0.44 */ },
++ {    221,  104, /*  0.41 */ },
++ {    347,   98, /*  0.38 */ },
++ {    495,   93, /*  0.37 */ },
++ {    663,   89, /*  0.35 */ },
++ {    851,   86, /*  0.34 */ },
++ {   1058,   83, /*  0.33 */ },
++ {   1284,   81, /*  0.32 */ },
++ {   1529,   78, /*  0.31 */ },
++ {   1793,   76, /*  0.30 */ },
++ {   2076,   74, /*  0.29 */ },
++ {   2378,   72, /*  0.28 */ },
++ {   2699,   71, /*  0.28 */ },
++ {   3039,   69, /*  0.27 */ },
++ {   3399,   68, /*  0.27 */ },
++ {   3778,   66, /*  0.26 */ },
++ {   4177,   65, /*  0.26 */ },
++ {   4596,   64, /*  0.25 */ },
++ {   5036,   62, /*  0.25 */ },
++ {   5497,   61, /*  0.24 */ },
++ {   5979,   60, /*  0.24 */ },
++ {   6483,   59, /*  0.23 */ },
++ {   7009,   58, /*  0.23 */ },
++ {   7558,   57, /*  0.22 */ },
++ {   8130,   56, /*  0.22 */ },
++ {   8726,   55, /*  0.22 */ },
++ {   9346,   54, /*  0.21 */ },
++ {   9991,   53, /*  0.21 */ },
++ {  10661,   52, /*  0.21 */ },
++ {  11358,   52, /*  0.20 */ },
++ {  12082,   51, /*  0.20 */ },
++ {  12834,   50, /*  0.20 */ },
++ {  13614,   49, /*  0.19 */ },
++ {  14424,   48, /*  0.19 */ },
++ {  15265,   48, /*  0.19 */ },
++ {  16137,   47, /*  0.19 */ },
++ {  17042,   46, /*  0.18 */ },
++ {  17981,   45, /*  0.18 */ },
++ {  18955,   45, /*  0.18 */ },
++ {  19965,   44, /*  0.17 */ },
++ {  21013,   43, /*  0.17 */ },
++ {  22101,   43, /*  0.17 */ },
++ {  23230,   42, /*  0.17 */ },
++ {  24402,   41, /*  0.16 */ },
++ {  25618,   41, /*  0.16 */ },
++ {  26881,   40, /*  0.16 */ },
++ {  28193,   39, /*  0.16 */ },
++ {  29557,   39, /*  0.15 */ },
++ {  30975,   38, /*  0.15 */ },
++ {  32450,   38, /*  0.15 */ },
++ {  33986,   37, /*  0.15 */ },
++ {  35586,   36, /*  0.14 */ },
++ {  37253,   36, /*  0.14 */ },
++ {  38992,   35, /*  0.14 */ },
++ {  40808,   35, /*  0.14 */ },
++ {  42707,   34, /*  0.13 */ },
++ {  44694,   33, /*  0.13 */ },
++ {  46776,   33, /*  0.13 */ },
++ {  48961,   32, /*  0.13 */ },
++ {  51258,   32, /*  0.13 */ },
++ {  53677,   31, /*  0.12 */ },
++ {  56230,   30, /*  0.12 */ },
++ {  58932,   30, /*  0.12 */ },
++ {  61799,   29, /*  0.12 */ },
++ {  64851,   28, /*  0.11 */ },
++ {  68113,   28, /*  0.11 */ },
++ {  71617,   27, /*  0.11 */ },
++ {  75401,   26, /*  0.10 */ },
++ {  79517,   26, /*  0.10 */ },
++ {  84035,   25, /*  0.10 */ },
++ {  89053,   24, /*  0.10 */ },
++};
++
++#define HSTCP_AIMD_MAX	ARRAY_SIZE(hstcp_aimd_vals)
++
++struct hstcp {
++	u32	ai;
++};
++
++static void hstcp_init(struct tcp_sock *tp)
++{
++	struct hstcp *ca = tcp_ca(tp);
++
++	ca->ai = 0;
++
++	/* Ensure the MD arithmetic works.  This is somewhat pedantic,
++	 * since I don't think we will see a cwnd this large. :) */
++	tp->snd_cwnd_clamp = min_t(u32, tp->snd_cwnd_clamp, 0xffffffff/128);
++}
++
++static void hstcp_cong_avoid(struct tcp_sock *tp, u32 adk, u32 rtt,
++			     u32 in_flight, int good)
++{
++	struct hstcp *ca = tcp_ca(tp);
++
++	if (in_flight < tp->snd_cwnd)
++		return;
++
++	if (tp->snd_cwnd <= tp->snd_ssthresh) {
++		if (tp->snd_cwnd < tp->snd_cwnd_clamp)
++			tp->snd_cwnd++;
++	} else {
++		/* Update AIMD parameters */
++		if (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd) {
++			while (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd &&
++			       ca->ai < HSTCP_AIMD_MAX)
++				ca->ai++;
++		} else if (tp->snd_cwnd < hstcp_aimd_vals[ca->ai].cwnd) {
++			while (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd &&
++			       ca->ai > 0)
++				ca->ai--;
++		}
++
++		/* Do additive increase */
++		if (tp->snd_cwnd < tp->snd_cwnd_clamp) {
++			tp->snd_cwnd_cnt += ca->ai;
++			if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
++				tp->snd_cwnd++;
++				tp->snd_cwnd_cnt -= tp->snd_cwnd;
++			}
++		}
++	}
++}
++
++static u32 hstcp_ssthresh(struct tcp_sock *tp)
++{
++	struct hstcp *ca = tcp_ca(tp);
++
++	/* Do multiplicative decrease */
++	return max(tp->snd_cwnd - ((tp->snd_cwnd * hstcp_aimd_vals[ca->ai].md) >> 8), 2U);
++}
++
++
++static struct tcp_congestion_ops tcp_highspeed = {
++	.init		= hstcp_init,
++	.ssthresh	= hstcp_ssthresh,
++	.cong_avoid	= hstcp_cong_avoid,
++	.min_cwnd	= tcp_reno_min_cwnd,
++
++	.owner		= THIS_MODULE,
++	.name		= "highspeed"
++};
++
++static int __init hstcp_register(void)
++{
++	BUG_ON(sizeof(struct hstcp) > TCP_CA_PRIV_SIZE);
++	return tcp_register_congestion_control(&tcp_highspeed);
++}
++
++static void __exit hstcp_unregister(void)
++{
++	tcp_unregister_congestion_control(&tcp_highspeed);
++}
++
++module_init(hstcp_register);
++module_exit(hstcp_unregister);
++
++MODULE_AUTHOR("John Heffner");
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("High Speed TCP");

\ No newline at end of file diff --git a/detail/52.html b/detail/52.html new file mode 100644 index 0000000..2f1284c --- /dev/null +++ b/detail/52.html @@ -0,0 +1,244 @@ +

Patches contributed by Universidad Politécnica de Cataluna


commit 3734dfc68b64d8ca202c799280daf28c2424659d
+Author: Julio M. Merino Vidal 
+Date:   Wed Apr 30 15:21:17 2008 +1000
+
+    [POWERPC] spufs: trace spu_acquire_saved events
+    
+    The sputrace module contained a trace entry for spu_acquire_saved, but
+    this marker was not placed anywhere. Fix this by adding a marker to the
+    routine.
+    
+    Signed-off-by: Julio M. Merino Vidal 
+    Signed-off-by: Jeremy Kerr 
+
+diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
+index 5c5010078042..177735f79317 100644
+--- a/arch/powerpc/platforms/cell/spufs/context.c
++++ b/arch/powerpc/platforms/cell/spufs/context.c
+@@ -152,6 +152,8 @@ int spu_acquire_saved(struct spu_context *ctx)
+ {
+ 	int ret;
+ 
++	spu_context_nospu_trace(spu_acquire_saved__enter, ctx);
++
+ 	ret = spu_acquire(ctx);
+ 	if (ret)
+ 		return ret;

commit 8a476d49555cb7e8d4222782f695048b46692731
+Author: Julio M. Merino Vidal 
+Date:   Wed Apr 30 15:16:14 2008 +1000
+
+    [POWERPC] spufs: fix marker name for find_victim
+    
+    Fix a typo in the marker for the find_victim function, which prevented
+    it from being traced. It previously read find_vitim.
+    
+    Signed-off-by: Julio M. Merino Vidal 
+    Signed-off-by: Jeremy Kerr 
+
+diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
+index 31e9d85761c2..62280c292aac 100644
+--- a/arch/powerpc/platforms/cell/spufs/sched.c
++++ b/arch/powerpc/platforms/cell/spufs/sched.c
+@@ -593,7 +593,7 @@ static struct spu *find_victim(struct spu_context *ctx)
+ 	struct spu *spu;
+ 	int node, n;
+ 
+-	spu_context_nospu_trace(spu_find_vitim__enter, ctx);
++	spu_context_nospu_trace(spu_find_victim__enter, ctx);
+ 
+ 	/*
+ 	 * Look for a possible preemption candidate on the local node first.

commit 534578816f028b0dc675fdcc3314016d98588327
+Author: Julio M. Merino Vidal 
+Date:   Wed Apr 30 15:12:30 2008 +1000
+
+    [POWERPC] spufs: add marker for destroy_spu_context
+    
+    The sputrace module contained a reference to a marker for
+    destroy_spu_context, but this marker did not appear in the code. Fix
+    this by adding a marker in the function.
+    
+    Signed-off-by: Julio M. Merino Vidal 
+    Signed-off-by: Jeremy Kerr 
+
+diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
+index 91f2d4d9aefd..5c5010078042 100644
+--- a/arch/powerpc/platforms/cell/spufs/context.c
++++ b/arch/powerpc/platforms/cell/spufs/context.c
+@@ -78,6 +78,7 @@ void destroy_spu_context(struct kref *kref)
+ {
+ 	struct spu_context *ctx;
+ 	ctx = container_of(kref, struct spu_context, kref);
++	spu_context_nospu_trace(destroy_spu_context__enter, ctx);
+ 	mutex_lock(&ctx->state_mutex);
+ 	spu_deactivate(ctx);
+ 	mutex_unlock(&ctx->state_mutex);

commit d6508aaf27ccef0d7e986aaa220ad4d098bca260
+Author: Julio M. Merino Vidal 
+Date:   Wed Apr 30 15:06:39 2008 +1000
+
+    [POWERPC] spufs: add sputrace marker parameter names
+    
+    The markers facility defines the marker parameters to be of the form
+    'name %format'. Add parameter names to sputrace, to specify the context
+    and %spu paramerters,  instead of just specifying the '%format' part.
+    
+    Signed-off-by: Julio M. Merino Vidal 
+    Signed-off-by: Jeremy Kerr 
+
+diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
+index dd63b16bb072..7312745b7540 100644
+--- a/arch/powerpc/platforms/cell/spufs/spufs.h
++++ b/arch/powerpc/platforms/cell/spufs/spufs.h
+@@ -359,8 +359,8 @@ extern void spuctx_switch_state(struct spu_context *ctx,
+ 		enum spu_utilization_state new_state);
+ 
+ #define spu_context_trace(name, ctx, spu) \
+-	trace_mark(name, "%p %p", ctx, spu);
++	trace_mark(name, "ctx %p spu %p", ctx, spu);
+ #define spu_context_nospu_trace(name, ctx) \
+-	trace_mark(name, "%p", ctx);
++	trace_mark(name, "ctx %p", ctx);
+ 
+ #endif
+diff --git a/arch/powerpc/platforms/cell/spufs/sputrace.c b/arch/powerpc/platforms/cell/spufs/sputrace.c
+index 79aa773f3c99..b9c79eda3359 100644
+--- a/arch/powerpc/platforms/cell/spufs/sputrace.c
++++ b/arch/powerpc/platforms/cell/spufs/sputrace.c
+@@ -171,24 +171,24 @@ static void spu_context_nospu_event(void *probe_private, void *call_data,
+ }
+ 
+ struct spu_probe spu_probes[] = {
+-	{ "spu_bind_context__enter", "%p %p", spu_context_event },
+-	{ "spu_unbind_context__enter", "%p %p", spu_context_event },
+-	{ "spu_get_idle__enter", "%p", spu_context_nospu_event },
+-	{ "spu_get_idle__found", "%p %p", spu_context_event },
+-	{ "spu_get_idle__not_found", "%p", spu_context_nospu_event },
+-	{ "spu_find_victim__enter", "%p", spu_context_nospu_event },
+-	{ "spusched_tick__preempt", "%p %p", spu_context_event },
+-	{ "spusched_tick__newslice", "%p", spu_context_nospu_event },
+-	{ "spu_yield__enter", "%p", spu_context_nospu_event },
+-	{ "spu_deactivate__enter", "%p", spu_context_nospu_event },
+-	{ "__spu_deactivate__unload", "%p %p", spu_context_event },
+-	{ "spufs_ps_nopfn__enter", "%p", spu_context_nospu_event },
+-	{ "spufs_ps_nopfn__sleep", "%p", spu_context_nospu_event },
+-	{ "spufs_ps_nopfn__wake", "%p %p", spu_context_event },
+-	{ "spufs_ps_nopfn__insert", "%p %p", spu_context_event },
+-	{ "spu_acquire_saved__enter", "%p", spu_context_nospu_event },
+-	{ "destroy_spu_context__enter", "%p", spu_context_nospu_event },
+-	{ "spufs_stop_callback__enter", "%p %p", spu_context_event },
++	{ "spu_bind_context__enter", "ctx %p spu %p", spu_context_event },
++	{ "spu_unbind_context__enter", "ctx %p spu %p", spu_context_event },
++	{ "spu_get_idle__enter", "ctx %p", spu_context_nospu_event },
++	{ "spu_get_idle__found", "ctx %p spu %p", spu_context_event },
++	{ "spu_get_idle__not_found", "ctx %p", spu_context_nospu_event },
++	{ "spu_find_victim__enter", "ctx %p", spu_context_nospu_event },
++	{ "spusched_tick__preempt", "ctx %p spu %p", spu_context_event },
++	{ "spusched_tick__newslice", "ctx %p", spu_context_nospu_event },
++	{ "spu_yield__enter", "ctx %p", spu_context_nospu_event },
++	{ "spu_deactivate__enter", "ctx %p", spu_context_nospu_event },
++	{ "__spu_deactivate__unload", "ctx %p spu %p", spu_context_event },
++	{ "spufs_ps_nopfn__enter", "ctx %p", spu_context_nospu_event },
++	{ "spufs_ps_nopfn__sleep", "ctx %p", spu_context_nospu_event },
++	{ "spufs_ps_nopfn__wake", "ctx %p spu %p", spu_context_event },
++	{ "spufs_ps_nopfn__insert", "ctx %p spu %p", spu_context_event },
++	{ "spu_acquire_saved__enter", "ctx %p", spu_context_nospu_event },
++	{ "destroy_spu_context__enter", "ctx %p", spu_context_nospu_event },
++	{ "spufs_stop_callback__enter", "ctx %p spu %p", spu_context_event },
+ };
+ 
+ static int __init sputrace_init(void)

commit 9b1d21f858e8bad750ab19cac23dcbf79d099be3
+Author: Julio M. Merino Vidal 
+Date:   Thu Dec 20 16:39:59 2007 +0900
+
+    [POWERPC] spufs: fix typos in sched.c comments
+    
+    Fix a few typos in the spufs scheduler comments
+    
+    Signed-off-by: Julio M. Merino Vidal 
+    Signed-off-by: Jeremy Kerr 
+    Signed-off-by: Paul Mackerras 
+
+diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
+index 4d257b3f9336..0117eb8f6a91 100644
+--- a/arch/powerpc/platforms/cell/spufs/sched.c
++++ b/arch/powerpc/platforms/cell/spufs/sched.c
+@@ -105,15 +105,15 @@ void spu_set_timeslice(struct spu_context *ctx)
+ void __spu_update_sched_info(struct spu_context *ctx)
+ {
+ 	/*
+-	 * 32-Bit assignment are atomic on powerpc, and we don't care about
+-	 * memory ordering here because retriving the controlling thread is
+-	 * per defintion racy.
++	 * 32-Bit assignments are atomic on powerpc, and we don't care about
++	 * memory ordering here because retrieving the controlling thread is
++	 * per definition racy.
+ 	 */
+ 	ctx->tid = current->pid;
+ 
+ 	/*
+ 	 * We do our own priority calculations, so we normally want
+-	 * ->static_prio to start with. Unfortunately thies field
++	 * ->static_prio to start with. Unfortunately this field
+ 	 * contains junk for threads with a realtime scheduling
+ 	 * policy so we have to look at ->prio in this case.
+ 	 */
+@@ -127,7 +127,7 @@ void __spu_update_sched_info(struct spu_context *ctx)
+ 	 * A lot of places that don't hold list_mutex poke into
+ 	 * cpus_allowed, including grab_runnable_context which
+ 	 * already holds the runq_lock.  So abuse runq_lock
+-	 * to protect this field aswell.
++	 * to protect this field as well.
+ 	 */
+ 	spin_lock(&spu_prio->runq_lock);
+ 	ctx->cpus_allowed = current->cpus_allowed;
+@@ -182,7 +182,7 @@ static void notify_spus_active(void)
+ 	 * Wake up the active spu_contexts.
+ 	 *
+ 	 * When the awakened processes see their "notify_active" flag is set,
+-	 * they will call spu_switch_notify();
++	 * they will call spu_switch_notify().
+ 	 */
+ 	for_each_online_node(node) {
+ 		struct spu *spu;
+@@ -579,7 +579,7 @@ static struct spu *find_victim(struct spu_context *ctx)
+ 	/*
+ 	 * Look for a possible preemption candidate on the local node first.
+ 	 * If there is no candidate look at the other nodes.  This isn't
+-	 * exactly fair, but so far the whole spu schedule tries to keep
++	 * exactly fair, but so far the whole spu scheduler tries to keep
+ 	 * a strong node affinity.  We might want to fine-tune this in
+ 	 * the future.
+ 	 */
+@@ -905,7 +905,7 @@ static int show_spu_loadavg(struct seq_file *s, void *private)
+ 
+ 	/*
+ 	 * Note that last_pid doesn't really make much sense for the
+-	 * SPU loadavg (it even seems very odd on the CPU side..),
++	 * SPU loadavg (it even seems very odd on the CPU side...),
+ 	 * but we include it here to have a 100% compatible interface.
+ 	 */
+ 	seq_printf(s, "%d.%02d %d.%02d %d.%02d %ld/%d %d\n",

commit 568e0c1119d7ff33fbcddc0dec9e2c799a53352d
+Author: Julio M. Merino Vidal 
+Date:   Sat Oct 20 00:36:33 2007 +0200
+
+    powerpc: Remove obsolete prototype
+    
+    The include/asm-powerpc/paca.h file has a prototype for a function that
+    does not exist any more; its name is setup_boot_paca.  This function was
+    removed in commit 4ba99b97dadd35b9ce1438b2bc7c992a4a14a8b1, so its
+    prototype should have been removed at that time too.
+    
+    Signed-off-by: Julio M. Merino Vidal 
+    Signed-off-by: Adrian Bunk 
+
+diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h
+index 98c6bd5756b7..f6dfce025adf 100644
+--- a/include/asm-powerpc/paca.h
++++ b/include/asm-powerpc/paca.h
+@@ -121,7 +121,5 @@ struct paca_struct {
+ 
+ extern struct paca_struct paca[];
+ 
+-void setup_boot_paca(void);
+-
+ #endif /* __KERNEL__ */
+ #endif /* _ASM_POWERPC_PACA_H */

\ No newline at end of file diff --git a/detail/57.html b/detail/57.html new file mode 100644 index 0000000..bd3fa5b --- /dev/null +++ b/detail/57.html @@ -0,0 +1,168 @@ +

Patches contributed by Unknown (udo.edu)


commit 866af407dad3f2202e5d5d717ebd6156ccc33cdd
+Author: Andrej Gelenberg 
+Date:   Mon Aug 2 11:59:31 2010 +0200
+
+    nconfig: Fix segfault when menu is empty
+    
+    nconf crush with segfault if press right arrow in empty menu.
+    
+    Signed-off-by: Andrej Gelenberg 
+    Signed-off-by: Michal Marek 
+
+diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c
+index 762caf80ce37..2ba71bcd38e6 100644
+--- a/scripts/kconfig/nconf.c
++++ b/scripts/kconfig/nconf.c
+@@ -676,6 +676,8 @@ static void *item_data(void)
+ 	struct mitem *mcur;
+ 
+ 	cur = current_item(curses_menu);
++	if (!cur)
++		return NULL;
+ 	mcur = (struct mitem *) item_userptr(cur);
+ 	return mcur->usrptr;
+ 

commit ffe6275f90cc2ea77e6120a510903687be067b16
+Author: Andrej Gelenberg 
+Date:   Fri May 14 15:15:58 2010 -0700
+
+    [CPUFREQ] revert "[CPUFREQ] remove rwsem lock from CPUFREQ_GOV_STOP call (second call site)"
+    
+    395913d0b1db37092ea3d9d69b832183b1dd84c5 ("[CPUFREQ] remove rwsem lock
+    from CPUFREQ_GOV_STOP call (second call site)") is not needed, because
+    there is no rwsem lock in cpufreq_ondemand and cpufreq_conservative
+    anymore.  Lock should not be released until the work done.
+    
+    Addresses https://bugzilla.kernel.org/show_bug.cgi?id=1594
+    
+    Signed-off-by: Andrej Gelenberg 
+    Cc: Mathieu Desnoyers 
+    Cc: Venkatesh Pallipadi 
+    Signed-off-by: Andrew Morton 
+    Acked-by: Mathieu Desnoyers 
+    Signed-off-by: Dave Jones 
+
+diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
+index 063b2184caf5..8f22ce1ea684 100644
+--- a/drivers/cpufreq/cpufreq.c
++++ b/drivers/cpufreq/cpufreq.c
+@@ -1762,17 +1762,8 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,
+ 			dprintk("governor switch\n");
+ 
+ 			/* end old governor */
+-			if (data->governor) {
+-				/*
+-				 * Need to release the rwsem around governor
+-				 * stop due to lock dependency between
+-				 * cancel_delayed_work_sync and the read lock
+-				 * taken in the delayed work handler.
+-				 */
+-				unlock_policy_rwsem_write(data->cpu);
++			if (data->governor)
+ 				__cpufreq_governor(data, CPUFREQ_GOV_STOP);
+-				lock_policy_rwsem_write(data->cpu);
+-			}
+ 
+ 			/* start new governor */
+ 			data->governor = policy->governor;

commit accd846698439ba18250e8fd5681af280446b853
+Author: Andrej Gelenberg 
+Date:   Fri May 14 15:15:58 2010 -0700
+
+    [CPUFREQ] revert "[CPUFREQ] remove rwsem lock from CPUFREQ_GOV_STOP call (second call site)"
+    
+    395913d0b1db37092ea3d9d69b832183b1dd84c5 ("[CPUFREQ] remove rwsem lock
+    from CPUFREQ_GOV_STOP call (second call site)") is not needed, because
+    there is no rwsem lock in cpufreq_ondemand and cpufreq_conservative
+    anymore.  Lock should not be released until the work done.
+    
+    Addresses https://bugzilla.kernel.org/show_bug.cgi?id=1594
+    
+    Signed-off-by: Andrej Gelenberg 
+    Cc: Mathieu Desnoyers 
+    Cc: Venkatesh Pallipadi 
+    Signed-off-by: Andrew Morton 
+    Acked-by: Mathieu Desnoyers 
+    Signed-off-by: Dave Jones 
+
+diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
+index 063b2184caf5..8f22ce1ea684 100644
+--- a/drivers/cpufreq/cpufreq.c
++++ b/drivers/cpufreq/cpufreq.c
+@@ -1762,17 +1762,8 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,
+ 			dprintk("governor switch\n");
+ 
+ 			/* end old governor */
+-			if (data->governor) {
+-				/*
+-				 * Need to release the rwsem around governor
+-				 * stop due to lock dependency between
+-				 * cancel_delayed_work_sync and the read lock
+-				 * taken in the delayed work handler.
+-				 */
+-				unlock_policy_rwsem_write(data->cpu);
++			if (data->governor)
+ 				__cpufreq_governor(data, CPUFREQ_GOV_STOP);
+-				lock_policy_rwsem_write(data->cpu);
+-			}
+ 
+ 			/* start new governor */
+ 			data->governor = policy->governor;

commit 0217f1499cf880d93c64579b2943e9382d8c2c21
+Author: Andrej Gelenberg 
+Date:   Sun May 9 22:10:41 2010 +0200
+
+    ALSA: hda - add support for Lenovo ThinkPad X100e in conexant codec
+    
+    Ideapad quirks working for my ThinkPad X100e (microphone is not tested).
+    
+    Signed-off-by: Andrej Gelenberg 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
+index 56e52071c769..d8213e2231a6 100644
+--- a/sound/pci/hda/patch_conexant.c
++++ b/sound/pci/hda/patch_conexant.c
+@@ -2846,6 +2846,7 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
+ 	SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD),
+ 	SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5),
+ 	SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5),
++	SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD),
+ 	SND_PCI_QUIRK(0x17aa, 0x3a0d, "ideapad", CXT5066_IDEAPAD),
+ 	{}
+ };

commit eff7f270e9a05688066f40589d7b44e1dcf335dc
+Author: Andrej Gelenberg 
+Date:   Tue Mar 9 13:49:54 2010 +0100
+
+    HID: add quirk for UC-Logik WP4030 tablet
+    
+    Add HID_QUIRK_MULTI_INPUT for UC-Logik tablet.
+    
+    $ lsusb
+    ...
+    Bus 004 Device 002: ID 5543:0003 UC-Logic Technology Corp. Genius MousePen 4x3 Tablet/Aquila L1 Tablet
+    
+    Signed-off-by: Andrej Gelenberg 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
+index 72c05f90553c..797e06470356 100644
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -445,6 +445,7 @@
+ 
+ #define USB_VENDOR_ID_UCLOGIC		0x5543
+ #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209	0x0042
++#define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U	0x0003
+ 
+ #define USB_VENDOR_ID_VERNIER		0x08f7
+ #define USB_DEVICE_ID_VERNIER_LABPRO	0x0001
+diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
+index 7844280897d1..928943c7ce9a 100644
+--- a/drivers/hid/usbhid/hid-quirks.c
++++ b/drivers/hid/usbhid/hid-quirks.c
+@@ -63,6 +63,7 @@ static const struct hid_blacklist {
+ 	{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT },
++	{ USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT },
+ 	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
+ 	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
+ 

\ No newline at end of file diff --git a/detail/6.html b/detail/6.html new file mode 100644 index 0000000..1a3604e --- /dev/null +++ b/detail/6.html @@ -0,0 +1,16213 @@ +

Patches contributed by Zhejiang University


commit 309fdb1c33fe726d92d0030481346f24e1b01f07
+Author: Zhipeng Lu 
+Date:   Thu Dec 14 21:04:04 2023 +0800
+
+    ethernet: atheros: fix a memleak in atl1e_setup_ring_resources
+    
+    In the error handling of 'offset > adapter->ring_size', the
+    tx_ring->tx_buffer allocated by kzalloc should be freed,
+    instead of 'goto failed' instantly.
+    
+    Fixes: a6a5325239c2 ("atl1e: Atheros L1E Gigabit Ethernet driver")
+    Signed-off-by: Zhipeng Lu 
+    Reviewed-by: Suman Ghosh 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+index 5935be190b9e..5f2a6fcba967 100644
+--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
++++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+@@ -866,10 +866,13 @@ static int atl1e_setup_ring_resources(struct atl1e_adapter *adapter)
+ 		netdev_err(adapter->netdev, "offset(%d) > ring size(%d) !!\n",
+ 			   offset, adapter->ring_size);
+ 		err = -1;
+-		goto failed;
++		goto free_buffer;
+ 	}
+ 
+ 	return 0;
++free_buffer:
++	kfree(tx_ring->tx_buffer);
++	tx_ring->tx_buffer = NULL;
+ failed:
+ 	if (adapter->ring_vir_addr != NULL) {
+ 		dma_free_coherent(&pdev->dev, adapter->ring_size,

commit e75efc6466ae289e599fb12a5a86545dff245c65
+Author: Dinghao Liu 
+Date:   Tue Nov 28 17:40:53 2023 +0800
+
+    net/mlx5e: fix a potential double-free in fs_udp_create_groups
+    
+    When kcalloc() for ft->g succeeds but kvzalloc() for in fails,
+    fs_udp_create_groups() will free ft->g. However, its caller
+    fs_udp_create_table() will free ft->g again through calling
+    mlx5e_destroy_flow_table(), which will lead to a double-free.
+    Fix this by setting ft->g to NULL in fs_udp_create_groups().
+    
+    Fixes: 1c80bd684388 ("net/mlx5e: Introduce Flow Steering UDP API")
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Tariq Toukan 
+    Reviewed-by: Simon Horman 
+    Signed-off-by: Saeed Mahameed 
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c b/drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c
+index be83ad9db82a..e1283531e0b8 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c
+@@ -154,6 +154,7 @@ static int fs_udp_create_groups(struct mlx5e_flow_table *ft, enum fs_udp_type ty
+ 	in = kvzalloc(inlen, GFP_KERNEL);
+ 	if  (!in || !ft->g) {
+ 		kfree(ft->g);
++		ft->g = NULL;
+ 		kvfree(in);
+ 		return -ENOMEM;
+ 	}

commit b65d52ac9c085c0c52dee012a210d4e2f352611b
+Author: Dinghao Liu 
+Date:   Sun Dec 10 12:52:55 2023 +0800
+
+    qed: Fix a potential use-after-free in qed_cxt_tables_alloc
+    
+    qed_ilt_shadow_alloc() will call qed_ilt_shadow_free() to
+    free p_hwfn->p_cxt_mngr->ilt_shadow on error. However,
+    qed_cxt_tables_alloc() accesses the freed pointer on failure
+    of qed_ilt_shadow_alloc() through calling qed_cxt_mngr_free(),
+    which may lead to use-after-free. Fix this issue by setting
+    p_mngr->ilt_shadow to NULL in qed_ilt_shadow_free().
+    
+    Fixes: fe56b9e6a8d9 ("qed: Add module with basic common support")
+    Reviewed-by: Przemek Kitszel 
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20231210045255.21383-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/drivers/net/ethernet/qlogic/qed/qed_cxt.c b/drivers/net/ethernet/qlogic/qed/qed_cxt.c
+index 65e20693c549..33f4f58ee51c 100644
+--- a/drivers/net/ethernet/qlogic/qed/qed_cxt.c
++++ b/drivers/net/ethernet/qlogic/qed/qed_cxt.c
+@@ -933,6 +933,7 @@ static void qed_ilt_shadow_free(struct qed_hwfn *p_hwfn)
+ 		p_dma->virt_addr = NULL;
+ 	}
+ 	kfree(p_mngr->ilt_shadow);
++	p_mngr->ilt_shadow = NULL;
+ }
+ 
+ static int qed_ilt_blk_alloc(struct qed_hwfn *p_hwfn,

commit 28a7cb045ab700de5554193a1642917602787784
+Author: Zhipeng Lu 
+Date:   Thu Dec 7 17:49:16 2023 +0800
+
+    octeontx2-af: fix a use-after-free in rvu_nix_register_reporters
+    
+    The rvu_dl will be freed in rvu_nix_health_reporters_destroy(rvu_dl)
+    after the create_workqueue fails, and after that free, the rvu_dl will
+    be translate back through the following call chain:
+    
+    rvu_nix_health_reporters_destroy
+      |-> rvu_nix_health_reporters_create
+           |-> rvu_health_reporters_create
+                 |-> rvu_register_dl (label err_dl_health)
+    
+    Finally. in the err_dl_health label, rvu_dl being freed again in
+    rvu_health_reporters_destroy(rvu) by rvu_nix_health_reporters_destroy.
+    In the second calls of rvu_nix_health_reporters_destroy, however,
+    it uses rvu_dl->rvu_nix_health_reporter, which is already freed at
+    the end of rvu_nix_health_reporters_destroy in the first call.
+    
+    So this patch prevents the first destroy by instantly returning -ENONMEN
+    when create_workqueue fails. In addition, since the failure of
+    create_workqueue is the only entrence of label err, it has been
+    integrated into the error-handling path of create_workqueue.
+    
+    Fixes: 5ed66306eab6 ("octeontx2-af: Add devlink health reporters for NIX")
+    Signed-off-by: Zhipeng Lu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
+index 62780d8b4f9a..21b5d71c1e37 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
+@@ -538,7 +538,7 @@ static int rvu_nix_register_reporters(struct rvu_devlink *rvu_dl)
+ 
+ 	rvu_dl->devlink_wq = create_workqueue("rvu_devlink_wq");
+ 	if (!rvu_dl->devlink_wq)
+-		goto err;
++		return -ENOMEM;
+ 
+ 	INIT_WORK(&rvu_reporters->intr_work, rvu_nix_intr_work);
+ 	INIT_WORK(&rvu_reporters->gen_work, rvu_nix_gen_work);
+@@ -546,9 +546,6 @@ static int rvu_nix_register_reporters(struct rvu_devlink *rvu_dl)
+ 	INIT_WORK(&rvu_reporters->ras_work, rvu_nix_ras_work);
+ 
+ 	return 0;
+-err:
+-	rvu_nix_health_reporters_destroy(rvu_dl);
+-	return -ENOMEM;
+ }
+ 
+ static int rvu_nix_health_reporters_create(struct rvu_devlink *rvu_dl)

commit d007caaaf052f82ca2340d4c7b32d04a3f5dbf3f
+Author: Dinghao Liu 
+Date:   Mon Dec 4 10:40:04 2023 +0800
+
+    net: bnxt: fix a potential use-after-free in bnxt_init_tc
+    
+    When flow_indr_dev_register() fails, bnxt_init_tc will free
+    bp->tc_info through kfree(). However, the caller function
+    bnxt_init_one() will ignore this failure and call
+    bnxt_shutdown_tc() on failure of bnxt_dl_register(), where
+    a use-after-free happens. Fix this issue by setting
+    bp->tc_info to NULL after kfree().
+    
+    Fixes: 627c89d00fb9 ("bnxt_en: flow_offload: offload tunnel decap rules via indirect callbacks")
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Pavan Chebbi 
+    Reviewed-by: Michael Chan 
+    Reviewed-by: Somnath Kotur 
+    Link: https://lore.kernel.org/r/20231204024004.8245-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
+index 38d89d80b4a9..273c9ba48f09 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
+@@ -2075,6 +2075,7 @@ int bnxt_init_tc(struct bnxt *bp)
+ 	rhashtable_destroy(&tc_info->flow_table);
+ free_tc_info:
+ 	kfree(tc_info);
++	bp->tc_info = NULL;
+ 	return rc;
+ }
+ 

commit 235f2b548d7f4ac5931d834f05d3f7f5166a2e72
+Author: Dinghao Liu 
+Date:   Thu Nov 23 16:19:41 2023 +0800
+
+    scsi: be2iscsi: Fix a memleak in beiscsi_init_wrb_handle()
+    
+    When an error occurs in the for loop of beiscsi_init_wrb_handle(), we
+    should free phwi_ctxt->be_wrbq before returning an error code to prevent
+    potential memleak.
+    
+    Fixes: a7909b396ba7 ("[SCSI] be2iscsi: Fix dynamic CID allocation Mechanism in driver")
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20231123081941.24854-1-dinghao.liu@zju.edu.cn
+    Reviewed-by: Mike Christie 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
+index e48f14ad6dfd..06acb5ff609e 100644
+--- a/drivers/scsi/be2iscsi/be_main.c
++++ b/drivers/scsi/be2iscsi/be_main.c
+@@ -2710,6 +2710,7 @@ static int beiscsi_init_wrb_handle(struct beiscsi_hba *phba)
+ 		kfree(pwrb_context->pwrb_handle_base);
+ 		kfree(pwrb_context->pwrb_handle_basestd);
+ 	}
++	kfree(phwi_ctxt->be_wrbq);
+ 	return -ENOMEM;
+ }
+ 

commit 3c91c909f13f0c32b0d54d75c3f798479b1a84f5
+Author: Zhipeng Lu 
+Date:   Sat Dec 2 17:59:02 2023 +0800
+
+    octeontx2-af: fix a use-after-free in rvu_npa_register_reporters
+    
+    The rvu_dl will be freed in rvu_npa_health_reporters_destroy(rvu_dl)
+    after the create_workqueue fails, and after that free, the rvu_dl will
+    be translate back through rvu_npa_health_reporters_create,
+    rvu_health_reporters_create, and rvu_register_dl. Finally it goes to the
+    err_dl_health label, being freed again in
+    rvu_health_reporters_destroy(rvu) by rvu_npa_health_reporters_destroy.
+    In the second calls of rvu_npa_health_reporters_destroy, however,
+    it uses rvu_dl->rvu_npa_health_reporter, which is already freed at
+    the end of rvu_npa_health_reporters_destroy in the first call.
+    
+    So this patch prevents the first destroy by instantly returning -ENONMEN
+    when create_workqueue fails. In addition, since the failure of
+    create_workqueue is the only entrence of label err, it has been
+    integrated into the error-handling path of create_workqueue.
+    
+    Fixes: f1168d1e207c ("octeontx2-af: Add devlink health reporters for NPA")
+    Signed-off-by: Zhipeng Lu 
+    Acked-by: Paolo Abeni 
+    Acked-by: Geethasowjanya Akula 
+    Link: https://lore.kernel.org/r/20231202095902.3264863-1-alexious@zju.edu.cn
+    Signed-off-by: Paolo Abeni 
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
+index c70932625d0d..62780d8b4f9a 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
+@@ -1087,7 +1087,7 @@ static int rvu_npa_register_reporters(struct rvu_devlink *rvu_dl)
+ 
+ 	rvu_dl->devlink_wq = create_workqueue("rvu_devlink_wq");
+ 	if (!rvu_dl->devlink_wq)
+-		goto err;
++		return -ENOMEM;
+ 
+ 	INIT_WORK(&rvu_reporters->intr_work, rvu_npa_intr_work);
+ 	INIT_WORK(&rvu_reporters->err_work, rvu_npa_err_work);
+@@ -1095,9 +1095,6 @@ static int rvu_npa_register_reporters(struct rvu_devlink *rvu_dl)
+ 	INIT_WORK(&rvu_reporters->ras_work, rvu_npa_ras_work);
+ 
+ 	return 0;
+-err:
+-	rvu_npa_health_reporters_destroy(rvu_dl);
+-	return -ENOMEM;
+ }
+ 
+ static int rvu_npa_health_reporters_create(struct rvu_devlink *rvu_dl)

commit 29046a78a3c0a1f8fa0427f164caa222f003cf5b
+Author: Dinghao Liu 
+Date:   Mon Dec 4 15:41:56 2023 +0800
+
+    ASoC: wm_adsp: fix memleak in wm_adsp_buffer_populate
+    
+    When wm_adsp_buffer_read() fails, we should free buf->regions.
+    Otherwise, the callers of wm_adsp_buffer_populate() will
+    directly free buf on failure, which makes buf->regions a leaked
+    memory.
+    
+    Fixes: a792af69b08f ("ASoC: wm_adsp: Refactor compress stream initialisation")
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Richard Fitzgerald 
+    Link: https://lore.kernel.org/r/20231204074158.12026-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
+index 236b12b69ae5..c01e31175015 100644
+--- a/sound/soc/codecs/wm_adsp.c
++++ b/sound/soc/codecs/wm_adsp.c
+@@ -1451,12 +1451,12 @@ static int wm_adsp_buffer_populate(struct wm_adsp_compr_buf *buf)
+ 		ret = wm_adsp_buffer_read(buf, caps->region_defs[i].base_offset,
+ 					  ®ion->base_addr);
+ 		if (ret < 0)
+-			return ret;
++			goto err;
+ 
+ 		ret = wm_adsp_buffer_read(buf, caps->region_defs[i].size_offset,
+ 					  &offset);
+ 		if (ret < 0)
+-			return ret;
++			goto err;
+ 
+ 		region->cumulative_size = offset;
+ 
+@@ -1467,6 +1467,10 @@ static int wm_adsp_buffer_populate(struct wm_adsp_compr_buf *buf)
+ 	}
+ 
+ 	return 0;
++
++err:
++	kfree(buf->regions);
++	return ret;
+ }
+ 
+ static void wm_adsp_buffer_clear(struct wm_adsp_compr_buf *buf)

commit 7a88f23e768491bae653b444a96091d2aaeb0818
+Author: Dinghao Liu 
+Date:   Thu Nov 23 15:33:22 2023 +0800
+
+    drm/amd/pm: fix a memleak in aldebaran_tables_init
+    
+    When kzalloc() for smu_table->ecc_table fails, we should free
+    the previously allocated resources to prevent memleak.
+    
+    Fixes: edd794208555 ("drm/amd/pm: add message smu to get ecc_table v2")
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Alex Deucher 
+
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
+index 1a6675d70a4b..f1440869d1ce 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
+@@ -257,8 +257,11 @@ static int aldebaran_tables_init(struct smu_context *smu)
+ 	}
+ 
+ 	smu_table->ecc_table = kzalloc(tables[SMU_TABLE_ECCINFO].size, GFP_KERNEL);
+-	if (!smu_table->ecc_table)
++	if (!smu_table->ecc_table) {
++		kfree(smu_table->metrics_table);
++		kfree(smu_table->gpu_metrics_table);
+ 		return -ENOMEM;
++	}
+ 
+ 	return 0;
+ }

commit 759c409bc5fc496cbc22cd0b392d3cbb0c0e23eb
+Author: Dinghao Liu 
+Date:   Mon Sep 25 10:41:33 2023 +0800
+
+    mfd: dln2: Fix double put in dln2_probe
+    
+    The dln2_free() already contains usb_put_dev(). Therefore,
+    the redundant usb_put_dev() before dln2_free() may lead to
+    a double free.
+    
+    Fixes: 96da8f148396 ("mfd: dln2: Fix memory leak in dln2_probe()")
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20230925024134.9683-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Lee Jones 
+
+diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c
+index c7510434380a..fbbe82c6e75b 100644
+--- a/drivers/mfd/dln2.c
++++ b/drivers/mfd/dln2.c
+@@ -826,7 +826,6 @@ static int dln2_probe(struct usb_interface *interface,
+ 	dln2_stop_rx_urbs(dln2);
+ 
+ out_free:
+-	usb_put_dev(dln2->usb_dev);
+ 	dln2_free(dln2);
+ 
+ 	return ret;

commit 63e8b94ad1840f02462633abdb363397f56bc642
+Author: Dinghao Liu 
+Date:   Thu Sep 21 15:14:12 2023 +0800
+
+    s390/cio: fix a memleak in css_alloc_subchannel
+    
+    When dma_set_coherent_mask() fails, sch->lock has not been
+    freed, which is allocated in css_sch_create_locks(), leading
+    to a memleak.
+    
+    Fixes: 4520a91a976e ("s390/cio: use dma helpers for setting masks")
+    Signed-off-by: Dinghao Liu 
+    Message-Id: <20230921071412.13806-1-dinghao.liu@zju.edu.cn>
+    Link: https://lore.kernel.org/linux-s390/bd38baa8-7b9d-4d89-9422-7e943d626d6e@linux.ibm.com/
+    Reviewed-by: Halil Pasic 
+    Reviewed-by: Peter Oberparleiter 
+    Signed-off-by: Vasily Gorbik 
+
+diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
+index 3ef636935a54..3ff46fc694f8 100644
+--- a/drivers/s390/cio/css.c
++++ b/drivers/s390/cio/css.c
+@@ -233,17 +233,19 @@ struct subchannel *css_alloc_subchannel(struct subchannel_id schid,
+ 	 */
+ 	ret = dma_set_coherent_mask(&sch->dev, DMA_BIT_MASK(31));
+ 	if (ret)
+-		goto err;
++		goto err_lock;
+ 	/*
+ 	 * But we don't have such restrictions imposed on the stuff that
+ 	 * is handled by the streaming API.
+ 	 */
+ 	ret = dma_set_mask(&sch->dev, DMA_BIT_MASK(64));
+ 	if (ret)
+-		goto err;
++		goto err_lock;
+ 
+ 	return sch;
+ 
++err_lock:
++	kfree(sch->lock);
+ err:
+ 	kfree(sch);
+ 	return ERR_PTR(ret);

commit f990874b1c98fe8e57ee9385669f501822979258
+Author: Dinghao Liu 
+Date:   Sat Oct 7 11:30:49 2023 +0800
+
+    ieee802154: ca8210: Fix a potential UAF in ca8210_probe
+    
+    If of_clk_add_provider() fails in ca8210_register_ext_clock(),
+    it calls clk_unregister() to release priv->clk and returns an
+    error. However, the caller ca8210_probe() then calls ca8210_remove(),
+    where priv->clk is freed again in ca8210_unregister_ext_clock(). In
+    this case, a use-after-free may happen in the second time we call
+    clk_unregister().
+    
+    Fix this by removing the first clk_unregister(). Also, priv->clk could
+    be an error code on failure of clk_register_fixed_rate(). Use
+    IS_ERR_OR_NULL to catch this case in ca8210_unregister_ext_clock().
+    
+    Fixes: ded845a781a5 ("ieee802154: Add CA8210 IEEE 802.15.4 device driver")
+    Signed-off-by: Dinghao Liu 
+    Message-ID: <20231007033049.22353-1-dinghao.liu@zju.edu.cn>
+    Signed-off-by: Stefan Schmidt 
+
+diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c
+index aebb19f1b3a4..4ec0dab38872 100644
+--- a/drivers/net/ieee802154/ca8210.c
++++ b/drivers/net/ieee802154/ca8210.c
+@@ -2740,7 +2740,6 @@ static int ca8210_register_ext_clock(struct spi_device *spi)
+ 	struct device_node *np = spi->dev.of_node;
+ 	struct ca8210_priv *priv = spi_get_drvdata(spi);
+ 	struct ca8210_platform_data *pdata = spi->dev.platform_data;
+-	int ret = 0;
+ 
+ 	if (!np)
+ 		return -EFAULT;
+@@ -2757,18 +2756,8 @@ static int ca8210_register_ext_clock(struct spi_device *spi)
+ 		dev_crit(&spi->dev, "Failed to register external clk\n");
+ 		return PTR_ERR(priv->clk);
+ 	}
+-	ret = of_clk_add_provider(np, of_clk_src_simple_get, priv->clk);
+-	if (ret) {
+-		clk_unregister(priv->clk);
+-		dev_crit(
+-			&spi->dev,
+-			"Failed to register external clock as clock provider\n"
+-		);
+-	} else {
+-		dev_info(&spi->dev, "External clock set as clock provider\n");
+-	}
+ 
+-	return ret;
++	return of_clk_add_provider(np, of_clk_src_simple_get, priv->clk);
+ }
+ 
+ /**
+@@ -2780,8 +2769,8 @@ static void ca8210_unregister_ext_clock(struct spi_device *spi)
+ {
+ 	struct ca8210_priv *priv = spi_get_drvdata(spi);
+ 
+-	if (!priv->clk)
+-		return
++	if (IS_ERR_OR_NULL(priv->clk))
++		return;
+ 
+ 	of_clk_del_provider(spi->dev.of_node);
+ 	clk_unregister(priv->clk);

commit 01f1ae2733e2bb4de92fefcea5fda847d92aede1
+Author: Duoming Zhou 
+Date:   Sun Aug 6 11:25:11 2023 +0800
+
+    dmaengine: mediatek: Fix deadlock caused by synchronize_irq()
+    
+    The synchronize_irq(c->irq) will not return until the IRQ handler
+    mtk_uart_apdma_irq_handler() is completed. If the synchronize_irq()
+    holds a spin_lock and waits the IRQ handler to complete, but the
+    IRQ handler also needs the same spin_lock. The deadlock will happen.
+    The process is shown below:
+    
+              cpu0                        cpu1
+    mtk_uart_apdma_device_pause() | mtk_uart_apdma_irq_handler()
+      spin_lock_irqsave()         |
+                                  |   spin_lock_irqsave()
+      //hold the lock to wait     |
+      synchronize_irq()           |
+    
+    This patch reorders the synchronize_irq(c->irq) outside the spin_lock
+    in order to mitigate the bug.
+    
+    Fixes: 9135408c3ace ("dmaengine: mediatek: Add MediaTek UART APDMA support")
+    Signed-off-by: Duoming Zhou 
+    Reviewed-by: Eugen Hristev 
+    Link: https://lore.kernel.org/r/20230806032511.45263-1-duoming@zju.edu.cn
+    Signed-off-by: Vinod Koul 
+
+diff --git a/drivers/dma/mediatek/mtk-uart-apdma.c b/drivers/dma/mediatek/mtk-uart-apdma.c
+index c51dc017b48a..06d12ac39144 100644
+--- a/drivers/dma/mediatek/mtk-uart-apdma.c
++++ b/drivers/dma/mediatek/mtk-uart-apdma.c
+@@ -450,9 +450,8 @@ static int mtk_uart_apdma_device_pause(struct dma_chan *chan)
+ 	mtk_uart_apdma_write(c, VFF_EN, VFF_EN_CLR_B);
+ 	mtk_uart_apdma_write(c, VFF_INT_EN, VFF_INT_EN_CLR_B);
+ 
+-	synchronize_irq(c->irq);
+-
+ 	spin_unlock_irqrestore(&c->vc.lock, flags);
++	synchronize_irq(c->irq);
+ 
+ 	return 0;
+ }

commit caa0578c1d487d39e4bb947a1b4965417053b409
+Author: Dinghao Liu 
+Date:   Fri Sep 22 17:40:44 2023 +0800
+
+    ptp: ocp: Fix error handling in ptp_ocp_device_init
+    
+    When device_add() fails, ptp_ocp_dev_release() will be called
+    after put_device(). Therefore, it seems that the
+    ptp_ocp_dev_release() before put_device() is redundant.
+    
+    Fixes: 773bda964921 ("ptp: ocp: Expose various resources on the timecard.")
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Vadim Feodrenko 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
+index 20a974ced8d6..a7a6947ab4bc 100644
+--- a/drivers/ptp/ptp_ocp.c
++++ b/drivers/ptp/ptp_ocp.c
+@@ -3998,7 +3998,6 @@ ptp_ocp_device_init(struct ptp_ocp *bp, struct pci_dev *pdev)
+ 	return 0;
+ 
+ out:
+-	ptp_ocp_dev_release(&bp->dev);
+ 	put_device(&bp->dev);
+ 	return err;
+ }

commit b481f644d9174670b385c3a699617052cd2a79d3
+Author: Dinghao Liu 
+Date:   Sat Sep 23 18:37:23 2023 +0800
+
+    scsi: zfcp: Fix a double put in zfcp_port_enqueue()
+    
+    When device_register() fails, zfcp_port_release() will be called after
+    put_device(). As a result, zfcp_ccw_adapter_put() will be called twice: one
+    in zfcp_port_release() and one in the error path after device_register().
+    So the reference on the adapter object is doubly put, which may lead to a
+    premature free. Fix this by adjusting the error tag after
+    device_register().
+    
+    Fixes: f3450c7b9172 ("[SCSI] zfcp: Replace local reference counting with common kref")
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20230923103723.10320-1-dinghao.liu@zju.edu.cn
+    Acked-by: Benjamin Block 
+    Cc: stable@vger.kernel.org # v2.6.33+
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
+index df782646e856..ab2f35bc294d 100644
+--- a/drivers/s390/scsi/zfcp_aux.c
++++ b/drivers/s390/scsi/zfcp_aux.c
+@@ -518,12 +518,12 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
+ 	if (port) {
+ 		put_device(&port->dev);
+ 		retval = -EEXIST;
+-		goto err_out;
++		goto err_put;
+ 	}
+ 
+ 	port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL);
+ 	if (!port)
+-		goto err_out;
++		goto err_put;
+ 
+ 	rwlock_init(&port->unit_list_lock);
+ 	INIT_LIST_HEAD(&port->unit_list);
+@@ -546,7 +546,7 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
+ 
+ 	if (dev_set_name(&port->dev, "0x%016llx", (unsigned long long)wwpn)) {
+ 		kfree(port);
+-		goto err_out;
++		goto err_put;
+ 	}
+ 	retval = -EINVAL;
+ 
+@@ -563,7 +563,8 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
+ 
+ 	return port;
+ 
+-err_out:
++err_put:
+ 	zfcp_ccw_adapter_put(adapter);
++err_out:
+ 	return ERR_PTR(retval);
+ }

commit cab63f64887616e3c4e31cfd8103320be6ebc8d3
+Author: Dinghao Liu 
+Date:   Thu Sep 21 16:24:10 2023 +0800
+
+    i3c: Fix potential refcount leak in i3c_master_register_new_i3c_devs
+    
+    put_device() needs to be called on failure of device_register()
+    to give up the reference initialized in it to avoid refcount leak.
+    
+    Fixes: 3a379bbcea0a ("i3c: Add core I3C infrastructure")
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20230921082410.25548-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Alexandre Belloni 
+
+diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
+index 839eb8b4bbde..e66a1f84cefb 100644
+--- a/drivers/i3c/master.c
++++ b/drivers/i3c/master.c
+@@ -1525,9 +1525,11 @@ i3c_master_register_new_i3c_devs(struct i3c_master_controller *master)
+ 			desc->dev->dev.of_node = desc->boardinfo->of_node;
+ 
+ 		ret = device_register(&desc->dev->dev);
+-		if (ret)
++		if (ret) {
+ 			dev_err(&master->dev,
+ 				"Failed to add I3C device (err = %d)\n", ret);
++			put_device(&desc->dev->dev);
++		}
+ 	}
+ }
+ 

commit f4dcf06bc6e0161920b700ba3966411d716a321b
+Author: Dinghao Liu 
+Date:   Mon Sep 25 16:08:44 2023 +0800
+
+    ACPI: video: Fix NULL pointer dereference in acpi_video_bus_add()
+    
+    acpi_video_bus_add_notify_handler() could free video->input and
+    set it to NULL on failure, but this failure would be missed in its
+    caller acpi_video_bus_add(). As a result, when an error happens in
+    acpi_dev_install_notify_handler(), acpi_video_bus_add() would call
+    acpi_video_bus_remove_notify_handler(), where a potential NULL pointer
+    video->input is dereferenced in input_unregister_device().
+    
+    Fix this by adding a return value check and adjusting the following
+    error handling code.
+    
+    Fixes: 6f7016819766 ("ACPI: video: Install Notify() handler directly")
+    Signed-off-by: Dinghao Liu 
+    [ rjw: Subject and changelog edits ]
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c
+index 948e31f7ce6e..b411948594ff 100644
+--- a/drivers/acpi/acpi_video.c
++++ b/drivers/acpi/acpi_video.c
+@@ -2057,7 +2057,9 @@ static int acpi_video_bus_add(struct acpi_device *device)
+ 	    !auto_detect)
+ 		acpi_video_bus_register_backlight(video);
+ 
+-	acpi_video_bus_add_notify_handler(video);
++	error = acpi_video_bus_add_notify_handler(video);
++	if (error)
++		goto err_del;
+ 
+ 	error = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
+ 						acpi_video_bus_notify);
+@@ -2067,10 +2069,11 @@ static int acpi_video_bus_add(struct acpi_device *device)
+ 	return 0;
+ 
+ err_remove:
++	acpi_video_bus_remove_notify_handler(video);
++err_del:
+ 	mutex_lock(&video_list_lock);
+ 	list_del(&video->entry);
+ 	mutex_unlock(&video_list_lock);
+-	acpi_video_bus_remove_notify_handler(video);
+ 	acpi_video_bus_unregister_backlight(video);
+ err_put_video:
+ 	acpi_video_bus_put_devices(video);

commit 246f80a0b17f8f582b2c0996db02998239057c65
+Author: Duoming Zhou 
+Date:   Wed Aug 2 11:37:37 2023 +0800
+
+    sh: push-switch: Reorder cleanup operations to avoid use-after-free bug
+    
+    The original code puts flush_work() before timer_shutdown_sync()
+    in switch_drv_remove(). Although we use flush_work() to stop
+    the worker, it could be rescheduled in switch_timer(). As a result,
+    a use-after-free bug can occur. The details are shown below:
+    
+          (cpu 0)                    |      (cpu 1)
+    switch_drv_remove()              |
+     flush_work()                    |
+      ...                            |  switch_timer // timer
+                                     |   schedule_work(&psw->work)
+     timer_shutdown_sync()           |
+     ...                             |  switch_work_handler // worker
+     kfree(psw) // free              |
+                                     |   psw->state = 0 // use
+    
+    This patch puts timer_shutdown_sync() before flush_work() to
+    mitigate the bugs. As a result, the worker and timer will be
+    stopped safely before the deallocate operations.
+    
+    Fixes: 9f5e8eee5cfe ("sh: generic push-switch framework.")
+    Signed-off-by: Duoming Zhou 
+    Reviewed-by: Geert Uytterhoeven 
+    Reviewed-by: John Paul Adrian Glaubitz 
+    Link: https://lore.kernel.org/r/20230802033737.9738-1-duoming@zju.edu.cn
+    Signed-off-by: John Paul Adrian Glaubitz 
+
+diff --git a/arch/sh/drivers/push-switch.c b/arch/sh/drivers/push-switch.c
+index c95f48ff3f6f..6ecba5f521eb 100644
+--- a/arch/sh/drivers/push-switch.c
++++ b/arch/sh/drivers/push-switch.c
+@@ -101,8 +101,8 @@ static int switch_drv_remove(struct platform_device *pdev)
+ 		device_remove_file(&pdev->dev, &dev_attr_switch);
+ 
+ 	platform_set_drvdata(pdev, NULL);
+-	flush_work(&psw->work);
+ 	timer_shutdown_sync(&psw->debounce);
++	flush_work(&psw->work);
+ 	free_irq(irq, pdev);
+ 
+ 	kfree(psw);

commit 218d690c49b7e9c94ad0d317adbdd4af846ea0dc
+Author: Lin Ma 
+Date:   Wed Aug 9 11:31:51 2023 +0800
+
+    wifi: nl80211/cfg80211: add forgotten nla_policy for BSS color attribute
+    
+    The previous commit dd3e4fc75b4a ("nl80211/cfg80211: add BSS color to
+    NDP ranging parameters") adds a parameter for NDP ranging by introducing
+    a new attribute type named NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR.
+    
+    However, the author forgot to also describe the nla_policy at
+    nl80211_pmsr_ftm_req_attr_policy (net/wireless/nl80211.c). Just
+    complement it to avoid malformed attribute that causes out-of-attribute
+    access.
+    
+    Fixes: dd3e4fc75b4a ("nl80211/cfg80211: add BSS color to NDP ranging parameters")
+    Signed-off-by: Lin Ma 
+    Reviewed-by: Simon Horman 
+    Link: https://lore.kernel.org/r/20230809033151.768910-1-linma@zju.edu.cn
+    Signed-off-by: Johannes Berg 
+
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index 0ffebf1a1eb6..de47838aca4f 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -323,6 +323,7 @@ nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = {
+ 	[NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED] = { .type = NLA_FLAG },
+ 	[NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED] = { .type = NLA_FLAG },
+ 	[NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK] = { .type = NLA_FLAG },
++	[NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR] = { .type = NLA_U8 },
+ };
+ 
+ static const struct nla_policy

commit 5d6ba607d6cb5c58a4ddf33381e18c83dbb4098f
+Author: Lin Ma 
+Date:   Thu Jul 27 20:57:52 2023 +0300
+
+    vdpa: Add max vqp attr to vdpa_nl_policy for nlattr length check
+    
+    The vdpa_nl_policy structure is used to validate the nlattr when parsing
+    the incoming nlmsg. It will ensure the attribute being described produces
+    a valid nlattr pointer in info->attrs before entering into each handler
+    in vdpa_nl_ops.
+    
+    That is to say, the missing part in vdpa_nl_policy may lead to illegal
+    nlattr after parsing, which could lead to OOB read just like CVE-2023-3773.
+    
+    This patch adds the missing nla_policy for vdpa max vqp attr to avoid
+    such bugs.
+    
+    Fixes: ad69dd0bf26b ("vdpa: Introduce query of device config layout")
+    Signed-off-by: Lin Ma 
+    Cc: stable@vger.kernel.org
+    Message-Id: <20230727175757.73988-7-dtatulea@nvidia.com>
+    Signed-off-by: Michael S. Tsirkin 
+
+diff --git a/drivers/vdpa/vdpa.c b/drivers/vdpa/vdpa.c
+index 75f1df2b9d2a..f2f654fd84e5 100644
+--- a/drivers/vdpa/vdpa.c
++++ b/drivers/vdpa/vdpa.c
+@@ -1247,6 +1247,7 @@ static const struct nla_policy vdpa_nl_policy[VDPA_ATTR_MAX + 1] = {
+ 	[VDPA_ATTR_MGMTDEV_DEV_NAME] = { .type = NLA_STRING },
+ 	[VDPA_ATTR_DEV_NAME] = { .type = NLA_STRING },
+ 	[VDPA_ATTR_DEV_NET_CFG_MACADDR] = NLA_POLICY_ETH_ADDR,
++	[VDPA_ATTR_DEV_NET_CFG_MAX_VQP] = { .type = NLA_U16 },
+ 	/* virtio spec 1.1 section 5.1.4.1 for valid MTU range */
+ 	[VDPA_ATTR_DEV_NET_CFG_MTU] = NLA_POLICY_MIN(NLA_U16, 68),
+ 	[VDPA_ATTR_DEV_QUEUE_INDEX] = { .type = NLA_U32 },

commit b3003e1b54e057f5f3124e437b80c3bef26ed3fe
+Author: Lin Ma 
+Date:   Thu Jul 27 20:57:50 2023 +0300
+
+    vdpa: Add queue index attr to vdpa_nl_policy for nlattr length check
+    
+    The vdpa_nl_policy structure is used to validate the nlattr when parsing
+    the incoming nlmsg. It will ensure the attribute being described produces
+    a valid nlattr pointer in info->attrs before entering into each handler
+    in vdpa_nl_ops.
+    
+    That is to say, the missing part in vdpa_nl_policy may lead to illegal
+    nlattr after parsing, which could lead to OOB read just like CVE-2023-3773.
+    
+    This patch adds the missing nla_policy for vdpa queue index attr to avoid
+    such bugs.
+    
+    Fixes: 13b00b135665 ("vdpa: Add support for querying vendor statistics")
+    Signed-off-by: Lin Ma 
+    Cc: stable@vger.kernelorg
+    Message-Id: <20230727175757.73988-5-dtatulea@nvidia.com>
+    Signed-off-by: Michael S. Tsirkin 
+
+diff --git a/drivers/vdpa/vdpa.c b/drivers/vdpa/vdpa.c
+index 3ad355a2208a..75f1df2b9d2a 100644
+--- a/drivers/vdpa/vdpa.c
++++ b/drivers/vdpa/vdpa.c
+@@ -1249,6 +1249,7 @@ static const struct nla_policy vdpa_nl_policy[VDPA_ATTR_MAX + 1] = {
+ 	[VDPA_ATTR_DEV_NET_CFG_MACADDR] = NLA_POLICY_ETH_ADDR,
+ 	/* virtio spec 1.1 section 5.1.4.1 for valid MTU range */
+ 	[VDPA_ATTR_DEV_NET_CFG_MTU] = NLA_POLICY_MIN(NLA_U16, 68),
++	[VDPA_ATTR_DEV_QUEUE_INDEX] = { .type = NLA_U32 },
+ 	[VDPA_ATTR_DEV_FEATURES] = { .type = NLA_U64 },
+ };
+ 

commit 79c8651587504ba263d2fd67fd4406240fb21f69
+Author: Lin Ma 
+Date:   Thu Jul 27 20:57:48 2023 +0300
+
+    vdpa: Add features attr to vdpa_nl_policy for nlattr length check
+    
+    The vdpa_nl_policy structure is used to validate the nlattr when parsing
+    the incoming nlmsg. It will ensure the attribute being described produces
+    a valid nlattr pointer in info->attrs before entering into each handler
+    in vdpa_nl_ops.
+    
+    That is to say, the missing part in vdpa_nl_policy may lead to illegal
+    nlattr after parsing, which could lead to OOB read just like CVE-2023-3773.
+    
+    This patch adds the missing nla_policy for vdpa features attr to avoid
+    such bugs.
+    
+    Fixes: 90fea5a800c3 ("vdpa: device feature provisioning")
+    Signed-off-by: Lin Ma 
+    Cc: stable@vger.kernel.org
+    Message-Id: <20230727175757.73988-3-dtatulea@nvidia.com>
+    Signed-off-by: Michael S. Tsirkin 
+
+diff --git a/drivers/vdpa/vdpa.c b/drivers/vdpa/vdpa.c
+index 965e32529eb8..3ad355a2208a 100644
+--- a/drivers/vdpa/vdpa.c
++++ b/drivers/vdpa/vdpa.c
+@@ -1249,6 +1249,7 @@ static const struct nla_policy vdpa_nl_policy[VDPA_ATTR_MAX + 1] = {
+ 	[VDPA_ATTR_DEV_NET_CFG_MACADDR] = NLA_POLICY_ETH_ADDR,
+ 	/* virtio spec 1.1 section 5.1.4.1 for valid MTU range */
+ 	[VDPA_ATTR_DEV_NET_CFG_MTU] = NLA_POLICY_MIN(NLA_U16, 68),
++	[VDPA_ATTR_DEV_FEATURES] = { .type = NLA_U64 },
+ };
+ 
+ static const struct genl_ops vdpa_nl_ops[] = {

commit f1d152eb66a30aecd19f22ff2676a7cb2584a920
+Author: Lin Ma 
+Date:   Mon Aug 7 17:13:47 2023 +0800
+
+    rtnetlink: remove redundant checks for nlattr IFLA_BRIDGE_MODE
+    
+    The commit d73ef2d69c0d ("rtnetlink: let rtnl_bridge_setlink checks
+    IFLA_BRIDGE_MODE length") added the nla_len check in rtnl_bridge_setlink,
+    which is the only caller for ndo_bridge_setlink handlers defined in
+    low-level driver codes. Hence, this patch cleanups the redundant checks in
+    each ndo_bridge_setlink handler function.
+    
+    Suggested-by: Hangbin Liu 
+    Signed-off-by: Lin Ma 
+    Acked-by: Pavan Chebbi 
+    Reviewed-by: Simon Horman 
+    Link: https://lore.kernel.org/r/20230807091347.3804523-1-linma@zju.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index eb168ca983b7..7be917a8da48 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -13132,9 +13132,6 @@ static int bnxt_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
+ 		if (nla_type(attr) != IFLA_BRIDGE_MODE)
+ 			continue;
+ 
+-		if (nla_len(attr) < sizeof(mode))
+-			return -EINVAL;
+-
+ 		mode = nla_get_u16(attr);
+ 		if (mode == bp->br_mode)
+ 			break;
+diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
+index 0616b5fe241c..ad862ed7888a 100644
+--- a/drivers/net/ethernet/emulex/benet/be_main.c
++++ b/drivers/net/ethernet/emulex/benet/be_main.c
+@@ -4986,9 +4986,6 @@ static int be_ndo_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
+ 		if (nla_type(attr) != IFLA_BRIDGE_MODE)
+ 			continue;
+ 
+-		if (nla_len(attr) < sizeof(mode))
+-			return -EINVAL;
+-
+ 		mode = nla_get_u16(attr);
+ 		if (BE3_chip(adapter) && mode == BRIDGE_MODE_VEPA)
+ 			return -EOPNOTSUPP;
+diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+index 8eb9839a3ca6..dd03b017dfc5 100644
+--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+@@ -10042,9 +10042,6 @@ static int ixgbe_ndo_bridge_setlink(struct net_device *dev,
+ 		if (nla_type(attr) != IFLA_BRIDGE_MODE)
+ 			continue;
+ 
+-		if (nla_len(attr) < sizeof(mode))
+-			return -EINVAL;
+-
+ 		mode = nla_get_u16(attr);
+ 		status = ixgbe_configure_bridge_mode(adapter, mode);
+ 		if (status)
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+index c8ec6467d4d1..ca80c220e4b0 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+@@ -4896,9 +4896,6 @@ static int mlx5e_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
+ 		if (nla_type(attr) != IFLA_BRIDGE_MODE)
+ 			continue;
+ 
+-		if (nla_len(attr) < sizeof(mode))
+-			return -EINVAL;
+-
+ 		mode = nla_get_u16(attr);
+ 		if (mode > BRIDGE_MODE_VEPA)
+ 			return -EINVAL;
+diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+index f18c791cf698..de0a5d5ded30 100644
+--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
++++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+@@ -2108,9 +2108,6 @@ static int nfp_net_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
+ 		if (nla_type(attr) != IFLA_BRIDGE_MODE)
+ 			continue;
+ 
+-		if (nla_len(attr) < sizeof(mode))
+-			return -EINVAL;
+-
+ 		new_ctrl = nn->dp.ctrl;
+ 		mode = nla_get_u16(attr);
+ 		if (mode == BRIDGE_MODE_VEPA)

commit 31d49ba033095f6e8158c60f69714a500922e0c3
+Author: Lin Ma 
+Date:   Tue Aug 1 09:32:48 2023 +0800
+
+    net: dcb: choose correct policy to parse DCB_ATTR_BCN
+    
+    The dcbnl_bcn_setcfg uses erroneous policy to parse tb[DCB_ATTR_BCN],
+    which is introduced in commit 859ee3c43812 ("DCB: Add support for DCB
+    BCN"). Please see the comment in below code
+    
+    static int dcbnl_bcn_setcfg(...)
+    {
+      ...
+      ret = nla_parse_nested_deprecated(..., dcbnl_pfc_up_nest, .. )
+      // !!! dcbnl_pfc_up_nest for attributes
+      //  DCB_PFC_UP_ATTR_0 to DCB_PFC_UP_ATTR_ALL in enum dcbnl_pfc_up_attrs
+      ...
+      for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) {
+      // !!! DCB_BCN_ATTR_RP_0 to DCB_BCN_ATTR_RP_7 in enum dcbnl_bcn_attrs
+        ...
+        value_byte = nla_get_u8(data[i]);
+        ...
+      }
+      ...
+      for (i = DCB_BCN_ATTR_BCNA_0; i <= DCB_BCN_ATTR_RI; i++) {
+      // !!! DCB_BCN_ATTR_BCNA_0 to DCB_BCN_ATTR_RI in enum dcbnl_bcn_attrs
+      ...
+        value_int = nla_get_u32(data[i]);
+      ...
+      }
+      ...
+    }
+    
+    That is, the nla_parse_nested_deprecated uses dcbnl_pfc_up_nest
+    attributes to parse nlattr defined in dcbnl_pfc_up_attrs. But the
+    following access code fetch each nlattr as dcbnl_bcn_attrs attributes.
+    By looking up the associated nla_policy for dcbnl_bcn_attrs. We can find
+    the beginning part of these two policies are "same".
+    
+    static const struct nla_policy dcbnl_pfc_up_nest[...] = {
+            [DCB_PFC_UP_ATTR_0]   = {.type = NLA_U8},
+            [DCB_PFC_UP_ATTR_1]   = {.type = NLA_U8},
+            [DCB_PFC_UP_ATTR_2]   = {.type = NLA_U8},
+            [DCB_PFC_UP_ATTR_3]   = {.type = NLA_U8},
+            [DCB_PFC_UP_ATTR_4]   = {.type = NLA_U8},
+            [DCB_PFC_UP_ATTR_5]   = {.type = NLA_U8},
+            [DCB_PFC_UP_ATTR_6]   = {.type = NLA_U8},
+            [DCB_PFC_UP_ATTR_7]   = {.type = NLA_U8},
+            [DCB_PFC_UP_ATTR_ALL] = {.type = NLA_FLAG},
+    };
+    
+    static const struct nla_policy dcbnl_bcn_nest[...] = {
+            [DCB_BCN_ATTR_RP_0]         = {.type = NLA_U8},
+            [DCB_BCN_ATTR_RP_1]         = {.type = NLA_U8},
+            [DCB_BCN_ATTR_RP_2]         = {.type = NLA_U8},
+            [DCB_BCN_ATTR_RP_3]         = {.type = NLA_U8},
+            [DCB_BCN_ATTR_RP_4]         = {.type = NLA_U8},
+            [DCB_BCN_ATTR_RP_5]         = {.type = NLA_U8},
+            [DCB_BCN_ATTR_RP_6]         = {.type = NLA_U8},
+            [DCB_BCN_ATTR_RP_7]         = {.type = NLA_U8},
+            [DCB_BCN_ATTR_RP_ALL]       = {.type = NLA_FLAG},
+            // from here is somewhat different
+            [DCB_BCN_ATTR_BCNA_0]       = {.type = NLA_U32},
+            ...
+            [DCB_BCN_ATTR_ALL]          = {.type = NLA_FLAG},
+    };
+    
+    Therefore, the current code is buggy and this
+    nla_parse_nested_deprecated could overflow the dcbnl_pfc_up_nest and use
+    the adjacent nla_policy to parse attributes from DCB_BCN_ATTR_BCNA_0.
+    
+    Hence use the correct policy dcbnl_bcn_nest to parse the nested
+    tb[DCB_ATTR_BCN] TLV.
+    
+    Fixes: 859ee3c43812 ("DCB: Add support for DCB BCN")
+    Signed-off-by: Lin Ma 
+    Reviewed-by: Simon Horman 
+    Link: https://lore.kernel.org/r/20230801013248.87240-1-linma@zju.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
+index c0c438128575..2e6b8c8fd2de 100644
+--- a/net/dcb/dcbnl.c
++++ b/net/dcb/dcbnl.c
+@@ -980,7 +980,7 @@ static int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlmsghdr *nlh,
+ 		return -EOPNOTSUPP;
+ 
+ 	ret = nla_parse_nested_deprecated(data, DCB_BCN_ATTR_MAX,
+-					  tb[DCB_ATTR_BCN], dcbnl_pfc_up_nest,
++					  tb[DCB_ATTR_BCN], dcbnl_bcn_nest,
+ 					  NULL);
+ 	if (ret)
+ 		return ret;

commit 1e7417c188d0a83fb385ba2dbe35fd2563f2b6f3
+Author: Duoming Zhou 
+Date:   Wed Jul 26 16:14:07 2023 +0800
+
+    net: usb: lan78xx: reorder cleanup operations to avoid UAF bugs
+    
+    The timer dev->stat_monitor can schedule the delayed work dev->wq and
+    the delayed work dev->wq can also arm the dev->stat_monitor timer.
+    
+    When the device is detaching, the net_device will be deallocated. but
+    the net_device private data could still be dereferenced in delayed work
+    or timer handler. As a result, the UAF bugs will happen.
+    
+    One racy situation is shown below:
+    
+          (Thread 1)                 |      (Thread 2)
+    lan78xx_stat_monitor()           |
+     ...                             |  lan78xx_disconnect()
+     lan78xx_defer_kevent()          |    ...
+      ...                            |    cancel_delayed_work_sync(&dev->wq);
+      schedule_delayed_work()        |    ...
+      (wait some time)               |    free_netdev(net); //free net_device
+      lan78xx_delayedwork()          |
+      //use net_device private data  |
+      dev-> //use                    |
+    
+    Although we use cancel_delayed_work_sync() to cancel the delayed work
+    in lan78xx_disconnect(), it could still be scheduled in timer handler
+    lan78xx_stat_monitor().
+    
+    Another racy situation is shown below:
+    
+          (Thread 1)                |      (Thread 2)
+    lan78xx_delayedwork             |
+     mod_timer()                    |  lan78xx_disconnect()
+                                    |   cancel_delayed_work_sync()
+     (wait some time)               |   if (timer_pending(&dev->stat_monitor))
+                                    |       del_timer_sync(&dev->stat_monitor);
+     lan78xx_stat_monitor()         |   ...
+      lan78xx_defer_kevent()        |   free_netdev(net); //free
+       //use net_device private data|
+       dev-> //use                  |
+    
+    Although we use del_timer_sync() to delete the timer, the function
+    timer_pending() returns 0 when the timer is activated. As a result,
+    the del_timer_sync() will not be executed and the timer could be
+    re-armed.
+    
+    In order to mitigate this bug, We use timer_shutdown_sync() to shutdown
+    the timer and then use cancel_delayed_work_sync() to cancel the delayed
+    work. As a result, the net_device could be deallocated safely.
+    
+    What's more, the dev->flags is set to EVENT_DEV_DISCONNECT in
+    lan78xx_disconnect(). But it could still be set to EVENT_STAT_UPDATE
+    in lan78xx_stat_monitor(). So this patch put the set_bit() behind
+    timer_shutdown_sync().
+    
+    Fixes: 77dfff5bb7e2 ("lan78xx: Fix race condition in disconnect handling")
+    Signed-off-by: Duoming Zhou 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
+index c458c030fadf..59cde06aa7f6 100644
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -4224,8 +4224,6 @@ static void lan78xx_disconnect(struct usb_interface *intf)
+ 	if (!dev)
+ 		return;
+ 
+-	set_bit(EVENT_DEV_DISCONNECT, &dev->flags);
+-
+ 	netif_napi_del(&dev->napi);
+ 
+ 	udev = interface_to_usbdev(intf);
+@@ -4233,6 +4231,8 @@ static void lan78xx_disconnect(struct usb_interface *intf)
+ 
+ 	unregister_netdev(net);
+ 
++	timer_shutdown_sync(&dev->stat_monitor);
++	set_bit(EVENT_DEV_DISCONNECT, &dev->flags);
+ 	cancel_delayed_work_sync(&dev->wq);
+ 
+ 	phydev = net->phydev;
+@@ -4247,9 +4247,6 @@ static void lan78xx_disconnect(struct usb_interface *intf)
+ 
+ 	usb_scuttle_anchored_urbs(&dev->deferred);
+ 
+-	if (timer_pending(&dev->stat_monitor))
+-		del_timer_sync(&dev->stat_monitor);
+-
+ 	lan78xx_unbind(dev, intf);
+ 
+ 	lan78xx_free_tx_resources(dev);

commit 5e2424708da7207087934c5c75211e8584d553a0
+Author: Lin Ma 
+Date:   Sun Jul 23 15:41:10 2023 +0800
+
+    xfrm: add forgotten nla_policy for XFRMA_MTIMER_THRESH
+    
+    The previous commit 4e484b3e969b ("xfrm: rate limit SA mapping change
+    message to user space") added one additional attribute named
+    XFRMA_MTIMER_THRESH and described its type at compat_policy
+    (net/xfrm/xfrm_compat.c).
+    
+    However, the author forgot to also describe the nla_policy at
+    xfrma_policy (net/xfrm/xfrm_user.c). Hence, this suppose NLA_U32 (4
+    bytes) value can be faked as empty (0 bytes) by a malicious user, which
+    leads to 4 bytes overflow read and heap information leak when parsing
+    nlattrs.
+    
+    To exploit this, one malicious user can spray the SLUB objects and then
+    leverage this 4 bytes OOB read to leak the heap data into
+    x->mapping_maxage (see xfrm_update_ae_params(...)), and leak it to
+    userspace via copy_to_user_state_extra(...).
+    
+    The above bug is assigned CVE-2023-3773. To fix it, this commit just
+    completes the nla_policy description for XFRMA_MTIMER_THRESH, which
+    enforces the length check and avoids such OOB read.
+    
+    Fixes: 4e484b3e969b ("xfrm: rate limit SA mapping change message to user space")
+    Signed-off-by: Lin Ma 
+    Reviewed-by: Simon Horman 
+    Reviewed-by: Leon Romanovsky 
+    Signed-off-by: Steffen Klassert 
+
+diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
+index 8f74dde4a55f..f06d6deb58dd 100644
+--- a/net/xfrm/xfrm_user.c
++++ b/net/xfrm/xfrm_user.c
+@@ -3044,6 +3044,7 @@ const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
+ 	[XFRMA_SET_MARK]	= { .type = NLA_U32 },
+ 	[XFRMA_SET_MARK_MASK]	= { .type = NLA_U32 },
+ 	[XFRMA_IF_ID]		= { .type = NLA_U32 },
++	[XFRMA_MTIMER_THRESH]   = { .type = NLA_U32 },
+ };
+ EXPORT_SYMBOL_GPL(xfrma_policy);
+ 

commit 00374d9b6d9f932802b55181be9831aa948e5b7c
+Author: Lin Ma 
+Date:   Fri Jul 21 22:51:03 2023 +0800
+
+    xfrm: add NULL check in xfrm_update_ae_params
+    
+    Normally, x->replay_esn and x->preplay_esn should be allocated at
+    xfrm_alloc_replay_state_esn(...) in xfrm_state_construct(...), hence the
+    xfrm_update_ae_params(...) is okay to update them. However, the current
+    implementation of xfrm_new_ae(...) allows a malicious user to directly
+    dereference a NULL pointer and crash the kernel like below.
+    
+    BUG: kernel NULL pointer dereference, address: 0000000000000000
+    PGD 8253067 P4D 8253067 PUD 8e0e067 PMD 0
+    Oops: 0002 [#1] PREEMPT SMP KASAN NOPTI
+    CPU: 0 PID: 98 Comm: poc.npd Not tainted 6.4.0-rc7-00072-gdad9774deaf1 #8
+    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.0-0-gd239552ce722-prebuilt.qemu.o4
+    RIP: 0010:memcpy_orig+0xad/0x140
+    Code: e8 4c 89 5f e0 48 8d 7f e0 73 d2 83 c2 20 48 29 d6 48 29 d7 83 fa 10 72 34 4c 8b 06 4c 8b 4e 08 c
+    RSP: 0018:ffff888008f57658 EFLAGS: 00000202
+    RAX: 0000000000000000 RBX: ffff888008bd0000 RCX: ffffffff8238e571
+    RDX: 0000000000000018 RSI: ffff888007f64844 RDI: 0000000000000000
+    RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
+    R10: 0000000000000000 R11: 0000000000000000 R12: ffff888008f57818
+    R13: ffff888007f64aa4 R14: 0000000000000000 R15: 0000000000000000
+    FS:  00000000014013c0(0000) GS:ffff88806d600000(0000) knlGS:0000000000000000
+    CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+    CR2: 0000000000000000 CR3: 00000000054d8000 CR4: 00000000000006f0
+    Call Trace:
+     
+     ? __die+0x1f/0x70
+     ? page_fault_oops+0x1e8/0x500
+     ? __pfx_is_prefetch.constprop.0+0x10/0x10
+     ? __pfx_page_fault_oops+0x10/0x10
+     ? _raw_spin_unlock_irqrestore+0x11/0x40
+     ? fixup_exception+0x36/0x460
+     ? _raw_spin_unlock_irqrestore+0x11/0x40
+     ? exc_page_fault+0x5e/0xc0
+     ? asm_exc_page_fault+0x26/0x30
+     ? xfrm_update_ae_params+0xd1/0x260
+     ? memcpy_orig+0xad/0x140
+     ? __pfx__raw_spin_lock_bh+0x10/0x10
+     xfrm_update_ae_params+0xe7/0x260
+     xfrm_new_ae+0x298/0x4e0
+     ? __pfx_xfrm_new_ae+0x10/0x10
+     ? __pfx_xfrm_new_ae+0x10/0x10
+     xfrm_user_rcv_msg+0x25a/0x410
+     ? __pfx_xfrm_user_rcv_msg+0x10/0x10
+     ? __alloc_skb+0xcf/0x210
+     ? stack_trace_save+0x90/0xd0
+     ? filter_irq_stacks+0x1c/0x70
+     ? __stack_depot_save+0x39/0x4e0
+     ? __kasan_slab_free+0x10a/0x190
+     ? kmem_cache_free+0x9c/0x340
+     ? netlink_recvmsg+0x23c/0x660
+     ? sock_recvmsg+0xeb/0xf0
+     ? __sys_recvfrom+0x13c/0x1f0
+     ? __x64_sys_recvfrom+0x71/0x90
+     ? do_syscall_64+0x3f/0x90
+     ? entry_SYSCALL_64_after_hwframe+0x72/0xdc
+     ? copyout+0x3e/0x50
+     netlink_rcv_skb+0xd6/0x210
+     ? __pfx_xfrm_user_rcv_msg+0x10/0x10
+     ? __pfx_netlink_rcv_skb+0x10/0x10
+     ? __pfx_sock_has_perm+0x10/0x10
+     ? mutex_lock+0x8d/0xe0
+     ? __pfx_mutex_lock+0x10/0x10
+     xfrm_netlink_rcv+0x44/0x50
+     netlink_unicast+0x36f/0x4c0
+     ? __pfx_netlink_unicast+0x10/0x10
+     ? netlink_recvmsg+0x500/0x660
+     netlink_sendmsg+0x3b7/0x700
+    
+    This Null-ptr-deref bug is assigned CVE-2023-3772. And this commit
+    adds additional NULL check in xfrm_update_ae_params to fix the NPD.
+    
+    Fixes: d8647b79c3b7 ("xfrm: Add user interface for esn and big anti-replay windows")
+    Signed-off-by: Lin Ma 
+    Reviewed-by: Leon Romanovsky 
+    Signed-off-by: Steffen Klassert 
+
+diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
+index fdc0c17122b6..8f74dde4a55f 100644
+--- a/net/xfrm/xfrm_user.c
++++ b/net/xfrm/xfrm_user.c
+@@ -628,7 +628,7 @@ static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs,
+ 	struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH];
+ 	struct nlattr *mt = attrs[XFRMA_MTIMER_THRESH];
+ 
+-	if (re) {
++	if (re && x->replay_esn && x->preplay_esn) {
+ 		struct xfrm_replay_state_esn *replay_esn;
+ 		replay_esn = nla_data(re);
+ 		memcpy(x->replay_esn, replay_esn,

commit d73ef2d69c0dba5f5a1cb9600045c873bab1fb7f
+Author: Lin Ma 
+Date:   Wed Jul 26 15:53:14 2023 +0800
+
+    rtnetlink: let rtnl_bridge_setlink checks IFLA_BRIDGE_MODE length
+    
+    There are totally 9 ndo_bridge_setlink handlers in the current kernel,
+    which are 1) bnxt_bridge_setlink, 2) be_ndo_bridge_setlink 3)
+    i40e_ndo_bridge_setlink 4) ice_bridge_setlink 5)
+    ixgbe_ndo_bridge_setlink 6) mlx5e_bridge_setlink 7)
+    nfp_net_bridge_setlink 8) qeth_l2_bridge_setlink 9) br_setlink.
+    
+    By investigating the code, we find that 1-7 parse and use nlattr
+    IFLA_BRIDGE_MODE but 3 and 4 forget to do the nla_len check. This can
+    lead to an out-of-attribute read and allow a malformed nlattr (e.g.,
+    length 0) to be viewed as a 2 byte integer.
+    
+    To avoid such issues, also for other ndo_bridge_setlink handlers in the
+    future. This patch adds the nla_len check in rtnl_bridge_setlink and
+    does an early error return if length mismatches. To make it works, the
+    break is removed from the parsing for IFLA_BRIDGE_FLAGS to make sure
+    this nla_for_each_nested iterates every attribute.
+    
+    Fixes: b1edc14a3fbf ("ice: Implement ice_bridge_getlink and ice_bridge_setlink")
+    Fixes: 51616018dd1b ("i40e: Add support for getlink, setlink ndo ops")
+    Suggested-by: Jakub Kicinski 
+    Signed-off-by: Lin Ma 
+    Acked-by: Nikolay Aleksandrov 
+    Reviewed-by: Hangbin Liu 
+    Link: https://lore.kernel.org/r/20230726075314.1059224-1-linma@zju.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
+index 3ad4e030846d..aef25aa5cf1d 100644
+--- a/net/core/rtnetlink.c
++++ b/net/core/rtnetlink.c
+@@ -5140,13 +5140,17 @@ static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
+ 	br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
+ 	if (br_spec) {
+ 		nla_for_each_nested(attr, br_spec, rem) {
+-			if (nla_type(attr) == IFLA_BRIDGE_FLAGS) {
++			if (nla_type(attr) == IFLA_BRIDGE_FLAGS && !have_flags) {
+ 				if (nla_len(attr) < sizeof(flags))
+ 					return -EINVAL;
+ 
+ 				have_flags = true;
+ 				flags = nla_get_u16(attr);
+-				break;
++			}
++
++			if (nla_type(attr) == IFLA_BRIDGE_MODE) {
++				if (nla_len(attr) < sizeof(u16))
++					return -EINVAL;
+ 			}
+ 		}
+ 	}

commit bcc29b7f5af6797702c2306a7aacb831fc5ce9cb
+Author: Lin Ma 
+Date:   Tue Jul 25 10:33:30 2023 +0800
+
+    bpf: Add length check for SK_DIAG_BPF_STORAGE_REQ_MAP_FD parsing
+    
+    The nla_for_each_nested parsing in function bpf_sk_storage_diag_alloc
+    does not check the length of the nested attribute. This can lead to an
+    out-of-attribute read and allow a malformed nlattr (e.g., length 0) to
+    be viewed as a 4 byte integer.
+    
+    This patch adds an additional check when the nlattr is getting counted.
+    This makes sure the latter nla_get_u32 can access the attributes with
+    the correct length.
+    
+    Fixes: 1ed4d92458a9 ("bpf: INET_DIAG support in bpf_sk_storage")
+    Suggested-by: Jakub Kicinski 
+    Signed-off-by: Lin Ma 
+    Reviewed-by: Jakub Kicinski 
+    Link: https://lore.kernel.org/r/20230725023330.422856-1-linma@zju.edu.cn
+    Signed-off-by: Martin KaFai Lau 
+
+diff --git a/net/core/bpf_sk_storage.c b/net/core/bpf_sk_storage.c
+index d4172534dfa8..cca7594be92e 100644
+--- a/net/core/bpf_sk_storage.c
++++ b/net/core/bpf_sk_storage.c
+@@ -496,8 +496,11 @@ bpf_sk_storage_diag_alloc(const struct nlattr *nla_stgs)
+ 		return ERR_PTR(-EPERM);
+ 
+ 	nla_for_each_nested(nla, nla_stgs, rem) {
+-		if (nla_type(nla) == SK_DIAG_BPF_STORAGE_REQ_MAP_FD)
++		if (nla_type(nla) == SK_DIAG_BPF_STORAGE_REQ_MAP_FD) {
++			if (nla_len(nla) != sizeof(u32))
++				return ERR_PTR(-EINVAL);
+ 			nr_maps++;
++		}
+ 	}
+ 
+ 	diag = kzalloc(struct_size(diag, maps, nr_maps), GFP_KERNEL);

commit 0c805e80e35d042a41c8702fa13f453a504d2ede
+Author: Lin Ma 
+Date:   Wed Jul 12 21:32:36 2023 +0800
+
+    netfilter: conntrack: validate cta_ip via parsing
+    
+    In current ctnetlink_parse_tuple_ip() function, nested parsing and
+    validation is splitting as two parts,  which could be cleanup to a
+    simplified form. As the nla_parse_nested_deprecated function
+    supports validation in the fly. These two finially reach same place
+    __nla_validate_parse with same validate flag.
+    
+    nla_parse_nested_deprecated
+      __nla_parse(.., NL_VALIDATE_LIBERAL, ..)
+        __nla_validate_parse
+    
+    nla_validate_nested_deprecated
+      __nla_validate_nested(.., NL_VALIDATE_LIBERAL, ..)
+        __nla_validate
+          __nla_validate_parse
+    
+    This commit removes the call to nla_validate_nested_deprecated and pass
+    cta_ip_nla_policy when do parsing.
+    
+    Signed-off-by: Lin Ma 
+    Reviewed-by: Simon Horman 
+    Signed-off-by: Florian Westphal 
+
+diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
+index 69c8c8c7e9b8..334db22199c1 100644
+--- a/net/netfilter/nf_conntrack_netlink.c
++++ b/net/netfilter/nf_conntrack_netlink.c
+@@ -1321,15 +1321,11 @@ static int ctnetlink_parse_tuple_ip(struct nlattr *attr,
+ 	struct nlattr *tb[CTA_IP_MAX+1];
+ 	int ret = 0;
+ 
+-	ret = nla_parse_nested_deprecated(tb, CTA_IP_MAX, attr, NULL, NULL);
++	ret = nla_parse_nested_deprecated(tb, CTA_IP_MAX, attr,
++					  cta_ip_nla_policy, NULL);
+ 	if (ret < 0)
+ 		return ret;
+ 
+-	ret = nla_validate_nested_deprecated(attr, CTA_IP_MAX,
+-					     cta_ip_nla_policy, NULL);
+-	if (ret)
+-		return ret;
+-
+ 	switch (tuple->src.l3num) {
+ 	case NFPROTO_IPV4:
+ 		ret = ipv4_nlattr_to_tuple(tb, tuple, flags);

commit 6c58c8816abb7b93b21fa3b1d0c1726402e5e568
+Author: Lin Ma 
+Date:   Tue Jul 25 10:42:27 2023 +0800
+
+    net/sched: mqprio: Add length check for TCA_MQPRIO_{MAX/MIN}_RATE64
+    
+    The nla_for_each_nested parsing in function mqprio_parse_nlattr() does
+    not check the length of the nested attribute. This can lead to an
+    out-of-attribute read and allow a malformed nlattr (e.g., length 0) to
+    be viewed as 8 byte integer and passed to priv->max_rate/min_rate.
+    
+    This patch adds the check based on nla_len() when check the nla_type(),
+    which ensures that the length of these two attribute must equals
+    sizeof(u64).
+    
+    Fixes: 4e8b86c06269 ("mqprio: Introduce new hardware offload mode and shaper in mqprio")
+    Reviewed-by: Victor Nogueira 
+    Signed-off-by: Lin Ma 
+    Link: https://lore.kernel.org/r/20230725024227.426561-1-linma@zju.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c
+index ab69ff7577fc..793009f445c0 100644
+--- a/net/sched/sch_mqprio.c
++++ b/net/sched/sch_mqprio.c
+@@ -290,6 +290,13 @@ static int mqprio_parse_nlattr(struct Qdisc *sch, struct tc_mqprio_qopt *qopt,
+ 						    "Attribute type expected to be TCA_MQPRIO_MIN_RATE64");
+ 				return -EINVAL;
+ 			}
++
++			if (nla_len(attr) != sizeof(u64)) {
++				NL_SET_ERR_MSG_ATTR(extack, attr,
++						    "Attribute TCA_MQPRIO_MIN_RATE64 expected to have 8 bytes length");
++				return -EINVAL;
++			}
++
+ 			if (i >= qopt->num_tc)
+ 				break;
+ 			priv->min_rate[i] = nla_get_u64(attr);
+@@ -312,6 +319,13 @@ static int mqprio_parse_nlattr(struct Qdisc *sch, struct tc_mqprio_qopt *qopt,
+ 						    "Attribute type expected to be TCA_MQPRIO_MAX_RATE64");
+ 				return -EINVAL;
+ 			}
++
++			if (nla_len(attr) != sizeof(u64)) {
++				NL_SET_ERR_MSG_ATTR(extack, attr,
++						    "Attribute TCA_MQPRIO_MAX_RATE64 expected to have 8 bytes length");
++				return -EINVAL;
++			}
++
+ 			if (i >= qopt->num_tc)
+ 				break;
+ 			priv->max_rate[i] = nla_get_u64(attr);

commit 74f12d511625e603fac8c0c2b6872e687e56dd61
+Author: Lin Ma 
+Date:   Sun Jul 23 16:03:50 2023 +0800
+
+    wifi: mt76: testmode: add nla_policy for MT76_TM_ATTR_TX_LENGTH
+    
+    It seems that the nla_policy in mt76_tm_policy is missed for attribute
+    MT76_TM_ATTR_TX_LENGTH. This patch adds the correct description to make
+    sure the
+    
+      u32 val = nla_get_u32(tb[MT76_TM_ATTR_TX_LENGTH]);
+    
+    in function mt76_testmode_cmd() is safe and will not result in
+    out-of-attribute read.
+    
+    Fixes: f0efa8621550 ("mt76: add API for testmode support")
+    Signed-off-by: Lin Ma 
+    Signed-off-by: Felix Fietkau 
+
+diff --git a/drivers/net/wireless/mediatek/mt76/testmode.c b/drivers/net/wireless/mediatek/mt76/testmode.c
+index 0accc71a91c9..4644dace9bb3 100644
+--- a/drivers/net/wireless/mediatek/mt76/testmode.c
++++ b/drivers/net/wireless/mediatek/mt76/testmode.c
+@@ -8,6 +8,7 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
+ 	[MT76_TM_ATTR_RESET] = { .type = NLA_FLAG },
+ 	[MT76_TM_ATTR_STATE] = { .type = NLA_U8 },
+ 	[MT76_TM_ATTR_TX_COUNT] = { .type = NLA_U32 },
++	[MT76_TM_ATTR_TX_LENGTH] = { .type = NLA_U32 },
+ 	[MT76_TM_ATTR_TX_RATE_MODE] = { .type = NLA_U8 },
+ 	[MT76_TM_ATTR_TX_RATE_NSS] = { .type = NLA_U8 },
+ 	[MT76_TM_ATTR_TX_RATE_IDX] = { .type = NLA_U8 },

commit 55cef78c244d0d076f5a75a35530ca63c92f4426
+Author: Lin Ma 
+Date:   Sun Jul 23 16:02:05 2023 +0800
+
+    macvlan: add forgotten nla_policy for IFLA_MACVLAN_BC_CUTOFF
+    
+    The previous commit 954d1fa1ac93 ("macvlan: Add netlink attribute for
+    broadcast cutoff") added one additional attribute named
+    IFLA_MACVLAN_BC_CUTOFF to allow broadcast cutfoff.
+    
+    However, it forgot to describe the nla_policy at macvlan_policy
+    (drivers/net/macvlan.c). Hence, this suppose NLA_S32 (4 bytes) integer
+    can be faked as empty (0 bytes) by a malicious user, which could leads
+    to OOB in heap just like CVE-2023-3773.
+    
+    To fix it, this commit just completes the nla_policy description for
+    IFLA_MACVLAN_BC_CUTOFF. This enforces the length check and avoids the
+    potential OOB read.
+    
+    Fixes: 954d1fa1ac93 ("macvlan: Add netlink attribute for broadcast cutoff")
+    Signed-off-by: Lin Ma 
+    Reviewed-by: Simon Horman 
+    Link: https://lore.kernel.org/r/20230723080205.3715164-1-linma@zju.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
+index 4a53debf9d7c..ed908165a8b4 100644
+--- a/drivers/net/macvlan.c
++++ b/drivers/net/macvlan.c
+@@ -1746,6 +1746,7 @@ static const struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX + 1] = {
+ 	[IFLA_MACVLAN_MACADDR_COUNT] = { .type = NLA_U32 },
+ 	[IFLA_MACVLAN_BC_QUEUE_LEN] = { .type = NLA_U32 },
+ 	[IFLA_MACVLAN_BC_QUEUE_LEN_USED] = { .type = NLA_REJECT },
++	[IFLA_MACVLAN_BC_CUTOFF] = { .type = NLA_S32 },
+ };
+ 
+ int macvlan_link_register(struct rtnl_link_ops *ops)

commit 47cd3770e31df942e2bb925a9a855c79ed0662eb
+Author: Lin Ma 
+Date:   Sun Jul 23 16:00:53 2023 +0800
+
+    scsi: qla4xxx: Add length check when parsing nlattrs
+    
+    There are three places that qla4xxx parses nlattrs:
+    
+     - qla4xxx_set_chap_entry()
+    
+     - qla4xxx_iface_set_param()
+    
+     - qla4xxx_sysfs_ddb_set_param()
+    
+    and each of them directly converts the nlattr to specific pointer of
+    structure without length checking. This could be dangerous as those
+    attributes are not validated and a malformed nlattr (e.g., length 0) could
+    result in an OOB read that leaks heap dirty data.
+    
+    Add the nla_len check before accessing the nlattr data and return EINVAL if
+    the length check fails.
+    
+    Fixes: 26ffd7b45fe9 ("[SCSI] qla4xxx: Add support to set CHAP entries")
+    Fixes: 1e9e2be3ee03 ("[SCSI] qla4xxx: Add flash node mgmt support")
+    Fixes: 00c31889f751 ("[SCSI] qla4xxx: fix data alignment and use nl helpers")
+    Signed-off-by: Lin Ma 
+    Link: https://lore.kernel.org/r/20230723080053.3714534-1-linma@zju.edu.cn
+    Reviewed-by: Chris Leech 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index b2a3988e1e15..675332e49a7b 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -968,6 +968,11 @@ static int qla4xxx_set_chap_entry(struct Scsi_Host *shost, void *data, int len)
+ 	memset(&chap_rec, 0, sizeof(chap_rec));
+ 
+ 	nla_for_each_attr(attr, data, len, rem) {
++		if (nla_len(attr) < sizeof(*param_info)) {
++			rc = -EINVAL;
++			goto exit_set_chap;
++		}
++
+ 		param_info = nla_data(attr);
+ 
+ 		switch (param_info->param) {
+@@ -2750,6 +2755,11 @@ qla4xxx_iface_set_param(struct Scsi_Host *shost, void *data, uint32_t len)
+ 	}
+ 
+ 	nla_for_each_attr(attr, data, len, rem) {
++		if (nla_len(attr) < sizeof(*iface_param)) {
++			rval = -EINVAL;
++			goto exit_init_fw_cb;
++		}
++
+ 		iface_param = nla_data(attr);
+ 
+ 		if (iface_param->param_type == ISCSI_NET_PARAM) {
+@@ -8104,6 +8114,11 @@ qla4xxx_sysfs_ddb_set_param(struct iscsi_bus_flash_session *fnode_sess,
+ 
+ 	memset((void *)&chap_tbl, 0, sizeof(chap_tbl));
+ 	nla_for_each_attr(attr, data, len, rem) {
++		if (nla_len(attr) < sizeof(*fnode_param)) {
++			rc = -EINVAL;
++			goto exit_set_param;
++		}
++
+ 		fnode_param = nla_data(attr);
+ 
+ 		switch (fnode_param->param) {

commit ee0268f230f66cb472df3424f380ea668da2749a
+Author: Lin Ma 
+Date:   Sun Jul 23 15:59:38 2023 +0800
+
+    scsi: be2iscsi: Add length check when parsing nlattrs
+    
+    beiscsi_iface_set_param() parses nlattr with nla_for_each_attr and assumes
+    every attributes can be viewed as struct iscsi_iface_param_info.
+    
+    This is not true because there is no any nla_policy to validate the
+    attributes passed from the upper function iscsi_set_iface_params().
+    
+    Add the nla_len check before accessing the nlattr data and return EINVAL if
+    the length check fails.
+    
+    Fixes: 0e43895ec1f4 ("[SCSI] be2iscsi: adding functionality to change network settings using iscsiadm")
+    Signed-off-by: Lin Ma 
+    Link: https://lore.kernel.org/r/20230723075938.3713864-1-linma@zju.edu.cn
+    Reviewed-by: Chris Leech 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
+index 8aeaddc93b16..8d374ae863ba 100644
+--- a/drivers/scsi/be2iscsi/be_iscsi.c
++++ b/drivers/scsi/be2iscsi/be_iscsi.c
+@@ -450,6 +450,10 @@ int beiscsi_iface_set_param(struct Scsi_Host *shost,
+ 	}
+ 
+ 	nla_for_each_attr(attrib, data, dt_len, rm_len) {
++		/* ignore nla_type as it is never used */
++		if (nla_len(attrib) < sizeof(*iface_param))
++			return -EINVAL;
++
+ 		iface_param = nla_data(attrib);
+ 
+ 		if (iface_param->param_type != ISCSI_NET_PARAM)

commit ce51c817008450ef4188471db31639d42d37a5e1
+Author: Lin Ma 
+Date:   Sun Jul 23 15:58:20 2023 +0800
+
+    scsi: iscsi: Add strlen() check in iscsi_if_set{_host}_param()
+    
+    The functions iscsi_if_set_param() and iscsi_if_set_host_param() convert an
+    nlattr payload to type char* and then call C string handling functions like
+    sscanf and kstrdup:
+    
+      char *data = (char*)ev + sizeof(*ev);
+      ...
+      sscanf(data, "%d", &value);
+    
+    However, since the nlattr is provided by the user-space program and the
+    nlmsg skb is allocated with GFP_KERNEL instead of GFP_ZERO flag (see
+    netlink_alloc_large_skb() in netlink_sendmsg()), dirty data on the heap can
+    lead to an OOB access for those string handling functions.
+    
+    By investigating how the bug is introduced, we find it is really
+    interesting as the old version parsing code starting from commit
+    fd7255f51a13 ("[SCSI] iscsi: add sysfs attrs for uspace sync up") treated
+    the nlattr as integer bytes instead of string and had length check in
+    iscsi_copy_param():
+    
+      if (ev->u.set_param.len != sizeof(uint32_t))
+        BUG();
+    
+    But, since the commit a54a52caad4b ("[SCSI] iscsi: fixup set/get param
+    functions"), the code treated the nlattr as C string while forgetting to
+    add any strlen checks(), opening the possibility of an OOB access.
+    
+    Fix the potential OOB by adding the strlen() check before accessing the
+    buf. If the data passes this check, all low-level set_param handlers can
+    safely treat this buf as legal C string.
+    
+    Fixes: fd7255f51a13 ("[SCSI] iscsi: add sysfs attrs for uspace sync up")
+    Fixes: 1d9bf13a9cf9 ("[SCSI] iscsi class: add iscsi host set param event")
+    Signed-off-by: Lin Ma 
+    Link: https://lore.kernel.org/r/20230723075820.3713119-1-linma@zju.edu.cn
+    Reviewed-by: Chris Leech 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 62b24f1c0232..3075b2ddf7a6 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -3030,6 +3030,10 @@ iscsi_if_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev, u
+ 	if (!conn || !session)
+ 		return -EINVAL;
+ 
++	/* data will be regarded as NULL-ended string, do length check */
++	if (strlen(data) > ev->u.set_param.len)
++		return -EINVAL;
++
+ 	switch (ev->u.set_param.param) {
+ 	case ISCSI_PARAM_SESS_RECOVERY_TMO:
+ 		sscanf(data, "%d", &value);
+@@ -3203,6 +3207,10 @@ iscsi_set_host_param(struct iscsi_transport *transport,
+ 		return -ENODEV;
+ 	}
+ 
++	/* see similar check in iscsi_if_set_param() */
++	if (strlen(data) > ev->u.set_host_param.len)
++		return -EINVAL;
++
+ 	err = transport->set_host_param(shost, ev->u.set_host_param.param,
+ 					data, ev->u.set_host_param.len);
+ 	scsi_host_put(shost);

commit 971dfcb74a800047952f5288512b9c7ddedb050a
+Author: Lin Ma 
+Date:   Tue Jul 25 10:45:29 2023 +0800
+
+    scsi: iscsi: Add length check for nlattr payload
+    
+    The current NETLINK_ISCSI netlink parsing loop checks every nlmsg to make
+    sure the length is bigger than sizeof(struct iscsi_uevent) and then calls
+    iscsi_if_recv_msg().
+    
+      nlh = nlmsg_hdr(skb);
+      if (nlh->nlmsg_len < sizeof(*nlh) + sizeof(*ev) ||
+        skb->len < nlh->nlmsg_len) {
+        break;
+      }
+      ...
+      err = iscsi_if_recv_msg(skb, nlh, &group);
+    
+    Hence, in iscsi_if_recv_msg() the nlmsg_data can be safely converted to
+    iscsi_uevent as the length is already checked.
+    
+    However, in other cases the length of nlattr payload is not checked before
+    the payload is converted to other data structures. One example is
+    iscsi_set_path() which converts the payload to type iscsi_path without any
+    checks:
+    
+      params = (struct iscsi_path *)((char *)ev + sizeof(*ev));
+    
+    Whereas iscsi_if_transport_conn() correctly checks the pdu_len:
+    
+      pdu_len = nlh->nlmsg_len - sizeof(*nlh) - sizeof(*ev);
+      if ((ev->u.send_pdu.hdr_size > pdu_len) ..
+        err = -EINVAL;
+    
+    To sum up, some code paths called in iscsi_if_recv_msg() do not check the
+    length of the data (see below picture) and directly convert the data to
+    another data structure. This could result in an out-of-bound reads and heap
+    dirty data leakage.
+    
+                 _________  nlmsg_len(nlh) _______________
+                /                                         \
+    +----------+--------------+---------------------------+
+    | nlmsghdr | iscsi_uevent |          data              |
+    +----------+--------------+---------------------------+
+                              \                          /
+                             iscsi_uevent->u.set_param.len
+    
+    Fix the issue by adding the length check before accessing it. To clean up
+    the code, an additional parameter named rlen is added. The rlen is
+    calculated at the beginning of iscsi_if_recv_msg() which avoids duplicated
+    calculation.
+    
+    Fixes: ac20c7bf070d ("[SCSI] iscsi_transport: Added Ping support")
+    Fixes: 43514774ff40 ("[SCSI] iscsi class: Add new NETLINK_ISCSI messages for cnic/bnx2i driver.")
+    Fixes: 1d9bf13a9cf9 ("[SCSI] iscsi class: add iscsi host set param event")
+    Fixes: 01cb225dad8d ("[SCSI] iscsi: add target discvery event to transport class")
+    Fixes: 264faaaa1254 ("[SCSI] iscsi: add transport end point callbacks")
+    Fixes: fd7255f51a13 ("[SCSI] iscsi: add sysfs attrs for uspace sync up")
+    Signed-off-by: Lin Ma 
+    Link: https://lore.kernel.org/r/20230725024529.428311-1-linma@zju.edu.cn
+    Reviewed-by: Chris Leech 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index e527ece12453..62b24f1c0232 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -3014,14 +3014,15 @@ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev
+ }
+ 
+ static int
+-iscsi_if_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
++iscsi_if_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev, u32 rlen)
+ {
+ 	char *data = (char*)ev + sizeof(*ev);
+ 	struct iscsi_cls_conn *conn;
+ 	struct iscsi_cls_session *session;
+ 	int err = 0, value = 0, state;
+ 
+-	if (ev->u.set_param.len > PAGE_SIZE)
++	if (ev->u.set_param.len > rlen ||
++	    ev->u.set_param.len > PAGE_SIZE)
+ 		return -EINVAL;
+ 
+ 	session = iscsi_session_lookup(ev->u.set_param.sid);
+@@ -3118,7 +3119,7 @@ static int iscsi_if_ep_disconnect(struct iscsi_transport *transport,
+ 
+ static int
+ iscsi_if_transport_ep(struct iscsi_transport *transport,
+-		      struct iscsi_uevent *ev, int msg_type)
++		      struct iscsi_uevent *ev, int msg_type, u32 rlen)
+ {
+ 	struct iscsi_endpoint *ep;
+ 	int rc = 0;
+@@ -3126,7 +3127,10 @@ iscsi_if_transport_ep(struct iscsi_transport *transport,
+ 	switch (msg_type) {
+ 	case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST:
+ 	case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
+-		rc = iscsi_if_ep_connect(transport, ev, msg_type);
++		if (rlen < sizeof(struct sockaddr))
++			rc = -EINVAL;
++		else
++			rc = iscsi_if_ep_connect(transport, ev, msg_type);
+ 		break;
+ 	case ISCSI_UEVENT_TRANSPORT_EP_POLL:
+ 		if (!transport->ep_poll)
+@@ -3150,12 +3154,15 @@ iscsi_if_transport_ep(struct iscsi_transport *transport,
+ 
+ static int
+ iscsi_tgt_dscvr(struct iscsi_transport *transport,
+-		struct iscsi_uevent *ev)
++		struct iscsi_uevent *ev, u32 rlen)
+ {
+ 	struct Scsi_Host *shost;
+ 	struct sockaddr *dst_addr;
+ 	int err;
+ 
++	if (rlen < sizeof(*dst_addr))
++		return -EINVAL;
++
+ 	if (!transport->tgt_dscvr)
+ 		return -EINVAL;
+ 
+@@ -3176,7 +3183,7 @@ iscsi_tgt_dscvr(struct iscsi_transport *transport,
+ 
+ static int
+ iscsi_set_host_param(struct iscsi_transport *transport,
+-		     struct iscsi_uevent *ev)
++		     struct iscsi_uevent *ev, u32 rlen)
+ {
+ 	char *data = (char*)ev + sizeof(*ev);
+ 	struct Scsi_Host *shost;
+@@ -3185,7 +3192,8 @@ iscsi_set_host_param(struct iscsi_transport *transport,
+ 	if (!transport->set_host_param)
+ 		return -ENOSYS;
+ 
+-	if (ev->u.set_host_param.len > PAGE_SIZE)
++	if (ev->u.set_host_param.len > rlen ||
++	    ev->u.set_host_param.len > PAGE_SIZE)
+ 		return -EINVAL;
+ 
+ 	shost = scsi_host_lookup(ev->u.set_host_param.host_no);
+@@ -3202,12 +3210,15 @@ iscsi_set_host_param(struct iscsi_transport *transport,
+ }
+ 
+ static int
+-iscsi_set_path(struct iscsi_transport *transport, struct iscsi_uevent *ev)
++iscsi_set_path(struct iscsi_transport *transport, struct iscsi_uevent *ev, u32 rlen)
+ {
+ 	struct Scsi_Host *shost;
+ 	struct iscsi_path *params;
+ 	int err;
+ 
++	if (rlen < sizeof(*params))
++		return -EINVAL;
++
+ 	if (!transport->set_path)
+ 		return -ENOSYS;
+ 
+@@ -3267,12 +3278,15 @@ iscsi_set_iface_params(struct iscsi_transport *transport,
+ }
+ 
+ static int
+-iscsi_send_ping(struct iscsi_transport *transport, struct iscsi_uevent *ev)
++iscsi_send_ping(struct iscsi_transport *transport, struct iscsi_uevent *ev, u32 rlen)
+ {
+ 	struct Scsi_Host *shost;
+ 	struct sockaddr *dst_addr;
+ 	int err;
+ 
++	if (rlen < sizeof(*dst_addr))
++		return -EINVAL;
++
+ 	if (!transport->send_ping)
+ 		return -ENOSYS;
+ 
+@@ -3770,13 +3784,12 @@ iscsi_get_host_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
+ }
+ 
+ static int iscsi_if_transport_conn(struct iscsi_transport *transport,
+-				   struct nlmsghdr *nlh)
++				   struct nlmsghdr *nlh, u32 pdu_len)
+ {
+ 	struct iscsi_uevent *ev = nlmsg_data(nlh);
+ 	struct iscsi_cls_session *session;
+ 	struct iscsi_cls_conn *conn = NULL;
+ 	struct iscsi_endpoint *ep;
+-	uint32_t pdu_len;
+ 	int err = 0;
+ 
+ 	switch (nlh->nlmsg_type) {
+@@ -3861,8 +3874,6 @@ static int iscsi_if_transport_conn(struct iscsi_transport *transport,
+ 
+ 		break;
+ 	case ISCSI_UEVENT_SEND_PDU:
+-		pdu_len = nlh->nlmsg_len - sizeof(*nlh) - sizeof(*ev);
+-
+ 		if ((ev->u.send_pdu.hdr_size > pdu_len) ||
+ 		    (ev->u.send_pdu.data_size > (pdu_len - ev->u.send_pdu.hdr_size))) {
+ 			err = -EINVAL;
+@@ -3892,6 +3903,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
+ 	struct iscsi_internal *priv;
+ 	struct iscsi_cls_session *session;
+ 	struct iscsi_endpoint *ep = NULL;
++	u32 rlen;
+ 
+ 	if (!netlink_capable(skb, CAP_SYS_ADMIN))
+ 		return -EPERM;
+@@ -3911,6 +3923,13 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
+ 
+ 	portid = NETLINK_CB(skb).portid;
+ 
++	/*
++	 * Even though the remaining payload may not be regarded as nlattr,
++	 * (like address or something else), calculate the remaining length
++	 * here to ease following length checks.
++	 */
++	rlen = nlmsg_attrlen(nlh, sizeof(*ev));
++
+ 	switch (nlh->nlmsg_type) {
+ 	case ISCSI_UEVENT_CREATE_SESSION:
+ 		err = iscsi_if_create_session(priv, ep, ev,
+@@ -3967,7 +3986,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
+ 			err = -EINVAL;
+ 		break;
+ 	case ISCSI_UEVENT_SET_PARAM:
+-		err = iscsi_if_set_param(transport, ev);
++		err = iscsi_if_set_param(transport, ev, rlen);
+ 		break;
+ 	case ISCSI_UEVENT_CREATE_CONN:
+ 	case ISCSI_UEVENT_DESTROY_CONN:
+@@ -3975,7 +3994,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
+ 	case ISCSI_UEVENT_START_CONN:
+ 	case ISCSI_UEVENT_BIND_CONN:
+ 	case ISCSI_UEVENT_SEND_PDU:
+-		err = iscsi_if_transport_conn(transport, nlh);
++		err = iscsi_if_transport_conn(transport, nlh, rlen);
+ 		break;
+ 	case ISCSI_UEVENT_GET_STATS:
+ 		err = iscsi_if_get_stats(transport, nlh);
+@@ -3984,23 +4003,22 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
+ 	case ISCSI_UEVENT_TRANSPORT_EP_POLL:
+ 	case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
+ 	case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST:
+-		err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type);
++		err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type, rlen);
+ 		break;
+ 	case ISCSI_UEVENT_TGT_DSCVR:
+-		err = iscsi_tgt_dscvr(transport, ev);
++		err = iscsi_tgt_dscvr(transport, ev, rlen);
+ 		break;
+ 	case ISCSI_UEVENT_SET_HOST_PARAM:
+-		err = iscsi_set_host_param(transport, ev);
++		err = iscsi_set_host_param(transport, ev, rlen);
+ 		break;
+ 	case ISCSI_UEVENT_PATH_UPDATE:
+-		err = iscsi_set_path(transport, ev);
++		err = iscsi_set_path(transport, ev, rlen);
+ 		break;
+ 	case ISCSI_UEVENT_SET_IFACE_PARAMS:
+-		err = iscsi_set_iface_params(transport, ev,
+-					     nlmsg_attrlen(nlh, sizeof(*ev)));
++		err = iscsi_set_iface_params(transport, ev, rlen);
+ 		break;
+ 	case ISCSI_UEVENT_PING:
+-		err = iscsi_send_ping(transport, ev);
++		err = iscsi_send_ping(transport, ev, rlen);
+ 		break;
+ 	case ISCSI_UEVENT_GET_CHAP:
+ 		err = iscsi_get_chap(transport, nlh);
+@@ -4009,13 +4027,10 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
+ 		err = iscsi_delete_chap(transport, ev);
+ 		break;
+ 	case ISCSI_UEVENT_SET_FLASHNODE_PARAMS:
+-		err = iscsi_set_flashnode_param(transport, ev,
+-						nlmsg_attrlen(nlh,
+-							      sizeof(*ev)));
++		err = iscsi_set_flashnode_param(transport, ev, rlen);
+ 		break;
+ 	case ISCSI_UEVENT_NEW_FLASHNODE:
+-		err = iscsi_new_flashnode(transport, ev,
+-					  nlmsg_attrlen(nlh, sizeof(*ev)));
++		err = iscsi_new_flashnode(transport, ev, rlen);
+ 		break;
+ 	case ISCSI_UEVENT_DEL_FLASHNODE:
+ 		err = iscsi_del_flashnode(transport, ev);
+@@ -4030,8 +4045,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
+ 		err = iscsi_logout_flashnode_sid(transport, ev);
+ 		break;
+ 	case ISCSI_UEVENT_SET_CHAP:
+-		err = iscsi_set_chap(transport, ev,
+-				     nlmsg_attrlen(nlh, sizeof(*ev)));
++		err = iscsi_set_chap(transport, ev, rlen);
+ 		break;
+ 	case ISCSI_UEVENT_GET_HOST_STATS:
+ 		err = iscsi_get_host_stats(transport, nlh);

commit 30c45b5361d39b4b793780ffac5538090b9e2eb1
+Author: Lin Ma 
+Date:   Mon Jul 3 19:08:42 2023 +0800
+
+    net/sched: act_pedit: Add size check for TCA_PEDIT_PARMS_EX
+    
+    The attribute TCA_PEDIT_PARMS_EX is not be included in pedit_policy and
+    one malicious user could fake a TCA_PEDIT_PARMS_EX whose length is
+    smaller than the intended sizeof(struct tc_pedit). Hence, the
+    dereference in tcf_pedit_init() could access dirty heap data.
+    
+    static int tcf_pedit_init(...)
+    {
+      // ...
+      pattr = tb[TCA_PEDIT_PARMS]; // TCA_PEDIT_PARMS is included
+      if (!pattr)
+        pattr = tb[TCA_PEDIT_PARMS_EX]; // but this is not
+    
+      // ...
+      parm = nla_data(pattr);
+    
+      index = parm->index; // parm is able to be smaller than 4 bytes
+                           // and this dereference gets dirty skb_buff
+                           // data created in netlink_sendmsg
+    }
+    
+    This commit adds TCA_PEDIT_PARMS_EX length in pedit_policy which avoid
+    the above case, just like the TCA_PEDIT_PARMS.
+    
+    Fixes: 71d0ed7079df ("net/act_pedit: Support using offset relative to the conventional network headers")
+    Signed-off-by: Lin Ma 
+    Reviewed-by: Pedro Tammela 
+    Link: https://lore.kernel.org/r/20230703110842.590282-1-linma@zju.edu.cn
+    Signed-off-by: Paolo Abeni 
+
+diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
+index b562fc2bb5b1..1ef8fcfa9997 100644
+--- a/net/sched/act_pedit.c
++++ b/net/sched/act_pedit.c
+@@ -29,6 +29,7 @@ static struct tc_action_ops act_pedit_ops;
+ 
+ static const struct nla_policy pedit_policy[TCA_PEDIT_MAX + 1] = {
+ 	[TCA_PEDIT_PARMS]	= { .len = sizeof(struct tc_pedit) },
++	[TCA_PEDIT_PARMS_EX]	= { .len = sizeof(struct tc_pedit) },
+ 	[TCA_PEDIT_KEYS_EX]   = { .type = NLA_NESTED },
+ };
+ 

commit d1e0e61d617ba17aa516db707aa871387566bbf7
+Author: Lin Ma 
+Date:   Fri Jun 30 16:19:11 2023 +0800
+
+    net: xfrm: Amend XFRMA_SEC_CTX nla_policy structure
+    
+    According to all consumers code of attrs[XFRMA_SEC_CTX], like
+    
+    * verify_sec_ctx_len(), convert to xfrm_user_sec_ctx*
+    * xfrm_state_construct(), call security_xfrm_state_alloc whose prototype
+    is int security_xfrm_state_alloc(.., struct xfrm_user_sec_ctx *sec_ctx);
+    * copy_from_user_sec_ctx(), convert to xfrm_user_sec_ctx *
+    ...
+    
+    It seems that the expected parsing result for XFRMA_SEC_CTX should be
+    structure xfrm_user_sec_ctx, and the current xfrm_sec_ctx is confusing
+    and misleading (Luckily, they happen to have same size 8 bytes).
+    
+    This commit amend the policy structure to xfrm_user_sec_ctx to avoid
+    ambiguity.
+    
+    Fixes: cf5cb79f6946 ("[XFRM] netlink: Establish an attribute policy")
+    Signed-off-by: Lin Ma 
+    Signed-off-by: Steffen Klassert 
+
+diff --git a/net/xfrm/xfrm_compat.c b/net/xfrm/xfrm_compat.c
+index 8cbf45a8bcdc..655fe4ff8621 100644
+--- a/net/xfrm/xfrm_compat.c
++++ b/net/xfrm/xfrm_compat.c
+@@ -108,7 +108,7 @@ static const struct nla_policy compat_policy[XFRMA_MAX+1] = {
+ 	[XFRMA_ALG_COMP]	= { .len = sizeof(struct xfrm_algo) },
+ 	[XFRMA_ENCAP]		= { .len = sizeof(struct xfrm_encap_tmpl) },
+ 	[XFRMA_TMPL]		= { .len = sizeof(struct xfrm_user_tmpl) },
+-	[XFRMA_SEC_CTX]		= { .len = sizeof(struct xfrm_sec_ctx) },
++	[XFRMA_SEC_CTX]		= { .len = sizeof(struct xfrm_user_sec_ctx) },
+ 	[XFRMA_LTIME_VAL]	= { .len = sizeof(struct xfrm_lifetime_cur) },
+ 	[XFRMA_REPLAY_VAL]	= { .len = sizeof(struct xfrm_replay_state) },
+ 	[XFRMA_REPLAY_THRESH]	= { .type = NLA_U32 },
+diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
+index 7c91deadc36e..fdc0c17122b6 100644
+--- a/net/xfrm/xfrm_user.c
++++ b/net/xfrm/xfrm_user.c
+@@ -3024,7 +3024,7 @@ const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
+ 	[XFRMA_ALG_COMP]	= { .len = sizeof(struct xfrm_algo) },
+ 	[XFRMA_ENCAP]		= { .len = sizeof(struct xfrm_encap_tmpl) },
+ 	[XFRMA_TMPL]		= { .len = sizeof(struct xfrm_user_tmpl) },
+-	[XFRMA_SEC_CTX]		= { .len = sizeof(struct xfrm_sec_ctx) },
++	[XFRMA_SEC_CTX]		= { .len = sizeof(struct xfrm_user_sec_ctx) },
+ 	[XFRMA_LTIME_VAL]	= { .len = sizeof(struct xfrm_lifetime_cur) },
+ 	[XFRMA_REPLAY_VAL]	= { .len = sizeof(struct xfrm_replay_state) },
+ 	[XFRMA_REPLAY_THRESH]	= { .type = NLA_U32 },

commit 75065a8929069bc93181848818e23f147a73f83a
+Author: Lin Ma 
+Date:   Tue Jun 27 11:39:54 2023 +0800
+
+    net: af_key: fix sadb_x_filter validation
+    
+    When running xfrm_state_walk_init(), the xfrm_address_filter being used
+    is okay to have a splen/dplen that equals to sizeof(xfrm_address_t)<<3.
+    This commit replaces >= to > to make sure the boundary checking is
+    correct.
+    
+    Fixes: 37bd22420f85 ("af_key: pfkey_dump needs parameter validation")
+    Signed-off-by: Lin Ma 
+    Signed-off-by: Steffen Klassert 
+
+diff --git a/net/key/af_key.c b/net/key/af_key.c
+index ede3c6a60353..b4ea4cf9fad4 100644
+--- a/net/key/af_key.c
++++ b/net/key/af_key.c
+@@ -1848,9 +1848,9 @@ static int pfkey_dump(struct sock *sk, struct sk_buff *skb, const struct sadb_ms
+ 	if (ext_hdrs[SADB_X_EXT_FILTER - 1]) {
+ 		struct sadb_x_filter *xfilter = ext_hdrs[SADB_X_EXT_FILTER - 1];
+ 
+-		if ((xfilter->sadb_x_filter_splen >=
++		if ((xfilter->sadb_x_filter_splen >
+ 			(sizeof(xfrm_address_t) << 3)) ||
+-		    (xfilter->sadb_x_filter_dplen >=
++		    (xfilter->sadb_x_filter_dplen >
+ 			(sizeof(xfrm_address_t) << 3))) {
+ 			mutex_unlock(&pfk->dump_lock);
+ 			return -EINVAL;

commit dfa73c17d55b921e1d4e154976de35317e43a93a
+Author: Lin Ma 
+Date:   Tue Jun 27 11:31:38 2023 +0800
+
+    net: xfrm: Fix xfrm_address_filter OOB read
+    
+    We found below OOB crash:
+    
+    [   44.211730] ==================================================================
+    [   44.212045] BUG: KASAN: slab-out-of-bounds in memcmp+0x8b/0xb0
+    [   44.212045] Read of size 8 at addr ffff88800870f320 by task poc.xfrm/97
+    [   44.212045]
+    [   44.212045] CPU: 0 PID: 97 Comm: poc.xfrm Not tainted 6.4.0-rc7-00072-gdad9774deaf1-dirty #4
+    [   44.212045] Call Trace:
+    [   44.212045]  
+    [   44.212045]  dump_stack_lvl+0x37/0x50
+    [   44.212045]  print_report+0xcc/0x620
+    [   44.212045]  ? __virt_addr_valid+0xf3/0x170
+    [   44.212045]  ? memcmp+0x8b/0xb0
+    [   44.212045]  kasan_report+0xb2/0xe0
+    [   44.212045]  ? memcmp+0x8b/0xb0
+    [   44.212045]  kasan_check_range+0x39/0x1c0
+    [   44.212045]  memcmp+0x8b/0xb0
+    [   44.212045]  xfrm_state_walk+0x21c/0x420
+    [   44.212045]  ? __pfx_dump_one_state+0x10/0x10
+    [   44.212045]  xfrm_dump_sa+0x1e2/0x290
+    [   44.212045]  ? __pfx_xfrm_dump_sa+0x10/0x10
+    [   44.212045]  ? __kernel_text_address+0xd/0x40
+    [   44.212045]  ? kasan_unpoison+0x27/0x60
+    [   44.212045]  ? mutex_lock+0x60/0xe0
+    [   44.212045]  ? __pfx_mutex_lock+0x10/0x10
+    [   44.212045]  ? kasan_save_stack+0x22/0x50
+    [   44.212045]  netlink_dump+0x322/0x6c0
+    [   44.212045]  ? __pfx_netlink_dump+0x10/0x10
+    [   44.212045]  ? mutex_unlock+0x7f/0xd0
+    [   44.212045]  ? __pfx_mutex_unlock+0x10/0x10
+    [   44.212045]  __netlink_dump_start+0x353/0x430
+    [   44.212045]  xfrm_user_rcv_msg+0x3a4/0x410
+    [   44.212045]  ? __pfx__raw_spin_lock_irqsave+0x10/0x10
+    [   44.212045]  ? __pfx_xfrm_user_rcv_msg+0x10/0x10
+    [   44.212045]  ? __pfx_xfrm_dump_sa+0x10/0x10
+    [   44.212045]  ? __pfx_xfrm_dump_sa_done+0x10/0x10
+    [   44.212045]  ? __stack_depot_save+0x382/0x4e0
+    [   44.212045]  ? filter_irq_stacks+0x1c/0x70
+    [   44.212045]  ? kasan_save_stack+0x32/0x50
+    [   44.212045]  ? kasan_save_stack+0x22/0x50
+    [   44.212045]  ? kasan_set_track+0x25/0x30
+    [   44.212045]  ? __kasan_slab_alloc+0x59/0x70
+    [   44.212045]  ? kmem_cache_alloc_node+0xf7/0x260
+    [   44.212045]  ? kmalloc_reserve+0xab/0x120
+    [   44.212045]  ? __alloc_skb+0xcf/0x210
+    [   44.212045]  ? netlink_sendmsg+0x509/0x700
+    [   44.212045]  ? sock_sendmsg+0xde/0xe0
+    [   44.212045]  ? __sys_sendto+0x18d/0x230
+    [   44.212045]  ? __x64_sys_sendto+0x71/0x90
+    [   44.212045]  ? do_syscall_64+0x3f/0x90
+    [   44.212045]  ? entry_SYSCALL_64_after_hwframe+0x72/0xdc
+    [   44.212045]  ? netlink_sendmsg+0x509/0x700
+    [   44.212045]  ? sock_sendmsg+0xde/0xe0
+    [   44.212045]  ? __sys_sendto+0x18d/0x230
+    [   44.212045]  ? __x64_sys_sendto+0x71/0x90
+    [   44.212045]  ? do_syscall_64+0x3f/0x90
+    [   44.212045]  ? entry_SYSCALL_64_after_hwframe+0x72/0xdc
+    [   44.212045]  ? kasan_save_stack+0x22/0x50
+    [   44.212045]  ? kasan_set_track+0x25/0x30
+    [   44.212045]  ? kasan_save_free_info+0x2e/0x50
+    [   44.212045]  ? __kasan_slab_free+0x10a/0x190
+    [   44.212045]  ? kmem_cache_free+0x9c/0x340
+    [   44.212045]  ? netlink_recvmsg+0x23c/0x660
+    [   44.212045]  ? sock_recvmsg+0xeb/0xf0
+    [   44.212045]  ? __sys_recvfrom+0x13c/0x1f0
+    [   44.212045]  ? __x64_sys_recvfrom+0x71/0x90
+    [   44.212045]  ? do_syscall_64+0x3f/0x90
+    [   44.212045]  ? entry_SYSCALL_64_after_hwframe+0x72/0xdc
+    [   44.212045]  ? copyout+0x3e/0x50
+    [   44.212045]  netlink_rcv_skb+0xd6/0x210
+    [   44.212045]  ? __pfx_xfrm_user_rcv_msg+0x10/0x10
+    [   44.212045]  ? __pfx_netlink_rcv_skb+0x10/0x10
+    [   44.212045]  ? __pfx_sock_has_perm+0x10/0x10
+    [   44.212045]  ? mutex_lock+0x8d/0xe0
+    [   44.212045]  ? __pfx_mutex_lock+0x10/0x10
+    [   44.212045]  xfrm_netlink_rcv+0x44/0x50
+    [   44.212045]  netlink_unicast+0x36f/0x4c0
+    [   44.212045]  ? __pfx_netlink_unicast+0x10/0x10
+    [   44.212045]  ? netlink_recvmsg+0x500/0x660
+    [   44.212045]  netlink_sendmsg+0x3b7/0x700
+    [   44.212045]  ? __pfx_netlink_sendmsg+0x10/0x10
+    [   44.212045]  ? __pfx_netlink_sendmsg+0x10/0x10
+    [   44.212045]  sock_sendmsg+0xde/0xe0
+    [   44.212045]  __sys_sendto+0x18d/0x230
+    [   44.212045]  ? __pfx___sys_sendto+0x10/0x10
+    [   44.212045]  ? rcu_core+0x44a/0xe10
+    [   44.212045]  ? __rseq_handle_notify_resume+0x45b/0x740
+    [   44.212045]  ? _raw_spin_lock_irq+0x81/0xe0
+    [   44.212045]  ? __pfx___rseq_handle_notify_resume+0x10/0x10
+    [   44.212045]  ? __pfx_restore_fpregs_from_fpstate+0x10/0x10
+    [   44.212045]  ? __pfx_blkcg_maybe_throttle_current+0x10/0x10
+    [   44.212045]  ? __pfx_task_work_run+0x10/0x10
+    [   44.212045]  __x64_sys_sendto+0x71/0x90
+    [   44.212045]  do_syscall_64+0x3f/0x90
+    [   44.212045]  entry_SYSCALL_64_after_hwframe+0x72/0xdc
+    [   44.212045] RIP: 0033:0x44b7da
+    [   44.212045] RSP: 002b:00007ffdc8838548 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
+    [   44.212045] RAX: ffffffffffffffda RBX: 00007ffdc8839978 RCX: 000000000044b7da
+    [   44.212045] RDX: 0000000000000038 RSI: 00007ffdc8838770 RDI: 0000000000000003
+    [   44.212045] RBP: 00007ffdc88385b0 R08: 00007ffdc883858c R09: 000000000000000c
+    [   44.212045] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000001
+    [   44.212045] R13: 00007ffdc8839968 R14: 00000000004c37d0 R15: 0000000000000001
+    [   44.212045]  
+    [   44.212045]
+    [   44.212045] Allocated by task 97:
+    [   44.212045]  kasan_save_stack+0x22/0x50
+    [   44.212045]  kasan_set_track+0x25/0x30
+    [   44.212045]  __kasan_kmalloc+0x7f/0x90
+    [   44.212045]  __kmalloc_node_track_caller+0x5b/0x140
+    [   44.212045]  kmemdup+0x21/0x50
+    [   44.212045]  xfrm_dump_sa+0x17d/0x290
+    [   44.212045]  netlink_dump+0x322/0x6c0
+    [   44.212045]  __netlink_dump_start+0x353/0x430
+    [   44.212045]  xfrm_user_rcv_msg+0x3a4/0x410
+    [   44.212045]  netlink_rcv_skb+0xd6/0x210
+    [   44.212045]  xfrm_netlink_rcv+0x44/0x50
+    [   44.212045]  netlink_unicast+0x36f/0x4c0
+    [   44.212045]  netlink_sendmsg+0x3b7/0x700
+    [   44.212045]  sock_sendmsg+0xde/0xe0
+    [   44.212045]  __sys_sendto+0x18d/0x230
+    [   44.212045]  __x64_sys_sendto+0x71/0x90
+    [   44.212045]  do_syscall_64+0x3f/0x90
+    [   44.212045]  entry_SYSCALL_64_after_hwframe+0x72/0xdc
+    [   44.212045]
+    [   44.212045] The buggy address belongs to the object at ffff88800870f300
+    [   44.212045]  which belongs to the cache kmalloc-64 of size 64
+    [   44.212045] The buggy address is located 32 bytes inside of
+    [   44.212045]  allocated 36-byte region [ffff88800870f300, ffff88800870f324)
+    [   44.212045]
+    [   44.212045] The buggy address belongs to the physical page:
+    [   44.212045] page:00000000e4de16ee refcount:1 mapcount:0 mapping:000000000 ...
+    [   44.212045] flags: 0x100000000000200(slab|node=0|zone=1)
+    [   44.212045] page_type: 0xffffffff()
+    [   44.212045] raw: 0100000000000200 ffff888004c41640 dead000000000122 0000000000000000
+    [   44.212045] raw: 0000000000000000 0000000080200020 00000001ffffffff 0000000000000000
+    [   44.212045] page dumped because: kasan: bad access detected
+    [   44.212045]
+    [   44.212045] Memory state around the buggy address:
+    [   44.212045]  ffff88800870f200: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
+    [   44.212045]  ffff88800870f280: 00 00 00 00 00 fc fc fc fc fc fc fc fc fc fc fc
+    [   44.212045] >ffff88800870f300: 00 00 00 00 04 fc fc fc fc fc fc fc fc fc fc fc
+    [   44.212045]                                ^
+    [   44.212045]  ffff88800870f380: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
+    [   44.212045]  ffff88800870f400: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
+    [   44.212045] ==================================================================
+    
+    By investigating the code, we find the root cause of this OOB is the lack
+    of checks in xfrm_dump_sa(). The buggy code allows a malicious user to pass
+    arbitrary value of filter->splen/dplen. Hence, with crafted xfrm states,
+    the attacker can achieve 8 bytes heap OOB read, which causes info leak.
+    
+      if (attrs[XFRMA_ADDRESS_FILTER]) {
+        filter = kmemdup(nla_data(attrs[XFRMA_ADDRESS_FILTER]),
+            sizeof(*filter), GFP_KERNEL);
+        if (filter == NULL)
+          return -ENOMEM;
+        // NO MORE CHECKS HERE !!!
+      }
+    
+    This patch fixes the OOB by adding necessary boundary checks, just like
+    the code in pfkey_dump() function.
+    
+    Fixes: d3623099d350 ("ipsec: add support of limited SA dump")
+    Signed-off-by: Lin Ma 
+    Signed-off-by: Steffen Klassert 
+
+diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
+index c34a2a06ca94..7c91deadc36e 100644
+--- a/net/xfrm/xfrm_user.c
++++ b/net/xfrm/xfrm_user.c
+@@ -1267,6 +1267,15 @@ static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb)
+ 					 sizeof(*filter), GFP_KERNEL);
+ 			if (filter == NULL)
+ 				return -ENOMEM;
++
++			/* see addr_match(), (prefix length >> 5) << 2
++			 * will be used to compare xfrm_address_t
++			 */
++			if (filter->splen > (sizeof(xfrm_address_t) << 3) ||
++			    filter->dplen > (sizeof(xfrm_address_t) << 3)) {
++				kfree(filter);
++				return -EINVAL;
++			}
+ 		}
+ 
+ 		if (attrs[XFRMA_PROTO])

commit 6709d4b7bc2e079241fdef15d1160581c5261c10
+Author: Lin Ma 
+Date:   Sun Jun 25 17:10:07 2023 +0800
+
+    net: nfc: Fix use-after-free caused by nfc_llcp_find_local
+    
+    This commit fixes several use-after-free that caused by function
+    nfc_llcp_find_local(). For example, one UAF can happen when below buggy
+    time window occurs.
+    
+    // nfc_genl_llc_get_params   | // nfc_unregister_device
+                                 |
+    dev = nfc_get_device(idx);   | device_lock(...)
+    if (!dev)                    | dev->shutting_down = true;
+        return -ENODEV;          | device_unlock(...);
+                                 |
+    device_lock(...);            |   // nfc_llcp_unregister_device
+                                 |   nfc_llcp_find_local()
+    nfc_llcp_find_local(...);    |
+                                 |   local_cleanup()
+    if (!local) {                |
+        rc = -ENODEV;            |     // nfc_llcp_local_put
+        goto exit;               |     kref_put(.., local_release)
+    }                            |
+                                 |       // local_release
+                                 |       list_del(&local->list)
+      // nfc_genl_send_params    |       kfree()
+      local->dev->idx !!!UAF!!!  |
+                                 |
+    
+    and the crash trace for the one of the discussed UAF like:
+    
+    BUG: KASAN: slab-use-after-free in nfc_genl_llc_get_params+0x72f/0x780  net/nfc/netlink.c:1045
+    Read of size 8 at addr ffff888105b0e410 by task 20114
+    
+    Call Trace:
+     
+     __dump_stack  lib/dump_stack.c:88 [inline]
+     dump_stack_lvl+0x72/0xa0  lib/dump_stack.c:106
+     print_address_description  mm/kasan/report.c:319 [inline]
+     print_report+0xcc/0x620  mm/kasan/report.c:430
+     kasan_report+0xb2/0xe0  mm/kasan/report.c:536
+     nfc_genl_send_params  net/nfc/netlink.c:999 [inline]
+     nfc_genl_llc_get_params+0x72f/0x780  net/nfc/netlink.c:1045
+     genl_family_rcv_msg_doit.isra.0+0x1ee/0x2e0  net/netlink/genetlink.c:968
+     genl_family_rcv_msg  net/netlink/genetlink.c:1048 [inline]
+     genl_rcv_msg+0x503/0x7d0  net/netlink/genetlink.c:1065
+     netlink_rcv_skb+0x161/0x430  net/netlink/af_netlink.c:2548
+     genl_rcv+0x28/0x40  net/netlink/genetlink.c:1076
+     netlink_unicast_kernel  net/netlink/af_netlink.c:1339 [inline]
+     netlink_unicast+0x644/0x900  net/netlink/af_netlink.c:1365
+     netlink_sendmsg+0x934/0xe70  net/netlink/af_netlink.c:1913
+     sock_sendmsg_nosec  net/socket.c:724 [inline]
+     sock_sendmsg+0x1b6/0x200  net/socket.c:747
+     ____sys_sendmsg+0x6e9/0x890  net/socket.c:2501
+     ___sys_sendmsg+0x110/0x1b0  net/socket.c:2555
+     __sys_sendmsg+0xf7/0x1d0  net/socket.c:2584
+     do_syscall_x64  arch/x86/entry/common.c:50 [inline]
+     do_syscall_64+0x3f/0x90  arch/x86/entry/common.c:80
+     entry_SYSCALL_64_after_hwframe+0x72/0xdc
+    RIP: 0033:0x7f34640a2389
+    RSP: 002b:00007f3463415168 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
+    RAX: ffffffffffffffda RBX: 00007f34641c1f80 RCX: 00007f34640a2389
+    RDX: 0000000000000000 RSI: 0000000020000240 RDI: 0000000000000006
+    RBP: 00007f34640ed493 R08: 0000000000000000 R09: 0000000000000000
+    R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
+    R13: 00007ffe38449ecf R14: 00007f3463415300 R15: 0000000000022000
+     
+    
+    Allocated by task 20116:
+     kasan_save_stack+0x22/0x50  mm/kasan/common.c:45
+     kasan_set_track+0x25/0x30  mm/kasan/common.c:52
+     ____kasan_kmalloc  mm/kasan/common.c:374 [inline]
+     __kasan_kmalloc+0x7f/0x90  mm/kasan/common.c:383
+     kmalloc  include/linux/slab.h:580 [inline]
+     kzalloc  include/linux/slab.h:720 [inline]
+     nfc_llcp_register_device+0x49/0xa40  net/nfc/llcp_core.c:1567
+     nfc_register_device+0x61/0x260  net/nfc/core.c:1124
+     nci_register_device+0x776/0xb20  net/nfc/nci/core.c:1257
+     virtual_ncidev_open+0x147/0x230  drivers/nfc/virtual_ncidev.c:148
+     misc_open+0x379/0x4a0  drivers/char/misc.c:165
+     chrdev_open+0x26c/0x780  fs/char_dev.c:414
+     do_dentry_open+0x6c4/0x12a0  fs/open.c:920
+     do_open  fs/namei.c:3560 [inline]
+     path_openat+0x24fe/0x37e0  fs/namei.c:3715
+     do_filp_open+0x1ba/0x410  fs/namei.c:3742
+     do_sys_openat2+0x171/0x4c0  fs/open.c:1356
+     do_sys_open  fs/open.c:1372 [inline]
+     __do_sys_openat  fs/open.c:1388 [inline]
+     __se_sys_openat  fs/open.c:1383 [inline]
+     __x64_sys_openat+0x143/0x200  fs/open.c:1383
+     do_syscall_x64  arch/x86/entry/common.c:50 [inline]
+     do_syscall_64+0x3f/0x90  arch/x86/entry/common.c:80
+     entry_SYSCALL_64_after_hwframe+0x72/0xdc
+    
+    Freed by task 20115:
+     kasan_save_stack+0x22/0x50  mm/kasan/common.c:45
+     kasan_set_track+0x25/0x30  mm/kasan/common.c:52
+     kasan_save_free_info+0x2e/0x50  mm/kasan/generic.c:521
+     ____kasan_slab_free  mm/kasan/common.c:236 [inline]
+     ____kasan_slab_free  mm/kasan/common.c:200 [inline]
+     __kasan_slab_free+0x10a/0x190  mm/kasan/common.c:244
+     kasan_slab_free  include/linux/kasan.h:162 [inline]
+     slab_free_hook  mm/slub.c:1781 [inline]
+     slab_free_freelist_hook  mm/slub.c:1807 [inline]
+     slab_free  mm/slub.c:3787 [inline]
+     __kmem_cache_free+0x7a/0x190  mm/slub.c:3800
+     local_release  net/nfc/llcp_core.c:174 [inline]
+     kref_put  include/linux/kref.h:65 [inline]
+     nfc_llcp_local_put  net/nfc/llcp_core.c:182 [inline]
+     nfc_llcp_local_put  net/nfc/llcp_core.c:177 [inline]
+     nfc_llcp_unregister_device+0x206/0x290  net/nfc/llcp_core.c:1620
+     nfc_unregister_device+0x160/0x1d0  net/nfc/core.c:1179
+     virtual_ncidev_close+0x52/0xa0  drivers/nfc/virtual_ncidev.c:163
+     __fput+0x252/0xa20  fs/file_table.c:321
+     task_work_run+0x174/0x270  kernel/task_work.c:179
+     resume_user_mode_work  include/linux/resume_user_mode.h:49 [inline]
+     exit_to_user_mode_loop  kernel/entry/common.c:171 [inline]
+     exit_to_user_mode_prepare+0x108/0x110  kernel/entry/common.c:204
+     __syscall_exit_to_user_mode_work  kernel/entry/common.c:286 [inline]
+     syscall_exit_to_user_mode+0x21/0x50  kernel/entry/common.c:297
+     do_syscall_64+0x4c/0x90  arch/x86/entry/common.c:86
+     entry_SYSCALL_64_after_hwframe+0x72/0xdc
+    
+    Last potentially related work creation:
+     kasan_save_stack+0x22/0x50  mm/kasan/common.c:45
+     __kasan_record_aux_stack+0x95/0xb0  mm/kasan/generic.c:491
+     kvfree_call_rcu+0x29/0xa80  kernel/rcu/tree.c:3328
+     drop_sysctl_table+0x3be/0x4e0  fs/proc/proc_sysctl.c:1735
+     unregister_sysctl_table.part.0+0x9c/0x190  fs/proc/proc_sysctl.c:1773
+     unregister_sysctl_table+0x24/0x30  fs/proc/proc_sysctl.c:1753
+     neigh_sysctl_unregister+0x5f/0x80  net/core/neighbour.c:3895
+     addrconf_notify+0x140/0x17b0  net/ipv6/addrconf.c:3684
+     notifier_call_chain+0xbe/0x210  kernel/notifier.c:87
+     call_netdevice_notifiers_info+0xb5/0x150  net/core/dev.c:1937
+     call_netdevice_notifiers_extack  net/core/dev.c:1975 [inline]
+     call_netdevice_notifiers  net/core/dev.c:1989 [inline]
+     dev_change_name+0x3c3/0x870  net/core/dev.c:1211
+     dev_ifsioc+0x800/0xf70  net/core/dev_ioctl.c:376
+     dev_ioctl+0x3d9/0xf80  net/core/dev_ioctl.c:542
+     sock_do_ioctl+0x160/0x260  net/socket.c:1213
+     sock_ioctl+0x3f9/0x670  net/socket.c:1316
+     vfs_ioctl  fs/ioctl.c:51 [inline]
+     __do_sys_ioctl  fs/ioctl.c:870 [inline]
+     __se_sys_ioctl  fs/ioctl.c:856 [inline]
+     __x64_sys_ioctl+0x19e/0x210  fs/ioctl.c:856
+     do_syscall_x64  arch/x86/entry/common.c:50 [inline]
+     do_syscall_64+0x3f/0x90  arch/x86/entry/common.c:80
+     entry_SYSCALL_64_after_hwframe+0x72/0xdc
+    
+    The buggy address belongs to the object at ffff888105b0e400
+     which belongs to the cache kmalloc-1k of size 1024
+    The buggy address is located 16 bytes inside of
+     freed 1024-byte region [ffff888105b0e400, ffff888105b0e800)
+    
+    The buggy address belongs to the physical page:
+    head:ffffea000416c200 order:3 entire_mapcount:0 nr_pages_mapped:0 pincount:0
+    flags: 0x200000000010200(slab|head|node=0|zone=2)
+    raw: 0200000000010200 ffff8881000430c0 ffffea00044c7010 ffffea0004510e10
+    raw: 0000000000000000 00000000000a000a 00000001ffffffff 0000000000000000
+    page dumped because: kasan: bad access detected
+    
+    Memory state around the buggy address:
+     ffff888105b0e300: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
+     ffff888105b0e380: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
+    >ffff888105b0e400: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+                             ^
+     ffff888105b0e480: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+     ffff888105b0e500: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+    
+    In summary, this patch solves those use-after-free by
+    
+    1. Re-implement the nfc_llcp_find_local(). The current version does not
+    grab the reference when getting the local from the linked list.  For
+    example, the llcp_sock_bind() gets the reference like below:
+    
+    // llcp_sock_bind()
+    
+        local = nfc_llcp_find_local(dev); // A
+        ..... \
+               | raceable
+        ..... /
+        llcp_sock->local = nfc_llcp_local_get(local); // B
+    
+    There is an apparent race window that one can  drop the reference
+    and free the local object fetched in (A) before (B) gets the reference.
+    
+    2. Some callers of the nfc_llcp_find_local() do not grab the reference
+    at all. For example, the nfc_genl_llc_{{get/set}_params/sdreq} functions.
+    We add the nfc_llcp_local_put() for them. Moreover, we add the necessary
+    error handling function to put the reference.
+    
+    3. Add the nfc_llcp_remove_local() helper. The local object is removed
+    from the linked list in local_release() when all reference is gone. This
+    patch removes it when nfc_llcp_unregister_device() is called.
+    
+    Therefore, every caller of nfc_llcp_find_local() will get a reference
+    even when the nfc_llcp_unregister_device() is called. This promises no
+    use-after-free for the local object is ever possible.
+    
+    Fixes: 52feb444a903 ("NFC: Extend netlink interface for LTO, RW, and MIUX parameters support")
+    Fixes: c7aa12252f51 ("NFC: Take a reference on the LLCP local pointer when creating a socket")
+    Signed-off-by: Lin Ma 
+    Reviewed-by: Simon Horman 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/nfc/llcp.h b/net/nfc/llcp.h
+index c1d9be636933..d8345ed57c95 100644
+--- a/net/nfc/llcp.h
++++ b/net/nfc/llcp.h
+@@ -201,7 +201,6 @@ void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *s);
+ void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *s);
+ void nfc_llcp_socket_remote_param_init(struct nfc_llcp_sock *sock);
+ struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev);
+-struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local);
+ int nfc_llcp_local_put(struct nfc_llcp_local *local);
+ u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
+ 			 struct nfc_llcp_sock *sock);
+diff --git a/net/nfc/llcp_commands.c b/net/nfc/llcp_commands.c
+index 41e3a20c8935..5d2d4bc26ef9 100644
+--- a/net/nfc/llcp_commands.c
++++ b/net/nfc/llcp_commands.c
+@@ -359,6 +359,7 @@ int nfc_llcp_send_symm(struct nfc_dev *dev)
+ 	struct sk_buff *skb;
+ 	struct nfc_llcp_local *local;
+ 	u16 size = 0;
++	int err;
+ 
+ 	local = nfc_llcp_find_local(dev);
+ 	if (local == NULL)
+@@ -368,8 +369,10 @@ int nfc_llcp_send_symm(struct nfc_dev *dev)
+ 	size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE;
+ 
+ 	skb = alloc_skb(size, GFP_KERNEL);
+-	if (skb == NULL)
+-		return -ENOMEM;
++	if (skb == NULL) {
++		err = -ENOMEM;
++		goto out;
++	}
+ 
+ 	skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE);
+ 
+@@ -379,8 +382,11 @@ int nfc_llcp_send_symm(struct nfc_dev *dev)
+ 
+ 	nfc_llcp_send_to_raw_sock(local, skb, NFC_DIRECTION_TX);
+ 
+-	return nfc_data_exchange(dev, local->target_idx, skb,
++	err = nfc_data_exchange(dev, local->target_idx, skb,
+ 				 nfc_llcp_recv, local);
++out:
++	nfc_llcp_local_put(local);
++	return err;
+ }
+ 
+ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
+diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c
+index a27e1842b2a0..f60e424e0607 100644
+--- a/net/nfc/llcp_core.c
++++ b/net/nfc/llcp_core.c
+@@ -17,6 +17,8 @@
+ static u8 llcp_magic[3] = {0x46, 0x66, 0x6d};
+ 
+ static LIST_HEAD(llcp_devices);
++/* Protects llcp_devices list */
++static DEFINE_SPINLOCK(llcp_devices_lock);
+ 
+ static void nfc_llcp_rx_skb(struct nfc_llcp_local *local, struct sk_buff *skb);
+ 
+@@ -141,7 +143,7 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool device,
+ 	write_unlock(&local->raw_sockets.lock);
+ }
+ 
+-struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
++static struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
+ {
+ 	kref_get(&local->ref);
+ 
+@@ -169,7 +171,6 @@ static void local_release(struct kref *ref)
+ 
+ 	local = container_of(ref, struct nfc_llcp_local, ref);
+ 
+-	list_del(&local->list);
+ 	local_cleanup(local);
+ 	kfree(local);
+ }
+@@ -282,12 +283,33 @@ static void nfc_llcp_sdreq_timer(struct timer_list *t)
+ struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev)
+ {
+ 	struct nfc_llcp_local *local;
++	struct nfc_llcp_local *res = NULL;
+ 
++	spin_lock(&llcp_devices_lock);
+ 	list_for_each_entry(local, &llcp_devices, list)
+-		if (local->dev == dev)
++		if (local->dev == dev) {
++			res = nfc_llcp_local_get(local);
++			break;
++		}
++	spin_unlock(&llcp_devices_lock);
++
++	return res;
++}
++
++static struct nfc_llcp_local *nfc_llcp_remove_local(struct nfc_dev *dev)
++{
++	struct nfc_llcp_local *local, *tmp;
++
++	spin_lock(&llcp_devices_lock);
++	list_for_each_entry_safe(local, tmp, &llcp_devices, list)
++		if (local->dev == dev) {
++			list_del(&local->list);
++			spin_unlock(&llcp_devices_lock);
+ 			return local;
++		}
++	spin_unlock(&llcp_devices_lock);
+ 
+-	pr_debug("No device found\n");
++	pr_warn("Shutting down device not found\n");
+ 
+ 	return NULL;
+ }
+@@ -608,12 +630,15 @@ u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len)
+ 
+ 	*general_bytes_len = local->gb_len;
+ 
++	nfc_llcp_local_put(local);
++
+ 	return local->gb;
+ }
+ 
+ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, const u8 *gb, u8 gb_len)
+ {
+ 	struct nfc_llcp_local *local;
++	int err;
+ 
+ 	if (gb_len < 3 || gb_len > NFC_MAX_GT_LEN)
+ 		return -EINVAL;
+@@ -630,12 +655,16 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, const u8 *gb, u8 gb_len)
+ 
+ 	if (memcmp(local->remote_gb, llcp_magic, 3)) {
+ 		pr_err("MAC does not support LLCP\n");
+-		return -EINVAL;
++		err = -EINVAL;
++		goto out;
+ 	}
+ 
+-	return nfc_llcp_parse_gb_tlv(local,
++	err = nfc_llcp_parse_gb_tlv(local,
+ 				     &local->remote_gb[3],
+ 				     local->remote_gb_len - 3);
++out:
++	nfc_llcp_local_put(local);
++	return err;
+ }
+ 
+ static u8 nfc_llcp_dsap(const struct sk_buff *pdu)
+@@ -1517,6 +1546,8 @@ int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb)
+ 
+ 	__nfc_llcp_recv(local, skb);
+ 
++	nfc_llcp_local_put(local);
++
+ 	return 0;
+ }
+ 
+@@ -1533,6 +1564,8 @@ void nfc_llcp_mac_is_down(struct nfc_dev *dev)
+ 
+ 	/* Close and purge all existing sockets */
+ 	nfc_llcp_socket_release(local, true, 0);
++
++	nfc_llcp_local_put(local);
+ }
+ 
+ void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
+@@ -1558,6 +1591,8 @@ void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
+ 		mod_timer(&local->link_timer,
+ 			  jiffies + msecs_to_jiffies(local->remote_lto));
+ 	}
++
++	nfc_llcp_local_put(local);
+ }
+ 
+ int nfc_llcp_register_device(struct nfc_dev *ndev)
+@@ -1608,7 +1643,7 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
+ 
+ void nfc_llcp_unregister_device(struct nfc_dev *dev)
+ {
+-	struct nfc_llcp_local *local = nfc_llcp_find_local(dev);
++	struct nfc_llcp_local *local = nfc_llcp_remove_local(dev);
+ 
+ 	if (local == NULL) {
+ 		pr_debug("No such device\n");
+diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c
+index 77642d18a3b4..645677f84dba 100644
+--- a/net/nfc/llcp_sock.c
++++ b/net/nfc/llcp_sock.c
+@@ -99,7 +99,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
+ 	}
+ 
+ 	llcp_sock->dev = dev;
+-	llcp_sock->local = nfc_llcp_local_get(local);
++	llcp_sock->local = local;
+ 	llcp_sock->nfc_protocol = llcp_addr.nfc_protocol;
+ 	llcp_sock->service_name_len = min_t(unsigned int,
+ 					    llcp_addr.service_name_len,
+@@ -186,7 +186,7 @@ static int llcp_raw_sock_bind(struct socket *sock, struct sockaddr *addr,
+ 	}
+ 
+ 	llcp_sock->dev = dev;
+-	llcp_sock->local = nfc_llcp_local_get(local);
++	llcp_sock->local = local;
+ 	llcp_sock->nfc_protocol = llcp_addr.nfc_protocol;
+ 
+ 	nfc_llcp_sock_link(&local->raw_sockets, sk);
+@@ -696,22 +696,22 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
+ 	if (dev->dep_link_up == false) {
+ 		ret = -ENOLINK;
+ 		device_unlock(&dev->dev);
+-		goto put_dev;
++		goto sock_llcp_put_local;
+ 	}
+ 	device_unlock(&dev->dev);
+ 
+ 	if (local->rf_mode == NFC_RF_INITIATOR &&
+ 	    addr->target_idx != local->target_idx) {
+ 		ret = -ENOLINK;
+-		goto put_dev;
++		goto sock_llcp_put_local;
+ 	}
+ 
+ 	llcp_sock->dev = dev;
+-	llcp_sock->local = nfc_llcp_local_get(local);
++	llcp_sock->local = local;
+ 	llcp_sock->ssap = nfc_llcp_get_local_ssap(local);
+ 	if (llcp_sock->ssap == LLCP_SAP_MAX) {
+ 		ret = -ENOMEM;
+-		goto sock_llcp_put_local;
++		goto sock_llcp_nullify;
+ 	}
+ 
+ 	llcp_sock->reserved_ssap = llcp_sock->ssap;
+@@ -757,11 +757,13 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
+ sock_llcp_release:
+ 	nfc_llcp_put_ssap(local, llcp_sock->ssap);
+ 
+-sock_llcp_put_local:
+-	nfc_llcp_local_put(llcp_sock->local);
++sock_llcp_nullify:
+ 	llcp_sock->local = NULL;
+ 	llcp_sock->dev = NULL;
+ 
++sock_llcp_put_local:
++	nfc_llcp_local_put(local);
++
+ put_dev:
+ 	nfc_put_device(dev);
+ 
+diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
+index b9264e730fd9..e9ac6a6f934e 100644
+--- a/net/nfc/netlink.c
++++ b/net/nfc/netlink.c
+@@ -1039,11 +1039,14 @@ static int nfc_genl_llc_get_params(struct sk_buff *skb, struct genl_info *info)
+ 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ 	if (!msg) {
+ 		rc = -ENOMEM;
+-		goto exit;
++		goto put_local;
+ 	}
+ 
+ 	rc = nfc_genl_send_params(msg, local, info->snd_portid, info->snd_seq);
+ 
++put_local:
++	nfc_llcp_local_put(local);
++
+ exit:
+ 	device_unlock(&dev->dev);
+ 
+@@ -1105,7 +1108,7 @@ static int nfc_genl_llc_set_params(struct sk_buff *skb, struct genl_info *info)
+ 	if (info->attrs[NFC_ATTR_LLC_PARAM_LTO]) {
+ 		if (dev->dep_link_up) {
+ 			rc = -EINPROGRESS;
+-			goto exit;
++			goto put_local;
+ 		}
+ 
+ 		local->lto = nla_get_u8(info->attrs[NFC_ATTR_LLC_PARAM_LTO]);
+@@ -1117,6 +1120,9 @@ static int nfc_genl_llc_set_params(struct sk_buff *skb, struct genl_info *info)
+ 	if (info->attrs[NFC_ATTR_LLC_PARAM_MIUX])
+ 		local->miux = cpu_to_be16(miux);
+ 
++put_local:
++	nfc_llcp_local_put(local);
++
+ exit:
+ 	device_unlock(&dev->dev);
+ 
+@@ -1172,7 +1178,7 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info)
+ 
+ 		if (rc != 0) {
+ 			rc = -EINVAL;
+-			goto exit;
++			goto put_local;
+ 		}
+ 
+ 		if (!sdp_attrs[NFC_SDP_ATTR_URI])
+@@ -1191,7 +1197,7 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info)
+ 		sdreq = nfc_llcp_build_sdreq_tlv(tid, uri, uri_len);
+ 		if (sdreq == NULL) {
+ 			rc = -ENOMEM;
+-			goto exit;
++			goto put_local;
+ 		}
+ 
+ 		tlvs_len += sdreq->tlv_len;
+@@ -1201,10 +1207,14 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info)
+ 
+ 	if (hlist_empty(&sdreq_list)) {
+ 		rc = -EINVAL;
+-		goto exit;
++		goto put_local;
+ 	}
+ 
+ 	rc = nfc_llcp_send_snl_sdreq(local, &sdreq_list, tlvs_len);
++
++put_local:
++	nfc_llcp_local_put(local);
++
+ exit:
+ 	device_unlock(&dev->dev);
+ 
+diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h
+index de2ec66d7e83..0b1e6466f4fb 100644
+--- a/net/nfc/nfc.h
++++ b/net/nfc/nfc.h
+@@ -52,6 +52,7 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, const u8 *gb, u8 gb_len);
+ u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len);
+ int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb);
+ struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev);
++int nfc_llcp_local_put(struct nfc_llcp_local *local);
+ int __init nfc_llcp_init(void);
+ void nfc_llcp_exit(void);
+ void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp);

commit f60ce8a48b97eb970bfbec1f26c914b9017c4a46
+Author: Lin Ma 
+Date:   Thu Jun 15 23:22:40 2023 +0800
+
+    net: mctp: remove redundant RTN_UNICAST check
+    
+    Current mctp_newroute() contains two exactly same check against
+    rtm->rtm_type
+    
+    static int mctp_newroute(...)
+    {
+    ...
+        if (rtm->rtm_type != RTN_UNICAST) { // (1)
+            NL_SET_ERR_MSG(extack, "rtm_type must be RTN_UNICAST");
+            return -EINVAL;
+        }
+    ...
+        if (rtm->rtm_type != RTN_UNICAST) // (2)
+            return -EINVAL;
+    ...
+    }
+    
+    This commits removes the (2) check as it is redundant.
+    
+    Signed-off-by: Lin Ma 
+    Reviewed-by: Pavan Chebbi 
+    Acked-by: Jeremy Kerr 
+    Link: https://lore.kernel.org/r/20230615152240.1749428-1-linma@zju.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/net/mctp/route.c b/net/mctp/route.c
+index f51a05ec7162..ab62fe447038 100644
+--- a/net/mctp/route.c
++++ b/net/mctp/route.c
+@@ -1249,9 +1249,6 @@ static int mctp_newroute(struct sk_buff *skb, struct nlmsghdr *nlh,
+ 			mtu = nla_get_u32(tbx[RTAX_MTU]);
+ 	}
+ 
+-	if (rtm->rtm_type != RTN_UNICAST)
+-		return -EINVAL;
+-
+ 	rc = mctp_route_add(mdev, daddr_start, rtm->rtm_dst_len, mtu,
+ 			    rtm->rtm_type);
+ 	return rc;

commit 44194cb1b6045dea33ae9a0d54fb7e7cd93a2e09
+Author: Lin Ma 
+Date:   Wed Jun 14 20:06:04 2023 +0800
+
+    net: tipc: resize nlattr array to correct size
+    
+    According to nla_parse_nested_deprecated(), the tb[] is supposed to the
+    destination array with maxtype+1 elements. In current
+    tipc_nl_media_get() and __tipc_nl_media_set(), a larger array is used
+    which is unnecessary. This patch resize them to a proper size.
+    
+    Fixes: 1e55417d8fc6 ("tipc: add media set to new netlink api")
+    Fixes: 46f15c6794fb ("tipc: add media get/dump to new netlink api")
+    Signed-off-by: Lin Ma 
+    Reviewed-by: Florian Westphal 
+    Reviewed-by: Tung Nguyen 
+    Link: https://lore.kernel.org/r/20230614120604.1196377-1-linma@zju.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
+index 53881406e200..cdcd2731860b 100644
+--- a/net/tipc/bearer.c
++++ b/net/tipc/bearer.c
+@@ -1258,7 +1258,7 @@ int tipc_nl_media_get(struct sk_buff *skb, struct genl_info *info)
+ 	struct tipc_nl_msg msg;
+ 	struct tipc_media *media;
+ 	struct sk_buff *rep;
+-	struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
++	struct nlattr *attrs[TIPC_NLA_MEDIA_MAX + 1];
+ 
+ 	if (!info->attrs[TIPC_NLA_MEDIA])
+ 		return -EINVAL;
+@@ -1307,7 +1307,7 @@ int __tipc_nl_media_set(struct sk_buff *skb, struct genl_info *info)
+ 	int err;
+ 	char *name;
+ 	struct tipc_media *m;
+-	struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
++	struct nlattr *attrs[TIPC_NLA_MEDIA_MAX + 1];
+ 
+ 	if (!info->attrs[TIPC_NLA_MEDIA])
+ 		return -EINVAL;

commit 361b6889ae636926cdff517add240c3c8e24593a
+Author: Lin Ma 
+Date:   Wed Jun 14 09:52:49 2023 +0800
+
+    net/handshake: remove fput() that causes use-after-free
+    
+    A reference underflow is found in TLS handshake subsystem that causes a
+    direct use-after-free. Part of the crash log is like below:
+    
+    [    2.022114] ------------[ cut here ]------------
+    [    2.022193] refcount_t: underflow; use-after-free.
+    [    2.022288] WARNING: CPU: 0 PID: 60 at lib/refcount.c:28 refcount_warn_saturate+0xbe/0x110
+    [    2.022432] Modules linked in:
+    [    2.022848] RIP: 0010:refcount_warn_saturate+0xbe/0x110
+    [    2.023231] RSP: 0018:ffffc900001bfe18 EFLAGS: 00000286
+    [    2.023325] RAX: 0000000000000000 RBX: 0000000000000007 RCX: 00000000ffffdfff
+    [    2.023438] RDX: 0000000000000000 RSI: 00000000ffffffea RDI: 0000000000000001
+    [    2.023555] RBP: ffff888004c20098 R08: ffffffff82b392c8 R09: 00000000ffffdfff
+    [    2.023693] R10: ffffffff82a592e0 R11: ffffffff82b092e0 R12: ffff888004c200d8
+    [    2.023813] R13: 0000000000000000 R14: ffff888004c20000 R15: ffffc90000013ca8
+    [    2.023930] FS:  0000000000000000(0000) GS:ffff88807dc00000(0000) knlGS:0000000000000000
+    [    2.024062] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+    [    2.024161] CR2: ffff888003601000 CR3: 0000000002a2e000 CR4: 00000000000006f0
+    [    2.024275] Call Trace:
+    [    2.024322]  
+    [    2.024367]  ? __warn+0x7f/0x130
+    [    2.024430]  ? refcount_warn_saturate+0xbe/0x110
+    [    2.024513]  ? report_bug+0x199/0x1b0
+    [    2.024585]  ? handle_bug+0x3c/0x70
+    [    2.024676]  ? exc_invalid_op+0x18/0x70
+    [    2.024750]  ? asm_exc_invalid_op+0x1a/0x20
+    [    2.024830]  ? refcount_warn_saturate+0xbe/0x110
+    [    2.024916]  ? refcount_warn_saturate+0xbe/0x110
+    [    2.024998]  __tcp_close+0x2f4/0x3d0
+    [    2.025065]  ? __pfx_kunit_generic_run_threadfn_adapter+0x10/0x10
+    [    2.025168]  tcp_close+0x1f/0x70
+    [    2.025231]  inet_release+0x33/0x60
+    [    2.025297]  sock_release+0x1f/0x80
+    [    2.025361]  handshake_req_cancel_test2+0x100/0x2d0
+    [    2.025457]  kunit_try_run_case+0x4c/0xa0
+    [    2.025532]  kunit_generic_run_threadfn_adapter+0x15/0x20
+    [    2.025644]  kthread+0xe1/0x110
+    [    2.025708]  ? __pfx_kthread+0x10/0x10
+    [    2.025780]  ret_from_fork+0x2c/0x50
+    
+    One can enable CONFIG_NET_HANDSHAKE_KUNIT_TEST config to reproduce above
+    crash.
+    
+    The root cause of this bug is that the commit 1ce77c998f04
+    ("net/handshake: Unpin sock->file if a handshake is cancelled") adds one
+    additional fput() function. That patch claims that the fput() is used to
+    enable sock->file to be freed even when user space never calls DONE.
+    
+    However, it seems that the intended DONE routine will never give an
+    additional fput() of ths sock->file. The existing two of them are just
+    used to balance the reference added in sockfd_lookup().
+    
+    This patch revert the mentioned commit to avoid the use-after-free. The
+    patched kernel could successfully pass the KUNIT test and boot to shell.
+    
+    [    0.733613]     # Subtest: Handshake API tests
+    [    0.734029]     1..11
+    [    0.734255]         KTAP version 1
+    [    0.734542]         # Subtest: req_alloc API fuzzing
+    [    0.736104]         ok 1 handshake_req_alloc NULL proto
+    [    0.736114]         ok 2 handshake_req_alloc CLASS_NONE
+    [    0.736559]         ok 3 handshake_req_alloc CLASS_MAX
+    [    0.737020]         ok 4 handshake_req_alloc no callbacks
+    [    0.737488]         ok 5 handshake_req_alloc no done callback
+    [    0.737988]         ok 6 handshake_req_alloc excessive privsize
+    [    0.738529]         ok 7 handshake_req_alloc all good
+    [    0.739036]     # req_alloc API fuzzing: pass:7 fail:0 skip:0 total:7
+    [    0.739444]     ok 1 req_alloc API fuzzing
+    [    0.740065]     ok 2 req_submit NULL req arg
+    [    0.740436]     ok 3 req_submit NULL sock arg
+    [    0.740834]     ok 4 req_submit NULL sock->file
+    [    0.741236]     ok 5 req_lookup works
+    [    0.741621]     ok 6 req_submit max pending
+    [    0.741974]     ok 7 req_submit multiple
+    [    0.742382]     ok 8 req_cancel before accept
+    [    0.742764]     ok 9 req_cancel after accept
+    [    0.743151]     ok 10 req_cancel after done
+    [    0.743510]     ok 11 req_destroy works
+    [    0.743882] # Handshake API tests: pass:11 fail:0 skip:0 total:11
+    [    0.744205] # Totals: pass:17 fail:0 skip:0 total:17
+    
+    Acked-by: Chuck Lever 
+    Fixes: 1ce77c998f04 ("net/handshake: Unpin sock->file if a handshake is cancelled")
+    Signed-off-by: Lin Ma 
+    Link: https://lore.kernel.org/r/20230613083204.633896-1-linma@zju.edu.cn
+    Link: https://lore.kernel.org/r/20230614015249.987448-1-linma@zju.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/net/handshake/handshake.h b/net/handshake/handshake.h
+index 8aeaadca844f..4dac965c99df 100644
+--- a/net/handshake/handshake.h
++++ b/net/handshake/handshake.h
+@@ -31,7 +31,6 @@ struct handshake_req {
+ 	struct list_head		hr_list;
+ 	struct rhash_head		hr_rhash;
+ 	unsigned long			hr_flags;
+-	struct file			*hr_file;
+ 	const struct handshake_proto	*hr_proto;
+ 	struct sock			*hr_sk;
+ 	void				(*hr_odestruct)(struct sock *sk);
+diff --git a/net/handshake/request.c b/net/handshake/request.c
+index d78d41abb3d9..94d5cef3e048 100644
+--- a/net/handshake/request.c
++++ b/net/handshake/request.c
+@@ -239,7 +239,6 @@ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
+ 	}
+ 	req->hr_odestruct = req->hr_sk->sk_destruct;
+ 	req->hr_sk->sk_destruct = handshake_sk_destruct;
+-	req->hr_file = sock->file;
+ 
+ 	ret = -EOPNOTSUPP;
+ 	net = sock_net(req->hr_sk);
+@@ -335,9 +334,6 @@ bool handshake_req_cancel(struct sock *sk)
+ 		return false;
+ 	}
+ 
+-	/* Request accepted and waiting for DONE */
+-	fput(req->hr_file);
+-
+ out_true:
+ 	trace_handshake_cancel(net, req, sk);
+ 

commit 6f489a966fbeb0da63d45c2c66a8957eab604bf6
+Author: Duoming Zhou 
+Date:   Tue May 23 07:59:32 2023 +0800
+
+    media: usb: siano: Fix warning due to null work_func_t function pointer
+    
+    The previous commit ebad8e731c1c ("media: usb: siano: Fix use after
+    free bugs caused by do_submit_urb") adds cancel_work_sync() in
+    smsusb_stop_streaming(). But smsusb_stop_streaming() may be called,
+    even if the work_struct surb->wq has not been initialized. As a result,
+    the warning will occur. One of the processes that could lead to warning
+    is shown below:
+    
+    smsusb_probe()
+      smsusb_init_device()
+        if (!dev->in_ep || !dev->out_ep || align < 0) {
+             smsusb_term_device(intf);
+               smsusb_stop_streaming()
+                 cancel_work_sync(&dev->surbs[i].wq);
+                   __cancel_work_timer()
+                     __flush_work()
+                       if (WARN_ON(!work->func)) // work->func is null
+    
+    The log reported by syzbot is shown below:
+    
+    WARNING: CPU: 0 PID: 897 at kernel/workqueue.c:3066 __flush_work+0x798/0xa80 kernel/workqueue.c:3063
+    Modules linked in:
+    CPU: 0 PID: 897 Comm: kworker/0:2 Not tainted 6.2.0-rc1-syzkaller #0
+    RIP: 0010:__flush_work+0x798/0xa80 kernel/workqueue.c:3066
+    ...
+    RSP: 0018:ffffc9000464ebf8 EFLAGS: 00010246
+    RAX: 1ffff11002dbb420 RBX: 0000000000000021 RCX: 1ffffffff204fa4e
+    RDX: dffffc0000000000 RSI: 0000000000000001 RDI: ffff888016dda0e8
+    RBP: ffffc9000464ed98 R08: 0000000000000001 R09: ffffffff90253b2f
+    R10: 0000000000000001 R11: 0000000000000000 R12: ffff888016dda0e8
+    R13: ffff888016dda0e8 R14: ffff888016dda100 R15: 0000000000000001
+    FS:  0000000000000000(0000) GS:ffff8880b9a00000(0000) knlGS:0000000000000000
+    CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+    CR2: 00007ffd4331efe8 CR3: 000000000b48e000 CR4: 00000000003506f0
+    DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+    DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+    Call Trace:
+     
+     __cancel_work_timer+0x315/0x460 kernel/workqueue.c:3160
+     smsusb_stop_streaming drivers/media/usb/siano/smsusb.c:182 [inline]
+     smsusb_term_device+0xda/0x2d0 drivers/media/usb/siano/smsusb.c:344
+     smsusb_init_device+0x400/0x9ce drivers/media/usb/siano/smsusb.c:419
+     smsusb_probe+0xbbd/0xc55 drivers/media/usb/siano/smsusb.c:567
+    ...
+    
+    This patch adds check before cancel_work_sync(). If surb->wq has not
+    been initialized, the cancel_work_sync() will not be executed.
+    
+    Reported-by: syzbot+27b0b464864741b18b99@syzkaller.appspotmail.com
+    Fixes: ebad8e731c1c ("media: usb: siano: Fix use after free bugs caused by do_submit_urb")
+    Signed-off-by: Duoming Zhou 
+    Signed-off-by: Hans Verkuil 
+
+diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c
+index 6f443c542c6d..640737d3b8ae 100644
+--- a/drivers/media/usb/siano/smsusb.c
++++ b/drivers/media/usb/siano/smsusb.c
+@@ -179,7 +179,8 @@ static void smsusb_stop_streaming(struct smsusb_device_t *dev)
+ 
+ 	for (i = 0; i < MAX_URBS; i++) {
+ 		usb_kill_urb(&dev->surbs[i].urb);
+-		cancel_work_sync(&dev->surbs[i].wq);
++		if (dev->surbs[i].wq.func)
++			cancel_work_sync(&dev->surbs[i].wq);
+ 
+ 		if (dev->surbs[i].cb) {
+ 			smscore_putbuffer(dev->coredev, dev->surbs[i].cb);

commit 0f5bb36bf9b39a2a96e730bf4455095b50713f63
+Author: Duoming Zhou 
+Date:   Wed Mar 8 12:55:14 2023 +0000
+
+    media: netup_unidvb: fix use-after-free at del_timer()
+    
+    When Universal DVB card is detaching, netup_unidvb_dma_fini()
+    uses del_timer() to stop dma->timeout timer. But when timer
+    handler netup_unidvb_dma_timeout() is running, del_timer()
+    could not stop it. As a result, the use-after-free bug could
+    happen. The process is shown below:
+    
+        (cleanup routine)          |        (timer routine)
+                                   | mod_timer(&dev->tx_sim_timer, ..)
+    netup_unidvb_finidev()         | (wait a time)
+      netup_unidvb_dma_fini()      | netup_unidvb_dma_timeout()
+        del_timer(&dma->timeout);  |
+                                   |   ndev->pci_dev->dev //USE
+    
+    Fix by changing del_timer() to del_timer_sync().
+    
+    Link: https://lore.kernel.org/linux-media/20230308125514.4208-1-duoming@zju.edu.cn
+    Fixes: 52b1eaf4c59a ("[media] netup_unidvb: NetUP Universal DVB-S/S2/T/T2/C PCI-E card driver")
+    Signed-off-by: Duoming Zhou 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
+index 8287851b5ffd..aaa1d2dedebd 100644
+--- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
++++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
+@@ -697,7 +697,7 @@ static void netup_unidvb_dma_fini(struct netup_unidvb_dev *ndev, int num)
+ 	netup_unidvb_dma_enable(dma, 0);
+ 	msleep(50);
+ 	cancel_work_sync(&dma->work);
+-	del_timer(&dma->timeout);
++	del_timer_sync(&dma->timeout);
+ }
+ 
+ static int netup_unidvb_dma_setup(struct netup_unidvb_dev *ndev)

commit dbe836576f12743a7d2d170ad4ad4fd324c4d47a
+Author: Duoming Zhou 
+Date:   Mon May 1 17:37:02 2023 -0700
+
+    Input: cyttsp4_core - change del_timer_sync() to timer_shutdown_sync()
+    
+    The watchdog_timer can schedule tx_timeout_task and watchdog_work
+    can also arm watchdog_timer. The process is shown below:
+    
+    ----------- timer schedules work ------------
+    cyttsp4_watchdog_timer() //timer handler
+      schedule_work(&cd->watchdog_work)
+    
+    ----------- work arms timer ------------
+    cyttsp4_watchdog_work() //workqueue callback function
+      cyttsp4_start_wd_timer()
+        mod_timer(&cd->watchdog_timer, ...)
+    
+    Although del_timer_sync() and cancel_work_sync() are called in
+    cyttsp4_remove(), the timer and workqueue could still be rearmed.
+    As a result, the possible use after free bugs could happen. The
+    process is shown below:
+    
+      (cleanup routine)           |  (timer and workqueue routine)
+    cyttsp4_remove()              | cyttsp4_watchdog_timer() //timer
+      cyttsp4_stop_wd_timer()     |   schedule_work()
+        del_timer_sync()          |
+                                  | cyttsp4_watchdog_work() //worker
+                                  |   cyttsp4_start_wd_timer()
+                                  |     mod_timer()
+        cancel_work_sync()        |
+                                  | cyttsp4_watchdog_timer() //timer
+                                  |   schedule_work()
+        del_timer_sync()          |
+      kfree(cd) //FREE            |
+                                  | cyttsp4_watchdog_work() // reschedule!
+                                  |   cd-> //USE
+    
+    This patch changes del_timer_sync() to timer_shutdown_sync(),
+    which could prevent rearming of the timer from the workqueue.
+    
+    Fixes: 17fb1563d69b ("Input: cyttsp4 - add core driver for Cypress TMA4XX touchscreen devices")
+    Signed-off-by: Duoming Zhou 
+    Link: https://lore.kernel.org/r/20230421082919.8471-1-duoming@zju.edu.cn
+    Signed-off-by: Dmitry Torokhov 
+
+diff --git a/drivers/input/touchscreen/cyttsp4_core.c b/drivers/input/touchscreen/cyttsp4_core.c
+index 0cd6f626adec..7cb26929dc73 100644
+--- a/drivers/input/touchscreen/cyttsp4_core.c
++++ b/drivers/input/touchscreen/cyttsp4_core.c
+@@ -1263,9 +1263,8 @@ static void cyttsp4_stop_wd_timer(struct cyttsp4 *cd)
+ 	 * Ensure we wait until the watchdog timer
+ 	 * running on a different CPU finishes
+ 	 */
+-	del_timer_sync(&cd->watchdog_timer);
++	timer_shutdown_sync(&cd->watchdog_timer);
+ 	cancel_work_sync(&cd->watchdog_work);
+-	del_timer_sync(&cd->watchdog_timer);
+ }
+ 
+ static void cyttsp4_watchdog_timer(struct timer_list *t)

commit e50b9b9e8610d47b7c22529443e45a16b1ea3a15
+Author: Duoming Zhou 
+Date:   Sat Apr 15 16:12:27 2023 +0800
+
+    cxgb4: fix use after free bugs caused by circular dependency problem
+    
+    The flower_stats_timer can schedule flower_stats_work and
+    flower_stats_work can also arm the flower_stats_timer. The
+    process is shown below:
+    
+    ----------- timer schedules work ------------
+    ch_flower_stats_cb() //timer handler
+      schedule_work(&adap->flower_stats_work);
+    
+    ----------- work arms timer ------------
+    ch_flower_stats_handler() //workqueue callback function
+      mod_timer(&adap->flower_stats_timer, ...);
+    
+    When the cxgb4 device is detaching, the timer and workqueue
+    could still be rearmed. The process is shown below:
+    
+      (cleanup routine)           | (timer and workqueue routine)
+    remove_one()                  |
+      free_some_resources()       | ch_flower_stats_cb() //timer
+        cxgb4_cleanup_tc_flower() |   schedule_work()
+          del_timer_sync()        |
+                                  | ch_flower_stats_handler() //workqueue
+                                  |   mod_timer()
+          cancel_work_sync()      |
+      kfree(adapter) //FREE       | ch_flower_stats_cb() //timer
+                                  |   adap->flower_stats_work //USE
+    
+    This patch changes del_timer_sync() to timer_shutdown_sync(),
+    which could prevent rearming of the timer from the workqueue.
+    
+    Fixes: e0f911c81e93 ("cxgb4: fetch stats for offloaded tc flower flows")
+    Signed-off-by: Duoming Zhou 
+    Link: https://lore.kernel.org/r/20230415081227.7463-1-duoming@zju.edu.cn
+    Signed-off-by: Paolo Abeni 
+
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
+index dd9be229819a..d3541159487d 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
++++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
+@@ -1135,7 +1135,7 @@ void cxgb4_cleanup_tc_flower(struct adapter *adap)
+ 		return;
+ 
+ 	if (adap->flower_stats_timer.function)
+-		del_timer_sync(&adap->flower_stats_timer);
++		timer_shutdown_sync(&adap->flower_stats_timer);
+ 	cancel_work_sync(&adap->flower_stats_work);
+ 	rhashtable_destroy(&adap->flower_tbl);
+ 	adap->tc_flower_initialized = false;

commit 65f69851e44d71248b952a687e44759a7abb5016
+Author: Lin Ma 
+Date:   Tue Mar 7 23:29:17 2023 +0800
+
+    igb: revert rtnl_lock() that causes deadlock
+    
+    The commit 6faee3d4ee8b ("igb: Add lock to avoid data race") adds
+    rtnl_lock to eliminate a false data race shown below
+    
+     (FREE from device detaching)      |   (USE from netdev core)
+    igb_remove                         |  igb_ndo_get_vf_config
+     igb_disable_sriov                 |  vf >= adapter->vfs_allocated_count?
+      kfree(adapter->vf_data)          |
+      adapter->vfs_allocated_count = 0 |
+                                       |    memcpy(... adapter->vf_data[vf]
+    
+    The above race will never happen and the extra rtnl_lock causes deadlock
+    below
+    
+    [  141.420169]  
+    [  141.420672]  __schedule+0x2dd/0x840
+    [  141.421427]  schedule+0x50/0xc0
+    [  141.422041]  schedule_preempt_disabled+0x11/0x20
+    [  141.422678]  __mutex_lock.isra.13+0x431/0x6b0
+    [  141.423324]  unregister_netdev+0xe/0x20
+    [  141.423578]  igbvf_remove+0x45/0xe0 [igbvf]
+    [  141.423791]  pci_device_remove+0x36/0xb0
+    [  141.423990]  device_release_driver_internal+0xc1/0x160
+    [  141.424270]  pci_stop_bus_device+0x6d/0x90
+    [  141.424507]  pci_stop_and_remove_bus_device+0xe/0x20
+    [  141.424789]  pci_iov_remove_virtfn+0xba/0x120
+    [  141.425452]  sriov_disable+0x2f/0xf0
+    [  141.425679]  igb_disable_sriov+0x4e/0x100 [igb]
+    [  141.426353]  igb_remove+0xa0/0x130 [igb]
+    [  141.426599]  pci_device_remove+0x36/0xb0
+    [  141.426796]  device_release_driver_internal+0xc1/0x160
+    [  141.427060]  driver_detach+0x44/0x90
+    [  141.427253]  bus_remove_driver+0x55/0xe0
+    [  141.427477]  pci_unregister_driver+0x2a/0xa0
+    [  141.428296]  __x64_sys_delete_module+0x141/0x2b0
+    [  141.429126]  ? mntput_no_expire+0x4a/0x240
+    [  141.429363]  ? syscall_trace_enter.isra.19+0x126/0x1a0
+    [  141.429653]  do_syscall_64+0x5b/0x80
+    [  141.429847]  ? exit_to_user_mode_prepare+0x14d/0x1c0
+    [  141.430109]  ? syscall_exit_to_user_mode+0x12/0x30
+    [  141.430849]  ? do_syscall_64+0x67/0x80
+    [  141.431083]  ? syscall_exit_to_user_mode_prepare+0x183/0x1b0
+    [  141.431770]  ? syscall_exit_to_user_mode+0x12/0x30
+    [  141.432482]  ? do_syscall_64+0x67/0x80
+    [  141.432714]  ? exc_page_fault+0x64/0x140
+    [  141.432911]  entry_SYSCALL_64_after_hwframe+0x72/0xdc
+    
+    Since the igb_disable_sriov() will call pci_disable_sriov() before
+    releasing any resources, the netdev core will synchronize the cleanup to
+    avoid any races. This patch removes the useless rtnl_(un)lock to guarantee
+    correctness.
+    
+    CC: stable@vger.kernel.org
+    Fixes: 6faee3d4ee8b ("igb: Add lock to avoid data race")
+    Reported-by: Corinna Vinschen 
+    Link: https://lore.kernel.org/intel-wired-lan/ZAcJvkEPqWeJHO2r@calimero.vinschen.de/
+    Signed-off-by: Lin Ma 
+    Tested-by: Corinna Vinschen 
+    Reviewed-by: Jacob Keller 
+    Reviewed-by: Simon Horman 
+    Tested-by: Rafal Romanowski 
+    Signed-off-by: Tony Nguyen 
+
+diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
+index 03bc1e8af575..5532361b0e94 100644
+--- a/drivers/net/ethernet/intel/igb/igb_main.c
++++ b/drivers/net/ethernet/intel/igb/igb_main.c
+@@ -3863,9 +3863,7 @@ static void igb_remove(struct pci_dev *pdev)
+ 	igb_release_hw_control(adapter);
+ 
+ #ifdef CONFIG_PCI_IOV
+-	rtnl_lock();
+ 	igb_disable_sriov(pdev);
+-	rtnl_unlock();
+ #endif
+ 
+ 	unregister_netdev(netdev);

commit ebad8e731c1c06adf04621d6fd327b860c0861b5
+Author: Duoming Zhou 
+Date:   Mon Jan 23 03:04:38 2023 +0100
+
+    media: usb: siano: Fix use after free bugs caused by do_submit_urb
+    
+    There are UAF bugs caused by do_submit_urb(). One of the KASan reports
+    is shown below:
+    
+    [   36.403605] BUG: KASAN: use-after-free in worker_thread+0x4a2/0x890
+    [   36.406105] Read of size 8 at addr ffff8880059600e8 by task kworker/0:2/49
+    [   36.408316]
+    [   36.408867] CPU: 0 PID: 49 Comm: kworker/0:2 Not tainted 6.2.0-rc3-15798-g5a41237ad1d4-dir8
+    [   36.411696] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g15584
+    [   36.416157] Workqueue:  0x0 (events)
+    [   36.417654] Call Trace:
+    [   36.418546]  
+    [   36.419320]  dump_stack_lvl+0x96/0xd0
+    [   36.420522]  print_address_description+0x75/0x350
+    [   36.421992]  print_report+0x11b/0x250
+    [   36.423174]  ? _raw_spin_lock_irqsave+0x87/0xd0
+    [   36.424806]  ? __virt_addr_valid+0xcf/0x170
+    [   36.426069]  ? worker_thread+0x4a2/0x890
+    [   36.427355]  kasan_report+0x131/0x160
+    [   36.428556]  ? worker_thread+0x4a2/0x890
+    [   36.430053]  worker_thread+0x4a2/0x890
+    [   36.431297]  ? worker_clr_flags+0x90/0x90
+    [   36.432479]  kthread+0x166/0x190
+    [   36.433493]  ? kthread_blkcg+0x50/0x50
+    [   36.434669]  ret_from_fork+0x22/0x30
+    [   36.435923]  
+    [   36.436684]
+    [   36.437215] Allocated by task 24:
+    [   36.438289]  kasan_set_track+0x50/0x80
+    [   36.439436]  __kasan_kmalloc+0x89/0xa0
+    [   36.440566]  smsusb_probe+0x374/0xc90
+    [   36.441920]  usb_probe_interface+0x2d1/0x4c0
+    [   36.443253]  really_probe+0x1d5/0x580
+    [   36.444539]  __driver_probe_device+0xe3/0x130
+    [   36.446085]  driver_probe_device+0x49/0x220
+    [   36.447423]  __device_attach_driver+0x19e/0x1b0
+    [   36.448931]  bus_for_each_drv+0xcb/0x110
+    [   36.450217]  __device_attach+0x132/0x1f0
+    [   36.451470]  bus_probe_device+0x59/0xf0
+    [   36.452563]  device_add+0x4ec/0x7b0
+    [   36.453830]  usb_set_configuration+0xc63/0xe10
+    [   36.455230]  usb_generic_driver_probe+0x3b/0x80
+    [   36.456166] printk: console [ttyGS0] disabled
+    [   36.456569]  usb_probe_device+0x90/0x110
+    [   36.459523]  really_probe+0x1d5/0x580
+    [   36.461027]  __driver_probe_device+0xe3/0x130
+    [   36.462465]  driver_probe_device+0x49/0x220
+    [   36.463847]  __device_attach_driver+0x19e/0x1b0
+    [   36.465229]  bus_for_each_drv+0xcb/0x110
+    [   36.466466]  __device_attach+0x132/0x1f0
+    [   36.467799]  bus_probe_device+0x59/0xf0
+    [   36.469010]  device_add+0x4ec/0x7b0
+    [   36.470125]  usb_new_device+0x863/0xa00
+    [   36.471374]  hub_event+0x18c7/0x2220
+    [   36.472746]  process_one_work+0x34c/0x5b0
+    [   36.474041]  worker_thread+0x4b7/0x890
+    [   36.475216]  kthread+0x166/0x190
+    [   36.476267]  ret_from_fork+0x22/0x30
+    [   36.477447]
+    [   36.478160] Freed by task 24:
+    [   36.479239]  kasan_set_track+0x50/0x80
+    [   36.480512]  kasan_save_free_info+0x2b/0x40
+    [   36.481808]  ____kasan_slab_free+0x122/0x1a0
+    [   36.483173]  __kmem_cache_free+0xc4/0x200
+    [   36.484563]  smsusb_term_device+0xcd/0xf0
+    [   36.485896]  smsusb_probe+0xc85/0xc90
+    [   36.486976]  usb_probe_interface+0x2d1/0x4c0
+    [   36.488303]  really_probe+0x1d5/0x580
+    [   36.489498]  __driver_probe_device+0xe3/0x130
+    [   36.491140]  driver_probe_device+0x49/0x220
+    [   36.492475]  __device_attach_driver+0x19e/0x1b0
+    [   36.493988]  bus_for_each_drv+0xcb/0x110
+    [   36.495171]  __device_attach+0x132/0x1f0
+    [   36.496617]  bus_probe_device+0x59/0xf0
+    [   36.497875]  device_add+0x4ec/0x7b0
+    [   36.498972]  usb_set_configuration+0xc63/0xe10
+    [   36.500264]  usb_generic_driver_probe+0x3b/0x80
+    [   36.501740]  usb_probe_device+0x90/0x110
+    [   36.503084]  really_probe+0x1d5/0x580
+    [   36.504241]  __driver_probe_device+0xe3/0x130
+    [   36.505548]  driver_probe_device+0x49/0x220
+    [   36.506766]  __device_attach_driver+0x19e/0x1b0
+    [   36.508368]  bus_for_each_drv+0xcb/0x110
+    [   36.509646]  __device_attach+0x132/0x1f0
+    [   36.510911]  bus_probe_device+0x59/0xf0
+    [   36.512103]  device_add+0x4ec/0x7b0
+    [   36.513215]  usb_new_device+0x863/0xa00
+    [   36.514736]  hub_event+0x18c7/0x2220
+    [   36.516130]  process_one_work+0x34c/0x5b0
+    [   36.517396]  worker_thread+0x4b7/0x890
+    [   36.518591]  kthread+0x166/0x190
+    [   36.519599]  ret_from_fork+0x22/0x30
+    [   36.520851]
+    [   36.521405] Last potentially related work creation:
+    [   36.523143]  kasan_save_stack+0x3f/0x60
+    [   36.524275]  kasan_record_aux_stack_noalloc+0x9d/0xb0
+    [   36.525831]  insert_work+0x25/0x130
+    [   36.527039]  __queue_work+0x4d4/0x620
+    [   36.528236]  queue_work_on+0x72/0xb0
+    [   36.529344]  __usb_hcd_giveback_urb+0x13f/0x1b0
+    [   36.530819]  dummy_timer+0x350/0x1a40
+    [   36.532149]  call_timer_fn+0x2c/0x190
+    [   36.533567]  expire_timers+0x69/0x1f0
+    [   36.534736]  __run_timers+0x289/0x2d0
+    [   36.535841]  run_timer_softirq+0x2d/0x60
+    [   36.537110]  __do_softirq+0x116/0x380
+    [   36.538377]
+    [   36.538950] Second to last potentially related work creation:
+    [   36.540855]  kasan_save_stack+0x3f/0x60
+    [   36.542084]  kasan_record_aux_stack_noalloc+0x9d/0xb0
+    [   36.543592]  insert_work+0x25/0x130
+    [   36.544891]  __queue_work+0x4d4/0x620
+    [   36.546168]  queue_work_on+0x72/0xb0
+    [   36.547328]  __usb_hcd_giveback_urb+0x13f/0x1b0
+    [   36.548805]  dummy_timer+0x350/0x1a40
+    [   36.550116]  call_timer_fn+0x2c/0x190
+    [   36.551570]  expire_timers+0x69/0x1f0
+    [   36.552762]  __run_timers+0x289/0x2d0
+    [   36.553916]  run_timer_softirq+0x2d/0x60
+    [   36.555118]  __do_softirq+0x116/0x380
+    [   36.556239]
+    [   36.556807] The buggy address belongs to the object at ffff888005960000
+    [   36.556807]  which belongs to the cache kmalloc-4k of size 4096
+    [   36.560652] The buggy address is located 232 bytes inside of
+    [   36.560652]  4096-byte region [ffff888005960000, ffff888005961000)
+    [   36.564791]
+    [   36.565355] The buggy address belongs to the physical page:
+    [   36.567212] page:000000004f0a0731 refcount:1 mapcount:0 mapping:0000000000000000 index:0x00
+    [   36.570534] head:000000004f0a0731 order:3 compound_mapcount:0 subpages_mapcount:0 compound0
+    [   36.573717] flags: 0x100000000010200(slab|head|node=0|zone=1)
+    [   36.575481] raw: 0100000000010200 ffff888001042140 dead000000000122 0000000000000000
+    [   36.577842] raw: 0000000000000000 0000000000040004 00000001ffffffff 0000000000000000
+    [   36.580175] page dumped because: kasan: bad access detected
+    [   36.581994]
+    [   36.582548] Memory state around the buggy address:
+    [   36.583983]  ffff88800595ff80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
+    [   36.586240]  ffff888005960000: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+    [   36.588884] >ffff888005960080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+    [   36.591071]                                                           ^
+    [   36.593295]  ffff888005960100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+    [   36.595705]  ffff888005960180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+    [   36.598026] ==================================================================
+    [   36.600224] Disabling lock debugging due to kernel taint
+    [   36.602681] general protection fault, probably for non-canonical address 0x43600a000000060I
+    [   36.607129] CPU: 0 PID: 49 Comm: kworker/0:2 Tainted: G    B              6.2.0-rc3-15798-8
+    [   36.611115] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g15584
+    [   36.615026] Workqueue: events do_submit_urb
+    [   36.616290] RIP: 0010:_raw_spin_lock_irqsave+0x8a/0xd0
+    [   36.618107] Code: 24 00 00 00 00 48 89 df be 04 00 00 00 e8 9e b5 c6 fe 48 89 ef be 04 00 5
+    [   36.623522] RSP: 0018:ffff888004b6fcf0 EFLAGS: 00010046
+    [   36.625072] RAX: 0000000000000000 RBX: 043600a000000060 RCX: ffffffff9fc0e0d7
+    [   36.627206] RDX: 0000000000000000 RSI: dffffc0000000000 RDI: ffff888004b6fcf0
+    [   36.629813] RBP: ffff888004b6fcf0 R08: dffffc0000000000 R09: ffffed100096df9f
+    [   36.631974] R10: dfffe9100096dfa0 R11: 1ffff1100096df9e R12: ffff888005960020
+    [   36.634285] R13: ffff8880059600f0 R14: 0000000000000246 R15: 0000000000000001
+    [   36.636438] FS:  0000000000000000(0000) GS:ffff88806d600000(0000) knlGS:0000000000000000
+    [   36.639092] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+    [   36.640951] CR2: 00007f07476819a3 CR3: 0000000004a34000 CR4: 00000000000006f0
+    [   36.643411] Call Trace:
+    [   36.644215]  
+    [   36.644902]  smscore_getbuffer+0x3e/0x1e0
+    [   36.646147]  do_submit_urb+0x4f/0x190
+    [   36.647449]  process_one_work+0x34c/0x5b0
+    [   36.648777]  worker_thread+0x4b7/0x890
+    [   36.649984]  ? worker_clr_flags+0x90/0x90
+    [   36.651166]  kthread+0x166/0x190
+    [   36.652151]  ? kthread_blkcg+0x50/0x50
+    [   36.653547]  ret_from_fork+0x22/0x30
+    [   36.655051]  
+    [   36.655733] Modules linked in:
+    [   36.656787] ---[ end trace 0000000000000000 ]---
+    [   36.658328] RIP: 0010:_raw_spin_lock_irqsave+0x8a/0xd0
+    [   36.660045] Code: 24 00 00 00 00 48 89 df be 04 00 00 00 e8 9e b5 c6 fe 48 89 ef be 04 00 5
+    [   36.665730] RSP: 0018:ffff888004b6fcf0 EFLAGS: 00010046
+    [   36.667448] RAX: 0000000000000000 RBX: 043600a000000060 RCX: ffffffff9fc0e0d7
+    [   36.669675] RDX: 0000000000000000 RSI: dffffc0000000000 RDI: ffff888004b6fcf0
+    [   36.672645] RBP: ffff888004b6fcf0 R08: dffffc0000000000 R09: ffffed100096df9f
+    [   36.674921] R10: dfffe9100096dfa0 R11: 1ffff1100096df9e R12: ffff888005960020
+    [   36.677034] R13: ffff8880059600f0 R14: 0000000000000246 R15: 0000000000000001
+    [   36.679184] FS:  0000000000000000(0000) GS:ffff88806d600000(0000) knlGS:0000000000000000
+    [   36.681655] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+    [   36.683383] CR2: 00007f07476819a3 CR3: 0000000004a34000 CR4: 00000000000006f0
+    [   36.685733] Kernel panic - not syncing: Fatal exception
+    [   36.688585] Kernel Offset: 0x1d400000 from 0xffffffff81000000 (relocation range: 0xfffffff)
+    [   36.692199] ---[ end Kernel panic - not syncing: Fatal exception ]---
+    
+    When the siano device is plugged in, it may call the following functions
+    to initialize the device.
+    
+    smsusb_probe()-->smsusb_init_device()-->smscore_start_device().
+    
+    When smscore_start_device() gets failed, the function smsusb_term_device()
+    will be called and smsusb_device_t will be deallocated. Although we use
+    usb_kill_urb() in smsusb_stop_streaming() to cancel transfer requests
+    and wait for them to finish, the worker threads that are scheduled by
+    smsusb_onresponse() may be still running. As a result, the UAF bugs
+    could happen.
+    
+    We add cancel_work_sync() in smsusb_stop_streaming() in order that the
+    worker threads could finish before the smsusb_device_t is deallocated.
+    
+    Fixes: dd47fbd40e6e ("[media] smsusb: don't sleep while atomic")
+    Signed-off-by: Duoming Zhou 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c
+index fe9c7b3a950e..6f443c542c6d 100644
+--- a/drivers/media/usb/siano/smsusb.c
++++ b/drivers/media/usb/siano/smsusb.c
+@@ -179,6 +179,7 @@ static void smsusb_stop_streaming(struct smsusb_device_t *dev)
+ 
+ 	for (i = 0; i < MAX_URBS; i++) {
+ 		usb_kill_urb(&dev->surbs[i].urb);
++		cancel_work_sync(&dev->surbs[i].wq);
+ 
+ 		if (dev->surbs[i].cb) {
+ 			smscore_putbuffer(dev->coredev, dev->surbs[i].cb);

commit 29b0589a865b6f66d141d79b2dd1373e4e50fe17
+Author: Duoming Zhou 
+Date:   Tue Jan 24 08:55:33 2023 +0100
+
+    media: rc: Fix use-after-free bugs caused by ene_tx_irqsim()
+    
+    When the ene device is detaching, function ene_remove() will
+    be called. But there is no function to cancel tx_sim_timer
+    in ene_remove(), the timer handler ene_tx_irqsim() could race
+    with ene_remove(). As a result, the UAF bugs could happen,
+    the process is shown below.
+    
+        (cleanup routine)          |        (timer routine)
+                                   | mod_timer(&dev->tx_sim_timer, ..)
+    ene_remove()                   | (wait a time)
+                                   | ene_tx_irqsim()
+                                   |   dev->hw_lock //USE
+                                   |   ene_tx_sample(dev) //USE
+    
+    Fix by adding del_timer_sync(&dev->tx_sim_timer) in ene_remove(),
+    The tx_sim_timer could stop before ene device is deallocated.
+    
+    What's more, The rc_unregister_device() and del_timer_sync()
+    should be called first in ene_remove() and the deallocated
+    functions such as free_irq(), release_region() and so on
+    should be called behind them. Because the rc_unregister_device()
+    is well synchronized. Otherwise, race conditions may happen. The
+    situations that may lead to race conditions are shown below.
+    
+    Firstly, the rx receiver is disabled with ene_rx_disable()
+    before rc_unregister_device() in ene_remove(), which means it
+    can be enabled again if a process opens /dev/lirc0 between
+    ene_rx_disable() and rc_unregister_device().
+    
+    Secondly, the irqaction descriptor is freed by free_irq()
+    before the rc device is unregistered, which means irqaction
+    descriptor may be accessed again after it is deallocated.
+    
+    Thirdly, the timer can call ene_tx_sample() that can write
+    to the io ports, which means the io ports could be accessed
+    again after they are deallocated by release_region().
+    
+    Therefore, the rc_unregister_device() and del_timer_sync()
+    should be called first in ene_remove().
+    
+    Suggested by: Sean Young 
+    
+    Fixes: 9ea53b74df9c ("V4L/DVB: STAGING: remove lirc_ene0100 driver")
+    Signed-off-by: Duoming Zhou 
+    Signed-off-by: Sean Young 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c
+index e09270916fbc..11ee21a7db8f 100644
+--- a/drivers/media/rc/ene_ir.c
++++ b/drivers/media/rc/ene_ir.c
+@@ -1106,6 +1106,8 @@ static void ene_remove(struct pnp_dev *pnp_dev)
+ 	struct ene_device *dev = pnp_get_drvdata(pnp_dev);
+ 	unsigned long flags;
+ 
++	rc_unregister_device(dev->rdev);
++	del_timer_sync(&dev->tx_sim_timer);
+ 	spin_lock_irqsave(&dev->hw_lock, flags);
+ 	ene_rx_disable(dev);
+ 	ene_rx_restore_hw_buffer(dev);
+@@ -1113,7 +1115,6 @@ static void ene_remove(struct pnp_dev *pnp_dev)
+ 
+ 	free_irq(dev->irq, dev);
+ 	release_region(dev->hw_io, ENE_IO_SIZE);
+-	rc_unregister_device(dev->rdev);
+ 	kfree(dev);
+ }
+ 

commit 70fae37a09268455b8ab4f64647086b61da6f39c
+Author: Duoming Zhou 
+Date:   Wed Jan 18 22:10:00 2023 +0800
+
+    Revert "char: pcmcia: cm4000_cs: Replace mdelay with usleep_range in set_protocol"
+    
+    This reverts commit be826ada52f1fcabed5b5217c94609ebf5967211.
+    
+    The function monitor_card() is a timer handler that runs in an
+    atomic context, but it calls usleep_range() that can sleep.
+    As a result, the sleep-in-atomic-context bugs will happen.
+    The process is shown below:
+    
+        (atomic context)
+    monitor_card()
+      set_protocol()
+        usleep_range() //sleep
+    
+    The origin commit c1986ee9bea3 ("[PATCH] New Omnikey Cardman
+    4000 driver") works fine.
+    
+    Fixes: be826ada52f1 ("char: pcmcia: cm4000_cs: Replace mdelay with usleep_range in set_protocol")
+    Signed-off-by: Duoming Zhou 
+    Link: https://lore.kernel.org/r/20230118141000.5580-1-duoming@zju.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
+index adaec8fd4b16..e656f42a28ac 100644
+--- a/drivers/char/pcmcia/cm4000_cs.c
++++ b/drivers/char/pcmcia/cm4000_cs.c
+@@ -529,7 +529,8 @@ static int set_protocol(struct cm4000_dev *dev, struct ptsreq *ptsreq)
+ 			DEBUGP(5, dev, "NumRecBytes is valid\n");
+ 			break;
+ 		}
+-		usleep_range(10000, 11000);
++		/* can not sleep as this is in atomic context */
++		mdelay(10);
+ 	}
+ 	if (i == 100) {
+ 		DEBUGP(5, dev, "Timeout waiting for NumRecBytes getting "
+@@ -549,7 +550,8 @@ static int set_protocol(struct cm4000_dev *dev, struct ptsreq *ptsreq)
+ 			}
+ 			break;
+ 		}
+-		usleep_range(10000, 11000);
++		/* can not sleep as this is in atomic context */
++		mdelay(10);
+ 	}
+ 
+ 	/* check whether it is a short PTS reply? */

commit 3a664569b71b0a52be5ffb9fb87cc4f83d29bd71
+Author: Lin Ma 
+Date:   Mon Nov 28 16:21:59 2022 +0000
+
+    media: dvbdev: fix refcnt bug
+    
+    Previous commit initialize the dvbdev->ref before the template copy,
+    which will overwrite the reference and cause refcnt bug.
+    
+    refcount_t: addition on 0; use-after-free.
+    WARNING: CPU: 0 PID: 1 at lib/refcount.c:25 refcount_warn_saturate+0x17c/0x1f0 lib/refcount.c:25
+    Modules linked in:
+    CPU: 0 PID: 1 Comm: swapper/0 Not tainted 6.1.0-rc6-next-20221128-syzkaller #0
+    ...
+    RIP: 0010:refcount_warn_saturate+0x17c/0x1f0 lib/refcount.c:25
+    RSP: 0000:ffffc900000678d0 EFLAGS: 00010282
+    RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
+    RDX: ffff88813ff58000 RSI: ffffffff81660e7c RDI: fffff5200000cf0c
+    RBP: ffff888022a45010 R08: 0000000000000005 R09: 0000000000000000
+    R10: 0000000080000000 R11: 0000000000000000 R12: 0000000000000001
+    R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000001
+    FS:  0000000000000000(0000) GS:ffff8880b9800000(0000) knlGS:0000000000000000
+    CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+    CR2: ffff88823ffff000 CR3: 000000000c48e000 CR4: 00000000003506f0
+    DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+    DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+    Call Trace:
+     
+     __refcount_add include/linux/refcount.h:199 [inline]
+     __refcount_inc include/linux/refcount.h:250 [inline]
+     refcount_inc include/linux/refcount.h:267 [inline]
+     kref_get include/linux/kref.h:45 [inline]
+     dvb_device_get drivers/media/dvb-core/dvbdev.c:585 [inline]
+     dvb_register_device+0xe83/0x16e0 drivers/media/dvb-core/dvbdev.c:517
+    ...
+    
+    Just place the kref_init at correct position.
+    
+    Reported-by: syzbot+fce48a3dd3368645bd6c@syzkaller.appspotmail.com
+    Fixes: 0fc044b2b5e2 ("media: dvbdev: adopts refcnt to avoid UAF")
+    Signed-off-by: Lin Ma 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c
+index d45673cb3ce1..2a857cf70c94 100644
+--- a/drivers/media/dvb-core/dvbdev.c
++++ b/drivers/media/dvb-core/dvbdev.c
+@@ -482,8 +482,8 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
+ 		return -ENOMEM;
+ 	}
+ 
+-	kref_init(&dvbdev->ref);
+ 	memcpy(dvbdev, template, sizeof(struct dvb_device));
++	kref_init(&dvbdev->ref);
+ 	dvbdev->type = type;
+ 	dvbdev->id = id;
+ 	dvbdev->adapter = adap;

commit 3edfd14bb50fa6f94ed1a37bbb17d9f1c2793b57
+Author: Lin Ma 
+Date:   Mon Nov 28 08:39:03 2022 +0000
+
+    media: dvbdev: fix build warning due to comments
+    
+    Previous commit that introduces reference counter does not add proper
+    comments, which will lead to warning when building htmldocs. Fix them.
+    
+    Reported-by: "Stephen Rothwell" 
+    Fixes: 0fc044b2b5e2 ("media: dvbdev: adopts refcnt to avoid UAF")
+    Signed-off-by: Lin Ma 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/include/media/dvbdev.h b/include/media/dvbdev.h
+index fad9871157e2..29d25c8a6f13 100644
+--- a/include/media/dvbdev.h
++++ b/include/media/dvbdev.h
+@@ -130,6 +130,7 @@ struct dvb_adapter {
+  * struct dvb_device - represents a DVB device node
+  *
+  * @list_head:	List head with all DVB devices
++ * @ref:	reference counter
+  * @fops:	pointer to struct file_operations
+  * @adapter:	pointer to the adapter that holds this device node
+  * @type:	type of the device, as defined by &enum dvb_device_type.
+@@ -200,7 +201,7 @@ struct dvb_device {
+ struct dvb_device *dvb_device_get(struct dvb_device *dvbdev);
+ 
+ /**
+- * dvb_device_get - Decrease dvb_device reference
++ * dvb_device_put - Decrease dvb_device reference
+  *
+  * @dvbdev:	pointer to struct dvb_device
+  */

commit 8d283ee62b077968e218531b24260e1cc51bd484
+Author: Jinlong Chen 
+Date:   Tue Nov 29 23:46:38 2022 +0800
+
+    block: use bool as the return type of elv_iosched_allow_bio_merge
+    
+    We have bool type now, update the old signature.
+    
+    Signed-off-by: Jinlong Chen 
+    Reviewed-by: Christoph Hellwig 
+    Link: https://lore.kernel.org/r/0db0a0298758d60d0f4df8b7126ac6a381e5a5bb.1669736350.git.nickyc975@zju.edu.cn
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/elevator.c b/block/elevator.c
+index 8a5c171306f1..14e03632b5b5 100644
+--- a/block/elevator.c
++++ b/block/elevator.c
+@@ -57,7 +57,7 @@ static LIST_HEAD(elv_list);
+  * Query io scheduler to see if the current process issuing bio may be
+  * merged with rq.
+  */
+-static int elv_iosched_allow_bio_merge(struct request *rq, struct bio *bio)
++static bool elv_iosched_allow_bio_merge(struct request *rq, struct bio *bio)
+ {
+ 	struct request_queue *q = rq->q;
+ 	struct elevator_queue *e = q->elevator;
+@@ -65,7 +65,7 @@ static int elv_iosched_allow_bio_merge(struct request *rq, struct bio *bio)
+ 	if (e->type->ops.allow_merge)
+ 		return e->type->ops.allow_merge(q, rq, bio);
+ 
+-	return 1;
++	return true;
+ }
+ 
+ /*

commit c6451ede406b9f57fcd61d48433a6b8b2be862e3
+Author: Jinlong Chen 
+Date:   Tue Nov 29 23:46:37 2022 +0800
+
+    block: replace "len+name" with "name+len" in elv_iosched_show
+    
+    The "pointer + offset" pattern is more resonable.
+    
+    Signed-off-by: Jinlong Chen 
+    Reviewed-by: Christoph Hellwig 
+    Link: https://lore.kernel.org/r/d9beaee71b14f7b2a39ab0db6458dc0f7d961ceb.1669736350.git.nickyc975@zju.edu.cn
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/elevator.c b/block/elevator.c
+index b2f2252f29e7..8a5c171306f1 100644
+--- a/block/elevator.c
++++ b/block/elevator.c
+@@ -783,7 +783,7 @@ ssize_t elv_iosched_show(struct request_queue *q, char *name)
+ 	}
+ 	spin_unlock(&elv_list_lock);
+ 
+-	len += sprintf(len+name, "\n");
++	len += sprintf(name+len, "\n");
+ 	return len;
+ }
+ 

commit 7a3b3660fd30c028e7ae1cd82697933789962406
+Author: Jinlong Chen 
+Date:   Tue Nov 29 23:46:36 2022 +0800
+
+    block: always use 'e' when printing scheduler name
+    
+    Printing e->elevator_name in all cases improves the readability, and
+    'e' and 'cur' are identical in this branch.
+    
+    Suggested-by: Christoph Hellwig 
+    Signed-off-by: Jinlong Chen 
+    Link: https://lore.kernel.org/r/4bae180ffbac608ea0cf46ffa9739ce0973b60aa.1669736350.git.nickyc975@zju.edu.cn
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/elevator.c b/block/elevator.c
+index ffa750976d25..b2f2252f29e7 100644
+--- a/block/elevator.c
++++ b/block/elevator.c
+@@ -777,7 +777,7 @@ ssize_t elv_iosched_show(struct request_queue *q, char *name)
+ 	spin_lock(&elv_list_lock);
+ 	list_for_each_entry(e, &elv_list, list) {
+ 		if (e == cur)
+-			len += sprintf(name+len, "[%s] ", cur->elevator_name);
++			len += sprintf(name+len, "[%s] ", e->elevator_name);
+ 		else if (elv_support_features(q, e))
+ 			len += sprintf(name+len, "%s ", e->elevator_name);
+ 	}

commit 5998249e3238428156b09911f1606b41113443c5
+Author: Jinlong Chen 
+Date:   Tue Nov 29 23:46:35 2022 +0800
+
+    block: replace continue with else-if in elv_iosched_show
+    
+    else-if is more readable than continue here.
+    
+    Signed-off-by: Jinlong Chen 
+    Link: https://lore.kernel.org/r/77ac19ba556efd2c8639a6396eb4203c59bc13d6.1669736350.git.nickyc975@zju.edu.cn
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/elevator.c b/block/elevator.c
+index 308bee253564..ffa750976d25 100644
+--- a/block/elevator.c
++++ b/block/elevator.c
+@@ -776,11 +776,9 @@ ssize_t elv_iosched_show(struct request_queue *q, char *name)
+ 
+ 	spin_lock(&elv_list_lock);
+ 	list_for_each_entry(e, &elv_list, list) {
+-		if (e == cur) {
++		if (e == cur)
+ 			len += sprintf(name+len, "[%s] ", cur->elevator_name);
+-			continue;
+-		}
+-		if (elv_support_features(q, e))
++		else if (elv_support_features(q, e))
+ 			len += sprintf(name+len, "%s ", e->elevator_name);
+ 	}
+ 	spin_unlock(&elv_list_lock);

commit 7919d679ae09c0dc30dfecb7cbc02306cf95cdd7
+Author: Jinlong Chen 
+Date:   Tue Nov 29 23:46:34 2022 +0800
+
+    block: include 'none' for initial elv_iosched_show call
+    
+    This makes the printing order of the io schedulers consistent, and removes
+    a redundant q->elevator check.
+    
+    Signed-off-by: Jinlong Chen 
+    Reviewed-by: Christoph Hellwig 
+    Link: https://lore.kernel.org/r/bdd7083ed4f232e3285f39081e3c5f30b20b8da2.1669736350.git.nickyc975@zju.edu.cn
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/elevator.c b/block/elevator.c
+index 599413620558..308bee253564 100644
+--- a/block/elevator.c
++++ b/block/elevator.c
+@@ -767,10 +767,12 @@ ssize_t elv_iosched_show(struct request_queue *q, char *name)
+ 	if (!elv_support_iosched(q))
+ 		return sprintf(name, "none\n");
+ 
+-	if (!q->elevator)
++	if (!q->elevator) {
+ 		len += sprintf(name+len, "[none] ");
+-	else
++	} else {
++		len += sprintf(name+len, "none ");
+ 		cur = eq->type;
++	}
+ 
+ 	spin_lock(&elv_list_lock);
+ 	list_for_each_entry(e, &elv_list, list) {
+@@ -783,9 +785,6 @@ ssize_t elv_iosched_show(struct request_queue *q, char *name)
+ 	}
+ 	spin_unlock(&elv_list_lock);
+ 
+-	if (q->elevator)
+-		len += sprintf(name+len, "none");
+-
+ 	len += sprintf(len+name, "\n");
+ 	return len;
+ }

commit 12ad3d2d6c5b0131a6052de91360849e3e154846
+Author: Lin Ma 
+Date:   Fri Nov 25 07:15:54 2022 -0700
+
+    io_uring/poll: fix poll_refs race with cancelation
+    
+    There is an interesting race condition of poll_refs which could result
+    in a NULL pointer dereference. The crash trace is like:
+    
+    KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f]
+    CPU: 0 PID: 30781 Comm: syz-executor.2 Not tainted 6.0.0-g493ffd6605b2 #1
+    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
+    1.13.0-1ubuntu1.1 04/01/2014
+    RIP: 0010:io_poll_remove_entry io_uring/poll.c:154 [inline]
+    RIP: 0010:io_poll_remove_entries+0x171/0x5b4 io_uring/poll.c:190
+    Code: ...
+    RSP: 0018:ffff88810dfefba0 EFLAGS: 00010202
+    RAX: 0000000000000001 RBX: 0000000000000000 RCX: 0000000000040000
+    RDX: ffffc900030c4000 RSI: 000000000003ffff RDI: 0000000000040000
+    RBP: 0000000000000008 R08: ffffffff9764d3dd R09: fffffbfff3836781
+    R10: fffffbfff3836781 R11: 0000000000000000 R12: 1ffff11003422d60
+    R13: ffff88801a116b04 R14: ffff88801a116ac0 R15: dffffc0000000000
+    FS:  00007f9c07497700(0000) GS:ffff88811a600000(0000) knlGS:0000000000000000
+    CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+    CR2: 00007ffb5c00ea98 CR3: 0000000105680005 CR4: 0000000000770ef0
+    DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+    DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+    PKRU: 55555554
+    Call Trace:
+     
+     io_apoll_task_func+0x3f/0xa0 io_uring/poll.c:299
+     handle_tw_list io_uring/io_uring.c:1037 [inline]
+     tctx_task_work+0x37e/0x4f0 io_uring/io_uring.c:1090
+     task_work_run+0x13a/0x1b0 kernel/task_work.c:177
+     get_signal+0x2402/0x25a0 kernel/signal.c:2635
+     arch_do_signal_or_restart+0x3b/0x660 arch/x86/kernel/signal.c:869
+     exit_to_user_mode_loop kernel/entry/common.c:166 [inline]
+     exit_to_user_mode_prepare+0xc2/0x160 kernel/entry/common.c:201
+     __syscall_exit_to_user_mode_work kernel/entry/common.c:283 [inline]
+     syscall_exit_to_user_mode+0x58/0x160 kernel/entry/common.c:294
+     entry_SYSCALL_64_after_hwframe+0x63/0xcd
+    
+    The root cause for this is a tiny overlooking in
+    io_poll_check_events() when cocurrently run with poll cancel routine
+    io_poll_cancel_req().
+    
+    The interleaving to trigger use-after-free:
+    
+    CPU0                                       |  CPU1
+                                               |
+    io_apoll_task_func()                       |  io_poll_cancel_req()
+     io_poll_check_events()                    |
+      // do while first loop                   |
+      v = atomic_read(...)                     |
+      // v = poll_refs = 1                     |
+      ...                                      |  io_poll_mark_cancelled()
+                                               |   atomic_or()
+                                               |   // poll_refs =
+    IO_POLL_CANCEL_FLAG | 1
+                                               |
+      atomic_sub_return(...)                   |
+      // poll_refs = IO_POLL_CANCEL_FLAG       |
+      // loop continue                         |
+                                               |
+                                               |  io_poll_execute()
+                                               |   io_poll_get_ownership()
+                                               |   // poll_refs =
+    IO_POLL_CANCEL_FLAG | 1
+                                               |   // gets the ownership
+      v = atomic_read(...)                     |
+      // poll_refs not change                  |
+                                               |
+      if (v & IO_POLL_CANCEL_FLAG)             |
+       return -ECANCELED;                      |
+      // io_poll_check_events return           |
+      // will go into                          |
+      // io_req_complete_failed() free req     |
+                                               |
+                                               |  io_apoll_task_func()
+                                               |  // also go into
+    io_req_complete_failed()
+    
+    And the interleaving to trigger the kernel WARNING:
+    
+    CPU0                                       |  CPU1
+                                               |
+    io_apoll_task_func()                       |  io_poll_cancel_req()
+     io_poll_check_events()                    |
+      // do while first loop                   |
+      v = atomic_read(...)                     |
+      // v = poll_refs = 1                     |
+      ...                                      |  io_poll_mark_cancelled()
+                                               |   atomic_or()
+                                               |   // poll_refs =
+    IO_POLL_CANCEL_FLAG | 1
+                                               |
+      atomic_sub_return(...)                   |
+      // poll_refs = IO_POLL_CANCEL_FLAG       |
+      // loop continue                         |
+                                               |
+      v = atomic_read(...)                     |
+      // v = IO_POLL_CANCEL_FLAG               |
+                                               |  io_poll_execute()
+                                               |   io_poll_get_ownership()
+                                               |   // poll_refs =
+    IO_POLL_CANCEL_FLAG | 1
+                                               |   // gets the ownership
+                                               |
+      WARN_ON_ONCE(!(v & IO_POLL_REF_MASK)))   |
+      // v & IO_POLL_REF_MASK = 0 WARN         |
+                                               |
+                                               |  io_apoll_task_func()
+                                               |  // also go into
+    io_req_complete_failed()
+    
+    By looking up the source code and communicating with Pavel, the
+    implementation of this atomic poll refs should continue the loop of
+    io_poll_check_events() just to avoid somewhere else to grab the
+    ownership. Therefore, this patch simply adds another AND operation to
+    make sure the loop will stop if it finds the poll_refs is exactly equal
+    to IO_POLL_CANCEL_FLAG. Since io_poll_cancel_req() grabs ownership and
+    will finally make its way to io_req_complete_failed(), the req will
+    be reclaimed as expected.
+    
+    Fixes: aa43477b0402 ("io_uring: poll rework")
+    Signed-off-by: Lin Ma 
+    Reviewed-by: Pavel Begunkov 
+    [axboe: tweak description and code style]
+    Signed-off-by: Jens Axboe 
+
+diff --git a/io_uring/poll.c b/io_uring/poll.c
+index b444b7d87697..d9bf1767867e 100644
+--- a/io_uring/poll.c
++++ b/io_uring/poll.c
+@@ -308,7 +308,8 @@ static int io_poll_check_events(struct io_kiocb *req, bool *locked)
+ 		 * Release all references, retry if someone tried to restart
+ 		 * task_work while we were executing it.
+ 		 */
+-	} while (atomic_sub_return(v & IO_POLL_REF_MASK, &req->poll_refs));
++	} while (atomic_sub_return(v & IO_POLL_REF_MASK, &req->poll_refs) &
++					IO_POLL_REF_MASK);
+ 
+ 	return IOU_POLL_NO_ACTION;
+ }

commit 9d94c04c0db024922e886c9fd429659f22f48ea4
+Author: Lin Ma 
+Date:   Wed Nov 23 02:40:15 2022 +0800
+
+    io_uring/filetable: fix file reference underflow
+    
+    There is an interesting reference bug when -ENOMEM occurs in calling of
+    io_install_fixed_file(). KASan report like below:
+    
+    [   14.057131] ==================================================================
+    [   14.059161] BUG: KASAN: use-after-free in unix_get_socket+0x10/0x90
+    [   14.060975] Read of size 8 at addr ffff88800b09cf20 by task kworker/u8:2/45
+    [   14.062684]
+    [   14.062768] CPU: 2 PID: 45 Comm: kworker/u8:2 Not tainted 6.1.0-rc4 #1
+    [   14.063099] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.0-0-gd239552ce722-prebuilt.qemu.org 04/01/2014
+    [   14.063666] Workqueue: events_unbound io_ring_exit_work
+    [   14.063936] Call Trace:
+    [   14.064065]  
+    [   14.064175]  dump_stack_lvl+0x34/0x48
+    [   14.064360]  print_report+0x172/0x475
+    [   14.064547]  ? _raw_spin_lock_irq+0x83/0xe0
+    [   14.064758]  ? __virt_addr_valid+0xef/0x170
+    [   14.064975]  ? unix_get_socket+0x10/0x90
+    [   14.065167]  kasan_report+0xad/0x130
+    [   14.065353]  ? unix_get_socket+0x10/0x90
+    [   14.065553]  unix_get_socket+0x10/0x90
+    [   14.065744]  __io_sqe_files_unregister+0x87/0x1e0
+    [   14.065989]  ? io_rsrc_refs_drop+0x1c/0xd0
+    [   14.066199]  io_ring_exit_work+0x388/0x6a5
+    [   14.066410]  ? io_uring_try_cancel_requests+0x5bf/0x5bf
+    [   14.066674]  ? try_to_wake_up+0xdb/0x910
+    [   14.066873]  ? virt_to_head_page+0xbe/0xbe
+    [   14.067080]  ? __schedule+0x574/0xd20
+    [   14.067273]  ? read_word_at_a_time+0xe/0x20
+    [   14.067492]  ? strscpy+0xb5/0x190
+    [   14.067665]  process_one_work+0x423/0x710
+    [   14.067879]  worker_thread+0x2a2/0x6f0
+    [   14.068073]  ? process_one_work+0x710/0x710
+    [   14.068284]  kthread+0x163/0x1a0
+    [   14.068454]  ? kthread_complete_and_exit+0x20/0x20
+    [   14.068697]  ret_from_fork+0x22/0x30
+    [   14.068886]  
+    [   14.069000]
+    [   14.069088] Allocated by task 289:
+    [   14.069269]  kasan_save_stack+0x1e/0x40
+    [   14.069463]  kasan_set_track+0x21/0x30
+    [   14.069652]  __kasan_slab_alloc+0x58/0x70
+    [   14.069899]  kmem_cache_alloc+0xc5/0x200
+    [   14.070100]  __alloc_file+0x20/0x160
+    [   14.070283]  alloc_empty_file+0x3b/0xc0
+    [   14.070479]  path_openat+0xc3/0x1770
+    [   14.070689]  do_filp_open+0x150/0x270
+    [   14.070888]  do_sys_openat2+0x113/0x270
+    [   14.071081]  __x64_sys_openat+0xc8/0x140
+    [   14.071283]  do_syscall_64+0x3b/0x90
+    [   14.071466]  entry_SYSCALL_64_after_hwframe+0x63/0xcd
+    [   14.071791]
+    [   14.071874] Freed by task 0:
+    [   14.072027]  kasan_save_stack+0x1e/0x40
+    [   14.072224]  kasan_set_track+0x21/0x30
+    [   14.072415]  kasan_save_free_info+0x2a/0x50
+    [   14.072627]  __kasan_slab_free+0x106/0x190
+    [   14.072858]  kmem_cache_free+0x98/0x340
+    [   14.073075]  rcu_core+0x427/0xe50
+    [   14.073249]  __do_softirq+0x110/0x3cd
+    [   14.073440]
+    [   14.073523] Last potentially related work creation:
+    [   14.073801]  kasan_save_stack+0x1e/0x40
+    [   14.074017]  __kasan_record_aux_stack+0x97/0xb0
+    [   14.074264]  call_rcu+0x41/0x550
+    [   14.074436]  task_work_run+0xf4/0x170
+    [   14.074619]  exit_to_user_mode_prepare+0x113/0x120
+    [   14.074858]  syscall_exit_to_user_mode+0x1d/0x40
+    [   14.075092]  do_syscall_64+0x48/0x90
+    [   14.075272]  entry_SYSCALL_64_after_hwframe+0x63/0xcd
+    [   14.075529]
+    [   14.075612] Second to last potentially related work creation:
+    [   14.075900]  kasan_save_stack+0x1e/0x40
+    [   14.076098]  __kasan_record_aux_stack+0x97/0xb0
+    [   14.076325]  task_work_add+0x72/0x1b0
+    [   14.076512]  fput+0x65/0xc0
+    [   14.076657]  filp_close+0x8e/0xa0
+    [   14.076825]  __x64_sys_close+0x15/0x50
+    [   14.077019]  do_syscall_64+0x3b/0x90
+    [   14.077199]  entry_SYSCALL_64_after_hwframe+0x63/0xcd
+    [   14.077448]
+    [   14.077530] The buggy address belongs to the object at ffff88800b09cf00
+    [   14.077530]  which belongs to the cache filp of size 232
+    [   14.078105] The buggy address is located 32 bytes inside of
+    [   14.078105]  232-byte region [ffff88800b09cf00, ffff88800b09cfe8)
+    [   14.078685]
+    [   14.078771] The buggy address belongs to the physical page:
+    [   14.079046] page:000000001bd520e7 refcount:1 mapcount:0 mapping:0000000000000000 index:0xffff88800b09de00 pfn:0xb09c
+    [   14.079575] head:000000001bd520e7 order:1 compound_mapcount:0 compound_pincount:0
+    [   14.079946] flags: 0x100000000010200(slab|head|node=0|zone=1)
+    [   14.080244] raw: 0100000000010200 0000000000000000 dead000000000001 ffff88800493cc80
+    [   14.080629] raw: ffff88800b09de00 0000000080190018 00000001ffffffff 0000000000000000
+    [   14.081016] page dumped because: kasan: bad access detected
+    [   14.081293]
+    [   14.081376] Memory state around the buggy address:
+    [   14.081618]  ffff88800b09ce00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+    [   14.081974]  ffff88800b09ce80: 00 00 00 00 00 fc fc fc fc fc fc fc fc fc fc fc
+    [   14.082336] >ffff88800b09cf00: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+    [   14.082690]                                ^
+    [   14.082909]  ffff88800b09cf80: fb fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc
+    [   14.083266]  ffff88800b09d000: fc fc fc fc fc fc fc fc fa fb fb fb fb fb fb fb
+    [   14.083622] ==================================================================
+    
+    The actual tracing of this bug is shown below:
+    
+    commit 8c71fe750215 ("io_uring: ensure fput() called correspondingly
+    when direct install fails") adds an additional fput() in
+    io_fixed_fd_install() when io_file_bitmap_get() returns error values. In
+    that case, the routine will never make it to io_install_fixed_file() due
+    to an early return.
+    
+    static int io_fixed_fd_install(...)
+    {
+      if (alloc_slot) {
+        ...
+        ret = io_file_bitmap_get(ctx);
+        if (unlikely(ret < 0)) {
+          io_ring_submit_unlock(ctx, issue_flags);
+          fput(file);
+          return ret;
+        }
+        ...
+      }
+      ...
+      ret = io_install_fixed_file(req, file, issue_flags, file_slot);
+      ...
+    }
+    
+    In the above scenario, the reference is okay as io_fixed_fd_install()
+    ensures the fput() is called when something bad happens, either via
+    bitmap or via inner io_install_fixed_file().
+    
+    However, the commit 61c1b44a21d7 ("io_uring: fix deadlock on iowq file
+    slot alloc") breaks the balance because it places fput() into the common
+    path for both io_file_bitmap_get() and io_install_fixed_file(). Since
+    io_install_fixed_file() handles the fput() itself, the reference
+    underflow come across then.
+    
+    There are some extra commits make the current code into
+    io_fixed_fd_install() -> __io_fixed_fd_install() ->
+    io_install_fixed_file()
+    
+    However, the fact that there is an extra fput() is called if
+    io_install_fixed_file() calls fput(). Traversing through the code, I
+    find that the existing two callers to __io_fixed_fd_install():
+    io_fixed_fd_install() and io_msg_send_fd() have fput() when handling
+    error return, this patch simply removes the fput() in
+    io_install_fixed_file() to fix the bug.
+    
+    Fixes: 61c1b44a21d7 ("io_uring: fix deadlock on iowq file slot alloc")
+    Signed-off-by: Lin Ma 
+    Link: https://lore.kernel.org/r/be4ba4b.5d44.184a0a406a4.Coremail.linma@zju.edu.cn
+    Signed-off-by: Jens Axboe 
+
+diff --git a/io_uring/filetable.c b/io_uring/filetable.c
+index 7b473259f3f4..68dfc6936aa7 100644
+--- a/io_uring/filetable.c
++++ b/io_uring/filetable.c
+@@ -101,8 +101,6 @@ static int io_install_fixed_file(struct io_ring_ctx *ctx, struct file *file,
+ err:
+ 	if (needs_switch)
+ 		io_rsrc_node_switch(ctx, ctx->file_data);
+-	if (ret)
+-		fput(file);
+ 	return ret;
+ }
+ 

commit 0fc044b2b5e2d05a1fa1fb0d7f270367a7855d79
+Author: Lin Ma 
+Date:   Sun Aug 7 15:59:52 2022 +0100
+
+    media: dvbdev: adopts refcnt to avoid UAF
+    
+    dvb_unregister_device() is known that prone to use-after-free.
+    That is, the cleanup from dvb_unregister_device() releases the dvb_device
+    even if there are pointers stored in file->private_data still refer to it.
+    
+    This patch adds a reference counter into struct dvb_device and delays its
+    deallocation until no pointer refers to the object.
+    
+    Link: https://lore.kernel.org/linux-media/20220807145952.10368-1-linma@zju.edu.cn
+    Signed-off-by: Lin Ma 
+    Reported-by: kernel test robot 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb-core/dvb_ca_en50221.c
+index 15a08d8c69ef..c2d2792227f8 100644
+--- a/drivers/media/dvb-core/dvb_ca_en50221.c
++++ b/drivers/media/dvb-core/dvb_ca_en50221.c
+@@ -157,7 +157,7 @@ static void dvb_ca_private_free(struct dvb_ca_private *ca)
+ {
+ 	unsigned int i;
+ 
+-	dvb_free_device(ca->dvbdev);
++	dvb_device_put(ca->dvbdev);
+ 	for (i = 0; i < ca->slot_count; i++)
+ 		vfree(ca->slot_info[i].rx_buffer.data);
+ 
+diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
+index 2a98082c605e..7ce4785c8d88 100644
+--- a/drivers/media/dvb-core/dvb_frontend.c
++++ b/drivers/media/dvb-core/dvb_frontend.c
+@@ -136,7 +136,7 @@ static void __dvb_frontend_free(struct dvb_frontend *fe)
+ 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+ 
+ 	if (fepriv)
+-		dvb_free_device(fepriv->dvbdev);
++		dvb_device_put(fepriv->dvbdev);
+ 
+ 	dvb_frontend_invoke_release(fe, fe->ops.release);
+ 
+diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c
+index 5b275a9395c1..d45673cb3ce1 100644
+--- a/drivers/media/dvb-core/dvbdev.c
++++ b/drivers/media/dvb-core/dvbdev.c
+@@ -97,7 +97,7 @@ static int dvb_device_open(struct inode *inode, struct file *file)
+ 		new_fops = fops_get(dvbdev->fops);
+ 		if (!new_fops)
+ 			goto fail;
+-		file->private_data = dvbdev;
++		file->private_data = dvb_device_get(dvbdev);
+ 		replace_fops(file, new_fops);
+ 		if (file->f_op->open)
+ 			err = file->f_op->open(inode, file);
+@@ -161,6 +161,9 @@ int dvb_generic_release(struct inode *inode, struct file *file)
+ 	}
+ 
+ 	dvbdev->users++;
++
++	dvb_device_put(dvbdev);
++
+ 	return 0;
+ }
+ EXPORT_SYMBOL(dvb_generic_release);
+@@ -479,6 +482,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
+ 		return -ENOMEM;
+ 	}
+ 
++	kref_init(&dvbdev->ref);
+ 	memcpy(dvbdev, template, sizeof(struct dvb_device));
+ 	dvbdev->type = type;
+ 	dvbdev->id = id;
+@@ -510,7 +514,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
+ #endif
+ 
+ 	dvbdev->minor = minor;
+-	dvb_minors[minor] = dvbdev;
++	dvb_minors[minor] = dvb_device_get(dvbdev);
+ 	up_write(&minor_rwsem);
+ 
+ 	ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads);
+@@ -555,6 +559,7 @@ void dvb_remove_device(struct dvb_device *dvbdev)
+ 
+ 	down_write(&minor_rwsem);
+ 	dvb_minors[dvbdev->minor] = NULL;
++	dvb_device_put(dvbdev);
+ 	up_write(&minor_rwsem);
+ 
+ 	dvb_media_device_free(dvbdev);
+@@ -566,21 +571,34 @@ void dvb_remove_device(struct dvb_device *dvbdev)
+ EXPORT_SYMBOL(dvb_remove_device);
+ 
+ 
+-void dvb_free_device(struct dvb_device *dvbdev)
++static void dvb_free_device(struct kref *ref)
+ {
+-	if (!dvbdev)
+-		return;
++	struct dvb_device *dvbdev = container_of(ref, struct dvb_device, ref);
+ 
+ 	kfree (dvbdev->fops);
+ 	kfree (dvbdev);
+ }
+-EXPORT_SYMBOL(dvb_free_device);
++
++
++struct dvb_device *dvb_device_get(struct dvb_device *dvbdev)
++{
++	kref_get(&dvbdev->ref);
++	return dvbdev;
++}
++EXPORT_SYMBOL(dvb_device_get);
++
++
++void dvb_device_put(struct dvb_device *dvbdev)
++{
++	if (dvbdev)
++		kref_put(&dvbdev->ref, dvb_free_device);
++}
+ 
+ 
+ void dvb_unregister_device(struct dvb_device *dvbdev)
+ {
+ 	dvb_remove_device(dvbdev);
+-	dvb_free_device(dvbdev);
++	dvb_device_put(dvbdev);
+ }
+ EXPORT_SYMBOL(dvb_unregister_device);
+ 
+diff --git a/include/media/dvbdev.h b/include/media/dvbdev.h
+index 6ccff7c6fa6b..fad9871157e2 100644
+--- a/include/media/dvbdev.h
++++ b/include/media/dvbdev.h
+@@ -160,6 +160,7 @@ struct dvb_adapter {
+  */
+ struct dvb_device {
+ 	struct list_head list_head;
++	struct kref ref;
+ 	const struct file_operations *fops;
+ 	struct dvb_adapter *adapter;
+ 	enum dvb_device_type type;
+@@ -191,6 +192,20 @@ struct dvb_device {
+ 	void *priv;
+ };
+ 
++/**
++ * dvb_device_get - Increase dvb_device reference
++ *
++ * @dvbdev:	pointer to struct dvb_device
++ */
++struct dvb_device *dvb_device_get(struct dvb_device *dvbdev);
++
++/**
++ * dvb_device_get - Decrease dvb_device reference
++ *
++ * @dvbdev:	pointer to struct dvb_device
++ */
++void dvb_device_put(struct dvb_device *dvbdev);
++
+ /**
+  * dvb_register_adapter - Registers a new DVB adapter
+  *
+@@ -235,29 +250,17 @@ int dvb_register_device(struct dvb_adapter *adap,
+ /**
+  * dvb_remove_device - Remove a registered DVB device
+  *
+- * This does not free memory.  To do that, call dvb_free_device().
++ * This does not free memory. dvb_free_device() will do that when
++ * reference counter is empty
+  *
+  * @dvbdev:	pointer to struct dvb_device
+  */
+ void dvb_remove_device(struct dvb_device *dvbdev);
+ 
+-/**
+- * dvb_free_device - Free memory occupied by a DVB device.
+- *
+- * Call dvb_unregister_device() before calling this function.
+- *
+- * @dvbdev:	pointer to struct dvb_device
+- */
+-void dvb_free_device(struct dvb_device *dvbdev);
+ 
+ /**
+  * dvb_unregister_device - Unregisters a DVB device
+  *
+- * This is a combination of dvb_remove_device() and dvb_free_device().
+- * Using this function is usually a mistake, and is often an indicator
+- * for a use-after-free bug (when a userspace process keeps a file
+- * handle to a detached device).
+- *
+  * @dvbdev:	pointer to struct dvb_device
+  */
+ void dvb_unregister_device(struct dvb_device *dvbdev);

commit 8dbd6e4ce1b9c527921643d9e34f188a10d4e893
+Author: Duoming Zhou 
+Date:   Wed Nov 23 18:06:42 2022 +0800
+
+    qlcnic: fix sleep-in-atomic-context bugs caused by msleep
+    
+    The watchdog timer is used to monitor whether the process
+    of transmitting data is timeout. If we use qlcnic driver,
+    the dev_watchdog() that is the timer handler of watchdog
+    timer will call qlcnic_tx_timeout() to process the timeout.
+    But the qlcnic_tx_timeout() calls msleep(), as a result,
+    the sleep-in-atomic-context bugs will happen. The processes
+    are shown below:
+    
+       (atomic context)
+    dev_watchdog
+      qlcnic_tx_timeout
+        qlcnic_83xx_idc_request_reset
+          qlcnic_83xx_lock_driver
+            msleep
+    
+    ---------------------------
+    
+       (atomic context)
+    dev_watchdog
+      qlcnic_tx_timeout
+        qlcnic_83xx_idc_request_reset
+          qlcnic_83xx_lock_driver
+            qlcnic_83xx_recover_driver_lock
+              msleep
+    
+    Fix by changing msleep() to mdelay(), the mdelay() is
+    busy-waiting and the bugs could be mitigated.
+    
+    Fixes: 629263acaea3 ("qlcnic: 83xx CNA inter driver communication mechanism")
+    Signed-off-by: Duoming Zhou 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+index bd0607680329..2fd5c6fdb500 100644
+--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+@@ -2991,7 +2991,7 @@ static void qlcnic_83xx_recover_driver_lock(struct qlcnic_adapter *adapter)
+ 		QLCWRX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK, val);
+ 		dev_info(&adapter->pdev->dev,
+ 			 "%s: lock recovery initiated\n", __func__);
+-		msleep(QLC_83XX_DRV_LOCK_RECOVERY_DELAY);
++		mdelay(QLC_83XX_DRV_LOCK_RECOVERY_DELAY);
+ 		val = QLCRDX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK);
+ 		id = ((val >> 2) & 0xF);
+ 		if (id == adapter->portnum) {
+@@ -3027,7 +3027,7 @@ int qlcnic_83xx_lock_driver(struct qlcnic_adapter *adapter)
+ 		if (status)
+ 			break;
+ 
+-		msleep(QLC_83XX_DRV_LOCK_WAIT_DELAY);
++		mdelay(QLC_83XX_DRV_LOCK_WAIT_DELAY);
+ 		i++;
+ 
+ 		if (i == 1)

commit 4284354758d67cf77ab2a4494e28d4c05fb83074
+Author: Jinlong Chen 
+Date:   Tue Nov 22 22:21:26 2022 +0800
+
+    elevator: remove an outdated comment in elevator_change
+    
+    mq is no longer a special case.
+    
+    Signed-off-by: Jinlong Chen 
+    Reviewed-by: Christoph Hellwig 
+    Link: https://lore.kernel.org/r/cbf47824fc726440371e74c867bf635ae1b671a3.1669126766.git.nickyc975@zju.edu.cn
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/elevator.c b/block/elevator.c
+index 5287b39cd7a9..599413620558 100644
+--- a/block/elevator.c
++++ b/block/elevator.c
+@@ -721,9 +721,6 @@ static int elevator_change(struct request_queue *q, const char *elevator_name)
+ 	if (!blk_queue_registered(q))
+ 		return -ENOENT;
+ 
+-	/*
+-	 * Special case for mq, turn off scheduling
+-	 */
+ 	if (!strncmp(elevator_name, "none", 4)) {
+ 		if (q->elevator)
+ 			elevator_disable(q);

commit f69b5e8f356e4e57e94b806ca1dcb9771933bb9c
+Author: Jinlong Chen 
+Date:   Tue Nov 22 22:21:25 2022 +0800
+
+    elevator: update the document of elevator_match
+    
+    elevator_match does not care about elevator_features any more. Remove
+    related descriptions from its document.
+    
+    Fixes: ffb86425ee2c ("block: don't check for required features in elevator_match")
+    Signed-off-by: Jinlong Chen 
+    Reviewed-by: Christoph Hellwig 
+    Link: https://lore.kernel.org/r/a58424555202c07a9ccf7f60c3ad7e247da09e25.1669126766.git.nickyc975@zju.edu.cn
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/elevator.c b/block/elevator.c
+index 1fa45717b1d6..5287b39cd7a9 100644
+--- a/block/elevator.c
++++ b/block/elevator.c
+@@ -91,12 +91,11 @@ static inline bool elv_support_features(struct request_queue *q,
+ }
+ 
+ /**
+- * elevator_match - Test an elevator name and features
++ * elevator_match - Check whether @e's name or alias matches @name
+  * @e: Scheduler to test
+  * @name: Elevator name to test
+  *
+- * Return true if the elevator @e name matches @name and if @e provides all
+- * the features specified by @required_features.
++ * Return true if the elevator @e's name or alias matches @name.
+  */
+ static bool elevator_match(const struct elevator_type *e, const char *name)
+ {

commit e0cca8bc9cd8d6176921cb3f5f466d3ccfbc6b99
+Author: Jinlong Chen 
+Date:   Tue Nov 22 22:21:24 2022 +0800
+
+    elevator: printk a warning if switching to a new io scheduler fails
+    
+    printk a warning to indicate that the io scheduler has been set to none
+    if switching to a new io scheduler fails.
+    
+    Suggested-by: Christoph Hellwig 
+    Signed-off-by: Jinlong Chen 
+    Reviewed-by: Christoph Hellwig 
+    Link: https://lore.kernel.org/r/d51ed0fb457db7a4f9cbb0dbce36d534e22be457.1669126766.git.nickyc975@zju.edu.cn
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/elevator.c b/block/elevator.c
+index 01aa9f38f22e..1fa45717b1d6 100644
+--- a/block/elevator.c
++++ b/block/elevator.c
+@@ -683,6 +683,12 @@ int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
+ out_unfreeze:
+ 	blk_mq_unquiesce_queue(q);
+ 	blk_mq_unfreeze_queue(q);
++
++	if (ret) {
++		pr_warn("elv: switch to \"%s\" failed, falling back to \"none\"\n",
++			new_e->elevator_name);
++	}
++
+ 	return ret;
+ }
+ 

commit ac1171bd2c7a3a32dfbdd3c347919fee32b745a1
+Author: Jinlong Chen 
+Date:   Tue Nov 22 22:21:23 2022 +0800
+
+    elevator: update the document of elevator_switch
+    
+    We no longer support falling back to the old io scheduler if switching to
+    the new one fails. Update the document to indicate that.
+    
+    Fixes: a1ce35fa4985 ("block: remove dead elevator code")
+    Signed-off-by: Jinlong Chen 
+    Reviewed-by: Christoph Hellwig 
+    Link: https://lore.kernel.org/r/94250961689ba7d2e67a7d9e7995a11166fedb31.1669126766.git.nickyc975@zju.edu.cn
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/elevator.c b/block/elevator.c
+index a5bdc3b1e7e5..01aa9f38f22e 100644
+--- a/block/elevator.c
++++ b/block/elevator.c
+@@ -650,10 +650,10 @@ void elevator_init_mq(struct request_queue *q)
+ }
+ 
+ /*
+- * switch to new_e io scheduler. be careful not to introduce deadlocks -
+- * we don't free the old io scheduler, before we have allocated what we
+- * need for the new one. this way we have a chance of going back to the old
+- * one, if the new one fails init for some reason.
++ * Switch to new_e io scheduler.
++ *
++ * If switching fails, we are most likely running out of memory and not able
++ * to restore the old io scheduler, so leaving the io scheduler being none.
+  */
+ int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
+ {

commit 23a6c9ac4dbd7cccf5b909e78aa84192b65f2833
+Author: Lin Ma 
+Date:   Thu Nov 10 20:21:03 2022 +0800
+
+    io_uring: update outdated comment of callbacks
+    
+    Previous commit ebc11b6c6b87 ("io_uring: clean io-wq callbacks") rename
+    io_free_work() into io_wq_free_work() for consistency. This patch also
+    updates relevant comment to avoid misunderstanding.
+    
+    Fixes: ebc11b6c6b87 ("io_uring: clean io-wq callbacks")
+    Signed-off-by: Lin Ma 
+    Link: https://lore.kernel.org/r/20221110122103.20120-1-linma@zju.edu.cn
+    Signed-off-by: Jens Axboe 
+
+diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
+index cf68d16255a0..c770eed4d717 100644
+--- a/io_uring/io_uring.c
++++ b/io_uring/io_uring.c
+@@ -1781,7 +1781,7 @@ void io_wq_submit_work(struct io_wq_work *work)
+ 	bool needs_poll = false;
+ 	int ret = 0, err = -ECANCELED;
+ 
+-	/* one will be dropped by ->io_free_work() after returning to io-wq */
++	/* one will be dropped by ->io_wq_free_work() after returning to io-wq */
+ 	if (!(req->flags & REQ_F_REFCOUNT))
+ 		__io_req_set_refcount(req, 2);
+ 	else

commit cd42a53d25d489317b9ae5213da721cde8cb7071
+Author: Lin Ma 
+Date:   Thu Nov 10 14:03:13 2022 +0800
+
+    io_uring/poll: remove outdated comments of caching
+    
+    Previous commit 13a99017ff19 ("io_uring: remove events caching
+    atavisms") entirely removes the events caching optimization introduced
+    by commit 81459350d581 ("io_uring: cache req->apoll->events in
+    req->cflags"). Hence the related comment should also be removed to avoid
+    misunderstanding.
+    
+    Fixes: 13a99017ff19 ("io_uring: remove events caching atavisms")
+    Signed-off-by: Lin Ma 
+    Link: https://lore.kernel.org/r/20221110060313.16303-1-linma@zju.edu.cn
+    Signed-off-by: Jens Axboe 
+
+diff --git a/io_uring/poll.c b/io_uring/poll.c
+index 58e02d963961..8fb8e781c02d 100644
+--- a/io_uring/poll.c
++++ b/io_uring/poll.c
+@@ -324,12 +324,7 @@ static void io_apoll_task_func(struct io_kiocb *req, bool *locked)
+ static void __io_poll_execute(struct io_kiocb *req, int mask)
+ {
+ 	io_req_set_res(req, mask, 0);
+-	/*
+-	 * This is useful for poll that is armed on behalf of another
+-	 * request, and where the wakeup path could be on a different
+-	 * CPU. We want to avoid pulling in req->apoll->events for that
+-	 * case.
+-	 */
++
+ 	if (req->opcode == IORING_OP_POLL_ADD)
+ 		req->io_task_work.func = io_poll_task_func;
+ 	else

commit 0ad6bded175e829c2ca261529c9dce39a32a042d
+Author: Lin Ma 
+Date:   Wed Nov 16 21:02:49 2022 +0800
+
+    nfc/nci: fix race with opening and closing
+    
+    Previously we leverage NCI_UNREG and the lock inside nci_close_device to
+    prevent the race condition between opening a device and closing a
+    device. However, it still has problem because a failed opening command
+    will erase the NCI_UNREG flag and allow another opening command to
+    bypass the status checking.
+    
+    This fix corrects that by making sure the NCI_UNREG is held.
+    
+    Reported-by: syzbot+43475bf3cfbd6e41f5b7@syzkaller.appspotmail.com
+    Fixes: 48b71a9e66c2 ("NFC: add NCI_UNREG flag to eliminate the race")
+    Signed-off-by: Lin Ma 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
+index 6a193cce2a75..4ffdf2f45c44 100644
+--- a/net/nfc/nci/core.c
++++ b/net/nfc/nci/core.c
+@@ -542,7 +542,7 @@ static int nci_open_device(struct nci_dev *ndev)
+ 		skb_queue_purge(&ndev->tx_q);
+ 
+ 		ndev->ops->close(ndev);
+-		ndev->flags = 0;
++		ndev->flags &= BIT(NCI_UNREG);
+ 	}
+ 
+ done:

commit ce8cc75c7419ad54cb99437543a54c97c7446db5
+Author: Duoming Zhou 
+Date:   Tue Oct 18 16:34:24 2022 +0800
+
+    drivers: staging: r8188eu: Fix sleep-in-atomic-context bug in rtw_join_timeout_handler
+    
+    The rtw_join_timeout_handler() is a timer handler that
+    runs in atomic context, but it could call msleep().
+    As a result, the sleep-in-atomic-context bug will happen.
+    The process is shown below:
+    
+         (atomic context)
+    rtw_join_timeout_handler
+     _rtw_join_timeout_handler
+      rtw_do_join
+       rtw_select_and_join_from_scanned_queue
+        rtw_indicate_disconnect
+         rtw_lps_ctrl_wk_cmd
+          lps_ctrl_wk_hdl
+           LPS_Leave
+            LPS_RF_ON_check
+             msleep //sleep in atomic context
+    
+    Fix by removing msleep() and replacing with mdelay().
+    
+    Fixes: 15865124feed ("staging: r8188eu: introduce new core dir for RTL8188eu driver")
+    Signed-off-by: Duoming Zhou 
+    Link: https://lore.kernel.org/r/20221018083424.79741-1-duoming@zju.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/r8188eu/core/rtw_pwrctrl.c b/drivers/staging/r8188eu/core/rtw_pwrctrl.c
+index 870d81735b8d..5290ac36f08c 100644
+--- a/drivers/staging/r8188eu/core/rtw_pwrctrl.c
++++ b/drivers/staging/r8188eu/core/rtw_pwrctrl.c
+@@ -273,7 +273,7 @@ static s32 LPS_RF_ON_check(struct adapter *padapter, u32 delay_ms)
+ 			err = -1;
+ 			break;
+ 		}
+-		msleep(1);
++		mdelay(1);
+ 	}
+ 
+ 	return err;

commit 7a58b8d6021426b796eebfae80983374d9a80a75
+Author: Duoming Zhou 
+Date:   Sun Sep 18 11:33:12 2022 +0800
+
+    usb: chipidea: fix deadlock in ci_otg_del_timer
+    
+    There is a deadlock in ci_otg_del_timer(), the process is
+    shown below:
+    
+        (thread 1)                  |        (thread 2)
+    ci_otg_del_timer()              | ci_otg_hrtimer_func()
+      ...                           |
+      spin_lock_irqsave() //(1)     |  ...
+      ...                           |
+      hrtimer_cancel()              |  spin_lock_irqsave() //(2)
+      (block forever)
+    
+    We hold ci->lock in position (1) and use hrtimer_cancel() to
+    wait ci_otg_hrtimer_func() to stop, but ci_otg_hrtimer_func()
+    also need ci->lock in position (2). As a result, the
+    hrtimer_cancel() in ci_otg_del_timer() will be blocked forever.
+    
+    This patch extracts hrtimer_cancel() from the protection of
+    spin_lock_irqsave() in order that the ci_otg_hrtimer_func()
+    could obtain the ci->lock.
+    
+    What`s more, there will be no race happen. Because the
+    "next_timer" is always under the protection of
+    spin_lock_irqsave() and we only check whether "next_timer"
+    equals to NUM_OTG_FSM_TIMERS in the following code.
+    
+    Fixes: 3a316ec4c91c ("usb: chipidea: use hrtimer for otg fsm timers")
+    Cc: stable 
+    Signed-off-by: Duoming Zhou 
+    Link: https://lore.kernel.org/r/20220918033312.94348-1-duoming@zju.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c
+index ada78daba6df..c17516c29b63 100644
+--- a/drivers/usb/chipidea/otg_fsm.c
++++ b/drivers/usb/chipidea/otg_fsm.c
+@@ -256,8 +256,10 @@ static void ci_otg_del_timer(struct ci_hdrc *ci, enum otg_fsm_timer t)
+ 	ci->enabled_otg_timer_bits &= ~(1 << t);
+ 	if (ci->next_otg_timer == t) {
+ 		if (ci->enabled_otg_timer_bits == 0) {
++			spin_unlock_irqrestore(&ci->lock, flags);
+ 			/* No enabled timers after delete it */
+ 			hrtimer_cancel(&ci->otg_fsm_hrtimer);
++			spin_lock_irqsave(&ci->lock, flags);
+ 			ci->next_otg_timer = NUM_OTG_FSM_TIMERS;
+ 		} else {
+ 			/* Find the next timer */

commit 7b7dfe4833c70a11cdfa51b38705103bd31eddaa
+Author: Duoming Zhou 
+Date:   Sun Oct 2 12:07:09 2022 +0800
+
+    tty: n_gsm: fix sleep-in-atomic-context bug in gsm_control_send
+    
+    The function gsm_dlci_t1() is a timer handler that runs in an
+    atomic context, but it calls "kzalloc(..., GFP_KERNEL)" that
+    may sleep. As a result, the sleep-in-atomic-context bug will
+    happen. The process is shown below:
+    
+    gsm_dlci_t1()
+     gsm_dlci_open()
+      gsm_modem_update()
+       gsm_modem_upd_via_msc()
+        gsm_control_send()
+         kzalloc(sizeof(.., GFP_KERNEL) //may sleep
+    
+    This patch changes the gfp_t parameter of kzalloc() from GFP_KERNEL to
+    GFP_ATOMIC in order to mitigate the bug.
+    
+    Fixes: e1eaea46bb40 ("tty: n_gsm line discipline")
+    Signed-off-by: Duoming Zhou 
+    Link: https://lore.kernel.org/r/20221002040709.27849-1-duoming@zju.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
+index 5c9f76073fcd..b6e0cc4571ea 100644
+--- a/drivers/tty/n_gsm.c
++++ b/drivers/tty/n_gsm.c
+@@ -1711,7 +1711,7 @@ static struct gsm_control *gsm_control_send(struct gsm_mux *gsm,
+ 		unsigned int command, u8 *data, int clen)
+ {
+ 	struct gsm_control *ctrl = kzalloc(sizeof(struct gsm_control),
+-						GFP_KERNEL);
++						GFP_ATOMIC);
+ 	unsigned long flags;
+ 	if (ctrl == NULL)
+ 		return NULL;

commit 4046728253751adb41b05e85ebd686210efde1ad
+Author: Jinlong Chen 
+Date:   Wed Nov 2 10:52:30 2022 +0800
+
+    blk-mq: use if-else instead of goto in blk_mq_alloc_cached_request()
+    
+    if-else is more readable than goto here.
+    
+    Signed-off-by: Jinlong Chen 
+    Link: https://lore.kernel.org/r/d3306fa4e92dc9cc614edc8f1802686096bafef2.1667356813.git.nickyc975@zju.edu.cn
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/blk-mq.c b/block/blk-mq.c
+index d4824b53f6b2..fc9c400adf92 100644
+--- a/block/blk-mq.c
++++ b/block/blk-mq.c
+@@ -575,25 +575,26 @@ static struct request *blk_mq_alloc_cached_request(struct request_queue *q,
+ 
+ 	if (!plug)
+ 		return NULL;
++
+ 	if (rq_list_empty(plug->cached_rq)) {
+ 		if (plug->nr_ios == 1)
+ 			return NULL;
+ 		rq = blk_mq_rq_cache_fill(q, plug, opf, flags);
+-		if (rq)
+-			goto got_it;
+-		return NULL;
+-	}
+-	rq = rq_list_peek(&plug->cached_rq);
+-	if (!rq || rq->q != q)
+-		return NULL;
++		if (!rq)
++			return NULL;
++	} else {
++		rq = rq_list_peek(&plug->cached_rq);
++		if (!rq || rq->q != q)
++			return NULL;
+ 
+-	if (blk_mq_get_hctx_type(opf) != rq->mq_hctx->type)
+-		return NULL;
+-	if (op_is_flush(rq->cmd_flags) != op_is_flush(opf))
+-		return NULL;
++		if (blk_mq_get_hctx_type(opf) != rq->mq_hctx->type)
++			return NULL;
++		if (op_is_flush(rq->cmd_flags) != op_is_flush(opf))
++			return NULL;
++
++		plug->cached_rq = rq_list_next(rq);
++	}
+ 
+-	plug->cached_rq = rq_list_next(rq);
+-got_it:
+ 	rq->cmd_flags = opf;
+ 	INIT_LIST_HEAD(&rq->queuelist);
+ 	return rq;

commit 7edfd68165b8dab8cde231728ff092a625469eb7
+Author: Jinlong Chen 
+Date:   Wed Nov 2 10:52:29 2022 +0800
+
+    blk-mq: improve error handling in blk_mq_alloc_rq_map()
+    
+    Use goto-style error handling like we do elsewhere in the kernel.
+    
+    Signed-off-by: Jinlong Chen 
+    Link: https://lore.kernel.org/r/bbbc2d9b17b137798c7fb92042141ca4cbbc58cc.1667356813.git.nickyc975@zju.edu.cn
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/blk-mq.c b/block/blk-mq.c
+index bae6f81c39b3..d4824b53f6b2 100644
+--- a/block/blk-mq.c
++++ b/block/blk-mq.c
+@@ -3305,21 +3305,22 @@ static struct blk_mq_tags *blk_mq_alloc_rq_map(struct blk_mq_tag_set *set,
+ 	tags->rqs = kcalloc_node(nr_tags, sizeof(struct request *),
+ 				 GFP_NOIO | __GFP_NOWARN | __GFP_NORETRY,
+ 				 node);
+-	if (!tags->rqs) {
+-		blk_mq_free_tags(tags);
+-		return NULL;
+-	}
++	if (!tags->rqs)
++		goto err_free_tags;
+ 
+ 	tags->static_rqs = kcalloc_node(nr_tags, sizeof(struct request *),
+ 					GFP_NOIO | __GFP_NOWARN | __GFP_NORETRY,
+ 					node);
+-	if (!tags->static_rqs) {
+-		kfree(tags->rqs);
+-		blk_mq_free_tags(tags);
+-		return NULL;
+-	}
++	if (!tags->static_rqs)
++		goto err_free_rqs;
+ 
+ 	return tags;
++
++err_free_rqs:
++	kfree(tags->rqs);
++err_free_tags:
++	blk_mq_free_tags(tags);
++	return NULL;
+ }
+ 
+ static int blk_mq_init_request(struct blk_mq_tag_set *set, struct request *rq,

commit 56c1ee92246a5099a626b955dd7f6636cdce6f93
+Author: Jinlong Chen 
+Date:   Sun Oct 30 16:32:12 2022 +0800
+
+    blk-mq: remove redundant call to blk_freeze_queue_start in blk_mq_destroy_queue
+    
+    The calling relationship in blk_mq_destroy_queue() is as follows:
+    
+    blk_mq_destroy_queue()
+        ...
+        -> blk_queue_start_drain()
+            -> blk_freeze_queue_start()  <- called
+            ...
+        -> blk_freeze_queue()
+            -> blk_freeze_queue_start()  <- called again
+            -> blk_mq_freeze_queue_wait()
+        ...
+    
+    So there is a redundant call to blk_freeze_queue_start().
+    
+    Replace blk_freeze_queue() with blk_mq_freeze_queue_wait() to avoid the
+    redundant call.
+    
+    Signed-off-by: Jinlong Chen 
+    Reviewed-by: Christoph Hellwig 
+    Link: https://lore.kernel.org/r/20221030083212.1251255-1-nickyc975@zju.edu.cn
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/blk-mq.c b/block/blk-mq.c
+index bcb402f9bff6..623e8a506539 100644
+--- a/block/blk-mq.c
++++ b/block/blk-mq.c
+@@ -4037,7 +4037,7 @@ void blk_mq_destroy_queue(struct request_queue *q)
+ 
+ 	blk_queue_flag_set(QUEUE_FLAG_DYING, q);
+ 	blk_queue_start_drain(q);
+-	blk_freeze_queue(q);
++	blk_mq_freeze_queue_wait(q);
+ 
+ 	blk_sync_queue(q);
+ 	blk_mq_cancel_work_sync(q);

commit 219cf43c552a49a7710b7b341bf616682a2643f0
+Author: Jinlong Chen 
+Date:   Sun Oct 30 17:47:30 2022 +0800
+
+    blk-mq: move queue_is_mq out of blk_mq_cancel_work_sync
+    
+    The only caller that needs queue_is_mq check is del_gendisk, so move the
+    check into it.
+    
+    Signed-off-by: Jinlong Chen 
+    Reviewed-by: Christoph Hellwig 
+    Link: https://lore.kernel.org/r/20221030094730.1275463-1-nickyc975@zju.edu.cn
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/blk-mq.c b/block/blk-mq.c
+index 060c8cca4b24..bcb402f9bff6 100644
+--- a/block/blk-mq.c
++++ b/block/blk-mq.c
+@@ -4883,15 +4883,13 @@ EXPORT_SYMBOL(blk_mq_rq_cpu);
+ 
+ void blk_mq_cancel_work_sync(struct request_queue *q)
+ {
+-	if (queue_is_mq(q)) {
+-		struct blk_mq_hw_ctx *hctx;
+-		unsigned long i;
++	struct blk_mq_hw_ctx *hctx;
++	unsigned long i;
+ 
+-		cancel_delayed_work_sync(&q->requeue_work);
++	cancel_delayed_work_sync(&q->requeue_work);
+ 
+-		queue_for_each_hw_ctx(q, hctx, i)
+-			cancel_delayed_work_sync(&hctx->run_work);
+-	}
++	queue_for_each_hw_ctx(q, hctx, i)
++		cancel_delayed_work_sync(&hctx->run_work);
+ }
+ 
+ static int __init blk_mq_init(void)
+diff --git a/block/genhd.c b/block/genhd.c
+index 17b33c62423d..493b93faee9c 100644
+--- a/block/genhd.c
++++ b/block/genhd.c
+@@ -638,7 +638,9 @@ void del_gendisk(struct gendisk *disk)
+ 
+ 	blk_sync_queue(q);
+ 	blk_flush_integrity();
+-	blk_mq_cancel_work_sync(q);
++
++	if (queue_is_mq(q))
++		blk_mq_cancel_work_sync(q);
+ 
+ 	blk_mq_quiesce_queue(q);
+ 	if (q->elevator) {

commit 8ed40ee35d94df2fdb56bbbc07e17dffd2383625
+Author: Jinlong Chen 
+Date:   Thu Oct 20 08:48:19 2022 +0200
+
+    block: fix up elevator_type refcounting
+    
+    The current reference management logic of io scheduler modules contains
+    refcnt problems. For example, blk_mq_init_sched may fail before or after
+    the calling of e->ops.init_sched. If it fails before the calling, it does
+    nothing to the reference to the io scheduler module. But if it fails after
+    the calling, it releases the reference by calling kobject_put(&eq->kobj).
+    
+    As the callers of blk_mq_init_sched can't know exactly where the failure
+    happens, they can't handle the reference to the io scheduler module
+    properly: releasing the reference on failure results in double-release if
+    blk_mq_init_sched has released it, and not releasing the reference results
+    in ghost reference if blk_mq_init_sched did not release it either.
+    
+    The same problem also exists in io schedulers' init_sched implementations.
+    
+    We can address the problem by adding releasing statements to the error
+    handling procedures of blk_mq_init_sched and init_sched implementations.
+    But that is counterintuitive and requires modifications to existing io
+    schedulers.
+    
+    Instead, We make elevator_alloc get the io scheduler module references
+    that will be released by elevator_release. And then, we match each
+    elevator_get with an elevator_put. Therefore, each reference to an io
+    scheduler module explicitly has its own getter and releaser, and we no
+    longer need to worry about the refcnt problems.
+    
+    The bugs and the patch can be validated with tools here:
+    https://github.com/nickyc975/linux_elv_refcnt_bug.git
+    
+    [hch: split out a few bits into separate patches, use a non-try
+          module_get in elevator_alloc]
+    
+    Signed-off-by: Jinlong Chen 
+    Signed-off-by: Christoph Hellwig 
+    Link: https://lore.kernel.org/r/20221020064819.1469928-5-hch@lst.de
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c
+index a4f7c101b53b..68227240fdea 100644
+--- a/block/blk-mq-sched.c
++++ b/block/blk-mq-sched.c
+@@ -555,6 +555,7 @@ static int blk_mq_init_sched_shared_tags(struct request_queue *queue)
+ 	return 0;
+ }
+ 
++/* caller must have a reference to @e, will grab another one if successful */
+ int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e)
+ {
+ 	unsigned int flags = q->tag_set->flags;
+diff --git a/block/blk-mq.c b/block/blk-mq.c
+index 9db8814cdd02..098432d3caf1 100644
+--- a/block/blk-mq.c
++++ b/block/blk-mq.c
+@@ -4591,6 +4591,8 @@ static void blk_mq_elv_switch_back(struct list_head *head,
+ 
+ 	mutex_lock(&q->sysfs_lock);
+ 	elevator_switch(q, t);
++	/* drop the reference acquired in blk_mq_elv_switch_none */
++	elevator_put(t);
+ 	mutex_unlock(&q->sysfs_lock);
+ }
+ 
+diff --git a/block/elevator.c b/block/elevator.c
+index 61d5655a3819..d26aa787e29f 100644
+--- a/block/elevator.c
++++ b/block/elevator.c
+@@ -165,6 +165,7 @@ struct elevator_queue *elevator_alloc(struct request_queue *q,
+ 	if (unlikely(!eq))
+ 		return NULL;
+ 
++	__elevator_get(e);
+ 	eq->type = e;
+ 	kobject_init(&eq->kobj, &elv_ktype);
+ 	mutex_init(&eq->sysfs_lock);
+@@ -704,8 +705,9 @@ void elevator_init_mq(struct request_queue *q)
+ 	if (err) {
+ 		pr_warn("\"%s\" elevator initialization failed, "
+ 			"falling back to \"none\"\n", e->elevator_name);
+-		elevator_put(e);
+ 	}
++
++	elevator_put(e);
+ }
+ 
+ /*
+@@ -737,6 +739,7 @@ int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
+ static int elevator_change(struct request_queue *q, const char *elevator_name)
+ {
+ 	struct elevator_type *e;
++	int ret;
+ 
+ 	/* Make sure queue is not in the middle of being removed */
+ 	if (!blk_queue_registered(q))
+@@ -757,8 +760,9 @@ static int elevator_change(struct request_queue *q, const char *elevator_name)
+ 	e = elevator_get(q, elevator_name, true);
+ 	if (!e)
+ 		return -EINVAL;
+-
+-	return elevator_switch(q, e);
++	ret = elevator_switch(q, e);
++	elevator_put(e);
++	return ret;
+ }
+ 
+ ssize_t elv_iosched_store(struct request_queue *q, const char *buf,

commit b54c2ad9b77de846e42104ecf94eb8329d2f03a3
+Author: Jinlong Chen 
+Date:   Thu Oct 20 08:48:18 2022 +0200
+
+    block: check for an unchanged elevator earlier in __elevator_change
+    
+    No need to find the actual elevator_type struct for this comparism,
+    the name is all that is needed.
+    
+    Signed-off-by: Jinlong Chen 
+    [hch: split from a larger patch]
+    Signed-off-by: Christoph Hellwig 
+    Link: https://lore.kernel.org/r/20221020064819.1469928-4-hch@lst.de
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/elevator.c b/block/elevator.c
+index 5b8fb8745e9a..61d5655a3819 100644
+--- a/block/elevator.c
++++ b/block/elevator.c
+@@ -751,16 +751,13 @@ static int elevator_change(struct request_queue *q, const char *elevator_name)
+ 		return elevator_switch(q, NULL);
+ 	}
+ 
++	if (q->elevator && elevator_match(q->elevator->type, elevator_name, 0))
++		return 0;
++
+ 	e = elevator_get(q, elevator_name, true);
+ 	if (!e)
+ 		return -EINVAL;
+ 
+-	if (q->elevator &&
+-	    elevator_match(q->elevator->type, elevator_name, 0)) {
+-		elevator_put(e);
+-		return 0;
+-	}
+-
+ 	return elevator_switch(q, e);
+ }
+ 

commit 175302f6b79ebbb207c2d58d6d3e679465de23b0
+Author: Duoming Zhou 
+Date:   Sun Oct 9 14:37:31 2022 +0800
+
+    mISDN: hfcpci: Fix use-after-free bug in hfcpci_softirq
+    
+    The function hfcpci_softirq() is a timer handler. If it
+    is running, the timer_pending() will return 0 and the
+    del_timer_sync() in HFC_cleanup() will not be executed.
+    As a result, the use-after-free bug will happen. The
+    process is shown below:
+    
+        (cleanup routine)          |        (timer handler)
+    HFC_cleanup()                  | hfcpci_softirq()
+     if (timer_pending(&hfc_tl))   |
+       del_timer_sync()            |
+     ...                           | ...
+     pci_unregister_driver(hc)     |
+      driver_unregister            |  driver_for_each_device
+       bus_remove_driver           |   _hfcpci_softirq
+        driver_detach              |   ...
+         put_device(dev) //[1]FREE |
+                                   |    dev_get_drvdata(dev) //[2]USE
+    
+    The device is deallocated is position [1] and used in
+    position [2].
+    
+    Fix by removing the "timer_pending" check in HFC_cleanup(),
+    which makes sure that the hfcpci_softirq() have finished
+    before the resource is deallocated.
+    
+    Fixes: 009fc857c5f6 ("mISDN: fix possible use-after-free in HFC_cleanup()")
+    Signed-off-by: Duoming Zhou 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
+index af17459c1a5c..e964a8dd8512 100644
+--- a/drivers/isdn/hardware/mISDN/hfcpci.c
++++ b/drivers/isdn/hardware/mISDN/hfcpci.c
+@@ -2345,8 +2345,7 @@ HFC_init(void)
+ static void __exit
+ HFC_cleanup(void)
+ {
+-	if (timer_pending(&hfc_tl))
+-		del_timer_sync(&hfc_tl);
++	del_timer_sync(&hfc_tl);
+ 
+ 	pci_unregister_driver(&hfc_driver);
+ }

commit 2568a7e0832ee30b0a351016d03062ab4e0e0a3f
+Author: Duoming Zhou 
+Date:   Wed Sep 28 21:39:38 2022 +0800
+
+    mISDN: fix use-after-free bugs in l1oip timer handlers
+    
+    The l1oip_cleanup() traverses the l1oip_ilist and calls
+    release_card() to cleanup module and stack. However,
+    release_card() calls del_timer() to delete the timers
+    such as keep_tl and timeout_tl. If the timer handler is
+    running, the del_timer() will not stop it and result in
+    UAF bugs. One of the processes is shown below:
+    
+        (cleanup routine)          |        (timer handler)
+    release_card()                 | l1oip_timeout()
+     ...                           |
+     del_timer()                   | ...
+     ...                           |
+     kfree(hc) //FREE              |
+                                   | hc->timeout_on = 0 //USE
+    
+    Fix by calling del_timer_sync() in release_card(), which
+    makes sure the timer handlers have finished before the
+    resources, such as l1oip and so on, have been deallocated.
+    
+    What's more, the hc->workq and hc->socket_thread can kick
+    those timers right back in. We add a bool flag to show
+    if card is released. Then, check this flag in hc->workq
+    and hc->socket_thread.
+    
+    Fixes: 3712b42d4b1b ("Add layer1 over IP support")
+    Signed-off-by: Duoming Zhou 
+    Reviewed-by: Leon Romanovsky 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/isdn/mISDN/l1oip.h b/drivers/isdn/mISDN/l1oip.h
+index 7ea10db20e3a..48133d022812 100644
+--- a/drivers/isdn/mISDN/l1oip.h
++++ b/drivers/isdn/mISDN/l1oip.h
+@@ -59,6 +59,7 @@ struct l1oip {
+ 	int			bundle;		/* bundle channels in one frm */
+ 	int			codec;		/* codec to use for transmis. */
+ 	int			limit;		/* limit number of bchannels */
++	bool			shutdown;	/* if card is released */
+ 
+ 	/* timer */
+ 	struct timer_list	keep_tl;
+diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c
+index 2c40412466e6..a77195e378b7 100644
+--- a/drivers/isdn/mISDN/l1oip_core.c
++++ b/drivers/isdn/mISDN/l1oip_core.c
+@@ -275,7 +275,7 @@ l1oip_socket_send(struct l1oip *hc, u8 localcodec, u8 channel, u32 chanmask,
+ 	p = frame;
+ 
+ 	/* restart timer */
+-	if (time_before(hc->keep_tl.expires, jiffies + 5 * HZ))
++	if (time_before(hc->keep_tl.expires, jiffies + 5 * HZ) && !hc->shutdown)
+ 		mod_timer(&hc->keep_tl, jiffies + L1OIP_KEEPALIVE * HZ);
+ 	else
+ 		hc->keep_tl.expires = jiffies + L1OIP_KEEPALIVE * HZ;
+@@ -601,7 +601,9 @@ l1oip_socket_parse(struct l1oip *hc, struct sockaddr_in *sin, u8 *buf, int len)
+ 		goto multiframe;
+ 
+ 	/* restart timer */
+-	if (time_before(hc->timeout_tl.expires, jiffies + 5 * HZ) || !hc->timeout_on) {
++	if ((time_before(hc->timeout_tl.expires, jiffies + 5 * HZ) ||
++	     !hc->timeout_on) &&
++	    !hc->shutdown) {
+ 		hc->timeout_on = 1;
+ 		mod_timer(&hc->timeout_tl, jiffies + L1OIP_TIMEOUT * HZ);
+ 	} else /* only adjust timer */
+@@ -1232,11 +1234,10 @@ release_card(struct l1oip *hc)
+ {
+ 	int	ch;
+ 
+-	if (timer_pending(&hc->keep_tl))
+-		del_timer(&hc->keep_tl);
++	hc->shutdown = true;
+ 
+-	if (timer_pending(&hc->timeout_tl))
+-		del_timer(&hc->timeout_tl);
++	del_timer_sync(&hc->keep_tl);
++	del_timer_sync(&hc->timeout_tl);
+ 
+ 	cancel_work_sync(&hc->workq);
+ 

commit 46ba53c30666717cb06c2b3c5d896301cd00d0c0
+Author: Duoming Zhou 
+Date:   Tue Sep 20 22:42:13 2022 +0800
+
+    scsi: libsas: Fix use-after-free bug in smp_execute_task_sg()
+    
+    When executing SMP task failed, the smp_execute_task_sg() calls del_timer()
+    to delete "slow_task->timer". However, if the timer handler
+    sas_task_internal_timedout() is running, the del_timer() in
+    smp_execute_task_sg() will not stop it and a UAF will happen. The process
+    is shown below:
+    
+          (thread 1)               |        (thread 2)
+    smp_execute_task_sg()          | sas_task_internal_timedout()
+     ...                           |
+     del_timer()                   |
+     ...                           |  ...
+     sas_free_task(task)           |
+      kfree(task->slow_task) //FREE|
+                                   |  task->slow_task->... //USE
+    
+    Fix by calling del_timer_sync() in smp_execute_task_sg(), which makes sure
+    the timer handler have finished before the "task->slow_task" is
+    deallocated.
+    
+    Link: https://lore.kernel.org/r/20220920144213.10536-1-duoming@zju.edu.cn
+    Fixes: 2908d778ab3e ("[SCSI] aic94xx: new driver")
+    Reviewed-by: Jason Yan 
+    Signed-off-by: Duoming Zhou 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
+index fa2209080cc2..5ce251830104 100644
+--- a/drivers/scsi/libsas/sas_expander.c
++++ b/drivers/scsi/libsas/sas_expander.c
+@@ -67,7 +67,7 @@ static int smp_execute_task_sg(struct domain_device *dev,
+ 		res = i->dft->lldd_execute_task(task, GFP_KERNEL);
+ 
+ 		if (res) {
+-			del_timer(&task->slow_task->timer);
++			del_timer_sync(&task->slow_task->timer);
+ 			pr_notice("executing SMP task failed:%d\n", res);
+ 			break;
+ 		}

commit 551e4745c7f218da7070b36a06318592913676ff
+Author: Duoming Zhou 
+Date:   Tue Aug 23 19:21:27 2022 +0800
+
+    mwifiex: fix sleep in atomic context bugs caused by dev_coredumpv
+    
+    There are sleep in atomic context bugs when uploading device dump
+    data in mwifiex. The root cause is that dev_coredumpv could not
+    be used in atomic contexts, because it calls dev_set_name which
+    include operations that may sleep. The call tree shows execution
+    paths that could lead to bugs:
+    
+       (Interrupt context)
+    fw_dump_timer_fn
+      mwifiex_upload_device_dump
+        dev_coredumpv(..., GFP_KERNEL)
+          dev_coredumpm()
+            kzalloc(sizeof(*devcd), gfp); //may sleep
+            dev_set_name
+              kobject_set_name_vargs
+                kvasprintf_const(GFP_KERNEL, ...); //may sleep
+                kstrdup(s, GFP_KERNEL); //may sleep
+    
+    The corresponding fail log is shown below:
+    
+    [  135.275938] usb 1-1: == mwifiex dump information to /sys/class/devcoredump start
+    [  135.281029] BUG: sleeping function called from invalid context at include/linux/sched/mm.h:265
+    ...
+    [  135.293613] Call Trace:
+    [  135.293613]  
+    [  135.293613]  dump_stack_lvl+0x57/0x7d
+    [  135.293613]  __might_resched.cold+0x138/0x173
+    [  135.293613]  ? dev_coredumpm+0xca/0x2e0
+    [  135.293613]  kmem_cache_alloc_trace+0x189/0x1f0
+    [  135.293613]  ? devcd_match_failing+0x30/0x30
+    [  135.293613]  dev_coredumpm+0xca/0x2e0
+    [  135.293613]  ? devcd_freev+0x10/0x10
+    [  135.293613]  dev_coredumpv+0x1c/0x20
+    [  135.293613]  ? devcd_match_failing+0x30/0x30
+    [  135.293613]  mwifiex_upload_device_dump+0x65/0xb0
+    [  135.293613]  ? mwifiex_dnld_fw+0x1b0/0x1b0
+    [  135.293613]  call_timer_fn+0x122/0x3d0
+    [  135.293613]  ? msleep_interruptible+0xb0/0xb0
+    [  135.293613]  ? lock_downgrade+0x3c0/0x3c0
+    [  135.293613]  ? __next_timer_interrupt+0x13c/0x160
+    [  135.293613]  ? lockdep_hardirqs_on_prepare+0xe/0x220
+    [  135.293613]  ? mwifiex_dnld_fw+0x1b0/0x1b0
+    [  135.293613]  __run_timers.part.0+0x3f8/0x540
+    [  135.293613]  ? call_timer_fn+0x3d0/0x3d0
+    [  135.293613]  ? arch_restore_msi_irqs+0x10/0x10
+    [  135.293613]  ? lapic_next_event+0x31/0x40
+    [  135.293613]  run_timer_softirq+0x4f/0xb0
+    [  135.293613]  __do_softirq+0x1c2/0x651
+    ...
+    [  135.293613] RIP: 0010:default_idle+0xb/0x10
+    [  135.293613] RSP: 0018:ffff888006317e68 EFLAGS: 00000246
+    [  135.293613] RAX: ffffffff82ad8d10 RBX: ffff888006301cc0 RCX: ffffffff82ac90e1
+    [  135.293613] RDX: ffffed100d9ff1b4 RSI: ffffffff831ad140 RDI: ffffffff82ad8f20
+    [  135.293613] RBP: 0000000000000003 R08: 0000000000000000 R09: ffff88806cff8d9b
+    [  135.293613] R10: ffffed100d9ff1b3 R11: 0000000000000001 R12: ffffffff84593410
+    [  135.293613] R13: 0000000000000000 R14: 0000000000000000 R15: 1ffff11000c62fd2
+    ...
+    [  135.389205] usb 1-1: == mwifiex dump information to /sys/class/devcoredump end
+    
+    This patch uses delayed work to replace timer and moves the operations
+    that may sleep into a delayed work in order to mitigate bugs, it was
+    tested on Marvell 88W8801 chip whose port is usb and the firmware is
+    usb8801_uapsta.bin. The following is the result after using delayed
+    work to replace timer.
+    
+    [  134.936453] usb 1-1: == mwifiex dump information to /sys/class/devcoredump start
+    [  135.043344] usb 1-1: == mwifiex dump information to /sys/class/devcoredump end
+    
+    As we can see, there is no bug now.
+    
+    Fixes: f5ecd02a8b20 ("mwifiex: device dump support for usb interface")
+    Signed-off-by: Duoming Zhou 
+    Reviewed-by: Brian Norris 
+    Acked-by: Greg Kroah-Hartman 
+    Signed-off-by: Kalle Valo 
+    Link: https://lore.kernel.org/r/5cfa5c473ff6d069cb67760ffa04a2f84ef450a8.1661252818.git.duoming@zju.edu.cn
+
+diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
+index fc77489cc511..7dddb4b5dea1 100644
+--- a/drivers/net/wireless/marvell/mwifiex/init.c
++++ b/drivers/net/wireless/marvell/mwifiex/init.c
+@@ -51,9 +51,10 @@ static void wakeup_timer_fn(struct timer_list *t)
+ 		adapter->if_ops.card_reset(adapter);
+ }
+ 
+-static void fw_dump_timer_fn(struct timer_list *t)
++static void fw_dump_work(struct work_struct *work)
+ {
+-	struct mwifiex_adapter *adapter = from_timer(adapter, t, devdump_timer);
++	struct mwifiex_adapter *adapter =
++		container_of(work, struct mwifiex_adapter, devdump_work.work);
+ 
+ 	mwifiex_upload_device_dump(adapter);
+ }
+@@ -309,7 +310,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
+ 	adapter->active_scan_triggered = false;
+ 	timer_setup(&adapter->wakeup_timer, wakeup_timer_fn, 0);
+ 	adapter->devdump_len = 0;
+-	timer_setup(&adapter->devdump_timer, fw_dump_timer_fn, 0);
++	INIT_DELAYED_WORK(&adapter->devdump_work, fw_dump_work);
+ }
+ 
+ /*
+@@ -388,7 +389,7 @@ static void
+ mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
+ {
+ 	del_timer(&adapter->wakeup_timer);
+-	del_timer_sync(&adapter->devdump_timer);
++	cancel_delayed_work_sync(&adapter->devdump_work);
+ 	mwifiex_cancel_all_pending_cmd(adapter);
+ 	wake_up_interruptible(&adapter->cmd_wait_q.wait);
+ 	wake_up_interruptible(&adapter->hs_activate_wait_q);
+diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
+index 87729d251fed..63f861e6b28a 100644
+--- a/drivers/net/wireless/marvell/mwifiex/main.h
++++ b/drivers/net/wireless/marvell/mwifiex/main.h
+@@ -37,6 +37,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include "decl.h"
+ #include "ioctl.h"
+@@ -1043,7 +1044,7 @@ struct mwifiex_adapter {
+ 	/* Device dump data/length */
+ 	void *devdump_data;
+ 	int devdump_len;
+-	struct timer_list devdump_timer;
++	struct delayed_work devdump_work;
+ 
+ 	bool ignore_btcoex_events;
+ };
+diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c
+index b6315fccd1bb..df9cdd10a494 100644
+--- a/drivers/net/wireless/marvell/mwifiex/sta_event.c
++++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c
+@@ -611,8 +611,8 @@ mwifiex_fw_dump_info_event(struct mwifiex_private *priv,
+ 		 * transmission event get lost, in this cornel case,
+ 		 * user would still get partial of the dump.
+ 		 */
+-		mod_timer(&adapter->devdump_timer,
+-			  jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
++		schedule_delayed_work(&adapter->devdump_work,
++				      msecs_to_jiffies(MWIFIEX_TIMER_10S));
+ 	}
+ 
+ 	/* Overflow check */
+@@ -631,7 +631,7 @@ mwifiex_fw_dump_info_event(struct mwifiex_private *priv,
+ 	return;
+ 
+ upload_dump:
+-	del_timer_sync(&adapter->devdump_timer);
++	cancel_delayed_work_sync(&adapter->devdump_work);
+ 	mwifiex_upload_device_dump(adapter);
+ }
+ 

commit c0955bf957be4bead01fae1d791476260da7325d
+Author: Duoming Zhou 
+Date:   Sat Aug 27 23:38:15 2022 +0800
+
+    ethernet: rocker: fix sleep in atomic context bug in neigh_timer_handler
+    
+    The function neigh_timer_handler() is a timer handler that runs in an
+    atomic context. When used by rocker, neigh_timer_handler() calls
+    "kzalloc(.., GFP_KERNEL)" that may sleep. As a result, the sleep in
+    atomic context bug will happen. One of the processes is shown below:
+    
+    ofdpa_fib4_add()
+     ...
+     neigh_add_timer()
+    
+    (wait a timer)
+    
+    neigh_timer_handler()
+     neigh_release()
+      neigh_destroy()
+       rocker_port_neigh_destroy()
+        rocker_world_port_neigh_destroy()
+         ofdpa_port_neigh_destroy()
+          ofdpa_port_ipv4_neigh()
+           kzalloc(sizeof(.., GFP_KERNEL) //may sleep
+    
+    This patch changes the gfp_t parameter of kzalloc() from GFP_KERNEL to
+    GFP_ATOMIC in order to mitigate the bug.
+    
+    Fixes: 00fc0c51e35b ("rocker: Change world_ops API and implementation to be switchdev independant")
+    Signed-off-by: Duoming Zhou 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/rocker/rocker_ofdpa.c b/drivers/net/ethernet/rocker/rocker_ofdpa.c
+index bc70c6abd6a5..58cf7cc54f40 100644
+--- a/drivers/net/ethernet/rocker/rocker_ofdpa.c
++++ b/drivers/net/ethernet/rocker/rocker_ofdpa.c
+@@ -1273,7 +1273,7 @@ static int ofdpa_port_ipv4_neigh(struct ofdpa_port *ofdpa_port,
+ 	bool removing;
+ 	int err = 0;
+ 
+-	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
++	entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
+ 	if (!entry)
+ 		return -ENOMEM;
+ 

commit afe7116f6d3b888778ed6d95e3cf724767b9aedf
+Author: Lin Ma 
+Date:   Mon Aug 8 11:42:24 2022 +0800
+
+    ieee802154/adf7242: defer destroy_workqueue call
+    
+    There is a possible race condition (use-after-free) like below
+    
+      (FREE)                     |  (USE)
+      adf7242_remove             |  adf7242_channel
+       cancel_delayed_work_sync  |
+        destroy_workqueue (1)    |   adf7242_cmd_rx
+                                 |    mod_delayed_work (2)
+                                 |
+    
+    The root cause for this race is that the upper layer (ieee802154) is
+    unaware of this detaching event and the function adf7242_channel can
+    be called without any checks.
+    
+    To fix this, we can add a flag write at the beginning of adf7242_remove
+    and add flag check in adf7242_channel. Or we can just defer the
+    destructive operation like other commit 3e0588c291d6 ("hamradio: defer
+    ax25 kfree after unregister_netdev") which let the
+    ieee802154_unregister_hw() to handle the synchronization. This patch
+    takes the second option.
+    
+    Fixes: 58e9683d1475 ("net: ieee802154: adf7242: Fix OCL calibration
+    runs")
+    Signed-off-by: Lin Ma 
+    Acked-by: Michael Hennerich 
+    Link: https://lore.kernel.org/r/20220808034224.12642-1-linma@zju.edu.cn
+    Signed-off-by: Stefan Schmidt 
+
+diff --git a/drivers/net/ieee802154/adf7242.c b/drivers/net/ieee802154/adf7242.c
+index 6afdf1622944..5cf218c674a5 100644
+--- a/drivers/net/ieee802154/adf7242.c
++++ b/drivers/net/ieee802154/adf7242.c
+@@ -1310,10 +1310,11 @@ static void adf7242_remove(struct spi_device *spi)
+ 
+ 	debugfs_remove_recursive(lp->debugfs_root);
+ 
++	ieee802154_unregister_hw(lp->hw);
++
+ 	cancel_delayed_work_sync(&lp->work);
+ 	destroy_workqueue(lp->wqueue);
+ 
+-	ieee802154_unregister_hw(lp->hw);
+ 	mutex_destroy(&lp->bmux);
+ 	ieee802154_free_hw(lp->hw);
+ }

commit f1e941dbf80a9b8bab0bffbc4cbe41cc7f4c6fb6
+Author: Duoming Zhou 
+Date:   Thu Aug 18 17:06:21 2022 +0800
+
+    nfc: pn533: Fix use-after-free bugs caused by pn532_cmd_timeout
+    
+    When the pn532 uart device is detaching, the pn532_uart_remove()
+    is called. But there are no functions in pn532_uart_remove() that
+    could delete the cmd_timeout timer, which will cause use-after-free
+    bugs. The process is shown below:
+    
+        (thread 1)                  |        (thread 2)
+                                    |  pn532_uart_send_frame
+    pn532_uart_remove               |    mod_timer(&pn532->cmd_timeout,...)
+      ...                           |    (wait a time)
+      kfree(pn532) //FREE           |    pn532_cmd_timeout
+                                    |      pn532_uart_send_frame
+                                    |        pn532->... //USE
+    
+    This patch adds del_timer_sync() in pn532_uart_remove() in order to
+    prevent the use-after-free bugs. What's more, the pn53x_unregister_nfc()
+    is well synchronized, it sets nfc_dev->shutting_down to true and there
+    are no syscalls could restart the cmd_timeout timer.
+    
+    Fixes: c656aa4c27b1 ("nfc: pn533: add UART phy driver")
+    Signed-off-by: Duoming Zhou 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/nfc/pn533/uart.c b/drivers/nfc/pn533/uart.c
+index 2caf997f9bc9..07596bf5f7d6 100644
+--- a/drivers/nfc/pn533/uart.c
++++ b/drivers/nfc/pn533/uart.c
+@@ -310,6 +310,7 @@ static void pn532_uart_remove(struct serdev_device *serdev)
+ 	pn53x_unregister_nfc(pn532->priv);
+ 	serdev_device_close(serdev);
+ 	pn53x_common_clean(pn532->priv);
++	del_timer_sync(&pn532->cmd_timeout);
+ 	kfree_skb(pn532->recv_skb);
+ 	kfree(pn532);
+ }

commit 6faee3d4ee8be0f0367d0c3d826afb3571b7a5e0
+Author: Lin Ma 
+Date:   Wed Aug 17 11:49:21 2022 -0700
+
+    igb: Add lock to avoid data race
+    
+    The commit c23d92b80e0b ("igb: Teardown SR-IOV before
+    unregister_netdev()") places the unregister_netdev() call after the
+    igb_disable_sriov() call to avoid functionality issue.
+    
+    However, it introduces several race conditions when detaching a device.
+    For example, when .remove() is called, the below interleaving leads to
+    use-after-free.
+    
+     (FREE from device detaching)      |   (USE from netdev core)
+    igb_remove                         |  igb_ndo_get_vf_config
+     igb_disable_sriov                 |  vf >= adapter->vfs_allocated_count?
+      kfree(adapter->vf_data)          |
+      adapter->vfs_allocated_count = 0 |
+                                       |    memcpy(... adapter->vf_data[vf]
+    
+    Moreover, the igb_disable_sriov() also suffers from data race with the
+    requests from VF driver.
+    
+     (FREE from device detaching)      |   (USE from requests)
+    igb_remove                         |  igb_msix_other
+     igb_disable_sriov                 |   igb_msg_task
+      kfree(adapter->vf_data)          |    vf < adapter->vfs_allocated_count
+      adapter->vfs_allocated_count = 0 |
+    
+    To this end, this commit first eliminates the data races from netdev
+    core by using rtnl_lock (similar to commit 719479230893 ("dpaa2-eth: add
+    MAC/PHY support through phylink")). And then adds a spinlock to
+    eliminate races from driver requests. (similar to commit 1e53834ce541
+    ("ixgbe: Add locking to prevent panic when setting sriov_numvfs to zero")
+    
+    Fixes: c23d92b80e0b ("igb: Teardown SR-IOV before unregister_netdev()")
+    Signed-off-by: Lin Ma 
+    Tested-by: Konrad Jankowski 
+    Signed-off-by: Tony Nguyen 
+    Link: https://lore.kernel.org/r/20220817184921.735244-1-anthony.l.nguyen@intel.com
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
+index 2d3daf022651..015b78144114 100644
+--- a/drivers/net/ethernet/intel/igb/igb.h
++++ b/drivers/net/ethernet/intel/igb/igb.h
+@@ -664,6 +664,8 @@ struct igb_adapter {
+ 	struct igb_mac_addr *mac_table;
+ 	struct vf_mac_filter vf_macs;
+ 	struct vf_mac_filter *vf_mac_list;
++	/* lock for VF resources */
++	spinlock_t vfs_lock;
+ };
+ 
+ /* flags controlling PTP/1588 function */
+diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
+index d8b836a85cc3..2796e81d2726 100644
+--- a/drivers/net/ethernet/intel/igb/igb_main.c
++++ b/drivers/net/ethernet/intel/igb/igb_main.c
+@@ -3637,6 +3637,7 @@ static int igb_disable_sriov(struct pci_dev *pdev)
+ 	struct net_device *netdev = pci_get_drvdata(pdev);
+ 	struct igb_adapter *adapter = netdev_priv(netdev);
+ 	struct e1000_hw *hw = &adapter->hw;
++	unsigned long flags;
+ 
+ 	/* reclaim resources allocated to VFs */
+ 	if (adapter->vf_data) {
+@@ -3649,12 +3650,13 @@ static int igb_disable_sriov(struct pci_dev *pdev)
+ 			pci_disable_sriov(pdev);
+ 			msleep(500);
+ 		}
+-
++		spin_lock_irqsave(&adapter->vfs_lock, flags);
+ 		kfree(adapter->vf_mac_list);
+ 		adapter->vf_mac_list = NULL;
+ 		kfree(adapter->vf_data);
+ 		adapter->vf_data = NULL;
+ 		adapter->vfs_allocated_count = 0;
++		spin_unlock_irqrestore(&adapter->vfs_lock, flags);
+ 		wr32(E1000_IOVCTL, E1000_IOVCTL_REUSE_VFQ);
+ 		wrfl();
+ 		msleep(100);
+@@ -3814,7 +3816,9 @@ static void igb_remove(struct pci_dev *pdev)
+ 	igb_release_hw_control(adapter);
+ 
+ #ifdef CONFIG_PCI_IOV
++	rtnl_lock();
+ 	igb_disable_sriov(pdev);
++	rtnl_unlock();
+ #endif
+ 
+ 	unregister_netdev(netdev);
+@@ -3974,6 +3978,9 @@ static int igb_sw_init(struct igb_adapter *adapter)
+ 
+ 	spin_lock_init(&adapter->nfc_lock);
+ 	spin_lock_init(&adapter->stats64_lock);
++
++	/* init spinlock to avoid concurrency of VF resources */
++	spin_lock_init(&adapter->vfs_lock);
+ #ifdef CONFIG_PCI_IOV
+ 	switch (hw->mac.type) {
+ 	case e1000_82576:
+@@ -7958,8 +7965,10 @@ static void igb_rcv_msg_from_vf(struct igb_adapter *adapter, u32 vf)
+ static void igb_msg_task(struct igb_adapter *adapter)
+ {
+ 	struct e1000_hw *hw = &adapter->hw;
++	unsigned long flags;
+ 	u32 vf;
+ 
++	spin_lock_irqsave(&adapter->vfs_lock, flags);
+ 	for (vf = 0; vf < adapter->vfs_allocated_count; vf++) {
+ 		/* process any reset requests */
+ 		if (!igb_check_for_rst(hw, vf))
+@@ -7973,6 +7982,7 @@ static void igb_msg_task(struct igb_adapter *adapter)
+ 		if (!igb_check_for_ack(hw, vf))
+ 			igb_rcv_ack_from_vf(adapter, vf);
+ 	}
++	spin_unlock_irqrestore(&adapter->vfs_lock, flags);
+ }
+ 
+ /**

commit 3f4093e2bf4673f218c0bf17d8362337c400e77b
+Author: Duoming Zhou 
+Date:   Fri Aug 5 15:00:08 2022 +0800
+
+    atm: idt77252: fix use-after-free bugs caused by tst_timer
+    
+    There are use-after-free bugs caused by tst_timer. The root cause
+    is that there are no functions to stop tst_timer in idt77252_exit().
+    One of the possible race conditions is shown below:
+    
+        (thread 1)          |        (thread 2)
+                            |  idt77252_init_one
+                            |    init_card
+                            |      fill_tst
+                            |        mod_timer(&card->tst_timer, ...)
+    idt77252_exit           |  (wait a time)
+                            |  tst_timer
+                            |
+                            |    ...
+      kfree(card) // FREE   |
+                            |    card->soft_tst[e] // USE
+    
+    The idt77252_dev is deallocated in idt77252_exit() and used in
+    timer handler.
+    
+    This patch adds del_timer_sync() in idt77252_exit() in order that
+    the timer handler could be stopped before the idt77252_dev is
+    deallocated.
+    
+    Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+    Signed-off-by: Duoming Zhou 
+    Link: https://lore.kernel.org/r/20220805070008.18007-1-duoming@zju.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
+index 81ce81a75fc6..681cb3786794 100644
+--- a/drivers/atm/idt77252.c
++++ b/drivers/atm/idt77252.c
+@@ -3752,6 +3752,7 @@ static void __exit idt77252_exit(void)
+ 		card = idt77252_chain;
+ 		dev = card->atmdev;
+ 		idt77252_chain = card->next;
++		del_timer_sync(&card->tst_timer);
+ 
+ 		if (dev->phy->stop)
+ 			dev->phy->stop(dev);

commit b89fc26f741d9f9efb51cba3e9b241cf1380ec5a
+Author: Duoming Zhou 
+Date:   Sat Jul 23 09:58:09 2022 +0800
+
+    sctp: fix sleep in atomic context bug in timer handlers
+    
+    There are sleep in atomic context bugs in timer handlers of sctp
+    such as sctp_generate_t3_rtx_event(), sctp_generate_probe_event(),
+    sctp_generate_t1_init_event(), sctp_generate_timeout_event(),
+    sctp_generate_t3_rtx_event() and so on.
+    
+    The root cause is sctp_sched_prio_init_sid() with GFP_KERNEL parameter
+    that may sleep could be called by different timer handlers which is in
+    interrupt context.
+    
+    One of the call paths that could trigger bug is shown below:
+    
+          (interrupt context)
+    sctp_generate_probe_event
+      sctp_do_sm
+        sctp_side_effects
+          sctp_cmd_interpreter
+            sctp_outq_teardown
+              sctp_outq_init
+                sctp_sched_set_sched
+                  n->init_sid(..,GFP_KERNEL)
+                    sctp_sched_prio_init_sid //may sleep
+    
+    This patch changes gfp_t parameter of init_sid in sctp_sched_set_sched()
+    from GFP_KERNEL to GFP_ATOMIC in order to prevent sleep in atomic
+    context bugs.
+    
+    Fixes: 5bbbbe32a431 ("sctp: introduce stream scheduler foundations")
+    Signed-off-by: Duoming Zhou 
+    Acked-by: Marcelo Ricardo Leitner 
+    Link: https://lore.kernel.org/r/20220723015809.11553-1-duoming@zju.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/net/sctp/stream_sched.c b/net/sctp/stream_sched.c
+index 518b1b9bf89d..1ad565ed5627 100644
+--- a/net/sctp/stream_sched.c
++++ b/net/sctp/stream_sched.c
+@@ -160,7 +160,7 @@ int sctp_sched_set_sched(struct sctp_association *asoc,
+ 		if (!SCTP_SO(&asoc->stream, i)->ext)
+ 			continue;
+ 
+-		ret = n->init_sid(&asoc->stream, i, GFP_KERNEL);
++		ret = n->init_sid(&asoc->stream, i, GFP_ATOMIC);
+ 		if (ret)
+ 			goto err;
+ 	}

commit 6a0c054930d554ad8f8044ef1fc856d9da391c81
+Author: Duoming Zhou 
+Date:   Sun Jul 10 18:30:02 2022 +0800
+
+    staging: rtl8192u: Fix sleep in atomic context bug in dm_fsync_timer_callback
+    
+    There are sleep in atomic context bugs when dm_fsync_timer_callback is
+    executing. The root cause is that the memory allocation functions with
+    GFP_KERNEL or GFP_NOIO parameters are called in dm_fsync_timer_callback
+    which is a timer handler. The call paths that could trigger bugs are
+    shown below:
+    
+        (interrupt context)
+    dm_fsync_timer_callback
+      write_nic_byte
+        kzalloc(sizeof(data), GFP_KERNEL); //may sleep
+        usb_control_msg
+          kmalloc(.., GFP_NOIO); //may sleep
+      write_nic_dword
+        kzalloc(sizeof(data), GFP_KERNEL); //may sleep
+        usb_control_msg
+          kmalloc(.., GFP_NOIO); //may sleep
+    
+    This patch uses delayed work to replace timer and moves the operations
+    that may sleep into the delayed work in order to mitigate bugs.
+    
+    Fixes: 8fc8598e61f6 ("Staging: Added Realtek rtl8192u driver to staging")
+    Signed-off-by: Duoming Zhou 
+    Link: https://lore.kernel.org/r/20220710103002.63283-1-duoming@zju.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8192u/r8192U.h b/drivers/staging/rtl8192u/r8192U.h
+index 14ca00a2789b..1942cb849374 100644
+--- a/drivers/staging/rtl8192u/r8192U.h
++++ b/drivers/staging/rtl8192u/r8192U.h
+@@ -1013,7 +1013,7 @@ typedef struct r8192_priv {
+ 	bool		bis_any_nonbepkts;
+ 	bool		bcurrent_turbo_EDCA;
+ 	bool		bis_cur_rdlstate;
+-	struct timer_list fsync_timer;
++	struct delayed_work fsync_work;
+ 	bool bfsync_processing;	/* 500ms Fsync timer is active or not */
+ 	u32	rate_record;
+ 	u32	rateCountDiffRecord;
+diff --git a/drivers/staging/rtl8192u/r8192U_dm.c b/drivers/staging/rtl8192u/r8192U_dm.c
+index 916618ddc4b7..00fc8fd344db 100644
+--- a/drivers/staging/rtl8192u/r8192U_dm.c
++++ b/drivers/staging/rtl8192u/r8192U_dm.c
+@@ -2578,19 +2578,20 @@ static void dm_init_fsync(struct net_device *dev)
+ 	priv->ieee80211->fsync_seconddiff_ratethreshold = 200;
+ 	priv->ieee80211->fsync_state = Default_Fsync;
+ 	priv->framesyncMonitor = 1;	/* current default 0xc38 monitor on */
+-	timer_setup(&priv->fsync_timer, dm_fsync_timer_callback, 0);
++	INIT_DELAYED_WORK(&priv->fsync_work, dm_fsync_work_callback);
+ }
+ 
+ static void dm_deInit_fsync(struct net_device *dev)
+ {
+ 	struct r8192_priv *priv = ieee80211_priv(dev);
+ 
+-	del_timer_sync(&priv->fsync_timer);
++	cancel_delayed_work_sync(&priv->fsync_work);
+ }
+ 
+-void dm_fsync_timer_callback(struct timer_list *t)
++void dm_fsync_work_callback(struct work_struct *work)
+ {
+-	struct r8192_priv *priv = from_timer(priv, t, fsync_timer);
++	struct r8192_priv *priv =
++	    container_of(work, struct r8192_priv, fsync_work.work);
+ 	struct net_device *dev = priv->ieee80211->dev;
+ 	u32 rate_index, rate_count = 0, rate_count_diff = 0;
+ 	bool		bSwitchFromCountDiff = false;
+@@ -2657,17 +2658,16 @@ void dm_fsync_timer_callback(struct timer_list *t)
+ 			}
+ 		}
+ 		if (bDoubleTimeInterval) {
+-			if (timer_pending(&priv->fsync_timer))
+-				del_timer_sync(&priv->fsync_timer);
+-			priv->fsync_timer.expires = jiffies +
+-				msecs_to_jiffies(priv->ieee80211->fsync_time_interval*priv->ieee80211->fsync_multiple_timeinterval);
+-			add_timer(&priv->fsync_timer);
++			cancel_delayed_work_sync(&priv->fsync_work);
++			schedule_delayed_work(&priv->fsync_work,
++					      msecs_to_jiffies(priv
++					      ->ieee80211->fsync_time_interval *
++					      priv->ieee80211->fsync_multiple_timeinterval));
+ 		} else {
+-			if (timer_pending(&priv->fsync_timer))
+-				del_timer_sync(&priv->fsync_timer);
+-			priv->fsync_timer.expires = jiffies +
+-				msecs_to_jiffies(priv->ieee80211->fsync_time_interval);
+-			add_timer(&priv->fsync_timer);
++			cancel_delayed_work_sync(&priv->fsync_work);
++			schedule_delayed_work(&priv->fsync_work,
++					      msecs_to_jiffies(priv
++					      ->ieee80211->fsync_time_interval));
+ 		}
+ 	} else {
+ 		/* Let Register return to default value; */
+@@ -2695,7 +2695,7 @@ static void dm_EndSWFsync(struct net_device *dev)
+ 	struct r8192_priv *priv = ieee80211_priv(dev);
+ 
+ 	RT_TRACE(COMP_HALDM, "%s\n", __func__);
+-	del_timer_sync(&(priv->fsync_timer));
++	cancel_delayed_work_sync(&priv->fsync_work);
+ 
+ 	/* Let Register return to default value; */
+ 	if (priv->bswitch_fsync) {
+@@ -2736,11 +2736,9 @@ static void dm_StartSWFsync(struct net_device *dev)
+ 		if (priv->ieee80211->fsync_rate_bitmap &  rateBitmap)
+ 			priv->rate_record += priv->stats.received_rate_histogram[1][rateIndex];
+ 	}
+-	if (timer_pending(&priv->fsync_timer))
+-		del_timer_sync(&priv->fsync_timer);
+-	priv->fsync_timer.expires = jiffies +
+-			msecs_to_jiffies(priv->ieee80211->fsync_time_interval);
+-	add_timer(&priv->fsync_timer);
++	cancel_delayed_work_sync(&priv->fsync_work);
++	schedule_delayed_work(&priv->fsync_work,
++			      msecs_to_jiffies(priv->ieee80211->fsync_time_interval));
+ 
+ 	write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c12cd);
+ }
+diff --git a/drivers/staging/rtl8192u/r8192U_dm.h b/drivers/staging/rtl8192u/r8192U_dm.h
+index 0b2a1c688597..2159018b4e38 100644
+--- a/drivers/staging/rtl8192u/r8192U_dm.h
++++ b/drivers/staging/rtl8192u/r8192U_dm.h
+@@ -166,7 +166,7 @@ void dm_force_tx_fw_info(struct net_device *dev,
+ void dm_init_edca_turbo(struct net_device *dev);
+ void dm_rf_operation_test_callback(unsigned long data);
+ void dm_rf_pathcheck_workitemcallback(struct work_struct *work);
+-void dm_fsync_timer_callback(struct timer_list *t);
++void dm_fsync_work_callback(struct work_struct *work);
+ void dm_cck_txpower_adjust(struct net_device *dev, bool  binch14);
+ void dm_shadow_init(struct net_device *dev);
+ void dm_initialize_txpower_tracking(struct net_device *dev);

commit 148ca04518070910739dfc4eeda765057856403d
+Author: Duoming Zhou 
+Date:   Tue Jul 5 20:56:10 2022 +0800
+
+    net: rose: fix UAF bug caused by rose_t0timer_expiry
+    
+    There are UAF bugs caused by rose_t0timer_expiry(). The
+    root cause is that del_timer() could not stop the timer
+    handler that is running and there is no synchronization.
+    One of the race conditions is shown below:
+    
+        (thread 1)             |        (thread 2)
+                               | rose_device_event
+                               |   rose_rt_device_down
+                               |     rose_remove_neigh
+    rose_t0timer_expiry        |       rose_stop_t0timer(rose_neigh)
+      ...                      |         del_timer(&neigh->t0timer)
+                               |         kfree(rose_neigh) //[1]FREE
+      neigh->dce_mode //[2]USE |
+    
+    The rose_neigh is deallocated in position [1] and use in
+    position [2].
+    
+    The crash trace triggered by POC is like below:
+    
+    BUG: KASAN: use-after-free in expire_timers+0x144/0x320
+    Write of size 8 at addr ffff888009b19658 by task swapper/0/0
+    ...
+    Call Trace:
+     
+     dump_stack_lvl+0xbf/0xee
+     print_address_description+0x7b/0x440
+     print_report+0x101/0x230
+     ? expire_timers+0x144/0x320
+     kasan_report+0xed/0x120
+     ? expire_timers+0x144/0x320
+     expire_timers+0x144/0x320
+     __run_timers+0x3ff/0x4d0
+     run_timer_softirq+0x41/0x80
+     __do_softirq+0x233/0x544
+     ...
+    
+    This patch changes rose_stop_ftimer() and rose_stop_t0timer()
+    in rose_remove_neigh() to del_timer_sync() in order that the
+    timer handler could be finished before the resources such as
+    rose_neigh and so on are deallocated. As a result, the UAF
+    bugs could be mitigated.
+    
+    Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+    Signed-off-by: Duoming Zhou 
+    Link: https://lore.kernel.org/r/20220705125610.77971-1-duoming@zju.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
+index fee6409c2bb3..eb0b8197ac82 100644
+--- a/net/rose/rose_route.c
++++ b/net/rose/rose_route.c
+@@ -227,8 +227,8 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh)
+ {
+ 	struct rose_neigh *s;
+ 
+-	rose_stop_ftimer(rose_neigh);
+-	rose_stop_t0timer(rose_neigh);
++	del_timer_sync(&rose_neigh->ftimer);
++	del_timer_sync(&rose_neigh->t0timer);
+ 
+ 	skb_queue_purge(&rose_neigh->queue);
+ 

commit 9cc02ede696272c5271a401e4f27c262359bc2f6
+Author: Duoming Zhou 
+Date:   Wed Jun 29 08:26:40 2022 +0800
+
+    net: rose: fix UAF bugs caused by timer handler
+    
+    There are UAF bugs in rose_heartbeat_expiry(), rose_timer_expiry()
+    and rose_idletimer_expiry(). The root cause is that del_timer()
+    could not stop the timer handler that is running and the refcount
+    of sock is not managed properly.
+    
+    One of the UAF bugs is shown below:
+    
+        (thread 1)          |        (thread 2)
+                            |  rose_bind
+                            |  rose_connect
+                            |    rose_start_heartbeat
+    rose_release            |    (wait a time)
+      case ROSE_STATE_0     |
+      rose_destroy_socket   |  rose_heartbeat_expiry
+        rose_stop_heartbeat |
+        sock_put(sk)        |    ...
+      sock_put(sk) // FREE  |
+                            |    bh_lock_sock(sk) // USE
+    
+    The sock is deallocated by sock_put() in rose_release() and
+    then used by bh_lock_sock() in rose_heartbeat_expiry().
+    
+    Although rose_destroy_socket() calls rose_stop_heartbeat(),
+    it could not stop the timer that is running.
+    
+    The KASAN report triggered by POC is shown below:
+    
+    BUG: KASAN: use-after-free in _raw_spin_lock+0x5a/0x110
+    Write of size 4 at addr ffff88800ae59098 by task swapper/3/0
+    ...
+    Call Trace:
+     
+     dump_stack_lvl+0xbf/0xee
+     print_address_description+0x7b/0x440
+     print_report+0x101/0x230
+     ? irq_work_single+0xbb/0x140
+     ? _raw_spin_lock+0x5a/0x110
+     kasan_report+0xed/0x120
+     ? _raw_spin_lock+0x5a/0x110
+     kasan_check_range+0x2bd/0x2e0
+     _raw_spin_lock+0x5a/0x110
+     rose_heartbeat_expiry+0x39/0x370
+     ? rose_start_heartbeat+0xb0/0xb0
+     call_timer_fn+0x2d/0x1c0
+     ? rose_start_heartbeat+0xb0/0xb0
+     expire_timers+0x1f3/0x320
+     __run_timers+0x3ff/0x4d0
+     run_timer_softirq+0x41/0x80
+     __do_softirq+0x233/0x544
+     irq_exit_rcu+0x41/0xa0
+     sysvec_apic_timer_interrupt+0x8c/0xb0
+     
+     
+     asm_sysvec_apic_timer_interrupt+0x1b/0x20
+    RIP: 0010:default_idle+0xb/0x10
+    RSP: 0018:ffffc9000012fea0 EFLAGS: 00000202
+    RAX: 000000000000bcae RBX: ffff888006660f00 RCX: 000000000000bcae
+    RDX: 0000000000000001 RSI: ffffffff843a11c0 RDI: ffffffff843a1180
+    RBP: dffffc0000000000 R08: dffffc0000000000 R09: ffffed100da36d46
+    R10: dfffe9100da36d47 R11: ffffffff83cf0950 R12: 0000000000000000
+    R13: 1ffff11000ccc1e0 R14: ffffffff8542af28 R15: dffffc0000000000
+    ...
+    Allocated by task 146:
+     __kasan_kmalloc+0xc4/0xf0
+     sk_prot_alloc+0xdd/0x1a0
+     sk_alloc+0x2d/0x4e0
+     rose_create+0x7b/0x330
+     __sock_create+0x2dd/0x640
+     __sys_socket+0xc7/0x270
+     __x64_sys_socket+0x71/0x80
+     do_syscall_64+0x43/0x90
+     entry_SYSCALL_64_after_hwframe+0x46/0xb0
+    
+    Freed by task 152:
+     kasan_set_track+0x4c/0x70
+     kasan_set_free_info+0x1f/0x40
+     ____kasan_slab_free+0x124/0x190
+     kfree+0xd3/0x270
+     __sk_destruct+0x314/0x460
+     rose_release+0x2fa/0x3b0
+     sock_close+0xcb/0x230
+     __fput+0x2d9/0x650
+     task_work_run+0xd6/0x160
+     exit_to_user_mode_loop+0xc7/0xd0
+     exit_to_user_mode_prepare+0x4e/0x80
+     syscall_exit_to_user_mode+0x20/0x40
+     do_syscall_64+0x4f/0x90
+     entry_SYSCALL_64_after_hwframe+0x46/0xb0
+    
+    This patch adds refcount of sock when we use functions
+    such as rose_start_heartbeat() and so on to start timer,
+    and decreases the refcount of sock when timer is finished
+    or deleted by functions such as rose_stop_heartbeat()
+    and so on. As a result, the UAF bugs could be mitigated.
+    
+    Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+    Signed-off-by: Duoming Zhou 
+    Tested-by: Duoming Zhou 
+    Link: https://lore.kernel.org/r/20220629002640.5693-1-duoming@zju.edu.cn
+    Signed-off-by: Paolo Abeni 
+
+diff --git a/net/rose/rose_timer.c b/net/rose/rose_timer.c
+index b3138fc2e552..f06ddbed3fed 100644
+--- a/net/rose/rose_timer.c
++++ b/net/rose/rose_timer.c
+@@ -31,89 +31,89 @@ static void rose_idletimer_expiry(struct timer_list *);
+ 
+ void rose_start_heartbeat(struct sock *sk)
+ {
+-	del_timer(&sk->sk_timer);
++	sk_stop_timer(sk, &sk->sk_timer);
+ 
+ 	sk->sk_timer.function = rose_heartbeat_expiry;
+ 	sk->sk_timer.expires  = jiffies + 5 * HZ;
+ 
+-	add_timer(&sk->sk_timer);
++	sk_reset_timer(sk, &sk->sk_timer, sk->sk_timer.expires);
+ }
+ 
+ void rose_start_t1timer(struct sock *sk)
+ {
+ 	struct rose_sock *rose = rose_sk(sk);
+ 
+-	del_timer(&rose->timer);
++	sk_stop_timer(sk, &rose->timer);
+ 
+ 	rose->timer.function = rose_timer_expiry;
+ 	rose->timer.expires  = jiffies + rose->t1;
+ 
+-	add_timer(&rose->timer);
++	sk_reset_timer(sk, &rose->timer, rose->timer.expires);
+ }
+ 
+ void rose_start_t2timer(struct sock *sk)
+ {
+ 	struct rose_sock *rose = rose_sk(sk);
+ 
+-	del_timer(&rose->timer);
++	sk_stop_timer(sk, &rose->timer);
+ 
+ 	rose->timer.function = rose_timer_expiry;
+ 	rose->timer.expires  = jiffies + rose->t2;
+ 
+-	add_timer(&rose->timer);
++	sk_reset_timer(sk, &rose->timer, rose->timer.expires);
+ }
+ 
+ void rose_start_t3timer(struct sock *sk)
+ {
+ 	struct rose_sock *rose = rose_sk(sk);
+ 
+-	del_timer(&rose->timer);
++	sk_stop_timer(sk, &rose->timer);
+ 
+ 	rose->timer.function = rose_timer_expiry;
+ 	rose->timer.expires  = jiffies + rose->t3;
+ 
+-	add_timer(&rose->timer);
++	sk_reset_timer(sk, &rose->timer, rose->timer.expires);
+ }
+ 
+ void rose_start_hbtimer(struct sock *sk)
+ {
+ 	struct rose_sock *rose = rose_sk(sk);
+ 
+-	del_timer(&rose->timer);
++	sk_stop_timer(sk, &rose->timer);
+ 
+ 	rose->timer.function = rose_timer_expiry;
+ 	rose->timer.expires  = jiffies + rose->hb;
+ 
+-	add_timer(&rose->timer);
++	sk_reset_timer(sk, &rose->timer, rose->timer.expires);
+ }
+ 
+ void rose_start_idletimer(struct sock *sk)
+ {
+ 	struct rose_sock *rose = rose_sk(sk);
+ 
+-	del_timer(&rose->idletimer);
++	sk_stop_timer(sk, &rose->idletimer);
+ 
+ 	if (rose->idle > 0) {
+ 		rose->idletimer.function = rose_idletimer_expiry;
+ 		rose->idletimer.expires  = jiffies + rose->idle;
+ 
+-		add_timer(&rose->idletimer);
++		sk_reset_timer(sk, &rose->idletimer, rose->idletimer.expires);
+ 	}
+ }
+ 
+ void rose_stop_heartbeat(struct sock *sk)
+ {
+-	del_timer(&sk->sk_timer);
++	sk_stop_timer(sk, &sk->sk_timer);
+ }
+ 
+ void rose_stop_timer(struct sock *sk)
+ {
+-	del_timer(&rose_sk(sk)->timer);
++	sk_stop_timer(sk, &rose_sk(sk)->timer);
+ }
+ 
+ void rose_stop_idletimer(struct sock *sk)
+ {
+-	del_timer(&rose_sk(sk)->idletimer);
++	sk_stop_timer(sk, &rose_sk(sk)->idletimer);
+ }
+ 
+ static void rose_heartbeat_expiry(struct timer_list *t)
+@@ -130,6 +130,7 @@ static void rose_heartbeat_expiry(struct timer_list *t)
+ 		    (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) {
+ 			bh_unlock_sock(sk);
+ 			rose_destroy_socket(sk);
++			sock_put(sk);
+ 			return;
+ 		}
+ 		break;
+@@ -152,6 +153,7 @@ static void rose_heartbeat_expiry(struct timer_list *t)
+ 
+ 	rose_start_heartbeat(sk);
+ 	bh_unlock_sock(sk);
++	sock_put(sk);
+ }
+ 
+ static void rose_timer_expiry(struct timer_list *t)
+@@ -181,6 +183,7 @@ static void rose_timer_expiry(struct timer_list *t)
+ 		break;
+ 	}
+ 	bh_unlock_sock(sk);
++	sock_put(sk);
+ }
+ 
+ static void rose_idletimer_expiry(struct timer_list *t)
+@@ -205,4 +208,5 @@ static void rose_idletimer_expiry(struct timer_list *t)
+ 		sock_set_flag(sk, SOCK_DEAD);
+ 	}
+ 	bh_unlock_sock(sk);
++	sock_put(sk);
+ }

commit a52ed4866d2b90dd5e4ae9dabd453f3ed8fa3cbc
+Author: Duoming Zhou 
+Date:   Tue Jun 7 11:26:26 2022 +0800
+
+    mwifiex: fix sleep in atomic context bugs caused by dev_coredumpv
+    
+    There are sleep in atomic context bugs when uploading device dump
+    data in mwifiex. The root cause is that dev_coredumpv could not
+    be used in atomic contexts, because it calls dev_set_name which
+    include operations that may sleep. The call tree shows execution
+    paths that could lead to bugs:
+    
+       (Interrupt context)
+    fw_dump_timer_fn
+      mwifiex_upload_device_dump
+        dev_coredumpv(..., GFP_KERNEL)
+          dev_coredumpm()
+            kzalloc(sizeof(*devcd), gfp); //may sleep
+            dev_set_name
+              kobject_set_name_vargs
+                kvasprintf_const(GFP_KERNEL, ...); //may sleep
+                kstrdup(s, GFP_KERNEL); //may sleep
+    
+    The corresponding fail log is shown below:
+    
+    [  135.275938] usb 1-1: == mwifiex dump information to /sys/class/devcoredump start
+    [  135.281029] BUG: sleeping function called from invalid context at include/linux/sched/mm.h:265
+    ...
+    [  135.293613] Call Trace:
+    [  135.293613]  
+    [  135.293613]  dump_stack_lvl+0x57/0x7d
+    [  135.293613]  __might_resched.cold+0x138/0x173
+    [  135.293613]  ? dev_coredumpm+0xca/0x2e0
+    [  135.293613]  kmem_cache_alloc_trace+0x189/0x1f0
+    [  135.293613]  ? devcd_match_failing+0x30/0x30
+    [  135.293613]  dev_coredumpm+0xca/0x2e0
+    [  135.293613]  ? devcd_freev+0x10/0x10
+    [  135.293613]  dev_coredumpv+0x1c/0x20
+    [  135.293613]  ? devcd_match_failing+0x30/0x30
+    [  135.293613]  mwifiex_upload_device_dump+0x65/0xb0
+    [  135.293613]  ? mwifiex_dnld_fw+0x1b0/0x1b0
+    [  135.293613]  call_timer_fn+0x122/0x3d0
+    [  135.293613]  ? msleep_interruptible+0xb0/0xb0
+    [  135.293613]  ? lock_downgrade+0x3c0/0x3c0
+    [  135.293613]  ? __next_timer_interrupt+0x13c/0x160
+    [  135.293613]  ? lockdep_hardirqs_on_prepare+0xe/0x220
+    [  135.293613]  ? mwifiex_dnld_fw+0x1b0/0x1b0
+    [  135.293613]  __run_timers.part.0+0x3f8/0x540
+    [  135.293613]  ? call_timer_fn+0x3d0/0x3d0
+    [  135.293613]  ? arch_restore_msi_irqs+0x10/0x10
+    [  135.293613]  ? lapic_next_event+0x31/0x40
+    [  135.293613]  run_timer_softirq+0x4f/0xb0
+    [  135.293613]  __do_softirq+0x1c2/0x651
+    ...
+    [  135.293613] RIP: 0010:default_idle+0xb/0x10
+    [  135.293613] RSP: 0018:ffff888006317e68 EFLAGS: 00000246
+    [  135.293613] RAX: ffffffff82ad8d10 RBX: ffff888006301cc0 RCX: ffffffff82ac90e1
+    [  135.293613] RDX: ffffed100d9ff1b4 RSI: ffffffff831ad140 RDI: ffffffff82ad8f20
+    [  135.293613] RBP: 0000000000000003 R08: 0000000000000000 R09: ffff88806cff8d9b
+    [  135.293613] R10: ffffed100d9ff1b3 R11: 0000000000000001 R12: ffffffff84593410
+    [  135.293613] R13: 0000000000000000 R14: 0000000000000000 R15: 1ffff11000c62fd2
+    ...
+    [  135.389205] usb 1-1: == mwifiex dump information to /sys/class/devcoredump end
+    
+    This patch uses delayed work to replace timer and moves the operations
+    that may sleep into a delayed work in order to mitigate bugs, it was
+    tested on Marvell 88W8801 chip whose port is usb and the firmware is
+    usb8801_uapsta.bin. The following is the result after using delayed
+    work to replace timer.
+    
+    [  134.936453] usb 1-1: == mwifiex dump information to /sys/class/devcoredump start
+    [  135.043344] usb 1-1: == mwifiex dump information to /sys/class/devcoredump end
+    
+    As we can see, there is no bug now.
+    
+    Fixes: f5ecd02a8b20 ("mwifiex: device dump support for usb interface")
+    Reviewed-by: Brian Norris 
+    Signed-off-by: Duoming Zhou 
+    Link: https://lore.kernel.org/r/b63b77fc84ed3e8a6bef02378e17c7c71a0bc3be.1654569290.git.duoming@zju.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
+index 88c72d1827a0..fca3ab948f6c 100644
+--- a/drivers/net/wireless/marvell/mwifiex/init.c
++++ b/drivers/net/wireless/marvell/mwifiex/init.c
+@@ -63,9 +63,10 @@ static void wakeup_timer_fn(struct timer_list *t)
+ 		adapter->if_ops.card_reset(adapter);
+ }
+ 
+-static void fw_dump_timer_fn(struct timer_list *t)
++static void fw_dump_work(struct work_struct *work)
+ {
+-	struct mwifiex_adapter *adapter = from_timer(adapter, t, devdump_timer);
++	struct mwifiex_adapter *adapter =
++		container_of(work, struct mwifiex_adapter, devdump_work.work);
+ 
+ 	mwifiex_upload_device_dump(adapter);
+ }
+@@ -321,7 +322,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
+ 	adapter->active_scan_triggered = false;
+ 	timer_setup(&adapter->wakeup_timer, wakeup_timer_fn, 0);
+ 	adapter->devdump_len = 0;
+-	timer_setup(&adapter->devdump_timer, fw_dump_timer_fn, 0);
++	INIT_DELAYED_WORK(&adapter->devdump_work, fw_dump_work);
+ }
+ 
+ /*
+@@ -400,7 +401,7 @@ static void
+ mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
+ {
+ 	del_timer(&adapter->wakeup_timer);
+-	del_timer_sync(&adapter->devdump_timer);
++	cancel_delayed_work_sync(&adapter->devdump_work);
+ 	mwifiex_cancel_all_pending_cmd(adapter);
+ 	wake_up_interruptible(&adapter->cmd_wait_q.wait);
+ 	wake_up_interruptible(&adapter->hs_activate_wait_q);
+diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
+index 332dd1c8db35..5d8646f16162 100644
+--- a/drivers/net/wireless/marvell/mwifiex/main.h
++++ b/drivers/net/wireless/marvell/mwifiex/main.h
+@@ -49,6 +49,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include "decl.h"
+ #include "ioctl.h"
+@@ -1055,7 +1056,7 @@ struct mwifiex_adapter {
+ 	/* Device dump data/length */
+ 	void *devdump_data;
+ 	int devdump_len;
+-	struct timer_list devdump_timer;
++	struct delayed_work devdump_work;
+ 
+ 	bool ignore_btcoex_events;
+ };
+diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c
+index 7d42c5d2dbf6..4d93386494c5 100644
+--- a/drivers/net/wireless/marvell/mwifiex/sta_event.c
++++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c
+@@ -623,8 +623,8 @@ mwifiex_fw_dump_info_event(struct mwifiex_private *priv,
+ 		 * transmission event get lost, in this cornel case,
+ 		 * user would still get partial of the dump.
+ 		 */
+-		mod_timer(&adapter->devdump_timer,
+-			  jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
++		schedule_delayed_work(&adapter->devdump_work,
++				      msecs_to_jiffies(MWIFIEX_TIMER_10S));
+ 	}
+ 
+ 	/* Overflow check */
+@@ -643,7 +643,7 @@ mwifiex_fw_dump_info_event(struct mwifiex_private *priv,
+ 	return;
+ 
+ upload_dump:
+-	del_timer_sync(&adapter->devdump_timer);
++	cancel_delayed_work_sync(&adapter->devdump_work);
+ 	mwifiex_upload_device_dump(adapter);
+ }
+ 

commit 77515ebaf01920e2db49e04672ef669a7c2907f2
+Author: Duoming Zhou 
+Date:   Tue Jun 7 11:26:25 2022 +0800
+
+    devcoredump: remove the useless gfp_t parameter in dev_coredumpv and dev_coredumpm
+    
+    The dev_coredumpv() and dev_coredumpm() could not be used in atomic
+    context, because they call kvasprintf_const() and kstrdup() with
+    GFP_KERNEL parameter. The process is shown below:
+    
+    dev_coredumpv(.., gfp_t gfp)
+      dev_coredumpm(.., gfp_t gfp)
+        dev_set_name
+          kobject_set_name_vargs
+            kvasprintf_const(GFP_KERNEL, ...); //may sleep
+              kstrdup(s, GFP_KERNEL); //may sleep
+    
+    This patch removes gfp_t parameter of dev_coredumpv() and dev_coredumpm()
+    and changes the gfp_t parameter of kzalloc() in dev_coredumpm() to
+    GFP_KERNEL in order to show they could not be used in atomic context.
+    
+    Fixes: 833c95456a70 ("device coredump: add new device coredump class")
+    Reviewed-by: Brian Norris 
+    Reviewed-by: Johannes Berg 
+    Signed-off-by: Duoming Zhou 
+    Link: https://lore.kernel.org/r/df72af3b1862bac7d8e793d1f3931857d3779dfd.1654569290.git.duoming@zju.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/base/devcoredump.c b/drivers/base/devcoredump.c
+index f4d794d6bb85..8535f0bd5dfb 100644
+--- a/drivers/base/devcoredump.c
++++ b/drivers/base/devcoredump.c
+@@ -173,15 +173,13 @@ static void devcd_freev(void *data)
+  * @dev: the struct device for the crashed device
+  * @data: vmalloc data containing the device coredump
+  * @datalen: length of the data
+- * @gfp: allocation flags
+  *
+  * This function takes ownership of the vmalloc'ed data and will free
+  * it when it is no longer used. See dev_coredumpm() for more information.
+  */
+-void dev_coredumpv(struct device *dev, void *data, size_t datalen,
+-		   gfp_t gfp)
++void dev_coredumpv(struct device *dev, void *data, size_t datalen)
+ {
+-	dev_coredumpm(dev, NULL, data, datalen, gfp, devcd_readv, devcd_freev);
++	dev_coredumpm(dev, NULL, data, datalen, devcd_readv, devcd_freev);
+ }
+ EXPORT_SYMBOL_GPL(dev_coredumpv);
+ 
+@@ -236,7 +234,6 @@ static ssize_t devcd_read_from_sgtable(char *buffer, loff_t offset,
+  * @owner: the module that contains the read/free functions, use %THIS_MODULE
+  * @data: data cookie for the @read/@free functions
+  * @datalen: length of the data
+- * @gfp: allocation flags
+  * @read: function to read from the given buffer
+  * @free: function to free the given buffer
+  *
+@@ -246,7 +243,7 @@ static ssize_t devcd_read_from_sgtable(char *buffer, loff_t offset,
+  * function will be called to free the data.
+  */
+ void dev_coredumpm(struct device *dev, struct module *owner,
+-		   void *data, size_t datalen, gfp_t gfp,
++		   void *data, size_t datalen,
+ 		   ssize_t (*read)(char *buffer, loff_t offset, size_t count,
+ 				   void *data, size_t datalen),
+ 		   void (*free)(void *data))
+@@ -268,7 +265,7 @@ void dev_coredumpm(struct device *dev, struct module *owner,
+ 	if (!try_module_get(owner))
+ 		goto free;
+ 
+-	devcd = kzalloc(sizeof(*devcd), gfp);
++	devcd = kzalloc(sizeof(*devcd), GFP_KERNEL);
+ 	if (!devcd)
+ 		goto put_module;
+ 
+@@ -318,7 +315,6 @@ EXPORT_SYMBOL_GPL(dev_coredumpm);
+  * @dev: the struct device for the crashed device
+  * @table: the dump data
+  * @datalen: length of the data
+- * @gfp: allocation flags
+  *
+  * Creates a new device coredump for the given device. If a previous one hasn't
+  * been read yet, the new coredump is discarded. The data lifetime is determined
+@@ -326,9 +322,9 @@ EXPORT_SYMBOL_GPL(dev_coredumpm);
+  * it will free the data.
+  */
+ void dev_coredumpsg(struct device *dev, struct scatterlist *table,
+-		    size_t datalen, gfp_t gfp)
++		    size_t datalen)
+ {
+-	dev_coredumpm(dev, NULL, table, datalen, gfp, devcd_read_from_sgtable,
++	dev_coredumpm(dev, NULL, table, datalen, devcd_read_from_sgtable,
+ 		      devcd_free_sgtable);
+ }
+ EXPORT_SYMBOL_GPL(dev_coredumpsg);
+diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
+index b8ef66f89fc1..9b9728719db2 100644
+--- a/drivers/bluetooth/btmrvl_sdio.c
++++ b/drivers/bluetooth/btmrvl_sdio.c
+@@ -1515,7 +1515,7 @@ static void btmrvl_sdio_coredump(struct device *dev)
+ 	/* fw_dump_data will be free in device coredump release function
+ 	 * after 5 min
+ 	 */
+-	dev_coredumpv(&card->func->dev, fw_dump_data, fw_dump_len, GFP_KERNEL);
++	dev_coredumpv(&card->func->dev, fw_dump_data, fw_dump_len);
+ 	BT_INFO("== btmrvl firmware dump to /sys/class/devcoredump end");
+ }
+ 
+diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
+index eab34e24d944..2e4074211ae9 100644
+--- a/drivers/bluetooth/hci_qca.c
++++ b/drivers/bluetooth/hci_qca.c
+@@ -1120,7 +1120,7 @@ static void qca_controller_memdump(struct work_struct *work)
+ 				    qca_memdump->ram_dump_size);
+ 			memdump_buf = qca_memdump->memdump_buf_head;
+ 			dev_coredumpv(&hu->serdev->dev, memdump_buf,
+-				      qca_memdump->received_dump, GFP_KERNEL);
++				      qca_memdump->received_dump);
+ 			cancel_delayed_work(&qca->ctrl_memdump_timeout);
+ 			kfree(qca->qca_memdump);
+ 			qca->qca_memdump = NULL;
+diff --git a/drivers/gpu/drm/etnaviv/etnaviv_dump.c b/drivers/gpu/drm/etnaviv/etnaviv_dump.c
+index f418e0b75772..519fcb234b3e 100644
+--- a/drivers/gpu/drm/etnaviv/etnaviv_dump.c
++++ b/drivers/gpu/drm/etnaviv/etnaviv_dump.c
+@@ -225,5 +225,5 @@ void etnaviv_core_dump(struct etnaviv_gem_submit *submit)
+ 
+ 	etnaviv_core_dump_header(&iter, ETDUMP_BUF_END, iter.data);
+ 
+-	dev_coredumpv(gpu->dev, iter.start, iter.data - iter.start, GFP_KERNEL);
++	dev_coredumpv(gpu->dev, iter.start, iter.data - iter.start);
+ }
+diff --git a/drivers/gpu/drm/msm/disp/msm_disp_snapshot.c b/drivers/gpu/drm/msm/disp/msm_disp_snapshot.c
+index e75b97127c0d..f057d294c30b 100644
+--- a/drivers/gpu/drm/msm/disp/msm_disp_snapshot.c
++++ b/drivers/gpu/drm/msm/disp/msm_disp_snapshot.c
+@@ -74,8 +74,8 @@ static void _msm_disp_snapshot_work(struct kthread_work *work)
+ 	 * If there is a codedump pending for the device, the dev_coredumpm()
+ 	 * will also free new coredump state.
+ 	 */
+-	dev_coredumpm(disp_state->dev, THIS_MODULE, disp_state, 0, GFP_KERNEL,
+-			disp_devcoredump_read, msm_disp_state_free);
++	dev_coredumpm(disp_state->dev, THIS_MODULE, disp_state, 0,
++		      disp_devcoredump_read, msm_disp_state_free);
+ }
+ 
+ void msm_disp_snapshot_state(struct drm_device *drm_dev)
+diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
+index eb8a6663f309..30576ced0a0a 100644
+--- a/drivers/gpu/drm/msm/msm_gpu.c
++++ b/drivers/gpu/drm/msm/msm_gpu.c
+@@ -317,8 +317,8 @@ static void msm_gpu_crashstate_capture(struct msm_gpu *gpu,
+ 	gpu->crashstate = state;
+ 
+ 	/* FIXME: Release the crashstate if this errors out? */
+-	dev_coredumpm(gpu->dev->dev, THIS_MODULE, gpu, 0, GFP_KERNEL,
+-		msm_gpu_devcoredump_read, msm_gpu_devcoredump_free);
++	dev_coredumpm(gpu->dev->dev, THIS_MODULE, gpu, 0,
++		      msm_gpu_devcoredump_read, msm_gpu_devcoredump_free);
+ }
+ #else
+ static void msm_gpu_crashstate_capture(struct msm_gpu *gpu,
+diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c
+index 877eca125803..db84dfb3fb11 100644
+--- a/drivers/media/platform/qcom/venus/core.c
++++ b/drivers/media/platform/qcom/venus/core.c
+@@ -49,7 +49,7 @@ static void venus_coredump(struct venus_core *core)
+ 
+ 	memcpy(data, mem_va, mem_size);
+ 	memunmap(mem_va);
+-	dev_coredumpv(dev, data, mem_size, GFP_KERNEL);
++	dev_coredumpv(dev, data, mem_size);
+ }
+ 
+ static void venus_event_notify(struct venus_core *core, u32 event)
+diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-dump.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-dump.c
+index c991b30bc9f0..fa520ab7c960 100644
+--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-dump.c
++++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-dump.c
+@@ -281,5 +281,5 @@ void mcp251xfd_dump(const struct mcp251xfd_priv *priv)
+ 	mcp251xfd_dump_end(priv, &iter);
+ 
+ 	dev_coredumpv(&priv->spi->dev, iter.start,
+-		      iter.data - iter.start, GFP_KERNEL);
++		      iter.data - iter.start);
+ }
+diff --git a/drivers/net/wireless/ath/ath10k/coredump.c b/drivers/net/wireless/ath/ath10k/coredump.c
+index fe6b6f97a916..dc9237069921 100644
+--- a/drivers/net/wireless/ath/ath10k/coredump.c
++++ b/drivers/net/wireless/ath/ath10k/coredump.c
+@@ -1607,7 +1607,7 @@ int ath10k_coredump_submit(struct ath10k *ar)
+ 		return -ENODATA;
+ 	}
+ 
+-	dev_coredumpv(ar->dev, dump, le32_to_cpu(dump->len), GFP_KERNEL);
++	dev_coredumpv(ar->dev, dump, le32_to_cpu(dump->len));
+ 
+ 	return 0;
+ }
+diff --git a/drivers/net/wireless/ath/wil6210/wil_crash_dump.c b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c
+index 89c12cb2aaab..79299609dd62 100644
+--- a/drivers/net/wireless/ath/wil6210/wil_crash_dump.c
++++ b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c
+@@ -117,6 +117,6 @@ void wil_fw_core_dump(struct wil6210_priv *wil)
+ 	/* fw_dump_data will be free in device coredump release function
+ 	 * after 5 min
+ 	 */
+-	dev_coredumpv(wil_to_dev(wil), fw_dump_data, fw_dump_size, GFP_KERNEL);
++	dev_coredumpv(wil_to_dev(wil), fw_dump_data, fw_dump_size);
+ 	wil_info(wil, "fw core dumped, size %d bytes\n", fw_dump_size);
+ }
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c
+index eecf8a38d94a..87f3652ef3bd 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c
+@@ -37,7 +37,7 @@ int brcmf_debug_create_memdump(struct brcmf_bus *bus, const void *data,
+ 		return err;
+ 	}
+ 
+-	dev_coredumpv(bus->dev, dump, len + ramsize, GFP_KERNEL);
++	dev_coredumpv(bus->dev, dump, len + ramsize);
+ 
+ 	return 0;
+ }
+diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+index abf49022edbe..f2f7cf494a8c 100644
+--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
++++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+@@ -2601,8 +2601,7 @@ static void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt,
+ 					     fw_error_dump.trans_ptr->data,
+ 					     fw_error_dump.trans_ptr->len,
+ 					     fw_error_dump.fwrt_len);
+-		dev_coredumpsg(fwrt->trans->dev, sg_dump_data, file_len,
+-			       GFP_KERNEL);
++		dev_coredumpsg(fwrt->trans->dev, sg_dump_data, file_len);
+ 	}
+ 	vfree(fw_error_dump.fwrt_ptr);
+ 	vfree(fw_error_dump.trans_ptr);
+@@ -2647,8 +2646,7 @@ static void iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt,
+ 					     entry->data, entry->size, offs);
+ 			offs += entry->size;
+ 		}
+-		dev_coredumpsg(fwrt->trans->dev, sg_dump_data, file_len,
+-			       GFP_KERNEL);
++		dev_coredumpsg(fwrt->trans->dev, sg_dump_data, file_len);
+ 	}
+ 	iwl_dump_ini_list_free(&dump_list);
+ }
+diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
+index ace7371c4773..26fef0ab1b0d 100644
+--- a/drivers/net/wireless/marvell/mwifiex/main.c
++++ b/drivers/net/wireless/marvell/mwifiex/main.c
+@@ -1115,8 +1115,7 @@ void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter)
+ 	 */
+ 	mwifiex_dbg(adapter, MSG,
+ 		    "== mwifiex dump information to /sys/class/devcoredump start\n");
+-	dev_coredumpv(adapter->dev, adapter->devdump_data, adapter->devdump_len,
+-		      GFP_KERNEL);
++	dev_coredumpv(adapter->dev, adapter->devdump_data, adapter->devdump_len);
+ 	mwifiex_dbg(adapter, MSG,
+ 		    "== mwifiex dump information to /sys/class/devcoredump end\n");
+ 
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
+index bd687f7de628..5336fe8c668d 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
+@@ -2421,6 +2421,5 @@ void mt7615_coredump_work(struct work_struct *work)
+ 
+ 		dev_kfree_skb(skb);
+ 	}
+-	dev_coredumpv(dev->mt76.dev, dump, MT76_CONNAC_COREDUMP_SZ,
+-		      GFP_KERNEL);
++	dev_coredumpv(dev->mt76.dev, dump, MT76_CONNAC_COREDUMP_SZ);
+ }
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+index a630ddbf19e5..cac284f95ce0 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+@@ -1630,8 +1630,7 @@ void mt7921_coredump_work(struct work_struct *work)
+ 	}
+ 
+ 	if (dump)
+-		dev_coredumpv(dev->mt76.dev, dump, MT76_CONNAC_COREDUMP_SZ,
+-			      GFP_KERNEL);
++		dev_coredumpv(dev->mt76.dev, dump, MT76_CONNAC_COREDUMP_SZ);
+ 
+ 	mt7921_reset(&dev->mt76);
+ }
+diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
+index efabd5b1bf5b..a276544cecdd 100644
+--- a/drivers/net/wireless/realtek/rtw88/main.c
++++ b/drivers/net/wireless/realtek/rtw88/main.c
+@@ -414,7 +414,7 @@ static void rtw_fwcd_dump(struct rtw_dev *rtwdev)
+ 	 * framework. Note that a new dump will be discarded if a previous one
+ 	 * hasn't been released yet.
+ 	 */
+-	dev_coredumpv(rtwdev->dev, desc->data, desc->size, GFP_KERNEL);
++	dev_coredumpv(rtwdev->dev, desc->data, desc->size);
+ }
+ 
+ static void rtw_fwcd_free(struct rtw_dev *rtwdev, bool free_self)
+diff --git a/drivers/net/wireless/realtek/rtw89/ser.c b/drivers/net/wireless/realtek/rtw89/ser.c
+index 9e95ed972710..d28fe01ad729 100644
+--- a/drivers/net/wireless/realtek/rtw89/ser.c
++++ b/drivers/net/wireless/realtek/rtw89/ser.c
+@@ -127,7 +127,7 @@ static void rtw89_ser_cd_send(struct rtw89_dev *rtwdev,
+ 	 * will be discarded if a previous one hasn't been released by
+ 	 * framework yet.
+ 	 */
+-	dev_coredumpv(rtwdev->dev, buf, sizeof(*buf), GFP_KERNEL);
++	dev_coredumpv(rtwdev->dev, buf, sizeof(*buf));
+ }
+ 
+ static void rtw89_ser_cd_free(struct rtw89_dev *rtwdev,
+diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
+index af217de75e4d..813d87faef6c 100644
+--- a/drivers/remoteproc/qcom_q6v5_mss.c
++++ b/drivers/remoteproc/qcom_q6v5_mss.c
+@@ -597,7 +597,7 @@ static void q6v5_dump_mba_logs(struct q6v5 *qproc)
+ 	data = vmalloc(MBA_LOG_SIZE);
+ 	if (data) {
+ 		memcpy(data, mba_region, MBA_LOG_SIZE);
+-		dev_coredumpv(&rproc->dev, data, MBA_LOG_SIZE, GFP_KERNEL);
++		dev_coredumpv(&rproc->dev, data, MBA_LOG_SIZE);
+ 	}
+ 	memunmap(mba_region);
+ }
+diff --git a/drivers/remoteproc/remoteproc_coredump.c b/drivers/remoteproc/remoteproc_coredump.c
+index 4b093420d98a..cd55c2abd227 100644
+--- a/drivers/remoteproc/remoteproc_coredump.c
++++ b/drivers/remoteproc/remoteproc_coredump.c
+@@ -309,7 +309,7 @@ void rproc_coredump(struct rproc *rproc)
+ 		phdr += elf_size_of_phdr(class);
+ 	}
+ 	if (dump_conf == RPROC_COREDUMP_ENABLED) {
+-		dev_coredumpv(&rproc->dev, data, data_size, GFP_KERNEL);
++		dev_coredumpv(&rproc->dev, data, data_size);
+ 		return;
+ 	}
+ 
+@@ -318,7 +318,7 @@ void rproc_coredump(struct rproc *rproc)
+ 	dump_state.header = data;
+ 	init_completion(&dump_state.dump_done);
+ 
+-	dev_coredumpm(&rproc->dev, NULL, &dump_state, data_size, GFP_KERNEL,
++	dev_coredumpm(&rproc->dev, NULL, &dump_state, data_size,
+ 		      rproc_coredump_read, rproc_coredump_free);
+ 
+ 	/*
+@@ -449,7 +449,7 @@ void rproc_coredump_using_sections(struct rproc *rproc)
+ 	}
+ 
+ 	if (dump_conf == RPROC_COREDUMP_ENABLED) {
+-		dev_coredumpv(&rproc->dev, data, data_size, GFP_KERNEL);
++		dev_coredumpv(&rproc->dev, data, data_size);
+ 		return;
+ 	}
+ 
+@@ -458,7 +458,7 @@ void rproc_coredump_using_sections(struct rproc *rproc)
+ 	dump_state.header = data;
+ 	init_completion(&dump_state.dump_done);
+ 
+-	dev_coredumpm(&rproc->dev, NULL, &dump_state, data_size, GFP_KERNEL,
++	dev_coredumpm(&rproc->dev, NULL, &dump_state, data_size,
+ 		      rproc_coredump_read, rproc_coredump_free);
+ 
+ 	/* Wait until the dump is read and free is called. Data is freed
+diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h
+index 22fabdeed297..b41850366bcc 100644
+--- a/include/drm/drm_print.h
++++ b/include/drm/drm_print.h
+@@ -162,7 +162,7 @@ struct drm_print_iterator {
+  *	void makecoredump(...)
+  *	{
+  *		...
+- *		dev_coredumpm(dev, THIS_MODULE, data, 0, GFP_KERNEL,
++ *		dev_coredumpm(dev, THIS_MODULE, data, 0,
+  *			coredump_read, ...)
+  *	}
+  *
+diff --git a/include/linux/devcoredump.h b/include/linux/devcoredump.h
+index c008169ed2c6..c7d840d824c3 100644
+--- a/include/linux/devcoredump.h
++++ b/include/linux/devcoredump.h
+@@ -52,27 +52,26 @@ static inline void _devcd_free_sgtable(struct scatterlist *table)
+ 
+ 
+ #ifdef CONFIG_DEV_COREDUMP
+-void dev_coredumpv(struct device *dev, void *data, size_t datalen,
+-		   gfp_t gfp);
++void dev_coredumpv(struct device *dev, void *data, size_t datalen);
+ 
+ void dev_coredumpm(struct device *dev, struct module *owner,
+-		   void *data, size_t datalen, gfp_t gfp,
++		   void *data, size_t datalen,
+ 		   ssize_t (*read)(char *buffer, loff_t offset, size_t count,
+ 				   void *data, size_t datalen),
+ 		   void (*free)(void *data));
+ 
+ void dev_coredumpsg(struct device *dev, struct scatterlist *table,
+-		    size_t datalen, gfp_t gfp);
++		    size_t datalen);
+ #else
+ static inline void dev_coredumpv(struct device *dev, void *data,
+-				 size_t datalen, gfp_t gfp)
++				 size_t datalen)
+ {
+ 	vfree(data);
+ }
+ 
+ static inline void
+ dev_coredumpm(struct device *dev, struct module *owner,
+-	      void *data, size_t datalen, gfp_t gfp,
++	      void *data, size_t datalen,
+ 	      ssize_t (*read)(char *buffer, loff_t offset, size_t count,
+ 			      void *data, size_t datalen),
+ 	      void (*free)(void *data))
+@@ -81,7 +80,7 @@ dev_coredumpm(struct device *dev, struct module *owner,
+ }
+ 
+ static inline void dev_coredumpsg(struct device *dev, struct scatterlist *table,
+-				  size_t datalen, gfp_t gfp)
++				  size_t datalen)
+ {
+ 	_devcd_free_sgtable(table);
+ }
+diff --git a/sound/soc/intel/avs/apl.c b/sound/soc/intel/avs/apl.c
+index b8e2b23c9f64..1ff57f1a483d 100644
+--- a/sound/soc/intel/avs/apl.c
++++ b/sound/soc/intel/avs/apl.c
+@@ -164,7 +164,7 @@ static int apl_coredump(struct avs_dev *adev, union avs_notify_msg *msg)
+ 	} while (offset < msg->ext.coredump.stack_dump_size);
+ 
+ exit:
+-	dev_coredumpv(adev->dev, dump, dump_size, GFP_KERNEL);
++	dev_coredumpv(adev->dev, dump, dump_size);
+ 
+ 	return 0;
+ }
+diff --git a/sound/soc/intel/avs/skl.c b/sound/soc/intel/avs/skl.c
+index bda5ec7510fe..3413162768dc 100644
+--- a/sound/soc/intel/avs/skl.c
++++ b/sound/soc/intel/avs/skl.c
+@@ -88,7 +88,7 @@ static int skl_coredump(struct avs_dev *adev, union avs_notify_msg *msg)
+ 		return -ENOMEM;
+ 
+ 	memcpy_fromio(dump, avs_sram_addr(adev, AVS_FW_REGS_WINDOW), AVS_FW_REGS_SIZE);
+-	dev_coredumpv(adev->dev, dump, AVS_FW_REGS_SIZE, GFP_KERNEL);
++	dev_coredumpv(adev->dev, dump, AVS_FW_REGS_SIZE);
+ 
+ 	return 0;
+ }
+diff --git a/sound/soc/intel/catpt/dsp.c b/sound/soc/intel/catpt/dsp.c
+index 346bec000306..d2afe9ff1e3a 100644
+--- a/sound/soc/intel/catpt/dsp.c
++++ b/sound/soc/intel/catpt/dsp.c
+@@ -539,7 +539,7 @@ int catpt_coredump(struct catpt_dev *cdev)
+ 		pos += CATPT_DMA_REGS_SIZE;
+ 	}
+ 
+-	dev_coredumpv(cdev->dev, dump, dump_size, GFP_KERNEL);
++	dev_coredumpv(cdev->dev, dump, dump_size);
+ 
+ 	return 0;
+ }

commit 219b51a6f040fa5367adadd7d58c4dda0896a01d
+Author: Duoming Zhou 
+Date:   Tue Jun 14 17:25:57 2022 +0800
+
+    net: ax25: Fix deadlock caused by skb_recv_datagram in ax25_recvmsg
+    
+    The skb_recv_datagram() in ax25_recvmsg() will hold lock_sock
+    and block until it receives a packet from the remote. If the client
+    doesn`t connect to server and calls read() directly, it will not
+    receive any packets forever. As a result, the deadlock will happen.
+    
+    The fail log caused by deadlock is shown below:
+    
+    [  369.606973] INFO: task ax25_deadlock:157 blocked for more than 245 seconds.
+    [  369.608919] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+    [  369.613058] Call Trace:
+    [  369.613315]  
+    [  369.614072]  __schedule+0x2f9/0xb20
+    [  369.615029]  schedule+0x49/0xb0
+    [  369.615734]  __lock_sock+0x92/0x100
+    [  369.616763]  ? destroy_sched_domains_rcu+0x20/0x20
+    [  369.617941]  lock_sock_nested+0x6e/0x70
+    [  369.618809]  ax25_bind+0xaa/0x210
+    [  369.619736]  __sys_bind+0xca/0xf0
+    [  369.620039]  ? do_futex+0xae/0x1b0
+    [  369.620387]  ? __x64_sys_futex+0x7c/0x1c0
+    [  369.620601]  ? fpregs_assert_state_consistent+0x19/0x40
+    [  369.620613]  __x64_sys_bind+0x11/0x20
+    [  369.621791]  do_syscall_64+0x3b/0x90
+    [  369.622423]  entry_SYSCALL_64_after_hwframe+0x46/0xb0
+    [  369.623319] RIP: 0033:0x7f43c8aa8af7
+    [  369.624301] RSP: 002b:00007f43c8197ef8 EFLAGS: 00000246 ORIG_RAX: 0000000000000031
+    [  369.625756] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f43c8aa8af7
+    [  369.626724] RDX: 0000000000000010 RSI: 000055768e2021d0 RDI: 0000000000000005
+    [  369.628569] RBP: 00007f43c8197f00 R08: 0000000000000011 R09: 00007f43c8198700
+    [  369.630208] R10: 0000000000000000 R11: 0000000000000246 R12: 00007fff845e6afe
+    [  369.632240] R13: 00007fff845e6aff R14: 00007f43c8197fc0 R15: 00007f43c8198700
+    
+    This patch replaces skb_recv_datagram() with an open-coded variant of it
+    releasing the socket lock before the __skb_wait_for_more_packets() call
+    and re-acquiring it after such call in order that other functions that
+    need socket lock could be executed.
+    
+    what's more, the socket lock will be released only when recvmsg() will
+    block and that should produce nicer overall behavior.
+    
+    Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+    Suggested-by: Thomas Osterried 
+    Signed-off-by: Duoming Zhou 
+    Reported-by: Thomas Habets 
+    Acked-by: Paolo Abeni 
+    Reviewed-by: Eric Dumazet 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
+index 95393bb2760b..4c7030ed8d33 100644
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -1661,9 +1661,12 @@ static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
+ 			int flags)
+ {
+ 	struct sock *sk = sock->sk;
+-	struct sk_buff *skb;
++	struct sk_buff *skb, *last;
++	struct sk_buff_head *sk_queue;
+ 	int copied;
+ 	int err = 0;
++	int off = 0;
++	long timeo;
+ 
+ 	lock_sock(sk);
+ 	/*
+@@ -1675,10 +1678,29 @@ static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
+ 		goto out;
+ 	}
+ 
+-	/* Now we can treat all alike */
+-	skb = skb_recv_datagram(sk, flags, &err);
+-	if (skb == NULL)
+-		goto out;
++	/*  We need support for non-blocking reads. */
++	sk_queue = &sk->sk_receive_queue;
++	skb = __skb_try_recv_datagram(sk, sk_queue, flags, &off, &err, &last);
++	/* If no packet is available, release_sock(sk) and try again. */
++	if (!skb) {
++		if (err != -EAGAIN)
++			goto out;
++		release_sock(sk);
++		timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
++		while (timeo && !__skb_wait_for_more_packets(sk, sk_queue, &err,
++							     &timeo, last)) {
++			skb = __skb_try_recv_datagram(sk, sk_queue, flags, &off,
++						      &err, &last);
++			if (skb)
++				break;
++
++			if (err != -EAGAIN)
++				goto done;
++		}
++		if (!skb)
++			goto done;
++		lock_sock(sk);
++	}
+ 
+ 	if (!sk_to_ax25(sk)->pidincl)
+ 		skb_pull(skb, 1);		/* Remove PID */
+@@ -1725,6 +1747,7 @@ static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
+ out:
+ 	release_sock(sk);
+ 
++done:
+ 	return err;
+ }
+ 

commit a61528d997619a518ee8c51cf0ef0513021afaff
+Author: Duoming Zhou 
+Date:   Tue May 24 12:48:41 2022 +0800
+
+    mtd: sm_ftl: Fix deadlock caused by cancel_work_sync in sm_release
+    
+    There is a deadlock between sm_release and sm_cache_flush_work
+    which is a work item. The cancel_work_sync in sm_release will
+    not return until sm_cache_flush_work is finished. If we hold
+    mutex_lock and use cancel_work_sync to wait the work item to
+    finish, the work item also requires mutex_lock. As a result,
+    the sm_release will be blocked forever. The race condition is
+    shown below:
+    
+        (Thread 1)             |   (Thread 2)
+    sm_release                 |
+      mutex_lock(&ftl->mutex)  | sm_cache_flush_work
+                               |   mutex_lock(&ftl->mutex)
+      cancel_work_sync         |   ...
+    
+    This patch moves del_timer_sync and cancel_work_sync out of
+    mutex_lock in order to mitigate deadlock.
+    
+    Fixes: 7d17c02a01a1 ("mtd: Add new SmartMedia/xD FTL")
+    Signed-off-by: Duoming Zhou 
+    Signed-off-by: Miquel Raynal 
+    Link: https://lore.kernel.org/linux-mtd/20220524044841.10517-1-duoming@zju.edu.cn
+
+diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c
+index 0cff2cda1b5a..7f955fade838 100644
+--- a/drivers/mtd/sm_ftl.c
++++ b/drivers/mtd/sm_ftl.c
+@@ -1111,9 +1111,9 @@ static void sm_release(struct mtd_blktrans_dev *dev)
+ {
+ 	struct sm_ftl *ftl = dev->priv;
+ 
+-	mutex_lock(&ftl->mutex);
+ 	del_timer_sync(&ftl->timer);
+ 	cancel_work_sync(&ftl->flush_work);
++	mutex_lock(&ftl->mutex);
+ 	sm_cache_flush(ftl);
+ 	mutex_unlock(&ftl->mutex);
+ }

commit 7d8a3a477b3e25ada8dc71d22048c2ea417209a0
+Author: Duoming Zhou 
+Date:   Mon May 30 23:21:58 2022 +0800
+
+    ax25: Fix ax25 session cleanup problems
+    
+    There are session cleanup problems in ax25_release() and
+    ax25_disconnect(). If we setup a session and then disconnect,
+    the disconnected session is still in "LISTENING" state that
+    is shown below.
+    
+    Active AX.25 sockets
+    Dest       Source     Device  State        Vr/Vs    Send-Q  Recv-Q
+    DL9SAU-4   DL9SAU-3   ???     LISTENING    000/000  0       0
+    DL9SAU-3   DL9SAU-4   ???     LISTENING    000/000  0       0
+    
+    The first reason is caused by del_timer_sync() in ax25_release().
+    The timers of ax25 are used for correct session cleanup. If we use
+    ax25_release() to close ax25 sessions and ax25_dev is not null,
+    the del_timer_sync() functions in ax25_release() will execute.
+    As a result, the sessions could not be cleaned up correctly,
+    because the timers have stopped.
+    
+    In order to solve this problem, this patch adds a device_up flag
+    in ax25_dev in order to judge whether the device is up. If there
+    are sessions to be cleaned up, the del_timer_sync() in
+    ax25_release() will not execute. What's more, we add ax25_cb_del()
+    in ax25_kill_by_device(), because the timers have been stopped
+    and there are no functions that could delete ax25_cb if we do not
+    call ax25_release(). Finally, we reorder the position of
+    ax25_list_lock in ax25_cb_del() in order to synchronize among
+    different functions that call ax25_cb_del().
+    
+    The second reason is caused by improper check in ax25_disconnect().
+    The incoming ax25 sessions which ax25->sk is null will close
+    heartbeat timer, because the check "if(!ax25->sk || ..)" is
+    satisfied. As a result, the session could not be cleaned up properly.
+    
+    In order to solve this problem, this patch changes the improper
+    check to "if(ax25->sk && ..)" in ax25_disconnect().
+    
+    What`s more, the ax25_disconnect() may be called twice, which is
+    not necessary. For example, ax25_kill_by_device() calls
+    ax25_disconnect() and sets ax25->state to AX25_STATE_0, but
+    ax25_release() calls ax25_disconnect() again.
+    
+    In order to solve this problem, this patch add a check in
+    ax25_release(). If the flag of ax25->sk equals to SOCK_DEAD,
+    the ax25_disconnect() in ax25_release() should not be executed.
+    
+    Fixes: 82e31755e55f ("ax25: Fix UAF bugs in ax25 timers")
+    Fixes: 8a367e74c012 ("ax25: Fix segfault after sock connection timeout")
+    Reported-and-tested-by: Thomas Osterried 
+    Signed-off-by: Duoming Zhou 
+    Link: https://lore.kernel.org/r/20220530152158.108619-1-duoming@zju.edu.cn
+    Signed-off-by: Paolo Abeni 
+
+diff --git a/include/net/ax25.h b/include/net/ax25.h
+index 0f9790c455bb..a427a05672e2 100644
+--- a/include/net/ax25.h
++++ b/include/net/ax25.h
+@@ -228,6 +228,7 @@ typedef struct ax25_dev {
+ 	ax25_dama_info		dama;
+ #endif
+ 	refcount_t		refcount;
++	bool device_up;
+ } ax25_dev;
+ 
+ typedef struct ax25_cb {
+diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
+index 116481e4da82..95393bb2760b 100644
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -62,12 +62,12 @@ static void ax25_free_sock(struct sock *sk)
+  */
+ static void ax25_cb_del(ax25_cb *ax25)
+ {
++	spin_lock_bh(&ax25_list_lock);
+ 	if (!hlist_unhashed(&ax25->ax25_node)) {
+-		spin_lock_bh(&ax25_list_lock);
+ 		hlist_del_init(&ax25->ax25_node);
+-		spin_unlock_bh(&ax25_list_lock);
+ 		ax25_cb_put(ax25);
+ 	}
++	spin_unlock_bh(&ax25_list_lock);
+ }
+ 
+ /*
+@@ -81,6 +81,7 @@ static void ax25_kill_by_device(struct net_device *dev)
+ 
+ 	if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
+ 		return;
++	ax25_dev->device_up = false;
+ 
+ 	spin_lock_bh(&ax25_list_lock);
+ again:
+@@ -91,6 +92,7 @@ static void ax25_kill_by_device(struct net_device *dev)
+ 				spin_unlock_bh(&ax25_list_lock);
+ 				ax25_disconnect(s, ENETUNREACH);
+ 				s->ax25_dev = NULL;
++				ax25_cb_del(s);
+ 				spin_lock_bh(&ax25_list_lock);
+ 				goto again;
+ 			}
+@@ -103,6 +105,7 @@ static void ax25_kill_by_device(struct net_device *dev)
+ 				dev_put_track(ax25_dev->dev, &ax25_dev->dev_tracker);
+ 				ax25_dev_put(ax25_dev);
+ 			}
++			ax25_cb_del(s);
+ 			release_sock(sk);
+ 			spin_lock_bh(&ax25_list_lock);
+ 			sock_put(sk);
+@@ -995,9 +998,11 @@ static int ax25_release(struct socket *sock)
+ 	if (sk->sk_type == SOCK_SEQPACKET) {
+ 		switch (ax25->state) {
+ 		case AX25_STATE_0:
+-			release_sock(sk);
+-			ax25_disconnect(ax25, 0);
+-			lock_sock(sk);
++			if (!sock_flag(ax25->sk, SOCK_DEAD)) {
++				release_sock(sk);
++				ax25_disconnect(ax25, 0);
++				lock_sock(sk);
++			}
+ 			ax25_destroy_socket(ax25);
+ 			break;
+ 
+@@ -1053,11 +1058,13 @@ static int ax25_release(struct socket *sock)
+ 		ax25_destroy_socket(ax25);
+ 	}
+ 	if (ax25_dev) {
+-		del_timer_sync(&ax25->timer);
+-		del_timer_sync(&ax25->t1timer);
+-		del_timer_sync(&ax25->t2timer);
+-		del_timer_sync(&ax25->t3timer);
+-		del_timer_sync(&ax25->idletimer);
++		if (!ax25_dev->device_up) {
++			del_timer_sync(&ax25->timer);
++			del_timer_sync(&ax25->t1timer);
++			del_timer_sync(&ax25->t2timer);
++			del_timer_sync(&ax25->t3timer);
++			del_timer_sync(&ax25->idletimer);
++		}
+ 		dev_put_track(ax25_dev->dev, &ax25_dev->dev_tracker);
+ 		ax25_dev_put(ax25_dev);
+ 	}
+diff --git a/net/ax25/ax25_dev.c b/net/ax25/ax25_dev.c
+index b80fccbac62a..95a76d571c44 100644
+--- a/net/ax25/ax25_dev.c
++++ b/net/ax25/ax25_dev.c
+@@ -62,6 +62,7 @@ void ax25_dev_device_up(struct net_device *dev)
+ 	ax25_dev->dev     = dev;
+ 	dev_hold_track(dev, &ax25_dev->dev_tracker, GFP_ATOMIC);
+ 	ax25_dev->forward = NULL;
++	ax25_dev->device_up = true;
+ 
+ 	ax25_dev->values[AX25_VALUES_IPDEFMODE] = AX25_DEF_IPDEFMODE;
+ 	ax25_dev->values[AX25_VALUES_AXDEFMODE] = AX25_DEF_AXDEFMODE;
+diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c
+index 3a476e4f6cd0..9ff98f46dc6b 100644
+--- a/net/ax25/ax25_subr.c
++++ b/net/ax25/ax25_subr.c
+@@ -268,7 +268,7 @@ void ax25_disconnect(ax25_cb *ax25, int reason)
+ 		del_timer_sync(&ax25->t3timer);
+ 		del_timer_sync(&ax25->idletimer);
+ 	} else {
+-		if (!ax25->sk || !sock_flag(ax25->sk, SOCK_DESTROY))
++		if (ax25->sk && !sock_flag(ax25->sk, SOCK_DESTROY))
+ 			ax25_stop_heartbeat(ax25);
+ 		ax25_stop_t1timer(ax25);
+ 		ax25_stop_t2timer(ax25);

commit b413b0cb008646e9f24ce5253cb3cf7ee217aff6
+Author: Duoming Zhou 
+Date:   Wed May 18 19:57:33 2022 +0800
+
+    NFC: hci: fix sleep in atomic context bugs in nfc_hci_hcp_message_tx
+    
+    There are sleep in atomic context bugs when the request to secure
+    element of st21nfca is timeout. The root cause is that kzalloc and
+    alloc_skb with GFP_KERNEL parameter and mutex_lock are called in
+    st21nfca_se_wt_timeout which is a timer handler. The call tree shows
+    the execution paths that could lead to bugs:
+    
+       (Interrupt context)
+    st21nfca_se_wt_timeout
+      nfc_hci_send_event
+        nfc_hci_hcp_message_tx
+          kzalloc(..., GFP_KERNEL) //may sleep
+          alloc_skb(..., GFP_KERNEL) //may sleep
+          mutex_lock() //may sleep
+    
+    This patch moves the operations that may sleep into a work item.
+    The work item will run in another kernel thread which is in
+    process context to execute the bottom half of the interrupt.
+    So it could prevent atomic context from sleeping.
+    
+    Fixes: 2130fb97fecf ("NFC: st21nfca: Adding support for secure element")
+    Signed-off-by: Duoming Zhou 
+    Reviewed-by: Krzysztof Kozlowski 
+    Link: https://lore.kernel.org/r/20220518115733.62111-1-duoming@zju.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/drivers/nfc/st21nfca/se.c b/drivers/nfc/st21nfca/se.c
+index c922f10d0d7b..7e213f8ddc98 100644
+--- a/drivers/nfc/st21nfca/se.c
++++ b/drivers/nfc/st21nfca/se.c
+@@ -241,7 +241,7 @@ int st21nfca_hci_se_io(struct nfc_hci_dev *hdev, u32 se_idx,
+ }
+ EXPORT_SYMBOL(st21nfca_hci_se_io);
+ 
+-static void st21nfca_se_wt_timeout(struct timer_list *t)
++static void st21nfca_se_wt_work(struct work_struct *work)
+ {
+ 	/*
+ 	 * No answer from the secure element
+@@ -254,8 +254,9 @@ static void st21nfca_se_wt_timeout(struct timer_list *t)
+ 	 */
+ 	/* hardware reset managed through VCC_UICC_OUT power supply */
+ 	u8 param = 0x01;
+-	struct st21nfca_hci_info *info = from_timer(info, t,
+-						    se_info.bwi_timer);
++	struct st21nfca_hci_info *info = container_of(work,
++						struct st21nfca_hci_info,
++						se_info.timeout_work);
+ 
+ 	info->se_info.bwi_active = false;
+ 
+@@ -271,6 +272,13 @@ static void st21nfca_se_wt_timeout(struct timer_list *t)
+ 	info->se_info.cb(info->se_info.cb_context, NULL, 0, -ETIME);
+ }
+ 
++static void st21nfca_se_wt_timeout(struct timer_list *t)
++{
++	struct st21nfca_hci_info *info = from_timer(info, t, se_info.bwi_timer);
++
++	schedule_work(&info->se_info.timeout_work);
++}
++
+ static void st21nfca_se_activation_timeout(struct timer_list *t)
+ {
+ 	struct st21nfca_hci_info *info = from_timer(info, t,
+@@ -360,6 +368,7 @@ int st21nfca_apdu_reader_event_received(struct nfc_hci_dev *hdev,
+ 	switch (event) {
+ 	case ST21NFCA_EVT_TRANSMIT_DATA:
+ 		del_timer_sync(&info->se_info.bwi_timer);
++		cancel_work_sync(&info->se_info.timeout_work);
+ 		info->se_info.bwi_active = false;
+ 		r = nfc_hci_send_event(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+ 				ST21NFCA_EVT_SE_END_OF_APDU_TRANSFER, NULL, 0);
+@@ -389,6 +398,7 @@ void st21nfca_se_init(struct nfc_hci_dev *hdev)
+ 	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+ 
+ 	init_completion(&info->se_info.req_completion);
++	INIT_WORK(&info->se_info.timeout_work, st21nfca_se_wt_work);
+ 	/* initialize timers */
+ 	timer_setup(&info->se_info.bwi_timer, st21nfca_se_wt_timeout, 0);
+ 	info->se_info.bwi_active = false;
+@@ -416,6 +426,7 @@ void st21nfca_se_deinit(struct nfc_hci_dev *hdev)
+ 	if (info->se_info.se_active)
+ 		del_timer_sync(&info->se_info.se_active_timer);
+ 
++	cancel_work_sync(&info->se_info.timeout_work);
+ 	info->se_info.bwi_active = false;
+ 	info->se_info.se_active = false;
+ }
+diff --git a/drivers/nfc/st21nfca/st21nfca.h b/drivers/nfc/st21nfca/st21nfca.h
+index cb6ad916be91..ae6771cc9894 100644
+--- a/drivers/nfc/st21nfca/st21nfca.h
++++ b/drivers/nfc/st21nfca/st21nfca.h
+@@ -141,6 +141,7 @@ struct st21nfca_se_info {
+ 
+ 	se_io_cb_t cb;
+ 	void *cb_context;
++	struct work_struct timeout_work;
+ };
+ 
+ struct st21nfca_hci_info {

commit b8cedb7093b2d1394cae9b86494cba4b62d3a30a
+Author: Lin Ma 
+Date:   Wed May 18 18:53:21 2022 +0800
+
+    nfc: pn533: Fix buggy cleanup order
+    
+    When removing the pn533 device (i2c or USB), there is a logic error. The
+    original code first cancels the worker (flush_delayed_work) and then
+    destroys the workqueue (destroy_workqueue), leaving the timer the last
+    one to be deleted (del_timer). This result in a possible race condition
+    in a multi-core preempt-able kernel. That is, if the cleanup
+    (pn53x_common_clean) is concurrently run with the timer handler
+    (pn533_listen_mode_timer), the timer can queue the poll_work to the
+    already destroyed workqueue, causing use-after-free.
+    
+    This patch reorder the cleanup: it uses the del_timer_sync to make sure
+    the handler is finished before the routine will destroy the workqueue.
+    Note that the timer cannot be activated by the worker again.
+    
+    static void pn533_wq_poll(struct work_struct *work)
+    ...
+     rc = pn533_send_poll_frame(dev);
+     if (rc)
+       return;
+    
+     if (cur_mod->len == 0 && dev->poll_mod_count > 1)
+       mod_timer(&dev->listen_timer, ...);
+    
+    That is, the mod_timer can be called only when pn533_send_poll_frame()
+    returns no error, which is impossible because the device is detaching
+    and the lower driver should return ENODEV code.
+    
+    Signed-off-by: Lin Ma 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/nfc/pn533/pn533.c b/drivers/nfc/pn533/pn533.c
+index a491db46e3bd..d9f6367b9993 100644
+--- a/drivers/nfc/pn533/pn533.c
++++ b/drivers/nfc/pn533/pn533.c
+@@ -2787,13 +2787,14 @@ void pn53x_common_clean(struct pn533 *priv)
+ {
+ 	struct pn533_cmd *cmd, *n;
+ 
++	/* delete the timer before cleanup the worker */
++	del_timer_sync(&priv->listen_timer);
++
+ 	flush_delayed_work(&priv->poll_work);
+ 	destroy_workqueue(priv->wq);
+ 
+ 	skb_queue_purge(&priv->resp_q);
+ 
+-	del_timer(&priv->listen_timer);
+-
+ 	list_for_each_entry_safe(cmd, n, &priv->cmd_queue, queue) {
+ 		list_del(&cmd->queue);
+ 		kfree(cmd);

commit 23dd4581350d4ffa23d58976ec46408f8f4c1e16
+Author: Duoming Zhou 
+Date:   Tue May 17 09:25:30 2022 +0800
+
+    NFC: nci: fix sleep in atomic context bugs caused by nci_skb_alloc
+    
+    There are sleep in atomic context bugs when the request to secure
+    element of st-nci is timeout. The root cause is that nci_skb_alloc
+    with GFP_KERNEL parameter is called in st_nci_se_wt_timeout which is
+    a timer handler. The call paths that could trigger bugs are shown below:
+    
+        (interrupt context 1)
+    st_nci_se_wt_timeout
+      nci_hci_send_event
+        nci_hci_send_data
+          nci_skb_alloc(..., GFP_KERNEL) //may sleep
+    
+       (interrupt context 2)
+    st_nci_se_wt_timeout
+      nci_hci_send_event
+        nci_hci_send_data
+          nci_send_data
+            nci_queue_tx_data_frags
+              nci_skb_alloc(..., GFP_KERNEL) //may sleep
+    
+    This patch changes allocation mode of nci_skb_alloc from GFP_KERNEL to
+    GFP_ATOMIC in order to prevent atomic context sleeping. The GFP_ATOMIC
+    flag makes memory allocation operation could be used in atomic context.
+    
+    Fixes: ed06aeefdac3 ("nfc: st-nci: Rename st21nfcb to st-nci")
+    Signed-off-by: Duoming Zhou 
+    Reviewed-by: Krzysztof Kozlowski 
+    Link: https://lore.kernel.org/r/20220517012530.75714-1-duoming@zju.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/net/nfc/nci/data.c b/net/nfc/nci/data.c
+index 6055dc9a82aa..aa5e712adf07 100644
+--- a/net/nfc/nci/data.c
++++ b/net/nfc/nci/data.c
+@@ -118,7 +118,7 @@ static int nci_queue_tx_data_frags(struct nci_dev *ndev,
+ 
+ 		skb_frag = nci_skb_alloc(ndev,
+ 					 (NCI_DATA_HDR_SIZE + frag_len),
+-					 GFP_KERNEL);
++					 GFP_ATOMIC);
+ 		if (skb_frag == NULL) {
+ 			rc = -ENOMEM;
+ 			goto free_exit;
+diff --git a/net/nfc/nci/hci.c b/net/nfc/nci/hci.c
+index 19703a649b5a..78c4b6addf15 100644
+--- a/net/nfc/nci/hci.c
++++ b/net/nfc/nci/hci.c
+@@ -153,7 +153,7 @@ static int nci_hci_send_data(struct nci_dev *ndev, u8 pipe,
+ 
+ 	i = 0;
+ 	skb = nci_skb_alloc(ndev, conn_info->max_pkt_payload_len +
+-			    NCI_DATA_HDR_SIZE, GFP_KERNEL);
++			    NCI_DATA_HDR_SIZE, GFP_ATOMIC);
+ 	if (!skb)
+ 		return -ENOMEM;
+ 
+@@ -184,7 +184,7 @@ static int nci_hci_send_data(struct nci_dev *ndev, u8 pipe,
+ 		if (i < data_len) {
+ 			skb = nci_skb_alloc(ndev,
+ 					    conn_info->max_pkt_payload_len +
+-					    NCI_DATA_HDR_SIZE, GFP_KERNEL);
++					    NCI_DATA_HDR_SIZE, GFP_ATOMIC);
+ 			if (!skb)
+ 				return -ENOMEM;
+ 

commit 2def44d3aec59e38d2701c568d65540783f90f2f
+Author: Lin Ma 
+Date:   Mon May 16 17:20:35 2022 +0800
+
+    ASoC: rt5645: Fix errorenous cleanup order
+    
+    There is a logic error when removing rt5645 device as the function
+    rt5645_i2c_remove() first cancel the &rt5645->jack_detect_work and
+    delete the &rt5645->btn_check_timer latter. However, since the timer
+    handler rt5645_btn_check_callback() will re-queue the jack_detect_work,
+    this cleanup order is buggy.
+    
+    That is, once the del_timer_sync in rt5645_i2c_remove is concurrently
+    run with the rt5645_btn_check_callback, the canceled jack_detect_work
+    will be rescheduled again, leading to possible use-after-free.
+    
+    This patch fix the issue by placing the del_timer_sync function before
+    the cancel_delayed_work_sync.
+    
+    Signed-off-by: Lin Ma 
+    Link: https://lore.kernel.org/r/20220516092035.28283-1-linma@zju.edu.cn
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
+index ccdea234a3ba..507aba8de3cc 100644
+--- a/sound/soc/codecs/rt5645.c
++++ b/sound/soc/codecs/rt5645.c
+@@ -4153,9 +4153,14 @@ static int rt5645_i2c_remove(struct i2c_client *i2c)
+ 	if (i2c->irq)
+ 		free_irq(i2c->irq, rt5645);
+ 
++	/*
++	 * Since the rt5645_btn_check_callback() can queue jack_detect_work,
++	 * the timer need to be delted first
++	 */
++	del_timer_sync(&rt5645->btn_check_timer);
++
+ 	cancel_delayed_work_sync(&rt5645->jack_detect_work);
+ 	cancel_delayed_work_sync(&rt5645->rcclock_work);
+-	del_timer_sync(&rt5645->btn_check_timer);
+ 
+ 	regulator_bulk_disable(ARRAY_SIZE(rt5645->supplies), rt5645->supplies);
+ 

commit 4071bf121d59944d5cd2238de0642f3d7995a997
+Author: Duoming Zhou 
+Date:   Wed May 4 13:58:47 2022 +0800
+
+    NFC: netlink: fix sleep in atomic bug when firmware download timeout
+    
+    There are sleep in atomic bug that could cause kernel panic during
+    firmware download process. The root cause is that nlmsg_new with
+    GFP_KERNEL parameter is called in fw_dnld_timeout which is a timer
+    handler. The call trace is shown below:
+    
+    BUG: sleeping function called from invalid context at include/linux/sched/mm.h:265
+    Call Trace:
+    kmem_cache_alloc_node
+    __alloc_skb
+    nfc_genl_fw_download_done
+    call_timer_fn
+    __run_timers.part.0
+    run_timer_softirq
+    __do_softirq
+    ...
+    
+    The nlmsg_new with GFP_KERNEL parameter may sleep during memory
+    allocation process, and the timer handler is run as the result of
+    a "software interrupt" that should not call any other function
+    that could sleep.
+    
+    This patch changes allocation mode of netlink message from GFP_KERNEL
+    to GFP_ATOMIC in order to prevent sleep in atomic bug. The GFP_ATOMIC
+    flag makes memory allocation operation could be used in atomic context.
+    
+    Fixes: 9674da8759df ("NFC: Add firmware upload netlink command")
+    Fixes: 9ea7187c53f6 ("NFC: netlink: Rename CMD_FW_UPLOAD to CMD_FW_DOWNLOAD")
+    Signed-off-by: Duoming Zhou 
+    Reviewed-by: Krzysztof Kozlowski 
+    Link: https://lore.kernel.org/r/20220504055847.38026-1-duoming@zju.edu.cn
+    Signed-off-by: Paolo Abeni 
+
+diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
+index f184b0db79d4..7c62417ccfd7 100644
+--- a/net/nfc/netlink.c
++++ b/net/nfc/netlink.c
+@@ -1244,7 +1244,7 @@ int nfc_genl_fw_download_done(struct nfc_dev *dev, const char *firmware_name,
+ 	struct sk_buff *msg;
+ 	void *hdr;
+ 
+-	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
++	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
+ 	if (!msg)
+ 		return -ENOMEM;
+ 
+@@ -1260,7 +1260,7 @@ int nfc_genl_fw_download_done(struct nfc_dev *dev, const char *firmware_name,
+ 
+ 	genlmsg_end(msg, hdr);
+ 
+-	genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL);
++	genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_ATOMIC);
+ 
+ 	return 0;
+ 

commit d270453a0d9ec10bb8a802a142fb1b3601a83098
+Author: Duoming Zhou 
+Date:   Fri Apr 29 20:45:51 2022 +0800
+
+    nfc: nfcmrvl: main: reorder destructive operations in nfcmrvl_nci_unregister_dev to avoid bugs
+    
+    There are destructive operations such as nfcmrvl_fw_dnld_abort and
+    gpio_free in nfcmrvl_nci_unregister_dev. The resources such as firmware,
+    gpio and so on could be destructed while the upper layer functions such as
+    nfcmrvl_fw_dnld_start and nfcmrvl_nci_recv_frame is executing, which leads
+    to double-free, use-after-free and null-ptr-deref bugs.
+    
+    There are three situations that could lead to double-free bugs.
+    
+    The first situation is shown below:
+    
+       (Thread 1)                 |      (Thread 2)
+    nfcmrvl_fw_dnld_start         |
+     ...                          |  nfcmrvl_nci_unregister_dev
+     release_firmware()           |   nfcmrvl_fw_dnld_abort
+      kfree(fw) //(1)             |    fw_dnld_over
+                                  |     release_firmware
+      ...                         |      kfree(fw) //(2)
+                                  |     ...
+    
+    The second situation is shown below:
+    
+       (Thread 1)                 |      (Thread 2)
+    nfcmrvl_fw_dnld_start         |
+     ...                          |
+     mod_timer                    |
+     (wait a time)                |
+     fw_dnld_timeout              |  nfcmrvl_nci_unregister_dev
+       fw_dnld_over               |   nfcmrvl_fw_dnld_abort
+        release_firmware          |    fw_dnld_over
+         kfree(fw) //(1)          |     release_firmware
+         ...                      |      kfree(fw) //(2)
+    
+    The third situation is shown below:
+    
+           (Thread 1)               |       (Thread 2)
+    nfcmrvl_nci_recv_frame          |
+     if(..->fw_download_in_progress)|
+      nfcmrvl_fw_dnld_recv_frame    |
+       queue_work                   |
+                                    |
+    fw_dnld_rx_work                 | nfcmrvl_nci_unregister_dev
+     fw_dnld_over                   |  nfcmrvl_fw_dnld_abort
+      release_firmware              |   fw_dnld_over
+       kfree(fw) //(1)              |    release_firmware
+                                    |     kfree(fw) //(2)
+    
+    The firmware struct is deallocated in position (1) and deallocated
+    in position (2) again.
+    
+    The crash trace triggered by POC is like below:
+    
+    BUG: KASAN: double-free or invalid-free in fw_dnld_over
+    Call Trace:
+      kfree
+      fw_dnld_over
+      nfcmrvl_nci_unregister_dev
+      nci_uart_tty_close
+      tty_ldisc_kill
+      tty_ldisc_hangup
+      __tty_hangup.part.0
+      tty_release
+      ...
+    
+    What's more, there are also use-after-free and null-ptr-deref bugs
+    in nfcmrvl_fw_dnld_start. If we deallocate firmware struct, gpio or
+    set null to the members of priv->fw_dnld in nfcmrvl_nci_unregister_dev,
+    then, we dereference firmware, gpio or the members of priv->fw_dnld in
+    nfcmrvl_fw_dnld_start, the UAF or NPD bugs will happen.
+    
+    This patch reorders destructive operations after nci_unregister_device
+    in order to synchronize between cleanup routine and firmware download
+    routine.
+    
+    The nci_unregister_device is well synchronized. If the device is
+    detaching, the firmware download routine will goto error. If firmware
+    download routine is executing, nci_unregister_device will wait until
+    firmware download routine is finished.
+    
+    Fixes: 3194c6870158 ("NFC: nfcmrvl: add firmware download support")
+    Signed-off-by: Duoming Zhou 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/nfc/nfcmrvl/main.c b/drivers/nfc/nfcmrvl/main.c
+index 2fcf545012b1..1a5284de4341 100644
+--- a/drivers/nfc/nfcmrvl/main.c
++++ b/drivers/nfc/nfcmrvl/main.c
+@@ -183,6 +183,7 @@ void nfcmrvl_nci_unregister_dev(struct nfcmrvl_private *priv)
+ {
+ 	struct nci_dev *ndev = priv->ndev;
+ 
++	nci_unregister_device(ndev);
+ 	if (priv->ndev->nfc_dev->fw_download_in_progress)
+ 		nfcmrvl_fw_dnld_abort(priv);
+ 
+@@ -191,7 +192,6 @@ void nfcmrvl_nci_unregister_dev(struct nfcmrvl_private *priv)
+ 	if (gpio_is_valid(priv->config.reset_n_io))
+ 		gpio_free(priv->config.reset_n_io);
+ 
+-	nci_unregister_device(ndev);
+ 	nci_free_device(ndev);
+ 	kfree(priv);
+ }

commit da5c0f119203ad9728920456a0f52a6d850c01cd
+Author: Duoming Zhou 
+Date:   Fri Apr 29 20:45:50 2022 +0800
+
+    nfc: replace improper check device_is_registered() in netlink related functions
+    
+    The device_is_registered() in nfc core is used to check whether
+    nfc device is registered in netlink related functions such as
+    nfc_fw_download(), nfc_dev_up() and so on. Although device_is_registered()
+    is protected by device_lock, there is still a race condition between
+    device_del() and device_is_registered(). The root cause is that
+    kobject_del() in device_del() is not protected by device_lock.
+    
+       (cleanup task)         |     (netlink task)
+                              |
+    nfc_unregister_device     | nfc_fw_download
+     device_del               |  device_lock
+      ...                     |   if (!device_is_registered)//(1)
+      kobject_del//(2)        |   ...
+     ...                      |  device_unlock
+    
+    The device_is_registered() returns the value of state_in_sysfs and
+    the state_in_sysfs is set to zero in kobject_del(). If we pass check in
+    position (1), then set zero in position (2). As a result, the check
+    in position (1) is useless.
+    
+    This patch uses bool variable instead of device_is_registered() to judge
+    whether the nfc device is registered, which is well synchronized.
+    
+    Fixes: 3e256b8f8dfa ("NFC: add nfc subsystem core")
+    Signed-off-by: Duoming Zhou 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/nfc/core.c b/net/nfc/core.c
+index dc7a2404efdf..5b286e1e0a6f 100644
+--- a/net/nfc/core.c
++++ b/net/nfc/core.c
+@@ -38,7 +38,7 @@ int nfc_fw_download(struct nfc_dev *dev, const char *firmware_name)
+ 
+ 	device_lock(&dev->dev);
+ 
+-	if (!device_is_registered(&dev->dev)) {
++	if (dev->shutting_down) {
+ 		rc = -ENODEV;
+ 		goto error;
+ 	}
+@@ -94,7 +94,7 @@ int nfc_dev_up(struct nfc_dev *dev)
+ 
+ 	device_lock(&dev->dev);
+ 
+-	if (!device_is_registered(&dev->dev)) {
++	if (dev->shutting_down) {
+ 		rc = -ENODEV;
+ 		goto error;
+ 	}
+@@ -142,7 +142,7 @@ int nfc_dev_down(struct nfc_dev *dev)
+ 
+ 	device_lock(&dev->dev);
+ 
+-	if (!device_is_registered(&dev->dev)) {
++	if (dev->shutting_down) {
+ 		rc = -ENODEV;
+ 		goto error;
+ 	}
+@@ -207,7 +207,7 @@ int nfc_start_poll(struct nfc_dev *dev, u32 im_protocols, u32 tm_protocols)
+ 
+ 	device_lock(&dev->dev);
+ 
+-	if (!device_is_registered(&dev->dev)) {
++	if (dev->shutting_down) {
+ 		rc = -ENODEV;
+ 		goto error;
+ 	}
+@@ -246,7 +246,7 @@ int nfc_stop_poll(struct nfc_dev *dev)
+ 
+ 	device_lock(&dev->dev);
+ 
+-	if (!device_is_registered(&dev->dev)) {
++	if (dev->shutting_down) {
+ 		rc = -ENODEV;
+ 		goto error;
+ 	}
+@@ -291,7 +291,7 @@ int nfc_dep_link_up(struct nfc_dev *dev, int target_index, u8 comm_mode)
+ 
+ 	device_lock(&dev->dev);
+ 
+-	if (!device_is_registered(&dev->dev)) {
++	if (dev->shutting_down) {
+ 		rc = -ENODEV;
+ 		goto error;
+ 	}
+@@ -335,7 +335,7 @@ int nfc_dep_link_down(struct nfc_dev *dev)
+ 
+ 	device_lock(&dev->dev);
+ 
+-	if (!device_is_registered(&dev->dev)) {
++	if (dev->shutting_down) {
+ 		rc = -ENODEV;
+ 		goto error;
+ 	}
+@@ -401,7 +401,7 @@ int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol)
+ 
+ 	device_lock(&dev->dev);
+ 
+-	if (!device_is_registered(&dev->dev)) {
++	if (dev->shutting_down) {
+ 		rc = -ENODEV;
+ 		goto error;
+ 	}
+@@ -448,7 +448,7 @@ int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx, u8 mode)
+ 
+ 	device_lock(&dev->dev);
+ 
+-	if (!device_is_registered(&dev->dev)) {
++	if (dev->shutting_down) {
+ 		rc = -ENODEV;
+ 		goto error;
+ 	}
+@@ -495,7 +495,7 @@ int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb,
+ 
+ 	device_lock(&dev->dev);
+ 
+-	if (!device_is_registered(&dev->dev)) {
++	if (dev->shutting_down) {
+ 		rc = -ENODEV;
+ 		kfree_skb(skb);
+ 		goto error;
+@@ -552,7 +552,7 @@ int nfc_enable_se(struct nfc_dev *dev, u32 se_idx)
+ 
+ 	device_lock(&dev->dev);
+ 
+-	if (!device_is_registered(&dev->dev)) {
++	if (dev->shutting_down) {
+ 		rc = -ENODEV;
+ 		goto error;
+ 	}
+@@ -601,7 +601,7 @@ int nfc_disable_se(struct nfc_dev *dev, u32 se_idx)
+ 
+ 	device_lock(&dev->dev);
+ 
+-	if (!device_is_registered(&dev->dev)) {
++	if (dev->shutting_down) {
+ 		rc = -ENODEV;
+ 		goto error;
+ 	}
+@@ -1134,6 +1134,7 @@ int nfc_register_device(struct nfc_dev *dev)
+ 			dev->rfkill = NULL;
+ 		}
+ 	}
++	dev->shutting_down = false;
+ 	device_unlock(&dev->dev);
+ 
+ 	rc = nfc_genl_device_added(dev);
+@@ -1166,12 +1167,10 @@ void nfc_unregister_device(struct nfc_dev *dev)
+ 		rfkill_unregister(dev->rfkill);
+ 		rfkill_destroy(dev->rfkill);
+ 	}
++	dev->shutting_down = true;
+ 	device_unlock(&dev->dev);
+ 
+ 	if (dev->ops->check_presence) {
+-		device_lock(&dev->dev);
+-		dev->shutting_down = true;
+-		device_unlock(&dev->dev);
+ 		del_timer_sync(&dev->check_pres_timer);
+ 		cancel_work_sync(&dev->check_pres_work);
+ 	}

commit 47f070a63e735bcc8d481de31be1b5a1aa62b31c
+Author: Duoming Zhou 
+Date:   Mon Apr 25 12:24:00 2022 +0800
+
+    can: grcan: grcan_close(): fix deadlock
+    
+    There are deadlocks caused by del_timer_sync(&priv->hang_timer) and
+    del_timer_sync(&priv->rr_timer) in grcan_close(), one of the deadlocks
+    are shown below:
+    
+       (Thread 1)              |      (Thread 2)
+                               | grcan_reset_timer()
+    grcan_close()              |  mod_timer()
+     spin_lock_irqsave() //(1) |  (wait a time)
+     ...                       | grcan_initiate_running_reset()
+     del_timer_sync()          |  spin_lock_irqsave() //(2)
+     (wait timer to stop)      |  ...
+    
+    We hold priv->lock in position (1) of thread 1 and use
+    del_timer_sync() to wait timer to stop, but timer handler also need
+    priv->lock in position (2) of thread 2. As a result, grcan_close()
+    will block forever.
+    
+    This patch extracts del_timer_sync() from the protection of
+    spin_lock_irqsave(), which could let timer handler to obtain the
+    needed lock.
+    
+    Link: https://lore.kernel.org/all/20220425042400.66517-1-duoming@zju.edu.cn
+    Fixes: 6cec9b07fe6a ("can: grcan: Add device driver for GRCAN and GRHCAN cores")
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Duoming Zhou 
+    Reviewed-by: Andreas Larsson 
+    Signed-off-by: Marc Kleine-Budde 
+
+diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c
+index d0c5a7a60daf..1189057b5d68 100644
+--- a/drivers/net/can/grcan.c
++++ b/drivers/net/can/grcan.c
+@@ -1102,8 +1102,10 @@ static int grcan_close(struct net_device *dev)
+ 
+ 	priv->closing = true;
+ 	if (priv->need_txbug_workaround) {
++		spin_unlock_irqrestore(&priv->lock, flags);
+ 		del_timer_sync(&priv->hang_timer);
+ 		del_timer_sync(&priv->rr_timer);
++		spin_lock_irqsave(&priv->lock, flags);
+ 	}
+ 	netif_stop_queue(dev);
+ 	grcan_stop_hardware(dev);

commit b561275d633bcd8e0e8055ab86f1a13df75a0269
+Author: Lin Ma 
+Date:   Fri Apr 22 19:43:40 2022 +0800
+
+    mctp: defer the kfree of object mdev->addrs
+    
+    The function mctp_unregister() reclaims the device's relevant resource
+    when a netcard detaches. However, a running routine may be unaware of
+    this and cause the use-after-free of the mdev->addrs object.
+    
+    The race condition can be demonstrated below
+    
+     cleanup thread               another thread
+                              |
+    unregister_netdev()       |  mctp_sendmsg()
+    ...                       |    ...
+      mctp_unregister()       |    rt = mctp_route_lookup()
+        ...                   |    mctl_local_output()
+        kfree(mdev->addrs)    |      ...
+                              |      saddr = rt->dev->addrs[0];
+                              |
+    
+    An attacker can adopt the (recent provided) mtcpserial driver with pty
+    to fake the device detaching and use the userfaultfd to increase the
+    race success chance (in mctp_sendmsg). The KASan report for such a POC
+    is shown below:
+    
+    [   86.051955] ==================================================================
+    [   86.051955] BUG: KASAN: use-after-free in mctp_local_output+0x4e9/0xb7d
+    [   86.051955] Read of size 1 at addr ffff888005f298c0 by task poc/295
+    [   86.051955]
+    [   86.051955] Call Trace:
+    [   86.051955]  
+    [   86.051955]  dump_stack_lvl+0x33/0x42
+    [   86.051955]  print_report.cold.13+0xb2/0x6b3
+    [   86.051955]  ? preempt_schedule_irq+0x57/0x80
+    [   86.051955]  ? mctp_local_output+0x4e9/0xb7d
+    [   86.051955]  kasan_report+0xa5/0x120
+    [   86.051955]  ? mctp_local_output+0x4e9/0xb7d
+    [   86.051955]  mctp_local_output+0x4e9/0xb7d
+    [   86.051955]  ? mctp_dev_set_key+0x79/0x79
+    [   86.051955]  ? copyin+0x38/0x50
+    [   86.051955]  ? _copy_from_iter+0x1b6/0xf20
+    [   86.051955]  ? sysvec_apic_timer_interrupt+0x97/0xb0
+    [   86.051955]  ? asm_sysvec_apic_timer_interrupt+0x12/0x20
+    [   86.051955]  ? mctp_local_output+0x1/0xb7d
+    [   86.051955]  mctp_sendmsg+0x64d/0xdb0
+    [   86.051955]  ? mctp_sk_close+0x20/0x20
+    [   86.051955]  ? __fget_light+0x2fd/0x4f0
+    [   86.051955]  ? mctp_sk_close+0x20/0x20
+    [   86.051955]  sock_sendmsg+0xdd/0x110
+    [   86.051955]  __sys_sendto+0x1cc/0x2a0
+    [   86.051955]  ? __ia32_sys_getpeername+0xa0/0xa0
+    [   86.051955]  ? new_sync_write+0x335/0x550
+    [   86.051955]  ? alloc_file+0x22f/0x500
+    [   86.051955]  ? __ip_do_redirect+0x820/0x1820
+    [   86.051955]  ? vfs_write+0x44d/0x7b0
+    [   86.051955]  ? vfs_write+0x44d/0x7b0
+    [   86.051955]  ? fput_many+0x15/0x120
+    [   86.051955]  ? ksys_write+0x155/0x1b0
+    [   86.051955]  ? __ia32_sys_read+0xa0/0xa0
+    [   86.051955]  __x64_sys_sendto+0xd8/0x1b0
+    [   86.051955]  ? exit_to_user_mode_prepare+0x2f/0x120
+    [   86.051955]  ? syscall_exit_to_user_mode+0x12/0x20
+    [   86.051955]  do_syscall_64+0x3a/0x80
+    [   86.051955]  entry_SYSCALL_64_after_hwframe+0x44/0xae
+    [   86.051955] RIP: 0033:0x7f82118a56b3
+    [   86.051955] RSP: 002b:00007ffdb154b110 EFLAGS: 00000293 ORIG_RAX: 000000000000002c
+    [   86.051955] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f82118a56b3
+    [   86.051955] RDX: 0000000000000010 RSI: 00007f8211cd4000 RDI: 0000000000000007
+    [   86.051955] RBP: 00007ffdb154c1d0 R08: 00007ffdb154b164 R09: 000000000000000c
+    [   86.051955] R10: 0000000000000000 R11: 0000000000000293 R12: 000055d779800db0
+    [   86.051955] R13: 00007ffdb154c2b0 R14: 0000000000000000 R15: 0000000000000000
+    [   86.051955]  
+    [   86.051955]
+    [   86.051955] Allocated by task 295:
+    [   86.051955]  kasan_save_stack+0x1c/0x40
+    [   86.051955]  __kasan_kmalloc+0x84/0xa0
+    [   86.051955]  mctp_rtm_newaddr+0x242/0x610
+    [   86.051955]  rtnetlink_rcv_msg+0x2fd/0x8b0
+    [   86.051955]  netlink_rcv_skb+0x11c/0x340
+    [   86.051955]  netlink_unicast+0x439/0x630
+    [   86.051955]  netlink_sendmsg+0x752/0xc00
+    [   86.051955]  sock_sendmsg+0xdd/0x110
+    [   86.051955]  __sys_sendto+0x1cc/0x2a0
+    [   86.051955]  __x64_sys_sendto+0xd8/0x1b0
+    [   86.051955]  do_syscall_64+0x3a/0x80
+    [   86.051955]  entry_SYSCALL_64_after_hwframe+0x44/0xae
+    [   86.051955]
+    [   86.051955] Freed by task 301:
+    [   86.051955]  kasan_save_stack+0x1c/0x40
+    [   86.051955]  kasan_set_track+0x21/0x30
+    [   86.051955]  kasan_set_free_info+0x20/0x30
+    [   86.051955]  __kasan_slab_free+0x104/0x170
+    [   86.051955]  kfree+0x8c/0x290
+    [   86.051955]  mctp_dev_notify+0x161/0x2c0
+    [   86.051955]  raw_notifier_call_chain+0x8b/0xc0
+    [   86.051955]  unregister_netdevice_many+0x299/0x1180
+    [   86.051955]  unregister_netdevice_queue+0x210/0x2f0
+    [   86.051955]  unregister_netdev+0x13/0x20
+    [   86.051955]  mctp_serial_close+0x6d/0xa0
+    [   86.051955]  tty_ldisc_kill+0x31/0xa0
+    [   86.051955]  tty_ldisc_hangup+0x24f/0x560
+    [   86.051955]  __tty_hangup.part.28+0x2ce/0x6b0
+    [   86.051955]  tty_release+0x327/0xc70
+    [   86.051955]  __fput+0x1df/0x8b0
+    [   86.051955]  task_work_run+0xca/0x150
+    [   86.051955]  exit_to_user_mode_prepare+0x114/0x120
+    [   86.051955]  syscall_exit_to_user_mode+0x12/0x20
+    [   86.051955]  do_syscall_64+0x46/0x80
+    [   86.051955]  entry_SYSCALL_64_after_hwframe+0x44/0xae
+    [   86.051955]
+    [   86.051955] The buggy address belongs to the object at ffff888005f298c0
+    [   86.051955]  which belongs to the cache kmalloc-8 of size 8
+    [   86.051955] The buggy address is located 0 bytes inside of
+    [   86.051955]  8-byte region [ffff888005f298c0, ffff888005f298c8)
+    [   86.051955]
+    [   86.051955] The buggy address belongs to the physical page:
+    [   86.051955] flags: 0x100000000000200(slab|node=0|zone=1)
+    [   86.051955] raw: 0100000000000200 dead000000000100 dead000000000122 ffff888005c42280
+    [   86.051955] raw: 0000000000000000 0000000080660066 00000001ffffffff 0000000000000000
+    [   86.051955] page dumped because: kasan: bad access detected
+    [   86.051955]
+    [   86.051955] Memory state around the buggy address:
+    [   86.051955]  ffff888005f29780: 00 fc fc fc fc 00 fc fc fc fc 00 fc fc fc fc 00
+    [   86.051955]  ffff888005f29800: fc fc fc fc 00 fc fc fc fc 00 fc fc fc fc 00 fc
+    [   86.051955] >ffff888005f29880: fc fc fc fb fc fc fc fc fa fc fc fc fc fa fc fc
+    [   86.051955]                                            ^
+    [   86.051955]  ffff888005f29900: fc fc 00 fc fc fc fc 00 fc fc fc fc 00 fc fc fc
+    [   86.051955]  ffff888005f29980: fc 00 fc fc fc fc 00 fc fc fc fc 00 fc fc fc fc
+    [   86.051955] ==================================================================
+    
+    To this end, just like the commit e04480920d1e ("Bluetooth: defer
+    cleanup of resources in hci_unregister_dev()")  this patch defers the
+    destructive kfree(mdev->addrs) in mctp_unregister to the mctp_dev_put,
+    where the refcount of mdev is zero and the entire device is reclaimed.
+    This prevents the use-after-free because the sendmsg thread holds the
+    reference of mdev in the mctp_route object.
+    
+    Fixes: 583be982d934 (mctp: Add device handling and netlink interface)
+    Signed-off-by: Lin Ma 
+    Acked-by: Jeremy Kerr 
+    Link: https://lore.kernel.org/r/20220422114340.32346-1-linma@zju.edu.cn
+    Signed-off-by: Paolo Abeni 
+
+diff --git a/net/mctp/device.c b/net/mctp/device.c
+index f49be882e98e..99a3bda8852f 100644
+--- a/net/mctp/device.c
++++ b/net/mctp/device.c
+@@ -313,6 +313,7 @@ void mctp_dev_hold(struct mctp_dev *mdev)
+ void mctp_dev_put(struct mctp_dev *mdev)
+ {
+ 	if (mdev && refcount_dec_and_test(&mdev->refs)) {
++		kfree(mdev->addrs);
+ 		dev_put(mdev->dev);
+ 		kfree_rcu(mdev, rcu);
+ 	}
+@@ -441,7 +442,6 @@ static void mctp_unregister(struct net_device *dev)
+ 
+ 	mctp_route_remove_dev(mdev);
+ 	mctp_neigh_remove_dev(mdev);
+-	kfree(mdev->addrs);
+ 
+ 	mctp_dev_put(mdev);
+ }

commit 4d378f2ae58138d4c55684e1d274e7dd94aa6524
+Author: Duoming Zhou 
+Date:   Sun Apr 17 20:03:05 2022 +0800
+
+    drivers: usb: host: Fix deadlock in oxu_bus_suspend()
+    
+    There is a deadlock in oxu_bus_suspend(), which is shown below:
+    
+       (Thread 1)              |      (Thread 2)
+                               | timer_action()
+    oxu_bus_suspend()          |  mod_timer()
+     spin_lock_irq() //(1)     |  (wait a time)
+     ...                       | oxu_watchdog()
+     del_timer_sync()          |  spin_lock_irq() //(2)
+     (wait timer to stop)      |  ...
+    
+    We hold oxu->lock in position (1) of thread 1, and use
+    del_timer_sync() to wait timer to stop, but timer handler
+    also need oxu->lock in position (2) of thread 2. As a result,
+    oxu_bus_suspend() will block forever.
+    
+    This patch extracts del_timer_sync() from the protection of
+    spin_lock_irq(), which could let timer handler to obtain
+    the needed lock.
+    
+    Signed-off-by: Duoming Zhou 
+    Link: https://lore.kernel.org/r/20220417120305.64577-1-duoming@zju.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
+index ddc155850bfc..8b73c61f86c9 100644
+--- a/drivers/usb/host/oxu210hp-hcd.c
++++ b/drivers/usb/host/oxu210hp-hcd.c
+@@ -3909,8 +3909,10 @@ static int oxu_bus_suspend(struct usb_hcd *hcd)
+ 		}
+ 	}
+ 
++	spin_unlock_irq(&oxu->lock);
+ 	/* turn off now-idle HC */
+ 	del_timer_sync(&oxu->watchdog);
++	spin_lock_irq(&oxu->lock);
+ 	ehci_halt(oxu);
+ 	hcd->state = HC_STATE_SUSPENDED;
+ 

commit 62b2caef400c1738b6d22f636c628d9f85cd4c4c
+Author: Duoming Zhou 
+Date:   Sun Apr 17 19:16:26 2022 +0800
+
+    drivers: tty: serial: Fix deadlock in sa1100_set_termios()
+    
+    There is a deadlock in sa1100_set_termios(), which is shown
+    below:
+    
+       (Thread 1)              |      (Thread 2)
+                               | sa1100_enable_ms()
+    sa1100_set_termios()       |  mod_timer()
+     spin_lock_irqsave() //(1) |  (wait a time)
+     ...                       | sa1100_timeout()
+     del_timer_sync()          |  spin_lock_irqsave() //(2)
+     (wait timer to stop)      |  ...
+    
+    We hold sport->port.lock in position (1) of thread 1 and
+    use del_timer_sync() to wait timer to stop, but timer handler
+    also need sport->port.lock in position (2) of thread 2. As a result,
+    sa1100_set_termios() will block forever.
+    
+    This patch moves del_timer_sync() before spin_lock_irqsave()
+    in order to prevent the deadlock.
+    
+    Signed-off-by: Duoming Zhou 
+    Link: https://lore.kernel.org/r/20220417111626.7802-1-duoming@zju.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c
+index 5fe6cccfc1ae..e64e42a19d1a 100644
+--- a/drivers/tty/serial/sa1100.c
++++ b/drivers/tty/serial/sa1100.c
+@@ -446,6 +446,8 @@ sa1100_set_termios(struct uart_port *port, struct ktermios *termios,
+ 	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 
+ 	quot = uart_get_divisor(port, baud);
+ 
++	del_timer_sync(&sport->timer);
++
+ 	spin_lock_irqsave(&sport->port.lock, flags);
+ 
+ 	sport->port.read_status_mask &= UTSR0_TO_SM(UTSR0_TFS);
+@@ -476,8 +478,6 @@ sa1100_set_termios(struct uart_port *port, struct ktermios *termios,
+ 				UTSR1_TO_SM(UTSR1_ROR);
+ 	}
+ 
+-	del_timer_sync(&sport->timer);
+-
+ 	/*
+ 	 * Update the per-port timeout.
+ 	 */

commit b92ffb1eddd9a66a90defc556dcbf65a43c196c7
+Author: Lin Ma 
+Date:   Tue Apr 12 22:43:59 2022 +0800
+
+    USB: storage: karma: fix rio_karma_init return
+    
+    The function rio_karam_init() should return -ENOMEM instead of
+    value 0 (USB_STOR_TRANSPORT_GOOD) when allocation fails.
+    
+    Similarly, it should return -EIO when rio_karma_send_command() fails.
+    
+    Fixes: dfe0d3ba20e8 ("USB Storage: add rio karma eject support")
+    Acked-by: Alan Stern 
+    Signed-off-by: Lin Ma 
+    Link: https://lore.kernel.org/r/20220412144359.28447-1-linma@zju.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c
+index 05cec81dcd3f..38ddfedef629 100644
+--- a/drivers/usb/storage/karma.c
++++ b/drivers/usb/storage/karma.c
+@@ -174,24 +174,25 @@ static void rio_karma_destructor(void *extra)
+ 
+ static int rio_karma_init(struct us_data *us)
+ {
+-	int ret = 0;
+ 	struct karma_data *data = kzalloc(sizeof(struct karma_data), GFP_NOIO);
+ 
+ 	if (!data)
+-		goto out;
++		return -ENOMEM;
+ 
+ 	data->recv = kmalloc(RIO_RECV_LEN, GFP_NOIO);
+ 	if (!data->recv) {
+ 		kfree(data);
+-		goto out;
++		return -ENOMEM;
+ 	}
+ 
+ 	us->extra = data;
+ 	us->extra_destructor = rio_karma_destructor;
+-	ret = rio_karma_send_command(RIO_ENTER_STORAGE, us);
+-	data->in_storage = (ret == 0);
+-out:
+-	return ret;
++	if (rio_karma_send_command(RIO_ENTER_STORAGE, us))
++		return -EIO;
++
++	data->in_storage = 1;
++
++	return 0;
+ }
+ 
+ static struct scsi_host_template karma_host_template;

commit ba6df3ea68196d54a1e8299cea1bf4565fc755c5
+Author: Lin Ma 
+Date:   Thu Apr 7 10:21:10 2022 +0800
+
+    usb-storage: isd200: fix initFunction error return
+    
+    The initFunction is called when probing a new device, its call relation
+    is like:
+    
+    USB core: probe() -> usb_stor_probe2() -> usb_stor_acquire_resources()
+    -> isd200_init_info()
+    
+    That is, the error return of the initFunction should tell USB core what
+    happened instead of using custom error code like ISD200_ERROR.
+    
+    Signed-off-by: Lin Ma 
+    Link: https://lore.kernel.org/r/20220407022110.3757-1-linma@zju.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
+index 05429f1f69f9..4e0eef1440b7 100644
+--- a/drivers/usb/storage/isd200.c
++++ b/drivers/usb/storage/isd200.c
+@@ -1449,7 +1449,7 @@ static void isd200_free_info_ptrs(void *info_)
+  * Allocates (if necessary) and initializes the driver structure.
+  *
+  * RETURNS:
+- *    ISD status code
++ *    error status code
+  */
+ static int isd200_init_info(struct us_data *us)
+ {
+@@ -1457,7 +1457,7 @@ static int isd200_init_info(struct us_data *us)
+ 
+ 	info = kzalloc(sizeof(struct isd200_info), GFP_KERNEL);
+ 	if (!info)
+-		return ISD200_ERROR;
++		return -ENOMEM;
+ 
+ 	info->id = kzalloc(ATA_ID_WORDS * 2, GFP_KERNEL);
+ 	info->RegsBuf = kmalloc(sizeof(info->ATARegs), GFP_KERNEL);
+@@ -1466,13 +1466,13 @@ static int isd200_init_info(struct us_data *us)
+ 	if (!info->id || !info->RegsBuf || !info->srb.sense_buffer) {
+ 		isd200_free_info_ptrs(info);
+ 		kfree(info);
+-		return ISD200_ERROR;
++		return -ENOMEM;
+ 	}
+ 
+ 	us->extra = info;
+ 	us->extra_destructor = isd200_free_info_ptrs;
+ 
+-	return ISD200_GOOD;
++	return 0;
+ }
+ 
+ /**************************************************************************

commit 1abf67983a4fd74133b3d2b43722704c744621a6
+Author: Lin Ma 
+Date:   Thu Apr 7 10:21:15 2022 +0800
+
+    usb-storage: shuttle_usbat: fix initFunction error return
+    
+    The initFunction is called when probing a new device, its call relation
+    is like:
+    USB core: probe() -> usb_stor_probe2() -> usb_stor_acquire_resources()
+    -> init_usbat_cd() or init_usbat_flash() -> init_usbat()
+    
+    That is, the error return of the initFunction should tell USB core what
+    happened instead of using constant or error code like
+    USB_STOR_TRANSPORT_FAILED.
+    
+    Signed-off-by: Lin Ma 
+    Link: https://lore.kernel.org/r/20220407022115.3773-1-linma@zju.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
+index 54aa1392c9ca..f0d0ca37163d 100644
+--- a/drivers/usb/storage/shuttle_usbat.c
++++ b/drivers/usb/storage/shuttle_usbat.c
+@@ -1456,7 +1456,7 @@ static int init_usbat(struct us_data *us, int devicetype)
+ 
+ 	us->extra = kzalloc(sizeof(struct usbat_info), GFP_NOIO);
+ 	if (!us->extra)
+-		return 1;
++		return -ENOMEM;
+ 
+ 	info = (struct usbat_info *) (us->extra);
+ 
+@@ -1465,7 +1465,7 @@ static int init_usbat(struct us_data *us, int devicetype)
+ 				 USBAT_UIO_OE1 | USBAT_UIO_OE0,
+ 				 USBAT_UIO_EPAD | USBAT_UIO_1);
+ 	if (rc != USB_STOR_XFER_GOOD)
+-		return USB_STOR_TRANSPORT_ERROR;
++		return -EIO;
+ 
+ 	usb_stor_dbg(us, "INIT 1\n");
+ 
+@@ -1473,42 +1473,42 @@ static int init_usbat(struct us_data *us, int devicetype)
+ 
+ 	rc = usbat_read_user_io(us, status);
+ 	if (rc != USB_STOR_TRANSPORT_GOOD)
+-		return rc;
++		return -EIO;
+ 
+ 	usb_stor_dbg(us, "INIT 2\n");
+ 
+ 	rc = usbat_read_user_io(us, status);
+ 	if (rc != USB_STOR_XFER_GOOD)
+-		return USB_STOR_TRANSPORT_ERROR;
++		return -EIO;
+ 
+ 	rc = usbat_read_user_io(us, status);
+ 	if (rc != USB_STOR_XFER_GOOD)
+-		return USB_STOR_TRANSPORT_ERROR;
++		return -EIO;
+ 
+ 	usb_stor_dbg(us, "INIT 3\n");
+ 
+ 	rc = usbat_select_and_test_registers(us);
+ 	if (rc != USB_STOR_TRANSPORT_GOOD)
+-		return rc;
++		return -EIO;
+ 
+ 	usb_stor_dbg(us, "INIT 4\n");
+ 
+ 	rc = usbat_read_user_io(us, status);
+ 	if (rc != USB_STOR_XFER_GOOD)
+-		return USB_STOR_TRANSPORT_ERROR;
++		return -EIO;
+ 
+ 	usb_stor_dbg(us, "INIT 5\n");
+ 
+ 	/* Enable peripheral control signals and card detect */
+ 	rc = usbat_device_enable_cdt(us);
+ 	if (rc != USB_STOR_TRANSPORT_GOOD)
+-		return rc;
++		return -EIO;
+ 
+ 	usb_stor_dbg(us, "INIT 6\n");
+ 
+ 	rc = usbat_read_user_io(us, status);
+ 	if (rc != USB_STOR_XFER_GOOD)
+-		return USB_STOR_TRANSPORT_ERROR;
++		return -EIO;
+ 
+ 	usb_stor_dbg(us, "INIT 7\n");
+ 
+@@ -1516,19 +1516,19 @@ static int init_usbat(struct us_data *us, int devicetype)
+ 
+ 	rc = usbat_read_user_io(us, status);
+ 	if (rc != USB_STOR_XFER_GOOD)
+-		return USB_STOR_TRANSPORT_ERROR;
++		return -EIO;
+ 
+ 	usb_stor_dbg(us, "INIT 8\n");
+ 
+ 	rc = usbat_select_and_test_registers(us);
+ 	if (rc != USB_STOR_TRANSPORT_GOOD)
+-		return rc;
++		return -EIO;
+ 
+ 	usb_stor_dbg(us, "INIT 9\n");
+ 
+ 	/* At this point, we need to detect which device we are using */
+ 	if (usbat_set_transport(us, info, devicetype))
+-		return USB_STOR_TRANSPORT_ERROR;
++		return -EIO;
+ 
+ 	usb_stor_dbg(us, "INIT 10\n");
+ 
+@@ -1539,11 +1539,11 @@ static int init_usbat(struct us_data *us, int devicetype)
+ 	rc = usbat_set_shuttle_features(us, (USBAT_FEAT_ETEN | USBAT_FEAT_ET2 | USBAT_FEAT_ET1),
+ 									0x00, 0x88, 0x08, subcountH, subcountL);
+ 	if (rc != USB_STOR_XFER_GOOD)
+-		return USB_STOR_TRANSPORT_ERROR;
++		return -EIO;
+ 
+ 	usb_stor_dbg(us, "INIT 11\n");
+ 
+-	return USB_STOR_TRANSPORT_GOOD;
++	return 0;
+ }
+ 
+ /*

commit 17b2fb9c231ea418fa6c8643f2c786ec991b56f5
+Author: Lin Ma 
+Date:   Thu Apr 7 10:20:58 2022 +0800
+
+    usb-storage: alauda: fix initFunction error return
+    
+    The initFunction is called when probing a new device, its call relation
+    is like:
+    
+    USB core: probe() -> usb_stor_probe2() -> usb_stor_acquire_resources()
+    -> init_alauda()
+    
+    That is, the error return of the initFunction should tell USB core what
+    happened instead of using error code like USB_STOR_TRANSPORT_ERROR.
+    
+    Signed-off-by: Lin Ma 
+    Link: https://lore.kernel.org/r/20220407022058.3741-1-linma@zju.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c
+index 20b857e97e60..747be69e5e69 100644
+--- a/drivers/usb/storage/alauda.c
++++ b/drivers/usb/storage/alauda.c
+@@ -1104,7 +1104,7 @@ static int init_alauda(struct us_data *us)
+ 
+ 	us->extra = kzalloc(sizeof(struct alauda_info), GFP_NOIO);
+ 	if (!us->extra)
+-		return USB_STOR_TRANSPORT_ERROR;
++		return -ENOMEM;
+ 
+ 	info = (struct alauda_info *) us->extra;
+ 	us->extra_destructor = alauda_info_destructor;
+@@ -1113,7 +1113,7 @@ static int init_alauda(struct us_data *us)
+ 		altsetting->endpoint[0].desc.bEndpointAddress
+ 		& USB_ENDPOINT_NUMBER_MASK);
+ 
+-	return USB_STOR_TRANSPORT_GOOD;
++	return 0;
+ }
+ 
+ static int alauda_transport(struct scsi_cmnd *srb, struct us_data *us)

commit bc6de2878429e85c1f1afaa566f7b5abb2243eef
+Author: Duoming Zhou 
+Date:   Sun Apr 17 20:55:19 2022 +0800
+
+    drivers: net: hippi: Fix deadlock in rr_close()
+    
+    There is a deadlock in rr_close(), which is shown below:
+    
+       (Thread 1)                |      (Thread 2)
+                                 | rr_open()
+    rr_close()                   |  add_timer()
+     spin_lock_irqsave() //(1)   |  (wait a time)
+     ...                         | rr_timer()
+     del_timer_sync()            |  spin_lock_irqsave() //(2)
+     (wait timer to stop)        |  ...
+    
+    We hold rrpriv->lock in position (1) of thread 1 and
+    use del_timer_sync() to wait timer to stop, but timer handler
+    also need rrpriv->lock in position (2) of thread 2.
+    As a result, rr_close() will block forever.
+    
+    This patch extracts del_timer_sync() from the protection of
+    spin_lock_irqsave(), which could let timer handler to obtain
+    the needed lock.
+    
+    Signed-off-by: Duoming Zhou 
+    Link: https://lore.kernel.org/r/20220417125519.82618-1-duoming@zju.edu.cn
+    Signed-off-by: Paolo Abeni 
+
+diff --git a/drivers/net/hippi/rrunner.c b/drivers/net/hippi/rrunner.c
+index 16105292b140..74e845fa2e07 100644
+--- a/drivers/net/hippi/rrunner.c
++++ b/drivers/net/hippi/rrunner.c
+@@ -1355,7 +1355,9 @@ static int rr_close(struct net_device *dev)
+ 
+ 	rrpriv->fw_running = 0;
+ 
++	spin_unlock_irqrestore(&rrpriv->lock, flags);
+ 	del_timer_sync(&rrpriv->timer);
++	spin_lock_irqsave(&rrpriv->lock, flags);
+ 
+ 	writel(0, ®s->TxPi);
+ 	writel(0, ®s->IpRxPi);

commit 9b6bdbd9337de3917945847bde262a34a87a6303
+Author: Duoming Zhou 
+Date:   Sun Apr 17 22:16:41 2022 +0800
+
+    drivers: staging: rtl8192e: Fix deadlock in rtllib_beacons_stop()
+    
+    There is a deadlock in rtllib_beacons_stop(), which is shown
+    below:
+    
+       (Thread 1)              |      (Thread 2)
+                               | rtllib_send_beacon()
+    rtllib_beacons_stop()      |  mod_timer()
+     spin_lock_irqsave() //(1) |  (wait a time)
+     ...                       | rtllib_send_beacon_cb()
+     del_timer_sync()          |  spin_lock_irqsave() //(2)
+     (wait timer to stop)      |  ...
+    
+    We hold ieee->beacon_lock in position (1) of thread 1 and
+    use del_timer_sync() to wait timer to stop, but timer handler
+    also need ieee->beacon_lock in position (2) of thread 2.
+    As a result, rtllib_beacons_stop() will block forever.
+    
+    This patch extracts del_timer_sync() from the protection of
+    spin_lock_irqsave(), which could let timer handler to obtain
+    the needed lock.
+    
+    Signed-off-by: Duoming Zhou 
+    Link: https://lore.kernel.org/r/20220417141641.124388-1-duoming@zju.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c
+index 82bf05eb1cbf..ef35889cbb96 100644
+--- a/drivers/staging/rtl8192e/rtllib_softmac.c
++++ b/drivers/staging/rtl8192e/rtllib_softmac.c
+@@ -651,9 +651,9 @@ static void rtllib_beacons_stop(struct rtllib_device *ieee)
+ 	spin_lock_irqsave(&ieee->beacon_lock, flags);
+ 
+ 	ieee->beacon_txing = 0;
+-	del_timer_sync(&ieee->beacon_timer);
+ 
+ 	spin_unlock_irqrestore(&ieee->beacon_lock, flags);
++	del_timer_sync(&ieee->beacon_timer);
+ 
+ }
+ 

commit 806c7b53414934ba2a39449b31fd1a038e500273
+Author: Duoming Zhou 
+Date:   Sun Apr 17 21:54:07 2022 +0800
+
+    drivers: staging: rtl8192u: Fix deadlock in ieee80211_beacons_stop()
+    
+    There is a deadlock in ieee80211_beacons_stop(), which is shown below:
+    
+       (Thread 1)              |      (Thread 2)
+                               | ieee80211_send_beacon()
+    ieee80211_beacons_stop()   |  mod_timer()
+     spin_lock_irqsave() //(1) |  (wait a time)
+     ...                       | ieee80211_send_beacon_cb()
+     del_timer_sync()          |  spin_lock_irqsave() //(2)
+     (wait timer to stop)      |  ...
+    
+    We hold ieee->beacon_lock in position (1) of thread 1 and use
+    del_timer_sync() to wait timer to stop, but timer handler
+    also need ieee->beacon_lock in position (2) of thread 2.
+    As a result, ieee80211_beacons_stop() will block forever.
+    
+    This patch extracts del_timer_sync() from the protection of
+    spin_lock_irqsave(), which could let timer handler to obtain
+    the needed lock.
+    
+    Signed-off-by: Duoming Zhou 
+    Link: https://lore.kernel.org/r/20220417135407.109536-1-duoming@zju.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
+index 4e8fbd2410a1..f0ee018b8106 100644
+--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
++++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
+@@ -528,9 +528,9 @@ static void ieee80211_beacons_stop(struct ieee80211_device *ieee)
+ 	spin_lock_irqsave(&ieee->beacon_lock, flags);
+ 
+ 	ieee->beacon_txing = 0;
+-	del_timer_sync(&ieee->beacon_timer);
+ 
+ 	spin_unlock_irqrestore(&ieee->beacon_lock, flags);
++	del_timer_sync(&ieee->beacon_timer);
+ }
+ 
+ void ieee80211_stop_send_beacons(struct ieee80211_device *ieee)

commit 679ab61bf5f5f519377d812afb4fb93634782c74
+Author: Duoming Zhou 
+Date:   Mon Apr 18 23:33:22 2022 +0800
+
+    RDMA/irdma: Fix deadlock in irdma_cleanup_cm_core()
+    
+    There is a deadlock in irdma_cleanup_cm_core(), which is shown below:
+    
+       (Thread 1)              |      (Thread 2)
+                               | irdma_schedule_cm_timer()
+    irdma_cleanup_cm_core()    |  add_timer()
+     spin_lock_irqsave() //(1) |  (wait a time)
+     ...                       | irdma_cm_timer_tick()
+     del_timer_sync()          |  spin_lock_irqsave() //(2)
+     (wait timer to stop)      |  ...
+    
+    We hold cm_core->ht_lock in position (1) of thread 1 and use
+    del_timer_sync() to wait timer to stop, but timer handler also need
+    cm_core->ht_lock in position (2) of thread 2.  As a result,
+    irdma_cleanup_cm_core() will block forever.
+    
+    This patch removes the check of timer_pending() in
+    irdma_cleanup_cm_core(), because the del_timer_sync() function will just
+    return directly if there isn't a pending timer. As a result, the lock is
+    redundant, because there is no resource it could protect.
+    
+    Link: https://lore.kernel.org/r/20220418153322.42524-1-duoming@zju.edu.cn
+    Signed-off-by: Duoming Zhou 
+    Reviewed-by: Shiraz Saleem 
+    Signed-off-by: Jason Gunthorpe 
+
+diff --git a/drivers/infiniband/hw/irdma/cm.c b/drivers/infiniband/hw/irdma/cm.c
+index dedb3b7edd8d..a98d962e5efb 100644
+--- a/drivers/infiniband/hw/irdma/cm.c
++++ b/drivers/infiniband/hw/irdma/cm.c
+@@ -3246,15 +3246,10 @@ int irdma_setup_cm_core(struct irdma_device *iwdev, u8 rdma_ver)
+  */
+ void irdma_cleanup_cm_core(struct irdma_cm_core *cm_core)
+ {
+-	unsigned long flags;
+-
+ 	if (!cm_core)
+ 		return;
+ 
+-	spin_lock_irqsave(&cm_core->ht_lock, flags);
+-	if (timer_pending(&cm_core->tcp_timer))
+-		del_timer_sync(&cm_core->tcp_timer);
+-	spin_unlock_irqrestore(&cm_core->ht_lock, flags);
++	del_timer_sync(&cm_core->tcp_timer);
+ 
+ 	destroy_workqueue(cm_core->event_wq);
+ 	cm_core->dev->ws_reset(&cm_core->iwdev->vsi);

commit ef27324e2cb7bb24542d6cb2571740eefe6b00dc
+Author: Lin Ma 
+Date:   Wed Apr 13 00:04:30 2022 +0800
+
+    nfc: nci: add flush_workqueue to prevent uaf
+    
+    Our detector found a concurrent use-after-free bug when detaching an
+    NCI device. The main reason for this bug is the unexpected scheduling
+    between the used delayed mechanism (timer and workqueue).
+    
+    The race can be demonstrated below:
+    
+    Thread-1                           Thread-2
+                                     | nci_dev_up()
+                                     |   nci_open_device()
+                                     |     __nci_request(nci_reset_req)
+                                     |       nci_send_cmd
+                                     |         queue_work(cmd_work)
+    nci_unregister_device()          |
+      nci_close_device()             | ...
+        del_timer_sync(cmd_timer)[1] |
+    ...                              | Worker
+    nci_free_device()                | nci_cmd_work()
+      kfree(ndev)[3]                 |   mod_timer(cmd_timer)[2]
+    
+    In short, the cleanup routine thought that the cmd_timer has already
+    been detached by [1] but the mod_timer can re-attach the timer [2], even
+    it is already released [3], resulting in UAF.
+    
+    This UAF is easy to trigger, crash trace by POC is like below
+    
+    [   66.703713] ==================================================================
+    [   66.703974] BUG: KASAN: use-after-free in enqueue_timer+0x448/0x490
+    [   66.703974] Write of size 8 at addr ffff888009fb7058 by task kworker/u4:1/33
+    [   66.703974]
+    [   66.703974] CPU: 1 PID: 33 Comm: kworker/u4:1 Not tainted 5.18.0-rc2 #5
+    [   66.703974] Workqueue: nfc2_nci_cmd_wq nci_cmd_work
+    [   66.703974] Call Trace:
+    [   66.703974]  
+    [   66.703974]  dump_stack_lvl+0x57/0x7d
+    [   66.703974]  print_report.cold+0x5e/0x5db
+    [   66.703974]  ? enqueue_timer+0x448/0x490
+    [   66.703974]  kasan_report+0xbe/0x1c0
+    [   66.703974]  ? enqueue_timer+0x448/0x490
+    [   66.703974]  enqueue_timer+0x448/0x490
+    [   66.703974]  __mod_timer+0x5e6/0xb80
+    [   66.703974]  ? mark_held_locks+0x9e/0xe0
+    [   66.703974]  ? try_to_del_timer_sync+0xf0/0xf0
+    [   66.703974]  ? lockdep_hardirqs_on_prepare+0x17b/0x410
+    [   66.703974]  ? queue_work_on+0x61/0x80
+    [   66.703974]  ? lockdep_hardirqs_on+0xbf/0x130
+    [   66.703974]  process_one_work+0x8bb/0x1510
+    [   66.703974]  ? lockdep_hardirqs_on_prepare+0x410/0x410
+    [   66.703974]  ? pwq_dec_nr_in_flight+0x230/0x230
+    [   66.703974]  ? rwlock_bug.part.0+0x90/0x90
+    [   66.703974]  ? _raw_spin_lock_irq+0x41/0x50
+    [   66.703974]  worker_thread+0x575/0x1190
+    [   66.703974]  ? process_one_work+0x1510/0x1510
+    [   66.703974]  kthread+0x2a0/0x340
+    [   66.703974]  ? kthread_complete_and_exit+0x20/0x20
+    [   66.703974]  ret_from_fork+0x22/0x30
+    [   66.703974]  
+    [   66.703974]
+    [   66.703974] Allocated by task 267:
+    [   66.703974]  kasan_save_stack+0x1e/0x40
+    [   66.703974]  __kasan_kmalloc+0x81/0xa0
+    [   66.703974]  nci_allocate_device+0xd3/0x390
+    [   66.703974]  nfcmrvl_nci_register_dev+0x183/0x2c0
+    [   66.703974]  nfcmrvl_nci_uart_open+0xf2/0x1dd
+    [   66.703974]  nci_uart_tty_ioctl+0x2c3/0x4a0
+    [   66.703974]  tty_ioctl+0x764/0x1310
+    [   66.703974]  __x64_sys_ioctl+0x122/0x190
+    [   66.703974]  do_syscall_64+0x3b/0x90
+    [   66.703974]  entry_SYSCALL_64_after_hwframe+0x44/0xae
+    [   66.703974]
+    [   66.703974] Freed by task 406:
+    [   66.703974]  kasan_save_stack+0x1e/0x40
+    [   66.703974]  kasan_set_track+0x21/0x30
+    [   66.703974]  kasan_set_free_info+0x20/0x30
+    [   66.703974]  __kasan_slab_free+0x108/0x170
+    [   66.703974]  kfree+0xb0/0x330
+    [   66.703974]  nfcmrvl_nci_unregister_dev+0x90/0xd0
+    [   66.703974]  nci_uart_tty_close+0xdf/0x180
+    [   66.703974]  tty_ldisc_kill+0x73/0x110
+    [   66.703974]  tty_ldisc_hangup+0x281/0x5b0
+    [   66.703974]  __tty_hangup.part.0+0x431/0x890
+    [   66.703974]  tty_release+0x3a8/0xc80
+    [   66.703974]  __fput+0x1f0/0x8c0
+    [   66.703974]  task_work_run+0xc9/0x170
+    [   66.703974]  exit_to_user_mode_prepare+0x194/0x1a0
+    [   66.703974]  syscall_exit_to_user_mode+0x19/0x50
+    [   66.703974]  do_syscall_64+0x48/0x90
+    [   66.703974]  entry_SYSCALL_64_after_hwframe+0x44/0xae
+    
+    To fix the UAF, this patch adds flush_workqueue() to ensure the
+    nci_cmd_work is finished before the following del_timer_sync.
+    This combination will promise the timer is actually detached.
+    
+    Fixes: 6a2968aaf50c ("NFC: basic NCI protocol implementation")
+    Signed-off-by: Lin Ma 
+    Reviewed-by: Krzysztof Kozlowski 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
+index d2537383a3e8..6a193cce2a75 100644
+--- a/net/nfc/nci/core.c
++++ b/net/nfc/nci/core.c
+@@ -560,6 +560,10 @@ static int nci_close_device(struct nci_dev *ndev)
+ 	mutex_lock(&ndev->req_lock);
+ 
+ 	if (!test_and_clear_bit(NCI_UP, &ndev->flags)) {
++		/* Need to flush the cmd wq in case
++		 * there is a queued/running cmd_work
++		 */
++		flush_workqueue(ndev->cmd_wq);
+ 		del_timer_sync(&ndev->cmd_timer);
+ 		del_timer_sync(&ndev->data_timer);
+ 		mutex_unlock(&ndev->req_lock);

commit 1b0e81416a24d6e9b8c2341e22e8bf48f8b8bfc9
+Author: Lin Ma 
+Date:   Tue Apr 12 13:32:08 2022 +0800
+
+    NFC: NULL out the dev->rfkill to prevent UAF
+    
+    Commit 3e3b5dfcd16a ("NFC: reorder the logic in nfc_{un,}register_device")
+    assumes the device_is_registered() in function nfc_dev_up() will help
+    to check when the rfkill is unregistered. However, this check only
+    take effect when device_del(&dev->dev) is done in nfc_unregister_device().
+    Hence, the rfkill object is still possible be dereferenced.
+    
+    The crash trace in latest kernel (5.18-rc2):
+    
+    [   68.760105] ==================================================================
+    [   68.760330] BUG: KASAN: use-after-free in __lock_acquire+0x3ec1/0x6750
+    [   68.760756] Read of size 8 at addr ffff888009c93018 by task fuzz/313
+    [   68.760756]
+    [   68.760756] CPU: 0 PID: 313 Comm: fuzz Not tainted 5.18.0-rc2 #4
+    [   68.760756] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g155821a1990b-prebuilt.qemu.org 04/01/2014
+    [   68.760756] Call Trace:
+    [   68.760756]  
+    [   68.760756]  dump_stack_lvl+0x57/0x7d
+    [   68.760756]  print_report.cold+0x5e/0x5db
+    [   68.760756]  ? __lock_acquire+0x3ec1/0x6750
+    [   68.760756]  kasan_report+0xbe/0x1c0
+    [   68.760756]  ? __lock_acquire+0x3ec1/0x6750
+    [   68.760756]  __lock_acquire+0x3ec1/0x6750
+    [   68.760756]  ? lockdep_hardirqs_on_prepare+0x410/0x410
+    [   68.760756]  ? register_lock_class+0x18d0/0x18d0
+    [   68.760756]  lock_acquire+0x1ac/0x4f0
+    [   68.760756]  ? rfkill_blocked+0xe/0x60
+    [   68.760756]  ? lockdep_hardirqs_on_prepare+0x410/0x410
+    [   68.760756]  ? mutex_lock_io_nested+0x12c0/0x12c0
+    [   68.760756]  ? nla_get_range_signed+0x540/0x540
+    [   68.760756]  ? _raw_spin_lock_irqsave+0x4e/0x50
+    [   68.760756]  _raw_spin_lock_irqsave+0x39/0x50
+    [   68.760756]  ? rfkill_blocked+0xe/0x60
+    [   68.760756]  rfkill_blocked+0xe/0x60
+    [   68.760756]  nfc_dev_up+0x84/0x260
+    [   68.760756]  nfc_genl_dev_up+0x90/0xe0
+    [   68.760756]  genl_family_rcv_msg_doit+0x1f4/0x2f0
+    [   68.760756]  ? genl_family_rcv_msg_attrs_parse.constprop.0+0x230/0x230
+    [   68.760756]  ? security_capable+0x51/0x90
+    [   68.760756]  genl_rcv_msg+0x280/0x500
+    [   68.760756]  ? genl_get_cmd+0x3c0/0x3c0
+    [   68.760756]  ? lock_acquire+0x1ac/0x4f0
+    [   68.760756]  ? nfc_genl_dev_down+0xe0/0xe0
+    [   68.760756]  ? lockdep_hardirqs_on_prepare+0x410/0x410
+    [   68.760756]  netlink_rcv_skb+0x11b/0x340
+    [   68.760756]  ? genl_get_cmd+0x3c0/0x3c0
+    [   68.760756]  ? netlink_ack+0x9c0/0x9c0
+    [   68.760756]  ? netlink_deliver_tap+0x136/0xb00
+    [   68.760756]  genl_rcv+0x1f/0x30
+    [   68.760756]  netlink_unicast+0x430/0x710
+    [   68.760756]  ? memset+0x20/0x40
+    [   68.760756]  ? netlink_attachskb+0x740/0x740
+    [   68.760756]  ? __build_skb_around+0x1f4/0x2a0
+    [   68.760756]  netlink_sendmsg+0x75d/0xc00
+    [   68.760756]  ? netlink_unicast+0x710/0x710
+    [   68.760756]  ? netlink_unicast+0x710/0x710
+    [   68.760756]  sock_sendmsg+0xdf/0x110
+    [   68.760756]  __sys_sendto+0x19e/0x270
+    [   68.760756]  ? __ia32_sys_getpeername+0xa0/0xa0
+    [   68.760756]  ? fd_install+0x178/0x4c0
+    [   68.760756]  ? fd_install+0x195/0x4c0
+    [   68.760756]  ? kernel_fpu_begin_mask+0x1c0/0x1c0
+    [   68.760756]  __x64_sys_sendto+0xd8/0x1b0
+    [   68.760756]  ? lockdep_hardirqs_on+0xbf/0x130
+    [   68.760756]  ? syscall_enter_from_user_mode+0x1d/0x50
+    [   68.760756]  do_syscall_64+0x3b/0x90
+    [   68.760756]  entry_SYSCALL_64_after_hwframe+0x44/0xae
+    [   68.760756] RIP: 0033:0x7f67fb50e6b3
+    ...
+    [   68.760756] RSP: 002b:00007f67fa91fe90 EFLAGS: 00000293 ORIG_RAX: 000000000000002c
+    [   68.760756] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f67fb50e6b3
+    [   68.760756] RDX: 000000000000001c RSI: 0000559354603090 RDI: 0000000000000003
+    [   68.760756] RBP: 00007f67fa91ff00 R08: 00007f67fa91fedc R09: 000000000000000c
+    [   68.760756] R10: 0000000000000000 R11: 0000000000000293 R12: 00007ffe824d496e
+    [   68.760756] R13: 00007ffe824d496f R14: 00007f67fa120000 R15: 0000000000000003
+    
+    [   68.760756]  
+    [   68.760756]
+    [   68.760756] Allocated by task 279:
+    [   68.760756]  kasan_save_stack+0x1e/0x40
+    [   68.760756]  __kasan_kmalloc+0x81/0xa0
+    [   68.760756]  rfkill_alloc+0x7f/0x280
+    [   68.760756]  nfc_register_device+0xa3/0x1a0
+    [   68.760756]  nci_register_device+0x77a/0xad0
+    [   68.760756]  nfcmrvl_nci_register_dev+0x20b/0x2c0
+    [   68.760756]  nfcmrvl_nci_uart_open+0xf2/0x1dd
+    [   68.760756]  nci_uart_tty_ioctl+0x2c3/0x4a0
+    [   68.760756]  tty_ioctl+0x764/0x1310
+    [   68.760756]  __x64_sys_ioctl+0x122/0x190
+    [   68.760756]  do_syscall_64+0x3b/0x90
+    [   68.760756]  entry_SYSCALL_64_after_hwframe+0x44/0xae
+    [   68.760756]
+    [   68.760756] Freed by task 314:
+    [   68.760756]  kasan_save_stack+0x1e/0x40
+    [   68.760756]  kasan_set_track+0x21/0x30
+    [   68.760756]  kasan_set_free_info+0x20/0x30
+    [   68.760756]  __kasan_slab_free+0x108/0x170
+    [   68.760756]  kfree+0xb0/0x330
+    [   68.760756]  device_release+0x96/0x200
+    [   68.760756]  kobject_put+0xf9/0x1d0
+    [   68.760756]  nfc_unregister_device+0x77/0x190
+    [   68.760756]  nfcmrvl_nci_unregister_dev+0x88/0xd0
+    [   68.760756]  nci_uart_tty_close+0xdf/0x180
+    [   68.760756]  tty_ldisc_kill+0x73/0x110
+    [   68.760756]  tty_ldisc_hangup+0x281/0x5b0
+    [   68.760756]  __tty_hangup.part.0+0x431/0x890
+    [   68.760756]  tty_release+0x3a8/0xc80
+    [   68.760756]  __fput+0x1f0/0x8c0
+    [   68.760756]  task_work_run+0xc9/0x170
+    [   68.760756]  exit_to_user_mode_prepare+0x194/0x1a0
+    [   68.760756]  syscall_exit_to_user_mode+0x19/0x50
+    [   68.760756]  do_syscall_64+0x48/0x90
+    [   68.760756]  entry_SYSCALL_64_after_hwframe+0x44/0xae
+    
+    This patch just add the null out of dev->rfkill to make sure such
+    dereference cannot happen. This is safe since the device_lock() already
+    protect the check/write from data race.
+    
+    Fixes: 3e3b5dfcd16a ("NFC: reorder the logic in nfc_{un,}register_device")
+    Signed-off-by: Lin Ma 
+    Reviewed-by: Krzysztof Kozlowski 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/nfc/core.c b/net/nfc/core.c
+index dc7a2404efdf..67524982b89b 100644
+--- a/net/nfc/core.c
++++ b/net/nfc/core.c
+@@ -1165,6 +1165,7 @@ void nfc_unregister_device(struct nfc_dev *dev)
+ 	if (dev->rfkill) {
+ 		rfkill_unregister(dev->rfkill);
+ 		rfkill_destroy(dev->rfkill);
++		dev->rfkill = NULL;
+ 	}
+ 	device_unlock(&dev->dev);
+ 

commit eb5adc70754d26a260f8b42d39db42da0d0af500
+Author: Duoming Zhou 
+Date:   Thu Apr 7 23:44:30 2022 +0800
+
+    arch: xtensa: platforms: Fix deadlock in rs_close()
+    
+    There is a deadlock in rs_close(), which is shown
+    below:
+    
+       (Thread 1)              |      (Thread 2)
+                               | rs_open()
+    rs_close()                 |  mod_timer()
+     spin_lock_bh() //(1)      |  (wait a time)
+     ...                       | rs_poll()
+     del_timer_sync()          |  spin_lock() //(2)
+     (wait timer to stop)      |  ...
+    
+    We hold timer_lock in position (1) of thread 1 and
+    use del_timer_sync() to wait timer to stop, but timer handler
+    also need timer_lock in position (2) of thread 2.
+    As a result, rs_close() will block forever.
+    
+    This patch deletes the redundant timer_lock in order to
+    prevent the deadlock. Because there is no race condition
+    between rs_close, rs_open and rs_poll.
+    
+    Signed-off-by: Duoming Zhou 
+    Message-Id: <20220407154430.22387-1-duoming@zju.edu.cn>
+    Signed-off-by: Max Filippov 
+
+diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c
+index 81d7c7e8f7e9..10b79d3c74e0 100644
+--- a/arch/xtensa/platforms/iss/console.c
++++ b/arch/xtensa/platforms/iss/console.c
+@@ -36,24 +36,19 @@ static void rs_poll(struct timer_list *);
+ static struct tty_driver *serial_driver;
+ static struct tty_port serial_port;
+ static DEFINE_TIMER(serial_timer, rs_poll);
+-static DEFINE_SPINLOCK(timer_lock);
+ 
+ static int rs_open(struct tty_struct *tty, struct file * filp)
+ {
+-	spin_lock_bh(&timer_lock);
+ 	if (tty->count == 1)
+ 		mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE);
+-	spin_unlock_bh(&timer_lock);
+ 
+ 	return 0;
+ }
+ 
+ static void rs_close(struct tty_struct *tty, struct file * filp)
+ {
+-	spin_lock_bh(&timer_lock);
+ 	if (tty->count == 1)
+ 		del_timer_sync(&serial_timer);
+-	spin_unlock_bh(&timer_lock);
+ }
+ 
+ 
+@@ -73,8 +68,6 @@ static void rs_poll(struct timer_list *unused)
+ 	int rd = 1;
+ 	unsigned char c;
+ 
+-	spin_lock(&timer_lock);
+-
+ 	while (simc_poll(0)) {
+ 		rd = simc_read(0, &c, 1);
+ 		if (rd <= 0)
+@@ -87,7 +80,6 @@ static void rs_poll(struct timer_list *unused)
+ 		tty_flip_buffer_push(port);
+ 	if (rd)
+ 		mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE);
+-	spin_unlock(&timer_lock);
+ }
+ 
+ 

commit 0fcddf9c7c10202946d5b19409efbdff744fba88
+Author: Duoming Zhou 
+Date:   Sat Apr 9 15:21:35 2022 +0800
+
+    drivers: staging: rtl8192eu: Fix deadlock in rtw_joinbss_event_prehandle
+    
+    There is a deadlock in rtw_joinbss_event_prehandle(), which is shown below:
+    
+       (Thread 1)                |      (Thread 2)
+                                 | _set_timer()
+    rtw_joinbss_event_prehandle()|  mod_timer()
+     spin_lock_bh() //(1)        |  (wait a time)
+     ...                         | rtw_join_timeout_handler()
+                                 |  _rtw_join_timeout_handler()
+     del_timer_sync()            |   spin_lock_bh() //(2)
+     (wait timer to stop)        |   ...
+    
+    We hold pmlmepriv->lock in position (1) of thread 1 and
+    use del_timer_sync() to wait timer to stop, but timer handler
+    also need pmlmepriv->lock in position (2) of thread 2.
+    As a result, rtw_joinbss_event_prehandle() will block forever.
+    
+    This patch extracts del_timer_sync() from the protection of
+    spin_lock_bh(), which could let timer handler to obtain
+    the needed lock. What`s more, we change spin_lock_bh() to
+    spin_lock_irq() in _rtw_join_timeout_handler() in order to
+    prevent deadlock.
+    
+    Signed-off-by: Duoming Zhou 
+    Link: https://lore.kernel.org/r/20220409072135.74248-1-duoming@zju.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/r8188eu/core/rtw_mlme.c b/drivers/staging/r8188eu/core/rtw_mlme.c
+index aa39f07847c2..3e9882f89f76 100644
+--- a/drivers/staging/r8188eu/core/rtw_mlme.c
++++ b/drivers/staging/r8188eu/core/rtw_mlme.c
+@@ -1070,8 +1070,10 @@ void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf)
+ 				rtw_indicate_connect(adapter);
+ 			}
+ 
++			spin_unlock_bh(&pmlmepriv->lock);
+ 			/* s5. Cancel assoc_timer */
+ 			del_timer_sync(&pmlmepriv->assoc_timer);
++			spin_lock_bh(&pmlmepriv->lock);
+ 		} else {
+ 			spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+ 			goto ignore_joinbss_callback;
+@@ -1315,7 +1317,7 @@ void _rtw_join_timeout_handler (struct adapter *adapter)
+ 	if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
+ 		return;
+ 
+-	spin_lock_bh(&pmlmepriv->lock);
++	spin_lock_irq(&pmlmepriv->lock);
+ 
+ 	if (rtw_to_roaming(adapter) > 0) { /* join timeout caused by roaming */
+ 		while (1) {
+@@ -1334,7 +1336,7 @@ void _rtw_join_timeout_handler (struct adapter *adapter)
+ 		rtw_indicate_disconnect(adapter);
+ 		free_scanqueue(pmlmepriv);/*  */
+ 	}
+-	spin_unlock_bh(&pmlmepriv->lock);
++	spin_unlock_irq(&pmlmepriv->lock);
+ 
+ }
+ 

commit 041879b12ddb0c6c83ed9c0bdd10dc82a056f2fc
+Author: Duoming Zhou 
+Date:   Sat Apr 9 14:49:53 2022 +0800
+
+    drivers: staging: rtl8192bs: Fix deadlock in rtw_joinbss_event_prehandle()
+    
+    There is a deadlock in rtw_joinbss_event_prehandle(), which is shown
+    below:
+    
+       (Thread 1)                |      (Thread 2)
+                                 | _set_timer()
+    rtw_joinbss_event_prehandle()|  mod_timer()
+     spin_lock_bh() //(1)        |  (wait a time)
+     ...                         | _rtw_join_timeout_handler()
+     del_timer_sync()            |  spin_lock_bh() //(2)
+     (wait timer to stop)        |  ...
+    
+    We hold pmlmepriv->lock in position (1) of thread 1 and
+    use del_timer_sync() to wait timer to stop, but timer handler
+    also need pmlmepriv->lock in position (2) of thread 2.
+    As a result, rtw_joinbss_event_prehandle() will block forever.
+    
+    This patch extracts del_timer_sync() from the protection of
+    spin_lock_bh(), which could let timer handler to obtain
+    the needed lock. What`s more, we change spin_lock_bh() to
+    spin_lock_irq() in _rtw_join_timeout_handler() in order to
+    prevent deadlock.
+    
+    Signed-off-by: Duoming Zhou 
+    Link: https://lore.kernel.org/r/20220409064953.67420-1-duoming@zju.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme.c b/drivers/staging/rtl8723bs/core/rtw_mlme.c
+index f7db483a5641..f2242cf2dfb4 100644
+--- a/drivers/staging/rtl8723bs/core/rtw_mlme.c
++++ b/drivers/staging/rtl8723bs/core/rtw_mlme.c
+@@ -1240,8 +1240,10 @@ void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf)
+ 
+ 			spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+ 
++			spin_unlock_bh(&pmlmepriv->lock);
+ 			/* s5. Cancel assoc_timer */
+ 			del_timer_sync(&pmlmepriv->assoc_timer);
++			spin_lock_bh(&pmlmepriv->lock);
+ 		} else {
+ 			spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
+ 		}
+@@ -1547,7 +1549,7 @@ void _rtw_join_timeout_handler(struct timer_list *t)
+ 	if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
+ 		return;
+ 
+-	spin_lock_bh(&pmlmepriv->lock);
++	spin_lock_irq(&pmlmepriv->lock);
+ 
+ 	if (rtw_to_roam(adapter) > 0) { /* join timeout caused by roaming */
+ 		while (1) {
+@@ -1575,7 +1577,7 @@ void _rtw_join_timeout_handler(struct timer_list *t)
+ 
+ 	}
+ 
+-	spin_unlock_bh(&pmlmepriv->lock);
++	spin_unlock_irq(&pmlmepriv->lock);
+ }
+ 
+ /*

commit cc7ad0d77b51c872d629bcd98aea463a3c4109e7
+Author: Duoming Zhou 
+Date:   Sat Apr 9 14:18:35 2022 +0800
+
+    drivers: staging: rtl8723bs: Fix deadlock in rtw_surveydone_event_callback()
+    
+    There is a deadlock in rtw_surveydone_event_callback(),
+    which is shown below:
+    
+       (Thread 1)                  |      (Thread 2)
+                                   | _set_timer()
+    rtw_surveydone_event_callback()|  mod_timer()
+     spin_lock_bh() //(1)          |  (wait a time)
+     ...                           | rtw_scan_timeout_handler()
+     del_timer_sync()              |  spin_lock_bh() //(2)
+     (wait timer to stop)          |  ...
+    
+    We hold pmlmepriv->lock in position (1) of thread 1 and use
+    del_timer_sync() to wait timer to stop, but timer handler
+    also need pmlmepriv->lock in position (2) of thread 2.
+    As a result, rtw_surveydone_event_callback() will block forever.
+    
+    This patch extracts del_timer_sync() from the protection of
+    spin_lock_bh(), which could let timer handler to obtain
+    the needed lock. What`s more, we change spin_lock_bh() in
+    rtw_scan_timeout_handler() to spin_lock_irq(). Otherwise,
+    spin_lock_bh() will also cause deadlock() in timer handler.
+    
+    Signed-off-by: Duoming Zhou 
+    Link: https://lore.kernel.org/r/20220409061836.60529-1-duoming@zju.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme.c b/drivers/staging/rtl8723bs/core/rtw_mlme.c
+index a45df775d535..f7db483a5641 100644
+--- a/drivers/staging/rtl8723bs/core/rtw_mlme.c
++++ b/drivers/staging/rtl8723bs/core/rtw_mlme.c
+@@ -751,7 +751,9 @@ void rtw_surveydone_event_callback(struct adapter	*adapter, u8 *pbuf)
+ 	}
+ 
+ 	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
++		spin_unlock_bh(&pmlmepriv->lock);
+ 		del_timer_sync(&pmlmepriv->scan_to_timer);
++		spin_lock_bh(&pmlmepriv->lock);
+ 		_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
+ 	}
+ 
+@@ -1586,11 +1588,11 @@ void rtw_scan_timeout_handler(struct timer_list *t)
+ 						  mlmepriv.scan_to_timer);
+ 	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ 
+-	spin_lock_bh(&pmlmepriv->lock);
++	spin_lock_irq(&pmlmepriv->lock);
+ 
+ 	_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
+ 
+-	spin_unlock_bh(&pmlmepriv->lock);
++	spin_unlock_irq(&pmlmepriv->lock);
+ 
+ 	rtw_indicate_scan_done(adapter, true);
+ }

commit ec4eb8a86ade4d22633e1da2a7d85a846b7d1798
+Author: Duoming Zhou 
+Date:   Tue Apr 5 21:22:06 2022 +0800
+
+    drivers: net: slip: fix NPD bug in sl_tx_timeout()
+    
+    When a slip driver is detaching, the slip_close() will act to
+    cleanup necessary resources and sl->tty is set to NULL in
+    slip_close(). Meanwhile, the packet we transmit is blocked,
+    sl_tx_timeout() will be called. Although slip_close() and
+    sl_tx_timeout() use sl->lock to synchronize, we don`t judge
+    whether sl->tty equals to NULL in sl_tx_timeout() and the
+    null pointer dereference bug will happen.
+    
+       (Thread 1)                 |      (Thread 2)
+                                  | slip_close()
+                                  |   spin_lock_bh(&sl->lock)
+                                  |   ...
+    ...                           |   sl->tty = NULL //(1)
+    sl_tx_timeout()               |   spin_unlock_bh(&sl->lock)
+      spin_lock(&sl->lock);       |
+      ...                         |   ...
+      tty_chars_in_buffer(sl->tty)|
+        if (tty->ops->..) //(2)   |
+        ...                       |   synchronize_rcu()
+    
+    We set NULL to sl->tty in position (1) and dereference sl->tty
+    in position (2).
+    
+    This patch adds check in sl_tx_timeout(). If sl->tty equals to
+    NULL, sl_tx_timeout() will goto out.
+    
+    Signed-off-by: Duoming Zhou 
+    Reviewed-by: Jiri Slaby 
+    Link: https://lore.kernel.org/r/20220405132206.55291-1-duoming@zju.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c
+index 88396ff99f03..6865d32270e5 100644
+--- a/drivers/net/slip/slip.c
++++ b/drivers/net/slip/slip.c
+@@ -469,7 +469,7 @@ static void sl_tx_timeout(struct net_device *dev, unsigned int txqueue)
+ 	spin_lock(&sl->lock);
+ 
+ 	if (netif_queue_stopped(dev)) {
+-		if (!netif_running(dev))
++		if (!netif_running(dev) || !sl->tty)
+ 			goto out;
+ 
+ 		/* May be we must check transmitter timeout here ?

commit 82e31755e55fbcea6a9dfaae5fe4860ade17cbc0
+Author: Duoming Zhou 
+Date:   Mon Mar 28 21:00:15 2022 +0800
+
+    ax25: Fix UAF bugs in ax25 timers
+    
+    There are race conditions that may lead to UAF bugs in
+    ax25_heartbeat_expiry(), ax25_t1timer_expiry(), ax25_t2timer_expiry(),
+    ax25_t3timer_expiry() and ax25_idletimer_expiry(), when we call
+    ax25_release() to deallocate ax25_dev.
+    
+    One of the UAF bugs caused by ax25_release() is shown below:
+    
+          (Thread 1)                    |      (Thread 2)
+    ax25_dev_device_up() //(1)          |
+    ...                                 | ax25_kill_by_device()
+    ax25_bind()          //(2)          |
+    ax25_connect()                      | ...
+     ax25_std_establish_data_link()     |
+      ax25_start_t1timer()              | ax25_dev_device_down() //(3)
+       mod_timer(&ax25->t1timer,..)     |
+                                        | ax25_release()
+       (wait a time)                    |  ...
+                                        |  ax25_dev_put(ax25_dev) //(4)FREE
+       ax25_t1timer_expiry()            |
+        ax25->ax25_dev->values[..] //USE|  ...
+         ...                            |
+    
+    We increase the refcount of ax25_dev in position (1) and (2), and
+    decrease the refcount of ax25_dev in position (3) and (4).
+    The ax25_dev will be freed in position (4) and be used in
+    ax25_t1timer_expiry().
+    
+    The fail log is shown below:
+    ==============================================================
+    
+    [  106.116942] BUG: KASAN: use-after-free in ax25_t1timer_expiry+0x1c/0x60
+    [  106.116942] Read of size 8 at addr ffff88800bda9028 by task swapper/0/0
+    [  106.116942] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.17.0-06123-g0905eec574
+    [  106.116942] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-14
+    [  106.116942] Call Trace:
+    ...
+    [  106.116942]  ax25_t1timer_expiry+0x1c/0x60
+    [  106.116942]  call_timer_fn+0x122/0x3d0
+    [  106.116942]  __run_timers.part.0+0x3f6/0x520
+    [  106.116942]  run_timer_softirq+0x4f/0xb0
+    [  106.116942]  __do_softirq+0x1c2/0x651
+    ...
+    
+    This patch adds del_timer_sync() in ax25_release(), which could ensure
+    that all timers stop before we deallocate ax25_dev.
+    
+    Signed-off-by: Duoming Zhou 
+    Signed-off-by: Paolo Abeni 
+
+diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
+index f5686c463bc0..363d47f94532 100644
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -1053,6 +1053,11 @@ static int ax25_release(struct socket *sock)
+ 		ax25_destroy_socket(ax25);
+ 	}
+ 	if (ax25_dev) {
++		del_timer_sync(&ax25->timer);
++		del_timer_sync(&ax25->t1timer);
++		del_timer_sync(&ax25->t2timer);
++		del_timer_sync(&ax25->t3timer);
++		del_timer_sync(&ax25->idletimer);
+ 		dev_put_track(ax25_dev->dev, &ax25_dev->dev_tracker);
+ 		ax25_dev_put(ax25_dev);
+ 	}

commit 5352a761308397a0e6250fdc629bb3f615b94747
+Author: Duoming Zhou 
+Date:   Mon Mar 28 21:00:14 2022 +0800
+
+    ax25: fix UAF bug in ax25_send_control()
+    
+    There are UAF bugs in ax25_send_control(), when we call ax25_release()
+    to deallocate ax25_dev. The possible race condition is shown below:
+    
+          (Thread 1)              |     (Thread 2)
+    ax25_dev_device_up() //(1)    |
+                                  | ax25_kill_by_device()
+    ax25_bind()          //(2)    |
+    ax25_connect()                | ...
+     ax25->state = AX25_STATE_1   |
+     ...                          | ax25_dev_device_down() //(3)
+    
+          (Thread 3)
+    ax25_release()                |
+     ax25_dev_put()  //(4) FREE   |
+     case AX25_STATE_1:           |
+      ax25_send_control()         |
+       alloc_skb()       //USE    |
+    
+    The refcount of ax25_dev increases in position (1) and (2), and
+    decreases in position (3) and (4). The ax25_dev will be freed
+    before dereference sites in ax25_send_control().
+    
+    The following is part of the report:
+    
+    [  102.297448] BUG: KASAN: use-after-free in ax25_send_control+0x33/0x210
+    [  102.297448] Read of size 8 at addr ffff888009e6e408 by task ax25_close/602
+    [  102.297448] Call Trace:
+    [  102.303751]  ax25_send_control+0x33/0x210
+    [  102.303751]  ax25_release+0x356/0x450
+    [  102.305431]  __sock_release+0x6d/0x120
+    [  102.305431]  sock_close+0xf/0x20
+    [  102.305431]  __fput+0x11f/0x420
+    [  102.305431]  task_work_run+0x86/0xd0
+    [  102.307130]  get_signal+0x1075/0x1220
+    [  102.308253]  arch_do_signal_or_restart+0x1df/0xc00
+    [  102.308253]  exit_to_user_mode_prepare+0x150/0x1e0
+    [  102.308253]  syscall_exit_to_user_mode+0x19/0x50
+    [  102.308253]  do_syscall_64+0x48/0x90
+    [  102.308253]  entry_SYSCALL_64_after_hwframe+0x44/0xae
+    [  102.308253] RIP: 0033:0x405ae7
+    
+    This patch defers the free operation of ax25_dev and net_device after
+    all corresponding dereference sites in ax25_release() to avoid UAF.
+    
+    Fixes: 9fd75b66b8f6 ("ax25: Fix refcount leaks caused by ax25_cb_del()")
+    Signed-off-by: Duoming Zhou 
+    Signed-off-by: Paolo Abeni 
+
+diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
+index 992b6e5d85d7..f5686c463bc0 100644
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -991,10 +991,6 @@ static int ax25_release(struct socket *sock)
+ 	sock_orphan(sk);
+ 	ax25 = sk_to_ax25(sk);
+ 	ax25_dev = ax25->ax25_dev;
+-	if (ax25_dev) {
+-		dev_put_track(ax25_dev->dev, &ax25_dev->dev_tracker);
+-		ax25_dev_put(ax25_dev);
+-	}
+ 
+ 	if (sk->sk_type == SOCK_SEQPACKET) {
+ 		switch (ax25->state) {
+@@ -1056,6 +1052,10 @@ static int ax25_release(struct socket *sock)
+ 		sk->sk_state_change(sk);
+ 		ax25_destroy_socket(ax25);
+ 	}
++	if (ax25_dev) {
++		dev_put_track(ax25_dev->dev, &ax25_dev->dev_tracker);
++		ax25_dev_put(ax25_dev);
++	}
+ 
+ 	sock->sk   = NULL;
+ 	release_sock(sk);

commit 7781607938c8371d4c2b243527430241c62e39c2
+Author: Duoming Zhou 
+Date:   Sat Mar 26 18:43:46 2022 +0800
+
+    net/x25: Fix null-ptr-deref caused by x25_disconnect
+    
+    When the link layer is terminating, x25->neighbour will be set to NULL
+    in x25_disconnect(). As a result, it could cause null-ptr-deref bugs in
+    x25_sendmsg(),x25_recvmsg() and x25_connect(). One of the bugs is
+    shown below.
+    
+        (Thread 1)                 |  (Thread 2)
+    x25_link_terminated()          | x25_recvmsg()
+     x25_kill_by_neigh()           |  ...
+      x25_disconnect()             |  lock_sock(sk)
+       ...                         |  ...
+       x25->neighbour = NULL //(1) |
+       ...                         |  x25->neighbour->extended //(2)
+    
+    The code sets NULL to x25->neighbour in position (1) and dereferences
+    x25->neighbour in position (2), which could cause null-ptr-deref bug.
+    
+    This patch adds lock_sock() in x25_kill_by_neigh() in order to synchronize
+    with x25_sendmsg(), x25_recvmsg() and x25_connect(). What`s more, the
+    sock held by lock_sock() is not NULL, because it is extracted from x25_list
+    and uses x25_list_lock to synchronize.
+    
+    Fixes: 4becb7ee5b3d ("net/x25: Fix x25_neigh refcnt leak when x25 disconnect")
+    Signed-off-by: Duoming Zhou 
+    Reviewed-by: Lin Ma 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
+index 3583354a7d7f..3a171828638b 100644
+--- a/net/x25/af_x25.c
++++ b/net/x25/af_x25.c
+@@ -1765,10 +1765,15 @@ void x25_kill_by_neigh(struct x25_neigh *nb)
+ 
+ 	write_lock_bh(&x25_list_lock);
+ 
+-	sk_for_each(s, &x25_list)
+-		if (x25_sk(s)->neighbour == nb)
++	sk_for_each(s, &x25_list) {
++		if (x25_sk(s)->neighbour == nb) {
++			write_unlock_bh(&x25_list_lock);
++			lock_sock(s);
+ 			x25_disconnect(s, ENETUNREACH, 0, 0);
+-
++			release_sock(s);
++			write_lock_bh(&x25_list_lock);
++		}
++	}
+ 	write_unlock_bh(&x25_list_lock);
+ 
+ 	/* Remove any related forwards */

commit fc6d01ff9ef03b66d4a3a23b46fc3c3d8cf92009
+Author: Duoming Zhou 
+Date:   Fri Mar 18 08:54:05 2022 +0800
+
+    ax25: Fix NULL pointer dereferences in ax25 timers
+    
+    The previous commit 7ec02f5ac8a5 ("ax25: fix NPD bug in ax25_disconnect")
+    move ax25_disconnect into lock_sock() in order to prevent NPD bugs. But
+    there are race conditions that may lead to null pointer dereferences in
+    ax25_heartbeat_expiry(), ax25_t1timer_expiry(), ax25_t2timer_expiry(),
+    ax25_t3timer_expiry() and ax25_idletimer_expiry(), when we use
+    ax25_kill_by_device() to detach the ax25 device.
+    
+    One of the race conditions that cause null pointer dereferences can be
+    shown as below:
+    
+          (Thread 1)                    |      (Thread 2)
+    ax25_connect()                      |
+     ax25_std_establish_data_link()     |
+      ax25_start_t1timer()              |
+       mod_timer(&ax25->t1timer,..)     |
+                                        | ax25_kill_by_device()
+       (wait a time)                    |  ...
+                                        |  s->ax25_dev = NULL; //(1)
+       ax25_t1timer_expiry()            |
+        ax25->ax25_dev->values[..] //(2)|  ...
+         ...                            |
+    
+    We set null to ax25_cb->ax25_dev in position (1) and dereference
+    the null pointer in position (2).
+    
+    The corresponding fail log is shown below:
+    ===============================================================
+    BUG: kernel NULL pointer dereference, address: 0000000000000050
+    CPU: 1 PID: 0 Comm: swapper/1 Not tainted 5.17.0-rc6-00794-g45690b7d0
+    RIP: 0010:ax25_t1timer_expiry+0x12/0x40
+    ...
+    Call Trace:
+     call_timer_fn+0x21/0x120
+     __run_timers.part.0+0x1ca/0x250
+     run_timer_softirq+0x2c/0x60
+     __do_softirq+0xef/0x2f3
+     irq_exit_rcu+0xb6/0x100
+     sysvec_apic_timer_interrupt+0xa2/0xd0
+    ...
+    
+    This patch moves ax25_disconnect() before s->ax25_dev = NULL
+    and uses del_timer_sync() to delete timers in ax25_disconnect().
+    If ax25_disconnect() is called by ax25_kill_by_device() or
+    ax25->ax25_dev is NULL, the reason in ax25_disconnect() will be
+    equal to ENETUNREACH, it will wait all timers to stop before we
+    set null to s->ax25_dev in ax25_kill_by_device().
+    
+    Fixes: 7ec02f5ac8a5 ("ax25: fix NPD bug in ax25_disconnect")
+    Signed-off-by: Duoming Zhou 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
+index cf8847cfc664..992b6e5d85d7 100644
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -89,20 +89,20 @@ static void ax25_kill_by_device(struct net_device *dev)
+ 			sk = s->sk;
+ 			if (!sk) {
+ 				spin_unlock_bh(&ax25_list_lock);
+-				s->ax25_dev = NULL;
+ 				ax25_disconnect(s, ENETUNREACH);
++				s->ax25_dev = NULL;
+ 				spin_lock_bh(&ax25_list_lock);
+ 				goto again;
+ 			}
+ 			sock_hold(sk);
+ 			spin_unlock_bh(&ax25_list_lock);
+ 			lock_sock(sk);
++			ax25_disconnect(s, ENETUNREACH);
+ 			s->ax25_dev = NULL;
+ 			if (sk->sk_socket) {
+ 				dev_put_track(ax25_dev->dev, &ax25_dev->dev_tracker);
+ 				ax25_dev_put(ax25_dev);
+ 			}
+-			ax25_disconnect(s, ENETUNREACH);
+ 			release_sock(sk);
+ 			spin_lock_bh(&ax25_list_lock);
+ 			sock_put(sk);
+diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c
+index 15ab812c4fe4..3a476e4f6cd0 100644
+--- a/net/ax25/ax25_subr.c
++++ b/net/ax25/ax25_subr.c
+@@ -261,12 +261,20 @@ void ax25_disconnect(ax25_cb *ax25, int reason)
+ {
+ 	ax25_clear_queues(ax25);
+ 
+-	if (!ax25->sk || !sock_flag(ax25->sk, SOCK_DESTROY))
+-		ax25_stop_heartbeat(ax25);
+-	ax25_stop_t1timer(ax25);
+-	ax25_stop_t2timer(ax25);
+-	ax25_stop_t3timer(ax25);
+-	ax25_stop_idletimer(ax25);
++	if (reason == ENETUNREACH) {
++		del_timer_sync(&ax25->timer);
++		del_timer_sync(&ax25->t1timer);
++		del_timer_sync(&ax25->t2timer);
++		del_timer_sync(&ax25->t3timer);
++		del_timer_sync(&ax25->idletimer);
++	} else {
++		if (!ax25->sk || !sock_flag(ax25->sk, SOCK_DESTROY))
++			ax25_stop_heartbeat(ax25);
++		ax25_stop_t1timer(ax25);
++		ax25_stop_t2timer(ax25);
++		ax25_stop_t3timer(ax25);
++		ax25_stop_idletimer(ax25);
++	}
+ 
+ 	ax25->state = AX25_STATE_0;
+ 

commit 9fd75b66b8f68498454d685dc4ba13192ae069b0
+Author: Duoming Zhou 
+Date:   Fri Mar 18 08:54:04 2022 +0800
+
+    ax25: Fix refcount leaks caused by ax25_cb_del()
+    
+    The previous commit d01ffb9eee4a ("ax25: add refcount in ax25_dev to
+    avoid UAF bugs") and commit feef318c855a ("ax25: fix UAF bugs of
+    net_device caused by rebinding operation") increase the refcounts of
+    ax25_dev and net_device in ax25_bind() and decrease the matching refcounts
+    in ax25_kill_by_device() in order to prevent UAF bugs, but there are
+    reference count leaks.
+    
+    The root cause of refcount leaks is shown below:
+    
+         (Thread 1)                      |      (Thread 2)
+    ax25_bind()                          |
+     ...                                 |
+     ax25_addr_ax25dev()                 |
+      ax25_dev_hold()   //(1)            |
+      ...                                |
+     dev_hold_track()   //(2)            |
+     ...                                 | ax25_destroy_socket()
+                                         |  ax25_cb_del()
+                                         |   ...
+                                         |   hlist_del_init() //(3)
+                                         |
+                                         |
+         (Thread 3)                      |
+    ax25_kill_by_device()                |
+     ...                                 |
+     ax25_for_each(s, &ax25_list) {      |
+      if (s->ax25_dev == ax25_dev) //(4) |
+       ...                               |
+    
+    Firstly, we use ax25_bind() to increase the refcount of ax25_dev in
+    position (1) and increase the refcount of net_device in position (2).
+    Then, we use ax25_cb_del() invoked by ax25_destroy_socket() to delete
+    ax25_cb in hlist in position (3) before calling ax25_kill_by_device().
+    Finally, the decrements of refcounts in ax25_kill_by_device() will not
+    be executed, because no s->ax25_dev equals to ax25_dev in position (4).
+    
+    This patch adds decrements of refcounts in ax25_release() and use
+    lock_sock() to do synchronization. If refcounts decrease in ax25_release(),
+    the decrements of refcounts in ax25_kill_by_device() will not be
+    executed and vice versa.
+    
+    Fixes: d01ffb9eee4a ("ax25: add refcount in ax25_dev to avoid UAF bugs")
+    Fixes: 87563a043cef ("ax25: fix reference count leaks of ax25_dev")
+    Fixes: feef318c855a ("ax25: fix UAF bugs of net_device caused by rebinding operation")
+    Reported-by: Thomas Osterried 
+    Signed-off-by: Duoming Zhou 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
+index 6bd097180772..cf8847cfc664 100644
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -98,8 +98,10 @@ static void ax25_kill_by_device(struct net_device *dev)
+ 			spin_unlock_bh(&ax25_list_lock);
+ 			lock_sock(sk);
+ 			s->ax25_dev = NULL;
+-			dev_put_track(ax25_dev->dev, &ax25_dev->dev_tracker);
+-			ax25_dev_put(ax25_dev);
++			if (sk->sk_socket) {
++				dev_put_track(ax25_dev->dev, &ax25_dev->dev_tracker);
++				ax25_dev_put(ax25_dev);
++			}
+ 			ax25_disconnect(s, ENETUNREACH);
+ 			release_sock(sk);
+ 			spin_lock_bh(&ax25_list_lock);
+@@ -979,14 +981,20 @@ static int ax25_release(struct socket *sock)
+ {
+ 	struct sock *sk = sock->sk;
+ 	ax25_cb *ax25;
++	ax25_dev *ax25_dev;
+ 
+ 	if (sk == NULL)
+ 		return 0;
+ 
+ 	sock_hold(sk);
+-	sock_orphan(sk);
+ 	lock_sock(sk);
++	sock_orphan(sk);
+ 	ax25 = sk_to_ax25(sk);
++	ax25_dev = ax25->ax25_dev;
++	if (ax25_dev) {
++		dev_put_track(ax25_dev->dev, &ax25_dev->dev_tracker);
++		ax25_dev_put(ax25_dev);
++	}
+ 
+ 	if (sk->sk_type == SOCK_SEQPACKET) {
+ 		switch (ax25->state) {

commit 71171ac8eb34ce7fe6b3267dce27c313ab3cb3ac
+Author: Duoming Zhou 
+Date:   Tue Mar 8 16:12:23 2022 +0800
+
+    ax25: Fix NULL pointer dereference in ax25_kill_by_device
+    
+    When two ax25 devices attempted to establish connection, the requester use ax25_create(),
+    ax25_bind() and ax25_connect() to initiate connection. The receiver use ax25_rcv() to
+    accept connection and use ax25_create_cb() in ax25_rcv() to create ax25_cb, but the
+    ax25_cb->sk is NULL. When the receiver is detaching, a NULL pointer dereference bug
+    caused by sock_hold(sk) in ax25_kill_by_device() will happen. The corresponding
+    fail log is shown below:
+    
+    ===============================================================
+    BUG: KASAN: null-ptr-deref in ax25_device_event+0xfd/0x290
+    Call Trace:
+    ...
+    ax25_device_event+0xfd/0x290
+    raw_notifier_call_chain+0x5e/0x70
+    dev_close_many+0x174/0x220
+    unregister_netdevice_many+0x1f7/0xa60
+    unregister_netdevice_queue+0x12f/0x170
+    unregister_netdev+0x13/0x20
+    mkiss_close+0xcd/0x140
+    tty_ldisc_release+0xc0/0x220
+    tty_release_struct+0x17/0xa0
+    tty_release+0x62d/0x670
+    ...
+    
+    This patch add condition check in ax25_kill_by_device(). If s->sk is
+    NULL, it will goto if branch to kill device.
+    
+    Fixes: 4e0f718daf97 ("ax25: improve the incomplete fix to avoid UAF and NPD bugs")
+    Reported-by: Thomas Osterried 
+    Signed-off-by: Duoming Zhou 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
+index d53cbb4e2503..6bd097180772 100644
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -87,6 +87,13 @@ static void ax25_kill_by_device(struct net_device *dev)
+ 	ax25_for_each(s, &ax25_list) {
+ 		if (s->ax25_dev == ax25_dev) {
+ 			sk = s->sk;
++			if (!sk) {
++				spin_unlock_bh(&ax25_list_lock);
++				s->ax25_dev = NULL;
++				ax25_disconnect(s, ENETUNREACH);
++				spin_lock_bh(&ax25_list_lock);
++				goto again;
++			}
+ 			sock_hold(sk);
+ 			spin_unlock_bh(&ax25_list_lock);
+ 			lock_sock(sk);

commit fa78d2d1d64f147062e384a4a10a26a5f89944b5
+Author: Lin Ma 
+Date:   Wed Feb 16 12:37:14 2022 +0800
+
+    Bluetooth: fix data races in smp_unregister(), smp_del_chan()
+    
+    Previous commit e04480920d1e ("Bluetooth: defer cleanup of resources
+    in hci_unregister_dev()") defers all destructive actions to
+    hci_release_dev() to prevent cocurrent problems like NPD, UAF.
+    
+    However, there are still some exceptions that are ignored.
+    
+    The smp_unregister() in hci_dev_close_sync() (previously in
+    hci_dev_do_close) will release resources like the sensitive channel
+    and the smp_dev objects. Consider the situations the device is detaching
+    or power down while the kernel is still operating on it, the following
+    data race could take place.
+    
+    thread-A  hci_dev_close_sync  | thread-B  read_local_oob_ext_data
+                                  |
+    hci_dev_unlock()              |
+    ...                           | hci_dev_lock()
+    if (hdev->smp_data)           |
+      chan = hdev->smp_data       |
+                                  | chan = hdev->smp_data (3)
+                                  |
+      hdev->smp_data = NULL (1)   | if (!chan || !chan->data) (4)
+      ...                         |
+      smp = chan->data            | smp = chan->data
+      if (smp)                    |
+        chan->data = NULL (2)     |
+        ...                       |
+        kfree_sensitive(smp)      |
+                                  | // dereference smp trigger UFA
+    
+    That is, the objects hdev->smp_data and chan->data both suffer from the
+    data races. In a preempt-enable kernel, the above schedule (when (3) is
+    before (1) and (4) is before (2)) leads to UAF bugs. It can be
+    reproduced in the latest kernel and below is part of the report:
+    
+    [   49.097146] ================================================================
+    [   49.097611] BUG: KASAN: use-after-free in smp_generate_oob+0x2dd/0x570
+    [   49.097611] Read of size 8 at addr ffff888006528360 by task generate_oob/155
+    [   49.097611]
+    [   49.097611] Call Trace:
+    [   49.097611]  
+    [   49.097611]  dump_stack_lvl+0x34/0x44
+    [   49.097611]  print_address_description.constprop.0+0x1f/0x150
+    [   49.097611]  ? smp_generate_oob+0x2dd/0x570
+    [   49.097611]  ? smp_generate_oob+0x2dd/0x570
+    [   49.097611]  kasan_report.cold+0x7f/0x11b
+    [   49.097611]  ? smp_generate_oob+0x2dd/0x570
+    [   49.097611]  smp_generate_oob+0x2dd/0x570
+    [   49.097611]  read_local_oob_ext_data+0x689/0xc30
+    [   49.097611]  ? hci_event_packet+0xc80/0xc80
+    [   49.097611]  ? sysvec_apic_timer_interrupt+0x9b/0xc0
+    [   49.097611]  ? asm_sysvec_apic_timer_interrupt+0x12/0x20
+    [   49.097611]  ? mgmt_init_hdev+0x1c/0x240
+    [   49.097611]  ? mgmt_init_hdev+0x28/0x240
+    [   49.097611]  hci_sock_sendmsg+0x1880/0x1e70
+    [   49.097611]  ? create_monitor_event+0x890/0x890
+    [   49.097611]  ? create_monitor_event+0x890/0x890
+    [   49.097611]  sock_sendmsg+0xdf/0x110
+    [   49.097611]  __sys_sendto+0x19e/0x270
+    [   49.097611]  ? __ia32_sys_getpeername+0xa0/0xa0
+    [   49.097611]  ? kernel_fpu_begin_mask+0x1c0/0x1c0
+    [   49.097611]  __x64_sys_sendto+0xd8/0x1b0
+    [   49.097611]  ? syscall_exit_to_user_mode+0x1d/0x40
+    [   49.097611]  do_syscall_64+0x3b/0x90
+    [   49.097611]  entry_SYSCALL_64_after_hwframe+0x44/0xae
+    [   49.097611] RIP: 0033:0x7f5a59f51f64
+    ...
+    [   49.097611] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f5a59f51f64
+    [   49.097611] RDX: 0000000000000007 RSI: 00007f5a59d6ac70 RDI: 0000000000000006
+    [   49.097611] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
+    [   49.097611] R10: 0000000000000040 R11: 0000000000000246 R12: 00007ffec26916ee
+    [   49.097611] R13: 00007ffec26916ef R14: 00007f5a59d6afc0 R15: 00007f5a59d6b700
+    
+    To solve these data races, this patch places the smp_unregister()
+    function in the protected area by the hci_dev_lock(). That is, the
+    smp_unregister() function can not be concurrently executed when
+    operating functions (most of them are mgmt operations in mgmt.c) hold
+    the device lock.
+    
+    This patch is tested with kernel LOCK DEBUGGING enabled. The price from
+    the extended holding time of the device lock is supposed to be low as the
+    smp_unregister() function is fairly short and efficient.
+    
+    Signed-off-by: Lin Ma 
+    Signed-off-by: Marcel Holtmann 
+
+diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
+index 0feb68f12545..e34fc15b7d2c 100644
+--- a/net/bluetooth/hci_sync.c
++++ b/net/bluetooth/hci_sync.c
+@@ -4106,9 +4106,9 @@ int hci_dev_close_sync(struct hci_dev *hdev)
+ 	hci_inquiry_cache_flush(hdev);
+ 	hci_pend_le_actions_clear(hdev);
+ 	hci_conn_hash_flush(hdev);
+-	hci_dev_unlock(hdev);
+-
++	/* Prevent data races on hdev->smp_data or hdev->smp_bredr_data */
+ 	smp_unregister(hdev);
++	hci_dev_unlock(hdev);
+ 
+ 	hci_sock_dev_event(hdev, HCI_DEV_DOWN);
+ 

commit efe4186e6a1b54bf38b9e05450d43b0da1fd7739
+Author: Duoming Zhou 
+Date:   Thu Feb 17 09:43:03 2022 +0800
+
+    drivers: hamradio: 6pack: fix UAF bug caused by mod_timer()
+    
+    When a 6pack device is detaching, the sixpack_close() will act to cleanup
+    necessary resources. Although del_timer_sync() in sixpack_close()
+    won't return if there is an active timer, one could use mod_timer() in
+    sp_xmit_on_air() to wake up timer again by calling userspace syscall such
+    as ax25_sendmsg(), ax25_connect() and ax25_ioctl().
+    
+    This unexpected waked handler, sp_xmit_on_air(), realizes nothing about
+    the undergoing cleanup and may still call pty_write() to use driver layer
+    resources that have already been released.
+    
+    One of the possible race conditions is shown below:
+    
+          (USE)                      |      (FREE)
+    ax25_sendmsg()                   |
+     ax25_queue_xmit()               |
+      ...                            |
+      sp_xmit()                      |
+       sp_encaps()                   | sixpack_close()
+        sp_xmit_on_air()             |  del_timer_sync(&sp->tx_t)
+         mod_timer(&sp->tx_t,...)    |  ...
+                                     |  unregister_netdev()
+                                     |  ...
+         (wait a while)              | tty_release()
+                                     |  tty_release_struct()
+                                     |   release_tty()
+        sp_xmit_on_air()             |    tty_kref_put(tty_struct) //FREE
+         pty_write(tty_struct) //USE |    ...
+    
+    The corresponding fail log is shown below:
+    ===============================================================
+    BUG: KASAN: use-after-free in __run_timers.part.0+0x170/0x470
+    Write of size 8 at addr ffff88800a652ab8 by task swapper/2/0
+    ...
+    Call Trace:
+      ...
+      queue_work_on+0x3f/0x50
+      pty_write+0xcd/0xe0pty_write+0xcd/0xe0
+      sp_xmit_on_air+0xb2/0x1f0
+      call_timer_fn+0x28/0x150
+      __run_timers.part.0+0x3c2/0x470
+      run_timer_softirq+0x3b/0x80
+      __do_softirq+0xf1/0x380
+      ...
+    
+    This patch reorders the del_timer_sync() after the unregister_netdev()
+    to avoid UAF bugs. Because the unregister_netdev() is well synchronized,
+    it flushs out any pending queues, waits the refcount of net_device
+    decreases to zero and removes net_device from kernel. There is not any
+    running routines after executing unregister_netdev(). Therefore, we could
+    not arouse timer from userspace again.
+    
+    Signed-off-by: Duoming Zhou 
+    Reviewed-by: Lin Ma 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
+index b1fc153125d9..45c3c4a1101b 100644
+--- a/drivers/net/hamradio/6pack.c
++++ b/drivers/net/hamradio/6pack.c
+@@ -668,11 +668,11 @@ static void sixpack_close(struct tty_struct *tty)
+ 	 */
+ 	netif_stop_queue(sp->dev);
+ 
++	unregister_netdev(sp->dev);
++
+ 	del_timer_sync(&sp->tx_t);
+ 	del_timer_sync(&sp->resync_t);
+ 
+-	unregister_netdev(sp->dev);
+-
+ 	/* Free all 6pack frame buffers after unreg. */
+ 	kfree(sp->rbuff);
+ 	kfree(sp->xbuff);

commit feef318c855a361a1eccd880f33e88c460eb63b4
+Author: Duoming Zhou 
+Date:   Wed Feb 9 20:53:45 2022 +0800
+
+    ax25: fix UAF bugs of net_device caused by rebinding operation
+    
+    The ax25_kill_by_device() will set s->ax25_dev = NULL and
+    call ax25_disconnect() to change states of ax25_cb and
+    sock, if we call ax25_bind() before ax25_kill_by_device().
+    
+    However, if we call ax25_bind() again between the window of
+    ax25_kill_by_device() and ax25_dev_device_down(), the values
+    and states changed by ax25_kill_by_device() will be reassigned.
+    
+    Finally, ax25_dev_device_down() will deallocate net_device.
+    If we dereference net_device in syscall functions such as
+    ax25_release(), ax25_sendmsg(), ax25_getsockopt(), ax25_getname()
+    and ax25_info_show(), a UAF bug will occur.
+    
+    One of the possible race conditions is shown below:
+    
+          (USE)                   |      (FREE)
+    ax25_bind()                   |
+                                  |  ax25_kill_by_device()
+    ax25_bind()                   |
+    ax25_connect()                |    ...
+                                  |  ax25_dev_device_down()
+                                  |    ...
+                                  |    dev_put_track(dev, ...) //FREE
+    ax25_release()                |    ...
+      ax25_send_control()         |
+        alloc_skb()      //USE    |
+    
+    the corresponding fail log is shown below:
+    ===============================================================
+    BUG: KASAN: use-after-free in ax25_send_control+0x43/0x210
+    ...
+    Call Trace:
+      ...
+      ax25_send_control+0x43/0x210
+      ax25_release+0x2db/0x3b0
+      __sock_release+0x6d/0x120
+      sock_close+0xf/0x20
+      __fput+0x11f/0x420
+      ...
+    Allocated by task 1283:
+      ...
+      __kasan_kmalloc+0x81/0xa0
+      alloc_netdev_mqs+0x5a/0x680
+      mkiss_open+0x6c/0x380
+      tty_ldisc_open+0x55/0x90
+      ...
+    Freed by task 1969:
+      ...
+      kfree+0xa3/0x2c0
+      device_release+0x54/0xe0
+      kobject_put+0xa5/0x120
+      tty_ldisc_kill+0x3e/0x80
+      ...
+    
+    In order to fix these UAF bugs caused by rebinding operation,
+    this patch adds dev_hold_track() into ax25_bind() and
+    corresponding dev_put_track() into ax25_kill_by_device().
+    
+    Signed-off-by: Duoming Zhou 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
+index 3d87040d1bfc..d53cbb4e2503 100644
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -91,6 +91,7 @@ static void ax25_kill_by_device(struct net_device *dev)
+ 			spin_unlock_bh(&ax25_list_lock);
+ 			lock_sock(sk);
+ 			s->ax25_dev = NULL;
++			dev_put_track(ax25_dev->dev, &ax25_dev->dev_tracker);
+ 			ax25_dev_put(ax25_dev);
+ 			ax25_disconnect(s, ENETUNREACH);
+ 			release_sock(sk);
+@@ -1116,8 +1117,10 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ 		}
+ 	}
+ 
+-	if (ax25_dev != NULL)
++	if (ax25_dev) {
+ 		ax25_fillin_cb(ax25, ax25_dev);
++		dev_hold_track(ax25_dev->dev, &ax25_dev->dev_tracker, GFP_ATOMIC);
++	}
+ 
+ done:
+ 	ax25_cb_add(ax25);

commit 7ec02f5ac8a5be5a3f20611731243dc5e1d9ba10
+Author: Duoming Zhou 
+Date:   Tue Feb 8 23:40:00 2022 +0800
+
+    ax25: fix NPD bug in ax25_disconnect
+    
+    The ax25_disconnect() in ax25_kill_by_device() is not
+    protected by any locks, thus there is a race condition
+    between ax25_disconnect() and ax25_destroy_socket().
+    when ax25->sk is assigned as NULL by ax25_destroy_socket(),
+    a NULL pointer dereference bug will occur if site (1) or (2)
+    dereferences ax25->sk.
+    
+    ax25_kill_by_device()                | ax25_release()
+      ax25_disconnect()                  |   ax25_destroy_socket()
+        ...                              |
+        if(ax25->sk != NULL)             |     ...
+          ...                            |     ax25->sk = NULL;
+          bh_lock_sock(ax25->sk); //(1)  |     ...
+          ...                            |
+          bh_unlock_sock(ax25->sk); //(2)|
+    
+    This patch moves ax25_disconnect() into lock_sock(), which can
+    synchronize with ax25_destroy_socket() in ax25_release().
+    
+    Fail log:
+    ===============================================================
+    BUG: kernel NULL pointer dereference, address: 0000000000000088
+    ...
+    RIP: 0010:_raw_spin_lock+0x7e/0xd0
+    ...
+    Call Trace:
+    ax25_disconnect+0xf6/0x220
+    ax25_device_event+0x187/0x250
+    raw_notifier_call_chain+0x5e/0x70
+    dev_close_many+0x17d/0x230
+    rollback_registered_many+0x1f1/0x950
+    unregister_netdevice_queue+0x133/0x200
+    unregister_netdev+0x13/0x20
+    ...
+    
+    Signed-off-by: Duoming Zhou 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
+index 3e49d28824ed..3d87040d1bfc 100644
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -92,8 +92,8 @@ static void ax25_kill_by_device(struct net_device *dev)
+ 			lock_sock(sk);
+ 			s->ax25_dev = NULL;
+ 			ax25_dev_put(ax25_dev);
+-			release_sock(sk);
+ 			ax25_disconnect(s, ENETUNREACH);
++			release_sock(sk);
+ 			spin_lock_bh(&ax25_list_lock);
+ 			sock_put(sk);
+ 			/* The entry could have been deleted from the

commit 87563a043cef044fed5db7967a75741cc16ad2b1
+Author: Duoming Zhou 
+Date:   Thu Feb 3 23:08:11 2022 +0800
+
+    ax25: fix reference count leaks of ax25_dev
+    
+    The previous commit d01ffb9eee4a ("ax25: add refcount in ax25_dev
+    to avoid UAF bugs") introduces refcount into ax25_dev, but there
+    are reference leak paths in ax25_ctl_ioctl(), ax25_fwd_ioctl(),
+    ax25_rt_add(), ax25_rt_del() and ax25_rt_opt().
+    
+    This patch uses ax25_dev_put() and adjusts the position of
+    ax25_addr_ax25dev() to fix reference cout leaks of ax25_dev.
+    
+    Fixes: d01ffb9eee4a ("ax25: add refcount in ax25_dev to avoid UAF bugs")
+    Signed-off-by: Duoming Zhou 
+    Reviewed-by: Dan Carpenter 
+    Link: https://lore.kernel.org/r/20220203150811.42256-1-duoming@zju.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/include/net/ax25.h b/include/net/ax25.h
+index 50b417df6221..8221af1811df 100644
+--- a/include/net/ax25.h
++++ b/include/net/ax25.h
+@@ -294,10 +294,12 @@ static __inline__ void ax25_cb_put(ax25_cb *ax25)
+ 	}
+ }
+ 
+-#define ax25_dev_hold(__ax25_dev) \
+-	refcount_inc(&((__ax25_dev)->refcount))
++static inline void ax25_dev_hold(ax25_dev *ax25_dev)
++{
++	refcount_inc(&ax25_dev->refcount);
++}
+ 
+-static __inline__ void ax25_dev_put(ax25_dev *ax25_dev)
++static inline void ax25_dev_put(ax25_dev *ax25_dev)
+ {
+ 	if (refcount_dec_and_test(&ax25_dev->refcount)) {
+ 		kfree(ax25_dev);
+diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
+index 32f61978ff29..3e49d28824ed 100644
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -359,21 +359,25 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void __user *arg)
+ 	if (copy_from_user(&ax25_ctl, arg, sizeof(ax25_ctl)))
+ 		return -EFAULT;
+ 
+-	if ((ax25_dev = ax25_addr_ax25dev(&ax25_ctl.port_addr)) == NULL)
+-		return -ENODEV;
+-
+ 	if (ax25_ctl.digi_count > AX25_MAX_DIGIS)
+ 		return -EINVAL;
+ 
+ 	if (ax25_ctl.arg > ULONG_MAX / HZ && ax25_ctl.cmd != AX25_KILL)
+ 		return -EINVAL;
+ 
++	ax25_dev = ax25_addr_ax25dev(&ax25_ctl.port_addr);
++	if (!ax25_dev)
++		return -ENODEV;
++
+ 	digi.ndigi = ax25_ctl.digi_count;
+ 	for (k = 0; k < digi.ndigi; k++)
+ 		digi.calls[k] = ax25_ctl.digi_addr[k];
+ 
+-	if ((ax25 = ax25_find_cb(&ax25_ctl.source_addr, &ax25_ctl.dest_addr, &digi, ax25_dev->dev)) == NULL)
++	ax25 = ax25_find_cb(&ax25_ctl.source_addr, &ax25_ctl.dest_addr, &digi, ax25_dev->dev);
++	if (!ax25) {
++		ax25_dev_put(ax25_dev);
+ 		return -ENOTCONN;
++	}
+ 
+ 	switch (ax25_ctl.cmd) {
+ 	case AX25_KILL:
+diff --git a/net/ax25/ax25_dev.c b/net/ax25/ax25_dev.c
+index 770b787fb7bb..d2a244e1c260 100644
+--- a/net/ax25/ax25_dev.c
++++ b/net/ax25/ax25_dev.c
+@@ -85,8 +85,8 @@ void ax25_dev_device_up(struct net_device *dev)
+ 	spin_lock_bh(&ax25_dev_lock);
+ 	ax25_dev->next = ax25_dev_list;
+ 	ax25_dev_list  = ax25_dev;
+-	ax25_dev_hold(ax25_dev);
+ 	spin_unlock_bh(&ax25_dev_lock);
++	ax25_dev_hold(ax25_dev);
+ 
+ 	ax25_register_dev_sysctl(ax25_dev);
+ }
+@@ -115,8 +115,8 @@ void ax25_dev_device_down(struct net_device *dev)
+ 
+ 	if ((s = ax25_dev_list) == ax25_dev) {
+ 		ax25_dev_list = s->next;
+-		ax25_dev_put(ax25_dev);
+ 		spin_unlock_bh(&ax25_dev_lock);
++		ax25_dev_put(ax25_dev);
+ 		dev->ax25_ptr = NULL;
+ 		dev_put_track(dev, &ax25_dev->dev_tracker);
+ 		ax25_dev_put(ax25_dev);
+@@ -126,8 +126,8 @@ void ax25_dev_device_down(struct net_device *dev)
+ 	while (s != NULL && s->next != NULL) {
+ 		if (s->next == ax25_dev) {
+ 			s->next = ax25_dev->next;
+-			ax25_dev_put(ax25_dev);
+ 			spin_unlock_bh(&ax25_dev_lock);
++			ax25_dev_put(ax25_dev);
+ 			dev->ax25_ptr = NULL;
+ 			dev_put_track(dev, &ax25_dev->dev_tracker);
+ 			ax25_dev_put(ax25_dev);
+@@ -150,25 +150,35 @@ int ax25_fwd_ioctl(unsigned int cmd, struct ax25_fwd_struct *fwd)
+ 
+ 	switch (cmd) {
+ 	case SIOCAX25ADDFWD:
+-		if ((fwd_dev = ax25_addr_ax25dev(&fwd->port_to)) == NULL)
++		fwd_dev = ax25_addr_ax25dev(&fwd->port_to);
++		if (!fwd_dev) {
++			ax25_dev_put(ax25_dev);
+ 			return -EINVAL;
+-		if (ax25_dev->forward != NULL)
++		}
++		if (ax25_dev->forward) {
++			ax25_dev_put(fwd_dev);
++			ax25_dev_put(ax25_dev);
+ 			return -EINVAL;
++		}
+ 		ax25_dev->forward = fwd_dev->dev;
+ 		ax25_dev_put(fwd_dev);
++		ax25_dev_put(ax25_dev);
+ 		break;
+ 
+ 	case SIOCAX25DELFWD:
+-		if (ax25_dev->forward == NULL)
++		if (!ax25_dev->forward) {
++			ax25_dev_put(ax25_dev);
+ 			return -EINVAL;
++		}
+ 		ax25_dev->forward = NULL;
++		ax25_dev_put(ax25_dev);
+ 		break;
+ 
+ 	default:
++		ax25_dev_put(ax25_dev);
+ 		return -EINVAL;
+ 	}
+ 
+-	ax25_dev_put(ax25_dev);
+ 	return 0;
+ }
+ 
+diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
+index 1e32693833e5..9751207f7757 100644
+--- a/net/ax25/ax25_route.c
++++ b/net/ax25/ax25_route.c
+@@ -75,11 +75,13 @@ static int __must_check ax25_rt_add(struct ax25_routes_struct *route)
+ 	ax25_dev *ax25_dev;
+ 	int i;
+ 
+-	if ((ax25_dev = ax25_addr_ax25dev(&route->port_addr)) == NULL)
+-		return -EINVAL;
+ 	if (route->digi_count > AX25_MAX_DIGIS)
+ 		return -EINVAL;
+ 
++	ax25_dev = ax25_addr_ax25dev(&route->port_addr);
++	if (!ax25_dev)
++		return -EINVAL;
++
+ 	write_lock_bh(&ax25_route_lock);
+ 
+ 	ax25_rt = ax25_route_list;
+@@ -91,6 +93,7 @@ static int __must_check ax25_rt_add(struct ax25_routes_struct *route)
+ 			if (route->digi_count != 0) {
+ 				if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
+ 					write_unlock_bh(&ax25_route_lock);
++					ax25_dev_put(ax25_dev);
+ 					return -ENOMEM;
+ 				}
+ 				ax25_rt->digipeat->lastrepeat = -1;
+@@ -101,6 +104,7 @@ static int __must_check ax25_rt_add(struct ax25_routes_struct *route)
+ 				}
+ 			}
+ 			write_unlock_bh(&ax25_route_lock);
++			ax25_dev_put(ax25_dev);
+ 			return 0;
+ 		}
+ 		ax25_rt = ax25_rt->next;
+@@ -108,6 +112,7 @@ static int __must_check ax25_rt_add(struct ax25_routes_struct *route)
+ 
+ 	if ((ax25_rt = kmalloc(sizeof(ax25_route), GFP_ATOMIC)) == NULL) {
+ 		write_unlock_bh(&ax25_route_lock);
++		ax25_dev_put(ax25_dev);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -116,11 +121,11 @@ static int __must_check ax25_rt_add(struct ax25_routes_struct *route)
+ 	ax25_rt->dev          = ax25_dev->dev;
+ 	ax25_rt->digipeat     = NULL;
+ 	ax25_rt->ip_mode      = ' ';
+-	ax25_dev_put(ax25_dev);
+ 	if (route->digi_count != 0) {
+ 		if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
+ 			write_unlock_bh(&ax25_route_lock);
+ 			kfree(ax25_rt);
++			ax25_dev_put(ax25_dev);
+ 			return -ENOMEM;
+ 		}
+ 		ax25_rt->digipeat->lastrepeat = -1;
+@@ -133,6 +138,7 @@ static int __must_check ax25_rt_add(struct ax25_routes_struct *route)
+ 	ax25_rt->next   = ax25_route_list;
+ 	ax25_route_list = ax25_rt;
+ 	write_unlock_bh(&ax25_route_lock);
++	ax25_dev_put(ax25_dev);
+ 
+ 	return 0;
+ }
+@@ -173,8 +179,8 @@ static int ax25_rt_del(struct ax25_routes_struct *route)
+ 			}
+ 		}
+ 	}
+-	ax25_dev_put(ax25_dev);
+ 	write_unlock_bh(&ax25_route_lock);
++	ax25_dev_put(ax25_dev);
+ 
+ 	return 0;
+ }
+@@ -216,8 +222,8 @@ static int ax25_rt_opt(struct ax25_route_opt_struct *rt_option)
+ 	}
+ 
+ out:
+-	ax25_dev_put(ax25_dev);
+ 	write_unlock_bh(&ax25_route_lock);
++	ax25_dev_put(ax25_dev);
+ 	return err;
+ }
+ 

commit d01ffb9eee4af165d83b08dd73ebdf9fe94a519b
+Author: Duoming Zhou 
+Date:   Fri Jan 28 12:47:16 2022 +0800
+
+    ax25: add refcount in ax25_dev to avoid UAF bugs
+    
+    If we dereference ax25_dev after we call kfree(ax25_dev) in
+    ax25_dev_device_down(), it will lead to concurrency UAF bugs.
+    There are eight syscall functions suffer from UAF bugs, include
+    ax25_bind(), ax25_release(), ax25_connect(), ax25_ioctl(),
+    ax25_getname(), ax25_sendmsg(), ax25_getsockopt() and
+    ax25_info_show().
+    
+    One of the concurrency UAF can be shown as below:
+    
+      (USE)                       |    (FREE)
+                                  |  ax25_device_event
+                                  |    ax25_dev_device_down
+    ax25_bind                     |    ...
+      ...                         |      kfree(ax25_dev)
+      ax25_fillin_cb()            |    ...
+        ax25_fillin_cb_from_dev() |
+      ...                         |
+    
+    The root cause of UAF bugs is that kfree(ax25_dev) in
+    ax25_dev_device_down() is not protected by any locks.
+    When ax25_dev, which there are still pointers point to,
+    is released, the concurrency UAF bug will happen.
+    
+    This patch introduces refcount into ax25_dev in order to
+    guarantee that there are no pointers point to it when ax25_dev
+    is released.
+    
+    Signed-off-by: Duoming Zhou 
+    Signed-off-by: David S. Miller 
+
+diff --git a/include/net/ax25.h b/include/net/ax25.h
+index 526e49589197..50b417df6221 100644
+--- a/include/net/ax25.h
++++ b/include/net/ax25.h
+@@ -239,6 +239,7 @@ typedef struct ax25_dev {
+ #if defined(CONFIG_AX25_DAMA_SLAVE) || defined(CONFIG_AX25_DAMA_MASTER)
+ 	ax25_dama_info		dama;
+ #endif
++	refcount_t		refcount;
+ } ax25_dev;
+ 
+ typedef struct ax25_cb {
+@@ -293,6 +294,15 @@ static __inline__ void ax25_cb_put(ax25_cb *ax25)
+ 	}
+ }
+ 
++#define ax25_dev_hold(__ax25_dev) \
++	refcount_inc(&((__ax25_dev)->refcount))
++
++static __inline__ void ax25_dev_put(ax25_dev *ax25_dev)
++{
++	if (refcount_dec_and_test(&ax25_dev->refcount)) {
++		kfree(ax25_dev);
++	}
++}
+ static inline __be16 ax25_type_trans(struct sk_buff *skb, struct net_device *dev)
+ {
+ 	skb->dev      = dev;
+diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
+index 44a8730c26ac..32f61978ff29 100644
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -91,6 +91,7 @@ static void ax25_kill_by_device(struct net_device *dev)
+ 			spin_unlock_bh(&ax25_list_lock);
+ 			lock_sock(sk);
+ 			s->ax25_dev = NULL;
++			ax25_dev_put(ax25_dev);
+ 			release_sock(sk);
+ 			ax25_disconnect(s, ENETUNREACH);
+ 			spin_lock_bh(&ax25_list_lock);
+@@ -439,6 +440,7 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void __user *arg)
+ 	  }
+ 
+ out_put:
++	ax25_dev_put(ax25_dev);
+ 	ax25_cb_put(ax25);
+ 	return ret;
+ 
+diff --git a/net/ax25/ax25_dev.c b/net/ax25/ax25_dev.c
+index 256fadb94df3..770b787fb7bb 100644
+--- a/net/ax25/ax25_dev.c
++++ b/net/ax25/ax25_dev.c
+@@ -37,6 +37,7 @@ ax25_dev *ax25_addr_ax25dev(ax25_address *addr)
+ 	for (ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next)
+ 		if (ax25cmp(addr, (const ax25_address *)ax25_dev->dev->dev_addr) == 0) {
+ 			res = ax25_dev;
++			ax25_dev_hold(ax25_dev);
+ 		}
+ 	spin_unlock_bh(&ax25_dev_lock);
+ 
+@@ -56,6 +57,7 @@ void ax25_dev_device_up(struct net_device *dev)
+ 		return;
+ 	}
+ 
++	refcount_set(&ax25_dev->refcount, 1);
+ 	dev->ax25_ptr     = ax25_dev;
+ 	ax25_dev->dev     = dev;
+ 	dev_hold_track(dev, &ax25_dev->dev_tracker, GFP_ATOMIC);
+@@ -83,6 +85,7 @@ void ax25_dev_device_up(struct net_device *dev)
+ 	spin_lock_bh(&ax25_dev_lock);
+ 	ax25_dev->next = ax25_dev_list;
+ 	ax25_dev_list  = ax25_dev;
++	ax25_dev_hold(ax25_dev);
+ 	spin_unlock_bh(&ax25_dev_lock);
+ 
+ 	ax25_register_dev_sysctl(ax25_dev);
+@@ -112,20 +115,22 @@ void ax25_dev_device_down(struct net_device *dev)
+ 
+ 	if ((s = ax25_dev_list) == ax25_dev) {
+ 		ax25_dev_list = s->next;
++		ax25_dev_put(ax25_dev);
+ 		spin_unlock_bh(&ax25_dev_lock);
+ 		dev->ax25_ptr = NULL;
+ 		dev_put_track(dev, &ax25_dev->dev_tracker);
+-		kfree(ax25_dev);
++		ax25_dev_put(ax25_dev);
+ 		return;
+ 	}
+ 
+ 	while (s != NULL && s->next != NULL) {
+ 		if (s->next == ax25_dev) {
+ 			s->next = ax25_dev->next;
++			ax25_dev_put(ax25_dev);
+ 			spin_unlock_bh(&ax25_dev_lock);
+ 			dev->ax25_ptr = NULL;
+ 			dev_put_track(dev, &ax25_dev->dev_tracker);
+-			kfree(ax25_dev);
++			ax25_dev_put(ax25_dev);
+ 			return;
+ 		}
+ 
+@@ -133,6 +138,7 @@ void ax25_dev_device_down(struct net_device *dev)
+ 	}
+ 	spin_unlock_bh(&ax25_dev_lock);
+ 	dev->ax25_ptr = NULL;
++	ax25_dev_put(ax25_dev);
+ }
+ 
+ int ax25_fwd_ioctl(unsigned int cmd, struct ax25_fwd_struct *fwd)
+@@ -149,6 +155,7 @@ int ax25_fwd_ioctl(unsigned int cmd, struct ax25_fwd_struct *fwd)
+ 		if (ax25_dev->forward != NULL)
+ 			return -EINVAL;
+ 		ax25_dev->forward = fwd_dev->dev;
++		ax25_dev_put(fwd_dev);
+ 		break;
+ 
+ 	case SIOCAX25DELFWD:
+@@ -161,6 +168,7 @@ int ax25_fwd_ioctl(unsigned int cmd, struct ax25_fwd_struct *fwd)
+ 		return -EINVAL;
+ 	}
+ 
++	ax25_dev_put(ax25_dev);
+ 	return 0;
+ }
+ 
+diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
+index d0b2e094bd55..1e32693833e5 100644
+--- a/net/ax25/ax25_route.c
++++ b/net/ax25/ax25_route.c
+@@ -116,6 +116,7 @@ static int __must_check ax25_rt_add(struct ax25_routes_struct *route)
+ 	ax25_rt->dev          = ax25_dev->dev;
+ 	ax25_rt->digipeat     = NULL;
+ 	ax25_rt->ip_mode      = ' ';
++	ax25_dev_put(ax25_dev);
+ 	if (route->digi_count != 0) {
+ 		if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
+ 			write_unlock_bh(&ax25_route_lock);
+@@ -172,6 +173,7 @@ static int ax25_rt_del(struct ax25_routes_struct *route)
+ 			}
+ 		}
+ 	}
++	ax25_dev_put(ax25_dev);
+ 	write_unlock_bh(&ax25_route_lock);
+ 
+ 	return 0;
+@@ -214,6 +216,7 @@ static int ax25_rt_opt(struct ax25_route_opt_struct *rt_option)
+ 	}
+ 
+ out:
++	ax25_dev_put(ax25_dev);
+ 	write_unlock_bh(&ax25_route_lock);
+ 	return err;
+ }

commit 4e0f718daf97d47cf7dec122da1be970f145c809
+Author: Duoming Zhou 
+Date:   Fri Jan 28 12:47:15 2022 +0800
+
+    ax25: improve the incomplete fix to avoid UAF and NPD bugs
+    
+    The previous commit 1ade48d0c27d ("ax25: NPD bug when detaching
+    AX25 device") introduce lock_sock() into ax25_kill_by_device to
+    prevent NPD bug. But the concurrency NPD or UAF bug will occur,
+    when lock_sock() or release_sock() dereferences the ax25_cb->sock.
+    
+    The NULL pointer dereference bug can be shown as below:
+    
+    ax25_kill_by_device()        | ax25_release()
+                                 |   ax25_destroy_socket()
+                                 |     ax25_cb_del()
+      ...                        |     ...
+                                 |     ax25->sk=NULL;
+      lock_sock(s->sk); //(1)    |
+      s->ax25_dev = NULL;        |     ...
+      release_sock(s->sk); //(2) |
+      ...                        |
+    
+    The root cause is that the sock is set to null before dereference
+    site (1) or (2). Therefore, this patch extracts the ax25_cb->sock
+    in advance, and uses ax25_list_lock to protect it, which can synchronize
+    with ax25_cb_del() and ensure the value of sock is not null before
+    dereference sites.
+    
+    The concurrency UAF bug can be shown as below:
+    
+    ax25_kill_by_device()        | ax25_release()
+                                 |   ax25_destroy_socket()
+      ...                        |   ...
+                                 |   sock_put(sk); //FREE
+      lock_sock(s->sk); //(1)    |
+      s->ax25_dev = NULL;        |   ...
+      release_sock(s->sk); //(2) |
+      ...                        |
+    
+    The root cause is that the sock is released before dereference
+    site (1) or (2). Therefore, this patch uses sock_hold() to increase
+    the refcount of sock and uses ax25_list_lock to protect it, which
+    can synchronize with ax25_cb_del() in ax25_destroy_socket() and
+    ensure the sock wil not be released before dereference sites.
+    
+    Signed-off-by: Duoming Zhou 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
+index 02f43f3e2c56..44a8730c26ac 100644
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -77,6 +77,7 @@ static void ax25_kill_by_device(struct net_device *dev)
+ {
+ 	ax25_dev *ax25_dev;
+ 	ax25_cb *s;
++	struct sock *sk;
+ 
+ 	if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
+ 		return;
+@@ -85,13 +86,15 @@ static void ax25_kill_by_device(struct net_device *dev)
+ again:
+ 	ax25_for_each(s, &ax25_list) {
+ 		if (s->ax25_dev == ax25_dev) {
++			sk = s->sk;
++			sock_hold(sk);
+ 			spin_unlock_bh(&ax25_list_lock);
+-			lock_sock(s->sk);
++			lock_sock(sk);
+ 			s->ax25_dev = NULL;
+-			release_sock(s->sk);
++			release_sock(sk);
+ 			ax25_disconnect(s, ENETUNREACH);
+ 			spin_lock_bh(&ax25_list_lock);
+-
++			sock_put(sk);
+ 			/* The entry could have been deleted from the
+ 			 * list meanwhile and thus the next pointer is
+ 			 * no longer valid.  Play it safe and restart

commit 1ade48d0c27d5da1ccf4b583d8c5fc8b534a3ac8
+Author: Lin Ma 
+Date:   Fri Dec 17 10:29:41 2021 +0800
+
+    ax25: NPD bug when detaching AX25 device
+    
+    The existing cleanup routine implementation is not well synchronized
+    with the syscall routine. When a device is detaching, below race could
+    occur.
+    
+    static int ax25_sendmsg(...) {
+      ...
+      lock_sock()
+      ax25 = sk_to_ax25(sk);
+      if (ax25->ax25_dev == NULL) // CHECK
+      ...
+      ax25_queue_xmit(skb, ax25->ax25_dev->dev); // USE
+      ...
+    }
+    
+    static void ax25_kill_by_device(...) {
+      ...
+      if (s->ax25_dev == ax25_dev) {
+        s->ax25_dev = NULL;
+        ...
+    }
+    
+    Other syscall functions like ax25_getsockopt, ax25_getname,
+    ax25_info_show also suffer from similar races. To fix them, this patch
+    introduce lock_sock() into ax25_kill_by_device in order to guarantee
+    that the nullify action in cleanup routine cannot proceed when another
+    socket request is pending.
+    
+    Signed-off-by: Hanjie Wu 
+    Signed-off-by: Lin Ma 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
+index 2f34bbdde0e8..cfca99e295b8 100644
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -85,8 +85,10 @@ static void ax25_kill_by_device(struct net_device *dev)
+ again:
+ 	ax25_for_each(s, &ax25_list) {
+ 		if (s->ax25_dev == ax25_dev) {
+-			s->ax25_dev = NULL;
+ 			spin_unlock_bh(&ax25_list_lock);
++			lock_sock(s->sk);
++			s->ax25_dev = NULL;
++			release_sock(s->sk);
+ 			ax25_disconnect(s, ENETUNREACH);
+ 			spin_lock_bh(&ax25_list_lock);
+ 

commit b2f37aead1b82a770c48b5d583f35ec22aabb61e
+Author: Lin Ma 
+Date:   Fri Dec 17 10:13:56 2021 +0800
+
+    hamradio: improve the incomplete fix to avoid NPD
+    
+    The previous commit 3e0588c291d6 ("hamradio: defer ax25 kfree after
+    unregister_netdev") reorder the kfree operations and unregister_netdev
+    operation to prevent UAF.
+    
+    This commit improves the previous one by also deferring the nullify of
+    the ax->tty pointer. Otherwise, a NULL pointer dereference bug occurs.
+    Partial of the stack trace is shown below.
+    
+    BUG: kernel NULL pointer dereference, address: 0000000000000538
+    RIP: 0010:ax_xmit+0x1f9/0x400
+    ...
+    Call Trace:
+     dev_hard_start_xmit+0xec/0x320
+     sch_direct_xmit+0xea/0x240
+     __qdisc_run+0x166/0x5c0
+     __dev_queue_xmit+0x2c7/0xaf0
+     ax25_std_establish_data_link+0x59/0x60
+     ax25_connect+0x3a0/0x500
+     ? security_socket_connect+0x2b/0x40
+     __sys_connect+0x96/0xc0
+     ? __hrtimer_init+0xc0/0xc0
+     ? common_nsleep+0x2e/0x50
+     ? switch_fpu_return+0x139/0x1a0
+     __x64_sys_connect+0x11/0x20
+     do_syscall_64+0x33/0x40
+     entry_SYSCALL_64_after_hwframe+0x44/0xa9
+    
+    The crash point is shown as below
+    
+    static void ax_encaps(...) {
+      ...
+      set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags); // ax->tty = NULL!
+      ...
+    }
+    
+    By placing the nullify action after the unregister_netdev, the ax->tty
+    pointer won't be assigned as NULL net_device framework layer is well
+    synchronized.
+    
+    Signed-off-by: Lin Ma 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
+index 7da2bb8a443c..edde9c3ae12b 100644
+--- a/drivers/net/hamradio/mkiss.c
++++ b/drivers/net/hamradio/mkiss.c
+@@ -794,14 +794,14 @@ static void mkiss_close(struct tty_struct *tty)
+ 	 */
+ 	netif_stop_queue(ax->dev);
+ 
+-	ax->tty = NULL;
+-
+ 	unregister_netdev(ax->dev);
+ 
+ 	/* Free all AX25 frame buffers after unreg. */
+ 	kfree(ax->rbuff);
+ 	kfree(ax->xbuff);
+ 
++	ax->tty = NULL;
++
+ 	free_netdev(ax->dev);
+ }
+ 

commit 48b71a9e66c2eab60564b1b1c85f4928ed04e406
+Author: Lin Ma 
+Date:   Tue Nov 16 23:27:32 2021 +0800
+
+    NFC: add NCI_UNREG flag to eliminate the race
+    
+    There are two sites that calls queue_work() after the
+    destroy_workqueue() and lead to possible UAF.
+    
+    The first site is nci_send_cmd(), which can happen after the
+    nci_close_device as below
+    
+    nfcmrvl_nci_unregister_dev   |  nfc_genl_dev_up
+      nci_close_device           |
+        flush_workqueue          |
+        del_timer_sync           |
+      nci_unregister_device      |    nfc_get_device
+        destroy_workqueue        |    nfc_dev_up
+        nfc_unregister_device    |      nci_dev_up
+          device_del             |        nci_open_device
+                                 |          __nci_request
+                                 |            nci_send_cmd
+                                 |              queue_work !!!
+    
+    Another site is nci_cmd_timer, awaked by the nci_cmd_work from the
+    nci_send_cmd.
+    
+      ...                        |  ...
+      nci_unregister_device      |  queue_work
+        destroy_workqueue        |
+        nfc_unregister_device    |  ...
+          device_del             |  nci_cmd_work
+                                 |  mod_timer
+                                 |  ...
+                                 |  nci_cmd_timer
+                                 |    queue_work !!!
+    
+    For the above two UAF, the root cause is that the nfc_dev_up can race
+    between the nci_unregister_device routine. Therefore, this patch
+    introduce NCI_UNREG flag to easily eliminate the possible race. In
+    addition, the mutex_lock in nci_close_device can act as a barrier.
+    
+    Signed-off-by: Lin Ma 
+    Fixes: 6a2968aaf50c ("NFC: basic NCI protocol implementation")
+    Reviewed-by: Jakub Kicinski 
+    Reviewed-by: Krzysztof Kozlowski 
+    Link: https://lore.kernel.org/r/20211116152732.19238-1-linma@zju.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
+index a964daedc17b..ea8595651c38 100644
+--- a/include/net/nfc/nci_core.h
++++ b/include/net/nfc/nci_core.h
+@@ -30,6 +30,7 @@ enum nci_flag {
+ 	NCI_UP,
+ 	NCI_DATA_EXCHANGE,
+ 	NCI_DATA_EXCHANGE_TO,
++	NCI_UNREG,
+ };
+ 
+ /* NCI device states */
+diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
+index 1dd0269c1a72..d2537383a3e8 100644
+--- a/net/nfc/nci/core.c
++++ b/net/nfc/nci/core.c
+@@ -476,6 +476,11 @@ static int nci_open_device(struct nci_dev *ndev)
+ 
+ 	mutex_lock(&ndev->req_lock);
+ 
++	if (test_bit(NCI_UNREG, &ndev->flags)) {
++		rc = -ENODEV;
++		goto done;
++	}
++
+ 	if (test_bit(NCI_UP, &ndev->flags)) {
+ 		rc = -EALREADY;
+ 		goto done;
+@@ -548,6 +553,10 @@ static int nci_open_device(struct nci_dev *ndev)
+ static int nci_close_device(struct nci_dev *ndev)
+ {
+ 	nci_req_cancel(ndev, ENODEV);
++
++	/* This mutex needs to be held as a barrier for
++	 * caller nci_unregister_device
++	 */
+ 	mutex_lock(&ndev->req_lock);
+ 
+ 	if (!test_and_clear_bit(NCI_UP, &ndev->flags)) {
+@@ -585,8 +594,8 @@ static int nci_close_device(struct nci_dev *ndev)
+ 
+ 	del_timer_sync(&ndev->cmd_timer);
+ 
+-	/* Clear flags */
+-	ndev->flags = 0;
++	/* Clear flags except NCI_UNREG */
++	ndev->flags &= BIT(NCI_UNREG);
+ 
+ 	mutex_unlock(&ndev->req_lock);
+ 
+@@ -1269,6 +1278,12 @@ void nci_unregister_device(struct nci_dev *ndev)
+ {
+ 	struct nci_conn_info *conn_info, *n;
+ 
++	/* This set_bit is not protected with specialized barrier,
++	 * However, it is fine because the mutex_lock(&ndev->req_lock);
++	 * in nci_close_device() will help to emit one.
++	 */
++	set_bit(NCI_UNREG, &ndev->flags);
++
+ 	nci_close_device(ndev);
+ 
+ 	destroy_workqueue(ndev->cmd_wq);

commit 3e3b5dfcd16a3e254aab61bd1e8c417dd4503102
+Author: Lin Ma 
+Date:   Tue Nov 16 23:26:52 2021 +0800
+
+    NFC: reorder the logic in nfc_{un,}register_device
+    
+    There is a potential UAF between the unregistration routine and the NFC
+    netlink operations.
+    
+    The race that cause that UAF can be shown as below:
+    
+     (FREE)                      |  (USE)
+    nfcmrvl_nci_unregister_dev   |  nfc_genl_dev_up
+      nci_close_device           |
+      nci_unregister_device      |    nfc_get_device
+        nfc_unregister_device    |    nfc_dev_up
+          rfkill_destory         |
+          device_del             |      rfkill_blocked
+      ...                        |    ...
+    
+    The root cause for this race is concluded below:
+    1. The rfkill_blocked (USE) in nfc_dev_up is supposed to be placed after
+    the device_is_registered check.
+    2. Since the netlink operations are possible just after the device_add
+    in nfc_register_device, the nfc_dev_up() can happen anywhere during the
+    rfkill creation process, which leads to data race.
+    
+    This patch reorder these actions to permit
+    1. Once device_del is finished, the nfc_dev_up cannot dereference the
+    rfkill object.
+    2. The rfkill_register need to be placed after the device_add of nfc_dev
+    because the parent device need to be created first. So this patch keeps
+    the order but inject device_lock to prevent the data race.
+    
+    Signed-off-by: Lin Ma 
+    Fixes: be055b2f89b5 ("NFC: RFKILL support")
+    Reviewed-by: Jakub Kicinski 
+    Reviewed-by: Krzysztof Kozlowski 
+    Link: https://lore.kernel.org/r/20211116152652.19217-1-linma@zju.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/net/nfc/core.c b/net/nfc/core.c
+index 3c645c1d99c9..dc7a2404efdf 100644
+--- a/net/nfc/core.c
++++ b/net/nfc/core.c
+@@ -94,13 +94,13 @@ int nfc_dev_up(struct nfc_dev *dev)
+ 
+ 	device_lock(&dev->dev);
+ 
+-	if (dev->rfkill && rfkill_blocked(dev->rfkill)) {
+-		rc = -ERFKILL;
++	if (!device_is_registered(&dev->dev)) {
++		rc = -ENODEV;
+ 		goto error;
+ 	}
+ 
+-	if (!device_is_registered(&dev->dev)) {
+-		rc = -ENODEV;
++	if (dev->rfkill && rfkill_blocked(dev->rfkill)) {
++		rc = -ERFKILL;
+ 		goto error;
+ 	}
+ 
+@@ -1125,11 +1125,7 @@ int nfc_register_device(struct nfc_dev *dev)
+ 	if (rc)
+ 		pr_err("Could not register llcp device\n");
+ 
+-	rc = nfc_genl_device_added(dev);
+-	if (rc)
+-		pr_debug("The userspace won't be notified that the device %s was added\n",
+-			 dev_name(&dev->dev));
+-
++	device_lock(&dev->dev);
+ 	dev->rfkill = rfkill_alloc(dev_name(&dev->dev), &dev->dev,
+ 				   RFKILL_TYPE_NFC, &nfc_rfkill_ops, dev);
+ 	if (dev->rfkill) {
+@@ -1138,6 +1134,12 @@ int nfc_register_device(struct nfc_dev *dev)
+ 			dev->rfkill = NULL;
+ 		}
+ 	}
++	device_unlock(&dev->dev);
++
++	rc = nfc_genl_device_added(dev);
++	if (rc)
++		pr_debug("The userspace won't be notified that the device %s was added\n",
++			 dev_name(&dev->dev));
+ 
+ 	return 0;
+ }
+@@ -1154,10 +1156,17 @@ void nfc_unregister_device(struct nfc_dev *dev)
+ 
+ 	pr_debug("dev_name=%s\n", dev_name(&dev->dev));
+ 
++	rc = nfc_genl_device_removed(dev);
++	if (rc)
++		pr_debug("The userspace won't be notified that the device %s "
++			 "was removed\n", dev_name(&dev->dev));
++
++	device_lock(&dev->dev);
+ 	if (dev->rfkill) {
+ 		rfkill_unregister(dev->rfkill);
+ 		rfkill_destroy(dev->rfkill);
+ 	}
++	device_unlock(&dev->dev);
+ 
+ 	if (dev->ops->check_presence) {
+ 		device_lock(&dev->dev);
+@@ -1167,11 +1176,6 @@ void nfc_unregister_device(struct nfc_dev *dev)
+ 		cancel_work_sync(&dev->check_pres_work);
+ 	}
+ 
+-	rc = nfc_genl_device_removed(dev);
+-	if (rc)
+-		pr_debug("The userspace won't be notified that the device %s "
+-			 "was removed\n", dev_name(&dev->dev));
+-
+ 	nfc_llcp_unregister_device(dev);
+ 
+ 	mutex_lock(&nfc_devlist_mutex);

commit 86cdf8e38792545161dbe3350a7eced558ba4d15
+Author: Lin Ma 
+Date:   Mon Nov 15 22:56:00 2021 +0800
+
+    NFC: reorganize the functions in nci_request
+    
+    There is a possible data race as shown below:
+    
+    thread-A in nci_request()       | thread-B in nci_close_device()
+                                    | mutex_lock(&ndev->req_lock);
+    test_bit(NCI_UP, &ndev->flags); |
+    ...                             | test_and_clear_bit(NCI_UP, &ndev->flags)
+    mutex_lock(&ndev->req_lock);    |
+                                    |
+    
+    This race will allow __nci_request() to be awaked while the device is
+    getting removed.
+    
+    Similar to commit e2cb6b891ad2 ("bluetooth: eliminate the potential race
+    condition when removing the HCI controller"). this patch alters the
+    function sequence in nci_request() to prevent the data races between the
+    nci_close_device().
+    
+    Signed-off-by: Lin Ma 
+    Fixes: 6a2968aaf50c ("NFC: basic NCI protocol implementation")
+    Link: https://lore.kernel.org/r/20211115145600.8320-1-linma@zju.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
+index 6fd873aa86be..1dd0269c1a72 100644
+--- a/net/nfc/nci/core.c
++++ b/net/nfc/nci/core.c
+@@ -144,12 +144,15 @@ inline int nci_request(struct nci_dev *ndev,
+ {
+ 	int rc;
+ 
+-	if (!test_bit(NCI_UP, &ndev->flags))
+-		return -ENETDOWN;
+-
+ 	/* Serialize all requests */
+ 	mutex_lock(&ndev->req_lock);
+-	rc = __nci_request(ndev, req, opt, timeout);
++	/* check the state after obtaing the lock against any races
++	 * from nci_close_device when the device gets removed.
++	 */
++	if (test_bit(NCI_UP, &ndev->flags))
++		rc = __nci_request(ndev, req, opt, timeout);
++	else
++		rc = -ENETDOWN;
+ 	mutex_unlock(&ndev->req_lock);
+ 
+ 	return rc;

commit 81b1d548d00bcd028303c4f3150fa753b9b8aa71
+Author: Lin Ma 
+Date:   Thu Nov 11 22:14:02 2021 +0800
+
+    hamradio: remove needs_free_netdev to avoid UAF
+    
+    The former patch "defer 6pack kfree after unregister_netdev" reorders
+    the kfree of two buffer after the unregister_netdev to prevent the race
+    condition. It also adds free_netdev() function in sixpack_close(), which
+    is a direct copy from the similar code in mkiss_close().
+    
+    However, in sixpack driver, the flag needs_free_netdev is set to true in
+    sp_setup(), hence the unregister_netdev() will free the netdev
+    automatically. Therefore, as the sp is netdev_priv, use-after-free
+    occurs.
+    
+    This patch removes the needs_free_netdev = true and just let the
+    free_netdev to finish this deallocation task.
+    
+    Fixes: 0b9111922b1f ("hamradio: defer 6pack kfree after unregister_netdev")
+    Signed-off-by: Lin Ma 
+    Link: https://lore.kernel.org/r/20211111141402.7551-1-linma@zju.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
+index bfdf89e54752..8a19a06b505d 100644
+--- a/drivers/net/hamradio/6pack.c
++++ b/drivers/net/hamradio/6pack.c
+@@ -306,7 +306,6 @@ static void sp_setup(struct net_device *dev)
+ {
+ 	/* Finish setting up the DEVICE info. */
+ 	dev->netdev_ops		= &sp_netdev_ops;
+-	dev->needs_free_netdev	= true;
+ 	dev->mtu		= SIXP_MTU;
+ 	dev->hard_header_len	= AX25_MAX_HEADER_LEN;
+ 	dev->header_ops 	= &ax25_header_ops;

commit 0b9111922b1f399aba6ed1e1b8f2079c3da1aed8
+Author: Lin Ma 
+Date:   Mon Nov 8 18:37:59 2021 +0800
+
+    hamradio: defer 6pack kfree after unregister_netdev
+    
+    There is a possible race condition (use-after-free) like below
+    
+     (USE)                       |  (FREE)
+      dev_queue_xmit             |
+       __dev_queue_xmit          |
+        __dev_xmit_skb           |
+         sch_direct_xmit         | ...
+          xmit_one               |
+           netdev_start_xmit     | tty_ldisc_kill
+            __netdev_start_xmit  |  6pack_close
+             sp_xmit             |   kfree
+              sp_encaps          |
+                                 |
+    
+    According to the patch "defer ax25 kfree after unregister_netdev", this
+    patch reorder the kfree after the unregister_netdev to avoid the possible
+    UAF as the unregister_netdev() is well synchronized and won't return if
+    there is a running routine.
+    
+    Signed-off-by: Lin Ma 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
+index f4e8793e995d..fb0a3825edd0 100644
+--- a/drivers/net/hamradio/6pack.c
++++ b/drivers/net/hamradio/6pack.c
+@@ -672,11 +672,13 @@ static void sixpack_close(struct tty_struct *tty)
+ 	del_timer_sync(&sp->tx_t);
+ 	del_timer_sync(&sp->resync_t);
+ 
+-	/* Free all 6pack frame buffers. */
++	unregister_netdev(sp->dev);
++
++	/* Free all 6pack frame buffers after unreg. */
+ 	kfree(sp->rbuff);
+ 	kfree(sp->xbuff);
+ 
+-	unregister_netdev(sp->dev);
++	free_netdev(sp->dev);
+ }
+ 
+ /* Perform I/O control on an active 6pack channel. */

commit 3e0588c291d6ce225f2b891753ca41d45ba42469
+Author: Lin Ma 
+Date:   Mon Nov 8 18:37:21 2021 +0800
+
+    hamradio: defer ax25 kfree after unregister_netdev
+    
+    There is a possible race condition (use-after-free) like below
+    
+     (USE)                       |  (FREE)
+    ax25_sendmsg                 |
+     ax25_queue_xmit             |
+      dev_queue_xmit             |
+       __dev_queue_xmit          |
+        __dev_xmit_skb           |
+         sch_direct_xmit         | ...
+          xmit_one               |
+           netdev_start_xmit     | tty_ldisc_kill
+            __netdev_start_xmit  |  mkiss_close
+             ax_xmit             |   kfree
+              ax_encaps          |
+                                 |
+    
+    Even though there are two synchronization primitives before the kfree:
+    1. wait_for_completion(&ax->dead). This can prevent the race with
+    routines from mkiss_ioctl. However, it cannot stop the routine coming
+    from upper layer, i.e., the ax25_sendmsg.
+    
+    2. netif_stop_queue(ax->dev). It seems that this line of code aims to
+    halt the transmit queue but it fails to stop the routine that already
+    being xmit.
+    
+    This patch reorder the kfree after the unregister_netdev to avoid the
+    possible UAF as the unregister_netdev() is well synchronized and won't
+    return if there is a running routine.
+    
+    Signed-off-by: Lin Ma 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
+index 867252a0247b..e2b332b54f06 100644
+--- a/drivers/net/hamradio/mkiss.c
++++ b/drivers/net/hamradio/mkiss.c
+@@ -792,13 +792,14 @@ static void mkiss_close(struct tty_struct *tty)
+ 	 */
+ 	netif_stop_queue(ax->dev);
+ 
+-	/* Free all AX25 frame buffers. */
+-	kfree(ax->rbuff);
+-	kfree(ax->xbuff);
+-
+ 	ax->tty = NULL;
+ 
+ 	unregister_netdev(ax->dev);
++
++	/* Free all AX25 frame buffers after unreg. */
++	kfree(ax->rbuff);
++	kfree(ax->xbuff);
++
+ 	free_netdev(ax->dev);
+ }
+ 

commit aedddb4e45b34426cfbfa84454b6f203712733c5
+Author: Lin Ma 
+Date:   Tue Nov 2 16:10:21 2021 +0800
+
+    NFC: add necessary privilege flags in netlink layer
+    
+    The CAP_NET_ADMIN checks are needed to prevent attackers faking a
+    device under NCIUARTSETDRIVER and exploit privileged commands.
+    
+    This patch add GENL_ADMIN_PERM flags in genl_ops to fulfill the check.
+    Except for commands like NFC_CMD_GET_DEVICE, NFC_CMD_GET_TARGET,
+    NFC_CMD_LLC_GET_PARAMS, and NFC_CMD_GET_SE, which are mainly information-
+    read operations.
+    
+    Signed-off-by: Lin Ma 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
+index 49089c50872e..334f63c9529e 100644
+--- a/net/nfc/netlink.c
++++ b/net/nfc/netlink.c
+@@ -1664,31 +1664,37 @@ static const struct genl_ops nfc_genl_ops[] = {
+ 		.cmd = NFC_CMD_DEV_UP,
+ 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+ 		.doit = nfc_genl_dev_up,
++		.flags = GENL_ADMIN_PERM,
+ 	},
+ 	{
+ 		.cmd = NFC_CMD_DEV_DOWN,
+ 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+ 		.doit = nfc_genl_dev_down,
++		.flags = GENL_ADMIN_PERM,
+ 	},
+ 	{
+ 		.cmd = NFC_CMD_START_POLL,
+ 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+ 		.doit = nfc_genl_start_poll,
++		.flags = GENL_ADMIN_PERM,
+ 	},
+ 	{
+ 		.cmd = NFC_CMD_STOP_POLL,
+ 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+ 		.doit = nfc_genl_stop_poll,
++		.flags = GENL_ADMIN_PERM,
+ 	},
+ 	{
+ 		.cmd = NFC_CMD_DEP_LINK_UP,
+ 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+ 		.doit = nfc_genl_dep_link_up,
++		.flags = GENL_ADMIN_PERM,
+ 	},
+ 	{
+ 		.cmd = NFC_CMD_DEP_LINK_DOWN,
+ 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+ 		.doit = nfc_genl_dep_link_down,
++		.flags = GENL_ADMIN_PERM,
+ 	},
+ 	{
+ 		.cmd = NFC_CMD_GET_TARGET,
+@@ -1706,26 +1712,31 @@ static const struct genl_ops nfc_genl_ops[] = {
+ 		.cmd = NFC_CMD_LLC_SET_PARAMS,
+ 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+ 		.doit = nfc_genl_llc_set_params,
++		.flags = GENL_ADMIN_PERM,
+ 	},
+ 	{
+ 		.cmd = NFC_CMD_LLC_SDREQ,
+ 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+ 		.doit = nfc_genl_llc_sdreq,
++		.flags = GENL_ADMIN_PERM,
+ 	},
+ 	{
+ 		.cmd = NFC_CMD_FW_DOWNLOAD,
+ 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+ 		.doit = nfc_genl_fw_download,
++		.flags = GENL_ADMIN_PERM,
+ 	},
+ 	{
+ 		.cmd = NFC_CMD_ENABLE_SE,
+ 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+ 		.doit = nfc_genl_enable_se,
++		.flags = GENL_ADMIN_PERM,
+ 	},
+ 	{
+ 		.cmd = NFC_CMD_DISABLE_SE,
+ 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+ 		.doit = nfc_genl_disable_se,
++		.flags = GENL_ADMIN_PERM,
+ 	},
+ 	{
+ 		.cmd = NFC_CMD_GET_SE,
+@@ -1737,21 +1748,25 @@ static const struct genl_ops nfc_genl_ops[] = {
+ 		.cmd = NFC_CMD_SE_IO,
+ 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+ 		.doit = nfc_genl_se_io,
++		.flags = GENL_ADMIN_PERM,
+ 	},
+ 	{
+ 		.cmd = NFC_CMD_ACTIVATE_TARGET,
+ 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+ 		.doit = nfc_genl_activate_target,
++		.flags = GENL_ADMIN_PERM,
+ 	},
+ 	{
+ 		.cmd = NFC_CMD_VENDOR,
+ 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+ 		.doit = nfc_genl_vendor_cmd,
++		.flags = GENL_ADMIN_PERM,
+ 	},
+ 	{
+ 		.cmd = NFC_CMD_DEACTIVATE_TARGET,
+ 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+ 		.doit = nfc_genl_deactivate_target,
++		.flags = GENL_ADMIN_PERM,
+ 	},
+ };
+ 

commit 1b1499a817c90fd1ce9453a2c98d2a01cca0e775
+Author: Lin Ma 
+Date:   Thu Oct 7 19:44:30 2021 +0200
+
+    nfc: nci: fix the UAF of rf_conn_info object
+    
+    The nci_core_conn_close_rsp_packet() function will release the conn_info
+    with given conn_id. However, it needs to set the rf_conn_info to NULL to
+    prevent other routines like nci_rf_intf_activated_ntf_packet() to trigger
+    the UAF.
+    
+    Reviewed-by: Krzysztof Kozlowski 
+    Signed-off-by: Lin Ma 
+    Signed-off-by: Krzysztof Kozlowski 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c
+index a2e72c003805..b911ab78bed9 100644
+--- a/net/nfc/nci/rsp.c
++++ b/net/nfc/nci/rsp.c
+@@ -334,6 +334,8 @@ static void nci_core_conn_close_rsp_packet(struct nci_dev *ndev,
+ 							 ndev->cur_conn_id);
+ 		if (conn_info) {
+ 			list_del(&conn_info->list);
++			if (conn_info == ndev->rf_conn_info)
++				ndev->rf_conn_info = NULL;
+ 			devm_kfree(&ndev->nfc_dev->dev, conn_info);
+ 		}
+ 	}

commit 3e5f2d90c28f9454e421108554707620bc23269d
+Author: Dinghao Liu 
+Date:   Wed Sep 22 21:49:45 2021 +0800
+
+    Bluetooth: btmtkuart: fix a memleak in mtk_hci_wmt_sync
+    
+    bdev->evt_skb will get freed in the normal path and one error path
+    of mtk_hci_wmt_sync, while the other error paths do not free it,
+    which may cause a memleak. This bug is suggested by a static analysis
+    tool, please advise.
+    
+    Fixes: e0b67035a90b ("Bluetooth: mediatek: update the common setup between MT7622 and other devices")
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Marcel Holtmann 
+
+diff --git a/drivers/bluetooth/btmtkuart.c b/drivers/bluetooth/btmtkuart.c
+index e9d91d7c0db4..9ba22b13b4fa 100644
+--- a/drivers/bluetooth/btmtkuart.c
++++ b/drivers/bluetooth/btmtkuart.c
+@@ -158,8 +158,10 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
+ 	int err;
+ 
+ 	hlen = sizeof(*hdr) + wmt_params->dlen;
+-	if (hlen > 255)
+-		return -EINVAL;
++	if (hlen > 255) {
++		err = -EINVAL;
++		goto err_free_skb;
++	}
+ 
+ 	hdr = (struct mtk_wmt_hdr *)&wc;
+ 	hdr->dir = 1;
+@@ -173,7 +175,7 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
+ 	err = __hci_cmd_send(hdev, 0xfc6f, hlen, &wc);
+ 	if (err < 0) {
+ 		clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
+-		return err;
++		goto err_free_skb;
+ 	}
+ 
+ 	/* The vendor specific WMT commands are all answered by a vendor
+@@ -190,13 +192,14 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
+ 	if (err == -EINTR) {
+ 		bt_dev_err(hdev, "Execution of wmt command interrupted");
+ 		clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
+-		return err;
++		goto err_free_skb;
+ 	}
+ 
+ 	if (err) {
+ 		bt_dev_err(hdev, "Execution of wmt command timed out");
+ 		clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
+-		return -ETIMEDOUT;
++		err = -ETIMEDOUT;
++		goto err_free_skb;
+ 	}
+ 
+ 	/* Parse and handle the return WMT event */

commit 9ddbc2a00d7f63fa9748f4278643193dac985f2d
+Author: Dinghao Liu 
+Date:   Fri Sep 3 15:35:43 2021 +0800
+
+    qlcnic: Remove redundant unlock in qlcnic_pinit_from_rom
+    
+    Previous commit 68233c583ab4 removes the qlcnic_rom_lock()
+    in qlcnic_pinit_from_rom(), but remains its corresponding
+    unlock function, which is odd. I'm not very sure whether the
+    lock is missing, or the unlock is redundant. This bug is
+    suggested by a static analysis tool, please advise.
+    
+    Fixes: 68233c583ab4 ("qlcnic: updated reset sequence")
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
+index 3d61a767a8a3..09f20c794754 100644
+--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
+@@ -437,7 +437,6 @@ int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter)
+ 	QLCWR32(adapter, QLCNIC_CRB_PEG_NET_4 + 0x3c, 1);
+ 	msleep(20);
+ 
+-	qlcnic_rom_unlock(adapter);
+ 	/* big hammer don't reset CAM block on reset */
+ 	QLCWR32(adapter, QLCNIC_ROMUSB_GLB_SW_RESET, 0xfeffffff);
+ 

commit a036ad088306a88de87e973981f2b9224e466c3f
+Author: Dinghao Liu 
+Date:   Mon Aug 16 16:55:31 2021 +0800
+
+    RDMA/bnxt_re: Remove unpaired rtnl unlock in bnxt_re_dev_init()
+    
+    The fixed commit removes all rtnl_lock() and rtnl_unlock() calls in
+    function bnxt_re_dev_init(), but forgets to remove a rtnl_unlock() in the
+    error handling path of bnxt_re_register_netdev(), which may cause a
+    deadlock. This bug is suggested by a static analysis tool.
+    
+    Fixes: c2b777a95923 ("RDMA/bnxt_re: Refactor device add/remove functionalities")
+    Link: https://lore.kernel.org/r/20210816085531.12167-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Dinghao Liu 
+    Acked-by: Selvin Xavier 
+    Reviewed-by: Jason Gunthorpe 
+    Signed-off-by: Jason Gunthorpe 
+
+diff --git a/drivers/infiniband/hw/bnxt_re/main.c b/drivers/infiniband/hw/bnxt_re/main.c
+index a8688a92c760..4678bd6ec7d6 100644
+--- a/drivers/infiniband/hw/bnxt_re/main.c
++++ b/drivers/infiniband/hw/bnxt_re/main.c
+@@ -1397,7 +1397,6 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 wqe_mode)
+ 	memset(&rattr, 0, sizeof(rattr));
+ 	rc = bnxt_re_register_netdev(rdev);
+ 	if (rc) {
+-		rtnl_unlock();
+ 		ibdev_err(&rdev->ibdev,
+ 			  "Failed to register with netedev: %#x\n", rc);
+ 		return -EINVAL;

commit 0a298d133893c72c96e2156ed7cb0f0c4a306a3e
+Author: Dinghao Liu 
+Date:   Mon Aug 16 21:14:04 2021 +0800
+
+    net: qlcnic: add missed unlock in qlcnic_83xx_flash_read32
+    
+    qlcnic_83xx_unlock_flash() is called on all paths after we call
+    qlcnic_83xx_lock_flash(), except for one error path on failure
+    of QLCRD32(), which may cause a deadlock. This bug is suggested
+    by a static analysis tool, please advise.
+    
+    Fixes: 81d0aeb0a4fff ("qlcnic: flash template based firmware reset recovery")
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20210816131405.24024-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+index d8882d0b6b49..d51bac7ba5af 100644
+--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+@@ -3156,8 +3156,10 @@ int qlcnic_83xx_flash_read32(struct qlcnic_adapter *adapter, u32 flash_addr,
+ 
+ 		indirect_addr = QLC_83XX_FLASH_DIRECT_DATA(addr);
+ 		ret = QLCRD32(adapter, indirect_addr, &err);
+-		if (err == -EIO)
++		if (err == -EIO) {
++			qlcnic_83xx_unlock_flash(adapter);
+ 			return err;
++		}
+ 
+ 		word = ret;
+ 		*(u32 *)p_data  = word;

commit 1e29cd9983eba1b596bc07f94d81d728007f8a25
+Author: Dinghao Liu 
+Date:   Thu Apr 8 15:24:02 2021 +0800
+
+    PCI: rcar: Fix runtime PM imbalance in rcar_pcie_ep_probe()
+    
+    pm_runtime_get_sync() will increase the runtime PM counter
+    even it returns an error. Thus a pairing decrement is needed
+    to prevent refcount leak. Fix this by replacing this API with
+    pm_runtime_resume_and_get(), which will not change the runtime
+    PM counter on error.
+    
+    Link: https://lore.kernel.org/r/20210408072402.15069-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Lorenzo Pieralisi 
+    Reviewed-by: Geert Uytterhoeven 
+
+diff --git a/drivers/pci/controller/pcie-rcar-ep.c b/drivers/pci/controller/pcie-rcar-ep.c
+index b4a288e24aaf..c91d85b15129 100644
+--- a/drivers/pci/controller/pcie-rcar-ep.c
++++ b/drivers/pci/controller/pcie-rcar-ep.c
+@@ -492,9 +492,9 @@ static int rcar_pcie_ep_probe(struct platform_device *pdev)
+ 	pcie->dev = dev;
+ 
+ 	pm_runtime_enable(dev);
+-	err = pm_runtime_get_sync(dev);
++	err = pm_runtime_resume_and_get(dev);
+ 	if (err < 0) {
+-		dev_err(dev, "pm_runtime_get_sync failed\n");
++		dev_err(dev, "pm_runtime_resume_and_get failed\n");
+ 		goto err_pm_disable;
+ 	}
+ 

commit 672fe1cf145ab9978c62eb827d6a16aa6b63994b
+Author: Dinghao Liu 
+Date:   Thu Apr 8 10:18:43 2021 +0200
+
+    media: atomisp: Fix runtime PM imbalance in atomisp_pci_probe
+    
+    When hmm_pool_register() fails, a pairing PM usage counter
+    increment is needed to keep the counter balanced. It's the
+    same for the following error paths.
+    
+    Link: https://lore.kernel.org/linux-media/20210408081850.24278-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Dinghao Liu 
+    Acked-by: Andy Shevchenko 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
+index 948769ca6539..af0d83eaa68c 100644
+--- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
++++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
+@@ -1815,6 +1815,7 @@ static int atomisp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
+ 	hmm_cleanup();
+ 	hmm_pool_unregister(HMM_POOL_TYPE_RESERVED);
+ hmm_pool_fail:
++	pm_runtime_get_noresume(&pdev->dev);
+ 	destroy_workqueue(isp->wdt_work_queue);
+ wdt_work_queue_fail:
+ 	atomisp_acc_cleanup(isp);

commit 9c04cfcd4aad232e36306cdc5c74cd9fc9148a7e
+Author: Dinghao Liu 
+Date:   Sun Feb 28 19:50:58 2021 +0800
+
+    i40e: Fix error handling in i40e_vsi_open
+    
+    When vsi->type == I40E_VSI_FDIR, we have caught the return value of
+    i40e_vsi_request_irq() but without further handling. Check and execute
+    memory clean on failure just like the other i40e_vsi_request_irq().
+    
+    Fixes: 8a9eb7d3cbcab ("i40e: rework fdir setup and teardown")
+    Signed-off-by: Dinghao Liu 
+    Tested-by: Tony Brelinski 
+    Signed-off-by: Tony Nguyen 
+
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
+index 704e474879c5..526fa0a791ea 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
+@@ -8703,6 +8703,8 @@ int i40e_vsi_open(struct i40e_vsi *vsi)
+ 			 dev_driver_string(&pf->pdev->dev),
+ 			 dev_name(&pf->pdev->dev));
+ 		err = i40e_vsi_request_irq(vsi, int_name);
++		if (err)
++			goto err_setup_rx;
+ 
+ 	} else {
+ 		err = -EINVAL;

commit e305509e678b3a4af2b3cfd410f409f7cdaabb52
+Author: Lin Ma 
+Date:   Sun May 30 21:37:43 2021 +0800
+
+    Bluetooth: use correct lock to prevent UAF of hdev object
+    
+    The hci_sock_dev_event() function will cleanup the hdev object for
+    sockets even if this object may still be in used within the
+    hci_sock_bound_ioctl() function, result in UAF vulnerability.
+    
+    This patch replace the BH context lock to serialize these affairs
+    and prevent the race condition.
+    
+    Signed-off-by: Lin Ma 
+    Signed-off-by: Marcel Holtmann 
+
+diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
+index 251b9128f530..eed0dd066e12 100644
+--- a/net/bluetooth/hci_sock.c
++++ b/net/bluetooth/hci_sock.c
+@@ -762,7 +762,7 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event)
+ 		/* Detach sockets from device */
+ 		read_lock(&hci_sk_list.lock);
+ 		sk_for_each(sk, &hci_sk_list.head) {
+-			bh_lock_sock_nested(sk);
++			lock_sock(sk);
+ 			if (hci_pi(sk)->hdev == hdev) {
+ 				hci_pi(sk)->hdev = NULL;
+ 				sk->sk_err = EPIPE;
+@@ -771,7 +771,7 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event)
+ 
+ 				hci_dev_put(hdev);
+ 			}
+-			bh_unlock_sock(sk);
++			release_sock(sk);
+ 		}
+ 		read_unlock(&hci_sk_list.lock);
+ 	}

commit 6a137caec23aeb9e036cdfd8a46dd8a366460e5d
+Author: Lin Ma 
+Date:   Tue May 25 14:39:02 2021 +0200
+
+    Bluetooth: fix the erroneous flush_work() order
+    
+    In the cleanup routine for failed initialization of HCI device,
+    the flush_work(&hdev->rx_work) need to be finished before the
+    flush_work(&hdev->cmd_work). Otherwise, the hci_rx_work() can
+    possibly invoke new cmd_work and cause a bug, like double free,
+    in late processings.
+    
+    This was assigned CVE-2021-3564.
+    
+    This patch reorder the flush_work() to fix this bug.
+    
+    Cc: Marcel Holtmann 
+    Cc: Johan Hedberg 
+    Cc: Luiz Augusto von Dentz 
+    Cc: "David S. Miller" 
+    Cc: Jakub Kicinski 
+    Cc: linux-bluetooth@vger.kernel.org
+    Cc: netdev@vger.kernel.org
+    Cc: linux-kernel@vger.kernel.org
+    Signed-off-by: Lin Ma 
+    Signed-off-by: Hao Xiong 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+    Signed-off-by: Marcel Holtmann 
+
+diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
+index fd12f1652bdf..7d71d104fdfd 100644
+--- a/net/bluetooth/hci_core.c
++++ b/net/bluetooth/hci_core.c
+@@ -1610,8 +1610,13 @@ static int hci_dev_do_open(struct hci_dev *hdev)
+ 	} else {
+ 		/* Init failed, cleanup */
+ 		flush_work(&hdev->tx_work);
+-		flush_work(&hdev->cmd_work);
++
++		/* Since hci_rx_work() is possible to awake new cmd_work
++		 * it should be flushed first to avoid unexpected call of
++		 * hci_cmd_work()
++		 */
+ 		flush_work(&hdev->rx_work);
++		flush_work(&hdev->cmd_work);
+ 
+ 		skb_queue_purge(&hdev->cmd_q);
+ 		skb_queue_purge(&hdev->rx_q);

commit a20a40a8bbc2cf4b29d7248ea31e974e9103dd7f
+Author: Dinghao Liu 
+Date:   Thu Apr 15 15:33:38 2021 +0800
+
+    clk: renesas: rcar-usb2-clock-sel: Fix error handling in .probe()
+    
+    The error handling paths after pm_runtime_get_sync() have no refcount
+    decrement, which leads to refcount leak.
+    
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20210415073338.22287-1-dinghao.liu@zju.edu.cn
+    [geert: Remove now unused variable priv]
+    Signed-off-by: Geert Uytterhoeven 
+
+diff --git a/drivers/clk/renesas/rcar-usb2-clock-sel.c b/drivers/clk/renesas/rcar-usb2-clock-sel.c
+index 34a85dc95beb..9fb79bd79435 100644
+--- a/drivers/clk/renesas/rcar-usb2-clock-sel.c
++++ b/drivers/clk/renesas/rcar-usb2-clock-sel.c
+@@ -128,10 +128,8 @@ static int rcar_usb2_clock_sel_resume(struct device *dev)
+ static int rcar_usb2_clock_sel_remove(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+-	struct usb2_clock_sel_priv *priv = platform_get_drvdata(pdev);
+ 
+ 	of_clk_del_provider(dev->of_node);
+-	clk_hw_unregister(&priv->hw);
+ 	pm_runtime_put(dev);
+ 	pm_runtime_disable(dev);
+ 
+@@ -164,9 +162,6 @@ static int rcar_usb2_clock_sel_probe(struct platform_device *pdev)
+ 	if (IS_ERR(priv->rsts))
+ 		return PTR_ERR(priv->rsts);
+ 
+-	pm_runtime_enable(dev);
+-	pm_runtime_get_sync(dev);
+-
+ 	clk = devm_clk_get(dev, "usb_extal");
+ 	if (!IS_ERR(clk) && !clk_prepare_enable(clk)) {
+ 		priv->extal = !!clk_get_rate(clk);
+@@ -183,6 +178,8 @@ static int rcar_usb2_clock_sel_probe(struct platform_device *pdev)
+ 		return -ENOENT;
+ 	}
+ 
++	pm_runtime_enable(dev);
++	pm_runtime_get_sync(dev);
+ 	platform_set_drvdata(pdev, priv);
+ 	dev_set_drvdata(dev, priv);
+ 
+@@ -190,11 +187,20 @@ static int rcar_usb2_clock_sel_probe(struct platform_device *pdev)
+ 	init.ops = &usb2_clock_sel_clock_ops;
+ 	priv->hw.init = &init;
+ 
+-	clk = clk_register(NULL, &priv->hw);
+-	if (IS_ERR(clk))
+-		return PTR_ERR(clk);
++	ret = devm_clk_hw_register(NULL, &priv->hw);
++	if (ret)
++		goto pm_put;
++
++	ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &priv->hw);
++	if (ret)
++		goto pm_put;
++
++	return 0;
+ 
+-	return of_clk_add_hw_provider(np, of_clk_hw_simple_get, &priv->hw);
++pm_put:
++	pm_runtime_put(dev);
++	pm_runtime_disable(dev);
++	return ret;
+ }
+ 
+ static const struct dev_pm_ops rcar_usb2_clock_sel_pm_ops = {

commit 07adc0225484fc199e3dc15ec889f75f498c4fca
+Author: Dinghao Liu 
+Date:   Mon Apr 12 13:49:07 2021 +0800
+
+    usb: cdns3: Fix runtime PM imbalance on error
+    
+    When cdns3_gadget_start() fails, a pairing PM usage counter
+    decrement is needed to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20210412054908.7975-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Peter Chen 
+
+diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c
+index 9b1bd417cec0..a8b7b50abf64 100644
+--- a/drivers/usb/cdns3/cdns3-gadget.c
++++ b/drivers/usb/cdns3/cdns3-gadget.c
+@@ -3268,8 +3268,10 @@ static int __cdns3_gadget_init(struct cdns *cdns)
+ 	pm_runtime_get_sync(cdns->dev);
+ 
+ 	ret = cdns3_gadget_start(cdns);
+-	if (ret)
++	if (ret) {
++		pm_runtime_put_sync(cdns->dev);
+ 		return ret;
++	}
+ 
+ 	/*
+ 	 * Because interrupt line can be shared with other components in

commit a2fa9242e89f27696515699fe0f0296bf1ac1815
+Author: Dinghao Liu 
+Date:   Mon Apr 12 13:32:02 2021 +0800
+
+    iio: proximity: pulsedlight: Fix rumtime PM imbalance on error
+    
+    When lidar_write_control() fails, a pairing PM usage counter
+    decrement is needed to keep the counter balanced.
+    
+    Fixes: 4ac4e086fd8c5 ("iio: pulsedlight-lidar-lite: add runtime PM")
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Andy Shevchenko 
+    Link: https://lore.kernel.org/r/20210412053204.4889-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Jonathan Cameron 
+
+diff --git a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
+index c685f10b5ae4..cc206bfa09c7 100644
+--- a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
++++ b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
+@@ -160,6 +160,7 @@ static int lidar_get_measurement(struct lidar_data *data, u16 *reg)
+ 	ret = lidar_write_control(data, LIDAR_REG_CONTROL_ACQUIRE);
+ 	if (ret < 0) {
+ 		dev_err(&client->dev, "cannot send start measurement command");
++		pm_runtime_put_noidle(&client->dev);
+ 		return ret;
+ 	}
+ 

commit 8edb79af88efc6e49e735f9baf61d9f0748b881f
+Author: Dinghao Liu 
+Date:   Wed Apr 7 11:49:27 2021 +0800
+
+    iio: light: gp2ap002: Fix rumtime PM imbalance on error
+    
+    When devm_request_threaded_irq() fails, we should decrease the
+    runtime PM counter to keep the counter balanced. But when
+    iio_device_register() fails, we need not to decrease it because
+    we have already decreased it before.
+    
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Linus Walleij 
+    Fixes: 97d642e23037 ("iio: light: Add a driver for Sharp GP2AP002x00F")
+    Link: https://lore.kernel.org/r/20210407034927.16882-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Jonathan Cameron 
+
+diff --git a/drivers/iio/light/gp2ap002.c b/drivers/iio/light/gp2ap002.c
+index d048ae257c51..f960be7d4001 100644
+--- a/drivers/iio/light/gp2ap002.c
++++ b/drivers/iio/light/gp2ap002.c
+@@ -582,7 +582,7 @@ static int gp2ap002_probe(struct i2c_client *client,
+ 					"gp2ap002", indio_dev);
+ 	if (ret) {
+ 		dev_err(dev, "unable to request IRQ\n");
+-		goto out_disable_vio;
++		goto out_put_pm;
+ 	}
+ 	gp2ap002->irq = client->irq;
+ 
+@@ -612,8 +612,9 @@ static int gp2ap002_probe(struct i2c_client *client,
+ 
+ 	return 0;
+ 
+-out_disable_pm:
++out_put_pm:
+ 	pm_runtime_put_noidle(dev);
++out_disable_pm:
+ 	pm_runtime_disable(dev);
+ out_disable_vio:
+ 	regulator_disable(gp2ap002->vio);

commit e2cb6b891ad2b8caa9131e3be70f45243df82a80
+Author: Lin Ma 
+Date:   Mon Apr 12 19:17:57 2021 +0800
+
+    bluetooth: eliminate the potential race condition when removing the HCI controller
+    
+    There is a possible race condition vulnerability between issuing a HCI
+    command and removing the cont.  Specifically, functions hci_req_sync()
+    and hci_dev_do_close() can race each other like below:
+    
+    thread-A in hci_req_sync()      |   thread-B in hci_dev_do_close()
+                                    |   hci_req_sync_lock(hdev);
+    test_bit(HCI_UP, &hdev->flags); |
+    ...                             |   test_and_clear_bit(HCI_UP, &hdev->flags)
+    hci_req_sync_lock(hdev);        |
+                                    |
+    In this commit we alter the sequence in function hci_req_sync(). Hence,
+    the thread-A cannot issue th.
+    
+    Signed-off-by: Lin Ma 
+    Cc: Marcel Holtmann 
+    Fixes: 7c6a329e4447 ("[Bluetooth] Fix regression from using default link policy")
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
+index e55976db4403..805ce546b813 100644
+--- a/net/bluetooth/hci_request.c
++++ b/net/bluetooth/hci_request.c
+@@ -272,12 +272,16 @@ int hci_req_sync(struct hci_dev *hdev, int (*req)(struct hci_request *req,
+ {
+ 	int ret;
+ 
+-	if (!test_bit(HCI_UP, &hdev->flags))
+-		return -ENETDOWN;
+-
+ 	/* Serialize all requests */
+ 	hci_req_sync_lock(hdev);
+-	ret = __hci_req_sync(hdev, req, opt, timeout, hci_status);
++	/* check the state after obtaing the lock to protect the HCI_UP
++	 * against any races from hci_dev_do_close when the controller
++	 * gets removed.
++	 */
++	if (test_bit(HCI_UP, &hdev->flags))
++		ret = __hci_req_sync(hdev, req, opt, timeout, hci_status);
++	else
++		ret = -ENETDOWN;
+ 	hci_req_sync_unlock(hdev);
+ 
+ 	return ret;

commit 58eaa7b2d07d3c25e1068b0bf42ca7e7464f4bca
+Author: Dinghao Liu 
+Date:   Thu Apr 15 15:46:44 2021 +0800
+
+    spi: spi-zynqmp-gqspi: Fix runtime PM imbalance in zynqmp_qspi_probe
+    
+    There is a PM usage counter decrement after zynqmp_qspi_init_hw()
+    without any refcount increment, which leads to refcount leak.Add
+    a refcount increment to balance the refcount. Also set
+    auto_runtime_pm to resume suspended spi controller.
+    
+    Fixes: 9e3a000362aec ("spi: zynqmp: Add pm runtime support")
+    Signed-off-by: Dinghao Liu 
+    Tested-by: Quanyang Wang 
+    Link: https://lore.kernel.org/r/20210415074644.24646-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Mark Brown 
+
+diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c
+index 408e348382c5..32e53f379e9b 100644
+--- a/drivers/spi/spi-zynqmp-gqspi.c
++++ b/drivers/spi/spi-zynqmp-gqspi.c
+@@ -1163,11 +1163,16 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
+ 	pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
+ 	pm_runtime_set_active(&pdev->dev);
+ 	pm_runtime_enable(&pdev->dev);
++
++	ret = pm_runtime_get_sync(&pdev->dev);
++	if (ret < 0) {
++		dev_err(&pdev->dev, "Failed to pm_runtime_get_sync: %d\n", ret);
++		goto clk_dis_all;
++	}
++
+ 	/* QSPI controller initializations */
+ 	zynqmp_qspi_init_hw(xqspi);
+ 
+-	pm_runtime_mark_last_busy(&pdev->dev);
+-	pm_runtime_put_autosuspend(&pdev->dev);
+ 	xqspi->irq = platform_get_irq(pdev, 0);
+ 	if (xqspi->irq <= 0) {
+ 		ret = -ENXIO;
+@@ -1190,6 +1195,7 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
+ 	ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_RX_DUAL | SPI_RX_QUAD |
+ 			    SPI_TX_DUAL | SPI_TX_QUAD;
+ 	ctlr->dev.of_node = np;
++	ctlr->auto_runtime_pm = true;
+ 
+ 	ret = devm_spi_register_controller(&pdev->dev, ctlr);
+ 	if (ret) {
+@@ -1197,9 +1203,13 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
+ 		goto clk_dis_all;
+ 	}
+ 
++	pm_runtime_mark_last_busy(&pdev->dev);
++	pm_runtime_put_autosuspend(&pdev->dev);
++
+ 	return 0;
+ 
+ clk_dis_all:
++	pm_runtime_put_sync(&pdev->dev);
+ 	pm_runtime_set_suspended(&pdev->dev);
+ 	pm_runtime_disable(&pdev->dev);
+ 	clk_disable_unprepare(xqspi->refclk);

commit fe6df2b48043bbe1e852b2320501d3b169363c35
+Author: Dinghao Liu 
+Date:   Wed Apr 7 13:11:49 2021 +0800
+
+    mfd: arizona: Fix rumtime PM imbalance on error
+    
+    pm_runtime_get_sync() will increase the rumtime PM counter
+    even it returns an error. Thus a pairing decrement is needed
+    to prevent refcount leak. Fix this by replacing this API with
+    pm_runtime_resume_and_get(), which will not change the runtime
+    PM counter on error.
+    
+    Signed-off-by: Dinghao Liu 
+    Acked-by: Charles Keepax 
+    Signed-off-by: Lee Jones 
+
+diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c
+index 077d9ab112b7..d919ae9691e2 100644
+--- a/drivers/mfd/arizona-irq.c
++++ b/drivers/mfd/arizona-irq.c
+@@ -100,7 +100,7 @@ static irqreturn_t arizona_irq_thread(int irq, void *data)
+ 	unsigned int val;
+ 	int ret;
+ 
+-	ret = pm_runtime_get_sync(arizona->dev);
++	ret = pm_runtime_resume_and_get(arizona->dev);
+ 	if (ret < 0) {
+ 		dev_err(arizona->dev, "Failed to resume device: %d\n", ret);
+ 		return IRQ_NONE;

commit 917a3200b9f467a154999c7572af345f2470aaf4
+Author: Dinghao Liu 
+Date:   Fri Apr 9 16:28:05 2021 +0800
+
+    dmaengine: tegra20: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() will increase the runtime PM counter
+    even it returns an error. Thus a pairing decrement is needed
+    to prevent refcount leak. Fix this by replacing this API with
+    pm_runtime_resume_and_get(), which will not change the runtime
+    PM counter on error.
+    
+    Signed-off-by: Dinghao Liu 
+    Acked-by: Thierry Reding 
+    Link: https://lore.kernel.org/r/20210409082805.23643-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Vinod Koul 
+
+diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c
+index 71827d9b0aa1..b7260749e8ee 100644
+--- a/drivers/dma/tegra20-apb-dma.c
++++ b/drivers/dma/tegra20-apb-dma.c
+@@ -723,7 +723,7 @@ static void tegra_dma_issue_pending(struct dma_chan *dc)
+ 		goto end;
+ 	}
+ 	if (!tdc->busy) {
+-		err = pm_runtime_get_sync(tdc->tdma->dev);
++		err = pm_runtime_resume_and_get(tdc->tdma->dev);
+ 		if (err < 0) {
+ 			dev_err(tdc2dev(tdc), "Failed to enable DMA\n");
+ 			goto end;
+@@ -818,7 +818,7 @@ static void tegra_dma_synchronize(struct dma_chan *dc)
+ 	struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc);
+ 	int err;
+ 
+-	err = pm_runtime_get_sync(tdc->tdma->dev);
++	err = pm_runtime_resume_and_get(tdc->tdma->dev);
+ 	if (err < 0) {
+ 		dev_err(tdc2dev(tdc), "Failed to synchronize DMA: %d\n", err);
+ 		return;

commit f1995d5e43cf897f63b4d7a7f84a252d891ae820
+Author: Dinghao Liu 
+Date:   Wed Apr 7 07:46:06 2021 +0200
+
+    media: sun8i-di: Fix runtime PM imbalance in deinterlace_start_streaming
+    
+    pm_runtime_get_sync() will increase the runtime PM counter
+    even it returns an error. Thus a pairing decrement is needed
+    to prevent refcount leak. Fix this by replacing this API with
+    pm_runtime_resume_and_get(), which will not change the runtime
+    PM counter on error.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c b/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c
+index ed863bf5ea80..671e4a928993 100644
+--- a/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c
++++ b/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c
+@@ -589,7 +589,7 @@ static int deinterlace_start_streaming(struct vb2_queue *vq, unsigned int count)
+ 	int ret;
+ 
+ 	if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
+-		ret = pm_runtime_get_sync(dev);
++		ret = pm_runtime_resume_and_get(dev);
+ 		if (ret < 0) {
+ 			dev_err(dev, "Failed to enable module\n");
+ 

commit 69306a947b3ae21e0d1cbfc9508f00fec86c7297
+Author: Dinghao Liu 
+Date:   Wed Apr 7 07:43:13 2021 +0200
+
+    media: platform: sti: Fix runtime PM imbalance in regs_show
+    
+    pm_runtime_get_sync() will increase the runtime PM counter
+    even it returns an error. Thus a pairing decrement is needed
+    to prevent refcount leak. Fix this by replacing this API with
+    pm_runtime_resume_and_get(), which will not change the runtime
+    PM counter on error.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/sti/bdisp/bdisp-debug.c b/drivers/media/platform/sti/bdisp/bdisp-debug.c
+index 2b270093009c..a27f638df11c 100644
+--- a/drivers/media/platform/sti/bdisp/bdisp-debug.c
++++ b/drivers/media/platform/sti/bdisp/bdisp-debug.c
+@@ -480,7 +480,7 @@ static int regs_show(struct seq_file *s, void *data)
+ 	int ret;
+ 	unsigned int i;
+ 
+-	ret = pm_runtime_get_sync(bdisp->dev);
++	ret = pm_runtime_resume_and_get(bdisp->dev);
+ 	if (ret < 0) {
+ 		seq_puts(s, "Cannot wake up IP\n");
+ 		return 0;

commit 5859c926d1f052ee61b5815b14658875c14f6243
+Author: Dinghao Liu 
+Date:   Thu Apr 8 15:26:58 2021 +0800
+
+    PCI: tegra: Fix runtime PM imbalance in pex_ep_event_pex_rst_deassert()
+    
+    pm_runtime_get_sync() will increase the runtime PM counter
+    even it returns an error. Thus a pairing decrement is needed
+    to prevent refcount leak. Fix this by replacing this API with
+    pm_runtime_resume_and_get(), which will not change the runtime
+    PM counter on error.
+    
+    Link: https://lore.kernel.org/r/20210408072700.15791-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Lorenzo Pieralisi 
+    Acked-by: Thierry Reding 
+
+diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
+index 18acd48e8e9b..9b6799258fa4 100644
+--- a/drivers/pci/controller/dwc/pcie-tegra194.c
++++ b/drivers/pci/controller/dwc/pcie-tegra194.c
+@@ -1645,7 +1645,7 @@ static void pex_ep_event_pex_rst_deassert(struct tegra_pcie_dw *pcie)
+ 	if (pcie->ep_state == EP_STATE_ENABLED)
+ 		return;
+ 
+-	ret = pm_runtime_get_sync(dev);
++	ret = pm_runtime_resume_and_get(dev);
+ 	if (ret < 0) {
+ 		dev_err(dev, "Failed to get runtime sync for PCIe dev: %d\n",
+ 			ret);

commit a21fbc42807b15b74b0891bd557063e6acf4fcae
+Author: Dinghao Liu 
+Date:   Thu Apr 8 17:25:59 2021 +0800
+
+    spi: spi-zynqmp-gqspi: Fix runtime PM imbalance in zynqmp_qspi_probe
+    
+    When platform_get_irq() fails, a pairing PM usage counter
+    increment is needed to keep the counter balanced. It's the
+    same for the following error paths.
+    
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20210408092559.3824-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Mark Brown 
+
+diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c
+index c8fa6ee18ae7..95963a2de64a 100644
+--- a/drivers/spi/spi-zynqmp-gqspi.c
++++ b/drivers/spi/spi-zynqmp-gqspi.c
+@@ -1197,6 +1197,7 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
+ 	return 0;
+ 
+ clk_dis_all:
++	pm_runtime_get_noresume(&pdev->dev);
+ 	pm_runtime_set_suspended(&pdev->dev);
+ 	pm_runtime_disable(&pdev->dev);
+ 	clk_disable_unprepare(xqspi->refclk);

commit 7b3f5b207da5116add56c335c5fb92cee140dc63
+Author: Dinghao Liu 
+Date:   Thu Apr 8 14:40:34 2021 +0800
+
+    ASoC: codecs: Fix runtime PM imbalance in tas2552_probe
+    
+    There is a rumtime PM imbalance between the error handling path
+    after devm_snd_soc_register_component() and all other error
+    handling paths. Add a PM runtime increment to balance refcount.
+    
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20210408064036.6691-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c
+index bd00c35116cd..700baa6314aa 100644
+--- a/sound/soc/codecs/tas2552.c
++++ b/sound/soc/codecs/tas2552.c
+@@ -730,8 +730,10 @@ static int tas2552_probe(struct i2c_client *client,
+ 	ret = devm_snd_soc_register_component(&client->dev,
+ 				      &soc_component_dev_tas2552,
+ 				      tas2552_dai, ARRAY_SIZE(tas2552_dai));
+-	if (ret < 0)
++	if (ret < 0) {
+ 		dev_err(&client->dev, "Failed to register component: %d\n", ret);
++		pm_runtime_get_noresume(&client->dev);
++	}
+ 
+ 	return ret;
+ }

commit d599005afde8dd86b819d353fd77568c35295337
+Author: Dinghao Liu 
+Date:   Fri Feb 26 16:41:46 2021 +0800
+
+    mmc: sdhci-pci-o2micro: Add missing checks in sdhci_pci_o2_probe
+    
+    It's odd to adopt different error handling on failure of
+    pci_read_config_dword(). Check the return value and terminate
+    execution flow on failure of all pci_read_config_dword() calls
+    in this function.
+    
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20210226084146.29095-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Ulf Hansson 
+
+diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c
+index 94e3f72f6405..51d55a87aebe 100644
+--- a/drivers/mmc/host/sdhci-pci-o2micro.c
++++ b/drivers/mmc/host/sdhci-pci-o2micro.c
+@@ -706,6 +706,8 @@ static int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)
+ 			ret = pci_read_config_dword(chip->pdev,
+ 						    O2_SD_FUNC_REG0,
+ 						    &scratch_32);
++			if (ret)
++				return ret;
+ 			scratch_32 = ((scratch_32 & 0xFF000000) >> 24);
+ 
+ 			/* Check Whether subId is 0x11 or 0x12 */
+@@ -716,6 +718,8 @@ static int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)
+ 				ret = pci_read_config_dword(chip->pdev,
+ 							    O2_SD_FUNC_REG4,
+ 							    &scratch_32);
++				if (ret)
++					return ret;
+ 
+ 				/* Enable Base Clk setting change */
+ 				scratch_32 |= O2_SD_FREG4_ENABLE_CLK_SET;
+@@ -795,6 +799,8 @@ static int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)
+ 
+ 		ret = pci_read_config_dword(chip->pdev,
+ 					    O2_SD_PLL_SETTING, &scratch_32);
++		if (ret)
++			return ret;
+ 
+ 		if ((scratch_32 & 0xff000000) == 0x01000000) {
+ 			scratch_32 &= 0x0000FFFF;
+@@ -812,6 +818,8 @@ static int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)
+ 			ret = pci_read_config_dword(chip->pdev,
+ 						    O2_SD_FUNC_REG4,
+ 						    &scratch_32);
++			if (ret)
++				return ret;
+ 			scratch_32 |= (1 << 22);
+ 			pci_write_config_dword(chip->pdev,
+ 					       O2_SD_FUNC_REG4, scratch_32);

commit d3bdd1c3140724967ca4136755538fa7c05c2b4e
+Author: Dinghao Liu 
+Date:   Tue Jan 19 16:10:55 2021 +0800
+
+    extcon: Fix error handling in extcon_dev_register
+    
+    When devm_kcalloc() fails, we should execute device_unregister()
+    to unregister edev->dev from system.
+    
+    Fixes: 046050f6e623e ("extcon: Update the prototype of extcon_register_notifier() with enum extcon")
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Chanwoo Choi 
+
+diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c
+index 0a6438cbb3f3..e7a9561a826d 100644
+--- a/drivers/extcon/extcon.c
++++ b/drivers/extcon/extcon.c
+@@ -1241,6 +1241,7 @@ int extcon_dev_register(struct extcon_dev *edev)
+ 				sizeof(*edev->nh), GFP_KERNEL);
+ 	if (!edev->nh) {
+ 		ret = -ENOMEM;
++		device_unregister(&edev->dev);
+ 		goto err_dev;
+ 	}
+ 

commit 17e499a7d6b52ff3be565a2f6184883dd1fdd9af
+Author: Dinghao Liu 
+Date:   Wed Mar 3 20:12:36 2021 +0800
+
+    power: supply: axp20x_usb_power: Add missing check in axp20x_usb_power_probe
+    
+    There are two regmap_update_bits() calls but only one of them has
+    return value check, which is odd. Add a return value check and
+    terminate the execution flow on failure just like the other call.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Sebastian Reichel 
+
+diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c
+index 8933ae26c3d6..7ed76eef8417 100644
+--- a/drivers/power/supply/axp20x_usb_power.c
++++ b/drivers/power/supply/axp20x_usb_power.c
+@@ -614,8 +614,10 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
+ 
+ 	if (power->axp20x_id == AXP813_ID) {
+ 		/* Enable USB Battery Charging specification detection */
+-		regmap_update_bits(axp20x->regmap, AXP288_BC_GLOBAL,
++		ret = regmap_update_bits(axp20x->regmap, AXP288_BC_GLOBAL,
+ 				   AXP813_BC_EN, AXP813_BC_EN);
++		if (ret)
++			return ret;
+ 	}
+ 
+ 	psy_cfg.of_node = pdev->dev.of_node;

commit 0ed0283f0297d0bb6b34a831a4989dd58f4c8368
+Author: Dinghao Liu 
+Date:   Wed Mar 3 15:34:08 2021 +0800
+
+    sata_dwc_460ex: Fix missing check in sata_dwc_isr
+    
+    The return value of ata_qc_from_tag() is checked in the whole
+    kernel except for two calls in sata_dwc_isr(), which may lead
+    to null-pointer-dereference. Add return value checks to avoid
+    such case.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
+index 9dcef6ac643b..f0ef844428bb 100644
+--- a/drivers/ata/sata_dwc_460ex.c
++++ b/drivers/ata/sata_dwc_460ex.c
+@@ -543,6 +543,11 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance)
+ 		hsdev->sactive_issued |= qcmd_tag_to_mask(tag);
+ 
+ 		qc = ata_qc_from_tag(ap, tag);
++		if (unlikely(!qc)) {
++			dev_err(ap->dev, "failed to get qc");
++			handled = 1;
++			goto DONE;
++		}
+ 		/*
+ 		 * Start FP DMA for NCQ command.  At this point the tag is the
+ 		 * active tag.  It is the tag that matches the command about to
+@@ -658,6 +663,11 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance)
+ 
+ 		tag_mask &= (~0x00000001);
+ 		qc = ata_qc_from_tag(ap, tag);
++		if (unlikely(!qc)) {
++			dev_err(ap->dev, "failed to get qc");
++			handled = 1;
++			goto DONE;
++		}
+ 
+ 		/* To be picked up by completion functions */
+ 		qc->ap->link.active_tag = tag;

commit b52912b8293f2c496f42583e65599aee606a0c18
+Author: Dinghao Liu 
+Date:   Sun Feb 28 17:44:23 2021 +0800
+
+    e1000e: Fix error handling in e1000_set_d0_lplu_state_82571
+    
+    There is one e1e_wphy() call in e1000_set_d0_lplu_state_82571
+    that we have caught its return value but lack further handling.
+    Check and terminate the execution flow just like other e1e_wphy()
+    in this function.
+    
+    Fixes: bc7f75fa9788 ("[E1000E]: New pci-express e1000 driver (currently for ICH9 devices only)")
+    Signed-off-by: Dinghao Liu 
+    Acked-by: Sasha Neftin 
+    Tested-by: Dvora Fuxbrumer 
+    Signed-off-by: Tony Nguyen 
+
+diff --git a/drivers/net/ethernet/intel/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c
+index 88faf05e23ba..0b1e890dd583 100644
+--- a/drivers/net/ethernet/intel/e1000e/82571.c
++++ b/drivers/net/ethernet/intel/e1000e/82571.c
+@@ -899,6 +899,8 @@ static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active)
+ 	} else {
+ 		data &= ~IGP02E1000_PM_D0_LPLU;
+ 		ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data);
++		if (ret_val)
++			return ret_val;
+ 		/* LPLU and SmartSpeed are mutually exclusive.  LPLU is used
+ 		 * during Dx states where the power conservation is most
+ 		 * important.  During driver activity we should enable

commit f8096ff38d5f62d8a2c473e1bec0163a1b2b86d8
+Author: Dinghao Liu 
+Date:   Mon Mar 1 20:50:57 2021 +0800
+
+    drivers: misc: ad525x_dpot: Add missing check in dpot_read_spi
+    
+    The use of dpot_read_r8d8() after checking dpot->uid is similar.
+    However, we check the return value and return an error code only
+    in one path, which is odd.
+    
+    Link: https://lore.kernel.org/r/20210301125057.28819-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/misc/ad525x_dpot.c b/drivers/misc/ad525x_dpot.c
+index 6f164522b028..5d8f3f6a95f2 100644
+--- a/drivers/misc/ad525x_dpot.c
++++ b/drivers/misc/ad525x_dpot.c
+@@ -139,6 +139,9 @@ static s32 dpot_read_spi(struct dpot_data *dpot, u8 reg)
+ 			value = dpot_read_r8d8(dpot,
+ 				DPOT_AD5291_READ_RDAC << 2);
+ 
++			if (value < 0)
++				return value;
++
+ 			if (dpot->uid == DPOT_UID(AD5291_ID))
+ 				value = value >> 2;
+ 

commit 6dbbbe4cfd398704b72b21c1d4a5d3807e909d60
+Author: Dinghao Liu 
+Date:   Mon Mar 1 16:04:21 2021 +0800
+
+    iio: gyro: mpu3050: Fix error handling in mpu3050_trigger_handler
+    
+    There is one regmap_bulk_read() call in mpu3050_trigger_handler
+    that we have caught its return value bug lack further handling.
+    Check and terminate the execution flow just like the other three
+    regmap_bulk_read() calls in this function.
+    
+    Fixes: 3904b28efb2c7 ("iio: gyro: Add driver for the MPU-3050 gyroscope")
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Linus Walleij 
+    Link: https://lore.kernel.org/r/20210301080421.13436-1-dinghao.liu@zju.edu.cn
+    Cc: 
+    Signed-off-by: Jonathan Cameron 
+
+diff --git a/drivers/iio/gyro/mpu3050-core.c b/drivers/iio/gyro/mpu3050-core.c
+index dfa31a23500f..ac90be03332a 100644
+--- a/drivers/iio/gyro/mpu3050-core.c
++++ b/drivers/iio/gyro/mpu3050-core.c
+@@ -551,6 +551,8 @@ static irqreturn_t mpu3050_trigger_handler(int irq, void *p)
+ 					       MPU3050_FIFO_R,
+ 					       &fifo_values[offset],
+ 					       toread);
++			if (ret)
++				goto out_trigger_unlock;
+ 
+ 			dev_dbg(mpu3050->dev,
+ 				"%04x %04x %04x %04x %04x\n",

commit 7a766381634da19fc837619b0a34590498d9d29a
+Author: Dinghao Liu 
+Date:   Sun Jan 3 16:08:42 2021 +0800
+
+    ixgbe: Fix memleak in ixgbe_configure_clsu32
+    
+    When ixgbe_fdir_write_perfect_filter_82599() fails,
+    input allocated by kzalloc() has not been freed,
+    which leads to memleak.
+    
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Paul Menzel 
+    Tested-by: Tony Brelinski 
+    Signed-off-by: Tony Nguyen 
+
+diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+index fae84202d870..9f3f12e2ccf2 100644
+--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+@@ -9565,8 +9565,10 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
+ 	ixgbe_atr_compute_perfect_hash_82599(&input->filter, mask);
+ 	err = ixgbe_fdir_write_perfect_filter_82599(hw, &input->filter,
+ 						    input->sw_idx, queue);
+-	if (!err)
+-		ixgbe_update_ethtool_fdir_entry(adapter, input, input->sw_idx);
++	if (err)
++		goto err_out_w_lock;
++
++	ixgbe_update_ethtool_fdir_entry(adapter, input, input->sw_idx);
+ 	spin_unlock(&adapter->fdir_perfect_lock);
+ 
+ 	if ((uhtid != 0x800) && (adapter->jump_tables[uhtid]))

commit 11b8ab3836454a2600e396f34731e491b661f9d5
+Author: Dinghao Liu 
+Date:   Tue Jan 5 14:03:40 2021 +0800
+
+    ubifs: Fix memleak in ubifs_init_authentication
+    
+    When crypto_shash_digestsize() fails, c->hmac_tfm
+    has not been freed before returning, which leads
+    to memleak.
+    
+    Fixes: 49525e5eecca5 ("ubifs: Add helper functions for authentication support")
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Zhihao Cheng 
+    Signed-off-by: Richard Weinberger 
+
+diff --git a/fs/ubifs/auth.c b/fs/ubifs/auth.c
+index 51a7c8c2c3f0..e564d5ff8781 100644
+--- a/fs/ubifs/auth.c
++++ b/fs/ubifs/auth.c
+@@ -327,7 +327,7 @@ int ubifs_init_authentication(struct ubifs_info *c)
+ 		ubifs_err(c, "hmac %s is bigger than maximum allowed hmac size (%d > %d)",
+ 			  hmac_name, c->hmac_desc_len, UBIFS_HMAC_ARR_SZ);
+ 		err = -EINVAL;
+-		goto out_free_hash;
++		goto out_free_hmac;
+ 	}
+ 
+ 	err = crypto_shash_setkey(c->hmac_tfm, ukp->data, ukp->datalen);

commit 0074946932cbd42647da947408a9d620746a4e0e
+Author: Dinghao Liu 
+Date:   Sun Jan 31 18:09:14 2021 +0800
+
+    ALSA: intel8x0: Fix missing check in snd_intel8x0m_create
+    
+    When device_type == DEVICE_ALI, we should also check the return
+    value of pci_iomap() to avoid potential null pointer dereference.
+    
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20210131100916.7915-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
+index 1b7df0c4e57c..19872cecc9d2 100644
+--- a/sound/pci/intel8x0m.c
++++ b/sound/pci/intel8x0m.c
+@@ -1129,13 +1129,14 @@ static int snd_intel8x0m_create(struct snd_card *card,
+ 		chip->bmaddr = pci_iomap(pci, 3, 0);
+ 	else
+ 		chip->bmaddr = pci_iomap(pci, 1, 0);
++
++port_inited:
+ 	if (!chip->bmaddr) {
+ 		dev_err(card->dev, "Controller space ioremap problem\n");
+ 		snd_intel8x0m_free(chip);
+ 		return -EIO;
+ 	}
+ 
+- port_inited:
+ 	/* initialize offsets */
+ 	chip->bdbars_count = 2;
+ 	tbl = intel_regs;

commit ef49d40b61a3e18a11edd5eb1c30b0183af9e850
+Author: Dinghao Liu 
+Date:   Sun Jan 17 16:50:17 2021 +0800
+
+    block: Fix an error handling in add_partition
+    
+    Once we have called device_initialize(), we should use put_device() to
+    give up the reference on error, just like what we have done on failure
+    of device_add().
+    
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Christoph Hellwig 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/partitions/core.c b/block/partitions/core.c
+index e7d776db803b..23460cee9de5 100644
+--- a/block/partitions/core.c
++++ b/block/partitions/core.c
+@@ -384,7 +384,7 @@ static struct block_device *add_partition(struct gendisk *disk, int partno,
+ 
+ 	err = blk_alloc_devt(bdev, &devt);
+ 	if (err)
+-		goto out_bdput;
++		goto out_put;
+ 	pdev->devt = devt;
+ 
+ 	/* delay uevent until 'holders' subdir is created */

commit ccf11dbaa07b328fa469415c362d33459c140a37
+Author: Dinghao Liu 
+Date:   Sun Jan 10 16:02:53 2021 +0800
+
+    evm: Fix memleak in init_desc
+    
+    tmp_tfm is allocated, but not freed on subsequent kmalloc failure, which
+    leads to a memory leak.  Free tmp_tfm.
+    
+    Fixes: d46eb3699502b ("evm: crypto hash replaced by shash")
+    Signed-off-by: Dinghao Liu 
+    [zohar@linux.ibm.com: formatted/reworded patch description]
+    Signed-off-by: Mimi Zohar 
+
+diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c
+index 168c3b78ac47..a6dd47eb086d 100644
+--- a/security/integrity/evm/evm_crypto.c
++++ b/security/integrity/evm/evm_crypto.c
+@@ -73,7 +73,7 @@ static struct shash_desc *init_desc(char type, uint8_t hash_algo)
+ {
+ 	long rc;
+ 	const char *algo;
+-	struct crypto_shash **tfm, *tmp_tfm;
++	struct crypto_shash **tfm, *tmp_tfm = NULL;
+ 	struct shash_desc *desc;
+ 
+ 	if (type == EVM_XATTR_HMAC) {
+@@ -118,13 +118,16 @@ static struct shash_desc *init_desc(char type, uint8_t hash_algo)
+ alloc:
+ 	desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(*tfm),
+ 			GFP_KERNEL);
+-	if (!desc)
++	if (!desc) {
++		crypto_free_shash(tmp_tfm);
+ 		return ERR_PTR(-ENOMEM);
++	}
+ 
+ 	desc->tfm = *tfm;
+ 
+ 	rc = crypto_shash_init(desc);
+ 	if (rc) {
++		crypto_free_shash(tmp_tfm);
+ 		kfree(desc);
+ 		return ERR_PTR(rc);
+ 	}

commit d6e3ae76728ccde49271d9f5acfebbea0c5625a3
+Author: Dinghao Liu 
+Date:   Fri Dec 25 16:35:20 2020 +0800
+
+    scsi: fnic: Fix memleak in vnic_dev_init_devcmd2
+    
+    When ioread32() returns 0xFFFFFFFF, we should execute cleanup functions
+    like other error handling paths before returning.
+    
+    Link: https://lore.kernel.org/r/20201225083520.22015-1-dinghao.liu@zju.edu.cn
+    Acked-by: Karan Tilak Kumar 
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/scsi/fnic/vnic_dev.c b/drivers/scsi/fnic/vnic_dev.c
+index a2beee6e09f0..5988c300cc82 100644
+--- a/drivers/scsi/fnic/vnic_dev.c
++++ b/drivers/scsi/fnic/vnic_dev.c
+@@ -444,7 +444,8 @@ static int vnic_dev_init_devcmd2(struct vnic_dev *vdev)
+ 	fetch_index = ioread32(&vdev->devcmd2->wq.ctrl->fetch_index);
+ 	if (fetch_index == 0xFFFFFFFF) { /* check for hardware gone  */
+ 		pr_err("error in devcmd2 init");
+-		return -ENODEV;
++		err = -ENODEV;
++		goto err_free_wq;
+ 	}
+ 
+ 	/*
+@@ -460,7 +461,7 @@ static int vnic_dev_init_devcmd2(struct vnic_dev *vdev)
+ 	err = vnic_dev_alloc_desc_ring(vdev, &vdev->devcmd2->results_ring,
+ 			DEVCMD2_RING_SIZE, DEVCMD2_DESC_SIZE);
+ 	if (err)
+-		goto err_free_wq;
++		goto err_disable_wq;
+ 
+ 	vdev->devcmd2->result =
+ 		(struct devcmd2_result *) vdev->devcmd2->results_ring.descs;
+@@ -481,8 +482,9 @@ static int vnic_dev_init_devcmd2(struct vnic_dev *vdev)
+ 
+ err_free_desc_ring:
+ 	vnic_dev_free_desc_ring(vdev, &vdev->devcmd2->results_ring);
+-err_free_wq:
++err_disable_wq:
+ 	vnic_wq_disable(&vdev->devcmd2->wq);
++err_free_wq:
+ 	vnic_wq_free(&vdev->devcmd2->wq);
+ err_free_devcmd2:
+ 	kfree(vdev->devcmd2);

commit 76aaf8a96771c16365b8510f1fb97738dc88026e
+Author: Dinghao Liu 
+Date:   Sat Jan 2 09:26:37 2021 +0100
+
+    media: tm6000: Fix memleak in tm6000_start_stream
+    
+    When usb_clear_halt() fails, dvb->bulk_urb->transfer_buffer
+    and dvb->bulk_urb should be freed just like when
+    usb_submit_urb() fails.
+    
+    Fixes: 3169c9b26fffa ("V4L/DVB (12788): tm6000: Add initial DVB-T support")
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/usb/tm6000/tm6000-dvb.c b/drivers/media/usb/tm6000/tm6000-dvb.c
+index 19c90fa9e443..293a460f4616 100644
+--- a/drivers/media/usb/tm6000/tm6000-dvb.c
++++ b/drivers/media/usb/tm6000/tm6000-dvb.c
+@@ -141,6 +141,10 @@ static int tm6000_start_stream(struct tm6000_core *dev)
+ 	if (ret < 0) {
+ 		printk(KERN_ERR "tm6000: error %i in %s during pipe reset\n",
+ 							ret, __func__);
++
++		kfree(dvb->bulk_urb->transfer_buffer);
++		usb_free_urb(dvb->bulk_urb);
++		dvb->bulk_urb = NULL;
+ 		return ret;
+ 	} else
+ 		printk(KERN_ERR "tm6000: pipe reset\n");

commit 15d0c52241ecb1c9d802506bff6f5c3f7872c0df
+Author: Dinghao Liu 
+Date:   Sat Jan 2 07:27:22 2021 +0100
+
+    media: media/pci: Fix memleak in empress_init
+    
+    When vb2_queue_init() fails, dev->empress_dev
+    should be released just like other error handling
+    paths.
+    
+    Fixes: 2ada815fc48bb ("[media] saa7134: convert to vb2")
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c
+index 39e3c7f8c5b4..76a37fbd8458 100644
+--- a/drivers/media/pci/saa7134/saa7134-empress.c
++++ b/drivers/media/pci/saa7134/saa7134-empress.c
+@@ -282,8 +282,11 @@ static int empress_init(struct saa7134_dev *dev)
+ 	q->lock = &dev->lock;
+ 	q->dev = &dev->pci->dev;
+ 	err = vb2_queue_init(q);
+-	if (err)
++	if (err) {
++		video_device_release(dev->empress_dev);
++		dev->empress_dev = NULL;
+ 		return err;
++	}
+ 	dev->empress_dev->queue = q;
+ 	dev->empress_dev->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
+ 					V4L2_CAP_VIDEO_CAPTURE;

commit a26efd1961a18b91ae4cd2e433adbcf865b40fa3
+Author: Dinghao Liu 
+Date:   Mon Dec 28 14:02:05 2020 +0100
+
+    media: em28xx: Fix use-after-free in em28xx_alloc_urbs
+    
+    When kzalloc() fails, em28xx_uninit_usb_xfer() will free
+    usb_bufs->buf and set it to NULL. Thus the later access
+    to usb_bufs->buf[i] will lead to null pointer dereference.
+    Also the kfree(usb_bufs->buf) after that is redundant.
+    
+    Fixes: d571b592c6206 ("media: em28xx: don't use coherent buffer for DMA transfers")
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c
+index e6088b5d1b80..3daa64bb1e1d 100644
+--- a/drivers/media/usb/em28xx/em28xx-core.c
++++ b/drivers/media/usb/em28xx/em28xx-core.c
+@@ -956,14 +956,10 @@ int em28xx_alloc_urbs(struct em28xx *dev, enum em28xx_mode mode, int xfer_bulk,
+ 
+ 		usb_bufs->buf[i] = kzalloc(sb_size, GFP_KERNEL);
+ 		if (!usb_bufs->buf[i]) {
+-			em28xx_uninit_usb_xfer(dev, mode);
+-
+ 			for (i--; i >= 0; i--)
+ 				kfree(usb_bufs->buf[i]);
+ 
+-			kfree(usb_bufs->buf);
+-			usb_bufs->buf = NULL;
+-
++			em28xx_uninit_usb_xfer(dev, mode);
+ 			return -ENOMEM;
+ 		}
+ 

commit 869f4fdaf4ca7bb6e0d05caf6fa1108dddc346a7
+Author: Dinghao Liu 
+Date:   Sat Jan 9 20:01:21 2021 +0800
+
+    netfilter: nf_nat: Fix memleak in nf_nat_init
+    
+    When register_pernet_subsys() fails, nf_nat_bysource
+    should be freed just like when nf_ct_extend_register()
+    fails.
+    
+    Fixes: 1cd472bf036ca ("netfilter: nf_nat: add nat hook register functions to nf_nat")
+    Signed-off-by: Dinghao Liu 
+    Acked-by: Florian Westphal 
+    Signed-off-by: Pablo Neira Ayuso 
+
+diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
+index ea923f8cf9c4..b7c3c902290f 100644
+--- a/net/netfilter/nf_nat_core.c
++++ b/net/netfilter/nf_nat_core.c
+@@ -1174,6 +1174,7 @@ static int __init nf_nat_init(void)
+ 	ret = register_pernet_subsys(&nat_net_ops);
+ 	if (ret < 0) {
+ 		nf_ct_extend_unregister(&nat_extend);
++		kvfree(nf_nat_bysource);
+ 		return ret;
+ 	}
+ 

commit 5b0bb12c58ac7d22e05b5bfdaa30a116c8c32e32
+Author: Dinghao Liu 
+Date:   Mon Dec 21 19:27:31 2020 +0800
+
+    net/mlx5e: Fix memleak in mlx5e_create_l2_table_groups
+    
+    When mlx5_create_flow_group() fails, ft->g should be
+    freed just like when kvzalloc() fails. The caller of
+    mlx5e_create_l2_table_groups() does not catch this
+    issue on failure, which leads to memleak.
+    
+    Fixes: 33cfaaa8f36f ("net/mlx5e: Split the main flow steering table")
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Leon Romanovsky 
+    Signed-off-by: Saeed Mahameed 
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
+index 44a2dfbc3853..e02e5895703d 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
+@@ -1392,6 +1392,7 @@ static int mlx5e_create_l2_table_groups(struct mlx5e_l2_table *l2_table)
+ 	ft->g[ft->num_groups] = NULL;
+ 	mlx5e_destroy_groups(ft);
+ 	kvfree(in);
++	kfree(ft->g);
+ 
+ 	return err;
+ }

commit 7a6eb072a9548492ead086f3e820e9aac71c7138
+Author: Dinghao Liu 
+Date:   Mon Dec 28 16:48:40 2020 +0800
+
+    net/mlx5e: Fix two double free cases
+    
+    mlx5e_create_ttc_table_groups() frees ft->g on failure of
+    kvzalloc(), but such failure will be caught by its caller
+    in mlx5e_create_ttc_table() and ft->g will be freed again
+    in mlx5e_destroy_flow_table(). The same issue also occurs
+    in mlx5e_create_ttc_table_groups(). Set ft->g to NULL after
+    kfree() to avoid double free.
+    
+    Fixes: 7b3722fa9ef6 ("net/mlx5e: Support RSS for GRE tunneled packets")
+    Fixes: 33cfaaa8f36f ("net/mlx5e: Split the main flow steering table")
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Leon Romanovsky 
+    Signed-off-by: Saeed Mahameed 
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
+index fa8149f6eb08..44a2dfbc3853 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
+@@ -942,6 +942,7 @@ static int mlx5e_create_ttc_table_groups(struct mlx5e_ttc_table *ttc,
+ 	in = kvzalloc(inlen, GFP_KERNEL);
+ 	if (!in) {
+ 		kfree(ft->g);
++		ft->g = NULL;
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -1087,6 +1088,7 @@ static int mlx5e_create_inner_ttc_table_groups(struct mlx5e_ttc_table *ttc)
+ 	in = kvzalloc(inlen, GFP_KERNEL);
+ 	if (!in) {
+ 		kfree(ft->g);
++		ft->g = NULL;
+ 		return -ENOMEM;
+ 	}
+ 

commit a306aba9c8d869b1fdfc8ad9237f1ed718ea55e6
+Author: Dinghao Liu 
+Date:   Sat Dec 26 15:42:48 2020 +0800
+
+    RDMA/usnic: Fix memleak in find_free_vf_and_create_qp_grp
+    
+    If usnic_ib_qp_grp_create() fails at the first call, dev_list
+    will not be freed on error, which leads to memleak.
+    
+    Fixes: e3cf00d0a87f ("IB/usnic: Add Cisco VIC low-level hardware driver")
+    Link: https://lore.kernel.org/r/20201226074248.2893-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Leon Romanovsky 
+    Signed-off-by: Jason Gunthorpe 
+
+diff --git a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
+index 38a37770c016..3705c6b8b223 100644
+--- a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
++++ b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
+@@ -214,6 +214,7 @@ find_free_vf_and_create_qp_grp(struct usnic_ib_dev *us_ibdev,
+ 
+ 		}
+ 		usnic_uiom_free_dev_list(dev_list);
++		dev_list = NULL;
+ 	}
+ 
+ 	/* Try to find resources on an unused vf */
+@@ -239,6 +240,8 @@ find_free_vf_and_create_qp_grp(struct usnic_ib_dev *us_ibdev,
+ qp_grp_check:
+ 	if (IS_ERR_OR_NULL(qp_grp)) {
+ 		usnic_err("Failed to allocate qp_grp\n");
++		if (usnic_ib_share_vf)
++			usnic_uiom_free_dev_list(dev_list);
+ 		return ERR_PTR(qp_grp ? PTR_ERR(qp_grp) : -ENOMEM);
+ 	}
+ 	return qp_grp;

commit 71f8e707557b9bc25dc90a59a752528d4e7c1cbf
+Author: Dinghao Liu 
+Date:   Sat Jan 2 13:47:55 2021 +0800
+
+    Bluetooth: hci_qca: Fix memleak in qca_controller_memdump
+    
+    When __le32_to_cpu() fails, qca_memdump should be freed
+    just like when vmalloc() fails.
+    
+    Fixes: d841502c79e3f ("Bluetooth: hci_qca: Collect controller memory dump during SSR")
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Marcel Holtmann 
+
+diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
+index 4a963682c702..5dbcb7c42b80 100644
+--- a/drivers/bluetooth/hci_qca.c
++++ b/drivers/bluetooth/hci_qca.c
+@@ -1024,7 +1024,9 @@ static void qca_controller_memdump(struct work_struct *work)
+ 			dump_size = __le32_to_cpu(dump->dump_size);
+ 			if (!(dump_size)) {
+ 				bt_dev_err(hu->hdev, "Rx invalid memdump size");
++				kfree(qca_memdump);
+ 				kfree_skb(skb);
++				qca->qca_memdump = NULL;
+ 				mutex_unlock(&qca->hci_memdump_lock);
+ 				return;
+ 			}

commit 3b01d7ea4dae907d34fa0eeb3f17bacd714c6d0c
+Author: Dinghao Liu 
+Date:   Sat Dec 26 14:15:03 2020 +0800
+
+    scsi: scsi_debug: Fix memleak in scsi_debug_init()
+    
+    When sdeb_zbc_model does not match BLK_ZONED_NONE, BLK_ZONED_HA or
+    BLK_ZONED_HM, we should free sdebug_q_arr to prevent memleak. Also there is
+    no need to execute sdebug_erase_store() on failure of sdeb_zbc_model_str().
+    
+    Link: https://lore.kernel.org/r/20201226061503.20050-1-dinghao.liu@zju.edu.cn
+    Acked-by: Douglas Gilbert 
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
+index 24c0f7ec0351..4a08c450b756 100644
+--- a/drivers/scsi/scsi_debug.c
++++ b/drivers/scsi/scsi_debug.c
+@@ -6740,7 +6740,7 @@ static int __init scsi_debug_init(void)
+ 		k = sdeb_zbc_model_str(sdeb_zbc_model_s);
+ 		if (k < 0) {
+ 			ret = k;
+-			goto free_vm;
++			goto free_q_arr;
+ 		}
+ 		sdeb_zbc_model = k;
+ 		switch (sdeb_zbc_model) {
+@@ -6753,7 +6753,8 @@ static int __init scsi_debug_init(void)
+ 			break;
+ 		default:
+ 			pr_err("Invalid ZBC model\n");
+-			return -EINVAL;
++			ret = -EINVAL;
++			goto free_q_arr;
+ 		}
+ 	}
+ 	if (sdeb_zbc_model != BLK_ZONED_NONE) {

commit ff2b46d7cff80d27d82f7f3252711f4ca1666129
+Author: Dinghao Liu 
+Date:   Tue Jan 5 13:18:37 2021 +0800
+
+    iommu/intel: Fix memleak in intel_irq_remapping_alloc
+    
+    When irq_domain_get_irq_data() or irqd_cfg() fails
+    at i == 0, data allocated by kzalloc() has not been
+    freed before returning, which leads to memleak.
+    
+    Fixes: b106ee63abcc ("irq_remapping/vt-d: Enhance Intel IR driver to support hierarchical irqdomains")
+    Signed-off-by: Dinghao Liu 
+    Acked-by: Lu Baolu 
+    Link: https://lore.kernel.org/r/20210105051837.32118-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Will Deacon 
+
+diff --git a/drivers/iommu/intel/irq_remapping.c b/drivers/iommu/intel/irq_remapping.c
+index aeffda92b10b..685200a5cff0 100644
+--- a/drivers/iommu/intel/irq_remapping.c
++++ b/drivers/iommu/intel/irq_remapping.c
+@@ -1353,6 +1353,8 @@ static int intel_irq_remapping_alloc(struct irq_domain *domain,
+ 		irq_data = irq_domain_get_irq_data(domain, virq + i);
+ 		irq_cfg = irqd_cfg(irq_data);
+ 		if (!irq_data || !irq_cfg) {
++			if (!i)
++				kfree(data);
+ 			ret = -EINVAL;
+ 			goto out_free_data;
+ 		}

commit b000700d6db50c933ce8b661154e26cf4ad06dba
+Author: Dinghao Liu 
+Date:   Sat Dec 26 15:27:14 2020 +0800
+
+    habanalabs: Fix memleak in hl_device_reset
+    
+    When kzalloc() fails, we should execute hl_mmu_fini()
+    to release the MMU module. It's the same when
+    hl_ctx_init() fails.
+    
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Oded Gabbay 
+    Signed-off-by: Oded Gabbay 
+
+diff --git a/drivers/misc/habanalabs/common/device.c b/drivers/misc/habanalabs/common/device.c
+index 0749c92cbcf6..1456eabf9601 100644
+--- a/drivers/misc/habanalabs/common/device.c
++++ b/drivers/misc/habanalabs/common/device.c
+@@ -1092,6 +1092,7 @@ int hl_device_reset(struct hl_device *hdev, bool hard_reset,
+ 						GFP_KERNEL);
+ 		if (!hdev->kernel_ctx) {
+ 			rc = -ENOMEM;
++			hl_mmu_fini(hdev);
+ 			goto out_err;
+ 		}
+ 
+@@ -1103,6 +1104,7 @@ int hl_device_reset(struct hl_device *hdev, bool hard_reset,
+ 				"failed to init kernel ctx in hard reset\n");
+ 			kfree(hdev->kernel_ctx);
+ 			hdev->kernel_ctx = NULL;
++			hl_mmu_fini(hdev);
+ 			goto out_err;
+ 		}
+ 	}

commit f31559af97a0eabd467e4719253675b7dccb8a46
+Author: Dinghao Liu 
+Date:   Mon Dec 21 20:24:35 2020 +0800
+
+    staging: fwserial: Fix error handling in fwserial_create
+    
+    When fw_core_add_address_handler() fails, we need to destroy
+    the port by tty_port_destroy(). Also we need to unregister
+    the address handler by fw_core_remove_address_handler() on
+    failure.
+    
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20201221122437.10274-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c
+index db83d34cd677..c368082aae1a 100644
+--- a/drivers/staging/fwserial/fwserial.c
++++ b/drivers/staging/fwserial/fwserial.c
+@@ -2189,6 +2189,7 @@ static int fwserial_create(struct fw_unit *unit)
+ 		err = fw_core_add_address_handler(&port->rx_handler,
+ 						  &fw_high_memory_region);
+ 		if (err) {
++			tty_port_destroy(&port->port);
+ 			kfree(port);
+ 			goto free_ports;
+ 		}
+@@ -2271,6 +2272,7 @@ static int fwserial_create(struct fw_unit *unit)
+ 
+ free_ports:
+ 	for (--i; i >= 0; --i) {
++		fw_core_remove_address_handler(&serial->ports[i]->rx_handler);
+ 		tty_port_destroy(&serial->ports[i]->port);
+ 		kfree(serial->ports[i]);
+ 	}

commit ec36ae7189acd9a24f417e4814e627034da68922
+Author: Dinghao Liu 
+Date:   Sat Dec 26 16:02:56 2020 +0800
+
+    staging: rtl8192u: Add null check in rtl8192_usb_initendpoints
+    
+    There is an allocation for priv->rx_urb[16] has no null check,
+    which may lead to a null pointer dereference.
+    
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20201226080258.6576-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
+index 93676af98629..9fc4adc83d77 100644
+--- a/drivers/staging/rtl8192u/r8192U_core.c
++++ b/drivers/staging/rtl8192u/r8192U_core.c
+@@ -1608,6 +1608,8 @@ static short rtl8192_usb_initendpoints(struct net_device *dev)
+ 		void *oldaddr, *newaddr;
+ 
+ 		priv->rx_urb[16] = usb_alloc_urb(0, GFP_KERNEL);
++		if (!priv->rx_urb[16])
++			return -ENOMEM;
+ 		priv->oldaddr = kmalloc(16, GFP_KERNEL);
+ 		if (!priv->oldaddr)
+ 			return -ENOMEM;

commit 5d41f9b7ee7a5a5138894f58846a4ffed601498a
+Author: Dinghao Liu 
+Date:   Wed Dec 23 19:06:12 2020 +0800
+
+    net: ethernet: Fix memleak in ethoc_probe
+    
+    When mdiobus_register() fails, priv->mdio allocated
+    by mdiobus_alloc() has not been freed, which leads
+    to memleak.
+    
+    Fixes: e7f4dc3536a4 ("mdio: Move allocation of interrupts into core")
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Andrew Lunn 
+    Link: https://lore.kernel.org/r/20201223110615.31389-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c
+index 0981fe9652e5..3d9b0b161e24 100644
+--- a/drivers/net/ethernet/ethoc.c
++++ b/drivers/net/ethernet/ethoc.c
+@@ -1211,7 +1211,7 @@ static int ethoc_probe(struct platform_device *pdev)
+ 	ret = mdiobus_register(priv->mdio);
+ 	if (ret) {
+ 		dev_err(&netdev->dev, "failed to register MDIO bus\n");
+-		goto free2;
++		goto free3;
+ 	}
+ 
+ 	ret = ethoc_mdio_probe(netdev);
+@@ -1243,6 +1243,7 @@ static int ethoc_probe(struct platform_device *pdev)
+ 	netif_napi_del(&priv->napi);
+ error:
+ 	mdiobus_unregister(priv->mdio);
++free3:
+ 	mdiobus_free(priv->mdio);
+ free2:
+ 	clk_disable_unprepare(priv->clk);

commit 58f60329a6be35a5653edb3fd2023ccef9eb9943
+Author: Dinghao Liu 
+Date:   Sun Dec 20 16:29:30 2020 +0800
+
+    net: ethernet: mvneta: Fix error handling in mvneta_probe
+    
+    When mvneta_port_power_up() fails, we should execute
+    cleanup functions after label err_netdev to avoid memleak.
+    
+    Fixes: 41c2b6b4f0f80 ("net: ethernet: mvneta: Add back interface mode validation")
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20201220082930.21623-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
+index 563ceac3060f..3369ec717a51 100644
+--- a/drivers/net/ethernet/marvell/mvneta.c
++++ b/drivers/net/ethernet/marvell/mvneta.c
+@@ -5255,7 +5255,7 @@ static int mvneta_probe(struct platform_device *pdev)
+ 	err = mvneta_port_power_up(pp, pp->phy_interface);
+ 	if (err < 0) {
+ 		dev_err(&pdev->dev, "can't power up port\n");
+-		return err;
++		goto err_netdev;
+ 	}
+ 
+ 	/* Armada3700 network controller does not support per-cpu

commit 167faadfcf9339088910e9e85a1b711fcbbef8e9
+Author: Dinghao Liu 
+Date:   Mon Aug 24 14:27:46 2020 +0200
+
+    media: dvbdev: Fix memleak in dvb_register_device
+    
+    When device_create() fails, dvbdev and dvbdevfops should
+    be freed just like when dvb_register_media_device() fails.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Sean Young 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c
+index 959fa2820259..5ff7bedee247 100644
+--- a/drivers/media/dvb-core/dvbdev.c
++++ b/drivers/media/dvb-core/dvbdev.c
+@@ -539,6 +539,9 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
+ 	if (IS_ERR(clsdev)) {
+ 		pr_err("%s: failed to create device dvb%d.%s%d (%ld)\n",
+ 		       __func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
++		dvb_media_device_free(dvbdev);
++		kfree(dvbdevfops);
++		kfree(dvbdev);
+ 		return PTR_ERR(clsdev);
+ 	}
+ 	dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",

commit 751341b4d7841e2b76e78eec382c2e119165497f
+Author: Dinghao Liu 
+Date:   Thu Aug 27 15:12:38 2020 +0800
+
+    jfs: Fix memleak in dbAdjCtl
+    
+    When dbBackSplit() fails, mp should be released to
+    prevent memleak. It's the same when dbJoin() fails.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Dave Kleikamp 
+
+diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
+index dc02c7faf01f..94b7c1cb5ceb 100644
+--- a/fs/jfs/jfs_dmap.c
++++ b/fs/jfs/jfs_dmap.c
+@@ -2549,15 +2549,19 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level)
+ 		 */
+ 		if (oldval == NOFREE) {
+ 			rc = dbBackSplit((dmtree_t *) dcp, leafno);
+-			if (rc)
++			if (rc) {
++				release_metapage(mp);
+ 				return rc;
++			}
+ 			oldval = dcp->stree[ti];
+ 		}
+ 		dbSplit((dmtree_t *) dcp, leafno, dcp->budmin, newval);
+ 	} else {
+ 		rc = dbJoin((dmtree_t *) dcp, leafno, newval);
+-		if (rc)
++		if (rc) {
++			release_metapage(mp);
+ 			return rc;
++		}
+ 	}
+ 
+ 	/* check if the root of the current dmap control page changed due

commit a5d704d33245b0799947a3008f9f376dba4d5c91
+Author: Dinghao Liu 
+Date:   Sat Aug 22 14:57:33 2020 +0800
+
+    drm/omap: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter
+    even when it returns an error code. However, users of its
+    direct wrappers in omapdrm assume that PM usage counter will
+    not change on error. Thus a pairing decrement is needed on
+    the error handling path for these wrappers to keep the counter
+    balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Tomi Valkeinen 
+    Link: https://patchwork.freedesktop.org/patch/msgid/20200822065743.13671-1-dinghao.liu@zju.edu.cn
+
+diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c
+index 48593932bddf..599183879caf 100644
+--- a/drivers/gpu/drm/omapdrm/dss/dispc.c
++++ b/drivers/gpu/drm/omapdrm/dss/dispc.c
+@@ -653,8 +653,11 @@ int dispc_runtime_get(struct dispc_device *dispc)
+ 	DSSDBG("dispc_runtime_get\n");
+ 
+ 	r = pm_runtime_get_sync(&dispc->pdev->dev);
+-	WARN_ON(r < 0);
+-	return r < 0 ? r : 0;
++	if (WARN_ON(r < 0)) {
++		pm_runtime_put_noidle(&dispc->pdev->dev);
++		return r;
++	}
++	return 0;
+ }
+ 
+ void dispc_runtime_put(struct dispc_device *dispc)
+diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c
+index 5929b320b3cf..735a4e9027d0 100644
+--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
++++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
+@@ -1112,8 +1112,11 @@ static int dsi_runtime_get(struct dsi_data *dsi)
+ 	DSSDBG("dsi_runtime_get\n");
+ 
+ 	r = pm_runtime_get_sync(dsi->dev);
+-	WARN_ON(r < 0);
+-	return r < 0 ? r : 0;
++	if (WARN_ON(r < 0)) {
++		pm_runtime_put_noidle(dsi->dev);
++		return r;
++	}
++	return 0;
+ }
+ 
+ static void dsi_runtime_put(struct dsi_data *dsi)
+diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c
+index 6ccbc29c4ce4..d7b2f5bcac16 100644
+--- a/drivers/gpu/drm/omapdrm/dss/dss.c
++++ b/drivers/gpu/drm/omapdrm/dss/dss.c
+@@ -858,8 +858,11 @@ int dss_runtime_get(struct dss_device *dss)
+ 	DSSDBG("dss_runtime_get\n");
+ 
+ 	r = pm_runtime_get_sync(&dss->pdev->dev);
+-	WARN_ON(r < 0);
+-	return r < 0 ? r : 0;
++	if (WARN_ON(r < 0)) {
++		pm_runtime_put_noidle(&dss->pdev->dev);
++		return r;
++	}
++	return 0;
+ }
+ 
+ void dss_runtime_put(struct dss_device *dss)
+diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+index ba4a21d25796..8de41e74e8f8 100644
+--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
++++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+@@ -43,10 +43,10 @@ static int hdmi_runtime_get(struct omap_hdmi *hdmi)
+ 	DSSDBG("hdmi_runtime_get\n");
+ 
+ 	r = pm_runtime_get_sync(&hdmi->pdev->dev);
+-	WARN_ON(r < 0);
+-	if (r < 0)
++	if (WARN_ON(r < 0)) {
++		pm_runtime_put_noidle(&hdmi->pdev->dev);
+ 		return r;
+-
++	}
+ 	return 0;
+ }
+ 
+diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+index 045aa445c737..54e5cb5aa52d 100644
+--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
++++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+@@ -44,10 +44,10 @@ static int hdmi_runtime_get(struct omap_hdmi *hdmi)
+ 	DSSDBG("hdmi_runtime_get\n");
+ 
+ 	r = pm_runtime_get_sync(&hdmi->pdev->dev);
+-	WARN_ON(r < 0);
+-	if (r < 0)
++	if (WARN_ON(r < 0)) {
++		pm_runtime_put_noidle(&hdmi->pdev->dev);
+ 		return r;
+-
++	}
+ 	return 0;
+ }
+ 
+diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c
+index 5c027c81760f..94cf50d837b0 100644
+--- a/drivers/gpu/drm/omapdrm/dss/venc.c
++++ b/drivers/gpu/drm/omapdrm/dss/venc.c
+@@ -361,8 +361,11 @@ static int venc_runtime_get(struct venc_device *venc)
+ 	DSSDBG("venc_runtime_get\n");
+ 
+ 	r = pm_runtime_get_sync(&venc->pdev->dev);
+-	WARN_ON(r < 0);
+-	return r < 0 ? r : 0;
++	if (WARN_ON(r < 0)) {
++		pm_runtime_put_noidle(&venc->pdev->dev);
++		return r;
++	}
++	return 0;
+ }
+ 
+ static void venc_runtime_put(struct venc_device *venc)

commit 468600c6ec28613b756193c5f780aac062f1acdf
+Author: Dinghao Liu 
+Date:   Wed Oct 21 13:36:55 2020 +0800
+
+    btrfs: ref-verify: fix memory leak in btrfs_ref_tree_mod
+    
+    There is one error handling path that does not free ref, which may cause
+    a minor memory leak.
+    
+    CC: stable@vger.kernel.org # 4.19+
+    Reviewed-by: Josef Bacik 
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: David Sterba 
+    Signed-off-by: David Sterba 
+
+diff --git a/fs/btrfs/ref-verify.c b/fs/btrfs/ref-verify.c
+index 7f03dbe5b609..78693d3dd15b 100644
+--- a/fs/btrfs/ref-verify.c
++++ b/fs/btrfs/ref-verify.c
+@@ -860,6 +860,7 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info,
+ "dropping a ref for a root that doesn't have a ref on the block");
+ 			dump_block_entry(fs_info, be);
+ 			dump_ref_action(fs_info, ra);
++			kfree(ref);
+ 			kfree(ra);
+ 			goto out_unlock;
+ 		}

commit 28d211919e422f58c1e6c900e5810eee4f1ce4c8
+Author: Dinghao Liu 
+Date:   Tue Oct 20 14:12:26 2020 +0800
+
+    rtc: sun6i: Fix memleak in sun6i_rtc_clk_init
+    
+    When clk_hw_register_fixed_rate_with_accuracy() fails,
+    clk_data should be freed. It's the same for the subsequent
+    two error paths, but we should also unregister the already
+    registered clocks in them.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Alexandre Belloni 
+    Link: https://lore.kernel.org/r/20201020061226.6572-1-dinghao.liu@zju.edu.cn
+
+diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
+index e2b8b150bcb4..f2818cdd11d8 100644
+--- a/drivers/rtc/rtc-sun6i.c
++++ b/drivers/rtc/rtc-sun6i.c
+@@ -272,7 +272,7 @@ static void __init sun6i_rtc_clk_init(struct device_node *node,
+ 								300000000);
+ 	if (IS_ERR(rtc->int_osc)) {
+ 		pr_crit("Couldn't register the internal oscillator\n");
+-		return;
++		goto err;
+ 	}
+ 
+ 	parents[0] = clk_hw_get_name(rtc->int_osc);
+@@ -290,7 +290,7 @@ static void __init sun6i_rtc_clk_init(struct device_node *node,
+ 	rtc->losc = clk_register(NULL, &rtc->hw);
+ 	if (IS_ERR(rtc->losc)) {
+ 		pr_crit("Couldn't register the LOSC clock\n");
+-		return;
++		goto err_register;
+ 	}
+ 
+ 	of_property_read_string_index(node, "clock-output-names", 1,
+@@ -301,7 +301,7 @@ static void __init sun6i_rtc_clk_init(struct device_node *node,
+ 					  &rtc->lock);
+ 	if (IS_ERR(rtc->ext_losc)) {
+ 		pr_crit("Couldn't register the LOSC external gate\n");
+-		return;
++		goto err_register;
+ 	}
+ 
+ 	clk_data->num = 2;
+@@ -314,6 +314,8 @@ static void __init sun6i_rtc_clk_init(struct device_node *node,
+ 	of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
+ 	return;
+ 
++err_register:
++	clk_hw_unregister_fixed_rate(rtc->int_osc);
+ err:
+ 	kfree(clk_data);
+ }

commit c9e87161cc621cbdcfc472fa0b2d81c63780c8f5
+Author: Dinghao Liu 
+Date:   Sat Aug 29 10:54:02 2020 +0800
+
+    ext4: fix error handling code in add_new_gdb
+    
+    When ext4_journal_get_write_access() fails, we should
+    terminate the execution flow and release n_group_desc,
+    iloc.bh, dind and gdb_bh.
+    
+    Cc: stable@kernel.org
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Andreas Dilger 
+    Link: https://lore.kernel.org/r/20200829025403.3139-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Theodore Ts'o 
+
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index a50b51270ea9..71bf600e5b42 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -843,8 +843,10 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
+ 
+ 	BUFFER_TRACE(dind, "get_write_access");
+ 	err = ext4_journal_get_write_access(handle, dind);
+-	if (unlikely(err))
++	if (unlikely(err)) {
+ 		ext4_std_error(sb, err);
++		goto errout;
++	}
+ 
+ 	/* ext4_reserve_inode_write() gets a reference on the iloc */
+ 	err = ext4_reserve_inode_write(handle, inode, &iloc);

commit 937425d4cd3ae4e2882b41e332bbbab616bcf0ad
+Author: Dinghao Liu 
+Date:   Mon Aug 24 11:12:30 2020 +0800
+
+    watchdog: Use put_device on error
+    
+    We should use put_device() instead of freeing device
+    directly after device_initialize().
+    
+    Fixes: cb36e29bb0e4b ("watchdog: initialize device before misc_register")
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Guenter Roeck 
+    Link: https://lore.kernel.org/r/20200824031230.31050-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Guenter Roeck 
+    Signed-off-by: Wim Van Sebroeck 
+
+diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c
+index 785270ee337c..bcf01af3fa6a 100644
+--- a/drivers/watchdog/watchdog_dev.c
++++ b/drivers/watchdog/watchdog_dev.c
+@@ -1023,7 +1023,7 @@ static int watchdog_cdev_register(struct watchdog_device *wdd)
+ 				pr_err("%s: a legacy watchdog module is probably present.\n",
+ 					wdd->info->identity);
+ 			old_wd_data = NULL;
+-			kfree(wd_data);
++			put_device(&wd_data->dev);
+ 			return err;
+ 		}
+ 	}

commit 5afb6d203d0293512aa2c6ae098274a2a4f6ed02
+Author: Dinghao Liu 
+Date:   Mon Aug 24 10:40:01 2020 +0800
+
+    watchdog: Fix memleak in watchdog_cdev_register
+    
+    When watchdog_kworker is NULL, we should free wd_data
+    before the function returns to prevent memleak.
+    
+    Fixes: 664a39236e718 ("watchdog: Introduce hardware maximum heartbeat in watchdog core")
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Guenter Roeck 
+    Link: https://lore.kernel.org/r/20200824024001.25474-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Guenter Roeck 
+    Signed-off-by: Wim Van Sebroeck 
+
+diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c
+index 6798addabd5a..785270ee337c 100644
+--- a/drivers/watchdog/watchdog_dev.c
++++ b/drivers/watchdog/watchdog_dev.c
+@@ -994,8 +994,10 @@ static int watchdog_cdev_register(struct watchdog_device *wdd)
+ 	wd_data->wdd = wdd;
+ 	wdd->wd_data = wd_data;
+ 
+-	if (IS_ERR_OR_NULL(watchdog_kworker))
++	if (IS_ERR_OR_NULL(watchdog_kworker)) {
++		kfree(wd_data);
+ 		return -ENODEV;
++	}
+ 
+ 	device_initialize(&wd_data->dev);
+ 	wd_data->dev.devt = MKDEV(MAJOR(watchdog_devt), wdd->id);

commit 98fae901c8883640202802174a4bd70a1b9118bd
+Author: Dinghao Liu 
+Date:   Mon Jun 8 07:29:19 2020 +0200
+
+    media: vsp1: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Kieran Bingham 
+    Reviewed-by: Laurent Pinchart 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
+index c650e45bb0ad..dc62533cf32c 100644
+--- a/drivers/media/platform/vsp1/vsp1_drv.c
++++ b/drivers/media/platform/vsp1/vsp1_drv.c
+@@ -562,7 +562,12 @@ int vsp1_device_get(struct vsp1_device *vsp1)
+ 	int ret;
+ 
+ 	ret = pm_runtime_get_sync(vsp1->dev);
+-	return ret < 0 ? ret : 0;
++	if (ret < 0) {
++		pm_runtime_put_noidle(vsp1->dev);
++		return ret;
++	}
++
++	return 0;
+ }
+ 
+ /*
+@@ -845,12 +850,12 @@ static int vsp1_probe(struct platform_device *pdev)
+ 	/* Configure device parameters based on the version register. */
+ 	pm_runtime_enable(&pdev->dev);
+ 
+-	ret = pm_runtime_get_sync(&pdev->dev);
++	ret = vsp1_device_get(vsp1);
+ 	if (ret < 0)
+ 		goto done;
+ 
+ 	vsp1->version = vsp1_read(vsp1, VI6_IP_VERSION);
+-	pm_runtime_put_sync(&pdev->dev);
++	vsp1_device_put(vsp1);
+ 
+ 	for (i = 0; i < ARRAY_SIZE(vsp1_device_infos); ++i) {
+ 		if ((vsp1->version & VI6_IP_VERSION_MODEL_MASK) ==

commit b4630215067a411341ceeb7850b95b341eee6511
+Author: Dinghao Liu 
+Date:   Mon May 25 15:02:06 2020 +0200
+
+    media: coda: Fix runtime PM imbalance in coda_probe
+    
+    When coda_firmware_request() returns an error code,
+    a pairing runtime PM usage counter decrement is needed
+    to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
+index eeba6c060981..87a2c706f747 100644
+--- a/drivers/media/platform/coda/coda-common.c
++++ b/drivers/media/platform/coda/coda-common.c
+@@ -3264,6 +3264,8 @@ static int coda_probe(struct platform_device *pdev)
+ 	return 0;
+ 
+ err_alloc_workqueue:
++	pm_runtime_disable(&pdev->dev);
++	pm_runtime_put_noidle(&pdev->dev);
+ 	destroy_workqueue(dev->workqueue);
+ err_v4l2_register:
+ 	v4l2_device_unregister(&dev->v4l2_dev);

commit dafa3605fe60d5a61239d670919b2a36e712481e
+Author: Dinghao Liu 
+Date:   Thu May 21 15:29:33 2020 +0200
+
+    media: platform: s3c-camif: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Also, call pm_runtime_disable() when pm_runtime_get_sync() returns
+    an error code.
+    
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Sylwester Nawrocki 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/s3c-camif/camif-core.c b/drivers/media/platform/s3c-camif/camif-core.c
+index 92f43c0cbc0c..422fd549e9c8 100644
+--- a/drivers/media/platform/s3c-camif/camif-core.c
++++ b/drivers/media/platform/s3c-camif/camif-core.c
+@@ -464,7 +464,7 @@ static int s3c_camif_probe(struct platform_device *pdev)
+ 
+ 	ret = camif_media_dev_init(camif);
+ 	if (ret < 0)
+-		goto err_alloc;
++		goto err_pm;
+ 
+ 	ret = camif_register_sensor(camif);
+ 	if (ret < 0)
+@@ -498,10 +498,9 @@ static int s3c_camif_probe(struct platform_device *pdev)
+ 	media_device_unregister(&camif->media_dev);
+ 	media_device_cleanup(&camif->media_dev);
+ 	camif_unregister_media_entities(camif);
+-err_alloc:
++err_pm:
+ 	pm_runtime_put(dev);
+ 	pm_runtime_disable(dev);
+-err_pm:
+ 	camif_clk_put(camif);
+ err_clk:
+ 	s3c_camif_unregister_subdev(camif);

commit d912a1d9e9afe69c6066c1ceb6bfc09063074075
+Author: Dinghao Liu 
+Date:   Thu May 21 12:05:02 2020 +0200
+
+    media: platform: sti: hva: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/sti/hva/hva-hw.c b/drivers/media/platform/sti/hva/hva-hw.c
+index 401aaafa1710..8533d3bc6d5c 100644
+--- a/drivers/media/platform/sti/hva/hva-hw.c
++++ b/drivers/media/platform/sti/hva/hva-hw.c
+@@ -388,7 +388,7 @@ int hva_hw_probe(struct platform_device *pdev, struct hva_dev *hva)
+ 	ret = pm_runtime_get_sync(dev);
+ 	if (ret < 0) {
+ 		dev_err(dev, "%s     failed to set PM\n", HVA_PREFIX);
+-		goto err_clk;
++		goto err_pm;
+ 	}
+ 
+ 	/* check IP hardware version */

commit dbd2f2dc025f9be8ae063e4f270099677238f620
+Author: Dinghao Liu 
+Date:   Thu May 21 12:00:21 2020 +0200
+
+    media: bdisp: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Fabien Dessenne 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
+index 7d50d6cd073d..060ca85f64d5 100644
+--- a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
++++ b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
+@@ -1367,7 +1367,7 @@ static int bdisp_probe(struct platform_device *pdev)
+ 	ret = pm_runtime_get_sync(dev);
+ 	if (ret < 0) {
+ 		dev_err(dev, "failed to set PM\n");
+-		goto err_dbg;
++		goto err_pm;
+ 	}
+ 
+ 	/* Filters */
+@@ -1395,7 +1395,6 @@ static int bdisp_probe(struct platform_device *pdev)
+ 	bdisp_hw_free_filters(bdisp->dev);
+ err_pm:
+ 	pm_runtime_put(dev);
+-err_dbg:
+ 	bdisp_debugfs_remove(bdisp);
+ 	v4l2_device_unregister(&bdisp->v4l2_dev);
+ err_clk:

commit 21d387b8d372f859d9e87fdcc7c3b4a432737f4d
+Author: Dinghao Liu 
+Date:   Wed Aug 26 11:26:04 2020 +0200
+
+    media: mx2_emmaprp: Fix memleak in emmaprp_probe
+    
+    When platform_get_irq() fails, we should release
+    vfd and unregister pcdev->v4l2_dev just like the
+    subsequent error paths.
+    
+    Fixes: d4e192cc44914 ("media: mx2_emmaprp: Check for platform_get_irq() error")
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Fabio Estevam 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/mx2_emmaprp.c b/drivers/media/platform/mx2_emmaprp.c
+index df78df59da45..08a5473b5610 100644
+--- a/drivers/media/platform/mx2_emmaprp.c
++++ b/drivers/media/platform/mx2_emmaprp.c
+@@ -852,8 +852,11 @@ static int emmaprp_probe(struct platform_device *pdev)
+ 	platform_set_drvdata(pdev, pcdev);
+ 
+ 	irq = platform_get_irq(pdev, 0);
+-	if (irq < 0)
+-		return irq;
++	if (irq < 0) {
++		ret = irq;
++		goto rel_vdev;
++	}
++
+ 	ret = devm_request_irq(&pdev->dev, irq, emmaprp_irq, 0,
+ 			       dev_name(&pdev->dev), pcdev);
+ 	if (ret)

commit 4fd9ac6bd3044734a7028bd993944c3617d1eede
+Author: Dinghao Liu 
+Date:   Sun Aug 23 19:12:11 2020 +0800
+
+    Platform: OLPC: Fix memleak in olpc_ec_probe
+    
+    When devm_regulator_register() fails, ec should be
+    freed just like when olpc_ec_cmd() fails.
+    
+    Fixes: 231c0c216172a ("Platform: OLPC: Add a regulator for the DCON")
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Andy Shevchenko 
+
+diff --git a/drivers/platform/olpc/olpc-ec.c b/drivers/platform/olpc/olpc-ec.c
+index 190e4a6186ef..f64b82824db2 100644
+--- a/drivers/platform/olpc/olpc-ec.c
++++ b/drivers/platform/olpc/olpc-ec.c
+@@ -439,7 +439,9 @@ static int olpc_ec_probe(struct platform_device *pdev)
+ 								&config);
+ 	if (IS_ERR(ec->dcon_rdev)) {
+ 		dev_err(&pdev->dev, "failed to register DCON regulator\n");
+-		return PTR_ERR(ec->dcon_rdev);
++		err = PTR_ERR(ec->dcon_rdev);
++		kfree(ec);
++		return err;
+ 	}
+ 
+ 	ec->dbgfs_dir = olpc_ec_setup_debugfs();

commit d8fc21c17099635e8ebd986d042be65a6c6b5bd0
+Author: Dinghao Liu 
+Date:   Mon Aug 24 08:53:52 2020 +0200
+
+    media: omap3isp: Fix memleak in isp_probe
+    
+    When devm_ioremap_resource() fails, isp should be
+    freed just like other error paths in isp_probe.
+    
+    Fixes: 8644cdf972dd6 ("[media] omap3isp: Replace many MMIO regions by two")
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Sakari Ailus 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
+index 74fa67082e09..b1fc4518e275 100644
+--- a/drivers/media/platform/omap3isp/isp.c
++++ b/drivers/media/platform/omap3isp/isp.c
+@@ -2328,8 +2328,10 @@ static int isp_probe(struct platform_device *pdev)
+ 		mem = platform_get_resource(pdev, IORESOURCE_MEM, i);
+ 		isp->mmio_base[map_idx] =
+ 			devm_ioremap_resource(isp->dev, mem);
+-		if (IS_ERR(isp->mmio_base[map_idx]))
+-			return PTR_ERR(isp->mmio_base[map_idx]);
++		if (IS_ERR(isp->mmio_base[map_idx])) {
++			ret = PTR_ERR(isp->mmio_base[map_idx]);
++			goto error;
++		}
+ 	}
+ 
+ 	ret = isp_get_clocks(isp);

commit fe6c6a4af2be8c15bac77f7ea160f947c04840d1
+Author: Dinghao Liu 
+Date:   Tue Aug 25 14:29:00 2020 +0800
+
+    video: fbdev: radeon: Fix memleak in radeonfb_pci_register
+    
+    When radeon_kick_out_firmware_fb() fails, info should be
+    freed just like the subsequent error paths.
+    
+    Fixes: 069ee21a82344 ("fbdev: Fix loading of module radeonfb on PowerMac")
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Mathieu Malaterre 
+    Cc: Kangjie Lu 
+    Cc: Benjamin Herrenschmidt 
+    Signed-off-by: Bartlomiej Zolnierkiewicz 
+    Link: https://patchwork.freedesktop.org/patch/msgid/20200825062900.11210-1-dinghao.liu@zju.edu.cn
+
+diff --git a/drivers/video/fbdev/aty/radeon_base.c b/drivers/video/fbdev/aty/radeon_base.c
+index 3fe509cb9b87..13bd2bd5c043 100644
+--- a/drivers/video/fbdev/aty/radeon_base.c
++++ b/drivers/video/fbdev/aty/radeon_base.c
+@@ -2307,7 +2307,7 @@ static int radeonfb_pci_register(struct pci_dev *pdev,
+ 
+ 	ret = radeon_kick_out_firmware_fb(pdev);
+ 	if (ret)
+-		return ret;
++		goto err_release_fb;
+ 
+ 	/* request the mem regions */
+ 	ret = pci_request_region(pdev, 0, "radeonfb framebuffer");

commit c1bca5b5ced0cbd779d56f60cdbc9f5e6f6449fe
+Author: Dinghao Liu 
+Date:   Fri Aug 21 07:49:16 2020 +0200
+
+    media: atomisp: fix memleak in ia_css_stream_create
+    
+    When aspect_ratio_crop_init() fails, curr_stream needs
+    to be freed just like what we've done in the following
+    error paths. However, current code is returning directly
+    and ends up leaking memory.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c
+index 54434c2dbaf9..8473e1437074 100644
+--- a/drivers/staging/media/atomisp/pci/sh_css.c
++++ b/drivers/staging/media/atomisp/pci/sh_css.c
+@@ -9521,7 +9521,7 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config,
+ 	if (err)
+ 	{
+ 		IA_CSS_LEAVE_ERR(err);
+-		return err;
++		goto ERR;
+ 	}
+ #endif
+ 	for (i = 0; i < num_pipes; i++)

commit 857a3139bd8be4f702c030c8ca06f3fd69c1741a
+Author: Dinghao Liu 
+Date:   Wed Aug 26 20:14:37 2020 +0800
+
+    EDAC/i5100: Fix error handling order in i5100_init_one()
+    
+    When pci_get_device_func() fails, the driver doesn't need to execute
+    pci_dev_put(). mci should still be freed, though, to prevent a memory
+    leak. When pci_enable_device() fails, the error injection PCI device
+    "einj" doesn't need to be disabled either.
+    
+     [ bp: Massage commit message, rename label to "bail_mc_free". ]
+    
+    Fixes: 52608ba205461 ("i5100_edac: probe for device 19 function 0")
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Borislav Petkov 
+    Link: https://lkml.kernel.org/r/20200826121437.31606-1-dinghao.liu@zju.edu.cn
+
+diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c
+index 191aa7c19ded..324a46b8479b 100644
+--- a/drivers/edac/i5100_edac.c
++++ b/drivers/edac/i5100_edac.c
+@@ -1061,16 +1061,15 @@ static int i5100_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 				    PCI_DEVICE_ID_INTEL_5100_19, 0);
+ 	if (!einj) {
+ 		ret = -ENODEV;
+-		goto bail_einj;
++		goto bail_mc_free;
+ 	}
+ 
+ 	rc = pci_enable_device(einj);
+ 	if (rc < 0) {
+ 		ret = rc;
+-		goto bail_disable_einj;
++		goto bail_einj;
+ 	}
+ 
+-
+ 	mci->pdev = &pdev->dev;
+ 
+ 	priv = mci->pvt_info;
+@@ -1136,14 +1135,14 @@ static int i5100_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ bail_scrub:
+ 	priv->scrub_enable = 0;
+ 	cancel_delayed_work_sync(&(priv->i5100_scrubbing));
+-	edac_mc_free(mci);
+-
+-bail_disable_einj:
+ 	pci_disable_device(einj);
+ 
+ bail_einj:
+ 	pci_dev_put(einj);
+ 
++bail_mc_free:
++	edac_mc_free(mci);
++
+ bail_disable_ch1:
+ 	pci_disable_device(ch1mm);
+ 

commit f7ec68b341dbd5da13d4c65ce444dcd605f1c42e
+Author: Dinghao Liu 
+Date:   Wed Aug 19 16:22:28 2020 +0800
+
+    drm/crc-debugfs: Fix memleak in crc_control_write
+    
+    When verify_crc_source() fails, source needs to be freed.
+    However, current code is returning directly and ends up
+    leaking memory.
+    
+    Fixes: d5cc15a0c66e ("drm: crc: Introduce verify_crc_source callback")
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Laurent Pinchart 
+    [danvet: change Fixes: tag per Laurent's review]
+    Signed-off-by: Daniel Vetter 
+    Link: https://patchwork.freedesktop.org/patch/msgid/20200819082228.26847-1-dinghao.liu@zju.edu.cn
+
+diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c
+index 5d67a41f7c3a..3dd70d813f69 100644
+--- a/drivers/gpu/drm/drm_debugfs_crc.c
++++ b/drivers/gpu/drm/drm_debugfs_crc.c
+@@ -144,8 +144,10 @@ static ssize_t crc_control_write(struct file *file, const char __user *ubuf,
+ 		source[len - 1] = '\0';
+ 
+ 	ret = crtc->funcs->verify_crc_source(crtc, source, &values_cnt);
+-	if (ret)
++	if (ret) {
++		kfree(source);
+ 		return ret;
++	}
+ 
+ 	spin_lock_irq(&crc->lock);
+ 

commit b7429ea53d6c0936a0f10a5d64164f0aea440143
+Author: Dinghao Liu 
+Date:   Mon Aug 31 17:06:43 2020 +0800
+
+    HID: elan: Fix memleak in elan_input_configured
+    
+    When input_mt_init_slots() fails, input should be freed
+    to prevent memleak. When input_register_device() fails,
+    we should call input_mt_destroy_slots() to free memory
+    allocated by input_mt_init_slots().
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/hid-elan.c b/drivers/hid/hid-elan.c
+index 45c4f888b7c4..dae193749d44 100644
+--- a/drivers/hid/hid-elan.c
++++ b/drivers/hid/hid-elan.c
+@@ -188,6 +188,7 @@ static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi)
+ 	ret = input_mt_init_slots(input, ELAN_MAX_FINGERS, INPUT_MT_POINTER);
+ 	if (ret) {
+ 		hid_err(hdev, "Failed to init elan MT slots: %d\n", ret);
++		input_free_device(input);
+ 		return ret;
+ 	}
+ 
+@@ -198,6 +199,7 @@ static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi)
+ 	if (ret) {
+ 		hid_err(hdev, "Failed to register elan input device: %d\n",
+ 			ret);
++		input_mt_destroy_slots(input);
+ 		input_free_device(input);
+ 		return ret;
+ 	}

commit ea403fde7552bd61bad6ea45e3feb99db77cb31e
+Author: Dinghao Liu 
+Date:   Sun Aug 23 17:14:53 2020 +0800
+
+    scsi: pm8001: Fix memleak in pm8001_exec_internal_task_abort
+    
+    When pm8001_tag_alloc() fails, task should be freed just like it is done in
+    the subsequent error paths.
+    
+    Link: https://lore.kernel.org/r/20200823091453.4782-1-dinghao.liu@zju.edu.cn
+    Acked-by: Jack Wang 
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
+index 337e79d6837f..9889bab7d31c 100644
+--- a/drivers/scsi/pm8001/pm8001_sas.c
++++ b/drivers/scsi/pm8001/pm8001_sas.c
+@@ -818,7 +818,7 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,
+ 
+ 		res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
+ 		if (res)
+-			return res;
++			goto ex_err;
+ 		ccb = &pm8001_ha->ccb_info[ccb_tag];
+ 		ccb->device = pm8001_dev;
+ 		ccb->ccb_tag = ccb_tag;

commit d33fe77bdf75806d785dabf90d21d962122e5296
+Author: Dinghao Liu 
+Date:   Sun Aug 23 15:44:21 2020 +0800
+
+    Bluetooth: btusb: Fix memleak in btusb_mtk_submit_wmt_recv_urb
+    
+    When kmalloc() on buf fails, urb should be freed just like
+    when kmalloc() on dr fails.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Marcel Holtmann 
+
+diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
+index 414575eccbad..fe80588c7bd3 100644
+--- a/drivers/bluetooth/btusb.c
++++ b/drivers/bluetooth/btusb.c
+@@ -2896,6 +2896,7 @@ static int btusb_mtk_submit_wmt_recv_urb(struct hci_dev *hdev)
+ 	buf = kmalloc(size, GFP_KERNEL);
+ 	if (!buf) {
+ 		kfree(dr);
++		usb_free_urb(urb);
+ 		return -ENOMEM;
+ 	}
+ 

commit d8eb176d97d3dcb810e19fb067f21bf6b115251a
+Author: Dinghao Liu 
+Date:   Wed Aug 19 19:54:26 2020 +0800
+
+    staging: wilc1000: Fix memleak in wilc_bus_probe
+    
+    When devm_clk_get() returns -EPROBE_DEFER, spi_priv
+    should be freed just like when wilc_cfg80211_init()
+    fails.
+    
+    Fixes: 854d66df74aed ("staging: wilc1000: look for rtc_clk clock in spi mode")
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20200819115426.29852-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/net/wireless/microchip/wilc1000/spi.c b/drivers/net/wireless/microchip/wilc1000/spi.c
+index 3f19e3f38a39..a18dac0aa6b6 100644
+--- a/drivers/net/wireless/microchip/wilc1000/spi.c
++++ b/drivers/net/wireless/microchip/wilc1000/spi.c
+@@ -112,9 +112,10 @@ static int wilc_bus_probe(struct spi_device *spi)
+ 	wilc->dev_irq_num = spi->irq;
+ 
+ 	wilc->rtc_clk = devm_clk_get(&spi->dev, "rtc_clk");
+-	if (PTR_ERR_OR_ZERO(wilc->rtc_clk) == -EPROBE_DEFER)
++	if (PTR_ERR_OR_ZERO(wilc->rtc_clk) == -EPROBE_DEFER) {
++		kfree(spi_priv);
+ 		return -EPROBE_DEFER;
+-	else if (!IS_ERR(wilc->rtc_clk))
++	} else if (!IS_ERR(wilc->rtc_clk))
+ 		clk_prepare_enable(wilc->rtc_clk);
+ 
+ 	return 0;

commit b7a4f80bc316a56d6ec8750e93e66f42431ed960
+Author: dinghao.liu@zju.edu.cn 
+Date:   Thu Aug 20 14:38:17 2020 +0800
+
+    backlight: sky81452-backlight: Fix refcount imbalance on error
+    
+    When of_property_read_u32_array() returns an error code, a
+    pairing refcount decrement is needed to keep np's refcount
+    balanced.
+    
+    Fixes: f705806c9f355 ("backlight: Add support Skyworks SKY81452 backlight driver")
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Daniel Thompson 
+    Signed-off-by: Lee Jones 
+
+diff --git a/drivers/video/backlight/sky81452-backlight.c b/drivers/video/backlight/sky81452-backlight.c
+index 0ce181585008..8268ac43d54f 100644
+--- a/drivers/video/backlight/sky81452-backlight.c
++++ b/drivers/video/backlight/sky81452-backlight.c
+@@ -217,6 +217,7 @@ static struct sky81452_bl_platform_data *sky81452_bl_parse_dt(
+ 					num_entry);
+ 		if (ret < 0) {
+ 			dev_err(dev, "led-sources node is invalid.\n");
++			of_node_put(np);
+ 			return ERR_PTR(-EINVAL);
+ 		}
+ 

commit b7b57a5643c2ae45afe6aa5e73363b553cacd14b
+Author: dinghao.liu@zju.edu.cn 
+Date:   Fri Aug 21 16:15:13 2020 +0800
+
+    crypto: ccree - fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter
+    even when it returns an error code. However, users of cc_pm_get(),
+    a direct wrapper of pm_runtime_get_sync(), assume that PM usage
+    counter will not change on error. Thus a pairing decrement is needed
+    on the error handling path to keep the counter balanced.
+    
+    Fixes: 8c7849a30255c ("crypto: ccree - simplify Runtime PM handling")
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Herbert Xu 
+
+diff --git a/drivers/crypto/ccree/cc_pm.c b/drivers/crypto/ccree/cc_pm.c
+index d39e1664fc7e..3c65bf070c90 100644
+--- a/drivers/crypto/ccree/cc_pm.c
++++ b/drivers/crypto/ccree/cc_pm.c
+@@ -65,8 +65,12 @@ const struct dev_pm_ops ccree_pm = {
+ int cc_pm_get(struct device *dev)
+ {
+ 	int rc = pm_runtime_get_sync(dev);
++	if (rc < 0) {
++		pm_runtime_put_noidle(dev);
++		return rc;
++	}
+ 
+-	return (rc == 1 ? 0 : rc);
++	return 0;
+ }
+ 
+ void cc_pm_put_suspend(struct device *dev)

commit b43c75abfd084b9e961a47c6331e01f2f91176b6
+Author: Dinghao Liu 
+Date:   Thu Aug 27 16:55:46 2020 +0100
+
+    rxrpc: Fix memory leak in rxkad_verify_response()
+    
+    Fix a memory leak in rxkad_verify_response() whereby the response buffer
+    doesn't get freed if we fail to allocate a ticket buffer.
+    
+    Fixes: ef68622da9cc ("rxrpc: Handle temporary errors better in rxkad security")
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: David Howells 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
+index 52a24d4ef5d8..e08130e5746b 100644
+--- a/net/rxrpc/rxkad.c
++++ b/net/rxrpc/rxkad.c
+@@ -1137,7 +1137,7 @@ static int rxkad_verify_response(struct rxrpc_connection *conn,
+ 	ret = -ENOMEM;
+ 	ticket = kmalloc(ticket_len, GFP_NOFS);
+ 	if (!ticket)
+-		goto temporary_error;
++		goto temporary_error_free_resp;
+ 
+ 	eproto = tracepoint_string("rxkad_tkt_short");
+ 	abort_code = RXKADPACKETSHORT;
+@@ -1230,6 +1230,7 @@ static int rxkad_verify_response(struct rxrpc_connection *conn,
+ 
+ temporary_error_free_ticket:
+ 	kfree(ticket);
++temporary_error_free_resp:
+ 	kfree(response);
+ temporary_error:
+ 	/* Ignore the response packet if we got a temporary error such as

commit e3ddd6067ee62f6e76ebcf61ff08b2c729ae412b
+Author: Dinghao Liu 
+Date:   Wed Aug 19 15:56:32 2020 +0800
+
+    RDMA/rxe: Fix memleak in rxe_mem_init_user
+    
+    When page_address() fails, umem should be freed just like when
+    rxe_mem_alloc() fails.
+    
+    Fixes: 8700e3e7c485 ("Soft RoCE driver")
+    Link: https://lore.kernel.org/r/20200819075632.22285-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Jason Gunthorpe 
+
+diff --git a/drivers/infiniband/sw/rxe/rxe_mr.c b/drivers/infiniband/sw/rxe/rxe_mr.c
+index cdd811a45120..ce24144de16a 100644
+--- a/drivers/infiniband/sw/rxe/rxe_mr.c
++++ b/drivers/infiniband/sw/rxe/rxe_mr.c
+@@ -205,6 +205,7 @@ int rxe_mem_init_user(struct rxe_pd *pd, u64 start,
+ 			vaddr = page_address(sg_page_iter_page(&sg_iter));
+ 			if (!vaddr) {
+ 				pr_warn("null vaddr\n");
++				ib_umem_release(umem);
+ 				err = -ENOMEM;
+ 				goto err1;
+ 			}

commit 9a19a939abfa7d949f584a7ad872e683473fdc14
+Author: Dinghao Liu 
+Date:   Thu Aug 20 13:52:56 2020 +0800
+
+    wilc1000: Fix memleak in wilc_bus_probe
+    
+    When devm_clk_get() returns -EPROBE_DEFER, spi_priv
+    should be freed just like when wilc_cfg80211_init()
+    fails.
+    
+    Fixes: 854d66df74aed ("staging: wilc1000: look for rtc_clk clock in spi mode")
+    Signed-off-by: Dinghao Liu 
+    Acked-by: Ajay Singh 
+    Signed-off-by: Kalle Valo 
+    Link: https://lore.kernel.org/r/20200820055256.24333-1-dinghao.liu@zju.edu.cn
+
+diff --git a/drivers/net/wireless/microchip/wilc1000/spi.c b/drivers/net/wireless/microchip/wilc1000/spi.c
+index 3f19e3f38a39..a18dac0aa6b6 100644
+--- a/drivers/net/wireless/microchip/wilc1000/spi.c
++++ b/drivers/net/wireless/microchip/wilc1000/spi.c
+@@ -112,9 +112,10 @@ static int wilc_bus_probe(struct spi_device *spi)
+ 	wilc->dev_irq_num = spi->irq;
+ 
+ 	wilc->rtc_clk = devm_clk_get(&spi->dev, "rtc_clk");
+-	if (PTR_ERR_OR_ZERO(wilc->rtc_clk) == -EPROBE_DEFER)
++	if (PTR_ERR_OR_ZERO(wilc->rtc_clk) == -EPROBE_DEFER) {
++		kfree(spi_priv);
+ 		return -EPROBE_DEFER;
+-	else if (!IS_ERR(wilc->rtc_clk))
++	} else if (!IS_ERR(wilc->rtc_clk))
+ 		clk_prepare_enable(wilc->rtc_clk);
+ 
+ 	return 0;

commit 8d95ab34b21ee0f870a9185b6457e8f6eb54914c
+Author: Dinghao Liu 
+Date:   Thu Aug 20 13:48:19 2020 +0800
+
+    wilc1000: Fix memleak in wilc_sdio_probe
+    
+    When devm_clk_get() returns -EPROBE_DEFER, sdio_priv
+    should be freed just like when wilc_cfg80211_init()
+    fails.
+    
+    Fixes: 8692b047e86cf ("staging: wilc1000: look for rtc_clk clock")
+    Signed-off-by: Dinghao Liu 
+    Acked-by: Ajay Singh 
+    Signed-off-by: Kalle Valo 
+    Link: https://lore.kernel.org/r/20200820054819.23365-1-dinghao.liu@zju.edu.cn
+
+diff --git a/drivers/net/wireless/microchip/wilc1000/sdio.c b/drivers/net/wireless/microchip/wilc1000/sdio.c
+index 3ece7b0b0392..351ff909ab1c 100644
+--- a/drivers/net/wireless/microchip/wilc1000/sdio.c
++++ b/drivers/net/wireless/microchip/wilc1000/sdio.c
+@@ -149,9 +149,10 @@ static int wilc_sdio_probe(struct sdio_func *func,
+ 	wilc->dev = &func->dev;
+ 
+ 	wilc->rtc_clk = devm_clk_get(&func->card->dev, "rtc");
+-	if (PTR_ERR_OR_ZERO(wilc->rtc_clk) == -EPROBE_DEFER)
++	if (PTR_ERR_OR_ZERO(wilc->rtc_clk) == -EPROBE_DEFER) {
++		kfree(sdio_priv);
+ 		return -EPROBE_DEFER;
+-	else if (!IS_ERR(wilc->rtc_clk))
++	} else if (!IS_ERR(wilc->rtc_clk))
+ 		clk_prepare_enable(wilc->rtc_clk);
+ 
+ 	dev_info(&func->dev, "Driver Initializing success\n");

commit 08572451b4b1783fdff787b0188c4d50fdf96b81
+Author: Dinghao Liu 
+Date:   Wed Aug 26 21:24:58 2020 +0800
+
+    drm/amd/display: Fix memleak in amdgpu_dm_mode_config_init
+    
+    When amdgpu_display_modeset_create_props() fails, state and
+    state->context should be freed to prevent memleak. It's the
+    same when amdgpu_dm_audio_init() fails.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Alex Deucher 
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 785f21ea35df..e2e7138c4e3f 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -2905,12 +2905,18 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)
+ 				    &dm_atomic_state_funcs);
+ 
+ 	r = amdgpu_display_modeset_create_props(adev);
+-	if (r)
++	if (r) {
++		dc_release_state(state->context);
++		kfree(state);
+ 		return r;
++	}
+ 
+ 	r = amdgpu_dm_audio_init(adev);
+-	if (r)
++	if (r) {
++		dc_release_state(state->context);
++		kfree(state);
+ 		return r;
++	}
+ 
+ 	return 0;
+ }

commit b67a468a4ccef593cd8df6a02ba3d167b77f0c81
+Author: Dinghao Liu 
+Date:   Wed Aug 26 21:24:58 2020 +0800
+
+    drm/amd/display: Fix memleak in amdgpu_dm_mode_config_init
+    
+    When amdgpu_display_modeset_create_props() fails, state and
+    state->context should be freed to prevent memleak. It's the
+    same when amdgpu_dm_audio_init() fails.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Alex Deucher 
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 778edf427b94..b51c527a3f0d 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -2834,12 +2834,18 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)
+ 				    &dm_atomic_state_funcs);
+ 
+ 	r = amdgpu_display_modeset_create_props(adev);
+-	if (r)
++	if (r) {
++		dc_release_state(state->context);
++		kfree(state);
+ 		return r;
++	}
+ 
+ 	r = amdgpu_dm_audio_init(adev);
+-	if (r)
++	if (r) {
++		dc_release_state(state->context);
++		kfree(state);
+ 		return r;
++	}
+ 
+ 	return 0;
+ }

commit c1e6414cdc371f9ed82cefebba7538499a3059f9
+Author: Dinghao Liu 
+Date:   Thu Aug 20 12:28:27 2020 +0800
+
+    ASoC: qcom: common: Fix refcount imbalance on error
+    
+    for_each_child_of_node returns a node pointer np with
+    refcount incremented. So when devm_kzalloc fails, a
+    pairing refcount decrement is needed to keep np's
+    refcount balanced.
+    
+    Fixes: 16395ceee11f8 ("ASoC: qcom: common: Fix NULL pointer in of parser")
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20200820042828.10308-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c
+index 5194d90ddb96..fd69cf8b1f23 100644
+--- a/sound/soc/qcom/common.c
++++ b/sound/soc/qcom/common.c
+@@ -52,8 +52,10 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
+ 
+ 	for_each_child_of_node(dev->of_node, np) {
+ 		dlc = devm_kzalloc(dev, 2 * sizeof(*dlc), GFP_KERNEL);
+-		if (!dlc)
+-			return -ENOMEM;
++		if (!dlc) {
++			ret = -ENOMEM;
++			goto err;
++		}
+ 
+ 		link->cpus	= &dlc[0];
+ 		link->platforms	= &dlc[1];

commit 15ac5cdafb9202424206dc5bd376437a358963f9
+Author: Dinghao Liu 
+Date:   Sun Aug 23 19:29:35 2020 +0800
+
+    firestream: Fix memleak in fs_open
+    
+    When make_rate() fails, vcc should be freed just
+    like other error paths in fs_open().
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c
+index 2ca9ec802734..510250cf5c87 100644
+--- a/drivers/atm/firestream.c
++++ b/drivers/atm/firestream.c
+@@ -998,6 +998,7 @@ static int fs_open(struct atm_vcc *atm_vcc)
+ 				error = make_rate (pcr, r, &tmc0, NULL);
+ 				if (error) {
+ 					kfree(tc);
++					kfree(vcc);
+ 					return error;
+ 				}
+ 			}

commit e2d79cd8875fa8c3cc7defa98a8cc99a1ed0c62f
+Author: Dinghao Liu 
+Date:   Sun Aug 23 16:56:47 2020 +0800
+
+    net: arc_emac: Fix memleak in arc_mdio_probe
+    
+    When devm_gpiod_get_optional() fails, bus should be
+    freed just like when of_mdiobus_register() fails.
+    
+    Fixes: 1bddd96cba03d ("net: arc_emac: support the phy reset for emac driver")
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Andrew Lunn 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/arc/emac_mdio.c b/drivers/net/ethernet/arc/emac_mdio.c
+index 0187dbf3b87d..54cdafdd067d 100644
+--- a/drivers/net/ethernet/arc/emac_mdio.c
++++ b/drivers/net/ethernet/arc/emac_mdio.c
+@@ -153,6 +153,7 @@ int arc_mdio_probe(struct arc_emac_priv *priv)
+ 	if (IS_ERR(data->reset_gpio)) {
+ 		error = PTR_ERR(data->reset_gpio);
+ 		dev_err(priv->dev, "Failed to request gpio: %d\n", error);
++		mdiobus_free(bus);
+ 		return error;
+ 	}
+ 

commit f97c04c316d8fea16dca449fdfbe101fbdfee6a2
+Author: Dinghao Liu 
+Date:   Sun Aug 23 15:23:43 2020 +0800
+
+    NFC: st95hf: Fix memleak in st95hf_in_send_cmd
+    
+    When down_killable() fails, skb_resp should be freed
+    just like when st95hf_spi_send() fails.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/nfc/st95hf/core.c b/drivers/nfc/st95hf/core.c
+index 9642971e89ce..457854765983 100644
+--- a/drivers/nfc/st95hf/core.c
++++ b/drivers/nfc/st95hf/core.c
+@@ -966,7 +966,7 @@ static int st95hf_in_send_cmd(struct nfc_digital_dev *ddev,
+ 	rc = down_killable(&stcontext->exchange_lock);
+ 	if (rc) {
+ 		WARN(1, "Semaphore is not found up in st95hf_in_send_cmd\n");
+-		return rc;
++		goto free_skb_resp;
+ 	}
+ 
+ 	rc = st95hf_spi_send(&stcontext->spicontext, skb->data,

commit dbb8df5c2d27610a87b0168a8acc89d73fbfde94
+Author: Dinghao Liu 
+Date:   Sun Aug 23 14:55:12 2020 +0800
+
+    ntb: intel: Fix memleak in intel_ntb_pci_probe
+    
+    The default error branch of a series of pdev_is_gen calls
+    should free ndev just like what we've done in these calls.
+    
+    Fixes: 26bfe3d0b227 ("ntb: intel: Add Icelake (gen4) support for Intel NTB")
+    Signed-off-by: Dinghao Liu 
+    Acked-by: Dave Jiang 
+    Signed-off-by: Jon Mason 
+
+diff --git a/drivers/ntb/hw/intel/ntb_hw_gen1.c b/drivers/ntb/hw/intel/ntb_hw_gen1.c
+index 3185efeab487..093dd20057b9 100644
+--- a/drivers/ntb/hw/intel/ntb_hw_gen1.c
++++ b/drivers/ntb/hw/intel/ntb_hw_gen1.c
+@@ -1893,7 +1893,7 @@ static int intel_ntb_pci_probe(struct pci_dev *pdev,
+ 			goto err_init_dev;
+ 	} else {
+ 		rc = -EINVAL;
+-		goto err_ndev;
++		goto err_init_pci;
+ 	}
+ 
+ 	ndev_reset_unsafe_flags(ndev);

commit 7ef1fc57301f3cef7201497aa27e89ccb91737fe
+Author: Dinghao Liu 
+Date:   Mon Aug 24 13:58:31 2020 +0800
+
+    net: systemport: Fix memleak in bcm_sysport_probe
+    
+    When devm_kcalloc() fails, dev should be freed just
+    like what we've done in the subsequent error paths.
+    
+    Fixes: 7b78be48a8eb6 ("net: systemport: Dynamically allocate number of TX rings")
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
+index dfed9ade6950..0762d5d1a810 100644
+--- a/drivers/net/ethernet/broadcom/bcmsysport.c
++++ b/drivers/net/ethernet/broadcom/bcmsysport.c
+@@ -2491,8 +2491,10 @@ static int bcm_sysport_probe(struct platform_device *pdev)
+ 	priv->tx_rings = devm_kcalloc(&pdev->dev, txq,
+ 				      sizeof(struct bcm_sysport_tx_ring),
+ 				      GFP_KERNEL);
+-	if (!priv->tx_rings)
+-		return -ENOMEM;
++	if (!priv->tx_rings) {
++		ret = -ENOMEM;
++		goto err_free_netdev;
++	}
+ 
+ 	priv->is_lite = params->is_lite;
+ 	priv->num_rx_desc_words = params->num_rx_desc_words;

commit 100e3345c6e719d2291e1efd5de311cc24bb9c0b
+Author: Dinghao Liu 
+Date:   Mon Aug 24 13:44:42 2020 +0800
+
+    net: hns: Fix memleak in hns_nic_dev_probe
+    
+    hns_nic_dev_probe allocates ndev, but not free it on
+    two error handling paths, which may lead to memleak.
+    
+    Fixes: 63434888aaf1b ("net: hns: net: hns: enet adds support of acpi")
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+index 23f278e46975..22522f8a5299 100644
+--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
++++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+@@ -2282,8 +2282,10 @@ static int hns_nic_dev_probe(struct platform_device *pdev)
+ 			priv->enet_ver = AE_VERSION_1;
+ 		else if (acpi_dev_found(hns_enet_acpi_match[1].id))
+ 			priv->enet_ver = AE_VERSION_2;
+-		else
+-			return -ENXIO;
++		else {
++			ret = -ENXIO;
++			goto out_read_prop_fail;
++		}
+ 
+ 		/* try to find port-idx-in-ae first */
+ 		ret = acpi_node_get_property_reference(dev->fwnode,
+@@ -2299,7 +2301,8 @@ static int hns_nic_dev_probe(struct platform_device *pdev)
+ 		priv->fwnode = args.fwnode;
+ 	} else {
+ 		dev_err(dev, "cannot read cfg data from OF or acpi\n");
+-		return -ENXIO;
++		ret = -ENXIO;
++		goto out_read_prop_fail;
+ 	}
+ 
+ 	ret = device_property_read_u32(dev, "port-idx-in-ae", &port_id);

commit bbe516e976fce538db96bd2b7287df942faa14a3
+Author: Dinghao Liu 
+Date:   Sun Jun 28 07:55:23 2020 +0200
+
+    media: venus: core: Fix runtime PM imbalance in venus_probe
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced. For other error
+    paths after this call, things are the same.
+    
+    Fix this by adding pm_runtime_put_noidle() after 'err_runtime_disable'
+    label. But in this case, the error path after pm_runtime_put_sync()
+    will decrease PM usage counter twice. Thus add an extra
+    pm_runtime_get_noresume() in this path to balance PM counter.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c
+index 203c6538044f..b0b932bf8c02 100644
+--- a/drivers/media/platform/qcom/venus/core.c
++++ b/drivers/media/platform/qcom/venus/core.c
+@@ -287,8 +287,10 @@ static int venus_probe(struct platform_device *pdev)
+ 		goto err_core_deinit;
+ 
+ 	ret = pm_runtime_put_sync(dev);
+-	if (ret)
++	if (ret) {
++		pm_runtime_get_noresume(dev);
+ 		goto err_dev_unregister;
++	}
+ 
+ 	return 0;
+ 
+@@ -299,6 +301,7 @@ static int venus_probe(struct platform_device *pdev)
+ err_venus_shutdown:
+ 	venus_shutdown(core);
+ err_runtime_disable:
++	pm_runtime_put_noidle(dev);
+ 	pm_runtime_set_suspended(dev);
+ 	pm_runtime_disable(dev);
+ 	hfi_destroy(core);

commit 062fa09f44f4fb3776a23184d5d296b0c8872eb9
+Author: Dinghao Liu 
+Date:   Thu Aug 13 16:41:10 2020 +0800
+
+    ASoC: intel: Fix memleak in sst_media_open
+    
+    When power_up_sst() fails, stream needs to be freed
+    just like when try_module_get() fails. However, current
+    code is returning directly and ends up leaking memory.
+    
+    Fixes: 0121327c1a68b ("ASoC: Intel: mfld-pcm: add control for powering up/down dsp")
+    Signed-off-by: Dinghao Liu 
+    Acked-by: Pierre-Louis Bossart 
+    Link: https://lore.kernel.org/r/20200813084112.26205-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
+index 49b9f18472bc..b1cac7abdc0a 100644
+--- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c
++++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
+@@ -331,7 +331,7 @@ static int sst_media_open(struct snd_pcm_substream *substream,
+ 
+ 	ret_val = power_up_sst(stream);
+ 	if (ret_val < 0)
+-		return ret_val;
++		goto out_power_up;
+ 
+ 	/* Make sure, that the period size is always even */
+ 	snd_pcm_hw_constraint_step(substream->runtime, 0,
+@@ -340,8 +340,9 @@ static int sst_media_open(struct snd_pcm_substream *substream,
+ 	return snd_pcm_hw_constraint_integer(runtime,
+ 			 SNDRV_PCM_HW_PARAM_PERIODS);
+ out_ops:
+-	kfree(stream);
+ 	mutex_unlock(&sst_lock);
++out_power_up:
++	kfree(stream);
+ 	return ret_val;
+ }
+ 

commit 5a25de6df789cc805a9b8ba7ab5deef5067af47e
+Author: Dinghao Liu 
+Date:   Thu Aug 13 15:46:30 2020 +0800
+
+    ALSA: echoaudio: Fix potential Oops in snd_echo_resume()
+    
+    Freeing chip on error may lead to an Oops at the next time
+    the system goes to resume. Fix this by removing all
+    snd_echo_free() calls on error.
+    
+    Fixes: 47b5d028fdce8 ("ALSA: Echoaudio - Add suspend support #2")
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20200813074632.17022-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
+index 1b7a67ccabce..a20b2bb5c898 100644
+--- a/sound/pci/echoaudio/echoaudio.c
++++ b/sound/pci/echoaudio/echoaudio.c
+@@ -2212,7 +2212,6 @@ static int snd_echo_resume(struct device *dev)
+ 	if (err < 0) {
+ 		kfree(commpage_bak);
+ 		dev_err(dev, "resume init_hw err=%d\n", err);
+-		snd_echo_free(chip);
+ 		return err;
+ 	}
+ 
+@@ -2239,7 +2238,6 @@ static int snd_echo_resume(struct device *dev)
+ 	if (request_irq(pci->irq, snd_echo_interrupt, IRQF_SHARED,
+ 			KBUILD_MODNAME, chip)) {
+ 		dev_err(chip->card->dev, "cannot grab irq\n");
+-		snd_echo_free(chip);
+ 		return -EBUSY;
+ 	}
+ 	chip->irq = pci->irq;

commit 11536442a3b4e1de6890ea5e805908debb74f94a
+Author: Dinghao Liu 
+Date:   Tue Jul 28 15:21:51 2020 +0800
+
+    Staging: rtl8188eu: rtw_mlme: Fix uninitialized variable authmode
+    
+    The variable authmode can be uninitialized. The danger would be if
+    it equals to _WPA_IE_ID_ (0xdd) or _WPA2_IE_ID_ (0x33). We can avoid
+    this by setting it to zero instead. This is the approach that was
+    used in the rtl8723bs driver.
+    
+    Fixes: 7b464c9fa5cc ("staging: r8188eu: Add files for new driver - part 4")
+    Co-developed-by: Dan Carpenter 
+    Signed-off-by: Dan Carpenter 
+    Signed-off-by: Dinghao Liu 
+    Cc: stable 
+    Link: https://lore.kernel.org/r/20200728072153.9202-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c
+index 5d7a749f1aac..d334dc335914 100644
+--- a/drivers/staging/rtl8188eu/core/rtw_mlme.c
++++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c
+@@ -1729,9 +1729,11 @@ int rtw_restruct_sec_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_
+ 	if ((ndisauthmode == Ndis802_11AuthModeWPA) ||
+ 	    (ndisauthmode == Ndis802_11AuthModeWPAPSK))
+ 		authmode = _WPA_IE_ID_;
+-	if ((ndisauthmode == Ndis802_11AuthModeWPA2) ||
++	else if ((ndisauthmode == Ndis802_11AuthModeWPA2) ||
+ 	    (ndisauthmode == Ndis802_11AuthModeWPA2PSK))
+ 		authmode = _WPA2_IE_ID_;
++	else
++		authmode = 0x0;
+ 
+ 	if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
+ 		memcpy(out_ie + ielength, psecuritypriv->wps_ie, psecuritypriv->wps_ie_len);

commit a68e06e729b1b06c50ee52917d6b825b43e7d269
+Author: Dinghao Liu 
+Date:   Thu Jul 9 14:43:56 2020 +0800
+
+    PCI: rcar: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when the call returns an error code. Thus a corresponding decrement is
+    needed on the error handling path to keep the counter balanced.
+    
+    Link: https://lore.kernel.org/r/20200709064356.8800-1-dinghao.liu@zju.edu.cn
+    Fixes: 0df6150e7ceb ("PCI: rcar: Use runtime PM to control controller clock")
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Lorenzo Pieralisi 
+    Reviewed-by: Yoshihiro Shimoda 
+
+diff --git a/drivers/pci/controller/pcie-rcar-host.c b/drivers/pci/controller/pcie-rcar-host.c
+index d210a36561be..060c24f5221e 100644
+--- a/drivers/pci/controller/pcie-rcar-host.c
++++ b/drivers/pci/controller/pcie-rcar-host.c
+@@ -986,7 +986,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)
+ 	err = pm_runtime_get_sync(pcie->dev);
+ 	if (err < 0) {
+ 		dev_err(pcie->dev, "pm_runtime_get_sync failed\n");
+-		goto err_pm_disable;
++		goto err_pm_put;
+ 	}
+ 
+ 	err = rcar_pcie_get_resources(host);
+@@ -1057,8 +1057,6 @@ static int rcar_pcie_probe(struct platform_device *pdev)
+ 
+ err_pm_put:
+ 	pm_runtime_put(dev);
+-
+-err_pm_disable:
+ 	pm_runtime_disable(dev);
+ 	pci_free_resource_list(&host->resources);
+ 

commit cb52a40202420d3886b84ea13dba699c9da13eb0
+Author: Dinghao Liu 
+Date:   Tue Jul 7 13:50:00 2020 +0800
+
+    PCI: qcom: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code, thus a matching decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Link: https://lore.kernel.org/r/20200707055000.9453-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Lorenzo Pieralisi 
+
+diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
+index 138e1a2d21cc..12abdfbff5ca 100644
+--- a/drivers/pci/controller/dwc/pcie-qcom.c
++++ b/drivers/pci/controller/dwc/pcie-qcom.c
+@@ -1339,10 +1339,8 @@ static int qcom_pcie_probe(struct platform_device *pdev)
+ 
+ 	pm_runtime_enable(dev);
+ 	ret = pm_runtime_get_sync(dev);
+-	if (ret < 0) {
+-		pm_runtime_disable(dev);
+-		return ret;
+-	}
++	if (ret < 0)
++		goto err_pm_runtime_put;
+ 
+ 	pci->dev = dev;
+ 	pci->ops = &dw_pcie_ops;

commit 7a790087c1ad110d1f4019021342d9ec55aead14
+Author: Dinghao Liu 
+Date:   Wed May 20 17:02:53 2020 +0800
+
+    PCI: cadence: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Link: https://lore.kernel.org/r/20200520090253.2761-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Lorenzo Pieralisi 
+
+diff --git a/drivers/pci/controller/cadence/pcie-cadence-plat.c b/drivers/pci/controller/cadence/pcie-cadence-plat.c
+index f5c6bf6dfcb8..33c3868e6dbd 100644
+--- a/drivers/pci/controller/cadence/pcie-cadence-plat.c
++++ b/drivers/pci/controller/cadence/pcie-cadence-plat.c
+@@ -115,9 +115,8 @@ static int cdns_plat_pcie_probe(struct platform_device *pdev)
+ 	}
+ 
+  err_init:
+-	pm_runtime_put_sync(dev);
+-
+  err_get_sync:
++	pm_runtime_put_sync(dev);
+ 	pm_runtime_disable(dev);
+ 	cdns_pcie_disable_phy(cdns_plat_pcie->pcie);
+ 	phy_count = cdns_plat_pcie->pcie->phy_count;

commit c2615d620a852adf43d425dea81eb854c8673cfd
+Author: Dinghao Liu 
+Date:   Wed May 20 16:47:56 2020 +0800
+
+    PCI: dwc: pci-dra7xx: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Link: https://lore.kernel.org/r/20200520084756.31620-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Lorenzo Pieralisi 
+
+diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c b/drivers/pci/controller/dwc/pci-dra7xx.c
+index 6184ebc9392d..01d821e98f0c 100644
+--- a/drivers/pci/controller/dwc/pci-dra7xx.c
++++ b/drivers/pci/controller/dwc/pci-dra7xx.c
+@@ -998,9 +998,8 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
+ 	return 0;
+ 
+ err_gpio:
+-	pm_runtime_put(dev);
+-
+ err_get_sync:
++	pm_runtime_put(dev);
+ 	pm_runtime_disable(dev);
+ 	dra7xx_pcie_disable_phy(dra7xx);
+ 

commit 831b8755fd2f60cf00cbf854c2a2eccb03f2060b
+Author: Dinghao Liu 
+Date:   Sun May 24 06:31:32 2020 +0200
+
+    media: venus: venc: Fix runtime PM imbalance in venc_open
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Stanimir Varbanov 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c
+index feed648550d1..513bbc07f7bc 100644
+--- a/drivers/media/platform/qcom/venus/venc.c
++++ b/drivers/media/platform/qcom/venus/venc.c
+@@ -1177,7 +1177,7 @@ static int venc_open(struct file *file)
+ 
+ 	ret = pm_runtime_get_sync(core->dev_enc);
+ 	if (ret < 0)
+-		goto err_free_inst;
++		goto err_put_sync;
+ 
+ 	ret = venc_ctrl_init(inst);
+ 	if (ret)
+@@ -1222,7 +1222,6 @@ static int venc_open(struct file *file)
+ 	venc_ctrl_deinit(inst);
+ err_put_sync:
+ 	pm_runtime_put_sync(core->dev_enc);
+-err_free_inst:
+ 	kfree(inst);
+ 	return ret;
+ }

commit 5c3a8a661e1bd9d7063485ac2d2ccb512c447129
+Author: Dinghao Liu 
+Date:   Mon Jun 22 10:40:08 2020 +0800
+
+    crypto: sun8i-ce - Fix runtime PM imbalance in sun8i_ce_cipher_init
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    the call returns an error code. Thus a corresponding decrement is
+    needed on the error handling path to keep the counter balanced.
+    
+    Fix this by adding the missed function call.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Herbert Xu 
+
+diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c
+index a6abb701bfc6..3665a0a2038f 100644
+--- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c
++++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c
+@@ -358,6 +358,7 @@ int sun8i_ce_cipher_init(struct crypto_tfm *tfm)
+ 
+ 	return 0;
+ error_pm:
++	pm_runtime_put_noidle(op->ce->dev);
+ 	crypto_free_sync_skcipher(op->fallback_tfm);
+ 	return err;
+ }

commit 5b78fac4b1ba731cf4177fdbc1e3a4661521bcd0
+Author: Dinghao Liu 
+Date:   Wed Jun 24 14:46:26 2020 +0800
+
+    dmaengine: tegra210-adma: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Jon Hunter 
+    Link: https://lore.kernel.org/r/20200624064626.19855-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Vinod Koul 
+
+diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c
+index db58d7e4f9fe..c5fa2ef74abc 100644
+--- a/drivers/dma/tegra210-adma.c
++++ b/drivers/dma/tegra210-adma.c
+@@ -658,6 +658,7 @@ static int tegra_adma_alloc_chan_resources(struct dma_chan *dc)
+ 
+ 	ret = pm_runtime_get_sync(tdc2dev(tdc));
+ 	if (ret < 0) {
++		pm_runtime_put_noidle(tdc2dev(tdc));
+ 		free_irq(tdc->irq, tdc);
+ 		return ret;
+ 	}
+@@ -869,8 +870,10 @@ static int tegra_adma_probe(struct platform_device *pdev)
+ 	pm_runtime_enable(&pdev->dev);
+ 
+ 	ret = pm_runtime_get_sync(&pdev->dev);
+-	if (ret < 0)
++	if (ret < 0) {
++		pm_runtime_put_noidle(&pdev->dev);
+ 		goto rpm_disable;
++	}
+ 
+ 	ret = tegra_adma_init(tdma);
+ 	if (ret)

commit 52db11f38333f90dcdc9a12a09f9ec990516025d
+Author: Dinghao Liu 
+Date:   Mon May 25 10:19:58 2020 +0200
+
+    media: smiapp: Fix runtime PM imbalance on error
+    
+    When v4l2_async_register_subdev_sensor_common() returns
+    an error code, a pairing runtime PM usage counter
+    decrement is needed to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Sakari Ailus 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
+index 5e4f6a2ef78e..0a8d27481bd1 100644
+--- a/drivers/media/i2c/smiapp/smiapp-core.c
++++ b/drivers/media/i2c/smiapp/smiapp-core.c
+@@ -3103,6 +3103,7 @@ static int smiapp_probe(struct i2c_client *client)
+ 	return 0;
+ 
+ out_disable_runtime_pm:
++	pm_runtime_put_noidle(&client->dev);
+ 	pm_runtime_disable(&client->dev);
+ 
+ out_media_entity_cleanup:

commit 4024d6f601e3c49bae9297930970f68d2621ea1d
+Author: Dinghao Liu 
+Date:   Sat May 23 13:49:17 2020 +0200
+
+    media: vpif: Fix runtime PM imbalance in vpif_probe
+    
+    When platform_get_resource() returns an error code, a
+    pairing runtime PM usage counter decrement is needed
+    to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Lad Prabhakar 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/davinci/vpif.c b/drivers/media/platform/davinci/vpif.c
+index df66461f5d4f..f28c1b27eac6 100644
+--- a/drivers/media/platform/davinci/vpif.c
++++ b/drivers/media/platform/davinci/vpif.c
+@@ -458,6 +458,7 @@ static int vpif_probe(struct platform_device *pdev)
+ 	res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ 	if (!res_irq) {
+ 		dev_warn(&pdev->dev, "Missing IRQ resource.\n");
++		pm_runtime_put(&pdev->dev);
+ 		return -EINVAL;
+ 	}
+ 

commit 4f9b5709cc087337bf02f004f0a238ec7ebda25b
+Author: Dinghao Liu 
+Date:   Sun May 24 04:59:02 2020 +0200
+
+    media: exynos4-is: Fix runtime PM imbalance in fimc_is_probe
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced. For all error
+    paths after pm_runtime_get_sync(), things are the same.
+    
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Sylwester Nawrocki 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/exynos4-is/fimc-is.c b/drivers/media/platform/exynos4-is/fimc-is.c
+index 64148b7e0d98..a474014f0a0f 100644
+--- a/drivers/media/platform/exynos4-is/fimc-is.c
++++ b/drivers/media/platform/exynos4-is/fimc-is.c
+@@ -871,6 +871,7 @@ static int fimc_is_probe(struct platform_device *pdev)
+ err_sd:
+ 	fimc_is_unregister_subdevs(is);
+ err_pm:
++	pm_runtime_put_noidle(dev);
+ 	if (!pm_runtime_enabled(dev))
+ 		fimc_is_runtime_suspend(dev);
+ err_irq:

commit 00b0228061fa2dc0536fbf3355fedf2d447df3bd
+Author: Dinghao Liu 
+Date:   Sun May 24 05:34:04 2020 +0200
+
+    media: exynos4-is: Fix runtime PM imbalance in isp_video_open
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Sylwester Nawrocki 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.c b/drivers/media/platform/exynos4-is/fimc-isp-video.c
+index 15f443fa7208..612b9872afc8 100644
+--- a/drivers/media/platform/exynos4-is/fimc-isp-video.c
++++ b/drivers/media/platform/exynos4-is/fimc-isp-video.c
+@@ -293,6 +293,7 @@ static int isp_video_open(struct file *file)
+ 	if (!ret)
+ 		goto unlock;
+ rel_fh:
++	pm_runtime_put_noidle(&isp->pdev->dev);
+ 	v4l2_fh_release(file);
+ unlock:
+ 	mutex_unlock(&isp->video_lock);

commit 779096916daede26699e75e51b0c3a000410d8ad
+Author: Dinghao Liu 
+Date:   Thu May 21 13:56:07 2020 +0200
+
+    media: camss: vfe: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c
+index a8c542fa647d..fc31c2c169cd 100644
+--- a/drivers/media/platform/qcom/camss/camss-vfe.c
++++ b/drivers/media/platform/qcom/camss/camss-vfe.c
+@@ -1265,12 +1265,12 @@ static int vfe_get(struct vfe_device *vfe)
+ 
+ 		ret = vfe_set_clock_rates(vfe);
+ 		if (ret < 0)
+-			goto error_clocks;
++			goto error_pm_runtime_get;
+ 
+ 		ret = camss_enable_clocks(vfe->nclocks, vfe->clock,
+ 					  vfe->camss->dev);
+ 		if (ret < 0)
+-			goto error_clocks;
++			goto error_pm_runtime_get;
+ 
+ 		ret = vfe_reset(vfe);
+ 		if (ret < 0)
+@@ -1282,7 +1282,7 @@ static int vfe_get(struct vfe_device *vfe)
+ 	} else {
+ 		ret = vfe_check_clock_rates(vfe);
+ 		if (ret < 0)
+-			goto error_clocks;
++			goto error_pm_runtime_get;
+ 	}
+ 	vfe->power_count++;
+ 
+@@ -1293,10 +1293,8 @@ static int vfe_get(struct vfe_device *vfe)
+ error_reset:
+ 	camss_disable_clocks(vfe->nclocks, vfe->clock);
+ 
+-error_clocks:
+-	pm_runtime_put_sync(vfe->camss->dev);
+-
+ error_pm_runtime_get:
++	pm_runtime_put_sync(vfe->camss->dev);
+ 	camss_pm_domain_off(vfe->camss, vfe->id);
+ 
+ error_pm_domain:

commit 606578801afe6ec8bb03f5d494a4bae49a684ef3
+Author: Dinghao Liu 
+Date:   Thu May 21 14:06:21 2020 +0200
+
+    media: camss: ispif: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/qcom/camss/camss-ispif.c b/drivers/media/platform/qcom/camss/camss-ispif.c
+index 1f33b4eb198c..5722e971b184 100644
+--- a/drivers/media/platform/qcom/camss/camss-ispif.c
++++ b/drivers/media/platform/qcom/camss/camss-ispif.c
+@@ -344,8 +344,10 @@ static int ispif_set_power(struct v4l2_subdev *sd, int on)
+ 		}
+ 
+ 		ret = pm_runtime_get_sync(dev);
+-		if (ret < 0)
++		if (ret < 0) {
++			pm_runtime_put_sync(dev);
+ 			goto exit;
++		}
+ 
+ 		ret = camss_enable_clocks(ispif->nclocks, ispif->clock, dev);
+ 		if (ret < 0) {

commit cf7b1c794d2f2362610143375b4156111e35aed5
+Author: Dinghao Liu 
+Date:   Sat May 23 09:36:39 2020 +0200
+
+    media: camss: csid: Fix runtime PM imbalance in csid_set_power
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/qcom/camss/camss-csid.c b/drivers/media/platform/qcom/camss/camss-csid.c
+index a5ae85674ffb..8a247b6f5550 100644
+--- a/drivers/media/platform/qcom/camss/camss-csid.c
++++ b/drivers/media/platform/qcom/camss/camss-csid.c
+@@ -562,8 +562,10 @@ static int csid_set_power(struct v4l2_subdev *sd, int on)
+ 		u32 hw_version;
+ 
+ 		ret = pm_runtime_get_sync(dev);
+-		if (ret < 0)
++		if (ret < 0) {
++			pm_runtime_put_sync(dev);
+ 			return ret;
++		}
+ 
+ 		ret = regulator_enable(csid->vdda);
+ 		if (ret < 0) {

commit 90361693ad8d13a4311fc671903dcedd6ec06940
+Author: Dinghao Liu 
+Date:   Thu May 21 12:17:35 2020 +0200
+
+    media: coda: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
+index 6f41f74d492c..3ab3d976d8ca 100644
+--- a/drivers/media/platform/coda/coda-common.c
++++ b/drivers/media/platform/coda/coda-common.c
+@@ -2653,7 +2653,7 @@ static int coda_open(struct file *file)
+ 
+ 	ret = clk_prepare_enable(dev->clk_per);
+ 	if (ret)
+-		goto err_clk_per;
++		goto err_pm_get;
+ 
+ 	ret = clk_prepare_enable(dev->clk_ahb);
+ 	if (ret)
+@@ -2692,9 +2692,8 @@ static int coda_open(struct file *file)
+ 	clk_disable_unprepare(dev->clk_ahb);
+ err_clk_ahb:
+ 	clk_disable_unprepare(dev->clk_per);
+-err_clk_per:
+-	pm_runtime_put_sync(dev->dev);
+ err_pm_get:
++	pm_runtime_put_sync(dev->dev);
+ 	v4l2_fh_del(&ctx->fh);
+ 	v4l2_fh_exit(&ctx->fh);
+ err_coda_name_init:

commit e40a8770fd147e7c0d5bd8c327d88090480242f2
+Author: Dinghao Liu 
+Date:   Thu May 21 12:22:04 2020 +0200
+
+    media: fimc-capture: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c
+index 705f182330ca..dd33b888971f 100644
+--- a/drivers/media/platform/exynos4-is/fimc-capture.c
++++ b/drivers/media/platform/exynos4-is/fimc-capture.c
+@@ -478,8 +478,10 @@ static int fimc_capture_open(struct file *file)
+ 
+ 	set_bit(ST_CAPT_BUSY, &fimc->state);
+ 	ret = pm_runtime_get_sync(&fimc->pdev->dev);
+-	if (ret < 0)
++	if (ret < 0) {
++		pm_runtime_put_sync(&fimc->pdev->dev);
+ 		goto unlock;
++	}
+ 
+ 	ret = v4l2_fh_open(file);
+ 	if (ret) {

commit 157282a5c6273976b31cf4ba4b1c46663f6519d1
+Author: Dinghao Liu 
+Date:   Thu May 21 13:07:47 2020 +0200
+
+    media: s5k6a3: Fix runtime PM imbalance on error
+    
+    pm_runtime_get() increments the runtime PM usage counter even
+    when it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/i2c/s5k6a3.c b/drivers/media/i2c/s5k6a3.c
+index bc6cc5a558db..f26c168ef942 100644
+--- a/drivers/media/i2c/s5k6a3.c
++++ b/drivers/media/i2c/s5k6a3.c
+@@ -197,7 +197,7 @@ static int __s5k6a3_power_on(struct s5k6a3 *sensor)
+ 
+ 	ret = pm_runtime_get(sensor->dev);
+ 	if (ret < 0)
+-		return ret;
++		goto error_rpm_put;
+ 
+ 	ret = regulator_enable(sensor->supplies[i].consumer);
+ 	if (ret < 0)

commit 7dcfb327f8fd7418124fc6d63bdce91b5844f50a
+Author: Dinghao Liu 
+Date:   Thu May 21 08:27:45 2020 +0200
+
+    media: staging: tegra-vde: fix runtime pm imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    the call returns an error code. Thus a pairing decrement is needed
+    on the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/staging/media/tegra-vde/vde.c b/drivers/staging/media/tegra-vde/vde.c
+index d3e63512a765..3fdf2cd0b99e 100644
+--- a/drivers/staging/media/tegra-vde/vde.c
++++ b/drivers/staging/media/tegra-vde/vde.c
+@@ -777,7 +777,7 @@ static int tegra_vde_ioctl_decode_h264(struct tegra_vde *vde,
+ 
+ 	ret = pm_runtime_get_sync(dev);
+ 	if (ret < 0)
+-		goto unlock;
++		goto put_runtime_pm;
+ 
+ 	/*
+ 	 * We rely on the VDE registers reset value, otherwise VDE
+@@ -843,8 +843,6 @@ static int tegra_vde_ioctl_decode_h264(struct tegra_vde *vde,
+ put_runtime_pm:
+ 	pm_runtime_mark_last_busy(dev);
+ 	pm_runtime_put_autosuspend(dev);
+-
+-unlock:
+ 	mutex_unlock(&vde->lock);
+ 
+ release_dpb_frames:

commit 1a37a039711610dd53ec03d8cab9e81875338225
+Author: Dinghao Liu 
+Date:   Mon May 25 19:05:40 2020 +0800
+
+    power: supply: bq24190_charger: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Rafael J. Wysocki 
+    Signed-off-by: Sebastian Reichel 
+
+diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
+index 4540e913057f..d14186525e1e 100644
+--- a/drivers/power/supply/bq24190_charger.c
++++ b/drivers/power/supply/bq24190_charger.c
+@@ -481,8 +481,10 @@ static ssize_t bq24190_sysfs_store(struct device *dev,
+ 		return ret;
+ 
+ 	ret = pm_runtime_get_sync(bdi->dev);
+-	if (ret < 0)
++	if (ret < 0) {
++		pm_runtime_put_noidle(bdi->dev);
+ 		return ret;
++	}
+ 
+ 	ret = bq24190_write_mask(bdi, info->reg, info->mask, info->shift, v);
+ 	if (ret)

commit 64092598c4566dc80a71ca57396dc36fdbf3da4b
+Author: Dinghao Liu 
+Date:   Fri May 22 21:41:09 2020 +0800
+
+    drm/panfrost: Fix runtime PM imbalance on error
+    
+    The caller expects panfrost_job_hw_submit() to increase
+    runtime PM usage counter. The refcount decrement on the
+    error branch of WARN_ON() will break the counter balance
+    and needs to be removed.
+    
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Steven Price 
+    Signed-off-by: Steven Price 
+    Link: https://patchwork.freedesktop.org/patch/msgid/20200522134109.27204-1-dinghao.liu@zju.edu.cn
+
+diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c
+index ac87ef675e8a..360146f6f3d9 100644
+--- a/drivers/gpu/drm/panfrost/panfrost_job.c
++++ b/drivers/gpu/drm/panfrost/panfrost_job.c
+@@ -152,7 +152,6 @@ static void panfrost_job_hw_submit(struct panfrost_job *job, int js)
+ 		return;
+ 
+ 	if (WARN_ON(job_read(pfdev, JS_COMMAND_NEXT(js)))) {
+-		pm_runtime_put_sync_autosuspend(pfdev->dev);
+ 		return;
+ 	}
+ 

commit a1e17eb03e69bb61bd1b1a14610436b7b9be12d9
+Author: Dinghao Liu 
+Date:   Fri May 22 12:59:29 2020 +0800
+
+    scsi: ufs-bsg: Fix runtime PM imbalance on error
+    
+    When ufs_bsg_alloc_desc_buffer() returns an error code, a pairing runtime
+    PM usage counter decrement is needed to keep the counter balanced.
+    
+    Link: https://lore.kernel.org/r/20200522045932.31795-1-dinghao.liu@zju.edu.cn
+    Fixes: 74e5e468b664 (scsi: ufs-bsg: Wake the device before sending raw upiu commands)
+    Reviewed-by: Avri Altman 
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
+index 53dd87628cbe..516a7f573942 100644
+--- a/drivers/scsi/ufs/ufs_bsg.c
++++ b/drivers/scsi/ufs/ufs_bsg.c
+@@ -106,8 +106,10 @@ static int ufs_bsg_request(struct bsg_job *job)
+ 		desc_op = bsg_request->upiu_req.qr.opcode;
+ 		ret = ufs_bsg_alloc_desc_buffer(hba, job, &desc_buff,
+ 						&desc_len, desc_op);
+-		if (ret)
++		if (ret) {
++			pm_runtime_put_sync(hba->dev);
+ 			goto out;
++		}
+ 
+ 		/* fall through */
+ 	case UPIU_TRANSACTION_NOP_OUT:

commit 95459261c99f1621d90bc628c2a48e60b7cf9a88
+Author: Dinghao Liu 
+Date:   Thu May 28 15:21:04 2020 +0800
+
+    hwrng: ks-sa - Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    the call returns an error code. Thus a pairing decrement is needed
+    on the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Alexander Sverdlin 
+    Signed-off-by: Herbert Xu 
+
+diff --git a/drivers/char/hw_random/ks-sa-rng.c b/drivers/char/hw_random/ks-sa-rng.c
+index e2330e757f1f..001617033d6a 100644
+--- a/drivers/char/hw_random/ks-sa-rng.c
++++ b/drivers/char/hw_random/ks-sa-rng.c
+@@ -244,6 +244,7 @@ static int ks_sa_rng_probe(struct platform_device *pdev)
+ 	ret = pm_runtime_get_sync(dev);
+ 	if (ret < 0) {
+ 		dev_err(dev, "Failed to enable SA power-domain\n");
++		pm_runtime_put_noidle(dev);
+ 		pm_runtime_disable(dev);
+ 		return ret;
+ 	}

commit 0187294d227dfc42889e1da8f8ce1e44fc25f147
+Author: Dinghao Liu 
+Date:   Tue May 26 18:47:17 2020 +0800
+
+    iio: magnetometer: ak8974: Fix runtime PM imbalance on error
+    
+    When devm_regmap_init_i2c() returns an error code, a pairing
+    runtime PM usage counter decrement is needed to keep the
+    counter balanced. For error paths after ak8974_set_power(),
+    ak8974_detect() and ak8974_reset(), things are the same.
+    
+    However, When iio_triggered_buffer_setup() returns an error
+    code, there will be two PM usgae counter decrements.
+    
+    Signed-off-by: Dinghao Liu 
+    Fixes: 7c94a8b2ee8c ("iio: magn: add a driver for AK8974")
+    Reviewed-by: Linus Walleij 
+    Cc: 
+    Signed-off-by: Jonathan Cameron 
+
+diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c
+index 810fdfd37c88..041c9007bfbe 100644
+--- a/drivers/iio/magnetometer/ak8974.c
++++ b/drivers/iio/magnetometer/ak8974.c
+@@ -862,19 +862,21 @@ static int ak8974_probe(struct i2c_client *i2c,
+ 	ak8974->map = devm_regmap_init_i2c(i2c, &ak8974_regmap_config);
+ 	if (IS_ERR(ak8974->map)) {
+ 		dev_err(&i2c->dev, "failed to allocate register map\n");
++		pm_runtime_put_noidle(&i2c->dev);
++		pm_runtime_disable(&i2c->dev);
+ 		return PTR_ERR(ak8974->map);
+ 	}
+ 
+ 	ret = ak8974_set_power(ak8974, AK8974_PWR_ON);
+ 	if (ret) {
+ 		dev_err(&i2c->dev, "could not power on\n");
+-		goto power_off;
++		goto disable_pm;
+ 	}
+ 
+ 	ret = ak8974_detect(ak8974);
+ 	if (ret) {
+ 		dev_err(&i2c->dev, "neither AK8974 nor AMI30x found\n");
+-		goto power_off;
++		goto disable_pm;
+ 	}
+ 
+ 	ret = ak8974_selftest(ak8974);
+@@ -884,14 +886,9 @@ static int ak8974_probe(struct i2c_client *i2c,
+ 	ret = ak8974_reset(ak8974);
+ 	if (ret) {
+ 		dev_err(&i2c->dev, "AK8974 reset failed\n");
+-		goto power_off;
++		goto disable_pm;
+ 	}
+ 
+-	pm_runtime_set_autosuspend_delay(&i2c->dev,
+-					 AK8974_AUTOSUSPEND_DELAY);
+-	pm_runtime_use_autosuspend(&i2c->dev);
+-	pm_runtime_put(&i2c->dev);
+-
+ 	indio_dev->dev.parent = &i2c->dev;
+ 	switch (ak8974->variant) {
+ 	case AK8974_WHOAMI_VALUE_AMI306:
+@@ -957,6 +954,11 @@ static int ak8974_probe(struct i2c_client *i2c,
+ 		goto cleanup_buffer;
+ 	}
+ 
++	pm_runtime_set_autosuspend_delay(&i2c->dev,
++					 AK8974_AUTOSUSPEND_DELAY);
++	pm_runtime_use_autosuspend(&i2c->dev);
++	pm_runtime_put(&i2c->dev);
++
+ 	return 0;
+ 
+ cleanup_buffer:
+@@ -965,7 +967,6 @@ static int ak8974_probe(struct i2c_client *i2c,
+ 	pm_runtime_put_noidle(&i2c->dev);
+ 	pm_runtime_disable(&i2c->dev);
+ 	ak8974_set_power(ak8974, AK8974_PWR_OFF);
+-power_off:
+ 	regulator_bulk_disable(ARRAY_SIZE(ak8974->regs), ak8974->regs);
+ 
+ 	return ret;

commit fcee90cdf6f3a3a371add04d41528d5ba9c3b411
+Author: Dinghao Liu 
+Date:   Thu May 21 10:47:09 2020 +0800
+
+    PCI: tegra: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Also, call pm_runtime_disable() when pm_runtime_get_sync() returns
+    an error code.
+    
+    Link: https://lore.kernel.org/r/20200521024709.2368-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Lorenzo Pieralisi 
+    Acked-by: Thierry Reding 
+
+diff --git a/drivers/pci/controller/pci-tegra.c b/drivers/pci/controller/pci-tegra.c
+index e3e917243e10..235b456698fc 100644
+--- a/drivers/pci/controller/pci-tegra.c
++++ b/drivers/pci/controller/pci-tegra.c
+@@ -2712,7 +2712,7 @@ static int tegra_pcie_probe(struct platform_device *pdev)
+ 	err = pm_runtime_get_sync(pcie->dev);
+ 	if (err < 0) {
+ 		dev_err(dev, "fail to enable pcie controller: %d\n", err);
+-		goto teardown_msi;
++		goto pm_runtime_put;
+ 	}
+ 
+ 	host->busnr = bus->start;
+@@ -2746,7 +2746,6 @@ static int tegra_pcie_probe(struct platform_device *pdev)
+ pm_runtime_put:
+ 	pm_runtime_put_sync(pcie->dev);
+ 	pm_runtime_disable(pcie->dev);
+-teardown_msi:
+ 	tegra_pcie_msi_teardown(pcie);
+ put_resources:
+ 	tegra_pcie_put_resources(pcie);

commit 37f7212148cf1d796135cdf8d0c7fee13067674b
+Author: Dinghao Liu 
+Date:   Fri May 22 18:40:06 2020 +0800
+
+    mtd: rawnand: omap_elm: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Miquel Raynal 
+    Link: https://lore.kernel.org/linux-mtd/20200522104008.28340-1-dinghao.liu@zju.edu.cn
+
+diff --git a/drivers/mtd/nand/raw/omap_elm.c b/drivers/mtd/nand/raw/omap_elm.c
+index 3fa0e2cbbe53..078b1022ac2a 100644
+--- a/drivers/mtd/nand/raw/omap_elm.c
++++ b/drivers/mtd/nand/raw/omap_elm.c
+@@ -411,6 +411,7 @@ static int elm_probe(struct platform_device *pdev)
+ 	pm_runtime_enable(&pdev->dev);
+ 	if (pm_runtime_get_sync(&pdev->dev) < 0) {
+ 		ret = -EINVAL;
++		pm_runtime_put_sync(&pdev->dev);
+ 		pm_runtime_disable(&pdev->dev);
+ 		dev_err(&pdev->dev, "can't enable clock\n");
+ 		return ret;

commit 8e935b92d269826f1e4bcf31d3f688dbcdf71219
+Author: Dinghao Liu 
+Date:   Fri May 22 18:17:13 2020 +0800
+
+    mtd: rawnand: gpmi: Fix runtime PM imbalance in gpmi_nand_probe
+    
+    There is no reason that the failure of __gpmi_enable_clk()
+    could lead to PM usage counter decrement.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Miquel Raynal 
+    Link: https://lore.kernel.org/linux-mtd/20200522101713.24350-1-dinghao.liu@zju.edu.cn
+
+diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+index 630de1a90eb4..c2d448812b85 100644
+--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
++++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+@@ -2663,7 +2663,7 @@ static int gpmi_nand_probe(struct platform_device *pdev)
+ 
+ 	ret = __gpmi_enable_clk(this, true);
+ 	if (ret)
+-		goto exit_nfc_init;
++		goto exit_acquire_resources;
+ 
+ 	pm_runtime_set_autosuspend_delay(&pdev->dev, 500);
+ 	pm_runtime_use_autosuspend(&pdev->dev);

commit 550e68ea36a6671a96576c0531685ce6e6c0d19d
+Author: Dinghao Liu 
+Date:   Fri May 22 17:51:39 2020 +0800
+
+    mtd: rawnand: gpmi: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Miquel Raynal 
+    Link: https://lore.kernel.org/linux-mtd/20200522095139.19653-1-dinghao.liu@zju.edu.cn
+
+diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+index 9a4a1d30669d..630de1a90eb4 100644
+--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
++++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+@@ -540,8 +540,10 @@ static int bch_set_geometry(struct gpmi_nand_data *this)
+ 		return ret;
+ 
+ 	ret = pm_runtime_get_sync(this->dev);
+-	if (ret < 0)
++	if (ret < 0) {
++		pm_runtime_put_autosuspend(this->dev);
+ 		return ret;
++	}
+ 
+ 	/*
+ 	* Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this

commit da74b6933b3ba27c88fa0b7ccbd019e4f41ebfd4
+Author: Dinghao Liu 
+Date:   Fri May 22 12:49:04 2020 +0800
+
+    wlcore: fix runtime pm imbalance in wlcore_irq_locked
+    
+    When wlcore_fw_status() returns an error code, a pairing
+    runtime PM usage counter decrement is needed to keep the
+    counter balanced. It's the same for all error paths after
+    wlcore_fw_status().
+    
+    Signed-off-by: Dinghao Liu 
+    Acked-by: Tony Lindgren 
+    Signed-off-by: Kalle Valo 
+    Link: https://lore.kernel.org/r/20200522044906.29564-1-dinghao.liu@zju.edu.cn
+
+diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
+index 0dcad4949889..de6c8a7589ca 100644
+--- a/drivers/net/wireless/ti/wlcore/main.c
++++ b/drivers/net/wireless/ti/wlcore/main.c
+@@ -548,7 +548,7 @@ static int wlcore_irq_locked(struct wl1271 *wl)
+ 
+ 		ret = wlcore_fw_status(wl, wl->fw_status);
+ 		if (ret < 0)
+-			goto out;
++			goto err_ret;
+ 
+ 		wlcore_hw_tx_immediate_compl(wl);
+ 
+@@ -565,7 +565,7 @@ static int wlcore_irq_locked(struct wl1271 *wl)
+ 			ret = -EIO;
+ 
+ 			/* restarting the chip. ignore any other interrupt. */
+-			goto out;
++			goto err_ret;
+ 		}
+ 
+ 		if (unlikely(intr & WL1271_ACX_SW_INTR_WATCHDOG)) {
+@@ -575,7 +575,7 @@ static int wlcore_irq_locked(struct wl1271 *wl)
+ 			ret = -EIO;
+ 
+ 			/* restarting the chip. ignore any other interrupt. */
+-			goto out;
++			goto err_ret;
+ 		}
+ 
+ 		if (likely(intr & WL1271_ACX_INTR_DATA)) {
+@@ -583,7 +583,7 @@ static int wlcore_irq_locked(struct wl1271 *wl)
+ 
+ 			ret = wlcore_rx(wl, wl->fw_status);
+ 			if (ret < 0)
+-				goto out;
++				goto err_ret;
+ 
+ 			/* Check if any tx blocks were freed */
+ 			spin_lock_irqsave(&wl->wl_lock, flags);
+@@ -596,7 +596,7 @@ static int wlcore_irq_locked(struct wl1271 *wl)
+ 				 */
+ 				ret = wlcore_tx_work_locked(wl);
+ 				if (ret < 0)
+-					goto out;
++					goto err_ret;
+ 			} else {
+ 				spin_unlock_irqrestore(&wl->wl_lock, flags);
+ 			}
+@@ -604,7 +604,7 @@ static int wlcore_irq_locked(struct wl1271 *wl)
+ 			/* check for tx results */
+ 			ret = wlcore_hw_tx_delayed_compl(wl);
+ 			if (ret < 0)
+-				goto out;
++				goto err_ret;
+ 
+ 			/* Make sure the deferred queues don't get too long */
+ 			defer_count = skb_queue_len(&wl->deferred_tx_queue) +
+@@ -617,14 +617,14 @@ static int wlcore_irq_locked(struct wl1271 *wl)
+ 			wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A");
+ 			ret = wl1271_event_handle(wl, 0);
+ 			if (ret < 0)
+-				goto out;
++				goto err_ret;
+ 		}
+ 
+ 		if (intr & WL1271_ACX_INTR_EVENT_B) {
+ 			wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B");
+ 			ret = wl1271_event_handle(wl, 1);
+ 			if (ret < 0)
+-				goto out;
++				goto err_ret;
+ 		}
+ 
+ 		if (intr & WL1271_ACX_INTR_INIT_COMPLETE)
+@@ -635,6 +635,7 @@ static int wlcore_irq_locked(struct wl1271 *wl)
+ 			wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE");
+ 	}
+ 
++err_ret:
+ 	pm_runtime_mark_last_busy(wl->dev);
+ 	pm_runtime_put_autosuspend(wl->dev);
+ 

commit 53df5271f2397706be85c3892246e3e726113902
+Author: Dinghao Liu 
+Date:   Wed May 20 21:08:04 2020 +0800
+
+    wlcore: fix runtime pm imbalance in __wl1271_op_remove_interface
+    
+    When wl12xx_cmd_role_disable() returns an error code,
+    a pairing runtime PM usage counter decrement is needed to
+    keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Acked-by: Tony Lindgren 
+    Signed-off-by: Kalle Valo 
+    Link: https://lore.kernel.org/r/20200520130806.14789-1-dinghao.liu@zju.edu.cn
+
+diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
+index bf6698fc1389..0dcad4949889 100644
+--- a/drivers/net/wireless/ti/wlcore/main.c
++++ b/drivers/net/wireless/ti/wlcore/main.c
+@@ -2696,12 +2696,16 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
+ 
+ 		if (!wlcore_is_p2p_mgmt(wlvif)) {
+ 			ret = wl12xx_cmd_role_disable(wl, &wlvif->role_id);
+-			if (ret < 0)
++			if (ret < 0) {
++				pm_runtime_put_noidle(wl->dev);
+ 				goto deinit;
++			}
+ 		} else {
+ 			ret = wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id);
+-			if (ret < 0)
++			if (ret < 0) {
++				pm_runtime_put_noidle(wl->dev);
+ 				goto deinit;
++			}
+ 		}
+ 
+ 		pm_runtime_mark_last_busy(wl->dev);

commit 3e69ed2b52fd0eeb1e812e20a667316d913e6a97
+Author: Dinghao Liu 
+Date:   Wed May 20 20:57:22 2020 +0800
+
+    wlcore: fix runtime pm imbalance in wl1271_op_suspend
+    
+    When wlcore_hw_interrupt_notify() returns an error code,
+    a pairing runtime PM usage counter decrement is needed to
+    keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Acked-by: Tony Lindgren 
+    Signed-off-by: Kalle Valo 
+    Link: https://lore.kernel.org/r/20200520125724.12832-1-dinghao.liu@zju.edu.cn
+
+diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
+index fa4ced9864c0..bf6698fc1389 100644
+--- a/drivers/net/wireless/ti/wlcore/main.c
++++ b/drivers/net/wireless/ti/wlcore/main.c
+@@ -1746,9 +1746,7 @@ static int __maybe_unused wl1271_op_suspend(struct ieee80211_hw *hw,
+ 
+ 		ret = wl1271_configure_suspend(wl, wlvif, wow);
+ 		if (ret < 0) {
+-			mutex_unlock(&wl->mutex);
+-			wl1271_warning("couldn't prepare device to suspend");
+-			return ret;
++			goto out_sleep;
+ 		}
+ 	}
+ 

commit 282a04bf1d8029eb98585cb5db3fd70fe8bc91f7
+Author: Dinghao Liu 
+Date:   Wed May 20 20:46:47 2020 +0800
+
+    wlcore: fix runtime pm imbalance in wlcore_regdomain_config
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    the call returns an error code. Thus a pairing decrement is needed
+    on the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Acked-by: Tony Lindgren 
+    Signed-off-by: Kalle Valo 
+    Link: https://lore.kernel.org/r/20200520124649.10848-1-dinghao.liu@zju.edu.cn
+
+diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
+index 4421fc656b1c..fa4ced9864c0 100644
+--- a/drivers/net/wireless/ti/wlcore/main.c
++++ b/drivers/net/wireless/ti/wlcore/main.c
+@@ -3665,8 +3665,10 @@ void wlcore_regdomain_config(struct wl1271 *wl)
+ 		goto out;
+ 
+ 	ret = pm_runtime_get_sync(wl->dev);
+-	if (ret < 0)
++	if (ret < 0) {
++		pm_runtime_put_autosuspend(wl->dev);
+ 		goto out;
++	}
+ 
+ 	ret = wlcore_cmd_regdomain_config_locked(wl);
+ 	if (ret < 0) {

commit 9604617e998b49f7695fea1479ed82421ef8c9f0
+Author: Dinghao Liu 
+Date:   Wed May 20 20:42:38 2020 +0800
+
+    wlcore: fix runtime pm imbalance in wl1271_tx_work
+    
+    There are two error handling paths in this functon. When
+    wlcore_tx_work_locked() returns an error code, we should
+    decrease the runtime PM usage counter the same way as the
+    error handling path beginning from pm_runtime_get_sync().
+    
+    Signed-off-by: Dinghao Liu 
+    Acked-by: Tony Lindgren 
+    Signed-off-by: Kalle Valo 
+    Link: https://lore.kernel.org/r/20200520124241.9931-1-dinghao.liu@zju.edu.cn
+
+diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c
+index 90e56d4c3df3..e20e18cd04ae 100644
+--- a/drivers/net/wireless/ti/wlcore/tx.c
++++ b/drivers/net/wireless/ti/wlcore/tx.c
+@@ -863,6 +863,7 @@ void wl1271_tx_work(struct work_struct *work)
+ 
+ 	ret = wlcore_tx_work_locked(wl);
+ 	if (ret < 0) {
++		pm_runtime_put_noidle(wl->dev);
+ 		wl12xx_queue_recovery_work(wl);
+ 		goto out;
+ 	}

commit 65bd91dd6957390c42a0491b9622cf31a2cdb140
+Author: Dinghao Liu 
+Date:   Fri May 29 09:22:28 2020 +0800
+
+    ASoC: img-i2s-out: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    the call returns an error code. Thus a pairing decrement is needed
+    on the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20200529012230.5863-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/img/img-i2s-out.c b/sound/soc/img/img-i2s-out.c
+index db052ec17d5d..b56a18e7f3ac 100644
+--- a/sound/soc/img/img-i2s-out.c
++++ b/sound/soc/img/img-i2s-out.c
+@@ -347,8 +347,10 @@ static int img_i2s_out_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+ 	chan_control_mask = IMG_I2S_OUT_CHAN_CTL_CLKT_MASK;
+ 
+ 	ret = pm_runtime_get_sync(i2s->dev);
+-	if (ret < 0)
++	if (ret < 0) {
++		pm_runtime_put_noidle(i2s->dev);
+ 		return ret;
++	}
+ 
+ 	img_i2s_out_disable(i2s);
+ 
+@@ -488,8 +490,10 @@ static int img_i2s_out_probe(struct platform_device *pdev)
+ 			goto err_pm_disable;
+ 	}
+ 	ret = pm_runtime_get_sync(&pdev->dev);
+-	if (ret < 0)
++	if (ret < 0) {
++		pm_runtime_put_noidle(&pdev->dev);
+ 		goto err_suspend;
++	}
+ 
+ 	reg = IMG_I2S_OUT_CTL_FRM_SIZE_MASK;
+ 	img_i2s_out_writel(i2s, reg, IMG_I2S_OUT_CTL);

commit 1c1dbb2c02623db18a50c61b175f19aead800b4e
+Author: Dinghao Liu 
+Date:   Thu May 21 11:13:49 2020 +0800
+
+    PCI: tegra194: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Link: https://lore.kernel.org/r/20200521031355.7022-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Lorenzo Pieralisi 
+    Acked-by: Thierry Reding 
+    Acked-by: Vidya Sagar 
+
+diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
+index ae30a2fd3716..2c0d2ce16b47 100644
+--- a/drivers/pci/controller/dwc/pcie-tegra194.c
++++ b/drivers/pci/controller/dwc/pcie-tegra194.c
+@@ -1623,7 +1623,7 @@ static int tegra_pcie_config_rp(struct tegra_pcie_dw *pcie)
+ 	ret = pinctrl_pm_select_default_state(dev);
+ 	if (ret < 0) {
+ 		dev_err(dev, "Failed to configure sideband pins: %d\n", ret);
+-		goto fail_pinctrl;
++		goto fail_pm_get_sync;
+ 	}
+ 
+ 	tegra_pcie_init_controller(pcie);
+@@ -1650,9 +1650,8 @@ static int tegra_pcie_config_rp(struct tegra_pcie_dw *pcie)
+ 
+ fail_host_init:
+ 	tegra_pcie_deinit_controller(pcie);
+-fail_pinctrl:
+-	pm_runtime_put_sync(dev);
+ fail_pm_get_sync:
++	pm_runtime_put_sync(dev);
+ 	pm_runtime_disable(dev);
+ 	return ret;
+ }

commit b2e5575a8d04028d17f6c914eea31036589bc79a
+Author: Dinghao Liu 
+Date:   Sat May 23 14:17:26 2020 +0800
+
+    extcon: arizona: Fix runtime PM imbalance on error
+    
+    When arizona_request_irq() returns an error code, a
+    pairing runtime PM usage counter decrement is needed
+    to keep the counter balanced. For error paths after
+    this function, things are the same.
+    
+    Also, remove calls to pm_runtime_disable() when
+    pm_runtime_enable() has not been executed.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Chanwoo Choi 
+
+diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
+index 7401733db08b..aae82db542a5 100644
+--- a/drivers/extcon/extcon-arizona.c
++++ b/drivers/extcon/extcon-arizona.c
+@@ -1460,7 +1460,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
+ 	if (!info->input) {
+ 		dev_err(arizona->dev, "Can't allocate input dev\n");
+ 		ret = -ENOMEM;
+-		goto err_register;
++		return ret;
+ 	}
+ 
+ 	info->input->name = "Headset";
+@@ -1492,7 +1492,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
+ 		if (ret != 0) {
+ 			dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
+ 				pdata->micd_pol_gpio, ret);
+-			goto err_register;
++			return ret;
+ 		}
+ 
+ 		info->micd_pol_gpio = gpio_to_desc(pdata->micd_pol_gpio);
+@@ -1515,7 +1515,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
+ 			dev_err(arizona->dev,
+ 				"Failed to get microphone polarity GPIO: %d\n",
+ 				ret);
+-			goto err_register;
++			return ret;
+ 		}
+ 	}
+ 
+@@ -1672,7 +1672,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
+ 	if (ret != 0) {
+ 		dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n",
+ 			ret);
+-		goto err_gpio;
++		goto err_pm;
+ 	}
+ 
+ 	ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1);
+@@ -1721,14 +1721,14 @@ static int arizona_extcon_probe(struct platform_device *pdev)
+ 		dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n",
+ 			 ret);
+ 
+-	pm_runtime_put(&pdev->dev);
+-
+ 	ret = input_register_device(info->input);
+ 	if (ret) {
+ 		dev_err(&pdev->dev, "Can't register input device: %d\n", ret);
+ 		goto err_hpdet;
+ 	}
+ 
++	pm_runtime_put(&pdev->dev);
++
+ 	return 0;
+ 
+ err_hpdet:
+@@ -1743,10 +1743,11 @@ static int arizona_extcon_probe(struct platform_device *pdev)
+ 	arizona_set_irq_wake(arizona, jack_irq_rise, 0);
+ err_rise:
+ 	arizona_free_irq(arizona, jack_irq_rise, info);
++err_pm:
++	pm_runtime_put(&pdev->dev);
++	pm_runtime_disable(&pdev->dev);
+ err_gpio:
+ 	gpiod_put(info->micd_pol_gpio);
+-err_register:
+-	pm_runtime_disable(&pdev->dev);
+ 	return ret;
+ }
+ 

commit 117858bd63fb2ebcdfcc27b09fd65cb44511ea4c
+Author: Dinghao Liu 
+Date:   Sat May 23 20:47:58 2020 +0800
+
+    spi: tegra20-sflash: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20200523124758.28604-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Mark Brown 
+
+diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c
+index 514429379206..02cf5f463ba6 100644
+--- a/drivers/spi/spi-tegra20-sflash.c
++++ b/drivers/spi/spi-tegra20-sflash.c
+@@ -491,6 +491,7 @@ static int tegra_sflash_probe(struct platform_device *pdev)
+ 	ret = pm_runtime_get_sync(&pdev->dev);
+ 	if (ret < 0) {
+ 		dev_err(&pdev->dev, "pm runtime get failed, e = %d\n", ret);
++		pm_runtime_put_noidle(&pdev->dev);
+ 		goto exit_pm_disable;
+ 	}
+ 

commit faedcc17ad183acfa5d74758ebc4f21aef341f11
+Author: Dinghao Liu 
+Date:   Sat May 23 20:29:09 2020 +0800
+
+    spi: tegra20-slink: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20200523122909.25247-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Mark Brown 
+
+diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c
+index 7f4d932dade7..a07b72e9c344 100644
+--- a/drivers/spi/spi-tegra20-slink.c
++++ b/drivers/spi/spi-tegra20-slink.c
+@@ -1118,6 +1118,7 @@ static int tegra_slink_probe(struct platform_device *pdev)
+ 	ret = pm_runtime_get_sync(&pdev->dev);
+ 	if (ret < 0) {
+ 		dev_err(&pdev->dev, "pm runtime get failed, e = %d\n", ret);
++		pm_runtime_put_noidle(&pdev->dev);
+ 		goto exit_pm_disable;
+ 	}
+ 	tspi->def_command_reg  = SLINK_M_S;

commit cddc36f3fd706b1046a4d4608359c0003f72db32
+Author: Dinghao Liu 
+Date:   Sat May 23 20:57:04 2020 +0800
+
+    spi: tegra114: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20200523125704.30300-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Mark Brown 
+
+diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
+index 83edabdb41ad..c2c58871a947 100644
+--- a/drivers/spi/spi-tegra114.c
++++ b/drivers/spi/spi-tegra114.c
+@@ -1398,6 +1398,7 @@ static int tegra_spi_probe(struct platform_device *pdev)
+ 	ret = pm_runtime_get_sync(&pdev->dev);
+ 	if (ret < 0) {
+ 		dev_err(&pdev->dev, "pm runtime get failed, e = %d\n", ret);
++		pm_runtime_put_noidle(&pdev->dev);
+ 		goto exit_pm_disable;
+ 	}
+ 

commit 920bef64cc5fa0e955be357bfc876179729df216
+Author: Dinghao Liu 
+Date:   Wed May 27 10:46:22 2020 +0800
+
+    ASoC: wm8962: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    the call returns an error code. Thus a pairing decrement is needed
+    on the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Acked-by: Charles Keepax 
+    Link: https://lore.kernel.org/r/20200527024625.9937-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
+index 08d19df8a700..1cc23a05ffe4 100644
+--- a/sound/soc/codecs/wm8962.c
++++ b/sound/soc/codecs/wm8962.c
+@@ -2880,6 +2880,7 @@ static int wm8962_set_fll(struct snd_soc_component *component, int fll_id, int s
+ 
+ 	ret = pm_runtime_get_sync(component->dev);
+ 	if (ret < 0) {
++		pm_runtime_put_noidle(component->dev);
+ 		dev_err(component->dev, "Failed to resume device: %d\n", ret);
+ 		return ret;
+ 	}
+@@ -3012,6 +3013,7 @@ static irqreturn_t wm8962_irq(int irq, void *data)
+ 
+ 	ret = pm_runtime_get_sync(dev);
+ 	if (ret < 0) {
++		pm_runtime_put_noidle(dev);
+ 		dev_err(dev, "Failed to resume: %d\n", ret);
+ 		return IRQ_NONE;
+ 	}

commit 53865b3259554389e40aeead392151c819b52a71
+Author: Dinghao Liu 
+Date:   Wed May 27 16:43:24 2020 +0800
+
+    ASoC: img-spdif-in: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    the call returns an error code. Thus a pairing decrement is needed
+    on the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20200527084326.4131-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/img/img-spdif-in.c b/sound/soc/img/img-spdif-in.c
+index fd639f4d082b..46ff8a3621d5 100644
+--- a/sound/soc/img/img-spdif-in.c
++++ b/sound/soc/img/img-spdif-in.c
+@@ -753,8 +753,10 @@ static int img_spdif_in_probe(struct platform_device *pdev)
+ 			goto err_pm_disable;
+ 	}
+ 	ret = pm_runtime_get_sync(&pdev->dev);
+-	if (ret < 0)
++	if (ret < 0) {
++		pm_runtime_put_noidle(&pdev->dev);
+ 		goto err_suspend;
++	}
+ 
+ 	rst = devm_reset_control_get_exclusive(&pdev->dev, "rst");
+ 	if (IS_ERR(rst)) {

commit 9ad61b5c804090022444719d1f16e1029e002430
+Author: Dinghao Liu 
+Date:   Wed May 27 16:46:08 2020 +0800
+
+    ASoC: img-spdif-out: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    the call returns an error code. Thus a pairing decrement is needed
+    on the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20200527084610.4790-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/img/img-spdif-out.c b/sound/soc/img/img-spdif-out.c
+index 456c462d52fb..b1d8e4535726 100644
+--- a/sound/soc/img/img-spdif-out.c
++++ b/sound/soc/img/img-spdif-out.c
+@@ -370,8 +370,10 @@ static int img_spdif_out_probe(struct platform_device *pdev)
+ 			goto err_pm_disable;
+ 	}
+ 	ret = pm_runtime_get_sync(&pdev->dev);
+-	if (ret < 0)
++	if (ret < 0) {
++		pm_runtime_put_noidle(&pdev->dev);
+ 		goto err_suspend;
++	}
+ 
+ 	img_spdif_out_writel(spdif, IMG_SPDIF_OUT_CTL_FS_MASK,
+ 			     IMG_SPDIF_OUT_CTL);

commit 8d728808194a12186ce5af0b72c8a47b42476bc3
+Author: Dinghao Liu 
+Date:   Sat May 23 21:38:59 2020 +0800
+
+    spi: spi-fsl-lpspi: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20200523133859.5625-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Mark Brown 
+
+diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
+index 511211b82430..1552b28b9515 100644
+--- a/drivers/spi/spi-fsl-lpspi.c
++++ b/drivers/spi/spi-fsl-lpspi.c
+@@ -940,7 +940,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
+ 	ret = pm_runtime_get_sync(fsl_lpspi->dev);
+ 	if (ret < 0) {
+ 		dev_err(fsl_lpspi->dev, "failed to enable clock\n");
+-		goto out_controller_put;
++		goto out_pm_get;
+ 	}
+ 
+ 	temp = readl(fsl_lpspi->base + IMX7ULP_PARAM);
+@@ -949,13 +949,15 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
+ 
+ 	ret = fsl_lpspi_dma_init(&pdev->dev, fsl_lpspi, controller);
+ 	if (ret == -EPROBE_DEFER)
+-		goto out_controller_put;
++		goto out_pm_get;
+ 
+ 	if (ret < 0)
+ 		dev_err(&pdev->dev, "dma setup error %d, use pio\n", ret);
+ 
+ 	return 0;
+ 
++out_pm_get:
++	pm_runtime_put_noidle(fsl_lpspi->dev);
+ out_controller_put:
+ 	spi_controller_put(controller);
+ 

commit 0d71a5cf691a8226151ceeb79fb872925f053df5
+Author: Dinghao Liu 
+Date:   Mon May 25 15:17:30 2020 +0800
+
+    ASoC: tas2552: Fix runtime PM imbalance in tas2552_component_probe
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20200525071732.5887-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c
+index 56671f21cfe5..d90e5f2b6f27 100644
+--- a/sound/soc/codecs/tas2552.c
++++ b/sound/soc/codecs/tas2552.c
+@@ -602,6 +602,7 @@ static int tas2552_component_probe(struct snd_soc_component *component)
+ 	return 0;
+ 
+ probe_fail:
++	pm_runtime_put_noidle(component->dev);
+ 	gpiod_set_value(tas2552->enable_gpio, 0);
+ 
+ 	regulator_bulk_disable(ARRAY_SIZE(tas2552->supplies),

commit c553d290577093553098a56c954e516950c35c59
+Author: Dinghao Liu 
+Date:   Mon May 25 16:58:48 2020 +0800
+
+    ASoC: ti: Fix runtime PM imbalance in omap2_mcbsp_set_clks_src
+    
+    When clk_set_parent() returns an error code, a pairing
+    runtime PM usage counter increment is needed to keep the
+    counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Acked-by: Peter Ujfalusi 
+    Link: https://lore.kernel.org/r/20200525085848.4227-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/ti/omap-mcbsp.c b/sound/soc/ti/omap-mcbsp.c
+index 4e67769b795a..32e3ccdbb7a2 100644
+--- a/sound/soc/ti/omap-mcbsp.c
++++ b/sound/soc/ti/omap-mcbsp.c
+@@ -77,18 +77,15 @@ static int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id)
+ 	pm_runtime_put_sync(mcbsp->dev);
+ 
+ 	r = clk_set_parent(mcbsp->fclk, fck_src);
+-	if (r) {
++	if (r)
+ 		dev_err(mcbsp->dev, "CLKS: could not clk_set_parent() to %s\n",
+ 			src);
+-		clk_put(fck_src);
+-		return r;
+-	}
+ 
+ 	pm_runtime_get_sync(mcbsp->dev);
+ 
+ 	clk_put(fck_src);
+ 
+-	return 0;
++	return r;
+ }
+ 
+ static irqreturn_t omap_mcbsp_irq_handler(int irq, void *data)

commit e4befc121df03dc8ed2ac1031c98f9538e244bae
+Author: Dinghao Liu 
+Date:   Sun May 24 21:50:49 2020 -0500
+
+    usb: musb: Fix runtime PM imbalance on error
+    
+    When copy_from_user() returns an error code, there
+    is a runtime PM usage counter imbalance.
+    
+    Fix this by moving copy_from_user() to the beginning
+    of this function.
+    
+    Fixes: 7b6c1b4c0e1e ("usb: musb: fix runtime PM in debugfs")
+    
+    Signed-off-by: Dinghao Liu 
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Bin Liu 
+    Link: https://lore.kernel.org/r/20200525025049.3400-7-b-liu@ti.com
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c
+index 7b6281ab62ed..30a89aa8a3e7 100644
+--- a/drivers/usb/musb/musb_debugfs.c
++++ b/drivers/usb/musb/musb_debugfs.c
+@@ -168,6 +168,11 @@ static ssize_t musb_test_mode_write(struct file *file,
+ 	u8			test;
+ 	char			buf[24];
+ 
++	memset(buf, 0x00, sizeof(buf));
++
++	if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
++		return -EFAULT;
++
+ 	pm_runtime_get_sync(musb->controller);
+ 	test = musb_readb(musb->mregs, MUSB_TESTMODE);
+ 	if (test) {
+@@ -176,11 +181,6 @@ static ssize_t musb_test_mode_write(struct file *file,
+ 		goto ret;
+ 	}
+ 
+-	memset(buf, 0x00, sizeof(buf));
+-
+-	if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
+-		return -EFAULT;
+-
+ 	if (strstarts(buf, "force host full-speed"))
+ 		test = MUSB_TEST_FORCE_HOST | MUSB_TEST_FORCE_FS;
+ 

commit 6f8cd246411575703d9312888b70705c396b53a9
+Author: Dinghao Liu 
+Date:   Fri May 22 16:08:38 2020 +0800
+
+    gpio: rcar: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Link: https://lore.kernel.org/r/20200522080839.32612-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Linus Walleij 
+
+diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c
+index 7284473c9fe3..eac1582c70da 100644
+--- a/drivers/gpio/gpio-rcar.c
++++ b/drivers/gpio/gpio-rcar.c
+@@ -250,8 +250,10 @@ static int gpio_rcar_request(struct gpio_chip *chip, unsigned offset)
+ 	int error;
+ 
+ 	error = pm_runtime_get_sync(p->dev);
+-	if (error < 0)
++	if (error < 0) {
++		pm_runtime_put(p->dev);
+ 		return error;
++	}
+ 
+ 	error = pinctrl_gpio_request(chip->base + offset);
+ 	if (error)

commit e5b913496099527abe46e175e5e2c844367bded0
+Author: Dinghao Liu 
+Date:   Thu May 21 15:39:19 2020 +0800
+
+    usb: cdns3: Fix runtime PM imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus a pairing decrement is needed on
+    the error handling path to keep the counter balanced.
+    
+    Reviewed-by: Peter Chen 
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/cdns3/cdns3-ti.c b/drivers/usb/cdns3/cdns3-ti.c
+index 5685ba11480b..e701ab56b0a7 100644
+--- a/drivers/usb/cdns3/cdns3-ti.c
++++ b/drivers/usb/cdns3/cdns3-ti.c
+@@ -138,7 +138,7 @@ static int cdns_ti_probe(struct platform_device *pdev)
+ 	error = pm_runtime_get_sync(dev);
+ 	if (error < 0) {
+ 		dev_err(dev, "pm_runtime_get_sync failed: %d\n", error);
+-		goto err_get;
++		goto err;
+ 	}
+ 
+ 	/* assert RESET */
+@@ -185,7 +185,6 @@ static int cdns_ti_probe(struct platform_device *pdev)
+ 
+ err:
+ 	pm_runtime_put_sync(data->dev);
+-err_get:
+ 	pm_runtime_disable(data->dev);
+ 
+ 	return error;

commit a22573740d93f31c30b57a40b334a1ec6b789f67
+Author: Dinghao Liu 
+Date:   Thu May 21 16:01:41 2020 +0800
+
+    watchdog: Fix runtime PM imbalance on error
+    
+    When watchdog_register_device() returns an error code,
+    a pairing runtime PM usage counter decrement is needed
+    to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Reviewed-by: Guenter Roeck 
+    Link: https://lore.kernel.org/r/20200521080141.24373-1-dinghao.liu@zju.edu.cn
+    Signed-off-by: Guenter Roeck 
+    Signed-off-by: Wim Van Sebroeck 
+
+diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
+index 9b91882fe3c4..1616f93dfad7 100644
+--- a/drivers/watchdog/omap_wdt.c
++++ b/drivers/watchdog/omap_wdt.c
+@@ -273,6 +273,7 @@ static int omap_wdt_probe(struct platform_device *pdev)
+ 
+ 	ret = watchdog_register_device(&wdev->wdog);
+ 	if (ret) {
++		pm_runtime_put(wdev->dev);
+ 		pm_runtime_disable(wdev->dev);
+ 		return ret;
+ 	}

commit 539d39ad0c61b35f69565a037d7586deaf6d6166
+Author: Dinghao Liu 
+Date:   Sat May 23 16:08:20 2020 +0800
+
+    net: smsc911x: Fix runtime PM imbalance on error
+    
+    Remove runtime PM usage counter decrement when the
+    increment function has not been called to keep the
+    counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
+index 49a6a9167af4..fc168f85e7af 100644
+--- a/drivers/net/ethernet/smsc/smsc911x.c
++++ b/drivers/net/ethernet/smsc/smsc911x.c
+@@ -2493,20 +2493,20 @@ static int smsc911x_drv_probe(struct platform_device *pdev)
+ 
+ 	retval = smsc911x_init(dev);
+ 	if (retval < 0)
+-		goto out_disable_resources;
++		goto out_init_fail;
+ 
+ 	netif_carrier_off(dev);
+ 
+ 	retval = smsc911x_mii_init(pdev, dev);
+ 	if (retval) {
+ 		SMSC_WARN(pdata, probe, "Error %i initialising mii", retval);
+-		goto out_disable_resources;
++		goto out_init_fail;
+ 	}
+ 
+ 	retval = register_netdev(dev);
+ 	if (retval) {
+ 		SMSC_WARN(pdata, probe, "Error %i registering device", retval);
+-		goto out_disable_resources;
++		goto out_init_fail;
+ 	} else {
+ 		SMSC_TRACE(pdata, probe,
+ 			   "Network interface: \"%s\"", dev->name);
+@@ -2547,9 +2547,10 @@ static int smsc911x_drv_probe(struct platform_device *pdev)
+ 
+ 	return 0;
+ 
+-out_disable_resources:
++out_init_fail:
+ 	pm_runtime_put(&pdev->dev);
+ 	pm_runtime_disable(&pdev->dev);
++out_disable_resources:
+ 	(void)smsc911x_disable_resources(pdev);
+ out_enable_resources_fail:
+ 	smsc911x_free_resources(pdev);

commit dc455f4c888365595c0a13da445e092422d55b8d
+Author: Dinghao Liu 
+Date:   Wed May 20 18:47:48 2020 +0800
+
+    drm/nouveau/dispnv50: fix runtime pm imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    the call returns an error code. Thus a pairing decrement is needed
+    on the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
+index 8d60252e5583..7622490d8602 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
+@@ -1137,8 +1137,10 @@ nv50_mstc_detect(struct drm_connector *connector,
+ 		return connector_status_disconnected;
+ 
+ 	ret = pm_runtime_get_sync(connector->dev->dev);
+-	if (ret < 0 && ret != -EACCES)
++	if (ret < 0 && ret != -EACCES) {
++		pm_runtime_put_autosuspend(connector->dev->dev);
+ 		return connector_status_disconnected;
++	}
+ 
+ 	ret = drm_dp_mst_detect_port(connector, ctx, mstc->port->mgr,
+ 				     mstc->port);

commit d3faddc7dcd326c0edc906f907f83a8454986d99
+Author: Dinghao Liu 
+Date:   Wed May 20 18:36:04 2020 +0800
+
+    drm/nouveau: fix runtime pm imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    the call returns an error code. Thus a pairing decrement is needed
+    on the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
+index 6697f960dd89..4c3f131ad31d 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
++++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
+@@ -159,8 +159,8 @@ nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv)
+ 			if (!WARN_ON(ret < 0 && ret != -EACCES)) {
+ 				nouveau_gem_object_unmap(nvbo, vma);
+ 				pm_runtime_mark_last_busy(dev);
+-				pm_runtime_put_autosuspend(dev);
+ 			}
++			pm_runtime_put_autosuspend(dev);
+ 		}
+ 	}
+ 	ttm_bo_unreserve(&nvbo->bo);

commit d7372dfb3f7f1602b87e0663e8b8646da23ebca7
+Author: Dinghao Liu 
+Date:   Wed May 20 18:25:49 2020 +0800
+
+    drm/nouveau: fix runtime pm imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    the call returns an error code. Thus a pairing decrement is needed
+    on the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
+index f5ece1f94973..6697f960dd89 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
++++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
+@@ -76,8 +76,10 @@ nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv)
+ 		return ret;
+ 
+ 	ret = pm_runtime_get_sync(dev);
+-	if (ret < 0 && ret != -EACCES)
++	if (ret < 0 && ret != -EACCES) {
++		pm_runtime_put_autosuspend(dev);
+ 		goto out;
++	}
+ 
+ 	ret = nouveau_vma_new(nvbo, vmm, &vma);
+ 	pm_runtime_mark_last_busy(dev);

commit 00583fbe8031f69bba8b0a9a861efb75fb7131af
+Author: Dinghao Liu 
+Date:   Wed May 20 18:14:53 2020 +0800
+
+    drm/nouveau/debugfs: fix runtime pm imbalance on error
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    the call returns an error code. Thus a pairing decrement is needed
+    on the error handling path to keep the counter balanced.
+    
+    Signed-off-by: Dinghao Liu 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.c b/drivers/gpu/drm/nouveau/nouveau_debugfs.c
+index 63cb5e432f8a..63b5c8cf9ae4 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_debugfs.c
++++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.c
+@@ -181,8 +181,11 @@ nouveau_debugfs_pstate_set(struct file *file, const char __user *ubuf,
+ 	}
+ 
+ 	ret = pm_runtime_get_sync(drm->dev);
+-	if (ret < 0 && ret != -EACCES)
++	if (ret < 0 && ret != -EACCES) {
++		pm_runtime_put_autosuspend(drm->dev);
+ 		return ret;
++	}
++
+ 	ret = nvif_mthd(ctrl, NVIF_CONTROL_PSTATE_USER, &args, sizeof(args));
+ 	pm_runtime_put_autosuspend(drm->dev);
+ 	if (ret < 0)

\ No newline at end of file diff --git a/detail/65.html b/detail/65.html new file mode 100644 index 0000000..8d0d15b --- /dev/null +++ b/detail/65.html @@ -0,0 +1,473 @@ +

Patches contributed by Unknown (whoi.edu)


commit 393df744e056ba24e9531d0657d09fc3c7c0dd22
+Author: Ned Forrester 
+Date:   Wed Nov 19 15:36:21 2008 -0800
+
+    pxa2xx_spi: bugfix full duplex dma data corruption
+    
+    Fixes a data corruption bug in pxa2xx_spi.c when operating in full duplex
+    mode with DMA and using buffers that overlap.
+    
+    SPI transmit and receive buffers are allowed to be the same or to overlap.
+     However, this driver fails if such overlap is attempted in DMA mode
+    because it maps the rx and tx buffers in the wrong order.  By mapping
+    DMA_FROM_DEVICE (read) before DMA_TO_DEVICE (write), it invalidates the
+    cache before flushing it, thus discarding data which should have been
+    transmitted.
+    
+    The patch corrects the order of mapping.  This bug exists in all versions
+    of pxa2xx_spi.c; similar bugs are in the drivers for two other SPI
+    controllers (au1500, imx).
+    
+    A version of this patch has been tested on kernel 2.6.20 using
+    verification of loopback data with: random transfer length, random
+    bits-per-word, random positive offsets (both larger and smaller than
+    transfer length) between the start of the rx and tx buffers, and varying
+    clock rates.
+    
+    Signed-off-by: Ned Forrester 
+    Cc: Vernon Sauder 
+    Cc: J. Scott Merritt 
+    Signed-off-by: David Brownell 
+    Cc:          [2.6.27.x]
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
+index dae87b1a4c6e..cf12f2d84be2 100644
+--- a/drivers/spi/pxa2xx_spi.c
++++ b/drivers/spi/pxa2xx_spi.c
+@@ -352,21 +352,21 @@ static int map_dma_buffers(struct driver_data *drv_data)
+ 	} else
+ 		drv_data->tx_map_len = drv_data->len;
+ 
+-	/* Stream map the rx buffer */
+-	drv_data->rx_dma = dma_map_single(dev, drv_data->rx,
+-						drv_data->rx_map_len,
+-						DMA_FROM_DEVICE);
+-	if (dma_mapping_error(dev, drv_data->rx_dma))
+-		return 0;
+-
+-	/* Stream map the tx buffer */
++	/* Stream map the tx buffer. Always do DMA_TO_DEVICE first
++	 * so we flush the cache *before* invalidating it, in case
++	 * the tx and rx buffers overlap.
++	 */
+ 	drv_data->tx_dma = dma_map_single(dev, drv_data->tx,
+-						drv_data->tx_map_len,
+-						DMA_TO_DEVICE);
++					drv_data->tx_map_len, DMA_TO_DEVICE);
++	if (dma_mapping_error(dev, drv_data->tx_dma))
++		return 0;
+ 
+-	if (dma_mapping_error(dev, drv_data->tx_dma)) {
+-		dma_unmap_single(dev, drv_data->rx_dma,
++	/* Stream map the rx buffer */
++	drv_data->rx_dma = dma_map_single(dev, drv_data->rx,
+ 					drv_data->rx_map_len, DMA_FROM_DEVICE);
++	if (dma_mapping_error(dev, drv_data->rx_dma)) {
++		dma_unmap_single(dev, drv_data->tx_dma,
++					drv_data->tx_map_len, DMA_TO_DEVICE);
+ 		return 0;
+ 	}
+ 

commit 7e96445533ac3f4f7964646a202ff3620602fab4
+Author: Ned Forrester 
+Date:   Sat Sep 13 02:33:18 2008 -0700
+
+    pxa2xx_spi: dma bugfixes
+    
+    Fixes two DMA bugs in the pxa2xx_spi driver.  The first bug is in all
+    versions of this driver; the second was introduced in the 2.6.20 kernel,
+    and prevents using the driver with chips like m25p16 flash (which can
+    issue large DMA reads).
+    
+     1. Zero length transfers are permitted for use to insert timing,
+        but pxa2xx_spi.c will fail if this is requested in DMA mode.
+        Fixed by using programmed I/O (PIO) mode for such transfers.
+    
+     2. Transfers larger than 8191 are not permitted in DMA mode.  A
+        test for length rejects all large transfers regardless of DMA
+        or PIO mode.  Worked around by rejecting only large transfers
+        with DMA mapped buffers, and forcing all other transfers
+        larger than 8191 to use PIO mode.  A rate limited warning is
+        issued for DMA transfers forced to PIO mode.
+    
+    This patch should apply to all kernels back to and including 2.6.20;
+    it was test patched against 2.6.20.  An additional patch would be
+    required for older kernels, but those versions are very buggy anyway.
+    
+    Signed-off-by: Ned Forrester 
+    Cc: Vernon Sauder 
+    Cc: Eric Miao 
+    Signed-off-by: David Brownell 
+    Cc:          [2.6.25.x, 2.6.26.x]
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
+index a7b9070e1b46..0e53354c1cfe 100644
+--- a/drivers/spi/pxa2xx_spi.c
++++ b/drivers/spi/pxa2xx_spi.c
+@@ -47,9 +47,10 @@ MODULE_ALIAS("platform:pxa2xx-spi");
+ 
+ #define MAX_BUSES 3
+ 
+-#define DMA_INT_MASK (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
+-#define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK)
+-#define IS_DMA_ALIGNED(x) (((u32)(x)&0x07)==0)
++#define DMA_INT_MASK		(DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
++#define RESET_DMA_CHANNEL	(DCSR_NODESC | DMA_INT_MASK)
++#define IS_DMA_ALIGNED(x)	(((x) & 0x07) == 0)
++#define MAX_DMA_LEN		8191
+ 
+ /*
+  * for testing SSCR1 changes that require SSP restart, basically
+@@ -887,14 +888,27 @@ static void pump_transfers(unsigned long data)
+ 			drv_data->cs_control(PXA2XX_CS_DEASSERT);
+ 	}
+ 
+-	/* Check transfer length */
+-	if (transfer->len > 8191)
+-	{
+-		dev_warn(&drv_data->pdev->dev, "pump_transfers: transfer "
+-				"length greater than 8191\n");
+-		message->status = -EINVAL;
+-		giveback(drv_data);
+-		return;
++	/* Check for transfers that need multiple DMA segments */
++	if (transfer->len > MAX_DMA_LEN && chip->enable_dma) {
++
++		/* reject already-mapped transfers; PIO won't always work */
++		if (message->is_dma_mapped
++				|| transfer->rx_dma || transfer->tx_dma) {
++			dev_err(&drv_data->pdev->dev,
++				"pump_transfers: mapped transfer length "
++				"of %lu is greater than %d\n",
++				transfer->len, MAX_DMA_LEN);
++			message->status = -EINVAL;
++			giveback(drv_data);
++			return;
++		}
++
++		/* warn ... we force this to PIO mode */
++		if (printk_ratelimit())
++			dev_warn(&message->spi->dev, "pump_transfers: "
++				"DMA disabled for transfer length %ld "
++				"greater than %d\n",
++				(long)drv_data->len, MAX_DMA_LEN);
+ 	}
+ 
+ 	/* Setup the transfer state based on the type of transfer */
+@@ -962,7 +976,7 @@ static void pump_transfers(unsigned long data)
+ 							&dma_thresh))
+ 				if (printk_ratelimit())
+ 					dev_warn(&message->spi->dev,
+-						"pump_transfer: "
++						"pump_transfers: "
+ 						"DMA burst size reduced to "
+ 						"match bits_per_word\n");
+ 		}
+@@ -976,8 +990,23 @@ static void pump_transfers(unsigned long data)
+ 
+ 	message->state = RUNNING_STATE;
+ 
+-	/* Try to map dma buffer and do a dma transfer if successful */
+-	if ((drv_data->dma_mapped = map_dma_buffers(drv_data))) {
++	/* Try to map dma buffer and do a dma transfer if successful, but
++	 * only if the length is non-zero and less than MAX_DMA_LEN.
++	 *
++	 * Zero-length non-descriptor DMA is illegal on PXA2xx; force use
++	 * of PIO instead.  Care is needed above because the transfer may
++	 * have have been passed with buffers that are already dma mapped.
++	 * A zero-length transfer in PIO mode will not try to write/read
++	 * to/from the buffers
++	 *
++	 * REVISIT large transfers are exactly where we most want to be
++	 * using DMA.  If this happens much, split those transfers into
++	 * multiple DMA segments rather than forcing PIO.
++	 */
++	drv_data->dma_mapped = 0;
++	if (drv_data->len > 0 && drv_data->len <= MAX_DMA_LEN)
++		drv_data->dma_mapped = map_dma_buffers(drv_data);
++	if (drv_data->dma_mapped) {
+ 
+ 		/* Ensure we have the correct interrupt handler */
+ 		drv_data->transfer_handler = dma_transfer;

commit 8423597d676615f3dd2d9ab36f59f147086b90b8
+Author: Ned Forrester 
+Date:   Sat Sep 13 02:33:17 2008 -0700
+
+    pxa2xx_spi: chipselect bugfixes
+    
+    Fixes several chipselect bugs in the pxa2xx_spi driver.  These bugs are in
+    all versions of this driver and prevent using it with chips like m25p16
+    flash.
+    
+     1. The spi_transfer.cs_change flag is handled too early:
+        before spi_transfer.delay_usecs applies, thus making the
+        delay ineffective at holding chip select.
+    
+     2. spi_transfer.delay_usecs is ignored on the last transfer
+        of a message (likewise not holding chipselect long enough).
+    
+     3. If spi_transfer.cs_change is set on the last transfer, the
+        chip select is always disabled, instead of the intended
+        meaning: optionally holding chip select enabled for the
+        next message.
+    
+    Those first three bugs were fixed with a relocation of delays
+    and chip select de-assertions.
+    
+     4. If a message has the cs_change flag set on the last transfer,
+        and had the chip select stayed enabled as requested (see 3,
+        above), it would not have been disabled if the next message is
+        for a different chip.  Fixed by dropping chip select regardless
+        of cs_change at end of a message, if there is no next message
+        or if the next message is for a different chip.
+    
+    This patch should apply to all kernels back to and including 2.6.20;
+    it was test patched against 2.6.20.  An additional patch would be
+    required for older kernels, but those versions are very buggy anyway.
+    
+    Signed-off-by: Ned Forrester 
+    Cc: Vernon Sauder 
+    Cc: Eric Miao 
+    Signed-off-by: David Brownell 
+    Cc:          [2.6.25.x, 2.6.26.x]
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
+index 34c7c9875681..a7b9070e1b46 100644
+--- a/drivers/spi/pxa2xx_spi.c
++++ b/drivers/spi/pxa2xx_spi.c
+@@ -144,7 +144,6 @@ struct driver_data {
+ 	size_t tx_map_len;
+ 	u8 n_bytes;
+ 	u32 dma_width;
+-	int cs_change;
+ 	int (*write)(struct driver_data *drv_data);
+ 	int (*read)(struct driver_data *drv_data);
+ 	irqreturn_t (*transfer_handler)(struct driver_data *drv_data);
+@@ -406,8 +405,45 @@ static void giveback(struct driver_data *drv_data)
+ 					struct spi_transfer,
+ 					transfer_list);
+ 
++	/* Delay if requested before any change in chip select */
++	if (last_transfer->delay_usecs)
++		udelay(last_transfer->delay_usecs);
++
++	/* Drop chip select UNLESS cs_change is true or we are returning
++	 * a message with an error, or next message is for another chip
++	 */
+ 	if (!last_transfer->cs_change)
+ 		drv_data->cs_control(PXA2XX_CS_DEASSERT);
++	else {
++		struct spi_message *next_msg;
++
++		/* Holding of cs was hinted, but we need to make sure
++		 * the next message is for the same chip.  Don't waste
++		 * time with the following tests unless this was hinted.
++		 *
++		 * We cannot postpone this until pump_messages, because
++		 * after calling msg->complete (below) the driver that
++		 * sent the current message could be unloaded, which
++		 * could invalidate the cs_control() callback...
++		 */
++
++		/* get a pointer to the next message, if any */
++		spin_lock_irqsave(&drv_data->lock, flags);
++		if (list_empty(&drv_data->queue))
++			next_msg = NULL;
++		else
++			next_msg = list_entry(drv_data->queue.next,
++					struct spi_message, queue);
++		spin_unlock_irqrestore(&drv_data->lock, flags);
++
++		/* see if the next and current messages point
++		 * to the same chip
++		 */
++		if (next_msg && next_msg->spi != msg->spi)
++			next_msg = NULL;
++		if (!next_msg || msg->state == ERROR_STATE)
++			drv_data->cs_control(PXA2XX_CS_DEASSERT);
++	}
+ 
+ 	msg->state = NULL;
+ 	if (msg->complete)
+@@ -490,10 +526,9 @@ static void dma_transfer_complete(struct driver_data *drv_data)
+ 	msg->actual_length += drv_data->len -
+ 				(drv_data->rx_end - drv_data->rx);
+ 
+-	/* Release chip select if requested, transfer delays are
+-	 * handled in pump_transfers */
+-	if (drv_data->cs_change)
+-		drv_data->cs_control(PXA2XX_CS_DEASSERT);
++	/* Transfer delays and chip select release are
++	 * handled in pump_transfers or giveback
++	 */
+ 
+ 	/* Move to next transfer */
+ 	msg->state = next_transfer(drv_data);
+@@ -602,10 +637,9 @@ static void int_transfer_complete(struct driver_data *drv_data)
+ 	drv_data->cur_msg->actual_length += drv_data->len -
+ 				(drv_data->rx_end - drv_data->rx);
+ 
+-	/* Release chip select if requested, transfer delays are
+-	 * handled in pump_transfers */
+-	if (drv_data->cs_change)
+-		drv_data->cs_control(PXA2XX_CS_DEASSERT);
++	/* Transfer delays and chip select release are
++	 * handled in pump_transfers or giveback
++	 */
+ 
+ 	/* Move to next transfer */
+ 	drv_data->cur_msg->state = next_transfer(drv_data);
+@@ -840,13 +874,17 @@ static void pump_transfers(unsigned long data)
+ 		return;
+ 	}
+ 
+-	/* Delay if requested at end of transfer*/
++	/* Delay if requested at end of transfer before CS change */
+ 	if (message->state == RUNNING_STATE) {
+ 		previous = list_entry(transfer->transfer_list.prev,
+ 					struct spi_transfer,
+ 					transfer_list);
+ 		if (previous->delay_usecs)
+ 			udelay(previous->delay_usecs);
++
++		/* Drop chip select only if cs_change is requested */
++		if (previous->cs_change)
++			drv_data->cs_control(PXA2XX_CS_DEASSERT);
+ 	}
+ 
+ 	/* Check transfer length */
+@@ -878,7 +916,6 @@ static void pump_transfers(unsigned long data)
+ 	drv_data->len = transfer->len & DCMD_LENGTH;
+ 	drv_data->write = drv_data->tx ? chip->write : null_writer;
+ 	drv_data->read = drv_data->rx ? chip->read : null_reader;
+-	drv_data->cs_change = transfer->cs_change;
+ 
+ 	/* Change speed and bit per word on a per transfer */
+ 	cr0 = chip->cr0;

commit b97c74bddce4e2c6fef6b3b58910b4fd9eb7f3b8
+Author: Ned Forrester 
+Date:   Sat Feb 23 15:23:40 2008 -0800
+
+    spi: pxa2xx_spi clock polarity fix
+    
+    Fixes a sequencing bug in spi driver pxa2xx_spi.c in which the chip select
+    for a transfer may be asserted before the clock polarity is set on the
+    interface.  As a result of this bug, the clock signal may have the wrong
+    polarity at transfer start, so it may need to make an extra half transition
+    before the intended clock/data signals begin.  (This probably means all
+    transfers are one bit out of sequence.)
+    
+    This only occurs on the first transfer following a change in clock polarity
+    in systems using more than one more than one such polarity.  The fix
+    assures that the clock mode is properly set before asserting chip select.
+    
+    This bug was introduced in a patch merged on 2006/12/10, kernel 2.6.20.
+    The patch defines an additional bit in: include/asm-arm/arch-pxa/regs-ssp.h
+    for 2.6.25 and newer kernels but this addition must be made in:
+    include/asm-arm/arch-pxa/pxa-regs.h for kernels between 2.6.20 and 2.6.24,
+    inclusive
+    
+    Signed-off-by: Ned Forrester 
+    Signed-off-by: David Brownell 
+    Cc: Russell King 
+    Cc: 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
+index 365e0e355aea..59deed79e0ab 100644
+--- a/drivers/spi/pxa2xx_spi.c
++++ b/drivers/spi/pxa2xx_spi.c
+@@ -51,13 +51,19 @@ MODULE_LICENSE("GPL");
+ #define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK)
+ #define IS_DMA_ALIGNED(x) (((u32)(x)&0x07)==0)
+ 
+-/* for testing SSCR1 changes that require SSP restart, basically
+- * everything except the service and interrupt enables */
+-#define SSCR1_CHANGE_MASK (SSCR1_TTELP | SSCR1_TTE | SSCR1_EBCEI | SSCR1_SCFR \
++/*
++ * for testing SSCR1 changes that require SSP restart, basically
++ * everything except the service and interrupt enables, the pxa270 developer
++ * manual says only SSCR1_SCFR, SSCR1_SPH, SSCR1_SPO need to be in this
++ * list, but the PXA255 dev man says all bits without really meaning the
++ * service and interrupt enables
++ */
++#define SSCR1_CHANGE_MASK (SSCR1_TTELP | SSCR1_TTE | SSCR1_SCFR \
+ 				| SSCR1_ECRA | SSCR1_ECRB | SSCR1_SCLKDIR \
+-				| SSCR1_RWOT | SSCR1_TRAIL | SSCR1_PINTE \
+-				| SSCR1_STRF | SSCR1_EFWR |SSCR1_RFT \
+-				| SSCR1_TFT | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)
++				| SSCR1_SFRMDIR | SSCR1_RWOT | SSCR1_TRAIL \
++				| SSCR1_IFS | SSCR1_STRF | SSCR1_EFWR \
++				| SSCR1_RFT | SSCR1_TFT | SSCR1_MWDS \
++				| SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)
+ 
+ #define DEFINE_SSP_REG(reg, off) \
+ static inline u32 read_##reg(void *p) { return __raw_readl(p + (off)); } \
+@@ -973,9 +979,6 @@ static void pump_transfers(unsigned long data)
+ 		if (drv_data->ssp_type == PXA25x_SSP)
+ 			DCMD(drv_data->tx_channel) |= DCMD_ENDIRQEN;
+ 
+-		/* Fix me, need to handle cs polarity */
+-		drv_data->cs_control(PXA2XX_CS_ASSERT);
+-
+ 		/* Clear status and start DMA engine */
+ 		cr1 = chip->cr1 | dma_thresh | drv_data->dma_cr1;
+ 		write_SSSR(drv_data->clear_sr, reg);
+@@ -985,9 +988,6 @@ static void pump_transfers(unsigned long data)
+ 		/* Ensure we have the correct interrupt handler	*/
+ 		drv_data->transfer_handler = interrupt_transfer;
+ 
+-		/* Fix me, need to handle cs polarity */
+-		drv_data->cs_control(PXA2XX_CS_ASSERT);
+-
+ 		/* Clear status  */
+ 		cr1 = chip->cr1 | chip->threshold | drv_data->int_cr1;
+ 		write_SSSR(drv_data->clear_sr, reg);
+@@ -998,16 +998,29 @@ static void pump_transfers(unsigned long data)
+ 		|| (read_SSCR1(reg) & SSCR1_CHANGE_MASK) !=
+ 			(cr1 & SSCR1_CHANGE_MASK)) {
+ 
++		/* stop the SSP, and update the other bits */
+ 		write_SSCR0(cr0 & ~SSCR0_SSE, reg);
+ 		if (drv_data->ssp_type != PXA25x_SSP)
+ 			write_SSTO(chip->timeout, reg);
+-		write_SSCR1(cr1, reg);
++		/* first set CR1 without interrupt and service enables */
++		write_SSCR1(cr1 & SSCR1_CHANGE_MASK, reg);
++		/* restart the SSP */
+ 		write_SSCR0(cr0, reg);
++
+ 	} else {
+ 		if (drv_data->ssp_type != PXA25x_SSP)
+ 			write_SSTO(chip->timeout, reg);
+-		write_SSCR1(cr1, reg);
+ 	}
++
++	/* FIXME, need to handle cs polarity,
++	 * this driver uses struct pxa2xx_spi_chip.cs_control to
++	 * specify a CS handling function, and it ignores most
++	 * struct spi_device.mode[s], including SPI_CS_HIGH */
++	drv_data->cs_control(PXA2XX_CS_ASSERT);
++
++	/* after chip select, release the data by enabling service
++	 * requests and interrupts, without changing any mode bits */
++	write_SSCR1(cr1, reg);
+ }
+ 
+ static void pump_messages(struct work_struct *work)
+diff --git a/include/asm-arm/arch-pxa/regs-ssp.h b/include/asm-arm/arch-pxa/regs-ssp.h
+index 991cb688db75..0255328c3c18 100644
+--- a/include/asm-arm/arch-pxa/regs-ssp.h
++++ b/include/asm-arm/arch-pxa/regs-ssp.h
+@@ -85,6 +85,7 @@
+ #define SSCR1_RSRE		(1 << 20)	/* Receive Service Request Enable */
+ #define SSCR1_TINTE		(1 << 19)	/* Receiver Time-out Interrupt enable */
+ #define SSCR1_PINTE		(1 << 18)	/* Peripheral Trailing Byte Interupt Enable */
++#define SSCR1_IFS		(1 << 16)	/* Invert Frame Signal */
+ #define SSCR1_STRF		(1 << 15)	/* Select FIFO or EFWR */
+ #define SSCR1_EFWR		(1 << 14)	/* Enable FIFO Write/Read */
+ 

\ No newline at end of file diff --git a/detail/7.html b/detail/7.html new file mode 100644 index 0000000..5813c57 --- /dev/null +++ b/detail/7.html @@ -0,0 +1,11089 @@ +

Patches contributed by University of Minnesota


commit f5e284bb74ab296f98122673c7ecd22028b2c200
+Author: Zhou Qingyang 
+Date:   Wed Dec 1 11:37:03 2021 +0800
+
+    drm/komeda: Fix an undefined behavior bug in komeda_plane_add()
+    
+    In komeda_plane_add(), komeda_get_layer_fourcc_list() is assigned to
+    formats and used in drm_universal_plane_init().
+    drm_universal_plane_init() passes formats to
+    __drm_universal_plane_init(). __drm_universal_plane_init() further
+    passes formats to memcpy() as src parameter, which could lead to an
+    undefined behavior bug on failure of komeda_get_layer_fourcc_list().
+    
+    Fix this bug by adding a check of formats.
+    
+    This bug was found by a static analyzer. The analysis employs
+    differential checking to identify inconsistent security operations
+    (e.g., checks or kfrees) between two code paths and confirms that the
+    inconsistent operations are not recovered in the current function or
+    the callers, so they constitute bugs.
+    
+    Note that, as a bug found by static analysis, it can be a false
+    positive or hard to trigger. Multiple researchers have cross-reviewed
+    the bug.
+    
+    Builds with CONFIG_DRM_KOMEDA=m show no new warnings,
+    and our static analyzer no longer warns about this code.
+    
+    Fixes: 61f1c4a8ab75 ("drm/komeda: Attach komeda_dev to DRM-KMS")
+    Signed-off-by: Zhou Qingyang 
+    Signed-off-by: Liviu Dudau 
+    Link: https://lore.kernel.org/dri-devel/20211201033704.32054-1-zhou1615@umn.edu
+
+diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
+index 541949f2d44a..9a8197a23c45 100644
+--- a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
++++ b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
+@@ -256,6 +256,10 @@ static int komeda_plane_add(struct komeda_kms_dev *kms,
+ 
+ 	formats = komeda_get_layer_fourcc_list(&mdev->fmt_tbl,
+ 					       layer->layer_type, &n_formats);
++	if (!formats) {
++		kfree(kplane);
++		return -ENOMEM;
++	}
+ 
+ 	err = drm_universal_plane_init(&kms->base, plane,
+ 			get_possible_crtcs(kms, c->pipeline),

commit abd77889851d2ead0d0c9c4d29f1808801477b00
+Author: Zhou Qingyang 
+Date:   Mon Jan 24 18:20:01 2022 +0100
+
+    media: ti-vpe: cal: Fix a NULL pointer dereference in cal_ctx_v4l2_init_formats()
+    
+    In cal_ctx_v4l2_init_formats(), devm_kzalloc() is assigned to
+    ctx->active_fmt and there is a dereference of it after that, which could
+    lead to NULL pointer dereference on failure of devm_kzalloc().
+    
+    Fix this bug by adding a NULL check of ctx->active_fmt.
+    
+    This bug was found by a static analyzer.
+    
+    Builds with 'make allyesconfig' show no new warnings, and our static
+    analyzer no longer warns about this code.
+    
+    Fixes: 7168155002cf ("media: ti-vpe: cal: Move format handling to cal.c and expose helpers")
+    Signed-off-by: Zhou Qingyang 
+    Reviewed-by: Pratyush Yadav 
+    Signed-off-by: Laurent Pinchart 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
+index 7799da1cc261..3e936a2ca36c 100644
+--- a/drivers/media/platform/ti-vpe/cal-video.c
++++ b/drivers/media/platform/ti-vpe/cal-video.c
+@@ -823,6 +823,9 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
+ 	/* Enumerate sub device formats and enable all matching local formats */
+ 	ctx->active_fmt = devm_kcalloc(ctx->cal->dev, cal_num_formats,
+ 				       sizeof(*ctx->active_fmt), GFP_KERNEL);
++	if (!ctx->active_fmt)
++		return -ENOMEM;
++
+ 	ctx->num_active_fmt = 0;
+ 
+ 	for (j = 0, i = 0; ; ++j) {

commit ab3824427b848da10e9fe2727f035bbeecae6ff4
+Author: Zhou Qingyang 
+Date:   Wed Dec 1 01:22:53 2021 +0800
+
+    spi: spi-zynq-qspi: Fix a NULL pointer dereference in zynq_qspi_exec_mem_op()
+    
+    In zynq_qspi_exec_mem_op(), kzalloc() is directly used in memset(),
+    which could lead to a NULL pointer dereference on failure of
+    kzalloc().
+    
+    Fix this bug by adding a check of tmpbuf.
+    
+    This bug was found by a static analyzer. The analysis employs
+    differential checking to identify inconsistent security operations
+    (e.g., checks or kfrees) between two code paths and confirms that the
+    inconsistent operations are not recovered in the current function or
+    the callers, so they constitute bugs.
+    
+    Note that, as a bug found by static analysis, it can be a false
+    positive or hard to trigger. Multiple researchers have cross-reviewed
+    the bug.
+    
+    Builds with CONFIG_SPI_ZYNQ_QSPI=m show no new warnings,
+    and our static analyzer no longer warns about this code.
+    
+    Fixes: 67dca5e580f1 ("spi: spi-mem: Add support for Zynq QSPI controller")
+    Signed-off-by: Zhou Qingyang 
+    Link: https://lore.kernel.org/r/20211130172253.203700-1-zhou1615@umn.edu
+    Signed-off-by: Mark Brown 
+
+diff --git a/drivers/spi/spi-zynq-qspi.c b/drivers/spi/spi-zynq-qspi.c
+index cfa222c9bd5e..78f31b61a2aa 100644
+--- a/drivers/spi/spi-zynq-qspi.c
++++ b/drivers/spi/spi-zynq-qspi.c
+@@ -570,6 +570,9 @@ static int zynq_qspi_exec_mem_op(struct spi_mem *mem,
+ 
+ 	if (op->dummy.nbytes) {
+ 		tmpbuf = kzalloc(op->dummy.nbytes, GFP_KERNEL);
++		if (!tmpbuf)
++			return -ENOMEM;
++
+ 		memset(tmpbuf, 0xff, op->dummy.nbytes);
+ 		reinit_completion(&xqspi->data_completion);
+ 		xqspi->txbuf = tmpbuf;

commit 9b6d90e2085ca2ce72ef9ea78658bf270855e62e
+Author: Zhou Qingyang 
+Date:   Tue Jan 25 00:45:25 2022 +0800
+
+    ata: pata_platform: Fix a NULL pointer dereference in __pata_platform_probe()
+    
+    In __pata_platform_probe(), devm_kzalloc() is assigned to ap->ops and
+    there is a dereference of it right after that, which could introduce a
+    NULL pointer dereference bug.
+    
+    Fix this by adding a NULL check of ap->ops.
+    
+    This bug was found by a static analyzer.
+    
+    Builds with 'make allyesconfig' show no new warnings,
+    and our static analyzer no longer warns about this code.
+    
+    Fixes: f3d5e4f18dba ("ata: pata_of_platform: Allow to use 16-bit wide data transfer")
+    Signed-off-by: Zhou Qingyang 
+    Signed-off-by: Damien Le Moal 
+    Reviewed-by: Sergey Shtylyov 
+
+diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
+index 028329428b75..87c7c90676ca 100644
+--- a/drivers/ata/pata_platform.c
++++ b/drivers/ata/pata_platform.c
+@@ -128,6 +128,8 @@ int __pata_platform_probe(struct device *dev, struct resource *io_res,
+ 	ap = host->ports[0];
+ 
+ 	ap->ops = devm_kzalloc(dev, sizeof(*ap->ops), GFP_KERNEL);
++	if (!ap->ops)
++		return -ENOMEM;
+ 	ap->ops->inherits = &ata_sff_port_ops;
+ 	ap->ops->cable_detect = ata_cable_unknown;
+ 	ap->ops->set_mode = pata_platform_set_mode;

commit 588a70177df3b1777484267584ef38ab2ca899a2
+Author: Zhou Qingyang 
+Date:   Tue Jan 25 00:57:29 2022 +0800
+
+    drm/amd/display: Fix a NULL pointer dereference in amdgpu_dm_connector_add_common_modes()
+    
+    In amdgpu_dm_connector_add_common_modes(), amdgpu_dm_create_common_mode()
+    is assigned to mode and is passed to drm_mode_probed_add() directly after
+    that. drm_mode_probed_add() passes &mode->head to list_add_tail(), and
+    there is a dereference of it in list_add_tail() without recoveries, which
+    could lead to NULL pointer dereference on failure of
+    amdgpu_dm_create_common_mode().
+    
+    Fix this by adding a NULL check of mode.
+    
+    This bug was found by a static analyzer.
+    
+    Builds with 'make allyesconfig' show no new warnings,
+    and our static analyzer no longer warns about this code.
+    
+    Fixes: e7b07ceef2a6 ("drm/amd/display: Merge amdgpu_dm_types and amdgpu_dm")
+    Signed-off-by: Zhou Qingyang 
+    Signed-off-by: Alex Deucher 
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 44f4d862a022..e6ff40fdf18b 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -8138,6 +8138,9 @@ static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder,
+ 		mode = amdgpu_dm_create_common_mode(encoder,
+ 				common_modes[i].name, common_modes[i].w,
+ 				common_modes[i].h);
++		if (!mode)
++			continue;
++
+ 		drm_mode_probed_add(connector, mode);
+ 		amdgpu_dm_connector->num_modes++;
+ 	}

commit 153a9529d7f372ce7ceb5eae7e2c312c0cd64d41
+Author: Zhou Qingyang 
+Date:   Tue Jan 25 00:55:51 2022 +0800
+
+    drm/amd/display/dc/calcs/dce_calcs: Fix a memleak in calculate_bandwidth()
+    
+    In calculate_bandwidth(), the tag free_sclk and free_yclk are reversed,
+    which could lead to a memory leak of yclk.
+    
+    Fix this bug by changing the location of free_sclk and free_yclk.
+    
+    This bug was found by a static analyzer.
+    
+    Builds with 'make allyesconfig' show no new warnings,
+    and our static analyzer no longer warns about this code.
+    
+    Fixes: 2be8989d0fc2 ("drm/amd/display/dc/calcs/dce_calcs: Move some large variables from the stack to the heap")
+    Signed-off-by: Zhou Qingyang 
+    Signed-off-by: Alex Deucher 
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/dml/calcs/dce_calcs.c
+index 8f136db39f3e..0100a6053ab6 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/calcs/dce_calcs.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/calcs/dce_calcs.c
+@@ -2033,10 +2033,10 @@ static void calculate_bandwidth(
+ 	kfree(surface_type);
+ free_tiling_mode:
+ 	kfree(tiling_mode);
+-free_yclk:
+-	kfree(yclk);
+ free_sclk:
+ 	kfree(sclk);
++free_yclk:
++	kfree(yclk);
+ }
+ 
+ /*******************************************************************************

commit ebc77bcc6e1660a011483c035d53c461c8dcc4f5
+Author: Zhou Qingyang 
+Date:   Tue Jan 25 00:55:51 2022 +0800
+
+    drm/amd/display/dc/calcs/dce_calcs: Fix a memleak in calculate_bandwidth()
+    
+    In calculate_bandwidth(), the tag free_sclk and free_yclk are reversed,
+    which could lead to a memory leak of yclk.
+    
+    Fix this bug by changing the location of free_sclk and free_yclk.
+    
+    This bug was found by a static analyzer.
+    
+    Builds with 'make allyesconfig' show no new warnings,
+    and our static analyzer no longer warns about this code.
+    
+    Fixes: 2be8989d0fc2 ("drm/amd/display/dc/calcs/dce_calcs: Move some large variables from the stack to the heap")
+    Signed-off-by: Zhou Qingyang 
+    Signed-off-by: Alex Deucher 
+
+diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c
+index ff5bb152ef49..e6ef36de0825 100644
+--- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c
++++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c
+@@ -2033,10 +2033,10 @@ static void calculate_bandwidth(
+ 	kfree(surface_type);
+ free_tiling_mode:
+ 	kfree(tiling_mode);
+-free_yclk:
+-	kfree(yclk);
+ free_sclk:
+ 	kfree(sclk);
++free_yclk:
++	kfree(yclk);
+ }
+ 
+ /*******************************************************************************

commit 2343bcdb4747d4f418a4daf2e898b94f86c24a59
+Author: Zhou Qingyang 
+Date:   Tue Jan 25 00:58:55 2022 +0800
+
+    drm/nouveau/acr: Fix undefined behavior in nvkm_acr_hsfw_load_bl()
+    
+    In nvkm_acr_hsfw_load_bl(), the return value of kmalloc() is directly
+    passed to memcpy(), which could lead to undefined behavior on failure
+    of kmalloc().
+    
+    Fix this bug by using kmemdup() instead of kmalloc()+memcpy().
+    
+    This bug was found by a static analyzer.
+    
+    Builds with 'make allyesconfig' show no new warnings,
+    and our static analyzer no longer warns about this code.
+    
+    Fixes: 22dcda45a3d1 ("drm/nouveau/acr: implement new subdev to replace "secure boot"")
+    Signed-off-by: Zhou Qingyang 
+    Reviewed-by: Lyude Paul 
+    Signed-off-by: Lyude Paul 
+    Link: https://patchwork.freedesktop.org/patch/msgid/20220124165856.57022-1-zhou1615@umn.edu
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c
+index 667fa016496e..a6ea89a5d51a 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c
+@@ -142,11 +142,12 @@ nvkm_acr_hsfw_load_bl(struct nvkm_acr *acr, const char *name, int ver,
+ 
+ 	hsfw->imem_size = desc->code_size;
+ 	hsfw->imem_tag = desc->start_tag;
+-	hsfw->imem = kmalloc(desc->code_size, GFP_KERNEL);
+-	memcpy(hsfw->imem, data + desc->code_off, desc->code_size);
+-
++	hsfw->imem = kmemdup(data + desc->code_off, desc->code_size, GFP_KERNEL);
+ 	nvkm_firmware_put(fw);
+-	return 0;
++	if (!hsfw->imem)
++		return -ENOMEM;
++	else
++		return 0;
+ }
+ 
+ int

commit 977d2e7c63c3d04d07ba340b39987742e3241554
+Author: Zhou Qingyang 
+Date:   Wed Dec 1 02:11:40 2021 +0800
+
+    pcmcia: rsrc_nonstatic: Fix a NULL pointer dereference in nonstatic_find_mem_region()
+    
+    In nonstatic_find_mem_region(), pcmcia_make_resource() is assigned to
+    res and used in pci_bus_alloc_resource(). There a dereference of res
+    in pci_bus_alloc_resource(), which could lead to a NULL pointer
+    dereference on failure of pcmcia_make_resource().
+    
+    Fix this bug by adding a check of res.
+    
+    This bug was found by a static analyzer. The analysis employs
+    differential checking to identify inconsistent security operations
+    (e.g., checks or kfrees) between two code paths and confirms that the
+    inconsistent operations are not recovered in the current function or
+    the callers, so they constitute bugs.
+    
+    Note that, as a bug found by static analysis, it can be a false
+    positive or hard to trigger. Multiple researchers have cross-reviewed
+    the bug.
+    
+    Builds with CONFIG_PCCARD_NONSTATIC=y show no new warnings,
+    and our static analyzer no longer warns about this code.
+    
+    Fixes: 49b1153adfe1 ("pcmcia: move all pcmcia_resource_ops providers into one module")
+    Signed-off-by: Zhou Qingyang 
+    Signed-off-by: Dominik Brodowski 
+
+diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
+index 827ca6e9ee54..1cac52870711 100644
+--- a/drivers/pcmcia/rsrc_nonstatic.c
++++ b/drivers/pcmcia/rsrc_nonstatic.c
+@@ -812,6 +812,9 @@ static struct resource *nonstatic_find_mem_region(u_long base, u_long num,
+ 	unsigned long min, max;
+ 	int ret, i, j;
+ 
++	if (!res)
++		return NULL;
++
+ 	low = low || !(s->features & SS_CAP_PAGE_REGS);
+ 
+ 	data.mask = align - 1;

commit ca0fe0d7c35c97528bdf621fdca75f13157c27af
+Author: Zhou Qingyang 
+Date:   Wed Dec 1 00:59:23 2021 +0800
+
+    pcmcia: rsrc_nonstatic: Fix a NULL pointer dereference in __nonstatic_find_io_region()
+    
+    In __nonstatic_find_io_region(), pcmcia_make_resource() is assigned to
+    res and used in pci_bus_alloc_resource(). There is a dereference of res
+    in pci_bus_alloc_resource(), which could lead to a NULL pointer
+    dereference on failure of pcmcia_make_resource().
+    
+    Fix this bug by adding a check of res.
+    
+    This bug was found by a static analyzer. The analysis employs
+    differential checking to identify inconsistent security operations
+    (e.g., checks or kfrees) between two code paths and confirms that the
+    inconsistent operations are not recovered in the current function or
+    the callers, so they constitute bugs.
+    
+    Note that, as a bug found by static analysis, it can be a false
+    positive or hard to trigger. Multiple researchers have cross-reviewed
+    the bug.
+    
+    Builds with CONFIG_PCCARD_NONSTATIC=y show no new warnings,
+    and our static analyzer no longer warns about this code.
+    
+    Fixes: 49b1153adfe1 ("pcmcia: move all pcmcia_resource_ops providers into one module")
+    Signed-off-by: Zhou Qingyang 
+    [linux@dominikbrodowski.net: Fix typo in commit message]
+    Signed-off-by: Dominik Brodowski 
+
+diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
+index bb15a8bdbaab..827ca6e9ee54 100644
+--- a/drivers/pcmcia/rsrc_nonstatic.c
++++ b/drivers/pcmcia/rsrc_nonstatic.c
+@@ -690,6 +690,9 @@ static struct resource *__nonstatic_find_io_region(struct pcmcia_socket *s,
+ 	unsigned long min = base;
+ 	int ret;
+ 
++	if (!res)
++		return NULL;
++
+ 	data.mask = align - 1;
+ 	data.offset = base & data.mask;
+ 	data.map = &s_data->io_db;

commit eccd25136386a04ebf46a64f3a34e8e0fab6d9e1
+Author: Zhou Qingyang 
+Date:   Mon Dec 13 11:53:07 2021 +0200
+
+    ath11k: Fix a NULL pointer dereference in ath11k_mac_op_hw_scan()
+    
+    In ath11k_mac_op_hw_scan(), the return value of kzalloc() is directly
+    used in memcpy(), which may lead to a NULL pointer dereference on
+    failure of kzalloc().
+    
+    Fix this bug by adding a check of arg.extraie.ptr.
+    
+    This bug was found by a static analyzer. The analysis employs
+    differential checking to identify inconsistent security operations
+    (e.g., checks or kfrees) between two code paths and confirms that the
+    inconsistent operations are not recovered in the current function or
+    the callers, so they constitute bugs.
+    
+    Note that, as a bug found by static analysis, it can be a false
+    positive or hard to trigger. Multiple researchers have cross-reviewed
+    the bug.
+    
+    Builds with CONFIG_ATH11K=m show no new warnings, and our static
+    analyzer no longer warns about this code.
+    
+    Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices")
+    Signed-off-by: Zhou Qingyang 
+    Signed-off-by: Kalle Valo 
+    Link: https://lore.kernel.org/r/20211202155348.71315-1-zhou1615@umn.edu
+
+diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
+index e8b76a311a54..6361378cb407 100644
+--- a/drivers/net/wireless/ath/ath11k/mac.c
++++ b/drivers/net/wireless/ath/ath11k/mac.c
+@@ -3520,9 +3520,12 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw,
+ 	arg.scan_id = ATH11K_SCAN_ID;
+ 
+ 	if (req->ie_len) {
++		arg.extraie.ptr = kmemdup(req->ie, req->ie_len, GFP_KERNEL);
++		if (!arg.extraie.ptr) {
++			ret = -ENOMEM;
++			goto exit;
++		}
+ 		arg.extraie.len = req->ie_len;
+-		arg.extraie.ptr = kzalloc(req->ie_len, GFP_KERNEL);
+-		memcpy(arg.extraie.ptr, req->ie, req->ie_len);
+ 	}
+ 
+ 	if (req->n_ssids) {

commit 3af86b046933ba513d08399dba0d4d8b50d607d0
+Author: Zhou Qingyang 
+Date:   Fri Dec 3 16:40:30 2021 +0100
+
+    media: saa7146: hexium_gemini: Fix a NULL pointer dereference in hexium_attach()
+    
+    In hexium_attach(dev, info), saa7146_vv_init() is called to allocate
+    a new memory for dev->vv_data. saa7146_vv_release() will be called on
+    failure of saa7146_register_device(). There is a dereference of
+    dev->vv_data in saa7146_vv_release(), which could lead to a NULL
+    pointer dereference on failure of saa7146_vv_init().
+    
+    Fix this bug by adding a check of saa7146_vv_init().
+    
+    This bug was found by a static analyzer. The analysis employs
+    differential checking to identify inconsistent security operations
+    (e.g., checks or kfrees) between two code paths and confirms that the
+    inconsistent operations are not recovered in the current function or
+    the callers, so they constitute bugs.
+    
+    Note that, as a bug found by static analysis, it can be a false
+    positive or hard to trigger. Multiple researchers have cross-reviewed
+    the bug.
+    
+    Builds with CONFIG_VIDEO_HEXIUM_GEMINI=m show no new warnings,
+    and our static analyzer no longer warns about this code.
+    
+    Link: https://lore.kernel.org/linux-media/20211203154030.111210-1-zhou1615@umn.edu
+    Signed-off-by: Zhou Qingyang 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/common/saa7146/saa7146_fops.c b/drivers/media/common/saa7146/saa7146_fops.c
+index baf5772c52a9..be3215977714 100644
+--- a/drivers/media/common/saa7146/saa7146_fops.c
++++ b/drivers/media/common/saa7146/saa7146_fops.c
+@@ -521,7 +521,7 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
+ 		ERR("out of memory. aborting.\n");
+ 		kfree(vv);
+ 		v4l2_ctrl_handler_free(hdl);
+-		return -1;
++		return -ENOMEM;
+ 	}
+ 
+ 	saa7146_video_uops.init(dev,vv);
+diff --git a/drivers/media/pci/saa7146/hexium_gemini.c b/drivers/media/pci/saa7146/hexium_gemini.c
+index 2214c74bbbf1..3947701cd6c7 100644
+--- a/drivers/media/pci/saa7146/hexium_gemini.c
++++ b/drivers/media/pci/saa7146/hexium_gemini.c
+@@ -284,7 +284,12 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d
+ 	hexium_set_input(hexium, 0);
+ 	hexium->cur_input = 0;
+ 
+-	saa7146_vv_init(dev, &vv_data);
++	ret = saa7146_vv_init(dev, &vv_data);
++	if (ret) {
++		i2c_del_adapter(&hexium->i2c_adapter);
++		kfree(hexium);
++		return ret;
++	}
+ 
+ 	vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
+ 	vv_data.vid_ops.vidioc_g_input = vidioc_g_input;

commit 0407c49ebe330333478440157c640fffd986f41b
+Author: Zhou Qingyang 
+Date:   Tue Nov 30 17:34:44 2021 +0100
+
+    media: saa7146: mxb: Fix a NULL pointer dereference in mxb_attach()
+    
+    In mxb_attach(dev, info), saa7146_vv_init() is called to allocate a
+    new memory for dev->vv_data. saa7146_vv_release() will be called on
+    failure of mxb_probe(dev). There is a dereference of dev->vv_data
+    in saa7146_vv_release(), which could lead to a NULL pointer dereference
+    on failure of saa7146_vv_init().
+    
+    Fix this bug by adding a check of saa7146_vv_init().
+    
+    This bug was found by a static analyzer. The analysis employs
+    differential checking to identify inconsistent security operations
+    (e.g., checks or kfrees) between two code paths and confirms that the
+    inconsistent operations are not recovered in the current function or
+    the callers, so they constitute bugs.
+    
+    Note that, as a bug found by static analysis, it can be a false
+    positive or hard to trigger. Multiple researchers have cross-reviewed
+    the bug.
+    
+    Builds with CONFIG_VIDEO_MXB=m show no new warnings,
+    and our static analyzer no longer warns about this code.
+    
+    Fixes: 03b1930efd3c ("V4L/DVB: saa7146: fix regression of the av7110/budget-av driver")
+    Signed-off-by: Zhou Qingyang 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/pci/saa7146/mxb.c b/drivers/media/pci/saa7146/mxb.c
+index 73fc901ecf3d..bf0b9b0914cd 100644
+--- a/drivers/media/pci/saa7146/mxb.c
++++ b/drivers/media/pci/saa7146/mxb.c
+@@ -683,10 +683,16 @@ static struct saa7146_ext_vv vv_data;
+ static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
+ {
+ 	struct mxb *mxb;
++	int ret;
+ 
+ 	DEB_EE("dev:%p\n", dev);
+ 
+-	saa7146_vv_init(dev, &vv_data);
++	ret = saa7146_vv_init(dev, &vv_data);
++	if (ret) {
++		ERR("Error in saa7146_vv_init()");
++		return ret;
++	}
++
+ 	if (mxb_probe(dev)) {
+ 		saa7146_vv_release(dev);
+ 		return -1;

commit 348df8035301dd212e3cc2860efe4c86cb0d3303
+Author: Zhou Qingyang 
+Date:   Tue Nov 30 17:25:49 2021 +0100
+
+    media: saa7146: hexium_orion: Fix a NULL pointer dereference in hexium_attach()
+    
+    In hexium_attach(dev, info), saa7146_vv_init() is called to allocate
+    a new memory for dev->vv_data. In hexium_detach(), saa7146_vv_release()
+    will be called and there is a dereference of dev->vv_data in
+    saa7146_vv_release(), which could lead to a NULL pointer dereference
+    on failure of saa7146_vv_init() according to the following logic.
+    
+    Both hexium_attach() and hexium_detach() are callback functions of
+    the variable 'extension', so there exists a possible call chain directly
+    from hexium_attach() to hexium_detach():
+    
+    hexium_attach(dev, info) -- fail to alloc memory to dev->vv_data
+            |                               in saa7146_vv_init().
+            |
+            |
+    hexium_detach() -- a dereference of dev->vv_data in saa7146_vv_release()
+    
+    Fix this bug by adding a check of saa7146_vv_init().
+    
+    This bug was found by a static analyzer. The analysis employs
+    differential checking to identify inconsistent security operations
+    (e.g., checks or kfrees) between two code paths and confirms that the
+    inconsistent operations are not recovered in the current function or
+    the callers, so they constitute bugs.
+    
+    Note that, as a bug found by static analysis, it can be a false
+    positive or hard to trigger. Multiple researchers have cross-reviewed
+    the bug.
+    
+    Builds with CONFIG_VIDEO_HEXIUM_ORION=m show no new warnings,
+    and our static analyzer no longer warns about this code.
+    
+    Signed-off-by: Zhou Qingyang 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/pci/saa7146/hexium_orion.c b/drivers/media/pci/saa7146/hexium_orion.c
+index 39d14c179d22..2eb4bee16b71 100644
+--- a/drivers/media/pci/saa7146/hexium_orion.c
++++ b/drivers/media/pci/saa7146/hexium_orion.c
+@@ -355,10 +355,16 @@ static struct saa7146_ext_vv vv_data;
+ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
+ {
+ 	struct hexium *hexium = (struct hexium *) dev->ext_priv;
++	int ret;
+ 
+ 	DEB_EE("\n");
+ 
+-	saa7146_vv_init(dev, &vv_data);
++	ret = saa7146_vv_init(dev, &vv_data);
++	if (ret) {
++		pr_err("Error in saa7146_vv_init()\n");
++		return ret;
++	}
++
+ 	vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
+ 	vv_data.vid_ops.vidioc_g_input = vidioc_g_input;
+ 	vv_data.vid_ops.vidioc_s_input = vidioc_s_input;

commit 8dbdcc7269a83305ee9d677b75064d3530a48ee2
+Author: Zhou Qingyang 
+Date:   Tue Nov 30 16:38:05 2021 +0100
+
+    media: dib8000: Fix a memleak in dib8000_init()
+    
+    In dib8000_init(), the variable fe is not freed or passed out on the
+    failure of dib8000_identify(&state->i2c), which could lead to a memleak.
+    
+    Fix this bug by adding a kfree of fe in the error path.
+    
+    This bug was found by a static analyzer. The analysis employs
+    differential checking to identify inconsistent security operations
+    (e.g., checks or kfrees) between two code paths and confirms that the
+    inconsistent operations are not recovered in the current function or
+    the callers, so they constitute bugs.
+    
+    Note that, as a bug found by static analysis, it can be a false
+    positive or hard to trigger. Multiple researchers have cross-reviewed
+    the bug.
+    
+    Builds with CONFIG_DVB_DIB8000=m show no new warnings,
+    and our static analyzer no longer warns about this code.
+    
+    Fixes: 77e2c0f5d471 ("V4L/DVB (12900): DiB8000: added support for DiBcom ISDB-T/ISDB-Tsb demodulator DiB8000")
+    Signed-off-by: Zhou Qingyang 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c
+index bb02354a48b8..d67f2dd997d0 100644
+--- a/drivers/media/dvb-frontends/dib8000.c
++++ b/drivers/media/dvb-frontends/dib8000.c
+@@ -4473,8 +4473,10 @@ static struct dvb_frontend *dib8000_init(struct i2c_adapter *i2c_adap, u8 i2c_ad
+ 
+ 	state->timf_default = cfg->pll->timf;
+ 
+-	if (dib8000_identify(&state->i2c) == 0)
++	if (dib8000_identify(&state->i2c) == 0) {
++		kfree(fe);
+ 		goto error;
++	}
+ 
+ 	dibx000_init_i2c_master(&state->i2c_master, DIB8000, state->i2c.adap, state->i2c.addr);
+ 

commit 37307f7020ab38dde0892a578249bf63d00bca64
+Author: Zhou Qingyang 
+Date:   Wed Dec 1 01:27:00 2021 +0800
+
+    usb: cdnsp: Fix a NULL pointer dereference in cdnsp_endpoint_init()
+    
+    In cdnsp_endpoint_init(), cdnsp_ring_alloc() is assigned to pep->ring
+    and there is a dereference of it in cdnsp_endpoint_init(), which could
+    lead to a NULL pointer dereference on failure of cdnsp_ring_alloc().
+    
+    Fix this bug by adding a check of pep->ring.
+    
+    This bug was found by a static analyzer. The analysis employs
+    differential checking to identify inconsistent security operations
+    (e.g., checks or kfrees) between two code paths and confirms that the
+    inconsistent operations are not recovered in the current function or
+    the callers, so they constitute bugs.
+    
+    Note that, as a bug found by static analysis, it can be a false
+    positive or hard to trigger. Multiple researchers have cross-reviewed
+    the bug.
+    
+    Builds with CONFIG_USB_CDNSP_GADGET=y show no new warnings,
+    and our static analyzer no longer warns about this code.
+    
+    Fixes: 3d82904559f4 ("usb: cdnsp: cdns3 Add main part of Cadence USBSSP DRD Driver")
+    Cc: stable 
+    Acked-by: Pawel Laszczak 
+    Acked-by: Peter Chen 
+    Signed-off-by: Zhou Qingyang 
+    Link: https://lore.kernel.org/r/20211130172700.206650-1-zhou1615@umn.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/cdns3/cdnsp-mem.c b/drivers/usb/cdns3/cdnsp-mem.c
+index ad9aee3f1e39..97866bfb2da9 100644
+--- a/drivers/usb/cdns3/cdnsp-mem.c
++++ b/drivers/usb/cdns3/cdnsp-mem.c
+@@ -987,6 +987,9 @@ int cdnsp_endpoint_init(struct cdnsp_device *pdev,
+ 
+ 	/* Set up the endpoint ring. */
+ 	pep->ring = cdnsp_ring_alloc(pdev, 2, ring_type, max_packet, mem_flags);
++	if (!pep->ring)
++		return -ENOMEM;
++
+ 	pep->skip = false;
+ 
+ 	/* Fill the endpoint context */

commit ab50cb9df8896b39aae65c537a30de2c79c19735
+Author: Zhou Qingyang 
+Date:   Wed Dec 1 23:13:10 2021 +0800
+
+    drm/radeon/radeon_kms: Fix a NULL pointer dereference in radeon_driver_open_kms()
+    
+    In radeon_driver_open_kms(), radeon_vm_bo_add() is assigned to
+    vm->ib_bo_va and passes and used in radeon_vm_bo_set_addr(). In
+    radeon_vm_bo_set_addr(), there is a dereference of vm->ib_bo_va,
+    which could lead to a NULL pointer dereference on failure of
+    radeon_vm_bo_add().
+    
+    Fix this bug by adding a check of vm->ib_bo_va.
+    
+    This bug was found by a static analyzer. The analysis employs
+    differential checking to identify inconsistent security operations
+    (e.g., checks or kfrees) between two code paths and confirms that the
+    inconsistent operations are not recovered in the current function or
+    the callers, so they constitute bugs.
+    
+    Note that, as a bug found by static analysis, it can be a false
+    positive or hard to trigger. Multiple researchers have cross-reviewed
+    the bug.
+    
+    Builds with CONFIG_DRM_RADEON=m show no new warnings,
+    and our static analyzer no longer warns about this code.
+    
+    Fixes: cc9e67e3d700 ("drm/radeon: fix VM IB handling")
+    Reviewed-by: Christian König 
+    Signed-off-by: Zhou Qingyang 
+    Signed-off-by: Alex Deucher 
+
+diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
+index 7afe28408085..e2488559cc9f 100644
+--- a/drivers/gpu/drm/radeon/radeon_kms.c
++++ b/drivers/gpu/drm/radeon/radeon_kms.c
+@@ -648,6 +648,8 @@ void radeon_driver_lastclose_kms(struct drm_device *dev)
+ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
+ {
+ 	struct radeon_device *rdev = dev->dev_private;
++	struct radeon_fpriv *fpriv;
++	struct radeon_vm *vm;
+ 	int r;
+ 
+ 	file_priv->driver_priv = NULL;
+@@ -660,8 +662,6 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
+ 
+ 	/* new gpu have virtual address space support */
+ 	if (rdev->family >= CHIP_CAYMAN) {
+-		struct radeon_fpriv *fpriv;
+-		struct radeon_vm *vm;
+ 
+ 		fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);
+ 		if (unlikely(!fpriv)) {
+@@ -672,35 +672,39 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
+ 		if (rdev->accel_working) {
+ 			vm = &fpriv->vm;
+ 			r = radeon_vm_init(rdev, vm);
+-			if (r) {
+-				kfree(fpriv);
+-				goto out_suspend;
+-			}
++			if (r)
++				goto out_fpriv;
+ 
+ 			r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);
+-			if (r) {
+-				radeon_vm_fini(rdev, vm);
+-				kfree(fpriv);
+-				goto out_suspend;
+-			}
++			if (r)
++				goto out_vm_fini;
+ 
+ 			/* map the ib pool buffer read only into
+ 			 * virtual address space */
+ 			vm->ib_bo_va = radeon_vm_bo_add(rdev, vm,
+ 							rdev->ring_tmp_bo.bo);
++			if (!vm->ib_bo_va) {
++				r = -ENOMEM;
++				goto out_vm_fini;
++			}
++
+ 			r = radeon_vm_bo_set_addr(rdev, vm->ib_bo_va,
+ 						  RADEON_VA_IB_OFFSET,
+ 						  RADEON_VM_PAGE_READABLE |
+ 						  RADEON_VM_PAGE_SNOOPED);
+-			if (r) {
+-				radeon_vm_fini(rdev, vm);
+-				kfree(fpriv);
+-				goto out_suspend;
+-			}
++			if (r)
++				goto out_vm_fini;
+ 		}
+ 		file_priv->driver_priv = fpriv;
+ 	}
+ 
++	if (!r)
++		goto out_suspend;
++
++out_vm_fini:
++	radeon_vm_fini(rdev, vm);
++out_fpriv:
++	kfree(fpriv);
+ out_suspend:
+ 	pm_runtime_mark_last_busy(dev->dev);
+ 	pm_runtime_put_autosuspend(dev->dev);

commit b220110e4cd442156f36e1d9b4914bb9e87b0d00
+Author: Zhou Qingyang 
+Date:   Fri Dec 3 00:17:36 2021 +0800
+
+    drm/amdgpu: Fix a NULL pointer dereference in amdgpu_connector_lcd_native_mode()
+    
+    In amdgpu_connector_lcd_native_mode(), the return value of
+    drm_mode_duplicate() is assigned to mode, and there is a dereference
+    of it in amdgpu_connector_lcd_native_mode(), which will lead to a NULL
+    pointer dereference on failure of drm_mode_duplicate().
+    
+    Fix this bug add a check of mode.
+    
+    This bug was found by a static analyzer. The analysis employs
+    differential checking to identify inconsistent security operations
+    (e.g., checks or kfrees) between two code paths and confirms that the
+    inconsistent operations are not recovered in the current function or
+    the callers, so they constitute bugs.
+    
+    Note that, as a bug found by static analysis, it can be a false
+    positive or hard to trigger. Multiple researchers have cross-reviewed
+    the bug.
+    
+    Builds with CONFIG_DRM_AMDGPU=m show no new warnings, and
+    our static analyzer no longer warns about this code.
+    
+    Fixes: d38ceaf99ed0 ("drm/amdgpu: add core driver (v4)")
+    Signed-off-by: Zhou Qingyang 
+    Signed-off-by: Alex Deucher 
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
+index 0de66f59adb8..df1f9b88a53f 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
+@@ -387,6 +387,9 @@ amdgpu_connector_lcd_native_mode(struct drm_encoder *encoder)
+ 	    native_mode->vdisplay != 0 &&
+ 	    native_mode->clock != 0) {
+ 		mode = drm_mode_duplicate(dev, native_mode);
++		if (!mode)
++			return NULL;
++
+ 		mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
+ 		drm_mode_set_name(mode);
+ 
+@@ -401,6 +404,9 @@ amdgpu_connector_lcd_native_mode(struct drm_encoder *encoder)
+ 		 * simpler.
+ 		 */
+ 		mode = drm_cvt_mode(dev, native_mode->hdisplay, native_mode->vdisplay, 60, true, false, false);
++		if (!mode)
++			return NULL;
++
+ 		mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
+ 		DRM_DEBUG_KMS("Adding cvt approximation of native panel mode %s\n", mode->name);
+ 	}

commit e07a097b4986afb8f925d0bb32612e1d3e88ce15
+Author: Zhou Qingyang 
+Date:   Wed Dec 1 00:50:39 2021 +0800
+
+    octeontx2-af: Fix a memleak bug in rvu_mbox_init()
+    
+    In rvu_mbox_init(), mbox_regions is not freed or passed out
+    under the switch-default region, which could lead to a memory leak.
+    
+    Fix this bug by changing 'return err' to 'goto free_regions'.
+    
+    This bug was found by a static analyzer. The analysis employs
+    differential checking to identify inconsistent security operations
+    (e.g., checks or kfrees) between two code paths and confirms that the
+    inconsistent operations are not recovered in the current function or
+    the callers, so they constitute bugs.
+    
+    Note that, as a bug found by static analysis, it can be a false
+    positive or hard to trigger. Multiple researchers have cross-reviewed
+    the bug.
+    
+    Builds with CONFIG_OCTEONTX2_AF=y show no new warnings,
+    and our static analyzer no longer warns about this code.
+    
+    Fixes: 98c561116360 (“octeontx2-af: cn10k: Add mbox support for CN10K platform”)
+    Signed-off-by: Zhou Qingyang 
+    Link: https://lore.kernel.org/r/20211130165039.192426-1-zhou1615@umn.edu
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
+index cb56e171ddd4..3ca6b942ebe2 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
+@@ -2341,7 +2341,7 @@ static int rvu_mbox_init(struct rvu *rvu, struct mbox_wq_info *mw,
+ 			goto free_regions;
+ 		break;
+ 	default:
+-		return err;
++		goto free_regions;
+ 	}
+ 
+ 	mw->mbox_wq = alloc_workqueue(name,

commit addad7643142f500080417dd7272f49b7a185570
+Author: Zhou Qingyang 
+Date:   Wed Dec 1 00:44:38 2021 +0800
+
+    net/mlx4_en: Fix an use-after-free bug in mlx4_en_try_alloc_resources()
+    
+    In mlx4_en_try_alloc_resources(), mlx4_en_copy_priv() is called and
+    tmp->tx_cq will be freed on the error path of mlx4_en_copy_priv().
+    After that mlx4_en_alloc_resources() is called and there is a dereference
+    of &tmp->tx_cq[t][i] in mlx4_en_alloc_resources(), which could lead to
+    a use after free problem on failure of mlx4_en_copy_priv().
+    
+    Fix this bug by adding a check of mlx4_en_copy_priv()
+    
+    This bug was found by a static analyzer. The analysis employs
+    differential checking to identify inconsistent security operations
+    (e.g., checks or kfrees) between two code paths and confirms that the
+    inconsistent operations are not recovered in the current function or
+    the callers, so they constitute bugs.
+    
+    Note that, as a bug found by static analysis, it can be a false
+    positive or hard to trigger. Multiple researchers have cross-reviewed
+    the bug.
+    
+    Builds with CONFIG_MLX4_EN=m show no new warnings,
+    and our static analyzer no longer warns about this code.
+    
+    Fixes: ec25bc04ed8e ("net/mlx4_en: Add resilience in low memory systems")
+    Signed-off-by: Zhou Qingyang 
+    Reviewed-by: Leon Romanovsky 
+    Link: https://lore.kernel.org/r/20211130164438.190591-1-zhou1615@umn.edu
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+index 3f6d5c384637..f1c10f2bda78 100644
+--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
++++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+@@ -2286,9 +2286,14 @@ int mlx4_en_try_alloc_resources(struct mlx4_en_priv *priv,
+ 				bool carry_xdp_prog)
+ {
+ 	struct bpf_prog *xdp_prog;
+-	int i, t;
++	int i, t, ret;
+ 
+-	mlx4_en_copy_priv(tmp, priv, prof);
++	ret = mlx4_en_copy_priv(tmp, priv, prof);
++	if (ret) {
++		en_warn(priv, "%s: mlx4_en_copy_priv() failed, return\n",
++			__func__);
++		return ret;
++	}
+ 
+ 	if (mlx4_en_alloc_resources(tmp)) {
+ 		en_warn(priv,

commit e2dabc4f7e7b60299c20a36d6a7b24ed9bf8e572
+Author: Zhou Qingyang 
+Date:   Tue Nov 30 19:08:48 2021 +0800
+
+    net: qlogic: qlcnic: Fix a NULL pointer dereference in qlcnic_83xx_add_rings()
+    
+    In qlcnic_83xx_add_rings(), the indirect function of
+    ahw->hw_ops->alloc_mbx_args will be called to allocate memory for
+    cmd.req.arg, and there is a dereference of it in qlcnic_83xx_add_rings(),
+    which could lead to a NULL pointer dereference on failure of the
+    indirect function like qlcnic_83xx_alloc_mbx_args().
+    
+    Fix this bug by adding a check of alloc_mbx_args(), this patch
+    imitates the logic of mbx_cmd()'s failure handling.
+    
+    This bug was found by a static analyzer. The analysis employs
+    differential checking to identify inconsistent security operations
+    (e.g., checks or kfrees) between two code paths and confirms that the
+    inconsistent operations are not recovered in the current function or
+    the callers, so they constitute bugs.
+    
+    Note that, as a bug found by static analysis, it can be a false
+    positive or hard to trigger. Multiple researchers have cross-reviewed
+    the bug.
+    
+    Builds with CONFIG_QLCNIC=m show no new warnings, and our
+    static analyzer no longer warns about this code.
+    
+    Fixes: 7f9664525f9c ("qlcnic: 83xx memory map and HW access routine")
+    Signed-off-by: Zhou Qingyang 
+    Link: https://lore.kernel.org/r/20211130110848.109026-1-zhou1615@umn.edu
+    Signed-off-by: Jakub Kicinski 
+
+diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+index d51bac7ba5af..bd0607680329 100644
+--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+@@ -1077,8 +1077,14 @@ static int qlcnic_83xx_add_rings(struct qlcnic_adapter *adapter)
+ 	sds_mbx_size = sizeof(struct qlcnic_sds_mbx);
+ 	context_id = recv_ctx->context_id;
+ 	num_sds = adapter->drv_sds_rings - QLCNIC_MAX_SDS_RINGS;
+-	ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+-				    QLCNIC_CMD_ADD_RCV_RINGS);
++	err = ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
++					QLCNIC_CMD_ADD_RCV_RINGS);
++	if (err) {
++		dev_err(&adapter->pdev->dev,
++			"Failed to alloc mbx args %d\n", err);
++		return err;
++	}
++
+ 	cmd.req.arg[1] = 0 | (num_sds << 8) | (context_id << 16);
+ 
+ 	/* set up status rings, mbx 2-81 */

commit 49a8bf50caa2fb0fb2eb1c89923ea61192227c32
+Author: Zhou Qingyang 
+Date:   Tue Nov 30 22:15:44 2021 +0800
+
+    drm/i915/gem: Fix a NULL pointer dereference in igt_request_rewind()
+    
+    In igt_request_rewind(), mock_context(i915, "A") is assigned to ctx[0]
+    and used in i915_gem_context_get_engine(). There is a dereference
+    of ctx[0] in i915_gem_context_get_engine(), which could lead to a NULL
+    pointer dereference on failure of mock_context(i915, "A") .
+    
+    So as mock_context(i915, "B").
+    
+    Although this bug is not serious for it belongs to testing code, it is
+    better to be fixed to avoid unexpected failure in testing.
+    
+    Fix this bugs by adding checks about ctx[0] and ctx[1].
+    
+    This bug was found by a static analyzer. The analysis employs
+    differential checking to identify inconsistent security operations
+    (e.g., checks or kfrees) between two code paths and confirms that the
+    inconsistent operations are not recovered in the current function or
+    the callers, so they constitute bugs.
+    
+    Note that, as a bug found by static analysis, it can be a false
+    positive or hard to trigger. Multiple researchers have cross-reviewed
+    the bug.
+    
+    Builds with CONFIG_DRM_I915_SELFTEST=y show no new warnings,
+    and our static analyzer no longer warns about this code.
+    
+    References: 591c0fb85d1c ("drm/i915: Exercise request cancellation using a mock selftest")
+    [tursulin: Replaced fixes with references to avoid.]
+    Signed-off-by: Zhou Qingyang 
+    Reviewed-by: Tvrtko Ursulin 
+    Signed-off-by: Tvrtko Ursulin 
+    Link: https://patchwork.freedesktop.org/patch/msgid/20211130141545.153899-1-zhou1615@umn.edu
+
+diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c
+index 6496671a113c..9979ef9197cd 100644
+--- a/drivers/gpu/drm/i915/selftests/i915_request.c
++++ b/drivers/gpu/drm/i915/selftests/i915_request.c
+@@ -209,6 +209,10 @@ static int igt_request_rewind(void *arg)
+ 	int err = -EINVAL;
+ 
+ 	ctx[0] = mock_context(i915, "A");
++	if (!ctx[0]) {
++		err = -ENOMEM;
++		goto err_ctx_0;
++	}
+ 
+ 	ce = i915_gem_context_get_engine(ctx[0], RCS0);
+ 	GEM_BUG_ON(IS_ERR(ce));
+@@ -223,6 +227,10 @@ static int igt_request_rewind(void *arg)
+ 	i915_request_add(request);
+ 
+ 	ctx[1] = mock_context(i915, "B");
++	if (!ctx[1]) {
++		err = -ENOMEM;
++		goto err_ctx_1;
++	}
+ 
+ 	ce = i915_gem_context_get_engine(ctx[1], RCS0);
+ 	GEM_BUG_ON(IS_ERR(ce));
+@@ -261,9 +269,11 @@ static int igt_request_rewind(void *arg)
+ 	i915_request_put(vip);
+ err_context_1:
+ 	mock_context_close(ctx[1]);
++err_ctx_1:
+ 	i915_request_put(request);
+ err_context_0:
+ 	mock_context_close(ctx[0]);
++err_ctx_0:
+ 	mock_device_flush(i915);
+ 	return err;
+ }

commit 0c85a7e87465f2d4cbc768e245f4f45b2f299b05
+Author: Aditya Pakki 
+Date:   Tue Apr 6 19:09:12 2021 -0500
+
+    net/rds: Avoid potential use after free in rds_send_remove_from_sock
+    
+    In case of rs failure in rds_send_remove_from_sock(), the 'rm' resource
+    is freed and later under spinlock, causing potential use-after-free.
+    Set the free pointer to NULL to avoid undefined behavior.
+    
+    Signed-off-by: Aditya Pakki 
+    Acked-by: Santosh Shilimkar 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/rds/message.c b/net/rds/message.c
+index 799034e0f513..4fc66ff0f1ec 100644
+--- a/net/rds/message.c
++++ b/net/rds/message.c
+@@ -180,6 +180,7 @@ void rds_message_put(struct rds_message *rm)
+ 		rds_message_purge(rm);
+ 
+ 		kfree(rm);
++		rm = NULL;
+ 	}
+ }
+ EXPORT_SYMBOL_GPL(rds_message_put);
+diff --git a/net/rds/send.c b/net/rds/send.c
+index 985d0b7713ac..fe5264b9d4b3 100644
+--- a/net/rds/send.c
++++ b/net/rds/send.c
+@@ -665,7 +665,7 @@ static void rds_send_remove_from_sock(struct list_head *messages, int status)
+ unlock_and_drop:
+ 		spin_unlock_irqrestore(&rm->m_rs_lock, flags);
+ 		rds_message_put(rm);
+-		if (was_on_sock)
++		if (was_on_sock && rm)
+ 			rds_message_put(rm);
+ 	}
+ 

commit 57cc666d36adc7b45e37ba4cd7bc4e44ec4c43d7
+Author: Aditya Pakki 
+Date:   Sun Jun 14 05:58:41 2020 +0200
+
+    media: st-delta: Fix reference count leak in delta_run_work
+    
+    delta_run_work() calls delta_get_sync() that increments
+    the reference counter. In case of failure, decrement the reference
+    count by calling delta_put_autosuspend().
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/sti/delta/delta-v4l2.c b/drivers/media/platform/sti/delta/delta-v4l2.c
+index 2503224eeee5..c691b3d81549 100644
+--- a/drivers/media/platform/sti/delta/delta-v4l2.c
++++ b/drivers/media/platform/sti/delta/delta-v4l2.c
+@@ -954,8 +954,10 @@ static void delta_run_work(struct work_struct *work)
+ 	/* enable the hardware */
+ 	if (!dec->pm) {
+ 		ret = delta_get_sync(ctx);
+-		if (ret)
++		if (ret) {
++			delta_put_autosuspend(ctx);
+ 			goto err;
++		}
+ 	}
+ 
+ 	/* decode this access unit */

commit 6f4432bae9f2d12fc1815b5e26cc07e69bcad0df
+Author: Qiushi Wu 
+Date:   Sun Jun 14 05:31:06 2020 +0200
+
+    media: sti: Fix reference count leaks
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code, causing incorrect ref count if
+    pm_runtime_put_noidle() is not called in error handling paths.
+    Thus call pm_runtime_put_noidle() if pm_runtime_get_sync() fails.
+    
+    Signed-off-by: Qiushi Wu 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/sti/hva/hva-hw.c b/drivers/media/platform/sti/hva/hva-hw.c
+index 8533d3bc6d5c..43f279e2a6a3 100644
+--- a/drivers/media/platform/sti/hva/hva-hw.c
++++ b/drivers/media/platform/sti/hva/hva-hw.c
+@@ -272,6 +272,7 @@ static unsigned long int hva_hw_get_ip_version(struct hva_dev *hva)
+ 
+ 	if (pm_runtime_get_sync(dev) < 0) {
+ 		dev_err(dev, "%s     failed to get pm_runtime\n", HVA_PREFIX);
++		pm_runtime_put_noidle(dev);
+ 		mutex_unlock(&hva->protect_mutex);
+ 		return -EFAULT;
+ 	}
+@@ -553,6 +554,7 @@ void hva_hw_dump_regs(struct hva_dev *hva, struct seq_file *s)
+ 
+ 	if (pm_runtime_get_sync(dev) < 0) {
+ 		seq_puts(s, "Cannot wake up IP\n");
++		pm_runtime_put_noidle(dev);
+ 		mutex_unlock(&hva->protect_mutex);
+ 		return;
+ 	}

commit 7ef64ceea0008c17e94a8a2c60c5d6d46f481996
+Author: Qiushi Wu 
+Date:   Sun Jun 14 05:18:29 2020 +0200
+
+    media: exynos4-is: Fix several reference count leaks due to pm_runtime_get_sync
+    
+    On calling pm_runtime_get_sync() the reference count of the device
+    is incremented. In case of failure, decrement the
+    reference count before returning the error.
+    
+    Signed-off-by: Qiushi Wu 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/exynos4-is/fimc-isp.c b/drivers/media/platform/exynos4-is/fimc-isp.c
+index cde0d254ec1c..a77c49b18511 100644
+--- a/drivers/media/platform/exynos4-is/fimc-isp.c
++++ b/drivers/media/platform/exynos4-is/fimc-isp.c
+@@ -305,8 +305,10 @@ static int fimc_isp_subdev_s_power(struct v4l2_subdev *sd, int on)
+ 
+ 	if (on) {
+ 		ret = pm_runtime_get_sync(&is->pdev->dev);
+-		if (ret < 0)
++		if (ret < 0) {
++			pm_runtime_put(&is->pdev->dev);
+ 			return ret;
++		}
+ 		set_bit(IS_ST_PWR_ON, &is->state);
+ 
+ 		ret = fimc_is_start_firmware(is);
+diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c
+index 9c666f663ab4..fdd0d369b192 100644
+--- a/drivers/media/platform/exynos4-is/fimc-lite.c
++++ b/drivers/media/platform/exynos4-is/fimc-lite.c
+@@ -471,7 +471,7 @@ static int fimc_lite_open(struct file *file)
+ 	set_bit(ST_FLITE_IN_USE, &fimc->state);
+ 	ret = pm_runtime_get_sync(&fimc->pdev->dev);
+ 	if (ret < 0)
+-		goto unlock;
++		goto err_pm;
+ 
+ 	ret = v4l2_fh_open(file);
+ 	if (ret < 0)

commit c47f7c779ef0458a58583f00c9ed71b7f5a4d0a2
+Author: Qiushi Wu 
+Date:   Sun Jun 14 05:10:58 2020 +0200
+
+    media: exynos4-is: Fix a reference count leak due to pm_runtime_get_sync
+    
+    On calling pm_runtime_get_sync() the reference count of the device
+    is incremented. In case of failure, decrement the
+    reference count before returning the error.
+    
+    Signed-off-by: Qiushi Wu 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
+index 7d92793a8e74..e636c33e847b 100644
+--- a/drivers/media/platform/exynos4-is/media-dev.c
++++ b/drivers/media/platform/exynos4-is/media-dev.c
+@@ -509,8 +509,10 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
+ 		return -ENXIO;
+ 
+ 	ret = pm_runtime_get_sync(fmd->pmf);
+-	if (ret < 0)
++	if (ret < 0) {
++		pm_runtime_put(fmd->pmf);
+ 		return ret;
++	}
+ 
+ 	fmd->num_sensors = 0;
+ 

commit 64157b2cb1940449e7df2670e85781c690266588
+Author: Qiushi Wu 
+Date:   Sun Jun 14 05:01:11 2020 +0200
+
+    media: exynos4-is: Fix a reference count leak
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code, causing incorrect ref count if
+    pm_runtime_put_noidle() is not called in error handling paths.
+    Thus call pm_runtime_put_noidle() if pm_runtime_get_sync() fails.
+    
+    Signed-off-by: Qiushi Wu 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c
+index 540151bbf58f..1aac167abb17 100644
+--- a/drivers/media/platform/exynos4-is/mipi-csis.c
++++ b/drivers/media/platform/exynos4-is/mipi-csis.c
+@@ -510,8 +510,10 @@ static int s5pcsis_s_stream(struct v4l2_subdev *sd, int enable)
+ 	if (enable) {
+ 		s5pcsis_clear_counters(state);
+ 		ret = pm_runtime_get_sync(&state->pdev->dev);
+-		if (ret && ret != 1)
++		if (ret && ret != 1) {
++			pm_runtime_put_noidle(&state->pdev->dev);
+ 			return ret;
++		}
+ 	}
+ 
+ 	mutex_lock(&state->lock);

commit 7dae2aaaf432767ca7aa11fa84643a7c2600dbdd
+Author: Qiushi Wu 
+Date:   Sun Jun 14 04:56:05 2020 +0200
+
+    media: ti-vpe: Fix a missing check and reference count leak
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code, causing incorrect ref count if
+    pm_runtime_put_noidle() is not called in error handling paths.
+    And also, when the call of function vpe_runtime_get() failed,
+    we won't call vpe_runtime_put().
+    Thus call pm_runtime_put_noidle() if pm_runtime_get_sync() fails
+    inside vpe_runtime_get().
+    
+    Fixes: 4571912743ac ("[media] v4l: ti-vpe: Add VPE mem to mem driver")
+    Signed-off-by: Qiushi Wu 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c
+index 346f8212791c..779dd74b82d0 100644
+--- a/drivers/media/platform/ti-vpe/vpe.c
++++ b/drivers/media/platform/ti-vpe/vpe.c
+@@ -2475,6 +2475,8 @@ static int vpe_runtime_get(struct platform_device *pdev)
+ 
+ 	r = pm_runtime_get_sync(&pdev->dev);
+ 	WARN_ON(r < 0);
++	if (r)
++		pm_runtime_put_noidle(&pdev->dev);
+ 	return r < 0 ? r : 0;
+ }
+ 

commit 88f50a05f907d96a27a9ce3cc9e8cbb91a6f0f22
+Author: Qiushi Wu 
+Date:   Sun Jun 14 04:36:59 2020 +0200
+
+    media: stm32-dcmi: Fix a reference count leak
+    
+    Calling pm_runtime_get_sync increments the counter even in case of
+    failure, causing incorrect ref count if pm_runtime_put is not
+    called in error handling paths. Thus replace the jump target
+    "err_release_buffers" by "err_pm_putw".
+    
+    Fixes: 152e0bf60219 ("media: stm32-dcmi: add power saving support")
+    Signed-off-by: Qiushi Wu 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c
+index b8931490b83b..fd1c41cba52f 100644
+--- a/drivers/media/platform/stm32/stm32-dcmi.c
++++ b/drivers/media/platform/stm32/stm32-dcmi.c
+@@ -733,7 +733,7 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
+ 	if (ret < 0) {
+ 		dev_err(dcmi->dev, "%s: Failed to start streaming, cannot get sync (%d)\n",
+ 			__func__, ret);
+-		goto err_release_buffers;
++		goto err_pm_put;
+ 	}
+ 
+ 	ret = media_pipeline_start(&dcmi->vdev->entity, &dcmi->pipeline);
+@@ -837,8 +837,6 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
+ 
+ err_pm_put:
+ 	pm_runtime_put(dcmi->dev);
+-
+-err_release_buffers:
+ 	spin_lock_irq(&dcmi->irqlock);
+ 	/*
+ 	 * Return all buffers to vb2 in QUEUED state.

commit 78741ce98c2e36188e2343434406b0e0bc50b0e7
+Author: Qiushi Wu 
+Date:   Sun Jun 14 04:31:22 2020 +0200
+
+    media: s5p-mfc: Fix a reference count leak
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code, causing incorrect ref count if
+    pm_runtime_put_noidle() is not called in error handling paths.
+    Thus call pm_runtime_put_noidle() if pm_runtime_get_sync() fails.
+    
+    Fixes: c5086f130a77 ("[media] s5p-mfc: Use clock gating only on MFC v5 hardware")
+    Signed-off-by: Qiushi Wu 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
+index 7d52431c2c83..62d2320a7218 100644
+--- a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
++++ b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
+@@ -79,8 +79,10 @@ int s5p_mfc_power_on(void)
+ 	int i, ret = 0;
+ 
+ 	ret = pm_runtime_get_sync(pm->device);
+-	if (ret < 0)
++	if (ret < 0) {
++		pm_runtime_put_noidle(pm->device);
+ 		return ret;
++	}
+ 
+ 	/* clock control */
+ 	for (i = 0; i < pm->num_clocks; i++) {

commit d0675b67b42eb4f1a840d1513b5b00f78312f833
+Author: Qiushi Wu 
+Date:   Sun Jun 14 01:27:12 2020 +0200
+
+    media: camss: Fix a reference count leak.
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code, causing incorrect ref count if
+    PM runtime put is not called in error handling paths.
+    Thus call pm_runtime_put_sync() if pm_runtime_get_sync() fails.
+    
+    Fixes: 02afa816dbbf ("media: camss: Add basic runtime PM support")
+    Signed-off-by: Qiushi Wu 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.c b/drivers/media/platform/qcom/camss/camss-csiphy.c
+index 03ef9c5f4774..85b24054f35e 100644
+--- a/drivers/media/platform/qcom/camss/camss-csiphy.c
++++ b/drivers/media/platform/qcom/camss/camss-csiphy.c
+@@ -176,8 +176,10 @@ static int csiphy_set_power(struct v4l2_subdev *sd, int on)
+ 		int ret;
+ 
+ 		ret = pm_runtime_get_sync(dev);
+-		if (ret < 0)
++		if (ret < 0) {
++			pm_runtime_put_sync(dev);
+ 			return ret;
++		}
+ 
+ 		ret = csiphy_set_clock_rates(csiphy);
+ 		if (ret < 0) {

commit 63e36a381d92a9cded97e90d481ee22566557dd1
+Author: Qiushi Wu 
+Date:   Sun Jun 14 01:19:44 2020 +0200
+
+    media: platform: fcp: Fix a reference count leak.
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code, causing incorrect ref count if
+    pm_runtime_put_noidle() is not called in error handling paths.
+    Thus call pm_runtime_put_noidle() if pm_runtime_get_sync() fails.
+    
+    Fixes: 6eaafbdb668b ("[media] v4l: rcar-fcp: Keep the coding style consistent")
+    Signed-off-by: Qiushi Wu 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/rcar-fcp.c b/drivers/media/platform/rcar-fcp.c
+index 13a84c7e3586..5c03318ae07b 100644
+--- a/drivers/media/platform/rcar-fcp.c
++++ b/drivers/media/platform/rcar-fcp.c
+@@ -102,8 +102,10 @@ int rcar_fcp_enable(struct rcar_fcp_device *fcp)
+ 		return 0;
+ 
+ 	ret = pm_runtime_get_sync(fcp->dev);
+-	if (ret < 0)
++	if (ret < 0) {
++		pm_runtime_put_noidle(fcp->dev);
+ 		return ret;
++	}
+ 
+ 	return 0;
+ }

commit 884d638e0853c4b5f01eb6d048fc3b6239012404
+Author: Qiushi Wu 
+Date:   Sun Jun 14 01:13:49 2020 +0200
+
+    media: rockchip/rga: Fix a reference count leak.
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus call pm_runtime_put_noidle()
+    if pm_runtime_get_sync() fails.
+    
+    Fixes: f7e7b48e6d79 ("[media] rockchip/rga: v4l2 m2m support")
+    Signed-off-by: Qiushi Wu 
+    Reviewed-by: Heiko Stuebner 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/rockchip/rga/rga-buf.c b/drivers/media/platform/rockchip/rga/rga-buf.c
+index 36b821ccc1db..bf9a75b75083 100644
+--- a/drivers/media/platform/rockchip/rga/rga-buf.c
++++ b/drivers/media/platform/rockchip/rga/rga-buf.c
+@@ -81,6 +81,7 @@ static int rga_buf_start_streaming(struct vb2_queue *q, unsigned int count)
+ 
+ 	ret = pm_runtime_get_sync(rga->dev);
+ 	if (ret < 0) {
++		pm_runtime_put_noidle(rga->dev);
+ 		rga_buf_return_buffers(q, VB2_BUF_STATE_QUEUED);
+ 		return ret;
+ 	}

commit 410822037cc909c4bef845a71e9cac92b75591d2
+Author: Qiushi Wu 
+Date:   Sun Jun 14 01:04:32 2020 +0200
+
+    media: rcar-vin: Fix a reference count leak.
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus call pm_runtime_put_noidle()
+    if pm_runtime_get_sync() fails.
+    
+    Fixes: 2a18fbec1dab ("media: rcar-vin: Move pm_runtime_{get,put} out of helpers")
+    Signed-off-by: Qiushi Wu 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c
+index 0e066bba747e..92415cf42dc9 100644
+--- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
++++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
+@@ -844,8 +844,10 @@ static int rvin_open(struct file *file)
+ 	int ret;
+ 
+ 	ret = pm_runtime_get_sync(vin->dev);
+-	if (ret < 0)
++	if (ret < 0) {
++		pm_runtime_put_noidle(vin->dev);
+ 		return ret;
++	}
+ 
+ 	ret = mutex_lock_interruptible(&vin->lock);
+ 	if (ret)

commit aaffa0126a111d65f4028c503c76192d4cc93277
+Author: Qiushi Wu 
+Date:   Sun Jun 14 00:30:08 2020 +0200
+
+    media: rcar-vin: Fix a reference count leak.
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code. Thus call pm_runtime_put_noidle()
+    if pm_runtime_get_sync() fails.
+    
+    Fixes: 90dedce9bc54 ("media: rcar-vin: add function to manipulate Gen3 chsel value")
+    Signed-off-by: Qiushi Wu 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c
+index d067439b0b0d..3504dd4a70e9 100644
+--- a/drivers/media/platform/rcar-vin/rcar-dma.c
++++ b/drivers/media/platform/rcar-vin/rcar-dma.c
+@@ -1420,8 +1420,10 @@ int rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel)
+ 	int ret;
+ 
+ 	ret = pm_runtime_get_sync(vin->dev);
+-	if (ret < 0)
++	if (ret < 0) {
++		pm_runtime_put_noidle(vin->dev);
+ 		return ret;
++	}
+ 
+ 	/* Make register writes take effect immediately. */
+ 	vnmc = rvin_read(vin, VNMC_REG);

commit fe3c60684377d5ad9b0569b87ed3e26e12c8173b
+Author: Qiushi Wu 
+Date:   Sat Jun 13 14:05:33 2020 -0500
+
+    firmware: Fix a reference count leak.
+    
+    kobject_init_and_add() takes reference even when it fails.
+    If this function returns an error, kobject_put() must be called to
+    properly clean up the memory associated with the object.
+    Callback function fw_cfg_sysfs_release_entry() in kobject_put()
+    can handle the pointer "entry" properly.
+    
+    Signed-off-by: Qiushi Wu 
+    Link: https://lore.kernel.org/r/20200613190533.15712-1-wu000273@umn.edu
+    Signed-off-by: Michael S. Tsirkin 
+
+diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
+index 039e0f91dba8..6945c3c96637 100644
+--- a/drivers/firmware/qemu_fw_cfg.c
++++ b/drivers/firmware/qemu_fw_cfg.c
+@@ -605,8 +605,10 @@ static int fw_cfg_register_file(const struct fw_cfg_file *f)
+ 	/* register entry under "/sys/firmware/qemu_fw_cfg/by_key/" */
+ 	err = kobject_init_and_add(&entry->kobj, &fw_cfg_sysfs_entry_ktype,
+ 				   fw_cfg_sel_ko, "%d", entry->select);
+-	if (err)
+-		goto err_register;
++	if (err) {
++		kobject_put(&entry->kobj);
++		return err;
++	}
+ 
+ 	/* add raw binary content access */
+ 	err = sysfs_create_bin_file(&entry->kobj, &fw_cfg_sysfs_attr_raw);
+@@ -622,7 +624,6 @@ static int fw_cfg_register_file(const struct fw_cfg_file *f)
+ 
+ err_add_raw:
+ 	kobject_del(&entry->kobj);
+-err_register:
+ 	kfree(entry);
+ 	return err;
+ }

commit 8f29432417b11039ef960ab18987c7d61b2b5396
+Author: Aditya Pakki 
+Date:   Sat Jun 13 20:48:37 2020 -0500
+
+    drm/nouveau: fix reference count leak in nouveau_debugfs_strap_peek
+    
+    nouveau_debugfs_strap_peek() calls pm_runtime_get_sync() that
+    increments the reference count. In case of failure, decrement the
+    ref count before returning the error.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.c b/drivers/gpu/drm/nouveau/nouveau_debugfs.c
+index 63b5c8cf9ae4..8f63cda3db17 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_debugfs.c
++++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.c
+@@ -54,8 +54,10 @@ nouveau_debugfs_strap_peek(struct seq_file *m, void *data)
+ 	int ret;
+ 
+ 	ret = pm_runtime_get_sync(drm->dev->dev);
+-	if (ret < 0 && ret != -EACCES)
++	if (ret < 0 && ret != -EACCES) {
++		pm_runtime_put_autosuspend(drm->dev->dev);
+ 		return ret;
++	}
+ 
+ 	seq_printf(m, "0x%08x\n",
+ 		   nvif_rd32(&drm->client.device.object, 0x101000));

commit 990a1162986e8eff7ca18cc5a0e03b4304392ae2
+Author: Aditya Pakki 
+Date:   Sat Jun 13 20:22:23 2020 -0500
+
+    drm/nouveau: Fix reference count leak in nouveau_connector_detect
+    
+    nouveau_connector_detect() calls pm_runtime_get_sync and in turn
+    increments the reference count. In case of failure, decrement the
+    ref count before returning the error.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
+index ab2c2b2cab10..1fa5d5614261 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
++++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
+@@ -571,8 +571,10 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
+ 		pm_runtime_get_noresume(dev->dev);
+ 	} else {
+ 		ret = pm_runtime_get_sync(dev->dev);
+-		if (ret < 0 && ret != -EACCES)
++		if (ret < 0 && ret != -EACCES) {
++			pm_runtime_put_autosuspend(dev->dev);
+ 			return conn_status;
++		}
+ 	}
+ 
+ 	nv_encoder = nouveau_connector_ddc_detect(connector);

commit a2cdf39536b0d21fb06113f5e16692513d7bcb9c
+Author: Aditya Pakki 
+Date:   Sat Jun 13 20:29:18 2020 -0500
+
+    drm/nouveau: fix reference count leak in nv50_disp_atomic_commit
+    
+    nv50_disp_atomic_commit() calls calls pm_runtime_get_sync and in turn
+    increments the reference count. In case of failure, decrement the
+    ref count before returning the error.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
+index 4c2894d8e15b..f4921460dbef 100644
+--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
+@@ -2171,8 +2171,10 @@ nv50_disp_atomic_commit(struct drm_device *dev,
+ 	int ret, i;
+ 
+ 	ret = pm_runtime_get_sync(dev->dev);
+-	if (ret < 0 && ret != -EACCES)
++	if (ret < 0 && ret != -EACCES) {
++		pm_runtime_put_autosuspend(dev->dev);
+ 		return ret;
++	}
+ 
+ 	ret = drm_atomic_helper_setup_commit(state, nonblock);
+ 	if (ret)

commit 659fb5f154c3434c90a34586f3b7aa1c39cf6062
+Author: Aditya Pakki 
+Date:   Sat Jun 13 20:41:56 2020 -0500
+
+    drm/nouveau: fix multiple instances of reference count leaks
+    
+    On calling pm_runtime_get_sync() the reference count of the device
+    is incremented. In case of failure, decrement the
+    ref count before returning the error.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
+index ac93d12201dc..880d962c1b19 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
++++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
+@@ -1026,8 +1026,10 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)
+ 
+ 	/* need to bring up power immediately if opening device */
+ 	ret = pm_runtime_get_sync(dev->dev);
+-	if (ret < 0 && ret != -EACCES)
++	if (ret < 0 && ret != -EACCES) {
++		pm_runtime_put_autosuspend(dev->dev);
+ 		return ret;
++	}
+ 
+ 	get_task_comm(tmpname, current);
+ 	snprintf(name, sizeof(name), "%s[%d]", tmpname, pid_nr(fpriv->pid));
+@@ -1109,8 +1111,10 @@ nouveau_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ 	long ret;
+ 
+ 	ret = pm_runtime_get_sync(dev->dev);
+-	if (ret < 0 && ret != -EACCES)
++	if (ret < 0 && ret != -EACCES) {
++		pm_runtime_put_autosuspend(dev->dev);
+ 		return ret;
++	}
+ 
+ 	switch (_IOC_NR(cmd) - DRM_COMMAND_BASE) {
+ 	case DRM_NOUVEAU_NVIF:
+diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
+index 63b832585390..133ab6fb7798 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
++++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
+@@ -45,8 +45,10 @@ nouveau_gem_object_del(struct drm_gem_object *gem)
+ 	int ret;
+ 
+ 	ret = pm_runtime_get_sync(dev);
+-	if (WARN_ON(ret < 0 && ret != -EACCES))
++	if (WARN_ON(ret < 0 && ret != -EACCES)) {
++		pm_runtime_put_autosuspend(dev);
+ 		return;
++	}
+ 
+ 	if (gem->import_attach)
+ 		drm_prime_gem_destroy(gem, nvbo->bo.sg);

commit bfad51c7633325b5d4b32444efe04329d53297b2
+Author: Aditya Pakki 
+Date:   Sat Jun 13 20:33:42 2020 -0500
+
+    drm/nouveau/drm/noveau: fix reference count leak in nouveau_fbcon_open
+    
+    nouveau_fbcon_open() calls calls pm_runtime_get_sync() that
+    increments the reference count. In case of failure, decrement the
+    ref count before returning the error.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Ben Skeggs 
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+index f9f5a13fdb80..4a93641c33e1 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
++++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+@@ -189,8 +189,10 @@ nouveau_fbcon_open(struct fb_info *info, int user)
+ 	struct nouveau_fbdev *fbcon = info->par;
+ 	struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
+ 	int ret = pm_runtime_get_sync(drm->dev->dev);
+-	if (ret < 0 && ret != -EACCES)
++	if (ret < 0 && ret != -EACCES) {
++		pm_runtime_put(drm->dev->dev);
+ 		return ret;
++	}
+ 	return 0;
+ }
+ 

commit 8a94644b440eef5a7b9c104ac8aa7a7f413e35e5
+Author: Qiushi Wu 
+Date:   Wed May 27 21:13:22 2020 -0500
+
+    PCI: Fix pci_create_slot() reference count leak
+    
+    kobject_init_and_add() takes a reference even when it fails.  If it returns
+    an error, kobject_put() must be called to clean up the memory associated
+    with the object.
+    
+    When kobject_init_and_add() fails, call kobject_put() instead of kfree().
+    
+    b8eb718348b8 ("net-sysfs: Fix reference count leak in
+    rx|netdev_queue_add_kobject") fixed a similar problem.
+    
+    Link: https://lore.kernel.org/r/20200528021322.1984-1-wu000273@umn.edu
+    Signed-off-by: Qiushi Wu 
+    Signed-off-by: Bjorn Helgaas 
+
+diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c
+index cc386ef2fa12..3861505741e6 100644
+--- a/drivers/pci/slot.c
++++ b/drivers/pci/slot.c
+@@ -268,13 +268,16 @@ struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
+ 	slot_name = make_slot_name(name);
+ 	if (!slot_name) {
+ 		err = -ENOMEM;
++		kfree(slot);
+ 		goto err;
+ 	}
+ 
+ 	err = kobject_init_and_add(&slot->kobj, &pci_slot_ktype, NULL,
+ 				   "%s", slot_name);
+-	if (err)
++	if (err) {
++		kobject_put(&slot->kobj);
+ 		goto err;
++	}
+ 
+ 	INIT_LIST_HEAD(&slot->list);
+ 	list_add(&slot->list, &parent->slots);
+@@ -293,7 +296,6 @@ struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
+ 	mutex_unlock(&pci_slot_mutex);
+ 	return slot;
+ err:
+-	kfree(slot);
+ 	slot = ERR_PTR(err);
+ 	goto out;
+ }

commit 78c2ce9bde70be5be7e3615a2ae7024ed8173087
+Author: Aditya Pakki 
+Date:   Sat Jun 13 22:05:18 2020 -0500
+
+    omapfb: fix multiple reference count leaks due to pm_runtime_get_sync
+    
+    On calling pm_runtime_get_sync() the reference count of the device
+    is incremented. In case of failure, decrement the
+    reference count before returning the error.
+    
+    Signed-off-by: Aditya Pakki 
+    Cc: kjlu@umn.edu
+    Cc: wu000273@umn.edu
+    Cc: Allison Randal 
+    Cc: Thomas Gleixner 
+    Cc: Enrico Weigelt 
+    cc: "Andrew F. Davis" 
+    Cc: Tomi Valkeinen 
+    Cc: Alexios Zavras 
+    Cc: Greg Kroah-Hartman 
+    Cc: YueHaibing 
+    Signed-off-by: Bartlomiej Zolnierkiewicz 
+    Link: https://patchwork.freedesktop.org/patch/msgid/20200614030528.128064-1-pakki001@umn.edu
+
+diff --git a/drivers/video/fbdev/omap2/omapfb/dss/dispc.c b/drivers/video/fbdev/omap2/omapfb/dss/dispc.c
+index 3bb951eb29c7..3920a0db0390 100644
+--- a/drivers/video/fbdev/omap2/omapfb/dss/dispc.c
++++ b/drivers/video/fbdev/omap2/omapfb/dss/dispc.c
+@@ -520,8 +520,11 @@ int dispc_runtime_get(void)
+ 	DSSDBG("dispc_runtime_get\n");
+ 
+ 	r = pm_runtime_get_sync(&dispc.pdev->dev);
+-	WARN_ON(r < 0);
+-	return r < 0 ? r : 0;
++	if (WARN_ON(r < 0)) {
++		pm_runtime_put_sync(&dispc.pdev->dev);
++		return r;
++	}
++	return 0;
+ }
+ EXPORT_SYMBOL(dispc_runtime_get);
+ 
+diff --git a/drivers/video/fbdev/omap2/omapfb/dss/dsi.c b/drivers/video/fbdev/omap2/omapfb/dss/dsi.c
+index d620376216e1..6f9c25fec994 100644
+--- a/drivers/video/fbdev/omap2/omapfb/dss/dsi.c
++++ b/drivers/video/fbdev/omap2/omapfb/dss/dsi.c
+@@ -1137,8 +1137,11 @@ static int dsi_runtime_get(struct platform_device *dsidev)
+ 	DSSDBG("dsi_runtime_get\n");
+ 
+ 	r = pm_runtime_get_sync(&dsi->pdev->dev);
+-	WARN_ON(r < 0);
+-	return r < 0 ? r : 0;
++	if (WARN_ON(r < 0)) {
++		pm_runtime_put_sync(&dsi->pdev->dev);
++		return r;
++	}
++	return 0;
+ }
+ 
+ static void dsi_runtime_put(struct platform_device *dsidev)
+diff --git a/drivers/video/fbdev/omap2/omapfb/dss/dss.c b/drivers/video/fbdev/omap2/omapfb/dss/dss.c
+index 7252d22dd117..3586579c838f 100644
+--- a/drivers/video/fbdev/omap2/omapfb/dss/dss.c
++++ b/drivers/video/fbdev/omap2/omapfb/dss/dss.c
+@@ -768,8 +768,11 @@ int dss_runtime_get(void)
+ 	DSSDBG("dss_runtime_get\n");
+ 
+ 	r = pm_runtime_get_sync(&dss.pdev->dev);
+-	WARN_ON(r < 0);
+-	return r < 0 ? r : 0;
++	if (WARN_ON(r < 0)) {
++		pm_runtime_put_sync(&dss.pdev->dev);
++		return r;
++	}
++	return 0;
+ }
+ 
+ void dss_runtime_put(void)
+diff --git a/drivers/video/fbdev/omap2/omapfb/dss/hdmi4.c b/drivers/video/fbdev/omap2/omapfb/dss/hdmi4.c
+index ef659c89ba58..1bbbda21d76c 100644
+--- a/drivers/video/fbdev/omap2/omapfb/dss/hdmi4.c
++++ b/drivers/video/fbdev/omap2/omapfb/dss/hdmi4.c
+@@ -39,9 +39,10 @@ static int hdmi_runtime_get(void)
+ 	DSSDBG("hdmi_runtime_get\n");
+ 
+ 	r = pm_runtime_get_sync(&hdmi.pdev->dev);
+-	WARN_ON(r < 0);
+-	if (r < 0)
++	if (WARN_ON(r < 0)) {
++		pm_runtime_put_sync(&hdmi.pdev->dev);
+ 		return r;
++	}
+ 
+ 	return 0;
+ }
+diff --git a/drivers/video/fbdev/omap2/omapfb/dss/hdmi5.c b/drivers/video/fbdev/omap2/omapfb/dss/hdmi5.c
+index ac49531e4732..a06b6f1355bd 100644
+--- a/drivers/video/fbdev/omap2/omapfb/dss/hdmi5.c
++++ b/drivers/video/fbdev/omap2/omapfb/dss/hdmi5.c
+@@ -43,9 +43,10 @@ static int hdmi_runtime_get(void)
+ 	DSSDBG("hdmi_runtime_get\n");
+ 
+ 	r = pm_runtime_get_sync(&hdmi.pdev->dev);
+-	WARN_ON(r < 0);
+-	if (r < 0)
++	if (WARN_ON(r < 0)) {
++		pm_runtime_put_sync(&hdmi.pdev->dev);
+ 		return r;
++	}
+ 
+ 	return 0;
+ }
+diff --git a/drivers/video/fbdev/omap2/omapfb/dss/venc.c b/drivers/video/fbdev/omap2/omapfb/dss/venc.c
+index d5404d56c922..0b0ad20afd63 100644
+--- a/drivers/video/fbdev/omap2/omapfb/dss/venc.c
++++ b/drivers/video/fbdev/omap2/omapfb/dss/venc.c
+@@ -348,8 +348,11 @@ static int venc_runtime_get(void)
+ 	DSSDBG("venc_runtime_get\n");
+ 
+ 	r = pm_runtime_get_sync(&venc.pdev->dev);
+-	WARN_ON(r < 0);
+-	return r < 0 ? r : 0;
++	if (WARN_ON(r < 0)) {
++		pm_runtime_put_sync(&venc.pdev->dev);
++		return r;
++	}
++	return 0;
+ }
+ 
+ static void venc_runtime_put(void)

commit 9fb10671011143d15b6b40d6d5fa9c52c57e9d63
+Author: Aditya Pakki 
+Date:   Sat Jun 13 21:21:22 2020 -0500
+
+    drm/radeon: Fix reference count leaks caused by pm_runtime_get_sync
+    
+    On calling pm_runtime_get_sync() the reference count of the device
+    is incremented. In case of failure, decrement the
+    reference count before returning the error.
+    
+    Acked-by: Evan Quan 
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Alex Deucher 
+
+diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
+index 35db79a168bf..df1a7eb73651 100644
+--- a/drivers/gpu/drm/radeon/radeon_display.c
++++ b/drivers/gpu/drm/radeon/radeon_display.c
+@@ -635,8 +635,10 @@ radeon_crtc_set_config(struct drm_mode_set *set,
+ 	dev = set->crtc->dev;
+ 
+ 	ret = pm_runtime_get_sync(dev->dev);
+-	if (ret < 0)
++	if (ret < 0) {
++		pm_runtime_put_autosuspend(dev->dev);
+ 		return ret;
++	}
+ 
+ 	ret = drm_crtc_helper_set_config(set, ctx);
+ 
+diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
+index a71f13116d6b..4cd30613fa1d 100644
+--- a/drivers/gpu/drm/radeon/radeon_drv.c
++++ b/drivers/gpu/drm/radeon/radeon_drv.c
+@@ -544,8 +544,10 @@ long radeon_drm_ioctl(struct file *filp,
+ 	long ret;
+ 	dev = file_priv->minor->dev;
+ 	ret = pm_runtime_get_sync(dev->dev);
+-	if (ret < 0)
++	if (ret < 0) {
++		pm_runtime_put_autosuspend(dev->dev);
+ 		return ret;
++	}
+ 
+ 	ret = drm_ioctl(filp, cmd, arg);
+ 	
+diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
+index 95006cbf42c3..c76955228731 100644
+--- a/drivers/gpu/drm/radeon/radeon_kms.c
++++ b/drivers/gpu/drm/radeon/radeon_kms.c
+@@ -638,8 +638,10 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
+ 	file_priv->driver_priv = NULL;
+ 
+ 	r = pm_runtime_get_sync(dev->dev);
+-	if (r < 0)
++	if (r < 0) {
++		pm_runtime_put_autosuspend(dev->dev);
+ 		return r;
++	}
+ 
+ 	/* new gpu have virtual address space support */
+ 	if (rdev->family >= CHIP_CAYMAN) {

commit 6f2e8acdb48ed166b65d47837c31b177460491ec
+Author: Aditya Pakki 
+Date:   Sat Jun 13 20:55:39 2020 -0500
+
+    drm/radeon: fix multiple reference count leak
+    
+    On calling pm_runtime_get_sync() the reference count of the device
+    is incremented. In case of failure, decrement the
+    reference count before returning the error.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Alex Deucher 
+
+diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
+index fe12d9d91d7a..e30834434442 100644
+--- a/drivers/gpu/drm/radeon/radeon_connectors.c
++++ b/drivers/gpu/drm/radeon/radeon_connectors.c
+@@ -879,8 +879,10 @@ radeon_lvds_detect(struct drm_connector *connector, bool force)
+ 
+ 	if (!drm_kms_helper_is_poll_worker()) {
+ 		r = pm_runtime_get_sync(connector->dev->dev);
+-		if (r < 0)
++		if (r < 0) {
++			pm_runtime_put_autosuspend(connector->dev->dev);
+ 			return connector_status_disconnected;
++		}
+ 	}
+ 
+ 	if (encoder) {
+@@ -1025,8 +1027,10 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
+ 
+ 	if (!drm_kms_helper_is_poll_worker()) {
+ 		r = pm_runtime_get_sync(connector->dev->dev);
+-		if (r < 0)
++		if (r < 0) {
++			pm_runtime_put_autosuspend(connector->dev->dev);
+ 			return connector_status_disconnected;
++		}
+ 	}
+ 
+ 	encoder = radeon_best_single_encoder(connector);
+@@ -1163,8 +1167,10 @@ radeon_tv_detect(struct drm_connector *connector, bool force)
+ 
+ 	if (!drm_kms_helper_is_poll_worker()) {
+ 		r = pm_runtime_get_sync(connector->dev->dev);
+-		if (r < 0)
++		if (r < 0) {
++			pm_runtime_put_autosuspend(connector->dev->dev);
+ 			return connector_status_disconnected;
++		}
+ 	}
+ 
+ 	encoder = radeon_best_single_encoder(connector);
+@@ -1247,8 +1253,10 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
+ 
+ 	if (!drm_kms_helper_is_poll_worker()) {
+ 		r = pm_runtime_get_sync(connector->dev->dev);
+-		if (r < 0)
++		if (r < 0) {
++			pm_runtime_put_autosuspend(connector->dev->dev);
+ 			return connector_status_disconnected;
++		}
+ 	}
+ 
+ 	if (radeon_connector->detected_hpd_without_ddc) {
+@@ -1657,8 +1665,10 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
+ 
+ 	if (!drm_kms_helper_is_poll_worker()) {
+ 		r = pm_runtime_get_sync(connector->dev->dev);
+-		if (r < 0)
++		if (r < 0) {
++			pm_runtime_put_autosuspend(connector->dev->dev);
+ 			return connector_status_disconnected;
++		}
+ 	}
+ 
+ 	if (!force && radeon_check_hpd_status_unchanged(connector)) {

commit 20eca0123a35305e38b344d571cf32768854168c
+Author: Qiushi Wu 
+Date:   Sat Jun 13 14:32:26 2020 -0500
+
+    drm/amdkfd: Fix reference count leaks.
+    
+    kobject_init_and_add() takes reference even when it fails.
+    If this function returns an error, kobject_put() must be called to
+    properly clean up the memory associated with the object.
+    
+    Signed-off-by: Qiushi Wu 
+    Reviewed-by: Felix Kuehling 
+    Signed-off-by: Felix Kuehling 
+    Signed-off-by: Alex Deucher 
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+index 4025efc619c7..cd18baf62727 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+@@ -636,8 +636,10 @@ static int kfd_build_sysfs_node_entry(struct kfd_topology_device *dev,
+ 
+ 	ret = kobject_init_and_add(dev->kobj_node, &node_type,
+ 			sys_props.kobj_nodes, "%d", id);
+-	if (ret < 0)
++	if (ret < 0) {
++		kobject_put(dev->kobj_node);
+ 		return ret;
++	}
+ 
+ 	dev->kobj_mem = kobject_create_and_add("mem_banks", dev->kobj_node);
+ 	if (!dev->kobj_mem)
+@@ -684,8 +686,10 @@ static int kfd_build_sysfs_node_entry(struct kfd_topology_device *dev,
+ 			return -ENOMEM;
+ 		ret = kobject_init_and_add(mem->kobj, &mem_type,
+ 				dev->kobj_mem, "%d", i);
+-		if (ret < 0)
++		if (ret < 0) {
++			kobject_put(mem->kobj);
+ 			return ret;
++		}
+ 
+ 		mem->attr.name = "properties";
+ 		mem->attr.mode = KFD_SYSFS_FILE_MODE;
+@@ -703,8 +707,10 @@ static int kfd_build_sysfs_node_entry(struct kfd_topology_device *dev,
+ 			return -ENOMEM;
+ 		ret = kobject_init_and_add(cache->kobj, &cache_type,
+ 				dev->kobj_cache, "%d", i);
+-		if (ret < 0)
++		if (ret < 0) {
++			kobject_put(cache->kobj);
+ 			return ret;
++		}
+ 
+ 		cache->attr.name = "properties";
+ 		cache->attr.mode = KFD_SYSFS_FILE_MODE;
+@@ -722,8 +728,10 @@ static int kfd_build_sysfs_node_entry(struct kfd_topology_device *dev,
+ 			return -ENOMEM;
+ 		ret = kobject_init_and_add(iolink->kobj, &iolink_type,
+ 				dev->kobj_iolink, "%d", i);
+-		if (ret < 0)
++		if (ret < 0) {
++			kobject_put(iolink->kobj);
+ 			return ret;
++		}
+ 
+ 		iolink->attr.name = "properties";
+ 		iolink->attr.mode = KFD_SYSFS_FILE_MODE;
+@@ -802,8 +810,10 @@ static int kfd_topology_update_sysfs(void)
+ 		ret = kobject_init_and_add(sys_props.kobj_topology,
+ 				&sysprops_type,  &kfd_device->kobj,
+ 				"topology");
+-		if (ret < 0)
++		if (ret < 0) {
++			kobject_put(sys_props.kobj_topology);
+ 			return ret;
++		}
+ 
+ 		sys_props.kobj_nodes = kobject_create_and_add("nodes",
+ 				sys_props.kobj_topology);

commit aaa3cbbac326c95308e315f1ab964a3369c4d07d
+Author: Qiushi Wu 
+Date:   Fri May 22 22:16:08 2020 -0500
+
+    platform/chrome: cros_ec_ishtp: Fix a double-unlock issue
+    
+    In function cros_ec_ishtp_probe(), "up_write" is already called
+    before function "cros_ec_dev_init". But "up_write" will be called
+    again after the calling of the function "cros_ec_dev_init" failed.
+    Thus add a call of the function “down_write” in this if branch
+    for the completion of the exception handling.
+    
+    Fixes: 26a14267aff2 ("platform/chrome: Add ChromeOS EC ISHTP driver")
+    Signed-off-by: Qiushi Wu 
+    Tested-by: Mathew King 
+    Signed-off-by: Enric Balletbo i Serra 
+
+diff --git a/drivers/platform/chrome/cros_ec_ishtp.c b/drivers/platform/chrome/cros_ec_ishtp.c
+index ed794a7ddba9..81364029af36 100644
+--- a/drivers/platform/chrome/cros_ec_ishtp.c
++++ b/drivers/platform/chrome/cros_ec_ishtp.c
+@@ -681,8 +681,10 @@ static int cros_ec_ishtp_probe(struct ishtp_cl_device *cl_device)
+ 
+ 	/* Register croc_ec_dev mfd */
+ 	rv = cros_ec_dev_init(client_data);
+-	if (rv)
++	if (rv) {
++		down_write(&init_lock);
+ 		goto end_cros_ec_dev_init_error;
++	}
+ 
+ 	return 0;
+ 

commit 2655971ad4b34e97dd921df16bb0b08db9449df7
+Author: Aditya Pakki 
+Date:   Sat Jun 13 22:15:25 2020 -0500
+
+    usb: dwc3: pci: Fix reference count leak in dwc3_pci_resume_work
+    
+    dwc3_pci_resume_work() calls pm_runtime_get_sync() that increments
+    the reference counter. In case of failure, decrement the reference
+    before returning.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
+index b67372737dc9..96c05b121fac 100644
+--- a/drivers/usb/dwc3/dwc3-pci.c
++++ b/drivers/usb/dwc3/dwc3-pci.c
+@@ -206,8 +206,10 @@ static void dwc3_pci_resume_work(struct work_struct *work)
+ 	int ret;
+ 
+ 	ret = pm_runtime_get_sync(&dwc3->dev);
+-	if (ret)
++	if (ret) {
++		pm_runtime_put_sync_autosuspend(&dwc3->dev);
+ 		return;
++	}
+ 
+ 	pm_runtime_mark_last_busy(&dwc3->dev);
+ 	pm_runtime_put_sync_autosuspend(&dwc3->dev);

commit f141a422159a199f4c8dedb7e0df55b3b2cf16cd
+Author: Qiushi Wu 
+Date:   Sat Jun 13 15:51:58 2020 -0500
+
+    ASoC: rockchip: Fix a reference count leak.
+    
+    Calling pm_runtime_get_sync increments the counter even in case of
+    failure, causing incorrect ref count if pm_runtime_put is not called in
+    error handling paths. Call pm_runtime_put if pm_runtime_get_sync fails.
+    
+    Fixes: fc05a5b22253 ("ASoC: rockchip: add support for pdm controller")
+    Signed-off-by: Qiushi Wu 
+    Reviewed-by: Heiko Stuebner 
+    Link: https://lore.kernel.org/r/20200613205158.27296-1-wu000273@umn.edu
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/rockchip/rockchip_pdm.c b/sound/soc/rockchip/rockchip_pdm.c
+index 7cd42fcfcf38..1707414cfa92 100644
+--- a/sound/soc/rockchip/rockchip_pdm.c
++++ b/sound/soc/rockchip/rockchip_pdm.c
+@@ -590,8 +590,10 @@ static int rockchip_pdm_resume(struct device *dev)
+ 	int ret;
+ 
+ 	ret = pm_runtime_get_sync(dev);
+-	if (ret < 0)
++	if (ret < 0) {
++		pm_runtime_put(dev);
+ 		return ret;
++	}
+ 
+ 	ret = regcache_sync(pdm->regmap);
+ 

commit 90a239ee25fa3a483facec3de7c144361a3d3a51
+Author: Aditya Pakki 
+Date:   Sat Jun 13 23:11:48 2020 -0500
+
+    RDMA/rvt: Fix potential memory leak caused by rvt_alloc_rq
+    
+    In case of failure of alloc_ud_wq_attr(), the memory allocated by
+    rvt_alloc_rq() is not freed. Fix it by calling rvt_free_rq() using the
+    existing clean-up code.
+    
+    Fixes: d310c4bf8aea ("IB/{rdmavt, hfi1, qib}: Remove AH refcount for UD QPs")
+    Link: https://lore.kernel.org/r/20200614041148.131983-1-pakki001@umn.edu
+    Signed-off-by: Aditya Pakki 
+    Acked-by: Dennis Dalessandro 
+    Signed-off-by: Jason Gunthorpe 
+
+diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c
+index 511b72809e14..7db35dd6ad74 100644
+--- a/drivers/infiniband/sw/rdmavt/qp.c
++++ b/drivers/infiniband/sw/rdmavt/qp.c
+@@ -1204,7 +1204,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
+ 		err = alloc_ud_wq_attr(qp, rdi->dparms.node);
+ 		if (err) {
+ 			ret = (ERR_PTR(err));
+-			goto bail_driver_priv;
++			goto bail_rq_rvt;
+ 		}
+ 
+ 		if (init_attr->create_flags & IB_QP_CREATE_NETDEV_USE)
+@@ -1314,9 +1314,11 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
+ 	rvt_free_qpn(&rdi->qp_dev->qpn_table, qp->ibqp.qp_num);
+ 
+ bail_rq_wq:
+-	rvt_free_rq(&qp->r_rq);
+ 	free_ud_wq_attr(qp);
+ 
++bail_rq_rvt:
++	rvt_free_rq(&qp->r_rq);
++
+ bail_driver_priv:
+ 	rdi->driver_f.qp_priv_free(rdi, qp);
+ 

commit 17ed808ad243192fb923e4e653c1338d3ba06207
+Author: Qiushi Wu 
+Date:   Thu May 28 15:22:37 2020 -0500
+
+    EDAC: Fix reference count leaks
+    
+    When kobject_init_and_add() returns an error, it should be handled
+    because kobject_init_and_add() takes a reference even when it fails. If
+    this function returns an error, kobject_put() must be called to properly
+    clean up the memory associated with the object.
+    
+    Therefore, replace calling kfree() and call kobject_put() and add a
+    missing kobject_put() in the edac_device_register_sysfs_main_kobj()
+    error path.
+    
+     [ bp: Massage and merge into a single patch. ]
+    
+    Fixes: b2ed215a3338 ("Kobject: change drivers/edac to use kobject_init_and_add")
+    Signed-off-by: Qiushi Wu 
+    Signed-off-by: Borislav Petkov 
+    Link: https://lkml.kernel.org/r/20200528202238.18078-1-wu000273@umn.edu
+    Link: https://lkml.kernel.org/r/20200528203526.20908-1-wu000273@umn.edu
+
+diff --git a/drivers/edac/edac_device_sysfs.c b/drivers/edac/edac_device_sysfs.c
+index 0e7ea3591b78..5e7593753799 100644
+--- a/drivers/edac/edac_device_sysfs.c
++++ b/drivers/edac/edac_device_sysfs.c
+@@ -275,6 +275,7 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
+ 
+ 	/* Error exit stack */
+ err_kobj_reg:
++	kobject_put(&edac_dev->kobj);
+ 	module_put(edac_dev->owner);
+ 
+ err_out:
+diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c
+index 72c9eb9fdffb..53042af7262e 100644
+--- a/drivers/edac/edac_pci_sysfs.c
++++ b/drivers/edac/edac_pci_sysfs.c
+@@ -386,7 +386,7 @@ static int edac_pci_main_kobj_setup(void)
+ 
+ 	/* Error unwind statck */
+ kobject_init_and_add_fail:
+-	kfree(edac_pci_top_main_kobj);
++	kobject_put(edac_pci_top_main_kobj);
+ 
+ kzalloc_fail:
+ 	module_put(THIS_MODULE);

commit deca195383a6085be62cb453079e03e04d618d6e
+Author: Qiushi Wu 
+Date:   Sat Jun 13 15:44:19 2020 -0500
+
+    ASoC: tegra: Fix reference count leaks.
+    
+    Calling pm_runtime_get_sync increments the counter even in case of
+    failure, causing incorrect ref count if pm_runtime_put is not called in
+    error handling paths. Call pm_runtime_put if pm_runtime_get_sync fails.
+    
+    Signed-off-by: Qiushi Wu 
+    Reviewed-by: Jon Hunter 
+    Link: https://lore.kernel.org/r/20200613204422.24484-1-wu000273@umn.edu
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c
+index 635eacbd28d4..156e3b9d613c 100644
+--- a/sound/soc/tegra/tegra30_ahub.c
++++ b/sound/soc/tegra/tegra30_ahub.c
+@@ -643,8 +643,10 @@ static int tegra30_ahub_resume(struct device *dev)
+ 	int ret;
+ 
+ 	ret = pm_runtime_get_sync(dev);
+-	if (ret < 0)
++	if (ret < 0) {
++		pm_runtime_put(dev);
+ 		return ret;
++	}
+ 	ret = regcache_sync(ahub->regmap_ahub);
+ 	ret |= regcache_sync(ahub->regmap_apbif);
+ 	pm_runtime_put(dev);
+diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c
+index d59882ec48f1..db5a8587bfa4 100644
+--- a/sound/soc/tegra/tegra30_i2s.c
++++ b/sound/soc/tegra/tegra30_i2s.c
+@@ -567,8 +567,10 @@ static int tegra30_i2s_resume(struct device *dev)
+ 	int ret;
+ 
+ 	ret = pm_runtime_get_sync(dev);
+-	if (ret < 0)
++	if (ret < 0) {
++		pm_runtime_put(dev);
+ 		return ret;
++	}
+ 	ret = regcache_sync(i2s->regmap);
+ 	pm_runtime_put(dev);
+ 

commit 58d0c864e1a759a15c9df78f50ea5a5c32b3989e
+Author: Aditya Pakki 
+Date:   Fri Jun 12 15:27:55 2020 -0500
+
+    rocker: fix incorrect error handling in dma_rings_init
+    
+    In rocker_dma_rings_init, the goto blocks in case of errors
+    caused by the functions rocker_dma_cmd_ring_waits_alloc() and
+    rocker_dma_ring_create() are incorrect. The patch fixes the
+    order consistent with cleanup in rocker_dma_rings_fini().
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
+index 7585cd2270ba..fc99e7118e49 100644
+--- a/drivers/net/ethernet/rocker/rocker_main.c
++++ b/drivers/net/ethernet/rocker/rocker_main.c
+@@ -647,10 +647,10 @@ static int rocker_dma_rings_init(struct rocker *rocker)
+ err_dma_event_ring_bufs_alloc:
+ 	rocker_dma_ring_destroy(rocker, &rocker->event_ring);
+ err_dma_event_ring_create:
++	rocker_dma_cmd_ring_waits_free(rocker);
++err_dma_cmd_ring_waits_alloc:
+ 	rocker_dma_ring_bufs_free(rocker, &rocker->cmd_ring,
+ 				  PCI_DMA_BIDIRECTIONAL);
+-err_dma_cmd_ring_waits_alloc:
+-	rocker_dma_cmd_ring_waits_free(rocker);
+ err_dma_cmd_ring_bufs_alloc:
+ 	rocker_dma_ring_destroy(rocker, &rocker->cmd_ring);
+ 	return err;

commit a6379f0ad6375a707e915518ecd5c2270afcd395
+Author: Aditya Pakki 
+Date:   Fri Jun 12 15:01:54 2020 -0500
+
+    test_objagg: Fix potential memory leak in error handling
+    
+    In case of failure of check_expect_hints_stats(), the resources
+    allocated by objagg_hints_get should be freed. The patch fixes
+    this issue.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: David S. Miller 
+
+diff --git a/lib/test_objagg.c b/lib/test_objagg.c
+index 72c1abfa154d..da137939a410 100644
+--- a/lib/test_objagg.c
++++ b/lib/test_objagg.c
+@@ -979,10 +979,10 @@ static int test_hints_case(const struct hints_case *hints_case)
+ err_world2_obj_get:
+ 	for (i--; i >= 0; i--)
+ 		world_obj_put(&world2, objagg, hints_case->key_ids[i]);
+-	objagg_hints_put(hints);
+-	objagg_destroy(objagg2);
+ 	i = hints_case->key_ids_count;
++	objagg_destroy(objagg2);
+ err_check_expect_hints_stats:
++	objagg_hints_put(hints);
+ err_hints_get:
+ err_check_expect_stats:
+ err_world_obj_get:

commit 6b9fbb073636906eee9fe4d4c05a4f445b9e2a23
+Author: Qiushi Wu 
+Date:   Sat Jun 13 22:33:43 2020 -0500
+
+    ASoC: img-parallel-out: Fix a reference count leak
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code, causing incorrect ref count if
+    pm_runtime_put_noidle() is not called in error handling paths.
+    Thus call pm_runtime_put_noidle() if pm_runtime_get_sync() fails.
+    
+    Signed-off-by: Qiushi Wu 
+    Link: https://lore.kernel.org/r/20200614033344.1814-1-wu000273@umn.edu
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/img/img-parallel-out.c b/sound/soc/img/img-parallel-out.c
+index 5ddbe3a31c2e..4da49a42e854 100644
+--- a/sound/soc/img/img-parallel-out.c
++++ b/sound/soc/img/img-parallel-out.c
+@@ -163,8 +163,10 @@ static int img_prl_out_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+ 	}
+ 
+ 	ret = pm_runtime_get_sync(prl->dev);
+-	if (ret < 0)
++	if (ret < 0) {
++		pm_runtime_put_noidle(prl->dev);
+ 		return ret;
++	}
+ 
+ 	reg = img_prl_out_readl(prl, IMG_PRL_OUT_CTL);
+ 	reg = (reg & ~IMG_PRL_OUT_CTL_EDGE_MASK) | control_set;

commit c4c59b95b7f7d4cef5071b151be2dadb33f3287b
+Author: Qiushi Wu 
+Date:   Sat Jun 13 22:37:48 2020 -0500
+
+    ASoC: img: Fix a reference count leak in img_i2s_in_set_fmt
+    
+    pm_runtime_get_sync() increments the runtime PM usage counter even
+    when it returns an error code, causing incorrect ref count if
+    pm_runtime_put_noidle() is not called in error handling paths.
+    Thus call pm_runtime_put_noidle() if pm_runtime_get_sync() fails.
+    
+    Signed-off-by: Qiushi Wu 
+    Link: https://lore.kernel.org/r/20200614033749.2975-1-wu000273@umn.edu
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/img/img-i2s-in.c b/sound/soc/img/img-i2s-in.c
+index e30b66b94bf6..0843235d73c9 100644
+--- a/sound/soc/img/img-i2s-in.c
++++ b/sound/soc/img/img-i2s-in.c
+@@ -343,8 +343,10 @@ static int img_i2s_in_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+ 	chan_control_mask = IMG_I2S_IN_CH_CTL_CLK_TRANS_MASK;
+ 
+ 	ret = pm_runtime_get_sync(i2s->dev);
+-	if (ret < 0)
++	if (ret < 0) {
++		pm_runtime_put_noidle(i2s->dev);
+ 		return ret;
++	}
+ 
+ 	for (i = 0; i < i2s->active_channels; i++)
+ 		img_i2s_in_ch_disable(i2s, i);

commit 4ddf4739be6e375116c375f0a68bf3893ffcee21
+Author: Qiushi Wu 
+Date:   Thu May 28 13:38:04 2020 -0500
+
+    efi/esrt: Fix reference count leak in esre_create_sysfs_entry.
+    
+    kobject_init_and_add() takes reference even when it fails.
+    If this function returns an error, kobject_put() must be called to
+    properly clean up the memory associated with the object. Previous
+    commit "b8eb718348b8" fixed a similar problem.
+    
+    Fixes: 0bb549052d33 ("efi: Add esrt support")
+    Signed-off-by: Qiushi Wu 
+    Link: https://lore.kernel.org/r/20200528183804.4497-1-wu000273@umn.edu
+    Signed-off-by: Ard Biesheuvel 
+
+diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c
+index e3d692696583..d5915272141f 100644
+--- a/drivers/firmware/efi/esrt.c
++++ b/drivers/firmware/efi/esrt.c
+@@ -181,7 +181,7 @@ static int esre_create_sysfs_entry(void *esre, int entry_num)
+ 		rc = kobject_init_and_add(&entry->kobj, &esre1_ktype, NULL,
+ 					  "entry%d", entry_num);
+ 		if (rc) {
+-			kfree(entry);
++			kobject_put(&entry->kobj);
+ 			return rc;
+ 		}
+ 	}

commit 0267ffce562c8bbf9b57ebe0e38445ad04972890
+Author: Qiushi Wu 
+Date:   Thu May 28 15:13:53 2020 -0500
+
+    scsi: iscsi: Fix reference count leak in iscsi_boot_create_kobj
+    
+    kobject_init_and_add() takes reference even when it fails. If this
+    function returns an error, kobject_put() must be called to properly
+    clean up the memory associated with the object.
+    
+    Link: https://lore.kernel.org/r/20200528201353.14849-1-wu000273@umn.edu
+    Reviewed-by: Lee Duncan 
+    Signed-off-by: Qiushi Wu 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/scsi/iscsi_boot_sysfs.c b/drivers/scsi/iscsi_boot_sysfs.c
+index e4857b728033..a64abe38db2d 100644
+--- a/drivers/scsi/iscsi_boot_sysfs.c
++++ b/drivers/scsi/iscsi_boot_sysfs.c
+@@ -352,7 +352,7 @@ iscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset,
+ 	boot_kobj->kobj.kset = boot_kset->kset;
+ 	if (kobject_init_and_add(&boot_kobj->kobj, &iscsi_boot_ktype,
+ 				 NULL, name, index)) {
+-		kfree(boot_kobj);
++		kobject_put(&boot_kobj->kobj);
+ 		return NULL;
+ 	}
+ 	boot_kobj->data = data;

commit aa8ba13cae3134b8ef1c1b6879f66372531da738
+Author: Qiushi Wu 
+Date:   Wed May 27 21:01:09 2020 -0500
+
+    vfio/mdev: Fix reference count leak in add_mdev_supported_type
+    
+    kobject_init_and_add() takes reference even when it fails.
+    If this function returns an error, kobject_put() must be called to
+    properly clean up the memory associated with the object. Thus,
+    replace kfree() by kobject_put() to fix this issue. Previous
+    commit "b8eb718348b8" fixed a similar problem.
+    
+    Fixes: 7b96953bc640 ("vfio: Mediated device Core driver")
+    Signed-off-by: Qiushi Wu 
+    Reviewed-by: Cornelia Huck 
+    Reviewed-by: Kirti Wankhede 
+    Signed-off-by: Alex Williamson 
+
+diff --git a/drivers/vfio/mdev/mdev_sysfs.c b/drivers/vfio/mdev/mdev_sysfs.c
+index 8ad14e5c02bf..917fd84c1c6f 100644
+--- a/drivers/vfio/mdev/mdev_sysfs.c
++++ b/drivers/vfio/mdev/mdev_sysfs.c
+@@ -110,7 +110,7 @@ static struct mdev_type *add_mdev_supported_type(struct mdev_parent *parent,
+ 				   "%s-%s", dev_driver_string(parent->dev),
+ 				   group->name);
+ 	if (ret) {
+-		kfree(type);
++		kobject_put(&type->kobj);
+ 		return ERR_PTR(ret);
+ 	}
+ 

commit 0b8e125e213204508e1b3c4bdfe69713280b7abd
+Author: Qiushi Wu 
+Date:   Wed May 27 22:02:30 2020 -0500
+
+    RDMA/core: Fix several reference count leaks.
+    
+    kobject_init_and_add() takes reference even when it fails.  If this
+    function returns an error, kobject_put() must be called to properly clean
+    up the memory associated with the object. Previous
+    commit b8eb718348b8 ("net-sysfs: Fix reference count leak in
+    rx|netdev_queue_add_kobject") fixed a similar problem.
+    
+    Link: https://lore.kernel.org/r/20200528030231.9082-1-wu000273@umn.edu
+    Signed-off-by: Qiushi Wu 
+    Reviewed-by: Jason Gunthorpe 
+    Signed-off-by: Jason Gunthorpe 
+
+diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
+index 087682e6969e..defe9cd4c5ee 100644
+--- a/drivers/infiniband/core/sysfs.c
++++ b/drivers/infiniband/core/sysfs.c
+@@ -1058,8 +1058,7 @@ static int add_port(struct ib_core_device *coredev, int port_num)
+ 				   coredev->ports_kobj,
+ 				   "%d", port_num);
+ 	if (ret) {
+-		kfree(p);
+-		return ret;
++		goto err_put;
+ 	}
+ 
+ 	p->gid_attr_group = kzalloc(sizeof(*p->gid_attr_group), GFP_KERNEL);
+@@ -1072,8 +1071,7 @@ static int add_port(struct ib_core_device *coredev, int port_num)
+ 	ret = kobject_init_and_add(&p->gid_attr_group->kobj, &gid_attr_type,
+ 				   &p->kobj, "gid_attrs");
+ 	if (ret) {
+-		kfree(p->gid_attr_group);
+-		goto err_put;
++		goto err_put_gid_attrs;
+ 	}
+ 
+ 	if (device->ops.process_mad && is_full_dev) {
+@@ -1404,8 +1402,10 @@ int ib_port_register_module_stat(struct ib_device *device, u8 port_num,
+ 
+ 		ret = kobject_init_and_add(kobj, ktype, &port->kobj, "%s",
+ 					   name);
+-		if (ret)
++		if (ret) {
++			kobject_put(kobj);
+ 			return ret;
++		}
+ 	}
+ 
+ 	return 0;

commit c343bf1ba5efcbf2266a1fe3baefec9cc82f867f
+Author: Qiushi Wu 
+Date:   Thu May 28 13:20:46 2020 -0500
+
+    cpuidle: Fix three reference count leaks
+    
+    kobject_init_and_add() takes reference even when it fails.
+    If this function returns an error, kobject_put() must be called to
+    properly clean up the memory associated with the object.
+    
+    Previous commit "b8eb718348b8" fixed a similar problem.
+    
+    Signed-off-by: Qiushi Wu 
+    [ rjw: Subject ]
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
+index 14c0eb536787..091d1caceb41 100644
+--- a/drivers/cpuidle/sysfs.c
++++ b/drivers/cpuidle/sysfs.c
+@@ -484,7 +484,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device)
+ 		ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle,
+ 					   &kdev->kobj, "state%d", i);
+ 		if (ret) {
+-			kfree(kobj);
++			kobject_put(&kobj->kobj);
+ 			goto error_state;
+ 		}
+ 		cpuidle_add_s2idle_attr_group(kobj);
+@@ -615,7 +615,7 @@ static int cpuidle_add_driver_sysfs(struct cpuidle_device *dev)
+ 	ret = kobject_init_and_add(&kdrv->kobj, &ktype_driver_cpuidle,
+ 				   &kdev->kobj, "driver");
+ 	if (ret) {
+-		kfree(kdrv);
++		kobject_put(&kdrv->kobj);
+ 		return ret;
+ 	}
+ 
+@@ -709,7 +709,7 @@ int cpuidle_add_sysfs(struct cpuidle_device *dev)
+ 	error = kobject_init_and_add(&kdev->kobj, &ktype_cpuidle, &cpu_dev->kobj,
+ 				   "cpuidle");
+ 	if (error) {
+-		kfree(kdev);
++		kobject_put(&kdev->kobj);
+ 		return error;
+ 	}
+ 

commit 7cc31613734c4870ae32f5265d576ef296621343
+Author: Qiushi Wu 
+Date:   Wed May 27 16:00:19 2020 -0500
+
+    iommu: Fix reference count leak in iommu_group_alloc.
+    
+    kobject_init_and_add() takes reference even when it fails.
+    Thus, when kobject_init_and_add() returns an error,
+    kobject_put() must be called to properly clean up the kobject.
+    
+    Fixes: d72e31c93746 ("iommu: IOMMU Groups")
+    Signed-off-by: Qiushi Wu 
+    Link: https://lore.kernel.org/r/20200527210020.6522-1-wu000273@umn.edu
+    Signed-off-by: Joerg Roedel 
+
+diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
+index 1faa08c8bbb4..03d6a26687bc 100644
+--- a/drivers/iommu/iommu.c
++++ b/drivers/iommu/iommu.c
+@@ -510,7 +510,7 @@ struct iommu_group *iommu_group_alloc(void)
+ 				   NULL, "%d", group->id);
+ 	if (ret) {
+ 		ida_simple_remove(&iommu_group_ida, group->id);
+-		kfree(group);
++		kobject_put(&group->kobj);
+ 		return ERR_PTR(ret);
+ 	}
+ 

commit a068aab42258e25094bc2c159948d263ed7d7a77
+Author: Qiushi Wu 
+Date:   Wed May 27 22:10:29 2020 -0500
+
+    bonding: Fix reference count leak in bond_sysfs_slave_add.
+    
+    kobject_init_and_add() takes reference even when it fails.
+    If this function returns an error, kobject_put() must be called to
+    properly clean up the memory associated with the object. Previous
+    commit "b8eb718348b8" fixed a similar problem.
+    
+    Fixes: 07699f9a7c8d ("bonding: add sysfs /slave dir for bond slave devices.")
+    Signed-off-by: Qiushi Wu 
+    Acked-by: Jay Vosburgh 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/bonding/bond_sysfs_slave.c b/drivers/net/bonding/bond_sysfs_slave.c
+index 007481557191..9b8346638f69 100644
+--- a/drivers/net/bonding/bond_sysfs_slave.c
++++ b/drivers/net/bonding/bond_sysfs_slave.c
+@@ -149,8 +149,10 @@ int bond_sysfs_slave_add(struct slave *slave)
+ 
+ 	err = kobject_init_and_add(&slave->kobj, &slave_ktype,
+ 				   &(slave->dev->dev.kobj), "bonding_slave");
+-	if (err)
++	if (err) {
++		kobject_put(&slave->kobj);
+ 		return err;
++	}
+ 
+ 	for (a = slave_attrs; *a; ++a) {
+ 		err = sysfs_create_file(&slave->kobj, &((*a)->attr));

commit 4d8be4bc94f74bb7d096e1c2e44457b530d5a170
+Author: Qiushi Wu 
+Date:   Wed May 27 17:35:51 2020 -0500
+
+    ACPI: CPPC: Fix reference count leak in acpi_cppc_processor_probe()
+    
+    kobject_init_and_add() takes reference even when it fails.
+    If this function returns an error, kobject_put() must be called to
+    properly clean up the memory associated with the object. Previous
+    commit "b8eb718348b8" fixed a similar problem.
+    
+    Fixes: 158c998ea44b ("ACPI / CPPC: add sysfs support to compute delivered performance")
+    Signed-off-by: Qiushi Wu 
+    Cc: 4.10+  # 4.10+
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
+index f8184004294a..7a99b19bb893 100644
+--- a/drivers/acpi/cppc_acpi.c
++++ b/drivers/acpi/cppc_acpi.c
+@@ -846,6 +846,7 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
+ 			"acpi_cppc");
+ 	if (ret) {
+ 		per_cpu(cpc_desc_ptr, pr->id) = NULL;
++		kobject_put(&cpc_ptr->kobj);
+ 		goto out_free;
+ 	}
+ 

commit 6e6c25283dff866308c87b49434c7dbad4774cc0
+Author: Qiushi Wu 
+Date:   Wed May 27 16:17:17 2020 -0500
+
+    ACPI: sysfs: Fix reference count leak in acpi_sysfs_add_hotplug_profile()
+    
+    kobject_init_and_add() takes reference even when it fails.
+    Thus, when kobject_init_and_add() returns an error,
+    kobject_put() must be called to properly clean up the kobject.
+    
+    Fixes: 3f8055c35836 ("ACPI / hotplug: Introduce user space interface for hotplug profiles")
+    Signed-off-by: Qiushi Wu 
+    Cc: 3.10+  # 3.10+
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
+index c60d2c6d31d6..3a89909b50a6 100644
+--- a/drivers/acpi/sysfs.c
++++ b/drivers/acpi/sysfs.c
+@@ -993,8 +993,10 @@ void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug,
+ 
+ 	error = kobject_init_and_add(&hotplug->kobj,
+ 		&acpi_hotplug_profile_ktype, hotplug_kobj, "%s", name);
+-	if (error)
++	if (error) {
++		kobject_put(&hotplug->kobj);
+ 		goto err_out;
++	}
+ 
+ 	kobject_uevent(&hotplug->kobj, KOBJ_ADD);
+ 	return;

commit 25bf943e4e7b47282bd86ae7d39e039217ebb007
+Author: Qiushi Wu 
+Date:   Mon May 25 00:50:11 2020 -0500
+
+    ASoC: fix incomplete error-handling in img_i2s_in_probe.
+    
+    Function "pm_runtime_get_sync()" is not handled by "pm_runtime_put()"
+    if "PTR_ERR(rst) == -EPROBE_DEFER". Fix this issue by adding
+    "pm_runtime_put()" into this error path.
+    
+    Fixes: f65bb92ca12e ("ASoC: img-i2s-in: Add runtime PM")
+    Signed-off-by: Qiushi Wu 
+    Link: https://lore.kernel.org/r/20200525055011.31925-1-wu000273@umn.edu
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/img/img-i2s-in.c b/sound/soc/img/img-i2s-in.c
+index a495d1050d49..e30b66b94bf6 100644
+--- a/sound/soc/img/img-i2s-in.c
++++ b/sound/soc/img/img-i2s-in.c
+@@ -482,6 +482,7 @@ static int img_i2s_in_probe(struct platform_device *pdev)
+ 	if (IS_ERR(rst)) {
+ 		if (PTR_ERR(rst) == -EPROBE_DEFER) {
+ 			ret = -EPROBE_DEFER;
++			pm_runtime_put(&pdev->dev);
+ 			goto err_suspend;
+ 		}
+ 

commit 15c973858903009e995b2037683de29dfe968621
+Author: Qiushi Wu 
+Date:   Mon May 25 03:24:39 2020 -0500
+
+    qlcnic: fix missing release in qlcnic_83xx_interrupt_test.
+    
+    In function qlcnic_83xx_interrupt_test(), function
+    qlcnic_83xx_diag_alloc_res() is not handled by function
+    qlcnic_83xx_diag_free_res() after a call of the function
+    qlcnic_alloc_mbx_args() failed. Fix this issue by adding
+    a jump target "fail_mbx_args", and jump to this new target
+    when qlcnic_alloc_mbx_args() failed.
+    
+    Fixes: b6b4316c8b2f ("qlcnic: Handle qlcnic_alloc_mbx_args() failure")
+    Signed-off-by: Qiushi Wu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+index 2a533280b124..29b9c728a65e 100644
+--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+@@ -3651,7 +3651,7 @@ int qlcnic_83xx_interrupt_test(struct net_device *netdev)
+ 	ahw->diag_cnt = 0;
+ 	ret = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INTRPT_TEST);
+ 	if (ret)
+-		goto fail_diag_irq;
++		goto fail_mbx_args;
+ 
+ 	if (adapter->flags & QLCNIC_MSIX_ENABLED)
+ 		intrpt_id = ahw->intr_tbl[0].id;
+@@ -3681,6 +3681,8 @@ int qlcnic_83xx_interrupt_test(struct net_device *netdev)
+ 
+ done:
+ 	qlcnic_free_mbx_args(&cmd);
++
++fail_mbx_args:
+ 	qlcnic_83xx_diag_free_res(netdev, drv_sds_rings);
+ 
+ fail_diag_irq:

commit db857e6ae548f0f4f4a0f63fffeeedf3cca21f9d
+Author: Qiushi Wu 
+Date:   Fri May 22 22:04:57 2020 -0500
+
+    RDMA/pvrdma: Fix missing pci disable in pvrdma_pci_probe()
+    
+    In function pvrdma_pci_probe(), pdev was not disabled in one error
+    path. Thus replace the jump target “err_free_device” by
+    "err_disable_pdev".
+    
+    Fixes: 29c8d9eba550 ("IB: Add vmw_pvrdma driver")
+    Link: https://lore.kernel.org/r/20200523030457.16160-1-wu000273@umn.edu
+    Signed-off-by: Qiushi Wu 
+    Signed-off-by: Jason Gunthorpe 
+
+diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
+index e580ae9cc55a..780fd2dfc07e 100644
+--- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
++++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
+@@ -829,7 +829,7 @@ static int pvrdma_pci_probe(struct pci_dev *pdev,
+ 	    !(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
+ 		dev_err(&pdev->dev, "PCI BAR region not MMIO\n");
+ 		ret = -ENOMEM;
+-		goto err_free_device;
++		goto err_disable_pdev;
+ 	}
+ 
+ 	ret = pci_request_regions(pdev, DRV_NAME);

commit 44734a594196bf1d474212f38fe3a0d37a73278b
+Author: Qiushi Wu 
+Date:   Fri May 22 23:06:25 2020 -0500
+
+    usb: gadget: fix potential double-free in m66592_probe.
+    
+    m66592_free_request() is called under label "err_add_udc"
+    and "clean_up", and m66592->ep0_req is not set to NULL after
+    first free, leading to a double-free. Fix this issue by
+    setting m66592->ep0_req to NULL after the first free.
+    
+    Fixes: 0f91349b89f3 ("usb: gadget: convert all users to the new udc infrastructure")
+    Signed-off-by: Qiushi Wu 
+    Signed-off-by: Felipe Balbi 
+
+diff --git a/drivers/usb/gadget/udc/m66592-udc.c b/drivers/usb/gadget/udc/m66592-udc.c
+index 75d16a8902e6..931e6362a13d 100644
+--- a/drivers/usb/gadget/udc/m66592-udc.c
++++ b/drivers/usb/gadget/udc/m66592-udc.c
+@@ -1667,7 +1667,7 @@ static int m66592_probe(struct platform_device *pdev)
+ 
+ err_add_udc:
+ 	m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
+-
++	m66592->ep0_req = NULL;
+ clean_up3:
+ 	if (m66592->pdata->on_chip) {
+ 		clk_disable(m66592->clk);

commit febfd9d3c7f74063e8e630b15413ca91b567f963
+Author: Qiushi Wu 
+Date:   Fri May 22 14:07:15 2020 -0500
+
+    net/mlx4_core: fix a memory leak bug.
+    
+    In function mlx4_opreq_action(), pointer "mailbox" is not released,
+    when mlx4_cmd_box() return and error, causing a memory leak bug.
+    Fix this issue by going to "out" label, mlx4_free_cmd_mailbox() can
+    free this pointer.
+    
+    Fixes: fe6f700d6cbb ("net/mlx4_core: Respond to operation request by firmware")
+    Signed-off-by: Qiushi Wu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c
+index 6e501af0e532..f6ff9620a137 100644
+--- a/drivers/net/ethernet/mellanox/mlx4/fw.c
++++ b/drivers/net/ethernet/mellanox/mlx4/fw.c
+@@ -2734,7 +2734,7 @@ void mlx4_opreq_action(struct work_struct *work)
+ 		if (err) {
+ 			mlx4_err(dev, "Failed to retrieve required operation: %d\n",
+ 				 err);
+-			return;
++			goto out;
+ 		}
+ 		MLX4_GET(modifier, outbox, GET_OP_REQ_MODIFIER_OFFSET);
+ 		MLX4_GET(token, outbox, GET_OP_REQ_TOKEN_OFFSET);

commit f45d01f4f30b53c3a0a1c6c1c154acb7ff74ab9f
+Author: Qiushi Wu 
+Date:   Fri May 22 13:45:18 2020 -0500
+
+    rxrpc: Fix a memory leak in rxkad_verify_response()
+    
+    A ticket was not released after a call of the function
+    "rxkad_decrypt_ticket" failed. Thus replace the jump target
+    "temporary_error_free_resp" by "temporary_error_free_ticket".
+    
+    Fixes: 8c2f826dc3631 ("rxrpc: Don't put crypto buffers on the stack")
+    Signed-off-by: Qiushi Wu 
+    Signed-off-by: David Howells 
+    cc: Markus Elfring 
+
+diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
+index 098f1f9ec53b..52a24d4ef5d8 100644
+--- a/net/rxrpc/rxkad.c
++++ b/net/rxrpc/rxkad.c
+@@ -1148,7 +1148,7 @@ static int rxkad_verify_response(struct rxrpc_connection *conn,
+ 	ret = rxkad_decrypt_ticket(conn, skb, ticket, ticket_len, &session_key,
+ 				   &expiry, _abort_code);
+ 	if (ret < 0)
+-		goto temporary_error_free_resp;
++		goto temporary_error_free_ticket;
+ 
+ 	/* use the session key from inside the ticket to decrypt the
+ 	 * response */
+@@ -1230,7 +1230,6 @@ static int rxkad_verify_response(struct rxrpc_connection *conn,
+ 
+ temporary_error_free_ticket:
+ 	kfree(ticket);
+-temporary_error_free_resp:
+ 	kfree(response);
+ temporary_error:
+ 	/* Ignore the response packet if we got a temporary error such as

commit 5a730153984dd13f82ffae93d7170d76eba204e9
+Author: Qiushi Wu 
+Date:   Fri May 22 16:50:27 2020 -0500
+
+    net: sun: fix missing release regions in cas_init_one().
+    
+    In cas_init_one(), "pdev" is requested by "pci_request_regions", but it
+    was not released after a call of the function “pci_write_config_byte”
+    failed. Thus replace the jump target “err_write_cacheline” by
+    "err_out_free_res".
+    
+    Fixes: 1f26dac32057 ("[NET]: Add Sun Cassini driver.")
+    Signed-off-by: Qiushi Wu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c
+index e6d1aa882fa5..f1c8615ab6f0 100644
+--- a/drivers/net/ethernet/sun/cassini.c
++++ b/drivers/net/ethernet/sun/cassini.c
+@@ -4963,7 +4963,7 @@ static int cas_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 					  cas_cacheline_size)) {
+ 			dev_err(&pdev->dev, "Could not set PCI cache "
+ 			       "line size\n");
+-			goto err_write_cacheline;
++			goto err_out_free_res;
+ 		}
+ 	}
+ #endif
+@@ -5136,7 +5136,6 @@ static int cas_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ err_out_free_res:
+ 	pci_release_regions(pdev);
+ 
+-err_write_cacheline:
+ 	/* Try to restore it in case the error occurred after we
+ 	 * set it.
+ 	 */

commit b975abbd382fe442713a4c233549abb90e57c22b
+Author: Qiushi Wu 
+Date:   Fri May 22 09:34:51 2020 +0100
+
+    agp/intel: Fix a memory leak on module initialisation failure
+    
+    In intel_gtt_setup_scratch_page(), pointer "page" is not released if
+    pci_dma_mapping_error() return an error, leading to a memory leak on
+    module initialisation failure.  Simply fix this issue by freeing "page"
+    before return.
+    
+    Fixes: 0e87d2b06cb46 ("intel-gtt: initialize our own scratch page")
+    Signed-off-by: Qiushi Wu 
+    Reviewed-by: Chris Wilson 
+    Signed-off-by: Chris Wilson 
+    Link: https://patchwork.freedesktop.org/patch/msgid/20200522083451.7448-1-chris@chris-wilson.co.uk
+
+diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c
+index 4b34a5195c65..5bfdf222d5f9 100644
+--- a/drivers/char/agp/intel-gtt.c
++++ b/drivers/char/agp/intel-gtt.c
+@@ -304,8 +304,10 @@ static int intel_gtt_setup_scratch_page(void)
+ 	if (intel_private.needs_dmar) {
+ 		dma_addr = pci_map_page(intel_private.pcidev, page, 0,
+ 				    PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+-		if (pci_dma_mapping_error(intel_private.pcidev, dma_addr))
++		if (pci_dma_mapping_error(intel_private.pcidev, dma_addr)) {
++			__free_page(page);
+ 			return -EINVAL;
++		}
+ 
+ 		intel_private.scratch_page_dma = dma_addr;
+ 	} else

commit 8816cd726a4fee197af2d851cbe25991ae19ea14
+Author: Qiushi Wu 
+Date:   Sun May 3 13:22:35 2020 -0500
+
+    rtc: mc13xxx: fix a double-unlock issue
+    
+    In function mc13xxx_rtc_probe, the mc13xxx_unlock() is called
+    before rtc_register_device(). But in the error path of
+    rtc_register_device(), the mc13xxx_unlock() is called again,
+    which causes a double-unlock problem. Thus add a call of the
+    function “mc13xxx_lock” in an if branch for the completion
+    of the exception handling.
+    
+    Fixes: e4ae7023e182a ("rtc: mc13xxx: set range")
+    Signed-off-by: Qiushi Wu 
+    Link: https://lore.kernel.org/r/20200503182235.1652-1-wu000273@umn.edu
+    Signed-off-by: Alexandre Belloni 
+
+diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c
+index afce2c0b4bd6..d6802e6191cb 100644
+--- a/drivers/rtc/rtc-mc13xxx.c
++++ b/drivers/rtc/rtc-mc13xxx.c
+@@ -308,8 +308,10 @@ static int __init mc13xxx_rtc_probe(struct platform_device *pdev)
+ 	mc13xxx_unlock(mc13xxx);
+ 
+ 	ret = rtc_register_device(priv->rtc);
+-	if (ret)
++	if (ret) {
++		mc13xxx_lock(mc13xxx);
+ 		goto err_irq_request;
++	}
+ 
+ 	return 0;
+ 

commit bd4af432cc71b5fbfe4833510359a6ad3ada250d
+Author: Qiushi Wu 
+Date:   Sat May 2 17:42:59 2020 -0500
+
+    nfp: abm: fix a memory leak bug
+    
+    In function nfp_abm_vnic_set_mac, pointer nsp is allocated by nfp_nsp_open.
+    But when nfp_nsp_has_hwinfo_lookup fail, the pointer is not released,
+    which can lead to a memory leak bug. Fix this issue by adding
+    nfp_nsp_close(nsp) in the error path.
+    
+    Fixes: f6e71efdf9fb1 ("nfp: abm: look up MAC addresses via management FW")
+    Signed-off-by: Qiushi Wu 
+    Acked-by: Jakub Kicinski 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/netronome/nfp/abm/main.c b/drivers/net/ethernet/netronome/nfp/abm/main.c
+index 9183b3e85d21..354efffac0f9 100644
+--- a/drivers/net/ethernet/netronome/nfp/abm/main.c
++++ b/drivers/net/ethernet/netronome/nfp/abm/main.c
+@@ -283,6 +283,7 @@ nfp_abm_vnic_set_mac(struct nfp_pf *pf, struct nfp_abm *abm, struct nfp_net *nn,
+ 	if (!nfp_nsp_has_hwinfo_lookup(nsp)) {
+ 		nfp_warn(pf->cpp, "NSP doesn't support PF MAC generation\n");
+ 		eth_hw_addr_random(nn->dp.netdev);
++		nfp_nsp_close(nsp);
+ 		return;
+ 	}
+ 

commit 1d7a7128a2e9e1f137c99b0a44e94d70a77343e3
+Author: Qiushi Wu 
+Date:   Sat May 2 18:33:38 2020 -0500
+
+    power: supply: core: fix memory leak in HWMON error path
+    
+    In function power_supply_add_hwmon_sysfs(), psyhw->props is
+    allocated by bitmap_zalloc(). But this pointer is not deallocated
+    when devm_add_action fail,  which lead to a memory leak bug. To fix
+    this, we replace devm_add_action with devm_add_action_or_reset.
+    
+    Cc: stable@kernel.org
+    Fixes: e67d4dfc9ff19 ("power: supply: Add HWMON compatibility layer")
+    Signed-off-by: Qiushi Wu 
+    Signed-off-by: Sebastian Reichel 
+
+diff --git a/drivers/power/supply/power_supply_hwmon.c b/drivers/power/supply/power_supply_hwmon.c
+index f5d538485aaa..7fe4b6b6ddc8 100644
+--- a/drivers/power/supply/power_supply_hwmon.c
++++ b/drivers/power/supply/power_supply_hwmon.c
+@@ -358,7 +358,7 @@ int power_supply_add_hwmon_sysfs(struct power_supply *psy)
+ 		goto error;
+ 	}
+ 
+-	ret = devm_add_action(dev, power_supply_hwmon_bitmap_free,
++	ret = devm_add_action_or_reset(dev, power_supply_hwmon_bitmap_free,
+ 			      psyhw->props);
+ 	if (ret)
+ 		goto error;

commit 639c0a5b0503fb57127fa8972208d43020a9bcf6
+Author: Aditya Pakki 
+Date:   Thu Dec 19 21:29:24 2019 +0100
+
+    media: media/saa7146: fix incorrect assertion in saa7146_buffer_finish
+    
+    In saa7146_buffer_finish, the code for q->curr to be NULL is
+    already present and asserting for NULL is unnecessary. This patch
+    elimiates such a check.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/common/saa7146/saa7146_fops.c b/drivers/media/common/saa7146/saa7146_fops.c
+index aabb830e7468..d7e83b55ddca 100644
+--- a/drivers/media/common/saa7146/saa7146_fops.c
++++ b/drivers/media/common/saa7146/saa7146_fops.c
+@@ -97,8 +97,6 @@ void saa7146_buffer_finish(struct saa7146_dev *dev,
+ 	DEB_EE("dev:%p, dmaq:%p, state:%d\n", dev, q, state);
+ 	DEB_EE("q->curr:%p\n", q->curr);
+ 
+-	BUG_ON(!q->curr);
+-
+ 	/* finish current buffer */
+ 	if (NULL == q->curr) {
+ 		DEB_D("aiii. no current buffer\n");

commit 2c2a7552dd6465e8fde6bc9cccf8d66ed1c1eb72
+Author: Aditya Pakki 
+Date:   Fri Feb 14 12:21:01 2020 -0600
+
+    ecryptfs: replace BUG_ON with error handling code
+    
+    In crypt_scatterlist, if the crypt_stat argument is not set up
+    correctly, the kernel crashes. Instead, by returning an error code
+    upstream, the error is handled safely.
+    
+    The issue is detected via a static analysis tool written by us.
+    
+    Fixes: 237fead619984 (ecryptfs: fs/Makefile and fs/Kconfig)
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Tyler Hicks 
+
+diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
+index f91db24bbf3b..a064b408d841 100644
+--- a/fs/ecryptfs/crypto.c
++++ b/fs/ecryptfs/crypto.c
+@@ -311,8 +311,10 @@ static int crypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat,
+ 	struct extent_crypt_result ecr;
+ 	int rc = 0;
+ 
+-	BUG_ON(!crypt_stat || !crypt_stat->tfm
+-	       || !(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED));
++	if (!crypt_stat || !crypt_stat->tfm
++	       || !(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED))
++		return -EINVAL;
++
+ 	if (unlikely(ecryptfs_verbosity > 0)) {
+ 		ecryptfs_printk(KERN_DEBUG, "Key size [%zd]; key:\n",
+ 				crypt_stat->key_size);

commit 8d7a577d04e8ce24b1b81ee44ec8cd1dda2a9cd9
+Author: Aditya Pakki 
+Date:   Tue Jan 21 17:33:49 2020 -0600
+
+    clk: samsung: Remove redundant check in samsung_cmu_register_one
+    
+    Consistent with other instances of samsung_clk_init, the check
+    if ctx is NULL is redundant. The function currently does not
+    return NULL.
+    
+    Signed-off-by: Aditya Pakki 
+    Link: https://lkml.kernel.org/r/20200121233349.28627-1-pakki001@umn.edu
+    Acked-by: Chanwoo Choi 
+    Signed-off-by: Stephen Boyd 
+
+diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
+index dad31308c071..1949ae7851b2 100644
+--- a/drivers/clk/samsung/clk.c
++++ b/drivers/clk/samsung/clk.c
+@@ -356,10 +356,6 @@ struct samsung_clk_provider * __init samsung_cmu_register_one(
+ 	}
+ 
+ 	ctx = samsung_clk_init(np, reg_base, cmu->nr_clk_ids);
+-	if (!ctx) {
+-		panic("%s: unable to allocate ctx\n", __func__);
+-		return ctx;
+-	}
+ 
+ 	if (cmu->pll_clks)
+ 		samsung_clk_register_pll(ctx, cmu->pll_clks, cmu->nr_pll_clks,

commit 67e2d2eb542338145a2e0b2336c1cdabd2424fd3
+Author: Aditya Pakki 
+Date:   Thu Jan 30 22:11:33 2020 -0800
+
+    fs: ocfs: remove unnecessary assertion in dlm_migrate_lockres
+    
+    In the only caller of dlm_migrate_lockres() - dlm_empty_lockres(),
+    target is checked for O2NM_MAX_NODES.  Thus, the assertion in
+    dlm_migrate_lockres() is unnecessary and can be removed.  The patch
+    eliminates such a check.
+    
+    Link: http://lkml.kernel.org/r/20191218194111.26041-1-pakki001@umn.edu
+    Signed-off-by: Aditya Pakki 
+    Cc: Mark Fasheh 
+    Cc: Joel Becker 
+    Cc: Junxiao Bi 
+    Cc: Joseph Qi 
+    Cc: Changwei Ge 
+    Cc: Gang He 
+    Cc: Jun Piao 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
+index 74b768ca1cd8..3b239637f884 100644
+--- a/fs/ocfs2/dlm/dlmmaster.c
++++ b/fs/ocfs2/dlm/dlmmaster.c
+@@ -2554,8 +2554,6 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm,
+ 	if (!dlm_grab(dlm))
+ 		return -EINVAL;
+ 
+-	BUG_ON(target == O2NM_MAX_NODES);
+-
+ 	name = res->lockname.name;
+ 	namelen = res->lockname.len;
+ 

commit b0e4cfae483fe1e3db71ab2d8509490df60e52c6
+Author: Aditya Pakki 
+Date:   Mon Jan 6 15:32:51 2020 +0100
+
+    media: davinci/vpfe_capture.c: Avoid BUG_ON for register failure
+    
+    In vpfe_register_ccdc_device(), failure to allocate dev->hw_ops
+    fields calls BUG_ON(). This patch returns the error to callers
+    instead of crashing. The issue was identified by a static
+    analysis tool, written by us.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c
+index 916ed743d716..9b1d9643589b 100644
+--- a/drivers/media/platform/davinci/vpfe_capture.c
++++ b/drivers/media/platform/davinci/vpfe_capture.c
+@@ -168,21 +168,22 @@ int vpfe_register_ccdc_device(const struct ccdc_hw_device *dev)
+ 	int ret = 0;
+ 	printk(KERN_NOTICE "vpfe_register_ccdc_device: %s\n", dev->name);
+ 
+-	BUG_ON(!dev->hw_ops.open);
+-	BUG_ON(!dev->hw_ops.enable);
+-	BUG_ON(!dev->hw_ops.set_hw_if_params);
+-	BUG_ON(!dev->hw_ops.configure);
+-	BUG_ON(!dev->hw_ops.set_buftype);
+-	BUG_ON(!dev->hw_ops.get_buftype);
+-	BUG_ON(!dev->hw_ops.enum_pix);
+-	BUG_ON(!dev->hw_ops.set_frame_format);
+-	BUG_ON(!dev->hw_ops.get_frame_format);
+-	BUG_ON(!dev->hw_ops.get_pixel_format);
+-	BUG_ON(!dev->hw_ops.set_pixel_format);
+-	BUG_ON(!dev->hw_ops.set_image_window);
+-	BUG_ON(!dev->hw_ops.get_image_window);
+-	BUG_ON(!dev->hw_ops.get_line_length);
+-	BUG_ON(!dev->hw_ops.getfid);
++	if (!dev->hw_ops.open ||
++	    !dev->hw_ops.enable ||
++	    !dev->hw_ops.set_hw_if_params ||
++	    !dev->hw_ops.configure ||
++	    !dev->hw_ops.set_buftype ||
++	    !dev->hw_ops.get_buftype ||
++	    !dev->hw_ops.enum_pix ||
++	    !dev->hw_ops.set_frame_format ||
++	    !dev->hw_ops.get_frame_format ||
++	    !dev->hw_ops.get_pixel_format ||
++	    !dev->hw_ops.set_pixel_format ||
++	    !dev->hw_ops.set_image_window ||
++	    !dev->hw_ops.get_image_window ||
++	    !dev->hw_ops.get_line_length ||
++	    !dev->hw_ops.getfid)
++		return -EINVAL;
+ 
+ 	mutex_lock(&ccdc_lock);
+ 	if (!ccdc_cfg) {

commit 1ec4c6efe23154b4ab44c1a34dbc0eb121eb614a
+Author: Aditya Pakki 
+Date:   Sun Dec 15 20:21:33 2019 +0100
+
+    media: saa7146: Avoid using BUG_ON as an assertion
+    
+    In video_begin and video_end, saa7146_format_by_fourcc can return
+    NULL and is checked via BUG_ON. However, by returning the error
+    to the callers upstream, we can avoid the crash and handle it via
+    recovery code.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/common/saa7146/saa7146_video.c b/drivers/media/common/saa7146/saa7146_video.c
+index d16122039b0c..ccd15b4d4920 100644
+--- a/drivers/media/common/saa7146/saa7146_video.c
++++ b/drivers/media/common/saa7146/saa7146_video.c
+@@ -345,7 +345,8 @@ static int video_begin(struct saa7146_fh *fh)
+ 
+ 	fmt = saa7146_format_by_fourcc(dev, vv->video_fmt.pixelformat);
+ 	/* we need to have a valid format set here */
+-	BUG_ON(NULL == fmt);
++	if (!fmt)
++		return -EINVAL;
+ 
+ 	if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {
+ 		resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS;
+@@ -398,7 +399,8 @@ static int video_end(struct saa7146_fh *fh, struct file *file)
+ 
+ 	fmt = saa7146_format_by_fourcc(dev, vv->video_fmt.pixelformat);
+ 	/* we need to have a valid format set here */
+-	BUG_ON(NULL == fmt);
++	if (!fmt)
++		return -EINVAL;
+ 
+ 	if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {
+ 		resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS;

commit 93a24578de721006055b422c7772e0e417e1983c
+Author: Aditya Pakki 
+Date:   Sun Dec 15 20:08:04 2019 +0100
+
+    media: cx231xx: replace BUG_ON with recovery code
+    
+    In cx231xx_i2c_register, if dev->cx231xx_send_usb_command is NULL,
+    the code crashes. However, the callers in cx231xx-core are able to
+    handle the error without crashing. This patch fixes this issue.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/usb/cx231xx/cx231xx-i2c.c b/drivers/media/usb/cx231xx/cx231xx-i2c.c
+index f33b6a077d57..c6659253c6fb 100644
+--- a/drivers/media/usb/cx231xx/cx231xx-i2c.c
++++ b/drivers/media/usb/cx231xx/cx231xx-i2c.c
+@@ -515,7 +515,8 @@ int cx231xx_i2c_register(struct cx231xx_i2c *bus)
+ {
+ 	struct cx231xx *dev = bus->dev;
+ 
+-	BUG_ON(!dev->cx231xx_send_usb_command);
++	if (!dev->cx231xx_send_usb_command)
++		return -EINVAL;
+ 
+ 	bus->i2c_adap = cx231xx_adap_template;
+ 	bus->i2c_adap.dev.parent = dev->dev;

commit 9f48db0d4a08624bb9ba847ea40c8abad753b396
+Author: Aditya Pakki 
+Date:   Tue Dec 17 13:44:37 2019 -0600
+
+    RDMA/srpt: Remove unnecessary assertion in srpt_queue_response
+    
+    Since ch has already been de-referenced by the time we get to the BUG_ON,
+    it is useless. The back trace alone is enough to tell what is going on,
+    delete the redundant BUG_ON.
+    
+    Link: https://lore.kernel.org/r/20191217194437.25568-1-pakki001@umn.edu
+    Signed-off-by: Aditya Pakki 
+    Reviewed-by: Bart Van Assche 
+    Reviewed-by: Jason Gunthorpe 
+    Signed-off-by: Jason Gunthorpe 
+
+diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
+index 23c782e3d49a..98552749d71c 100644
+--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
++++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
+@@ -2810,8 +2810,6 @@ static void srpt_queue_response(struct se_cmd *cmd)
+ 	int resp_len, ret, i;
+ 	u8 srp_tm_status;
+ 
+-	BUG_ON(!ch);
+-
+ 	state = ioctx->state;
+ 	switch (state) {
+ 	case SRPT_STATE_NEW:

commit d7a336d67ab5443a0ef14b8335d139e855e8a682
+Author: Aditya Pakki 
+Date:   Thu Dec 19 11:21:11 2019 -0600
+
+    staging: kpc2000: remove unnecessary assertions in kpc_dma_transfer
+    
+    In kpc_dma_transfer(), the assertion that priv is NULL and priv->ldev
+    is NULL, are never satisfied. The two callers of the function,
+    dereference the fields before the function is called. This patch
+    removes the two BUG_ON calls.
+    
+    Signed-off-by: Aditya Pakki 
+    Link: https://lore.kernel.org/r/20191219172118.17456-1-pakki001@umn.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/kpc2000/kpc_dma/fileops.c b/drivers/staging/kpc2000/kpc_dma/fileops.c
+index cb52bd9a6d2f..40525540dde6 100644
+--- a/drivers/staging/kpc2000/kpc_dma/fileops.c
++++ b/drivers/staging/kpc2000/kpc_dma/fileops.c
+@@ -49,9 +49,7 @@ static int kpc_dma_transfer(struct dev_private_data *priv,
+ 	u64 dma_addr;
+ 	u64 user_ctl;
+ 
+-	BUG_ON(priv == NULL);
+ 	ldev = priv->ldev;
+-	BUG_ON(ldev == NULL);
+ 
+ 	acd = kzalloc(sizeof(*acd), GFP_KERNEL);
+ 	if (!acd) {

commit d6bd6cf9feb81737f9f64d2c1acf98fdaacebad1
+Author: Aditya Pakki 
+Date:   Tue Dec 17 14:53:56 2019 -0600
+
+    xen/grant-table: remove multiple BUG_ON on gnttab_interface
+    
+    gnttab_request_version() always sets the gnttab_interface variable
+    and the assertions to check for empty gnttab_interface is unnecessary.
+    The patch eliminates multiple such assertions.
+    
+    Signed-off-by: Aditya Pakki 
+    Reviewed-by: Juergen Gross 
+    Signed-off-by: Juergen Gross 
+
+diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
+index 49b381e104ef..7b36b51cdb9f 100644
+--- a/drivers/xen/grant-table.c
++++ b/drivers/xen/grant-table.c
+@@ -664,7 +664,6 @@ static int grow_gnttab_list(unsigned int more_frames)
+ 	unsigned int nr_glist_frames, new_nr_glist_frames;
+ 	unsigned int grefs_per_frame;
+ 
+-	BUG_ON(gnttab_interface == NULL);
+ 	grefs_per_frame = gnttab_interface->grefs_per_grant_frame;
+ 
+ 	new_nr_grant_frames = nr_grant_frames + more_frames;
+@@ -1160,7 +1159,6 @@ EXPORT_SYMBOL_GPL(gnttab_unmap_refs_sync);
+ 
+ static unsigned int nr_status_frames(unsigned int nr_grant_frames)
+ {
+-	BUG_ON(gnttab_interface == NULL);
+ 	return gnttab_frames(nr_grant_frames, SPP);
+ }
+ 
+@@ -1388,7 +1386,6 @@ static int gnttab_expand(unsigned int req_entries)
+ 	int rc;
+ 	unsigned int cur, extra;
+ 
+-	BUG_ON(gnttab_interface == NULL);
+ 	cur = nr_grant_frames;
+ 	extra = ((req_entries + gnttab_interface->grefs_per_grant_frame - 1) /
+ 		 gnttab_interface->grefs_per_grant_frame);
+@@ -1423,7 +1420,6 @@ int gnttab_init(void)
+ 	/* Determine the maximum number of frames required for the
+ 	 * grant reference free list on the current hypervisor.
+ 	 */
+-	BUG_ON(gnttab_interface == NULL);
+ 	max_nr_glist_frames = (max_nr_grant_frames *
+ 			       gnttab_interface->grefs_per_grant_frame / RPP);
+ 

commit 52b894393cecdc303990e834778d39b85d0553fc
+Author: Aditya Pakki 
+Date:   Tue Dec 17 15:22:13 2019 -0600
+
+    scsi: libfc: remove unnecessary assertion on ep variable
+    
+    In ft_recv_write_data(), the pointer ep is dereferenced first and then
+    asserts for NULL. The patch removes the unnecessary assertion.
+    
+    Link: https://lore.kernel.org/r/20191217212214.30722-1-pakki001@umn.edu
+    Reviewed-by: Hannes Reinecke 
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/target/tcm_fc/tfc_io.c b/drivers/target/tcm_fc/tfc_io.c
+index 1354a157e9af..6a38ff936389 100644
+--- a/drivers/target/tcm_fc/tfc_io.c
++++ b/drivers/target/tcm_fc/tfc_io.c
+@@ -221,7 +221,6 @@ void ft_recv_write_data(struct ft_cmd *cmd, struct fc_frame *fp)
+ 	ep = fc_seq_exch(seq);
+ 	lport = ep->lp;
+ 	if (cmd->was_ddp_setup) {
+-		BUG_ON(!ep);
+ 		BUG_ON(!lport);
+ 		/*
+ 		 * Since DDP (Large Rx offload) was setup for this request,

commit a886ca6fcfffd337482352f383c1002c72786b17
+Author: Aditya Pakki 
+Date:   Tue Dec 17 15:06:19 2019 -0600
+
+    hdlcdrv: replace unnecessary assertion in hdlcdrv_register
+    
+    In hdlcdrv_register, failure to register the driver causes a crash.
+    The three callers of hdlcdrv_register all pass valid pointers and
+    do not fail. The patch eliminates the unnecessary BUG_ON assertion.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
+index df495b5595f5..e7413a643929 100644
+--- a/drivers/net/hamradio/hdlcdrv.c
++++ b/drivers/net/hamradio/hdlcdrv.c
+@@ -687,8 +687,6 @@ struct net_device *hdlcdrv_register(const struct hdlcdrv_ops *ops,
+ 	struct hdlcdrv_state *s;
+ 	int err;
+ 
+-	BUG_ON(ops == NULL);
+-
+ 	if (privsize < sizeof(struct hdlcdrv_state))
+ 		privsize = sizeof(struct hdlcdrv_state);
+ 

commit 615f22f58029aa747b12768985e7f91cd053daa2
+Author: Aditya Pakki 
+Date:   Tue Dec 17 14:43:00 2019 -0600
+
+    nfc: s3fwrn5: replace the assertion with a WARN_ON
+    
+    In s3fwrn5_fw_recv_frame, if fw_info->rsp is not empty, the
+    current code causes a crash via BUG_ON. However, s3fwrn5_fw_send_msg
+    does not crash in such a scenario. The patch replaces the BUG_ON
+    by returning the error to the callers and frees up skb.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/nfc/s3fwrn5/firmware.c b/drivers/nfc/s3fwrn5/firmware.c
+index be110d9cef02..de613c623a2c 100644
+--- a/drivers/nfc/s3fwrn5/firmware.c
++++ b/drivers/nfc/s3fwrn5/firmware.c
+@@ -507,7 +507,10 @@ int s3fwrn5_fw_recv_frame(struct nci_dev *ndev, struct sk_buff *skb)
+ 	struct s3fwrn5_info *info = nci_get_drvdata(ndev);
+ 	struct s3fwrn5_fw_info *fw_info = &info->fw_info;
+ 
+-	BUG_ON(fw_info->rsp);
++	if (WARN_ON(fw_info->rsp)) {
++		kfree_skb(skb);
++		return -EINVAL;
++	}
+ 
+ 	fw_info->rsp = skb;
+ 

commit fc1b20659597015a30e8ea032f168e97848c1d39
+Author: Aditya Pakki 
+Date:   Tue Dec 17 16:50:47 2019 -0600
+
+    nfsd: remove unnecessary assertion in nfsd4_encode_replay
+    
+    The replay variable is set in the only caller of nfsd4_encode_replay.
+    The assertion is unnecessary and the patch removes this check.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: J. Bruce Fields 
+
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index 1d8a08b84e32..85949fd6ae7f 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -4649,8 +4649,6 @@ nfsd4_encode_replay(struct xdr_stream *xdr, struct nfsd4_op *op)
+ 	__be32 *p;
+ 	struct nfs4_replay *rp = op->replay;
+ 
+-	BUG_ON(!rp);
+-
+ 	p = xdr_reserve_space(xdr, 8 + rp->rp_buflen);
+ 	if (!p) {
+ 		WARN_ON_ONCE(1);

commit 5bf2fc1f9c88397b125d5ec5f65b1ed9300ba59d
+Author: Aditya Pakki 
+Date:   Thu Dec 19 11:57:35 2019 -0600
+
+    bpf: Remove unnecessary assertion on fp_old
+    
+    The two callers of bpf_prog_realloc - bpf_patch_insn_single and
+    bpf_migrate_filter dereference the struct fp_old, before passing
+    it to the function. Thus assertion to check fp_old is unnecessary
+    and can be removed.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Daniel Borkmann 
+    Link: https://lore.kernel.org/bpf/20191219175735.19231-1-pakki001@umn.edu
+
+diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
+index 2ff01a716128..7622dfc36705 100644
+--- a/kernel/bpf/core.c
++++ b/kernel/bpf/core.c
+@@ -222,8 +222,6 @@ struct bpf_prog *bpf_prog_realloc(struct bpf_prog *fp_old, unsigned int size,
+ 	u32 pages, delta;
+ 	int ret;
+ 
+-	BUG_ON(fp_old == NULL);
+-
+ 	size = round_up(size, PAGE_SIZE);
+ 	pages = size / PAGE_SIZE;
+ 	if (pages <= fp_old->pages)

commit c705f9fc6a1736dcf6ec01f8206707c108dca824
+Author: Aditya Pakki 
+Date:   Sun Dec 15 13:58:58 2019 -0600
+
+    orinoco: avoid assertion in case of NULL pointer
+    
+    In ezusb_init, if upriv is NULL, the code crashes. However, the caller
+    in ezusb_probe can handle the error and print the failure message.
+    The patch replaces the BUG_ON call to error return.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Kalle Valo 
+
+diff --git a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
+index 8c79b963bcff..e753f43e0162 100644
+--- a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
++++ b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
+@@ -1361,7 +1361,8 @@ static int ezusb_init(struct hermes *hw)
+ 	int retval;
+ 
+ 	BUG_ON(in_interrupt());
+-	BUG_ON(!upriv);
++	if (!upriv)
++		return -EINVAL;
+ 
+ 	upriv->reply_count = 0;
+ 	/* Write the MAGIC number on the simulated registers to keep

commit 8b6fc114beeb9f1a270e5b6d25c30a5143801bf8
+Author: Aditya Pakki 
+Date:   Sun Dec 15 13:43:44 2019 -0600
+
+    drm: remove duplicate check on parent and avoid BUG_ON
+    
+    In drm_dev_init, parent is checked for NULL via assert after
+    checked in devm_drm_dev_init(). The patch removes the duplicate
+    check and replaces the assertion with WARN_ON. Further, it returns
+    -EINVAL consistent with the usage in devm_drm_dev_init.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Daniel Vetter 
+    Link: https://patchwork.freedesktop.org/patch/msgid/20191215194345.4679-1-pakki001@umn.edu
+
+diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
+index 1b9b40a1c7c9..7c18a980cd4b 100644
+--- a/drivers/gpu/drm/drm_drv.c
++++ b/drivers/gpu/drm/drm_drv.c
+@@ -622,7 +622,8 @@ int drm_dev_init(struct drm_device *dev,
+ 		return -ENODEV;
+ 	}
+ 
+-	BUG_ON(!parent);
++	if (WARN_ON(!parent))
++		return -EINVAL;
+ 
+ 	kref_init(&dev->ref);
+ 	dev->dev = get_device(parent);
+@@ -725,7 +726,7 @@ int devm_drm_dev_init(struct device *parent,
+ {
+ 	int ret;
+ 
+-	if (WARN_ON(!parent || !driver->release))
++	if (WARN_ON(!driver->release))
+ 		return -EINVAL;
+ 
+ 	ret = drm_dev_init(dev, driver, parent);

commit c5dea815834c7d2e9fc633785455bc428b7a1956
+Author: Aditya Pakki 
+Date:   Sun Dec 15 11:51:30 2019 -0600
+
+    net: caif: replace BUG_ON with recovery code
+    
+    In caif_xmit, there is a crash if the ptr dev is NULL. However, by
+    returning the error to the callers, the error can be handled. The
+    patch fixes this issue.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c
+index bd40b114d6cd..d737ceb61203 100644
+--- a/drivers/net/caif/caif_serial.c
++++ b/drivers/net/caif/caif_serial.c
+@@ -270,7 +270,9 @@ static int caif_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
+ 	struct ser_device *ser;
+ 
+-	BUG_ON(dev == NULL);
++	if (WARN_ON(!dev))
++		return -EINVAL;
++
+ 	ser = netdev_priv(dev);
+ 
+ 	/* Send flow off once, on high water mark */

commit bbd20c939c8aa3f27fa30e86691af250bf92973a
+Author: Aditya Pakki 
+Date:   Sun Dec 15 10:14:51 2019 -0600
+
+    fore200e: Fix incorrect checks of NULL pointer dereference
+    
+    In fore200e_send and fore200e_close, the pointers from the arguments
+    are dereferenced in the variable declaration block and then checked
+    for NULL. The patch fixes these issues by avoiding NULL pointer
+    dereferences.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
+index f1a500205313..8fbd36eb8941 100644
+--- a/drivers/atm/fore200e.c
++++ b/drivers/atm/fore200e.c
+@@ -1414,12 +1414,14 @@ fore200e_open(struct atm_vcc *vcc)
+ static void
+ fore200e_close(struct atm_vcc* vcc)
+ {
+-    struct fore200e*        fore200e = FORE200E_DEV(vcc->dev);
+     struct fore200e_vcc*    fore200e_vcc;
++    struct fore200e*        fore200e;
+     struct fore200e_vc_map* vc_map;
+     unsigned long           flags;
+ 
+     ASSERT(vcc);
++    fore200e = FORE200E_DEV(vcc->dev);
++
+     ASSERT((vcc->vpi >= 0) && (vcc->vpi < 1<vci >= 0) && (vcc->vci < 1<dev);
+-    struct fore200e_vcc*    fore200e_vcc = FORE200E_VCC(vcc);
++    struct fore200e*        fore200e;
++    struct fore200e_vcc*    fore200e_vcc;
+     struct fore200e_vc_map* vc_map;
+-    struct host_txq*        txq          = &fore200e->host_txq;
++    struct host_txq*        txq;
+     struct host_txq_entry*  entry;
+     struct tpd*             tpd;
+     struct tpd_haddr        tpd_haddr;
+@@ -1480,9 +1482,18 @@ fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb)
+     unsigned char*          data;
+     unsigned long           flags;
+ 
+-    ASSERT(vcc);
+-    ASSERT(fore200e);
+-    ASSERT(fore200e_vcc);
++    if (!vcc)
++        return -EINVAL;
++
++    fore200e = FORE200E_DEV(vcc->dev);
++    fore200e_vcc = FORE200E_VCC(vcc);
++
++    if (!fore200e)
++        return -EINVAL;
++
++    txq = &fore200e->host_txq;
++    if (!fore200e_vcc)
++        return -EINVAL;
+ 
+     if (!test_bit(ATM_VF_READY, &vcc->flags)) {
+ 	DPRINTK(1, "VC %d.%d.%d not ready for tx\n", vcc->itf, vcc->vpi, vcc->vpi);

commit 1ee7826ab68f7e9fa1a01533983acf6a6f62e297
+Author: Aditya Pakki 
+Date:   Sun Dec 15 09:23:48 2019 -0600
+
+    mac80211: Remove redundant assertion
+    
+    In wiphy_to_ieee80211_hw, the assertion to check if wiphy is NULL is
+    repeated in wiphy_priv. The patch removes the duplicated BUG_ON check.
+    
+    Signed-off-by: Aditya Pakki 
+    Link: https://lore.kernel.org/r/20191215152348.20912-1-pakki001@umn.edu
+    Signed-off-by: Johannes Berg 
+
+diff --git a/net/mac80211/util.c b/net/mac80211/util.c
+index 32a7a53833c0..780df3e9092e 100644
+--- a/net/mac80211/util.c
++++ b/net/mac80211/util.c
+@@ -39,7 +39,6 @@ const void *const mac80211_wiphy_privid = &mac80211_wiphy_privid;
+ struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy)
+ {
+ 	struct ieee80211_local *local;
+-	BUG_ON(!wiphy);
+ 
+ 	local = wiphy_priv(wiphy);
+ 	return &local->hw;

commit 6fc232db9e8cd50b9b83534de9cd91ace711b2d7
+Author: Aditya Pakki 
+Date:   Sun Dec 15 09:34:08 2019 -0600
+
+    rfkill: Fix incorrect check to avoid NULL pointer dereference
+    
+    In rfkill_register, the struct rfkill pointer is first derefernced
+    and then checked for NULL. This patch removes the BUG_ON and returns
+    an error to the caller in case rfkill is NULL.
+    
+    Signed-off-by: Aditya Pakki 
+    Link: https://lore.kernel.org/r/20191215153409.21696-1-pakki001@umn.edu
+    Signed-off-by: Johannes Berg 
+
+diff --git a/net/rfkill/core.c b/net/rfkill/core.c
+index 461d75274fb3..971c73c7d34c 100644
+--- a/net/rfkill/core.c
++++ b/net/rfkill/core.c
+@@ -1002,10 +1002,13 @@ static void rfkill_sync_work(struct work_struct *work)
+ int __must_check rfkill_register(struct rfkill *rfkill)
+ {
+ 	static unsigned long rfkill_no;
+-	struct device *dev = &rfkill->dev;
++	struct device *dev;
+ 	int error;
+ 
+-	BUG_ON(!rfkill);
++	if (!rfkill)
++		return -EINVAL;
++
++	dev = &rfkill->dev;
+ 
+ 	mutex_lock(&rfkill_global_mutex);
+ 

commit 169f9acae08685d4f2a6fd32983958d44e10905d
+Author: Aditya Pakki 
+Date:   Thu Dec 5 17:14:21 2019 -0600
+
+    spi: dw: Avoid BUG_ON() in case of host failure
+    
+    If dws is NULL in dw_spi_host_add(), we return the error to the
+    upper callers instead of crashing. The patch replaces BUG_ON by
+    returning -EINVAL to the caller.
+    
+    Signed-off-by: Aditya Pakki 
+    Link: https://lore.kernel.org/r/20191205231421.9333-1-pakki001@umn.edu
+    Signed-off-by: Mark Brown 
+
+diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c
+index a92aa5cd4fbe..a160d9a141ea 100644
+--- a/drivers/spi/spi-dw.c
++++ b/drivers/spi/spi-dw.c
+@@ -460,7 +460,8 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
+ 	struct spi_controller *master;
+ 	int ret;
+ 
+-	BUG_ON(dws == NULL);
++	if (!dws)
++		return -EINVAL;
+ 
+ 	master = spi_alloc_master(dev, 0);
+ 	if (!master)

commit 02a896ca84874bbfcedc006303f2951dda89b298
+Author: Aditya Pakki 
+Date:   Thu Dec 5 17:04:49 2019 -0600
+
+    pppoe: remove redundant BUG_ON() check in pppoe_pernet
+    
+    Passing NULL to pppoe_pernet causes a crash via BUG_ON.
+    Dereferencing net in net_generici() also has the same effect. This patch
+    removes the redundant BUG_ON check on the same parameter.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
+index a44dd3c8af63..d760a36db28c 100644
+--- a/drivers/net/ppp/pppoe.c
++++ b/drivers/net/ppp/pppoe.c
+@@ -119,8 +119,6 @@ static inline bool stage_session(__be16 sid)
+ 
+ static inline struct pppoe_net *pppoe_pernet(struct net *net)
+ {
+-	BUG_ON(!net);
+-
+ 	return net_generic(net, pppoe_net_id);
+ }
+ 

commit 60f5c4aaae452ae9252128ef7f9ae222aa70c569
+Author: Aditya Pakki 
+Date:   Sun Nov 17 14:28:36 2019 -0600
+
+    net: atm: Reduce the severity of logging in unlink_clip_vcc
+    
+    In case of errors in unlink_clip_vcc, the logging level is set to
+    pr_crit but failures in clip_setentry are handled by pr_err().
+    The patch changes the severity consistent across invocations.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/atm/clip.c b/net/atm/clip.c
+index a7972da7235d..294cb9efe3d3 100644
+--- a/net/atm/clip.c
++++ b/net/atm/clip.c
+@@ -89,7 +89,7 @@ static void unlink_clip_vcc(struct clip_vcc *clip_vcc)
+ 	struct clip_vcc **walk;
+ 
+ 	if (!entry) {
+-		pr_crit("!clip_vcc->entry (clip_vcc %p)\n", clip_vcc);
++		pr_err("!clip_vcc->entry (clip_vcc %p)\n", clip_vcc);
+ 		return;
+ 	}
+ 	netif_tx_lock_bh(entry->neigh->dev);	/* block clip_start_xmit() */
+@@ -109,10 +109,10 @@ static void unlink_clip_vcc(struct clip_vcc *clip_vcc)
+ 			error = neigh_update(entry->neigh, NULL, NUD_NONE,
+ 					     NEIGH_UPDATE_F_ADMIN, 0);
+ 			if (error)
+-				pr_crit("neigh_update failed with %d\n", error);
++				pr_err("neigh_update failed with %d\n", error);
+ 			goto out;
+ 		}
+-	pr_crit("ATMARP: failed (entry %p, vcc 0x%p)\n", entry, clip_vcc);
++	pr_err("ATMARP: failed (entry %p, vcc 0x%p)\n", entry, clip_vcc);
+ out:
+ 	netif_tx_unlock_bh(entry->neigh->dev);
+ }

commit d39083234c60519724c6ed59509a2129fd2aed41
+Author: Kangjie Lu 
+Date:   Fri Oct 18 01:47:00 2019 -0300
+
+    media: rcar_drif: fix a memory disclosure
+    
+    "f->fmt.sdr.reserved" is uninitialized. As other peer drivers
+    like msi2500 and airspy do, the fix initializes it to avoid
+    memory disclosures.
+    
+    Signed-off-by: Kangjie Lu 
+    Reviewed-by: Geert Uytterhoeven 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/rcar_drif.c b/drivers/media/platform/rcar_drif.c
+index 608e5217ccd5..0f267a237b42 100644
+--- a/drivers/media/platform/rcar_drif.c
++++ b/drivers/media/platform/rcar_drif.c
+@@ -912,6 +912,7 @@ static int rcar_drif_g_fmt_sdr_cap(struct file *file, void *priv,
+ {
+ 	struct rcar_drif_sdr *sdr = video_drvdata(file);
+ 
++	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
+ 	f->fmt.sdr.pixelformat = sdr->fmt->pixelformat;
+ 	f->fmt.sdr.buffersize = sdr->fmt->buffersize;
+ 

commit ec3b7b6eb8c90b52f61adff11b6db7a8db34de19
+Author: Kangjie Lu 
+Date:   Thu Oct 17 23:41:50 2019 -0500
+
+    drm/gma500: fix memory disclosures due to uninitialized bytes
+    
+    "clock" may be copied to "best_clock". Initializing best_clock
+    is not sufficient. The fix initializes clock as well to avoid
+    memory disclosures and informaiton leaks.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Daniel Vetter 
+    Link: https://patchwork.freedesktop.org/patch/msgid/20191018044150.1899-1-kjlu@umn.edu
+
+diff --git a/drivers/gpu/drm/gma500/oaktrail_crtc.c b/drivers/gpu/drm/gma500/oaktrail_crtc.c
+index 167c10767dd4..900e5499249d 100644
+--- a/drivers/gpu/drm/gma500/oaktrail_crtc.c
++++ b/drivers/gpu/drm/gma500/oaktrail_crtc.c
+@@ -129,6 +129,7 @@ static bool mrst_sdvo_find_best_pll(const struct gma_limit_t *limit,
+ 	s32 freq_error, min_error = 100000;
+ 
+ 	memset(best_clock, 0, sizeof(*best_clock));
++	memset(&clock, 0, sizeof(clock));
+ 
+ 	for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) {
+ 		for (clock.n = limit->n.min; clock.n <= limit->n.max;
+@@ -185,6 +186,7 @@ static bool mrst_lvds_find_best_pll(const struct gma_limit_t *limit,
+ 	int err = target;
+ 
+ 	memset(best_clock, 0, sizeof(*best_clock));
++	memset(&clock, 0, sizeof(clock));
+ 
+ 	for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) {
+ 		for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max;

commit 57a25a5f754ce27da2cfa6f413cfd366f878db76
+Author: Kangjie Lu 
+Date:   Thu Oct 17 23:29:53 2019 -0500
+
+    gma/gma500: fix a memory disclosure bug due to uninitialized bytes
+    
+    `best_clock` is an object that may be sent out. Object `clock`
+    contains uninitialized bytes that are copied to `best_clock`,
+    which leads to memory disclosure and information leak.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Daniel Vetter 
+    Link: https://patchwork.freedesktop.org/patch/msgid/20191018042953.31099-1-kjlu@umn.edu
+
+diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c
+index f56852a503e8..8b784947ed3b 100644
+--- a/drivers/gpu/drm/gma500/cdv_intel_display.c
++++ b/drivers/gpu/drm/gma500/cdv_intel_display.c
+@@ -405,6 +405,8 @@ static bool cdv_intel_find_dp_pll(const struct gma_limit_t *limit,
+ 	struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
+ 	struct gma_clock_t clock;
+ 
++	memset(&clock, 0, sizeof(clock));
++
+ 	switch (refclk) {
+ 	case 27000:
+ 		if (target < 200000) {

commit 8da96730331dab78e7194c5af48efbcf90264d02
+Author: Kangjie Lu 
+Date:   Fri Mar 15 00:19:03 2019 -0500
+
+    ath10k: fix missing checks for bmi reads and writes
+    
+    ath10k_bmi_write32 and ath10k_bmi_read32 can fail. The fix
+    checks their statuses to avoid potential undefined behaviors.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Kalle Valo 
+
+diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
+index 383d4fa555a8..3d91a4025cfc 100644
+--- a/drivers/net/wireless/ath/ath10k/core.c
++++ b/drivers/net/wireless/ath/ath10k/core.c
+@@ -677,13 +677,22 @@ static void ath10k_send_suspend_complete(struct ath10k *ar)
+ 	complete(&ar->target_suspend);
+ }
+ 
+-static void ath10k_init_sdio(struct ath10k *ar, enum ath10k_firmware_mode mode)
++static int ath10k_init_sdio(struct ath10k *ar, enum ath10k_firmware_mode mode)
+ {
++	int ret;
+ 	u32 param = 0;
+ 
+-	ath10k_bmi_write32(ar, hi_mbox_io_block_sz, 256);
+-	ath10k_bmi_write32(ar, hi_mbox_isr_yield_limit, 99);
+-	ath10k_bmi_read32(ar, hi_acs_flags, ¶m);
++	ret = ath10k_bmi_write32(ar, hi_mbox_io_block_sz, 256);
++	if (ret)
++		return ret;
++
++	ret = ath10k_bmi_write32(ar, hi_mbox_isr_yield_limit, 99);
++	if (ret)
++		return ret;
++
++	ret = ath10k_bmi_read32(ar, hi_acs_flags, ¶m);
++	if (ret)
++		return ret;
+ 
+ 	/* Data transfer is not initiated, when reduced Tx completion
+ 	 * is used for SDIO. disable it until fixed
+@@ -700,14 +709,23 @@ static void ath10k_init_sdio(struct ath10k *ar, enum ath10k_firmware_mode mode)
+ 	else
+ 		param |= HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET;
+ 
+-	ath10k_bmi_write32(ar, hi_acs_flags, param);
++	ret = ath10k_bmi_write32(ar, hi_acs_flags, param);
++	if (ret)
++		return ret;
+ 
+ 	/* Explicitly set fwlog prints to zero as target may turn it on
+ 	 * based on scratch registers.
+ 	 */
+-	ath10k_bmi_read32(ar, hi_option_flag, ¶m);
++	ret = ath10k_bmi_read32(ar, hi_option_flag, ¶m);
++	if (ret)
++		return ret;
++
+ 	param |= HI_OPTION_DISABLE_DBGLOG;
+-	ath10k_bmi_write32(ar, hi_option_flag, param);
++	ret = ath10k_bmi_write32(ar, hi_option_flag, param);
++	if (ret)
++		return ret;
++
++	return 0;
+ }
+ 
+ static int ath10k_init_configure_target(struct ath10k *ar)
+@@ -2565,8 +2583,13 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
+ 		if (status)
+ 			goto err;
+ 
+-		if (ar->hif.bus == ATH10K_BUS_SDIO)
+-			ath10k_init_sdio(ar, mode);
++		if (ar->hif.bus == ATH10K_BUS_SDIO) {
++			status = ath10k_init_sdio(ar, mode);
++			if (status) {
++				ath10k_err(ar, "failed to init SDIO: %d\n", status);
++				goto err;
++			}
++		}
+ 	}
+ 
+ 	ar->htc.htc_ops.target_send_suspend_complete =

commit f4f5748bfec94cf418e49bf05f0c81a1b9ebc950
+Author: Aditya Pakki 
+Date:   Mon Jun 10 12:47:37 2019 +0200
+
+    netfilter: ipset: fix a missing check of nla_parse
+    
+    When nla_parse fails, we should not use the results (the first
+    argument). The fix checks if it fails, and if so, returns its error code
+    upstream.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Jozsef Kadlecsik 
+
+diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
+index 2ad609900b22..d0f4c627ff91 100644
+--- a/net/netfilter/ipset/ip_set_core.c
++++ b/net/netfilter/ipset/ip_set_core.c
+@@ -1544,10 +1544,14 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
+ 		memcpy(&errmsg->msg, nlh, nlh->nlmsg_len);
+ 		cmdattr = (void *)&errmsg->msg + min_len;
+ 
+-		nla_parse_deprecated(cda, IPSET_ATTR_CMD_MAX, cmdattr,
+-				     nlh->nlmsg_len - min_len,
+-				     ip_set_adt_policy, NULL);
++		ret = nla_parse_deprecated(cda, IPSET_ATTR_CMD_MAX, cmdattr,
++					   nlh->nlmsg_len - min_len,
++					   ip_set_adt_policy, NULL);
+ 
++		if (ret) {
++			nlmsg_free(skb2);
++			return ret;
++		}
+ 		errline = nla_data(cda[IPSET_ATTR_LINENO]);
+ 
+ 		*errline = lineno;

commit 20d437ee8f4899573e6ea76c06ef0206e98bccb6
+Author: Kangjie Lu 
+Date:   Fri Mar 8 21:31:23 2019 -0600
+
+    net: ixgbevf: fix a missing check of ixgbevf_write_msg_read_ack
+    
+    If ixgbevf_write_msg_read_ack fails, return its error code upstream
+    
+    Signed-off-by: Kangjie Lu 
+    Tested-by: Andrew Bowers 
+    Reviewed-by: Mukesh Ojha 
+    Signed-off-by: Jeff Kirsher 
+
+diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.c b/drivers/net/ethernet/intel/ixgbevf/vf.c
+index cd3b81300cc7..d5ce49636548 100644
+--- a/drivers/net/ethernet/intel/ixgbevf/vf.c
++++ b/drivers/net/ethernet/intel/ixgbevf/vf.c
+@@ -508,9 +508,8 @@ static s32 ixgbevf_update_mc_addr_list_vf(struct ixgbe_hw *hw,
+ 		vector_list[i++] = ixgbevf_mta_vector(hw, ha->addr);
+ 	}
+ 
+-	ixgbevf_write_msg_read_ack(hw, msgbuf, msgbuf, IXGBE_VFMAILBOX_SIZE);
+-
+-	return 0;
++	return ixgbevf_write_msg_read_ack(hw, msgbuf, msgbuf,
++			IXGBE_VFMAILBOX_SIZE);
+ }
+ 
+ /**

commit e08f0761234def47961d3252eac09ccedfe4c6a0
+Author: Kangjie Lu 
+Date:   Fri Mar 22 22:51:06 2019 -0400
+
+    media: vpss: fix a potential NULL pointer dereference
+    
+    In case ioremap fails, the fix returns -ENOMEM to avoid NULL
+    pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Acked-by: Lad, Prabhakar 
+    Reviewed-by: Mukesh Ojha 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/davinci/vpss.c b/drivers/media/platform/davinci/vpss.c
+index 19cf6853411e..89a86c19579b 100644
+--- a/drivers/media/platform/davinci/vpss.c
++++ b/drivers/media/platform/davinci/vpss.c
+@@ -518,6 +518,11 @@ static int __init vpss_init(void)
+ 		return -EBUSY;
+ 
+ 	oper_cfg.vpss_regs_base2 = ioremap(VPSS_CLK_CTRL, 4);
++	if (unlikely(!oper_cfg.vpss_regs_base2)) {
++		release_mem_region(VPSS_CLK_CTRL, 4);
++		return -ENOMEM;
++	}
++
+ 	writel(VPSS_CLK_CTRL_VENCCLKEN |
+ 		     VPSS_CLK_CTRL_DACCLKEN, oper_cfg.vpss_regs_base2);
+ 

commit 23015b22e47c5409620b1726a677d69e5cd032ba
+Author: Kangjie Lu 
+Date:   Tue May 14 15:44:49 2019 -0700
+
+    rapidio: fix a NULL pointer dereference when create_workqueue() fails
+    
+    In case create_workqueue fails, the fix releases resources and returns
+    -ENOMEM to avoid NULL pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Acked-by: Alexandre Bounine 
+    Cc: Matt Porter 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/rapidio/rio_cm.c b/drivers/rapidio/rio_cm.c
+index cf45829585cb..b29fc258eeba 100644
+--- a/drivers/rapidio/rio_cm.c
++++ b/drivers/rapidio/rio_cm.c
+@@ -2147,6 +2147,14 @@ static int riocm_add_mport(struct device *dev,
+ 	mutex_init(&cm->rx_lock);
+ 	riocm_rx_fill(cm, RIOCM_RX_RING_SIZE);
+ 	cm->rx_wq = create_workqueue(DRV_NAME "/rxq");
++	if (!cm->rx_wq) {
++		riocm_error("failed to allocate IBMBOX_%d on %s",
++			    cmbox, mport->name);
++		rio_release_outb_mbox(mport, cmbox);
++		kfree(cm);
++		return -ENOMEM;
++	}
++
+ 	INIT_WORK(&cm->rx_work, rio_ibmsg_handler);
+ 
+ 	cm->tx_slot = 0;

commit a2be42f18d409213bb7e7a736e3ef6ba005115bb
+Author: Kangjie Lu 
+Date:   Thu Mar 14 22:51:20 2019 -0500
+
+    ASoC: cs43130: fix a NULL pointer dereference
+    
+    In case create_singlethread_workqueue fails, the fix returns
+    -ENOMEM to avoid potential NULL pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/codecs/cs43130.c b/sound/soc/codecs/cs43130.c
+index 3f7b255587e6..80d672710eae 100644
+--- a/sound/soc/codecs/cs43130.c
++++ b/sound/soc/codecs/cs43130.c
+@@ -2322,6 +2322,8 @@ static int cs43130_probe(struct snd_soc_component *component)
+ 			return ret;
+ 
+ 		cs43130->wq = create_singlethread_workqueue("cs43130_hp");
++		if (!cs43130->wq)
++			return -ENOMEM;
+ 		INIT_WORK(&cs43130->work, cs43130_imp_meas);
+ 	}
+ 

commit 51dd97d1df5fb9ac58b9b358e63e67b530f6ae21
+Author: Kangjie Lu 
+Date:   Thu Mar 14 22:48:32 2019 -0500
+
+    ASoC: rt5645: fix a NULL pointer dereference
+    
+    devm_kcalloc() may fail and return NULL. The fix returns ENOMEM
+    in case it fails to avoid NULL pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
+index 9a0751978090..f842775dbf2c 100644
+--- a/sound/soc/codecs/rt5645.c
++++ b/sound/soc/codecs/rt5645.c
+@@ -3419,6 +3419,9 @@ static int rt5645_probe(struct snd_soc_component *component)
+ 		RT5645_HWEQ_NUM, sizeof(struct rt5645_eq_param_s),
+ 		GFP_KERNEL);
+ 
++	if (!rt5645->eq_param)
++		return -ENOMEM;
++
+ 	return 0;
+ }
+ 

commit cbb88db76a1536e02e93e5bd37ebbfbb6c4043a9
+Author: Wenwen Wang 
+Date:   Mon Apr 29 12:45:40 2019 -0500
+
+    ALSA: usx2y: fix a double free bug
+    
+    In usX2Y_In04_init(), a new urb is firstly created through usb_alloc_urb()
+    and saved to 'usX2Y->In04urb'. Then, a buffer is allocated through
+    kmalloc() and saved to 'usX2Y->In04Buf'. If the allocation of the buffer
+    fails, the error code ENOMEM is returned after usb_free_urb(), which frees
+    the created urb. However, the urb is actually freed at card->private_free
+    callback, i.e., snd_usX2Y_card_private_free(). So the free operation here
+    leads to a double free bug.
+    
+    To fix the above issue, simply remove usb_free_urb().
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
+index 9f7bbed2c0f0..e8687b3bd3c8 100644
+--- a/sound/usb/usx2y/usbusx2y.c
++++ b/sound/usb/usx2y/usbusx2y.c
+@@ -293,10 +293,8 @@ int usX2Y_In04_init(struct usX2Ydev *usX2Y)
+ 	if (! (usX2Y->In04urb = usb_alloc_urb(0, GFP_KERNEL)))
+ 		return -ENOMEM;
+ 
+-	if (! (usX2Y->In04Buf = kmalloc(21, GFP_KERNEL))) {
+-		usb_free_urb(usX2Y->In04urb);
++	if (! (usX2Y->In04Buf = kmalloc(21, GFP_KERNEL)))
+ 		return -ENOMEM;
+-	}
+ 	 
+ 	init_waitqueue_head(&usX2Y->In04WaitQueue);
+ 	usb_fill_int_urb(usX2Y->In04urb, usX2Y->dev, usb_rcvintpipe(usX2Y->dev, 0x4),

commit cb5173594d50c72b7bfa14113dfc5084b4d2f726
+Author: Wenwen Wang 
+Date:   Sat Apr 27 01:06:46 2019 -0500
+
+    ALSA: usb-audio: Fix a memory leak bug
+    
+    In parse_audio_selector_unit(), the string array 'namelist' is allocated
+    through kmalloc_array(), and each string pointer in this array, i.e.,
+    'namelist[]', is allocated through kmalloc() in the following for loop.
+    Then, a control instance 'kctl' is created by invoking snd_ctl_new1(). If
+    an error occurs during the creation process, the string array 'namelist',
+    including all string pointers in the array 'namelist[]', should be freed,
+    before the error code ENOMEM is returned. However, the current code does
+    not free 'namelist[]', resulting in memory leaks.
+    
+    To fix the above issue, free all string pointers 'namelist[]' in a loop.
+    
+    Signed-off-by: Wenwen Wang 
+    Cc: 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
+index c095d9751924..e003b5e7b01a 100644
+--- a/sound/usb/mixer.c
++++ b/sound/usb/mixer.c
+@@ -2675,6 +2675,8 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid,
+ 	kctl = snd_ctl_new1(&mixer_selectunit_ctl, cval);
+ 	if (! kctl) {
+ 		usb_audio_err(state->chip, "cannot malloc kcontrol\n");
++		for (i = 0; i < desc->bNrInPins; i++)
++			kfree(namelist[i]);
+ 		kfree(namelist);
+ 		kfree(cval);
+ 		return -ENOMEM;

commit 91862cc7867bba4ee5c8fcf0ca2f1d30427b6129
+Author: Wenwen Wang 
+Date:   Fri Apr 19 21:22:59 2019 -0500
+
+    tracing: Fix a memory leak by early error exit in trace_pid_write()
+    
+    In trace_pid_write(), the buffer for trace parser is allocated through
+    kmalloc() in trace_parser_get_init(). Later on, after the buffer is used,
+    it is then freed through kfree() in trace_parser_put(). However, it is
+    possible that trace_pid_write() is terminated due to unexpected errors,
+    e.g., ENOMEM. In that case, the allocated buffer will not be freed, which
+    is a memory leak bug.
+    
+    To fix this issue, free the allocated buffer when an error is encountered.
+    
+    Link: http://lkml.kernel.org/r/1555726979-15633-1-git-send-email-wang6495@umn.edu
+    
+    Fixes: f4d34a87e9c10 ("tracing: Use pid bitmap instead of a pid array for set_event_pid")
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Steven Rostedt (VMware) 
+
+diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
+index 0cfa13a60086..46f68fad6373 100644
+--- a/kernel/trace/trace.c
++++ b/kernel/trace/trace.c
+@@ -496,8 +496,10 @@ int trace_pid_write(struct trace_pid_list *filtered_pids,
+ 	 * not modified.
+ 	 */
+ 	pid_list = kmalloc(sizeof(*pid_list), GFP_KERNEL);
+-	if (!pid_list)
++	if (!pid_list) {
++		trace_parser_put(&parser);
+ 		return -ENOMEM;
++	}
+ 
+ 	pid_list->pid_max = READ_ONCE(pid_max);
+ 
+@@ -507,6 +509,7 @@ int trace_pid_write(struct trace_pid_list *filtered_pids,
+ 
+ 	pid_list->pids = vzalloc((pid_list->pid_max + 7) >> 3);
+ 	if (!pid_list->pids) {
++		trace_parser_put(&parser);
+ 		kfree(pid_list);
+ 		return -ENOMEM;
+ 	}

commit 06d5d6b7f9948a89543e1160ef852d57892c750d
+Author: Kangjie Lu 
+Date:   Sat Apr 13 11:34:47 2019 +0100
+
+    slimbus: fix a potential NULL pointer dereference in of_qcom_slim_ngd_register
+    
+    In case platform_device_alloc fails, the fix returns an error
+    code to avoid the NULL pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Srinivas Kandagatla 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/slimbus/qcom-ngd-ctrl.c b/drivers/slimbus/qcom-ngd-ctrl.c
+index 71f094c9ec68..f3585777324c 100644
+--- a/drivers/slimbus/qcom-ngd-ctrl.c
++++ b/drivers/slimbus/qcom-ngd-ctrl.c
+@@ -1342,6 +1342,10 @@ static int of_qcom_slim_ngd_register(struct device *parent,
+ 			return -ENOMEM;
+ 
+ 		ngd->pdev = platform_device_alloc(QCOM_SLIM_NGD_DRV_NAME, id);
++		if (!ngd->pdev) {
++			kfree(ngd);
++			return -ENOMEM;
++		}
+ 		ngd->id = id;
+ 		ngd->pdev->dev.parent = parent;
+ 		ngd->pdev->driver_override = QCOM_SLIM_NGD_DRV_NAME;

commit d5414c2355b20ea8201156d2e874265f1cb0d775
+Author: Aditya Pakki 
+Date:   Sat Mar 23 15:49:16 2019 -0500
+
+    rsi: Fix NULL pointer dereference in kmalloc
+    
+    kmalloc can fail in rsi_register_rates_channels but memcpy still attempts
+    to write to channels. The patch replaces these calls with kmemdup and
+    passes the error upstream.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Kalle Valo 
+
+diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+index 831046e760f8..49df3bb08d41 100644
+--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
++++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+@@ -188,27 +188,27 @@ bool rsi_is_cipher_wep(struct rsi_common *common)
+  * @adapter: Pointer to the adapter structure.
+  * @band: Operating band to be set.
+  *
+- * Return: None.
++ * Return: int - 0 on success, negative error on failure.
+  */
+-static void rsi_register_rates_channels(struct rsi_hw *adapter, int band)
++static int rsi_register_rates_channels(struct rsi_hw *adapter, int band)
+ {
+ 	struct ieee80211_supported_band *sbands = &adapter->sbands[band];
+ 	void *channels = NULL;
+ 
+ 	if (band == NL80211_BAND_2GHZ) {
+-		channels = kmalloc(sizeof(rsi_2ghz_channels), GFP_KERNEL);
+-		memcpy(channels,
+-		       rsi_2ghz_channels,
+-		       sizeof(rsi_2ghz_channels));
++		channels = kmemdup(rsi_2ghz_channels, sizeof(rsi_2ghz_channels),
++				   GFP_KERNEL);
++		if (!channels)
++			return -ENOMEM;
+ 		sbands->band = NL80211_BAND_2GHZ;
+ 		sbands->n_channels = ARRAY_SIZE(rsi_2ghz_channels);
+ 		sbands->bitrates = rsi_rates;
+ 		sbands->n_bitrates = ARRAY_SIZE(rsi_rates);
+ 	} else {
+-		channels = kmalloc(sizeof(rsi_5ghz_channels), GFP_KERNEL);
+-		memcpy(channels,
+-		       rsi_5ghz_channels,
+-		       sizeof(rsi_5ghz_channels));
++		channels = kmemdup(rsi_5ghz_channels, sizeof(rsi_5ghz_channels),
++				   GFP_KERNEL);
++		if (!channels)
++			return -ENOMEM;
+ 		sbands->band = NL80211_BAND_5GHZ;
+ 		sbands->n_channels = ARRAY_SIZE(rsi_5ghz_channels);
+ 		sbands->bitrates = &rsi_rates[4];
+@@ -227,6 +227,7 @@ static void rsi_register_rates_channels(struct rsi_hw *adapter, int band)
+ 	sbands->ht_cap.mcs.rx_mask[0] = 0xff;
+ 	sbands->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
+ 	/* sbands->ht_cap.mcs.rx_highest = 0x82; */
++	return 0;
+ }
+ 
+ static int rsi_mac80211_hw_scan_start(struct ieee80211_hw *hw,
+@@ -2064,11 +2065,16 @@ int rsi_mac80211_attach(struct rsi_common *common)
+ 	wiphy->available_antennas_rx = 1;
+ 	wiphy->available_antennas_tx = 1;
+ 
+-	rsi_register_rates_channels(adapter, NL80211_BAND_2GHZ);
++	status = rsi_register_rates_channels(adapter, NL80211_BAND_2GHZ);
++	if (status)
++		return status;
+ 	wiphy->bands[NL80211_BAND_2GHZ] =
+ 		&adapter->sbands[NL80211_BAND_2GHZ];
+ 	if (common->num_supp_bands > 1) {
+-		rsi_register_rates_channels(adapter, NL80211_BAND_5GHZ);
++		status = rsi_register_rates_channels(adapter,
++						     NL80211_BAND_5GHZ);
++		if (status)
++			return status;
+ 		wiphy->bands[NL80211_BAND_5GHZ] =
+ 			&adapter->sbands[NL80211_BAND_5GHZ];
+ 	}

commit 0ed2a005347400500a39ea7c7318f1fea57fb3ca
+Author: Kangjie Lu 
+Date:   Tue Mar 12 03:05:02 2019 -0500
+
+    net: cw1200: fix a NULL pointer dereference
+    
+    In case create_singlethread_workqueue fails, the fix free the
+    hardware and returns NULL to avoid NULL pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Kalle Valo 
+
+diff --git a/drivers/net/wireless/st/cw1200/main.c b/drivers/net/wireless/st/cw1200/main.c
+index 90dc979f260b..c1608f0bf6d0 100644
+--- a/drivers/net/wireless/st/cw1200/main.c
++++ b/drivers/net/wireless/st/cw1200/main.c
+@@ -345,6 +345,11 @@ static struct ieee80211_hw *cw1200_init_common(const u8 *macaddr,
+ 	mutex_init(&priv->wsm_cmd_mux);
+ 	mutex_init(&priv->conf_mutex);
+ 	priv->workqueue = create_singlethread_workqueue("cw1200_wq");
++	if (!priv->workqueue) {
++		ieee80211_free_hw(hw);
++		return NULL;
++	}
++
+ 	sema_init(&priv->scan.lock, 1);
+ 	INIT_WORK(&priv->scan.work, cw1200_scan_work);
+ 	INIT_DELAYED_WORK(&priv->scan.probe_work, cw1200_probe_work);

commit 22e8860cf8f777fbf6a83f2fb7127f682a8e9de4
+Author: Kangjie Lu 
+Date:   Sun Mar 24 18:18:56 2019 -0500
+
+    net: ieee802154: fix missing checks for regmap_update_bits
+    
+    regmap_update_bits could fail and deserves a check.
+    
+    The patch adds the checks and if it fails, returns its error
+    code upstream.
+    
+    Signed-off-by: Kangjie Lu 
+    Reviewed-by: Mukesh Ojha 
+    Signed-off-by: Stefan Schmidt 
+
+diff --git a/drivers/net/ieee802154/mcr20a.c b/drivers/net/ieee802154/mcr20a.c
+index c589f5ae75bb..8bb53ec8d9cf 100644
+--- a/drivers/net/ieee802154/mcr20a.c
++++ b/drivers/net/ieee802154/mcr20a.c
+@@ -533,6 +533,8 @@ mcr20a_start(struct ieee802154_hw *hw)
+ 	dev_dbg(printdev(lp), "no slotted operation\n");
+ 	ret = regmap_update_bits(lp->regmap_dar, DAR_PHY_CTRL1,
+ 				 DAR_PHY_CTRL1_SLOTTED, 0x0);
++	if (ret < 0)
++		return ret;
+ 
+ 	/* enable irq */
+ 	enable_irq(lp->spi->irq);
+@@ -540,11 +542,15 @@ mcr20a_start(struct ieee802154_hw *hw)
+ 	/* Unmask SEQ interrupt */
+ 	ret = regmap_update_bits(lp->regmap_dar, DAR_PHY_CTRL2,
+ 				 DAR_PHY_CTRL2_SEQMSK, 0x0);
++	if (ret < 0)
++		return ret;
+ 
+ 	/* Start the RX sequence */
+ 	dev_dbg(printdev(lp), "start the RX sequence\n");
+ 	ret = regmap_update_bits(lp->regmap_dar, DAR_PHY_CTRL1,
+ 				 DAR_PHY_CTRL1_XCVSEQ_MASK, MCR20A_XCVSEQ_RX);
++	if (ret < 0)
++		return ret;
+ 
+ 	return 0;
+ }

commit 70c4cf17e445264453bc5323db3e50aa0ac9e81f
+Author: Wenwen Wang 
+Date:   Fri Apr 19 20:49:29 2019 -0500
+
+    audit: fix a memory leak bug
+    
+    In audit_rule_change(), audit_data_to_entry() is firstly invoked to
+    translate the payload data to the kernel's rule representation. In
+    audit_data_to_entry(), depending on the audit field type, an audit tree may
+    be created in audit_make_tree(), which eventually invokes kmalloc() to
+    allocate the tree.  Since this tree is a temporary tree, it will be then
+    freed in the following execution, e.g., audit_add_rule() if the message
+    type is AUDIT_ADD_RULE or audit_del_rule() if the message type is
+    AUDIT_DEL_RULE. However, if the message type is neither AUDIT_ADD_RULE nor
+    AUDIT_DEL_RULE, i.e., the default case of the switch statement, this
+    temporary tree is not freed.
+    
+    To fix this issue, only allocate the tree when the type is AUDIT_ADD_RULE
+    or AUDIT_DEL_RULE.
+    
+    Signed-off-by: Wenwen Wang 
+    Reviewed-by: Richard Guy Briggs 
+    Signed-off-by: Paul Moore 
+
+diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
+index 2c3c2f349b23..1bc6410413e6 100644
+--- a/kernel/auditfilter.c
++++ b/kernel/auditfilter.c
+@@ -1114,22 +1114,24 @@ int audit_rule_change(int type, int seq, void *data, size_t datasz)
+ 	int err = 0;
+ 	struct audit_entry *entry;
+ 
+-	entry = audit_data_to_entry(data, datasz);
+-	if (IS_ERR(entry))
+-		return PTR_ERR(entry);
+-
+ 	switch (type) {
+ 	case AUDIT_ADD_RULE:
++		entry = audit_data_to_entry(data, datasz);
++		if (IS_ERR(entry))
++			return PTR_ERR(entry);
+ 		err = audit_add_rule(entry);
+ 		audit_log_rule_change("add_rule", &entry->rule, !err);
+ 		break;
+ 	case AUDIT_DEL_RULE:
++		entry = audit_data_to_entry(data, datasz);
++		if (IS_ERR(entry))
++			return PTR_ERR(entry);
+ 		err = audit_del_rule(entry);
+ 		audit_log_rule_change("remove_rule", &entry->rule, !err);
+ 		break;
+ 	default:
+-		err = -EINVAL;
+ 		WARN_ON(1);
++		return -EINVAL;
+ 	}
+ 
+ 	if (err || type == AUDIT_DEL_RULE) {

commit ea094d53580f40c2124cef3d072b73b2425e7bfd
+Author: Wenwen Wang 
+Date:   Wed Apr 17 09:18:50 2019 -0500
+
+    x86/PCI: Fix PCI IRQ routing table memory leak
+    
+    In pcibios_irq_init(), the PCI IRQ routing table 'pirq_table' is first
+    found through pirq_find_routing_table().  If the table is not found and
+    CONFIG_PCI_BIOS is defined, the table is then allocated in
+    pcibios_get_irq_routing_table() using kmalloc().  Later, if the I/O APIC is
+    used, this table is actually not used.  In that case, the allocated table
+    is not freed, which is a memory leak.
+    
+    Free the allocated table if it is not used.
+    
+    Signed-off-by: Wenwen Wang 
+    [bhelgaas: added Ingo's reviewed-by, since the only change since v1 was to
+    use the irq_routing_table local variable name he suggested]
+    Signed-off-by: Bjorn Helgaas 
+    Reviewed-by: Ingo Molnar 
+    Acked-by: Thomas Gleixner 
+
+diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
+index 52e55108404e..d3a73f9335e1 100644
+--- a/arch/x86/pci/irq.c
++++ b/arch/x86/pci/irq.c
+@@ -1119,6 +1119,8 @@ static const struct dmi_system_id pciirq_dmi_table[] __initconst = {
+ 
+ void __init pcibios_irq_init(void)
+ {
++	struct irq_routing_table *rtable = NULL;
++
+ 	DBG(KERN_DEBUG "PCI: IRQ init\n");
+ 
+ 	if (raw_pci_ops == NULL)
+@@ -1129,8 +1131,10 @@ void __init pcibios_irq_init(void)
+ 	pirq_table = pirq_find_routing_table();
+ 
+ #ifdef CONFIG_PCI_BIOS
+-	if (!pirq_table && (pci_probe & PCI_BIOS_IRQ_SCAN))
++	if (!pirq_table && (pci_probe & PCI_BIOS_IRQ_SCAN)) {
+ 		pirq_table = pcibios_get_irq_routing_table();
++		rtable = pirq_table;
++	}
+ #endif
+ 	if (pirq_table) {
+ 		pirq_peer_trick();
+@@ -1145,8 +1149,10 @@ void __init pcibios_irq_init(void)
+ 		 * If we're using the I/O APIC, avoid using the PCI IRQ
+ 		 * routing table
+ 		 */
+-		if (io_apic_assign_pci_irqs)
++		if (io_apic_assign_pci_irqs) {
++			kfree(rtable);
+ 			pirq_table = NULL;
++		}
+ 	}
+ 
+ 	x86_init.pci.fixup_irqs();

commit 39416c5872db69859e867fa250b9cbb3f1e0d185
+Author: Wenwen Wang 
+Date:   Mon Apr 15 12:58:06 2019 -0500
+
+    udf: fix an uninitialized read bug and remove dead code
+    
+    In udf_lookup(), the pointer 'fi' is a local variable initialized by the
+    return value of the function call udf_find_entry(). However, if the macro
+    'UDF_RECOVERY' is defined, this variable will become uninitialized if the
+    else branch is not taken, which can potentially cause incorrect results in
+    the following execution.
+    
+    To fix this issue, this patch drops the whole code in the ifdef
+    'UDF_RECOVERY' region, as it is dead code.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Jan Kara 
+
+diff --git a/fs/udf/namei.c b/fs/udf/namei.c
+index 58cc2414992b..77b6d89b9bcd 100644
+--- a/fs/udf/namei.c
++++ b/fs/udf/namei.c
+@@ -304,21 +304,6 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
+ 	if (dentry->d_name.len > UDF_NAME_LEN)
+ 		return ERR_PTR(-ENAMETOOLONG);
+ 
+-#ifdef UDF_RECOVERY
+-	/* temporary shorthand for specifying files by inode number */
+-	if (!strncmp(dentry->d_name.name, ".B=", 3)) {
+-		struct kernel_lb_addr lb = {
+-			.logicalBlockNum = 0,
+-			.partitionReferenceNum =
+-				simple_strtoul(dentry->d_name.name + 3,
+-						NULL, 0),
+-		};
+-		inode = udf_iget(dir->i_sb, lb);
+-		if (IS_ERR(inode))
+-			return inode;
+-	} else
+-#endif /* UDF_RECOVERY */
+-
+ 	fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi);
+ 	if (IS_ERR(fi))
+ 		return ERR_CAST(fi);

commit 611025983b7976df0183390a63a2166411d177f1
+Author: Kangjie Lu 
+Date:   Mon Mar 11 00:53:33 2019 -0500
+
+    mmc_spi: add a status check for spi_sync_locked
+    
+    In case spi_sync_locked fails, the fix reports the error and
+    returns the error code upstream.
+    
+    Signed-off-by: Kangjie Lu 
+    Reviewed-by: Laurent Pinchart 
+    Signed-off-by: Ulf Hansson 
+
+diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
+index 1b1498805972..a3533935e282 100644
+--- a/drivers/mmc/host/mmc_spi.c
++++ b/drivers/mmc/host/mmc_spi.c
+@@ -819,6 +819,10 @@ mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t,
+ 	}
+ 
+ 	status = spi_sync_locked(spi, &host->m);
++	if (status < 0) {
++		dev_dbg(&spi->dev, "read error %d\n", status);
++		return status;
++	}
+ 
+ 	if (host->dma_dev) {
+ 		dma_sync_single_for_cpu(host->dma_dev,

commit d9350f21e5fe2614e1f78ef20c3a3e83c4a36391
+Author: Aditya Pakki 
+Date:   Fri Mar 22 16:55:03 2019 -0500
+
+    firmware: arm_scmi: replace of_match_device->data with of_device_get_match_data()
+    
+    of_match_device can return NULL if no matching device is found though
+    it's highly unlikely to happen in scmi_probe as it's called only if
+    a valid match is found.
+    
+    However we can use of_device_get_match_data() instead of
+    of_match_device()->data to handle NULL pointer checks and return -EINVAL
+    in such a scenario.
+    
+    Reviewed-by: Steven Price 
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Sudeep Holla 
+
+diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
+index dd967d675c08..b5bc4c7a8fab 100644
+--- a/drivers/firmware/arm_scmi/driver.c
++++ b/drivers/firmware/arm_scmi/driver.c
+@@ -796,7 +796,9 @@ static int scmi_probe(struct platform_device *pdev)
+ 		return -EINVAL;
+ 	}
+ 
+-	desc = of_match_device(scmi_of_match, dev)->data;
++	desc = of_device_get_match_data(dev);
++	if (!desc)
++		return -EINVAL;
+ 
+ 	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
+ 	if (!info)

commit 507b820009a457afa78202da337bcb56791fbb12
+Author: Kangjie Lu 
+Date:   Fri Mar 15 00:07:10 2019 -0500
+
+    PCI: endpoint: Fix a potential NULL pointer dereference
+    
+    In case alloc_workqueue() fails, return -ENOMEM to avoid
+    potential NULL pointer dereferences.
+    
+    Signed-off-by: Kangjie Lu 
+    [lorenzo.pieralisi@arm.com: commit log and code update]
+    Signed-off-by: Lorenzo Pieralisi 
+
+diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c
+index d0b91da49bf4..ed5cd28b9572 100644
+--- a/drivers/pci/endpoint/functions/pci-epf-test.c
++++ b/drivers/pci/endpoint/functions/pci-epf-test.c
+@@ -591,6 +591,11 @@ static int __init pci_epf_test_init(void)
+ 
+ 	kpcitest_workqueue = alloc_workqueue("kpcitest",
+ 					     WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
++	if (!kpcitest_workqueue) {
++		pr_err("Failed to allocate the kpcitest work queue\n");
++		return -ENOMEM;
++	}
++
+ 	ret = pci_epf_register_driver(&test_driver);
+ 	if (ret) {
+ 		pr_err("Failed to register pci epf test driver --> %d\n", ret);

commit e183d4e414b64711baf7a04e214b61969ca08dfa
+Author: Kangjie Lu 
+Date:   Thu Apr 11 11:17:31 2019 +0200
+
+    net/smc: fix a NULL pointer dereference
+    
+    In case alloc_ordered_workqueue fails, the fix returns NULL
+    to avoid NULL pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Ursula Braun 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/smc/smc_ism.c b/net/smc/smc_ism.c
+index 2fff79db1a59..e89e918b88e0 100644
+--- a/net/smc/smc_ism.c
++++ b/net/smc/smc_ism.c
+@@ -289,6 +289,11 @@ struct smcd_dev *smcd_alloc_dev(struct device *parent, const char *name,
+ 	INIT_LIST_HEAD(&smcd->vlan);
+ 	smcd->event_wq = alloc_ordered_workqueue("ism_evt_wq-%s)",
+ 						 WQ_MEM_RECLAIM, name);
++	if (!smcd->event_wq) {
++		kfree(smcd->conn);
++		kfree(smcd);
++		return NULL;
++	}
+ 	return smcd;
+ }
+ EXPORT_SYMBOL_GPL(smcd_alloc_dev);

commit d1a0846006e4325cc951ca0b05c02ed1d0865006
+Author: Kangjie Lu 
+Date:   Fri Mar 15 16:00:25 2019 -0500
+
+    security: inode: fix a missing check for securityfs_create_file
+    
+    securityfs_create_file  may fail. The fix checks its status and
+    returns the error code upstream if it fails.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: James Morris 
+
+diff --git a/security/inode.c b/security/inode.c
+index b7772a9b315e..667f8b15027d 100644
+--- a/security/inode.c
++++ b/security/inode.c
+@@ -339,6 +339,11 @@ static int __init securityfs_init(void)
+ #ifdef CONFIG_SECURITY
+ 	lsm_dentry = securityfs_create_file("lsm", 0444, NULL, NULL,
+ 						&lsm_ops);
++	if (IS_ERR(lsm_dentry)) {
++		unregister_filesystem(&fs_type);
++		sysfs_remove_mount_point(kernel_kobj, "security");
++		return PTR_ERR(lsm_dentry);
++	}
+ #endif
+ 	return 0;
+ }

commit 1adc90c7395742827d754a5f02f446818a77c379
+Author: Aditya Pakki 
+Date:   Tue Mar 12 10:19:10 2019 -0500
+
+    pinctrl: axp209: Fix NULL pointer dereference after allocation
+    
+    axp20x_build_funcs_groups allocates groups via devm_kcalloc and tries to
+    dereference without checking for NULL. This patch avoids such a
+    scenario.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Linus Walleij 
+
+diff --git a/drivers/pinctrl/pinctrl-axp209.c b/drivers/pinctrl/pinctrl-axp209.c
+index afd0b533c40a..4fcf7262bed9 100644
+--- a/drivers/pinctrl/pinctrl-axp209.c
++++ b/drivers/pinctrl/pinctrl-axp209.c
+@@ -366,6 +366,8 @@ static int axp20x_build_funcs_groups(struct platform_device *pdev)
+ 		pctl->funcs[i].groups = devm_kcalloc(&pdev->dev,
+ 						     npins, sizeof(char *),
+ 						     GFP_KERNEL);
++		if (!pctl->funcs[i].groups)
++			return -ENOMEM;
+ 		for (pin = 0; pin < npins; pin++)
+ 			pctl->funcs[i].groups[pin] = pctl->desc->pins[pin].name;
+ 	}

commit 6f0ce4dfc5a35bcb21f26d5347f4797fdde52810
+Author: Aditya Pakki 
+Date:   Mon Mar 18 18:24:34 2019 -0500
+
+    mtd: rawnand: vf610: Avoid a potential NULL pointer dereference
+    
+    of_match_device can return NULL if there is no matching device. Avoid
+    a potential NULL pointer dereference by checking for the return value
+    and passing the error upstream.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Miquel Raynal 
+
+diff --git a/drivers/mtd/nand/raw/vf610_nfc.c b/drivers/mtd/nand/raw/vf610_nfc.c
+index a662ca1970e5..6d43ddb3332f 100644
+--- a/drivers/mtd/nand/raw/vf610_nfc.c
++++ b/drivers/mtd/nand/raw/vf610_nfc.c
+@@ -850,6 +850,9 @@ static int vf610_nfc_probe(struct platform_device *pdev)
+ 	}
+ 
+ 	of_id = of_match_device(vf610_nfc_dt_ids, &pdev->dev);
++	if (!of_id)
++		return -ENODEV;
++
+ 	nfc->variant = (enum vf610_nfc_variant)of_id->data;
+ 
+ 	for_each_available_child_of_node(nfc->dev->of_node, child) {

commit 75cf4f5aa903604e1bd7bec2c0988d643c6fb946
+Author: Kangjie Lu 
+Date:   Thu Mar 14 01:02:47 2019 -0500
+
+    power: charger-manager: fix a potential NULL pointer dereference
+    
+    In case create_freezable_workqueue fails, the fix return -ENOMEM
+    to avoid a potential NULL pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Sebastian Reichel 
+
+diff --git a/drivers/power/supply/charger-manager.c b/drivers/power/supply/charger-manager.c
+index 2e8db5e6de0b..a6900aa0d2ed 100644
+--- a/drivers/power/supply/charger-manager.c
++++ b/drivers/power/supply/charger-manager.c
+@@ -1987,6 +1987,9 @@ static struct platform_driver charger_manager_driver = {
+ static int __init charger_manager_init(void)
+ {
+ 	cm_wq = create_freezable_workqueue("charger_manager");
++	if (unlikely(!cm_wq))
++		return -ENOMEM;
++
+ 	INIT_DELAYED_WORK(&cm_monitor_work, cm_monitor_poller);
+ 
+ 	return platform_driver_register(&charger_manager_driver);

commit 536cc27deade8f1ec3c1beefa60d5fbe0f6fcb28
+Author: Kangjie Lu 
+Date:   Sat Mar 16 17:08:33 2019 -0500
+
+    iio: hmc5843: fix potential NULL pointer dereferences
+    
+    devm_regmap_init_i2c may fail and return NULL. The fix returns
+    the error when it fails.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Jonathan Cameron 
+
+diff --git a/drivers/iio/magnetometer/hmc5843_i2c.c b/drivers/iio/magnetometer/hmc5843_i2c.c
+index 3de7f4426ac4..86abba5827a2 100644
+--- a/drivers/iio/magnetometer/hmc5843_i2c.c
++++ b/drivers/iio/magnetometer/hmc5843_i2c.c
+@@ -58,8 +58,13 @@ static const struct regmap_config hmc5843_i2c_regmap_config = {
+ static int hmc5843_i2c_probe(struct i2c_client *cli,
+ 			     const struct i2c_device_id *id)
+ {
++	struct regmap *regmap = devm_regmap_init_i2c(cli,
++			&hmc5843_i2c_regmap_config);
++	if (IS_ERR(regmap))
++		return PTR_ERR(regmap);
++
+ 	return hmc5843_common_probe(&cli->dev,
+-			devm_regmap_init_i2c(cli, &hmc5843_i2c_regmap_config),
++			regmap,
+ 			id->driver_data, id->name);
+ }
+ 
+diff --git a/drivers/iio/magnetometer/hmc5843_spi.c b/drivers/iio/magnetometer/hmc5843_spi.c
+index 535f03a70d63..79b2b707f90e 100644
+--- a/drivers/iio/magnetometer/hmc5843_spi.c
++++ b/drivers/iio/magnetometer/hmc5843_spi.c
+@@ -58,6 +58,7 @@ static const struct regmap_config hmc5843_spi_regmap_config = {
+ static int hmc5843_spi_probe(struct spi_device *spi)
+ {
+ 	int ret;
++	struct regmap *regmap;
+ 	const struct spi_device_id *id = spi_get_device_id(spi);
+ 
+ 	spi->mode = SPI_MODE_3;
+@@ -67,8 +68,12 @@ static int hmc5843_spi_probe(struct spi_device *spi)
+ 	if (ret)
+ 		return ret;
+ 
++	regmap = devm_regmap_init_spi(spi, &hmc5843_spi_regmap_config);
++	if (IS_ERR(regmap))
++		return PTR_ERR(regmap);
++
+ 	return hmc5843_common_probe(&spi->dev,
+-			devm_regmap_init_spi(spi, &hmc5843_spi_regmap_config),
++			regmap,
+ 			id->driver_data, id->name);
+ }
+ 

commit 13814627c9658cf8382dd052bc251ee415670a55
+Author: Kangjie Lu 
+Date:   Fri Mar 8 22:53:55 2019 -0600
+
+    iio: adc: fix a potential NULL pointer dereference
+    
+    devm_iio_trigger_alloc may fail and return NULL. The fix returns
+    ENOMEM when it fails.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Jonathan Cameron 
+
+diff --git a/drivers/iio/adc/mxs-lradc-adc.c b/drivers/iio/adc/mxs-lradc-adc.c
+index c627513d9f0f..5384472b6c4d 100644
+--- a/drivers/iio/adc/mxs-lradc-adc.c
++++ b/drivers/iio/adc/mxs-lradc-adc.c
+@@ -465,6 +465,8 @@ static int mxs_lradc_adc_trigger_init(struct iio_dev *iio)
+ 
+ 	trig = devm_iio_trigger_alloc(&iio->dev, "%s-dev%i", iio->name,
+ 				      iio->id);
++	if (!trig)
++		return -ENOMEM;
+ 
+ 	trig->dev.parent = adc->dev;
+ 	iio_trigger_set_drvdata(trig, iio);

commit f0d14edd2ba43b995bef4dd5da5ffe0ae19321a1
+Author: Kangjie Lu 
+Date:   Fri Mar 15 02:29:43 2019 -0500
+
+    PCI: rcar: Fix a potential NULL pointer dereference
+    
+    In case __get_free_pages() fails and returns NULL, fix the return
+    value to -ENOMEM and release resources to avoid dereferencing a
+    NULL pointer.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Lorenzo Pieralisi 
+    Reviewed-by: Ulrich Hecht 
+    Reviewed-by: Geert Uytterhoeven 
+    Reviewed-by: Simon Horman 
+
+diff --git a/drivers/pci/controller/pcie-rcar.c b/drivers/pci/controller/pcie-rcar.c
+index a25527185bf1..0004b6457124 100644
+--- a/drivers/pci/controller/pcie-rcar.c
++++ b/drivers/pci/controller/pcie-rcar.c
+@@ -929,6 +929,10 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
+ 
+ 	/* setup MSI data target */
+ 	msi->pages = __get_free_pages(GFP_KERNEL, 0);
++	if (!msi->pages) {
++		err = -ENOMEM;
++		goto err;
++	}
+ 	base = virt_to_phys((void *)msi->pages);
+ 
+ 	rcar_pci_write_reg(pcie, lower_32_bits(base) | MSIFE, PCIEMSIALR);

commit 765976285a8c8db3f0eb7f033829a899d0c2786e
+Author: Kangjie Lu 
+Date:   Tue Mar 12 02:56:33 2019 -0500
+
+    rtlwifi: fix a potential NULL pointer dereference
+    
+    In case alloc_workqueue fails, the fix reports the error and
+    returns to avoid NULL pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Kalle Valo 
+
+diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c
+index 217d2a7a43c7..ac746c322554 100644
+--- a/drivers/net/wireless/realtek/rtlwifi/base.c
++++ b/drivers/net/wireless/realtek/rtlwifi/base.c
+@@ -448,6 +448,11 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
+ 	/* <2> work queue */
+ 	rtlpriv->works.hw = hw;
+ 	rtlpriv->works.rtl_wq = alloc_workqueue("%s", 0, 0, rtlpriv->cfg->name);
++	if (unlikely(!rtlpriv->works.rtl_wq)) {
++		pr_err("Failed to allocate work queue\n");
++		return;
++	}
++
+ 	INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq,
+ 			  (void *)rtl_watchdog_wq_callback);
+ 	INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq,

commit e5b9b206f3f6376b9a1406b67eafe4e7bb9f123c
+Author: Kangjie Lu 
+Date:   Tue Mar 12 00:31:07 2019 -0500
+
+    net: mwifiex: fix a NULL pointer dereference
+    
+    In case dev_alloc_skb fails, the fix returns -ENOMEM to avoid
+    NULL pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Kalle Valo 
+
+diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
+index 60db2b969e20..8c35441fd9b7 100644
+--- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
++++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
+@@ -341,6 +341,12 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter)
+ 		sleep_cfm_tmp =
+ 			dev_alloc_skb(sizeof(struct mwifiex_opt_sleep_confirm)
+ 				      + MWIFIEX_TYPE_LEN);
++		if (!sleep_cfm_tmp) {
++			mwifiex_dbg(adapter, ERROR,
++				    "SLEEP_CFM: dev_alloc_skb failed\n");
++			return -ENOMEM;
++		}
++
+ 		skb_put(sleep_cfm_tmp, sizeof(struct mwifiex_opt_sleep_confirm)
+ 			+ MWIFIEX_TYPE_LEN);
+ 		put_unaligned_le32(MWIFIEX_USB_TYPE_CMD, sleep_cfm_tmp->data);

commit 46953f97224d56a12ccbe9c6acaa84ca0dab2780
+Author: Kangjie Lu 
+Date:   Fri Mar 15 12:04:32 2019 -0500
+
+    brcmfmac: fix missing checks for kmemdup
+    
+    In case kmemdup fails, the fix sets conn_info->req_ie_len and
+    conn_info->resp_ie_len to zero to avoid buffer overflows.
+    
+    Signed-off-by: Kangjie Lu 
+    Acked-by: Arend van Spriel 
+    Signed-off-by: Kalle Valo 
+
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+index e92f6351bd22..8ee8af4e7ec4 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -5464,6 +5464,8 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg,
+ 		conn_info->req_ie =
+ 		    kmemdup(cfg->extra_buf, conn_info->req_ie_len,
+ 			    GFP_KERNEL);
++		if (!conn_info->req_ie)
++			conn_info->req_ie_len = 0;
+ 	} else {
+ 		conn_info->req_ie_len = 0;
+ 		conn_info->req_ie = NULL;
+@@ -5480,6 +5482,8 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg,
+ 		conn_info->resp_ie =
+ 		    kmemdup(cfg->extra_buf, conn_info->resp_ie_len,
+ 			    GFP_KERNEL);
++		if (!conn_info->resp_ie)
++			conn_info->resp_ie_len = 0;
+ 	} else {
+ 		conn_info->resp_ie_len = 0;
+ 		conn_info->resp_ie = NULL;

commit 3c77ff8f8bae4d328de662b26921bc4da1d293f1
+Author: Kangjie Lu 
+Date:   Sun Mar 24 18:16:02 2019 -0500
+
+    drm/v3d: fix a missing check of pm_runtime_get_sync
+    
+    pm_runtime_get_sync could fail and thus deserves a check.
+    
+    The patch adds such a check and return its error code upstream
+    if it indeed failed.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Eric Anholt 
+    Link: https://patchwork.freedesktop.org/patch/msgid/20190324231602.2436-1-kjlu@umn.edu
+    Reviewed-by: Mukesh Ojha 
+
+diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c
+index d600628bb5c1..a06b05f714a5 100644
+--- a/drivers/gpu/drm/v3d/v3d_drv.c
++++ b/drivers/gpu/drm/v3d/v3d_drv.c
+@@ -102,6 +102,8 @@ static int v3d_get_param_ioctl(struct drm_device *dev, void *data,
+ 			return -EINVAL;
+ 
+ 		ret = pm_runtime_get_sync(v3d->dev);
++		if (ret < 0)
++			return ret;
+ 		if (args->param >= DRM_V3D_PARAM_V3D_CORE0_IDENT0 &&
+ 		    args->param <= DRM_V3D_PARAM_V3D_CORE0_IDENT2) {
+ 			args->value = V3D_CORE_READ(0, offset);

commit 1d84353d205a953e2381044953b7fa31c8c9702d
+Author: Kangjie Lu 
+Date:   Mon Apr 1 17:46:58 2019 +0200
+
+    video: imsttfb: fix potential NULL pointer dereferences
+    
+    In case ioremap fails, the fix releases resources and returns
+    -ENOMEM to avoid NULL pointer dereferences.
+    
+    Signed-off-by: Kangjie Lu 
+    Cc: Aditya Pakki 
+    Cc: Finn Thain 
+    Cc: Rob Herring 
+    Cc: Greg Kroah-Hartman 
+    [b.zolnierkie: minor patch summary fixup]
+    Signed-off-by: Bartlomiej Zolnierkiewicz 
+
+diff --git a/drivers/video/fbdev/imsttfb.c b/drivers/video/fbdev/imsttfb.c
+index 4b9615e4ce74..35bba3c2036d 100644
+--- a/drivers/video/fbdev/imsttfb.c
++++ b/drivers/video/fbdev/imsttfb.c
+@@ -1515,6 +1515,11 @@ static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	info->fix.smem_start = addr;
+ 	info->screen_base = (__u8 *)ioremap(addr, par->ramdac == IBM ?
+ 					    0x400000 : 0x800000);
++	if (!info->screen_base) {
++		release_mem_region(addr, size);
++		framebuffer_release(info);
++		return -ENOMEM;
++	}
+ 	info->fix.mmio_start = addr + 0x800000;
+ 	par->dc_regs = ioremap(addr + 0x800000, 0x1000);
+ 	par->cmap_regs_phys = addr + 0x840000;

commit ec7f6aad57ad29e4e66cc2e18e1e1599ddb02542
+Author: Kangjie Lu 
+Date:   Mon Apr 1 17:46:58 2019 +0200
+
+    video: hgafb: fix potential NULL pointer dereference
+    
+    When ioremap fails, hga_vram should not be dereferenced. The fix
+    check the failure to avoid NULL pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Cc: Aditya Pakki 
+    Cc: Ferenc Bakonyi 
+    [b.zolnierkie: minor patch summary fixup]
+    Signed-off-by: Bartlomiej Zolnierkiewicz 
+
+diff --git a/drivers/video/fbdev/hgafb.c b/drivers/video/fbdev/hgafb.c
+index 463028543173..59e1cae57948 100644
+--- a/drivers/video/fbdev/hgafb.c
++++ b/drivers/video/fbdev/hgafb.c
+@@ -285,6 +285,8 @@ static int hga_card_detect(void)
+ 	hga_vram_len  = 0x08000;
+ 
+ 	hga_vram = ioremap(0xb0000, hga_vram_len);
++	if (!hga_vram)
++		goto error;
+ 
+ 	if (request_region(0x3b0, 12, "hgafb"))
+ 		release_io_ports = 1;

commit 31fa6e2ae65feed0de10823c5d1eea21a93086c9
+Author: Aditya Pakki 
+Date:   Mon Apr 1 17:46:57 2019 +0200
+
+    omapfb: Fix potential NULL pointer dereference in kmalloc
+    
+    Memory allocated, using kmalloc, for new_compat may fail. This patch
+    checks for such an error and prevents potential NULL pointer
+    dereference.
+    
+    Signed-off-by: Aditya Pakki 
+    Cc: Kangjie Lu 
+    Signed-off-by: Bartlomiej Zolnierkiewicz 
+
+diff --git a/drivers/video/fbdev/omap2/omapfb/dss/omapdss-boot-init.c b/drivers/video/fbdev/omap2/omapfb/dss/omapdss-boot-init.c
+index cb6acbac9c47..5da7ed6d653e 100644
+--- a/drivers/video/fbdev/omap2/omapfb/dss/omapdss-boot-init.c
++++ b/drivers/video/fbdev/omap2/omapfb/dss/omapdss-boot-init.c
+@@ -111,6 +111,8 @@ static void __init omapdss_omapify_node(struct device_node *node)
+ 
+ 	new_len = prop->length + strlen(prefix) * num_strs;
+ 	new_compat = kmalloc(new_len, GFP_KERNEL);
++	if (!new_compat)
++		return;
+ 
+ 	omapdss_prefix_strcpy(new_compat, new_len, prop->value, prop->length);
+ 

commit 0aab8e4df4702b31314a27ec4b0631dfad0fae0a
+Author: Kangjie Lu 
+Date:   Sat Mar 9 00:04:11 2019 -0600
+
+    leds: pca9532: fix a potential NULL pointer dereference
+    
+    In case of_match_device cannot find a match, return -EINVAL to avoid
+    NULL pointer dereference.
+    
+    Fixes: fa4191a609f2 ("leds: pca9532: Add device tree support")
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Jacek Anaszewski 
+
+diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c
+index 7fea18b0c15d..7cb4d685a1f1 100644
+--- a/drivers/leds/leds-pca9532.c
++++ b/drivers/leds/leds-pca9532.c
+@@ -513,6 +513,7 @@ static int pca9532_probe(struct i2c_client *client,
+ 	const struct i2c_device_id *id)
+ {
+ 	int devid;
++	const struct of_device_id *of_id;
+ 	struct pca9532_data *data = i2c_get_clientdata(client);
+ 	struct pca9532_platform_data *pca9532_pdata =
+ 			dev_get_platdata(&client->dev);
+@@ -528,8 +529,11 @@ static int pca9532_probe(struct i2c_client *client,
+ 			dev_err(&client->dev, "no platform data\n");
+ 			return -EINVAL;
+ 		}
+-		devid = (int)(uintptr_t)of_match_device(
+-			of_pca9532_leds_match, &client->dev)->data;
++		of_id = of_match_device(of_pca9532_leds_match,
++				&client->dev);
++		if (unlikely(!of_id))
++			return -EINVAL;
++		devid = (int)(uintptr_t) of_id->data;
+ 	} else {
+ 		devid = id->driver_data;
+ 	}

commit 8e949363f017e2011464812a714fb29710fb95b4
+Author: Aditya Pakki 
+Date:   Tue Mar 19 16:42:40 2019 -0500
+
+    net: mlx5: Add a missing check on idr_find, free buf
+    
+    idr_find() can return a NULL value to 'flow' which is used without a
+    check. The patch adds a check to avoid potential NULL pointer dereference.
+    
+    In case of mlx5_fpga_sbu_conn_sendmsg() failure, free buf allocated
+    using kzalloc.
+    
+    Fixes: ab412e1dd7db ("net/mlx5: Accel, add TLS rx offload routines")
+    Signed-off-by: Aditya Pakki 
+    Reviewed-by: Yuval Shaia 
+    Signed-off-by: Saeed Mahameed 
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fpga/tls.c b/drivers/net/ethernet/mellanox/mlx5/core/fpga/tls.c
+index 5cf5f2a9d51f..8de64e88c670 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/fpga/tls.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/fpga/tls.c
+@@ -217,15 +217,21 @@ int mlx5_fpga_tls_resync_rx(struct mlx5_core_dev *mdev, u32 handle, u32 seq,
+ 	void *cmd;
+ 	int ret;
+ 
++	rcu_read_lock();
++	flow = idr_find(&mdev->fpga->tls->rx_idr, ntohl(handle));
++	rcu_read_unlock();
++
++	if (!flow) {
++		WARN_ONCE(1, "Received NULL pointer for handle\n");
++		return -EINVAL;
++	}
++
+ 	buf = kzalloc(size, GFP_ATOMIC);
+ 	if (!buf)
+ 		return -ENOMEM;
+ 
+ 	cmd = (buf + 1);
+ 
+-	rcu_read_lock();
+-	flow = idr_find(&mdev->fpga->tls->rx_idr, ntohl(handle));
+-	rcu_read_unlock();
+ 	mlx5_fpga_tls_flow_to_cmd(flow, cmd);
+ 
+ 	MLX5_SET(tls_cmd, cmd, swid, ntohl(handle));
+@@ -238,6 +244,8 @@ int mlx5_fpga_tls_resync_rx(struct mlx5_core_dev *mdev, u32 handle, u32 seq,
+ 	buf->complete = mlx_tls_kfree_complete;
+ 
+ 	ret = mlx5_fpga_sbu_conn_sendmsg(mdev->fpga->tls->conn, buf);
++	if (ret < 0)
++		kfree(buf);
+ 
+ 	return ret;
+ }

commit b5af36e3e5aa074605a4d90a89dd8f714b30909b
+Author: Kangjie Lu 
+Date:   Thu Mar 14 01:45:24 2019 -0500
+
+    staging: greybus: audio_manager: fix a missing check of ida_simple_get
+    
+    ida_simple_get could fail. The fix inserts a check for its
+    return value.
+    
+    Signed-off-by: Kangjie Lu 
+    Reviewed-by: Vaibhav Agarwal 
+    Acked-by: Viresh Kumar 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/greybus/audio_manager.c b/drivers/staging/greybus/audio_manager.c
+index d44b070d8862..c2a4af4c1d06 100644
+--- a/drivers/staging/greybus/audio_manager.c
++++ b/drivers/staging/greybus/audio_manager.c
+@@ -45,6 +45,9 @@ int gb_audio_manager_add(struct gb_audio_manager_module_descriptor *desc)
+ 	int err;
+ 
+ 	id = ida_simple_get(&module_id, 0, 0, GFP_KERNEL);
++	if (id < 0)
++		return id;
++
+ 	err = gb_audio_manager_module_create(&module, manager_kset,
+ 					     id, desc);
+ 	if (err) {

commit 699ca30162686bf305cdf94861be02eb0cf9bda2
+Author: Kangjie Lu 
+Date:   Mon Mar 25 17:19:09 2019 -0500
+
+    PCI: xilinx: Check for __get_free_pages() failure
+    
+    If __get_free_pages() fails, return -ENOMEM to avoid a NULL pointer
+    dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Lorenzo Pieralisi 
+    Reviewed-by: Steven Price 
+    Reviewed-by: Mukesh Ojha 
+
+diff --git a/drivers/pci/controller/pcie-xilinx.c b/drivers/pci/controller/pcie-xilinx.c
+index 9bd1a35cd5d8..5bf3af3b28e6 100644
+--- a/drivers/pci/controller/pcie-xilinx.c
++++ b/drivers/pci/controller/pcie-xilinx.c
+@@ -336,14 +336,19 @@ static const struct irq_domain_ops msi_domain_ops = {
+  * xilinx_pcie_enable_msi - Enable MSI support
+  * @port: PCIe port information
+  */
+-static void xilinx_pcie_enable_msi(struct xilinx_pcie_port *port)
++static int xilinx_pcie_enable_msi(struct xilinx_pcie_port *port)
+ {
+ 	phys_addr_t msg_addr;
+ 
+ 	port->msi_pages = __get_free_pages(GFP_KERNEL, 0);
++	if (!port->msi_pages)
++		return -ENOMEM;
++
+ 	msg_addr = virt_to_phys((void *)port->msi_pages);
+ 	pcie_write(port, 0x0, XILINX_PCIE_REG_MSIBASE1);
+ 	pcie_write(port, msg_addr, XILINX_PCIE_REG_MSIBASE2);
++
++	return 0;
+ }
+ 
+ /* INTx Functions */
+@@ -498,6 +503,7 @@ static int xilinx_pcie_init_irq_domain(struct xilinx_pcie_port *port)
+ 	struct device *dev = port->dev;
+ 	struct device_node *node = dev->of_node;
+ 	struct device_node *pcie_intc_node;
++	int ret;
+ 
+ 	/* Setup INTx */
+ 	pcie_intc_node = of_get_next_child(node, NULL);
+@@ -526,7 +532,9 @@ static int xilinx_pcie_init_irq_domain(struct xilinx_pcie_port *port)
+ 			return -ENODEV;
+ 		}
+ 
+-		xilinx_pcie_enable_msi(port);
++		ret = xilinx_pcie_enable_msi(port);
++		if (ret)
++			return ret;
+ 	}
+ 
+ 	return 0;

commit f8ee34c3e77afd8cfc13f98e326325f17494f1e5
+Author: Kangjie Lu 
+Date:   Sat Mar 9 02:42:26 2019 -0500
+
+    media: usbvision: fix a potential NULL pointer dereference
+    
+    In case usb_alloc_coherent fails, the fix returns -ENOMEM to
+    avoid a potential NULL pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/usb/usbvision/usbvision-core.c b/drivers/media/usb/usbvision/usbvision-core.c
+index 92d166bf8c12..abc4eed832a3 100644
+--- a/drivers/media/usb/usbvision/usbvision-core.c
++++ b/drivers/media/usb/usbvision/usbvision-core.c
+@@ -2302,6 +2302,9 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
+ 					   sb_size,
+ 					   GFP_KERNEL,
+ 					   &urb->transfer_dma);
++		if (!usbvision->sbuf[buf_idx].data)
++			return -ENOMEM;
++
+ 		urb->dev = dev;
+ 		urb->context = usbvision;
+ 		urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp);

commit aeb0d0f581e2079868e64a2e5ee346d340376eae
+Author: Kangjie Lu 
+Date:   Sat Mar 9 02:20:56 2019 -0500
+
+    media: video-mux: fix null pointer dereferences
+    
+    devm_kcalloc may fail and return a null pointer. The fix returns
+    -ENOMEM upon failures to avoid null pointer dereferences.
+    
+    Signed-off-by: Kangjie Lu 
+    Reviewed-by: Philipp Zabel 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/video-mux.c b/drivers/media/platform/video-mux.c
+index 0ba30756e1e4..d8cd5f5cb10d 100644
+--- a/drivers/media/platform/video-mux.c
++++ b/drivers/media/platform/video-mux.c
+@@ -419,9 +419,14 @@ static int video_mux_probe(struct platform_device *pdev)
+ 	vmux->active = -1;
+ 	vmux->pads = devm_kcalloc(dev, num_pads, sizeof(*vmux->pads),
+ 				  GFP_KERNEL);
++	if (!vmux->pads)
++		return -ENOMEM;
++
+ 	vmux->format_mbus = devm_kcalloc(dev, num_pads,
+ 					 sizeof(*vmux->format_mbus),
+ 					 GFP_KERNEL);
++	if (!vmux->format_mbus)
++		return -ENOMEM;
+ 
+ 	for (i = 0; i < num_pads; i++) {
+ 		vmux->pads[i].flags = (i < num_pads - 1) ? MEDIA_PAD_FL_SINK

commit fd21b79e541e4666c938a344f3ad2df74b4f5120
+Author: Aditya Pakki 
+Date:   Mon Mar 25 16:25:22 2019 -0500
+
+    thunderbolt: Fix to check the return value of kmemdup
+    
+    uuid in add_switch is allocted via kmemdup which can fail. The patch
+    logs the error and cleans up the allocated memory for switch.
+    
+    Signed-off-by: Aditya Pakki 
+    Reviewed-by: Mukesh Ojha 
+    Signed-off-by: Mika Westerberg 
+
+diff --git a/drivers/thunderbolt/icm.c b/drivers/thunderbolt/icm.c
+index e3fc920af682..8b7f9131e9d1 100644
+--- a/drivers/thunderbolt/icm.c
++++ b/drivers/thunderbolt/icm.c
+@@ -473,6 +473,11 @@ static void add_switch(struct tb_switch *parent_sw, u64 route,
+ 		goto out;
+ 
+ 	sw->uuid = kmemdup(uuid, sizeof(*uuid), GFP_KERNEL);
++	if (!sw->uuid) {
++		tb_sw_warn(sw, "cannot allocate memory for switch\n");
++		tb_switch_put(sw);
++		goto out;
++	}
+ 	sw->connection_id = connection_id;
+ 	sw->connection_key = connection_key;
+ 	sw->link = link;

commit 6183d5a51866f3acdeeb66b75e87d44025b01a55
+Author: Kangjie Lu 
+Date:   Mon Mar 25 15:23:08 2019 -0500
+
+    thunderbolt: property: Fix a missing check of kzalloc
+    
+    No check is enforced for the return value of kzalloc,
+    which may lead to NULL-pointer dereference.
+    
+    The patch fixes this issue.
+    
+    Signed-off-by: Kangjie Lu 
+    Reviewed-by: Mukesh Ojha 
+    Signed-off-by: Mika Westerberg 
+
+diff --git a/drivers/thunderbolt/property.c b/drivers/thunderbolt/property.c
+index 841314deb446..d5b0cdb8f0b1 100644
+--- a/drivers/thunderbolt/property.c
++++ b/drivers/thunderbolt/property.c
+@@ -587,7 +587,12 @@ int tb_property_add_text(struct tb_property_dir *parent, const char *key,
+ 		return -ENOMEM;
+ 
+ 	property->length = size / 4;
+-	property->value.data = kzalloc(size, GFP_KERNEL);
++	property->value.text = kzalloc(size, GFP_KERNEL);
++	if (!property->value.text) {
++		kfree(property);
++		return -ENOMEM;
++	}
++
+ 	strcpy(property->value.text, text);
+ 
+ 	list_add_tail(&property->list, &parent->properties);

commit 13bd14a41ce3105d5b1f3cd8b4d1e249d17b6d9b
+Author: Kangjie Lu 
+Date:   Fri Mar 8 21:50:24 2019 -0600
+
+    char: hpet: fix a missing check of ioremap
+    
+    Check if ioremap fails, and if so, return AE_ERROR.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
+index d0ad85900b79..3a1e6b3ccd10 100644
+--- a/drivers/char/hpet.c
++++ b/drivers/char/hpet.c
+@@ -973,6 +973,8 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
+ 	if (ACPI_SUCCESS(status)) {
+ 		hdp->hd_phys_address = addr.address.minimum;
+ 		hdp->hd_address = ioremap(addr.address.minimum, addr.address.address_length);
++		if (!hdp->hd_address)
++			return AE_ERROR;
+ 
+ 		if (hpet_is_known(hdp)) {
+ 			iounmap(hdp->hd_address);

commit 486fa92df4707b5df58d6508728bdb9321a59766
+Author: Aditya Pakki 
+Date:   Mon Mar 25 16:55:27 2019 -0500
+
+    libnvdimm/btt: Fix a kmemdup failure check
+    
+    In case kmemdup fails, the fix releases resources and returns to
+    avoid the NULL pointer dereference.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Dan Williams 
+
+diff --git a/drivers/nvdimm/btt_devs.c b/drivers/nvdimm/btt_devs.c
+index b72a303176c7..9486acc08402 100644
+--- a/drivers/nvdimm/btt_devs.c
++++ b/drivers/nvdimm/btt_devs.c
+@@ -198,14 +198,15 @@ static struct device *__nd_btt_create(struct nd_region *nd_region,
+ 		return NULL;
+ 
+ 	nd_btt->id = ida_simple_get(&nd_region->btt_ida, 0, 0, GFP_KERNEL);
+-	if (nd_btt->id < 0) {
+-		kfree(nd_btt);
+-		return NULL;
+-	}
++	if (nd_btt->id < 0)
++		goto out_nd_btt;
+ 
+ 	nd_btt->lbasize = lbasize;
+-	if (uuid)
++	if (uuid) {
+ 		uuid = kmemdup(uuid, 16, GFP_KERNEL);
++		if (!uuid)
++			goto out_put_id;
++	}
+ 	nd_btt->uuid = uuid;
+ 	dev = &nd_btt->dev;
+ 	dev_set_name(dev, "btt%d.%d", nd_region->id, nd_btt->id);
+@@ -220,6 +221,13 @@ static struct device *__nd_btt_create(struct nd_region *nd_region,
+ 		return NULL;
+ 	}
+ 	return dev;
++
++out_put_id:
++	ida_simple_remove(&nd_region->btt_ida, nd_btt->id);
++
++out_nd_btt:
++	kfree(nd_btt);
++	return NULL;
+ }
+ 
+ struct device *nd_btt_create(struct nd_region *nd_region)

commit 1bbb1c318cd8a3a39e8c3e2e83d5e90542d6c3e3
+Author: Kangjie Lu 
+Date:   Fri Mar 15 02:07:12 2019 -0500
+
+    tty: ipwireless: fix missing checks for ioremap
+    
+    ipw->attr_memory and ipw->common_memory are assigned with the
+    return value of ioremap. ioremap may fail, but no checks
+    are enforced. The fix inserts the checks to avoid potential
+    NULL pointer dereferences.
+    
+    Signed-off-by: Kangjie Lu 
+    Reviewed-by: David Sterba 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/tty/ipwireless/main.c b/drivers/tty/ipwireless/main.c
+index 3475e841ef5c..4c18bbfe1a92 100644
+--- a/drivers/tty/ipwireless/main.c
++++ b/drivers/tty/ipwireless/main.c
+@@ -114,6 +114,10 @@ static int ipwireless_probe(struct pcmcia_device *p_dev, void *priv_data)
+ 
+ 	ipw->common_memory = ioremap(p_dev->resource[2]->start,
+ 				resource_size(p_dev->resource[2]));
++	if (!ipw->common_memory) {
++		ret = -ENOMEM;
++		goto exit1;
++	}
+ 	if (!request_mem_region(p_dev->resource[2]->start,
+ 				resource_size(p_dev->resource[2]),
+ 				IPWIRELESS_PCCARD_NAME)) {
+@@ -134,6 +138,10 @@ static int ipwireless_probe(struct pcmcia_device *p_dev, void *priv_data)
+ 
+ 	ipw->attr_memory = ioremap(p_dev->resource[3]->start,
+ 				resource_size(p_dev->resource[3]));
++	if (!ipw->attr_memory) {
++		ret = -ENOMEM;
++		goto exit3;
++	}
+ 	if (!request_mem_region(p_dev->resource[3]->start,
+ 				resource_size(p_dev->resource[3]),
+ 				IPWIRELESS_PCCARD_NAME)) {

commit e2a438bd7116889af36304903b92e56d0f347228
+Author: Kangjie Lu 
+Date:   Fri Mar 15 01:57:14 2019 -0500
+
+    RDMA/i40iw: Handle workqueue allocation failure
+    
+    alloc_ordered_workqueue may fail and return NULL.  The fix captures the
+    failure and handles it properly to avoid potential NULL pointer
+    dereferences.
+    
+    Signed-off-by: Kangjie Lu 
+    Reviewed-by: Shiraz, Saleem 
+    Signed-off-by: Jason Gunthorpe 
+
+diff --git a/drivers/infiniband/hw/i40iw/i40iw.h b/drivers/infiniband/hw/i40iw/i40iw.h
+index 2f2b4426ded7..8feec35f95a7 100644
+--- a/drivers/infiniband/hw/i40iw/i40iw.h
++++ b/drivers/infiniband/hw/i40iw/i40iw.h
+@@ -552,7 +552,7 @@ enum i40iw_status_code i40iw_obj_aligned_mem(struct i40iw_device *iwdev,
+ 
+ void i40iw_request_reset(struct i40iw_device *iwdev);
+ void i40iw_destroy_rdma_device(struct i40iw_ib_device *iwibdev);
+-void i40iw_setup_cm_core(struct i40iw_device *iwdev);
++int i40iw_setup_cm_core(struct i40iw_device *iwdev);
+ void i40iw_cleanup_cm_core(struct i40iw_cm_core *cm_core);
+ void i40iw_process_ceq(struct i40iw_device *, struct i40iw_ceq *iwceq);
+ void i40iw_process_aeq(struct i40iw_device *);
+diff --git a/drivers/infiniband/hw/i40iw/i40iw_cm.c b/drivers/infiniband/hw/i40iw/i40iw_cm.c
+index 206cfb0016f8..1c6aa0efd2b6 100644
+--- a/drivers/infiniband/hw/i40iw/i40iw_cm.c
++++ b/drivers/infiniband/hw/i40iw/i40iw_cm.c
+@@ -3237,7 +3237,7 @@ void i40iw_receive_ilq(struct i40iw_sc_vsi *vsi, struct i40iw_puda_buf *rbuf)
+  * core
+  * @iwdev: iwarp device structure
+  */
+-void i40iw_setup_cm_core(struct i40iw_device *iwdev)
++int i40iw_setup_cm_core(struct i40iw_device *iwdev)
+ {
+ 	struct i40iw_cm_core *cm_core = &iwdev->cm_core;
+ 
+@@ -3256,9 +3256,19 @@ void i40iw_setup_cm_core(struct i40iw_device *iwdev)
+ 
+ 	cm_core->event_wq = alloc_ordered_workqueue("iwewq",
+ 						    WQ_MEM_RECLAIM);
++	if (!cm_core->event_wq)
++		goto error;
+ 
+ 	cm_core->disconn_wq = alloc_ordered_workqueue("iwdwq",
+ 						      WQ_MEM_RECLAIM);
++	if (!cm_core->disconn_wq)
++		goto error;
++
++	return 0;
++error:
++	i40iw_cleanup_cm_core(&iwdev->cm_core);
++
++	return -ENOMEM;
+ }
+ 
+ /**
+@@ -3278,8 +3288,10 @@ void i40iw_cleanup_cm_core(struct i40iw_cm_core *cm_core)
+ 		del_timer_sync(&cm_core->tcp_timer);
+ 	spin_unlock_irqrestore(&cm_core->ht_lock, flags);
+ 
+-	destroy_workqueue(cm_core->event_wq);
+-	destroy_workqueue(cm_core->disconn_wq);
++	if (cm_core->event_wq)
++		destroy_workqueue(cm_core->event_wq);
++	if (cm_core->disconn_wq)
++		destroy_workqueue(cm_core->disconn_wq);
+ }
+ 
+ /**
+diff --git a/drivers/infiniband/hw/i40iw/i40iw_main.c b/drivers/infiniband/hw/i40iw/i40iw_main.c
+index 68095f00d08f..10932baee279 100644
+--- a/drivers/infiniband/hw/i40iw/i40iw_main.c
++++ b/drivers/infiniband/hw/i40iw/i40iw_main.c
+@@ -1641,7 +1641,10 @@ static int i40iw_open(struct i40e_info *ldev, struct i40e_client *client)
+ 	iwdev = &hdl->device;
+ 	iwdev->hdl = hdl;
+ 	dev = &iwdev->sc_dev;
+-	i40iw_setup_cm_core(iwdev);
++	if (i40iw_setup_cm_core(iwdev)) {
++		kfree(iwdev->hdl);
++		return -ENOMEM;
++	}
+ 
+ 	dev->back_dev = (void *)iwdev;
+ 	iwdev->ldev = &hdl->ldev;

commit 766460852cfaeca4042e5f3aeb9616b3689147bc
+Author: Kangjie Lu 
+Date:   Mon Mar 25 15:29:22 2019 -0500
+
+    x86/platform/uv: Fix missing checks of kcalloc() return values
+    
+    Handle potential errors returned from kcalloc().
+    
+     [ bp: rewrite commit message. ]
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Borislav Petkov 
+    Cc: Andrew Banman 
+    Cc: Andy Shevchenko 
+    Cc: Colin Ian King 
+    Cc: Darren Hart 
+    Cc: "Gustavo A. R. Silva" 
+    Cc: "H. Peter Anvin" 
+    Cc: Ingo Molnar 
+    Cc: Kees Cook 
+    Cc: Mike Travis 
+    Cc: Nicolai Stange 
+    Cc: pakki001@umn.edu
+    Cc: platform-driver-x86@vger.kernel.org
+    Cc: Thomas Gleixner 
+    Cc: Varsha Rao 
+    Cc: x86-ml 
+    Link: https://lkml.kernel.org/r/20190325202924.4624-1-kjlu@umn.edu
+
+diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c
+index 2c53b0f19329..1297e185b8c8 100644
+--- a/arch/x86/platform/uv/tlb_uv.c
++++ b/arch/x86/platform/uv/tlb_uv.c
+@@ -2133,14 +2133,19 @@ static int __init summarize_uvhub_sockets(int nuvhubs,
+  */
+ static int __init init_per_cpu(int nuvhubs, int base_part_pnode)
+ {
+-	unsigned char *uvhub_mask;
+ 	struct uvhub_desc *uvhub_descs;
++	unsigned char *uvhub_mask = NULL;
+ 
+ 	if (is_uv3_hub() || is_uv2_hub() || is_uv1_hub())
+ 		timeout_us = calculate_destination_timeout();
+ 
+ 	uvhub_descs = kcalloc(nuvhubs, sizeof(struct uvhub_desc), GFP_KERNEL);
++	if (!uvhub_descs)
++		goto fail;
++
+ 	uvhub_mask = kzalloc((nuvhubs+7)/8, GFP_KERNEL);
++	if (!uvhub_mask)
++		goto fail;
+ 
+ 	if (get_cpu_topology(base_part_pnode, uvhub_descs, uvhub_mask))
+ 		goto fail;

commit 41f00e6e9e55546390031996b773e7f3c1d95928
+Author: Aditya Pakki 
+Date:   Wed Mar 20 10:27:11 2019 -0500
+
+    usb: usb251xb: fix to avoid potential NULL pointer dereference
+    
+    of_match_device in usb251xb_probe can fail and returns a NULL pointer.
+    The patch avoids a potential NULL pointer dereference in this scenario.
+    
+    Signed-off-by: Aditya Pakki 
+    Reviewed-by: Richard Leitner 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/misc/usb251xb.c b/drivers/usb/misc/usb251xb.c
+index 2c8e2cad7e10..04684849d683 100644
+--- a/drivers/usb/misc/usb251xb.c
++++ b/drivers/usb/misc/usb251xb.c
+@@ -612,7 +612,7 @@ static int usb251xb_probe(struct usb251xb *hub)
+ 							   dev);
+ 	int err;
+ 
+-	if (np) {
++	if (np && of_id) {
+ 		err = usb251xb_get_ofdata(hub,
+ 					  (struct usb251xb_data *)of_id->data);
+ 		if (err) {

commit 3de3dbe7c13210171ba8411e36b409a2c29c7415
+Author: Kangjie Lu 
+Date:   Tue Mar 19 12:34:06 2019 -0500
+
+    usb: u132-hcd: fix potential NULL pointer dereference
+    
+    In case create_singlethread_workqueue fails, the fix notifies
+    callers the error to avoid potential NULL pointer dereferences.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
+index 934584f0a20a..e29165027e8b 100644
+--- a/drivers/usb/host/u132-hcd.c
++++ b/drivers/usb/host/u132-hcd.c
+@@ -3203,6 +3203,8 @@ static int __init u132_hcd_init(void)
+ 		return -ENODEV;
+ 	printk(KERN_INFO "driver %s\n", hcd_name);
+ 	workqueue = create_singlethread_workqueue("u132");
++	if (!workqueue)
++		return -ENOMEM;
+ 	retval = platform_driver_register(&u132_platform_driver);
+ 	return retval;
+ }

commit 1a137b47ce6bd4f4b14662d2f5ace913ea7ffbf8
+Author: Kangjie Lu 
+Date:   Sun Mar 24 22:08:28 2019 -0500
+
+    usb: sierra: fix a missing check of device_create_file
+    
+    device_create_file() could fail and return an error code. The fix
+    captures the error and returns the error code upstream in case it
+    indeed failed.
+    
+    Signed-off-by: Kangjie Lu 
+    Acked-by: Alan Stern 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/sierra_ms.c b/drivers/usb/storage/sierra_ms.c
+index 6ac60abd2e15..e605cbc3d8bf 100644
+--- a/drivers/usb/storage/sierra_ms.c
++++ b/drivers/usb/storage/sierra_ms.c
+@@ -194,8 +194,6 @@ int sierra_ms_init(struct us_data *us)
+ 		kfree(swocInfo);
+ 	}
+ complete:
+-	result = device_create_file(&us->pusb_intf->dev, &dev_attr_truinst);
+-
+-	return 0;
++	return device_create_file(&us->pusb_intf->dev, &dev_attr_truinst);
+ }
+ 

commit fba1bdd2a9a93f3e2181ec1936a3c2f6b37e7ed6
+Author: Kangjie Lu 
+Date:   Thu Mar 14 01:30:59 2019 -0500
+
+    scsi: qla4xxx: fix a potential NULL pointer dereference
+    
+    In case iscsi_lookup_endpoint fails, the fix returns -EINVAL to avoid NULL
+    pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Acked-by: Manish Rangankar 
+    Reviewed-by: Mukesh Ojha 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index 16a18d5d856f..6e4f4931ae17 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -3203,6 +3203,8 @@ static int qla4xxx_conn_bind(struct iscsi_cls_session *cls_session,
+ 	if (iscsi_conn_bind(cls_session, cls_conn, is_leading))
+ 		return -EINVAL;
+ 	ep = iscsi_lookup_endpoint(transport_fd);
++	if (!ep)
++		return -EINVAL;
+ 	conn = cls_conn->dd_data;
+ 	qla_conn = conn->dd_data;
+ 	qla_conn->qla_ep = ep->dd_data;

commit 78540a259b050480d20354efaf1055c233728b3b
+Author: Aditya Pakki 
+Date:   Fri Mar 22 17:00:29 2019 -0500
+
+    ASoC: sirf-audio: Remove redundant of_match_node call
+    
+    Unlike other drivers probe method, of_match_node return value
+    is not used or checked. This patch removes the redundant code.
+    
+    Signed-off-by: Aditya Pakki 
+    Reviewed-by: Steven Price 
+    Signed-off-by: Mark Brown 
+
+diff --git a/sound/soc/codecs/sirf-audio-codec.c b/sound/soc/codecs/sirf-audio-codec.c
+index e424499a8450..e0af21050078 100644
+--- a/sound/soc/codecs/sirf-audio-codec.c
++++ b/sound/soc/codecs/sirf-audio-codec.c
+@@ -461,9 +461,6 @@ static int sirf_audio_codec_driver_probe(struct platform_device *pdev)
+ 	struct sirf_audio_codec *sirf_audio_codec;
+ 	void __iomem *base;
+ 	struct resource *mem_res;
+-	const struct of_device_id *match;
+-
+-	match = of_match_node(sirf_audio_codec_of_match, pdev->dev.of_node);
+ 
+ 	sirf_audio_codec = devm_kzalloc(&pdev->dev,
+ 		sizeof(struct sirf_audio_codec), GFP_KERNEL);

commit 208c6e8cff1b96eca401adbd544ac00133df9e90
+Author: Kangjie Lu 
+Date:   Fri Mar 8 22:36:27 2019 -0600
+
+    drm: vkms: check status of alloc_ordered_workqueue
+    
+    alloc_ordered_workqueue may fail and return NULL.
+    The fix returns ENOMEM when it fails to avoid potential NULL
+    pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Daniel Vetter 
+    Link: https://patchwork.freedesktop.org/patch/msgid/20190309043628.6078-1-kjlu@umn.edu
+
+diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c
+index 8a9aeb0a9ea8..bb66dbcd5e3f 100644
+--- a/drivers/gpu/drm/vkms/vkms_crtc.c
++++ b/drivers/gpu/drm/vkms/vkms_crtc.c
+@@ -219,6 +219,8 @@ int vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
+ 	spin_lock_init(&vkms_out->state_lock);
+ 
+ 	vkms_out->crc_workq = alloc_ordered_workqueue("vkms_crc_workq", 0);
++	if (!vkms_out->crc_workq)
++		return -ENOMEM;
+ 
+ 	return ret;
+ }

commit 6cf4511e9729c00a7306cf94085f9cc3c52ee723
+Author: Kangjie Lu 
+Date:   Sun Mar 24 18:10:02 2019 -0500
+
+    gpio: aspeed: fix a potential NULL pointer dereference
+    
+    In case devm_kzalloc, the patch returns ENOMEM to avoid potential
+    NULL pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Reviewed-by: Andrew Jeffery 
+    Signed-off-by: Bartosz Golaszewski 
+
+diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
+index 854bce4fb9e7..217507002dbc 100644
+--- a/drivers/gpio/gpio-aspeed.c
++++ b/drivers/gpio/gpio-aspeed.c
+@@ -1224,6 +1224,8 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
+ 
+ 	gpio->offset_timer =
+ 		devm_kzalloc(&pdev->dev, gpio->chip.ngpio, GFP_KERNEL);
++	if (!gpio->offset_timer)
++		return -ENOMEM;
+ 
+ 	return aspeed_gpio_setup_irqs(gpio, pdev);
+ }

commit 55c1fc0af29a6c1b92f217b7eb7581a882e0c07c
+Author: Kangjie Lu 
+Date:   Tue Mar 12 03:20:34 2019 -0500
+
+    libnvdimm/namespace: Fix a potential NULL pointer dereference
+    
+    In case kmemdup fails, the fix goes to blk_err to avoid NULL
+    pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Dan Williams 
+
+diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
+index 7849bf1812c4..f293556cbbf6 100644
+--- a/drivers/nvdimm/namespace_devs.c
++++ b/drivers/nvdimm/namespace_devs.c
+@@ -2249,9 +2249,12 @@ static struct device *create_namespace_blk(struct nd_region *nd_region,
+ 	if (!nsblk->uuid)
+ 		goto blk_err;
+ 	memcpy(name, nd_label->name, NSLABEL_NAME_LEN);
+-	if (name[0])
++	if (name[0]) {
+ 		nsblk->alt_name = kmemdup(name, NSLABEL_NAME_LEN,
+ 				GFP_KERNEL);
++		if (!nsblk->alt_name)
++			goto blk_err;
++	}
+ 	res = nsblk_add_resource(nd_region, ndd, nsblk,
+ 			__le64_to_cpu(nd_label->dpa));
+ 	if (!res)

commit 7ecced0934e574b528a1ba6c237731e682216a74
+Author: Kangjie Lu 
+Date:   Fri Mar 8 22:07:57 2019 -0600
+
+    gpio: exar: add a check for the return value of ida_simple_get fails
+    
+    ida_simple_get may fail and return a negative error number.
+    The fix checks its return value; if it fails, go to err_destroy.
+    
+    Cc: 
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Bartosz Golaszewski 
+
+diff --git a/drivers/gpio/gpio-exar.c b/drivers/gpio/gpio-exar.c
+index 0ecd2369c2ca..a09d2f9ebacc 100644
+--- a/drivers/gpio/gpio-exar.c
++++ b/drivers/gpio/gpio-exar.c
+@@ -148,6 +148,8 @@ static int gpio_exar_probe(struct platform_device *pdev)
+ 	mutex_init(&exar_gpio->lock);
+ 
+ 	index = ida_simple_get(&ida_index, 0, 0, GFP_KERNEL);
++	if (index < 0)
++		goto err_destroy;
+ 
+ 	sprintf(exar_gpio->name, "exar_gpio%d", index);
+ 	exar_gpio->gpio_chip.label = exar_gpio->name;

commit 48f40b96de2c790eac6114e3e879a48fe9f89349
+Author: Aditya Pakki 
+Date:   Wed Mar 20 11:47:20 2019 -0500
+
+    thunderbolt: xdomain: Fix to check return value of kmemdup
+    
+    kmemdup can fail and return a NULL pointer. The patch modifies the
+    signature of tb_xdp_schedule_request and passes the failure error upstream.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Mika Westerberg 
+
+diff --git a/drivers/thunderbolt/xdomain.c b/drivers/thunderbolt/xdomain.c
+index e0642dcb8b9b..e2fc4543142d 100644
+--- a/drivers/thunderbolt/xdomain.c
++++ b/drivers/thunderbolt/xdomain.c
+@@ -526,7 +526,7 @@ static void tb_xdp_handle_request(struct work_struct *work)
+ 	kfree(xw);
+ }
+ 
+-static void
++static bool
+ tb_xdp_schedule_request(struct tb *tb, const struct tb_xdp_header *hdr,
+ 			size_t size)
+ {
+@@ -534,13 +534,18 @@ tb_xdp_schedule_request(struct tb *tb, const struct tb_xdp_header *hdr,
+ 
+ 	xw = kmalloc(sizeof(*xw), GFP_KERNEL);
+ 	if (!xw)
+-		return;
++		return false;
+ 
+ 	INIT_WORK(&xw->work, tb_xdp_handle_request);
+ 	xw->pkg = kmemdup(hdr, size, GFP_KERNEL);
++	if (!xw->pkg) {
++		kfree(xw);
++		return false;
++	}
+ 	xw->tb = tb;
+ 
+ 	queue_work(tb->wq, &xw->work);
++	return true;
+ }
+ 
+ /**
+@@ -1422,10 +1427,8 @@ bool tb_xdomain_handle_request(struct tb *tb, enum tb_cfg_pkg_type type,
+ 	 * handlers in turn.
+ 	 */
+ 	if (uuid_equal(&hdr->uuid, &tb_xdp_uuid)) {
+-		if (type == TB_CFG_PKG_XDOMAIN_REQ) {
+-			tb_xdp_schedule_request(tb, hdr, size);
+-			return true;
+-		}
++		if (type == TB_CFG_PKG_XDOMAIN_REQ)
++			return tb_xdp_schedule_request(tb, hdr, size);
+ 		return false;
+ 	}
+ 

commit 9aabb68568b473bf2f0b179d053b403961e42e4d
+Author: Aditya Pakki 
+Date:   Wed Mar 20 11:34:09 2019 -0500
+
+    thunderbolt: Fix to check return value of ida_simple_get
+    
+    In enumerate_services, ida_simple_get on failure can return an error and
+    leaks memory. The patch ensures that the dev_set_name is set on non
+    failure cases, and releases memory during failure.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Mika Westerberg 
+
+diff --git a/drivers/thunderbolt/xdomain.c b/drivers/thunderbolt/xdomain.c
+index e27dd8beb94b..e0642dcb8b9b 100644
+--- a/drivers/thunderbolt/xdomain.c
++++ b/drivers/thunderbolt/xdomain.c
+@@ -740,6 +740,7 @@ static void enumerate_services(struct tb_xdomain *xd)
+ 	struct tb_service *svc;
+ 	struct tb_property *p;
+ 	struct device *dev;
++	int id;
+ 
+ 	/*
+ 	 * First remove all services that are not available anymore in
+@@ -768,7 +769,12 @@ static void enumerate_services(struct tb_xdomain *xd)
+ 			break;
+ 		}
+ 
+-		svc->id = ida_simple_get(&xd->service_ids, 0, 0, GFP_KERNEL);
++		id = ida_simple_get(&xd->service_ids, 0, 0, GFP_KERNEL);
++		if (id < 0) {
++			kfree(svc);
++			break;
++		}
++		svc->id = id;
+ 		svc->dev.bus = &tb_bus_type;
+ 		svc->dev.type = &tb_service_type;
+ 		svc->dev.parent = &xd->dev;

commit 2cc12751cf464a722ff57b54d17d30c84553f9c0
+Author: Aditya Pakki 
+Date:   Wed Mar 20 10:57:54 2019 -0500
+
+    thunderbolt: Fix to check for kmemdup failure
+    
+    Memory allocated via kmemdup might fail and return a NULL pointer.
+    This patch adds a check on the return value of kmemdup and passes the
+    error upstream.
+    
+    Signed-off-by: Aditya Pakki 
+    Reviewed-by: Mukesh Ojha 
+    Signed-off-by: Mika Westerberg 
+
+diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
+index cd96994dc094..504365d46827 100644
+--- a/drivers/thunderbolt/switch.c
++++ b/drivers/thunderbolt/switch.c
+@@ -1294,13 +1294,14 @@ int tb_switch_configure(struct tb_switch *sw)
+ 	return tb_plug_events_active(sw, true);
+ }
+ 
+-static void tb_switch_set_uuid(struct tb_switch *sw)
++static int tb_switch_set_uuid(struct tb_switch *sw)
+ {
+ 	u32 uuid[4];
+-	int cap;
++	int cap, ret;
+ 
++	ret = 0;
+ 	if (sw->uuid)
+-		return;
++		return ret;
+ 
+ 	/*
+ 	 * The newer controllers include fused UUID as part of link
+@@ -1308,7 +1309,9 @@ static void tb_switch_set_uuid(struct tb_switch *sw)
+ 	 */
+ 	cap = tb_switch_find_vse_cap(sw, TB_VSE_CAP_LINK_CONTROLLER);
+ 	if (cap > 0) {
+-		tb_sw_read(sw, uuid, TB_CFG_SWITCH, cap + 3, 4);
++		ret = tb_sw_read(sw, uuid, TB_CFG_SWITCH, cap + 3, 4);
++		if (ret)
++			return ret;
+ 	} else {
+ 		/*
+ 		 * ICM generates UUID based on UID and fills the upper
+@@ -1323,6 +1326,9 @@ static void tb_switch_set_uuid(struct tb_switch *sw)
+ 	}
+ 
+ 	sw->uuid = kmemdup(uuid, sizeof(uuid), GFP_KERNEL);
++	if (!sw->uuid)
++		ret = -ENOMEM;
++	return ret;
+ }
+ 
+ static int tb_switch_add_dma_port(struct tb_switch *sw)
+@@ -1372,7 +1378,9 @@ static int tb_switch_add_dma_port(struct tb_switch *sw)
+ 
+ 	if (status) {
+ 		tb_sw_info(sw, "switch flash authentication failed\n");
+-		tb_switch_set_uuid(sw);
++		ret = tb_switch_set_uuid(sw);
++		if (ret)
++			return ret;
+ 		nvm_set_auth_status(sw, status);
+ 	}
+ 
+@@ -1422,7 +1430,9 @@ int tb_switch_add(struct tb_switch *sw)
+ 		}
+ 		tb_sw_dbg(sw, "uid: %#llx\n", sw->uid);
+ 
+-		tb_switch_set_uuid(sw);
++		ret = tb_switch_set_uuid(sw);
++		if (ret)
++			return ret;
+ 
+ 		for (i = 0; i <= sw->config.max_port_number; i++) {
+ 			if (sw->ports[i].disabled) {

commit 534c89c22e26b183d838294f0937ee092c82ad3a
+Author: Kangjie Lu 
+Date:   Thu Mar 14 00:46:51 2019 -0500
+
+    x86/hyperv: Prevent potential NULL pointer dereference
+    
+    The page allocation in hv_cpu_init() can fail, but the code does not
+    have a check for that.
+    
+    Add a check and return -ENOMEM when the allocation fails.
+    
+    [ tglx: Massaged changelog ]
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Thomas Gleixner 
+    Reviewed-by: Mukesh Ojha 
+    Acked-by: "K. Y. Srinivasan" 
+    Cc: pakki001@umn.edu
+    Cc: Haiyang Zhang 
+    Cc: Stephen Hemminger 
+    Cc: Sasha Levin 
+    Cc: Borislav Petkov 
+    Cc: "H. Peter Anvin" 
+    Cc: linux-hyperv@vger.kernel.org
+    Link: https://lkml.kernel.org/r/20190314054651.1315-1-kjlu@umn.edu
+
+diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
+index 6461a16b4559..e4ba467a9fc6 100644
+--- a/arch/x86/hyperv/hv_init.c
++++ b/arch/x86/hyperv/hv_init.c
+@@ -103,9 +103,13 @@ static int hv_cpu_init(unsigned int cpu)
+ 	u64 msr_vp_index;
+ 	struct hv_vp_assist_page **hvp = &hv_vp_assist_page[smp_processor_id()];
+ 	void **input_arg;
++	struct page *pg;
+ 
+ 	input_arg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
+-	*input_arg = page_address(alloc_page(GFP_KERNEL));
++	pg = alloc_page(GFP_KERNEL);
++	if (unlikely(!pg))
++		return -ENOMEM;
++	*input_arg = page_address(pg);
+ 
+ 	hv_get_vp_index(msr_vp_index);
+ 

commit 2e84f116afca3719c9d0a1a78b47b48f75fd5724
+Author: Aditya Pakki 
+Date:   Mon Mar 18 21:19:56 2019 -0500
+
+    x86/hpet: Prevent potential NULL pointer dereference
+    
+    hpet_virt_address may be NULL when ioremap_nocache fail, but the code lacks
+    a check.
+    
+    Add a check to prevent NULL pointer dereference.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Thomas Gleixner 
+    Cc: kjlu@umn.edu
+    Cc: Borislav Petkov 
+    Cc: "H. Peter Anvin" 
+    Cc: Kees Cook 
+    Cc: Joe Perches 
+    Cc: Nicolai Stange 
+    Cc: Roland Dreier 
+    Link: https://lkml.kernel.org/r/20190319021958.17275-1-pakki001@umn.edu
+
+diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
+index dfd3aca82c61..fb32925a2e62 100644
+--- a/arch/x86/kernel/hpet.c
++++ b/arch/x86/kernel/hpet.c
+@@ -905,6 +905,8 @@ int __init hpet_enable(void)
+ 		return 0;
+ 
+ 	hpet_set_mapping();
++	if (!hpet_virt_address)
++		return 0;
+ 
+ 	/*
+ 	 * Read the period and check for a sane value:

commit 6a8ca24590a2136921439b376c926c11a6effc0e
+Author: Aditya Pakki 
+Date:   Wed Mar 20 10:42:32 2019 -0500
+
+    staging: rtlwifi: Fix potential NULL pointer dereference of kzalloc
+    
+    phydm.internal is allocated using kzalloc which is used multiple
+    times without a check for NULL pointer. This patch avoids such a
+    scenario by returning 0, consistent with the failure case.
+    
+    Signed-off-by: Aditya Pakki 
+    Reviewed-by: Mukesh Ojha 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtlwifi/phydm/rtl_phydm.c b/drivers/staging/rtlwifi/phydm/rtl_phydm.c
+index 9930ed954abb..4cc77b2016e1 100644
+--- a/drivers/staging/rtlwifi/phydm/rtl_phydm.c
++++ b/drivers/staging/rtlwifi/phydm/rtl_phydm.c
+@@ -180,6 +180,8 @@ static int rtl_phydm_init_priv(struct rtl_priv *rtlpriv,
+ 
+ 	rtlpriv->phydm.internal =
+ 		kzalloc(sizeof(struct phy_dm_struct), GFP_KERNEL);
++	if (!rtlpriv->phydm.internal)
++		return 0;
+ 
+ 	_rtl_phydm_init_com_info(rtlpriv, ic, params);
+ 

commit d70d70aec9632679dd00dcc1b1e8b2517e2c7da0
+Author: Aditya Pakki 
+Date:   Wed Mar 20 12:02:49 2019 -0500
+
+    staging: rtlwifi: rtl8822b: fix to avoid potential NULL pointer dereference
+    
+    skb allocated via dev_alloc_skb can fail and return a NULL pointer.
+    This patch avoids such a scenario and returns, consistent with other
+    invocations.
+    
+    Signed-off-by: Aditya Pakki 
+    Reviewed-by: Mukesh Ojha 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtlwifi/rtl8822be/fw.c b/drivers/staging/rtlwifi/rtl8822be/fw.c
+index f061dd1382aa..cf6b7a80b753 100644
+--- a/drivers/staging/rtlwifi/rtl8822be/fw.c
++++ b/drivers/staging/rtlwifi/rtl8822be/fw.c
+@@ -743,6 +743,8 @@ void rtl8822be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
+ 		      u1_rsvd_page_loc, 3);
+ 
+ 	skb = dev_alloc_skb(totalpacketlen);
++	if (!skb)
++		return;
+ 	memcpy((u8 *)skb_put(skb, totalpacketlen), &reserved_page_packet,
+ 	       totalpacketlen);
+ 

commit 7671ce0d92933762f469266daf43bd34d422d58c
+Author: Aditya Pakki 
+Date:   Wed Mar 20 12:21:35 2019 -0500
+
+    staging: rtl8188eu: Fix potential NULL pointer dereference of kcalloc
+    
+    hwxmits is allocated via kcalloc and not checked for failure before its
+    dereference. The patch fixes this problem by returning error upstream
+    in rtl8723bs, rtl8188eu.
+    
+    Signed-off-by: Aditya Pakki 
+    Acked-by: Mukesh Ojha 
+    Reviewed-by: Hans de Goede 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c
+index 1723a47a96b4..952f2ab51347 100644
+--- a/drivers/staging/rtl8188eu/core/rtw_xmit.c
++++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c
+@@ -174,7 +174,9 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
+ 
+ 	pxmitpriv->free_xmit_extbuf_cnt = num_xmit_extbuf;
+ 
+-	rtw_alloc_hwxmits(padapter);
++	res = rtw_alloc_hwxmits(padapter);
++	if (res == _FAIL)
++		goto exit;
+ 	rtw_init_hwxmits(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
+ 
+ 	for (i = 0; i < 4; i++)
+@@ -1503,7 +1505,7 @@ s32 rtw_xmit_classifier(struct adapter *padapter, struct xmit_frame *pxmitframe)
+ 	return res;
+ }
+ 
+-void rtw_alloc_hwxmits(struct adapter *padapter)
++s32 rtw_alloc_hwxmits(struct adapter *padapter)
+ {
+ 	struct hw_xmit *hwxmits;
+ 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+@@ -1512,6 +1514,8 @@ void rtw_alloc_hwxmits(struct adapter *padapter)
+ 
+ 	pxmitpriv->hwxmits = kcalloc(pxmitpriv->hwxmit_entry,
+ 				     sizeof(struct hw_xmit), GFP_KERNEL);
++	if (!pxmitpriv->hwxmits)
++		return _FAIL;
+ 
+ 	hwxmits = pxmitpriv->hwxmits;
+ 
+@@ -1519,6 +1523,7 @@ void rtw_alloc_hwxmits(struct adapter *padapter)
+ 	hwxmits[1] .sta_queue = &pxmitpriv->vi_pending;
+ 	hwxmits[2] .sta_queue = &pxmitpriv->be_pending;
+ 	hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
++	return _SUCCESS;
+ }
+ 
+ void rtw_free_hwxmits(struct adapter *padapter)
+diff --git a/drivers/staging/rtl8188eu/include/rtw_xmit.h b/drivers/staging/rtl8188eu/include/rtw_xmit.h
+index 788f59c74ea1..ba7e15fbde72 100644
+--- a/drivers/staging/rtl8188eu/include/rtw_xmit.h
++++ b/drivers/staging/rtl8188eu/include/rtw_xmit.h
+@@ -336,7 +336,7 @@ s32 rtw_txframes_sta_ac_pending(struct adapter *padapter,
+ void rtw_init_hwxmits(struct hw_xmit *phwxmit, int entry);
+ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter);
+ void _rtw_free_xmit_priv(struct xmit_priv *pxmitpriv);
+-void rtw_alloc_hwxmits(struct adapter *padapter);
++s32 rtw_alloc_hwxmits(struct adapter *padapter);
+ void rtw_free_hwxmits(struct adapter *padapter);
+ s32 rtw_xmit(struct adapter *padapter, struct sk_buff **pkt);
+ 
+diff --git a/drivers/staging/rtl8723bs/core/rtw_xmit.c b/drivers/staging/rtl8723bs/core/rtw_xmit.c
+index 094d61bcb469..b87f13a0b563 100644
+--- a/drivers/staging/rtl8723bs/core/rtw_xmit.c
++++ b/drivers/staging/rtl8723bs/core/rtw_xmit.c
+@@ -260,7 +260,9 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
+ 		}
+ 	}
+ 
+-	rtw_alloc_hwxmits(padapter);
++	res = rtw_alloc_hwxmits(padapter);
++	if (res == _FAIL)
++		goto exit;
+ 	rtw_init_hwxmits(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
+ 
+ 	for (i = 0; i < 4; i++) {
+@@ -2144,7 +2146,7 @@ s32 rtw_xmit_classifier(struct adapter *padapter, struct xmit_frame *pxmitframe)
+ 	return res;
+ }
+ 
+-void rtw_alloc_hwxmits(struct adapter *padapter)
++s32 rtw_alloc_hwxmits(struct adapter *padapter)
+ {
+ 	struct hw_xmit *hwxmits;
+ 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+@@ -2155,10 +2157,8 @@ void rtw_alloc_hwxmits(struct adapter *padapter)
+ 
+ 	pxmitpriv->hwxmits = rtw_zmalloc(sizeof(struct hw_xmit) * pxmitpriv->hwxmit_entry);
+ 
+-	if (pxmitpriv->hwxmits == NULL) {
+-		DBG_871X("alloc hwxmits fail!...\n");
+-		return;
+-	}
++	if (!pxmitpriv->hwxmits)
++		return _FAIL;
+ 
+ 	hwxmits = pxmitpriv->hwxmits;
+ 
+@@ -2204,7 +2204,7 @@ void rtw_alloc_hwxmits(struct adapter *padapter)
+ 
+ 	}
+ 
+-
++	return _SUCCESS;
+ }
+ 
+ void rtw_free_hwxmits(struct adapter *padapter)
+diff --git a/drivers/staging/rtl8723bs/include/rtw_xmit.h b/drivers/staging/rtl8723bs/include/rtw_xmit.h
+index 1b38b9182b31..37f42b2f22f1 100644
+--- a/drivers/staging/rtl8723bs/include/rtw_xmit.h
++++ b/drivers/staging/rtl8723bs/include/rtw_xmit.h
+@@ -487,7 +487,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter);
+ void _rtw_free_xmit_priv (struct xmit_priv *pxmitpriv);
+ 
+ 
+-void rtw_alloc_hwxmits(struct adapter *padapter);
++s32 rtw_alloc_hwxmits(struct adapter *padapter);
+ void rtw_free_hwxmits(struct adapter *padapter);
+ 
+ 

commit e4dfdd5804cce1255f99c5dd033526a18135a616
+Author: Kangjie Lu 
+Date:   Thu Mar 14 01:55:31 2019 -0500
+
+    thunderbolt: Fix a missing check of kmemdup
+    
+    kmemdup may fail and return NULL. The fix adds a check and returns
+    NULL in case it fails to avoid NULL pointer dereferecen.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Mika Westerberg 
+
+diff --git a/drivers/thunderbolt/property.c b/drivers/thunderbolt/property.c
+index ee76449524a3..841314deb446 100644
+--- a/drivers/thunderbolt/property.c
++++ b/drivers/thunderbolt/property.c
+@@ -176,6 +176,10 @@ static struct tb_property_dir *__tb_property_parse_dir(const u32 *block,
+ 	} else {
+ 		dir->uuid = kmemdup(&block[dir_offset], sizeof(*dir->uuid),
+ 				    GFP_KERNEL);
++		if (!dir->uuid) {
++			tb_property_free_dir(dir);
++			return NULL;
++		}
+ 		content_offset = dir_offset + 4;
+ 		content_len = dir_len - 4; /* Length includes UUID */
+ 	}

commit 106204b56f60abf1bead7dceb88f2be3e34433da
+Author: Kangjie Lu 
+Date:   Tue Mar 12 03:33:28 2019 -0500
+
+    thunderbolt: property: Fix a NULL pointer dereference
+    
+    In case kzalloc fails, the fix releases resources and returns
+    -ENOMEM to avoid the NULL pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Mika Westerberg 
+
+diff --git a/drivers/thunderbolt/property.c b/drivers/thunderbolt/property.c
+index b2f0d6386cee..ee76449524a3 100644
+--- a/drivers/thunderbolt/property.c
++++ b/drivers/thunderbolt/property.c
+@@ -548,6 +548,11 @@ int tb_property_add_data(struct tb_property_dir *parent, const char *key,
+ 
+ 	property->length = size / 4;
+ 	property->value.data = kzalloc(size, GFP_KERNEL);
++	if (!property->value.data) {
++		kfree(property);
++		return -ENOMEM;
++	}
++
+ 	memcpy(property->value.data, buf, buflen);
+ 
+ 	list_add_tail(&property->list, &parent->properties);

commit d7737d4257459ca8921ff911c88937be1a11ea9d
+Author: Aditya Pakki 
+Date:   Mon Mar 18 22:19:44 2019 -0500
+
+    nfc: Fix to check for kmemdup failure
+    
+    In case of kmemdup failure while setting the service name the patch
+    returns -ENOMEM upstream for processing.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c
+index ae296273ce3d..17dcd0b5eb32 100644
+--- a/net/nfc/llcp_sock.c
++++ b/net/nfc/llcp_sock.c
+@@ -726,6 +726,10 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
+ 	llcp_sock->service_name = kmemdup(addr->service_name,
+ 					  llcp_sock->service_name_len,
+ 					  GFP_KERNEL);
++	if (!llcp_sock->service_name) {
++		ret = -ENOMEM;
++		goto sock_llcp_release;
++	}
+ 
+ 	nfc_llcp_sock_link(&local->connecting_sockets, sk);
+ 
+@@ -745,10 +749,11 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
+ 	return ret;
+ 
+ sock_unlink:
+-	nfc_llcp_put_ssap(local, llcp_sock->ssap);
+-
+ 	nfc_llcp_sock_unlink(&local->connecting_sockets, sk);
+ 
++sock_llcp_release:
++	nfc_llcp_put_ssap(local, llcp_sock->ssap);
++
+ put_dev:
+ 	nfc_put_device(dev);
+ 

commit 0ab34a08812a3334350dbaf69a018ee0ab3d2ddd
+Author: Kangjie Lu 
+Date:   Thu Dec 20 23:54:03 2018 -0500
+
+    media: si2165: fix a missing check of return value
+    
+    si2165_readreg8() may fail. Looking into si2165_readreg8(), we will find
+    that "val_tmp" will be an uninitialized value when regmap_read() fails.
+    "val_tmp" is then assigned to "val". So if si2165_readreg8() fails,
+    "val" will be a random value. Further use will lead to undefined
+    behaviors. The fix checks if si2165_readreg8() fails, and if so, returns
+    its error code upstream.
+    
+    Signed-off-by: Kangjie Lu 
+    Reviewed-by: Matthias Schwarzott 
+    Tested-by: Matthias Schwarzott 
+    Signed-off-by: Sean Young 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb-frontends/si2165.c b/drivers/media/dvb-frontends/si2165.c
+index feacd8da421d..d55d8f169dca 100644
+--- a/drivers/media/dvb-frontends/si2165.c
++++ b/drivers/media/dvb-frontends/si2165.c
+@@ -275,18 +275,20 @@ static u32 si2165_get_fe_clk(struct si2165_state *state)
+ 
+ static int si2165_wait_init_done(struct si2165_state *state)
+ {
+-	int ret = -EINVAL;
++	int ret;
+ 	u8 val = 0;
+ 	int i;
+ 
+ 	for (i = 0; i < 3; ++i) {
+-		si2165_readreg8(state, REG_INIT_DONE, &val);
++		ret = si2165_readreg8(state, REG_INIT_DONE, &val);
++		if (ret < 0)
++			return ret;
+ 		if (val == 0x01)
+ 			return 0;
+ 		usleep_range(1000, 50000);
+ 	}
+ 	dev_err(&state->client->dev, "init_done was not set\n");
+-	return ret;
++	return -EINVAL;
+ }
+ 
+ static int si2165_upload_firmware_block(struct si2165_state *state,

commit 63a06181d7ce169d09843645c50fea1901bc9f0a
+Author: Kangjie Lu 
+Date:   Fri Mar 15 02:11:56 2019 -0500
+
+    scsi: ufs: fix a missing check of devm_reset_control_get
+    
+    devm_reset_control_get could fail, so the fix checks its return value and
+    passes the error code upstream in case it fails.
+    
+    Signed-off-by: Kangjie Lu 
+    Acked-by: Avri Altman 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/scsi/ufs/ufs-hisi.c b/drivers/scsi/ufs/ufs-hisi.c
+index 0e855b5afe82..2f592df921d9 100644
+--- a/drivers/scsi/ufs/ufs-hisi.c
++++ b/drivers/scsi/ufs/ufs-hisi.c
+@@ -587,6 +587,10 @@ static int ufs_hisi_init_common(struct ufs_hba *hba)
+ 	ufshcd_set_variant(hba, host);
+ 
+ 	host->rst  = devm_reset_control_get(dev, "rst");
++	if (IS_ERR(host->rst)) {
++		dev_err(dev, "%s: failed to get reset control\n", __func__);
++		return PTR_ERR(host->rst);
++	}
+ 
+ 	ufs_hisi_set_pm_lvl(hba);
+ 

commit 6734330654dac550f12e932996b868c6d0dcb421
+Author: Kangjie Lu 
+Date:   Thu Mar 14 02:21:51 2019 -0500
+
+    tty: mxs-auart: fix a potential NULL pointer dereference
+    
+    In case ioremap fails, the fix returns -ENOMEM to avoid NULL
+    pointer dereferences.
+    Multiple places use port.membase.
+    
+    Signed-off-by: Kangjie Lu 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
+index 27235a526cce..4c188f4079b3 100644
+--- a/drivers/tty/serial/mxs-auart.c
++++ b/drivers/tty/serial/mxs-auart.c
+@@ -1686,6 +1686,10 @@ static int mxs_auart_probe(struct platform_device *pdev)
+ 
+ 	s->port.mapbase = r->start;
+ 	s->port.membase = ioremap(r->start, resource_size(r));
++	if (!s->port.membase) {
++		ret = -ENOMEM;
++		goto out_disable_clks;
++	}
+ 	s->port.ops = &mxs_auart_ops;
+ 	s->port.iotype = UPIO_MEM;
+ 	s->port.fifosize = MXS_AUART_FIFO_SIZE;

commit c85be041065c0be8bc48eda4c45e0319caf1d0e5
+Author: Kangjie Lu 
+Date:   Fri Mar 15 12:16:06 2019 -0500
+
+    tty: atmel_serial: fix a potential NULL pointer dereference
+    
+    In case dmaengine_prep_dma_cyclic fails, the fix returns a proper
+    error code to avoid NULL pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Fixes: 34df42f59a60 ("serial: at91: add rx dma support")
+    Acked-by: Richard Genoud 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
+index 05147fe24343..41b728d223d1 100644
+--- a/drivers/tty/serial/atmel_serial.c
++++ b/drivers/tty/serial/atmel_serial.c
+@@ -1288,6 +1288,10 @@ static int atmel_prepare_rx_dma(struct uart_port *port)
+ 					 sg_dma_len(&atmel_port->sg_rx)/2,
+ 					 DMA_DEV_TO_MEM,
+ 					 DMA_PREP_INTERRUPT);
++	if (!desc) {
++		dev_err(port->dev, "Preparing DMA cyclic failed\n");
++		goto chan_err;
++	}
+ 	desc->callback = atmel_complete_rx_dma;
+ 	desc->callback_param = port;
+ 	atmel_port->desc_rx = desc;

commit 3a10e3dd52e80b9a97a3346020024d17b2c272d6
+Author: Aditya Pakki 
+Date:   Mon Mar 18 18:44:14 2019 -0500
+
+    serial: max310x: Fix to avoid potential NULL pointer dereference
+    
+    of_match_device can return a NULL pointer when matching device is not
+    found. This patch avoids a scenario causing NULL pointer derefernce.
+    
+    Signed-off-by: Aditya Pakki 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
+index f5bdde405627..450ba6d7996c 100644
+--- a/drivers/tty/serial/max310x.c
++++ b/drivers/tty/serial/max310x.c
+@@ -1415,6 +1415,8 @@ static int max310x_spi_probe(struct spi_device *spi)
+ 	if (spi->dev.of_node) {
+ 		const struct of_device_id *of_id =
+ 			of_match_device(max310x_dt_ids, &spi->dev);
++		if (!of_id)
++			return -ENODEV;
+ 
+ 		devtype = (struct max310x_devtype *)of_id->data;
+ 	} else {

commit 32f47179833b63de72427131169809065db6745e
+Author: Aditya Pakki 
+Date:   Mon Mar 18 18:50:56 2019 -0500
+
+    serial: mvebu-uart: Fix to avoid a potential NULL pointer dereference
+    
+    of_match_device on failure to find a matching device can return a NULL
+    pointer. The patch checks for such a scenrio and passes the error upstream.
+    
+    Signed-off-by: Aditya Pakki 
+    Cc: stable 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/tty/serial/mvebu-uart.c b/drivers/tty/serial/mvebu-uart.c
+index 231f751d1ef4..7e7b1559fa36 100644
+--- a/drivers/tty/serial/mvebu-uart.c
++++ b/drivers/tty/serial/mvebu-uart.c
+@@ -810,6 +810,9 @@ static int mvebu_uart_probe(struct platform_device *pdev)
+ 		return -EINVAL;
+ 	}
+ 
++	if (!match)
++		return -ENODEV;
++
+ 	/* Assume that all UART ports have a DT alias or none has */
+ 	id = of_alias_get_id(pdev->dev.of_node, "serial");
+ 	if (!pdev->dev.of_node || id < 0)

commit 6c44b15e1c9076d925d5236ddadf1318b0a25ce2
+Author: Kangjie Lu 
+Date:   Thu Mar 14 00:24:02 2019 -0500
+
+    HID: logitech: check the return value of create_singlethread_workqueue
+    
+    create_singlethread_workqueue may fail and return NULL. The fix checks if it is
+    NULL to avoid NULL pointer dereference.  Also, the fix moves the call of
+    create_singlethread_workqueue earlier to avoid resource-release issues.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
+index 15ed6177a7a3..0a243247b231 100644
+--- a/drivers/hid/hid-logitech-hidpp.c
++++ b/drivers/hid/hid-logitech-hidpp.c
+@@ -2111,6 +2111,13 @@ static int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index)
+ 		kfree(data);
+ 		return -ENOMEM;
+ 	}
++	data->wq = create_singlethread_workqueue("hidpp-ff-sendqueue");
++	if (!data->wq) {
++		kfree(data->effect_ids);
++		kfree(data);
++		return -ENOMEM;
++	}
++
+ 	data->hidpp = hidpp;
+ 	data->feature_index = feature_index;
+ 	data->version = version;
+@@ -2155,7 +2162,6 @@ static int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index)
+ 	/* ignore boost value at response.fap.params[2] */
+ 
+ 	/* init the hardware command queue */
+-	data->wq = create_singlethread_workqueue("hidpp-ff-sendqueue");
+ 	atomic_set(&data->workqueue_size, 0);
+ 
+ 	/* initialize with zero autocenter to get wheel in usable state */

commit 6d65561f3d5ec933151939c543d006b79044e7a6
+Author: Kangjie Lu 
+Date:   Thu Mar 14 02:58:18 2019 -0500
+
+    netfilter: ip6t_srh: fix NULL pointer dereferences
+    
+    skb_header_pointer may return NULL. The current code dereference
+    its return values without a NULL check.
+    
+    The fix inserts the checks to avoid NULL pointer dereferences.
+    
+    Fixes: 202a8ff545cc ("netfilter: add IPv6 segment routing header 'srh' match")
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Pablo Neira Ayuso 
+
+diff --git a/net/ipv6/netfilter/ip6t_srh.c b/net/ipv6/netfilter/ip6t_srh.c
+index 1059894a6f4c..4cb83fb69844 100644
+--- a/net/ipv6/netfilter/ip6t_srh.c
++++ b/net/ipv6/netfilter/ip6t_srh.c
+@@ -210,6 +210,8 @@ static bool srh1_mt6(const struct sk_buff *skb, struct xt_action_param *par)
+ 		psidoff = srhoff + sizeof(struct ipv6_sr_hdr) +
+ 			  ((srh->segments_left + 1) * sizeof(struct in6_addr));
+ 		psid = skb_header_pointer(skb, psidoff, sizeof(_psid), &_psid);
++		if (!psid)
++			return false;
+ 		if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_PSID,
+ 				ipv6_masked_addr_cmp(psid, &srhinfo->psid_msk,
+ 						     &srhinfo->psid_addr)))
+@@ -223,6 +225,8 @@ static bool srh1_mt6(const struct sk_buff *skb, struct xt_action_param *par)
+ 		nsidoff = srhoff + sizeof(struct ipv6_sr_hdr) +
+ 			  ((srh->segments_left - 1) * sizeof(struct in6_addr));
+ 		nsid = skb_header_pointer(skb, nsidoff, sizeof(_nsid), &_nsid);
++		if (!nsid)
++			return false;
+ 		if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_NSID,
+ 				ipv6_masked_addr_cmp(nsid, &srhinfo->nsid_msk,
+ 						     &srhinfo->nsid_addr)))
+@@ -233,6 +237,8 @@ static bool srh1_mt6(const struct sk_buff *skb, struct xt_action_param *par)
+ 	if (srhinfo->mt_flags & IP6T_SRH_LSID) {
+ 		lsidoff = srhoff + sizeof(struct ipv6_sr_hdr);
+ 		lsid = skb_header_pointer(skb, lsidoff, sizeof(_lsid), &_lsid);
++		if (!lsid)
++			return false;
+ 		if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LSID,
+ 				ipv6_masked_addr_cmp(lsid, &srhinfo->lsid_msk,
+ 						     &srhinfo->lsid_addr)))

commit f37d8e67f39e6d3eaf4cc5471e8a3d21209843c6
+Author: Aditya Pakki 
+Date:   Wed Mar 13 11:55:41 2019 -0500
+
+    spi : spi-topcliff-pch: Fix to handle empty DMA buffers
+    
+    pch_alloc_dma_buf allocated tx, rx DMA buffers which can fail. Further,
+    these buffers are used without a check. The patch checks for these
+    failures and sends the error upstream.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Mark Brown 
+
+diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c
+index e7e8ea1edcce..fa730a871d25 100644
+--- a/drivers/spi/spi-topcliff-pch.c
++++ b/drivers/spi/spi-topcliff-pch.c
+@@ -1300,18 +1300,27 @@ static void pch_free_dma_buf(struct pch_spi_board_data *board_dat,
+ 				  dma->rx_buf_virt, dma->rx_buf_dma);
+ }
+ 
+-static void pch_alloc_dma_buf(struct pch_spi_board_data *board_dat,
++static int pch_alloc_dma_buf(struct pch_spi_board_data *board_dat,
+ 			      struct pch_spi_data *data)
+ {
+ 	struct pch_spi_dma_ctrl *dma;
++	int ret;
+ 
+ 	dma = &data->dma;
++	ret = 0;
+ 	/* Get Consistent memory for Tx DMA */
+ 	dma->tx_buf_virt = dma_alloc_coherent(&board_dat->pdev->dev,
+ 				PCH_BUF_SIZE, &dma->tx_buf_dma, GFP_KERNEL);
++	if (!dma->tx_buf_virt)
++		ret = -ENOMEM;
++
+ 	/* Get Consistent memory for Rx DMA */
+ 	dma->rx_buf_virt = dma_alloc_coherent(&board_dat->pdev->dev,
+ 				PCH_BUF_SIZE, &dma->rx_buf_dma, GFP_KERNEL);
++	if (!dma->rx_buf_virt)
++		ret = -ENOMEM;
++
++	return ret;
+ }
+ 
+ static int pch_spi_pd_probe(struct platform_device *plat_dev)
+@@ -1388,7 +1397,9 @@ static int pch_spi_pd_probe(struct platform_device *plat_dev)
+ 
+ 	if (use_dma) {
+ 		dev_info(&plat_dev->dev, "Use DMA for data transfers\n");
+-		pch_alloc_dma_buf(board_dat, data);
++		ret = pch_alloc_dma_buf(board_dat, data);
++		if (ret)
++			goto err_spi_register_master;
+ 	}
+ 
+ 	ret = spi_register_master(master);

commit d6cb77228e3ae070061195a6fff6ba7c3c0b8e47
+Author: Aditya Pakki 
+Date:   Tue Mar 12 10:05:52 2019 -0500
+
+    pinctrl: baytrail: Fix potential NULL pointer dereference
+    
+    saved-context in byt_gpio_probe is allocated via devm_kcalloc and is
+    used without checking for NULL in later functions. This patch avoids
+    such a scenario.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Andy Shevchenko 
+
+diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c
+index 241384ead4ed..18d9ad504194 100644
+--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
++++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
+@@ -1710,6 +1710,8 @@ static int byt_gpio_probe(struct byt_gpio *vg)
+ #ifdef CONFIG_PM_SLEEP
+ 	vg->saved_context = devm_kcalloc(&vg->pdev->dev, gc->ngpio,
+ 				       sizeof(*vg->saved_context), GFP_KERNEL);
++	if (!vg->saved_context)
++		return -ENOMEM;
+ #endif
+ 	ret = devm_gpiochip_add_data(&vg->pdev->dev, gc, vg);
+ 	if (ret) {

commit 517ccc2aa50dbd7767a9eb8e1d9987a3ed7ced3e
+Author: Kangjie Lu 
+Date:   Sat Mar 16 16:46:05 2019 -0500
+
+    net: tipc: fix a missing check for nla_nest_start
+    
+    nla_nest_start may fail. The fix check its status and returns
+    -EMSGSIZE in case it fails.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/tipc/socket.c b/net/tipc/socket.c
+index 3274ef625dba..d6b26862b34e 100644
+--- a/net/tipc/socket.c
++++ b/net/tipc/socket.c
+@@ -3255,6 +3255,8 @@ static int __tipc_nl_add_sk_con(struct sk_buff *skb, struct tipc_sock *tsk)
+ 	peer_port = tsk_peer_port(tsk);
+ 
+ 	nest = nla_nest_start(skb, TIPC_NLA_SOCK_CON);
++	if (!nest)
++		return -EMSGSIZE;
+ 
+ 	if (nla_put_u32(skb, TIPC_NLA_CON_NODE, peer_node))
+ 		goto msg_full;

commit 4589e28db46ee4961edfd794c5bb43887d38c8e5
+Author: Kangjie Lu 
+Date:   Fri Mar 15 12:11:59 2019 -0500
+
+    net: tipc: fix a missing check of nla_nest_start
+    
+    nla_nest_start could fail and requires a check. The fix returns
+    -EMSGSIZE if it fails.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/tipc/group.c b/net/tipc/group.c
+index 06fee142f09f..63f39201e41e 100644
+--- a/net/tipc/group.c
++++ b/net/tipc/group.c
+@@ -919,6 +919,9 @@ int tipc_group_fill_sock_diag(struct tipc_group *grp, struct sk_buff *skb)
+ {
+ 	struct nlattr *group = nla_nest_start(skb, TIPC_NLA_SOCK_GROUP);
+ 
++	if (!group)
++		return -EMSGSIZE;
++
+ 	if (nla_put_u32(skb, TIPC_NLA_SOCK_GROUP_ID,
+ 			grp->type) ||
+ 	    nla_put_u32(skb, TIPC_NLA_SOCK_GROUP_INSTANCE,

commit 07660ca679da3007d3231938e2dfb415d3440716
+Author: Kangjie Lu 
+Date:   Fri Mar 15 01:14:33 2019 -0500
+
+    net: ncsi: fix a missing check for nla_nest_start
+    
+    nla_nest_start may fail and thus deserves a check.
+    
+    The fix returns -EMSGSIZE in case it fails.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ncsi/ncsi-netlink.c b/net/ncsi/ncsi-netlink.c
+index 5d782445d2fc..bad17bba8ba7 100644
+--- a/net/ncsi/ncsi-netlink.c
++++ b/net/ncsi/ncsi-netlink.c
+@@ -251,6 +251,10 @@ static int ncsi_pkg_info_all_nl(struct sk_buff *skb,
+ 	}
+ 
+ 	attr = nla_nest_start(skb, NCSI_ATTR_PACKAGE_LIST);
++	if (!attr) {
++		rc = -EMSGSIZE;
++		goto err;
++	}
+ 	rc = ncsi_write_package_info(skb, ndp, package->id);
+ 	if (rc) {
+ 		nla_nest_cancel(skb, attr);

commit 0fff9bd47e1341b5c4db862cc39fc68ce45f165d
+Author: Kangjie Lu 
+Date:   Fri Mar 15 01:11:22 2019 -0500
+
+    net: openvswitch: fix missing checks for nla_nest_start
+    
+    nla_nest_start may fail and thus deserves a check.
+    The fix returns -EMSGSIZE when it fails.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
+index 45d1469308b0..9dd158ab51b3 100644
+--- a/net/openvswitch/datapath.c
++++ b/net/openvswitch/datapath.c
+@@ -464,6 +464,10 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
+ 
+ 	if (upcall_info->egress_tun_info) {
+ 		nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_EGRESS_TUN_KEY);
++		if (!nla) {
++			err = -EMSGSIZE;
++			goto out;
++		}
+ 		err = ovs_nla_put_tunnel_info(user_skb,
+ 					      upcall_info->egress_tun_info);
+ 		BUG_ON(err);
+@@ -472,6 +476,10 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
+ 
+ 	if (upcall_info->actions_len) {
+ 		nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_ACTIONS);
++		if (!nla) {
++			err = -EMSGSIZE;
++			goto out;
++		}
+ 		err = ovs_nla_put_actions(upcall_info->actions,
+ 					  upcall_info->actions_len,
+ 					  user_skb);

commit 6f19893b644a9454d85e593b5e90914e7a72b7dd
+Author: Kangjie Lu 
+Date:   Thu Mar 14 23:20:16 2019 -0500
+
+    net: openvswitch: fix a NULL pointer dereference
+    
+    upcall is dereferenced even when genlmsg_put fails. The fix
+    goto out to avoid the NULL pointer dereference in this case.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
+index 6679e96ab1dc..45d1469308b0 100644
+--- a/net/openvswitch/datapath.c
++++ b/net/openvswitch/datapath.c
+@@ -448,6 +448,10 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
+ 
+ 	upcall = genlmsg_put(user_skb, 0, 0, &dp_packet_genl_family,
+ 			     0, upcall_info->cmd);
++	if (!upcall) {
++		err = -EINVAL;
++		goto out;
++	}
+ 	upcall->dp_ifindex = dp_ifindex;
+ 
+ 	err = ovs_nla_put_key(key, key, OVS_PACKET_ATTR_KEY, false, user_skb);

commit dcd0feac9bab901d5739de51b3f69840851f8919
+Author: Kangjie Lu 
+Date:   Thu Mar 14 23:04:14 2019 -0500
+
+    ALSA: sb8: add a check for request_region
+    
+    In case request_region fails, the fix returns an error code to
+    avoid NULL pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
+index aa2a83eb81a9..dc27a480c2d9 100644
+--- a/sound/isa/sb/sb8.c
++++ b/sound/isa/sb/sb8.c
+@@ -111,6 +111,10 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev)
+ 
+ 	/* block the 0x388 port to avoid PnP conflicts */
+ 	acard->fm_res = request_region(0x388, 4, "SoundBlaster FM");
++	if (!acard->fm_res) {
++		err = -EBUSY;
++		goto _err;
++	}
+ 
+ 	if (port[dev] != SNDRV_AUTO_PORT) {
+ 		if ((err = snd_sbdsp_create(card, port[dev], irq[dev],

commit 6ade657d6125ec3ec07f95fa51e28138aef6208f
+Author: Kangjie Lu 
+Date:   Thu Mar 14 22:58:29 2019 -0500
+
+    ALSA: echoaudio: add a check for ioremap_nocache
+    
+    In case ioremap_nocache fails, the fix releases chip and returns
+    an error code upstream to avoid NULL pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
+index ea876b0b02b9..dc0084dc8550 100644
+--- a/sound/pci/echoaudio/echoaudio.c
++++ b/sound/pci/echoaudio/echoaudio.c
+@@ -1952,6 +1952,11 @@ static int snd_echo_create(struct snd_card *card,
+ 	}
+ 	chip->dsp_registers = (volatile u32 __iomem *)
+ 		ioremap_nocache(chip->dsp_registers_phys, sz);
++	if (!chip->dsp_registers) {
++		dev_err(chip->card->dev, "ioremap failed\n");
++		snd_echo_free(chip);
++		return -ENOMEM;
++	}
+ 
+ 	if (request_irq(pci->irq, snd_echo_interrupt, IRQF_SHARED,
+ 			KBUILD_MODNAME, chip)) {

commit 228cd2dba27cee9956c1af97e6445be056881e41
+Author: Kangjie Lu 
+Date:   Thu Mar 14 23:12:06 2019 -0500
+
+    net: strparser: fix a missing check for create_singlethread_workqueue
+    
+    In case create_singlethread_workqueue fails, the check returns
+    an error to callers to avoid potential NULL pointer dereferences.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/strparser/strparser.c b/net/strparser/strparser.c
+index da1a676860ca..860dcfb95ee4 100644
+--- a/net/strparser/strparser.c
++++ b/net/strparser/strparser.c
+@@ -550,6 +550,8 @@ EXPORT_SYMBOL_GPL(strp_check_rcv);
+ static int __init strp_mod_init(void)
+ {
+ 	strp_wq = create_singlethread_workqueue("kstrp");
++	if (unlikely(!strp_wq))
++		return -ENOMEM;
+ 
+ 	return 0;
+ }

commit 5bf7295fe34a5251b1d241b9736af4697b590670
+Author: Aditya Pakki 
+Date:   Thu Mar 14 15:31:40 2019 -0500
+
+    qlcnic: Avoid potential NULL pointer dereference
+    
+    netdev_alloc_skb can fail and return a NULL pointer which is
+    dereferenced without a check. The patch avoids such a scenario.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
+index 3b0adda7cc9c..a4cd6f2cfb86 100644
+--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
+@@ -1048,6 +1048,8 @@ int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
+ 
+ 	for (i = 0; i < QLCNIC_NUM_ILB_PKT; i++) {
+ 		skb = netdev_alloc_skb(adapter->netdev, QLCNIC_ILB_PKT_SIZE);
++		if (!skb)
++			break;
+ 		qlcnic_create_loopback_buff(skb->data, adapter->mac_addr);
+ 		skb_put(skb, QLCNIC_ILB_PKT_SIZE);
+ 		adapter->ahw->diag_cnt = 0;

commit a2c6433ee5a35a8de6d563f6512a26f87835ea0f
+Author: Aditya Pakki 
+Date:   Mon Mar 4 17:00:02 2019 -0600
+
+    ALSA: usx2y: Fix potential NULL pointer dereference
+    
+    usb_alloc_urb() can fail due to kmalloc failure and push the error
+    upstream. Further this can cause a NULL pointer dereference in
+    init_pipe_urbs(). This patch avoids such a scenario.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c
+index b0f8979ff2d2..221adf68bd0c 100644
+--- a/sound/usb/usx2y/usb_stream.c
++++ b/sound/usb/usx2y/usb_stream.c
+@@ -104,7 +104,12 @@ static int init_urbs(struct usb_stream_kernel *sk, unsigned use_packsize,
+ 
+ 	for (u = 0; u < USB_STREAM_NURBS; ++u) {
+ 		sk->inurb[u] = usb_alloc_urb(sk->n_o_ps, GFP_KERNEL);
++		if (!sk->inurb[u])
++			return -ENOMEM;
++
+ 		sk->outurb[u] = usb_alloc_urb(sk->n_o_ps, GFP_KERNEL);
++		if (!sk->outurb[u])
++			return -ENOMEM;
+ 	}
+ 
+ 	if (init_pipe_urbs(sk, use_packsize, sk->inurb, indata, dev, in_pipe) ||

commit 2795e8c251614ac0784c9d41008551109f665716
+Author: Kangjie Lu 
+Date:   Mon Mar 11 02:25:17 2019 -0500
+
+    net: ieee802154: fix a potential NULL pointer dereference
+    
+    In case alloc_ordered_workqueue fails, the fix releases
+    sources and returns -ENOMEM to avoid NULL pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Acked-by: Michael Hennerich 
+    Signed-off-by: Stefan Schmidt 
+
+diff --git a/drivers/net/ieee802154/adf7242.c b/drivers/net/ieee802154/adf7242.c
+index cd1d8faccca5..cd6b95e673a5 100644
+--- a/drivers/net/ieee802154/adf7242.c
++++ b/drivers/net/ieee802154/adf7242.c
+@@ -1268,6 +1268,10 @@ static int adf7242_probe(struct spi_device *spi)
+ 	INIT_DELAYED_WORK(&lp->work, adf7242_rx_cal_work);
+ 	lp->wqueue = alloc_ordered_workqueue(dev_name(&spi->dev),
+ 					     WQ_MEM_RECLAIM);
++	if (unlikely(!lp->wqueue)) {
++		ret = -ENOMEM;
++		goto err_hw_init;
++	}
+ 
+ 	ret = adf7242_hw_init(lp);
+ 	if (ret)

commit 4ec850e5dfec092b26cf3b7d5a6c9e444ea4babd
+Author: Kangjie Lu 
+Date:   Tue Mar 12 02:50:40 2019 -0500
+
+    net: dwmac-sun8i: fix a missing check of of_get_phy_mode
+    
+    of_get_phy_mode may fail and return a negative error code;
+    the fix checks the return value of of_get_phy_mode and
+    returns -EINVAL of it fails.
+    
+    Signed-off-by: Kangjie Lu 
+    Acked-by: Maxime Ripard 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+index 0f660af01a4b..195669f550f0 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+@@ -1147,7 +1147,10 @@ static int sun8i_dwmac_probe(struct platform_device *pdev)
+ 		return ret;
+ 	}
+ 
+-	plat_dat->interface = of_get_phy_mode(dev->of_node);
++	ret = of_get_phy_mode(dev->of_node);
++	if (ret < 0)
++		return -EINVAL;
++	plat_dat->interface = ret;
+ 
+ 	/* platform data specifying hardware features and callbacks.
+ 	 * hardware features were copied from Allwinner drivers.

commit 035a14e71f27eefa50087963b94cbdb3580d08bf
+Author: Kangjie Lu 
+Date:   Tue Mar 12 02:43:18 2019 -0500
+
+    net: sh_eth: fix a missing check of of_get_phy_mode
+    
+    of_get_phy_mode may fail and return a negative error code;
+    the fix checks the return value of of_get_phy_mode and
+    returns NULL of it fails.
+    
+    Fixes: b356e978e92f ("sh_eth: add device tree support")
+    Signed-off-by: Kangjie Lu 
+    Reviewed-by: Sergei Shtylyov 
+    Reviewed-by: Geert Uytterhoeven 
+    Tested-by: Geert Uytterhoeven 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
+index 339b2eae2100..e33af371b169 100644
+--- a/drivers/net/ethernet/renesas/sh_eth.c
++++ b/drivers/net/ethernet/renesas/sh_eth.c
+@@ -3181,12 +3181,16 @@ static struct sh_eth_plat_data *sh_eth_parse_dt(struct device *dev)
+ 	struct device_node *np = dev->of_node;
+ 	struct sh_eth_plat_data *pdata;
+ 	const char *mac_addr;
++	int ret;
+ 
+ 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ 	if (!pdata)
+ 		return NULL;
+ 
+-	pdata->phy_interface = of_get_phy_mode(np);
++	ret = of_get_phy_mode(np);
++	if (ret < 0)
++		return NULL;
++	pdata->phy_interface = ret;
+ 
+ 	mac_addr = of_get_mac_address(np);
+ 	if (mac_addr)

commit c7cbc3e937b885c9394bf9d0ca21ceb75c2ac262
+Author: Kangjie Lu 
+Date:   Tue Mar 12 02:24:07 2019 -0500
+
+    net: 8390: fix potential NULL pointer dereferences
+    
+    In case ioremap fails, the fix releases resources and returns
+    to avoid NULL pointer dereferences.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/8390/pcnet_cs.c b/drivers/net/ethernet/8390/pcnet_cs.c
+index 61e43802b9a5..645efac6310d 100644
+--- a/drivers/net/ethernet/8390/pcnet_cs.c
++++ b/drivers/net/ethernet/8390/pcnet_cs.c
+@@ -289,6 +289,11 @@ static struct hw_info *get_hwinfo(struct pcmcia_device *link)
+ 
+     virt = ioremap(link->resource[2]->start,
+ 	    resource_size(link->resource[2]));
++    if (unlikely(!virt)) {
++	    pcmcia_release_window(link, link->resource[2]);
++	    return NULL;
++    }
++
+     for (i = 0; i < NR_INFO; i++) {
+ 	pcmcia_map_mem_page(link, link->resource[2],
+ 		hw_info[i].offset & ~(resource_size(link->resource[2])-1));
+@@ -1423,6 +1428,11 @@ static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
+     /* Try scribbling on the buffer */
+     info->base = ioremap(link->resource[3]->start,
+ 			resource_size(link->resource[3]));
++    if (unlikely(!info->base)) {
++	    ret = -ENOMEM;
++	    goto failed;
++    }
++
+     for (i = 0; i < (TX_PAGES<<8); i += 2)
+ 	__raw_writew((i>>1), info->base+offset+i);
+     udelay(100);

commit 9f4d6358e11bbc7b839f9419636188e4151fb6e4
+Author: Kangjie Lu 
+Date:   Tue Mar 12 02:16:21 2019 -0500
+
+    net: fujitsu: fix a potential NULL pointer dereference
+    
+    In case ioremap fails, the fix releases the pcmcia window and
+    returns -ENOMEM to avoid the NULL pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/fujitsu/fmvj18x_cs.c b/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
+index a69cd19a55ae..1eca0fdb9933 100644
+--- a/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
++++ b/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
+@@ -547,6 +547,11 @@ static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
+ 	return -1;
+ 
+     base = ioremap(link->resource[2]->start, resource_size(link->resource[2]));
++    if (!base) {
++	    pcmcia_release_window(link, link->resource[2]);
++	    return -ENOMEM;
++    }
++
+     pcmcia_map_mem_page(link, link->resource[2], 0);
+ 
+     /*

commit eb32cfcdef2305dc0e44a65d42801315669bb27e
+Author: Kangjie Lu 
+Date:   Tue Mar 12 02:06:47 2019 -0500
+
+    net: qlogic: fix a potential NULL pointer dereference
+    
+    In case create_singlethread_workqueue fails, the fix returns
+    -ENOMEM to avoid NULL pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c
+index 10b075bc5959..b61b88cbc0c7 100644
+--- a/drivers/net/ethernet/qlogic/qla3xxx.c
++++ b/drivers/net/ethernet/qlogic/qla3xxx.c
+@@ -3886,6 +3886,12 @@ static int ql3xxx_probe(struct pci_dev *pdev,
+ 	netif_stop_queue(ndev);
+ 
+ 	qdev->workqueue = create_singlethread_workqueue(ndev->name);
++	if (!qdev->workqueue) {
++		unregister_netdev(ndev);
++		err = -ENOMEM;
++		goto err_out_iounmap;
++	}
++
+ 	INIT_DELAYED_WORK(&qdev->reset_work, ql_reset_work);
+ 	INIT_DELAYED_WORK(&qdev->tx_timeout_work, ql_tx_timeout_work);
+ 	INIT_DELAYED_WORK(&qdev->link_state_work, ql_link_state_machine_work);

commit 10010493c1261ca3d7444d372f281009890a5ff7
+Author: Kangjie Lu 
+Date:   Tue Mar 12 00:54:55 2019 -0500
+
+    isdn: hfcpci: fix potential NULL pointer dereference
+    
+    In case ioremap fails, the fix releases resources and returns.
+    The following printk is for logging purpose and thus is
+    preserved.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
+index ebb3fa2e1d00..362aa5450a5e 100644
+--- a/drivers/isdn/hardware/mISDN/hfcpci.c
++++ b/drivers/isdn/hardware/mISDN/hfcpci.c
+@@ -2032,10 +2032,19 @@ setup_hw(struct hfc_pci *hc)
+ 	hc->hw.fifos = buffer;
+ 	pci_write_config_dword(hc->pdev, 0x80, hc->hw.dmahandle);
+ 	hc->hw.pci_io = ioremap((ulong) hc->hw.pci_io, 256);
++	if (unlikely(!hc->hw.pci_io)) {
++		printk(KERN_WARNING
++		       "HFC-PCI: Error in ioremap for PCI!\n");
++		pci_free_consistent(hc->pdev, 0x8000, hc->hw.fifos,
++				    hc->hw.dmahandle);
++		return 1;
++	}
++
+ 	printk(KERN_INFO
+ 	       "HFC-PCI: defined at mem %#lx fifo %#lx(%#lx) IRQ %d HZ %d\n",
+ 	       (u_long) hc->hw.pci_io, (u_long) hc->hw.fifos,
+ 	       (u_long) hc->hw.dmahandle, hc->irq, HZ);
++
+ 	/* enable memory mapped ports, disable busmaster */
+ 	pci_write_config_word(hc->pdev, PCI_COMMAND, PCI_ENA_MEMIO);
+ 	hc->hw.int_m2 = 0;

commit e406f12dde1a8375d77ea02d91f313fb1a9c6aec
+Author: Aditya Pakki 
+Date:   Mon Mar 4 16:48:54 2019 -0600
+
+    md: Fix failed allocation of md_register_thread
+    
+    mddev->sync_thread can be set to NULL on kzalloc failure downstream.
+    The patch checks for such a scenario and frees allocated resources.
+    
+    Committer node:
+    
+    Added similar fix to raid5.c, as suggested by Guoqing.
+    
+    Cc: stable@vger.kernel.org # v3.16+
+    Acked-by: Guoqing Jiang 
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Song Liu 
+
+diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
+index ecef42bfe19d..3b6880dd648d 100644
+--- a/drivers/md/raid10.c
++++ b/drivers/md/raid10.c
+@@ -3939,6 +3939,8 @@ static int raid10_run(struct mddev *mddev)
+ 		set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
+ 		mddev->sync_thread = md_register_thread(md_do_sync, mddev,
+ 							"reshape");
++		if (!mddev->sync_thread)
++			goto out_free_conf;
+ 	}
+ 
+ 	return 0;
+diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
+index 09562d7cc080..992fd08437d8 100644
+--- a/drivers/md/raid5.c
++++ b/drivers/md/raid5.c
+@@ -7403,6 +7403,8 @@ static int raid5_run(struct mddev *mddev)
+ 		set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
+ 		mddev->sync_thread = md_register_thread(md_do_sync, mddev,
+ 							"reshape");
++		if (!mddev->sync_thread)
++			goto abort;
+ 	}
+ 
+ 	/* Ok, everything is just fine now */

commit 5c149314d91876f743ee43efd75b6287ec55480e
+Author: Kangjie Lu 
+Date:   Mon Mar 11 02:06:06 2019 -0500
+
+    net: rocker: fix a potential NULL pointer dereference
+    
+    In case kzalloc fails, the fix releases resources and returns
+    NOTIFY_BAD to avoid NULL pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
+index c883aa89b7ca..a71c900ca04f 100644
+--- a/drivers/net/ethernet/rocker/rocker_main.c
++++ b/drivers/net/ethernet/rocker/rocker_main.c
+@@ -2805,6 +2805,11 @@ static int rocker_switchdev_event(struct notifier_block *unused,
+ 		memcpy(&switchdev_work->fdb_info, ptr,
+ 		       sizeof(switchdev_work->fdb_info));
+ 		switchdev_work->fdb_info.addr = kzalloc(ETH_ALEN, GFP_ATOMIC);
++		if (unlikely(!switchdev_work->fdb_info.addr)) {
++			kfree(switchdev_work);
++			return NOTIFY_BAD;
++		}
++
+ 		ether_addr_copy((u8 *)switchdev_work->fdb_info.addr,
+ 				fdb_info->addr);
+ 		/* Take a reference on the rocker device */

commit 4280b73092fe136d412db9e8e0d69cbc753cdac6
+Author: Kangjie Lu 
+Date:   Mon Mar 11 01:53:15 2019 -0500
+
+    net: qlge: fix a potential NULL pointer dereference
+    
+    In case alloc_ordered_workqueue fails, the fix returns
+    -ENOMEM to avoid NULL pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
+index 096515c27263..07e1c623048e 100644
+--- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c
++++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
+@@ -4681,6 +4681,11 @@ static int ql_init_device(struct pci_dev *pdev, struct net_device *ndev,
+ 	 */
+ 	qdev->workqueue = alloc_ordered_workqueue("%s", WQ_MEM_RECLAIM,
+ 						  ndev->name);
++	if (!qdev->workqueue) {
++		err = -ENOMEM;
++		goto err_out2;
++	}
++
+ 	INIT_DELAYED_WORK(&qdev->asic_reset_work, ql_asic_reset_work);
+ 	INIT_DELAYED_WORK(&qdev->mpi_reset_work, ql_mpi_reset_work);
+ 	INIT_DELAYED_WORK(&qdev->mpi_work, ql_mpi_work);

commit 0b31d98d90f09868dce71319615e19cd1f146fb6
+Author: Kangjie Lu 
+Date:   Mon Mar 11 01:05:41 2019 -0500
+
+    net: thunder: fix a potential NULL pointer dereference
+    
+    In case alloc_ordered_workqueue fails, the fix reports the error
+    and returns -ENOMEM.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+index 503cfadff4ac..aa2be4807191 100644
+--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
++++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+@@ -2234,6 +2234,12 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	nic->nicvf_rx_mode_wq = alloc_ordered_workqueue("nicvf_rx_mode_wq_VF%d",
+ 							WQ_MEM_RECLAIM,
+ 							nic->vf_id);
++	if (!nic->nicvf_rx_mode_wq) {
++		err = -ENOMEM;
++		dev_err(dev, "Failed to allocate work queue\n");
++		goto err_unregister_interrupts;
++	}
++
+ 	INIT_WORK(&nic->rx_mode_work.work, nicvf_set_rx_mode_task);
+ 	spin_lock_init(&nic->rx_mode_wq_lock);
+ 	mutex_init(&nic->rx_mode_mtx);

commit 41af8b3a097c6fd17a4867efa25966927094f57c
+Author: Kangjie Lu 
+Date:   Mon Mar 11 01:01:41 2019 -0500
+
+    net: lio_core: fix two NULL pointer dereferences
+    
+    In case octeon_alloc_soft_command fails, the fix reports the
+    error and returns to avoid NULL pointer dereferences.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/cavium/liquidio/lio_core.c b/drivers/net/ethernet/cavium/liquidio/lio_core.c
+index e21bf3724611..1c50c10b5a16 100644
+--- a/drivers/net/ethernet/cavium/liquidio/lio_core.c
++++ b/drivers/net/ethernet/cavium/liquidio/lio_core.c
+@@ -1211,6 +1211,11 @@ int liquidio_change_mtu(struct net_device *netdev, int new_mtu)
+ 
+ 	sc = (struct octeon_soft_command *)
+ 		octeon_alloc_soft_command(oct, OCTNET_CMD_SIZE, 16, 0);
++	if (!sc) {
++		netif_info(lio, rx_err, lio->netdev,
++			   "Failed to allocate soft command\n");
++		return -ENOMEM;
++	}
+ 
+ 	ncmd = (union octnet_cmd *)sc->virtdptr;
+ 
+@@ -1684,6 +1689,11 @@ int liquidio_set_fec(struct lio *lio, int on_off)
+ 
+ 	sc = octeon_alloc_soft_command(oct, OCTNET_CMD_SIZE,
+ 				       sizeof(struct oct_nic_seapi_resp), 0);
++	if (!sc) {
++		dev_err(&oct->pci_dev->dev,
++			"Failed to allocate soft command\n");
++		return -ENOMEM;
++	}
+ 
+ 	ncmd = sc->virtdptr;
+ 	resp = sc->virtrptr;

commit fe543b2f174f34a7a751aa08b334fe6b105c4569
+Author: Kangjie Lu 
+Date:   Mon Mar 11 00:02:32 2019 -0500
+
+    net: liquidio: fix a NULL pointer dereference
+    
+    In case octeon_alloc_soft_command fails, the fix reports the
+    error and returns to avoid NULL pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
+index 9b7819fdc9de..fb6f813cff65 100644
+--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
++++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
+@@ -1192,6 +1192,11 @@ static void send_rx_ctrl_cmd(struct lio *lio, int start_stop)
+ 	sc = (struct octeon_soft_command *)
+ 		octeon_alloc_soft_command(oct, OCTNET_CMD_SIZE,
+ 					  16, 0);
++	if (!sc) {
++		netif_info(lio, rx_err, lio->netdev,
++			   "Failed to allocate octeon_soft_command\n");
++		return;
++	}
+ 
+ 	ncmd = (union octnet_cmd *)sc->virtdptr;
+ 

commit d721fe99f6ada070ae8fc0ec3e01ce5a42def0d9
+Author: Kangjie Lu 
+Date:   Fri Mar 8 23:49:34 2019 -0600
+
+    isdn: mISDNinfineon: fix potential NULL pointer dereference
+    
+    In case ioremap fails, the fix returns -ENOMEM to avoid NULL
+    pointer dereference.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/isdn/hardware/mISDN/mISDNinfineon.c b/drivers/isdn/hardware/mISDN/mISDNinfineon.c
+index 3e01012be4ab..0fe6ddcb3fdc 100644
+--- a/drivers/isdn/hardware/mISDN/mISDNinfineon.c
++++ b/drivers/isdn/hardware/mISDN/mISDNinfineon.c
+@@ -712,8 +712,11 @@ setup_io(struct inf_hw *hw)
+ 				(ulong)hw->addr.start, (ulong)hw->addr.size);
+ 			return err;
+ 		}
+-		if (hw->ci->addr_mode == AM_MEMIO)
++		if (hw->ci->addr_mode == AM_MEMIO) {
+ 			hw->addr.p = ioremap(hw->addr.start, hw->addr.size);
++			if (unlikely(!hw->addr.p))
++				return -ENOMEM;
++		}
+ 		hw->addr.mode = hw->ci->addr_mode;
+ 		if (debug & DEBUG_HW)
+ 			pr_notice("%s: IO addr %lx (%lu bytes) mode%d\n",

commit 38d22659803a033b1b66cd2624c33570c0dde77d
+Author: Aditya Pakki 
+Date:   Sat Mar 2 15:20:43 2019 -0600
+
+    isdn: mISDN: Fix potential NULL pointer dereference of kzalloc
+    
+    Allocating memory via kzalloc for phi may fail and causes a
+    NULL pointer dereference. This patch avoids such a scenario.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c
+index 124ff530da82..26e3182bbca8 100644
+--- a/drivers/isdn/hardware/mISDN/hfcsusb.c
++++ b/drivers/isdn/hardware/mISDN/hfcsusb.c
+@@ -263,6 +263,9 @@ hfcsusb_ph_info(struct hfcsusb *hw)
+ 	int i;
+ 
+ 	phi = kzalloc(struct_size(phi, bch, dch->dev.nrbchan), GFP_ATOMIC);
++	if (!phi)
++		return;
++
+ 	phi->dch.ch.protocol = hw->protocol;
+ 	phi->dch.ch.Flags = dch->Flags;
+ 	phi->dch.state = dch->state;

commit 434256833d8eb988cb7f3b8a41699e2fe48d9332
+Author: Kangjie Lu 
+Date:   Tue Jan 8 11:42:21 2019 -0600
+
+    libertas: add checks for the return value of sysfs_create_group
+    
+    sysfs_create_group() could fail. The fix checkes its return values
+    and issue error messages if it fails.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Kalle Valo 
+
+diff --git a/drivers/net/wireless/marvell/libertas/mesh.c b/drivers/net/wireless/marvell/libertas/mesh.c
+index b0cb16ef8d1d..2315fdff56c2 100644
+--- a/drivers/net/wireless/marvell/libertas/mesh.c
++++ b/drivers/net/wireless/marvell/libertas/mesh.c
+@@ -797,7 +797,12 @@ static void lbs_persist_config_init(struct net_device *dev)
+ {
+ 	int ret;
+ 	ret = sysfs_create_group(&(dev->dev.kobj), &boot_opts_group);
++	if (ret)
++		pr_err("failed to create boot_opts_group.\n");
++
+ 	ret = sysfs_create_group(&(dev->dev.kobj), &mesh_ie_group);
++	if (ret)
++		pr_err("failed to create mesh_ie_group.\n");
+ }
+ 
+ static void lbs_persist_config_remove(struct net_device *dev)

commit 9a20b5e35a536d6bb4b2d4a3b14a0457e205356c
+Author: Kangjie Lu 
+Date:   Tue Dec 25 21:09:11 2018 -0600
+
+    rtc: hym8563: fix a missing check of block data read
+    
+    When i2c_smbus_read_i2c_block_data() fails, the read data in "buf" could
+    be incorrect and should not be used. The fix checks if
+    i2c_smbus_read_i2c_block_data fails, and if so, return its error code
+    upstream.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Alexandre Belloni 
+
+diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c
+index e5ad527cb75e..d03f5d212eea 100644
+--- a/drivers/rtc/rtc-hym8563.c
++++ b/drivers/rtc/rtc-hym8563.c
+@@ -109,6 +109,8 @@ static int hym8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
+ 	}
+ 
+ 	ret = i2c_smbus_read_i2c_block_data(client, HYM8563_SEC, 7, buf);
++	if (ret < 0)
++		return ret;
+ 
+ 	tm->tm_sec = bcd2bin(buf[0] & HYM8563_SEC_MASK);
+ 	tm->tm_min = bcd2bin(buf[1] & HYM8563_MIN_MASK);

commit 5910fa0d0d9809c4d8fbf1fb905a8c86fbf2eccb
+Author: Kangjie Lu 
+Date:   Tue Dec 25 20:43:33 2018 -0600
+
+    rtc: coh901331: fix a missing check of clk_prepare
+    
+    clk_prepare() could fail, so let's check its status and if it fails
+    return its error code upstream.
+    
+    Signed-off-by: Kangjie Lu 
+    Acked-by: Linus Walleij 
+    Signed-off-by: Alexandre Belloni 
+
+diff --git a/drivers/rtc/rtc-coh901331.c b/drivers/rtc/rtc-coh901331.c
+index fc5cf5c44ae7..0b232c84f674 100644
+--- a/drivers/rtc/rtc-coh901331.c
++++ b/drivers/rtc/rtc-coh901331.c
+@@ -235,9 +235,13 @@ static int coh901331_suspend(struct device *dev)
+ 
+ static int coh901331_resume(struct device *dev)
+ {
++	int ret;
+ 	struct coh901331_port *rtap = dev_get_drvdata(dev);
+ 
+-	clk_prepare(rtap->clk);
++	ret = clk_prepare(rtap->clk);
++	if (ret)
++		return ret;
++
+ 	if (device_may_wakeup(dev)) {
+ 		disable_irq_wake(rtap->irq);
+ 	} else {

commit 6f12e46eebf1a7d4fdd66df5e815df96b8f8b1b5
+Author: Kangjie Lu 
+Date:   Thu Dec 20 13:51:24 2018 -0600
+
+    power: twl4030: fix a missing check of return value
+    
+    If twl4030_bci_read() fails, the read data in "s" is incorrect,
+    which is however used in the following execution. The fix checks
+    the return value of twl4030_bci_read() and returns an error code
+    upstream upon the failure of twl4030_bci_read().
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Sebastian Reichel 
+
+diff --git a/drivers/power/supply/twl4030_charger.c b/drivers/power/supply/twl4030_charger.c
+index 0e202d4273fb..4299873a1118 100644
+--- a/drivers/power/supply/twl4030_charger.c
++++ b/drivers/power/supply/twl4030_charger.c
+@@ -809,7 +809,9 @@ static int twl4030_bci_get_property(struct power_supply *psy,
+ 		is_charging = state & TWL4030_MSTATEC_AC;
+ 	if (!is_charging) {
+ 		u8 s;
+-		twl4030_bci_read(TWL4030_BCIMDEN, &s);
++		ret = twl4030_bci_read(TWL4030_BCIMDEN, &s);
++		if (ret < 0)
++			return ret;
+ 		if (psy->desc->type == POWER_SUPPLY_TYPE_USB)
+ 			is_charging = s & 1;
+ 		else

commit b05ae01fdb8966afff5b153e7a7ee24684745e2d
+Author: Aditya Pakki 
+Date:   Mon Dec 24 11:31:13 2018 -0600
+
+    misc/ics932s401: Add a missing check to i2c_smbus_read_word_data
+    
+    ics932s401_update_device may fail reading in i2c_smbus_read_word_data
+    due to error in i2c_smbus_xfer. The fix checks the status and defaults
+    the register to 0.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/misc/ics932s401.c b/drivers/misc/ics932s401.c
+index 81a0541ef3ac..294fb2f66bfe 100644
+--- a/drivers/misc/ics932s401.c
++++ b/drivers/misc/ics932s401.c
+@@ -146,6 +146,8 @@ static struct ics932s401_data *ics932s401_update_device(struct device *dev)
+ 	 */
+ 	for (i = 0; i < NUM_MIRRORED_REGS; i++) {
+ 		temp = i2c_smbus_read_word_data(client, regs_to_copy[i]);
++		if (temp < 0)
++			data->regs[regs_to_copy[i]] = 0;
+ 		data->regs[regs_to_copy[i]] = temp >> 8;
+ 	}
+ 

commit 40619f7dd3ef05ae7861bc60d401585d316e1374
+Author: Aditya Pakki 
+Date:   Sat Jan 5 13:58:45 2019 -0600
+
+    PM: clock_ops: fix missing clk_prepare() return value check
+    
+    clk_prepare() can fail, so check its status and if it fails,
+    issue an error message and change the clock_entry_status to
+    PCE_STATUS_ERROR.
+    
+    Signed-off-by: Aditya Pakki 
+    [ rjw: Subject ]
+    Signed-off-by: Rafael J. Wysocki 
+
+diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c
+index 5a42ae4078c2..365ad751ce0f 100644
+--- a/drivers/base/power/clock_ops.c
++++ b/drivers/base/power/clock_ops.c
+@@ -65,10 +65,15 @@ static void pm_clk_acquire(struct device *dev, struct pm_clock_entry *ce)
+ 	if (IS_ERR(ce->clk)) {
+ 		ce->status = PCE_STATUS_ERROR;
+ 	} else {
+-		clk_prepare(ce->clk);
+-		ce->status = PCE_STATUS_ACQUIRED;
+-		dev_dbg(dev, "Clock %pC con_id %s managed by runtime PM.\n",
+-			ce->clk, ce->con_id);
++		if (clk_prepare(ce->clk)) {
++			ce->status = PCE_STATUS_ERROR;
++			dev_err(dev, "clk_prepare() failed\n");
++		} else {
++			ce->status = PCE_STATUS_ACQUIRED;
++			dev_dbg(dev,
++				"Clock %pC con_id %s managed by runtime PM.\n",
++				ce->clk, ce->con_id);
++		}
+ 	}
+ }
+ 

commit 248b57015f35c94d4eae2fdd8c6febf5cd703900
+Author: Kangjie Lu 
+Date:   Tue Dec 25 22:18:23 2018 -0600
+
+    leds: lp5523: fix a missing check of return value of lp55xx_read
+    
+    When lp55xx_read() fails, "status" is an uninitialized variable and thus
+    may contain random value; using it leads to undefined behaviors.
+    
+    The fix inserts a check for the return value of lp55xx_read: if it
+    fails, returns with its error code.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Jacek Anaszewski 
+
+diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c
+index a2e74feee2b2..fd64df5a57a5 100644
+--- a/drivers/leds/leds-lp5523.c
++++ b/drivers/leds/leds-lp5523.c
+@@ -318,7 +318,9 @@ static int lp5523_init_program_engine(struct lp55xx_chip *chip)
+ 
+ 	/* Let the programs run for couple of ms and check the engine status */
+ 	usleep_range(3000, 6000);
+-	lp55xx_read(chip, LP5523_REG_STATUS, &status);
++	ret = lp55xx_read(chip, LP5523_REG_STATUS, &status);
++	if (ret)
++		return ret;
+ 	status &= LP5523_ENG_STATUS_MASK;
+ 
+ 	if (status != LP5523_ENG_STATUS_MASK) {

commit 467a37fba93f2b4fe3ab597ff6a517b22b566882
+Author: Aditya Pakki 
+Date:   Thu Dec 27 13:58:01 2018 -0500
+
+    media: dvb: Add check on sp8870_readreg
+    
+    In sp8870_set_frontend_parameters, the function sp8870_readreg
+    may return an error when i2c_transfer fails. The fix checks for
+    this error and returns upstream consistent with other invocations.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Sean Young 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb-frontends/sp8870.c b/drivers/media/dvb-frontends/sp8870.c
+index 8d31cf3f4f07..270a3c559e08 100644
+--- a/drivers/media/dvb-frontends/sp8870.c
++++ b/drivers/media/dvb-frontends/sp8870.c
+@@ -293,7 +293,9 @@ static int sp8870_set_frontend_parameters(struct dvb_frontend *fe)
+ 	sp8870_writereg(state, 0xc05, reg0xc05);
+ 
+ 	// read status reg in order to clear pending irqs
+-	sp8870_readreg(state, 0x200);
++	err = sp8870_readreg(state, 0x200);
++	if (err)
++		return err;
+ 
+ 	// system controller start
+ 	sp8870_microcontroller_start(state);

commit 0f787c12ee7b2b41a74594ed158a0112736f4e4e
+Author: Aditya Pakki 
+Date:   Thu Dec 27 13:47:20 2018 -0500
+
+    media: dvb: add return value check on Write16
+    
+    Write16 can return an error code -1 when the i2c_write fails. The
+    fix checks for these failures and returns the error upstream
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Sean Young 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb-frontends/drxd_hard.c b/drivers/media/dvb-frontends/drxd_hard.c
+index 684d428efb0d..0a5b15bee1d7 100644
+--- a/drivers/media/dvb-frontends/drxd_hard.c
++++ b/drivers/media/dvb-frontends/drxd_hard.c
+@@ -1144,6 +1144,8 @@ static int EnableAndResetMB(struct drxd_state *state)
+ 
+ static int InitCC(struct drxd_state *state)
+ {
++	int status = 0;
++
+ 	if (state->osc_clock_freq == 0 ||
+ 	    state->osc_clock_freq > 20000 ||
+ 	    (state->osc_clock_freq % 4000) != 0) {
+@@ -1151,14 +1153,17 @@ static int InitCC(struct drxd_state *state)
+ 		return -1;
+ 	}
+ 
+-	Write16(state, CC_REG_OSC_MODE__A, CC_REG_OSC_MODE_M20, 0);
+-	Write16(state, CC_REG_PLL_MODE__A, CC_REG_PLL_MODE_BYPASS_PLL |
+-		CC_REG_PLL_MODE_PUMP_CUR_12, 0);
+-	Write16(state, CC_REG_REF_DIVIDE__A, state->osc_clock_freq / 4000, 0);
+-	Write16(state, CC_REG_PWD_MODE__A, CC_REG_PWD_MODE_DOWN_PLL, 0);
+-	Write16(state, CC_REG_UPDATE__A, CC_REG_UPDATE_KEY, 0);
++	status |= Write16(state, CC_REG_OSC_MODE__A, CC_REG_OSC_MODE_M20, 0);
++	status |= Write16(state, CC_REG_PLL_MODE__A,
++				CC_REG_PLL_MODE_BYPASS_PLL |
++				CC_REG_PLL_MODE_PUMP_CUR_12, 0);
++	status |= Write16(state, CC_REG_REF_DIVIDE__A,
++				state->osc_clock_freq / 4000, 0);
++	status |= Write16(state, CC_REG_PWD_MODE__A, CC_REG_PWD_MODE_DOWN_PLL,
++				0);
++	status |= Write16(state, CC_REG_UPDATE__A, CC_REG_UPDATE_KEY, 0);
+ 
+-	return 0;
++	return status;
+ }
+ 
+ static int ResetECOD(struct drxd_state *state)
+@@ -1312,7 +1317,10 @@ static int SC_SendCommand(struct drxd_state *state, u16 cmd)
+ 	int status = 0, ret;
+ 	u16 errCode;
+ 
+-	Write16(state, SC_RA_RAM_CMD__A, cmd, 0);
++	status = Write16(state, SC_RA_RAM_CMD__A, cmd, 0);
++	if (status < 0)
++		return status;
++
+ 	SC_WaitForReady(state);
+ 
+ 	ret = Read16(state, SC_RA_RAM_CMD_ADDR__A, &errCode, 0);
+@@ -1339,9 +1347,9 @@ static int SC_ProcStartCommand(struct drxd_state *state,
+ 			break;
+ 		}
+ 		SC_WaitForReady(state);
+-		Write16(state, SC_RA_RAM_CMD_ADDR__A, subCmd, 0);
+-		Write16(state, SC_RA_RAM_PARAM1__A, param1, 0);
+-		Write16(state, SC_RA_RAM_PARAM0__A, param0, 0);
++		status |= Write16(state, SC_RA_RAM_CMD_ADDR__A, subCmd, 0);
++		status |= Write16(state, SC_RA_RAM_PARAM1__A, param1, 0);
++		status |= Write16(state, SC_RA_RAM_PARAM0__A, param0, 0);
+ 
+ 		SC_SendCommand(state, SC_RA_RAM_CMD_PROC_START);
+ 	} while (0);

commit 9502cdf0807058a10029488052b064cecceb7fc9
+Author: Kangjie Lu 
+Date:   Fri Dec 21 02:07:20 2018 -0500
+
+    media: mt312: fix a missing check of mt312 reset
+    
+    mt312_reset() may fail. Although it is called in the end of
+    mt312_set_frontend(), we better check its status and return its error
+    code upstream instead of 0.
+    
+    Signed-off-by: Kangjie Lu 
+    Reviewed-by: Matthias Schwarzott 
+    Signed-off-by: Sean Young 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb-frontends/mt312.c b/drivers/media/dvb-frontends/mt312.c
+index 03e74a729168..bfbb879469f2 100644
+--- a/drivers/media/dvb-frontends/mt312.c
++++ b/drivers/media/dvb-frontends/mt312.c
+@@ -645,7 +645,9 @@ static int mt312_set_frontend(struct dvb_frontend *fe)
+ 	if (ret < 0)
+ 		return ret;
+ 
+-	mt312_reset(state, 0);
++	ret = mt312_reset(state, 0);
++	if (ret < 0)
++		return ret;
+ 
+ 	return 0;
+ }

commit c9b7d8f252a5a6f8ca6e948151367cbc7bc4b776
+Author: Kangjie Lu 
+Date:   Thu Dec 20 02:48:42 2018 -0500
+
+    media: lgdt3306a: fix a missing check of return value
+    
+    If lgdt3306a_read_reg() fails, the read data in "val" is incorrect, thus
+    shouldn't be further used. The fix inserts a check for the return value
+    of lgdt3306a_read_reg(). If it fails, goto fail.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Sean Young 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/dvb-frontends/lgdt3306a.c b/drivers/media/dvb-frontends/lgdt3306a.c
+index cee9c83e48de..99c6289ae585 100644
+--- a/drivers/media/dvb-frontends/lgdt3306a.c
++++ b/drivers/media/dvb-frontends/lgdt3306a.c
+@@ -1685,7 +1685,10 @@ static int lgdt3306a_read_signal_strength(struct dvb_frontend *fe,
+ 	case QAM_256:
+ 	case QAM_AUTO:
+ 		/* need to know actual modulation to set proper SNR baseline */
+-		lgdt3306a_read_reg(state, 0x00a6, &val);
++		ret = lgdt3306a_read_reg(state, 0x00a6, &val);
++		if (lg_chkerr(ret))
++			goto fail;
++
+ 		if(val & 0x04)
+ 			ref_snr = 2800; /* QAM-256 28dB */
+ 		else

commit 656025850074f5c1ba2e05be37bda57ba2b8d491
+Author: Aditya Pakki 
+Date:   Fri Dec 28 13:51:10 2018 -0500
+
+    media: gspca: mt9m111: Check write_bridge for timeout
+    
+    In mt9m111_probe, m5602_write_bridge can timeout and return a negative
+    error value. The fix checks for this error and passes it upstream.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/usb/gspca/m5602/m5602_mt9m111.c b/drivers/media/usb/gspca/m5602/m5602_mt9m111.c
+index c9947c4a0f63..8fac814f4779 100644
+--- a/drivers/media/usb/gspca/m5602/m5602_mt9m111.c
++++ b/drivers/media/usb/gspca/m5602/m5602_mt9m111.c
+@@ -199,7 +199,7 @@ static const struct v4l2_ctrl_config mt9m111_greenbal_cfg = {
+ int mt9m111_probe(struct sd *sd)
+ {
+ 	u8 data[2] = {0x00, 0x00};
+-	int i;
++	int i, rc = 0;
+ 	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 
+ 	if (force_sensor) {
+@@ -217,16 +217,18 @@ int mt9m111_probe(struct sd *sd)
+ 	/* Do the preinit */
+ 	for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) {
+ 		if (preinit_mt9m111[i][0] == BRIDGE) {
+-			m5602_write_bridge(sd,
++			rc |= m5602_write_bridge(sd,
+ 				preinit_mt9m111[i][1],
+ 				preinit_mt9m111[i][2]);
+ 		} else {
+ 			data[0] = preinit_mt9m111[i][2];
+ 			data[1] = preinit_mt9m111[i][3];
+-			m5602_write_sensor(sd,
++			rc |= m5602_write_sensor(sd,
+ 				preinit_mt9m111[i][1], data, 2);
+ 		}
+ 	}
++	if (rc < 0)
++		return rc;
+ 
+ 	if (m5602_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2))
+ 		return -ENODEV;

commit a21a0eb56b4e8fe4a330243af8030f890cde2283
+Author: Aditya Pakki 
+Date:   Fri Dec 28 13:37:36 2018 -0500
+
+    media: gspca: Check the return value of write_bridge for timeout
+    
+    In po1030_probe(), m5602_write_bridge() can timeout and return an error
+    value. The fix checks for the return value and propagates upstream
+    consistent with other usb drivers.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/usb/gspca/m5602/m5602_po1030.c b/drivers/media/usb/gspca/m5602/m5602_po1030.c
+index 37d2891e5f5b..5e43b4782f02 100644
+--- a/drivers/media/usb/gspca/m5602/m5602_po1030.c
++++ b/drivers/media/usb/gspca/m5602/m5602_po1030.c
+@@ -158,6 +158,7 @@ static const struct v4l2_ctrl_config po1030_greenbal_cfg = {
+ 
+ int po1030_probe(struct sd *sd)
+ {
++	int rc = 0;
+ 	u8 dev_id_h = 0, i;
+ 	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
+ 
+@@ -177,11 +178,14 @@ int po1030_probe(struct sd *sd)
+ 	for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) {
+ 		u8 data = preinit_po1030[i][2];
+ 		if (preinit_po1030[i][0] == SENSOR)
+-			m5602_write_sensor(sd,
++			rc |= m5602_write_sensor(sd,
+ 				preinit_po1030[i][1], &data, 1);
+ 		else
+-			m5602_write_bridge(sd, preinit_po1030[i][1], data);
++			rc |= m5602_write_bridge(sd, preinit_po1030[i][1],
++						data);
+ 	}
++	if (rc < 0)
++		return rc;
+ 
+ 	if (m5602_read_sensor(sd, PO1030_DEVID_H, &dev_id_h, 1))
+ 		return -ENODEV;

commit 5b711870bec4dc9a6d705d41e127e73944fa3650
+Author: Kangjie Lu 
+Date:   Tue Dec 25 03:24:41 2018 -0500
+
+    media: usb: gspca: add a missed check for goto_low_power
+    
+    The fix checks if goto_low_power() fails, and if so, issues an error
+    message.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/usb/gspca/cpia1.c b/drivers/media/usb/gspca/cpia1.c
+index 23fbda56fc91..7c817a4a93c4 100644
+--- a/drivers/media/usb/gspca/cpia1.c
++++ b/drivers/media/usb/gspca/cpia1.c
+@@ -1434,6 +1434,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ {
+ 	struct sd *sd = (struct sd *) gspca_dev;
+ 	struct cam *cam;
++	int ret;
+ 
+ 	sd->mainsFreq = FREQ_DEF == V4L2_CID_POWER_LINE_FREQUENCY_60HZ;
+ 	reset_camera_params(gspca_dev);
+@@ -1445,7 +1446,10 @@ static int sd_config(struct gspca_dev *gspca_dev,
+ 	cam->cam_mode = mode;
+ 	cam->nmodes = ARRAY_SIZE(mode);
+ 
+-	goto_low_power(gspca_dev);
++	ret = goto_low_power(gspca_dev);
++	if (ret)
++		gspca_err(gspca_dev, "Cannot go to low power mode: %d\n",
++			  ret);
+ 	/* Check the firmware version. */
+ 	sd->params.version.firmwareVersion = 0;
+ 	get_version_information(gspca_dev);

commit 5ceaf5452c1b2a452dadaf377f9f07af7bda9cc3
+Author: Kangjie Lu 
+Date:   Tue Dec 25 01:31:21 2018 -0500
+
+    media: usb: gspca: add a missed return-value check for do_command
+    
+    do_command() may fail. The fix adds the missed return value of
+    do_command(). If it fails, returns its error code.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/usb/gspca/cpia1.c b/drivers/media/usb/gspca/cpia1.c
+index 2b09af8865f4..23fbda56fc91 100644
+--- a/drivers/media/usb/gspca/cpia1.c
++++ b/drivers/media/usb/gspca/cpia1.c
+@@ -547,10 +547,14 @@ static int do_command(struct gspca_dev *gspca_dev, u16 command,
+ 		}
+ 		if (sd->params.qx3.button) {
+ 			/* button pressed - unlock the latch */
+-			do_command(gspca_dev, CPIA_COMMAND_WriteMCPort,
++			ret = do_command(gspca_dev, CPIA_COMMAND_WriteMCPort,
+ 				   3, 0xdf, 0xdf, 0);
+-			do_command(gspca_dev, CPIA_COMMAND_WriteMCPort,
++			if (ret)
++				return ret;
++			ret = do_command(gspca_dev, CPIA_COMMAND_WriteMCPort,
+ 				   3, 0xff, 0xff, 0);
++			if (ret)
++				return ret;
+ 		}
+ 
+ 		/* test whether microscope is cradled */

commit 0a54ea9f481f1a2ca5a171e91ddaacb75040f287
+Author: Kangjie Lu 
+Date:   Sat Dec 22 16:58:06 2018 -0600
+
+    staging: rtlwifi: rtl8822b: fix a missing check of alloc_skb
+    
+    __netdev_alloc_skb() return NULl when it fails. skb_put() further uses
+    it even when the allocation fails, leading to NULL pointer dereference.
+    The fix inserts a check for the return value of __netdev_alloc_skb().
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtlwifi/rtl8822be/fw.c b/drivers/staging/rtlwifi/rtl8822be/fw.c
+index a40396614814..f061dd1382aa 100644
+--- a/drivers/staging/rtlwifi/rtl8822be/fw.c
++++ b/drivers/staging/rtlwifi/rtl8822be/fw.c
+@@ -486,6 +486,8 @@ bool rtl8822b_halmac_cb_write_data_h2c(struct rtl_priv *rtlpriv, u8 *buf,
+ 
+ 	/* without GFP_DMA, pci_map_single() may not work */
+ 	skb = __netdev_alloc_skb(NULL, size, GFP_ATOMIC | GFP_DMA);
++	if (!skb)
++		return false;
+ 	memcpy((u8 *)skb_put(skb, size), buf, size);
+ 
+ 	return _rtl8822be_send_bcn_or_cmd_packet(rtlpriv->hw, skb, H2C_QUEUE);

commit fc6a6521556c8250e356ddc6a3f2391aa62dc976
+Author: Kangjie Lu 
+Date:   Wed Dec 26 00:43:28 2018 -0600
+
+    ath6kl: return error code in ath6kl_wmi_set_roam_lrssi_cmd()
+    
+    ath6kl_wmi_cmd_send could fail, so let's return its error code upstream.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Kalle Valo 
+
+diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
+index 9d7ac1ab2d02..68854c45d0a4 100644
+--- a/drivers/net/wireless/ath/ath6kl/wmi.c
++++ b/drivers/net/wireless/ath/ath6kl/wmi.c
+@@ -776,10 +776,8 @@ int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi)
+ 	cmd->info.params.roam_rssi_floor = DEF_LRSSI_ROAM_FLOOR;
+ 	cmd->roam_ctrl = WMI_SET_LRSSI_SCAN_PARAMS;
+ 
+-	ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_ROAM_CTRL_CMDID,
++	return ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_ROAM_CTRL_CMDID,
+ 			    NO_SYNC_WMIFLAG);
+-
+-	return 0;
+ }
+ 
+ int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid)

commit 42daad3343be4a4e1ee03e30a5f5cc731dadfef5
+Author: Kangjie Lu 
+Date:   Tue Dec 25 19:22:24 2018 -0600
+
+    brcmfmac: add a check for the status of usb_register
+    
+    usb_register() may fail, so let's check its status and issue an error
+    message if it fails.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Kalle Valo 
+
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+index a4308c6e72d7..76cfaf6999c8 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+@@ -1550,6 +1550,10 @@ void brcmf_usb_exit(void)
+ 
+ void brcmf_usb_register(void)
+ {
++	int ret;
++
+ 	brcmf_dbg(USB, "Enter\n");
+-	usb_register(&brcmf_usbdrvr);
++	ret = usb_register(&brcmf_usbdrvr);
++	if (ret)
++		brcmf_err("usb_register failed %d\n", ret);
+ }

commit 51f689cc11333944c7a457f25ec75fcb41e99410
+Author: Kangjie Lu 
+Date:   Tue Dec 25 19:26:19 2018 -0600
+
+    serial: max310x: pass return value of spi_register_driver
+    
+    spi_register_driver() may fail, so let's pass its return value upstream.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
+index 4f479841769a..eb040d8292a8 100644
+--- a/drivers/tty/serial/max310x.c
++++ b/drivers/tty/serial/max310x.c
+@@ -1467,10 +1467,10 @@ static int __init max310x_uart_init(void)
+ 		return ret;
+ 
+ #ifdef CONFIG_SPI_MASTER
+-	spi_register_driver(&max310x_spi_driver);
++	ret = spi_register_driver(&max310x_spi_driver);
+ #endif
+ 
+-	return 0;
++	return ret;
+ }
+ module_init(max310x_uart_init);
+ 

commit e85bb0beb6498c0dffe18a2f1f16d575bc175c32
+Author: Aditya Pakki 
+Date:   Mon Jan 7 11:53:59 2019 -0800
+
+    Input: ad7879 - add check for read errors in interrupt
+    
+    regmap_bulk_read() can return a non zero value on failure. The fix checks
+    if the function call succeeded before calling mod_timer. The issue was
+    identified by a static analysis tool.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Dmitry Torokhov 
+
+diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c
+index 6fa714c587b4..3a016f43fb85 100644
+--- a/drivers/input/touchscreen/ad7879.c
++++ b/drivers/input/touchscreen/ad7879.c
+@@ -246,11 +246,14 @@ static void ad7879_timer(struct timer_list *t)
+ static irqreturn_t ad7879_irq(int irq, void *handle)
+ {
+ 	struct ad7879 *ts = handle;
++	int error;
+ 
+-	regmap_bulk_read(ts->regmap, AD7879_REG_XPLUS,
+-			 ts->conversion_data, AD7879_NR_SENSE);
+-
+-	if (!ad7879_report(ts))
++	error = regmap_bulk_read(ts->regmap, AD7879_REG_XPLUS,
++				 ts->conversion_data, AD7879_NR_SENSE);
++	if (error)
++		dev_err_ratelimited(ts->dev, "failed to read %#02x: %d\n",
++				    AD7879_REG_XPLUS, error);
++	else if (!ad7879_report(ts))
+ 		mod_timer(&ts->timer, jiffies + TS_PEN_UP_TIMEOUT);
+ 
+ 	return IRQ_HANDLED;

commit 44fabd8cdaaa3acb80ad2bb3b5c61ae2136af661
+Author: Kangjie Lu 
+Date:   Tue Dec 25 20:29:48 2018 -0600
+
+    ASoC: atom: fix a missing check of snd_pcm_lib_malloc_pages
+    
+    snd_pcm_lib_malloc_pages() may fail, so let's check its status and
+    return its error code upstream.
+    
+    Signed-off-by: Kangjie Lu 
+    Acked-by: Pierre-Louis Bossart 
+    Signed-off-by: Mark Brown 
+    Cc: stable@vger.kernel.org
+
+diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
+index afc559866095..91a2436ce952 100644
+--- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c
++++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
+@@ -399,7 +399,13 @@ static int sst_media_hw_params(struct snd_pcm_substream *substream,
+ 				struct snd_pcm_hw_params *params,
+ 				struct snd_soc_dai *dai)
+ {
+-	snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
++	int ret;
++
++	ret =
++		snd_pcm_lib_malloc_pages(substream,
++				params_buffer_bytes(params));
++	if (ret)
++		return ret;
+ 	memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
+ 	return 0;
+ }

commit beae77170c60aa786f3e4599c18ead2854d8694d
+Author: Aditya Pakki 
+Date:   Sun Jan 6 11:16:00 2019 -0600
+
+    ALSA: sb: fix a missing check of snd_ctl_add
+    
+    snd_ctl_add() could fail, so let's check its return value and return its
+    error code upstream upon failure.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c
+index 37e6ce7b0b13..981d65d122b6 100644
+--- a/sound/isa/sb/sb16_main.c
++++ b/sound/isa/sb/sb16_main.c
+@@ -879,10 +879,14 @@ int snd_sb16dsp_pcm(struct snd_sb *chip, int device)
+ 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sb16_playback_ops);
+ 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sb16_capture_ops);
+ 
+-	if (chip->dma16 >= 0 && chip->dma8 != chip->dma16)
+-		snd_ctl_add(card, snd_ctl_new1(&snd_sb16_dma_control, chip));
+-	else
++	if (chip->dma16 >= 0 && chip->dma8 != chip->dma16) {
++		err = snd_ctl_add(card, snd_ctl_new1(
++					&snd_sb16_dma_control, chip));
++		if (err)
++			return err;
++	} else {
+ 		pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
++	}
+ 
+ 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ 					      snd_dma_isa_data(),

commit 02cc53e223d498010de5f114d72c11a2d55118e8
+Author: Aditya Pakki 
+Date:   Sun Jan 6 11:01:47 2019 -0600
+
+    ALSA: line6: fix check on snd_card_register
+    
+    The fix checks if snd_card_register() fails, and if so logs the error
+    via dev_err() consistent with other patches.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/usb/line6/pod.c b/sound/usb/line6/pod.c
+index 020c81818951..ce45b6dab651 100644
+--- a/sound/usb/line6/pod.c
++++ b/sound/usb/line6/pod.c
+@@ -320,7 +320,8 @@ static void pod_startup4(struct work_struct *work)
+ 	line6_read_serial_number(&pod->line6, &pod->serial_number);
+ 
+ 	/* ALSA audio interface: */
+-	snd_card_register(line6->card);
++	if (snd_card_register(line6->card))
++		dev_err(line6->ifcdev, "Failed to register POD card.\n");
+ }
+ 
+ /* POD special files: */

commit c99776cc4018e91c66bd448002e924edd4910947
+Author: Aditya Pakki 
+Date:   Sun Jan 6 10:31:44 2019 -0600
+
+    ALSA: ice1712: fix a missing check of snd_i2c_sendbytes
+    
+    snd_i2c_sendbytes could fail. The fix checks its return value: if it
+    fails, issues an error message and returns with its error code.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c
+index b8af747ecb43..7646c93e8268 100644
+--- a/sound/pci/ice1712/ews.c
++++ b/sound/pci/ice1712/ews.c
+@@ -826,7 +826,12 @@ static int snd_ice1712_6fire_read_pca(struct snd_ice1712 *ice, unsigned char reg
+ 
+ 	snd_i2c_lock(ice->i2c);
+ 	byte = reg;
+-	snd_i2c_sendbytes(spec->i2cdevs[EWS_I2C_6FIRE], &byte, 1);
++	if (snd_i2c_sendbytes(spec->i2cdevs[EWS_I2C_6FIRE], &byte, 1)) {
++		snd_i2c_unlock(ice->i2c);
++		dev_err(ice->card->dev, "cannot send pca\n");
++		return -EIO;
++	}
++
+ 	byte = 0;
+ 	if (snd_i2c_readbytes(spec->i2cdevs[EWS_I2C_6FIRE], &byte, 1) != 1) {
+ 		snd_i2c_unlock(ice->i2c);

commit 0f25e000cb4398081748e54f62a902098aa79ec1
+Author: Kangjie Lu 
+Date:   Tue Dec 25 19:40:51 2018 -0600
+
+    ALSA: gus: add a check of the status of snd_ctl_add
+    
+    snd_ctl_add() could fail, so let's check its status and issue an error
+    message if it indeed fails.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c
+index 3b8a0c880db5..33c8b66d5c8a 100644
+--- a/sound/isa/gus/gus_main.c
++++ b/sound/isa/gus/gus_main.c
+@@ -92,8 +92,17 @@ static const struct snd_kcontrol_new snd_gus_joystick_control = {
+ 
+ static void snd_gus_init_control(struct snd_gus_card *gus)
+ {
+-	if (!gus->ace_flag)
+-		snd_ctl_add(gus->card, snd_ctl_new1(&snd_gus_joystick_control, gus));
++	int ret;
++
++	if (!gus->ace_flag) {
++		ret =
++			snd_ctl_add(gus->card,
++					snd_ctl_new1(&snd_gus_joystick_control,
++						gus));
++		if (ret)
++			snd_printk(KERN_ERR "gus: snd_ctl_add failed: %d\n",
++					ret);
++	}
+ }
+ 
+ /*

commit c8c2702409430a6a2fd928e857f15773aaafcc99
+Author: Aditya Pakki 
+Date:   Sat Jan 5 08:14:41 2019 -0600
+
+    Staging: rts5208: Fix error handling on rtsx_send_cmd
+    
+    In sd_execute_write_data, the rtsx_send_cmd could fail with ETIMEDOUT
+    or EIO. The fix adds a check to handle these failures.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rts5208/sd.c b/drivers/staging/rts5208/sd.c
+index 2c47ae613ea1..c256a2398651 100644
+--- a/drivers/staging/rts5208/sd.c
++++ b/drivers/staging/rts5208/sd.c
+@@ -4437,7 +4437,12 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+ 		rtsx_init_cmd(chip);
+ 		rtsx_add_cmd(chip, CHECK_REG_CMD, 0xFD30, 0x02, 0x02);
+ 
+-		rtsx_send_cmd(chip, SD_CARD, 250);
++		retval = rtsx_send_cmd(chip, SD_CARD, 250);
++		if (retval < 0) {
++			write_err = true;
++			rtsx_clear_sd_error(chip);
++			goto sd_execute_write_cmd_failed;
++		}
+ 
+ 		retval = sd_update_lock_status(chip);
+ 		if (retval != STATUS_SUCCESS) {

commit 73b69c01cc925d9c48e5b4f78e3d8b88c4e5b924
+Author: Aditya Pakki 
+Date:   Thu Dec 27 13:35:53 2018 -0600
+
+    staging: rts5208: Add a check for ms_read_extra_data
+    
+    In ms_copy_page, the function ms_read_extra_data may fail for many
+    reasons. The fix adds a check similar to other invocation to return
+    error upstream.
+    
+    Signed-off-by: Aditya Pakki 
+    Reviewed-by: Dan Carpenter 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c
+index e43f92080c20..1128eec3bd08 100644
+--- a/drivers/staging/rts5208/ms.c
++++ b/drivers/staging/rts5208/ms.c
+@@ -1665,7 +1665,10 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
+ 			return STATUS_FAIL;
+ 		}
+ 
+-		ms_read_extra_data(chip, old_blk, i, extra, MS_EXTRA_SIZE);
++		retval = ms_read_extra_data(chip, old_blk, i, extra,
++					    MS_EXTRA_SIZE);
++		if (retval != STATUS_SUCCESS)
++			return STATUS_FAIL;
+ 
+ 		retval = ms_set_rw_reg_addr(chip, OverwriteFlag,
+ 					    MS_EXTRA_SIZE, SystemParm, 6);

commit 906b40b246b0acb54c4dc97e815cf734761c9820
+Author: Aditya Pakki 
+Date:   Fri Dec 28 13:26:41 2018 -0600
+
+    dmaengine: stm32-mdma: Add a check on read_u32_array
+    
+    In stm32_mdma_probe, after reading the property "st,ahb-addr-masks", the
+    second call is not checked for failure. This time of check to time of use
+    case of "count" error is sent upstream.
+    
+    Signed-off-by: Aditya Pakki 
+    Acked-by: Pierre-Yves MORDRET 
+    Signed-off-by: Vinod Koul 
+
+diff --git a/drivers/dma/stm32-mdma.c b/drivers/dma/stm32-mdma.c
+index 390e4cae0e1a..485dea177704 100644
+--- a/drivers/dma/stm32-mdma.c
++++ b/drivers/dma/stm32-mdma.c
+@@ -1579,9 +1579,11 @@ static int stm32_mdma_probe(struct platform_device *pdev)
+ 
+ 	dmadev->nr_channels = nr_channels;
+ 	dmadev->nr_requests = nr_requests;
+-	device_property_read_u32_array(&pdev->dev, "st,ahb-addr-masks",
++	ret = device_property_read_u32_array(&pdev->dev, "st,ahb-addr-masks",
+ 				       dmadev->ahb_addr_masks,
+ 				       count);
++	if (ret)
++		return ret;
+ 	dmadev->nr_ahb_addr_masks = count;
+ 
+ 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

commit a474b3f0428d6b02a538aa10b3c3b722751cb382
+Author: Aditya Pakki 
+Date:   Fri Dec 28 14:11:19 2018 -0600
+
+    dmaengine: qcom_hidma: Check for driver register failure
+    
+    While initializing the driver, the function platform_driver_register can
+    fail and return an error. Consistent with other invocations, this patch
+    returns the error upstream.
+    
+    Signed-off-by: Aditya Pakki 
+    Acked-by: Sinan Kaya 
+    Signed-off-by: Vinod Koul 
+
+diff --git a/drivers/dma/qcom/hidma_mgmt.c b/drivers/dma/qcom/hidma_mgmt.c
+index d64edeb6771a..681de12f4c67 100644
+--- a/drivers/dma/qcom/hidma_mgmt.c
++++ b/drivers/dma/qcom/hidma_mgmt.c
+@@ -423,9 +423,8 @@ static int __init hidma_mgmt_init(void)
+ 		hidma_mgmt_of_populate_channels(child);
+ 	}
+ #endif
+-	platform_driver_register(&hidma_mgmt_driver);
++	return platform_driver_register(&hidma_mgmt_driver);
+ 
+-	return 0;
+ }
+ module_init(hidma_mgmt_init);
+ MODULE_LICENSE("GPL v2");

commit 7c97381e7a9a5ec359007c0d491a143e3d9f787c
+Author: Aditya Pakki 
+Date:   Mon Dec 24 11:41:54 2018 -0600
+
+    dmaengine: mv_xor: Fix a missing check in mv_xor_channel_add
+    
+    dma_async_device_register() may fail and return an error. The capabilities
+    checked in mv_xor_channel_add() are not complete. The fix handles the
+    error by freeing the resources.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Vinod Koul 
+
+diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
+index 7f595355fb79..e733c5eeaabc 100644
+--- a/drivers/dma/mv_xor.c
++++ b/drivers/dma/mv_xor.c
+@@ -1153,7 +1153,10 @@ mv_xor_channel_add(struct mv_xor_device *xordev,
+ 		 dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask) ? "cpy " : "",
+ 		 dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask) ? "intr " : "");
+ 
+-	dma_async_device_register(dma_dev);
++	ret = dma_async_device_register(dma_dev);
++	if (ret)
++		goto err_free_irq;
++
+ 	return mv_chan;
+ 
+ err_free_irq:

commit 7fc93f3285b17f4632694efce5ff0160303388a8
+Author: Aditya Pakki 
+Date:   Thu Dec 27 13:54:52 2018 -0600
+
+    iio: adc: xilinx: check return value of xadc_write_adc_reg
+    
+    In function xadc_probe, xadc_write_adc_reg can return an error value
+    when write fails. The fix checks for the return value consistent with
+    other invocations of the latter function.
+    
+    Signed-off-by: Aditya Pakki 
+    Reviewed-by: Michal Simek 
+    Signed-off-by: Jonathan Cameron 
+
+diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c
+index 3f6be5ac049a..b13c61539d46 100644
+--- a/drivers/iio/adc/xilinx-xadc-core.c
++++ b/drivers/iio/adc/xilinx-xadc-core.c
+@@ -1273,8 +1273,10 @@ static int xadc_probe(struct platform_device *pdev)
+ 			xadc->threshold[i] = 0xffff;
+ 		else
+ 			xadc->threshold[i] = 0;
+-		xadc_write_adc_reg(xadc, XADC_REG_THRESHOLD(i),
++		ret = xadc_write_adc_reg(xadc, XADC_REG_THRESHOLD(i),
+ 			xadc->threshold[i]);
++		if (ret)
++			goto err_free_irq;
+ 	}
+ 
+ 	/* Go to non-buffered mode */

commit ae0b3773721f08526c850e2d8dec85bdb870cd12
+Author: Kangjie Lu 
+Date:   Thu Dec 20 01:21:22 2018 -0600
+
+    iio: ad9523: fix a missing check of return value
+    
+    If ad9523_write() fails, indio_dev may get incorrect data. The fix
+    inserts a check for the return value of ad9523_write(), and it fails,
+    returns an error.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Jonathan Cameron 
+
+diff --git a/drivers/iio/frequency/ad9523.c b/drivers/iio/frequency/ad9523.c
+index f3f94fbdd20a..3f9be69499ec 100644
+--- a/drivers/iio/frequency/ad9523.c
++++ b/drivers/iio/frequency/ad9523.c
+@@ -943,11 +943,14 @@ static int ad9523_setup(struct iio_dev *indio_dev)
+ 		}
+ 	}
+ 
+-	for_each_clear_bit(i, &active_mask, AD9523_NUM_CHAN)
+-		ad9523_write(indio_dev,
++	for_each_clear_bit(i, &active_mask, AD9523_NUM_CHAN) {
++		ret = ad9523_write(indio_dev,
+ 			     AD9523_CHANNEL_CLOCK_DIST(i),
+ 			     AD9523_CLK_DIST_DRIVER_MODE(TRISTATE) |
+ 			     AD9523_CLK_DIST_PWR_DOWN_EN);
++		if (ret < 0)
++			return ret;
++	}
+ 
+ 	ret = ad9523_write(indio_dev, AD9523_POWER_DOWN_CTRL, 0);
+ 	if (ret < 0)

commit 6ae16dfb61bce538d48b7fe98160fada446056c5
+Author: Aditya Pakki 
+Date:   Mon Dec 24 15:39:14 2018 -0600
+
+    HID: lenovo: Add checks to fix of_led_classdev_register
+    
+    In lenovo_probe_tpkbd(), the function of_led_classdev_register() could
+    return an error value that is unchecked. The fix adds these checks.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: Jiri Kosina 
+
+diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
+index 643b6eb54442..eacc76d2ab96 100644
+--- a/drivers/hid/hid-lenovo.c
++++ b/drivers/hid/hid-lenovo.c
+@@ -743,7 +743,9 @@ static int lenovo_probe_tpkbd(struct hid_device *hdev)
+ 	data_pointer->led_mute.brightness_get = lenovo_led_brightness_get_tpkbd;
+ 	data_pointer->led_mute.brightness_set = lenovo_led_brightness_set_tpkbd;
+ 	data_pointer->led_mute.dev = dev;
+-	led_classdev_register(dev, &data_pointer->led_mute);
++	ret = led_classdev_register(dev, &data_pointer->led_mute);
++	if (ret < 0)
++		goto err;
+ 
+ 	data_pointer->led_micmute.name = name_micmute;
+ 	data_pointer->led_micmute.brightness_get =
+@@ -751,7 +753,11 @@ static int lenovo_probe_tpkbd(struct hid_device *hdev)
+ 	data_pointer->led_micmute.brightness_set =
+ 		lenovo_led_brightness_set_tpkbd;
+ 	data_pointer->led_micmute.dev = dev;
+-	led_classdev_register(dev, &data_pointer->led_micmute);
++	ret = led_classdev_register(dev, &data_pointer->led_micmute);
++	if (ret < 0) {
++		led_classdev_unregister(&data_pointer->led_mute);
++		goto err;
++	}
+ 
+ 	lenovo_features_set_tpkbd(hdev);
+ 

commit 9e28989d41c0eab57ec0bb156617a8757406ff8a
+Author: Kangjie Lu 
+Date:   Thu Dec 20 15:12:11 2018 -0600
+
+    mfd: mc13xxx: Fix a missing check of a register-read failure
+    
+    When mc13xxx_reg_read() fails, "old_adc0" is uninitialized and will
+    contain random value. Further execution uses "old_adc0" even when
+    mc13xxx_reg_read() fails.
+    The fix checks the return value of mc13xxx_reg_read(), and exits
+    the execution when it fails.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Lee Jones 
+
+diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c
+index f475e848252f..d0bf50e3568d 100644
+--- a/drivers/mfd/mc13xxx-core.c
++++ b/drivers/mfd/mc13xxx-core.c
+@@ -274,7 +274,9 @@ int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, unsigned int mode,
+ 
+ 	mc13xxx->adcflags |= MC13XXX_ADC_WORKING;
+ 
+-	mc13xxx_reg_read(mc13xxx, MC13XXX_ADC0, &old_adc0);
++	ret = mc13xxx_reg_read(mc13xxx, MC13XXX_ADC0, &old_adc0);
++	if (ret)
++		goto out;
+ 
+ 	adc0 = MC13XXX_ADC0_ADINC1 | MC13XXX_ADC0_ADINC2 |
+ 	       MC13XXX_ADC0_CHRGRAWDIV;

commit 9c6260de505b63638dd86fcc33849b17f6146d94
+Author: Aditya Pakki 
+Date:   Mon Dec 24 12:24:45 2018 -0600
+
+    infiniband/qedr: Potential null ptr dereference of qp
+    
+    idr_find() may fail and return a NULL pointer. The fix checks the return
+    value of the function and returns an error in case of NULL.
+    
+    Signed-off-by: Aditya Pakki 
+    Acked-by: Michal Kalderon 
+    Signed-off-by: Jason Gunthorpe 
+
+diff --git a/drivers/infiniband/hw/qedr/qedr_iw_cm.c b/drivers/infiniband/hw/qedr/qedr_iw_cm.c
+index 505fa3648762..93b16237b767 100644
+--- a/drivers/infiniband/hw/qedr/qedr_iw_cm.c
++++ b/drivers/infiniband/hw/qedr/qedr_iw_cm.c
+@@ -492,6 +492,8 @@ int qedr_iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+ 	int i;
+ 
+ 	qp = idr_find(&dev->qpidr.idr, conn_param->qpn);
++	if (unlikely(!qp))
++		return -EINVAL;
+ 
+ 	laddr = (struct sockaddr_in *)&cm_id->m_local_addr;
+ 	raddr = (struct sockaddr_in *)&cm_id->m_remote_addr;

commit 94edd87a1c59f3efa6fdf4e98d6d492e6cec6173
+Author: Aditya Pakki 
+Date:   Wed Dec 26 12:56:22 2018 -0600
+
+    infiniband: bnxt_re: qplib: Check the return value of send_message
+    
+    In bnxt_qplib_map_tc2cos(), bnxt_qplib_rcfw_send_message() can return an
+    error value but it is lost. Propagate this error to the callers.
+    
+    Signed-off-by: Aditya Pakki 
+    Acked-By: Devesh Sharma 
+    Signed-off-by: Jason Gunthorpe 
+
+diff --git a/drivers/infiniband/hw/bnxt_re/qplib_sp.c b/drivers/infiniband/hw/bnxt_re/qplib_sp.c
+index be03b5738f71..efa0f2949dc7 100644
+--- a/drivers/infiniband/hw/bnxt_re/qplib_sp.c
++++ b/drivers/infiniband/hw/bnxt_re/qplib_sp.c
+@@ -780,9 +780,8 @@ int bnxt_qplib_map_tc2cos(struct bnxt_qplib_res *res, u16 *cids)
+ 	req.cos0 = cpu_to_le16(cids[0]);
+ 	req.cos1 = cpu_to_le16(cids[1]);
+ 
+-	bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, NULL,
+-				     0);
+-	return 0;
++	return bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
++						NULL, 0);
+ }
+ 
+ int bnxt_qplib_get_roce_stats(struct bnxt_qplib_rcfw *rcfw,

commit 093c48213ee37c3c3ff1cf5ac1aa2a9d8bc66017
+Author: Wenwen Wang 
+Date:   Wed Dec 26 20:15:13 2018 -0600
+
+    gdrom: fix a memory leak bug
+    
+    In probe_gdrom(), the buffer pointed by 'gd.cd_info' is allocated through
+    kzalloc() and is used to hold the information of the gdrom device. To
+    register and unregister the device, the pointer 'gd.cd_info' is passed to
+    the functions register_cdrom() and unregister_cdrom(), respectively.
+    However, this buffer is not freed after it is used, which can cause a
+    memory leak bug.
+    
+    This patch simply frees the buffer 'gd.cd_info' in exit_gdrom() to fix the
+    above issue.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c
+index a5b8afe3609c..f8b7345fe1cb 100644
+--- a/drivers/cdrom/gdrom.c
++++ b/drivers/cdrom/gdrom.c
+@@ -873,6 +873,7 @@ static void __exit exit_gdrom(void)
+ 	platform_device_unregister(pd);
+ 	platform_driver_unregister(&gdrom_driver);
+ 	kfree(gd.toc);
++	kfree(gd.cd_info);
+ }
+ 
+ module_init(init_gdrom);

commit eb8950861c1bfd3eecc8f6faad213e3bca0dc395
+Author: Kangjie Lu 
+Date:   Fri Dec 21 00:46:23 2018 -0600
+
+    netfilter: nf_tables: fix a missing check of nla_put_failure
+    
+    If nla_nest_start() may fail. The fix checks its return value and goes
+    to nla_put_failure if it fails.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Pablo Neira Ayuso 
+
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index fec814dace5a..2b0a93300dd7 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -5727,6 +5727,8 @@ static int nf_tables_fill_flowtable_info(struct sk_buff *skb, struct net *net,
+ 		goto nla_put_failure;
+ 
+ 	nest = nla_nest_start(skb, NFTA_FLOWTABLE_HOOK);
++	if (!nest)
++		goto nla_put_failure;
+ 	if (nla_put_be32(skb, NFTA_FLOWTABLE_HOOK_NUM, htonl(flowtable->hooknum)) ||
+ 	    nla_put_be32(skb, NFTA_FLOWTABLE_HOOK_PRIORITY, htonl(flowtable->priority)))
+ 		goto nla_put_failure;

commit 92ee77d148bf06d8c52664be4d1b862583fd5c0e
+Author: Kangjie Lu 
+Date:   Wed Dec 26 00:31:08 2018 -0600
+
+    net: marvell: fix a missing check of acpi_match_device
+    
+    When acpi_match_device fails, its return value is NULL. Directly using
+    the return value without a check may result in a NULL-pointer
+    dereference. The fix checks if acpi_match_device fails, and if so,
+    returns -EINVAL.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+index f1dab0b55769..c9444346475b 100644
+--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
++++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+@@ -5255,6 +5255,8 @@ static int mvpp2_probe(struct platform_device *pdev)
+ 	if (has_acpi_companion(&pdev->dev)) {
+ 		acpi_id = acpi_match_device(pdev->dev.driver->acpi_match_table,
+ 					    &pdev->dev);
++		if (!acpi_id)
++			return -EINVAL;
+ 		priv->hw_version = (unsigned long)acpi_id->driver_data;
+ 	} else {
+ 		priv->hw_version =

commit 46273cf7e009231d2b6bc10a926e82b8928a9fb2
+Author: Kangjie Lu 
+Date:   Wed Dec 26 00:09:04 2018 -0600
+
+    tipc: fix a missing check of genlmsg_put
+    
+    genlmsg_put could fail. The fix inserts a check of its return value, and
+    if it fails, returns -EMSGSIZE.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c
+index 21f6ccc89401..40f5cae623a7 100644
+--- a/net/tipc/netlink_compat.c
++++ b/net/tipc/netlink_compat.c
+@@ -904,6 +904,8 @@ static int tipc_nl_compat_publ_dump(struct tipc_nl_compat_msg *msg, u32 sock)
+ 
+ 	hdr = genlmsg_put(args, 0, 0, &tipc_genl_family, NLM_F_MULTI,
+ 			  TIPC_NL_PUBL_GET);
++	if (!hdr)
++		return -EMSGSIZE;
+ 
+ 	nest = nla_nest_start(args, TIPC_NLA_SOCK);
+ 	if (!nest) {

commit ff07d48d7bc0974d4f96a85a4df14564fb09f1ef
+Author: Kangjie Lu 
+Date:   Tue Dec 25 22:23:19 2018 -0600
+
+    atl1e: checking the status of atl1e_write_phy_reg
+    
+    atl1e_write_phy_reg() could fail. The fix issues an error message when
+    it fails.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+index 9dc6da039a6d..3164aad29bcf 100644
+--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
++++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+@@ -473,7 +473,9 @@ static void atl1e_mdio_write(struct net_device *netdev, int phy_id,
+ {
+ 	struct atl1e_adapter *adapter = netdev_priv(netdev);
+ 
+-	atl1e_write_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, val);
++	if (atl1e_write_phy_reg(&adapter->hw,
++				reg_num & MDIO_REG_ADDR_MASK, val))
++		netdev_err(netdev, "write phy register failed\n");
+ }
+ 
+ static int atl1e_mii_ioctl(struct net_device *netdev,

commit e49505f7255be8ced695919c08a29bf2c3d79616
+Author: Kangjie Lu 
+Date:   Tue Dec 25 22:08:18 2018 -0600
+
+    net: dsa: bcm_sf2: Propagate error value from mdio_write
+    
+    Both bcm_sf2_sw_indir_rw and mdiobus_write_nested could fail, so let's
+    return their error codes upstream.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
+index aa4a1f5206f1..361fbde76654 100644
+--- a/drivers/net/dsa/bcm_sf2.c
++++ b/drivers/net/dsa/bcm_sf2.c
+@@ -303,11 +303,10 @@ static int bcm_sf2_sw_mdio_write(struct mii_bus *bus, int addr, int regnum,
+ 	 * send them to our master MDIO bus controller
+ 	 */
+ 	if (addr == BRCM_PSEUDO_PHY_ADDR && priv->indir_phy_mask & BIT(addr))
+-		bcm_sf2_sw_indir_rw(priv, 0, addr, regnum, val);
++		return bcm_sf2_sw_indir_rw(priv, 0, addr, regnum, val);
+ 	else
+-		mdiobus_write_nested(priv->master_mii_bus, addr, regnum, val);
+-
+-	return 0;
++		return mdiobus_write_nested(priv->master_mii_bus, addr,
++				regnum, val);
+ }
+ 
+ static irqreturn_t bcm_sf2_switch_0_isr(int irq, void *dev_id)

commit f86a3b83833e7cfe558ca4d70b64ebc48903efec
+Author: Kangjie Lu 
+Date:   Tue Dec 25 20:57:14 2018 -0600
+
+    net: stmicro: fix a missing check of clk_prepare
+    
+    clk_prepare() could fail, so let's check its status, and if it fails,
+    return its error code upstream.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
+index d07520fb969e..62ccbd47c1db 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
+@@ -59,7 +59,9 @@ static int sun7i_gmac_init(struct platform_device *pdev, void *priv)
+ 		gmac->clk_enabled = 1;
+ 	} else {
+ 		clk_set_rate(gmac->tx_clk, SUN7I_GMAC_MII_RATE);
+-		clk_prepare(gmac->tx_clk);
++		ret = clk_prepare(gmac->tx_clk);
++		if (ret)
++			return ret;
+ 	}
+ 
+ 	return 0;

commit 2d822f2dbab7f4c820f72eb8570aacf3f35855bd
+Author: Kangjie Lu 
+Date:   Tue Dec 25 20:55:37 2018 -0600
+
+    net: (cpts) fix a missing check of clk_prepare
+    
+    clk_prepare() could fail, so let's check its status, and if it fails,
+    return its error code upstream.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c
+index 054f78295d1d..2a9ba4acd7fa 100644
+--- a/drivers/net/ethernet/ti/cpts.c
++++ b/drivers/net/ethernet/ti/cpts.c
+@@ -590,7 +590,9 @@ struct cpts *cpts_create(struct device *dev, void __iomem *regs,
+ 		return ERR_CAST(cpts->refclk);
+ 	}
+ 
+-	clk_prepare(cpts->refclk);
++	ret = clk_prepare(cpts->refclk);
++	if (ret)
++		return ERR_PTR(ret);
+ 
+ 	cpts->cc.read = cpts_systim_read;
+ 	cpts->cc.mask = CLOCKSOURCE_MASK(32);

commit 26fd962bde0b15e54234fe762d86bc0349df1de4
+Author: Kangjie Lu 
+Date:   Tue Dec 25 01:56:14 2018 -0600
+
+    niu: fix missing checks of niu_pci_eeprom_read
+    
+    niu_pci_eeprom_read() may fail, so we should check its return value
+    before using the read data.
+    
+    Signed-off-by: Kangjie Lu 
+    Acked-by: Shannon Nelson 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c
+index 9319d84bf49f..d84501441edd 100644
+--- a/drivers/net/ethernet/sun/niu.c
++++ b/drivers/net/ethernet/sun/niu.c
+@@ -8100,6 +8100,8 @@ static int niu_pci_vpd_scan_props(struct niu *np, u32 start, u32 end)
+ 		start += 3;
+ 
+ 		prop_len = niu_pci_eeprom_read(np, start + 4);
++		if (prop_len < 0)
++			return prop_len;
+ 		err = niu_pci_vpd_get_propname(np, start + 5, namebuf, 64);
+ 		if (err < 0)
+ 			return err;
+@@ -8144,8 +8146,12 @@ static int niu_pci_vpd_scan_props(struct niu *np, u32 start, u32 end)
+ 			netif_printk(np, probe, KERN_DEBUG, np->dev,
+ 				     "VPD_SCAN: Reading in property [%s] len[%d]\n",
+ 				     namebuf, prop_len);
+-			for (i = 0; i < prop_len; i++)
+-				*prop_buf++ = niu_pci_eeprom_read(np, off + i);
++			for (i = 0; i < prop_len; i++) {
++				err = niu_pci_eeprom_read(np, off + i);
++				if (err >= 0)
++					*prop_buf = err;
++				++prop_buf;
++			}
+ 		}
+ 
+ 		start += len;

commit ca19fcb6285bfce1601c073bf4b9d2942e2df8d9
+Author: Aditya Pakki 
+Date:   Mon Dec 24 15:21:21 2018 -0600
+
+    net: chelsio: Add a missing check on cudg_get_buffer
+    
+    cudbg_collect_hw_sched() could fail when the function cudg_get_buffer()
+    returns an error. The fix adds a check to the latter function returning
+    error on failure
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c b/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c
+index 7c49681407ad..127b1f624413 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c
++++ b/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c
+@@ -1229,6 +1229,10 @@ int cudbg_collect_hw_sched(struct cudbg_init *pdbg_init,
+ 
+ 	rc = cudbg_get_buff(pdbg_init, dbg_buff, sizeof(struct cudbg_hw_sched),
+ 			    &temp_buff);
++
++	if (rc)
++		return rc;
++
+ 	hw_sched_buff = (struct cudbg_hw_sched *)temp_buff.data;
+ 	hw_sched_buff->map = t4_read_reg(padap, TP_TX_MOD_QUEUE_REQ_MAP_A);
+ 	hw_sched_buff->mode = TIMERMODE_G(t4_read_reg(padap, TP_MOD_CONFIG_A));

commit f0fb9b288d0a7e9cc324ae362e2dfd2cc2217ded
+Author: Aditya Pakki 
+Date:   Mon Dec 24 10:30:17 2018 -0600
+
+    ipv6/route: Add a missing check on proc_dointvec
+    
+    While flushing the cache via  ipv6_sysctl_rtcache_flush(), the call
+    to proc_dointvec() may fail. The fix adds a check that returns the
+    error, on failure.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv6/route.c b/net/ipv6/route.c
+index 194bc162866d..a94e0b02a8ac 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -5054,12 +5054,16 @@ int ipv6_sysctl_rtcache_flush(struct ctl_table *ctl, int write,
+ {
+ 	struct net *net;
+ 	int delay;
++	int ret;
+ 	if (!write)
+ 		return -EINVAL;
+ 
+ 	net = (struct net *)ctl->extra1;
+ 	delay = net->ipv6.sysctl.flush_delay;
+-	proc_dointvec(ctl, write, buffer, lenp, ppos);
++	ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
++	if (ret)
++		return ret;
++
+ 	fib6_run_gc(delay <= 0 ? 0 : (unsigned long)delay, net, delay > 0);
+ 	return 0;
+ }

commit 0eb987c874dc93f9c9d85a6465dbde20fdd3884c
+Author: Aditya Pakki 
+Date:   Sun Dec 23 19:42:38 2018 -0600
+
+    net/net_namespace: Check the return value of register_pernet_subsys()
+    
+    In net_ns_init(), register_pernet_subsys() could fail while registering
+    network namespace subsystems. The fix checks the return value and
+    sends a panic() on failure.
+    
+    Signed-off-by: Aditya Pakki 
+    Reviewed-by: Kirill Tkhai 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
+index fefe72774aeb..af8849a7a9c3 100644
+--- a/net/core/net_namespace.c
++++ b/net/core/net_namespace.c
+@@ -917,7 +917,8 @@ static int __init net_ns_init(void)
+ 	init_net_initialized = true;
+ 	up_write(&pernet_ops_rwsem);
+ 
+-	register_pernet_subsys(&net_ns_ops);
++	if (register_pernet_subsys(&net_ns_ops))
++		panic("Could not register network namespace subsystems");
+ 
+ 	rtnl_register(PF_UNSPEC, RTM_NEWNSID, rtnl_net_newid, NULL,
+ 		      RTNL_FLAG_DOIT_UNLOCKED);

commit 89dfd0083751d00d5d7ead36f6d8b045bf89c5e1
+Author: Aditya Pakki 
+Date:   Sun Dec 23 18:54:53 2018 -0600
+
+    net/netlink_compat: Fix a missing check of nla_parse_nested
+    
+    In tipc_nl_compat_sk_dump(), if nla_parse_nested() fails, it could return
+    an error. To be consistent with other invocations of the function call,
+    on error, the fix passes the return value upstream.
+    
+    Signed-off-by: Aditya Pakki 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c
+index 6376467e78f8..21f6ccc89401 100644
+--- a/net/tipc/netlink_compat.c
++++ b/net/tipc/netlink_compat.c
+@@ -951,8 +951,11 @@ static int tipc_nl_compat_sk_dump(struct tipc_nl_compat_msg *msg,
+ 		u32 node;
+ 		struct nlattr *con[TIPC_NLA_CON_MAX + 1];
+ 
+-		nla_parse_nested(con, TIPC_NLA_CON_MAX,
+-				 sock[TIPC_NLA_SOCK_CON], NULL, NULL);
++		err = nla_parse_nested(con, TIPC_NLA_CON_MAX,
++				       sock[TIPC_NLA_SOCK_CON], NULL, NULL);
++
++		if (err)
++			return err;
+ 
+ 		node = nla_get_u32(con[TIPC_NLA_CON_NODE]);
+ 		tipc_tlv_sprintf(msg->rep, "  connected to <%u.%u.%u:%u>",

commit 9aa3aa15f4c2f74f47afd6c5db4b420fadf3f315
+Author: Kangjie Lu 
+Date:   Fri Dec 21 13:10:39 2018 -0600
+
+    hwmon: (lm80) fix a missing check of bus read in lm80 probe
+    
+    In lm80_probe(), if lm80_read_value() fails, it returns a negative
+    error number which is stored to data->fan[f_min] and will be further
+    used. We should avoid using the data if the read fails.
+    
+    The fix checks if lm80_read_value() fails, and if so, returns with the
+    error number.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Guenter Roeck 
+
+diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c
+index 04f9df0d2341..0e30fa00204c 100644
+--- a/drivers/hwmon/lm80.c
++++ b/drivers/hwmon/lm80.c
+@@ -628,6 +628,7 @@ static int lm80_probe(struct i2c_client *client,
+ 	struct device *dev = &client->dev;
+ 	struct device *hwmon_dev;
+ 	struct lm80_data *data;
++	int rv;
+ 
+ 	data = devm_kzalloc(dev, sizeof(struct lm80_data), GFP_KERNEL);
+ 	if (!data)
+@@ -640,8 +641,14 @@ static int lm80_probe(struct i2c_client *client,
+ 	lm80_init_client(client);
+ 
+ 	/* A few vars need to be filled upon startup */
+-	data->fan[f_min][0] = lm80_read_value(client, LM80_REG_FAN_MIN(1));
+-	data->fan[f_min][1] = lm80_read_value(client, LM80_REG_FAN_MIN(2));
++	rv = lm80_read_value(client, LM80_REG_FAN_MIN(1));
++	if (rv < 0)
++		return rv;
++	data->fan[f_min][0] = rv;
++	rv = lm80_read_value(client, LM80_REG_FAN_MIN(2));
++	if (rv < 0)
++		return rv;
++	data->fan[f_min][1] = rv;
+ 
+ 	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ 							   data, lm80_groups);

commit c9c63915519b1def7043b184680f33c24cd49d7b
+Author: Kangjie Lu 
+Date:   Fri Dec 21 13:01:33 2018 -0600
+
+    hwmon: (lm80) fix a missing check of the status of SMBus read
+    
+    If lm80_read_value() fails, it returns a negative number instead of the
+    correct read data. Therefore, we should avoid using the data if it
+    fails.
+    
+    The fix checks if lm80_read_value() fails, and if so, returns with the
+    error number.
+    
+    Signed-off-by: Kangjie Lu 
+    [groeck: One variable for return values is enough]
+    Signed-off-by: Guenter Roeck 
+
+diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c
+index 08e3945a6fbf..04f9df0d2341 100644
+--- a/drivers/hwmon/lm80.c
++++ b/drivers/hwmon/lm80.c
+@@ -360,9 +360,11 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
+ 	struct i2c_client *client = data->client;
+ 	unsigned long min, val;
+ 	u8 reg;
+-	int err = kstrtoul(buf, 10, &val);
+-	if (err < 0)
+-		return err;
++	int rv;
++
++	rv = kstrtoul(buf, 10, &val);
++	if (rv < 0)
++		return rv;
+ 
+ 	/* Save fan_min */
+ 	mutex_lock(&data->update_lock);
+@@ -390,8 +392,11 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
+ 		return -EINVAL;
+ 	}
+ 
+-	reg = (lm80_read_value(client, LM80_REG_FANDIV) &
+-	       ~(3 << (2 * (nr + 1)))) | (data->fan_div[nr] << (2 * (nr + 1)));
++	rv = lm80_read_value(client, LM80_REG_FANDIV);
++	if (rv < 0)
++		return rv;
++	reg = (rv & ~(3 << (2 * (nr + 1))))
++	    | (data->fan_div[nr] << (2 * (nr + 1)));
+ 	lm80_write_value(client, LM80_REG_FANDIV, reg);
+ 
+ 	/* Restore fan_min */

commit d134e486e831defd26130770181f01dfc6195f7d
+Author: Kangjie Lu 
+Date:   Fri Dec 21 00:22:32 2018 -0600
+
+    net: netxen: fix a missing check and an uninitialized use
+    
+    When netxen_rom_fast_read() fails, "bios" is left uninitialized and may
+    contain random value, thus should not be used.
+    
+    The fix ensures that if netxen_rom_fast_read() fails, we return "-EIO".
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
+index 0ea141ece19e..6547a9dd5935 100644
+--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
++++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
+@@ -1125,7 +1125,8 @@ netxen_validate_firmware(struct netxen_adapter *adapter)
+ 		return -EINVAL;
+ 	}
+ 	val = nx_get_bios_version(adapter);
+-	netxen_rom_fast_read(adapter, NX_BIOS_VERSION_OFFSET, (int *)&bios);
++	if (netxen_rom_fast_read(adapter, NX_BIOS_VERSION_OFFSET, (int *)&bios))
++		return -EIO;
+ 	if ((__force u32)val != bios) {
+ 		dev_err(&pdev->dev, "%s: firmware bios is incompatible\n",
+ 				fw_name[fw_type]);

commit cd07e3701fa6a4c68f8493ee1d12caa18d46ec6a
+Author: Kangjie Lu 
+Date:   Fri Dec 21 00:29:19 2018 -0600
+
+    regulator: tps65910: fix a missing check of return value
+    
+    tps65910_reg_set_bits() may fail. The fix checks if it fails, and if so,
+    returns with its error code.
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Mark Brown 
+
+diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c
+index 02ccdaa226a7..5ebb6ee73f07 100644
+--- a/drivers/regulator/tps65910-regulator.c
++++ b/drivers/regulator/tps65910-regulator.c
+@@ -1102,8 +1102,10 @@ static int tps65910_probe(struct platform_device *pdev)
+ 	platform_set_drvdata(pdev, pmic);
+ 
+ 	/* Give control of all register to control port */
+-	tps65910_reg_set_bits(pmic->mfd, TPS65910_DEVCTRL,
++	err = tps65910_reg_set_bits(pmic->mfd, TPS65910_DEVCTRL,
+ 				DEVCTRL_SR_CTL_I2C_SEL_MASK);
++	if (err < 0)
++		return err;
+ 
+ 	switch (tps65910_chip_id(tps65910)) {
+ 	case TPS65910:

commit 966e927bf8cc6a44f8b72582a1d6d3ffc73b12ad
+Author: Kangjie Lu 
+Date:   Tue Dec 18 23:04:13 2018 -0600
+
+    drivers/regulator: fix a missing check of return value
+    
+    If palmas_smps_read() fails, we should not use the read data in "reg"
+    which may contain random value. The fix inserts a check for the return
+    value of palmas_smps_read(): If it fails, we return the error code
+    upstream and stop using "reg".
+    
+    Signed-off-by: Kangjie Lu 
+    Signed-off-by: Mark Brown 
+
+diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c
+index bb5ab7d78895..c2cc392a27d4 100644
+--- a/drivers/regulator/palmas-regulator.c
++++ b/drivers/regulator/palmas-regulator.c
+@@ -443,13 +443,16 @@ static int palmas_ldo_write(struct palmas *palmas, unsigned int reg,
+ static int palmas_set_mode_smps(struct regulator_dev *dev, unsigned int mode)
+ {
+ 	int id = rdev_get_id(dev);
++	int ret;
+ 	struct palmas_pmic *pmic = rdev_get_drvdata(dev);
+ 	struct palmas_pmic_driver_data *ddata = pmic->palmas->pmic_ddata;
+ 	struct palmas_regs_info *rinfo = &ddata->palmas_regs_info[id];
+ 	unsigned int reg;
+ 	bool rail_enable = true;
+ 
+-	palmas_smps_read(pmic->palmas, rinfo->ctrl_addr, ®);
++	ret = palmas_smps_read(pmic->palmas, rinfo->ctrl_addr, ®);
++	if (ret)
++		return ret;
+ 
+ 	reg &= ~PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
+ 

commit 15b3048aeed8bf8232156456c884ae94ed52d6cd
+Author: Wenwen Wang 
+Date:   Tue Dec 4 09:16:41 2018 -0600
+
+    misc: mic: fix a DMA pool free failure
+    
+    In _scif_prog_signal(), a DMA pool is allocated if the MIC Coprocessor is
+    not X100, i.e., the boolean variable 'x100' is false. This DMA pool will be
+    freed eventually through the callback function scif_prog_signal_cb() with
+    the parameter of 'status', which actually points to the start of DMA pool.
+    Specifically, in scif_prog_signal_cb(), the 'ep' field and the
+    'src_dma_addr' field of 'status' are used to free the DMA pool by invoking
+    dma_pool_free(). Given that 'status' points to the start address of the DMA
+    pool, both 'status->ep' and 'status->src_dma_addr' are in the DMA pool. And
+    so, the device has the permission to access them. Even worse, a malicious
+    device can modify them. As a result, dma_pool_free() will not succeed.
+    
+    To avoid the above issue, this patch introduces a new data structure, i.e.,
+    scif_cb_arg, to store the arguments required by the call back function. A
+    variable 'cb_arg' is allocated in _scif_prog_signal() to pass the
+    arguments. 'cb_arg' will be freed after dma_pool_free() in
+    scif_prog_signal_cb().
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/misc/mic/scif/scif_fence.c b/drivers/misc/mic/scif/scif_fence.c
+index 7bb929f05d85..2e7ce6ae9dd2 100644
+--- a/drivers/misc/mic/scif/scif_fence.c
++++ b/drivers/misc/mic/scif/scif_fence.c
+@@ -195,10 +195,11 @@ static inline void *scif_get_local_va(off_t off, struct scif_window *window)
+ 
+ static void scif_prog_signal_cb(void *arg)
+ {
+-	struct scif_status *status = arg;
++	struct scif_cb_arg *cb_arg = arg;
+ 
+-	dma_pool_free(status->ep->remote_dev->signal_pool, status,
+-		      status->src_dma_addr);
++	dma_pool_free(cb_arg->ep->remote_dev->signal_pool, cb_arg->status,
++		      cb_arg->src_dma_addr);
++	kfree(cb_arg);
+ }
+ 
+ static int _scif_prog_signal(scif_epd_t epd, dma_addr_t dst, u64 val)
+@@ -209,6 +210,7 @@ static int _scif_prog_signal(scif_epd_t epd, dma_addr_t dst, u64 val)
+ 	bool x100 = !is_dma_copy_aligned(chan->device, 1, 1, 1);
+ 	struct dma_async_tx_descriptor *tx;
+ 	struct scif_status *status = NULL;
++	struct scif_cb_arg *cb_arg = NULL;
+ 	dma_addr_t src;
+ 	dma_cookie_t cookie;
+ 	int err;
+@@ -257,8 +259,16 @@ static int _scif_prog_signal(scif_epd_t epd, dma_addr_t dst, u64 val)
+ 		goto dma_fail;
+ 	}
+ 	if (!x100) {
++		cb_arg = kmalloc(sizeof(*cb_arg), GFP_KERNEL);
++		if (!cb_arg) {
++			err = -ENOMEM;
++			goto dma_fail;
++		}
++		cb_arg->src_dma_addr = src;
++		cb_arg->status = status;
++		cb_arg->ep = ep;
+ 		tx->callback = scif_prog_signal_cb;
+-		tx->callback_param = status;
++		tx->callback_param = cb_arg;
+ 	}
+ 	cookie = tx->tx_submit(tx);
+ 	if (dma_submit_error(cookie)) {
+@@ -270,9 +280,11 @@ static int _scif_prog_signal(scif_epd_t epd, dma_addr_t dst, u64 val)
+ 	dma_async_issue_pending(chan);
+ 	return 0;
+ dma_fail:
+-	if (!x100)
++	if (!x100) {
+ 		dma_pool_free(ep->remote_dev->signal_pool, status,
+ 			      src - offsetof(struct scif_status, val));
++		kfree(cb_arg);
++	}
+ alloc_fail:
+ 	return err;
+ }
+diff --git a/drivers/misc/mic/scif/scif_rma.h b/drivers/misc/mic/scif/scif_rma.h
+index fa6722279196..84af3033a473 100644
+--- a/drivers/misc/mic/scif/scif_rma.h
++++ b/drivers/misc/mic/scif/scif_rma.h
+@@ -205,6 +205,19 @@ struct scif_status {
+ 	struct scif_endpt *ep;
+ };
+ 
++/*
++ * struct scif_cb_arg - Stores the argument of the callback func
++ *
++ * @src_dma_addr: Source buffer DMA address
++ * @status: DMA status
++ * @ep: SCIF endpoint
++ */
++struct scif_cb_arg {
++	dma_addr_t src_dma_addr;
++	struct scif_status *status;
++	struct scif_endpt *ep;
++};
++
+ /*
+  * struct scif_window - Registration Window for Self and Remote
+  *

commit 7172122be6a4712d699da4d261f92aa5ab3a78b8
+Author: Wenwen Wang 
+Date:   Thu Oct 18 19:50:43 2018 -0500
+
+    crypto: cavium/nitrox - fix a DMA pool free failure
+    
+    In crypto_alloc_context(), a DMA pool is allocated through dma_pool_alloc()
+    to hold the crypto context. The meta data of the DMA pool, including the
+    pool used for the allocation 'ndev->ctx_pool' and the base address of the
+    DMA pool used by the device 'dma', are then stored to the beginning of the
+    pool. These meta data are eventually used in crypto_free_context() to free
+    the DMA pool through dma_pool_free(). However, given that the DMA pool can
+    also be accessed by the device, a malicious device can modify these meta
+    data, especially when the device is controlled to deploy an attack. This
+    can cause an unexpected DMA pool free failure.
+    
+    To avoid the above issue, this patch introduces a new structure
+    crypto_ctx_hdr and a new field chdr in the structure nitrox_crypto_ctx hold
+    the meta data information of the DMA pool after the allocation. Note that
+    the original structure ctx_hdr is not changed to ensure the compatibility.
+    
+    Cc: 
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Herbert Xu 
+
+diff --git a/drivers/crypto/cavium/nitrox/nitrox_algs.c b/drivers/crypto/cavium/nitrox/nitrox_algs.c
+index 2ae6124e5da6..5d54ebc20cb3 100644
+--- a/drivers/crypto/cavium/nitrox/nitrox_algs.c
++++ b/drivers/crypto/cavium/nitrox/nitrox_algs.c
+@@ -73,7 +73,7 @@ static int flexi_aes_keylen(int keylen)
+ static int nitrox_skcipher_init(struct crypto_skcipher *tfm)
+ {
+ 	struct nitrox_crypto_ctx *nctx = crypto_skcipher_ctx(tfm);
+-	void *fctx;
++	struct crypto_ctx_hdr *chdr;
+ 
+ 	/* get the first device */
+ 	nctx->ndev = nitrox_get_first_device();
+@@ -81,12 +81,14 @@ static int nitrox_skcipher_init(struct crypto_skcipher *tfm)
+ 		return -ENODEV;
+ 
+ 	/* allocate nitrox crypto context */
+-	fctx = crypto_alloc_context(nctx->ndev);
+-	if (!fctx) {
++	chdr = crypto_alloc_context(nctx->ndev);
++	if (!chdr) {
+ 		nitrox_put_device(nctx->ndev);
+ 		return -ENOMEM;
+ 	}
+-	nctx->u.ctx_handle = (uintptr_t)fctx;
++	nctx->chdr = chdr;
++	nctx->u.ctx_handle = (uintptr_t)((u8 *)chdr->vaddr +
++					 sizeof(struct ctx_hdr));
+ 	crypto_skcipher_set_reqsize(tfm, crypto_skcipher_reqsize(tfm) +
+ 				    sizeof(struct nitrox_kcrypt_request));
+ 	return 0;
+@@ -102,7 +104,7 @@ static void nitrox_skcipher_exit(struct crypto_skcipher *tfm)
+ 
+ 		memset(&fctx->crypto, 0, sizeof(struct crypto_keys));
+ 		memset(&fctx->auth, 0, sizeof(struct auth_keys));
+-		crypto_free_context((void *)fctx);
++		crypto_free_context((void *)nctx->chdr);
+ 	}
+ 	nitrox_put_device(nctx->ndev);
+ 
+diff --git a/drivers/crypto/cavium/nitrox/nitrox_lib.c b/drivers/crypto/cavium/nitrox/nitrox_lib.c
+index 2260efa42308..9138bae12521 100644
+--- a/drivers/crypto/cavium/nitrox/nitrox_lib.c
++++ b/drivers/crypto/cavium/nitrox/nitrox_lib.c
+@@ -158,12 +158,19 @@ static void destroy_crypto_dma_pool(struct nitrox_device *ndev)
+ void *crypto_alloc_context(struct nitrox_device *ndev)
+ {
+ 	struct ctx_hdr *ctx;
++	struct crypto_ctx_hdr *chdr;
+ 	void *vaddr;
+ 	dma_addr_t dma;
+ 
++	chdr = kmalloc(sizeof(*chdr), GFP_KERNEL);
++	if (!chdr)
++		return NULL;
++
+ 	vaddr = dma_pool_zalloc(ndev->ctx_pool, GFP_KERNEL, &dma);
+-	if (!vaddr)
++	if (!vaddr) {
++		kfree(chdr);
+ 		return NULL;
++	}
+ 
+ 	/* fill meta data */
+ 	ctx = vaddr;
+@@ -171,7 +178,11 @@ void *crypto_alloc_context(struct nitrox_device *ndev)
+ 	ctx->dma = dma;
+ 	ctx->ctx_dma = dma + sizeof(struct ctx_hdr);
+ 
+-	return ((u8 *)vaddr + sizeof(struct ctx_hdr));
++	chdr->pool = ndev->ctx_pool;
++	chdr->dma = dma;
++	chdr->vaddr = vaddr;
++
++	return chdr;
+ }
+ 
+ /**
+@@ -180,13 +191,14 @@ void *crypto_alloc_context(struct nitrox_device *ndev)
+  */
+ void crypto_free_context(void *ctx)
+ {
+-	struct ctx_hdr *ctxp;
++	struct crypto_ctx_hdr *ctxp;
+ 
+ 	if (!ctx)
+ 		return;
+ 
+-	ctxp = (struct ctx_hdr *)((u8 *)ctx - sizeof(struct ctx_hdr));
+-	dma_pool_free(ctxp->pool, ctxp, ctxp->dma);
++	ctxp = ctx;
++	dma_pool_free(ctxp->pool, ctxp->vaddr, ctxp->dma);
++	kfree(ctxp);
+ }
+ 
+ /**
+diff --git a/drivers/crypto/cavium/nitrox/nitrox_req.h b/drivers/crypto/cavium/nitrox/nitrox_req.h
+index d091b6f5f5dd..19f0a20e3bb3 100644
+--- a/drivers/crypto/cavium/nitrox/nitrox_req.h
++++ b/drivers/crypto/cavium/nitrox/nitrox_req.h
+@@ -181,12 +181,19 @@ struct flexi_crypto_context {
+ 	struct auth_keys auth;
+ };
+ 
++struct crypto_ctx_hdr {
++	struct dma_pool *pool;
++	dma_addr_t dma;
++	void *vaddr;
++};
++
+ struct nitrox_crypto_ctx {
+ 	struct nitrox_device *ndev;
+ 	union {
+ 		u64 ctx_handle;
+ 		struct flexi_crypto_context *fctx;
+ 	} u;
++	struct crypto_ctx_hdr *chdr;
+ };
+ 
+ struct nitrox_kcrypt_request {

commit b6168562c8ce2bd5a30e213021650422e08764dc
+Author: Wenwen Wang 
+Date:   Thu Oct 18 09:36:46 2018 -0500
+
+    net: socket: fix a missing-check bug
+    
+    In ethtool_ioctl(), the ioctl command 'ethcmd' is checked through a switch
+    statement to see whether it is necessary to pre-process the ethtool
+    structure, because, as mentioned in the comment, the structure
+    ethtool_rxnfc is defined with padding. If yes, a user-space buffer 'rxnfc'
+    is allocated through compat_alloc_user_space(). One thing to note here is
+    that, if 'ethcmd' is ETHTOOL_GRXCLSRLALL, the size of the buffer 'rxnfc' is
+    partially determined by 'rule_cnt', which is actually acquired from the
+    user-space buffer 'compat_rxnfc', i.e., 'compat_rxnfc->rule_cnt', through
+    get_user(). After 'rxnfc' is allocated, the data in the original user-space
+    buffer 'compat_rxnfc' is then copied to 'rxnfc' through copy_in_user(),
+    including the 'rule_cnt' field. However, after this copy, no check is
+    re-enforced on 'rxnfc->rule_cnt'. So it is possible that a malicious user
+    race to change the value in the 'compat_rxnfc->rule_cnt' between these two
+    copies. Through this way, the attacker can bypass the previous check on
+    'rule_cnt' and inject malicious data. This can cause undefined behavior of
+    the kernel and introduce potential security risk.
+    
+    This patch avoids the above issue via copying the value acquired by
+    get_user() to 'rxnfc->rule_cn', if 'ethcmd' is ETHTOOL_GRXCLSRLALL.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/socket.c b/net/socket.c
+index 01f3f8f32d6f..390a8ecef4bf 100644
+--- a/net/socket.c
++++ b/net/socket.c
+@@ -2875,9 +2875,14 @@ static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
+ 		    copy_in_user(&rxnfc->fs.ring_cookie,
+ 				 &compat_rxnfc->fs.ring_cookie,
+ 				 (void __user *)(&rxnfc->fs.location + 1) -
+-				 (void __user *)&rxnfc->fs.ring_cookie) ||
+-		    copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt,
+-				 sizeof(rxnfc->rule_cnt)))
++				 (void __user *)&rxnfc->fs.ring_cookie))
++			return -EFAULT;
++		if (ethcmd == ETHTOOL_GRXCLSRLALL) {
++			if (put_user(rule_cnt, &rxnfc->rule_cnt))
++				return -EFAULT;
++		} else if (copy_in_user(&rxnfc->rule_cnt,
++					&compat_rxnfc->rule_cnt,
++					sizeof(rxnfc->rule_cnt)))
+ 			return -EFAULT;
+ 	}
+ 

commit 800a7340ab7dd667edf95e74d8e4f23a17e87076
+Author: Wenwen Wang 
+Date:   Wed Oct 3 11:43:59 2018 -0500
+
+    dm ioctl: harden copy_params()'s copy_from_user() from malicious users
+    
+    In copy_params(), the struct 'dm_ioctl' is first copied from the user
+    space buffer 'user' to 'param_kernel' and the field 'data_size' is
+    checked against 'minimum_data_size' (size of 'struct dm_ioctl' payload
+    up to its 'data' member).  If the check fails, an error code EINVAL will be
+    returned.  Otherwise, param_kernel->data_size is used to do a second copy,
+    which copies from the same user-space buffer to 'dmi'.  After the second
+    copy, only 'dmi->data_size' is checked against 'param_kernel->data_size'.
+    Given that the buffer 'user' resides in the user space, a malicious
+    user-space process can race to change the content in the buffer between
+    the two copies.  This way, the attacker can inject inconsistent data
+    into 'dmi' (versus previously validated 'param_kernel').
+    
+    Fix redundant copying of 'minimum_data_size' from user-space buffer by
+    using the first copy stored in 'param_kernel'.  Also remove the
+    'data_size' check after the second copy because it is now unnecessary.
+    
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Mike Snitzer 
+
+diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
+index b810ea77e6b1..f666778ad237 100644
+--- a/drivers/md/dm-ioctl.c
++++ b/drivers/md/dm-ioctl.c
+@@ -1720,8 +1720,7 @@ static void free_params(struct dm_ioctl *param, size_t param_size, int param_fla
+ }
+ 
+ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kernel,
+-		       int ioctl_flags,
+-		       struct dm_ioctl **param, int *param_flags)
++		       int ioctl_flags, struct dm_ioctl **param, int *param_flags)
+ {
+ 	struct dm_ioctl *dmi;
+ 	int secure_data;
+@@ -1762,18 +1761,13 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern
+ 
+ 	*param_flags |= DM_PARAMS_MALLOC;
+ 
+-	if (copy_from_user(dmi, user, param_kernel->data_size))
+-		goto bad;
++	/* Copy from param_kernel (which was already copied from user) */
++	memcpy(dmi, param_kernel, minimum_data_size);
+ 
+-data_copied:
+-	/*
+-	 * Abort if something changed the ioctl data while it was being copied.
+-	 */
+-	if (dmi->data_size != param_kernel->data_size) {
+-		DMERR("rejecting ioctl: data size modified while processing parameters");
++	if (copy_from_user(&dmi->data, (char __user *)user + minimum_data_size,
++			   param_kernel->data_size - minimum_data_size))
+ 		goto bad;
+-	}
+-
++data_copied:
+ 	/* Wipe the user buffer so we do not return it to userspace */
+ 	if (secure_data && clear_user(user, param_kernel->data_size))
+ 		goto bad;

commit 47db7873136a9c57c45390a53b57019cf73c8259
+Author: Wenwen Wang 
+Date:   Sat Oct 6 13:34:21 2018 -0500
+
+    scsi: megaraid_sas: fix a missing-check bug
+    
+    In megasas_mgmt_compat_ioctl_fw(), to handle the structure
+    compat_megasas_iocpacket 'cioc', a user-space structure megasas_iocpacket
+    'ioc' is allocated before megasas_mgmt_ioctl_fw() is invoked to handle
+    the packet. Since the two data structures have different fields, the data
+    is copied from 'cioc' to 'ioc' field by field. In the copy process,
+    'sense_ptr' is prepared if the field 'sense_len' is not null, because it
+    will be used in megasas_mgmt_ioctl_fw(). To prepare 'sense_ptr', the
+    user-space data 'ioc->sense_off' and 'cioc->sense_off' are copied and
+    saved to kernel-space variables 'local_sense_off' and 'user_sense_off'
+    respectively. Given that 'ioc->sense_off' is also copied from
+    'cioc->sense_off', 'local_sense_off' and 'user_sense_off' should have the
+    same value. However, 'cioc' is in the user space and a malicious user can
+    race to change the value of 'cioc->sense_off' after it is copied to
+    'ioc->sense_off' but before it is copied to 'user_sense_off'. By doing
+    so, the attacker can inject different values into 'local_sense_off' and
+    'user_sense_off'. This can cause undefined behavior in the following
+    execution, because the two variables are supposed to be same.
+    
+    This patch enforces a check on the two kernel variables 'local_sense_off'
+    and 'user_sense_off' to make sure they are the same after the copy. In
+    case they are not, an error code EINVAL will be returned.
+    
+    Signed-off-by: Wenwen Wang 
+    Acked-by: Sumit Saxena 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index 9aa9590c5373..f6de7526ded5 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -7523,6 +7523,9 @@ static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg)
+ 		get_user(user_sense_off, &cioc->sense_off))
+ 		return -EFAULT;
+ 
++	if (local_sense_off != user_sense_off)
++		return -EINVAL;
++
+ 	if (local_sense_len) {
+ 		void __user **sense_ioc_ptr =
+ 			(void __user **)((u8 *)((unsigned long)&ioc->frame.raw) + local_sense_off);

commit 58f5bbe331c566f49c9559568f982202a278aa78
+Author: Wenwen Wang 
+Date:   Mon Oct 8 10:49:35 2018 -0500
+
+    ethtool: fix a privilege escalation bug
+    
+    In dev_ethtool(), the eth command 'ethcmd' is firstly copied from the
+    use-space buffer 'useraddr' and checked to see whether it is
+    ETHTOOL_PERQUEUE. If yes, the sub-command 'sub_cmd' is further copied from
+    the user space. Otherwise, 'sub_cmd' is the same as 'ethcmd'. Next,
+    according to 'sub_cmd', a permission check is enforced through the function
+    ns_capable(). For example, the permission check is required if 'sub_cmd' is
+    ETHTOOL_SCOALESCE, but it is not necessary if 'sub_cmd' is
+    ETHTOOL_GCOALESCE, as suggested in the comment "Allow some commands to be
+    done by anyone". The following execution invokes different handlers
+    according to 'ethcmd'. Specifically, if 'ethcmd' is ETHTOOL_PERQUEUE,
+    ethtool_set_per_queue() is called. In ethtool_set_per_queue(), the kernel
+    object 'per_queue_opt' is copied again from the user-space buffer
+    'useraddr' and 'per_queue_opt.sub_command' is used to determine which
+    operation should be performed. Given that the buffer 'useraddr' is in the
+    user space, a malicious user can race to change the sub-command between the
+    two copies. In particular, the attacker can supply ETHTOOL_PERQUEUE and
+    ETHTOOL_GCOALESCE to bypass the permission check in dev_ethtool(). Then
+    before ethtool_set_per_queue() is called, the attacker changes
+    ETHTOOL_GCOALESCE to ETHTOOL_SCOALESCE. In this way, the attacker can
+    bypass the permission check and execute ETHTOOL_SCOALESCE.
+    
+    This patch enforces a check in ethtool_set_per_queue() after the second
+    copy from 'useraddr'. If the sub-command is different from the one obtained
+    in the first copy in dev_ethtool(), an error code EINVAL will be returned.
+    
+    Fixes: f38d138a7da6 ("net/ethtool: support set coalesce per queue")
+    Signed-off-by: Wenwen Wang 
+    Reviewed-by: Michal Kubecek 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/core/ethtool.c b/net/core/ethtool.c
+index 192f2f76b7bd..aeabc4831fca 100644
+--- a/net/core/ethtool.c
++++ b/net/core/ethtool.c
+@@ -2472,13 +2472,17 @@ static int ethtool_set_per_queue_coalesce(struct net_device *dev,
+ 	return ret;
+ }
+ 
+-static int ethtool_set_per_queue(struct net_device *dev, void __user *useraddr)
++static int ethtool_set_per_queue(struct net_device *dev,
++				 void __user *useraddr, u32 sub_cmd)
+ {
+ 	struct ethtool_per_queue_op per_queue_opt;
+ 
+ 	if (copy_from_user(&per_queue_opt, useraddr, sizeof(per_queue_opt)))
+ 		return -EFAULT;
+ 
++	if (per_queue_opt.sub_command != sub_cmd)
++		return -EINVAL;
++
+ 	switch (per_queue_opt.sub_command) {
+ 	case ETHTOOL_GCOALESCE:
+ 		return ethtool_get_per_queue_coalesce(dev, useraddr, &per_queue_opt);
+@@ -2849,7 +2853,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
+ 		rc = ethtool_get_phy_stats(dev, useraddr);
+ 		break;
+ 	case ETHTOOL_PERQUEUE:
+-		rc = ethtool_set_per_queue(dev, useraddr);
++		rc = ethtool_set_per_queue(dev, useraddr, sub_cmd);
+ 		break;
+ 	case ETHTOOL_GLINKSETTINGS:
+ 		rc = ethtool_get_link_ksettings(dev, useraddr);

commit 2bb3207dbbd4d30e96dd0e1c8e013104193bd59c
+Author: Wenwen Wang 
+Date:   Tue Oct 9 08:15:38 2018 -0500
+
+    ethtool: fix a missing-check bug
+    
+    In ethtool_get_rxnfc(), the eth command 'cmd' is compared against
+    'ETHTOOL_GRXFH' to see whether it is necessary to adjust the variable
+    'info_size'. Then the whole structure of 'info' is copied from the
+    user-space buffer 'useraddr' with 'info_size' bytes. In the following
+    execution, 'info' may be copied again from the buffer 'useraddr' depending
+    on the 'cmd' and the 'info.flow_type'. However, after these two copies,
+    there is no check between 'cmd' and 'info.cmd'. In fact, 'cmd' is also
+    copied from the buffer 'useraddr' in dev_ethtool(), which is the caller
+    function of ethtool_get_rxnfc(). Given that 'useraddr' is in the user
+    space, a malicious user can race to change the eth command in the buffer
+    between these copies. By doing so, the attacker can supply inconsistent
+    data and cause undefined behavior because in the following execution 'info'
+    will be passed to ops->get_rxnfc().
+    
+    This patch adds a necessary check on 'info.cmd' and 'cmd' to confirm that
+    they are still same after the two copies in ethtool_get_rxnfc(). Otherwise,
+    an error code EINVAL will be returned.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/core/ethtool.c b/net/core/ethtool.c
+index 0762aaf8e964..192f2f76b7bd 100644
+--- a/net/core/ethtool.c
++++ b/net/core/ethtool.c
+@@ -1015,6 +1015,9 @@ static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev,
+ 			return -EINVAL;
+ 	}
+ 
++	if (info.cmd != cmd)
++		return -EINVAL;
++
+ 	if (info.cmd == ETHTOOL_GRXCLSRLALL) {
+ 		if (info.rule_cnt > 0) {
+ 			if (info.rule_cnt <= KMALLOC_MAX_SIZE / sizeof(u32))

commit 6b995f4eec34745f6cb20d66d5277611f0b3c3fa
+Author: Wenwen Wang 
+Date:   Wed Oct 10 18:38:28 2018 -0500
+
+    misc: mic: fix a DMA pool free failure
+    
+    In _scif_prog_signal(), the boolean variable 'x100' is used to indicate
+    whether the MIC Coprocessor is X100. If 'x100' is true, the status
+    descriptor will be used to write the value to the destination. Otherwise, a
+    DMA pool will be allocated for this purpose. Specifically, if the DMA pool
+    is allocated successfully, two memory addresses will be returned. One is
+    for the CPU and the other is for the device to access the DMA pool. The
+    former is stored to the variable 'status' and the latter is stored to the
+    variable 'src'. After the allocation, the address in 'src' is saved to
+    'status->src_dma_addr', which is actually in the DMA pool, and 'src' is
+    then modified.
+    
+    Later on, if an error occurs, the execution flow will transfer to the label
+    'dma_fail', which will check 'x100' and free up the allocated DMA pool if
+    'x100' is false. The point here is that 'status->src_dma_addr' is used for
+    freeing up the DMA pool. As mentioned before, 'status->src_dma_addr' is in
+    the DMA pool. And thus, the device is able to modify this data. This can
+    potentially cause failures when freeing up the DMA pool because of the
+    modified device address.
+    
+    This patch avoids the above issue by using the variable 'src' (with
+    necessary calculation) to free up the DMA pool.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/misc/mic/scif/scif_fence.c b/drivers/misc/mic/scif/scif_fence.c
+index cac3bcc308a7..7bb929f05d85 100644
+--- a/drivers/misc/mic/scif/scif_fence.c
++++ b/drivers/misc/mic/scif/scif_fence.c
+@@ -272,7 +272,7 @@ static int _scif_prog_signal(scif_epd_t epd, dma_addr_t dst, u64 val)
+ dma_fail:
+ 	if (!x100)
+ 		dma_pool_free(ep->remote_dev->signal_pool, status,
+-			      status->src_dma_addr);
++			      src - offsetof(struct scif_status, val));
+ alloc_fail:
+ 	return err;
+ }

commit 8af03d1ae2e154a8be3631e8694b87007e1bdbc2
+Author: Wenwen Wang 
+Date:   Sun Oct 7 15:23:15 2018 -0500
+
+    bpf: btf: Fix a missing check bug
+    
+    In btf_parse_hdr(), the length of the btf data header is firstly copied
+    from the user space to 'hdr_len' and checked to see whether it is larger
+    than 'btf_data_size'. If yes, an error code EINVAL is returned. Otherwise,
+    the whole header is copied again from the user space to 'btf->hdr'.
+    However, after the second copy, there is no check between
+    'btf->hdr->hdr_len' and 'hdr_len' to confirm that the two copies get the
+    same value. Given that the btf data is in the user space, a malicious user
+    can race to change the data between the two copies. By doing so, the user
+    can provide malicious data to the kernel and cause undefined behavior.
+    
+    This patch adds a necessary check after the second copy, to make sure
+    'btf->hdr->hdr_len' has the same value as 'hdr_len'. Otherwise, an error
+    code EINVAL will be returned.
+    
+    Signed-off-by: Wenwen Wang 
+    Acked-by: Song Liu 
+    Signed-off-by: Alexei Starovoitov 
+
+diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
+index 138f0302692e..378cef70341c 100644
+--- a/kernel/bpf/btf.c
++++ b/kernel/bpf/btf.c
+@@ -2114,6 +2114,9 @@ static int btf_parse_hdr(struct btf_verifier_env *env, void __user *btf_data,
+ 
+ 	hdr = &btf->hdr;
+ 
++	if (hdr->hdr_len != hdr_len)
++		return -EINVAL;
++
+ 	btf_verifier_log_hdr(env, btf_data_size);
+ 
+ 	if (hdr->magic != BTF_MAGIC) {

commit a26ac6c1bed951b2066cc4b2257facd919e35c0b
+Author: Wenwen Wang 
+Date:   Thu Oct 4 11:44:02 2018 -0400
+
+    media: isif: fix a NULL pointer dereference bug
+    
+    In isif_probe(), there is a while loop to get the ISIF base address and
+    linearization table0 and table1 address. In the loop body, the function
+    platform_get_resource() is called to get the resource. If
+    platform_get_resource() returns NULL, the loop is terminated and the
+    execution goes to 'fail_nobase_res'. Suppose the loop is terminated at the
+    first iteration because platform_get_resource() returns NULL and the
+    execution goes to 'fail_nobase_res'. Given that there is another while loop
+    at 'fail_nobase_res' and i equals to 0, one iteration of the second while
+    loop will be executed. However, the second while loop does not check the
+    return value of platform_get_resource(). This can cause a NULL pointer
+    dereference bug if the return value is a NULL pointer.
+    
+    This patch avoids the above issue by adding a check in the second while
+    loop after the call to platform_get_resource().
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Hans Verkuil 
+    Signed-off-by: Mauro Carvalho Chehab 
+
+diff --git a/drivers/media/platform/davinci/isif.c b/drivers/media/platform/davinci/isif.c
+index f924e76e2fbf..340f8218f54d 100644
+--- a/drivers/media/platform/davinci/isif.c
++++ b/drivers/media/platform/davinci/isif.c
+@@ -1100,7 +1100,8 @@ static int isif_probe(struct platform_device *pdev)
+ 
+ 	while (i >= 0) {
+ 		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+-		release_mem_region(res->start, resource_size(res));
++		if (res)
++			release_mem_region(res->start, resource_size(res));
+ 		i--;
+ 	}
+ 	vpfe_unregister_ccdc_device(&isif_hw_dev);

commit 0781168e23a2fc8dceb989f11fc5b39b3ccacc35
+Author: Wenwen Wang 
+Date:   Fri Oct 5 10:59:36 2018 -0500
+
+    yam: fix a missing-check bug
+    
+    In yam_ioctl(), the concrete ioctl command is firstly copied from the
+    user-space buffer 'ifr->ifr_data' to 'ioctl_cmd' and checked through the
+    following switch statement. If the command is not as expected, an error
+    code EINVAL is returned. In the following execution the buffer
+    'ifr->ifr_data' is copied again in the cases of the switch statement to
+    specific data structures according to what kind of ioctl command is
+    requested. However, after the second copy, no re-check is enforced on the
+    newly-copied command. Given that the buffer 'ifr->ifr_data' is in the user
+    space, a malicious user can race to change the command between the two
+    copies. This way, the attacker can inject inconsistent data and cause
+    undefined behavior.
+    
+    This patch adds a re-check in each case of the switch statement if there is
+    a second copy in that case, to re-check whether the command obtained in the
+    second copy is the same as the one in the first copy. If not, an error code
+    EINVAL will be returned.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
+index 16ec7af6ab7b..ba9df430fca6 100644
+--- a/drivers/net/hamradio/yam.c
++++ b/drivers/net/hamradio/yam.c
+@@ -966,6 +966,8 @@ static int yam_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ 				 sizeof(struct yamdrv_ioctl_mcs));
+ 		if (IS_ERR(ym))
+ 			return PTR_ERR(ym);
++		if (ym->cmd != SIOCYAMSMCS)
++			return -EINVAL;
+ 		if (ym->bitrate > YAM_MAXBITRATE) {
+ 			kfree(ym);
+ 			return -EINVAL;
+@@ -981,6 +983,8 @@ static int yam_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ 		if (copy_from_user(&yi, ifr->ifr_data, sizeof(struct yamdrv_ioctl_cfg)))
+ 			 return -EFAULT;
+ 
++		if (yi.cmd != SIOCYAMSCFG)
++			return -EINVAL;
+ 		if ((yi.cfg.mask & YAM_IOBASE) && netif_running(dev))
+ 			return -EINVAL;		/* Cannot change this parameter when up */
+ 		if ((yi.cfg.mask & YAM_IRQ) && netif_running(dev))

commit 2c05d88818ab6571816b93edce4d53703870d7ae
+Author: Wenwen Wang 
+Date:   Fri Oct 5 08:48:27 2018 -0500
+
+    net: cxgb3_main: fix a missing-check bug
+    
+    In cxgb_extension_ioctl(), the command of the ioctl is firstly copied from
+    the user-space buffer 'useraddr' to 'cmd' and checked through the
+    switch statement. If the command is not as expected, an error code
+    EOPNOTSUPP is returned. In the following execution, i.e., the cases of the
+    switch statement, the whole buffer of 'useraddr' is copied again to a
+    specific data structure, according to what kind of command is requested.
+    However, after the second copy, there is no re-check on the newly-copied
+    command. Given that the buffer 'useraddr' is in the user space, a malicious
+    user can race to change the command between the two copies. By doing so,
+    the attacker can supply malicious data to the kernel and cause undefined
+    behavior.
+    
+    This patch adds a re-check in each case of the switch statement if there is
+    a second copy in that case, to re-check whether the command obtained in the
+    second copy is the same as the one in the first copy. If not, an error code
+    EINVAL is returned.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+index a19172dbe6be..c34ea385fe4a 100644
+--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
++++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+@@ -2159,6 +2159,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
+ 			return -EPERM;
+ 		if (copy_from_user(&t, useraddr, sizeof(t)))
+ 			return -EFAULT;
++		if (t.cmd != CHELSIO_SET_QSET_PARAMS)
++			return -EINVAL;
+ 		if (t.qset_idx >= SGE_QSETS)
+ 			return -EINVAL;
+ 		if (!in_range(t.intr_lat, 0, M_NEWTIMER) ||
+@@ -2258,6 +2260,9 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
+ 		if (copy_from_user(&t, useraddr, sizeof(t)))
+ 			return -EFAULT;
+ 
++		if (t.cmd != CHELSIO_GET_QSET_PARAMS)
++			return -EINVAL;
++
+ 		/* Display qsets for all ports when offload enabled */
+ 		if (test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map)) {
+ 			q1 = 0;
+@@ -2303,6 +2308,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
+ 			return -EBUSY;
+ 		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+ 			return -EFAULT;
++		if (edata.cmd != CHELSIO_SET_QSET_NUM)
++			return -EINVAL;
+ 		if (edata.val < 1 ||
+ 			(edata.val > 1 && !(adapter->flags & USING_MSIX)))
+ 			return -EINVAL;
+@@ -2343,6 +2350,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
+ 			return -EPERM;
+ 		if (copy_from_user(&t, useraddr, sizeof(t)))
+ 			return -EFAULT;
++		if (t.cmd != CHELSIO_LOAD_FW)
++			return -EINVAL;
+ 		/* Check t.len sanity ? */
+ 		fw_data = memdup_user(useraddr + sizeof(t), t.len);
+ 		if (IS_ERR(fw_data))
+@@ -2366,6 +2375,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
+ 			return -EBUSY;
+ 		if (copy_from_user(&m, useraddr, sizeof(m)))
+ 			return -EFAULT;
++		if (m.cmd != CHELSIO_SETMTUTAB)
++			return -EINVAL;
+ 		if (m.nmtus != NMTUS)
+ 			return -EINVAL;
+ 		if (m.mtus[0] < 81)	/* accommodate SACK */
+@@ -2407,6 +2418,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
+ 			return -EBUSY;
+ 		if (copy_from_user(&m, useraddr, sizeof(m)))
+ 			return -EFAULT;
++		if (m.cmd != CHELSIO_SET_PM)
++			return -EINVAL;
+ 		if (!is_power_of_2(m.rx_pg_sz) ||
+ 			!is_power_of_2(m.tx_pg_sz))
+ 			return -EINVAL;	/* not power of 2 */
+@@ -2440,6 +2453,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
+ 			return -EIO;	/* need the memory controllers */
+ 		if (copy_from_user(&t, useraddr, sizeof(t)))
+ 			return -EFAULT;
++		if (t.cmd != CHELSIO_GET_MEM)
++			return -EINVAL;
+ 		if ((t.addr & 7) || (t.len & 7))
+ 			return -EINVAL;
+ 		if (t.mem_id == MEM_CM)
+@@ -2492,6 +2507,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
+ 			return -EAGAIN;
+ 		if (copy_from_user(&t, useraddr, sizeof(t)))
+ 			return -EFAULT;
++		if (t.cmd != CHELSIO_SET_TRACE_FILTER)
++			return -EINVAL;
+ 
+ 		tp = (const struct trace_params *)&t.sip;
+ 		if (t.config_tx)

commit f16b613ca8b3e4960cdc5575e9b8e1dbdd7d54d5
+Author: Wenwen Wang 
+Date:   Fri May 18 14:55:35 2018 -0500
+
+    crypto: chtls - fix a missing-check bug
+    
+    In do_chtls_setsockopt(), the tls crypto info is first copied from the
+    poiner 'optval' in userspace and saved to 'tmp_crypto_info'. Then the
+    'version' of the crypto info is checked. If the version is not as expected,
+    i.e., TLS_1_2_VERSION, error code -ENOTSUPP is returned to indicate that
+    the provided crypto info is not supported yet. Then, the 'cipher_type'
+    field of the 'tmp_crypto_info' is also checked to see if it is
+    TLS_CIPHER_AES_GCM_128. If it is, the whole struct of
+    tls12_crypto_info_aes_gcm_128 is copied from the pointer 'optval' and then
+    the function chtls_setkey() is invoked to set the key.
+    
+    Given that the 'optval' pointer resides in userspace, a malicious userspace
+    process can race to change the data pointed by 'optval' between the two
+    copies. For example, a user can provide a crypto info with TLS_1_2_VERSION
+    and TLS_CIPHER_AES_GCM_128. After the first copy, the user can modify the
+    'version' and the 'cipher_type' fields to any versions and/or cipher types
+    that are not allowed. This way, the user can bypass the checks, inject
+    bad data to the kernel, cause chtls_setkey() to set a wrong key or other
+    issues.
+    
+    This patch reuses the data copied in the first try so as to ensure these
+    checks will not be bypassed.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Herbert Xu 
+
+diff --git a/drivers/crypto/chelsio/chtls/chtls_main.c b/drivers/crypto/chelsio/chtls/chtls_main.c
+index 5b9dd582aac0..53ffb00d45bf 100644
+--- a/drivers/crypto/chelsio/chtls/chtls_main.c
++++ b/drivers/crypto/chelsio/chtls/chtls_main.c
+@@ -490,9 +490,13 @@ static int do_chtls_setsockopt(struct sock *sk, int optname,
+ 
+ 	switch (tmp_crypto_info.cipher_type) {
+ 	case TLS_CIPHER_AES_GCM_128: {
+-		rc = copy_from_user(crypto_info, optval,
+-				    sizeof(struct
+-					   tls12_crypto_info_aes_gcm_128));
++		/* Obtain version and type from previous copy */
++		crypto_info[0] = tmp_crypto_info;
++		/* Now copy the following data */
++		rc = copy_from_user((char *)crypto_info + sizeof(*crypto_info),
++				optval + sizeof(*crypto_info),
++				sizeof(struct tls12_crypto_info_aes_gcm_128)
++				- sizeof(*crypto_info));
+ 
+ 		if (rc) {
+ 			rc = -EFAULT;

commit 6009d1fe6ba3bb2dab55921da60465329cc1cd89
+Author: Wenwen Wang 
+Date:   Mon May 21 01:58:07 2018 -0500
+
+    isdn: eicon: fix a missing-check bug
+    
+    In divasmain.c, the function divas_write() firstly invokes the function
+    diva_xdi_open_adapter() to open the adapter that matches with the adapter
+    number provided by the user, and then invokes the function diva_xdi_write()
+    to perform the write operation using the matched adapter. The two functions
+    diva_xdi_open_adapter() and diva_xdi_write() are located in diva.c.
+    
+    In diva_xdi_open_adapter(), the user command is copied to the object 'msg'
+    from the userspace pointer 'src' through the function pointer 'cp_fn',
+    which eventually calls copy_from_user() to do the copy. Then, the adapter
+    number 'msg.adapter' is used to find out a matched adapter from the
+    'adapter_queue'. A matched adapter will be returned if it is found.
+    Otherwise, NULL is returned to indicate the failure of the verification on
+    the adapter number.
+    
+    As mentioned above, if a matched adapter is returned, the function
+    diva_xdi_write() is invoked to perform the write operation. In this
+    function, the user command is copied once again from the userspace pointer
+    'src', which is the same as the 'src' pointer in diva_xdi_open_adapter() as
+    both of them are from the 'buf' pointer in divas_write(). Similarly, the
+    copy is achieved through the function pointer 'cp_fn', which finally calls
+    copy_from_user(). After the successful copy, the corresponding command
+    processing handler of the matched adapter is invoked to perform the write
+    operation.
+    
+    It is obvious that there are two copies here from userspace, one is in
+    diva_xdi_open_adapter(), and one is in diva_xdi_write(). Plus, both of
+    these two copies share the same source userspace pointer, i.e., the 'buf'
+    pointer in divas_write(). Given that a malicious userspace process can race
+    to change the content pointed by the 'buf' pointer, this can pose potential
+    security issues. For example, in the first copy, the user provides a valid
+    adapter number to pass the verification process and a valid adapter can be
+    found. Then the user can modify the adapter number to an invalid number.
+    This way, the user can bypass the verification process of the adapter
+    number and inject inconsistent data.
+    
+    This patch reuses the data copied in
+    diva_xdi_open_adapter() and passes it to diva_xdi_write(). This way, the
+    above issues can be avoided.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: David S. Miller 
+
+diff --git a/drivers/isdn/hardware/eicon/diva.c b/drivers/isdn/hardware/eicon/diva.c
+index 944a7f338099..1b25d8bc153a 100644
+--- a/drivers/isdn/hardware/eicon/diva.c
++++ b/drivers/isdn/hardware/eicon/diva.c
+@@ -388,10 +388,10 @@ void divasa_xdi_driver_unload(void)
+ **  Receive and process command from user mode utility
+ */
+ void *diva_xdi_open_adapter(void *os_handle, const void __user *src,
+-			    int length,
++			    int length, void *mptr,
+ 			    divas_xdi_copy_from_user_fn_t cp_fn)
+ {
+-	diva_xdi_um_cfg_cmd_t msg;
++	diva_xdi_um_cfg_cmd_t *msg = (diva_xdi_um_cfg_cmd_t *)mptr;
+ 	diva_os_xdi_adapter_t *a = NULL;
+ 	diva_os_spin_lock_magic_t old_irql;
+ 	struct list_head *tmp;
+@@ -401,21 +401,21 @@ void *diva_xdi_open_adapter(void *os_handle, const void __user *src,
+ 			 length, sizeof(diva_xdi_um_cfg_cmd_t)))
+ 			return NULL;
+ 	}
+-	if ((*cp_fn) (os_handle, &msg, src, sizeof(msg)) <= 0) {
++	if ((*cp_fn) (os_handle, msg, src, sizeof(*msg)) <= 0) {
+ 		DBG_ERR(("A: A(?) open, write error"))
+ 			return NULL;
+ 	}
+ 	diva_os_enter_spin_lock(&adapter_lock, &old_irql, "open_adapter");
+ 	list_for_each(tmp, &adapter_queue) {
+ 		a = list_entry(tmp, diva_os_xdi_adapter_t, link);
+-		if (a->controller == (int)msg.adapter)
++		if (a->controller == (int)msg->adapter)
+ 			break;
+ 		a = NULL;
+ 	}
+ 	diva_os_leave_spin_lock(&adapter_lock, &old_irql, "open_adapter");
+ 
+ 	if (!a) {
+-		DBG_ERR(("A: A(%d) open, adapter not found", msg.adapter))
++		DBG_ERR(("A: A(%d) open, adapter not found", msg->adapter))
+ 			}
+ 
+ 	return (a);
+@@ -437,8 +437,10 @@ void diva_xdi_close_adapter(void *adapter, void *os_handle)
+ 
+ int
+ diva_xdi_write(void *adapter, void *os_handle, const void __user *src,
+-	       int length, divas_xdi_copy_from_user_fn_t cp_fn)
++	       int length, void *mptr,
++	       divas_xdi_copy_from_user_fn_t cp_fn)
+ {
++	diva_xdi_um_cfg_cmd_t *msg = (diva_xdi_um_cfg_cmd_t *)mptr;
+ 	diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) adapter;
+ 	void *data;
+ 
+@@ -459,7 +461,13 @@ diva_xdi_write(void *adapter, void *os_handle, const void __user *src,
+ 			return (-2);
+ 	}
+ 
+-	length = (*cp_fn) (os_handle, data, src, length);
++	if (msg) {
++		*(diva_xdi_um_cfg_cmd_t *)data = *msg;
++		length = (*cp_fn) (os_handle, (char *)data + sizeof(*msg),
++				   src + sizeof(*msg), length - sizeof(*msg));
++	} else {
++		length = (*cp_fn) (os_handle, data, src, length);
++	}
+ 	if (length > 0) {
+ 		if ((*(a->interface.cmd_proc))
+ 		    (a, (diva_xdi_um_cfg_cmd_t *) data, length)) {
+diff --git a/drivers/isdn/hardware/eicon/diva.h b/drivers/isdn/hardware/eicon/diva.h
+index b067032093a8..1ad76650fbf9 100644
+--- a/drivers/isdn/hardware/eicon/diva.h
++++ b/drivers/isdn/hardware/eicon/diva.h
+@@ -20,10 +20,11 @@ int diva_xdi_read(void *adapter, void *os_handle, void __user *dst,
+ 		  int max_length, divas_xdi_copy_to_user_fn_t cp_fn);
+ 
+ int diva_xdi_write(void *adapter, void *os_handle, const void __user *src,
+-		   int length, divas_xdi_copy_from_user_fn_t cp_fn);
++		   int length, void *msg,
++		   divas_xdi_copy_from_user_fn_t cp_fn);
+ 
+ void *diva_xdi_open_adapter(void *os_handle, const void __user *src,
+-			    int length,
++			    int length, void *msg,
+ 			    divas_xdi_copy_from_user_fn_t cp_fn);
+ 
+ void diva_xdi_close_adapter(void *adapter, void *os_handle);
+diff --git a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c
+index b9980e84f9db..b6a3950b2564 100644
+--- a/drivers/isdn/hardware/eicon/divasmain.c
++++ b/drivers/isdn/hardware/eicon/divasmain.c
+@@ -591,19 +591,22 @@ static int divas_release(struct inode *inode, struct file *file)
+ static ssize_t divas_write(struct file *file, const char __user *buf,
+ 			   size_t count, loff_t *ppos)
+ {
++	diva_xdi_um_cfg_cmd_t msg;
+ 	int ret = -EINVAL;
+ 
+ 	if (!file->private_data) {
+ 		file->private_data = diva_xdi_open_adapter(file, buf,
+-							   count,
++							   count, &msg,
+ 							   xdi_copy_from_user);
+-	}
+-	if (!file->private_data) {
+-		return (-ENODEV);
++		if (!file->private_data)
++			return (-ENODEV);
++		ret = diva_xdi_write(file->private_data, file,
++				     buf, count, &msg, xdi_copy_from_user);
++	} else {
++		ret = diva_xdi_write(file->private_data, file,
++				     buf, count, NULL, xdi_copy_from_user);
+ 	}
+ 
+-	ret = diva_xdi_write(file->private_data, file,
+-			     buf, count, xdi_copy_from_user);
+ 	switch (ret) {
+ 	case -1:		/* Message should be removed from rx mailbox first */
+ 		ret = -EBUSY;
+@@ -622,11 +625,12 @@ static ssize_t divas_write(struct file *file, const char __user *buf,
+ static ssize_t divas_read(struct file *file, char __user *buf,
+ 			  size_t count, loff_t *ppos)
+ {
++	diva_xdi_um_cfg_cmd_t msg;
+ 	int ret = -EINVAL;
+ 
+ 	if (!file->private_data) {
+ 		file->private_data = diva_xdi_open_adapter(file, buf,
+-							   count,
++							   count, &msg,
+ 							   xdi_copy_from_user);
+ 	}
+ 	if (!file->private_data) {

commit 8e03477cb709b73a2c1e1f4349ee3b7b33c50416
+Author: Wenwen Wang 
+Date:   Sat May 5 08:02:21 2018 -0500
+
+    i2c: core: smbus: fix a potential missing-check bug
+    
+    In i2c_smbus_xfer_emulated(), the function i2c_transfer() is invoked to
+    transfer i2c messages. The number of actual transferred messages is
+    returned and saved to 'status'. If 'status' is negative, that means an
+    error occurred during the transfer process. In that case, the value of
+    'status' is an error code to indicate the reason of the transfer failure.
+    In most cases, i2c_transfer() can transfer 'num' messages with no error.
+    And so 'status' == 'num'. However, due to unexpected errors, it is probable
+    that only partial messages are transferred by i2c_transfer(). As a result,
+    'status' != 'num'. This special case is not checked after the invocation of
+    i2c_transfer() and can potentially lead to unexpected issues in the
+    following execution since it is expected that 'status' == 'num'.
+    
+    This patch checks the return value of i2c_transfer() and returns an error
+    code -EIO if the number of actual transferred messages 'status' is not
+    equal to 'num'.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: Wolfram Sang 
+
+diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c
+index b5aec33002c3..f3f683041e7f 100644
+--- a/drivers/i2c/i2c-core-smbus.c
++++ b/drivers/i2c/i2c-core-smbus.c
+@@ -466,6 +466,8 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
+ 	status = i2c_transfer(adapter, msg, num);
+ 	if (status < 0)
+ 		return status;
++	if (status != num)
++		return -EIO;
+ 
+ 	/* Check PEC if last message is a read */
+ 	if (i && (msg[num-1].flags & I2C_M_RD)) {

commit bd23a7269834dc7c1f93e83535d16ebc44b75eba
+Author: Wenwen Wang 
+Date:   Tue May 8 08:50:28 2018 -0500
+
+    virt: vbox: Only copy_from_user the request-header once
+    
+    In vbg_misc_device_ioctl(), the header of the ioctl argument is copied from
+    the userspace pointer 'arg' and saved to the kernel object 'hdr'. Then the
+    'version', 'size_in', and 'size_out' fields of 'hdr' are verified.
+    
+    Before this commit, after the checks a buffer for the entire request would
+    be allocated and then all data including the verified header would be
+    copied from the userspace 'arg' pointer again.
+    
+    Given that the 'arg' pointer resides in userspace, a malicious userspace
+    process can race to change the data pointed to by 'arg' between the two
+    copies. By doing so, the user can bypass the verifications on the ioctl
+    argument.
+    
+    This commit fixes this by using the already checked copy of the header
+    to fill the header part of the allocated buffer and only copying the
+    remainder of the data from userspace.
+    
+    Signed-off-by: Wenwen Wang 
+    Reviewed-by: Hans de Goede 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/virt/vboxguest/vboxguest_linux.c b/drivers/virt/vboxguest/vboxguest_linux.c
+index 398d22693234..6e2a9619192d 100644
+--- a/drivers/virt/vboxguest/vboxguest_linux.c
++++ b/drivers/virt/vboxguest/vboxguest_linux.c
+@@ -121,7 +121,9 @@ static long vbg_misc_device_ioctl(struct file *filp, unsigned int req,
+ 	if (!buf)
+ 		return -ENOMEM;
+ 
+-	if (copy_from_user(buf, (void *)arg, hdr.size_in)) {
++	*((struct vbg_ioctl_hdr *)buf) = hdr;
++	if (copy_from_user(buf + sizeof(hdr), (void *)arg + sizeof(hdr),
++			   hdr.size_in - sizeof(hdr))) {
+ 		ret = -EFAULT;
+ 		goto out;
+ 	}

commit 3f12888dfae2a48741c4caa9214885b3aaf350f9
+Author: Wenwen Wang 
+Date:   Sat May 5 13:38:03 2018 -0500
+
+    ALSA: control: fix a redundant-copy issue
+    
+    In snd_ctl_elem_add_compat(), the fields of the struct 'data' need to be
+    copied from the corresponding fields of the struct 'data32' in userspace.
+    This is achieved by invoking copy_from_user() and get_user() functions. The
+    problem here is that the 'type' field is copied twice. One is by
+    copy_from_user() and one is by get_user(). Given that the 'type' field is
+    not used between the two copies, the second copy is *completely* redundant
+    and should be removed for better performance and cleanup. Also, these two
+    copies can cause inconsistent data: as the struct 'data32' resides in
+    userspace and a malicious userspace process can race to change the 'type'
+    field between the two copies to cause inconsistent data. Depending on how
+    the data is used in the future, such an inconsistency may cause potential
+    security risks.
+    
+    For above reasons, we should take out the second copy.
+    
+    Signed-off-by: Wenwen Wang 
+    Cc: 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c
+index a848836a5de0..507fd5210c1c 100644
+--- a/sound/core/control_compat.c
++++ b/sound/core/control_compat.c
+@@ -396,8 +396,7 @@ static int snd_ctl_elem_add_compat(struct snd_ctl_file *file,
+ 	if (copy_from_user(&data->id, &data32->id, sizeof(data->id)) ||
+ 	    copy_from_user(&data->type, &data32->type, 3 * sizeof(u32)))
+ 		goto error;
+-	if (get_user(data->owner, &data32->owner) ||
+-	    get_user(data->type, &data32->type))
++	if (get_user(data->owner, &data32->owner))
+ 		goto error;
+ 	switch (data->type) {
+ 	case SNDRV_CTL_ELEM_TYPE_BOOLEAN:

commit 9899e4d3523faaef17c67141aa80ff2088f17871
+Author: Wenwen Wang 
+Date:   Mon May 7 19:54:01 2018 -0500
+
+    scsi: 3w-xxxx: fix a missing-check bug
+    
+    In tw_chrdev_ioctl(), the length of the data buffer is firstly copied
+    from the userspace pointer 'argp' and saved to the kernel object
+    'data_buffer_length'. Then a security check is performed on it to make
+    sure that the length is not more than 'TW_MAX_IOCTL_SECTORS *
+    512'. Otherwise, an error code -EINVAL is returned. If the security
+    check is passed, the entire ioctl command is copied again from the
+    'argp' pointer and saved to the kernel object 'tw_ioctl'. Then, various
+    operations are performed on 'tw_ioctl' according to the 'cmd'. Given
+    that the 'argp' pointer resides in userspace, a malicious userspace
+    process can race to change the buffer length between the two
+    copies. This way, the user can bypass the security check and inject
+    invalid data buffer length. This can cause potential security issues in
+    the following execution.
+    
+    This patch checks for capable(CAP_SYS_ADMIN) in tw_chrdev_open() to
+    avoid the above issues.
+    
+    Signed-off-by: Wenwen Wang 
+    Acked-by: Adam Radford 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
+index 33261b690774..f6179e3d6953 100644
+--- a/drivers/scsi/3w-xxxx.c
++++ b/drivers/scsi/3w-xxxx.c
+@@ -1033,6 +1033,9 @@ static int tw_chrdev_open(struct inode *inode, struct file *file)
+ 
+ 	dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_open()\n");
+ 
++	if (!capable(CAP_SYS_ADMIN))
++		return -EACCES;
++
+ 	minor_number = iminor(inode);
+ 	if (minor_number >= tw_device_extension_count)
+ 		return -ENODEV;

commit c9318a3e0218bc9dacc25be46b9eec363259536f
+Author: Wenwen Wang 
+Date:   Mon May 7 19:46:43 2018 -0500
+
+    scsi: 3w-9xxx: fix a missing-check bug
+    
+    In twa_chrdev_ioctl(), the ioctl driver command is firstly copied from
+    the userspace pointer 'argp' and saved to the kernel object
+    'driver_command'.  Then a security check is performed on the data buffer
+    size indicated by 'driver_command', which is
+    'driver_command.buffer_length'. If the security check is passed, the
+    entire ioctl command is copied again from the 'argp' pointer and saved
+    to the kernel object 'tw_ioctl'. Then, various operations are performed
+    on 'tw_ioctl' according to the 'cmd'. Given that the 'argp' pointer
+    resides in userspace, a malicious userspace process can race to change
+    the buffer size between the two copies. This way, the user can bypass
+    the security check and inject invalid data buffer size. This can cause
+    potential security issues in the following execution.
+    
+    This patch checks for capable(CAP_SYS_ADMIN) in twa_chrdev_open()t o
+    avoid the above issues.
+    
+    Signed-off-by: Wenwen Wang 
+    Acked-by: Adam Radford 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
+index b42c9c479d4b..99ba4a770406 100644
+--- a/drivers/scsi/3w-9xxx.c
++++ b/drivers/scsi/3w-9xxx.c
+@@ -882,6 +882,11 @@ static int twa_chrdev_open(struct inode *inode, struct file *file)
+ 	unsigned int minor_number;
+ 	int retval = TW_IOCTL_ERROR_OS_ENODEV;
+ 
++	if (!capable(CAP_SYS_ADMIN)) {
++		retval = -EACCES;
++		goto out;
++	}
++
+ 	minor_number = iminor(inode);
+ 	if (minor_number >= twa_device_extension_count)
+ 		goto out;

commit dc487321b1e6ab27f545fd8826ce3f76b01b63c2
+Author: Wenwen Wang 
+Date:   Mon Apr 30 17:56:10 2018 -0500
+
+    staging: lustre: llite: fix potential missing-check bug when copying lumv
+    
+    In ll_dir_ioctl(), the object lumv3 is firstly copied from the user space
+    using Its address, i.e., lumv1 = &lumv3. If the lmm_magic field of lumv3 is
+    LOV_USER_MAGIC_V3, lumv3 will be modified by the second copy from the user
+    space. The second copy is necessary, because the two versions (i.e.,
+    lov_user_md_v1 and lov_user_md_v3) have different data formats and lengths.
+    However, given that the user data resides in the user space, a malicious
+    user-space process can race to change the data between the two copies. By
+    doing so, the attacker can provide a data with an inconsistent version,
+    e.g., v1 version + v3 data. This can lead to logical errors in the
+    following execution in ll_dir_setstripe(), which performs different actions
+    according to the version specified by the field lmm_magic.
+    
+    This patch rechecks the version field lmm_magic in the second copy.  If the
+    version is not as expected, i.e., LOV_USER_MAGIC_V3, an error code will be
+    returned: -EINVAL.
+    
+    Signed-off-by: Wenwen Wang 
+    Reviewed-by: Andreas Dilger 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c
+index d10d27268323..80d44ca9516a 100644
+--- a/drivers/staging/lustre/lustre/llite/dir.c
++++ b/drivers/staging/lustre/lustre/llite/dir.c
+@@ -1185,6 +1185,8 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ 		if (lumv1->lmm_magic == LOV_USER_MAGIC_V3) {
+ 			if (copy_from_user(&lumv3, lumv3p, sizeof(lumv3)))
+ 				return -EFAULT;
++			if (lumv3.lmm_magic != LOV_USER_MAGIC_V3)
++				return -EINVAL;
+ 		}
+ 
+ 		if (is_root_inode(inode))

commit d656fe49e33df48ee6bc19e871f5862f49895c9e
+Author: Wenwen Wang 
+Date:   Mon Apr 30 12:31:13 2018 -0500
+
+    ethtool: fix a potential missing-check bug
+    
+    In ethtool_get_rxnfc(), the object "info" is firstly copied from
+    user-space. If the FLOW_RSS flag is set in the member field flow_type of
+    "info" (and cmd is ETHTOOL_GRXFH), info needs to be copied again from
+    user-space because FLOW_RSS is newer and has new definition, as mentioned
+    in the comment. However, given that the user data resides in user-space, a
+    malicious user can race to change the data after the first copy. By doing
+    so, the user can inject inconsistent data. For example, in the second
+    copy, the FLOW_RSS flag could be cleared in the field flow_type of "info".
+    In the following execution, "info" will be used in the function
+    ops->get_rxnfc(). Such inconsistent data can potentially lead to unexpected
+    information leakage since ops->get_rxnfc() will prepare various types of
+    data according to flow_type, and the prepared data will be eventually
+    copied to user-space. This inconsistent data may also cause undefined
+    behaviors based on how ops->get_rxnfc() is implemented.
+    
+    This patch simply re-verifies the flow_type field of "info" after the
+    second copy. If the value is not as expected, an error code will be
+    returned.
+    
+    Signed-off-by: Wenwen Wang 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/core/ethtool.c b/net/core/ethtool.c
+index 03416e6dd5d7..ba02f0dfe85c 100644
+--- a/net/core/ethtool.c
++++ b/net/core/ethtool.c
+@@ -1032,6 +1032,11 @@ static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev,
+ 		info_size = sizeof(info);
+ 		if (copy_from_user(&info, useraddr, info_size))
+ 			return -EFAULT;
++		/* Since malicious users may modify the original data,
++		 * we need to check whether FLOW_RSS is still requested.
++		 */
++		if (!(info.flow_type & FLOW_RSS))
++			return -EINVAL;
+ 	}
+ 
+ 	if (info.cmd == ETHTOOL_GRXCLSRLALL) {

commit 23779fbc99302dddab7f056ae47c3463169cbb64
+Author: Alireza Haghdoost 
+Date:   Wed Oct 23 17:08:16 2013 +0100
+
+    block: Enable sysfs nomerge control for I/O requests in the plug list
+    
+    This patch enables the sysfs to control I/O request merge
+    functionality in the plug list. While this control has been
+    implemented for the request queue, it was dismissed in the plug list.
+    Therefore, block layer merges requests together (or attempt to merge)
+    even if the merge capability was disable using sysfs nomerge parameter
+    value 2.
+    
+    This limitation is directly affects functionality of io_submit()
+    system call. The system call enables user to submit a bunch of IO
+    requests from user space using struct iocb **ios input argument.
+    However, the unconditioned merging functionality in the plug list
+    potentially merges these requests together down the road. Therefore,
+    there is no way to distinguish between an application sending bunch of
+    sequential IOs and an application sending one big IO. Ultimately, all
+    requests generated by the former app merge within the plug list
+    together and looks similar to the second app.
+    
+    While the merging functionality is a desirable feature to improve the
+    performance of IO subsystem for some applications, it is not useful
+    for other application like ours at all.
+    
+    Signed-off-by: Alireza Haghdoost 
+    Reviewed-by: Jeff Moyer 
+    
+    Coding style modified.
+    
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/blk-core.c b/block/blk-core.c
+index fce4b9387f36..25f13479f552 100644
+--- a/block/blk-core.c
++++ b/block/blk-core.c
+@@ -1429,6 +1429,9 @@ static bool attempt_plug_merge(struct request_queue *q, struct bio *bio,
+ 	struct request *rq;
+ 	bool ret = false;
+ 
++	if (blk_queue_nomerges(q))
++		goto out;
++
+ 	plug = current->plug;
+ 	if (!plug)
+ 		goto out;

commit ae0fda0cdf009731a33f031f86df8566f1977ffe
+Author: Dave C Boutcher 
+Date:   Thu Jul 6 22:08:49 2006 -0500
+
+    [SCSI] ibmvscsi: handle inactive SCSI target during probe
+    
+    Without this patch we register an interrupt with request_irq,
+    but then return a bad return code from the module probe.
+    
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c
+index 242b8873b333..ed22b96580c6 100644
+--- a/drivers/scsi/ibmvscsi/rpa_vscsi.c
++++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c
+@@ -238,6 +238,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
+ 	if (rc == 2) {
+ 		/* Adapter is good, but other end is not ready */
+ 		printk(KERN_WARNING "ibmvscsi: Partner adapter not ready\n");
++		retrc = 0;
+ 	} else if (rc != 0) {
+ 		printk(KERN_WARNING "ibmvscsi: Error %d opening adapter\n", rc);
+ 		goto reg_crq_failed;

commit 6c51fe10475eda9f5c535f337411e1ed0e6915b9
+Author: Dave C Boutcher 
+Date:   Thu Jul 6 22:07:47 2006 -0500
+
+    [SCSI] ibmvscsi: allocate lpevents for ibmvscsi on iseries
+    
+    Allocate the correct number of lp events when running
+    ibmvscsi on legacy iseries
+    
+    Signed-off-by: Dave Boutcher 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/ibmvscsi/iseries_vscsi.c b/drivers/scsi/ibmvscsi/iseries_vscsi.c
+index 7eed0b098171..6aeb5f003c3c 100644
+--- a/drivers/scsi/ibmvscsi/iseries_vscsi.c
++++ b/drivers/scsi/ibmvscsi/iseries_vscsi.c
+@@ -81,7 +81,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
+ 	int rc;
+ 
+ 	single_host_data = hostdata;
+-	rc = viopath_open(viopath_hostLp, viomajorsubtype_scsi, 0);
++	rc = viopath_open(viopath_hostLp, viomajorsubtype_scsi, max_requests);
+ 	if (rc < 0) {
+ 		printk("viopath_open failed with rc %d in open_event_path\n",
+ 		       rc);

commit cefbda2d6cd9bf78a93768130729a6d142588d67
+Author: Dave C Boutcher 
+Date:   Mon Jun 12 21:22:51 2006 -0500
+
+    [SCSI] ibmvscsi: treat busy and error conditions separately
+    
+    This patch fixes a condition where ibmvscsi treats a transport error as a
+    "busy" condition, so no errors were returned to the scsi mid-layer.
+    In a RAID environment this means that I/O hung rather than failing
+    over.
+    
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
+index 944fc1203ebd..669ea4fff166 100644
+--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
++++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
+@@ -535,6 +535,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
+ 				   struct ibmvscsi_host_data *hostdata)
+ {
+ 	u64 *crq_as_u64 = (u64 *) &evt_struct->crq;
++	int request_status;
+ 	int rc;
+ 
+ 	/* If we have exhausted our request limit, just fail this request.
+@@ -542,9 +543,18 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
+ 	 * (such as task management requests) that the mid layer may think we
+ 	 * can handle more requests (can_queue) when we actually can't
+ 	 */
+-	if ((evt_struct->crq.format == VIOSRP_SRP_FORMAT) &&
+-	    (atomic_dec_if_positive(&hostdata->request_limit) < 0))
+-		goto send_error;
++	if (evt_struct->crq.format == VIOSRP_SRP_FORMAT) {
++		request_status =
++			atomic_dec_if_positive(&hostdata->request_limit);
++		/* If request limit was -1 when we started, it is now even
++		 * less than that
++		 */
++		if (request_status < -1)
++			goto send_error;
++		/* Otherwise, if we have run out of requests */
++		else if (request_status < 0)
++			goto send_busy;
++	}
+ 
+ 	/* Copy the IU into the transfer area */
+ 	*evt_struct->xfer_iu = evt_struct->iu;
+@@ -567,11 +577,23 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
+ 
+ 	return 0;
+ 
+- send_error:
++ send_busy:
+ 	unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev);
+ 
+ 	free_event_struct(&hostdata->pool, evt_struct);
+  	return SCSI_MLQUEUE_HOST_BUSY;
++
++ send_error:
++	unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev);
++
++	if (evt_struct->cmnd != NULL) {
++		evt_struct->cmnd->result = DID_ERROR << 16;
++		evt_struct->cmnd_done(evt_struct->cmnd);
++	} else if (evt_struct->done)
++		evt_struct->done(evt_struct);
++
++	free_event_struct(&hostdata->pool, evt_struct);
++	return 0;
+ }
+ 
+ /**
+@@ -1184,27 +1206,37 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq,
+ 		return;
+ 	case 0xFF:	/* Hypervisor telling us the connection is closed */
+ 		scsi_block_requests(hostdata->host);
++		atomic_set(&hostdata->request_limit, 0);
+ 		if (crq->format == 0x06) {
+ 			/* We need to re-setup the interpartition connection */
+ 			printk(KERN_INFO
+ 			       "ibmvscsi: Re-enabling adapter!\n");
+-			atomic_set(&hostdata->request_limit, -1);
+ 			purge_requests(hostdata, DID_REQUEUE);
+-			if (ibmvscsi_reenable_crq_queue(&hostdata->queue,
+-							hostdata) == 0)
+-				if (ibmvscsi_send_crq(hostdata,
+-						      0xC001000000000000LL, 0))
++			if ((ibmvscsi_reenable_crq_queue(&hostdata->queue,
++							hostdata) == 0) ||
++			    (ibmvscsi_send_crq(hostdata,
++					       0xC001000000000000LL, 0))) {
++					atomic_set(&hostdata->request_limit,
++						   -1);
+ 					printk(KERN_ERR
+-					       "ibmvscsi: transmit error after"
++					       "ibmvscsi: error after"
+ 					       " enable\n");
++			}
+ 		} else {
+ 			printk(KERN_INFO
+ 			       "ibmvscsi: Virtual adapter failed rc %d!\n",
+ 			       crq->format);
+ 
+-			atomic_set(&hostdata->request_limit, -1);
+ 			purge_requests(hostdata, DID_ERROR);
+-			ibmvscsi_reset_crq_queue(&hostdata->queue, hostdata);
++			if ((ibmvscsi_reset_crq_queue(&hostdata->queue,
++							hostdata)) ||
++			    (ibmvscsi_send_crq(hostdata,
++					       0xC001000000000000LL, 0))) {
++					atomic_set(&hostdata->request_limit,
++						   -1);
++					printk(KERN_ERR
++					       "ibmvscsi: error after reset\n");
++			}
+ 		}
+ 		scsi_unblock_requests(hostdata->host);
+ 		return;
+@@ -1467,6 +1499,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
+ 	struct Scsi_Host *host;
+ 	struct device *dev = &vdev->dev;
+ 	unsigned long wait_switch = 0;
++	int rc;
+ 
+ 	vdev->dev.driver_data = NULL;
+ 
+@@ -1484,8 +1517,8 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
+ 	atomic_set(&hostdata->request_limit, -1);
+ 	hostdata->host->max_sectors = 32 * 8; /* default max I/O 32 pages */
+ 
+-	if (ibmvscsi_init_crq_queue(&hostdata->queue, hostdata,
+-				    max_requests) != 0) {
++	rc = ibmvscsi_init_crq_queue(&hostdata->queue, hostdata, max_requests);
++	if (rc != 0 && rc != H_RESOURCE) {
+ 		printk(KERN_ERR "ibmvscsi: couldn't initialize crq\n");
+ 		goto init_crq_failed;
+ 	}
+@@ -1505,7 +1538,8 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
+ 	 * to fail if the other end is not acive.  In that case we don't
+ 	 * want to scan
+ 	 */
+-	if (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0) == 0) {
++	if (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0) == 0
++	    || rc == H_RESOURCE) {
+ 		/*
+ 		 * Wait around max init_timeout secs for the adapter to finish
+ 		 * initializing. When we are done initializing, we will have a
+diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c
+index 1a9992bdfef8..242b8873b333 100644
+--- a/drivers/scsi/ibmvscsi/rpa_vscsi.c
++++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c
+@@ -208,6 +208,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
+ 			    int max_requests)
+ {
+ 	int rc;
++	int retrc;
+ 	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
+ 
+ 	queue->msgs = (struct viosrp_crq *)get_zeroed_page(GFP_KERNEL);
+@@ -226,7 +227,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
+ 	gather_partition_info();
+ 	set_adapter_info(hostdata);
+ 
+-	rc = plpar_hcall_norets(H_REG_CRQ,
++	retrc = rc = plpar_hcall_norets(H_REG_CRQ,
+ 				vdev->unit_address,
+ 				queue->msg_token, PAGE_SIZE);
+ 	if (rc == H_RESOURCE)
+@@ -263,7 +264,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
+ 	tasklet_init(&hostdata->srp_task, (void *)ibmvscsi_task,
+ 		     (unsigned long)hostdata);
+ 
+-	return 0;
++	return retrc;
+ 
+       req_irq_failed:
+ 	do {

commit 368a6ba5d188552aea2a668301a259164c9f355e
+Author: Dave C Boutcher 
+Date:   Mon Jun 12 19:49:20 2006 -0500
+
+    [POWERPC] check firmware state before suspending
+    
+    Currently the kernel blindly halts all the processors and calls the
+    ibm,suspend-me rtas call.  If the firmware is not in the correct
+    state, we then re-start all the processors and return.  It is much
+    smarter to first check the firmware state, and only if it is waiting,
+    call the ibm,suspend-me call.
+    
+    Signed-off-by: Paul Mackerras 
+
+diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
+index 13496f319855..fd15e3e3bb33 100644
+--- a/arch/powerpc/kernel/rtas.c
++++ b/arch/powerpc/kernel/rtas.c
+@@ -593,9 +593,31 @@ static void rtas_percpu_suspend_me(void *info)
+ static int rtas_ibm_suspend_me(struct rtas_args *args)
+ {
+ 	int i;
++	long state;
++	long rc;
++	unsigned long dummy;
+ 
+ 	struct rtas_suspend_me_data data;
+ 
++	/* Make sure the state is valid */
++	rc = plpar_hcall(H_VASI_STATE,
++			 ((u64)args->args[0] << 32) | args->args[1],
++			 0, 0, 0,
++			 &state, &dummy, &dummy);
++
++	if (rc) {
++		printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned %ld\n",rc);
++		return rc;
++	} else if (state == H_VASI_ENABLED) {
++		args->args[args->nargs] = RTAS_NOT_SUSPENDABLE;
++		return 0;
++	} else if (state != H_VASI_SUSPENDING) {
++		printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned state %ld\n",
++		       state);
++		args->args[args->nargs] = -1;
++		return 0;
++	}
++
+ 	data.waiting = 1;
+ 	data.args = args;
+ 
+diff --git a/include/asm-powerpc/hvcall.h b/include/asm-powerpc/hvcall.h
+index 6cc7e1fb7bfd..0d3c4e85711a 100644
+--- a/include/asm-powerpc/hvcall.h
++++ b/include/asm-powerpc/hvcall.h
+@@ -102,6 +102,15 @@
+ #define H_PP1			(1UL<<(63-62))
+ #define H_PP2			(1UL<<(63-63))
+ 
++/* VASI States */
++#define H_VASI_INVALID          0
++#define H_VASI_ENABLED          1
++#define H_VASI_ABORTED          2
++#define H_VASI_SUSPENDING       3
++#define H_VASI_SUSPENDED        4
++#define H_VASI_RESUMED          5
++#define H_VASI_COMPLETED        6
++
+ /* DABRX flags */
+ #define H_DABRX_HYPERVISOR	(1UL<<(63-61))
+ #define H_DABRX_KERNEL		(1UL<<(63-62))
+@@ -190,6 +199,7 @@
+ #define H_QUERY_INT_STATE       0x1E4
+ #define H_POLL_PENDING		0x1D8
+ #define H_JOIN			0x298
++#define H_VASI_STATE            0x2A4
+ #define H_ENABLE_CRQ		0x2B0
+ 
+ #ifndef __ASSEMBLY__
+diff --git a/include/asm-powerpc/rtas.h b/include/asm-powerpc/rtas.h
+index a3b4e55569c7..02e213e3d69f 100644
+--- a/include/asm-powerpc/rtas.h
++++ b/include/asm-powerpc/rtas.h
+@@ -24,6 +24,7 @@
+ #define RTAS_RMOBUF_MAX (64 * 1024)
+ 
+ /* RTAS return status codes */
++#define RTAS_NOT_SUSPENDABLE	-9004
+ #define RTAS_BUSY		-2    /* RTAS Busy */
+ #define RTAS_EXTENDED_DELAY_MIN	9900
+ #define RTAS_EXTENDED_DELAY_MAX	9905

commit 9b833e428ad24dc7cec2c0c7e6898caa91449c95
+Author: Dave C Boutcher 
+Date:   Thu Mar 23 13:47:07 2006 -0600
+
+    [SCSI] ibmvscsi: prevent scsi commands being sent in invalid state
+    
+    There is a window where we can be re-enabling an adapter, but
+    still allow SCSI commands to be sent to the target.  This fix
+    sets our window (request_limit) to -1 as soon as we know the
+    adapter is being reenabled, and closes a very teeny tiny
+    window where we could set the window back to 1 before we
+    grab a lock.
+    
+    Signed-off-by: Dave Boutcher 
+    Signed-off-by: James Bottomley 
+
+diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
+index eaefeddb2b4a..a279d0a8dff5 100644
+--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
++++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
+@@ -853,14 +853,15 @@ static int send_srp_login(struct ibmvscsi_host_data *hostdata)
+ 	login->max_requested_initiator_to_target_iulen = sizeof(union srp_iu);
+ 	login->required_buffer_formats = 0x0006;
+ 	
++	spin_lock_irqsave(hostdata->host->host_lock, flags);
+ 	/* Start out with a request limit of 1, since this is negotiated in
+ 	 * the login request we are just sending
+ 	 */
+ 	atomic_set(&hostdata->request_limit, 1);
+ 
+-	spin_lock_irqsave(hostdata->host->host_lock, flags);
+ 	rc = ibmvscsi_send_srp_event(evt_struct, hostdata);
+ 	spin_unlock_irqrestore(hostdata->host->host_lock, flags);
++	printk("ibmvscsic: sent SRP login\n");
+ 	return rc;
+ };
+ 
+@@ -1179,6 +1180,7 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq,
+ 			/* We need to re-setup the interpartition connection */
+ 			printk(KERN_INFO
+ 			       "ibmvscsi: Re-enabling adapter!\n");
++			atomic_set(&hostdata->request_limit, -1);
+ 			purge_requests(hostdata, DID_REQUEUE);
+ 			if (ibmvscsi_reenable_crq_queue(&hostdata->queue,
+ 							hostdata) == 0)

commit b4fd884a037c791a39f2f03da719e251af176a97
+Author: Dave C Boutcher 
+Date:   Fri Feb 3 01:18:36 2006 -0600
+
+    [PATCH] powerpc: remove useless call to touch_softlockup_watchdog
+    
+    It turns out that we can't stop the watchdog from
+    triggering here.  If we touch the timer (which just uses the current jiffie
+    value) before we enable interrupts, it does nothing because jiffies
+    are not mass-updated until after we enable interrupts.  If we touch the
+    timer after we enable interrupts, its too late because the softlockup
+    watchdog will already have triggered.  The touch_softlockup_watchdog
+    call removed below does nothing.
+    
+    Signed-off-by: Dave Boutcher 
+    Signed-off-by: Paul Mackerras 
+
+diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
+index 0c6ed6d75b17..b5b2add7ad1e 100644
+--- a/arch/powerpc/kernel/rtas.c
++++ b/arch/powerpc/kernel/rtas.c
+@@ -599,10 +599,6 @@ static void rtas_percpu_suspend_me(void *info)
+ 	}
+ 
+ out:
+-	/* before we restore interrupts, make sure we don't
+-	 * generate a spurious soft lockup errors
+-	 */
+-	touch_softlockup_watchdog();
+ 	local_irq_restore(flags);
+ 	return;
+ }

commit 82a4df74628a3bf0ac762be198b45e02a7c5879f
+Author: Dave C Boutcher 
+Date:   Fri Feb 3 01:18:39 2006 -0600
+
+    [PATCH] powerpc: prod all processors after ibm,suspend-me
+    
+    We need to prod everyone here since this is the only CPU that is
+    guaranteed to be running after the ibm,suspend-me RTAS call returns.
+    
+    Signed-off-by: Dave Boutcher 
+    Signed-off-by: Paul Mackerras 
+
+diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
+index f9b34e3ccf5a..0c6ed6d75b17 100644
+--- a/arch/powerpc/kernel/rtas.c
++++ b/arch/powerpc/kernel/rtas.c
+@@ -566,6 +566,7 @@ static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE;
+ #ifdef CONFIG_PPC_PSERIES
+ static void rtas_percpu_suspend_me(void *info)
+ {
++	int i;
+ 	long rc;
+ 	long flags;
+ 	struct rtas_suspend_me_data *data =
+@@ -590,6 +591,8 @@ static void rtas_percpu_suspend_me(void *info)
+ 		data->waiting = 0;
+ 		data->args->args[data->args->nargs] =
+ 			rtas_call(ibm_suspend_me_token, 0, 1, NULL);
++		for_each_cpu(i)
++			plpar_hcall_norets(H_PROD,i);
+ 	} else {
+ 		data->waiting = -EBUSY;
+ 		printk(KERN_ERR "Error on H_Join hypervisor call\n");

commit c4cb8ecca66e3f136f66b5b30ec189530290a9b9
+Author: Dave C Boutcher 
+Date:   Fri Feb 3 01:18:46 2006 -0600
+
+    [PATCH] powerpc: return correct rtas status from ibm,suspend-me
+    
+    Correctly return the status from the RTAS call.  rtas_call expects
+    to return the status as a return value.
+    
+    Signed-off-by: Dave Boutcher 
+    Signed-off-by: Paul Mackerras 
+
+diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
+index b7092a47064b..f9b34e3ccf5a 100644
+--- a/arch/powerpc/kernel/rtas.c
++++ b/arch/powerpc/kernel/rtas.c
+@@ -588,8 +588,8 @@ static void rtas_percpu_suspend_me(void *info)
+ 
+ 	if (rc == H_Continue) {
+ 		data->waiting = 0;
+-		rtas_call(ibm_suspend_me_token, 0, 1,
+-			  data->args->args);
++		data->args->args[data->args->nargs] =
++			rtas_call(ibm_suspend_me_token, 0, 1, NULL);
+ 	} else {
+ 		data->waiting = -EBUSY;
+ 		printk(KERN_ERR "Error on H_Join hypervisor call\n");

\ No newline at end of file diff --git a/detail/74.html b/detail/74.html new file mode 100644 index 0000000..244dba8 --- /dev/null +++ b/detail/74.html @@ -0,0 +1,349 @@ +

Patches contributed by North Carolina State University


commit ae27e98a51526595837ab7498b23d6478a198960
+Author: Sangtae Ha 
+Date:   Wed Oct 29 00:07:18 2008 -0400
+
+    [TCP] CUBIC v2.3
+    
+    Signed-off-by: Sangtae Ha 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c
+index 4a1221e5e8ee..ee467ec40c4f 100644
+--- a/net/ipv4/tcp_cubic.c
++++ b/net/ipv4/tcp_cubic.c
+@@ -1,13 +1,23 @@
+ /*
+- * TCP CUBIC: Binary Increase Congestion control for TCP v2.2
++ * TCP CUBIC: Binary Increase Congestion control for TCP v2.3
+  * Home page:
+  *      http://netsrv.csc.ncsu.edu/twiki/bin/view/Main/BIC
+  * This is from the implementation of CUBIC TCP in
+- * Injong Rhee, Lisong Xu.
+- *  "CUBIC: A New TCP-Friendly High-Speed TCP Variant
+- *  in PFLDnet 2005
++ * Sangtae Ha, Injong Rhee and Lisong Xu,
++ *  "CUBIC: A New TCP-Friendly High-Speed TCP Variant"
++ *  in ACM SIGOPS Operating System Review, July 2008.
+  * Available from:
+- *  http://netsrv.csc.ncsu.edu/export/cubic-paper.pdf
++ *  http://netsrv.csc.ncsu.edu/export/cubic_a_new_tcp_2008.pdf
++ *
++ * CUBIC integrates a new slow start algorithm, called HyStart.
++ * The details of HyStart are presented in
++ *  Sangtae Ha and Injong Rhee,
++ *  "Taming the Elephants: New TCP Slow Start", NCSU TechReport 2008.
++ * Available from:
++ *  http://netsrv.csc.ncsu.edu/export/hystart_techreport_2008.pdf
++ *
++ * All testing results are available from:
++ * http://netsrv.csc.ncsu.edu/wiki/index.php/TCP_Testing
+  *
+  * Unless CUBIC is enabled and congestion window is large
+  * this behaves the same as the original Reno.
+@@ -23,12 +33,26 @@
+ 					 */
+ #define	BICTCP_HZ		10	/* BIC HZ 2^10 = 1024 */
+ 
++/* Two methods of hybrid slow start */
++#define HYSTART_ACK_TRAIN	0x1
++#define HYSTART_DELAY		0x2
++
++/* Number of delay samples for detecting the increase of delay */
++#define HYSTART_MIN_SAMPLES	8
++#define HYSTART_DELAY_MIN	(2U<<3)
++#define HYSTART_DELAY_MAX	(16U<<3)
++#define HYSTART_DELAY_THRESH(x)	clamp(x, HYSTART_DELAY_MIN, HYSTART_DELAY_MAX)
++
+ static int fast_convergence __read_mostly = 1;
+ static int beta __read_mostly = 717;	/* = 717/1024 (BICTCP_BETA_SCALE) */
+ static int initial_ssthresh __read_mostly;
+ static int bic_scale __read_mostly = 41;
+ static int tcp_friendliness __read_mostly = 1;
+ 
++static int hystart __read_mostly = 1;
++static int hystart_detect __read_mostly = HYSTART_ACK_TRAIN | HYSTART_DELAY;
++static int hystart_low_window __read_mostly = 16;
++
+ static u32 cube_rtt_scale __read_mostly;
+ static u32 beta_scale __read_mostly;
+ static u64 cube_factor __read_mostly;
+@@ -44,6 +68,13 @@ module_param(bic_scale, int, 0444);
+ MODULE_PARM_DESC(bic_scale, "scale (scaled by 1024) value for bic function (bic_scale/1024)");
+ module_param(tcp_friendliness, int, 0644);
+ MODULE_PARM_DESC(tcp_friendliness, "turn on/off tcp friendliness");
++module_param(hystart, int, 0644);
++MODULE_PARM_DESC(hystart, "turn on/off hybrid slow start algorithm");
++module_param(hystart_detect, int, 0644);
++MODULE_PARM_DESC(hystart_detect, "hyrbrid slow start detection mechanisms"
++		 " 1: packet-train 2: delay 3: both packet-train and delay");
++module_param(hystart_low_window, int, 0644);
++MODULE_PARM_DESC(hystart_low_window, "lower bound cwnd for hybrid slow start");
+ 
+ /* BIC TCP Parameters */
+ struct bictcp {
+@@ -59,7 +90,13 @@ struct bictcp {
+ 	u32	ack_cnt;	/* number of acks */
+ 	u32	tcp_cwnd;	/* estimated tcp cwnd */
+ #define ACK_RATIO_SHIFT	4
+-	u32	delayed_ack;	/* estimate the ratio of Packets/ACKs << 4 */
++	u16	delayed_ack;	/* estimate the ratio of Packets/ACKs << 4 */
++	u8	sample_cnt;	/* number of samples to decide curr_rtt */
++	u8	found;		/* the exit point is found? */
++	u32	round_start;	/* beginning of each round */
++	u32	end_seq;	/* end_seq of the round */
++	u32	last_jiffies;	/* last time when the ACK spacing is close */
++	u32	curr_rtt;	/* the minimum rtt of current round */
+ };
+ 
+ static inline void bictcp_reset(struct bictcp *ca)
+@@ -76,12 +113,28 @@ static inline void bictcp_reset(struct bictcp *ca)
+ 	ca->delayed_ack = 2 << ACK_RATIO_SHIFT;
+ 	ca->ack_cnt = 0;
+ 	ca->tcp_cwnd = 0;
++	ca->found = 0;
++}
++
++static inline void bictcp_hystart_reset(struct sock *sk)
++{
++	struct tcp_sock *tp = tcp_sk(sk);
++	struct bictcp *ca = inet_csk_ca(sk);
++
++	ca->round_start = ca->last_jiffies = jiffies;
++	ca->end_seq = tp->snd_nxt;
++	ca->curr_rtt = 0;
++	ca->sample_cnt = 0;
+ }
+ 
+ static void bictcp_init(struct sock *sk)
+ {
+ 	bictcp_reset(inet_csk_ca(sk));
+-	if (initial_ssthresh)
++
++	if (hystart)
++		bictcp_hystart_reset(sk);
++
++	if (!hystart && initial_ssthresh)
+ 		tcp_sk(sk)->snd_ssthresh = initial_ssthresh;
+ }
+ 
+@@ -235,9 +288,11 @@ static void bictcp_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)
+ 	if (!tcp_is_cwnd_limited(sk, in_flight))
+ 		return;
+ 
+-	if (tp->snd_cwnd <= tp->snd_ssthresh)
++	if (tp->snd_cwnd <= tp->snd_ssthresh) {
++		if (hystart && after(ack, ca->end_seq))
++			bictcp_hystart_reset(sk);
+ 		tcp_slow_start(tp);
+-	else {
++	} else {
+ 		bictcp_update(ca, tp->snd_cwnd);
+ 
+ 		/* In dangerous area, increase slowly.
+@@ -281,8 +336,45 @@ static u32 bictcp_undo_cwnd(struct sock *sk)
+ 
+ static void bictcp_state(struct sock *sk, u8 new_state)
+ {
+-	if (new_state == TCP_CA_Loss)
++	if (new_state == TCP_CA_Loss) {
+ 		bictcp_reset(inet_csk_ca(sk));
++		bictcp_hystart_reset(sk);
++	}
++}
++
++static void hystart_update(struct sock *sk, u32 delay)
++{
++	struct tcp_sock *tp = tcp_sk(sk);
++	struct bictcp *ca = inet_csk_ca(sk);
++
++	if (!(ca->found & hystart_detect)) {
++		u32 curr_jiffies = jiffies;
++
++		/* first detection parameter - ack-train detection */
++		if (curr_jiffies - ca->last_jiffies <= msecs_to_jiffies(2)) {
++			ca->last_jiffies = curr_jiffies;
++			if (curr_jiffies - ca->round_start >= ca->delay_min>>4)
++				ca->found |= HYSTART_ACK_TRAIN;
++		}
++
++		/* obtain the minimum delay of more than sampling packets */
++		if (ca->sample_cnt < HYSTART_MIN_SAMPLES) {
++			if (ca->curr_rtt == 0 || ca->curr_rtt > delay)
++				ca->curr_rtt = delay;
++
++			ca->sample_cnt++;
++		} else {
++			if (ca->curr_rtt > ca->delay_min +
++			    HYSTART_DELAY_THRESH(ca->delay_min>>4))
++				ca->found |= HYSTART_DELAY;
++		}
++		/*
++		 * Either one of two conditions are met,
++		 * we exit from slow start immediately.
++		 */
++		if (ca->found & hystart_detect)
++			tp->snd_ssthresh = tp->snd_cwnd;
++	}
+ }
+ 
+ /* Track delayed acknowledgment ratio using sliding window
+@@ -291,6 +383,7 @@ static void bictcp_state(struct sock *sk, u8 new_state)
+ static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us)
+ {
+ 	const struct inet_connection_sock *icsk = inet_csk(sk);
++	const struct tcp_sock *tp = tcp_sk(sk);
+ 	struct bictcp *ca = inet_csk_ca(sk);
+ 	u32 delay;
+ 
+@@ -314,6 +407,11 @@ static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us)
+ 	/* first time call or link delay decreases */
+ 	if (ca->delay_min == 0 || ca->delay_min > delay)
+ 		ca->delay_min = delay;
++
++	/* hystart triggers when cwnd is larger than some threshold */
++	if (hystart && tp->snd_cwnd <= tp->snd_ssthresh &&
++	    tp->snd_cwnd >= hystart_low_window)
++		hystart_update(sk, delay);
+ }
+ 
+ static struct tcp_congestion_ops cubictcp = {
+@@ -372,4 +470,4 @@ module_exit(cubictcp_unregister);
+ MODULE_AUTHOR("Sangtae Ha, Stephen Hemminger");
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("CUBIC TCP");
+-MODULE_VERSION("2.2");
++MODULE_VERSION("2.3");

commit 6b3d626321c1d4ce9138a86b047dfafc6a403016
+Author: Sangtae Ha 
+Date:   Tue Mar 4 14:17:41 2008 -0800
+
+    [TCP]: TCP cubic v2.2
+    
+    We have updated CUBIC to fix some issues with slow increase in large
+    BDP networks. We also improved its convergence speed. The fix is in
+    fact very simple -- the window increase limit of smax during the
+    window probing phase (i.e., convex growth phase) is removed. We found
+    that this does not affect TCP friendliness, but only improves its
+    scalability. We have run some tests in our lab and also over the
+    Internet path from NCSU to Japan. These results can be seen from the
+    following page:
+    
+    http://netsrv.csc.ncsu.edu/wiki/index.php/Intra_protocol_fairness_testing_with_linux-2.6.23.9
+    http://netsrv.csc.ncsu.edu/wiki/index.php/RTT_fairness_testing_with_linux-2.6.23.9
+    http://netsrv.csc.ncsu.edu/wiki/index.php/TCP_friendliness_testing_with_linux-2.6.23.9
+    
+    Signed-off-by: Sangtae Ha 
+    Signed-off-by: Stephen Hemminger 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c
+index 3aa0b23c1ea0..eb5b9854c8c7 100644
+--- a/net/ipv4/tcp_cubic.c
++++ b/net/ipv4/tcp_cubic.c
+@@ -1,12 +1,13 @@
+ /*
+- * TCP CUBIC: Binary Increase Congestion control for TCP v2.1
+- *
++ * TCP CUBIC: Binary Increase Congestion control for TCP v2.2
++ * Home page:
++ *      http://netsrv.csc.ncsu.edu/twiki/bin/view/Main/BIC
+  * This is from the implementation of CUBIC TCP in
+  * Injong Rhee, Lisong Xu.
+  *  "CUBIC: A New TCP-Friendly High-Speed TCP Variant
+  *  in PFLDnet 2005
+  * Available from:
+- *  http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/cubic-paper.pdf
++ *  http://netsrv.csc.ncsu.edu/export/cubic-paper.pdf
+  *
+  * Unless CUBIC is enabled and congestion window is large
+  * this behaves the same as the original Reno.
+@@ -20,15 +21,10 @@
+ #define BICTCP_BETA_SCALE    1024	/* Scale factor beta calculation
+ 					 * max_cwnd = snd_cwnd * beta
+ 					 */
+-#define BICTCP_B		4	 /*
+-					  * In binary search,
+-					  * go to point (max+min)/N
+-					  */
+ #define	BICTCP_HZ		10	/* BIC HZ 2^10 = 1024 */
+ 
+ static int fast_convergence __read_mostly = 1;
+-static int max_increment __read_mostly = 16;
+-static int beta __read_mostly = 819;	/* = 819/1024 (BICTCP_BETA_SCALE) */
++static int beta __read_mostly = 717;	/* = 717/1024 (BICTCP_BETA_SCALE) */
+ static int initial_ssthresh __read_mostly;
+ static int bic_scale __read_mostly = 41;
+ static int tcp_friendliness __read_mostly = 1;
+@@ -40,9 +36,7 @@ static u64 cube_factor __read_mostly;
+ /* Note parameters that are used for precomputing scale factors are read-only */
+ module_param(fast_convergence, int, 0644);
+ MODULE_PARM_DESC(fast_convergence, "turn on/off fast convergence");
+-module_param(max_increment, int, 0644);
+-MODULE_PARM_DESC(max_increment, "Limit on increment allowed during binary search");
+-module_param(beta, int, 0444);
++module_param(beta, int, 0644);
+ MODULE_PARM_DESC(beta, "beta for multiplicative increase");
+ module_param(initial_ssthresh, int, 0644);
+ MODULE_PARM_DESC(initial_ssthresh, "initial value of slow start threshold");
+@@ -145,7 +139,7 @@ static u32 cubic_root(u64 a)
+ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
+ {
+ 	u64 offs;
+-	u32 delta, t, bic_target, min_cnt, max_cnt;
++	u32 delta, t, bic_target, max_cnt;
+ 
+ 	ca->ack_cnt++;	/* count the number of ACKs */
+ 
+@@ -211,19 +205,6 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
+ 		ca->cnt = 100 * cwnd;              /* very small increment*/
+ 	}
+ 
+-	if (ca->delay_min > 0) {
+-		/* max increment = Smax * rtt / 0.1  */
+-		min_cnt = (cwnd * HZ * 8)/(10 * max_increment * ca->delay_min);
+-
+-		/* use concave growth when the target is above the origin */
+-		if (ca->cnt < min_cnt && t >= ca->bic_K)
+-			ca->cnt = min_cnt;
+-	}
+-
+-	/* slow start and low utilization  */
+-	if (ca->loss_cwnd == 0)		/* could be aggressive in slow start */
+-		ca->cnt = 50;
+-
+ 	/* TCP Friendly */
+ 	if (tcp_friendliness) {
+ 		u32 scale = beta_scale;
+@@ -391,4 +372,4 @@ module_exit(cubictcp_unregister);
+ MODULE_AUTHOR("Sangtae Ha, Stephen Hemminger");
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("CUBIC TCP");
+-MODULE_VERSION("2.1");
++MODULE_VERSION("2.2");

commit 0bc8c7bf9e7440500fe04f95d6cddc58ea023cd2
+Author: Sangtae Ha 
+Date:   Thu Feb 28 22:14:32 2008 -0800
+
+    [TCP]: BIC web page link is corrected.
+    
+    Signed-off-by: Sangtae Ha 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv4/tcp_bic.c b/net/ipv4/tcp_bic.c
+index 5212ed9b0c98..7eb7636db0d0 100644
+--- a/net/ipv4/tcp_bic.c
++++ b/net/ipv4/tcp_bic.c
+@@ -1,12 +1,13 @@
+ /*
+  * Binary Increase Congestion control for TCP
+- *
++ * Home page:
++ *      http://netsrv.csc.ncsu.edu/twiki/bin/view/Main/BIC
+  * This is from the implementation of BICTCP in
+  * Lison-Xu, Kahaled Harfoush, and Injong Rhee.
+  *  "Binary Increase Congestion Control for Fast, Long Distance
+  *  Networks" in InfoComm 2004
+  * Available from:
+- *  http://www.csc.ncsu.edu/faculty/rhee/export/bitcp.pdf
++ *  http://netsrv.csc.ncsu.edu/export/bitcp.pdf
+  *
+  * Unless BIC is enabled and congestion window is large
+  * this behaves the same as the original Reno.

\ No newline at end of file diff --git a/detail/8.html b/detail/8.html new file mode 100644 index 0000000..37ce85d --- /dev/null +++ b/detail/8.html @@ -0,0 +1,19764 @@ +

Patches contributed by University of New South Wales


commit d5608a0578a07766a97c00904d85f6a7221ddb37
+Author: Michael Zhou 
+Date:   Fri Aug 7 01:15:25 2020 +1000
+
+    netfilter: ip6t_NPT: rewrite addresses in ICMPv6 original packet
+    
+    Detect and rewrite a prefix embedded in an ICMPv6 original packet that was
+    rewritten by a corresponding DNPT/SNPT rule so it will be recognised by
+    the host that sent the original packet.
+    
+    Example
+    
+    Rules in effect on the 1:2:3:4::/64 + 5:6:7:8::/64 side router:
+    * SNPT src-pfx 1:2:3:4::/64 dst-pfx 5:6:7:8::/64
+    * DNPT src-pfx 5:6:7:8::/64 dst-pfx 1:2:3:4::/64
+    
+    No rules on the 9:a:b:c::/64 side.
+    
+    1. 1:2:3:4::1 sends UDP packet to 9:a:b:c::1
+    2. Router applies SNPT changing src to 5:6:7:8::ffef::1
+    3. 9:a:b:c::1 receives packet with (src 5:6:7:8::ffef::1 dst 9:a:b:c::1)
+            and replies with ICMPv6 port unreachable to 5:6:7:8::ffef::1,
+            including original packet (src 5:6:7:8::ffef::1 dst 9:a:b:c::1)
+    4. Router forwards ICMPv6 packet with (src 9:a:b:c::1 dst 5:6:7:8::ffef::1)
+            including original packet (src 5:6:7:8::ffef::1 dst 9:a:b:c::1)
+            and applies DNPT changing dst to 1:2:3:4::1
+    5. 1:2:3:4::1 receives ICMPv6 packet with (src 9:a:b:c::1 dst 1:2:3:4::1)
+            including original packet (src 5:6:7:8::ffef::1 dst 9:a:b:c::1).
+            It doesn't recognise the original packet as the src doesn't
+            match anything it originally sent
+    
+    With this change, at step 4, DNPT will also rewrite the original packet
+    src to 1:2:3:4::1, so at step 5, 1:2:3:4::1 will recognise the ICMPv6
+    error and provide feedback to the application properly.
+    
+    Conversely, SNPT will help when ICMPv6 errors are sent from the
+    translated network.
+    
+    1. 9:a:b:c::1 sends UDP packet to 5:6:7:8::ffef::1
+    2. Router applies DNPT changing dst to 1:2:3:4::1
+    3. 1:2:3:4::1 receives packet with (src 9:a:b:c::1 dst 1:2:3:4::1)
+            and replies with ICMPv6 port unreachable to 9:a:b:c::1
+            including original packet (src 9:a:b:c::1 dst 1:2:3:4::1)
+    4. Router forwards ICMPv6 packet with (src 1:2:3:4::1 dst 9:a:b:c::1)
+            including original packet (src 9:a:b:c::1 dst 1:2:3:4::1)
+            and applies SNPT changing src to 5:6:7:8::ffef::1
+    5. 9:a:b:c::1 receives ICMPv6 packet with
+            (src 5:6:7:8::ffef::1 dst 9:a:b:c::1) including
+            original packet (src 9:a:b:c::1 dst 1:2:3:4::1).
+            It doesn't recognise the original packet as the dst doesn't
+            match anything it already sent
+    
+    The change to SNPT means the ICMPv6 original packet dst will be
+    rewritten to 5:6:7:8::ffef::1 in step 4, allowing the error to be
+    properly recognised in step 5.
+    
+    Signed-off-by: Michael Zhou 
+    Signed-off-by: Pablo Neira Ayuso 
+
+diff --git a/net/ipv6/netfilter/ip6t_NPT.c b/net/ipv6/netfilter/ip6t_NPT.c
+index 9ee077bf4f49..787c74aa85e3 100644
+--- a/net/ipv6/netfilter/ip6t_NPT.c
++++ b/net/ipv6/netfilter/ip6t_NPT.c
+@@ -77,16 +77,43 @@ static bool ip6t_npt_map_pfx(const struct ip6t_npt_tginfo *npt,
+ 	return true;
+ }
+ 
++static struct ipv6hdr *icmpv6_bounced_ipv6hdr(struct sk_buff *skb,
++					      struct ipv6hdr *_bounced_hdr)
++{
++	if (ipv6_hdr(skb)->nexthdr != IPPROTO_ICMPV6)
++		return NULL;
++
++	if (!icmpv6_is_err(icmp6_hdr(skb)->icmp6_type))
++		return NULL;
++
++	return skb_header_pointer(skb,
++				  skb_transport_offset(skb) + sizeof(struct icmp6hdr),
++				  sizeof(struct ipv6hdr),
++				  _bounced_hdr);
++}
++
+ static unsigned int
+ ip6t_snpt_tg(struct sk_buff *skb, const struct xt_action_param *par)
+ {
+ 	const struct ip6t_npt_tginfo *npt = par->targinfo;
++	struct ipv6hdr _bounced_hdr;
++	struct ipv6hdr *bounced_hdr;
++	struct in6_addr bounced_pfx;
+ 
+ 	if (!ip6t_npt_map_pfx(npt, &ipv6_hdr(skb)->saddr)) {
+ 		icmpv6_send(skb, ICMPV6_PARAMPROB, ICMPV6_HDR_FIELD,
+ 			    offsetof(struct ipv6hdr, saddr));
+ 		return NF_DROP;
+ 	}
++
++	/* rewrite dst addr of bounced packet which was sent to dst range */
++	bounced_hdr = icmpv6_bounced_ipv6hdr(skb, &_bounced_hdr);
++	if (bounced_hdr) {
++		ipv6_addr_prefix(&bounced_pfx, &bounced_hdr->daddr, npt->src_pfx_len);
++		if (ipv6_addr_cmp(&bounced_pfx, &npt->src_pfx.in6) == 0)
++			ip6t_npt_map_pfx(npt, &bounced_hdr->daddr);
++	}
++
+ 	return XT_CONTINUE;
+ }
+ 
+@@ -94,12 +121,24 @@ static unsigned int
+ ip6t_dnpt_tg(struct sk_buff *skb, const struct xt_action_param *par)
+ {
+ 	const struct ip6t_npt_tginfo *npt = par->targinfo;
++	struct ipv6hdr _bounced_hdr;
++	struct ipv6hdr *bounced_hdr;
++	struct in6_addr bounced_pfx;
+ 
+ 	if (!ip6t_npt_map_pfx(npt, &ipv6_hdr(skb)->daddr)) {
+ 		icmpv6_send(skb, ICMPV6_PARAMPROB, ICMPV6_HDR_FIELD,
+ 			    offsetof(struct ipv6hdr, daddr));
+ 		return NF_DROP;
+ 	}
++
++	/* rewrite src addr of bounced packet which was sent from dst range */
++	bounced_hdr = icmpv6_bounced_ipv6hdr(skb, &_bounced_hdr);
++	if (bounced_hdr) {
++		ipv6_addr_prefix(&bounced_pfx, &bounced_hdr->saddr, npt->src_pfx_len);
++		if (ipv6_addr_cmp(&bounced_pfx, &npt->src_pfx.in6) == 0)
++			ip6t_npt_map_pfx(npt, &bounced_hdr->saddr);
++	}
++
+ 	return XT_CONTINUE;
+ }
+ 

commit 1f1e030bf75774b6a283518e1534d598e14147d4
+Author: NeilBrown 
+Date:   Fri Jan 6 00:09:49 2006 -0800
+
+    [PATCH] knfsd: fix hash function for IP addresses on 64bit little-endian machines.
+    
+    The hash.h hash_long function, when used on a 64 bit machine, ignores many
+    of the middle-order bits.  (The prime chosen it too bit-sparse).
+    
+    IP addresses for clients of an NFS server are very likely to differ only in
+    the low-order bits.  As addresses are stored in network-byte-order, these
+    bits become middle-order bits in a little-endian 64bit 'long', and so do
+    not contribute to the hash.  Thus you can have the situation where all
+    clients appear on one hash chain.
+    
+    So, until hash_long is fixed (or maybe forever), us a hash function that
+    works well on IP addresses - xor the bytes together.
+    
+    Thanks to "Iozone"  for identifying this problem.
+    
+    Cc: "Iozone" 
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
+index cac2e774dd81..3e6c694bbad1 100644
+--- a/net/sunrpc/svcauth_unix.c
++++ b/net/sunrpc/svcauth_unix.c
+@@ -101,10 +101,22 @@ static void ip_map_put(struct cache_head *item, struct cache_detail *cd)
+ 	}
+ }
+ 
++#if IP_HASHBITS == 8
++/* hash_long on a 64 bit machine is currently REALLY BAD for
++ * IP addresses in reverse-endian (i.e. on a little-endian machine).
++ * So use a trivial but reliable hash instead
++ */
++static inline int hash_ip(unsigned long ip)
++{
++	int hash = ip ^ (ip>>16);
++	return (hash ^ (hash>>8)) & 0xff;
++}
++#endif
++
+ static inline int ip_map_hash(struct ip_map *item)
+ {
+ 	return hash_str(item->m_class, IP_HASHBITS) ^ 
+-		hash_long((unsigned long)item->m_addr.s_addr, IP_HASHBITS);
++		hash_ip((unsigned long)item->m_addr.s_addr);
+ }
+ static inline int ip_map_match(struct ip_map *item, struct ip_map *tmp)
+ {

commit 1887b93529410633b5529a7c2d304897dbed5b3e
+Author: NeilBrown 
+Date:   Tue Nov 15 00:09:10 2005 -0800
+
+    [PATCH] knfsd: make sure nfsd doesn't hog a cpu forever
+    
+    Being kernel-threads, nfsd servers don't get pre-empted (depending on
+    CONFIG).  If there is a steady stream of NFS requests that can be served
+    from cache, an nfsd thread may hold on to a cpu indefinitely, which isn't
+    very friendly.
+    
+    So it is good to have a cond_resched in there (just before looking for a
+    new request to serve), to make sure we play nice.
+    
+    Signed-off-by: Neil Brown 
+    Acked-by: Ingo Molnar 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
+index e50e7cf43737..c6a51911e71e 100644
+--- a/net/sunrpc/svcsock.c
++++ b/net/sunrpc/svcsock.c
+@@ -1178,6 +1178,7 @@ svc_recv(struct svc_serv *serv, struct svc_rqst *rqstp, long timeout)
+ 	arg->tail[0].iov_len = 0;
+ 
+ 	try_to_freeze();
++	cond_resched();
+ 	if (signalled())
+ 		return -EINTR;
+ 

commit 80d188a643b0f550a2aaedf7bf4dd1abd86cfc45
+Author: NeilBrown 
+Date:   Mon Nov 7 01:00:27 2005 -0800
+
+    [PATCH] knfsd: make sure svc_process call the correct pg_authenticate for multi-service port
+    
+    If an RPC socket is serving multiple programs, then the pg_authenticate of
+    the first program in the list is called, instead of pg_authenticate for the
+    program to be run.
+    
+    This does not cause a problem with any programs in the current kernel, but
+    could confuse future code.
+    
+    Also set pg_authenticate for nfsd_acl_program incase it ever gets used.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
+index 0568ff8565b1..89ed04696865 100644
+--- a/fs/nfsd/nfssvc.c
++++ b/fs/nfsd/nfssvc.c
+@@ -427,6 +427,7 @@ static struct svc_program	nfsd_acl_program = {
+ 	.pg_name		= "nfsd",
+ 	.pg_class		= "nfsd",
+ 	.pg_stats		= &nfsd_acl_svcstats,
++	.pg_authenticate	= &svc_set_client,
+ };
+ 
+ static struct svc_stat	nfsd_acl_svcstats = {
+diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
+index e9bd91265f70..5a220b2bb376 100644
+--- a/net/sunrpc/svc.c
++++ b/net/sunrpc/svc.c
+@@ -313,6 +313,11 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
+ 	rqstp->rq_proc = proc = ntohl(svc_getu32(argv));	/* procedure number */
+ 
+ 	progp = serv->sv_program;
++
++	for (progp = serv->sv_program; progp; progp = progp->pg_next)
++		if (prog == progp->pg_prog)
++			break;
++
+ 	/*
+ 	 * Decode auth data, and add verifier to reply buffer.
+ 	 * We do this before anything else in order to get a decent
+@@ -320,7 +325,7 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
+ 	 */
+ 	auth_res = svc_authenticate(rqstp, &auth_stat);
+ 	/* Also give the program a chance to reject this call: */
+-	if (auth_res == SVC_OK) {
++	if (auth_res == SVC_OK && progp) {
+ 		auth_stat = rpc_autherr_badcred;
+ 		auth_res = progp->pg_authenticate(rqstp);
+ 	}
+@@ -340,10 +345,7 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
+ 	case SVC_COMPLETE:
+ 		goto sendit;
+ 	}
+-		
+-	for (progp = serv->sv_program; progp; progp = progp->pg_next)
+-		if (prog == progp->pg_prog)
+-			break;
++
+ 	if (progp == NULL)
+ 		goto err_bad_prog;
+ 

commit 0ba7536d5d47e4ecf2259a80b207158dc4e711eb
+Author: NeilBrown 
+Date:   Mon Nov 7 01:00:26 2005 -0800
+
+    [PATCH] knfsd: Fix some minor sign problems in nfsd/xdr
+    
+    There are a couple of tests which could possibly be confused by extremely
+    large numbers appearing in 'xdr' packets.  I think the closest to an exploit
+    you could get would be writing random data from a free page into a file - i.e.
+     leak data out of kernel space.
+    
+    I'm fairly sure they cannot be used for remote compromise.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
+index e0e134d6baba..9147b8524d05 100644
+--- a/fs/nfsd/nfs3xdr.c
++++ b/fs/nfsd/nfs3xdr.c
+@@ -366,7 +366,8 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, u32 *p,
+ 	len = args->len = ntohl(*p++);
+ 
+ 	hdr = (void*)p - rqstp->rq_arg.head[0].iov_base;
+-	if (rqstp->rq_arg.len < len + hdr)
++	if (rqstp->rq_arg.len < hdr ||
++	    rqstp->rq_arg.len - hdr < len)
+ 		return 0;
+ 
+ 	args->vec[0].iov_base = (void*)p;
+diff --git a/include/linux/nfsd/xdr3.h b/include/linux/nfsd/xdr3.h
+index 21e18ce7ca63..3c2a71b43bac 100644
+--- a/include/linux/nfsd/xdr3.h
++++ b/include/linux/nfsd/xdr3.h
+@@ -42,7 +42,7 @@ struct nfsd3_writeargs {
+ 	__u64			offset;
+ 	__u32			count;
+ 	int			stable;
+-	int			len;
++	__u32			len;
+ 	struct kvec		vec[RPCSVC_MAXPAGES];
+ 	int			vlen;
+ };
+diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
+index 5af8800e0ce3..e4086ec8b952 100644
+--- a/include/linux/sunrpc/svc.h
++++ b/include/linux/sunrpc/svc.h
+@@ -171,7 +171,8 @@ xdr_argsize_check(struct svc_rqst *rqstp, u32 *p)
+ {
+ 	char *cp = (char *)p;
+ 	struct kvec *vec = &rqstp->rq_arg.head[0];
+-	return cp - (char*)vec->iov_base <= vec->iov_len;
++	return cp >= (char*)vec->iov_base
++		&& cp <= (char*)vec->iov_base + vec->iov_len;
+ }
+ 
+ static inline int

commit 70c3b76c28b012452d63bb27f6d0517afb05d86f
+Author: NeilBrown 
+Date:   Mon Nov 7 01:00:25 2005 -0800
+
+    [PATCH] knfsd: Allow run-time selection of NFS versions to export
+    
+    Provide a file in the NFSD filesystem that allows setting and querying of
+    which version of NFS are being exported.  Changes are only allowed while no
+    server is running.
+    
+    Signed-off-by: Steve Dickson 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index 2a99a0bf54f6..a0871b3efeb7 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -23,6 +23,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ #include 
+@@ -35,6 +36,8 @@
+ 
+ #include 
+ 
++unsigned int nfsd_versbits = ~0;
++
+ /*
+  *	We have a single directory with 9 nodes in it.
+  */
+@@ -50,8 +53,15 @@ enum {
+ 	NFSD_List,
+ 	NFSD_Fh,
+ 	NFSD_Threads,
++	NFSD_Versions,
++	/*
++	 * The below MUST come last.  Otherwise we leave a hole in nfsd_files[]
++	 * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops
++	 */
++#ifdef CONFIG_NFSD_V4
+ 	NFSD_Leasetime,
+ 	NFSD_RecoveryDir,
++#endif
+ };
+ 
+ /*
+@@ -66,8 +76,11 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size);
+ static ssize_t write_getfs(struct file *file, char *buf, size_t size);
+ static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
+ static ssize_t write_threads(struct file *file, char *buf, size_t size);
++static ssize_t write_versions(struct file *file, char *buf, size_t size);
++#ifdef CONFIG_NFSD_V4
+ static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
+ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
++#endif
+ 
+ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
+ 	[NFSD_Svc] = write_svc,
+@@ -79,8 +92,11 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
+ 	[NFSD_Getfs] = write_getfs,
+ 	[NFSD_Fh] = write_filehandle,
+ 	[NFSD_Threads] = write_threads,
++	[NFSD_Versions] = write_versions,
++#ifdef CONFIG_NFSD_V4
+ 	[NFSD_Leasetime] = write_leasetime,
+ 	[NFSD_RecoveryDir] = write_recoverydir,
++#endif
+ };
+ 
+ static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
+@@ -343,6 +359,70 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
+ 	return strlen(buf);
+ }
+ 
++static ssize_t write_versions(struct file *file, char *buf, size_t size)
++{
++	/*
++	 * Format:
++	 *   [-/+]vers [-/+]vers ...
++	 */
++	char *mesg = buf;
++	char *vers, sign;
++	int len, num;
++	ssize_t tlen = 0;
++	char *sep;
++
++	if (size>0) {
++		if (nfsd_serv)
++			return -EBUSY;
++		if (buf[size-1] != '\n')
++			return -EINVAL;
++		buf[size-1] = 0;
++
++		vers = mesg;
++		len = qword_get(&mesg, vers, size);
++		if (len <= 0) return -EINVAL;
++		do {
++			sign = *vers;
++			if (sign == '+' || sign == '-')
++				num = simple_strtol((vers+1), NULL, 0);
++			else
++				num = simple_strtol(vers, NULL, 0);
++			switch(num) {
++			case 2:
++			case 3:
++			case 4:
++				if (sign != '-')
++					NFSCTL_VERSET(nfsd_versbits, num);
++				else
++					NFSCTL_VERUNSET(nfsd_versbits, num);
++				break;
++			default:
++				return -EINVAL;
++			}
++			vers += len + 1;
++			tlen += len;
++		} while ((len = qword_get(&mesg, vers, size)) > 0);
++		/* If all get turned off, turn them back on, as
++		 * having no versions is BAD
++		 */
++		if ((nfsd_versbits & NFSCTL_VERALL)==0)
++			nfsd_versbits = NFSCTL_VERALL;
++	}
++	/* Now write current state into reply buffer */
++	len = 0;
++	sep = "";
++	for (num=2 ; num <= 4 ; num++)
++		if (NFSCTL_VERISSET(NFSCTL_VERALL, num)) {
++			len += sprintf(buf+len, "%s%c%d", sep,
++				       NFSCTL_VERISSET(nfsd_versbits, num)?'+':'-',
++				       num);
++			sep = " ";
++		}
++	len += sprintf(buf+len, "\n");
++	return len;
++}
++
++#ifdef CONFIG_NFSD_V4
+ extern time_t nfs4_leasetime(void);
+ 
+ static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
+@@ -384,6 +464,7 @@ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
+ 	status = nfs4_reset_recoverydir(recdir);
+ 	return strlen(buf);
+ }
++#endif
+ 
+ /*----------------------------------------------------------------------------*/
+ /*
+@@ -403,6 +484,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
+ 		[NFSD_List] = {"exports", &exports_operations, S_IRUGO},
+ 		[NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR},
+ 		[NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
++		[NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR},
+ #ifdef CONFIG_NFSD_V4
+ 		[NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
+ 		[NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR},
+diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
+index 1697539a7171..0568ff8565b1 100644
+--- a/fs/nfsd/nfssvc.c
++++ b/fs/nfsd/nfssvc.c
+@@ -30,6 +30,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ 
+@@ -52,7 +53,7 @@
+ extern struct svc_program	nfsd_program;
+ static void			nfsd(struct svc_rqst *rqstp);
+ struct timeval			nfssvc_boot;
+-static struct svc_serv 		*nfsd_serv;
++       struct svc_serv 		*nfsd_serv;
+ static atomic_t			nfsd_busy;
+ static unsigned long		nfsd_last_call;
+ static DEFINE_SPINLOCK(nfsd_call_lock);
+@@ -63,6 +64,31 @@ struct nfsd_list {
+ };
+ static struct list_head nfsd_list = LIST_HEAD_INIT(nfsd_list);
+ 
++static struct svc_version *	nfsd_version[] = {
++	[2] = &nfsd_version2,
++#if defined(CONFIG_NFSD_V3)
++	[3] = &nfsd_version3,
++#endif
++#if defined(CONFIG_NFSD_V4)
++	[4] = &nfsd_version4,
++#endif
++};
++
++#define NFSD_MINVERS    	2
++#define NFSD_NRVERS		(sizeof(nfsd_version)/sizeof(nfsd_version[0]))
++static struct svc_version *nfsd_versions[NFSD_NRVERS];
++
++struct svc_program		nfsd_program = {
++	.pg_prog		= NFS_PROGRAM,		/* program number */
++	.pg_nvers		= NFSD_NRVERS,		/* nr of entries in nfsd_version */
++	.pg_vers		= nfsd_versions,	/* version table */
++	.pg_name		= "nfsd",		/* program name */
++	.pg_class		= "nfsd",		/* authentication class */
++	.pg_stats		= &nfsd_svcstats,	/* version table */
++	.pg_authenticate	= &svc_set_client,	/* export authentication */
++
++};
++
+ /*
+  * Maximum number of nfsd processes
+  */
+@@ -80,11 +106,12 @@ int
+ nfsd_svc(unsigned short port, int nrservs)
+ {
+ 	int	error;
+-	int	none_left;	
++	int	none_left, found_one, i;
+ 	struct list_head *victim;
+ 	
+ 	lock_kernel();
+-	dprintk("nfsd: creating service\n");
++	dprintk("nfsd: creating service: vers 0x%x\n",
++		nfsd_versbits);
+ 	error = -EINVAL;
+ 	if (nrservs <= 0)
+ 		nrservs = 0;
+@@ -99,6 +126,27 @@ nfsd_svc(unsigned short port, int nrservs)
+ 	if (error<0)
+ 		goto out;
+ 	if (!nfsd_serv) {
++		/*
++		 * Use the nfsd_ctlbits to define which
++		 * versions that will be advertised.
++		 * If nfsd_ctlbits doesn't list any version,
++		 * export them all.
++		 */
++		found_one = 0;
++
++		for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) {
++			if (NFSCTL_VERISSET(nfsd_versbits, i)) {
++				nfsd_program.pg_vers[i] = nfsd_version[i];
++				found_one = 1;
++			} else
++				nfsd_program.pg_vers[i] = NULL;
++		}
++
++		if (!found_one) {
++			for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++)
++				nfsd_program.pg_vers[i] = nfsd_version[i];
++		}
++
+ 		atomic_set(&nfsd_busy, 0);
+ 		error = -ENOMEM;
+ 		nfsd_serv = svc_create(&nfsd_program, NFSD_BUFSIZE);
+@@ -389,28 +437,3 @@ static struct svc_stat	nfsd_acl_svcstats = {
+ #else
+ #define nfsd_acl_program_p	NULL
+ #endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
+-
+-extern struct svc_version nfsd_version2, nfsd_version3, nfsd_version4;
+-
+-static struct svc_version *	nfsd_version[] = {
+-	[2] = &nfsd_version2,
+-#if defined(CONFIG_NFSD_V3)
+-	[3] = &nfsd_version3,
+-#endif
+-#if defined(CONFIG_NFSD_V4)
+-	[4] = &nfsd_version4,
+-#endif
+-};
+-
+-#define NFSD_NRVERS		(sizeof(nfsd_version)/sizeof(nfsd_version[0]))
+-struct svc_program		nfsd_program = {
+-	.pg_next		= nfsd_acl_program_p,
+-	.pg_prog		= NFS_PROGRAM,		/* program number */
+-	.pg_nvers		= NFSD_NRVERS,		/* nr of entries in nfsd_version */
+-	.pg_vers		= nfsd_version,		/* version table */
+-	.pg_name		= "nfsd",		/* program name */
+-	.pg_class		= "nfsd",		/* authentication class */
+-	.pg_stats		= &nfsd_svcstats,	/* version table */
+-	.pg_authenticate	= &svc_set_client,	/* export authentication */
+-
+-};
+diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
+index 6d5a24f3fc6d..51c231a1e5a6 100644
+--- a/include/linux/nfsd/nfsd.h
++++ b/include/linux/nfsd/nfsd.h
+@@ -60,7 +60,7 @@ typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int);
+ extern struct svc_program	nfsd_program;
+ extern struct svc_version	nfsd_version2, nfsd_version3,
+ 				nfsd_version4;
+-
++extern struct svc_serv		*nfsd_serv;
+ /*
+  * Function prototypes.
+  */
+diff --git a/include/linux/nfsd/syscall.h b/include/linux/nfsd/syscall.h
+index e65c9db6d13f..781efbf94ed3 100644
+--- a/include/linux/nfsd/syscall.h
++++ b/include/linux/nfsd/syscall.h
+@@ -39,6 +39,21 @@
+ #define NFSCTL_GETFD		7	/* get an fh by path (used by mountd) */
+ #define	NFSCTL_GETFS		8	/* get an fh by path with max FH len */
+ 
++/*
++ * Macros used to set version
++ */
++#define NFSCTL_VERSET(_cltbits, _v)   ((_cltbits) |=  (1 << (_v)))
++#define NFSCTL_VERUNSET(_cltbits, _v) ((_cltbits) &= ~(1 << (_v)))
++#define NFSCTL_VERISSET(_cltbits, _v) ((_cltbits) & (1 << (_v)))
++
++#if defined(CONFIG_NFSD_V4)
++#define	NFSCTL_VERALL	(0x1c /* 0b011100 */)
++#elif defined(CONFIG_NFSD_V3)
++#define	NFSCTL_VERALL	(0x0c /* 0b001100 */)
++#else
++#define	NFSCTL_VERALL	(0x04 /* 0b000100 */)
++#endif
++
+ /* SVC */
+ struct nfsctl_svc {
+ 	unsigned short		svc_port;
+@@ -120,6 +135,8 @@ extern int		exp_delclient(struct nfsctl_client *ncp);
+ extern int		exp_export(struct nfsctl_export *nxp);
+ extern int		exp_unexport(struct nfsctl_export *nxp);
+ 
++extern unsigned int nfsd_versbits;
++
+ #endif /* __KERNEL__ */
+ 
+ #endif /* NFSD_SYSCALL_H */

commit 7390022d697bcc62a7556d6fdc61ec56ce3a381a
+Author: NeilBrown 
+Date:   Mon Nov 7 01:00:24 2005 -0800
+
+    [PATCH] knfsd: Restore functionality to read from file in /proc/fs/nfsd/
+    
+    Most files in the nfsd filesystems are transaction files.  You write a
+    request, and read a response.
+    
+    For some (e.g.  'threads') it makes sense to just be able to read and get the
+    current value.
+    
+    This functionality did exist but was broken recently when someone modified
+    nfsctl.c without going through the maintainer.  This patch fixes the
+    regression.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index 841c562991e8..2a99a0bf54f6 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -104,9 +104,23 @@ static ssize_t nfsctl_transaction_write(struct file *file, const char __user *bu
+ 	return rv;
+ }
+ 
++static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
++{
++	if (! file->private_data) {
++		/* An attempt to read a transaction file without writing
++		 * causes a 0-byte write so that the file can return
++		 * state information
++		 */
++		ssize_t rv = nfsctl_transaction_write(file, buf, 0, pos);
++		if (rv < 0)
++			return rv;
++	}
++	return simple_transaction_read(file, buf, size, pos);
++}
++
+ static struct file_operations transaction_ops = {
+ 	.write		= nfsctl_transaction_write,
+-	.read		= simple_transaction_read,
++	.read		= nfsctl_transaction_read,
+ 	.release	= simple_transaction_release,
+ };
+ 

commit 15b7a1b86d663ef40108b1ba322973e32d5b62d6
+Author: NeilBrown 
+Date:   Mon Nov 7 01:00:23 2005 -0800
+
+    [PATCH] knfsd: fix setattr-on-symlink error return
+    
+    This is a somewhat cosmetic fix to keep the SpecFS validation test from
+    complaining.
+    
+    SpecFS want's to try chmod on symlinks, and ext3 and reiser (at least) return
+    ENOTSUPP.
+    
+    Probably both sides are being silly, but it is easiest to simply make it a
+    non-issue and filter out chmod requests on symlinks at the nfsd level.
+    
+    Signed-off-by: Olaf Kirch 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index 4f2cd3d27566..af7c3c3074b0 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -254,12 +254,19 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
+ 
+ 	/* Get inode */
+ 	err = fh_verify(rqstp, fhp, ftype, accmode);
+-	if (err || !iap->ia_valid)
++	if (err)
+ 		goto out;
+ 
+ 	dentry = fhp->fh_dentry;
+ 	inode = dentry->d_inode;
+ 
++	/* Ignore any mode updates on symlinks */
++	if (S_ISLNK(inode->i_mode))
++		iap->ia_valid &= ~ATTR_MODE;
++
++	if (!iap->ia_valid)
++		goto out;
++
+ 	/* NFSv2 does not differentiate between "set-[ac]time-to-now"
+ 	 * which only requires access, and "set-[ac]time-to-X" which
+ 	 * requires ownership.

commit 500af87abb81098da47474c81f29ea315a056dc5
+Author: NeilBrown 
+Date:   Fri Sep 9 16:23:58 2005 -0700
+
+    [PATCH] md: tidy up daemon stop/start code in md/bitmap.c
+    
+    The bitmap code used to have two daemons, so there is some 'common' start/stop
+    code.  But now there is only one, so the common code is just noise.
+    
+    This patch tidies this up somewhat.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Adrian Bunk 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
+index 87145faac491..2fba2bbe72d8 100644
+--- a/drivers/md/bitmap.c
++++ b/drivers/md/bitmap.c
+@@ -626,7 +626,7 @@ static void bitmap_file_unmap(struct bitmap *bitmap)
+ 		page_cache_release(sb_page);
+ }
+ 
+-static void bitmap_stop_daemons(struct bitmap *bitmap);
++static void bitmap_stop_daemon(struct bitmap *bitmap);
+ 
+ /* dequeue the next item in a page list -- don't call from irq context */
+ static struct page_list *dequeue_page(struct bitmap *bitmap)
+@@ -668,7 +668,7 @@ static void bitmap_file_put(struct bitmap *bitmap)
+ 	bitmap->file = NULL;
+ 	spin_unlock_irqrestore(&bitmap->lock, flags);
+ 
+-	bitmap_stop_daemons(bitmap);
++	bitmap_stop_daemon(bitmap);
+ 
+ 	drain_write_queues(bitmap);
+ 
+@@ -1188,21 +1188,12 @@ static void bitmap_writeback_daemon(mddev_t *mddev)
+ 	}
+ }
+ 
+-static int bitmap_start_daemon(struct bitmap *bitmap, mdk_thread_t **ptr,
++static mdk_thread_t *bitmap_start_daemon(struct bitmap *bitmap,
+ 				void (*func)(mddev_t *), char *name)
+ {
+ 	mdk_thread_t *daemon;
+-	unsigned long flags;
+ 	char namebuf[32];
+ 
+-	spin_lock_irqsave(&bitmap->lock, flags);
+-	*ptr = NULL;
+-
+-	if (!bitmap->file) /* no need for daemon if there's no backing file */
+-		goto out_unlock;
+-
+-	spin_unlock_irqrestore(&bitmap->lock, flags);
+-
+ #ifdef INJECT_FATAL_FAULT_2
+ 	daemon = NULL;
+ #else
+@@ -1212,47 +1203,32 @@ static int bitmap_start_daemon(struct bitmap *bitmap, mdk_thread_t **ptr,
+ 	if (!daemon) {
+ 		printk(KERN_ERR "%s: failed to start bitmap daemon\n",
+ 			bmname(bitmap));
+-		return -ECHILD;
++		return ERR_PTR(-ECHILD);
+ 	}
+ 
+-	spin_lock_irqsave(&bitmap->lock, flags);
+-	*ptr = daemon;
+-
+ 	md_wakeup_thread(daemon); /* start it running */
+ 
+ 	PRINTK("%s: %s daemon (pid %d) started...\n",
+ 		bmname(bitmap), name, daemon->tsk->pid);
+-out_unlock:
+-	spin_unlock_irqrestore(&bitmap->lock, flags);
+-	return 0;
+-}
+ 
+-static int bitmap_start_daemons(struct bitmap *bitmap)
+-{
+-	int err = bitmap_start_daemon(bitmap, &bitmap->writeback_daemon,
+-					bitmap_writeback_daemon, "bitmap_wb");
+-	return err;
++	return daemon;
+ }
+ 
+-static void bitmap_stop_daemon(struct bitmap *bitmap, mdk_thread_t **ptr)
++static void bitmap_stop_daemon(struct bitmap *bitmap)
+ {
+-	mdk_thread_t *daemon;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&bitmap->lock, flags);
+-	daemon = *ptr;
+-	*ptr = NULL;
+-	spin_unlock_irqrestore(&bitmap->lock, flags);
+-	if (daemon)
+-		md_unregister_thread(daemon); /* destroy the thread */
+-}
++	/* the daemon can't stop itself... it'll just exit instead... */
++	if (bitmap->writeback_daemon && ! IS_ERR(bitmap->writeback_daemon) &&
++	    current->pid != bitmap->writeback_daemon->tsk->pid) {
++		mdk_thread_t *daemon;
++		unsigned long flags;
+ 
+-static void bitmap_stop_daemons(struct bitmap *bitmap)
+-{
+-	/* the daemons can't stop themselves... they'll just exit instead... */
+-	if (bitmap->writeback_daemon &&
+-	    current->pid != bitmap->writeback_daemon->tsk->pid)
+-		bitmap_stop_daemon(bitmap, &bitmap->writeback_daemon);
++		spin_lock_irqsave(&bitmap->lock, flags);
++		daemon = bitmap->writeback_daemon;
++		bitmap->writeback_daemon = NULL;
++		spin_unlock_irqrestore(&bitmap->lock, flags);
++		if (daemon && ! IS_ERR(daemon))
++			md_unregister_thread(daemon); /* destroy the thread */
++	}
+ }
+ 
+ static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
+@@ -1637,10 +1613,15 @@ int bitmap_create(mddev_t *mddev)
+ 
+ 	mddev->bitmap = bitmap;
+ 
+-	/* kick off the bitmap daemons */
+-	err = bitmap_start_daemons(bitmap);
+-	if (err)
+-		return err;
++	if (file)
++		/* kick off the bitmap writeback daemon */
++		bitmap->writeback_daemon =
++			bitmap_start_daemon(bitmap,
++					    bitmap_writeback_daemon,
++					    "bitmap_wb");
++
++	if (IS_ERR(bitmap->writeback_daemon))
++		return PTR_ERR(bitmap->writeback_daemon);
+ 	return bitmap_update_sb(bitmap);
+ 
+  error:
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index bfe78571586b..a93ca478142a 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -1703,7 +1703,7 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
+ 	return 0;
+ }
+ 
+-void raid1_quiesce(mddev_t *mddev, int state)
++static void raid1_quiesce(mddev_t *mddev, int state)
+ {
+ 	conf_t *conf = mddev_to_conf(mddev);
+ 

commit 9ba00538ada7ecb4fb8bd71ba734a8eada987817
+Author: NeilBrown 
+Date:   Fri Sep 9 16:23:57 2005 -0700
+
+    [PATCH] md: ensure bitmap_writeback_daemon handles shutdown properly.
+    
+    mddev->bitmap gets clearred before the writeback daemon is stopped.  So the
+    write_back daemon needs to be careful not to dereference the 'bitmap' if it is
+    NULL.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
+index 90fe70d76a31..87145faac491 100644
+--- a/drivers/md/bitmap.c
++++ b/drivers/md/bitmap.c
+@@ -1156,6 +1156,9 @@ static void bitmap_writeback_daemon(mddev_t *mddev)
+ 		err = -EINTR;
+ 		goto out;
+ 	}
++	if (bitmap == NULL)
++		/* about to be stopped. */
++		return;
+ 
+ 	PRINTK("%s: bitmap writeback daemon woke up...\n", bmname(bitmap));
+ 	/* wait on bitmap page writebacks */

commit a6fb0934f923f889055152cb0b033674f627460b
+Author: NeilBrown 
+Date:   Fri Sep 9 16:23:56 2005 -0700
+
+    [PATCH] md: use kthread infrastructure in md
+    
+    Switch MD to use the kthread infrastructure, to simplify the code and get rid
+    of tasklist_lock abuse in md_unregister_thread.
+    
+    Also don't flush signals in md_thread, as the called thread will always do
+    that.
+    
+    Signed-off-by: Christoph Hellwig 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 008149e2bc4a..30e3624f3d90 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -34,6 +34,7 @@
+ 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -3049,18 +3050,6 @@ static int md_thread(void * arg)
+ {
+ 	mdk_thread_t *thread = arg;
+ 
+-	lock_kernel();
+-
+-	/*
+-	 * Detach thread
+-	 */
+-
+-	daemonize(thread->name, mdname(thread->mddev));
+-
+-	current->exit_signal = SIGCHLD;
+-	allow_signal(SIGKILL);
+-	thread->tsk = current;
+-
+ 	/*
+ 	 * md_thread is a 'system-thread', it's priority should be very
+ 	 * high. We avoid resource deadlocks individually in each
+@@ -3072,14 +3061,14 @@ static int md_thread(void * arg)
+ 	 * bdflush, otherwise bdflush will deadlock if there are too
+ 	 * many dirty RAID5 blocks.
+ 	 */
+-	unlock_kernel();
+ 
+ 	complete(thread->event);
+-	while (thread->run) {
++	while (!kthread_should_stop()) {
+ 		void (*run)(mddev_t *);
+ 
+ 		wait_event_interruptible_timeout(thread->wqueue,
+-						 test_bit(THREAD_WAKEUP, &thread->flags),
++						 test_bit(THREAD_WAKEUP, &thread->flags)
++						 || kthread_should_stop(),
+ 						 thread->timeout);
+ 		try_to_freeze();
+ 
+@@ -3088,11 +3077,8 @@ static int md_thread(void * arg)
+ 		run = thread->run;
+ 		if (run)
+ 			run(thread->mddev);
+-
+-		if (signal_pending(current))
+-			flush_signals(current);
+ 	}
+-	complete(thread->event);
++
+ 	return 0;
+ }
+ 
+@@ -3109,11 +3095,9 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
+ 				 const char *name)
+ {
+ 	mdk_thread_t *thread;
+-	int ret;
+ 	struct completion event;
+ 
+-	thread = (mdk_thread_t *) kmalloc
+-				(sizeof(mdk_thread_t), GFP_KERNEL);
++	thread = kmalloc(sizeof(mdk_thread_t), GFP_KERNEL);
+ 	if (!thread)
+ 		return NULL;
+ 
+@@ -3126,8 +3110,8 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
+ 	thread->mddev = mddev;
+ 	thread->name = name;
+ 	thread->timeout = MAX_SCHEDULE_TIMEOUT;
+-	ret = kernel_thread(md_thread, thread, 0);
+-	if (ret < 0) {
++	thread->tsk = kthread_run(md_thread, thread, mdname(thread->mddev));
++	if (IS_ERR(thread->tsk)) {
+ 		kfree(thread);
+ 		return NULL;
+ 	}
+@@ -3137,21 +3121,9 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
+ 
+ void md_unregister_thread(mdk_thread_t *thread)
+ {
+-	struct completion event;
+-
+-	init_completion(&event);
+-
+-	thread->event = &event;
+-
+-	/* As soon as ->run is set to NULL, the task could disappear,
+-	 * so we need to hold tasklist_lock until we have sent the signal
+-	 */
+ 	dprintk("interrupting MD-thread pid %d\n", thread->tsk->pid);
+-	read_lock(&tasklist_lock);
+-	thread->run = NULL;
+-	send_sig(SIGKILL, thread->tsk, 1);
+-	read_unlock(&tasklist_lock);
+-	wait_for_completion(&event);
++
++	kthread_stop(thread->tsk);
+ 	kfree(thread);
+ }
+ 

commit 934ce7c840992a771ffc478b132092db9c935c42
+Author: NeilBrown 
+Date:   Fri Sep 9 16:23:55 2005 -0700
+
+    [PATCH] md: write-intent bitmap support for raid6
+    
+    This is a direct port of the raid5 patch.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index dbf540a7fccc..008149e2bc4a 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -645,7 +645,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+ 
+ 		if (sb->state & (1<bitmap_file == NULL) {
+-			if (mddev->level != 1 && mddev->level != 5) {
++			if (mddev->level != 1 && mddev->level != 5 && mddev->level != 6) {
+ 				/* FIXME use a better test */
+ 				printk(KERN_WARNING "md: bitmaps only support for raid1\n");
+ 				return -EINVAL;
+diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
+index 09cb7272c09f..267eb1430c83 100644
+--- a/drivers/md/raid6main.c
++++ b/drivers/md/raid6main.c
+@@ -29,6 +29,8 @@
+ #include 
+ #include "raid6.h"
+ 
++#include 
++
+ /*
+  * Stripe cache
+  */
+@@ -98,8 +100,13 @@ static inline void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh)
+ 		if (test_bit(STRIPE_HANDLE, &sh->state)) {
+ 			if (test_bit(STRIPE_DELAYED, &sh->state))
+ 				list_add_tail(&sh->lru, &conf->delayed_list);
+-			else
++			else if (test_bit(STRIPE_BIT_DELAY, &sh->state) &&
++				 conf->seq_write == sh->bm_seq)
++				list_add_tail(&sh->lru, &conf->bitmap_list);
++			else {
++				clear_bit(STRIPE_BIT_DELAY, &sh->state);
+ 				list_add_tail(&sh->lru, &conf->handle_list);
++			}
+ 			md_wakeup_thread(conf->mddev->thread);
+ 		} else {
+ 			if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
+@@ -262,6 +269,9 @@ static struct stripe_head *get_active_stripe(raid6_conf_t *conf, sector_t sector
+ 	spin_lock_irq(&conf->device_lock);
+ 
+ 	do {
++		wait_event_lock_irq(conf->wait_for_stripe,
++				    conf->quiesce == 0,
++				    conf->device_lock, /* nothing */);
+ 		sh = __find_stripe(conf, sector);
+ 		if (!sh) {
+ 			if (!conf->inactive_blocked)
+@@ -906,6 +916,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
+ {
+ 	struct bio **bip;
+ 	raid6_conf_t *conf = sh->raid_conf;
++	int firstwrite=0;
+ 
+ 	PRINTK("adding bh b#%llu to stripe s#%llu\n",
+ 		(unsigned long long)bi->bi_sector,
+@@ -914,9 +925,11 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
+ 
+ 	spin_lock(&sh->lock);
+ 	spin_lock_irq(&conf->device_lock);
+-	if (forwrite)
++	if (forwrite) {
+ 		bip = &sh->dev[dd_idx].towrite;
+-	else
++		if (*bip == NULL && sh->dev[dd_idx].written == NULL)
++			firstwrite = 1;
++	} else
+ 		bip = &sh->dev[dd_idx].toread;
+ 	while (*bip && (*bip)->bi_sector < bi->bi_sector) {
+ 		if ((*bip)->bi_sector + ((*bip)->bi_size >> 9) > bi->bi_sector)
+@@ -939,6 +952,13 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
+ 		(unsigned long long)bi->bi_sector,
+ 		(unsigned long long)sh->sector, dd_idx);
+ 
++	if (conf->mddev->bitmap && firstwrite) {
++		sh->bm_seq = conf->seq_write;
++		bitmap_startwrite(conf->mddev->bitmap, sh->sector,
++				  STRIPE_SECTORS, 0);
++		set_bit(STRIPE_BIT_DELAY, &sh->state);
++	}
++
+ 	if (forwrite) {
+ 		/* check if page is covered */
+ 		sector_t sector = sh->dev[dd_idx].sector;
+@@ -1066,12 +1086,13 @@ static void handle_stripe(struct stripe_head *sh)
+ 	 * need to be failed
+ 	 */
+ 	if (failed > 2 && to_read+to_write+written) {
+-		spin_lock_irq(&conf->device_lock);
+ 		for (i=disks; i--; ) {
++			int bitmap_end = 0;
++			spin_lock_irq(&conf->device_lock);
+ 			/* fail all writes first */
+ 			bi = sh->dev[i].towrite;
+ 			sh->dev[i].towrite = NULL;
+-			if (bi) to_write--;
++			if (bi) { to_write--; bitmap_end = 1; }
+ 
+ 			if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
+ 				wake_up(&conf->wait_for_overlap);
+@@ -1089,6 +1110,7 @@ static void handle_stripe(struct stripe_head *sh)
+ 			/* and fail all 'written' */
+ 			bi = sh->dev[i].written;
+ 			sh->dev[i].written = NULL;
++			if (bi) bitmap_end = 1;
+ 			while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) {
+ 				struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
+ 				clear_bit(BIO_UPTODATE, &bi->bi_flags);
+@@ -1117,8 +1139,11 @@ static void handle_stripe(struct stripe_head *sh)
+ 					bi = nextbi;
+ 				}
+ 			}
++			spin_unlock_irq(&conf->device_lock);
++			if (bitmap_end)
++				bitmap_endwrite(conf->mddev->bitmap, sh->sector,
++						STRIPE_SECTORS, 0, 0);
+ 		}
+-		spin_unlock_irq(&conf->device_lock);
+ 	}
+ 	if (failed > 2 && syncing) {
+ 		md_done_sync(conf->mddev, STRIPE_SECTORS,0);
+@@ -1155,6 +1180,7 @@ static void handle_stripe(struct stripe_head *sh)
+ 				if (!test_bit(R5_LOCKED, &dev->flags) &&
+ 				    test_bit(R5_UPTODATE, &dev->flags) ) {
+ 					/* We can return any write requests */
++					int bitmap_end = 0;
+ 					struct bio *wbi, *wbi2;
+ 					PRINTK("Return write for stripe %llu disc %d\n",
+ 					       (unsigned long long)sh->sector, i);
+@@ -1170,7 +1196,13 @@ static void handle_stripe(struct stripe_head *sh)
+ 						}
+ 						wbi = wbi2;
+ 					}
++					if (dev->towrite == NULL)
++						bitmap_end = 1;
+ 					spin_unlock_irq(&conf->device_lock);
++					if (bitmap_end)
++						bitmap_endwrite(conf->mddev->bitmap, sh->sector,
++								STRIPE_SECTORS,
++								!test_bit(STRIPE_DEGRADED, &sh->state), 0);
+ 				}
+ 			}
+ 	}
+@@ -1285,7 +1317,8 @@ static void handle_stripe(struct stripe_head *sh)
+ 				}
+ 			}
+ 		/* now if nothing is locked, and if we have enough data, we can start a write request */
+-		if (locked == 0 && rcw == 0) {
++		if (locked == 0 && rcw == 0 &&
++		    !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
+ 			if ( must_compute > 0 ) {
+ 				/* We have failed blocks and need to compute them */
+ 				switch ( failed ) {
+@@ -1388,6 +1421,7 @@ static void handle_stripe(struct stripe_head *sh)
+ 			bdev = &sh->dev[failed_num[1]];
+ 			locked += !test_bit(R5_LOCKED, &bdev->flags);
+ 			set_bit(R5_LOCKED, &bdev->flags);
++			clear_bit(STRIPE_DEGRADED, &sh->state);
+ 			set_bit(R5_Wantwrite, &bdev->flags);
+ 
+ 			set_bit(STRIPE_INSYNC, &sh->state);
+@@ -1457,6 +1491,8 @@ static void handle_stripe(struct stripe_head *sh)
+ 			bi->bi_next = NULL;
+ 			generic_make_request(bi);
+ 		} else {
++			if (rw == 1)
++				set_bit(STRIPE_DEGRADED, &sh->state);
+ 			PRINTK("skip op %ld on disc %d for sector %llu\n",
+ 				bi->bi_rw, i, (unsigned long long)sh->sector);
+ 			clear_bit(R5_LOCKED, &sh->dev[i].flags);
+@@ -1481,6 +1517,20 @@ static inline void raid6_activate_delayed(raid6_conf_t *conf)
+ 	}
+ }
+ 
++static inline void activate_bit_delay(raid6_conf_t *conf)
++{
++	/* device_lock is held */
++	struct list_head head;
++	list_add(&head, &conf->bitmap_list);
++	list_del_init(&conf->bitmap_list);
++	while (!list_empty(&head)) {
++		struct stripe_head *sh = list_entry(head.next, struct stripe_head, lru);
++		list_del_init(&sh->lru);
++		atomic_inc(&sh->count);
++		__release_stripe(conf, sh);
++	}
++}
++
+ static void unplug_slaves(mddev_t *mddev)
+ {
+ 	raid6_conf_t *conf = mddev_to_conf(mddev);
+@@ -1513,8 +1563,10 @@ static void raid6_unplug_device(request_queue_t *q)
+ 
+ 	spin_lock_irqsave(&conf->device_lock, flags);
+ 
+-	if (blk_remove_plug(q))
++	if (blk_remove_plug(q)) {
++		conf->seq_flush++;
+ 		raid6_activate_delayed(conf);
++	}
+ 	md_wakeup_thread(mddev->thread);
+ 
+ 	spin_unlock_irqrestore(&conf->device_lock, flags);
+@@ -1652,10 +1704,20 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
+ 	sector_t first_sector;
+ 	int raid_disks = conf->raid_disks;
+ 	int data_disks = raid_disks - 2;
++	sector_t max_sector = mddev->size << 1;
++	int sync_blocks;
+ 
+-	if (sector_nr >= mddev->size <<1) {
++	if (sector_nr >= max_sector) {
+ 		/* just being told to finish up .. nothing much to do */
+ 		unplug_slaves(mddev);
++
++		if (mddev->curr_resync < max_sector) /* aborted */
++			bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
++					&sync_blocks, 1);
++		else /* compelted sync */
++			conf->fullsync = 0;
++		bitmap_close_sync(mddev->bitmap);
++
+ 		return 0;
+ 	}
+ 	/* if there are 2 or more failed drives and we are trying
+@@ -1667,6 +1729,13 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
+ 		*skipped = 1;
+ 		return rv;
+ 	}
++	if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
++	    !conf->fullsync && sync_blocks >= STRIPE_SECTORS) {
++		/* we can skip this block, and probably more */
++		sync_blocks /= STRIPE_SECTORS;
++		*skipped = 1;
++		return sync_blocks * STRIPE_SECTORS; /* keep things rounded to whole stripes */
++	}
+ 
+ 	x = sector_nr;
+ 	chunk_offset = sector_div(x, sectors_per_chunk);
+@@ -1684,6 +1753,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
+ 		set_current_state(TASK_UNINTERRUPTIBLE);
+ 		schedule_timeout(1);
+ 	}
++	bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 0);
+ 	spin_lock(&sh->lock);
+ 	set_bit(STRIPE_SYNCING, &sh->state);
+ 	clear_bit(STRIPE_INSYNC, &sh->state);
+@@ -1717,6 +1787,13 @@ static void raid6d (mddev_t *mddev)
+ 	while (1) {
+ 		struct list_head *first;
+ 
++		if (conf->seq_flush - conf->seq_write > 0) {
++			int seq = conf->seq_flush;
++			bitmap_unplug(mddev->bitmap);
++			conf->seq_write = seq;
++			activate_bit_delay(conf);
++		}
++
+ 		if (list_empty(&conf->handle_list) &&
+ 		    atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD &&
+ 		    !blk_queue_plugged(mddev->queue) &&
+@@ -1750,7 +1827,7 @@ static void raid6d (mddev_t *mddev)
+ 	PRINTK("--- raid6d inactive\n");
+ }
+ 
+-static int run (mddev_t *mddev)
++static int run(mddev_t *mddev)
+ {
+ 	raid6_conf_t *conf;
+ 	int raid_disk, memory;
+@@ -1780,6 +1857,7 @@ static int run (mddev_t *mddev)
+ 	init_waitqueue_head(&conf->wait_for_overlap);
+ 	INIT_LIST_HEAD(&conf->handle_list);
+ 	INIT_LIST_HEAD(&conf->delayed_list);
++	INIT_LIST_HEAD(&conf->bitmap_list);
+ 	INIT_LIST_HEAD(&conf->inactive_list);
+ 	atomic_set(&conf->active_stripes, 0);
+ 	atomic_set(&conf->preread_active_stripes, 0);
+@@ -1899,6 +1977,9 @@ static int run (mddev_t *mddev)
+ 	/* Ok, everything is just fine now */
+ 	mddev->array_size =  mddev->size * (mddev->raid_disks - 2);
+ 
++	if (mddev->bitmap)
++		mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
++
+ 	mddev->queue->unplug_fn = raid6_unplug_device;
+ 	mddev->queue->issue_flush_fn = raid6_issue_flush;
+ 	return 0;
+@@ -2076,6 +2157,8 @@ static int raid6_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
+ 			rdev->in_sync = 0;
+ 			rdev->raid_disk = disk;
+ 			found = 1;
++			if (rdev->saved_raid_disk != disk)
++				conf->fullsync = 1;
+ 			p->rdev = rdev;
+ 			break;
+ 		}
+@@ -2105,6 +2188,35 @@ static int raid6_resize(mddev_t *mddev, sector_t sectors)
+ 	return 0;
+ }
+ 
++static void raid6_quiesce(mddev_t *mddev, int state)
++{
++	raid6_conf_t *conf = mddev_to_conf(mddev);
++
++	switch(state) {
++	case 1: /* stop all writes */
++		spin_lock_irq(&conf->device_lock);
++		conf->quiesce = 1;
++		wait_event_lock_irq(conf->wait_for_stripe,
++				    atomic_read(&conf->active_stripes) == 0,
++				    conf->device_lock, /* nothing */);
++		spin_unlock_irq(&conf->device_lock);
++		break;
++
++	case 0: /* re-enable writes */
++		spin_lock_irq(&conf->device_lock);
++		conf->quiesce = 0;
++		wake_up(&conf->wait_for_stripe);
++		spin_unlock_irq(&conf->device_lock);
++		break;
++	}
++	if (mddev->thread) {
++		if (mddev->bitmap)
++			mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
++		else
++			mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
++		md_wakeup_thread(mddev->thread);
++	}
++}
+ static mdk_personality_t raid6_personality=
+ {
+ 	.name		= "raid6",
+@@ -2119,6 +2231,7 @@ static mdk_personality_t raid6_personality=
+ 	.spare_active	= raid6_spare_active,
+ 	.sync_request	= sync_request,
+ 	.resize		= raid6_resize,
++	.quiesce	= raid6_quiesce,
+ };
+ 
+ static int __init raid6_init (void)

commit 72626685dc66d455742a7f215a0535c551628b9e
+Author: NeilBrown 
+Date:   Fri Sep 9 16:23:54 2005 -0700
+
+    [PATCH] md: add write-intent-bitmap support to raid5
+    
+    Most awkward part of this is delaying write requests until bitmap updates have
+    been flushed.
+    
+    To achieve this, we have a sequence number (seq_flush) which is incremented
+    each time the raid5 is unplugged.
+    
+    If the raid thread notices that this has changed, it flushes bitmap changes,
+    and assigned the value of seq_flush to seq_write.
+    
+    When a write request arrives, it is given the number from seq_write, and that
+    write request may not complete until seq_flush is larger than the saved seq
+    number.
+    
+    We have a new queue for storing stripes which are waiting for a bitmap flush
+    and an extra flag for stripes to record if the write was 'degraded' and so
+    should not clear the a bit in the bitmap.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index be7873c61b3c..dbf540a7fccc 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -645,7 +645,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+ 
+ 		if (sb->state & (1<bitmap_file == NULL) {
+-			if (mddev->level != 1) {
++			if (mddev->level != 1 && mddev->level != 5) {
+ 				/* FIXME use a better test */
+ 				printk(KERN_WARNING "md: bitmaps only support for raid1\n");
+ 				return -EINVAL;
+@@ -3517,7 +3517,6 @@ void md_done_sync(mddev_t *mddev, int blocks, int ok)
+  */
+ void md_write_start(mddev_t *mddev, struct bio *bi)
+ {
+-	DEFINE_WAIT(w);
+ 	if (bio_data_dir(bi) != WRITE)
+ 		return;
+ 
+diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
+index ed859e08d600..4683ca24c046 100644
+--- a/drivers/md/raid5.c
++++ b/drivers/md/raid5.c
+@@ -24,6 +24,8 @@
+ #include 
+ #include 
+ 
++#include 
++
+ /*
+  * Stripe cache
+  */
+@@ -79,8 +81,13 @@ static inline void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
+ 		if (test_bit(STRIPE_HANDLE, &sh->state)) {
+ 			if (test_bit(STRIPE_DELAYED, &sh->state))
+ 				list_add_tail(&sh->lru, &conf->delayed_list);
+-			else
++			else if (test_bit(STRIPE_BIT_DELAY, &sh->state) &&
++				 conf->seq_write == sh->bm_seq)
++				list_add_tail(&sh->lru, &conf->bitmap_list);
++			else {
++				clear_bit(STRIPE_BIT_DELAY, &sh->state);
+ 				list_add_tail(&sh->lru, &conf->handle_list);
++			}
+ 			md_wakeup_thread(conf->mddev->thread);
+ 		} else {
+ 			if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
+@@ -244,6 +251,9 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector
+ 	spin_lock_irq(&conf->device_lock);
+ 
+ 	do {
++		wait_event_lock_irq(conf->wait_for_stripe,
++				    conf->quiesce == 0,
++				    conf->device_lock, /* nothing */);
+ 		sh = __find_stripe(conf, sector);
+ 		if (!sh) {
+ 			if (!conf->inactive_blocked)
+@@ -803,6 +813,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
+ {
+ 	struct bio **bip;
+ 	raid5_conf_t *conf = sh->raid_conf;
++	int firstwrite=0;
+ 
+ 	PRINTK("adding bh b#%llu to stripe s#%llu\n",
+ 		(unsigned long long)bi->bi_sector,
+@@ -811,9 +822,11 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
+ 
+ 	spin_lock(&sh->lock);
+ 	spin_lock_irq(&conf->device_lock);
+-	if (forwrite)
++	if (forwrite) {
+ 		bip = &sh->dev[dd_idx].towrite;
+-	else
++		if (*bip == NULL && sh->dev[dd_idx].written == NULL)
++			firstwrite = 1;
++	} else
+ 		bip = &sh->dev[dd_idx].toread;
+ 	while (*bip && (*bip)->bi_sector < bi->bi_sector) {
+ 		if ((*bip)->bi_sector + ((*bip)->bi_size >> 9) > bi->bi_sector)
+@@ -836,6 +849,13 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
+ 		(unsigned long long)bi->bi_sector,
+ 		(unsigned long long)sh->sector, dd_idx);
+ 
++	if (conf->mddev->bitmap && firstwrite) {
++		sh->bm_seq = conf->seq_write;
++		bitmap_startwrite(conf->mddev->bitmap, sh->sector,
++				  STRIPE_SECTORS, 0);
++		set_bit(STRIPE_BIT_DELAY, &sh->state);
++	}
++
+ 	if (forwrite) {
+ 		/* check if page is covered */
+ 		sector_t sector = sh->dev[dd_idx].sector;
+@@ -958,12 +978,13 @@ static void handle_stripe(struct stripe_head *sh)
+ 	 * need to be failed
+ 	 */
+ 	if (failed > 1 && to_read+to_write+written) {
+-		spin_lock_irq(&conf->device_lock);
+ 		for (i=disks; i--; ) {
++			int bitmap_end = 0;
++			spin_lock_irq(&conf->device_lock);
+ 			/* fail all writes first */
+ 			bi = sh->dev[i].towrite;
+ 			sh->dev[i].towrite = NULL;
+-			if (bi) to_write--;
++			if (bi) { to_write--; bitmap_end = 1; }
+ 
+ 			if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
+ 				wake_up(&conf->wait_for_overlap);
+@@ -981,6 +1002,7 @@ static void handle_stripe(struct stripe_head *sh)
+ 			/* and fail all 'written' */
+ 			bi = sh->dev[i].written;
+ 			sh->dev[i].written = NULL;
++			if (bi) bitmap_end = 1;
+ 			while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) {
+ 				struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
+ 				clear_bit(BIO_UPTODATE, &bi->bi_flags);
+@@ -1009,8 +1031,11 @@ static void handle_stripe(struct stripe_head *sh)
+ 					bi = nextbi;
+ 				}
+ 			}
++			spin_unlock_irq(&conf->device_lock);
++			if (bitmap_end)
++				bitmap_endwrite(conf->mddev->bitmap, sh->sector,
++						STRIPE_SECTORS, 0, 0);
+ 		}
+-		spin_unlock_irq(&conf->device_lock);
+ 	}
+ 	if (failed > 1 && syncing) {
+ 		md_done_sync(conf->mddev, STRIPE_SECTORS,0);
+@@ -1038,6 +1063,7 @@ static void handle_stripe(struct stripe_head *sh)
+ 			 test_bit(R5_UPTODATE, &dev->flags) ) {
+ 			/* We can return any write requests */
+ 			    struct bio *wbi, *wbi2;
++			    int bitmap_end = 0;
+ 			    PRINTK("Return write for disc %d\n", i);
+ 			    spin_lock_irq(&conf->device_lock);
+ 			    wbi = dev->written;
+@@ -1051,7 +1077,13 @@ static void handle_stripe(struct stripe_head *sh)
+ 				    }
+ 				    wbi = wbi2;
+ 			    }
++			    if (dev->towrite == NULL)
++				    bitmap_end = 1;
+ 			    spin_unlock_irq(&conf->device_lock);
++			    if (bitmap_end)
++				    bitmap_endwrite(conf->mddev->bitmap, sh->sector,
++						    STRIPE_SECTORS,
++						    !test_bit(STRIPE_DEGRADED, &sh->state), 0);
+ 		    }
+ 		}
+ 	}
+@@ -1175,7 +1207,8 @@ static void handle_stripe(struct stripe_head *sh)
+ 				}
+ 			}
+ 		/* now if nothing is locked, and if we have enough data, we can start a write request */
+-		if (locked == 0 && (rcw == 0 ||rmw == 0)) {
++		if (locked == 0 && (rcw == 0 ||rmw == 0) &&
++		    !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
+ 			PRINTK("Computing parity...\n");
+ 			compute_parity(sh, rcw==0 ? RECONSTRUCT_WRITE : READ_MODIFY_WRITE);
+ 			/* now every locked buffer is ready to be written */
+@@ -1231,6 +1264,7 @@ static void handle_stripe(struct stripe_head *sh)
+ 			dev = &sh->dev[failed_num];
+ 			set_bit(R5_LOCKED, &dev->flags);
+ 			set_bit(R5_Wantwrite, &dev->flags);
++			clear_bit(STRIPE_DEGRADED, &sh->state);
+ 			locked++;
+ 			set_bit(STRIPE_INSYNC, &sh->state);
+ 			set_bit(R5_Syncio, &dev->flags);
+@@ -1298,6 +1332,8 @@ static void handle_stripe(struct stripe_head *sh)
+ 			bi->bi_next = NULL;
+ 			generic_make_request(bi);
+ 		} else {
++			if (rw == 1)
++				set_bit(STRIPE_DEGRADED, &sh->state);
+ 			PRINTK("skip op %ld on disc %d for sector %llu\n",
+ 				bi->bi_rw, i, (unsigned long long)sh->sector);
+ 			clear_bit(R5_LOCKED, &sh->dev[i].flags);
+@@ -1322,6 +1358,20 @@ static inline void raid5_activate_delayed(raid5_conf_t *conf)
+ 	}
+ }
+ 
++static inline void activate_bit_delay(raid5_conf_t *conf)
++{
++	/* device_lock is held */
++	struct list_head head;
++	list_add(&head, &conf->bitmap_list);
++	list_del_init(&conf->bitmap_list);
++	while (!list_empty(&head)) {
++		struct stripe_head *sh = list_entry(head.next, struct stripe_head, lru);
++		list_del_init(&sh->lru);
++		atomic_inc(&sh->count);
++		__release_stripe(conf, sh);
++	}
++}
++
+ static void unplug_slaves(mddev_t *mddev)
+ {
+ 	raid5_conf_t *conf = mddev_to_conf(mddev);
+@@ -1354,8 +1404,10 @@ static void raid5_unplug_device(request_queue_t *q)
+ 
+ 	spin_lock_irqsave(&conf->device_lock, flags);
+ 
+-	if (blk_remove_plug(q))
++	if (blk_remove_plug(q)) {
++		conf->seq_flush++;
+ 		raid5_activate_delayed(conf);
++	}
+ 	md_wakeup_thread(mddev->thread);
+ 
+ 	spin_unlock_irqrestore(&conf->device_lock, flags);
+@@ -1493,10 +1545,20 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
+ 	sector_t first_sector;
+ 	int raid_disks = conf->raid_disks;
+ 	int data_disks = raid_disks-1;
++	sector_t max_sector = mddev->size << 1;
++	int sync_blocks;
+ 
+-	if (sector_nr >= mddev->size <<1) {
++	if (sector_nr >= max_sector) {
+ 		/* just being told to finish up .. nothing much to do */
+ 		unplug_slaves(mddev);
++
++		if (mddev->curr_resync < max_sector) /* aborted */
++			bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
++					&sync_blocks, 1);
++		else /* compelted sync */
++			conf->fullsync = 0;
++		bitmap_close_sync(mddev->bitmap);
++
+ 		return 0;
+ 	}
+ 	/* if there is 1 or more failed drives and we are trying
+@@ -1508,6 +1570,13 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
+ 		*skipped = 1;
+ 		return rv;
+ 	}
++	if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
++	    !conf->fullsync && sync_blocks >= STRIPE_SECTORS) {
++		/* we can skip this block, and probably more */
++		sync_blocks /= STRIPE_SECTORS;
++		*skipped = 1;
++		return sync_blocks * STRIPE_SECTORS; /* keep things rounded to whole stripes */
++	}
+ 
+ 	x = sector_nr;
+ 	chunk_offset = sector_div(x, sectors_per_chunk);
+@@ -1525,6 +1594,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
+ 		set_current_state(TASK_UNINTERRUPTIBLE);
+ 		schedule_timeout(1);
+ 	}
++	bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 0);
+ 	spin_lock(&sh->lock);	
+ 	set_bit(STRIPE_SYNCING, &sh->state);
+ 	clear_bit(STRIPE_INSYNC, &sh->state);
+@@ -1558,6 +1628,13 @@ static void raid5d (mddev_t *mddev)
+ 	while (1) {
+ 		struct list_head *first;
+ 
++		if (conf->seq_flush - conf->seq_write > 0) {
++			int seq = conf->seq_flush;
++			bitmap_unplug(mddev->bitmap);
++			conf->seq_write = seq;
++			activate_bit_delay(conf);
++		}
++
+ 		if (list_empty(&conf->handle_list) &&
+ 		    atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD &&
+ 		    !blk_queue_plugged(mddev->queue) &&
+@@ -1591,7 +1668,7 @@ static void raid5d (mddev_t *mddev)
+ 	PRINTK("--- raid5d inactive\n");
+ }
+ 
+-static int run (mddev_t *mddev)
++static int run(mddev_t *mddev)
+ {
+ 	raid5_conf_t *conf;
+ 	int raid_disk, memory;
+@@ -1621,6 +1698,7 @@ static int run (mddev_t *mddev)
+ 	init_waitqueue_head(&conf->wait_for_overlap);
+ 	INIT_LIST_HEAD(&conf->handle_list);
+ 	INIT_LIST_HEAD(&conf->delayed_list);
++	INIT_LIST_HEAD(&conf->bitmap_list);
+ 	INIT_LIST_HEAD(&conf->inactive_list);
+ 	atomic_set(&conf->active_stripes, 0);
+ 	atomic_set(&conf->preread_active_stripes, 0);
+@@ -1732,6 +1810,9 @@ memory = conf->max_nr_stripes * (sizeof(struct stripe_head) +
+ 
+ 	/* Ok, everything is just fine now */
+ 
++	if (mddev->bitmap)
++		mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
++
+ 	mddev->queue->unplug_fn = raid5_unplug_device;
+ 	mddev->queue->issue_flush_fn = raid5_issue_flush;
+ 
+@@ -1912,6 +1993,8 @@ static int raid5_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
+ 			rdev->in_sync = 0;
+ 			rdev->raid_disk = disk;
+ 			found = 1;
++			if (rdev->saved_raid_disk != disk)
++				conf->fullsync = 1;
+ 			p->rdev = rdev;
+ 			break;
+ 		}
+@@ -1941,6 +2024,35 @@ static int raid5_resize(mddev_t *mddev, sector_t sectors)
+ 	return 0;
+ }
+ 
++static void raid5_quiesce(mddev_t *mddev, int state)
++{
++	raid5_conf_t *conf = mddev_to_conf(mddev);
++
++	switch(state) {
++	case 1: /* stop all writes */
++		spin_lock_irq(&conf->device_lock);
++		conf->quiesce = 1;
++		wait_event_lock_irq(conf->wait_for_stripe,
++				    atomic_read(&conf->active_stripes) == 0,
++				    conf->device_lock, /* nothing */);
++		spin_unlock_irq(&conf->device_lock);
++		break;
++
++	case 0: /* re-enable writes */
++		spin_lock_irq(&conf->device_lock);
++		conf->quiesce = 0;
++		wake_up(&conf->wait_for_stripe);
++		spin_unlock_irq(&conf->device_lock);
++		break;
++	}
++	if (mddev->thread) {
++		if (mddev->bitmap)
++			mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
++		else
++			mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
++		md_wakeup_thread(mddev->thread);
++	}
++}
+ static mdk_personality_t raid5_personality=
+ {
+ 	.name		= "raid5",
+@@ -1955,6 +2067,7 @@ static mdk_personality_t raid5_personality=
+ 	.spare_active	= raid5_spare_active,
+ 	.sync_request	= sync_request,
+ 	.resize		= raid5_resize,
++	.quiesce	= raid5_quiesce,
+ };
+ 
+ static int __init raid5_init (void)
+diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h
+index d63ddcb4afad..176fc653c284 100644
+--- a/include/linux/raid/raid5.h
++++ b/include/linux/raid/raid5.h
+@@ -134,6 +134,7 @@ struct stripe_head {
+ 	unsigned long		state;			/* state flags */
+ 	atomic_t		count;			/* nr of active thread/requests */
+ 	spinlock_t		lock;
++	int			bm_seq;	/* sequence number for bitmap flushes */
+ 	struct r5dev {
+ 		struct bio	req;
+ 		struct bio_vec	vec;
+@@ -165,12 +166,13 @@ struct stripe_head {
+ /*
+  * Stripe state
+  */
+-#define STRIPE_ERROR		1
+ #define STRIPE_HANDLE		2
+ #define	STRIPE_SYNCING		3
+ #define	STRIPE_INSYNC		4
+ #define	STRIPE_PREREAD_ACTIVE	5
+ #define	STRIPE_DELAYED		6
++#define	STRIPE_DEGRADED		7
++#define	STRIPE_BIT_DELAY	8
+ 
+ /*
+  * Plugging:
+@@ -210,10 +212,20 @@ struct raid5_private_data {
+ 
+ 	struct list_head	handle_list; /* stripes needing handling */
+ 	struct list_head	delayed_list; /* stripes that have plugged requests */
++	struct list_head	bitmap_list; /* stripes delaying awaiting bitmap update */
+ 	atomic_t		preread_active_stripes; /* stripes with scheduled io */
+ 
+ 	char			cache_name[20];
+ 	kmem_cache_t		*slab_cache; /* for allocating stripes */
++
++	int			seq_flush, seq_write;
++	int			quiesce;
++
++	int			fullsync;  /* set to 1 if a full sync is needed,
++					    * (fresh device added).
++					    * Cleared when a sync completes.
++					    */
++
+ 	/*
+ 	 * Free stripes pool
+ 	 */

commit 0002b2718dd04da67c21f8a7830de8d95a9b0345
+Author: NeilBrown 
+Date:   Fri Sep 9 16:23:53 2005 -0700
+
+    [PATCH] md: limit size of sb read/written to appropriate amount
+    
+    version-1 superblocks are not (normally) 4K long, and can be of variable size.
+     Writing the full 4K can cause corruption (but only in non-default
+    configurations).
+    
+    With this patch the super-block-flavour can choose a size to read, and set a
+    size to write based on what it finds.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 1be3f2de396b..be7873c61b3c 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -393,7 +393,7 @@ int sync_page_io(struct block_device *bdev, sector_t sector, int size,
+ 	return ret;
+ }
+ 
+-static int read_disk_sb(mdk_rdev_t * rdev)
++static int read_disk_sb(mdk_rdev_t * rdev, int size)
+ {
+ 	char b[BDEVNAME_SIZE];
+ 	if (!rdev->sb_page) {
+@@ -404,7 +404,7 @@ static int read_disk_sb(mdk_rdev_t * rdev)
+ 		return 0;
+ 
+ 
+-	if (!sync_page_io(rdev->bdev, rdev->sb_offset<<1, MD_SB_BYTES, rdev->sb_page, READ))
++	if (!sync_page_io(rdev->bdev, rdev->sb_offset<<1, size, rdev->sb_page, READ))
+ 		goto fail;
+ 	rdev->sb_loaded = 1;
+ 	return 0;
+@@ -531,7 +531,7 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
+ 	sb_offset = calc_dev_sboffset(rdev->bdev);
+ 	rdev->sb_offset = sb_offset;
+ 
+-	ret = read_disk_sb(rdev);
++	ret = read_disk_sb(rdev, MD_SB_BYTES);
+ 	if (ret) return ret;
+ 
+ 	ret = -EINVAL;
+@@ -564,6 +564,7 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
+ 
+ 	rdev->preferred_minor = sb->md_minor;
+ 	rdev->data_offset = 0;
++	rdev->sb_size = MD_SB_BYTES;
+ 
+ 	if (sb->level == LEVEL_MULTIPATH)
+ 		rdev->desc_nr = -1;
+@@ -837,6 +838,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
+ 	int ret;
+ 	sector_t sb_offset;
+ 	char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
++	int bmask;
+ 
+ 	/*
+ 	 * Calculate the position of the superblock.
+@@ -865,7 +867,10 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
+ 	}
+ 	rdev->sb_offset = sb_offset;
+ 
+-	ret = read_disk_sb(rdev);
++	/* superblock is rarely larger than 1K, but it can be larger,
++	 * and it is safe to read 4k, so we do that
++	 */
++	ret = read_disk_sb(rdev, 4096);
+ 	if (ret) return ret;
+ 
+ 
+@@ -891,6 +896,11 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
+ 	rdev->preferred_minor = 0xffff;
+ 	rdev->data_offset = le64_to_cpu(sb->data_offset);
+ 
++	rdev->sb_size = le32_to_cpu(sb->max_dev) * 2 + 256;
++	bmask = block_size(rdev->bdev)-1;
++	if (rdev->sb_size & bmask)
++		rdev-> sb_size = (rdev->sb_size | bmask)+1;
++
+ 	if (refdev == 0)
+ 		return 1;
+ 	else {
+@@ -1375,7 +1385,7 @@ static void md_update_sb(mddev_t * mddev)
+ 		dprintk("%s ", bdevname(rdev->bdev,b));
+ 		if (!rdev->faulty) {
+ 			md_super_write(mddev,rdev,
+-				       rdev->sb_offset<<1, MD_SB_BYTES,
++				       rdev->sb_offset<<1, rdev->sb_size,
+ 				       rdev->sb_page);
+ 			dprintk(KERN_INFO "(write) %s's sb offset: %llu\n",
+ 				bdevname(rdev->bdev,b),
+diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
+index 8042f55dd323..ebce949b1443 100644
+--- a/include/linux/raid/md_k.h
++++ b/include/linux/raid/md_k.h
+@@ -102,6 +102,7 @@ struct mdk_rdev_s
+ 	int		sb_loaded;
+ 	sector_t	data_offset;	/* start of data in array */
+ 	sector_t	sb_offset;
++	int		sb_size;	/* bytes in the superblock */
+ 	int		preferred_minor;	/* autorun support */
+ 
+ 	/* A device can be in one of three states based on two flags:

commit 773f7834425e83144c95fbbc553ced3c2b74b828
+Author: NeilBrown 
+Date:   Fri Sep 9 16:23:53 2005 -0700
+
+    [PATCH] md: remove old cruft from md_k.h header file
+    
+    These inlines haven't been used for ages, they should go.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
+index 2514e5fcda7f..8042f55dd323 100644
+--- a/include/linux/raid/md_k.h
++++ b/include/linux/raid/md_k.h
+@@ -85,70 +85,6 @@ typedef struct mdk_rdev_s mdk_rdev_t;
+ 
+ #define MAX_CHUNK_SIZE (4096*1024)
+ 
+-/*
+- * default readahead
+- */
+-
+-static inline int disk_faulty(mdp_disk_t * d)
+-{
+-	return d->state & (1 << MD_DISK_FAULTY);
+-}
+-
+-static inline int disk_active(mdp_disk_t * d)
+-{
+-	return d->state & (1 << MD_DISK_ACTIVE);
+-}
+-
+-static inline int disk_sync(mdp_disk_t * d)
+-{
+-	return d->state & (1 << MD_DISK_SYNC);
+-}
+-
+-static inline int disk_spare(mdp_disk_t * d)
+-{
+-	return !disk_sync(d) && !disk_active(d) && !disk_faulty(d);
+-}
+-
+-static inline int disk_removed(mdp_disk_t * d)
+-{
+-	return d->state & (1 << MD_DISK_REMOVED);
+-}
+-
+-static inline void mark_disk_faulty(mdp_disk_t * d)
+-{
+-	d->state |= (1 << MD_DISK_FAULTY);
+-}
+-
+-static inline void mark_disk_active(mdp_disk_t * d)
+-{
+-	d->state |= (1 << MD_DISK_ACTIVE);
+-}
+-
+-static inline void mark_disk_sync(mdp_disk_t * d)
+-{
+-	d->state |= (1 << MD_DISK_SYNC);
+-}
+-
+-static inline void mark_disk_spare(mdp_disk_t * d)
+-{
+-	d->state = 0;
+-}
+-
+-static inline void mark_disk_removed(mdp_disk_t * d)
+-{
+-	d->state = (1 << MD_DISK_FAULTY) | (1 << MD_DISK_REMOVED);
+-}
+-
+-static inline void mark_disk_inactive(mdp_disk_t * d)
+-{
+-	d->state &= ~(1 << MD_DISK_ACTIVE);
+-}
+-
+-static inline void mark_disk_nonsync(mdp_disk_t * d)
+-{
+-	d->state &= ~(1 << MD_DISK_SYNC);
+-}
+-
+ /*
+  * MD's 'extended' device
+  */

commit ab904d634625ef8dc590240b7ee06c7b724e636b
+Author: NeilBrown 
+Date:   Fri Sep 9 16:23:52 2005 -0700
+
+    [PATCH] md: fix bitmap/read_sb_page so that it handles errors properly.
+    
+    read_sb_page() assumed that if sync_page_io fails, the device would be marked
+    faultly.  However it isn't.  So in the face of error, read_sb_page would loop
+    forever.
+    
+    Redo the logic so that this cannot happen.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
+index c971d38f3a05..90fe70d76a31 100644
+--- a/drivers/md/bitmap.c
++++ b/drivers/md/bitmap.c
+@@ -270,19 +270,20 @@ static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long inde
+ 
+ 	if (!page)
+ 		return ERR_PTR(-ENOMEM);
+-	do {
+-		ITERATE_RDEV(mddev, rdev, tmp)
+-			if (rdev->in_sync && !rdev->faulty)
+-				goto found;
+-		return ERR_PTR(-EIO);
+ 
+-	found:
++	ITERATE_RDEV(mddev, rdev, tmp) {
++		if (! rdev->in_sync || rdev->faulty)
++			continue;
++
+ 		target = (rdev->sb_offset << 1) + offset + index * (PAGE_SIZE/512);
+ 
+-	} while (!sync_page_io(rdev->bdev, target, PAGE_SIZE, page, READ));
++		if (sync_page_io(rdev->bdev, target, PAGE_SIZE, page, READ)) {
++			page->index = index;
++			return page;
++		}
++	}
++	return ERR_PTR(-EIO);
+ 
+-	page->index = index;
+-	return page;
+ }
+ 
+ static int write_sb_page(mddev_t *mddev, long offset, struct page *page, int wait)

commit 71c0805cb48462c99fbe0e5fcc6c12d7b9929c09
+Author: NeilBrown 
+Date:   Fri Sep 9 16:23:51 2005 -0700
+
+    [PATCH] md: allow md to load a superblock with feature-bit '1' set
+    
+    As this is used to flag an internal bitmap.
+    
+    Also, introduce symbolic names for feature bits.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 866c704e008a..1be3f2de396b 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -875,7 +875,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
+ 	    sb->major_version != cpu_to_le32(1) ||
+ 	    le32_to_cpu(sb->max_dev) > (4096-256)/2 ||
+ 	    le64_to_cpu(sb->super_offset) != (rdev->sb_offset<<1) ||
+-	    sb->feature_map != 0)
++	    (le32_to_cpu(sb->feature_map) & ~MD_FEATURE_ALL) != 0)
+ 		return -EINVAL;
+ 
+ 	if (calc_sb_1_csum(sb) != sb->sb_csum) {
+@@ -954,7 +954,7 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+ 
+ 		mddev->max_disks =  (4096-256)/2;
+ 
+-		if ((le32_to_cpu(sb->feature_map) & 1) &&
++		if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET) &&
+ 		    mddev->bitmap_file == NULL ) {
+ 			if (mddev->level != 1) {
+ 				printk(KERN_WARNING "md: bitmaps only supported for raid1\n");
+@@ -1029,7 +1029,7 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
+ 
+ 	if (mddev->bitmap && mddev->bitmap_file == NULL) {
+ 		sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset);
+-		sb->feature_map = cpu_to_le32(1);
++		sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET);
+ 	}
+ 
+ 	max_dev = 0;
+diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h
+index 4f047f84fb1f..c100fa5d4bfa 100644
+--- a/include/linux/raid/md_p.h
++++ b/include/linux/raid/md_p.h
+@@ -238,5 +238,10 @@ struct mdp_superblock_1 {
+ 	__u16	dev_roles[0];	/* role in array, or 0xffff for a spare, or 0xfffe for faulty */
+ };
+ 
++/* feature_map bits */
++#define MD_FEATURE_BITMAP_OFFSET	1
++
++#define	MD_FEATURE_ALL			1
++
+ #endif 
+ 

commit 7b1e35f6d666693e8f376ce02242efca3ec09aaf
+Author: NeilBrown 
+Date:   Fri Sep 9 16:23:50 2005 -0700
+
+    [PATCH] md: allow hot-adding devices to arrays with non-persistant superblocks.
+    
+    It is possibly (and occasionally useful) to have a raid1 without persistent
+    superblocks.  The code in add_new_disk for adding a device to such an array
+    always tries to read a superblock.
+    
+    This will obviously fail.
+    
+    So do the appropriate test and call md_import_device with
+    appropriate args.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index f1ac356e656d..866c704e008a 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -2226,8 +2226,11 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
+ 			       mdname(mddev));
+ 			return -EINVAL;
+ 		}
+-		rdev = md_import_device(dev, mddev->major_version,
+-					mddev->minor_version);
++		if (mddev->persistent)
++			rdev = md_import_device(dev, mddev->major_version,
++						mddev->minor_version);
++		else
++			rdev = md_import_device(dev, -1, -1);
+ 		if (IS_ERR(rdev)) {
+ 			printk(KERN_WARNING 
+ 				"md: md_import_device returned %ld\n",

commit 3178b0dbdf67322f6506582e494bdf553cc85c32
+Author: NeilBrown 
+Date:   Fri Sep 9 16:23:50 2005 -0700
+
+    [PATCH] md: do not set mddev->bitmap until bitmap is fully initialised
+    
+    When hot-adding a bitmap, bitmap_daemon_work could get called while the bitmap
+    is being created, so don't set mddev->bitmap until the bitmap is ready.
+    
+    This requires freeing the bitmap inside bitmap_create if creation failed
+    part-way through.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
+index f0f510c13410..c971d38f3a05 100644
+--- a/drivers/md/bitmap.c
++++ b/drivers/md/bitmap.c
+@@ -1503,17 +1503,14 @@ void bitmap_flush(mddev_t *mddev)
+ /*
+  * free memory that was allocated
+  */
+-void bitmap_destroy(mddev_t *mddev)
++static void bitmap_free(struct bitmap *bitmap)
+ {
+ 	unsigned long k, pages;
+ 	struct bitmap_page *bp;
+-	struct bitmap *bitmap = mddev->bitmap;
+ 
+ 	if (!bitmap) /* there was no bitmap */
+ 		return;
+ 
+-	mddev->bitmap = NULL; /* disconnect from the md device */
+-
+ 	/* release the bitmap file and kill the daemon */
+ 	bitmap_file_put(bitmap);
+ 
+@@ -1531,6 +1528,17 @@ void bitmap_destroy(mddev_t *mddev)
+ 	kfree(bp);
+ 	kfree(bitmap);
+ }
++void bitmap_destroy(mddev_t *mddev)
++{
++	struct bitmap *bitmap = mddev->bitmap;
++
++	if (!bitmap) /* there was no bitmap */
++		return;
++
++	mddev->bitmap = NULL; /* disconnect from the md device */
++
++	bitmap_free(bitmap);
++}
+ 
+ /*
+  * initialize the bitmap structure
+@@ -1561,15 +1569,15 @@ int bitmap_create(mddev_t *mddev)
+ 
+ 	spin_lock_init(&bitmap->lock);
+ 	bitmap->mddev = mddev;
+-	mddev->bitmap = bitmap;
+ 
+ 	spin_lock_init(&bitmap->write_lock);
+ 	INIT_LIST_HEAD(&bitmap->complete_pages);
+ 	init_waitqueue_head(&bitmap->write_wait);
+ 	bitmap->write_pool = mempool_create(WRITE_POOL_SIZE, write_pool_alloc,
+ 				write_pool_free, NULL);
++	err = -ENOMEM;
+ 	if (!bitmap->write_pool)
+-		return -ENOMEM;
++		goto error;
+ 
+ 	bitmap->file = file;
+ 	bitmap->offset = mddev->bitmap_offset;
+@@ -1577,7 +1585,7 @@ int bitmap_create(mddev_t *mddev)
+ 	/* read superblock from bitmap file (this sets bitmap->chunksize) */
+ 	err = bitmap_read_sb(bitmap);
+ 	if (err)
+-		return err;
++		goto error;
+ 
+ 	bitmap->chunkshift = find_first_bit(&bitmap->chunksize,
+ 					sizeof(bitmap->chunksize));
+@@ -1601,8 +1609,9 @@ int bitmap_create(mddev_t *mddev)
+ #else
+ 	bitmap->bp = kmalloc(pages * sizeof(*bitmap->bp), GFP_KERNEL);
+ #endif
++	err = -ENOMEM;
+ 	if (!bitmap->bp)
+-		return -ENOMEM;
++		goto error;
+ 	memset(bitmap->bp, 0, pages * sizeof(*bitmap->bp));
+ 
+ 	bitmap->flags |= BITMAP_ACTIVE;
+@@ -1617,16 +1626,22 @@ int bitmap_create(mddev_t *mddev)
+ 	err = bitmap_init_from_disk(bitmap, start);
+ 
+ 	if (err)
+-		return err;
++		goto error;
+ 
+ 	printk(KERN_INFO "created bitmap (%lu pages) for device %s\n",
+ 		pages, bmname(bitmap));
+ 
++	mddev->bitmap = bitmap;
++
+ 	/* kick off the bitmap daemons */
+ 	err = bitmap_start_daemons(bitmap);
+ 	if (err)
+ 		return err;
+ 	return bitmap_update_sb(bitmap);
++
++ error:
++	bitmap_free(bitmap);
++	return err;
+ }
+ 
+ /* the bitmap API -- for raid personalities */

commit 585f0dd5a955c420ff3af5193aa07d6f789bf81a
+Author: NeilBrown 
+Date:   Fri Sep 9 16:23:49 2005 -0700
+
+    [PATCH] md: make sure bitmap_daemon_work actually does work.
+    
+    The 'lastrun' time wasn't being initialised, so it could be half a
+    jiffie-cycle before it seemed to be time to do work again.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
+index 2c84de2b4ad5..f0f510c13410 100644
+--- a/drivers/md/bitmap.c
++++ b/drivers/md/bitmap.c
+@@ -522,6 +522,7 @@ static int bitmap_read_sb(struct bitmap *bitmap)
+ 	/* assign fields using values from superblock */
+ 	bitmap->chunksize = chunksize;
+ 	bitmap->daemon_sleep = daemon_sleep;
++	bitmap->daemon_lastrun = jiffies;
+ 	bitmap->max_write_behind = write_behind;
+ 	bitmap->flags |= sb->state;
+ 	bitmap->events_cleared = le64_to_cpu(sb->events_cleared);

commit 9e6603da9b9cfb14a6aca3845227f8c59f7eeb9b
+Author: NeilBrown 
+Date:   Fri Sep 9 16:23:48 2005 -0700
+
+    [PATCH] md: raid1_quiesce is back to front, fix it.
+    
+    A state of 0 mean 'not quiesced'
+    A state of 1 means 'is quiesced'
+    
+    The original code got this wrong.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index ba7f5f256161..bfe78571586b 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -1708,14 +1708,14 @@ void raid1_quiesce(mddev_t *mddev, int state)
+ 	conf_t *conf = mddev_to_conf(mddev);
+ 
+ 	switch(state) {
+-	case 0:
++	case 1:
+ 		spin_lock_irq(&conf->resync_lock);
+ 		conf->barrier++;
+ 		wait_event_lock_irq(conf->wait_idle, !conf->nr_pending,
+ 				    conf->resync_lock, raid1_unplug(mddev->queue));
+ 		spin_unlock_irq(&conf->resync_lock);
+ 		break;
+-	case 1:
++	case 0:
+ 		spin_lock_irq(&conf->resync_lock);
+ 		conf->barrier--;
+ 		spin_unlock_irq(&conf->resync_lock);

commit 15945fee6f09bff1f86b1a735b5888dc59cf38e3
+Author: NeilBrown 
+Date:   Fri Sep 9 16:23:47 2005 -0700
+
+    [PATCH] md: support md/linear array with components greater than 2 terabytes.
+    
+    linear currently uses division by the size of the smallest componenet device
+    to find which device a request goes to.  If that smallest device is larger
+    than 2 terabytes, then the division will not work on some systems.
+    
+    So we introduce a pre-shift, and take care not to make the hash table too
+    large, much like the code in raid0.
+    
+    Also get rid of conf->nr_zones, which is not needed.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/linear.c b/drivers/md/linear.c
+index 4991ba543368..bb279fad2fd2 100644
+--- a/drivers/md/linear.c
++++ b/drivers/md/linear.c
+@@ -38,7 +38,8 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
+ 	/*
+ 	 * sector_div(a,b) returns the remainer and sets a to a/b
+ 	 */
+-	(void)sector_div(block, conf->smallest->size);
++	block >>= conf->preshift;
++	(void)sector_div(block, conf->hash_spacing);
+ 	hash = conf->hash_table[block];
+ 
+ 	while ((sector>>1) >= (hash->size + hash->offset))
+@@ -47,7 +48,7 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
+ }
+ 
+ /**
+- *	linear_mergeable_bvec -- tell bio layer if a two requests can be merged
++ *	linear_mergeable_bvec -- tell bio layer if two requests can be merged
+  *	@q: request queue
+  *	@bio: the buffer head that's been built up so far
+  *	@biovec: the request that could be merged to it.
+@@ -116,7 +117,7 @@ static int linear_run (mddev_t *mddev)
+ 	dev_info_t **table;
+ 	mdk_rdev_t *rdev;
+ 	int i, nb_zone, cnt;
+-	sector_t start;
++	sector_t min_spacing;
+ 	sector_t curr_offset;
+ 	struct list_head *tmp;
+ 
+@@ -127,11 +128,6 @@ static int linear_run (mddev_t *mddev)
+ 	memset(conf, 0, sizeof(*conf) + mddev->raid_disks*sizeof(dev_info_t));
+ 	mddev->private = conf;
+ 
+-	/*
+-	 * Find the smallest device.
+-	 */
+-
+-	conf->smallest = NULL;
+ 	cnt = 0;
+ 	mddev->array_size = 0;
+ 
+@@ -159,8 +155,6 @@ static int linear_run (mddev_t *mddev)
+ 		disk->size = rdev->size;
+ 		mddev->array_size += rdev->size;
+ 
+-		if (!conf->smallest || (disk->size < conf->smallest->size))
+-			conf->smallest = disk;
+ 		cnt++;
+ 	}
+ 	if (cnt != mddev->raid_disks) {
+@@ -168,6 +162,36 @@ static int linear_run (mddev_t *mddev)
+ 		goto out;
+ 	}
+ 
++	min_spacing = mddev->array_size;
++	sector_div(min_spacing, PAGE_SIZE/sizeof(struct dev_info *));
++
++	/* min_spacing is the minimum spacing that will fit the hash
++	 * table in one PAGE.  This may be much smaller than needed.
++	 * We find the smallest non-terminal set of consecutive devices
++	 * that is larger than min_spacing as use the size of that as
++	 * the actual spacing
++	 */
++	conf->hash_spacing = mddev->array_size;
++	for (i=0; i < cnt-1 ; i++) {
++		sector_t sz = 0;
++		int j;
++		for (j=i; idisks[j].size;
++		if (sz >= min_spacing && sz < conf->hash_spacing)
++			conf->hash_spacing = sz;
++	}
++
++	/* hash_spacing may be too large for sector_div to work with,
++	 * so we might need to pre-shift
++	 */
++	conf->preshift = 0;
++	if (sizeof(sector_t) > sizeof(u32)) {
++		sector_t space = conf->hash_spacing;
++		while (space > (sector_t)(~(u32)0)) {
++			space >>= 1;
++			conf->preshift++;
++		}
++	}
+ 	/*
+ 	 * This code was restructured to work around a gcc-2.95.3 internal
+ 	 * compiler error.  Alter it with care.
+@@ -177,39 +201,52 @@ static int linear_run (mddev_t *mddev)
+ 		unsigned round;
+ 		unsigned long base;
+ 
+-		sz = mddev->array_size;
+-		base = conf->smallest->size;
++		sz = mddev->array_size >> conf->preshift;
++		sz += 1; /* force round-up */
++		base = conf->hash_spacing >> conf->preshift;
+ 		round = sector_div(sz, base);
+-		nb_zone = conf->nr_zones = sz + (round ? 1 : 0);
++		nb_zone = sz + (round ? 1 : 0);
+ 	}
+-			
+-	conf->hash_table = kmalloc (sizeof (dev_info_t*) * nb_zone,
++	BUG_ON(nb_zone > PAGE_SIZE / sizeof(struct dev_info *));
++
++	conf->hash_table = kmalloc (sizeof (struct dev_info *) * nb_zone,
+ 					GFP_KERNEL);
+ 	if (!conf->hash_table)
+ 		goto out;
+ 
+ 	/*
+ 	 * Here we generate the linear hash table
++	 * First calculate the device offsets.
+ 	 */
++	conf->disks[0].offset = 0;
++	for (i=1; iraid_disks; i++)
++		conf->disks[i].offset =
++			conf->disks[i-1].offset +
++			conf->disks[i-1].size;
++
+ 	table = conf->hash_table;
+-	start = 0;
+ 	curr_offset = 0;
+-	for (i = 0; i < cnt; i++) {
+-		dev_info_t *disk = conf->disks + i;
++	i = 0;
++	for (curr_offset = 0;
++	     curr_offset < mddev->array_size;
++	     curr_offset += conf->hash_spacing) {
+ 
+-		disk->offset = curr_offset;
+-		curr_offset += disk->size;
++		while (i < mddev->raid_disks-1 &&
++		       curr_offset >= conf->disks[i+1].offset)
++			i++;
+ 
+-		/* 'curr_offset' is the end of this disk
+-		 * 'start' is the start of table
++		*table ++ = conf->disks + i;
++	}
++
++	if (conf->preshift) {
++		conf->hash_spacing >>= conf->preshift;
++		/* round hash_spacing up so that when we divide by it,
++		 * we err on the side of "too-low", which is safest.
+ 		 */
+-		while (start < curr_offset) {
+-			*table++ = disk;
+-			start += conf->smallest->size;
+-		}
++		conf->hash_spacing++;
+ 	}
+-	if (table-conf->hash_table != nb_zone)
+-		BUG();
++
++	BUG_ON(table - conf->hash_table > nb_zone);
+ 
+ 	blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec);
+ 	mddev->queue->unplug_fn = linear_unplug;
+@@ -299,7 +336,7 @@ static void linear_status (struct seq_file *seq, mddev_t *mddev)
+ 	sector_t s = 0;
+   
+ 	seq_printf(seq, "      ");
+-	for (j = 0; j < conf->nr_zones; j++)
++	for (j = 0; j < mddev->raid_disks; j++)
+ 	{
+ 		char b[BDEVNAME_SIZE];
+ 		s += conf->smallest_size;
+diff --git a/include/linux/raid/linear.h b/include/linux/raid/linear.h
+index e04c4fe45b53..7eaf290e10e7 100644
+--- a/include/linux/raid/linear.h
++++ b/include/linux/raid/linear.h
+@@ -14,8 +14,8 @@ typedef struct dev_info dev_info_t;
+ struct linear_private_data
+ {
+ 	dev_info_t		**hash_table;
+-	dev_info_t		*smallest;
+-	int			nr_zones;
++	sector_t		hash_spacing;
++	int			preshift; /* shift before dividing by hash_spacing */
+ 	dev_info_t		disks[0];
+ };
+ 

commit 4b6d287f627b5fb6a49f78f9e81649ff98c62bb7
+Author: NeilBrown 
+Date:   Fri Sep 9 16:23:47 2005 -0700
+
+    [PATCH] md: add write-behind support for md/raid1
+    
+    If a device is flagged 'WriteMostly' and the array has a bitmap, and the
+    bitmap superblock indicates that write_behind is allowed, then write_behind is
+    enabled for WriteMostly devices.
+    
+    Write requests will be acknowledges as complete to the caller (via b_end_io)
+    when all non-WriteMostly devices have completed the write, but will not be
+    cleared from the bitmap until all devices complete.
+    
+    This requires memory allocation to make a local copy of the data being
+    written.  If there is insufficient memory, then we fall-back on normal write
+    semantics.
+    
+    Signed-Off-By: Paul Clements 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
+index 2925219f0881..2c84de2b4ad5 100644
+--- a/drivers/md/bitmap.c
++++ b/drivers/md/bitmap.c
+@@ -437,6 +437,7 @@ void bitmap_print_sb(struct bitmap *bitmap)
+ 	printk(KERN_DEBUG "  daemon sleep: %ds\n", le32_to_cpu(sb->daemon_sleep));
+ 	printk(KERN_DEBUG "     sync size: %llu KB\n",
+ 			(unsigned long long)le64_to_cpu(sb->sync_size)/2);
++	printk(KERN_DEBUG "max write behind: %d\n", le32_to_cpu(sb->write_behind));
+ 	kunmap(bitmap->sb_page);
+ }
+ 
+@@ -445,7 +446,7 @@ static int bitmap_read_sb(struct bitmap *bitmap)
+ {
+ 	char *reason = NULL;
+ 	bitmap_super_t *sb;
+-	unsigned long chunksize, daemon_sleep;
++	unsigned long chunksize, daemon_sleep, write_behind;
+ 	unsigned long bytes_read;
+ 	unsigned long long events;
+ 	int err = -EINVAL;
+@@ -474,6 +475,7 @@ static int bitmap_read_sb(struct bitmap *bitmap)
+ 
+ 	chunksize = le32_to_cpu(sb->chunksize);
+ 	daemon_sleep = le32_to_cpu(sb->daemon_sleep);
++	write_behind = le32_to_cpu(sb->write_behind);
+ 
+ 	/* verify that the bitmap-specific fields are valid */
+ 	if (sb->magic != cpu_to_le32(BITMAP_MAGIC))
+@@ -485,7 +487,9 @@ static int bitmap_read_sb(struct bitmap *bitmap)
+ 	else if ((1 << ffz(~chunksize)) != chunksize)
+ 		reason = "bitmap chunksize not a power of 2";
+ 	else if (daemon_sleep < 1 || daemon_sleep > 15)
+-		reason = "daemon sleep period out of range";
++		reason = "daemon sleep period out of range (1-15s)";
++	else if (write_behind > COUNTER_MAX)
++		reason = "write-behind limit out of range (0 - 16383)";
+ 	if (reason) {
+ 		printk(KERN_INFO "%s: invalid bitmap file superblock: %s\n",
+ 			bmname(bitmap), reason);
+@@ -518,6 +522,7 @@ static int bitmap_read_sb(struct bitmap *bitmap)
+ 	/* assign fields using values from superblock */
+ 	bitmap->chunksize = chunksize;
+ 	bitmap->daemon_sleep = daemon_sleep;
++	bitmap->max_write_behind = write_behind;
+ 	bitmap->flags |= sb->state;
+ 	bitmap->events_cleared = le64_to_cpu(sb->events_cleared);
+ 	if (sb->state & BITMAP_STALE)
+@@ -1282,9 +1287,16 @@ static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
+ 	}
+ }
+ 
+-int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors)
++int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors, int behind)
+ {
+ 	if (!bitmap) return 0;
++
++	if (behind) {
++		atomic_inc(&bitmap->behind_writes);
++		PRINTK(KERN_DEBUG "inc write-behind count %d/%d\n",
++		  atomic_read(&bitmap->behind_writes), bitmap->max_write_behind);
++	}
++
+ 	while (sectors) {
+ 		int blocks;
+ 		bitmap_counter_t *bmc;
+@@ -1319,9 +1331,15 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
+ }
+ 
+ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors,
+-		     int success)
++		     int success, int behind)
+ {
+ 	if (!bitmap) return;
++	if (behind) {
++		atomic_dec(&bitmap->behind_writes);
++		PRINTK(KERN_DEBUG "dec write-behind count %d/%d\n",
++		  atomic_read(&bitmap->behind_writes), bitmap->max_write_behind);
++	}
++
+ 	while (sectors) {
+ 		int blocks;
+ 		unsigned long flags;
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index 28839a8193f2..ba7f5f256161 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -222,8 +222,17 @@ static void raid_end_bio_io(r1bio_t *r1_bio)
+ {
+ 	struct bio *bio = r1_bio->master_bio;
+ 
+-	bio_endio(bio, bio->bi_size,
+-		test_bit(R1BIO_Uptodate, &r1_bio->state) ? 0 : -EIO);
++	/* if nobody has done the final endio yet, do it now */
++	if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) {
++		PRINTK(KERN_DEBUG "raid1: sync end %s on sectors %llu-%llu\n",
++			(bio_data_dir(bio) == WRITE) ? "write" : "read",
++			(unsigned long long) bio->bi_sector,
++			(unsigned long long) bio->bi_sector +
++				(bio->bi_size >> 9) - 1);
++
++		bio_endio(bio, bio->bi_size,
++			test_bit(R1BIO_Uptodate, &r1_bio->state) ? 0 : -EIO);
++	}
+ 	free_r1bio(r1_bio);
+ }
+ 
+@@ -292,7 +301,7 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
+ {
+ 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
+ 	r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private);
+-	int mirror;
++	int mirror, behind;
+ 	conf_t *conf = mddev_to_conf(r1_bio->mddev);
+ 
+ 	if (bio->bi_size)
+@@ -323,16 +332,46 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
+ 
+ 	update_head_pos(mirror, r1_bio);
+ 
++	behind = test_bit(R1BIO_BehindIO, &r1_bio->state);
++	if (behind) {
++		if (test_bit(WriteMostly, &conf->mirrors[mirror].rdev->flags))
++			atomic_dec(&r1_bio->behind_remaining);
++
++		/* In behind mode, we ACK the master bio once the I/O has safely
++		 * reached all non-writemostly disks. Setting the Returned bit
++		 * ensures that this gets done only once -- we don't ever want to
++		 * return -EIO here, instead we'll wait */
++
++		if (atomic_read(&r1_bio->behind_remaining) >= (atomic_read(&r1_bio->remaining)-1) &&
++		    test_bit(R1BIO_Uptodate, &r1_bio->state)) {
++			/* Maybe we can return now */
++			if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) {
++				struct bio *mbio = r1_bio->master_bio;
++				PRINTK(KERN_DEBUG "raid1: behind end write sectors %llu-%llu\n",
++				       (unsigned long long) mbio->bi_sector,
++				       (unsigned long long) mbio->bi_sector +
++				       (mbio->bi_size >> 9) - 1);
++				bio_endio(mbio, mbio->bi_size, 0);
++			}
++		}
++	}
+ 	/*
+ 	 *
+ 	 * Let's see if all mirrored write operations have finished
+ 	 * already.
+ 	 */
+ 	if (atomic_dec_and_test(&r1_bio->remaining)) {
++		if (test_bit(R1BIO_BehindIO, &r1_bio->state)) {
++			/* free extra copy of the data pages */
++			int i = bio->bi_vcnt;
++			while (i--)
++				__free_page(bio->bi_io_vec[i].bv_page);
++		}
+ 		/* clear the bitmap if all writes complete successfully */
+ 		bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector,
+ 				r1_bio->sectors,
+-				!test_bit(R1BIO_Degraded, &r1_bio->state));
++				!test_bit(R1BIO_Degraded, &r1_bio->state),
++				behind);
+ 		md_write_end(r1_bio->mddev);
+ 		raid_end_bio_io(r1_bio);
+ 	}
+@@ -562,6 +601,39 @@ static void device_barrier(conf_t *conf, sector_t sect)
+ 	spin_unlock_irq(&conf->resync_lock);
+ }
+ 
++/* duplicate the data pages for behind I/O */
++static struct page **alloc_behind_pages(struct bio *bio)
++{
++	int i;
++	struct bio_vec *bvec;
++	struct page **pages = kmalloc(bio->bi_vcnt * sizeof(struct page *),
++					GFP_NOIO);
++	if (unlikely(!pages))
++		goto do_sync_io;
++
++	memset(pages, 0, bio->bi_vcnt * sizeof(struct page *));
++
++	bio_for_each_segment(bvec, bio, i) {
++		pages[i] = alloc_page(GFP_NOIO);
++		if (unlikely(!pages[i]))
++			goto do_sync_io;
++		memcpy(kmap(pages[i]) + bvec->bv_offset,
++			kmap(bvec->bv_page) + bvec->bv_offset, bvec->bv_len);
++		kunmap(pages[i]);
++		kunmap(bvec->bv_page);
++	}
++
++	return pages;
++
++do_sync_io:
++	if (pages)
++		for (i = 0; i < bio->bi_vcnt && pages[i]; i++)
++			__free_page(pages[i]);
++	kfree(pages);
++	PRINTK("%dB behind alloc failed, doing sync I/O\n", bio->bi_size);
++	return NULL;
++}
++
+ static int make_request(request_queue_t *q, struct bio * bio)
+ {
+ 	mddev_t *mddev = q->queuedata;
+@@ -574,6 +646,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
+ 	struct bitmap *bitmap = mddev->bitmap;
+ 	unsigned long flags;
+ 	struct bio_list bl;
++	struct page **behind_pages = NULL;
+ 
+ 	if (unlikely(bio_barrier(bio))) {
+ 		bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
+@@ -613,8 +686,6 @@ static int make_request(request_queue_t *q, struct bio * bio)
+ 	r1_bio->mddev = mddev;
+ 	r1_bio->sector = bio->bi_sector;
+ 
+-	r1_bio->state = 0;
+-
+ 	if (bio_data_dir(bio) == READ) {
+ 		/*
+ 		 * read balancing logic:
+@@ -675,13 +746,22 @@ static int make_request(request_queue_t *q, struct bio * bio)
+ 	}
+ 	rcu_read_unlock();
+ 
++	BUG_ON(targets == 0); /* we never fail the last device */
++
+ 	if (targets < conf->raid_disks) {
+ 		/* array is degraded, we will not clear the bitmap
+ 		 * on I/O completion (see raid1_end_write_request) */
+ 		set_bit(R1BIO_Degraded, &r1_bio->state);
+ 	}
+ 
++	/* do behind I/O ? */
++	if (bitmap &&
++	    atomic_read(&bitmap->behind_writes) < bitmap->max_write_behind &&
++	    (behind_pages = alloc_behind_pages(bio)) != NULL)
++		set_bit(R1BIO_BehindIO, &r1_bio->state);
++
+ 	atomic_set(&r1_bio->remaining, 0);
++	atomic_set(&r1_bio->behind_remaining, 0);
+ 
+ 	bio_list_init(&bl);
+ 	for (i = 0; i < disks; i++) {
+@@ -698,12 +778,31 @@ static int make_request(request_queue_t *q, struct bio * bio)
+ 		mbio->bi_rw = WRITE;
+ 		mbio->bi_private = r1_bio;
+ 
++		if (behind_pages) {
++			struct bio_vec *bvec;
++			int j;
++
++			/* Yes, I really want the '__' version so that
++			 * we clear any unused pointer in the io_vec, rather
++			 * than leave them unchanged.  This is important
++			 * because when we come to free the pages, we won't
++			 * know the originial bi_idx, so we just free
++			 * them all
++			 */
++			__bio_for_each_segment(bvec, mbio, j, 0)
++				bvec->bv_page = behind_pages[j];
++			if (test_bit(WriteMostly, &conf->mirrors[i].rdev->flags))
++				atomic_inc(&r1_bio->behind_remaining);
++		}
++
+ 		atomic_inc(&r1_bio->remaining);
+ 
+ 		bio_list_add(&bl, mbio);
+ 	}
++	kfree(behind_pages); /* the behind pages are attached to the bios now */
+ 
+-	bitmap_startwrite(bitmap, bio->bi_sector, r1_bio->sectors);
++	bitmap_startwrite(bitmap, bio->bi_sector, r1_bio->sectors,
++				test_bit(R1BIO_BehindIO, &r1_bio->state));
+ 	spin_lock_irqsave(&conf->device_lock, flags);
+ 	bio_list_merge(&conf->pending_bio_list, &bl);
+ 	bio_list_init(&bl);
+@@ -1471,6 +1570,17 @@ static int run(mddev_t *mddev)
+ static int stop(mddev_t *mddev)
+ {
+ 	conf_t *conf = mddev_to_conf(mddev);
++	struct bitmap *bitmap = mddev->bitmap;
++	int behind_wait = 0;
++
++	/* wait for behind writes to complete */
++	while (bitmap && atomic_read(&bitmap->behind_writes) > 0) {
++		behind_wait++;
++		printk(KERN_INFO "raid1: behind writes in progress on device %s, waiting to stop (%d)\n", mdname(mddev), behind_wait);
++		set_current_state(TASK_UNINTERRUPTIBLE);
++		schedule_timeout(HZ); /* wait a second */
++		/* need to kick something here to make sure I/O goes? */
++	}
+ 
+ 	md_unregister_thread(mddev->thread);
+ 	mddev->thread = NULL;
+diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h
+index 4bf1659f8aa8..9de99198caf1 100644
+--- a/include/linux/raid/bitmap.h
++++ b/include/linux/raid/bitmap.h
+@@ -7,7 +7,7 @@
+ #define BITMAP_H 1
+ 
+ #define BITMAP_MAJOR 3
+-#define BITMAP_MINOR 38
++#define BITMAP_MINOR 39
+ 
+ /*
+  * in-memory bitmap:
+@@ -147,8 +147,9 @@ typedef struct bitmap_super_s {
+ 	__u32 state;        /* 48  bitmap state information */
+ 	__u32 chunksize;    /* 52  the bitmap chunk size in bytes */
+ 	__u32 daemon_sleep; /* 56  seconds between disk flushes */
++	__u32 write_behind; /* 60  number of outstanding write-behind writes */
+ 
+-	__u8  pad[256 - 60]; /* set to zero */
++	__u8  pad[256 - 64]; /* set to zero */
+ } bitmap_super_t;
+ 
+ /* notes:
+@@ -226,6 +227,9 @@ struct bitmap {
+ 
+ 	unsigned long flags;
+ 
++	unsigned long max_write_behind; /* write-behind mode */
++	atomic_t behind_writes;
++
+ 	/*
+ 	 * the bitmap daemon - periodically wakes up and sweeps the bitmap
+ 	 * file, cleaning up bits and flushing out pages to disk as necessary
+@@ -260,9 +264,10 @@ int  bitmap_setallbits(struct bitmap *bitmap);
+ void bitmap_write_all(struct bitmap *bitmap);
+ 
+ /* these are exported */
+-int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors);
+-void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors,
+-		     int success);
++int bitmap_startwrite(struct bitmap *bitmap, sector_t offset,
++			unsigned long sectors, int behind);
++void bitmap_endwrite(struct bitmap *bitmap, sector_t offset,
++			unsigned long sectors, int success, int behind);
+ int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int degraded);
+ void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int aborted);
+ void bitmap_close_sync(struct bitmap *bitmap);
+diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
+index 7ef78e15ce04..2514e5fcda7f 100644
+--- a/include/linux/raid/md_k.h
++++ b/include/linux/raid/md_k.h
+@@ -275,6 +275,9 @@ struct mddev_s
+ 	atomic_t			writes_pending; 
+ 	request_queue_t			*queue;	/* for plugging ... */
+ 
++	atomic_t                        write_behind; /* outstanding async IO */
++	unsigned int                    max_write_behind; /* 0 = sync */
++
+ 	struct bitmap                   *bitmap; /* the bitmap for the device */
+ 	struct file			*bitmap_file; /* the bitmap file */
+ 	long				bitmap_offset; /* offset from superblock of
+diff --git a/include/linux/raid/raid1.h b/include/linux/raid/raid1.h
+index 9d93cf12e890..60e19b667548 100644
+--- a/include/linux/raid/raid1.h
++++ b/include/linux/raid/raid1.h
+@@ -80,6 +80,9 @@ struct r1bio_s {
+ 	atomic_t		remaining; /* 'have we finished' count,
+ 					    * used from IRQ handlers
+ 					    */
++	atomic_t		behind_remaining; /* number of write-behind ios remaining
++						 * in this BehindIO request
++						 */
+ 	sector_t		sector;
+ 	int			sectors;
+ 	unsigned long		state;
+@@ -107,4 +110,14 @@ struct r1bio_s {
+ #define	R1BIO_Uptodate	0
+ #define	R1BIO_IsSync	1
+ #define	R1BIO_Degraded	2
++#define	R1BIO_BehindIO   3
++/* For write-behind requests, we call bi_end_io when
++ * the last non-write-behind device completes, providing
++ * any write was successful.  Otherwise we call when
++ * any write-behind write succeeds, otherwise we call
++ * with failure when last write completes (and all failed).
++ * Record that bi_end_io was called with this flag...
++ */
++#define	R1BIO_Returned 4
++
+ #endif

commit 8ddf9efe6708f3674f0ddfeb6425fd27bea109a2
+Author: NeilBrown 
+Date:   Fri Sep 9 16:23:45 2005 -0700
+
+    [PATCH] md: support write-mostly device in raid1
+    
+    This allows a device in a raid1 to be marked as "write mostly".  Read requests
+    will only be sent if there is no other option.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index ae654466dc23..f1ac356e656d 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -670,6 +670,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+ 
+ 	if (mddev->level != LEVEL_MULTIPATH) {
+ 		rdev->faulty = 0;
++		rdev->flags = 0;
+ 		desc = sb->disks + rdev->desc_nr;
+ 
+ 		if (desc->state & (1<in_sync = 1;
+ 			rdev->raid_disk = desc->raid_disk;
+ 		}
++		if (desc->state & (1<flags);
+ 	} else /* MULTIPATH are always insync */
+ 		rdev->in_sync = 1;
+ 	return 0;
+@@ -777,6 +780,8 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
+ 			spare++;
+ 			working++;
+ 		}
++		if (test_bit(WriteMostly, &rdev2->flags))
++			d->state |= (1<raid_disk = role;
+ 			break;
+ 		}
++		rdev->flags = 0;
++		if (sb->devflags & WriteMostly1)
++			set_bit(WriteMostly, &rdev->flags);
+ 	} else /* MULTIPATH are always insync */
+ 		rdev->in_sync = 1;
+ 
+@@ -2152,6 +2160,8 @@ static int get_disk_info(mddev_t * mddev, void __user * arg)
+ 			info.state |= (1<flags))
++			info.state |= (1<saved_raid_disk = rdev->raid_disk;
+ 
+ 		rdev->in_sync = 0; /* just to be sure */
++		if (info->state & (1<flags);
++
+ 		rdev->raid_disk = -1;
+ 		err = bind_rdev_to_array(rdev, mddev);
+ 		if (err)
+@@ -2277,6 +2290,9 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
+ 		else
+ 			rdev->in_sync = 0;
+ 
++		if (info->state & (1<flags);
++
+ 		err = bind_rdev_to_array(rdev, mddev);
+ 		if (err) {
+ 			export_rdev(rdev);
+@@ -3329,6 +3345,8 @@ static int md_seq_show(struct seq_file *seq, void *v)
+ 			char b[BDEVNAME_SIZE];
+ 			seq_printf(seq, " %s[%d]",
+ 				bdevname(rdev->bdev,b), rdev->desc_nr);
++			if (test_bit(WriteMostly, &rdev->flags))
++				seq_printf(seq, "(W)");
+ 			if (rdev->faulty) {
+ 				seq_printf(seq, "(F)");
+ 				continue;
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index ba643e4bfac9..28839a8193f2 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -360,13 +360,14 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
+ {
+ 	const unsigned long this_sector = r1_bio->sector;
+ 	int new_disk = conf->last_used, disk = new_disk;
++	int wonly_disk = -1;
+ 	const int sectors = r1_bio->sectors;
+ 	sector_t new_distance, current_distance;
+-	mdk_rdev_t *new_rdev, *rdev;
++	mdk_rdev_t *rdev;
+ 
+ 	rcu_read_lock();
+ 	/*
+-	 * Check if it if we can balance. We can balance on the whole
++	 * Check if we can balance. We can balance on the whole
+ 	 * device if no resync is going on, or below the resync window.
+ 	 * We take the first readable disk when above the resync window.
+ 	 */
+@@ -376,11 +377,16 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
+ 		/* Choose the first operation device, for consistancy */
+ 		new_disk = 0;
+ 
+-		while ((new_rdev=conf->mirrors[new_disk].rdev) == NULL ||
+-		       !new_rdev->in_sync) {
+-			new_disk++;
+-			if (new_disk == conf->raid_disks) {
+-				new_disk = -1;
++		for (rdev = conf->mirrors[new_disk].rdev;
++		     !rdev || !rdev->in_sync
++			     || test_bit(WriteMostly, &rdev->flags);
++		     rdev = conf->mirrors[++new_disk].rdev) {
++
++			if (rdev && rdev->in_sync)
++				wonly_disk = new_disk;
++
++			if (new_disk == conf->raid_disks - 1) {
++				new_disk = wonly_disk;
+ 				break;
+ 			}
+ 		}
+@@ -389,16 +395,26 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
+ 
+ 
+ 	/* make sure the disk is operational */
+-	while ((new_rdev=conf->mirrors[new_disk].rdev) == NULL ||
+-	       !new_rdev->in_sync) {
++	for (rdev = conf->mirrors[new_disk].rdev;
++	     !rdev || !rdev->in_sync ||
++		     test_bit(WriteMostly, &rdev->flags);
++	     rdev = conf->mirrors[new_disk].rdev) {
++
++		if (rdev && rdev->in_sync)
++			wonly_disk = new_disk;
++
+ 		if (new_disk <= 0)
+ 			new_disk = conf->raid_disks;
+ 		new_disk--;
+ 		if (new_disk == disk) {
+-			new_disk = -1;
+-			goto rb_out;
++			new_disk = wonly_disk;
++			break;
+ 		}
+ 	}
++
++	if (new_disk < 0)
++		goto rb_out;
++
+ 	disk = new_disk;
+ 	/* now disk == new_disk == starting point for search */
+ 
+@@ -419,37 +435,41 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
+ 			disk = conf->raid_disks;
+ 		disk--;
+ 
+-		if ((rdev=conf->mirrors[disk].rdev) == NULL ||
+-		    !rdev->in_sync)
++		rdev = conf->mirrors[disk].rdev;
++
++		if (!rdev ||
++		    !rdev->in_sync ||
++		    test_bit(WriteMostly, &rdev->flags))
+ 			continue;
+ 
+ 		if (!atomic_read(&rdev->nr_pending)) {
+ 			new_disk = disk;
+-			new_rdev = rdev;
+ 			break;
+ 		}
+ 		new_distance = abs(this_sector - conf->mirrors[disk].head_position);
+ 		if (new_distance < current_distance) {
+ 			current_distance = new_distance;
+ 			new_disk = disk;
+-			new_rdev = rdev;
+ 		}
+ 	} while (disk != conf->last_used);
+ 
+-rb_out:
++ rb_out:
+ 
+ 
+ 	if (new_disk >= 0) {
+-		conf->next_seq_sect = this_sector + sectors;
+-		conf->last_used = new_disk;
+-		atomic_inc(&new_rdev->nr_pending);
+-		if (!new_rdev->in_sync) {
++		rdev = conf->mirrors[new_disk].rdev;
++		if (!rdev)
++			goto retry;
++		atomic_inc(&rdev->nr_pending);
++		if (!rdev->in_sync) {
+ 			/* cannot risk returning a device that failed
+ 			 * before we inc'ed nr_pending
+ 			 */
+-			atomic_dec(&new_rdev->nr_pending);
++			atomic_dec(&rdev->nr_pending);
+ 			goto retry;
+ 		}
++		conf->next_seq_sect = this_sector + sectors;
++		conf->last_used = new_disk;
+ 	}
+ 	rcu_read_unlock();
+ 
+@@ -1109,6 +1129,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
+ 	sector_t max_sector, nr_sectors;
+ 	int disk;
+ 	int i;
++	int wonly;
+ 	int write_targets = 0;
+ 	int sync_blocks;
+ 	int still_degraded = 0;
+@@ -1164,14 +1185,21 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
+ 	 */
+ 	disk = conf->last_used;
+ 	/* make sure disk is operational */
+-
++	wonly = disk;
+ 	while (conf->mirrors[disk].rdev == NULL ||
+-	       !conf->mirrors[disk].rdev->in_sync) {
++	       !conf->mirrors[disk].rdev->in_sync ||
++	       test_bit(WriteMostly, &conf->mirrors[disk].rdev->flags)
++		) {
++		if (conf->mirrors[disk].rdev  &&
++		    conf->mirrors[disk].rdev->in_sync)
++			wonly = disk;
+ 		if (disk <= 0)
+ 			disk = conf->raid_disks;
+ 		disk--;
+-		if (disk == conf->last_used)
++		if (disk == conf->last_used) {
++			disk = wonly;
+ 			break;
++		}
+ 	}
+ 	conf->last_used = disk;
+ 	atomic_inc(&conf->mirrors[disk].rdev->nr_pending);
+diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
+index 817062bf7352..7ef78e15ce04 100644
+--- a/include/linux/raid/md_k.h
++++ b/include/linux/raid/md_k.h
+@@ -181,6 +181,9 @@ struct mdk_rdev_s
+ 	int faulty;			/* if faulty do not issue IO requests */
+ 	int in_sync;			/* device is a full member of the array */
+ 
++	unsigned long	flags;		/* Should include faulty and in_sync here. */
++#define	WriteMostly	4		/* Avoid reading if at all possible */
++
+ 	int desc_nr;			/* descriptor index in the superblock */
+ 	int raid_disk;			/* role of device in array */
+ 	int saved_raid_disk;		/* role that device used to have in the
+diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h
+index dc65cd435494..4f047f84fb1f 100644
+--- a/include/linux/raid/md_p.h
++++ b/include/linux/raid/md_p.h
+@@ -79,6 +79,11 @@
+ #define MD_DISK_SYNC		2 /* disk is in sync with the raid set */
+ #define MD_DISK_REMOVED		3 /* disk is in sync with the raid set */
+ 
++#define	MD_DISK_WRITEMOSTLY	9 /* disk is "write-mostly" is RAID1 config.
++				   * read requests will only be sent here in
++				   * dire need
++				   */
++
+ typedef struct mdp_device_descriptor_s {
+ 	__u32 number;		/* 0 Device number in the entire set	      */
+ 	__u32 major;		/* 1 Device major number		      */
+@@ -193,7 +198,7 @@ struct mdp_superblock_1 {
+ 
+ 	__u64	ctime;		/* lo 40 bits are seconds, top 24 are microseconds or 0*/
+ 	__u32	level;		/* -4 (multipath), -1 (linear), 0,1,4,5 */
+-	__u32	layout;		/* only for raid5 currently */
++	__u32	layout;		/* only for raid5 and raid10 currently */
+ 	__u64	size;		/* used size of component devices, in 512byte sectors */
+ 
+ 	__u32	chunksize;	/* in 512byte sectors */
+@@ -212,7 +217,9 @@ struct mdp_superblock_1 {
+ 	__u32	dev_number;	/* permanent identifier of this  device - not role in raid */
+ 	__u32	cnt_corrected_read; /* number of read errors that were corrected by re-writing */
+ 	__u8	device_uuid[16]; /* user-space setable, ignored by kernel */
+-	__u8	pad2[64-56];	/* set to 0 when writing */
++	__u8	devflags;	/* per-device flags.  Only one defined...*/
++#define	WriteMostly1	1	/* mask for writemostly flag in above */
++	__u8	pad2[64-57];	/* set to 0 when writing */
+ 
+ 	/* array state information - 64 bytes */
+ 	__u64	utime;		/* 40 bits second, 24 btes microseconds */

commit 36fa30636fb84b209210299684e1be66d9e58217
+Author: NeilBrown 
+Date:   Fri Sep 9 16:23:45 2005 -0700
+
+    [PATCH] md: all hot-add and hot-remove of md intent logging bitmaps
+    
+    Both file-bitmaps and superblock bitmaps are supported.
+    
+    If you add a bitmap file on the array device, you lose.
+    
+    This introduces a 'default_bitmap_offset' field in mddev, as the ioctl used
+    for adding a superblock bitmap doesn't have room for giving an offset.  Later,
+    this value will be setable via sysfs.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 63c566165189..ae654466dc23 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -623,6 +623,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+ 		mddev->size = sb->size;
+ 		mddev->events = md_event(sb);
+ 		mddev->bitmap_offset = 0;
++		mddev->default_bitmap_offset = MD_SB_BYTES >> 9;
+ 
+ 		if (sb->state & (1<recovery_cp = MaxSector;
+@@ -648,7 +649,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+ 				printk(KERN_WARNING "md: bitmaps only support for raid1\n");
+ 				return -EINVAL;
+ 			}
+-			mddev->bitmap_offset = (MD_SB_BYTES >> 9);
++			mddev->bitmap_offset = mddev->default_bitmap_offset;
+ 		}
+ 
+ 	} else if (mddev->pers == NULL) {
+@@ -939,6 +940,9 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+ 		mddev->size = le64_to_cpu(sb->size)/2;
+ 		mddev->events = le64_to_cpu(sb->events);
+ 		mddev->bitmap_offset = 0;
++		mddev->default_bitmap_offset = 0;
++		if (mddev->minor_version == 0)
++			mddev->default_bitmap_offset = -(64*1024)/512;
+ 		
+ 		mddev->recovery_cp = le64_to_cpu(sb->resync_offset);
+ 		memcpy(mddev->uuid, sb->set_uuid, 16);
+@@ -2073,6 +2077,8 @@ static int get_array_info(mddev_t * mddev, void __user * arg)
+ 	info.state         = 0;
+ 	if (mddev->in_sync)
+ 		info.state = (1<bitmap && mddev->bitmap_offset)
++		info.state = (1<pers || mddev->bitmap_file)
+-		return -EBUSY;
++	if (mddev->pers) {
++		if (!mddev->pers->quiesce)
++			return -EBUSY;
++		if (mddev->recovery || mddev->sync_thread)
++			return -EBUSY;
++		/* we should be able to change the bitmap.. */
++	}
+ 
+-	mddev->bitmap_file = fget(fd);
+ 
+-	if (mddev->bitmap_file == NULL) {
+-		printk(KERN_ERR "%s: error: failed to get bitmap file\n",
+-			mdname(mddev));
+-		return -EBADF;
+-	}
++	if (fd >= 0) {
++		if (mddev->bitmap)
++			return -EEXIST; /* cannot add when bitmap is present */
++		mddev->bitmap_file = fget(fd);
+ 
+-	err = deny_bitmap_write_access(mddev->bitmap_file);
+-	if (err) {
+-		printk(KERN_ERR "%s: error: bitmap file is already in use\n",
+-			mdname(mddev));
+-		fput(mddev->bitmap_file);
+-		mddev->bitmap_file = NULL;
+-	} else
++		if (mddev->bitmap_file == NULL) {
++			printk(KERN_ERR "%s: error: failed to get bitmap file\n",
++			       mdname(mddev));
++			return -EBADF;
++		}
++
++		err = deny_bitmap_write_access(mddev->bitmap_file);
++		if (err) {
++			printk(KERN_ERR "%s: error: bitmap file is already in use\n",
++			       mdname(mddev));
++			fput(mddev->bitmap_file);
++			mddev->bitmap_file = NULL;
++			return err;
++		}
+ 		mddev->bitmap_offset = 0; /* file overrides offset */
++	} else if (mddev->bitmap == NULL)
++		return -ENOENT; /* cannot remove what isn't there */
++	err = 0;
++	if (mddev->pers) {
++		mddev->pers->quiesce(mddev, 1);
++		if (fd >= 0)
++			err = bitmap_create(mddev);
++		if (fd < 0 || err)
++			bitmap_destroy(mddev);
++		mddev->pers->quiesce(mddev, 0);
++	} else if (fd < 0) {
++		if (mddev->bitmap_file)
++			fput(mddev->bitmap_file);
++		mddev->bitmap_file = NULL;
++	}
++
+ 	return err;
+ }
+ 
+@@ -2528,6 +2560,11 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
+ {
+ 	int rv = 0;
+ 	int cnt = 0;
++	int state = 0;
++
++	/* calculate expected state,ignoring low bits */
++	if (mddev->bitmap && mddev->bitmap_offset)
++		state |= (1 << MD_SB_BITMAP_PRESENT);
+ 
+ 	if (mddev->major_version != info->major_version ||
+ 	    mddev->minor_version != info->minor_version ||
+@@ -2536,12 +2573,16 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
+ 	    mddev->level         != info->level         ||
+ /*	    mddev->layout        != info->layout        || */
+ 	    !mddev->persistent	 != info->not_persistent||
+-	    mddev->chunk_size    != info->chunk_size    )
++	    mddev->chunk_size    != info->chunk_size    ||
++	    /* ignore bottom 8 bits of state, and allow SB_BITMAP_PRESENT to change */
++	    ((state^info->state) & 0xfffffe00)
++		)
+ 		return -EINVAL;
+ 	/* Check there is only one change */
+ 	if (mddev->size != info->size) cnt++;
+ 	if (mddev->raid_disks != info->raid_disks) cnt++;
+ 	if (mddev->layout != info->layout) cnt++;
++	if ((state ^ info->state) & (1< 1) return -EINVAL;
+ 
+@@ -2620,6 +2661,35 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
+ 			}
+ 		}
+ 	}
++	if ((state ^ info->state) & (1<pers->quiesce == NULL)
++			return -EINVAL;
++		if (mddev->recovery || mddev->sync_thread)
++			return -EBUSY;
++		if (info->state & (1<bitmap)
++				return -EEXIST;
++			if (mddev->default_bitmap_offset == 0)
++				return -EINVAL;
++			mddev->bitmap_offset = mddev->default_bitmap_offset;
++			mddev->pers->quiesce(mddev, 1);
++			rv = bitmap_create(mddev);
++			if (rv)
++				bitmap_destroy(mddev);
++			mddev->pers->quiesce(mddev, 0);
++		} else {
++			/* remove the bitmap */
++			if (!mddev->bitmap)
++				return -ENOENT;
++			if (mddev->bitmap->file)
++				return -EINVAL;
++			mddev->pers->quiesce(mddev, 1);
++			bitmap_destroy(mddev);
++			mddev->pers->quiesce(mddev, 0);
++			mddev->bitmap_offset = 0;
++		}
++	}
+ 	md_update_sb(mddev);
+ 	return rv;
+ }
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index ace41c571aeb..ba643e4bfac9 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -1565,6 +1565,35 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
+ 	return 0;
+ }
+ 
++void raid1_quiesce(mddev_t *mddev, int state)
++{
++	conf_t *conf = mddev_to_conf(mddev);
++
++	switch(state) {
++	case 0:
++		spin_lock_irq(&conf->resync_lock);
++		conf->barrier++;
++		wait_event_lock_irq(conf->wait_idle, !conf->nr_pending,
++				    conf->resync_lock, raid1_unplug(mddev->queue));
++		spin_unlock_irq(&conf->resync_lock);
++		break;
++	case 1:
++		spin_lock_irq(&conf->resync_lock);
++		conf->barrier--;
++		spin_unlock_irq(&conf->resync_lock);
++		wake_up(&conf->wait_resume);
++		wake_up(&conf->wait_idle);
++		break;
++	}
++	if (mddev->thread) {
++		if (mddev->bitmap)
++			mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
++		else
++			mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
++		md_wakeup_thread(mddev->thread);
++	}
++}
++
+ 
+ static mdk_personality_t raid1_personality =
+ {
+@@ -1581,6 +1610,7 @@ static mdk_personality_t raid1_personality =
+ 	.sync_request	= sync_request,
+ 	.resize		= raid1_resize,
+ 	.reshape	= raid1_reshape,
++	.quiesce	= raid1_quiesce,
+ };
+ 
+ static int __init raid_init(void)
+diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
+index 8c14ba565a45..817062bf7352 100644
+--- a/include/linux/raid/md_k.h
++++ b/include/linux/raid/md_k.h
+@@ -278,6 +278,10 @@ struct mddev_s
+ 							* start of bitmap. May be
+ 							* negative, but not '0'
+ 							*/
++	long				default_bitmap_offset; /* this is the offset to use when
++								* hot-adding a bitmap.  It should
++								* eventually be settable by sysfs.
++								*/
+ 
+ 	struct list_head		all_mddevs;
+ };
+@@ -314,6 +318,12 @@ struct mdk_personality_s
+ 	int (*resize) (mddev_t *mddev, sector_t sectors);
+ 	int (*reshape) (mddev_t *mddev, int raid_disks);
+ 	int (*reconfig) (mddev_t *mddev, int layout, int chunk_size);
++	/* quiesce moves between quiescence states
++	 * 0 - fully active
++	 * 1 - no new requests allowed
++	 * others - reserved
++	 */
++	void (*quiesce) (mddev_t *mddev, int state);
+ };
+ 
+ 

commit 6a07997fc34ac15a1c5dc650285d79b7604a2276
+Author: NeilBrown 
+Date:   Fri Sep 9 16:23:44 2005 -0700
+
+    [PATCH] md: improve handling of bitmap initialisation.
+    
+    When we find a 'stale' bitmap, possibly because it is new, we should just
+    assume every bit needs to be set, but rather base the setting of bits on the
+    current state of the array (degraded and recovery_cp).
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
+index 41df4cda66e2..2925219f0881 100644
+--- a/drivers/md/bitmap.c
++++ b/drivers/md/bitmap.c
+@@ -520,6 +520,8 @@ static int bitmap_read_sb(struct bitmap *bitmap)
+ 	bitmap->daemon_sleep = daemon_sleep;
+ 	bitmap->flags |= sb->state;
+ 	bitmap->events_cleared = le64_to_cpu(sb->events_cleared);
++	if (sb->state & BITMAP_STALE)
++		bitmap->events_cleared = bitmap->mddev->events;
+ 	err = 0;
+ out:
+ 	kunmap(bitmap->sb_page);
+@@ -818,7 +820,7 @@ int bitmap_unplug(struct bitmap *bitmap)
+ 	return 0;
+ }
+ 
+-static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset);
++static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed);
+ /* * bitmap_init_from_disk -- called at bitmap_create time to initialize
+  * the in-memory bitmap from the on-disk bitmap -- also, sets up the
+  * memory mapping of the bitmap file
+@@ -826,8 +828,11 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset);
+  *   if there's no bitmap file, or if the bitmap file had been
+  *   previously kicked from the array, we mark all the bits as
+  *   1's in order to cause a full resync.
++ *
++ * We ignore all bits for sectors that end earlier than 'start'.
++ * This is used when reading an out-of-date bitmap...
+  */
+-static int bitmap_init_from_disk(struct bitmap *bitmap)
++static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
+ {
+ 	unsigned long i, chunks, index, oldindex, bit;
+ 	struct page *page = NULL, *oldpage = NULL;
+@@ -914,7 +919,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap)
+ 			 	 * whole page and write it out
+ 				 */
+ 				memset(page_address(page) + offset, 0xff,
+-					PAGE_SIZE - offset);
++				       PAGE_SIZE - offset);
+ 				ret = write_page(bitmap, page, 1);
+ 				if (ret) {
+ 					kunmap(page);
+@@ -928,8 +933,11 @@ static int bitmap_init_from_disk(struct bitmap *bitmap)
+ 		}
+ 		if (test_bit(bit, page_address(page))) {
+ 			/* if the disk bit is set, set the memory bit */
+-			bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap));
++			bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap),
++					       ((i+1) << (CHUNK_BLOCK_SHIFT(bitmap)) >= start)
++				);
+ 			bit_cnt++;
++			set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
+ 		}
+ 	}
+ 
+@@ -1424,7 +1432,7 @@ void bitmap_close_sync(struct bitmap *bitmap)
+ 	}
+ }
+ 
+-static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset)
++static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed)
+ {
+ 	/* For each chunk covered by any of these sectors, set the
+ 	 * counter to 1 and set resync_needed.  They should all
+@@ -1441,7 +1449,7 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset)
+ 	}
+ 	if (! *bmc) {
+ 		struct page *page;
+-		*bmc = 1 | NEEDED_MASK;
++		*bmc = 1 | (needed?NEEDED_MASK:0);
+ 		bitmap_count_page(bitmap, offset, 1);
+ 		page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
+ 		set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
+@@ -1517,6 +1525,7 @@ int bitmap_create(mddev_t *mddev)
+ 	unsigned long pages;
+ 	struct file *file = mddev->bitmap_file;
+ 	int err;
++	sector_t start;
+ 
+ 	BUG_ON(sizeof(bitmap_super_t) != 256);
+ 
+@@ -1581,7 +1590,12 @@ int bitmap_create(mddev_t *mddev)
+ 
+ 	/* now that we have some pages available, initialize the in-memory
+ 	 * bitmap from the on-disk bitmap */
+-	err = bitmap_init_from_disk(bitmap);
++	start = 0;
++	if (mddev->degraded == 0
++	    || bitmap->events_cleared == mddev->events)
++		/* no need to keep dirty bits to optimise a re-add of a missing device */
++		start = mddev->recovery_cp;
++	err = bitmap_init_from_disk(bitmap, start);
+ 
+ 	if (err)
+ 		return err;

commit 1923b99a0f4748aa6be0b9b9523ce224a3449b17
+Author: NeilBrown 
+Date:   Fri Sep 9 16:23:43 2005 -0700
+
+    [PATCH] md: don't allow new md/bitmap file to be set if one already exists
+    
+    ... otherwise we loose a reference and can never free the file.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 373ab92e367b..63c566165189 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -2430,7 +2430,7 @@ static int set_bitmap_file(mddev_t *mddev, int fd)
+ {
+ 	int err;
+ 
+-	if (mddev->pers)
++	if (mddev->pers || mddev->bitmap_file)
+ 		return -EBUSY;
+ 
+ 	mddev->bitmap_file = fget(fd);

commit e5dcdd80a60627371f40797426273048630dc8ca
+Author: NeilBrown 
+Date:   Fri Sep 9 16:23:41 2005 -0700
+
+    [PATCH] md: fail IO request to md that require a barrier.
+    
+    md does not yet support BIO_RW_BARRIER, so be honest about it and fail
+    (-EOPNOTSUPP) any such requests.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/linear.c b/drivers/md/linear.c
+index 8d740013d74d..4991ba543368 100644
+--- a/drivers/md/linear.c
++++ b/drivers/md/linear.c
+@@ -238,6 +238,11 @@ static int linear_make_request (request_queue_t *q, struct bio *bio)
+ 	dev_info_t *tmp_dev;
+ 	sector_t block;
+ 
++	if (unlikely(bio_barrier(bio))) {
++		bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
++		return 0;
++	}
++
+ 	if (bio_data_dir(bio)==WRITE) {
+ 		disk_stat_inc(mddev->gendisk, writes);
+ 		disk_stat_add(mddev->gendisk, write_sectors, bio_sectors(bio));
+diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
+index 2d2ca7fa0265..286342375fb7 100644
+--- a/drivers/md/multipath.c
++++ b/drivers/md/multipath.c
+@@ -169,6 +169,11 @@ static int multipath_make_request (request_queue_t *q, struct bio * bio)
+ 	struct multipath_bh * mp_bh;
+ 	struct multipath_info *multipath;
+ 
++	if (unlikely(bio_barrier(bio))) {
++		bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
++		return 0;
++	}
++
+ 	mp_bh = mempool_alloc(conf->pool, GFP_NOIO);
+ 
+ 	mp_bh->master_bio = bio;
+diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
+index 2120710172c5..f6757259ce7f 100644
+--- a/drivers/md/raid0.c
++++ b/drivers/md/raid0.c
+@@ -404,6 +404,11 @@ static int raid0_make_request (request_queue_t *q, struct bio *bio)
+ 	unsigned long chunk;
+ 	sector_t block, rsect;
+ 
++	if (unlikely(bio_barrier(bio))) {
++		bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
++		return 0;
++	}
++
+ 	if (bio_data_dir(bio)==WRITE) {
+ 		disk_stat_inc(mddev->gendisk, writes);
+ 		disk_stat_add(mddev->gendisk, write_sectors, bio_sectors(bio));
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index 51d9645ed09c..ace41c571aeb 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -555,6 +555,10 @@ static int make_request(request_queue_t *q, struct bio * bio)
+ 	unsigned long flags;
+ 	struct bio_list bl;
+ 
++	if (unlikely(bio_barrier(bio))) {
++		bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
++		return 0;
++	}
+ 
+ 	/*
+ 	 * Register the new request and wait if the reconstruction
+diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
+index 7239079203ec..5e0b333793d5 100644
+--- a/drivers/md/raid10.c
++++ b/drivers/md/raid10.c
+@@ -669,6 +669,11 @@ static int make_request(request_queue_t *q, struct bio * bio)
+ 	int i;
+ 	int chunk_sects = conf->chunk_mask + 1;
+ 
++	if (unlikely(bio_barrier(bio))) {
++		bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
++		return 0;
++	}
++
+ 	/* If this request crosses a chunk boundary, we need to
+ 	 * split it.  This will only happen for 1 PAGE (or less) requests.
+ 	 */
+diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
+index 43f231a467d5..ed859e08d600 100644
+--- a/drivers/md/raid5.c
++++ b/drivers/md/raid5.c
+@@ -1411,6 +1411,11 @@ static int make_request (request_queue_t *q, struct bio * bi)
+ 	sector_t logical_sector, last_sector;
+ 	struct stripe_head *sh;
+ 
++	if (unlikely(bio_barrier(bi))) {
++		bio_endio(bi, bi->bi_size, -EOPNOTSUPP);
++		return 0;
++	}
++
+ 	md_write_start(mddev, bi);
+ 
+ 	if (bio_data_dir(bi)==WRITE) {
+diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
+index 495dee1d1e83..09cb7272c09f 100644
+--- a/drivers/md/raid6main.c
++++ b/drivers/md/raid6main.c
+@@ -1570,6 +1570,11 @@ static int make_request (request_queue_t *q, struct bio * bi)
+ 	sector_t logical_sector, last_sector;
+ 	struct stripe_head *sh;
+ 
++	if (unlikely(bio_barrier(bi))) {
++		bio_endio(bi, bi->bi_size, -EOPNOTSUPP);
++		return 0;
++	}
++
+ 	md_write_start(mddev, bi);
+ 
+ 	if (bio_data_dir(bi)==WRITE) {

commit 3ec67ac1a399d576d48b0736096bcce7721fe3cf
+Author: NeilBrown 
+Date:   Fri Sep 9 16:23:40 2005 -0700
+
+    [PATCH] md: fix minor error in raid10 read-balancing calculation.
+    
+    'this_sector' is a virtual (array) address while 'head_position' is a physical
+    (device) address, so substraction doesn't make any sense.  devs[slot].addr
+    should be used instead of this_sector.
+    
+    However, this patch doesn't make much practical different to the read
+    balancing due to the effects of later code.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
+index 62ebb1bc72be..7239079203ec 100644
+--- a/drivers/md/raid10.c
++++ b/drivers/md/raid10.c
+@@ -538,7 +538,8 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio)
+ 	}
+ 
+ 
+-	current_distance = abs(this_sector - conf->mirrors[disk].head_position);
++	current_distance = abs(r10_bio->devs[slot].addr -
++			       conf->mirrors[disk].head_position);
+ 
+ 	/* Find the disk whose head is closest */
+ 

commit 657390d25d4241705cb4fc5b3b4ba5b30575dc17
+Author: NeilBrown 
+Date:   Fri Aug 26 18:34:16 2005 -0700
+
+    [PATCH] md: clear the 'recovery' flags when starting an md array.
+    
+    It's possible for this to still have flags in it and a previous instance
+    has been stopped, and that confused the new array using the same mddev.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index deccd560c0de..20ca80b7dc20 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -1689,6 +1689,7 @@ static int do_md_run(mddev_t * mddev)
+ 	mddev->pers = pers[pnum];
+ 	spin_unlock(&pers_lock);
+ 
++	mddev->recovery = 0;
+ 	mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */
+ 
+ 	/* before we start the array running, initialise the bitmap */

commit 72008652dae7d10fa668d7b2ada3bddff7403d86
+Author: NeilBrown 
+Date:   Fri Aug 26 18:34:15 2005 -0700
+
+    [PATCH] md: create a MODULE_ALIAS for md corresponding to its block major number.
+    
+    I just discovered this is needed for module auto-loading.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 486ee50cfdda..deccd560c0de 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -4011,3 +4011,4 @@ EXPORT_SYMBOL(md_print_devices);
+ EXPORT_SYMBOL(md_check_recovery);
+ MODULE_LICENSE("GPL");
+ MODULE_ALIAS("md");
++MODULE_ALIAS_BLOCKDEV_MAJOR(MD_MAJOR);

commit 005eca5e74b222db4360f8938140eb843d283325
+Author: NeilBrown 
+Date:   Mon Aug 22 13:11:08 2005 -0700
+
+    [PATCH] md: make sure resync gets started when array starts.
+    
+    We weren't actually waking up the md thread after setting
+    MD_RECOVERY_NEEDED when assembling an array, so it is possible to lose a
+    race and not actually start resync.
+    
+    So add a call to md_wakeup_thread, and while we are at it, remove all the
+    "if (mddev->thread)" guards as md_wake_thread does its own checking.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index d4c275604a3e..486ee50cfdda 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -256,8 +256,7 @@ static inline void mddev_unlock(mddev_t * mddev)
+ {
+ 	up(&mddev->reconfig_sem);
+ 
+-	if (mddev->thread)
+-		md_wakeup_thread(mddev->thread);
++	md_wakeup_thread(mddev->thread);
+ }
+ 
+ mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr)
+@@ -1714,6 +1713,7 @@ static int do_md_run(mddev_t * mddev)
+ 	mddev->in_sync = 1;
+ 	
+ 	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
++	md_wakeup_thread(mddev->thread);
+ 	
+ 	if (mddev->sb_dirty)
+ 		md_update_sb(mddev);
+@@ -2236,8 +2236,7 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
+ 			export_rdev(rdev);
+ 
+ 		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+-		if (mddev->thread)
+-			md_wakeup_thread(mddev->thread);
++		md_wakeup_thread(mddev->thread);
+ 		return err;
+ 	}
+ 

commit 9223214e8d757663f366133ba5f9b58aa6b28efb
+Author: NeilBrown 
+Date:   Thu Aug 18 11:24:16 2005 -0700
+
+    [PATCH] md: make sure mddev->bitmap_offset gets cleared between array instantiations.
+    
+    ... otherwise we might try to load a bitmap from an array which hasn't one.
+    
+    The bug is that if you create an array with an internal bitmap, shut it down,
+    and then create an array with the same md device, the md drive will assume it
+    should have a bitmap too.  As the array can be created with a different md
+    device, it is mostly an inconvenience.  I'm pretty sure there is no risk of
+    data corruption.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 480f658db6f2..d4c275604a3e 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -623,6 +623,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+ 		mddev->raid_disks = sb->raid_disks;
+ 		mddev->size = sb->size;
+ 		mddev->events = md_event(sb);
++		mddev->bitmap_offset = 0;
+ 
+ 		if (sb->state & (1<recovery_cp = MaxSector;
+@@ -938,6 +939,7 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+ 		mddev->raid_disks = le32_to_cpu(sb->raid_disks);
+ 		mddev->size = le64_to_cpu(sb->size)/2;
+ 		mddev->events = le64_to_cpu(sb->events);
++		mddev->bitmap_offset = 0;
+ 		
+ 		mddev->recovery_cp = le64_to_cpu(sb->resync_offset);
+ 		memcpy(mddev->uuid, sb->set_uuid, 16);
+@@ -1824,6 +1826,7 @@ static int do_md_stop(mddev_t * mddev, int ro)
+ 		fput(mddev->bitmap_file);
+ 		mddev->bitmap_file = NULL;
+ 	}
++	mddev->bitmap_offset = 0;
+ 
+ 	/*
+ 	 * Free resources if final stop

commit 6b8b3e8a8b3e62b4209eaa36697e3c9df457e196
+Author: NeilBrown 
+Date:   Thu Aug 4 12:53:35 2005 -0700
+
+    [PATCH] md: make sure md bitmap updates are flushed when array is stopped.
+    
+    The recent change to never ignore the bitmap, revealed that the bitmap isn't
+    begin flushed properly when an array is stopped.
+    
+    We call bitmap_daemon_work three times as there is a three-stage pipeline for
+    flushing updates to the bitmap file.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
+index 09d32db06d20..41df4cda66e2 100644
+--- a/drivers/md/bitmap.c
++++ b/drivers/md/bitmap.c
+@@ -1450,6 +1450,29 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset)
+ 
+ }
+ 
++/*
++ * flush out any pending updates
++ */
++void bitmap_flush(mddev_t *mddev)
++{
++	struct bitmap *bitmap = mddev->bitmap;
++	int sleep;
++
++	if (!bitmap) /* there was no bitmap */
++		return;
++
++	/* run the daemon_work three time to ensure everything is flushed
++	 * that can be
++	 */
++	sleep = bitmap->daemon_sleep;
++	bitmap->daemon_sleep = 0;
++	bitmap_daemon_work(bitmap);
++	bitmap_daemon_work(bitmap);
++	bitmap_daemon_work(bitmap);
++	bitmap->daemon_sleep = sleep;
++	bitmap_update_sb(bitmap);
++}
++
+ /*
+  * free memory that was allocated
+  */
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 9fd4dbea0d0d..480f658db6f2 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -1798,6 +1798,8 @@ static int do_md_stop(mddev_t * mddev, int ro)
+ 				goto out;
+ 			mddev->ro = 1;
+ 		} else {
++			bitmap_flush(mddev);
++			wait_event(mddev->sb_wait, atomic_read(&mddev->pending_writes)==0);
+ 			if (mddev->ro)
+ 				set_disk_ro(disk, 0);
+ 			blk_queue_make_request(mddev->queue, md_fail_request);
+diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h
+index 6213e976eade..4bf1659f8aa8 100644
+--- a/include/linux/raid/bitmap.h
++++ b/include/linux/raid/bitmap.h
+@@ -248,6 +248,7 @@ struct bitmap {
+ 
+ /* these are used only by md/bitmap */
+ int  bitmap_create(mddev_t *mddev);
++void bitmap_flush(mddev_t *mddev);
+ void bitmap_destroy(mddev_t *mddev);
+ int  bitmap_active(struct bitmap *bitmap);
+ 

commit e3b9703e27aab3839dcdb76b00d98428b67d25b0
+Author: NeilBrown 
+Date:   Thu Aug 4 12:53:34 2005 -0700
+
+    [PATCH] md: yet another attempt to get bitmap-based resync to do the right thing in all cases...
+    
+    Firstly, R1BIO_Degraded was being set in a number of places in the resync
+    code, but is never used there, so get rid of those settings.
+    
+    Then: When doing a resync, we want to clear the bit in the bitmap iff the
+    array will be non-degraded when the sync has completed.  However the current
+    code would clear the bitmap if the array was non-degraded when the resync
+    *started*, which obviously isn't right (it is for 'resync' but not for
+    'recovery' - i.e.  rebuilding a failed drive).
+    
+    This patch calculated 'still_degraded' and uses the to tell bitmap_start_sync
+    whether this sync should clear the corresponding bit.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index d3a64a04a6d8..51d9645ed09c 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -893,7 +893,6 @@ static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error)
+ 	if (!uptodate) {
+ 		md_error(r1_bio->mddev,
+ 			 conf->mirrors[r1_bio->read_disk].rdev);
+-		set_bit(R1BIO_Degraded, &r1_bio->state);
+ 	} else
+ 		set_bit(R1BIO_Uptodate, &r1_bio->state);
+ 	rdev_dec_pending(conf->mirrors[r1_bio->read_disk].rdev, conf->mddev);
+@@ -918,10 +917,9 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error)
+ 			mirror = i;
+ 			break;
+ 		}
+-	if (!uptodate) {
++	if (!uptodate)
+ 		md_error(mddev, conf->mirrors[mirror].rdev);
+-		set_bit(R1BIO_Degraded, &r1_bio->state);
+-	}
++
+ 	update_head_pos(mirror, r1_bio);
+ 
+ 	if (atomic_dec_and_test(&r1_bio->remaining)) {
+@@ -1109,6 +1107,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
+ 	int i;
+ 	int write_targets = 0;
+ 	int sync_blocks;
++	int still_degraded = 0;
+ 
+ 	if (!conf->r1buf_pool)
+ 	{
+@@ -1137,7 +1136,10 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
+ 		return 0;
+ 	}
+ 
+-	if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, mddev->degraded) &&
++	/* before building a request, check if we can skip these blocks..
++	 * This call the bitmap_start_sync doesn't actually record anything
++	 */
++	if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
+ 	    !conf->fullsync) {
+ 		/* We can skip this block, and probably several more */
+ 		*skipped = 1;
+@@ -1203,24 +1205,23 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
+ 		if (i == disk) {
+ 			bio->bi_rw = READ;
+ 			bio->bi_end_io = end_sync_read;
+-		} else if (conf->mirrors[i].rdev &&
+-			   !conf->mirrors[i].rdev->faulty &&
+-			   (!conf->mirrors[i].rdev->in_sync ||
+-			    sector_nr + RESYNC_SECTORS > mddev->recovery_cp)) {
++		} else if (conf->mirrors[i].rdev == NULL ||
++			   conf->mirrors[i].rdev->faulty) {
++			still_degraded = 1;
++			continue;
++		} else if (!conf->mirrors[i].rdev->in_sync ||
++			   sector_nr + RESYNC_SECTORS > mddev->recovery_cp) {
+ 			bio->bi_rw = WRITE;
+ 			bio->bi_end_io = end_sync_write;
+ 			write_targets ++;
+ 		} else
++			/* no need to read or write here */
+ 			continue;
+ 		bio->bi_sector = sector_nr + conf->mirrors[i].rdev->data_offset;
+ 		bio->bi_bdev = conf->mirrors[i].rdev->bdev;
+ 		bio->bi_private = r1_bio;
+ 	}
+ 
+-	if (write_targets + 1 < conf->raid_disks)
+-		/* array degraded, can't clear bitmap */
+-		set_bit(R1BIO_Degraded, &r1_bio->state);
+-
+ 	if (write_targets == 0) {
+ 		/* There is nowhere to write, so all non-sync
+ 		 * drives must be failed - so we are finished
+@@ -1243,7 +1244,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
+ 			break;
+ 		if (sync_blocks == 0) {
+ 			if (!bitmap_start_sync(mddev->bitmap, sector_nr,
+-					&sync_blocks, mddev->degraded) &&
++					&sync_blocks, still_degraded) &&
+ 					!conf->fullsync)
+ 				break;
+ 			if (sync_blocks < (PAGE_SIZE>>9))

commit 193f1c931517592ec4188d15bf261e4bff368207
+Author: NeilBrown 
+Date:   Thu Aug 4 12:53:33 2005 -0700
+
+    [PATCH] md: always honour md bitmap being read from disk
+    
+    The code currently will ignore the bitmap if the array seem to be in-sync.
+    This is wrong if the array is degraded, and probably wrong anyway.  If the
+    bitmap says some chunks are not in in-sync, and the superblock says everything
+    IS in sync, then something is clearly wrong, and it is safer to trust the
+    bitmap.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
+index 70bca955e0de..09d32db06d20 100644
+--- a/drivers/md/bitmap.c
++++ b/drivers/md/bitmap.c
+@@ -818,8 +818,7 @@ int bitmap_unplug(struct bitmap *bitmap)
+ 	return 0;
+ }
+ 
+-static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
+-	unsigned long sectors, int in_sync);
++static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset);
+ /* * bitmap_init_from_disk -- called at bitmap_create time to initialize
+  * the in-memory bitmap from the on-disk bitmap -- also, sets up the
+  * memory mapping of the bitmap file
+@@ -828,7 +827,7 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
+  *   previously kicked from the array, we mark all the bits as
+  *   1's in order to cause a full resync.
+  */
+-static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
++static int bitmap_init_from_disk(struct bitmap *bitmap)
+ {
+ 	unsigned long i, chunks, index, oldindex, bit;
+ 	struct page *page = NULL, *oldpage = NULL;
+@@ -929,8 +928,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
+ 		}
+ 		if (test_bit(bit, page_address(page))) {
+ 			/* if the disk bit is set, set the memory bit */
+-			bitmap_set_memory_bits(bitmap,
+-					i << CHUNK_BLOCK_SHIFT(bitmap), 1, in_sync);
++			bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap));
+ 			bit_cnt++;
+ 		}
+ 	}
+@@ -1426,35 +1424,30 @@ void bitmap_close_sync(struct bitmap *bitmap)
+ 	}
+ }
+ 
+-static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
+-				   unsigned long sectors, int in_sync)
++static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset)
+ {
+ 	/* For each chunk covered by any of these sectors, set the
+-	 * counter to 1 and set resync_needed unless in_sync.  They should all
++	 * counter to 1 and set resync_needed.  They should all
+ 	 * be 0 at this point
+ 	 */
+-	while (sectors) {
+-		int secs;
+-		bitmap_counter_t *bmc;
+-		spin_lock_irq(&bitmap->lock);
+-		bmc = bitmap_get_counter(bitmap, offset, &secs, 1);
+-		if (!bmc) {
+-			spin_unlock_irq(&bitmap->lock);
+-			return;
+-		}
+-		if (! *bmc) {
+-			struct page *page;
+-			*bmc = 1 | (in_sync? 0 : NEEDED_MASK);
+-			bitmap_count_page(bitmap, offset, 1);
+-			page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
+-			set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
+-		}
++
++	int secs;
++	bitmap_counter_t *bmc;
++	spin_lock_irq(&bitmap->lock);
++	bmc = bitmap_get_counter(bitmap, offset, &secs, 1);
++	if (!bmc) {
+ 		spin_unlock_irq(&bitmap->lock);
+-		if (sectors > secs)
+-			sectors -= secs;
+-		else
+-			sectors = 0;
++		return;
+ 	}
++	if (! *bmc) {
++		struct page *page;
++		*bmc = 1 | NEEDED_MASK;
++		bitmap_count_page(bitmap, offset, 1);
++		page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
++		set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
++	}
++	spin_unlock_irq(&bitmap->lock);
++
+ }
+ 
+ /*
+@@ -1565,7 +1558,8 @@ int bitmap_create(mddev_t *mddev)
+ 
+ 	/* now that we have some pages available, initialize the in-memory
+ 	 * bitmap from the on-disk bitmap */
+-	err = bitmap_init_from_disk(bitmap, mddev->recovery_cp == MaxSector);
++	err = bitmap_init_from_disk(bitmap);
++
+ 	if (err)
+ 		return err;
+ 

commit aa1595e9f3d0d731bcfc6c2680d5483b78f663dc
+Author: NeilBrown 
+Date:   Thu Aug 4 12:53:32 2005 -0700
+
+    [PATCH] md: make 'md' and alias for 'md-mod'
+    
+    Until the bitmap code was added,
+    
+       modprobe md
+    
+    would load the md module.  But now the md module is called 'md-mod', so we
+    really need an alias for backwards comparability.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 08f003aa6cd7..9fd4dbea0d0d 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -4006,3 +4006,4 @@ EXPORT_SYMBOL(md_wakeup_thread);
+ EXPORT_SYMBOL(md_print_devices);
+ EXPORT_SYMBOL(md_check_recovery);
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("md");

commit efd8be2a4280f334be9309fa4ca1fb8f4e29475d
+Author: NeilBrown 
+Date:   Thu Aug 4 12:53:32 2005 -0700
+
+    [PATCH] md: remove a stray debugging printk.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 6580e0fa4a47..08f003aa6cd7 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -3484,7 +3484,6 @@ static void md_do_sync(mddev_t *mddev)
+ 			goto skip;
+ 		}
+ 		ITERATE_MDDEV(mddev2,tmp) {
+-			printk(".");
+ 			if (mddev2 == mddev)
+ 				continue;
+ 			if (mddev2->curr_resync && 

commit b1581566183f310abbd2d384a9079d4039faca05
+Author: NeilBrown 
+Date:   Sun Jul 31 22:34:50 2005 -0700
+
+    [PATCH] md: make sure raid5/raid6 resync uses correct 'max_sectors'
+    
+    The default resync_max_sector is set to "mddev->size << 1".  If the
+    raid-personality-module updates mddev->size, it must update
+    resync_max_sectors too.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
+index 4698d5f79575..43f231a467d5 100644
+--- a/drivers/md/raid5.c
++++ b/drivers/md/raid5.c
+@@ -1653,6 +1653,7 @@ static int run (mddev_t *mddev)
+ 
+ 	/* device size must be a multiple of chunk size */
+ 	mddev->size &= ~(mddev->chunk_size/1024 -1);
++	mddev->resync_max_sectors = mddev->size << 1;
+ 
+ 	if (!conf->chunk_size || conf->chunk_size % 4) {
+ 		printk(KERN_ERR "raid5: invalid chunk size %d for %s\n",
+diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
+index f5ee16805111..495dee1d1e83 100644
+--- a/drivers/md/raid6main.c
++++ b/drivers/md/raid6main.c
+@@ -1813,6 +1813,7 @@ static int run (mddev_t *mddev)
+ 
+ 	/* device size must be a multiple of chunk size */
+ 	mddev->size &= ~(mddev->chunk_size/1024 -1);
++	mddev->resync_max_sectors = mddev->size << 1;
+ 
+ 	if (conf->raid_disks < 4) {
+ 		printk(KERN_ERR "raid6: not enough configured devices for %s (%d, minimum 4)\n",

commit 4b5c7ae83704320e2afb0912f4c42eadabc7535b
+Author: NeilBrown 
+Date:   Wed Jul 27 11:43:28 2005 -0700
+
+    [PATCH] md: when resizing an array, we need to update resync_max_sectors as well as size
+    
+    Without this, and attempt to 'grow' an array will claim to have synced the
+    extra part without actually having done anything.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index 5f253ee536bb..d3a64a04a6d8 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -1468,6 +1468,7 @@ static int raid1_resize(mddev_t *mddev, sector_t sectors)
+ 		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+ 	}
+ 	mddev->size = mddev->array_size;
++	mddev->resync_max_sectors = sectors;
+ 	return 0;
+ }
+ 
+diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
+index 93a9726cc2d6..4698d5f79575 100644
+--- a/drivers/md/raid5.c
++++ b/drivers/md/raid5.c
+@@ -1931,6 +1931,7 @@ static int raid5_resize(mddev_t *mddev, sector_t sectors)
+ 		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+ 	}
+ 	mddev->size = sectors /2;
++	mddev->resync_max_sectors = sectors;
+ 	return 0;
+ }
+ 
+diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
+index f62ea1a73d0d..f5ee16805111 100644
+--- a/drivers/md/raid6main.c
++++ b/drivers/md/raid6main.c
+@@ -2095,6 +2095,7 @@ static int raid6_resize(mddev_t *mddev, sector_t sectors)
+ 		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+ 	}
+ 	mddev->size = sectors /2;
++	mddev->resync_max_sectors = sectors;
+ 	return 0;
+ }
+ 

commit 6a806c510de490318846b53bbfec463d02ca274b
+Author: NeilBrown 
+Date:   Fri Jul 15 03:56:35 2005 -0700
+
+    [PATCH] md/raid1: clear bitmap when fullsync completes
+    
+    We need to be careful differentiating between a resync of a complete array,
+    in which we can clear the bitmap, and a resync of a degraded array, in
+    which we cannot.
+    
+    This patch cleans all that up.
+    
+    Cc: Paul Clements 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
+index 95980ad6b27b..0c2ed99a3832 100644
+--- a/drivers/md/bitmap.c
++++ b/drivers/md/bitmap.c
+@@ -1345,7 +1345,8 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto
+ 	}
+ }
+ 
+-int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks)
++int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks,
++			int degraded)
+ {
+ 	bitmap_counter_t *bmc;
+ 	int rv;
+@@ -1362,8 +1363,10 @@ int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks)
+ 			rv = 1;
+ 		else if (NEEDED(*bmc)) {
+ 			rv = 1;
+-			*bmc |= RESYNC_MASK;
+-			*bmc &= ~NEEDED_MASK;
++			if (!degraded) { /* don't set/clear bits if degraded */
++				*bmc |= RESYNC_MASK;
++				*bmc &= ~NEEDED_MASK;
++			}
+ 		}
+ 	}
+ 	spin_unlock_irq(&bitmap->lock);
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index ff1dbec864af..5f253ee536bb 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -1126,21 +1126,19 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
+ 		 * only be one in raid1 resync.
+ 		 * We can find the current addess in mddev->curr_resync
+ 		 */
+-		if (!conf->fullsync) {
+-			if (mddev->curr_resync < max_sector)
+-				bitmap_end_sync(mddev->bitmap,
+-						mddev->curr_resync,
++		if (mddev->curr_resync < max_sector) /* aborted */
++			bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
+ 						&sync_blocks, 1);
+-			bitmap_close_sync(mddev->bitmap);
+-		}
+-		if (mddev->curr_resync >= max_sector)
++		else /* completed sync */
+ 			conf->fullsync = 0;
++
++		bitmap_close_sync(mddev->bitmap);
+ 		close_sync(conf);
+ 		return 0;
+ 	}
+ 
+-	if (!conf->fullsync &&
+-	    !bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks)) {
++	if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, mddev->degraded) &&
++	    !conf->fullsync) {
+ 		/* We can skip this block, and probably several more */
+ 		*skipped = 1;
+ 		return sync_blocks;
+@@ -1243,15 +1241,15 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
+ 			len = (max_sector - sector_nr) << 9;
+ 		if (len == 0)
+ 			break;
+-		if (!conf->fullsync) {
+-			if (sync_blocks == 0) {
+-				if (!bitmap_start_sync(mddev->bitmap,
+-						       sector_nr, &sync_blocks))
+-					break;
+-				if (sync_blocks < (PAGE_SIZE>>9))
+-					BUG();
+-				if (len > (sync_blocks<<9)) len = sync_blocks<<9;
+-			}
++		if (sync_blocks == 0) {
++			if (!bitmap_start_sync(mddev->bitmap, sector_nr,
++					&sync_blocks, mddev->degraded) &&
++					!conf->fullsync)
++				break;
++			if (sync_blocks < (PAGE_SIZE>>9))
++				BUG();
++			if (len > (sync_blocks<<9))
++				len = sync_blocks<<9;
+ 		}
+ 
+ 		for (i=0 ; i < conf->raid_disks; i++) {
+@@ -1264,7 +1262,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
+ 					while (i > 0) {
+ 						i--;
+ 						bio = r1_bio->bios[i];
+-						if (bio->bi_end_io==NULL) continue;
++						if (bio->bi_end_io==NULL)
++							continue;
+ 						/* remove last page from this bio */
+ 						bio->bi_vcnt--;
+ 						bio->bi_size -= len;
+diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h
+index e24b74b11150..6213e976eade 100644
+--- a/include/linux/raid/bitmap.h
++++ b/include/linux/raid/bitmap.h
+@@ -262,7 +262,7 @@ void bitmap_write_all(struct bitmap *bitmap);
+ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors);
+ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors,
+ 		     int success);
+-int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks);
++int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int degraded);
+ void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int aborted);
+ void bitmap_close_sync(struct bitmap *bitmap);
+ 

commit 1eb29128c644581fa51f822545921394ad4f719f
+Author: Neil Brown 
+Date:   Fri Jul 15 03:56:27 2005 -0700
+
+    [PATCH] Fix raid0's attempt to divide by 64bit numbers
+    
+    Apparently sector_div is only guaranteed to work with a 32bit divisor, even
+    on 64bit architectures.  So allow for this in raid0.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
+index e11dd14d0b43..2120710172c5 100644
+--- a/drivers/md/raid0.c
++++ b/drivers/md/raid0.c
+@@ -314,16 +314,16 @@ static int raid0_run (mddev_t *mddev)
+ 		sector_t space = conf->hash_spacing;
+ 		int round;
+ 		conf->preshift = 0;
+-		if (sizeof(sector_t) > sizeof(unsigned long)) {
++		if (sizeof(sector_t) > sizeof(u32)) {
+ 			/*shift down space and s so that sector_div will work */
+-			while (space > (sector_t) (~(unsigned long)0)) {
++			while (space > (sector_t) (~(u32)0)) {
+ 				s >>= 1;
+ 				space >>= 1;
+ 				s += 1; /* force round-up */
+ 				conf->preshift++;
+ 			}
+ 		}
+-		round = sector_div(s, (unsigned long)space) ? 1 : 0;
++		round = sector_div(s, (u32)space) ? 1 : 0;
+ 		nb_zone = s + round;
+ 	}
+ 	printk("raid0 : nb_zone is %d.\n", nb_zone);
+@@ -443,7 +443,7 @@ static int raid0_make_request (request_queue_t *q, struct bio *bio)
+ 		volatile
+ #endif
+ 		sector_t x = block >> conf->preshift;
+-		sector_div(x, (unsigned long)conf->hash_spacing);
++		sector_div(x, (u32)conf->hash_spacing);
+ 		zone = conf->hash_table[x];
+ 	}
+  

commit bef5a66fd7fd8d606da5c9f210e2673f4e636f57
+Author: Neil Brown 
+Date:   Mon Jul 11 01:05:47 2005 -0500
+
+    Input: serio_raw - fix Kconfig help
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Vojtech Pavlik 
+    Signed-off-by: Dmitry Torokhov 
+
+diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
+index b3710733b36b..98acf170252c 100644
+--- a/drivers/input/serio/Kconfig
++++ b/drivers/input/serio/Kconfig
+@@ -175,7 +175,7 @@ config SERIO_RAW
+ 	  allocating minor 1 (that historically corresponds to /dev/psaux)
+ 	  first. To bind this driver to a serio port use sysfs interface:
+ 
+-	      echo -n "serio_raw" > /sys/bus/serio/devices/serioX/driver
++	      echo -n "serio_raw" > /sys/bus/serio/devices/serioX/drvctl
+ 
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called serio_raw.

commit e34ac862ee6644378bfe6ea65c2e0dda4545513d
+Author: NeilBrown 
+Date:   Thu Jul 7 17:59:30 2005 -0700
+
+    [PATCH] nfsd4: fix fh_expire_type
+    
+    After discussion at the recent NFSv4 bake-a-thon, I realized that my
+    assumption that NFS4_FH_PERSISTENT required filehandles to persist was a
+    misreading of the spec.  This also fixes an interoperability problem with the
+    Solaris client.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index 1515c5b8096f..4c4146350236 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -1366,9 +1366,9 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
+ 		if ((buflen -= 4) < 0)
+ 			goto out_resource;
+ 		if (exp->ex_flags & NFSEXP_NOSUBTREECHECK)
+-			WRITE32(NFS4_FH_VOLATILE_ANY);
++			WRITE32(NFS4_FH_PERSISTENT);
+ 		else
+-			WRITE32(NFS4_FH_VOLATILE_ANY|NFS4_FH_VOL_RENAME);
++			WRITE32(NFS4_FH_PERSISTENT|NFS4_FH_VOL_RENAME);
+ 	}
+ 	if (bmval0 & FATTR4_WORD0_CHANGE) {
+ 		/*

commit 4c4cd222ee329025840bc2f8cebf71d36c62440c
+Author: NeilBrown 
+Date:   Thu Jul 7 17:59:27 2005 -0700
+
+    [PATCH] nfsd4: check lock type against openmode.
+    
+    We shouldn't be allowing, e.g., write locks on files not open for read.  To
+    enforce this, we add a pointer from the lock stateid back to the open stateid
+    it came from, so that the check will continue to be correct even after the
+    open is upgraded or downgraded.
+    
+    Signed-off-by: Andy Adamson 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 59b214f01b6d..b83f8fb441e1 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1160,6 +1160,7 @@ init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *
+ 	stp->st_deny_bmap = 0;
+ 	__set_bit(open->op_share_access, &stp->st_access_bmap);
+ 	__set_bit(open->op_share_deny, &stp->st_deny_bmap);
++	stp->st_openstp = NULL;
+ }
+ 
+ static void
+@@ -2158,12 +2159,18 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
+ 	return status;
+ }
+ 
++static inline int
++setlkflg (int type)
++{
++	return (type == NFS4_READW_LT || type == NFS4_READ_LT) ?
++		RD_STATE : WR_STATE;
++}
+ 
+ /* 
+  * Checks for sequence id mutating operations. 
+  */
+ static int
+-nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, clientid_t *lockclid)
++nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, struct nfsd4_lock *lock)
+ {
+ 	struct nfs4_stateid *stp;
+ 	struct nfs4_stateowner *sop;
+@@ -2201,21 +2208,31 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
+ 		goto check_replay;
+ 	}
+ 
+-	/* for new lock stateowners:
+-	 * check that the lock->v.new.open_stateid
+-	 * refers to an open stateowner
+-	 *
+-	 * check that the lockclid (nfs4_lock->v.new.clientid) is the same
+-	 * as the open_stateid->st_stateowner->so_client->clientid
+-	 */
+-	if (lockclid) {
++	if (lock) {
+ 		struct nfs4_stateowner *sop = stp->st_stateowner;
++		clientid_t *lockclid = &lock->v.new.clientid;
+ 		struct nfs4_client *clp = sop->so_client;
++		int lkflg = 0;
++		int status;
++
++		lkflg = setlkflg(lock->lk_type);
++
++		if (lock->lk_is_new) {
++                       if (!sop->so_is_open_owner)
++			       return nfserr_bad_stateid;
++                       if (!cmp_clid(&clp->cl_clientid, lockclid))
++			       return nfserr_bad_stateid;
++                       /* stp is the open stateid */
++                       status = nfs4_check_openmode(stp, lkflg);
++                       if (status)
++			       return status;
++               } else {
++                       /* stp is the lock stateid */
++                       status = nfs4_check_openmode(stp->st_openstp, lkflg);
++                       if (status)
++			       return status;
++               }
+ 
+-		if (!sop->so_is_open_owner)
+-			return nfserr_bad_stateid;
+-		if (!cmp_clid(&clp->cl_clientid, lockclid))
+-			return nfserr_bad_stateid;
+ 	}
+ 
+ 	if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) {
+@@ -2642,6 +2659,7 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc
+ 	stp->st_vfs_file = open_stp->st_vfs_file; /* FIXME refcount?? */
+ 	stp->st_access_bmap = open_stp->st_access_bmap;
+ 	stp->st_deny_bmap = open_stp->st_deny_bmap;
++	stp->st_openstp = open_stp;
+ 
+ out:
+ 	return stp;
+@@ -2697,8 +2715,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
+ 				        lock->lk_new_open_seqid,
+ 		                        &lock->lk_new_open_stateid,
+ 		                        CHECK_FH | OPEN_STATE,
+-		                        &open_sop, &open_stp,
+-					&lock->v.new.clientid);
++		                        &open_sop, &open_stp, lock);
+ 		if (status)
+ 			goto out;
+ 		/* create lockowner and lock stateid */
+@@ -2726,7 +2743,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
+ 				       lock->lk_old_lock_seqid, 
+ 				       &lock->lk_old_lock_stateid, 
+ 				       CHECK_FH | LOCK_STATE, 
+-				       &lock->lk_stateowner, &lock_stp, NULL);
++				       &lock->lk_stateowner, &lock_stp, lock);
+ 		if (status)
+ 			goto out;
+ 	}
+diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
+index 2d19431f47ea..8bf23cf8b603 100644
+--- a/include/linux/nfsd/state.h
++++ b/include/linux/nfsd/state.h
+@@ -237,6 +237,10 @@ struct nfs4_file {
+ *       st_perlockowner: (open stateid) list of lock nfs4_stateowners
+ * 	st_access_bmap: used only for open stateid
+ * 	st_deny_bmap: used only for open stateid
++*	st_openstp: open stateid lock stateid was derived from
++*
++* XXX: open stateids and lock stateids have diverged sufficiently that
++* we should consider defining separate structs for the two cases.
+ */
+ 
+ struct nfs4_stateid {
+@@ -250,6 +254,7 @@ struct nfs4_stateid {
+ 	struct file                 * st_vfs_file;
+ 	unsigned long                 st_access_bmap;
+ 	unsigned long                 st_deny_bmap;
++	struct nfs4_stateid         * st_openstp;
+ };
+ 
+ /* flags for preprocess_seqid_op() */

commit 3a4f98bbf481cb9f755005ac569ceb5303e1b69f
+Author: NeilBrown 
+Date:   Thu Jul 7 17:59:26 2005 -0700
+
+    [PATCH] nfsd4: clean up nfs4_preprocess_seqid_op
+    
+    As long as we're here, do some miscellaneous cleanup.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 67e03b5d0d83..59b214f01b6d 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2165,7 +2165,6 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
+ static int
+ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, clientid_t *lockclid)
+ {
+-	int status;
+ 	struct nfs4_stateid *stp;
+ 	struct nfs4_stateowner *sop;
+ 
+@@ -2173,19 +2172,17 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
+ 			"stateid = (%08x/%08x/%08x/%08x)\n", seqid,
+ 		stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid,
+ 		stateid->si_generation);
+-			        
++
+ 	*stpp = NULL;
+ 	*sopp = NULL;
+ 
+-	status = nfserr_bad_stateid;
+ 	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) {
+ 		printk("NFSD: preprocess_seqid_op: magic stateid!\n");
+-		goto out;
++		return nfserr_bad_stateid;
+ 	}
+ 
+-	status = nfserr_stale_stateid;
+ 	if (STALE_STATEID(stateid))
+-		goto out;
++		return nfserr_stale_stateid;
+ 	/*
+ 	* We return BAD_STATEID if filehandle doesn't match stateid, 
+ 	* the confirmed flag is incorrecly set, or the generation 
+@@ -2204,8 +2201,6 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
+ 		goto check_replay;
+ 	}
+ 
+-	status = nfserr_bad_stateid;
+-
+ 	/* for new lock stateowners:
+ 	 * check that the lock->v.new.open_stateid
+ 	 * refers to an open stateowner
+@@ -2218,14 +2213,14 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
+ 		struct nfs4_client *clp = sop->so_client;
+ 
+ 		if (!sop->so_is_open_owner)
+-			goto out;
++			return nfserr_bad_stateid;
+ 		if (!cmp_clid(&clp->cl_clientid, lockclid))
+-			goto out;
++			return nfserr_bad_stateid;
+ 	}
+ 
+ 	if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) {
+ 		printk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n");
+-		goto out;
++		return nfserr_bad_stateid;
+ 	}
+ 
+ 	*stpp = stp;
+@@ -2239,45 +2234,38 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
+ 	if (seqid != sop->so_seqid)
+ 		goto check_replay;
+ 
+-	if (sop->so_confirmed) {
+-		if (flags & CONFIRM) {
+-			printk("NFSD: preprocess_seqid_op: expected unconfirmed stateowner!\n");
+-			goto out;
+-		}
++	if (sop->so_confirmed && flags & CONFIRM) {
++		printk("NFSD: preprocess_seqid_op: expected"
++				" unconfirmed stateowner!\n");
++		return nfserr_bad_stateid;
+ 	}
+-	else {
+-		if (!(flags & CONFIRM)) {
+-			printk("NFSD: preprocess_seqid_op: stateowner not confirmed yet!\n");
+-			goto out;
+-		}
++	if (!sop->so_confirmed && !(flags & CONFIRM)) {
++		printk("NFSD: preprocess_seqid_op: stateowner not"
++				" confirmed yet!\n");
++		return nfserr_bad_stateid;
+ 	}
+ 	if (stateid->si_generation > stp->st_stateid.si_generation) {
+ 		printk("NFSD: preprocess_seqid_op: future stateid?!\n");
+-		goto out;
++		return nfserr_bad_stateid;
+ 	}
+ 
+-	status = nfserr_old_stateid;
+ 	if (stateid->si_generation < stp->st_stateid.si_generation) {
+ 		printk("NFSD: preprocess_seqid_op: old stateid!\n");
+-		goto out;
++		return nfserr_old_stateid;
+ 	}
+ 	renew_client(sop->so_client);
+-	status = nfs_ok;
++	return nfs_ok;
+ 
+-out:
+-	return status;
+ check_replay:
+ 	if (seqid == sop->so_seqid - 1) {
+ 		printk("NFSD: preprocess_seqid_op: retransmission?\n");
+ 		/* indicate replay to calling function */
+-		status = NFSERR_REPLAY_ME;
+-	} else  {
+-		printk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d\n", sop->so_seqid, seqid);
+-
+-		*sopp = NULL;
+-		status = nfserr_bad_seqid;
++		return NFSERR_REPLAY_ME;
+ 	}
+-	goto out;
++	printk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d)\n",
++			sop->so_seqid, seqid);
++	*sopp = NULL;
++	return nfserr_bad_seqid;
+ }
+ 
+ int

commit f8816512fcfde986326a2eb0f5a58e463d9904d8
+Author: NeilBrown 
+Date:   Thu Jul 7 17:59:25 2005 -0700
+
+    [PATCH] nfsd4: clarify close_lru handling
+    
+    The handling of close_lru in preprocess_stateid_op was a source of some
+    confusion here recently.  Try to make the logic a little clearer, by renaming
+    find_openstateowner_id to make its purpose clearer and untangling some
+    unnecessarily complicated goto's.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 7694fb8aae35..67e03b5d0d83 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1988,14 +1988,11 @@ laundromat_main(void *not_used)
+ 	queue_delayed_work(laundry_wq, &laundromat_work, t*HZ);
+ }
+ 
+-/* search ownerid_hashtbl[] and close_lru for stateid owner
+- * (stateid->si_stateownerid)
+- */
+ static struct nfs4_stateowner *
+-find_openstateowner_id(u32 st_id, int flags) {
++search_close_lru(u32 st_id, int flags)
++{
+ 	struct nfs4_stateowner *local = NULL;
+ 
+-	dprintk("NFSD: find_openstateowner_id %d\n", st_id);
+ 	if (flags & CLOSE_STATE) {
+ 		list_for_each_entry(local, &close_lru, so_close_lru) {
+ 			if (local->so_id == st_id)
+@@ -2193,13 +2190,19 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
+ 	* We return BAD_STATEID if filehandle doesn't match stateid, 
+ 	* the confirmed flag is incorrecly set, or the generation 
+ 	* number is incorrect.  
+-	* If there is no entry in the openfile table for this id, 
+-	* we can't always return BAD_STATEID;
+-	* this might be a retransmitted CLOSE which has arrived after 
+-	* the openfile has been released.
+ 	*/
+-	if (!(stp = find_stateid(stateid, flags)))
+-		goto no_nfs4_stateid;
++	stp = find_stateid(stateid, flags);
++	if (stp == NULL) {
++		/*
++		 * Also, we should make sure this isn't just the result of
++		 * a replayed close:
++		 */
++		sop = search_close_lru(stateid->si_stateownerid, flags);
++		if (sop == NULL)
++			return nfserr_bad_stateid;
++		*sopp = sop;
++		goto check_replay;
++	}
+ 
+ 	status = nfserr_bad_stateid;
+ 
+@@ -2263,21 +2266,6 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
+ 
+ out:
+ 	return status;
+-
+-no_nfs4_stateid:
+-
+-	/*
+-	* We determine whether this is a bad stateid or a replay, 
+-	* starting by trying to look up the stateowner.
+-	* If stateowner is not found - stateid is bad.
+-	*/
+-	if (!(sop = find_openstateowner_id(stateid->si_stateownerid, flags))) {
+-		printk("NFSD: preprocess_seqid_op: no stateowner or nfs4_stateid!\n");
+-		status = nfserr_bad_stateid;
+-		goto out;
+-	}
+-	*sopp = sop;
+-
+ check_replay:
+ 	if (seqid == sop->so_seqid - 1) {
+ 		printk("NFSD: preprocess_seqid_op: retransmission?\n");

commit 52fd004e296ac07cde820af9e3139d47dda03cf8
+Author: NeilBrown 
+Date:   Thu Jul 7 17:59:24 2005 -0700
+
+    [PATCH] nfsd4: renew lease on seqid modifying operations
+    
+    nfs4_preprocess_seqid_op is called by NFSv4 operations that imply an implicit
+    renewal of the client lease.
+    
+    Signed-off-by: Andy Adamson 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 3647c942915e..7694fb8aae35 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2258,7 +2258,7 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
+ 		printk("NFSD: preprocess_seqid_op: old stateid!\n");
+ 		goto out;
+ 	}
+-	/* XXX renew the client lease here */
++	renew_client(sop->so_client);
+ 	status = nfs_ok;
+ 
+ out:

commit b700949b781480819e53bdc38a53f053226dd75e
+Author: NeilBrown 
+Date:   Thu Jul 7 17:59:23 2005 -0700
+
+    [PATCH] nfsd4: return better error on io incompatible with open mode
+    
+    from RFC 3530:
+    "Share reservations are established by OPEN operations and by their
+    nature are mandatory in that when the OPEN denies READ or WRITE
+    operations, that denial results in such operations being rejected
+    with error NFS4ERR_LOCKED."
+    
+    (Note that share_denied is really only a legal error for OPEN.)
+    
+    Signed-off-by: Andy Adamson 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index b96714ae3dd7..3647c942915e 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1295,7 +1295,7 @@ nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
+ 	fp = find_file(ino);
+ 	if (!fp)
+ 		return nfs_ok;
+-	ret = nfserr_share_denied;
++	ret = nfserr_locked;
+ 	/* Search for conflicting share reservations */
+ 	list_for_each_entry(stp, &fp->fi_stateids, st_perfile) {
+ 		if (test_bit(deny_type, &stp->st_deny_bmap) ||
+diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
+index c2da1b62d416..6d5a24f3fc6d 100644
+--- a/include/linux/nfsd/nfsd.h
++++ b/include/linux/nfsd/nfsd.h
+@@ -231,6 +231,7 @@ void		nfsd_lockd_shutdown(void);
+ #define	nfserr_reclaim_bad	__constant_htonl(NFSERR_RECLAIM_BAD)
+ #define	nfserr_badname		__constant_htonl(NFSERR_BADNAME)
+ #define	nfserr_cb_path_down	__constant_htonl(NFSERR_CB_PATH_DOWN)
++#define	nfserr_locked		__constant_htonl(NFSERR_LOCKED)
+ 
+ /* error codes for internal use */
+ /* if a request fails due to kmalloc failure, it gets dropped.

commit 444c2c07c2d7a6936d1381d381ab80e3f5541427
+Author: NeilBrown 
+Date:   Thu Jul 7 17:59:22 2005 -0700
+
+    [PATCH] nfsd4: always update stateid on open
+    
+    An OPEN from the same client/open stateowner requires a stateid update because
+    of the share/deny access update.
+    
+    Signed-off-by: Andy Adamson 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 386daac508f5..b96714ae3dd7 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1820,6 +1820,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
+ 		status = nfs4_upgrade_open(rqstp, current_fh, stp, open);
+ 		if (status)
+ 			goto out;
++		update_stateid(&stp->st_stateid);
+ 	} else {
+ 		/* Stateid was not found, this is a new OPEN */
+ 		int flags = 0;

commit e66770cd7b0c36f28a2f6eb0957c0575ac8b3787
+Author: NeilBrown 
+Date:   Thu Jul 7 17:59:21 2005 -0700
+
+    [PATCH] nfsd4: relax new lock seqid check
+    
+    We're insisting that the lock sequence id field passed in the
+    open_to_lockowner struct always be zero.  This is probably thanks to the
+    sentence in rfc3530: "The first request issued for any given lock_owner is
+    issued with a sequence number of zero."
+    
+    But there doesn't seem to be any problem with allowing initial sequence
+    numbers other than zero.  And currently this is causing lock reclaims from the
+    Linux client to fail.
+    
+    In the spirit of "be liberal in what you accept, conservative in what you
+    send", we'll relax the check (and patch the Linux client as well).
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index f60bcad77f71..386daac508f5 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2715,11 +2715,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
+ 			goto out;
+ 		}
+ 
+-		/* is the new lock seqid presented by the client zero? */
+-		status = nfserr_bad_seqid;
+-		if (lock->v.new.lock_seqid != 0)
+-			goto out;
+-
+ 		/* validate and update open stateid and open seqid */
+ 		status = nfs4_preprocess_seqid_op(current_fh, 
+ 				        lock->lk_new_open_seqid,

commit 7fb64cee34f5dc743f697041717cafda8a94b5ac
+Author: NeilBrown 
+Date:   Thu Jul 7 17:59:20 2005 -0700
+
+    [PATCH] nfsd4: seqid comments
+    
+    Add some comments on the use of so_seqid, in an attempt to avoid some of the
+    confusion outlined in the previous patch....
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index 5207068cde1a..1515c5b8096f 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -1210,10 +1210,10 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
+ 	save = resp->p;
+ 
+ /*
+- * Routine for encoding the result of a
+- * "seqid-mutating" NFSv4 operation.  This is
+- * where seqids are incremented, and the
+- * replay cache is filled.
++ * Routine for encoding the result of a "seqid-mutating" NFSv4 operation.  This
++ * is where sequence id's are incremented, and the replay cache is filled.
++ * Note that we increment sequence id's here, at the last moment, so we're sure
++ * we know whether the error to be returned is a sequence id mutating error.
+  */
+ 
+ #define ENCODE_SEQID_OP_TAIL(stateowner) do {			\
+diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
+index a84a3fa99be1..2d19431f47ea 100644
+--- a/include/linux/nfsd/state.h
++++ b/include/linux/nfsd/state.h
+@@ -203,7 +203,9 @@ struct nfs4_stateowner {
+ 	int			so_is_open_owner; /* 1=openowner,0=lockowner */
+ 	u32                     so_id;
+ 	struct nfs4_client *    so_client;
+-	u32                     so_seqid;    
++	/* after increment in ENCODE_SEQID_OP_TAIL, represents the next
++	 * sequence id expected from the client: */
++	u32                     so_seqid;
+ 	struct xdr_netobj       so_owner;     /* open owner name */
+ 	int                     so_confirmed; /* successful OPEN_CONFIRM? */
+ 	struct nfs4_replay	so_replay;

commit bd9aac523b812d58e644fde5e59f5697fb9e3822
+Author: NeilBrown 
+Date:   Thu Jul 7 17:59:19 2005 -0700
+
+    [PATCH] nfsd4: fix open_reclaim seqid
+    
+    The sequence number we store in the sequence id is the last one we received
+    from the client.  So on the next operation we'll check that the client gives
+    us the next higher number.
+    
+    We increment sequence id's at the last moment, in encode, so that we're sure
+    of knowing the right error return.  (The decision to increment the sequence id
+    depends on the exact error returned.)
+    
+    However on the *first* use of a sequence number, if we set the sequence number
+    to the one received from the client and then let the increment happen on
+    encode, we'll be left with a sequence number one to high.
+    
+    For that reason, ENCODE_SEQID_OP_TAIL only increments the sequence id on
+    *confirmed* stateowners.
+    
+    This creates a problem for open reclaims, which are confirmed on first use.
+    Therefore the open reclaim code, as a special exception, *decrements* the
+    sequence id, cancelling out the undesired increment on encode.  But this
+    prevents the sequence id from ever being incremented in the case where
+    multiple reclaims are sent with the same openowner.  Yuch!
+    
+    We could add another exception to the open reclaim code, decrementing the
+    sequence id only if this is the first use of the open owner.
+    
+    But it's simpler by far to modify the meaning of the op_seqid field: instead
+    of representing the previous value sent by the client, we take op_seqid, after
+    encoding, to represent the *next* sequence id that we expect from the client.
+    This eliminates the need for special-case handling of the first use of a
+    stateowner.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 74cd9bf3e0a1..f60bcad77f71 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1483,7 +1483,7 @@ nfsd4_process_open1(struct nfsd4_open *open)
+ 	if (sop) {
+ 		open->op_stateowner = sop;
+ 		/* check for replay */
+-		if (open->op_seqid == sop->so_seqid){
++		if (open->op_seqid == sop->so_seqid - 1){
+ 			if (sop->so_replay.rp_buflen)
+ 				return NFSERR_REPLAY_ME;
+ 			else {
+@@ -1498,7 +1498,7 @@ nfsd4_process_open1(struct nfsd4_open *open)
+ 				goto renew;
+ 			}
+ 		} else if (sop->so_confirmed) {
+-			if (open->op_seqid == sop->so_seqid + 1)
++			if (open->op_seqid == sop->so_seqid)
+ 				goto renew;
+ 			status = nfserr_bad_seqid;
+ 			goto out;
+@@ -1684,13 +1684,11 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_sta
+ }
+ 
+ 
+-/* decrement seqid on successful reclaim, it will be bumped in encode_open */
+ static void
+ nfs4_set_claim_prev(struct nfsd4_open *open)
+ {
+ 	open->op_stateowner->so_confirmed = 1;
+ 	open->op_stateowner->so_client->cl_firststate = 1;
+-	open->op_stateowner->so_seqid--;
+ }
+ 
+ /*
+@@ -2234,7 +2232,7 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
+ 	*  For the moment, we ignore the possibility of 
+ 	*  generation number wraparound.
+ 	*/
+-	if (seqid != sop->so_seqid + 1)
++	if (seqid != sop->so_seqid)
+ 		goto check_replay;
+ 
+ 	if (sop->so_confirmed) {
+@@ -2280,12 +2278,12 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
+ 	*sopp = sop;
+ 
+ check_replay:
+-	if (seqid == sop->so_seqid) {
++	if (seqid == sop->so_seqid - 1) {
+ 		printk("NFSD: preprocess_seqid_op: retransmission?\n");
+ 		/* indicate replay to calling function */
+ 		status = NFSERR_REPLAY_ME;
+ 	} else  {
+-		printk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d\n", sop->so_seqid +1, seqid);
++		printk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d\n", sop->so_seqid, seqid);
+ 
+ 		*sopp = NULL;
+ 		status = nfserr_bad_seqid;
+@@ -2608,7 +2606,6 @@ find_lockstateowner_str(struct inode *inode, clientid_t *clid,
+  * occured. 
+  *
+  * strhashval = lock_ownerstr_hashval 
+- * so_seqid = lock->lk_new_lock_seqid - 1: it gets bumped in encode 
+  */
+ 
+ static struct nfs4_stateowner *
+@@ -2633,7 +2630,7 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
+ 	sop->so_is_open_owner = 0;
+ 	sop->so_id = current_ownerid++;
+ 	sop->so_client = clp;
+-	sop->so_seqid = lock->lk_new_lock_seqid - 1;
++	sop->so_seqid = lock->lk_new_lock_seqid;
+ 	sop->so_confirmed = 1;
+ 	rp = &sop->so_replay;
+ 	rp->rp_status = NFSERR_SERVERFAULT;
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index 91fb171d2ace..5207068cde1a 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -1218,8 +1218,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
+ 
+ #define ENCODE_SEQID_OP_TAIL(stateowner) do {			\
+ 	if (seqid_mutating_err(nfserr) && stateowner) { 	\
+-		if (stateowner->so_confirmed)			\
+-			stateowner->so_seqid++;			\
++		stateowner->so_seqid++;				\
+ 		stateowner->so_replay.rp_status = nfserr;   	\
+ 		stateowner->so_replay.rp_buflen = 		\
+ 			  (((char *)(resp)->p - (char *)save)); \

commit 893f87701c9e5bd5610dfbb3f8bf1135f86d85cb
+Author: NeilBrown 
+Date:   Thu Jul 7 17:59:17 2005 -0700
+
+    [PATCH] nfsd4: comment indentation
+    
+    Yeah, it's trivial, but this drives me up the wall....
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 142b63bc2051..74cd9bf3e0a1 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2704,11 +2704,11 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
+ 	nfs4_lock_state();
+ 
+ 	if (lock->lk_is_new) {
+-	/*
+-	 * Client indicates that this is a new lockowner.
+-	 * Use open owner and open stateid to create lock owner and lock 
+-	 * stateid.
+-	 */
++		/*
++		 * Client indicates that this is a new lockowner.
++		 * Use open owner and open stateid to create lock owner and
++		 * lock stateid.
++		 */
+ 		struct nfs4_stateid *open_stp = NULL;
+ 		struct nfs4_file *fp;
+ 		
+@@ -2842,10 +2842,10 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
+ out_destroy_new_stateid:
+ 	if (lock->lk_is_new) {
+ 		dprintk("NFSD: nfsd4_lock: destroy new stateid!\n");
+-	/*
+-	* An error encountered after instantiation of the new
+-	* stateid has forced us to destroy it.
+-	*/
++		/*
++		 * An error encountered after instantiation of the new
++		 * stateid has forced us to destroy it.
++		 */
+ 		if (!seqid_mutating_err(status))
+ 			open_sop->so_seqid--;
+ 

commit 375151773125f56b7f6d798d914ea469256b330b
+Author: NeilBrown 
+Date:   Thu Jul 7 17:59:16 2005 -0700
+
+    [PATCH] nfsd4: stop overusing RECLAIM_BAD
+    
+    A misreading of the spec lead us to convert all errors on open and lock
+    reclaims to RECLAIM_BAD.  This causes problems--for example, a reboot within
+    the grace period could lead to reclaims with stale stateid's, and we'd like to
+    return STALE errors in those cases.
+    
+    What rfc3530 actually says about RECLAIM_BAD: "The reclaim provided by the
+    client does not match any of the server's state consistency checks and is
+    bad." I'm assuming that "state consistency checks" refers to checks for
+    consistency with the state recorded to stable storage, and that the error
+    should be reserved for that case.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 92968c94c6e6..142b63bc2051 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1531,8 +1531,6 @@ nfsd4_process_open1(struct nfsd4_open *open)
+ 	status = nfs_ok;
+ 	renew_client(sop->so_client);
+ out:
+-	if (status && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
+-		status = nfserr_reclaim_bad;
+ 	return status;
+ }
+ 
+@@ -1688,17 +1686,11 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_sta
+ 
+ /* decrement seqid on successful reclaim, it will be bumped in encode_open */
+ static void
+-nfs4_set_claim_prev(struct nfsd4_open *open, int *status)
++nfs4_set_claim_prev(struct nfsd4_open *open)
+ {
+-	if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) {
+-		if (*status)
+-			*status = nfserr_reclaim_bad;
+-		else {
+-			open->op_stateowner->so_confirmed = 1;
+-			open->op_stateowner->so_client->cl_firststate = 1;
+-			open->op_stateowner->so_seqid--;
+-		}
+-	}
++	open->op_stateowner->so_confirmed = 1;
++	open->op_stateowner->so_client->cl_firststate = 1;
++	open->op_stateowner->so_seqid--;
+ }
+ 
+ /*
+@@ -1863,8 +1855,8 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
+ out:
+ 	if (fp)
+ 		put_nfs4_file(fp);
+-	/* CLAIM_PREVIOUS has different error returns */
+-	nfs4_set_claim_prev(open, &status);
++	if (status == 0 && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
++		nfs4_set_claim_prev(open);
+ 	/*
+ 	* To finish the open response, we just need to set the rflags.
+ 	*/
+@@ -2738,11 +2730,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
+ 		                        CHECK_FH | OPEN_STATE,
+ 		                        &open_sop, &open_stp,
+ 					&lock->v.new.clientid);
+-		if (status) {
+-			if (lock->lk_reclaim)
+-				status = nfserr_reclaim_bad;
++		if (status)
+ 			goto out;
+-		}
+ 		/* create lockowner and lock stateid */
+ 		fp = open_stp->st_file;
+ 		strhashval = lock_ownerstr_hashval(fp->fi_inode, 

commit 0dd395dc76071a06eea39839cc946c1241af3650
+Author: NeilBrown 
+Date:   Thu Jul 7 17:59:15 2005 -0700
+
+    [PATCH] nfsd4: ERR_GRACE should bump seqid on lock
+    
+    A GRACE or NOGRACE response to a lock request should also bump the sequence
+    id.  So we delay the handling of grace period errors till after we've found
+    the relevant owner.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 568d5deacac0..92968c94c6e6 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2706,11 +2706,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
+ 		(long long) lock->lk_offset,
+ 		(long long) lock->lk_length);
+ 
+-	if (nfs4_in_grace() && !lock->lk_reclaim)
+-		return nfserr_grace;
+-	if (!nfs4_in_grace() && lock->lk_reclaim)
+-		return nfserr_no_grace;
+-
+ 	if (check_lock_length(lock->lk_offset, lock->lk_length))
+ 		 return nfserr_inval;
+ 
+@@ -2785,6 +2780,13 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
+ 		goto out;
+ 	}
+ 
++	status = nfserr_grace;
++	if (nfs4_in_grace() && !lock->lk_reclaim)
++		goto out;
++	status = nfserr_no_grace;
++	if (!nfs4_in_grace() && lock->lk_reclaim)
++		goto out;
++
+ 	locks_init_lock(&file_lock);
+ 	switch (lock->lk_type) {
+ 		case NFS4_READ_LT:

commit b648330a1d741d5df8a5076b2a0a2519c69c8f41
+Author: NeilBrown 
+Date:   Thu Jul 7 17:59:15 2005 -0700
+
+    [PATCH] nfsd4: ERR_GRACE should bump seqid on open
+    
+    The GRACE and NOGRACE errors should bump the sequence id on open.  So we delay
+    the handling of these errors until nfsd4_process_open2, at which point we've
+    set the open owner, so the encode routine will be able to bump the sequence
+    id.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index d71f14517b9c..e08edc17c6a0 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -169,12 +169,6 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
+ 		(int)open->op_fname.len, open->op_fname.data,
+ 		open->op_stateowner);
+ 
+-	if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
+-		return nfserr_grace;
+-
+-	if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
+-		return nfserr_no_grace;
+-
+ 	/* This check required by spec. */
+ 	if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
+ 		return nfserr_inval;
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index e388c9070de4..568d5deacac0 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1790,6 +1790,12 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
+ 	struct nfs4_delegation *dp = NULL;
+ 	int status;
+ 
++	if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
++		return nfserr_grace;
++
++	if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
++		return nfserr_no_grace;
++
+ 	status = nfserr_inval;
+ 	if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny))
+ 		goto out;

commit 0fa822e452084032b8495ca0d8e0199329847815
+Author: NeilBrown 
+Date:   Thu Jul 7 17:59:14 2005 -0700
+
+    [PATCH] nfsd4: fix release_lockowner
+    
+    We oops in list_for_each_entry(), because release_stateowner frees something
+    on the list we're traversing.
+    
+    Signed-off-by: Andy Adamson 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 9f9db40b5666..e388c9070de4 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -3084,7 +3084,12 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *
+ 	 * of the lockowner state released; so don't release any until all
+ 	 * have been checked. */
+ 	status = nfs_ok;
+-	list_for_each_entry(sop, &matches, so_perclient) {
++	while (!list_empty(&matches)) {
++		sop = list_entry(matches.next, struct nfs4_stateowner,
++								so_perclient);
++		/* unhash_stateowner deletes so_perclient only
++		 * for openowners. */
++		list_del(&sop->so_perclient);
+ 		release_stateowner(sop);
+ 	}
+ out:

commit 67be431350941765e211eeed237c12def3aaba70
+Author: NeilBrown 
+Date:   Thu Jul 7 17:59:13 2005 -0700
+
+    [PATCH] nfsd4: prevent multiple unlinks of recovery directories
+    
+    Make sure we don't try to delete client recovery directories multiple times;
+    fixes some spurious error messages.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
+index 53abb333732e..57ed50fe7f85 100644
+--- a/fs/nfsd/nfs4recover.c
++++ b/fs/nfsd/nfs4recover.c
+@@ -316,6 +316,7 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
+ 	if (!rec_dir_init || !clp->cl_firststate)
+ 		return;
+ 
++	clp->cl_firststate = 0;
+ 	nfs4_save_user(&uid, &gid);
+ 	status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1);
+ 	nfs4_reset_user(uid, gid);

commit cdc5524e8a257b1c91dd8e4cdfbab979f4e17a60
+Author: NeilBrown 
+Date:   Thu Jul 7 17:59:12 2005 -0700
+
+    [PATCH] nfsd4: lookup_one_len takes i_sem
+    
+    Oops, this lookup_one_len needs the i_sem.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
+index bb40083b6b7d..53abb333732e 100644
+--- a/fs/nfsd/nfs4recover.c
++++ b/fs/nfsd/nfs4recover.c
+@@ -289,7 +289,9 @@ nfsd4_unlink_clid_dir(char *name, int namlen)
+ 
+ 	dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name);
+ 
++	down(&rec_dir.dentry->d_inode->i_sem);
+ 	dentry = lookup_one_len(name, rec_dir.dentry, namlen);
++	up(&rec_dir.dentry->d_inode->i_sem);
+ 	if (IS_ERR(dentry)) {
+ 		status = PTR_ERR(dentry);
+ 		return status;

commit a6ccbbb8865101d83c2e716f08feae1da1c48584
+Author: NeilBrown 
+Date:   Thu Jul 7 17:59:11 2005 -0700
+
+    [PATCH] nfsd4: fix sync'ing of recovery directory
+    
+    We need to fsync the recovery directory after writing to it, but we weren't
+    doing this correctly.  (For example, we weren't taking the i_sem when calling
+    ->fsync().)
+    
+    Just reuse the existing nfsd fsync code instead.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
+index 095f1740f3ae..bb40083b6b7d 100644
+--- a/fs/nfsd/nfs4recover.c
++++ b/fs/nfsd/nfs4recover.c
+@@ -119,25 +119,12 @@ nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname)
+ 	return status;
+ }
+ 
+-static int
+-nfsd4_rec_fsync(struct dentry *dentry)
++static void
++nfsd4_sync_rec_dir(void)
+ {
+-	struct file *filp;
+-	int status = nfs_ok;
+-
+-	dprintk("NFSD: nfs4_fsync_rec_dir\n");
+-	filp = dentry_open(dget(dentry), mntget(rec_dir.mnt), O_RDWR);
+-	if (IS_ERR(filp)) {
+-		status = PTR_ERR(filp);
+-		goto out;
+-	}
+-	if (filp->f_op && filp->f_op->fsync)
+-		status = filp->f_op->fsync(filp, filp->f_dentry, 0);
+-	fput(filp);
+-out:
+-	if (status)
+-		printk("nfsd4: unable to sync recovery directory\n");
+-	return status;
++	down(&rec_dir.dentry->d_inode->i_sem);
++	nfsd_sync_dir(rec_dir.dentry);
++	up(&rec_dir.dentry->d_inode->i_sem);
+ }
+ 
+ int
+@@ -176,7 +163,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
+ 	up(&rec_dir.dentry->d_inode->i_sem);
+ 	if (status == 0) {
+ 		clp->cl_firststate = 1;
+-		status = nfsd4_rec_fsync(rec_dir.dentry);
++		nfsd4_sync_rec_dir();
+ 	}
+ 	nfs4_reset_user(uid, gid);
+ 	dprintk("NFSD: nfsd4_create_clid_dir returns %d\n", status);
+@@ -331,7 +318,7 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
+ 	status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1);
+ 	nfs4_reset_user(uid, gid);
+ 	if (status == 0)
+-		status = nfsd4_rec_fsync(rec_dir.dentry);
++		nfsd4_sync_rec_dir();
+ 	if (status)
+ 		printk("NFSD: Failed to remove expired client state directory"
+ 				" %.*s\n", HEXDIR_LEN, clp->cl_recdir);
+@@ -362,7 +349,7 @@ nfsd4_recdir_purge_old(void) {
+ 		return;
+ 	status = nfsd4_list_rec_dir(rec_dir.dentry, purge_old);
+ 	if (status == 0)
+-		status = nfsd4_rec_fsync(rec_dir.dentry);
++		nfsd4_sync_rec_dir();
+ 	if (status)
+ 		printk("nfsd4: failed to purge old clients from recovery"
+ 			" directory %s\n", rec_dir.dentry->d_name.name);
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index be24ead89d94..5e0bf3917607 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -733,7 +733,7 @@ nfsd_sync(struct file *filp)
+ 	up(&inode->i_sem);
+ }
+ 
+-static void
++void
+ nfsd_sync_dir(struct dentry *dp)
+ {
+ 	nfsd_dosync(NULL, dp, dp->d_inode->i_fop);
+diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
+index 5791dfd30dd0..c2da1b62d416 100644
+--- a/include/linux/nfsd/nfsd.h
++++ b/include/linux/nfsd/nfsd.h
+@@ -124,6 +124,7 @@ int		nfsd_statfs(struct svc_rqst *, struct svc_fh *,
+ 
+ int		nfsd_notify_change(struct inode *, struct iattr *);
+ int		nfsd_permission(struct svc_export *, struct dentry *, int);
++void		nfsd_sync_dir(struct dentry *dp);
+ 
+ #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
+ #ifdef CONFIG_NFSD_V2_ACL

commit 463090294e1e460cf97f5ade376d4b1e62bc5263
+Author: NeilBrown 
+Date:   Thu Jul 7 17:59:10 2005 -0700
+
+    [PATCH] nfsd4: reboot recovery fix
+    
+    We need to remove the recovery directory here too.  (This chunk just got lost
+    somehow in the process of commuting the reboot recovery patches past the other
+    patches.)
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 89e36526d7f2..9f9db40b5666 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -874,6 +874,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
+ 			  * change request correctly. */
+ 			atomic_set(&conf->cl_callback.cb_set, 0);
+ 			gen_confirm(conf);
++			nfsd4_remove_clid_dir(unconf);
+ 			expire_client(unconf);
+ 			status = nfs_ok;
+ 

commit f8b58edf3acf0dcc186b8330939000ecf709368a
+Author: Neil Brown 
+Date:   Mon Jun 27 22:29:34 2005 -0700
+
+    [PATCH] md: bio leak fix
+    
+    insert a missing bio_put when writting the md superblock.
+    
+    Without this we have a steady growth in the "bio" slab.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 3802f7a17f16..4a0c57db2b67 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -338,6 +338,7 @@ static int super_written(struct bio *bio, unsigned int bytes_done, int error)
+ 
+ 	if (atomic_dec_and_test(&rdev->mddev->pending_writes))
+ 		wake_up(&rdev->mddev->sb_wait);
++	bio_put(bio);
+ 	return 0;
+ }
+ 

commit 0964a3d3f1aa96468091924f6b0c391a46dc6d0b
+Author: NeilBrown 
+Date:   Thu Jun 23 22:04:32 2005 -0700
+
+    [PATCH] knfsd: nfsd4 reboot dirname fix
+    
+    Set the recovery directory via /proc/fs/nfsd/nfs4recoverydir.
+    
+    It may be changed any time, but is used only on startup.
+    
+    Signed-off-by: Andy Adamson 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
+index 2805c5245eac..095f1740f3ae 100644
+--- a/fs/nfsd/nfs4recover.c
++++ b/fs/nfsd/nfs4recover.c
+@@ -50,7 +50,6 @@
+ #define NFSDDBG_FACILITY                NFSDDBG_PROC
+ 
+ /* Globals */
+-char recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
+ static struct nameidata rec_dir;
+ static int rec_dir_init = 0;
+ 
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 6cca358cd650..89e36526d7f2 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -48,6 +48,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #define NFSDDBG_FACILITY                NFSDDBG_PROC
+ 
+@@ -71,7 +72,8 @@ static stateid_t onestateid;              /* bits all 1 */
+ static struct nfs4_stateid * find_stateid(stateid_t *stid, int flags);
+ static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid);
+ static void release_stateid_lockowners(struct nfs4_stateid *open_stp);
+-extern char recovery_dirname[];
++static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
++static void nfs4_set_recdir(char *recdir);
+ 
+ /* Locking:
+  *
+@@ -3224,8 +3226,10 @@ nfsd4_load_reboot_recovery_data(void)
+ {
+ 	int status;
+ 
+-	nfsd4_init_recdir(recovery_dirname);
++	nfs4_lock_state();
++	nfsd4_init_recdir(user_recovery_dirname);
+ 	status = nfsd4_recdir_load();
++	nfs4_unlock_state();
+ 	if (status)
+ 		printk("NFSD: Failure reading reboot recovery data\n");
+ }
+@@ -3329,6 +3333,35 @@ nfs4_state_shutdown(void)
+ 	nfs4_unlock_state();
+ }
+ 
++static void
++nfs4_set_recdir(char *recdir)
++{
++	nfs4_lock_state();
++	strcpy(user_recovery_dirname, recdir);
++	nfs4_unlock_state();
++}
++
++/*
++ * Change the NFSv4 recovery directory to recdir.
++ */
++int
++nfs4_reset_recoverydir(char *recdir)
++{
++	int status;
++	struct nameidata nd;
++
++	status = path_lookup(recdir, LOOKUP_FOLLOW, &nd);
++	if (status)
++		return status;
++	status = -ENOTDIR;
++	if (S_ISDIR(nd.dentry->d_inode->i_mode)) {
++		nfs4_set_recdir(recdir);
++		status = 0;
++	}
++	path_release(&nd);
++	return status;
++}
++
+ /*
+  * Called when leasetime is changed.
+  *
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index 3da43a3ed32c..841c562991e8 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -51,6 +51,7 @@ enum {
+ 	NFSD_Fh,
+ 	NFSD_Threads,
+ 	NFSD_Leasetime,
++	NFSD_RecoveryDir,
+ };
+ 
+ /*
+@@ -66,6 +67,7 @@ static ssize_t write_getfs(struct file *file, char *buf, size_t size);
+ static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
+ static ssize_t write_threads(struct file *file, char *buf, size_t size);
+ static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
++static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
+ 
+ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
+ 	[NFSD_Svc] = write_svc,
+@@ -78,6 +80,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
+ 	[NFSD_Fh] = write_filehandle,
+ 	[NFSD_Threads] = write_threads,
+ 	[NFSD_Leasetime] = write_leasetime,
++	[NFSD_RecoveryDir] = write_recoverydir,
+ };
+ 
+ static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
+@@ -349,6 +352,25 @@ static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
+ 	return strlen(buf);
+ }
+ 
++static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
++{
++	char *mesg = buf;
++	char *recdir;
++	int len, status;
++
++	if (size > PATH_MAX || buf[size-1] != '\n')
++		return -EINVAL;
++	buf[size-1] = 0;
++
++	recdir = mesg;
++	len = qword_get(&mesg, recdir, size);
++	if (len <= 0)
++		return -EINVAL;
++
++	status = nfs4_reset_recoverydir(recdir);
++	return strlen(buf);
++}
++
+ /*----------------------------------------------------------------------------*/
+ /*
+  *	populating the filesystem.
+@@ -369,6 +391,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
+ 		[NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
+ #ifdef CONFIG_NFSD_V4
+ 		[NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
++		[NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR},
+ #endif
+ 		/* last one */ {""}
+ 	};
+diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
+index 21c6e9d86e4f..5791dfd30dd0 100644
+--- a/include/linux/nfsd/nfsd.h
++++ b/include/linux/nfsd/nfsd.h
+@@ -150,12 +150,14 @@ int nfs4_state_start(void);
+ void nfs4_state_shutdown(void);
+ time_t nfs4_lease_time(void);
+ void nfs4_reset_lease(time_t leasetime);
++int nfs4_reset_recoverydir(char *recdir);
+ #else
+ static inline void nfs4_state_init(void){};
+ static inline int nfs4_state_start(void){return 0;}
+ static inline void nfs4_state_shutdown(void){}
+ static inline time_t nfs4_lease_time(void){return 0;}
+ static inline void nfs4_reset_lease(time_t leasetime){}
++static inline int nfs4_reset_recoverydir(char *recdir) {return 0;}
+ #endif
+ 
+ /*

commit c7b9a45927e74c81d6562153f7fde9d32da00159
+Author: NeilBrown 
+Date:   Thu Jun 23 22:04:30 2005 -0700
+
+    [PATCH] knfsd: nfsd4: reboot recovery
+    
+    This patch adds the code to create and remove client subdirectories from the
+    recovery directory, as described in the previous patch comment.
+    
+    Signed-off-by: Andy Adamson 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
+index 2dc9851a1d37..2805c5245eac 100644
+--- a/fs/nfsd/nfs4recover.c
++++ b/fs/nfsd/nfs4recover.c
+@@ -120,6 +120,70 @@ nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname)
+ 	return status;
+ }
+ 
++static int
++nfsd4_rec_fsync(struct dentry *dentry)
++{
++	struct file *filp;
++	int status = nfs_ok;
++
++	dprintk("NFSD: nfs4_fsync_rec_dir\n");
++	filp = dentry_open(dget(dentry), mntget(rec_dir.mnt), O_RDWR);
++	if (IS_ERR(filp)) {
++		status = PTR_ERR(filp);
++		goto out;
++	}
++	if (filp->f_op && filp->f_op->fsync)
++		status = filp->f_op->fsync(filp, filp->f_dentry, 0);
++	fput(filp);
++out:
++	if (status)
++		printk("nfsd4: unable to sync recovery directory\n");
++	return status;
++}
++
++int
++nfsd4_create_clid_dir(struct nfs4_client *clp)
++{
++	char *dname = clp->cl_recdir;
++	struct dentry *dentry;
++	uid_t uid;
++	gid_t gid;
++	int status;
++
++	dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname);
++
++	if (!rec_dir_init || clp->cl_firststate)
++		return 0;
++
++	nfs4_save_user(&uid, &gid);
++
++	/* lock the parent */
++	down(&rec_dir.dentry->d_inode->i_sem);
++
++	dentry = lookup_one_len(dname, rec_dir.dentry, HEXDIR_LEN-1);
++	if (IS_ERR(dentry)) {
++		status = PTR_ERR(dentry);
++		goto out_unlock;
++	}
++	status = -EEXIST;
++	if (dentry->d_inode) {
++		dprintk("NFSD: nfsd4_create_clid_dir: DIRECTORY EXISTS\n");
++		goto out_put;
++	}
++	status = vfs_mkdir(rec_dir.dentry->d_inode, dentry, S_IRWXU);
++out_put:
++	dput(dentry);
++out_unlock:
++	up(&rec_dir.dentry->d_inode->i_sem);
++	if (status == 0) {
++		clp->cl_firststate = 1;
++		status = nfsd4_rec_fsync(rec_dir.dentry);
++	}
++	nfs4_reset_user(uid, gid);
++	dprintk("NFSD: nfsd4_create_clid_dir returns %d\n", status);
++	return status;
++}
++
+ typedef int (recdir_func)(struct dentry *, struct dentry *);
+ 
+ struct dentry_list {
+@@ -201,6 +265,111 @@ nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
+ 	return status;
+ }
+ 
++static int
++nfsd4_remove_clid_file(struct dentry *dir, struct dentry *dentry)
++{
++	int status;
++
++	if (!S_ISREG(dir->d_inode->i_mode)) {
++		printk("nfsd4: non-file found in client recovery directory\n");
++		return -EINVAL;
++	}
++	down(&dir->d_inode->i_sem);
++	status = vfs_unlink(dir->d_inode, dentry);
++	up(&dir->d_inode->i_sem);
++	return status;
++}
++
++static int
++nfsd4_clear_clid_dir(struct dentry *dir, struct dentry *dentry)
++{
++	int status;
++
++	/* For now this directory should already be empty, but we empty it of
++	 * any regular files anyway, just in case the directory was created by
++	 * a kernel from the future.... */
++	nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file);
++	down(&dir->d_inode->i_sem);
++	status = vfs_rmdir(dir->d_inode, dentry);
++	up(&dir->d_inode->i_sem);
++	return status;
++}
++
++static int
++nfsd4_unlink_clid_dir(char *name, int namlen)
++{
++	struct dentry *dentry;
++	int status;
++
++	dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name);
++
++	dentry = lookup_one_len(name, rec_dir.dentry, namlen);
++	if (IS_ERR(dentry)) {
++		status = PTR_ERR(dentry);
++		return status;
++	}
++	status = -ENOENT;
++	if (!dentry->d_inode)
++		goto out;
++
++	status = nfsd4_clear_clid_dir(rec_dir.dentry, dentry);
++out:
++	dput(dentry);
++	return status;
++}
++
++void
++nfsd4_remove_clid_dir(struct nfs4_client *clp)
++{
++	uid_t uid;
++	gid_t gid;
++	int status;
++
++	if (!rec_dir_init || !clp->cl_firststate)
++		return;
++
++	nfs4_save_user(&uid, &gid);
++	status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1);
++	nfs4_reset_user(uid, gid);
++	if (status == 0)
++		status = nfsd4_rec_fsync(rec_dir.dentry);
++	if (status)
++		printk("NFSD: Failed to remove expired client state directory"
++				" %.*s\n", HEXDIR_LEN, clp->cl_recdir);
++	return;
++}
++
++static int
++purge_old(struct dentry *parent, struct dentry *child)
++{
++	int status;
++
++	if (nfs4_has_reclaimed_state(child->d_name.name))
++		return nfs_ok;
++
++	status = nfsd4_clear_clid_dir(parent, child);
++	if (status)
++		printk("failed to remove client recovery directory %s\n",
++				child->d_name.name);
++	/* Keep trying, success or failure: */
++	return nfs_ok;
++}
++
++void
++nfsd4_recdir_purge_old(void) {
++	int status;
++
++	if (!rec_dir_init)
++		return;
++	status = nfsd4_list_rec_dir(rec_dir.dentry, purge_old);
++	if (status == 0)
++		status = nfsd4_rec_fsync(rec_dir.dentry);
++	if (status)
++		printk("nfsd4: failed to purge old clients from recovery"
++			" directory %s\n", rec_dir.dentry->d_name.name);
++	return;
++}
++
+ static int
+ load_recdir(struct dentry *parent, struct dentry *child)
+ {
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 6b9d23c39afe..6cca358cd650 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -905,6 +905,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
+ 			conf = find_confirmed_client_by_str(unconf->cl_recdir,
+ 									hash);
+ 			if (conf) {
++				nfsd4_remove_clid_dir(conf);
+ 				expire_client(conf);
+ 			}
+ 			move_to_confirmed(unconf);
+@@ -1691,6 +1692,7 @@ nfs4_set_claim_prev(struct nfsd4_open *open, int *status)
+ 			*status = nfserr_reclaim_bad;
+ 		else {
+ 			open->op_stateowner->so_confirmed = 1;
++			open->op_stateowner->so_client->cl_firststate = 1;
+ 			open->op_stateowner->so_seqid--;
+ 		}
+ 	}
+@@ -1903,6 +1905,7 @@ static void
+ end_grace(void)
+ {
+ 	dprintk("NFSD: end of grace period\n");
++	nfsd4_recdir_purge_old();
+ 	in_grace = 0;
+ }
+ 
+@@ -1932,6 +1935,7 @@ nfs4_laundromat(void)
+ 		}
+ 		dprintk("NFSD: purging unused client (clientid %08x)\n",
+ 			clp->cl_clientid.cl_id);
++		nfsd4_remove_clid_dir(clp);
+ 		expire_client(clp);
+ 	}
+ 	INIT_LIST_HEAD(&reaplist);
+@@ -2320,6 +2324,8 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs
+ 		         stp->st_stateid.si_stateownerid,
+ 		         stp->st_stateid.si_fileid,
+ 		         stp->st_stateid.si_generation);
++
++	nfsd4_create_clid_dir(sop->so_client);
+ out:
+ 	if (oc->oc_stateowner)
+ 		nfs4_get_stateowner(oc->oc_stateowner);
+@@ -3089,6 +3095,16 @@ alloc_reclaim(void)
+ 	return kmalloc(sizeof(struct nfs4_client_reclaim), GFP_KERNEL);
+ }
+ 
++int
++nfs4_has_reclaimed_state(const char *name)
++{
++	unsigned int strhashval = clientstr_hashval(name);
++	struct nfs4_client *clp;
++
++	clp = find_confirmed_client_by_str(name, strhashval);
++	return clp ? 1 : 0;
++}
++
+ /*
+  * failure => all reset bets are off, nfserr_no_grace...
+  */
+diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
+index 19481ab122df..a84a3fa99be1 100644
+--- a/include/linux/nfsd/state.h
++++ b/include/linux/nfsd/state.h
+@@ -131,6 +131,7 @@ struct nfs4_client {
+ 	nfs4_verifier		cl_confirm;	/* generated by server */
+ 	struct nfs4_callback	cl_callback;    /* callback info */
+ 	atomic_t		cl_count;	/* ref count */
++	u32			cl_firststate;	/* recovery dir creation */
+ };
+ 
+ /* struct nfs4_client_reset
+@@ -282,6 +283,10 @@ extern void nfsd4_init_recdir(char *recdir_name);
+ extern int nfsd4_recdir_load(void);
+ extern void nfsd4_shutdown_recdir(void);
+ extern int nfs4_client_to_reclaim(const char *name);
++extern int nfs4_has_reclaimed_state(const char *name);
++extern void nfsd4_recdir_purge_old(void);
++extern int nfsd4_create_clid_dir(struct nfs4_client *clp);
++extern void nfsd4_remove_clid_dir(struct nfs4_client *clp);
+ 
+ static inline void
+ nfs4_put_stateowner(struct nfs4_stateowner *so)

commit 190e4fbf96037e5e526ba3210f2bcc2a3b6fe964
+Author: NeilBrown 
+Date:   Thu Jun 23 22:04:25 2005 -0700
+
+    [PATCH] knfsd: nfsd4: initialize recovery directory
+    
+    NFSv4 clients are required to know what state they have on the server so that
+    they can reclaim it on server reboot.  However, it is possible for
+    pathalogical combinations of server reboots and network partitions to leave a
+    client in a state where it cannot know whether it has lost its state on the
+    server.
+    
+    For this reason, rfc3530 requires that we store some information about clients
+    to stable storage.
+    
+    So we maintain a directory /var/lib/nfs/v4recovery with a subdirectory for
+    each client with active state.  We leave open the possibility of including
+    files underneath each such subdirectory with information about the client, but
+    for now the subdirectories are empty.
+    
+    We create a client subdirectory whenever a client makes its first non-reclaim
+    open_confirm.
+    
+    We remove a client subdirectory whenever either
+            a) its lease expires, or
+            b) the grace period ends without it reclaiming anything.
+    When handling reclaims, we allow the reclaim if and only if the client doing
+    the reclaim has a subdirectory.
+    
+    This patch adds just the code to scan the recovery directory on nfsd startup.
+    
+    Signed-off-by: Andy Adamson 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
+index 841a305d7948..2dc9851a1d37 100644
+--- a/fs/nfsd/nfs4recover.c
++++ b/fs/nfsd/nfs4recover.c
+@@ -39,6 +39,9 @@
+ #include 
+ #include 
+ #include 
++#include 
++#include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -46,6 +49,27 @@
+ 
+ #define NFSDDBG_FACILITY                NFSDDBG_PROC
+ 
++/* Globals */
++char recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
++static struct nameidata rec_dir;
++static int rec_dir_init = 0;
++
++static void
++nfs4_save_user(uid_t *saveuid, gid_t *savegid)
++{
++	*saveuid = current->fsuid;
++	*savegid = current->fsgid;
++	current->fsuid = 0;
++	current->fsgid = 0;
++}
++
++static void
++nfs4_reset_user(uid_t saveuid, gid_t savegid)
++{
++	current->fsuid = saveuid;
++	current->fsgid = savegid;
++}
++
+ static void
+ md5_to_hex(char *out, char *md5)
+ {
+@@ -95,3 +119,145 @@ nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname)
+ 		crypto_free_tfm(tfm);
+ 	return status;
+ }
++
++typedef int (recdir_func)(struct dentry *, struct dentry *);
++
++struct dentry_list {
++	struct dentry *dentry;
++	struct list_head list;
++};
++
++struct dentry_list_arg {
++	struct list_head dentries;
++	struct dentry *parent;
++};
++
++static int
++nfsd4_build_dentrylist(void *arg, const char *name, int namlen,
++		loff_t offset, ino_t ino, unsigned int d_type)
++{
++	struct dentry_list_arg *dla = arg;
++	struct list_head *dentries = &dla->dentries;
++	struct dentry *parent = dla->parent;
++	struct dentry *dentry;
++	struct dentry_list *child;
++
++	if (name && isdotent(name, namlen))
++		return nfs_ok;
++	dentry = lookup_one_len(name, parent, namlen);
++	if (IS_ERR(dentry))
++		return PTR_ERR(dentry);
++	child = kmalloc(sizeof(*child), GFP_KERNEL);
++	if (child == NULL)
++		return -ENOMEM;
++	child->dentry = dentry;
++	list_add(&child->list, dentries);
++	return 0;
++}
++
++static int
++nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
++{
++	struct file *filp;
++	struct dentry_list_arg dla = {
++		.parent = dir,
++	};
++	struct list_head *dentries = &dla.dentries;
++	struct dentry_list *child;
++	uid_t uid;
++	gid_t gid;
++	int status;
++
++	if (!rec_dir_init)
++		return 0;
++
++	nfs4_save_user(&uid, &gid);
++
++	filp = dentry_open(dget(dir), mntget(rec_dir.mnt),
++			O_RDWR);
++	status = PTR_ERR(filp);
++	if (IS_ERR(filp))
++		goto out;
++	INIT_LIST_HEAD(dentries);
++	status = vfs_readdir(filp, nfsd4_build_dentrylist, &dla);
++	fput(filp);
++	while (!list_empty(dentries)) {
++		child = list_entry(dentries->next, struct dentry_list, list);
++		status = f(dir, child->dentry);
++		if (status)
++			goto out;
++		list_del(&child->list);
++		dput(child->dentry);
++		kfree(child);
++	}
++out:
++	while (!list_empty(dentries)) {
++		child = list_entry(dentries->next, struct dentry_list, list);
++		list_del(&child->list);
++		dput(child->dentry);
++		kfree(child);
++	}
++	nfs4_reset_user(uid, gid);
++	return status;
++}
++
++static int
++load_recdir(struct dentry *parent, struct dentry *child)
++{
++	if (child->d_name.len != HEXDIR_LEN - 1) {
++		printk("nfsd4: illegal name %s in recovery directory\n",
++				child->d_name.name);
++		/* Keep trying; maybe the others are OK: */
++		return nfs_ok;
++	}
++	nfs4_client_to_reclaim(child->d_name.name);
++	return nfs_ok;
++}
++
++int
++nfsd4_recdir_load(void) {
++	int status;
++
++	status = nfsd4_list_rec_dir(rec_dir.dentry, load_recdir);
++	if (status)
++		printk("nfsd4: failed loading clients from recovery"
++			" directory %s\n", rec_dir.dentry->d_name.name);
++	return status;
++}
++
++/*
++ * Hold reference to the recovery directory.
++ */
++
++void
++nfsd4_init_recdir(char *rec_dirname)
++{
++	uid_t			uid = 0;
++	gid_t			gid = 0;
++	int 			status;
++
++	printk("NFSD: Using %s as the NFSv4 state recovery directory\n",
++			rec_dirname);
++
++	BUG_ON(rec_dir_init);
++
++	nfs4_save_user(&uid, &gid);
++
++	status = path_lookup(rec_dirname, LOOKUP_FOLLOW, &rec_dir);
++	if (status == -ENOENT)
++		printk("NFSD: recovery directory %s doesn't exist\n",
++				rec_dirname);
++
++	if (!status)
++		rec_dir_init = 1;
++	nfs4_reset_user(uid, gid);
++}
++
++void
++nfsd4_shutdown_recdir(void)
++{
++	if (!rec_dir_init)
++		return;
++	rec_dir_init = 0;
++	path_release(&rec_dir);
++}
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 0b47a97e953d..6b9d23c39afe 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -71,6 +71,7 @@ static stateid_t onestateid;              /* bits all 1 */
+ static struct nfs4_stateid * find_stateid(stateid_t *stid, int flags);
+ static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid);
+ static void release_stateid_lockowners(struct nfs4_stateid *open_stp);
++extern char recovery_dirname[];
+ 
+ /* Locking:
+  *
+@@ -3091,8 +3092,8 @@ alloc_reclaim(void)
+ /*
+  * failure => all reset bets are off, nfserr_no_grace...
+  */
+-static int
+-nfs4_client_to_reclaim(char *name)
++int
++nfs4_client_to_reclaim(const char *name)
+ {
+ 	unsigned int strhashval;
+ 	struct nfs4_client_reclaim *crp = NULL;
+@@ -3202,6 +3203,17 @@ nfs4_state_init(void)
+ 	reclaim_str_hashtbl_size = 0;
+ }
+ 
++static void
++nfsd4_load_reboot_recovery_data(void)
++{
++	int status;
++
++	nfsd4_init_recdir(recovery_dirname);
++	status = nfsd4_recdir_load();
++	if (status)
++		printk("NFSD: Failure reading reboot recovery data\n");
++}
++
+ /* initialization to perform when the nfsd service is started: */
+ 
+ static void
+@@ -3228,6 +3240,7 @@ nfs4_state_start(void)
+ 	status = nfsd4_init_slabs();
+ 	if (status)
+ 		return status;
++	nfsd4_load_reboot_recovery_data();
+ 	__nfs4_state_start();
+ 	nfs4_init = 1;
+ 	return 0;
+@@ -3286,6 +3299,7 @@ __nfs4_state_shutdown(void)
+ 	cancel_delayed_work(&laundromat_work);
+ 	flush_workqueue(laundry_wq);
+ 	destroy_workqueue(laundry_wq);
++	nfsd4_shutdown_recdir();
+ 	nfs4_init = 0;
+ }
+ 
+diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
+index 83d29ec03a58..19481ab122df 100644
+--- a/include/linux/nfsd/state.h
++++ b/include/linux/nfsd/state.h
+@@ -278,6 +278,10 @@ extern void nfsd4_probe_callback(struct nfs4_client *clp);
+ extern void nfsd4_cb_recall(struct nfs4_delegation *dp);
+ extern void nfs4_put_delegation(struct nfs4_delegation *dp);
+ extern int nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname);
++extern void nfsd4_init_recdir(char *recdir_name);
++extern int nfsd4_recdir_load(void);
++extern void nfsd4_shutdown_recdir(void);
++extern int nfs4_client_to_reclaim(const char *name);
+ 
+ static inline void
+ nfs4_put_stateowner(struct nfs4_stateowner *so)

commit cb36d6345752fa24827044c68e15f6708a40d9f6
+Author: NeilBrown 
+Date:   Thu Jun 23 22:04:23 2005 -0700
+
+    [PATCH] knfsd: nfsd4: remove cb_parsed
+    
+    The cb_parsed field is only used by probe_callback, to determine whether the
+    callback information has been filled in by setclientid.  But there is no way
+    that probe_callback() can be called without that having already happened, so
+    that check is superfluous, as is cb_parsed.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 68bb245491f6..583c0710e45e 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -386,9 +386,7 @@ nfsd4_probe_callback(struct nfs4_client *clp)
+ 	char                    hostname[32];
+ 	int status;
+ 
+-	dprintk("NFSD: probe_callback. cb_parsed %d cb_set %d\n",
+-			cb->cb_parsed, atomic_read(&cb->cb_set));
+-	if (!cb->cb_parsed || atomic_read(&cb->cb_set))
++	if (atomic_read(&cb->cb_set))
+ 		return;
+ 
+ 	/* Initialize address */
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 26d00465c28a..0b47a97e953d 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -377,7 +377,6 @@ create_client(struct xdr_netobj name, char *recdir) {
+ 	memcpy(clp->cl_recdir, recdir, HEXDIR_LEN);
+ 	atomic_set(&clp->cl_count, 1);
+ 	atomic_set(&clp->cl_callback.cb_set, 0);
+-	clp->cl_callback.cb_parsed = 0;
+ 	INIT_LIST_HEAD(&clp->cl_idhash);
+ 	INIT_LIST_HEAD(&clp->cl_strhash);
+ 	INIT_LIST_HEAD(&clp->cl_openowners);
+@@ -620,14 +619,12 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
+ 		goto out_err;
+ 	cb->cb_prog = se->se_callback_prog;
+ 	cb->cb_ident = se->se_callback_ident;
+-	cb->cb_parsed = 1;
+ 	return;
+ out_err:
+ 	printk(KERN_INFO "NFSD: this client (clientid %08x/%08x) "
+ 		"will not receive delegations\n",
+ 		clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
+ 
+-	cb->cb_parsed = 0;
+ 	return;
+ }
+ 
+@@ -872,7 +869,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
+ 		else {
+ 			/* XXX: We just turn off callbacks until we can handle
+ 			  * change request correctly. */
+-			conf->cl_callback.cb_parsed = 0;
++			atomic_set(&conf->cl_callback.cb_set, 0);
+ 			gen_confirm(conf);
+ 			expire_client(unconf);
+ 			status = nfs_ok;
+diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
+index f4f27b76ee64..83d29ec03a58 100644
+--- a/include/linux/nfsd/state.h
++++ b/include/linux/nfsd/state.h
+@@ -92,7 +92,6 @@ struct nfs4_delegation {
+ /* client delegation callback info */
+ struct nfs4_callback {
+ 	/* SETCLIENTID info */
+-	u32			cb_parsed;  /* addr parsed */
+ 	u32                     cb_addr;
+ 	unsigned short          cb_port;
+ 	u32                     cb_prog;

commit 3e9e3dbe0fe36c824ce2c5d7b05997c87a64bbdc
+Author: NeilBrown 
+Date:   Thu Jun 23 22:04:20 2005 -0700
+
+    [PATCH] knfsd: nfsd4: allow multiple lockowners
+    
+    >From the language of rfc3530 section 8.1.3 (e.g., the suggestion that a
+    "process id" might be a reasonable lockowner value) it's conceivable that a
+    client might want to use the same lockowner string on multiple files, so we may
+    as well allow that.  We expect each use of open_to_lockowner to create a
+    distinct seqid stream, though.
+    
+    For now we're also allowing multiple uses of open_to_lockowner with the same
+    open, though it seems unlikely clients would actually do that.
+    
+    Also add a comment reminding myself of some very non-scalable data structures.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 22e76e3f06a5..26d00465c28a 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2583,22 +2583,6 @@ nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny)
+ 		deny->ld_type = NFS4_WRITE_LT;
+ }
+ 
+-static struct nfs4_stateowner *
+-find_lockstateowner(struct xdr_netobj *owner, clientid_t *clid)
+-{
+-	struct nfs4_stateowner *local = NULL;
+-	int i;
+-
+-	for (i = 0; i < LOCK_HASH_SIZE; i++) {
+-		list_for_each_entry(local, &lock_ownerid_hashtbl[i], so_idhash) {
+-			if (!cmp_owner_str(local, owner, clid))
+-				continue;
+-			return local;
+-		}
+-	}
+-	return NULL;
+-}
+-
+ static struct nfs4_stateowner *
+ find_lockstateowner_str(struct inode *inode, clientid_t *clid,
+ 		struct xdr_netobj *owner)
+@@ -2697,7 +2681,7 @@ check_lock_length(u64 offset, u64 length)
+ int
+ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock)
+ {
+-	struct nfs4_stateowner *lock_sop = NULL, *open_sop = NULL;
++	struct nfs4_stateowner *open_sop = NULL;
+ 	struct nfs4_stateid *lock_stp;
+ 	struct file *filp;
+ 	struct file_lock file_lock;
+@@ -2756,16 +2740,9 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
+ 		strhashval = lock_ownerstr_hashval(fp->fi_inode, 
+ 				open_sop->so_client->cl_clientid.cl_id, 
+ 				&lock->v.new.owner);
+-		/* 
+-		 * If we already have this lock owner, the client is in 
+-		 * error (or our bookeeping is wrong!) 
+-		 * for asking for a 'new lock'.
+-		 */
+-		status = nfserr_bad_stateid;
+-		lock_sop = find_lockstateowner(&lock->v.new.owner,
+-						&lock->v.new.clientid);
+-		if (lock_sop)
+-			goto out;
++		/* XXX: Do we need to check for duplicate stateowners on
++		 * the same file, or should they just be allowed (and
++		 * create new stateids)? */
+ 		status = nfserr_resource;
+ 		if (!(lock->lk_stateowner = alloc_init_lock_stateowner(strhashval, open_sop->so_client, open_stp, lock)))
+ 			goto out;
+@@ -3056,8 +3033,11 @@ int
+ nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *rlockowner)
+ {
+ 	clientid_t *clid = &rlockowner->rl_clientid;
+-	struct nfs4_stateowner *local = NULL;
++	struct nfs4_stateowner *sop;
++	struct nfs4_stateid *stp;
+ 	struct xdr_netobj *owner = &rlockowner->rl_owner;
++	struct list_head matches;
++	int i;
+ 	int status;
+ 
+ 	dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n",
+@@ -3073,22 +3053,32 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *
+ 
+ 	nfs4_lock_state();
+ 
+-	status = nfs_ok;
+-	local = find_lockstateowner(owner, clid);
+-	if (local) {
+-		struct nfs4_stateid *stp;
+-
+-		/* check for any locks held by any stateid
+-		 * associated with the (lock) stateowner */
+-		status = nfserr_locks_held;
+-		list_for_each_entry(stp, &local->so_stateids,
+-				st_perstateowner) {
+-			if (check_for_locks(stp->st_vfs_file, local))
+-				goto out;
++	status = nfserr_locks_held;
++	/* XXX: we're doing a linear search through all the lockowners.
++	 * Yipes!  For now we'll just hope clients aren't really using
++	 * release_lockowner much, but eventually we have to fix these
++	 * data structures. */
++	INIT_LIST_HEAD(&matches);
++	for (i = 0; i < LOCK_HASH_SIZE; i++) {
++		list_for_each_entry(sop, &lock_ownerid_hashtbl[i], so_idhash) {
++			if (!cmp_owner_str(sop, owner, clid))
++				continue;
++			list_for_each_entry(stp, &sop->so_stateids,
++					st_perstateowner) {
++				if (check_for_locks(stp->st_vfs_file, sop))
++					goto out;
++				/* Note: so_perclient unused for lockowners,
++				 * so it's OK to fool with here. */
++				list_add(&sop->so_perclient, &matches);
++			}
+ 		}
+-		/* no locks held by (lock) stateowner */
+-		status = nfs_ok;
+-		release_stateowner(local);
++	}
++	/* Clients probably won't expect us to return with some (but not all)
++	 * of the lockowner state released; so don't release any until all
++	 * have been checked. */
++	status = nfs_ok;
++	list_for_each_entry(sop, &matches, so_perclient) {
++		release_stateowner(sop);
+ 	}
+ out:
+ 	nfs4_unlock_state();

commit ea1da636e956ad1591a74904f23d98bbc26a644b
+Author: NeilBrown 
+Date:   Thu Jun 23 22:04:17 2005 -0700
+
+    [PATCH] knfsd: nfsd4: rename state list fields
+    
+    Trivial renaming patch:
+    
+    I can never remember, while looking at various lists relating the nfsd4 state
+    structures, which are the "heads" and which are items on other lists, or which
+    structures are actually on the various lists.  The following convention helps
+    me: given structures foo and bar, with foo containing the head of a list of
+    bars, use "bars" for the name of the head of the list contained in the struct
+    foo, and use "per_foo" for the entries in the struct bars.
+    
+    Already done for struct nfs4_file; go ahead and do it for the other nfsd4
+    state structures.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 884115198116..22e76e3f06a5 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -154,8 +154,8 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
+ 	dp = kmem_cache_alloc(deleg_slab, GFP_KERNEL);
+ 	if (dp == NULL)
+ 		return dp;
+-	INIT_LIST_HEAD(&dp->dl_del_perfile);
+-	INIT_LIST_HEAD(&dp->dl_del_perclnt);
++	INIT_LIST_HEAD(&dp->dl_perfile);
++	INIT_LIST_HEAD(&dp->dl_perclnt);
+ 	INIT_LIST_HEAD(&dp->dl_recall_lru);
+ 	dp->dl_client = clp;
+ 	get_nfs4_file(fp);
+@@ -176,8 +176,8 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
+ 		        current_fh->fh_handle.fh_size);
+ 	dp->dl_time = 0;
+ 	atomic_set(&dp->dl_count, 1);
+-	list_add(&dp->dl_del_perfile, &fp->fi_delegations);
+-	list_add(&dp->dl_del_perclnt, &clp->cl_del_perclnt);
++	list_add(&dp->dl_perfile, &fp->fi_delegations);
++	list_add(&dp->dl_perclnt, &clp->cl_delegations);
+ 	return dp;
+ }
+ 
+@@ -214,8 +214,8 @@ nfs4_close_delegation(struct nfs4_delegation *dp)
+ static void
+ unhash_delegation(struct nfs4_delegation *dp)
+ {
+-	list_del_init(&dp->dl_del_perfile);
+-	list_del_init(&dp->dl_del_perclnt);
++	list_del_init(&dp->dl_perfile);
++	list_del_init(&dp->dl_perclnt);
+ 	spin_lock(&recall_lock);
+ 	list_del_init(&dp->dl_recall_lru);
+ 	spin_unlock(&recall_lock);
+@@ -345,11 +345,11 @@ expire_client(struct nfs4_client *clp)
+ 
+ 	INIT_LIST_HEAD(&reaplist);
+ 	spin_lock(&recall_lock);
+-	while (!list_empty(&clp->cl_del_perclnt)) {
+-		dp = list_entry(clp->cl_del_perclnt.next, struct nfs4_delegation, dl_del_perclnt);
++	while (!list_empty(&clp->cl_delegations)) {
++		dp = list_entry(clp->cl_delegations.next, struct nfs4_delegation, dl_perclnt);
+ 		dprintk("NFSD: expire client. dp %p, fp %p\n", dp,
+ 				dp->dl_flock);
+-		list_del_init(&dp->dl_del_perclnt);
++		list_del_init(&dp->dl_perclnt);
+ 		list_move(&dp->dl_recall_lru, &reaplist);
+ 	}
+ 	spin_unlock(&recall_lock);
+@@ -361,8 +361,8 @@ expire_client(struct nfs4_client *clp)
+ 	list_del(&clp->cl_idhash);
+ 	list_del(&clp->cl_strhash);
+ 	list_del(&clp->cl_lru);
+-	while (!list_empty(&clp->cl_perclient)) {
+-		sop = list_entry(clp->cl_perclient.next, struct nfs4_stateowner, so_perclient);
++	while (!list_empty(&clp->cl_openowners)) {
++		sop = list_entry(clp->cl_openowners.next, struct nfs4_stateowner, so_perclient);
+ 		release_stateowner(sop);
+ 	}
+ 	put_nfs4_client(clp);
+@@ -380,8 +380,8 @@ create_client(struct xdr_netobj name, char *recdir) {
+ 	clp->cl_callback.cb_parsed = 0;
+ 	INIT_LIST_HEAD(&clp->cl_idhash);
+ 	INIT_LIST_HEAD(&clp->cl_strhash);
+-	INIT_LIST_HEAD(&clp->cl_perclient);
+-	INIT_LIST_HEAD(&clp->cl_del_perclnt);
++	INIT_LIST_HEAD(&clp->cl_openowners);
++	INIT_LIST_HEAD(&clp->cl_delegations);
+ 	INIT_LIST_HEAD(&clp->cl_lru);
+ out:
+ 	return clp;
+@@ -1074,13 +1074,13 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
+ 	INIT_LIST_HEAD(&sop->so_idhash);
+ 	INIT_LIST_HEAD(&sop->so_strhash);
+ 	INIT_LIST_HEAD(&sop->so_perclient);
+-	INIT_LIST_HEAD(&sop->so_perfilestate);
+-	INIT_LIST_HEAD(&sop->so_perlockowner);  /* not used */
++	INIT_LIST_HEAD(&sop->so_stateids);
++	INIT_LIST_HEAD(&sop->so_perstateid);  /* not used */
+ 	INIT_LIST_HEAD(&sop->so_close_lru);
+ 	sop->so_time = 0;
+ 	list_add(&sop->so_idhash, &ownerid_hashtbl[idhashval]);
+ 	list_add(&sop->so_strhash, &ownerstr_hashtbl[strhashval]);
+-	list_add(&sop->so_perclient, &clp->cl_perclient);
++	list_add(&sop->so_perclient, &clp->cl_openowners);
+ 	sop->so_is_open_owner = 1;
+ 	sop->so_id = current_ownerid++;
+ 	sop->so_client = clp;
+@@ -1098,10 +1098,10 @@ release_stateid_lockowners(struct nfs4_stateid *open_stp)
+ {
+ 	struct nfs4_stateowner *lock_sop;
+ 
+-	while (!list_empty(&open_stp->st_perlockowner)) {
+-		lock_sop = list_entry(open_stp->st_perlockowner.next,
+-				struct nfs4_stateowner, so_perlockowner);
+-		/* list_del(&open_stp->st_perlockowner);  */
++	while (!list_empty(&open_stp->st_lockowners)) {
++		lock_sop = list_entry(open_stp->st_lockowners.next,
++				struct nfs4_stateowner, so_perstateid);
++		/* list_del(&open_stp->st_lockowners);  */
+ 		BUG_ON(lock_sop->so_is_open_owner);
+ 		release_stateowner(lock_sop);
+ 	}
+@@ -1116,10 +1116,10 @@ unhash_stateowner(struct nfs4_stateowner *sop)
+ 	list_del(&sop->so_strhash);
+ 	if (sop->so_is_open_owner)
+ 		list_del(&sop->so_perclient);
+-	list_del(&sop->so_perlockowner);
+-	while (!list_empty(&sop->so_perfilestate)) {
+-		stp = list_entry(sop->so_perfilestate.next, 
+-			struct nfs4_stateid, st_perfilestate);
++	list_del(&sop->so_perstateid);
++	while (!list_empty(&sop->so_stateids)) {
++		stp = list_entry(sop->so_stateids.next,
++			struct nfs4_stateid, st_perstateowner);
+ 		if (sop->so_is_open_owner)
+ 			release_stateid(stp, OPEN_STATE);
+ 		else
+@@ -1141,11 +1141,11 @@ init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *
+ 	unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id);
+ 
+ 	INIT_LIST_HEAD(&stp->st_hash);
+-	INIT_LIST_HEAD(&stp->st_perfilestate);
+-	INIT_LIST_HEAD(&stp->st_perlockowner);
++	INIT_LIST_HEAD(&stp->st_perstateowner);
++	INIT_LIST_HEAD(&stp->st_lockowners);
+ 	INIT_LIST_HEAD(&stp->st_perfile);
+ 	list_add(&stp->st_hash, &stateid_hashtbl[hashval]);
+-	list_add(&stp->st_perfilestate, &sop->so_perfilestate);
++	list_add(&stp->st_perstateowner, &sop->so_stateids);
+ 	list_add(&stp->st_perfile, &fp->fi_stateids);
+ 	stp->st_stateowner = sop;
+ 	get_nfs4_file(fp);
+@@ -1167,7 +1167,7 @@ release_stateid(struct nfs4_stateid *stp, int flags)
+ 
+ 	list_del(&stp->st_hash);
+ 	list_del(&stp->st_perfile);
+-	list_del(&stp->st_perfilestate);
++	list_del(&stp->st_perstateowner);
+ 	if (flags & OPEN_STATE) {
+ 		release_stateid_lockowners(stp);
+ 		stp->st_vfs_file = NULL;
+@@ -1201,7 +1201,7 @@ release_state_owner(struct nfs4_stateid *stp, int flag)
+ 	 * released by the laundromat service after the lease period
+ 	 * to enable us to handle CLOSE replay
+ 	 */
+-	if (sop->so_confirmed && list_empty(&sop->so_perfilestate))
++	if (sop->so_confirmed && list_empty(&sop->so_stateids))
+ 		move_to_close_lru(sop);
+ }
+ 
+@@ -1548,7 +1548,7 @@ find_delegation_file(struct nfs4_file *fp, stateid_t *stid)
+ {
+ 	struct nfs4_delegation *dp;
+ 
+-	list_for_each_entry(dp, &fp->fi_delegations, dl_del_perfile) {
++	list_for_each_entry(dp, &fp->fi_delegations, dl_perfile) {
+ 		if (dp->dl_stateid.si_stateownerid == stid->si_stateownerid)
+ 			return dp;
+ 	}
+@@ -1892,7 +1892,7 @@ nfsd4_renew(clientid_t *clid)
+ 	}
+ 	renew_client(clp);
+ 	status = nfserr_cb_path_down;
+-	if (!list_empty(&clp->cl_del_perclnt)
++	if (!list_empty(&clp->cl_delegations)
+ 			&& !atomic_read(&clp->cl_callback.cb_set))
+ 		goto out;
+ 	status = nfs_ok;
+@@ -2634,13 +2634,13 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
+ 	INIT_LIST_HEAD(&sop->so_idhash);
+ 	INIT_LIST_HEAD(&sop->so_strhash);
+ 	INIT_LIST_HEAD(&sop->so_perclient);
+-	INIT_LIST_HEAD(&sop->so_perfilestate);
+-	INIT_LIST_HEAD(&sop->so_perlockowner);
++	INIT_LIST_HEAD(&sop->so_stateids);
++	INIT_LIST_HEAD(&sop->so_perstateid);
+ 	INIT_LIST_HEAD(&sop->so_close_lru); /* not used */
+ 	sop->so_time = 0;
+ 	list_add(&sop->so_idhash, &lock_ownerid_hashtbl[idhashval]);
+ 	list_add(&sop->so_strhash, &lock_ownerstr_hashtbl[strhashval]);
+-	list_add(&sop->so_perlockowner, &open_stp->st_perlockowner);
++	list_add(&sop->so_perstateid, &open_stp->st_lockowners);
+ 	sop->so_is_open_owner = 0;
+ 	sop->so_id = current_ownerid++;
+ 	sop->so_client = clp;
+@@ -2664,11 +2664,11 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc
+ 		goto out;
+ 	INIT_LIST_HEAD(&stp->st_hash);
+ 	INIT_LIST_HEAD(&stp->st_perfile);
+-	INIT_LIST_HEAD(&stp->st_perfilestate);
+-	INIT_LIST_HEAD(&stp->st_perlockowner); /* not used */
++	INIT_LIST_HEAD(&stp->st_perstateowner);
++	INIT_LIST_HEAD(&stp->st_lockowners); /* not used */
+ 	list_add(&stp->st_hash, &lockstateid_hashtbl[hashval]);
+ 	list_add(&stp->st_perfile, &fp->fi_stateids);
+-	list_add(&stp->st_perfilestate, &sop->so_perfilestate);
++	list_add(&stp->st_perstateowner, &sop->so_stateids);
+ 	stp->st_stateowner = sop;
+ 	get_nfs4_file(fp);
+ 	stp->st_file = fp;
+@@ -3081,8 +3081,8 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *
+ 		/* check for any locks held by any stateid
+ 		 * associated with the (lock) stateowner */
+ 		status = nfserr_locks_held;
+-		list_for_each_entry(stp, &local->so_perfilestate,
+-				st_perfilestate) {
++		list_for_each_entry(stp, &local->so_stateids,
++				st_perstateowner) {
+ 			if (check_for_locks(stp->st_vfs_file, local))
+ 				goto out;
+ 		}
+diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
+index 0e18ae22127d..f4f27b76ee64 100644
+--- a/include/linux/nfsd/state.h
++++ b/include/linux/nfsd/state.h
+@@ -72,8 +72,8 @@ struct nfs4_cb_recall {
+ };
+ 
+ struct nfs4_delegation {
+-	struct list_head	dl_del_perfile; /* nfs4_file->fi_del_perfile */
+-	struct list_head	dl_del_perclnt; /* nfs4_client->cl_del_perclnt*/
++	struct list_head	dl_perfile;
++	struct list_head	dl_perclnt;
+ 	struct list_head	dl_recall_lru;  /* delegation recalled */
+ 	atomic_t		dl_count;       /* ref count */
+ 	struct nfs4_client	*dl_client;
+@@ -119,8 +119,8 @@ struct nfs4_callback {
+ struct nfs4_client {
+ 	struct list_head	cl_idhash; 	/* hash by cl_clientid.id */
+ 	struct list_head	cl_strhash; 	/* hash by cl_name */
+-	struct list_head	cl_perclient; 	/* list: stateowners */
+-	struct list_head	cl_del_perclnt; /* list: delegations */
++	struct list_head	cl_openowners;
++	struct list_head	cl_delegations;
+ 	struct list_head        cl_lru;         /* tail queue */
+ 	struct xdr_netobj	cl_name; 	/* id generated by client */
+ 	char                    cl_recdir[HEXDIR_LEN]; /* recovery dir */
+@@ -195,9 +195,9 @@ struct nfs4_stateowner {
+ 	struct kref		so_ref;
+ 	struct list_head        so_idhash;   /* hash by so_id */
+ 	struct list_head        so_strhash;   /* hash by op_name */
+-	struct list_head        so_perclient; /* nfs4_client->cl_perclient */
+-	struct list_head        so_perfilestate; /* list: nfs4_stateid */
+-	struct list_head        so_perlockowner; /* nfs4_stateid->st_perlockowner */
++	struct list_head        so_perclient;
++	struct list_head        so_stateids;
++	struct list_head        so_perstateid; /* for lockowners only */
+ 	struct list_head	so_close_lru; /* tail queue */
+ 	time_t			so_time; /* time of placement on so_close_lru */
+ 	int			so_is_open_owner; /* 1=openowner,0=lockowner */
+@@ -240,8 +240,8 @@ struct nfs4_file {
+ struct nfs4_stateid {
+ 	struct list_head              st_hash; 
+ 	struct list_head              st_perfile;
+-	struct list_head              st_perfilestate; 
+-	struct list_head              st_perlockowner;
++	struct list_head              st_perstateowner;
++	struct list_head              st_lockowners;
+ 	struct nfs4_stateowner      * st_stateowner;
+ 	struct nfs4_file            * st_file;
+ 	stateid_t                     st_stateid;

commit 21ab45a480ec7705d177e959ebf452d62340c004
+Author: NeilBrown 
+Date:   Thu Jun 23 22:04:14 2005 -0700
+
+    [PATCH] knfsd: nfsd4: miscellaneous setclientid_confirm cleanup
+    
+    Minor cleanup, remove some unnecessary printk's.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index f100eeab5458..884115198116 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -834,7 +834,7 @@ int
+ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm)
+ {
+ 	u32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
+-	struct nfs4_client *clp, *conf = NULL, *unconf = NULL;
++	struct nfs4_client *conf, *unconf;
+ 	nfs4_verifier confirm = setclientid_confirm->sc_confirm; 
+ 	clientid_t * clid = &setclientid_confirm->sc_clientid;
+ 	int status;
+@@ -847,28 +847,16 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
+ 	 */
+ 
+ 	nfs4_lock_state();
+-	clp = find_confirmed_client(clid);
+-	if (clp) {
+-		status = nfserr_clid_inuse;
+-		if (clp->cl_addr != ip_addr) { 
+-			printk("NFSD: setclientid: string in use by client"
+-			"(clientid %08x/%08x)\n",
+-			clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
+-			goto out;
+-		}
+-		conf = clp;
+-	}
+-	clp = find_unconfirmed_client(clid);
+-	if (clp) {
+-		status = nfserr_clid_inuse;
+-		if (clp->cl_addr != ip_addr) { 
+-			printk("NFSD: setclientid: string in use by client"
+-			"(clientid %08x/%08x)\n",
+-			clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
+-			goto out;
+-		}
+-		unconf = clp;
+-	}
++
++	conf = find_confirmed_client(clid);
++	unconf = find_unconfirmed_client(clid);
++
++	status = nfserr_clid_inuse;
++	if (conf && conf->cl_addr != ip_addr)
++		goto out;
++	if (unconf && unconf->cl_addr != ip_addr)
++		goto out;
++
+ 	if ((conf && unconf) && 
+ 	    (cmp_verf(&unconf->cl_confirm, &confirm)) &&
+ 	    (cmp_verf(&conf->cl_verifier, &unconf->cl_verifier)) &&
+@@ -884,9 +872,8 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
+ 		else {
+ 			/* XXX: We just turn off callbacks until we can handle
+ 			  * change request correctly. */
+-			clp = conf;
+-			clp->cl_callback.cb_parsed = 0;
+-			gen_confirm(clp);
++			conf->cl_callback.cb_parsed = 0;
++			gen_confirm(conf);
+ 			expire_client(unconf);
+ 			status = nfs_ok;
+ 
+@@ -901,12 +888,10 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
+ 		 * unconf->cl_name or unconf->cl_verifier don't match the
+ 		 * conf record.
+ 		 */
+-		if (!cmp_creds(&conf->cl_cred,&rqstp->rq_cred)) {
++		if (!cmp_creds(&conf->cl_cred,&rqstp->rq_cred))
+ 			status = nfserr_clid_inuse;
+-		} else {
+-			clp = conf;
++		else
+ 			status = nfs_ok;
+-		}
+ 	} else if (!conf && unconf
+ 			&& cmp_verf(&unconf->cl_confirm, &confirm)) {
+ 		/* CASE 3:
+@@ -924,8 +909,8 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
+ 			if (conf) {
+ 				expire_client(conf);
+ 			}
+-			clp = unconf;
+ 			move_to_confirmed(unconf);
++			conf = unconf;
+ 			status = nfs_ok;
+ 		}
+ 	} else if ((!conf || (conf && !cmp_verf(&conf->cl_confirm, &confirm)))
+@@ -944,7 +929,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
+ 	}
+ out:
+ 	if (!status)
+-		nfsd4_probe_callback(clp);
++		nfsd4_probe_callback(conf);
+ 	nfs4_unlock_state();
+ 	return status;
+ }

commit 7c79f7377cd4f2a50d51475f4c7966a3e60596a7
+Author: NeilBrown 
+Date:   Thu Jun 23 22:04:13 2005 -0700
+
+    [PATCH] knfsd: nfsd4: setclientid_confirm comments
+    
+    Trivial whitespace and comment fixes.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 9014dc2a632a..f100eeab5458 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -869,16 +869,16 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
+ 		}
+ 		unconf = clp;
+ 	}
+-	/* CASE 1: 
+-	* unconf record that matches input clientid and input confirm.
+-	* conf record that matches input clientid.
+-	* conf  and unconf records match names, verifiers 
+-	*/
+ 	if ((conf && unconf) && 
+ 	    (cmp_verf(&unconf->cl_confirm, &confirm)) &&
+ 	    (cmp_verf(&conf->cl_verifier, &unconf->cl_verifier)) &&
+ 	    (same_name(conf->cl_recdir,unconf->cl_recdir))  &&
+ 	    (!cmp_verf(&conf->cl_confirm, &unconf->cl_confirm))) {
++		/* CASE 1:
++		* unconf record that matches input clientid and input confirm.
++		* conf record that matches input clientid.
++		* conf and unconf records match names, verifiers
++		*/
+ 		if (!cmp_creds(&conf->cl_cred, &unconf->cl_cred)) 
+ 			status = nfserr_clid_inuse;
+ 		else {
+@@ -891,29 +891,29 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
+ 			status = nfs_ok;
+ 
+ 		}
+-	} 
+-	/* CASE 2:
+-	 * conf record that matches input clientid.
+-	 * if unconf record that matches input clientid, then unconf->cl_name
+-	 * or unconf->cl_verifier don't match the conf record.
+-	 */
+-	else if ((conf && !unconf) ||
++	} else if ((conf && !unconf) ||
+ 	    ((conf && unconf) && 
+ 	     (!cmp_verf(&conf->cl_verifier, &unconf->cl_verifier) ||
+ 	      !same_name(conf->cl_recdir, unconf->cl_recdir)))) {
++		/* CASE 2:
++		 * conf record that matches input clientid.
++		 * if unconf record matches input clientid, then
++		 * unconf->cl_name or unconf->cl_verifier don't match the
++		 * conf record.
++		 */
+ 		if (!cmp_creds(&conf->cl_cred,&rqstp->rq_cred)) {
+ 			status = nfserr_clid_inuse;
+ 		} else {
+ 			clp = conf;
+ 			status = nfs_ok;
+ 		}
+-	}
+-	/* CASE 3:
+-	 * conf record not found.
+-	 * unconf record found. 
+-	 * unconf->cl_confirm matches input confirm
+-	 */ 
+-	else if (!conf && unconf && cmp_verf(&unconf->cl_confirm, &confirm)) {
++	} else if (!conf && unconf
++			&& cmp_verf(&unconf->cl_confirm, &confirm)) {
++		/* CASE 3:
++		 * conf record not found.
++		 * unconf record found.
++		 * unconf->cl_confirm matches input confirm
++		 */
+ 		if (!cmp_creds(&unconf->cl_cred, &rqstp->rq_cred)) {
+ 			status = nfserr_clid_inuse;
+ 		} else {
+@@ -928,18 +928,17 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
+ 			move_to_confirmed(unconf);
+ 			status = nfs_ok;
+ 		}
+-	}
+-	/* CASE 4:
+-	 * conf record not found, or if conf, then conf->cl_confirm does not
+-	 * match input confirm.
+-	 * unconf record not found, or if unconf, then unconf->cl_confirm 
+-	 * does not match input confirm.
+-	 */
+-	else if ((!conf || (conf && !cmp_verf(&conf->cl_confirm, &confirm))) &&
+-	    (!unconf || (unconf && !cmp_verf(&unconf->cl_confirm, &confirm)))) {
++	} else if ((!conf || (conf && !cmp_verf(&conf->cl_confirm, &confirm)))
++	    && (!unconf || (unconf && !cmp_verf(&unconf->cl_confirm,
++				    				&confirm)))) {
++		/* CASE 4:
++		 * conf record not found, or if conf, conf->cl_confirm does not
++		 * match input confirm.
++		 * unconf record not found, or if unconf, unconf->cl_confirm
++		 * does not match input confirm.
++		 */
+ 		status = nfserr_stale_clientid;
+-	}
+-	else {
++	} else {
+ 		/* check that we have hit one of the cases...*/
+ 		status = nfserr_clid_inuse;
+ 	}

commit 08e8987c37cd04d2df211c1e019d8f165d44266e
+Author: NeilBrown 
+Date:   Thu Jun 23 22:04:11 2005 -0700
+
+    [PATCH] knfsd: nfsd4: setclientid_confirm gotoectomy
+    
+    Change from "goto" to "else if" format in setclientid_confirm.
+    
+    From: Fred Isaman
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 2dc6da74ccea..9014dc2a632a 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -891,14 +891,13 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
+ 			status = nfs_ok;
+ 
+ 		}
+-		goto out;
+ 	} 
+ 	/* CASE 2:
+ 	 * conf record that matches input clientid.
+ 	 * if unconf record that matches input clientid, then unconf->cl_name
+ 	 * or unconf->cl_verifier don't match the conf record.
+ 	 */
+-	if ((conf && !unconf) || 
++	else if ((conf && !unconf) ||
+ 	    ((conf && unconf) && 
+ 	     (!cmp_verf(&conf->cl_verifier, &unconf->cl_verifier) ||
+ 	      !same_name(conf->cl_recdir, unconf->cl_recdir)))) {
+@@ -908,14 +907,13 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
+ 			clp = conf;
+ 			status = nfs_ok;
+ 		}
+-		goto out;
+ 	}
+ 	/* CASE 3:
+ 	 * conf record not found.
+ 	 * unconf record found. 
+ 	 * unconf->cl_confirm matches input confirm
+ 	 */ 
+-	if (!conf && unconf && cmp_verf(&unconf->cl_confirm, &confirm)) {
++	else if (!conf && unconf && cmp_verf(&unconf->cl_confirm, &confirm)) {
+ 		if (!cmp_creds(&unconf->cl_cred, &rqstp->rq_cred)) {
+ 			status = nfserr_clid_inuse;
+ 		} else {
+@@ -930,7 +928,6 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
+ 			move_to_confirmed(unconf);
+ 			status = nfs_ok;
+ 		}
+-		goto out;
+ 	}
+ 	/* CASE 4:
+ 	 * conf record not found, or if conf, then conf->cl_confirm does not
+@@ -938,14 +935,14 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
+ 	 * unconf record not found, or if unconf, then unconf->cl_confirm 
+ 	 * does not match input confirm.
+ 	 */
+-	if ((!conf || (conf && !cmp_verf(&conf->cl_confirm, &confirm))) &&
++	else if ((!conf || (conf && !cmp_verf(&conf->cl_confirm, &confirm))) &&
+ 	    (!unconf || (unconf && !cmp_verf(&unconf->cl_confirm, &confirm)))) {
+ 		status = nfserr_stale_clientid;
+-		goto out;
+ 	}
+-	/* check that we have hit one of the cases...*/
+-	status = nfserr_clid_inuse;
+-	goto out;
++	else {
++		/* check that we have hit one of the cases...*/
++		status = nfserr_clid_inuse;
++	}
+ out:
+ 	if (!status)
+ 		nfsd4_probe_callback(clp);

commit 22de4d837439071a0bec897485d3911383b6ffad
+Author: NeilBrown 
+Date:   Thu Jun 23 22:04:09 2005 -0700
+
+    [PATCH] knfsd: nfsd4: fix setclientid_confirm error return
+    
+    NFS4_INVAL is not a valid error for setclientid_confirm, and INUSE is the more
+    logical error here anyway.
+    
+    From: Fred Isaman
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 997343c23043..2dc6da74ccea 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -849,12 +849,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
+ 	nfs4_lock_state();
+ 	clp = find_confirmed_client(clid);
+ 	if (clp) {
+-		status = nfserr_inval;
+-		/* 
+-		 * Found a record for this clientid. If the IP addresses
+-		 * don't match, return ERR_INVAL just as if the record had
+-		 * not been found.
+-		 */
++		status = nfserr_clid_inuse;
+ 		if (clp->cl_addr != ip_addr) { 
+ 			printk("NFSD: setclientid: string in use by client"
+ 			"(clientid %08x/%08x)\n",
+@@ -865,7 +860,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
+ 	}
+ 	clp = find_unconfirmed_client(clid);
+ 	if (clp) {
+-		status = nfserr_inval;
++		status = nfserr_clid_inuse;
+ 		if (clp->cl_addr != ip_addr) { 
+ 			printk("NFSD: setclientid: string in use by client"
+ 			"(clientid %08x/%08x)\n",
+@@ -949,7 +944,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
+ 		goto out;
+ 	}
+ 	/* check that we have hit one of the cases...*/
+-	status = nfserr_inval;
++	status = nfserr_clid_inuse;
+ 	goto out;
+ out:
+ 	if (!status)

commit 1a69c179a28a9bb9f4d086927b192d5cffe88e50
+Author: NeilBrown 
+Date:   Thu Jun 23 22:04:08 2005 -0700
+
+    [PATCH] knfsd: nfsd4: fix setclientid_confirm cases
+    
+    Setclientid_confirm code confused states 1 and 3 (numbering from the
+    IMPLEMENTATION section of rfc3530, section 14.2.33).  Fix this.
+    
+    State 1 allows the client to change the callback channel on the fly.  We don't
+    implement this currently, so just turn off the callback channel in this case.
+    
+    From: Fred Isaman
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 67a038dc0d0e..997343c23043 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -887,10 +887,14 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
+ 		if (!cmp_creds(&conf->cl_cred, &unconf->cl_cred)) 
+ 			status = nfserr_clid_inuse;
+ 		else {
+-			expire_client(conf);
+-			clp = unconf;
+-			move_to_confirmed(unconf);
++			/* XXX: We just turn off callbacks until we can handle
++			  * change request correctly. */
++			clp = conf;
++			clp->cl_callback.cb_parsed = 0;
++			gen_confirm(clp);
++			expire_client(unconf);
+ 			status = nfs_ok;
++
+ 		}
+ 		goto out;
+ 	} 
+@@ -920,9 +924,16 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
+ 		if (!cmp_creds(&unconf->cl_cred, &rqstp->rq_cred)) {
+ 			status = nfserr_clid_inuse;
+ 		} else {
+-			status = nfs_ok;
++			unsigned int hash =
++				clientstr_hashval(unconf->cl_recdir);
++			conf = find_confirmed_client_by_str(unconf->cl_recdir,
++									hash);
++			if (conf) {
++				expire_client(conf);
++			}
+ 			clp = unconf;
+ 			move_to_confirmed(unconf);
++			status = nfs_ok;
+ 		}
+ 		goto out;
+ 	}

commit 31f4a6c127f619886bf97f643e546f7788248f3f
+Author: NeilBrown 
+Date:   Thu Jun 23 22:04:06 2005 -0700
+
+    [PATCH] knfsd: nfsd4: fix uncomfirmed list
+    
+    Setclientid code assumes there is only one match in unconfirmed list.
+    Make sure that assumption holds.
+    
+    From: Fred Isaman
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 8a5f777b1e96..67a038dc0d0e 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -743,10 +743,13 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
+ 		 * nfs4_client,  but with the new callback info and a 
+ 		 * new cl_confirm
+ 		 */
+-		if ((unconf) && 
+-		    cmp_verf(&unconf->cl_verifier, &conf->cl_verifier) &&
+-		     cmp_clid(&unconf->cl_clientid, &conf->cl_clientid)) {
+-				expire_client(unconf);
++		if (unconf) {
++			/* Note this is removing unconfirmed {*x***},
++			 * which is stronger than RFC recommended {vxc**}.
++			 * This has the advantage that there is at most
++			 * one {*x***} in either list at any time.
++			 */
++			expire_client(unconf);
+ 		}
+ 		new = create_client(clname, dname);
+ 		if (new == NULL)

commit fd39ca9a808c6026989bc2188868a0574eb37108
+Author: NeilBrown 
+Date:   Thu Jun 23 22:04:03 2005 -0700
+
+    [PATCH] knfsd: nfsd4: make needlessly global code static
+    
+    This patch contains the following possible cleanups:
+    
+    - make needlessly global code static
+    
+    Signed-off-by: Adrian Bunk 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
+index 11ebf6c4aa54..4a2105552ac4 100644
+--- a/fs/nfsd/nfs4acl.c
++++ b/fs/nfsd/nfs4acl.c
+@@ -125,7 +125,7 @@ static short ace2type(struct nfs4_ace *);
+ static int _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, unsigned int);
+ static struct posix_acl *_nfsv4_to_posix_one(struct nfs4_acl *, unsigned int);
+ int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
+-int nfs4_acl_split(struct nfs4_acl *, struct nfs4_acl *);
++static int nfs4_acl_split(struct nfs4_acl *, struct nfs4_acl *);
+ 
+ struct nfs4_acl *
+ nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl,
+@@ -775,7 +775,7 @@ _nfsv4_to_posix_one(struct nfs4_acl *n4acl, unsigned int flags)
+ 	return pacl;
+ }
+ 
+-int
++static int
+ nfs4_acl_split(struct nfs4_acl *acl, struct nfs4_acl *dacl)
+ {
+ 	struct list_head *h, *n;
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 38c3e1c47d83..68bb245491f6 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -54,7 +54,6 @@
+ 
+ /* declarations */
+ static void nfs4_cb_null(struct rpc_task *task);
+-extern spinlock_t recall_lock;
+ 
+ /* Index of predefined Linux callback client operations */
+ 
+@@ -329,12 +328,12 @@ nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp, u32 *p)
+         .p_bufsiz = MAX(NFS4_##argtype##_sz,NFS4_##restype##_sz) << 2,  \
+ }
+ 
+-struct rpc_procinfo     nfs4_cb_procedures[] = {
++static struct rpc_procinfo     nfs4_cb_procedures[] = {
+     PROC(CB_NULL,      NULL,     enc_cb_null,     dec_cb_null),
+     PROC(CB_RECALL,    COMPOUND,   enc_cb_recall,      dec_cb_recall),
+ };
+ 
+-struct rpc_version              nfs_cb_version4 = {
++static struct rpc_version       nfs_cb_version4 = {
+         .number                 = 1,
+         .nrprocs                = sizeof(nfs4_cb_procedures)/sizeof(nfs4_cb_procedures[0]),
+         .procs                  = nfs4_cb_procedures
+@@ -348,7 +347,7 @@ static struct rpc_version *	nfs_cb_version[] = {
+ /*
+  * Use the SETCLIENTID credential
+  */
+-struct rpc_cred *
++static struct rpc_cred *
+ nfsd4_lookupcred(struct nfs4_client *clp, int taskflags)
+ {
+         struct auth_cred acred;
+diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
+index 4ba540841cf6..5605a26efc57 100644
+--- a/fs/nfsd/nfs4idmap.c
++++ b/fs/nfsd/nfs4idmap.c
+@@ -104,7 +104,7 @@ ent_update(struct ent *new, struct ent *itm)
+ 	ent_init(new, itm);
+ }
+ 
+-void
++static void
+ ent_put(struct cache_head *ch, struct cache_detail *cd)
+ {
+ 	if (cache_put(ch, cd)) {
+@@ -186,7 +186,7 @@ warn_no_idmapd(struct cache_detail *detail)
+ static int         idtoname_parse(struct cache_detail *, char *, int);
+ static struct ent *idtoname_lookup(struct ent *, int);
+ 
+-struct cache_detail idtoname_cache = {
++static struct cache_detail idtoname_cache = {
+ 	.hash_size	= ENT_HASHMAX,
+ 	.hash_table	= idtoname_table,
+ 	.name		= "nfs4.idtoname",
+@@ -277,7 +277,7 @@ nametoid_hash(struct ent *ent)
+ 	return hash_str(ent->name, ENT_HASHBITS);
+ }
+ 
+-void
++static void
+ nametoid_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
+     int *blen)
+ {
+@@ -317,9 +317,9 @@ nametoid_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
+ }
+ 
+ static struct ent *nametoid_lookup(struct ent *, int);
+-int                nametoid_parse(struct cache_detail *, char *, int);
++static int         nametoid_parse(struct cache_detail *, char *, int);
+ 
+-struct cache_detail nametoid_cache = {
++static struct cache_detail nametoid_cache = {
+ 	.hash_size	= ENT_HASHMAX,
+ 	.hash_table	= nametoid_table,
+ 	.name		= "nfs4.nametoid",
+@@ -330,7 +330,7 @@ struct cache_detail nametoid_cache = {
+ 	.warn_no_listener = warn_no_idmapd,
+ };
+ 
+-int
++static int
+ nametoid_parse(struct cache_detail *cd, char *buf, int buflen)
+ {
+ 	struct ent ent, *res;
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 1b2f67f5eef6..8a5f777b1e96 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -54,18 +54,21 @@
+ /* Globals */
+ static time_t lease_time = 90;     /* default lease time */
+ static time_t user_lease_time = 90;
+-time_t boot_time;
++static time_t boot_time;
+ static int in_grace = 1;
+ static u32 current_clientid = 1;
+ static u32 current_ownerid = 1;
+ static u32 current_fileid = 1;
+ static u32 current_delegid = 1;
+ static u32 nfs4_init;
+-stateid_t zerostateid;             /* bits all 0 */
+-stateid_t onestateid;              /* bits all 1 */
++static stateid_t zerostateid;             /* bits all 0 */
++static stateid_t onestateid;              /* bits all 1 */
++
++#define ZERO_STATEID(stateid) (!memcmp((stateid), &zerostateid, sizeof(stateid_t)))
++#define ONE_STATEID(stateid)  (!memcmp((stateid), &onestateid, sizeof(stateid_t)))
+ 
+ /* forward declarations */
+-struct nfs4_stateid * find_stateid(stateid_t *stid, int flags);
++static struct nfs4_stateid * find_stateid(stateid_t *stid, int flags);
+ static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid);
+ static void release_stateid_lockowners(struct nfs4_stateid *open_stp);
+ 
+@@ -77,10 +80,10 @@ static void release_stateid_lockowners(struct nfs4_stateid *open_stp);
+  */
+ static DECLARE_MUTEX(client_sema);
+ 
+-kmem_cache_t *stateowner_slab = NULL;
+-kmem_cache_t *file_slab = NULL;
+-kmem_cache_t *stateid_slab = NULL;
+-kmem_cache_t *deleg_slab = NULL;
++static kmem_cache_t *stateowner_slab = NULL;
++static kmem_cache_t *file_slab = NULL;
++static kmem_cache_t *stateid_slab = NULL;
++static kmem_cache_t *deleg_slab = NULL;
+ 
+ void
+ nfs4_lock_state(void)
+@@ -116,7 +119,7 @@ static void release_stateid(struct nfs4_stateid *stp, int flags);
+  */
+ 
+ /* recall_lock protects the del_recall_lru */
+-spinlock_t recall_lock = SPIN_LOCK_UNLOCKED;
++static spinlock_t recall_lock = SPIN_LOCK_UNLOCKED;
+ static struct list_head del_recall_lru;
+ 
+ static void
+@@ -456,7 +459,7 @@ check_name(struct xdr_netobj name) {
+ 	return 1;
+ }
+ 
+-void
++static void
+ add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval)
+ {
+ 	unsigned int idhashval;
+@@ -468,7 +471,7 @@ add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval)
+ 	clp->cl_time = get_seconds();
+ }
+ 
+-void
++static void
+ move_to_confirmed(struct nfs4_client *clp)
+ {
+ 	unsigned int idhashval = clientid_hashval(clp->cl_clientid.cl_id);
+@@ -567,7 +570,7 @@ parse_octet(unsigned int *lenp, char **addrp)
+ }
+ 
+ /* parse and set the setclientid ipv4 callback address */
+-int
++static int
+ parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigned short *cbportp)
+ {
+ 	int temp = 0;
+@@ -603,7 +606,7 @@ parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigne
+ 	return 1;
+ }
+ 
+-void
++static void
+ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
+ {
+ 	struct nfs4_callback *cb = &clp->cl_callback;
+@@ -1186,7 +1189,7 @@ release_stateid(struct nfs4_stateid *stp, int flags)
+ 	stp = NULL;
+ }
+ 
+-void
++static void
+ move_to_close_lru(struct nfs4_stateowner *sop)
+ {
+ 	dprintk("NFSD: move_to_close_lru nfs4_stateowner %p\n", sop);
+@@ -1196,7 +1199,7 @@ move_to_close_lru(struct nfs4_stateowner *sop)
+ 	sop->so_time = get_seconds();
+ }
+ 
+-void
++static void
+ release_state_owner(struct nfs4_stateid *stp, int flag)
+ {
+ 	struct nfs4_stateowner *sop = stp->st_stateowner;
+@@ -1250,7 +1253,7 @@ find_file(struct inode *ino)
+ #define TEST_ACCESS(x) ((x > 0 || x < 4)?1:0)
+ #define TEST_DENY(x) ((x >= 0 || x < 5)?1:0)
+ 
+-void
++static void
+ set_access(unsigned int *access, unsigned long bmap) {
+ 	int i;
+ 
+@@ -1261,7 +1264,7 @@ set_access(unsigned int *access, unsigned long bmap) {
+ 	}
+ }
+ 
+-void
++static void
+ set_deny(unsigned int *deny, unsigned long bmap) {
+ 	int i;
+ 
+@@ -1287,7 +1290,7 @@ test_share(struct nfs4_stateid *stp, struct nfsd4_open *open) {
+  * Called to check deny when READ with all zero stateid or
+  * WRITE with all zero or all one stateid
+  */
+-int
++static int
+ nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
+ {
+ 	struct inode *ino = current_fh->fh_dentry->d_inode;
+@@ -1442,7 +1445,7 @@ int nfsd_change_deleg_cb(struct file_lock **onlist, int arg)
+ 		return -EAGAIN;
+ }
+ 
+-struct lock_manager_operations nfsd_lease_mng_ops = {
++static struct lock_manager_operations nfsd_lease_mng_ops = {
+ 	.fl_break = nfsd_break_deleg_cb,
+ 	.fl_release_private = nfsd_release_deleg_cb,
+ 	.fl_copy_lock = nfsd_copy_lock_deleg_cb,
+@@ -1915,7 +1918,7 @@ end_grace(void)
+ 	in_grace = 0;
+ }
+ 
+-time_t
++static time_t
+ nfs4_laundromat(void)
+ {
+ 	struct nfs4_client *clp;
+@@ -1996,7 +1999,7 @@ laundromat_main(void *not_used)
+ /* search ownerid_hashtbl[] and close_lru for stateid owner
+  * (stateid->si_stateownerid)
+  */
+-struct nfs4_stateowner *
++static struct nfs4_stateowner *
+ find_openstateowner_id(u32 st_id, int flags) {
+ 	struct nfs4_stateowner *local = NULL;
+ 
+@@ -2170,7 +2173,7 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
+ /* 
+  * Checks for sequence id mutating operations. 
+  */
+-int
++static int
+ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, clientid_t *lockclid)
+ {
+ 	int status;
+@@ -2486,7 +2489,7 @@ static struct list_head lock_ownerid_hashtbl[LOCK_HASH_SIZE];
+ static struct list_head	lock_ownerstr_hashtbl[LOCK_HASH_SIZE];
+ static struct list_head lockstateid_hashtbl[STATEID_HASH_SIZE];
+ 
+-struct nfs4_stateid *
++static struct nfs4_stateid *
+ find_stateid(stateid_t *stid, int flags)
+ {
+ 	struct nfs4_stateid *local = NULL;
+@@ -2550,7 +2553,7 @@ nfs4_transform_lock_offset(struct file_lock *lock)
+ 		lock->fl_end = OFFSET_MAX;
+ }
+ 
+-int
++static int
+ nfs4_verify_lock_stateowner(struct nfs4_stateowner *sop, unsigned int hashval)
+ {
+ 	struct nfs4_stateowner *local = NULL;
+@@ -2660,7 +2663,7 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
+ 	return sop;
+ }
+ 
+-struct nfs4_stateid *
++static struct nfs4_stateid *
+ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struct nfs4_stateid *open_stp)
+ {
+ 	struct nfs4_stateid *stp;
+@@ -2691,7 +2694,7 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc
+ 	return stp;
+ }
+ 
+-int
++static int
+ check_lock_length(u64 offset, u64 length)
+ {
+ 	return ((length == 0)  || ((length != ~(u64)0) &&
+@@ -3149,7 +3152,7 @@ nfs4_release_reclaim(void)
+ 
+ /*
+  * called from OPEN, CLAIM_PREVIOUS with a new clientid. */
+-struct nfs4_client_reclaim *
++static struct nfs4_client_reclaim *
+ nfs4_find_reclaim_client(clientid_t *clid)
+ {
+ 	unsigned int strhashval;
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index cfe978a72cea..91fb171d2ace 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -136,7 +136,7 @@ xdr_error:					\
+ 	}					\
+ } while (0)
+ 
+-u32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes)
++static u32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes)
+ {
+ 	/* We want more bytes than seem to be available.
+ 	 * Maybe we need a new page, maybe we have just run out
+@@ -190,7 +190,7 @@ defer_free(struct nfsd4_compoundargs *argp,
+ 	return 0;
+ }
+ 
+-char *savemem(struct nfsd4_compoundargs *argp, u32 *p, int nbytes)
++static char *savemem(struct nfsd4_compoundargs *argp, u32 *p, int nbytes)
+ {
+ 	void *new = NULL;
+ 	if (p == argp->tmp) {
+diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
+index fdaa84addadb..0e18ae22127d 100644
+--- a/include/linux/nfsd/state.h
++++ b/include/linux/nfsd/state.h
+@@ -61,11 +61,6 @@ typedef struct {
+ #define si_stateownerid   si_opaque.so_stateownerid
+ #define si_fileid         si_opaque.so_fileid
+ 
+-extern stateid_t zerostateid;
+-extern stateid_t onestateid;
+-
+-#define ZERO_STATEID(stateid)       (!memcmp((stateid), &zerostateid, sizeof(stateid_t)))
+-#define ONE_STATEID(stateid)        (!memcmp((stateid), &onestateid, sizeof(stateid_t)))
+ 
+ struct nfs4_cb_recall {
+ 	u32			cbr_ident;
+@@ -271,12 +266,9 @@ struct nfs4_stateid {
+ 	((err) != nfserr_stale_stateid) &&      \
+ 	((err) != nfserr_bad_stateid))
+ 
+-extern time_t nfs4_laundromat(void);
+ extern int nfsd4_renew(clientid_t *clid);
+ extern int nfs4_preprocess_stateid_op(struct svc_fh *current_fh, 
+ 		stateid_t *stateid, int flags, struct file **filp);
+-extern int nfs4_share_conflict(struct svc_fh *current_fh, 
+-		unsigned int deny_type);
+ extern void nfs4_lock_state(void);
+ extern void nfs4_unlock_state(void);
+ extern int nfs4_in_grace(void);

commit a76b4319ca85b5e3a8098470c623a272d40271cd
+Author: NeilBrown 
+Date:   Thu Jun 23 22:04:01 2005 -0700
+
+    [PATCH] knfsd: nfsd4: grace period end
+    
+    For the purposes of reboot recovery, we want to do some work during the
+    transition period at the end of the grace period.  Some of that work must be
+    guaranteed to have a certain relationship with the end of the grace period, so
+    we want to control the transition there.
+    
+    Our approach is to modify the in_grace() checks to consult a global variable
+    instead of checking the time directly, to schedule the first run of the
+    laundromat thread at the end of the grace period, and to set the global
+    end-of-grace-period there.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 72f2b6fdae66..1b2f67f5eef6 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -55,7 +55,7 @@
+ static time_t lease_time = 90;     /* default lease time */
+ static time_t user_lease_time = 90;
+ time_t boot_time;
+-static time_t grace_end = 0;
++static int in_grace = 1;
+ static u32 current_clientid = 1;
+ static u32 current_ownerid = 1;
+ static u32 current_fileid = 1;
+@@ -1908,6 +1908,13 @@ nfsd4_renew(clientid_t *clid)
+ 	return status;
+ }
+ 
++static void
++end_grace(void)
++{
++	dprintk("NFSD: end of grace period\n");
++	in_grace = 0;
++}
++
+ time_t
+ nfs4_laundromat(void)
+ {
+@@ -1922,6 +1929,8 @@ nfs4_laundromat(void)
+ 	nfs4_lock_state();
+ 
+ 	dprintk("NFSD: laundromat service - starting\n");
++	if (in_grace)
++		end_grace();
+ 	list_for_each_safe(pos, next, &client_lru) {
+ 		clp = list_entry(pos, struct nfs4_client, cl_lru);
+ 		if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) {
+@@ -3223,10 +3232,10 @@ __nfs4_state_start(void)
+ 	boot_time = get_seconds();
+ 	grace_time = max(user_lease_time, lease_time);
+ 	lease_time = user_lease_time;
++	in_grace = 1;
+ 	printk("NFSD: starting %ld-second grace period\n", grace_time);
+-	grace_end = boot_time + grace_time;
+ 	laundry_wq = create_singlethread_workqueue("nfsd4");
+-	queue_delayed_work(laundry_wq, &laundromat_work, NFSD_LEASE_TIME*HZ);
++	queue_delayed_work(laundry_wq, &laundromat_work, grace_time*HZ);
+ }
+ 
+ int
+@@ -3247,14 +3256,7 @@ nfs4_state_start(void)
+ int
+ nfs4_in_grace(void)
+ {
+-	return get_seconds() < grace_end;
+-}
+-
+-void
+-set_no_grace(void)
+-{
+-	printk("NFSD: ERROR in reboot recovery.  State reclaims will fail.\n");
+-	grace_end = get_seconds();
++	return in_grace;
+ }
+ 
+ time_t

commit 28ce6054f1de89834e5e9522f9e451cd88a35f85
+Author: NeilBrown 
+Date:   Thu Jun 23 22:03:56 2005 -0700
+
+    [PATCH] knfsd: nfsd4: add find_{un}conf_by_str functions to simplify setclientid
+    
+    Minor setclientid cleanup
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 0be0b37c84e9..72f2b6fdae66 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -509,6 +509,30 @@ find_unconfirmed_client(clientid_t *clid)
+ 	return NULL;
+ }
+ 
++static struct nfs4_client *
++find_confirmed_client_by_str(const char *dname, unsigned int hashval)
++{
++	struct nfs4_client *clp;
++
++	list_for_each_entry(clp, &conf_str_hashtbl[hashval], cl_strhash) {
++		if (same_name(clp->cl_recdir, dname))
++			return clp;
++	}
++	return NULL;
++}
++
++static struct nfs4_client *
++find_unconfirmed_client_by_str(const char *dname, unsigned int hashval)
++{
++	struct nfs4_client *clp;
++
++	list_for_each_entry(clp, &unconf_str_hashtbl[hashval], cl_strhash) {
++		if (same_name(clp->cl_recdir, dname))
++			return clp;
++	}
++	return NULL;
++}
++
+ /* a helper function for parse_callback */
+ static int
+ parse_octet(unsigned int *lenp, char **addrp)
+@@ -647,7 +671,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
+ 	};
+ 	nfs4_verifier		clverifier = setclid->se_verf;
+ 	unsigned int 		strhashval;
+-	struct nfs4_client *	conf, * unconf, * new, * clp;
++	struct nfs4_client	*conf, *unconf, *new;
+ 	int 			status;
+ 	char                    dname[HEXDIR_LEN];
+ 	
+@@ -666,35 +690,24 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
+ 
+ 	strhashval = clientstr_hashval(dname);
+ 
+-	conf = NULL;
+ 	nfs4_lock_state();
+-	list_for_each_entry(clp, &conf_str_hashtbl[strhashval], cl_strhash) {
+-		if (!same_name(clp->cl_recdir, dname))
+-			continue;
++	conf = find_confirmed_client_by_str(dname, strhashval);
++	if (conf) {
+ 		/* 
+ 		 * CASE 0:
+ 		 * clname match, confirmed, different principal
+ 		 * or different ip_address
+ 		 */
+ 		status = nfserr_clid_inuse;
+-		if (!cmp_creds(&clp->cl_cred,&rqstp->rq_cred)
+-				|| clp->cl_addr != ip_addr) {
++		if (!cmp_creds(&conf->cl_cred, &rqstp->rq_cred)
++				|| conf->cl_addr != ip_addr) {
+ 			printk("NFSD: setclientid: string in use by client"
+ 			"(clientid %08x/%08x)\n",
+-			clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
++			conf->cl_clientid.cl_boot, conf->cl_clientid.cl_id);
+ 			goto out;
+ 		}
+-		conf = clp;
+-		break;
+-	}
+-	unconf = NULL;
+-	list_for_each_entry(clp, &unconf_str_hashtbl[strhashval], cl_strhash) {
+-		if (!same_name(clp->cl_recdir, dname))
+-			continue;
+-		/* cl_name match from a previous SETCLIENTID operation */
+-		unconf = clp;
+-		break;
+ 	}
++	unconf = find_unconfirmed_client_by_str(dname, strhashval);
+ 	status = nfserr_resource;
+ 	if (!conf) {
+ 		/* 

commit a55370a3c0106106a975c5a09cee800611d0cf50
+Author: NeilBrown 
+Date:   Thu Jun 23 22:03:52 2005 -0700
+
+    [PATCH] knfsd: nfsd4: reboot hash
+    
+    For the purposes of reboot recovery we keep a directory with subdirectories
+    each having a name that is the ascii hex representation of the md5 sum of a
+    client identifier for an active client.
+    
+    This adds the code to calculate that name.  We also use it for the purposes of
+    comparing clients, so if someone ever manages to find two client names that
+    are md5 collisions, then we'll return clid_inuse to the second.
+    
+    Signed-off-by: Andy Adamson 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/Kconfig b/fs/Kconfig
+index a7c0cc3203cb..5c704d05627a 100644
+--- a/fs/Kconfig
++++ b/fs/Kconfig
+@@ -1413,6 +1413,8 @@ config NFSD_V4
+ 	bool "Provide NFSv4 server support (EXPERIMENTAL)"
+ 	depends on NFSD_V3 && EXPERIMENTAL
+ 	select NFSD_TCP
++	select CRYPTO_MD5
++	select CRYPTO
+ 	help
+ 	  If you would like to include the NFSv4 server as well as the NFSv2
+ 	  and NFSv3 servers, say Y here.  This feature is experimental, and
+diff --git a/fs/nfsd/Makefile b/fs/nfsd/Makefile
+index 9f043f44c92f..ce341dc76d5e 100644
+--- a/fs/nfsd/Makefile
++++ b/fs/nfsd/Makefile
+@@ -10,5 +10,5 @@ nfsd-$(CONFIG_NFSD_V2_ACL) += nfs2acl.o
+ nfsd-$(CONFIG_NFSD_V3)	+= nfs3proc.o nfs3xdr.o
+ nfsd-$(CONFIG_NFSD_V3_ACL) += nfs3acl.o
+ nfsd-$(CONFIG_NFSD_V4)	+= nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o \
+-			   nfs4acl.o nfs4callback.o
++			   nfs4acl.o nfs4callback.o nfs4recover.o
+ nfsd-objs		:= $(nfsd-y)
+diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
+new file mode 100644
+index 000000000000..841a305d7948
+--- /dev/null
++++ b/fs/nfsd/nfs4recover.c
+@@ -0,0 +1,97 @@
++/*
++*  linux/fs/nfsd/nfs4recover.c
++*
++*  Copyright (c) 2004 The Regents of the University of Michigan.
++*  All rights reserved.
++*
++*  Andy Adamson 
++*
++*  Redistribution and use in source and binary forms, with or without
++*  modification, are permitted provided that the following conditions
++*  are met:
++*
++*  1. Redistributions of source code must retain the above copyright
++*     notice, this list of conditions and the following disclaimer.
++*  2. Redistributions in binary form must reproduce the above copyright
++*     notice, this list of conditions and the following disclaimer in the
++*     documentation and/or other materials provided with the distribution.
++*  3. Neither the name of the University nor the names of its
++*     contributors may be used to endorse or promote products derived
++*     from this software without specific prior written permission.
++*
++*  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
++*  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
++*  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++*  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
++*  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++*  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
++*  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
++*  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
++*  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++*
++*/
++
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++
++#define NFSDDBG_FACILITY                NFSDDBG_PROC
++
++static void
++md5_to_hex(char *out, char *md5)
++{
++	int i;
++
++	for (i=0; i<16; i++) {
++		unsigned char c = md5[i];
++
++		*out++ = '0' + ((c&0xf0)>>4) + (c>=0xa0)*('a'-'9'-1);
++		*out++ = '0' + (c&0x0f) + ((c&0x0f)>=0x0a)*('a'-'9'-1);
++	}
++	*out = '\0';
++}
++
++int
++nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname)
++{
++	struct xdr_netobj cksum;
++	struct crypto_tfm *tfm;
++	struct scatterlist sg[1];
++	int status = nfserr_resource;
++
++	dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n",
++			clname->len, clname->data);
++	tfm = crypto_alloc_tfm("md5", 0);
++	if (tfm == NULL)
++		goto out;
++	cksum.len = crypto_tfm_alg_digestsize(tfm);
++	cksum.data = kmalloc(cksum.len, GFP_KERNEL);
++	if (cksum.data == NULL)
++ 		goto out;
++	crypto_digest_init(tfm);
++
++	sg[0].page = virt_to_page(clname->data);
++	sg[0].offset = offset_in_page(clname->data);
++	sg[0].length = clname->len;
++
++	crypto_digest_update(tfm, sg, 1);
++	crypto_digest_final(tfm, cksum.data);
++
++	md5_to_hex(dname, cksum.data);
++
++	kfree(cksum.data);
++	status = nfs_ok;
++out:
++	if (tfm)
++		crypto_free_tfm(tfm);
++	return status;
++}
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 2a59d176e69a..0be0b37c84e9 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -231,8 +231,8 @@ unhash_delegation(struct nfs4_delegation *dp)
+ 
+ #define clientid_hashval(id) \
+ 	((id) & CLIENT_HASH_MASK)
+-#define clientstr_hashval(name, namelen) \
+-	(opaque_hashval((name), (namelen)) & CLIENT_HASH_MASK)
++#define clientstr_hashval(name) \
++	(opaque_hashval((name), 8) & CLIENT_HASH_MASK)
+ /*
+  * reclaim_str_hashtbl[] holds known client info from previous reset/reboot
+  * used in reboot/reset lease grace period processing
+@@ -366,11 +366,12 @@ expire_client(struct nfs4_client *clp)
+ }
+ 
+ static struct nfs4_client *
+-create_client(struct xdr_netobj name) {
++create_client(struct xdr_netobj name, char *recdir) {
+ 	struct nfs4_client *clp;
+ 
+ 	if (!(clp = alloc_client(name)))
+ 		goto out;
++	memcpy(clp->cl_recdir, recdir, HEXDIR_LEN);
+ 	atomic_set(&clp->cl_count, 1);
+ 	atomic_set(&clp->cl_callback.cb_set, 0);
+ 	clp->cl_callback.cb_parsed = 0;
+@@ -403,11 +404,9 @@ copy_cred(struct svc_cred *target, struct svc_cred *source) {
+ 	get_group_info(target->cr_group_info);
+ }
+ 
+-static int
+-cmp_name(struct xdr_netobj *n1, struct xdr_netobj *n2) {
+-	if (!n1 || !n2)
+-		return 0;
+-	return((n1->len == n2->len) && !memcmp(n1->data, n2->data, n2->len));
++static inline int
++same_name(const char *n1, const char *n2) {
++	return 0 == memcmp(n1, n2, HEXDIR_LEN);
+ }
+ 
+ static int
+@@ -479,8 +478,7 @@ move_to_confirmed(struct nfs4_client *clp)
+ 	list_del_init(&clp->cl_strhash);
+ 	list_del_init(&clp->cl_idhash);
+ 	list_add(&clp->cl_idhash, &conf_id_hashtbl[idhashval]);
+-	strhashval = clientstr_hashval(clp->cl_name.data, 
+-			clp->cl_name.len);
++	strhashval = clientstr_hashval(clp->cl_recdir);
+ 	list_add(&clp->cl_strhash, &conf_str_hashtbl[strhashval]);
+ 	renew_client(clp);
+ }
+@@ -651,22 +649,27 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
+ 	unsigned int 		strhashval;
+ 	struct nfs4_client *	conf, * unconf, * new, * clp;
+ 	int 			status;
++	char                    dname[HEXDIR_LEN];
+ 	
+ 	status = nfserr_inval;
+ 	if (!check_name(clname))
+ 		goto out;
+ 
++	status = nfs4_make_rec_clidname(dname, &clname);
++	if (status)
++		goto out;
++
+ 	/* 
+ 	 * XXX The Duplicate Request Cache (DRC) has been checked (??)
+ 	 * We get here on a DRC miss.
+ 	 */
+ 
+-	strhashval = clientstr_hashval(clname.data, clname.len);
++	strhashval = clientstr_hashval(dname);
+ 
+ 	conf = NULL;
+ 	nfs4_lock_state();
+ 	list_for_each_entry(clp, &conf_str_hashtbl[strhashval], cl_strhash) {
+-		if (!cmp_name(&clp->cl_name, &clname))
++		if (!same_name(clp->cl_recdir, dname))
+ 			continue;
+ 		/* 
+ 		 * CASE 0:
+@@ -686,7 +689,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
+ 	}
+ 	unconf = NULL;
+ 	list_for_each_entry(clp, &unconf_str_hashtbl[strhashval], cl_strhash) {
+-		if (!cmp_name(&clp->cl_name, &clname))
++		if (!same_name(clp->cl_recdir, dname))
+ 			continue;
+ 		/* cl_name match from a previous SETCLIENTID operation */
+ 		unconf = clp;
+@@ -700,7 +703,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
+ 		 */
+ 		if (unconf)
+ 			expire_client(unconf);
+-		if (!(new = create_client(clname)))
++		new = create_client(clname, dname);
++		if (new == NULL)
+ 			goto out;
+ 		copy_verf(new, &clverifier);
+ 		new->cl_addr = ip_addr;
+@@ -728,7 +732,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
+ 		     cmp_clid(&unconf->cl_clientid, &conf->cl_clientid)) {
+ 				expire_client(unconf);
+ 		}
+-		if (!(new = create_client(clname)))
++		new = create_client(clname, dname);
++		if (new == NULL)
+ 			goto out;
+ 		copy_verf(new,&conf->cl_verifier);
+ 		new->cl_addr = ip_addr;
+@@ -746,7 +751,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
+ 		 * using input clverifier, clname, and callback info
+ 		 * and generate a new cl_clientid and cl_confirm.
+ 		 */
+-		if (!(new = create_client(clname)))
++		new = create_client(clname, dname);
++		if (new == NULL)
+ 			goto out;
+ 		copy_verf(new,&clverifier);
+ 		new->cl_addr = ip_addr;
+@@ -772,7 +778,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
+ 		 * new cl_verifier and a new cl_confirm
+ 		 */
+ 		expire_client(unconf);
+-		if (!(new = create_client(clname)))
++		new = create_client(clname, dname);
++		if (new == NULL)
+ 			goto out;
+ 		copy_verf(new,&clverifier);
+ 		new->cl_addr = ip_addr;
+@@ -856,7 +863,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
+ 	if ((conf && unconf) && 
+ 	    (cmp_verf(&unconf->cl_confirm, &confirm)) &&
+ 	    (cmp_verf(&conf->cl_verifier, &unconf->cl_verifier)) &&
+-	    (cmp_name(&conf->cl_name,&unconf->cl_name))  &&
++	    (same_name(conf->cl_recdir,unconf->cl_recdir))  &&
+ 	    (!cmp_verf(&conf->cl_confirm, &unconf->cl_confirm))) {
+ 		if (!cmp_creds(&conf->cl_cred, &unconf->cl_cred)) 
+ 			status = nfserr_clid_inuse;
+@@ -876,7 +883,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
+ 	if ((conf && !unconf) || 
+ 	    ((conf && unconf) && 
+ 	     (!cmp_verf(&conf->cl_verifier, &unconf->cl_verifier) ||
+-	      !cmp_name(&conf->cl_name, &unconf->cl_name)))) {
++	      !same_name(conf->cl_recdir, unconf->cl_recdir)))) {
+ 		if (!cmp_creds(&conf->cl_cred,&rqstp->rq_cred)) {
+ 			status = nfserr_clid_inuse;
+ 		} else {
+@@ -3074,39 +3081,28 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *
+ }
+ 
+ static inline struct nfs4_client_reclaim *
+-alloc_reclaim(int namelen)
++alloc_reclaim(void)
+ {
+-	struct nfs4_client_reclaim *crp = NULL;
+-
+-	crp = kmalloc(sizeof(struct nfs4_client_reclaim), GFP_KERNEL);
+-	if (!crp)
+-		return NULL;
+-	crp->cr_name.data = kmalloc(namelen, GFP_KERNEL);
+-	if (!crp->cr_name.data) {
+-		kfree(crp);
+-		return NULL;
+-	}
+-	return crp;
++	return kmalloc(sizeof(struct nfs4_client_reclaim), GFP_KERNEL);
+ }
+ 
+ /*
+  * failure => all reset bets are off, nfserr_no_grace...
+  */
+ static int
+-nfs4_client_to_reclaim(char *name, int namlen)
++nfs4_client_to_reclaim(char *name)
+ {
+ 	unsigned int strhashval;
+ 	struct nfs4_client_reclaim *crp = NULL;
+ 
+-	dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", namlen, name);
+-	crp = alloc_reclaim(namlen);
++	dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", HEXDIR_LEN, name);
++	crp = alloc_reclaim();
+ 	if (!crp)
+ 		return 0;
+-	strhashval = clientstr_hashval(name, namlen);
++	strhashval = clientstr_hashval(name);
+ 	INIT_LIST_HEAD(&crp->cr_strhash);
+ 	list_add(&crp->cr_strhash, &reclaim_str_hashtbl[strhashval]);
+-	memcpy(crp->cr_name.data, name, namlen);
+-	crp->cr_name.len = namlen;
++	memcpy(crp->cr_recdir, name, HEXDIR_LEN);
+ 	reclaim_str_hashtbl_size++;
+ 	return 1;
+ }
+@@ -3122,7 +3118,6 @@ nfs4_release_reclaim(void)
+ 			crp = list_entry(reclaim_str_hashtbl[i].next,
+ 			                struct nfs4_client_reclaim, cr_strhash);
+ 			list_del(&crp->cr_strhash);
+-			kfree(crp->cr_name.data);
+ 			kfree(crp);
+ 			reclaim_str_hashtbl_size--;
+ 		}
+@@ -3145,13 +3140,14 @@ nfs4_find_reclaim_client(clientid_t *clid)
+ 	if (clp == NULL)
+ 		return NULL;
+ 
+-	dprintk("NFSD: nfs4_find_reclaim_client for %.*s\n",
+-		            clp->cl_name.len, clp->cl_name.data);
++	dprintk("NFSD: nfs4_find_reclaim_client for %.*s with recdir %s\n",
++		            clp->cl_name.len, clp->cl_name.data,
++			    clp->cl_recdir);
+ 
+ 	/* find clp->cl_name in reclaim_str_hashtbl */
+-	strhashval = clientstr_hashval(clp->cl_name.data, clp->cl_name.len);
++	strhashval = clientstr_hashval(clp->cl_recdir);
+ 	list_for_each_entry(crp, &reclaim_str_hashtbl[strhashval], cr_strhash) {
+-		if (cmp_name(&crp->cr_name, &clp->cl_name)) {
++		if (same_name(crp->cr_recdir, clp->cl_recdir)) {
+ 			return crp;
+ 		}
+ 	}
+diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
+index 296e6429fc3b..fdaa84addadb 100644
+--- a/include/linux/nfsd/state.h
++++ b/include/linux/nfsd/state.h
+@@ -109,6 +109,8 @@ struct nfs4_callback {
+ 	struct rpc_clnt *       cb_client;
+ };
+ 
++#define HEXDIR_LEN     33 /* hex version of 16 byte md5 of cl_name plus '\0' */
++
+ /*
+  * struct nfs4_client - one per client.  Clientids live here.
+  * 	o Each nfs4_client is hashed by clientid.
+@@ -126,6 +128,7 @@ struct nfs4_client {
+ 	struct list_head	cl_del_perclnt; /* list: delegations */
+ 	struct list_head        cl_lru;         /* tail queue */
+ 	struct xdr_netobj	cl_name; 	/* id generated by client */
++	char                    cl_recdir[HEXDIR_LEN]; /* recovery dir */
+ 	nfs4_verifier		cl_verifier; 	/* generated by client */
+ 	time_t                  cl_time;        /* time of last lease renewal */
+ 	u32			cl_addr; 	/* client ipaddress */
+@@ -143,7 +146,7 @@ struct nfs4_client {
+  */
+ struct nfs4_client_reclaim {
+ 	struct list_head	cr_strhash;	/* hash by cr_name */
+-	struct xdr_netobj 	cr_name; 	/* id generated by client */
++	char			cr_recdir[HEXDIR_LEN]; /* recover dir */
+ };
+ 
+ static inline void
+@@ -283,6 +286,7 @@ extern void nfs4_free_stateowner(struct kref *kref);
+ extern void nfsd4_probe_callback(struct nfs4_client *clp);
+ extern void nfsd4_cb_recall(struct nfs4_delegation *dp);
+ extern void nfs4_put_delegation(struct nfs4_delegation *dp);
++extern int nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname);
+ 
+ static inline void
+ nfs4_put_stateowner(struct nfs4_stateowner *so)

commit 7dea9d280c96f90382ec5d5709433e66a0993ec9
+Author: NeilBrown 
+Date:   Thu Jun 23 22:03:42 2005 -0700
+
+    [PATCH] knfsd: nfsd4: setclientid simplification
+    
+    We can be a little more concise here.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index fb9b4eb4302d..2a59d176e69a 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -674,23 +674,13 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
+ 		 * or different ip_address
+ 		 */
+ 		status = nfserr_clid_inuse;
+-		if (!cmp_creds(&clp->cl_cred,&rqstp->rq_cred)) {
++		if (!cmp_creds(&clp->cl_cred,&rqstp->rq_cred)
++				|| clp->cl_addr != ip_addr) {
+ 			printk("NFSD: setclientid: string in use by client"
+ 			"(clientid %08x/%08x)\n",
+ 			clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
+ 			goto out;
+ 		}
+-		if (clp->cl_addr != ip_addr) { 
+-			printk("NFSD: setclientid: string in use by client"
+-			"(clientid %08x/%08x)\n",
+-			clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
+-			goto out;
+-		}
+-
+-		/* 
+-	 	 * cl_name match from a previous SETCLIENTID operation
+-	 	 * XXX check for additional matches?
+-		 */
+ 		conf = clp;
+ 		break;
+ 	}

commit bd0b1e954e3ba3e5d2cab941458cf98206471bd2
+Author: NeilBrown 
+Date:   Thu Jun 23 22:03:35 2005 -0700
+
+    [PATCH] knfsd: nfsd4: idmap initialization
+    
+    Adopt standard kernel style by defining a no-op function instead of putting
+    ifdef's in the code where the function is called.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index 3d56531a7a03..3da43a3ed32c 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -398,9 +398,7 @@ static int __init init_nfsd(void)
+ 	nfsd_export_init();	/* Exports table */
+ 	nfsd_lockd_init();	/* lockd->nfsd callbacks */
+ 	nfs4_state_init();	/* NFSv4 locking state */
+-#ifdef CONFIG_NFSD_V4
+ 	nfsd_idmap_init();      /* Name to ID mapping */
+-#endif /* CONFIG_NFSD_V4 */
+ 	if (proc_mkdir("fs/nfs", NULL)) {
+ 		struct proc_dir_entry *entry;
+ 		entry = create_proc_entry("fs/nfs/exports", 0, NULL);
+@@ -427,9 +425,7 @@ static void __exit exit_nfsd(void)
+ 	remove_proc_entry("fs/nfs", NULL);
+ 	nfsd_stat_shutdown();
+ 	nfsd_lockd_shutdown();
+-#ifdef CONFIG_NFSD_V4
+ 	nfsd_idmap_shutdown();
+-#endif /* CONFIG_NFSD_V4 */
+ 	unregister_filesystem(&nfsd_fs_type);
+ }
+ 
+diff --git a/include/linux/nfsd_idmap.h b/include/linux/nfsd_idmap.h
+index 9bb7f30e923b..e82746fcad14 100644
+--- a/include/linux/nfsd_idmap.h
++++ b/include/linux/nfsd_idmap.h
+@@ -43,8 +43,13 @@
+ /* XXX from linux/nfs_idmap.h */
+ #define IDMAP_NAMESZ 128
+ 
++#ifdef CONFIG_NFSD_V4
+ void nfsd_idmap_init(void);
+ void nfsd_idmap_shutdown(void);
++#else
++static inline void nfsd_idmap_init(void) {};
++static inline void nfsd_idmap_shutdown(void) {};
++#endif
+ 
+ int nfsd_map_name_to_uid(struct svc_rqst *, const char *, size_t, __u32 *);
+ int nfsd_map_name_to_gid(struct svc_rqst *, const char *, size_t, __u32 *);

commit 707d4ab7b3aa6d1f7a7d2cd123fb83ba9a528205
+Author: NeilBrown 
+Date:   Thu Jun 23 22:03:32 2005 -0700
+
+    [PATCH] knfsd: nfsd4: remove nfs4_reclaim_init
+    
+    nfs4_reclaim_init is no longer performing any useful function.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 1f68ce36e724..fb9b4eb4302d 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -54,7 +54,6 @@
+ /* Globals */
+ static time_t lease_time = 90;     /* default lease time */
+ static time_t user_lease_time = 90;
+-static u32 nfs4_reclaim_init = 0;
+ time_t boot_time;
+ static time_t grace_end = 0;
+ static u32 current_clientid = 1;
+@@ -3128,7 +3127,6 @@ nfs4_release_reclaim(void)
+ 	struct nfs4_client_reclaim *crp = NULL;
+ 	int i;
+ 
+-	BUG_ON(!nfs4_reclaim_init);
+ 	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
+ 		while (!list_empty(&reclaim_str_hashtbl[i])) {
+ 			crp = list_entry(reclaim_str_hashtbl[i].next,
+@@ -3214,7 +3212,6 @@ nfs4_state_init(void)
+ 	for (i = 0; i < CLIENT_HASH_SIZE; i++)
+ 		INIT_LIST_HEAD(&reclaim_str_hashtbl[i]);
+ 	reclaim_str_hashtbl_size = 0;
+-	nfs4_reclaim_init = 1;
+ }
+ 
+ /* initialization to perform when the nfsd service is started: */

commit ac4d8ff2a57179de3ef7834c6ab3fac430b0a05d
+Author: NeilBrown 
+Date:   Thu Jun 23 22:03:30 2005 -0700
+
+    [PATCH] knfsd: nfsd4: clean up state initialization
+    
+    Separate out stuff that needs initialization on startup from stuff that only
+    needs initialization on module init from static data.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index e00b3472851c..1f68ce36e724 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -117,7 +117,7 @@ static void release_stateid(struct nfs4_stateid *stp, int flags);
+  */
+ 
+ /* recall_lock protects the del_recall_lru */
+-spinlock_t recall_lock;
++spinlock_t recall_lock = SPIN_LOCK_UNLOCKED;
+ static struct list_head del_recall_lru;
+ 
+ static void
+@@ -3179,23 +3179,13 @@ nfs4_check_open_reclaim(clientid_t *clid)
+ 	return nfs4_find_reclaim_client(clid) ? nfs_ok : nfserr_reclaim_bad;
+ }
+ 
++/* initialization to perform at module load time: */
+ 
+-/* 
+- * Start and stop routines
+- */
+-
+-static void
+-__nfs4_state_start(void)
++void
++nfs4_state_init(void)
+ {
+ 	int i;
+-	time_t grace_time;
+ 
+-	if (!nfs4_reclaim_init) {
+-		for (i = 0; i < CLIENT_HASH_SIZE; i++)
+-			INIT_LIST_HEAD(&reclaim_str_hashtbl[i]);
+-		reclaim_str_hashtbl_size = 0;
+-		nfs4_reclaim_init = 1;
+-	}
+ 	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
+ 		INIT_LIST_HEAD(&conf_id_hashtbl[i]);
+ 		INIT_LIST_HEAD(&conf_str_hashtbl[i]);
+@@ -3217,19 +3207,28 @@ __nfs4_state_start(void)
+ 		INIT_LIST_HEAD(&lock_ownerid_hashtbl[i]);
+ 		INIT_LIST_HEAD(&lock_ownerstr_hashtbl[i]);
+ 	}
+-	memset(&zerostateid, 0, sizeof(stateid_t));
+ 	memset(&onestateid, ~0, sizeof(stateid_t));
+-
+ 	INIT_LIST_HEAD(&close_lru);
+ 	INIT_LIST_HEAD(&client_lru);
+ 	INIT_LIST_HEAD(&del_recall_lru);
+-	spin_lock_init(&recall_lock);
++	for (i = 0; i < CLIENT_HASH_SIZE; i++)
++		INIT_LIST_HEAD(&reclaim_str_hashtbl[i]);
++	reclaim_str_hashtbl_size = 0;
++	nfs4_reclaim_init = 1;
++}
++
++/* initialization to perform when the nfsd service is started: */
++
++static void
++__nfs4_state_start(void)
++{
++	time_t grace_time;
++
+ 	boot_time = get_seconds();
+ 	grace_time = max(user_lease_time, lease_time);
+ 	lease_time = user_lease_time;
+ 	printk("NFSD: starting %ld-second grace period\n", grace_time);
+ 	grace_end = boot_time + grace_time;
+-	INIT_WORK(&laundromat_work,laundromat_main, NULL);
+ 	laundry_wq = create_singlethread_workqueue("nfsd4");
+ 	queue_delayed_work(laundry_wq, &laundromat_work, NFSD_LEASE_TIME*HZ);
+ }
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index 161afdcb8f7d..3d56531a7a03 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -397,6 +397,7 @@ static int __init init_nfsd(void)
+ 	nfsd_cache_init();	/* RPC reply cache */
+ 	nfsd_export_init();	/* Exports table */
+ 	nfsd_lockd_init();	/* lockd->nfsd callbacks */
++	nfs4_state_init();	/* NFSv4 locking state */
+ #ifdef CONFIG_NFSD_V4
+ 	nfsd_idmap_init();      /* Name to ID mapping */
+ #endif /* CONFIG_NFSD_V4 */
+diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
+index 3855fdc5af77..21c6e9d86e4f 100644
+--- a/include/linux/nfsd/nfsd.h
++++ b/include/linux/nfsd/nfsd.h
+@@ -145,11 +145,13 @@ int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *);
+  * NFSv4 State
+  */
+ #ifdef CONFIG_NFSD_V4
++void nfs4_state_init(void);
+ int nfs4_state_start(void);
+ void nfs4_state_shutdown(void);
+ time_t nfs4_lease_time(void);
+ void nfs4_reset_lease(time_t leasetime);
+ #else
++static inline void nfs4_state_init(void){};
+ static inline int nfs4_state_start(void){return 0;}
+ static inline void nfs4_state_shutdown(void){}
+ static inline time_t nfs4_lease_time(void){return 0;}

commit 76a3550ec50ed86885a10a767ebaebb7c9104721
+Author: NeilBrown 
+Date:   Thu Jun 23 22:03:26 2005 -0700
+
+    [PATCH] knfsd: nfsd4: rename nfs4_state_init
+    
+    Somewhat gratuitous rename to simplify following patch.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 0f6119714c8c..e00b3472851c 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -3185,7 +3185,7 @@ nfs4_check_open_reclaim(clientid_t *clid)
+  */
+ 
+ static void
+-__nfs4_state_init(void)
++__nfs4_state_start(void)
+ {
+ 	int i;
+ 	time_t grace_time;
+@@ -3235,7 +3235,7 @@ __nfs4_state_init(void)
+ }
+ 
+ int
+-nfs4_state_init(void)
++nfs4_state_start(void)
+ {
+ 	int status;
+ 
+@@ -3244,7 +3244,7 @@ nfs4_state_init(void)
+ 	status = nfsd4_init_slabs();
+ 	if (status)
+ 		return status;
+-	__nfs4_state_init();
++	__nfs4_state_start();
+ 	nfs4_init = 1;
+ 	return 0;
+ }
+diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
+index 904df604e86b..07b9a065e9da 100644
+--- a/fs/nfsd/nfssvc.c
++++ b/fs/nfsd/nfssvc.c
+@@ -95,7 +95,7 @@ nfsd_svc(unsigned short port, int nrservs)
+ 	error =	nfsd_racache_init(2*nrservs);
+ 	if (error<0)
+ 		goto out;
+-	error = nfs4_state_init();
++	error = nfs4_state_start();
+ 	if (error<0)
+ 		goto out;
+ 	if (!nfsd_serv) {
+diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
+index 4bf931d5ff56..3855fdc5af77 100644
+--- a/include/linux/nfsd/nfsd.h
++++ b/include/linux/nfsd/nfsd.h
+@@ -145,12 +145,12 @@ int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *);
+  * NFSv4 State
+  */
+ #ifdef CONFIG_NFSD_V4
+-int nfs4_state_init(void);
++int nfs4_state_start(void);
+ void nfs4_state_shutdown(void);
+ time_t nfs4_lease_time(void);
+ void nfs4_reset_lease(time_t leasetime);
+ #else
+-static inline int nfs4_state_init(void){return 0;}
++static inline int nfs4_state_start(void){return 0;}
+ static inline void nfs4_state_shutdown(void){}
+ static inline time_t nfs4_lease_time(void){return 0;}
+ static inline void nfs4_reset_lease(time_t leasetime){}

commit 7b190fecfa33d72bcf74c9473134c2ad14ae9545
+Author: NeilBrown 
+Date:   Thu Jun 23 22:03:23 2005 -0700
+
+    [PATCH] knfsd: nfsd4: delegation recovery
+    
+    Allow recovery of delegations after reboot.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 16c9a43218c3..0f6119714c8c 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1709,14 +1709,30 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
+ 	int status, flag = 0;
+ 
+ 	flag = NFS4_OPEN_DELEGATE_NONE;
+-	if (open->op_claim_type != NFS4_OPEN_CLAIM_NULL
+-	     || !atomic_read(&cb->cb_set) || !sop->so_confirmed)
+-		goto out;
+-
+-	if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
+-		flag = NFS4_OPEN_DELEGATE_WRITE;
+-	else
+-		flag = NFS4_OPEN_DELEGATE_READ;
++	open->op_recall = 0;
++	switch (open->op_claim_type) {
++		case NFS4_OPEN_CLAIM_PREVIOUS:
++			if (!atomic_read(&cb->cb_set))
++				open->op_recall = 1;
++			flag = open->op_delegate_type;
++			if (flag == NFS4_OPEN_DELEGATE_NONE)
++				goto out;
++			break;
++		case NFS4_OPEN_CLAIM_NULL:
++			/* Let's not give out any delegations till everyone's
++			 * had the chance to reclaim theirs.... */
++			if (nfs4_in_grace())
++				goto out;
++			if (!atomic_read(&cb->cb_set) || !sop->so_confirmed)
++				goto out;
++			if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
++				flag = NFS4_OPEN_DELEGATE_WRITE;
++			else
++				flag = NFS4_OPEN_DELEGATE_READ;
++			break;
++		default:
++			goto out;
++	}
+ 
+ 	dp = alloc_init_deleg(sop->so_client, stp, fh, flag);
+ 	if (dp == NULL) {
+@@ -1750,6 +1766,10 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
+ 	             dp->dl_stateid.si_fileid,
+ 	             dp->dl_stateid.si_generation);
+ out:
++	if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS
++			&& flag == NFS4_OPEN_DELEGATE_NONE
++			&& open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE)
++		printk("NFSD: WARNING: refusing delegation reclaim\n");
+ 	open->op_delegate_type = flag;
+ }
+ 
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index 0ae1467c3bc3..cfe978a72cea 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -1972,7 +1972,7 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_open
+ 	case NFS4_OPEN_DELEGATE_READ:
+ 		RESERVE_SPACE(20 + sizeof(stateid_t));
+ 		WRITEMEM(&open->op_delegate_stateid, sizeof(stateid_t));
+-		WRITE32(0);
++		WRITE32(open->op_recall);
+ 
+ 		/*
+ 		 * TODO: ACE's in delegations
+diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
+index a1f5ad0be1bf..4d24d65c0e88 100644
+--- a/include/linux/nfsd/xdr4.h
++++ b/include/linux/nfsd/xdr4.h
+@@ -210,6 +210,7 @@ struct nfsd4_open {
+ 	u32		op_share_access;    /* request */
+ 	u32		op_share_deny;      /* request */
+ 	stateid_t	op_stateid;         /* response */
++	u32		op_recall;          /* recall */
+ 	struct nfsd4_change_info  op_cinfo; /* response */
+ 	u32		op_rflags;          /* response */
+ 	int		op_truncate;        /* used during processing */

commit d99a05adf8490cc171b7709554936b8f3ac9e362
+Author: NeilBrown 
+Date:   Thu Jun 23 22:03:21 2005 -0700
+
+    [PATCH] knfsd: nfsd4: simplify lease changing
+    
+    The only way the protocol gives to change the lease time on the fly is to
+    simulate a reboot.  We don't have that completely right in the current code;
+    among other things, we should probably put lockd in grace too while we do
+    this.
+    
+    For now, let's just keep this simple, and wait till the next time nfsd starts
+    to register any changes in lease time.  If the administrator really wants to
+    change the lease time *now*, they can go ahead and bring nfsd down and then
+    back up again after changing the lease time.
+    
+    Also remove the "if (reclaim_str_hashtbl_size == 0)" case, a shortcut which
+    skips the grace period if we know of no clients in need of recovery.  This
+    isn't going to work well with nlm.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 9bec088e7657..16c9a43218c3 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -53,7 +53,7 @@
+ 
+ /* Globals */
+ static time_t lease_time = 90;     /* default lease time */
+-static time_t old_lease_time = 90; /* past incarnation lease time */
++static time_t user_lease_time = 90;
+ static u32 nfs4_reclaim_init = 0;
+ time_t boot_time;
+ static time_t grace_end = 0;
+@@ -3205,11 +3205,9 @@ __nfs4_state_init(void)
+ 	INIT_LIST_HEAD(&del_recall_lru);
+ 	spin_lock_init(&recall_lock);
+ 	boot_time = get_seconds();
+-	grace_time = max(old_lease_time, lease_time);
+-	if (reclaim_str_hashtbl_size == 0)
+-		grace_time = 0;
+-	if (grace_time)
+-		printk("NFSD: starting %ld-second grace period\n", grace_time);
++	grace_time = max(user_lease_time, lease_time);
++	lease_time = user_lease_time;
++	printk("NFSD: starting %ld-second grace period\n", grace_time);
+ 	grace_end = boot_time + grace_time;
+ 	INIT_WORK(&laundromat_work,laundromat_main, NULL);
+ 	laundry_wq = create_singlethread_workqueue("nfsd4");
+@@ -3307,53 +3305,16 @@ nfs4_state_shutdown(void)
+ /*
+  * Called when leasetime is changed.
+  *
+- * if nfsd is not started, simply set the global lease.
+- *
+- * if nfsd(s) are running, lease change requires nfsv4 state to be reset.
+- * e.g: boot_time is reset, existing nfs4_client structs are
+- * used to fill reclaim_str_hashtbl, then all state (except for the
+- * reclaim_str_hashtbl) is re-initialized.
+- *
+- * if the old lease time is greater than the new lease time, the grace
+- * period needs to be set to the old lease time to allow clients to reclaim
+- * their state. XXX - we may want to set the grace period == lease time
+- * after an initial grace period == old lease time
+- *
+- * if an error occurs in this process, the new lease is set, but the server
+- * will not honor OPEN or LOCK reclaims, and will return nfserr_no_grace
+- * which means OPEN/LOCK/READ/WRITE will fail during grace period.
+- *
+- * clients will attempt to reset all state with SETCLIENTID/CONFIRM, and
+- * OPEN and LOCK reclaims.
++ * The only way the protocol gives us to handle on-the-fly lease changes is to
++ * simulate a reboot.  Instead of doing that, we just wait till the next time
++ * we start to register any changes in lease time.  If the administrator
++ * really wants to change the lease time *now*, they can go ahead and bring
++ * nfsd down and then back up again after changing the lease time.
+  */
+ void
+ nfs4_reset_lease(time_t leasetime)
+ {
+-	struct nfs4_client *clp;
+-	int i;
+-
+-	printk("NFSD: New leasetime %ld\n",leasetime);
+-	if (!nfs4_init)
+-		return;
+-	nfs4_lock_state();
+-	old_lease_time = lease_time;
+-	lease_time = leasetime;
+-
+-	nfs4_release_reclaim();
+-
+-	/* populate reclaim_str_hashtbl with current confirmed nfs4_clientid */
+-	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
+-		list_for_each_entry(clp, &conf_id_hashtbl[i], cl_idhash) {
+-			if (!nfs4_client_to_reclaim(clp->cl_name.data,
+-						clp->cl_name.len)) {
+-				nfs4_release_reclaim();
+-				goto init_state;
+-			}
+-		}
+-	}
+-init_state:
+-	__nfs4_state_shutdown();
+-	__nfs4_state_init();
+-	nfs4_unlock_state();
++	lock_kernel();
++	user_lease_time = leasetime;
++	unlock_kernel();
+ }
+-

commit 58da282b733cff4caef805c6555c7a3b90772946
+Author: NeilBrown 
+Date:   Thu Jun 23 22:03:19 2005 -0700
+
+    [PATCH] knfsd: nfsd4: create separate laundromat workqueue
+    
+    We're running the laundromat work on the default kevent worker thread.  But
+    the laundromat takes the nfsv4 state semaphore, which is used for way too much
+    stuff, and the potential for deadlocks is high.  Better to have this on a
+    separate workqueue.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 2a5f00b0ee99..9bec088e7657 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1844,6 +1844,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
+ 	return status;
+ }
+ 
++static struct workqueue_struct *laundry_wq;
+ static struct work_struct laundromat_work;
+ static void laundromat_main(void *);
+ static DECLARE_WORK(laundromat_work, laundromat_main, NULL);
+@@ -1951,7 +1952,7 @@ laundromat_main(void *not_used)
+ 
+ 	t = nfs4_laundromat();
+ 	dprintk("NFSD: laundromat_main - sleeping for %ld seconds\n", t);
+-	schedule_delayed_work(&laundromat_work, t*HZ);
++	queue_delayed_work(laundry_wq, &laundromat_work, t*HZ);
+ }
+ 
+ /* search ownerid_hashtbl[] and close_lru for stateid owner
+@@ -3211,7 +3212,8 @@ __nfs4_state_init(void)
+ 		printk("NFSD: starting %ld-second grace period\n", grace_time);
+ 	grace_end = boot_time + grace_time;
+ 	INIT_WORK(&laundromat_work,laundromat_main, NULL);
+-	schedule_delayed_work(&laundromat_work, NFSD_LEASE_TIME*HZ);
++	laundry_wq = create_singlethread_workqueue("nfsd4");
++	queue_delayed_work(laundry_wq, &laundromat_work, NFSD_LEASE_TIME*HZ);
+ }
+ 
+ int
+@@ -3287,7 +3289,8 @@ __nfs4_state_shutdown(void)
+ 	}
+ 
+ 	cancel_delayed_work(&laundromat_work);
+-	flush_scheduled_work();
++	flush_workqueue(laundry_wq);
++	destroy_workqueue(laundry_wq);
+ 	nfs4_init = 0;
+ }
+ 

commit dfc8356570b6fcb4035c7d916ade5bbbe6c3b50a
+Author: NeilBrown 
+Date:   Thu Jun 23 22:03:16 2005 -0700
+
+    [PATCH] knfsd: nfsd4: nfs4_check_open_reclaim cleanup
+    
+    Minor cleanup.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 6ba428afa433..2a5f00b0ee99 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -3155,11 +3155,7 @@ nfs4_find_reclaim_client(clientid_t *clid)
+ int
+ nfs4_check_open_reclaim(clientid_t *clid)
+ {
+-	struct nfs4_client_reclaim *crp;
+-
+-	if ((crp = nfs4_find_reclaim_client(clid)) == NULL)
+-		return nfserr_reclaim_bad;
+-	return nfs_ok;
++	return nfs4_find_reclaim_client(clid) ? nfs_ok : nfserr_reclaim_bad;
+ }
+ 
+ 

commit 5ba266d6323e957588712f6a7d31252cd6b797bb
+Author: NeilBrown 
+Date:   Thu Jun 23 22:03:15 2005 -0700
+
+    [PATCH] knfsd: nfsd4: fix probe_callback
+    
+    rpc_create_client was modified recently to do its own (synchronous) NULL ping
+    of the server.  We'd rather do that on our own, asynchronously, so that we
+    don't have to block the nfsd thread doing the probe, and so that setclientid
+    handling (hence, client mounts) can proceed normally whether the callback is
+    succesful or not.  (We can still function fine without the callback
+    channel--we just won't be able to give out delegations till it's verified to
+    work.)
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 634465e9cfc6..38c3e1c47d83 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -427,7 +427,7 @@ nfsd4_probe_callback(struct nfs4_client *clp)
+ 	 * XXX AUTH_UNIX only - need AUTH_GSS....
+ 	 */
+ 	sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(addr.sin_addr.s_addr));
+-	clnt = rpc_create_client(xprt, hostname, program, 1, RPC_AUTH_UNIX);
++	clnt = rpc_new_client(xprt, hostname, program, 1, RPC_AUTH_UNIX);
+ 	if (IS_ERR(clnt)) {
+ 		dprintk("NFSD: couldn't create callback client\n");
+ 		goto out_err;
+diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
+index 32e8acbc60fe..62a073495276 100644
+--- a/net/sunrpc/sunrpc_syms.c
++++ b/net/sunrpc/sunrpc_syms.c
+@@ -41,6 +41,7 @@ EXPORT_SYMBOL(rpc_release_task);
+ 
+ /* RPC client functions */
+ EXPORT_SYMBOL(rpc_create_client);
++EXPORT_SYMBOL(rpc_new_client);
+ EXPORT_SYMBOL(rpc_clone_client);
+ EXPORT_SYMBOL(rpc_bind_new_program);
+ EXPORT_SYMBOL(rpc_destroy_client);

commit 7e06b7f9e9537cb826f3cff95816fc4384b67806
+Author: NeilBrown 
+Date:   Thu Jun 23 22:03:13 2005 -0700
+
+    [PATCH] knfsd: nfs4: hold filp while reading or writing
+    
+    We're trying to read and write from a struct file that we may not hold a
+    reference to any more (since a close could be processed as soon as we drop the
+    state lock).
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index ac4878ac2213..d71f14517b9c 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -45,6 +45,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ #include 
+@@ -477,26 +478,27 @@ static inline int
+ nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read)
+ {
+ 	int status;
+-	struct file *filp = NULL;
+ 
+ 	/* no need to check permission - this will be done in nfsd_read() */
+ 
++	read->rd_filp = NULL;
+ 	if (read->rd_offset >= OFFSET_MAX)
+ 		return nfserr_inval;
+ 
+ 	nfs4_lock_state();
+ 	/* check stateid */
+ 	if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid,
+-					CHECK_FH | RD_STATE, &filp))) {
++				CHECK_FH | RD_STATE, &read->rd_filp))) {
+ 		dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
+ 		goto out;
+ 	}
++	if (read->rd_filp)
++		get_file(read->rd_filp);
+ 	status = nfs_ok;
+ out:
+ 	nfs4_unlock_state();
+ 	read->rd_rqstp = rqstp;
+ 	read->rd_fhp = current_fh;
+-	read->rd_filp = filp;
+ 	return status;
+ }
+ 
+@@ -633,6 +635,8 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
+ 		dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
+ 		goto out;
+ 	}
++	if (filp)
++		get_file(filp);
+ 	nfs4_unlock_state();
+ 
+ 	write->wr_bytes_written = write->wr_buflen;
+@@ -644,6 +648,8 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
+ 	status =  nfsd_write(rqstp, current_fh, filp, write->wr_offset,
+ 			write->wr_vec, write->wr_vlen, write->wr_buflen,
+ 			&write->wr_how_written);
++	if (filp)
++		fput(filp);
+ 
+ 	if (status == nfserr_symlink)
+ 		status = nfserr_inval;
+@@ -932,6 +938,9 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
+ 			nfs4_put_stateowner(replay_owner);
+ 			replay_owner = NULL;
+ 		}
++		/* XXX Ugh, we need to get rid of this kind of special case: */
++		if (op->opnum == OP_READ && op->u.read.rd_filp)
++			fput(op->u.read.rd_filp);
+ 	}
+ 
+ out:

commit 46be925fa6f4796e732e16a020fa0ef9d48ea7c8
+Author: NeilBrown 
+Date:   Thu Jun 23 22:03:11 2005 -0700
+
+    [PATCH] knfsd: lockd: flush signals on shutdown
+    
+    Silence another annoying "failed to contact portmap (errno -512)" on shutdown.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
+index b82e470912e8..6e242556b903 100644
+--- a/fs/lockd/svc.c
++++ b/fs/lockd/svc.c
+@@ -191,7 +191,9 @@ lockd(struct svc_rqst *rqstp)
+ 		printk(KERN_DEBUG
+ 			"lockd: new process, skipping host shutdown\n");
+ 	wake_up(&lockd_exit);
+-		
++
++	flush_signals(current);
++
+ 	/* Exit the RPC thread */
+ 	svc_exit_thread(rqstp);
+ 

commit 13cd21845d6a9729ca95e36ae6e8c669623fbfd4
+Author: NeilBrown 
+Date:   Thu Jun 23 22:03:10 2005 -0700
+
+    [PATCH] nfsd4: reference count struct nfs4_file
+    
+    Add a struct kref to each nfs4_file and take a reference to it from each
+    stateid and delegation that refers to it.  The atomicity guarantees are
+    overkill given that all this stuff is done under the single nfsd4 state lock,
+    but a) we'd like finer-grained locking some day, and b) this simplifies the
+    cleanup of the structures a bit, something that has previously been a bit
+    complicated and bug-prone.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index a84a80e8c0cf..6ba428afa433 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -111,7 +111,6 @@ opaque_hashval(const void *ptr, int nbytes)
+ /* forward declarations */
+ static void release_stateowner(struct nfs4_stateowner *sop);
+ static void release_stateid(struct nfs4_stateid *stp, int flags);
+-static void release_file(struct nfs4_file *fp);
+ 
+ /*
+  * Delegation state
+@@ -121,6 +120,27 @@ static void release_file(struct nfs4_file *fp);
+ spinlock_t recall_lock;
+ static struct list_head del_recall_lru;
+ 
++static void
++free_nfs4_file(struct kref *kref)
++{
++	struct nfs4_file *fp = container_of(kref, struct nfs4_file, fi_ref);
++	list_del(&fp->fi_hash);
++	iput(fp->fi_inode);
++	kmem_cache_free(file_slab, fp);
++}
++
++static inline void
++put_nfs4_file(struct nfs4_file *fi)
++{
++	kref_put(&fi->fi_ref, free_nfs4_file);
++}
++
++static inline void
++get_nfs4_file(struct nfs4_file *fi)
++{
++	kref_get(&fi->fi_ref);
++}
++
+ static struct nfs4_delegation *
+ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_fh *current_fh, u32 type)
+ {
+@@ -136,6 +156,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
+ 	INIT_LIST_HEAD(&dp->dl_del_perclnt);
+ 	INIT_LIST_HEAD(&dp->dl_recall_lru);
+ 	dp->dl_client = clp;
++	get_nfs4_file(fp);
+ 	dp->dl_file = fp;
+ 	dp->dl_flock = NULL;
+ 	get_file(stp->st_vfs_file);
+@@ -163,6 +184,7 @@ nfs4_put_delegation(struct nfs4_delegation *dp)
+ {
+ 	if (atomic_dec_and_test(&dp->dl_count)) {
+ 		dprintk("NFSD: freeing dp %p\n",dp);
++		put_nfs4_file(dp->dl_file);
+ 		kmem_cache_free(deleg_slab, dp);
+ 	}
+ }
+@@ -953,6 +975,7 @@ alloc_init_file(struct inode *ino)
+ 
+ 	fp = kmem_cache_alloc(file_slab, GFP_KERNEL);
+ 	if (fp) {
++		kref_init(&fp->fi_ref);
+ 		INIT_LIST_HEAD(&fp->fi_hash);
+ 		INIT_LIST_HEAD(&fp->fi_stateids);
+ 		INIT_LIST_HEAD(&fp->fi_delegations);
+@@ -964,24 +987,6 @@ alloc_init_file(struct inode *ino)
+ 	return NULL;
+ }
+ 
+-static void
+-release_all_files(void)
+-{
+-	int i;
+-	struct nfs4_file *fp;
+-
+-	for (i=0;ifi_stateids) || !list_empty(&fp->fi_delegations)) {
+-				printk("ERROR: release_all_files: file %p is open, creating dangling state !!!\n",fp);
+-			}
+-			release_file(fp);
+-		}
+-	}
+-}
+-
+ static void
+ nfsd4_free_slab(kmem_cache_t **slab)
+ {
+@@ -1141,6 +1146,7 @@ init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *
+ 	list_add(&stp->st_perfilestate, &sop->so_perfilestate);
+ 	list_add(&stp->st_perfile, &fp->fi_stateids);
+ 	stp->st_stateowner = sop;
++	get_nfs4_file(fp);
+ 	stp->st_file = fp;
+ 	stp->st_stateid.si_boot = boot_time;
+ 	stp->st_stateid.si_stateownerid = sop->so_id;
+@@ -1166,18 +1172,11 @@ release_stateid(struct nfs4_stateid *stp, int flags)
+ 		nfsd_close(filp);
+ 	} else if (flags & LOCK_STATE)
+ 		locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner);
++	put_nfs4_file(stp->st_file);
+ 	kmem_cache_free(stateid_slab, stp);
+ 	stp = NULL;
+ }
+ 
+-static void
+-release_file(struct nfs4_file *fp)
+-{
+-	list_del(&fp->fi_hash);
+-	iput(fp->fi_inode);
+-	kmem_cache_free(file_slab, fp);
+-}	
+-
+ void
+ move_to_close_lru(struct nfs4_stateowner *sop)
+ {
+@@ -1192,7 +1191,6 @@ void
+ release_state_owner(struct nfs4_stateid *stp, int flag)
+ {
+ 	struct nfs4_stateowner *sop = stp->st_stateowner;
+-	struct nfs4_file *fp = stp->st_file;
+ 
+ 	dprintk("NFSD: release_state_owner\n");
+ 	release_stateid(stp, flag);
+@@ -1203,10 +1201,6 @@ release_state_owner(struct nfs4_stateid *stp, int flag)
+ 	 */
+ 	if (sop->so_confirmed && list_empty(&sop->so_perfilestate))
+ 		move_to_close_lru(sop);
+-	/* unused nfs4_file's are releseed. XXX slab cache? */
+-	if (list_empty(&fp->fi_stateids) && list_empty(&fp->fi_delegations)) {
+-		release_file(fp);
+-	}
+ }
+ 
+ static int
+@@ -1236,8 +1230,10 @@ find_file(struct inode *ino)
+ 	struct nfs4_file *fp;
+ 
+ 	list_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) {
+-		if (fp->fi_inode == ino)
++		if (fp->fi_inode == ino) {
++			get_nfs4_file(fp);
+ 			return fp;
++		}
+ 	}
+ 	return NULL;
+ }
+@@ -1288,19 +1284,24 @@ nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
+ 	struct inode *ino = current_fh->fh_dentry->d_inode;
+ 	struct nfs4_file *fp;
+ 	struct nfs4_stateid *stp;
++	int ret;
+ 
+ 	dprintk("NFSD: nfs4_share_conflict\n");
+ 
+ 	fp = find_file(ino);
+-	if (fp) {
++	if (!fp)
++		return nfs_ok;
++	ret = nfserr_share_denied;
+ 	/* Search for conflicting share reservations */
+-		list_for_each_entry(stp, &fp->fi_stateids, st_perfile) {
+-			if (test_bit(deny_type, &stp->st_deny_bmap) ||
+-			    test_bit(NFS4_SHARE_DENY_BOTH, &stp->st_deny_bmap))
+-				return nfserr_share_denied;
+-		}
++	list_for_each_entry(stp, &fp->fi_stateids, st_perfile) {
++		if (test_bit(deny_type, &stp->st_deny_bmap) ||
++		    test_bit(NFS4_SHARE_DENY_BOTH, &stp->st_deny_bmap))
++			goto out;
+ 	}
+-	return nfs_ok;
++	ret = nfs_ok;
++out:
++	put_nfs4_file(fp);
++	return ret;
+ }
+ 
+ static inline void
+@@ -1829,10 +1830,8 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
+ 	            stp->st_stateid.si_boot, stp->st_stateid.si_stateownerid,
+ 	            stp->st_stateid.si_fileid, stp->st_stateid.si_generation);
+ out:
+-	/* take the opportunity to clean up unused state */
+-	if (fp && list_empty(&fp->fi_stateids) && list_empty(&fp->fi_delegations))
+-		release_file(fp);
+-
++	if (fp)
++		put_nfs4_file(fp);
+ 	/* CLAIM_PREVIOUS has different error returns */
+ 	nfs4_set_claim_prev(open, &status);
+ 	/*
+@@ -2480,16 +2479,19 @@ find_stateid(stateid_t *stid, int flags)
+ static struct nfs4_delegation *
+ find_delegation_stateid(struct inode *ino, stateid_t *stid)
+ {
+-	struct nfs4_file *fp = NULL;
++	struct nfs4_file *fp;
++	struct nfs4_delegation *dl;
+ 
+ 	dprintk("NFSD:find_delegation_stateid stateid=(%08x/%08x/%08x/%08x)\n",
+                     stid->si_boot, stid->si_stateownerid,
+                     stid->si_fileid, stid->si_generation);
+ 
+ 	fp = find_file(ino);
+-	if (fp)
+-		return find_delegation_file(fp, stid);
+-	return NULL;
++	if (!fp)
++		return NULL;
++	dl = find_delegation_file(fp, stid);
++	put_nfs4_file(fp);
++	return dl;
+ }
+ 
+ /*
+@@ -2636,6 +2638,7 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc
+ 	list_add(&stp->st_perfile, &fp->fi_stateids);
+ 	list_add(&stp->st_perfilestate, &sop->so_perfilestate);
+ 	stp->st_stateowner = sop;
++	get_nfs4_file(fp);
+ 	stp->st_file = fp;
+ 	stp->st_stateid.si_boot = boot_time;
+ 	stp->st_stateid.si_stateownerid = sop->so_id;
+@@ -3287,7 +3290,6 @@ __nfs4_state_shutdown(void)
+ 		unhash_delegation(dp);
+ 	}
+ 
+-	release_all_files();
+ 	cancel_delayed_work(&laundromat_work);
+ 	flush_scheduled_work();
+ 	nfs4_init = 0;
+diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
+index 2c3b42674a4c..296e6429fc3b 100644
+--- a/include/linux/nfsd/state.h
++++ b/include/linux/nfsd/state.h
+@@ -217,6 +217,7 @@ struct nfs4_stateowner {
+ *      share_acces, share_deny on the file.
+ */
+ struct nfs4_file {
++	struct kref		fi_ref;
+ 	struct list_head        fi_hash;    /* hash by "struct inode *" */
+ 	struct list_head        fi_stateids;
+ 	struct list_head	fi_delegations;

commit 8beefa249371f55432394ac96864c83b0b309c28
+Author: NeilBrown 
+Date:   Thu Jun 23 22:03:08 2005 -0700
+
+    [PATCH] nfsd4: rename nfs4_file fields
+    
+    Trivial renaming patch:
+    
+    I can never remember, while looking at various lists relating the nfsd4 state
+    structures, which are the "heads" and which are items on other lists, or which
+    structures are actually on the various lists.  The following convention helps
+    me: given structures foo and bar, with foo containing the head of a list of
+    bars, use "bars" for the name of the head of the list contained in the struct
+    foo, and use "per_foo" for the entries in the struct bars.
+    
+    Go ahead and do this for struct nfs4_file.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index f03a4180fa11..a84a80e8c0cf 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -153,7 +153,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
+ 		        current_fh->fh_handle.fh_size);
+ 	dp->dl_time = 0;
+ 	atomic_set(&dp->dl_count, 1);
+-	list_add(&dp->dl_del_perfile, &fp->fi_del_perfile);
++	list_add(&dp->dl_del_perfile, &fp->fi_delegations);
+ 	list_add(&dp->dl_del_perclnt, &clp->cl_del_perclnt);
+ 	return dp;
+ }
+@@ -954,8 +954,8 @@ alloc_init_file(struct inode *ino)
+ 	fp = kmem_cache_alloc(file_slab, GFP_KERNEL);
+ 	if (fp) {
+ 		INIT_LIST_HEAD(&fp->fi_hash);
+-		INIT_LIST_HEAD(&fp->fi_perfile);
+-		INIT_LIST_HEAD(&fp->fi_del_perfile);
++		INIT_LIST_HEAD(&fp->fi_stateids);
++		INIT_LIST_HEAD(&fp->fi_delegations);
+ 		list_add(&fp->fi_hash, &file_hashtbl[hashval]);
+ 		fp->fi_inode = igrab(ino);
+ 		fp->fi_id = current_fileid++;
+@@ -974,7 +974,7 @@ release_all_files(void)
+ 		while (!list_empty(&file_hashtbl[i])) {
+ 			fp = list_entry(file_hashtbl[i].next, struct nfs4_file, fi_hash);
+ 			/* this should never be more than once... */
+-			if (!list_empty(&fp->fi_perfile) || !list_empty(&fp->fi_del_perfile)) {
++			if (!list_empty(&fp->fi_stateids) || !list_empty(&fp->fi_delegations)) {
+ 				printk("ERROR: release_all_files: file %p is open, creating dangling state !!!\n",fp);
+ 			}
+ 			release_file(fp);
+@@ -1139,7 +1139,7 @@ init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *
+ 	INIT_LIST_HEAD(&stp->st_perfile);
+ 	list_add(&stp->st_hash, &stateid_hashtbl[hashval]);
+ 	list_add(&stp->st_perfilestate, &sop->so_perfilestate);
+-	list_add(&stp->st_perfile, &fp->fi_perfile);
++	list_add(&stp->st_perfile, &fp->fi_stateids);
+ 	stp->st_stateowner = sop;
+ 	stp->st_file = fp;
+ 	stp->st_stateid.si_boot = boot_time;
+@@ -1204,7 +1204,7 @@ release_state_owner(struct nfs4_stateid *stp, int flag)
+ 	if (sop->so_confirmed && list_empty(&sop->so_perfilestate))
+ 		move_to_close_lru(sop);
+ 	/* unused nfs4_file's are releseed. XXX slab cache? */
+-	if (list_empty(&fp->fi_perfile) && list_empty(&fp->fi_del_perfile)) {
++	if (list_empty(&fp->fi_stateids) && list_empty(&fp->fi_delegations)) {
+ 		release_file(fp);
+ 	}
+ }
+@@ -1294,7 +1294,7 @@ nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
+ 	fp = find_file(ino);
+ 	if (fp) {
+ 	/* Search for conflicting share reservations */
+-		list_for_each_entry(stp, &fp->fi_perfile, st_perfile) {
++		list_for_each_entry(stp, &fp->fi_stateids, st_perfile) {
+ 			if (test_bit(deny_type, &stp->st_deny_bmap) ||
+ 			    test_bit(NFS4_SHARE_DENY_BOTH, &stp->st_deny_bmap))
+ 				return nfserr_share_denied;
+@@ -1545,7 +1545,7 @@ find_delegation_file(struct nfs4_file *fp, stateid_t *stid)
+ {
+ 	struct nfs4_delegation *dp;
+ 
+-	list_for_each_entry(dp, &fp->fi_del_perfile, dl_del_perfile) {
++	list_for_each_entry(dp, &fp->fi_delegations, dl_del_perfile) {
+ 		if (dp->dl_stateid.si_stateownerid == stid->si_stateownerid)
+ 			return dp;
+ 	}
+@@ -1583,7 +1583,7 @@ nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_state
+ 	int status = nfserr_share_denied;
+ 	struct nfs4_stateowner *sop = open->op_stateowner;
+ 
+-	list_for_each_entry(local, &fp->fi_perfile, st_perfile) {
++	list_for_each_entry(local, &fp->fi_stateids, st_perfile) {
+ 		/* ignore lock owners */
+ 		if (local->st_stateowner->so_is_open_owner == 0)
+ 			continue;
+@@ -1830,7 +1830,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
+ 	            stp->st_stateid.si_fileid, stp->st_stateid.si_generation);
+ out:
+ 	/* take the opportunity to clean up unused state */
+-	if (fp && list_empty(&fp->fi_perfile) && list_empty(&fp->fi_del_perfile))
++	if (fp && list_empty(&fp->fi_stateids) && list_empty(&fp->fi_delegations))
+ 		release_file(fp);
+ 
+ 	/* CLAIM_PREVIOUS has different error returns */
+@@ -2633,7 +2633,7 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc
+ 	INIT_LIST_HEAD(&stp->st_perfilestate);
+ 	INIT_LIST_HEAD(&stp->st_perlockowner); /* not used */
+ 	list_add(&stp->st_hash, &lockstateid_hashtbl[hashval]);
+-	list_add(&stp->st_perfile, &fp->fi_perfile);
++	list_add(&stp->st_perfile, &fp->fi_stateids);
+ 	list_add(&stp->st_perfilestate, &sop->so_perfilestate);
+ 	stp->st_stateowner = sop;
+ 	stp->st_file = fp;
+diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
+index b6b2fe1e7c63..2c3b42674a4c 100644
+--- a/include/linux/nfsd/state.h
++++ b/include/linux/nfsd/state.h
+@@ -218,8 +218,8 @@ struct nfs4_stateowner {
+ */
+ struct nfs4_file {
+ 	struct list_head        fi_hash;    /* hash by "struct inode *" */
+-	struct list_head        fi_perfile; /* list: nfs4_stateid */
+-	struct list_head	fi_del_perfile; /* list: nfs4_delegation */
++	struct list_head        fi_stateids;
++	struct list_head	fi_delegations;
+ 	struct inode		*fi_inode;
+ 	u32                     fi_id;      /* used with stateowner->so_id 
+ 					     * for stateid_hashtbl hash */

commit 6fa305ded4cc859deb4727ad9b25df0bbc064e99
+Author: NeilBrown 
+Date:   Thu Jun 23 22:03:06 2005 -0700
+
+    [PATCH] nfsd4: remove debugging counters
+    
+    These remaining debugging counters haven't proved that useful.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 927d2007d5ab..f03a4180fa11 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -65,14 +65,6 @@ static u32 nfs4_init;
+ stateid_t zerostateid;             /* bits all 0 */
+ stateid_t onestateid;              /* bits all 1 */
+ 
+-/* debug counters */
+-u32 list_add_perfile = 0; 
+-u32 list_del_perfile = 0;
+-u32 add_perclient = 0;
+-u32 del_perclient = 0;
+-u32 vfsopen = 0;
+-u32 vfsclose = 0;
+-
+ /* forward declarations */
+ struct nfs4_stateid * find_stateid(stateid_t *stid, int flags);
+ static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid);
+@@ -192,7 +184,6 @@ nfs4_close_delegation(struct nfs4_delegation *dp)
+ 	if (dp->dl_flock)
+ 		setlease(filp, F_UNLCK, &dp->dl_flock);
+ 	nfsd_close(filp);
+-	vfsclose++;
+ }
+ 
+ /* Called under the state lock. */
+@@ -1083,7 +1074,6 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
+ 	list_add(&sop->so_idhash, &ownerid_hashtbl[idhashval]);
+ 	list_add(&sop->so_strhash, &ownerstr_hashtbl[strhashval]);
+ 	list_add(&sop->so_perclient, &clp->cl_perclient);
+-	add_perclient++;
+ 	sop->so_is_open_owner = 1;
+ 	sop->so_id = current_ownerid++;
+ 	sop->so_client = clp;
+@@ -1117,10 +1107,8 @@ unhash_stateowner(struct nfs4_stateowner *sop)
+ 
+ 	list_del(&sop->so_idhash);
+ 	list_del(&sop->so_strhash);
+-	if (sop->so_is_open_owner) {
++	if (sop->so_is_open_owner)
+ 		list_del(&sop->so_perclient);
+-		del_perclient++;
+-	}
+ 	list_del(&sop->so_perlockowner);
+ 	while (!list_empty(&sop->so_perfilestate)) {
+ 		stp = list_entry(sop->so_perfilestate.next, 
+@@ -1151,7 +1139,6 @@ init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *
+ 	INIT_LIST_HEAD(&stp->st_perfile);
+ 	list_add(&stp->st_hash, &stateid_hashtbl[hashval]);
+ 	list_add(&stp->st_perfilestate, &sop->so_perfilestate);
+-	list_add_perfile++;
+ 	list_add(&stp->st_perfile, &fp->fi_perfile);
+ 	stp->st_stateowner = sop;
+ 	stp->st_file = fp;
+@@ -1171,14 +1158,12 @@ release_stateid(struct nfs4_stateid *stp, int flags)
+ 	struct file *filp = stp->st_vfs_file;
+ 
+ 	list_del(&stp->st_hash);
+-	list_del_perfile++;
+ 	list_del(&stp->st_perfile);
+ 	list_del(&stp->st_perfilestate);
+ 	if (flags & OPEN_STATE) {
+ 		release_stateid_lockowners(stp);
+ 		stp->st_vfs_file = NULL;
+ 		nfsd_close(filp);
+-		vfsclose++;
+ 	} else if (flags & LOCK_STATE)
+ 		locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner);
+ 	kmem_cache_free(stateid_slab, stp);
+@@ -1645,7 +1630,6 @@ nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp,
+ 			return status;
+ 		}
+ 	}
+-	vfsopen++;
+ 	*stpp = stp;
+ 	return 0;
+ }
+@@ -2650,7 +2634,6 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc
+ 	INIT_LIST_HEAD(&stp->st_perlockowner); /* not used */
+ 	list_add(&stp->st_hash, &lockstateid_hashtbl[hashval]);
+ 	list_add(&stp->st_perfile, &fp->fi_perfile);
+-	list_add_perfile++;
+ 	list_add(&stp->st_perfilestate, &sop->so_perfilestate);
+ 	stp->st_stateowner = sop;
+ 	stp->st_file = fp;
+@@ -3308,12 +3291,6 @@ __nfs4_state_shutdown(void)
+ 	cancel_delayed_work(&laundromat_work);
+ 	flush_scheduled_work();
+ 	nfs4_init = 0;
+-	dprintk("NFSD: list_add_perfile %d list_del_perfile %d\n",
+-			list_add_perfile, list_del_perfile);
+-	dprintk("NFSD: add_perclient %d del_perclient %d\n",
+-			add_perclient, del_perclient);
+-	dprintk("NFSD: vfsopen %d vfsclose %d\n",
+-			vfsopen, vfsclose);
+ }
+ 
+ void

commit 5b2d21c1965859acc881dd862b6ebbfae67cdc14
+Author: NeilBrown 
+Date:   Thu Jun 23 22:03:04 2005 -0700
+
+    [PATCH] nfsd4: slabify delegations
+    
+    Allocate delegations from a slab cache.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index c5fce309d87e..927d2007d5ab 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -72,8 +72,6 @@ u32 add_perclient = 0;
+ u32 del_perclient = 0;
+ u32 vfsopen = 0;
+ u32 vfsclose = 0;
+-u32 alloc_delegation= 0;
+-u32 free_delegation= 0;
+ 
+ /* forward declarations */
+ struct nfs4_stateid * find_stateid(stateid_t *stid, int flags);
+@@ -91,6 +89,7 @@ static DECLARE_MUTEX(client_sema);
+ kmem_cache_t *stateowner_slab = NULL;
+ kmem_cache_t *file_slab = NULL;
+ kmem_cache_t *stateid_slab = NULL;
++kmem_cache_t *deleg_slab = NULL;
+ 
+ void
+ nfs4_lock_state(void)
+@@ -138,8 +137,8 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
+ 	struct nfs4_callback *cb = &stp->st_stateowner->so_client->cl_callback;
+ 
+ 	dprintk("NFSD alloc_init_deleg\n");
+-	if ((dp = kmalloc(sizeof(struct nfs4_delegation),
+-		GFP_KERNEL)) == NULL)
++	dp = kmem_cache_alloc(deleg_slab, GFP_KERNEL);
++	if (dp == NULL)
+ 		return dp;
+ 	INIT_LIST_HEAD(&dp->dl_del_perfile);
+ 	INIT_LIST_HEAD(&dp->dl_del_perclnt);
+@@ -164,7 +163,6 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
+ 	atomic_set(&dp->dl_count, 1);
+ 	list_add(&dp->dl_del_perfile, &fp->fi_del_perfile);
+ 	list_add(&dp->dl_del_perclnt, &clp->cl_del_perclnt);
+-	alloc_delegation++;
+ 	return dp;
+ }
+ 
+@@ -173,8 +171,7 @@ nfs4_put_delegation(struct nfs4_delegation *dp)
+ {
+ 	if (atomic_dec_and_test(&dp->dl_count)) {
+ 		dprintk("NFSD: freeing dp %p\n",dp);
+-		kfree(dp);
+-		free_delegation++;
++		kmem_cache_free(deleg_slab, dp);
+ 	}
+ }
+ 
+@@ -1012,6 +1009,7 @@ nfsd4_free_slabs(void)
+ 	nfsd4_free_slab(&stateowner_slab);
+ 	nfsd4_free_slab(&file_slab);
+ 	nfsd4_free_slab(&stateid_slab);
++	nfsd4_free_slab(&deleg_slab);
+ }
+ 
+ static int
+@@ -1029,6 +1027,10 @@ nfsd4_init_slabs(void)
+ 			sizeof(struct nfs4_stateid), 0, 0, NULL, NULL);
+ 	if (stateid_slab == NULL)
+ 		goto out_nomem;
++	deleg_slab = kmem_cache_create("nfsd4_delegations",
++			sizeof(struct nfs4_delegation), 0, 0, NULL, NULL);
++	if (deleg_slab == NULL)
++		goto out_nomem;
+ 	return 0;
+ out_nomem:
+ 	nfsd4_free_slabs();
+@@ -3312,9 +3314,6 @@ __nfs4_state_shutdown(void)
+ 			add_perclient, del_perclient);
+ 	dprintk("NFSD: vfsopen %d vfsclose %d\n",
+ 			vfsopen, vfsclose);
+-	dprintk("NFSD: alloc_delegation %d free_delegation %d\n",
+-			alloc_delegation, free_delegation);
+-
+ }
+ 
+ void

commit 5ac049ac66416bbe84923f7c2384f23f6ee4aa88
+Author: NeilBrown 
+Date:   Thu Jun 23 22:03:03 2005 -0700
+
+    [PATCH] nfsd4: slabify stateids
+    
+    Allocate stateid's from a slab cache.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 260c1cbe25c4..c5fce309d87e 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -90,6 +90,7 @@ static DECLARE_MUTEX(client_sema);
+ 
+ kmem_cache_t *stateowner_slab = NULL;
+ kmem_cache_t *file_slab = NULL;
++kmem_cache_t *stateid_slab = NULL;
+ 
+ void
+ nfs4_lock_state(void)
+@@ -1010,6 +1011,7 @@ nfsd4_free_slabs(void)
+ {
+ 	nfsd4_free_slab(&stateowner_slab);
+ 	nfsd4_free_slab(&file_slab);
++	nfsd4_free_slab(&stateid_slab);
+ }
+ 
+ static int
+@@ -1023,6 +1025,10 @@ nfsd4_init_slabs(void)
+ 			sizeof(struct nfs4_file), 0, 0, NULL, NULL);
+ 	if (file_slab == NULL)
+ 		goto out_nomem;
++	stateid_slab = kmem_cache_create("nfsd4_stateids",
++			sizeof(struct nfs4_stateid), 0, 0, NULL, NULL);
++	if (stateid_slab == NULL)
++		goto out_nomem;
+ 	return 0;
+ out_nomem:
+ 	nfsd4_free_slabs();
+@@ -1173,7 +1179,7 @@ release_stateid(struct nfs4_stateid *stp, int flags)
+ 		vfsclose++;
+ 	} else if (flags & LOCK_STATE)
+ 		locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner);
+-	kfree(stp);
++	kmem_cache_free(stateid_slab, stp);
+ 	stp = NULL;
+ }
+ 
+@@ -1606,6 +1612,12 @@ nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_state
+ 	return status;
+ }
+ 
++static inline struct nfs4_stateid *
++nfs4_alloc_stateid(void)
++{
++	return kmem_cache_alloc(stateid_slab, GFP_KERNEL);
++}
++
+ static int
+ nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp,
+ 		struct nfs4_delegation *dp,
+@@ -1613,7 +1625,7 @@ nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp,
+ {
+ 	struct nfs4_stateid *stp;
+ 
+-	stp = kmalloc(sizeof(struct nfs4_stateid), GFP_KERNEL);
++	stp = nfs4_alloc_stateid();
+ 	if (stp == NULL)
+ 		return nfserr_resource;
+ 
+@@ -1627,7 +1639,7 @@ nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp,
+ 		if (status) {
+ 			if (status == nfserr_dropit)
+ 				status = nfserr_jukebox;
+-			kfree(stp);
++			kmem_cache_free(stateid_slab, stp);
+ 			return status;
+ 		}
+ 	}
+@@ -2627,8 +2639,8 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc
+ 	struct nfs4_stateid *stp;
+ 	unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id);
+ 
+-	if ((stp = kmalloc(sizeof(struct nfs4_stateid), 
+-					GFP_KERNEL)) == NULL)
++	stp = nfs4_alloc_stateid();
++	if (stp == NULL)
+ 		goto out;
+ 	INIT_LIST_HEAD(&stp->st_hash);
+ 	INIT_LIST_HEAD(&stp->st_perfile);

commit e60d4398a7c20fbe9c4a6cc39d7188ef9f65d2f1
+Author: NeilBrown 
+Date:   Thu Jun 23 22:03:01 2005 -0700
+
+    [PATCH] nfsd4: slabify nfs4_files
+    
+    The structures the server uses to keep track of various pieces of nfsv4 state
+    (open files, outstanding delegations, etc.) are likely to be allocated and
+    deallocated frequently and seem reasonable candidates for slab caches.
+    
+    While we're at it, the slab code keeps statistics that help catch leaks and
+    such, so we may as well take this chance to eliminate some debugging counters
+    that we've been keeping ourselves.
+    
+    Start with the struct nfs4_file.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 8ac0c9abe941..260c1cbe25c4 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -70,8 +70,6 @@ u32 list_add_perfile = 0;
+ u32 list_del_perfile = 0;
+ u32 add_perclient = 0;
+ u32 del_perclient = 0;
+-u32 alloc_file = 0;
+-u32 free_file = 0;
+ u32 vfsopen = 0;
+ u32 vfsclose = 0;
+ u32 alloc_delegation= 0;
+@@ -90,6 +88,9 @@ static void release_stateid_lockowners(struct nfs4_stateid *open_stp);
+  */
+ static DECLARE_MUTEX(client_sema);
+ 
++kmem_cache_t *stateowner_slab = NULL;
++kmem_cache_t *file_slab = NULL;
++
+ void
+ nfs4_lock_state(void)
+ {
+@@ -961,14 +962,14 @@ alloc_init_file(struct inode *ino)
+ 	struct nfs4_file *fp;
+ 	unsigned int hashval = file_hashval(ino);
+ 
+-	if ((fp = kmalloc(sizeof(struct nfs4_file),GFP_KERNEL))) {
++	fp = kmem_cache_alloc(file_slab, GFP_KERNEL);
++	if (fp) {
+ 		INIT_LIST_HEAD(&fp->fi_hash);
+ 		INIT_LIST_HEAD(&fp->fi_perfile);
+ 		INIT_LIST_HEAD(&fp->fi_del_perfile);
+ 		list_add(&fp->fi_hash, &file_hashtbl[hashval]);
+ 		fp->fi_inode = igrab(ino);
+ 		fp->fi_id = current_fileid++;
+-		alloc_file++;
+ 		return fp;
+ 	}
+ 	return NULL;
+@@ -992,29 +993,41 @@ release_all_files(void)
+ 	}
+ }
+ 
+-kmem_cache_t *stateowner_slab = NULL;
+-
+-static int
+-nfsd4_init_slabs(void)
++static void
++nfsd4_free_slab(kmem_cache_t **slab)
+ {
+-	stateowner_slab = kmem_cache_create("nfsd4_stateowners",
+-			sizeof(struct nfs4_stateowner), 0, 0, NULL, NULL);
+-	if (stateowner_slab == NULL) {
+-		dprintk("nfsd4: out of memory while initializing nfsv4\n");
+-		return -ENOMEM;
+-	}
+-	return 0;
++	int status;
++
++	if (*slab == NULL)
++		return;
++	status = kmem_cache_destroy(*slab);
++	*slab = NULL;
++	WARN_ON(status);
+ }
+ 
+ static void
+ nfsd4_free_slabs(void)
+ {
+-	int status = 0;
++	nfsd4_free_slab(&stateowner_slab);
++	nfsd4_free_slab(&file_slab);
++}
+ 
+-	if (stateowner_slab)
+-		status = kmem_cache_destroy(stateowner_slab);
+-	stateowner_slab = NULL;
+-	BUG_ON(status);
++static int
++nfsd4_init_slabs(void)
++{
++	stateowner_slab = kmem_cache_create("nfsd4_stateowners",
++			sizeof(struct nfs4_stateowner), 0, 0, NULL, NULL);
++	if (stateowner_slab == NULL)
++		goto out_nomem;
++	file_slab = kmem_cache_create("nfsd4_files",
++			sizeof(struct nfs4_file), 0, 0, NULL, NULL);
++	if (file_slab == NULL)
++		goto out_nomem;
++	return 0;
++out_nomem:
++	nfsd4_free_slabs();
++	dprintk("nfsd4: out of memory while initializing nfsv4\n");
++	return -ENOMEM;
+ }
+ 
+ void
+@@ -1167,10 +1180,9 @@ release_stateid(struct nfs4_stateid *stp, int flags)
+ static void
+ release_file(struct nfs4_file *fp)
+ {
+-	free_file++;
+ 	list_del(&fp->fi_hash);
+ 	iput(fp->fi_inode);
+-	kfree(fp);
++	kmem_cache_free(file_slab, fp);
+ }	
+ 
+ void
+@@ -3286,8 +3298,6 @@ __nfs4_state_shutdown(void)
+ 			list_add_perfile, list_del_perfile);
+ 	dprintk("NFSD: add_perclient %d del_perclient %d\n",
+ 			add_perclient, del_perclient);
+-	dprintk("NFSD: alloc_file %d free_file %d\n",
+-			alloc_file, free_file);
+ 	dprintk("NFSD: vfsopen %d vfsclose %d\n",
+ 			vfsopen, vfsclose);
+ 	dprintk("NFSD: alloc_delegation %d free_delegation %d\n",

commit c815afc73eeef089922449857ca4ed4d2e8950cb
+Author: NeilBrown 
+Date:   Thu Jun 23 22:03:00 2005 -0700
+
+    [PATCH] nfsd4: block metadata ops during grace period
+    
+    We currently return err_grace if a user attempts a non-reclaim open during the
+    grace period.  But we also need to prevent renames and removes, at least, to
+    ensure clients have the chance to recover state on files before they are moved
+    or deleted.
+    
+    Of course, local users could also do renames and removes during the lease
+    period, and there's not much we can do about that.  This at least will help
+    with remote users.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index eb8c1337d9ba..ac4878ac2213 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -536,6 +536,8 @@ nfsd4_remove(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_rem
+ {
+ 	int status;
+ 
++	if (nfs4_in_grace())
++		return nfserr_grace;
+ 	status = nfsd_unlink(rqstp, current_fh, 0, remove->rm_name, remove->rm_namelen);
+ 	if (status == nfserr_symlink)
+ 		return nfserr_notdir;
+@@ -554,6 +556,9 @@ nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh,
+ 
+ 	if (!save_fh->fh_dentry)
+ 		return status;
++	if (nfs4_in_grace() && !(save_fh->fh_export->ex_flags
++					& NFSEXP_NOSUBTREECHECK))
++		return nfserr_grace;
+ 	status = nfsd_rename(rqstp, save_fh, rename->rn_sname,
+ 			     rename->rn_snamelen, current_fh,
+ 			     rename->rn_tname, rename->rn_tnamelen);

commit 496400014f22c4dbdbc1e89249a2feba46939708
+Author: NeilBrown 
+Date:   Thu Jun 23 22:02:58 2005 -0700
+
+    [PATCH] nfsd4: fix fh_expire_type
+    
+    We're returning NFS4_FH_NOEXPIRE_WITH_OPEN | NFS4_FH_VOL_RENAME for the
+    fh_expire_type attribute.  This is incorrect:
+            1. The spec actually only allows NOEXPIRE_WITH_OPEN when
+               VOLATILE_ANY is also set.
+            2. Filehandles for open files can expire, if the file is removed
+               and there is a reboot.
+            3. Filehandles are only volatile on rename in the nosubtree check
+               case.
+    
+    Unfortunately, there's no way to indicate that we only expire on remove.  So
+    our only choice is FH4_VOLATILE_ANY.  Although it's redundant, we also set
+    FH4_VOL_RENAME in the subtree check case, since subtreecheck does actually
+    cause problems in practice and it seems possibly useful to give clients some
+    way to distinguish that case.
+    
+    Fix a mispelled #define while we're at it.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index 36a058a112d5..0ae1467c3bc3 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -1366,7 +1366,10 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
+ 	if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) {
+ 		if ((buflen -= 4) < 0)
+ 			goto out_resource;
+-		WRITE32( NFS4_FH_NOEXPIRE_WITH_OPEN | NFS4_FH_VOL_RENAME );
++		if (exp->ex_flags & NFSEXP_NOSUBTREECHECK)
++			WRITE32(NFS4_FH_VOLATILE_ANY);
++		else
++			WRITE32(NFS4_FH_VOLATILE_ANY|NFS4_FH_VOL_RENAME);
+ 	}
+ 	if (bmval0 & FATTR4_WORD0_CHANGE) {
+ 		/*
+diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
+index 5bb5b2fd7ba2..0c1c306cdaec 100644
+--- a/include/linux/nfs4.h
++++ b/include/linux/nfs4.h
+@@ -28,7 +28,7 @@
+ #define NFS4_ACCESS_DELETE      0x0010
+ #define NFS4_ACCESS_EXECUTE     0x0020
+ 
+-#define NFS4_FH_PERISTENT		0x0000
++#define NFS4_FH_PERSISTENT		0x0000
+ #define NFS4_FH_NOEXPIRE_WITH_OPEN	0x0001
+ #define NFS4_FH_VOLATILE_ANY		0x0002
+ #define NFS4_FH_VOL_MIGRATION		0x0004

commit 0dd3c19212961453817f219cd6200981c38564bc
+Author: NeilBrown 
+Date:   Thu Jun 23 22:02:56 2005 -0700
+
+    [PATCH] nfsd4: support CLAIM_DELEGATE_CUR
+    
+    Add OPEN claim type NFS4_OPEN_CLAIM_DELEGATE_CUR to nfsd4_open().
+    
+    A delegation stateid and a name are provided.  OPEN with O_CREAT is not legal
+    with this claim type; otherwise, use the NFS4_OPEN_CLAIM_NULL code path to
+    lookup the filename to be opened.
+    
+    Signed-off-by: Andy Adamson 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index e8158741e8b5..eb8c1337d9ba 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -198,6 +198,11 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
+ 	if (status)
+ 		goto out;
+ 	switch (open->op_claim_type) {
++		case NFS4_OPEN_CLAIM_DELEGATE_CUR:
++			status = nfserr_inval;
++			if (open->op_create)
++				goto out;
++			/* fall through */
+ 		case NFS4_OPEN_CLAIM_NULL:
+ 			/*
+ 			 * (1) set CURRENT_FH to the file being opened,
+@@ -220,7 +225,6 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
+ 			if (status)
+ 				goto out;
+ 			break;
+-		case NFS4_OPEN_CLAIM_DELEGATE_CUR:
+              	case NFS4_OPEN_CLAIM_DELEGATE_PREV:
+ 			printk("NFSD: unsupported OPEN claim type %d\n",
+ 				open->op_claim_type);

commit c44c5eeb2c022ddac98a8543c08dc8ff820561dc
+Author: NeilBrown 
+Date:   Thu Jun 23 22:02:54 2005 -0700
+
+    [PATCH] nfsd4: add open state code for CLAIM_DELEGATE_CUR
+    
+    State logic for OPEN with claim type CLAIM_DELEGATE_CUR, which the NFSv4
+    client uses to report local OPENs on a delegated file back to the NFSv4
+    server.
+    
+    nfs4_check_deleg() performs input delegation stateid lookup and sanity check.
+    
+    Signed-off-by: Andy Adamson 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 3791c9d84dad..8ac0c9abe941 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1547,22 +1547,28 @@ find_delegation_file(struct nfs4_file *fp, stateid_t *stid)
+ 	return NULL;
+ }
+ 
+-static void
++static int
+ nfs4_check_deleg(struct nfs4_file *fp, struct nfsd4_open *open,
+ 		struct nfs4_delegation **dp)
+ {
+ 	int flags;
+-	int status;
++	int status = nfserr_bad_stateid;
+ 
+ 	*dp = find_delegation_file(fp, &open->op_delegate_stateid);
+ 	if (*dp == NULL)
+-		return;
++		goto out;
+ 	flags = open->op_share_access == NFS4_SHARE_ACCESS_READ ?
+ 						RD_STATE : WR_STATE;
+ 	status = nfs4_check_delegmode(*dp, flags);
+ 	if (status)
+ 		*dp = NULL;
+-	return;
++out:
++	if (open->op_claim_type != NFS4_OPEN_CLAIM_DELEGATE_CUR)
++		return nfs_ok;
++	if (status)
++		return status;
++	open->op_stateowner->so_confirmed = 1;
++	return nfs_ok;
+ }
+ 
+ static int
+@@ -1760,8 +1766,13 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
+ 	if (fp) {
+ 		if ((status = nfs4_check_open(fp, open, &stp)))
+ 			goto out;
+-		nfs4_check_deleg(fp, open, &dp);
++		status = nfs4_check_deleg(fp, open, &dp);
++		if (status)
++			goto out;
+ 	} else {
++		status = nfserr_bad_stateid;
++		if (open->op_claim_type == NFS4_OPEN_CLAIM_DELEGATE_CUR)
++			goto out;
+ 		status = nfserr_resource;
+ 		fp = alloc_init_file(ino);
+ 		if (fp == NULL)

commit 567d98292e81033182e3da4c33b41ada9c113447
+Author: NeilBrown 
+Date:   Thu Jun 23 22:02:53 2005 -0700
+
+    [PATCH] nfsd4: don't reopen for delegated client
+    
+    We don't really need to be doing a separate open for every stateid.  And in
+    the case of an open from a client that already has a delegation on a file, it
+    unnecessarily results in a delegation recall.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 31f7082df49f..3791c9d84dad 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1547,6 +1547,24 @@ find_delegation_file(struct nfs4_file *fp, stateid_t *stid)
+ 	return NULL;
+ }
+ 
++static void
++nfs4_check_deleg(struct nfs4_file *fp, struct nfsd4_open *open,
++		struct nfs4_delegation **dp)
++{
++	int flags;
++	int status;
++
++	*dp = find_delegation_file(fp, &open->op_delegate_stateid);
++	if (*dp == NULL)
++		return;
++	flags = open->op_share_access == NFS4_SHARE_ACCESS_READ ?
++						RD_STATE : WR_STATE;
++	status = nfs4_check_delegmode(*dp, flags);
++	if (status)
++		*dp = NULL;
++	return;
++}
++
+ static int
+ nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_stateid **stpp)
+ {
+@@ -1572,21 +1590,28 @@ nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_state
+ 
+ static int
+ nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp,
++		struct nfs4_delegation *dp,
+ 		struct svc_fh *cur_fh, int flags)
+ {
+ 	struct nfs4_stateid *stp;
+-	int status;
+ 
+ 	stp = kmalloc(sizeof(struct nfs4_stateid), GFP_KERNEL);
+ 	if (stp == NULL)
+ 		return nfserr_resource;
+ 
+-	status = nfsd_open(rqstp, cur_fh, S_IFREG, flags, &stp->st_vfs_file);
+-	if (status) {
+-		if (status == nfserr_dropit)
+-			status = nfserr_jukebox;
+-		kfree(stp);
+-		return status;
++	if (dp) {
++		get_file(dp->dl_vfs_file);
++		stp->st_vfs_file = dp->dl_vfs_file;
++	} else {
++		int status;
++		status = nfsd_open(rqstp, cur_fh, S_IFREG, flags,
++				&stp->st_vfs_file);
++		if (status) {
++			if (status == nfserr_dropit)
++				status = nfserr_jukebox;
++			kfree(stp);
++			return status;
++		}
+ 	}
+ 	vfsopen++;
+ 	*stpp = stp;
+@@ -1720,6 +1745,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
+ 	struct nfs4_file *fp = NULL;
+ 	struct inode *ino = current_fh->fh_dentry->d_inode;
+ 	struct nfs4_stateid *stp = NULL;
++	struct nfs4_delegation *dp = NULL;
+ 	int status;
+ 
+ 	status = nfserr_inval;
+@@ -1734,6 +1760,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
+ 	if (fp) {
+ 		if ((status = nfs4_check_open(fp, open, &stp)))
+ 			goto out;
++		nfs4_check_deleg(fp, open, &dp);
+ 	} else {
+ 		status = nfserr_resource;
+ 		fp = alloc_init_file(ino);
+@@ -1757,7 +1784,8 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
+ 			flags = MAY_WRITE;
+ 		else
+ 			flags = MAY_READ;
+-		if ((status = nfs4_new_open(rqstp, &stp, current_fh, flags)))
++		status = nfs4_new_open(rqstp, &stp, dp, current_fh, flags);
++		if (status)
+ 			goto out;
+ 		init_stateid(stp, fp, open);
+ 		status = nfsd4_truncate(rqstp, current_fh, open);

commit 4a6e43e6d4e43723699879f421d321e39eab5e41
+Author: NeilBrown 
+Date:   Thu Jun 23 22:02:50 2005 -0700
+
+    [PATCH] nfsd4: nfs4_check_delegmode
+    
+    Additional minor code reshuffling to prepare for claim_deleg_cur support.
+    
+    Signed-off-by: Andy Adamson 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index bb95275e7bae..31f7082df49f 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1526,6 +1526,15 @@ nfsd4_process_open1(struct nfsd4_open *open)
+ 	return status;
+ }
+ 
++static inline int
++nfs4_check_delegmode(struct nfs4_delegation *dp, int flags)
++{
++	if ((flags & WR_STATE) && (dp->dl_type == NFS4_OPEN_DELEGATE_READ))
++		return nfserr_openmode;
++	else
++		return nfs_ok;
++}
++
+ static struct nfs4_delegation *
+ find_delegation_file(struct nfs4_file *fp, stateid_t *stid)
+ {
+@@ -1960,15 +1969,6 @@ int nfs4_check_openmode(struct nfs4_stateid *stp, int flags)
+ 	return status;
+ }
+ 
+-static inline int
+-nfs4_check_delegmode(struct nfs4_delegation *dp, int flags)
+-{
+-	if ((flags & WR_STATE) && (dp->dl_type == NFS4_OPEN_DELEGATE_READ))
+-		return nfserr_openmode;
+-	else
+-		return nfs_ok;
+-}
+-
+ static inline int
+ check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
+ {

commit 52f4fb43063c182f3ef7e257ab336a8be8066bb0
+Author: NeilBrown 
+Date:   Thu Jun 23 22:02:49 2005 -0700
+
+    [PATCH] nfsd4: find_delegation_file()
+    
+    Factor out a bit of common code that will be useful elsewhere.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 75e8b137580c..bb95275e7bae 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1526,6 +1526,18 @@ nfsd4_process_open1(struct nfsd4_open *open)
+ 	return status;
+ }
+ 
++static struct nfs4_delegation *
++find_delegation_file(struct nfs4_file *fp, stateid_t *stid)
++{
++	struct nfs4_delegation *dp;
++
++	list_for_each_entry(dp, &fp->fi_del_perfile, dl_del_perfile) {
++		if (dp->dl_stateid.si_stateownerid == stid->si_stateownerid)
++			return dp;
++	}
++	return NULL;
++}
++
+ static int
+ nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_stateid **stpp)
+ {
+@@ -2419,24 +2431,15 @@ find_stateid(stateid_t *stid, int flags)
+ static struct nfs4_delegation *
+ find_delegation_stateid(struct inode *ino, stateid_t *stid)
+ {
+-	struct nfs4_delegation *dp = NULL;
+ 	struct nfs4_file *fp = NULL;
+-	u32 st_id;
+ 
+ 	dprintk("NFSD:find_delegation_stateid stateid=(%08x/%08x/%08x/%08x)\n",
+                     stid->si_boot, stid->si_stateownerid,
+                     stid->si_fileid, stid->si_generation);
+ 
+-	st_id = stid->si_stateownerid;
+ 	fp = find_file(ino);
+-	if (fp) {
+-		list_for_each_entry(dp, &fp->fi_del_perfile, dl_del_perfile) {
+-			if(dp->dl_stateid.si_stateownerid == st_id) {
+-				dprintk("NFSD: find_delegation dp %p\n",dp);
+-				return dp;
+-			}
+-		}
+-	}
++	if (fp)
++		return find_delegation_file(fp, stid);
+ 	return NULL;
+ }
+ 

commit 8a5e9cf1d6626586ff08e49f400a006a9f0c3275
+Author: NeilBrown 
+Date:   Tue Jun 21 17:17:29 2005 -0700
+
+    [PATCH] md: make sure md/bitmap doesn't try to write a page with active writeback
+    
+    Due to the use of write-behind, it is possible for md to write a page to
+    the bitmap file that is still completing writeback.  This is not allowed.
+    
+    With this patch, we detect those cases and either force a sync write, or
+    back off and try later, as appropriate.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
+index 030d6861051a..95980ad6b27b 100644
+--- a/drivers/md/bitmap.c
++++ b/drivers/md/bitmap.c
+@@ -313,7 +313,16 @@ static int write_page(struct bitmap *bitmap, struct page *page, int wait)
+ 	if (bitmap->file == NULL)
+ 		return write_sb_page(bitmap->mddev, bitmap->offset, page, wait);
+ 
+-	lock_page(page);
++	if (wait)
++		lock_page(page);
++	else {
++		if (TestSetPageLocked(page))
++			return -EAGAIN; /* already locked */
++		if (PageWriteback(page)) {
++			unlock_page(page);
++			return -EAGAIN;
++		}
++	}
+ 
+ 	ret = page->mapping->a_ops->prepare_write(NULL, page, 0, PAGE_SIZE);
+ 	if (!ret)
+@@ -400,7 +409,7 @@ int bitmap_update_sb(struct bitmap *bitmap)
+ 	if (!bitmap->mddev->degraded)
+ 		sb->events_cleared = cpu_to_le64(bitmap->mddev->events);
+ 	kunmap(bitmap->sb_page);
+-	return write_page(bitmap, bitmap->sb_page, 0);
++	return write_page(bitmap, bitmap->sb_page, 1);
+ }
+ 
+ /* print out the bitmap file superblock */
+@@ -762,6 +771,7 @@ int bitmap_unplug(struct bitmap *bitmap)
+ 	unsigned long i, attr, flags;
+ 	struct page *page;
+ 	int wait = 0;
++	int err;
+ 
+ 	if (!bitmap)
+ 		return 0;
+@@ -782,9 +792,17 @@ int bitmap_unplug(struct bitmap *bitmap)
+ 			wait = 1;
+ 		spin_unlock_irqrestore(&bitmap->lock, flags);
+ 
+-		if (attr & (BITMAP_PAGE_DIRTY | BITMAP_PAGE_NEEDWRITE))
+-			if (write_page(bitmap, page, 0))
++		if (attr & (BITMAP_PAGE_DIRTY | BITMAP_PAGE_NEEDWRITE)) {
++			err = write_page(bitmap, page, 0);
++			if (err == -EAGAIN) {
++				if (attr & BITMAP_PAGE_DIRTY)
++					err = write_page(bitmap, page, 1);
++				else
++					err = 0;
++			}
++			if (err)
+ 				return 1;
++		}
+ 	}
+ 	if (wait) { /* if any writes were performed, we need to wait on them */
+ 		if (bitmap->file) {
+@@ -1006,8 +1024,15 @@ int bitmap_daemon_work(struct bitmap *bitmap)
+ 				}
+ 				spin_unlock_irqrestore(&bitmap->lock, flags);
+ 				if (attr & BITMAP_PAGE_NEEDWRITE) {
+-					if (write_page(bitmap, page, 0))
++					switch (write_page(bitmap, page, 0)) {
++					case -EAGAIN:
++						set_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
++						break;
++					case 0:
++						break;
++					default:
+ 						bitmap_file_kick(bitmap);
++					}
+ 					page_cache_release(page);
+ 				}
+ 				continue;
+@@ -1020,6 +1045,10 @@ int bitmap_daemon_work(struct bitmap *bitmap)
+ 					clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+ 					spin_unlock_irqrestore(&bitmap->lock, flags);
+ 					err = write_page(bitmap, lastpage, 0);
++					if (err == -EAGAIN) {
++						err = 0;
++						set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
++					}
+ 				} else {
+ 					set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+ 					spin_unlock_irqrestore(&bitmap->lock, flags);
+@@ -1068,6 +1097,10 @@ int bitmap_daemon_work(struct bitmap *bitmap)
+ 			clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+ 			spin_unlock_irqrestore(&bitmap->lock, flags);
+ 			err = write_page(bitmap, lastpage, 0);
++			if (err == -EAGAIN) {
++				set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
++				err = 0;
++			}
+ 		} else {
+ 			set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+ 			spin_unlock_irqrestore(&bitmap->lock, flags);
+@@ -1421,31 +1454,6 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
+ 	}
+ }
+ 
+-/* dirty the entire bitmap */
+-int bitmap_setallbits(struct bitmap *bitmap)
+-{
+-	unsigned long flags;
+-	unsigned long j;
+-
+-	/* dirty the in-memory bitmap */
+-	bitmap_set_memory_bits(bitmap, 0, bitmap->chunks << CHUNK_BLOCK_SHIFT(bitmap), 1);
+-
+-	/* dirty the bitmap file */
+-	for (j = 0; j < bitmap->file_pages; j++) {
+-		struct page *page = bitmap->filemap[j];
+-
+-		spin_lock_irqsave(&bitmap->lock, flags);
+-		page_cache_get(page);
+-		spin_unlock_irqrestore(&bitmap->lock, flags);
+-		memset(kmap(page), 0xff, PAGE_SIZE);
+-		kunmap(page);
+-		if (write_page(bitmap, page, 0))
+-			return 1;
+-	}
+-
+-	return 0;
+-}
+-
+ /*
+  * free memory that was allocated
+  */

commit 39730960d94306d7be414e8d54f4e5c071af1278
+Author: NeilBrown 
+Date:   Tue Jun 21 17:17:28 2005 -0700
+
+    [PATCH] Two small fixes for md verion-1 superblocks.
+    
+    1/ Must typecast int to (sector_t) before inverting or we
+     might not invert enough bits.
+    
+    2/ When "bitmap_offset" was added to mdp_superblock_1, we didn't increase
+       the count of words-used (96 to 100).
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index ef3ad99562c1..65fab74ad737 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -847,7 +847,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
+ 	case 0:
+ 		sb_offset = rdev->bdev->bd_inode->i_size >> 9;
+ 		sb_offset -= 8*2;
+-		sb_offset &= ~(4*2-1);
++		sb_offset &= ~(sector_t)(4*2-1);
+ 		/* convert from sectors to K */
+ 		sb_offset /= 2;
+ 		break;
+diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h
+index 8e592a25a8b5..dc65cd435494 100644
+--- a/include/linux/raid/md_p.h
++++ b/include/linux/raid/md_p.h
+@@ -202,7 +202,7 @@ struct mdp_superblock_1 {
+ 				 * NOTE: signed, so bitmap can be before superblock
+ 				 * only meaningful of feature_map[0] is set.
+ 				 */
+-	__u8	pad1[128-96];	/* set to 0 when written */
++	__u8	pad1[128-100];	/* set to 0 when written */
+ 
+ 	/* constant this-device information - 64 bytes */
+ 	__u64	data_offset;	/* sector start of data, often 0 */

commit 7bfa19f2748000d646dbdf8f48258cfe1d257b52
+Author: NeilBrown 
+Date:   Tue Jun 21 17:17:28 2005 -0700
+
+    [PATCH] md: allow md to update multiple superblocks in parallel.
+    
+    currently, md updates all superblocks (one on each device) in series.  It
+    waits for one write to complete before starting the next.  This isn't a big
+    problem as superblock updates don't happen that often.
+    
+    However it is neater to do it in parallel, and if the drives in the array have
+    gone to "sleep" after a period of idleness, then waking them is parallel is
+    faster (and someone else should be worrying about power drain).
+    
+    Futher, we will need parallel superblock updates for a future patch which
+    keeps the intent-logging bitmap near the superblock.
+    
+    Also remove the silly code that retired superblock updates 100 times.  This
+    simply never made sense.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index fde8acfac320..ef3ad99562c1 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -328,6 +328,40 @@ static void free_disk_sb(mdk_rdev_t * rdev)
+ }
+ 
+ 
++static int super_written(struct bio *bio, unsigned int bytes_done, int error)
++{
++	mdk_rdev_t *rdev = bio->bi_private;
++	if (bio->bi_size)
++		return 1;
++
++	if (error || !test_bit(BIO_UPTODATE, &bio->bi_flags))
++		md_error(rdev->mddev, rdev);
++
++	if (atomic_dec_and_test(&rdev->mddev->pending_writes))
++		wake_up(&rdev->mddev->sb_wait);
++	return 0;
++}
++
++void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
++		   sector_t sector, int size, struct page *page)
++{
++	/* write first size bytes of page to sector of rdev
++	 * Increment mddev->pending_writes before returning
++	 * and decrement it on completion, waking up sb_wait
++	 * if zero is reached.
++	 * If an error occurred, call md_error
++	 */
++	struct bio *bio = bio_alloc(GFP_NOIO, 1);
++
++	bio->bi_bdev = rdev->bdev;
++	bio->bi_sector = sector;
++	bio_add_page(bio, page, size, 0);
++	bio->bi_private = rdev;
++	bio->bi_end_io = super_written;
++	atomic_inc(&mddev->pending_writes);
++	submit_bio((1<bi_size)
+@@ -1268,30 +1302,6 @@ void md_print_devices(void)
+ }
+ 
+ 
+-static int write_disk_sb(mdk_rdev_t * rdev)
+-{
+-	char b[BDEVNAME_SIZE];
+-	if (!rdev->sb_loaded) {
+-		MD_BUG();
+-		return 1;
+-	}
+-	if (rdev->faulty) {
+-		MD_BUG();
+-		return 1;
+-	}
+-
+-	dprintk(KERN_INFO "(write) %s's sb offset: %llu\n",
+-		bdevname(rdev->bdev,b),
+-	       (unsigned long long)rdev->sb_offset);
+-  
+-	if (sync_page_io(rdev->bdev, rdev->sb_offset<<1, MD_SB_BYTES, rdev->sb_page, WRITE))
+-		return 0;
+-
+-	printk("md: write_disk_sb failed for device %s\n", 
+-		bdevname(rdev->bdev,b));
+-	return 1;
+-}
+-
+ static void sync_sbs(mddev_t * mddev)
+ {
+ 	mdk_rdev_t *rdev;
+@@ -1306,7 +1316,7 @@ static void sync_sbs(mddev_t * mddev)
+ 
+ static void md_update_sb(mddev_t * mddev)
+ {
+-	int err, count = 100;
++	int err;
+ 	struct list_head *tmp;
+ 	mdk_rdev_t *rdev;
+ 	int sync_req;
+@@ -1326,6 +1336,7 @@ static void md_update_sb(mddev_t * mddev)
+ 		MD_BUG();
+ 		mddev->events --;
+ 	}
++	mddev->sb_dirty = 2;
+ 	sync_sbs(mddev);
+ 
+ 	/*
+@@ -1353,24 +1364,24 @@ static void md_update_sb(mddev_t * mddev)
+ 
+ 		dprintk("%s ", bdevname(rdev->bdev,b));
+ 		if (!rdev->faulty) {
+-			err += write_disk_sb(rdev);
++			md_super_write(mddev,rdev,
++				       rdev->sb_offset<<1, MD_SB_BYTES,
++				       rdev->sb_page);
++			dprintk(KERN_INFO "(write) %s's sb offset: %llu\n",
++				bdevname(rdev->bdev,b),
++				(unsigned long long)rdev->sb_offset);
++
+ 		} else
+ 			dprintk(")\n");
+-		if (!err && mddev->level == LEVEL_MULTIPATH)
++		if (mddev->level == LEVEL_MULTIPATH)
+ 			/* only need to write one superblock... */
+ 			break;
+ 	}
+-	if (err) {
+-		if (--count) {
+-			printk(KERN_ERR "md: errors occurred during superblock"
+-				" update, repeating\n");
+-			goto repeat;
+-		}
+-		printk(KERN_ERR \
+-			"md: excessive errors occurred during superblock update, exiting\n");
+-	}
++	wait_event(mddev->sb_wait, atomic_read(&mddev->pending_writes)==0);
++	/* if there was a failure, sb_dirty was set to 1, and we re-write super */
++
+ 	spin_lock(&mddev->write_lock);
+-	if (mddev->in_sync != sync_req) {
++	if (mddev->in_sync != sync_req|| mddev->sb_dirty == 1) {
+ 		/* have to write it out again */
+ 		spin_unlock(&mddev->write_lock);
+ 		goto repeat;
+diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
+index a3725b57fb7d..8c14ba565a45 100644
+--- a/include/linux/raid/md_k.h
++++ b/include/linux/raid/md_k.h
+@@ -262,6 +262,7 @@ struct mddev_s
+ 
+ 	spinlock_t			write_lock;
+ 	wait_queue_head_t		sb_wait;	/* for waiting on superblock updates */
++	atomic_t			pending_writes;	/* number of active superblock writes */
+ 
+ 	unsigned int			safemode;	/* if set, update "clean" superblock
+ 							 * when no writes pending.

commit a654b9d8f851f4ca02649d5825cbe6c608adb10c
+Author: NeilBrown 
+Date:   Tue Jun 21 17:17:27 2005 -0700
+
+    [PATCH] md: allow md intent bitmap to be stored near the superblock.
+    
+    This provides an alternate to storing the bitmap in a separate file.  The
+    bitmap can be stored at a given offset from the superblock.  Obviously the
+    creator of the array must make sure this doesn't intersect with data....
+    After is good for version-0.90 superblocks.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
+index 204564dc6a0d..030d6861051a 100644
+--- a/drivers/md/bitmap.c
++++ b/drivers/md/bitmap.c
+@@ -116,7 +116,7 @@ static unsigned char *bitmap_alloc_page(struct bitmap *bitmap)
+ 	if (!page)
+ 		printk("%s: bitmap_alloc_page FAILED\n", bmname(bitmap));
+ 	else
+-		printk("%s: bitmap_alloc_page: allocated page at %p\n",
++		PRINTK("%s: bitmap_alloc_page: allocated page at %p\n",
+ 			bmname(bitmap), page);
+ 	return page;
+ }
+@@ -258,13 +258,61 @@ char *file_path(struct file *file, char *buf, int count)
+  * basic page I/O operations
+  */
+ 
++/* IO operations when bitmap is stored near all superblocks */
++static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long index)
++{
++	/* choose a good rdev and read the page from there */
++
++	mdk_rdev_t *rdev;
++	struct list_head *tmp;
++	struct page *page = alloc_page(GFP_KERNEL);
++	sector_t target;
++
++	if (!page)
++		return ERR_PTR(-ENOMEM);
++	do {
++		ITERATE_RDEV(mddev, rdev, tmp)
++			if (rdev->in_sync && !rdev->faulty)
++				goto found;
++		return ERR_PTR(-EIO);
++
++	found:
++		target = (rdev->sb_offset << 1) + offset + index * (PAGE_SIZE/512);
++
++	} while (!sync_page_io(rdev->bdev, target, PAGE_SIZE, page, READ));
++
++	page->index = index;
++	return page;
++}
++
++static int write_sb_page(mddev_t *mddev, long offset, struct page *page, int wait)
++{
++	mdk_rdev_t *rdev;
++	struct list_head *tmp;
++
++	ITERATE_RDEV(mddev, rdev, tmp)
++		if (rdev->in_sync && !rdev->faulty)
++			md_super_write(mddev, rdev,
++				       (rdev->sb_offset<<1) + offset
++				       + page->index * (PAGE_SIZE/512),
++				       PAGE_SIZE,
++				       page);
++
++	if (wait)
++		wait_event(mddev->sb_wait, atomic_read(&mddev->pending_writes)==0);
++	return 0;
++}
++
+ /*
+- * write out a page
++ * write out a page to a file
+  */
+ static int write_page(struct bitmap *bitmap, struct page *page, int wait)
+ {
+ 	int ret = -ENOMEM;
+ 
++	if (bitmap->file == NULL)
++		return write_sb_page(bitmap->mddev, bitmap->offset, page, wait);
++
+ 	lock_page(page);
+ 
+ 	ret = page->mapping->a_ops->prepare_write(NULL, page, 0, PAGE_SIZE);
+@@ -394,7 +442,12 @@ static int bitmap_read_sb(struct bitmap *bitmap)
+ 	int err = -EINVAL;
+ 
+ 	/* page 0 is the superblock, read it... */
+-	bitmap->sb_page = read_page(bitmap->file, 0, &bytes_read);
++	if (bitmap->file)
++		bitmap->sb_page = read_page(bitmap->file, 0, &bytes_read);
++	else {
++		bitmap->sb_page = read_sb_page(bitmap->mddev, bitmap->offset, 0);
++		bytes_read = PAGE_SIZE;
++	}
+ 	if (IS_ERR(bitmap->sb_page)) {
+ 		err = PTR_ERR(bitmap->sb_page);
+ 		bitmap->sb_page = NULL;
+@@ -625,14 +678,16 @@ static void bitmap_file_kick(struct bitmap *bitmap)
+ 	bitmap_mask_state(bitmap, BITMAP_STALE, MASK_SET);
+ 	bitmap_update_sb(bitmap);
+ 
+-	path = kmalloc(PAGE_SIZE, GFP_KERNEL);
+-	if (path)
+-		ptr = file_path(bitmap->file, path, PAGE_SIZE);
++	if (bitmap->file) {
++		path = kmalloc(PAGE_SIZE, GFP_KERNEL);
++		if (path)
++			ptr = file_path(bitmap->file, path, PAGE_SIZE);
+ 
+-	printk(KERN_ALERT "%s: kicking failed bitmap file %s from array!\n",
+-		bmname(bitmap), ptr ? ptr : "");
++		printk(KERN_ALERT "%s: kicking failed bitmap file %s from array!\n",
++		       bmname(bitmap), ptr ? ptr : "");
+ 
+-	kfree(path);
++		kfree(path);
++	}
+ 
+ 	bitmap_file_put(bitmap);
+ 
+@@ -676,7 +731,7 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
+ 	void *kaddr;
+ 	unsigned long chunk = block >> CHUNK_BLOCK_SHIFT(bitmap);
+ 
+-	if (!bitmap->file || !bitmap->filemap) {
++	if (!bitmap->filemap) {
+ 		return;
+ 	}
+ 
+@@ -715,7 +770,7 @@ int bitmap_unplug(struct bitmap *bitmap)
+ 	 * flushed out to disk */
+ 	for (i = 0; i < bitmap->file_pages; i++) {
+ 		spin_lock_irqsave(&bitmap->lock, flags);
+-		if (!bitmap->file || !bitmap->filemap) {
++		if (!bitmap->filemap) {
+ 			spin_unlock_irqrestore(&bitmap->lock, flags);
+ 			return 0;
+ 		}
+@@ -732,11 +787,15 @@ int bitmap_unplug(struct bitmap *bitmap)
+ 				return 1;
+ 	}
+ 	if (wait) { /* if any writes were performed, we need to wait on them */
+-		spin_lock_irq(&bitmap->write_lock);
+-		wait_event_lock_irq(bitmap->write_wait,
+-			list_empty(&bitmap->complete_pages), bitmap->write_lock,
+-			wake_up_process(bitmap->writeback_daemon->tsk));
+-		spin_unlock_irq(&bitmap->write_lock);
++		if (bitmap->file) {
++			spin_lock_irq(&bitmap->write_lock);
++			wait_event_lock_irq(bitmap->write_wait,
++					    list_empty(&bitmap->complete_pages), bitmap->write_lock,
++					    wake_up_process(bitmap->writeback_daemon->tsk));
++			spin_unlock_irq(&bitmap->write_lock);
++		} else
++			wait_event(bitmap->mddev->sb_wait,
++				   atomic_read(&bitmap->mddev->pending_writes)==0);
+ 	}
+ 	return 0;
+ }
+@@ -764,7 +823,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
+ 	chunks = bitmap->chunks;
+ 	file = bitmap->file;
+ 
+-	BUG_ON(!file);
++	BUG_ON(!file && !bitmap->offset);
+ 
+ #if INJECT_FAULTS_3
+ 	outofdate = 1;
+@@ -779,7 +838,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
+ 
+ 	num_pages = (bytes + sizeof(bitmap_super_t) + PAGE_SIZE - 1) / PAGE_SIZE;
+ 
+-	if (i_size_read(file->f_mapping->host) < bytes + sizeof(bitmap_super_t)) {
++	if (file && i_size_read(file->f_mapping->host) < bytes + sizeof(bitmap_super_t)) {
+ 		printk(KERN_INFO "%s: bitmap file too short %lu < %lu\n",
+ 			bmname(bitmap),
+ 			(unsigned long) i_size_read(file->f_mapping->host),
+@@ -816,14 +875,18 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
+ 				 */
+ 				page = bitmap->sb_page;
+ 				offset = sizeof(bitmap_super_t);
+-			} else {
++			} else if (file) {
+ 				page = read_page(file, index, &dummy);
+-				if (IS_ERR(page)) { /* read error */
+-					ret = PTR_ERR(page);
+-					goto out;
+-				}
++				offset = 0;
++			} else {
++				page = read_sb_page(bitmap->mddev, bitmap->offset, index);
+ 				offset = 0;
+ 			}
++			if (IS_ERR(page)) { /* read error */
++				ret = PTR_ERR(page);
++				goto out;
++			}
++
+ 			oldindex = index;
+ 			oldpage = page;
+ 			kmap(page);
+@@ -874,6 +937,19 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
+ 	return ret;
+ }
+ 
++void bitmap_write_all(struct bitmap *bitmap)
++{
++	/* We don't actually write all bitmap blocks here,
++	 * just flag them as needing to be written
++	 */
++
++	unsigned long chunks = bitmap->chunks;
++	unsigned long bytes = (chunks+7)/8 + sizeof(bitmap_super_t);
++	unsigned long num_pages = (bytes + PAGE_SIZE-1) / PAGE_SIZE;
++	while (num_pages--)
++		bitmap->filemap_attr[num_pages] |= BITMAP_PAGE_NEEDWRITE;
++}
++
+ 
+ static void bitmap_count_page(struct bitmap *bitmap, sector_t offset, int inc)
+ {
+@@ -913,7 +989,7 @@ int bitmap_daemon_work(struct bitmap *bitmap)
+ 	for (j = 0; j < bitmap->chunks; j++) {
+ 		bitmap_counter_t *bmc;
+ 		spin_lock_irqsave(&bitmap->lock, flags);
+-		if (!bitmap->file || !bitmap->filemap) {
++		if (!bitmap->filemap) {
+ 			/* error or shutdown */
+ 			spin_unlock_irqrestore(&bitmap->lock, flags);
+ 			break;
+@@ -1072,6 +1148,7 @@ static int bitmap_start_daemon(struct bitmap *bitmap, mdk_thread_t **ptr,
+ 
+ 	spin_lock_irqsave(&bitmap->lock, flags);
+ 	*ptr = NULL;
++
+ 	if (!bitmap->file) /* no need for daemon if there's no backing file */
+ 		goto out_unlock;
+ 
+@@ -1416,9 +1493,11 @@ int bitmap_create(mddev_t *mddev)
+ 
+ 	BUG_ON(sizeof(bitmap_super_t) != 256);
+ 
+-	if (!file) /* bitmap disabled, nothing to do */
++	if (!file && !mddev->bitmap_offset) /* bitmap disabled, nothing to do */
+ 		return 0;
+ 
++	BUG_ON(file && mddev->bitmap_offset);
++
+ 	bitmap = kmalloc(sizeof(*bitmap), GFP_KERNEL);
+ 	if (!bitmap)
+ 		return -ENOMEM;
+@@ -1438,7 +1517,8 @@ int bitmap_create(mddev_t *mddev)
+ 		return -ENOMEM;
+ 
+ 	bitmap->file = file;
+-	get_file(file);
++	bitmap->offset = mddev->bitmap_offset;
++	if (file) get_file(file);
+ 	/* read superblock from bitmap file (this sets bitmap->chunksize) */
+ 	err = bitmap_read_sb(bitmap);
+ 	if (err)
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 7075bebb7f37..fde8acfac320 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -337,7 +337,7 @@ static int bi_complete(struct bio *bio, unsigned int bytes_done, int error)
+ 	return 0;
+ }
+ 
+-static int sync_page_io(struct block_device *bdev, sector_t sector, int size,
++int sync_page_io(struct block_device *bdev, sector_t sector, int size,
+ 		   struct page *page, int rw)
+ {
+ 	struct bio *bio = bio_alloc(GFP_NOIO, 1);
+@@ -609,6 +609,17 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+ 		memcpy(mddev->uuid+12,&sb->set_uuid3, 4);
+ 
+ 		mddev->max_disks = MD_SB_DISKS;
++
++		if (sb->state & (1<bitmap_file == NULL) {
++			if (mddev->level != 1) {
++				/* FIXME use a better test */
++				printk(KERN_WARNING "md: bitmaps only support for raid1\n");
++				return -EINVAL;
++			}
++			mddev->bitmap_offset = (MD_SB_BYTES >> 9);
++		}
++
+ 	} else if (mddev->pers == NULL) {
+ 		/* Insist on good event counter while assembling */
+ 		__u64 ev1 = md_event(sb);
+@@ -702,6 +713,9 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
+ 	sb->layout = mddev->layout;
+ 	sb->chunk_size = mddev->chunk_size;
+ 
++	if (mddev->bitmap && mddev->bitmap_file == NULL)
++		sb->state |= (1<disks[0].state = (1<uuid, sb->set_uuid, 16);
+ 
+ 		mddev->max_disks =  (4096-256)/2;
++
++		if ((le32_to_cpu(sb->feature_map) & 1) &&
++		    mddev->bitmap_file == NULL ) {
++			if (mddev->level != 1) {
++				printk(KERN_WARNING "md: bitmaps only supported for raid1\n");
++				return -EINVAL;
++			}
++			mddev->bitmap_offset = (__s32)le32_to_cpu(sb->bitmap_offset);
++		}
+ 	} else if (mddev->pers == NULL) {
+ 		/* Insist of good event counter while assembling */
+ 		__u64 ev1 = le64_to_cpu(sb->events);
+@@ -960,6 +983,11 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
+ 	else
+ 		sb->resync_offset = cpu_to_le64(0);
+ 
++	if (mddev->bitmap && mddev->bitmap_file == NULL) {
++		sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset);
++		sb->feature_map = cpu_to_le32(1);
++	}
++
+ 	max_dev = 0;
+ 	ITERATE_RDEV(mddev,rdev2,tmp)
+ 		if (rdev2->desc_nr+1 > max_dev)
+@@ -2406,7 +2434,8 @@ static int set_bitmap_file(mddev_t *mddev, int fd)
+ 			mdname(mddev));
+ 		fput(mddev->bitmap_file);
+ 		mddev->bitmap_file = NULL;
+-	}
++	} else
++		mddev->bitmap_offset = 0; /* file overrides offset */
+ 	return err;
+ }
+ 
+@@ -3774,6 +3803,13 @@ void md_check_recovery(mddev_t *mddev)
+ 			set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
+ 			if (!spares)
+ 				set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
++			if (spares && mddev->bitmap && ! mddev->bitmap->file) {
++				/* We are adding a device or devices to an array
++				 * which has the bitmap stored on all devices.
++				 * So make sure all bitmap pages get written
++				 */
++				bitmap_write_all(mddev->bitmap);
++			}
+ 			mddev->sync_thread = md_register_thread(md_do_sync,
+ 								mddev,
+ 								"%s_resync");
+diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h
+index cfe60cfc8f3d..e24b74b11150 100644
+--- a/include/linux/raid/bitmap.h
++++ b/include/linux/raid/bitmap.h
+@@ -217,6 +217,7 @@ struct bitmap {
+ 	/* bitmap spinlock */
+ 	spinlock_t lock;
+ 
++	long offset; /* offset from superblock if file is NULL */
+ 	struct file *file; /* backing disk file */
+ 	struct page *sb_page; /* cached copy of the bitmap file superblock */
+ 	struct page **filemap; /* list of cache pages for the file */
+@@ -255,6 +256,7 @@ void bitmap_print_sb(struct bitmap *bitmap);
+ int bitmap_update_sb(struct bitmap *bitmap);
+ 
+ int  bitmap_setallbits(struct bitmap *bitmap);
++void bitmap_write_all(struct bitmap *bitmap);
+ 
+ /* these are exported */
+ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors);
+diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h
+index 75f41d8faed2..ffa316ce4dc8 100644
+--- a/include/linux/raid/md.h
++++ b/include/linux/raid/md.h
+@@ -60,7 +60,14 @@
+  */
+ #define MD_MAJOR_VERSION                0
+ #define MD_MINOR_VERSION                90
+-#define MD_PATCHLEVEL_VERSION           1
++/*
++ * MD_PATCHLEVEL_VERSION indicates kernel functionality.
++ * >=1 means different superblock formats are selectable using SET_ARRAY_INFO
++ *     and major_version/minor_version accordingly
++ * >=2 means that Internal bitmaps are supported by setting MD_SB_BITMAP_PRESENT
++ *     in the super status byte
++ */
++#define MD_PATCHLEVEL_VERSION           2
+ 
+ extern int register_md_personality (int p_num, mdk_personality_t *p);
+ extern int unregister_md_personality (int p_num);
+@@ -78,6 +85,12 @@ extern void md_unplug_mddev(mddev_t *mddev);
+ 
+ extern void md_print_devices (void);
+ 
++extern void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
++			   sector_t sector, int size, struct page *page);
++extern int sync_page_io(struct block_device *bdev, sector_t sector, int size,
++			struct page *page, int rw);
++
++
+ #define MD_BUG(x...) { printk("md: bug in file %s, line %d\n", __FILE__, __LINE__); md_print_devices(); }
+ 
+ #endif 
+diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
+index 3e977025cf43..a3725b57fb7d 100644
+--- a/include/linux/raid/md_k.h
++++ b/include/linux/raid/md_k.h
+@@ -273,6 +273,10 @@ struct mddev_s
+ 
+ 	struct bitmap                   *bitmap; /* the bitmap for the device */
+ 	struct file			*bitmap_file; /* the bitmap file */
++	long				bitmap_offset; /* offset from superblock of
++							* start of bitmap. May be
++							* negative, but not '0'
++							*/
+ 
+ 	struct list_head		all_mddevs;
+ };
+diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h
+index 8ba95d67329f..8e592a25a8b5 100644
+--- a/include/linux/raid/md_p.h
++++ b/include/linux/raid/md_p.h
+@@ -96,6 +96,7 @@ typedef struct mdp_device_descriptor_s {
+ #define MD_SB_CLEAN		0
+ #define MD_SB_ERRORS		1
+ 
++#define	MD_SB_BITMAP_PRESENT	8 /* bitmap may be present nearby */
+ typedef struct mdp_superblock_s {
+ 	/*
+ 	 * Constant generic information
+@@ -184,7 +185,7 @@ struct mdp_superblock_1 {
+ 	/* constant array information - 128 bytes */
+ 	__u32	magic;		/* MD_SB_MAGIC: 0xa92b4efc - little endian */
+ 	__u32	major_version;	/* 1 */
+-	__u32	feature_map;	/* 0 for now */
++	__u32	feature_map;	/* bit 0 set if 'bitmap_offset' is meaningful */
+ 	__u32	pad0;		/* always set to 0 when writing */
+ 
+ 	__u8	set_uuid[16];	/* user-space generated. */
+@@ -197,6 +198,10 @@ struct mdp_superblock_1 {
+ 
+ 	__u32	chunksize;	/* in 512byte sectors */
+ 	__u32	raid_disks;
++	__u32	bitmap_offset;	/* sectors after start of superblock that bitmap starts
++				 * NOTE: signed, so bitmap can be before superblock
++				 * only meaningful of feature_map[0] is set.
++				 */
+ 	__u8	pad1[128-96];	/* set to 0 when written */
+ 
+ 	/* constant this-device information - 64 bytes */

commit 3d310eb7b3df1252e8595d059d982b0a9825a137
+Author: NeilBrown 
+Date:   Tue Jun 21 17:17:26 2005 -0700
+
+    [PATCH] md: fix deadlock due to md thread processing delayed requests.
+    
+    Before completing a 'write' the md superblock might need to be updated.
+    This is best done by the md_thread.
+    
+    The current code schedules this up and queues the write request for later
+    handling by the md_thread.
+    
+    However some personalities (Raid5/raid6) will deadlock if the md_thread
+    tries to submit requests to its own array.
+    
+    So this patch changes things so the processes submitting the request waits
+    for the superblock to be written and then submits the request itself.
+    
+    This fixes a recently-created deadlock in raid5/raid6
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 789b114f860a..7075bebb7f37 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -224,8 +224,8 @@ static mddev_t * mddev_find(dev_t unit)
+ 	INIT_LIST_HEAD(&new->all_mddevs);
+ 	init_timer(&new->safemode_timer);
+ 	atomic_set(&new->active, 1);
+-	bio_list_init(&new->write_list);
+ 	spin_lock_init(&new->write_lock);
++	init_waitqueue_head(&new->sb_wait);
+ 
+ 	new->queue = blk_alloc_queue(GFP_KERNEL);
+ 	if (!new->queue) {
+@@ -1307,6 +1307,7 @@ static void md_update_sb(mddev_t * mddev)
+ 	if (!mddev->persistent) {
+ 		mddev->sb_dirty = 0;
+ 		spin_unlock(&mddev->write_lock);
++		wake_up(&mddev->sb_wait);
+ 		return;
+ 	}
+ 	spin_unlock(&mddev->write_lock);
+@@ -1348,6 +1349,7 @@ static void md_update_sb(mddev_t * mddev)
+ 	}
+ 	mddev->sb_dirty = 0;
+ 	spin_unlock(&mddev->write_lock);
++	wake_up(&mddev->sb_wait);
+ 
+ }
+ 
+@@ -3368,29 +3370,26 @@ void md_done_sync(mddev_t *mddev, int blocks, int ok)
+ 
+ /* md_write_start(mddev, bi)
+  * If we need to update some array metadata (e.g. 'active' flag
+- * in superblock) before writing, queue bi for later writing
+- * and return 0, else return 1 and it will be written now
++ * in superblock) before writing, schedule a superblock update
++ * and wait for it to complete.
+  */
+-int md_write_start(mddev_t *mddev, struct bio *bi)
++void md_write_start(mddev_t *mddev, struct bio *bi)
+ {
++	DEFINE_WAIT(w);
+ 	if (bio_data_dir(bi) != WRITE)
+-		return 1;
++		return;
+ 
+ 	atomic_inc(&mddev->writes_pending);
+-	spin_lock(&mddev->write_lock);
+-	if (mddev->in_sync == 0 && mddev->sb_dirty == 0) {
+-		spin_unlock(&mddev->write_lock);
+-		return 1;
+-	}
+-	bio_list_add(&mddev->write_list, bi);
+-
+ 	if (mddev->in_sync) {
+-		mddev->in_sync = 0;
+-		mddev->sb_dirty = 1;
++		spin_lock(&mddev->write_lock);
++		if (mddev->in_sync) {
++			mddev->in_sync = 0;
++			mddev->sb_dirty = 1;
++			md_wakeup_thread(mddev->thread);
++		}
++		spin_unlock(&mddev->write_lock);
+ 	}
+-	spin_unlock(&mddev->write_lock);
+-	md_wakeup_thread(mddev->thread);
+-	return 0;
++	wait_event(mddev->sb_wait, mddev->sb_dirty==0);
+ }
+ 
+ void md_write_end(mddev_t *mddev)
+@@ -3685,7 +3684,6 @@ void md_check_recovery(mddev_t *mddev)
+ 		mddev->sb_dirty ||
+ 		test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) ||
+ 		test_bit(MD_RECOVERY_DONE, &mddev->recovery) ||
+-		mddev->write_list.head ||
+ 		(mddev->safemode == 1) ||
+ 		(mddev->safemode == 2 && ! atomic_read(&mddev->writes_pending)
+ 		 && !mddev->in_sync && mddev->recovery_cp == MaxSector)
+@@ -3694,7 +3692,6 @@ void md_check_recovery(mddev_t *mddev)
+ 
+ 	if (mddev_trylock(mddev)==0) {
+ 		int spares =0;
+-		struct bio *blist;
+ 
+ 		spin_lock(&mddev->write_lock);
+ 		if (mddev->safemode && !atomic_read(&mddev->writes_pending) &&
+@@ -3704,21 +3701,11 @@ void md_check_recovery(mddev_t *mddev)
+ 		}
+ 		if (mddev->safemode == 1)
+ 			mddev->safemode = 0;
+-		blist = bio_list_get(&mddev->write_list);
+ 		spin_unlock(&mddev->write_lock);
+ 
+ 		if (mddev->sb_dirty)
+ 			md_update_sb(mddev);
+ 
+-		while (blist) {
+-			struct bio *b = blist;
+-			blist = blist->bi_next;
+-			b->bi_next = NULL;
+-			generic_make_request(b);
+-			/* we already counted this, so need to un-count */
+-			md_write_end(mddev);
+-		}
+-
+ 
+ 		if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) &&
+ 		    !test_bit(MD_RECOVERY_DONE, &mddev->recovery)) {
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index 3f5234fe3593..98b09773e79e 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -561,8 +561,8 @@ static int make_request(request_queue_t *q, struct bio * bio)
+ 	 * thread has put up a bar for new requests.
+ 	 * Continue immediately if no resync is active currently.
+ 	 */
+-	if (md_write_start(mddev, bio)==0)
+-		return 0;
++	md_write_start(mddev, bio); /* wait on superblock update early */
++
+ 	spin_lock_irq(&conf->resync_lock);
+ 	wait_event_lock_irq(conf->wait_resume, !conf->barrier, conf->resync_lock, );
+ 	conf->nr_pending++;
+diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
+index 8476515bfdc7..fd7324a86d13 100644
+--- a/drivers/md/raid10.c
++++ b/drivers/md/raid10.c
+@@ -700,8 +700,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
+ 		return 0;
+ 	}
+ 
+-	if (md_write_start(mddev, bio) == 0)
+-		return 0;
++	md_write_start(mddev, bio);
+ 
+ 	/*
+ 	 * Register the new request and wait if the reconstruction
+diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
+index 1ce3f5aaa984..93a9726cc2d6 100644
+--- a/drivers/md/raid5.c
++++ b/drivers/md/raid5.c
+@@ -1411,8 +1411,7 @@ static int make_request (request_queue_t *q, struct bio * bi)
+ 	sector_t logical_sector, last_sector;
+ 	struct stripe_head *sh;
+ 
+-	if (md_write_start(mddev, bi)==0)
+-		return 0;
++	md_write_start(mddev, bi);
+ 
+ 	if (bio_data_dir(bi)==WRITE) {
+ 		disk_stat_inc(mddev->gendisk, writes);
+diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
+index d9c385496dc5..f62ea1a73d0d 100644
+--- a/drivers/md/raid6main.c
++++ b/drivers/md/raid6main.c
+@@ -1570,8 +1570,7 @@ static int make_request (request_queue_t *q, struct bio * bi)
+ 	sector_t logical_sector, last_sector;
+ 	struct stripe_head *sh;
+ 
+-	if (md_write_start(mddev, bi)==0)
+-		return 0;
++	md_write_start(mddev, bi);
+ 
+ 	if (bio_data_dir(bi)==WRITE) {
+ 		disk_stat_inc(mddev->gendisk, writes);
+diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h
+index cfde8f497d6d..75f41d8faed2 100644
+--- a/include/linux/raid/md.h
++++ b/include/linux/raid/md.h
+@@ -69,7 +69,7 @@ extern mdk_thread_t * md_register_thread (void (*run) (mddev_t *mddev),
+ extern void md_unregister_thread (mdk_thread_t *thread);
+ extern void md_wakeup_thread(mdk_thread_t *thread);
+ extern void md_check_recovery(mddev_t *mddev);
+-extern int md_write_start(mddev_t *mddev, struct bio *bi);
++extern void md_write_start(mddev_t *mddev, struct bio *bi);
+ extern void md_write_end(mddev_t *mddev);
+ extern void md_handle_safemode(mddev_t *mddev);
+ extern void md_done_sync(mddev_t *mddev, int blocks, int ok);
+diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
+index 6cdcb4434c6c..3e977025cf43 100644
+--- a/include/linux/raid/md_k.h
++++ b/include/linux/raid/md_k.h
+@@ -261,7 +261,7 @@ struct mddev_s
+ 	sector_t			recovery_cp;
+ 
+ 	spinlock_t			write_lock;
+-	struct bio_list			write_list;
++	wait_queue_head_t		sb_wait;	/* for waiting on superblock updates */
+ 
+ 	unsigned int			safemode;	/* if set, update "clean" superblock
+ 							 * when no writes pending.

commit 41158c7eb22312cfaa256744e1553bb4042ff085
+Author: NeilBrown 
+Date:   Tue Jun 21 17:17:25 2005 -0700
+
+    [PATCH] md: optimise reconstruction when re-adding a recently failed drive.
+    
+    When an array is degraded, bit in the intent-bitmap are never cleared.  So if
+    a recently failed drive is re-added, we only need to reconstruct the block
+    that are still reflected in the bitmap.
+    
+    This patch adds support for this re-adding.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index b02f8d1d77e7..789b114f860a 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -577,6 +577,8 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+ 	mdp_disk_t *desc;
+ 	mdp_super_t *sb = (mdp_super_t *)page_address(rdev->sb_page);
+ 
++	rdev->raid_disk = -1;
++	rdev->in_sync = 0;
+ 	if (mddev->raid_disks == 0) {
+ 		mddev->major_version = 0;
+ 		mddev->minor_version = sb->minor_version;
+@@ -607,16 +609,24 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+ 		memcpy(mddev->uuid+12,&sb->set_uuid3, 4);
+ 
+ 		mddev->max_disks = MD_SB_DISKS;
+-	} else {
+-		__u64 ev1;
+-		ev1 = md_event(sb);
++	} else if (mddev->pers == NULL) {
++		/* Insist on good event counter while assembling */
++		__u64 ev1 = md_event(sb);
+ 		++ev1;
+ 		if (ev1 < mddev->events) 
+ 			return -EINVAL;
+-	}
++	} else if (mddev->bitmap) {
++		/* if adding to array with a bitmap, then we can accept an
++		 * older device ... but not too old.
++		 */
++		__u64 ev1 = md_event(sb);
++		if (ev1 < mddev->bitmap->events_cleared)
++			return 0;
++	} else /* just a hot-add of a new device, leave raid_disk at -1 */
++		return 0;
++
+ 	if (mddev->level != LEVEL_MULTIPATH) {
+-		rdev->raid_disk = -1;
+-		rdev->in_sync = rdev->faulty = 0;
++		rdev->faulty = 0;
+ 		desc = sb->disks + rdev->desc_nr;
+ 
+ 		if (desc->state & (1<in_sync = 1;
+ 			rdev->raid_disk = desc->raid_disk;
+ 		}
+-	}
++	} else /* MULTIPATH are always insync */
++		rdev->in_sync = 1;
+ 	return 0;
+ }
+ 
+@@ -868,6 +879,8 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+ {
+ 	struct mdp_superblock_1 *sb = (struct mdp_superblock_1*)page_address(rdev->sb_page);
+ 
++	rdev->raid_disk = -1;
++	rdev->in_sync = 0;
+ 	if (mddev->raid_disks == 0) {
+ 		mddev->major_version = 1;
+ 		mddev->patch_version = 0;
+@@ -885,13 +898,21 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+ 		memcpy(mddev->uuid, sb->set_uuid, 16);
+ 
+ 		mddev->max_disks =  (4096-256)/2;
+-	} else {
+-		__u64 ev1;
+-		ev1 = le64_to_cpu(sb->events);
++	} else if (mddev->pers == NULL) {
++		/* Insist of good event counter while assembling */
++		__u64 ev1 = le64_to_cpu(sb->events);
+ 		++ev1;
+ 		if (ev1 < mddev->events)
+ 			return -EINVAL;
+-	}
++	} else if (mddev->bitmap) {
++		/* If adding to array with a bitmap, then we can accept an
++		 * older device, but not too old.
++		 */
++		__u64 ev1 = le64_to_cpu(sb->events);
++		if (ev1 < mddev->bitmap->events_cleared)
++			return 0;
++	} else /* just a hot-add of a new device, leave raid_disk at -1 */
++		return 0;
+ 
+ 	if (mddev->level != LEVEL_MULTIPATH) {
+ 		int role;
+@@ -899,14 +920,10 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+ 		role = le16_to_cpu(sb->dev_roles[rdev->desc_nr]);
+ 		switch(role) {
+ 		case 0xffff: /* spare */
+-			rdev->in_sync = 0;
+ 			rdev->faulty = 0;
+-			rdev->raid_disk = -1;
+ 			break;
+ 		case 0xfffe: /* faulty */
+-			rdev->in_sync = 0;
+ 			rdev->faulty = 1;
+-			rdev->raid_disk = -1;
+ 			break;
+ 		default:
+ 			rdev->in_sync = 1;
+@@ -914,7 +931,9 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+ 			rdev->raid_disk = role;
+ 			break;
+ 		}
+-	}
++	} else /* MULTIPATH are always insync */
++		rdev->in_sync = 1;
++
+ 	return 0;
+ }
+ 
+@@ -2155,6 +2174,18 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
+ 				PTR_ERR(rdev));
+ 			return PTR_ERR(rdev);
+ 		}
++		/* set save_raid_disk if appropriate */
++		if (!mddev->persistent) {
++			if (info->state & (1<raid_disk < mddev->raid_disks)
++				rdev->raid_disk = info->raid_disk;
++			else
++				rdev->raid_disk = -1;
++		} else
++			super_types[mddev->major_version].
++				validate_super(mddev, rdev);
++		rdev->saved_raid_disk = rdev->raid_disk;
++
+ 		rdev->in_sync = 0; /* just to be sure */
+ 		rdev->raid_disk = -1;
+ 		err = bind_rdev_to_array(rdev, mddev);
+@@ -3706,6 +3737,14 @@ void md_check_recovery(mddev_t *mddev)
+ 				mddev->pers->spare_active(mddev);
+ 			}
+ 			md_update_sb(mddev);
++
++			/* if array is no-longer degraded, then any saved_raid_disk
++			 * information must be scrapped
++			 */
++			if (!mddev->degraded)
++				ITERATE_RDEV(mddev,rdev,rtmp)
++					rdev->saved_raid_disk = -1;
++
+ 			mddev->recovery = 0;
+ 			/* flag recovery needed just to double check */
+ 			set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index c3b4772cfaea..3f5234fe3593 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -811,9 +811,12 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
+ {
+ 	conf_t *conf = mddev->private;
+ 	int found = 0;
+-	int mirror;
++	int mirror = 0;
+ 	mirror_info_t *p;
+ 
++	if (rdev->saved_raid_disk >= 0 &&
++	    conf->mirrors[rdev->saved_raid_disk].rdev == NULL)
++		mirror = rdev->saved_raid_disk;
+ 	for (mirror=0; mirror < mddev->raid_disks; mirror++)
+ 		if ( !(p=conf->mirrors+mirror)->rdev) {
+ 
+@@ -830,6 +833,8 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
+ 			p->head_position = 0;
+ 			rdev->raid_disk = mirror;
+ 			found = 1;
++			if (rdev->saved_raid_disk != mirror)
++				conf->fullsync = 1;
+ 			p->rdev = rdev;
+ 			break;
+ 		}
+diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
+index 16e94a9f0f8c..6cdcb4434c6c 100644
+--- a/include/linux/raid/md_k.h
++++ b/include/linux/raid/md_k.h
+@@ -183,6 +183,10 @@ struct mdk_rdev_s
+ 
+ 	int desc_nr;			/* descriptor index in the superblock */
+ 	int raid_disk;			/* role of device in array */
++	int saved_raid_disk;		/* role that device used to have in the
++					 * array and could again if we did a partial
++					 * resync from the bitmap
++					 */
+ 
+ 	atomic_t	nr_pending;	/* number of pending requests.
+ 					 * only maintained for arrays that

commit 289e99e8ed8f36e386bf7de49947311c17ae1482
+Author: NeilBrown 
+Date:   Tue Jun 21 17:17:24 2005 -0700
+
+    [PATCH] md: initialise sync_blocks in raid1 resync
+    
+    Otherwise it could have a random value and might BUG.  This fixes a BUG
+    during resync problem in raid1 introduced by the bitmap-based-intent-loggin
+    patches.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index 9d9acc3e51a7..c3b4772cfaea 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -1230,6 +1230,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
+ 	}
+ 
+ 	nr_sectors = 0;
++	sync_blocks = 0;
+ 	do {
+ 		struct page *page;
+ 		int len = PAGE_SIZE;

commit ab7a30c7051ee32d0d72415fe0a16d60eba38a0d
+Author: NeilBrown 
+Date:   Tue Jun 21 17:17:23 2005 -0700
+
+    [PATCH] md: fix bug when raid1 attempts a partial reconstruct.
+    
+    The logic here is wrong.  if fullsync is 0, it WILL BUG.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index 0fd4c3bfc851..9d9acc3e51a7 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -1237,13 +1237,16 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
+ 			len = (max_sector - sector_nr) << 9;
+ 		if (len == 0)
+ 			break;
+-		if (!conf->fullsync && sync_blocks == 0)
+-			if (!bitmap_start_sync(mddev->bitmap,
+-					       sector_nr, &sync_blocks))
+-				break;
+-		if (sync_blocks < (PAGE_SIZE>>9))
+-			BUG();
+-		if (len > (sync_blocks<<9)) len = sync_blocks<<9;
++		if (!conf->fullsync) {
++			if (sync_blocks == 0) {
++				if (!bitmap_start_sync(mddev->bitmap,
++						       sector_nr, &sync_blocks))
++					break;
++				if (sync_blocks < (PAGE_SIZE>>9))
++					BUG();
++				if (len > (sync_blocks<<9)) len = sync_blocks<<9;
++			}
++		}
+ 
+ 		for (i=0 ; i < conf->raid_disks; i++) {
+ 			bio = r1_bio->bios[i];

commit 191ea9b2c7cc3ebbe0678834ab710d7d95ad3f9a
+Author: NeilBrown 
+Date:   Tue Jun 21 17:17:23 2005 -0700
+
+    [PATCH] md: raid1 support for bitmap intent logging
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index 3c5c916cb09e..0fd4c3bfc851 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -12,6 +12,15 @@
+  * Fixes to reconstruction by Jakob ?stergaard" 
+  * Various fixes by Neil Brown 
+  *
++ * Changes by Peter T. Breuer  31/1/2003 to support
++ * bitmapped intelligence in resync:
++ *
++ *      - bitmap marked during normal i/o
++ *      - bitmap used to skip nondirty blocks during sync
++ *
++ * Additions to bitmap code, (C) 2003-2004 Paul Clements, SteelEye Technology:
++ * - persistent bitmap code
++ *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+  * the Free Software Foundation; either version 2, or (at your option)
+@@ -22,7 +31,16 @@
+  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+  */
+ 
++#include "dm-bio-list.h"
+ #include 
++#include 
++
++#define DEBUG 0
++#if DEBUG
++#define PRINTK(x...) printk(x)
++#else
++#define PRINTK(x...)
++#endif
+ 
+ /*
+  * Number of guaranteed r1bios in case of extreme VM load:
+@@ -287,9 +305,11 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
+ 	/*
+ 	 * this branch is our 'one mirror IO has finished' event handler:
+ 	 */
+-	if (!uptodate)
++	if (!uptodate) {
+ 		md_error(r1_bio->mddev, conf->mirrors[mirror].rdev);
+-	else
++		/* an I/O failed, we can't clear the bitmap */
++		set_bit(R1BIO_Degraded, &r1_bio->state);
++	} else
+ 		/*
+ 		 * Set R1BIO_Uptodate in our master bio, so that
+ 		 * we will return a good error code for to the higher
+@@ -309,6 +329,10 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
+ 	 * already.
+ 	 */
+ 	if (atomic_dec_and_test(&r1_bio->remaining)) {
++		/* clear the bitmap if all writes complete successfully */
++		bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector,
++				r1_bio->sectors,
++				!test_bit(R1BIO_Degraded, &r1_bio->state));
+ 		md_write_end(r1_bio->mddev);
+ 		raid_end_bio_io(r1_bio);
+ 	}
+@@ -458,7 +482,10 @@ static void unplug_slaves(mddev_t *mddev)
+ 
+ static void raid1_unplug(request_queue_t *q)
+ {
+-	unplug_slaves(q->queuedata);
++	mddev_t *mddev = q->queuedata;
++
++	unplug_slaves(mddev);
++	md_wakeup_thread(mddev->thread);
+ }
+ 
+ static int raid1_issue_flush(request_queue_t *q, struct gendisk *disk,
+@@ -501,16 +528,16 @@ static void device_barrier(conf_t *conf, sector_t sect)
+ {
+ 	spin_lock_irq(&conf->resync_lock);
+ 	wait_event_lock_irq(conf->wait_idle, !waitqueue_active(&conf->wait_resume),
+-			    conf->resync_lock, unplug_slaves(conf->mddev));
++			    conf->resync_lock, raid1_unplug(conf->mddev->queue));
+ 	
+ 	if (!conf->barrier++) {
+ 		wait_event_lock_irq(conf->wait_idle, !conf->nr_pending,
+-				    conf->resync_lock, unplug_slaves(conf->mddev));
++				    conf->resync_lock, raid1_unplug(conf->mddev->queue));
+ 		if (conf->nr_pending)
+ 			BUG();
+ 	}
+ 	wait_event_lock_irq(conf->wait_resume, conf->barrier < RESYNC_DEPTH,
+-			    conf->resync_lock, unplug_slaves(conf->mddev));
++			    conf->resync_lock, raid1_unplug(conf->mddev->queue));
+ 	conf->next_resync = sect;
+ 	spin_unlock_irq(&conf->resync_lock);
+ }
+@@ -522,8 +549,12 @@ static int make_request(request_queue_t *q, struct bio * bio)
+ 	mirror_info_t *mirror;
+ 	r1bio_t *r1_bio;
+ 	struct bio *read_bio;
+-	int i, disks;
++	int i, targets = 0, disks;
+ 	mdk_rdev_t *rdev;
++	struct bitmap *bitmap = mddev->bitmap;
++	unsigned long flags;
++	struct bio_list bl;
++
+ 
+ 	/*
+ 	 * Register the new request and wait if the reconstruction
+@@ -554,7 +585,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
+ 
+ 	r1_bio->master_bio = bio;
+ 	r1_bio->sectors = bio->bi_size >> 9;
+-
++	r1_bio->state = 0;
+ 	r1_bio->mddev = mddev;
+ 	r1_bio->sector = bio->bi_sector;
+ 
+@@ -597,6 +628,13 @@ static int make_request(request_queue_t *q, struct bio * bio)
+ 	 * bios[x] to bio
+ 	 */
+ 	disks = conf->raid_disks;
++#if 0
++	{ static int first=1;
++	if (first) printk("First Write sector %llu disks %d\n",
++			  (unsigned long long)r1_bio->sector, disks);
++	first = 0;
++	}
++#endif
+ 	rcu_read_lock();
+ 	for (i = 0;  i < disks; i++) {
+ 		if ((rdev=conf->mirrors[i].rdev) != NULL &&
+@@ -607,13 +645,21 @@ static int make_request(request_queue_t *q, struct bio * bio)
+ 				r1_bio->bios[i] = NULL;
+ 			} else
+ 				r1_bio->bios[i] = bio;
++			targets++;
+ 		} else
+ 			r1_bio->bios[i] = NULL;
+ 	}
+ 	rcu_read_unlock();
+ 
+-	atomic_set(&r1_bio->remaining, 1);
++	if (targets < conf->raid_disks) {
++		/* array is degraded, we will not clear the bitmap
++		 * on I/O completion (see raid1_end_write_request) */
++		set_bit(R1BIO_Degraded, &r1_bio->state);
++	}
++
++	atomic_set(&r1_bio->remaining, 0);
+ 
++	bio_list_init(&bl);
+ 	for (i = 0; i < disks; i++) {
+ 		struct bio *mbio;
+ 		if (!r1_bio->bios[i])
+@@ -629,14 +675,23 @@ static int make_request(request_queue_t *q, struct bio * bio)
+ 		mbio->bi_private = r1_bio;
+ 
+ 		atomic_inc(&r1_bio->remaining);
+-		generic_make_request(mbio);
+-	}
+ 
+-	if (atomic_dec_and_test(&r1_bio->remaining)) {
+-		md_write_end(mddev);
+-		raid_end_bio_io(r1_bio);
++		bio_list_add(&bl, mbio);
+ 	}
+ 
++	bitmap_startwrite(bitmap, bio->bi_sector, r1_bio->sectors);
++	spin_lock_irqsave(&conf->device_lock, flags);
++	bio_list_merge(&conf->pending_bio_list, &bl);
++	bio_list_init(&bl);
++
++	blk_plug_device(mddev->queue);
++	spin_unlock_irqrestore(&conf->device_lock, flags);
++
++#if 0
++	while ((bio = bio_list_pop(&bl)) != NULL)
++		generic_make_request(bio);
++#endif
++
+ 	return 0;
+ }
+ 
+@@ -716,7 +771,7 @@ static void close_sync(conf_t *conf)
+ {
+ 	spin_lock_irq(&conf->resync_lock);
+ 	wait_event_lock_irq(conf->wait_resume, !conf->barrier,
+-			    conf->resync_lock, 	unplug_slaves(conf->mddev));
++			    conf->resync_lock, 	raid1_unplug(conf->mddev->queue));
+ 	spin_unlock_irq(&conf->resync_lock);
+ 
+ 	if (conf->barrier) BUG();
+@@ -830,10 +885,11 @@ static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error)
+ 	 * or re-read if the read failed.
+ 	 * We don't do much here, just schedule handling by raid1d
+ 	 */
+-	if (!uptodate)
++	if (!uptodate) {
+ 		md_error(r1_bio->mddev,
+ 			 conf->mirrors[r1_bio->read_disk].rdev);
+-	else
++		set_bit(R1BIO_Degraded, &r1_bio->state);
++	} else
+ 		set_bit(R1BIO_Uptodate, &r1_bio->state);
+ 	rdev_dec_pending(conf->mirrors[r1_bio->read_disk].rdev, conf->mddev);
+ 	reschedule_retry(r1_bio);
+@@ -857,8 +913,10 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error)
+ 			mirror = i;
+ 			break;
+ 		}
+-	if (!uptodate)
++	if (!uptodate) {
+ 		md_error(mddev, conf->mirrors[mirror].rdev);
++		set_bit(R1BIO_Degraded, &r1_bio->state);
++	}
+ 	update_head_pos(mirror, r1_bio);
+ 
+ 	if (atomic_dec_and_test(&r1_bio->remaining)) {
+@@ -878,6 +936,9 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
+ 
+ 	bio = r1_bio->bios[r1_bio->read_disk];
+ 
++/*
++	if (r1_bio->sector == 0) printk("First sync write startss\n");
++*/
+ 	/*
+ 	 * schedule writes
+ 	 */
+@@ -905,10 +966,12 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
+ 		atomic_inc(&conf->mirrors[i].rdev->nr_pending);
+ 		atomic_inc(&r1_bio->remaining);
+ 		md_sync_acct(conf->mirrors[i].rdev->bdev, wbio->bi_size >> 9);
++
+ 		generic_make_request(wbio);
+ 	}
+ 
+ 	if (atomic_dec_and_test(&r1_bio->remaining)) {
++		/* if we're here, all write(s) have completed, so clean up */
+ 		md_done_sync(mddev, r1_bio->sectors, 1);
+ 		put_buf(r1_bio);
+ 	}
+@@ -937,6 +1000,26 @@ static void raid1d(mddev_t *mddev)
+ 	for (;;) {
+ 		char b[BDEVNAME_SIZE];
+ 		spin_lock_irqsave(&conf->device_lock, flags);
++
++		if (conf->pending_bio_list.head) {
++			bio = bio_list_get(&conf->pending_bio_list);
++			blk_remove_plug(mddev->queue);
++			spin_unlock_irqrestore(&conf->device_lock, flags);
++			/* flush any pending bitmap writes to disk before proceeding w/ I/O */
++			if (bitmap_unplug(mddev->bitmap) != 0)
++				printk("%s: bitmap file write failed!\n", mdname(mddev));
++
++			while (bio) { /* submit pending writes */
++				struct bio *next = bio->bi_next;
++				bio->bi_next = NULL;
++				generic_make_request(bio);
++				bio = next;
++			}
++			unplug = 1;
++
++			continue;
++		}
++
+ 		if (list_empty(head))
+ 			break;
+ 		r1_bio = list_entry(head->prev, r1bio_t, retry_list);
+@@ -1020,17 +1103,43 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
+ 	int disk;
+ 	int i;
+ 	int write_targets = 0;
++	int sync_blocks;
+ 
+ 	if (!conf->r1buf_pool)
++	{
++/*
++		printk("sync start - bitmap %p\n", mddev->bitmap);
++*/
+ 		if (init_resync(conf))
+ 			return 0;
++	}
+ 
+ 	max_sector = mddev->size << 1;
+ 	if (sector_nr >= max_sector) {
++		/* If we aborted, we need to abort the
++		 * sync on the 'current' bitmap chunk (there will
++		 * only be one in raid1 resync.
++		 * We can find the current addess in mddev->curr_resync
++		 */
++		if (!conf->fullsync) {
++			if (mddev->curr_resync < max_sector)
++				bitmap_end_sync(mddev->bitmap,
++						mddev->curr_resync,
++						&sync_blocks, 1);
++			bitmap_close_sync(mddev->bitmap);
++		}
++		if (mddev->curr_resync >= max_sector)
++			conf->fullsync = 0;
+ 		close_sync(conf);
+ 		return 0;
+ 	}
+ 
++	if (!conf->fullsync &&
++	    !bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks)) {
++		/* We can skip this block, and probably several more */
++		*skipped = 1;
++		return sync_blocks;
++	}
+ 	/*
+ 	 * If there is non-resync activity waiting for us then
+ 	 * put in a delay to throttle resync.
+@@ -1069,6 +1178,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
+ 
+ 	r1_bio->mddev = mddev;
+ 	r1_bio->sector = sector_nr;
++	r1_bio->state = 0;
+ 	set_bit(R1BIO_IsSync, &r1_bio->state);
+ 	r1_bio->read_disk = disk;
+ 
+@@ -1103,6 +1213,11 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
+ 		bio->bi_bdev = conf->mirrors[i].rdev->bdev;
+ 		bio->bi_private = r1_bio;
+ 	}
++
++	if (write_targets + 1 < conf->raid_disks)
++		/* array degraded, can't clear bitmap */
++		set_bit(R1BIO_Degraded, &r1_bio->state);
++
+ 	if (write_targets == 0) {
+ 		/* There is nowhere to write, so all non-sync
+ 		 * drives must be failed - so we are finished
+@@ -1122,6 +1237,14 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
+ 			len = (max_sector - sector_nr) << 9;
+ 		if (len == 0)
+ 			break;
++		if (!conf->fullsync && sync_blocks == 0)
++			if (!bitmap_start_sync(mddev->bitmap,
++					       sector_nr, &sync_blocks))
++				break;
++		if (sync_blocks < (PAGE_SIZE>>9))
++			BUG();
++		if (len > (sync_blocks<<9)) len = sync_blocks<<9;
++
+ 		for (i=0 ; i < conf->raid_disks; i++) {
+ 			bio = r1_bio->bios[i];
+ 			if (bio->bi_end_io) {
+@@ -1144,6 +1267,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
+ 		}
+ 		nr_sectors += len>>9;
+ 		sector_nr += len>>9;
++		sync_blocks -= (len>>9);
+ 	} while (r1_bio->bios[disk]->bi_vcnt < RESYNC_PAGES);
+  bio_full:
+ 	bio = r1_bio->bios[disk];
+@@ -1232,6 +1356,9 @@ static int run(mddev_t *mddev)
+ 	init_waitqueue_head(&conf->wait_idle);
+ 	init_waitqueue_head(&conf->wait_resume);
+ 
++	bio_list_init(&conf->pending_bio_list);
++	bio_list_init(&conf->flushing_bio_list);
++
+ 	if (!conf->working_disks) {
+ 		printk(KERN_ERR "raid1: no operational mirrors for %s\n",
+ 			mdname(mddev));
+@@ -1260,16 +1387,15 @@ static int run(mddev_t *mddev)
+ 	conf->last_used = j;
+ 
+ 
+-
+-	{
+-		mddev->thread = md_register_thread(raid1d, mddev, "%s_raid1");
+-		if (!mddev->thread) {
+-			printk(KERN_ERR 
+-				"raid1: couldn't allocate thread for %s\n", 
+-				mdname(mddev));
+-			goto out_free_conf;
+-		}
++	mddev->thread = md_register_thread(raid1d, mddev, "%s_raid1");
++	if (!mddev->thread) {
++		printk(KERN_ERR
++		       "raid1: couldn't allocate thread for %s\n",
++		       mdname(mddev));
++		goto out_free_conf;
+ 	}
++	if (mddev->bitmap) mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
++
+ 	printk(KERN_INFO 
+ 		"raid1: raid set %s active with %d out of %d mirrors\n",
+ 		mdname(mddev), mddev->raid_disks - mddev->degraded, 
+@@ -1394,7 +1520,7 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
+ 	spin_lock_irq(&conf->resync_lock);
+ 	conf->barrier++;
+ 	wait_event_lock_irq(conf->wait_idle, !conf->nr_pending,
+-			    conf->resync_lock, unplug_slaves(mddev));
++			    conf->resync_lock, raid1_unplug(mddev->queue));
+ 	spin_unlock_irq(&conf->resync_lock);
+ 
+ 	/* ok, everything is stopped */
+diff --git a/include/linux/raid/raid1.h b/include/linux/raid/raid1.h
+index abbfdd9afe1e..9d93cf12e890 100644
+--- a/include/linux/raid/raid1.h
++++ b/include/linux/raid/raid1.h
+@@ -36,12 +36,21 @@ struct r1_private_data_s {
+ 	spinlock_t		device_lock;
+ 
+ 	struct list_head	retry_list;
++	/* queue pending writes and submit them on unplug */
++	struct bio_list		pending_bio_list;
++	/* queue of writes that have been unplugged */
++	struct bio_list		flushing_bio_list;
++
+ 	/* for use when syncing mirrors: */
+ 
+ 	spinlock_t		resync_lock;
+-	int nr_pending;
+-	int barrier;
++	int			nr_pending;
++	int			barrier;
+ 	sector_t		next_resync;
++	int			fullsync;  /* set to 1 if a full sync is needed,
++					    * (fresh device added).
++					    * Cleared when a sync completes.
++					    */
+ 
+ 	wait_queue_head_t	wait_idle;
+ 	wait_queue_head_t	wait_resume;
+@@ -85,14 +94,17 @@ struct r1bio_s {
+ 	int			read_disk;
+ 
+ 	struct list_head	retry_list;
++	struct bitmap_update	*bitmap_update;
+ 	/*
+ 	 * if the IO is in WRITE direction, then multiple bios are used.
+ 	 * We choose the number when they are allocated.
+ 	 */
+ 	struct bio		*bios[0];
++	/* DO NOT PUT ANY NEW FIELDS HERE - bios array is contiguously alloced*/
+ };
+ 
+ /* bits for r1bio.state */
+ #define	R1BIO_Uptodate	0
+ #define	R1BIO_IsSync	1
++#define	R1BIO_Degraded	2
+ #endif

commit aa3163f81654fa057039258e32a6811147bf0c14
+Author: NeilBrown 
+Date:   Tue Jun 21 17:17:22 2005 -0700
+
+    [PATCH] md: don't skip bitmap pages due to lack of bit that we just cleared.
+    
+    When looking for pages that need cleaning we skip pages that don't have
+    BITMAP_PAGE_CLEAN set.  But if it is the 'current' page we will have cleared
+    that bit ourselves, so skipping it is wrong.  So: move the 'skip this page'
+    inside 'if page != lastpage'.
+    
+    Also fold call of file_page_offset into the one place where the value (bit) is
+    used.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
+index 86b6b037fa44..204564dc6a0d 100644
+--- a/drivers/md/bitmap.c
++++ b/drivers/md/bitmap.c
+@@ -897,7 +897,7 @@ static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
+ 
+ int bitmap_daemon_work(struct bitmap *bitmap)
+ {
+-	unsigned long bit, j;
++	unsigned long j;
+ 	unsigned long flags;
+ 	struct page *page = NULL, *lastpage = NULL;
+ 	int err = 0;
+@@ -920,24 +920,23 @@ int bitmap_daemon_work(struct bitmap *bitmap)
+ 		}
+ 
+ 		page = filemap_get_page(bitmap, j);
+-		/* skip this page unless it's marked as needing cleaning */
+-		if (!((attr=get_page_attr(bitmap, page)) & BITMAP_PAGE_CLEAN)) {
+-			if (attr & BITMAP_PAGE_NEEDWRITE) {
+-				page_cache_get(page);
+-				clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
+-			}
+-			spin_unlock_irqrestore(&bitmap->lock, flags);
+-			if (attr & BITMAP_PAGE_NEEDWRITE) {
+-				if (write_page(bitmap, page, 0))
+-					bitmap_file_kick(bitmap);
+-				page_cache_release(page);
+-			}
+-			continue;
+-		}
+-
+-		bit = file_page_offset(j);
+ 
+ 		if (page != lastpage) {
++			/* skip this page unless it's marked as needing cleaning */
++			if (!((attr=get_page_attr(bitmap, page)) & BITMAP_PAGE_CLEAN)) {
++				if (attr & BITMAP_PAGE_NEEDWRITE) {
++					page_cache_get(page);
++					clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
++				}
++				spin_unlock_irqrestore(&bitmap->lock, flags);
++				if (attr & BITMAP_PAGE_NEEDWRITE) {
++					if (write_page(bitmap, page, 0))
++						bitmap_file_kick(bitmap);
++					page_cache_release(page);
++				}
++				continue;
++			}
++
+ 			/* grab the new page, sync and release the old */
+ 			page_cache_get(page);
+ 			if (lastpage != NULL) {
+@@ -979,7 +978,7 @@ int bitmap_daemon_work(struct bitmap *bitmap)
+ 						  -1);
+ 
+ 				/* clear the bit */
+-				clear_bit(bit, page_address(page));
++				clear_bit(file_page_offset(j), page_address(page));
+ 			}
+ 		}
+ 		spin_unlock_irqrestore(&bitmap->lock, flags);

commit 77ad4bc706fe6c52ab953f31c287a6af712d080c
+Author: NeilBrown 
+Date:   Tue Jun 21 17:17:21 2005 -0700
+
+    [PATCH] md: enable the bitmap write-back daemon and wait for it.
+    
+    Currently we don't wait for updates to the bitmap to be flushed to disk
+    properly.  The infrastructure all there, but it isn't being used....
+    
+    A separate kernel thread (bitmap_writeback_daemon) is needed to wait for each
+    page as we cannot get callbacks when a page write completes.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
+index 9462fdd517c0..86b6b037fa44 100644
+--- a/drivers/md/bitmap.c
++++ b/drivers/md/bitmap.c
+@@ -261,30 +261,33 @@ char *file_path(struct file *file, char *buf, int count)
+ /*
+  * write out a page
+  */
+-static int write_page(struct page *page, int wait)
++static int write_page(struct bitmap *bitmap, struct page *page, int wait)
+ {
+ 	int ret = -ENOMEM;
+ 
+ 	lock_page(page);
+ 
+-	if (page->mapping == NULL)
+-		goto unlock_out;
+-	else if (i_size_read(page->mapping->host) < page->index << PAGE_SHIFT) {
+-		ret = -ENOENT;
+-		goto unlock_out;
+-	}
+-
+ 	ret = page->mapping->a_ops->prepare_write(NULL, page, 0, PAGE_SIZE);
+ 	if (!ret)
+ 		ret = page->mapping->a_ops->commit_write(NULL, page, 0,
+ 			PAGE_SIZE);
+ 	if (ret) {
+-unlock_out:
+ 		unlock_page(page);
+ 		return ret;
+ 	}
+ 
+ 	set_page_dirty(page); /* force it to be written out */
++
++	if (!wait) {
++		/* add to list to be waited for by daemon */
++		struct page_list *item = mempool_alloc(bitmap->write_pool, GFP_NOIO);
++		item->page = page;
++		page_cache_get(page);
++		spin_lock(&bitmap->write_lock);
++		list_add(&item->list, &bitmap->complete_pages);
++		spin_unlock(&bitmap->write_lock);
++		md_wakeup_thread(bitmap->writeback_daemon);
++	}
+ 	return write_one_page(page, wait);
+ }
+ 
+@@ -343,14 +346,13 @@ int bitmap_update_sb(struct bitmap *bitmap)
+ 		spin_unlock_irqrestore(&bitmap->lock, flags);
+ 		return 0;
+ 	}
+-	page_cache_get(bitmap->sb_page);
+ 	spin_unlock_irqrestore(&bitmap->lock, flags);
+ 	sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+ 	sb->events = cpu_to_le64(bitmap->mddev->events);
+ 	if (!bitmap->mddev->degraded)
+ 		sb->events_cleared = cpu_to_le64(bitmap->mddev->events);
+ 	kunmap(bitmap->sb_page);
+-	return write_page(bitmap->sb_page, 0);
++	return write_page(bitmap, bitmap->sb_page, 0);
+ }
+ 
+ /* print out the bitmap file superblock */
+@@ -556,10 +558,10 @@ static void bitmap_file_unmap(struct bitmap *bitmap)
+ static void bitmap_stop_daemons(struct bitmap *bitmap);
+ 
+ /* dequeue the next item in a page list -- don't call from irq context */
+-static struct page_list *dequeue_page(struct bitmap *bitmap,
+-					struct list_head *head)
++static struct page_list *dequeue_page(struct bitmap *bitmap)
+ {
+ 	struct page_list *item = NULL;
++	struct list_head *head = &bitmap->complete_pages;
+ 
+ 	spin_lock(&bitmap->write_lock);
+ 	if (list_empty(head))
+@@ -573,23 +575,15 @@ static struct page_list *dequeue_page(struct bitmap *bitmap,
+ 
+ static void drain_write_queues(struct bitmap *bitmap)
+ {
+-	struct list_head *queues[] = { 	&bitmap->complete_pages, NULL };
+-	struct list_head *head;
+ 	struct page_list *item;
+-	int i;
+ 
+-	for (i = 0; queues[i]; i++) {
+-		head = queues[i];
+-		while ((item = dequeue_page(bitmap, head))) {
+-			page_cache_release(item->page);
+-			mempool_free(item, bitmap->write_pool);
+-		}
++	while ((item = dequeue_page(bitmap))) {
++		/* don't bother to wait */
++		page_cache_release(item->page);
++		mempool_free(item, bitmap->write_pool);
+ 	}
+ 
+-	spin_lock(&bitmap->write_lock);
+-	bitmap->writes_pending = 0; /* make sure waiters continue */
+ 	wake_up(&bitmap->write_wait);
+-	spin_unlock(&bitmap->write_lock);
+ }
+ 
+ static void bitmap_file_put(struct bitmap *bitmap)
+@@ -734,13 +728,13 @@ int bitmap_unplug(struct bitmap *bitmap)
+ 		spin_unlock_irqrestore(&bitmap->lock, flags);
+ 
+ 		if (attr & (BITMAP_PAGE_DIRTY | BITMAP_PAGE_NEEDWRITE))
+-			if (write_page(page, 0))
++			if (write_page(bitmap, page, 0))
+ 				return 1;
+ 	}
+ 	if (wait) { /* if any writes were performed, we need to wait on them */
+ 		spin_lock_irq(&bitmap->write_lock);
+ 		wait_event_lock_irq(bitmap->write_wait,
+-			bitmap->writes_pending == 0, bitmap->write_lock,
++			list_empty(&bitmap->complete_pages), bitmap->write_lock,
+ 			wake_up_process(bitmap->writeback_daemon->tsk));
+ 		spin_unlock_irq(&bitmap->write_lock);
+ 	}
+@@ -841,7 +835,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
+ 				 */
+ 				memset(page_address(page) + offset, 0xff,
+ 					PAGE_SIZE - offset);
+-				ret = write_page(page, 1);
++				ret = write_page(bitmap, page, 1);
+ 				if (ret) {
+ 					kunmap(page);
+ 					/* release, page not in filemap yet */
+@@ -934,7 +928,7 @@ int bitmap_daemon_work(struct bitmap *bitmap)
+ 			}
+ 			spin_unlock_irqrestore(&bitmap->lock, flags);
+ 			if (attr & BITMAP_PAGE_NEEDWRITE) {
+-				if (write_page(page, 0))
++				if (write_page(bitmap, page, 0))
+ 					bitmap_file_kick(bitmap);
+ 				page_cache_release(page);
+ 			}
+@@ -950,7 +944,7 @@ int bitmap_daemon_work(struct bitmap *bitmap)
+ 				if (get_page_attr(bitmap, lastpage) & BITMAP_PAGE_NEEDWRITE) {
+ 					clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+ 					spin_unlock_irqrestore(&bitmap->lock, flags);
+-					err = write_page(lastpage, 0);
++					err = write_page(bitmap, lastpage, 0);
+ 				} else {
+ 					set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+ 					spin_unlock_irqrestore(&bitmap->lock, flags);
+@@ -998,7 +992,7 @@ int bitmap_daemon_work(struct bitmap *bitmap)
+ 		if (get_page_attr(bitmap, lastpage) &BITMAP_PAGE_NEEDWRITE) {
+ 			clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+ 			spin_unlock_irqrestore(&bitmap->lock, flags);
+-			err = write_page(lastpage, 0);
++			err = write_page(bitmap, lastpage, 0);
+ 		} else {
+ 			set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+ 			spin_unlock_irqrestore(&bitmap->lock, flags);
+@@ -1034,46 +1028,40 @@ static void bitmap_writeback_daemon(mddev_t *mddev)
+ 	struct page_list *item;
+ 	int err = 0;
+ 
+-	while (1) {
+-		PRINTK("%s: bitmap writeback daemon waiting...\n", bmname(bitmap));
+-		down_interruptible(&bitmap->write_done);
+-		if (signal_pending(current)) {
+-			printk(KERN_INFO
+-			    "%s: bitmap writeback daemon got signal, exiting...\n",
+-			    bmname(bitmap));
+-			break;
+-		}
++	if (signal_pending(current)) {
++		printk(KERN_INFO
++		       "%s: bitmap writeback daemon got signal, exiting...\n",
++		       bmname(bitmap));
++		err = -EINTR;
++		goto out;
++	}
+ 
+-		PRINTK("%s: bitmap writeback daemon woke up...\n", bmname(bitmap));
+-		/* wait on bitmap page writebacks */
+-		while ((item = dequeue_page(bitmap, &bitmap->complete_pages))) {
+-			page = item->page;
+-			mempool_free(item, bitmap->write_pool);
+-			PRINTK("wait on page writeback: %p %lu\n", page, bitmap->writes_pending);
+-			wait_on_page_writeback(page);
+-			PRINTK("finished page writeback: %p %lu\n", page, bitmap->writes_pending);
+-			spin_lock(&bitmap->write_lock);
+-			if (!--bitmap->writes_pending)
+-				wake_up(&bitmap->write_wait);
+-			spin_unlock(&bitmap->write_lock);
+-			err = PageError(page);
+-			page_cache_release(page);
+-			if (err) {
+-				printk(KERN_WARNING "%s: bitmap file writeback "
+-					"failed (page %lu): %d\n",
+-					bmname(bitmap), page->index, err);
+-				bitmap_file_kick(bitmap);
+-				goto out;
+-			}
++	PRINTK("%s: bitmap writeback daemon woke up...\n", bmname(bitmap));
++	/* wait on bitmap page writebacks */
++	while ((item = dequeue_page(bitmap))) {
++		page = item->page;
++		mempool_free(item, bitmap->write_pool);
++		PRINTK("wait on page writeback: %p\n", page);
++		wait_on_page_writeback(page);
++		PRINTK("finished page writeback: %p\n", page);
++
++		err = PageError(page);
++		page_cache_release(page);
++		if (err) {
++			printk(KERN_WARNING "%s: bitmap file writeback "
++			       "failed (page %lu): %d\n",
++			       bmname(bitmap), page->index, err);
++			bitmap_file_kick(bitmap);
++			goto out;
+ 		}
+ 	}
+-out:
++ out:
++	wake_up(&bitmap->write_wait);
+ 	if (err) {
+ 		printk(KERN_INFO "%s: bitmap writeback daemon exiting (%d)\n",
+-			bmname(bitmap), err);
++		       bmname(bitmap), err);
+ 		daemon_exit(bitmap, &bitmap->writeback_daemon);
+ 	}
+-	return;
+ }
+ 
+ static int bitmap_start_daemon(struct bitmap *bitmap, mdk_thread_t **ptr,
+@@ -1375,7 +1363,7 @@ int bitmap_setallbits(struct bitmap *bitmap)
+ 		spin_unlock_irqrestore(&bitmap->lock, flags);
+ 		memset(kmap(page), 0xff, PAGE_SIZE);
+ 		kunmap(page);
+-		if (write_page(page, 0))
++		if (write_page(bitmap, page, 0))
+ 			return 1;
+ 	}
+ 
+@@ -1443,7 +1431,6 @@ int bitmap_create(mddev_t *mddev)
+ 	mddev->bitmap = bitmap;
+ 
+ 	spin_lock_init(&bitmap->write_lock);
+-	init_MUTEX_LOCKED(&bitmap->write_done);
+ 	INIT_LIST_HEAD(&bitmap->complete_pages);
+ 	init_waitqueue_head(&bitmap->write_wait);
+ 	bitmap->write_pool = mempool_create(WRITE_POOL_SIZE, write_pool_alloc,
+diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h
+index f785cf26cbad..cfe60cfc8f3d 100644
+--- a/include/linux/raid/bitmap.h
++++ b/include/linux/raid/bitmap.h
+@@ -233,21 +233,12 @@ struct bitmap {
+ 	unsigned long daemon_sleep; /* how many seconds between updates? */
+ 
+ 	/*
+-	 * bitmap write daemon - this daemon performs writes to the bitmap file
+-	 * this thread is only needed because of a limitation in ext3 (jbd)
+-	 * that does not allow a task to have two journal transactions ongoing
+-	 * simultaneously (even if the transactions are for two different
+-	 * filesystems) -- in the case of bitmap, that would be the filesystem
+-	 * that the bitmap file resides on and the filesystem that is mounted
+-	 * on the md device -- see current->journal_info in jbd/transaction.c
++	 * bitmap_writeback_daemon waits for file-pages that have been written,
++	 * as there is no way to get a call-back when a page write completes.
+ 	 */
+ 	mdk_thread_t *writeback_daemon;
+ 	spinlock_t write_lock;
+-	struct semaphore write_ready;
+-	struct semaphore write_done;
+-	unsigned long writes_pending;
+ 	wait_queue_head_t write_wait;
+-	struct list_head write_pages;
+ 	struct list_head complete_pages;
+ 	mempool_t *write_pool;
+ };

commit bfb39fba4e8cdda091f9ebee29fbb8331c4bb605
+Author: NeilBrown 
+Date:   Tue Jun 21 17:17:20 2005 -0700
+
+    [PATCH] md: check return value of write_page, rather than ignore it
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
+index f197db2ef92d..9462fdd517c0 100644
+--- a/drivers/md/bitmap.c
++++ b/drivers/md/bitmap.c
+@@ -350,8 +350,7 @@ int bitmap_update_sb(struct bitmap *bitmap)
+ 	if (!bitmap->mddev->degraded)
+ 		sb->events_cleared = cpu_to_le64(bitmap->mddev->events);
+ 	kunmap(bitmap->sb_page);
+-	write_page(bitmap->sb_page, 0);
+-	return 0;
++	return write_page(bitmap->sb_page, 0);
+ }
+ 
+ /* print out the bitmap file superblock */
+@@ -735,7 +734,8 @@ int bitmap_unplug(struct bitmap *bitmap)
+ 		spin_unlock_irqrestore(&bitmap->lock, flags);
+ 
+ 		if (attr & (BITMAP_PAGE_DIRTY | BITMAP_PAGE_NEEDWRITE))
+-			write_page(page, 0);
++			if (write_page(page, 0))
++				return 1;
+ 	}
+ 	if (wait) { /* if any writes were performed, we need to wait on them */
+ 		spin_lock_irq(&bitmap->write_lock);
+@@ -950,7 +950,7 @@ int bitmap_daemon_work(struct bitmap *bitmap)
+ 				if (get_page_attr(bitmap, lastpage) & BITMAP_PAGE_NEEDWRITE) {
+ 					clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+ 					spin_unlock_irqrestore(&bitmap->lock, flags);
+-					write_page(lastpage, 0);
++					err = write_page(lastpage, 0);
+ 				} else {
+ 					set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+ 					spin_unlock_irqrestore(&bitmap->lock, flags);
+@@ -998,7 +998,7 @@ int bitmap_daemon_work(struct bitmap *bitmap)
+ 		if (get_page_attr(bitmap, lastpage) &BITMAP_PAGE_NEEDWRITE) {
+ 			clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+ 			spin_unlock_irqrestore(&bitmap->lock, flags);
+-			write_page(lastpage, 0);
++			err = write_page(lastpage, 0);
+ 		} else {
+ 			set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+ 			spin_unlock_irqrestore(&bitmap->lock, flags);
+@@ -1375,7 +1375,8 @@ int bitmap_setallbits(struct bitmap *bitmap)
+ 		spin_unlock_irqrestore(&bitmap->lock, flags);
+ 		memset(kmap(page), 0xff, PAGE_SIZE);
+ 		kunmap(page);
+-		write_page(page, 0);
++		if (write_page(page, 0))
++			return 1;
+ 	}
+ 
+ 	return 0;

commit a2cff26ad18a8794722fb0d3c019d93e14fce3f1
+Author: NeilBrown 
+Date:   Tue Jun 21 17:17:20 2005 -0700
+
+    [PATCH] md: improve debug-printing of bitmap superblock.
+    
+    - report sync_size properly  - need /2 to convert sectors to KB
+    - move everything over 2 spaces to allow proper spelling of
+      "events cleared".
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
+index dd84e15fcaea..f197db2ef92d 100644
+--- a/drivers/md/bitmap.c
++++ b/drivers/md/bitmap.c
+@@ -363,22 +363,22 @@ void bitmap_print_sb(struct bitmap *bitmap)
+ 		return;
+ 	sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+ 	printk(KERN_DEBUG "%s: bitmap file superblock:\n", bmname(bitmap));
+-	printk(KERN_DEBUG "       magic: %08x\n", le32_to_cpu(sb->magic));
+-	printk(KERN_DEBUG "     version: %d\n", le32_to_cpu(sb->version));
+-	printk(KERN_DEBUG "        uuid: %08x.%08x.%08x.%08x\n",
++	printk(KERN_DEBUG "         magic: %08x\n", le32_to_cpu(sb->magic));
++	printk(KERN_DEBUG "       version: %d\n", le32_to_cpu(sb->version));
++	printk(KERN_DEBUG "          uuid: %08x.%08x.%08x.%08x\n",
+ 					*(__u32 *)(sb->uuid+0),
+ 					*(__u32 *)(sb->uuid+4),
+ 					*(__u32 *)(sb->uuid+8),
+ 					*(__u32 *)(sb->uuid+12));
+-	printk(KERN_DEBUG "      events: %llu\n",
++	printk(KERN_DEBUG "        events: %llu\n",
+ 			(unsigned long long) le64_to_cpu(sb->events));
+-	printk(KERN_DEBUG "events_clred: %llu\n",
++	printk(KERN_DEBUG "events cleared: %llu\n",
+ 			(unsigned long long) le64_to_cpu(sb->events_cleared));
+-	printk(KERN_DEBUG "       state: %08x\n", le32_to_cpu(sb->state));
+-	printk(KERN_DEBUG "   chunksize: %d B\n", le32_to_cpu(sb->chunksize));
+-	printk(KERN_DEBUG "daemon sleep: %ds\n", le32_to_cpu(sb->daemon_sleep));
+-	printk(KERN_DEBUG "   sync size: %llu KB\n",
+-			(unsigned long long)le64_to_cpu(sb->sync_size));
++	printk(KERN_DEBUG "         state: %08x\n", le32_to_cpu(sb->state));
++	printk(KERN_DEBUG "     chunksize: %d B\n", le32_to_cpu(sb->chunksize));
++	printk(KERN_DEBUG "  daemon sleep: %ds\n", le32_to_cpu(sb->daemon_sleep));
++	printk(KERN_DEBUG "     sync size: %llu KB\n",
++			(unsigned long long)le64_to_cpu(sb->sync_size)/2);
+ 	kunmap(bitmap->sb_page);
+ }
+ 

commit cdbb4cc2e5c30895709163d8544057db21ee23e0
+Author: NeilBrown 
+Date:   Tue Jun 21 17:17:18 2005 -0700
+
+    [PATCH] md: make sure md bitmap is cleared on a clean start.
+    
+    As the array-wide clean bit (in the superblock) is set more agressively than
+    the bits in the bitmap are cleared, it is possible to have an array which is
+    clean despite there being bits set in the bitmap.
+    
+    These bits will currently never get cleared, as they can only be cleared by a
+    resync pass, which never happens.
+    
+    No, when reading bits from disk, be aware of whether the whole array is known
+    to be in sync, and act accordingly.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
+index 62fac2b38000..275a2aa79b79 100644
+--- a/drivers/md/bitmap.c
++++ b/drivers/md/bitmap.c
+@@ -747,7 +747,7 @@ int bitmap_unplug(struct bitmap *bitmap)
+ }
+ 
+ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
+-	unsigned long sectors, int set);
++	unsigned long sectors, int in_sync);
+ /* * bitmap_init_from_disk -- called at bitmap_create time to initialize
+  * the in-memory bitmap from the on-disk bitmap -- also, sets up the
+  * memory mapping of the bitmap file
+@@ -756,7 +756,7 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
+  *   previously kicked from the array, we mark all the bits as
+  *   1's in order to cause a full resync.
+  */
+-static int bitmap_init_from_disk(struct bitmap *bitmap)
++static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
+ {
+ 	unsigned long i, chunks, index, oldindex, bit;
+ 	struct page *page = NULL, *oldpage = NULL;
+@@ -782,7 +782,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap)
+ 
+ 	bytes = (chunks + 7) / 8;
+ 
+-	num_pages = (bytes + sizeof(bitmap_super_t) + PAGE_SIZE - 1) / PAGE_SIZE + 1;
++	num_pages = (bytes + sizeof(bitmap_super_t) + PAGE_SIZE - 1) / PAGE_SIZE;
+ 
+ 	if (i_size_read(file->f_mapping->host) < bytes + sizeof(bitmap_super_t)) {
+ 		printk(KERN_INFO "%s: bitmap file too short %lu < %lu\n",
+@@ -854,14 +854,9 @@ static int bitmap_init_from_disk(struct bitmap *bitmap)
+ 		if (test_bit(bit, page_address(page))) {
+ 			/* if the disk bit is set, set the memory bit */
+ 			bitmap_set_memory_bits(bitmap,
+-					i << CHUNK_BLOCK_SHIFT(bitmap), 1, 1);
++					i << CHUNK_BLOCK_SHIFT(bitmap), 1, in_sync);
+ 			bit_cnt++;
+ 		}
+-#if 0
+-		else
+-			bitmap_set_memory_bits(bitmap,
+-				       i << CHUNK_BLOCK_SHIFT(bitmap), 1, 0);
+-#endif
+ 	}
+ 
+  	/* everything went OK */
+@@ -1331,10 +1326,10 @@ void bitmap_close_sync(struct bitmap *bitmap)
+ }
+ 
+ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
+-				   unsigned long sectors, int set)
++				   unsigned long sectors, int in_sync)
+ {
+ 	/* For each chunk covered by any of these sectors, set the
+-	 * resync needed bit, and the counter to 1.  They should all
++	 * counter to 1 and set resync_needed unless in_sync.  They should all
+ 	 * be 0 at this point
+ 	 */
+ 	while (sectors) {
+@@ -1346,10 +1341,12 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
+ 			spin_unlock_irq(&bitmap->lock);
+ 			return;
+ 		}
+-		if (set && !NEEDED(*bmc)) {
+-			BUG_ON(*bmc);
+-			*bmc = NEEDED_MASK | 1;
++		if (! *bmc) {
++			struct page *page;
++			*bmc = 1 | (in_sync? 0 : NEEDED_MASK);
+ 			bitmap_count_page(bitmap, offset, 1);
++			page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
++			set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
+ 		}
+ 		spin_unlock_irq(&bitmap->lock);
+ 		if (sectors > secs)
+@@ -1489,7 +1486,7 @@ int bitmap_create(mddev_t *mddev)
+ 
+ 	/* now that we have some pages available, initialize the in-memory
+ 	 * bitmap from the on-disk bitmap */
+-	err = bitmap_init_from_disk(bitmap);
++	err = bitmap_init_from_disk(bitmap, mddev->recovery_cp == MaxSector);
+ 	if (err)
+ 		return err;
+ 

commit bc7f77de2cd81718dd789a2cfe68a7cf1b48f016
+Author: NeilBrown 
+Date:   Tue Jun 21 17:17:17 2005 -0700
+
+    [PATCH] md: minor code rearrangement in bitmap_init_from_disk
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
+index c43fd031aafe..62fac2b38000 100644
+--- a/drivers/md/bitmap.c
++++ b/drivers/md/bitmap.c
+@@ -781,7 +781,9 @@ static int bitmap_init_from_disk(struct bitmap *bitmap)
+ 			"recovery\n", bmname(bitmap));
+ 
+ 	bytes = (chunks + 7) / 8;
+-	num_pages = (bytes + PAGE_SIZE - 1) / PAGE_SIZE;
++
++	num_pages = (bytes + sizeof(bitmap_super_t) + PAGE_SIZE - 1) / PAGE_SIZE + 1;
++
+ 	if (i_size_read(file->f_mapping->host) < bytes + sizeof(bitmap_super_t)) {
+ 		printk(KERN_INFO "%s: bitmap file too short %lu < %lu\n",
+ 			bmname(bitmap),
+@@ -789,18 +791,16 @@ static int bitmap_init_from_disk(struct bitmap *bitmap)
+ 			bytes + sizeof(bitmap_super_t));
+ 		goto out;
+ 	}
+-	num_pages++;
++
++	ret = -ENOMEM;
++
+ 	bitmap->filemap = kmalloc(sizeof(struct page *) * num_pages, GFP_KERNEL);
+-	if (!bitmap->filemap) {
+-		ret = -ENOMEM;
++	if (!bitmap->filemap)
+ 		goto out;
+-	}
+ 
+ 	bitmap->filemap_attr = kmalloc(sizeof(long) * num_pages, GFP_KERNEL);
+-	if (!bitmap->filemap_attr) {
+-		ret = -ENOMEM;
++	if (!bitmap->filemap_attr)
+ 		goto out;
+-	}
+ 
+ 	memset(bitmap->filemap_attr, 0, sizeof(long) * num_pages);
+ 

commit d80a138c013f81c1b9383c83983934e34e380a2d
+Author: NeilBrown 
+Date:   Tue Jun 21 17:17:17 2005 -0700
+
+    [PATCH] md: print correct pid for newly created bitmap-writeback-daemon.
+    
+    The debugging message printed the wrong pid, which didn't help remove bugs....
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
+index b43bdb2c7e64..c43fd031aafe 100644
+--- a/drivers/md/bitmap.c
++++ b/drivers/md/bitmap.c
+@@ -1112,7 +1112,7 @@ static int bitmap_start_daemon(struct bitmap *bitmap, mdk_thread_t **ptr,
+ 	md_wakeup_thread(daemon); /* start it running */
+ 
+ 	PRINTK("%s: %s daemon (pid %d) started...\n",
+-		bmname(bitmap), name, bitmap->daemon->tsk->pid);
++		bmname(bitmap), name, daemon->tsk->pid);
+ out_unlock:
+ 	spin_unlock_irqrestore(&bitmap->lock, flags);
+ 	return 0;

commit 5f40402d96cb21df912e5bbb3fffa5e1afc81e98
+Author: NeilBrown 
+Date:   Tue Jun 21 17:17:16 2005 -0700
+
+    [PATCH] md: call bitmap_daemon_work regularly
+    
+    bitmap_daemon_work clears bits in the bitmap for blocks that haven't been
+    written to for a while.  It needs to be called regularly to make sure the
+    bitmap doesn't endup full of ones ....  but it wasn't.
+    
+    So call it from the increasingly-inaptly-named md_check_recovery
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 52fafb820f74..b02f8d1d77e7 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -3635,7 +3635,8 @@ void md_check_recovery(mddev_t *mddev)
+ 	struct list_head *rtmp;
+ 
+ 
+-	dprintk(KERN_INFO "md: recovery thread got woken up ...\n");
++	if (mddev->bitmap)
++		bitmap_daemon_work(mddev->bitmap);
+ 
+ 	if (mddev->ro)
+ 		return;

commit 78d742d876bdf7263d0d966fbe9593559fd904a7
+Author: NeilBrown 
+Date:   Tue Jun 21 17:17:15 2005 -0700
+
+    [PATCH] md: a couple of tidyups relating to the bitmap file.
+    
+    1/ When init from disk, it is a BUG if there is nowhere
+       to init from,
+    2/ use seq_path to print path in /proc/mdstat
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
+index 34ffc133db05..b43bdb2c7e64 100644
+--- a/drivers/md/bitmap.c
++++ b/drivers/md/bitmap.c
+@@ -769,13 +769,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap)
+ 	chunks = bitmap->chunks;
+ 	file = bitmap->file;
+ 
+-	if (!file) { /* no file, dirty all the in-memory bits */
+-		printk(KERN_INFO "%s: no bitmap file, doing full recovery\n",
+-			bmname(bitmap));
+-		bitmap_set_memory_bits(bitmap, 0,
+-				       chunks << CHUNK_BLOCK_SHIFT(bitmap), 1);
+-		return 0;
+-	}
++	BUG_ON(!file);
+ 
+ #if INJECT_FAULTS_3
+ 	outofdate = 1;
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index c402f6cc7047..52fafb820f74 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -3213,10 +3213,8 @@ static int md_seq_show(struct seq_file *seq, void *v)
+ 			seq_printf(seq, "\n       ");
+ 
+ 		if ((bitmap = mddev->bitmap)) {
+-			char *buf, *path;
+ 			unsigned long chunk_kb;
+ 			unsigned long flags;
+-			buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ 			spin_lock_irqsave(&bitmap->lock, flags);
+ 			chunk_kb = bitmap->chunksize >> 10;
+ 			seq_printf(seq, "bitmap: %lu/%lu pages [%luKB], "
+@@ -3227,13 +3225,14 @@ static int md_seq_show(struct seq_file *seq, void *v)
+ 					<< (PAGE_SHIFT - 10),
+ 				chunk_kb ? chunk_kb : bitmap->chunksize,
+ 				chunk_kb ? "KB" : "B");
+-			if (bitmap->file && buf) {
+-				path = file_path(bitmap->file, buf, PAGE_SIZE);
+-				seq_printf(seq, ", file: %s", path ? path : "");
++			if (bitmap->file) {
++				seq_printf(seq, ", file: ");
++				seq_path(seq, bitmap->file->f_vfsmnt,
++					 bitmap->file->f_dentry," \t\n");
+ 			}
++
+ 			seq_printf(seq, "\n");
+ 			spin_unlock_irqrestore(&bitmap->lock, flags);
+-			kfree(buf);
+ 		}
+ 
+ 		seq_printf(seq, "\n");

commit 32a7627cf3a35396a8e834faf34e38ae9f3b1309
+Author: NeilBrown 
+Date:   Tue Jun 21 17:17:14 2005 -0700
+
+    [PATCH] md: optimised resync using Bitmap based intent logging
+    
+    With this patch, the intent to write to some block in the array can be logged
+    to a bitmap file.  Each bit represents some number of sectors and is set
+    before any update happens, and only cleared when all writes relating to all
+    sectors are complete.
+    
+    After an unclean shutdown, information in this bitmap can be used to optimise
+    resync - only sectors which could be out-of-sync need to be updated.
+    
+    Also if a drive is removed and then added back into an array, the recovery can
+    make use of the bitmap to optimise reconstruction.  This is not implemented in
+    this patch.
+    
+    Currently the bitmap is stored in a file which must (obviously) be stored on a
+    separate device.
+    
+    The patch only provided infrastructure.  It does not update any personalities
+    to bitmap intent logging.
+    
+    Md arrays can still be used with no bitmap file.  This patch has minimal
+    impact on such arrays.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/Makefile b/drivers/md/Makefile
+index 90de9c146a5f..d3efedf6a6ad 100644
+--- a/drivers/md/Makefile
++++ b/drivers/md/Makefile
+@@ -7,6 +7,7 @@ dm-mod-objs	:= dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \
+ dm-multipath-objs := dm-hw-handler.o dm-path-selector.o dm-mpath.o
+ dm-snapshot-objs := dm-snap.o dm-exception-store.o
+ dm-mirror-objs	:= dm-log.o dm-raid1.o
++md-mod-objs     := md.o bitmap.o
+ raid6-objs	:= raid6main.o raid6algos.o raid6recov.o raid6tables.o \
+ 		   raid6int1.o raid6int2.o raid6int4.o \
+ 		   raid6int8.o raid6int16.o raid6int32.o \
+@@ -28,7 +29,7 @@ obj-$(CONFIG_MD_RAID5)		+= raid5.o xor.o
+ obj-$(CONFIG_MD_RAID6)		+= raid6.o xor.o
+ obj-$(CONFIG_MD_MULTIPATH)	+= multipath.o
+ obj-$(CONFIG_MD_FAULTY)		+= faulty.o
+-obj-$(CONFIG_BLK_DEV_MD)	+= md.o
++obj-$(CONFIG_BLK_DEV_MD)	+= md-mod.o
+ obj-$(CONFIG_BLK_DEV_DM)	+= dm-mod.o
+ obj-$(CONFIG_DM_CRYPT)		+= dm-crypt.o
+ obj-$(CONFIG_DM_MULTIPATH)	+= dm-multipath.o dm-round-robin.o
+diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
+new file mode 100644
+index 000000000000..34ffc133db05
+--- /dev/null
++++ b/drivers/md/bitmap.c
+@@ -0,0 +1,1519 @@
++/*
++ * bitmap.c two-level bitmap (C) Peter T. Breuer (ptb@ot.uc3m.es) 2003
++ *
++ * bitmap_create  - sets up the bitmap structure
++ * bitmap_destroy - destroys the bitmap structure
++ *
++ * additions, Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, Inc.:
++ * - added disk storage for bitmap
++ * - changes to allow various bitmap chunk sizes
++ * - added bitmap daemon (to asynchronously clear bitmap bits from disk)
++ */
++
++/*
++ * Still to do:
++ *
++ * flush after percent set rather than just time based. (maybe both).
++ * wait if count gets too high, wake when it drops to half.
++ * allow bitmap to be mirrored with superblock (before or after...)
++ * allow hot-add to re-instate a current device.
++ * allow hot-add of bitmap after quiessing device
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++/* debug macros */
++
++#define DEBUG 0
++
++#if DEBUG
++/* these are for debugging purposes only! */
++
++/* define one and only one of these */
++#define INJECT_FAULTS_1 0 /* cause bitmap_alloc_page to fail always */
++#define INJECT_FAULTS_2 0 /* cause bitmap file to be kicked when first bit set*/
++#define INJECT_FAULTS_3 0 /* treat bitmap file as kicked at init time */
++#define INJECT_FAULTS_4 0 /* undef */
++#define INJECT_FAULTS_5 0 /* undef */
++#define INJECT_FAULTS_6 0
++
++/* if these are defined, the driver will fail! debug only */
++#define INJECT_FATAL_FAULT_1 0 /* fail kmalloc, causing bitmap_create to fail */
++#define INJECT_FATAL_FAULT_2 0 /* undef */
++#define INJECT_FATAL_FAULT_3 0 /* undef */
++#endif
++
++//#define DPRINTK PRINTK /* set this NULL to avoid verbose debug output */
++#define DPRINTK(x...) do { } while(0)
++
++#ifndef PRINTK
++#  if DEBUG > 0
++#    define PRINTK(x...) printk(KERN_DEBUG x)
++#  else
++#    define PRINTK(x...)
++#  endif
++#endif
++
++static inline char * bmname(struct bitmap *bitmap)
++{
++	return bitmap->mddev ? mdname(bitmap->mddev) : "mdX";
++}
++
++
++/*
++ * test if the bitmap is active
++ */
++int bitmap_active(struct bitmap *bitmap)
++{
++	unsigned long flags;
++	int res = 0;
++
++	if (!bitmap)
++		return res;
++	spin_lock_irqsave(&bitmap->lock, flags);
++	res = bitmap->flags & BITMAP_ACTIVE;
++	spin_unlock_irqrestore(&bitmap->lock, flags);
++	return res;
++}
++
++#define WRITE_POOL_SIZE 256
++/* mempool for queueing pending writes on the bitmap file */
++static void *write_pool_alloc(unsigned int gfp_flags, void *data)
++{
++	return kmalloc(sizeof(struct page_list), gfp_flags);
++}
++
++static void write_pool_free(void *ptr, void *data)
++{
++	kfree(ptr);
++}
++
++/*
++ * just a placeholder - calls kmalloc for bitmap pages
++ */
++static unsigned char *bitmap_alloc_page(struct bitmap *bitmap)
++{
++	unsigned char *page;
++
++#if INJECT_FAULTS_1
++	page = NULL;
++#else
++	page = kmalloc(PAGE_SIZE, GFP_NOIO);
++#endif
++	if (!page)
++		printk("%s: bitmap_alloc_page FAILED\n", bmname(bitmap));
++	else
++		printk("%s: bitmap_alloc_page: allocated page at %p\n",
++			bmname(bitmap), page);
++	return page;
++}
++
++/*
++ * for now just a placeholder -- just calls kfree for bitmap pages
++ */
++static void bitmap_free_page(struct bitmap *bitmap, unsigned char *page)
++{
++	PRINTK("%s: bitmap_free_page: free page %p\n", bmname(bitmap), page);
++	kfree(page);
++}
++
++/*
++ * check a page and, if necessary, allocate it (or hijack it if the alloc fails)
++ *
++ * 1) check to see if this page is allocated, if it's not then try to alloc
++ * 2) if the alloc fails, set the page's hijacked flag so we'll use the
++ *    page pointer directly as a counter
++ *
++ * if we find our page, we increment the page's refcount so that it stays
++ * allocated while we're using it
++ */
++static int bitmap_checkpage(struct bitmap *bitmap, unsigned long page, int create)
++{
++	unsigned char *mappage;
++
++	if (page >= bitmap->pages) {
++		printk(KERN_ALERT
++			"%s: invalid bitmap page request: %lu (> %lu)\n",
++			bmname(bitmap), page, bitmap->pages-1);
++		return -EINVAL;
++	}
++
++
++	if (bitmap->bp[page].hijacked) /* it's hijacked, don't try to alloc */
++		return 0;
++
++	if (bitmap->bp[page].map) /* page is already allocated, just return */
++		return 0;
++
++	if (!create)
++		return -ENOENT;
++
++	spin_unlock_irq(&bitmap->lock);
++
++	/* this page has not been allocated yet */
++
++	if ((mappage = bitmap_alloc_page(bitmap)) == NULL) {
++		PRINTK("%s: bitmap map page allocation failed, hijacking\n",
++			bmname(bitmap));
++		/* failed - set the hijacked flag so that we can use the
++		 * pointer as a counter */
++		spin_lock_irq(&bitmap->lock);
++		if (!bitmap->bp[page].map)
++			bitmap->bp[page].hijacked = 1;
++		goto out;
++	}
++
++	/* got a page */
++
++	spin_lock_irq(&bitmap->lock);
++
++	/* recheck the page */
++
++	if (bitmap->bp[page].map || bitmap->bp[page].hijacked) {
++		/* somebody beat us to getting the page */
++		bitmap_free_page(bitmap, mappage);
++		return 0;
++	}
++
++	/* no page was in place and we have one, so install it */
++
++	memset(mappage, 0, PAGE_SIZE);
++	bitmap->bp[page].map = mappage;
++	bitmap->missing_pages--;
++out:
++	return 0;
++}
++
++
++/* if page is completely empty, put it back on the free list, or dealloc it */
++/* if page was hijacked, unmark the flag so it might get alloced next time */
++/* Note: lock should be held when calling this */
++static inline void bitmap_checkfree(struct bitmap *bitmap, unsigned long page)
++{
++	char *ptr;
++
++	if (bitmap->bp[page].count) /* page is still busy */
++		return;
++
++	/* page is no longer in use, it can be released */
++
++	if (bitmap->bp[page].hijacked) { /* page was hijacked, undo this now */
++		bitmap->bp[page].hijacked = 0;
++		bitmap->bp[page].map = NULL;
++		return;
++	}
++
++	/* normal case, free the page */
++
++#if 0
++/* actually ... let's not.  We will probably need the page again exactly when
++ * memory is tight and we are flusing to disk
++ */
++	return;
++#else
++	ptr = bitmap->bp[page].map;
++	bitmap->bp[page].map = NULL;
++	bitmap->missing_pages++;
++	bitmap_free_page(bitmap, ptr);
++	return;
++#endif
++}
++
++
++/*
++ * bitmap file handling - read and write the bitmap file and its superblock
++ */
++
++/* copy the pathname of a file to a buffer */
++char *file_path(struct file *file, char *buf, int count)
++{
++	struct dentry *d;
++	struct vfsmount *v;
++
++	if (!buf)
++		return NULL;
++
++	d = file->f_dentry;
++	v = file->f_vfsmnt;
++
++	buf = d_path(d, v, buf, count);
++
++	return IS_ERR(buf) ? NULL : buf;
++}
++
++/*
++ * basic page I/O operations
++ */
++
++/*
++ * write out a page
++ */
++static int write_page(struct page *page, int wait)
++{
++	int ret = -ENOMEM;
++
++	lock_page(page);
++
++	if (page->mapping == NULL)
++		goto unlock_out;
++	else if (i_size_read(page->mapping->host) < page->index << PAGE_SHIFT) {
++		ret = -ENOENT;
++		goto unlock_out;
++	}
++
++	ret = page->mapping->a_ops->prepare_write(NULL, page, 0, PAGE_SIZE);
++	if (!ret)
++		ret = page->mapping->a_ops->commit_write(NULL, page, 0,
++			PAGE_SIZE);
++	if (ret) {
++unlock_out:
++		unlock_page(page);
++		return ret;
++	}
++
++	set_page_dirty(page); /* force it to be written out */
++	return write_one_page(page, wait);
++}
++
++/* read a page from a file, pinning it into cache, and return bytes_read */
++static struct page *read_page(struct file *file, unsigned long index,
++					unsigned long *bytes_read)
++{
++	struct inode *inode = file->f_mapping->host;
++	struct page *page = NULL;
++	loff_t isize = i_size_read(inode);
++	unsigned long end_index = isize >> PAGE_CACHE_SHIFT;
++
++	PRINTK("read bitmap file (%dB @ %Lu)\n", (int)PAGE_CACHE_SIZE,
++			(unsigned long long)index << PAGE_CACHE_SHIFT);
++
++	page = read_cache_page(inode->i_mapping, index,
++			(filler_t *)inode->i_mapping->a_ops->readpage, file);
++	if (IS_ERR(page))
++		goto out;
++	wait_on_page_locked(page);
++	if (!PageUptodate(page) || PageError(page)) {
++		page_cache_release(page);
++		page = ERR_PTR(-EIO);
++		goto out;
++	}
++
++	if (index > end_index) /* we have read beyond EOF */
++		*bytes_read = 0;
++	else if (index == end_index) /* possible short read */
++		*bytes_read = isize & ~PAGE_CACHE_MASK;
++	else
++		*bytes_read = PAGE_CACHE_SIZE; /* got a full page */
++out:
++	if (IS_ERR(page))
++		printk(KERN_ALERT "md: bitmap read error: (%dB @ %Lu): %ld\n",
++			(int)PAGE_CACHE_SIZE,
++			(unsigned long long)index << PAGE_CACHE_SHIFT,
++			PTR_ERR(page));
++	return page;
++}
++
++/*
++ * bitmap file superblock operations
++ */
++
++/* update the event counter and sync the superblock to disk */
++int bitmap_update_sb(struct bitmap *bitmap)
++{
++	bitmap_super_t *sb;
++	unsigned long flags;
++
++	if (!bitmap || !bitmap->mddev) /* no bitmap for this array */
++		return 0;
++	spin_lock_irqsave(&bitmap->lock, flags);
++	if (!bitmap->sb_page) { /* no superblock */
++		spin_unlock_irqrestore(&bitmap->lock, flags);
++		return 0;
++	}
++	page_cache_get(bitmap->sb_page);
++	spin_unlock_irqrestore(&bitmap->lock, flags);
++	sb = (bitmap_super_t *)kmap(bitmap->sb_page);
++	sb->events = cpu_to_le64(bitmap->mddev->events);
++	if (!bitmap->mddev->degraded)
++		sb->events_cleared = cpu_to_le64(bitmap->mddev->events);
++	kunmap(bitmap->sb_page);
++	write_page(bitmap->sb_page, 0);
++	return 0;
++}
++
++/* print out the bitmap file superblock */
++void bitmap_print_sb(struct bitmap *bitmap)
++{
++	bitmap_super_t *sb;
++
++	if (!bitmap || !bitmap->sb_page)
++		return;
++	sb = (bitmap_super_t *)kmap(bitmap->sb_page);
++	printk(KERN_DEBUG "%s: bitmap file superblock:\n", bmname(bitmap));
++	printk(KERN_DEBUG "       magic: %08x\n", le32_to_cpu(sb->magic));
++	printk(KERN_DEBUG "     version: %d\n", le32_to_cpu(sb->version));
++	printk(KERN_DEBUG "        uuid: %08x.%08x.%08x.%08x\n",
++					*(__u32 *)(sb->uuid+0),
++					*(__u32 *)(sb->uuid+4),
++					*(__u32 *)(sb->uuid+8),
++					*(__u32 *)(sb->uuid+12));
++	printk(KERN_DEBUG "      events: %llu\n",
++			(unsigned long long) le64_to_cpu(sb->events));
++	printk(KERN_DEBUG "events_clred: %llu\n",
++			(unsigned long long) le64_to_cpu(sb->events_cleared));
++	printk(KERN_DEBUG "       state: %08x\n", le32_to_cpu(sb->state));
++	printk(KERN_DEBUG "   chunksize: %d B\n", le32_to_cpu(sb->chunksize));
++	printk(KERN_DEBUG "daemon sleep: %ds\n", le32_to_cpu(sb->daemon_sleep));
++	printk(KERN_DEBUG "   sync size: %llu KB\n", le64_to_cpu(sb->sync_size));
++	kunmap(bitmap->sb_page);
++}
++
++/* read the superblock from the bitmap file and initialize some bitmap fields */
++static int bitmap_read_sb(struct bitmap *bitmap)
++{
++	char *reason = NULL;
++	bitmap_super_t *sb;
++	unsigned long chunksize, daemon_sleep;
++	unsigned long bytes_read;
++	unsigned long long events;
++	int err = -EINVAL;
++
++	/* page 0 is the superblock, read it... */
++	bitmap->sb_page = read_page(bitmap->file, 0, &bytes_read);
++	if (IS_ERR(bitmap->sb_page)) {
++		err = PTR_ERR(bitmap->sb_page);
++		bitmap->sb_page = NULL;
++		return err;
++	}
++
++	sb = (bitmap_super_t *)kmap(bitmap->sb_page);
++
++	if (bytes_read < sizeof(*sb)) { /* short read */
++		printk(KERN_INFO "%s: bitmap file superblock truncated\n",
++			bmname(bitmap));
++		err = -ENOSPC;
++		goto out;
++	}
++
++	chunksize = le32_to_cpu(sb->chunksize);
++	daemon_sleep = le32_to_cpu(sb->daemon_sleep);
++
++	/* verify that the bitmap-specific fields are valid */
++	if (sb->magic != cpu_to_le32(BITMAP_MAGIC))
++		reason = "bad magic";
++	else if (sb->version != cpu_to_le32(BITMAP_MAJOR))
++		reason = "unrecognized superblock version";
++	else if (chunksize < 512 || chunksize > (1024 * 1024 * 4))
++		reason = "bitmap chunksize out of range (512B - 4MB)";
++	else if ((1 << ffz(~chunksize)) != chunksize)
++		reason = "bitmap chunksize not a power of 2";
++	else if (daemon_sleep < 1 || daemon_sleep > 15)
++		reason = "daemon sleep period out of range";
++	if (reason) {
++		printk(KERN_INFO "%s: invalid bitmap file superblock: %s\n",
++			bmname(bitmap), reason);
++		goto out;
++	}
++
++	/* keep the array size field of the bitmap superblock up to date */
++	sb->sync_size = cpu_to_le64(bitmap->mddev->resync_max_sectors);
++
++	if (!bitmap->mddev->persistent)
++		goto success;
++
++	/*
++	 * if we have a persistent array superblock, compare the
++	 * bitmap's UUID and event counter to the mddev's
++	 */
++	if (memcmp(sb->uuid, bitmap->mddev->uuid, 16)) {
++		printk(KERN_INFO "%s: bitmap superblock UUID mismatch\n",
++			bmname(bitmap));
++		goto out;
++	}
++	events = le64_to_cpu(sb->events);
++	if (events < bitmap->mddev->events) {
++		printk(KERN_INFO "%s: bitmap file is out of date (%llu < %llu) "
++			"-- forcing full recovery\n", bmname(bitmap), events,
++			(unsigned long long) bitmap->mddev->events);
++		sb->state |= BITMAP_STALE;
++	}
++success:
++	/* assign fields using values from superblock */
++	bitmap->chunksize = chunksize;
++	bitmap->daemon_sleep = daemon_sleep;
++	bitmap->flags |= sb->state;
++	bitmap->events_cleared = le64_to_cpu(sb->events_cleared);
++	err = 0;
++out:
++	kunmap(bitmap->sb_page);
++	if (err)
++		bitmap_print_sb(bitmap);
++	return err;
++}
++
++enum bitmap_mask_op {
++	MASK_SET,
++	MASK_UNSET
++};
++
++/* record the state of the bitmap in the superblock */
++static void bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
++				enum bitmap_mask_op op)
++{
++	bitmap_super_t *sb;
++	unsigned long flags;
++
++	spin_lock_irqsave(&bitmap->lock, flags);
++	if (!bitmap || !bitmap->sb_page) { /* can't set the state */
++		spin_unlock_irqrestore(&bitmap->lock, flags);
++		return;
++	}
++	page_cache_get(bitmap->sb_page);
++	spin_unlock_irqrestore(&bitmap->lock, flags);
++	sb = (bitmap_super_t *)kmap(bitmap->sb_page);
++	switch (op) {
++		case MASK_SET: sb->state |= bits;
++				break;
++		case MASK_UNSET: sb->state &= ~bits;
++				break;
++		default: BUG();
++	}
++	kunmap(bitmap->sb_page);
++	page_cache_release(bitmap->sb_page);
++}
++
++/*
++ * general bitmap file operations
++ */
++
++/* calculate the index of the page that contains this bit */
++static inline unsigned long file_page_index(unsigned long chunk)
++{
++	return CHUNK_BIT_OFFSET(chunk) >> PAGE_BIT_SHIFT;
++}
++
++/* calculate the (bit) offset of this bit within a page */
++static inline unsigned long file_page_offset(unsigned long chunk)
++{
++	return CHUNK_BIT_OFFSET(chunk) & (PAGE_BITS - 1);
++}
++
++/*
++ * return a pointer to the page in the filemap that contains the given bit
++ *
++ * this lookup is complicated by the fact that the bitmap sb might be exactly
++ * 1 page (e.g., x86) or less than 1 page -- so the bitmap might start on page
++ * 0 or page 1
++ */
++static inline struct page *filemap_get_page(struct bitmap *bitmap,
++					unsigned long chunk)
++{
++	return bitmap->filemap[file_page_index(chunk) - file_page_index(0)];
++}
++
++
++static void bitmap_file_unmap(struct bitmap *bitmap)
++{
++	struct page **map, *sb_page;
++	unsigned long *attr;
++	int pages;
++	unsigned long flags;
++
++	spin_lock_irqsave(&bitmap->lock, flags);
++	map = bitmap->filemap;
++	bitmap->filemap = NULL;
++	attr = bitmap->filemap_attr;
++	bitmap->filemap_attr = NULL;
++	pages = bitmap->file_pages;
++	bitmap->file_pages = 0;
++	sb_page = bitmap->sb_page;
++	bitmap->sb_page = NULL;
++	spin_unlock_irqrestore(&bitmap->lock, flags);
++
++	while (pages--)
++		if (map[pages]->index != 0) /* 0 is sb_page, release it below */
++			page_cache_release(map[pages]);
++	kfree(map);
++	kfree(attr);
++
++	if (sb_page)
++		page_cache_release(sb_page);
++}
++
++static void bitmap_stop_daemons(struct bitmap *bitmap);
++
++/* dequeue the next item in a page list -- don't call from irq context */
++static struct page_list *dequeue_page(struct bitmap *bitmap,
++					struct list_head *head)
++{
++	struct page_list *item = NULL;
++
++	spin_lock(&bitmap->write_lock);
++	if (list_empty(head))
++		goto out;
++	item = list_entry(head->prev, struct page_list, list);
++	list_del(head->prev);
++out:
++	spin_unlock(&bitmap->write_lock);
++	return item;
++}
++
++static void drain_write_queues(struct bitmap *bitmap)
++{
++	struct list_head *queues[] = { 	&bitmap->complete_pages, NULL };
++	struct list_head *head;
++	struct page_list *item;
++	int i;
++
++	for (i = 0; queues[i]; i++) {
++		head = queues[i];
++		while ((item = dequeue_page(bitmap, head))) {
++			page_cache_release(item->page);
++			mempool_free(item, bitmap->write_pool);
++		}
++	}
++
++	spin_lock(&bitmap->write_lock);
++	bitmap->writes_pending = 0; /* make sure waiters continue */
++	wake_up(&bitmap->write_wait);
++	spin_unlock(&bitmap->write_lock);
++}
++
++static void bitmap_file_put(struct bitmap *bitmap)
++{
++	struct file *file;
++	struct inode *inode;
++	unsigned long flags;
++
++	spin_lock_irqsave(&bitmap->lock, flags);
++	file = bitmap->file;
++	bitmap->file = NULL;
++	spin_unlock_irqrestore(&bitmap->lock, flags);
++
++	bitmap_stop_daemons(bitmap);
++
++	drain_write_queues(bitmap);
++
++	bitmap_file_unmap(bitmap);
++
++	if (file) {
++		inode = file->f_mapping->host;
++		spin_lock(&inode->i_lock);
++		atomic_set(&inode->i_writecount, 1); /* allow writes again */
++		spin_unlock(&inode->i_lock);
++		fput(file);
++	}
++}
++
++
++/*
++ * bitmap_file_kick - if an error occurs while manipulating the bitmap file
++ * then it is no longer reliable, so we stop using it and we mark the file
++ * as failed in the superblock
++ */
++static void bitmap_file_kick(struct bitmap *bitmap)
++{
++	char *path, *ptr = NULL;
++
++	bitmap_mask_state(bitmap, BITMAP_STALE, MASK_SET);
++	bitmap_update_sb(bitmap);
++
++	path = kmalloc(PAGE_SIZE, GFP_KERNEL);
++	if (path)
++		ptr = file_path(bitmap->file, path, PAGE_SIZE);
++
++	printk(KERN_ALERT "%s: kicking failed bitmap file %s from array!\n",
++		bmname(bitmap), ptr ? ptr : "");
++
++	kfree(path);
++
++	bitmap_file_put(bitmap);
++
++	return;
++}
++
++enum bitmap_page_attr {
++	BITMAP_PAGE_DIRTY = 1, // there are set bits that need to be synced
++	BITMAP_PAGE_CLEAN = 2, // there are bits that might need to be cleared
++	BITMAP_PAGE_NEEDWRITE=4, // there are cleared bits that need to be synced
++};
++
++static inline void set_page_attr(struct bitmap *bitmap, struct page *page,
++				enum bitmap_page_attr attr)
++{
++	bitmap->filemap_attr[page->index] |= attr;
++}
++
++static inline void clear_page_attr(struct bitmap *bitmap, struct page *page,
++				enum bitmap_page_attr attr)
++{
++	bitmap->filemap_attr[page->index] &= ~attr;
++}
++
++static inline unsigned long get_page_attr(struct bitmap *bitmap, struct page *page)
++{
++	return bitmap->filemap_attr[page->index];
++}
++
++/*
++ * bitmap_file_set_bit -- called before performing a write to the md device
++ * to set (and eventually sync) a particular bit in the bitmap file
++ *
++ * we set the bit immediately, then we record the page number so that
++ * when an unplug occurs, we can flush the dirty pages out to disk
++ */
++static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
++{
++	unsigned long bit;
++	struct page *page;
++	void *kaddr;
++	unsigned long chunk = block >> CHUNK_BLOCK_SHIFT(bitmap);
++
++	if (!bitmap->file || !bitmap->filemap) {
++		return;
++	}
++
++	page = filemap_get_page(bitmap, chunk);
++	bit = file_page_offset(chunk);
++
++
++	/* make sure the page stays cached until it gets written out */
++	if (! (get_page_attr(bitmap, page) & BITMAP_PAGE_DIRTY))
++		page_cache_get(page);
++
++ 	/* set the bit */
++	kaddr = kmap_atomic(page, KM_USER0);
++	set_bit(bit, kaddr);
++	kunmap_atomic(kaddr, KM_USER0);
++	PRINTK("set file bit %lu page %lu\n", bit, page->index);
++
++	/* record page number so it gets flushed to disk when unplug occurs */
++	set_page_attr(bitmap, page, BITMAP_PAGE_DIRTY);
++
++}
++
++/* this gets called when the md device is ready to unplug its underlying
++ * (slave) device queues -- before we let any writes go down, we need to
++ * sync the dirty pages of the bitmap file to disk */
++int bitmap_unplug(struct bitmap *bitmap)
++{
++	unsigned long i, attr, flags;
++	struct page *page;
++	int wait = 0;
++
++	if (!bitmap)
++		return 0;
++
++	/* look at each page to see if there are any set bits that need to be
++	 * flushed out to disk */
++	for (i = 0; i < bitmap->file_pages; i++) {
++		spin_lock_irqsave(&bitmap->lock, flags);
++		if (!bitmap->file || !bitmap->filemap) {
++			spin_unlock_irqrestore(&bitmap->lock, flags);
++			return 0;
++		}
++		page = bitmap->filemap[i];
++		attr = get_page_attr(bitmap, page);
++		clear_page_attr(bitmap, page, BITMAP_PAGE_DIRTY);
++		clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
++		if ((attr & BITMAP_PAGE_DIRTY))
++			wait = 1;
++		spin_unlock_irqrestore(&bitmap->lock, flags);
++
++		if (attr & (BITMAP_PAGE_DIRTY | BITMAP_PAGE_NEEDWRITE))
++			write_page(page, 0);
++	}
++	if (wait) { /* if any writes were performed, we need to wait on them */
++		spin_lock_irq(&bitmap->write_lock);
++		wait_event_lock_irq(bitmap->write_wait,
++			bitmap->writes_pending == 0, bitmap->write_lock,
++			wake_up_process(bitmap->writeback_daemon->tsk));
++		spin_unlock_irq(&bitmap->write_lock);
++	}
++	return 0;
++}
++
++static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
++	unsigned long sectors, int set);
++/* * bitmap_init_from_disk -- called at bitmap_create time to initialize
++ * the in-memory bitmap from the on-disk bitmap -- also, sets up the
++ * memory mapping of the bitmap file
++ * Special cases:
++ *   if there's no bitmap file, or if the bitmap file had been
++ *   previously kicked from the array, we mark all the bits as
++ *   1's in order to cause a full resync.
++ */
++static int bitmap_init_from_disk(struct bitmap *bitmap)
++{
++	unsigned long i, chunks, index, oldindex, bit;
++	struct page *page = NULL, *oldpage = NULL;
++	unsigned long num_pages, bit_cnt = 0;
++	struct file *file;
++	unsigned long bytes, offset, dummy;
++	int outofdate;
++	int ret = -ENOSPC;
++
++	chunks = bitmap->chunks;
++	file = bitmap->file;
++
++	if (!file) { /* no file, dirty all the in-memory bits */
++		printk(KERN_INFO "%s: no bitmap file, doing full recovery\n",
++			bmname(bitmap));
++		bitmap_set_memory_bits(bitmap, 0,
++				       chunks << CHUNK_BLOCK_SHIFT(bitmap), 1);
++		return 0;
++	}
++
++#if INJECT_FAULTS_3
++	outofdate = 1;
++#else
++	outofdate = bitmap->flags & BITMAP_STALE;
++#endif
++	if (outofdate)
++		printk(KERN_INFO "%s: bitmap file is out of date, doing full "
++			"recovery\n", bmname(bitmap));
++
++	bytes = (chunks + 7) / 8;
++	num_pages = (bytes + PAGE_SIZE - 1) / PAGE_SIZE;
++	if (i_size_read(file->f_mapping->host) < bytes + sizeof(bitmap_super_t)) {
++		printk(KERN_INFO "%s: bitmap file too short %lu < %lu\n",
++			bmname(bitmap),
++			(unsigned long) i_size_read(file->f_mapping->host),
++			bytes + sizeof(bitmap_super_t));
++		goto out;
++	}
++	num_pages++;
++	bitmap->filemap = kmalloc(sizeof(struct page *) * num_pages, GFP_KERNEL);
++	if (!bitmap->filemap) {
++		ret = -ENOMEM;
++		goto out;
++	}
++
++	bitmap->filemap_attr = kmalloc(sizeof(long) * num_pages, GFP_KERNEL);
++	if (!bitmap->filemap_attr) {
++		ret = -ENOMEM;
++		goto out;
++	}
++
++	memset(bitmap->filemap_attr, 0, sizeof(long) * num_pages);
++
++	oldindex = ~0L;
++
++	for (i = 0; i < chunks; i++) {
++		index = file_page_index(i);
++		bit = file_page_offset(i);
++		if (index != oldindex) { /* this is a new page, read it in */
++			/* unmap the old page, we're done with it */
++			if (oldpage != NULL)
++				kunmap(oldpage);
++			if (index == 0) {
++				/*
++				 * if we're here then the superblock page
++				 * contains some bits (PAGE_SIZE != sizeof sb)
++				 * we've already read it in, so just use it
++				 */
++				page = bitmap->sb_page;
++				offset = sizeof(bitmap_super_t);
++			} else {
++				page = read_page(file, index, &dummy);
++				if (IS_ERR(page)) { /* read error */
++					ret = PTR_ERR(page);
++					goto out;
++				}
++				offset = 0;
++			}
++			oldindex = index;
++			oldpage = page;
++			kmap(page);
++
++			if (outofdate) {
++				/*
++				 * if bitmap is out of date, dirty the
++			 	 * whole page and write it out
++				 */
++				memset(page_address(page) + offset, 0xff,
++					PAGE_SIZE - offset);
++				ret = write_page(page, 1);
++				if (ret) {
++					kunmap(page);
++					/* release, page not in filemap yet */
++					page_cache_release(page);
++					goto out;
++				}
++			}
++
++			bitmap->filemap[bitmap->file_pages++] = page;
++		}
++		if (test_bit(bit, page_address(page))) {
++			/* if the disk bit is set, set the memory bit */
++			bitmap_set_memory_bits(bitmap,
++					i << CHUNK_BLOCK_SHIFT(bitmap), 1, 1);
++			bit_cnt++;
++		}
++#if 0
++		else
++			bitmap_set_memory_bits(bitmap,
++				       i << CHUNK_BLOCK_SHIFT(bitmap), 1, 0);
++#endif
++	}
++
++ 	/* everything went OK */
++	ret = 0;
++	bitmap_mask_state(bitmap, BITMAP_STALE, MASK_UNSET);
++
++	if (page) /* unmap the last page */
++		kunmap(page);
++
++	if (bit_cnt) { /* Kick recovery if any bits were set */
++		set_bit(MD_RECOVERY_NEEDED, &bitmap->mddev->recovery);
++		md_wakeup_thread(bitmap->mddev->thread);
++	}
++
++out:
++	printk(KERN_INFO "%s: bitmap initialized from disk: "
++		"read %lu/%lu pages, set %lu bits, status: %d\n",
++		bmname(bitmap), bitmap->file_pages, num_pages, bit_cnt, ret);
++
++	return ret;
++}
++
++
++static void bitmap_count_page(struct bitmap *bitmap, sector_t offset, int inc)
++{
++	sector_t chunk = offset >> CHUNK_BLOCK_SHIFT(bitmap);
++	unsigned long page = chunk >> PAGE_COUNTER_SHIFT;
++	bitmap->bp[page].count += inc;
++/*
++	if (page == 0) printk("count page 0, offset %llu: %d gives %d\n",
++			      (unsigned long long)offset, inc, bitmap->bp[page].count);
++*/
++	bitmap_checkfree(bitmap, page);
++}
++static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
++					    sector_t offset, int *blocks,
++					    int create);
++
++/*
++ * bitmap daemon -- periodically wakes up to clean bits and flush pages
++ *			out to disk
++ */
++
++int bitmap_daemon_work(struct bitmap *bitmap)
++{
++	unsigned long bit, j;
++	unsigned long flags;
++	struct page *page = NULL, *lastpage = NULL;
++	int err = 0;
++	int blocks;
++	int attr;
++
++	if (bitmap == NULL)
++		return 0;
++	if (time_before(jiffies, bitmap->daemon_lastrun + bitmap->daemon_sleep*HZ))
++		return 0;
++	bitmap->daemon_lastrun = jiffies;
++
++	for (j = 0; j < bitmap->chunks; j++) {
++		bitmap_counter_t *bmc;
++		spin_lock_irqsave(&bitmap->lock, flags);
++		if (!bitmap->file || !bitmap->filemap) {
++			/* error or shutdown */
++			spin_unlock_irqrestore(&bitmap->lock, flags);
++			break;
++		}
++
++		page = filemap_get_page(bitmap, j);
++		/* skip this page unless it's marked as needing cleaning */
++		if (!((attr=get_page_attr(bitmap, page)) & BITMAP_PAGE_CLEAN)) {
++			if (attr & BITMAP_PAGE_NEEDWRITE) {
++				page_cache_get(page);
++				clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
++			}
++			spin_unlock_irqrestore(&bitmap->lock, flags);
++			if (attr & BITMAP_PAGE_NEEDWRITE) {
++				if (write_page(page, 0))
++					bitmap_file_kick(bitmap);
++				page_cache_release(page);
++			}
++			continue;
++		}
++
++		bit = file_page_offset(j);
++
++		if (page != lastpage) {
++			/* grab the new page, sync and release the old */
++			page_cache_get(page);
++			if (lastpage != NULL) {
++				if (get_page_attr(bitmap, lastpage) & BITMAP_PAGE_NEEDWRITE) {
++					clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
++					spin_unlock_irqrestore(&bitmap->lock, flags);
++					write_page(lastpage, 0);
++				} else {
++					set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
++					spin_unlock_irqrestore(&bitmap->lock, flags);
++				}
++				kunmap(lastpage);
++				page_cache_release(lastpage);
++				if (err)
++					bitmap_file_kick(bitmap);
++			} else
++				spin_unlock_irqrestore(&bitmap->lock, flags);
++			lastpage = page;
++			kmap(page);
++/*
++			printk("bitmap clean at page %lu\n", j);
++*/
++			spin_lock_irqsave(&bitmap->lock, flags);
++			clear_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
++		}
++		bmc = bitmap_get_counter(bitmap, j << CHUNK_BLOCK_SHIFT(bitmap),
++					&blocks, 0);
++		if (bmc) {
++/*
++  if (j < 100) printk("bitmap: j=%lu, *bmc = 0x%x\n", j, *bmc);
++*/
++			if (*bmc == 2) {
++				*bmc=1; /* maybe clear the bit next time */
++				set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
++			} else if (*bmc == 1) {
++				/* we can clear the bit */
++				*bmc = 0;
++				bitmap_count_page(bitmap, j << CHUNK_BLOCK_SHIFT(bitmap),
++						  -1);
++
++				/* clear the bit */
++				clear_bit(bit, page_address(page));
++			}
++		}
++		spin_unlock_irqrestore(&bitmap->lock, flags);
++	}
++
++	/* now sync the final page */
++	if (lastpage != NULL) {
++		kunmap(lastpage);
++		spin_lock_irqsave(&bitmap->lock, flags);
++		if (get_page_attr(bitmap, lastpage) &BITMAP_PAGE_NEEDWRITE) {
++			clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
++			spin_unlock_irqrestore(&bitmap->lock, flags);
++			write_page(lastpage, 0);
++		} else {
++			set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
++			spin_unlock_irqrestore(&bitmap->lock, flags);
++		}
++
++		page_cache_release(lastpage);
++	}
++
++	return err;
++}
++
++static void daemon_exit(struct bitmap *bitmap, mdk_thread_t **daemon)
++{
++	mdk_thread_t *dmn;
++	unsigned long flags;
++
++	/* if no one is waiting on us, we'll free the md thread struct
++	 * and exit, otherwise we let the waiter clean things up */
++	spin_lock_irqsave(&bitmap->lock, flags);
++	if ((dmn = *daemon)) { /* no one is waiting, cleanup and exit */
++		*daemon = NULL;
++		spin_unlock_irqrestore(&bitmap->lock, flags);
++		kfree(dmn);
++		complete_and_exit(NULL, 0); /* do_exit not exported */
++	}
++	spin_unlock_irqrestore(&bitmap->lock, flags);
++}
++
++static void bitmap_writeback_daemon(mddev_t *mddev)
++{
++	struct bitmap *bitmap = mddev->bitmap;
++	struct page *page;
++	struct page_list *item;
++	int err = 0;
++
++	while (1) {
++		PRINTK("%s: bitmap writeback daemon waiting...\n", bmname(bitmap));
++		down_interruptible(&bitmap->write_done);
++		if (signal_pending(current)) {
++			printk(KERN_INFO
++			    "%s: bitmap writeback daemon got signal, exiting...\n",
++			    bmname(bitmap));
++			break;
++		}
++
++		PRINTK("%s: bitmap writeback daemon woke up...\n", bmname(bitmap));
++		/* wait on bitmap page writebacks */
++		while ((item = dequeue_page(bitmap, &bitmap->complete_pages))) {
++			page = item->page;
++			mempool_free(item, bitmap->write_pool);
++			PRINTK("wait on page writeback: %p %lu\n", page, bitmap->writes_pending);
++			wait_on_page_writeback(page);
++			PRINTK("finished page writeback: %p %lu\n", page, bitmap->writes_pending);
++			spin_lock(&bitmap->write_lock);
++			if (!--bitmap->writes_pending)
++				wake_up(&bitmap->write_wait);
++			spin_unlock(&bitmap->write_lock);
++			err = PageError(page);
++			page_cache_release(page);
++			if (err) {
++				printk(KERN_WARNING "%s: bitmap file writeback "
++					"failed (page %lu): %d\n",
++					bmname(bitmap), page->index, err);
++				bitmap_file_kick(bitmap);
++				goto out;
++			}
++		}
++	}
++out:
++	if (err) {
++		printk(KERN_INFO "%s: bitmap writeback daemon exiting (%d)\n",
++			bmname(bitmap), err);
++		daemon_exit(bitmap, &bitmap->writeback_daemon);
++	}
++	return;
++}
++
++static int bitmap_start_daemon(struct bitmap *bitmap, mdk_thread_t **ptr,
++				void (*func)(mddev_t *), char *name)
++{
++	mdk_thread_t *daemon;
++	unsigned long flags;
++	char namebuf[32];
++
++	spin_lock_irqsave(&bitmap->lock, flags);
++	*ptr = NULL;
++	if (!bitmap->file) /* no need for daemon if there's no backing file */
++		goto out_unlock;
++
++	spin_unlock_irqrestore(&bitmap->lock, flags);
++
++#if INJECT_FATAL_FAULT_2
++	daemon = NULL;
++#else
++	sprintf(namebuf, "%%s_%s", name);
++	daemon = md_register_thread(func, bitmap->mddev, namebuf);
++#endif
++	if (!daemon) {
++		printk(KERN_ERR "%s: failed to start bitmap daemon\n",
++			bmname(bitmap));
++		return -ECHILD;
++	}
++
++	spin_lock_irqsave(&bitmap->lock, flags);
++	*ptr = daemon;
++
++	md_wakeup_thread(daemon); /* start it running */
++
++	PRINTK("%s: %s daemon (pid %d) started...\n",
++		bmname(bitmap), name, bitmap->daemon->tsk->pid);
++out_unlock:
++	spin_unlock_irqrestore(&bitmap->lock, flags);
++	return 0;
++}
++
++static int bitmap_start_daemons(struct bitmap *bitmap)
++{
++	int err = bitmap_start_daemon(bitmap, &bitmap->writeback_daemon,
++					bitmap_writeback_daemon, "bitmap_wb");
++	return err;
++}
++
++static void bitmap_stop_daemon(struct bitmap *bitmap, mdk_thread_t **ptr)
++{
++	mdk_thread_t *daemon;
++	unsigned long flags;
++
++	spin_lock_irqsave(&bitmap->lock, flags);
++	daemon = *ptr;
++	*ptr = NULL;
++	spin_unlock_irqrestore(&bitmap->lock, flags);
++	if (daemon)
++		md_unregister_thread(daemon); /* destroy the thread */
++}
++
++static void bitmap_stop_daemons(struct bitmap *bitmap)
++{
++	/* the daemons can't stop themselves... they'll just exit instead... */
++	if (bitmap->writeback_daemon &&
++	    current->pid != bitmap->writeback_daemon->tsk->pid)
++		bitmap_stop_daemon(bitmap, &bitmap->writeback_daemon);
++}
++
++static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
++					    sector_t offset, int *blocks,
++					    int create)
++{
++	/* If 'create', we might release the lock and reclaim it.
++	 * The lock must have been taken with interrupts enabled.
++	 * If !create, we don't release the lock.
++	 */
++	sector_t chunk = offset >> CHUNK_BLOCK_SHIFT(bitmap);
++	unsigned long page = chunk >> PAGE_COUNTER_SHIFT;
++	unsigned long pageoff = (chunk & PAGE_COUNTER_MASK) << COUNTER_BYTE_SHIFT;
++	sector_t csize;
++
++	if (bitmap_checkpage(bitmap, page, create) < 0) {
++		csize = ((sector_t)1) << (CHUNK_BLOCK_SHIFT(bitmap));
++		*blocks = csize - (offset & (csize- 1));
++		return NULL;
++	}
++	/* now locked ... */
++
++	if (bitmap->bp[page].hijacked) { /* hijacked pointer */
++		/* should we use the first or second counter field
++		 * of the hijacked pointer? */
++		int hi = (pageoff > PAGE_COUNTER_MASK);
++		csize = ((sector_t)1) << (CHUNK_BLOCK_SHIFT(bitmap) +
++					  PAGE_COUNTER_SHIFT - 1);
++		*blocks = csize - (offset & (csize- 1));
++		return  &((bitmap_counter_t *)
++			  &bitmap->bp[page].map)[hi];
++	} else { /* page is allocated */
++		csize = ((sector_t)1) << (CHUNK_BLOCK_SHIFT(bitmap));
++		*blocks = csize - (offset & (csize- 1));
++		return (bitmap_counter_t *)
++			&(bitmap->bp[page].map[pageoff]);
++	}
++}
++
++int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors)
++{
++	if (!bitmap) return 0;
++	while (sectors) {
++		int blocks;
++		bitmap_counter_t *bmc;
++
++		spin_lock_irq(&bitmap->lock);
++		bmc = bitmap_get_counter(bitmap, offset, &blocks, 1);
++		if (!bmc) {
++			spin_unlock_irq(&bitmap->lock);
++			return 0;
++		}
++
++		switch(*bmc) {
++		case 0:
++			bitmap_file_set_bit(bitmap, offset);
++			bitmap_count_page(bitmap,offset, 1);
++			blk_plug_device(bitmap->mddev->queue);
++			/* fall through */
++		case 1:
++			*bmc = 2;
++		}
++		if ((*bmc & COUNTER_MAX) == COUNTER_MAX) BUG();
++		(*bmc)++;
++
++		spin_unlock_irq(&bitmap->lock);
++
++		offset += blocks;
++		if (sectors > blocks)
++			sectors -= blocks;
++		else sectors = 0;
++	}
++	return 0;
++}
++
++void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors,
++		     int success)
++{
++	if (!bitmap) return;
++	while (sectors) {
++		int blocks;
++		unsigned long flags;
++		bitmap_counter_t *bmc;
++
++		spin_lock_irqsave(&bitmap->lock, flags);
++		bmc = bitmap_get_counter(bitmap, offset, &blocks, 0);
++		if (!bmc) {
++			spin_unlock_irqrestore(&bitmap->lock, flags);
++			return;
++		}
++
++		if (!success && ! (*bmc & NEEDED_MASK))
++			*bmc |= NEEDED_MASK;
++
++		(*bmc)--;
++		if (*bmc <= 2) {
++			set_page_attr(bitmap,
++				      filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)),
++				      BITMAP_PAGE_CLEAN);
++		}
++		spin_unlock_irqrestore(&bitmap->lock, flags);
++		offset += blocks;
++		if (sectors > blocks)
++			sectors -= blocks;
++		else sectors = 0;
++	}
++}
++
++int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks)
++{
++	bitmap_counter_t *bmc;
++	int rv;
++	if (bitmap == NULL) {/* FIXME or bitmap set as 'failed' */
++		*blocks = 1024;
++		return 1; /* always resync if no bitmap */
++	}
++	spin_lock_irq(&bitmap->lock);
++	bmc = bitmap_get_counter(bitmap, offset, blocks, 0);
++	rv = 0;
++	if (bmc) {
++		/* locked */
++		if (RESYNC(*bmc))
++			rv = 1;
++		else if (NEEDED(*bmc)) {
++			rv = 1;
++			*bmc |= RESYNC_MASK;
++			*bmc &= ~NEEDED_MASK;
++		}
++	}
++	spin_unlock_irq(&bitmap->lock);
++	return rv;
++}
++
++void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int aborted)
++{
++	bitmap_counter_t *bmc;
++	unsigned long flags;
++/*
++	if (offset == 0) printk("bitmap_end_sync 0 (%d)\n", aborted);
++*/	if (bitmap == NULL) {
++		*blocks = 1024;
++		return;
++	}
++	spin_lock_irqsave(&bitmap->lock, flags);
++	bmc = bitmap_get_counter(bitmap, offset, blocks, 0);
++	if (bmc == NULL)
++		goto unlock;
++	/* locked */
++/*
++	if (offset == 0) printk("bitmap_end sync found 0x%x, blocks %d\n", *bmc, *blocks);
++*/
++	if (RESYNC(*bmc)) {
++		*bmc &= ~RESYNC_MASK;
++
++		if (!NEEDED(*bmc) && aborted)
++			*bmc |= NEEDED_MASK;
++		else {
++			if (*bmc <= 2) {
++				set_page_attr(bitmap,
++					      filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)),
++					      BITMAP_PAGE_CLEAN);
++			}
++		}
++	}
++ unlock:
++	spin_unlock_irqrestore(&bitmap->lock, flags);
++}
++
++void bitmap_close_sync(struct bitmap *bitmap)
++{
++	/* Sync has finished, and any bitmap chunks that weren't synced
++	 * properly have been aborted.  It remains to us to clear the
++	 * RESYNC bit wherever it is still on
++	 */
++	sector_t sector = 0;
++	int blocks;
++	if (!bitmap) return;
++	while (sector < bitmap->mddev->resync_max_sectors) {
++		bitmap_end_sync(bitmap, sector, &blocks, 0);
++/*
++		if (sector < 500) printk("bitmap_close_sync: sec %llu blks %d\n",
++					 (unsigned long long)sector, blocks);
++*/		sector += blocks;
++	}
++}
++
++static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
++				   unsigned long sectors, int set)
++{
++	/* For each chunk covered by any of these sectors, set the
++	 * resync needed bit, and the counter to 1.  They should all
++	 * be 0 at this point
++	 */
++	while (sectors) {
++		int secs;
++		bitmap_counter_t *bmc;
++		spin_lock_irq(&bitmap->lock);
++		bmc = bitmap_get_counter(bitmap, offset, &secs, 1);
++		if (!bmc) {
++			spin_unlock_irq(&bitmap->lock);
++			return;
++		}
++		if (set && !NEEDED(*bmc)) {
++			BUG_ON(*bmc);
++			*bmc = NEEDED_MASK | 1;
++			bitmap_count_page(bitmap, offset, 1);
++		}
++		spin_unlock_irq(&bitmap->lock);
++		if (sectors > secs)
++			sectors -= secs;
++		else
++			sectors = 0;
++	}
++}
++
++/* dirty the entire bitmap */
++int bitmap_setallbits(struct bitmap *bitmap)
++{
++	unsigned long flags;
++	unsigned long j;
++
++	/* dirty the in-memory bitmap */
++	bitmap_set_memory_bits(bitmap, 0, bitmap->chunks << CHUNK_BLOCK_SHIFT(bitmap), 1);
++
++	/* dirty the bitmap file */
++	for (j = 0; j < bitmap->file_pages; j++) {
++		struct page *page = bitmap->filemap[j];
++
++		spin_lock_irqsave(&bitmap->lock, flags);
++		page_cache_get(page);
++		spin_unlock_irqrestore(&bitmap->lock, flags);
++		memset(kmap(page), 0xff, PAGE_SIZE);
++		kunmap(page);
++		write_page(page, 0);
++	}
++
++	return 0;
++}
++
++/*
++ * free memory that was allocated
++ */
++void bitmap_destroy(mddev_t *mddev)
++{
++	unsigned long k, pages;
++	struct bitmap_page *bp;
++	struct bitmap *bitmap = mddev->bitmap;
++
++	if (!bitmap) /* there was no bitmap */
++		return;
++
++	mddev->bitmap = NULL; /* disconnect from the md device */
++
++	/* release the bitmap file and kill the daemon */
++	bitmap_file_put(bitmap);
++
++	bp = bitmap->bp;
++	pages = bitmap->pages;
++
++	/* free all allocated memory */
++
++	mempool_destroy(bitmap->write_pool);
++
++	if (bp) /* deallocate the page memory */
++		for (k = 0; k < pages; k++)
++			if (bp[k].map && !bp[k].hijacked)
++				kfree(bp[k].map);
++	kfree(bp);
++	kfree(bitmap);
++}
++
++/*
++ * initialize the bitmap structure
++ * if this returns an error, bitmap_destroy must be called to do clean up
++ */
++int bitmap_create(mddev_t *mddev)
++{
++	struct bitmap *bitmap;
++	unsigned long blocks = mddev->resync_max_sectors;
++	unsigned long chunks;
++	unsigned long pages;
++	struct file *file = mddev->bitmap_file;
++	int err;
++
++	BUG_ON(sizeof(bitmap_super_t) != 256);
++
++	if (!file) /* bitmap disabled, nothing to do */
++		return 0;
++
++	bitmap = kmalloc(sizeof(*bitmap), GFP_KERNEL);
++	if (!bitmap)
++		return -ENOMEM;
++
++	memset(bitmap, 0, sizeof(*bitmap));
++
++	spin_lock_init(&bitmap->lock);
++	bitmap->mddev = mddev;
++	mddev->bitmap = bitmap;
++
++	spin_lock_init(&bitmap->write_lock);
++	init_MUTEX_LOCKED(&bitmap->write_done);
++	INIT_LIST_HEAD(&bitmap->complete_pages);
++	init_waitqueue_head(&bitmap->write_wait);
++	bitmap->write_pool = mempool_create(WRITE_POOL_SIZE, write_pool_alloc,
++				write_pool_free, NULL);
++	if (!bitmap->write_pool)
++		return -ENOMEM;
++
++	bitmap->file = file;
++	get_file(file);
++	/* read superblock from bitmap file (this sets bitmap->chunksize) */
++	err = bitmap_read_sb(bitmap);
++	if (err)
++		return err;
++
++	bitmap->chunkshift = find_first_bit(&bitmap->chunksize,
++					sizeof(bitmap->chunksize));
++
++	/* now that chunksize and chunkshift are set, we can use these macros */
++ 	chunks = (blocks + CHUNK_BLOCK_RATIO(bitmap) - 1) /
++			CHUNK_BLOCK_RATIO(bitmap);
++ 	pages = (chunks + PAGE_COUNTER_RATIO - 1) / PAGE_COUNTER_RATIO;
++
++	BUG_ON(!pages);
++
++	bitmap->chunks = chunks;
++	bitmap->pages = pages;
++	bitmap->missing_pages = pages;
++	bitmap->counter_bits = COUNTER_BITS;
++
++	bitmap->syncchunk = ~0UL;
++
++#if INJECT_FATAL_FAULT_1
++	bitmap->bp = NULL;
++#else
++	bitmap->bp = kmalloc(pages * sizeof(*bitmap->bp), GFP_KERNEL);
++#endif
++	if (!bitmap->bp)
++		return -ENOMEM;
++	memset(bitmap->bp, 0, pages * sizeof(*bitmap->bp));
++
++	bitmap->flags |= BITMAP_ACTIVE;
++
++	/* now that we have some pages available, initialize the in-memory
++	 * bitmap from the on-disk bitmap */
++	err = bitmap_init_from_disk(bitmap);
++	if (err)
++		return err;
++
++	printk(KERN_INFO "created bitmap (%lu pages) for device %s\n",
++		pages, bmname(bitmap));
++
++	/* kick off the bitmap daemons */
++	err = bitmap_start_daemons(bitmap);
++	if (err)
++		return err;
++	return bitmap_update_sb(bitmap);
++}
++
++/* the bitmap API -- for raid personalities */
++EXPORT_SYMBOL(bitmap_startwrite);
++EXPORT_SYMBOL(bitmap_endwrite);
++EXPORT_SYMBOL(bitmap_start_sync);
++EXPORT_SYMBOL(bitmap_end_sync);
++EXPORT_SYMBOL(bitmap_unplug);
++EXPORT_SYMBOL(bitmap_close_sync);
++EXPORT_SYMBOL(bitmap_daemon_work);
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index fa608a1a5c20..c402f6cc7047 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -19,6 +19,9 @@
+ 
+      Neil Brown .
+ 
++   - persistent bitmap code
++     Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, Inc.
++
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2, or (at your option)
+@@ -33,6 +36,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include  /* for invalidate_bdev */
+@@ -40,6 +44,8 @@
+ 
+ #include 
+ 
++#include 
++
+ #ifdef CONFIG_KMOD
+ #include 
+ #endif
+@@ -1198,8 +1204,11 @@ void md_print_devices(void)
+ 	printk("md:	*  *\n");
+ 	printk("md:	**********************************\n");
+ 	ITERATE_MDDEV(mddev,tmp) {
+-		printk("%s: ", mdname(mddev));
+ 
++		if (mddev->bitmap)
++			bitmap_print_sb(mddev->bitmap);
++		else
++			printk("%s: ", mdname(mddev));
+ 		ITERATE_RDEV(mddev,rdev,tmp2)
+ 			printk("<%s>", bdevname(rdev->bdev,b));
+ 		printk("\n");
+@@ -1287,7 +1296,7 @@ static void md_update_sb(mddev_t * mddev)
+ 		"md: updating %s RAID superblock on device (in sync %d)\n",
+ 		mdname(mddev),mddev->in_sync);
+ 
+-	err = 0;
++	err = bitmap_update_sb(mddev->bitmap);
+ 	ITERATE_RDEV(mddev,rdev,tmp) {
+ 		char b[BDEVNAME_SIZE];
+ 		dprintk(KERN_INFO "md: ");
+@@ -1624,12 +1633,19 @@ static int do_md_run(mddev_t * mddev)
+ 
+ 	mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */
+ 
+-	err = mddev->pers->run(mddev);
++	/* before we start the array running, initialise the bitmap */
++	err = bitmap_create(mddev);
++	if (err)
++		printk(KERN_ERR "%s: failed to create bitmap (%d)\n",
++			mdname(mddev), err);
++	else
++		err = mddev->pers->run(mddev);
+ 	if (err) {
+ 		printk(KERN_ERR "md: pers->run() failed ...\n");
+ 		module_put(mddev->pers->owner);
+ 		mddev->pers = NULL;
+-		return -EINVAL;
++		bitmap_destroy(mddev);
++		return err;
+ 	}
+  	atomic_set(&mddev->writes_pending,0);
+ 	mddev->safemode = 0;
+@@ -1742,6 +1758,14 @@ static int do_md_stop(mddev_t * mddev, int ro)
+ 		if (ro)
+ 			set_disk_ro(disk, 1);
+ 	}
++
++	bitmap_destroy(mddev);
++	if (mddev->bitmap_file) {
++		atomic_set(&mddev->bitmap_file->f_dentry->d_inode->i_writecount, 1);
++		fput(mddev->bitmap_file);
++		mddev->bitmap_file = NULL;
++	}
++
+ 	/*
+ 	 * Free resources if final stop
+ 	 */
+@@ -2000,6 +2024,42 @@ static int get_array_info(mddev_t * mddev, void __user * arg)
+ 	return 0;
+ }
+ 
++static int get_bitmap_file(mddev_t * mddev, void * arg)
++{
++	mdu_bitmap_file_t *file = NULL; /* too big for stack allocation */
++	char *ptr, *buf = NULL;
++	int err = -ENOMEM;
++
++	file = kmalloc(sizeof(*file), GFP_KERNEL);
++	if (!file)
++		goto out;
++
++	/* bitmap disabled, zero the first byte and copy out */
++	if (!mddev->bitmap || !mddev->bitmap->file) {
++		file->pathname[0] = '\0';
++		goto copy_out;
++	}
++
++	buf = kmalloc(sizeof(file->pathname), GFP_KERNEL);
++	if (!buf)
++		goto out;
++
++	ptr = file_path(mddev->bitmap->file, buf, sizeof(file->pathname));
++	if (!ptr)
++		goto out;
++
++	strcpy(file->pathname, ptr);
++
++copy_out:
++	err = 0;
++	if (copy_to_user(arg, file, sizeof(*file)))
++		err = -EFAULT;
++out:
++	kfree(buf);
++	kfree(file);
++	return err;
++}
++
+ static int get_disk_info(mddev_t * mddev, void __user * arg)
+ {
+ 	mdu_disk_info_t info;
+@@ -2275,6 +2335,48 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
+ 	return err;
+ }
+ 
++/* similar to deny_write_access, but accounts for our holding a reference
++ * to the file ourselves */
++static int deny_bitmap_write_access(struct file * file)
++{
++	struct inode *inode = file->f_mapping->host;
++
++	spin_lock(&inode->i_lock);
++	if (atomic_read(&inode->i_writecount) > 1) {
++		spin_unlock(&inode->i_lock);
++		return -ETXTBSY;
++	}
++	atomic_set(&inode->i_writecount, -1);
++	spin_unlock(&inode->i_lock);
++
++	return 0;
++}
++
++static int set_bitmap_file(mddev_t *mddev, int fd)
++{
++	int err;
++
++	if (mddev->pers)
++		return -EBUSY;
++
++	mddev->bitmap_file = fget(fd);
++
++	if (mddev->bitmap_file == NULL) {
++		printk(KERN_ERR "%s: error: failed to get bitmap file\n",
++			mdname(mddev));
++		return -EBADF;
++	}
++
++	err = deny_bitmap_write_access(mddev->bitmap_file);
++	if (err) {
++		printk(KERN_ERR "%s: error: bitmap file is already in use\n",
++			mdname(mddev));
++		fput(mddev->bitmap_file);
++		mddev->bitmap_file = NULL;
++	}
++	return err;
++}
++
+ /*
+  * set_array_info is used two different ways
+  * The original usage is when creating a new array.
+@@ -2586,8 +2688,10 @@ static int md_ioctl(struct inode *inode, struct file *file,
+ 	/*
+ 	 * Commands querying/configuring an existing array:
+ 	 */
+-	/* if we are initialised yet, only ADD_NEW_DISK or STOP_ARRAY is allowed */
+-	if (!mddev->raid_disks && cmd != ADD_NEW_DISK && cmd != STOP_ARRAY && cmd != RUN_ARRAY) {
++	/* if we are not initialised yet, only ADD_NEW_DISK, STOP_ARRAY,
++	 * RUN_ARRAY, and SET_BITMAP_FILE are allowed */
++	if (!mddev->raid_disks && cmd != ADD_NEW_DISK && cmd != STOP_ARRAY
++			&& cmd != RUN_ARRAY && cmd != SET_BITMAP_FILE) {
+ 		err = -ENODEV;
+ 		goto abort_unlock;
+ 	}
+@@ -2601,6 +2705,10 @@ static int md_ioctl(struct inode *inode, struct file *file,
+ 			err = get_array_info(mddev, argp);
+ 			goto done_unlock;
+ 
++		case GET_BITMAP_FILE:
++			err = get_bitmap_file(mddev, (void *)arg);
++			goto done_unlock;
++
+ 		case GET_DISK_INFO:
+ 			err = get_disk_info(mddev, argp);
+ 			goto done_unlock;
+@@ -2681,6 +2789,10 @@ static int md_ioctl(struct inode *inode, struct file *file,
+ 			err = do_md_run (mddev);
+ 			goto done_unlock;
+ 
++		case SET_BITMAP_FILE:
++			err = set_bitmap_file(mddev, (int)arg);
++			goto done_unlock;
++
+ 		default:
+ 			if (_IOC_TYPE(cmd) == MD_MAJOR)
+ 				printk(KERN_WARNING "md: %s(pid %d) used"
+@@ -2792,8 +2904,9 @@ static int md_thread(void * arg)
+ 	while (thread->run) {
+ 		void (*run)(mddev_t *);
+ 
+-		wait_event_interruptible(thread->wqueue,
+-					 test_bit(THREAD_WAKEUP, &thread->flags));
++		wait_event_interruptible_timeout(thread->wqueue,
++						 test_bit(THREAD_WAKEUP, &thread->flags),
++						 thread->timeout);
+ 		if (current->flags & PF_FREEZE)
+ 			refrigerator(PF_FREEZE);
+ 
+@@ -2839,6 +2952,7 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
+ 	thread->run = run;
+ 	thread->mddev = mddev;
+ 	thread->name = name;
++	thread->timeout = MAX_SCHEDULE_TIMEOUT;
+ 	ret = kernel_thread(md_thread, thread, 0);
+ 	if (ret < 0) {
+ 		kfree(thread);
+@@ -2877,13 +2991,13 @@ void md_error(mddev_t *mddev, mdk_rdev_t *rdev)
+ 
+ 	if (!rdev || rdev->faulty)
+ 		return;
+-
++/*
+ 	dprintk("md_error dev:%s, rdev:(%d:%d), (caller: %p,%p,%p,%p).\n",
+ 		mdname(mddev),
+ 		MAJOR(rdev->bdev->bd_dev), MINOR(rdev->bdev->bd_dev),
+ 		__builtin_return_address(0),__builtin_return_address(1),
+ 		__builtin_return_address(2),__builtin_return_address(3));
+-
++*/
+ 	if (!mddev->pers->error_handler)
+ 		return;
+ 	mddev->pers->error_handler(mddev,rdev);
+@@ -3037,6 +3151,7 @@ static int md_seq_show(struct seq_file *seq, void *v)
+ 	struct list_head *tmp2;
+ 	mdk_rdev_t *rdev;
+ 	int i;
++	struct bitmap *bitmap;
+ 
+ 	if (v == (void*)1) {
+ 		seq_printf(seq, "Personalities : ");
+@@ -3089,10 +3204,36 @@ static int md_seq_show(struct seq_file *seq, void *v)
+ 		if (mddev->pers) {
+ 			mddev->pers->status (seq, mddev);
+ 	 		seq_printf(seq, "\n      ");
+-			if (mddev->curr_resync > 2)
++			if (mddev->curr_resync > 2) {
+ 				status_resync (seq, mddev);
+-			else if (mddev->curr_resync == 1 || mddev->curr_resync == 2)
+-				seq_printf(seq, "	resync=DELAYED");
++				seq_printf(seq, "\n      ");
++			} else if (mddev->curr_resync == 1 || mddev->curr_resync == 2)
++				seq_printf(seq, "	resync=DELAYED\n      ");
++		} else
++			seq_printf(seq, "\n       ");
++
++		if ((bitmap = mddev->bitmap)) {
++			char *buf, *path;
++			unsigned long chunk_kb;
++			unsigned long flags;
++			buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
++			spin_lock_irqsave(&bitmap->lock, flags);
++			chunk_kb = bitmap->chunksize >> 10;
++			seq_printf(seq, "bitmap: %lu/%lu pages [%luKB], "
++				"%lu%s chunk",
++				bitmap->pages - bitmap->missing_pages,
++				bitmap->pages,
++				(bitmap->pages - bitmap->missing_pages)
++					<< (PAGE_SHIFT - 10),
++				chunk_kb ? chunk_kb : bitmap->chunksize,
++				chunk_kb ? "KB" : "B");
++			if (bitmap->file && buf) {
++				path = file_path(bitmap->file, buf, PAGE_SIZE);
++				seq_printf(seq, ", file: %s", path ? path : "");
++			}
++			seq_printf(seq, "\n");
++			spin_unlock_irqrestore(&bitmap->lock, flags);
++			kfree(buf);
+ 		}
+ 
+ 		seq_printf(seq, "\n");
+@@ -3328,7 +3469,8 @@ static void md_do_sync(mddev_t *mddev)
+ 	       sysctl_speed_limit_max);
+ 
+ 	is_mddev_idle(mddev); /* this also initializes IO event counters */
+-	if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
++	/* we don't use the checkpoint if there's a bitmap */
++	if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && !mddev->bitmap)
+ 		j = mddev->recovery_cp;
+ 	else
+ 		j = 0;
+@@ -3673,6 +3815,8 @@ static int __init md_init(void)
+ 			" MD_SB_DISKS=%d\n",
+ 			MD_MAJOR_VERSION, MD_MINOR_VERSION,
+ 			MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MD_SB_DISKS);
++	printk(KERN_INFO "md: bitmap version %d.%d\n", BITMAP_MAJOR,
++			BITMAP_MINOR);
+ 
+ 	if (register_blkdev(MAJOR_NR, "md"))
+ 		return -1;
+diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h
+new file mode 100644
+index 000000000000..f785cf26cbad
+--- /dev/null
++++ b/include/linux/raid/bitmap.h
+@@ -0,0 +1,280 @@
++/*
++ * bitmap.h: Copyright (C) Peter T. Breuer (ptb@ot.uc3m.es) 2003
++ *
++ * additions: Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, Inc.
++ */
++#ifndef BITMAP_H
++#define BITMAP_H 1
++
++#define BITMAP_MAJOR 3
++#define BITMAP_MINOR 38
++
++/*
++ * in-memory bitmap:
++ *
++ * Use 16 bit block counters to track pending writes to each "chunk".
++ * The 2 high order bits are special-purpose, the first is a flag indicating
++ * whether a resync is needed.  The second is a flag indicating whether a
++ * resync is active.
++ * This means that the counter is actually 14 bits:
++ *
++ * +--------+--------+------------------------------------------------+
++ * | resync | resync |               counter                          |
++ * | needed | active |                                                |
++ * |  (0-1) |  (0-1) |              (0-16383)                         |
++ * +--------+--------+------------------------------------------------+
++ *
++ * The "resync needed" bit is set when:
++ *    a '1' bit is read from storage at startup.
++ *    a write request fails on some drives
++ *    a resync is aborted on a chunk with 'resync active' set
++ * It is cleared (and resync-active set) when a resync starts across all drives
++ * of the chunk.
++ *
++ *
++ * The "resync active" bit is set when:
++ *    a resync is started on all drives, and resync_needed is set.
++ *       resync_needed will be cleared (as long as resync_active wasn't already set).
++ * It is cleared when a resync completes.
++ *
++ * The counter counts pending write requests, plus the on-disk bit.
++ * When the counter is '1' and the resync bits are clear, the on-disk
++ * bit can be cleared aswell, thus setting the counter to 0.
++ * When we set a bit, or in the counter (to start a write), if the fields is
++ * 0, we first set the disk bit and set the counter to 1.
++ *
++ * If the counter is 0, the on-disk bit is clear and the stipe is clean
++ * Anything that dirties the stipe pushes the counter to 2 (at least)
++ * and sets the on-disk bit (lazily).
++ * If a periodic sweep find the counter at 2, it is decremented to 1.
++ * If the sweep find the counter at 1, the on-disk bit is cleared and the
++ * counter goes to zero.
++ *
++ * Also, we'll hijack the "map" pointer itself and use it as two 16 bit block
++ * counters as a fallback when "page" memory cannot be allocated:
++ *
++ * Normal case (page memory allocated):
++ *
++ *     page pointer (32-bit)
++ *
++ *     [ ] ------+
++ *               |
++ *               +-------> [   ][   ]..[   ] (4096 byte page == 2048 counters)
++ *                          c1   c2    c2048
++ *
++ * Hijacked case (page memory allocation failed):
++ *
++ *     hijacked page pointer (32-bit)
++ *
++ *     [		  ][		  ] (no page memory allocated)
++ *      counter #1 (16-bit) counter #2 (16-bit)
++ *
++ */
++
++#ifdef __KERNEL__
++
++#define PAGE_BITS (PAGE_SIZE << 3)
++#define PAGE_BIT_SHIFT (PAGE_SHIFT + 3)
++
++typedef __u16 bitmap_counter_t;
++#define COUNTER_BITS 16
++#define COUNTER_BIT_SHIFT 4
++#define COUNTER_BYTE_RATIO (COUNTER_BITS / 8)
++#define COUNTER_BYTE_SHIFT (COUNTER_BIT_SHIFT - 3)
++
++#define NEEDED_MASK ((bitmap_counter_t) (1 << (COUNTER_BITS - 1)))
++#define RESYNC_MASK ((bitmap_counter_t) (1 << (COUNTER_BITS - 2)))
++#define COUNTER_MAX ((bitmap_counter_t) RESYNC_MASK - 1)
++#define NEEDED(x) (((bitmap_counter_t) x) & NEEDED_MASK)
++#define RESYNC(x) (((bitmap_counter_t) x) & RESYNC_MASK)
++#define COUNTER(x) (((bitmap_counter_t) x) & COUNTER_MAX)
++
++/* how many counters per page? */
++#define PAGE_COUNTER_RATIO (PAGE_BITS / COUNTER_BITS)
++/* same, except a shift value for more efficient bitops */
++#define PAGE_COUNTER_SHIFT (PAGE_BIT_SHIFT - COUNTER_BIT_SHIFT)
++/* same, except a mask value for more efficient bitops */
++#define PAGE_COUNTER_MASK  (PAGE_COUNTER_RATIO - 1)
++
++#define BITMAP_BLOCK_SIZE 512
++#define BITMAP_BLOCK_SHIFT 9
++
++/* how many blocks per chunk? (this is variable) */
++#define CHUNK_BLOCK_RATIO(bitmap) ((bitmap)->chunksize >> BITMAP_BLOCK_SHIFT)
++#define CHUNK_BLOCK_SHIFT(bitmap) ((bitmap)->chunkshift - BITMAP_BLOCK_SHIFT)
++#define CHUNK_BLOCK_MASK(bitmap) (CHUNK_BLOCK_RATIO(bitmap) - 1)
++
++/* when hijacked, the counters and bits represent even larger "chunks" */
++/* there will be 1024 chunks represented by each counter in the page pointers */
++#define PAGEPTR_BLOCK_RATIO(bitmap) \
++			(CHUNK_BLOCK_RATIO(bitmap) << PAGE_COUNTER_SHIFT >> 1)
++#define PAGEPTR_BLOCK_SHIFT(bitmap) \
++			(CHUNK_BLOCK_SHIFT(bitmap) + PAGE_COUNTER_SHIFT - 1)
++#define PAGEPTR_BLOCK_MASK(bitmap) (PAGEPTR_BLOCK_RATIO(bitmap) - 1)
++
++/*
++ * on-disk bitmap:
++ *
++ * Use one bit per "chunk" (block set). We do the disk I/O on the bitmap
++ * file a page at a time. There's a superblock at the start of the file.
++ */
++
++/* map chunks (bits) to file pages - offset by the size of the superblock */
++#define CHUNK_BIT_OFFSET(chunk) ((chunk) + (sizeof(bitmap_super_t) << 3))
++
++#endif
++
++/*
++ * bitmap structures:
++ */
++
++#define BITMAP_MAGIC 0x6d746962
++
++/* use these for bitmap->flags and bitmap->sb->state bit-fields */
++enum bitmap_state {
++	BITMAP_ACTIVE = 0x001, /* the bitmap is in use */
++	BITMAP_STALE  = 0x002  /* the bitmap file is out of date or had -EIO */
++};
++
++/* the superblock at the front of the bitmap file -- little endian */
++typedef struct bitmap_super_s {
++	__u32 magic;        /*  0  BITMAP_MAGIC */
++	__u32 version;      /*  4  the bitmap major for now, could change... */
++	__u8  uuid[16];     /*  8  128 bit uuid - must match md device uuid */
++	__u64 events;       /* 24  event counter for the bitmap (1)*/
++	__u64 events_cleared;/*32  event counter when last bit cleared (2) */
++	__u64 sync_size;    /* 40  the size of the md device's sync range(3) */
++	__u32 state;        /* 48  bitmap state information */
++	__u32 chunksize;    /* 52  the bitmap chunk size in bytes */
++	__u32 daemon_sleep; /* 56  seconds between disk flushes */
++
++	__u8  pad[256 - 60]; /* set to zero */
++} bitmap_super_t;
++
++/* notes:
++ * (1) This event counter is updated before the eventcounter in the md superblock
++ *    When a bitmap is loaded, it is only accepted if this event counter is equal
++ *    to, or one greater than, the event counter in the superblock.
++ * (2) This event counter is updated when the other one is *if*and*only*if* the
++ *    array is not degraded.  As bits are not cleared when the array is degraded,
++ *    this represents the last time that any bits were cleared.
++ *    If a device is being added that has an event count with this value or
++ *    higher, it is accepted as conforming to the bitmap.
++ * (3)This is the number of sectors represented by the bitmap, and is the range that
++ *    resync happens across.  For raid1 and raid5/6 it is the size of individual
++ *    devices.  For raid10 it is the size of the array.
++ */
++
++#ifdef __KERNEL__
++
++/* the in-memory bitmap is represented by bitmap_pages */
++struct bitmap_page {
++	/*
++	 * map points to the actual memory page
++	 */
++	char *map;
++	/*
++	 * in emergencies (when map cannot be alloced), hijack the map
++	 * pointer and use it as two counters itself
++	 */
++	unsigned int hijacked:1;
++	/*
++	 * count of dirty bits on the page
++	 */
++	unsigned int  count:31;
++};
++
++/* keep track of bitmap file pages that have pending writes on them */
++struct page_list {
++	struct list_head list;
++	struct page *page;
++};
++
++/* the main bitmap structure - one per mddev */
++struct bitmap {
++	struct bitmap_page *bp;
++	unsigned long pages; /* total number of pages in the bitmap */
++	unsigned long missing_pages; /* number of pages not yet allocated */
++
++	mddev_t *mddev; /* the md device that the bitmap is for */
++
++	int counter_bits; /* how many bits per block counter */
++
++	/* bitmap chunksize -- how much data does each bit represent? */
++	unsigned long chunksize;
++	unsigned long chunkshift; /* chunksize = 2^chunkshift (for bitops) */
++	unsigned long chunks; /* total number of data chunks for the array */
++
++	/* We hold a count on the chunk currently being synced, and drop
++	 * it when the last block is started.  If the resync is aborted
++	 * midway, we need to be able to drop that count, so we remember
++	 * the counted chunk..
++	 */
++	unsigned long syncchunk;
++
++	__u64	events_cleared;
++
++	/* bitmap spinlock */
++	spinlock_t lock;
++
++	struct file *file; /* backing disk file */
++	struct page *sb_page; /* cached copy of the bitmap file superblock */
++	struct page **filemap; /* list of cache pages for the file */
++	unsigned long *filemap_attr; /* attributes associated w/ filemap pages */
++	unsigned long file_pages; /* number of pages in the file */
++
++	unsigned long flags;
++
++	/*
++	 * the bitmap daemon - periodically wakes up and sweeps the bitmap
++	 * file, cleaning up bits and flushing out pages to disk as necessary
++	 */
++	unsigned long daemon_lastrun; /* jiffies of last run */
++	unsigned long daemon_sleep; /* how many seconds between updates? */
++
++	/*
++	 * bitmap write daemon - this daemon performs writes to the bitmap file
++	 * this thread is only needed because of a limitation in ext3 (jbd)
++	 * that does not allow a task to have two journal transactions ongoing
++	 * simultaneously (even if the transactions are for two different
++	 * filesystems) -- in the case of bitmap, that would be the filesystem
++	 * that the bitmap file resides on and the filesystem that is mounted
++	 * on the md device -- see current->journal_info in jbd/transaction.c
++	 */
++	mdk_thread_t *writeback_daemon;
++	spinlock_t write_lock;
++	struct semaphore write_ready;
++	struct semaphore write_done;
++	unsigned long writes_pending;
++	wait_queue_head_t write_wait;
++	struct list_head write_pages;
++	struct list_head complete_pages;
++	mempool_t *write_pool;
++};
++
++/* the bitmap API */
++
++/* these are used only by md/bitmap */
++int  bitmap_create(mddev_t *mddev);
++void bitmap_destroy(mddev_t *mddev);
++int  bitmap_active(struct bitmap *bitmap);
++
++char *file_path(struct file *file, char *buf, int count);
++void bitmap_print_sb(struct bitmap *bitmap);
++int bitmap_update_sb(struct bitmap *bitmap);
++
++int  bitmap_setallbits(struct bitmap *bitmap);
++
++/* these are exported */
++int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors);
++void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors,
++		     int success);
++int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks);
++void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int aborted);
++void bitmap_close_sync(struct bitmap *bitmap);
++
++int bitmap_unplug(struct bitmap *bitmap);
++int bitmap_daemon_work(struct bitmap *bitmap);
++#endif
++
++#endif
+diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
+index bce0032decff..16e94a9f0f8c 100644
+--- a/include/linux/raid/md_k.h
++++ b/include/linux/raid/md_k.h
+@@ -267,6 +267,9 @@ struct mddev_s
+ 	atomic_t			writes_pending; 
+ 	request_queue_t			*queue;	/* for plugging ... */
+ 
++	struct bitmap                   *bitmap; /* the bitmap for the device */
++	struct file			*bitmap_file; /* the bitmap file */
++
+ 	struct list_head		all_mddevs;
+ };
+ 
+@@ -341,6 +344,7 @@ typedef struct mdk_thread_s {
+ 	unsigned long           flags;
+ 	struct completion	*event;
+ 	struct task_struct	*tsk;
++	unsigned long		timeout;
+ 	const char		*name;
+ } mdk_thread_t;
+ 
+diff --git a/include/linux/raid/md_u.h b/include/linux/raid/md_u.h
+index a2df5c2a42af..81da20ccec4d 100644
+--- a/include/linux/raid/md_u.h
++++ b/include/linux/raid/md_u.h
+@@ -23,6 +23,7 @@
+ #define GET_DISK_INFO		_IOR (MD_MAJOR, 0x12, mdu_disk_info_t)
+ #define PRINT_RAID_DEBUG	_IO (MD_MAJOR, 0x13)
+ #define RAID_AUTORUN		_IO (MD_MAJOR, 0x14)
++#define GET_BITMAP_FILE		_IOR (MD_MAJOR, 0x15, mdu_bitmap_file_t)
+ 
+ /* configuration */
+ #define CLEAR_ARRAY		_IO (MD_MAJOR, 0x20)
+@@ -36,6 +37,7 @@
+ #define HOT_ADD_DISK		_IO (MD_MAJOR, 0x28)
+ #define SET_DISK_FAULTY		_IO (MD_MAJOR, 0x29)
+ #define HOT_GENERATE_ERROR	_IO (MD_MAJOR, 0x2a)
++#define SET_BITMAP_FILE		_IOW (MD_MAJOR, 0x2b, int)
+ 
+ /* usage */
+ #define RUN_ARRAY		_IOW (MD_MAJOR, 0x30, mdu_param_t)
+@@ -106,6 +108,11 @@ typedef struct mdu_start_info_s {
+ 
+ } mdu_start_info_t;
+ 
++typedef struct mdu_bitmap_file_s
++{
++	char pathname[4096];
++} mdu_bitmap_file_t;
++
+ typedef struct mdu_param_s
+ {
+ 	int			personality;	/* 1,2,3,4 */

commit 57afd89f98a990747445f01c458ecae64263b2f8
+Author: NeilBrown 
+Date:   Tue Jun 21 17:17:13 2005 -0700
+
+    [PATCH] md: improve the interface to sync_request
+    
+    1/ change the return value (which is number-of-sectors synced)
+     from 'int' to 'sector_t'.
+     The number of sectors is usually easily small enough to fit
+     in an int, but if resync needs to abort, it may want to return
+     the total number of remaining sectors, which could be large.
+     Also errors cannot be returned as negative numbers now, so use
+     0 instead
+    2/ Add a 'skipped' return parameter to allow the array to report
+     that it skipped the sectors.  This allows md to take this into account
+     in the speed calculations.
+     Currently there is no important skipping, but the bitmap-based-resync
+     that is coming will use this.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 177d2a7d7cea..fa608a1a5c20 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -3241,12 +3241,13 @@ static void md_do_sync(mddev_t *mddev)
+ 	mddev_t *mddev2;
+ 	unsigned int currspeed = 0,
+ 		 window;
+-	sector_t max_sectors,j;
++	sector_t max_sectors,j, io_sectors;
+ 	unsigned long mark[SYNC_MARKS];
+ 	sector_t mark_cnt[SYNC_MARKS];
+ 	int last_mark,m;
+ 	struct list_head *tmp;
+ 	sector_t last_check;
++	int skipped = 0;
+ 
+ 	/* just incase thread restarts... */
+ 	if (test_bit(MD_RECOVERY_DONE, &mddev->recovery))
+@@ -3312,7 +3313,7 @@ static void md_do_sync(mddev_t *mddev)
+ 
+ 	if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
+ 		/* resync follows the size requested by the personality,
+-		 * which default to physical size, but can be virtual size
++		 * which defaults to physical size, but can be virtual size
+ 		 */
+ 		max_sectors = mddev->resync_max_sectors;
+ 	else
+@@ -3331,9 +3332,10 @@ static void md_do_sync(mddev_t *mddev)
+ 		j = mddev->recovery_cp;
+ 	else
+ 		j = 0;
++	io_sectors = 0;
+ 	for (m = 0; m < SYNC_MARKS; m++) {
+ 		mark[m] = jiffies;
+-		mark_cnt[m] = j;
++		mark_cnt[m] = io_sectors;
+ 	}
+ 	last_mark = 0;
+ 	mddev->resync_mark = mark[last_mark];
+@@ -3358,21 +3360,29 @@ static void md_do_sync(mddev_t *mddev)
+ 	}
+ 
+ 	while (j < max_sectors) {
+-		int sectors;
++		sector_t sectors;
+ 
+-		sectors = mddev->pers->sync_request(mddev, j, currspeed < sysctl_speed_limit_min);
+-		if (sectors < 0) {
++		skipped = 0;
++		sectors = mddev->pers->sync_request(mddev, j, &skipped,
++					    currspeed < sysctl_speed_limit_min);
++		if (sectors == 0) {
+ 			set_bit(MD_RECOVERY_ERR, &mddev->recovery);
+ 			goto out;
+ 		}
+-		atomic_add(sectors, &mddev->recovery_active);
++
++		if (!skipped) { /* actual IO requested */
++			io_sectors += sectors;
++			atomic_add(sectors, &mddev->recovery_active);
++		}
++
+ 		j += sectors;
+ 		if (j>1) mddev->curr_resync = j;
+ 
+-		if (last_check + window > j || j == max_sectors)
++
++		if (last_check + window > io_sectors || j == max_sectors)
+ 			continue;
+ 
+-		last_check = j;
++		last_check = io_sectors;
+ 
+ 		if (test_bit(MD_RECOVERY_INTR, &mddev->recovery) ||
+ 		    test_bit(MD_RECOVERY_ERR, &mddev->recovery))
+@@ -3386,7 +3396,7 @@ static void md_do_sync(mddev_t *mddev)
+ 			mddev->resync_mark = mark[next];
+ 			mddev->resync_mark_cnt = mark_cnt[next];
+ 			mark[next] = jiffies;
+-			mark_cnt[next] = j - atomic_read(&mddev->recovery_active);
++			mark_cnt[next] = io_sectors - atomic_read(&mddev->recovery_active);
+ 			last_mark = next;
+ 		}
+ 
+@@ -3413,7 +3423,8 @@ static void md_do_sync(mddev_t *mddev)
+ 		mddev->queue->unplug_fn(mddev->queue);
+ 		cond_resched();
+ 
+-		currspeed = ((unsigned long)(j-mddev->resync_mark_cnt))/2/((jiffies-mddev->resync_mark)/HZ +1) +1;
++		currspeed = ((unsigned long)(io_sectors-mddev->resync_mark_cnt))/2
++			/((jiffies-mddev->resync_mark)/HZ +1) +1;
+ 
+ 		if (currspeed > sysctl_speed_limit_min) {
+ 			if ((currspeed > sysctl_speed_limit_max) ||
+@@ -3433,7 +3444,7 @@ static void md_do_sync(mddev_t *mddev)
+ 	wait_event(mddev->recovery_wait, !atomic_read(&mddev->recovery_active));
+ 
+ 	/* tell personality that we are finished */
+-	mddev->pers->sync_request(mddev, max_sectors, 1);
++	mddev->pers->sync_request(mddev, max_sectors, &skipped, 1);
+ 
+ 	if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) &&
+ 	    mddev->curr_resync > 2 &&
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index 3f1280bbaf39..3c5c916cb09e 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -1010,7 +1010,7 @@ static int init_resync(conf_t *conf)
+  * that can be installed to exclude normal IO requests.
+  */
+ 
+-static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
++static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
+ {
+ 	conf_t *conf = mddev_to_conf(mddev);
+ 	mirror_info_t *mirror;
+@@ -1023,7 +1023,7 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
+ 
+ 	if (!conf->r1buf_pool)
+ 		if (init_resync(conf))
+-			return -ENOMEM;
++			return 0;
+ 
+ 	max_sector = mddev->size << 1;
+ 	if (sector_nr >= max_sector) {
+@@ -1107,8 +1107,8 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
+ 		/* There is nowhere to write, so all non-sync
+ 		 * drives must be failed - so we are finished
+ 		 */
+-		int rv = max_sector - sector_nr;
+-		md_done_sync(mddev, rv, 1);
++		sector_t rv = max_sector - sector_nr;
++		*skipped = 1;
+ 		put_buf(r1_bio);
+ 		rdev_dec_pending(conf->mirrors[disk].rdev, mddev);
+ 		return rv;
+diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
+index bfc9f52f0ecf..8476515bfdc7 100644
+--- a/drivers/md/raid10.c
++++ b/drivers/md/raid10.c
+@@ -1321,7 +1321,7 @@ static int init_resync(conf_t *conf)
+  *
+  */
+ 
+-static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
++static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
+ {
+ 	conf_t *conf = mddev_to_conf(mddev);
+ 	r10bio_t *r10_bio;
+@@ -1335,7 +1335,7 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
+ 
+ 	if (!conf->r10buf_pool)
+ 		if (init_resync(conf))
+-			return -ENOMEM;
++			return 0;
+ 
+  skipped:
+ 	max_sector = mddev->size << 1;
+@@ -1343,15 +1343,15 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
+ 		max_sector = mddev->resync_max_sectors;
+ 	if (sector_nr >= max_sector) {
+ 		close_sync(conf);
++		*skipped = 1;
+ 		return sectors_skipped;
+ 	}
+ 	if (chunks_skipped >= conf->raid_disks) {
+ 		/* if there has been nothing to do on any drive,
+ 		 * then there is nothing to do at all..
+ 		 */
+-		sector_t sec = max_sector - sector_nr;
+-		md_done_sync(mddev, sec, 1);
+-		return sec + sectors_skipped;
++		*skipped = 1;
++		return (max_sector - sector_nr) + sectors_skipped;
+ 	}
+ 
+ 	/* make sure whole request will fit in a chunk - if chunks
+@@ -1565,17 +1565,22 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
+ 		}
+ 	}
+ 
++	if (sectors_skipped)
++		/* pretend they weren't skipped, it makes
++		 * no important difference in this case
++		 */
++		md_done_sync(mddev, sectors_skipped, 1);
++
+ 	return sectors_skipped + nr_sectors;
+  giveup:
+ 	/* There is nowhere to write, so all non-sync
+ 	 * drives must be failed, so try the next chunk...
+ 	 */
+ 	{
+-	int sec = max_sector - sector_nr;
++	sector_t sec = max_sector - sector_nr;
+ 	sectors_skipped += sec;
+ 	chunks_skipped ++;
+ 	sector_nr = max_sector;
+-	md_done_sync(mddev, sec, 1);
+ 	goto skipped;
+ 	}
+ }
+diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
+index 677ce49078da..1ce3f5aaa984 100644
+--- a/drivers/md/raid5.c
++++ b/drivers/md/raid5.c
+@@ -1477,7 +1477,7 @@ static int make_request (request_queue_t *q, struct bio * bi)
+ }
+ 
+ /* FIXME go_faster isn't used */
+-static int sync_request (mddev_t *mddev, sector_t sector_nr, int go_faster)
++static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
+ {
+ 	raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
+ 	struct stripe_head *sh;
+@@ -1500,8 +1500,8 @@ static int sync_request (mddev_t *mddev, sector_t sector_nr, int go_faster)
+ 	 * nothing we can do.
+ 	 */
+ 	if (mddev->degraded >= 1 && test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
+-		int rv = (mddev->size << 1) - sector_nr;
+-		md_done_sync(mddev, rv, 1);
++		sector_t rv = (mddev->size << 1) - sector_nr;
++		*skipped = 1;
+ 		return rv;
+ 	}
+ 
+diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
+index fede16c4e8f3..d9c385496dc5 100644
+--- a/drivers/md/raid6main.c
++++ b/drivers/md/raid6main.c
+@@ -1636,7 +1636,7 @@ static int make_request (request_queue_t *q, struct bio * bi)
+ }
+ 
+ /* FIXME go_faster isn't used */
+-static int sync_request (mddev_t *mddev, sector_t sector_nr, int go_faster)
++static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
+ {
+ 	raid6_conf_t *conf = (raid6_conf_t *) mddev->private;
+ 	struct stripe_head *sh;
+@@ -1659,8 +1659,8 @@ static int sync_request (mddev_t *mddev, sector_t sector_nr, int go_faster)
+ 	 * nothing we can do.
+ 	 */
+ 	if (mddev->degraded >= 2 && test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
+-		int rv = (mddev->size << 1) - sector_nr;
+-		md_done_sync(mddev, rv, 1);
++		sector_t rv = (mddev->size << 1) - sector_nr;
++		*skipped = 1;
+ 		return rv;
+ 	}
+ 
+diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
+index d92db54255a3..bce0032decff 100644
+--- a/include/linux/raid/md_k.h
++++ b/include/linux/raid/md_k.h
+@@ -298,7 +298,7 @@ struct mdk_personality_s
+ 	int (*hot_add_disk) (mddev_t *mddev, mdk_rdev_t *rdev);
+ 	int (*hot_remove_disk) (mddev_t *mddev, int number);
+ 	int (*spare_active) (mddev_t *mddev);
+-	int (*sync_request)(mddev_t *mddev, sector_t sector_nr, int go_faster);
++	sector_t (*sync_request)(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster);
+ 	int (*resize) (mddev_t *mddev, sector_t sectors);
+ 	int (*reshape) (mddev_t *mddev, int raid_disks);
+ 	int (*reconfig) (mddev_t *mddev, int layout, int chunk_size);

commit 06d91a5fe0b50c9060e70bdf7786f8a3c66249db
+Author: NeilBrown 
+Date:   Tue Jun 21 17:17:12 2005 -0700
+
+    [PATCH] md: improve locking on 'safemode' and move superblock writes
+    
+    When md marks the superblock dirty before a write, it calls
+    generic_make_request (to write the superblock) from within
+    generic_make_request (to write the first dirty block), which could cause
+    problems later.
+    
+    With this patch, the superblock write is always done by the helper thread, and
+    write request are delayed until that write completes.
+    
+    Also, the locking around marking the array dirty and writing the superblock is
+    improved to avoid possible races.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index c842e34d850e..177d2a7d7cea 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -218,6 +218,8 @@ static mddev_t * mddev_find(dev_t unit)
+ 	INIT_LIST_HEAD(&new->all_mddevs);
+ 	init_timer(&new->safemode_timer);
+ 	atomic_set(&new->active, 1);
++	bio_list_init(&new->write_list);
++	spin_lock_init(&new->write_lock);
+ 
+ 	new->queue = blk_alloc_queue(GFP_KERNEL);
+ 	if (!new->queue) {
+@@ -1251,9 +1253,11 @@ static void md_update_sb(mddev_t * mddev)
+ 	int err, count = 100;
+ 	struct list_head *tmp;
+ 	mdk_rdev_t *rdev;
++	int sync_req;
+ 
+-	mddev->sb_dirty = 0;
+ repeat:
++	spin_lock(&mddev->write_lock);
++	sync_req = mddev->in_sync;
+ 	mddev->utime = get_seconds();
+ 	mddev->events ++;
+ 
+@@ -1272,8 +1276,12 @@ static void md_update_sb(mddev_t * mddev)
+ 	 * do not write anything to disk if using
+ 	 * nonpersistent superblocks
+ 	 */
+-	if (!mddev->persistent)
++	if (!mddev->persistent) {
++		mddev->sb_dirty = 0;
++		spin_unlock(&mddev->write_lock);
+ 		return;
++	}
++	spin_unlock(&mddev->write_lock);
+ 
+ 	dprintk(KERN_INFO 
+ 		"md: updating %s RAID superblock on device (in sync %d)\n",
+@@ -1304,6 +1312,15 @@ static void md_update_sb(mddev_t * mddev)
+ 		printk(KERN_ERR \
+ 			"md: excessive errors occurred during superblock update, exiting\n");
+ 	}
++	spin_lock(&mddev->write_lock);
++	if (mddev->in_sync != sync_req) {
++		/* have to write it out again */
++		spin_unlock(&mddev->write_lock);
++		goto repeat;
++	}
++	mddev->sb_dirty = 0;
++	spin_unlock(&mddev->write_lock);
++
+ }
+ 
+ /*
+@@ -3178,19 +3195,31 @@ void md_done_sync(mddev_t *mddev, int blocks, int ok)
+ }
+ 
+ 
+-void md_write_start(mddev_t *mddev)
++/* md_write_start(mddev, bi)
++ * If we need to update some array metadata (e.g. 'active' flag
++ * in superblock) before writing, queue bi for later writing
++ * and return 0, else return 1 and it will be written now
++ */
++int md_write_start(mddev_t *mddev, struct bio *bi)
+ {
+-	if (!atomic_read(&mddev->writes_pending)) {
+-		mddev_lock_uninterruptible(mddev);
+-		if (mddev->in_sync) {
+-			mddev->in_sync = 0;
+- 			del_timer(&mddev->safemode_timer);
+-			md_update_sb(mddev);
+-		}
+-		atomic_inc(&mddev->writes_pending);
+-		mddev_unlock(mddev);
+-	} else
+-		atomic_inc(&mddev->writes_pending);
++	if (bio_data_dir(bi) != WRITE)
++		return 1;
++
++	atomic_inc(&mddev->writes_pending);
++	spin_lock(&mddev->write_lock);
++	if (mddev->in_sync == 0 && mddev->sb_dirty == 0) {
++		spin_unlock(&mddev->write_lock);
++		return 1;
++	}
++	bio_list_add(&mddev->write_list, bi);
++
++	if (mddev->in_sync) {
++		mddev->in_sync = 0;
++		mddev->sb_dirty = 1;
++	}
++	spin_unlock(&mddev->write_lock);
++	md_wakeup_thread(mddev->thread);
++	return 0;
+ }
+ 
+ void md_write_end(mddev_t *mddev)
+@@ -3472,6 +3501,7 @@ void md_check_recovery(mddev_t *mddev)
+ 		mddev->sb_dirty ||
+ 		test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) ||
+ 		test_bit(MD_RECOVERY_DONE, &mddev->recovery) ||
++		mddev->write_list.head ||
+ 		(mddev->safemode == 1) ||
+ 		(mddev->safemode == 2 && ! atomic_read(&mddev->writes_pending)
+ 		 && !mddev->in_sync && mddev->recovery_cp == MaxSector)
+@@ -3480,7 +3510,9 @@ void md_check_recovery(mddev_t *mddev)
+ 
+ 	if (mddev_trylock(mddev)==0) {
+ 		int spares =0;
++		struct bio *blist;
+ 
++		spin_lock(&mddev->write_lock);
+ 		if (mddev->safemode && !atomic_read(&mddev->writes_pending) &&
+ 		    !mddev->in_sync && mddev->recovery_cp == MaxSector) {
+ 			mddev->in_sync = 1;
+@@ -3488,9 +3520,22 @@ void md_check_recovery(mddev_t *mddev)
+ 		}
+ 		if (mddev->safemode == 1)
+ 			mddev->safemode = 0;
++		blist = bio_list_get(&mddev->write_list);
++		spin_unlock(&mddev->write_lock);
+ 
+ 		if (mddev->sb_dirty)
+ 			md_update_sb(mddev);
++
++		while (blist) {
++			struct bio *b = blist;
++			blist = blist->bi_next;
++			b->bi_next = NULL;
++			generic_make_request(b);
++			/* we already counted this, so need to un-count */
++			md_write_end(mddev);
++		}
++
++
+ 		if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) &&
+ 		    !test_bit(MD_RECOVERY_DONE, &mddev->recovery)) {
+ 			/* resync/recovery still happening */
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index b34ad56362df..3f1280bbaf39 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -530,6 +530,8 @@ static int make_request(request_queue_t *q, struct bio * bio)
+ 	 * thread has put up a bar for new requests.
+ 	 * Continue immediately if no resync is active currently.
+ 	 */
++	if (md_write_start(mddev, bio)==0)
++		return 0;
+ 	spin_lock_irq(&conf->resync_lock);
+ 	wait_event_lock_irq(conf->wait_resume, !conf->barrier, conf->resync_lock, );
+ 	conf->nr_pending++;
+@@ -611,7 +613,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
+ 	rcu_read_unlock();
+ 
+ 	atomic_set(&r1_bio->remaining, 1);
+-	md_write_start(mddev);
++
+ 	for (i = 0; i < disks; i++) {
+ 		struct bio *mbio;
+ 		if (!r1_bio->bios[i])
+diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
+index 9ae21504db8a..bfc9f52f0ecf 100644
+--- a/drivers/md/raid10.c
++++ b/drivers/md/raid10.c
+@@ -700,6 +700,9 @@ static int make_request(request_queue_t *q, struct bio * bio)
+ 		return 0;
+ 	}
+ 
++	if (md_write_start(mddev, bio) == 0)
++		return 0;
++
+ 	/*
+ 	 * Register the new request and wait if the reconstruction
+ 	 * thread has put up a bar for new requests.
+@@ -774,7 +777,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
+ 	rcu_read_unlock();
+ 
+ 	atomic_set(&r10_bio->remaining, 1);
+-	md_write_start(mddev);
++
+ 	for (i = 0; i < conf->copies; i++) {
+ 		struct bio *mbio;
+ 		int d = r10_bio->devs[i].devnum;
+diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
+index 63b1c59d36ff..677ce49078da 100644
+--- a/drivers/md/raid5.c
++++ b/drivers/md/raid5.c
+@@ -1411,6 +1411,9 @@ static int make_request (request_queue_t *q, struct bio * bi)
+ 	sector_t logical_sector, last_sector;
+ 	struct stripe_head *sh;
+ 
++	if (md_write_start(mddev, bi)==0)
++		return 0;
++
+ 	if (bio_data_dir(bi)==WRITE) {
+ 		disk_stat_inc(mddev->gendisk, writes);
+ 		disk_stat_add(mddev->gendisk, write_sectors, bio_sectors(bi));
+@@ -1423,8 +1426,7 @@ static int make_request (request_queue_t *q, struct bio * bi)
+ 	last_sector = bi->bi_sector + (bi->bi_size>>9);
+ 	bi->bi_next = NULL;
+ 	bi->bi_phys_segments = 1;	/* over-loaded to count active stripes */
+-	if ( bio_data_dir(bi) == WRITE )
+-		md_write_start(mddev);
++
+ 	for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) {
+ 		DEFINE_WAIT(w);
+ 		
+diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
+index 9d0e0e42a3be..fede16c4e8f3 100644
+--- a/drivers/md/raid6main.c
++++ b/drivers/md/raid6main.c
+@@ -1570,6 +1570,9 @@ static int make_request (request_queue_t *q, struct bio * bi)
+ 	sector_t logical_sector, last_sector;
+ 	struct stripe_head *sh;
+ 
++	if (md_write_start(mddev, bi)==0)
++		return 0;
++
+ 	if (bio_data_dir(bi)==WRITE) {
+ 		disk_stat_inc(mddev->gendisk, writes);
+ 		disk_stat_add(mddev->gendisk, write_sectors, bio_sectors(bi));
+@@ -1583,8 +1586,7 @@ static int make_request (request_queue_t *q, struct bio * bi)
+ 
+ 	bi->bi_next = NULL;
+ 	bi->bi_phys_segments = 1;	/* over-loaded to count active stripes */
+-	if ( bio_data_dir(bi) == WRITE )
+-		md_write_start(mddev);
++
+ 	for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) {
+ 		DEFINE_WAIT(w);
+ 
+diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h
+index a6a67d102bfa..cfde8f497d6d 100644
+--- a/include/linux/raid/md.h
++++ b/include/linux/raid/md.h
+@@ -69,7 +69,7 @@ extern mdk_thread_t * md_register_thread (void (*run) (mddev_t *mddev),
+ extern void md_unregister_thread (mdk_thread_t *thread);
+ extern void md_wakeup_thread(mdk_thread_t *thread);
+ extern void md_check_recovery(mddev_t *mddev);
+-extern void md_write_start(mddev_t *mddev);
++extern int md_write_start(mddev_t *mddev, struct bio *bi);
+ extern void md_write_end(mddev_t *mddev);
+ extern void md_handle_safemode(mddev_t *mddev);
+ extern void md_done_sync(mddev_t *mddev, int blocks, int ok);
+diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
+index c9a0d4013be7..d92db54255a3 100644
+--- a/include/linux/raid/md_k.h
++++ b/include/linux/raid/md_k.h
+@@ -15,6 +15,9 @@
+ #ifndef _MD_K_H
+ #define _MD_K_H
+ 
++/* and dm-bio-list.h is not under include/linux because.... ??? */
++#include "../../../drivers/md/dm-bio-list.h"
++
+ #define MD_RESERVED       0UL
+ #define LINEAR            1UL
+ #define RAID0             2UL
+@@ -252,6 +255,10 @@ struct mddev_s
+ 	atomic_t			recovery_active; /* blocks scheduled, but not written */
+ 	wait_queue_head_t		recovery_wait;
+ 	sector_t			recovery_cp;
++
++	spinlock_t			write_lock;
++	struct bio_list			write_list;
++
+ 	unsigned int			safemode;	/* if set, update "clean" superblock
+ 							 * when no writes pending.
+ 							 */ 

commit fca4d848f0e6fafdc2b25f8a0cf1e76935f13ac2
+Author: NeilBrown 
+Date:   Tue Jun 21 17:17:11 2005 -0700
+
+    [PATCH] md: merge md_enter_safemode into md_check_recovery
+    
+    md_enter_safemode checks if it is time to mark the md superblock as 'clean'.
+    i.e.  if all writes have completed and a suitable delay has passed.
+    
+    This is currently called from md_handle_safemode which in-turn is called
+    (almost) every time md_check_recovery is called, and from the end of
+    md_do_sync which causes the mddev->thread to run, which will always call
+    md_check_recovery as well.
+    
+    So it doesn't need to be a separate function and fits quite well into
+    md_check_recovery.
+    
+    The "almost" is because multipathd calls md_check_recovery but not
+    md_handle_safemode.  This is OK because the code from md_enter_safemode is a
+    no-op if mddev->safemode == 0, which it always is for a multipathd (providing
+    we don't allow it to be set to 2 on a signal...)
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 60835dfd058e..c842e34d850e 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -3203,37 +3203,6 @@ void md_write_end(mddev_t *mddev)
+ 	}
+ }
+ 
+-static inline void md_enter_safemode(mddev_t *mddev)
+-{
+-	if (!mddev->safemode) return;
+-	if (mddev->safemode == 2 &&
+-	    (atomic_read(&mddev->writes_pending) || mddev->in_sync ||
+-		    mddev->recovery_cp != MaxSector))
+-		return; /* avoid the lock */
+-	mddev_lock_uninterruptible(mddev);
+-	if (mddev->safemode && !atomic_read(&mddev->writes_pending) &&
+-	    !mddev->in_sync && mddev->recovery_cp == MaxSector) {
+-		mddev->in_sync = 1;
+-		md_update_sb(mddev);
+-	}
+-	mddev_unlock(mddev);
+-
+-	if (mddev->safemode == 1)
+-		mddev->safemode = 0;
+-}
+-
+-void md_handle_safemode(mddev_t *mddev)
+-{
+-	if (signal_pending(current)) {
+-		printk(KERN_INFO "md: %s in immediate safe mode\n",
+-			mdname(mddev));
+-		mddev->safemode = 2;
+-		flush_signals(current);
+-	}
+-	md_enter_safemode(mddev);
+-}
+-
+-
+ static DECLARE_WAIT_QUEUE_HEAD(resync_wait);
+ 
+ #define SYNC_MARKS	10
+@@ -3449,7 +3418,6 @@ static void md_do_sync(mddev_t *mddev)
+ 			mddev->recovery_cp = MaxSector;
+ 	}
+ 
+-	md_enter_safemode(mddev);
+  skip:
+ 	mddev->curr_resync = 0;
+ 	wake_up(&resync_wait);
+@@ -3490,14 +3458,37 @@ void md_check_recovery(mddev_t *mddev)
+ 
+ 	if (mddev->ro)
+ 		return;
++
++	if (signal_pending(current)) {
++		if (mddev->pers->sync_request) {
++			printk(KERN_INFO "md: %s in immediate safe mode\n",
++			       mdname(mddev));
++			mddev->safemode = 2;
++		}
++		flush_signals(current);
++	}
++
+ 	if ( ! (
+ 		mddev->sb_dirty ||
+ 		test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) ||
+-		test_bit(MD_RECOVERY_DONE, &mddev->recovery)
++		test_bit(MD_RECOVERY_DONE, &mddev->recovery) ||
++		(mddev->safemode == 1) ||
++		(mddev->safemode == 2 && ! atomic_read(&mddev->writes_pending)
++		 && !mddev->in_sync && mddev->recovery_cp == MaxSector)
+ 		))
+ 		return;
++
+ 	if (mddev_trylock(mddev)==0) {
+ 		int spares =0;
++
++		if (mddev->safemode && !atomic_read(&mddev->writes_pending) &&
++		    !mddev->in_sync && mddev->recovery_cp == MaxSector) {
++			mddev->in_sync = 1;
++			mddev->sb_dirty = 1;
++		}
++		if (mddev->safemode == 1)
++			mddev->safemode = 0;
++
+ 		if (mddev->sb_dirty)
+ 			md_update_sb(mddev);
+ 		if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) &&
+@@ -3741,7 +3732,6 @@ EXPORT_SYMBOL(md_error);
+ EXPORT_SYMBOL(md_done_sync);
+ EXPORT_SYMBOL(md_write_start);
+ EXPORT_SYMBOL(md_write_end);
+-EXPORT_SYMBOL(md_handle_safemode);
+ EXPORT_SYMBOL(md_register_thread);
+ EXPORT_SYMBOL(md_unregister_thread);
+ EXPORT_SYMBOL(md_wakeup_thread);
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index 4947f599b652..b34ad56362df 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -931,7 +931,6 @@ static void raid1d(mddev_t *mddev)
+ 	mdk_rdev_t *rdev;
+ 
+ 	md_check_recovery(mddev);
+-	md_handle_safemode(mddev);
+ 	
+ 	for (;;) {
+ 		char b[BDEVNAME_SIZE];
+diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
+index 3c37be6423d7..9ae21504db8a 100644
+--- a/drivers/md/raid10.c
++++ b/drivers/md/raid10.c
+@@ -1216,7 +1216,6 @@ static void raid10d(mddev_t *mddev)
+ 	mdk_rdev_t *rdev;
+ 
+ 	md_check_recovery(mddev);
+-	md_handle_safemode(mddev);
+ 
+ 	for (;;) {
+ 		char b[BDEVNAME_SIZE];
+diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
+index 3cb11ac232fa..63b1c59d36ff 100644
+--- a/drivers/md/raid5.c
++++ b/drivers/md/raid5.c
+@@ -1546,7 +1546,6 @@ static void raid5d (mddev_t *mddev)
+ 	PRINTK("+++ raid5d active\n");
+ 
+ 	md_check_recovery(mddev);
+-	md_handle_safemode(mddev);
+ 
+ 	handled = 0;
+ 	spin_lock_irq(&conf->device_lock);
+diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
+index 908edd78a792..9d0e0e42a3be 100644
+--- a/drivers/md/raid6main.c
++++ b/drivers/md/raid6main.c
+@@ -1705,7 +1705,6 @@ static void raid6d (mddev_t *mddev)
+ 	PRINTK("+++ raid6d active\n");
+ 
+ 	md_check_recovery(mddev);
+-	md_handle_safemode(mddev);
+ 
+ 	handled = 0;
+ 	spin_lock_irq(&conf->device_lock);

commit c361777fb9347a4d16b82272f7d3b234e94bef2d
+Author: NeilBrown 
+Date:   Tue Jun 21 17:17:10 2005 -0700
+
+    [PATCH] md: make sure recovery happens when add_new_disk is used for hot_add
+    
+    Currently if add_new_disk is used to hot-add a drive to a degraded array,
+    recovery doesn't start ...  because we didn't tell it to.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index d899204d3743..60835dfd058e 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -2083,6 +2083,8 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
+ 		err = bind_rdev_to_array(rdev, mddev);
+ 		if (err)
+ 			export_rdev(rdev);
++
++		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+ 		if (mddev->thread)
+ 			md_wakeup_thread(mddev->thread);
+ 		return err;

commit 6ea9c07c6c6d1c14d9757dd8470dc4c85bbe9f28
+Author: NeilBrown 
+Date:   Tue Jun 21 17:17:09 2005 -0700
+
+    [PATCH] md: cause md/raid1 to "repack" working devices when number of drives is changed
+    
+    i.e.  missing or failed drives are moved to the end of the list.  The means
+    a 3 drive md array with the first drive missing can be shrunk to a two
+    drive array.  Currently that isn't possible.
+    
+    Also, the "last_used" device number might be out-of-range after the number
+    of devices is reduced, so we set it to 0.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index 1db5de52d376..4947f599b652 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -1349,17 +1349,26 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
+ 	 * We allocate a new r1bio_pool if we can.
+ 	 * Then raise a device barrier and wait until all IO stops.
+ 	 * Then resize conf->mirrors and swap in the new r1bio pool.
++	 *
++	 * At the same time, we "pack" the devices so that all the missing
++	 * devices have the higher raid_disk numbers.
+ 	 */
+ 	mempool_t *newpool, *oldpool;
+ 	struct pool_info *newpoolinfo;
+ 	mirror_info_t *newmirrors;
+ 	conf_t *conf = mddev_to_conf(mddev);
++	int cnt;
+ 
+-	int d;
++	int d, d2;
+ 
+-	for (d= raid_disks; d < conf->raid_disks; d++)
+-		if (conf->mirrors[d].rdev)
++	if (raid_disks < conf->raid_disks) {
++		cnt=0;
++		for (d= 0; d < conf->raid_disks; d++)
++			if (conf->mirrors[d].rdev)
++				cnt++;
++		if (cnt > raid_disks)
+ 			return -EBUSY;
++	}
+ 
+ 	newpoolinfo = kmalloc(sizeof(*newpoolinfo), GFP_KERNEL);
+ 	if (!newpoolinfo)
+@@ -1390,8 +1399,12 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
+ 	/* ok, everything is stopped */
+ 	oldpool = conf->r1bio_pool;
+ 	conf->r1bio_pool = newpool;
+-	for (d=0; d < raid_disks && d < conf->raid_disks; d++)
+-		newmirrors[d] = conf->mirrors[d];
++
++	for (d=d2=0; d < conf->raid_disks; d++)
++		if (conf->mirrors[d].rdev) {
++			conf->mirrors[d].rdev->raid_disk = d2;
++			newmirrors[d2++].rdev = conf->mirrors[d].rdev;
++		}
+ 	kfree(conf->mirrors);
+ 	conf->mirrors = newmirrors;
+ 	kfree(conf->poolinfo);
+@@ -1400,6 +1413,7 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
+ 	mddev->degraded += (raid_disks - conf->raid_disks);
+ 	conf->raid_disks = mddev->raid_disks = raid_disks;
+ 
++	conf->last_used = 0; /* just make sure it is in-range */
+ 	spin_lock_irq(&conf->resync_lock);
+ 	conf->barrier--;
+ 	spin_unlock_irq(&conf->resync_lock);

commit 7a5febe9ffeecd1e78c5b505260ccc1ef18021b4
+Author: NeilBrown 
+Date:   Mon May 16 21:53:16 2005 -0700
+
+    [PATCH] md: set the unplug_fn and issue_flush_fn for md devices *after* committed to creation
+    
+    We we set the too early, they may still be in place and possibly get called
+    even though the array didn't get set up properly.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
+index 4e4bfde3db5d..2ae2d709cb15 100644
+--- a/drivers/md/multipath.c
++++ b/drivers/md/multipath.c
+@@ -462,10 +462,6 @@ static int multipath_run (mddev_t *mddev)
+ 	}
+ 	memset(conf->multipaths, 0, sizeof(struct multipath_info)*mddev->raid_disks);
+ 
+-	mddev->queue->unplug_fn = multipath_unplug;
+-
+-	mddev->queue->issue_flush_fn = multipath_issue_flush;
+-
+ 	conf->working_disks = 0;
+ 	ITERATE_RDEV(mddev,rdev,tmp) {
+ 		disk_idx = rdev->raid_disk;
+@@ -528,6 +524,10 @@ static int multipath_run (mddev_t *mddev)
+ 	 * Ok, everything is just fine now
+ 	 */
+ 	mddev->array_size = mddev->size;
++
++	mddev->queue->unplug_fn = multipath_unplug;
++	mddev->queue->issue_flush_fn = multipath_issue_flush;
++
+ 	return 0;
+ 
+ out_free_conf:
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index 83380b5d6593..1db5de52d376 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -1197,10 +1197,6 @@ static int run(mddev_t *mddev)
+ 	if (!conf->r1bio_pool)
+ 		goto out_no_mem;
+ 
+-	mddev->queue->unplug_fn = raid1_unplug;
+-
+-	mddev->queue->issue_flush_fn = raid1_issue_flush;
+-
+ 	ITERATE_RDEV(mddev, rdev, tmp) {
+ 		disk_idx = rdev->raid_disk;
+ 		if (disk_idx >= mddev->raid_disks
+@@ -1282,6 +1278,9 @@ static int run(mddev_t *mddev)
+ 	 */
+ 	mddev->array_size = mddev->size;
+ 
++	mddev->queue->unplug_fn = raid1_unplug;
++	mddev->queue->issue_flush_fn = raid1_issue_flush;
++
+ 	return 0;
+ 
+ out_no_mem:
+diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
+index e9dc2876a626..3c37be6423d7 100644
+--- a/drivers/md/raid10.c
++++ b/drivers/md/raid10.c
+@@ -1639,9 +1639,6 @@ static int run(mddev_t *mddev)
+ 			mdname(mddev));
+ 		goto out_free_conf;
+ 	}
+-	mddev->queue->unplug_fn = raid10_unplug;
+-
+-	mddev->queue->issue_flush_fn = raid10_issue_flush;
+ 
+ 	ITERATE_RDEV(mddev, rdev, tmp) {
+ 		disk_idx = rdev->raid_disk;
+@@ -1713,6 +1710,9 @@ static int run(mddev_t *mddev)
+ 	mddev->array_size = size/2;
+ 	mddev->resync_max_sectors = size;
+ 
++	mddev->queue->unplug_fn = raid10_unplug;
++	mddev->queue->issue_flush_fn = raid10_issue_flush;
++
+ 	/* Calculate max read-ahead size.
+ 	 * We need to readahead at least twice a whole stripe....
+ 	 * maybe...
+diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
+index e96e2a10a9c9..3cb11ac232fa 100644
+--- a/drivers/md/raid5.c
++++ b/drivers/md/raid5.c
+@@ -1620,9 +1620,6 @@ static int run (mddev_t *mddev)
+ 	atomic_set(&conf->active_stripes, 0);
+ 	atomic_set(&conf->preread_active_stripes, 0);
+ 
+-	mddev->queue->unplug_fn = raid5_unplug_device;
+-	mddev->queue->issue_flush_fn = raid5_issue_flush;
+-
+ 	PRINTK("raid5: run(%s) called.\n", mdname(mddev));
+ 
+ 	ITERATE_RDEV(mddev,rdev,tmp) {
+@@ -1728,6 +1725,10 @@ memory = conf->max_nr_stripes * (sizeof(struct stripe_head) +
+ 	}
+ 
+ 	/* Ok, everything is just fine now */
++
++	mddev->queue->unplug_fn = raid5_unplug_device;
++	mddev->queue->issue_flush_fn = raid5_issue_flush;
++
+ 	mddev->array_size =  mddev->size * (mddev->raid_disks - 1);
+ 	return 0;
+ abort:
+diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
+index 8a33f351e092..908edd78a792 100644
+--- a/drivers/md/raid6main.c
++++ b/drivers/md/raid6main.c
+@@ -1779,9 +1779,6 @@ static int run (mddev_t *mddev)
+ 	atomic_set(&conf->active_stripes, 0);
+ 	atomic_set(&conf->preread_active_stripes, 0);
+ 
+-	mddev->queue->unplug_fn = raid6_unplug_device;
+-	mddev->queue->issue_flush_fn = raid6_issue_flush;
+-
+ 	PRINTK("raid6: run(%s) called.\n", mdname(mddev));
+ 
+ 	ITERATE_RDEV(mddev,rdev,tmp) {
+@@ -1895,6 +1892,9 @@ static int run (mddev_t *mddev)
+ 
+ 	/* Ok, everything is just fine now */
+ 	mddev->array_size =  mddev->size * (mddev->raid_disks - 2);
++
++	mddev->queue->unplug_fn = raid6_unplug_device;
++	mddev->queue->issue_flush_fn = raid6_issue_flush;
+ 	return 0;
+ abort:
+ 	if (conf) {

commit 29ac8e056f2016a8404edc02749d095019aa1f82
+Author: NeilBrown 
+Date:   Mon May 16 21:53:15 2005 -0700
+
+    [PATCH] md: fix splitting of md/linear request that cross a device boundary
+    
+    When a request crosses a boundary between devices, it needs to be split.
+    But where we should calculate the amount of the request before the boundary
+    to find the split-point, we care currently calculating the amount that is
+    *after* the boundary !!!
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/linear.c b/drivers/md/linear.c
+index 161e9aa87291..b1941b887f46 100644
+--- a/drivers/md/linear.c
++++ b/drivers/md/linear.c
+@@ -269,9 +269,8 @@ static int linear_make_request (request_queue_t *q, struct bio *bio)
+ 		 * split it.
+ 		 */
+ 		struct bio_pair *bp;
+-		bp = bio_split(bio, bio_split_pool, 
+-			       (bio->bi_sector + (bio->bi_size >> 9) -
+-				(tmp_dev->offset + tmp_dev->size))<<1);
++		bp = bio_split(bio, bio_split_pool,
++			       ((tmp_dev->offset + tmp_dev->size)<<1) - bio->bi_sector);
+ 		if (linear_make_request(q, &bp->bio1))
+ 			generic_make_request(&bp->bio1);
+ 		if (linear_make_request(q, &bp->bio2))

commit a757e64cfa400391041ed7953f0290c34a820c93
+Author: NeilBrown 
+Date:   Sat Apr 16 15:26:42 2005 -0700
+
+    [PATCH] md: remove a number of misleading calls to MD_BUG
+    
+    The conditions that cause these calls to MD_BUG are not kernel bugs, just
+    oddities in what userspace is asking for.
+    
+    Also convert analyze_sbs to return void, and the value it returned was
+    always 0.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 44a164965546..97af857d8a88 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -1387,7 +1387,7 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi
+  */
+ 
+ 
+-static int analyze_sbs(mddev_t * mddev)
++static void analyze_sbs(mddev_t * mddev)
+ {
+ 	int i;
+ 	struct list_head *tmp;
+@@ -1441,7 +1441,6 @@ static int analyze_sbs(mddev_t * mddev)
+ 		       " -- starting background reconstruction\n",
+ 		       mdname(mddev));
+ 
+-	return 0;
+ }
+ 
+ int mdp_major = 0;
+@@ -1508,10 +1507,9 @@ static int do_md_run(mddev_t * mddev)
+ 	struct gendisk *disk;
+ 	char b[BDEVNAME_SIZE];
+ 
+-	if (list_empty(&mddev->disks)) {
+-		MD_BUG();
++	if (list_empty(&mddev->disks))
++		/* cannot run an array with no devices.. */
+ 		return -EINVAL;
+-	}
+ 
+ 	if (mddev->pers)
+ 		return -EBUSY;
+@@ -1519,10 +1517,8 @@ static int do_md_run(mddev_t * mddev)
+ 	/*
+ 	 * Analyze all RAID superblock(s)
+ 	 */
+-	if (!mddev->raid_disks && analyze_sbs(mddev)) {
+-		MD_BUG();
+-		return -EINVAL;
+-	}
++	if (!mddev->raid_disks)
++		analyze_sbs(mddev);
+ 
+ 	chunk_size = mddev->chunk_size;
+ 	pnum = level_to_pers(mddev->level);
+@@ -1548,7 +1544,7 @@ static int do_md_run(mddev_t * mddev)
+ 		 * chunk-size has to be a power of 2 and multiples of PAGE_SIZE
+ 		 */
+ 		if ( (1 << ffz(~chunk_size)) != chunk_size) {
+-			MD_BUG();
++			printk(KERN_ERR "chunk_size of %d not valid\n", chunk_size);
+ 			return -EINVAL;
+ 		}
+ 		if (chunk_size < PAGE_SIZE) {
+@@ -1573,11 +1569,6 @@ static int do_md_run(mddev_t * mddev)
+ 		}
+ 	}
+ 
+-	if (pnum >= MAX_PERSONALITY) {
+-		MD_BUG();
+-		return -EINVAL;
+-	}
+-
+ #ifdef CONFIG_KMOD
+ 	if (!pers[pnum])
+ 	{
+@@ -1762,10 +1753,8 @@ static void autorun_array(mddev_t *mddev)
+ 	struct list_head *tmp;
+ 	int err;
+ 
+-	if (list_empty(&mddev->disks)) {
+-		MD_BUG();
++	if (list_empty(&mddev->disks))
+ 		return;
+-	}
+ 
+ 	printk(KERN_INFO "md: running: ");
+ 
+@@ -3128,7 +3117,6 @@ int register_md_personality(int pnum, mdk_personality_t *p)
+ 	spin_lock(&pers_lock);
+ 	if (pers[pnum]) {
+ 		spin_unlock(&pers_lock);
+-		MD_BUG();
+ 		return -EBUSY;
+ 	}
+ 
+@@ -3140,10 +3128,8 @@ int register_md_personality(int pnum, mdk_personality_t *p)
+ 
+ int unregister_md_personality(int pnum)
+ {
+-	if (pnum >= MAX_PERSONALITY) {
+-		MD_BUG();
++	if (pnum >= MAX_PERSONALITY)
+ 		return -EINVAL;
+-	}
+ 
+ 	printk(KERN_INFO "md: %s personality unregistered\n", pers[pnum]->name);
+ 	spin_lock(&pers_lock);

commit d28446fe2d87ea344c14741c39962dcc7aee5c78
+Author: NeilBrown 
+Date:   Sat Apr 16 15:26:41 2005 -0700
+
+    [PATCH] md: close a small race in md thread deregistration
+    
+    There is a tiny race when de-registering an MD thread, in that the thread
+    could disappear before it is set a SIGKILL, causing send_sig to have
+    problems.
+    
+    This is most easily closed by holding tasklist_lock between enabling the
+    thread to exit (setting ->run to NULL) and telling it to exit.
+    
+    (akpm: ick.  Needs to use kthread API and stop using signals)
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index aa72c88a024f..44a164965546 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -2840,16 +2840,6 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
+ 	return thread;
+ }
+ 
+-static void md_interrupt_thread(mdk_thread_t *thread)
+-{
+-	if (!thread->tsk) {
+-		MD_BUG();
+-		return;
+-	}
+-	dprintk("interrupting MD-thread pid %d\n", thread->tsk->pid);
+-	send_sig(SIGKILL, thread->tsk, 1);
+-}
+-
+ void md_unregister_thread(mdk_thread_t *thread)
+ {
+ 	struct completion event;
+@@ -2857,9 +2847,15 @@ void md_unregister_thread(mdk_thread_t *thread)
+ 	init_completion(&event);
+ 
+ 	thread->event = &event;
++
++	/* As soon as ->run is set to NULL, the task could disappear,
++	 * so we need to hold tasklist_lock until we have sent the signal
++	 */
++	dprintk("interrupting MD-thread pid %d\n", thread->tsk->pid);
++	read_lock(&tasklist_lock);
+ 	thread->run = NULL;
+-	thread->name = NULL;
+-	md_interrupt_thread(thread);
++	send_sig(SIGKILL, thread->tsk, 1);
++	read_unlock(&tasklist_lock);
+ 	wait_for_completion(&event);
+ 	kfree(thread);
+ }

commit c907132d534c10b4f34a60383c8384403cb424a4
+Author: NeilBrown 
+Date:   Sat Apr 16 15:26:38 2005 -0700
+
+    [PATCH] nfsd4: fix struct file leak
+    
+    We were failing to close on an error path, resulting in a leak of struct files
+    which could take a v4 server down fairly quickly....  So call
+    nfs4_close_delegation instead of just open-coding parts of it.
+    
+    Simplify the cleanup on delegation failure while we're at it.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 579f7fea7968..75e8b137580c 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -190,7 +190,8 @@ nfs4_close_delegation(struct nfs4_delegation *dp)
+ 	dp->dl_vfs_file = NULL;
+ 	/* The following nfsd_close may not actually close the file,
+ 	 * but we want to remove the lease in any case. */
+-	setlease(filp, F_UNLCK, &dp->dl_flock);
++	if (dp->dl_flock)
++		setlease(filp, F_UNLCK, &dp->dl_flock);
+ 	nfsd_close(filp);
+ 	vfsclose++;
+ }
+@@ -1673,10 +1674,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
+ 	if ((status = setlease(stp->st_vfs_file,
+ 		flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK, &flp))) {
+ 		dprintk("NFSD: setlease failed [%d], no delegation\n", status);
+-		list_del(&dp->dl_del_perfile);
+-		list_del(&dp->dl_del_perclnt);
+-		nfs4_put_delegation(dp);
+-		free_delegation++;
++		unhash_delegation(dp);
+ 		flag = NFS4_OPEN_DELEGATE_NONE;
+ 		goto out;
+ 	}

commit f1ee4f22f21d74bc3ca63b95ca5b63d3a8620527
+Author: NeilBrown 
+Date:   Sat Apr 16 15:26:38 2005 -0700
+
+    [PATCH] nfsd4: callback create rpc client returns
+    
+    rpc_create_clnt and friends return errors, not NULL, on failure.
+    
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index c70de9c2af74..1a55dfcb74bc 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -405,7 +405,8 @@ nfsd4_probe_callback(struct nfs4_client *clp)
+ 	timeparms.to_exponential = 1;
+ 
+ 	/* Create RPC transport */
+-	if (!(xprt = xprt_create_proto(IPPROTO_TCP, &addr, &timeparms))) {
++	xprt = xprt_create_proto(IPPROTO_TCP, &addr, &timeparms);
++	if (IS_ERR(xprt)) {
+ 		dprintk("NFSD: couldn't create callback transport!\n");
+ 		goto out_err;
+ 	}
+@@ -426,7 +427,8 @@ nfsd4_probe_callback(struct nfs4_client *clp)
+ 	 * XXX AUTH_UNIX only - need AUTH_GSS....
+ 	 */
+ 	sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(addr.sin_addr.s_addr));
+-	if (!(clnt = rpc_create_client(xprt, hostname, program, 1, RPC_AUTH_UNIX))) {
++	clnt = rpc_create_client(xprt, hostname, program, 1, RPC_AUTH_UNIX);
++	if (IS_ERR(clnt)) {
+ 		dprintk("NFSD: couldn't create callback client\n");
+ 		goto out_xprt;
+ 	}

commit 9e416052f1462801ca857c7536288bac0621615e
+Author: NeilBrown 
+Date:   Sat Apr 16 15:26:37 2005 -0700
+
+    [PATCH] nfsd: clear signals before exiting the nfsd() thread
+    
+    Fixes the error "RPC: failed to contact portmap (errno -512)." when the server
+    later tries to unregister from the portmapper.
+    
+    Signed-off-by: Trond Myklebust 
+    Signed-off-by: J. Bruce Fields 
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
+index 39551657e656..02ded7cfbdcf 100644
+--- a/fs/nfsd/nfssvc.c
++++ b/fs/nfsd/nfssvc.c
+@@ -258,6 +258,8 @@ nfsd(struct svc_rqst *rqstp)
+ 				break;
+ 		err = signo;
+ 	}
++	/* Clear signals before calling lockd_down() and svc_exit_thread() */
++	flush_signals(current);
+ 
+ 	lock_kernel();
+ 

commit baaa2c512dc1c47e3afeb9d558c5323c9240bd21
+Author: Neil Brown 
+Date:   Sat Apr 16 15:23:54 2005 -0700
+
+    [PATCH] Avoid deadlock in sync_page_io by using GFP_NOIO
+    
+    ..as sync_page_io can be called on the write-out path.
+    
+    Signed-off-by: Neil Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 04562add1920..aa72c88a024f 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -332,7 +332,7 @@ static int bi_complete(struct bio *bio, unsigned int bytes_done, int error)
+ static int sync_page_io(struct block_device *bdev, sector_t sector, int size,
+ 		   struct page *page, int rw)
+ {
+-	struct bio *bio = bio_alloc(GFP_KERNEL, 1);
++	struct bio *bio = bio_alloc(GFP_NOIO, 1);
+ 	struct completion event;
+ 	int ret;
+ 

commit e354597cce8d219d135d65e585dc4f30323486b9
+Author: Peter Chubb 
+Date:   Mon Oct 13 11:49:04 2008 +1100
+
+    PCI: fix 64-vbit prefetchable memory resource BARs
+    
+    Since patch 6ac665c63dcac8fcec534a1d224ecbb8b867ad59 my infiniband
+    controller hasn't worked.  This is because it has 64-bit prefetchable
+    memory, which was mistakenly being  taken to be 32-bit memory.  The
+    resource flags in this case are PCI_BASE_ADDRESS_MEM_TYPE_64 |
+    PCI_BASE_ADDRESS_MEM_PREFETCH.
+    
+    This patch checks only for the PCI_BASE_ADDRESS_MEM_TYPE_64 bit; thus
+    whether the region is prefetchable or not is ignored.  This fixes my
+    Infiniband.
+    
+    Reviewed-by: Matthew Wilcox 
+    Signed-off-by: Peter Chubb 
+    Signed-off-by: Jesse Barnes 
+
+diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
+index f6754e87f046..49599ac49bda 100644
+--- a/drivers/pci/probe.c
++++ b/drivers/pci/probe.c
+@@ -217,7 +217,7 @@ static inline enum pci_bar_type decode_bar(struct resource *res, u32 bar)
+ 
+ 	res->flags = bar & ~PCI_BASE_ADDRESS_MEM_MASK;
+ 
+-	if (res->flags == PCI_BASE_ADDRESS_MEM_TYPE_64)
++	if (res->flags & PCI_BASE_ADDRESS_MEM_TYPE_64)
+ 		return pci_bar_mem64;
+ 	return pci_bar_mem32;
+ }

commit 45333d5a31296d0af886d94f1d08f128231cab8e
+Author: Aaron Carroll 
+Date:   Tue Aug 26 15:52:36 2008 +0200
+
+    cfq-iosched: fix queue depth detection
+    
+    CFQ's detection of queueing devices assumes a non-queuing device and detects
+    if the queue depth reaches a certain threshold.  Under some workloads (e.g.
+    synchronous reads), CFQ effectively forces a unit queue depth, thus defeating
+    the detection logic.  This leads to poor performance on queuing hardware,
+    since the idle window remains enabled.
+    
+    This patch inverts the sense of the logic: assume a queuing-capable device,
+    and detect if the depth does not exceed the threshold.
+    
+    Signed-off-by: Aaron Carroll 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
+index 5f6fd287c185..494b6fdcb183 100644
+--- a/block/cfq-iosched.c
++++ b/block/cfq-iosched.c
+@@ -39,6 +39,7 @@ static int cfq_slice_idle = HZ / 125;
+ #define CFQ_MIN_TT		(2)
+ 
+ #define CFQ_SLICE_SCALE		(5)
++#define CFQ_HW_QUEUE_MIN	(5)
+ 
+ #define RQ_CIC(rq)		\
+ 	((struct cfq_io_context *) (rq)->elevator_private)
+@@ -86,7 +87,14 @@ struct cfq_data {
+ 
+ 	int rq_in_driver;
+ 	int sync_flight;
++
++	/*
++	 * queue-depth detection
++	 */
++	int rq_queued;
+ 	int hw_tag;
++	int hw_tag_samples;
++	int rq_in_driver_peak;
+ 
+ 	/*
+ 	 * idle window management
+@@ -654,15 +662,6 @@ static void cfq_activate_request(struct request_queue *q, struct request *rq)
+ 	cfq_log_cfqq(cfqd, RQ_CFQQ(rq), "activate rq, drv=%d",
+ 						cfqd->rq_in_driver);
+ 
+-	/*
+-	 * If the depth is larger 1, it really could be queueing. But lets
+-	 * make the mark a little higher - idling could still be good for
+-	 * low queueing, and a low queueing number could also just indicate
+-	 * a SCSI mid layer like behaviour where limit+1 is often seen.
+-	 */
+-	if (!cfqd->hw_tag && cfqd->rq_in_driver > 4)
+-		cfqd->hw_tag = 1;
+-
+ 	cfqd->last_position = rq->hard_sector + rq->hard_nr_sectors;
+ }
+ 
+@@ -686,6 +685,7 @@ static void cfq_remove_request(struct request *rq)
+ 	list_del_init(&rq->queuelist);
+ 	cfq_del_rq_rb(rq);
+ 
++	cfqq->cfqd->rq_queued--;
+ 	if (rq_is_meta(rq)) {
+ 		WARN_ON(!cfqq->meta_pending);
+ 		cfqq->meta_pending--;
+@@ -1833,6 +1833,7 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
+ {
+ 	struct cfq_io_context *cic = RQ_CIC(rq);
+ 
++	cfqd->rq_queued++;
+ 	if (rq_is_meta(rq))
+ 		cfqq->meta_pending++;
+ 
+@@ -1880,6 +1881,31 @@ static void cfq_insert_request(struct request_queue *q, struct request *rq)
+ 	cfq_rq_enqueued(cfqd, cfqq, rq);
+ }
+ 
++/*
++ * Update hw_tag based on peak queue depth over 50 samples under
++ * sufficient load.
++ */
++static void cfq_update_hw_tag(struct cfq_data *cfqd)
++{
++	if (cfqd->rq_in_driver > cfqd->rq_in_driver_peak)
++		cfqd->rq_in_driver_peak = cfqd->rq_in_driver;
++
++	if (cfqd->rq_queued <= CFQ_HW_QUEUE_MIN &&
++	    cfqd->rq_in_driver <= CFQ_HW_QUEUE_MIN)
++		return;
++
++	if (cfqd->hw_tag_samples++ < 50)
++		return;
++
++	if (cfqd->rq_in_driver_peak >= CFQ_HW_QUEUE_MIN)
++		cfqd->hw_tag = 1;
++	else
++		cfqd->hw_tag = 0;
++
++	cfqd->hw_tag_samples = 0;
++	cfqd->rq_in_driver_peak = 0;
++}
++
+ static void cfq_completed_request(struct request_queue *q, struct request *rq)
+ {
+ 	struct cfq_queue *cfqq = RQ_CFQQ(rq);
+@@ -1890,6 +1916,8 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq)
+ 	now = jiffies;
+ 	cfq_log_cfqq(cfqd, cfqq, "complete");
+ 
++	cfq_update_hw_tag(cfqd);
++
+ 	WARN_ON(!cfqd->rq_in_driver);
+ 	WARN_ON(!cfqq->dispatched);
+ 	cfqd->rq_in_driver--;
+@@ -2200,6 +2228,7 @@ static void *cfq_init_queue(struct request_queue *q)
+ 	cfqd->cfq_slice[1] = cfq_slice_sync;
+ 	cfqd->cfq_slice_async_rq = cfq_slice_async_rq;
+ 	cfqd->cfq_slice_idle = cfq_slice_idle;
++	cfqd->hw_tag = 1;
+ 
+ 	return cfqd;
+ }

commit 6a421c1dc94b12923294a359822346f12492de5e
+Author: Aaron Carroll 
+Date:   Thu Aug 14 18:17:15 2008 +1000
+
+    block: update documentation for deadline fifo_batch tunable
+    
+    Update the description of fifo_batch to match the current implementation,
+    and include a description of how to tune it.
+    
+    Signed-off-by: Aaron Carroll 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/Documentation/block/deadline-iosched.txt b/Documentation/block/deadline-iosched.txt
+index c23cab13c3d1..72576769e0f4 100644
+--- a/Documentation/block/deadline-iosched.txt
++++ b/Documentation/block/deadline-iosched.txt
+@@ -30,12 +30,18 @@ write_expire	(in ms)
+ Similar to read_expire mentioned above, but for writes.
+ 
+ 
+-fifo_batch
++fifo_batch	(number of requests)
+ ----------
+ 
+-When a read request expires its deadline, we must move some requests from
+-the sorted io scheduler list to the block device dispatch queue. fifo_batch
+-controls how many requests we move.
++Requests are grouped into ``batches'' of a particular data direction (read or
++write) which are serviced in increasing sector order.  To limit extra seeking,
++deadline expiries are only checked between batches.  fifo_batch controls the
++maximum number of requests per batch.
++
++This parameter tunes the balance between per-request latency and aggregate
++throughput.  When low latency is the primary concern, smaller is better (where
++a value of 1 yields first-come first-served behaviour).  Increasing fifo_batch
++generally improves throughput, at the cost of latency variation.
+ 
+ 
+ writes_starved	(number of dispatches)

commit 4fb72f7646e86874eb2798256eaa6bf3fbe4edcf
+Author: Aaron Carroll 
+Date:   Thu Aug 14 18:17:14 2008 +1000
+
+    deadline-iosched: non-functional fixes
+    
+    * convert goto to simpler while loop;
+     * use rq_end_sector() instead of computing manually;
+     * fix false comments;
+     * remove spurious whitespace;
+     * convert rq_rb_root macro to an inline function.
+    
+    Signed-off-by: Aaron Carroll 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c
+index 07b80e4642f9..fd311179f44c 100644
+--- a/block/deadline-iosched.c
++++ b/block/deadline-iosched.c
+@@ -33,7 +33,7 @@ struct deadline_data {
+ 	 */
+ 	struct rb_root sort_list[2];	
+ 	struct list_head fifo_list[2];
+-	
++
+ 	/*
+ 	 * next in sort order. read, write or both are NULL
+ 	 */
+@@ -53,7 +53,11 @@ struct deadline_data {
+ 
+ static void deadline_move_request(struct deadline_data *, struct request *);
+ 
+-#define RQ_RB_ROOT(dd, rq)	(&(dd)->sort_list[rq_data_dir((rq))])
++static inline struct rb_root *
++deadline_rb_root(struct deadline_data *dd, struct request *rq)
++{
++	return &dd->sort_list[rq_data_dir(rq)];
++}
+ 
+ /*
+  * get the request after `rq' in sector-sorted order
+@@ -72,15 +76,11 @@ deadline_latter_request(struct request *rq)
+ static void
+ deadline_add_rq_rb(struct deadline_data *dd, struct request *rq)
+ {
+-	struct rb_root *root = RQ_RB_ROOT(dd, rq);
++	struct rb_root *root = deadline_rb_root(dd, rq);
+ 	struct request *__alias;
+ 
+-retry:
+-	__alias = elv_rb_add(root, rq);
+-	if (unlikely(__alias)) {
++	while (unlikely(__alias = elv_rb_add(root, rq)))
+ 		deadline_move_request(dd, __alias);
+-		goto retry;
+-	}
+ }
+ 
+ static inline void
+@@ -91,7 +91,7 @@ deadline_del_rq_rb(struct deadline_data *dd, struct request *rq)
+ 	if (dd->next_rq[data_dir] == rq)
+ 		dd->next_rq[data_dir] = deadline_latter_request(rq);
+ 
+-	elv_rb_del(RQ_RB_ROOT(dd, rq), rq);
++	elv_rb_del(deadline_rb_root(dd, rq), rq);
+ }
+ 
+ /*
+@@ -106,7 +106,7 @@ deadline_add_request(struct request_queue *q, struct request *rq)
+ 	deadline_add_rq_rb(dd, rq);
+ 
+ 	/*
+-	 * set expire time (only used for reads) and add to fifo list
++	 * set expire time and add to fifo list
+ 	 */
+ 	rq_set_fifo_time(rq, jiffies + dd->fifo_expire[data_dir]);
+ 	list_add_tail(&rq->queuelist, &dd->fifo_list[data_dir]);
+@@ -162,7 +162,7 @@ static void deadline_merged_request(struct request_queue *q,
+ 	 * if the merge was a front merge, we need to reposition request
+ 	 */
+ 	if (type == ELEVATOR_FRONT_MERGE) {
+-		elv_rb_del(RQ_RB_ROOT(dd, req), req);
++		elv_rb_del(deadline_rb_root(dd, req), req);
+ 		deadline_add_rq_rb(dd, req);
+ 	}
+ }
+@@ -212,7 +212,7 @@ deadline_move_request(struct deadline_data *dd, struct request *rq)
+ 	dd->next_rq[WRITE] = NULL;
+ 	dd->next_rq[data_dir] = deadline_latter_request(rq);
+ 
+-	dd->last_sector = rq->sector + rq->nr_sectors;
++	dd->last_sector = rq_end_sector(rq);
+ 
+ 	/*
+ 	 * take it off the sort and fifo list, move
+@@ -222,7 +222,7 @@ deadline_move_request(struct deadline_data *dd, struct request *rq)
+ }
+ 
+ /*
+- * deadline_check_fifo returns 0 if there are no expired reads on the fifo,
++ * deadline_check_fifo returns 0 if there are no expired requests on the fifo,
+  * 1 otherwise. Requires !list_empty(&dd->fifo_list[data_dir])
+  */
+ static inline int deadline_check_fifo(struct deadline_data *dd, int ddir)

commit 63de428b139d3d31d86ebe25ae97b33f6540fb7e
+Author: Aaron Carroll 
+Date:   Thu Aug 14 18:17:13 2008 +1000
+
+    deadline-iosched: allow non-sequential batching
+    
+    Deadline currently only batches sector-contiguous requests, so except
+    for a few circumstances (e.g. requests in a single direction), it is
+    essentially first come first served.  This is bad for throughput, so
+    change it to CSCAN, which means requests in a batch do not need to be
+    sequential and are issued in increasing sector order.
+    
+    Signed-off-by: Aaron Carroll 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c
+index 342448c3d2dd..07b80e4642f9 100644
+--- a/block/deadline-iosched.c
++++ b/block/deadline-iosched.c
+@@ -258,17 +258,9 @@ static int deadline_dispatch_requests(struct request_queue *q, int force)
+ 	else
+ 		rq = dd->next_rq[READ];
+ 
+-	if (rq) {
+-		/* we have a "next request" */
+-		
+-		if (dd->last_sector != rq->sector)
+-			/* end the batch on a non sequential request */
+-			dd->batching += dd->fifo_batch;
+-		
+-		if (dd->batching < dd->fifo_batch)
+-			/* we are still entitled to batch */
+-			goto dispatch_request;
+-	}
++	if (rq && dd->batching < dd->fifo_batch)
++		/* we have a next request are still entitled to batch */
++		goto dispatch_request;
+ 
+ 	/*
+ 	 * at this point we are not running a batch. select the appropriate

commit bf4634afd8bb72936d2d56425ec792ca1bfa92a2
+Author: Peter Chubb 
+Date:   Thu Jul 31 10:56:34 2008 +1000
+
+    rt2500pci: restoring missing line
+    
+    In kernel version 2.6.26-rc9 my wireless LAN card worked; but in the
+    released 2.6.26, my RaLink rt2500 card wouldn't associate.
+    
+    Git-bisect led me to this patch:
+    
+            61486e0f68d1f8966c09b734566a187d42d65c54
+            rt2x00: Remove ieee80211_tx_control argument from write_tx_desc()
+    
+    I believe that there is a problem with that patch --- it
+    (inadvertantly) removes an extra line of code, that used to set the
+    DATABYTE_COUNT field.
+    
+    This patch reinstates that line, and with it my card works again.
+    
+    Signed-off-by: Peter Chubb 
+    Acked-by: Ivo van Doorn 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
+index aa6dfb811c71..181a146b4768 100644
+--- a/drivers/net/wireless/rt2x00/rt2500pci.c
++++ b/drivers/net/wireless/rt2x00/rt2500pci.c
+@@ -1220,6 +1220,7 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ 	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
+ 	rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
+ 			   test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
++	rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len);
+ 	rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
+ 	rt2x00_desc_write(txd, 0, word);
+ }

commit e384f41409cb9e543fbc84b375e2ba46cbcbec6a
+Author: Ian Wienand 
+Date:   Tue Nov 20 14:12:46 2007 +1100
+
+    [IA64] set_thread_area fails in IA32 chroot
+    
+    I tried to upgrade an IA32 chroot on my IA64 to a new glibc with TLS.
+    It kept dying because set_thread_area was returning -ESRCH
+    (bugs.debian.org/451939).
+    
+    I instrumented arch/ia64/ia32/sys_ia32.c:get_free_idx() and ended up
+    seeing output like
+    
+    [pid] idx   desc->a  desc->b
+    -----------------------------
+    [2710] 0 -> c6b0ffff 40dff31b
+    [2710] 1 -> 0 0
+    [2710] 2 -> 0 0
+    
+    [2710] 0 -> c6b0ffff 40dff31b
+    [2710] 1 -> c6b0ffff 40dff31b
+    [2710] 2 -> 0 0
+    
+    [2711] 0 -> c6b0ffff 40dff31b
+    [2711] 1 -> c6b0ffff 40dff31b
+    [2711] 2 -> 48c0ffff 40dff317
+    
+    which suggested to me that TLS pointers were surviving exec() calls,
+    leading to GDT pointers filling up and the eventual failure of
+    get_free_idx().
+    
+    I think the solution is flushing the tls array on exec.
+    
+    Signed-Off-By: Ian Wienand 
+    Signed-off-by: Tony Luck 
+
+diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
+index a70ad185725c..7377d323131d 100644
+--- a/arch/ia64/kernel/process.c
++++ b/arch/ia64/kernel/process.c
+@@ -739,6 +739,7 @@ flush_thread (void)
+ 		ia32_drop_ia64_partial_page_list(current);
+ 		current->thread.task_size = IA32_PAGE_OFFSET;
+ 		set_fs(USER_DS);
++		memset(current->thread.tls_array, 0, sizeof(current->thread.tls_array));
+ 	}
+ #endif
+ }

commit 49565124b13bb16607e7f8fc8fb1d9c5c355a1a3
+Author: Aaron Carroll 
+Date:   Wed Dec 5 21:07:07 2007 +1100
+
+    as-iosched: fix write batch start point
+    
+    New write batches currently start from where the last one completed.
+    We have no idea where the head is after switching batches, so this
+    makes little sense.  Instead, start the next batch from the request
+    with the earliest deadline in the hope that we avoid a deadline
+    expiry later on.
+    
+    Signed-off-by: Aaron Carroll 
+    Acked-by: Nick Piggin 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/as-iosched.c b/block/as-iosched.c
+index 4513fc59c9da..555cd6bf4ce5 100644
+--- a/block/as-iosched.c
++++ b/block/as-iosched.c
+@@ -1097,7 +1097,8 @@ static int as_dispatch_request(struct request_queue *q, int force)
+ 		ad->batch_data_dir = REQ_ASYNC;
+ 		ad->current_write_count = ad->write_batch_count;
+ 		ad->write_batch_idled = 0;
+-		rq = ad->next_rq[ad->batch_data_dir];
++		rq = rq_entry_fifo(ad->fifo_list[REQ_ASYNC].next);
++		ad->last_check_fifo[REQ_ASYNC] = jiffies;
+ 		goto dispatch_request;
+ 	}
+ 

commit 8896f3c039b0834ba695d154299b724ee5710b97
+Author: Aaron Carroll 
+Date:   Wed Dec 5 21:06:50 2007 +1100
+
+    as-iosched: fix incorrect comments
+    
+    Two comments refer to deadlines applying to reads only.  This is
+    not the case.
+    
+    Signed-off-by: Aaron Carroll 
+    Acked-by: Nick Piggin 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/as-iosched.c b/block/as-iosched.c
+index dc715a562e14..4513fc59c9da 100644
+--- a/block/as-iosched.c
++++ b/block/as-iosched.c
+@@ -880,7 +880,7 @@ static void as_remove_queued_request(struct request_queue *q,
+ }
+ 
+ /*
+- * as_fifo_expired returns 0 if there are no expired reads on the fifo,
++ * as_fifo_expired returns 0 if there are no expired requests on the fifo,
+  * 1 otherwise.  It is ratelimited so that we only perform the check once per
+  * `fifo_expire' interval.  Otherwise a large number of expired requests
+  * would create a hopeless seekstorm.
+@@ -1159,7 +1159,7 @@ static void as_add_request(struct request_queue *q, struct request *rq)
+ 	as_add_rq_rb(ad, rq);
+ 
+ 	/*
+-	 * set expire time (only used for reads) and add to fifo list
++	 * set expire time and add to fifo list
+ 	 */
+ 	rq_set_fifo_time(rq, jiffies + ad->fifo_expire[data_dir]);
+ 	list_add_tail(&rq->queuelist, &ad->fifo_list[data_dir]);

commit c5d07d6ccc6710cad5815768c6d5e629c99b4dca
+Author: Peter Chubb 
+Date:   Wed Oct 31 11:45:50 2007 +1100
+
+    [IA64] Add gate.lds to list of files ignored by Git
+    
+    If you build the kernel `in-place' then do a git update, git
+    complains about arch/ia64/kernel/gate.lds being modified and
+    untracked.
+    
+    Add that (generated) file to a .gitignore file.
+    
+    Signed-off-by: Peter Chubb 
+    Signed-off-by: Tony Luck 
+
+diff --git a/arch/ia64/kernel/.gitignore b/arch/ia64/kernel/.gitignore
+new file mode 100644
+index 000000000000..98307759a3b8
+--- /dev/null
++++ b/arch/ia64/kernel/.gitignore
+@@ -0,0 +1 @@
++gate.lds

commit 6f5d8aa6382eef2b26032c88656270bdae7f0c42
+Author: Aaron Carroll 
+Date:   Tue Oct 30 10:40:13 2007 +0100
+
+    Deadline iosched: Fix batching fairness
+    
+    After switching data directions, deadline always starts the next batch
+    from the lowest-sector request.  This gives excessive deadline expiries
+    and large latency and throughput disparity between high- and low-sector
+    requests; an order of magnitude in some tests.
+    
+    This patch changes the batching behaviour so new batches start from the
+    request whose expiry is earliest.
+    
+    Signed-off-by: Aaron Carroll 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c
+index cb94c838087a..a054eef8dff6 100644
+--- a/block/deadline-iosched.c
++++ b/block/deadline-iosched.c
+@@ -306,27 +306,20 @@ static int deadline_dispatch_requests(struct request_queue *q, int force)
+ dispatch_find_request:
+ 	/*
+ 	 * we are not running a batch, find best request for selected data_dir
+-	 * and start a new batch
+ 	 */
+-	if (deadline_check_fifo(dd, data_dir)) {
+-		/* An expired request exists - satisfy it */
++	if (deadline_check_fifo(dd, data_dir) || !dd->next_rq[data_dir]) {
++		/*
++		 * A deadline has expired, the last request was in the other
++		 * direction, or we have run out of higher-sectored requests.
++		 * Start again from the request with the earliest expiry time.
++		 */
+ 		rq = rq_entry_fifo(dd->fifo_list[data_dir].next);
+-	} else if (dd->next_rq[data_dir]) {
++	} else {
+ 		/*
+ 		 * The last req was the same dir and we have a next request in
+ 		 * sort order. No expired requests so continue on from here.
+ 		 */
+ 		rq = dd->next_rq[data_dir];
+-	} else {
+-		struct rb_node *node;
+-		/*
+-		 * The last req was the other direction or we have run out of
+-		 * higher-sectored requests. Go back to the lowest sectored
+-		 * request (1 way elevator) and start a new batch.
+-		 */
+-		node = rb_first(&dd->sort_list[data_dir]);
+-		if (node)
+-			rq = rb_entry_rq(node);
+ 	}
+ 
+ 	dd->batching = 0;

commit dfb3d72a9aa519672c9ae06f0d2f93eccb35482f
+Author: Aaron Carroll 
+Date:   Tue Oct 30 10:40:13 2007 +0100
+
+    Deadline iosched: Reset batch for ordered requests
+    
+    The deadline I/O scheduler does not reset the batch count when starting
+    a new batch at a higher-sectored request.  This means the second and
+    subsequent batch in the same data direction will never exceed a single
+    request in size whenever higher-sectored requests are pending.
+    
+    This patch gives new batches in the same data direction as old ones
+    their full quota of requests by resetting the batch count.
+    
+    Signed-off-by: Aaron Carroll 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c
+index a44437e5a94b..cb94c838087a 100644
+--- a/block/deadline-iosched.c
++++ b/block/deadline-iosched.c
+@@ -306,12 +306,11 @@ static int deadline_dispatch_requests(struct request_queue *q, int force)
+ dispatch_find_request:
+ 	/*
+ 	 * we are not running a batch, find best request for selected data_dir
++	 * and start a new batch
+ 	 */
+ 	if (deadline_check_fifo(dd, data_dir)) {
+ 		/* An expired request exists - satisfy it */
+-		dd->batching = 0;
+ 		rq = rq_entry_fifo(dd->fifo_list[data_dir].next);
+-		
+ 	} else if (dd->next_rq[data_dir]) {
+ 		/*
+ 		 * The last req was the same dir and we have a next request in
+@@ -325,12 +324,13 @@ static int deadline_dispatch_requests(struct request_queue *q, int force)
+ 		 * higher-sectored requests. Go back to the lowest sectored
+ 		 * request (1 way elevator) and start a new batch.
+ 		 */
+-		dd->batching = 0;
+ 		node = rb_first(&dd->sort_list[data_dir]);
+ 		if (node)
+ 			rq = rb_entry_rq(node);
+ 	}
+ 
++	dd->batching = 0;
++
+ dispatch_request:
+ 	/*
+ 	 * rq is the selected appropriate request.

commit 5d1a536621403b442eef60ddd35e6b7a46fb04b7
+Author: Aaron Carroll 
+Date:   Tue Oct 30 10:40:12 2007 +0100
+
+    Deadline iosched: Factor out finding latter reques
+    
+    Factor finding the next request in sector-sorted order into
+    a function deadline_latter_request.
+    
+    Signed-off-by: Aaron Carroll 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c
+index 1a511ffaf8a4..a44437e5a94b 100644
+--- a/block/deadline-iosched.c
++++ b/block/deadline-iosched.c
+@@ -55,6 +55,20 @@ static void deadline_move_request(struct deadline_data *, struct request *);
+ 
+ #define RQ_RB_ROOT(dd, rq)	(&(dd)->sort_list[rq_data_dir((rq))])
+ 
++/*
++ * get the request after `rq' in sector-sorted order
++ */
++static inline struct request *
++deadline_latter_request(struct request *rq)
++{
++	struct rb_node *node = rb_next(&rq->rb_node);
++
++	if (node)
++		return rb_entry_rq(node);
++
++	return NULL;
++}
++
+ static void
+ deadline_add_rq_rb(struct deadline_data *dd, struct request *rq)
+ {
+@@ -74,13 +88,8 @@ deadline_del_rq_rb(struct deadline_data *dd, struct request *rq)
+ {
+ 	const int data_dir = rq_data_dir(rq);
+ 
+-	if (dd->next_rq[data_dir] == rq) {
+-		struct rb_node *rbnext = rb_next(&rq->rb_node);
+-
+-		dd->next_rq[data_dir] = NULL;
+-		if (rbnext)
+-			dd->next_rq[data_dir] = rb_entry_rq(rbnext);
+-	}
++	if (dd->next_rq[data_dir] == rq)
++		dd->next_rq[data_dir] = deadline_latter_request(rq);
+ 
+ 	elv_rb_del(RQ_RB_ROOT(dd, rq), rq);
+ }
+@@ -198,14 +207,11 @@ static void
+ deadline_move_request(struct deadline_data *dd, struct request *rq)
+ {
+ 	const int data_dir = rq_data_dir(rq);
+-	struct rb_node *rbnext = rb_next(&rq->rb_node);
+ 
+ 	dd->next_rq[READ] = NULL;
+ 	dd->next_rq[WRITE] = NULL;
++	dd->next_rq[data_dir] = deadline_latter_request(rq);
+ 
+-	if (rbnext)
+-		dd->next_rq[data_dir] = rb_entry_rq(rbnext);
+-	
+ 	dd->last_sector = rq->sector + rq->nr_sectors;
+ 
+ 	/*

commit 7b3166dbc3df5b72f2ba4ea130f4461e318a3838
+Author: Peter Chubb 
+Date:   Tue Aug 21 13:57:01 2007 +1000
+
+    [IA64] Cleanup HPSIM code (was: Re: Enable early console for Ski simulator)
+    
+    After my last patch we have a new header file for HP simulator use.
+    Here's code to use it for stuff that used to have `extern' statements
+    inline in the code.  Functionality should not change with this patch.
+    
+    Signed-off-by: Peter Chubb 
+    Signed-off-by: Tony Luck 
+
+diff --git a/arch/ia64/hp/sim/hpsim_console.c b/arch/ia64/hp/sim/hpsim_console.c
+index 0475a5452404..01663bc42b1a 100644
+--- a/arch/ia64/hp/sim/hpsim_console.c
++++ b/arch/ia64/hp/sim/hpsim_console.c
+@@ -59,7 +59,6 @@ simcons_write (struct console *cons, const char *buf, unsigned count)
+ 
+ static struct tty_driver *simcons_console_device (struct console *c, int *index)
+ {
+-	extern struct tty_driver *hp_simserial_driver;
+ 	*index = c->index;
+ 	return hp_simserial_driver;
+ }
+diff --git a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c
+index f26077a773d5..4017696ada63 100644
+--- a/arch/ia64/hp/sim/simeth.c
++++ b/arch/ia64/hp/sim/simeth.c
+@@ -22,6 +22,9 @@
+ #include 
+ #include 
+ #include 
++#include 
++
++#include "hpsim_ssc.h"
+ 
+ #define SIMETH_RECV_MAX	10
+ 
+@@ -35,12 +38,6 @@
+ #define SIMETH_FRAME_SIZE	ETH_FRAME_LEN
+ 
+ 
+-#define SSC_NETDEV_PROBE		100
+-#define SSC_NETDEV_SEND			101
+-#define SSC_NETDEV_RECV			102
+-#define SSC_NETDEV_ATTACH		103
+-#define SSC_NETDEV_DETACH		104
+-
+ #define NETWORK_INTR			8
+ 
+ struct simeth_local {
+@@ -124,9 +121,6 @@ simeth_probe (void)
+ 	return r;
+ }
+ 
+-extern long ia64_ssc (long, long, long, long, int);
+-extern void ia64_ssc_connect_irq (long intr, long irq);
+-
+ static inline int
+ netdev_probe(char *name, unsigned char *ether)
+ {
+diff --git a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c
+index e62694f8ef75..4552a1cf5b33 100644
+--- a/arch/ia64/hp/sim/simscsi.c
++++ b/arch/ia64/hp/sim/simscsi.c
+@@ -14,6 +14,7 @@
+ #include 
+ #include 
+ #include 
++#include "hpsim_ssc.h"
+ 
+ #include 
+ #include 
+@@ -59,8 +60,6 @@ struct disk_stat {
+ 	unsigned count;
+ };
+ 
+-extern long ia64_ssc (long arg0, long arg1, long arg2, long arg3, int nr);
+-
+ static int desc[16] = {
+ 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+ };
+diff --git a/include/asm-ia64/hpsim.h b/include/asm-ia64/hpsim.h
+index d6be3fdc39fa..892ab198a9da 100644
+--- a/include/asm-ia64/hpsim.h
++++ b/include/asm-ia64/hpsim.h
+@@ -7,4 +7,10 @@ static inline int simcons_register(void) { return 1; }
+ int simcons_register(void);
+ #endif
+ 
++struct tty_driver;
++extern struct tty_driver *hp_simserial_driver;
++
++void ia64_ssc_connect_irq(long intr, long irq);
++void ia64_ctl_trace(long on);
++
+ #endif

commit 471e7a44848f467c9b83adc3463d019d2fa8817f
+Author: Peter Chubb 
+Date:   Thu Aug 16 15:03:07 2007 +1000
+
+    [IA64] Enable early console for Ski simulator
+    
+    When using Ski to debug early startup, it's a bit of a pain not to
+    have printk.
+    
+    This patch enables the simulated console very early.
+    It may be worth conditionalising on the command line... but this is
+    enough for now.
+    
+    Signed-off-by: Peter Chubb 
+    Signed-off-by: Tony Luck 
+
+diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
+index cd9a37a552c3..407efea04bf5 100644
+--- a/arch/ia64/kernel/setup.c
++++ b/arch/ia64/kernel/setup.c
+@@ -389,6 +389,13 @@ early_console_setup (char *cmdline)
+ 	if (!efi_setup_pcdp_console(cmdline))
+ 		earlycons++;
+ #endif
++#ifdef CONFIG_HP_SIMSERIAL_CONSOLE
++	{
++		extern struct console hpsim_cons;
++		register_console(&hpsim_cons);
++		earlycons++;
++	}
++#endif
+ 
+ 	return (earlycons) ? 0 : -1;
+ }

commit cd5bfea278987ebfe60f3ff92a01696b17c4f978
+Author: Peter Chubb 
+Date:   Fri Aug 10 13:01:10 2007 -0700
+
+    fix compilation with gcc 4.2
+    
+    gcc-4.2 is a lot more picky about its symbol handling.  EXPORT_SYMBOL no
+    longer works on symbols that are undefined or defined with static scope.
+    
+    For example, with CONFIG_PROFILE off, I see:
+    
+      kernel/profile.c:206: error: __ksymtab_profile_event_unregister causes a section type conflict
+      kernel/profile.c:205: error: __ksymtab_profile_event_register causes a section type conflict
+    
+    This patch moves the EXPORTs inside the #ifdef CONFIG_PROFILE, so we
+    only try to export symbols that are defined.
+    
+    Also, in kernel/kprobes.c there's an EXPORT_SYMBOL_GPL() for
+    jprobes_return, which if CONFIG_JPROBES is undefined is a static
+    inline and gives the same error.
+    
+    And in drivers/acpi/resources/rsxface.c, there's an
+    ACPI_EXPORT_SYMBOPL() for a static symbol. If it's static, it's not
+    accessible from outside the compilation unit, so should bot be exported.
+    
+    These three changes allow building a zx1_defconfig kernel with gcc 4.2
+    on IA64.
+    
+    [akpm@linux-foundation.org: export jpobe_return properly]
+    Signed-off-by: Peter Chubb 
+    Cc: Prasanna S Panchamukhi 
+    Cc: Ananth N Mavinakayanahalli 
+    Cc: Anil S Keshavamurthy 
+    Cc: "Luck, Tony" 
+    Cc: Len Brown 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c
+index f63813a358c5..4c3fd4cdaf73 100644
+--- a/drivers/acpi/resources/rsxface.c
++++ b/drivers/acpi/resources/rsxface.c
+@@ -474,8 +474,6 @@ acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context)
+ 	return (AE_CTRL_TERMINATE);
+ }
+ 
+-ACPI_EXPORT_SYMBOL(acpi_rs_match_vendor_resource)
+-
+ /*******************************************************************************
+  *
+  * FUNCTION:    acpi_walk_resources
+diff --git a/kernel/kprobes.c b/kernel/kprobes.c
+index 3e9f513a728d..4b8a4493c541 100644
+--- a/kernel/kprobes.c
++++ b/kernel/kprobes.c
+@@ -1063,6 +1063,11 @@ EXPORT_SYMBOL_GPL(register_kprobe);
+ EXPORT_SYMBOL_GPL(unregister_kprobe);
+ EXPORT_SYMBOL_GPL(register_jprobe);
+ EXPORT_SYMBOL_GPL(unregister_jprobe);
++#ifdef CONFIG_KPROBES
+ EXPORT_SYMBOL_GPL(jprobe_return);
++#endif
++
++#ifdef CONFIG_KPROBES
+ EXPORT_SYMBOL_GPL(register_kretprobe);
+ EXPORT_SYMBOL_GPL(unregister_kretprobe);
++#endif
+diff --git a/kernel/profile.c b/kernel/profile.c
+index 5b20fe977bed..cb1e37d2dac3 100644
+--- a/kernel/profile.c
++++ b/kernel/profile.c
+@@ -199,11 +199,11 @@ EXPORT_SYMBOL_GPL(register_timer_hook);
+ EXPORT_SYMBOL_GPL(unregister_timer_hook);
+ EXPORT_SYMBOL_GPL(task_handoff_register);
+ EXPORT_SYMBOL_GPL(task_handoff_unregister);
++EXPORT_SYMBOL_GPL(profile_event_register);
++EXPORT_SYMBOL_GPL(profile_event_unregister);
+ 
+ #endif /* CONFIG_PROFILING */
+ 
+-EXPORT_SYMBOL_GPL(profile_event_register);
+-EXPORT_SYMBOL_GPL(profile_event_unregister);
+ 
+ #ifdef CONFIG_SMP
+ /*

commit c7f570a5eca59575572ee231390df727df207bda
+Author: Peter Chubb 
+Date:   Tue Dec 5 12:25:31 2006 +1100
+
+    [IA64] Fix pci.c kernel compilation breakage.
+    
+    The recent change to convert the is_enabled flag in the PCI device to an
+    atomic count broke the IA64 compilation.
+    
+    As pcibios_disable_device is only ever called if the reference count
+    is zero, convert the if to a BUG_ON.
+    
+    Signed-off-by: Peter Chubb 
+    Signed-off-by: Tony Luck 
+
+diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
+index f4edfbf27134..eb92cef9cd0d 100644
+--- a/arch/ia64/pci/pci.c
++++ b/arch/ia64/pci/pci.c
+@@ -564,8 +564,8 @@ pcibios_enable_device (struct pci_dev *dev, int mask)
+ void
+ pcibios_disable_device (struct pci_dev *dev)
+ {
+-	if (dev->is_enabled)
+-		acpi_pci_irq_disable(dev);
++	BUG_ON(atomic_read(&dev->enable_cnt));
++	acpi_pci_irq_disable(dev);
+ }
+ 
+ void

commit 23219c134865d524357e9bb90e5badb422ac8fff
+Author: Peter Chubb 
+Date:   Tue Jul 25 20:39:14 2006 +1000
+
+    USB: Patch for rtl8150 to fix unplug problems
+    
+    The RTL8150 driver currently crashes the kernel if the USB lead is unplugged
+    while the device is active.  The attached patch adds error handling to
+    tell the network layer that the device has gone away when the device is
+    unplugged.  With this patch, the device can be plugged and unplugged
+    to one's hearts' content, without crashing anything.
+    
+    Oh, I've also added rudimentary suspend and resume methods.
+    
+    Signed-off-by: Peter Chubb 
+    Acked-by: Petko Manolov 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
+index e5e6e4f3ef87..bd09232ce13c 100644
+--- a/drivers/usb/net/rtl8150.c
++++ b/drivers/usb/net/rtl8150.c
+@@ -175,6 +175,8 @@ static inline struct sk_buff *pull_skb(rtl8150_t *);
+ static void rtl8150_disconnect(struct usb_interface *intf);
+ static int rtl8150_probe(struct usb_interface *intf,
+ 			   const struct usb_device_id *id);
++static int rtl8150_suspend(struct usb_interface *intf, pm_message_t message);
++static int rtl8150_resume(struct usb_interface *intf);
+ 
+ static const char driver_name [] = "rtl8150";
+ 
+@@ -183,6 +185,8 @@ static struct usb_driver rtl8150_driver = {
+ 	.probe =	rtl8150_probe,
+ 	.disconnect =	rtl8150_disconnect,
+ 	.id_table =	rtl8150_table,
++	.suspend =	rtl8150_suspend,
++	.resume =	rtl8150_resume
+ };
+ 
+ /*
+@@ -238,9 +242,11 @@ static int async_set_registers(rtl8150_t * dev, u16 indx, u16 size)
+ 	usb_fill_control_urb(dev->ctrl_urb, dev->udev,
+ 			 usb_sndctrlpipe(dev->udev, 0), (char *) &dev->dr,
+ 			 &dev->rx_creg, size, ctrl_callback, dev);
+-	if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC)))
++	if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC))) {
++		if (ret == -ENODEV)
++			netif_device_detach(dev->netdev);
+ 		err("control request submission failed: %d", ret);
+-	else
++	} else
+ 		set_bit(RX_REG_SET, &dev->flags);
+ 
+ 	return ret;
+@@ -416,6 +422,7 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
+ 	struct sk_buff *skb;
+ 	struct net_device *netdev;
+ 	u16 rx_stat;
++	int status;
+ 
+ 	dev = urb->context;
+ 	if (!dev)
+@@ -465,7 +472,10 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
+ goon:
+ 	usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
+ 		      dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev);
+-	if (usb_submit_urb(dev->rx_urb, GFP_ATOMIC)) {
++	status = usb_submit_urb(dev->rx_urb, GFP_ATOMIC);
++	if (status == -ENODEV)
++		netif_device_detach(dev->netdev);
++	else if (status) {
+ 		set_bit(RX_URB_FAIL, &dev->flags);
+ 		goto resched;
+ 	} else {
+@@ -481,6 +491,7 @@ static void rx_fixup(unsigned long data)
+ {
+ 	rtl8150_t *dev;
+ 	struct sk_buff *skb;
++	int status;
+ 
+ 	dev = (rtl8150_t *)data;
+ 
+@@ -499,10 +510,13 @@ static void rx_fixup(unsigned long data)
+ 	usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
+ 		      dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev);
+ try_again:
+-	if (usb_submit_urb(dev->rx_urb, GFP_ATOMIC)) {
++	status = usb_submit_urb(dev->rx_urb, GFP_ATOMIC);
++	if (status == -ENODEV) {
++		netif_device_detach(dev->netdev);
++	} else if (status) {
+ 		set_bit(RX_URB_FAIL, &dev->flags);
+ 		goto tlsched;
+-	 } else {
++	} else {
+ 		clear_bit(RX_URB_FAIL, &dev->flags);
+ 	}
+ 
+@@ -574,12 +588,43 @@ static void intr_callback(struct urb *urb, struct pt_regs *regs)
+ 
+ resubmit:
+ 	status = usb_submit_urb (urb, SLAB_ATOMIC);
+-	if (status)
++	if (status == -ENODEV)
++		netif_device_detach(dev->netdev);
++	else if (status)
+ 		err ("can't resubmit intr, %s-%s/input0, status %d",
+ 				dev->udev->bus->bus_name,
+ 				dev->udev->devpath, status);
+ }
+ 
++static int rtl8150_suspend(struct usb_interface *intf, pm_message_t message)
++{
++	rtl8150_t *dev = usb_get_intfdata(intf);
++
++	netif_device_detach(dev->netdev);
++
++	if (netif_running(dev->netdev)) {
++		usb_kill_urb(dev->rx_urb);
++		usb_kill_urb(dev->intr_urb);
++	}
++	return 0;
++}
++
++static int rtl8150_resume(struct usb_interface *intf)
++{
++	rtl8150_t *dev = usb_get_intfdata(intf);
++
++	netif_device_attach(dev->netdev);
++	if (netif_running(dev->netdev)) {
++		dev->rx_urb->status = 0;
++		dev->rx_urb->actual_length = 0;
++		read_bulk_callback(dev->rx_urb, NULL);
++
++		dev->intr_urb->status = 0;
++		dev->intr_urb->actual_length = 0;
++		intr_callback(dev->intr_urb, NULL);
++	}
++	return 0;
++}
+ 
+ /*
+ **
+@@ -690,9 +735,14 @@ static int rtl8150_start_xmit(struct sk_buff *skb, struct net_device *netdev)
+ 	usb_fill_bulk_urb(dev->tx_urb, dev->udev, usb_sndbulkpipe(dev->udev, 2),
+ 		      skb->data, count, write_bulk_callback, dev);
+ 	if ((res = usb_submit_urb(dev->tx_urb, GFP_ATOMIC))) {
+-		warn("failed tx_urb %d\n", res);
+-		dev->stats.tx_errors++;
+-		netif_start_queue(netdev);
++		/* Can we get/handle EPIPE here? */
++		if (res == -ENODEV)
++			netif_device_detach(dev->netdev);
++		else {
++			warn("failed tx_urb %d\n", res);
++			dev->stats.tx_errors++;
++			netif_start_queue(netdev);
++		}
+ 	} else {
+ 		dev->stats.tx_packets++;
+ 		dev->stats.tx_bytes += skb->len;
+@@ -729,16 +779,25 @@ static int rtl8150_open(struct net_device *netdev)
+ 	
+ 	usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
+ 		      dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev);
+-	if ((res = usb_submit_urb(dev->rx_urb, GFP_KERNEL)))
++	if ((res = usb_submit_urb(dev->rx_urb, GFP_KERNEL))) {
++		if (res == -ENODEV)
++			netif_device_detach(dev->netdev);
+ 		warn("%s: rx_urb submit failed: %d", __FUNCTION__, res);
++		return res;
++	}
+ 	usb_fill_int_urb(dev->intr_urb, dev->udev, usb_rcvintpipe(dev->udev, 3),
+ 		     dev->intr_buff, INTBUFSIZE, intr_callback,
+ 		     dev, dev->intr_interval);
+-	if ((res = usb_submit_urb(dev->intr_urb, GFP_KERNEL)))
++	if ((res = usb_submit_urb(dev->intr_urb, GFP_KERNEL))) {
++		if (res == -ENODEV)
++			netif_device_detach(dev->netdev);
+ 		warn("%s: intr_urb submit failed: %d", __FUNCTION__, res);
+-	netif_start_queue(netdev);
++		usb_kill_urb(dev->rx_urb);
++		return res;
++	}
+ 	enable_net_traffic(dev);
+ 	set_carrier(netdev);
++	netif_start_queue(netdev);
+ 
+ 	return res;
+ }

commit bdcfd9e349eff9398a1d85eaa517294f493bb3c8
+Author: Peter Chubb 
+Date:   Tue May 2 18:29:34 2006 +0100
+
+    [PATCH] USB: shuttle_usbat: Hardcode detection of HP CDRW devices
+    
+    Use USB vendor and product IDs to determine whether the attached
+    device is a CDROM or a Flash device.  Daniel Drake says that the
+    *same* vendor and product IDs for non-HP vendor ID could be either
+    flash or cdrom, so try to probe for them.
+    
+    Signed-off-by: Peter Chubb 
+    Signed-off-by: Daniel Drake 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
+index 92095b858eb7..8fcec01dc622 100644
+--- a/drivers/usb/storage/shuttle_usbat.c
++++ b/drivers/usb/storage/shuttle_usbat.c
+@@ -893,22 +893,28 @@ static int usbat_identify_device(struct us_data *us,
+  * Set the transport function based on the device type
+  */
+ static int usbat_set_transport(struct us_data *us,
+-			       struct usbat_info *info)
++			       struct usbat_info *info,
++			       int devicetype)
+ {
+-	int rc;
+ 
+-	if (!info->devicetype) {
+-		rc = usbat_identify_device(us, info);
+-		if (rc != USB_STOR_TRANSPORT_GOOD) {
+-			US_DEBUGP("usbat_set_transport: Could not identify device\n");
+-			return 1;
+-		}
+-	}
++	if (!info->devicetype)
++		info->devicetype = devicetype;
+ 
+-	if (usbat_get_device_type(us) == USBAT_DEV_HP8200)
++	if (!info->devicetype)
++		usbat_identify_device(us, info);
++
++	switch (info->devicetype) {
++	default:
++		return USB_STOR_TRANSPORT_ERROR;
++
++	case  USBAT_DEV_HP8200:
+ 		us->transport = usbat_hp8200e_transport;
+-	else if (usbat_get_device_type(us) == USBAT_DEV_FLASH)
++		break;
++
++	case USBAT_DEV_FLASH:
+ 		us->transport = usbat_flash_transport;
++		break;
++	}
+ 
+ 	return 0;
+ }
+@@ -1316,7 +1322,7 @@ static int usbat_select_and_test_registers(struct us_data *us)
+ /*
+  * Initialize the USBAT processor and the storage device
+  */
+-int init_usbat(struct us_data *us)
++static int init_usbat(struct us_data *us, int devicetype)
+ {
+ 	int rc;
+ 	struct usbat_info *info;
+@@ -1398,7 +1404,7 @@ int init_usbat(struct us_data *us)
+ 	US_DEBUGP("INIT 9\n");
+ 
+ 	/* At this point, we need to detect which device we are using */
+-	if (usbat_set_transport(us, info))
++	if (usbat_set_transport(us, info, devicetype))
+ 		return USB_STOR_TRANSPORT_ERROR;
+ 
+ 	US_DEBUGP("INIT 10\n");
+@@ -1701,6 +1707,22 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
+ 	return USB_STOR_TRANSPORT_FAILED;
+ }
+ 
++int init_usbat_cd(struct us_data *us)
++{
++	return init_usbat(us, USBAT_DEV_HP8200);
++}
++
++
++int init_usbat_flash(struct us_data *us)
++{
++	return init_usbat(us, USBAT_DEV_FLASH);
++}
++
++int init_usbat_probe(struct us_data *us)
++{
++	return init_usbat(us, 0);
++}
++
+ /*
+  * Default transport function. Attempts to detect which transport function
+  * should be called, makes it the new default, and calls it.
+@@ -1714,9 +1736,8 @@ int usbat_transport(struct scsi_cmnd *srb, struct us_data *us)
+ {
+ 	struct usbat_info *info = (struct usbat_info*) (us->extra);
+ 
+-	if (usbat_set_transport(us, info))
++	if (usbat_set_transport(us, info, 0))
+ 		return USB_STOR_TRANSPORT_ERROR;
+ 
+ 	return us->transport(srb, us);	
+ }
+-
+diff --git a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h
+index 25e7d8b340b8..3ddf143a1dec 100644
+--- a/drivers/usb/storage/shuttle_usbat.h
++++ b/drivers/usb/storage/shuttle_usbat.h
+@@ -106,7 +106,9 @@
+ #define USBAT_FEAT_ET2	0x01
+ 
+ extern int usbat_transport(struct scsi_cmnd *srb, struct us_data *us);
+-extern int init_usbat(struct us_data *us);
++extern int init_usbat_cd(struct us_data *us);
++extern int init_usbat_flash(struct us_data *us);
++extern int init_usbat_probe(struct us_data *us);
+ 
+ struct usbat_info {
+ 	int devicetype;
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index aec5ea8682d5..f24fa12eaedf 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -78,12 +78,12 @@ UNUSUAL_DEV(  0x03f0, 0x0107, 0x0200, 0x0200,
+ UNUSUAL_DEV(  0x03f0, 0x0207, 0x0001, 0x0001, 
+ 		"HP",
+ 		"CD-Writer+ 8200e",
+-		US_SC_8070, US_PR_USBAT, init_usbat, 0),
++		US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
+ 
+ UNUSUAL_DEV(  0x03f0, 0x0307, 0x0001, 0x0001, 
+ 		"HP",
+ 		"CD-Writer+ CD-4e",
+-		US_SC_8070, US_PR_USBAT, init_usbat, 0),
++		US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
+ #endif
+ 
+ /* Reported by Sebastian Kapfer 
+@@ -393,7 +393,7 @@ UNUSUAL_DEV(  0x04fc, 0x80c2, 0x0100, 0x0100,
+ UNUSUAL_DEV(  0x04e6, 0x1010, 0x0000, 0x9999,
+ 		"Shuttle/SCM",
+ 		"USBAT-02",
+-		US_SC_SCSI, US_PR_USBAT, init_usbat,
++		US_SC_SCSI, US_PR_USBAT, init_usbat_probe,
+ 		US_FL_SINGLE_LUN),
+ #endif
+ 
+@@ -797,7 +797,7 @@ UNUSUAL_DEV(  0x0781, 0x0002, 0x0009, 0x0009,
+ UNUSUAL_DEV(  0x0781, 0x0005, 0x0005, 0x0005,
+ 		"Sandisk",
+ 		"ImageMate SDDR-05b",
+-		US_SC_SCSI, US_PR_USBAT, init_usbat,
++		US_SC_SCSI, US_PR_USBAT, init_usbat_flash,
+ 		US_FL_SINGLE_LUN ),
+ #endif
+ 

commit 141804d401631f0384feabfa5fc3e2ce1321c0f0
+Author: Peter Chubb 
+Date:   Tue May 2 18:30:12 2006 +0100
+
+    [PATCH] USB: shuttle_usbat: Fix handling of scatter-gather buffers
+    
+    I've worked out what's going wrong.  The scsi layer is now much
+    more likely to pass down scatterlists instead of plain buffers.  So
+    you have to make sure that they're handled correctly.  In one of the
+    changes along the way, usbat_write_block and friends stopped obeying
+    the srb->use_sg flag.
+    
+    Anyway, with the appended patch, and the one I'm putting in the next email, it
+    all seems to work for the HP cd4e.  Of course, someone's going to have
+    to test it with the flash drives as well....
+    
+    This patch teaches the usbat_{read,write}_block functions to
+    obey the use_sg flag in the scsi-request.
+    
+    Signed-off-by: Peter Chubb 
+    Signed-off-by: Daniel Drake 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
+index f2bc5c9e23d5..92095b858eb7 100644
+--- a/drivers/usb/storage/shuttle_usbat.c
++++ b/drivers/usb/storage/shuttle_usbat.c
+@@ -131,28 +131,30 @@ static int usbat_write(struct us_data *us,
+  * Convenience function to perform a bulk read
+  */
+ static int usbat_bulk_read(struct us_data *us,
+-							 unsigned char *data,
+-							 unsigned int len)
++			   unsigned char *data,
++			   unsigned int len,
++			   int use_sg)
+ {
+ 	if (len == 0)
+ 		return USB_STOR_XFER_GOOD;
+ 
+ 	US_DEBUGP("usbat_bulk_read: len = %d\n", len);
+-	return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, data, len, NULL);
++	return usb_stor_bulk_transfer_sg(us, us->recv_bulk_pipe, data, len, use_sg, NULL);
+ }
+ 
+ /*
+  * Convenience function to perform a bulk write
+  */
+ static int usbat_bulk_write(struct us_data *us,
+-							unsigned char *data,
+-							unsigned int len)
++			    unsigned char *data,
++			    unsigned int len,
++			    int use_sg)
+ {
+ 	if (len == 0)
+ 		return USB_STOR_XFER_GOOD;
+ 
+ 	US_DEBUGP("usbat_bulk_write:  len = %d\n", len);
+-	return usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, data, len, NULL);
++	return usb_stor_bulk_transfer_sg(us, us->send_bulk_pipe, data, len, use_sg, NULL);
+ }
+ 
+ /*
+@@ -317,7 +319,8 @@ static int usbat_wait_not_busy(struct us_data *us, int minutes)
+  */
+ static int usbat_read_block(struct us_data *us,
+ 			    unsigned char *content,
+-			    unsigned short len)
++			    unsigned short len,
++			    int use_sg)
+ {
+ 	int result;
+ 	unsigned char *command = us->iobuf;
+@@ -338,7 +341,7 @@ static int usbat_read_block(struct us_data *us,
+ 	if (result != USB_STOR_XFER_GOOD)
+ 		return USB_STOR_TRANSPORT_ERROR;
+ 
+-	result = usbat_bulk_read(us, content, len);
++	result = usbat_bulk_read(us, content, len, use_sg);
+ 	return (result == USB_STOR_XFER_GOOD ?
+ 			USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR);
+ }
+@@ -350,7 +353,8 @@ static int usbat_write_block(struct us_data *us,
+ 			     unsigned char access,
+ 			     unsigned char *content,
+ 			     unsigned short len,
+-			     int minutes)
++			     int minutes,
++			     int use_sg)
+ {
+ 	int result;
+ 	unsigned char *command = us->iobuf;
+@@ -372,7 +376,7 @@ static int usbat_write_block(struct us_data *us,
+ 	if (result != USB_STOR_XFER_GOOD)
+ 		return USB_STOR_TRANSPORT_ERROR;
+ 
+-	result = usbat_bulk_write(us, content, len);
++	result = usbat_bulk_write(us, content, len, use_sg);
+ 	if (result != USB_STOR_XFER_GOOD)
+ 		return USB_STOR_TRANSPORT_ERROR;
+ 
+@@ -465,7 +469,7 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us,
+ 				data[1+(j<<1)] = data_out[j];
+ 			}
+ 
+-			result = usbat_bulk_write(us, data, num_registers*2);
++			result = usbat_bulk_write(us, data, num_registers*2, 0);
+ 			if (result != USB_STOR_XFER_GOOD)
+ 				return USB_STOR_TRANSPORT_ERROR;
+ 
+@@ -583,7 +587,7 @@ static int usbat_multiple_write(struct us_data *us,
+ 	}
+ 
+ 	/* Send the data */
+-	result = usbat_bulk_write(us, data, num_registers*2);
++	result = usbat_bulk_write(us, data, num_registers*2, 0);
+ 	if (result != USB_STOR_XFER_GOOD)
+ 		return USB_STOR_TRANSPORT_ERROR;
+ 
+@@ -606,8 +610,9 @@ static int usbat_multiple_write(struct us_data *us,
+  * other related details) are defined beforehand with _set_shuttle_features().
+  */
+ static int usbat_read_blocks(struct us_data *us,
+-							 unsigned char *buffer,
+-							 int len)
++			     unsigned char *buffer,
++			     int len,
++			     int use_sg)
+ {
+ 	int result;
+ 	unsigned char *command = us->iobuf;
+@@ -627,7 +632,7 @@ static int usbat_read_blocks(struct us_data *us,
+ 		return USB_STOR_TRANSPORT_FAILED;
+ 	
+ 	/* Read the blocks we just asked for */
+-	result = usbat_bulk_read(us, buffer, len);
++	result = usbat_bulk_read(us, buffer, len, use_sg);
+ 	if (result != USB_STOR_XFER_GOOD)
+ 		return USB_STOR_TRANSPORT_FAILED;
+ 
+@@ -648,7 +653,8 @@ static int usbat_read_blocks(struct us_data *us,
+  */
+ static int usbat_write_blocks(struct us_data *us,
+ 							  unsigned char *buffer,
+-							  int len)
++			      int len,
++			      int use_sg)
+ {
+ 	int result;
+ 	unsigned char *command = us->iobuf;
+@@ -668,7 +674,7 @@ static int usbat_write_blocks(struct us_data *us,
+ 		return USB_STOR_TRANSPORT_FAILED;
+ 	
+ 	/* Write the data */
+-	result = usbat_bulk_write(us, buffer, len);
++	result = usbat_bulk_write(us, buffer, len, use_sg);
+ 	if (result != USB_STOR_XFER_GOOD)
+ 		return USB_STOR_TRANSPORT_FAILED;
+ 
+@@ -947,7 +953,7 @@ static int usbat_flash_get_sector_count(struct us_data *us,
+ 	msleep(100);
+ 
+ 	/* Read the device identification data */
+-	rc = usbat_read_block(us, reply, 512);
++	rc = usbat_read_block(us, reply, 512, 0);
+ 	if (rc != USB_STOR_TRANSPORT_GOOD)
+ 		goto leave;
+ 
+@@ -1031,7 +1037,7 @@ static int usbat_flash_read_data(struct us_data *us,
+ 			goto leave;
+ 
+ 		/* Read the data we just requested */
+-		result = usbat_read_blocks(us, buffer, len);
++		result = usbat_read_blocks(us, buffer, len, 0);
+ 		if (result != USB_STOR_TRANSPORT_GOOD)
+ 			goto leave;
+   	 
+@@ -1125,7 +1131,7 @@ static int usbat_flash_write_data(struct us_data *us,
+ 			goto leave;
+ 
+ 		/* Write the data */
+-		result = usbat_write_blocks(us, buffer, len);
++		result = usbat_write_blocks(us, buffer, len, 0);
+ 		if (result != USB_STOR_TRANSPORT_GOOD)
+ 			goto leave;
+ 
+@@ -1503,10 +1509,10 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 	 * AT SPEED 4 IS UNRELIABLE!!!
+ 	 */
+ 
+-	if ( (result = usbat_write_block(us, 
++	if ((result = usbat_write_block(us,
+ 			USBAT_ATA, srb->cmnd, 12,
+-			srb->cmnd[0]==GPCMD_BLANK ? 75 : 10)) !=
+-				USB_STOR_TRANSPORT_GOOD) {
++				(srb->cmnd[0]==GPCMD_BLANK ? 75 : 10), 0) !=
++			     USB_STOR_TRANSPORT_GOOD)) {
+ 		return result;
+ 	}
+ 
+@@ -1533,7 +1539,7 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 			len = *status;
+ 
+ 
+-		result = usbat_read_block(us, srb->request_buffer, len);
++		result = usbat_read_block(us, srb->request_buffer, len, srb->use_sg);
+ 
+ 		/* Debug-print the first 32 bytes of the transfer */
+ 

commit 9ba89334552b96e2127dcafb1c46ce255ecf2667
+Author: Ian Wienand 
+Date:   Wed Jun 21 10:33:04 2006 +1000
+
+    [IA64] SKI Simulator boot
+    
+    Sorry I didn't notice earlier, but that BUG_ON triggers for me on the
+    simulator.  AFAICS the mask for itv is set in cpu_init(), which comes
+    after sal_init().  Consequently on the simulator the itv still has its
+    start value of zero.  I've probably missed something, but I wonder why
+    at this stage of the boot you even need to save and restore the itv?
+    
+    Signed-Off-By: Ian Wienand 
+    Signed-off-by: Tony Luck 
+
+diff --git a/arch/ia64/kernel/sal.c b/arch/ia64/kernel/sal.c
+index 056f7a6eedc7..77fa65903d94 100644
+--- a/arch/ia64/kernel/sal.c
++++ b/arch/ia64/kernel/sal.c
+@@ -227,7 +227,7 @@ static int sal_cache_flush_drops_interrupts;
+ static void __init
+ check_sal_cache_flush (void)
+ {
+-	unsigned long flags, itv;
++	unsigned long flags;
+ 	int cpu;
+ 	u64 vector;
+ 
+@@ -238,9 +238,6 @@ check_sal_cache_flush (void)
+ 	 * Schedule a timer interrupt, wait until it's reported, and see if
+ 	 * SAL_CACHE_FLUSH drops it.
+ 	 */
+-	itv = ia64_get_itv();
+-	BUG_ON((itv & (1 << 16)) == 0);
+-
+ 	ia64_set_itv(IA64_TIMER_VECTOR);
+ 	ia64_set_itm(ia64_get_itc() + 1000);
+ 
+@@ -260,7 +257,6 @@ check_sal_cache_flush (void)
+ 		ia64_eoi();
+ 	}
+ 
+-	ia64_set_itv(itv);
+ 	local_irq_restore(flags);
+ 	put_cpu();
+ }

commit 4dc6d9cc38cea1004a7f827cf76409ae42231fee
+Author: Peter Chubb 
+Date:   Thu Mar 23 21:39:47 2006 -0800
+
+    [BRIDGE]: Unaligned accesses in the ethernet bridge
+    
+    I see lots of
+            kernel unaligned access to 0xa0000001009dbb6f, ip=0xa000000100811591
+            kernel unaligned access to 0xa0000001009dbb6b, ip=0xa0000001008115c1
+            kernel unaligned access to 0xa0000001009dbb6d, ip=0xa0000001008115f1
+    messages in my logs on IA64 when using the ethernet bridge with 2.6.16.
+    
+    Appended is a patch to fix them.
+    
+    Signed-off-by: Peter Chubb 
+    Signed-off-by: Stephen Hemminger 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c
+index 8934a54792be..a7ba0cce0b46 100644
+--- a/net/bridge/br_stp_bpdu.c
++++ b/net/bridge/br_stp_bpdu.c
+@@ -19,6 +19,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include "br_private.h"
+ #include "br_private_stp.h"
+@@ -59,12 +60,12 @@ static inline void br_set_ticks(unsigned char *dest, int j)
+ {
+ 	unsigned long ticks = (STP_HZ * j)/ HZ;
+ 
+-	*((__be16 *) dest) = htons(ticks);
++	put_unaligned(htons(ticks), (__be16 *)dest);
+ }
+ 
+ static inline int br_get_ticks(const unsigned char *src)
+ {
+-	unsigned long ticks = ntohs(*(__be16 *)src);
++	unsigned long ticks = ntohs(get_unaligned((__be16 *)src));
+ 
+ 	return (ticks * HZ + STP_HZ - 1) / STP_HZ;
+ }

commit 44fd0261d3509b0b4303fd9ba792058d230186ab
+Author: Peter Chubb 
+Date:   Wed Nov 9 13:05:47 2005 -0800
+
+    [IPV6]: Fix fallout from CONFIG_IPV6_PRIVACY
+    
+    Trying to build today's 2.6.14+git snapshot gives undefined references
+    to use_tempaddr
+    
+    Looks like an ifdef got left out.
+    
+    Signed-off-by: Peter Chubb 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
+index b7a5f51238b3..ddcf7754eec2 100644
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -1022,6 +1022,7 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
+ 					continue;
+ 			}
+ 
++#ifdef CONFIG_IPV6_PRIVACY
+ 			/* Rule 7: Prefer public address
+ 			 * Note: prefer temprary address if use_tempaddr >= 2
+ 			 */
+@@ -1042,7 +1043,7 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
+ 				if (hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY)
+ 					continue;
+ 			}
+-
++#endif
+ 			/* Rule 8: Use longest matching prefix */
+ 			if (hiscore.rule < 8)
+ 				hiscore.matchlen = ipv6_addr_diff(&ifa_result->addr, daddr);

commit 7afada45da2727fd96402b1244168e0420ca496a
+Author: Ian Wienand 
+Date:   Wed Nov 2 22:49:10 2005 -0500
+
+    Input: convert dmasound_awacs (OSS) to dynamic input allocation
+    
+    Signed-off-by: Ian Wienand 
+    Signed-off-by: Dmitry Torokhov 
+
+diff --git a/sound/oss/dmasound/dmasound_awacs.c b/sound/oss/dmasound/dmasound_awacs.c
+index b2bf8bac842d..cebd881b91ae 100644
+--- a/sound/oss/dmasound/dmasound_awacs.c
++++ b/sound/oss/dmasound/dmasound_awacs.c
+@@ -2805,16 +2805,7 @@ __init setup_beep(void)
+ 	return 0 ;
+ }
+ 
+-static struct input_dev awacs_beep_dev = {
+-	.evbit		= { BIT(EV_SND) },
+-	.sndbit		= { BIT(SND_BELL) | BIT(SND_TONE) },
+-	.event		= awacs_beep_event,
+-	.name		= "dmasound beeper",
+-	.phys		= "macio/input0", /* what the heck is this?? */
+-	.id		= {
+-		.bustype	= BUS_HOST,
+-	},
+-};
++static struct input_dev *awacs_beep_dev;
+ 
+ int __init dmasound_awacs_init(void)
+ {
+@@ -2907,6 +2898,22 @@ printk("dmasound_pmac: couldn't find a Codec we can handle\n");
+ 		return -ENODEV;
+ 	}
+ 
++	awacs_beep_dev = input_allocate_device();
++	if (!awacs_beep_dev) {
++		release_OF_resource(io, 0);
++		release_OF_resource(io, 1);
++		release_OF_resource(io, 2);
++		printk(KERN_ERR "dmasound: can't allocate input device !\n");
++		return -ENOMEM;
++	}
++
++	awacs_beep_dev->name = "dmasound beeper";
++	awacs_beep_dev->phys = "macio/input0";
++	awacs_beep_dev->id.bustype = BUS_HOST;
++	awacs_beep_dev->event = awacs_beep_event;
++	awacs_beep_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
++	awacs_beep_dev->evbit[0] = BIT(EV_SND);
++
+ 	/* all OF versions I've seen use this value */
+ 	if (i2s_node)
+ 		i2s = ioremap(io->addrs[0].address, 0x1000);
+@@ -3140,14 +3147,14 @@ printk("dmasound_pmac: Awacs/Screamer Codec Mfct: %d Rev %d\n", mfg, rev);
+ 	 * XXX: we should handle errors here, but that would mean
+ 	 * rewriting the whole init code.  later..
+ 	 */
+-	input_register_device(&awacs_beep_dev);
++	input_register_device(awacs_beep_dev);
+ 
+ 	return dmasound_init();
+ }
+ 
+ static void __exit dmasound_awacs_cleanup(void)
+ {
+-	input_unregister_device(&awacs_beep_dev);
++	input_unregister_device(awacs_beep_dev);
+ 
+ 	switch (awacs_revision) {
+ 		case AWACS_TUMBLER:

commit b6a7e1ecef66b9ecd1eed31f46ba0248d6d7e957
+Author: Peter Chubb 
+Date:   Thu Oct 20 12:31:19 2005 +1000
+
+    [IA64] Allow simulator to use bigger disks
+    
+    The simscsi code at present overflows an int if it's given a large
+    disk image.  The attached patch increases the possible size to 128G.
+    While it's unlikely that anyone will want to use SKI with such a
+    large drive, the same framework is currently being used for various
+    virtualisation experiments.
+    
+    Signed-off-by: Peter Chubb 
+    Signed-off-by: Tony Luck 
+
+diff --git a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c
+index a18983a3c934..a3fe97531134 100644
+--- a/arch/ia64/hp/sim/simscsi.c
++++ b/arch/ia64/hp/sim/simscsi.c
+@@ -205,10 +205,11 @@ simscsi_get_disk_size (int fd)
+ 	char buf[512];
+ 
+ 	/*
+-	 * This is a bit kludgey: the simulator doesn't provide a direct way of determining
+-	 * the disk size, so we do a binary search, assuming a maximum disk size of 4GB.
++	 * This is a bit kludgey: the simulator doesn't provide a
++	 * direct way of determining the disk size, so we do a binary
++	 * search, assuming a maximum disk size of 128GB.
+ 	 */
+-	for (bit = (4UL << 30)/512; bit != 0; bit >>= 1) {
++	for (bit = (128UL << 30)/512; bit != 0; bit >>= 1) {
+ 		req.addr = __pa(&buf);
+ 		req.len = sizeof(buf);
+ 		ia64_ssc(fd, 1, __pa(&req), ((sectors | bit) - 1)*512, SSC_READ);
+@@ -225,8 +226,10 @@ simscsi_readwrite10 (struct scsi_cmnd *sc, int mode)
+ {
+ 	unsigned long offset;
+ 
+-	offset = (  (sc->cmnd[2] << 24) | (sc->cmnd[3] << 16)
+-		  | (sc->cmnd[4] <<  8) | (sc->cmnd[5] <<  0))*512;
++	offset = (((unsigned long)sc->cmnd[2] << 24) 
++		| ((unsigned long)sc->cmnd[3] << 16)
++		| ((unsigned long)sc->cmnd[4] <<  8) 
++		| ((unsigned long)sc->cmnd[5] <<  0))*512UL;
+ 	if (sc->use_sg > 0)
+ 		simscsi_sg_readwrite(sc, mode, offset);
+ 	else

commit 51b190b304bbeb1090ba20b0623d39917fa62997
+Author: Peter Chubb 
+Date:   Wed Oct 19 22:45:14 2005 -0700
+
+    [PATCH] `unaligned access' in acpi get_root_bridge_busnr()
+    
+    In drivers/acpi/glue.c the address of an integer is cast to the address of
+    an unsigned long.  This breaks on systems where a long is larger than an
+    int --- for a start the int can be misaligned; for a second the assignment
+    through the pointer will overwrite part of the next variable.
+    
+    Signed-off-by: Peter Chubb 
+    Acked-by: "Brown, Len" 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
+index e36c5da2b31a..3937adf4e5e5 100644
+--- a/drivers/acpi/glue.c
++++ b/drivers/acpi/glue.c
+@@ -96,7 +96,7 @@ struct acpi_find_pci_root {
+ static acpi_status
+ do_root_bridge_busnr_callback(struct acpi_resource *resource, void *data)
+ {
+-	int *busnr = (int *)data;
++	unsigned long *busnr = (unsigned long *)data;
+ 	struct acpi_resource_address64 address;
+ 
+ 	if (resource->id != ACPI_RSTYPE_ADDRESS16 &&
+@@ -115,13 +115,13 @@ do_root_bridge_busnr_callback(struct acpi_resource *resource, void *data)
+ static int get_root_bridge_busnr(acpi_handle handle)
+ {
+ 	acpi_status status;
+-	int bus, bbn;
++	unsigned long bus, bbn;
+ 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ 
+ 	acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+ 
+ 	status = acpi_evaluate_integer(handle, METHOD_NAME__BBN, NULL,
+-				       (unsigned long *)&bbn);
++				       &bbn);
+ 	if (status == AE_NOT_FOUND) {
+ 		/* Assume bus = 0 */
+ 		printk(KERN_INFO PREFIX
+@@ -153,7 +153,7 @@ static int get_root_bridge_busnr(acpi_handle handle)
+ 	}
+       exit:
+ 	acpi_os_free(buffer.pointer);
+-	return bbn;
++	return (int)bbn;
+ }
+ 
+ static acpi_status

commit 83a78d9ba792660418d692fd6737871aefdbff36
+Author: Peter Chubb 
+Date:   Mon Sep 19 09:36:12 2005 +1000
+
+    [IA64] Fix simscsi for new SCSI midlayer
+    
+    The sd driver now uses scsi_execute_req() for almost everything.
+    scsi_execute_req() converts requests into scatterlists.
+    
+    Fix the HP SCSI disk simulator to understand scatterlists for
+    more commands.
+    
+    Without this patch the current kernel will not boot on the simulator
+    (the disks are always detected as having no sectors, and so cannot be
+    mounted).
+    
+    Signed-off-by: Peter Chubb 
+    Signed-off-by: Tony Luck 
+
+diff --git a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c
+index 56405dbfd739..a18983a3c934 100644
+--- a/arch/ia64/hp/sim/simscsi.c
++++ b/arch/ia64/hp/sim/simscsi.c
+@@ -233,6 +233,23 @@ simscsi_readwrite10 (struct scsi_cmnd *sc, int mode)
+ 		simscsi_readwrite(sc, mode, offset, ((sc->cmnd[7] << 8) | sc->cmnd[8])*512);
+ }
+ 
++static void simscsi_fillresult(struct scsi_cmnd *sc, char *buf, unsigned len)
++{
++
++	int scatterlen = sc->use_sg;
++	struct scatterlist *slp;
++
++	if (scatterlen == 0)
++		memcpy(sc->request_buffer, buf, len);
++	else for (slp = (struct scatterlist *)sc->buffer; scatterlen-- > 0 && len > 0; slp++) {
++		unsigned thislen = min(len, slp->length);
++
++		memcpy(page_address(slp->page) + slp->offset, buf, thislen);
++		slp++;
++		len -= thislen;
++	}
++}
++
+ static int
+ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ {
+@@ -240,6 +257,7 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 	char fname[MAX_ROOT_LEN+16];
+ 	size_t disk_size;
+ 	char *buf;
++	char localbuf[36];
+ #if DEBUG_SIMSCSI
+ 	register long sp asm ("sp");
+ 
+@@ -263,7 +281,7 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 				/* disk doesn't exist... */
+ 				break;
+ 			}
+-			buf = sc->request_buffer;
++			buf = localbuf;
+ 			buf[0] = 0;	/* magnetic disk */
+ 			buf[1] = 0;	/* not a removable medium */
+ 			buf[2] = 2;	/* SCSI-2 compliant device */
+@@ -273,6 +291,7 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 			buf[6] = 0;	/* reserved */
+ 			buf[7] = 0;	/* various flags */
+ 			memcpy(buf + 8, "HP      SIMULATED DISK  0.00",  28);
++			simscsi_fillresult(sc, buf, 36);
+ 			sc->result = GOOD;
+ 			break;
+ 
+@@ -304,16 +323,13 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 			simscsi_readwrite10(sc, SSC_WRITE);
+ 			break;
+ 
+-
+ 		      case READ_CAPACITY:
+ 			if (desc[target_id] < 0 || sc->request_bufflen < 8) {
+ 				break;
+ 			}
+-			buf = sc->request_buffer;
+-
++			buf = localbuf;
+ 			disk_size = simscsi_get_disk_size(desc[target_id]);
+ 
+-			/* pretend to be a 1GB disk (partition table contains real stuff): */
+ 			buf[0] = (disk_size >> 24) & 0xff;
+ 			buf[1] = (disk_size >> 16) & 0xff;
+ 			buf[2] = (disk_size >>  8) & 0xff;
+@@ -323,13 +339,14 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 			buf[5] = 0;
+ 			buf[6] = 2;
+ 			buf[7] = 0;
++			simscsi_fillresult(sc, buf, 8);
+ 			sc->result = GOOD;
+ 			break;
+ 
+ 		      case MODE_SENSE:
+ 		      case MODE_SENSE_10:
+ 			/* sd.c uses this to determine whether disk does write-caching. */
+-			memset(sc->request_buffer, 0, 128);
++			simscsi_fillresult(sc, (char *)empty_zero_page, sc->request_bufflen);
+ 			sc->result = GOOD;
+ 			break;
+ 

commit 24b8e0cc09483adc0fdd9c68914b19597bb9fddc
+Author: Peter Chubb 
+Date:   Thu Sep 15 15:36:35 2005 +1000
+
+    [IA64] Remove warnings for gcc 4.0 IA64 compilation.
+    
+    This patch removes some compilation warnings, mostly
+    trivially. acpi.c fix also noted by Kenji Kaneshige.
+    
+    Signed-off-by; Peter Chubb 
+    Signed-off-by: Tony Luck 
+
+diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
+index 28a4529fdd60..7e926471e4ec 100644
+--- a/arch/ia64/kernel/acpi.c
++++ b/arch/ia64/kernel/acpi.c
+@@ -899,7 +899,7 @@ int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
+ 	if ((err = iosapic_init(phys_addr, gsi_base)))
+ 		return err;
+ 
+-#if CONFIG_ACPI_NUMA
++#ifdef CONFIG_ACPI_NUMA
+ 	acpi_map_iosapic(handle, 0, NULL, NULL);
+ #endif				/* CONFIG_ACPI_NUMA */
+ 
+diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
+index ba0b6a1f429f..0741b066b98f 100644
+--- a/arch/ia64/kernel/entry.S
++++ b/arch/ia64/kernel/entry.S
+@@ -491,7 +491,7 @@ GLOBAL_ENTRY(prefetch_stack)
+ 	;;
+ 	lfetch.fault [r16], 128
+ 	br.ret.sptk.many rp
+-END(prefetch_switch_stack)
++END(prefetch_stack)
+ 
+ GLOBAL_ENTRY(execve)
+ 	mov r15=__NR_execve			// put syscall number in place
+diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
+index 1650353e3f77..af42cda6be80 100644
+--- a/arch/ia64/kernel/perfmon.c
++++ b/arch/ia64/kernel/perfmon.c
+@@ -574,7 +574,7 @@ pfm_protect_ctx_ctxsw(pfm_context_t *x)
+ 	return 0UL;
+ }
+ 
+-static inline unsigned long
++static inline void
+ pfm_unprotect_ctx_ctxsw(pfm_context_t *x, unsigned long f)
+ {
+ 	spin_unlock(&(x)->ctx_lock);
+diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
+index 99762b6c19ae..de5d6d212674 100644
+--- a/drivers/char/agp/hp-agp.c
++++ b/drivers/char/agp/hp-agp.c
+@@ -252,7 +252,7 @@ hp_zx1_configure (void)
+ 		readl(hp->ioc_regs+HP_ZX1_PDIR_BASE);
+ 		writel(hp->io_tlb_ps, hp->ioc_regs+HP_ZX1_TCNFG);
+ 		readl(hp->ioc_regs+HP_ZX1_TCNFG);
+-		writel(~(HP_ZX1_IOVA_SIZE-1), hp->ioc_regs+HP_ZX1_IMASK);
++		writel((unsigned int)(~(HP_ZX1_IOVA_SIZE-1)), hp->ioc_regs+HP_ZX1_IMASK);
+ 		readl(hp->ioc_regs+HP_ZX1_IMASK);
+ 		writel(hp->iova_base|1, hp->ioc_regs+HP_ZX1_IBASE);
+ 		readl(hp->ioc_regs+HP_ZX1_IBASE);

commit dc85dec68880176c8ba05f68218a161964cada46
+Author: Peter Chubb 
+Date:   Sat Sep 3 14:05:06 2005 -0700
+
+    [PATCH] 'mdio_bus_exit' in discarded section .text.exit
+    
+    When building with  CONFIG_PHYLIB=y on Itanium, I see:
+     `mdio_bus_exit' referenced in section `.init.text' of
+    drivers/built-in.o: defined in discarded section `.exit.text' of
+    drivers/built-in.o
+    
+    I believe that mdio_bus_exit should not be declared __exit, because it is
+    referencesd from __init sections in, say, phy_init().
+    
+    Signed-off-by: Peter Chubb 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Jeff Garzik 
+
+diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
+index 5e81494e9a9a..90630672703d 100644
+--- a/drivers/net/phy/mdio_bus.c
++++ b/drivers/net/phy/mdio_bus.c
+@@ -170,7 +170,7 @@ int __init mdio_bus_init(void)
+ 	return bus_register(&mdio_bus_type);
+ }
+ 
+-void __exit mdio_bus_exit(void)
++void mdio_bus_exit(void)
+ {
+ 	bus_unregister(&mdio_bus_type);
+ }

commit 6cf07a8cc86a0b471466c7fe45892f7ef434015b
+Author: Peter Chubb 
+Date:   Tue Aug 23 20:07:00 2005 -0700
+
+    [IA64] Fix nasty VMLPT problem...
+    
+    I've solved the problem I was having with the simulator and not
+    booting Debian.
+    
+    The problem is that the number of bits for the virtual linear array
+    short-format VHPT (Virtually mapped linear page table, VMLPT for
+    short) is being tested incorrectly.
+    
+    There are two problems:
+          1. The PAL call that should tell the kernel the size of the
+          virtual address space isn't implemented for the simulator, so
+          the kernel uses the default 50.  This is addressed separately
+          in dc90e95f310f4f821c905b2aec8e9449bb3270fa
+    
+          2.  In arch/ia64/mm/init.c there's code to calcualte the size
+          of the VMLPT based on the number of implemented virtual address
+          bits and the page size.  It checks to see if the VMLPT base
+          address overlaps the top of the mapped region, but this check
+          doesn't allow for the address space hole, and in fact will
+          never trigger.
+    
+    Here's an alternative test and panic, that I think is more accurate.
+    
+    Signed-off-by: Peter Chubb 
+    Signed-off-by: Tony Luck 
+
+diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
+index 65f9958db9f0..1281c609ee98 100644
+--- a/arch/ia64/mm/init.c
++++ b/arch/ia64/mm/init.c
+@@ -382,13 +382,22 @@ ia64_mmu_init (void *my_cpu_data)
+ 
+ 	if (impl_va_bits < 51 || impl_va_bits > 61)
+ 		panic("CPU has bogus IMPL_VA_MSB value of %lu!\n", impl_va_bits - 1);
++	/*
++	 * mapped_space_bits - PAGE_SHIFT is the total number of ptes we need,
++	 * which must fit into "vmlpt_bits - pte_bits" slots. Second half of
++	 * the test makes sure that our mapped space doesn't overlap the
++	 * unimplemented hole in the middle of the region.
++	 */
++	if ((mapped_space_bits - PAGE_SHIFT > vmlpt_bits - pte_bits) ||
++	    (mapped_space_bits > impl_va_bits - 1))
++		panic("Cannot build a big enough virtual-linear page table"
++		      " to cover mapped address space.\n"
++		      " Try using a smaller page size.\n");
++
+ 
+ 	/* place the VMLPT at the end of each page-table mapped region: */
+ 	pta = POW2(61) - POW2(vmlpt_bits);
+ 
+-	if (POW2(mapped_space_bits) >= pta)
+-		panic("mm/init: overlap between virtually mapped linear page table and "
+-		      "mapped kernel space!");
+ 	/*
+ 	 * Set the (virtually mapped linear) page table address.  Bit
+ 	 * 8 selects between the short and long format, bits 2-7 the

commit 714d2dc14914f0f7bb008effe830c99eb47c75df
+Author: Peter Chubb 
+Date:   Thu Aug 25 17:39:00 2005 -0700
+
+    [IA64] Allow /proc/pal/cpu0/vm_info under the simulator
+    
+    Not all of the PAL VM calls are implemented for the SKI simulator.
+    Don't just give up if one fails, print information from the calls
+    that succeed.
+    
+    Signed-off-by: Peter Chubb 
+    Signed-off-by: Tony Luck 
+
+diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
+index 25e7c8344564..89faa603c6be 100644
+--- a/arch/ia64/kernel/palinfo.c
++++ b/arch/ia64/kernel/palinfo.c
+@@ -307,11 +307,9 @@ vm_info(char *page)
+ 
+ 	if ((status = ia64_pal_vm_summary(&vm_info_1, &vm_info_2)) !=0) {
+ 		printk(KERN_ERR "ia64_pal_vm_summary=%ld\n", status);
+-		return 0;
+-	}
++	} else {
+ 
+-
+-	p += sprintf(p,
++		p += sprintf(p,
+ 		     "Physical Address Space         : %d bits\n"
+ 		     "Virtual Address Space          : %d bits\n"
+ 		     "Protection Key Registers(PKR)  : %d\n"
+@@ -319,92 +317,99 @@ vm_info(char *page)
+ 		     "Hash Tag ID                    : 0x%x\n"
+ 		     "Size of RR.rid                 : %d\n",
+ 		     vm_info_1.pal_vm_info_1_s.phys_add_size,
+-		     vm_info_2.pal_vm_info_2_s.impl_va_msb+1, vm_info_1.pal_vm_info_1_s.max_pkr+1,
+-		     vm_info_1.pal_vm_info_1_s.key_size, vm_info_1.pal_vm_info_1_s.hash_tag_id,
++		     vm_info_2.pal_vm_info_2_s.impl_va_msb+1,
++		     vm_info_1.pal_vm_info_1_s.max_pkr+1,
++		     vm_info_1.pal_vm_info_1_s.key_size,
++		     vm_info_1.pal_vm_info_1_s.hash_tag_id,
+ 		     vm_info_2.pal_vm_info_2_s.rid_size);
++	}
+ 
+-	if (ia64_pal_mem_attrib(&attrib) != 0)
+-		return 0;
+-
+-	p += sprintf(p, "Supported memory attributes    : ");
+-	sep = "";
+-	for (i = 0; i < 8; i++) {
+-		if (attrib & (1 << i)) {
+-			p += sprintf(p, "%s%s", sep, mem_attrib[i]);
+-			sep = ", ";
++	if (ia64_pal_mem_attrib(&attrib) == 0) {
++		p += sprintf(p, "Supported memory attributes    : ");
++		sep = "";
++		for (i = 0; i < 8; i++) {
++			if (attrib & (1 << i)) {
++				p += sprintf(p, "%s%s", sep, mem_attrib[i]);
++				sep = ", ";
++			}
+ 		}
++		p += sprintf(p, "\n");
+ 	}
+-	p += sprintf(p, "\n");
+ 
+ 	if ((status = ia64_pal_vm_page_size(&tr_pages, &vw_pages)) !=0) {
+ 		printk(KERN_ERR "ia64_pal_vm_page_size=%ld\n", status);
+-		return 0;
+-	}
+-
+-	p += sprintf(p,
+-		     "\nTLB walker                     : %simplemented\n"
+-		     "Number of DTR                  : %d\n"
+-		     "Number of ITR                  : %d\n"
+-		     "TLB insertable page sizes      : ",
+-		     vm_info_1.pal_vm_info_1_s.vw ? "" : "not ",
+-		     vm_info_1.pal_vm_info_1_s.max_dtr_entry+1,
+-		     vm_info_1.pal_vm_info_1_s.max_itr_entry+1);
++	} else {
+ 
++		p += sprintf(p,
++			     "\nTLB walker                     : %simplemented\n"
++			     "Number of DTR                  : %d\n"
++			     "Number of ITR                  : %d\n"
++			     "TLB insertable page sizes      : ",
++			     vm_info_1.pal_vm_info_1_s.vw ? "" : "not ",
++			     vm_info_1.pal_vm_info_1_s.max_dtr_entry+1,
++			     vm_info_1.pal_vm_info_1_s.max_itr_entry+1);
+ 
+-	p = bitvector_process(p, tr_pages);
+ 
+-	p += sprintf(p, "\nTLB purgeable page sizes       : ");
++		p = bitvector_process(p, tr_pages);
+ 
+-	p = bitvector_process(p, vw_pages);
++		p += sprintf(p, "\nTLB purgeable page sizes       : ");
+ 
++		p = bitvector_process(p, vw_pages);
++	}
+ 	if ((status=ia64_get_ptce(&ptce)) != 0) {
+ 		printk(KERN_ERR "ia64_get_ptce=%ld\n", status);
+-		return 0;
+-	}
+-
+-	p += sprintf(p,
++	} else {
++		p += sprintf(p,
+ 		     "\nPurge base address             : 0x%016lx\n"
+ 		     "Purge outer loop count         : %d\n"
+ 		     "Purge inner loop count         : %d\n"
+ 		     "Purge outer loop stride        : %d\n"
+ 		     "Purge inner loop stride        : %d\n",
+-		     ptce.base, ptce.count[0], ptce.count[1], ptce.stride[0], ptce.stride[1]);
++		     ptce.base, ptce.count[0], ptce.count[1],
++		     ptce.stride[0], ptce.stride[1]);
+ 
+-	p += sprintf(p,
++		p += sprintf(p,
+ 		     "TC Levels                      : %d\n"
+ 		     "Unique TC(s)                   : %d\n",
+ 		     vm_info_1.pal_vm_info_1_s.num_tc_levels,
+ 		     vm_info_1.pal_vm_info_1_s.max_unique_tcs);
+ 
+-	for(i=0; i < vm_info_1.pal_vm_info_1_s.num_tc_levels; i++) {
+-		for (j=2; j>0 ; j--) {
+-			tc_pages = 0; /* just in case */
++		for(i=0; i < vm_info_1.pal_vm_info_1_s.num_tc_levels; i++) {
++			for (j=2; j>0 ; j--) {
++				tc_pages = 0; /* just in case */
+ 
+ 
+-			/* even without unification, some levels may not be present */
+-			if ((status=ia64_pal_vm_info(i,j, &tc_info, &tc_pages)) != 0) {
+-				continue;
+-			}
++				/* even without unification, some levels may not be present */
++				if ((status=ia64_pal_vm_info(i,j, &tc_info, &tc_pages)) != 0) {
++					continue;
++				}
+ 
+-			p += sprintf(p,
++				p += sprintf(p,
+ 				     "\n%s Translation Cache Level %d:\n"
+ 				     "\tHash sets           : %d\n"
+ 				     "\tAssociativity       : %d\n"
+ 				     "\tNumber of entries   : %d\n"
+ 				     "\tFlags               : ",
+-				     cache_types[j+tc_info.tc_unified], i+1, tc_info.tc_num_sets,
+-				     tc_info.tc_associativity, tc_info.tc_num_entries);
++				     cache_types[j+tc_info.tc_unified], i+1,
++				     tc_info.tc_num_sets,
++				     tc_info.tc_associativity,
++				     tc_info.tc_num_entries);
+ 
+-			if (tc_info.tc_pf) p += sprintf(p, "PreferredPageSizeOptimized ");
+-			if (tc_info.tc_unified) p += sprintf(p, "Unified ");
+-			if (tc_info.tc_reduce_tr) p += sprintf(p, "TCReduction");
++				if (tc_info.tc_pf)
++					p += sprintf(p, "PreferredPageSizeOptimized ");
++				if (tc_info.tc_unified)
++					p += sprintf(p, "Unified ");
++				if (tc_info.tc_reduce_tr)
++					p += sprintf(p, "TCReduction");
+ 
+-			p += sprintf(p, "\n\tSupported page sizes: ");
++				p += sprintf(p, "\n\tSupported page sizes: ");
+ 
+-			p = bitvector_process(p, tc_pages);
++				p = bitvector_process(p, tc_pages);
+ 
+-			/* when unified date (j=2) is enough */
+-			if (tc_info.tc_unified) break;
++				/* when unified date (j=2) is enough */
++				if (tc_info.tc_unified)
++					break;
++			}
+ 		}
+ 	}
+ 	p += sprintf(p, "\n");
+@@ -440,14 +445,14 @@ register_info(char *page)
+ 		p += sprintf(p, "\n");
+ 	}
+ 
+-	if (ia64_pal_rse_info(&phys_stacked, &hints) != 0) return 0;
++	if (ia64_pal_rse_info(&phys_stacked, &hints) == 0) {
+ 
+ 	p += sprintf(p,
+ 		     "RSE stacked physical registers   : %ld\n"
+ 		     "RSE load/store hints             : %ld (%s)\n",
+ 		     phys_stacked, hints.ph_data,
+ 		     hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(??)");
+-
++	}
+ 	if (ia64_pal_debug_info(&iregs, &dregs))
+ 		return 0;
+ 

commit dc90e95f310f4f821c905b2aec8e9449bb3270fa
+Author: Peter Chubb 
+Date:   Wed Aug 24 17:13:00 2005 -0700
+
+    [IA64] Add PAL_VM_SUMMARY/PAL_MEM_ATTRIB to bootloader for SKI
+    
+    This patch implements PAL_VM_SUMMARY (and PAL_MEM_ATTRIB for good
+    measure) and pretends that the simulated machine is a McKinley.
+    
+    Some extra comments and clean-up by Tony Luck.
+    
+    Signed-off-by: Peter Chubb 
+    Signed-off-by: Tony Luck 
+
+diff --git a/arch/ia64/hp/sim/boot/boot_head.S b/arch/ia64/hp/sim/boot/boot_head.S
+index 1c8c7e6a9a5e..a9bd71ac78e2 100644
+--- a/arch/ia64/hp/sim/boot/boot_head.S
++++ b/arch/ia64/hp/sim/boot/boot_head.S
+@@ -4,6 +4,7 @@
+  */
+ 
+ #include 
++#include 
+ 
+ 	.bss
+ 	.align 16
+@@ -49,7 +50,11 @@ GLOBAL_ENTRY(jmp_to_kernel)
+ 	br.sptk.few b7
+ END(jmp_to_kernel)
+ 
+-
++/*
++ * r28 contains the index of the PAL function
++ * r29--31 the args
++ * Return values in ret0--3 (r8--11)
++ */
+ GLOBAL_ENTRY(pal_emulator_static)
+ 	mov r8=-1
+ 	mov r9=256
+@@ -62,7 +67,7 @@ GLOBAL_ENTRY(pal_emulator_static)
+ 	cmp.gtu p6,p7=r9,r28
+ (p6)	br.cond.sptk.few stacked
+ 	;;
+-static:	cmp.eq p6,p7=6,r28		/* PAL_PTCE_INFO */
++static:	cmp.eq p6,p7=PAL_PTCE_INFO,r28
+ (p7)	br.cond.sptk.few 1f
+ 	;;
+ 	mov r8=0			/* status = 0 */
+@@ -70,21 +75,21 @@ static:	cmp.eq p6,p7=6,r28		/* PAL_PTCE_INFO */
+ 	movl r10=0x0000000200000003	/* count[0], count[1] */
+ 	movl r11=0x1000000000002000	/* stride[0], stride[1] */
+ 	br.cond.sptk.few rp
+-1:	cmp.eq p6,p7=14,r28		/* PAL_FREQ_RATIOS */
++1:	cmp.eq p6,p7=PAL_FREQ_RATIOS,r28
+ (p7)	br.cond.sptk.few 1f
+ 	mov r8=0			/* status = 0 */
+ 	movl r9 =0x100000064		/* proc_ratio (1/100) */
+ 	movl r10=0x100000100		/* bus_ratio<<32 (1/256) */
+ 	movl r11=0x100000064		/* itc_ratio<<32 (1/100) */
+ 	;;
+-1:	cmp.eq p6,p7=19,r28		/* PAL_RSE_INFO */
++1:	cmp.eq p6,p7=PAL_RSE_INFO,r28
+ (p7)	br.cond.sptk.few 1f
+ 	mov r8=0			/* status = 0 */
+ 	mov r9=96			/* num phys stacked */
+ 	mov r10=0			/* hints */
+ 	mov r11=0
+ 	br.cond.sptk.few rp
+-1:	cmp.eq p6,p7=1,r28		/* PAL_CACHE_FLUSH */
++1:	cmp.eq p6,p7=PAL_CACHE_FLUSH,r28		/* PAL_CACHE_FLUSH */
+ (p7)	br.cond.sptk.few 1f
+ 	mov r9=ar.lc
+ 	movl r8=524288			/* flush 512k million cache lines (16MB) */
+@@ -102,7 +107,7 @@ static:	cmp.eq p6,p7=6,r28		/* PAL_PTCE_INFO */
+ 	mov ar.lc=r9
+ 	mov r8=r0
+ 	;;
+-1:	cmp.eq p6,p7=15,r28		/* PAL_PERF_MON_INFO */
++1:	cmp.eq p6,p7=PAL_PERF_MON_INFO,r28
+ (p7)	br.cond.sptk.few 1f
+ 	mov r8=0			/* status = 0 */
+ 	movl r9 =0x08122f04		/* generic=4 width=47 retired=8 cycles=18 */
+@@ -138,6 +143,20 @@ static:	cmp.eq p6,p7=6,r28		/* PAL_PTCE_INFO */
+ 	st8 [r29]=r0,16			/* clear remaining bits  */
+ 	st8 [r18]=r0,16			/* clear remaining bits  */
+ 	;;
++1:	cmp.eq p6,p7=PAL_VM_SUMMARY,r28
++(p7)	br.cond.sptk.few 1f
++	mov	r8=0			/* status = 0  */
++	movl	r9=0x2044040020F1865	/* num_tc_levels=2, num_unique_tcs=4 */
++					/* max_itr_entry=64, max_dtr_entry=64 */
++					/* hash_tag_id=2, max_pkr=15 */
++					/* key_size=24, phys_add_size=50, vw=1 */
++	movl	r10=0x183C		/* rid_size=24, impl_va_msb=60 */
++	;;
++1:	cmp.eq p6,p7=PAL_MEM_ATTRIB,r28
++(p7)	br.cond.sptk.few 1f
++	mov	r8=0			/* status = 0 */
++	mov	r9=0x80|0x01		/* NatPage|WB */
++	;;
+ 1:	br.cond.sptk.few rp
+ stacked:
+ 	br.ret.sptk.few rp

commit 0a41e2501160587eb8f66cef3bdf1c6f2cb86997
+Author: Peter Chubb 
+Date:   Tue Aug 16 19:54:00 2005 -0700
+
+    [IA64] Rationalise Region Definitions
+    
+    Currently, region numbers are defined in several files, with several
+    names.  For example, we have REGION_KERNEL in asm/page.h and
+    RGN_KERNEL in pgtable.h
+    
+    We also have address definitions that should depend on the
+    RGN_XXX macros, but are currently just long constants.
+    
+    The following patch reorganises all the definitions so that they have
+    the same form (RGN_XXX), are in one place, and that addresses that
+    depend on RGN_XXX are derived from them.
+    
+    (This is a necessary but not sufficient patch to allow UML-like
+    operation on IA64).
+    
+    Thanks to David Mosberger for catching the change I missed in mmu_context.h.
+    
+    Signed-off-by: Peter Chubb 
+    Signed-off-by: Tony Luck 
+
+diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c
+index 770fab37928e..f2dbcd1db0d4 100644
+--- a/arch/ia64/kernel/sys_ia64.c
++++ b/arch/ia64/kernel/sys_ia64.c
+@@ -35,7 +35,7 @@ arch_get_unmapped_area (struct file *filp, unsigned long addr, unsigned long len
+ 		return -ENOMEM;
+ 
+ #ifdef CONFIG_HUGETLB_PAGE
+-	if (REGION_NUMBER(addr) == REGION_HPAGE)
++	if (REGION_NUMBER(addr) == RGN_HPAGE)
+ 		addr = 0;
+ #endif
+ 	if (!addr)
+diff --git a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c
+index e0a776a3044c..2d13889d0a99 100644
+--- a/arch/ia64/mm/hugetlbpage.c
++++ b/arch/ia64/mm/hugetlbpage.c
+@@ -76,7 +76,7 @@ int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
+ 		return -EINVAL;
+ 	if (addr & ~HPAGE_MASK)
+ 		return -EINVAL;
+-	if (REGION_NUMBER(addr) != REGION_HPAGE)
++	if (REGION_NUMBER(addr) != RGN_HPAGE)
+ 		return -EINVAL;
+ 
+ 	return 0;
+@@ -87,7 +87,7 @@ struct page *follow_huge_addr(struct mm_struct *mm, unsigned long addr, int writ
+ 	struct page *page;
+ 	pte_t *ptep;
+ 
+-	if (REGION_NUMBER(addr) != REGION_HPAGE)
++	if (REGION_NUMBER(addr) != RGN_HPAGE)
+ 		return ERR_PTR(-EINVAL);
+ 
+ 	ptep = huge_pte_offset(mm, addr);
+@@ -142,8 +142,8 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, u
+ 		return -ENOMEM;
+ 	if (len & ~HPAGE_MASK)
+ 		return -EINVAL;
+-	/* This code assumes that REGION_HPAGE != 0. */
+-	if ((REGION_NUMBER(addr) != REGION_HPAGE) || (addr & (HPAGE_SIZE - 1)))
++	/* This code assumes that RGN_HPAGE != 0. */
++	if ((REGION_NUMBER(addr) != RGN_HPAGE) || (addr & (HPAGE_SIZE - 1)))
+ 		addr = HPAGE_REGION_BASE;
+ 	else
+ 		addr = ALIGN(addr, HPAGE_SIZE);
+diff --git a/include/asm-ia64/io.h b/include/asm-ia64/io.h
+index 54e7637a326c..3c28eeb0b009 100644
+--- a/include/asm-ia64/io.h
++++ b/include/asm-ia64/io.h
+@@ -23,7 +23,7 @@
+ #define __SLOW_DOWN_IO	do { } while (0)
+ #define SLOW_DOWN_IO	do { } while (0)
+ 
+-#define __IA64_UNCACHED_OFFSET	0xc000000000000000UL	/* region 6 */
++#define __IA64_UNCACHED_OFFSET	RGN_BASE(RGN_UNCACHED)
+ 
+ /*
+  * The legacy I/O space defined by the ia64 architecture supports only 65536 ports, but
+diff --git a/include/asm-ia64/mmu_context.h b/include/asm-ia64/mmu_context.h
+index e3e5fededb04..ab60a6a26911 100644
+--- a/include/asm-ia64/mmu_context.h
++++ b/include/asm-ia64/mmu_context.h
+@@ -19,6 +19,7 @@
+ 
+ #define ia64_rid(ctx,addr)	(((ctx) << 3) | (addr >> 61))
+ 
++# include 
+ # ifndef __ASSEMBLY__
+ 
+ #include 
+@@ -110,7 +111,7 @@ reload_context (mm_context_t context)
+ 	unsigned long rid_incr = 0;
+ 	unsigned long rr0, rr1, rr2, rr3, rr4, old_rr4;
+ 
+-	old_rr4 = ia64_get_rr(0x8000000000000000UL);
++	old_rr4 = ia64_get_rr(RGN_BASE(RGN_HPAGE));
+ 	rid = context << 3;	/* make space for encoding the region number */
+ 	rid_incr = 1 << 8;
+ 
+@@ -122,6 +123,10 @@ reload_context (mm_context_t context)
+ 	rr4 = rr0 + 4*rid_incr;
+ #ifdef  CONFIG_HUGETLB_PAGE
+ 	rr4 = (rr4 & (~(0xfcUL))) | (old_rr4 & 0xfc);
++
++#  if RGN_HPAGE != 4
++#    error "reload_context assumes RGN_HPAGE is 4"
++#  endif
+ #endif
+ 
+ 	ia64_set_rr(0x0000000000000000UL, rr0);
+diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h
+index 08894f73abf0..ec17f9e9da75 100644
+--- a/include/asm-ia64/page.h
++++ b/include/asm-ia64/page.h
+@@ -12,6 +12,19 @@
+ #include 
+ #include 
+ 
++/*
++ * The top three bits of an IA64 address are its Region Number.
++ * Different regions are assigned to different purposes.
++ */
++#define RGN_SHIFT	(61)
++#define RGN_BASE(r)  (__IA64_UL_CONST(r)<> (HPAGE_SHIFT-PAGE_SHIFT)))
+ # define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
+ # define is_hugepage_only_range(mm, addr, len)		\
+-	 (REGION_NUMBER(addr) == REGION_HPAGE &&	\
+-	  REGION_NUMBER((addr)+(len)-1) == REGION_HPAGE)
++	 (REGION_NUMBER(addr) == RGN_HPAGE &&	\
++	  REGION_NUMBER((addr)+(len)-1) == RGN_HPAGE)
+ extern unsigned int hpage_shift;
+ #endif
+ 
+@@ -197,7 +206,7 @@ get_order (unsigned long size)
+ # define __pgprot(x)	(x)
+ #endif /* !STRICT_MM_TYPECHECKS */
+ 
+-#define PAGE_OFFSET			__IA64_UL_CONST(0xe000000000000000)
++#define PAGE_OFFSET			RGN_BASE(RGN_KERNEL)
+ 
+ #define VM_DATA_DEFAULT_FLAGS		(VM_READ | VM_WRITE |					\
+ 					 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC |		\
+diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
+index 48586e08f432..2e34c06e6777 100644
+--- a/include/asm-ia64/pgtable.h
++++ b/include/asm-ia64/pgtable.h
+@@ -204,21 +204,18 @@ ia64_phys_addr_valid (unsigned long addr)
+ #define set_pte(ptep, pteval)	(*(ptep) = (pteval))
+ #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
+ 
+-#define RGN_SIZE	(1UL << 61)
+-#define RGN_KERNEL	7
+-
+-#define VMALLOC_START		0xa000000200000000UL
++#define VMALLOC_START		(RGN_BASE(RGN_GATE) + 0x200000000UL)
+ #ifdef CONFIG_VIRTUAL_MEM_MAP
+-# define VMALLOC_END_INIT	(0xa000000000000000UL + (1UL << (4*PAGE_SHIFT - 9)))
++# define VMALLOC_END_INIT	(RGN_BASE(RGN_GATE) + (1UL << (4*PAGE_SHIFT - 9)))
+ # define VMALLOC_END		vmalloc_end
+   extern unsigned long vmalloc_end;
+ #else
+-# define VMALLOC_END		(0xa000000000000000UL + (1UL << (4*PAGE_SHIFT - 9)))
++# define VMALLOC_END		(RGN_BASE(RGN_GATE) + (1UL << (4*PAGE_SHIFT - 9)))
+ #endif
+ 
+ /* fs/proc/kcore.c */
+-#define	kc_vaddr_to_offset(v) ((v) - 0xa000000000000000UL)
+-#define	kc_offset_to_vaddr(o) ((o) + 0xa000000000000000UL)
++#define	kc_vaddr_to_offset(v) ((v) - RGN_BASE(RGN_GATE))
++#define	kc_offset_to_vaddr(o) ((o) + RGN_BASE(RGN_GATE))
+ 
+ /*
+  * Conversion functions: convert page frame number (pfn) and a protection value to a page
+diff --git a/include/asm-ia64/system.h b/include/asm-ia64/system.h
+index cd2cf76b2db1..33256db4a7cf 100644
+--- a/include/asm-ia64/system.h
++++ b/include/asm-ia64/system.h
+@@ -19,12 +19,13 @@
+ #include 
+ #include 
+ 
+-#define GATE_ADDR		__IA64_UL_CONST(0xa000000000000000)
++#define GATE_ADDR		RGN_BASE(RGN_GATE)
++
+ /*
+  * 0xa000000000000000+2*PERCPU_PAGE_SIZE
+  * - 0xa000000000000000+3*PERCPU_PAGE_SIZE remain unmapped (guard page)
+  */
+-#define KERNEL_START		 __IA64_UL_CONST(0xa000000100000000)
++#define KERNEL_START		 (GATE_ADDR+0x100000000)
+ #define PERCPU_ADDR		(-PERCPU_PAGE_SIZE)
+ 
+ #ifndef __ASSEMBLY__

commit a4cce10492358b33d33bb43f98284c80482037e8
+Author: Peter Chubb 
+Date:   Mon Aug 22 17:50:00 2005 -0700
+
+    [IA64] Fix simulator boot (for real this time).
+    
+    Thanks to Stephane, we've now worked out the real cause of the
+    `Linux  will not boot on simulator' problem.  Turns out it's a stack
+    overflow because the stack pointer wasn't being initialised properly
+    in boot_head.S (it was being initialised to the lowest instead of the
+    highest address of the stack, so the first push started to overwrite
+    data in the BSS).
+    
+    Signed-off-by: Peter Chubb 
+    Signed-off-by: Tony Luck 
+
+diff --git a/arch/ia64/hp/sim/boot/boot_head.S b/arch/ia64/hp/sim/boot/boot_head.S
+index 9364199e5632..1c8c7e6a9a5e 100644
+--- a/arch/ia64/hp/sim/boot/boot_head.S
++++ b/arch/ia64/hp/sim/boot/boot_head.S
+@@ -22,7 +22,7 @@ GLOBAL_ENTRY(_start)
+ 	.save rp, r0
+ 	.body
+ 	movl gp = __gp
+-	movl sp = stack_mem
++	movl sp = stack_mem+16384-16
+ 	bsw.1
+ 	br.call.sptk.many rp=start_bootloader
+ END(_start)

commit 4aec0fb12267718c750475f3404337ad13caa8f5
+Author: Ian Wienand 
+Date:   Tue Jul 19 22:32:00 2005 -0700
+
+    [IA64] Simulator bootloader fails with gcc 4
+    After building a fresh tree with gcc 4 I can't boot the simulator as
+    the bootloader loader dies with
+    
+    loading /home/ianw/kerntest/kerncomp//build/sim_defconfig/vmlinux...
+    failed to read phdr
+    
+    After some investigation I believe this is do with differences between
+    the alignment of variables on the stack between gcc 3 and 4 and the
+    ski simulator.  If you trace through with the simulator you can see
+    that the disk_stat structure value returned from the SSC_WAIT_COMPLETION
+    call seems to be only half loaded.  I guess it doesn't like the alignment
+    of the input.
+    
+    Signed-off-by: Ian Wienand 
+    Signed-off-by: Tony Luck 
+
+diff --git a/arch/ia64/hp/sim/boot/bootloader.c b/arch/ia64/hp/sim/boot/bootloader.c
+index 51a7b7b4dd0e..a7bed60b69f9 100644
+--- a/arch/ia64/hp/sim/boot/bootloader.c
++++ b/arch/ia64/hp/sim/boot/bootloader.c
+@@ -30,10 +30,14 @@ struct disk_req {
+ 	unsigned len;
+ };
+ 
++/* SSC_WAIT_COMPLETION appears to want this large alignment.  gcc < 4
++ * seems to give it by default, however gcc > 4 is smarter and may
++ * not.
++ */
+ struct disk_stat {
+ 	int fd;
+ 	unsigned count;
+-};
++} __attribute__ ((aligned (16)));
+ 
+ extern void jmp_to_kernel (unsigned long bp, unsigned long e_entry);
+ extern struct ia64_boot_param *sys_fw_init (const char *args, int arglen);

commit 7f09d6f935aaa91f71fe64d64013ad3bd2a9d2f4
+Author: Peter Chubb 
+Date:   Tue Aug 16 17:27:00 2005 -0700
+
+    [IA64] Updated zx1 defconfig
+    
+    Just `make oldconfig' doesn't help for the zx1 defconfig ---
+    because we need the MPT Fusion drivers, which are picked up as not
+    selected.
+    Tested on HP ZX2000 and ZX2600.
+    
+    Signed-off-by: Peter Chubb 
+    Signed-off-by: Tony Luck 
+
+diff --git a/arch/ia64/configs/zx1_defconfig b/arch/ia64/configs/zx1_defconfig
+index b7755e4436d2..88e8867fa8e8 100644
+--- a/arch/ia64/configs/zx1_defconfig
++++ b/arch/ia64/configs/zx1_defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.13-rc1-20050629
+-# Wed Jun 29 15:31:11 2005
++# Linux kernel version: 2.6.13-rc6
++# Wed Aug 17 10:02:43 2005
+ #
+ 
+ #
+@@ -132,6 +132,7 @@ CONFIG_ACPI_BOOT=y
+ CONFIG_ACPI_INTERPRETER=y
+ CONFIG_ACPI_BUTTON=y
+ CONFIG_ACPI_VIDEO=m
++CONFIG_ACPI_HOTKEY=m
+ CONFIG_ACPI_FAN=y
+ CONFIG_ACPI_PROCESSOR=y
+ CONFIG_ACPI_THERMAL=y
+@@ -168,6 +169,83 @@ CONFIG_HOTPLUG_PCI_ACPI=y
+ #
+ # CONFIG_PCCARD is not set
+ 
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++# CONFIG_IP_PNP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_IP_TCPDIAG is not set
++# CONFIG_IP_TCPDIAG_IPV6 is not set
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_BIC=y
++
++#
++# IP: Virtual Server Configuration
++#
++# CONFIG_IP_VS is not set
++# CONFIG_IPV6 is not set
++CONFIG_NETFILTER=y
++# CONFIG_NETFILTER_DEBUG is not set
++
++#
++# IP: Netfilter Configuration
++#
++# CONFIG_IP_NF_CONNTRACK is not set
++# CONFIG_IP_NF_CONNTRACK_MARK is not set
++# CONFIG_IP_NF_QUEUE is not set
++# CONFIG_IP_NF_IPTABLES is not set
++CONFIG_IP_NF_ARPTABLES=y
++# CONFIG_IP_NF_ARPFILTER is not set
++# CONFIG_IP_NF_ARP_MANGLE is not set
++
++#
++# SCTP Configuration (EXPERIMENTAL)
++#
++# CONFIG_IP_SCTP is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_NET_DIVERT is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++# CONFIG_NET_CLS_ROUTE is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++
+ #
+ # Device Drivers
+ #
+@@ -349,6 +427,7 @@ CONFIG_SCSI_QLA2XXX=y
+ # CONFIG_SCSI_QLA2300 is not set
+ # CONFIG_SCSI_QLA2322 is not set
+ # CONFIG_SCSI_QLA6312 is not set
++# CONFIG_SCSI_QLA24XX is not set
+ # CONFIG_SCSI_LPFC is not set
+ # CONFIG_SCSI_DC395x is not set
+ # CONFIG_SCSI_DC390T is not set
+@@ -362,9 +441,11 @@ CONFIG_SCSI_QLA2XXX=y
+ #
+ # Fusion MPT device support
+ #
+-# CONFIG_FUSION is not set
+-# CONFIG_FUSION_SPI is not set
+-# CONFIG_FUSION_FC is not set
++CONFIG_FUSION=y
++CONFIG_FUSION_SPI=y
++CONFIG_FUSION_FC=y
++CONFIG_FUSION_MAX_SGE=128
++CONFIG_FUSION_CTL=m
+ 
+ #
+ # IEEE 1394 (FireWire) support
+@@ -377,87 +458,8 @@ CONFIG_SCSI_QLA2XXX=y
+ # CONFIG_I2O is not set
+ 
+ #
+-# Networking support
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-# CONFIG_IP_PNP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_TUNNEL is not set
+-# CONFIG_IP_TCPDIAG is not set
+-# CONFIG_IP_TCPDIAG_IPV6 is not set
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_BIC=y
+-
+-#
+-# IP: Virtual Server Configuration
+-#
+-# CONFIG_IP_VS is not set
+-# CONFIG_IPV6 is not set
+-CONFIG_NETFILTER=y
+-# CONFIG_NETFILTER_DEBUG is not set
+-
+-#
+-# IP: Netfilter Configuration
++# Network device support
+ #
+-# CONFIG_IP_NF_CONNTRACK is not set
+-# CONFIG_IP_NF_CONNTRACK_MARK is not set
+-# CONFIG_IP_NF_QUEUE is not set
+-# CONFIG_IP_NF_IPTABLES is not set
+-CONFIG_IP_NF_ARPTABLES=y
+-# CONFIG_IP_NF_ARPFILTER is not set
+-# CONFIG_IP_NF_ARP_MANGLE is not set
+-
+-#
+-# SCTP Configuration (EXPERIMENTAL)
+-#
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_NET_DIVERT is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-
+-#
+-# QoS and/or fair queueing
+-#
+-# CONFIG_NET_SCHED is not set
+-# CONFIG_NET_CLS_ROUTE is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+ CONFIG_NETDEVICES=y
+ CONFIG_DUMMY=y
+ # CONFIG_BONDING is not set
+@@ -555,6 +557,8 @@ CONFIG_TIGON3=y
+ # CONFIG_NET_FC is not set
+ # CONFIG_SHAPER is not set
+ # CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
+ 
+ #
+ # ISDN subsystem
+@@ -659,6 +663,7 @@ CONFIG_DRM=y
+ CONFIG_DRM_RADEON=y
+ # CONFIG_DRM_MGA is not set
+ # CONFIG_DRM_SIS is not set
++# CONFIG_DRM_VIA is not set
+ # CONFIG_RAW_DRIVER is not set
+ # CONFIG_HPET is not set
+ # CONFIG_HANGCHECK_TIMER is not set
+@@ -706,47 +711,10 @@ CONFIG_I2C_ALGOPCF=y
+ # CONFIG_I2C_VIAPRO is not set
+ # CONFIG_I2C_VOODOO3 is not set
+ # CONFIG_I2C_PCA_ISA is not set
++# CONFIG_I2C_SENSOR is not set
+ 
+ #
+-# Hardware Sensors Chip support
+-#
+-# CONFIG_I2C_SENSOR is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ASB100 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_FSCHER is not set
+-# CONFIG_SENSORS_FSCPOS is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-
+-#
+-# Other I2C Chip support
++# Miscellaneous I2C Chip support
+ #
+ # CONFIG_SENSORS_DS1337 is not set
+ # CONFIG_SENSORS_DS1374 is not set
+@@ -766,6 +734,11 @@ CONFIG_I2C_ALGOPCF=y
+ #
+ # CONFIG_W1 is not set
+ 
++#
++# Hardware Monitoring support
++#
++# CONFIG_HWMON is not set
++
+ #
+ # Misc devices
+ #
+@@ -782,7 +755,6 @@ CONFIG_VIDEO_DEV=y
+ #
+ # Video Adapters
+ #
+-# CONFIG_TUNER_MULTI_I2C is not set
+ # CONFIG_VIDEO_BT848 is not set
+ # CONFIG_VIDEO_CPIA is not set
+ # CONFIG_VIDEO_SAA5246A is not set
+@@ -1025,6 +997,7 @@ CONFIG_USB_HIDDEV=y
+ # CONFIG_USB_EGALAX is not set
+ # CONFIG_USB_XPAD is not set
+ # CONFIG_USB_ATI_REMOTE is not set
++# CONFIG_USB_KEYSPAN_REMOTE is not set
+ 
+ #
+ # USB Imaging devices
+@@ -1080,6 +1053,7 @@ CONFIG_USB_MON=y
+ # CONFIG_USB_PHIDGETSERVO is not set
+ # CONFIG_USB_IDMOUSE is not set
+ # CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
+ 
+ #
+ # USB DSL modem support
+@@ -1121,6 +1095,7 @@ CONFIG_JBD=y
+ CONFIG_FS_MBCACHE=y
+ # CONFIG_REISERFS_FS is not set
+ # CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
+ 
+ #
+ # XFS support
+@@ -1128,6 +1103,7 @@ CONFIG_FS_MBCACHE=y
+ # CONFIG_XFS_FS is not set
+ # CONFIG_MINIX_FS is not set
+ # CONFIG_ROMFS_FS is not set
++# CONFIG_INOTIFY is not set
+ # CONFIG_QUOTA is not set
+ CONFIG_DNOTIFY=y
+ CONFIG_AUTOFS_FS=y

commit 46906c4415f88cebfad530917bada0835d651824
+Author: Ian Wienand 
+Date:   Wed Jul 13 21:09:00 2005 -0700
+
+    [IA64] Fix undefined reference to can_cpei_retarget for simulator
+    
+    The simulator build doesn't turn on ACPI, so doesn't have a definition
+    of can_cpei_retarget.
+    
+    Signed-off-by: Tony Luck 
+
+diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c
+index d8030f3bd865..92ff46ad21e2 100644
+--- a/arch/ia64/kernel/topology.c
++++ b/arch/ia64/kernel/topology.c
+@@ -36,12 +36,14 @@ int arch_register_cpu(int num)
+ 	parent = &sysfs_nodes[cpu_to_node(num)];
+ #endif /* CONFIG_NUMA */
+ 
++#ifdef CONFIG_ACPI_BOOT
+ 	/*
+ 	 * If CPEI cannot be re-targetted, and this is
+ 	 * CPEI target, then dont create the control file
+ 	 */
+ 	if (!can_cpei_retarget() && is_cpu_cpei_target(num))
+ 		sysfs_cpus[num].cpu.no_control = 1;
++#endif
+ 
+ 	return register_cpu(&sysfs_cpus[num].cpu, num, parent);
+ }

commit a68db763af9b676590c3fe9ec3f17bf18015eb2f
+Author: Peter Chubb 
+Date:   Thu Jun 23 21:14:00 2005 -0700
+
+    [IA64] Fix another IA64 preemption problem
+    
+    There's another problem shown up by Ingo's recent patch to make
+    smp_processor_id() complain if it's called with preemption enabled.
+    local_finish_flush_tlb_mm() calls activate_context() in a situation
+    where it could be rescheduled to another processor.  This patch
+    disables preemption around the call.
+    
+    Signed-off-by: Peter Chubb 
+    Signed-off-by: Tony Luck 
+
+diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
+index b49d4ddaab93..0166a9847095 100644
+--- a/arch/ia64/kernel/smp.c
++++ b/arch/ia64/kernel/smp.c
+@@ -231,13 +231,16 @@ smp_flush_tlb_all (void)
+ void
+ smp_flush_tlb_mm (struct mm_struct *mm)
+ {
++	preempt_disable();
+ 	/* this happens for the common case of a single-threaded fork():  */
+ 	if (likely(mm == current->active_mm && atomic_read(&mm->mm_users) == 1))
+ 	{
+ 		local_finish_flush_tlb_mm(mm);
++		preempt_enable();
+ 		return;
+ 	}
+ 
++	preempt_enable();
+ 	/*
+ 	 * We could optimize this further by using mm->cpu_vm_mask to track which CPUs
+ 	 * have been running in the address space.  It's not clear that this is worth the
+diff --git a/include/asm-ia64/mmu_context.h b/include/asm-ia64/mmu_context.h
+index 0096e7e05012..e3e5fededb04 100644
+--- a/include/asm-ia64/mmu_context.h
++++ b/include/asm-ia64/mmu_context.h
+@@ -132,6 +132,9 @@ reload_context (mm_context_t context)
+ 	ia64_srlz_i();			/* srlz.i implies srlz.d */
+ }
+ 
++/*
++ * Must be called with preemption off
++ */
+ static inline void
+ activate_context (struct mm_struct *mm)
+ {

commit 05062d96a23ec0959ee5ea969f40813170c73c0e
+Author: Peter Chubb 
+Date:   Wed Jun 8 15:50:20 2005 -0700
+
+    [PATCH] ia64: fix floating-point preemption problem
+    
+    There've been reports of problems with CONFIG_PREEMPT=y and the high
+    floating point partition.  This is caused by the possibility of preemption
+    and rescheduling on a different processor while saving or restioirng the
+    high partition.
+    
+    The only places where the FPU state is touched are in ptrace, in
+    switch_to(), and where handling a floating-point exception.  In switch_to()
+    preemption is off.  So it's only in trap.c and ptrace.c that we need to
+    prevent preemption.
+    
+    Here is a patch that adds commentary to make the conditions clear, and adds
+    appropriate preempt_{en,dis}able() calls to make it so.  In trap.c I use
+    preempt_enable_no_resched(), as we're about to return to user space where
+    the preemption flag will be checked anyway.
+    
+    Signed-off-by: Peter Chubb 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
+index 08c8a5eb25ab..575a8f657b31 100644
+--- a/arch/ia64/kernel/ptrace.c
++++ b/arch/ia64/kernel/ptrace.c
+@@ -635,11 +635,17 @@ ia64_flush_fph (struct task_struct *task)
+ {
+ 	struct ia64_psr *psr = ia64_psr(ia64_task_regs(task));
+ 
++	/*
++	 * Prevent migrating this task while
++	 * we're fiddling with the FPU state
++	 */
++	preempt_disable();
+ 	if (ia64_is_local_fpu_owner(task) && psr->mfh) {
+ 		psr->mfh = 0;
+ 		task->thread.flags |= IA64_THREAD_FPH_VALID;
+ 		ia64_save_fpu(&task->thread.fph[0]);
+ 	}
++	preempt_enable();
+ }
+ 
+ /*
+diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
+index 9bad6652d531..1861173bd4f6 100644
+--- a/arch/ia64/kernel/traps.c
++++ b/arch/ia64/kernel/traps.c
+@@ -220,13 +220,21 @@ disabled_fph_fault (struct pt_regs *regs)
+ 
+ 	/* first, grant user-level access to fph partition: */
+ 	psr->dfh = 0;
++
++	/*
++	 * Make sure that no other task gets in on this processor
++	 * while we're claiming the FPU
++	 */
++	preempt_disable();
+ #ifndef CONFIG_SMP
+ 	{
+ 		struct task_struct *fpu_owner
+ 			= (struct task_struct *)ia64_get_kr(IA64_KR_FPU_OWNER);
+ 
+-		if (ia64_is_local_fpu_owner(current))
++		if (ia64_is_local_fpu_owner(current)) {
++			preempt_enable_no_resched();
+ 			return;
++		}
+ 
+ 		if (fpu_owner)
+ 			ia64_flush_fph(fpu_owner);
+@@ -244,6 +252,7 @@ disabled_fph_fault (struct pt_regs *regs)
+ 		 */
+ 		psr->mfh = 1;
+ 	}
++	preempt_enable_no_resched();
+ }
+ 
+ static inline int
+diff --git a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h
+index 9e1ba8b7fb68..91bbd1f22461 100644
+--- a/include/asm-ia64/processor.h
++++ b/include/asm-ia64/processor.h
+@@ -403,7 +403,10 @@ extern void ia64_setreg_unknown_kr (void);
+  * task_struct at this point.
+  */
+ 
+-/* Return TRUE if task T owns the fph partition of the CPU we're running on. */
++/*
++ * Return TRUE if task T owns the fph partition of the CPU we're running on.
++ * Must be called from code that has preemption disabled.
++ */
+ #define ia64_is_local_fpu_owner(t)								\
+ ({												\
+ 	struct task_struct *__ia64_islfo_task = (t);						\
+@@ -411,7 +414,10 @@ extern void ia64_setreg_unknown_kr (void);
+ 	 && __ia64_islfo_task == (struct task_struct *) ia64_get_kr(IA64_KR_FPU_OWNER));	\
+ })
+ 
+-/* Mark task T as owning the fph partition of the CPU we're running on. */
++/*
++ * Mark task T as owning the fph partition of the CPU we're running on.
++ * Must be called from code that has preemption disabled.
++ */
+ #define ia64_set_local_fpu_owner(t) do {						\
+ 	struct task_struct *__ia64_slfo_task = (t);					\
+ 	__ia64_slfo_task->thread.last_fph_cpu = smp_processor_id();			\

commit d8caebd285a084ee1e4d484ce597865228614067
+Author: Peter Chubb 
+Date:   Tue May 31 22:37:00 2005 -0700
+
+    [IA64] fix compilation warning in sys32_epoll_wait()
+    
+    This gets rid of an unused variable `error' in sys_ia32.c:sys32_epoll_wait()
+    
+    Getting rid of this one makes parsing the output of the kernecomp
+    autobuild easier --- searching for `Error' to find a problem kept
+    hitting this one, even though it's only a warning.
+    
+    Signed-off-by: Tony Luck 
+
+diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
+index 247a21c64aea..c1e20d65dd6c 100644
+--- a/arch/ia64/ia32/sys_ia32.c
++++ b/arch/ia64/ia32/sys_ia32.c
+@@ -2427,7 +2427,7 @@ sys32_epoll_wait(int epfd, struct epoll_event32 __user * events, int maxevents,
+ {
+ 	struct epoll_event *events64 = NULL;
+ 	mm_segment_t old_fs = get_fs();
+-	int error, numevents, size;
++	int numevents, size;
+ 	int evt_idx;
+ 	int do_free_pages = 0;
+ 

commit b655913bf364603d17ad770dc4fb80e60555a255
+Author: Peter Chubb 
+Date:   Tue May 31 22:34:00 2005 -0700
+
+    [IA64] Cleanup compile warnings for ski config
+    
+    The attached patch cleans up a compilation warning when ACPI
+    is turned off (i.e., when compiling for the Ski simulator).
+    
+    Signed-off-by: Tony Luck 
+
+diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
+index 2c75741dcc66..736e328b5e61 100644
+--- a/arch/ia64/kernel/mca.c
++++ b/arch/ia64/kernel/mca.c
+@@ -1103,8 +1103,6 @@ ia64_mca_cpe_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs)
+ 	return IRQ_HANDLED;
+ }
+ 
+-#endif /* CONFIG_ACPI */
+-
+ /*
+  *  ia64_mca_cpe_poll
+  *
+@@ -1122,6 +1120,8 @@ ia64_mca_cpe_poll (unsigned long dummy)
+ 	platform_send_ipi(first_cpu(cpu_online_map), IA64_CPEP_VECTOR, IA64_IPI_DM_INT, 0);
+ }
+ 
++#endif /* CONFIG_ACPI */
++
+ /*
+  * C portion of the OS INIT handler
+  *

commit 97d3a00f77fa527886d53dd943017654ce142186
+Author: Peter Chubb 
+Date:   Tue May 31 14:39:30 2005 -0700
+
+    [PATCH] pcdp.c build fix
+    
+    In file included from drivers/firmware/pcdp.c:18:
+    drivers/firmware/pcdp.h:48: error: field `addr' has incomplete type
+    drivers/firmware/pcdp.c: In function `setup_serial_console':
+    drivers/firmware/pcdp.c:27: error:  `ACPI_ADR_SPACE_SYSTEM_MEMORY' undeclared (first use in this  function)
+    
+    Cc: 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/firmware/pcdp.c b/drivers/firmware/pcdp.c
+index 6d5df6c2efa2..df1b721154d2 100644
+--- a/drivers/firmware/pcdp.c
++++ b/drivers/firmware/pcdp.c
+@@ -11,6 +11,7 @@
+  * published by the Free Software Foundation.
+  */
+ 
++#include 
+ #include 
+ #include 
+ #include 

\ No newline at end of file diff --git a/detail/88.html b/detail/88.html new file mode 100644 index 0000000..bf4a824 --- /dev/null +++ b/detail/88.html @@ -0,0 +1,72 @@ +

Patches contributed by Brown University


commit 46bdac99382dd36e2d8c36cfb35d879b5c136965
+Author: Tom Duffy 
+Date:   Sun Aug 7 09:42:23 2005 -0700
+
+    [PATCH] visws: linkage fix
+    
+    This patch add stubs to allow the visws subarch to link again.
+    
+    Signed-off-by: Tom Duffy 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/i386/mach-visws/setup.c b/arch/i386/mach-visws/setup.c
+index 9f6d2d9b1be7..26ada6fc0d77 100644
+--- a/arch/i386/mach-visws/setup.c
++++ b/arch/i386/mach-visws/setup.c
+@@ -14,6 +14,8 @@
+ #include "cobalt.h"
+ #include "piix4.h"
+ 
++int no_broadcast;
++
+ char visws_board_type = -1;
+ char visws_board_rev = -1;
+ 
+diff --git a/arch/i386/pci/visws.c b/arch/i386/pci/visws.c
+index 314c933b6b8e..6c17433fdf7d 100644
+--- a/arch/i386/pci/visws.c
++++ b/arch/i386/pci/visws.c
+@@ -18,8 +18,10 @@
+ extern struct pci_raw_ops pci_direct_conf1;
+ 
+ static int pci_visws_enable_irq(struct pci_dev *dev) { return 0; }
++static void pci_visws_disable_irq(struct pci_dev *dev) { }
+ 
+ int (*pcibios_enable_irq)(struct pci_dev *dev) = &pci_visws_enable_irq;
++void (*pcibios_disable_irq)(struct pci_dev *dev) = &pci_visws_disable_irq;
+ 
+ void __init pcibios_penalize_isa_irq(int irq, int active) {}
+ 

commit 6c79d7260a8522a54374fa10dd2838eaef492cf2
+Author: Tom Duffy 
+Date:   Sun Aug 7 09:42:16 2005 -0700
+
+    [PATCH] Make visws compile again
+    
+    In file included from linux-2.6.13-rc5/arch/i386/kernel/timers/timer_pit.c:20:
+    linux-2.6.13-rc5/include/asm-i386/mach-visws/do_timer.h: In function `do_timer_overflow':
+    linux-2.6.13-rc5/include/asm-i386/mach-visws/do_timer.h:32: error: `i8259A_lock' undeclared (first use in this function)
+    linux-2.6.13-rc5/include/asm-i386/mach-visws/do_timer.h:32: error: (Each undeclared identifier is reported only once
+    linux-2.6.13-rc5/include/asm-i386/mach-visws/do_timer.h:32: error: for each function it appears in.)
+    make[3]: *** [arch/i386/kernel/timers/timer_pit.o] Error 1
+    make[2]: *** [arch/i386/kernel/timers] Error 2
+    make[1]: *** [arch/i386/kernel] Error 2
+    make: *** [_all] Error 2
+    
+    Signed-off-by: Tom Duffy 
+    Cc: Andrey Panin 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/asm-i386/mach-visws/do_timer.h b/include/asm-i386/mach-visws/do_timer.h
+index 33acd50fd9a8..92d638fc8b11 100644
+--- a/include/asm-i386/mach-visws/do_timer.h
++++ b/include/asm-i386/mach-visws/do_timer.h
+@@ -1,6 +1,7 @@
+ /* defines for inline arch setup functions */
+ 
+ #include 
++#include 
+ #include "cobalt.h"
+ 
+ static inline void do_timer_interrupt_hook(struct pt_regs *regs)

\ No newline at end of file diff --git a/detail/9.html b/detail/9.html new file mode 100644 index 0000000..6e02a70 --- /dev/null +++ b/detail/9.html @@ -0,0 +1,22926 @@ +

Patches contributed by Virginia Tech


commit 69163dd9eaebef22975ecf20852d4aab875eb20d
+Author: Carlos Bilbao 
+Date:   Sat Dec 3 18:01:10 2022 -0600
+
+    docs/sp_SP: Add process code-of-conduct.rst translation
+    
+    Translate the following document into Spanish:
+    
+    - process/code-of-conduct.rst
+    
+    Signed-off-by: Carlos Bilbao 
+    Link: https://lore.kernel.org/r/20221204000109.17224-1-bilbao@vt.edu
+    Signed-off-by: Jonathan Corbet 
+
+diff --git a/Documentation/translations/sp_SP/process/code-of-conduct.rst b/Documentation/translations/sp_SP/process/code-of-conduct.rst
+new file mode 100644
+index 000000000000..adc6c770cc37
+--- /dev/null
++++ b/Documentation/translations/sp_SP/process/code-of-conduct.rst
+@@ -0,0 +1,97 @@
++.. include:: ../disclaimer-sp.rst
++
++:Original: :ref:`Documentation/process/code-of-conduct.rst `
++:Translator: Contributor Covenant and Carlos Bilbao 
++
++.. _sp_code_of_conduct:
++
++Código de Conducta para Contribuyentes
+++++++++++++++++++++++++++++++++++++++++
++
++Nuestro Compromiso
++==================
++
++Nosotros, como miembros, contribuyentes y administradores nos comprometemos
++a hacer de la participación en nuestra comunidad una experiencia libre de
++acoso para todo el mundo, independientemente de la edad, dimensión corporal,
++minusvalía visible o invisible, etnicidad, características sexuales,
++identidad y expresión de género, nivel de experiencia, educación, nivel
++socio-económico, nacionalidad, apariencia personal, raza, religión, o
++identidad u orientación sexual. Nos comprometemos a actuar e interactuar de
++maneras que contribuyan a una comunidad abierta, acogedora, diversa,
++inclusiva y sana.
++
++Nuestros Estándares
++===================
++
++Ejemplos de comportamiento que contribuyen a crear un ambiente positivo
++para nuestra comunidad:
++
++* Demostrar empatía y amabilidad ante otras personas
++* Respeto a diferentes opiniones, puntos de vista y experiencias
++* Dar y aceptar adecuadamente retroalimentación constructiva
++* Aceptar la responsabilidad y disculparse ante quienes se vean afectados
++  por nuestros errores, aprendiendo de la experiencia
++* Centrarse en lo que sea mejor no sólo para nosotros como individuos, sino
++  para la comunidad en general
++
++
++Ejemplos de comportamiento inaceptable:
++
++* El uso de lenguaje o imágenes sexualizadas, y aproximaciones o
++  atenciones sexuales de cualquier tipo
++* Comentarios despectivos (trolling), insultantes o derogatorios, y ataques
++  personales o políticos
++* El acoso en público o privado
++* Publicar información privada de otras personas, tales como direcciones
++  físicas o de correo
++  electrónico, sin su permiso explícito
++* Otras conductas que puedan ser razonablemente consideradas como
++  inapropiadas en un entorno profesional
++
++
++Aplicación de las responsabilidades
++===================================
++
++Los administradores de la comunidad son responsables de aclarar y hacer
++cumplir nuestros estándares de comportamiento aceptable y tomarán acciones
++apropiadas y correctivas de forma justa en respuesta a cualquier
++comportamiento que consideren inapropiado, amenazante, ofensivo o dañino.
++
++Los administradores de la comunidad tendrán el derecho y la responsabilidad
++de eliminar, editar o rechazar comentarios, commits, código, ediciones de
++páginas de wiki, issues y otras contribuciones que no se alineen con este
++Código de Conducta, y comunicarán las razones para sus decisiones de
++moderación cuando sea apropiado.
++
++Alcance
++=======
++
++Este código de conducta aplica tanto a espacios del proyecto como a
++espacios públicos donde un individuo esté en representación del proyecto o
++comunidad. Ejemplos de esto incluyen el uso de la cuenta oficial de correo
++electrónico, publicaciones a través de las redes sociales oficiales, o
++presentaciones con personas designadas en eventos en línea o no.
++
++Aplicación
++==========
++
++Instancias de comportamiento abusivo, acosador o inaceptable de otro modo
++podrán ser reportadas contactando el Code of Conduct Commitee a través de
++. Todas las quejas serán evaluadas e investigadas de
++una manera puntual y justa. El Code of Condut Commitee está obligados a
++respetar la privacidad y la seguridad de quienes reporten incidentes.
++Detalles de políticas y aplicación en particular, serán incluidos por
++separado.
++
++Atribución
++==========
++
++Este Código de Conducta es una adaptación del Contributor Covenant, versión
++1.4, disponible en https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
++
++Interpretación
++==============
++
++Consulte el documento :ref:`code_of_conduct_interpretation` para ver cómo
++interpretará la comunidad del kernel Linux este documento.
+diff --git a/Documentation/translations/sp_SP/process/index.rst b/Documentation/translations/sp_SP/process/index.rst
+index 49a05f6a5544..0998cc15d274 100644
+--- a/Documentation/translations/sp_SP/process/index.rst
++++ b/Documentation/translations/sp_SP/process/index.rst
+@@ -13,3 +13,4 @@
+    submitting-patches
+    kernel-docs
+    coding-style
++   code-of-conduct

commit e62e074814862cffd8e60a1bdf52d6b592a03675
+Author: Carlos Bilbao 
+Date:   Thu Jul 8 07:15:42 2021 -0400
+
+    arm64: Add missing header  in two files
+    
+    Add missing header  on include/asm/smp_plat.h, as it calls function
+    cpu_logical_map(). Also include it on kernel/cpufeature.c since it has calls to
+    functions cpu_panic_kernel() and cpu_die_early().
+    
+    Both files call functions defined on this header, make the header dependencies
+    less fragile.
+    
+    Signed-off-by: Carlos Bilbao 
+    Acked-by: Mark Rutland 
+    Link: https://lore.kernel.org/r/4325940.LvFx2qVVIh@iron-maiden
+    Signed-off-by: Will Deacon 
+
+diff --git a/arch/arm64/include/asm/smp_plat.h b/arch/arm64/include/asm/smp_plat.h
+index 99ad77df8f52..97ddc6c203b7 100644
+--- a/arch/arm64/include/asm/smp_plat.h
++++ b/arch/arm64/include/asm/smp_plat.h
+@@ -10,6 +10,7 @@
+ 
+ #include 
+ 
++#include 
+ #include 
+ 
+ struct mpidr_hash {
+diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
+index 125d5c9471ac..0ead8bfedf20 100644
+--- a/arch/arm64/kernel/cpufeature.c
++++ b/arch/arm64/kernel/cpufeature.c
+@@ -81,6 +81,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 

commit 3e42d1de020805ff3f7d854e1cff742d14e158f5
+Author: Carlos Bilbao 
+Date:   Thu May 13 09:31:10 2021 -0400
+
+    docs: typo fixes in Documentation/ABI/
+    
+    Fix the following typos in the Documentation/ABI/ directory:
+    
+    - In file obsolete/sysfs-cpuidle, change "obselete" for "obsolete".
+    
+    - In file removed/sysfs-kernel-uids, change "propotional" for "proportional".
+    
+    - In directory stable/, fix the following words: "associtated" for "associated",
+      "hexidecimal" for "hexadecimal", "vlue" for "value", "csed" for "caused" and
+      "wrtie" for "write". This updates a total of five files.
+    
+    - In directory testing/, fix the following words: "subystem" for "subsystem",
+      "isochrnous" for "isochronous", "Desctiptors" for "Descriptors", "picutre" for
+      "picture", "capture" for "capture", "occured" for "ocurred", "connnected" for
+      "connected","agressively" for "aggressively","manufacturee" for "manufacturer"
+      and "transaction" for "transaction", "malformatted" for "incorrectly formated"
+      ,"internel" for "internal", "writtento" for "written to", "specificed" for
+      "specified", "beyound" for "beyond", "Symetric" for "Symmetric". This updates
+      a total of eleven files.
+    
+    Signed-off-by: Carlos Bilbao 
+    Reviewed-by: Randy Dunlap 
+    Reviewed-by: Mauro Carvalho Chehab 
+    Link: https://lore.kernel.org/r/5710038.lOV4Wx5bFT@iron-maiden
+    Signed-off-by: Jonathan Corbet 
+
+diff --git a/Documentation/ABI/obsolete/sysfs-cpuidle b/Documentation/ABI/obsolete/sysfs-cpuidle
+index e398fb5e542f..972cc11d3434 100644
+--- a/Documentation/ABI/obsolete/sysfs-cpuidle
++++ b/Documentation/ABI/obsolete/sysfs-cpuidle
+@@ -6,4 +6,4 @@ Description:
+ 	with the update that cpuidle governor can be changed at runtime in default,
+ 	both current_governor and current_governor_ro co-exist under
+ 	/sys/devices/system/cpu/cpuidle/ file, it's duplicate so make
+-	current_governor_ro obselete.
++	current_governor_ro obsolete.
+diff --git a/Documentation/ABI/removed/sysfs-kernel-uids b/Documentation/ABI/removed/sysfs-kernel-uids
+index dc4463f190a7..85a90b86ce1e 100644
+--- a/Documentation/ABI/removed/sysfs-kernel-uids
++++ b/Documentation/ABI/removed/sysfs-kernel-uids
+@@ -5,7 +5,7 @@ Contact:	Dhaval Giani 
+ Description:
+ 		The /sys/kernel/uids//cpu_shares tunable is used
+ 		to set the cpu bandwidth a user is allowed. This is a
+-		propotional value. What that means is that if there
++		proportional value. What that means is that if there
+ 		are two users logged in, each with an equal number of
+ 		shares, then they will get equal CPU bandwidth. Another
+ 		example would be, if User A has shares = 1024 and user
+diff --git a/Documentation/ABI/stable/sysfs-bus-vmbus b/Documentation/ABI/stable/sysfs-bus-vmbus
+index 42599d9fa161..3066feae1d8d 100644
+--- a/Documentation/ABI/stable/sysfs-bus-vmbus
++++ b/Documentation/ABI/stable/sysfs-bus-vmbus
+@@ -61,7 +61,7 @@ Date:		September. 2017
+ KernelVersion:	4.14
+ Contact:	Stephen Hemminger 
+ Description:	Directory for per-channel information
+-		NN is the VMBUS relid associtated with the channel.
++		NN is the VMBUS relid associated with the channel.
+ 
+ What:		/sys/bus/vmbus/devices//channels//cpu
+ Date:		September. 2017
+diff --git a/Documentation/ABI/stable/sysfs-bus-xen-backend b/Documentation/ABI/stable/sysfs-bus-xen-backend
+index e8b60bd766f7..480a89edfa05 100644
+--- a/Documentation/ABI/stable/sysfs-bus-xen-backend
++++ b/Documentation/ABI/stable/sysfs-bus-xen-backend
+@@ -19,7 +19,7 @@ Date:		April 2011
+ KernelVersion:	3.0
+ Contact:	Konrad Rzeszutek Wilk 
+ Description:
+-                The major:minor number (in hexidecimal) of the
++                The major:minor number (in hexadecimal) of the
+                 physical device providing the storage for this backend
+                 block device.
+ 
+diff --git a/Documentation/ABI/stable/sysfs-driver-dma-idxd b/Documentation/ABI/stable/sysfs-driver-dma-idxd
+index 55285c136cf0..d431e2d00472 100644
+--- a/Documentation/ABI/stable/sysfs-driver-dma-idxd
++++ b/Documentation/ABI/stable/sysfs-driver-dma-idxd
+@@ -173,7 +173,7 @@ What:           /sys/bus/dsa/devices/wq./priority
+ Date:           Oct 25, 2019
+ KernelVersion:  5.6.0
+ Contact:        dmaengine@vger.kernel.org
+-Description:    The priority value of this work queue, it is a vlue relative to
++Description:    The priority value of this work queue, it is a value relative to
+ 		other work queue in the same group to control quality of service
+ 		for dispatching work from multiple workqueues in the same group.
+ 
+diff --git a/Documentation/ABI/stable/sysfs-driver-mlxreg-io b/Documentation/ABI/stable/sysfs-driver-mlxreg-io
+index fd9a8045bb0c..b2553df2e786 100644
+--- a/Documentation/ABI/stable/sysfs-driver-mlxreg-io
++++ b/Documentation/ABI/stable/sysfs-driver-mlxreg-io
+@@ -137,7 +137,7 @@ Contact:	Vadim Pasternak 
+ Description:	These files show the system reset cause, as following:
+ 		COMEX thermal shutdown; wathchdog power off or reset was derived
+ 		by one of the next components: COMEX, switch board or by Small Form
+-		Factor mezzanine, reset requested from ASIC, reset cuased by BIOS
++		Factor mezzanine, reset requested from ASIC, reset caused by BIOS
+ 		reload. Value 1 in file means this is reset cause, 0 - otherwise.
+ 		Only one of the above causes could be 1 at the same time, representing
+ 		only last reset cause.
+@@ -183,7 +183,7 @@ What:		/sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/vpd_wp
+ Date:		January 2020
+ KernelVersion:	5.6
+ Contact:	Vadim Pasternak 
+-Description:	This file allows to overwrite system VPD hardware wrtie
++Description:	This file allows to overwrite system VPD hardware write
+ 		protection when attribute is set 1.
+ 
+ 		The file is read/write.
+diff --git a/Documentation/ABI/testing/configfs-iio b/Documentation/ABI/testing/configfs-iio
+index aebda53ec0f7..1637fcb50f56 100644
+--- a/Documentation/ABI/testing/configfs-iio
++++ b/Documentation/ABI/testing/configfs-iio
+@@ -31,4 +31,4 @@ Date:		April 2016
+ KernelVersion:	4.7
+ Description:
+ 		Dummy IIO devices directory. Creating a directory here will result
+-		in creating a dummy IIO device in the IIO subystem.
++		in creating a dummy IIO device in the IIO subsystem.
+diff --git a/Documentation/ABI/testing/configfs-most b/Documentation/ABI/testing/configfs-most
+index bc6b8bd18da4..0a4b8649aa5a 100644
+--- a/Documentation/ABI/testing/configfs-most
++++ b/Documentation/ABI/testing/configfs-most
+@@ -20,7 +20,7 @@ Description:
+ 
+ 		subbuffer_size
+ 				configure the sub-buffer size for this channel
+-				(needed for synchronous and isochrnous data)
++				(needed for synchronous and isochronous data)
+ 
+ 
+ 		num_buffers
+@@ -75,7 +75,7 @@ Description:
+ 
+ 		subbuffer_size
+ 				configure the sub-buffer size for this channel
+-				(needed for synchronous and isochrnous data)
++				(needed for synchronous and isochronous data)
+ 
+ 
+ 		num_buffers
+@@ -130,7 +130,7 @@ Description:
+ 
+ 		subbuffer_size
+ 				configure the sub-buffer size for this channel
+-				(needed for synchronous and isochrnous data)
++				(needed for synchronous and isochronous data)
+ 
+ 
+ 		num_buffers
+@@ -196,7 +196,7 @@ Description:
+ 
+ 		subbuffer_size
+ 				configure the sub-buffer size for this channel
+-				(needed for synchronous and isochrnous data)
++				(needed for synchronous and isochronous data)
+ 
+ 
+ 		num_buffers
+diff --git a/Documentation/ABI/testing/configfs-usb-gadget b/Documentation/ABI/testing/configfs-usb-gadget
+index dc351e9af80a..b7943aa7e997 100644
+--- a/Documentation/ABI/testing/configfs-usb-gadget
++++ b/Documentation/ABI/testing/configfs-usb-gadget
+@@ -137,7 +137,7 @@ Description:
+ 		This group contains "OS String" extension handling attributes.
+ 
+ 		=============	===============================================
+-		use		flag turning "OS Desctiptors" support on/off
++		use		flag turning "OS Descriptors" support on/off
+ 		b_vendor_code	one-byte value used for custom per-device and
+ 				per-interface requests
+ 		qw_sign		an identifier to be reported as "OS String"
+diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uvc b/Documentation/ABI/testing/configfs-usb-gadget-uvc
+index ac5e11af79a8..889ed45be4ca 100644
+--- a/Documentation/ABI/testing/configfs-usb-gadget-uvc
++++ b/Documentation/ABI/testing/configfs-usb-gadget-uvc
+@@ -170,7 +170,7 @@ Description:	Default color matching descriptors
+ 		bMatrixCoefficients	  matrix used to compute luma and
+ 					  chroma values from the color primaries
+ 		bTransferCharacteristics  optoelectronic transfer
+-					  characteristic of the source picutre,
++					  characteristic of the source picture,
+ 					  also called the gamma function
+ 		bColorPrimaries		  color primaries and the reference
+ 					  white
+@@ -311,7 +311,7 @@ Description:	Specific streaming header descriptors
+ 					a hardware trigger interrupt event
+ 		bTriggerSupport		flag specifying if hardware
+ 					triggering is supported
+-		bStillCaptureMethod	method of still image caputre
++		bStillCaptureMethod	method of still image capture
+ 					supported
+ 		bTerminalLink		id of the output terminal to which
+ 					the video endpoint of this interface
+diff --git a/Documentation/ABI/testing/debugfs-driver-genwqe b/Documentation/ABI/testing/debugfs-driver-genwqe
+index 1c2f25674e8c..b45b016545d8 100644
+--- a/Documentation/ABI/testing/debugfs-driver-genwqe
++++ b/Documentation/ABI/testing/debugfs-driver-genwqe
+@@ -31,7 +31,7 @@ What:           /sys/kernel/debug/genwqe/genwqe_card/prev_regs
+ Date:           Oct 2013
+ Contact:        haver@linux.vnet.ibm.com
+ Description:    Dump of the error registers before the last reset of
+-                the card occured.
++                the card occurred.
+                 Only available for PF.
+ 
+ What:           /sys/kernel/debug/genwqe/genwqe_card/prev_dbg_uid0
+diff --git a/Documentation/ABI/testing/debugfs-driver-habanalabs b/Documentation/ABI/testing/debugfs-driver-habanalabs
+index c78fc9282876..e89c6351503c 100644
+--- a/Documentation/ABI/testing/debugfs-driver-habanalabs
++++ b/Documentation/ABI/testing/debugfs-driver-habanalabs
+@@ -153,7 +153,7 @@ KernelVersion:  5.1
+ Contact:        ogabbay@kernel.org
+ Description:    Triggers an I2C transaction that is generated by the device's
+                 CPU. Writing to this file generates a write transaction while
+-                reading from the file generates a read transcation
++                reading from the file generates a read transaction
+ 
+ What:           /sys/kernel/debug/habanalabs/hl/i2c_reg
+ Date:           Jan 2019
+diff --git a/Documentation/ABI/testing/sysfs-bus-fsi b/Documentation/ABI/testing/sysfs-bus-fsi
+index d148214181a1..76e0caa0c2b3 100644
+--- a/Documentation/ABI/testing/sysfs-bus-fsi
++++ b/Documentation/ABI/testing/sysfs-bus-fsi
+@@ -12,7 +12,7 @@ KernelVersion:  4.12
+ Contact:        linux-fsi@lists.ozlabs.org
+ Description:
+ 		Sends an FSI BREAK command on a master's communication
+-		link to any connnected slaves.  A BREAK resets connected
++		link to any connected slaves.  A BREAK resets connected
+ 		device's logic and preps it to receive further commands
+ 		from the master.
+ 
+diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci
+index ef00fada2efb..793cbb76cd25 100644
+--- a/Documentation/ABI/testing/sysfs-bus-pci
++++ b/Documentation/ABI/testing/sysfs-bus-pci
+@@ -139,8 +139,8 @@ Description:
+ 		binary file containing the Vital Product Data for the
+ 		device.  It should follow the VPD format defined in
+ 		PCI Specification 2.1 or 2.2, but users should consider
+-		that some devices may have malformatted data.  If the
+-		underlying VPD has a writable section then the
++		that some devices may have incorrectly formatted data.  
++		If the underlying VPD has a writable section then the
+ 		corresponding section of this file will be writable.
+ 
+ What:		/sys/bus/pci/devices/.../virtfnN
+diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
+index fe13baa53c59..160b10c029c0 100644
+--- a/Documentation/ABI/testing/sysfs-devices-system-cpu
++++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
+@@ -50,7 +50,7 @@ Description:	Dynamic addition and removal of CPU's.  This is not hotplug
+ 		architecture specific.
+ 
+ 		release: writes to this file dynamically remove a CPU from
+-		the system.  Information writtento the file to remove CPU's
++		the system.  Information written to the file to remove CPU's
+ 		is architecture specific.
+ 
+ What:		/sys/devices/system/cpu/cpu#/node
+@@ -97,7 +97,7 @@ Description:	CPU topology files that describe a logical CPU's relationship
+ 		corresponds to a physical socket number, but the actual value
+ 		is architecture and platform dependent.
+ 
+-		thread_siblings: internel kernel map of cpu#'s hardware
++		thread_siblings: internal kernel map of cpu#'s hardware
+ 		threads within the same core as cpu#
+ 
+ 		thread_siblings_list: human-readable list of cpu#'s hardware
+@@ -280,7 +280,7 @@ Description:	Disable L3 cache indices
+ 		on a processor with this functionality will return the currently
+ 		disabled index for that node. There is one L3 structure per
+ 		node, or per internal node on MCM machines. Writing a valid
+-		index to one of these files will cause the specificed cache
++		index to one of these files will cause the specified cache
+ 		index to be disabled.
+ 
+ 		All AMD processors with L3 caches provide this functionality.
+@@ -295,7 +295,7 @@ Description:	Processor frequency boosting control
+ 
+ 		This switch controls the boost setting for the whole system.
+ 		Boosting allows the CPU and the firmware to run at a frequency
+-		beyound it's nominal limit.
++		beyond it's nominal limit.
+ 
+ 		More details can be found in
+ 		Documentation/admin-guide/pm/cpufreq.rst
+@@ -532,7 +532,7 @@ What:		/sys/devices/system/cpu/smt
+ 		/sys/devices/system/cpu/smt/control
+ Date:		June 2018
+ Contact:	Linux kernel mailing list 
+-Description:	Control Symetric Multi Threading (SMT)
++Description:	Control Symmetric Multi Threading (SMT)
+ 
+ 		active:  Tells whether SMT is active (enabled and siblings online)
+ 
+diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
+index d1bc23cb6a9d..eaac6898f0c0 100644
+--- a/Documentation/ABI/testing/sysfs-driver-ufs
++++ b/Documentation/ABI/testing/sysfs-driver-ufs
+@@ -168,7 +168,7 @@ Description:	This file shows the manufacturing date in BCD format.
+ What:		/sys/bus/platform/drivers/ufshcd/*/device_descriptor/manufacturer_id
+ Date:		February 2018
+ Contact:	Stanislav Nijnikov 
+-Description:	This file shows the manufacturee ID. This is one of the
++Description:	This file shows the manufacturer ID. This is one of the
+ 		UFS device descriptor parameters. The full information about
+ 		the descriptor could be found at UFS specifications 2.1.
+ 
+@@ -521,7 +521,7 @@ Description:	This file shows maximum VCC, VCCQ and VCCQ2 value for
+ What:		/sys/bus/platform/drivers/ufshcd/*/string_descriptors/manufacturer_name
+ Date:		February 2018
+ Contact:	Stanislav Nijnikov 
+-Description:	This file contains a device manufactureer name string.
++Description:	This file contains a device manufacturer name string.
+ 		The full information about the descriptor could be found at
+ 		UFS specifications 2.1.
+ 
+diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs
+index 4849b8e84e42..5d9ae27bd462 100644
+--- a/Documentation/ABI/testing/sysfs-fs-f2fs
++++ b/Documentation/ABI/testing/sysfs-fs-f2fs
+@@ -238,7 +238,7 @@ Description:	Shows current reserved blocks in system, it may be temporarily
+ What:		/sys/fs/f2fs//gc_urgent
+ Date:		August 2017
+ Contact:	"Jaegeuk Kim" 
+-Description:	Do background GC agressively when set. When gc_urgent = 1,
++Description:	Do background GC aggressively when set. When gc_urgent = 1,
+ 		background thread starts to do GC by given gc_urgent_sleep_time
+ 		interval. When gc_urgent = 2, F2FS will lower the bar of
+ 		checking idle in order to process outstanding discard commands

commit 6a79162fe5d5e0eb55bc48e99450982b0daf0a0f
+Author: bilbao@vt.edu 
+Date:   Tue Apr 27 13:28:29 2021 -0400
+
+    docs: Fix typo in Documentation/x86/x86_64/5level-paging.rst
+    
+    fix two typos in the documentation
+    (Documentation/x86/x86_64/5level-paging.rst), changing 'paing' for 'paging'
+    and using the right verbal form for plural on 'some vendors offer'.
+    
+    Signed-off-by: Carlos Bilbao 
+    Link: https://lore.kernel.org/r/2599991.mvXUDI8C0e@iron-maiden
+    Signed-off-by: Jonathan Corbet 
+
+diff --git a/Documentation/x86/x86_64/5level-paging.rst b/Documentation/x86/x86_64/5level-paging.rst
+index 44856417e6a5..b792bbdc0b01 100644
+--- a/Documentation/x86/x86_64/5level-paging.rst
++++ b/Documentation/x86/x86_64/5level-paging.rst
+@@ -6,9 +6,9 @@
+ 
+ Overview
+ ========
+-Original x86-64 was limited by 4-level paing to 256 TiB of virtual address
++Original x86-64 was limited by 4-level paging to 256 TiB of virtual address
+ space and 64 TiB of physical address space. We are already bumping into
+-this limit: some vendors offers servers with 64 TiB of memory today.
++this limit: some vendors offer servers with 64 TiB of memory today.
+ 
+ To overcome the limitation upcoming hardware will introduce support for
+ 5-level paging. It is a straight-forward extension of the current page

commit 389102a3515b53a38858554a915006be7f0b6a06
+Author: Valdis Kletnieks 
+Date:   Fri Jan 15 02:07:03 2021 -0500
+
+    scsi: target: iscsi: Fix typo in comment
+    
+    Correct the spelling of Nagle's name in a comment.
+    
+    Link: https://lore.kernel.org/r/2921.1610694423@turing-police
+    Reviewed-by: Chaitanya Kulkarni 
+    Signed-off-by: Valdis Klētnieks 
+    Signed-off-by: Martin K. Petersen 
+
+diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
+index 893d1b406c29..1a9c50401bdb 100644
+--- a/drivers/target/iscsi/iscsi_target_login.c
++++ b/drivers/target/iscsi/iscsi_target_login.c
+@@ -896,7 +896,7 @@ int iscsit_setup_np(
+ 	else
+ 		len = sizeof(struct sockaddr_in);
+ 	/*
+-	 * Set SO_REUSEADDR, and disable Nagel Algorithm with TCP_NODELAY.
++	 * Set SO_REUSEADDR, and disable Nagle Algorithm with TCP_NODELAY.
+ 	 */
+ 	if (np->np_network_transport == ISCSI_TCP)
+ 		tcp_sock_set_nodelay(sock->sk);

commit 67a5a68013056cbcf0a647e36cb6f4622fb6a470
+Author: Valdis Kletnieks 
+Date:   Sat Dec 26 13:21:58 2020 -0500
+
+    gcc-plugins: fix gcc 11 indigestion with plugins...
+    
+    Fedora Rawhide has started including gcc 11,and the g++ compiler
+    throws a wobbly when it hits scripts/gcc-plugins:
+    
+      HOSTCXX scripts/gcc-plugins/latent_entropy_plugin.so
+    In file included from /usr/include/c++/11/type_traits:35,
+                     from /usr/lib/gcc/x86_64-redhat-linux/11/plugin/include/system.h:244,
+                     from /usr/lib/gcc/x86_64-redhat-linux/11/plugin/include/gcc-plugin.h:28,
+                     from scripts/gcc-plugins/gcc-common.h:7,
+                     from scripts/gcc-plugins/latent_entropy_plugin.c:78:
+    /usr/include/c++/11/bits/c++0x_warning.h:32:2: error: #error This file requires compiler and library support for the ISO
+     C++ 2011 standard. This support must be enabled with the -std=c++11 or -std=gnu++11 compiler options.
+       32 | #error This file requires compiler and library support \
+    
+    In fact, it works just fine with c++11, which has been in gcc since 4.8,
+    and we now require 4.9 as a minimum.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Acked-by: Josh Poimboeuf 
+    Signed-off-by: Kees Cook 
+    Link: https://lore.kernel.org/r/82487.1609006918@turing-police
+
+diff --git a/scripts/gcc-plugins/Makefile b/scripts/gcc-plugins/Makefile
+index d66949bfeba4..b5487cce69e8 100644
+--- a/scripts/gcc-plugins/Makefile
++++ b/scripts/gcc-plugins/Makefile
+@@ -22,9 +22,9 @@ always-y += $(GCC_PLUGIN)
+ GCC_PLUGINS_DIR = $(shell $(CC) -print-file-name=plugin)
+ 
+ plugin_cxxflags	= -Wp,-MMD,$(depfile) $(KBUILD_HOSTCXXFLAGS) -fPIC \
+-		   -I $(GCC_PLUGINS_DIR)/include -I $(obj) -std=gnu++98 \
++		   -I $(GCC_PLUGINS_DIR)/include -I $(obj) -std=gnu++11 \
+ 		   -fno-rtti -fno-exceptions -fasynchronous-unwind-tables \
+-		   -ggdb -Wno-narrowing -Wno-unused-variable -Wno-c++11-compat \
++		   -ggdb -Wno-narrowing -Wno-unused-variable \
+ 		   -Wno-format-diag
+ 
+ plugin_ldflags	= -shared

commit 036491542aa47633a7c9a1b01a0c19f2c5e67f04
+Author: Valdis Kletnieks 
+Date:   Sat Jun 20 13:03:22 2020 -0400
+
+    opp: core: Add missing export for dev_pm_opp_adjust_voltage
+    
+    Export dev_pm_opp_adjust_voltage() as it may be used by modules later
+    on.
+    
+    Signed-off-by: Valdis Kletnieks 
+    [ Viresh: Rewrote commit log ]
+    Signed-off-by: Viresh Kumar 
+
+diff --git a/drivers/opp/core.c b/drivers/opp/core.c
+index dfbd3d10410c..864cf4c65fff 100644
+--- a/drivers/opp/core.c
++++ b/drivers/opp/core.c
+@@ -2271,6 +2271,7 @@ int dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq,
+ 	dev_pm_opp_put_opp_table(opp_table);
+ 	return r;
+ }
++EXPORT_SYMBOL_GPL(dev_pm_opp_adjust_voltage);
+ 
+ /**
+  * dev_pm_opp_enable() - Enable a specific OPP

commit 9f64fbdb774838db1445268fa8c46041fb1c28ab
+Author: Valdis Kletnieks 
+Date:   Sat May 9 00:47:19 2020 -0400
+
+    bpfilter: document build requirements for bpfilter_umh
+    
+    It's not intuitively obvious that bpfilter_umh is a statically linked binary.
+    Mention the toolchain requirement in the Kconfig help, so people
+    have an easier time figuring out what's needed.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Masahiro Yamada 
+
+diff --git a/net/bpfilter/Kconfig b/net/bpfilter/Kconfig
+index 045144d4a42c..84015ef3ee27 100644
+--- a/net/bpfilter/Kconfig
++++ b/net/bpfilter/Kconfig
+@@ -13,4 +13,8 @@ config BPFILTER_UMH
+ 	default m
+ 	help
+ 	  This builds bpfilter kernel module with embedded user mode helper
++
++	  Note: your toolchain must support building static binaries, since
++	  rootfs isn't mounted at the time when __init functions are called
++	  and do_execv won't be able to find the elf interpreter.
+ endif

commit 9acd0d53800c55c6e2186e29b6433daf24617451
+Author: Valdis Kletnieks 
+Date:   Mon Mar 2 15:21:45 2020 +0900
+
+    exfat: update file system parameter handling
+    
+    Al Viro recently reworked the way file system parameters are handled
+    Update super.c to work with it in linux-next 20200203.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Reviewed-by: Christoph Hellwig 
+    Acked-by: Namjae Jeon 
+    Signed-off-by: Al Viro 
+
+diff --git a/fs/exfat/super.c b/fs/exfat/super.c
+index f06e0b53e393..16ed202ef527 100644
+--- a/fs/exfat/super.c
++++ b/fs/exfat/super.c
+@@ -214,7 +214,14 @@ enum {
+ 	Opt_time_offset,
+ };
+ 
+-static const struct fs_parameter_spec exfat_param_specs[] = {
++static const struct constant_table exfat_param_enums[] = {
++	{ "continue",		EXFAT_ERRORS_CONT },
++	{ "panic",		EXFAT_ERRORS_PANIC },
++	{ "remount-ro",		EXFAT_ERRORS_RO },
++	{}
++};
++
++static const struct fs_parameter_spec exfat_parameters[] = {
+ 	fsparam_u32("uid",			Opt_uid),
+ 	fsparam_u32("gid",			Opt_gid),
+ 	fsparam_u32oct("umask",			Opt_umask),
+@@ -222,25 +229,12 @@ static const struct fs_parameter_spec exfat_param_specs[] = {
+ 	fsparam_u32oct("fmask",			Opt_fmask),
+ 	fsparam_u32oct("allow_utime",		Opt_allow_utime),
+ 	fsparam_string("iocharset",		Opt_charset),
+-	fsparam_enum("errors",			Opt_errors),
++	fsparam_enum("errors",			Opt_errors, exfat_param_enums),
+ 	fsparam_flag("discard",			Opt_discard),
+ 	fsparam_s32("time_offset",		Opt_time_offset),
+ 	{}
+ };
+ 
+-static const struct fs_parameter_enum exfat_param_enums[] = {
+-	{ Opt_errors,	"continue",		EXFAT_ERRORS_CONT },
+-	{ Opt_errors,	"panic",		EXFAT_ERRORS_PANIC },
+-	{ Opt_errors,	"remount-ro",		EXFAT_ERRORS_RO },
+-	{}
+-};
+-
+-static const struct fs_parameter_description exfat_parameters = {
+-	.name		= "exfat",
+-	.specs		= exfat_param_specs,
+-	.enums		= exfat_param_enums,
+-};
+-
+ static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param)
+ {
+ 	struct exfat_sb_info *sbi = fc->s_fs_info;
+@@ -248,7 +242,7 @@ static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param)
+ 	struct fs_parse_result result;
+ 	int opt;
+ 
+-	opt = fs_parse(fc, &exfat_parameters, param, &result);
++	opt = fs_parse(fc, exfat_parameters, param, &result);
+ 	if (opt < 0)
+ 		return opt;
+ 
+@@ -665,7 +659,7 @@ static struct file_system_type exfat_fs_type = {
+ 	.owner			= THIS_MODULE,
+ 	.name			= "exfat",
+ 	.init_fs_context	= exfat_init_fs_context,
+-	.parameters		= &exfat_parameters,
++	.parameters		= exfat_parameters,
+ 	.kill_sb		= kill_block_super,
+ 	.fs_flags		= FS_REQUIRES_DEV,
+ };

commit 575b255c1663c8fccc41fe965dcac281e3113c65
+Author: Valdis Kletnieks 
+Date:   Thu Feb 27 21:49:52 2020 -0500
+
+    KVM: x86: allow compiling as non-module with W=1
+    
+    Compile error with CONFIG_KVM_INTEL=y and W=1:
+    
+      CC      arch/x86/kvm/vmx/vmx.o
+    arch/x86/kvm/vmx/vmx.c:68:32: error: 'vmx_cpu_id' defined but not used [-Werror=unused-const-variable=]
+       68 | static const struct x86_cpu_id vmx_cpu_id[] = {
+          |                                ^~~~~~~~~~
+    cc1: all warnings being treated as errors
+    
+    When building with =y, the MODULE_DEVICE_TABLE macro doesn't generate a
+    reference to the structure (or any code at all).  This makes W=1 compiles
+    unhappy.
+    
+    Wrap both in a #ifdef to avoid the issue.
+    
+    Signed-off-by: Valdis Kletnieks 
+    [Do the same for CONFIG_KVM_AMD. - Paolo]
+    Signed-off-by: Paolo Bonzini 
+
+diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
+index bd02526300ab..24c0b2ba8fb9 100644
+--- a/arch/x86/kvm/svm.c
++++ b/arch/x86/kvm/svm.c
+@@ -57,11 +57,13 @@
+ MODULE_AUTHOR("Qumranet");
+ MODULE_LICENSE("GPL");
+ 
++#ifdef MODULE
+ static const struct x86_cpu_id svm_cpu_id[] = {
+ 	X86_FEATURE_MATCH(X86_FEATURE_SVM),
+ 	{}
+ };
+ MODULE_DEVICE_TABLE(x86cpu, svm_cpu_id);
++#endif
+ 
+ #define IOPM_ALLOC_ORDER 2
+ #define MSRPM_ALLOC_ORDER 1
+diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
+index 63aaf44edd1f..ce70a71037ed 100644
+--- a/arch/x86/kvm/vmx/vmx.c
++++ b/arch/x86/kvm/vmx/vmx.c
+@@ -64,11 +64,13 @@
+ MODULE_AUTHOR("Qumranet");
+ MODULE_LICENSE("GPL");
+ 
++#ifdef MODULE
+ static const struct x86_cpu_id vmx_cpu_id[] = {
+ 	X86_FEATURE_MATCH(X86_FEATURE_VMX),
+ 	{}
+ };
+ MODULE_DEVICE_TABLE(x86cpu, vmx_cpu_id);
++#endif
+ 
+ bool __read_mostly enable_vpid = 1;
+ module_param_named(vpid, enable_vpid, bool, 0444);

commit bff47c2302cc249bcd550b17067f8dddbd4b6f77
+Author: Valdis Kletnieks 
+Date:   Thu Dec 5 21:36:07 2019 -0500
+
+    x86/vdso: Provide missing include file
+    
+    When building with C=1, sparse issues a warning:
+    
+      CHECK   arch/x86/entry/vdso/vdso32-setup.c
+      arch/x86/entry/vdso/vdso32-setup.c:28:28: warning: symbol 'vdso32_enabled' was not declared. Should it be static?
+    
+    Provide the missing header file.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Borislav Petkov 
+    Cc: "H. Peter Anvin" 
+    Cc: Andy Lutomirski 
+    Cc: Ingo Molnar 
+    Cc: Thomas Gleixner 
+    Cc: x86-ml 
+    Link: https://lkml.kernel.org/r/36224.1575599767@turing-police
+
+diff --git a/arch/x86/entry/vdso/vdso32-setup.c b/arch/x86/entry/vdso/vdso32-setup.c
+index 240626e7f55a..43842fade8fa 100644
+--- a/arch/x86/entry/vdso/vdso32-setup.c
++++ b/arch/x86/entry/vdso/vdso32-setup.c
+@@ -11,6 +11,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ #include 

commit 82c881b28aa89215a760e39c5f6bcde2d6ce4918
+Author: Valdis Kletnieks 
+Date:   Thu Dec 5 22:44:33 2019 -0500
+
+    x86/microcode/AMD: Make stub function static inline
+    
+    When building with C=1 W=1 (and when CONFIG_MICROCODE_AMD=n, as Luc Van
+    Oostenryck correctly points out) both sparse and gcc complain:
+    
+      CHECK   arch/x86/kernel/cpu/microcode/core.c
+      ./arch/x86/include/asm/microcode_amd.h:56:6: warning: symbol \
+              'reload_ucode_amd' was not declared. Should it be static?
+        CC      arch/x86/kernel/cpu/microcode/core.o
+      In file included from arch/x86/kernel/cpu/microcode/core.c:36:
+      ./arch/x86/include/asm/microcode_amd.h:56:6: warning: no previous \
+              prototype for 'reload_ucode_amd' [-Wmissing-prototypes]
+         56 | void reload_ucode_amd(void) {}
+            |      ^~~~~~~~~~~~~~~~
+    
+    And they're right - that function can be a static inline like its
+    brethren.
+    
+    Signed-off-by: Valdis Klētnieks 
+    Signed-off-by: Borislav Petkov 
+    Cc: Luc Van Oostenryck 
+    Cc: x86@kernel.org
+    Link: https://lkml.kernel.org/r/52170.1575603873@turing-police
+
+diff --git a/arch/x86/include/asm/microcode_amd.h b/arch/x86/include/asm/microcode_amd.h
+index 209492849566..6685e1218959 100644
+--- a/arch/x86/include/asm/microcode_amd.h
++++ b/arch/x86/include/asm/microcode_amd.h
+@@ -53,6 +53,6 @@ static inline void __init load_ucode_amd_bsp(unsigned int family) {}
+ static inline void load_ucode_amd_ap(unsigned int family) {}
+ static inline int __init
+ save_microcode_in_initrd_amd(unsigned int family) { return -EINVAL; }
+-void reload_ucode_amd(void) {}
++static inline void reload_ucode_amd(void) {}
+ #endif
+ #endif /* _ASM_X86_MICROCODE_AMD_H */

commit 579d705cd64e44f3fcda1a6cfd5f37468a5ddf63
+Author: Valdis Kletnieks 
+Date:   Thu Dec 5 20:58:36 2019 -0500
+
+    crypto: chacha - fix warning message in header file
+    
+    Building with W=1 causes a warning:
+    
+      CC [M]  arch/x86/crypto/chacha_glue.o
+    In file included from arch/x86/crypto/chacha_glue.c:10:
+    ./include/crypto/internal/chacha.h:37:1: warning: 'inline' is not at beginning of declaration [-Wold-style-declaration]
+       37 | static int inline chacha12_setkey(struct crypto_skcipher *tfm, const u8 *key,
+          | ^~~~~~
+    
+    Straighten out the order to match the rest of the header file.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Herbert Xu 
+
+diff --git a/include/crypto/internal/chacha.h b/include/crypto/internal/chacha.h
+index aa5d4a16aac5..b085dc1ac151 100644
+--- a/include/crypto/internal/chacha.h
++++ b/include/crypto/internal/chacha.h
+@@ -34,7 +34,7 @@ static inline int chacha20_setkey(struct crypto_skcipher *tfm, const u8 *key,
+ 	return chacha_setkey(tfm, key, keysize, 20);
+ }
+ 
+-static int inline chacha12_setkey(struct crypto_skcipher *tfm, const u8 *key,
++static inline int chacha12_setkey(struct crypto_skcipher *tfm, const u8 *key,
+ 				  unsigned int keysize)
+ {
+ 	return chacha_setkey(tfm, key, keysize, 12);

commit 6366e523eb56b4b7191fd4261941a2762b6957bd
+Author: Valdis Kletnieks 
+Date:   Tue Nov 12 17:36:08 2019 -0500
+
+    staging: exfat: Update the TODO file
+    
+    Updating with the current laundry list of things that need attention.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191112223609.163501-1-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/TODO b/drivers/staging/exfat/TODO
+index b60e50b9cf4e..a283ce534cf4 100644
+--- a/drivers/staging/exfat/TODO
++++ b/drivers/staging/exfat/TODO
+@@ -1,17 +1,22 @@
++A laundry list of things that need looking at, most of which will
++require more work than the average checkpatch cleanup...
++
++Note that some of these entries may not be bugs - they're things
++that need to be looked at, and *possibly* fixed.
++
++Clean up the ffsCamelCase function names.
++
++Fix (thing)->flags to not use magic numbers - multiple offenders
++
++Sort out all the s32/u32/u8 nonsense - most of these should be plain int.
++
+ exfat_core.c - ffsReadFile - the goto err_out seem to leak a brelse().
+ same for ffsWriteFile.
+ 
+-exfat_core.c - fs_sync(sb,0) all over the place looks fishy as hell.
+-There's only one place that calls it with a non-zero argument.
+-Randomly removing fs_sync() calls is *not* the right answer, especially
+-if the removal then leaves a call to fs_set_vol_flags(VOL_CLEAN), as that
+-says the file system is clean and synced when we *know* it isn't.
+-The proper fix here is to go through and actually analyze how DELAYED_SYNC
+-should work, and any time we're setting VOL_CLEAN, ensure the file system
+-has in fact been synced to disk.  In other words, changing the 'false' to
+-'true' is probably more correct. Also, it's likely that the one current
+-place where it actually does an bdev_sync isn't sufficient in the DELAYED_SYNC
+-case.
++All the calls to fs_sync() need to be looked at, particularly in the
++context of EXFAT_DELAYED_SYNC. Currently, if that's defined, we only
++flush to disk when sync() gets called.  We should be doing at least
++metadata flushes at appropriate times.
+ 
+ ffsTruncateFile -  if (old_size <= new_size) {
+ That doesn't look right. How did it ever work? Are they relying on lazy
+@@ -19,3 +24,46 @@ block allocation when actual writes happen? If nothing else, it never
+ does the 'fid->size = new_size' and do the inode update....
+ 
+ ffsSetAttr() is just dangling in the breeze, not wired up at all...
++
++Convert global mutexes to a per-superblock mutex.
++
++Right now, we load exactly one UTF-8 table. Check to see
++if that plays nice with different codepage and iocharset values
++for simultanous mounts of different devices
++
++exfat_rmdir() checks for -EBUSY but ffsRemoveDir() doesn't return it.
++In fact, there's a complete lack of -EBUSY testing anywhere.
++
++There's probably a few missing checks for -EEXIST
++
++check return codes of sync_dirty_buffer()
++
++Why is remove_file doing a num_entries++??
++
++Double check a lot of can't-happen parameter checks (for null pointers for
++things that have only one call site and can't pass a null, etc).
++
++All the DEBUG stuff can probably be tossed, including the ioctl(). Either
++that, or convert to a proper fault-injection system.
++
++exfat_remount does exactly one thing.  Fix to actually deal with remount
++options, particularly handling R/O correctly.  For that matter, allow
++R/O mounts in the first place.
++
++Figure out why the VFAT code used multi_sector_(read|write) but the
++exfat code doesn't use it. The difference matters on SSDs with wear leveling.
++
++exfat_fat_sync(), exfat_buf_sync(), and sync_alloc_bitmap()
++aren't called anyplace....
++
++Create helper function for exfat_set_entry_time() and exfat_set_entry_type()
++because it's sort of ugly to be calling the same functionn directly and
++other code calling through the fs_func struc ponters...
++
++clean up the remaining vol_type checks, which are of two types:
++some are ?: operators with magic numbers, and the rest are places
++where we're doing stuff with '.' and '..'.
++
++Patches to:
++	Greg Kroah-Hartman 
++	Valdis Kletnieks 

commit 65b88d81f5c9603ddfc86fc86c28f282408ffe8e
+Author: Valdis Kletnieks 
+Date:   Tue Nov 12 16:12:38 2019 -0500
+
+    staging: exfat: Clean up the namespace pollution part 8
+    
+    Rename all the FAT_* functions to exfat_fat_*.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191112211238.156490-13-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index 6a9cb6c68d28..2aac1e000977 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -739,12 +739,12 @@ void nls_cstring_to_uniname(struct super_block *sb,
+ /* buffer cache management */
+ void exfat_buf_init(struct super_block *sb);
+ void exfat_buf_shutdown(struct super_block *sb);
+-int FAT_read(struct super_block *sb, u32 loc, u32 *content);
+-s32 FAT_write(struct super_block *sb, u32 loc, u32 content);
+-u8 *FAT_getblk(struct super_block *sb, sector_t sec);
+-void FAT_modify(struct super_block *sb, sector_t sec);
+-void FAT_release_all(struct super_block *sb);
+-void FAT_sync(struct super_block *sb);
++int exfat_fat_read(struct super_block *sb, u32 loc, u32 *content);
++s32 exfat_fat_write(struct super_block *sb, u32 loc, u32 content);
++u8 *exfat_fat_getblk(struct super_block *sb, sector_t sec);
++void exfat_fat_modify(struct super_block *sb, sector_t sec);
++void exfat_fat_release_all(struct super_block *sb);
++void exfat_fat_sync(struct super_block *sb);
+ u8 *exfat_buf_getblk(struct super_block *sb, sector_t sec);
+ void exfat_buf_modify(struct super_block *sb, sector_t sec);
+ void exfat_buf_lock(struct super_block *sb, sector_t sec);
+diff --git a/drivers/staging/exfat/exfat_cache.c b/drivers/staging/exfat/exfat_cache.c
+index 835871b2a3d0..3fd5604058a9 100644
+--- a/drivers/staging/exfat/exfat_cache.c
++++ b/drivers/staging/exfat/exfat_cache.c
+@@ -193,7 +193,7 @@ void exfat_buf_shutdown(struct super_block *sb)
+ {
+ }
+ 
+-static int __FAT_read(struct super_block *sb, u32 loc, u32 *content)
++static int __exfat_fat_read(struct super_block *sb, u32 loc, u32 *content)
+ {
+ 	s32 off;
+ 	u32 _content;
+@@ -206,7 +206,7 @@ static int __FAT_read(struct super_block *sb, u32 loc, u32 *content)
+ 		(loc >> (p_bd->sector_size_bits - 2));
+ 	off = (loc << 2) & p_bd->sector_size_mask;
+ 
+-	fat_sector = FAT_getblk(sb, sec);
++	fat_sector = exfat_fat_getblk(sb, sec);
+ 	if (!fat_sector)
+ 		return -1;
+ 
+@@ -226,18 +226,18 @@ static int __FAT_read(struct super_block *sb, u32 loc, u32 *content)
+  * returns 0 on success
+  *            -1 on error
+  */
+-int FAT_read(struct super_block *sb, u32 loc, u32 *content)
++int exfat_fat_read(struct super_block *sb, u32 loc, u32 *content)
+ {
+ 	s32 ret;
+ 
+ 	mutex_lock(&f_mutex);
+-	ret = __FAT_read(sb, loc, content);
++	ret = __exfat_fat_read(sb, loc, content);
+ 	mutex_unlock(&f_mutex);
+ 
+ 	return ret;
+ }
+ 
+-static s32 __FAT_write(struct super_block *sb, u32 loc, u32 content)
++static s32 __exfat_fat_write(struct super_block *sb, u32 loc, u32 content)
+ {
+ 	s32 off;
+ 	sector_t sec;
+@@ -249,7 +249,7 @@ static s32 __FAT_write(struct super_block *sb, u32 loc, u32 content)
+ 					 (p_bd->sector_size_bits - 2));
+ 	off = (loc << 2) & p_bd->sector_size_mask;
+ 
+-	fat_sector = FAT_getblk(sb, sec);
++	fat_sector = exfat_fat_getblk(sb, sec);
+ 	if (!fat_sector)
+ 		return -1;
+ 
+@@ -257,22 +257,22 @@ static s32 __FAT_write(struct super_block *sb, u32 loc, u32 content)
+ 
+ 	SET32_A(fat_entry, content);
+ 
+-	FAT_modify(sb, sec);
++	exfat_fat_modify(sb, sec);
+ 	return 0;
+ }
+ 
+-int FAT_write(struct super_block *sb, u32 loc, u32 content)
++int exfat_fat_write(struct super_block *sb, u32 loc, u32 content)
+ {
+ 	s32 ret;
+ 
+ 	mutex_lock(&f_mutex);
+-	ret = __FAT_write(sb, loc, content);
++	ret = __exfat_fat_write(sb, loc, content);
+ 	mutex_unlock(&f_mutex);
+ 
+ 	return ret;
+ }
+ 
+-u8 *FAT_getblk(struct super_block *sb, sector_t sec)
++u8 *exfat_fat_getblk(struct super_block *sb, sector_t sec)
+ {
+ 	struct buf_cache_t *bp;
+ 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+@@ -307,7 +307,7 @@ u8 *FAT_getblk(struct super_block *sb, sector_t sec)
+ 	return bp->buf_bh->b_data;
+ }
+ 
+-void FAT_modify(struct super_block *sb, sector_t sec)
++void exfat_fat_modify(struct super_block *sb, sector_t sec)
+ {
+ 	struct buf_cache_t *bp;
+ 
+@@ -316,7 +316,7 @@ void FAT_modify(struct super_block *sb, sector_t sec)
+ 		sector_write(sb, sec, bp->buf_bh, 0);
+ }
+ 
+-void FAT_release_all(struct super_block *sb)
++void exfat_fat_release_all(struct super_block *sb)
+ {
+ 	struct buf_cache_t *bp;
+ 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+@@ -341,7 +341,7 @@ void FAT_release_all(struct super_block *sb)
+ 	mutex_unlock(&f_mutex);
+ }
+ 
+-void FAT_sync(struct super_block *sb)
++void exfat_fat_sync(struct super_block *sb)
+ {
+ 	struct buf_cache_t *bp;
+ 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
+index f60fb691e165..1638ed266f68 100644
+--- a/drivers/staging/exfat/exfat_core.c
++++ b/drivers/staging/exfat/exfat_core.c
+@@ -283,7 +283,7 @@ static s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc,
+ 		num_clusters++;
+ 
+ 		if (p_chain->flags == 0x01) {
+-			if (FAT_write(sb, new_clu, CLUSTER_32(~0)) < 0)
++			if (exfat_fat_write(sb, new_clu, CLUSTER_32(~0)) < 0)
+ 				return -EIO;
+ 		}
+ 
+@@ -291,7 +291,7 @@ static s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc,
+ 			p_chain->dir = new_clu;
+ 		} else {
+ 			if (p_chain->flags == 0x01) {
+-				if (FAT_write(sb, last_clu, new_clu) < 0)
++				if (exfat_fat_write(sb, last_clu, new_clu) < 0)
+ 					return -EIO;
+ 			}
+ 		}
+@@ -375,7 +375,7 @@ static void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
+ 			if (clr_alloc_bitmap(sb, clu - 2) != 0)
+ 				break;
+ 
+-			if (FAT_read(sb, clu, &clu) == -1)
++			if (exfat_fat_read(sb, clu, &clu) == -1)
+ 				break;
+ 			num_clusters++;
+ 		} while ((clu != CLUSTER_32(0)) && (clu != CLUSTER_32(~0)));
+@@ -395,7 +395,7 @@ static u32 find_last_cluster(struct super_block *sb, struct chain_t *p_chain)
+ 	if (p_chain->flags == 0x03) {
+ 		clu += p_chain->size - 1;
+ 	} else {
+-		while ((FAT_read(sb, clu, &next) == 0) &&
++		while ((exfat_fat_read(sb, clu, &next) == 0) &&
+ 		       (next != CLUSTER_32(~0))) {
+ 			if (p_fs->dev_ejected)
+ 				break;
+@@ -422,7 +422,7 @@ s32 count_num_clusters(struct super_block *sb, struct chain_t *p_chain)
+ 	} else {
+ 		for (i = 2; i < p_fs->num_clusters; i++) {
+ 			count++;
+-			if (FAT_read(sb, clu, &clu) != 0)
++			if (exfat_fat_read(sb, clu, &clu) != 0)
+ 				return 0;
+ 			if (clu == CLUSTER_32(~0))
+ 				break;
+@@ -461,12 +461,12 @@ void exfat_chain_cont_cluster(struct super_block *sb, u32 chain, s32 len)
+ 		return;
+ 
+ 	while (len > 1) {
+-		if (FAT_write(sb, chain, chain + 1) < 0)
++		if (exfat_fat_write(sb, chain, chain + 1) < 0)
+ 			break;
+ 		chain++;
+ 		len--;
+ 	}
+-	FAT_write(sb, chain, CLUSTER_32(~0));
++	exfat_fat_write(sb, chain, CLUSTER_32(~0));
+ }
+ 
+ /*
+@@ -538,7 +538,7 @@ s32 load_alloc_bitmap(struct super_block *sb)
+ 			}
+ 		}
+ 
+-		if (FAT_read(sb, clu.dir, &clu.dir) != 0)
++		if (exfat_fat_read(sb, clu.dir, &clu.dir) != 0)
+ 			return -EIO;
+ 	}
+ 
+@@ -760,7 +760,7 @@ s32 load_upcase_table(struct super_block *sb)
+ 				break;
+ 			return 0;
+ 		}
+-		if (FAT_read(sb, clu.dir, &clu.dir) != 0)
++		if (exfat_fat_read(sb, clu.dir, &clu.dir) != 0)
+ 			return -EIO;
+ 	}
+ 	/* load default upcase table */
+@@ -1180,7 +1180,7 @@ static s32 __write_partial_entries_in_entry_set(struct super_block *sb,
+ 				if (es->alloc_flag == 0x03) {
+ 					clu++;
+ 				} else {
+-					if (FAT_read(sb, clu, &clu) == -1)
++					if (exfat_fat_read(sb, clu, &clu) == -1)
+ 						goto err_out;
+ 				}
+ 				sec = START_SECTOR(clu);
+@@ -1242,7 +1242,7 @@ static s32 _walk_fat_chain(struct super_block *sb, struct chain_t *p_dir,
+ 		cur_clu += clu_offset;
+ 	} else {
+ 		while (clu_offset > 0) {
+-			if (FAT_read(sb, cur_clu, &cur_clu) == -1)
++			if (exfat_fat_read(sb, cur_clu, &cur_clu) == -1)
+ 				return -EIO;
+ 			clu_offset--;
+ 		}
+@@ -1450,7 +1450,7 @@ struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb,
+ 				if (es->alloc_flag == 0x03) {
+ 					clu++;
+ 				} else {
+-					if (FAT_read(sb, clu, &clu) == -1)
++					if (exfat_fat_read(sb, clu, &clu) == -1)
+ 						goto err_out;
+ 				}
+ 				sec = START_SECTOR(clu);
+@@ -1575,7 +1575,7 @@ static s32 search_deleted_or_unused_entry(struct super_block *sb,
+ 			else
+ 				clu.dir = CLUSTER_32(~0);
+ 		} else {
+-			if (FAT_read(sb, clu.dir, &clu.dir) != 0)
++			if (exfat_fat_read(sb, clu.dir, &clu.dir) != 0)
+ 				return -1;
+ 		}
+ 	}
+@@ -1625,7 +1625,7 @@ static s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_
+ 			p_fs->hint_uentry.clu.flags = 0x01;
+ 		}
+ 		if (clu.flags == 0x01)
+-			if (FAT_write(sb, last_clu, clu.dir) < 0)
++			if (exfat_fat_write(sb, last_clu, clu.dir) < 0)
+ 				return -EIO;
+ 
+ 		if (p_fs->hint_uentry.entry == -1) {
+@@ -1822,7 +1822,7 @@ static s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+ 			else
+ 				clu.dir = CLUSTER_32(~0);
+ 		} else {
+-			if (FAT_read(sb, clu.dir, &clu.dir) != 0)
++			if (exfat_fat_read(sb, clu.dir, &clu.dir) != 0)
+ 				return -2;
+ 		}
+ 	}
+@@ -1903,7 +1903,7 @@ s32 count_dos_name_entries(struct super_block *sb, struct chain_t *p_dir,
+ 			else
+ 				clu.dir = CLUSTER_32(~0);
+ 		} else {
+-			if (FAT_read(sb, clu.dir, &clu.dir) != 0)
++			if (exfat_fat_read(sb, clu.dir, &clu.dir) != 0)
+ 				return -EIO;
+ 		}
+ 	}
+@@ -1963,7 +1963,7 @@ bool is_dir_empty(struct super_block *sb, struct chain_t *p_dir)
+ 			else
+ 				clu.dir = CLUSTER_32(~0);
+ 		}
+-		if (FAT_read(sb, clu.dir, &clu.dir) != 0)
++		if (exfat_fat_read(sb, clu.dir, &clu.dir) != 0)
+ 			break;
+ 	}
+ 
+diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
+index 4b8915098d20..23002aefc964 100644
+--- a/drivers/staging/exfat/exfat_super.c
++++ b/drivers/staging/exfat/exfat_super.c
+@@ -457,7 +457,7 @@ static int ffsUmountVol(struct super_block *sb)
+ 	free_upcase_table(sb);
+ 	free_alloc_bitmap(sb);
+ 
+-	FAT_release_all(sb);
++	exfat_fat_release_all(sb);
+ 	exfat_buf_release_all(sb);
+ 
+ 	/* close the block device */
+@@ -722,8 +722,8 @@ static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer,
+ 			}
+ 
+ 			while (clu_offset > 0) {
+-				/* clu = FAT_read(sb, clu); */
+-				if (FAT_read(sb, clu, &clu) == -1) {
++				/* clu = exfat_fat_read(sb, clu); */
++				if (exfat_fat_read(sb, clu, &clu) == -1) {
+ 					ret = -EIO;
+ 					goto out;
+ 				}
+@@ -868,8 +868,8 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
+ 
+ 			while ((clu_offset > 0) && (clu != CLUSTER_32(~0))) {
+ 				last_clu = clu;
+-				/* clu = FAT_read(sb, clu); */
+-				if (FAT_read(sb, clu, &clu) == -1) {
++				/* clu = exfat_fat_read(sb, clu); */
++				if (exfat_fat_read(sb, clu, &clu) == -1) {
+ 					ret = -EIO;
+ 					goto out;
+ 				}
+@@ -911,7 +911,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
+ 					modified = true;
+ 				}
+ 				if (new_clu.flags == 0x01)
+-					FAT_write(sb, last_clu, new_clu.dir);
++					exfat_fat_write(sb, last_clu, new_clu.dir);
+ 			}
+ 
+ 			num_clusters += num_alloced;
+@@ -1081,7 +1081,7 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size)
+ 		} else {
+ 			while (num_clusters > 0) {
+ 				last_clu = clu.dir;
+-				if (FAT_read(sb, clu.dir, &clu.dir) == -1) {
++				if (exfat_fat_read(sb, clu.dir, &clu.dir) == -1) {
+ 					ret = -EIO;
+ 					goto out;
+ 				}
+@@ -1123,7 +1123,7 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size)
+ 	/* (2) cut off from the FAT chain */
+ 	if (last_clu != CLUSTER_32(0)) {
+ 		if (fid->flags == 0x01)
+-			FAT_write(sb, last_clu, CLUSTER_32(~0));
++			exfat_fat_write(sb, last_clu, CLUSTER_32(~0));
+ 	}
+ 
+ 	/* (3) free the clusters */
+@@ -1687,7 +1687,7 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
+ 
+ 		while ((clu_offset > 0) && (*clu != CLUSTER_32(~0))) {
+ 			last_clu = *clu;
+-			if (FAT_read(sb, *clu, clu) == -1) {
++			if (exfat_fat_read(sb, *clu, clu) == -1) {
+ 				ret = -EIO;
+ 				goto out;
+ 			}
+@@ -1727,7 +1727,7 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
+ 				modified = true;
+ 			}
+ 			if (new_clu.flags == 0x01)
+-				FAT_write(sb, last_clu, new_clu.dir);
++				exfat_fat_write(sb, last_clu, new_clu.dir);
+ 		}
+ 
+ 		num_clusters += num_alloced;
+@@ -1888,8 +1888,8 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
+ 			}
+ 
+ 			while (clu_offset > 0) {
+-				/* clu.dir = FAT_read(sb, clu.dir); */
+-				if (FAT_read(sb, clu.dir, &clu.dir) == -1) {
++				/* clu.dir = exfat_fat_read(sb, clu.dir); */
++				if (exfat_fat_read(sb, clu.dir, &clu.dir) == -1) {
+ 					ret = -EIO;
+ 					goto out;
+ 				}
+@@ -1983,8 +1983,8 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
+ 			else
+ 				clu.dir = CLUSTER_32(~0);
+ 		} else {
+-			/* clu.dir = FAT_read(sb, clu.dir); */
+-			if (FAT_read(sb, clu.dir, &clu.dir) == -1) {
++			/* clu.dir = exfat_fat_read(sb, clu.dir); */
++			if (exfat_fat_read(sb, clu.dir, &clu.dir) == -1) {
+ 				ret = -EIO;
+ 				goto out;
+ 			}
+@@ -3821,7 +3821,7 @@ static void exfat_debug_kill_sb(struct super_block *sb)
+ 			 * dirty. We use this to simulate device removal.
+ 			 */
+ 			mutex_lock(&p_fs->v_mutex);
+-			FAT_release_all(sb);
++			exfat_fat_release_all(sb);
+ 			exfat_buf_release_all(sb);
+ 			mutex_unlock(&p_fs->v_mutex);
+ 

commit 99a4b135289ed3e633a2f6bba1750513d9e4f731
+Author: Valdis Kletnieks 
+Date:   Tue Nov 12 16:12:37 2019 -0500
+
+    staging: exfat: Clean up the namespace pollution part 7
+    
+    Global functions called 'buf*' are a linkage editor disaster waiting to
+    happen.  Rename our buf_* functions to exfat_buf_*
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191112211238.156490-12-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index 188ea1bd7162..6a9cb6c68d28 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -737,21 +737,21 @@ void nls_cstring_to_uniname(struct super_block *sb,
+ 			    bool *p_lossy);
+ 
+ /* buffer cache management */
+-void buf_init(struct super_block *sb);
+-void buf_shutdown(struct super_block *sb);
++void exfat_buf_init(struct super_block *sb);
++void exfat_buf_shutdown(struct super_block *sb);
+ int FAT_read(struct super_block *sb, u32 loc, u32 *content);
+ s32 FAT_write(struct super_block *sb, u32 loc, u32 content);
+ u8 *FAT_getblk(struct super_block *sb, sector_t sec);
+ void FAT_modify(struct super_block *sb, sector_t sec);
+ void FAT_release_all(struct super_block *sb);
+ void FAT_sync(struct super_block *sb);
+-u8 *buf_getblk(struct super_block *sb, sector_t sec);
+-void buf_modify(struct super_block *sb, sector_t sec);
+-void buf_lock(struct super_block *sb, sector_t sec);
+-void buf_unlock(struct super_block *sb, sector_t sec);
+-void buf_release(struct super_block *sb, sector_t sec);
+-void buf_release_all(struct super_block *sb);
+-void buf_sync(struct super_block *sb);
++u8 *exfat_buf_getblk(struct super_block *sb, sector_t sec);
++void exfat_buf_modify(struct super_block *sb, sector_t sec);
++void exfat_buf_lock(struct super_block *sb, sector_t sec);
++void exfat_buf_unlock(struct super_block *sb, sector_t sec);
++void exfat_buf_release(struct super_block *sb, sector_t sec);
++void exfat_buf_release_all(struct super_block *sb);
++void exfat_buf_sync(struct super_block *sb);
+ 
+ /* fs management functions */
+ void fs_set_vol_flags(struct super_block *sb, u32 new_flag);
+diff --git a/drivers/staging/exfat/exfat_cache.c b/drivers/staging/exfat/exfat_cache.c
+index 1d344c5f3e15..835871b2a3d0 100644
+--- a/drivers/staging/exfat/exfat_cache.c
++++ b/drivers/staging/exfat/exfat_cache.c
+@@ -128,7 +128,7 @@ static void buf_cache_remove_hash(struct buf_cache_t *bp)
+ 	(bp->hash_next)->hash_prev = bp->hash_prev;
+ }
+ 
+-void buf_init(struct super_block *sb)
++void exfat_buf_init(struct super_block *sb)
+ {
+ 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+ 
+@@ -189,7 +189,7 @@ void buf_init(struct super_block *sb)
+ 		buf_cache_insert_hash(sb, &p_fs->buf_cache_array[i]);
+ }
+ 
+-void buf_shutdown(struct super_block *sb)
++void exfat_buf_shutdown(struct super_block *sb)
+ {
+ }
+ 
+@@ -392,7 +392,7 @@ static struct buf_cache_t *buf_cache_get(struct super_block *sb, sector_t sec)
+ 	return bp;
+ }
+ 
+-static u8 *__buf_getblk(struct super_block *sb, sector_t sec)
++static u8 *__exfat_buf_getblk(struct super_block *sb, sector_t sec)
+ {
+ 	struct buf_cache_t *bp;
+ 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+@@ -427,18 +427,18 @@ static u8 *__buf_getblk(struct super_block *sb, sector_t sec)
+ 	return bp->buf_bh->b_data;
+ }
+ 
+-u8 *buf_getblk(struct super_block *sb, sector_t sec)
++u8 *exfat_buf_getblk(struct super_block *sb, sector_t sec)
+ {
+ 	u8 *buf;
+ 
+ 	mutex_lock(&b_mutex);
+-	buf = __buf_getblk(sb, sec);
++	buf = __exfat_buf_getblk(sb, sec);
+ 	mutex_unlock(&b_mutex);
+ 
+ 	return buf;
+ }
+ 
+-void buf_modify(struct super_block *sb, sector_t sec)
++void exfat_buf_modify(struct super_block *sb, sector_t sec)
+ {
+ 	struct buf_cache_t *bp;
+ 
+@@ -454,7 +454,7 @@ void buf_modify(struct super_block *sb, sector_t sec)
+ 	mutex_unlock(&b_mutex);
+ }
+ 
+-void buf_lock(struct super_block *sb, sector_t sec)
++void exfat_buf_lock(struct super_block *sb, sector_t sec)
+ {
+ 	struct buf_cache_t *bp;
+ 
+@@ -470,7 +470,7 @@ void buf_lock(struct super_block *sb, sector_t sec)
+ 	mutex_unlock(&b_mutex);
+ }
+ 
+-void buf_unlock(struct super_block *sb, sector_t sec)
++void exfat_buf_unlock(struct super_block *sb, sector_t sec)
+ {
+ 	struct buf_cache_t *bp;
+ 
+@@ -486,7 +486,7 @@ void buf_unlock(struct super_block *sb, sector_t sec)
+ 	mutex_unlock(&b_mutex);
+ }
+ 
+-void buf_release(struct super_block *sb, sector_t sec)
++void exfat_buf_release(struct super_block *sb, sector_t sec)
+ {
+ 	struct buf_cache_t *bp;
+ 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+@@ -510,7 +510,7 @@ void buf_release(struct super_block *sb, sector_t sec)
+ 	mutex_unlock(&b_mutex);
+ }
+ 
+-void buf_release_all(struct super_block *sb)
++void exfat_buf_release_all(struct super_block *sb)
+ {
+ 	struct buf_cache_t *bp;
+ 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+@@ -535,7 +535,7 @@ void buf_release_all(struct super_block *sb)
+ 	mutex_unlock(&b_mutex);
+ }
+ 
+-void buf_sync(struct super_block *sb)
++void exfat_buf_sync(struct super_block *sb)
+ {
+ 	struct buf_cache_t *bp;
+ 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
+index 3cc13aaaed24..f60fb691e165 100644
+--- a/drivers/staging/exfat/exfat_core.c
++++ b/drivers/staging/exfat/exfat_core.c
+@@ -352,7 +352,7 @@ static void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
+ 			if (do_relse) {
+ 				sector = START_SECTOR(clu);
+ 				for (i = 0; i < p_fs->sectors_per_clu; i++)
+-					buf_release(sb, sector + i);
++					exfat_buf_release(sb, sector + i);
+ 			}
+ 
+ 			if (clr_alloc_bitmap(sb, clu - 2) != 0)
+@@ -369,7 +369,7 @@ static void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
+ 			if (do_relse) {
+ 				sector = START_SECTOR(clu);
+ 				for (i = 0; i < p_fs->sectors_per_clu; i++)
+-					buf_release(sb, sector + i);
++					exfat_buf_release(sb, sector + i);
+ 			}
+ 
+ 			if (clr_alloc_bitmap(sb, clu - 2) != 0)
+@@ -1032,10 +1032,10 @@ static s32 exfat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+ 		return -ENOENT;
+ 
+ 	init_file_entry(file_ep, type);
+-	buf_modify(sb, sector);
++	exfat_buf_modify(sb, sector);
+ 
+ 	init_strm_entry(strm_ep, flags, start_clu, size);
+-	buf_modify(sb, sector);
++	exfat_buf_modify(sb, sector);
+ 
+ 	return 0;
+ }
+@@ -1058,7 +1058,7 @@ static s32 exfat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir,
+ 		return -ENOENT;
+ 
+ 	file_ep->num_ext = (u8)(num_entries - 1);
+-	buf_modify(sb, sector);
++	exfat_buf_modify(sb, sector);
+ 
+ 	strm_ep = (struct strm_dentry_t *)get_entry_in_dir(sb, p_dir, entry + 1,
+ 							   §or);
+@@ -1067,7 +1067,7 @@ static s32 exfat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir,
+ 
+ 	strm_ep->name_len = p_uniname->name_len;
+ 	SET16_A(strm_ep->name_hash, p_uniname->name_hash);
+-	buf_modify(sb, sector);
++	exfat_buf_modify(sb, sector);
+ 
+ 	for (i = 2; i < num_entries; i++) {
+ 		name_ep = (struct name_dentry_t *)get_entry_in_dir(sb, p_dir,
+@@ -1077,7 +1077,7 @@ static s32 exfat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir,
+ 			return -ENOENT;
+ 
+ 		init_name_entry(name_ep, uniname);
+-		buf_modify(sb, sector);
++		exfat_buf_modify(sb, sector);
+ 		uniname += 15;
+ 	}
+ 
+@@ -1100,7 +1100,7 @@ static void exfat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir
+ 			return;
+ 
+ 		p_fs->fs_func->set_entry_type(ep, TYPE_DELETED);
+-		buf_modify(sb, sector);
++		exfat_buf_modify(sb, sector);
+ 	}
+ }
+ 
+@@ -1118,7 +1118,7 @@ void update_dir_checksum(struct super_block *sb, struct chain_t *p_dir,
+ 	if (!file_ep)
+ 		return;
+ 
+-	buf_lock(sb, sector);
++	exfat_buf_lock(sb, sector);
+ 
+ 	num_entries = (s32)file_ep->num_ext + 1;
+ 	chksum = calc_checksum_2byte((void *)file_ep, DENTRY_SIZE, 0,
+@@ -1127,7 +1127,7 @@ void update_dir_checksum(struct super_block *sb, struct chain_t *p_dir,
+ 	for (i = 1; i < num_entries; i++) {
+ 		ep = get_entry_in_dir(sb, p_dir, entry + i, NULL);
+ 		if (!ep) {
+-			buf_unlock(sb, sector);
++			exfat_buf_unlock(sb, sector);
+ 			return;
+ 		}
+ 
+@@ -1136,8 +1136,8 @@ void update_dir_checksum(struct super_block *sb, struct chain_t *p_dir,
+ 	}
+ 
+ 	SET16_A(file_ep->checksum, chksum);
+-	buf_modify(sb, sector);
+-	buf_unlock(sb, sector);
++	exfat_buf_modify(sb, sector);
++	exfat_buf_unlock(sb, sector);
+ }
+ 
+ static s32 __write_partial_entries_in_entry_set(struct super_block *sb,
+@@ -1161,7 +1161,7 @@ static s32 __write_partial_entries_in_entry_set(struct super_block *sb,
+ 		copy_entries = min_t(s32,
+ 				     remaining_byte_in_sector >> DENTRY_SIZE_BITS,
+ 				     num_entries);
+-		buf = buf_getblk(sb, sec);
++		buf = exfat_buf_getblk(sb, sec);
+ 		if (!buf)
+ 			goto err_out;
+ 		pr_debug("es->buf %p buf_off %u\n", esbuf, buf_off);
+@@ -1170,7 +1170,7 @@ static s32 __write_partial_entries_in_entry_set(struct super_block *sb,
+ 			 (unsigned long long)sec);
+ 		memcpy(buf + off, esbuf + buf_off,
+ 		       copy_entries << DENTRY_SIZE_BITS);
+-		buf_modify(sb, sec);
++		exfat_buf_modify(sb, sec);
+ 		num_entries -= copy_entries;
+ 
+ 		if (num_entries) {
+@@ -1295,7 +1295,7 @@ struct dentry_t *get_entry_in_dir(struct super_block *sb, struct chain_t *p_dir,
+ 	if (find_location(sb, p_dir, entry, &sec, &off) != 0)
+ 		return NULL;
+ 
+-	buf = buf_getblk(sb, sec);
++	buf = exfat_buf_getblk(sb, sec);
+ 
+ 	if (!buf)
+ 		return NULL;
+@@ -1359,7 +1359,7 @@ struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb,
+ 	sec = byte_offset >> p_bd->sector_size_bits;
+ 	sec += START_SECTOR(clu);
+ 
+-	buf = buf_getblk(sb, sec);
++	buf = exfat_buf_getblk(sb, sec);
+ 	if (!buf)
+ 		goto err_out;
+ 
+@@ -1457,7 +1457,7 @@ struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb,
+ 			} else {
+ 				sec++;
+ 			}
+-			buf = buf_getblk(sb, sec);
++			buf = exfat_buf_getblk(sb, sec);
+ 			if (!buf)
+ 				goto err_out;
+ 			off = 0;
+@@ -1649,7 +1649,7 @@ static s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_
+ 				return -ENOENT;
+ 			p_fs->fs_func->set_entry_size(ep, size);
+ 			p_fs->fs_func->set_entry_flag(ep, p_dir->flags);
+-			buf_modify(sb, sector);
++			exfat_buf_modify(sb, sector);
+ 
+ 			update_dir_checksum(sb, &fid->dir,
+ 					    fid->entry);
+@@ -2341,17 +2341,17 @@ void remove_file(struct inode *inode, struct chain_t *p_dir, s32 entry)
+ 	if (!ep)
+ 		return;
+ 
+-	buf_lock(sb, sector);
++	exfat_buf_lock(sb, sector);
+ 
+-	/* buf_lock() before call count_ext_entries() */
++	/* exfat_buf_lock() before call count_ext_entries() */
+ 	num_entries = fs_func->count_ext_entries(sb, p_dir, entry, ep);
+ 	if (num_entries < 0) {
+-		buf_unlock(sb, sector);
++		exfat_buf_unlock(sb, sector);
+ 		return;
+ 	}
+ 	num_entries++;
+ 
+-	buf_unlock(sb, sector);
++	exfat_buf_unlock(sb, sector);
+ 
+ 	/* (1) update the directory entry */
+ 	fs_func->delete_dir_entry(sb, p_dir, entry, 0, num_entries);
+@@ -2372,13 +2372,13 @@ s32 rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry,
+ 	if (!epold)
+ 		return -ENOENT;
+ 
+-	buf_lock(sb, sector_old);
++	exfat_buf_lock(sb, sector_old);
+ 
+-	/* buf_lock() before call count_ext_entries() */
++	/* exfat_buf_lock() before call count_ext_entries() */
+ 	num_old_entries = fs_func->count_ext_entries(sb, p_dir, oldentry,
+ 						     epold);
+ 	if (num_old_entries < 0) {
+-		buf_unlock(sb, sector_old);
++		exfat_buf_unlock(sb, sector_old);
+ 		return -ENOENT;
+ 	}
+ 	num_old_entries++;
+@@ -2386,20 +2386,20 @@ s32 rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry,
+ 	ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname,
+ 					   &num_new_entries, &dos_name);
+ 	if (ret) {
+-		buf_unlock(sb, sector_old);
++		exfat_buf_unlock(sb, sector_old);
+ 		return ret;
+ 	}
+ 
+ 	if (num_old_entries < num_new_entries) {
+ 		newentry = find_empty_entry(inode, p_dir, num_new_entries);
+ 		if (newentry < 0) {
+-			buf_unlock(sb, sector_old);
++			exfat_buf_unlock(sb, sector_old);
+ 			return -ENOSPC;
+ 		}
+ 
+ 		epnew = get_entry_in_dir(sb, p_dir, newentry, §or_new);
+ 		if (!epnew) {
+-			buf_unlock(sb, sector_old);
++			exfat_buf_unlock(sb, sector_old);
+ 			return -ENOENT;
+ 		}
+ 
+@@ -2410,23 +2410,23 @@ s32 rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry,
+ 						ATTR_ARCHIVE);
+ 			fid->attr |= ATTR_ARCHIVE;
+ 		}
+-		buf_modify(sb, sector_new);
+-		buf_unlock(sb, sector_old);
++		exfat_buf_modify(sb, sector_new);
++		exfat_buf_unlock(sb, sector_old);
+ 
+ 		epold = get_entry_in_dir(sb, p_dir, oldentry + 1,
+ 					 §or_old);
+-		buf_lock(sb, sector_old);
++		exfat_buf_lock(sb, sector_old);
+ 		epnew = get_entry_in_dir(sb, p_dir, newentry + 1,
+ 					 §or_new);
+ 
+ 		if (!epold || !epnew) {
+-			buf_unlock(sb, sector_old);
++			exfat_buf_unlock(sb, sector_old);
+ 			return -ENOENT;
+ 		}
+ 
+ 		memcpy((void *)epnew, (void *)epold, DENTRY_SIZE);
+-		buf_modify(sb, sector_new);
+-		buf_unlock(sb, sector_old);
++		exfat_buf_modify(sb, sector_new);
++		exfat_buf_unlock(sb, sector_old);
+ 
+ 		ret = fs_func->init_ext_entry(sb, p_dir, newentry,
+ 					      num_new_entries, p_uniname,
+@@ -2444,8 +2444,8 @@ s32 rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry,
+ 						ATTR_ARCHIVE);
+ 			fid->attr |= ATTR_ARCHIVE;
+ 		}
+-		buf_modify(sb, sector_old);
+-		buf_unlock(sb, sector_old);
++		exfat_buf_modify(sb, sector_old);
++		exfat_buf_unlock(sb, sector_old);
+ 
+ 		ret = fs_func->init_ext_entry(sb, p_dir, oldentry,
+ 					      num_new_entries, p_uniname,
+@@ -2481,13 +2481,13 @@ s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
+ 	    fs_func->get_entry_clu0(epmov) == p_newdir->dir)
+ 		return -EINVAL;
+ 
+-	buf_lock(sb, sector_mov);
++	exfat_buf_lock(sb, sector_mov);
+ 
+-	/* buf_lock() before call count_ext_entries() */
++	/* exfat_buf_lock() before call count_ext_entries() */
+ 	num_old_entries = fs_func->count_ext_entries(sb, p_olddir, oldentry,
+ 						     epmov);
+ 	if (num_old_entries < 0) {
+-		buf_unlock(sb, sector_mov);
++		exfat_buf_unlock(sb, sector_mov);
+ 		return -ENOENT;
+ 	}
+ 	num_old_entries++;
+@@ -2495,19 +2495,19 @@ s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
+ 	ret = get_num_entries_and_dos_name(sb, p_newdir, p_uniname,
+ 					   &num_new_entries, &dos_name);
+ 	if (ret) {
+-		buf_unlock(sb, sector_mov);
++		exfat_buf_unlock(sb, sector_mov);
+ 		return ret;
+ 	}
+ 
+ 	newentry = find_empty_entry(inode, p_newdir, num_new_entries);
+ 	if (newentry < 0) {
+-		buf_unlock(sb, sector_mov);
++		exfat_buf_unlock(sb, sector_mov);
+ 		return -ENOSPC;
+ 	}
+ 
+ 	epnew = get_entry_in_dir(sb, p_newdir, newentry, §or_new);
+ 	if (!epnew) {
+-		buf_unlock(sb, sector_mov);
++		exfat_buf_unlock(sb, sector_mov);
+ 		return -ENOENT;
+ 	}
+ 
+@@ -2517,22 +2517,22 @@ s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
+ 					ATTR_ARCHIVE);
+ 		fid->attr |= ATTR_ARCHIVE;
+ 	}
+-	buf_modify(sb, sector_new);
+-	buf_unlock(sb, sector_mov);
++	exfat_buf_modify(sb, sector_new);
++	exfat_buf_unlock(sb, sector_mov);
+ 
+ 	epmov = get_entry_in_dir(sb, p_olddir, oldentry + 1,
+ 				 §or_mov);
+-	buf_lock(sb, sector_mov);
++	exfat_buf_lock(sb, sector_mov);
+ 	epnew = get_entry_in_dir(sb, p_newdir, newentry + 1,
+ 				 §or_new);
+ 	if (!epmov || !epnew) {
+-		buf_unlock(sb, sector_mov);
++		exfat_buf_unlock(sb, sector_mov);
+ 		return -ENOENT;
+ 	}
+ 
+ 	memcpy((void *)epnew, (void *)epmov, DENTRY_SIZE);
+-	buf_modify(sb, sector_new);
+-	buf_unlock(sb, sector_mov);
++	exfat_buf_modify(sb, sector_new);
++	exfat_buf_unlock(sb, sector_mov);
+ 
+ 	ret = fs_func->init_ext_entry(sb, p_newdir, newentry, num_new_entries,
+ 				      p_uniname, &dos_name);
+diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
+index 3828150bca3f..4b8915098d20 100644
+--- a/drivers/staging/exfat/exfat_super.c
++++ b/drivers/staging/exfat/exfat_super.c
+@@ -355,7 +355,7 @@ static int ffsMountVol(struct super_block *sb)
+ 
+ 	mutex_lock(&z_mutex);
+ 
+-	buf_init(sb);
++	exfat_buf_init(sb);
+ 
+ 	mutex_init(&p_fs->v_mutex);
+ 	p_fs->dev_ejected = 0;
+@@ -458,7 +458,7 @@ static int ffsUmountVol(struct super_block *sb)
+ 	free_alloc_bitmap(sb);
+ 
+ 	FAT_release_all(sb);
+-	buf_release_all(sb);
++	exfat_buf_release_all(sb);
+ 
+ 	/* close the block device */
+ 	exfat_bdev_close(sb);
+@@ -468,7 +468,7 @@ static int ffsUmountVol(struct super_block *sb)
+ 		err = -EIO;
+ 	}
+ 
+-	buf_shutdown(sb);
++	exfat_buf_shutdown(sb);
+ 
+ 	/* release the lock for file system critical section */
+ 	mutex_unlock(&p_fs->v_mutex);
+@@ -1921,7 +1921,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
+ 			if ((type != TYPE_FILE) && (type != TYPE_DIR))
+ 				continue;
+ 
+-			buf_lock(sb, sector);
++			exfat_buf_lock(sb, sector);
+ 			dir_entry->Attr = fs_func->get_entry_attr(ep);
+ 
+ 			fs_func->get_entry_time(ep, &tm, TM_CREATE);
+@@ -1949,7 +1949,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
+ 			fs_func->get_uni_name_from_ext_entry(sb, &dir, dentry,
+ 							     uni_name.name);
+ 			nls_uniname_to_cstring(sb, dir_entry->Name, &uni_name);
+-			buf_unlock(sb, sector);
++			exfat_buf_unlock(sb, sector);
+ 
+ 			ep = get_entry_in_dir(sb, &clu, i + 1, NULL);
+ 			if (!ep) {
+@@ -3822,7 +3822,7 @@ static void exfat_debug_kill_sb(struct super_block *sb)
+ 			 */
+ 			mutex_lock(&p_fs->v_mutex);
+ 			FAT_release_all(sb);
+-			buf_release_all(sb);
++			exfat_buf_release_all(sb);
+ 			mutex_unlock(&p_fs->v_mutex);
+ 
+ 			invalidate_bdev(bdev);

commit e5a490e03756ab07adbb736c9ecd3c34b40e0da4
+Author: Valdis Kletnieks 
+Date:   Tue Nov 12 16:12:36 2019 -0500
+
+    staging: exfat: Clean up the namespace pollution part 6
+    
+    Move a few more things so we can make them static and clear exfat.h out.
+    At this point, pretty much everything that can be static is static.
+    (Note: FAT_sync(), buf_sync(), and sync_alloc_bitmap() aren't called
+    anyplace, but aren't static because (a) that will toss an error and
+    (b) they probably *should* be getting called someplace
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191112211238.156490-11-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index c41fc3ec9f29..188ea1bd7162 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -780,12 +780,6 @@ struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb,
+ 					       u32 type,
+ 					       struct dentry_t **file_ep);
+ void release_entry_set(struct entry_set_cache_t *es);
+-s32 write_whole_entry_set(struct super_block *sb, struct entry_set_cache_t *es);
+-s32 write_partial_entries_in_entry_set(struct super_block *sb,
+-				       struct entry_set_cache_t *es,
+-				       struct dentry_t *ep, u32 count);
+-s32 search_deleted_or_unused_entry(struct super_block *sb,
+-				   struct chain_t *p_dir, s32 num_entries);
+ s32 count_dos_name_entries(struct super_block *sb, struct chain_t *p_dir,
+ 			   u32 type);
+ void update_dir_checksum(struct super_block *sb, struct chain_t *p_dir,
+@@ -798,8 +792,6 @@ bool is_dir_empty(struct super_block *sb, struct chain_t *p_dir);
+ s32 get_num_entries_and_dos_name(struct super_block *sb, struct chain_t *p_dir,
+ 				 struct uni_name_t *p_uniname, s32 *entries,
+ 				 struct dos_name_t *p_dosname);
+-s32 extract_uni_name_from_name_entry(struct name_dentry_t *ep,
+-				     u16 *uniname, s32 order);
+ u16 calc_checksum_2byte(void *data, s32 len, u16 chksum, s32 type);
+ 
+ /* name resolution functions */
+diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
+index 8d38f70c9726..3cc13aaaed24 100644
+--- a/drivers/staging/exfat/exfat_core.c
++++ b/drivers/staging/exfat/exfat_core.c
+@@ -1140,6 +1140,73 @@ void update_dir_checksum(struct super_block *sb, struct chain_t *p_dir,
+ 	buf_unlock(sb, sector);
+ }
+ 
++static s32 __write_partial_entries_in_entry_set(struct super_block *sb,
++						struct entry_set_cache_t *es,
++						sector_t sec, s32 off, u32 count)
++{
++	s32 num_entries, buf_off = (off - es->offset);
++	u32 remaining_byte_in_sector, copy_entries;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++	u32 clu;
++	u8 *buf, *esbuf = (u8 *)&es->__buf;
++
++	pr_debug("%s entered es %p sec %llu off %d count %d\n",
++		 __func__, es, (unsigned long long)sec, off, count);
++	num_entries = count;
++
++	while (num_entries) {
++		/* white per sector base */
++		remaining_byte_in_sector = (1 << p_bd->sector_size_bits) - off;
++		copy_entries = min_t(s32,
++				     remaining_byte_in_sector >> DENTRY_SIZE_BITS,
++				     num_entries);
++		buf = buf_getblk(sb, sec);
++		if (!buf)
++			goto err_out;
++		pr_debug("es->buf %p buf_off %u\n", esbuf, buf_off);
++		pr_debug("copying %d entries from %p to sector %llu\n",
++			 copy_entries, (esbuf + buf_off),
++			 (unsigned long long)sec);
++		memcpy(buf + off, esbuf + buf_off,
++		       copy_entries << DENTRY_SIZE_BITS);
++		buf_modify(sb, sec);
++		num_entries -= copy_entries;
++
++		if (num_entries) {
++			/* get next sector */
++			if (IS_LAST_SECTOR_IN_CLUSTER(sec)) {
++				clu = GET_CLUSTER_FROM_SECTOR(sec);
++				if (es->alloc_flag == 0x03) {
++					clu++;
++				} else {
++					if (FAT_read(sb, clu, &clu) == -1)
++						goto err_out;
++				}
++				sec = START_SECTOR(clu);
++			} else {
++				sec++;
++			}
++			off = 0;
++			buf_off += copy_entries << DENTRY_SIZE_BITS;
++		}
++	}
++
++	pr_debug("%s exited successfully\n", __func__);
++	return 0;
++err_out:
++	pr_debug("%s failed\n", __func__);
++	return -EINVAL;
++}
++
++/* write back all entries in entry set */
++static s32 write_whole_entry_set(struct super_block *sb, struct entry_set_cache_t *es)
++{
++	return __write_partial_entries_in_entry_set(sb, es, es->sector,
++						    es->offset,
++						    es->num_entries);
++}
++
+ void update_dir_checksum_with_entry_set(struct super_block *sb,
+ 					struct entry_set_cache_t *es)
+ {
+@@ -1421,75 +1488,8 @@ void release_entry_set(struct entry_set_cache_t *es)
+ 	kfree(es);
+ }
+ 
+-static s32 __write_partial_entries_in_entry_set(struct super_block *sb,
+-						struct entry_set_cache_t *es,
+-						sector_t sec, s32 off, u32 count)
+-{
+-	s32 num_entries, buf_off = (off - es->offset);
+-	u32 remaining_byte_in_sector, copy_entries;
+-	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+-	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
+-	u32 clu;
+-	u8 *buf, *esbuf = (u8 *)&es->__buf;
+-
+-	pr_debug("%s entered es %p sec %llu off %d count %d\n",
+-		 __func__, es, (unsigned long long)sec, off, count);
+-	num_entries = count;
+-
+-	while (num_entries) {
+-		/* white per sector base */
+-		remaining_byte_in_sector = (1 << p_bd->sector_size_bits) - off;
+-		copy_entries = min_t(s32,
+-				     remaining_byte_in_sector >> DENTRY_SIZE_BITS,
+-				     num_entries);
+-		buf = buf_getblk(sb, sec);
+-		if (!buf)
+-			goto err_out;
+-		pr_debug("es->buf %p buf_off %u\n", esbuf, buf_off);
+-		pr_debug("copying %d entries from %p to sector %llu\n",
+-			 copy_entries, (esbuf + buf_off),
+-			 (unsigned long long)sec);
+-		memcpy(buf + off, esbuf + buf_off,
+-		       copy_entries << DENTRY_SIZE_BITS);
+-		buf_modify(sb, sec);
+-		num_entries -= copy_entries;
+-
+-		if (num_entries) {
+-			/* get next sector */
+-			if (IS_LAST_SECTOR_IN_CLUSTER(sec)) {
+-				clu = GET_CLUSTER_FROM_SECTOR(sec);
+-				if (es->alloc_flag == 0x03) {
+-					clu++;
+-				} else {
+-					if (FAT_read(sb, clu, &clu) == -1)
+-						goto err_out;
+-				}
+-				sec = START_SECTOR(clu);
+-			} else {
+-				sec++;
+-			}
+-			off = 0;
+-			buf_off += copy_entries << DENTRY_SIZE_BITS;
+-		}
+-	}
+-
+-	pr_debug("%s exited successfully\n", __func__);
+-	return 0;
+-err_out:
+-	pr_debug("%s failed\n", __func__);
+-	return -EINVAL;
+-}
+-
+-/* write back all entries in entry set */
+-s32 write_whole_entry_set(struct super_block *sb, struct entry_set_cache_t *es)
+-{
+-	return __write_partial_entries_in_entry_set(sb, es, es->sector,
+-						    es->offset,
+-						    es->num_entries);
+-}
+-
+ /* search EMPTY CONTINUOUS "num_entries" entries */
+-s32 search_deleted_or_unused_entry(struct super_block *sb,
++static s32 search_deleted_or_unused_entry(struct super_block *sb,
+ 				   struct chain_t *p_dir, s32 num_entries)
+ {
+ 	int i, dentry, num_empty = 0;
+@@ -1665,6 +1665,23 @@ static s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_
+ 	return dentry;
+ }
+ 
++static s32 extract_uni_name_from_name_entry(struct name_dentry_t *ep, u16 *uniname,
++				     s32 order)
++{
++	int i, len = 0;
++
++	for (i = 0; i < 30; i += 2) {
++		*uniname = GET16_A(ep->unicode_0_14 + i);
++		if (*uniname == 0x0)
++			return len;
++		uniname++;
++		len++;
++	}
++
++	*uniname = 0x0;
++	return len;
++}
++
+ /* return values of exfat_find_dir_entry()
+  * >= 0 : return dir entiry position with the name in dir
+  * -1 : (root dir, ".") it is the root dir itself
+@@ -2013,23 +2030,6 @@ static void exfat_get_uni_name_from_ext_entry(struct super_block *sb,
+ 	release_entry_set(es);
+ }
+ 
+-s32 extract_uni_name_from_name_entry(struct name_dentry_t *ep, u16 *uniname,
+-				     s32 order)
+-{
+-	int i, len = 0;
+-
+-	for (i = 0; i < 30; i += 2) {
+-		*uniname = GET16_A(ep->unicode_0_14 + i);
+-		if (*uniname == 0x0)
+-			return len;
+-		uniname++;
+-		len++;
+-	}
+-
+-	*uniname = 0x0;
+-	return len;
+-}
+-
+ static s32 exfat_calc_num_entries(struct uni_name_t *p_uniname)
+ {
+ 	s32 len;

commit a78b34b89bcbb919b912fc8c0e1e964189972d87
+Author: Valdis Kletnieks 
+Date:   Tue Nov 12 16:12:35 2019 -0500
+
+    staging: exfat: Clean up the namespace pollution part 5
+    
+    Some more functions that can be moved and made static
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191112211238.156490-10-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index 48267dd11e9d..c41fc3ec9f29 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -764,9 +764,6 @@ void exfat_chain_cont_cluster(struct super_block *sb, u32 chain, s32 len);
+ /* allocation bitmap management functions */
+ s32 load_alloc_bitmap(struct super_block *sb);
+ void free_alloc_bitmap(struct super_block *sb);
+-s32 set_alloc_bitmap(struct super_block *sb, u32 clu);
+-s32 clr_alloc_bitmap(struct super_block *sb, u32 clu);
+-u32 test_alloc_bitmap(struct super_block *sb, u32 clu);
+ void sync_alloc_bitmap(struct super_block *sb);
+ 
+ /* upcase table management functions */
+diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
+index 24700b251acb..8d38f70c9726 100644
+--- a/drivers/staging/exfat/exfat_core.c
++++ b/drivers/staging/exfat/exfat_core.c
+@@ -156,6 +156,97 @@ static s32 clear_cluster(struct super_block *sb, u32 clu)
+ 	return ret;
+ }
+ 
++static s32 set_alloc_bitmap(struct super_block *sb, u32 clu)
++{
++	int i, b;
++	sector_t sector;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++
++	i = clu >> (p_bd->sector_size_bits + 3);
++	b = clu & ((p_bd->sector_size << 3) - 1);
++
++	sector = START_SECTOR(p_fs->map_clu) + i;
++
++	exfat_bitmap_set((u8 *)p_fs->vol_amap[i]->b_data, b);
++
++	return sector_write(sb, sector, p_fs->vol_amap[i], 0);
++}
++
++static s32 clr_alloc_bitmap(struct super_block *sb, u32 clu)
++{
++	int i, b;
++	sector_t sector;
++#ifdef CONFIG_EXFAT_DISCARD
++	struct exfat_sb_info *sbi = EXFAT_SB(sb);
++	struct exfat_mount_options *opts = &sbi->options;
++	int ret;
++#endif /* CONFIG_EXFAT_DISCARD */
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++
++	i = clu >> (p_bd->sector_size_bits + 3);
++	b = clu & ((p_bd->sector_size << 3) - 1);
++
++	sector = START_SECTOR(p_fs->map_clu) + i;
++
++	exfat_bitmap_clear((u8 *)p_fs->vol_amap[i]->b_data, b);
++
++	return sector_write(sb, sector, p_fs->vol_amap[i], 0);
++
++#ifdef CONFIG_EXFAT_DISCARD
++	if (opts->discard) {
++		ret = sb_issue_discard(sb, START_SECTOR(clu),
++				       (1 << p_fs->sectors_per_clu_bits),
++				       GFP_NOFS, 0);
++		if (ret == -EOPNOTSUPP) {
++			pr_warn("discard not supported by device, disabling");
++			opts->discard = 0;
++		}
++	}
++#endif /* CONFIG_EXFAT_DISCARD */
++}
++
++static u32 test_alloc_bitmap(struct super_block *sb, u32 clu)
++{
++	int i, map_i, map_b;
++	u32 clu_base, clu_free;
++	u8 k, clu_mask;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++
++	clu_base = (clu & ~(0x7)) + 2;
++	clu_mask = (1 << (clu - clu_base + 2)) - 1;
++
++	map_i = clu >> (p_bd->sector_size_bits + 3);
++	map_b = (clu >> 3) & p_bd->sector_size_mask;
++
++	for (i = 2; i < p_fs->num_clusters; i += 8) {
++		k = *(((u8 *)p_fs->vol_amap[map_i]->b_data) + map_b);
++		if (clu_mask > 0) {
++			k |= clu_mask;
++			clu_mask = 0;
++		}
++		if (k < 0xFF) {
++			clu_free = clu_base + free_bit[k];
++			if (clu_free < p_fs->num_clusters)
++				return clu_free;
++		}
++		clu_base += 8;
++
++		if (((++map_b) >= p_bd->sector_size) ||
++		    (clu_base >= p_fs->num_clusters)) {
++			if ((++map_i) >= p_fs->map_sectors) {
++				clu_base = 2;
++				map_i = 0;
++			}
++			map_b = 0;
++		}
++	}
++
++	return CLUSTER_32(~0);
++}
++
+ static s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc,
+ 			struct chain_t *p_chain)
+ {
+@@ -468,97 +559,6 @@ void free_alloc_bitmap(struct super_block *sb)
+ 	p_fs->vol_amap = NULL;
+ }
+ 
+-s32 set_alloc_bitmap(struct super_block *sb, u32 clu)
+-{
+-	int i, b;
+-	sector_t sector;
+-	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+-	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
+-
+-	i = clu >> (p_bd->sector_size_bits + 3);
+-	b = clu & ((p_bd->sector_size << 3) - 1);
+-
+-	sector = START_SECTOR(p_fs->map_clu) + i;
+-
+-	exfat_bitmap_set((u8 *)p_fs->vol_amap[i]->b_data, b);
+-
+-	return sector_write(sb, sector, p_fs->vol_amap[i], 0);
+-}
+-
+-s32 clr_alloc_bitmap(struct super_block *sb, u32 clu)
+-{
+-	int i, b;
+-	sector_t sector;
+-#ifdef CONFIG_EXFAT_DISCARD
+-	struct exfat_sb_info *sbi = EXFAT_SB(sb);
+-	struct exfat_mount_options *opts = &sbi->options;
+-	int ret;
+-#endif /* CONFIG_EXFAT_DISCARD */
+-	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+-	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
+-
+-	i = clu >> (p_bd->sector_size_bits + 3);
+-	b = clu & ((p_bd->sector_size << 3) - 1);
+-
+-	sector = START_SECTOR(p_fs->map_clu) + i;
+-
+-	exfat_bitmap_clear((u8 *)p_fs->vol_amap[i]->b_data, b);
+-
+-	return sector_write(sb, sector, p_fs->vol_amap[i], 0);
+-
+-#ifdef CONFIG_EXFAT_DISCARD
+-	if (opts->discard) {
+-		ret = sb_issue_discard(sb, START_SECTOR(clu),
+-				       (1 << p_fs->sectors_per_clu_bits),
+-				       GFP_NOFS, 0);
+-		if (ret == -EOPNOTSUPP) {
+-			pr_warn("discard not supported by device, disabling");
+-			opts->discard = 0;
+-		}
+-	}
+-#endif /* CONFIG_EXFAT_DISCARD */
+-}
+-
+-u32 test_alloc_bitmap(struct super_block *sb, u32 clu)
+-{
+-	int i, map_i, map_b;
+-	u32 clu_base, clu_free;
+-	u8 k, clu_mask;
+-	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+-	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
+-
+-	clu_base = (clu & ~(0x7)) + 2;
+-	clu_mask = (1 << (clu - clu_base + 2)) - 1;
+-
+-	map_i = clu >> (p_bd->sector_size_bits + 3);
+-	map_b = (clu >> 3) & p_bd->sector_size_mask;
+-
+-	for (i = 2; i < p_fs->num_clusters; i += 8) {
+-		k = *(((u8 *)p_fs->vol_amap[map_i]->b_data) + map_b);
+-		if (clu_mask > 0) {
+-			k |= clu_mask;
+-			clu_mask = 0;
+-		}
+-		if (k < 0xFF) {
+-			clu_free = clu_base + free_bit[k];
+-			if (clu_free < p_fs->num_clusters)
+-				return clu_free;
+-		}
+-		clu_base += 8;
+-
+-		if (((++map_b) >= p_bd->sector_size) ||
+-		    (clu_base >= p_fs->num_clusters)) {
+-			if ((++map_i) >= p_fs->map_sectors) {
+-				clu_base = 2;
+-				map_i = 0;
+-			}
+-			map_b = 0;
+-		}
+-	}
+-
+-	return CLUSTER_32(~0);
+-}
+-
+ void sync_alloc_bitmap(struct super_block *sb)
+ {
+ 	int i;

commit 9435fa8d0601b22d30a6e0d0d78a28aca5e1a7b7
+Author: Valdis Kletnieks 
+Date:   Tue Nov 12 16:12:34 2019 -0500
+
+    staging: exfat: Clean up the namespace pollution part 4
+    
+    Relocating these functions to before first use lets us make them static
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191112211238.156490-9-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index 407dbb017c5f..48267dd11e9d 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -775,10 +775,6 @@ void free_upcase_table(struct super_block *sb);
+ 
+ /* dir entry management functions */
+ struct timestamp_t *tm_current(struct timestamp_t *tm);
+-void init_file_entry(struct file_dentry_t *ep, u32 type);
+-void init_strm_entry(struct strm_dentry_t *ep, u8 flags, u32 start_clu,
+-		     u64 size);
+-void init_name_entry(struct name_dentry_t *ep, u16 *uniname);
+ 
+ struct dentry_t *get_entry_in_dir(struct super_block *sb, struct chain_t *p_dir,
+ 				  s32 entry, sector_t *sector);
+diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
+index 3ea51d12c38d..24700b251acb 100644
+--- a/drivers/staging/exfat/exfat_core.c
++++ b/drivers/staging/exfat/exfat_core.c
+@@ -971,6 +971,45 @@ static void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *t
+ 	}
+ }
+ 
++static void init_file_entry(struct file_dentry_t *ep, u32 type)
++{
++	struct timestamp_t tm, *tp;
++
++	exfat_set_entry_type((struct dentry_t *)ep, type);
++
++	tp = tm_current(&tm);
++	exfat_set_entry_time((struct dentry_t *)ep, tp, TM_CREATE);
++	exfat_set_entry_time((struct dentry_t *)ep, tp, TM_MODIFY);
++	exfat_set_entry_time((struct dentry_t *)ep, tp, TM_ACCESS);
++	ep->create_time_ms = 0;
++	ep->modify_time_ms = 0;
++	ep->access_time_ms = 0;
++}
++
++static void init_strm_entry(struct strm_dentry_t *ep, u8 flags, u32 start_clu, u64 size)
++{
++	exfat_set_entry_type((struct dentry_t *)ep, TYPE_STREAM);
++	ep->flags = flags;
++	SET32_A(ep->start_clu, start_clu);
++	SET64_A(ep->valid_size, size);
++	SET64_A(ep->size, size);
++}
++
++static void init_name_entry(struct name_dentry_t *ep, u16 *uniname)
++{
++	int i;
++
++	exfat_set_entry_type((struct dentry_t *)ep, TYPE_EXTEND);
++	ep->flags = 0x0;
++
++	for (i = 0; i < 30; i++, i++) {
++		SET16_A(ep->unicode_0_14 + i, *uniname);
++		if (*uniname == 0x0)
++			break;
++		uniname++;
++	}
++}
++
+ static s32 exfat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+ 			 s32 entry, u32 type, u32 start_clu, u64 size)
+ {
+@@ -1047,45 +1086,6 @@ static s32 exfat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir,
+ 	return 0;
+ }
+ 
+-void init_file_entry(struct file_dentry_t *ep, u32 type)
+-{
+-	struct timestamp_t tm, *tp;
+-
+-	exfat_set_entry_type((struct dentry_t *)ep, type);
+-
+-	tp = tm_current(&tm);
+-	exfat_set_entry_time((struct dentry_t *)ep, tp, TM_CREATE);
+-	exfat_set_entry_time((struct dentry_t *)ep, tp, TM_MODIFY);
+-	exfat_set_entry_time((struct dentry_t *)ep, tp, TM_ACCESS);
+-	ep->create_time_ms = 0;
+-	ep->modify_time_ms = 0;
+-	ep->access_time_ms = 0;
+-}
+-
+-void init_strm_entry(struct strm_dentry_t *ep, u8 flags, u32 start_clu, u64 size)
+-{
+-	exfat_set_entry_type((struct dentry_t *)ep, TYPE_STREAM);
+-	ep->flags = flags;
+-	SET32_A(ep->start_clu, start_clu);
+-	SET64_A(ep->valid_size, size);
+-	SET64_A(ep->size, size);
+-}
+-
+-void init_name_entry(struct name_dentry_t *ep, u16 *uniname)
+-{
+-	int i;
+-
+-	exfat_set_entry_type((struct dentry_t *)ep, TYPE_EXTEND);
+-	ep->flags = 0x0;
+-
+-	for (i = 0; i < 30; i++, i++) {
+-		SET16_A(ep->unicode_0_14 + i, *uniname);
+-		if (*uniname == 0x0)
+-			break;
+-		uniname++;
+-	}
+-}
+-
+ static void exfat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+ 			    s32 entry, s32 order, s32 num_entries)
+ {

commit 388cd66808d52cd761c2885defd22f7f52ce4c52
+Author: Valdis Kletnieks 
+Date:   Tue Nov 12 16:12:33 2019 -0500
+
+    staging: exfat: Clean up the namespace pollution part 3
+    
+    These functions are only used in the local file, make them static
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191112211238.156490-8-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index 5044523ccb97..407dbb017c5f 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -758,8 +758,6 @@ void fs_set_vol_flags(struct super_block *sb, u32 new_flag);
+ void fs_error(struct super_block *sb);
+ 
+ /* cluster management functions */
+-s32 clear_cluster(struct super_block *sb, u32 clu);
+-u32 find_last_cluster(struct super_block *sb, struct chain_t *p_chain);
+ s32 count_num_clusters(struct super_block *sb, struct chain_t *dir);
+ void exfat_chain_cont_cluster(struct super_block *sb, u32 chain, s32 len);
+ 
+@@ -782,8 +780,6 @@ void init_strm_entry(struct strm_dentry_t *ep, u8 flags, u32 start_clu,
+ 		     u64 size);
+ void init_name_entry(struct name_dentry_t *ep, u16 *uniname);
+ 
+-s32 find_location(struct super_block *sb, struct chain_t *p_dir, s32 entry,
+-		  sector_t *sector, s32 *offset);
+ struct dentry_t *get_entry_in_dir(struct super_block *sb, struct chain_t *p_dir,
+ 				  s32 entry, sector_t *sector);
+ struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb,
+@@ -797,8 +793,6 @@ s32 write_partial_entries_in_entry_set(struct super_block *sb,
+ 				       struct dentry_t *ep, u32 count);
+ s32 search_deleted_or_unused_entry(struct super_block *sb,
+ 				   struct chain_t *p_dir, s32 num_entries);
+-s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir,
+-		     s32 num_entries);
+ s32 count_dos_name_entries(struct super_block *sb, struct chain_t *p_dir,
+ 			   u32 type);
+ void update_dir_checksum(struct super_block *sb, struct chain_t *p_dir,
+diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
+index 5a01fc25f31d..3ea51d12c38d 100644
+--- a/drivers/staging/exfat/exfat_core.c
++++ b/drivers/staging/exfat/exfat_core.c
+@@ -125,7 +125,7 @@ void fs_error(struct super_block *sb)
+  *  Cluster Management Functions
+  */
+ 
+-s32 clear_cluster(struct super_block *sb, u32 clu)
++static s32 clear_cluster(struct super_block *sb, u32 clu)
+ {
+ 	sector_t s, n;
+ 	s32 ret = 0;
+@@ -294,7 +294,7 @@ static void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
+ 		p_fs->used_clusters -= num_clusters;
+ }
+ 
+-u32 find_last_cluster(struct super_block *sb, struct chain_t *p_chain)
++static u32 find_last_cluster(struct super_block *sb, struct chain_t *p_chain)
+ {
+ 	u32 clu, next;
+ 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+@@ -1186,7 +1186,7 @@ static s32 _walk_fat_chain(struct super_block *sb, struct chain_t *p_dir,
+ 	return 0;
+ }
+ 
+-s32 find_location(struct super_block *sb, struct chain_t *p_dir, s32 entry,
++static s32 find_location(struct super_block *sb, struct chain_t *p_dir, s32 entry,
+ 		  sector_t *sector, s32 *offset)
+ {
+ 	s32 off, ret;
+@@ -1583,7 +1583,7 @@ s32 search_deleted_or_unused_entry(struct super_block *sb,
+ 	return -1;
+ }
+ 
+-s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_entries)
++static s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_entries)
+ {
+ 	s32 ret, dentry;
+ 	u32 last_clu;

commit ed5916c1e8db99eeab6cbbf7cba150a5cee90c0f
+Author: Valdis Kletnieks 
+Date:   Tue Nov 12 16:12:32 2019 -0500
+
+    staging: exfat: Clean up the namespace pollution part 2
+    
+    Rename all the bdev_* to exfat_bdev_*
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191112211238.156490-7-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index 5efba3d4259b..5044523ccb97 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -842,13 +842,13 @@ int multi_sector_read(struct super_block *sb, sector_t sec,
+ int multi_sector_write(struct super_block *sb, sector_t sec,
+ 		       struct buffer_head *bh, s32 num_secs, bool sync);
+ 
+-void bdev_open(struct super_block *sb);
+-void bdev_close(struct super_block *sb);
+-int bdev_read(struct super_block *sb, sector_t secno,
++void exfat_bdev_open(struct super_block *sb);
++void exfat_bdev_close(struct super_block *sb);
++int exfat_bdev_read(struct super_block *sb, sector_t secno,
+ 	      struct buffer_head **bh, u32 num_secs, bool read);
+-int bdev_write(struct super_block *sb, sector_t secno,
++int exfat_bdev_write(struct super_block *sb, sector_t secno,
+ 	       struct buffer_head *bh, u32 num_secs, bool sync);
+-int bdev_sync(struct super_block *sb);
++int exfat_bdev_sync(struct super_block *sb);
+ 
+ extern const u8 uni_upcase[];
+ #endif /* _EXFAT_H */
+diff --git a/drivers/staging/exfat/exfat_blkdev.c b/drivers/staging/exfat/exfat_blkdev.c
+index 0abae041f632..7bcd98b13109 100644
+--- a/drivers/staging/exfat/exfat_blkdev.c
++++ b/drivers/staging/exfat/exfat_blkdev.c
+@@ -8,7 +8,7 @@
+ #include 
+ #include "exfat.h"
+ 
+-void bdev_open(struct super_block *sb)
++void exfat_bdev_open(struct super_block *sb)
+ {
+ 	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
+ 
+@@ -23,14 +23,14 @@ void bdev_open(struct super_block *sb)
+ 	p_bd->opened = true;
+ }
+ 
+-void bdev_close(struct super_block *sb)
++void exfat_bdev_close(struct super_block *sb)
+ {
+ 	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
+ 
+ 	p_bd->opened = false;
+ }
+ 
+-int bdev_read(struct super_block *sb, sector_t secno, struct buffer_head **bh,
++int exfat_bdev_read(struct super_block *sb, sector_t secno, struct buffer_head **bh,
+ 	      u32 num_secs, bool read)
+ {
+ 	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
+@@ -65,7 +65,7 @@ int bdev_read(struct super_block *sb, sector_t secno, struct buffer_head **bh,
+ 	return -EIO;
+ }
+ 
+-int bdev_write(struct super_block *sb, sector_t secno, struct buffer_head *bh,
++int exfat_bdev_write(struct super_block *sb, sector_t secno, struct buffer_head *bh,
+ 	       u32 num_secs, bool sync)
+ {
+ 	s32 count;
+@@ -118,7 +118,7 @@ int bdev_write(struct super_block *sb, sector_t secno, struct buffer_head *bh,
+ 	return -EIO;
+ }
+ 
+-int bdev_sync(struct super_block *sb)
++int exfat_bdev_sync(struct super_block *sb)
+ {
+ 	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
+ #ifdef CONFIG_EXFAT_KERNEL_DEBUG
+diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
+index 2dc07e81bad0..5a01fc25f31d 100644
+--- a/drivers/staging/exfat/exfat_core.c
++++ b/drivers/staging/exfat/exfat_core.c
+@@ -2569,7 +2569,7 @@ int sector_read(struct super_block *sb, sector_t sec, struct buffer_head **bh,
+ 	}
+ 
+ 	if (!p_fs->dev_ejected) {
+-		ret = bdev_read(sb, sec, bh, 1, read);
++		ret = exfat_bdev_read(sb, sec, bh, 1, read);
+ 		if (ret != 0)
+ 			p_fs->dev_ejected = 1;
+ 	}
+@@ -2598,7 +2598,7 @@ int sector_write(struct super_block *sb, sector_t sec, struct buffer_head *bh,
+ 	}
+ 
+ 	if (!p_fs->dev_ejected) {
+-		ret = bdev_write(sb, sec, bh, 1, sync);
++		ret = exfat_bdev_write(sb, sec, bh, 1, sync);
+ 		if (ret != 0)
+ 			p_fs->dev_ejected = 1;
+ 	}
+@@ -2621,7 +2621,7 @@ int multi_sector_read(struct super_block *sb, sector_t sec,
+ 	}
+ 
+ 	if (!p_fs->dev_ejected) {
+-		ret = bdev_read(sb, sec, bh, num_secs, read);
++		ret = exfat_bdev_read(sb, sec, bh, num_secs, read);
+ 		if (ret != 0)
+ 			p_fs->dev_ejected = 1;
+ 	}
+@@ -2649,7 +2649,7 @@ int multi_sector_write(struct super_block *sb, sector_t sec,
+ 	}
+ 
+ 	if (!p_fs->dev_ejected) {
+-		ret = bdev_write(sb, sec, bh, num_secs, sync);
++		ret = exfat_bdev_write(sb, sec, bh, num_secs, sync);
+ 		if (ret != 0)
+ 			p_fs->dev_ejected = 1;
+ 	}
+diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
+index 259cb5a7bd81..3828150bca3f 100644
+--- a/drivers/staging/exfat/exfat_super.c
++++ b/drivers/staging/exfat/exfat_super.c
+@@ -289,7 +289,7 @@ static DEFINE_MUTEX(z_mutex);
+ static inline void fs_sync(struct super_block *sb, bool do_sync)
+ {
+ 	if (do_sync)
+-		bdev_sync(sb);
++		exfat_bdev_sync(sb);
+ }
+ 
+ /*
+@@ -361,7 +361,7 @@ static int ffsMountVol(struct super_block *sb)
+ 	p_fs->dev_ejected = 0;
+ 
+ 	/* open the block device */
+-	bdev_open(sb);
++	exfat_bdev_open(sb);
+ 
+ 	if (p_bd->sector_size < sb->s_blocksize) {
+ 		printk(KERN_INFO "EXFAT: maont failed - sector size %d less than blocksize %ld\n",
+@@ -385,7 +385,7 @@ static int ffsMountVol(struct super_block *sb)
+ 	/* check the validity of PBR */
+ 	if (GET16_A(p_pbr->signature) != PBR_SIGNATURE) {
+ 		brelse(tmp_bh);
+-		bdev_close(sb);
++		exfat_bdev_close(sb);
+ 		ret = -EFSCORRUPTED;
+ 		goto out;
+ 	}
+@@ -407,26 +407,26 @@ static int ffsMountVol(struct super_block *sb)
+ 	brelse(tmp_bh);
+ 
+ 	if (ret) {
+-		bdev_close(sb);
++		exfat_bdev_close(sb);
+ 		goto out;
+ 	}
+ 
+ 	ret = load_alloc_bitmap(sb);
+ 	if (ret) {
+-		bdev_close(sb);
++		exfat_bdev_close(sb);
+ 		goto out;
+ 	}
+ 	ret = load_upcase_table(sb);
+ 	if (ret) {
+ 		free_alloc_bitmap(sb);
+-		bdev_close(sb);
++		exfat_bdev_close(sb);
+ 		goto out;
+ 	}
+ 
+ 	if (p_fs->dev_ejected) {
+ 		free_upcase_table(sb);
+ 		free_alloc_bitmap(sb);
+-		bdev_close(sb);
++		exfat_bdev_close(sb);
+ 		ret = -EIO;
+ 		goto out;
+ 	}
+@@ -461,7 +461,7 @@ static int ffsUmountVol(struct super_block *sb)
+ 	buf_release_all(sb);
+ 
+ 	/* close the block device */
+-	bdev_close(sb);
++	exfat_bdev_close(sb);
+ 
+ 	if (p_fs->dev_ejected) {
+ 		pr_info("[EXFAT] unmounted with media errors. Device is already ejected.\n");

commit 19e2bfe6ed135ed45d6adb6860181cad49dbb90e
+Author: Valdis Kletnieks 
+Date:   Tue Nov 12 16:12:31 2019 -0500
+
+    staging: exfat: Clean up the namespace pollution part 1
+    
+    Everything referenced in the struct fs_func exfat_fs_func is located
+    in that same .c file.  Make them static and remove from exfat.h
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191112211238.156490-6-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index 470e409ef536..5efba3d4259b 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -759,13 +759,8 @@ void fs_error(struct super_block *sb);
+ 
+ /* cluster management functions */
+ s32 clear_cluster(struct super_block *sb, u32 clu);
+-s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc,
+-			struct chain_t *p_chain);
+-void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
+-			s32 do_relse);
+ u32 find_last_cluster(struct super_block *sb, struct chain_t *p_chain);
+ s32 count_num_clusters(struct super_block *sb, struct chain_t *dir);
+-s32 exfat_count_used_clusters(struct super_block *sb);
+ void exfat_chain_cont_cluster(struct super_block *sb, u32 chain, s32 len);
+ 
+ /* allocation bitmap management functions */
+@@ -781,29 +776,11 @@ s32 load_upcase_table(struct super_block *sb);
+ void free_upcase_table(struct super_block *sb);
+ 
+ /* dir entry management functions */
+-u32 exfat_get_entry_type(struct dentry_t *p_entry);
+-void exfat_set_entry_type(struct dentry_t *p_entry, u32 type);
+-u32 exfat_get_entry_attr(struct dentry_t *p_entry);
+-void exfat_set_entry_attr(struct dentry_t *p_entry, u32 attr);
+-u8 exfat_get_entry_flag(struct dentry_t *p_entry);
+-void exfat_set_entry_flag(struct dentry_t *p_entry, u8 flag);
+-u32 exfat_get_entry_clu0(struct dentry_t *p_entry);
+-void exfat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu);
+-u64 exfat_get_entry_size(struct dentry_t *p_entry);
+-void exfat_set_entry_size(struct dentry_t *p_entry, u64 size);
+ struct timestamp_t *tm_current(struct timestamp_t *tm);
+-void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
+-			  u8 mode);
+-void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
+-			  u8 mode);
+-s32 exfat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+-			 s32 entry, u32 type, u32 start_clu, u64 size);
+ void init_file_entry(struct file_dentry_t *ep, u32 type);
+ void init_strm_entry(struct strm_dentry_t *ep, u8 flags, u32 start_clu,
+ 		     u64 size);
+ void init_name_entry(struct name_dentry_t *ep, u16 *uniname);
+-void exfat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+-			    s32 entry, s32 order, s32 num_entries);
+ 
+ s32 find_location(struct super_block *sb, struct chain_t *p_dir, s32 entry,
+ 		  sector_t *sector, s32 *offset);
+@@ -822,11 +799,6 @@ s32 search_deleted_or_unused_entry(struct super_block *sb,
+ 				   struct chain_t *p_dir, s32 num_entries);
+ s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir,
+ 		     s32 num_entries);
+-s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+-			 struct uni_name_t *p_uniname, s32 num_entries,
+-			 struct dos_name_t *p_dosname, u32 type);
+-s32 exfat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir,
+-			    s32 entry, struct dentry_t *p_entry);
+ s32 count_dos_name_entries(struct super_block *sb, struct chain_t *p_dir,
+ 			   u32 type);
+ void update_dir_checksum(struct super_block *sb, struct chain_t *p_dir,
+@@ -839,12 +811,8 @@ bool is_dir_empty(struct super_block *sb, struct chain_t *p_dir);
+ s32 get_num_entries_and_dos_name(struct super_block *sb, struct chain_t *p_dir,
+ 				 struct uni_name_t *p_uniname, s32 *entries,
+ 				 struct dos_name_t *p_dosname);
+-void exfat_get_uni_name_from_ext_entry(struct super_block *sb,
+-				       struct chain_t *p_dir, s32 entry,
+-				       u16 *uniname);
+ s32 extract_uni_name_from_name_entry(struct name_dentry_t *ep,
+ 				     u16 *uniname, s32 order);
+-s32 exfat_calc_num_entries(struct uni_name_t *p_uniname);
+ u16 calc_checksum_2byte(void *data, s32 len, u16 chksum, s32 type);
+ 
+ /* name resolution functions */
+diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
+index c3454e883e3c..2dc07e81bad0 100644
+--- a/drivers/staging/exfat/exfat_core.c
++++ b/drivers/staging/exfat/exfat_core.c
+@@ -156,7 +156,7 @@ s32 clear_cluster(struct super_block *sb, u32 clu)
+ 	return ret;
+ }
+ 
+-s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc,
++static s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc,
+ 			struct chain_t *p_chain)
+ {
+ 	s32 num_clusters = 0;
+@@ -235,7 +235,7 @@ s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc,
+ 	return num_clusters;
+ }
+ 
+-void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
++static void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
+ 			s32 do_relse)
+ {
+ 	s32 num_clusters = 0;
+@@ -341,7 +341,7 @@ s32 count_num_clusters(struct super_block *sb, struct chain_t *p_chain)
+ 	return count;
+ }
+ 
+-s32 exfat_count_used_clusters(struct super_block *sb)
++static s32 exfat_count_used_clusters(struct super_block *sb)
+ {
+ 	int i, map_i, map_b, count = 0;
+ 	u8 k;
+@@ -785,7 +785,7 @@ void free_upcase_table(struct super_block *sb)
+  *  Directory Entry Management Functions
+  */
+ 
+-u32 exfat_get_entry_type(struct dentry_t *p_entry)
++static u32 exfat_get_entry_type(struct dentry_t *p_entry)
+ {
+ 	struct file_dentry_t *ep = (struct file_dentry_t *)p_entry;
+ 
+@@ -830,7 +830,7 @@ u32 exfat_get_entry_type(struct dentry_t *p_entry)
+ 	return TYPE_BENIGN_SEC;
+ }
+ 
+-void exfat_set_entry_type(struct dentry_t *p_entry, u32 type)
++static void exfat_set_entry_type(struct dentry_t *p_entry, u32 type)
+ {
+ 	struct file_dentry_t *ep = (struct file_dentry_t *)p_entry;
+ 
+@@ -860,56 +860,56 @@ void exfat_set_entry_type(struct dentry_t *p_entry, u32 type)
+ 	}
+ }
+ 
+-u32 exfat_get_entry_attr(struct dentry_t *p_entry)
++static u32 exfat_get_entry_attr(struct dentry_t *p_entry)
+ {
+ 	struct file_dentry_t *ep = (struct file_dentry_t *)p_entry;
+ 
+ 	return (u32)GET16_A(ep->attr);
+ }
+ 
+-void exfat_set_entry_attr(struct dentry_t *p_entry, u32 attr)
++static void exfat_set_entry_attr(struct dentry_t *p_entry, u32 attr)
+ {
+ 	struct file_dentry_t *ep = (struct file_dentry_t *)p_entry;
+ 
+ 	SET16_A(ep->attr, (u16)attr);
+ }
+ 
+-u8 exfat_get_entry_flag(struct dentry_t *p_entry)
++static u8 exfat_get_entry_flag(struct dentry_t *p_entry)
+ {
+ 	struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry;
+ 
+ 	return ep->flags;
+ }
+ 
+-void exfat_set_entry_flag(struct dentry_t *p_entry, u8 flags)
++static void exfat_set_entry_flag(struct dentry_t *p_entry, u8 flags)
+ {
+ 	struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry;
+ 
+ 	ep->flags = flags;
+ }
+ 
+-u32 exfat_get_entry_clu0(struct dentry_t *p_entry)
++static u32 exfat_get_entry_clu0(struct dentry_t *p_entry)
+ {
+ 	struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry;
+ 
+ 	return GET32_A(ep->start_clu);
+ }
+ 
+-void exfat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu)
++static void exfat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu)
+ {
+ 	struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry;
+ 
+ 	SET32_A(ep->start_clu, start_clu);
+ }
+ 
+-u64 exfat_get_entry_size(struct dentry_t *p_entry)
++static u64 exfat_get_entry_size(struct dentry_t *p_entry)
+ {
+ 	struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry;
+ 
+ 	return GET64_A(ep->valid_size);
+ }
+ 
+-void exfat_set_entry_size(struct dentry_t *p_entry, u64 size)
++static void exfat_set_entry_size(struct dentry_t *p_entry, u64 size)
+ {
+ 	struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry;
+ 
+@@ -917,7 +917,7 @@ void exfat_set_entry_size(struct dentry_t *p_entry, u64 size)
+ 	SET64_A(ep->size, size);
+ }
+ 
+-void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
++static void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
+ 			  u8 mode)
+ {
+ 	u16 t = 0x00, d = 0x21;
+@@ -946,7 +946,7 @@ void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
+ 	tp->year = (d >> 9);
+ }
+ 
+-void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
++static void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
+ 			  u8 mode)
+ {
+ 	u16 t, d;
+@@ -971,7 +971,7 @@ void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
+ 	}
+ }
+ 
+-s32 exfat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir,
++static s32 exfat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+ 			 s32 entry, u32 type, u32 start_clu, u64 size)
+ {
+ 	sector_t sector;
+@@ -1086,7 +1086,7 @@ void init_name_entry(struct name_dentry_t *ep, u16 *uniname)
+ 	}
+ }
+ 
+-void exfat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir,
++static void exfat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+ 			    s32 entry, s32 order, s32 num_entries)
+ {
+ 	int i;
+@@ -1670,7 +1670,7 @@ s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_entries
+  * -1 : (root dir, ".") it is the root dir itself
+  * -2 : entry with the name does not exist
+  */
+-s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir,
++static s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+ 			 struct uni_name_t *p_uniname, s32 num_entries,
+ 			 struct dos_name_t *p_dosname, u32 type)
+ {
+@@ -1813,7 +1813,7 @@ s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+ 	return -2;
+ }
+ 
+-s32 exfat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir,
++static s32 exfat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir,
+ 			    s32 entry, struct dentry_t *p_entry)
+ {
+ 	int i, count = 0;
+@@ -1976,7 +1976,7 @@ s32 get_num_entries_and_dos_name(struct super_block *sb, struct chain_t *p_dir,
+ 	return 0;
+ }
+ 
+-void exfat_get_uni_name_from_ext_entry(struct super_block *sb,
++static void exfat_get_uni_name_from_ext_entry(struct super_block *sb,
+ 				       struct chain_t *p_dir, s32 entry,
+ 				       u16 *uniname)
+ {
+@@ -2030,7 +2030,7 @@ s32 extract_uni_name_from_name_entry(struct name_dentry_t *ep, u16 *uniname,
+ 	return len;
+ }
+ 
+-s32 exfat_calc_num_entries(struct uni_name_t *p_uniname)
++static s32 exfat_calc_num_entries(struct uni_name_t *p_uniname)
+ {
+ 	s32 len;
+ 

commit 35a829c1b797d1a927bf54b6a958e154eb248026
+Author: Valdis Kletnieks 
+Date:   Tue Nov 12 16:12:30 2019 -0500
+
+    staging: exfat: Remove FAT/VFAT mount support, part 4
+    
+    The code simplification from the previous patch rendered a few more
+    routines unreferenced, so heave them over the side as well.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191112211238.156490-5-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index 9ea865f607af..470e409ef536 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -729,14 +729,7 @@ static inline struct exfat_inode_info *EXFAT_I(struct inode *inode)
+ 
+ /* NLS management function */
+ u16 nls_upper(struct super_block *sb, u16 a);
+-int nls_dosname_cmp(struct super_block *sb, u8 *a, u8 *b);
+ int nls_uniname_cmp(struct super_block *sb, u16 *a, u16 *b);
+-void nls_uniname_to_dosname(struct super_block *sb,
+-			    struct dos_name_t *p_dosname,
+-			    struct uni_name_t *p_uniname, bool *p_lossy);
+-void nls_dosname_to_uniname(struct super_block *sb,
+-			    struct uni_name_t *p_uniname,
+-			    struct dos_name_t *p_dosname);
+ void nls_uniname_to_cstring(struct super_block *sb, u8 *p_cstring,
+ 			    struct uni_name_t *p_uniname);
+ void nls_cstring_to_uniname(struct super_block *sb,
+@@ -805,10 +798,6 @@ void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
+ 			  u8 mode);
+ s32 exfat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+ 			 s32 entry, u32 type, u32 start_clu, u64 size);
+-s32 exfat_init_ext_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+-			     s32 entry, s32 num_entries,
+-			     struct uni_name_t *p_uniname,
+-		struct dos_name_t *p_dosname);
+ void init_file_entry(struct file_dentry_t *ep, u32 type);
+ void init_strm_entry(struct strm_dentry_t *ep, u8 flags, u32 start_clu,
+ 		     u64 size);
+@@ -850,25 +839,17 @@ bool is_dir_empty(struct super_block *sb, struct chain_t *p_dir);
+ s32 get_num_entries_and_dos_name(struct super_block *sb, struct chain_t *p_dir,
+ 				 struct uni_name_t *p_uniname, s32 *entries,
+ 				 struct dos_name_t *p_dosname);
+-void get_uni_name_from_dos_entry(struct super_block *sb,
+-				 struct dos_dentry_t *ep,
+-				 struct uni_name_t *p_uniname, u8 mode);
+ void exfat_get_uni_name_from_ext_entry(struct super_block *sb,
+ 				       struct chain_t *p_dir, s32 entry,
+ 				       u16 *uniname);
+ s32 extract_uni_name_from_name_entry(struct name_dentry_t *ep,
+ 				     u16 *uniname, s32 order);
+-s32 fat_generate_dos_name(struct super_block *sb, struct chain_t *p_dir,
+-			  struct dos_name_t *p_dosname);
+-void fat_attach_count_to_dos_name(u8 *dosname, s32 count);
+-s32 fat_calc_num_entries(struct uni_name_t *p_uniname);
+ s32 exfat_calc_num_entries(struct uni_name_t *p_uniname);
+ u16 calc_checksum_2byte(void *data, s32 len, u16 chksum, s32 type);
+ 
+ /* name resolution functions */
+ s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir,
+ 		 struct uni_name_t *p_uniname);
+-s32 resolve_name(u8 *name, u8 **arg);
+ 
+ /* file operation functions */
+ s32 exfat_mount(struct super_block *sb, struct pbr_sector_t *p_pbr);
+diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
+index 77b826dfdeda..c3454e883e3c 100644
+--- a/drivers/staging/exfat/exfat_core.c
++++ b/drivers/staging/exfat/exfat_core.c
+@@ -1976,21 +1976,6 @@ s32 get_num_entries_and_dos_name(struct super_block *sb, struct chain_t *p_dir,
+ 	return 0;
+ }
+ 
+-void get_uni_name_from_dos_entry(struct super_block *sb,
+-				 struct dos_dentry_t *ep,
+-				 struct uni_name_t *p_uniname, u8 mode)
+-{
+-	struct dos_name_t dos_name;
+-
+-	if (mode == 0x0)
+-		dos_name.name_case = 0x0;
+-	else
+-		dos_name.name_case = ep->lcase;
+-
+-	memcpy(dos_name.name, ep->name, DOS_NAME_LENGTH);
+-	nls_dosname_to_uniname(sb, p_uniname, &dos_name);
+-}
+-
+ void exfat_get_uni_name_from_ext_entry(struct super_block *sb,
+ 				       struct chain_t *p_dir, s32 entry,
+ 				       u16 *uniname)
+@@ -2045,128 +2030,6 @@ s32 extract_uni_name_from_name_entry(struct name_dentry_t *ep, u16 *uniname,
+ 	return len;
+ }
+ 
+-s32 fat_generate_dos_name(struct super_block *sb, struct chain_t *p_dir,
+-			  struct dos_name_t *p_dosname)
+-{
+-	int i, j, count = 0;
+-	bool count_begin = false;
+-	s32 dentries_per_clu;
+-	u32 type;
+-	u8 bmap[128/* 1 ~ 1023 */];
+-	struct chain_t clu;
+-	struct dos_dentry_t *ep;
+-	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+-
+-	memset(bmap, 0, sizeof(bmap));
+-	exfat_bitmap_set(bmap, 0);
+-
+-	if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */
+-		dentries_per_clu = p_fs->dentries_in_root;
+-	else
+-		dentries_per_clu = p_fs->dentries_per_clu;
+-
+-	clu.dir = p_dir->dir;
+-	clu.flags = p_dir->flags;
+-
+-	while (clu.dir != CLUSTER_32(~0)) {
+-		if (p_fs->dev_ejected)
+-			break;
+-
+-		for (i = 0; i < dentries_per_clu; i++) {
+-			ep = (struct dos_dentry_t *)get_entry_in_dir(sb, &clu,
+-								     i, NULL);
+-			if (!ep)
+-				return -ENOENT;
+-
+-			type = p_fs->fs_func->get_entry_type((struct dentry_t *)
+-							     ep);
+-
+-			if (type == TYPE_UNUSED)
+-				break;
+-			if ((type != TYPE_FILE) && (type != TYPE_DIR))
+-				continue;
+-
+-			count = 0;
+-			count_begin = false;
+-
+-			for (j = 0; j < 8; j++) {
+-				if (ep->name[j] == ' ')
+-					break;
+-
+-				if (ep->name[j] == '~') {
+-					count_begin = true;
+-				} else if (count_begin) {
+-					if ((ep->name[j] >= '0') &&
+-					    (ep->name[j] <= '9')) {
+-						count = count * 10 +
+-							(ep->name[j] - '0');
+-					} else {
+-						count = 0;
+-						count_begin = false;
+-					}
+-				}
+-			}
+-
+-			if ((count > 0) && (count < 1024))
+-				exfat_bitmap_set(bmap, count);
+-		}
+-
+-		if (p_dir->dir == CLUSTER_32(0))
+-			break; /* FAT16 root_dir */
+-
+-		if (FAT_read(sb, clu.dir, &clu.dir) != 0)
+-			return -EIO;
+-	}
+-
+-	count = 0;
+-	for (i = 0; i < 128; i++) {
+-		if (bmap[i] != 0xFF) {
+-			for (j = 0; j < 8; j++) {
+-				if (exfat_bitmap_test(&bmap[i], j) == 0) {
+-					count = (i << 3) + j;
+-					break;
+-				}
+-			}
+-			if (count != 0)
+-				break;
+-		}
+-	}
+-
+-	if ((count == 0) || (count >= 1024))
+-		return -EEXIST;
+-	fat_attach_count_to_dos_name(p_dosname->name, count);
+-
+-	/* Now dos_name has DOS~????.EXT */
+-	return 0;
+-}
+-
+-void fat_attach_count_to_dos_name(u8 *dosname, s32 count)
+-{
+-	int i, j, length;
+-	char str_count[6];
+-
+-	snprintf(str_count, sizeof(str_count), "~%d", count);
+-	length = strlen(str_count);
+-
+-	i = 0;
+-	j = 0;
+-	while (j <= (8 - length)) {
+-		i = j;
+-		if (dosname[j] == ' ')
+-			break;
+-		if (dosname[j] & 0x80)
+-			j += 2;
+-		else
+-			j++;
+-	}
+-
+-	for (j = 0; j < length; i++, j++)
+-		dosname[i] = (u8)str_count[j];
+-
+-	if (i == 7)
+-		dosname[7] = ' ';
+-}
+-
+ s32 exfat_calc_num_entries(struct uni_name_t *p_uniname)
+ {
+ 	s32 len;
+diff --git a/drivers/staging/exfat/exfat_nls.c b/drivers/staging/exfat/exfat_nls.c
+index a5c4b68925fb..91e8b0c4dce7 100644
+--- a/drivers/staging/exfat/exfat_nls.c
++++ b/drivers/staging/exfat/exfat_nls.c
+@@ -7,13 +7,6 @@
+ #include 
+ #include "exfat.h"
+ 
+-static u16 bad_dos_chars[] = {
+-	/* + , ; = [ ] */
+-	0x002B, 0x002C, 0x003B, 0x003D, 0x005B, 0x005D,
+-	0xFF0B, 0xFF0C, 0xFF1B, 0xFF1D, 0xFF3B, 0xFF3D,
+-	0
+-};
+-
+ static u16 bad_uni_chars[] = {
+ 	/* " * / : < > ? \ | */
+ 	0x0022,         0x002A, 0x002F, 0x003A,
+@@ -96,11 +89,6 @@ static u16 *nls_wstrchr(u16 *str, u16 wchar)
+ 	return NULL;
+ }
+ 
+-int nls_dosname_cmp(struct super_block *sb, u8 *a, u8 *b)
+-{
+-	return strncmp(a, b, DOS_NAME_LENGTH);
+-}
+-
+ int nls_uniname_cmp(struct super_block *sb, u16 *a, u16 *b)
+ {
+ 	int i;
+@@ -114,186 +102,6 @@ int nls_uniname_cmp(struct super_block *sb, u16 *a, u16 *b)
+ 	return 0;
+ }
+ 
+-void nls_uniname_to_dosname(struct super_block *sb,
+-			    struct dos_name_t *p_dosname,
+-			    struct uni_name_t *p_uniname, bool *p_lossy)
+-{
+-	int i, j, len;
+-	bool lossy = false;
+-	u8 buf[MAX_CHARSET_SIZE];
+-	u8 lower = 0, upper = 0;
+-	u8 *dosname = p_dosname->name;
+-	u16 *uniname = p_uniname->name;
+-	u16 *p, *last_period;
+-	struct nls_table *nls = EXFAT_SB(sb)->nls_disk;
+-
+-	for (i = 0; i < DOS_NAME_LENGTH; i++)
+-		*(dosname + i) = ' ';
+-
+-	if (!nls_uniname_cmp(sb, uniname, (u16 *)UNI_CUR_DIR_NAME)) {
+-		*(dosname) = '.';
+-		p_dosname->name_case = 0x0;
+-		if (p_lossy)
+-			*p_lossy = false;
+-		return;
+-	}
+-
+-	if (!nls_uniname_cmp(sb, uniname, (u16 *)UNI_PAR_DIR_NAME)) {
+-		*(dosname) = '.';
+-		*(dosname + 1) = '.';
+-		p_dosname->name_case = 0x0;
+-		if (p_lossy)
+-			*p_lossy = false;
+-		return;
+-	}
+-
+-	/* search for the last embedded period */
+-	last_period = NULL;
+-	for (p = uniname; *p; p++) {
+-		if (*p == (u16)'.')
+-			last_period = p;
+-	}
+-
+-	i = 0;
+-	while (i < DOS_NAME_LENGTH) {
+-		if (i == 8) {
+-			if (!last_period)
+-				break;
+-
+-			if (uniname <= last_period) {
+-				if (uniname < last_period)
+-					lossy = true;
+-				uniname = last_period + 1;
+-			}
+-		}
+-
+-		if (*uniname == (u16)'\0') {
+-			break;
+-		} else if (*uniname == (u16)' ') {
+-			lossy = true;
+-		} else if (*uniname == (u16)'.') {
+-			if (uniname < last_period)
+-				lossy = true;
+-			else
+-				i = 8;
+-		} else if (nls_wstrchr(bad_dos_chars, *uniname)) {
+-			lossy = true;
+-			*(dosname + i) = '_';
+-			i++;
+-		} else {
+-			len = convert_uni_to_ch(nls, buf, *uniname, &lossy);
+-
+-			if (len > 1) {
+-				if ((i >= 8) && ((i + len) > DOS_NAME_LENGTH))
+-					break;
+-
+-				if ((i < 8) && ((i + len) > 8)) {
+-					i = 8;
+-					continue;
+-				}
+-
+-				lower = 0xFF;
+-
+-				for (j = 0; j < len; j++, i++)
+-					*(dosname + i) = *(buf + j);
+-			} else { /* len == 1 */
+-				if ((*buf >= 'a') && (*buf <= 'z')) {
+-					*(dosname + i) = *buf - ('a' - 'A');
+-
+-					if (i < 8)
+-						lower |= 0x08;
+-					else
+-						lower |= 0x10;
+-				} else if ((*buf >= 'A') && (*buf <= 'Z')) {
+-					*(dosname + i) = *buf;
+-
+-					if (i < 8)
+-						upper |= 0x08;
+-					else
+-						upper |= 0x10;
+-				} else {
+-					*(dosname + i) = *buf;
+-				}
+-				i++;
+-			}
+-		}
+-
+-		uniname++;
+-	}
+-
+-	if (*dosname == 0xE5)
+-		*dosname = 0x05;
+-
+-	if (*uniname != 0x0)
+-		lossy = true;
+-
+-	if (upper & lower)
+-		p_dosname->name_case = 0xFF;
+-	else
+-		p_dosname->name_case = lower;
+-
+-	if (p_lossy)
+-		*p_lossy = lossy;
+-}
+-
+-void nls_dosname_to_uniname(struct super_block *sb,
+-			    struct uni_name_t *p_uniname,
+-			    struct dos_name_t *p_dosname)
+-{
+-	int i = 0, j, n = 0;
+-	u8 buf[DOS_NAME_LENGTH + 2];
+-	u8 *dosname = p_dosname->name;
+-	u16 *uniname = p_uniname->name;
+-	struct nls_table *nls = EXFAT_SB(sb)->nls_disk;
+-
+-	if (*dosname == 0x05) {
+-		*buf = 0xE5;
+-		i++;
+-		n++;
+-	}
+-
+-	for (; i < 8; i++, n++) {
+-		if (*(dosname + i) == ' ')
+-			break;
+-
+-		if ((*(dosname + i) >= 'A') && (*(dosname + i) <= 'Z') &&
+-		    (p_dosname->name_case & 0x08))
+-			*(buf + n) = *(dosname + i) + ('a' - 'A');
+-		else
+-			*(buf + n) = *(dosname + i);
+-	}
+-	if (*(dosname + 8) != ' ') {
+-		*(buf + n) = '.';
+-		n++;
+-	}
+-
+-	for (i = 8; i < DOS_NAME_LENGTH; i++, n++) {
+-		if (*(dosname + i) == ' ')
+-			break;
+-
+-		if ((*(dosname + i) >= 'A') && (*(dosname + i) <= 'Z') &&
+-		    (p_dosname->name_case & 0x10))
+-			*(buf + n) = *(dosname + i) + ('a' - 'A');
+-		else
+-			*(buf + n) = *(dosname + i);
+-	}
+-	*(buf + n) = '\0';
+-
+-	i = 0;
+-	j = 0;
+-	while (j < (MAX_NAME_LENGTH - 1)) {
+-		if (*(buf + i) == '\0')
+-			break;
+-
+-		i += convert_ch_to_uni(nls, uniname, (buf + i), NULL);
+-
+-		uniname++;
+-		j++;
+-	}
+-
+-	*uniname = (u16)'\0';
+-}
+-
+ void nls_uniname_to_cstring(struct super_block *sb, u8 *p_cstring,
+ 			    struct uni_name_t *p_uniname)
+ {

commit 2a17b09fdecd580c88a5b80fd7ccd33bee576e4d
+Author: Valdis Kletnieks 
+Date:   Tue Nov 12 16:12:29 2019 -0500
+
+    staging: exfat: Remove FAT/VFAT mount support, part 3
+    
+    In this patch, we straighten out most of the cases where the
+    code was testing 'p_fs->vol_type == EXFAT' and '!= EXFAT'
+    
+    There's still some ?: ops and a few places where the code
+    is doing checks for '.' and '..' that require looking at,
+    but those are future patches
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191112211238.156490-4-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat_cache.c b/drivers/staging/exfat/exfat_cache.c
+index 28a67f8139ea..1d344c5f3e15 100644
+--- a/drivers/staging/exfat/exfat_cache.c
++++ b/drivers/staging/exfat/exfat_cache.c
+@@ -202,107 +202,22 @@ static int __FAT_read(struct super_block *sb, u32 loc, u32 *content)
+ 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+ 	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
+ 
+-	if (p_fs->vol_type == FAT12) {
+-		sec = p_fs->FAT1_start_sector +
+-			((loc + (loc >> 1)) >> p_bd->sector_size_bits);
+-		off = (loc + (loc >> 1)) & p_bd->sector_size_mask;
+-
+-		if (off == (p_bd->sector_size - 1)) {
+-			fat_sector = FAT_getblk(sb, sec);
+-			if (!fat_sector)
+-				return -1;
+-
+-			_content = (u32)fat_sector[off];
+-
+-			fat_sector = FAT_getblk(sb, ++sec);
+-			if (!fat_sector)
+-				return -1;
+-
+-			_content |= (u32)fat_sector[0] << 8;
+-		} else {
+-			fat_sector = FAT_getblk(sb, sec);
+-			if (!fat_sector)
+-				return -1;
+-
+-			fat_entry = &fat_sector[off];
+-			_content = GET16(fat_entry);
+-		}
+-
+-		if (loc & 1)
+-			_content >>= 4;
+-
+-		_content &= 0x00000FFF;
+-
+-		if (_content >= CLUSTER_16(0x0FF8)) {
+-			*content = CLUSTER_32(~0);
+-			return 0;
+-		}
+-		*content = CLUSTER_32(_content);
+-		return 0;
+-	} else if (p_fs->vol_type == FAT16) {
+-		sec = p_fs->FAT1_start_sector +
+-			(loc >> (p_bd->sector_size_bits - 1));
+-		off = (loc << 1) & p_bd->sector_size_mask;
+-
+-		fat_sector = FAT_getblk(sb, sec);
+-		if (!fat_sector)
+-			return -1;
+-
+-		fat_entry = &fat_sector[off];
+-
+-		_content = GET16_A(fat_entry);
+-
+-		_content &= 0x0000FFFF;
+-
+-		if (_content >= CLUSTER_16(0xFFF8)) {
+-			*content = CLUSTER_32(~0);
+-			return 0;
+-		}
+-		*content = CLUSTER_32(_content);
+-		return 0;
+-	} else if (p_fs->vol_type == FAT32) {
+-		sec = p_fs->FAT1_start_sector +
+-			(loc >> (p_bd->sector_size_bits - 2));
+-		off = (loc << 2) & p_bd->sector_size_mask;
+-
+-		fat_sector = FAT_getblk(sb, sec);
+-		if (!fat_sector)
+-			return -1;
++	sec = p_fs->FAT1_start_sector +
++		(loc >> (p_bd->sector_size_bits - 2));
++	off = (loc << 2) & p_bd->sector_size_mask;
+ 
+-		fat_entry = &fat_sector[off];
++	fat_sector = FAT_getblk(sb, sec);
++	if (!fat_sector)
++		return -1;
+ 
+-		_content = GET32_A(fat_entry);
++	fat_entry = &fat_sector[off];
++	_content = GET32_A(fat_entry);
+ 
+-		_content &= 0x0FFFFFFF;
+-
+-		if (_content >= CLUSTER_32(0x0FFFFFF8)) {
+-			*content = CLUSTER_32(~0);
+-			return 0;
+-		}
+-		*content = CLUSTER_32(_content);
+-		return 0;
+-	} else if (p_fs->vol_type == EXFAT) {
+-		sec = p_fs->FAT1_start_sector +
+-			(loc >> (p_bd->sector_size_bits - 2));
+-		off = (loc << 2) & p_bd->sector_size_mask;
+-
+-		fat_sector = FAT_getblk(sb, sec);
+-		if (!fat_sector)
+-			return -1;
+-
+-		fat_entry = &fat_sector[off];
+-		_content = GET32_A(fat_entry);
+-
+-		if (_content >= CLUSTER_32(0xFFFFFFF8)) {
+-			*content = CLUSTER_32(~0);
+-			return 0;
+-		}
+-		*content = CLUSTER_32(_content);
++	if (_content >= CLUSTER_32(0xFFFFFFF8)) {
++		*content = CLUSTER_32(~0);
+ 		return 0;
+ 	}
+-
+-	/* Unknown volume type, throw in the towel and go home */
+-	*content = CLUSTER_32(~0);
++	*content = CLUSTER_32(_content);
+ 	return 0;
+ }
+ 
+@@ -330,101 +245,17 @@ static s32 __FAT_write(struct super_block *sb, u32 loc, u32 content)
+ 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+ 	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
+ 
+-	if (p_fs->vol_type == FAT12) {
+-		content &= 0x00000FFF;
++	sec = p_fs->FAT1_start_sector + (loc >>
++					 (p_bd->sector_size_bits - 2));
++	off = (loc << 2) & p_bd->sector_size_mask;
+ 
+-		sec = p_fs->FAT1_start_sector +
+-			((loc + (loc >> 1)) >> p_bd->sector_size_bits);
+-		off = (loc + (loc >> 1)) & p_bd->sector_size_mask;
++	fat_sector = FAT_getblk(sb, sec);
++	if (!fat_sector)
++		return -1;
+ 
+-		fat_sector = FAT_getblk(sb, sec);
+-		if (!fat_sector)
+-			return -1;
++	fat_entry = &fat_sector[off];
+ 
+-		if (loc & 1) { /* odd */
+-			content <<= 4;
+-
+-			if (off == (p_bd->sector_size - 1)) {
+-				fat_sector[off] = (u8)(content |
+-						       (fat_sector[off] &
+-							0x0F));
+-				FAT_modify(sb, sec);
+-
+-				fat_sector = FAT_getblk(sb, ++sec);
+-				if (!fat_sector)
+-					return -1;
+-
+-				fat_sector[0] = (u8)(content >> 8);
+-			} else {
+-				fat_entry = &fat_sector[off];
+-				content |= GET16(fat_entry) & 0x000F;
+-
+-				SET16(fat_entry, content);
+-			}
+-		} else { /* even */
+-			fat_sector[off] = (u8)(content);
+-
+-			if (off == (p_bd->sector_size - 1)) {
+-				fat_sector[off] = (u8)(content);
+-				FAT_modify(sb, sec);
+-
+-				fat_sector = FAT_getblk(sb, ++sec);
+-				if (!fat_sector)
+-					return -1;
+-				fat_sector[0] = (u8)((fat_sector[0] & 0xF0) |
+-						     (content >> 8));
+-			} else {
+-				fat_entry = &fat_sector[off];
+-				content |= GET16(fat_entry) & 0xF000;
+-
+-				SET16(fat_entry, content);
+-			}
+-		}
+-	}
+-
+-	else if (p_fs->vol_type == FAT16) {
+-		content &= 0x0000FFFF;
+-
+-		sec = p_fs->FAT1_start_sector + (loc >>
+-						 (p_bd->sector_size_bits - 1));
+-		off = (loc << 1) & p_bd->sector_size_mask;
+-
+-		fat_sector = FAT_getblk(sb, sec);
+-		if (!fat_sector)
+-			return -1;
+-
+-		fat_entry = &fat_sector[off];
+-
+-		SET16_A(fat_entry, content);
+-	} else if (p_fs->vol_type == FAT32) {
+-		content &= 0x0FFFFFFF;
+-
+-		sec = p_fs->FAT1_start_sector + (loc >>
+-						 (p_bd->sector_size_bits - 2));
+-		off = (loc << 2) & p_bd->sector_size_mask;
+-
+-		fat_sector = FAT_getblk(sb, sec);
+-		if (!fat_sector)
+-			return -1;
+-
+-		fat_entry = &fat_sector[off];
+-
+-		content |= GET32_A(fat_entry) & 0xF0000000;
+-
+-		SET32_A(fat_entry, content);
+-	} else { /* p_fs->vol_type == EXFAT */
+-		sec = p_fs->FAT1_start_sector + (loc >>
+-						 (p_bd->sector_size_bits - 2));
+-		off = (loc << 2) & p_bd->sector_size_mask;
+-
+-		fat_sector = FAT_getblk(sb, sec);
+-		if (!fat_sector)
+-			return -1;
+-
+-		fat_entry = &fat_sector[off];
+-
+-		SET32_A(fat_entry, content);
+-	}
++	SET32_A(fat_entry, content);
+ 
+ 	FAT_modify(sb, sec);
+ 	return 0;
+diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
+index ed9e4521ec04..77b826dfdeda 100644
+--- a/drivers/staging/exfat/exfat_core.c
++++ b/drivers/staging/exfat/exfat_core.c
+@@ -20,15 +20,6 @@ static void __set_sb_dirty(struct super_block *sb)
+ 
+ static u8 name_buf[MAX_PATH_LENGTH * MAX_CHARSET_SIZE];
+ 
+-static char *reserved_names[] = {
+-	"AUX     ", "CON     ", "NUL     ", "PRN     ",
+-	"COM1    ", "COM2    ", "COM3    ", "COM4    ",
+-	"COM5    ", "COM6    ", "COM7    ", "COM8    ", "COM9    ",
+-	"LPT1    ", "LPT2    ", "LPT3    ", "LPT4    ",
+-	"LPT5    ", "LPT6    ", "LPT7    ", "LPT8    ", "LPT9    ",
+-	NULL
+-};
+-
+ static u8 free_bit[] = {
+ 	0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, /*   0 ~  19 */
+ 	0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, /*  20 ~  39 */
+@@ -99,25 +90,23 @@ void fs_set_vol_flags(struct super_block *sb, u32 new_flag)
+ 
+ 	p_fs->vol_flag = new_flag;
+ 
+-	if (p_fs->vol_type == EXFAT) {
+-		if (!p_fs->pbr_bh) {
+-			if (sector_read(sb, p_fs->PBR_sector,
+-					&p_fs->pbr_bh, 1) != 0)
+-				return;
+-		}
++	if (!p_fs->pbr_bh) {
++		if (sector_read(sb, p_fs->PBR_sector,
++				&p_fs->pbr_bh, 1) != 0)
++			return;
++	}
+ 
+-		p_pbr = (struct pbr_sector_t *)p_fs->pbr_bh->b_data;
+-		p_bpb = (struct bpbex_t *)p_pbr->bpb;
+-		SET16(p_bpb->vol_flags, (u16)new_flag);
++	p_pbr = (struct pbr_sector_t *)p_fs->pbr_bh->b_data;
++	p_bpb = (struct bpbex_t *)p_pbr->bpb;
++	SET16(p_bpb->vol_flags, (u16)new_flag);
+ 
+-		/* XXX duyoung
+-		 * what can we do here? (cuz fs_set_vol_flags() is void)
+-		 */
+-		if ((new_flag == VOL_DIRTY) && (!buffer_dirty(p_fs->pbr_bh)))
+-			sector_write(sb, p_fs->PBR_sector, p_fs->pbr_bh, 1);
+-		else
+-			sector_write(sb, p_fs->PBR_sector, p_fs->pbr_bh, 0);
+-	}
++	/* XXX duyoung
++	 * what can we do here? (cuz fs_set_vol_flags() is void)
++	 */
++	if ((new_flag == VOL_DIRTY) && (!buffer_dirty(p_fs->pbr_bh)))
++		sector_write(sb, p_fs->PBR_sector, p_fs->pbr_bh, 1);
++	else
++		sector_write(sb, p_fs->PBR_sector, p_fs->pbr_bh, 0);
+ }
+ 
+ void fs_error(struct super_block *sb)
+@@ -1613,10 +1602,8 @@ s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_entries
+ 		if (p_fs->dev_ejected)
+ 			break;
+ 
+-		if (p_fs->vol_type == EXFAT) {
+-			if (p_dir->dir != p_fs->root_dir)
+-				size = i_size_read(inode);
+-		}
++		if (p_dir->dir != p_fs->root_dir)
++			size = i_size_read(inode);
+ 
+ 		last_clu = find_last_cluster(sb, p_dir);
+ 		clu.dir = last_clu + 1;
+@@ -1653,21 +1640,19 @@ s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_entries
+ 		p_dir->size++;
+ 
+ 		/* (3) update the directory entry */
+-		if (p_fs->vol_type == EXFAT) {
+-			if (p_dir->dir != p_fs->root_dir) {
+-				size += p_fs->cluster_size;
+-
+-				ep = get_entry_in_dir(sb, &fid->dir,
+-						      fid->entry + 1, §or);
+-				if (!ep)
+-					return -ENOENT;
+-				p_fs->fs_func->set_entry_size(ep, size);
+-				p_fs->fs_func->set_entry_flag(ep, p_dir->flags);
+-				buf_modify(sb, sector);
+-
+-				update_dir_checksum(sb, &fid->dir,
+-						    fid->entry);
+-			}
++		if (p_dir->dir != p_fs->root_dir) {
++			size += p_fs->cluster_size;
++
++			ep = get_entry_in_dir(sb, &fid->dir,
++					      fid->entry + 1, §or);
++			if (!ep)
++				return -ENOENT;
++			p_fs->fs_func->set_entry_size(ep, size);
++			p_fs->fs_func->set_entry_flag(ep, p_dir->flags);
++			buf_modify(sb, sector);
++
++			update_dir_checksum(sb, &fid->dir,
++					    fid->entry);
+ 		}
+ 
+ 		i_size_write(inode, i_size_read(inode) + p_fs->cluster_size);
+@@ -1979,36 +1964,13 @@ s32 get_num_entries_and_dos_name(struct super_block *sb, struct chain_t *p_dir,
+ 				 struct uni_name_t *p_uniname, s32 *entries,
+ 				 struct dos_name_t *p_dosname)
+ {
+-	s32 ret, num_entries;
+-	bool lossy = false;
+-	char **r;
++	s32 num_entries;
+ 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+ 
+ 	num_entries = p_fs->fs_func->calc_num_entries(p_uniname);
+ 	if (num_entries == 0)
+ 		return -EINVAL;
+ 
+-	if (p_fs->vol_type != EXFAT) {
+-		nls_uniname_to_dosname(sb, p_dosname, p_uniname, &lossy);
+-
+-		if (lossy) {
+-			ret = fat_generate_dos_name(sb, p_dir, p_dosname);
+-			if (ret)
+-				return ret;
+-		} else {
+-			for (r = reserved_names; *r; r++) {
+-				if (!strncmp((void *)p_dosname->name, *r, 8))
+-					return -EINVAL;
+-			}
+-
+-			if (p_dosname->name_case != 0xFF)
+-				num_entries = 1;
+-		}
+-
+-		if (num_entries > 1)
+-			p_dosname->name_case = 0x0;
+-	}
+-
+ 	*entries = num_entries;
+ 
+ 	return 0;
+@@ -2392,7 +2354,7 @@ s32 create_dir(struct inode *inode, struct chain_t *p_dir,
+ 	s32 ret, dentry, num_entries;
+ 	u64 size;
+ 	struct chain_t clu;
+-	struct dos_name_t dos_name, dot_name;
++	struct dos_name_t dos_name;
+ 	struct super_block *sb = inode->i_sb;
+ 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+ 	struct fs_func *fs_func = p_fs->fs_func;
+@@ -2422,45 +2384,7 @@ s32 create_dir(struct inode *inode, struct chain_t *p_dir,
+ 	if (ret != 0)
+ 		return ret;
+ 
+-	if (p_fs->vol_type == EXFAT) {
+-		size = p_fs->cluster_size;
+-	} else {
+-		size = 0;
+-
+-		/* initialize the . and .. entry
+-		 * Information for . points to itself
+-		 * Information for .. points to parent dir
+-		 */
+-
+-		dot_name.name_case = 0x0;
+-		memcpy(dot_name.name, DOS_CUR_DIR_NAME, DOS_NAME_LENGTH);
+-
+-		ret = fs_func->init_dir_entry(sb, &clu, 0, TYPE_DIR, clu.dir,
+-					      0);
+-		if (ret != 0)
+-			return ret;
+-
+-		ret = fs_func->init_ext_entry(sb, &clu, 0, 1, NULL, &dot_name);
+-		if (ret != 0)
+-			return ret;
+-
+-		memcpy(dot_name.name, DOS_PAR_DIR_NAME, DOS_NAME_LENGTH);
+-
+-		if (p_dir->dir == p_fs->root_dir)
+-			ret = fs_func->init_dir_entry(sb, &clu, 1, TYPE_DIR,
+-						      CLUSTER_32(0), 0);
+-		else
+-			ret = fs_func->init_dir_entry(sb, &clu, 1, TYPE_DIR,
+-						      p_dir->dir, 0);
+-
+-		if (ret != 0)
+-			return ret;
+-
+-		ret = p_fs->fs_func->init_ext_entry(sb, &clu, 1, 1, NULL,
+-						    &dot_name);
+-		if (ret != 0)
+-			return ret;
+-	}
++	size = p_fs->cluster_size;
+ 
+ 	/* (2) update the directory entry */
+ 	/* make sub-dir entry in parent directory */
+@@ -2626,23 +2550,21 @@ s32 rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry,
+ 		buf_modify(sb, sector_new);
+ 		buf_unlock(sb, sector_old);
+ 
+-		if (p_fs->vol_type == EXFAT) {
+-			epold = get_entry_in_dir(sb, p_dir, oldentry + 1,
+-						 §or_old);
+-			buf_lock(sb, sector_old);
+-			epnew = get_entry_in_dir(sb, p_dir, newentry + 1,
+-						 §or_new);
+-
+-			if (!epold || !epnew) {
+-				buf_unlock(sb, sector_old);
+-				return -ENOENT;
+-			}
++		epold = get_entry_in_dir(sb, p_dir, oldentry + 1,
++					 §or_old);
++		buf_lock(sb, sector_old);
++		epnew = get_entry_in_dir(sb, p_dir, newentry + 1,
++					 §or_new);
+ 
+-			memcpy((void *)epnew, (void *)epold, DENTRY_SIZE);
+-			buf_modify(sb, sector_new);
++		if (!epold || !epnew) {
+ 			buf_unlock(sb, sector_old);
++			return -ENOENT;
+ 		}
+ 
++		memcpy((void *)epnew, (void *)epold, DENTRY_SIZE);
++		buf_modify(sb, sector_new);
++		buf_unlock(sb, sector_old);
++
+ 		ret = fs_func->init_ext_entry(sb, p_dir, newentry,
+ 					      num_new_entries, p_uniname,
+ 					      &dos_name);
+@@ -2681,7 +2603,6 @@ s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
+ {
+ 	s32 ret, newentry, num_new_entries, num_old_entries;
+ 	sector_t sector_mov, sector_new;
+-	struct chain_t clu;
+ 	struct dos_name_t dos_name;
+ 	struct dentry_t *epmov, *epnew;
+ 	struct super_block *sb = inode->i_sb;
+@@ -2736,36 +2657,20 @@ s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
+ 	buf_modify(sb, sector_new);
+ 	buf_unlock(sb, sector_mov);
+ 
+-	if (p_fs->vol_type == EXFAT) {
+-		epmov = get_entry_in_dir(sb, p_olddir, oldentry + 1,
+-					 §or_mov);
+-		buf_lock(sb, sector_mov);
+-		epnew = get_entry_in_dir(sb, p_newdir, newentry + 1,
+-					 §or_new);
+-		if (!epmov || !epnew) {
+-			buf_unlock(sb, sector_mov);
+-			return -ENOENT;
+-		}
+-
+-		memcpy((void *)epnew, (void *)epmov, DENTRY_SIZE);
+-		buf_modify(sb, sector_new);
++	epmov = get_entry_in_dir(sb, p_olddir, oldentry + 1,
++				 §or_mov);
++	buf_lock(sb, sector_mov);
++	epnew = get_entry_in_dir(sb, p_newdir, newentry + 1,
++				 §or_new);
++	if (!epmov || !epnew) {
+ 		buf_unlock(sb, sector_mov);
+-	} else if (fs_func->get_entry_type(epnew) == TYPE_DIR) {
+-		/* change ".." pointer to new parent dir */
+-		clu.dir = fs_func->get_entry_clu0(epnew);
+-		clu.flags = 0x01;
+-
+-		epnew = get_entry_in_dir(sb, &clu, 1, §or_new);
+-		if (!epnew)
+-			return -ENOENT;
+-
+-		if (p_newdir->dir == p_fs->root_dir)
+-			fs_func->set_entry_clu0(epnew, CLUSTER_32(0));
+-		else
+-			fs_func->set_entry_clu0(epnew, p_newdir->dir);
+-		buf_modify(sb, sector_new);
++		return -ENOENT;
+ 	}
+ 
++	memcpy((void *)epnew, (void *)epmov, DENTRY_SIZE);
++	buf_modify(sb, sector_new);
++	buf_unlock(sb, sector_mov);
++
+ 	ret = fs_func->init_ext_entry(sb, p_newdir, newentry, num_new_entries,
+ 				      p_uniname, &dos_name);
+ 	if (ret != 0)
+diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
+index 0ebf342122da..259cb5a7bd81 100644
+--- a/drivers/staging/exfat/exfat_super.c
++++ b/drivers/staging/exfat/exfat_super.c
+@@ -411,25 +411,21 @@ static int ffsMountVol(struct super_block *sb)
+ 		goto out;
+ 	}
+ 
+-	if (p_fs->vol_type == EXFAT) {
+-		ret = load_alloc_bitmap(sb);
+-		if (ret) {
+-			bdev_close(sb);
+-			goto out;
+-		}
+-		ret = load_upcase_table(sb);
+-		if (ret) {
+-			free_alloc_bitmap(sb);
+-			bdev_close(sb);
+-			goto out;
+-		}
++	ret = load_alloc_bitmap(sb);
++	if (ret) {
++		bdev_close(sb);
++		goto out;
++	}
++	ret = load_upcase_table(sb);
++	if (ret) {
++		free_alloc_bitmap(sb);
++		bdev_close(sb);
++		goto out;
+ 	}
+ 
+ 	if (p_fs->dev_ejected) {
+-		if (p_fs->vol_type == EXFAT) {
+-			free_upcase_table(sb);
+-			free_alloc_bitmap(sb);
+-		}
++		free_upcase_table(sb);
++		free_alloc_bitmap(sb);
+ 		bdev_close(sb);
+ 		ret = -EIO;
+ 		goto out;
+@@ -458,10 +454,8 @@ static int ffsUmountVol(struct super_block *sb)
+ 	fs_sync(sb, true);
+ 	fs_set_vol_flags(sb, VOL_CLEAN);
+ 
+-	if (p_fs->vol_type == EXFAT) {
+-		free_upcase_table(sb);
+-		free_alloc_bitmap(sb);
+-	}
++	free_upcase_table(sb);
++	free_alloc_bitmap(sb);
+ 
+ 	FAT_release_all(sb);
+ 	buf_release_all(sb);
+@@ -593,22 +587,13 @@ static int ffsLookupFile(struct inode *inode, char *path, struct file_id_t *fid)
+ 		fid->size = 0;
+ 		fid->start_clu = p_fs->root_dir;
+ 	} else {
+-		if (p_fs->vol_type == EXFAT) {
+-			es = get_entry_set_in_dir(sb, &dir, dentry,
+-						  ES_2_ENTRIES, &ep);
+-			if (!es) {
+-				ret =  -ENOENT;
+-				goto out;
+-			}
+-			ep2 = ep + 1;
+-		} else {
+-			ep = get_entry_in_dir(sb, &dir, dentry, NULL);
+-			if (!ep) {
+-				ret =  -ENOENT;
+-				goto out;
+-			}
+-			ep2 = ep;
++		es = get_entry_set_in_dir(sb, &dir, dentry,
++					  ES_2_ENTRIES, &ep);
++		if (!es) {
++			ret =  -ENOENT;
++			goto out;
+ 		}
++		ep2 = ep + 1;
+ 
+ 		fid->type = p_fs->fs_func->get_entry_type(ep);
+ 		fid->rwoffset = 0;
+@@ -624,8 +609,7 @@ static int ffsLookupFile(struct inode *inode, char *path, struct file_id_t *fid)
+ 			fid->start_clu = p_fs->fs_func->get_entry_clu0(ep2);
+ 		}
+ 
+-		if (p_fs->vol_type == EXFAT)
+-			release_entry_set(es);
++		release_entry_set(es);
+ 	}
+ 
+ 	if (p_fs->dev_ejected)
+@@ -812,7 +796,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
+ 	s32 num_clusters, num_alloc, num_alloced = (s32)~0;
+ 	int ret = 0;
+ 	u32 clu, last_clu;
+-	sector_t LogSector, sector = 0;
++	sector_t LogSector;
+ 	u64 oneblkwrite, write_bytes;
+ 	struct chain_t new_clu;
+ 	struct timestamp_t tm;
+@@ -1001,25 +985,15 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
+ 	brelse(tmp_bh);
+ 
+ 	/* (3) update the direcoty entry */
+-	if (p_fs->vol_type == EXFAT) {
+-		es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
+-					  ES_ALL_ENTRIES, &ep);
+-		if (!es)
+-			goto err_out;
+-		ep2 = ep + 1;
+-	} else {
+-		ep = get_entry_in_dir(sb, &fid->dir, fid->entry, §or);
+-		if (!ep)
+-			goto err_out;
+-		ep2 = ep;
+-	}
++	es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
++				  ES_ALL_ENTRIES, &ep);
++	if (!es)
++		goto err_out;
++	ep2 = ep + 1;
+ 
+ 	p_fs->fs_func->set_entry_time(ep, tm_current(&tm), TM_MODIFY);
+ 	p_fs->fs_func->set_entry_attr(ep, fid->attr);
+ 
+-	if (p_fs->vol_type != EXFAT)
+-		buf_modify(sb, sector);
+-
+ 	if (modified) {
+ 		if (p_fs->fs_func->get_entry_flag(ep2) != fid->flags)
+ 			p_fs->fs_func->set_entry_flag(ep2, fid->flags);
+@@ -1029,15 +1003,10 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
+ 
+ 		if (p_fs->fs_func->get_entry_clu0(ep2) != fid->start_clu)
+ 			p_fs->fs_func->set_entry_clu0(ep2, fid->start_clu);
+-
+-		if (p_fs->vol_type != EXFAT)
+-			buf_modify(sb, sector);
+ 	}
+ 
+-	if (p_fs->vol_type == EXFAT) {
+-		update_dir_checksum_with_entry_set(sb, es);
+-		release_entry_set(es);
+-	}
++	update_dir_checksum_with_entry_set(sb, es);
++	release_entry_set(es);
+ 
+ #ifndef CONFIG_EXFAT_DELAYED_SYNC
+ 	fs_sync(sb, true);
+@@ -1067,7 +1036,6 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size)
+ 	s32 num_clusters;
+ 	u32 last_clu = CLUSTER_32(0);
+ 	int ret = 0;
+-	sector_t sector = 0;
+ 	struct chain_t clu;
+ 	struct timestamp_t tm;
+ 	struct dentry_t *ep, *ep2;
+@@ -1132,22 +1100,13 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size)
+ 	}
+ 
+ 	/* (1) update the directory entry */
+-	if (p_fs->vol_type == EXFAT) {
+-		es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
+-					  ES_ALL_ENTRIES, &ep);
+-		if (!es) {
+-			ret = -ENOENT;
+-			goto out;
+-			}
+-		ep2 = ep + 1;
+-	} else {
+-		ep = get_entry_in_dir(sb, &fid->dir, fid->entry, §or);
+-		if (!ep) {
+-			ret = -ENOENT;
+-			goto out;
++	es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
++				  ES_ALL_ENTRIES, &ep);
++	if (!es) {
++		ret = -ENOENT;
++		goto out;
+ 		}
+-		ep2 = ep;
+-	}
++	ep2 = ep + 1;
+ 
+ 	p_fs->fs_func->set_entry_time(ep, tm_current(&tm), TM_MODIFY);
+ 	p_fs->fs_func->set_entry_attr(ep, fid->attr);
+@@ -1158,12 +1117,8 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size)
+ 		p_fs->fs_func->set_entry_clu0(ep2, CLUSTER_32(0));
+ 	}
+ 
+-	if (p_fs->vol_type != EXFAT) {
+-		buf_modify(sb, sector);
+-	} else {
+-		update_dir_checksum_with_entry_set(sb, es);
+-		release_entry_set(es);
+-	}
++	update_dir_checksum_with_entry_set(sb, es);
++	release_entry_set(es);
+ 
+ 	/* (2) cut off from the FAT chain */
+ 	if (last_clu != CLUSTER_32(0)) {
+@@ -1436,19 +1391,11 @@ static int ffsSetAttr(struct inode *inode, u32 attr)
+ 	mutex_lock(&p_fs->v_mutex);
+ 
+ 	/* get the directory entry of given file */
+-	if (p_fs->vol_type == EXFAT) {
+-		es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
+-					  ES_ALL_ENTRIES, &ep);
+-		if (!es) {
+-			ret = -ENOENT;
+-			goto out;
+-		}
+-	} else {
+-		ep = get_entry_in_dir(sb, &fid->dir, fid->entry, §or);
+-		if (!ep) {
+-			ret = -ENOENT;
+-			goto out;
+-		}
++	es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
++				  ES_ALL_ENTRIES, &ep);
++	if (!es) {
++		ret = -ENOENT;
++		goto out;
+ 	}
+ 
+ 	type = p_fs->fs_func->get_entry_type(ep);
+@@ -1460,8 +1407,7 @@ static int ffsSetAttr(struct inode *inode, u32 attr)
+ 		else
+ 			ret = -EINVAL;
+ 
+-		if (p_fs->vol_type == EXFAT)
+-			release_entry_set(es);
++		release_entry_set(es);
+ 		goto out;
+ 	}
+ 
+@@ -1471,12 +1417,8 @@ static int ffsSetAttr(struct inode *inode, u32 attr)
+ 	fid->attr = attr;
+ 	p_fs->fs_func->set_entry_attr(ep, attr);
+ 
+-	if (p_fs->vol_type != EXFAT) {
+-		buf_modify(sb, sector);
+-	} else {
+-		update_dir_checksum_with_entry_set(sb, es);
+-		release_entry_set(es);
+-	}
++	update_dir_checksum_with_entry_set(sb, es);
++	release_entry_set(es);
+ 
+ #ifndef CONFIG_EXFAT_DELAYED_SYNC
+ 	fs_sync(sb, true);
+@@ -1495,7 +1437,6 @@ static int ffsSetAttr(struct inode *inode, u32 attr)
+ 
+ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info)
+ {
+-	sector_t sector = 0;
+ 	s32 count;
+ 	int ret = 0;
+ 	struct chain_t dir;
+@@ -1552,23 +1493,13 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info)
+ 	}
+ 
+ 	/* get the directory entry of given file or directory */
+-	if (p_fs->vol_type == EXFAT) {
+-		es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
+-					  ES_2_ENTRIES, &ep);
+-		if (!es) {
+-			ret = -ENOENT;
+-			goto out;
+-		}
+-		ep2 = ep + 1;
+-	} else {
+-		ep = get_entry_in_dir(sb, &fid->dir, fid->entry, §or);
+-		if (!ep) {
+-			ret = -ENOENT;
+-			goto out;
+-		}
+-		ep2 = ep;
+-		buf_lock(sb, sector);
++	es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
++				  ES_2_ENTRIES, &ep);
++	if (!es) {
++		ret = -ENOENT;
++		goto out;
+ 	}
++	ep2 = ep + 1;
+ 
+ 	/* set FILE_INFO structure using the acquired struct dentry_t */
+ 	info->Attr = p_fs->fs_func->get_entry_attr(ep);
+@@ -1599,25 +1530,13 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info)
+ 	 */
+ 	p_fs->fs_func->get_uni_name_from_ext_entry(sb, &fid->dir, fid->entry,
+ 						   uni_name.name);
+-	if (*uni_name.name == 0x0 && p_fs->vol_type != EXFAT)
+-		get_uni_name_from_dos_entry(sb, (struct dos_dentry_t *)ep,
+-					    &uni_name, 0x1);
+ 	nls_uniname_to_cstring(sb, info->Name, &uni_name);
+ 
+-	if (p_fs->vol_type == EXFAT) {
+-		info->NumSubdirs = 2;
+-	} else {
+-		buf_unlock(sb, sector);
+-		get_uni_name_from_dos_entry(sb, (struct dos_dentry_t *)ep,
+-					    &uni_name, 0x0);
+-		nls_uniname_to_cstring(sb, info->ShortName, &uni_name);
+-		info->NumSubdirs = 0;
+-	}
++	info->NumSubdirs = 2;
+ 
+ 	info->Size = p_fs->fs_func->get_entry_size(ep2);
+ 
+-	if (p_fs->vol_type == EXFAT)
+-		release_entry_set(es);
++	release_entry_set(es);
+ 
+ 	if (is_dir) {
+ 		dir.dir = fid->start_clu;
+@@ -1648,7 +1567,6 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info)
+ 
+ static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info)
+ {
+-	sector_t sector = 0;
+ 	int ret = 0;
+ 	struct timestamp_t tm;
+ 	struct dentry_t *ep, *ep2;
+@@ -1676,23 +1594,13 @@ static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info)
+ 	fs_set_vol_flags(sb, VOL_DIRTY);
+ 
+ 	/* get the directory entry of given file or directory */
+-	if (p_fs->vol_type == EXFAT) {
+-		es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
+-					  ES_ALL_ENTRIES, &ep);
+-		if (!es) {
+-			ret = -ENOENT;
+-			goto out;
+-		}
+-		ep2 = ep + 1;
+-	} else {
+-		/* for other than exfat */
+-		ep = get_entry_in_dir(sb, &fid->dir, fid->entry, §or);
+-		if (!ep) {
+-			ret = -ENOENT;
+-			goto out;
+-		}
+-		ep2 = ep;
++	es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
++				  ES_ALL_ENTRIES, &ep);
++	if (!es) {
++		ret = -ENOENT;
++		goto out;
+ 	}
++	ep2 = ep + 1;
+ 
+ 	p_fs->fs_func->set_entry_attr(ep, info->Attr);
+ 
+@@ -1715,12 +1623,8 @@ static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info)
+ 
+ 	p_fs->fs_func->set_entry_size(ep2, info->Size);
+ 
+-	if (p_fs->vol_type != EXFAT) {
+-		buf_modify(sb, sector);
+-	} else {
+-		update_dir_checksum_with_entry_set(sb, es);
+-		release_entry_set(es);
+-	}
++	update_dir_checksum_with_entry_set(sb, es);
++	release_entry_set(es);
+ 
+ 	if (p_fs->dev_ejected)
+ 		ret = -EIO;
+@@ -1740,7 +1644,6 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
+ 	bool modified = false;
+ 	u32 last_clu;
+ 	int ret = 0;
+-	sector_t sector = 0;
+ 	struct chain_t new_clu;
+ 	struct dentry_t *ep;
+ 	struct entry_set_cache_t *es = NULL;
+@@ -1830,28 +1733,17 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
+ 		num_clusters += num_alloced;
+ 		*clu = new_clu.dir;
+ 
+-		if (p_fs->vol_type == EXFAT) {
+-			es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
+-						  ES_ALL_ENTRIES, &ep);
+-			if (!es) {
+-				ret = -ENOENT;
+-				goto out;
+-			}
+-			/* get stream entry */
+-			ep++;
++		es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
++					  ES_ALL_ENTRIES, &ep);
++		if (!es) {
++			ret = -ENOENT;
++			goto out;
+ 		}
++		/* get stream entry */
++		ep++;
+ 
+ 		/* (3) update directory entry */
+ 		if (modified) {
+-			if (p_fs->vol_type != EXFAT) {
+-				ep = get_entry_in_dir(sb, &fid->dir,
+-						      fid->entry, §or);
+-				if (!ep) {
+-					ret = -ENOENT;
+-					goto out;
+-				}
+-			}
+-
+ 			if (p_fs->fs_func->get_entry_flag(ep) != fid->flags)
+ 				p_fs->fs_func->set_entry_flag(ep, fid->flags);
+ 
+@@ -1859,14 +1751,10 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
+ 				p_fs->fs_func->set_entry_clu0(ep,
+ 							      fid->start_clu);
+ 
+-			if (p_fs->vol_type != EXFAT)
+-				buf_modify(sb, sector);
+ 		}
+ 
+-		if (p_fs->vol_type == EXFAT) {
+-			update_dir_checksum_with_entry_set(sb, es);
+-			release_entry_set(es);
+-		}
++		update_dir_checksum_with_entry_set(sb, es);
++		release_entry_set(es);
+ 
+ 		/* add number of new blocks to inode */
+ 		inode->i_blocks += num_alloced << (p_fs->cluster_size_bits - 9);
+@@ -2060,25 +1948,13 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
+ 			*uni_name.name = 0x0;
+ 			fs_func->get_uni_name_from_ext_entry(sb, &dir, dentry,
+ 							     uni_name.name);
+-			if (*uni_name.name == 0x0 && p_fs->vol_type != EXFAT)
+-				get_uni_name_from_dos_entry(sb,
+-						(struct dos_dentry_t *)ep,
+-						&uni_name, 0x1);
+ 			nls_uniname_to_cstring(sb, dir_entry->Name, &uni_name);
+ 			buf_unlock(sb, sector);
+ 
+-			if (p_fs->vol_type == EXFAT) {
+-				ep = get_entry_in_dir(sb, &clu, i + 1, NULL);
+-				if (!ep) {
+-					ret = -ENOENT;
+-					goto out;
+-				}
+-			} else {
+-				get_uni_name_from_dos_entry(sb,
+-						(struct dos_dentry_t *)ep,
+-						&uni_name, 0x0);
+-				nls_uniname_to_cstring(sb, dir_entry->ShortName,
+-						       &uni_name);
++			ep = get_entry_in_dir(sb, &clu, i + 1, NULL);
++			if (!ep) {
++				ret = -ENOENT;
++				goto out;
+ 			}
+ 
+ 			dir_entry->Size = fs_func->get_entry_size(ep);
+@@ -3056,7 +2932,6 @@ static int exfat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
+ 	struct super_block *sb = inode->i_sb;
+ 	struct exfat_sb_info *sbi = EXFAT_SB(sb);
+ 	struct fs_info_t *p_fs = &sbi->fs_info;
+-	struct bd_info_t *p_bd = &sbi->bd_info;
+ 	const unsigned long blocksize = sb->s_blocksize;
+ 	const unsigned char blocksize_bits = sb->s_blocksize_bits;
+ 	sector_t last_block;
+@@ -3066,18 +2941,6 @@ static int exfat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
+ 	*phys = 0;
+ 	*mapped_blocks = 0;
+ 
+-	if ((p_fs->vol_type == FAT12) || (p_fs->vol_type == FAT16)) {
+-		if (inode->i_ino == EXFAT_ROOT_INO) {
+-			if (sector <
+-			    (p_fs->dentries_in_root >>
+-			     (p_bd->sector_size_bits - DENTRY_SIZE_BITS))) {
+-				*phys = sector + p_fs->root_start_sector;
+-				*mapped_blocks = 1;
+-			}
+-			return 0;
+-		}
+-	}
+-
+ 	last_block = (i_size_read(inode) + (blocksize - 1)) >> blocksize_bits;
+ 	if (sector >= last_block) {
+ 		if (*create == 0)
+@@ -3823,7 +3686,6 @@ static int exfat_fill_super(struct super_block *sb, void *data, int silent)
+ 	struct exfat_sb_info *sbi;
+ 	int debug, ret;
+ 	long error;
+-	char buf[50];
+ 
+ 	/*
+ 	 * GFP_KERNEL is ok here, because while we do hold the
+@@ -3870,17 +3732,6 @@ static int exfat_fill_super(struct super_block *sb, void *data, int silent)
+ 	 * if (FAT_FIRST_ENT(sb, media) != first)
+ 	 */
+ 
+-	/* codepage is not meaningful in exfat */
+-	if (sbi->fs_info.vol_type != EXFAT) {
+-		error = -EINVAL;
+-		sprintf(buf, "cp%d", sbi->options.codepage);
+-		sbi->nls_disk = load_nls(buf);
+-		if (!sbi->nls_disk) {
+-			pr_err("[EXFAT] Codepage %s not found\n", buf);
+-			goto out_fail2;
+-		}
+-	}
+-
+ 	sbi->nls_io = load_nls(sbi->options.iocharset);
+ 
+ 	error = -ENOMEM;

commit 7c6d78eb7c9c55952e354fe9fd212d45d9af0807
+Author: Valdis Kletnieks 
+Date:   Tue Nov 12 16:12:28 2019 -0500
+
+    staging: exfat: Remove FAT/VFAT mount support, part 2
+    
+    Remove no longer referenced FAT/VFAT routines.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191112211238.156490-3-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index 68f79e13af2b..9ea865f607af 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -766,17 +766,12 @@ void fs_error(struct super_block *sb);
+ 
+ /* cluster management functions */
+ s32 clear_cluster(struct super_block *sb, u32 clu);
+-s32 fat_alloc_cluster(struct super_block *sb, s32 num_alloc,
+-		      struct chain_t *p_chain);
+ s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc,
+ 			struct chain_t *p_chain);
+-void fat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
+-		      s32 do_relse);
+ void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
+ 			s32 do_relse);
+ u32 find_last_cluster(struct super_block *sb, struct chain_t *p_chain);
+ s32 count_num_clusters(struct super_block *sb, struct chain_t *dir);
+-s32 fat_count_used_clusters(struct super_block *sb);
+ s32 exfat_count_used_clusters(struct super_block *sb);
+ void exfat_chain_cont_cluster(struct super_block *sb, u32 chain, s32 len);
+ 
+@@ -793,63 +788,36 @@ s32 load_upcase_table(struct super_block *sb);
+ void free_upcase_table(struct super_block *sb);
+ 
+ /* dir entry management functions */
+-u32 fat_get_entry_type(struct dentry_t *p_entry);
+ u32 exfat_get_entry_type(struct dentry_t *p_entry);
+-void fat_set_entry_type(struct dentry_t *p_entry, u32 type);
+ void exfat_set_entry_type(struct dentry_t *p_entry, u32 type);
+-u32 fat_get_entry_attr(struct dentry_t *p_entry);
+ u32 exfat_get_entry_attr(struct dentry_t *p_entry);
+-void fat_set_entry_attr(struct dentry_t *p_entry, u32 attr);
+ void exfat_set_entry_attr(struct dentry_t *p_entry, u32 attr);
+-u8 fat_get_entry_flag(struct dentry_t *p_entry);
+ u8 exfat_get_entry_flag(struct dentry_t *p_entry);
+-void fat_set_entry_flag(struct dentry_t *p_entry, u8 flag);
+ void exfat_set_entry_flag(struct dentry_t *p_entry, u8 flag);
+-u32 fat_get_entry_clu0(struct dentry_t *p_entry);
+ u32 exfat_get_entry_clu0(struct dentry_t *p_entry);
+-void fat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu);
+ void exfat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu);
+-u64 fat_get_entry_size(struct dentry_t *p_entry);
+ u64 exfat_get_entry_size(struct dentry_t *p_entry);
+-void fat_set_entry_size(struct dentry_t *p_entry, u64 size);
+ void exfat_set_entry_size(struct dentry_t *p_entry, u64 size);
+ struct timestamp_t *tm_current(struct timestamp_t *tm);
+-void fat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
+-			u8 mode);
+ void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
+ 			  u8 mode);
+-void fat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
+-			u8 mode);
+ void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
+ 			  u8 mode);
+-s32 fat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir, s32 entry,
+-		       u32 type, u32 start_clu, u64 size);
+ s32 exfat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+ 			 s32 entry, u32 type, u32 start_clu, u64 size);
+-s32 fat_init_ext_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+-			   s32 entry, s32 num_entries,
+-			   struct uni_name_t *p_uniname,
+-			   struct dos_name_t *p_dosname);
+ s32 exfat_init_ext_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+ 			     s32 entry, s32 num_entries,
+ 			     struct uni_name_t *p_uniname,
+ 		struct dos_name_t *p_dosname);
+-void init_dos_entry(struct dos_dentry_t *ep, u32 type, u32 start_clu);
+-void init_ext_entry(struct ext_dentry_t *ep, s32 order, u8 chksum,
+-		    u16 *uniname);
+ void init_file_entry(struct file_dentry_t *ep, u32 type);
+ void init_strm_entry(struct strm_dentry_t *ep, u8 flags, u32 start_clu,
+ 		     u64 size);
+ void init_name_entry(struct name_dentry_t *ep, u16 *uniname);
+-void fat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+-			  s32 entry, s32 order, s32 num_entries);
+ void exfat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+ 			    s32 entry, s32 order, s32 num_entries);
+ 
+ s32 find_location(struct super_block *sb, struct chain_t *p_dir, s32 entry,
+ 		  sector_t *sector, s32 *offset);
+-struct dentry_t *get_entry_with_sector(struct super_block *sb, sector_t sector,
+-				       s32 offset);
+ struct dentry_t *get_entry_in_dir(struct super_block *sb, struct chain_t *p_dir,
+ 				  s32 entry, sector_t *sector);
+ struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb,
+@@ -865,14 +833,9 @@ s32 search_deleted_or_unused_entry(struct super_block *sb,
+ 				   struct chain_t *p_dir, s32 num_entries);
+ s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir,
+ 		     s32 num_entries);
+-s32 fat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+-		       struct uni_name_t *p_uniname, s32 num_entries,
+-		       struct dos_name_t *p_dosname, u32 type);
+ s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+ 			 struct uni_name_t *p_uniname, s32 num_entries,
+ 			 struct dos_name_t *p_dosname, u32 type);
+-s32 fat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir,
+-			  s32 entry, struct dentry_t *p_entry);
+ s32 exfat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir,
+ 			    s32 entry, struct dentry_t *p_entry);
+ s32 count_dos_name_entries(struct super_block *sb, struct chain_t *p_dir,
+@@ -890,14 +853,9 @@ s32 get_num_entries_and_dos_name(struct super_block *sb, struct chain_t *p_dir,
+ void get_uni_name_from_dos_entry(struct super_block *sb,
+ 				 struct dos_dentry_t *ep,
+ 				 struct uni_name_t *p_uniname, u8 mode);
+-void fat_get_uni_name_from_ext_entry(struct super_block *sb,
+-				     struct chain_t *p_dir, s32 entry,
+-				     u16 *uniname);
+ void exfat_get_uni_name_from_ext_entry(struct super_block *sb,
+ 				       struct chain_t *p_dir, s32 entry,
+ 				       u16 *uniname);
+-s32 extract_uni_name_from_ext_entry(struct ext_dentry_t *ep,
+-				    u16 *uniname, s32 order);
+ s32 extract_uni_name_from_name_entry(struct name_dentry_t *ep,
+ 				     u16 *uniname, s32 order);
+ s32 fat_generate_dos_name(struct super_block *sb, struct chain_t *p_dir,
+@@ -905,9 +863,7 @@ s32 fat_generate_dos_name(struct super_block *sb, struct chain_t *p_dir,
+ void fat_attach_count_to_dos_name(u8 *dosname, s32 count);
+ s32 fat_calc_num_entries(struct uni_name_t *p_uniname);
+ s32 exfat_calc_num_entries(struct uni_name_t *p_uniname);
+-u8 calc_checksum_1byte(void *data, s32 len, u8 chksum);
+ u16 calc_checksum_2byte(void *data, s32 len, u16 chksum, s32 type);
+-u32 calc_checksum_4byte(void *data, s32 len, u32 chksum, s32 type);
+ 
+ /* name resolution functions */
+ s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir,
+diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
+index 89bed7460162..ed9e4521ec04 100644
+--- a/drivers/staging/exfat/exfat_core.c
++++ b/drivers/staging/exfat/exfat_core.c
+@@ -167,60 +167,6 @@ s32 clear_cluster(struct super_block *sb, u32 clu)
+ 	return ret;
+ }
+ 
+-s32 fat_alloc_cluster(struct super_block *sb, s32 num_alloc,
+-		      struct chain_t *p_chain)
+-{
+-	int i, num_clusters = 0;
+-	u32 new_clu, last_clu = CLUSTER_32(~0), read_clu;
+-	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+-
+-	new_clu = p_chain->dir;
+-	if (new_clu == CLUSTER_32(~0))
+-		new_clu = p_fs->clu_srch_ptr;
+-	else if (new_clu >= p_fs->num_clusters)
+-		new_clu = 2;
+-
+-	__set_sb_dirty(sb);
+-
+-	p_chain->dir = CLUSTER_32(~0);
+-
+-	for (i = 2; i < p_fs->num_clusters; i++) {
+-		if (FAT_read(sb, new_clu, &read_clu) != 0)
+-			return -1;
+-
+-		if (read_clu == CLUSTER_32(0)) {
+-			if (FAT_write(sb, new_clu, CLUSTER_32(~0)) < 0)
+-				return -1;
+-			num_clusters++;
+-
+-			if (p_chain->dir == CLUSTER_32(~0)) {
+-				p_chain->dir = new_clu;
+-			} else {
+-				if (FAT_write(sb, last_clu, new_clu) < 0)
+-					return -1;
+-			}
+-
+-			last_clu = new_clu;
+-
+-			if ((--num_alloc) == 0) {
+-				p_fs->clu_srch_ptr = new_clu;
+-				if (p_fs->used_clusters != UINT_MAX)
+-					p_fs->used_clusters += num_clusters;
+-
+-				return num_clusters;
+-			}
+-		}
+-		if ((++new_clu) >= p_fs->num_clusters)
+-			new_clu = 2;
+-	}
+-
+-	p_fs->clu_srch_ptr = new_clu;
+-	if (p_fs->used_clusters != UINT_MAX)
+-		p_fs->used_clusters += num_clusters;
+-
+-	return num_clusters;
+-}
+-
+ s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc,
+ 			struct chain_t *p_chain)
+ {
+@@ -300,47 +246,6 @@ s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc,
+ 	return num_clusters;
+ }
+ 
+-void fat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
+-		      s32 do_relse)
+-{
+-	s32 num_clusters = 0;
+-	u32 clu, prev;
+-	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+-	int i;
+-	sector_t sector;
+-
+-	if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0)))
+-		return;
+-	__set_sb_dirty(sb);
+-	clu = p_chain->dir;
+-
+-	if (p_chain->size <= 0)
+-		return;
+-
+-	do {
+-		if (p_fs->dev_ejected)
+-			break;
+-
+-		if (do_relse) {
+-			sector = START_SECTOR(clu);
+-			for (i = 0; i < p_fs->sectors_per_clu; i++)
+-				buf_release(sb, sector + i);
+-		}
+-
+-		prev = clu;
+-		if (FAT_read(sb, clu, &clu) == -1)
+-			break;
+-
+-		if (FAT_write(sb, prev, CLUSTER_32(0)) < 0)
+-			break;
+-		num_clusters++;
+-
+-	} while (clu != CLUSTER_32(~0));
+-
+-	if (p_fs->used_clusters != UINT_MAX)
+-		p_fs->used_clusters -= num_clusters;
+-}
+-
+ void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
+ 			s32 do_relse)
+ {
+@@ -447,22 +352,6 @@ s32 count_num_clusters(struct super_block *sb, struct chain_t *p_chain)
+ 	return count;
+ }
+ 
+-s32 fat_count_used_clusters(struct super_block *sb)
+-{
+-	int i, count = 0;
+-	u32 clu;
+-	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+-
+-	for (i = 2; i < p_fs->num_clusters; i++) {
+-		if (FAT_read(sb, i, &clu) != 0)
+-			break;
+-		if (clu != CLUSTER_32(0))
+-			count++;
+-	}
+-
+-	return count;
+-}
+-
+ s32 exfat_count_used_clusters(struct super_block *sb)
+ {
+ 	int i, map_i, map_b, count = 0;
+@@ -907,28 +796,6 @@ void free_upcase_table(struct super_block *sb)
+  *  Directory Entry Management Functions
+  */
+ 
+-u32 fat_get_entry_type(struct dentry_t *p_entry)
+-{
+-	struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
+-
+-	if (*ep->name == 0x0)
+-		return TYPE_UNUSED;
+-
+-	else if (*ep->name == 0xE5)
+-		return TYPE_DELETED;
+-
+-	else if (ep->attr == ATTR_EXTEND)
+-		return TYPE_EXTEND;
+-
+-	else if ((ep->attr & (ATTR_SUBDIR | ATTR_VOLUME)) == ATTR_VOLUME)
+-		return TYPE_VOLUME;
+-
+-	else if ((ep->attr & (ATTR_SUBDIR | ATTR_VOLUME)) == ATTR_SUBDIR)
+-		return TYPE_DIR;
+-
+-	return TYPE_FILE;
+-}
+-
+ u32 exfat_get_entry_type(struct dentry_t *p_entry)
+ {
+ 	struct file_dentry_t *ep = (struct file_dentry_t *)p_entry;
+@@ -974,29 +841,6 @@ u32 exfat_get_entry_type(struct dentry_t *p_entry)
+ 	return TYPE_BENIGN_SEC;
+ }
+ 
+-void fat_set_entry_type(struct dentry_t *p_entry, u32 type)
+-{
+-	struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
+-
+-	if (type == TYPE_UNUSED)
+-		*ep->name = 0x0;
+-
+-	else if (type == TYPE_DELETED)
+-		*ep->name = 0xE5;
+-
+-	else if (type == TYPE_EXTEND)
+-		ep->attr = ATTR_EXTEND;
+-
+-	else if (type == TYPE_DIR)
+-		ep->attr = ATTR_SUBDIR;
+-
+-	else if (type == TYPE_FILE)
+-		ep->attr = ATTR_ARCHIVE;
+-
+-	else if (type == TYPE_SYMLINK)
+-		ep->attr = ATTR_ARCHIVE | ATTR_SYMLINK;
+-}
+-
+ void exfat_set_entry_type(struct dentry_t *p_entry, u32 type)
+ {
+ 	struct file_dentry_t *ep = (struct file_dentry_t *)p_entry;
+@@ -1027,13 +871,6 @@ void exfat_set_entry_type(struct dentry_t *p_entry, u32 type)
+ 	}
+ }
+ 
+-u32 fat_get_entry_attr(struct dentry_t *p_entry)
+-{
+-	struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
+-
+-	return (u32)ep->attr;
+-}
+-
+ u32 exfat_get_entry_attr(struct dentry_t *p_entry)
+ {
+ 	struct file_dentry_t *ep = (struct file_dentry_t *)p_entry;
+@@ -1041,13 +878,6 @@ u32 exfat_get_entry_attr(struct dentry_t *p_entry)
+ 	return (u32)GET16_A(ep->attr);
+ }
+ 
+-void fat_set_entry_attr(struct dentry_t *p_entry, u32 attr)
+-{
+-	struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
+-
+-	ep->attr = (u8)attr;
+-}
+-
+ void exfat_set_entry_attr(struct dentry_t *p_entry, u32 attr)
+ {
+ 	struct file_dentry_t *ep = (struct file_dentry_t *)p_entry;
+@@ -1055,11 +885,6 @@ void exfat_set_entry_attr(struct dentry_t *p_entry, u32 attr)
+ 	SET16_A(ep->attr, (u16)attr);
+ }
+ 
+-u8 fat_get_entry_flag(struct dentry_t *p_entry)
+-{
+-	return 0x01;
+-}
+-
+ u8 exfat_get_entry_flag(struct dentry_t *p_entry)
+ {
+ 	struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry;
+@@ -1067,10 +892,6 @@ u8 exfat_get_entry_flag(struct dentry_t *p_entry)
+ 	return ep->flags;
+ }
+ 
+-void fat_set_entry_flag(struct dentry_t *p_entry, u8 flags)
+-{
+-}
+-
+ void exfat_set_entry_flag(struct dentry_t *p_entry, u8 flags)
+ {
+ 	struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry;
+@@ -1078,14 +899,6 @@ void exfat_set_entry_flag(struct dentry_t *p_entry, u8 flags)
+ 	ep->flags = flags;
+ }
+ 
+-u32 fat_get_entry_clu0(struct dentry_t *p_entry)
+-{
+-	struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
+-
+-	return ((u32)GET16_A(ep->start_clu_hi) << 16) |
+-		GET16_A(ep->start_clu_lo);
+-}
+-
+ u32 exfat_get_entry_clu0(struct dentry_t *p_entry)
+ {
+ 	struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry;
+@@ -1093,14 +906,6 @@ u32 exfat_get_entry_clu0(struct dentry_t *p_entry)
+ 	return GET32_A(ep->start_clu);
+ }
+ 
+-void fat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu)
+-{
+-	struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
+-
+-	SET16_A(ep->start_clu_lo, CLUSTER_16(start_clu));
+-	SET16_A(ep->start_clu_hi, CLUSTER_16(start_clu >> 16));
+-}
+-
+ void exfat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu)
+ {
+ 	struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry;
+@@ -1108,13 +913,6 @@ void exfat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu)
+ 	SET32_A(ep->start_clu, start_clu);
+ }
+ 
+-u64 fat_get_entry_size(struct dentry_t *p_entry)
+-{
+-	struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
+-
+-	return (u64)GET32_A(ep->size);
+-}
+-
+ u64 exfat_get_entry_size(struct dentry_t *p_entry)
+ {
+ 	struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry;
+@@ -1122,13 +920,6 @@ u64 exfat_get_entry_size(struct dentry_t *p_entry)
+ 	return GET64_A(ep->valid_size);
+ }
+ 
+-void fat_set_entry_size(struct dentry_t *p_entry, u64 size)
+-{
+-	struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
+-
+-	SET32_A(ep->size, (u32)size);
+-}
+-
+ void exfat_set_entry_size(struct dentry_t *p_entry, u64 size)
+ {
+ 	struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry;
+@@ -1137,31 +928,6 @@ void exfat_set_entry_size(struct dentry_t *p_entry, u64 size)
+ 	SET64_A(ep->size, size);
+ }
+ 
+-void fat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
+-			u8 mode)
+-{
+-	u16 t = 0x00, d = 0x21;
+-	struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
+-
+-	switch (mode) {
+-	case TM_CREATE:
+-		t = GET16_A(ep->create_time);
+-		d = GET16_A(ep->create_date);
+-		break;
+-	case TM_MODIFY:
+-		t = GET16_A(ep->modify_time);
+-		d = GET16_A(ep->modify_date);
+-		break;
+-	}
+-
+-	tp->sec  = (t & 0x001F) << 1;
+-	tp->min  = (t >> 5) & 0x003F;
+-	tp->hour = (t >> 11);
+-	tp->day  = (d & 0x001F);
+-	tp->mon  = (d >> 5) & 0x000F;
+-	tp->year = (d >> 9);
+-}
+-
+ void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
+ 			  u8 mode)
+ {
+@@ -1191,27 +957,6 @@ void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
+ 	tp->year = (d >> 9);
+ }
+ 
+-void fat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
+-			u8 mode)
+-{
+-	u16 t, d;
+-	struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
+-
+-	t = (tp->hour << 11) | (tp->min << 5) | (tp->sec >> 1);
+-	d = (tp->year <<  9) | (tp->mon << 5) |  tp->day;
+-
+-	switch (mode) {
+-	case TM_CREATE:
+-		SET16_A(ep->create_time, t);
+-		SET16_A(ep->create_date, d);
+-		break;
+-	case TM_MODIFY:
+-		SET16_A(ep->modify_time, t);
+-		SET16_A(ep->modify_date, d);
+-		break;
+-	}
+-}
+-
+ void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
+ 			  u8 mode)
+ {
+@@ -1237,23 +982,6 @@ void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
+ 	}
+ }
+ 
+-s32 fat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir, s32 entry,
+-		       u32 type, u32 start_clu, u64 size)
+-{
+-	sector_t sector;
+-	struct dos_dentry_t *dos_ep;
+-
+-	dos_ep = (struct dos_dentry_t *)get_entry_in_dir(sb, p_dir, entry,
+-							 §or);
+-	if (!dos_ep)
+-		return -EIO;
+-
+-	init_dos_entry(dos_ep, type, start_clu);
+-	buf_modify(sb, sector);
+-
+-	return 0;
+-}
+-
+ s32 exfat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+ 			 s32 entry, u32 type, u32 start_clu, u64 size)
+ {
+@@ -1330,70 +1058,6 @@ static s32 exfat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir,
+ 	return 0;
+ }
+ 
+-void init_dos_entry(struct dos_dentry_t *ep, u32 type, u32 start_clu)
+-{
+-	struct timestamp_t tm, *tp;
+-
+-	fat_set_entry_type((struct dentry_t *)ep, type);
+-	SET16_A(ep->start_clu_lo, CLUSTER_16(start_clu));
+-	SET16_A(ep->start_clu_hi, CLUSTER_16(start_clu >> 16));
+-	SET32_A(ep->size, 0);
+-
+-	tp = tm_current(&tm);
+-	fat_set_entry_time((struct dentry_t *)ep, tp, TM_CREATE);
+-	fat_set_entry_time((struct dentry_t *)ep, tp, TM_MODIFY);
+-	SET16_A(ep->access_date, 0);
+-	ep->create_time_ms = 0;
+-}
+-
+-void init_ext_entry(struct ext_dentry_t *ep, s32 order, u8 chksum, u16 *uniname)
+-{
+-	int i;
+-	bool end = false;
+-
+-	fat_set_entry_type((struct dentry_t *)ep, TYPE_EXTEND);
+-	ep->order = (u8)order;
+-	ep->sysid = 0;
+-	ep->checksum = chksum;
+-	SET16_A(ep->start_clu, 0);
+-
+-	for (i = 0; i < 10; i += 2) {
+-		if (!end) {
+-			SET16(ep->unicode_0_4 + i, *uniname);
+-			if (*uniname == 0x0)
+-				end = true;
+-			else
+-				uniname++;
+-		} else {
+-			SET16(ep->unicode_0_4 + i, 0xFFFF);
+-		}
+-	}
+-
+-	for (i = 0; i < 12; i += 2) {
+-		if (!end) {
+-			SET16_A(ep->unicode_5_10 + i, *uniname);
+-			if (*uniname == 0x0)
+-				end = true;
+-			else
+-				uniname++;
+-		} else {
+-			SET16_A(ep->unicode_5_10 + i, 0xFFFF);
+-		}
+-	}
+-
+-	for (i = 0; i < 4; i += 2) {
+-		if (!end) {
+-			SET16_A(ep->unicode_11_12 + i, *uniname);
+-			if (*uniname == 0x0)
+-				end = true;
+-			else
+-				uniname++;
+-		} else {
+-			SET16_A(ep->unicode_11_12 + i, 0xFFFF);
+-		}
+-	}
+-}
+-
+ void init_file_entry(struct file_dentry_t *ep, u32 type)
+ {
+ 	struct timestamp_t tm, *tp;
+@@ -1433,24 +1097,6 @@ void init_name_entry(struct name_dentry_t *ep, u16 *uniname)
+ 	}
+ }
+ 
+-void fat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+-		s32 entry, s32 order, s32 num_entries)
+-{
+-	int i;
+-	sector_t sector;
+-	struct dentry_t *ep;
+-	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+-
+-	for (i = num_entries - 1; i >= order; i--) {
+-		ep = get_entry_in_dir(sb, p_dir, entry - i, §or);
+-		if (!ep)
+-			return;
+-
+-		p_fs->fs_func->set_entry_type(ep, TYPE_DELETED);
+-		buf_modify(sb, sector);
+-	}
+-}
+-
+ void exfat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+ 			    s32 entry, s32 order, s32 num_entries)
+ {
+@@ -1583,19 +1229,6 @@ s32 find_location(struct super_block *sb, struct chain_t *p_dir, s32 entry,
+ 	return 0;
+ }
+ 
+-struct dentry_t *get_entry_with_sector(struct super_block *sb, sector_t sector,
+-				       s32 offset)
+-{
+-	u8 *buf;
+-
+-	buf = buf_getblk(sb, sector);
+-
+-	if (!buf)
+-		return NULL;
+-
+-	return (struct dentry_t *)(buf + offset);
+-}
+-
+ struct dentry_t *get_entry_in_dir(struct super_block *sb, struct chain_t *p_dir,
+ 				  s32 entry, sector_t *sector)
+ {
+@@ -1866,46 +1499,6 @@ s32 write_whole_entry_set(struct super_block *sb, struct entry_set_cache_t *es)
+ 						    es->num_entries);
+ }
+ 
+-/* write back some entries in entry set */
+-s32 write_partial_entries_in_entry_set(struct super_block *sb,
+-				       struct entry_set_cache_t *es,
+-				       struct dentry_t *ep, u32 count)
+-{
+-	s32 ret, byte_offset, off;
+-	u32 clu = 0;
+-	sector_t sec;
+-	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+-	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
+-	struct chain_t dir;
+-
+-	/* vaidity check */
+-	if (ep + count  > ((struct dentry_t *)&es->__buf) + es->num_entries)
+-		return -EINVAL;
+-
+-	dir.dir = GET_CLUSTER_FROM_SECTOR(es->sector);
+-	dir.flags = es->alloc_flag;
+-	dir.size = 0xffffffff;		/* XXX */
+-
+-	byte_offset = (es->sector - START_SECTOR(dir.dir)) <<
+-			p_bd->sector_size_bits;
+-	byte_offset += ((void **)ep - &es->__buf) + es->offset;
+-
+-	ret = _walk_fat_chain(sb, &dir, byte_offset, &clu);
+-	if (ret != 0)
+-		return ret;
+-
+-	/* byte offset in cluster */
+-	byte_offset &= p_fs->cluster_size - 1;
+-
+-	/* byte offset in sector    */
+-	off = byte_offset & p_bd->sector_size_mask;
+-
+-	/* sector offset in cluster */
+-	sec = byte_offset >> p_bd->sector_size_bits;
+-	sec += START_SECTOR(clu);
+-	return __write_partial_entries_in_entry_set(sb, es, sec, off, count);
+-}
+-
+ /* search EMPTY CONTINUOUS "num_entries" entries */
+ s32 search_deleted_or_unused_entry(struct super_block *sb,
+ 				   struct chain_t *p_dir, s32 num_entries)
+@@ -2087,104 +1680,6 @@ s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_entries
+ 	return dentry;
+ }
+ 
+-/* return values of fat_find_dir_entry()
+- * >= 0 : return dir entiry position with the name in dir
+- * -1 : (root dir, ".") it is the root dir itself
+- * -2 : entry with the name does not exist
+- */
+-s32 fat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+-		       struct uni_name_t *p_uniname, s32 num_entries,
+-		       struct dos_name_t *p_dosname, u32 type)
+-{
+-	int i, dentry = 0, len;
+-	s32 order = 0;
+-	bool is_feasible_entry = true, has_ext_entry = false;
+-	s32 dentries_per_clu;
+-	u32 entry_type;
+-	u16 entry_uniname[14], *uniname = NULL, unichar;
+-	struct chain_t clu;
+-	struct dentry_t *ep;
+-	struct dos_dentry_t *dos_ep;
+-	struct ext_dentry_t *ext_ep;
+-	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+-
+-	if (p_dir->dir == p_fs->root_dir) {
+-		if ((!nls_uniname_cmp(sb, p_uniname->name,
+-				      (u16 *)UNI_CUR_DIR_NAME)) ||
+-			(!nls_uniname_cmp(sb, p_uniname->name,
+-					  (u16 *)UNI_PAR_DIR_NAME)))
+-			return -1; // special case, root directory itself
+-	}
+-
+-	if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */
+-		dentries_per_clu = p_fs->dentries_in_root;
+-	else
+-		dentries_per_clu = p_fs->dentries_per_clu;
+-
+-	clu.dir = p_dir->dir;
+-	clu.flags = p_dir->flags;
+-
+-	while (clu.dir != CLUSTER_32(~0)) {
+-		if (p_fs->dev_ejected)
+-			break;
+-
+-		for (i = 0; i < dentries_per_clu; i++, dentry++) {
+-			ep = get_entry_in_dir(sb, &clu, i, NULL);
+-			if (!ep)
+-				return -2;
+-
+-			entry_type = p_fs->fs_func->get_entry_type(ep);
+-
+-			if ((entry_type == TYPE_FILE) || (entry_type == TYPE_DIR)) {
+-				if ((type == TYPE_ALL) || (type == entry_type)) {
+-					if (is_feasible_entry && has_ext_entry)
+-						return dentry;
+-
+-					dos_ep = (struct dos_dentry_t *)ep;
+-					if (!nls_dosname_cmp(sb, p_dosname->name, dos_ep->name))
+-						return dentry;
+-				}
+-				is_feasible_entry = true;
+-				has_ext_entry = false;
+-			} else if (entry_type == TYPE_EXTEND) {
+-				if (is_feasible_entry) {
+-					ext_ep = (struct ext_dentry_t *)ep;
+-					if (ext_ep->order > 0x40) {
+-						order = (s32)(ext_ep->order - 0x40);
+-						uniname = p_uniname->name + 13 * (order - 1);
+-					} else {
+-						order = (s32)ext_ep->order;
+-						uniname -= 13;
+-					}
+-
+-					len = extract_uni_name_from_ext_entry(ext_ep, entry_uniname, order);
+-
+-					unichar = *(uniname + len);
+-					*(uniname + len) = 0x0;
+-
+-					if (nls_uniname_cmp(sb, uniname, entry_uniname))
+-						is_feasible_entry = false;
+-
+-					*(uniname + len) = unichar;
+-				}
+-				has_ext_entry = true;
+-			} else if (entry_type == TYPE_UNUSED) {
+-				return -2;
+-			}
+-			is_feasible_entry = true;
+-			has_ext_entry = false;
+-		}
+-
+-		if (p_dir->dir == CLUSTER_32(0))
+-			break; /* FAT16 root_dir */
+-
+-		if (FAT_read(sb, clu.dir, &clu.dir) != 0)
+-			return -2;
+-	}
+-
+-	return -2;
+-}
+-
+ /* return values of exfat_find_dir_entry()
+  * >= 0 : return dir entiry position with the name in dir
+  * -1 : (root dir, ".") it is the root dir itself
+@@ -2333,36 +1828,6 @@ s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+ 	return -2;
+ }
+ 
+-s32 fat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir,
+-			  s32 entry, struct dentry_t *p_entry)
+-{
+-	s32 count = 0;
+-	u8 chksum;
+-	struct dos_dentry_t *dos_ep = (struct dos_dentry_t *)p_entry;
+-	struct ext_dentry_t *ext_ep;
+-	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+-
+-	chksum = calc_checksum_1byte((void *)dos_ep->name, DOS_NAME_LENGTH, 0);
+-
+-	for (entry--; entry >= 0; entry--) {
+-		ext_ep = (struct ext_dentry_t *)get_entry_in_dir(sb, p_dir,
+-								 entry, NULL);
+-		if (!ext_ep)
+-			return -1;
+-
+-		if ((p_fs->fs_func->get_entry_type((struct dentry_t *)ext_ep) ==
+-		     TYPE_EXTEND) && (ext_ep->checksum == chksum)) {
+-			count++;
+-			if (ext_ep->order > 0x40)
+-				return count;
+-		} else {
+-			return count;
+-		}
+-	}
+-
+-	return count;
+-}
+-
+ s32 exfat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir,
+ 			    s32 entry, struct dentry_t *p_entry)
+ {
+@@ -2564,33 +2029,6 @@ void get_uni_name_from_dos_entry(struct super_block *sb,
+ 	nls_dosname_to_uniname(sb, p_uniname, &dos_name);
+ }
+ 
+-void fat_get_uni_name_from_ext_entry(struct super_block *sb,
+-				     struct chain_t *p_dir, s32 entry,
+-				     u16 *uniname)
+-{
+-	int i;
+-	struct ext_dentry_t *ep;
+-	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+-
+-	for (entry--, i = 1; entry >= 0; entry--, i++) {
+-		ep = (struct ext_dentry_t *)get_entry_in_dir(sb, p_dir, entry,
+-							     NULL);
+-		if (!ep)
+-			return;
+-
+-		if (p_fs->fs_func->get_entry_type((struct dentry_t *)ep) ==
+-		    TYPE_EXTEND) {
+-			extract_uni_name_from_ext_entry(ep, uniname, i);
+-			if (ep->order > 0x40)
+-				return;
+-		} else {
+-			return;
+-		}
+-
+-		uniname += 13;
+-	}
+-}
+-
+ void exfat_get_uni_name_from_ext_entry(struct super_block *sb,
+ 				       struct chain_t *p_dir, s32 entry,
+ 				       u16 *uniname)
+@@ -2628,51 +2066,6 @@ void exfat_get_uni_name_from_ext_entry(struct super_block *sb,
+ 	release_entry_set(es);
+ }
+ 
+-s32 extract_uni_name_from_ext_entry(struct ext_dentry_t *ep, u16 *uniname,
+-				    s32 order)
+-{
+-	int i, len = 0;
+-
+-	for (i = 0; i < 10; i += 2) {
+-		*uniname = GET16(ep->unicode_0_4 + i);
+-		if (*uniname == 0x0)
+-			return len;
+-		uniname++;
+-		len++;
+-	}
+-
+-	if (order < 20) {
+-		for (i = 0; i < 12; i += 2) {
+-			*uniname = GET16_A(ep->unicode_5_10 + i);
+-			if (*uniname == 0x0)
+-				return len;
+-			uniname++;
+-			len++;
+-		}
+-	} else {
+-		for (i = 0; i < 8; i += 2) {
+-			*uniname = GET16_A(ep->unicode_5_10 + i);
+-			if (*uniname == 0x0)
+-				return len;
+-			uniname++;
+-			len++;
+-		}
+-		*uniname = 0x0; /* uniname[MAX_NAME_LENGTH-1] */
+-		return len;
+-	}
+-
+-	for (i = 0; i < 4; i += 2) {
+-		*uniname = GET16_A(ep->unicode_11_12 + i);
+-		if (*uniname == 0x0)
+-			return len;
+-		uniname++;
+-		len++;
+-	}
+-
+-	*uniname = 0x0;
+-	return len;
+-}
+-
+ s32 extract_uni_name_from_name_entry(struct name_dentry_t *ep, u16 *uniname,
+ 				     s32 order)
+ {
+@@ -2812,18 +2205,6 @@ void fat_attach_count_to_dos_name(u8 *dosname, s32 count)
+ 		dosname[7] = ' ';
+ }
+ 
+-s32 fat_calc_num_entries(struct uni_name_t *p_uniname)
+-{
+-	s32 len;
+-
+-	len = p_uniname->name_len;
+-	if (len == 0)
+-		return 0;
+-
+-	/* 1 dos name entry + extended entries */
+-	return (len - 1) / 13 + 2;
+-}
+-
+ s32 exfat_calc_num_entries(struct uni_name_t *p_uniname)
+ {
+ 	s32 len;

commit 04a991cd9066dd182602a82e234bf91b1ea423d7
+Author: Valdis Kletnieks 
+Date:   Tue Nov 12 16:12:27 2019 -0500
+
+    staging: exfat: Remove FAT/VFAT mount support, part 1
+    
+    Remove the top-level mount functionality, to make this driver handle
+    only exfat file systems.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191112211238.156490-2-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/Kconfig b/drivers/staging/exfat/Kconfig
+index ce32dfe33bec..0130019cbec2 100644
+--- a/drivers/staging/exfat/Kconfig
++++ b/drivers/staging/exfat/Kconfig
+@@ -6,15 +6,6 @@ config EXFAT_FS
+ 	help
+ 	  This adds support for the exFAT file system.
+ 
+-config EXFAT_DONT_MOUNT_VFAT
+-	bool "Prohibit mounting of fat/vfat filesystems by exFAT"
+-	depends on EXFAT_FS
+-	default y
+-	help
+-	  By default, the exFAT driver will only mount exFAT filesystems, and refuse
+-	  to mount fat/vfat filesystems.  Set this to 'n' to allow the exFAT driver
+-	  to mount these filesystems.
+-
+ config EXFAT_DISCARD
+ 	bool "enable discard support"
+ 	depends on EXFAT_FS
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index 72cf40e123de..68f79e13af2b 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -915,8 +915,6 @@ s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir,
+ s32 resolve_name(u8 *name, u8 **arg);
+ 
+ /* file operation functions */
+-s32 fat16_mount(struct super_block *sb, struct pbr_sector_t *p_pbr);
+-s32 fat32_mount(struct super_block *sb, struct pbr_sector_t *p_pbr);
+ s32 exfat_mount(struct super_block *sb, struct pbr_sector_t *p_pbr);
+ s32 create_dir(struct inode *inode, struct chain_t *p_dir,
+ 	       struct uni_name_t *p_uniname, struct file_id_t *fid);
+diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
+index 1f0ef94bdd47..89bed7460162 100644
+--- a/drivers/staging/exfat/exfat_core.c
++++ b/drivers/staging/exfat/exfat_core.c
+@@ -1284,57 +1284,6 @@ s32 exfat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+ 	return 0;
+ }
+ 
+-static s32 fat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir,
+-			      s32 entry, s32 num_entries,
+-			      struct uni_name_t *p_uniname,
+-			      struct dos_name_t *p_dosname)
+-{
+-	int i;
+-	sector_t sector;
+-	u8 chksum;
+-	u16 *uniname = p_uniname->name;
+-	struct dos_dentry_t *dos_ep;
+-	struct ext_dentry_t *ext_ep;
+-
+-	dos_ep = (struct dos_dentry_t *)get_entry_in_dir(sb, p_dir, entry,
+-							 §or);
+-	if (!dos_ep)
+-		return -EIO;
+-
+-	dos_ep->lcase = p_dosname->name_case;
+-	memcpy(dos_ep->name, p_dosname->name, DOS_NAME_LENGTH);
+-	buf_modify(sb, sector);
+-
+-	if ((--num_entries) > 0) {
+-		chksum = calc_checksum_1byte((void *)dos_ep->name,
+-					     DOS_NAME_LENGTH, 0);
+-
+-		for (i = 1; i < num_entries; i++) {
+-			ext_ep = (struct ext_dentry_t *)get_entry_in_dir(sb,
+-									 p_dir,
+-									 entry - i,
+-									 §or);
+-			if (!ext_ep)
+-				return -EIO;
+-
+-			init_ext_entry(ext_ep, i, chksum, uniname);
+-			buf_modify(sb, sector);
+-			uniname += 13;
+-		}
+-
+-		ext_ep = (struct ext_dentry_t *)get_entry_in_dir(sb, p_dir,
+-								 entry - i,
+-								 §or);
+-		if (!ext_ep)
+-			return -EIO;
+-
+-		init_ext_entry(ext_ep, i + 0x40, chksum, uniname);
+-		buf_modify(sb, sector);
+-	}
+-
+-	return 0;
+-}
+-
+ static s32 exfat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir,
+ 				s32 entry, s32 num_entries,
+ 				struct uni_name_t *p_uniname,
+@@ -2981,148 +2930,6 @@ s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir,
+ /*
+  *  File Operation Functions
+  */
+-static struct fs_func fat_fs_func = {
+-	.alloc_cluster = fat_alloc_cluster,
+-	.free_cluster = fat_free_cluster,
+-	.count_used_clusters = fat_count_used_clusters,
+-
+-	.init_dir_entry = fat_init_dir_entry,
+-	.init_ext_entry = fat_init_ext_entry,
+-	.find_dir_entry = fat_find_dir_entry,
+-	.delete_dir_entry = fat_delete_dir_entry,
+-	.get_uni_name_from_ext_entry = fat_get_uni_name_from_ext_entry,
+-	.count_ext_entries = fat_count_ext_entries,
+-	.calc_num_entries = fat_calc_num_entries,
+-
+-	.get_entry_type = fat_get_entry_type,
+-	.set_entry_type = fat_set_entry_type,
+-	.get_entry_attr = fat_get_entry_attr,
+-	.set_entry_attr = fat_set_entry_attr,
+-	.get_entry_flag = fat_get_entry_flag,
+-	.set_entry_flag = fat_set_entry_flag,
+-	.get_entry_clu0 = fat_get_entry_clu0,
+-	.set_entry_clu0 = fat_set_entry_clu0,
+-	.get_entry_size = fat_get_entry_size,
+-	.set_entry_size = fat_set_entry_size,
+-	.get_entry_time = fat_get_entry_time,
+-	.set_entry_time = fat_set_entry_time,
+-};
+-
+-s32 fat16_mount(struct super_block *sb, struct pbr_sector_t *p_pbr)
+-{
+-	s32 num_reserved, num_root_sectors;
+-	struct bpb16_t *p_bpb = (struct bpb16_t *)p_pbr->bpb;
+-	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+-	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
+-
+-	if (p_bpb->num_fats == 0)
+-		return -EFSCORRUPTED;
+-
+-	num_root_sectors = GET16(p_bpb->num_root_entries) << DENTRY_SIZE_BITS;
+-	num_root_sectors = ((num_root_sectors - 1) >>
+-			    p_bd->sector_size_bits) + 1;
+-
+-	p_fs->sectors_per_clu = p_bpb->sectors_per_clu;
+-	p_fs->sectors_per_clu_bits = ilog2(p_bpb->sectors_per_clu);
+-	p_fs->cluster_size_bits = p_fs->sectors_per_clu_bits +
+-				  p_bd->sector_size_bits;
+-	p_fs->cluster_size = 1 << p_fs->cluster_size_bits;
+-
+-	p_fs->num_FAT_sectors = GET16(p_bpb->num_fat_sectors);
+-
+-	p_fs->FAT1_start_sector = p_fs->PBR_sector + GET16(p_bpb->num_reserved);
+-	if (p_bpb->num_fats == 1)
+-		p_fs->FAT2_start_sector = p_fs->FAT1_start_sector;
+-	else
+-		p_fs->FAT2_start_sector = p_fs->FAT1_start_sector +
+-					  p_fs->num_FAT_sectors;
+-
+-	p_fs->root_start_sector = p_fs->FAT2_start_sector +
+-				  p_fs->num_FAT_sectors;
+-	p_fs->data_start_sector = p_fs->root_start_sector + num_root_sectors;
+-
+-	p_fs->num_sectors = GET16(p_bpb->num_sectors);
+-	if (p_fs->num_sectors == 0)
+-		p_fs->num_sectors = GET32(p_bpb->num_huge_sectors);
+-
+-	num_reserved = p_fs->data_start_sector - p_fs->PBR_sector;
+-	p_fs->num_clusters = ((p_fs->num_sectors - num_reserved) >>
+-			      p_fs->sectors_per_clu_bits) + 2;
+-	/* because the cluster index starts with 2 */
+-
+-	if (p_fs->num_clusters < FAT12_THRESHOLD)
+-		p_fs->vol_type = FAT12;
+-	else
+-		p_fs->vol_type = FAT16;
+-	p_fs->vol_id = GET32(p_bpb->vol_serial);
+-
+-	p_fs->root_dir = 0;
+-	p_fs->dentries_in_root = GET16(p_bpb->num_root_entries);
+-	p_fs->dentries_per_clu = 1 << (p_fs->cluster_size_bits -
+-				       DENTRY_SIZE_BITS);
+-
+-	p_fs->vol_flag = VOL_CLEAN;
+-	p_fs->clu_srch_ptr = 2;
+-	p_fs->used_clusters = UINT_MAX;
+-
+-	p_fs->fs_func = &fat_fs_func;
+-
+-	return 0;
+-}
+-
+-s32 fat32_mount(struct super_block *sb, struct pbr_sector_t *p_pbr)
+-{
+-	s32 num_reserved;
+-	struct bpb32_t *p_bpb = (struct bpb32_t *)p_pbr->bpb;
+-	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+-	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
+-
+-	if (p_bpb->num_fats == 0)
+-		return -EFSCORRUPTED;
+-
+-	p_fs->sectors_per_clu = p_bpb->sectors_per_clu;
+-	p_fs->sectors_per_clu_bits = ilog2(p_bpb->sectors_per_clu);
+-	p_fs->cluster_size_bits = p_fs->sectors_per_clu_bits +
+-				  p_bd->sector_size_bits;
+-	p_fs->cluster_size = 1 << p_fs->cluster_size_bits;
+-
+-	p_fs->num_FAT_sectors = GET32(p_bpb->num_fat32_sectors);
+-
+-	p_fs->FAT1_start_sector = p_fs->PBR_sector + GET16(p_bpb->num_reserved);
+-	if (p_bpb->num_fats == 1)
+-		p_fs->FAT2_start_sector = p_fs->FAT1_start_sector;
+-	else
+-		p_fs->FAT2_start_sector = p_fs->FAT1_start_sector +
+-					  p_fs->num_FAT_sectors;
+-
+-	p_fs->root_start_sector = p_fs->FAT2_start_sector +
+-				  p_fs->num_FAT_sectors;
+-	p_fs->data_start_sector = p_fs->root_start_sector;
+-
+-	p_fs->num_sectors = GET32(p_bpb->num_huge_sectors);
+-	num_reserved = p_fs->data_start_sector - p_fs->PBR_sector;
+-
+-	p_fs->num_clusters = ((p_fs->num_sectors - num_reserved) >>
+-			      p_fs->sectors_per_clu_bits) + 2;
+-	/* because the cluster index starts with 2 */
+-
+-	p_fs->vol_type = FAT32;
+-	p_fs->vol_id = GET32(p_bpb->vol_serial);
+-
+-	p_fs->root_dir = GET32(p_bpb->root_cluster);
+-	p_fs->dentries_in_root = 0;
+-	p_fs->dentries_per_clu = 1 << (p_fs->cluster_size_bits -
+-				       DENTRY_SIZE_BITS);
+-
+-	p_fs->vol_flag = VOL_CLEAN;
+-	p_fs->clu_srch_ptr = 2;
+-	p_fs->used_clusters = UINT_MAX;
+-
+-	p_fs->fs_func = &fat_fs_func;
+-
+-	return 0;
+-}
+-
+ static struct fs_func exfat_fs_func = {
+ 	.alloc_cluster = exfat_alloc_cluster,
+ 	.free_cluster = exfat_free_cluster,
+diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
+index 4c8afe60d48b..0ebf342122da 100644
+--- a/drivers/staging/exfat/exfat_super.c
++++ b/drivers/staging/exfat/exfat_super.c
+@@ -396,16 +396,10 @@ static int ffsMountVol(struct super_block *sb)
+ 			break;
+ 
+ 	if (i < 53) {
+-#ifdef CONFIG_EXFAT_DONT_MOUNT_VFAT
++		/* Not sure how we'd get here, but complain if it does */
+ 		ret = -EINVAL;
+ 		pr_info("EXFAT: Attempted to mount VFAT filesystem\n");
+ 		goto out;
+-#else
+-		if (GET16(p_pbr->bpb + 11)) /* num_fat_sectors */
+-			ret = fat16_mount(sb, p_pbr);
+-		else
+-			ret = fat32_mount(sb, p_pbr);
+-#endif
+ 	} else {
+ 		ret = exfat_mount(sb, p_pbr);
+ 	}

commit ecbc9e989f62e59cdd3e87b1e7babacc765041ba
+Author: Valdis Kletnieks 
+Date:   Mon Nov 11 21:09:57 2019 -0500
+
+    staging: exfat: Correct return code
+    
+    Use -ENOTEMPTY rather than -EEXIST for attempting to remove
+    a directory that still has files in it.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191112021000.42091-10-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
+index 3e13e002cd14..4c8afe60d48b 100644
+--- a/drivers/staging/exfat/exfat_super.c
++++ b/drivers/staging/exfat/exfat_super.c
+@@ -2167,7 +2167,7 @@ static int ffsRemoveDir(struct inode *inode, struct file_id_t *fid)
+ 	clu_to_free.flags = fid->flags;
+ 
+ 	if (!is_dir_empty(sb, &clu_to_free)) {
+-		ret = -EEXIST;
++		ret = -ENOTEMPTY;
+ 		goto out;
+ 	}
+ 

commit ad03f80f7b7229f39623f6a11fe8cb07cab1c05e
+Author: Valdis Kletnieks 
+Date:   Mon Nov 11 21:09:56 2019 -0500
+
+    staging: exfat: Collapse redundant return code translations
+    
+    Now that we no longer use odd internal return codes, we can
+    heave the translation code over the side, and just pass the
+    error code back up the call chain.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191112021000.42091-9-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
+index 7941944ec09f..3e13e002cd14 100644
+--- a/drivers/staging/exfat/exfat_super.c
++++ b/drivers/staging/exfat/exfat_super.c
+@@ -650,7 +650,7 @@ static int ffsCreateFile(struct inode *inode, char *path, u8 mode,
+ 	struct uni_name_t uni_name;
+ 	struct super_block *sb = inode->i_sb;
+ 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+-	int ret;
++	int ret = 0;
+ 
+ 	/* check the validity of pointer parameters */
+ 	if (!fid || !path || (*path == '\0'))
+@@ -2366,19 +2366,9 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+ 	pr_debug("%s entered\n", __func__);
+ 
+ 	err = ffsCreateFile(dir, (u8 *)dentry->d_name.name, FM_REGULAR, &fid);
+-	if (err) {
+-		if (err == -EINVAL)
+-			err = -EINVAL;
+-		else if (err == -EEXIST)
+-			err = -EEXIST;
+-		else if (err == -ENOSPC)
+-			err = -ENOSPC;
+-		else if (err == -ENAMETOOLONG)
+-			err = -ENAMETOOLONG;
+-		else
+-			err = -EIO;
++	if (err)
+ 		goto out;
+-	}
++
+ 	INC_IVERSION(dir);
+ 	curtime = current_time(dir);
+ 	dir->i_ctime = curtime;
+@@ -2543,13 +2533,9 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry)
+ 	EXFAT_I(inode)->fid.size = i_size_read(inode);
+ 
+ 	err = ffsRemoveFile(dir, &(EXFAT_I(inode)->fid));
+-	if (err) {
+-		if (err == -EPERM)
+-			err = -EPERM;
+-		else
+-			err = -EIO;
++	if (err)
+ 		goto out;
+-	}
++
+ 	INC_IVERSION(dir);
+ 	curtime = current_time(dir);
+ 	dir->i_mtime = curtime;
+@@ -2589,27 +2575,14 @@ static int exfat_symlink(struct inode *dir, struct dentry *dentry,
+ 	pr_debug("%s entered\n", __func__);
+ 
+ 	err = ffsCreateFile(dir, (u8 *)dentry->d_name.name, FM_SYMLINK, &fid);
+-	if (err) {
+-		if (err == -EINVAL)
+-			err = -EINVAL;
+-		else if (err == -EEXIST)
+-			err = -EEXIST;
+-		else if (err == -ENOSPC)
+-			err = -ENOSPC;
+-		else
+-			err = -EIO;
++	if (err)
+ 		goto out;
+-	}
++
+ 
+ 	err = ffsWriteFile(dir, &fid, (char *)target, len, &ret);
+ 
+ 	if (err) {
+ 		ffsRemoveFile(dir, &fid);
+-
+-		if (err == -ENOSPC)
+-			err = -ENOSPC;
+-		else
+-			err = -EIO;
+ 		goto out;
+ 	}
+ 
+@@ -2666,19 +2639,9 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+ 	pr_debug("%s entered\n", __func__);
+ 
+ 	err = ffsCreateDir(dir, (u8 *)dentry->d_name.name, &fid);
+-	if (err) {
+-		if (err == -EINVAL)
+-			err = -EINVAL;
+-		else if (err == -EEXIST)
+-			err = -EEXIST;
+-		else if (err == -ENOSPC)
+-			err = -ENOSPC;
+-		else if (err == -ENAMETOOLONG)
+-			err = -ENAMETOOLONG;
+-		else
+-			err = -EIO;
++	if (err)
+ 		goto out;
+-	}
++
+ 	INC_IVERSION(dir);
+ 	curtime = current_time(dir);
+ 	dir->i_ctime = curtime;
+@@ -2727,19 +2690,9 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
+ 	EXFAT_I(inode)->fid.size = i_size_read(inode);
+ 
+ 	err = ffsRemoveDir(dir, &(EXFAT_I(inode)->fid));
+-	if (err) {
+-		if (err == -EINVAL)
+-			err = -EINVAL;
+-		else if (err == -EEXIST)
+-			err = -ENOTEMPTY;
+-		else if (err == -ENOENT)
+-			err = -ENOENT;
+-		else if (err == -EBUSY)
+-			err = -EBUSY;
+-		else
+-			err = -EIO;
++	if (err)
+ 		goto out;
+-	}
++
+ 	INC_IVERSION(dir);
+ 	curtime = current_time(dir);
+ 	dir->i_mtime = curtime;
+@@ -2787,21 +2740,9 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 
+ 	err = ffsMoveFile(old_dir, &(EXFAT_I(old_inode)->fid), new_dir,
+ 			  new_dentry);
+-	if (err) {
+-		if (err == -EPERM)
+-			err = -EPERM;
+-		else if (err == -EINVAL)
+-			err = -EINVAL;
+-		else if (err == -EEXIST)
+-			err = -EEXIST;
+-		else if (err == -ENOENT)
+-			err = -ENOENT;
+-		else if (err == -ENOSPC)
+-			err = -ENOSPC;
+-		else
+-			err = -EIO;
++	if (err)
+ 		goto out;
+-	}
++
+ 	INC_IVERSION(new_dir);
+ 	curtime = current_time(new_dir);
+ 	new_dir->i_ctime = curtime;
+@@ -3161,12 +3102,7 @@ static int exfat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
+ 
+ 	err = ffsMapCluster(inode, clu_offset, &cluster);
+ 
+-	if (err) {
+-		if (err == -ENOSPC)
+-			return -ENOSPC;
+-		else
+-			return -EIO;
+-	} else if (cluster != CLUSTER_32(~0)) {
++	if (!err && (cluster != CLUSTER_32(~0))) {
+ 		*phys = START_SECTOR(cluster) + sec_offset;
+ 		*mapped_blocks = p_fs->sectors_per_clu - sec_offset;
+ 	}

commit 4b18672132332d3ec429ea9370d0b380dae730cd
+Author: Valdis Kletnieks 
+Date:   Mon Nov 11 21:09:55 2019 -0500
+
+    staging: exfat: Clean up return codes - FFS_SUCCESS
+    
+    Convert FFS_SUCCESS to 0.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191112021000.42091-8-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index b3fc9bb06c24..72cf40e123de 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -208,9 +208,6 @@ static inline u16 get_row_index(u16 i)
+ #define FM_REGULAR              0x00
+ #define FM_SYMLINK              0x40
+ 
+-/* return values */
+-#define FFS_SUCCESS             0
+-
+ #define NUM_UPCASE              2918
+ 
+ #define DOS_CUR_DIR_NAME        ".          "
+diff --git a/drivers/staging/exfat/exfat_cache.c b/drivers/staging/exfat/exfat_cache.c
+index 467b93630d86..28a67f8139ea 100644
+--- a/drivers/staging/exfat/exfat_cache.c
++++ b/drivers/staging/exfat/exfat_cache.c
+@@ -462,7 +462,7 @@ u8 *FAT_getblk(struct super_block *sb, sector_t sec)
+ 
+ 	FAT_cache_insert_hash(sb, bp);
+ 
+-	if (sector_read(sb, sec, &bp->buf_bh, 1) != FFS_SUCCESS) {
++	if (sector_read(sb, sec, &bp->buf_bh, 1) != 0) {
+ 		FAT_cache_remove_hash(bp);
+ 		bp->drv = -1;
+ 		bp->sec = ~0;
+@@ -582,7 +582,7 @@ static u8 *__buf_getblk(struct super_block *sb, sector_t sec)
+ 
+ 	buf_cache_insert_hash(sb, bp);
+ 
+-	if (sector_read(sb, sec, &bp->buf_bh, 1) != FFS_SUCCESS) {
++	if (sector_read(sb, sec, &bp->buf_bh, 1) != 0) {
+ 		buf_cache_remove_hash(bp);
+ 		bp->drv = -1;
+ 		bp->sec = ~0;
+diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
+index ffcad6867ecb..1f0ef94bdd47 100644
+--- a/drivers/staging/exfat/exfat_core.c
++++ b/drivers/staging/exfat/exfat_core.c
+@@ -102,7 +102,7 @@ void fs_set_vol_flags(struct super_block *sb, u32 new_flag)
+ 	if (p_fs->vol_type == EXFAT) {
+ 		if (!p_fs->pbr_bh) {
+ 			if (sector_read(sb, p_fs->PBR_sector,
+-					&p_fs->pbr_bh, 1) != FFS_SUCCESS)
++					&p_fs->pbr_bh, 1) != 0)
+ 				return;
+ 		}
+ 
+@@ -139,7 +139,7 @@ void fs_error(struct super_block *sb)
+ s32 clear_cluster(struct super_block *sb, u32 clu)
+ {
+ 	sector_t s, n;
+-	s32 ret = FFS_SUCCESS;
++	s32 ret = 0;
+ 	struct buffer_head *tmp_bh = NULL;
+ 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+ 	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
+@@ -154,12 +154,12 @@ s32 clear_cluster(struct super_block *sb, u32 clu)
+ 
+ 	for (; s < n; s++) {
+ 		ret = sector_read(sb, s, &tmp_bh, 0);
+-		if (ret != FFS_SUCCESS)
++		if (ret != 0)
+ 			return ret;
+ 
+ 		memset((char *)tmp_bh->b_data, 0x0, p_bd->sector_size);
+ 		ret = sector_write(sb, s, tmp_bh, 0);
+-		if (ret != FFS_SUCCESS)
++		if (ret != 0)
+ 			break;
+ 	}
+ 
+@@ -251,7 +251,7 @@ s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc,
+ 			}
+ 		}
+ 
+-		if (set_alloc_bitmap(sb, new_clu - 2) != FFS_SUCCESS)
++		if (set_alloc_bitmap(sb, new_clu - 2) != 0)
+ 			return -EIO;
+ 
+ 		num_clusters++;
+@@ -370,7 +370,7 @@ void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
+ 					buf_release(sb, sector + i);
+ 			}
+ 
+-			if (clr_alloc_bitmap(sb, clu - 2) != FFS_SUCCESS)
++			if (clr_alloc_bitmap(sb, clu - 2) != 0)
+ 				break;
+ 			clu++;
+ 
+@@ -387,7 +387,7 @@ void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
+ 					buf_release(sb, sector + i);
+ 			}
+ 
+-			if (clr_alloc_bitmap(sb, clu - 2) != FFS_SUCCESS)
++			if (clr_alloc_bitmap(sb, clu - 2) != 0)
+ 				break;
+ 
+ 			if (FAT_read(sb, clu, &clu) == -1)
+@@ -552,7 +552,7 @@ s32 load_alloc_bitmap(struct super_block *sb)
+ 				for (j = 0; j < p_fs->map_sectors; j++) {
+ 					p_fs->vol_amap[j] = NULL;
+ 					ret = sector_read(sb, sector + j, &p_fs->vol_amap[j], 1);
+-					if (ret != FFS_SUCCESS) {
++					if (ret != 0) {
+ 						/*  release all buffers and free vol_amap */
+ 						i = 0;
+ 						while (i < j)
+@@ -565,7 +565,7 @@ s32 load_alloc_bitmap(struct super_block *sb)
+ 				}
+ 
+ 				p_fs->pbr_bh = NULL;
+-				return FFS_SUCCESS;
++				return 0;
+ 			}
+ 		}
+ 
+@@ -721,7 +721,7 @@ static s32 __load_upcase_table(struct super_block *sb, sector_t sector,
+ 
+ 	while (sector < end_sector) {
+ 		ret = sector_read(sb, sector, &tmp_bh, 1);
+-		if (ret != FFS_SUCCESS) {
++		if (ret != 0) {
+ 			pr_debug("sector read (0x%llX)fail\n",
+ 				 (unsigned long long)sector);
+ 			goto error;
+@@ -772,7 +772,7 @@ static s32 __load_upcase_table(struct super_block *sb, sector_t sector,
+ 	if (index >= 0xFFFF && utbl_checksum == checksum) {
+ 		if (tmp_bh)
+ 			brelse(tmp_bh);
+-		return FFS_SUCCESS;
++		return 0;
+ 	}
+ 	ret = -EINVAL;
+ error:
+@@ -833,7 +833,7 @@ static s32 __load_default_upcase_table(struct super_block *sb)
+ 	}
+ 
+ 	if (index >= 0xFFFF)
+-		return FFS_SUCCESS;
++		return 0;
+ 
+ error:
+ 	/* FATAL error: default upcase table has error */
+@@ -878,9 +878,9 @@ s32 load_upcase_table(struct super_block *sb)
+ 			sector = START_SECTOR(tbl_clu);
+ 			num_sectors = ((tbl_size - 1) >> p_bd->sector_size_bits) + 1;
+ 			if (__load_upcase_table(sb, sector, num_sectors,
+-						GET32_A(ep->checksum)) != FFS_SUCCESS)
++						GET32_A(ep->checksum)) != 0)
+ 				break;
+-			return FFS_SUCCESS;
++			return 0;
+ 		}
+ 		if (FAT_read(sb, clu.dir, &clu.dir) != 0)
+ 			return -EIO;
+@@ -1251,7 +1251,7 @@ s32 fat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir, s32 entry,
+ 	init_dos_entry(dos_ep, type, start_clu);
+ 	buf_modify(sb, sector);
+ 
+-	return FFS_SUCCESS;
++	return 0;
+ }
+ 
+ s32 exfat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+@@ -1281,7 +1281,7 @@ s32 exfat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+ 	init_strm_entry(strm_ep, flags, start_clu, size);
+ 	buf_modify(sb, sector);
+ 
+-	return FFS_SUCCESS;
++	return 0;
+ }
+ 
+ static s32 fat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir,
+@@ -1332,7 +1332,7 @@ static s32 fat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir,
+ 		buf_modify(sb, sector);
+ 	}
+ 
+-	return FFS_SUCCESS;
++	return 0;
+ }
+ 
+ static s32 exfat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir,
+@@ -1378,7 +1378,7 @@ static s32 exfat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir,
+ 
+ 	update_dir_checksum(sb, p_dir, entry);
+ 
+-	return FFS_SUCCESS;
++	return 0;
+ }
+ 
+ void init_dos_entry(struct dos_dentry_t *ep, u32 type, u32 start_clu)
+@@ -1599,7 +1599,7 @@ static s32 _walk_fat_chain(struct super_block *sb, struct chain_t *p_dir,
+ 
+ 	if (clu)
+ 		*clu = cur_clu;
+-	return FFS_SUCCESS;
++	return 0;
+ }
+ 
+ s32 find_location(struct super_block *sb, struct chain_t *p_dir, s32 entry,
+@@ -1618,7 +1618,7 @@ s32 find_location(struct super_block *sb, struct chain_t *p_dir, s32 entry,
+ 		*sector += p_fs->root_start_sector;
+ 	} else {
+ 		ret = _walk_fat_chain(sb, p_dir, off, &clu);
+-		if (ret != FFS_SUCCESS)
++		if (ret != 0)
+ 			return ret;
+ 
+ 		/* byte offset in cluster */
+@@ -1631,7 +1631,7 @@ s32 find_location(struct super_block *sb, struct chain_t *p_dir, s32 entry,
+ 		*sector = off >> p_bd->sector_size_bits;
+ 		*sector += START_SECTOR(clu);
+ 	}
+-	return FFS_SUCCESS;
++	return 0;
+ }
+ 
+ struct dentry_t *get_entry_with_sector(struct super_block *sb, sector_t sector,
+@@ -1654,7 +1654,7 @@ struct dentry_t *get_entry_in_dir(struct super_block *sb, struct chain_t *p_dir,
+ 	sector_t sec;
+ 	u8 *buf;
+ 
+-	if (find_location(sb, p_dir, entry, &sec, &off) != FFS_SUCCESS)
++	if (find_location(sb, p_dir, entry, &sec, &off) != 0)
+ 		return NULL;
+ 
+ 	buf = buf_getblk(sb, sec);
+@@ -1708,7 +1708,7 @@ struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb,
+ 
+ 	byte_offset = entry << DENTRY_SIZE_BITS;
+ 	ret = _walk_fat_chain(sb, p_dir, byte_offset, &clu);
+-	if (ret != FFS_SUCCESS)
++	if (ret != 0)
+ 		return NULL;
+ 
+ 	/* byte offset in cluster */
+@@ -1903,7 +1903,7 @@ static s32 __write_partial_entries_in_entry_set(struct super_block *sb,
+ 	}
+ 
+ 	pr_debug("%s exited successfully\n", __func__);
+-	return FFS_SUCCESS;
++	return 0;
+ err_out:
+ 	pr_debug("%s failed\n", __func__);
+ 	return -EINVAL;
+@@ -1942,7 +1942,7 @@ s32 write_partial_entries_in_entry_set(struct super_block *sb,
+ 	byte_offset += ((void **)ep - &es->__buf) + es->offset;
+ 
+ 	ret = _walk_fat_chain(sb, &dir, byte_offset, &clu);
+-	if (ret != FFS_SUCCESS)
++	if (ret != 0)
+ 		return ret;
+ 
+ 	/* byte offset in cluster */
+@@ -2086,7 +2086,7 @@ s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_entries
+ 		if (ret < 1)
+ 			return -EIO;
+ 
+-		if (clear_cluster(sb, clu.dir) != FFS_SUCCESS)
++		if (clear_cluster(sb, clu.dir) != 0)
+ 			return -EIO;
+ 
+ 		/* (2) append to the FAT chain */
+@@ -2597,7 +2597,7 @@ s32 get_num_entries_and_dos_name(struct super_block *sb, struct chain_t *p_dir,
+ 
+ 	*entries = num_entries;
+ 
+-	return FFS_SUCCESS;
++	return 0;
+ }
+ 
+ void get_uni_name_from_dos_entry(struct super_block *sb,
+@@ -2833,7 +2833,7 @@ s32 fat_generate_dos_name(struct super_block *sb, struct chain_t *p_dir,
+ 	fat_attach_count_to_dos_name(p_dosname->name, count);
+ 
+ 	/* Now dos_name has DOS~????.EXT */
+-	return FFS_SUCCESS;
++	return 0;
+ }
+ 
+ void fat_attach_count_to_dos_name(u8 *dosname, s32 count)
+@@ -2975,7 +2975,7 @@ s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir,
+ 	p_dir->size = (s32)(fid->size >> p_fs->cluster_size_bits);
+ 	p_dir->flags = fid->flags;
+ 
+-	return FFS_SUCCESS;
++	return 0;
+ }
+ 
+ /*
+@@ -3067,7 +3067,7 @@ s32 fat16_mount(struct super_block *sb, struct pbr_sector_t *p_pbr)
+ 
+ 	p_fs->fs_func = &fat_fs_func;
+ 
+-	return FFS_SUCCESS;
++	return 0;
+ }
+ 
+ s32 fat32_mount(struct super_block *sb, struct pbr_sector_t *p_pbr)
+@@ -3120,7 +3120,7 @@ s32 fat32_mount(struct super_block *sb, struct pbr_sector_t *p_pbr)
+ 
+ 	p_fs->fs_func = &fat_fs_func;
+ 
+-	return FFS_SUCCESS;
++	return 0;
+ }
+ 
+ static struct fs_func exfat_fs_func = {
+@@ -3195,7 +3195,7 @@ s32 exfat_mount(struct super_block *sb, struct pbr_sector_t *p_pbr)
+ 
+ 	p_fs->fs_func = &exfat_fs_func;
+ 
+-	return FFS_SUCCESS;
++	return 0;
+ }
+ 
+ s32 create_dir(struct inode *inode, struct chain_t *p_dir,
+@@ -3231,7 +3231,7 @@ s32 create_dir(struct inode *inode, struct chain_t *p_dir,
+ 		return -ENOSPC;
+ 
+ 	ret = clear_cluster(sb, clu.dir);
+-	if (ret != FFS_SUCCESS)
++	if (ret != 0)
+ 		return ret;
+ 
+ 	if (p_fs->vol_type == EXFAT) {
+@@ -3249,11 +3249,11 @@ s32 create_dir(struct inode *inode, struct chain_t *p_dir,
+ 
+ 		ret = fs_func->init_dir_entry(sb, &clu, 0, TYPE_DIR, clu.dir,
+ 					      0);
+-		if (ret != FFS_SUCCESS)
++		if (ret != 0)
+ 			return ret;
+ 
+ 		ret = fs_func->init_ext_entry(sb, &clu, 0, 1, NULL, &dot_name);
+-		if (ret != FFS_SUCCESS)
++		if (ret != 0)
+ 			return ret;
+ 
+ 		memcpy(dot_name.name, DOS_PAR_DIR_NAME, DOS_NAME_LENGTH);
+@@ -3265,12 +3265,12 @@ s32 create_dir(struct inode *inode, struct chain_t *p_dir,
+ 			ret = fs_func->init_dir_entry(sb, &clu, 1, TYPE_DIR,
+ 						      p_dir->dir, 0);
+ 
+-		if (ret != FFS_SUCCESS)
++		if (ret != 0)
+ 			return ret;
+ 
+ 		ret = p_fs->fs_func->init_ext_entry(sb, &clu, 1, 1, NULL,
+ 						    &dot_name);
+-		if (ret != FFS_SUCCESS)
++		if (ret != 0)
+ 			return ret;
+ 	}
+ 
+@@ -3278,12 +3278,12 @@ s32 create_dir(struct inode *inode, struct chain_t *p_dir,
+ 	/* make sub-dir entry in parent directory */
+ 	ret = fs_func->init_dir_entry(sb, p_dir, dentry, TYPE_DIR, clu.dir,
+ 				      size);
+-	if (ret != FFS_SUCCESS)
++	if (ret != 0)
+ 		return ret;
+ 
+ 	ret = fs_func->init_ext_entry(sb, p_dir, dentry, num_entries, p_uniname,
+ 				      &dos_name);
+-	if (ret != FFS_SUCCESS)
++	if (ret != 0)
+ 		return ret;
+ 
+ 	fid->dir.dir = p_dir->dir;
+@@ -3300,7 +3300,7 @@ s32 create_dir(struct inode *inode, struct chain_t *p_dir,
+ 	fid->rwoffset = 0;
+ 	fid->hint_last_off = -1;
+ 
+-	return FFS_SUCCESS;
++	return 0;
+ }
+ 
+ s32 create_file(struct inode *inode, struct chain_t *p_dir,
+@@ -3328,12 +3328,12 @@ s32 create_file(struct inode *inode, struct chain_t *p_dir,
+ 	 */
+ 	ret = fs_func->init_dir_entry(sb, p_dir, dentry, TYPE_FILE | mode,
+ 				      CLUSTER_32(0), 0);
+-	if (ret != FFS_SUCCESS)
++	if (ret != 0)
+ 		return ret;
+ 
+ 	ret = fs_func->init_ext_entry(sb, p_dir, dentry, num_entries, p_uniname,
+ 				      &dos_name);
+-	if (ret != FFS_SUCCESS)
++	if (ret != 0)
+ 		return ret;
+ 
+ 	fid->dir.dir = p_dir->dir;
+@@ -3350,7 +3350,7 @@ s32 create_file(struct inode *inode, struct chain_t *p_dir,
+ 	fid->rwoffset = 0;
+ 	fid->hint_last_off = -1;
+ 
+-	return FFS_SUCCESS;
++	return 0;
+ }
+ 
+ void remove_file(struct inode *inode, struct chain_t *p_dir, s32 entry)
+@@ -3458,7 +3458,7 @@ s32 rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry,
+ 		ret = fs_func->init_ext_entry(sb, p_dir, newentry,
+ 					      num_new_entries, p_uniname,
+ 					      &dos_name);
+-		if (ret != FFS_SUCCESS)
++		if (ret != 0)
+ 			return ret;
+ 
+ 		fs_func->delete_dir_entry(sb, p_dir, oldentry, 0,
+@@ -3477,14 +3477,14 @@ s32 rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry,
+ 		ret = fs_func->init_ext_entry(sb, p_dir, oldentry,
+ 					      num_new_entries, p_uniname,
+ 					      &dos_name);
+-		if (ret != FFS_SUCCESS)
++		if (ret != 0)
+ 			return ret;
+ 
+ 		fs_func->delete_dir_entry(sb, p_dir, oldentry, num_new_entries,
+ 					  num_old_entries);
+ 	}
+ 
+-	return FFS_SUCCESS;
++	return 0;
+ }
+ 
+ s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
+@@ -3580,7 +3580,7 @@ s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
+ 
+ 	ret = fs_func->init_ext_entry(sb, p_newdir, newentry, num_new_entries,
+ 				      p_uniname, &dos_name);
+-	if (ret != FFS_SUCCESS)
++	if (ret != 0)
+ 		return ret;
+ 
+ 	fs_func->delete_dir_entry(sb, p_olddir, oldentry, 0, num_old_entries);
+@@ -3591,7 +3591,7 @@ s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
+ 
+ 	fid->entry = newentry;
+ 
+-	return FFS_SUCCESS;
++	return 0;
+ }
+ 
+ /*
+@@ -3614,7 +3614,7 @@ int sector_read(struct super_block *sb, sector_t sec, struct buffer_head **bh,
+ 
+ 	if (!p_fs->dev_ejected) {
+ 		ret = bdev_read(sb, sec, bh, 1, read);
+-		if (ret != FFS_SUCCESS)
++		if (ret != 0)
+ 			p_fs->dev_ejected = 1;
+ 	}
+ 
+@@ -3643,7 +3643,7 @@ int sector_write(struct super_block *sb, sector_t sec, struct buffer_head *bh,
+ 
+ 	if (!p_fs->dev_ejected) {
+ 		ret = bdev_write(sb, sec, bh, 1, sync);
+-		if (ret != FFS_SUCCESS)
++		if (ret != 0)
+ 			p_fs->dev_ejected = 1;
+ 	}
+ 
+@@ -3666,7 +3666,7 @@ int multi_sector_read(struct super_block *sb, sector_t sec,
+ 
+ 	if (!p_fs->dev_ejected) {
+ 		ret = bdev_read(sb, sec, bh, num_secs, read);
+-		if (ret != FFS_SUCCESS)
++		if (ret != 0)
+ 			p_fs->dev_ejected = 1;
+ 	}
+ 
+@@ -3694,7 +3694,7 @@ int multi_sector_write(struct super_block *sb, sector_t sec,
+ 
+ 	if (!p_fs->dev_ejected) {
+ 		ret = bdev_write(sb, sec, bh, num_secs, sync);
+-		if (ret != FFS_SUCCESS)
++		if (ret != 0)
+ 			p_fs->dev_ejected = 1;
+ 	}
+ 
+diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
+index 2f199d78bfa6..7941944ec09f 100644
+--- a/drivers/staging/exfat/exfat_super.c
++++ b/drivers/staging/exfat/exfat_super.c
+@@ -373,7 +373,7 @@ static int ffsMountVol(struct super_block *sb)
+ 		sb_set_blocksize(sb, p_bd->sector_size);
+ 
+ 	/* read Sector 0 */
+-	if (sector_read(sb, 0, &tmp_bh, 1) != FFS_SUCCESS) {
++	if (sector_read(sb, 0, &tmp_bh, 1) != 0) {
+ 		ret = -EIO;
+ 		goto out;
+ 	}
+@@ -452,7 +452,7 @@ static int ffsMountVol(struct super_block *sb)
+ static int ffsUmountVol(struct super_block *sb)
+ {
+ 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+-	int err = FFS_SUCCESS;
++	int err = 0;
+ 
+ 	pr_info("[EXFAT] trying to unmount...\n");
+ 
+@@ -493,7 +493,7 @@ static int ffsUmountVol(struct super_block *sb)
+ 
+ static int ffsGetVolInfo(struct super_block *sb, struct vol_info_t *info)
+ {
+-	int err = FFS_SUCCESS;
++	int err = 0;
+ 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+ 
+ 	/* check the validity of pointer parameters */
+@@ -523,7 +523,7 @@ static int ffsGetVolInfo(struct super_block *sb, struct vol_info_t *info)
+ 
+ static int ffsSyncVol(struct super_block *sb, bool do_sync)
+ {
+-	int err = FFS_SUCCESS;
++	int err = 0;
+ 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+ 
+ 	/* acquire the lock for file system critical section */
+@@ -776,13 +776,13 @@ static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer,
+ 
+ 		if ((offset == 0) && (oneblkread == p_bd->sector_size)) {
+ 			if (sector_read(sb, LogSector, &tmp_bh, 1) !=
+-			    FFS_SUCCESS)
++			    0)
+ 				goto err_out;
+ 			memcpy((char *)buffer + read_bytes,
+ 			       (char *)tmp_bh->b_data, (s32)oneblkread);
+ 		} else {
+ 			if (sector_read(sb, LogSector, &tmp_bh, 1) !=
+-			    FFS_SUCCESS)
++			    0)
+ 				goto err_out;
+ 			memcpy((char *)buffer + read_bytes,
+ 			       (char *)tmp_bh->b_data + offset,
+@@ -852,7 +852,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
+ 	if (count == 0) {
+ 		if (wcount)
+ 			*wcount = 0;
+-		ret = FFS_SUCCESS;
++		ret = 0;
+ 		goto out;
+ 	}
+ 
+@@ -962,12 +962,12 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
+ 
+ 		if ((offset == 0) && (oneblkwrite == p_bd->sector_size)) {
+ 			if (sector_read(sb, LogSector, &tmp_bh, 0) !=
+-			    FFS_SUCCESS)
++			    0)
+ 				goto err_out;
+ 			memcpy((char *)tmp_bh->b_data,
+ 			       (char *)buffer + write_bytes, (s32)oneblkwrite);
+ 			if (sector_write(sb, LogSector, tmp_bh, 0) !=
+-			    FFS_SUCCESS) {
++			    0) {
+ 				brelse(tmp_bh);
+ 				goto err_out;
+ 			}
+@@ -975,18 +975,18 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
+ 			if ((offset > 0) ||
+ 			    ((fid->rwoffset + oneblkwrite) < fid->size)) {
+ 				if (sector_read(sb, LogSector, &tmp_bh, 1) !=
+-				    FFS_SUCCESS)
++				    0)
+ 					goto err_out;
+ 			} else {
+ 				if (sector_read(sb, LogSector, &tmp_bh, 0) !=
+-				    FFS_SUCCESS)
++				    0)
+ 					goto err_out;
+ 			}
+ 
+ 			memcpy((char *)tmp_bh->b_data + offset,
+ 			       (char *)buffer + write_bytes, (s32)oneblkwrite);
+ 			if (sector_write(sb, LogSector, tmp_bh, 0) !=
+-			    FFS_SUCCESS) {
++			    0) {
+ 				brelse(tmp_bh);
+ 				goto err_out;
+ 			}
+@@ -1100,7 +1100,7 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size)
+ 	}
+ 
+ 	if (old_size <= new_size) {
+-		ret = FFS_SUCCESS;
++		ret = 0;
+ 		goto out;
+ 	}
+ 
+@@ -1319,7 +1319,7 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid,
+ 		ret = move_file(new_parent_inode, &olddir, dentry, &newdir,
+ 				&uni_name, fid);
+ 
+-	if ((ret == FFS_SUCCESS) && new_inode) {
++	if ((ret == 0) && new_inode) {
+ 		/* delete entries of new_dir */
+ 		ep = get_entry_in_dir(sb, p_dir, new_entry, NULL);
+ 		if (!ep)
+@@ -1350,7 +1350,7 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid,
+ static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid)
+ {
+ 	s32 dentry;
+-	int ret = FFS_SUCCESS;
++	int ret = 0;
+ 	struct chain_t dir, clu_to_free;
+ 	struct dentry_t *ep;
+ 	struct super_block *sb = inode->i_sb;
+@@ -1414,7 +1414,7 @@ static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid)
+ static int ffsSetAttr(struct inode *inode, u32 attr)
+ {
+ 	u32 type;
+-	int ret = FFS_SUCCESS;
++	int ret = 0;
+ 	sector_t sector = 0;
+ 	struct dentry_t *ep;
+ 	struct super_block *sb = inode->i_sb;
+@@ -1426,7 +1426,7 @@ static int ffsSetAttr(struct inode *inode, u32 attr)
+ 	if (fid->attr == attr) {
+ 		if (p_fs->dev_ejected)
+ 			return -EIO;
+-		return FFS_SUCCESS;
++		return 0;
+ 	}
+ 
+ 	if (is_dir) {
+@@ -1434,7 +1434,7 @@ static int ffsSetAttr(struct inode *inode, u32 attr)
+ 		    (fid->entry == -1)) {
+ 			if (p_fs->dev_ejected)
+ 				return -EIO;
+-			return FFS_SUCCESS;
++			return 0;
+ 		}
+ 	}
+ 
+@@ -1503,7 +1503,7 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info)
+ {
+ 	sector_t sector = 0;
+ 	s32 count;
+-	int ret = FFS_SUCCESS;
++	int ret = 0;
+ 	struct chain_t dir;
+ 	struct uni_name_t uni_name;
+ 	struct timestamp_t tm;
+@@ -1655,7 +1655,7 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info)
+ static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info)
+ {
+ 	sector_t sector = 0;
+-	int ret = FFS_SUCCESS;
++	int ret = 0;
+ 	struct timestamp_t tm;
+ 	struct dentry_t *ep, *ep2;
+ 	struct entry_set_cache_t *es = NULL;
+@@ -1674,7 +1674,7 @@ static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info)
+ 		    (fid->entry == -1)) {
+ 			if (p_fs->dev_ejected)
+ 				ret = -EIO;
+-			ret = FFS_SUCCESS;
++			ret = 0;
+ 			goto out;
+ 		}
+ 	}
+@@ -1745,7 +1745,7 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
+ 	s32 num_clusters, num_alloced;
+ 	bool modified = false;
+ 	u32 last_clu;
+-	int ret = FFS_SUCCESS;
++	int ret = 0;
+ 	sector_t sector = 0;
+ 	struct chain_t new_clu;
+ 	struct dentry_t *ep;
+@@ -1898,7 +1898,7 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
+ 
+ static int ffsCreateDir(struct inode *inode, char *path, struct file_id_t *fid)
+ {
+-	int ret = FFS_SUCCESS;
++	int ret = 0;
+ 	struct chain_t dir;
+ 	struct uni_name_t uni_name;
+ 	struct super_block *sb = inode->i_sb;
+@@ -1939,7 +1939,7 @@ static int ffsCreateDir(struct inode *inode, char *path, struct file_id_t *fid)
+ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
+ {
+ 	int i, dentry, clu_offset;
+-	int ret = FFS_SUCCESS;
++	int ret = 0;
+ 	s32 dentries_per_clu, dentries_per_clu_bits = 0;
+ 	u32 type;
+ 	sector_t sector;
+@@ -2138,7 +2138,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
+ static int ffsRemoveDir(struct inode *inode, struct file_id_t *fid)
+ {
+ 	s32 dentry;
+-	int ret = FFS_SUCCESS;
++	int ret = 0;
+ 	struct chain_t dir, clu_to_free;
+ 	struct super_block *sb = inode->i_sb;
+ 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);

commit 97eab6cee3a6ac679a2f531a248df3c994182522
+Author: Valdis Kletnieks 
+Date:   Mon Nov 11 21:09:54 2019 -0500
+
+    staging: exfat: Clean up return codes - remove unused codes
+    
+    There are 6 FFS_* error values not used at all. Remove them.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191112021000.42091-7-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index 443fafe1d89d..b3fc9bb06c24 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -210,12 +210,6 @@ static inline u16 get_row_index(u16 i)
+ 
+ /* return values */
+ #define FFS_SUCCESS             0
+-#define FFS_MOUNTED             3
+-#define FFS_NOTMOUNTED          4
+-#define FFS_ALIGNMENTERR        5
+-#define FFS_SEMAPHOREERR        6
+-#define FFS_NOTOPENED           12
+-#define FFS_MAXOPENED           13
+ 
+ #define NUM_UPCASE              2918
+ 

commit 0a7ef8d9483b96bea89c8b99b7b509697d48701d
+Author: Valdis Kletnieks 
+Date:   Mon Nov 11 21:09:53 2019 -0500
+
+    staging: exfat: Clean up return codes - FFS_ERROR
+    
+    Convert FFS_ERROR to -EINVAL
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191112021000.42091-6-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index 7a817405c624..443fafe1d89d 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -216,7 +216,6 @@ static inline u16 get_row_index(u16 i)
+ #define FFS_SEMAPHOREERR        6
+ #define FFS_NOTOPENED           12
+ #define FFS_MAXOPENED           13
+-#define FFS_ERROR               19
+ 
+ #define NUM_UPCASE              2918
+ 
+diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
+index 2f6e9d724625..ffcad6867ecb 100644
+--- a/drivers/staging/exfat/exfat_core.c
++++ b/drivers/staging/exfat/exfat_core.c
+@@ -699,7 +699,7 @@ void sync_alloc_bitmap(struct super_block *sb)
+ static s32 __load_upcase_table(struct super_block *sb, sector_t sector,
+ 			       u32 num_sectors, u32 utbl_checksum)
+ {
+-	int i, ret = FFS_ERROR;
++	int i, ret = -EINVAL;
+ 	u32 j;
+ 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+ 	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
+@@ -774,7 +774,7 @@ static s32 __load_upcase_table(struct super_block *sb, sector_t sector,
+ 			brelse(tmp_bh);
+ 		return FFS_SUCCESS;
+ 	}
+-	ret = FFS_ERROR;
++	ret = -EINVAL;
+ error:
+ 	if (tmp_bh)
+ 		brelse(tmp_bh);
+@@ -784,7 +784,7 @@ static s32 __load_upcase_table(struct super_block *sb, sector_t sector,
+ 
+ static s32 __load_default_upcase_table(struct super_block *sb)
+ {
+-	int i, ret = FFS_ERROR;
++	int i, ret = -EINVAL;
+ 	u32 j;
+ 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+ 
+@@ -1906,7 +1906,7 @@ static s32 __write_partial_entries_in_entry_set(struct super_block *sb,
+ 	return FFS_SUCCESS;
+ err_out:
+ 	pr_debug("%s failed\n", __func__);
+-	return FFS_ERROR;
++	return -EINVAL;
+ }
+ 
+ /* write back all entries in entry set */
+@@ -1931,7 +1931,7 @@ s32 write_partial_entries_in_entry_set(struct super_block *sb,
+ 
+ 	/* vaidity check */
+ 	if (ep + count  > ((struct dentry_t *)&es->__buf) + es->num_entries)
+-		return FFS_ERROR;
++		return -EINVAL;
+ 
+ 	dir.dir = GET_CLUSTER_FROM_SECTOR(es->sector);
+ 	dir.flags = es->alloc_flag;
+diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
+index a9129b569523..2f199d78bfa6 100644
+--- a/drivers/staging/exfat/exfat_super.c
++++ b/drivers/staging/exfat/exfat_super.c
+@@ -498,7 +498,7 @@ static int ffsGetVolInfo(struct super_block *sb, struct vol_info_t *info)
+ 
+ 	/* check the validity of pointer parameters */
+ 	if (!info)
+-		return FFS_ERROR;
++		return -EINVAL;
+ 
+ 	/* acquire the lock for file system critical section */
+ 	mutex_lock(&p_fs->v_mutex);
+@@ -561,7 +561,7 @@ static int ffsLookupFile(struct inode *inode, char *path, struct file_id_t *fid)
+ 
+ 	/* check the validity of pointer parameters */
+ 	if (!fid || !path || (*path == '\0'))
+-		return FFS_ERROR;
++		return -EINVAL;
+ 
+ 	/* acquire the lock for file system critical section */
+ 	mutex_lock(&p_fs->v_mutex);
+@@ -654,7 +654,7 @@ static int ffsCreateFile(struct inode *inode, char *path, u8 mode,
+ 
+ 	/* check the validity of pointer parameters */
+ 	if (!fid || !path || (*path == '\0'))
+-		return FFS_ERROR;
++		return -EINVAL;
+ 
+ 	/* acquire the lock for file system critical section */
+ 	mutex_lock(&p_fs->v_mutex);
+@@ -703,7 +703,7 @@ static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer,
+ 
+ 	/* check the validity of pointer parameters */
+ 	if (!buffer)
+-		return FFS_ERROR;
++		return -EINVAL;
+ 
+ 	/* acquire the lock for file system critical section */
+ 	mutex_lock(&p_fs->v_mutex);
+@@ -835,7 +835,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
+ 
+ 	/* check the validity of pointer parameters */
+ 	if (!buffer)
+-		return FFS_ERROR;
++		return -EINVAL;
+ 
+ 	/* acquire the lock for file system critical section */
+ 	mutex_lock(&p_fs->v_mutex);
+@@ -1241,7 +1241,7 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid,
+ 
+ 	/* check the validity of pointer parameters */
+ 	if (!new_path || (*new_path == '\0'))
+-		return FFS_ERROR;
++		return -EINVAL;
+ 
+ 	/* acquire the lock for file system critical section */
+ 	mutex_lock(&p_fs->v_mutex);
+@@ -1464,7 +1464,7 @@ static int ffsSetAttr(struct inode *inode, u32 attr)
+ 		if (p_fs->dev_ejected)
+ 			ret = -EIO;
+ 		else
+-			ret = FFS_ERROR;
++			ret = -EINVAL;
+ 
+ 		if (p_fs->vol_type == EXFAT)
+ 			release_entry_set(es);
+@@ -1756,7 +1756,7 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
+ 
+ 	/* check the validity of pointer parameters */
+ 	if (!clu)
+-		return FFS_ERROR;
++		return -EINVAL;
+ 
+ 	/* acquire the lock for file system critical section */
+ 	mutex_lock(&p_fs->v_mutex);
+@@ -1908,7 +1908,7 @@ static int ffsCreateDir(struct inode *inode, char *path, struct file_id_t *fid)
+ 
+ 	/* check the validity of pointer parameters */
+ 	if (!fid || !path || (*path == '\0'))
+-		return FFS_ERROR;
++		return -EINVAL;
+ 
+ 	/* acquire the lock for file system critical section */
+ 	mutex_lock(&p_fs->v_mutex);
+@@ -1954,7 +1954,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
+ 
+ 	/* check the validity of pointer parameters */
+ 	if (!dir_entry)
+-		return FFS_ERROR;
++		return -EINVAL;
+ 
+ 	/* check if the given file ID is opened */
+ 	if (fid->type != TYPE_DIR)

commit 7785913b079fafd461a668034c76d604fe513770
+Author: Valdis Kletnieks 
+Date:   Mon Nov 11 21:09:52 2019 -0500
+
+    staging: exfat: Clean up return codes - FFS_INVALIDFID
+    
+    Covert FFS_INVALIDFID to -EINVAL
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191112021000.42091-5-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index 292af85e3cd2..7a817405c624 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -214,7 +214,6 @@ static inline u16 get_row_index(u16 i)
+ #define FFS_NOTMOUNTED          4
+ #define FFS_ALIGNMENTERR        5
+ #define FFS_SEMAPHOREERR        6
+-#define FFS_INVALIDFID          8
+ #define FFS_NOTOPENED           12
+ #define FFS_MAXOPENED           13
+ #define FFS_ERROR               19
+diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
+index 77e00d007ad3..a9129b569523 100644
+--- a/drivers/staging/exfat/exfat_super.c
++++ b/drivers/staging/exfat/exfat_super.c
+@@ -699,7 +699,7 @@ static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer,
+ 
+ 	/* check the validity of the given file id */
+ 	if (!fid)
+-		return FFS_INVALIDFID;
++		return -EINVAL;
+ 
+ 	/* check the validity of pointer parameters */
+ 	if (!buffer)
+@@ -831,7 +831,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
+ 
+ 	/* check the validity of the given file id */
+ 	if (!fid)
+-		return FFS_INVALIDFID;
++		return -EINVAL;
+ 
+ 	/* check the validity of pointer parameters */
+ 	if (!buffer)
+@@ -1237,7 +1237,7 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid,
+ 
+ 	/* check the validity of the given file id */
+ 	if (!fid)
+-		return FFS_INVALIDFID;
++		return -EINVAL;
+ 
+ 	/* check the validity of pointer parameters */
+ 	if (!new_path || (*new_path == '\0'))
+@@ -1358,7 +1358,7 @@ static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid)
+ 
+ 	/* check the validity of the given file id */
+ 	if (!fid)
+-		return FFS_INVALIDFID;
++		return -EINVAL;
+ 
+ 	/* acquire the lock for file system critical section */
+ 	mutex_lock(&p_fs->v_mutex);
+@@ -2145,7 +2145,7 @@ static int ffsRemoveDir(struct inode *inode, struct file_id_t *fid)
+ 
+ 	/* check the validity of the given file id */
+ 	if (!fid)
+-		return FFS_INVALIDFID;
++		return -EINVAL;
+ 
+ 	dir.dir = fid->dir.dir;
+ 	dir.size = fid->dir.size;

commit f9c53abb42997d5af1232712a39f81c7f1ba1c01
+Author: Valdis Kletnieks 
+Date:   Mon Nov 11 21:09:51 2019 -0500
+
+    staging: exfat: Clean up return codes - FFS_EOF
+    
+    Convert FFS_EOF to return 0 for a zero-length read() as per 'man 2 read'.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191112021000.42091-4-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index 286605262345..292af85e3cd2 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -217,7 +217,6 @@ static inline u16 get_row_index(u16 i)
+ #define FFS_INVALIDFID          8
+ #define FFS_NOTOPENED           12
+ #define FFS_MAXOPENED           13
+-#define FFS_EOF                 15
+ #define FFS_ERROR               19
+ 
+ #define NUM_UPCASE              2918
+diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
+index 1a906579724c..77e00d007ad3 100644
+--- a/drivers/staging/exfat/exfat_super.c
++++ b/drivers/staging/exfat/exfat_super.c
+@@ -723,7 +723,7 @@ static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer,
+ 	if (count == 0) {
+ 		if (rcount)
+ 			*rcount = 0;
+-		ret = FFS_EOF;
++		ret = 0;
+ 		goto out;
+ 	}
+ 

commit a75500c5d3106d1b8f967b26edfcb9f945871516
+Author: Valdis Kletnieks 
+Date:   Mon Nov 11 21:09:50 2019 -0500
+
+    staging: exfat: Clean up return codes - FFS_MEDIAERR
+    
+    Convert FFS_MEDIAERR to (mostly) -ENOENT and -EIO.  Some additional code surgery
+    needed to propogate correct error codes upwards.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191112021000.42091-3-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index 4f9ba235d967..286605262345 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -210,7 +210,6 @@ static inline u16 get_row_index(u16 i)
+ 
+ /* return values */
+ #define FFS_SUCCESS             0
+-#define FFS_MEDIAERR            1
+ #define FFS_MOUNTED             3
+ #define FFS_NOTMOUNTED          4
+ #define FFS_ALIGNMENTERR        5
+diff --git a/drivers/staging/exfat/exfat_blkdev.c b/drivers/staging/exfat/exfat_blkdev.c
+index 81d20e6241c6..0abae041f632 100644
+--- a/drivers/staging/exfat/exfat_blkdev.c
++++ b/drivers/staging/exfat/exfat_blkdev.c
+@@ -40,11 +40,11 @@ int bdev_read(struct super_block *sb, sector_t secno, struct buffer_head **bh,
+ 	long flags = sbi->debug_flags;
+ 
+ 	if (flags & EXFAT_DEBUGFLAGS_ERROR_RW)
+-		return FFS_MEDIAERR;
++		return -EIO;
+ #endif /* CONFIG_EXFAT_KERNEL_DEBUG */
+ 
+ 	if (!p_bd->opened)
+-		return FFS_MEDIAERR;
++		return -ENODEV;
+ 
+ 	if (*bh)
+ 		__brelse(*bh);
+@@ -62,7 +62,7 @@ int bdev_read(struct super_block *sb, sector_t secno, struct buffer_head **bh,
+ 	WARN(!p_fs->dev_ejected,
+ 	     "[EXFAT] No bh, device seems wrong or to be ejected.\n");
+ 
+-	return FFS_MEDIAERR;
++	return -EIO;
+ }
+ 
+ int bdev_write(struct super_block *sb, sector_t secno, struct buffer_head *bh,
+@@ -77,11 +77,11 @@ int bdev_write(struct super_block *sb, sector_t secno, struct buffer_head *bh,
+ 	long flags = sbi->debug_flags;
+ 
+ 	if (flags & EXFAT_DEBUGFLAGS_ERROR_RW)
+-		return FFS_MEDIAERR;
++		return -EIO;
+ #endif /* CONFIG_EXFAT_KERNEL_DEBUG */
+ 
+ 	if (!p_bd->opened)
+-		return FFS_MEDIAERR;
++		return -ENODEV;
+ 
+ 	if (secno == bh->b_blocknr) {
+ 		lock_buffer(bh);
+@@ -89,7 +89,7 @@ int bdev_write(struct super_block *sb, sector_t secno, struct buffer_head *bh,
+ 		mark_buffer_dirty(bh);
+ 		unlock_buffer(bh);
+ 		if (sync && (sync_dirty_buffer(bh) != 0))
+-			return FFS_MEDIAERR;
++			return -EIO;
+ 	} else {
+ 		count = num_secs << p_bd->sector_size_bits;
+ 
+@@ -115,7 +115,7 @@ int bdev_write(struct super_block *sb, sector_t secno, struct buffer_head *bh,
+ 	WARN(!p_fs->dev_ejected,
+ 	     "[EXFAT] No bh, device seems wrong or to be ejected.\n");
+ 
+-	return FFS_MEDIAERR;
++	return -EIO;
+ }
+ 
+ int bdev_sync(struct super_block *sb)
+@@ -126,11 +126,11 @@ int bdev_sync(struct super_block *sb)
+ 	long flags = sbi->debug_flags;
+ 
+ 	if (flags & EXFAT_DEBUGFLAGS_ERROR_RW)
+-		return FFS_MEDIAERR;
++		return -EIO;
+ #endif /* CONFIG_EXFAT_KERNEL_DEBUG */
+ 
+ 	if (!p_bd->opened)
+-		return FFS_MEDIAERR;
++		return -ENODEV;
+ 
+ 	return sync_blockdev(sb->s_bdev);
+ }
+diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
+index e90b54a17150..2f6e9d724625 100644
+--- a/drivers/staging/exfat/exfat_core.c
++++ b/drivers/staging/exfat/exfat_core.c
+@@ -252,13 +252,13 @@ s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc,
+ 		}
+ 
+ 		if (set_alloc_bitmap(sb, new_clu - 2) != FFS_SUCCESS)
+-			return -1;
++			return -EIO;
+ 
+ 		num_clusters++;
+ 
+ 		if (p_chain->flags == 0x01) {
+ 			if (FAT_write(sb, new_clu, CLUSTER_32(~0)) < 0)
+-				return -1;
++				return -EIO;
+ 		}
+ 
+ 		if (p_chain->dir == CLUSTER_32(~0)) {
+@@ -266,7 +266,7 @@ s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc,
+ 		} else {
+ 			if (p_chain->flags == 0x01) {
+ 				if (FAT_write(sb, last_clu, new_clu) < 0)
+-					return -1;
++					return -EIO;
+ 			}
+ 		}
+ 		last_clu = new_clu;
+@@ -526,7 +526,7 @@ s32 load_alloc_bitmap(struct super_block *sb)
+ 			ep = (struct bmap_dentry_t *)get_entry_in_dir(sb, &clu,
+ 								      i, NULL);
+ 			if (!ep)
+-				return FFS_MEDIAERR;
++				return -ENOENT;
+ 
+ 			type = p_fs->fs_func->get_entry_type((struct dentry_t *)ep);
+ 
+@@ -570,7 +570,7 @@ s32 load_alloc_bitmap(struct super_block *sb)
+ 		}
+ 
+ 		if (FAT_read(sb, clu.dir, &clu.dir) != 0)
+-			return FFS_MEDIAERR;
++			return -EIO;
+ 	}
+ 
+ 	return -EFSCORRUPTED;
+@@ -856,14 +856,14 @@ s32 load_upcase_table(struct super_block *sb)
+ 	clu.flags = 0x01;
+ 
+ 	if (p_fs->dev_ejected)
+-		return FFS_MEDIAERR;
++		return -EIO;
+ 
+ 	while (clu.dir != CLUSTER_32(~0)) {
+ 		for (i = 0; i < p_fs->dentries_per_clu; i++) {
+ 			ep = (struct case_dentry_t *)get_entry_in_dir(sb, &clu,
+ 								      i, NULL);
+ 			if (!ep)
+-				return FFS_MEDIAERR;
++				return -ENOENT;
+ 
+ 			type = p_fs->fs_func->get_entry_type((struct dentry_t *)ep);
+ 
+@@ -883,7 +883,7 @@ s32 load_upcase_table(struct super_block *sb)
+ 			return FFS_SUCCESS;
+ 		}
+ 		if (FAT_read(sb, clu.dir, &clu.dir) != 0)
+-			return FFS_MEDIAERR;
++			return -EIO;
+ 	}
+ 	/* load default upcase table */
+ 	return __load_default_upcase_table(sb);
+@@ -1246,7 +1246,7 @@ s32 fat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir, s32 entry,
+ 	dos_ep = (struct dos_dentry_t *)get_entry_in_dir(sb, p_dir, entry,
+ 							 §or);
+ 	if (!dos_ep)
+-		return FFS_MEDIAERR;
++		return -EIO;
+ 
+ 	init_dos_entry(dos_ep, type, start_clu);
+ 	buf_modify(sb, sector);
+@@ -1268,12 +1268,12 @@ s32 exfat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+ 	file_ep = (struct file_dentry_t *)get_entry_in_dir(sb, p_dir, entry,
+ 							   §or);
+ 	if (!file_ep)
+-		return FFS_MEDIAERR;
++		return -ENOENT;
+ 
+ 	strm_ep = (struct strm_dentry_t *)get_entry_in_dir(sb, p_dir, entry + 1,
+ 							   §or);
+ 	if (!strm_ep)
+-		return FFS_MEDIAERR;
++		return -ENOENT;
+ 
+ 	init_file_entry(file_ep, type);
+ 	buf_modify(sb, sector);
+@@ -1299,7 +1299,7 @@ static s32 fat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir,
+ 	dos_ep = (struct dos_dentry_t *)get_entry_in_dir(sb, p_dir, entry,
+ 							 §or);
+ 	if (!dos_ep)
+-		return FFS_MEDIAERR;
++		return -EIO;
+ 
+ 	dos_ep->lcase = p_dosname->name_case;
+ 	memcpy(dos_ep->name, p_dosname->name, DOS_NAME_LENGTH);
+@@ -1315,7 +1315,7 @@ static s32 fat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir,
+ 									 entry - i,
+ 									 §or);
+ 			if (!ext_ep)
+-				return FFS_MEDIAERR;
++				return -EIO;
+ 
+ 			init_ext_entry(ext_ep, i, chksum, uniname);
+ 			buf_modify(sb, sector);
+@@ -1326,7 +1326,7 @@ static s32 fat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir,
+ 								 entry - i,
+ 								 §or);
+ 		if (!ext_ep)
+-			return FFS_MEDIAERR;
++			return -EIO;
+ 
+ 		init_ext_entry(ext_ep, i + 0x40, chksum, uniname);
+ 		buf_modify(sb, sector);
+@@ -1350,7 +1350,7 @@ static s32 exfat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir,
+ 	file_ep = (struct file_dentry_t *)get_entry_in_dir(sb, p_dir, entry,
+ 							   §or);
+ 	if (!file_ep)
+-		return FFS_MEDIAERR;
++		return -ENOENT;
+ 
+ 	file_ep->num_ext = (u8)(num_entries - 1);
+ 	buf_modify(sb, sector);
+@@ -1358,7 +1358,7 @@ static s32 exfat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir,
+ 	strm_ep = (struct strm_dentry_t *)get_entry_in_dir(sb, p_dir, entry + 1,
+ 							   §or);
+ 	if (!strm_ep)
+-		return FFS_MEDIAERR;
++		return -ENOENT;
+ 
+ 	strm_ep->name_len = p_uniname->name_len;
+ 	SET16_A(strm_ep->name_hash, p_uniname->name_hash);
+@@ -1369,7 +1369,7 @@ static s32 exfat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir,
+ 								   entry + i,
+ 								   §or);
+ 		if (!name_ep)
+-			return FFS_MEDIAERR;
++			return -ENOENT;
+ 
+ 		init_name_entry(name_ep, uniname);
+ 		buf_modify(sb, sector);
+@@ -1592,7 +1592,7 @@ static s32 _walk_fat_chain(struct super_block *sb, struct chain_t *p_dir,
+ 	} else {
+ 		while (clu_offset > 0) {
+ 			if (FAT_read(sb, cur_clu, &cur_clu) == -1)
+-				return FFS_MEDIAERR;
++				return -EIO;
+ 			clu_offset--;
+ 		}
+ 	}
+@@ -2084,10 +2084,10 @@ s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_entries
+ 		/* (1) allocate a cluster */
+ 		ret = p_fs->fs_func->alloc_cluster(sb, 1, &clu);
+ 		if (ret < 1)
+-			return -1;
++			return -EIO;
+ 
+ 		if (clear_cluster(sb, clu.dir) != FFS_SUCCESS)
+-			return -1;
++			return -EIO;
+ 
+ 		/* (2) append to the FAT chain */
+ 		if (clu.flags != p_dir->flags) {
+@@ -2097,7 +2097,7 @@ s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_entries
+ 		}
+ 		if (clu.flags == 0x01)
+ 			if (FAT_write(sb, last_clu, clu.dir) < 0)
+-				return -1;
++				return -EIO;
+ 
+ 		if (p_fs->hint_uentry.entry == -1) {
+ 			p_fs->hint_uentry.dir = p_dir->dir;
+@@ -2118,7 +2118,7 @@ s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_entries
+ 				ep = get_entry_in_dir(sb, &fid->dir,
+ 						      fid->entry + 1, §or);
+ 				if (!ep)
+-					return -1;
++					return -ENOENT;
+ 				p_fs->fs_func->set_entry_size(ep, size);
+ 				p_fs->fs_func->set_entry_flag(ep, p_dir->flags);
+ 				buf_modify(sb, sector);
+@@ -2464,7 +2464,7 @@ s32 count_dos_name_entries(struct super_block *sb, struct chain_t *p_dir,
+ 		for (i = 0; i < dentries_per_clu; i++) {
+ 			ep = get_entry_in_dir(sb, &clu, i, NULL);
+ 			if (!ep)
+-				return -1;
++				return -ENOENT;
+ 
+ 			entry_type = p_fs->fs_func->get_entry_type(ep);
+ 
+@@ -2488,7 +2488,7 @@ s32 count_dos_name_entries(struct super_block *sb, struct chain_t *p_dir,
+ 				clu.dir = CLUSTER_32(~0);
+ 		} else {
+ 			if (FAT_read(sb, clu.dir, &clu.dir) != 0)
+-				return -1;
++				return -EIO;
+ 		}
+ 	}
+ 
+@@ -2772,7 +2772,7 @@ s32 fat_generate_dos_name(struct super_block *sb, struct chain_t *p_dir,
+ 			ep = (struct dos_dentry_t *)get_entry_in_dir(sb, &clu,
+ 								     i, NULL);
+ 			if (!ep)
+-				return FFS_MEDIAERR;
++				return -ENOENT;
+ 
+ 			type = p_fs->fs_func->get_entry_type((struct dentry_t *)
+ 							     ep);
+@@ -2811,7 +2811,7 @@ s32 fat_generate_dos_name(struct super_block *sb, struct chain_t *p_dir,
+ 			break; /* FAT16 root_dir */
+ 
+ 		if (FAT_read(sb, clu.dir, &clu.dir) != 0)
+-			return FFS_MEDIAERR;
++			return -EIO;
+ 	}
+ 
+ 	count = 0;
+@@ -3226,7 +3226,7 @@ s32 create_dir(struct inode *inode, struct chain_t *p_dir,
+ 	/* (1) allocate a cluster */
+ 	ret = fs_func->alloc_cluster(sb, 1, &clu);
+ 	if (ret < 0)
+-		return FFS_MEDIAERR;
++		return ret;
+ 	else if (ret == 0)
+ 		return -ENOSPC;
+ 
+@@ -3395,7 +3395,7 @@ s32 rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry,
+ 
+ 	epold = get_entry_in_dir(sb, p_dir, oldentry, §or_old);
+ 	if (!epold)
+-		return FFS_MEDIAERR;
++		return -ENOENT;
+ 
+ 	buf_lock(sb, sector_old);
+ 
+@@ -3404,7 +3404,7 @@ s32 rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry,
+ 						     epold);
+ 	if (num_old_entries < 0) {
+ 		buf_unlock(sb, sector_old);
+-		return FFS_MEDIAERR;
++		return -ENOENT;
+ 	}
+ 	num_old_entries++;
+ 
+@@ -3425,7 +3425,7 @@ s32 rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry,
+ 		epnew = get_entry_in_dir(sb, p_dir, newentry, §or_new);
+ 		if (!epnew) {
+ 			buf_unlock(sb, sector_old);
+-			return FFS_MEDIAERR;
++			return -ENOENT;
+ 		}
+ 
+ 		memcpy((void *)epnew, (void *)epold, DENTRY_SIZE);
+@@ -3447,7 +3447,7 @@ s32 rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry,
+ 
+ 			if (!epold || !epnew) {
+ 				buf_unlock(sb, sector_old);
+-				return FFS_MEDIAERR;
++				return -ENOENT;
+ 			}
+ 
+ 			memcpy((void *)epnew, (void *)epold, DENTRY_SIZE);
+@@ -3502,7 +3502,7 @@ s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
+ 
+ 	epmov = get_entry_in_dir(sb, p_olddir, oldentry, §or_mov);
+ 	if (!epmov)
+-		return FFS_MEDIAERR;
++		return -ENOENT;
+ 
+ 	/* check if the source and target directory is the same */
+ 	if (fs_func->get_entry_type(epmov) == TYPE_DIR &&
+@@ -3516,7 +3516,7 @@ s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
+ 						     epmov);
+ 	if (num_old_entries < 0) {
+ 		buf_unlock(sb, sector_mov);
+-		return FFS_MEDIAERR;
++		return -ENOENT;
+ 	}
+ 	num_old_entries++;
+ 
+@@ -3536,7 +3536,7 @@ s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
+ 	epnew = get_entry_in_dir(sb, p_newdir, newentry, §or_new);
+ 	if (!epnew) {
+ 		buf_unlock(sb, sector_mov);
+-		return FFS_MEDIAERR;
++		return -ENOENT;
+ 	}
+ 
+ 	memcpy((void *)epnew, (void *)epmov, DENTRY_SIZE);
+@@ -3556,7 +3556,7 @@ s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
+ 					 §or_new);
+ 		if (!epmov || !epnew) {
+ 			buf_unlock(sb, sector_mov);
+-			return FFS_MEDIAERR;
++			return -ENOENT;
+ 		}
+ 
+ 		memcpy((void *)epnew, (void *)epmov, DENTRY_SIZE);
+@@ -3569,7 +3569,7 @@ s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
+ 
+ 		epnew = get_entry_in_dir(sb, &clu, 1, §or_new);
+ 		if (!epnew)
+-			return FFS_MEDIAERR;
++			return -ENOENT;
+ 
+ 		if (p_newdir->dir == p_fs->root_dir)
+ 			fs_func->set_entry_clu0(epnew, CLUSTER_32(0));
+@@ -3601,7 +3601,7 @@ s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
+ int sector_read(struct super_block *sb, sector_t sec, struct buffer_head **bh,
+ 		bool read)
+ {
+-	s32 ret = FFS_MEDIAERR;
++	s32 ret = -EIO;
+ 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+ 
+ 	if ((sec >= (p_fs->PBR_sector + p_fs->num_sectors)) &&
+@@ -3624,7 +3624,7 @@ int sector_read(struct super_block *sb, sector_t sec, struct buffer_head **bh,
+ int sector_write(struct super_block *sb, sector_t sec, struct buffer_head *bh,
+ 		 bool sync)
+ {
+-	s32 ret = FFS_MEDIAERR;
++	s32 ret = -EIO;
+ 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+ 
+ 	if (sec >= (p_fs->PBR_sector + p_fs->num_sectors) &&
+@@ -3653,7 +3653,7 @@ int sector_write(struct super_block *sb, sector_t sec, struct buffer_head *bh,
+ int multi_sector_read(struct super_block *sb, sector_t sec,
+ 		      struct buffer_head **bh, s32 num_secs, bool read)
+ {
+-	s32 ret = FFS_MEDIAERR;
++	s32 ret = -EIO;
+ 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+ 
+ 	if (((sec + num_secs) > (p_fs->PBR_sector + p_fs->num_sectors)) &&
+@@ -3676,7 +3676,7 @@ int multi_sector_read(struct super_block *sb, sector_t sec,
+ int multi_sector_write(struct super_block *sb, sector_t sec,
+ 		       struct buffer_head *bh, s32 num_secs, bool sync)
+ {
+-	s32 ret = FFS_MEDIAERR;
++	s32 ret = -EIO;
+ 	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+ 
+ 	if ((sec + num_secs) > (p_fs->PBR_sector + p_fs->num_sectors) &&
+diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
+index 9337fd4caaae..1a906579724c 100644
+--- a/drivers/staging/exfat/exfat_super.c
++++ b/drivers/staging/exfat/exfat_super.c
+@@ -364,7 +364,9 @@ static int ffsMountVol(struct super_block *sb)
+ 	bdev_open(sb);
+ 
+ 	if (p_bd->sector_size < sb->s_blocksize) {
+-		ret = FFS_MEDIAERR;
++		printk(KERN_INFO "EXFAT: maont failed - sector size %d less than blocksize %ld\n",
++			p_bd->sector_size,  sb->s_blocksize);
++		ret = -EINVAL;
+ 		goto out;
+ 	}
+ 	if (p_bd->sector_size > sb->s_blocksize)
+@@ -372,7 +374,7 @@ static int ffsMountVol(struct super_block *sb)
+ 
+ 	/* read Sector 0 */
+ 	if (sector_read(sb, 0, &tmp_bh, 1) != FFS_SUCCESS) {
+-		ret = FFS_MEDIAERR;
++		ret = -EIO;
+ 		goto out;
+ 	}
+ 
+@@ -435,7 +437,7 @@ static int ffsMountVol(struct super_block *sb)
+ 			free_alloc_bitmap(sb);
+ 		}
+ 		bdev_close(sb);
+-		ret = FFS_MEDIAERR;
++		ret = -EIO;
+ 		goto out;
+ 	}
+ 
+@@ -475,7 +477,7 @@ static int ffsUmountVol(struct super_block *sb)
+ 
+ 	if (p_fs->dev_ejected) {
+ 		pr_info("[EXFAT] unmounted with media errors. Device is already ejected.\n");
+-		err = FFS_MEDIAERR;
++		err = -EIO;
+ 	}
+ 
+ 	buf_shutdown(sb);
+@@ -511,7 +513,7 @@ static int ffsGetVolInfo(struct super_block *sb, struct vol_info_t *info)
+ 	info->FreeClusters = info->NumClusters - info->UsedClusters;
+ 
+ 	if (p_fs->dev_ejected)
+-		err = FFS_MEDIAERR;
++		err = -EIO;
+ 
+ 	/* release the lock for file system critical section */
+ 	mutex_unlock(&p_fs->v_mutex);
+@@ -532,7 +534,7 @@ static int ffsSyncVol(struct super_block *sb, bool do_sync)
+ 	fs_set_vol_flags(sb, VOL_CLEAN);
+ 
+ 	if (p_fs->dev_ejected)
+-		err = FFS_MEDIAERR;
++		err = -EIO;
+ 
+ 	/* release the lock for file system critical section */
+ 	mutex_unlock(&p_fs->v_mutex);
+@@ -601,14 +603,14 @@ static int ffsLookupFile(struct inode *inode, char *path, struct file_id_t *fid)
+ 			es = get_entry_set_in_dir(sb, &dir, dentry,
+ 						  ES_2_ENTRIES, &ep);
+ 			if (!es) {
+-				ret =  FFS_MEDIAERR;
++				ret =  -ENOENT;
+ 				goto out;
+ 			}
+ 			ep2 = ep + 1;
+ 		} else {
+ 			ep = get_entry_in_dir(sb, &dir, dentry, NULL);
+ 			if (!ep) {
+-				ret =  FFS_MEDIAERR;
++				ret =  -ENOENT;
+ 				goto out;
+ 			}
+ 			ep2 = ep;
+@@ -633,7 +635,7 @@ static int ffsLookupFile(struct inode *inode, char *path, struct file_id_t *fid)
+ 	}
+ 
+ 	if (p_fs->dev_ejected)
+-		ret = FFS_MEDIAERR;
++		ret = -EIO;
+ out:
+ 	/* release the lock for file system critical section */
+ 	mutex_unlock(&p_fs->v_mutex);
+@@ -673,7 +675,7 @@ static int ffsCreateFile(struct inode *inode, char *path, u8 mode,
+ #endif
+ 
+ 	if (p_fs->dev_ejected)
+-		ret = FFS_MEDIAERR;
++		ret = -EIO;
+ 
+ out:
+ 	/* release the lock for file system critical section */
+@@ -744,7 +746,7 @@ static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer,
+ 			while (clu_offset > 0) {
+ 				/* clu = FAT_read(sb, clu); */
+ 				if (FAT_read(sb, clu, &clu) == -1) {
+-					ret = FFS_MEDIAERR;
++					ret = -EIO;
+ 					goto out;
+ 				}
+ 
+@@ -799,7 +801,7 @@ static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer,
+ 		*rcount = read_bytes;
+ 
+ 	if (p_fs->dev_ejected)
+-		ret = FFS_MEDIAERR;
++		ret = -EIO;
+ 
+ out:
+ 	/* release the lock for file system critical section */
+@@ -890,7 +892,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
+ 				last_clu = clu;
+ 				/* clu = FAT_read(sb, clu); */
+ 				if (FAT_read(sb, clu, &clu) == -1) {
+-					ret = FFS_MEDIAERR;
++					ret = -EIO;
+ 					goto out;
+ 				}
+ 				clu_offset--;
+@@ -912,7 +914,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
+ 			if (num_alloced == 0)
+ 				break;
+ 			if (num_alloced < 0) {
+-				ret = FFS_MEDIAERR;
++				ret = num_alloced;
+ 				goto out;
+ 			}
+ 
+@@ -1057,7 +1059,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
+ 		ret = -ENOSPC;
+ 
+ 	else if (p_fs->dev_ejected)
+-		ret = FFS_MEDIAERR;
++		ret = -EIO;
+ 
+ out:
+ 	/* release the lock for file system critical section */
+@@ -1118,7 +1120,7 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size)
+ 			while (num_clusters > 0) {
+ 				last_clu = clu.dir;
+ 				if (FAT_read(sb, clu.dir, &clu.dir) == -1) {
+-					ret = FFS_MEDIAERR;
++					ret = -EIO;
+ 					goto out;
+ 				}
+ 				num_clusters--;
+@@ -1140,14 +1142,14 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size)
+ 		es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
+ 					  ES_ALL_ENTRIES, &ep);
+ 		if (!es) {
+-			ret = FFS_MEDIAERR;
++			ret = -ENOENT;
+ 			goto out;
+ 			}
+ 		ep2 = ep + 1;
+ 	} else {
+ 		ep = get_entry_in_dir(sb, &fid->dir, fid->entry, §or);
+ 		if (!ep) {
+-			ret = FFS_MEDIAERR;
++			ret = -ENOENT;
+ 			goto out;
+ 		}
+ 		ep2 = ep;
+@@ -1189,7 +1191,7 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size)
+ #endif
+ 
+ 	if (p_fs->dev_ejected)
+-		ret = FFS_MEDIAERR;
++		ret = -EIO;
+ 
+ out:
+ 	pr_debug("%s exited (%d)\n", __func__, ret);
+@@ -1262,7 +1264,7 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid,
+ 
+ 	ep = get_entry_in_dir(sb, &olddir, dentry, NULL);
+ 	if (!ep) {
+-		ret = FFS_MEDIAERR;
++		ret = -ENOENT;
+ 		goto out2;
+ 	}
+ 
+@@ -1275,7 +1277,7 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid,
+ 	if (new_inode) {
+ 		u32 entry_type;
+ 
+-		ret = FFS_MEDIAERR;
++		ret = -ENOENT;
+ 		new_fid = &EXFAT_I(new_inode)->fid;
+ 
+ 		update_parent_info(new_fid, new_parent_inode);
+@@ -1337,7 +1339,7 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid,
+ #endif
+ 
+ 	if (p_fs->dev_ejected)
+-		ret = FFS_MEDIAERR;
++		ret = -EIO;
+ out2:
+ 	/* release the lock for file system critical section */
+ 	mutex_unlock(&p_fs->v_mutex);
+@@ -1369,7 +1371,7 @@ static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid)
+ 
+ 	ep = get_entry_in_dir(sb, &dir, dentry, NULL);
+ 	if (!ep) {
+-		ret = FFS_MEDIAERR;
++		ret = -ENOENT;
+ 		goto out;
+ 	}
+ 
+@@ -1399,7 +1401,7 @@ static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid)
+ #endif
+ 
+ 	if (p_fs->dev_ejected)
+-		ret = FFS_MEDIAERR;
++		ret = -EIO;
+ out:
+ 	/* release the lock for file system critical section */
+ 	mutex_unlock(&p_fs->v_mutex);
+@@ -1423,7 +1425,7 @@ static int ffsSetAttr(struct inode *inode, u32 attr)
+ 
+ 	if (fid->attr == attr) {
+ 		if (p_fs->dev_ejected)
+-			return FFS_MEDIAERR;
++			return -EIO;
+ 		return FFS_SUCCESS;
+ 	}
+ 
+@@ -1431,7 +1433,7 @@ static int ffsSetAttr(struct inode *inode, u32 attr)
+ 		if ((fid->dir.dir == p_fs->root_dir) &&
+ 		    (fid->entry == -1)) {
+ 			if (p_fs->dev_ejected)
+-				return FFS_MEDIAERR;
++				return -EIO;
+ 			return FFS_SUCCESS;
+ 		}
+ 	}
+@@ -1444,13 +1446,13 @@ static int ffsSetAttr(struct inode *inode, u32 attr)
+ 		es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
+ 					  ES_ALL_ENTRIES, &ep);
+ 		if (!es) {
+-			ret = FFS_MEDIAERR;
++			ret = -ENOENT;
+ 			goto out;
+ 		}
+ 	} else {
+ 		ep = get_entry_in_dir(sb, &fid->dir, fid->entry, §or);
+ 		if (!ep) {
+-			ret = FFS_MEDIAERR;
++			ret = -ENOENT;
+ 			goto out;
+ 		}
+ 	}
+@@ -1460,7 +1462,7 @@ static int ffsSetAttr(struct inode *inode, u32 attr)
+ 	if (((type == TYPE_FILE) && (attr & ATTR_SUBDIR)) ||
+ 	    ((type == TYPE_DIR) && (!(attr & ATTR_SUBDIR)))) {
+ 		if (p_fs->dev_ejected)
+-			ret = FFS_MEDIAERR;
++			ret = -EIO;
+ 		else
+ 			ret = FFS_ERROR;
+ 
+@@ -1488,7 +1490,7 @@ static int ffsSetAttr(struct inode *inode, u32 attr)
+ #endif
+ 
+ 	if (p_fs->dev_ejected)
+-		ret = FFS_MEDIAERR;
++		ret = -EIO;
+ out:
+ 	/* release the lock for file system critical section */
+ 	mutex_unlock(&p_fs->v_mutex);
+@@ -1544,13 +1546,13 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info)
+ 
+ 			count = count_dos_name_entries(sb, &dir, TYPE_DIR);
+ 			if (count < 0) {
+-				ret = FFS_MEDIAERR;
++				ret = count; /* propogate error upward */
+ 				goto out;
+ 			}
+ 			info->NumSubdirs = count;
+ 
+ 			if (p_fs->dev_ejected)
+-				ret = FFS_MEDIAERR;
++				ret = -EIO;
+ 			goto out;
+ 		}
+ 	}
+@@ -1560,14 +1562,14 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info)
+ 		es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
+ 					  ES_2_ENTRIES, &ep);
+ 		if (!es) {
+-			ret = FFS_MEDIAERR;
++			ret = -ENOENT;
+ 			goto out;
+ 		}
+ 		ep2 = ep + 1;
+ 	} else {
+ 		ep = get_entry_in_dir(sb, &fid->dir, fid->entry, §or);
+ 		if (!ep) {
+-			ret = FFS_MEDIAERR;
++			ret = -ENOENT;
+ 			goto out;
+ 		}
+ 		ep2 = ep;
+@@ -1633,14 +1635,14 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info)
+ 
+ 		count = count_dos_name_entries(sb, &dir, TYPE_DIR);
+ 		if (count < 0) {
+-			ret = FFS_MEDIAERR;
++			ret = count; /* propogate error upward */
+ 			goto out;
+ 		}
+ 		info->NumSubdirs += count;
+ 	}
+ 
+ 	if (p_fs->dev_ejected)
+-		ret = FFS_MEDIAERR;
++		ret = -EIO;
+ 
+ out:
+ 	/* release the lock for file system critical section */
+@@ -1671,7 +1673,7 @@ static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info)
+ 		if ((fid->dir.dir == p_fs->root_dir) &&
+ 		    (fid->entry == -1)) {
+ 			if (p_fs->dev_ejected)
+-				ret = FFS_MEDIAERR;
++				ret = -EIO;
+ 			ret = FFS_SUCCESS;
+ 			goto out;
+ 		}
+@@ -1684,7 +1686,7 @@ static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info)
+ 		es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
+ 					  ES_ALL_ENTRIES, &ep);
+ 		if (!es) {
+-			ret = FFS_MEDIAERR;
++			ret = -ENOENT;
+ 			goto out;
+ 		}
+ 		ep2 = ep + 1;
+@@ -1692,7 +1694,7 @@ static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info)
+ 		/* for other than exfat */
+ 		ep = get_entry_in_dir(sb, &fid->dir, fid->entry, §or);
+ 		if (!ep) {
+-			ret = FFS_MEDIAERR;
++			ret = -ENOENT;
+ 			goto out;
+ 		}
+ 		ep2 = ep;
+@@ -1727,7 +1729,7 @@ static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info)
+ 	}
+ 
+ 	if (p_fs->dev_ejected)
+-		ret = FFS_MEDIAERR;
++		ret = -EIO;
+ 
+ out:
+ 	/* release the lock for file system critical section */
+@@ -1789,7 +1791,7 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
+ 		while ((clu_offset > 0) && (*clu != CLUSTER_32(~0))) {
+ 			last_clu = *clu;
+ 			if (FAT_read(sb, *clu, clu) == -1) {
+-				ret = FFS_MEDIAERR;
++				ret = -EIO;
+ 				goto out;
+ 			}
+ 			clu_offset--;
+@@ -1807,7 +1809,7 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
+ 		/* (1) allocate a cluster */
+ 		num_alloced = p_fs->fs_func->alloc_cluster(sb, 1, &new_clu);
+ 		if (num_alloced < 0) {
+-			ret = FFS_MEDIAERR;
++			ret = -EIO;
+ 			goto out;
+ 		} else if (num_alloced == 0) {
+ 			ret = -ENOSPC;
+@@ -1838,7 +1840,7 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
+ 			es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
+ 						  ES_ALL_ENTRIES, &ep);
+ 			if (!es) {
+-				ret = FFS_MEDIAERR;
++				ret = -ENOENT;
+ 				goto out;
+ 			}
+ 			/* get stream entry */
+@@ -1851,7 +1853,7 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
+ 				ep = get_entry_in_dir(sb, &fid->dir,
+ 						      fid->entry, §or);
+ 				if (!ep) {
+-					ret = FFS_MEDIAERR;
++					ret = -ENOENT;
+ 					goto out;
+ 				}
+ 			}
+@@ -1881,7 +1883,7 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
+ 	fid->hint_last_clu = *clu;
+ 
+ 	if (p_fs->dev_ejected)
+-		ret = FFS_MEDIAERR;
++		ret = -EIO;
+ 
+ out:
+ 	/* release the lock for file system critical section */
+@@ -1926,7 +1928,7 @@ static int ffsCreateDir(struct inode *inode, char *path, struct file_id_t *fid)
+ #endif
+ 
+ 	if (p_fs->dev_ejected)
+-		ret = FFS_MEDIAERR;
++		ret = -EIO;
+ out:
+ 	/* release the lock for file system critical section */
+ 	mutex_unlock(&p_fs->v_mutex);
+@@ -1956,7 +1958,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
+ 
+ 	/* check if the given file ID is opened */
+ 	if (fid->type != TYPE_DIR)
+-		return -EPERM;
++		return -ENOTDIR;
+ 
+ 	/* acquire the lock for file system critical section */
+ 	mutex_lock(&p_fs->v_mutex);
+@@ -2006,7 +2008,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
+ 			while (clu_offset > 0) {
+ 				/* clu.dir = FAT_read(sb, clu.dir); */
+ 				if (FAT_read(sb, clu.dir, &clu.dir) == -1) {
+-					ret = FFS_MEDIAERR;
++					ret = -EIO;
+ 					goto out;
+ 				}
+ 				clu_offset--;
+@@ -2026,7 +2028,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
+ 		for ( ; i < dentries_per_clu; i++, dentry++) {
+ 			ep = get_entry_in_dir(sb, &clu, i, §or);
+ 			if (!ep) {
+-				ret = FFS_MEDIAERR;
++				ret = -ENOENT;
+ 				goto out;
+ 			}
+ 			type = fs_func->get_entry_type(ep);
+@@ -2074,7 +2076,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
+ 			if (p_fs->vol_type == EXFAT) {
+ 				ep = get_entry_in_dir(sb, &clu, i + 1, NULL);
+ 				if (!ep) {
+-					ret = FFS_MEDIAERR;
++					ret = -ENOENT;
+ 					goto out;
+ 				}
+ 			} else {
+@@ -2098,7 +2100,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
+ 			fid->rwoffset = (s64)(++dentry);
+ 
+ 			if (p_fs->dev_ejected)
+-				ret = FFS_MEDIAERR;
++				ret = -EIO;
+ 			goto out;
+ 		}
+ 
+@@ -2113,7 +2115,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
+ 		} else {
+ 			/* clu.dir = FAT_read(sb, clu.dir); */
+ 			if (FAT_read(sb, clu.dir, &clu.dir) == -1) {
+-				ret = FFS_MEDIAERR;
++				ret = -EIO;
+ 				goto out;
+ 			}
+ 		}
+@@ -2124,7 +2126,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
+ 	fid->rwoffset = (s64)(++dentry);
+ 
+ 	if (p_fs->dev_ejected)
+-		ret = FFS_MEDIAERR;
++		ret = -EIO;
+ 
+ out:
+ 	/* release the lock for file system critical section */
+@@ -2187,7 +2189,7 @@ static int ffsRemoveDir(struct inode *inode, struct file_id_t *fid)
+ #endif
+ 
+ 	if (p_fs->dev_ejected)
+-		ret = FFS_MEDIAERR;
++		ret = -EIO;
+ 
+ out:
+ 	/* release the lock for file system critical section */
+@@ -2247,12 +2249,11 @@ static int exfat_readdir(struct file *filp, struct dir_context *ctx)
+ 		/* at least we tried to read a sector
+ 		 * move cpos to next sector position (should be aligned)
+ 		 */
+-		if (err == FFS_MEDIAERR) {
++		if (err == -EIO) {
+ 			cpos += 1 << p_bd->sector_size_bits;
+ 			cpos &= ~((1 << p_bd->sector_size_bits) - 1);
+ 		}
+ 
+-		err = -EIO;
+ 		goto end_of_dir;
+ 	}
+ 
+@@ -3550,7 +3551,7 @@ static int exfat_statfs(struct dentry *dentry, struct kstatfs *buf)
+ 	struct vol_info_t info;
+ 
+ 	if (p_fs->used_clusters == UINT_MAX) {
+-		if (ffsGetVolInfo(sb, &info) == FFS_MEDIAERR)
++		if (ffsGetVolInfo(sb, &info) == -EIO)
+ 			return -EIO;
+ 
+ 	} else {

commit 133c887424712b50f184731b1cfe26ed7201cd6b
+Author: Valdis Kletnieks 
+Date:   Mon Nov 11 21:09:49 2019 -0500
+
+    staging: exfat: Clean up return codes - FFS_FORMATERR
+    
+    Convert FFS_FORMATERR to -EFSCORRUPTED
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191112021000.42091-2-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index acb73f47a253..4f9ba235d967 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -30,6 +30,8 @@
+ #undef DEBUG
+ #endif
+ 
++#define EFSCORRUPTED	EUCLEAN		/* Filesystem is corrupted */
++
+ #define DENTRY_SIZE		32	/* dir entry size */
+ #define DENTRY_SIZE_BITS	5
+ 
+@@ -209,7 +211,6 @@ static inline u16 get_row_index(u16 i)
+ /* return values */
+ #define FFS_SUCCESS             0
+ #define FFS_MEDIAERR            1
+-#define FFS_FORMATERR           2
+ #define FFS_MOUNTED             3
+ #define FFS_NOTMOUNTED          4
+ #define FFS_ALIGNMENTERR        5
+diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
+index b23fbf3ebaa5..e90b54a17150 100644
+--- a/drivers/staging/exfat/exfat_core.c
++++ b/drivers/staging/exfat/exfat_core.c
+@@ -573,7 +573,7 @@ s32 load_alloc_bitmap(struct super_block *sb)
+ 			return FFS_MEDIAERR;
+ 	}
+ 
+-	return FFS_FORMATERR;
++	return -EFSCORRUPTED;
+ }
+ 
+ void free_alloc_bitmap(struct super_block *sb)
+@@ -3016,7 +3016,7 @@ s32 fat16_mount(struct super_block *sb, struct pbr_sector_t *p_pbr)
+ 	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
+ 
+ 	if (p_bpb->num_fats == 0)
+-		return FFS_FORMATERR;
++		return -EFSCORRUPTED;
+ 
+ 	num_root_sectors = GET16(p_bpb->num_root_entries) << DENTRY_SIZE_BITS;
+ 	num_root_sectors = ((num_root_sectors - 1) >>
+@@ -3078,7 +3078,7 @@ s32 fat32_mount(struct super_block *sb, struct pbr_sector_t *p_pbr)
+ 	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
+ 
+ 	if (p_bpb->num_fats == 0)
+-		return FFS_FORMATERR;
++		return -EFSCORRUPTED;
+ 
+ 	p_fs->sectors_per_clu = p_bpb->sectors_per_clu;
+ 	p_fs->sectors_per_clu_bits = ilog2(p_bpb->sectors_per_clu);
+@@ -3157,7 +3157,7 @@ s32 exfat_mount(struct super_block *sb, struct pbr_sector_t *p_pbr)
+ 	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
+ 
+ 	if (p_bpb->num_fats == 0)
+-		return FFS_FORMATERR;
++		return -EFSCORRUPTED;
+ 
+ 	p_fs->sectors_per_clu = 1 << p_bpb->sectors_per_clu_bits;
+ 	p_fs->sectors_per_clu_bits = p_bpb->sectors_per_clu_bits;
+diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
+index ee3d64178069..9337fd4caaae 100644
+--- a/drivers/staging/exfat/exfat_super.c
++++ b/drivers/staging/exfat/exfat_super.c
+@@ -384,7 +384,7 @@ static int ffsMountVol(struct super_block *sb)
+ 	if (GET16_A(p_pbr->signature) != PBR_SIGNATURE) {
+ 		brelse(tmp_bh);
+ 		bdev_close(sb);
+-		ret = FFS_FORMATERR;
++		ret = -EFSCORRUPTED;
+ 		goto out;
+ 	}
+ 

commit 37c250fd3844037fb53ad92366f3389e7876ab1d
+Author: Valdis Kletnieks 
+Date:   Wed Oct 23 01:53:53 2019 -0400
+
+    staging: exfat: Update MAINTAINERS file
+    
+    Add a L: tag so get_maintainers.pl output includes the linux-fsdevel list
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191023055353.695275-1-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index dfe76fb1ed5a..9034b76fe1df 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -6159,6 +6159,7 @@ F:	include/uapi/linux/mii.h
+ 
+ EXFAT FILE SYSTEM
+ M:	Valdis Kletnieks 
++L:	linux-fsdevel@vger.kernel.org
+ S:	Maintained
+ F:	drivers/staging/exfat/
+ 

commit 630d00b8b26de7d0487df6c45a3afbdae66475e6
+Author: Valdis Kletnieks 
+Date:   Thu Oct 24 11:53:19 2019 -0400
+
+    staging: exfat: Clean up return code - FFS_MEMORYERR
+    
+    Convert FFS_MEMORYERR to -ENOMEM
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191024155327.1095907-9-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index 8cb6d2e2ad8d..6142e880f682 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -218,7 +218,6 @@ static inline u16 get_row_index(u16 i)
+ #define FFS_NOTOPENED           12
+ #define FFS_MAXOPENED           13
+ #define FFS_EOF                 15
+-#define FFS_MEMORYERR           17
+ #define FFS_ERROR               19
+ 
+ #define NUM_UPCASE              2918
+diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
+index 0331fa6724ff..80fd3f0d6db4 100644
+--- a/drivers/staging/exfat/exfat_core.c
++++ b/drivers/staging/exfat/exfat_core.c
+@@ -544,7 +544,7 @@ s32 load_alloc_bitmap(struct super_block *sb)
+ 							       sizeof(struct buffer_head *),
+ 							       GFP_KERNEL);
+ 				if (!p_fs->vol_amap)
+-					return FFS_MEMORYERR;
++					return -ENOMEM;
+ 
+ 				sector = START_SECTOR(p_fs->map_clu);
+ 
+@@ -715,7 +715,7 @@ static s32 __load_upcase_table(struct super_block *sb, sector_t sector,
+ 	upcase_table = p_fs->vol_utbl = kmalloc(UTBL_COL_COUNT * sizeof(u16 *),
+ 						GFP_KERNEL);
+ 	if (!upcase_table)
+-		return FFS_MEMORYERR;
++		return -ENOMEM;
+ 	memset(upcase_table, 0, UTBL_COL_COUNT * sizeof(u16 *));
+ 
+ 	while (sector < end_sector) {
+@@ -755,7 +755,7 @@ static s32 __load_upcase_table(struct super_block *sb, sector_t sector,
+ 					upcase_table[col_index] = kmalloc_array(UTBL_ROW_COUNT,
+ 						sizeof(u16), GFP_KERNEL);
+ 					if (!upcase_table[col_index]) {
+-						ret = FFS_MEMORYERR;
++						ret = -ENOMEM;
+ 						goto error;
+ 					}
+ 
+@@ -795,7 +795,7 @@ static s32 __load_default_upcase_table(struct super_block *sb)
+ 	upcase_table = p_fs->vol_utbl = kmalloc(UTBL_COL_COUNT * sizeof(u16 *),
+ 						GFP_KERNEL);
+ 	if (!upcase_table)
+-		return FFS_MEMORYERR;
++		return -ENOMEM;
+ 	memset(upcase_table, 0, UTBL_COL_COUNT * sizeof(u16 *));
+ 
+ 	for (i = 0; index <= 0xFFFF && i < NUM_UPCASE * 2; i += 2) {
+@@ -818,7 +818,7 @@ static s32 __load_default_upcase_table(struct super_block *sb)
+ 									sizeof(u16),
+ 									GFP_KERNEL);
+ 				if (!upcase_table[col_index]) {
+-					ret = FFS_MEMORYERR;
++					ret = -ENOMEM;
+ 					goto error;
+ 				}
+ 

commit 03eac8d594738fc6a678a4df2176d17f9ee130f4
+Author: Valdis Kletnieks 
+Date:   Thu Oct 24 11:53:18 2019 -0400
+
+    staging: exfat: Clean up return codes - FFS_INVALIDPATH
+    
+    Convert FFS_INVALIDPATH to -EINVAL
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191024155327.1095907-8-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index b7dac748aaf9..8cb6d2e2ad8d 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -214,7 +214,6 @@ static inline u16 get_row_index(u16 i)
+ #define FFS_NOTMOUNTED          4
+ #define FFS_ALIGNMENTERR        5
+ #define FFS_SEMAPHOREERR        6
+-#define FFS_INVALIDPATH         7
+ #define FFS_INVALIDFID          8
+ #define FFS_NOTOPENED           12
+ #define FFS_MAXOPENED           13
+diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
+index 43aaa9566260..0331fa6724ff 100644
+--- a/drivers/staging/exfat/exfat_core.c
++++ b/drivers/staging/exfat/exfat_core.c
+@@ -2571,7 +2571,7 @@ s32 get_num_entries_and_dos_name(struct super_block *sb, struct chain_t *p_dir,
+ 
+ 	num_entries = p_fs->fs_func->calc_num_entries(p_uniname);
+ 	if (num_entries == 0)
+-		return FFS_INVALIDPATH;
++		return -EINVAL;
+ 
+ 	if (p_fs->vol_type != EXFAT) {
+ 		nls_uniname_to_dosname(sb, p_dosname, p_uniname, &lossy);
+@@ -2583,7 +2583,7 @@ s32 get_num_entries_and_dos_name(struct super_block *sb, struct chain_t *p_dir,
+ 		} else {
+ 			for (r = reserved_names; *r; r++) {
+ 				if (!strncmp((void *)p_dosname->name, *r, 8))
+-					return FFS_INVALIDPATH;
++					return -EINVAL;
+ 			}
+ 
+ 			if (p_dosname->name_case != 0xFF)
+@@ -2962,11 +2962,11 @@ s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir,
+ 	struct file_id_t *fid = &(EXFAT_I(inode)->fid);
+ 
+ 	if (strscpy(name_buf, path, sizeof(name_buf)) < 0)
+-		return FFS_INVALIDPATH;
++		return -EINVAL;
+ 
+ 	nls_cstring_to_uniname(sb, p_uniname, name_buf, &lossy);
+ 	if (lossy)
+-		return FFS_INVALIDPATH;
++		return -EINVAL;
+ 
+ 	fid->size = i_size_read(inode);
+ 
+@@ -3506,7 +3506,7 @@ s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
+ 	/* check if the source and target directory is the same */
+ 	if (fs_func->get_entry_type(epmov) == TYPE_DIR &&
+ 	    fs_func->get_entry_clu0(epmov) == p_newdir->dir)
+-		return FFS_INVALIDPATH;
++		return -EINVAL;
+ 
+ 	buf_lock(sb, sector_mov);
+ 
+diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
+index bc175b3366ac..dcf90b5f147b 100644
+--- a/drivers/staging/exfat/exfat_super.c
++++ b/drivers/staging/exfat/exfat_super.c
+@@ -2362,7 +2362,7 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+ 
+ 	err = ffsCreateFile(dir, (u8 *)dentry->d_name.name, FM_REGULAR, &fid);
+ 	if (err) {
+-		if (err == FFS_INVALIDPATH)
++		if (err == -EINVAL)
+ 			err = -EINVAL;
+ 		else if (err == -EEXIST)
+ 			err = -EEXIST;
+@@ -2573,7 +2573,7 @@ static int exfat_symlink(struct inode *dir, struct dentry *dentry,
+ 
+ 	err = ffsCreateFile(dir, (u8 *)dentry->d_name.name, FM_SYMLINK, &fid);
+ 	if (err) {
+-		if (err == FFS_INVALIDPATH)
++		if (err == -EINVAL)
+ 			err = -EINVAL;
+ 		else if (err == -EEXIST)
+ 			err = -EEXIST;
+@@ -2643,7 +2643,7 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+ 
+ 	err = ffsCreateDir(dir, (u8 *)dentry->d_name.name, &fid);
+ 	if (err) {
+-		if (err == FFS_INVALIDPATH)
++		if (err == -EINVAL)
+ 			err = -EINVAL;
+ 		else if (err == -EEXIST)
+ 			err = -EEXIST;
+@@ -2697,7 +2697,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
+ 
+ 	err = ffsRemoveDir(dir, &(EXFAT_I(inode)->fid));
+ 	if (err) {
+-		if (err == FFS_INVALIDPATH)
++		if (err == -EINVAL)
+ 			err = -EINVAL;
+ 		else if (err == -EEXIST)
+ 			err = -ENOTEMPTY;
+@@ -2754,7 +2754,7 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 	if (err) {
+ 		if (err == -EPERM)
+ 			err = -EPERM;
+-		else if (err == FFS_INVALIDPATH)
++		else if (err == -EINVAL)
+ 			err = -EINVAL;
+ 		else if (err == -EEXIST)
+ 			err = -EEXIST;

commit c76c4ad5470cd907ed9c432f0e8cabd924cc2b54
+Author: Valdis Kletnieks 
+Date:   Thu Oct 24 11:53:17 2019 -0400
+
+    staging: exfat: Clean up return codes - FFS_FILEEXIST
+    
+    Convert FFS_FILEEXIST to -EEXIST
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191024155327.1095907-7-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index 0c8e8606472b..b7dac748aaf9 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -216,7 +216,6 @@ static inline u16 get_row_index(u16 i)
+ #define FFS_SEMAPHOREERR        6
+ #define FFS_INVALIDPATH         7
+ #define FFS_INVALIDFID          8
+-#define FFS_FILEEXIST           10
+ #define FFS_NOTOPENED           12
+ #define FFS_MAXOPENED           13
+ #define FFS_EOF                 15
+diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
+index 5ac57e573764..43aaa9566260 100644
+--- a/drivers/staging/exfat/exfat_core.c
++++ b/drivers/staging/exfat/exfat_core.c
+@@ -2828,7 +2828,7 @@ s32 fat_generate_dos_name(struct super_block *sb, struct chain_t *p_dir,
+ 	}
+ 
+ 	if ((count == 0) || (count >= 1024))
+-		return FFS_FILEEXIST;
++		return -EEXIST;
+ 	fat_attach_count_to_dos_name(p_dosname->name, count);
+ 
+ 	/* Now dos_name has DOS~????.EXT */
+diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
+index cf0300a4e0f4..bc175b3366ac 100644
+--- a/drivers/staging/exfat/exfat_super.c
++++ b/drivers/staging/exfat/exfat_super.c
+@@ -1294,7 +1294,7 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid,
+ 			new_clu.flags = new_fid->flags;
+ 
+ 			if (!is_dir_empty(sb, &new_clu)) {
+-				ret = FFS_FILEEXIST;
++				ret = -EEXIST;
+ 				goto out;
+ 			}
+ 		}
+@@ -2162,7 +2162,7 @@ static int ffsRemoveDir(struct inode *inode, struct file_id_t *fid)
+ 	clu_to_free.flags = fid->flags;
+ 
+ 	if (!is_dir_empty(sb, &clu_to_free)) {
+-		ret = FFS_FILEEXIST;
++		ret = -EEXIST;
+ 		goto out;
+ 	}
+ 
+@@ -2364,7 +2364,7 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+ 	if (err) {
+ 		if (err == FFS_INVALIDPATH)
+ 			err = -EINVAL;
+-		else if (err == FFS_FILEEXIST)
++		else if (err == -EEXIST)
+ 			err = -EEXIST;
+ 		else if (err == -ENOSPC)
+ 			err = -ENOSPC;
+@@ -2575,7 +2575,7 @@ static int exfat_symlink(struct inode *dir, struct dentry *dentry,
+ 	if (err) {
+ 		if (err == FFS_INVALIDPATH)
+ 			err = -EINVAL;
+-		else if (err == FFS_FILEEXIST)
++		else if (err == -EEXIST)
+ 			err = -EEXIST;
+ 		else if (err == -ENOSPC)
+ 			err = -ENOSPC;
+@@ -2645,7 +2645,7 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+ 	if (err) {
+ 		if (err == FFS_INVALIDPATH)
+ 			err = -EINVAL;
+-		else if (err == FFS_FILEEXIST)
++		else if (err == -EEXIST)
+ 			err = -EEXIST;
+ 		else if (err == -ENOSPC)
+ 			err = -ENOSPC;
+@@ -2699,7 +2699,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
+ 	if (err) {
+ 		if (err == FFS_INVALIDPATH)
+ 			err = -EINVAL;
+-		else if (err == FFS_FILEEXIST)
++		else if (err == -EEXIST)
+ 			err = -ENOTEMPTY;
+ 		else if (err == -ENOENT)
+ 			err = -ENOENT;
+@@ -2756,7 +2756,7 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 			err = -EPERM;
+ 		else if (err == FFS_INVALIDPATH)
+ 			err = -EINVAL;
+-		else if (err == FFS_FILEEXIST)
++		else if (err == -EEXIST)
+ 			err = -EEXIST;
+ 		else if (err == -ENOENT)
+ 			err = -ENOENT;

commit ab5a321da0082f1877dab619f56b966997dbc4fb
+Author: Valdis Kletnieks 
+Date:   Thu Oct 24 11:53:16 2019 -0400
+
+    staging: exfat: Clean up return codes - FFS_NAMETOOLONG
+    
+    Convert FFS_NOTNAMETOOLONG to -ENAMETOOLONG
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191024155327.1095907-6-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index a6e0c79ba6a4..0c8e8606472b 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -221,7 +221,6 @@ static inline u16 get_row_index(u16 i)
+ #define FFS_MAXOPENED           13
+ #define FFS_EOF                 15
+ #define FFS_MEMORYERR           17
+-#define FFS_NAMETOOLONG		18
+ #define FFS_ERROR               19
+ 
+ #define NUM_UPCASE              2918
+diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
+index afa687a786a3..cf0300a4e0f4 100644
+--- a/drivers/staging/exfat/exfat_super.c
++++ b/drivers/staging/exfat/exfat_super.c
+@@ -2368,7 +2368,7 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+ 			err = -EEXIST;
+ 		else if (err == -ENOSPC)
+ 			err = -ENOSPC;
+-		else if (err == FFS_NAMETOOLONG)
++		else if (err == -ENAMETOOLONG)
+ 			err = -ENAMETOOLONG;
+ 		else
+ 			err = -EIO;
+@@ -2649,7 +2649,7 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+ 			err = -EEXIST;
+ 		else if (err == -ENOSPC)
+ 			err = -ENOSPC;
+-		else if (err == FFS_NAMETOOLONG)
++		else if (err == -ENAMETOOLONG)
+ 			err = -ENAMETOOLONG;
+ 		else
+ 			err = -EIO;

commit 7ca8049f09807004639dc7d44f1476ac6ef7c917
+Author: Valdis Kletnieks 
+Date:   Thu Oct 24 11:53:15 2019 -0400
+
+    staging: exfat: Clean up return codes - FFS_PERMISSIONERR
+    
+    Convert FFS_PERMISSIONERR to -EPERM
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191024155327.1095907-5-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index f3736b33ca56..a6e0c79ba6a4 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -217,7 +217,6 @@ static inline u16 get_row_index(u16 i)
+ #define FFS_INVALIDPATH         7
+ #define FFS_INVALIDFID          8
+ #define FFS_FILEEXIST           10
+-#define FFS_PERMISSIONERR       11
+ #define FFS_NOTOPENED           12
+ #define FFS_MAXOPENED           13
+ #define FFS_EOF                 15
+diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
+index 638de11eb625..afa687a786a3 100644
+--- a/drivers/staging/exfat/exfat_super.c
++++ b/drivers/staging/exfat/exfat_super.c
+@@ -708,7 +708,7 @@ static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer,
+ 
+ 	/* check if the given file ID is opened */
+ 	if (fid->type != TYPE_FILE) {
+-		ret = FFS_PERMISSIONERR;
++		ret = -EPERM;
+ 		goto out;
+ 	}
+ 
+@@ -838,7 +838,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
+ 
+ 	/* check if the given file ID is opened */
+ 	if (fid->type != TYPE_FILE) {
+-		ret = FFS_PERMISSIONERR;
++		ret = -EPERM;
+ 		goto out;
+ 	}
+ 
+@@ -1085,7 +1085,7 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size)
+ 
+ 	/* check if the given file ID is opened */
+ 	if (fid->type != TYPE_FILE) {
+-		ret = FFS_PERMISSIONERR;
++		ret = -EPERM;
+ 		goto out;
+ 	}
+ 
+@@ -1252,7 +1252,7 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid,
+ 	/* check if the old file is "." or ".." */
+ 	if (p_fs->vol_type != EXFAT) {
+ 		if ((olddir.dir != p_fs->root_dir) && (dentry < 2)) {
+-			ret = FFS_PERMISSIONERR;
++			ret = -EPERM;
+ 			goto out2;
+ 		}
+ 	}
+@@ -1264,7 +1264,7 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid,
+ 	}
+ 
+ 	if (p_fs->fs_func->get_entry_attr(ep) & ATTR_READONLY) {
+-		ret = FFS_PERMISSIONERR;
++		ret = -EPERM;
+ 		goto out2;
+ 	}
+ 
+@@ -1371,7 +1371,7 @@ static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid)
+ 	}
+ 
+ 	if (p_fs->fs_func->get_entry_attr(ep) & ATTR_READONLY) {
+-		ret = FFS_PERMISSIONERR;
++		ret = -EPERM;
+ 		goto out;
+ 	}
+ 	fs_set_vol_flags(sb, VOL_DIRTY);
+@@ -1953,7 +1953,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
+ 
+ 	/* check if the given file ID is opened */
+ 	if (fid->type != TYPE_DIR)
+-		return FFS_PERMISSIONERR;
++		return -EPERM;
+ 
+ 	/* acquire the lock for file system critical section */
+ 	down(&p_fs->v_sem);
+@@ -2151,7 +2151,7 @@ static int ffsRemoveDir(struct inode *inode, struct file_id_t *fid)
+ 	/* check if the file is "." or ".." */
+ 	if (p_fs->vol_type != EXFAT) {
+ 		if ((dir.dir != p_fs->root_dir) && (dentry < 2))
+-			return FFS_PERMISSIONERR;
++			return -EPERM;
+ 	}
+ 
+ 	/* acquire the lock for file system critical section */
+@@ -2532,7 +2532,7 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry)
+ 
+ 	err = ffsRemoveFile(dir, &(EXFAT_I(inode)->fid));
+ 	if (err) {
+-		if (err == FFS_PERMISSIONERR)
++		if (err == -EPERM)
+ 			err = -EPERM;
+ 		else
+ 			err = -EIO;
+@@ -2752,7 +2752,7 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 	err = ffsMoveFile(old_dir, &(EXFAT_I(old_inode)->fid), new_dir,
+ 			  new_dentry);
+ 	if (err) {
+-		if (err == FFS_PERMISSIONERR)
++		if (err == -EPERM)
+ 			err = -EPERM;
+ 		else if (err == FFS_INVALIDPATH)
+ 			err = -EINVAL;

commit df7098f84f7eff2cb0a669557f2519f1ee68a74e
+Author: Valdis Kletnieks 
+Date:   Thu Oct 24 11:53:14 2019 -0400
+
+    staging: exfat: Clean up return codes - FFS_DIRBUSY
+    
+    Convert FFS_DIRBUSY to -EBUSY
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191024155327.1095907-4-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index 26120dfcaba5..f3736b33ca56 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -221,7 +221,6 @@ static inline u16 get_row_index(u16 i)
+ #define FFS_NOTOPENED           12
+ #define FFS_MAXOPENED           13
+ #define FFS_EOF                 15
+-#define FFS_DIRBUSY             16
+ #define FFS_MEMORYERR           17
+ #define FFS_NAMETOOLONG		18
+ #define FFS_ERROR               19
+diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
+index 7b1ed81efadd..638de11eb625 100644
+--- a/drivers/staging/exfat/exfat_super.c
++++ b/drivers/staging/exfat/exfat_super.c
+@@ -2703,7 +2703,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
+ 			err = -ENOTEMPTY;
+ 		else if (err == -ENOENT)
+ 			err = -ENOENT;
+-		else if (err == FFS_DIRBUSY)
++		else if (err == -EBUSY)
+ 			err = -EBUSY;
+ 		else
+ 			err = -EIO;

commit 67f8224c3b52908c100311bfef9d0fb60ae5b449
+Author: Valdis Kletnieks 
+Date:   Thu Oct 24 11:53:13 2019 -0400
+
+    staging: exfat: Clean up return codes - FFS_NOTFOUND
+    
+    Convert FFS_NOTFOUND to -ENOENT
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191024155327.1095907-3-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index 548b7ada3c44..26120dfcaba5 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -216,7 +216,6 @@ static inline u16 get_row_index(u16 i)
+ #define FFS_SEMAPHOREERR        6
+ #define FFS_INVALIDPATH         7
+ #define FFS_INVALIDFID          8
+-#define FFS_NOTFOUND            9
+ #define FFS_FILEEXIST           10
+ #define FFS_PERMISSIONERR       11
+ #define FFS_NOTOPENED           12
+diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
+index 90ae0f2841f2..7b1ed81efadd 100644
+--- a/drivers/staging/exfat/exfat_super.c
++++ b/drivers/staging/exfat/exfat_super.c
+@@ -578,7 +578,7 @@ static int ffsLookupFile(struct inode *inode, char *path, struct file_id_t *fid)
+ 	dentry = p_fs->fs_func->find_dir_entry(sb, &dir, &uni_name, num_entries,
+ 					       &dos_name, TYPE_ALL);
+ 	if (dentry < -1) {
+-		ret = FFS_NOTFOUND;
++		ret = -ENOENT;
+ 		goto out;
+ 	}
+ 
+@@ -2701,7 +2701,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
+ 			err = -EINVAL;
+ 		else if (err == FFS_FILEEXIST)
+ 			err = -ENOTEMPTY;
+-		else if (err == FFS_NOTFOUND)
++		else if (err == -ENOENT)
+ 			err = -ENOENT;
+ 		else if (err == FFS_DIRBUSY)
+ 			err = -EBUSY;
+@@ -2758,7 +2758,7 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 			err = -EINVAL;
+ 		else if (err == FFS_FILEEXIST)
+ 			err = -EEXIST;
+-		else if (err == FFS_NOTFOUND)
++		else if (err == -ENOENT)
+ 			err = -ENOENT;
+ 		else if (err == -ENOSPC)
+ 			err = -ENOSPC;

commit 2f2e28866bd7bb1b4d73e338d22100d4edf710ec
+Author: Valdis Kletnieks 
+Date:   Thu Oct 24 11:53:12 2019 -0400
+
+    staging: exfat: Clean up return codes - FFS_FULL
+    
+    Start cleaning up the odd scheme of return codes, starting with FFS_FULL
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/20191024155327.1095907-2-Valdis.Kletnieks@vt.edu
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index 3abab33e932c..548b7ada3c44 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -221,7 +221,6 @@ static inline u16 get_row_index(u16 i)
+ #define FFS_PERMISSIONERR       11
+ #define FFS_NOTOPENED           12
+ #define FFS_MAXOPENED           13
+-#define FFS_FULL                14
+ #define FFS_EOF                 15
+ #define FFS_DIRBUSY             16
+ #define FFS_MEMORYERR           17
+diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
+index 79174e5c4145..5ac57e573764 100644
+--- a/drivers/staging/exfat/exfat_core.c
++++ b/drivers/staging/exfat/exfat_core.c
+@@ -3216,7 +3216,7 @@ s32 create_dir(struct inode *inode, struct chain_t *p_dir,
+ 	/* find_empty_entry must be called before alloc_cluster */
+ 	dentry = find_empty_entry(inode, p_dir, num_entries);
+ 	if (dentry < 0)
+-		return FFS_FULL;
++		return -ENOSPC;
+ 
+ 	clu.dir = CLUSTER_32(~0);
+ 	clu.size = 0;
+@@ -3227,7 +3227,7 @@ s32 create_dir(struct inode *inode, struct chain_t *p_dir,
+ 	if (ret < 0)
+ 		return FFS_MEDIAERR;
+ 	else if (ret == 0)
+-		return FFS_FULL;
++		return -ENOSPC;
+ 
+ 	ret = clear_cluster(sb, clu.dir);
+ 	if (ret != FFS_SUCCESS)
+@@ -3319,7 +3319,7 @@ s32 create_file(struct inode *inode, struct chain_t *p_dir,
+ 	/* find_empty_entry must be called before alloc_cluster() */
+ 	dentry = find_empty_entry(inode, p_dir, num_entries);
+ 	if (dentry < 0)
+-		return FFS_FULL;
++		return -ENOSPC;
+ 
+ 	/* (1) update the directory entry */
+ 	/* fill the dos name directory entry information of the created file.
+@@ -3418,7 +3418,7 @@ s32 rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry,
+ 		newentry = find_empty_entry(inode, p_dir, num_new_entries);
+ 		if (newentry < 0) {
+ 			buf_unlock(sb, sector_old);
+-			return FFS_FULL;
++			return -ENOSPC;
+ 		}
+ 
+ 		epnew = get_entry_in_dir(sb, p_dir, newentry, §or_new);
+@@ -3529,7 +3529,7 @@ s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
+ 	newentry = find_empty_entry(inode, p_newdir, num_new_entries);
+ 	if (newentry < 0) {
+ 		buf_unlock(sb, sector_mov);
+-		return FFS_FULL;
++		return -ENOSPC;
+ 	}
+ 
+ 	epnew = get_entry_in_dir(sb, p_newdir, newentry, §or_new);
+diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
+index 86ace780a60b..90ae0f2841f2 100644
+--- a/drivers/staging/exfat/exfat_super.c
++++ b/drivers/staging/exfat/exfat_super.c
+@@ -1051,7 +1051,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
+ 		*wcount = write_bytes;
+ 
+ 	if (num_alloced == 0)
+-		ret = FFS_FULL;
++		ret = -ENOSPC;
+ 
+ 	else if (p_fs->dev_ejected)
+ 		ret = FFS_MEDIAERR;
+@@ -1807,7 +1807,7 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
+ 			ret = FFS_MEDIAERR;
+ 			goto out;
+ 		} else if (num_alloced == 0) {
+-			ret = FFS_FULL;
++			ret = -ENOSPC;
+ 			goto out;
+ 		}
+ 
+@@ -2366,7 +2366,7 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+ 			err = -EINVAL;
+ 		else if (err == FFS_FILEEXIST)
+ 			err = -EEXIST;
+-		else if (err == FFS_FULL)
++		else if (err == -ENOSPC)
+ 			err = -ENOSPC;
+ 		else if (err == FFS_NAMETOOLONG)
+ 			err = -ENAMETOOLONG;
+@@ -2577,7 +2577,7 @@ static int exfat_symlink(struct inode *dir, struct dentry *dentry,
+ 			err = -EINVAL;
+ 		else if (err == FFS_FILEEXIST)
+ 			err = -EEXIST;
+-		else if (err == FFS_FULL)
++		else if (err == -ENOSPC)
+ 			err = -ENOSPC;
+ 		else
+ 			err = -EIO;
+@@ -2589,7 +2589,7 @@ static int exfat_symlink(struct inode *dir, struct dentry *dentry,
+ 	if (err) {
+ 		ffsRemoveFile(dir, &fid);
+ 
+-		if (err == FFS_FULL)
++		if (err == -ENOSPC)
+ 			err = -ENOSPC;
+ 		else
+ 			err = -EIO;
+@@ -2647,7 +2647,7 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+ 			err = -EINVAL;
+ 		else if (err == FFS_FILEEXIST)
+ 			err = -EEXIST;
+-		else if (err == FFS_FULL)
++		else if (err == -ENOSPC)
+ 			err = -ENOSPC;
+ 		else if (err == FFS_NAMETOOLONG)
+ 			err = -ENAMETOOLONG;
+@@ -2760,7 +2760,7 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 			err = -EEXIST;
+ 		else if (err == FFS_NOTFOUND)
+ 			err = -ENOENT;
+-		else if (err == FFS_FULL)
++		else if (err == -ENOSPC)
+ 			err = -ENOSPC;
+ 		else
+ 			err = -EIO;
+@@ -3115,7 +3115,7 @@ static int exfat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
+ 	err = ffsMapCluster(inode, clu_offset, &cluster);
+ 
+ 	if (err) {
+-		if (err == FFS_FULL)
++		if (err == -ENOSPC)
+ 			return -ENOSPC;
+ 		else
+ 			return -EIO;

commit d98bb9c2fec01254d2e04e1eed51dde9ae611314
+Author: Valdis Kletnieks 
+Date:   Wed Oct 2 15:01:35 2019 -0400
+
+    staging: exfat: explain the fs_sync() issue in TODO
+    
+    We've seen several incorrect patches for fs_sync() calls in the exfat driver.
+    Add code to the TODO that explains this isn't just a delete code and refactor,
+    but that actual analysis of when the filesystem should be flushed to disk
+    needs to be done.
+    
+    Signed-off-by: Valdis Kletnieks 
+    
+    Link: https://lore.kernel.org/r/9837.1570042895@turing-police
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/TODO b/drivers/staging/exfat/TODO
+index a3eb282f9efc..b60e50b9cf4e 100644
+--- a/drivers/staging/exfat/TODO
++++ b/drivers/staging/exfat/TODO
+@@ -3,6 +3,15 @@ same for ffsWriteFile.
+ 
+ exfat_core.c - fs_sync(sb,0) all over the place looks fishy as hell.
+ There's only one place that calls it with a non-zero argument.
++Randomly removing fs_sync() calls is *not* the right answer, especially
++if the removal then leaves a call to fs_set_vol_flags(VOL_CLEAN), as that
++says the file system is clean and synced when we *know* it isn't.
++The proper fix here is to go through and actually analyze how DELAYED_SYNC
++should work, and any time we're setting VOL_CLEAN, ensure the file system
++has in fact been synced to disk.  In other words, changing the 'false' to
++'true' is probably more correct. Also, it's likely that the one current
++place where it actually does an bdev_sync isn't sufficient in the DELAYED_SYNC
++case.
+ 
+ ffsTruncateFile -  if (old_size <= new_size) {
+ That doesn't look right. How did it ever work? Are they relying on lazy

commit 8789f13ddc77723e9451548b984382605340899c
+Author: Valdis Kletnieks 
+Date:   Wed Oct 2 15:16:24 2019 -0400
+
+    staging: exfat: fix fs_sync() calls.
+    
+    The majority of them were totally backwards.  Change the logic
+    so that if DELAYED_SYNC *isn't* in the config, we actually flush to disk
+    before flagging the file system as clean.
+    
+    That leaves two calls in the DELAYED_SYNC case.  More detailed
+    analysis is needed to make sure that's what's really needed, or if other
+    call sites also need a fs_sync() call.  This patch is at least "less wrong"
+    than the code was, but further changes should be another patch.
+    
+    Signed-off-by: Valdis Kletnieks 
+    
+    Link: https://lore.kernel.org/r/11092.1570043784@turing-police
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
+index 5f6caee819a6..2526044569ee 100644
+--- a/drivers/staging/exfat/exfat_super.c
++++ b/drivers/staging/exfat/exfat_super.c
+@@ -458,7 +458,7 @@ static int ffsUmountVol(struct super_block *sb)
+ 	/* acquire the lock for file system critical section */
+ 	down(&p_fs->v_sem);
+ 
+-	fs_sync(sb, false);
++	fs_sync(sb, true);
+ 	fs_set_vol_flags(sb, VOL_CLEAN);
+ 
+ 	if (p_fs->vol_type == EXFAT) {
+@@ -666,8 +666,8 @@ static int ffsCreateFile(struct inode *inode, char *path, u8 mode,
+ 	/* create a new file */
+ 	ret = create_file(inode, &dir, &uni_name, mode, fid);
+ 
+-#ifdef CONFIG_EXFAT_DELAYED_SYNC
+-	fs_sync(sb, false);
++#ifndef CONFIG_EXFAT_DELAYED_SYNC
++	fs_sync(sb, true);
+ 	fs_set_vol_flags(sb, VOL_CLEAN);
+ #endif
+ 
+@@ -1039,8 +1039,8 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
+ 		release_entry_set(es);
+ 	}
+ 
+-#ifdef CONFIG_EXFAT_DELAYED_SYNC
+-	fs_sync(sb, false);
++#ifndef CONFIG_EXFAT_DELAYED_SYNC
++	fs_sync(sb, true);
+ 	fs_set_vol_flags(sb, VOL_CLEAN);
+ #endif
+ 
+@@ -1179,8 +1179,8 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size)
+ 	if (fid->rwoffset > fid->size)
+ 		fid->rwoffset = fid->size;
+ 
+-#ifdef CONFIG_EXFAT_DELAYED_SYNC
+-	fs_sync(sb, false);
++#ifndef CONFIG_EXFAT_DELAYED_SYNC
++	fs_sync(sb, true);
+ 	fs_set_vol_flags(sb, VOL_CLEAN);
+ #endif
+ 
+@@ -1327,8 +1327,8 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid,
+ 						num_entries + 1);
+ 	}
+ out:
+-#ifdef CONFIG_EXFAT_DELAYED_SYNC
+-	fs_sync(sb, false);
++#ifndef CONFIG_EXFAT_DELAYED_SYNC
++	fs_sync(sb, true);
+ 	fs_set_vol_flags(sb, VOL_CLEAN);
+ #endif
+ 
+@@ -1389,8 +1389,8 @@ static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid)
+ 	fid->start_clu = CLUSTER_32(~0);
+ 	fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01;
+ 
+-#ifdef CONFIG_EXFAT_DELAYED_SYNC
+-	fs_sync(sb, false);
++#ifndef CONFIG_EXFAT_DELAYED_SYNC
++	fs_sync(sb, true);
+ 	fs_set_vol_flags(sb, VOL_CLEAN);
+ #endif
+ 
+@@ -1478,8 +1478,8 @@ static int ffsSetAttr(struct inode *inode, u32 attr)
+ 		release_entry_set(es);
+ 	}
+ 
+-#ifdef CONFIG_EXFAT_DELAYED_SYNC
+-	fs_sync(sb, false);
++#ifndef CONFIG_EXFAT_DELAYED_SYNC
++	fs_sync(sb, true);
+ 	fs_set_vol_flags(sb, VOL_CLEAN);
+ #endif
+ 
+@@ -1916,8 +1916,8 @@ static int ffsCreateDir(struct inode *inode, char *path, struct file_id_t *fid)
+ 
+ 	ret = create_dir(inode, &dir, &uni_name, fid);
+ 
+-#ifdef CONFIG_EXFAT_DELAYED_SYNC
+-	fs_sync(sb, false);
++#ifndef CONFIG_EXFAT_DELAYED_SYNC
++	fs_sync(sb, true);
+ 	fs_set_vol_flags(sb, VOL_CLEAN);
+ #endif
+ 
+@@ -2177,8 +2177,8 @@ static int ffsRemoveDir(struct inode *inode, struct file_id_t *fid)
+ 	fid->start_clu = CLUSTER_32(~0);
+ 	fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01;
+ 
+-#ifdef CONFIG_EXFAT_DELAYED_SYNC
+-	fs_sync(sb, false);
++#ifndef CONFIG_EXFAT_DELAYED_SYNC
++	fs_sync(sb, true);
+ 	fs_set_vol_flags(sb, VOL_CLEAN);
+ #endif
+ 

commit a358eea07c78d9d0c246738ed1c6349d72d41920
+Author: Valdis Kletnieks 
+Date:   Wed Sep 18 20:38:08 2019 -0400
+
+    staging: exfat - fix SPDX tags..
+    
+    The copyright notices as I got them said "GPLv2 or later", which I
+    screwed up when putting in the SPDX tags.  Fix them to match the
+    license I got the code under.
+    
+    Signed-off-by: Valdis Kletnieks 
+    
+    Link: https://lore.kernel.org/r/122590.1568853488@turing-police
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/Makefile b/drivers/staging/exfat/Makefile
+index 84944dfbae28..6c90aec83feb 100644
+--- a/drivers/staging/exfat/Makefile
++++ b/drivers/staging/exfat/Makefile
+@@ -1,4 +1,4 @@
+-# SPDX-License-Identifier: GPL-2.0
++# SPDX-License-Identifier: GPL-2.0-or-later
+ 
+ obj-$(CONFIG_EXFAT_FS) += exfat.o
+ 
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+index 6c12f2d79f4d..3abab33e932c 100644
+--- a/drivers/staging/exfat/exfat.h
++++ b/drivers/staging/exfat/exfat.h
+@@ -1,4 +1,4 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
++/* SPDX-License-Identifier: GPL-2.0-or-later */
+ /*
+  *  Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
+  */
+diff --git a/drivers/staging/exfat/exfat_blkdev.c b/drivers/staging/exfat/exfat_blkdev.c
+index f086c75e7076..81d20e6241c6 100644
+--- a/drivers/staging/exfat/exfat_blkdev.c
++++ b/drivers/staging/exfat/exfat_blkdev.c
+@@ -1,4 +1,4 @@
+-// SPDX-License-Identifier: GPL-2.0
++// SPDX-License-Identifier: GPL-2.0-or-later
+ /*
+  *  Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
+  */
+diff --git a/drivers/staging/exfat/exfat_cache.c b/drivers/staging/exfat/exfat_cache.c
+index 1565ce65d39f..e1b001718709 100644
+--- a/drivers/staging/exfat/exfat_cache.c
++++ b/drivers/staging/exfat/exfat_cache.c
+@@ -1,4 +1,4 @@
+-// SPDX-License-Identifier: GPL-2.0
++// SPDX-License-Identifier: GPL-2.0-or-later
+ /*
+  *  Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
+  */
+diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
+index b3e9cf725cf5..79174e5c4145 100644
+--- a/drivers/staging/exfat/exfat_core.c
++++ b/drivers/staging/exfat/exfat_core.c
+@@ -1,4 +1,4 @@
+-// SPDX-License-Identifier: GPL-2.0
++// SPDX-License-Identifier: GPL-2.0-or-later
+ /*
+  *  Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
+  */
+diff --git a/drivers/staging/exfat/exfat_nls.c b/drivers/staging/exfat/exfat_nls.c
+index 03cb8290b5d2..a5c4b68925fb 100644
+--- a/drivers/staging/exfat/exfat_nls.c
++++ b/drivers/staging/exfat/exfat_nls.c
+@@ -1,4 +1,4 @@
+-// SPDX-License-Identifier: GPL-2.0
++// SPDX-License-Identifier: GPL-2.0-or-later
+ /*
+  *  Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
+  */
+diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
+index 5f6caee819a6..229ecabe7a93 100644
+--- a/drivers/staging/exfat/exfat_super.c
++++ b/drivers/staging/exfat/exfat_super.c
+@@ -1,4 +1,4 @@
+-// SPDX-License-Identifier: GPL-2.0
++// SPDX-License-Identifier: GPL-2.0-or-later
+ /*
+  *  Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
+  */
+diff --git a/drivers/staging/exfat/exfat_upcase.c b/drivers/staging/exfat/exfat_upcase.c
+index 366082fb3dab..b91a1faa0e50 100644
+--- a/drivers/staging/exfat/exfat_upcase.c
++++ b/drivers/staging/exfat/exfat_upcase.c
+@@ -1,4 +1,4 @@
+-// SPDX-License-Identifier: GPL-2.0
++// SPDX-License-Identifier: GPL-2.0-or-later
+ /*
+  *  Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
+  */

commit 8e72a7a44df5534ae7664240c1fa75e71e11c64a
+Author: Valdis Kletnieks 
+Date:   Wed Sep 25 16:46:26 2019 -0700
+
+    lib/extable.c: add missing prototypes
+    
+    When building with W=1, a number of warnings are issued:
+    
+      CC      lib/extable.o
+    lib/extable.c:63:6: warning: no previous prototype for 'sort_extable' [-Wmissing-prototypes]
+       63 | void sort_extable(struct exception_table_entry *start,
+          |      ^~~~~~~~~~~~
+    lib/extable.c:75:6: warning: no previous prototype for 'trim_init_extable' [-Wmissing-prototypes]
+       75 | void trim_init_extable(struct module *m)
+          |      ^~~~~~~~~~~~~~~~~
+    lib/extable.c:115:1: warning: no previous prototype for 'search_extable' [-Wmissing-prototypes]
+      115 | search_extable(const struct exception_table_entry *base,
+          | ^~~~~~~~~~~~~~
+    
+    Add the missing #include for the prototypes.
+    
+    Link: http://lkml.kernel.org/r/45574.1565235784@turing-police
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/lib/extable.c b/lib/extable.c
+index 25da4071122a..c3e59caf7ffa 100644
+--- a/lib/extable.c
++++ b/lib/extable.c
+@@ -10,6 +10,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #ifndef ARCH_HAS_RELATIVE_EXTABLE
+ #define ex_to_insn(x)	((x)->insn)

commit e3f4faa42095cacceeb33c68fda647a8e6d48a90
+Author: Valdis Kletnieks 
+Date:   Wed Sep 25 16:46:23 2019 -0700
+
+    lib/generic-radix-tree.c: make 2 functions static inline
+    
+    When building with W=1, we get some warnings:
+    
+    l  CC      lib/generic-radix-tree.o
+    lib/generic-radix-tree.c:39:10: warning: no previous prototype for 'genradix_root_to_depth' [-Wmissing-prototypes]
+       39 | unsigned genradix_root_to_depth(struct genradix_root *r)
+          |          ^~~~~~~~~~~~~~~~~~~~~~
+    lib/generic-radix-tree.c:44:23: warning: no previous prototype for 'genradix_root_to_node' [-Wmissing-prototypes]
+       44 | struct genradix_node *genradix_root_to_node(struct genradix_root *r)
+          |                       ^~~~~~~~~~~~~~~~~~~~~
+    
+    They're not used anywhere else, so make them static inline.
+    
+    Link: http://lkml.kernel.org/r/46923.1565236485@turing-police
+    Signed-off-by: Valdis Kletnieks 
+    Cc: Kent Overstreet 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/lib/generic-radix-tree.c b/lib/generic-radix-tree.c
+index a7bafc413730..ae25e2fa2187 100644
+--- a/lib/generic-radix-tree.c
++++ b/lib/generic-radix-tree.c
+@@ -36,12 +36,12 @@ static inline size_t genradix_depth_size(unsigned depth)
+ #define GENRADIX_DEPTH_MASK				\
+ 	((unsigned long) (roundup_pow_of_two(GENRADIX_MAX_DEPTH + 1) - 1))
+ 
+-unsigned genradix_root_to_depth(struct genradix_root *r)
++static inline unsigned genradix_root_to_depth(struct genradix_root *r)
+ {
+ 	return (unsigned long) r & GENRADIX_DEPTH_MASK;
+ }
+ 
+-struct genradix_node *genradix_root_to_node(struct genradix_root *r)
++static inline struct genradix_node *genradix_root_to_node(struct genradix_root *r)
+ {
+ 	return (void *) ((unsigned long) r & ~GENRADIX_DEPTH_MASK);
+ }

commit 0f74914071ab7e7b78731ed62bf350e3a344e0a5
+Author: Valdis Kletnieks 
+Date:   Wed Sep 25 16:45:59 2019 -0700
+
+    kernel/elfcore.c: include proper prototypes
+    
+    When building with W=1, gcc properly complains that there's no prototypes:
+    
+      CC      kernel/elfcore.o
+    kernel/elfcore.c:7:17: warning: no previous prototype for 'elf_core_extra_phdrs' [-Wmissing-prototypes]
+        7 | Elf_Half __weak elf_core_extra_phdrs(void)
+          |                 ^~~~~~~~~~~~~~~~~~~~
+    kernel/elfcore.c:12:12: warning: no previous prototype for 'elf_core_write_extra_phdrs' [-Wmissing-prototypes]
+       12 | int __weak elf_core_write_extra_phdrs(struct coredump_params *cprm, loff_t offset)
+          |            ^~~~~~~~~~~~~~~~~~~~~~~~~~
+    kernel/elfcore.c:17:12: warning: no previous prototype for 'elf_core_write_extra_data' [-Wmissing-prototypes]
+       17 | int __weak elf_core_write_extra_data(struct coredump_params *cprm)
+          |            ^~~~~~~~~~~~~~~~~~~~~~~~~
+    kernel/elfcore.c:22:15: warning: no previous prototype for 'elf_core_extra_data_size' [-Wmissing-prototypes]
+       22 | size_t __weak elf_core_extra_data_size(void)
+          |               ^~~~~~~~~~~~~~~~~~~~~~~~
+    
+    Provide the include file so gcc is happy, and we don't have potential code drift
+    
+    Link: http://lkml.kernel.org/r/29875.1565224705@turing-police
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/kernel/elfcore.c b/kernel/elfcore.c
+index fc482c8e0bd8..57fb4dcff434 100644
+--- a/kernel/elfcore.c
++++ b/kernel/elfcore.c
+@@ -3,6 +3,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ Elf_Half __weak elf_core_extra_phdrs(void)
+ {

commit b6326fc025aa998daa62672731ecfdcc22f43771
+Author: Valdis Kletnieks 
+Date:   Wed Aug 7 21:51:58 2019 -0400
+
+    rtlwifi: fix non-kerneldoc comment in usb.c
+    
+    Fix spurious warning message when building with W=1:
+    
+      CC [M]  drivers/net/wireless/realtek/rtlwifi/usb.o
+    drivers/net/wireless/realtek/rtlwifi/usb.c:243: warning: Cannot understand  * on line 243 - I thought it was a doc line
+    drivers/net/wireless/realtek/rtlwifi/usb.c:760: warning: Cannot understand  * on line 760 - I thought it was a doc line
+    drivers/net/wireless/realtek/rtlwifi/usb.c:790: warning: Cannot understand  * on line 790 - I thought it was a doc line
+    
+    Clean up the comment format.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Kalle Valo 
+
+diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c
+index 34d68dbf4b4c..4b59f3b46b28 100644
+--- a/drivers/net/wireless/realtek/rtlwifi/usb.c
++++ b/drivers/net/wireless/realtek/rtlwifi/usb.c
+@@ -239,10 +239,7 @@ static void _rtl_usb_io_handler_release(struct ieee80211_hw *hw)
+ 	mutex_destroy(&rtlpriv->io.bb_mutex);
+ }
+ 
+-/**
+- *
+- *	Default aggregation handler. Do nothing and just return the oldest skb.
+- */
++/*	Default aggregation handler. Do nothing and just return the oldest skb.  */
+ static struct sk_buff *_none_usb_tx_aggregate_hdl(struct ieee80211_hw *hw,
+ 						  struct sk_buff_head *list)
+ {
+@@ -756,11 +753,6 @@ static int rtl_usb_start(struct ieee80211_hw *hw)
+ 	return err;
+ }
+ 
+-/**
+- *
+- *
+- */
+-
+ /*=======================  tx =========================================*/
+ static void rtl_usb_cleanup(struct ieee80211_hw *hw)
+ {
+@@ -786,11 +778,7 @@ static void rtl_usb_cleanup(struct ieee80211_hw *hw)
+ 	usb_kill_anchored_urbs(&rtlusb->tx_submitted);
+ }
+ 
+-/**
+- *
+- * We may add some struct into struct rtl_usb later. Do deinit here.
+- *
+- */
++/* We may add some struct into struct rtl_usb later. Do deinit here.  */
+ static void rtl_usb_deinit(struct ieee80211_hw *hw)
+ {
+ 	rtl_usb_cleanup(hw);

commit d9f3b450f206332b7ef3d78b5a85b6c20ad00fd2
+Author: Valdis Kletnieks 
+Date:   Thu Aug 8 13:44:02 2019 -0400
+
+    perf/x86: Make more stuff static
+    
+    When building with C=2, sparse makes note of a number of things:
+    
+      arch/x86/events/intel/rapl.c:637:30: warning: symbol 'rapl_attr_update' was not declared. Should it be static?
+      arch/x86/events/intel/cstate.c:449:30: warning: symbol 'core_attr_update' was not declared. Should it be static?
+      arch/x86/events/intel/cstate.c:457:30: warning: symbol 'pkg_attr_update' was not declared. Should it be static?
+      arch/x86/events/msr.c:170:30: warning: symbol 'attr_update' was not declared. Should it be static?
+      arch/x86/events/intel/lbr.c:276:1: warning: symbol 'lbr_from_quirk_key' was not declared. Should it be static?
+    
+    And they can all indeed be static.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Peter Zijlstra (Intel) 
+    Cc: Alexander Shishkin 
+    Cc: Arnaldo Carvalho de Melo 
+    Cc: Jiri Olsa 
+    Cc: Linus Torvalds 
+    Cc: Peter Zijlstra 
+    Cc: Thomas Gleixner 
+    Link: https://lkml.kernel.org/r/128059.1565286242@turing-police
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/x86/events/intel/cstate.c b/arch/x86/events/intel/cstate.c
+index 688592b34564..db498b5d4aae 100644
+--- a/arch/x86/events/intel/cstate.c
++++ b/arch/x86/events/intel/cstate.c
+@@ -446,7 +446,7 @@ static int cstate_cpu_init(unsigned int cpu)
+ 	return 0;
+ }
+ 
+-const struct attribute_group *core_attr_update[] = {
++static const struct attribute_group *core_attr_update[] = {
+ 	&group_cstate_core_c1,
+ 	&group_cstate_core_c3,
+ 	&group_cstate_core_c6,
+@@ -454,7 +454,7 @@ const struct attribute_group *core_attr_update[] = {
+ 	NULL,
+ };
+ 
+-const struct attribute_group *pkg_attr_update[] = {
++static const struct attribute_group *pkg_attr_update[] = {
+ 	&group_cstate_pkg_c2,
+ 	&group_cstate_pkg_c3,
+ 	&group_cstate_pkg_c6,
+diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c
+index 6f814a27416b..ea54634eabf3 100644
+--- a/arch/x86/events/intel/lbr.c
++++ b/arch/x86/events/intel/lbr.c
+@@ -273,7 +273,7 @@ static inline bool lbr_from_signext_quirk_needed(void)
+ 	return !tsx_support && (lbr_desc[lbr_format] & LBR_TSX);
+ }
+ 
+-DEFINE_STATIC_KEY_FALSE(lbr_from_quirk_key);
++static DEFINE_STATIC_KEY_FALSE(lbr_from_quirk_key);
+ 
+ /* If quirk is enabled, ensure sign extension is 63 bits: */
+ inline u64 lbr_from_signext_quirk_wr(u64 val)
+diff --git a/arch/x86/events/intel/rapl.c b/arch/x86/events/intel/rapl.c
+index 64ab51ffdf06..f34b9491ea6e 100644
+--- a/arch/x86/events/intel/rapl.c
++++ b/arch/x86/events/intel/rapl.c
+@@ -634,7 +634,7 @@ static void cleanup_rapl_pmus(void)
+ 	kfree(rapl_pmus);
+ }
+ 
+-const struct attribute_group *rapl_attr_update[] = {
++static const struct attribute_group *rapl_attr_update[] = {
+ 	&rapl_events_cores_group,
+ 	&rapl_events_pkg_group,
+ 	&rapl_events_ram_group,
+diff --git a/arch/x86/events/msr.c b/arch/x86/events/msr.c
+index 9431447541e9..5812e8747d1f 100644
+--- a/arch/x86/events/msr.c
++++ b/arch/x86/events/msr.c
+@@ -167,7 +167,7 @@ static const struct attribute_group *attr_groups[] = {
+ 	NULL,
+ };
+ 
+-const struct attribute_group *attr_update[] = {
++static const struct attribute_group *attr_update[] = {
+ 	&group_aperf,
+ 	&group_mperf,
+ 	&group_pperf,

commit 58985a9d2d03e977db93bf574a16162766a318fe
+Author: Valdis Kletnieks 
+Date:   Fri Aug 30 12:42:39 2019 -0400
+
+    drivers/staging/exfat - by default, prohibit mount of fat/vfat
+    
+    Concerns have been raised about the exfat driver accidentally mounting
+    fat/vfat file systems.  Add an extra configure option to help prevent that.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Link: https://lore.kernel.org/r/245727.1567183359@turing-police
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/exfat/Kconfig b/drivers/staging/exfat/Kconfig
+index 78b32aa2ca19..f52129c67f97 100644
+--- a/drivers/staging/exfat/Kconfig
++++ b/drivers/staging/exfat/Kconfig
+@@ -4,6 +4,14 @@ config EXFAT_FS
+ 	help
+ 	  This adds support for the exFAT file system.
+ 
++config EXFAT_DONT_MOUNT_VFAT
++	bool "Prohibit mounting of fat/vfat filesysems by exFAT"
++	default y
++	help
++	  By default, the exFAT driver will only mount exFAT filesystems, and refuse
++	  to mount fat/vfat filesystems.  Set this to 'n' to allow the exFAT driver
++	  to mount these filesystems.
++
+ config EXFAT_DISCARD
+ 	bool "enable discard support"
+ 	depends on EXFAT_FS
+diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
+index 5b5c2ca8c9aa..d9787635a373 100644
+--- a/drivers/staging/exfat/exfat_super.c
++++ b/drivers/staging/exfat/exfat_super.c
+@@ -486,10 +486,16 @@ static int ffsMountVol(struct super_block *sb)
+ 			break;
+ 
+ 	if (i < 53) {
++#ifdef CONFIG_EXFAT_DONT_MOUNT_VFAT
++		ret = -EINVAL;
++		printk(KERN_INFO "EXFAT: Attempted to mount VFAT filesystem\n");
++		goto out;
++#else
+ 		if (GET16(p_pbr->bpb + 11)) /* num_fat_sectors */
+ 			ret = fat16_mount(sb, p_pbr);
+ 		else
+ 			ret = fat32_mount(sb, p_pbr);
++#endif
+ 	} else {
+ 		ret = exfat_mount(sb, p_pbr);
+ 	}

commit c48c9f7ff32b8b3965a08e40eb6763682d905b5d
+Author: Valdis Kletnieks 
+Date:   Wed Aug 28 18:08:17 2019 +0200
+
+    staging: exfat: add exfat filesystem code to staging
+    
+    The exfat code needs a lot of work to get it into "real" shape for
+    the fs/ part of the kernel, so put it into drivers/staging/ for now so
+    that it can be worked on by everyone in the community.
+    
+    The full specification of the filesystem can be found at:
+      https://docs.microsoft.com/en-us/windows/win32/fileio/exfat-specification
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Sasha Levin 
+    Signed-off-by: Greg Kroah-Hartman 
+    Link: https://lore.kernel.org/r/20190828160817.6250-1-gregkh@linuxfoundation.org
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index e3242687cd19..a484b36e5117 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -6097,6 +6097,11 @@ F:	include/trace/events/mdio.h
+ F:	include/uapi/linux/mdio.h
+ F:	include/uapi/linux/mii.h
+ 
++EXFAT FILE SYSTEM
++M:	Valdis Kletnieks 
++S:	Maintained
++F:	fs/exfat/
++
+ EXT2 FILE SYSTEM
+ M:	Jan Kara 
+ L:	linux-ext4@vger.kernel.org
+diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
+index d972ec8e71fb..fbdc33874780 100644
+--- a/drivers/staging/Kconfig
++++ b/drivers/staging/Kconfig
+@@ -118,4 +118,6 @@ source "drivers/staging/kpc2000/Kconfig"
+ 
+ source "drivers/staging/isdn/Kconfig"
+ 
++source "drivers/staging/exfat/Kconfig"
++
+ endif # STAGING
+diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
+index 6018b9a4a077..ca13f87b1e1b 100644
+--- a/drivers/staging/Makefile
++++ b/drivers/staging/Makefile
+@@ -49,3 +49,4 @@ obj-$(CONFIG_XIL_AXIS_FIFO)	+= axis-fifo/
+ obj-$(CONFIG_FIELDBUS_DEV)     += fieldbus/
+ obj-$(CONFIG_KPC2000)		+= kpc2000/
+ obj-$(CONFIG_ISDN_CAPI)		+= isdn/
++obj-$(CONFIG_EXFAT_FS)		+= exfat/
+diff --git a/drivers/staging/exfat/Kconfig b/drivers/staging/exfat/Kconfig
+new file mode 100644
+index 000000000000..78b32aa2ca19
+--- /dev/null
++++ b/drivers/staging/exfat/Kconfig
+@@ -0,0 +1,39 @@
++config EXFAT_FS
++	tristate "exFAT fs support"
++	select NLS
++	help
++	  This adds support for the exFAT file system.
++
++config EXFAT_DISCARD
++	bool "enable discard support"
++	depends on EXFAT_FS
++	default y
++
++config EXFAT_DELAYED_SYNC
++	bool "enable delayed sync"
++	depends on EXFAT_FS
++	default n
++
++config EXFAT_KERNEL_DEBUG
++	bool "enable kernel debug features via ioctl"
++	depends on EXFAT_FS
++	default n
++
++config EXFAT_DEBUG_MSG
++	bool "print debug messages"
++	depends on EXFAT_FS
++	default n
++
++config EXFAT_DEFAULT_CODEPAGE
++	int "Default codepage for exFAT"
++	default 437
++	depends on EXFAT_FS
++	help
++	  This option should be set to the codepage of your exFAT filesystems.
++
++config EXFAT_DEFAULT_IOCHARSET
++	string "Default iocharset for exFAT"
++	default "utf8"
++	depends on EXFAT_FS
++	help
++	  Set this to the default input/output character set you'd like exFAT to use.
+diff --git a/drivers/staging/exfat/Makefile b/drivers/staging/exfat/Makefile
+new file mode 100644
+index 000000000000..84944dfbae28
+--- /dev/null
++++ b/drivers/staging/exfat/Makefile
+@@ -0,0 +1,10 @@
++# SPDX-License-Identifier: GPL-2.0
++
++obj-$(CONFIG_EXFAT_FS) += exfat.o
++
++exfat-y :=	exfat_core.o	\
++		exfat_super.o	\
++		exfat_blkdev.o	\
++		exfat_cache.o	\
++		exfat_nls.o	\
++		exfat_upcase.o
+diff --git a/drivers/staging/exfat/TODO b/drivers/staging/exfat/TODO
+new file mode 100644
+index 000000000000..a3eb282f9efc
+--- /dev/null
++++ b/drivers/staging/exfat/TODO
+@@ -0,0 +1,12 @@
++exfat_core.c - ffsReadFile - the goto err_out seem to leak a brelse().
++same for ffsWriteFile.
++
++exfat_core.c - fs_sync(sb,0) all over the place looks fishy as hell.
++There's only one place that calls it with a non-zero argument.
++
++ffsTruncateFile -  if (old_size <= new_size) {
++That doesn't look right. How did it ever work? Are they relying on lazy
++block allocation when actual writes happen? If nothing else, it never
++does the 'fid->size = new_size' and do the inode update....
++
++ffsSetAttr() is just dangling in the breeze, not wired up at all...
+diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
+new file mode 100644
+index 000000000000..bae180e10609
+--- /dev/null
++++ b/drivers/staging/exfat/exfat.h
+@@ -0,0 +1,973 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ *  Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
++ */
++
++#ifndef _EXFAT_H
++#define _EXFAT_H
++
++#include 
++#include 
++
++#ifdef CONFIG_EXFAT_KERNEL_DEBUG
++  /* For Debugging Purpose */
++	/* IOCTL code 'f' used by
++	 *   - file systems typically #0~0x1F
++	 *   - embedded terminal devices #128~
++	 *   - exts for debugging purpose #99
++	 * number 100 and 101 is available now but has possible conflicts
++	 */
++#define EXFAT_IOC_GET_DEBUGFLAGS	_IOR('f', 100, long)
++#define EXFAT_IOC_SET_DEBUGFLAGS	_IOW('f', 101, long)
++
++#define EXFAT_DEBUGFLAGS_INVALID_UMOUNT	0x01
++#define EXFAT_DEBUGFLAGS_ERROR_RW	0x02
++#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
++
++#ifdef CONFIG_EXFAT_DEBUG_MSG
++#define DEBUG	1
++#else
++#undef DEBUG
++#endif
++
++#define DENTRY_SIZE		32	/* dir entry size */
++#define DENTRY_SIZE_BITS	5
++
++/* PBR entries */
++#define PBR_SIGNATURE	0xAA55
++#define EXT_SIGNATURE	0xAA550000
++#define VOL_LABEL	"NO NAME    "	/* size should be 11 */
++#define OEM_NAME	"MSWIN4.1"	/* size should be 8 */
++#define STR_FAT12	"FAT12   "	/* size should be 8 */
++#define STR_FAT16	"FAT16   "	/* size should be 8 */
++#define STR_FAT32	"FAT32   "	/* size should be 8 */
++#define STR_EXFAT	"EXFAT   "	/* size should be 8 */
++#define VOL_CLEAN	0x0000
++#define VOL_DIRTY	0x0002
++
++/* max number of clusters */
++#define FAT12_THRESHOLD		4087		/* 2^12 - 1 + 2 (clu 0 & 1) */
++#define FAT16_THRESHOLD		65527		/* 2^16 - 1 + 2 */
++#define FAT32_THRESHOLD		268435457	/* 2^28 - 1 + 2 */
++#define EXFAT_THRESHOLD		268435457	/* 2^28 - 1 + 2 */
++
++/* file types */
++#define TYPE_UNUSED		0x0000
++#define TYPE_DELETED		0x0001
++#define TYPE_INVALID		0x0002
++#define TYPE_CRITICAL_PRI	0x0100
++#define TYPE_BITMAP		0x0101
++#define TYPE_UPCASE		0x0102
++#define TYPE_VOLUME		0x0103
++#define TYPE_DIR		0x0104
++#define TYPE_FILE		0x011F
++#define TYPE_SYMLINK		0x015F
++#define TYPE_CRITICAL_SEC	0x0200
++#define TYPE_STREAM		0x0201
++#define TYPE_EXTEND		0x0202
++#define TYPE_ACL		0x0203
++#define TYPE_BENIGN_PRI		0x0400
++#define TYPE_GUID		0x0401
++#define TYPE_PADDING		0x0402
++#define TYPE_ACLTAB		0x0403
++#define TYPE_BENIGN_SEC		0x0800
++#define TYPE_ALL		0x0FFF
++
++/* time modes */
++#define TM_CREATE		0
++#define TM_MODIFY		1
++#define TM_ACCESS		2
++
++/* checksum types */
++#define CS_DIR_ENTRY		0
++#define CS_PBR_SECTOR		1
++#define CS_DEFAULT		2
++
++#define CLUSTER_16(x)		((u16)(x))
++#define CLUSTER_32(x)		((u32)(x))
++
++#define FALSE			0
++#define TRUE			1
++
++#define START_SECTOR(x)							\
++	((((sector_t)((x) - 2)) << p_fs->sectors_per_clu_bits) +	\
++	 p_fs->data_start_sector)
++
++#define IS_LAST_SECTOR_IN_CLUSTER(sec)				\
++	((((sec) - p_fs->data_start_sector + 1) &		\
++	  ((1 <<  p_fs->sectors_per_clu_bits) - 1)) == 0)
++
++#define GET_CLUSTER_FROM_SECTOR(sec)				\
++	((u32)((((sec) - p_fs->data_start_sector) >>		\
++		p_fs->sectors_per_clu_bits) + 2))
++
++#define GET16(p_src)						\
++	(((u16)(p_src)[0]) | (((u16)(p_src)[1]) << 8))
++#define GET32(p_src)						\
++	(((u32)(p_src)[0]) | (((u32)(p_src)[1]) << 8) |		\
++	(((u32)(p_src)[2]) << 16) | (((u32)(p_src)[3]) << 24))
++#define GET64(p_src) \
++	(((u64)(p_src)[0]) | (((u64)(p_src)[1]) << 8) |		\
++	(((u64)(p_src)[2]) << 16) | (((u64)(p_src)[3]) << 24) |	\
++	(((u64)(p_src)[4]) << 32) | (((u64)(p_src)[5]) << 40) |	\
++	(((u64)(p_src)[6]) << 48) | (((u64)(p_src)[7]) << 56))
++
++#define SET16(p_dst, src)					\
++	do {							\
++		(p_dst)[0] = (u8)(src);				\
++		(p_dst)[1] = (u8)(((u16)(src)) >> 8);		\
++	} while (0)
++#define SET32(p_dst, src)					\
++	do {							\
++		(p_dst)[0] = (u8)(src);				\
++		(p_dst)[1] = (u8)(((u32)(src)) >> 8);		\
++		(p_dst)[2] = (u8)(((u32)(src)) >> 16);		\
++		(p_dst)[3] = (u8)(((u32)(src)) >> 24);		\
++	} while (0)
++#define SET64(p_dst, src)					\
++	do {							\
++		(p_dst)[0] = (u8)(src);				\
++		(p_dst)[1] = (u8)(((u64)(src)) >> 8);		\
++		(p_dst)[2] = (u8)(((u64)(src)) >> 16);		\
++		(p_dst)[3] = (u8)(((u64)(src)) >> 24);		\
++		(p_dst)[4] = (u8)(((u64)(src)) >> 32);		\
++		(p_dst)[5] = (u8)(((u64)(src)) >> 40);		\
++		(p_dst)[6] = (u8)(((u64)(src)) >> 48);		\
++		(p_dst)[7] = (u8)(((u64)(src)) >> 56);		\
++	} while (0)
++
++#ifdef __LITTLE_ENDIAN
++#define GET16_A(p_src)		(*((u16 *)(p_src)))
++#define GET32_A(p_src)		(*((u32 *)(p_src)))
++#define GET64_A(p_src)		(*((u64 *)(p_src)))
++#define SET16_A(p_dst, src)	(*((u16 *)(p_dst)) = (u16)(src))
++#define SET32_A(p_dst, src)	(*((u32 *)(p_dst)) = (u32)(src))
++#define SET64_A(p_dst, src)	(*((u64 *)(p_dst)) = (u64)(src))
++#else /* BIG_ENDIAN */
++#define GET16_A(p_src)		GET16(p_src)
++#define GET32_A(p_src)		GET32(p_src)
++#define GET64_A(p_src)		GET64(p_src)
++#define SET16_A(p_dst, src)	SET16(p_dst, src)
++#define SET32_A(p_dst, src)	SET32(p_dst, src)
++#define SET64_A(p_dst, src)	SET64(p_dst, src)
++#endif
++
++/* cache size (in number of sectors) */
++/* (should be an exponential value of 2) */
++#define FAT_CACHE_SIZE		128
++#define FAT_CACHE_HASH_SIZE	64
++#define BUF_CACHE_SIZE		256
++#define BUF_CACHE_HASH_SIZE	64
++
++/* Upcase table macro */
++#define HIGH_INDEX_BIT	(8)
++#define HIGH_INDEX_MASK	(0xFF00)
++#define LOW_INDEX_BIT	(16-HIGH_INDEX_BIT)
++#define UTBL_ROW_COUNT	(1<> LOW_INDEX_BIT;
++}
++static inline u16 get_row_index(u16 i)
++{
++	return i & ~HIGH_INDEX_MASK;
++}
++
++#define EXFAT_SUPER_MAGIC       (0x2011BAB0L)
++#define EXFAT_ROOT_INO          1
++
++/* FAT types */
++#define FAT12			0x01	/* FAT12 */
++#define FAT16			0x0E	/* Win95 FAT16 (LBA) */
++#define FAT32			0x0C	/* Win95 FAT32 (LBA) */
++#define EXFAT			0x07	/* exFAT */
++
++/* file name lengths */
++#define MAX_CHARSET_SIZE	3	/* max size of multi-byte character */
++#define MAX_PATH_DEPTH		15	/* max depth of path name */
++#define MAX_NAME_LENGTH		256	/* max len of filename including NULL */
++#define MAX_PATH_LENGTH		260	/* max len of pathname including NULL */
++#define DOS_NAME_LENGTH		11	/* DOS filename length excluding NULL */
++#define DOS_PATH_LENGTH		80	/* DOS pathname length excluding NULL */
++
++/* file attributes */
++#define ATTR_NORMAL		0x0000
++#define ATTR_READONLY		0x0001
++#define ATTR_HIDDEN		0x0002
++#define ATTR_SYSTEM		0x0004
++#define ATTR_VOLUME		0x0008
++#define ATTR_SUBDIR		0x0010
++#define ATTR_ARCHIVE		0x0020
++#define ATTR_SYMLINK		0x0040
++#define ATTR_EXTEND		0x000F
++#define ATTR_RWMASK		0x007E
++
++/* file creation modes */
++#define FM_REGULAR              0x00
++#define FM_SYMLINK              0x40
++
++/* return values */
++#define FFS_SUCCESS             0
++#define FFS_MEDIAERR            1
++#define FFS_FORMATERR           2
++#define FFS_MOUNTED             3
++#define FFS_NOTMOUNTED          4
++#define FFS_ALIGNMENTERR        5
++#define FFS_SEMAPHOREERR        6
++#define FFS_INVALIDPATH         7
++#define FFS_INVALIDFID          8
++#define FFS_NOTFOUND            9
++#define FFS_FILEEXIST           10
++#define FFS_PERMISSIONERR       11
++#define FFS_NOTOPENED           12
++#define FFS_MAXOPENED           13
++#define FFS_FULL                14
++#define FFS_EOF                 15
++#define FFS_DIRBUSY             16
++#define FFS_MEMORYERR           17
++#define FFS_NAMETOOLONG		18
++#define FFS_ERROR               19
++
++#define NUM_UPCASE              2918
++
++#define DOS_CUR_DIR_NAME        ".          "
++#define DOS_PAR_DIR_NAME        "..         "
++
++#ifdef __LITTLE_ENDIAN
++#define UNI_CUR_DIR_NAME        ".\0"
++#define UNI_PAR_DIR_NAME        ".\0.\0"
++#else
++#define UNI_CUR_DIR_NAME        "\0."
++#define UNI_PAR_DIR_NAME        "\0.\0."
++#endif
++
++struct date_time_t {
++	u16      Year;
++	u16      Month;
++	u16      Day;
++	u16      Hour;
++	u16      Minute;
++	u16      Second;
++	u16      MilliSecond;
++};
++
++struct part_info_t {
++	u32      Offset;    /* start sector number of the partition */
++	u32      Size;      /* in sectors */
++};
++
++struct dev_info_t {
++	u32      SecSize;    /* sector size in bytes */
++	u32      DevSize;    /* block device size in sectors */
++};
++
++struct vol_info_t {
++	u32      FatType;
++	u32      ClusterSize;
++	u32      NumClusters;
++	u32      FreeClusters;
++	u32      UsedClusters;
++};
++
++/* directory structure */
++struct chain_t {
++	u32      dir;
++	s32       size;
++	u8       flags;
++};
++
++struct file_id_t {
++	struct chain_t     dir;
++	s32       entry;
++	u32      type;
++	u32      attr;
++	u32      start_clu;
++	u64      size;
++	u8       flags;
++	s64       rwoffset;
++	s32       hint_last_off;
++	u32      hint_last_clu;
++};
++
++struct dir_entry_t {
++	char Name[MAX_NAME_LENGTH * MAX_CHARSET_SIZE];
++
++	/* used only for FAT12/16/32, not used for exFAT */
++	char ShortName[DOS_NAME_LENGTH + 2];
++
++	u32 Attr;
++	u64 Size;
++	u32 NumSubdirs;
++	struct date_time_t CreateTimestamp;
++	struct date_time_t ModifyTimestamp;
++	struct date_time_t AccessTimestamp;
++};
++
++struct timestamp_t {
++	u16      sec;        /* 0 ~ 59               */
++	u16      min;        /* 0 ~ 59               */
++	u16      hour;       /* 0 ~ 23               */
++	u16      day;        /* 1 ~ 31               */
++	u16      mon;        /* 1 ~ 12               */
++	u16      year;       /* 0 ~ 127 (since 1980) */
++};
++
++/* MS_DOS FAT partition boot record (512 bytes) */
++struct pbr_sector_t {
++	u8       jmp_boot[3];
++	u8       oem_name[8];
++	u8       bpb[109];
++	u8       boot_code[390];
++	u8       signature[2];
++};
++
++/* MS-DOS FAT12/16 BIOS parameter block (51 bytes) */
++struct bpb16_t {
++	u8       sector_size[2];
++	u8       sectors_per_clu;
++	u8       num_reserved[2];
++	u8       num_fats;
++	u8       num_root_entries[2];
++	u8       num_sectors[2];
++	u8       media_type;
++	u8       num_fat_sectors[2];
++	u8       sectors_in_track[2];
++	u8       num_heads[2];
++	u8       num_hid_sectors[4];
++	u8       num_huge_sectors[4];
++
++	u8       phy_drv_no;
++	u8       reserved;
++	u8       ext_signature;
++	u8       vol_serial[4];
++	u8       vol_label[11];
++	u8       vol_type[8];
++};
++
++/* MS-DOS FAT32 BIOS parameter block (79 bytes) */
++struct bpb32_t {
++	u8       sector_size[2];
++	u8       sectors_per_clu;
++	u8       num_reserved[2];
++	u8       num_fats;
++	u8       num_root_entries[2];
++	u8       num_sectors[2];
++	u8       media_type;
++	u8       num_fat_sectors[2];
++	u8       sectors_in_track[2];
++	u8       num_heads[2];
++	u8       num_hid_sectors[4];
++	u8       num_huge_sectors[4];
++	u8       num_fat32_sectors[4];
++	u8       ext_flags[2];
++	u8       fs_version[2];
++	u8       root_cluster[4];
++	u8       fsinfo_sector[2];
++	u8       backup_sector[2];
++	u8       reserved[12];
++
++	u8       phy_drv_no;
++	u8       ext_reserved;
++	u8       ext_signature;
++	u8       vol_serial[4];
++	u8       vol_label[11];
++	u8       vol_type[8];
++};
++
++/* MS-DOS EXFAT BIOS parameter block (109 bytes) */
++struct bpbex_t {
++	u8       reserved1[53];
++	u8       vol_offset[8];
++	u8       vol_length[8];
++	u8       fat_offset[4];
++	u8       fat_length[4];
++	u8       clu_offset[4];
++	u8       clu_count[4];
++	u8       root_cluster[4];
++	u8       vol_serial[4];
++	u8       fs_version[2];
++	u8       vol_flags[2];
++	u8       sector_size_bits;
++	u8       sectors_per_clu_bits;
++	u8       num_fats;
++	u8       phy_drv_no;
++	u8       perc_in_use;
++	u8       reserved2[7];
++};
++
++/* MS-DOS FAT file system information sector (512 bytes) */
++struct fsi_sector_t {
++	u8       signature1[4];
++	u8       reserved1[480];
++	u8       signature2[4];
++	u8       free_cluster[4];
++	u8       next_cluster[4];
++	u8       reserved2[14];
++	u8       signature3[2];
++};
++
++/* MS-DOS FAT directory entry (32 bytes) */
++struct dentry_t {
++	u8       dummy[32];
++};
++
++struct dos_dentry_t {
++	u8       name[DOS_NAME_LENGTH];
++	u8       attr;
++	u8       lcase;
++	u8       create_time_ms;
++	u8       create_time[2];
++	u8       create_date[2];
++	u8       access_date[2];
++	u8       start_clu_hi[2];
++	u8       modify_time[2];
++	u8       modify_date[2];
++	u8       start_clu_lo[2];
++	u8       size[4];
++};
++
++/* MS-DOS FAT extended directory entry (32 bytes) */
++struct ext_dentry_t {
++	u8       order;
++	u8       unicode_0_4[10];
++	u8       attr;
++	u8       sysid;
++	u8       checksum;
++	u8       unicode_5_10[12];
++	u8       start_clu[2];
++	u8       unicode_11_12[4];
++};
++
++/* MS-DOS EXFAT file directory entry (32 bytes) */
++struct file_dentry_t {
++	u8       type;
++	u8       num_ext;
++	u8       checksum[2];
++	u8       attr[2];
++	u8       reserved1[2];
++	u8       create_time[2];
++	u8       create_date[2];
++	u8       modify_time[2];
++	u8       modify_date[2];
++	u8       access_time[2];
++	u8       access_date[2];
++	u8       create_time_ms;
++	u8       modify_time_ms;
++	u8       access_time_ms;
++	u8       reserved2[9];
++};
++
++/* MS-DOS EXFAT stream extension directory entry (32 bytes) */
++struct strm_dentry_t {
++	u8       type;
++	u8       flags;
++	u8       reserved1;
++	u8       name_len;
++	u8       name_hash[2];
++	u8       reserved2[2];
++	u8       valid_size[8];
++	u8       reserved3[4];
++	u8       start_clu[4];
++	u8       size[8];
++};
++
++/* MS-DOS EXFAT file name directory entry (32 bytes) */
++struct name_dentry_t {
++	u8       type;
++	u8       flags;
++	u8       unicode_0_14[30];
++};
++
++/* MS-DOS EXFAT allocation bitmap directory entry (32 bytes) */
++struct bmap_dentry_t {
++	u8       type;
++	u8       flags;
++	u8       reserved[18];
++	u8       start_clu[4];
++	u8       size[8];
++};
++
++/* MS-DOS EXFAT up-case table directory entry (32 bytes) */
++struct case_dentry_t {
++	u8       type;
++	u8       reserved1[3];
++	u8       checksum[4];
++	u8       reserved2[12];
++	u8       start_clu[4];
++	u8       size[8];
++};
++
++/* MS-DOS EXFAT volume label directory entry (32 bytes) */
++struct volm_dentry_t {
++	u8       type;
++	u8       label_len;
++	u8       unicode_0_10[22];
++	u8       reserved[8];
++};
++
++/* unused entry hint information */
++struct uentry_t {
++	u32      dir;
++	s32       entry;
++	struct chain_t     clu;
++};
++
++/* DOS name structure */
++struct dos_name_t {
++	u8       name[DOS_NAME_LENGTH];
++	u8       name_case;
++};
++
++/* unicode name structure */
++struct uni_name_t {
++	u16      name[MAX_NAME_LENGTH];
++	u16      name_hash;
++	u8       name_len;
++};
++
++struct buf_cache_t {
++	struct buf_cache_t *next;
++	struct buf_cache_t *prev;
++	struct buf_cache_t *hash_next;
++	struct buf_cache_t *hash_prev;
++	s32                drv;
++	sector_t          sec;
++	u32               flag;
++	struct buffer_head   *buf_bh;
++};
++
++struct fs_func {
++	s32	(*alloc_cluster)(struct super_block *sb, s32 num_alloc,
++				 struct chain_t *p_chain);
++	void	(*free_cluster)(struct super_block *sb, struct chain_t *p_chain,
++				s32 do_relse);
++	s32	(*count_used_clusters)(struct super_block *sb);
++
++	s32	(*init_dir_entry)(struct super_block *sb, struct chain_t *p_dir,
++				  s32 entry, u32 type, u32 start_clu, u64 size);
++	s32	(*init_ext_entry)(struct super_block *sb, struct chain_t *p_dir,
++				  s32 entry, s32 num_entries,
++				  struct uni_name_t *p_uniname,
++				  struct dos_name_t *p_dosname);
++	s32	(*find_dir_entry)(struct super_block *sb, struct chain_t *p_dir,
++				  struct uni_name_t *p_uniname, s32 num_entries,
++				  struct dos_name_t *p_dosname, u32 type);
++	void	(*delete_dir_entry)(struct super_block *sb,
++				    struct chain_t *p_dir, s32 entry,
++				    s32 offset, s32 num_entries);
++	void	(*get_uni_name_from_ext_entry)(struct super_block *sb,
++					       struct chain_t *p_dir, s32 entry,
++					       u16 *uniname);
++	s32	(*count_ext_entries)(struct super_block *sb,
++				     struct chain_t *p_dir, s32 entry,
++				     struct dentry_t *p_entry);
++	s32	(*calc_num_entries)(struct uni_name_t *p_uniname);
++
++	u32	(*get_entry_type)(struct dentry_t *p_entry);
++	void	(*set_entry_type)(struct dentry_t *p_entry, u32 type);
++	u32	(*get_entry_attr)(struct dentry_t *p_entry);
++	void	(*set_entry_attr)(struct dentry_t *p_entry, u32 attr);
++	u8	(*get_entry_flag)(struct dentry_t *p_entry);
++	void	(*set_entry_flag)(struct dentry_t *p_entry, u8 flag);
++	u32	(*get_entry_clu0)(struct dentry_t *p_entry);
++	void	(*set_entry_clu0)(struct dentry_t *p_entry, u32 clu0);
++	u64	(*get_entry_size)(struct dentry_t *p_entry);
++	void	(*set_entry_size)(struct dentry_t *p_entry, u64 size);
++	void	(*get_entry_time)(struct dentry_t *p_entry,
++				  struct timestamp_t *tp, u8 mode);
++	void	(*set_entry_time)(struct dentry_t *p_entry,
++				  struct timestamp_t *tp, u8 mode);
++};
++
++struct fs_info_t {
++	u32      drv;                    /* drive ID */
++	u32      vol_type;               /* volume FAT type */
++	u32      vol_id;                 /* volume serial number */
++
++	u64      num_sectors;            /* num of sectors in volume */
++	u32      num_clusters;           /* num of clusters in volume */
++	u32      cluster_size;           /* cluster size in bytes */
++	u32      cluster_size_bits;
++	u32      sectors_per_clu;        /* cluster size in sectors */
++	u32      sectors_per_clu_bits;
++
++	u32      PBR_sector;             /* PBR sector */
++	u32      FAT1_start_sector;      /* FAT1 start sector */
++	u32      FAT2_start_sector;      /* FAT2 start sector */
++	u32      root_start_sector;      /* root dir start sector */
++	u32      data_start_sector;      /* data area start sector */
++	u32      num_FAT_sectors;        /* num of FAT sectors */
++
++	u32      root_dir;               /* root dir cluster */
++	u32      dentries_in_root;       /* num of dentries in root dir */
++	u32      dentries_per_clu;       /* num of dentries per cluster */
++
++	u32      vol_flag;               /* volume dirty flag */
++	struct buffer_head *pbr_bh;         /* PBR sector */
++
++	u32      map_clu;                /* allocation bitmap start cluster */
++	u32      map_sectors;            /* num of allocation bitmap sectors */
++	struct buffer_head **vol_amap;      /* allocation bitmap */
++
++	u16 **vol_utbl;			/* upcase table */
++
++	u32 clu_srch_ptr;		/* cluster search pointer */
++	u32 used_clusters;		/* number of used clusters */
++	struct uentry_t hint_uentry;	/* unused entry hint information */
++
++	u32 dev_ejected;	/* block device operation error flag */
++
++	struct fs_func *fs_func;
++	struct semaphore v_sem;
++
++	/* FAT cache */
++	struct buf_cache_t FAT_cache_array[FAT_CACHE_SIZE];
++	struct buf_cache_t FAT_cache_lru_list;
++	struct buf_cache_t FAT_cache_hash_list[FAT_CACHE_HASH_SIZE];
++
++	/* buf cache */
++	struct buf_cache_t buf_cache_array[BUF_CACHE_SIZE];
++	struct buf_cache_t buf_cache_lru_list;
++	struct buf_cache_t buf_cache_hash_list[BUF_CACHE_HASH_SIZE];
++};
++
++#define ES_2_ENTRIES		2
++#define ES_3_ENTRIES		3
++#define ES_ALL_ENTRIES		0
++
++struct entry_set_cache_t {
++	/* sector number that contains file_entry */
++	sector_t sector;
++
++	/* byte offset in the sector */
++	s32 offset;
++
++	/*
++	 * flag in stream entry.
++	 * 01 for cluster chain,
++	 * 03 for contig. clusteres.
++	 */
++	s32 alloc_flag;
++
++	u32 num_entries;
++
++	/* __buf should be the last member */
++	void *__buf;
++};
++
++#define EXFAT_ERRORS_CONT	1	/* ignore error and continue */
++#define EXFAT_ERRORS_PANIC	2	/* panic on error */
++#define EXFAT_ERRORS_RO		3	/* remount r/o on error */
++
++/* ioctl command */
++#define EXFAT_IOCTL_GET_VOLUME_ID _IOR('r', 0x12, __u32)
++
++struct exfat_mount_options {
++	kuid_t fs_uid;
++	kgid_t fs_gid;
++	unsigned short fs_fmask;
++	unsigned short fs_dmask;
++
++	/* permission for setting the [am]time */
++	unsigned short allow_utime;
++
++	/* codepage for shortname conversions */
++	unsigned short codepage;
++
++	/* charset for filename input/display */
++	char *iocharset;
++
++	unsigned char casesensitive;
++
++	/* on error: continue, panic, remount-ro */
++	unsigned char errors;
++#ifdef CONFIG_EXFAT_DISCARD
++	/* flag on if -o dicard specified and device support discard() */
++	unsigned char discard;
++#endif /* CONFIG_EXFAT_DISCARD */
++};
++
++#define EXFAT_HASH_BITS		8
++#define EXFAT_HASH_SIZE		(1UL << EXFAT_HASH_BITS)
++
++/*
++ * EXFAT file system in-core superblock data
++ */
++struct bd_info_t {
++	s32 sector_size;	/* in bytes */
++	s32 sector_size_bits;
++	s32 sector_size_mask;
++
++	/* total number of sectors in this block device */
++	s32 num_sectors;
++
++	/* opened or not */
++	bool opened;
++};
++
++struct exfat_sb_info {
++	struct fs_info_t fs_info;
++	struct bd_info_t bd_info;
++
++	struct exfat_mount_options options;
++
++	int s_dirt;
++	struct mutex s_lock;
++	struct nls_table *nls_disk; /* Codepage used on disk */
++	struct nls_table *nls_io;   /* Charset used for input and display */
++
++	struct inode *fat_inode;
++
++	spinlock_t inode_hash_lock;
++	struct hlist_head inode_hashtable[EXFAT_HASH_SIZE];
++#ifdef CONFIG_EXFAT_KERNEL_DEBUG
++	long debug_flags;
++#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
++};
++
++/*
++ * EXFAT file system inode data in memory
++ */
++struct exfat_inode_info {
++	struct file_id_t fid;
++	char  *target;
++	/* NOTE: mmu_private is 64bits, so must hold ->i_mutex to access */
++	loff_t mmu_private;	/* physically allocated size */
++	loff_t i_pos;		/* on-disk position of directory entry or 0 */
++	struct hlist_node i_hash_fat;	/* hash by i_location */
++	struct rw_semaphore truncate_lock;
++	struct inode vfs_inode;
++	struct rw_semaphore i_alloc_sem; /* protect bmap against truncate */
++};
++
++#define EXFAT_SB(sb)		((struct exfat_sb_info *)((sb)->s_fs_info))
++
++static inline struct exfat_inode_info *EXFAT_I(struct inode *inode)
++{
++	return container_of(inode, struct exfat_inode_info, vfs_inode);
++}
++
++/* NLS management function */
++u16 nls_upper(struct super_block *sb, u16 a);
++int nls_dosname_cmp(struct super_block *sb, u8 *a, u8 *b);
++int nls_uniname_cmp(struct super_block *sb, u16 *a, u16 *b);
++void nls_uniname_to_dosname(struct super_block *sb,
++			    struct dos_name_t *p_dosname,
++			    struct uni_name_t *p_uniname, bool *p_lossy);
++void nls_dosname_to_uniname(struct super_block *sb,
++			    struct uni_name_t *p_uniname,
++			    struct dos_name_t *p_dosname);
++void nls_uniname_to_cstring(struct super_block *sb, u8 *p_cstring,
++			    struct uni_name_t *p_uniname);
++void nls_cstring_to_uniname(struct super_block *sb,
++			    struct uni_name_t *p_uniname, u8 *p_cstring,
++			    bool *p_lossy);
++
++/* buffer cache management */
++void buf_init(struct super_block *sb);
++void buf_shutdown(struct super_block *sb);
++int FAT_read(struct super_block *sb, u32 loc, u32 *content);
++s32 FAT_write(struct super_block *sb, u32 loc, u32 content);
++u8 *FAT_getblk(struct super_block *sb, sector_t sec);
++void FAT_modify(struct super_block *sb, sector_t sec);
++void FAT_release_all(struct super_block *sb);
++void FAT_sync(struct super_block *sb);
++u8 *buf_getblk(struct super_block *sb, sector_t sec);
++void buf_modify(struct super_block *sb, sector_t sec);
++void buf_lock(struct super_block *sb, sector_t sec);
++void buf_unlock(struct super_block *sb, sector_t sec);
++void buf_release(struct super_block *sb, sector_t sec);
++void buf_release_all(struct super_block *sb);
++void buf_sync(struct super_block *sb);
++
++/* fs management functions */
++void fs_set_vol_flags(struct super_block *sb, u32 new_flag);
++void fs_error(struct super_block *sb);
++
++/* cluster management functions */
++s32 clear_cluster(struct super_block *sb, u32 clu);
++s32 fat_alloc_cluster(struct super_block *sb, s32 num_alloc,
++		      struct chain_t *p_chain);
++s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc,
++			struct chain_t *p_chain);
++void fat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
++		      s32 do_relse);
++void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
++			s32 do_relse);
++u32 find_last_cluster(struct super_block *sb, struct chain_t *p_chain);
++s32 count_num_clusters(struct super_block *sb, struct chain_t *dir);
++s32 fat_count_used_clusters(struct super_block *sb);
++s32 exfat_count_used_clusters(struct super_block *sb);
++void exfat_chain_cont_cluster(struct super_block *sb, u32 chain, s32 len);
++
++/* allocation bitmap management functions */
++s32 load_alloc_bitmap(struct super_block *sb);
++void free_alloc_bitmap(struct super_block *sb);
++s32 set_alloc_bitmap(struct super_block *sb, u32 clu);
++s32 clr_alloc_bitmap(struct super_block *sb, u32 clu);
++u32 test_alloc_bitmap(struct super_block *sb, u32 clu);
++void sync_alloc_bitmap(struct super_block *sb);
++
++/* upcase table management functions */
++s32 load_upcase_table(struct super_block *sb);
++void free_upcase_table(struct super_block *sb);
++
++/* dir entry management functions */
++u32 fat_get_entry_type(struct dentry_t *p_entry);
++u32 exfat_get_entry_type(struct dentry_t *p_entry);
++void fat_set_entry_type(struct dentry_t *p_entry, u32 type);
++void exfat_set_entry_type(struct dentry_t *p_entry, u32 type);
++u32 fat_get_entry_attr(struct dentry_t *p_entry);
++u32 exfat_get_entry_attr(struct dentry_t *p_entry);
++void fat_set_entry_attr(struct dentry_t *p_entry, u32 attr);
++void exfat_set_entry_attr(struct dentry_t *p_entry, u32 attr);
++u8 fat_get_entry_flag(struct dentry_t *p_entry);
++u8 exfat_get_entry_flag(struct dentry_t *p_entry);
++void fat_set_entry_flag(struct dentry_t *p_entry, u8 flag);
++void exfat_set_entry_flag(struct dentry_t *p_entry, u8 flag);
++u32 fat_get_entry_clu0(struct dentry_t *p_entry);
++u32 exfat_get_entry_clu0(struct dentry_t *p_entry);
++void fat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu);
++void exfat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu);
++u64 fat_get_entry_size(struct dentry_t *p_entry);
++u64 exfat_get_entry_size(struct dentry_t *p_entry);
++void fat_set_entry_size(struct dentry_t *p_entry, u64 size);
++void exfat_set_entry_size(struct dentry_t *p_entry, u64 size);
++struct timestamp_t *tm_current(struct timestamp_t *tm);
++void fat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
++			u8 mode);
++void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
++			  u8 mode);
++void fat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
++			u8 mode);
++void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
++			  u8 mode);
++s32 fat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir, s32 entry,
++		       u32 type, u32 start_clu, u64 size);
++s32 exfat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir,
++			 s32 entry, u32 type, u32 start_clu, u64 size);
++s32 fat_init_ext_dir_entry(struct super_block *sb, struct chain_t *p_dir,
++			   s32 entry, s32 num_entries,
++			   struct uni_name_t *p_uniname,
++			   struct dos_name_t *p_dosname);
++s32 exfat_init_ext_dir_entry(struct super_block *sb, struct chain_t *p_dir,
++			     s32 entry, s32 num_entries,
++			     struct uni_name_t *p_uniname,
++		struct dos_name_t *p_dosname);
++void init_dos_entry(struct dos_dentry_t *ep, u32 type, u32 start_clu);
++void init_ext_entry(struct ext_dentry_t *ep, s32 order, u8 chksum,
++		    u16 *uniname);
++void init_file_entry(struct file_dentry_t *ep, u32 type);
++void init_strm_entry(struct strm_dentry_t *ep, u8 flags, u32 start_clu,
++		     u64 size);
++void init_name_entry(struct name_dentry_t *ep, u16 *uniname);
++void fat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir,
++			  s32 entry, s32 order, s32 num_entries);
++void exfat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir,
++			    s32 entry, s32 order, s32 num_entries);
++
++s32 find_location(struct super_block *sb, struct chain_t *p_dir, s32 entry,
++		  sector_t *sector, s32 *offset);
++struct dentry_t *get_entry_with_sector(struct super_block *sb, sector_t sector,
++				       s32 offset);
++struct dentry_t *get_entry_in_dir(struct super_block *sb, struct chain_t *p_dir,
++				  s32 entry, sector_t *sector);
++struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb,
++					       struct chain_t *p_dir, s32 entry,
++					       u32 type,
++					       struct dentry_t **file_ep);
++void release_entry_set(struct entry_set_cache_t *es);
++s32 write_whole_entry_set(struct super_block *sb, struct entry_set_cache_t *es);
++s32 write_partial_entries_in_entry_set(struct super_block *sb,
++				       struct entry_set_cache_t *es,
++				       struct dentry_t *ep, u32 count);
++s32 search_deleted_or_unused_entry(struct super_block *sb,
++				   struct chain_t *p_dir, s32 num_entries);
++s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir,
++		     s32 num_entries);
++s32 fat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir,
++		       struct uni_name_t *p_uniname, s32 num_entries,
++		       struct dos_name_t *p_dosname, u32 type);
++s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir,
++			 struct uni_name_t *p_uniname, s32 num_entries,
++			 struct dos_name_t *p_dosname, u32 type);
++s32 fat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir,
++			  s32 entry, struct dentry_t *p_entry);
++s32 exfat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir,
++			    s32 entry, struct dentry_t *p_entry);
++s32 count_dos_name_entries(struct super_block *sb, struct chain_t *p_dir,
++			   u32 type);
++void update_dir_checksum(struct super_block *sb, struct chain_t *p_dir,
++			 s32 entry);
++void update_dir_checksum_with_entry_set(struct super_block *sb,
++					struct entry_set_cache_t *es);
++bool is_dir_empty(struct super_block *sb, struct chain_t *p_dir);
++
++/* name conversion functions */
++s32 get_num_entries_and_dos_name(struct super_block *sb, struct chain_t *p_dir,
++				 struct uni_name_t *p_uniname, s32 *entries,
++				 struct dos_name_t *p_dosname);
++void get_uni_name_from_dos_entry(struct super_block *sb,
++				 struct dos_dentry_t *ep,
++				 struct uni_name_t *p_uniname, u8 mode);
++void fat_get_uni_name_from_ext_entry(struct super_block *sb,
++				     struct chain_t *p_dir, s32 entry,
++				     u16 *uniname);
++void exfat_get_uni_name_from_ext_entry(struct super_block *sb,
++				       struct chain_t *p_dir, s32 entry,
++				       u16 *uniname);
++s32 extract_uni_name_from_ext_entry(struct ext_dentry_t *ep,
++				    u16 *uniname, s32 order);
++s32 extract_uni_name_from_name_entry(struct name_dentry_t *ep,
++				     u16 *uniname, s32 order);
++s32 fat_generate_dos_name(struct super_block *sb, struct chain_t *p_dir,
++			  struct dos_name_t *p_dosname);
++void fat_attach_count_to_dos_name(u8 *dosname, s32 count);
++s32 fat_calc_num_entries(struct uni_name_t *p_uniname);
++s32 exfat_calc_num_entries(struct uni_name_t *p_uniname);
++u8 calc_checksum_1byte(void *data, s32 len, u8 chksum);
++u16 calc_checksum_2byte(void *data, s32 len, u16 chksum, s32 type);
++u32 calc_checksum_4byte(void *data, s32 len, u32 chksum, s32 type);
++
++/* name resolution functions */
++s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir,
++		 struct uni_name_t *p_uniname);
++s32 resolve_name(u8 *name, u8 **arg);
++
++/* file operation functions */
++s32 fat16_mount(struct super_block *sb, struct pbr_sector_t *p_pbr);
++s32 fat32_mount(struct super_block *sb, struct pbr_sector_t *p_pbr);
++s32 exfat_mount(struct super_block *sb, struct pbr_sector_t *p_pbr);
++s32 create_dir(struct inode *inode, struct chain_t *p_dir,
++	       struct uni_name_t *p_uniname, struct file_id_t *fid);
++s32 create_file(struct inode *inode, struct chain_t *p_dir,
++		struct uni_name_t *p_uniname, u8 mode, struct file_id_t *fid);
++void remove_file(struct inode *inode, struct chain_t *p_dir, s32 entry);
++s32 rename_file(struct inode *inode, struct chain_t *p_dir, s32 old_entry,
++		struct uni_name_t *p_uniname, struct file_id_t *fid);
++s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
++	      struct chain_t *p_newdir, struct uni_name_t *p_uniname,
++	      struct file_id_t *fid);
++
++/* sector read/write functions */
++int sector_read(struct super_block *sb, sector_t sec,
++		struct buffer_head **bh, bool read);
++int sector_write(struct super_block *sb, sector_t sec,
++		 struct buffer_head *bh, bool sync);
++int multi_sector_read(struct super_block *sb, sector_t sec,
++		      struct buffer_head **bh, s32 num_secs, bool read);
++int multi_sector_write(struct super_block *sb, sector_t sec,
++		       struct buffer_head *bh, s32 num_secs, bool sync);
++
++void bdev_open(struct super_block *sb);
++void bdev_close(struct super_block *sb);
++int bdev_read(struct super_block *sb, sector_t secno,
++	      struct buffer_head **bh, u32 num_secs, bool read);
++int bdev_write(struct super_block *sb, sector_t secno,
++	       struct buffer_head *bh, u32 num_secs, bool sync);
++int bdev_sync(struct super_block *sb);
++
++extern const u8 uni_upcase[];
++#endif /* _EXFAT_H */
+diff --git a/drivers/staging/exfat/exfat_blkdev.c b/drivers/staging/exfat/exfat_blkdev.c
+new file mode 100644
+index 000000000000..f086c75e7076
+--- /dev/null
++++ b/drivers/staging/exfat/exfat_blkdev.c
+@@ -0,0 +1,136 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ *  Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
++ */
++
++#include 
++#include 
++#include 
++#include "exfat.h"
++
++void bdev_open(struct super_block *sb)
++{
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++
++	if (p_bd->opened)
++		return;
++
++	p_bd->sector_size      = bdev_logical_block_size(sb->s_bdev);
++	p_bd->sector_size_bits = ilog2(p_bd->sector_size);
++	p_bd->sector_size_mask = p_bd->sector_size - 1;
++	p_bd->num_sectors      = i_size_read(sb->s_bdev->bd_inode) >>
++				 p_bd->sector_size_bits;
++	p_bd->opened = true;
++}
++
++void bdev_close(struct super_block *sb)
++{
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++
++	p_bd->opened = false;
++}
++
++int bdev_read(struct super_block *sb, sector_t secno, struct buffer_head **bh,
++	      u32 num_secs, bool read)
++{
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++#ifdef CONFIG_EXFAT_KERNEL_DEBUG
++	struct exfat_sb_info *sbi = EXFAT_SB(sb);
++	long flags = sbi->debug_flags;
++
++	if (flags & EXFAT_DEBUGFLAGS_ERROR_RW)
++		return FFS_MEDIAERR;
++#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
++
++	if (!p_bd->opened)
++		return FFS_MEDIAERR;
++
++	if (*bh)
++		__brelse(*bh);
++
++	if (read)
++		*bh = __bread(sb->s_bdev, secno,
++			      num_secs << p_bd->sector_size_bits);
++	else
++		*bh = __getblk(sb->s_bdev, secno,
++			       num_secs << p_bd->sector_size_bits);
++
++	if (*bh)
++		return 0;
++
++	WARN(!p_fs->dev_ejected,
++	     "[EXFAT] No bh, device seems wrong or to be ejected.\n");
++
++	return FFS_MEDIAERR;
++}
++
++int bdev_write(struct super_block *sb, sector_t secno, struct buffer_head *bh,
++	       u32 num_secs, bool sync)
++{
++	s32 count;
++	struct buffer_head *bh2;
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++#ifdef CONFIG_EXFAT_KERNEL_DEBUG
++	struct exfat_sb_info *sbi = EXFAT_SB(sb);
++	long flags = sbi->debug_flags;
++
++	if (flags & EXFAT_DEBUGFLAGS_ERROR_RW)
++		return FFS_MEDIAERR;
++#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
++
++	if (!p_bd->opened)
++		return FFS_MEDIAERR;
++
++	if (secno == bh->b_blocknr) {
++		lock_buffer(bh);
++		set_buffer_uptodate(bh);
++		mark_buffer_dirty(bh);
++		unlock_buffer(bh);
++		if (sync && (sync_dirty_buffer(bh) != 0))
++			return FFS_MEDIAERR;
++	} else {
++		count = num_secs << p_bd->sector_size_bits;
++
++		bh2 = __getblk(sb->s_bdev, secno, count);
++		if (!bh2)
++			goto no_bh;
++
++		lock_buffer(bh2);
++		memcpy(bh2->b_data, bh->b_data, count);
++		set_buffer_uptodate(bh2);
++		mark_buffer_dirty(bh2);
++		unlock_buffer(bh2);
++		if (sync && (sync_dirty_buffer(bh2) != 0)) {
++			__brelse(bh2);
++			goto no_bh;
++		}
++		__brelse(bh2);
++	}
++
++	return 0;
++
++no_bh:
++	WARN(!p_fs->dev_ejected,
++	     "[EXFAT] No bh, device seems wrong or to be ejected.\n");
++
++	return FFS_MEDIAERR;
++}
++
++int bdev_sync(struct super_block *sb)
++{
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++#ifdef CONFIG_EXFAT_KERNEL_DEBUG
++	struct exfat_sb_info *sbi = EXFAT_SB(sb);
++	long flags = sbi->debug_flags;
++
++	if (flags & EXFAT_DEBUGFLAGS_ERROR_RW)
++		return FFS_MEDIAERR;
++#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
++
++	if (!p_bd->opened)
++		return FFS_MEDIAERR;
++
++	return sync_blockdev(sb->s_bdev);
++}
+diff --git a/drivers/staging/exfat/exfat_cache.c b/drivers/staging/exfat/exfat_cache.c
+new file mode 100644
+index 000000000000..f05d692c2b1e
+--- /dev/null
++++ b/drivers/staging/exfat/exfat_cache.c
+@@ -0,0 +1,722 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ *  Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
++ */
++
++#include 
++#include 
++#include 
++#include "exfat.h"
++
++#define LOCKBIT		0x01
++#define DIRTYBIT	0x02
++
++/* Local variables */
++static DEFINE_SEMAPHORE(f_sem);
++static DEFINE_SEMAPHORE(b_sem);
++
++static struct buf_cache_t *FAT_cache_find(struct super_block *sb, sector_t sec)
++{
++	s32 off;
++	struct buf_cache_t *bp, *hp;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	off = (sec +
++	       (sec >> p_fs->sectors_per_clu_bits)) & (FAT_CACHE_HASH_SIZE - 1);
++
++	hp = &p_fs->FAT_cache_hash_list[off];
++	for (bp = hp->hash_next; bp != hp; bp = bp->hash_next) {
++		if ((bp->drv == p_fs->drv) && (bp->sec == sec)) {
++			WARN(!bp->buf_bh,
++			     "[EXFAT] FAT_cache has no bh. It will make system panic.\n");
++
++			touch_buffer(bp->buf_bh);
++			return bp;
++		}
++	}
++	return NULL;
++}
++
++static void push_to_mru(struct buf_cache_t *bp, struct buf_cache_t *list)
++{
++	bp->next = list->next;
++	bp->prev = list;
++	list->next->prev = bp;
++	list->next = bp;
++}
++
++static void push_to_lru(struct buf_cache_t *bp, struct buf_cache_t *list)
++{
++	bp->prev = list->prev;
++	bp->next = list;
++	list->prev->next = bp;
++	list->prev = bp;
++}
++
++static void move_to_mru(struct buf_cache_t *bp, struct buf_cache_t *list)
++{
++	bp->prev->next = bp->next;
++	bp->next->prev = bp->prev;
++	push_to_mru(bp, list);
++}
++
++static void move_to_lru(struct buf_cache_t *bp, struct buf_cache_t *list)
++{
++	bp->prev->next = bp->next;
++	bp->next->prev = bp->prev;
++	push_to_lru(bp, list);
++}
++
++static struct buf_cache_t *FAT_cache_get(struct super_block *sb, sector_t sec)
++{
++	struct buf_cache_t *bp;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	bp = p_fs->FAT_cache_lru_list.prev;
++
++	move_to_mru(bp, &p_fs->FAT_cache_lru_list);
++	return bp;
++}
++
++static void FAT_cache_insert_hash(struct super_block *sb,
++				  struct buf_cache_t *bp)
++{
++	s32 off;
++	struct buf_cache_t *hp;
++	struct fs_info_t *p_fs;
++
++	p_fs = &(EXFAT_SB(sb)->fs_info);
++	off = (bp->sec +
++	       (bp->sec >> p_fs->sectors_per_clu_bits)) &
++		(FAT_CACHE_HASH_SIZE - 1);
++
++	hp = &p_fs->FAT_cache_hash_list[off];
++	bp->hash_next = hp->hash_next;
++	bp->hash_prev = hp;
++	hp->hash_next->hash_prev = bp;
++	hp->hash_next = bp;
++}
++
++static void FAT_cache_remove_hash(struct buf_cache_t *bp)
++{
++	(bp->hash_prev)->hash_next = bp->hash_next;
++	(bp->hash_next)->hash_prev = bp->hash_prev;
++}
++
++static void buf_cache_insert_hash(struct super_block *sb,
++				  struct buf_cache_t *bp)
++{
++	s32 off;
++	struct buf_cache_t *hp;
++	struct fs_info_t *p_fs;
++
++	p_fs = &(EXFAT_SB(sb)->fs_info);
++	off = (bp->sec +
++	       (bp->sec >> p_fs->sectors_per_clu_bits)) &
++		(BUF_CACHE_HASH_SIZE - 1);
++
++	hp = &p_fs->buf_cache_hash_list[off];
++	bp->hash_next = hp->hash_next;
++	bp->hash_prev = hp;
++	hp->hash_next->hash_prev = bp;
++	hp->hash_next = bp;
++}
++
++static void buf_cache_remove_hash(struct buf_cache_t *bp)
++{
++	(bp->hash_prev)->hash_next = bp->hash_next;
++	(bp->hash_next)->hash_prev = bp->hash_prev;
++}
++
++void buf_init(struct super_block *sb)
++{
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	int i;
++
++	/* LRU list */
++	p_fs->FAT_cache_lru_list.next = &p_fs->FAT_cache_lru_list;
++	p_fs->FAT_cache_lru_list.prev = &p_fs->FAT_cache_lru_list;
++
++	for (i = 0; i < FAT_CACHE_SIZE; i++) {
++		p_fs->FAT_cache_array[i].drv = -1;
++		p_fs->FAT_cache_array[i].sec = ~0;
++		p_fs->FAT_cache_array[i].flag = 0;
++		p_fs->FAT_cache_array[i].buf_bh = NULL;
++		p_fs->FAT_cache_array[i].prev = NULL;
++		p_fs->FAT_cache_array[i].next = NULL;
++		push_to_mru(&p_fs->FAT_cache_array[i],
++			    &p_fs->FAT_cache_lru_list);
++	}
++
++	p_fs->buf_cache_lru_list.next = &p_fs->buf_cache_lru_list;
++	p_fs->buf_cache_lru_list.prev = &p_fs->buf_cache_lru_list;
++
++	for (i = 0; i < BUF_CACHE_SIZE; i++) {
++		p_fs->buf_cache_array[i].drv = -1;
++		p_fs->buf_cache_array[i].sec = ~0;
++		p_fs->buf_cache_array[i].flag = 0;
++		p_fs->buf_cache_array[i].buf_bh = NULL;
++		p_fs->buf_cache_array[i].prev = NULL;
++		p_fs->buf_cache_array[i].next = NULL;
++		push_to_mru(&p_fs->buf_cache_array[i],
++			    &p_fs->buf_cache_lru_list);
++	}
++
++	/* HASH list */
++	for (i = 0; i < FAT_CACHE_HASH_SIZE; i++) {
++		p_fs->FAT_cache_hash_list[i].drv = -1;
++		p_fs->FAT_cache_hash_list[i].sec = ~0;
++		p_fs->FAT_cache_hash_list[i].hash_next =
++			&p_fs->FAT_cache_hash_list[i];
++		p_fs->FAT_cache_hash_list[i].hash_prev =
++			&p_fs->FAT_cache_hash_list[i];
++	}
++
++	for (i = 0; i < FAT_CACHE_SIZE; i++)
++		FAT_cache_insert_hash(sb, &p_fs->FAT_cache_array[i]);
++
++	for (i = 0; i < BUF_CACHE_HASH_SIZE; i++) {
++		p_fs->buf_cache_hash_list[i].drv = -1;
++		p_fs->buf_cache_hash_list[i].sec = ~0;
++		p_fs->buf_cache_hash_list[i].hash_next =
++			&p_fs->buf_cache_hash_list[i];
++		p_fs->buf_cache_hash_list[i].hash_prev =
++			&p_fs->buf_cache_hash_list[i];
++	}
++
++	for (i = 0; i < BUF_CACHE_SIZE; i++)
++		buf_cache_insert_hash(sb, &p_fs->buf_cache_array[i]);
++}
++
++void buf_shutdown(struct super_block *sb)
++{
++}
++
++static int __FAT_read(struct super_block *sb, u32 loc, u32 *content)
++{
++	s32 off;
++	u32 _content;
++	sector_t sec;
++	u8 *fat_sector, *fat_entry;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++
++	if (p_fs->vol_type == FAT12) {
++		sec = p_fs->FAT1_start_sector +
++			((loc + (loc >> 1)) >> p_bd->sector_size_bits);
++		off = (loc + (loc >> 1)) & p_bd->sector_size_mask;
++
++		if (off == (p_bd->sector_size - 1)) {
++			fat_sector = FAT_getblk(sb, sec);
++			if (!fat_sector)
++				return -1;
++
++			_content = (u32)fat_sector[off];
++
++			fat_sector = FAT_getblk(sb, ++sec);
++			if (!fat_sector)
++				return -1;
++
++			_content |= (u32)fat_sector[0] << 8;
++		} else {
++			fat_sector = FAT_getblk(sb, sec);
++			if (!fat_sector)
++				return -1;
++
++			fat_entry = &fat_sector[off];
++			_content = GET16(fat_entry);
++		}
++
++		if (loc & 1)
++			_content >>= 4;
++
++		_content &= 0x00000FFF;
++
++		if (_content >= CLUSTER_16(0x0FF8)) {
++			*content = CLUSTER_32(~0);
++			return 0;
++		}
++		*content = CLUSTER_32(_content);
++		return 0;
++	} else if (p_fs->vol_type == FAT16) {
++		sec = p_fs->FAT1_start_sector +
++			(loc >> (p_bd->sector_size_bits - 1));
++		off = (loc << 1) & p_bd->sector_size_mask;
++
++		fat_sector = FAT_getblk(sb, sec);
++		if (!fat_sector)
++			return -1;
++
++		fat_entry = &fat_sector[off];
++
++		_content = GET16_A(fat_entry);
++
++		_content &= 0x0000FFFF;
++
++		if (_content >= CLUSTER_16(0xFFF8)) {
++			*content = CLUSTER_32(~0);
++			return 0;
++		}
++		*content = CLUSTER_32(_content);
++		return 0;
++	} else if (p_fs->vol_type == FAT32) {
++		sec = p_fs->FAT1_start_sector +
++			(loc >> (p_bd->sector_size_bits - 2));
++		off = (loc << 2) & p_bd->sector_size_mask;
++
++		fat_sector = FAT_getblk(sb, sec);
++		if (!fat_sector)
++			return -1;
++
++		fat_entry = &fat_sector[off];
++
++		_content = GET32_A(fat_entry);
++
++		_content &= 0x0FFFFFFF;
++
++		if (_content >= CLUSTER_32(0x0FFFFFF8)) {
++			*content = CLUSTER_32(~0);
++			return 0;
++		}
++		*content = CLUSTER_32(_content);
++		return 0;
++	} else if (p_fs->vol_type == EXFAT) {
++		sec = p_fs->FAT1_start_sector +
++			(loc >> (p_bd->sector_size_bits - 2));
++		off = (loc << 2) & p_bd->sector_size_mask;
++
++		fat_sector = FAT_getblk(sb, sec);
++		if (!fat_sector)
++			return -1;
++
++		fat_entry = &fat_sector[off];
++		_content = GET32_A(fat_entry);
++
++		if (_content >= CLUSTER_32(0xFFFFFFF8)) {
++			*content = CLUSTER_32(~0);
++			return 0;
++		}
++		*content = CLUSTER_32(_content);
++		return 0;
++	}
++
++	/* Unknown volume type, throw in the towel and go home */
++	*content = CLUSTER_32(~0);
++	return 0;
++}
++
++/* in : sb, loc
++ * out: content
++ * returns 0 on success
++ *            -1 on error
++ */
++int FAT_read(struct super_block *sb, u32 loc, u32 *content)
++{
++	s32 ret;
++
++	down(&f_sem);
++	ret = __FAT_read(sb, loc, content);
++	up(&f_sem);
++
++	return ret;
++}
++
++static s32 __FAT_write(struct super_block *sb, u32 loc, u32 content)
++{
++	s32 off;
++	sector_t sec;
++	u8 *fat_sector, *fat_entry;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++
++	if (p_fs->vol_type == FAT12) {
++		content &= 0x00000FFF;
++
++		sec = p_fs->FAT1_start_sector +
++			((loc + (loc >> 1)) >> p_bd->sector_size_bits);
++		off = (loc + (loc >> 1)) & p_bd->sector_size_mask;
++
++		fat_sector = FAT_getblk(sb, sec);
++		if (!fat_sector)
++			return -1;
++
++		if (loc & 1) { /* odd */
++			content <<= 4;
++
++			if (off == (p_bd->sector_size - 1)) {
++				fat_sector[off] = (u8)(content |
++						       (fat_sector[off] &
++							0x0F));
++				FAT_modify(sb, sec);
++
++				fat_sector = FAT_getblk(sb, ++sec);
++				if (!fat_sector)
++					return -1;
++
++				fat_sector[0] = (u8)(content >> 8);
++			} else {
++				fat_entry = &fat_sector[off];
++				content |= GET16(fat_entry) & 0x000F;
++
++				SET16(fat_entry, content);
++			}
++		} else { /* even */
++			fat_sector[off] = (u8)(content);
++
++			if (off == (p_bd->sector_size - 1)) {
++				fat_sector[off] = (u8)(content);
++				FAT_modify(sb, sec);
++
++				fat_sector = FAT_getblk(sb, ++sec);
++				fat_sector[0] = (u8)((fat_sector[0] & 0xF0) |
++						     (content >> 8));
++			} else {
++				fat_entry = &fat_sector[off];
++				content |= GET16(fat_entry) & 0xF000;
++
++				SET16(fat_entry, content);
++			}
++		}
++	}
++
++	else if (p_fs->vol_type == FAT16) {
++		content &= 0x0000FFFF;
++
++		sec = p_fs->FAT1_start_sector + (loc >>
++						 (p_bd->sector_size_bits - 1));
++		off = (loc << 1) & p_bd->sector_size_mask;
++
++		fat_sector = FAT_getblk(sb, sec);
++		if (!fat_sector)
++			return -1;
++
++		fat_entry = &fat_sector[off];
++
++		SET16_A(fat_entry, content);
++	} else if (p_fs->vol_type == FAT32) {
++		content &= 0x0FFFFFFF;
++
++		sec = p_fs->FAT1_start_sector + (loc >>
++						 (p_bd->sector_size_bits - 2));
++		off = (loc << 2) & p_bd->sector_size_mask;
++
++		fat_sector = FAT_getblk(sb, sec);
++		if (!fat_sector)
++			return -1;
++
++		fat_entry = &fat_sector[off];
++
++		content |= GET32_A(fat_entry) & 0xF0000000;
++
++		SET32_A(fat_entry, content);
++	} else { /* p_fs->vol_type == EXFAT */
++		sec = p_fs->FAT1_start_sector + (loc >>
++						 (p_bd->sector_size_bits - 2));
++		off = (loc << 2) & p_bd->sector_size_mask;
++
++		fat_sector = FAT_getblk(sb, sec);
++		if (!fat_sector)
++			return -1;
++
++		fat_entry = &fat_sector[off];
++
++		SET32_A(fat_entry, content);
++	}
++
++	FAT_modify(sb, sec);
++	return 0;
++}
++
++int FAT_write(struct super_block *sb, u32 loc, u32 content)
++{
++	s32 ret;
++
++	down(&f_sem);
++	ret = __FAT_write(sb, loc, content);
++	up(&f_sem);
++
++	return ret;
++}
++
++u8 *FAT_getblk(struct super_block *sb, sector_t sec)
++{
++	struct buf_cache_t *bp;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	bp = FAT_cache_find(sb, sec);
++	if (bp) {
++		move_to_mru(bp, &p_fs->FAT_cache_lru_list);
++		return bp->buf_bh->b_data;
++	}
++
++	bp = FAT_cache_get(sb, sec);
++
++	FAT_cache_remove_hash(bp);
++
++	bp->drv = p_fs->drv;
++	bp->sec = sec;
++	bp->flag = 0;
++
++	FAT_cache_insert_hash(sb, bp);
++
++	if (sector_read(sb, sec, &bp->buf_bh, 1) != FFS_SUCCESS) {
++		FAT_cache_remove_hash(bp);
++		bp->drv = -1;
++		bp->sec = ~0;
++		bp->flag = 0;
++		bp->buf_bh = NULL;
++
++		move_to_lru(bp, &p_fs->FAT_cache_lru_list);
++		return NULL;
++	}
++
++	return bp->buf_bh->b_data;
++}
++
++void FAT_modify(struct super_block *sb, sector_t sec)
++{
++	struct buf_cache_t *bp;
++
++	bp = FAT_cache_find(sb, sec);
++	if (bp)
++		sector_write(sb, sec, bp->buf_bh, 0);
++}
++
++void FAT_release_all(struct super_block *sb)
++{
++	struct buf_cache_t *bp;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	down(&f_sem);
++
++	bp = p_fs->FAT_cache_lru_list.next;
++	while (bp != &p_fs->FAT_cache_lru_list) {
++		if (bp->drv == p_fs->drv) {
++			bp->drv = -1;
++			bp->sec = ~0;
++			bp->flag = 0;
++
++			if (bp->buf_bh) {
++				__brelse(bp->buf_bh);
++				bp->buf_bh = NULL;
++			}
++		}
++		bp = bp->next;
++	}
++
++	up(&f_sem);
++}
++
++void FAT_sync(struct super_block *sb)
++{
++	struct buf_cache_t *bp;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	down(&f_sem);
++
++	bp = p_fs->FAT_cache_lru_list.next;
++	while (bp != &p_fs->FAT_cache_lru_list) {
++		if ((bp->drv == p_fs->drv) && (bp->flag & DIRTYBIT)) {
++			sync_dirty_buffer(bp->buf_bh);
++			bp->flag &= ~(DIRTYBIT);
++		}
++		bp = bp->next;
++	}
++
++	up(&f_sem);
++}
++
++static struct buf_cache_t *buf_cache_find(struct super_block *sb, sector_t sec)
++{
++	s32 off;
++	struct buf_cache_t *bp, *hp;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	off = (sec + (sec >> p_fs->sectors_per_clu_bits)) &
++		(BUF_CACHE_HASH_SIZE - 1);
++
++	hp = &p_fs->buf_cache_hash_list[off];
++	for (bp = hp->hash_next; bp != hp; bp = bp->hash_next) {
++		if ((bp->drv == p_fs->drv) && (bp->sec == sec)) {
++			touch_buffer(bp->buf_bh);
++			return bp;
++		}
++	}
++	return NULL;
++}
++
++static struct buf_cache_t *buf_cache_get(struct super_block *sb, sector_t sec)
++{
++	struct buf_cache_t *bp;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	bp = p_fs->buf_cache_lru_list.prev;
++	while (bp->flag & LOCKBIT)
++		bp = bp->prev;
++
++	move_to_mru(bp, &p_fs->buf_cache_lru_list);
++	return bp;
++}
++
++static u8 *__buf_getblk(struct super_block *sb, sector_t sec)
++{
++	struct buf_cache_t *bp;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	bp = buf_cache_find(sb, sec);
++	if (bp) {
++		move_to_mru(bp, &p_fs->buf_cache_lru_list);
++		return bp->buf_bh->b_data;
++	}
++
++	bp = buf_cache_get(sb, sec);
++
++	buf_cache_remove_hash(bp);
++
++	bp->drv = p_fs->drv;
++	bp->sec = sec;
++	bp->flag = 0;
++
++	buf_cache_insert_hash(sb, bp);
++
++	if (sector_read(sb, sec, &bp->buf_bh, 1) != FFS_SUCCESS) {
++		buf_cache_remove_hash(bp);
++		bp->drv = -1;
++		bp->sec = ~0;
++		bp->flag = 0;
++		bp->buf_bh = NULL;
++
++		move_to_lru(bp, &p_fs->buf_cache_lru_list);
++		return NULL;
++	}
++
++	return bp->buf_bh->b_data;
++}
++
++u8 *buf_getblk(struct super_block *sb, sector_t sec)
++{
++	u8 *buf;
++
++	down(&b_sem);
++	buf = __buf_getblk(sb, sec);
++	up(&b_sem);
++
++	return buf;
++}
++
++void buf_modify(struct super_block *sb, sector_t sec)
++{
++	struct buf_cache_t *bp;
++
++	down(&b_sem);
++
++	bp = buf_cache_find(sb, sec);
++	if (likely(bp))
++		sector_write(sb, sec, bp->buf_bh, 0);
++
++	WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n",
++	     (unsigned long long)sec);
++
++	up(&b_sem);
++}
++
++void buf_lock(struct super_block *sb, sector_t sec)
++{
++	struct buf_cache_t *bp;
++
++	down(&b_sem);
++
++	bp = buf_cache_find(sb, sec);
++	if (likely(bp))
++		bp->flag |= LOCKBIT;
++
++	WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n",
++	     (unsigned long long)sec);
++
++	up(&b_sem);
++}
++
++void buf_unlock(struct super_block *sb, sector_t sec)
++{
++	struct buf_cache_t *bp;
++
++	down(&b_sem);
++
++	bp = buf_cache_find(sb, sec);
++	if (likely(bp))
++		bp->flag &= ~(LOCKBIT);
++
++	WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n",
++	     (unsigned long long)sec);
++
++	up(&b_sem);
++}
++
++void buf_release(struct super_block *sb, sector_t sec)
++{
++	struct buf_cache_t *bp;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	down(&b_sem);
++
++	bp = buf_cache_find(sb, sec);
++	if (likely(bp)) {
++		bp->drv = -1;
++		bp->sec = ~0;
++		bp->flag = 0;
++
++		if (bp->buf_bh) {
++			__brelse(bp->buf_bh);
++			bp->buf_bh = NULL;
++		}
++
++		move_to_lru(bp, &p_fs->buf_cache_lru_list);
++	}
++
++	up(&b_sem);
++}
++
++void buf_release_all(struct super_block *sb)
++{
++	struct buf_cache_t *bp;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	down(&b_sem);
++
++	bp = p_fs->buf_cache_lru_list.next;
++	while (bp != &p_fs->buf_cache_lru_list) {
++		if (bp->drv == p_fs->drv) {
++			bp->drv = -1;
++			bp->sec = ~0;
++			bp->flag = 0;
++
++			if (bp->buf_bh) {
++				__brelse(bp->buf_bh);
++				bp->buf_bh = NULL;
++			}
++		}
++		bp = bp->next;
++	}
++
++	up(&b_sem);
++}
++
++void buf_sync(struct super_block *sb)
++{
++	struct buf_cache_t *bp;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	down(&b_sem);
++
++	bp = p_fs->buf_cache_lru_list.next;
++	while (bp != &p_fs->buf_cache_lru_list) {
++		if ((bp->drv == p_fs->drv) && (bp->flag & DIRTYBIT)) {
++			sync_dirty_buffer(bp->buf_bh);
++			bp->flag &= ~(DIRTYBIT);
++		}
++		bp = bp->next;
++	}
++
++	up(&b_sem);
++}
+diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
+new file mode 100644
+index 000000000000..9f76ca175c80
+--- /dev/null
++++ b/drivers/staging/exfat/exfat_core.c
+@@ -0,0 +1,3704 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ *  Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include "exfat.h"
++
++
++static void __set_sb_dirty(struct super_block *sb)
++{
++	struct exfat_sb_info *sbi = EXFAT_SB(sb);
++
++	sbi->s_dirt = 1;
++}
++
++static u8 name_buf[MAX_PATH_LENGTH * MAX_CHARSET_SIZE];
++
++static char *reserved_names[] = {
++	"AUX     ", "CON     ", "NUL     ", "PRN     ",
++	"COM1    ", "COM2    ", "COM3    ", "COM4    ",
++	"COM5    ", "COM6    ", "COM7    ", "COM8    ", "COM9    ",
++	"LPT1    ", "LPT2    ", "LPT3    ", "LPT4    ",
++	"LPT5    ", "LPT6    ", "LPT7    ", "LPT8    ", "LPT9    ",
++	NULL
++};
++
++static u8 free_bit[] = {
++	0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, /*   0 ~  19 */
++	0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, /*  20 ~  39 */
++	0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, /*  40 ~  59 */
++	0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, /*  60 ~  79 */
++	0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, /*  80 ~  99 */
++	0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, /* 100 ~ 119 */
++	0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, /* 120 ~ 139 */
++	0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, /* 140 ~ 159 */
++	0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, /* 160 ~ 179 */
++	0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, /* 180 ~ 199 */
++	0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, /* 200 ~ 219 */
++	0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, /* 220 ~ 239 */
++	0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0                 /* 240 ~ 254 */
++};
++
++static u8 used_bit[] = {
++	0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, /*   0 ~  19 */
++	2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, /*  20 ~  39 */
++	2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, /*  40 ~  59 */
++	4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, /*  60 ~  79 */
++	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, /*  80 ~  99 */
++	3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, /* 100 ~ 119 */
++	4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, /* 120 ~ 139 */
++	3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 140 ~ 159 */
++	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, /* 160 ~ 179 */
++	4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, /* 180 ~ 199 */
++	3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, /* 200 ~ 219 */
++	5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 220 ~ 239 */
++	4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8              /* 240 ~ 255 */
++};
++
++#define BITMAP_LOC(v)           ((v) >> 3)
++#define BITMAP_SHIFT(v)         ((v) & 0x07)
++
++static inline s32 exfat_bitmap_test(u8 *bitmap, int i)
++{
++	u8 data;
++
++	data = bitmap[BITMAP_LOC(i)];
++	if ((data >> BITMAP_SHIFT(i)) & 0x01)
++		return 1;
++	return 0;
++}
++
++static inline void exfat_bitmap_set(u8 *bitmap, int i)
++{
++	bitmap[BITMAP_LOC(i)] |= (0x01 << BITMAP_SHIFT(i));
++}
++
++static inline void exfat_bitmap_clear(u8 *bitmap, int i)
++{
++	bitmap[BITMAP_LOC(i)] &= ~(0x01 << BITMAP_SHIFT(i));
++}
++
++/*
++ *  File System Management Functions
++ */
++
++void fs_set_vol_flags(struct super_block *sb, u32 new_flag)
++{
++	struct pbr_sector_t *p_pbr;
++	struct bpbex_t *p_bpb;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	if (p_fs->vol_flag == new_flag)
++		return;
++
++	p_fs->vol_flag = new_flag;
++
++	if (p_fs->vol_type == EXFAT) {
++		if (p_fs->pbr_bh == NULL) {
++			if (sector_read(sb, p_fs->PBR_sector,
++					&p_fs->pbr_bh, 1) != FFS_SUCCESS)
++				return;
++		}
++
++		p_pbr = (struct pbr_sector_t *)p_fs->pbr_bh->b_data;
++		p_bpb = (struct bpbex_t *)p_pbr->bpb;
++		SET16(p_bpb->vol_flags, (u16)new_flag);
++
++		/* XXX duyoung
++		 * what can we do here? (cuz fs_set_vol_flags() is void)
++		 */
++		if ((new_flag == VOL_DIRTY) && (!buffer_dirty(p_fs->pbr_bh)))
++			sector_write(sb, p_fs->PBR_sector, p_fs->pbr_bh, 1);
++		else
++			sector_write(sb, p_fs->PBR_sector, p_fs->pbr_bh, 0);
++	}
++}
++
++void fs_error(struct super_block *sb)
++{
++	struct exfat_mount_options *opts = &EXFAT_SB(sb)->options;
++
++	if (opts->errors == EXFAT_ERRORS_PANIC) {
++		panic("[EXFAT] Filesystem panic from previous error\n");
++	} else if ((opts->errors == EXFAT_ERRORS_RO) && !sb_rdonly(sb)) {
++		sb->s_flags |= SB_RDONLY;
++		pr_err("[EXFAT] Filesystem has been set read-only\n");
++	}
++}
++
++/*
++ *  Cluster Management Functions
++ */
++
++s32 clear_cluster(struct super_block *sb, u32 clu)
++{
++	sector_t s, n;
++	s32 ret = FFS_SUCCESS;
++	struct buffer_head *tmp_bh = NULL;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++
++	if (clu == CLUSTER_32(0)) { /* FAT16 root_dir */
++		s = p_fs->root_start_sector;
++		n = p_fs->data_start_sector;
++	} else {
++		s = START_SECTOR(clu);
++		n = s + p_fs->sectors_per_clu;
++	}
++
++	for (; s < n; s++) {
++		ret = sector_read(sb, s, &tmp_bh, 0);
++		if (ret != FFS_SUCCESS)
++			return ret;
++
++		memset((char *)tmp_bh->b_data, 0x0, p_bd->sector_size);
++		ret = sector_write(sb, s, tmp_bh, 0);
++		if (ret != FFS_SUCCESS)
++			break;
++	}
++
++	brelse(tmp_bh);
++	return ret;
++}
++
++s32 fat_alloc_cluster(struct super_block *sb, s32 num_alloc,
++		      struct chain_t *p_chain)
++{
++	int i, num_clusters = 0;
++	u32 new_clu, last_clu = CLUSTER_32(~0), read_clu;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	new_clu = p_chain->dir;
++	if (new_clu == CLUSTER_32(~0))
++		new_clu = p_fs->clu_srch_ptr;
++	else if (new_clu >= p_fs->num_clusters)
++		new_clu = 2;
++
++	__set_sb_dirty(sb);
++
++	p_chain->dir = CLUSTER_32(~0);
++
++	for (i = 2; i < p_fs->num_clusters; i++) {
++		if (FAT_read(sb, new_clu, &read_clu) != 0)
++			return -1;
++
++		if (read_clu == CLUSTER_32(0)) {
++			if (FAT_write(sb, new_clu, CLUSTER_32(~0)) < 0)
++				return -1;
++			num_clusters++;
++
++			if (p_chain->dir == CLUSTER_32(~0)) {
++				p_chain->dir = new_clu;
++			} else {
++				if (FAT_write(sb, last_clu, new_clu) < 0)
++					return -1;
++			}
++
++			last_clu = new_clu;
++
++			if ((--num_alloc) == 0) {
++				p_fs->clu_srch_ptr = new_clu;
++				if (p_fs->used_clusters != (u32) ~0)
++					p_fs->used_clusters += num_clusters;
++
++				return num_clusters;
++			}
++		}
++		if ((++new_clu) >= p_fs->num_clusters)
++			new_clu = 2;
++	}
++
++	p_fs->clu_srch_ptr = new_clu;
++	if (p_fs->used_clusters != (u32) ~0)
++		p_fs->used_clusters += num_clusters;
++
++	return num_clusters;
++}
++
++s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc,
++			struct chain_t *p_chain)
++{
++	s32 num_clusters = 0;
++	u32 hint_clu, new_clu, last_clu = CLUSTER_32(~0);
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	hint_clu = p_chain->dir;
++	if (hint_clu == CLUSTER_32(~0)) {
++		hint_clu = test_alloc_bitmap(sb, p_fs->clu_srch_ptr-2);
++		if (hint_clu == CLUSTER_32(~0))
++			return 0;
++	} else if (hint_clu >= p_fs->num_clusters) {
++		hint_clu = 2;
++		p_chain->flags = 0x01;
++	}
++
++	__set_sb_dirty(sb);
++
++	p_chain->dir = CLUSTER_32(~0);
++
++	while ((new_clu = test_alloc_bitmap(sb, hint_clu-2)) != CLUSTER_32(~0)) {
++		if (new_clu != hint_clu) {
++			if (p_chain->flags == 0x03) {
++				exfat_chain_cont_cluster(sb, p_chain->dir,
++							 num_clusters);
++				p_chain->flags = 0x01;
++			}
++		}
++
++		if (set_alloc_bitmap(sb, new_clu-2) != FFS_SUCCESS)
++			return -1;
++
++		num_clusters++;
++
++		if (p_chain->flags == 0x01) {
++			if (FAT_write(sb, new_clu, CLUSTER_32(~0)) < 0)
++				return -1;
++		}
++
++		if (p_chain->dir == CLUSTER_32(~0)) {
++			p_chain->dir = new_clu;
++		} else {
++			if (p_chain->flags == 0x01) {
++				if (FAT_write(sb, last_clu, new_clu) < 0)
++					return -1;
++			}
++		}
++		last_clu = new_clu;
++
++		if ((--num_alloc) == 0) {
++			p_fs->clu_srch_ptr = hint_clu;
++			if (p_fs->used_clusters != (u32) ~0)
++				p_fs->used_clusters += num_clusters;
++
++			p_chain->size += num_clusters;
++			return num_clusters;
++		}
++
++		hint_clu = new_clu + 1;
++		if (hint_clu >= p_fs->num_clusters) {
++			hint_clu = 2;
++
++			if (p_chain->flags == 0x03) {
++				exfat_chain_cont_cluster(sb, p_chain->dir,
++							 num_clusters);
++				p_chain->flags = 0x01;
++			}
++		}
++	}
++
++	p_fs->clu_srch_ptr = hint_clu;
++	if (p_fs->used_clusters != (u32) ~0)
++		p_fs->used_clusters += num_clusters;
++
++	p_chain->size += num_clusters;
++	return num_clusters;
++}
++
++void fat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
++		      s32 do_relse)
++{
++	s32 num_clusters = 0;
++	u32 clu, prev;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	int i;
++	sector_t sector;
++
++	if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0)))
++		return;
++	__set_sb_dirty(sb);
++	clu = p_chain->dir;
++
++	if (p_chain->size <= 0)
++		return;
++
++	do {
++		if (p_fs->dev_ejected)
++			break;
++
++		if (do_relse) {
++			sector = START_SECTOR(clu);
++			for (i = 0; i < p_fs->sectors_per_clu; i++)
++				buf_release(sb, sector+i);
++		}
++
++		prev = clu;
++		if (FAT_read(sb, clu, &clu) == -1)
++			break;
++
++		if (FAT_write(sb, prev, CLUSTER_32(0)) < 0)
++			break;
++		num_clusters++;
++
++	} while (clu != CLUSTER_32(~0));
++
++	if (p_fs->used_clusters != (u32) ~0)
++		p_fs->used_clusters -= num_clusters;
++}
++
++void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
++			s32 do_relse)
++{
++	s32 num_clusters = 0;
++	u32 clu;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	int i;
++	sector_t sector;
++
++	if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0)))
++		return;
++
++	if (p_chain->size <= 0) {
++		pr_err("[EXFAT] free_cluster : skip free-req clu:%u, because of zero-size truncation\n",
++		       p_chain->dir);
++		return;
++	}
++
++	__set_sb_dirty(sb);
++	clu = p_chain->dir;
++
++	if (p_chain->flags == 0x03) {
++		do {
++			if (do_relse) {
++				sector = START_SECTOR(clu);
++				for (i = 0; i < p_fs->sectors_per_clu; i++)
++					buf_release(sb, sector+i);
++			}
++
++			if (clr_alloc_bitmap(sb, clu-2) != FFS_SUCCESS)
++				break;
++			clu++;
++
++			num_clusters++;
++		} while (num_clusters < p_chain->size);
++	} else {
++		do {
++			if (p_fs->dev_ejected)
++				break;
++
++			if (do_relse) {
++				sector = START_SECTOR(clu);
++				for (i = 0; i < p_fs->sectors_per_clu; i++)
++					buf_release(sb, sector+i);
++			}
++
++			if (clr_alloc_bitmap(sb, clu-2) != FFS_SUCCESS)
++				break;
++
++			if (FAT_read(sb, clu, &clu) == -1)
++				break;
++			num_clusters++;
++		} while ((clu != CLUSTER_32(0)) && (clu != CLUSTER_32(~0)));
++	}
++
++	if (p_fs->used_clusters != (u32) ~0)
++		p_fs->used_clusters -= num_clusters;
++}
++
++u32 find_last_cluster(struct super_block *sb, struct chain_t *p_chain)
++{
++	u32 clu, next;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	clu = p_chain->dir;
++
++	if (p_chain->flags == 0x03) {
++		clu += p_chain->size - 1;
++	} else {
++		while ((FAT_read(sb, clu, &next) == 0) &&
++		       (next != CLUSTER_32(~0))) {
++			if (p_fs->dev_ejected)
++				break;
++			clu = next;
++		}
++	}
++
++	return clu;
++}
++
++s32 count_num_clusters(struct super_block *sb, struct chain_t *p_chain)
++{
++	int i, count = 0;
++	u32 clu;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0)))
++		return 0;
++
++	clu = p_chain->dir;
++
++	if (p_chain->flags == 0x03) {
++		count = p_chain->size;
++	} else {
++		for (i = 2; i < p_fs->num_clusters; i++) {
++			count++;
++			if (FAT_read(sb, clu, &clu) != 0)
++				return 0;
++			if (clu == CLUSTER_32(~0))
++				break;
++		}
++	}
++
++	return count;
++}
++
++s32 fat_count_used_clusters(struct super_block *sb)
++{
++	int i, count = 0;
++	u32 clu;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	for (i = 2; i < p_fs->num_clusters; i++) {
++		if (FAT_read(sb, i, &clu) != 0)
++			break;
++		if (clu != CLUSTER_32(0))
++			count++;
++	}
++
++	return count;
++}
++
++s32 exfat_count_used_clusters(struct super_block *sb)
++{
++	int i, map_i, map_b, count = 0;
++	u8 k;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++
++	map_i = map_b = 0;
++
++	for (i = 2; i < p_fs->num_clusters; i += 8) {
++		k = *(((u8 *) p_fs->vol_amap[map_i]->b_data) + map_b);
++		count += used_bit[k];
++
++		if ((++map_b) >= p_bd->sector_size) {
++			map_i++;
++			map_b = 0;
++		}
++	}
++
++	return count;
++}
++
++void exfat_chain_cont_cluster(struct super_block *sb, u32 chain, s32 len)
++{
++	if (len == 0)
++		return;
++
++	while (len > 1) {
++		if (FAT_write(sb, chain, chain+1) < 0)
++			break;
++		chain++;
++		len--;
++	}
++	FAT_write(sb, chain, CLUSTER_32(~0));
++}
++
++/*
++ *  Allocation Bitmap Management Functions
++ */
++
++s32 load_alloc_bitmap(struct super_block *sb)
++{
++	int i, j, ret;
++	u32 map_size;
++	u32 type;
++	sector_t sector;
++	struct chain_t clu;
++	struct bmap_dentry_t *ep;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++
++	clu.dir = p_fs->root_dir;
++	clu.flags = 0x01;
++
++	while (clu.dir != CLUSTER_32(~0)) {
++		if (p_fs->dev_ejected)
++			break;
++
++		for (i = 0; i < p_fs->dentries_per_clu; i++) {
++			ep = (struct bmap_dentry_t *)get_entry_in_dir(sb, &clu,
++								      i, NULL);
++			if (!ep)
++				return FFS_MEDIAERR;
++
++			type = p_fs->fs_func->get_entry_type((struct dentry_t *)ep);
++
++			if (type == TYPE_UNUSED)
++				break;
++			if (type != TYPE_BITMAP)
++				continue;
++
++			if (ep->flags == 0x0) {
++				p_fs->map_clu  = GET32_A(ep->start_clu);
++				map_size = (u32) GET64_A(ep->size);
++
++				p_fs->map_sectors = ((map_size-1) >> p_bd->sector_size_bits) + 1;
++
++				p_fs->vol_amap = kmalloc_array(p_fs->map_sectors,
++							       sizeof(struct buffer_head *),
++							       GFP_KERNEL);
++				if (p_fs->vol_amap == NULL)
++					return FFS_MEMORYERR;
++
++				sector = START_SECTOR(p_fs->map_clu);
++
++				for (j = 0; j < p_fs->map_sectors; j++) {
++					p_fs->vol_amap[j] = NULL;
++					ret = sector_read(sb, sector+j, &(p_fs->vol_amap[j]), 1);
++					if (ret != FFS_SUCCESS) {
++						/*  release all buffers and free vol_amap */
++						i = 0;
++						while (i < j)
++							brelse(p_fs->vol_amap[i++]);
++
++						kfree(p_fs->vol_amap);
++						p_fs->vol_amap = NULL;
++						return ret;
++					}
++				}
++
++				p_fs->pbr_bh = NULL;
++				return FFS_SUCCESS;
++			}
++		}
++
++		if (FAT_read(sb, clu.dir, &clu.dir) != 0)
++			return FFS_MEDIAERR;
++	}
++
++	return FFS_FORMATERR;
++}
++
++void free_alloc_bitmap(struct super_block *sb)
++{
++	int i;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	brelse(p_fs->pbr_bh);
++
++	for (i = 0; i < p_fs->map_sectors; i++)
++		__brelse(p_fs->vol_amap[i]);
++
++	kfree(p_fs->vol_amap);
++	p_fs->vol_amap = NULL;
++}
++
++s32 set_alloc_bitmap(struct super_block *sb, u32 clu)
++{
++	int i, b;
++	sector_t sector;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++
++	i = clu >> (p_bd->sector_size_bits + 3);
++	b = clu & ((p_bd->sector_size << 3) - 1);
++
++	sector = START_SECTOR(p_fs->map_clu) + i;
++
++	exfat_bitmap_set((u8 *) p_fs->vol_amap[i]->b_data, b);
++
++	return sector_write(sb, sector, p_fs->vol_amap[i], 0);
++}
++
++s32 clr_alloc_bitmap(struct super_block *sb, u32 clu)
++{
++	int i, b;
++	sector_t sector;
++#ifdef CONFIG_EXFAT_DISCARD
++	struct exfat_sb_info *sbi = EXFAT_SB(sb);
++	struct exfat_mount_options *opts = &sbi->options;
++	int ret;
++#endif /* CONFIG_EXFAT_DISCARD */
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++
++	i = clu >> (p_bd->sector_size_bits + 3);
++	b = clu & ((p_bd->sector_size << 3) - 1);
++
++	sector = START_SECTOR(p_fs->map_clu) + i;
++
++	exfat_bitmap_clear((u8 *) p_fs->vol_amap[i]->b_data, b);
++
++	return sector_write(sb, sector, p_fs->vol_amap[i], 0);
++
++#ifdef CONFIG_EXFAT_DISCARD
++	if (opts->discard) {
++		ret = sb_issue_discard(sb, START_SECTOR(clu),
++				       (1 << p_fs->sectors_per_clu_bits),
++				       GFP_NOFS, 0);
++		if (ret == -EOPNOTSUPP) {
++			pr_warn("discard not supported by device, disabling");
++			opts->discard = 0;
++		}
++	}
++#endif /* CONFIG_EXFAT_DISCARD */
++}
++
++u32 test_alloc_bitmap(struct super_block *sb, u32 clu)
++{
++	int i, map_i, map_b;
++	u32 clu_base, clu_free;
++	u8 k, clu_mask;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++
++	clu_base = (clu & ~(0x7)) + 2;
++	clu_mask = (1 << (clu - clu_base + 2)) - 1;
++
++	map_i = clu >> (p_bd->sector_size_bits + 3);
++	map_b = (clu >> 3) & p_bd->sector_size_mask;
++
++	for (i = 2; i < p_fs->num_clusters; i += 8) {
++		k = *(((u8 *) p_fs->vol_amap[map_i]->b_data) + map_b);
++		if (clu_mask > 0) {
++			k |= clu_mask;
++			clu_mask = 0;
++		}
++		if (k < 0xFF) {
++			clu_free = clu_base + free_bit[k];
++			if (clu_free < p_fs->num_clusters)
++				return clu_free;
++		}
++		clu_base += 8;
++
++		if (((++map_b) >= p_bd->sector_size) ||
++		    (clu_base >= p_fs->num_clusters)) {
++			if ((++map_i) >= p_fs->map_sectors) {
++				clu_base = 2;
++				map_i = 0;
++			}
++			map_b = 0;
++		}
++	}
++
++	return CLUSTER_32(~0);
++}
++
++void sync_alloc_bitmap(struct super_block *sb)
++{
++	int i;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	if (p_fs->vol_amap == NULL)
++		return;
++
++	for (i = 0; i < p_fs->map_sectors; i++)
++		sync_dirty_buffer(p_fs->vol_amap[i]);
++}
++
++/*
++ *  Upcase table Management Functions
++ */
++static s32 __load_upcase_table(struct super_block *sb, sector_t sector,
++			       u32 num_sectors, u32 utbl_checksum)
++{
++	int i, ret = FFS_ERROR;
++	u32 j;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++	struct buffer_head *tmp_bh = NULL;
++	sector_t end_sector = num_sectors + sector;
++
++	u8	skip = FALSE;
++	u32	index = 0;
++	u16	uni = 0;
++	u16 **upcase_table;
++
++	u32 checksum = 0;
++
++	upcase_table = p_fs->vol_utbl = kmalloc(UTBL_COL_COUNT * sizeof(u16 *),
++						GFP_KERNEL);
++	if (upcase_table == NULL)
++		return FFS_MEMORYERR;
++	memset(upcase_table, 0, UTBL_COL_COUNT * sizeof(u16 *));
++
++	while (sector < end_sector) {
++		ret = sector_read(sb, sector, &tmp_bh, 1);
++		if (ret != FFS_SUCCESS) {
++			pr_debug("sector read (0x%llX)fail\n",
++				 (unsigned long long)sector);
++			goto error;
++		}
++		sector++;
++
++		for (i = 0; i < p_bd->sector_size && index <= 0xFFFF; i += 2) {
++			uni = GET16(((u8 *) tmp_bh->b_data)+i);
++
++			checksum = ((checksum & 1) ? 0x80000000 : 0) +
++				   (checksum >> 1) + *(((u8 *)tmp_bh->b_data) +
++						       i);
++			checksum = ((checksum & 1) ? 0x80000000 : 0) +
++				   (checksum >> 1) + *(((u8 *)tmp_bh->b_data) +
++						       (i + 1));
++
++			if (skip) {
++				pr_debug("skip from 0x%X ", index);
++				index += uni;
++				pr_debug("to 0x%X (amount of 0x%X)\n",
++					 index, uni);
++				skip = FALSE;
++			} else if (uni == index)
++				index++;
++			else if (uni == 0xFFFF)
++				skip = TRUE;
++			else { /* uni != index , uni != 0xFFFF */
++				u16 col_index = get_col_index(index);
++
++				if (upcase_table[col_index] == NULL) {
++					pr_debug("alloc = 0x%X\n", col_index);
++					upcase_table[col_index] = kmalloc_array(UTBL_ROW_COUNT,
++						sizeof(u16), GFP_KERNEL);
++					if (upcase_table[col_index] == NULL) {
++						ret = FFS_MEMORYERR;
++						goto error;
++					}
++
++					for (j = 0; j < UTBL_ROW_COUNT; j++)
++						upcase_table[col_index][j] = (col_index << LOW_INDEX_BIT) | j;
++				}
++
++				upcase_table[col_index][get_row_index(index)] = uni;
++				index++;
++			}
++		}
++	}
++	if (index >= 0xFFFF && utbl_checksum == checksum) {
++		if (tmp_bh)
++			brelse(tmp_bh);
++		return FFS_SUCCESS;
++	}
++	ret = FFS_ERROR;
++error:
++	if (tmp_bh)
++		brelse(tmp_bh);
++	free_upcase_table(sb);
++	return ret;
++}
++
++static s32 __load_default_upcase_table(struct super_block *sb)
++{
++	int i, ret = FFS_ERROR;
++	u32 j;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	u8	skip = FALSE;
++	u32	index = 0;
++	u16	uni = 0;
++	u16 **upcase_table;
++
++	upcase_table = p_fs->vol_utbl = kmalloc(UTBL_COL_COUNT * sizeof(u16 *),
++						GFP_KERNEL);
++	if (upcase_table == NULL)
++		return FFS_MEMORYERR;
++	memset(upcase_table, 0, UTBL_COL_COUNT * sizeof(u16 *));
++
++	for (i = 0; index <= 0xFFFF && i < NUM_UPCASE*2; i += 2) {
++		uni = GET16(uni_upcase + i);
++		if (skip) {
++			pr_debug("skip from 0x%X ", index);
++			index += uni;
++			pr_debug("to 0x%X (amount of 0x%X)\n", index, uni);
++			skip = FALSE;
++		} else if (uni == index)
++			index++;
++		else if (uni == 0xFFFF)
++			skip = TRUE;
++		else { /* uni != index , uni != 0xFFFF */
++			u16 col_index = get_col_index(index);
++
++			if (upcase_table[col_index] == NULL) {
++				pr_debug("alloc = 0x%X\n", col_index);
++				upcase_table[col_index] = kmalloc_array(UTBL_ROW_COUNT,
++									sizeof(u16),
++									GFP_KERNEL);
++				if (upcase_table[col_index] == NULL) {
++					ret = FFS_MEMORYERR;
++					goto error;
++				}
++
++				for (j = 0; j < UTBL_ROW_COUNT; j++)
++					upcase_table[col_index][j] = (col_index << LOW_INDEX_BIT) | j;
++			}
++
++			upcase_table[col_index][get_row_index(index)] = uni;
++			index++;
++		}
++	}
++
++	if (index >= 0xFFFF)
++		return FFS_SUCCESS;
++
++error:
++	/* FATAL error: default upcase table has error */
++	free_upcase_table(sb);
++	return ret;
++}
++
++s32 load_upcase_table(struct super_block *sb)
++{
++	int i;
++	u32 tbl_clu, tbl_size;
++	sector_t sector;
++	u32 type, num_sectors;
++	struct chain_t clu;
++	struct case_dentry_t *ep;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++
++	clu.dir = p_fs->root_dir;
++	clu.flags = 0x01;
++
++	if (p_fs->dev_ejected)
++		return FFS_MEDIAERR;
++
++	while (clu.dir != CLUSTER_32(~0)) {
++		for (i = 0; i < p_fs->dentries_per_clu; i++) {
++			ep = (struct case_dentry_t *)get_entry_in_dir(sb, &clu,
++								      i, NULL);
++			if (!ep)
++				return FFS_MEDIAERR;
++
++			type = p_fs->fs_func->get_entry_type((struct dentry_t *)ep);
++
++			if (type == TYPE_UNUSED)
++				break;
++			if (type != TYPE_UPCASE)
++				continue;
++
++			tbl_clu  = GET32_A(ep->start_clu);
++			tbl_size = (u32) GET64_A(ep->size);
++
++			sector = START_SECTOR(tbl_clu);
++			num_sectors = ((tbl_size-1) >> p_bd->sector_size_bits) + 1;
++			if (__load_upcase_table(sb, sector, num_sectors,
++						GET32_A(ep->checksum)) != FFS_SUCCESS)
++				break;
++			return FFS_SUCCESS;
++		}
++		if (FAT_read(sb, clu.dir, &clu.dir) != 0)
++			return FFS_MEDIAERR;
++	}
++	/* load default upcase table */
++	return __load_default_upcase_table(sb);
++}
++
++void free_upcase_table(struct super_block *sb)
++{
++	u32 i;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	u16 **upcase_table;
++
++	upcase_table = p_fs->vol_utbl;
++	for (i = 0; i < UTBL_COL_COUNT; i++)
++		kfree(upcase_table[i]);
++
++	kfree(p_fs->vol_utbl);
++	p_fs->vol_utbl = NULL;
++}
++
++/*
++ *  Directory Entry Management Functions
++ */
++
++u32 fat_get_entry_type(struct dentry_t *p_entry)
++{
++	struct dos_dentry_t *ep = (struct dos_dentry_t *) p_entry;
++
++	if (*(ep->name) == 0x0)
++		return TYPE_UNUSED;
++
++	else if (*(ep->name) == 0xE5)
++		return TYPE_DELETED;
++
++	else if (ep->attr == ATTR_EXTEND)
++		return TYPE_EXTEND;
++
++	else if ((ep->attr & (ATTR_SUBDIR|ATTR_VOLUME)) == ATTR_VOLUME)
++		return TYPE_VOLUME;
++
++	else if ((ep->attr & (ATTR_SUBDIR|ATTR_VOLUME)) == ATTR_SUBDIR)
++		return TYPE_DIR;
++
++	return TYPE_FILE;
++}
++
++u32 exfat_get_entry_type(struct dentry_t *p_entry)
++{
++	struct file_dentry_t *ep = (struct file_dentry_t *) p_entry;
++
++	if (ep->type == 0x0) {
++		return TYPE_UNUSED;
++	} else if (ep->type < 0x80) {
++		return TYPE_DELETED;
++	} else if (ep->type == 0x80) {
++		return TYPE_INVALID;
++	} else if (ep->type < 0xA0) {
++		if (ep->type == 0x81) {
++			return TYPE_BITMAP;
++		} else if (ep->type == 0x82) {
++			return TYPE_UPCASE;
++		} else if (ep->type == 0x83) {
++			return TYPE_VOLUME;
++		} else if (ep->type == 0x85) {
++			if (GET16_A(ep->attr) & ATTR_SUBDIR)
++				return TYPE_DIR;
++			else
++				return TYPE_FILE;
++		}
++		return TYPE_CRITICAL_PRI;
++	} else if (ep->type < 0xC0) {
++		if (ep->type == 0xA0)
++			return TYPE_GUID;
++		else if (ep->type == 0xA1)
++			return TYPE_PADDING;
++		else if (ep->type == 0xA2)
++			return TYPE_ACLTAB;
++		return TYPE_BENIGN_PRI;
++	} else if (ep->type < 0xE0) {
++		if (ep->type == 0xC0)
++			return TYPE_STREAM;
++		else if (ep->type == 0xC1)
++			return TYPE_EXTEND;
++		else if (ep->type == 0xC2)
++			return TYPE_ACL;
++		return TYPE_CRITICAL_SEC;
++	}
++
++	return TYPE_BENIGN_SEC;
++}
++
++void fat_set_entry_type(struct dentry_t *p_entry, u32 type)
++{
++	struct dos_dentry_t *ep = (struct dos_dentry_t *) p_entry;
++
++	if (type == TYPE_UNUSED)
++		*(ep->name) = 0x0;
++
++	else if (type == TYPE_DELETED)
++		*(ep->name) = 0xE5;
++
++	else if (type == TYPE_EXTEND)
++		ep->attr = ATTR_EXTEND;
++
++	else if (type == TYPE_DIR)
++		ep->attr = ATTR_SUBDIR;
++
++	else if (type == TYPE_FILE)
++		ep->attr = ATTR_ARCHIVE;
++
++	else if (type == TYPE_SYMLINK)
++		ep->attr = ATTR_ARCHIVE | ATTR_SYMLINK;
++}
++
++void exfat_set_entry_type(struct dentry_t *p_entry, u32 type)
++{
++	struct file_dentry_t *ep = (struct file_dentry_t *) p_entry;
++
++	if (type == TYPE_UNUSED) {
++		ep->type = 0x0;
++	} else if (type == TYPE_DELETED) {
++		ep->type &= ~0x80;
++	} else if (type == TYPE_STREAM) {
++		ep->type = 0xC0;
++	} else if (type == TYPE_EXTEND) {
++		ep->type = 0xC1;
++	} else if (type == TYPE_BITMAP) {
++		ep->type = 0x81;
++	} else if (type == TYPE_UPCASE) {
++		ep->type = 0x82;
++	} else if (type == TYPE_VOLUME) {
++		ep->type = 0x83;
++	} else if (type == TYPE_DIR) {
++		ep->type = 0x85;
++		SET16_A(ep->attr, ATTR_SUBDIR);
++	} else if (type == TYPE_FILE) {
++		ep->type = 0x85;
++		SET16_A(ep->attr, ATTR_ARCHIVE);
++	} else if (type == TYPE_SYMLINK) {
++		ep->type = 0x85;
++		SET16_A(ep->attr, ATTR_ARCHIVE | ATTR_SYMLINK);
++	}
++}
++
++u32 fat_get_entry_attr(struct dentry_t *p_entry)
++{
++	struct dos_dentry_t *ep = (struct dos_dentry_t *) p_entry;
++
++	return (u32) ep->attr;
++}
++
++u32 exfat_get_entry_attr(struct dentry_t *p_entry)
++{
++	struct file_dentry_t *ep = (struct file_dentry_t *) p_entry;
++
++	return (u32) GET16_A(ep->attr);
++}
++
++void fat_set_entry_attr(struct dentry_t *p_entry, u32 attr)
++{
++	struct dos_dentry_t *ep = (struct dos_dentry_t *) p_entry;
++
++	ep->attr = (u8) attr;
++}
++
++void exfat_set_entry_attr(struct dentry_t *p_entry, u32 attr)
++{
++	struct file_dentry_t *ep = (struct file_dentry_t *) p_entry;
++
++	SET16_A(ep->attr, (u16) attr);
++}
++
++u8 fat_get_entry_flag(struct dentry_t *p_entry)
++{
++	return 0x01;
++}
++
++u8 exfat_get_entry_flag(struct dentry_t *p_entry)
++{
++	struct strm_dentry_t *ep = (struct strm_dentry_t *) p_entry;
++
++	return ep->flags;
++}
++
++void fat_set_entry_flag(struct dentry_t *p_entry, u8 flags)
++{
++}
++
++void exfat_set_entry_flag(struct dentry_t *p_entry, u8 flags)
++{
++	struct strm_dentry_t *ep = (struct strm_dentry_t *) p_entry;
++
++	ep->flags = flags;
++}
++
++u32 fat_get_entry_clu0(struct dentry_t *p_entry)
++{
++	struct dos_dentry_t *ep = (struct dos_dentry_t *) p_entry;
++
++	return ((u32)GET16_A(ep->start_clu_hi) << 16) |
++		GET16_A(ep->start_clu_lo);
++}
++
++u32 exfat_get_entry_clu0(struct dentry_t *p_entry)
++{
++	struct strm_dentry_t *ep = (struct strm_dentry_t *) p_entry;
++
++	return GET32_A(ep->start_clu);
++}
++
++void fat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu)
++{
++	struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
++
++	SET16_A(ep->start_clu_lo, CLUSTER_16(start_clu));
++	SET16_A(ep->start_clu_hi, CLUSTER_16(start_clu >> 16));
++}
++
++void exfat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu)
++{
++	struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry;
++
++	SET32_A(ep->start_clu, start_clu);
++}
++
++u64 fat_get_entry_size(struct dentry_t *p_entry)
++{
++	struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
++
++	return (u64) GET32_A(ep->size);
++}
++
++u64 exfat_get_entry_size(struct dentry_t *p_entry)
++{
++	struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry;
++
++	return GET64_A(ep->valid_size);
++}
++
++void fat_set_entry_size(struct dentry_t *p_entry, u64 size)
++{
++	struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
++
++	SET32_A(ep->size, (u32) size);
++}
++
++void exfat_set_entry_size(struct dentry_t *p_entry, u64 size)
++{
++	struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry;
++
++	SET64_A(ep->valid_size, size);
++	SET64_A(ep->size, size);
++}
++
++void fat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
++			u8 mode)
++{
++	u16 t = 0x00, d = 0x21;
++	struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
++
++	switch (mode) {
++	case TM_CREATE:
++		t = GET16_A(ep->create_time);
++		d = GET16_A(ep->create_date);
++		break;
++	case TM_MODIFY:
++		t = GET16_A(ep->modify_time);
++		d = GET16_A(ep->modify_date);
++		break;
++	}
++
++	tp->sec  = (t & 0x001F) << 1;
++	tp->min  = (t >> 5) & 0x003F;
++	tp->hour = (t >> 11);
++	tp->day  = (d & 0x001F);
++	tp->mon  = (d >> 5) & 0x000F;
++	tp->year = (d >> 9);
++}
++
++void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
++			  u8 mode)
++{
++	u16 t = 0x00, d = 0x21;
++	struct file_dentry_t *ep = (struct file_dentry_t *)p_entry;
++
++	switch (mode) {
++	case TM_CREATE:
++		t = GET16_A(ep->create_time);
++		d = GET16_A(ep->create_date);
++		break;
++	case TM_MODIFY:
++		t = GET16_A(ep->modify_time);
++		d = GET16_A(ep->modify_date);
++		break;
++	case TM_ACCESS:
++		t = GET16_A(ep->access_time);
++		d = GET16_A(ep->access_date);
++		break;
++	}
++
++	tp->sec  = (t & 0x001F) << 1;
++	tp->min  = (t >> 5) & 0x003F;
++	tp->hour = (t >> 11);
++	tp->day  = (d & 0x001F);
++	tp->mon  = (d >> 5) & 0x000F;
++	tp->year = (d >> 9);
++}
++
++void fat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
++			u8 mode)
++{
++	u16 t, d;
++	struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
++
++	t = (tp->hour << 11) | (tp->min << 5) | (tp->sec >> 1);
++	d = (tp->year <<  9) | (tp->mon << 5) |  tp->day;
++
++	switch (mode) {
++	case TM_CREATE:
++		SET16_A(ep->create_time, t);
++		SET16_A(ep->create_date, d);
++		break;
++	case TM_MODIFY:
++		SET16_A(ep->modify_time, t);
++		SET16_A(ep->modify_date, d);
++		break;
++	}
++}
++
++void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
++			  u8 mode)
++{
++	u16 t, d;
++	struct file_dentry_t *ep = (struct file_dentry_t *)p_entry;
++
++	t = (tp->hour << 11) | (tp->min << 5) | (tp->sec >> 1);
++	d = (tp->year <<  9) | (tp->mon << 5) |  tp->day;
++
++	switch (mode) {
++	case TM_CREATE:
++		SET16_A(ep->create_time, t);
++		SET16_A(ep->create_date, d);
++		break;
++	case TM_MODIFY:
++		SET16_A(ep->modify_time, t);
++		SET16_A(ep->modify_date, d);
++		break;
++	case TM_ACCESS:
++		SET16_A(ep->access_time, t);
++		SET16_A(ep->access_date, d);
++		break;
++	}
++}
++
++s32 fat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir, s32 entry,
++		       u32 type, u32 start_clu, u64 size)
++{
++	sector_t sector;
++	struct dos_dentry_t *dos_ep;
++
++	dos_ep = (struct dos_dentry_t *)get_entry_in_dir(sb, p_dir, entry,
++							 §or);
++	if (!dos_ep)
++		return FFS_MEDIAERR;
++
++	init_dos_entry(dos_ep, type, start_clu);
++	buf_modify(sb, sector);
++
++	return FFS_SUCCESS;
++}
++
++s32 exfat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir,
++			 s32 entry, u32 type, u32 start_clu, u64 size)
++{
++	sector_t sector;
++	u8 flags;
++	struct file_dentry_t *file_ep;
++	struct strm_dentry_t *strm_ep;
++
++	flags = (type == TYPE_FILE) ? 0x01 : 0x03;
++
++	/* we cannot use get_entry_set_in_dir here because file ep is not initialized yet */
++	file_ep = (struct file_dentry_t *)get_entry_in_dir(sb, p_dir, entry,
++							   §or);
++	if (!file_ep)
++		return FFS_MEDIAERR;
++
++	strm_ep = (struct strm_dentry_t *)get_entry_in_dir(sb, p_dir, entry+1,
++							   §or);
++	if (!strm_ep)
++		return FFS_MEDIAERR;
++
++	init_file_entry(file_ep, type);
++	buf_modify(sb, sector);
++
++	init_strm_entry(strm_ep, flags, start_clu, size);
++	buf_modify(sb, sector);
++
++	return FFS_SUCCESS;
++}
++
++static s32 fat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir,
++			      s32 entry, s32 num_entries,
++			      struct uni_name_t *p_uniname,
++			      struct dos_name_t *p_dosname)
++{
++	int i;
++	sector_t sector;
++	u8 chksum;
++	u16 *uniname = p_uniname->name;
++	struct dos_dentry_t *dos_ep;
++	struct ext_dentry_t *ext_ep;
++
++	dos_ep = (struct dos_dentry_t *)get_entry_in_dir(sb, p_dir, entry,
++							 §or);
++	if (!dos_ep)
++		return FFS_MEDIAERR;
++
++	dos_ep->lcase = p_dosname->name_case;
++	memcpy(dos_ep->name, p_dosname->name, DOS_NAME_LENGTH);
++	buf_modify(sb, sector);
++
++	if ((--num_entries) > 0) {
++		chksum = calc_checksum_1byte((void *)dos_ep->name,
++					     DOS_NAME_LENGTH, 0);
++
++		for (i = 1; i < num_entries; i++) {
++			ext_ep = (struct ext_dentry_t *)get_entry_in_dir(sb,
++									 p_dir,
++									 entry - i,
++									 §or);
++			if (!ext_ep)
++				return FFS_MEDIAERR;
++
++			init_ext_entry(ext_ep, i, chksum, uniname);
++			buf_modify(sb, sector);
++			uniname += 13;
++		}
++
++		ext_ep = (struct ext_dentry_t *)get_entry_in_dir(sb, p_dir,
++								 entry - i,
++								 §or);
++		if (!ext_ep)
++			return FFS_MEDIAERR;
++
++		init_ext_entry(ext_ep, i+0x40, chksum, uniname);
++		buf_modify(sb, sector);
++	}
++
++	return FFS_SUCCESS;
++}
++
++static s32 exfat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir,
++				s32 entry, s32 num_entries,
++				struct uni_name_t *p_uniname,
++				struct dos_name_t *p_dosname)
++{
++	int i;
++	sector_t sector;
++	u16 *uniname = p_uniname->name;
++	struct file_dentry_t *file_ep;
++	struct strm_dentry_t *strm_ep;
++	struct name_dentry_t *name_ep;
++
++	file_ep = (struct file_dentry_t *)get_entry_in_dir(sb, p_dir, entry,
++							   §or);
++	if (!file_ep)
++		return FFS_MEDIAERR;
++
++	file_ep->num_ext = (u8)(num_entries - 1);
++	buf_modify(sb, sector);
++
++	strm_ep = (struct strm_dentry_t *)get_entry_in_dir(sb, p_dir, entry+1,
++							   §or);
++	if (!strm_ep)
++		return FFS_MEDIAERR;
++
++	strm_ep->name_len = p_uniname->name_len;
++	SET16_A(strm_ep->name_hash, p_uniname->name_hash);
++	buf_modify(sb, sector);
++
++	for (i = 2; i < num_entries; i++) {
++		name_ep = (struct name_dentry_t *)get_entry_in_dir(sb, p_dir,
++								   entry + i,
++								   §or);
++		if (!name_ep)
++			return FFS_MEDIAERR;
++
++		init_name_entry(name_ep, uniname);
++		buf_modify(sb, sector);
++		uniname += 15;
++	}
++
++	update_dir_checksum(sb, p_dir, entry);
++
++	return FFS_SUCCESS;
++}
++
++void init_dos_entry(struct dos_dentry_t *ep, u32 type, u32 start_clu)
++{
++	struct timestamp_t tm, *tp;
++
++	fat_set_entry_type((struct dentry_t *) ep, type);
++	SET16_A(ep->start_clu_lo, CLUSTER_16(start_clu));
++	SET16_A(ep->start_clu_hi, CLUSTER_16(start_clu >> 16));
++	SET32_A(ep->size, 0);
++
++	tp = tm_current(&tm);
++	fat_set_entry_time((struct dentry_t *) ep, tp, TM_CREATE);
++	fat_set_entry_time((struct dentry_t *) ep, tp, TM_MODIFY);
++	SET16_A(ep->access_date, 0);
++	ep->create_time_ms = 0;
++}
++
++void init_ext_entry(struct ext_dentry_t *ep, s32 order, u8 chksum, u16 *uniname)
++{
++	int i;
++	u8 end = FALSE;
++
++	fat_set_entry_type((struct dentry_t *) ep, TYPE_EXTEND);
++	ep->order = (u8) order;
++	ep->sysid = 0;
++	ep->checksum = chksum;
++	SET16_A(ep->start_clu, 0);
++
++	for (i = 0; i < 10; i += 2) {
++		if (!end) {
++			SET16(ep->unicode_0_4+i, *uniname);
++			if (*uniname == 0x0)
++				end = TRUE;
++			else
++				uniname++;
++		} else {
++			SET16(ep->unicode_0_4+i, 0xFFFF);
++		}
++	}
++
++	for (i = 0; i < 12; i += 2) {
++		if (!end) {
++			SET16_A(ep->unicode_5_10 + i, *uniname);
++			if (*uniname == 0x0)
++				end = TRUE;
++			else
++				uniname++;
++		} else {
++			SET16_A(ep->unicode_5_10 + i, 0xFFFF);
++		}
++	}
++
++	for (i = 0; i < 4; i += 2) {
++		if (!end) {
++			SET16_A(ep->unicode_11_12 + i, *uniname);
++			if (*uniname == 0x0)
++				end = TRUE;
++			else
++				uniname++;
++		} else {
++			SET16_A(ep->unicode_11_12 + i, 0xFFFF);
++		}
++	}
++}
++
++void init_file_entry(struct file_dentry_t *ep, u32 type)
++{
++	struct timestamp_t tm, *tp;
++
++	exfat_set_entry_type((struct dentry_t *)ep, type);
++
++	tp = tm_current(&tm);
++	exfat_set_entry_time((struct dentry_t *)ep, tp, TM_CREATE);
++	exfat_set_entry_time((struct dentry_t *)ep, tp, TM_MODIFY);
++	exfat_set_entry_time((struct dentry_t *)ep, tp, TM_ACCESS);
++	ep->create_time_ms = 0;
++	ep->modify_time_ms = 0;
++	ep->access_time_ms = 0;
++}
++
++void init_strm_entry(struct strm_dentry_t *ep, u8 flags, u32 start_clu, u64 size)
++{
++	exfat_set_entry_type((struct dentry_t *)ep, TYPE_STREAM);
++	ep->flags = flags;
++	SET32_A(ep->start_clu, start_clu);
++	SET64_A(ep->valid_size, size);
++	SET64_A(ep->size, size);
++}
++
++void init_name_entry(struct name_dentry_t *ep, u16 *uniname)
++{
++	int i;
++
++	exfat_set_entry_type((struct dentry_t *)ep, TYPE_EXTEND);
++	ep->flags = 0x0;
++
++	for (i = 0; i < 30; i++, i++) {
++		SET16_A(ep->unicode_0_14+i, *uniname);
++		if (*uniname == 0x0)
++			break;
++		uniname++;
++	}
++}
++
++void fat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir,
++		s32 entry, s32 order, s32 num_entries)
++{
++	int i;
++	sector_t sector;
++	struct dentry_t *ep;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	for (i = num_entries-1; i >= order; i--) {
++		ep = get_entry_in_dir(sb, p_dir, entry-i, §or);
++		if (!ep)
++			return;
++
++		p_fs->fs_func->set_entry_type(ep, TYPE_DELETED);
++		buf_modify(sb, sector);
++	}
++}
++
++void exfat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir,
++		s32 entry, s32 order, s32 num_entries)
++{
++	int i;
++	sector_t sector;
++	struct dentry_t *ep;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	for (i = order; i < num_entries; i++) {
++		ep = get_entry_in_dir(sb, p_dir, entry+i, §or);
++		if (!ep)
++			return;
++
++		p_fs->fs_func->set_entry_type(ep, TYPE_DELETED);
++		buf_modify(sb, sector);
++	}
++}
++
++void update_dir_checksum(struct super_block *sb, struct chain_t *p_dir,
++			 s32 entry)
++{
++	int i, num_entries;
++	sector_t sector;
++	u16 chksum;
++	struct file_dentry_t *file_ep;
++	struct dentry_t *ep;
++
++	file_ep = (struct file_dentry_t *)get_entry_in_dir(sb, p_dir, entry,
++							   §or);
++	if (!file_ep)
++		return;
++
++	buf_lock(sb, sector);
++
++	num_entries = (s32) file_ep->num_ext + 1;
++	chksum = calc_checksum_2byte((void *)file_ep, DENTRY_SIZE, 0,
++				     CS_DIR_ENTRY);
++
++	for (i = 1; i < num_entries; i++) {
++		ep = get_entry_in_dir(sb, p_dir, entry+i, NULL);
++		if (!ep) {
++			buf_unlock(sb, sector);
++			return;
++		}
++
++		chksum = calc_checksum_2byte((void *)ep, DENTRY_SIZE, chksum,
++					     CS_DEFAULT);
++	}
++
++	SET16_A(file_ep->checksum, chksum);
++	buf_modify(sb, sector);
++	buf_unlock(sb, sector);
++}
++
++void update_dir_checksum_with_entry_set(struct super_block *sb,
++					struct entry_set_cache_t *es)
++{
++	struct dentry_t *ep;
++	u16 chksum = 0;
++	s32 chksum_type = CS_DIR_ENTRY, i;
++
++	ep = (struct dentry_t *)&(es->__buf);
++	for (i = 0; i < es->num_entries; i++) {
++		pr_debug("%s ep %p\n", __func__, ep);
++		chksum = calc_checksum_2byte((void *)ep, DENTRY_SIZE, chksum,
++					     chksum_type);
++		ep++;
++		chksum_type = CS_DEFAULT;
++	}
++
++	ep = (struct dentry_t *)&(es->__buf);
++	SET16_A(((struct file_dentry_t *)ep)->checksum, chksum);
++	write_whole_entry_set(sb, es);
++}
++
++static s32 _walk_fat_chain(struct super_block *sb, struct chain_t *p_dir,
++			   s32 byte_offset, u32 *clu)
++{
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	s32 clu_offset;
++	u32 cur_clu;
++
++	clu_offset = byte_offset >> p_fs->cluster_size_bits;
++	cur_clu = p_dir->dir;
++
++	if (p_dir->flags == 0x03) {
++		cur_clu += clu_offset;
++	} else {
++		while (clu_offset > 0) {
++			if (FAT_read(sb, cur_clu, &cur_clu) == -1)
++				return FFS_MEDIAERR;
++			clu_offset--;
++		}
++	}
++
++	if (clu)
++		*clu = cur_clu;
++	return FFS_SUCCESS;
++}
++
++s32 find_location(struct super_block *sb, struct chain_t *p_dir, s32 entry,
++		  sector_t *sector, s32 *offset)
++{
++	s32 off, ret;
++	u32 clu = 0;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++
++	off = entry << DENTRY_SIZE_BITS;
++
++	if (p_dir->dir == CLUSTER_32(0)) { /* FAT16 root_dir */
++		*offset = off & p_bd->sector_size_mask;
++		*sector = off >> p_bd->sector_size_bits;
++		*sector += p_fs->root_start_sector;
++	} else {
++		ret = _walk_fat_chain(sb, p_dir, off, &clu);
++		if (ret != FFS_SUCCESS)
++			return ret;
++
++		/* byte offset in cluster */
++		off &= p_fs->cluster_size - 1;
++
++		/* byte offset in sector    */
++		*offset = off & p_bd->sector_size_mask;
++
++		/* sector offset in cluster */
++		*sector = off >> p_bd->sector_size_bits;
++		*sector += START_SECTOR(clu);
++	}
++	return FFS_SUCCESS;
++}
++
++struct dentry_t *get_entry_with_sector(struct super_block *sb, sector_t sector,
++				       s32 offset)
++{
++	u8 *buf;
++
++	buf = buf_getblk(sb, sector);
++
++	if (buf == NULL)
++		return NULL;
++
++	return (struct dentry_t *)(buf + offset);
++}
++
++struct dentry_t *get_entry_in_dir(struct super_block *sb, struct chain_t *p_dir,
++				  s32 entry, sector_t *sector)
++{
++	s32 off;
++	sector_t sec;
++	u8 *buf;
++
++	if (find_location(sb, p_dir, entry, &sec, &off) != FFS_SUCCESS)
++		return NULL;
++
++	buf = buf_getblk(sb, sec);
++
++	if (buf == NULL)
++		return NULL;
++
++	if (sector != NULL)
++		*sector = sec;
++	return (struct dentry_t *)(buf + off);
++}
++
++/* returns a set of dentries for a file or dir.
++ * Note that this is a copy (dump) of dentries so that user should call write_entry_set()
++ * to apply changes made in this entry set to the real device.
++ * in:
++ *   sb+p_dir+entry: indicates a file/dir
++ *   type:  specifies how many dentries should be included.
++ * out:
++ *   file_ep: will point the first dentry(= file dentry) on success
++ * return:
++ *   pointer of entry set on success,
++ *   NULL on failure.
++ */
++
++#define ES_MODE_STARTED				0
++#define ES_MODE_GET_FILE_ENTRY			1
++#define ES_MODE_GET_STRM_ENTRY			2
++#define ES_MODE_GET_NAME_ENTRY			3
++#define ES_MODE_GET_CRITICAL_SEC_ENTRY		4
++struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb,
++					       struct chain_t *p_dir, s32 entry,
++					       u32 type,
++					       struct dentry_t **file_ep)
++{
++	s32 off, ret, byte_offset;
++	u32 clu = 0;
++	sector_t sec;
++	u32 entry_type;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++	struct entry_set_cache_t *es = NULL;
++	struct dentry_t *ep, *pos;
++	u8 *buf;
++	u8 num_entries;
++	s32 mode = ES_MODE_STARTED;
++	size_t bufsize;
++
++	pr_debug("%s entered p_dir dir %u flags %x size %d\n",
++		__func__, p_dir->dir, p_dir->flags, p_dir->size);
++
++	byte_offset = entry << DENTRY_SIZE_BITS;
++	ret = _walk_fat_chain(sb, p_dir, byte_offset, &clu);
++	if (ret != FFS_SUCCESS)
++		return NULL;
++
++
++	/* byte offset in cluster */
++	byte_offset &= p_fs->cluster_size - 1;
++
++	/* byte offset in sector    */
++	off = byte_offset & p_bd->sector_size_mask;
++
++	/* sector offset in cluster */
++	sec = byte_offset >> p_bd->sector_size_bits;
++	sec += START_SECTOR(clu);
++
++	buf = buf_getblk(sb, sec);
++	if (buf == NULL)
++		goto err_out;
++
++
++	ep = (struct dentry_t *)(buf + off);
++	entry_type = p_fs->fs_func->get_entry_type(ep);
++
++	if ((entry_type != TYPE_FILE)
++		&& (entry_type != TYPE_DIR))
++		goto err_out;
++
++	if (type == ES_ALL_ENTRIES)
++		num_entries = ((struct file_dentry_t *)ep)->num_ext+1;
++	else
++		num_entries = type;
++
++	bufsize = offsetof(struct entry_set_cache_t, __buf) + (num_entries) *
++		  sizeof(struct dentry_t);
++	pr_debug("%s: trying to kmalloc %zx bytes for %d entries\n", __func__,
++		 bufsize, num_entries);
++	es = kmalloc(bufsize, GFP_KERNEL);
++	if (es == NULL)
++		goto err_out;
++
++	es->num_entries = num_entries;
++	es->sector = sec;
++	es->offset = off;
++	es->alloc_flag = p_dir->flags;
++
++	pos = (struct dentry_t *) &(es->__buf);
++
++	while (num_entries) {
++		/*
++		 * instead of copying whole sector, we will check every entry.
++		 * this will provide minimum stablity and consistancy.
++		 */
++		entry_type = p_fs->fs_func->get_entry_type(ep);
++
++		if ((entry_type == TYPE_UNUSED) || (entry_type == TYPE_DELETED))
++			goto err_out;
++
++		switch (mode) {
++		case ES_MODE_STARTED:
++			if ((entry_type == TYPE_FILE) || (entry_type == TYPE_DIR))
++				mode = ES_MODE_GET_FILE_ENTRY;
++			else
++				goto err_out;
++			break;
++		case ES_MODE_GET_FILE_ENTRY:
++			if (entry_type == TYPE_STREAM)
++				mode = ES_MODE_GET_STRM_ENTRY;
++			else
++				goto err_out;
++			break;
++		case ES_MODE_GET_STRM_ENTRY:
++			if (entry_type == TYPE_EXTEND)
++				mode = ES_MODE_GET_NAME_ENTRY;
++			else
++				goto err_out;
++			break;
++		case ES_MODE_GET_NAME_ENTRY:
++			if (entry_type == TYPE_EXTEND)
++				break;
++			else if (entry_type == TYPE_STREAM)
++				goto err_out;
++			else if (entry_type & TYPE_CRITICAL_SEC)
++				mode = ES_MODE_GET_CRITICAL_SEC_ENTRY;
++			else
++				goto err_out;
++			break;
++		case ES_MODE_GET_CRITICAL_SEC_ENTRY:
++			if ((entry_type == TYPE_EXTEND) ||
++			    (entry_type == TYPE_STREAM))
++				goto err_out;
++			else if ((entry_type & TYPE_CRITICAL_SEC) !=
++				 TYPE_CRITICAL_SEC)
++				goto err_out;
++			break;
++		}
++
++		memcpy(pos, ep, sizeof(struct dentry_t));
++
++		if (--num_entries == 0)
++			break;
++
++		if (((off + DENTRY_SIZE) & p_bd->sector_size_mask) <
++		    (off &  p_bd->sector_size_mask)) {
++			/* get the next sector */
++			if (IS_LAST_SECTOR_IN_CLUSTER(sec)) {
++				if (es->alloc_flag == 0x03) {
++					clu++;
++				} else {
++					if (FAT_read(sb, clu, &clu) == -1)
++						goto err_out;
++				}
++				sec = START_SECTOR(clu);
++			} else {
++				sec++;
++			}
++			buf = buf_getblk(sb, sec);
++			if (buf == NULL)
++				goto err_out;
++			off = 0;
++			ep = (struct dentry_t *)(buf);
++		} else {
++			ep++;
++			off += DENTRY_SIZE;
++		}
++		pos++;
++	}
++
++	if (file_ep)
++		*file_ep = (struct dentry_t *)&(es->__buf);
++
++	pr_debug("%s exiting es %p sec %llu offset %d flags %d, num_entries %u buf ptr %p\n",
++		   __func__, es, (unsigned long long)es->sector, es->offset,
++		   es->alloc_flag, es->num_entries, &es->__buf);
++	return es;
++err_out:
++	pr_debug("%s exited NULL (es %p)\n", __func__, es);
++	kfree(es);
++	return NULL;
++}
++
++void release_entry_set(struct entry_set_cache_t *es)
++{
++	pr_debug("%s es=%p\n", __func__, es);
++	kfree(es);
++}
++
++
++static s32 __write_partial_entries_in_entry_set(struct super_block *sb,
++						struct entry_set_cache_t *es,
++						sector_t sec, s32 off, u32 count)
++{
++	s32 num_entries, buf_off = (off - es->offset);
++	u32 remaining_byte_in_sector, copy_entries;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++	u32 clu;
++	u8 *buf, *esbuf = (u8 *)&(es->__buf);
++
++	pr_debug("%s entered es %p sec %llu off %d count %d\n",
++		__func__, es, (unsigned long long)sec, off, count);
++	num_entries = count;
++
++	while (num_entries) {
++		/* white per sector base */
++		remaining_byte_in_sector = (1 << p_bd->sector_size_bits) - off;
++		copy_entries = min_t(s32,
++				     remaining_byte_in_sector >> DENTRY_SIZE_BITS,
++				     num_entries);
++		buf = buf_getblk(sb, sec);
++		if (buf == NULL)
++			goto err_out;
++		pr_debug("es->buf %p buf_off %u\n", esbuf, buf_off);
++		pr_debug("copying %d entries from %p to sector %llu\n",
++			copy_entries, (esbuf + buf_off),
++			(unsigned long long)sec);
++		memcpy(buf + off, esbuf + buf_off,
++		       copy_entries << DENTRY_SIZE_BITS);
++		buf_modify(sb, sec);
++		num_entries -= copy_entries;
++
++		if (num_entries) {
++			/* get next sector */
++			if (IS_LAST_SECTOR_IN_CLUSTER(sec)) {
++				clu = GET_CLUSTER_FROM_SECTOR(sec);
++				if (es->alloc_flag == 0x03) {
++					clu++;
++				} else {
++					if (FAT_read(sb, clu, &clu) == -1)
++						goto err_out;
++				}
++				sec = START_SECTOR(clu);
++			} else {
++				sec++;
++			}
++			off = 0;
++			buf_off += copy_entries << DENTRY_SIZE_BITS;
++		}
++	}
++
++	pr_debug("%s exited successfully\n", __func__);
++	return FFS_SUCCESS;
++err_out:
++	pr_debug("%s failed\n", __func__);
++	return FFS_ERROR;
++}
++
++/* write back all entries in entry set */
++s32 write_whole_entry_set(struct super_block *sb, struct entry_set_cache_t *es)
++{
++	return __write_partial_entries_in_entry_set(sb, es, es->sector,
++						    es->offset,
++						    es->num_entries);
++}
++
++/* write back some entries in entry set */
++s32 write_partial_entries_in_entry_set(struct super_block *sb,
++	struct entry_set_cache_t *es, struct dentry_t *ep, u32 count)
++{
++	s32 ret, byte_offset, off;
++	u32 clu = 0;
++	sector_t sec;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++	struct chain_t dir;
++
++	/* vaidity check */
++	if (ep + count  > ((struct dentry_t *)&(es->__buf)) + es->num_entries)
++		return FFS_ERROR;
++
++	dir.dir = GET_CLUSTER_FROM_SECTOR(es->sector);
++	dir.flags = es->alloc_flag;
++	dir.size = 0xffffffff;		/* XXX */
++
++	byte_offset = (es->sector - START_SECTOR(dir.dir)) <<
++			p_bd->sector_size_bits;
++	byte_offset += ((void **)ep - &(es->__buf)) + es->offset;
++
++	ret = _walk_fat_chain(sb, &dir, byte_offset, &clu);
++	if (ret != FFS_SUCCESS)
++		return ret;
++
++	/* byte offset in cluster */
++	byte_offset &= p_fs->cluster_size - 1;
++
++	/* byte offset in sector    */
++	off = byte_offset & p_bd->sector_size_mask;
++
++	/* sector offset in cluster */
++	sec = byte_offset >> p_bd->sector_size_bits;
++	sec += START_SECTOR(clu);
++	return __write_partial_entries_in_entry_set(sb, es, sec, off, count);
++}
++
++/* search EMPTY CONTINUOUS "num_entries" entries */
++s32 search_deleted_or_unused_entry(struct super_block *sb,
++				   struct chain_t *p_dir, s32 num_entries)
++{
++	int i, dentry, num_empty = 0;
++	s32 dentries_per_clu;
++	u32 type;
++	struct chain_t clu;
++	struct dentry_t *ep;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */
++		dentries_per_clu = p_fs->dentries_in_root;
++	else
++		dentries_per_clu = p_fs->dentries_per_clu;
++
++	if (p_fs->hint_uentry.dir == p_dir->dir) {
++		if (p_fs->hint_uentry.entry == -1)
++			return -1;
++
++		clu.dir = p_fs->hint_uentry.clu.dir;
++		clu.size = p_fs->hint_uentry.clu.size;
++		clu.flags = p_fs->hint_uentry.clu.flags;
++
++		dentry = p_fs->hint_uentry.entry;
++	} else {
++		p_fs->hint_uentry.entry = -1;
++
++		clu.dir = p_dir->dir;
++		clu.size = p_dir->size;
++		clu.flags = p_dir->flags;
++
++		dentry = 0;
++	}
++
++	while (clu.dir != CLUSTER_32(~0)) {
++		if (p_fs->dev_ejected)
++			break;
++
++		if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */
++			i = dentry % dentries_per_clu;
++		else
++			i = dentry & (dentries_per_clu-1);
++
++		for (; i < dentries_per_clu; i++, dentry++) {
++			ep = get_entry_in_dir(sb, &clu, i, NULL);
++			if (!ep)
++				return -1;
++
++			type = p_fs->fs_func->get_entry_type(ep);
++
++			if (type == TYPE_UNUSED) {
++				num_empty++;
++				if (p_fs->hint_uentry.entry == -1) {
++					p_fs->hint_uentry.dir = p_dir->dir;
++					p_fs->hint_uentry.entry = dentry;
++
++					p_fs->hint_uentry.clu.dir = clu.dir;
++					p_fs->hint_uentry.clu.size = clu.size;
++					p_fs->hint_uentry.clu.flags = clu.flags;
++				}
++			} else if (type == TYPE_DELETED) {
++				num_empty++;
++			} else {
++				num_empty = 0;
++			}
++
++			if (num_empty >= num_entries) {
++				p_fs->hint_uentry.dir = CLUSTER_32(~0);
++				p_fs->hint_uentry.entry = -1;
++
++				if (p_fs->vol_type == EXFAT)
++					return dentry - (num_entries-1);
++				else
++					return dentry;
++			}
++		}
++
++		if (p_dir->dir == CLUSTER_32(0))
++			break; /* FAT16 root_dir */
++
++		if (clu.flags == 0x03) {
++			if ((--clu.size) > 0)
++				clu.dir++;
++			else
++				clu.dir = CLUSTER_32(~0);
++		} else {
++			if (FAT_read(sb, clu.dir, &clu.dir) != 0)
++				return -1;
++		}
++	}
++
++	return -1;
++}
++
++s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_entries)
++{
++	s32 ret, dentry;
++	u32 last_clu;
++	sector_t sector;
++	u64 size = 0;
++	struct chain_t clu;
++	struct dentry_t *ep = NULL;
++	struct super_block *sb = inode->i_sb;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct file_id_t *fid = &(EXFAT_I(inode)->fid);
++
++	if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */
++		return search_deleted_or_unused_entry(sb, p_dir, num_entries);
++
++	while ((dentry = search_deleted_or_unused_entry(sb, p_dir, num_entries)) < 0) {
++		if (p_fs->dev_ejected)
++			break;
++
++		if (p_fs->vol_type == EXFAT) {
++			if (p_dir->dir != p_fs->root_dir)
++				size = i_size_read(inode);
++		}
++
++		last_clu = find_last_cluster(sb, p_dir);
++		clu.dir = last_clu + 1;
++		clu.size = 0;
++		clu.flags = p_dir->flags;
++
++		/* (1) allocate a cluster */
++		ret = p_fs->fs_func->alloc_cluster(sb, 1, &clu);
++		if (ret < 1)
++			return -1;
++
++		if (clear_cluster(sb, clu.dir) != FFS_SUCCESS)
++			return -1;
++
++		/* (2) append to the FAT chain */
++		if (clu.flags != p_dir->flags) {
++			exfat_chain_cont_cluster(sb, p_dir->dir, p_dir->size);
++			p_dir->flags = 0x01;
++			p_fs->hint_uentry.clu.flags = 0x01;
++		}
++		if (clu.flags == 0x01)
++			if (FAT_write(sb, last_clu, clu.dir) < 0)
++				return -1;
++
++		if (p_fs->hint_uentry.entry == -1) {
++			p_fs->hint_uentry.dir = p_dir->dir;
++			p_fs->hint_uentry.entry = p_dir->size << (p_fs->cluster_size_bits - DENTRY_SIZE_BITS);
++
++			p_fs->hint_uentry.clu.dir = clu.dir;
++			p_fs->hint_uentry.clu.size = 0;
++			p_fs->hint_uentry.clu.flags = clu.flags;
++		}
++		p_fs->hint_uentry.clu.size++;
++		p_dir->size++;
++
++		/* (3) update the directory entry */
++		if (p_fs->vol_type == EXFAT) {
++			if (p_dir->dir != p_fs->root_dir) {
++				size += p_fs->cluster_size;
++
++				ep = get_entry_in_dir(sb, &fid->dir,
++						      fid->entry + 1, §or);
++				if (!ep)
++					return -1;
++				p_fs->fs_func->set_entry_size(ep, size);
++				p_fs->fs_func->set_entry_flag(ep, p_dir->flags);
++				buf_modify(sb, sector);
++
++				update_dir_checksum(sb, &(fid->dir),
++						    fid->entry);
++			}
++		}
++
++		i_size_write(inode, i_size_read(inode)+p_fs->cluster_size);
++		EXFAT_I(inode)->mmu_private += p_fs->cluster_size;
++		EXFAT_I(inode)->fid.size += p_fs->cluster_size;
++		EXFAT_I(inode)->fid.flags = p_dir->flags;
++		inode->i_blocks += 1 << (p_fs->cluster_size_bits - 9);
++	}
++
++	return dentry;
++}
++
++/* return values of fat_find_dir_entry()
++ * >= 0 : return dir entiry position with the name in dir
++ * -1 : (root dir, ".") it is the root dir itself
++ * -2 : entry with the name does not exist
++ */
++s32 fat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir,
++		       struct uni_name_t *p_uniname, s32 num_entries,
++		       struct dos_name_t *p_dosname, u32 type)
++{
++	int i, dentry = 0, lossy = FALSE, len;
++	s32 order = 0, is_feasible_entry = TRUE, has_ext_entry = FALSE;
++	s32 dentries_per_clu;
++	u32 entry_type;
++	u16 entry_uniname[14], *uniname = NULL, unichar;
++	struct chain_t clu;
++	struct dentry_t *ep;
++	struct dos_dentry_t *dos_ep;
++	struct ext_dentry_t *ext_ep;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	if (p_dir->dir == p_fs->root_dir) {
++		if ((!nls_uniname_cmp(sb, p_uniname->name,
++				      (u16 *)UNI_CUR_DIR_NAME)) ||
++			(!nls_uniname_cmp(sb, p_uniname->name,
++					  (u16 *)UNI_PAR_DIR_NAME)))
++			return -1; // special case, root directory itself
++	}
++
++	if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */
++		dentries_per_clu = p_fs->dentries_in_root;
++	else
++		dentries_per_clu = p_fs->dentries_per_clu;
++
++	clu.dir = p_dir->dir;
++	clu.flags = p_dir->flags;
++
++	while (clu.dir != CLUSTER_32(~0)) {
++		if (p_fs->dev_ejected)
++			break;
++
++		for (i = 0; i < dentries_per_clu; i++, dentry++) {
++			ep = get_entry_in_dir(sb, &clu, i, NULL);
++			if (!ep)
++				return -2;
++
++			entry_type = p_fs->fs_func->get_entry_type(ep);
++
++			if ((entry_type == TYPE_FILE) || (entry_type == TYPE_DIR)) {
++				if ((type == TYPE_ALL) || (type == entry_type)) {
++					if (is_feasible_entry && has_ext_entry)
++						return dentry;
++
++					dos_ep = (struct dos_dentry_t *) ep;
++					if ((!lossy) && (!nls_dosname_cmp(sb, p_dosname->name, dos_ep->name)))
++						return dentry;
++				}
++				is_feasible_entry = TRUE;
++				has_ext_entry = FALSE;
++			} else if (entry_type == TYPE_EXTEND) {
++				if (is_feasible_entry) {
++					ext_ep = (struct ext_dentry_t *) ep;
++					if (ext_ep->order > 0x40) {
++						order = (s32)(ext_ep->order - 0x40);
++						uniname = p_uniname->name + 13 * (order-1);
++					} else {
++						order = (s32) ext_ep->order;
++						uniname -= 13;
++					}
++
++					len = extract_uni_name_from_ext_entry(ext_ep, entry_uniname, order);
++
++					unichar = *(uniname+len);
++					*(uniname+len) = 0x0;
++
++					if (nls_uniname_cmp(sb, uniname, entry_uniname))
++						is_feasible_entry = FALSE;
++
++					*(uniname+len) = unichar;
++				}
++				has_ext_entry = TRUE;
++			} else if (entry_type == TYPE_UNUSED) {
++				return -2;
++			}
++			is_feasible_entry = TRUE;
++			has_ext_entry = FALSE;
++		}
++
++		if (p_dir->dir == CLUSTER_32(0))
++			break; /* FAT16 root_dir */
++
++		if (FAT_read(sb, clu.dir, &clu.dir) != 0)
++			return -2;
++	}
++
++	return -2;
++}
++
++/* return values of exfat_find_dir_entry()
++ * >= 0 : return dir entiry position with the name in dir
++ * -1 : (root dir, ".") it is the root dir itself
++ * -2 : entry with the name does not exist
++ */
++s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir,
++			 struct uni_name_t *p_uniname, s32 num_entries,
++			 struct dos_name_t *p_dosname, u32 type)
++{
++	int i = 0, dentry = 0, num_ext_entries = 0, len, step;
++	s32 order = 0, is_feasible_entry = FALSE;
++	s32 dentries_per_clu, num_empty = 0;
++	u32 entry_type;
++	u16 entry_uniname[16], *uniname = NULL, unichar;
++	struct chain_t clu;
++	struct dentry_t *ep;
++	struct file_dentry_t *file_ep;
++	struct strm_dentry_t *strm_ep;
++	struct name_dentry_t *name_ep;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	if (p_dir->dir == p_fs->root_dir) {
++		if ((!nls_uniname_cmp(sb, p_uniname->name,
++				      (u16 *)UNI_CUR_DIR_NAME)) ||
++			(!nls_uniname_cmp(sb, p_uniname->name,
++					  (u16 *)UNI_PAR_DIR_NAME)))
++			return -1; // special case, root directory itself
++	}
++
++	if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */
++		dentries_per_clu = p_fs->dentries_in_root;
++	else
++		dentries_per_clu = p_fs->dentries_per_clu;
++
++	clu.dir = p_dir->dir;
++	clu.size = p_dir->size;
++	clu.flags = p_dir->flags;
++
++	p_fs->hint_uentry.dir = p_dir->dir;
++	p_fs->hint_uentry.entry = -1;
++
++	while (clu.dir != CLUSTER_32(~0)) {
++		if (p_fs->dev_ejected)
++			break;
++
++		while (i < dentries_per_clu) {
++			ep = get_entry_in_dir(sb, &clu, i, NULL);
++			if (!ep)
++				return -2;
++
++			entry_type = p_fs->fs_func->get_entry_type(ep);
++			step = 1;
++
++			if ((entry_type == TYPE_UNUSED) || (entry_type == TYPE_DELETED)) {
++				is_feasible_entry = FALSE;
++
++				if (p_fs->hint_uentry.entry == -1) {
++					num_empty++;
++
++					if (num_empty == 1) {
++						p_fs->hint_uentry.clu.dir = clu.dir;
++						p_fs->hint_uentry.clu.size = clu.size;
++						p_fs->hint_uentry.clu.flags = clu.flags;
++					}
++					if ((num_empty >= num_entries) || (entry_type == TYPE_UNUSED))
++						p_fs->hint_uentry.entry = dentry - (num_empty-1);
++				}
++
++				if (entry_type == TYPE_UNUSED)
++					return -2;
++			} else {
++				num_empty = 0;
++
++				if ((entry_type == TYPE_FILE) || (entry_type == TYPE_DIR)) {
++					file_ep = (struct file_dentry_t *) ep;
++					if ((type == TYPE_ALL) || (type == entry_type)) {
++						num_ext_entries = file_ep->num_ext;
++						is_feasible_entry = TRUE;
++					} else {
++						is_feasible_entry = FALSE;
++						step = file_ep->num_ext + 1;
++					}
++				} else if (entry_type == TYPE_STREAM) {
++					if (is_feasible_entry) {
++						strm_ep = (struct strm_dentry_t *)ep;
++						if (p_uniname->name_hash == GET16_A(strm_ep->name_hash) &&
++						    p_uniname->name_len == strm_ep->name_len) {
++							order = 1;
++						} else {
++							is_feasible_entry = FALSE;
++							step = num_ext_entries;
++						}
++					}
++				} else if (entry_type == TYPE_EXTEND) {
++					if (is_feasible_entry) {
++						name_ep = (struct name_dentry_t *)ep;
++
++						if ((++order) == 2)
++							uniname = p_uniname->name;
++						else
++							uniname += 15;
++
++						len = extract_uni_name_from_name_entry(name_ep,
++								entry_uniname, order);
++
++						unichar = *(uniname+len);
++						*(uniname+len) = 0x0;
++
++						if (nls_uniname_cmp(sb, uniname, entry_uniname)) {
++							is_feasible_entry = FALSE;
++							step = num_ext_entries - order + 1;
++						} else if (order == num_ext_entries) {
++							p_fs->hint_uentry.dir = CLUSTER_32(~0);
++							p_fs->hint_uentry.entry = -1;
++							return dentry - (num_ext_entries);
++						}
++
++						*(uniname+len) = unichar;
++					}
++				} else {
++					is_feasible_entry = FALSE;
++				}
++			}
++
++			i += step;
++			dentry += step;
++		}
++
++		i -= dentries_per_clu;
++
++		if (p_dir->dir == CLUSTER_32(0))
++			break; /* FAT16 root_dir */
++
++		if (clu.flags == 0x03) {
++			if ((--clu.size) > 0)
++				clu.dir++;
++			else
++				clu.dir = CLUSTER_32(~0);
++		} else {
++			if (FAT_read(sb, clu.dir, &clu.dir) != 0)
++				return -2;
++		}
++	}
++
++	return -2;
++}
++
++s32 fat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir,
++			  s32 entry, struct dentry_t *p_entry)
++{
++	s32 count = 0;
++	u8 chksum;
++	struct dos_dentry_t *dos_ep = (struct dos_dentry_t *) p_entry;
++	struct ext_dentry_t *ext_ep;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	chksum = calc_checksum_1byte((void *) dos_ep->name, DOS_NAME_LENGTH, 0);
++
++	for (entry--; entry >= 0; entry--) {
++		ext_ep = (struct ext_dentry_t *)get_entry_in_dir(sb, p_dir,
++								 entry, NULL);
++		if (!ext_ep)
++			return -1;
++
++		if ((p_fs->fs_func->get_entry_type((struct dentry_t *)ext_ep) ==
++		     TYPE_EXTEND) && (ext_ep->checksum == chksum)) {
++			count++;
++			if (ext_ep->order > 0x40)
++				return count;
++		} else {
++			return count;
++		}
++	}
++
++	return count;
++}
++
++s32 exfat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir,
++			    s32 entry, struct dentry_t *p_entry)
++{
++	int i, count = 0;
++	u32 type;
++	struct file_dentry_t *file_ep = (struct file_dentry_t *)p_entry;
++	struct dentry_t *ext_ep;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	for (i = 0, entry++; i < file_ep->num_ext; i++, entry++) {
++		ext_ep = get_entry_in_dir(sb, p_dir, entry, NULL);
++		if (!ext_ep)
++			return -1;
++
++		type = p_fs->fs_func->get_entry_type(ext_ep);
++		if ((type == TYPE_EXTEND) || (type == TYPE_STREAM))
++			count++;
++		else
++			return count;
++	}
++
++	return count;
++}
++
++s32 count_dos_name_entries(struct super_block *sb, struct chain_t *p_dir,
++			   u32 type)
++{
++	int i, count = 0;
++	s32 dentries_per_clu;
++	u32 entry_type;
++	struct chain_t clu;
++	struct dentry_t *ep;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */
++		dentries_per_clu = p_fs->dentries_in_root;
++	else
++		dentries_per_clu = p_fs->dentries_per_clu;
++
++	clu.dir = p_dir->dir;
++	clu.size = p_dir->size;
++	clu.flags = p_dir->flags;
++
++	while (clu.dir != CLUSTER_32(~0)) {
++		if (p_fs->dev_ejected)
++			break;
++
++		for (i = 0; i < dentries_per_clu; i++) {
++			ep = get_entry_in_dir(sb, &clu, i, NULL);
++			if (!ep)
++				return -1;
++
++			entry_type = p_fs->fs_func->get_entry_type(ep);
++
++			if (entry_type == TYPE_UNUSED)
++				return count;
++			if (!(type & TYPE_CRITICAL_PRI) &&
++			    !(type & TYPE_BENIGN_PRI))
++				continue;
++
++			if ((type == TYPE_ALL) || (type == entry_type))
++				count++;
++		}
++
++		if (p_dir->dir == CLUSTER_32(0))
++			break; /* FAT16 root_dir */
++
++		if (clu.flags == 0x03) {
++			if ((--clu.size) > 0)
++				clu.dir++;
++			else
++				clu.dir = CLUSTER_32(~0);
++		} else {
++			if (FAT_read(sb, clu.dir, &clu.dir) != 0)
++				return -1;
++		}
++	}
++
++	return count;
++}
++
++bool is_dir_empty(struct super_block *sb, struct chain_t *p_dir)
++{
++	int i, count = 0;
++	s32 dentries_per_clu;
++	u32 type;
++	struct chain_t clu;
++	struct dentry_t *ep;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */
++		dentries_per_clu = p_fs->dentries_in_root;
++	else
++		dentries_per_clu = p_fs->dentries_per_clu;
++
++	clu.dir = p_dir->dir;
++	clu.size = p_dir->size;
++	clu.flags = p_dir->flags;
++
++	while (clu.dir != CLUSTER_32(~0)) {
++		if (p_fs->dev_ejected)
++			break;
++
++		for (i = 0; i < dentries_per_clu; i++) {
++			ep = get_entry_in_dir(sb, &clu, i, NULL);
++			if (!ep)
++				break;
++
++			type = p_fs->fs_func->get_entry_type(ep);
++
++			if (type == TYPE_UNUSED)
++				return TRUE;
++			if ((type != TYPE_FILE) && (type != TYPE_DIR))
++				continue;
++
++			if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */
++				return FALSE;
++
++			if (p_fs->vol_type == EXFAT)
++				return FALSE;
++			if ((p_dir->dir == p_fs->root_dir) || ((++count) > 2))
++				return FALSE;
++		}
++
++		if (p_dir->dir == CLUSTER_32(0))
++			break; /* FAT16 root_dir */
++
++		if (clu.flags == 0x03) {
++			if ((--clu.size) > 0)
++				clu.dir++;
++			else
++				clu.dir = CLUSTER_32(~0);
++		}
++		if (FAT_read(sb, clu.dir, &clu.dir) != 0)
++			break;
++	}
++
++	return TRUE;
++}
++
++/*
++ *  Name Conversion Functions
++ */
++
++/* input  : dir, uni_name
++ * output : num_of_entry, dos_name(format : aaaaaa~1.bbb)
++ */
++s32 get_num_entries_and_dos_name(struct super_block *sb, struct chain_t *p_dir,
++				 struct uni_name_t *p_uniname, s32 *entries,
++				 struct dos_name_t *p_dosname)
++{
++	s32 ret, num_entries;
++	bool lossy = false;
++	char **r;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	num_entries = p_fs->fs_func->calc_num_entries(p_uniname);
++	if (num_entries == 0)
++		return FFS_INVALIDPATH;
++
++	if (p_fs->vol_type != EXFAT) {
++		nls_uniname_to_dosname(sb, p_dosname, p_uniname, &lossy);
++
++		if (lossy) {
++			ret = fat_generate_dos_name(sb, p_dir, p_dosname);
++			if (ret)
++				return ret;
++		} else {
++			for (r = reserved_names; *r; r++) {
++				if (!strncmp((void *)p_dosname->name, *r, 8))
++					return FFS_INVALIDPATH;
++			}
++
++			if (p_dosname->name_case != 0xFF)
++				num_entries = 1;
++		}
++
++		if (num_entries > 1)
++			p_dosname->name_case = 0x0;
++	}
++
++	*entries = num_entries;
++
++	return FFS_SUCCESS;
++}
++
++void get_uni_name_from_dos_entry(struct super_block *sb,
++				 struct dos_dentry_t *ep,
++				 struct uni_name_t *p_uniname, u8 mode)
++{
++	struct dos_name_t dos_name;
++
++	if (mode == 0x0)
++		dos_name.name_case = 0x0;
++	else
++		dos_name.name_case = ep->lcase;
++
++	memcpy(dos_name.name, ep->name, DOS_NAME_LENGTH);
++	nls_dosname_to_uniname(sb, p_uniname, &dos_name);
++}
++
++void fat_get_uni_name_from_ext_entry(struct super_block *sb,
++				     struct chain_t *p_dir, s32 entry,
++				     u16 *uniname)
++{
++	int i;
++	struct ext_dentry_t *ep;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	for (entry--, i = 1; entry >= 0; entry--, i++) {
++		ep = (struct ext_dentry_t *)get_entry_in_dir(sb, p_dir, entry,
++							     NULL);
++		if (!ep)
++			return;
++
++		if (p_fs->fs_func->get_entry_type((struct dentry_t *)ep) ==
++		    TYPE_EXTEND) {
++			extract_uni_name_from_ext_entry(ep, uniname, i);
++			if (ep->order > 0x40)
++				return;
++		} else {
++			return;
++		}
++
++		uniname += 13;
++	}
++}
++
++void exfat_get_uni_name_from_ext_entry(struct super_block *sb,
++				       struct chain_t *p_dir, s32 entry,
++				       u16 *uniname)
++{
++	int i;
++	struct dentry_t *ep;
++	struct entry_set_cache_t *es;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	es = get_entry_set_in_dir(sb, p_dir, entry, ES_ALL_ENTRIES, &ep);
++	if (es == NULL || es->num_entries < 3) {
++		if (es)
++			release_entry_set(es);
++		return;
++	}
++
++	ep += 2;
++
++	/*
++	 * First entry  : file entry
++	 * Second entry : stream-extension entry
++	 * Third entry  : first file-name entry
++	 * So, the index of first file-name dentry should start from 2.
++	 */
++	for (i = 2; i < es->num_entries; i++, ep++) {
++		if (p_fs->fs_func->get_entry_type(ep) == TYPE_EXTEND)
++			extract_uni_name_from_name_entry((struct name_dentry_t *)
++							 ep, uniname, i);
++		else
++			goto out;
++		uniname += 15;
++	}
++
++out:
++	release_entry_set(es);
++}
++
++s32 extract_uni_name_from_ext_entry(struct ext_dentry_t *ep, u16 *uniname,
++				    s32 order)
++{
++	int i, len = 0;
++
++	for (i = 0; i < 10; i += 2) {
++		*uniname = GET16(ep->unicode_0_4 + i);
++		if (*uniname == 0x0)
++			return len;
++		uniname++;
++		len++;
++	}
++
++	if (order < 20) {
++		for (i = 0; i < 12; i += 2) {
++			*uniname = GET16_A(ep->unicode_5_10 + i);
++			if (*uniname == 0x0)
++				return len;
++			uniname++;
++			len++;
++		}
++	} else {
++		for (i = 0; i < 8; i += 2) {
++			*uniname = GET16_A(ep->unicode_5_10 + i);
++			if (*uniname == 0x0)
++				return len;
++			uniname++;
++			len++;
++		}
++		*uniname = 0x0; /* uniname[MAX_NAME_LENGTH-1] */
++		return len;
++	}
++
++	for (i = 0; i < 4; i += 2) {
++		*uniname = GET16_A(ep->unicode_11_12 + i);
++		if (*uniname == 0x0)
++			return len;
++		uniname++;
++		len++;
++	}
++
++	*uniname = 0x0;
++	return len;
++}
++
++s32 extract_uni_name_from_name_entry(struct name_dentry_t *ep, u16 *uniname,
++				     s32 order)
++{
++	int i, len = 0;
++
++	for (i = 0; i < 30; i += 2) {
++		*uniname = GET16_A(ep->unicode_0_14 + i);
++		if (*uniname == 0x0)
++			return len;
++		uniname++;
++		len++;
++	}
++
++	*uniname = 0x0;
++	return len;
++}
++
++s32 fat_generate_dos_name(struct super_block *sb, struct chain_t *p_dir,
++			  struct dos_name_t *p_dosname)
++{
++	int i, j, count = 0, count_begin = FALSE;
++	s32 dentries_per_clu;
++	u32 type;
++	u8 bmap[128/* 1 ~ 1023 */];
++	struct chain_t clu;
++	struct dos_dentry_t *ep;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	memset(bmap, 0, sizeof(bmap));
++	exfat_bitmap_set(bmap, 0);
++
++	if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */
++		dentries_per_clu = p_fs->dentries_in_root;
++	else
++		dentries_per_clu = p_fs->dentries_per_clu;
++
++	clu.dir = p_dir->dir;
++	clu.flags = p_dir->flags;
++
++	while (clu.dir != CLUSTER_32(~0)) {
++		if (p_fs->dev_ejected)
++			break;
++
++		for (i = 0; i < dentries_per_clu; i++) {
++			ep = (struct dos_dentry_t *)get_entry_in_dir(sb, &clu,
++								     i, NULL);
++			if (!ep)
++				return FFS_MEDIAERR;
++
++			type = p_fs->fs_func->get_entry_type((struct dentry_t *)
++							     ep);
++
++			if (type == TYPE_UNUSED)
++				break;
++			if ((type != TYPE_FILE) && (type != TYPE_DIR))
++				continue;
++
++			count = 0;
++			count_begin = FALSE;
++
++			for (j = 0; j < 8; j++) {
++				if (ep->name[j] == ' ')
++					break;
++
++				if (ep->name[j] == '~') {
++					count_begin = TRUE;
++				} else if (count_begin) {
++					if ((ep->name[j] >= '0') &&
++					    (ep->name[j] <= '9')) {
++						count = count * 10 +
++							(ep->name[j] - '0');
++					} else {
++						count = 0;
++						count_begin = FALSE;
++					}
++				}
++			}
++
++			if ((count > 0) && (count < 1024))
++				exfat_bitmap_set(bmap, count);
++		}
++
++		if (p_dir->dir == CLUSTER_32(0))
++			break; /* FAT16 root_dir */
++
++		if (FAT_read(sb, clu.dir, &clu.dir) != 0)
++			return FFS_MEDIAERR;
++	}
++
++	count = 0;
++	for (i = 0; i < 128; i++) {
++		if (bmap[i] != 0xFF) {
++			for (j = 0; j < 8; j++) {
++				if (exfat_bitmap_test(&bmap[i], j) == 0) {
++					count = (i << 3) + j;
++					break;
++				}
++			}
++			if (count != 0)
++				break;
++		}
++	}
++
++	if ((count == 0) || (count >= 1024))
++		return FFS_FILEEXIST;
++	fat_attach_count_to_dos_name(p_dosname->name, count);
++
++	/* Now dos_name has DOS~????.EXT */
++	return FFS_SUCCESS;
++}
++
++void fat_attach_count_to_dos_name(u8 *dosname, s32 count)
++{
++	int i, j, length;
++	char str_count[6];
++
++	snprintf(str_count, sizeof(str_count), "~%d", count);
++	length = strlen(str_count);
++
++	i = 0;
++	j = 0;
++	while (j <= (8 - length)) {
++		i = j;
++		if (dosname[j] == ' ')
++			break;
++		if (dosname[j] & 0x80)
++			j += 2;
++		else
++			j++;
++	}
++
++	for (j = 0; j < length; i++, j++)
++		dosname[i] = (u8)str_count[j];
++
++	if (i == 7)
++		dosname[7] = ' ';
++}
++
++s32 fat_calc_num_entries(struct uni_name_t *p_uniname)
++{
++	s32 len;
++
++	len = p_uniname->name_len;
++	if (len == 0)
++		return 0;
++
++	/* 1 dos name entry + extended entries */
++	return (len - 1) / 13 + 2;
++}
++
++s32 exfat_calc_num_entries(struct uni_name_t *p_uniname)
++{
++	s32 len;
++
++	len = p_uniname->name_len;
++	if (len == 0)
++		return 0;
++
++	/* 1 file entry + 1 stream entry + name entries */
++	return (len - 1) / 15 + 3;
++}
++
++u8 calc_checksum_1byte(void *data, s32 len, u8 chksum)
++{
++	int i;
++	u8 *c = (u8 *)data;
++
++	for (i = 0; i < len; i++, c++)
++		chksum = (((chksum & 1) << 7) | ((chksum & 0xFE) >> 1)) + *c;
++
++	return chksum;
++}
++
++u16 calc_checksum_2byte(void *data, s32 len, u16 chksum, s32 type)
++{
++	int i;
++	u8 *c = (u8 *)data;
++
++	switch (type) {
++	case CS_DIR_ENTRY:
++		for (i = 0; i < len; i++, c++) {
++			if ((i == 2) || (i == 3))
++				continue;
++			chksum = (((chksum & 1) << 15) |
++				  ((chksum & 0xFFFE) >> 1)) + (u16)*c;
++		}
++		break;
++	default
++			:
++		for (i = 0; i < len; i++, c++)
++			chksum = (((chksum & 1) << 15) |
++				  ((chksum & 0xFFFE) >> 1)) + (u16)*c;
++	}
++
++	return chksum;
++}
++
++u32 calc_checksum_4byte(void *data, s32 len, u32 chksum, s32 type)
++{
++	int i;
++	u8 *c = (u8 *)data;
++
++	switch (type) {
++	case CS_PBR_SECTOR:
++		for (i = 0; i < len; i++, c++) {
++			if ((i == 106) || (i == 107) || (i == 112))
++				continue;
++			chksum = (((chksum & 1) << 31) |
++				  ((chksum & 0xFFFFFFFE) >> 1)) + (u32)*c;
++		}
++		break;
++	default
++			:
++		for (i = 0; i < len; i++, c++)
++			chksum = (((chksum & 1) << 31) |
++				  ((chksum & 0xFFFFFFFE) >> 1)) + (u32)*c;
++	}
++
++	return chksum;
++}
++
++/*
++ *  Name Resolution Functions
++ */
++
++/* return values of resolve_path()
++ * > 0 : return the length of the path
++ * < 0 : return error
++ */
++s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir,
++		 struct uni_name_t *p_uniname)
++{
++	bool lossy = false;
++	struct super_block *sb = inode->i_sb;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct file_id_t *fid = &(EXFAT_I(inode)->fid);
++
++	if (strlen(path) >= (MAX_NAME_LENGTH * MAX_CHARSET_SIZE))
++		return FFS_INVALIDPATH;
++
++	strcpy(name_buf, path);
++
++	nls_cstring_to_uniname(sb, p_uniname, name_buf, &lossy);
++	if (lossy)
++		return FFS_INVALIDPATH;
++
++	fid->size = i_size_read(inode);
++
++	p_dir->dir = fid->start_clu;
++	p_dir->size = (s32)(fid->size >> p_fs->cluster_size_bits);
++	p_dir->flags = fid->flags;
++
++	return FFS_SUCCESS;
++}
++
++/*
++ *  File Operation Functions
++ */
++static struct fs_func fat_fs_func = {
++	.alloc_cluster = fat_alloc_cluster,
++	.free_cluster = fat_free_cluster,
++	.count_used_clusters = fat_count_used_clusters,
++
++	.init_dir_entry = fat_init_dir_entry,
++	.init_ext_entry = fat_init_ext_entry,
++	.find_dir_entry = fat_find_dir_entry,
++	.delete_dir_entry = fat_delete_dir_entry,
++	.get_uni_name_from_ext_entry = fat_get_uni_name_from_ext_entry,
++	.count_ext_entries = fat_count_ext_entries,
++	.calc_num_entries = fat_calc_num_entries,
++
++	.get_entry_type = fat_get_entry_type,
++	.set_entry_type = fat_set_entry_type,
++	.get_entry_attr = fat_get_entry_attr,
++	.set_entry_attr = fat_set_entry_attr,
++	.get_entry_flag = fat_get_entry_flag,
++	.set_entry_flag = fat_set_entry_flag,
++	.get_entry_clu0 = fat_get_entry_clu0,
++	.set_entry_clu0 = fat_set_entry_clu0,
++	.get_entry_size = fat_get_entry_size,
++	.set_entry_size = fat_set_entry_size,
++	.get_entry_time = fat_get_entry_time,
++	.set_entry_time = fat_set_entry_time,
++};
++
++s32 fat16_mount(struct super_block *sb, struct pbr_sector_t *p_pbr)
++{
++	s32 num_reserved, num_root_sectors;
++	struct bpb16_t *p_bpb = (struct bpb16_t *)p_pbr->bpb;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++
++	if (p_bpb->num_fats == 0)
++		return FFS_FORMATERR;
++
++	num_root_sectors = GET16(p_bpb->num_root_entries) << DENTRY_SIZE_BITS;
++	num_root_sectors = ((num_root_sectors - 1) >>
++			    p_bd->sector_size_bits) + 1;
++
++	p_fs->sectors_per_clu = p_bpb->sectors_per_clu;
++	p_fs->sectors_per_clu_bits = ilog2(p_bpb->sectors_per_clu);
++	p_fs->cluster_size_bits = p_fs->sectors_per_clu_bits +
++				  p_bd->sector_size_bits;
++	p_fs->cluster_size = 1 << p_fs->cluster_size_bits;
++
++	p_fs->num_FAT_sectors = GET16(p_bpb->num_fat_sectors);
++
++	p_fs->FAT1_start_sector = p_fs->PBR_sector + GET16(p_bpb->num_reserved);
++	if (p_bpb->num_fats == 1)
++		p_fs->FAT2_start_sector = p_fs->FAT1_start_sector;
++	else
++		p_fs->FAT2_start_sector = p_fs->FAT1_start_sector +
++					  p_fs->num_FAT_sectors;
++
++	p_fs->root_start_sector = p_fs->FAT2_start_sector +
++				  p_fs->num_FAT_sectors;
++	p_fs->data_start_sector = p_fs->root_start_sector + num_root_sectors;
++
++	p_fs->num_sectors = GET16(p_bpb->num_sectors);
++	if (p_fs->num_sectors == 0)
++		p_fs->num_sectors = GET32(p_bpb->num_huge_sectors);
++
++	num_reserved = p_fs->data_start_sector - p_fs->PBR_sector;
++	p_fs->num_clusters = ((p_fs->num_sectors - num_reserved) >>
++			      p_fs->sectors_per_clu_bits) + 2;
++	/* because the cluster index starts with 2 */
++
++	if (p_fs->num_clusters < FAT12_THRESHOLD)
++		p_fs->vol_type = FAT12;
++	else
++		p_fs->vol_type = FAT16;
++	p_fs->vol_id = GET32(p_bpb->vol_serial);
++
++	p_fs->root_dir = 0;
++	p_fs->dentries_in_root = GET16(p_bpb->num_root_entries);
++	p_fs->dentries_per_clu = 1 << (p_fs->cluster_size_bits -
++				       DENTRY_SIZE_BITS);
++
++	p_fs->vol_flag = VOL_CLEAN;
++	p_fs->clu_srch_ptr = 2;
++	p_fs->used_clusters = (u32)~0;
++
++	p_fs->fs_func = &fat_fs_func;
++
++	return FFS_SUCCESS;
++}
++
++s32 fat32_mount(struct super_block *sb, struct pbr_sector_t *p_pbr)
++{
++	s32 num_reserved;
++	struct bpb32_t *p_bpb = (struct bpb32_t *)p_pbr->bpb;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++
++	if (p_bpb->num_fats == 0)
++		return FFS_FORMATERR;
++
++	p_fs->sectors_per_clu = p_bpb->sectors_per_clu;
++	p_fs->sectors_per_clu_bits = ilog2(p_bpb->sectors_per_clu);
++	p_fs->cluster_size_bits = p_fs->sectors_per_clu_bits +
++				  p_bd->sector_size_bits;
++	p_fs->cluster_size = 1 << p_fs->cluster_size_bits;
++
++	p_fs->num_FAT_sectors = GET32(p_bpb->num_fat32_sectors);
++
++	p_fs->FAT1_start_sector = p_fs->PBR_sector + GET16(p_bpb->num_reserved);
++	if (p_bpb->num_fats == 1)
++		p_fs->FAT2_start_sector = p_fs->FAT1_start_sector;
++	else
++		p_fs->FAT2_start_sector = p_fs->FAT1_start_sector +
++					  p_fs->num_FAT_sectors;
++
++	p_fs->root_start_sector = p_fs->FAT2_start_sector +
++				  p_fs->num_FAT_sectors;
++	p_fs->data_start_sector = p_fs->root_start_sector;
++
++	p_fs->num_sectors = GET32(p_bpb->num_huge_sectors);
++	num_reserved = p_fs->data_start_sector - p_fs->PBR_sector;
++
++	p_fs->num_clusters = ((p_fs->num_sectors - num_reserved) >>
++			      p_fs->sectors_per_clu_bits) + 2;
++	/* because the cluster index starts with 2 */
++
++	p_fs->vol_type = FAT32;
++	p_fs->vol_id = GET32(p_bpb->vol_serial);
++
++	p_fs->root_dir = GET32(p_bpb->root_cluster);
++	p_fs->dentries_in_root = 0;
++	p_fs->dentries_per_clu = 1 << (p_fs->cluster_size_bits -
++				       DENTRY_SIZE_BITS);
++
++	p_fs->vol_flag = VOL_CLEAN;
++	p_fs->clu_srch_ptr = 2;
++	p_fs->used_clusters = (u32)~0;
++
++	p_fs->fs_func = &fat_fs_func;
++
++	return FFS_SUCCESS;
++}
++
++static struct fs_func exfat_fs_func = {
++	.alloc_cluster = exfat_alloc_cluster,
++	.free_cluster = exfat_free_cluster,
++	.count_used_clusters = exfat_count_used_clusters,
++
++	.init_dir_entry = exfat_init_dir_entry,
++	.init_ext_entry = exfat_init_ext_entry,
++	.find_dir_entry = exfat_find_dir_entry,
++	.delete_dir_entry = exfat_delete_dir_entry,
++	.get_uni_name_from_ext_entry = exfat_get_uni_name_from_ext_entry,
++	.count_ext_entries = exfat_count_ext_entries,
++	.calc_num_entries = exfat_calc_num_entries,
++
++	.get_entry_type = exfat_get_entry_type,
++	.set_entry_type = exfat_set_entry_type,
++	.get_entry_attr = exfat_get_entry_attr,
++	.set_entry_attr = exfat_set_entry_attr,
++	.get_entry_flag = exfat_get_entry_flag,
++	.set_entry_flag = exfat_set_entry_flag,
++	.get_entry_clu0 = exfat_get_entry_clu0,
++	.set_entry_clu0 = exfat_set_entry_clu0,
++	.get_entry_size = exfat_get_entry_size,
++	.set_entry_size = exfat_set_entry_size,
++	.get_entry_time = exfat_get_entry_time,
++	.set_entry_time = exfat_set_entry_time,
++};
++
++s32 exfat_mount(struct super_block *sb, struct pbr_sector_t *p_pbr)
++{
++	struct bpbex_t *p_bpb = (struct bpbex_t *)p_pbr->bpb;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++
++	if (p_bpb->num_fats == 0)
++		return FFS_FORMATERR;
++
++	p_fs->sectors_per_clu = 1 << p_bpb->sectors_per_clu_bits;
++	p_fs->sectors_per_clu_bits = p_bpb->sectors_per_clu_bits;
++	p_fs->cluster_size_bits = p_fs->sectors_per_clu_bits +
++				  p_bd->sector_size_bits;
++	p_fs->cluster_size = 1 << p_fs->cluster_size_bits;
++
++	p_fs->num_FAT_sectors = GET32(p_bpb->fat_length);
++
++	p_fs->FAT1_start_sector = p_fs->PBR_sector + GET32(p_bpb->fat_offset);
++	if (p_bpb->num_fats == 1)
++		p_fs->FAT2_start_sector = p_fs->FAT1_start_sector;
++	else
++		p_fs->FAT2_start_sector = p_fs->FAT1_start_sector +
++					  p_fs->num_FAT_sectors;
++
++	p_fs->root_start_sector = p_fs->PBR_sector + GET32(p_bpb->clu_offset);
++	p_fs->data_start_sector = p_fs->root_start_sector;
++
++	p_fs->num_sectors = GET64(p_bpb->vol_length);
++	p_fs->num_clusters = GET32(p_bpb->clu_count) + 2;
++	/* because the cluster index starts with 2 */
++
++	p_fs->vol_type = EXFAT;
++	p_fs->vol_id = GET32(p_bpb->vol_serial);
++
++	p_fs->root_dir = GET32(p_bpb->root_cluster);
++	p_fs->dentries_in_root = 0;
++	p_fs->dentries_per_clu = 1 << (p_fs->cluster_size_bits -
++				       DENTRY_SIZE_BITS);
++
++	p_fs->vol_flag = (u32)GET16(p_bpb->vol_flags);
++	p_fs->clu_srch_ptr = 2;
++	p_fs->used_clusters = (u32)~0;
++
++	p_fs->fs_func = &exfat_fs_func;
++
++	return FFS_SUCCESS;
++}
++
++s32 create_dir(struct inode *inode, struct chain_t *p_dir,
++	       struct uni_name_t *p_uniname, struct file_id_t *fid)
++{
++	s32 ret, dentry, num_entries;
++	u64 size;
++	struct chain_t clu;
++	struct dos_name_t dos_name, dot_name;
++	struct super_block *sb = inode->i_sb;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct fs_func *fs_func = p_fs->fs_func;
++
++	ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname, &num_entries,
++					   &dos_name);
++	if (ret)
++		return ret;
++
++	/* find_empty_entry must be called before alloc_cluster */
++	dentry = find_empty_entry(inode, p_dir, num_entries);
++	if (dentry < 0)
++		return FFS_FULL;
++
++	clu.dir = CLUSTER_32(~0);
++	clu.size = 0;
++	clu.flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01;
++
++	/* (1) allocate a cluster */
++	ret = fs_func->alloc_cluster(sb, 1, &clu);
++	if (ret < 0)
++		return FFS_MEDIAERR;
++	else if (ret == 0)
++		return FFS_FULL;
++
++	ret = clear_cluster(sb, clu.dir);
++	if (ret != FFS_SUCCESS)
++		return ret;
++
++	if (p_fs->vol_type == EXFAT) {
++		size = p_fs->cluster_size;
++	} else {
++		size = 0;
++
++		/* initialize the . and .. entry
++		 * Information for . points to itself
++		 * Information for .. points to parent dir
++		 */
++
++		dot_name.name_case = 0x0;
++		memcpy(dot_name.name, DOS_CUR_DIR_NAME, DOS_NAME_LENGTH);
++
++		ret = fs_func->init_dir_entry(sb, &clu, 0, TYPE_DIR, clu.dir,
++					      0);
++		if (ret != FFS_SUCCESS)
++			return ret;
++
++		ret = fs_func->init_ext_entry(sb, &clu, 0, 1, NULL, &dot_name);
++		if (ret != FFS_SUCCESS)
++			return ret;
++
++		memcpy(dot_name.name, DOS_PAR_DIR_NAME, DOS_NAME_LENGTH);
++
++		if (p_dir->dir == p_fs->root_dir)
++			ret = fs_func->init_dir_entry(sb, &clu, 1, TYPE_DIR,
++						      CLUSTER_32(0), 0);
++		else
++			ret = fs_func->init_dir_entry(sb, &clu, 1, TYPE_DIR,
++						      p_dir->dir, 0);
++
++		if (ret != FFS_SUCCESS)
++			return ret;
++
++		ret = p_fs->fs_func->init_ext_entry(sb, &clu, 1, 1, NULL,
++						    &dot_name);
++		if (ret != FFS_SUCCESS)
++			return ret;
++	}
++
++	/* (2) update the directory entry */
++	/* make sub-dir entry in parent directory */
++	ret = fs_func->init_dir_entry(sb, p_dir, dentry, TYPE_DIR, clu.dir,
++				      size);
++	if (ret != FFS_SUCCESS)
++		return ret;
++
++	ret = fs_func->init_ext_entry(sb, p_dir, dentry, num_entries, p_uniname,
++				      &dos_name);
++	if (ret != FFS_SUCCESS)
++		return ret;
++
++	fid->dir.dir = p_dir->dir;
++	fid->dir.size = p_dir->size;
++	fid->dir.flags = p_dir->flags;
++	fid->entry = dentry;
++
++	fid->attr = ATTR_SUBDIR;
++	fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01;
++	fid->size = size;
++	fid->start_clu = clu.dir;
++
++	fid->type = TYPE_DIR;
++	fid->rwoffset = 0;
++	fid->hint_last_off = -1;
++
++	return FFS_SUCCESS;
++}
++
++s32 create_file(struct inode *inode, struct chain_t *p_dir,
++		struct uni_name_t *p_uniname, u8 mode, struct file_id_t *fid)
++{
++	s32 ret, dentry, num_entries;
++	struct dos_name_t dos_name;
++	struct super_block *sb = inode->i_sb;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct fs_func *fs_func = p_fs->fs_func;
++
++	ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname, &num_entries,
++					   &dos_name);
++	if (ret)
++		return ret;
++
++	/* find_empty_entry must be called before alloc_cluster() */
++	dentry = find_empty_entry(inode, p_dir, num_entries);
++	if (dentry < 0)
++		return FFS_FULL;
++
++	/* (1) update the directory entry */
++	/* fill the dos name directory entry information of the created file.
++	 * the first cluster is not determined yet. (0)
++	 */
++	ret = fs_func->init_dir_entry(sb, p_dir, dentry, TYPE_FILE | mode,
++				      CLUSTER_32(0), 0);
++	if (ret != FFS_SUCCESS)
++		return ret;
++
++	ret = fs_func->init_ext_entry(sb, p_dir, dentry, num_entries, p_uniname,
++				      &dos_name);
++	if (ret != FFS_SUCCESS)
++		return ret;
++
++	fid->dir.dir = p_dir->dir;
++	fid->dir.size = p_dir->size;
++	fid->dir.flags = p_dir->flags;
++	fid->entry = dentry;
++
++	fid->attr = ATTR_ARCHIVE | mode;
++	fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01;
++	fid->size = 0;
++	fid->start_clu = CLUSTER_32(~0);
++
++	fid->type = TYPE_FILE;
++	fid->rwoffset = 0;
++	fid->hint_last_off = -1;
++
++	return FFS_SUCCESS;
++}
++
++void remove_file(struct inode *inode, struct chain_t *p_dir, s32 entry)
++{
++	s32 num_entries;
++	sector_t sector;
++	struct dentry_t *ep;
++	struct super_block *sb = inode->i_sb;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct fs_func *fs_func = p_fs->fs_func;
++
++	ep = get_entry_in_dir(sb, p_dir, entry, §or);
++	if (!ep)
++		return;
++
++	buf_lock(sb, sector);
++
++	/* buf_lock() before call count_ext_entries() */
++	num_entries = fs_func->count_ext_entries(sb, p_dir, entry, ep);
++	if (num_entries < 0) {
++		buf_unlock(sb, sector);
++		return;
++	}
++	num_entries++;
++
++	buf_unlock(sb, sector);
++
++	/* (1) update the directory entry */
++	fs_func->delete_dir_entry(sb, p_dir, entry, 0, num_entries);
++}
++
++s32 rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry,
++		struct uni_name_t *p_uniname, struct file_id_t *fid)
++{
++	s32 ret, newentry = -1, num_old_entries, num_new_entries;
++	sector_t sector_old, sector_new;
++	struct dos_name_t dos_name;
++	struct dentry_t *epold, *epnew;
++	struct super_block *sb = inode->i_sb;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct fs_func *fs_func = p_fs->fs_func;
++
++	epold = get_entry_in_dir(sb, p_dir, oldentry, §or_old);
++	if (!epold)
++		return FFS_MEDIAERR;
++
++	buf_lock(sb, sector_old);
++
++	/* buf_lock() before call count_ext_entries() */
++	num_old_entries = fs_func->count_ext_entries(sb, p_dir, oldentry,
++						     epold);
++	if (num_old_entries < 0) {
++		buf_unlock(sb, sector_old);
++		return FFS_MEDIAERR;
++	}
++	num_old_entries++;
++
++	ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname,
++					   &num_new_entries, &dos_name);
++	if (ret) {
++		buf_unlock(sb, sector_old);
++		return ret;
++	}
++
++	if (num_old_entries < num_new_entries) {
++		newentry = find_empty_entry(inode, p_dir, num_new_entries);
++		if (newentry < 0) {
++			buf_unlock(sb, sector_old);
++			return FFS_FULL;
++		}
++
++		epnew = get_entry_in_dir(sb, p_dir, newentry, §or_new);
++		if (!epnew) {
++			buf_unlock(sb, sector_old);
++			return FFS_MEDIAERR;
++		}
++
++		memcpy((void *)epnew, (void *)epold, DENTRY_SIZE);
++		if (fs_func->get_entry_type(epnew) == TYPE_FILE) {
++			fs_func->set_entry_attr(epnew,
++						fs_func->get_entry_attr(epnew) |
++						ATTR_ARCHIVE);
++			fid->attr |= ATTR_ARCHIVE;
++		}
++		buf_modify(sb, sector_new);
++		buf_unlock(sb, sector_old);
++
++		if (p_fs->vol_type == EXFAT) {
++			epold = get_entry_in_dir(sb, p_dir, oldentry + 1,
++						 §or_old);
++			buf_lock(sb, sector_old);
++			epnew = get_entry_in_dir(sb, p_dir, newentry + 1,
++						 §or_new);
++
++			if (!epold || !epnew) {
++				buf_unlock(sb, sector_old);
++				return FFS_MEDIAERR;
++			}
++
++			memcpy((void *)epnew, (void *)epold, DENTRY_SIZE);
++			buf_modify(sb, sector_new);
++			buf_unlock(sb, sector_old);
++		}
++
++		ret = fs_func->init_ext_entry(sb, p_dir, newentry,
++					      num_new_entries, p_uniname,
++					      &dos_name);
++		if (ret != FFS_SUCCESS)
++			return ret;
++
++		fs_func->delete_dir_entry(sb, p_dir, oldentry, 0,
++					  num_old_entries);
++		fid->entry = newentry;
++	} else {
++		if (fs_func->get_entry_type(epold) == TYPE_FILE) {
++			fs_func->set_entry_attr(epold,
++						fs_func->get_entry_attr(epold) |
++						ATTR_ARCHIVE);
++			fid->attr |= ATTR_ARCHIVE;
++		}
++		buf_modify(sb, sector_old);
++		buf_unlock(sb, sector_old);
++
++		ret = fs_func->init_ext_entry(sb, p_dir, oldentry,
++					      num_new_entries, p_uniname,
++					      &dos_name);
++		if (ret != FFS_SUCCESS)
++			return ret;
++
++		fs_func->delete_dir_entry(sb, p_dir, oldentry, num_new_entries,
++					  num_old_entries);
++	}
++
++	return FFS_SUCCESS;
++}
++
++s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
++	      struct chain_t *p_newdir, struct uni_name_t *p_uniname,
++	      struct file_id_t *fid)
++{
++	s32 ret, newentry, num_new_entries, num_old_entries;
++	sector_t sector_mov, sector_new;
++	struct chain_t clu;
++	struct dos_name_t dos_name;
++	struct dentry_t *epmov, *epnew;
++	struct super_block *sb = inode->i_sb;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct fs_func *fs_func = p_fs->fs_func;
++
++	epmov = get_entry_in_dir(sb, p_olddir, oldentry, §or_mov);
++	if (!epmov)
++		return FFS_MEDIAERR;
++
++	/* check if the source and target directory is the same */
++	if (fs_func->get_entry_type(epmov) == TYPE_DIR &&
++	    fs_func->get_entry_clu0(epmov) == p_newdir->dir)
++		return FFS_INVALIDPATH;
++
++	buf_lock(sb, sector_mov);
++
++	/* buf_lock() before call count_ext_entries() */
++	num_old_entries = fs_func->count_ext_entries(sb, p_olddir, oldentry,
++						     epmov);
++	if (num_old_entries < 0) {
++		buf_unlock(sb, sector_mov);
++		return FFS_MEDIAERR;
++	}
++	num_old_entries++;
++
++	ret = get_num_entries_and_dos_name(sb, p_newdir, p_uniname,
++					   &num_new_entries, &dos_name);
++	if (ret) {
++		buf_unlock(sb, sector_mov);
++		return ret;
++	}
++
++	newentry = find_empty_entry(inode, p_newdir, num_new_entries);
++	if (newentry < 0) {
++		buf_unlock(sb, sector_mov);
++		return FFS_FULL;
++	}
++
++	epnew = get_entry_in_dir(sb, p_newdir, newentry, §or_new);
++	if (!epnew) {
++		buf_unlock(sb, sector_mov);
++		return FFS_MEDIAERR;
++	}
++
++	memcpy((void *)epnew, (void *)epmov, DENTRY_SIZE);
++	if (fs_func->get_entry_type(epnew) == TYPE_FILE) {
++		fs_func->set_entry_attr(epnew, fs_func->get_entry_attr(epnew) |
++					ATTR_ARCHIVE);
++		fid->attr |= ATTR_ARCHIVE;
++	}
++	buf_modify(sb, sector_new);
++	buf_unlock(sb, sector_mov);
++
++	if (p_fs->vol_type == EXFAT) {
++		epmov = get_entry_in_dir(sb, p_olddir, oldentry + 1,
++					 §or_mov);
++		buf_lock(sb, sector_mov);
++		epnew = get_entry_in_dir(sb, p_newdir, newentry + 1,
++					 §or_new);
++		if (!epmov || !epnew) {
++			buf_unlock(sb, sector_mov);
++			return FFS_MEDIAERR;
++		}
++
++		memcpy((void *)epnew, (void *)epmov, DENTRY_SIZE);
++		buf_modify(sb, sector_new);
++		buf_unlock(sb, sector_mov);
++	} else if (fs_func->get_entry_type(epnew) == TYPE_DIR) {
++		/* change ".." pointer to new parent dir */
++		clu.dir = fs_func->get_entry_clu0(epnew);
++		clu.flags = 0x01;
++
++		epnew = get_entry_in_dir(sb, &clu, 1, §or_new);
++		if (!epnew)
++			return FFS_MEDIAERR;
++
++		if (p_newdir->dir == p_fs->root_dir)
++			fs_func->set_entry_clu0(epnew, CLUSTER_32(0));
++		else
++			fs_func->set_entry_clu0(epnew, p_newdir->dir);
++		buf_modify(sb, sector_new);
++	}
++
++	ret = fs_func->init_ext_entry(sb, p_newdir, newentry, num_new_entries,
++				      p_uniname, &dos_name);
++	if (ret != FFS_SUCCESS)
++		return ret;
++
++	fs_func->delete_dir_entry(sb, p_olddir, oldentry, 0, num_old_entries);
++
++	fid->dir.dir = p_newdir->dir;
++	fid->dir.size = p_newdir->size;
++	fid->dir.flags = p_newdir->flags;
++
++	fid->entry = newentry;
++
++	return FFS_SUCCESS;
++}
++
++/*
++ *  Sector Read/Write Functions
++ */
++
++int sector_read(struct super_block *sb, sector_t sec, struct buffer_head **bh,
++		bool read)
++{
++	s32 ret = FFS_MEDIAERR;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	if ((sec >= (p_fs->PBR_sector + p_fs->num_sectors)) &&
++	    (p_fs->num_sectors > 0)) {
++		pr_err("[EXFAT] %s: out of range error! (sec = %llu)\n",
++		       __func__, (unsigned long long)sec);
++		fs_error(sb);
++		return ret;
++	}
++
++	if (!p_fs->dev_ejected) {
++		ret = bdev_read(sb, sec, bh, 1, read);
++		if (ret != FFS_SUCCESS)
++			p_fs->dev_ejected = TRUE;
++	}
++
++	return ret;
++}
++
++int sector_write(struct super_block *sb, sector_t sec, struct buffer_head *bh,
++		 bool sync)
++{
++	s32 ret = FFS_MEDIAERR;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	if (sec >= (p_fs->PBR_sector + p_fs->num_sectors) &&
++	    (p_fs->num_sectors > 0)) {
++		pr_err("[EXFAT] %s: out of range error! (sec = %llu)\n",
++		       __func__, (unsigned long long)sec);
++		fs_error(sb);
++		return ret;
++	}
++
++	if (!bh) {
++		pr_err("[EXFAT] %s: bh is NULL!\n", __func__);
++		fs_error(sb);
++		return ret;
++	}
++
++	if (!p_fs->dev_ejected) {
++		ret = bdev_write(sb, sec, bh, 1, sync);
++		if (ret != FFS_SUCCESS)
++			p_fs->dev_ejected = TRUE;
++	}
++
++	return ret;
++}
++
++int multi_sector_read(struct super_block *sb, sector_t sec,
++		      struct buffer_head **bh, s32 num_secs, bool read)
++{
++	s32 ret = FFS_MEDIAERR;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	if (((sec + num_secs) > (p_fs->PBR_sector + p_fs->num_sectors)) &&
++	    (p_fs->num_sectors > 0)) {
++		pr_err("[EXFAT] %s: out of range error! (sec = %llu, num_secs = %d)\n",
++		       __func__, (unsigned long long)sec, num_secs);
++		fs_error(sb);
++		return ret;
++	}
++
++	if (!p_fs->dev_ejected) {
++		ret = bdev_read(sb, sec, bh, num_secs, read);
++		if (ret != FFS_SUCCESS)
++			p_fs->dev_ejected = TRUE;
++	}
++
++	return ret;
++}
++
++int multi_sector_write(struct super_block *sb, sector_t sec,
++		       struct buffer_head *bh, s32 num_secs, bool sync)
++{
++	s32 ret = FFS_MEDIAERR;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	if ((sec + num_secs) > (p_fs->PBR_sector + p_fs->num_sectors) &&
++	    (p_fs->num_sectors > 0)) {
++		pr_err("[EXFAT] %s: out of range error! (sec = %llu, num_secs = %d)\n",
++		       __func__, (unsigned long long)sec, num_secs);
++		fs_error(sb);
++		return ret;
++	}
++	if (!bh) {
++		pr_err("[EXFAT] %s: bh is NULL!\n", __func__);
++		fs_error(sb);
++		return ret;
++	}
++
++	if (!p_fs->dev_ejected) {
++		ret = bdev_write(sb, sec, bh, num_secs, sync);
++		if (ret != FFS_SUCCESS)
++			p_fs->dev_ejected = TRUE;
++	}
++
++	return ret;
++}
+diff --git a/drivers/staging/exfat/exfat_nls.c b/drivers/staging/exfat/exfat_nls.c
+new file mode 100644
+index 000000000000..2ca58616159b
+--- /dev/null
++++ b/drivers/staging/exfat/exfat_nls.c
+@@ -0,0 +1,404 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ *  Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
++ */
++
++#include 
++#include 
++#include "exfat.h"
++
++static u16 bad_dos_chars[] = {
++	/* + , ; = [ ] */
++	0x002B, 0x002C, 0x003B, 0x003D, 0x005B, 0x005D,
++	0xFF0B, 0xFF0C, 0xFF1B, 0xFF1D, 0xFF3B, 0xFF3D,
++	0
++};
++
++static u16 bad_uni_chars[] = {
++	/* " * / : < > ? \ | */
++	0x0022,         0x002A, 0x002F, 0x003A,
++	0x003C, 0x003E, 0x003F, 0x005C, 0x007C,
++	0
++};
++
++static int convert_ch_to_uni(struct nls_table *nls, u16 *uni, u8 *ch,
++			     bool *lossy)
++{
++	int len;
++
++	*uni = 0x0;
++
++	if (ch[0] < 0x80) {
++		*uni = (u16)ch[0];
++		return 1;
++	}
++
++	len = nls->char2uni(ch, NLS_MAX_CHARSET_SIZE, uni);
++	if (len < 0) {
++		/* conversion failed */
++		pr_info("%s: fail to use nls\n", __func__);
++		if (lossy)
++			*lossy = true;
++		*uni = (u16)'_';
++		if (!strcmp(nls->charset, "utf8"))
++			return 1;
++		else
++			return 2;
++	}
++
++	return len;
++}
++
++static int convert_uni_to_ch(struct nls_table *nls, u8 *ch, u16 uni,
++			     bool *lossy)
++{
++	int len;
++
++	ch[0] = 0x0;
++
++	if (uni < 0x0080) {
++		ch[0] = (u8)uni;
++		return 1;
++	}
++
++	len = nls->uni2char(uni, ch, NLS_MAX_CHARSET_SIZE);
++	if (len < 0) {
++		/* conversion failed */
++		pr_info("%s: fail to use nls\n", __func__);
++		if (lossy)
++			*lossy = true;
++		ch[0] = '_';
++		return 1;
++	}
++
++	return len;
++}
++
++u16 nls_upper(struct super_block *sb, u16 a)
++{
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	if (EXFAT_SB(sb)->options.casesensitive)
++		return a;
++	if (p_fs->vol_utbl && p_fs->vol_utbl[get_col_index(a)])
++		return p_fs->vol_utbl[get_col_index(a)][get_row_index(a)];
++	else
++		return a;
++}
++
++static u16 *nls_wstrchr(u16 *str, u16 wchar)
++{
++	while (*str) {
++		if (*(str++) == wchar)
++			return str;
++	}
++
++	return NULL;
++}
++
++int nls_dosname_cmp(struct super_block *sb, u8 *a, u8 *b)
++{
++	return strncmp(a, b, DOS_NAME_LENGTH);
++}
++
++int nls_uniname_cmp(struct super_block *sb, u16 *a, u16 *b)
++{
++	int i;
++
++	for (i = 0; i < MAX_NAME_LENGTH; i++, a++, b++) {
++		if (nls_upper(sb, *a) != nls_upper(sb, *b))
++			return 1;
++		if (*a == 0x0)
++			return 0;
++	}
++	return 0;
++}
++
++void nls_uniname_to_dosname(struct super_block *sb,
++			    struct dos_name_t *p_dosname,
++			    struct uni_name_t *p_uniname, bool *p_lossy)
++{
++	int i, j, len;
++	bool lossy = false;
++	u8 buf[MAX_CHARSET_SIZE];
++	u8 lower = 0, upper = 0;
++	u8 *dosname = p_dosname->name;
++	u16 *uniname = p_uniname->name;
++	u16 *p, *last_period;
++	struct nls_table *nls = EXFAT_SB(sb)->nls_disk;
++
++	for (i = 0; i < DOS_NAME_LENGTH; i++)
++		*(dosname + i) = ' ';
++
++	if (!nls_uniname_cmp(sb, uniname, (u16 *)UNI_CUR_DIR_NAME)) {
++		*(dosname) = '.';
++		p_dosname->name_case = 0x0;
++		if (p_lossy)
++			*p_lossy = false;
++		return;
++	}
++
++	if (!nls_uniname_cmp(sb, uniname, (u16 *)UNI_PAR_DIR_NAME)) {
++		*(dosname) = '.';
++		*(dosname + 1) = '.';
++		p_dosname->name_case = 0x0;
++		if (p_lossy)
++			*p_lossy = false;
++		return;
++	}
++
++	/* search for the last embedded period */
++	last_period = NULL;
++	for (p = uniname; *p; p++) {
++		if (*p == (u16)'.')
++			last_period = p;
++	}
++
++	i = 0;
++	while (i < DOS_NAME_LENGTH) {
++		if (i == 8) {
++			if (!last_period)
++				break;
++
++			if (uniname <= last_period) {
++				if (uniname < last_period)
++					lossy = true;
++				uniname = last_period + 1;
++			}
++		}
++
++		if (*uniname == (u16)'\0') {
++			break;
++		} else if (*uniname == (u16)' ') {
++			lossy = true;
++		} else if (*uniname == (u16)'.') {
++			if (uniname < last_period)
++				lossy = true;
++			else
++				i = 8;
++		} else if (nls_wstrchr(bad_dos_chars, *uniname)) {
++			lossy = true;
++			*(dosname + i) = '_';
++			i++;
++		} else {
++			len = convert_uni_to_ch(nls, buf, *uniname, &lossy);
++
++			if (len > 1) {
++				if ((i >= 8) && ((i + len) > DOS_NAME_LENGTH))
++					break;
++
++				if ((i < 8) && ((i + len) > 8)) {
++					i = 8;
++					continue;
++				}
++
++				lower = 0xFF;
++
++				for (j = 0; j < len; j++, i++)
++					*(dosname + i) = *(buf + j);
++			} else { /* len == 1 */
++				if ((*buf >= 'a') && (*buf <= 'z')) {
++					*(dosname + i) = *buf - ('a' - 'A');
++
++					if (i < 8)
++						lower |= 0x08;
++					else
++						lower |= 0x10;
++				} else if ((*buf >= 'A') && (*buf <= 'Z')) {
++					*(dosname + i) = *buf;
++
++					if (i < 8)
++						upper |= 0x08;
++					else
++						upper |= 0x10;
++				} else {
++					*(dosname + i) = *buf;
++				}
++				i++;
++			}
++		}
++
++		uniname++;
++	}
++
++	if (*dosname == 0xE5)
++		*dosname = 0x05;
++
++	if (*uniname != 0x0)
++		lossy = TRUE;
++
++	if (upper & lower)
++		p_dosname->name_case = 0xFF;
++	else
++		p_dosname->name_case = lower;
++
++	if (p_lossy)
++		*p_lossy = lossy;
++}
++
++void nls_dosname_to_uniname(struct super_block *sb,
++			    struct uni_name_t *p_uniname,
++			    struct dos_name_t *p_dosname)
++{
++	int i = 0, j, n = 0;
++	u8 buf[DOS_NAME_LENGTH + 2];
++	u8 *dosname = p_dosname->name;
++	u16 *uniname = p_uniname->name;
++	struct nls_table *nls = EXFAT_SB(sb)->nls_disk;
++
++	if (*dosname == 0x05) {
++		*buf = 0xE5;
++		i++;
++		n++;
++	}
++
++	for (; i < 8; i++, n++) {
++		if (*(dosname + i) == ' ')
++			break;
++
++		if ((*(dosname + i) >= 'A') && (*(dosname + i) <= 'Z') &&
++		    (p_dosname->name_case & 0x08))
++			*(buf + n) = *(dosname + i) + ('a' - 'A');
++		else
++			*(buf + n) = *(dosname + i);
++	}
++	if (*(dosname + 8) != ' ') {
++		*(buf + n) = '.';
++		n++;
++	}
++
++	for (i = 8; i < DOS_NAME_LENGTH; i++, n++) {
++		if (*(dosname + i) == ' ')
++			break;
++
++		if ((*(dosname + i) >= 'A') && (*(dosname + i) <= 'Z') &&
++		    (p_dosname->name_case & 0x10))
++			*(buf + n) = *(dosname + i) + ('a' - 'A');
++		else
++			*(buf + n) = *(dosname + i);
++	}
++	*(buf + n) = '\0';
++
++	i = 0;
++	j = 0;
++	while (j < (MAX_NAME_LENGTH - 1)) {
++		if (*(buf + i) == '\0')
++			break;
++
++		i += convert_ch_to_uni(nls, uniname, (buf + i), NULL);
++
++		uniname++;
++		j++;
++	}
++
++	*uniname = (u16)'\0';
++}
++
++void nls_uniname_to_cstring(struct super_block *sb, u8 *p_cstring,
++			    struct uni_name_t *p_uniname)
++{
++	int i, j, len;
++	u8 buf[MAX_CHARSET_SIZE];
++	u16 *uniname = p_uniname->name;
++	struct nls_table *nls = EXFAT_SB(sb)->nls_io;
++
++	if (!nls) {
++		len = utf16s_to_utf8s(uniname, MAX_NAME_LENGTH,
++				      UTF16_HOST_ENDIAN, p_cstring,
++				      MAX_NAME_LENGTH);
++		p_cstring[len] = 0;
++		return;
++	}
++
++	i = 0;
++	while (i < (MAX_NAME_LENGTH - 1)) {
++		if (*uniname == (u16)'\0')
++			break;
++
++		len = convert_uni_to_ch(nls, buf, *uniname, NULL);
++
++		if (len > 1) {
++			for (j = 0; j < len; j++)
++				*p_cstring++ = (char)*(buf + j);
++		} else { /* len == 1 */
++			*p_cstring++ = (char)*buf;
++		}
++
++		uniname++;
++		i++;
++	}
++
++	*p_cstring = '\0';
++}
++
++void nls_cstring_to_uniname(struct super_block *sb,
++			    struct uni_name_t *p_uniname, u8 *p_cstring,
++			    bool *p_lossy)
++{
++	int i, j;
++	bool lossy = false;
++	u8 *end_of_name;
++	u8 upname[MAX_NAME_LENGTH * 2];
++	u16 *uniname = p_uniname->name;
++	struct nls_table *nls = EXFAT_SB(sb)->nls_io;
++
++	/* strip all trailing spaces */
++	end_of_name = p_cstring + strlen(p_cstring);
++
++	while (*(--end_of_name) == ' ') {
++		if (end_of_name < p_cstring)
++			break;
++	}
++	*(++end_of_name) = '\0';
++
++	if (strcmp(p_cstring, ".") && strcmp(p_cstring, "..")) {
++		/* strip all trailing periods */
++		while (*(--end_of_name) == '.') {
++			if (end_of_name < p_cstring)
++				break;
++		}
++		*(++end_of_name) = '\0';
++	}
++
++	if (*p_cstring == '\0')
++		lossy = true;
++
++	if (!nls) {
++		i = utf8s_to_utf16s(p_cstring, MAX_NAME_LENGTH,
++				    UTF16_HOST_ENDIAN, uniname,
++				    MAX_NAME_LENGTH);
++		for (j = 0; j < i; j++)
++			SET16_A(upname + j * 2, nls_upper(sb, uniname[j]));
++		uniname[i] = '\0';
++	} else {
++		i = 0;
++		j = 0;
++		while (j < (MAX_NAME_LENGTH - 1)) {
++			if (*(p_cstring + i) == '\0')
++				break;
++
++			i += convert_ch_to_uni(nls, uniname,
++					       (u8 *)(p_cstring + i), &lossy);
++
++			if ((*uniname < 0x0020) ||
++			    nls_wstrchr(bad_uni_chars, *uniname))
++				lossy = true;
++
++			SET16_A(upname + j * 2, nls_upper(sb, *uniname));
++
++			uniname++;
++			j++;
++		}
++
++		if (*(p_cstring + i) != '\0')
++			lossy = true;
++		*uniname = (u16)'\0';
++	}
++
++	p_uniname->name_len = j;
++	p_uniname->name_hash = calc_checksum_2byte(upname, j << 1, 0,
++						   CS_DEFAULT);
++
++	if (p_lossy)
++		*p_lossy = lossy;
++}
+diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
+new file mode 100644
+index 000000000000..5b5c2ca8c9aa
+--- /dev/null
++++ b/drivers/staging/exfat/exfat_super.c
+@@ -0,0 +1,4137 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ *  Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
++ */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++
++#include 
++#include 
++#include 
++#include 
++
++#define EXFAT_VERSION  "1.3.0"
++
++#include "exfat.h"
++
++static struct kmem_cache *exfat_inode_cachep;
++
++// FIXME use commented lines
++// static int exfat_default_codepage = CONFIG_EXFAT_DEFAULT_CODEPAGE;
++// static char exfat_default_iocharset[] = CONFIG_EXFAT_DEFAULT_IOCHARSET;
++static int exfat_default_codepage = CONFIG_FAT_DEFAULT_CODEPAGE;
++static char exfat_default_iocharset[] = CONFIG_FAT_DEFAULT_IOCHARSET;
++
++#define INC_IVERSION(x) (inode_inc_iversion(x))
++#define GET_IVERSION(x) (inode_peek_iversion_raw(x))
++#define SET_IVERSION(x, y) (inode_set_iversion(x, y))
++
++static struct inode *exfat_iget(struct super_block *sb, loff_t i_pos);
++static int exfat_sync_inode(struct inode *inode);
++static struct inode *exfat_build_inode(struct super_block *sb,
++				       struct file_id_t *fid, loff_t i_pos);
++static int exfat_write_inode(struct inode *inode,
++			     struct writeback_control *wbc);
++static void exfat_write_super(struct super_block *sb);
++
++#define UNIX_SECS_1980    315532800L
++
++#if BITS_PER_LONG == 64
++#define UNIX_SECS_2108    4354819200L
++#endif
++
++/* days between 1.1.70 and 1.1.80 (2 leap days) */
++#define DAYS_DELTA_DECADE    (365 * 10 + 2)
++/* 120 (2100 - 1980) isn't leap year */
++#define NO_LEAP_YEAR_2100    (120)
++#define IS_LEAP_YEAR(y)    (!((y) & 0x3) && (y) != NO_LEAP_YEAR_2100)
++
++#define SECS_PER_MIN    (60)
++#define SECS_PER_HOUR   (60 * SECS_PER_MIN)
++#define SECS_PER_DAY    (24 * SECS_PER_HOUR)
++
++#define MAKE_LEAP_YEAR(leap_year, year)                         \
++	do {                                                    \
++		if (unlikely(year > NO_LEAP_YEAR_2100))         \
++			leap_year = ((year + 3) / 4) - 1;       \
++		else                                            \
++			leap_year = ((year + 3) / 4);           \
++	} while (0)
++
++/* Linear day numbers of the respective 1sts in non-leap years. */
++static time_t accum_days_in_year[] = {
++	/* Jan  Feb  Mar  Apr  May  Jun  Jul  Aug  Sep  Oct  Nov  Dec */
++	0,   0,  31,  59,  90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0,
++};
++
++/* Convert a FAT time/date pair to a UNIX date (seconds since 1 1 70). */
++static void exfat_time_fat2unix(struct exfat_sb_info *sbi,
++				struct timespec64 *ts, struct date_time_t *tp)
++{
++	time_t year = tp->Year;
++	time_t ld;
++
++	MAKE_LEAP_YEAR(ld, year);
++
++	if (IS_LEAP_YEAR(year) && (tp->Month) > 2)
++		ld++;
++
++	ts->tv_sec = tp->Second +
++		     tp->Minute * SECS_PER_MIN +
++		     tp->Hour * SECS_PER_HOUR +
++		     (ld + accum_days_in_year[(tp->Month)] +
++		      (tp->Day - 1)) * SECS_PER_DAY +
++		     (year * 365 + DAYS_DELTA_DECADE) * SECS_PER_DAY +
++		     sys_tz.tz_minuteswest * SECS_PER_MIN;
++
++	ts->tv_nsec = 0;
++}
++
++/* Convert linear UNIX date to a FAT time/date pair. */
++static void exfat_time_unix2fat(struct exfat_sb_info *sbi,
++				struct timespec64 *ts, struct date_time_t *tp)
++{
++	time_t second = ts->tv_sec;
++	time_t day, month, year;
++	time_t ld;
++
++	second -= sys_tz.tz_minuteswest * SECS_PER_MIN;
++
++	/* Jan 1 GMT 00:00:00 1980. But what about another time zone? */
++	if (second < UNIX_SECS_1980) {
++		tp->Second  = 0;
++		tp->Minute  = 0;
++		tp->Hour = 0;
++		tp->Day  = 1;
++		tp->Month  = 1;
++		tp->Year = 0;
++		return;
++	}
++#if (BITS_PER_LONG == 64)
++	if (second >= UNIX_SECS_2108) {
++		tp->Second  = 59;
++		tp->Minute  = 59;
++		tp->Hour = 23;
++		tp->Day  = 31;
++		tp->Month  = 12;
++		tp->Year = 127;
++		return;
++	}
++#endif
++	day = second / SECS_PER_DAY - DAYS_DELTA_DECADE;
++	year = day / 365;
++	MAKE_LEAP_YEAR(ld, year);
++	if (year * 365 + ld > day)
++		year--;
++
++	MAKE_LEAP_YEAR(ld, year);
++	day -= year * 365 + ld;
++
++	if (IS_LEAP_YEAR(year) && day == accum_days_in_year[3]) {
++		month = 2;
++	} else {
++		if (IS_LEAP_YEAR(year) && day > accum_days_in_year[3])
++			day--;
++		for (month = 1; month < 12; month++) {
++			if (accum_days_in_year[month + 1] > day)
++				break;
++		}
++	}
++	day -= accum_days_in_year[month];
++
++	tp->Second  = second % SECS_PER_MIN;
++	tp->Minute  = (second / SECS_PER_MIN) % 60;
++	tp->Hour = (second / SECS_PER_HOUR) % 24;
++	tp->Day  = day + 1;
++	tp->Month  = month;
++	tp->Year = year;
++}
++
++struct timestamp_t *tm_current(struct timestamp_t *tp)
++{
++	struct timespec64 ts;
++	time_t second, day, leap_day, month, year;
++
++	ktime_get_real_ts64(&ts);
++
++	second = ts.tv_sec;
++	second -= sys_tz.tz_minuteswest * SECS_PER_MIN;
++
++	/* Jan 1 GMT 00:00:00 1980. But what about another time zone? */
++	if (second < UNIX_SECS_1980) {
++		tp->sec  = 0;
++		tp->min  = 0;
++		tp->hour = 0;
++		tp->day  = 1;
++		tp->mon  = 1;
++		tp->year = 0;
++		return tp;
++	}
++#if BITS_PER_LONG == 64
++	if (second >= UNIX_SECS_2108) {
++		tp->sec  = 59;
++		tp->min  = 59;
++		tp->hour = 23;
++		tp->day  = 31;
++		tp->mon  = 12;
++		tp->year = 127;
++		return tp;
++	}
++#endif
++
++	day = second / SECS_PER_DAY - DAYS_DELTA_DECADE;
++	year = day / 365;
++
++	MAKE_LEAP_YEAR(leap_day, year);
++	if (year * 365 + leap_day > day)
++		year--;
++
++	MAKE_LEAP_YEAR(leap_day, year);
++
++	day -= year * 365 + leap_day;
++
++	if (IS_LEAP_YEAR(year) && day == accum_days_in_year[3]) {
++		month = 2;
++	} else {
++		if (IS_LEAP_YEAR(year) && day > accum_days_in_year[3])
++			day--;
++		for (month = 1; month < 12; month++) {
++			if (accum_days_in_year[month + 1] > day)
++				break;
++		}
++	}
++	day -= accum_days_in_year[month];
++
++	tp->sec  = second % SECS_PER_MIN;
++	tp->min  = (second / SECS_PER_MIN) % 60;
++	tp->hour = (second / SECS_PER_HOUR) % 24;
++	tp->day  = day + 1;
++	tp->mon  = month;
++	tp->year = year;
++
++	return tp;
++}
++
++static void __lock_super(struct super_block *sb)
++{
++	struct exfat_sb_info *sbi = EXFAT_SB(sb);
++
++	mutex_lock(&sbi->s_lock);
++}
++
++static void __unlock_super(struct super_block *sb)
++{
++	struct exfat_sb_info *sbi = EXFAT_SB(sb);
++
++	mutex_unlock(&sbi->s_lock);
++}
++
++static int __is_sb_dirty(struct super_block *sb)
++{
++	struct exfat_sb_info *sbi = EXFAT_SB(sb);
++
++	return sbi->s_dirt;
++}
++
++static void __set_sb_clean(struct super_block *sb)
++{
++	struct exfat_sb_info *sbi = EXFAT_SB(sb);
++
++	sbi->s_dirt = 0;
++}
++
++static int __exfat_revalidate(struct dentry *dentry)
++{
++	return 0;
++}
++
++static int exfat_revalidate(struct dentry *dentry, unsigned int flags)
++{
++	if (flags & LOOKUP_RCU)
++		return -ECHILD;
++
++	if (dentry->d_inode)
++		return 1;
++	return __exfat_revalidate(dentry);
++}
++
++static int exfat_revalidate_ci(struct dentry *dentry, unsigned int flags)
++{
++	if (flags & LOOKUP_RCU)
++		return -ECHILD;
++
++	if (dentry->d_inode)
++		return 1;
++
++	if (!flags)
++		return 0;
++
++	if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
++		return 0;
++
++	return __exfat_revalidate(dentry);
++}
++
++static unsigned int __exfat_striptail_len(unsigned int len, const char *name)
++{
++	while (len && name[len - 1] == '.')
++		len--;
++	return len;
++}
++
++static unsigned int exfat_striptail_len(const struct qstr *qstr)
++{
++	return __exfat_striptail_len(qstr->len, qstr->name);
++}
++
++static int exfat_d_hash(const struct dentry *dentry, struct qstr *qstr)
++{
++	qstr->hash = full_name_hash(dentry, qstr->name,
++				    exfat_striptail_len(qstr));
++	return 0;
++}
++
++static int exfat_d_hashi(const struct dentry *dentry, struct qstr *qstr)
++{
++	struct super_block *sb = dentry->d_sb;
++	const unsigned char *name;
++	unsigned int len;
++	unsigned long hash;
++
++	name = qstr->name;
++	len = exfat_striptail_len(qstr);
++
++	hash = init_name_hash(dentry);
++	while (len--)
++		hash = partial_name_hash(nls_upper(sb, *name++), hash);
++	qstr->hash = end_name_hash(hash);
++
++	return 0;
++}
++
++static int exfat_cmpi(const struct dentry *dentry, unsigned int len,
++		      const char *str, const struct qstr *name)
++{
++	struct nls_table *t = EXFAT_SB(dentry->d_sb)->nls_io;
++	unsigned int alen, blen;
++
++	alen = exfat_striptail_len(name);
++	blen = __exfat_striptail_len(len, str);
++	if (alen == blen) {
++		if (t == NULL) {
++			if (strncasecmp(name->name, str, alen) == 0)
++				return 0;
++		} else if (nls_strnicmp(t, name->name, str, alen) == 0)
++			return 0;
++	}
++	return 1;
++}
++
++static int exfat_cmp(const struct dentry *dentry, unsigned int len,
++		     const char *str, const struct qstr *name)
++{
++	unsigned int alen, blen;
++
++	alen = exfat_striptail_len(name);
++	blen = __exfat_striptail_len(len, str);
++	if (alen == blen) {
++		if (strncmp(name->name, str, alen) == 0)
++			return 0;
++	}
++	return 1;
++}
++
++static const struct dentry_operations exfat_ci_dentry_ops = {
++	.d_revalidate   = exfat_revalidate_ci,
++	.d_hash         = exfat_d_hashi,
++	.d_compare      = exfat_cmpi,
++};
++
++static const struct dentry_operations exfat_dentry_ops = {
++	.d_revalidate   = exfat_revalidate,
++	.d_hash         = exfat_d_hash,
++	.d_compare      = exfat_cmp,
++};
++
++static DEFINE_SEMAPHORE(z_sem);
++
++static inline void fs_sync(struct super_block *sb, bool do_sync)
++{
++	if (do_sync)
++		bdev_sync(sb);
++}
++
++/*
++ * If ->i_mode can't hold S_IWUGO (i.e. ATTR_RO), we use ->i_attrs to
++ * save ATTR_RO instead of ->i_mode.
++ *
++ * If it's directory and !sbi->options.rodir, ATTR_RO isn't read-only
++ * bit, it's just used as flag for app.
++ */
++static inline int exfat_mode_can_hold_ro(struct inode *inode)
++{
++	struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb);
++
++	if (S_ISDIR(inode->i_mode))
++		return 0;
++
++	if ((~sbi->options.fs_fmask) & 0222)
++		return 1;
++	return 0;
++}
++
++/* Convert attribute bits and a mask to the UNIX mode. */
++static inline mode_t exfat_make_mode(struct exfat_sb_info *sbi, u32 attr,
++				     mode_t mode)
++{
++	if ((attr & ATTR_READONLY) && !(attr & ATTR_SUBDIR))
++		mode &= ~0222;
++
++	if (attr & ATTR_SUBDIR)
++		return (mode & ~sbi->options.fs_dmask) | S_IFDIR;
++	else if (attr & ATTR_SYMLINK)
++		return (mode & ~sbi->options.fs_dmask) | S_IFLNK;
++	else
++		return (mode & ~sbi->options.fs_fmask) | S_IFREG;
++}
++
++/* Return the FAT attribute byte for this inode */
++static inline u32 exfat_make_attr(struct inode *inode)
++{
++	if (exfat_mode_can_hold_ro(inode) && !(inode->i_mode & 0222))
++		return (EXFAT_I(inode)->fid.attr) | ATTR_READONLY;
++	else
++		return EXFAT_I(inode)->fid.attr;
++}
++
++static inline void exfat_save_attr(struct inode *inode, u32 attr)
++{
++	if (exfat_mode_can_hold_ro(inode))
++		EXFAT_I(inode)->fid.attr = attr & ATTR_RWMASK;
++	else
++		EXFAT_I(inode)->fid.attr = attr & (ATTR_RWMASK | ATTR_READONLY);
++}
++
++static int ffsMountVol(struct super_block *sb)
++{
++	int i, ret;
++	struct pbr_sector_t *p_pbr;
++	struct buffer_head *tmp_bh = NULL;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++
++	pr_info("[EXFAT] trying to mount...\n");
++
++	down(&z_sem);
++
++	buf_init(sb);
++
++	sema_init(&p_fs->v_sem, 1);
++	p_fs->dev_ejected = FALSE;
++
++	/* open the block device */
++	bdev_open(sb);
++
++	if (p_bd->sector_size < sb->s_blocksize) {
++		ret = FFS_MEDIAERR;
++		goto out;
++	}
++	if (p_bd->sector_size > sb->s_blocksize)
++		sb_set_blocksize(sb, p_bd->sector_size);
++
++	/* read Sector 0 */
++	if (sector_read(sb, 0, &tmp_bh, 1) != FFS_SUCCESS) {
++		ret = FFS_MEDIAERR;
++		goto out;
++	}
++
++	p_fs->PBR_sector = 0;
++
++	p_pbr = (struct pbr_sector_t *) tmp_bh->b_data;
++
++	/* check the validity of PBR */
++	if (GET16_A(p_pbr->signature) != PBR_SIGNATURE) {
++		brelse(tmp_bh);
++		bdev_close(sb);
++		ret = FFS_FORMATERR;
++		goto out;
++	}
++
++	/* fill fs_stuct */
++	for (i = 0; i < 53; i++)
++		if (p_pbr->bpb[i])
++			break;
++
++	if (i < 53) {
++		if (GET16(p_pbr->bpb + 11)) /* num_fat_sectors */
++			ret = fat16_mount(sb, p_pbr);
++		else
++			ret = fat32_mount(sb, p_pbr);
++	} else {
++		ret = exfat_mount(sb, p_pbr);
++	}
++
++	brelse(tmp_bh);
++
++	if (ret) {
++		bdev_close(sb);
++		goto out;
++	}
++
++	if (p_fs->vol_type == EXFAT) {
++		ret = load_alloc_bitmap(sb);
++		if (ret) {
++			bdev_close(sb);
++			goto out;
++		}
++		ret = load_upcase_table(sb);
++		if (ret) {
++			free_alloc_bitmap(sb);
++			bdev_close(sb);
++			goto out;
++		}
++	}
++
++	if (p_fs->dev_ejected) {
++		if (p_fs->vol_type == EXFAT) {
++			free_upcase_table(sb);
++			free_alloc_bitmap(sb);
++		}
++		bdev_close(sb);
++		ret = FFS_MEDIAERR;
++		goto out;
++	}
++
++	pr_info("[EXFAT] mounted successfully\n");
++
++out:
++	up(&z_sem);
++
++	return ret;
++}
++
++static int ffsUmountVol(struct super_block *sb)
++{
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	int err = FFS_SUCCESS;
++
++	pr_info("[EXFAT] trying to unmount...\n");
++
++	down(&z_sem);
++
++	/* acquire the lock for file system critical section */
++	down(&p_fs->v_sem);
++
++	fs_sync(sb, false);
++	fs_set_vol_flags(sb, VOL_CLEAN);
++
++	if (p_fs->vol_type == EXFAT) {
++		free_upcase_table(sb);
++		free_alloc_bitmap(sb);
++	}
++
++	FAT_release_all(sb);
++	buf_release_all(sb);
++
++	/* close the block device */
++	bdev_close(sb);
++
++	if (p_fs->dev_ejected) {
++		pr_info("[EXFAT] unmounted with media errors. Device is already ejected.\n");
++		err = FFS_MEDIAERR;
++	}
++
++	buf_shutdown(sb);
++
++	/* release the lock for file system critical section */
++	up(&p_fs->v_sem);
++	up(&z_sem);
++
++	pr_info("[EXFAT] unmounted successfully\n");
++
++	return err;
++}
++
++static int ffsGetVolInfo(struct super_block *sb, struct vol_info_t *info)
++{
++	int err = FFS_SUCCESS;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	/* check the validity of pointer parameters */
++	if (info == NULL)
++		return FFS_ERROR;
++
++	/* acquire the lock for file system critical section */
++	down(&p_fs->v_sem);
++
++	if (p_fs->used_clusters == (u32) ~0)
++		p_fs->used_clusters = p_fs->fs_func->count_used_clusters(sb);
++
++	info->FatType = p_fs->vol_type;
++	info->ClusterSize = p_fs->cluster_size;
++	info->NumClusters = p_fs->num_clusters - 2; /* clu 0 & 1 */
++	info->UsedClusters = p_fs->used_clusters;
++	info->FreeClusters = info->NumClusters - info->UsedClusters;
++
++	if (p_fs->dev_ejected)
++		err = FFS_MEDIAERR;
++
++	/* release the lock for file system critical section */
++	up(&p_fs->v_sem);
++
++	return err;
++}
++
++static int ffsSyncVol(struct super_block *sb, bool do_sync)
++{
++	int err = FFS_SUCCESS;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	/* acquire the lock for file system critical section */
++	down(&p_fs->v_sem);
++
++	/* synchronize the file system */
++	fs_sync(sb, do_sync);
++	fs_set_vol_flags(sb, VOL_CLEAN);
++
++	if (p_fs->dev_ejected)
++		err = FFS_MEDIAERR;
++
++	/* release the lock for file system critical section */
++	up(&p_fs->v_sem);
++
++	return err;
++}
++
++/*----------------------------------------------------------------------*/
++/*  File Operation Functions                                            */
++/*----------------------------------------------------------------------*/
++
++static int ffsLookupFile(struct inode *inode, char *path, struct file_id_t *fid)
++{
++	int ret, dentry, num_entries;
++	struct chain_t dir;
++	struct uni_name_t uni_name;
++	struct dos_name_t dos_name;
++	struct dentry_t *ep, *ep2;
++	struct entry_set_cache_t *es = NULL;
++	struct super_block *sb = inode->i_sb;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	pr_debug("%s entered\n", __func__);
++
++	/* check the validity of pointer parameters */
++	if ((fid == NULL) || (path == NULL) || (*path == '\0'))
++		return FFS_ERROR;
++
++	/* acquire the lock for file system critical section */
++	down(&p_fs->v_sem);
++
++	/* check the validity of directory name in the given pathname */
++	ret = resolve_path(inode, path, &dir, &uni_name);
++	if (ret)
++		goto out;
++
++	ret = get_num_entries_and_dos_name(sb, &dir, &uni_name, &num_entries,
++					   &dos_name);
++	if (ret)
++		goto out;
++
++	/* search the file name for directories */
++	dentry = p_fs->fs_func->find_dir_entry(sb, &dir, &uni_name, num_entries,
++					       &dos_name, TYPE_ALL);
++	if (dentry < -1) {
++		return FFS_NOTFOUND;
++		goto out;
++	}
++
++	fid->dir.dir = dir.dir;
++	fid->dir.size = dir.size;
++	fid->dir.flags = dir.flags;
++	fid->entry = dentry;
++
++	if (dentry == -1) {
++		fid->type = TYPE_DIR;
++		fid->rwoffset = 0;
++		fid->hint_last_off = -1;
++
++		fid->attr = ATTR_SUBDIR;
++		fid->flags = 0x01;
++		fid->size = 0;
++		fid->start_clu = p_fs->root_dir;
++	} else {
++		if (p_fs->vol_type == EXFAT) {
++			es = get_entry_set_in_dir(sb, &dir, dentry,
++						  ES_2_ENTRIES, &ep);
++			if (!es) {
++				ret =  FFS_MEDIAERR;
++				goto out;
++			}
++			ep2 = ep+1;
++		} else {
++			ep = get_entry_in_dir(sb, &dir, dentry, NULL);
++			if (!ep) {
++				ret =  FFS_MEDIAERR;
++				goto out;
++			}
++			ep2 = ep;
++		}
++
++		fid->type = p_fs->fs_func->get_entry_type(ep);
++		fid->rwoffset = 0;
++		fid->hint_last_off = -1;
++		fid->attr = p_fs->fs_func->get_entry_attr(ep);
++
++		fid->size = p_fs->fs_func->get_entry_size(ep2);
++		if ((fid->type == TYPE_FILE) && (fid->size == 0)) {
++			fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01;
++			fid->start_clu = CLUSTER_32(~0);
++		} else {
++			fid->flags = p_fs->fs_func->get_entry_flag(ep2);
++			fid->start_clu = p_fs->fs_func->get_entry_clu0(ep2);
++		}
++
++		if (p_fs->vol_type == EXFAT)
++			release_entry_set(es);
++	}
++
++	if (p_fs->dev_ejected)
++		ret = FFS_MEDIAERR;
++out:
++	/* release the lock for file system critical section */
++	up(&p_fs->v_sem);
++
++	return ret;
++}
++
++static int ffsCreateFile(struct inode *inode, char *path, u8 mode,
++			 struct file_id_t *fid)
++{
++	struct chain_t dir;
++	struct uni_name_t uni_name;
++	struct super_block *sb = inode->i_sb;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	int ret;
++
++	/* check the validity of pointer parameters */
++	if ((fid == NULL) || (path == NULL) || (*path == '\0'))
++		return FFS_ERROR;
++
++	/* acquire the lock for file system critical section */
++	down(&p_fs->v_sem);
++
++	/* check the validity of directory name in the given pathname */
++	ret = resolve_path(inode, path, &dir, &uni_name);
++	if (ret)
++		goto out;
++
++	fs_set_vol_flags(sb, VOL_DIRTY);
++
++	/* create a new file */
++	ret = create_file(inode, &dir, &uni_name, mode, fid);
++
++#ifdef CONFIG_EXFAT_DELAYED_SYNC
++	fs_sync(sb, false);
++	fs_set_vol_flags(sb, VOL_CLEAN);
++#endif
++
++	if (p_fs->dev_ejected)
++		ret = FFS_MEDIAERR;
++
++out:
++	/* release the lock for file system critical section */
++	up(&p_fs->v_sem);
++
++	return ret;
++}
++
++static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer,
++		       u64 count, u64 *rcount)
++{
++	s32 offset, sec_offset, clu_offset;
++	u32 clu;
++	int ret;
++	sector_t LogSector;
++	u64 oneblkread, read_bytes;
++	struct buffer_head *tmp_bh = NULL;
++	struct super_block *sb = inode->i_sb;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++
++	/* check the validity of the given file id */
++	if (fid == NULL)
++		return FFS_INVALIDFID;
++
++	/* check the validity of pointer parameters */
++	if (buffer == NULL)
++		return FFS_ERROR;
++
++	/* acquire the lock for file system critical section */
++	down(&p_fs->v_sem);
++
++	/* check if the given file ID is opened */
++	if (fid->type != TYPE_FILE) {
++		ret = FFS_PERMISSIONERR;
++		goto out;
++	}
++
++	if (fid->rwoffset > fid->size)
++		fid->rwoffset = fid->size;
++
++	if (count > (fid->size - fid->rwoffset))
++		count = fid->size - fid->rwoffset;
++
++	if (count == 0) {
++		if (rcount != NULL)
++			*rcount = 0;
++		ret = FFS_EOF;
++		goto out;
++	}
++
++	read_bytes = 0;
++
++	while (count > 0) {
++		clu_offset = (s32)(fid->rwoffset >> p_fs->cluster_size_bits);
++		clu = fid->start_clu;
++
++		if (fid->flags == 0x03) {
++			clu += clu_offset;
++		} else {
++			/* hint information */
++			if ((clu_offset > 0) && (fid->hint_last_off > 0) &&
++			    (clu_offset >= fid->hint_last_off)) {
++				clu_offset -= fid->hint_last_off;
++				clu = fid->hint_last_clu;
++			}
++
++			while (clu_offset > 0) {
++				/* clu = FAT_read(sb, clu); */
++				if (FAT_read(sb, clu, &clu) == -1)
++					return FFS_MEDIAERR;
++
++				clu_offset--;
++			}
++		}
++
++		/* hint information */
++		fid->hint_last_off = (s32)(fid->rwoffset >>
++					   p_fs->cluster_size_bits);
++		fid->hint_last_clu = clu;
++
++		/* byte offset in cluster */
++		offset = (s32)(fid->rwoffset & (p_fs->cluster_size-1));
++
++		/* sector offset in cluster */
++		sec_offset = offset >> p_bd->sector_size_bits;
++
++		/* byte offset in sector */
++		offset &= p_bd->sector_size_mask;
++
++		LogSector = START_SECTOR(clu) + sec_offset;
++
++		oneblkread = (u64)(p_bd->sector_size - offset);
++		if (oneblkread > count)
++			oneblkread = count;
++
++		if ((offset == 0) && (oneblkread == p_bd->sector_size)) {
++			if (sector_read(sb, LogSector, &tmp_bh, 1) !=
++			    FFS_SUCCESS)
++				goto err_out;
++			memcpy((char *)buffer + read_bytes,
++			       (char *)tmp_bh->b_data, (s32)oneblkread);
++		} else {
++			if (sector_read(sb, LogSector, &tmp_bh, 1) !=
++			    FFS_SUCCESS)
++				goto err_out;
++			memcpy((char *)buffer + read_bytes,
++			       (char *)tmp_bh->b_data + offset,
++			       (s32)oneblkread);
++		}
++		count -= oneblkread;
++		read_bytes += oneblkread;
++		fid->rwoffset += oneblkread;
++	}
++	brelse(tmp_bh);
++
++/* How did this ever work and not leak a brlse()?? */
++err_out:
++	/* set the size of read bytes */
++	if (rcount != NULL)
++		*rcount = read_bytes;
++
++	if (p_fs->dev_ejected)
++		ret = FFS_MEDIAERR;
++
++out:
++	/* release the lock for file system critical section */
++	up(&p_fs->v_sem);
++
++	return ret;
++}
++
++static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
++			void *buffer, u64 count, u64 *wcount)
++{
++	s32 modified = FALSE, offset, sec_offset, clu_offset;
++	s32 num_clusters, num_alloc, num_alloced = (s32) ~0;
++	int ret = 0;
++	u32 clu, last_clu;
++	sector_t LogSector, sector = 0;
++	u64 oneblkwrite, write_bytes;
++	struct chain_t new_clu;
++	struct timestamp_t tm;
++	struct dentry_t *ep, *ep2;
++	struct entry_set_cache_t *es = NULL;
++	struct buffer_head *tmp_bh = NULL;
++	struct super_block *sb = inode->i_sb;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++
++	/* check the validity of the given file id */
++	if (fid == NULL)
++		return FFS_INVALIDFID;
++
++	/* check the validity of pointer parameters */
++	if (buffer == NULL)
++		return FFS_ERROR;
++
++	/* acquire the lock for file system critical section */
++	down(&p_fs->v_sem);
++
++	/* check if the given file ID is opened */
++	if (fid->type != TYPE_FILE) {
++		ret = FFS_PERMISSIONERR;
++		goto out;
++	}
++
++	if (fid->rwoffset > fid->size)
++		fid->rwoffset = fid->size;
++
++	if (count == 0) {
++		if (wcount != NULL)
++			*wcount = 0;
++		ret = FFS_SUCCESS;
++		goto out;
++	}
++
++	fs_set_vol_flags(sb, VOL_DIRTY);
++
++	if (fid->size == 0)
++		num_clusters = 0;
++	else
++		num_clusters = (s32)((fid->size-1) >>
++				     p_fs->cluster_size_bits) + 1;
++
++	write_bytes = 0;
++
++	while (count > 0) {
++		clu_offset = (s32)(fid->rwoffset >> p_fs->cluster_size_bits);
++		clu = last_clu = fid->start_clu;
++
++		if (fid->flags == 0x03) {
++			if ((clu_offset > 0) && (clu != CLUSTER_32(~0))) {
++				last_clu += clu_offset - 1;
++
++				if (clu_offset == num_clusters)
++					clu = CLUSTER_32(~0);
++				else
++					clu += clu_offset;
++			}
++		} else {
++			/* hint information */
++			if ((clu_offset > 0) && (fid->hint_last_off > 0) &&
++			    (clu_offset >= fid->hint_last_off)) {
++				clu_offset -= fid->hint_last_off;
++				clu = fid->hint_last_clu;
++			}
++
++			while ((clu_offset > 0) && (clu != CLUSTER_32(~0))) {
++				last_clu = clu;
++				/* clu = FAT_read(sb, clu); */
++				if (FAT_read(sb, clu, &clu) == -1) {
++					ret = FFS_MEDIAERR;
++					goto out;
++				}
++				clu_offset--;
++			}
++		}
++
++		if (clu == CLUSTER_32(~0)) {
++			num_alloc = (s32)((count - 1) >>
++					  p_fs->cluster_size_bits) + 1;
++			new_clu.dir = (last_clu == CLUSTER_32(~0)) ?
++					CLUSTER_32(~0) : last_clu+1;
++			new_clu.size = 0;
++			new_clu.flags = fid->flags;
++
++			/* (1) allocate a chain of clusters */
++			num_alloced = p_fs->fs_func->alloc_cluster(sb,
++								   num_alloc,
++								   &new_clu);
++			if (num_alloced == 0)
++				break;
++			else if (num_alloced < 0) {
++				ret = FFS_MEDIAERR;
++				goto out;
++			}
++
++			/* (2) append to the FAT chain */
++			if (last_clu == CLUSTER_32(~0)) {
++				if (new_clu.flags == 0x01)
++					fid->flags = 0x01;
++				fid->start_clu = new_clu.dir;
++				modified = TRUE;
++			} else {
++				if (new_clu.flags != fid->flags) {
++					exfat_chain_cont_cluster(sb,
++								 fid->start_clu,
++								 num_clusters);
++					fid->flags = 0x01;
++					modified = TRUE;
++				}
++				if (new_clu.flags == 0x01)
++					FAT_write(sb, last_clu, new_clu.dir);
++			}
++
++			num_clusters += num_alloced;
++			clu = new_clu.dir;
++		}
++
++		/* hint information */
++		fid->hint_last_off = (s32)(fid->rwoffset >>
++					   p_fs->cluster_size_bits);
++		fid->hint_last_clu = clu;
++
++		/* byte offset in cluster   */
++		offset = (s32)(fid->rwoffset & (p_fs->cluster_size - 1));
++
++		/* sector offset in cluster */
++		sec_offset = offset >> p_bd->sector_size_bits;
++
++		/* byte offset in sector    */
++		offset &= p_bd->sector_size_mask;
++
++		LogSector = START_SECTOR(clu) + sec_offset;
++
++		oneblkwrite = (u64)(p_bd->sector_size - offset);
++		if (oneblkwrite > count)
++			oneblkwrite = count;
++
++		if ((offset == 0) && (oneblkwrite == p_bd->sector_size)) {
++			if (sector_read(sb, LogSector, &tmp_bh, 0) !=
++			    FFS_SUCCESS)
++				goto err_out;
++			memcpy((char *)tmp_bh->b_data,
++			       (char *)buffer + write_bytes, (s32)oneblkwrite);
++			if (sector_write(sb, LogSector, tmp_bh, 0) !=
++			    FFS_SUCCESS) {
++				brelse(tmp_bh);
++				goto err_out;
++			}
++		} else {
++			if ((offset > 0) ||
++			    ((fid->rwoffset+oneblkwrite) < fid->size)) {
++				if (sector_read(sb, LogSector, &tmp_bh, 1) !=
++				    FFS_SUCCESS)
++					goto err_out;
++			} else {
++				if (sector_read(sb, LogSector, &tmp_bh, 0) !=
++				    FFS_SUCCESS)
++					goto err_out;
++			}
++
++			memcpy((char *)tmp_bh->b_data + offset,
++			       (char *)buffer + write_bytes, (s32)oneblkwrite);
++			if (sector_write(sb, LogSector, tmp_bh, 0) !=
++			    FFS_SUCCESS) {
++				brelse(tmp_bh);
++				goto err_out;
++			}
++		}
++
++		count -= oneblkwrite;
++		write_bytes += oneblkwrite;
++		fid->rwoffset += oneblkwrite;
++
++		fid->attr |= ATTR_ARCHIVE;
++
++		if (fid->size < fid->rwoffset) {
++			fid->size = fid->rwoffset;
++			modified = TRUE;
++		}
++	}
++
++	brelse(tmp_bh);
++
++	/* (3) update the direcoty entry */
++	if (p_fs->vol_type == EXFAT) {
++		es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry,
++					  ES_ALL_ENTRIES, &ep);
++		if (es == NULL)
++			goto err_out;
++		ep2 = ep+1;
++	} else {
++		ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or);
++		if (!ep)
++			goto err_out;
++		ep2 = ep;
++	}
++
++	p_fs->fs_func->set_entry_time(ep, tm_current(&tm), TM_MODIFY);
++	p_fs->fs_func->set_entry_attr(ep, fid->attr);
++
++	if (p_fs->vol_type != EXFAT)
++		buf_modify(sb, sector);
++
++	if (modified) {
++		if (p_fs->fs_func->get_entry_flag(ep2) != fid->flags)
++			p_fs->fs_func->set_entry_flag(ep2, fid->flags);
++
++		if (p_fs->fs_func->get_entry_size(ep2) != fid->size)
++			p_fs->fs_func->set_entry_size(ep2, fid->size);
++
++		if (p_fs->fs_func->get_entry_clu0(ep2) != fid->start_clu)
++			p_fs->fs_func->set_entry_clu0(ep2, fid->start_clu);
++
++		if (p_fs->vol_type != EXFAT)
++			buf_modify(sb, sector);
++	}
++
++	if (p_fs->vol_type == EXFAT) {
++		update_dir_checksum_with_entry_set(sb, es);
++		release_entry_set(es);
++	}
++
++#ifdef CONFIG_EXFAT_DELAYED_SYNC
++	fs_sync(sb, false);
++	fs_set_vol_flags(sb, VOL_CLEAN);
++#endif
++
++err_out:
++	/* set the size of written bytes */
++	if (wcount != NULL)
++		*wcount = write_bytes;
++
++	if (num_alloced == 0)
++		ret = FFS_FULL;
++
++	else if (p_fs->dev_ejected)
++		ret = FFS_MEDIAERR;
++
++out:
++	/* release the lock for file system critical section */
++	up(&p_fs->v_sem);
++
++	return ret;
++}
++
++static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size)
++{
++	s32 num_clusters;
++	u32 last_clu = CLUSTER_32(0);
++	int ret = 0;
++	sector_t sector = 0;
++	struct chain_t clu;
++	struct timestamp_t tm;
++	struct dentry_t *ep, *ep2;
++	struct super_block *sb = inode->i_sb;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct file_id_t *fid = &(EXFAT_I(inode)->fid);
++	struct entry_set_cache_t *es = NULL;
++
++	pr_debug("%s entered (inode %p size %llu)\n", __func__, inode,
++		 new_size);
++
++	/* acquire the lock for file system critical section */
++	down(&p_fs->v_sem);
++
++	/* check if the given file ID is opened */
++	if (fid->type != TYPE_FILE) {
++		ret = FFS_PERMISSIONERR;
++		goto out;
++	}
++
++	if (fid->size != old_size) {
++		pr_err("[EXFAT] truncate : can't skip it because of size-mismatch(old:%lld->fid:%lld).\n",
++		       old_size, fid->size);
++	}
++
++	if (old_size <= new_size) {
++		ret = FFS_SUCCESS;
++		goto out;
++	}
++
++	fs_set_vol_flags(sb, VOL_DIRTY);
++
++	clu.dir = fid->start_clu;
++	clu.size = (s32)((old_size-1) >> p_fs->cluster_size_bits) + 1;
++	clu.flags = fid->flags;
++
++	if (new_size > 0) {
++		num_clusters = (s32)((new_size-1) >>
++				     p_fs->cluster_size_bits) + 1;
++
++		if (clu.flags == 0x03) {
++			clu.dir += num_clusters;
++		} else {
++			while (num_clusters > 0) {
++				last_clu = clu.dir;
++				if (FAT_read(sb, clu.dir, &clu.dir) == -1)
++					return FFS_MEDIAERR;
++				num_clusters--;
++			}
++		}
++
++		clu.size -= num_clusters;
++	}
++
++	fid->size = new_size;
++	fid->attr |= ATTR_ARCHIVE;
++	if (new_size == 0) {
++		fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01;
++		fid->start_clu = CLUSTER_32(~0);
++	}
++
++	/* (1) update the directory entry */
++	if (p_fs->vol_type == EXFAT) {
++		es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
++					  ES_ALL_ENTRIES, &ep);
++		if (es == NULL) {
++			ret = FFS_MEDIAERR;
++			goto out;
++			}
++		ep2 = ep+1;
++	} else {
++		ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or);
++		if (!ep) {
++			ret = FFS_MEDIAERR;
++			goto out;
++		}
++		ep2 = ep;
++	}
++
++	p_fs->fs_func->set_entry_time(ep, tm_current(&tm), TM_MODIFY);
++	p_fs->fs_func->set_entry_attr(ep, fid->attr);
++
++	p_fs->fs_func->set_entry_size(ep2, new_size);
++	if (new_size == 0) {
++		p_fs->fs_func->set_entry_flag(ep2, 0x01);
++		p_fs->fs_func->set_entry_clu0(ep2, CLUSTER_32(0));
++	}
++
++	if (p_fs->vol_type != EXFAT)
++		buf_modify(sb, sector);
++	else {
++		update_dir_checksum_with_entry_set(sb, es);
++		release_entry_set(es);
++	}
++
++	/* (2) cut off from the FAT chain */
++	if (last_clu != CLUSTER_32(0)) {
++		if (fid->flags == 0x01)
++			FAT_write(sb, last_clu, CLUSTER_32(~0));
++	}
++
++	/* (3) free the clusters */
++	p_fs->fs_func->free_cluster(sb, &clu, 0);
++
++	/* hint information */
++	fid->hint_last_off = -1;
++	if (fid->rwoffset > fid->size)
++		fid->rwoffset = fid->size;
++
++#ifdef CONFIG_EXFAT_DELAYED_SYNC
++	fs_sync(sb, false);
++	fs_set_vol_flags(sb, VOL_CLEAN);
++#endif
++
++	if (p_fs->dev_ejected)
++		ret = FFS_MEDIAERR;
++
++out:
++	pr_debug("%s exited (%d)\n", __func__, ret);
++	/* release the lock for file system critical section */
++	up(&p_fs->v_sem);
++
++	return ret;
++}
++
++static void update_parent_info(struct file_id_t *fid,
++			       struct inode *parent_inode)
++{
++	struct fs_info_t *p_fs = &(EXFAT_SB(parent_inode->i_sb)->fs_info);
++	struct file_id_t *parent_fid = &(EXFAT_I(parent_inode)->fid);
++
++	if (unlikely((parent_fid->flags != fid->dir.flags) ||
++		     (parent_fid->size !=
++		      (fid->dir.size << p_fs->cluster_size_bits)) ||
++		     (parent_fid->start_clu != fid->dir.dir))) {
++		fid->dir.dir = parent_fid->start_clu;
++		fid->dir.flags = parent_fid->flags;
++		fid->dir.size = ((parent_fid->size + (p_fs->cluster_size-1))
++						>> p_fs->cluster_size_bits);
++	}
++}
++
++static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid,
++		       struct inode *new_parent_inode, struct dentry *new_dentry)
++{
++	s32 ret;
++	s32 dentry;
++	struct chain_t olddir, newdir;
++	struct chain_t *p_dir = NULL;
++	struct uni_name_t uni_name;
++	struct dentry_t *ep;
++	struct super_block *sb = old_parent_inode->i_sb;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	u8 *new_path = (u8 *) new_dentry->d_name.name;
++	struct inode *new_inode = new_dentry->d_inode;
++	int num_entries;
++	struct file_id_t *new_fid = NULL;
++	s32 new_entry = 0;
++
++	/* check the validity of the given file id */
++	if (fid == NULL)
++		return FFS_INVALIDFID;
++
++	/* check the validity of pointer parameters */
++	if ((new_path == NULL) || (*new_path == '\0'))
++		return FFS_ERROR;
++
++	/* acquire the lock for file system critical section */
++	down(&p_fs->v_sem);
++
++	update_parent_info(fid, old_parent_inode);
++
++	olddir.dir = fid->dir.dir;
++	olddir.size = fid->dir.size;
++	olddir.flags = fid->dir.flags;
++
++	dentry = fid->entry;
++
++	/* check if the old file is "." or ".." */
++	if (p_fs->vol_type != EXFAT) {
++		if ((olddir.dir != p_fs->root_dir) && (dentry < 2)) {
++			ret = FFS_PERMISSIONERR;
++			goto out2;
++		}
++	}
++
++	ep = get_entry_in_dir(sb, &olddir, dentry, NULL);
++	if (!ep) {
++		ret = FFS_MEDIAERR;
++		goto out2;
++	}
++
++	if (p_fs->fs_func->get_entry_attr(ep) & ATTR_READONLY) {
++		ret = FFS_PERMISSIONERR;
++		goto out2;
++	}
++
++	/* check whether new dir is existing directory and empty */
++	if (new_inode) {
++		u32 entry_type;
++
++		ret = FFS_MEDIAERR;
++		new_fid = &EXFAT_I(new_inode)->fid;
++
++		update_parent_info(new_fid, new_parent_inode);
++
++		p_dir = &(new_fid->dir);
++		new_entry = new_fid->entry;
++		ep = get_entry_in_dir(sb, p_dir, new_entry, NULL);
++		if (!ep)
++			goto out;
++
++		entry_type = p_fs->fs_func->get_entry_type(ep);
++
++		if (entry_type == TYPE_DIR) {
++			struct chain_t new_clu;
++
++			new_clu.dir = new_fid->start_clu;
++			new_clu.size = (s32)((new_fid->size - 1) >>
++					     p_fs->cluster_size_bits) + 1;
++			new_clu.flags = new_fid->flags;
++
++			if (!is_dir_empty(sb, &new_clu)) {
++				ret = FFS_FILEEXIST;
++				goto out;
++			}
++		}
++	}
++
++	/* check the validity of directory name in the given new pathname */
++	ret = resolve_path(new_parent_inode, new_path, &newdir, &uni_name);
++	if (ret)
++		goto out2;
++
++	fs_set_vol_flags(sb, VOL_DIRTY);
++
++	if (olddir.dir == newdir.dir)
++		ret = rename_file(new_parent_inode, &olddir, dentry, &uni_name,
++				  fid);
++	else
++		ret = move_file(new_parent_inode, &olddir, dentry, &newdir,
++				&uni_name, fid);
++
++	if ((ret == FFS_SUCCESS) && new_inode) {
++		/* delete entries of new_dir */
++		ep = get_entry_in_dir(sb, p_dir, new_entry, NULL);
++		if (!ep)
++			goto out;
++
++		num_entries = p_fs->fs_func->count_ext_entries(sb, p_dir,
++							       new_entry, ep);
++		if (num_entries < 0)
++			goto out;
++		p_fs->fs_func->delete_dir_entry(sb, p_dir, new_entry, 0,
++						num_entries+1);
++	}
++out:
++#ifdef CONFIG_EXFAT_DELAYED_SYNC
++	fs_sync(sb, false);
++	fs_set_vol_flags(sb, VOL_CLEAN);
++#endif
++
++	if (p_fs->dev_ejected)
++		ret = FFS_MEDIAERR;
++out2:
++	/* release the lock for file system critical section */
++	up(&p_fs->v_sem);
++
++	return ret;
++}
++
++static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid)
++{
++	s32 dentry;
++	int ret = FFS_SUCCESS;
++	struct chain_t dir, clu_to_free;
++	struct dentry_t *ep;
++	struct super_block *sb = inode->i_sb;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	/* check the validity of the given file id */
++	if (fid == NULL)
++		return FFS_INVALIDFID;
++
++	/* acquire the lock for file system critical section */
++	down(&p_fs->v_sem);
++
++	dir.dir = fid->dir.dir;
++	dir.size = fid->dir.size;
++	dir.flags = fid->dir.flags;
++
++	dentry = fid->entry;
++
++	ep = get_entry_in_dir(sb, &dir, dentry, NULL);
++	if (!ep) {
++		ret = FFS_MEDIAERR;
++		goto out;
++	}
++
++	if (p_fs->fs_func->get_entry_attr(ep) & ATTR_READONLY) {
++		ret = FFS_PERMISSIONERR;
++		goto out;
++	}
++	fs_set_vol_flags(sb, VOL_DIRTY);
++
++	/* (1) update the directory entry */
++	remove_file(inode, &dir, dentry);
++
++	clu_to_free.dir = fid->start_clu;
++	clu_to_free.size = (s32)((fid->size-1) >> p_fs->cluster_size_bits) + 1;
++	clu_to_free.flags = fid->flags;
++
++	/* (2) free the clusters */
++	p_fs->fs_func->free_cluster(sb, &clu_to_free, 0);
++
++	fid->size = 0;
++	fid->start_clu = CLUSTER_32(~0);
++	fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01;
++
++#ifdef CONFIG_EXFAT_DELAYED_SYNC
++	fs_sync(sb, false);
++	fs_set_vol_flags(sb, VOL_CLEAN);
++#endif
++
++	if (p_fs->dev_ejected)
++		ret = FFS_MEDIAERR;
++out:
++	/* release the lock for file system critical section */
++	up(&p_fs->v_sem);
++
++	return ret;
++}
++
++#if 0
++/* Not currently wired up */
++static int ffsSetAttr(struct inode *inode, u32 attr)
++{
++	u32 type;
++	int ret = FFS_SUCCESS;
++	sector_t sector = 0;
++	struct dentry_t *ep;
++	struct super_block *sb = inode->i_sb;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct file_id_t *fid = &(EXFAT_I(inode)->fid);
++	u8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0;
++	struct entry_set_cache_t *es = NULL;
++
++	if (fid->attr == attr) {
++		if (p_fs->dev_ejected)
++			return FFS_MEDIAERR;
++		return FFS_SUCCESS;
++	}
++
++	if (is_dir) {
++		if ((fid->dir.dir == p_fs->root_dir) &&
++		    (fid->entry == -1)) {
++			if (p_fs->dev_ejected)
++				return FFS_MEDIAERR;
++			return FFS_SUCCESS;
++		}
++	}
++
++	/* acquire the lock for file system critical section */
++	down(&p_fs->v_sem);
++
++	/* get the directory entry of given file */
++	if (p_fs->vol_type == EXFAT) {
++		es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry,
++					  ES_ALL_ENTRIES, &ep);
++		if (es == NULL) {
++			ret = FFS_MEDIAERR;
++			goto out;
++		}
++	} else {
++		ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or);
++		if (!ep) {
++			ret = FFS_MEDIAERR;
++			goto out;
++		}
++	}
++
++	type = p_fs->fs_func->get_entry_type(ep);
++
++	if (((type == TYPE_FILE) && (attr & ATTR_SUBDIR)) ||
++	    ((type == TYPE_DIR) && (!(attr & ATTR_SUBDIR)))) {
++		if (p_fs->dev_ejected)
++			ret = FFS_MEDIAERR;
++		else
++			ret = FFS_ERROR;
++
++		if (p_fs->vol_type == EXFAT)
++			release_entry_set(es);
++		goto out;
++	}
++
++	fs_set_vol_flags(sb, VOL_DIRTY);
++
++	/* set the file attribute */
++	fid->attr = attr;
++	p_fs->fs_func->set_entry_attr(ep, attr);
++
++	if (p_fs->vol_type != EXFAT)
++		buf_modify(sb, sector);
++	else {
++		update_dir_checksum_with_entry_set(sb, es);
++		release_entry_set(es);
++	}
++
++#ifdef CONFIG_EXFAT_DELAYED_SYNC
++	fs_sync(sb, false);
++	fs_set_vol_flags(sb, VOL_CLEAN);
++#endif
++
++	if (p_fs->dev_ejected)
++		ret = FFS_MEDIAERR;
++out:
++	/* release the lock for file system critical section */
++	up(&p_fs->v_sem);
++
++	return ret;
++}
++#endif
++
++static int ffsReadStat(struct inode *inode, struct dir_entry_t *info)
++{
++	sector_t sector = 0;
++	s32 count;
++	int ret = FFS_SUCCESS;
++	struct chain_t dir;
++	struct uni_name_t uni_name;
++	struct timestamp_t tm;
++	struct dentry_t *ep, *ep2;
++	struct super_block *sb = inode->i_sb;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct file_id_t *fid = &(EXFAT_I(inode)->fid);
++	struct entry_set_cache_t *es = NULL;
++	u8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0;
++
++	pr_debug("%s entered\n", __func__);
++
++	/* acquire the lock for file system critical section */
++	down(&p_fs->v_sem);
++
++	if (is_dir) {
++		if ((fid->dir.dir == p_fs->root_dir) &&
++		    (fid->entry == -1)) {
++			info->Attr = ATTR_SUBDIR;
++			memset((char *)&info->CreateTimestamp, 0,
++			       sizeof(struct date_time_t));
++			memset((char *)&info->ModifyTimestamp, 0,
++			       sizeof(struct date_time_t));
++			memset((char *)&info->AccessTimestamp, 0,
++			       sizeof(struct date_time_t));
++			strcpy(info->ShortName, ".");
++			strcpy(info->Name, ".");
++
++			dir.dir = p_fs->root_dir;
++			dir.flags = 0x01;
++
++			if (p_fs->root_dir == CLUSTER_32(0)) {
++				/* FAT16 root_dir */
++				info->Size = p_fs->dentries_in_root <<
++						DENTRY_SIZE_BITS;
++			} else {
++				info->Size = count_num_clusters(sb, &dir) <<
++						p_fs->cluster_size_bits;
++			}
++
++			count = count_dos_name_entries(sb, &dir, TYPE_DIR);
++			if (count < 0) {
++				ret = FFS_MEDIAERR;
++				goto out;
++			}
++			info->NumSubdirs = count;
++
++			if (p_fs->dev_ejected)
++				ret = FFS_MEDIAERR;
++			goto out;
++		}
++	}
++
++	/* get the directory entry of given file or directory */
++	if (p_fs->vol_type == EXFAT) {
++		es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry,
++					  ES_2_ENTRIES, &ep);
++		if (es == NULL) {
++			ret = FFS_MEDIAERR;
++			goto out;
++		}
++		ep2 = ep+1;
++	} else {
++		ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or);
++		if (!ep) {
++			ret = FFS_MEDIAERR;
++			goto out;
++		}
++		ep2 = ep;
++		buf_lock(sb, sector);
++	}
++
++	/* set FILE_INFO structure using the acquired struct dentry_t */
++	info->Attr = p_fs->fs_func->get_entry_attr(ep);
++
++	p_fs->fs_func->get_entry_time(ep, &tm, TM_CREATE);
++	info->CreateTimestamp.Year = tm.year;
++	info->CreateTimestamp.Month = tm.mon;
++	info->CreateTimestamp.Day = tm.day;
++	info->CreateTimestamp.Hour = tm.hour;
++	info->CreateTimestamp.Minute = tm.min;
++	info->CreateTimestamp.Second = tm.sec;
++	info->CreateTimestamp.MilliSecond = 0;
++
++	p_fs->fs_func->get_entry_time(ep, &tm, TM_MODIFY);
++	info->ModifyTimestamp.Year = tm.year;
++	info->ModifyTimestamp.Month = tm.mon;
++	info->ModifyTimestamp.Day = tm.day;
++	info->ModifyTimestamp.Hour = tm.hour;
++	info->ModifyTimestamp.Minute = tm.min;
++	info->ModifyTimestamp.Second = tm.sec;
++	info->ModifyTimestamp.MilliSecond = 0;
++
++	memset((char *) &info->AccessTimestamp, 0, sizeof(struct date_time_t));
++
++	*(uni_name.name) = 0x0;
++	/* XXX this is very bad for exfat cuz name is already included in es.
++	 * API should be revised
++	 */
++	p_fs->fs_func->get_uni_name_from_ext_entry(sb, &(fid->dir), fid->entry,
++						   uni_name.name);
++	if (*uni_name.name == 0x0 && p_fs->vol_type != EXFAT)
++		get_uni_name_from_dos_entry(sb, (struct dos_dentry_t *)ep,
++					    &uni_name, 0x1);
++	nls_uniname_to_cstring(sb, info->Name, &uni_name);
++
++	if (p_fs->vol_type == EXFAT) {
++		info->NumSubdirs = 2;
++	} else {
++		buf_unlock(sb, sector);
++		get_uni_name_from_dos_entry(sb, (struct dos_dentry_t *)ep,
++					    &uni_name, 0x0);
++		nls_uniname_to_cstring(sb, info->ShortName, &uni_name);
++		info->NumSubdirs = 0;
++	}
++
++	info->Size = p_fs->fs_func->get_entry_size(ep2);
++
++	if (p_fs->vol_type == EXFAT)
++		release_entry_set(es);
++
++	if (is_dir) {
++		dir.dir = fid->start_clu;
++		dir.flags = 0x01;
++
++		if (info->Size == 0)
++			info->Size = (u64)count_num_clusters(sb, &dir) <<
++					p_fs->cluster_size_bits;
++
++		count = count_dos_name_entries(sb, &dir, TYPE_DIR);
++		if (count < 0) {
++			ret = FFS_MEDIAERR;
++			goto out;
++		}
++		info->NumSubdirs += count;
++	}
++
++	if (p_fs->dev_ejected)
++		ret = FFS_MEDIAERR;
++
++out:
++	/* release the lock for file system critical section */
++	up(&p_fs->v_sem);
++
++	pr_debug("%s exited successfully\n", __func__);
++	return ret;
++}
++
++static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info)
++{
++	sector_t sector = 0;
++	int ret = FFS_SUCCESS;
++	struct timestamp_t tm;
++	struct dentry_t *ep, *ep2;
++	struct entry_set_cache_t *es = NULL;
++	struct super_block *sb = inode->i_sb;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct file_id_t *fid = &(EXFAT_I(inode)->fid);
++	u8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0;
++
++	pr_debug("%s entered (inode %p info %p\n", __func__, inode, info);
++
++	/* acquire the lock for file system critical section */
++	down(&p_fs->v_sem);
++
++	if (is_dir) {
++		if ((fid->dir.dir == p_fs->root_dir) &&
++		    (fid->entry == -1)) {
++			if (p_fs->dev_ejected)
++				ret = FFS_MEDIAERR;
++			ret = FFS_SUCCESS;
++			goto out;
++		}
++	}
++
++	fs_set_vol_flags(sb, VOL_DIRTY);
++
++	/* get the directory entry of given file or directory */
++	if (p_fs->vol_type == EXFAT) {
++		es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry,
++					  ES_ALL_ENTRIES, &ep);
++		if (es == NULL) {
++			ret = FFS_MEDIAERR;
++			goto out;
++		}
++		ep2 = ep+1;
++	} else {
++		/* for other than exfat */
++		ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or);
++		if (!ep) {
++			ret = FFS_MEDIAERR;
++			goto out;
++		}
++		ep2 = ep;
++	}
++
++	p_fs->fs_func->set_entry_attr(ep, info->Attr);
++
++	/* set FILE_INFO structure using the acquired struct dentry_t */
++	tm.sec  = info->CreateTimestamp.Second;
++	tm.min  = info->CreateTimestamp.Minute;
++	tm.hour = info->CreateTimestamp.Hour;
++	tm.day  = info->CreateTimestamp.Day;
++	tm.mon  = info->CreateTimestamp.Month;
++	tm.year = info->CreateTimestamp.Year;
++	p_fs->fs_func->set_entry_time(ep, &tm, TM_CREATE);
++
++	tm.sec  = info->ModifyTimestamp.Second;
++	tm.min  = info->ModifyTimestamp.Minute;
++	tm.hour = info->ModifyTimestamp.Hour;
++	tm.day  = info->ModifyTimestamp.Day;
++	tm.mon  = info->ModifyTimestamp.Month;
++	tm.year = info->ModifyTimestamp.Year;
++	p_fs->fs_func->set_entry_time(ep, &tm, TM_MODIFY);
++
++	p_fs->fs_func->set_entry_size(ep2, info->Size);
++
++	if (p_fs->vol_type != EXFAT) {
++		buf_modify(sb, sector);
++	} else {
++		update_dir_checksum_with_entry_set(sb, es);
++		release_entry_set(es);
++	}
++
++	if (p_fs->dev_ejected)
++		ret = FFS_MEDIAERR;
++
++out:
++	/* release the lock for file system critical section */
++	up(&p_fs->v_sem);
++
++	pr_debug("%s exited (%d)\n", __func__, ret);
++
++	return ret;
++}
++
++static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
++{
++	s32 num_clusters, num_alloced, modified = FALSE;
++	u32 last_clu;
++	int ret = FFS_SUCCESS;
++	sector_t sector = 0;
++	struct chain_t new_clu;
++	struct dentry_t *ep;
++	struct entry_set_cache_t *es = NULL;
++	struct super_block *sb = inode->i_sb;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct file_id_t *fid = &(EXFAT_I(inode)->fid);
++
++	/* check the validity of pointer parameters */
++	if (clu == NULL)
++		return FFS_ERROR;
++
++	/* acquire the lock for file system critical section */
++	down(&p_fs->v_sem);
++
++	fid->rwoffset = (s64)(clu_offset) << p_fs->cluster_size_bits;
++
++	if (EXFAT_I(inode)->mmu_private == 0)
++		num_clusters = 0;
++	else
++		num_clusters = (s32)((EXFAT_I(inode)->mmu_private - 1) >>
++				     p_fs->cluster_size_bits) + 1;
++
++	*clu = last_clu = fid->start_clu;
++
++	if (fid->flags == 0x03) {
++		if ((clu_offset > 0) && (*clu != CLUSTER_32(~0))) {
++			last_clu += clu_offset - 1;
++
++			if (clu_offset == num_clusters)
++				*clu = CLUSTER_32(~0);
++			else
++				*clu += clu_offset;
++		}
++	} else {
++		/* hint information */
++		if ((clu_offset > 0) && (fid->hint_last_off > 0) &&
++		    (clu_offset >= fid->hint_last_off)) {
++			clu_offset -= fid->hint_last_off;
++			*clu = fid->hint_last_clu;
++		}
++
++		while ((clu_offset > 0) && (*clu != CLUSTER_32(~0))) {
++			last_clu = *clu;
++			if (FAT_read(sb, *clu, clu) == -1) {
++				ret = FFS_MEDIAERR;
++				goto out;
++			}
++			clu_offset--;
++		}
++	}
++
++	if (*clu == CLUSTER_32(~0)) {
++		fs_set_vol_flags(sb, VOL_DIRTY);
++
++		new_clu.dir = (last_clu == CLUSTER_32(~0)) ? CLUSTER_32(~0) :
++					last_clu + 1;
++		new_clu.size = 0;
++		new_clu.flags = fid->flags;
++
++		/* (1) allocate a cluster */
++		num_alloced = p_fs->fs_func->alloc_cluster(sb, 1, &new_clu);
++		if (num_alloced < 0) {
++			ret = FFS_MEDIAERR;
++			goto out;
++		} else if (num_alloced == 0) {
++			ret = FFS_FULL;
++			goto out;
++		}
++
++		/* (2) append to the FAT chain */
++		if (last_clu == CLUSTER_32(~0)) {
++			if (new_clu.flags == 0x01)
++				fid->flags = 0x01;
++			fid->start_clu = new_clu.dir;
++			modified = TRUE;
++		} else {
++			if (new_clu.flags != fid->flags) {
++				exfat_chain_cont_cluster(sb, fid->start_clu,
++							 num_clusters);
++				fid->flags = 0x01;
++				modified = TRUE;
++			}
++			if (new_clu.flags == 0x01)
++				FAT_write(sb, last_clu, new_clu.dir);
++		}
++
++		num_clusters += num_alloced;
++		*clu = new_clu.dir;
++
++		if (p_fs->vol_type == EXFAT) {
++			es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
++						  ES_ALL_ENTRIES, &ep);
++			if (es == NULL) {
++				ret = FFS_MEDIAERR;
++				goto out;
++			}
++			/* get stream entry */
++			ep++;
++		}
++
++		/* (3) update directory entry */
++		if (modified) {
++			if (p_fs->vol_type != EXFAT) {
++				ep = get_entry_in_dir(sb, &(fid->dir),
++						      fid->entry, §or);
++				if (!ep) {
++					ret = FFS_MEDIAERR;
++					goto out;
++				}
++			}
++
++			if (p_fs->fs_func->get_entry_flag(ep) != fid->flags)
++				p_fs->fs_func->set_entry_flag(ep, fid->flags);
++
++			if (p_fs->fs_func->get_entry_clu0(ep) != fid->start_clu)
++				p_fs->fs_func->set_entry_clu0(ep,
++							      fid->start_clu);
++
++			if (p_fs->vol_type != EXFAT)
++				buf_modify(sb, sector);
++		}
++
++		if (p_fs->vol_type == EXFAT) {
++			update_dir_checksum_with_entry_set(sb, es);
++			release_entry_set(es);
++		}
++
++		/* add number of new blocks to inode */
++		inode->i_blocks += num_alloced << (p_fs->cluster_size_bits - 9);
++	}
++
++	/* hint information */
++	fid->hint_last_off = (s32)(fid->rwoffset >> p_fs->cluster_size_bits);
++	fid->hint_last_clu = *clu;
++
++	if (p_fs->dev_ejected)
++		ret = FFS_MEDIAERR;
++
++out:
++	/* release the lock for file system critical section */
++	up(&p_fs->v_sem);
++
++	return ret;
++}
++
++/*----------------------------------------------------------------------*/
++/*  Directory Operation Functions                                       */
++/*----------------------------------------------------------------------*/
++
++static int ffsCreateDir(struct inode *inode, char *path, struct file_id_t *fid)
++{
++	int ret = FFS_SUCCESS;
++	struct chain_t dir;
++	struct uni_name_t uni_name;
++	struct super_block *sb = inode->i_sb;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	pr_debug("%s entered\n", __func__);
++
++	/* check the validity of pointer parameters */
++	if ((fid == NULL) || (path == NULL) || (*path == '\0'))
++		return FFS_ERROR;
++
++	/* acquire the lock for file system critical section */
++	down(&p_fs->v_sem);
++
++	/* check the validity of directory name in the given old pathname */
++	ret = resolve_path(inode, path, &dir, &uni_name);
++	if (ret)
++		goto out;
++
++	fs_set_vol_flags(sb, VOL_DIRTY);
++
++	ret = create_dir(inode, &dir, &uni_name, fid);
++
++#ifdef CONFIG_EXFAT_DELAYED_SYNC
++	fs_sync(sb, false);
++	fs_set_vol_flags(sb, VOL_CLEAN);
++#endif
++
++	if (p_fs->dev_ejected)
++		ret = FFS_MEDIAERR;
++out:
++	/* release the lock for file system critical section */
++	up(&p_fs->v_sem);
++
++	return ret;
++}
++
++static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
++{
++	int i, dentry, clu_offset;
++	int ret = FFS_SUCCESS;
++	s32 dentries_per_clu, dentries_per_clu_bits = 0;
++	u32 type;
++	sector_t sector;
++	struct chain_t dir, clu;
++	struct uni_name_t uni_name;
++	struct timestamp_t tm;
++	struct dentry_t *ep;
++	struct super_block *sb = inode->i_sb;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct fs_func *fs_func = p_fs->fs_func;
++	struct file_id_t *fid = &(EXFAT_I(inode)->fid);
++
++	/* check the validity of pointer parameters */
++	if (dir_entry == NULL)
++		return FFS_ERROR;
++
++	/* check if the given file ID is opened */
++	if (fid->type != TYPE_DIR)
++		return FFS_PERMISSIONERR;
++
++	/* acquire the lock for file system critical section */
++	down(&p_fs->v_sem);
++
++	if (fid->entry == -1) {
++		dir.dir = p_fs->root_dir;
++		dir.flags = 0x01;
++	} else {
++		dir.dir = fid->start_clu;
++		dir.size = (s32)(fid->size >> p_fs->cluster_size_bits);
++		dir.flags = fid->flags;
++	}
++
++	dentry = (s32)fid->rwoffset;
++
++	if (dir.dir == CLUSTER_32(0)) {
++		/* FAT16 root_dir */
++		dentries_per_clu = p_fs->dentries_in_root;
++
++		if (dentry == dentries_per_clu) {
++			clu.dir = CLUSTER_32(~0);
++		} else {
++			clu.dir = dir.dir;
++			clu.size = dir.size;
++			clu.flags = dir.flags;
++		}
++	} else {
++		dentries_per_clu = p_fs->dentries_per_clu;
++		dentries_per_clu_bits = ilog2(dentries_per_clu);
++
++		clu_offset = dentry >> dentries_per_clu_bits;
++		clu.dir = dir.dir;
++		clu.size = dir.size;
++		clu.flags = dir.flags;
++
++		if (clu.flags == 0x03) {
++			clu.dir += clu_offset;
++			clu.size -= clu_offset;
++		} else {
++			/* hint_information */
++			if ((clu_offset > 0) && (fid->hint_last_off > 0) &&
++			    (clu_offset >= fid->hint_last_off)) {
++				clu_offset -= fid->hint_last_off;
++				clu.dir = fid->hint_last_clu;
++			}
++
++			while (clu_offset > 0) {
++				/* clu.dir = FAT_read(sb, clu.dir); */
++				if (FAT_read(sb, clu.dir, &clu.dir) == -1) {
++					ret = FFS_MEDIAERR;
++					goto out;
++				}
++				clu_offset--;
++			}
++		}
++	}
++
++	while (clu.dir != CLUSTER_32(~0)) {
++		if (p_fs->dev_ejected)
++			break;
++
++		if (dir.dir == CLUSTER_32(0)) /* FAT16 root_dir */
++			i = dentry % dentries_per_clu;
++		else
++			i = dentry & (dentries_per_clu-1);
++
++		for ( ; i < dentries_per_clu; i++, dentry++) {
++			ep = get_entry_in_dir(sb, &clu, i, §or);
++			if (!ep) {
++				ret = FFS_MEDIAERR;
++				goto out;
++			}
++			type = fs_func->get_entry_type(ep);
++
++			if (type == TYPE_UNUSED)
++				break;
++
++			if ((type != TYPE_FILE) && (type != TYPE_DIR))
++				continue;
++
++			buf_lock(sb, sector);
++			dir_entry->Attr = fs_func->get_entry_attr(ep);
++
++			fs_func->get_entry_time(ep, &tm, TM_CREATE);
++			dir_entry->CreateTimestamp.Year = tm.year;
++			dir_entry->CreateTimestamp.Month = tm.mon;
++			dir_entry->CreateTimestamp.Day = tm.day;
++			dir_entry->CreateTimestamp.Hour = tm.hour;
++			dir_entry->CreateTimestamp.Minute = tm.min;
++			dir_entry->CreateTimestamp.Second = tm.sec;
++			dir_entry->CreateTimestamp.MilliSecond = 0;
++
++			fs_func->get_entry_time(ep, &tm, TM_MODIFY);
++			dir_entry->ModifyTimestamp.Year = tm.year;
++			dir_entry->ModifyTimestamp.Month = tm.mon;
++			dir_entry->ModifyTimestamp.Day = tm.day;
++			dir_entry->ModifyTimestamp.Hour = tm.hour;
++			dir_entry->ModifyTimestamp.Minute = tm.min;
++			dir_entry->ModifyTimestamp.Second = tm.sec;
++			dir_entry->ModifyTimestamp.MilliSecond = 0;
++
++			memset((char *)&dir_entry->AccessTimestamp, 0,
++			       sizeof(struct date_time_t));
++
++			*(uni_name.name) = 0x0;
++			fs_func->get_uni_name_from_ext_entry(sb, &dir, dentry,
++							     uni_name.name);
++			if (*uni_name.name == 0x0 && p_fs->vol_type != EXFAT)
++				get_uni_name_from_dos_entry(sb,
++						(struct dos_dentry_t *)ep,
++						&uni_name, 0x1);
++			nls_uniname_to_cstring(sb, dir_entry->Name, &uni_name);
++			buf_unlock(sb, sector);
++
++			if (p_fs->vol_type == EXFAT) {
++				ep = get_entry_in_dir(sb, &clu, i+1, NULL);
++				if (!ep) {
++					ret = FFS_MEDIAERR;
++					goto out;
++				}
++			} else {
++				get_uni_name_from_dos_entry(sb,
++						(struct dos_dentry_t *)ep,
++						&uni_name, 0x0);
++				nls_uniname_to_cstring(sb, dir_entry->ShortName,
++						       &uni_name);
++			}
++
++			dir_entry->Size = fs_func->get_entry_size(ep);
++
++			/* hint information */
++			if (dir.dir == CLUSTER_32(0)) { /* FAT16 root_dir */
++			} else {
++				fid->hint_last_off = dentry >>
++							dentries_per_clu_bits;
++				fid->hint_last_clu = clu.dir;
++			}
++
++			fid->rwoffset = (s64) ++dentry;
++
++			if (p_fs->dev_ejected)
++				ret = FFS_MEDIAERR;
++			goto out;
++		}
++
++		if (dir.dir == CLUSTER_32(0))
++			break; /* FAT16 root_dir */
++
++		if (clu.flags == 0x03) {
++			if ((--clu.size) > 0)
++				clu.dir++;
++			else
++				clu.dir = CLUSTER_32(~0);
++		} else {
++			/* clu.dir = FAT_read(sb, clu.dir); */
++			if (FAT_read(sb, clu.dir, &clu.dir) == -1) {
++				ret = FFS_MEDIAERR;
++				goto out;
++			}
++		}
++	}
++
++	*(dir_entry->Name) = '\0';
++
++	fid->rwoffset = (s64) ++dentry;
++
++	if (p_fs->dev_ejected)
++		ret = FFS_MEDIAERR;
++
++out:
++	/* release the lock for file system critical section */
++	up(&p_fs->v_sem);
++
++	return ret;
++}
++
++static int ffsRemoveDir(struct inode *inode, struct file_id_t *fid)
++{
++	s32 dentry;
++	int ret = FFS_SUCCESS;
++	struct chain_t dir, clu_to_free;
++	struct super_block *sb = inode->i_sb;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	/* check the validity of the given file id */
++	if (fid == NULL)
++		return FFS_INVALIDFID;
++
++	dir.dir = fid->dir.dir;
++	dir.size = fid->dir.size;
++	dir.flags = fid->dir.flags;
++
++	dentry = fid->entry;
++
++	/* check if the file is "." or ".." */
++	if (p_fs->vol_type != EXFAT) {
++		if ((dir.dir != p_fs->root_dir) && (dentry < 2))
++			return FFS_PERMISSIONERR;
++	}
++
++	/* acquire the lock for file system critical section */
++	down(&p_fs->v_sem);
++
++	clu_to_free.dir = fid->start_clu;
++	clu_to_free.size = (s32)((fid->size-1) >> p_fs->cluster_size_bits) + 1;
++	clu_to_free.flags = fid->flags;
++
++	if (!is_dir_empty(sb, &clu_to_free)) {
++		ret = FFS_FILEEXIST;
++		goto out;
++	}
++
++	fs_set_vol_flags(sb, VOL_DIRTY);
++
++	/* (1) update the directory entry */
++	remove_file(inode, &dir, dentry);
++
++	/* (2) free the clusters */
++	p_fs->fs_func->free_cluster(sb, &clu_to_free, 1);
++
++	fid->size = 0;
++	fid->start_clu = CLUSTER_32(~0);
++	fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01;
++
++#ifdef CONFIG_EXFAT_DELAYED_SYNC
++	fs_sync(sb, false);
++	fs_set_vol_flags(sb, VOL_CLEAN);
++#endif
++
++	if (p_fs->dev_ejected)
++		ret = FFS_MEDIAERR;
++
++out:
++	/* release the lock for file system critical section */
++	up(&p_fs->v_sem);
++
++	return ret;
++}
++
++/*======================================================================*/
++/*  Directory Entry Operations                                          */
++/*======================================================================*/
++
++static int exfat_readdir(struct file *filp, struct dir_context *ctx)
++{
++	struct inode *inode = file_inode(filp);
++	struct super_block *sb = inode->i_sb;
++	struct exfat_sb_info *sbi = EXFAT_SB(sb);
++	struct fs_info_t *p_fs = &(sbi->fs_info);
++	struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
++	struct dir_entry_t de;
++	unsigned long inum;
++	loff_t cpos;
++	int err = 0;
++
++	__lock_super(sb);
++
++	cpos = ctx->pos;
++	/* Fake . and .. for the root directory. */
++	if ((p_fs->vol_type == EXFAT) || (inode->i_ino == EXFAT_ROOT_INO)) {
++		while (cpos < 2) {
++			if (inode->i_ino == EXFAT_ROOT_INO)
++				inum = EXFAT_ROOT_INO;
++			else if (cpos == 0)
++				inum = inode->i_ino;
++			else /* (cpos == 1) */
++				inum = parent_ino(filp->f_path.dentry);
++
++			if (!dir_emit_dots(filp, ctx))
++				goto out;
++			cpos++;
++			ctx->pos++;
++		}
++		if (cpos == 2)
++			cpos = 0;
++	}
++	if (cpos & (DENTRY_SIZE - 1)) {
++		err = -ENOENT;
++		goto out;
++	}
++
++get_new:
++	EXFAT_I(inode)->fid.size = i_size_read(inode);
++	EXFAT_I(inode)->fid.rwoffset = cpos >> DENTRY_SIZE_BITS;
++
++	err = ffsReadDir(inode, &de);
++	if (err) {
++		/* at least we tried to read a sector
++		 * move cpos to next sector position (should be aligned)
++		 */
++		if (err == FFS_MEDIAERR) {
++			cpos += 1 << p_bd->sector_size_bits;
++			cpos &= ~((1 << p_bd->sector_size_bits)-1);
++		}
++
++		err = -EIO;
++		goto end_of_dir;
++	}
++
++	cpos = EXFAT_I(inode)->fid.rwoffset << DENTRY_SIZE_BITS;
++
++	if (!de.Name[0])
++		goto end_of_dir;
++
++	if (!memcmp(de.ShortName, DOS_CUR_DIR_NAME, DOS_NAME_LENGTH)) {
++		inum = inode->i_ino;
++	} else if (!memcmp(de.ShortName, DOS_PAR_DIR_NAME, DOS_NAME_LENGTH)) {
++		inum = parent_ino(filp->f_path.dentry);
++	} else {
++		loff_t i_pos = ((loff_t) EXFAT_I(inode)->fid.start_clu << 32) |
++				((EXFAT_I(inode)->fid.rwoffset-1) & 0xffffffff);
++		struct inode *tmp = exfat_iget(sb, i_pos);
++
++		if (tmp) {
++			inum = tmp->i_ino;
++			iput(tmp);
++		} else {
++			inum = iunique(sb, EXFAT_ROOT_INO);
++		}
++	}
++
++	if (!dir_emit(ctx, de.Name, strlen(de.Name), inum,
++		      (de.Attr & ATTR_SUBDIR) ? DT_DIR : DT_REG))
++		goto out;
++
++	ctx->pos = cpos;
++	goto get_new;
++
++end_of_dir:
++	ctx->pos = cpos;
++out:
++	__unlock_super(sb);
++	return err;
++}
++
++static int exfat_ioctl_volume_id(struct inode *dir)
++{
++	struct super_block *sb = dir->i_sb;
++	struct exfat_sb_info *sbi = EXFAT_SB(sb);
++	struct fs_info_t *p_fs = &(sbi->fs_info);
++
++	return p_fs->vol_id;
++}
++
++static long exfat_generic_ioctl(struct file *filp, unsigned int cmd,
++				unsigned long arg)
++{
++struct inode *inode = filp->f_path.dentry->d_inode;
++#ifdef CONFIG_EXFAT_KERNEL_DEBUG
++	unsigned int flags;
++#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
++
++	switch (cmd) {
++	case EXFAT_IOCTL_GET_VOLUME_ID:
++		return exfat_ioctl_volume_id(inode);
++#ifdef CONFIG_EXFAT_KERNEL_DEBUG
++	case EXFAT_IOC_GET_DEBUGFLAGS: {
++		struct super_block *sb = inode->i_sb;
++		struct exfat_sb_info *sbi = EXFAT_SB(sb);
++
++		flags = sbi->debug_flags;
++		return put_user(flags, (int __user *)arg);
++	}
++	case EXFAT_IOC_SET_DEBUGFLAGS: {
++		struct super_block *sb = inode->i_sb;
++		struct exfat_sb_info *sbi = EXFAT_SB(sb);
++
++		if (!capable(CAP_SYS_ADMIN))
++			return -EPERM;
++
++		if (get_user(flags, (int __user *) arg))
++			return -EFAULT;
++
++		__lock_super(sb);
++		sbi->debug_flags = flags;
++		__unlock_super(sb);
++
++		return 0;
++	}
++#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
++	default:
++		return -ENOTTY; /* Inappropriate ioctl for device */
++	}
++}
++
++static const struct file_operations exfat_dir_operations = {
++	.llseek     = generic_file_llseek,
++	.read       = generic_read_dir,
++	.iterate    = exfat_readdir,
++	.unlocked_ioctl = exfat_generic_ioctl,
++	.fsync      = generic_file_fsync,
++};
++
++static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
++			bool excl)
++{
++	struct super_block *sb = dir->i_sb;
++	struct inode *inode;
++	struct file_id_t fid;
++	loff_t i_pos;
++	int err;
++
++	__lock_super(sb);
++
++	pr_debug("%s entered\n", __func__);
++
++	err = ffsCreateFile(dir, (u8 *) dentry->d_name.name, FM_REGULAR, &fid);
++	if (err) {
++		if (err == FFS_INVALIDPATH)
++			err = -EINVAL;
++		else if (err == FFS_FILEEXIST)
++			err = -EEXIST;
++		else if (err == FFS_FULL)
++			err = -ENOSPC;
++		else if (err == FFS_NAMETOOLONG)
++			err = -ENAMETOOLONG;
++		else
++			err = -EIO;
++		goto out;
++	}
++	INC_IVERSION(dir);
++	dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(dir);
++	if (IS_DIRSYNC(dir))
++		(void) exfat_sync_inode(dir);
++	else
++		mark_inode_dirty(dir);
++
++	i_pos = ((loff_t) fid.dir.dir << 32) | (fid.entry & 0xffffffff);
++
++	inode = exfat_build_inode(sb, &fid, i_pos);
++	if (IS_ERR(inode)) {
++		err = PTR_ERR(inode);
++		goto out;
++	}
++	INC_IVERSION(inode);
++	inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
++	/*
++	 * timestamp is already written, so mark_inode_dirty() is unnecessary.
++	 */
++
++	dentry->d_time = GET_IVERSION(dentry->d_parent->d_inode);
++	d_instantiate(dentry, inode);
++
++out:
++	__unlock_super(sb);
++	pr_debug("%s exited\n", __func__);
++	return err;
++}
++
++static int exfat_find(struct inode *dir, struct qstr *qname,
++		      struct file_id_t *fid)
++{
++	int err;
++
++	if (qname->len == 0)
++		return -ENOENT;
++
++	err = ffsLookupFile(dir, (u8 *) qname->name, fid);
++	if (err)
++		return -ENOENT;
++
++	return 0;
++}
++
++static int exfat_d_anon_disconn(struct dentry *dentry)
++{
++	return IS_ROOT(dentry) && (dentry->d_flags & DCACHE_DISCONNECTED);
++}
++
++static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry,
++				   unsigned int flags)
++{
++	struct super_block *sb = dir->i_sb;
++	struct inode *inode;
++	struct dentry *alias;
++	int err;
++	struct file_id_t fid;
++	loff_t i_pos;
++	u64 ret;
++	mode_t i_mode;
++
++	__lock_super(sb);
++	pr_debug("%s entered\n", __func__);
++	err = exfat_find(dir, &dentry->d_name, &fid);
++	if (err) {
++		if (err == -ENOENT) {
++			inode = NULL;
++			goto out;
++		}
++		goto error;
++	}
++
++	i_pos = ((loff_t) fid.dir.dir << 32) | (fid.entry & 0xffffffff);
++	inode = exfat_build_inode(sb, &fid, i_pos);
++	if (IS_ERR(inode)) {
++		err = PTR_ERR(inode);
++		goto error;
++	}
++
++	i_mode = inode->i_mode;
++	if (S_ISLNK(i_mode) && !EXFAT_I(inode)->target) {
++		EXFAT_I(inode)->target = kmalloc(i_size_read(inode) + 1,
++						 GFP_KERNEL);
++		if (!EXFAT_I(inode)->target) {
++			err = -ENOMEM;
++			goto error;
++		}
++		ffsReadFile(dir, &fid, EXFAT_I(inode)->target,
++			    i_size_read(inode), &ret);
++		*(EXFAT_I(inode)->target + i_size_read(inode)) = '\0';
++	}
++
++	alias = d_find_alias(inode);
++	if (alias && !exfat_d_anon_disconn(alias)) {
++		BUG_ON(d_unhashed(alias));
++		if (!S_ISDIR(i_mode))
++			d_move(alias, dentry);
++		iput(inode);
++		__unlock_super(sb);
++		pr_debug("%s exited 1\n", __func__);
++		return alias;
++	}
++	dput(alias);
++out:
++	__unlock_super(sb);
++	dentry->d_time = GET_IVERSION(dentry->d_parent->d_inode);
++	dentry = d_splice_alias(inode, dentry);
++	if (dentry)
++		dentry->d_time = GET_IVERSION(dentry->d_parent->d_inode);
++	pr_debug("%s exited 2\n", __func__);
++	return dentry;
++
++error:
++	__unlock_super(sb);
++	pr_debug("%s exited 3\n", __func__);
++	return ERR_PTR(err);
++}
++
++static inline unsigned long exfat_hash(loff_t i_pos)
++{
++	return hash_32(i_pos, EXFAT_HASH_BITS);
++}
++
++static void exfat_attach(struct inode *inode, loff_t i_pos)
++{
++	struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb);
++	struct hlist_head *head = sbi->inode_hashtable + exfat_hash(i_pos);
++
++	spin_lock(&sbi->inode_hash_lock);
++	EXFAT_I(inode)->i_pos = i_pos;
++	hlist_add_head(&EXFAT_I(inode)->i_hash_fat, head);
++	spin_unlock(&sbi->inode_hash_lock);
++}
++
++static void exfat_detach(struct inode *inode)
++{
++	struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb);
++
++	spin_lock(&sbi->inode_hash_lock);
++	hlist_del_init(&EXFAT_I(inode)->i_hash_fat);
++	EXFAT_I(inode)->i_pos = 0;
++	spin_unlock(&sbi->inode_hash_lock);
++}
++
++static int exfat_unlink(struct inode *dir, struct dentry *dentry)
++{
++	struct inode *inode = dentry->d_inode;
++	struct super_block *sb = dir->i_sb;
++	int err;
++
++	__lock_super(sb);
++
++	pr_debug("%s entered\n", __func__);
++
++	EXFAT_I(inode)->fid.size = i_size_read(inode);
++
++	err = ffsRemoveFile(dir, &(EXFAT_I(inode)->fid));
++	if (err) {
++		if (err == FFS_PERMISSIONERR)
++			err = -EPERM;
++		else
++			err = -EIO;
++		goto out;
++	}
++	INC_IVERSION(dir);
++	dir->i_mtime = dir->i_atime = current_time(dir);
++	if (IS_DIRSYNC(dir))
++		(void) exfat_sync_inode(dir);
++	else
++		mark_inode_dirty(dir);
++
++	clear_nlink(inode);
++	inode->i_mtime = inode->i_atime = current_time(inode);
++	exfat_detach(inode);
++	remove_inode_hash(inode);
++
++out:
++	__unlock_super(sb);
++	pr_debug("%s exited\n", __func__);
++	return err;
++}
++
++static int exfat_symlink(struct inode *dir, struct dentry *dentry,
++			 const char *target)
++{
++	struct super_block *sb = dir->i_sb;
++	struct inode *inode;
++	struct file_id_t fid;
++	loff_t i_pos;
++	int err;
++	u64 len = (u64) strlen(target);
++	u64 ret;
++
++	__lock_super(sb);
++
++	pr_debug("%s entered\n", __func__);
++
++	err = ffsCreateFile(dir, (u8 *) dentry->d_name.name, FM_SYMLINK, &fid);
++	if (err) {
++		if (err == FFS_INVALIDPATH)
++			err = -EINVAL;
++		else if (err == FFS_FILEEXIST)
++			err = -EEXIST;
++		else if (err == FFS_FULL)
++			err = -ENOSPC;
++		else
++			err = -EIO;
++		goto out;
++	}
++
++	err = ffsWriteFile(dir, &fid, (char *) target, len, &ret);
++
++	if (err) {
++		ffsRemoveFile(dir, &fid);
++
++		if (err == FFS_FULL)
++			err = -ENOSPC;
++		else
++			err = -EIO;
++		goto out;
++	}
++
++	INC_IVERSION(dir);
++	dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(dir);
++	if (IS_DIRSYNC(dir))
++		(void) exfat_sync_inode(dir);
++	else
++		mark_inode_dirty(dir);
++
++	i_pos = ((loff_t) fid.dir.dir << 32) | (fid.entry & 0xffffffff);
++
++	inode = exfat_build_inode(sb, &fid, i_pos);
++	if (IS_ERR(inode)) {
++		err = PTR_ERR(inode);
++		goto out;
++	}
++	INC_IVERSION(inode);
++	inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
++	/* timestamp is already written, so mark_inode_dirty() is unneeded. */
++
++	EXFAT_I(inode)->target = kmalloc(len+1, GFP_KERNEL);
++	if (!EXFAT_I(inode)->target) {
++		err = -ENOMEM;
++		goto out;
++	}
++	memcpy(EXFAT_I(inode)->target, target, len+1);
++
++	dentry->d_time = GET_IVERSION(dentry->d_parent->d_inode);
++	d_instantiate(dentry, inode);
++
++out:
++	__unlock_super(sb);
++	pr_debug("%s exited\n", __func__);
++	return err;
++}
++
++static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
++{
++	struct super_block *sb = dir->i_sb;
++	struct inode *inode;
++	struct file_id_t fid;
++	loff_t i_pos;
++	int err;
++
++	__lock_super(sb);
++
++	pr_debug("%s entered\n", __func__);
++
++	err = ffsCreateDir(dir, (u8 *) dentry->d_name.name, &fid);
++	if (err) {
++		if (err == FFS_INVALIDPATH)
++			err = -EINVAL;
++		else if (err == FFS_FILEEXIST)
++			err = -EEXIST;
++		else if (err == FFS_FULL)
++			err = -ENOSPC;
++		else if (err == FFS_NAMETOOLONG)
++			err = -ENAMETOOLONG;
++		else
++			err = -EIO;
++		goto out;
++	}
++	INC_IVERSION(dir);
++	dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(dir);
++	if (IS_DIRSYNC(dir))
++		(void) exfat_sync_inode(dir);
++	else
++		mark_inode_dirty(dir);
++	inc_nlink(dir);
++
++	i_pos = ((loff_t) fid.dir.dir << 32) | (fid.entry & 0xffffffff);
++
++	inode = exfat_build_inode(sb, &fid, i_pos);
++	if (IS_ERR(inode)) {
++		err = PTR_ERR(inode);
++		goto out;
++	}
++	INC_IVERSION(inode);
++	inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
++	/* timestamp is already written, so mark_inode_dirty() is unneeded. */
++
++	dentry->d_time = GET_IVERSION(dentry->d_parent->d_inode);
++	d_instantiate(dentry, inode);
++
++out:
++	__unlock_super(sb);
++	pr_debug("%s exited\n", __func__);
++	return err;
++}
++
++static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
++{
++	struct inode *inode = dentry->d_inode;
++	struct super_block *sb = dir->i_sb;
++	int err;
++
++	__lock_super(sb);
++
++	pr_debug("%s entered\n", __func__);
++
++	EXFAT_I(inode)->fid.size = i_size_read(inode);
++
++	err = ffsRemoveDir(dir, &(EXFAT_I(inode)->fid));
++	if (err) {
++		if (err == FFS_INVALIDPATH)
++			err = -EINVAL;
++		else if (err == FFS_FILEEXIST)
++			err = -ENOTEMPTY;
++		else if (err == FFS_NOTFOUND)
++			err = -ENOENT;
++		else if (err == FFS_DIRBUSY)
++			err = -EBUSY;
++		else
++			err = -EIO;
++		goto out;
++	}
++	INC_IVERSION(dir);
++	dir->i_mtime = dir->i_atime = current_time(dir);
++	if (IS_DIRSYNC(dir))
++		(void) exfat_sync_inode(dir);
++	else
++		mark_inode_dirty(dir);
++	drop_nlink(dir);
++
++	clear_nlink(inode);
++	inode->i_mtime = inode->i_atime = current_time(inode);
++	exfat_detach(inode);
++	remove_inode_hash(inode);
++
++out:
++	__unlock_super(sb);
++	pr_debug("%s exited\n", __func__);
++	return err;
++}
++
++static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry,
++			struct inode *new_dir, struct dentry *new_dentry,
++			unsigned int flags)
++{
++	struct inode *old_inode, *new_inode;
++	struct super_block *sb = old_dir->i_sb;
++	loff_t i_pos;
++	int err;
++
++	if (flags)
++		return -EINVAL;
++
++	__lock_super(sb);
++
++	pr_debug("%s entered\n", __func__);
++
++	old_inode = old_dentry->d_inode;
++	new_inode = new_dentry->d_inode;
++
++	EXFAT_I(old_inode)->fid.size = i_size_read(old_inode);
++
++	err = ffsMoveFile(old_dir, &(EXFAT_I(old_inode)->fid), new_dir,
++			  new_dentry);
++	if (err) {
++		if (err == FFS_PERMISSIONERR)
++			err = -EPERM;
++		else if (err == FFS_INVALIDPATH)
++			err = -EINVAL;
++		else if (err == FFS_FILEEXIST)
++			err = -EEXIST;
++		else if (err == FFS_NOTFOUND)
++			err = -ENOENT;
++		else if (err == FFS_FULL)
++			err = -ENOSPC;
++		else
++			err = -EIO;
++		goto out;
++	}
++	INC_IVERSION(new_dir);
++	new_dir->i_ctime = new_dir->i_mtime = new_dir->i_atime =
++				current_time(new_dir);
++	if (IS_DIRSYNC(new_dir))
++		(void) exfat_sync_inode(new_dir);
++	else
++		mark_inode_dirty(new_dir);
++
++	i_pos = ((loff_t) EXFAT_I(old_inode)->fid.dir.dir << 32) |
++			(EXFAT_I(old_inode)->fid.entry & 0xffffffff);
++
++	exfat_detach(old_inode);
++	exfat_attach(old_inode, i_pos);
++	if (IS_DIRSYNC(new_dir))
++		(void) exfat_sync_inode(old_inode);
++	else
++		mark_inode_dirty(old_inode);
++
++	if ((S_ISDIR(old_inode->i_mode)) && (old_dir != new_dir)) {
++		drop_nlink(old_dir);
++		if (!new_inode)
++			inc_nlink(new_dir);
++	}
++	INC_IVERSION(old_dir);
++	old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir);
++	if (IS_DIRSYNC(old_dir))
++		(void) exfat_sync_inode(old_dir);
++	else
++		mark_inode_dirty(old_dir);
++
++	if (new_inode) {
++		exfat_detach(new_inode);
++		drop_nlink(new_inode);
++		if (S_ISDIR(new_inode->i_mode))
++			drop_nlink(new_inode);
++		new_inode->i_ctime = current_time(new_inode);
++	}
++
++out:
++	__unlock_super(sb);
++	pr_debug("%s exited\n", __func__);
++	return err;
++}
++
++static int exfat_cont_expand(struct inode *inode, loff_t size)
++{
++	struct address_space *mapping = inode->i_mapping;
++	loff_t start = i_size_read(inode), count = size - i_size_read(inode);
++	int err, err2;
++
++	err = generic_cont_expand_simple(inode, size);
++	if (err != 0)
++		return err;
++
++	inode->i_ctime = inode->i_mtime = current_time(inode);
++	mark_inode_dirty(inode);
++
++	if (IS_SYNC(inode)) {
++		err = filemap_fdatawrite_range(mapping, start,
++					       start + count - 1);
++		err2 = sync_mapping_buffers(mapping);
++		err = (err) ? (err) : (err2);
++		err2 = write_inode_now(inode, 1);
++		err = (err) ? (err) : (err2);
++		if (!err)
++			err =  filemap_fdatawait_range(mapping, start,
++						       start + count - 1);
++	}
++	return err;
++}
++
++static int exfat_allow_set_time(struct exfat_sb_info *sbi, struct inode *inode)
++{
++	mode_t allow_utime = sbi->options.allow_utime;
++
++	if (!uid_eq(current_fsuid(), inode->i_uid)) {
++		if (in_group_p(inode->i_gid))
++			allow_utime >>= 3;
++		if (allow_utime & MAY_WRITE)
++			return 1;
++	}
++
++	/* use a default check */
++	return 0;
++}
++
++static int exfat_sanitize_mode(const struct exfat_sb_info *sbi,
++			       struct inode *inode, umode_t *mode_ptr)
++{
++	mode_t i_mode, mask, perm;
++
++	i_mode = inode->i_mode;
++
++	if (S_ISREG(i_mode) || S_ISLNK(i_mode))
++		mask = sbi->options.fs_fmask;
++	else
++		mask = sbi->options.fs_dmask;
++
++	perm = *mode_ptr & ~(S_IFMT | mask);
++
++	/* Of the r and x bits, all (subject to umask) must be present.*/
++	if ((perm & 0555) != (i_mode & 0555))
++		return -EPERM;
++
++	if (exfat_mode_can_hold_ro(inode)) {
++		/*
++		 * Of the w bits, either all (subject to umask) or none must be
++		 * present.
++		 */
++		if ((perm & 0222) && ((perm & 0222) != (0222 & ~mask)))
++			return -EPERM;
++	} else {
++		/*
++		 * If exfat_mode_can_hold_ro(inode) is false, can't change w
++		 * bits.
++		 */
++		if ((perm & 0222) != (0222 & ~mask))
++			return -EPERM;
++	}
++
++	*mode_ptr &= S_IFMT | perm;
++
++	return 0;
++}
++
++static void exfat_truncate(struct inode *inode, loff_t old_size)
++{
++	struct super_block *sb = inode->i_sb;
++	struct exfat_sb_info *sbi = EXFAT_SB(sb);
++	struct fs_info_t *p_fs = &(sbi->fs_info);
++	int err;
++
++	__lock_super(sb);
++
++	/*
++	 * This protects against truncating a file bigger than it was then
++	 * trying to write into the hole.
++	 */
++	if (EXFAT_I(inode)->mmu_private > i_size_read(inode))
++		EXFAT_I(inode)->mmu_private = i_size_read(inode);
++
++	if (EXFAT_I(inode)->fid.start_clu == 0)
++		goto out;
++
++	err = ffsTruncateFile(inode, old_size, i_size_read(inode));
++	if (err)
++		goto out;
++
++	inode->i_ctime = inode->i_mtime = current_time(inode);
++	if (IS_DIRSYNC(inode))
++		(void) exfat_sync_inode(inode);
++	else
++		mark_inode_dirty(inode);
++
++	inode->i_blocks = ((i_size_read(inode) + (p_fs->cluster_size - 1)) &
++			   ~((loff_t)p_fs->cluster_size - 1)) >> 9;
++out:
++	__unlock_super(sb);
++}
++
++static int exfat_setattr(struct dentry *dentry, struct iattr *attr)
++{
++
++	struct exfat_sb_info *sbi = EXFAT_SB(dentry->d_sb);
++	struct inode *inode = dentry->d_inode;
++	unsigned int ia_valid;
++	int error;
++	loff_t old_size;
++
++	pr_debug("%s entered\n", __func__);
++
++	if ((attr->ia_valid & ATTR_SIZE)
++		&& (attr->ia_size > i_size_read(inode))) {
++		error = exfat_cont_expand(inode, attr->ia_size);
++		if (error || attr->ia_valid == ATTR_SIZE)
++			return error;
++		attr->ia_valid &= ~ATTR_SIZE;
++	}
++
++	ia_valid = attr->ia_valid;
++
++	if ((ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET))
++		&& exfat_allow_set_time(sbi, inode)) {
++		attr->ia_valid &= ~(ATTR_MTIME_SET |
++				    ATTR_ATIME_SET |
++				    ATTR_TIMES_SET);
++	}
++
++	error = setattr_prepare(dentry, attr);
++	attr->ia_valid = ia_valid;
++	if (error)
++		return error;
++
++	if (((attr->ia_valid & ATTR_UID) &&
++	     (!uid_eq(attr->ia_uid, sbi->options.fs_uid))) ||
++	    ((attr->ia_valid & ATTR_GID) &&
++	     (!gid_eq(attr->ia_gid, sbi->options.fs_gid))) ||
++	    ((attr->ia_valid & ATTR_MODE) &&
++	     (attr->ia_mode & ~(S_IFREG | S_IFLNK | S_IFDIR | 0777)))) {
++		return -EPERM;
++	}
++
++	/*
++	 * We don't return -EPERM here. Yes, strange, but this is too
++	 * old behavior.
++	 */
++	if (attr->ia_valid & ATTR_MODE) {
++		if (exfat_sanitize_mode(sbi, inode, &attr->ia_mode) < 0)
++			attr->ia_valid &= ~ATTR_MODE;
++	}
++
++	EXFAT_I(inode)->fid.size = i_size_read(inode);
++
++	if (attr->ia_valid & ATTR_SIZE) {
++		old_size = i_size_read(inode);
++		down_write(&EXFAT_I(inode)->truncate_lock);
++		truncate_setsize(inode, attr->ia_size);
++		exfat_truncate(inode, old_size);
++		up_write(&EXFAT_I(inode)->truncate_lock);
++	}
++	setattr_copy(inode, attr);
++	mark_inode_dirty(inode);
++
++	pr_debug("%s exited\n", __func__);
++	return error;
++}
++
++static int exfat_getattr(const struct path *path, struct kstat *stat,
++			 u32 request_mask, unsigned int flags)
++{
++	struct inode *inode = path->dentry->d_inode;
++
++	pr_debug("%s entered\n", __func__);
++
++	generic_fillattr(inode, stat);
++	stat->blksize = EXFAT_SB(inode->i_sb)->fs_info.cluster_size;
++
++	pr_debug("%s exited\n", __func__);
++	return 0;
++}
++
++static const struct inode_operations exfat_dir_inode_operations = {
++	.create        = exfat_create,
++	.lookup        = exfat_lookup,
++	.unlink        = exfat_unlink,
++	.symlink       = exfat_symlink,
++	.mkdir         = exfat_mkdir,
++	.rmdir         = exfat_rmdir,
++	.rename        = exfat_rename,
++	.setattr       = exfat_setattr,
++	.getattr       = exfat_getattr,
++};
++
++/*======================================================================*/
++/*  File Operations                                                     */
++/*======================================================================*/
++static const char *exfat_get_link(struct dentry *dentry, struct inode *inode,
++				  struct delayed_call *done)
++{
++	struct exfat_inode_info *ei = EXFAT_I(inode);
++
++	if (ei->target != NULL) {
++		char *cookie = ei->target;
++
++		if (cookie != NULL)
++			return (char *)(ei->target);
++	}
++	return NULL;
++}
++
++static const struct inode_operations exfat_symlink_inode_operations = {
++		.get_link = exfat_get_link,
++};
++
++static int exfat_file_release(struct inode *inode, struct file *filp)
++{
++	struct super_block *sb = inode->i_sb;
++
++	EXFAT_I(inode)->fid.size = i_size_read(inode);
++	ffsSyncVol(sb, false);
++	return 0;
++}
++
++static const struct file_operations exfat_file_operations = {
++	.llseek      = generic_file_llseek,
++	.read_iter   = generic_file_read_iter,
++	.write_iter  = generic_file_write_iter,
++	.mmap        = generic_file_mmap,
++	.release     = exfat_file_release,
++	.unlocked_ioctl  = exfat_generic_ioctl,
++	.fsync       = generic_file_fsync,
++	.splice_read = generic_file_splice_read,
++};
++
++static const struct inode_operations exfat_file_inode_operations = {
++	.setattr     = exfat_setattr,
++	.getattr     = exfat_getattr,
++};
++
++/*======================================================================*/
++/*  Address Space Operations                                            */
++/*======================================================================*/
++
++static int exfat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
++		      unsigned long *mapped_blocks, int *create)
++{
++	struct super_block *sb = inode->i_sb;
++	struct exfat_sb_info *sbi = EXFAT_SB(sb);
++	struct fs_info_t *p_fs = &(sbi->fs_info);
++	struct bd_info_t *p_bd = &(sbi->bd_info);
++	const unsigned long blocksize = sb->s_blocksize;
++	const unsigned char blocksize_bits = sb->s_blocksize_bits;
++	sector_t last_block;
++	int err, clu_offset, sec_offset;
++	unsigned int cluster;
++
++	*phys = 0;
++	*mapped_blocks = 0;
++
++	if ((p_fs->vol_type == FAT12) || (p_fs->vol_type == FAT16)) {
++		if (inode->i_ino == EXFAT_ROOT_INO) {
++			if (sector <
++			    (p_fs->dentries_in_root >>
++			     (p_bd->sector_size_bits-DENTRY_SIZE_BITS))) {
++				*phys = sector + p_fs->root_start_sector;
++				*mapped_blocks = 1;
++			}
++			return 0;
++		}
++	}
++
++	last_block = (i_size_read(inode) + (blocksize - 1)) >> blocksize_bits;
++	if (sector >= last_block) {
++		if (*create == 0)
++			return 0;
++	} else {
++		*create = 0;
++	}
++
++	/* cluster offset */
++	clu_offset = sector >> p_fs->sectors_per_clu_bits;
++
++	/* sector offset in cluster */
++	sec_offset = sector & (p_fs->sectors_per_clu - 1);
++
++	EXFAT_I(inode)->fid.size = i_size_read(inode);
++
++	err = ffsMapCluster(inode, clu_offset, &cluster);
++
++	if (err) {
++		if (err == FFS_FULL)
++			return -ENOSPC;
++		else
++			return -EIO;
++	} else if (cluster != CLUSTER_32(~0)) {
++		*phys = START_SECTOR(cluster) + sec_offset;
++		*mapped_blocks = p_fs->sectors_per_clu - sec_offset;
++	}
++
++	return 0;
++}
++
++static int exfat_get_block(struct inode *inode, sector_t iblock,
++			   struct buffer_head *bh_result, int create)
++{
++	struct super_block *sb = inode->i_sb;
++	unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits;
++	int err;
++	unsigned long mapped_blocks;
++	sector_t phys;
++
++	__lock_super(sb);
++
++	err = exfat_bmap(inode, iblock, &phys, &mapped_blocks, &create);
++	if (err) {
++		__unlock_super(sb);
++		return err;
++	}
++
++	if (phys) {
++		max_blocks = min(mapped_blocks, max_blocks);
++		if (create) {
++			EXFAT_I(inode)->mmu_private += max_blocks <<
++							sb->s_blocksize_bits;
++			set_buffer_new(bh_result);
++		}
++		map_bh(bh_result, sb, phys);
++	}
++
++	bh_result->b_size = max_blocks << sb->s_blocksize_bits;
++	__unlock_super(sb);
++
++	return 0;
++}
++
++static int exfat_readpage(struct file *file, struct page *page)
++{
++	return  mpage_readpage(page, exfat_get_block);
++}
++
++static int exfat_readpages(struct file *file, struct address_space *mapping,
++			   struct list_head *pages, unsigned int nr_pages)
++{
++	return  mpage_readpages(mapping, pages, nr_pages, exfat_get_block);
++}
++
++static int exfat_writepage(struct page *page, struct writeback_control *wbc)
++{
++	return block_write_full_page(page, exfat_get_block, wbc);
++}
++
++static int exfat_writepages(struct address_space *mapping,
++			    struct writeback_control *wbc)
++{
++	return mpage_writepages(mapping, wbc, exfat_get_block);
++}
++
++static void exfat_write_failed(struct address_space *mapping, loff_t to)
++{
++	struct inode *inode = mapping->host;
++
++	if (to > i_size_read(inode)) {
++		truncate_pagecache(inode, i_size_read(inode));
++		EXFAT_I(inode)->fid.size = i_size_read(inode);
++		exfat_truncate(inode, i_size_read(inode));
++	}
++}
++
++static int exfat_write_begin(struct file *file, struct address_space *mapping,
++			     loff_t pos, unsigned int len, unsigned int flags,
++			     struct page **pagep, void **fsdata)
++{
++	int ret;
++
++	*pagep = NULL;
++	ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
++			       exfat_get_block,
++			       &EXFAT_I(mapping->host)->mmu_private);
++
++	if (ret < 0)
++		exfat_write_failed(mapping, pos+len);
++	return ret;
++}
++
++static int exfat_write_end(struct file *file, struct address_space *mapping,
++			   loff_t pos, unsigned int len, unsigned int copied,
++			   struct page *pagep, void *fsdata)
++{
++	struct inode *inode = mapping->host;
++	struct file_id_t *fid = &(EXFAT_I(inode)->fid);
++	int err;
++
++	err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata);
++
++	if (err < len)
++		exfat_write_failed(mapping, pos+len);
++
++	if (!(err < 0) && !(fid->attr & ATTR_ARCHIVE)) {
++		inode->i_mtime = inode->i_ctime = current_time(inode);
++		fid->attr |= ATTR_ARCHIVE;
++		mark_inode_dirty(inode);
++	}
++	return err;
++}
++
++static ssize_t exfat_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
++{
++	struct inode *inode = iocb->ki_filp->f_mapping->host;
++	struct address_space *mapping = iocb->ki_filp->f_mapping;
++	ssize_t ret;
++	int rw;
++
++	rw = iov_iter_rw(iter);
++
++	if (rw == WRITE) {
++		if (EXFAT_I(inode)->mmu_private < iov_iter_count(iter))
++			return 0;
++	}
++	ret = blockdev_direct_IO(iocb, inode, iter, exfat_get_block);
++
++	if ((ret < 0) && (rw & WRITE))
++		exfat_write_failed(mapping, iov_iter_count(iter));
++	return ret;
++}
++
++static sector_t _exfat_bmap(struct address_space *mapping, sector_t block)
++{
++	sector_t blocknr;
++
++	/* exfat_get_cluster() assumes the requested blocknr isn't truncated. */
++	down_read(&EXFAT_I(mapping->host)->truncate_lock);
++	blocknr = generic_block_bmap(mapping, block, exfat_get_block);
++	up_read(&EXFAT_I(mapping->host)->truncate_lock);
++
++	return blocknr;
++}
++
++static const struct address_space_operations exfat_aops = {
++	.readpage    = exfat_readpage,
++	.readpages   = exfat_readpages,
++	.writepage   = exfat_writepage,
++	.writepages  = exfat_writepages,
++	.write_begin = exfat_write_begin,
++	.write_end   = exfat_write_end,
++	.direct_IO   = exfat_direct_IO,
++	.bmap        = _exfat_bmap
++};
++
++/*======================================================================*/
++/*  Super Operations                                                    */
++/*======================================================================*/
++
++static struct inode *exfat_iget(struct super_block *sb, loff_t i_pos)
++{
++	struct exfat_sb_info *sbi = EXFAT_SB(sb);
++	struct exfat_inode_info *info;
++	struct hlist_head *head = sbi->inode_hashtable + exfat_hash(i_pos);
++	struct inode *inode = NULL;
++
++	spin_lock(&sbi->inode_hash_lock);
++	hlist_for_each_entry(info, head, i_hash_fat) {
++		BUG_ON(info->vfs_inode.i_sb != sb);
++
++		if (i_pos != info->i_pos)
++			continue;
++		inode = igrab(&info->vfs_inode);
++		if (inode)
++			break;
++	}
++	spin_unlock(&sbi->inode_hash_lock);
++	return inode;
++}
++
++/* doesn't deal with root inode */
++static int exfat_fill_inode(struct inode *inode, struct file_id_t *fid)
++{
++	struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb);
++	struct fs_info_t *p_fs = &(sbi->fs_info);
++	struct dir_entry_t info;
++
++	memcpy(&(EXFAT_I(inode)->fid), fid, sizeof(struct file_id_t));
++
++	ffsReadStat(inode, &info);
++
++	EXFAT_I(inode)->i_pos = 0;
++	EXFAT_I(inode)->target = NULL;
++	inode->i_uid = sbi->options.fs_uid;
++	inode->i_gid = sbi->options.fs_gid;
++	INC_IVERSION(inode);
++	inode->i_generation = get_seconds();
++
++	if (info.Attr & ATTR_SUBDIR) { /* directory */
++		inode->i_generation &= ~1;
++		inode->i_mode = exfat_make_mode(sbi, info.Attr, 0777);
++		inode->i_op = &exfat_dir_inode_operations;
++		inode->i_fop = &exfat_dir_operations;
++
++		i_size_write(inode, info.Size);
++		EXFAT_I(inode)->mmu_private = i_size_read(inode);
++		set_nlink(inode, info.NumSubdirs);
++	} else if (info.Attr & ATTR_SYMLINK) { /* symbolic link */
++		inode->i_generation |= 1;
++		inode->i_mode = exfat_make_mode(sbi, info.Attr, 0777);
++		inode->i_op = &exfat_symlink_inode_operations;
++
++		i_size_write(inode, info.Size);
++		EXFAT_I(inode)->mmu_private = i_size_read(inode);
++	} else { /* regular file */
++		inode->i_generation |= 1;
++		inode->i_mode = exfat_make_mode(sbi, info.Attr, 0777);
++		inode->i_op = &exfat_file_inode_operations;
++		inode->i_fop = &exfat_file_operations;
++		inode->i_mapping->a_ops = &exfat_aops;
++		inode->i_mapping->nrpages = 0;
++
++		i_size_write(inode, info.Size);
++		EXFAT_I(inode)->mmu_private = i_size_read(inode);
++	}
++	exfat_save_attr(inode, info.Attr);
++
++	inode->i_blocks = ((i_size_read(inode) + (p_fs->cluster_size - 1))
++				& ~((loff_t)p_fs->cluster_size - 1)) >> 9;
++
++	exfat_time_fat2unix(sbi, &inode->i_mtime, &info.ModifyTimestamp);
++	exfat_time_fat2unix(sbi, &inode->i_ctime, &info.CreateTimestamp);
++	exfat_time_fat2unix(sbi, &inode->i_atime, &info.AccessTimestamp);
++
++	return 0;
++}
++
++static struct inode *exfat_build_inode(struct super_block *sb,
++				       struct file_id_t *fid, loff_t i_pos)
++{
++	struct inode *inode;
++	int err;
++
++	inode = exfat_iget(sb, i_pos);
++	if (inode)
++		goto out;
++	inode = new_inode(sb);
++	if (!inode) {
++		inode = ERR_PTR(-ENOMEM);
++		goto out;
++	}
++	inode->i_ino = iunique(sb, EXFAT_ROOT_INO);
++	SET_IVERSION(inode, 1);
++	err = exfat_fill_inode(inode, fid);
++	if (err) {
++		iput(inode);
++		inode = ERR_PTR(err);
++		goto out;
++	}
++	exfat_attach(inode, i_pos);
++	insert_inode_hash(inode);
++out:
++	return inode;
++}
++
++static int exfat_sync_inode(struct inode *inode)
++{
++	return exfat_write_inode(inode, NULL);
++}
++
++static struct inode *exfat_alloc_inode(struct super_block *sb)
++{
++	struct exfat_inode_info *ei;
++
++	ei = kmem_cache_alloc(exfat_inode_cachep, GFP_NOFS);
++	if (!ei)
++		return NULL;
++
++	init_rwsem(&ei->truncate_lock);
++
++	return &ei->vfs_inode;
++}
++
++static void exfat_destroy_inode(struct inode *inode)
++{
++	if (EXFAT_I(inode)->target)
++		kfree(EXFAT_I(inode)->target);
++	EXFAT_I(inode)->target = NULL;
++
++	kmem_cache_free(exfat_inode_cachep, EXFAT_I(inode));
++}
++
++static int exfat_write_inode(struct inode *inode, struct writeback_control *wbc)
++{
++	struct super_block *sb = inode->i_sb;
++	struct exfat_sb_info *sbi = EXFAT_SB(sb);
++	struct dir_entry_t info;
++
++	if (inode->i_ino == EXFAT_ROOT_INO)
++		return 0;
++
++	info.Attr = exfat_make_attr(inode);
++	info.Size = i_size_read(inode);
++
++	exfat_time_unix2fat(sbi, &inode->i_mtime, &info.ModifyTimestamp);
++	exfat_time_unix2fat(sbi, &inode->i_ctime, &info.CreateTimestamp);
++	exfat_time_unix2fat(sbi, &inode->i_atime, &info.AccessTimestamp);
++
++	ffsWriteStat(inode, &info);
++
++	return 0;
++}
++
++static void exfat_evict_inode(struct inode *inode)
++{
++	truncate_inode_pages(&inode->i_data, 0);
++
++	if (!inode->i_nlink)
++		i_size_write(inode, 0);
++	invalidate_inode_buffers(inode);
++	clear_inode(inode);
++	exfat_detach(inode);
++
++	remove_inode_hash(inode);
++}
++
++static void exfat_free_super(struct exfat_sb_info *sbi)
++{
++	if (sbi->nls_disk)
++		unload_nls(sbi->nls_disk);
++	if (sbi->nls_io)
++		unload_nls(sbi->nls_io);
++	if (sbi->options.iocharset != exfat_default_iocharset)
++		kfree(sbi->options.iocharset);
++	/* mutex_init is in exfat_fill_super function. only for 3.7+ */
++	mutex_destroy(&sbi->s_lock);
++	kfree(sbi);
++}
++
++static void exfat_put_super(struct super_block *sb)
++{
++	struct exfat_sb_info *sbi = EXFAT_SB(sb);
++
++	if (__is_sb_dirty(sb))
++		exfat_write_super(sb);
++
++	ffsUmountVol(sb);
++
++	sb->s_fs_info = NULL;
++	exfat_free_super(sbi);
++}
++
++static void exfat_write_super(struct super_block *sb)
++{
++	__lock_super(sb);
++
++	__set_sb_clean(sb);
++
++	if (!sb_rdonly(sb))
++		ffsSyncVol(sb, true);
++
++	__unlock_super(sb);
++}
++
++static int exfat_sync_fs(struct super_block *sb, int wait)
++{
++	int err = 0;
++
++	if (__is_sb_dirty(sb)) {
++		__lock_super(sb);
++		__set_sb_clean(sb);
++		err = ffsSyncVol(sb, true);
++		__unlock_super(sb);
++	}
++
++	return err;
++}
++
++static int exfat_statfs(struct dentry *dentry, struct kstatfs *buf)
++{
++	struct super_block *sb = dentry->d_sb;
++	u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++	struct vol_info_t info;
++
++	if (p_fs->used_clusters == (u32) ~0) {
++		if (ffsGetVolInfo(sb, &info) == FFS_MEDIAERR)
++			return -EIO;
++
++	} else {
++		info.FatType = p_fs->vol_type;
++		info.ClusterSize = p_fs->cluster_size;
++		info.NumClusters = p_fs->num_clusters - 2;
++		info.UsedClusters = p_fs->used_clusters;
++		info.FreeClusters = info.NumClusters - info.UsedClusters;
++
++		if (p_fs->dev_ejected)
++			pr_info("[EXFAT] statfs on device that is ejected\n");
++	}
++
++	buf->f_type = sb->s_magic;
++	buf->f_bsize = info.ClusterSize;
++	buf->f_blocks = info.NumClusters;
++	buf->f_bfree = info.FreeClusters;
++	buf->f_bavail = info.FreeClusters;
++	buf->f_fsid.val[0] = (u32)id;
++	buf->f_fsid.val[1] = (u32)(id >> 32);
++	buf->f_namelen = 260;
++
++	return 0;
++}
++
++static int exfat_remount(struct super_block *sb, int *flags, char *data)
++{
++	*flags |= SB_NODIRATIME;
++	return 0;
++}
++
++static int exfat_show_options(struct seq_file *m, struct dentry *root)
++{
++	struct exfat_sb_info *sbi = EXFAT_SB(root->d_sb);
++	struct exfat_mount_options *opts = &sbi->options;
++
++	if (__kuid_val(opts->fs_uid))
++		seq_printf(m, ",uid=%u", __kuid_val(opts->fs_uid));
++	if (__kgid_val(opts->fs_gid))
++		seq_printf(m, ",gid=%u", __kgid_val(opts->fs_gid));
++	seq_printf(m, ",fmask=%04o", opts->fs_fmask);
++	seq_printf(m, ",dmask=%04o", opts->fs_dmask);
++	if (opts->allow_utime)
++		seq_printf(m, ",allow_utime=%04o", opts->allow_utime);
++	if (sbi->nls_disk)
++		seq_printf(m, ",codepage=%s", sbi->nls_disk->charset);
++	if (sbi->nls_io)
++		seq_printf(m, ",iocharset=%s", sbi->nls_io->charset);
++	seq_printf(m, ",namecase=%u", opts->casesensitive);
++	if (opts->errors == EXFAT_ERRORS_CONT)
++		seq_puts(m, ",errors=continue");
++	else if (opts->errors == EXFAT_ERRORS_PANIC)
++		seq_puts(m, ",errors=panic");
++	else
++		seq_puts(m, ",errors=remount-ro");
++#ifdef CONFIG_EXFAT_DISCARD
++	if (opts->discard)
++		seq_puts(m, ",discard");
++#endif
++	return 0;
++}
++
++static const struct super_operations exfat_sops = {
++	.alloc_inode   = exfat_alloc_inode,
++	.destroy_inode = exfat_destroy_inode,
++	.write_inode   = exfat_write_inode,
++	.evict_inode  = exfat_evict_inode,
++	.put_super     = exfat_put_super,
++	.sync_fs       = exfat_sync_fs,
++	.statfs        = exfat_statfs,
++	.remount_fs    = exfat_remount,
++	.show_options  = exfat_show_options,
++};
++
++/*======================================================================*/
++/*  Export Operations                                                   */
++/*======================================================================*/
++
++static struct inode *exfat_nfs_get_inode(struct super_block *sb, u64 ino,
++					 u32 generation)
++{
++	struct inode *inode = NULL;
++
++	if (ino < EXFAT_ROOT_INO)
++		return inode;
++	inode = ilookup(sb, ino);
++
++	if (inode && generation && (inode->i_generation != generation)) {
++		iput(inode);
++		inode = NULL;
++	}
++
++	return inode;
++}
++
++static struct dentry *exfat_fh_to_dentry(struct super_block *sb,
++					 struct fid *fid, int fh_len,
++					 int fh_type)
++{
++	return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
++				exfat_nfs_get_inode);
++}
++
++static struct dentry *exfat_fh_to_parent(struct super_block *sb,
++					 struct fid *fid, int fh_len,
++					 int fh_type)
++{
++	return generic_fh_to_parent(sb, fid, fh_len, fh_type,
++				exfat_nfs_get_inode);
++}
++
++static const struct export_operations exfat_export_ops = {
++	.fh_to_dentry   = exfat_fh_to_dentry,
++	.fh_to_parent   = exfat_fh_to_parent,
++};
++
++/*======================================================================*/
++/*  Super Block Read Operations                                         */
++/*======================================================================*/
++
++enum {
++	Opt_uid,
++	Opt_gid,
++	Opt_umask,
++	Opt_dmask,
++	Opt_fmask,
++	Opt_allow_utime,
++	Opt_codepage,
++	Opt_charset,
++	Opt_namecase,
++	Opt_debug,
++	Opt_err_cont,
++	Opt_err_panic,
++	Opt_err_ro,
++	Opt_utf8_hack,
++	Opt_err,
++#ifdef CONFIG_EXFAT_DISCARD
++	Opt_discard,
++#endif /* EXFAT_CONFIG_DISCARD */
++};
++
++static const match_table_t exfat_tokens = {
++	{Opt_uid, "uid=%u"},
++	{Opt_gid, "gid=%u"},
++	{Opt_umask, "umask=%o"},
++	{Opt_dmask, "dmask=%o"},
++	{Opt_fmask, "fmask=%o"},
++	{Opt_allow_utime, "allow_utime=%o"},
++	{Opt_codepage, "codepage=%u"},
++	{Opt_charset, "iocharset=%s"},
++	{Opt_namecase, "namecase=%u"},
++	{Opt_debug, "debug"},
++	{Opt_err_cont, "errors=continue"},
++	{Opt_err_panic, "errors=panic"},
++	{Opt_err_ro, "errors=remount-ro"},
++	{Opt_utf8_hack, "utf8"},
++#ifdef CONFIG_EXFAT_DISCARD
++	{Opt_discard, "discard"},
++#endif /* CONFIG_EXFAT_DISCARD */
++	{Opt_err, NULL}
++};
++
++static int parse_options(char *options, int silent, int *debug,
++			 struct exfat_mount_options *opts)
++{
++	char *p;
++	substring_t args[MAX_OPT_ARGS];
++	int option;
++	char *iocharset;
++
++	opts->fs_uid = current_uid();
++	opts->fs_gid = current_gid();
++	opts->fs_fmask = opts->fs_dmask = current->fs->umask;
++	opts->allow_utime = (unsigned short) -1;
++	opts->codepage = exfat_default_codepage;
++	opts->iocharset = exfat_default_iocharset;
++	opts->casesensitive = 0;
++	opts->errors = EXFAT_ERRORS_RO;
++#ifdef CONFIG_EXFAT_DISCARD
++	opts->discard = 0;
++#endif
++	*debug = 0;
++
++	if (!options)
++		goto out;
++
++	while ((p = strsep(&options, ",")) != NULL) {
++		int token;
++
++		if (!*p)
++			continue;
++
++		token = match_token(p, exfat_tokens, args);
++		switch (token) {
++		case Opt_uid:
++			if (match_int(&args[0], &option))
++				return 0;
++			opts->fs_uid = KUIDT_INIT(option);
++			break;
++		case Opt_gid:
++			if (match_int(&args[0], &option))
++				return 0;
++			opts->fs_gid = KGIDT_INIT(option);
++			break;
++		case Opt_umask:
++		case Opt_dmask:
++		case Opt_fmask:
++			if (match_octal(&args[0], &option))
++				return 0;
++			if (token != Opt_dmask)
++				opts->fs_fmask = option;
++			if (token != Opt_fmask)
++				opts->fs_dmask = option;
++			break;
++		case Opt_allow_utime:
++			if (match_octal(&args[0], &option))
++				return 0;
++			opts->allow_utime = option & 0022;
++			break;
++		case Opt_codepage:
++			if (match_int(&args[0], &option))
++				return 0;
++			opts->codepage = option;
++			break;
++		case Opt_charset:
++			if (opts->iocharset != exfat_default_iocharset)
++				kfree(opts->iocharset);
++			iocharset = match_strdup(&args[0]);
++			if (!iocharset)
++				return -ENOMEM;
++			opts->iocharset = iocharset;
++			break;
++		case Opt_namecase:
++			if (match_int(&args[0], &option))
++				return 0;
++			opts->casesensitive = option;
++			break;
++		case Opt_err_cont:
++			opts->errors = EXFAT_ERRORS_CONT;
++			break;
++		case Opt_err_panic:
++			opts->errors = EXFAT_ERRORS_PANIC;
++			break;
++		case Opt_err_ro:
++			opts->errors = EXFAT_ERRORS_RO;
++			break;
++		case Opt_debug:
++			*debug = 1;
++			break;
++#ifdef CONFIG_EXFAT_DISCARD
++		case Opt_discard:
++			opts->discard = 1;
++			break;
++#endif /* CONFIG_EXFAT_DISCARD */
++		case Opt_utf8_hack:
++			break;
++		default:
++			if (!silent)
++				pr_err("[EXFAT] Unrecognized mount option %s or missing value\n",
++				       p);
++			return -EINVAL;
++		}
++	}
++
++out:
++	if (opts->allow_utime == (unsigned short) -1)
++		opts->allow_utime = ~opts->fs_dmask & 0022;
++
++	return 0;
++}
++
++static void exfat_hash_init(struct super_block *sb)
++{
++	struct exfat_sb_info *sbi = EXFAT_SB(sb);
++	int i;
++
++	spin_lock_init(&sbi->inode_hash_lock);
++	for (i = 0; i < EXFAT_HASH_SIZE; i++)
++		INIT_HLIST_HEAD(&sbi->inode_hashtable[i]);
++}
++
++static int exfat_read_root(struct inode *inode)
++{
++	struct super_block *sb = inode->i_sb;
++	struct exfat_sb_info *sbi = EXFAT_SB(sb);
++	struct fs_info_t *p_fs = &(sbi->fs_info);
++	struct dir_entry_t info;
++
++	EXFAT_I(inode)->fid.dir.dir = p_fs->root_dir;
++	EXFAT_I(inode)->fid.dir.flags = 0x01;
++	EXFAT_I(inode)->fid.entry = -1;
++	EXFAT_I(inode)->fid.start_clu = p_fs->root_dir;
++	EXFAT_I(inode)->fid.flags = 0x01;
++	EXFAT_I(inode)->fid.type = TYPE_DIR;
++	EXFAT_I(inode)->fid.rwoffset = 0;
++	EXFAT_I(inode)->fid.hint_last_off = -1;
++
++	EXFAT_I(inode)->target = NULL;
++
++	ffsReadStat(inode, &info);
++
++	inode->i_uid = sbi->options.fs_uid;
++	inode->i_gid = sbi->options.fs_gid;
++	INC_IVERSION(inode);
++	inode->i_generation = 0;
++	inode->i_mode = exfat_make_mode(sbi, ATTR_SUBDIR, 0777);
++	inode->i_op = &exfat_dir_inode_operations;
++	inode->i_fop = &exfat_dir_operations;
++
++	i_size_write(inode, info.Size);
++	inode->i_blocks = ((i_size_read(inode) + (p_fs->cluster_size - 1))
++				& ~((loff_t)p_fs->cluster_size - 1)) >> 9;
++	EXFAT_I(inode)->i_pos = ((loff_t) p_fs->root_dir << 32) | 0xffffffff;
++	EXFAT_I(inode)->mmu_private = i_size_read(inode);
++
++	exfat_save_attr(inode, ATTR_SUBDIR);
++	inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
++	set_nlink(inode, info.NumSubdirs + 2);
++
++	return 0;
++}
++
++static void setup_dops(struct super_block *sb)
++{
++	if (EXFAT_SB(sb)->options.casesensitive == 0)
++		sb->s_d_op = &exfat_ci_dentry_ops;
++	else
++		sb->s_d_op = &exfat_dentry_ops;
++}
++
++static int exfat_fill_super(struct super_block *sb, void *data, int silent)
++{
++	struct inode *root_inode = NULL;
++	struct exfat_sb_info *sbi;
++	int debug, ret;
++	long error;
++	char buf[50];
++
++	/*
++	 * GFP_KERNEL is ok here, because while we do hold the
++	 * supeblock lock, memory pressure can't call back into
++	 * the filesystem, since we're only just about to mount
++	 * it and have no inodes etc active!
++	 */
++	sbi = kzalloc(sizeof(struct exfat_sb_info), GFP_KERNEL);
++	if (!sbi)
++		return -ENOMEM;
++	mutex_init(&sbi->s_lock);
++	sb->s_fs_info = sbi;
++	sb->s_flags |= SB_NODIRATIME;
++	sb->s_magic = EXFAT_SUPER_MAGIC;
++	sb->s_op = &exfat_sops;
++	sb->s_export_op = &exfat_export_ops;
++
++	error = parse_options(data, silent, &debug, &sbi->options);
++	if (error)
++		goto out_fail;
++
++	setup_dops(sb);
++
++	error = -EIO;
++	sb_min_blocksize(sb, 512);
++	sb->s_maxbytes = 0x7fffffffffffffffLL;    /* maximum file size */
++
++	ret = ffsMountVol(sb);
++	if (ret) {
++		if (!silent)
++			pr_err("[EXFAT] ffsMountVol failed\n");
++
++		goto out_fail;
++	}
++
++	/* set up enough so that it can read an inode */
++	exfat_hash_init(sb);
++
++	/*
++	 * The low byte of FAT's first entry must have same value with
++	 * media-field.  But in real world, too many devices is
++	 * writing wrong value.  So, removed that validity check.
++	 *
++	 * if (FAT_FIRST_ENT(sb, media) != first)
++	 */
++
++	/* codepage is not meaningful in exfat */
++	if (sbi->fs_info.vol_type != EXFAT) {
++		error = -EINVAL;
++		sprintf(buf, "cp%d", sbi->options.codepage);
++		sbi->nls_disk = load_nls(buf);
++		if (!sbi->nls_disk) {
++			pr_err("[EXFAT] Codepage %s not found\n", buf);
++			goto out_fail2;
++		}
++	}
++
++	sbi->nls_io = load_nls(sbi->options.iocharset);
++
++	error = -ENOMEM;
++	root_inode = new_inode(sb);
++	if (!root_inode)
++		goto out_fail2;
++	root_inode->i_ino = EXFAT_ROOT_INO;
++	SET_IVERSION(root_inode, 1);
++
++	error = exfat_read_root(root_inode);
++	if (error < 0)
++		goto out_fail2;
++	error = -ENOMEM;
++	exfat_attach(root_inode, EXFAT_I(root_inode)->i_pos);
++	insert_inode_hash(root_inode);
++	sb->s_root = d_make_root(root_inode);
++	if (!sb->s_root) {
++		pr_err("[EXFAT] Getting the root inode failed\n");
++		goto out_fail2;
++	}
++
++	return 0;
++
++out_fail2:
++	ffsUmountVol(sb);
++out_fail:
++	if (root_inode)
++		iput(root_inode);
++	sb->s_fs_info = NULL;
++	exfat_free_super(sbi);
++	return error;
++}
++
++static struct dentry *exfat_fs_mount(struct file_system_type *fs_type,
++				     int flags, const char *dev_name,
++				     void *data)
++{
++	return mount_bdev(fs_type, flags, dev_name, data, exfat_fill_super);
++}
++
++static void init_once(void *foo)
++{
++	struct exfat_inode_info *ei = (struct exfat_inode_info *)foo;
++
++	INIT_HLIST_NODE(&ei->i_hash_fat);
++	inode_init_once(&ei->vfs_inode);
++}
++
++static int __init exfat_init_inodecache(void)
++{
++	exfat_inode_cachep = kmem_cache_create("exfat_inode_cache",
++					       sizeof(struct exfat_inode_info),
++					       0,
++					       (SLAB_RECLAIM_ACCOUNT |
++						SLAB_MEM_SPREAD),
++					       init_once);
++	if (exfat_inode_cachep == NULL)
++		return -ENOMEM;
++	return 0;
++}
++
++static void __exit exfat_destroy_inodecache(void)
++{
++	/*
++	 * Make sure all delayed rcu free inodes are flushed before we
++	 * destroy cache.
++	 */
++	rcu_barrier();
++	kmem_cache_destroy(exfat_inode_cachep);
++}
++
++#ifdef CONFIG_EXFAT_KERNEL_DEBUG
++static void exfat_debug_kill_sb(struct super_block *sb)
++{
++	struct exfat_sb_info *sbi = EXFAT_SB(sb);
++	struct block_device *bdev = sb->s_bdev;
++	struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
++
++	long flags;
++
++	if (sbi) {
++		flags = sbi->debug_flags;
++
++		if (flags & EXFAT_DEBUGFLAGS_INVALID_UMOUNT) {
++			/*
++			 * invalidate_bdev drops all device cache include
++			 * dirty. We use this to simulate device removal.
++			 */
++			down(&p_fs->v_sem);
++			FAT_release_all(sb);
++			buf_release_all(sb);
++			up(&p_fs->v_sem);
++
++			invalidate_bdev(bdev);
++		}
++	}
++
++	kill_block_super(sb);
++}
++#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
++
++static struct file_system_type exfat_fs_type = {
++	.owner       = THIS_MODULE,
++	.name        = "exfat",
++	.mount       = exfat_fs_mount,
++#ifdef CONFIG_EXFAT_KERNEL_DEBUG
++	.kill_sb    = exfat_debug_kill_sb,
++#else
++	.kill_sb    = kill_block_super,
++#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
++	.fs_flags    = FS_REQUIRES_DEV,
++};
++
++static int __init init_exfat(void)
++{
++	int err;
++
++	BUILD_BUG_ON(sizeof(struct dentry_t) != DENTRY_SIZE);
++	BUILD_BUG_ON(sizeof(struct dos_dentry_t) != DENTRY_SIZE);
++	BUILD_BUG_ON(sizeof(struct ext_dentry_t) != DENTRY_SIZE);
++	BUILD_BUG_ON(sizeof(struct file_dentry_t) != DENTRY_SIZE);
++	BUILD_BUG_ON(sizeof(struct strm_dentry_t) != DENTRY_SIZE);
++	BUILD_BUG_ON(sizeof(struct name_dentry_t) != DENTRY_SIZE);
++	BUILD_BUG_ON(sizeof(struct bmap_dentry_t) != DENTRY_SIZE);
++	BUILD_BUG_ON(sizeof(struct case_dentry_t) != DENTRY_SIZE);
++	BUILD_BUG_ON(sizeof(struct volm_dentry_t) != DENTRY_SIZE);
++
++	pr_info("exFAT: Version %s\n", EXFAT_VERSION);
++
++	err = exfat_init_inodecache();
++	if (err)
++		return err;
++
++	err = register_filesystem(&exfat_fs_type);
++	if (err)
++		return err;
++
++	return 0;
++}
++
++static void __exit exit_exfat(void)
++{
++	exfat_destroy_inodecache();
++	unregister_filesystem(&exfat_fs_type);
++}
++
++module_init(init_exfat);
++module_exit(exit_exfat);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("exFAT Filesystem Driver");
++MODULE_ALIAS_FS("exfat");
+diff --git a/drivers/staging/exfat/exfat_upcase.c b/drivers/staging/exfat/exfat_upcase.c
+new file mode 100644
+index 000000000000..366082fb3dab
+--- /dev/null
++++ b/drivers/staging/exfat/exfat_upcase.c
+@@ -0,0 +1,740 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ *  Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
++ */
++
++#include 
++#include "exfat.h"
++
++const u8 uni_upcase[NUM_UPCASE << 1] = {
++	0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00,
++	0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00,
++	0x08, 0x00, 0x09, 0x00, 0x0A, 0x00, 0x0B, 0x00,
++	0x0C, 0x00, 0x0D, 0x00, 0x0E, 0x00, 0x0F, 0x00,
++	0x10, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13, 0x00,
++	0x14, 0x00, 0x15, 0x00, 0x16, 0x00, 0x17, 0x00,
++	0x18, 0x00, 0x19, 0x00, 0x1A, 0x00, 0x1B, 0x00,
++	0x1C, 0x00, 0x1D, 0x00, 0x1E, 0x00, 0x1F, 0x00,
++	0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x23, 0x00,
++	0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00,
++	0x28, 0x00, 0x29, 0x00, 0x2A, 0x00, 0x2B, 0x00,
++	0x2C, 0x00, 0x2D, 0x00, 0x2E, 0x00, 0x2F, 0x00,
++	0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00,
++	0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00,
++	0x38, 0x00, 0x39, 0x00, 0x3A, 0x00, 0x3B, 0x00,
++	0x3C, 0x00, 0x3D, 0x00, 0x3E, 0x00, 0x3F, 0x00,
++	0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00,
++	0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00,
++	0x48, 0x00, 0x49, 0x00, 0x4A, 0x00, 0x4B, 0x00,
++	0x4C, 0x00, 0x4D, 0x00, 0x4E, 0x00, 0x4F, 0x00,
++	0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00,
++	0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00,
++	0x58, 0x00, 0x59, 0x00, 0x5A, 0x00, 0x5B, 0x00,
++	0x5C, 0x00, 0x5D, 0x00, 0x5E, 0x00, 0x5F, 0x00,
++	0x60, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00,
++	0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00,
++	0x48, 0x00, 0x49, 0x00, 0x4A, 0x00, 0x4B, 0x00,
++	0x4C, 0x00, 0x4D, 0x00, 0x4E, 0x00, 0x4F, 0x00,
++	0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00,
++	0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00,
++	0x58, 0x00, 0x59, 0x00, 0x5A, 0x00, 0x7B, 0x00,
++	0x7C, 0x00, 0x7D, 0x00, 0x7E, 0x00, 0x7F, 0x00,
++	0x80, 0x00, 0x81, 0x00, 0x82, 0x00, 0x83, 0x00,
++	0x84, 0x00, 0x85, 0x00, 0x86, 0x00, 0x87, 0x00,
++	0x88, 0x00, 0x89, 0x00, 0x8A, 0x00, 0x8B, 0x00,
++	0x8C, 0x00, 0x8D, 0x00, 0x8E, 0x00, 0x8F, 0x00,
++	0x90, 0x00, 0x91, 0x00, 0x92, 0x00, 0x93, 0x00,
++	0x94, 0x00, 0x95, 0x00, 0x96, 0x00, 0x97, 0x00,
++	0x98, 0x00, 0x99, 0x00, 0x9A, 0x00, 0x9B, 0x00,
++	0x9C, 0x00, 0x9D, 0x00, 0x9E, 0x00, 0x9F, 0x00,
++	0xA0, 0x00, 0xA1, 0x00, 0xA2, 0x00, 0xA3, 0x00,
++	0xA4, 0x00, 0xA5, 0x00, 0xA6, 0x00, 0xA7, 0x00,
++	0xA8, 0x00, 0xA9, 0x00, 0xAA, 0x00, 0xAB, 0x00,
++	0xAC, 0x00, 0xAD, 0x00, 0xAE, 0x00, 0xAF, 0x00,
++	0xB0, 0x00, 0xB1, 0x00, 0xB2, 0x00, 0xB3, 0x00,
++	0xB4, 0x00, 0xB5, 0x00, 0xB6, 0x00, 0xB7, 0x00,
++	0xB8, 0x00, 0xB9, 0x00, 0xBA, 0x00, 0xBB, 0x00,
++	0xBC, 0x00, 0xBD, 0x00, 0xBE, 0x00, 0xBF, 0x00,
++	0xC0, 0x00, 0xC1, 0x00, 0xC2, 0x00, 0xC3, 0x00,
++	0xC4, 0x00, 0xC5, 0x00, 0xC6, 0x00, 0xC7, 0x00,
++	0xC8, 0x00, 0xC9, 0x00, 0xCA, 0x00, 0xCB, 0x00,
++	0xCC, 0x00, 0xCD, 0x00, 0xCE, 0x00, 0xCF, 0x00,
++	0xD0, 0x00, 0xD1, 0x00, 0xD2, 0x00, 0xD3, 0x00,
++	0xD4, 0x00, 0xD5, 0x00, 0xD6, 0x00, 0xD7, 0x00,
++	0xD8, 0x00, 0xD9, 0x00, 0xDA, 0x00, 0xDB, 0x00,
++	0xDC, 0x00, 0xDD, 0x00, 0xDE, 0x00, 0xDF, 0x00,
++	0xC0, 0x00, 0xC1, 0x00, 0xC2, 0x00, 0xC3, 0x00,
++	0xC4, 0x00, 0xC5, 0x00, 0xC6, 0x00, 0xC7, 0x00,
++	0xC8, 0x00, 0xC9, 0x00, 0xCA, 0x00, 0xCB, 0x00,
++	0xCC, 0x00, 0xCD, 0x00, 0xCE, 0x00, 0xCF, 0x00,
++	0xD0, 0x00, 0xD1, 0x00, 0xD2, 0x00, 0xD3, 0x00,
++	0xD4, 0x00, 0xD5, 0x00, 0xD6, 0x00, 0xF7, 0x00,
++	0xD8, 0x00, 0xD9, 0x00, 0xDA, 0x00, 0xDB, 0x00,
++	0xDC, 0x00, 0xDD, 0x00, 0xDE, 0x00, 0x78, 0x01,
++	0x00, 0x01, 0x00, 0x01, 0x02, 0x01, 0x02, 0x01,
++	0x04, 0x01, 0x04, 0x01, 0x06, 0x01, 0x06, 0x01,
++	0x08, 0x01, 0x08, 0x01, 0x0A, 0x01, 0x0A, 0x01,
++	0x0C, 0x01, 0x0C, 0x01, 0x0E, 0x01, 0x0E, 0x01,
++	0x10, 0x01, 0x10, 0x01, 0x12, 0x01, 0x12, 0x01,
++	0x14, 0x01, 0x14, 0x01, 0x16, 0x01, 0x16, 0x01,
++	0x18, 0x01, 0x18, 0x01, 0x1A, 0x01, 0x1A, 0x01,
++	0x1C, 0x01, 0x1C, 0x01, 0x1E, 0x01, 0x1E, 0x01,
++	0x20, 0x01, 0x20, 0x01, 0x22, 0x01, 0x22, 0x01,
++	0x24, 0x01, 0x24, 0x01, 0x26, 0x01, 0x26, 0x01,
++	0x28, 0x01, 0x28, 0x01, 0x2A, 0x01, 0x2A, 0x01,
++	0x2C, 0x01, 0x2C, 0x01, 0x2E, 0x01, 0x2E, 0x01,
++	0x30, 0x01, 0x31, 0x01, 0x32, 0x01, 0x32, 0x01,
++	0x34, 0x01, 0x34, 0x01, 0x36, 0x01, 0x36, 0x01,
++	0x38, 0x01, 0x39, 0x01, 0x39, 0x01, 0x3B, 0x01,
++	0x3B, 0x01, 0x3D, 0x01, 0x3D, 0x01, 0x3F, 0x01,
++	0x3F, 0x01, 0x41, 0x01, 0x41, 0x01, 0x43, 0x01,
++	0x43, 0x01, 0x45, 0x01, 0x45, 0x01, 0x47, 0x01,
++	0x47, 0x01, 0x49, 0x01, 0x4A, 0x01, 0x4A, 0x01,
++	0x4C, 0x01, 0x4C, 0x01, 0x4E, 0x01, 0x4E, 0x01,
++	0x50, 0x01, 0x50, 0x01, 0x52, 0x01, 0x52, 0x01,
++	0x54, 0x01, 0x54, 0x01, 0x56, 0x01, 0x56, 0x01,
++	0x58, 0x01, 0x58, 0x01, 0x5A, 0x01, 0x5A, 0x01,
++	0x5C, 0x01, 0x5C, 0x01, 0x5E, 0x01, 0x5E, 0x01,
++	0x60, 0x01, 0x60, 0x01, 0x62, 0x01, 0x62, 0x01,
++	0x64, 0x01, 0x64, 0x01, 0x66, 0x01, 0x66, 0x01,
++	0x68, 0x01, 0x68, 0x01, 0x6A, 0x01, 0x6A, 0x01,
++	0x6C, 0x01, 0x6C, 0x01, 0x6E, 0x01, 0x6E, 0x01,
++	0x70, 0x01, 0x70, 0x01, 0x72, 0x01, 0x72, 0x01,
++	0x74, 0x01, 0x74, 0x01, 0x76, 0x01, 0x76, 0x01,
++	0x78, 0x01, 0x79, 0x01, 0x79, 0x01, 0x7B, 0x01,
++	0x7B, 0x01, 0x7D, 0x01, 0x7D, 0x01, 0x7F, 0x01,
++	0x43, 0x02, 0x81, 0x01, 0x82, 0x01, 0x82, 0x01,
++	0x84, 0x01, 0x84, 0x01, 0x86, 0x01, 0x87, 0x01,
++	0x87, 0x01, 0x89, 0x01, 0x8A, 0x01, 0x8B, 0x01,
++	0x8B, 0x01, 0x8D, 0x01, 0x8E, 0x01, 0x8F, 0x01,
++	0x90, 0x01, 0x91, 0x01, 0x91, 0x01, 0x93, 0x01,
++	0x94, 0x01, 0xF6, 0x01, 0x96, 0x01, 0x97, 0x01,
++	0x98, 0x01, 0x98, 0x01, 0x3D, 0x02, 0x9B, 0x01,
++	0x9C, 0x01, 0x9D, 0x01, 0x20, 0x02, 0x9F, 0x01,
++	0xA0, 0x01, 0xA0, 0x01, 0xA2, 0x01, 0xA2, 0x01,
++	0xA4, 0x01, 0xA4, 0x01, 0xA6, 0x01, 0xA7, 0x01,
++	0xA7, 0x01, 0xA9, 0x01, 0xAA, 0x01, 0xAB, 0x01,
++	0xAC, 0x01, 0xAC, 0x01, 0xAE, 0x01, 0xAF, 0x01,
++	0xAF, 0x01, 0xB1, 0x01, 0xB2, 0x01, 0xB3, 0x01,
++	0xB3, 0x01, 0xB5, 0x01, 0xB5, 0x01, 0xB7, 0x01,
++	0xB8, 0x01, 0xB8, 0x01, 0xBA, 0x01, 0xBB, 0x01,
++	0xBC, 0x01, 0xBC, 0x01, 0xBE, 0x01, 0xF7, 0x01,
++	0xC0, 0x01, 0xC1, 0x01, 0xC2, 0x01, 0xC3, 0x01,
++	0xC4, 0x01, 0xC5, 0x01, 0xC4, 0x01, 0xC7, 0x01,
++	0xC8, 0x01, 0xC7, 0x01, 0xCA, 0x01, 0xCB, 0x01,
++	0xCA, 0x01, 0xCD, 0x01, 0xCD, 0x01, 0xCF, 0x01,
++	0xCF, 0x01, 0xD1, 0x01, 0xD1, 0x01, 0xD3, 0x01,
++	0xD3, 0x01, 0xD5, 0x01, 0xD5, 0x01, 0xD7, 0x01,
++	0xD7, 0x01, 0xD9, 0x01, 0xD9, 0x01, 0xDB, 0x01,
++	0xDB, 0x01, 0x8E, 0x01, 0xDE, 0x01, 0xDE, 0x01,
++	0xE0, 0x01, 0xE0, 0x01, 0xE2, 0x01, 0xE2, 0x01,
++	0xE4, 0x01, 0xE4, 0x01, 0xE6, 0x01, 0xE6, 0x01,
++	0xE8, 0x01, 0xE8, 0x01, 0xEA, 0x01, 0xEA, 0x01,
++	0xEC, 0x01, 0xEC, 0x01, 0xEE, 0x01, 0xEE, 0x01,
++	0xF0, 0x01, 0xF1, 0x01, 0xF2, 0x01, 0xF1, 0x01,
++	0xF4, 0x01, 0xF4, 0x01, 0xF6, 0x01, 0xF7, 0x01,
++	0xF8, 0x01, 0xF8, 0x01, 0xFA, 0x01, 0xFA, 0x01,
++	0xFC, 0x01, 0xFC, 0x01, 0xFE, 0x01, 0xFE, 0x01,
++	0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
++	0x04, 0x02, 0x04, 0x02, 0x06, 0x02, 0x06, 0x02,
++	0x08, 0x02, 0x08, 0x02, 0x0A, 0x02, 0x0A, 0x02,
++	0x0C, 0x02, 0x0C, 0x02, 0x0E, 0x02, 0x0E, 0x02,
++	0x10, 0x02, 0x10, 0x02, 0x12, 0x02, 0x12, 0x02,
++	0x14, 0x02, 0x14, 0x02, 0x16, 0x02, 0x16, 0x02,
++	0x18, 0x02, 0x18, 0x02, 0x1A, 0x02, 0x1A, 0x02,
++	0x1C, 0x02, 0x1C, 0x02, 0x1E, 0x02, 0x1E, 0x02,
++	0x20, 0x02, 0x21, 0x02, 0x22, 0x02, 0x22, 0x02,
++	0x24, 0x02, 0x24, 0x02, 0x26, 0x02, 0x26, 0x02,
++	0x28, 0x02, 0x28, 0x02, 0x2A, 0x02, 0x2A, 0x02,
++	0x2C, 0x02, 0x2C, 0x02, 0x2E, 0x02, 0x2E, 0x02,
++	0x30, 0x02, 0x30, 0x02, 0x32, 0x02, 0x32, 0x02,
++	0x34, 0x02, 0x35, 0x02, 0x36, 0x02, 0x37, 0x02,
++	0x38, 0x02, 0x39, 0x02, 0x65, 0x2C, 0x3B, 0x02,
++	0x3B, 0x02, 0x3D, 0x02, 0x66, 0x2C, 0x3F, 0x02,
++	0x40, 0x02, 0x41, 0x02, 0x41, 0x02, 0x43, 0x02,
++	0x44, 0x02, 0x45, 0x02, 0x46, 0x02, 0x46, 0x02,
++	0x48, 0x02, 0x48, 0x02, 0x4A, 0x02, 0x4A, 0x02,
++	0x4C, 0x02, 0x4C, 0x02, 0x4E, 0x02, 0x4E, 0x02,
++	0x50, 0x02, 0x51, 0x02, 0x52, 0x02, 0x81, 0x01,
++	0x86, 0x01, 0x55, 0x02, 0x89, 0x01, 0x8A, 0x01,
++	0x58, 0x02, 0x8F, 0x01, 0x5A, 0x02, 0x90, 0x01,
++	0x5C, 0x02, 0x5D, 0x02, 0x5E, 0x02, 0x5F, 0x02,
++	0x93, 0x01, 0x61, 0x02, 0x62, 0x02, 0x94, 0x01,
++	0x64, 0x02, 0x65, 0x02, 0x66, 0x02, 0x67, 0x02,
++	0x97, 0x01, 0x96, 0x01, 0x6A, 0x02, 0x62, 0x2C,
++	0x6C, 0x02, 0x6D, 0x02, 0x6E, 0x02, 0x9C, 0x01,
++	0x70, 0x02, 0x71, 0x02, 0x9D, 0x01, 0x73, 0x02,
++	0x74, 0x02, 0x9F, 0x01, 0x76, 0x02, 0x77, 0x02,
++	0x78, 0x02, 0x79, 0x02, 0x7A, 0x02, 0x7B, 0x02,
++	0x7C, 0x02, 0x64, 0x2C, 0x7E, 0x02, 0x7F, 0x02,
++	0xA6, 0x01, 0x81, 0x02, 0x82, 0x02, 0xA9, 0x01,
++	0x84, 0x02, 0x85, 0x02, 0x86, 0x02, 0x87, 0x02,
++	0xAE, 0x01, 0x44, 0x02, 0xB1, 0x01, 0xB2, 0x01,
++	0x45, 0x02, 0x8D, 0x02, 0x8E, 0x02, 0x8F, 0x02,
++	0x90, 0x02, 0x91, 0x02, 0xB7, 0x01, 0x93, 0x02,
++	0x94, 0x02, 0x95, 0x02, 0x96, 0x02, 0x97, 0x02,
++	0x98, 0x02, 0x99, 0x02, 0x9A, 0x02, 0x9B, 0x02,
++	0x9C, 0x02, 0x9D, 0x02, 0x9E, 0x02, 0x9F, 0x02,
++	0xA0, 0x02, 0xA1, 0x02, 0xA2, 0x02, 0xA3, 0x02,
++	0xA4, 0x02, 0xA5, 0x02, 0xA6, 0x02, 0xA7, 0x02,
++	0xA8, 0x02, 0xA9, 0x02, 0xAA, 0x02, 0xAB, 0x02,
++	0xAC, 0x02, 0xAD, 0x02, 0xAE, 0x02, 0xAF, 0x02,
++	0xB0, 0x02, 0xB1, 0x02, 0xB2, 0x02, 0xB3, 0x02,
++	0xB4, 0x02, 0xB5, 0x02, 0xB6, 0x02, 0xB7, 0x02,
++	0xB8, 0x02, 0xB9, 0x02, 0xBA, 0x02, 0xBB, 0x02,
++	0xBC, 0x02, 0xBD, 0x02, 0xBE, 0x02, 0xBF, 0x02,
++	0xC0, 0x02, 0xC1, 0x02, 0xC2, 0x02, 0xC3, 0x02,
++	0xC4, 0x02, 0xC5, 0x02, 0xC6, 0x02, 0xC7, 0x02,
++	0xC8, 0x02, 0xC9, 0x02, 0xCA, 0x02, 0xCB, 0x02,
++	0xCC, 0x02, 0xCD, 0x02, 0xCE, 0x02, 0xCF, 0x02,
++	0xD0, 0x02, 0xD1, 0x02, 0xD2, 0x02, 0xD3, 0x02,
++	0xD4, 0x02, 0xD5, 0x02, 0xD6, 0x02, 0xD7, 0x02,
++	0xD8, 0x02, 0xD9, 0x02, 0xDA, 0x02, 0xDB, 0x02,
++	0xDC, 0x02, 0xDD, 0x02, 0xDE, 0x02, 0xDF, 0x02,
++	0xE0, 0x02, 0xE1, 0x02, 0xE2, 0x02, 0xE3, 0x02,
++	0xE4, 0x02, 0xE5, 0x02, 0xE6, 0x02, 0xE7, 0x02,
++	0xE8, 0x02, 0xE9, 0x02, 0xEA, 0x02, 0xEB, 0x02,
++	0xEC, 0x02, 0xED, 0x02, 0xEE, 0x02, 0xEF, 0x02,
++	0xF0, 0x02, 0xF1, 0x02, 0xF2, 0x02, 0xF3, 0x02,
++	0xF4, 0x02, 0xF5, 0x02, 0xF6, 0x02, 0xF7, 0x02,
++	0xF8, 0x02, 0xF9, 0x02, 0xFA, 0x02, 0xFB, 0x02,
++	0xFC, 0x02, 0xFD, 0x02, 0xFE, 0x02, 0xFF, 0x02,
++	0x00, 0x03, 0x01, 0x03, 0x02, 0x03, 0x03, 0x03,
++	0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x07, 0x03,
++	0x08, 0x03, 0x09, 0x03, 0x0A, 0x03, 0x0B, 0x03,
++	0x0C, 0x03, 0x0D, 0x03, 0x0E, 0x03, 0x0F, 0x03,
++	0x10, 0x03, 0x11, 0x03, 0x12, 0x03, 0x13, 0x03,
++	0x14, 0x03, 0x15, 0x03, 0x16, 0x03, 0x17, 0x03,
++	0x18, 0x03, 0x19, 0x03, 0x1A, 0x03, 0x1B, 0x03,
++	0x1C, 0x03, 0x1D, 0x03, 0x1E, 0x03, 0x1F, 0x03,
++	0x20, 0x03, 0x21, 0x03, 0x22, 0x03, 0x23, 0x03,
++	0x24, 0x03, 0x25, 0x03, 0x26, 0x03, 0x27, 0x03,
++	0x28, 0x03, 0x29, 0x03, 0x2A, 0x03, 0x2B, 0x03,
++	0x2C, 0x03, 0x2D, 0x03, 0x2E, 0x03, 0x2F, 0x03,
++	0x30, 0x03, 0x31, 0x03, 0x32, 0x03, 0x33, 0x03,
++	0x34, 0x03, 0x35, 0x03, 0x36, 0x03, 0x37, 0x03,
++	0x38, 0x03, 0x39, 0x03, 0x3A, 0x03, 0x3B, 0x03,
++	0x3C, 0x03, 0x3D, 0x03, 0x3E, 0x03, 0x3F, 0x03,
++	0x40, 0x03, 0x41, 0x03, 0x42, 0x03, 0x43, 0x03,
++	0x44, 0x03, 0x45, 0x03, 0x46, 0x03, 0x47, 0x03,
++	0x48, 0x03, 0x49, 0x03, 0x4A, 0x03, 0x4B, 0x03,
++	0x4C, 0x03, 0x4D, 0x03, 0x4E, 0x03, 0x4F, 0x03,
++	0x50, 0x03, 0x51, 0x03, 0x52, 0x03, 0x53, 0x03,
++	0x54, 0x03, 0x55, 0x03, 0x56, 0x03, 0x57, 0x03,
++	0x58, 0x03, 0x59, 0x03, 0x5A, 0x03, 0x5B, 0x03,
++	0x5C, 0x03, 0x5D, 0x03, 0x5E, 0x03, 0x5F, 0x03,
++	0x60, 0x03, 0x61, 0x03, 0x62, 0x03, 0x63, 0x03,
++	0x64, 0x03, 0x65, 0x03, 0x66, 0x03, 0x67, 0x03,
++	0x68, 0x03, 0x69, 0x03, 0x6A, 0x03, 0x6B, 0x03,
++	0x6C, 0x03, 0x6D, 0x03, 0x6E, 0x03, 0x6F, 0x03,
++	0x70, 0x03, 0x71, 0x03, 0x72, 0x03, 0x73, 0x03,
++	0x74, 0x03, 0x75, 0x03, 0x76, 0x03, 0x77, 0x03,
++	0x78, 0x03, 0x79, 0x03, 0x7A, 0x03, 0xFD, 0x03,
++	0xFE, 0x03, 0xFF, 0x03, 0x7E, 0x03, 0x7F, 0x03,
++	0x80, 0x03, 0x81, 0x03, 0x82, 0x03, 0x83, 0x03,
++	0x84, 0x03, 0x85, 0x03, 0x86, 0x03, 0x87, 0x03,
++	0x88, 0x03, 0x89, 0x03, 0x8A, 0x03, 0x8B, 0x03,
++	0x8C, 0x03, 0x8D, 0x03, 0x8E, 0x03, 0x8F, 0x03,
++	0x90, 0x03, 0x91, 0x03, 0x92, 0x03, 0x93, 0x03,
++	0x94, 0x03, 0x95, 0x03, 0x96, 0x03, 0x97, 0x03,
++	0x98, 0x03, 0x99, 0x03, 0x9A, 0x03, 0x9B, 0x03,
++	0x9C, 0x03, 0x9D, 0x03, 0x9E, 0x03, 0x9F, 0x03,
++	0xA0, 0x03, 0xA1, 0x03, 0xA2, 0x03, 0xA3, 0x03,
++	0xA4, 0x03, 0xA5, 0x03, 0xA6, 0x03, 0xA7, 0x03,
++	0xA8, 0x03, 0xA9, 0x03, 0xAA, 0x03, 0xAB, 0x03,
++	0x86, 0x03, 0x88, 0x03, 0x89, 0x03, 0x8A, 0x03,
++	0xB0, 0x03, 0x91, 0x03, 0x92, 0x03, 0x93, 0x03,
++	0x94, 0x03, 0x95, 0x03, 0x96, 0x03, 0x97, 0x03,
++	0x98, 0x03, 0x99, 0x03, 0x9A, 0x03, 0x9B, 0x03,
++	0x9C, 0x03, 0x9D, 0x03, 0x9E, 0x03, 0x9F, 0x03,
++	0xA0, 0x03, 0xA1, 0x03, 0xA3, 0x03, 0xA3, 0x03,
++	0xA4, 0x03, 0xA5, 0x03, 0xA6, 0x03, 0xA7, 0x03,
++	0xA8, 0x03, 0xA9, 0x03, 0xAA, 0x03, 0xAB, 0x03,
++	0x8C, 0x03, 0x8E, 0x03, 0x8F, 0x03, 0xCF, 0x03,
++	0xD0, 0x03, 0xD1, 0x03, 0xD2, 0x03, 0xD3, 0x03,
++	0xD4, 0x03, 0xD5, 0x03, 0xD6, 0x03, 0xD7, 0x03,
++	0xD8, 0x03, 0xD8, 0x03, 0xDA, 0x03, 0xDA, 0x03,
++	0xDC, 0x03, 0xDC, 0x03, 0xDE, 0x03, 0xDE, 0x03,
++	0xE0, 0x03, 0xE0, 0x03, 0xE2, 0x03, 0xE2, 0x03,
++	0xE4, 0x03, 0xE4, 0x03, 0xE6, 0x03, 0xE6, 0x03,
++	0xE8, 0x03, 0xE8, 0x03, 0xEA, 0x03, 0xEA, 0x03,
++	0xEC, 0x03, 0xEC, 0x03, 0xEE, 0x03, 0xEE, 0x03,
++	0xF0, 0x03, 0xF1, 0x03, 0xF9, 0x03, 0xF3, 0x03,
++	0xF4, 0x03, 0xF5, 0x03, 0xF6, 0x03, 0xF7, 0x03,
++	0xF7, 0x03, 0xF9, 0x03, 0xFA, 0x03, 0xFA, 0x03,
++	0xFC, 0x03, 0xFD, 0x03, 0xFE, 0x03, 0xFF, 0x03,
++	0x00, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x04,
++	0x04, 0x04, 0x05, 0x04, 0x06, 0x04, 0x07, 0x04,
++	0x08, 0x04, 0x09, 0x04, 0x0A, 0x04, 0x0B, 0x04,
++	0x0C, 0x04, 0x0D, 0x04, 0x0E, 0x04, 0x0F, 0x04,
++	0x10, 0x04, 0x11, 0x04, 0x12, 0x04, 0x13, 0x04,
++	0x14, 0x04, 0x15, 0x04, 0x16, 0x04, 0x17, 0x04,
++	0x18, 0x04, 0x19, 0x04, 0x1A, 0x04, 0x1B, 0x04,
++	0x1C, 0x04, 0x1D, 0x04, 0x1E, 0x04, 0x1F, 0x04,
++	0x20, 0x04, 0x21, 0x04, 0x22, 0x04, 0x23, 0x04,
++	0x24, 0x04, 0x25, 0x04, 0x26, 0x04, 0x27, 0x04,
++	0x28, 0x04, 0x29, 0x04, 0x2A, 0x04, 0x2B, 0x04,
++	0x2C, 0x04, 0x2D, 0x04, 0x2E, 0x04, 0x2F, 0x04,
++	0x10, 0x04, 0x11, 0x04, 0x12, 0x04, 0x13, 0x04,
++	0x14, 0x04, 0x15, 0x04, 0x16, 0x04, 0x17, 0x04,
++	0x18, 0x04, 0x19, 0x04, 0x1A, 0x04, 0x1B, 0x04,
++	0x1C, 0x04, 0x1D, 0x04, 0x1E, 0x04, 0x1F, 0x04,
++	0x20, 0x04, 0x21, 0x04, 0x22, 0x04, 0x23, 0x04,
++	0x24, 0x04, 0x25, 0x04, 0x26, 0x04, 0x27, 0x04,
++	0x28, 0x04, 0x29, 0x04, 0x2A, 0x04, 0x2B, 0x04,
++	0x2C, 0x04, 0x2D, 0x04, 0x2E, 0x04, 0x2F, 0x04,
++	0x00, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x04,
++	0x04, 0x04, 0x05, 0x04, 0x06, 0x04, 0x07, 0x04,
++	0x08, 0x04, 0x09, 0x04, 0x0A, 0x04, 0x0B, 0x04,
++	0x0C, 0x04, 0x0D, 0x04, 0x0E, 0x04, 0x0F, 0x04,
++	0x60, 0x04, 0x60, 0x04, 0x62, 0x04, 0x62, 0x04,
++	0x64, 0x04, 0x64, 0x04, 0x66, 0x04, 0x66, 0x04,
++	0x68, 0x04, 0x68, 0x04, 0x6A, 0x04, 0x6A, 0x04,
++	0x6C, 0x04, 0x6C, 0x04, 0x6E, 0x04, 0x6E, 0x04,
++	0x70, 0x04, 0x70, 0x04, 0x72, 0x04, 0x72, 0x04,
++	0x74, 0x04, 0x74, 0x04, 0x76, 0x04, 0x76, 0x04,
++	0x78, 0x04, 0x78, 0x04, 0x7A, 0x04, 0x7A, 0x04,
++	0x7C, 0x04, 0x7C, 0x04, 0x7E, 0x04, 0x7E, 0x04,
++	0x80, 0x04, 0x80, 0x04, 0x82, 0x04, 0x83, 0x04,
++	0x84, 0x04, 0x85, 0x04, 0x86, 0x04, 0x87, 0x04,
++	0x88, 0x04, 0x89, 0x04, 0x8A, 0x04, 0x8A, 0x04,
++	0x8C, 0x04, 0x8C, 0x04, 0x8E, 0x04, 0x8E, 0x04,
++	0x90, 0x04, 0x90, 0x04, 0x92, 0x04, 0x92, 0x04,
++	0x94, 0x04, 0x94, 0x04, 0x96, 0x04, 0x96, 0x04,
++	0x98, 0x04, 0x98, 0x04, 0x9A, 0x04, 0x9A, 0x04,
++	0x9C, 0x04, 0x9C, 0x04, 0x9E, 0x04, 0x9E, 0x04,
++	0xA0, 0x04, 0xA0, 0x04, 0xA2, 0x04, 0xA2, 0x04,
++	0xA4, 0x04, 0xA4, 0x04, 0xA6, 0x04, 0xA6, 0x04,
++	0xA8, 0x04, 0xA8, 0x04, 0xAA, 0x04, 0xAA, 0x04,
++	0xAC, 0x04, 0xAC, 0x04, 0xAE, 0x04, 0xAE, 0x04,
++	0xB0, 0x04, 0xB0, 0x04, 0xB2, 0x04, 0xB2, 0x04,
++	0xB4, 0x04, 0xB4, 0x04, 0xB6, 0x04, 0xB6, 0x04,
++	0xB8, 0x04, 0xB8, 0x04, 0xBA, 0x04, 0xBA, 0x04,
++	0xBC, 0x04, 0xBC, 0x04, 0xBE, 0x04, 0xBE, 0x04,
++	0xC0, 0x04, 0xC1, 0x04, 0xC1, 0x04, 0xC3, 0x04,
++	0xC3, 0x04, 0xC5, 0x04, 0xC5, 0x04, 0xC7, 0x04,
++	0xC7, 0x04, 0xC9, 0x04, 0xC9, 0x04, 0xCB, 0x04,
++	0xCB, 0x04, 0xCD, 0x04, 0xCD, 0x04, 0xC0, 0x04,
++	0xD0, 0x04, 0xD0, 0x04, 0xD2, 0x04, 0xD2, 0x04,
++	0xD4, 0x04, 0xD4, 0x04, 0xD6, 0x04, 0xD6, 0x04,
++	0xD8, 0x04, 0xD8, 0x04, 0xDA, 0x04, 0xDA, 0x04,
++	0xDC, 0x04, 0xDC, 0x04, 0xDE, 0x04, 0xDE, 0x04,
++	0xE0, 0x04, 0xE0, 0x04, 0xE2, 0x04, 0xE2, 0x04,
++	0xE4, 0x04, 0xE4, 0x04, 0xE6, 0x04, 0xE6, 0x04,
++	0xE8, 0x04, 0xE8, 0x04, 0xEA, 0x04, 0xEA, 0x04,
++	0xEC, 0x04, 0xEC, 0x04, 0xEE, 0x04, 0xEE, 0x04,
++	0xF0, 0x04, 0xF0, 0x04, 0xF2, 0x04, 0xF2, 0x04,
++	0xF4, 0x04, 0xF4, 0x04, 0xF6, 0x04, 0xF6, 0x04,
++	0xF8, 0x04, 0xF8, 0x04, 0xFA, 0x04, 0xFA, 0x04,
++	0xFC, 0x04, 0xFC, 0x04, 0xFE, 0x04, 0xFE, 0x04,
++	0x00, 0x05, 0x00, 0x05, 0x02, 0x05, 0x02, 0x05,
++	0x04, 0x05, 0x04, 0x05, 0x06, 0x05, 0x06, 0x05,
++	0x08, 0x05, 0x08, 0x05, 0x0A, 0x05, 0x0A, 0x05,
++	0x0C, 0x05, 0x0C, 0x05, 0x0E, 0x05, 0x0E, 0x05,
++	0x10, 0x05, 0x10, 0x05, 0x12, 0x05, 0x12, 0x05,
++	0x14, 0x05, 0x15, 0x05, 0x16, 0x05, 0x17, 0x05,
++	0x18, 0x05, 0x19, 0x05, 0x1A, 0x05, 0x1B, 0x05,
++	0x1C, 0x05, 0x1D, 0x05, 0x1E, 0x05, 0x1F, 0x05,
++	0x20, 0x05, 0x21, 0x05, 0x22, 0x05, 0x23, 0x05,
++	0x24, 0x05, 0x25, 0x05, 0x26, 0x05, 0x27, 0x05,
++	0x28, 0x05, 0x29, 0x05, 0x2A, 0x05, 0x2B, 0x05,
++	0x2C, 0x05, 0x2D, 0x05, 0x2E, 0x05, 0x2F, 0x05,
++	0x30, 0x05, 0x31, 0x05, 0x32, 0x05, 0x33, 0x05,
++	0x34, 0x05, 0x35, 0x05, 0x36, 0x05, 0x37, 0x05,
++	0x38, 0x05, 0x39, 0x05, 0x3A, 0x05, 0x3B, 0x05,
++	0x3C, 0x05, 0x3D, 0x05, 0x3E, 0x05, 0x3F, 0x05,
++	0x40, 0x05, 0x41, 0x05, 0x42, 0x05, 0x43, 0x05,
++	0x44, 0x05, 0x45, 0x05, 0x46, 0x05, 0x47, 0x05,
++	0x48, 0x05, 0x49, 0x05, 0x4A, 0x05, 0x4B, 0x05,
++	0x4C, 0x05, 0x4D, 0x05, 0x4E, 0x05, 0x4F, 0x05,
++	0x50, 0x05, 0x51, 0x05, 0x52, 0x05, 0x53, 0x05,
++	0x54, 0x05, 0x55, 0x05, 0x56, 0x05, 0x57, 0x05,
++	0x58, 0x05, 0x59, 0x05, 0x5A, 0x05, 0x5B, 0x05,
++	0x5C, 0x05, 0x5D, 0x05, 0x5E, 0x05, 0x5F, 0x05,
++	0x60, 0x05, 0x31, 0x05, 0x32, 0x05, 0x33, 0x05,
++	0x34, 0x05, 0x35, 0x05, 0x36, 0x05, 0x37, 0x05,
++	0x38, 0x05, 0x39, 0x05, 0x3A, 0x05, 0x3B, 0x05,
++	0x3C, 0x05, 0x3D, 0x05, 0x3E, 0x05, 0x3F, 0x05,
++	0x40, 0x05, 0x41, 0x05, 0x42, 0x05, 0x43, 0x05,
++	0x44, 0x05, 0x45, 0x05, 0x46, 0x05, 0x47, 0x05,
++	0x48, 0x05, 0x49, 0x05, 0x4A, 0x05, 0x4B, 0x05,
++	0x4C, 0x05, 0x4D, 0x05, 0x4E, 0x05, 0x4F, 0x05,
++	0x50, 0x05, 0x51, 0x05, 0x52, 0x05, 0x53, 0x05,
++	0x54, 0x05, 0x55, 0x05, 0x56, 0x05, 0xFF, 0xFF,
++	0xF6, 0x17, 0x63, 0x2C, 0x7E, 0x1D, 0x7F, 0x1D,
++	0x80, 0x1D, 0x81, 0x1D, 0x82, 0x1D, 0x83, 0x1D,
++	0x84, 0x1D, 0x85, 0x1D, 0x86, 0x1D, 0x87, 0x1D,
++	0x88, 0x1D, 0x89, 0x1D, 0x8A, 0x1D, 0x8B, 0x1D,
++	0x8C, 0x1D, 0x8D, 0x1D, 0x8E, 0x1D, 0x8F, 0x1D,
++	0x90, 0x1D, 0x91, 0x1D, 0x92, 0x1D, 0x93, 0x1D,
++	0x94, 0x1D, 0x95, 0x1D, 0x96, 0x1D, 0x97, 0x1D,
++	0x98, 0x1D, 0x99, 0x1D, 0x9A, 0x1D, 0x9B, 0x1D,
++	0x9C, 0x1D, 0x9D, 0x1D, 0x9E, 0x1D, 0x9F, 0x1D,
++	0xA0, 0x1D, 0xA1, 0x1D, 0xA2, 0x1D, 0xA3, 0x1D,
++	0xA4, 0x1D, 0xA5, 0x1D, 0xA6, 0x1D, 0xA7, 0x1D,
++	0xA8, 0x1D, 0xA9, 0x1D, 0xAA, 0x1D, 0xAB, 0x1D,
++	0xAC, 0x1D, 0xAD, 0x1D, 0xAE, 0x1D, 0xAF, 0x1D,
++	0xB0, 0x1D, 0xB1, 0x1D, 0xB2, 0x1D, 0xB3, 0x1D,
++	0xB4, 0x1D, 0xB5, 0x1D, 0xB6, 0x1D, 0xB7, 0x1D,
++	0xB8, 0x1D, 0xB9, 0x1D, 0xBA, 0x1D, 0xBB, 0x1D,
++	0xBC, 0x1D, 0xBD, 0x1D, 0xBE, 0x1D, 0xBF, 0x1D,
++	0xC0, 0x1D, 0xC1, 0x1D, 0xC2, 0x1D, 0xC3, 0x1D,
++	0xC4, 0x1D, 0xC5, 0x1D, 0xC6, 0x1D, 0xC7, 0x1D,
++	0xC8, 0x1D, 0xC9, 0x1D, 0xCA, 0x1D, 0xCB, 0x1D,
++	0xCC, 0x1D, 0xCD, 0x1D, 0xCE, 0x1D, 0xCF, 0x1D,
++	0xD0, 0x1D, 0xD1, 0x1D, 0xD2, 0x1D, 0xD3, 0x1D,
++	0xD4, 0x1D, 0xD5, 0x1D, 0xD6, 0x1D, 0xD7, 0x1D,
++	0xD8, 0x1D, 0xD9, 0x1D, 0xDA, 0x1D, 0xDB, 0x1D,
++	0xDC, 0x1D, 0xDD, 0x1D, 0xDE, 0x1D, 0xDF, 0x1D,
++	0xE0, 0x1D, 0xE1, 0x1D, 0xE2, 0x1D, 0xE3, 0x1D,
++	0xE4, 0x1D, 0xE5, 0x1D, 0xE6, 0x1D, 0xE7, 0x1D,
++	0xE8, 0x1D, 0xE9, 0x1D, 0xEA, 0x1D, 0xEB, 0x1D,
++	0xEC, 0x1D, 0xED, 0x1D, 0xEE, 0x1D, 0xEF, 0x1D,
++	0xF0, 0x1D, 0xF1, 0x1D, 0xF2, 0x1D, 0xF3, 0x1D,
++	0xF4, 0x1D, 0xF5, 0x1D, 0xF6, 0x1D, 0xF7, 0x1D,
++	0xF8, 0x1D, 0xF9, 0x1D, 0xFA, 0x1D, 0xFB, 0x1D,
++	0xFC, 0x1D, 0xFD, 0x1D, 0xFE, 0x1D, 0xFF, 0x1D,
++	0x00, 0x1E, 0x00, 0x1E, 0x02, 0x1E, 0x02, 0x1E,
++	0x04, 0x1E, 0x04, 0x1E, 0x06, 0x1E, 0x06, 0x1E,
++	0x08, 0x1E, 0x08, 0x1E, 0x0A, 0x1E, 0x0A, 0x1E,
++	0x0C, 0x1E, 0x0C, 0x1E, 0x0E, 0x1E, 0x0E, 0x1E,
++	0x10, 0x1E, 0x10, 0x1E, 0x12, 0x1E, 0x12, 0x1E,
++	0x14, 0x1E, 0x14, 0x1E, 0x16, 0x1E, 0x16, 0x1E,
++	0x18, 0x1E, 0x18, 0x1E, 0x1A, 0x1E, 0x1A, 0x1E,
++	0x1C, 0x1E, 0x1C, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E,
++	0x20, 0x1E, 0x20, 0x1E, 0x22, 0x1E, 0x22, 0x1E,
++	0x24, 0x1E, 0x24, 0x1E, 0x26, 0x1E, 0x26, 0x1E,
++	0x28, 0x1E, 0x28, 0x1E, 0x2A, 0x1E, 0x2A, 0x1E,
++	0x2C, 0x1E, 0x2C, 0x1E, 0x2E, 0x1E, 0x2E, 0x1E,
++	0x30, 0x1E, 0x30, 0x1E, 0x32, 0x1E, 0x32, 0x1E,
++	0x34, 0x1E, 0x34, 0x1E, 0x36, 0x1E, 0x36, 0x1E,
++	0x38, 0x1E, 0x38, 0x1E, 0x3A, 0x1E, 0x3A, 0x1E,
++	0x3C, 0x1E, 0x3C, 0x1E, 0x3E, 0x1E, 0x3E, 0x1E,
++	0x40, 0x1E, 0x40, 0x1E, 0x42, 0x1E, 0x42, 0x1E,
++	0x44, 0x1E, 0x44, 0x1E, 0x46, 0x1E, 0x46, 0x1E,
++	0x48, 0x1E, 0x48, 0x1E, 0x4A, 0x1E, 0x4A, 0x1E,
++	0x4C, 0x1E, 0x4C, 0x1E, 0x4E, 0x1E, 0x4E, 0x1E,
++	0x50, 0x1E, 0x50, 0x1E, 0x52, 0x1E, 0x52, 0x1E,
++	0x54, 0x1E, 0x54, 0x1E, 0x56, 0x1E, 0x56, 0x1E,
++	0x58, 0x1E, 0x58, 0x1E, 0x5A, 0x1E, 0x5A, 0x1E,
++	0x5C, 0x1E, 0x5C, 0x1E, 0x5E, 0x1E, 0x5E, 0x1E,
++	0x60, 0x1E, 0x60, 0x1E, 0x62, 0x1E, 0x62, 0x1E,
++	0x64, 0x1E, 0x64, 0x1E, 0x66, 0x1E, 0x66, 0x1E,
++	0x68, 0x1E, 0x68, 0x1E, 0x6A, 0x1E, 0x6A, 0x1E,
++	0x6C, 0x1E, 0x6C, 0x1E, 0x6E, 0x1E, 0x6E, 0x1E,
++	0x70, 0x1E, 0x70, 0x1E, 0x72, 0x1E, 0x72, 0x1E,
++	0x74, 0x1E, 0x74, 0x1E, 0x76, 0x1E, 0x76, 0x1E,
++	0x78, 0x1E, 0x78, 0x1E, 0x7A, 0x1E, 0x7A, 0x1E,
++	0x7C, 0x1E, 0x7C, 0x1E, 0x7E, 0x1E, 0x7E, 0x1E,
++	0x80, 0x1E, 0x80, 0x1E, 0x82, 0x1E, 0x82, 0x1E,
++	0x84, 0x1E, 0x84, 0x1E, 0x86, 0x1E, 0x86, 0x1E,
++	0x88, 0x1E, 0x88, 0x1E, 0x8A, 0x1E, 0x8A, 0x1E,
++	0x8C, 0x1E, 0x8C, 0x1E, 0x8E, 0x1E, 0x8E, 0x1E,
++	0x90, 0x1E, 0x90, 0x1E, 0x92, 0x1E, 0x92, 0x1E,
++	0x94, 0x1E, 0x94, 0x1E, 0x96, 0x1E, 0x97, 0x1E,
++	0x98, 0x1E, 0x99, 0x1E, 0x9A, 0x1E, 0x9B, 0x1E,
++	0x9C, 0x1E, 0x9D, 0x1E, 0x9E, 0x1E, 0x9F, 0x1E,
++	0xA0, 0x1E, 0xA0, 0x1E, 0xA2, 0x1E, 0xA2, 0x1E,
++	0xA4, 0x1E, 0xA4, 0x1E, 0xA6, 0x1E, 0xA6, 0x1E,
++	0xA8, 0x1E, 0xA8, 0x1E, 0xAA, 0x1E, 0xAA, 0x1E,
++	0xAC, 0x1E, 0xAC, 0x1E, 0xAE, 0x1E, 0xAE, 0x1E,
++	0xB0, 0x1E, 0xB0, 0x1E, 0xB2, 0x1E, 0xB2, 0x1E,
++	0xB4, 0x1E, 0xB4, 0x1E, 0xB6, 0x1E, 0xB6, 0x1E,
++	0xB8, 0x1E, 0xB8, 0x1E, 0xBA, 0x1E, 0xBA, 0x1E,
++	0xBC, 0x1E, 0xBC, 0x1E, 0xBE, 0x1E, 0xBE, 0x1E,
++	0xC0, 0x1E, 0xC0, 0x1E, 0xC2, 0x1E, 0xC2, 0x1E,
++	0xC4, 0x1E, 0xC4, 0x1E, 0xC6, 0x1E, 0xC6, 0x1E,
++	0xC8, 0x1E, 0xC8, 0x1E, 0xCA, 0x1E, 0xCA, 0x1E,
++	0xCC, 0x1E, 0xCC, 0x1E, 0xCE, 0x1E, 0xCE, 0x1E,
++	0xD0, 0x1E, 0xD0, 0x1E, 0xD2, 0x1E, 0xD2, 0x1E,
++	0xD4, 0x1E, 0xD4, 0x1E, 0xD6, 0x1E, 0xD6, 0x1E,
++	0xD8, 0x1E, 0xD8, 0x1E, 0xDA, 0x1E, 0xDA, 0x1E,
++	0xDC, 0x1E, 0xDC, 0x1E, 0xDE, 0x1E, 0xDE, 0x1E,
++	0xE0, 0x1E, 0xE0, 0x1E, 0xE2, 0x1E, 0xE2, 0x1E,
++	0xE4, 0x1E, 0xE4, 0x1E, 0xE6, 0x1E, 0xE6, 0x1E,
++	0xE8, 0x1E, 0xE8, 0x1E, 0xEA, 0x1E, 0xEA, 0x1E,
++	0xEC, 0x1E, 0xEC, 0x1E, 0xEE, 0x1E, 0xEE, 0x1E,
++	0xF0, 0x1E, 0xF0, 0x1E, 0xF2, 0x1E, 0xF2, 0x1E,
++	0xF4, 0x1E, 0xF4, 0x1E, 0xF6, 0x1E, 0xF6, 0x1E,
++	0xF8, 0x1E, 0xF8, 0x1E, 0xFA, 0x1E, 0xFB, 0x1E,
++	0xFC, 0x1E, 0xFD, 0x1E, 0xFE, 0x1E, 0xFF, 0x1E,
++	0x08, 0x1F, 0x09, 0x1F, 0x0A, 0x1F, 0x0B, 0x1F,
++	0x0C, 0x1F, 0x0D, 0x1F, 0x0E, 0x1F, 0x0F, 0x1F,
++	0x08, 0x1F, 0x09, 0x1F, 0x0A, 0x1F, 0x0B, 0x1F,
++	0x0C, 0x1F, 0x0D, 0x1F, 0x0E, 0x1F, 0x0F, 0x1F,
++	0x18, 0x1F, 0x19, 0x1F, 0x1A, 0x1F, 0x1B, 0x1F,
++	0x1C, 0x1F, 0x1D, 0x1F, 0x16, 0x1F, 0x17, 0x1F,
++	0x18, 0x1F, 0x19, 0x1F, 0x1A, 0x1F, 0x1B, 0x1F,
++	0x1C, 0x1F, 0x1D, 0x1F, 0x1E, 0x1F, 0x1F, 0x1F,
++	0x28, 0x1F, 0x29, 0x1F, 0x2A, 0x1F, 0x2B, 0x1F,
++	0x2C, 0x1F, 0x2D, 0x1F, 0x2E, 0x1F, 0x2F, 0x1F,
++	0x28, 0x1F, 0x29, 0x1F, 0x2A, 0x1F, 0x2B, 0x1F,
++	0x2C, 0x1F, 0x2D, 0x1F, 0x2E, 0x1F, 0x2F, 0x1F,
++	0x38, 0x1F, 0x39, 0x1F, 0x3A, 0x1F, 0x3B, 0x1F,
++	0x3C, 0x1F, 0x3D, 0x1F, 0x3E, 0x1F, 0x3F, 0x1F,
++	0x38, 0x1F, 0x39, 0x1F, 0x3A, 0x1F, 0x3B, 0x1F,
++	0x3C, 0x1F, 0x3D, 0x1F, 0x3E, 0x1F, 0x3F, 0x1F,
++	0x48, 0x1F, 0x49, 0x1F, 0x4A, 0x1F, 0x4B, 0x1F,
++	0x4C, 0x1F, 0x4D, 0x1F, 0x46, 0x1F, 0x47, 0x1F,
++	0x48, 0x1F, 0x49, 0x1F, 0x4A, 0x1F, 0x4B, 0x1F,
++	0x4C, 0x1F, 0x4D, 0x1F, 0x4E, 0x1F, 0x4F, 0x1F,
++	0x50, 0x1F, 0x59, 0x1F, 0x52, 0x1F, 0x5B, 0x1F,
++	0x54, 0x1F, 0x5D, 0x1F, 0x56, 0x1F, 0x5F, 0x1F,
++	0x58, 0x1F, 0x59, 0x1F, 0x5A, 0x1F, 0x5B, 0x1F,
++	0x5C, 0x1F, 0x5D, 0x1F, 0x5E, 0x1F, 0x5F, 0x1F,
++	0x68, 0x1F, 0x69, 0x1F, 0x6A, 0x1F, 0x6B, 0x1F,
++	0x6C, 0x1F, 0x6D, 0x1F, 0x6E, 0x1F, 0x6F, 0x1F,
++	0x68, 0x1F, 0x69, 0x1F, 0x6A, 0x1F, 0x6B, 0x1F,
++	0x6C, 0x1F, 0x6D, 0x1F, 0x6E, 0x1F, 0x6F, 0x1F,
++	0xBA, 0x1F, 0xBB, 0x1F, 0xC8, 0x1F, 0xC9, 0x1F,
++	0xCA, 0x1F, 0xCB, 0x1F, 0xDA, 0x1F, 0xDB, 0x1F,
++	0xF8, 0x1F, 0xF9, 0x1F, 0xEA, 0x1F, 0xEB, 0x1F,
++	0xFA, 0x1F, 0xFB, 0x1F, 0x7E, 0x1F, 0x7F, 0x1F,
++	0x88, 0x1F, 0x89, 0x1F, 0x8A, 0x1F, 0x8B, 0x1F,
++	0x8C, 0x1F, 0x8D, 0x1F, 0x8E, 0x1F, 0x8F, 0x1F,
++	0x88, 0x1F, 0x89, 0x1F, 0x8A, 0x1F, 0x8B, 0x1F,
++	0x8C, 0x1F, 0x8D, 0x1F, 0x8E, 0x1F, 0x8F, 0x1F,
++	0x98, 0x1F, 0x99, 0x1F, 0x9A, 0x1F, 0x9B, 0x1F,
++	0x9C, 0x1F, 0x9D, 0x1F, 0x9E, 0x1F, 0x9F, 0x1F,
++	0x98, 0x1F, 0x99, 0x1F, 0x9A, 0x1F, 0x9B, 0x1F,
++	0x9C, 0x1F, 0x9D, 0x1F, 0x9E, 0x1F, 0x9F, 0x1F,
++	0xA8, 0x1F, 0xA9, 0x1F, 0xAA, 0x1F, 0xAB, 0x1F,
++	0xAC, 0x1F, 0xAD, 0x1F, 0xAE, 0x1F, 0xAF, 0x1F,
++	0xA8, 0x1F, 0xA9, 0x1F, 0xAA, 0x1F, 0xAB, 0x1F,
++	0xAC, 0x1F, 0xAD, 0x1F, 0xAE, 0x1F, 0xAF, 0x1F,
++	0xB8, 0x1F, 0xB9, 0x1F, 0xB2, 0x1F, 0xBC, 0x1F,
++	0xB4, 0x1F, 0xB5, 0x1F, 0xB6, 0x1F, 0xB7, 0x1F,
++	0xB8, 0x1F, 0xB9, 0x1F, 0xBA, 0x1F, 0xBB, 0x1F,
++	0xBC, 0x1F, 0xBD, 0x1F, 0xBE, 0x1F, 0xBF, 0x1F,
++	0xC0, 0x1F, 0xC1, 0x1F, 0xC2, 0x1F, 0xC3, 0x1F,
++	0xC4, 0x1F, 0xC5, 0x1F, 0xC6, 0x1F, 0xC7, 0x1F,
++	0xC8, 0x1F, 0xC9, 0x1F, 0xCA, 0x1F, 0xCB, 0x1F,
++	0xC3, 0x1F, 0xCD, 0x1F, 0xCE, 0x1F, 0xCF, 0x1F,
++	0xD8, 0x1F, 0xD9, 0x1F, 0xD2, 0x1F, 0xD3, 0x1F,
++	0xD4, 0x1F, 0xD5, 0x1F, 0xD6, 0x1F, 0xD7, 0x1F,
++	0xD8, 0x1F, 0xD9, 0x1F, 0xDA, 0x1F, 0xDB, 0x1F,
++	0xDC, 0x1F, 0xDD, 0x1F, 0xDE, 0x1F, 0xDF, 0x1F,
++	0xE8, 0x1F, 0xE9, 0x1F, 0xE2, 0x1F, 0xE3, 0x1F,
++	0xE4, 0x1F, 0xEC, 0x1F, 0xE6, 0x1F, 0xE7, 0x1F,
++	0xE8, 0x1F, 0xE9, 0x1F, 0xEA, 0x1F, 0xEB, 0x1F,
++	0xEC, 0x1F, 0xED, 0x1F, 0xEE, 0x1F, 0xEF, 0x1F,
++	0xF0, 0x1F, 0xF1, 0x1F, 0xF2, 0x1F, 0xF3, 0x1F,
++	0xF4, 0x1F, 0xF5, 0x1F, 0xF6, 0x1F, 0xF7, 0x1F,
++	0xF8, 0x1F, 0xF9, 0x1F, 0xFA, 0x1F, 0xFB, 0x1F,
++	0xF3, 0x1F, 0xFD, 0x1F, 0xFE, 0x1F, 0xFF, 0x1F,
++	0x00, 0x20, 0x01, 0x20, 0x02, 0x20, 0x03, 0x20,
++	0x04, 0x20, 0x05, 0x20, 0x06, 0x20, 0x07, 0x20,
++	0x08, 0x20, 0x09, 0x20, 0x0A, 0x20, 0x0B, 0x20,
++	0x0C, 0x20, 0x0D, 0x20, 0x0E, 0x20, 0x0F, 0x20,
++	0x10, 0x20, 0x11, 0x20, 0x12, 0x20, 0x13, 0x20,
++	0x14, 0x20, 0x15, 0x20, 0x16, 0x20, 0x17, 0x20,
++	0x18, 0x20, 0x19, 0x20, 0x1A, 0x20, 0x1B, 0x20,
++	0x1C, 0x20, 0x1D, 0x20, 0x1E, 0x20, 0x1F, 0x20,
++	0x20, 0x20, 0x21, 0x20, 0x22, 0x20, 0x23, 0x20,
++	0x24, 0x20, 0x25, 0x20, 0x26, 0x20, 0x27, 0x20,
++	0x28, 0x20, 0x29, 0x20, 0x2A, 0x20, 0x2B, 0x20,
++	0x2C, 0x20, 0x2D, 0x20, 0x2E, 0x20, 0x2F, 0x20,
++	0x30, 0x20, 0x31, 0x20, 0x32, 0x20, 0x33, 0x20,
++	0x34, 0x20, 0x35, 0x20, 0x36, 0x20, 0x37, 0x20,
++	0x38, 0x20, 0x39, 0x20, 0x3A, 0x20, 0x3B, 0x20,
++	0x3C, 0x20, 0x3D, 0x20, 0x3E, 0x20, 0x3F, 0x20,
++	0x40, 0x20, 0x41, 0x20, 0x42, 0x20, 0x43, 0x20,
++	0x44, 0x20, 0x45, 0x20, 0x46, 0x20, 0x47, 0x20,
++	0x48, 0x20, 0x49, 0x20, 0x4A, 0x20, 0x4B, 0x20,
++	0x4C, 0x20, 0x4D, 0x20, 0x4E, 0x20, 0x4F, 0x20,
++	0x50, 0x20, 0x51, 0x20, 0x52, 0x20, 0x53, 0x20,
++	0x54, 0x20, 0x55, 0x20, 0x56, 0x20, 0x57, 0x20,
++	0x58, 0x20, 0x59, 0x20, 0x5A, 0x20, 0x5B, 0x20,
++	0x5C, 0x20, 0x5D, 0x20, 0x5E, 0x20, 0x5F, 0x20,
++	0x60, 0x20, 0x61, 0x20, 0x62, 0x20, 0x63, 0x20,
++	0x64, 0x20, 0x65, 0x20, 0x66, 0x20, 0x67, 0x20,
++	0x68, 0x20, 0x69, 0x20, 0x6A, 0x20, 0x6B, 0x20,
++	0x6C, 0x20, 0x6D, 0x20, 0x6E, 0x20, 0x6F, 0x20,
++	0x70, 0x20, 0x71, 0x20, 0x72, 0x20, 0x73, 0x20,
++	0x74, 0x20, 0x75, 0x20, 0x76, 0x20, 0x77, 0x20,
++	0x78, 0x20, 0x79, 0x20, 0x7A, 0x20, 0x7B, 0x20,
++	0x7C, 0x20, 0x7D, 0x20, 0x7E, 0x20, 0x7F, 0x20,
++	0x80, 0x20, 0x81, 0x20, 0x82, 0x20, 0x83, 0x20,
++	0x84, 0x20, 0x85, 0x20, 0x86, 0x20, 0x87, 0x20,
++	0x88, 0x20, 0x89, 0x20, 0x8A, 0x20, 0x8B, 0x20,
++	0x8C, 0x20, 0x8D, 0x20, 0x8E, 0x20, 0x8F, 0x20,
++	0x90, 0x20, 0x91, 0x20, 0x92, 0x20, 0x93, 0x20,
++	0x94, 0x20, 0x95, 0x20, 0x96, 0x20, 0x97, 0x20,
++	0x98, 0x20, 0x99, 0x20, 0x9A, 0x20, 0x9B, 0x20,
++	0x9C, 0x20, 0x9D, 0x20, 0x9E, 0x20, 0x9F, 0x20,
++	0xA0, 0x20, 0xA1, 0x20, 0xA2, 0x20, 0xA3, 0x20,
++	0xA4, 0x20, 0xA5, 0x20, 0xA6, 0x20, 0xA7, 0x20,
++	0xA8, 0x20, 0xA9, 0x20, 0xAA, 0x20, 0xAB, 0x20,
++	0xAC, 0x20, 0xAD, 0x20, 0xAE, 0x20, 0xAF, 0x20,
++	0xB0, 0x20, 0xB1, 0x20, 0xB2, 0x20, 0xB3, 0x20,
++	0xB4, 0x20, 0xB5, 0x20, 0xB6, 0x20, 0xB7, 0x20,
++	0xB8, 0x20, 0xB9, 0x20, 0xBA, 0x20, 0xBB, 0x20,
++	0xBC, 0x20, 0xBD, 0x20, 0xBE, 0x20, 0xBF, 0x20,
++	0xC0, 0x20, 0xC1, 0x20, 0xC2, 0x20, 0xC3, 0x20,
++	0xC4, 0x20, 0xC5, 0x20, 0xC6, 0x20, 0xC7, 0x20,
++	0xC8, 0x20, 0xC9, 0x20, 0xCA, 0x20, 0xCB, 0x20,
++	0xCC, 0x20, 0xCD, 0x20, 0xCE, 0x20, 0xCF, 0x20,
++	0xD0, 0x20, 0xD1, 0x20, 0xD2, 0x20, 0xD3, 0x20,
++	0xD4, 0x20, 0xD5, 0x20, 0xD6, 0x20, 0xD7, 0x20,
++	0xD8, 0x20, 0xD9, 0x20, 0xDA, 0x20, 0xDB, 0x20,
++	0xDC, 0x20, 0xDD, 0x20, 0xDE, 0x20, 0xDF, 0x20,
++	0xE0, 0x20, 0xE1, 0x20, 0xE2, 0x20, 0xE3, 0x20,
++	0xE4, 0x20, 0xE5, 0x20, 0xE6, 0x20, 0xE7, 0x20,
++	0xE8, 0x20, 0xE9, 0x20, 0xEA, 0x20, 0xEB, 0x20,
++	0xEC, 0x20, 0xED, 0x20, 0xEE, 0x20, 0xEF, 0x20,
++	0xF0, 0x20, 0xF1, 0x20, 0xF2, 0x20, 0xF3, 0x20,
++	0xF4, 0x20, 0xF5, 0x20, 0xF6, 0x20, 0xF7, 0x20,
++	0xF8, 0x20, 0xF9, 0x20, 0xFA, 0x20, 0xFB, 0x20,
++	0xFC, 0x20, 0xFD, 0x20, 0xFE, 0x20, 0xFF, 0x20,
++	0x00, 0x21, 0x01, 0x21, 0x02, 0x21, 0x03, 0x21,
++	0x04, 0x21, 0x05, 0x21, 0x06, 0x21, 0x07, 0x21,
++	0x08, 0x21, 0x09, 0x21, 0x0A, 0x21, 0x0B, 0x21,
++	0x0C, 0x21, 0x0D, 0x21, 0x0E, 0x21, 0x0F, 0x21,
++	0x10, 0x21, 0x11, 0x21, 0x12, 0x21, 0x13, 0x21,
++	0x14, 0x21, 0x15, 0x21, 0x16, 0x21, 0x17, 0x21,
++	0x18, 0x21, 0x19, 0x21, 0x1A, 0x21, 0x1B, 0x21,
++	0x1C, 0x21, 0x1D, 0x21, 0x1E, 0x21, 0x1F, 0x21,
++	0x20, 0x21, 0x21, 0x21, 0x22, 0x21, 0x23, 0x21,
++	0x24, 0x21, 0x25, 0x21, 0x26, 0x21, 0x27, 0x21,
++	0x28, 0x21, 0x29, 0x21, 0x2A, 0x21, 0x2B, 0x21,
++	0x2C, 0x21, 0x2D, 0x21, 0x2E, 0x21, 0x2F, 0x21,
++	0x30, 0x21, 0x31, 0x21, 0x32, 0x21, 0x33, 0x21,
++	0x34, 0x21, 0x35, 0x21, 0x36, 0x21, 0x37, 0x21,
++	0x38, 0x21, 0x39, 0x21, 0x3A, 0x21, 0x3B, 0x21,
++	0x3C, 0x21, 0x3D, 0x21, 0x3E, 0x21, 0x3F, 0x21,
++	0x40, 0x21, 0x41, 0x21, 0x42, 0x21, 0x43, 0x21,
++	0x44, 0x21, 0x45, 0x21, 0x46, 0x21, 0x47, 0x21,
++	0x48, 0x21, 0x49, 0x21, 0x4A, 0x21, 0x4B, 0x21,
++	0x4C, 0x21, 0x4D, 0x21, 0x32, 0x21, 0x4F, 0x21,
++	0x50, 0x21, 0x51, 0x21, 0x52, 0x21, 0x53, 0x21,
++	0x54, 0x21, 0x55, 0x21, 0x56, 0x21, 0x57, 0x21,
++	0x58, 0x21, 0x59, 0x21, 0x5A, 0x21, 0x5B, 0x21,
++	0x5C, 0x21, 0x5D, 0x21, 0x5E, 0x21, 0x5F, 0x21,
++	0x60, 0x21, 0x61, 0x21, 0x62, 0x21, 0x63, 0x21,
++	0x64, 0x21, 0x65, 0x21, 0x66, 0x21, 0x67, 0x21,
++	0x68, 0x21, 0x69, 0x21, 0x6A, 0x21, 0x6B, 0x21,
++	0x6C, 0x21, 0x6D, 0x21, 0x6E, 0x21, 0x6F, 0x21,
++	0x60, 0x21, 0x61, 0x21, 0x62, 0x21, 0x63, 0x21,
++	0x64, 0x21, 0x65, 0x21, 0x66, 0x21, 0x67, 0x21,
++	0x68, 0x21, 0x69, 0x21, 0x6A, 0x21, 0x6B, 0x21,
++	0x6C, 0x21, 0x6D, 0x21, 0x6E, 0x21, 0x6F, 0x21,
++	0x80, 0x21, 0x81, 0x21, 0x82, 0x21, 0x83, 0x21,
++	0x83, 0x21, 0xFF, 0xFF, 0x4B, 0x03, 0xB6, 0x24,
++	0xB7, 0x24, 0xB8, 0x24, 0xB9, 0x24, 0xBA, 0x24,
++	0xBB, 0x24, 0xBC, 0x24, 0xBD, 0x24, 0xBE, 0x24,
++	0xBF, 0x24, 0xC0, 0x24, 0xC1, 0x24, 0xC2, 0x24,
++	0xC3, 0x24, 0xC4, 0x24, 0xC5, 0x24, 0xC6, 0x24,
++	0xC7, 0x24, 0xC8, 0x24, 0xC9, 0x24, 0xCA, 0x24,
++	0xCB, 0x24, 0xCC, 0x24, 0xCD, 0x24, 0xCE, 0x24,
++	0xCF, 0x24, 0xFF, 0xFF, 0x46, 0x07, 0x00, 0x2C,
++	0x01, 0x2C, 0x02, 0x2C, 0x03, 0x2C, 0x04, 0x2C,
++	0x05, 0x2C, 0x06, 0x2C, 0x07, 0x2C, 0x08, 0x2C,
++	0x09, 0x2C, 0x0A, 0x2C, 0x0B, 0x2C, 0x0C, 0x2C,
++	0x0D, 0x2C, 0x0E, 0x2C, 0x0F, 0x2C, 0x10, 0x2C,
++	0x11, 0x2C, 0x12, 0x2C, 0x13, 0x2C, 0x14, 0x2C,
++	0x15, 0x2C, 0x16, 0x2C, 0x17, 0x2C, 0x18, 0x2C,
++	0x19, 0x2C, 0x1A, 0x2C, 0x1B, 0x2C, 0x1C, 0x2C,
++	0x1D, 0x2C, 0x1E, 0x2C, 0x1F, 0x2C, 0x20, 0x2C,
++	0x21, 0x2C, 0x22, 0x2C, 0x23, 0x2C, 0x24, 0x2C,
++	0x25, 0x2C, 0x26, 0x2C, 0x27, 0x2C, 0x28, 0x2C,
++	0x29, 0x2C, 0x2A, 0x2C, 0x2B, 0x2C, 0x2C, 0x2C,
++	0x2D, 0x2C, 0x2E, 0x2C, 0x5F, 0x2C, 0x60, 0x2C,
++	0x60, 0x2C, 0x62, 0x2C, 0x63, 0x2C, 0x64, 0x2C,
++	0x65, 0x2C, 0x66, 0x2C, 0x67, 0x2C, 0x67, 0x2C,
++	0x69, 0x2C, 0x69, 0x2C, 0x6B, 0x2C, 0x6B, 0x2C,
++	0x6D, 0x2C, 0x6E, 0x2C, 0x6F, 0x2C, 0x70, 0x2C,
++	0x71, 0x2C, 0x72, 0x2C, 0x73, 0x2C, 0x74, 0x2C,
++	0x75, 0x2C, 0x75, 0x2C, 0x77, 0x2C, 0x78, 0x2C,
++	0x79, 0x2C, 0x7A, 0x2C, 0x7B, 0x2C, 0x7C, 0x2C,
++	0x7D, 0x2C, 0x7E, 0x2C, 0x7F, 0x2C, 0x80, 0x2C,
++	0x80, 0x2C, 0x82, 0x2C, 0x82, 0x2C, 0x84, 0x2C,
++	0x84, 0x2C, 0x86, 0x2C, 0x86, 0x2C, 0x88, 0x2C,
++	0x88, 0x2C, 0x8A, 0x2C, 0x8A, 0x2C, 0x8C, 0x2C,
++	0x8C, 0x2C, 0x8E, 0x2C, 0x8E, 0x2C, 0x90, 0x2C,
++	0x90, 0x2C, 0x92, 0x2C, 0x92, 0x2C, 0x94, 0x2C,
++	0x94, 0x2C, 0x96, 0x2C, 0x96, 0x2C, 0x98, 0x2C,
++	0x98, 0x2C, 0x9A, 0x2C, 0x9A, 0x2C, 0x9C, 0x2C,
++	0x9C, 0x2C, 0x9E, 0x2C, 0x9E, 0x2C, 0xA0, 0x2C,
++	0xA0, 0x2C, 0xA2, 0x2C, 0xA2, 0x2C, 0xA4, 0x2C,
++	0xA4, 0x2C, 0xA6, 0x2C, 0xA6, 0x2C, 0xA8, 0x2C,
++	0xA8, 0x2C, 0xAA, 0x2C, 0xAA, 0x2C, 0xAC, 0x2C,
++	0xAC, 0x2C, 0xAE, 0x2C, 0xAE, 0x2C, 0xB0, 0x2C,
++	0xB0, 0x2C, 0xB2, 0x2C, 0xB2, 0x2C, 0xB4, 0x2C,
++	0xB4, 0x2C, 0xB6, 0x2C, 0xB6, 0x2C, 0xB8, 0x2C,
++	0xB8, 0x2C, 0xBA, 0x2C, 0xBA, 0x2C, 0xBC, 0x2C,
++	0xBC, 0x2C, 0xBE, 0x2C, 0xBE, 0x2C, 0xC0, 0x2C,
++	0xC0, 0x2C, 0xC2, 0x2C, 0xC2, 0x2C, 0xC4, 0x2C,
++	0xC4, 0x2C, 0xC6, 0x2C, 0xC6, 0x2C, 0xC8, 0x2C,
++	0xC8, 0x2C, 0xCA, 0x2C, 0xCA, 0x2C, 0xCC, 0x2C,
++	0xCC, 0x2C, 0xCE, 0x2C, 0xCE, 0x2C, 0xD0, 0x2C,
++	0xD0, 0x2C, 0xD2, 0x2C, 0xD2, 0x2C, 0xD4, 0x2C,
++	0xD4, 0x2C, 0xD6, 0x2C, 0xD6, 0x2C, 0xD8, 0x2C,
++	0xD8, 0x2C, 0xDA, 0x2C, 0xDA, 0x2C, 0xDC, 0x2C,
++	0xDC, 0x2C, 0xDE, 0x2C, 0xDE, 0x2C, 0xE0, 0x2C,
++	0xE0, 0x2C, 0xE2, 0x2C, 0xE2, 0x2C, 0xE4, 0x2C,
++	0xE5, 0x2C, 0xE6, 0x2C, 0xE7, 0x2C, 0xE8, 0x2C,
++	0xE9, 0x2C, 0xEA, 0x2C, 0xEB, 0x2C, 0xEC, 0x2C,
++	0xED, 0x2C, 0xEE, 0x2C, 0xEF, 0x2C, 0xF0, 0x2C,
++	0xF1, 0x2C, 0xF2, 0x2C, 0xF3, 0x2C, 0xF4, 0x2C,
++	0xF5, 0x2C, 0xF6, 0x2C, 0xF7, 0x2C, 0xF8, 0x2C,
++	0xF9, 0x2C, 0xFA, 0x2C, 0xFB, 0x2C, 0xFC, 0x2C,
++	0xFD, 0x2C, 0xFE, 0x2C, 0xFF, 0x2C, 0xA0, 0x10,
++	0xA1, 0x10, 0xA2, 0x10, 0xA3, 0x10, 0xA4, 0x10,
++	0xA5, 0x10, 0xA6, 0x10, 0xA7, 0x10, 0xA8, 0x10,
++	0xA9, 0x10, 0xAA, 0x10, 0xAB, 0x10, 0xAC, 0x10,
++	0xAD, 0x10, 0xAE, 0x10, 0xAF, 0x10, 0xB0, 0x10,
++	0xB1, 0x10, 0xB2, 0x10, 0xB3, 0x10, 0xB4, 0x10,
++	0xB5, 0x10, 0xB6, 0x10, 0xB7, 0x10, 0xB8, 0x10,
++	0xB9, 0x10, 0xBA, 0x10, 0xBB, 0x10, 0xBC, 0x10,
++	0xBD, 0x10, 0xBE, 0x10, 0xBF, 0x10, 0xC0, 0x10,
++	0xC1, 0x10, 0xC2, 0x10, 0xC3, 0x10, 0xC4, 0x10,
++	0xC5, 0x10, 0xFF, 0xFF, 0x1B, 0xD2, 0x21, 0xFF,
++	0x22, 0xFF, 0x23, 0xFF, 0x24, 0xFF, 0x25, 0xFF,
++	0x26, 0xFF, 0x27, 0xFF, 0x28, 0xFF, 0x29, 0xFF,
++	0x2A, 0xFF, 0x2B, 0xFF, 0x2C, 0xFF, 0x2D, 0xFF,
++	0x2E, 0xFF, 0x2F, 0xFF, 0x30, 0xFF, 0x31, 0xFF,
++	0x32, 0xFF, 0x33, 0xFF, 0x34, 0xFF, 0x35, 0xFF,
++	0x36, 0xFF, 0x37, 0xFF, 0x38, 0xFF, 0x39, 0xFF,
++	0x3A, 0xFF, 0x5B, 0xFF, 0x5C, 0xFF, 0x5D, 0xFF,
++	0x5E, 0xFF, 0x5F, 0xFF, 0x60, 0xFF, 0x61, 0xFF,
++	0x62, 0xFF, 0x63, 0xFF, 0x64, 0xFF, 0x65, 0xFF,
++	0x66, 0xFF, 0x67, 0xFF, 0x68, 0xFF, 0x69, 0xFF,
++	0x6A, 0xFF, 0x6B, 0xFF, 0x6C, 0xFF, 0x6D, 0xFF,
++	0x6E, 0xFF, 0x6F, 0xFF, 0x70, 0xFF, 0x71, 0xFF,
++	0x72, 0xFF, 0x73, 0xFF, 0x74, 0xFF, 0x75, 0xFF,
++	0x76, 0xFF, 0x77, 0xFF, 0x78, 0xFF, 0x79, 0xFF,
++	0x7A, 0xFF, 0x7B, 0xFF, 0x7C, 0xFF, 0x7D, 0xFF,
++	0x7E, 0xFF, 0x7F, 0xFF, 0x80, 0xFF, 0x81, 0xFF,
++	0x82, 0xFF, 0x83, 0xFF, 0x84, 0xFF, 0x85, 0xFF,
++	0x86, 0xFF, 0x87, 0xFF, 0x88, 0xFF, 0x89, 0xFF,
++	0x8A, 0xFF, 0x8B, 0xFF, 0x8C, 0xFF, 0x8D, 0xFF,
++	0x8E, 0xFF, 0x8F, 0xFF, 0x90, 0xFF, 0x91, 0xFF,
++	0x92, 0xFF, 0x93, 0xFF, 0x94, 0xFF, 0x95, 0xFF,
++	0x96, 0xFF, 0x97, 0xFF, 0x98, 0xFF, 0x99, 0xFF,
++	0x9A, 0xFF, 0x9B, 0xFF, 0x9C, 0xFF, 0x9D, 0xFF,
++	0x9E, 0xFF, 0x9F, 0xFF, 0xA0, 0xFF, 0xA1, 0xFF,
++	0xA2, 0xFF, 0xA3, 0xFF, 0xA4, 0xFF, 0xA5, 0xFF,
++	0xA6, 0xFF, 0xA7, 0xFF, 0xA8, 0xFF, 0xA9, 0xFF,
++	0xAA, 0xFF, 0xAB, 0xFF, 0xAC, 0xFF, 0xAD, 0xFF,
++	0xAE, 0xFF, 0xAF, 0xFF, 0xB0, 0xFF, 0xB1, 0xFF,
++	0xB2, 0xFF, 0xB3, 0xFF, 0xB4, 0xFF, 0xB5, 0xFF,
++	0xB6, 0xFF, 0xB7, 0xFF, 0xB8, 0xFF, 0xB9, 0xFF,
++	0xBA, 0xFF, 0xBB, 0xFF, 0xBC, 0xFF, 0xBD, 0xFF,
++	0xBE, 0xFF, 0xBF, 0xFF, 0xC0, 0xFF, 0xC1, 0xFF,
++	0xC2, 0xFF, 0xC3, 0xFF, 0xC4, 0xFF, 0xC5, 0xFF,
++	0xC6, 0xFF, 0xC7, 0xFF, 0xC8, 0xFF, 0xC9, 0xFF,
++	0xCA, 0xFF, 0xCB, 0xFF, 0xCC, 0xFF, 0xCD, 0xFF,
++	0xCE, 0xFF, 0xCF, 0xFF, 0xD0, 0xFF, 0xD1, 0xFF,
++	0xD2, 0xFF, 0xD3, 0xFF, 0xD4, 0xFF, 0xD5, 0xFF,
++	0xD6, 0xFF, 0xD7, 0xFF, 0xD8, 0xFF, 0xD9, 0xFF,
++	0xDA, 0xFF, 0xDB, 0xFF, 0xDC, 0xFF, 0xDD, 0xFF,
++	0xDE, 0xFF, 0xDF, 0xFF, 0xE0, 0xFF, 0xE1, 0xFF,
++	0xE2, 0xFF, 0xE3, 0xFF, 0xE4, 0xFF, 0xE5, 0xFF,
++	0xE6, 0xFF, 0xE7, 0xFF, 0xE8, 0xFF, 0xE9, 0xFF,
++	0xEA, 0xFF, 0xEB, 0xFF, 0xEC, 0xFF, 0xED, 0xFF,
++	0xEE, 0xFF, 0xEF, 0xFF, 0xF0, 0xFF, 0xF1, 0xFF,
++	0xF2, 0xFF, 0xF3, 0xFF, 0xF4, 0xFF, 0xF5, 0xFF,
++	0xF6, 0xFF, 0xF7, 0xFF, 0xF8, 0xFF, 0xF9, 0xFF,
++	0xFA, 0xFF, 0xFB, 0xFF, 0xFC, 0xFF, 0xFD, 0xFF,
++	0xFE, 0xFF, 0xFF, 0xFF
++};

commit 0a30ba509fdeea740bedb81ce3bee4f74a759654
+Author: Valdis Kletnieks 
+Date:   Thu Aug 8 01:43:22 2019 -0400
+
+    netfilter: nf_nat_proto: make tables static
+    
+    Sparse warns about two tables not being declared.
+    
+      CHECK   net/netfilter/nf_nat_proto.c
+    net/netfilter/nf_nat_proto.c:725:26: warning: symbol 'nf_nat_ipv4_ops' was not declared. Should it be static?
+    net/netfilter/nf_nat_proto.c:964:26: warning: symbol 'nf_nat_ipv6_ops' was not declared. Should it be static?
+    
+    And in fact they can indeed be static.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Acked-by: Florian Westphal 
+    Signed-off-by: Pablo Neira Ayuso 
+
+diff --git a/net/netfilter/nf_nat_proto.c b/net/netfilter/nf_nat_proto.c
+index 7ac733ebd060..0a59c14b5177 100644
+--- a/net/netfilter/nf_nat_proto.c
++++ b/net/netfilter/nf_nat_proto.c
+@@ -722,7 +722,7 @@ nf_nat_ipv4_local_fn(void *priv, struct sk_buff *skb,
+ 	return ret;
+ }
+ 
+-const struct nf_hook_ops nf_nat_ipv4_ops[] = {
++static const struct nf_hook_ops nf_nat_ipv4_ops[] = {
+ 	/* Before packet filtering, change destination */
+ 	{
+ 		.hook		= nf_nat_ipv4_in,
+@@ -961,7 +961,7 @@ nf_nat_ipv6_local_fn(void *priv, struct sk_buff *skb,
+ 	return ret;
+ }
+ 
+-const struct nf_hook_ops nf_nat_ipv6_ops[] = {
++static const struct nf_hook_ops nf_nat_ipv6_ops[] = {
+ 	/* Before packet filtering, change destination */
+ 	{
+ 		.hook		= nf_nat_ipv6_in,

commit 5785cf15fd74ec3b1a076fd39bc67382a8455fe7
+Author: Valdis Kletnieks 
+Date:   Thu Aug 8 01:28:08 2019 -0400
+
+    netfilter: nf_tables: add missing prototypes.
+    
+    Sparse rightly complains about undeclared symbols.
+    
+      CHECK   net/netfilter/nft_set_hash.c
+    net/netfilter/nft_set_hash.c:647:21: warning: symbol 'nft_set_rhash_type' was not declared. Should it be static?
+    net/netfilter/nft_set_hash.c:670:21: warning: symbol 'nft_set_hash_type' was not declared. Should it be static?
+    net/netfilter/nft_set_hash.c:690:21: warning: symbol 'nft_set_hash_fast_type' was not declared. Should it be static?
+      CHECK   net/netfilter/nft_set_bitmap.c
+    net/netfilter/nft_set_bitmap.c:296:21: warning: symbol 'nft_set_bitmap_type' was not declared. Should it be static?
+      CHECK   net/netfilter/nft_set_rbtree.c
+    net/netfilter/nft_set_rbtree.c:470:21: warning: symbol 'nft_set_rbtree_type' was not declared. Should it be static?
+    
+    Include nf_tables_core.h rather than nf_tables.h to pick up the additional definitions.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Pablo Neira Ayuso 
+
+diff --git a/net/netfilter/nft_set_bitmap.c b/net/netfilter/nft_set_bitmap.c
+index b5aeccdddb22..087a056e34d1 100644
+--- a/net/netfilter/nft_set_bitmap.c
++++ b/net/netfilter/nft_set_bitmap.c
+@@ -10,7 +10,7 @@
+ #include 
+ #include 
+ #include 
+-#include 
++#include 
+ 
+ struct nft_bitmap_elem {
+ 	struct list_head	head;
+diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c
+index 6e8d20c03e3d..c490451fcebf 100644
+--- a/net/netfilter/nft_set_hash.c
++++ b/net/netfilter/nft_set_hash.c
+@@ -16,7 +16,7 @@
+ #include 
+ #include 
+ #include 
+-#include 
++#include 
+ 
+ /* We target a hash table size of 4, element hint is 75% of final size */
+ #define NFT_RHASH_ELEMENT_HINT 3
+diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
+index 419d58ef802b..57123259452f 100644
+--- a/net/netfilter/nft_set_rbtree.c
++++ b/net/netfilter/nft_set_rbtree.c
+@@ -13,7 +13,7 @@
+ #include 
+ #include 
+ #include 
+-#include 
++#include 
+ 
+ struct nft_rbtree {
+ 	struct rb_root		root;

commit b6ff24f7b5101101ff897dfdde3f37924e676bc2
+Author: Valdis Kletnieks 
+Date:   Thu Aug 8 16:32:27 2019 +0200
+
+    RAS: Build debugfs.o only when enabled in Kconfig
+    
+    In addition, the 0day bot reported this build error:
+    
+      >> drivers/ras/debugfs.c:10:5: error: redefinition of 'ras_userspace_consumers'
+          int ras_userspace_consumers(void)
+              ^~~~~~~~~~~~~~~~~~~~~~~
+         In file included from drivers/ras/debugfs.c:3:0:
+         include/linux/ras.h:14:19: note: previous definition of 'ras_userspace_consumers' was here
+          static inline int ras_userspace_consumers(void) { return 0; }
+                          ^~~~~~~~~~~~~~~~~~~~~~~
+    
+    for a riscv-specific .config where CONFIG_DEBUG_FS is not set. Fix all
+    that by making debugfs.o depend on that define.
+    
+     [ bp: Rewrite commit message. ]
+    
+    Reported-by: kbuild test robot 
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Borislav Petkov 
+    Cc: Tony Luck 
+    Cc: linux-edac@vger.kernel.org
+    Cc: x86@kernel.org
+    Link: http://lkml.kernel.org/r/7053.1565218556@turing-police
+
+diff --git a/drivers/ras/Makefile b/drivers/ras/Makefile
+index ef6777e14d3d..6f0404f50107 100644
+--- a/drivers/ras/Makefile
++++ b/drivers/ras/Makefile
+@@ -1,3 +1,4 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+-obj-$(CONFIG_RAS)	+= ras.o debugfs.o
++obj-$(CONFIG_RAS)	+= ras.o
++obj-$(CONFIG_DEBUG_FS)	+= debugfs.o
+ obj-$(CONFIG_RAS_CEC)	+= cec.o

commit 0a54b809a3a2c31e1055b45b03708eb730222be1
+Author: Valdis Kletnieks 
+Date:   Wed Aug 7 18:59:29 2019 -0400
+
+    RAS: Fix prototype warnings
+    
+    When building with C=2 and/or W=1, legitimate warnings are issued about
+    missing prototypes:
+    
+        CHECK   drivers/ras/debugfs.c
+      drivers/ras/debugfs.c:4:15: warning: symbol 'ras_debugfs_dir' was not declared. Should it be static?
+      drivers/ras/debugfs.c:8:5: warning: symbol 'ras_userspace_consumers' was not declared. Should it be static?
+      drivers/ras/debugfs.c:38:12: warning: symbol 'ras_add_daemon_trace' was not declared. Should it be static?
+      drivers/ras/debugfs.c:54:13: warning: symbol 'ras_debugfs_init' was not declared. Should it be static?
+        CC      drivers/ras/debugfs.o
+      drivers/ras/debugfs.c:8:5: warning: no previous prototype for 'ras_userspace_consumers' [-Wmissing-prototypes]
+          8 | int ras_userspace_consumers(void)
+            |     ^~~~~~~~~~~~~~~~~~~~~~~
+      drivers/ras/debugfs.c:38:12: warning: no previous prototype for 'ras_add_daemon_trace' [-Wmissing-prototypes]
+         38 | int __init ras_add_daemon_trace(void)
+            |            ^~~~~~~~~~~~~~~~~~~~
+      drivers/ras/debugfs.c:54:13: warning: no previous prototype for 'ras_debugfs_init' [-Wmissing-prototypes]
+         54 | void __init ras_debugfs_init(void)
+            |             ^~~~~~~~~~~~~~~~
+    
+    Provide the proper includes.
+    
+     [ bp: Take care of the same warnings for cec.c too. ]
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Borislav Petkov 
+    Cc: Tony Luck 
+    Cc: linux-edac@vger.kernel.org
+    Cc: x86@kernel.org
+    Link: http://lkml.kernel.org/r/7168.1565218769@turing-police
+
+diff --git a/drivers/ras/cec.c b/drivers/ras/cec.c
+index 5d545806d930..c09cf55e2d20 100644
+--- a/drivers/ras/cec.c
++++ b/drivers/ras/cec.c
+@@ -4,6 +4,7 @@
+  */
+ #include 
+ #include 
++#include 
+ #include 
+ #include 
+ 
+diff --git a/drivers/ras/debugfs.c b/drivers/ras/debugfs.c
+index 9c1b717efad8..0d4f985afbf3 100644
+--- a/drivers/ras/debugfs.c
++++ b/drivers/ras/debugfs.c
+@@ -1,5 +1,7 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ #include 
++#include 
++#include "debugfs.h"
+ 
+ struct dentry *ras_debugfs_dir;
+ 

commit 04f5bda84b0712d6f172556a7e8dca9ded5e73b9
+Author: Valdis Kletnieks 
+Date:   Wed Aug 7 23:27:17 2019 -0400
+
+    x86/lib/cpu: Address missing prototypes warning
+    
+    When building with W=1, warnings about missing prototypes are emitted:
+    
+      CC      arch/x86/lib/cpu.o
+    arch/x86/lib/cpu.c:5:14: warning: no previous prototype for 'x86_family' [-Wmissing-prototypes]
+        5 | unsigned int x86_family(unsigned int sig)
+          |              ^~~~~~~~~~
+    arch/x86/lib/cpu.c:18:14: warning: no previous prototype for 'x86_model' [-Wmissing-prototypes]
+       18 | unsigned int x86_model(unsigned int sig)
+          |              ^~~~~~~~~
+    arch/x86/lib/cpu.c:33:14: warning: no previous prototype for 'x86_stepping' [-Wmissing-prototypes]
+       33 | unsigned int x86_stepping(unsigned int sig)
+          |              ^~~~~~~~~~~~
+    
+    Add the proper include file so the prototypes are there.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Thomas Gleixner 
+    Link: https://lkml.kernel.org/r/42513.1565234837@turing-police
+
+diff --git a/arch/x86/lib/cpu.c b/arch/x86/lib/cpu.c
+index 04967cdce5d1..7ad68917a51e 100644
+--- a/arch/x86/lib/cpu.c
++++ b/arch/x86/lib/cpu.c
+@@ -1,6 +1,7 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ #include 
+ #include 
++#include 
+ 
+ unsigned int x86_family(unsigned int sig)
+ {

commit a92c7ba982e3950a82fd63b3fd289248bd99e8f4
+Author: Valdis Kletnieks 
+Date:   Wed Aug 7 19:22:34 2019 -0400
+
+    fs/handle.c - fix up kerneldoc
+    
+    When building with W=1, we get some kerneldoc warnings:
+    
+      CC      fs/fhandle.o
+    fs/fhandle.c:259: warning: Function parameter or member 'flags' not described in 'sys_open_by_handle_at'
+    fs/fhandle.c:259: warning: Excess function parameter 'flag' description in 'sys_open_by_handle_at'
+    
+    Fix the typo that caused it.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Al Viro 
+
+diff --git a/fs/fhandle.c b/fs/fhandle.c
+index 0ee727485615..01263ffbc4c0 100644
+--- a/fs/fhandle.c
++++ b/fs/fhandle.c
+@@ -246,7 +246,7 @@ static long do_handle_open(int mountdirfd, struct file_handle __user *ufh,
+  * sys_open_by_handle_at: Open the file handle
+  * @mountdirfd: directory file descriptor
+  * @handle: file handle to be opened
+- * @flag: open flags.
++ * @flags: open flags.
+  *
+  * @mountdirfd indicate the directory file descriptor
+  * of the mount point. file handle is decoded relative

commit aee450cbe482a8c2f6fa5b05b178ef8b8ff107ca
+Author: Valdis Kletnieks 
+Date:   Thu Jun 6 22:39:27 2019 -0400
+
+    bpf: silence warning messages in core
+    
+    Compiling kernel/bpf/core.c with W=1 causes a flood of warnings:
+    
+    kernel/bpf/core.c:1198:65: warning: initialized field overwritten [-Woverride-init]
+     1198 | #define BPF_INSN_3_TBL(x, y, z) [BPF_##x | BPF_##y | BPF_##z] = true
+          |                                                                 ^~~~
+    kernel/bpf/core.c:1087:2: note: in expansion of macro 'BPF_INSN_3_TBL'
+     1087 |  INSN_3(ALU, ADD,  X),   \
+          |  ^~~~~~
+    kernel/bpf/core.c:1202:3: note: in expansion of macro 'BPF_INSN_MAP'
+     1202 |   BPF_INSN_MAP(BPF_INSN_2_TBL, BPF_INSN_3_TBL),
+          |   ^~~~~~~~~~~~
+    kernel/bpf/core.c:1198:65: note: (near initialization for 'public_insntable[12]')
+     1198 | #define BPF_INSN_3_TBL(x, y, z) [BPF_##x | BPF_##y | BPF_##z] = true
+          |                                                                 ^~~~
+    kernel/bpf/core.c:1087:2: note: in expansion of macro 'BPF_INSN_3_TBL'
+     1087 |  INSN_3(ALU, ADD,  X),   \
+          |  ^~~~~~
+    kernel/bpf/core.c:1202:3: note: in expansion of macro 'BPF_INSN_MAP'
+     1202 |   BPF_INSN_MAP(BPF_INSN_2_TBL, BPF_INSN_3_TBL),
+          |   ^~~~~~~~~~~~
+    
+    98 copies of the above.
+    
+    The attached patch silences the warnings, because we *know* we're overwriting
+    the default initializer. That leaves bpf/core.c with only 6 other warnings,
+    which become more visible in comparison.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Acked-by: Andrii Nakryiko 
+    Signed-off-by: Daniel Borkmann 
+
+diff --git a/kernel/bpf/Makefile b/kernel/bpf/Makefile
+index 4c2fa3ac56f6..29d781061cd5 100644
+--- a/kernel/bpf/Makefile
++++ b/kernel/bpf/Makefile
+@@ -1,5 +1,6 @@
+ # SPDX-License-Identifier: GPL-2.0
+ obj-y := core.o
++CFLAGS_core.o += $(call cc-disable-warning, override-init)
+ 
+ obj-$(CONFIG_BPF_SYSCALL) += syscall.o verifier.o inode.o helpers.o tnum.o
+ obj-$(CONFIG_BPF_SYSCALL) += hashtab.o arraymap.o percpu_freelist.o bpf_lru_list.o lpm_trie.o map_in_map.o

commit e28f296ea155da36f710eb1f1173d8780fbac49d
+Author: Valdis Kletnieks 
+Date:   Tue Mar 12 07:26:06 2019 -0400
+
+    platform/x86: dell-rbtn: Add missing #include
+    
+    Building with W=1 complains:
+      CC [M]  drivers/platform/x86/dell-rbtn.o
+    drivers/platform/x86/dell-rbtn.c:345:5: warning: no previous prototype for 'dell_rbtn_notifier_register' [-Wmissing-prototypes]
+      345 | int dell_rbtn_notifier_register(struct notifier_block *nb)
+          |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~
+    drivers/platform/x86/dell-rbtn.c:371:5: warning: no previous prototype for 'dell_rbtn_notifier_unregister' [-Wmissing-prototypes]
+      371 | int dell_rbtn_notifier_unregister(struct notifier_block *nb)
+          |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    
+    The real problem is a missing include. Add it to keep dell-rbtn.c and .h in sync.
+    
+    Fixes: b05ffc95f9ed ("dell-rbtn: Export notifier for other kernel modules")
+    Signed-off-by: Valdis Kletnieks 
+    [andy: massaged commit message, added Fixes tag]
+    Signed-off-by: Andy Shevchenko 
+
+diff --git a/drivers/platform/x86/dell-rbtn.c b/drivers/platform/x86/dell-rbtn.c
+index f3afe778001e..56535d7222dd 100644
+--- a/drivers/platform/x86/dell-rbtn.c
++++ b/drivers/platform/x86/dell-rbtn.c
+@@ -18,6 +18,8 @@
+ #include 
+ #include 
+ 
++#include "dell-rbtn.h"
++
+ enum rbtn_type {
+ 	RBTN_UNKNOWN,
+ 	RBTN_TOGGLE,

commit db8b4aefd17b1ccf108d81a4fbb181c8e50abf0e
+Author: Valdis Kletnieks 
+Date:   Tue Mar 12 06:42:31 2019 -0400
+
+    extcon: Fix build warning for extcon_unregister_notifier comment
+    
+    Give the line the asterisk it wanted to fix the build warning.
+    
+    [Build warning message]
+    Building with W=1 reports:
+    
+      CC      drivers/extcon/devres.o
+    drivers/extcon/devres.c:208: warning: bad line:
+            - Resource-managed extcon_unregister_notifier()
+    
+    Signed-off-by: Valdis Kletnieks 
+    [cw00.choi: Edit the patch subject and description]
+    Signed-off-by: Chanwoo Choi 
+
+diff --git a/drivers/extcon/devres.c b/drivers/extcon/devres.c
+index f599aeddf8e5..f487d877ab5d 100644
+--- a/drivers/extcon/devres.c
++++ b/drivers/extcon/devres.c
+@@ -205,7 +205,7 @@ EXPORT_SYMBOL(devm_extcon_register_notifier);
+ 
+ /**
+  * devm_extcon_unregister_notifier()
+-			- Resource-managed extcon_unregister_notifier()
++ *			- Resource-managed extcon_unregister_notifier()
+  * @dev:	the device owning the extcon device being created
+  * @edev:	the extcon device
+  * @id:		the unique id among the extcon enumeration

commit d18bf4229b1772e91c0c36772737c01cf9726720
+Author: Valdis Kletnieks 
+Date:   Tue Mar 12 04:06:37 2019 -0400
+
+    perf/core: Make perf_swevent_init_cpu() static
+    
+    'make W=1' causes GCC to complain:
+    
+      kernel/events/core.c:11877:6: warning: no previous prototype for 'perf_swevent_init_cpu' [-Wmissing-prototypes]
+    
+    It's not referenced anywhere else, make it static.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Peter Zijlstra (Intel) 
+    Cc: Linus Torvalds 
+    Cc: Peter Zijlstra 
+    Cc: Thomas Gleixner 
+    Link: https://lkml.kernel.org/r/28974.1552377997@turing-police
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/kernel/events/core.c b/kernel/events/core.c
+index 72d06e302e99..dfc4bab0b02b 100644
+--- a/kernel/events/core.c
++++ b/kernel/events/core.c
+@@ -11878,7 +11878,7 @@ static void __init perf_event_init_all_cpus(void)
+ 	}
+ }
+ 
+-void perf_swevent_init_cpu(unsigned int cpu)
++static void perf_swevent_init_cpu(unsigned int cpu)
+ {
+ 	struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
+ 

commit 3adf2aa8af2d5122917b78988de9cdeb828cdd9d
+Author: Valdis Kletnieks 
+Date:   Tue Mar 12 07:49:03 2019 -0400
+
+    drivers/tty/tty_jobctrl.c - fix non-kerneldoc comment
+    
+    Building with W=1 reports (among other things):
+      CC      drivers/tty/tty_jobctrl.o
+    drivers/tty/tty_jobctrl.c:317: warning: Cannot understand  *
+     on line 317 - I thought it was a doc line
+    
+    Fix up the non-kerneldoc comment. (other warnings to be cleaned up in separate patch)
+    
+    Signed-off-by Valdis Kletnieks 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/tty/tty_jobctrl.c b/drivers/tty/tty_jobctrl.c
+index c4ecd66fafef..1393f71bb170 100644
+--- a/drivers/tty/tty_jobctrl.c
++++ b/drivers/tty/tty_jobctrl.c
+@@ -313,7 +313,7 @@ void disassociate_ctty(int on_exit)
+ 	read_unlock(&tasklist_lock);
+ }
+ 
+-/**
++/*
+  *
+  *	no_tty	- Ensure the current process does not have a controlling tty
+  */

commit 48084abf212052ca1d39fae064c581b1ce5b1fdf
+Author: Valdis Kletnieks 
+Date:   Tue Mar 12 05:33:48 2019 -0400
+
+    watchdog/core: Make variables static
+    
+    sparse complains:
+      CHECK   kernel/watchdog.c
+    kernel/watchdog.c:45:19: warning: symbol 'nmi_watchdog_available'
+                                      was not declared. Should it be static?
+    kernel/watchdog.c:47:16: warning: symbol 'watchdog_allowed_mask'
+                                      was not declared. Should it be static?
+    
+    They're not referenced by name from anyplace else, make them static.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Thomas Gleixner 
+    Link: https://lkml.kernel.org/r/7855.1552383228@turing-police
+
+diff --git a/kernel/watchdog.c b/kernel/watchdog.c
+index 8fbfda94a67b..403c9bd90413 100644
+--- a/kernel/watchdog.c
++++ b/kernel/watchdog.c
+@@ -42,9 +42,9 @@ int __read_mostly watchdog_user_enabled = 1;
+ int __read_mostly nmi_watchdog_user_enabled = NMI_WATCHDOG_DEFAULT;
+ int __read_mostly soft_watchdog_user_enabled = 1;
+ int __read_mostly watchdog_thresh = 10;
+-int __read_mostly nmi_watchdog_available;
++static int __read_mostly nmi_watchdog_available;
+ 
+-struct cpumask watchdog_allowed_mask __read_mostly;
++static struct cpumask watchdog_allowed_mask __read_mostly;
+ 
+ struct cpumask watchdog_cpumask __read_mostly;
+ unsigned long *watchdog_cpumask_bits = cpumask_bits(&watchdog_cpumask);

commit e8750053d64a3317cbc15f8341f0f11ca751bfeb
+Author: Valdis Kletnieks 
+Date:   Tue Mar 12 04:38:35 2019 -0400
+
+    time/jiffies: Make refined_jiffies static
+    
+    sparse complains:
+    
+      CHECK   kernel/time/jiffies.c
+    kernel/time/jiffies.c:92:20: warning: symbol 'refined_jiffies' was not
+                                          declared. Should it be static?
+    
+    Its only used in file scope. Make it static.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Thomas Gleixner 
+    Link: https://lkml.kernel.org/r/32342.1552379915@turing-police
+
+diff --git a/kernel/time/jiffies.c b/kernel/time/jiffies.c
+index dc1b6f1929f9..ac9c03dd6c7d 100644
+--- a/kernel/time/jiffies.c
++++ b/kernel/time/jiffies.c
+@@ -89,7 +89,7 @@ struct clocksource * __init __weak clocksource_default_clock(void)
+ 	return &clocksource_jiffies;
+ }
+ 
+-struct clocksource refined_jiffies;
++static struct clocksource refined_jiffies;
+ 
+ int register_refined_jiffies(long cycles_per_second)
+ {

commit bb2e320565f997273fe04035bb6c17f643da6f8a
+Author: Valdis Kletnieks 
+Date:   Tue Mar 12 04:17:56 2019 -0400
+
+    genirq/devres: Remove excess parameter from kernel doc
+    
+    Building with 'make W=1' complains:
+    
+      CC      kernel/irq/devres.o
+    kernel/irq/devres.c:104: warning: Excess function parameter 'thread_fn'
+                             description in 'devm_request_any_context_irq'
+    
+    Remove it.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Thomas Gleixner 
+    Link: https://lkml.kernel.org/r/31207.1552378676@turing-police
+
+diff --git a/kernel/irq/devres.c b/kernel/irq/devres.c
+index 5d5378ea0afe..f808c6a97dcc 100644
+--- a/kernel/irq/devres.c
++++ b/kernel/irq/devres.c
+@@ -84,8 +84,6 @@ EXPORT_SYMBOL(devm_request_threaded_irq);
+  *	@dev: device to request interrupt for
+  *	@irq: Interrupt line to allocate
+  *	@handler: Function to be called when the IRQ occurs
+- *	@thread_fn: function to be called in a threaded interrupt context. NULL
+- *		    for devices which handle everything in @handler
+  *	@irqflags: Interrupt type flags
+  *	@devname: An ascii name for the claiming device, dev_name(dev) if NULL
+  *	@dev_id: A cookie passed back to the handler function

commit 4fe64a62e04cfb2dc1daab0d8f05d212aa014161
+Author: Valdis Kletnieks 
+Date:   Tue Mar 12 03:47:53 2019 -0400
+
+    x86/mm/pti: Make local symbols static
+    
+    With 'make C=2 W=1', sparse and gcc both complain:
+    
+      CHECK   arch/x86/mm/pti.c
+    arch/x86/mm/pti.c:84:3: warning: symbol 'pti_mode' was not declared. Should it be static?
+    arch/x86/mm/pti.c:605:6: warning: symbol 'pti_set_kernel_image_nonglobal' was not declared. Should it be static?
+      CC      arch/x86/mm/pti.o
+    arch/x86/mm/pti.c:605:6: warning: no previous prototype for 'pti_set_kernel_image_nonglobal' [-Wmissing-prototypes]
+      605 | void pti_set_kernel_image_nonglobal(void)
+          |      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    
+    pti_set_kernel_image_nonglobal() is only used locally. 'pti_mode' exists in
+    drivers/hwtracing/intel_th/pti.c as well, but it's a completely unrelated
+    local (static) symbol.
+    
+    Make both static.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Thomas Gleixner 
+    Cc: Dave Hansen 
+    Cc: Andy Lutomirski 
+    Cc: Peter Zijlstra 
+    Link: https://lkml.kernel.org/r/27680.1552376873@turing-police
+
+diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c
+index 4fee5c3003ed..139b28a01ce4 100644
+--- a/arch/x86/mm/pti.c
++++ b/arch/x86/mm/pti.c
+@@ -77,7 +77,7 @@ static void __init pti_print_if_secure(const char *reason)
+ 		pr_info("%s\n", reason);
+ }
+ 
+-enum pti_mode {
++static enum pti_mode {
+ 	PTI_AUTO = 0,
+ 	PTI_FORCE_OFF,
+ 	PTI_FORCE_ON
+@@ -602,7 +602,7 @@ static void pti_clone_kernel_text(void)
+ 	set_memory_global(start, (end_global - start) >> PAGE_SHIFT);
+ }
+ 
+-void pti_set_kernel_image_nonglobal(void)
++static void pti_set_kernel_image_nonglobal(void)
+ {
+ 	/*
+ 	 * The identity map is created with PMDs, regardless of the

commit 50505e578f5395a4405008997814ae7f41ff5300
+Author: Valdis Kletnieks 
+Date:   Tue Mar 12 08:09:20 2019 -0400
+
+    staging: rtl8712 - fix up non-kerneldoc comments
+    
+    Building with W=1 reports (among other things)
+    
+      CC [M]  drivers/staging/rtl8712/rtl871x_ioctl_linux.o
+    drivers/staging/rtl8712/rtl871x_ioctl_linux.c:1106: warning: Cannot understand  *
+     on line 1106 - I thought it was a doc line
+    
+      CC [M]  drivers/staging/rtl8712/os_intfs.o
+    drivers/staging/rtl8712/os_intfs.c:366: warning: Cannot understand  *
+     on line 366 - I thought it was a doc line
+    drivers/staging/rtl8712/os_intfs.c:434: warning: Cannot understand  *
+     on line 434 - I thought it was a doc line
+    
+    Fix up the non-kerneldoc comments
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c
+index 41ba1eeea2f2..c962696c9822 100644
+--- a/drivers/staging/rtl8712/os_intfs.c
++++ b/drivers/staging/rtl8712/os_intfs.c
+@@ -362,7 +362,7 @@ static void enable_video_mode(struct _adapter *padapter, int cbw40_value)
+ 	r8712_fw_cmd(padapter, intcmd);
+ }
+ 
+-/**
++/*
+  *
+  * This function intends to handle the activation of an interface
+  * i.e. when it is brought Up/Active from a Down state.
+@@ -430,7 +430,7 @@ static int netdev_open(struct net_device *pnetdev)
+ 	return -1;
+ }
+ 
+-/**
++/*
+  *
+  * This function intends to handle the shutdown of an interface
+  * i.e. when it is brought Down from an Up/Active state.
+diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
+index ad9b2f76d04a..a7230c0c7b23 100644
+--- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
++++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
+@@ -1102,7 +1102,7 @@ static int r871x_wx_set_mlme(struct net_device *dev,
+ 	return ret;
+ }
+ 
+-/**
++/*
+  *
+  * This function intends to handle the Set Scan command.
+  * Currently, the request comes via Wireless Extensions' SIOCSIWSCAN ioctl.

commit cede666e2eb28dc8a680d1622fded533769f07a4
+Author: Valdis Kletnieks 
+Date:   Tue Mar 12 04:58:32 2019 -0400
+
+    trace/probes: Remove kernel doc style from non kernel doc comment
+    
+      CC      kernel/trace/trace_kprobe.o
+    kernel/trace/trace_kprobe.c:41: warning: cannot understand function prototype: 'struct trace_kprobe '
+    
+    The real problem is that a comment looked like kerneldoc when it shouldn't be...
+    
+    Link: http://lkml.kernel.org/r/2812.1552381112@turing-police
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Steven Rostedt (VMware) 
+
+diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
+index d5fb09ebba8b..ceafa0a2b1d1 100644
+--- a/kernel/trace/trace_kprobe.c
++++ b/kernel/trace/trace_kprobe.c
+@@ -35,7 +35,7 @@ static struct dyn_event_operations trace_kprobe_ops = {
+ 	.match = trace_kprobe_match,
+ };
+ 
+-/**
++/*
+  * Kprobe event core functions
+  */
+ struct trace_kprobe {

commit 0841625201b649c0b1bf0f0e25cf4401e68fb8fd
+Author: Valdis Kletnieks 
+Date:   Tue Mar 12 04:52:58 2019 -0400
+
+    tracing/probes: Make reserved_field_names static
+    
+    sparse complains:
+      CHECK   kernel/trace/trace_probe.c
+    kernel/trace/trace_probe.c:16:12: warning: symbol 'reserved_field_names' was not declared. Should it be static?
+    
+    Yes, it should be static.
+    
+    Link: http://lkml.kernel.org/r/2478.1552380778@turing-police
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Steven Rostedt (VMware) 
+
+diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c
+index 89da34b326e3..cfcf77e6fb19 100644
+--- a/kernel/trace/trace_probe.c
++++ b/kernel/trace/trace_probe.c
+@@ -13,7 +13,7 @@
+ 
+ #include "trace_probe.h"
+ 
+-const char *reserved_field_names[] = {
++static const char *reserved_field_names[] = {
+ 	"common_type",
+ 	"common_flags",
+ 	"common_preempt_count",

commit 8496ecd0bed4c70b43f39cecf0872b84360f0d14
+Author: Valdis Kletnieks 
+Date:   Thu Mar 7 16:29:06 2019 -0800
+
+    init/calibrate.c: provide proper prototype
+    
+    Sparse issues a warning:
+    
+        CHECK   init/calibrate.c
+      init/calibrate.c:271:28: warning: symbol 'calibration_delay_done' was not declared. Should it be static?
+    
+    The actual issue is that it's a __weak symbol that archs can override
+    (in fact, ARM does so), but no prototype is provided.  Let's provide one
+    to prevent surprises.
+    
+    Link: http://lkml.kernel.org/r/18827.1548750938@turing-police.cc.vt.edu
+    Signed-off-by: Valdis Kletnieks 
+    Reviewed-by: Andrew Morton 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/include/linux/delay.h b/include/linux/delay.h
+index b78bab4395d8..8e6828094c1e 100644
+--- a/include/linux/delay.h
++++ b/include/linux/delay.h
+@@ -55,6 +55,7 @@ static inline void ndelay(unsigned long x)
+ 
+ extern unsigned long lpj_fine;
+ void calibrate_delay(void);
++void __attribute__((weak)) calibration_delay_done(void);
+ void msleep(unsigned int msecs);
+ unsigned long msleep_interruptible(unsigned int msecs);
+ void usleep_range(unsigned long min, unsigned long max);

commit a98eb6f19952f18a7e5ac55d6bd7bbbb2bdc8b88
+Author: Valdis Kletnieks 
+Date:   Thu Mar 7 16:26:46 2019 -0800
+
+    kernel/hung_task.c - fix sparse warnings
+    
+    sparse complains:
+    
+        CHECK   kernel/hung_task.c
+      kernel/hung_task.c:28:19: warning: symbol 'sysctl_hung_task_check_count' was not declared. Should it be static?
+      kernel/hung_task.c:42:29: warning: symbol 'sysctl_hung_task_timeout_secs' was not declared. Should it be static?
+      kernel/hung_task.c:47:29: warning: symbol 'sysctl_hung_task_check_interval_secs' was not declared. Should it be static?
+      kernel/hung_task.c:49:19: warning: symbol 'sysctl_hung_task_warnings' was not declared. Should it be static?
+      kernel/hung_task.c:61:28: warning: symbol 'sysctl_hung_task_panic' was not declared. Should it be static?
+      kernel/hung_task.c:219:5: warning: symbol 'proc_dohung_task_timeout_secs' was not declared. Should it be static?
+    
+    Add the appropriate header file to provide declarations.
+    
+    Link: http://lkml.kernel.org/r/467.1548649525@turing-police.cc.vt.edu
+    Signed-off-by: Valdis Kletnieks 
+    Cc: "Paul E. McKenney" 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/kernel/hung_task.c b/kernel/hung_task.c
+index 4a9191617076..0c11216171c9 100644
+--- a/kernel/hung_task.c
++++ b/kernel/hung_task.c
+@@ -19,6 +19,7 @@
+ #include 
+ #include 
+ #include 
++#include 
+ 
+ #include 
+ 

commit 1832f4ef5867fd3898d8a6c6c1978b75d76fc246
+Author: Valdis Kletnieks 
+Date:   Tue Jan 29 01:47:06 2019 -0500
+
+    bpf, cgroups: clean up kerneldoc warnings
+    
+    Building with W=1 reveals some bitrot:
+    
+      CC      kernel/bpf/cgroup.o
+    kernel/bpf/cgroup.c:238: warning: Function parameter or member 'flags' not described in '__cgroup_bpf_attach'
+    kernel/bpf/cgroup.c:367: warning: Function parameter or member 'unused_flags' not described in '__cgroup_bpf_detach'
+    
+    Add a kerneldoc line for 'flags'.
+    
+    Fixing the warning for 'unused_flags' is best approached by
+    removing the unused parameter on the function call.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Acked-by: Song Liu 
+    Signed-off-by: Daniel Borkmann 
+
+diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h
+index 588dd5f0bd85..695b2a880d9a 100644
+--- a/include/linux/bpf-cgroup.h
++++ b/include/linux/bpf-cgroup.h
+@@ -78,7 +78,7 @@ int cgroup_bpf_inherit(struct cgroup *cgrp);
+ int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog,
+ 			enum bpf_attach_type type, u32 flags);
+ int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,
+-			enum bpf_attach_type type, u32 flags);
++			enum bpf_attach_type type);
+ int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
+ 		       union bpf_attr __user *uattr);
+ 
+diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c
+index ab612fe9862f..d78cfec5807d 100644
+--- a/kernel/bpf/cgroup.c
++++ b/kernel/bpf/cgroup.c
+@@ -230,6 +230,7 @@ static int update_effective_progs(struct cgroup *cgrp,
+  * @cgrp: The cgroup which descendants to traverse
+  * @prog: A program to attach
+  * @type: Type of attach operation
++ * @flags: Option flags
+  *
+  * Must be called with cgroup_mutex held.
+  */
+@@ -363,7 +364,7 @@ int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog,
+  * Must be called with cgroup_mutex held.
+  */
+ int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,
+-			enum bpf_attach_type type, u32 unused_flags)
++			enum bpf_attach_type type)
+ {
+ 	struct list_head *progs = &cgrp->bpf.progs[type];
+ 	enum bpf_cgroup_storage_type stype;
+diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
+index f31bd61c9466..9f617605dacb 100644
+--- a/kernel/cgroup/cgroup.c
++++ b/kernel/cgroup/cgroup.c
+@@ -5996,7 +5996,7 @@ int cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,
+ 	int ret;
+ 
+ 	mutex_lock(&cgroup_mutex);
+-	ret = __cgroup_bpf_detach(cgrp, prog, type, flags);
++	ret = __cgroup_bpf_detach(cgrp, prog, type);
+ 	mutex_unlock(&cgroup_mutex);
+ 	return ret;
+ }

commit 116bfa96a255123ed209da6544f74a4f2eaca5da
+Author: Valdis Kletnieks 
+Date:   Tue Jan 29 01:04:25 2019 -0500
+
+    bpf: fix missing prototype warnings
+    
+    Compiling with W=1 generates warnings:
+    
+      CC      kernel/bpf/core.o
+    kernel/bpf/core.c:721:12: warning: no previous prototype for ?bpf_jit_alloc_exec_limit? [-Wmissing-prototypes]
+      721 | u64 __weak bpf_jit_alloc_exec_limit(void)
+          |            ^~~~~~~~~~~~~~~~~~~~~~~~
+    kernel/bpf/core.c:757:14: warning: no previous prototype for ?bpf_jit_alloc_exec? [-Wmissing-prototypes]
+      757 | void *__weak bpf_jit_alloc_exec(unsigned long size)
+          |              ^~~~~~~~~~~~~~~~~~
+    kernel/bpf/core.c:762:13: warning: no previous prototype for ?bpf_jit_free_exec? [-Wmissing-prototypes]
+      762 | void __weak bpf_jit_free_exec(void *addr)
+          |             ^~~~~~~~~~~~~~~~~
+    
+    All three are weak functions that archs can override, provide
+    proper prototypes for when a new arch provides their own.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Acked-by: Song Liu 
+    Signed-off-by: Daniel Borkmann 
+
+diff --git a/include/linux/filter.h b/include/linux/filter.h
+index e4b473f85b46..7317376734f7 100644
+--- a/include/linux/filter.h
++++ b/include/linux/filter.h
+@@ -880,7 +880,9 @@ bpf_jit_binary_alloc(unsigned int proglen, u8 **image_ptr,
+ 		     unsigned int alignment,
+ 		     bpf_jit_fill_hole_t bpf_fill_ill_insns);
+ void bpf_jit_binary_free(struct bpf_binary_header *hdr);
+-
++u64 bpf_jit_alloc_exec_limit(void);
++void *bpf_jit_alloc_exec(unsigned long size);
++void bpf_jit_free_exec(void *addr);
+ void bpf_jit_free(struct bpf_prog *fp);
+ 
+ int bpf_jit_get_func_addr(const struct bpf_prog *prog,

commit de1da68d9c9d230e448b9fa0abff139a0468fb96
+Author: Valdis Kletnieks 
+Date:   Mon Jan 28 23:04:46 2019 -0500
+
+    bpf: fix bitrotted kerneldoc
+    
+    Over the years, the function signature has changed, but the
+    kerneldoc block hasn't.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Acked-by: Song Liu 
+    Signed-off-by: Daniel Borkmann 
+
+diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
+index a7bcb23bee84..f13c543b7b36 100644
+--- a/kernel/bpf/core.c
++++ b/kernel/bpf/core.c
+@@ -1263,8 +1263,9 @@ bool bpf_opcode_in_insntable(u8 code)
+ #ifndef CONFIG_BPF_JIT_ALWAYS_ON
+ /**
+  *	__bpf_prog_run - run eBPF program on a given context
+- *	@ctx: is the data we are operating on
++ *	@regs: is the array of MAX_BPF_EXT_REG eBPF pseudo-registers
+  *	@insn: is the array of eBPF instructions
++ *	@stack: is the eBPF storage stack
+  *
+  * Decode and execute eBPF instructions.
+  */

commit 90a8c78b8b5e2c8537a170ee675127f02ca94532
+Author: Valdis Kletnieks 
+Date:   Wed Sep 26 18:49:38 2018 -0400
+
+    crypto/morus(640,1280) - make crypto_...-algs static
+    
+    sparse complains thusly:
+    
+      CHECK   arch/x86/crypto/morus640-sse2-glue.c
+    arch/x86/crypto/morus640-sse2-glue.c:38:1: warning: symbol 'crypto_morus640_sse2_algs' was not declared. Should it be static?
+      CHECK   arch/x86/crypto/morus1280-sse2-glue.c
+    arch/x86/crypto/morus1280-sse2-glue.c:38:1: warning: symbol 'crypto_morus1280_sse2_algs' was not declared. Should it be static?
+      CHECK   arch/x86/crypto/morus1280-avx2-glue.c
+    arch/x86/crypto/morus1280-avx2-glue.c:38:1: warning: symbol 'crypto_morus1280_avx2_algs' was not declared. Should it be static?
+    
+    and sparse is correct - these don't need to be global and polluting the namespace.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Acked-by: Ondrej Mosnacek 
+    Signed-off-by: Herbert Xu 
+
+diff --git a/include/crypto/morus1280_glue.h b/include/crypto/morus1280_glue.h
+index b26dd70efd9a..ba782e10065e 100644
+--- a/include/crypto/morus1280_glue.h
++++ b/include/crypto/morus1280_glue.h
+@@ -82,7 +82,7 @@ void cryptd_morus1280_glue_exit_tfm(struct crypto_aead *aead);
+ 	{ \
+ 	} \
+ 	\
+-	struct aead_alg crypto_morus1280_##id##_algs[] = {\
++	static struct aead_alg crypto_morus1280_##id##_algs[] = {\
+ 		{ \
+ 			.setkey = crypto_morus1280_glue_setkey, \
+ 			.setauthsize = crypto_morus1280_glue_setauthsize, \
+diff --git a/include/crypto/morus640_glue.h b/include/crypto/morus640_glue.h
+index 90c8db07e740..27fa790a2362 100644
+--- a/include/crypto/morus640_glue.h
++++ b/include/crypto/morus640_glue.h
+@@ -82,7 +82,7 @@ void cryptd_morus640_glue_exit_tfm(struct crypto_aead *aead);
+ 	{ \
+ 	} \
+ 	\
+-	struct aead_alg crypto_morus640_##id##_algs[] = {\
++	static struct aead_alg crypto_morus640_##id##_algs[] = {\
+ 		{ \
+ 			.setkey = crypto_morus640_glue_setkey, \
+ 			.setauthsize = crypto_morus640_glue_setauthsize, \

commit 1ec49a236565060566be547b6e050bb414d0da96
+Author: Valdis Kletnieks 
+Date:   Wed Aug 8 16:16:54 2018 -0400
+
+    mt76: fix build for MediaTek MT7610U USB wireless dongle
+    
+    The mt76x0 driver requires the mt76 core driver to actually function.
+    So add a 'select' to avoid embarrassing 'symbol unknown' errors
+    when attempting to modprobe it in a module tree that doesn't
+    include mt76.ko
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Kalle Valo 
+
+diff --git a/drivers/net/wireless/mediatek/mt76/Kconfig b/drivers/net/wireless/mediatek/mt76/Kconfig
+index 850611ad347a..b6c5f17dca30 100644
+--- a/drivers/net/wireless/mediatek/mt76/Kconfig
++++ b/drivers/net/wireless/mediatek/mt76/Kconfig
+@@ -11,6 +11,7 @@ config MT76x2_COMMON
+ 
+ config MT76x0U
+ 	tristate "MediaTek MT76x0U (USB) support"
++	select MT76_CORE
+ 	depends on MAC80211
+ 	depends on USB
+ 	help

commit 701b3a3c0ac42630f74a5efba8545d61ac0e3293
+Author: Valdis Kletnieks 
+Date:   Tue Jul 17 12:57:29 2018 -0400
+
+    PATCH scripts/kernel-doc
+    
+    Fix a warning whinge from Perl introduced by "scripts: kernel-doc: parse next structs/unions"
+    
+    Unescaped left brace in regex is deprecated here (and will be fatal in Perl 5.32), passed through in regex; marked by <-- HERE in m/({ <-- HERE [^\{\}]*})/ at ./scripts/kernel-doc line 1155.
+    Unescaped left brace in regex is deprecated here (and will be fatal in Perl 5.32), passed through in regex; marked by <-- HERE in m/({ <-- HERE )/ at ./scripts/kernel-doc line 1179.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Reviewed-by: Mauro Carvalho Chehab 
+    Signed-off-by: Jonathan Corbet 
+
+diff --git a/scripts/kernel-doc b/scripts/kernel-doc
+index 0057d8eafcc1..31a34ced55a3 100755
+--- a/scripts/kernel-doc
++++ b/scripts/kernel-doc
+@@ -1152,7 +1152,7 @@ sub dump_struct($$) {
+ 	}
+ 
+ 	# Ignore other nested elements, like enums
+-	$members =~ s/({[^\{\}]*})//g;
++	$members =~ s/(\{[^\{\}]*})//g;
+ 
+ 	create_parameterlist($members, ';', $file, $declaration_name);
+ 	check_sections($file, $declaration_name, $decl_type, $sectcheck, $struct_actual);
+@@ -1176,7 +1176,7 @@ sub dump_struct($$) {
+ 			$declaration .= "\t" x $level;
+ 		}
+ 		$declaration .= "\t" . $clause . "\n";
+-		$level++ if ($clause =~ m/({)/ && !($clause =~m/}/));
++		$level++ if ($clause =~ m/(\{)/ && !($clause =~m/}/));
+ 	}
+ 	output_declaration($declaration_name,
+ 			   'struct',

commit 80d172431696482d9acd8d2c4ea78fed8956e2a1
+Author: Valdis Kletnieks 
+Date:   Sun Feb 4 12:01:43 2018 -0500
+
+    gcc-plugins: Add include required by GCC release 8
+    
+    GCC requires another #include to get the gcc-plugins to build cleanly.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Kees Cook 
+
+diff --git a/scripts/gcc-plugins/gcc-common.h b/scripts/gcc-plugins/gcc-common.h
+index ffd1dfaa1cc1..f46750053377 100644
+--- a/scripts/gcc-plugins/gcc-common.h
++++ b/scripts/gcc-plugins/gcc-common.h
+@@ -97,6 +97,10 @@
+ #include "predict.h"
+ #include "ipa-utils.h"
+ 
++#if BUILDING_GCC_VERSION >= 8000
++#include "stringpool.h"
++#endif
++
+ #if BUILDING_GCC_VERSION >= 4009
+ #include "attribs.h"
+ #include "varasm.h"

commit 0da325afbdb80098e014b83937372e3eef6872d5
+Author: Valdis Kletnieks 
+Date:   Tue Sep 20 18:14:53 2016 -0400
+
+    ALSA: line6: snd-usb-line6 depends on CONFIG_SND_HWDEP
+    
+    ERROR: "snd_hwdep_new" [sound/usb/line6/snd-usb-line6.ko] undefined!
+    scripts/Makefile.modpost:91: recipe for target '__modpost' failed
+    make[1]: *** [__modpost] Error 1
+    
+    Fixes: a16039cbf1a1 ('ALSA: line6: Add hwdep interface to access the POD control messages')
+    Signed-off-by: Valdis Kletnieks 
+    Reviewed-by: Takashi Sakamoto 
+    Signed-off-by: Takashi Iwai 
+
+diff --git a/sound/usb/line6/Kconfig b/sound/usb/line6/Kconfig
+index 8ffcf48097d9..39b400392d71 100644
+--- a/sound/usb/line6/Kconfig
++++ b/sound/usb/line6/Kconfig
+@@ -2,6 +2,7 @@ config SND_USB_LINE6
+ 	tristate
+ 	select SND_RAWMIDI
+ 	select SND_PCM
++	select SND_HWDEP
+ 
+ config SND_USB_POD
+ 	tristate "Line 6 POD USB support"

commit 5e44258d168b2bdee51d9e2e1f1f4726ff9775cd
+Author: Valdis Kletnieks 
+Date:   Sun Jul 31 23:24:50 2016 -0400
+
+    x86/build: Reduce the W=1 warnings noise when compiling x86 syscall tables
+    
+    Building an X86_64 kernel with W=1 throws a total of 9,948 lines of warnings of
+    this form for both 32-bit and 64-bit syscall tables. Given that the entire rest
+    of the build for my config only generates 8,375 lines of output, this is a big
+    reduction in the warnings generated.
+    
+    The warnings follow this pattern:
+    
+      ./arch/x86/include/generated/asm/syscalls_32.h:885:21: warning: initialized field overwritten [-Woverride-init]
+       __SYSCALL_I386(379, compat_sys_pwritev2, )
+                         ^
+      arch/x86/entry/syscall_32.c:13:46: note: in definition of macro '__SYSCALL_I386'
+       #define __SYSCALL_I386(nr, sym, qual) [nr] = sym,
+                                                  ^~~
+      ./arch/x86/include/generated/asm/syscalls_32.h:885:21: note: (near initialization for 'ia32_sys_call_table[379]')
+       __SYSCALL_I386(379, compat_sys_pwritev2, )
+                         ^
+      arch/x86/entry/syscall_32.c:13:46: note: in definition of macro '__SYSCALL_I386'
+       #define __SYSCALL_I386(nr, sym, qual) [nr] = sym,
+    
+    Since we intentionally build the syscall tables this way, ignore that one
+    warning in the two files.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Cc: Andy Lutomirski 
+    Cc: Borislav Petkov 
+    Cc: Brian Gerst 
+    Cc: Denys Vlasenko 
+    Cc: H. Peter Anvin 
+    Cc: Josh Poimboeuf 
+    Cc: Linus Torvalds 
+    Cc: Peter Zijlstra 
+    Cc: Thomas Gleixner 
+    Link: http://lkml.kernel.org/r/7464.1470021890@turing-police.cc.vt.edu
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/x86/entry/Makefile b/arch/x86/entry/Makefile
+index fe91c25092da..77f28ce9c646 100644
+--- a/arch/x86/entry/Makefile
++++ b/arch/x86/entry/Makefile
+@@ -5,6 +5,8 @@
+ OBJECT_FILES_NON_STANDARD_entry_$(BITS).o   := y
+ OBJECT_FILES_NON_STANDARD_entry_64_compat.o := y
+ 
++CFLAGS_syscall_64.o		+= -Wno-override-init
++CFLAGS_syscall_32.o		+= -Wno-override-init
+ obj-y				:= entry_$(BITS).o thunk_$(BITS).o syscall_$(BITS).o
+ obj-y				+= common.o
+ 

commit f1cb637e75b59a07450cf81ad68b04f3f46b03d7
+Author: Valdis Kletnieks 
+Date:   Tue Aug 2 14:07:27 2016 -0700
+
+    init/Kconfig: add clarification for out-of-tree modules
+    
+    It doesn't trim just symbols that are totally unused in-tree - it trims
+    the symbols unused by any in-tree modules actually built.  If you've
+    done a 'make localmodconfig' and only build a hundred or so modules,
+    it's pretty likely that your out-of-tree module will come up lacking
+    something...
+    
+    Hopefully this will save the next guy from a Homer Simpson "D'oh!"
+    moment.
+    
+    Link: http://lkml.kernel.org/r/10177.1469787292@turing-police.cc.vt.edu
+    Signed-off-by: Valdis Kletnieks 
+    Cc: Michal Marek 
+    Cc: Rusty Russell 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/init/Kconfig b/init/Kconfig
+index 380798f86aae..69886493ff1e 100644
+--- a/init/Kconfig
++++ b/init/Kconfig
+@@ -2080,7 +2080,7 @@ config TRIM_UNUSED_KSYMS
+ 	  (especially when using LTO) for optimizing the code and reducing
+ 	  binary size.  This might have some security advantages as well.
+ 
+-	  If unsure say N.
++	  If unsure, or if you need to build out-of-tree modules, say N.
+ 
+ endif # MODULES
+ 

commit ca52953f5f24aff0aa8fa8de750b76ba0302142d
+Author: Valdis Kletnieks 
+Date:   Tue Aug 2 14:03:25 2016 -0700
+
+    fs/proc/task_mmu.c: suppress compilation warnings with W=1
+    
+    Suppress a bunch of warnings of the form:
+    
+      fs/proc/task_mmu.c: In function 'show_smap_vma_flags':
+      fs/proc/task_mmu.c:635:22: warning: initialized field overwritten [-Wt override-init]
+         [ilog2(VM_READ)] = "rd",
+                            ^~~~
+      fs/proc/task_mmu.c:635:22: note: (near initialization for 'mnemonics[0]')
+    
+    They happen because of the way we intentionally build the table, so
+    silence the warning when building with 'make W=1'.
+    
+    Link: http://lkml.kernel.org/r/8727.1470022083@turing-police.cc.vt.edu
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/proc/Makefile b/fs/proc/Makefile
+index 7151ea428041..a8c13605b434 100644
+--- a/fs/proc/Makefile
++++ b/fs/proc/Makefile
+@@ -4,6 +4,7 @@
+ 
+ obj-y   += proc.o
+ 
++CFLAGS_task_mmu.o	+= -Wno-override-init
+ proc-y			:= nommu.o task_nommu.o
+ proc-$(CONFIG_MMU)	:= task_mmu.o
+ 

commit 117dec978cf64e8e96f13d0cf4891ff77c9acf55
+Author: Valdis Kletnieks 
+Date:   Tue Aug 2 14:02:28 2016 -0700
+
+    tools/testing/radix-tree/linux/gfp.h: fix bitrotted value
+    
+    Apparently, the tools/testing version dates to a few flags ago, and
+    we've sprouted 4 new ones since.  Keep in sync with the value in the
+    main tree...
+    
+    Link: http://lkml.kernel.org/r/23400.1469702675@turing-police.cc.vt.edu
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/tools/testing/radix-tree/linux/gfp.h b/tools/testing/radix-tree/linux/gfp.h
+index 0e37f7a760eb..5201b915f631 100644
+--- a/tools/testing/radix-tree/linux/gfp.h
++++ b/tools/testing/radix-tree/linux/gfp.h
+@@ -1,7 +1,7 @@
+ #ifndef _GFP_H
+ #define _GFP_H
+ 
+-#define __GFP_BITS_SHIFT 22
++#define __GFP_BITS_SHIFT 26
+ #define __GFP_BITS_MASK ((gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
+ #define __GFP_WAIT 1
+ #define __GFP_ACCOUNT 0

commit c67f69576bba438e69f3d0657e08bdecb4cc2097
+Author: Valdis Kletnieks 
+Date:   Mon May 30 02:26:38 2016 -0400
+
+    Fix annoyingly awkward typo in drm_edid_load.c
+    
+    Fix egregious typo in comment.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Daniel Vetter 
+    Link: http://patchwork.freedesktop.org/patch/msgid/10576.1464589598@turing-police.cc.vt.edu
+
+diff --git a/drivers/gpu/drm/drm_edid_load.c b/drivers/gpu/drm/drm_edid_load.c
+index 9a401aed98e0..622f788bff46 100644
+--- a/drivers/gpu/drm/drm_edid_load.c
++++ b/drivers/gpu/drm/drm_edid_load.c
+@@ -271,7 +271,7 @@ int drm_load_edid_firmware(struct drm_connector *connector)
+ 	 * by commas, search through the list looking for one that
+ 	 * matches the connector.
+ 	 *
+-	 * If there's one or more that don't't specify a connector, keep
++	 * If there's one or more that doesn't specify a connector, keep
+ 	 * the last one found one as a fallback.
+ 	 */
+ 	fwstr = kstrdup(edid_firmware, GFP_KERNEL);

commit ad0d7799382b37e6afa910f27fa342af62d80ded
+Author: Valdis Kletnieks 
+Date:   Tue Dec 22 19:36:54 2015 -0500
+
+    drivers/staging/lustre: Nuke another unsigned >= 0 assert
+    
+    Clean up another case of the compiler remininding the programmer they
+    are an idiot:
+    
+    drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c:308:34: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits]
+      LASSERT(page_pools.epp_waitqlen >= 0);
+    
+    Just lose the assert, and save a page of compiler spew.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c
+index 6152c1b766c3..22621c74a66a 100644
+--- a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c
++++ b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c
+@@ -304,7 +304,6 @@ static unsigned long enc_pools_cleanup(struct page ***pools, int npools)
+ static inline void enc_pools_wakeup(void)
+ {
+ 	assert_spin_locked(&page_pools.epp_lock);
+-	LASSERT(page_pools.epp_waitqlen >= 0);
+ 
+ 	if (unlikely(page_pools.epp_waitqlen)) {
+ 		LASSERT(waitqueue_active(&page_pools.epp_waitq));

commit bd6455de1a1af6b382b9ee93311397284c165c92
+Author: Valdis Kletnieks 
+Date:   Tue Dec 22 19:36:53 2015 -0500
+
+    drivers/staging/lustre: Nuke an unsigned >= 0 assert
+    
+    Writing asserts for almost-never-can-happen things can be valuable.
+    Writing an assert that tests that an "unsigned int" hasn't gone negative
+    isn't.
+    
+    And it generates an *ugly* message:
+    
+    drivers/staging/lustre/lustre/llite/rw.c:763:20: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits]
+      LASSERTF(reserved >= 0, "reserved %lu\n", reserved);
+                        ^
+    include/linux/compiler.h:137:45: note: in definition of macro 'unlikely'
+     #  define unlikely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 0))
+                                                 ^
+    drivers/staging/lustre/lustre/llite/rw.c:763:2: note: in expansion of macro 'LASSERTF'
+      LASSERTF(reserved >= 0, "reserved %lu\n", reserved);
+      ^
+    drivers/staging/lustre/lustre/llite/rw.c:763:20: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits]
+      LASSERTF(reserved >= 0, "reserved %lu\n", reserved);
+                        ^
+    include/linux/compiler.h:137:53: note: in definition of macro 'unlikely'
+     #  define unlikely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 0))
+                                                         ^
+    drivers/staging/lustre/lustre/llite/rw.c:763:2: note: in expansion of macro 'LASSERTF'
+      LASSERTF(reserved >= 0, "reserved %lu\n", reserved);
+      ^
+    drivers/staging/lustre/lustre/llite/rw.c:763:20: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits]
+      LASSERTF(reserved >= 0, "reserved %lu\n", reserved);
+                        ^
+    include/linux/compiler.h:110:47: note: in definition of macro 'likely_notrace'
+     #define likely_notrace(x) __builtin_expect(!!(x), 1)
+                                                   ^
+    include/linux/compiler.h:137:58: note: in expansion of macro '__branch_check__'
+     #  define unlikely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 0))
+                                                              ^
+    drivers/staging/lustre/lustre/llite/../include/linux/../../../include/linux/libcfs/libcfs_private.h:58:6: note: in expansion of macro 'unlikely'
+      if (unlikely(!(cond))) {     \
+          ^
+    drivers/staging/lustre/lustre/llite/rw.c:763:2: note: in expansion of macro 'LASSERTF'
+      LASSERTF(reserved >= 0, "reserved %lu\n", reserved);
+      ^
+    
+    Umm, thank you, GCC.  We'll delete the problem line so we never see that spew again.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c
+index f355474967d6..6b587d66d1b3 100644
+--- a/drivers/staging/lustre/lustre/llite/rw.c
++++ b/drivers/staging/lustre/lustre/llite/rw.c
+@@ -764,7 +764,6 @@ int ll_readahead(const struct lu_env *env, struct cl_io *io,
+ 	ret = ll_read_ahead_pages(env, io, queue,
+ 				  ria, &reserved, mapping, &ra_end);
+ 
+-	LASSERTF(reserved >= 0, "reserved %lu\n", reserved);
+ 	if (reserved != 0)
+ 		ll_ra_count_put(ll_i2sbi(inode), reserved);
+ 

commit 5aec2e0791a5a76bec020b088a8b8a10afcfd522
+Author: Valdis Kletnieks 
+Date:   Tue Dec 22 19:36:52 2015 -0500
+
+    drivers/staging/lustre: Fix another C compiler whine: set but not used
+    
+      CC [M]  drivers/staging/lustre/lustre/libcfs/module.o
+    drivers/staging/lustre/lustre/libcfs/module.c: In function 'lustre_insert_debugfs':
+    drivers/staging/lustre/lustre/libcfs/module.c:670:17: warning: variable 'entry' set but not used [-Wunused-but-set-variable]
+      struct dentry *entry;
+                         ^
+    
+    Just ignore the dentry returned, and add a comment that we *know*
+    we're not really leaking the dentry because something else will be able
+    to reap it via recursion.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/lustre/lustre/libcfs/module.c b/drivers/staging/lustre/lustre/libcfs/module.c
+index 0067e5347884..af516a29c20e 100644
+--- a/drivers/staging/lustre/lustre/libcfs/module.c
++++ b/drivers/staging/lustre/lustre/libcfs/module.c
+@@ -511,8 +511,6 @@ static const struct file_operations lnet_debugfs_file_operations = {
+ void lustre_insert_debugfs(struct ctl_table *table,
+ 			   const struct lnet_debugfs_symlink_def *symlinks)
+ {
+-	struct dentry *entry;
+-
+ 	if (lnet_debugfs_root == NULL)
+ 		lnet_debugfs_root = debugfs_create_dir("lnet", NULL);
+ 
+@@ -520,15 +518,17 @@ void lustre_insert_debugfs(struct ctl_table *table,
+ 	if (IS_ERR_OR_NULL(lnet_debugfs_root))
+ 		return;
+ 
++	/* We don't save the dentry returned in next two calls, because
++	 * we don't call debugfs_remove() but rather remove_recursive()
++	 */
+ 	for (; table->procname; table++)
+-		entry = debugfs_create_file(table->procname, table->mode,
+-					    lnet_debugfs_root, table,
+-					    &lnet_debugfs_file_operations);
++		debugfs_create_file(table->procname, table->mode,
++				    lnet_debugfs_root, table,
++				    &lnet_debugfs_file_operations);
+ 
+ 	for (; symlinks && symlinks->name; symlinks++)
+-		entry = debugfs_create_symlink(symlinks->name,
+-					       lnet_debugfs_root,
+-					       symlinks->target);
++		debugfs_create_symlink(symlinks->name, lnet_debugfs_root,
++				       symlinks->target);
+ 
+ }
+ EXPORT_SYMBOL_GPL(lustre_insert_debugfs);

commit 7f6ab07293c8ee6a64783b01840189f894dc3f16
+Author: Valdis Kletnieks 
+Date:   Tue Dec 22 19:36:51 2015 -0500
+
+    drivers/staging/lustre: Clean up another C warnining: set but not used
+    
+    drivers/staging/lustre/lustre/fid/../include/lustre_cfg.h: In function 'lustre_cfg_free':
+    drivers/staging/lustre/lustre/fid/../include/lustre_cfg.h:253:6: warning: variable 'len' set but not used [-Wunused-but-set-variable]
+      int len;
+    
+    Yep, we're just gonna call kfree, no need to calculate len. Bye-bye.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/lustre/lustre/include/lustre_cfg.h b/drivers/staging/lustre/lustre/include/lustre_cfg.h
+index eb6b292b7b25..d30d8b054c92 100644
+--- a/drivers/staging/lustre/lustre/include/lustre_cfg.h
++++ b/drivers/staging/lustre/lustre/include/lustre_cfg.h
+@@ -252,10 +252,6 @@ static inline struct lustre_cfg *lustre_cfg_new(int cmd,
+ 
+ static inline void lustre_cfg_free(struct lustre_cfg *lcfg)
+ {
+-	int len;
+-
+-	len = lustre_cfg_len(lcfg->lcfg_bufcount, lcfg->lcfg_buflens);
+-
+ 	kfree(lcfg);
+ 	return;
+ }

commit f65a0922f024d44a73fa113a833e55f4a5033597
+Author: Valdis Kletnieks 
+Date:   Tue Dec 22 19:36:50 2015 -0500
+
+    drivers/staging/lustre: Fix set-but-unused whinge.
+    
+    drivers/staging/lustre/lustre/fid/lproc_fid.c: In function 'ldebugfs_fid_write_common':
+    drivers/staging/lustre/lustre/fid/lproc_fid.c:67:6: warning: variable 'rc' set but not used [-Wunused-but-set-variable]
+      int rc;
+    
+    We fix it by *using* the return code to help bulletproof it.  It says it's
+    test code - it should be *more* bulletproof than production, not less.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/lustre/lustre/fid/lproc_fid.c b/drivers/staging/lustre/lustre/fid/lproc_fid.c
+index 39f2aa32e984..0320b6e83576 100644
+--- a/drivers/staging/lustre/lustre/fid/lproc_fid.c
++++ b/drivers/staging/lustre/lustre/fid/lproc_fid.c
+@@ -85,6 +85,8 @@ ldebugfs_fid_write_common(const char __user *buffer, size_t count,
+ 	rc = sscanf(kernbuf, "[%llx - %llx]\n",
+ 		    (unsigned long long *)&tmp.lsr_start,
+ 		    (unsigned long long *)&tmp.lsr_end);
++	if (rc != 2)
++		return -EINVAL;
+ 	if (!range_is_sane(&tmp) || range_is_zero(&tmp) ||
+ 	    tmp.lsr_start < range->lsr_start || tmp.lsr_end > range->lsr_end)
+ 		return -EINVAL;

commit b8947b399dbbce510183521d80f361df462e4383
+Author: Valdis Kletnieks 
+Date:   Tue Dec 22 19:36:49 2015 -0500
+
+    drivers/staging/lustre: Silence warning about 'inline'
+    
+    Low-hanging fruit first:
+    
+      CC [M]  drivers/staging/lustre/lustre/fid/fid_request.o
+    In file included from drivers/staging/lustre/lustre/fid/../include/lustre_net.h:66:0,
+                     from drivers/staging/lustre/lustre/fid/../include/lustre_lib.h:64,
+                     from drivers/staging/lustre/lustre/fid/../include/obd.h:52,
+                     from drivers/staging/lustre/lustre/fid/fid_request.c:48:
+    drivers/staging/lustre/lustre/fid/../include/lu_object.h:765:1: warning: 'inline' is not at beginning of declaration [-Wold-style-declaration]
+     static const inline struct lu_device_operations *
+     ^
+    
+    So we just swap inline and const.  272 warnings gone. :)
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/lustre/lustre/include/lu_object.h b/drivers/staging/lustre/lustre/include/lu_object.h
+index ee1dbb257d5d..0b22e5ee99ac 100644
+--- a/drivers/staging/lustre/lustre/include/lu_object.h
++++ b/drivers/staging/lustre/lustre/include/lu_object.h
+@@ -756,7 +756,7 @@ static inline const struct lu_fid *lu_object_fid(const struct lu_object *o)
+ /**
+  * return device operations vector for this object
+  */
+-static const inline struct lu_device_operations *
++static inline const struct lu_device_operations *
+ lu_object_ops(const struct lu_object *o)
+ {
+ 	return o->lo_dev->ld_ops;

commit e8dd2d2d641cb2724ee10e76c0ad02e04289c017
+Author: Valdis Kletnieks 
+Date:   Sat Aug 29 17:49:16 2015 -0400
+
+    Silence compiler warning in arch/x86/kvm/emulate.c
+    
+    Compiler warning:
+    
+     CC [M]  arch/x86/kvm/emulate.o
+    arch/x86/kvm/emulate.c: In function "__do_insn_fetch_bytes":
+    arch/x86/kvm/emulate.c:814:9: warning: "linear" may be used uninitialized in this function [-Wmaybe-uninitialized]
+    
+    GCC is smart enough to realize that the inlined __linearize may return before
+    setting the value of linear, but not smart enough to realize the same
+    X86EMU_CONTINUE blocks actual use of the value.  However, the value of
+    'linear' can only be set to one value, so hoisting the one line of code
+    upwards makes GCC happy with the code.
+    
+    Reported-by: Aruna Hewapathirane 
+    Tested-by: Aruna Hewapathirane 
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Paolo Bonzini 
+
+diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
+index e7a4fde5d631..b372a7557c16 100644
+--- a/arch/x86/kvm/emulate.c
++++ b/arch/x86/kvm/emulate.c
+@@ -650,6 +650,7 @@ static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt,
+ 	u16 sel;
+ 
+ 	la = seg_base(ctxt, addr.seg) + addr.ea;
++	*linear = la;
+ 	*max_size = 0;
+ 	switch (mode) {
+ 	case X86EMUL_MODE_PROT64:
+@@ -693,7 +694,6 @@ static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt,
+ 	}
+ 	if (insn_aligned(ctxt, size) && ((la & (size - 1)) != 0))
+ 		return emulate_gp(ctxt, 0);
+-	*linear = la;
+ 	return X86EMUL_CONTINUE;
+ bad:
+ 	if (addr.seg == VCPU_SREG_SS)

commit 9261dc1de11e158a5f6b4b92c8bf1ef4a02dbf0d
+Author: Valdis Kletnieks 
+Date:   Fri Jan 2 11:19:57 2015 -0500
+
+    x86/build/defconfig: Enable USB_EHCI_TT_NEWSCHED=y
+    
+    Some Gentoo users are encountering problems because
+    USB_EHCI_TT_NEWSCHED isn't set in the defconfig (and Gentoo
+    differs from other distros in not providing a distro .config).
+    Alan Stern has said there's no reason to not set it, and the
+    ability to turn it off at all should probably be yanked:
+    
+      http://article.gmane.org/gmane.linux.usb.general/119920
+    
+    This addresses issue:
+    
+      https://bugs.gentoo.org/show_bug.cgi?id=533472
+    
+    (The problem also theoretically affects the sh, arm, mips,
+    powerpc, and sparc archs, but those would be other patches if
+    this one that fixes 98% of the problem is accepted).
+    
+    Signed-off-by: Valdis Kletnieks 
+    Acked-by: Alan Stern 
+    Signed-off-by: Ingo Molnar 
+
+diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig
+index 419819d6dab3..aaa1118bf01e 100644
+--- a/arch/x86/configs/i386_defconfig
++++ b/arch/x86/configs/i386_defconfig
+@@ -248,7 +248,7 @@ CONFIG_USB=y
+ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+ CONFIG_USB_MON=y
+ CONFIG_USB_EHCI_HCD=y
+-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
++CONFIG_USB_EHCI_TT_NEWSCHED=y
+ CONFIG_USB_OHCI_HCD=y
+ CONFIG_USB_UHCI_HCD=y
+ CONFIG_USB_PRINTER=y
+diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig
+index 4c311ddd973b..315b86106572 100644
+--- a/arch/x86/configs/x86_64_defconfig
++++ b/arch/x86/configs/x86_64_defconfig
+@@ -243,7 +243,7 @@ CONFIG_USB=y
+ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+ CONFIG_USB_MON=y
+ CONFIG_USB_EHCI_HCD=y
+-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
++CONFIG_USB_EHCI_TT_NEWSCHED=y
+ CONFIG_USB_OHCI_HCD=y
+ CONFIG_USB_UHCI_HCD=y
+ CONFIG_USB_PRINTER=y

commit 69204cf7eb9c5a72067ce6922d4699378251d053
+Author: Valdis Kletnieks 
+Date:   Tue Dec 9 16:15:50 2014 -0500
+
+    net: fix suspicious rcu_dereference_check in net/sched/sch_fq_codel.c
+    
+    commit 46e5da40ae (net: qdisc: use rcu prefix and silence
+     sparse warnings) triggers a spurious warning:
+    
+    net/sched/sch_fq_codel.c:97 suspicious rcu_dereference_check() usage!
+    
+    The code should be using the _bh variant of rcu_dereference.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Acked-by: Eric Dumazet 
+    Acked-by: John Fastabend 
+    Signed-off-by: David S. Miller 
+
+diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c
+index b9ca32ebc1de..1e52decb7b59 100644
+--- a/net/sched/sch_fq_codel.c
++++ b/net/sched/sch_fq_codel.c
+@@ -94,7 +94,7 @@ static unsigned int fq_codel_classify(struct sk_buff *skb, struct Qdisc *sch,
+ 	    TC_H_MIN(skb->priority) <= q->flows_cnt)
+ 		return TC_H_MIN(skb->priority);
+ 
+-	filter = rcu_dereference(q->filter_list);
++	filter = rcu_dereference_bh(q->filter_list);
+ 	if (!filter)
+ 		return fq_codel_hash(q, skb) + 1;
+ 

commit d4bf205da618bbd0b038e404d646f14e76915718
+Author: Valdis Kletnieks 
+Date:   Sun Oct 12 23:09:08 2014 -0400
+
+    pstore: Fix duplicate {console,ftrace}-efi entries
+    
+    The pstore filesystem still creates duplicate filename/inode pairs for
+    some pstore types.  Add the id to the filename to prevent that.
+    
+    Before patch:
+    
+    [/sys/fs/pstore] ls -li
+    total 0
+    1250 -r--r--r--. 1 root root 67 Sep 29 17:09 console-efi
+    1250 -r--r--r--. 1 root root 67 Sep 29 17:09 console-efi
+    1250 -r--r--r--. 1 root root 67 Sep 29 17:09 console-efi
+    1250 -r--r--r--. 1 root root 67 Sep 29 17:09 console-efi
+    1250 -r--r--r--. 1 root root 67 Sep 29 17:09 console-efi
+    1250 -r--r--r--. 1 root root 67 Sep 29 17:09 console-efi
+    1250 -r--r--r--. 1 root root 67 Sep 29 17:09 console-efi
+    1250 -r--r--r--. 1 root root 67 Sep 29 17:09 console-efi
+    1250 -r--r--r--. 1 root root 67 Sep 29 17:09 console-efi
+    
+    After:
+    
+    [/sys/fs/pstore] ls -li
+    total 0
+    1232 -r--r--r--. 1 root root 148 Sep 29 17:09 console-efi-141202499100000
+    1231 -r--r--r--. 1 root root  67 Sep 29 17:09 console-efi-141202499200000
+    1230 -r--r--r--. 1 root root 148 Sep 29 17:44 console-efi-141202705400000
+    1229 -r--r--r--. 1 root root  67 Sep 29 17:44 console-efi-141202705500000
+    1228 -r--r--r--. 1 root root  67 Sep 29 20:42 console-efi-141203772600000
+    1227 -r--r--r--. 1 root root 148 Sep 29 23:42 console-efi-141204854900000
+    1226 -r--r--r--. 1 root root  67 Sep 29 23:42 console-efi-141204855000000
+    1225 -r--r--r--. 1 root root 148 Sep 29 23:59 console-efi-141204954200000
+    1224 -r--r--r--. 1 root root  67 Sep 29 23:59 console-efi-141204954400000
+    
+    Signed-off-by: Valdis Kletnieks 
+    Acked-by: Kees Cook 
+    Cc: stable@vger.kernel.org # 3.6+
+    Signed-off-by: Tony Luck 
+
+diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
+index 192297b0090d..fafb7a02a5d6 100644
+--- a/fs/pstore/inode.c
++++ b/fs/pstore/inode.c
+@@ -320,10 +320,10 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, int count,
+ 						compressed ? ".enc.z" : "");
+ 		break;
+ 	case PSTORE_TYPE_CONSOLE:
+-		sprintf(name, "console-%s", psname);
++		sprintf(name, "console-%s-%lld", psname, id);
+ 		break;
+ 	case PSTORE_TYPE_FTRACE:
+-		sprintf(name, "ftrace-%s", psname);
++		sprintf(name, "ftrace-%s-%lld", psname, id);
+ 		break;
+ 	case PSTORE_TYPE_MCE:
+ 		sprintf(name, "mce-%s-%lld", psname, id);

commit 79d99c305fd4edb9ee11ff57f43dc961ad684ab6
+Author: Valdis Kletnieks 
+Date:   Mon Sep 8 18:09:48 2014 -0400
+
+    staging/rtl8192u - check for skb alloc failure
+    
+    It's possible for dev_alloc_skb() to fail. Propagate the error to the caller,
+    so it can clean up and drop the packet. The sender should end up retransmitting
+    the packet, hopefully at a time we're prepared to allocate skb's again.
+    
+    Reported-By: Nicholas Krause 
+    Signed-Off-By: Valdis Kletnieks 
+    
+    Signed-off-by: Greg Kroah-Hartman 
+
+diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
+index 40da37fdbcdc..73de9e9669f6 100644
+--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
++++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
+@@ -847,6 +847,8 @@ static u8 parse_subframe(struct sk_buff *skb,
+ #else
+ 			/* Allocate new skb for releasing to upper layer */
+ 			sub_skb = dev_alloc_skb(nSubframe_Length + 12);
++			if (!sub_skb)
++				return 0;
+ 			skb_reserve(sub_skb, 12);
+ 			data_ptr = (u8 *)skb_put(sub_skb, nSubframe_Length);
+ 			memcpy(data_ptr, skb->data, nSubframe_Length);

commit 015af06e103fa47af29ada0f564301c81d4973b2
+Author: Valdis Kletnieks 
+Date:   Tue May 27 14:28:59 2014 -0400
+
+    kernel/workqueue.c: pr_warning/pr_warn & printk/pr_info
+    
+    This commit did an incorrect printk->pr_info conversion. If we were
+    converting to pr_info() we should lose the log_level parameter. The problem is
+    that this is called (indirectly) by show_regs_print_info(), which is called
+    with various log_levels (from _INFO clear to _EMERG). So we leave it as
+    a printk() call so the desired log_level is applied.
+    
+    Not a full revert, as the other half of the patch is correct.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Tejun Heo 
+
+diff --git a/kernel/workqueue.c b/kernel/workqueue.c
+index bc3c18892b7d..90a0fa592b72 100644
+--- a/kernel/workqueue.c
++++ b/kernel/workqueue.c
+@@ -4440,7 +4440,7 @@ void print_worker_info(const char *log_lvl, struct task_struct *task)
+ 		probe_kernel_read(desc, worker->desc, sizeof(desc) - 1);
+ 
+ 	if (fn || name[0] || desc[0]) {
+-		pr_info("%sWorkqueue: %s %pf", log_lvl, name, fn);
++		printk("%sWorkqueue: %s %pf", log_lvl, name, fn);
+ 		if (desc[0])
+ 			pr_cont(" (%s)", desc);
+ 		pr_cont("\n");

commit 5d1fadc1472396d602f0eeb10d37519e2a14e8bc
+Author: Valdis Kletnieks 
+Date:   Wed Feb 27 17:03:13 2013 -0800
+
+    kernel/signal.c: fix suboptimal printk usage
+    
+    Several printk's were missing KERN_INFO and KERN_CONT flags.  In
+    addition, a printk that was outside a #if/#endif should have been
+    inside, which would result in stray blank line on non-x86 boxes.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Cc: Oleg Nesterov 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/kernel/signal.c b/kernel/signal.c
+index c6209135cca4..2676aac4103d 100644
+--- a/kernel/signal.c
++++ b/kernel/signal.c
+@@ -1157,11 +1157,11 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
+ static void print_fatal_signal(int signr)
+ {
+ 	struct pt_regs *regs = signal_pt_regs();
+-	printk("%s/%d: potentially unexpected fatal signal %d.\n",
++	printk(KERN_INFO "%s/%d: potentially unexpected fatal signal %d.\n",
+ 		current->comm, task_pid_nr(current), signr);
+ 
+ #if defined(__i386__) && !defined(__arch_um__)
+-	printk("code at %08lx: ", regs->ip);
++	printk(KERN_INFO "code at %08lx: ", regs->ip);
+ 	{
+ 		int i;
+ 		for (i = 0; i < 16; i++) {
+@@ -1169,11 +1169,11 @@ static void print_fatal_signal(int signr)
+ 
+ 			if (get_user(insn, (unsigned char *)(regs->ip + i)))
+ 				break;
+-			printk("%02x ", insn);
++			printk(KERN_CONT "%02x ", insn);
+ 		}
+ 	}
++	printk(KERN_CONT "\n");
+ #endif
+-	printk("\n");
+ 	preempt_disable();
+ 	show_regs(regs);
+ 	preempt_enable();

commit 38124328fb3ea0b28451071bf3c7401e35c91020
+Author: Reese Moore 
+Date:   Wed Nov 7 07:05:08 2012 +0000
+
+    netfilter: nf_ct_pptp: Fix comment referring to incorrect RFC
+    
+    The header of this file cites to "RFFC2673" which is "Binary Labels in the
+    Domain Name System". It should refer to "RFC 2637" which is "Point-to-Point
+    Tunneling Protocol (PPTP)". This patch also corrects the typo RFFC.
+    
+    Signed-off-by: Reese Moore 
+    Signed-off-by: Pablo Neira Ayuso 
+
+diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c
+index cc7669ef0b95..e6678d2b624e 100644
+--- a/net/netfilter/nf_conntrack_pptp.c
++++ b/net/netfilter/nf_conntrack_pptp.c
+@@ -14,7 +14,7 @@
+  * Limitations:
+  * 	 - We blindly assume that control connections are always
+  * 	   established in PNS->PAC direction.  This is a violation
+- * 	   of RFFC2673
++ *	   of RFC 2637
+  * 	 - We can only support one single call within each session
+  * TODO:
+  *	 - testing of incoming PPTP calls

commit d19978f58745e586d9385d306d557e7c785abe23
+Author: Valdis Kletnieks 
+Date:   Wed Nov 9 01:29:20 2011 -0500
+
+    crypto: fix typo in crypto/Kconfig
+    
+    Fix a typo in the Kconfig file help text.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Herbert Xu 
+
+diff --git a/crypto/Kconfig b/crypto/Kconfig
+index 527a857d10b6..733208fe0a2d 100644
+--- a/crypto/Kconfig
++++ b/crypto/Kconfig
+@@ -105,7 +105,7 @@ config CRYPTO_USER
+ 	depends on NET
+ 	select CRYPTO_MANAGER
+ 	help
+-	  Userapace configuration for cryptographic instantiations such as
++	  Userspace configuration for cryptographic instantiations such as
+ 	  cbc(aes).
+ 
+ config CRYPTO_MANAGER_DISABLE_TESTS

commit d2df40857fd57f02906e6ac1484d10cb7accbc86
+Author: Valdis Kletnieks 
+Date:   Fri Oct 29 17:03:46 2010 -0400
+
+    drivers/dma/Kconfig: add part number for Topcliff.
+    
+    Product codenames are OK, but once an actual product name is available,
+    it should be referenced as well.
+    
+      http://ark.intel.com/chipset.aspx?familyID=52499
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
+index 79d1542f31c0..6ee23592700a 100644
+--- a/drivers/dma/Kconfig
++++ b/drivers/dma/Kconfig
+@@ -200,11 +200,11 @@ config PL330_DMA
+ 	  platform_data for a dma-pl330 device.
+ 
+ config PCH_DMA
+-	tristate "Topcliff PCH DMA support"
++	tristate "Topcliff (Intel EG20T) PCH DMA support"
+ 	depends on PCI && X86
+ 	select DMA_ENGINE
+ 	help
+-	  Enable support for the Topcliff PCH DMA engine.
++	  Enable support for the Topcliff (Intel EG20T) PCH DMA engine.
+ 
+ config IMX_SDMA
+ 	tristate "i.MX SDMA support"

commit 4c6a3999651741419cd3cc4303cf0c2be07d89bc
+Author: Valdis Kletnieks 
+Date:   Thu Apr 22 14:29:10 2010 -0400
+
+    dri-devel mailing list moved - update MAINTAINERS
+    
+    I posted to dri-devel@lists.sourceforge.net, and got a bounce back:
+    
+       The dri-devel list has moved to freedesktop.org (see
+       http://lists.freedesktop.org/mailman/listinfo/dri-devel). If you were
+       subscribed to the list here, the subscription should have been
+       transferred to the new location.
+    
+       Please only post to the new list.
+    
+    Fix MAINTAINERS to correspond.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index a2d9254a2233..183887518fe3 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -1960,7 +1960,7 @@ F:	lib/kobj*
+ 
+ DRM DRIVERS
+ M:	David Airlie 
+-L:	dri-devel@lists.sourceforge.net
++L:	dri-devel@lists.freedesktop.org
+ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6.git
+ S:	Maintained
+ F:	drivers/gpu/drm/

commit fb9f88e1dc76f9feb39d39c40a5d61aad6df4388
+Author: Bharath Ramesh 
+Date:   Thu Jan 29 14:25:24 2009 -0800
+
+    hwmon: applesmc: add support for MacPro 3 temperature sensors
+    
+    MacPro 3 have more temperature sensors than the previous MacPro's also the
+    sensor THTG has been removed.  This patch add supports for the newer
+    temperature sensors in the MacPro3.
+    
+    Signed-off-by: Bharath Ramesh 
+    Signed-off-by: Henrik Rydberg 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
+index e30186236588..678e34b01e52 100644
+--- a/drivers/hwmon/applesmc.c
++++ b/drivers/hwmon/applesmc.c
+@@ -83,7 +83,7 @@
+ /*
+  * Temperature sensors keys (sp78 - 2 bytes).
+  */
+-static const char* temperature_sensors_sets[][36] = {
++static const char *temperature_sensors_sets[][41] = {
+ /* Set 0: Macbook Pro */
+ 	{ "TA0P", "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "Th0H",
+ 	  "Th1H", "Tm0P", "Ts0P", "Ts1P", NULL },
+@@ -135,6 +135,13 @@ static const char* temperature_sensors_sets[][36] = {
+ 	{ "TB0T", "TB1S", "TB1T", "TB2S", "TB2T", "TC0D", "TN0D", "TTF0",
+ 	  "TV0P", "TVFP", "TW0P", "Th0P", "Tp0P", "Tp1P", "TpFP", "Ts0P",
+ 	  "Ts0S", NULL },
++/* Set 16: Mac Pro 3,1 (2 x Quad-Core) */
++	{ "TA0P", "TCAG", "TCAH", "TCBG", "TCBH", "TC0C", "TC0D", "TC0P",
++	  "TC1C", "TC1D", "TC2C", "TC2D", "TC3C", "TC3D", "TH0P", "TH1P",
++	  "TH2P", "TH3P", "TMAP", "TMAS", "TMBS", "TM0P", "TM0S", "TM1P",
++	  "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", "TM8S", "TM9P", "TM9S",
++	  "TN0C", "TN0D", "TN0H", "TS0C", "Tp0C", "Tp1C", "Tv0S", "Tv1S",
++	  NULL },
+ };
+ 
+ /* List of keys used to read/write fan speeds */
+@@ -1153,6 +1160,16 @@ static SENSOR_DEVICE_ATTR(temp34_input, S_IRUGO,
+ 					applesmc_show_temperature, NULL, 33);
+ static SENSOR_DEVICE_ATTR(temp35_input, S_IRUGO,
+ 					applesmc_show_temperature, NULL, 34);
++static SENSOR_DEVICE_ATTR(temp36_input, S_IRUGO,
++					applesmc_show_temperature, NULL, 35);
++static SENSOR_DEVICE_ATTR(temp37_input, S_IRUGO,
++					applesmc_show_temperature, NULL, 36);
++static SENSOR_DEVICE_ATTR(temp38_input, S_IRUGO,
++					applesmc_show_temperature, NULL, 37);
++static SENSOR_DEVICE_ATTR(temp39_input, S_IRUGO,
++					applesmc_show_temperature, NULL, 38);
++static SENSOR_DEVICE_ATTR(temp40_input, S_IRUGO,
++					applesmc_show_temperature, NULL, 39);
+ 
+ static struct attribute *temperature_attributes[] = {
+ 	&sensor_dev_attr_temp1_input.dev_attr.attr,
+@@ -1190,6 +1207,11 @@ static struct attribute *temperature_attributes[] = {
+ 	&sensor_dev_attr_temp33_input.dev_attr.attr,
+ 	&sensor_dev_attr_temp34_input.dev_attr.attr,
+ 	&sensor_dev_attr_temp35_input.dev_attr.attr,
++	&sensor_dev_attr_temp36_input.dev_attr.attr,
++	&sensor_dev_attr_temp37_input.dev_attr.attr,
++	&sensor_dev_attr_temp38_input.dev_attr.attr,
++	&sensor_dev_attr_temp39_input.dev_attr.attr,
++	&sensor_dev_attr_temp40_input.dev_attr.attr,
+ 	NULL
+ };
+ 
+@@ -1312,6 +1334,8 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = {
+ 	{ .accelerometer = 0, .light = 0, .temperature_set = 14 },
+ /* MacBook Air 2,1: accelerometer, backlight and temperature set 15 */
+ 	{ .accelerometer = 1, .light = 1, .temperature_set = 15 },
++/* MacPro3,1: temperature set 16 */
++	{ .accelerometer = 0, .light = 0, .temperature_set = 16 },
+ };
+ 
+ /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1".
+@@ -1369,6 +1393,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = {
+ 	  DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
+ 	  DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") },
+ 		&applesmc_dmi_data[4]},
++	{ applesmc_dmi_match, "Apple MacPro3", {
++	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
++	  DMI_MATCH(DMI_PRODUCT_NAME, "MacPro3") },
++		&applesmc_dmi_data[16]},
+ 	{ applesmc_dmi_match, "Apple MacPro", {
+ 	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+ 	  DMI_MATCH(DMI_PRODUCT_NAME, "MacPro") },

commit 292cf4a8a989cb564a6a5f0ba7a66e08a095afa1
+Author: Valdis Kletnieks 
+Date:   Wed Oct 15 22:04:35 2008 -0700
+
+    tpm: work around bug in Broadcom BCM0102 chipset
+    
+    Patch tpm-correct-tpm-timeouts-to-jiffies-conversion reveals a bug in the
+    Broadcom BCM0102 TPM chipset used in the Dell Latitude D820 - although
+    most of the timeouts are returned in usecs as per the spec, one is
+    apparently returned in msecs, which results in a too-small value leading
+    to a timeout when the code treats it as usecs.  To prevent a regression,
+    we check for the known too-short value and adjust it to a value that makes
+    things work.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Cc: Marcin Obara 
+    Cc: Marcel Selhorst 
+    Cc: Kylene Jo Hall 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
+index 6b5a0e0127a7..aa899cec6b3f 100644
+--- a/drivers/char/tpm/tpm.c
++++ b/drivers/char/tpm/tpm.c
+@@ -557,6 +557,13 @@ void tpm_get_timeouts(struct tpm_chip *chip)
+ 	    usecs_to_jiffies(be32_to_cpu
+ 			     (*((__be32 *) (data +
+ 					    TPM_GET_CAP_RET_UINT32_1_IDX))));
++	/* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above
++	 * value wrong and apparently reports msecs rather than usecs. So we
++	 * fix up the resulting too-small TPM_SHORT value to make things work.
++	 */
++	if (chip->vendor.duration[TPM_SHORT] < (HZ/100))
++		chip->vendor.duration[TPM_SHORT] = HZ;
++
+ 	chip->vendor.duration[TPM_MEDIUM] =
+ 	    usecs_to_jiffies(be32_to_cpu
+ 			     (*((__be32 *) (data +

commit 243f40cecb292cbb2333749614cf54302fc9cdc0
+Author: Valdis Kletnieks 
+Date:   Fri Dec 28 21:22:48 2007 -0500
+
+    kbuild: document 'make prepare' in 'make help'
+    
+    The output of 'make help' covers a lot of options, but doesn't include
+    a listing for 'make prepare'.  Here's a one-liner to fix that...
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Sam Ravnborg 
+
+diff --git a/Makefile b/Makefile
+index 698dfc6ba65c..6847464402aa 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1181,6 +1181,7 @@ help:
+ 	@echo  '  dir/            - Build all files in dir and below'
+ 	@echo  '  dir/file.[ois]  - Build specified target only'
+ 	@echo  '  dir/file.ko     - Build module including final link'
++	@echo  '  prepare         - Set up for building external modules'
+ 	@echo  '  tags/TAGS	  - Generate tags file for editors'
+ 	@echo  '  cscope	  - Generate cscope index'
+ 	@echo  '  kernelrelease	  - Output the release version string'

commit 319e799abb89d9215a203e32c2cad51115d302f4
+Author: Valdis Kletnieks 
+Date:   Wed Dec 6 20:37:43 2006 -0800
+
+    [PATCH] ver_linux additions
+    
+    scripts/ver_linux needed some minor clean-ups, as follows:
+    1) Add reporting of actual oprofile release
+    2) Add reporting of actual wireless-tools release
+    3) Add reporting of actual pcmciautils release
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/scripts/ver_linux b/scripts/ver_linux
+index 84999f69773d..72876dfadc8a 100755
+--- a/scripts/ver_linux
++++ b/scripts/ver_linux
+@@ -48,6 +48,8 @@ fsck.reiser4 -V 2>&1 | grep ^fsck.reiser4 | awk \
+ xfs_db -V 2>&1 | grep version | awk \
+ 'NR==1{print "xfsprogs              ", $3}'
+ 
++pccardctl -V 2>&1| grep pcmciautils | awk '{print "pcmciautils           ", $2}'
++
+ cardmgr -V 2>&1| grep version | awk \
+ 'NR==1{print "pcmcia-cs             ", $3}'
+ 
+@@ -87,10 +89,16 @@ loadkeys -h 2>&1 | awk \
+ loadkeys -V 2>&1 | awk \
+ '(NR==1 && ($2 ~ /console-tools/)) {print "Console-tools         ", $3}'
+ 
++oprofiled --version 2>&1 | awk \
++'(NR==1 && ($2 == "oprofile")) {print "oprofile              ", $3}'
++
+ expr --v 2>&1 | awk 'NR==1{print "Sh-utils              ", $NF}'
+ 
+ udevinfo -V 2>&1 | grep version | awk '{print "udev                  ", $3}'
+ 
++iwconfig --version 2>&1 | awk \
++'(NR==1 && ($3 == "version")) {print "wireless-tools        ",$4}'
++
+ if [ -e /proc/modules ]; then
+     X=`cat /proc/modules | sed -e "s/ .*$//"`
+     echo "Modules Loaded         "$X

commit 73af994c7d58dd513922dc9d5cd76b124ec02b1b
+Author: Valdis Kletnieks 
+Date:   Wed Apr 19 09:23:09 2006 +0200
+
+    [PATCH] Document online io scheduler switching
+    
+    We added the ability to change a block device's IO elevator scheduler both
+    at kernel boot and on-the-fly, but we only documented the elevator= boot
+    parameter.  Add a quick how-to on doing it on the fly.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Jens Axboe 
+
+diff --git a/Documentation/block/switching-sched.txt b/Documentation/block/switching-sched.txt
+new file mode 100644
+index 000000000000..5fa130a67531
+--- /dev/null
++++ b/Documentation/block/switching-sched.txt
+@@ -0,0 +1,22 @@
++As of the Linux 2.6.10 kernel, it is now possible to change the
++IO scheduler for a given block device on the fly (thus making it possible,
++for instance, to set the CFQ scheduler for the system default, but
++set a specific device to use the anticipatory or noop schedulers - which
++can improve that device's throughput).
++
++To set a specific scheduler, simply do this:
++
++echo SCHEDNAME > /sys/block/DEV/queue/scheduler
++
++where SCHEDNAME is the name of a defined IO scheduler, and DEV is the
++device name (hda, hdb, sga, or whatever you happen to have).
++
++The list of defined schedulers can be found by simply doing
++a "cat /sys/block/DEV/queue/scheduler" - the list of valid names
++will be displayed, with the currently selected scheduler in brackets:
++
++# cat /sys/block/hda/queue/scheduler
++noop anticipatory deadline [cfq]
++# echo anticipatory > /sys/block/hda/queue/scheduler
++# cat /sys/block/hda/queue/scheduler
++noop [anticipatory] deadline cfq

commit 4f95af5bb546a9e7f46ed10f5e0dbe1e42a77884
+Author: Valdis Kletnieks 
+Date:   Thu Jan 19 02:07:47 2006 -0500
+
+    [PATCH] orinoco_cs: tweak Vcc debugging messages
+    
+    The current orinoco_cs.c can issue the exact same error message for
+    2 different tests that can fail.  Alter them so we can tell which
+    one of the two failed.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Signed-off-by: John W. Linville 
+
+diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
+index b664708481cc..3c128b692bce 100644
+--- a/drivers/net/wireless/orinoco_cs.c
++++ b/drivers/net/wireless/orinoco_cs.c
+@@ -261,13 +261,13 @@ orinoco_cs_config(dev_link_t *link)
+ 		/* Note that the CIS values need to be rescaled */
+ 		if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+ 			if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
+-				DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n",  conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
++				DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, cfg CIS = %d)\n",  conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
+ 				if (!ignore_cis_vcc)
+ 					goto next_entry;
+ 			}
+ 		} else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
+ 			if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) {
+-				DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n",  conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000);
++				DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, dflt CIS = %d)\n",  conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000);
+ 				if(!ignore_cis_vcc)
+ 					goto next_entry;
+ 			}

commit 3135806358e8d3d8ac61a13f58f148d0a98a7b9b
+Author: Valdis Kletnieks 
+Date:   Sat Jan 14 13:21:10 2006 -0800
+
+    [PATCH] quota: make useless quota error message informative
+    
+    fs/quota_v2.c can, under some conditions, issue a kernel message that says,
+    in totality, 'failed read'.  This patch does the following:
+    
+    1) Gives a hint who issued the error message, so people reading the logs
+       don't have to go grepping the entire kernel tree (with 11 false
+       positives).
+    
+    2) Say what amount of data we expected, and actually got.
+    
+    Signed-off-by: Valdis Kletnieks 
+    Cc: Jan Kara 
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/quota_v2.c b/fs/quota_v2.c
+index 7afcbb1b9376..a4ef91bb4f3b 100644
+--- a/fs/quota_v2.c
++++ b/fs/quota_v2.c
+@@ -35,7 +35,8 @@ static int v2_check_quota_file(struct super_block *sb, int type)
+  
+ 	size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0);
+ 	if (size != sizeof(struct v2_disk_dqheader)) {
+-		printk("failed read\n");
++		printk("quota_v2: failed read expected=%d got=%d\n",
++			sizeof(struct v2_disk_dqheader), size);
+ 		return 0;
+ 	}
+ 	if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||

commit fc9c9ab22d5650977c417ef2032d02f455011b23
+Author: Bharath Ramesh 
+Date:   Sat Apr 16 15:25:41 2005 -0700
+
+    [PATCH] AYSNC IO using singals other than SIGIO
+    
+    A question on sigwaitinfo based IO mechanism in multithreaded applications.
+    
+    I am trying to use RT signals to notify me of IO events using RT signals
+    instead of SIGIO in a multithreaded applications.  I noticed that there was
+    some discussion on lkml during november 1999 with the subject of the
+    discussion as "Signal driven IO".  In the thread I noticed that RT signals
+    were being delivered to the worker thread.  I am running 2.6.10 kernel and
+    I am trying to use the very same mechanism and I find that only SIGIO being
+    propogated to the worker threads and RT signals only being propogated to
+    the main thread and not the worker threads where I actually want them to be
+    propogated too.  On further inspection I found that the following patch
+    which I have attached solves the problem.
+    
+    I am not sure if this is a bug or feature in the kernel.
+    
+    
+    Roland McGrath  said:
+    
+    This relates only to fcntl F_SETSIG, which is a Linux extension.  So there is
+    no POSIX issue.  When changing various things like the normal SIGIO signalling
+    to do group signals, I was concerned strictly with the POSIX semantics and
+    generally avoided touching things in the domain of Linux inventions.  That's
+    why I didn't change this when I changed the call right next to it.  There is
+    no reason I can see that F_SETSIG-requested signals shouldn't use a group
+    signal like normal SIGIO does.  I'm happy to ACK this patch, there is nothing
+    wrong with its change to the semantics in my book.  But neither POSIX nor I
+    care a whit what F_SETSIG does.
+    
+    Signed-off-by: Andrew Morton 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/fs/fcntl.c b/fs/fcntl.c
+index c1708066bf55..3e7ab16ed154 100644
+--- a/fs/fcntl.c
++++ b/fs/fcntl.c
+@@ -437,7 +437,7 @@ static void send_sigio_to_task(struct task_struct *p,
+ 			else
+ 				si.si_band = band_table[reason - POLL_IN];
+ 			si.si_fd    = fd;
+-			if (!send_sig_info(fown->signum, &si, p))
++			if (!send_group_sig_info(fown->signum, &si, p))
+ 				break;
+ 		/* fall-through: fall back on the old plain SIGIO signal */
+ 		case 0:

commit c09b42404d29c8a9266f8186632330dc8474bf2e
+Author: Matt Tolentino 
+Date:   Tue Jan 17 07:03:44 2006 +0100
+
+    [PATCH] x86_64: add __meminit for memory hotplug
+    
+    Add __meminit to the __init lineup to ensure functions default
+    to __init when memory hotplug is not enabled.  Replace __devinit
+    with __meminit on functions that were changed when the memory
+    hotplug code was introduced.
+    
+    Signed-off-by: Matt Tolentino 
+    Signed-off-by: Andi Kleen 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
+index 7df494b51a5b..2700f01994ba 100644
+--- a/arch/i386/mm/init.c
++++ b/arch/i386/mm/init.c
+@@ -268,7 +268,7 @@ static void __init permanent_kmaps_init(pgd_t *pgd_base)
+ 	pkmap_page_table = pte;	
+ }
+ 
+-static void __devinit free_new_highpage(struct page *page)
++static void __meminit free_new_highpage(struct page *page)
+ {
+ 	set_page_count(page, 1);
+ 	__free_page(page);
+diff --git a/include/linux/init.h b/include/linux/init.h
+index 59008c3826cf..ff8d8b8632f4 100644
+--- a/include/linux/init.h
++++ b/include/linux/init.h
+@@ -241,6 +241,18 @@ void __init parse_early_param(void);
+ #define __cpuexitdata	__exitdata
+ #endif
+ 
++#ifdef CONFIG_MEMORY_HOTPLUG
++#define __meminit
++#define __meminitdata
++#define __memexit
++#define __memexitdata
++#else
++#define __meminit	__init
++#define __meminitdata __initdata
++#define __memexit __exit
++#define __memexitdata	__exitdata
++#endif
++
+ /* Functions marked as __devexit may be discarded at kernel link time, depending
+    on config options.  Newer versions of binutils detect references from
+    retained sections to discarded sections and flag an error.  Pointers to
+diff --git a/mm/page_alloc.c b/mm/page_alloc.c
+index 8c960b469593..c2e29743a8d1 100644
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -1735,7 +1735,7 @@ static void __init calculate_zone_totalpages(struct pglist_data *pgdat,
+  * up by free_all_bootmem() once the early boot process is
+  * done. Non-atomic initialization, single-pass.
+  */
+-void __devinit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
++void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
+ 		unsigned long start_pfn)
+ {
+ 	struct page *page;
+@@ -1788,7 +1788,7 @@ void zonetable_add(struct zone *zone, int nid, int zid, unsigned long pfn,
+ 	memmap_init_zone((size), (nid), (zone), (start_pfn))
+ #endif
+ 
+-static int __devinit zone_batchsize(struct zone *zone)
++static int __meminit zone_batchsize(struct zone *zone)
+ {
+ 	int batch;
+ 
+@@ -1882,7 +1882,7 @@ static struct per_cpu_pageset
+  * Dynamically allocate memory for the
+  * per cpu pageset array in struct zone.
+  */
+-static int __devinit process_zones(int cpu)
++static int __meminit process_zones(int cpu)
+ {
+ 	struct zone *zone, *dzone;
+ 
+@@ -1923,7 +1923,7 @@ static inline void free_zone_pagesets(int cpu)
+ 	}
+ }
+ 
+-static int __devinit pageset_cpuup_callback(struct notifier_block *nfb,
++static int __meminit pageset_cpuup_callback(struct notifier_block *nfb,
+ 		unsigned long action,
+ 		void *hcpu)
+ {
+@@ -1963,7 +1963,7 @@ void __init setup_per_cpu_pageset(void)
+ 
+ #endif
+ 
+-static __devinit
++static __meminit
+ void zone_wait_table_init(struct zone *zone, unsigned long zone_size_pages)
+ {
+ 	int i;
+@@ -1983,7 +1983,7 @@ void zone_wait_table_init(struct zone *zone, unsigned long zone_size_pages)
+ 		init_waitqueue_head(zone->wait_table + i);
+ }
+ 
+-static __devinit void zone_pcp_init(struct zone *zone)
++static __meminit void zone_pcp_init(struct zone *zone)
+ {
+ 	int cpu;
+ 	unsigned long batch = zone_batchsize(zone);
+@@ -2001,7 +2001,7 @@ static __devinit void zone_pcp_init(struct zone *zone)
+ 		zone->name, zone->present_pages, batch);
+ }
+ 
+-static __devinit void init_currently_empty_zone(struct zone *zone,
++static __meminit void init_currently_empty_zone(struct zone *zone,
+ 		unsigned long zone_start_pfn, unsigned long size)
+ {
+ 	struct pglist_data *pgdat = zone->zone_pgdat;

commit 44df75e629106efcada087cead6c3f33ed6bcc60
+Author: Matt Tolentino 
+Date:   Tue Jan 17 07:03:41 2006 +0100
+
+    [PATCH] x86_64: add x86-64 support for memory hot-add
+    
+    Add x86-64 specific memory hot-add functions, Kconfig options,
+    and runtime kernel page table update functions to make
+    hot-add usable on x86-64 machines.  Also, fixup the nefarious
+    conditional locking and exports pointed out by Andi.
+    
+    Tested on Intel and IBM x86-64 memory hot-add capable systems.
+    
+    Signed-off-by: Matt Tolentino 
+    Signed-off-by: Andi Kleen 
+    Signed-off-by: Linus Torvalds 
+
+diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
+index 787feff0e8a5..2f9deca31cc9 100644
+--- a/arch/x86_64/Kconfig
++++ b/arch/x86_64/Kconfig
+@@ -305,7 +305,11 @@ config ARCH_DISCONTIGMEM_DEFAULT
+ 
+ config ARCH_SPARSEMEM_ENABLE
+ 	def_bool y
+-	depends on NUMA
++	depends on (NUMA || EXPERIMENTAL)
++
++config ARCH_MEMORY_PROBE
++	def_bool y
++	depends on MEMORY_HOTPLUG
+ 
+ config ARCH_FLATMEM_ENABLE
+ 	def_bool y
+@@ -315,6 +319,7 @@ source "mm/Kconfig"
+ 
+ config HAVE_ARCH_EARLY_PFN_TO_NID
+ 	def_bool y
++	depends on NUMA
+ 
+ config NR_CPUS
+ 	int "Maximum number of CPUs (2-256)"
+diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
+index 307d1ac0ef33..7af1742aa958 100644
+--- a/arch/x86_64/mm/init.c
++++ b/arch/x86_64/mm/init.c
+@@ -24,6 +24,8 @@
+ #include 
+ #include 
+ #include 
++#include 
++#include 
+ 
+ #include 
+ #include 
+@@ -180,13 +182,19 @@ static  struct temp_map {
+ 	{}
+ }; 
+ 
+-static __init void *alloc_low_page(int *index, unsigned long *phys) 
++static __meminit void *alloc_low_page(int *index, unsigned long *phys)
+ { 
+ 	struct temp_map *ti;
+ 	int i; 
+ 	unsigned long pfn = table_end++, paddr; 
+ 	void *adr;
+ 
++	if (after_bootmem) {
++		adr = (void *)get_zeroed_page(GFP_ATOMIC);
++		*phys = __pa(adr);
++		return adr;
++	}
++
+ 	if (pfn >= end_pfn) 
+ 		panic("alloc_low_page: ran out of memory"); 
+ 	for (i = 0; temp_mappings[i].allocated; i++) {
+@@ -199,55 +207,86 @@ static __init void *alloc_low_page(int *index, unsigned long *phys)
+ 	ti->allocated = 1; 
+ 	__flush_tlb(); 	       
+ 	adr = ti->address + ((pfn << PAGE_SHIFT) & ~PMD_MASK); 
++	memset(adr, 0, PAGE_SIZE);
+ 	*index = i; 
+ 	*phys  = pfn * PAGE_SIZE;  
+ 	return adr; 
+ } 
+ 
+-static __init void unmap_low_page(int i)
++static __meminit void unmap_low_page(int i)
+ { 
+-	struct temp_map *ti = &temp_mappings[i];
++	struct temp_map *ti;
++
++	if (after_bootmem)
++		return;
++
++	ti = &temp_mappings[i];
+ 	set_pmd(ti->pmd, __pmd(0));
+ 	ti->allocated = 0; 
+ } 
+ 
+-static void __init phys_pud_init(pud_t *pud, unsigned long address, unsigned long end)
++static void __meminit
++phys_pmd_init(pmd_t *pmd, unsigned long address, unsigned long end)
++{
++	int i;
++
++	for (i = 0; i < PTRS_PER_PMD; pmd++, i++, address += PMD_SIZE) {
++		unsigned long entry;
++
++		if (address > end) {
++			for (; i < PTRS_PER_PMD; i++, pmd++)
++				set_pmd(pmd, __pmd(0));
++			break;
++		}
++		entry = _PAGE_NX|_PAGE_PSE|_KERNPG_TABLE|_PAGE_GLOBAL|address;
++		entry &= __supported_pte_mask;
++		set_pmd(pmd, __pmd(entry));
++	}
++}
++
++static void __meminit
++phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end)
++{
++	pmd_t *pmd = pmd_offset(pud, (unsigned long)__va(address));
++
++	if (pmd_none(*pmd)) {
++		spin_lock(&init_mm.page_table_lock);
++		phys_pmd_init(pmd, address, end);
++		spin_unlock(&init_mm.page_table_lock);
++		__flush_tlb_all();
++	}
++}
++
++static void __meminit phys_pud_init(pud_t *pud, unsigned long address, unsigned long end)
+ { 
+-	long i, j; 
++	long i = pud_index(address);
+ 
+-	i = pud_index(address);
+ 	pud = pud + i;
++
++	if (after_bootmem && pud_val(*pud)) {
++		phys_pmd_update(pud, address, end);
++		return;
++	}
++
+ 	for (; i < PTRS_PER_PUD; pud++, i++) {
+ 		int map; 
+ 		unsigned long paddr, pmd_phys;
+ 		pmd_t *pmd;
+ 
+-		paddr = address + i*PUD_SIZE;
+-		if (paddr >= end) { 
+-			for (; i < PTRS_PER_PUD; i++, pud++) 
+-				set_pud(pud, __pud(0)); 
++		paddr = (address & PGDIR_MASK) + i*PUD_SIZE;
++		if (paddr >= end)
+ 			break;
+-		} 
+ 
+-		if (!e820_mapped(paddr, paddr+PUD_SIZE, 0)) { 
++		if (!after_bootmem && !e820_mapped(paddr, paddr+PUD_SIZE, 0)) {
+ 			set_pud(pud, __pud(0)); 
+ 			continue;
+ 		} 
+ 
+ 		pmd = alloc_low_page(&map, &pmd_phys);
++		spin_lock(&init_mm.page_table_lock);
+ 		set_pud(pud, __pud(pmd_phys | _KERNPG_TABLE));
+-		for (j = 0; j < PTRS_PER_PMD; pmd++, j++, paddr += PMD_SIZE) {
+-			unsigned long pe;
+-
+-			if (paddr >= end) { 
+-				for (; j < PTRS_PER_PMD; j++, pmd++)
+-					set_pmd(pmd,  __pmd(0)); 
+-				break;
+-		}
+-			pe = _PAGE_NX|_PAGE_PSE | _KERNPG_TABLE | _PAGE_GLOBAL | paddr;
+-			pe &= __supported_pte_mask;
+-			set_pmd(pmd, __pmd(pe));
+-		}
++		phys_pmd_init(pmd, paddr, end);
++		spin_unlock(&init_mm.page_table_lock);
+ 		unmap_low_page(map);
+ 	}
+ 	__flush_tlb();
+@@ -272,12 +311,15 @@ static void __init find_early_table_space(unsigned long end)
+ 
+ 	table_start >>= PAGE_SHIFT;
+ 	table_end = table_start;
++
++	early_printk("kernel direct mapping tables up to %lx @ %lx-%lx\n",
++		end, table_start << PAGE_SHIFT, table_end << PAGE_SHIFT);
+ }
+ 
+ /* Setup the direct mapping of the physical memory at PAGE_OFFSET.
+    This runs before bootmem is initialized and gets pages directly from the 
+    physical memory. To access them they are temporarily mapped. */
+-void __init init_memory_mapping(unsigned long start, unsigned long end)
++void __meminit init_memory_mapping(unsigned long start, unsigned long end)
+ { 
+ 	unsigned long next; 
+ 
+@@ -289,7 +331,8 @@ void __init init_memory_mapping(unsigned long start, unsigned long end)
+ 	 * mapped.  Unfortunately this is done currently before the nodes are 
+ 	 * discovered.
+ 	 */
+-	find_early_table_space(end);
++	if (!after_bootmem)
++		find_early_table_space(end);
+ 
+ 	start = (unsigned long)__va(start);
+ 	end = (unsigned long)__va(end);
+@@ -297,20 +340,26 @@ void __init init_memory_mapping(unsigned long start, unsigned long end)
+ 	for (; start < end; start = next) {
+ 		int map;
+ 		unsigned long pud_phys; 
+-		pud_t *pud = alloc_low_page(&map, &pud_phys);
++		pgd_t *pgd = pgd_offset_k(start);
++		pud_t *pud;
++
++		if (after_bootmem)
++			pud = pud_offset_k(pgd, __PAGE_OFFSET);
++		else
++			pud = alloc_low_page(&map, &pud_phys);
++
+ 		next = start + PGDIR_SIZE;
+ 		if (next > end) 
+ 			next = end; 
+ 		phys_pud_init(pud, __pa(start), __pa(next));
+-		set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys));
++		if (!after_bootmem)
++			set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys));
+ 		unmap_low_page(map);   
+ 	} 
+ 
+-	asm volatile("movq %%cr4,%0" : "=r" (mmu_cr4_features));
++	if (!after_bootmem)
++		asm volatile("movq %%cr4,%0" : "=r" (mmu_cr4_features));
+ 	__flush_tlb_all();
+-	early_printk("kernel direct mapping tables upto %lx @ %lx-%lx\n", end, 
+-	       table_start<> PAGE_SHIFT, holes);
+@@ -425,6 +477,50 @@ void __init clear_kernel_mapping(unsigned long address, unsigned long size)
+ 	__flush_tlb_all();
+ } 
+ 
++/*
++ * Memory hotplug specific functions
++ * These are only for non-NUMA machines right now.
++ */
++#ifdef CONFIG_MEMORY_HOTPLUG
++
++void online_page(struct page *page)
++{
++	ClearPageReserved(page);
++	set_page_count(page, 1);
++	__free_page(page);
++	totalram_pages++;
++	num_physpages++;
++}
++
++int add_memory(u64 start, u64 size)
++{
++	struct pglist_data *pgdat = NODE_DATA(0);
++	struct zone *zone = pgdat->node_zones + MAX_NR_ZONES-2;
++	unsigned long start_pfn = start >> PAGE_SHIFT;
++	unsigned long nr_pages = size >> PAGE_SHIFT;
++	int ret;
++
++	ret = __add_pages(zone, start_pfn, nr_pages);
++	if (ret)
++		goto error;
++
++	init_memory_mapping(start, (start + size -1));
++
++	return ret;
++error:
++	printk("%s: Problem encountered in __add_pages!\n", __func__);
++	return ret;
++}
++EXPORT_SYMBOL_GPL(add_memory);
++
++int remove_memory(u64 start, u64 size)
++{
++	return -EINVAL;
++}
++EXPORT_SYMBOL_GPL(remove_memory);
++
++#endif
++
+ static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, kcore_modules,
+ 			 kcore_vsyscall;
+ 

\ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..3c2dac3 --- /dev/null +++ b/index.html @@ -0,0 +1,126 @@ + + + + + + + Kernel Contribute Rank + + + + + + + + + + + + +
+ + + + + + + \ No newline at end of file diff --git a/result.json b/result.json new file mode 100644 index 0000000..d650289 --- /dev/null +++ b/result.json @@ -0,0 +1,3232 @@ +{ + "meta": { + "update": "2024-02-19T01:51:27.701753", + "repo": "Linux Mainline", + "branch": "master", + "commit": "fbafc3e621c3f4ded43720fdb1d6ce1728ec664e" + }, + "data": [ + { + "name": "Massachusetts Institute of Technology", + "domains": [ + "mit.edu", + "csail.mit.edu", + "alum.mit.edu", + "ll.mit.edu" + ], + "university": { + "web_pages": [ + "http://web.mit.edu/" + ], + "name": "Massachusetts Institute of Technology", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "mit.edu" + ], + "country": "United States" + }, + "count": 1532, + "id": 1, + "rank": 1 + }, + { + "name": "Harvard University", + "domains": [ + "rowland.harvard.edu" + ], + "university": { + "web_pages": [ + "http://www.harvard.edu/" + ], + "name": "Harvard University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "harvard.edu" + ], + "country": "United States" + }, + "count": 1388, + "id": 2, + "rank": 2 + }, + { + "name": "University of Virginia, Charlottesville", + "domains": [ + "virginia.edu", + "viridian.itc.virginia.edu" + ], + "university": { + "web_pages": [ + "http://www.virginia.edu/" + ], + "name": "University of Virginia, Charlottesville", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "virginia.edu" + ], + "country": "United States" + }, + "count": 826, + "id": 3, + "rank": 3 + }, + { + "name": "University of Michigan - Ann Arbor", + "domains": [ + "umich.edu", + "citi.umich.edu", + "engin.umich.edu", + "snoopy.citi.umich.edu" + ], + "university": { + "web_pages": [ + "http://www.umich.edu/" + ], + "name": "University of Michigan - Ann Arbor", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "umich.edu" + ], + "country": "United States" + }, + "count": 562, + "id": 4, + "rank": 4 + }, + { + "name": "University of South Carolina", + "domains": [ + "cs.wisc.edu", + "ssec.wisc.edu", + "osc.edu", + "psc.edu" + ], + "university": { + "web_pages": [ + "http://www.sc.edu/" + ], + "name": "University of South Carolina", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "sc.edu" + ], + "country": "United States" + }, + "count": 475, + "id": 5, + "rank": 5 + }, + { + "name": "Zhejiang University", + "domains": [ + "zju.edu.cn" + ], + "university": { + "web_pages": [ + "http://www.zju.edu.cn/" + ], + "name": "Zhejiang University", + "alpha_two_code": "CN", + "state-province": null, + "domains": [ + "zju.edu.cn" + ], + "country": "China" + }, + "count": 293, + "id": 6, + "rank": 6 + }, + { + "name": "University of Minnesota", + "domains": [ + "umn.edu", + "cs.umn.edu" + ], + "university": { + "web_pages": [ + "http://www.umn.edu/" + ], + "name": "University of Minnesota", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "umn.edu" + ], + "country": "United States" + }, + "count": 291, + "id": 7, + "rank": 7 + }, + { + "name": "University of New South Wales", + "domains": [ + "cse.unsw.edu.au", + "gelato.unsw.edu.au" + ], + "university": { + "web_pages": [ + "http://www.unsw.edu.au/" + ], + "name": "University of New South Wales", + "alpha_two_code": "AU", + "state-province": "New South Wales", + "domains": [ + "unsw.edu.au" + ], + "country": "Australia" + }, + "count": 178, + "id": 8, + "rank": 8 + }, + { + "name": "Virginia Tech", + "domains": [ + "vt.edu", + "cs.vt.edu" + ], + "university": { + "web_pages": [ + "https://www.vt.edu/" + ], + "name": "Virginia Tech", + "alpha_two_code": "US", + "state-province": "Virginia", + "domains": [ + "vt.edu" + ], + "country": "United States" + }, + "count": 114, + "id": 9, + "rank": 9 + }, + { + "name": "Peking University", + "domains": [ + "pku.edu.cn", + "mprc.pku.edu.cn", + "ss.pku.edu.cn" + ], + "university": { + "web_pages": [ + "http://www.pku.edu.cn/" + ], + "name": "Peking University", + "alpha_two_code": "CN", + "state-province": null, + "domains": [ + "pku.edu.cn" + ], + "country": "China" + }, + "count": 99, + "id": 10, + "rank": 10 + }, + { + "name": "Unknown (fsl.cs.sunysb.edu)", + "domains": [ + "fsl.cs.sunysb.edu" + ], + "university": null, + "count": 81, + "id": 11, + "rank": 11 + }, + { + "name": "University of Science and Technology of China", + "domains": [ + "mail.ustc.edu.cn" + ], + "university": { + "web_pages": [ + "http://www.ustc.edu.cn/" + ], + "name": "University of Science and Technology of China", + "alpha_two_code": "CN", + "state-province": null, + "domains": [ + "ustc.edu.cn" + ], + "country": "China" + }, + "count": 80, + "id": 12, + "rank": 12 + }, + { + "name": "University of Washington", + "domains": [ + "uw.edu", + "cs.washington.edu", + "u.washington.edu" + ], + "university": { + "web_pages": [ + "http://www.washington.edu/" + ], + "name": "University of Washington", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "uw.edu", + "washington.edu" + ], + "country": "United States" + }, + "count": 75, + "id": 13, + "rank": 13 + }, + { + "name": "Carnegie Mellon University", + "domains": [ + "cs.cmu.edu", + "cmu.edu", + "andrew.cmu.edu", + "rec.ri.cmu.edu", + "qatar.cmu.edu" + ], + "university": { + "web_pages": [ + "http://www.cmu.edu/" + ], + "name": "Carnegie Mellon University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "cmu.edu" + ], + "country": "United States" + }, + "count": 73, + "id": 14, + "rank": 14 + }, + { + "name": "Fudan University", + "domains": [ + "fudan.edu.cn" + ], + "university": { + "web_pages": [ + "http://www.fudan.edu.cn/" + ], + "name": "Fudan University", + "alpha_two_code": "CN", + "state-province": null, + "domains": [ + "fudan.edu.cn" + ], + "country": "China" + }, + "count": 69, + "id": 15, + "rank": 15 + }, + { + "name": "California Institute of Technology", + "domains": [ + "ovro.caltech.edu", + "its.caltech.edu" + ], + "university": { + "web_pages": [ + "http://www.caltech.edu/" + ], + "name": "California Institute of Technology", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "caltech.edu" + ], + "country": "United States" + }, + "count": 69, + "id": 16, + "rank": 15 + }, + { + "name": "University of Queensland", + "domains": [ + "itee.uq.edu.au" + ], + "university": { + "web_pages": [ + "http://www.uq.edu.au/" + ], + "name": "University of Queensland", + "alpha_two_code": "AU", + "state-province": "Queensland", + "domains": [ + "uq.edu.au" + ], + "country": "Australia" + }, + "count": 67, + "id": 17, + "rank": 17 + }, + { + "name": "Huazhong University of Science and Technology", + "domains": [ + "hust.edu.cn" + ], + "university": { + "web_pages": [ + "http://www.hust.edu.cn/" + ], + "name": "Huazhong University of Science and Technology", + "alpha_two_code": "CN", + "state-province": null, + "domains": [ + "hust.edu.cn" + ], + "country": "China" + }, + "count": 66, + "id": 18, + "rank": 18 + }, + { + "name": "University of Georgia", + "domains": [ + "cs.uga.edu" + ], + "university": { + "web_pages": [ + "http://www.uga.edu/" + ], + "name": "University of Georgia", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "uga.edu" + ], + "country": "United States" + }, + "count": 57, + "id": 19, + "rank": 19 + }, + { + "name": "Unknown (cs.sunysb.edu)", + "domains": [ + "cs.sunysb.edu" + ], + "university": null, + "count": 53, + "id": 20, + "rank": 20 + }, + { + "name": "Concordia University Wisconsin", + "domains": [ + "cuw.edu" + ], + "university": { + "web_pages": [ + "https://cuw.edu" + ], + "name": "Concordia University Wisconsin", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "cuw.edu" + ], + "country": "United States" + }, + "count": 41, + "id": 21, + "rank": 21 + }, + { + "name": "Shenzhen University", + "domains": [ + "email.szu.edu.cn" + ], + "university": { + "web_pages": [ + "http://www.szu.edu.cn/" + ], + "name": "Shenzhen University", + "alpha_two_code": "CN", + "state-province": null, + "domains": [ + "szu.edu.cn" + ], + "country": "China" + }, + "count": 32, + "id": 22, + "rank": 22 + }, + { + "name": "University of Maine System", + "domains": [ + "maine.edu" + ], + "university": { + "web_pages": [ + "http://www.maine.edu/" + ], + "name": "University of Maine System", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "maine.edu" + ], + "country": "United States" + }, + "count": 32, + "id": 23, + "rank": 22 + }, + { + "name": "Columbia University", + "domains": [ + "columbia.edu", + "cs.columbia.edu" + ], + "university": { + "web_pages": [ + "http://www.columbia.edu/" + ], + "name": "Columbia University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "columbia.edu" + ], + "country": "United States" + }, + "count": 29, + "id": 24, + "rank": 24 + }, + { + "name": "University of Pennsylvania", + "domains": [ + "seas.upenn.edu", + "physics.upenn.edu" + ], + "university": { + "web_pages": [ + "http://www.upenn.edu/" + ], + "name": "University of Pennsylvania", + "alpha_two_code": "US", + "state-province": "Pennsylvania", + "domains": [ + "upenn.edu", + "seas.upenn.edu" + ], + "country": "United States" + }, + "count": 26, + "id": 25, + "rank": 25 + }, + { + "name": "University of Adelaide", + "domains": [ + "physics.adelaide.edu.au" + ], + "university": { + "web_pages": [ + "http://www.adelaide.edu.au/" + ], + "name": "University of Adelaide", + "alpha_two_code": "AU", + "state-province": "South Australia", + "domains": [ + "adelaide.edu.au" + ], + "country": "Australia" + }, + "count": 26, + "id": 26, + "rank": 25 + }, + { + "name": "Georgia Institute of Technology", + "domains": [ + "gatech.edu", + "gtri.gatech.edu" + ], + "university": { + "web_pages": [ + "http://www.gatech.edu/" + ], + "name": "Georgia Institute of Technology", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "gatech.edu" + ], + "country": "United States" + }, + "count": 25, + "id": 27, + "rank": 27 + }, + { + "name": "University of Illinois, Urbana-Champaign", + "domains": [ + "illinois.edu", + "uiuc.edu" + ], + "university": { + "web_pages": [ + "https://illinois.edu/" + ], + "name": "University of Illinois, Urbana-Champaign", + "alpha_two_code": "US", + "state-province": "Illinois", + "domains": [ + "uiuc.edu", + "illinois.edu" + ], + "country": "United States" + }, + "count": 23, + "id": 28, + "rank": 28 + }, + { + "name": "Unknown (shanghaitech.edu.cn)", + "domains": [ + "shanghaitech.edu.cn" + ], + "university": null, + "count": 22, + "id": 29, + "rank": 29 + }, + { + "name": "Auburn University", + "domains": [ + "banach.math.auburn.edu", + "auburn.edu" + ], + "university": { + "web_pages": [ + "http://www.auburn.edu/" + ], + "name": "Auburn University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "auburn.edu" + ], + "country": "United States" + }, + "count": 22, + "id": 30, + "rank": 29 + }, + { + "name": "Indiana University", + "domains": [ + "iu.edu", + "umail.iu.edu" + ], + "university": { + "web_pages": [ + "http://www.iu.edu/" + ], + "name": "Indiana University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "iu.edu" + ], + "country": "United States" + }, + "count": 21, + "id": 31, + "rank": 31 + }, + { + "name": "University of California, Berkeley", + "domains": [ + "eecs.berkeley.edu", + "math.berkeley.edu", + "cs.berkeley.edu", + "berkeley.edu" + ], + "university": { + "web_pages": [ + "http://www.berkeley.edu/" + ], + "name": "University of California, Berkeley", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "berkeley.edu" + ], + "country": "United States" + }, + "count": 20, + "id": 32, + "rank": 32 + }, + { + "name": "University of California, Riverside", + "domains": [ + "ucr.edu" + ], + "university": { + "web_pages": [ + "http://www.ucr.edu/" + ], + "name": "University of California, Riverside", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "ucr.edu" + ], + "country": "United States" + }, + "count": 19, + "id": 33, + "rank": 33 + }, + { + "name": "Unknown (nitk.edu.in)", + "domains": [ + "nitk.edu.in" + ], + "university": null, + "count": 17, + "id": 34, + "rank": 34 + }, + { + "name": "Rochester Institute of Technology", + "domains": [ + "rit.edu" + ], + "university": { + "web_pages": [ + "http://www.rit.edu/" + ], + "name": "Rochester Institute of Technology", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "rit.edu" + ], + "country": "United States" + }, + "count": 17, + "id": 35, + "rank": 34 + }, + { + "name": "City College of San Francisco", + "domains": [ + "mail.ccsf.edu" + ], + "university": { + "web_pages": [ + "http://www.ccsf.edu" + ], + "name": "City College of San Francisco", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "ccsf.edu" + ], + "country": "United States" + }, + "count": 16, + "id": 36, + "rank": 36 + }, + { + "name": "Jimei University", + "domains": [ + "jmu.edu.cn" + ], + "university": { + "web_pages": [ + "http://www.jmu.edu.cn/" + ], + "name": "Jimei University", + "alpha_two_code": "CN", + "state-province": null, + "domains": [ + "jmu.edu.cn" + ], + "country": "China" + }, + "count": 15, + "id": 37, + "rank": 37 + }, + { + "name": "Shanghai Jiaotong University", + "domains": [ + "sjtu.edu.cn" + ], + "university": { + "web_pages": [ + "http://www.sjtu.edu.cn/" + ], + "name": "Shanghai Jiaotong University", + "alpha_two_code": "CN", + "state-province": null, + "domains": [ + "sjtu.edu.cn" + ], + "country": "China" + }, + "count": 15, + "id": 38, + "rank": 37 + }, + { + "name": "Rutgers University", + "domains": [ + "rutgers.edu", + "cs.rutgers.edu", + "winlab.rutgers.edu" + ], + "university": { + "web_pages": [ + "http://www.rutgers.edu/" + ], + "name": "Rutgers University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "rutgers.edu" + ], + "country": "United States" + }, + "count": 15, + "id": 39, + "rank": 37 + }, + { + "name": "Portland State University", + "domains": [ + "pdx.edu", + "cs.pdx.edu" + ], + "university": { + "web_pages": [ + "http://www.ee.pdx.edu/" + ], + "name": "Portland State University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "pdx.edu" + ], + "country": "United States" + }, + "count": 15, + "id": 40, + "rank": 37 + }, + { + "name": "Unknown (rosedu.org)", + "domains": [ + "rosedu.org" + ], + "university": null, + "count": 15, + "id": 41, + "rank": 37 + }, + { + "name": "Purdue University", + "domains": [ + "purdue.edu" + ], + "university": { + "web_pages": [ + "http://www.purdue.edu/" + ], + "name": "Purdue University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "purdue.edu" + ], + "country": "United States" + }, + "count": 13, + "id": 42, + "rank": 42 + }, + { + "name": "Unknown (ashoka.edu.in)", + "domains": [ + "ashoka.edu.in" + ], + "university": null, + "count": 13, + "id": 43, + "rank": 42 + }, + { + "name": "Stanford University", + "domains": [ + "cs.stanford.edu", + "stanford.edu", + "slac.stanford.edu" + ], + "university": { + "web_pages": [ + "http://www.stanford.edu/" + ], + "name": "Stanford University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "stanford.edu" + ], + "country": "United States" + }, + "count": 11, + "id": 44, + "rank": 44 + }, + { + "name": "Australian National University", + "domains": [ + "anu.edu.au" + ], + "university": { + "web_pages": [ + "http://www.anu.edu.au/" + ], + "name": "Australian National University", + "alpha_two_code": "AU", + "state-province": "Australian Capital Territory", + "domains": [ + "anu.edu.au" + ], + "country": "Australia" + }, + "count": 10, + "id": 45, + "rank": 45 + }, + { + "name": "Rensselaer Polytechnic Institute", + "domains": [ + "rpi.edu" + ], + "university": { + "web_pages": [ + "http://www.rpi.edu/" + ], + "name": "Rensselaer Polytechnic Institute", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "rpi.edu" + ], + "country": "United States" + }, + "count": 9, + "id": 46, + "rank": 46 + }, + { + "name": "University of Pittsburgh", + "domains": [ + "pitt.edu" + ], + "university": { + "web_pages": [ + "http://www.pitt.edu/" + ], + "name": "University of Pittsburgh", + "alpha_two_code": "US", + "state-province": "Pennsylvania", + "domains": [ + "pitt.edu" + ], + "country": "United States" + }, + "count": 8, + "id": 47, + "rank": 47 + }, + { + "name": "University of California, San Diego", + "domains": [ + "eng.ucsd.edu", + "ucsd.edu" + ], + "university": { + "web_pages": [ + "http://www.ucsd.edu/" + ], + "name": "University of California, San Diego", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "ucsd.edu" + ], + "country": "United States" + }, + "count": 7, + "id": 48, + "rank": 48 + }, + { + "name": "Warsaw University of Technology", + "domains": [ + "mion.elka.pw.edu.pl", + "elka.pw.edu.pl", + "ee.pw.edu.pl" + ], + "university": { + "web_pages": [ + "http://www.pw.edu.pl/" + ], + "name": "Warsaw University of Technology", + "alpha_two_code": "PL", + "state-province": null, + "domains": [ + "pw.edu.pl" + ], + "country": "Poland" + }, + "count": 7, + "id": 49, + "rank": 48 + }, + { + "name": "University of Tennessee, Knoxville", + "domains": [ + "eecs.utk.edu" + ], + "university": { + "web_pages": [ + "http://www.utk.edu/" + ], + "name": "University of Tennessee, Knoxville", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "utk.edu" + ], + "country": "United States" + }, + "count": 7, + "id": 50, + "rank": 48 + }, + { + "name": "Ohio University", + "domains": [ + "ohio.edu" + ], + "university": { + "web_pages": [ + "http://www.ohio.edu/" + ], + "name": "Ohio University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "ohio.edu" + ], + "country": "United States" + }, + "count": 7, + "id": 51, + "rank": 48 + }, + { + "name": "University of California, Santa Cruz", + "domains": [ + "ucsc.edu" + ], + "university": { + "web_pages": [ + "http://www.ucsc.edu/" + ], + "name": "University of California, Santa Cruz", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "ucsc.edu" + ], + "country": "United States" + }, + "count": 6, + "id": 52, + "rank": 52 + }, + { + "name": "Lanzhou University", + "domains": [ + "lzu.edu.cn" + ], + "university": { + "web_pages": [ + "http://www.lzu.edu.cn/" + ], + "name": "Lanzhou University", + "alpha_two_code": "CN", + "state-province": null, + "domains": [ + "lzu.edu.cn" + ], + "country": "China" + }, + "count": 6, + "id": 53, + "rank": 52 + }, + { + "name": "Clemson University", + "domains": [ + "clemson.edu", + "cs.clemson.edu" + ], + "university": { + "web_pages": [ + "http://www.clemson.edu/" + ], + "name": "Clemson University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "clemson.edu" + ], + "country": "United States" + }, + "count": 6, + "id": 54, + "rank": 52 + }, + { + "name": "Cornell University", + "domains": [ + "cornell.edu" + ], + "university": { + "web_pages": [ + "http://www.cornell.edu/" + ], + "name": "Cornell University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "cornell.edu" + ], + "country": "United States" + }, + "count": 6, + "id": 55, + "rank": 52 + }, + { + "name": "Universidad Polit\u00e9cnica de Cataluna", + "domains": [ + "ac.upc.edu" + ], + "university": { + "web_pages": [ + "http://www.upc.edu/" + ], + "name": "Universidad Polit\u00e9cnica de Cataluna", + "alpha_two_code": "ES", + "state-province": null, + "domains": [ + "upc.edu" + ], + "country": "Spain" + }, + "count": 6, + "id": 56, + "rank": 52 + }, + { + "name": "Oregon State University", + "domains": [ + "oregonstate.edu", + "flip.engr.oregonstate.edu" + ], + "university": { + "web_pages": [ + "http://www.oregonstate.edu/" + ], + "name": "Oregon State University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "oregonstate.edu" + ], + "country": "United States" + }, + "count": 5, + "id": 57, + "rank": 57 + }, + { + "name": "Renmin University of China", + "domains": [ + "ruc.edu.cn" + ], + "university": { + "web_pages": [ + "http://www.ruc.edu.cn/" + ], + "name": "Renmin University of China", + "alpha_two_code": "CN", + "state-province": null, + "domains": [ + "ruc.edu.cn" + ], + "country": "China" + }, + "count": 5, + "id": 58, + "rank": 57 + }, + { + "name": "Tsinghua University", + "domains": [ + "mails.tsinghua.edu.cn", + "tsinghua.edu.cn" + ], + "university": { + "web_pages": [ + "http://www.tsinghua.edu.cn/" + ], + "name": "Tsinghua University", + "alpha_two_code": "CN", + "state-province": null, + "domains": [ + "tsinghua.edu.cn" + ], + "country": "China" + }, + "count": 5, + "id": 59, + "rank": 57 + }, + { + "name": "PES University", + "domains": [ + "pesu.pes.edu" + ], + "university": { + "web_pages": [ + "http://www.pes.edu/" + ], + "name": "PES University", + "alpha_two_code": "IN", + "state-province": "Karnataka", + "domains": [ + "pes.edu" + ], + "country": "India" + }, + "count": 5, + "id": 60, + "rank": 57 + }, + { + "name": "Northeastern University", + "domains": [ + "northeastern.edu", + "ccs.neu.edu" + ], + "university": { + "web_pages": [ + "http://www.northeastern.edu/" + ], + "name": "Northeastern University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "neu.edu", + "northeastern.edu" + ], + "country": "United States" + }, + "count": 5, + "id": 61, + "rank": 57 + }, + { + "name": "University of Delaware", + "domains": [ + "udel.edu", + "bartol.udel.edu" + ], + "university": { + "web_pages": [ + "http://www.udel.edu/" + ], + "name": "University of Delaware", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "udel.edu" + ], + "country": "United States" + }, + "count": 5, + "id": 62, + "rank": 57 + }, + { + "name": "Johns Hopkins University", + "domains": [ + "cs.jhu.edu" + ], + "university": { + "web_pages": [ + "http://www.jhu.edu/" + ], + "name": "Johns Hopkins University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "jh.edu", + "jhu.edu", + "johnshopkins.edu" + ], + "country": "United States" + }, + "count": 5, + "id": 63, + "rank": 57 + }, + { + "name": "Unknown (udo.edu)", + "domains": [ + "udo.edu" + ], + "university": null, + "count": 5, + "id": 64, + "rank": 57 + }, + { + "name": "Pennsylvania State University", + "domains": [ + "psu.edu", + "cse.psu.edu" + ], + "university": { + "web_pages": [ + "http://www.psu.edu/" + ], + "name": "Pennsylvania State University", + "alpha_two_code": "US", + "state-province": "Pennsylvania", + "domains": [ + "psu.edu" + ], + "country": "United States" + }, + "count": 4, + "id": 65, + "rank": 65 + }, + { + "name": "Arizona State University", + "domains": [ + "asu.edu" + ], + "university": { + "web_pages": [ + "http://www.asu.edu/" + ], + "name": "Arizona State University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "asu.edu" + ], + "country": "United States" + }, + "count": 4, + "id": 66, + "rank": 65 + }, + { + "name": "Wuhan University", + "domains": [ + "whu.edu.cn" + ], + "university": { + "web_pages": [ + "http://www.whu.edu.cn/" + ], + "name": "Wuhan University", + "alpha_two_code": "CN", + "state-province": null, + "domains": [ + "whu.edu.cn" + ], + "country": "China" + }, + "count": 4, + "id": 67, + "rank": 65 + }, + { + "name": "University of Electronic Science and Technology of China", + "domains": [ + "cduestc.edu.cn" + ], + "university": { + "web_pages": [ + "http://www.uestc.edu.cn/" + ], + "name": "University of Electronic Science and Technology of China", + "alpha_two_code": "CN", + "state-province": null, + "domains": [ + "uestc.edu.cn" + ], + "country": "China" + }, + "count": 4, + "id": 68, + "rank": 65 + }, + { + "name": "Boston University", + "domains": [ + "bu.edu" + ], + "university": { + "web_pages": [ + "http://www.bu.edu/" + ], + "name": "Boston University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "bu.edu" + ], + "country": "United States" + }, + "count": 4, + "id": 69, + "rank": 65 + }, + { + "name": "Saint Michael's College", + "domains": [ + "mail.smcvt.edu" + ], + "university": { + "web_pages": [ + "http://www.smcvt.edu/" + ], + "name": "Saint Michael's College", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "smcvt.edu" + ], + "country": "United States" + }, + "count": 4, + "id": 70, + "rank": 65 + }, + { + "name": "Drexel University", + "domains": [ + "drexel.edu", + "cs.drexel.edu", + "bandersnatch.cs.drexel.edu" + ], + "university": { + "web_pages": [ + "http://www.drexel.edu/" + ], + "name": "Drexel University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "drexel.edu" + ], + "country": "United States" + }, + "count": 4, + "id": 71, + "rank": 65 + }, + { + "name": "Iowa State University", + "domains": [ + "iastate.edu" + ], + "university": { + "web_pages": [ + "http://www.iastate.edu/" + ], + "name": "Iowa State University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "iastate.edu" + ], + "country": "United States" + }, + "count": 4, + "id": 72, + "rank": 65 + }, + { + "name": "Unknown (whoi.edu)", + "domains": [ + "whoi.edu" + ], + "university": null, + "count": 4, + "id": 73, + "rank": 65 + }, + { + "name": "Beijing University of Aeronautics and Astronautics", + "domains": [ + "buaa.edu.cn" + ], + "university": { + "web_pages": [ + "http://www.buaa.edu.cn/" + ], + "name": "Beijing University of Aeronautics and Astronautics", + "alpha_two_code": "CN", + "state-province": null, + "domains": [ + "buaa.edu.cn" + ], + "country": "China" + }, + "count": 3, + "id": 74, + "rank": 74 + }, + { + "name": "New York University", + "domains": [ + "nyu.edu" + ], + "university": { + "web_pages": [ + "http://www.nyu.edu/" + ], + "name": "New York University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "nyu.edu" + ], + "country": "United States" + }, + "count": 3, + "id": 75, + "rank": 74 + }, + { + "name": "State University of New York at Stony Brook", + "domains": [ + "cs.stonybrook.edu" + ], + "university": { + "web_pages": [ + "http://www.stonybrook.edu/" + ], + "name": "State University of New York at Stony Brook", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "stonybrook.edu" + ], + "country": "United States" + }, + "count": 3, + "id": 76, + "rank": 74 + }, + { + "name": "National University of Singapore", + "domains": [ + "comp.nus.edu.sg" + ], + "university": { + "web_pages": [ + "https://www.nus.edu/", + "https://www.nus.edu.sg/" + ], + "name": "National University of Singapore", + "alpha_two_code": "SG", + "state-province": null, + "domains": [ + "nus.edu", + "nus.edu.sg" + ], + "country": "Singapore" + }, + "count": 3, + "id": 77, + "rank": 74 + }, + { + "name": "Concordia College - St. Paul", + "domains": [ + "csp.edu" + ], + "university": { + "web_pages": [ + "http://www.csp.edu/" + ], + "name": "Concordia College - St. Paul", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "csp.edu" + ], + "country": "United States" + }, + "count": 3, + "id": 78, + "rank": 74 + }, + { + "name": "National Central University", + "domains": [ + "g.ncu.edu.tw" + ], + "university": { + "web_pages": [ + "http://www.ncu.edu.tw/" + ], + "name": "National Central University", + "alpha_two_code": "TW", + "state-province": null, + "domains": [ + "ncu.edu.tw" + ], + "country": "Taiwan" + }, + "count": 3, + "id": 79, + "rank": 74 + }, + { + "name": "University of North Carolina at Chapel Hill", + "domains": [ + "cs.unc.edu" + ], + "university": { + "web_pages": [ + "http://www.unc.edu/" + ], + "name": "University of North Carolina at Chapel Hill", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "unc.edu", + "ad.unc.edu" + ], + "country": "United States" + }, + "count": 3, + "id": 80, + "rank": 74 + }, + { + "name": "George Washington University", + "domains": [ + "gwmail.gwu.edu", + "gwu.edu" + ], + "university": { + "web_pages": [ + "http://www.gwu.edu/" + ], + "name": "George Washington University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "gwu.edu" + ], + "country": "United States" + }, + "count": 3, + "id": 81, + "rank": 74 + }, + { + "name": "University of Utah", + "domains": [ + "cs.utah.edu", + "eng.utah.edu" + ], + "university": { + "web_pages": [ + "http://www.utah.edu/" + ], + "name": "University of Utah", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "utah.edu" + ], + "country": "United States" + }, + "count": 3, + "id": 82, + "rank": 74 + }, + { + "name": "University of Oklahoma", + "domains": [ + "ou.edu" + ], + "university": { + "web_pages": [ + "http://www.ou.edu/" + ], + "name": "University of Oklahoma", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "ou.edu" + ], + "country": "United States" + }, + "count": 3, + "id": 83, + "rank": 74 + }, + { + "name": "University of Sydney", + "domains": [ + "sydney.edu.au", + "maths.usyd.edu.au" + ], + "university": { + "web_pages": [ + "http://sydney.edu.au/" + ], + "name": "University of Sydney", + "alpha_two_code": "AU", + "state-province": "New South Wales", + "domains": [ + "sydney.edu.au", + "usyd.edu.au", + "uni.sydney.edu.au" + ], + "country": "Australia" + }, + "count": 3, + "id": 84, + "rank": 74 + }, + { + "name": "Unknown (eecg.toronto.edu)", + "domains": [ + "eecg.toronto.edu" + ], + "university": null, + "count": 3, + "id": 85, + "rank": 74 + }, + { + "name": "Princeton University", + "domains": [ + "princeton.edu", + "cs.princeton.edu" + ], + "university": { + "web_pages": [ + "http://www.princeton.edu/" + ], + "name": "Princeton University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "princeton.edu" + ], + "country": "United States" + }, + "count": 3, + "id": 86, + "rank": 74 + }, + { + "name": "North Carolina State University", + "domains": [ + "ncsu.edu" + ], + "university": { + "web_pages": [ + "http://www.ncsu.edu/" + ], + "name": "North Carolina State University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "ncsu.edu" + ], + "country": "United States" + }, + "count": 3, + "id": 87, + "rank": 74 + }, + { + "name": "National Taiwan University", + "domains": [ + "csie.ntu.edu.tw" + ], + "university": { + "web_pages": [ + "http://www.ntu.edu.tw/" + ], + "name": "National Taiwan University", + "alpha_two_code": "TW", + "state-province": null, + "domains": [ + "ntu.edu.tw" + ], + "country": "Taiwan" + }, + "count": 2, + "id": 88, + "rank": 88 + }, + { + "name": "Beijing University of Posts and Telecommunications", + "domains": [ + "bupt.edu.cn" + ], + "university": { + "web_pages": [ + "http://www.bupt.edu.cn/" + ], + "name": "Beijing University of Posts and Telecommunications", + "alpha_two_code": "CN", + "state-province": null, + "domains": [ + "bupt.edu.cn" + ], + "country": "China" + }, + "count": 2, + "id": 89, + "rank": 88 + }, + { + "name": "South China University of Technology", + "domains": [ + "mail.scut.edu.cn" + ], + "university": { + "web_pages": [ + "http://www.scut.edu.cn/" + ], + "name": "South China University of Technology", + "alpha_two_code": "CN", + "state-province": null, + "domains": [ + "scut.edu.cn" + ], + "country": "China" + }, + "count": 2, + "id": 90, + "rank": 88 + }, + { + "name": "Michigan Technological University", + "domains": [ + "mtu.edu" + ], + "university": { + "web_pages": [ + "http://www.mtu.edu/" + ], + "name": "Michigan Technological University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "mtu.edu" + ], + "country": "United States" + }, + "count": 2, + "id": 91, + "rank": 88 + }, + { + "name": "Nanjing University", + "domains": [ + "smail.nju.edu.cn" + ], + "university": { + "web_pages": [ + "http://www.nju.edu.cn/" + ], + "name": "Nanjing University", + "alpha_two_code": "CN", + "state-province": null, + "domains": [ + "nju.edu.cn" + ], + "country": "China" + }, + "count": 2, + "id": 92, + "rank": 88 + }, + { + "name": "Moscow Institute of Physics and Technology", + "domains": [ + "phystech.edu" + ], + "university": { + "web_pages": [ + "http://www.mipt.ru/", + "http://www.phystech.edu/" + ], + "name": "Moscow Institute of Physics and Technology", + "alpha_two_code": "RU", + "state-province": null, + "domains": [ + "mipt.ru", + "phystech.edu" + ], + "country": "Russian Federation" + }, + "count": 2, + "id": 93, + "rank": 88 + }, + { + "name": "Worcester Polytechnic Institute", + "domains": [ + "alum.wpi.edu" + ], + "university": { + "web_pages": [ + "http://www.wpi.edu/" + ], + "name": "Worcester Polytechnic Institute", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "wpi.edu" + ], + "country": "United States" + }, + "count": 2, + "id": 94, + "rank": 88 + }, + { + "name": "University of Central Florida", + "domains": [ + "Knights.ucf.edu", + "knights.ucf.edu" + ], + "university": { + "web_pages": [ + "http://www.ucf.edu/" + ], + "name": "University of Central Florida", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "ucf.edu" + ], + "country": "United States" + }, + "count": 2, + "id": 95, + "rank": 88 + }, + { + "name": "The University of Texas at Austin", + "domains": [ + "cs.utexas.edu", + "tacc.utexas.edu" + ], + "university": { + "web_pages": [ + "https://www.utexas.edu/" + ], + "name": "The University of Texas at Austin", + "alpha_two_code": "US", + "state-province": "Texas", + "domains": [ + "utexas.edu" + ], + "country": "United States" + }, + "count": 2, + "id": 96, + "rank": 88 + }, + { + "name": "State University of New York at Binghamton", + "domains": [ + "binghamton.edu" + ], + "university": { + "web_pages": [ + "http://www.binghamton.edu/" + ], + "name": "State University of New York at Binghamton", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "binghamton.edu" + ], + "country": "United States" + }, + "count": 2, + "id": 97, + "rank": 88 + }, + { + "name": "Unknown (meduna.org)", + "domains": [ + "meduna.org" + ], + "university": null, + "count": 2, + "id": 98, + "rank": 88 + }, + { + "name": "Unknown (ozu.edu.tr)", + "domains": [ + "ozu.edu.tr" + ], + "university": null, + "count": 2, + "id": 99, + "rank": 88 + }, + { + "name": "University of California, Los Angeles", + "domains": [ + "ucla.edu", + "cs.ucla.edu" + ], + "university": { + "web_pages": [ + "http://www.ucla.edu/" + ], + "name": "University of California, Los Angeles", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "ucla.edu" + ], + "country": "United States" + }, + "count": 2, + "id": 100, + "rank": 88 + }, + { + "name": "Yavapai College", + "domains": [ + "opensource.dyc.edu" + ], + "university": { + "web_pages": [ + "http://www.YC.EDU" + ], + "name": "Yavapai College", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "yc.edu" + ], + "country": "United States" + }, + "count": 2, + "id": 101, + "rank": 88 + }, + { + "name": "Colorado School of Mines", + "domains": [ + "mines.edu" + ], + "university": { + "web_pages": [ + "http://www.mines.edu/" + ], + "name": "Colorado School of Mines", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "mines.edu" + ], + "country": "United States" + }, + "count": 2, + "id": 102, + "rank": 88 + }, + { + "name": "National University of Defense Technology", + "domains": [ + "nudt.edu.cn" + ], + "university": { + "web_pages": [ + "http://www.nudt.edu.cn/" + ], + "name": "National University of Defense Technology", + "alpha_two_code": "CN", + "state-province": null, + "domains": [ + "nudt.edu.cn" + ], + "country": "China" + }, + "count": 2, + "id": 103, + "rank": 88 + }, + { + "name": "University of Warsaw", + "domains": [ + "mimuw.edu.pl", + "sith.mimuw.edu.pl" + ], + "university": { + "web_pages": [ + "http://www.uw.edu.pl/" + ], + "name": "University of Warsaw", + "alpha_two_code": "PL", + "state-province": null, + "domains": [ + "uw.edu.pl" + ], + "country": "Poland" + }, + "count": 2, + "id": 104, + "rank": 88 + }, + { + "name": "Rose-Hulman Institute of Technology", + "domains": [ + "rose-hulman.edu" + ], + "university": { + "web_pages": [ + "http://www.rose-hulman.edu/" + ], + "name": "Rose-Hulman Institute of Technology", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "rose-hulman.edu" + ], + "country": "United States" + }, + "count": 2, + "id": 105, + "rank": 88 + }, + { + "name": "Chongqing University", + "domains": [ + "cqu.edu.cn" + ], + "university": { + "web_pages": [ + "http://www.cqu.edu.cn/" + ], + "name": "Chongqing University", + "alpha_two_code": "CN", + "state-province": null, + "domains": [ + "cqu.edu.cn" + ], + "country": "China" + }, + "count": 2, + "id": 106, + "rank": 88 + }, + { + "name": "New Mexico Institute of Mining & Technology", + "domains": [ + "nmt.edu" + ], + "university": { + "web_pages": [ + "http://www.nmt.edu/" + ], + "name": "New Mexico Institute of Mining & Technology", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "nmt.edu" + ], + "country": "United States" + }, + "count": 2, + "id": 107, + "rank": 88 + }, + { + "name": "Temple University", + "domains": [ + "temple.edu" + ], + "university": { + "web_pages": [ + "http://www.temple.edu/" + ], + "name": "Temple University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "temple.edu" + ], + "country": "United States" + }, + "count": 2, + "id": 108, + "rank": 88 + }, + { + "name": "Brown University", + "domains": [ + "alumni.brown.edu" + ], + "university": { + "web_pages": [ + "http://www.brown.edu/" + ], + "name": "Brown University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "brown.edu" + ], + "country": "United States" + }, + "count": 2, + "id": 109, + "rank": 88 + }, + { + "name": "New College of Florida", + "domains": [ + "ncf.edu" + ], + "university": { + "web_pages": [ + "http://www.ncf.edu/" + ], + "name": "New College of Florida", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "ncf.edu" + ], + "country": "United States" + }, + "count": 1, + "id": 110, + "rank": 110 + }, + { + "name": "Taiyuan University of Technology", + "domains": [ + "link.tyut.edu.cn" + ], + "university": { + "web_pages": [ + "http://www.tyut.edu.cn/" + ], + "name": "Taiyuan University of Technology", + "alpha_two_code": "CN", + "state-province": null, + "domains": [ + "tyut.edu.cn" + ], + "country": "China" + }, + "count": 1, + "id": 111, + "rank": 110 + }, + { + "name": "Ching Kuo Institue of Management & Health", + "domains": [ + "gs.ncku.edu.tw" + ], + "university": { + "web_pages": [ + "http://www.cku.edu.tw/" + ], + "name": "Ching Kuo Institue of Management & Health", + "alpha_two_code": "TW", + "state-province": null, + "domains": [ + "cku.edu.tw" + ], + "country": "Taiwan" + }, + "count": 1, + "id": 112, + "rank": 110 + }, + { + "name": "Unknown (ustc.edu)", + "domains": [ + "ustc.edu" + ], + "university": null, + "count": 1, + "id": 113, + "rank": 110 + }, + { + "name": "University of Turin", + "domains": [ + "edu.unito.it" + ], + "university": { + "web_pages": [ + "http://www.unito.it/" + ], + "name": "University of Turin", + "alpha_two_code": "IT", + "state-province": null, + "domains": [ + "unito.it" + ], + "country": "Italy" + }, + "count": 1, + "id": 114, + "rank": 110 + }, + { + "name": "American University of Sharjah", + "domains": [ + "aus.edu" + ], + "university": { + "web_pages": [ + "http://www.aus.edu/" + ], + "name": "American University of Sharjah", + "alpha_two_code": "AE", + "state-province": null, + "domains": [ + "aus.edu" + ], + "country": "United Arab Emirates" + }, + "count": 1, + "id": 115, + "rank": 110 + }, + { + "name": "University of Southern California", + "domains": [ + "usc.edu" + ], + "university": { + "web_pages": [ + "http://www.usc.edu/" + ], + "name": "University of Southern California", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "usc.edu" + ], + "country": "United States" + }, + "count": 1, + "id": 116, + "rank": 110 + }, + { + "name": "Brigham Young University", + "domains": [ + "byu.edu" + ], + "university": { + "web_pages": [ + "http://www.byu.edu/" + ], + "name": "Brigham Young University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "byu.edu" + ], + "country": "United States" + }, + "count": 1, + "id": 117, + "rank": 110 + }, + { + "name": "Bucknell University", + "domains": [ + "bucknell.edu" + ], + "university": { + "web_pages": [ + "http://www.bucknell.edu/" + ], + "name": "Bucknell University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "bucknell.edu" + ], + "country": "United States" + }, + "count": 1, + "id": 118, + "rank": 110 + }, + { + "name": "Unknown (rajagiritech.edu.in)", + "domains": [ + "rajagiritech.edu.in" + ], + "university": null, + "count": 1, + "id": 119, + "rank": 110 + }, + { + "name": "Unknown (embedur.com)", + "domains": [ + "embedur.com" + ], + "university": null, + "count": 1, + "id": 120, + "rank": 110 + }, + { + "name": "Unknown (isi.edu)", + "domains": [ + "isi.edu" + ], + "university": null, + "count": 1, + "id": 121, + "rank": 110 + }, + { + "name": "Unknown (fedux.com.ar)", + "domains": [ + "fedux.com.ar" + ], + "university": null, + "count": 1, + "id": 122, + "rank": 110 + }, + { + "name": "University of Florida", + "domains": [ + "ece.ufl.edu" + ], + "university": { + "web_pages": [ + "http://www.ufl.edu/" + ], + "name": "University of Florida", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "ufl.edu" + ], + "country": "United States" + }, + "count": 1, + "id": 123, + "rank": 110 + }, + { + "name": "Kent State University", + "domains": [ + "kent.edu" + ], + "university": { + "web_pages": [ + "http://www.kent.edu/" + ], + "name": "Kent State University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "kent.edu" + ], + "country": "United States" + }, + "count": 1, + "id": 124, + "rank": 110 + }, + { + "name": "Shenandoah University", + "domains": [ + "sdl.usu.edu" + ], + "university": { + "web_pages": [ + "http://www.su.edu/" + ], + "name": "Shenandoah University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "su.edu" + ], + "country": "United States" + }, + "count": 1, + "id": 125, + "rank": 110 + }, + { + "name": "AGH University of Science and Technology", + "domains": [ + "agh.edu.pl" + ], + "university": { + "web_pages": [ + "http://www.agh.edu.pl/" + ], + "name": "AGH University of Science and Technology", + "alpha_two_code": "PL", + "state-province": null, + "domains": [ + "agh.edu.pl" + ], + "country": "Poland" + }, + "count": 1, + "id": 126, + "rank": 110 + }, + { + "name": "Ecole Centrale d'Electronique - ECE", + "domains": [ + "edu.ece.fr" + ], + "university": { + "web_pages": [ + "http://www.ece.fr/" + ], + "name": "Ecole Centrale d'Electronique - ECE", + "alpha_two_code": "FR", + "state-province": null, + "domains": [ + "ece.fr" + ], + "country": "France" + }, + "count": 1, + "id": 127, + "rank": 110 + }, + { + "name": "Karlsruher Institut f\u00fcr Technologie", + "domains": [ + "student.kit.edu" + ], + "university": { + "web_pages": [ + "http://www.kit.edu/" + ], + "name": "Karlsruher Institut f\u00fcr Technologie", + "alpha_two_code": "DE", + "state-province": null, + "domains": [ + "kit.edu" + ], + "country": "Germany" + }, + "count": 1, + "id": 128, + "rank": 110 + }, + { + "name": "University of California, Santa Barbara", + "domains": [ + "cs.ucsb.edu" + ], + "university": { + "web_pages": [ + "http://www.ucsb.edu/" + ], + "name": "University of California, Santa Barbara", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "ucsb.edu" + ], + "country": "United States" + }, + "count": 1, + "id": 129, + "rank": 110 + }, + { + "name": "University of California, Davis", + "domains": [ + "ucdavis.edu" + ], + "university": { + "web_pages": [ + "http://www.ucdavis.edu/" + ], + "name": "University of California, Davis", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "ucdavis.edu" + ], + "country": "United States" + }, + "count": 1, + "id": 130, + "rank": 110 + }, + { + "name": "University of Texas at Dallas", + "domains": [ + "utdallas.edu" + ], + "university": { + "web_pages": [ + "http://www.utdallas.edu/" + ], + "name": "University of Texas at Dallas", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "utd.edu", + "utdallas.edu" + ], + "country": "United States" + }, + "count": 1, + "id": 131, + "rank": 110 + }, + { + "name": "University of Colorado at Boulder", + "domains": [ + "colorado.edu" + ], + "university": { + "web_pages": [ + "http://www.colorado.edu/" + ], + "name": "University of Colorado at Boulder", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "colorado.edu" + ], + "country": "United States" + }, + "count": 1, + "id": 132, + "rank": 110 + }, + { + "name": "American International College", + "domains": [ + "naic.edu" + ], + "university": { + "web_pages": [ + "http://www.aic.edu/" + ], + "name": "American International College", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "aic.edu" + ], + "country": "United States" + }, + "count": 1, + "id": 133, + "rank": 110 + }, + { + "name": "California Polytechnic State University, San Luis Obispo", + "domains": [ + "calpoly.edu" + ], + "university": { + "web_pages": [ + "http://www.calpoly.edu/" + ], + "name": "California Polytechnic State University, San Luis Obispo", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "calpoly.edu" + ], + "country": "United States" + }, + "count": 1, + "id": 134, + "rank": 110 + }, + { + "name": "Unknown (tilburguniversity.edu)", + "domains": [ + "tilburguniversity.edu" + ], + "university": null, + "count": 1, + "id": 135, + "rank": 110 + }, + { + "name": "Universidad Galileo", + "domains": [ + "galileo.edu" + ], + "university": { + "web_pages": [ + "http://www.galileo.edu/" + ], + "name": "Universidad Galileo", + "alpha_two_code": "GT", + "state-province": null, + "domains": [ + "galileo.edu" + ], + "country": "Guatemala" + }, + "count": 1, + "id": 136, + "rank": 110 + }, + { + "name": "Harvey Mudd College", + "domains": [ + "cs.hmc.edu" + ], + "university": { + "web_pages": [ + "http://www.hmc.edu/" + ], + "name": "Harvey Mudd College", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "hmc.edu" + ], + "country": "United States" + }, + "count": 1, + "id": 137, + "rank": 110 + }, + { + "name": "University of Rhode Island", + "domains": [ + "ele.uri.edu" + ], + "university": { + "web_pages": [ + "http://www.uri.edu/" + ], + "name": "University of Rhode Island", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "uri.edu" + ], + "country": "United States" + }, + "count": 1, + "id": 138, + "rank": 110 + }, + { + "name": "Polish-Japanese Institute of Information Technology in Warsaw", + "domains": [ + "pjwstk.edu.pl" + ], + "university": { + "web_pages": [ + "http://www.pjwstk.edu.pl/" + ], + "name": "Polish-Japanese Institute of Information Technology in Warsaw", + "alpha_two_code": "PL", + "state-province": null, + "domains": [ + "pjwstk.edu.pl" + ], + "country": "Poland" + }, + "count": 1, + "id": 139, + "rank": 110 + }, + { + "name": "Rice University", + "domains": [ + "rice.edu" + ], + "university": { + "web_pages": [ + "http://www.rice.edu/" + ], + "name": "Rice University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "rice.edu" + ], + "country": "United States" + }, + "count": 1, + "id": 140, + "rank": 110 + }, + { + "name": "Mississippi State University", + "domains": [ + "msstate.edu" + ], + "university": { + "web_pages": [ + "http://www.msstate.edu/" + ], + "name": "Mississippi State University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "msstate.edu" + ], + "country": "United States" + }, + "count": 1, + "id": 141, + "rank": 110 + }, + { + "name": "Unknown (camk.edu.pl)", + "domains": [ + "camk.edu.pl" + ], + "university": null, + "count": 1, + "id": 142, + "rank": 110 + }, + { + "name": "Tulane University", + "domains": [ + "tulane.edu" + ], + "university": { + "web_pages": [ + "http://www.tulane.edu/" + ], + "name": "Tulane University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "tulane.edu" + ], + "country": "United States" + }, + "count": 1, + "id": 143, + "rank": 110 + }, + { + "name": "Universidade Federal de Campina Grande", + "domains": [ + "embedded.ufcg.edu.br" + ], + "university": { + "web_pages": [ + "http://www.ufcg.edu.br/" + ], + "name": "Universidade Federal de Campina Grande", + "alpha_two_code": "BR", + "state-province": null, + "domains": [ + "ufcg.edu.br" + ], + "country": "Brazil" + }, + "count": 1, + "id": 144, + "rank": 110 + }, + { + "name": "Unknown (students.olin.edu)", + "domains": [ + "students.olin.edu" + ], + "university": null, + "count": 1, + "id": 145, + "rank": 110 + }, + { + "name": "Singapore Management University", + "domains": [ + "smu.edu.sg" + ], + "university": { + "web_pages": [ + "https://www.smu.edu.sg/" + ], + "name": "Singapore Management University", + "alpha_two_code": "SG", + "state-province": null, + "domains": [ + "smu.edu.sg" + ], + "country": "Singapore" + }, + "count": 1, + "id": 146, + "rank": 110 + }, + { + "name": "Jagiellonian University Cracow", + "domains": [ + "smp.if.uj.edu.pl" + ], + "university": { + "web_pages": [ + "http://www.uj.edu.pl/" + ], + "name": "Jagiellonian University Cracow", + "alpha_two_code": "PL", + "state-province": null, + "domains": [ + "uj.edu.pl" + ], + "country": "Poland" + }, + "count": 1, + "id": 147, + "rank": 110 + }, + { + "name": "University of New Hampshire", + "domains": [ + "unh.edu" + ], + "university": { + "web_pages": [ + "https://www.unh.edu/" + ], + "name": "University of New Hampshire", + "alpha_two_code": "US", + "state-province": "New Hampshire", + "domains": [ + "unh.edu" + ], + "country": "United States" + }, + "count": 1, + "id": 148, + "rank": 110 + }, + { + "name": "University of Technology Sydney", + "domains": [ + "uts.edu.au" + ], + "university": { + "web_pages": [ + "http://www.uts.edu.au/" + ], + "name": "University of Technology Sydney", + "alpha_two_code": "AU", + "state-province": "New South Wales", + "domains": [ + "uts.edu.au", + "student.uts.edu.au" + ], + "country": "Australia" + }, + "count": 1, + "id": 149, + "rank": 110 + }, + { + "name": "National Sun Yat-Sen University", + "domains": [ + "cse.nsysu.edu.tw" + ], + "university": { + "web_pages": [ + "http://www.nsysu.edu.tw/" + ], + "name": "National Sun Yat-Sen University", + "alpha_two_code": "TW", + "state-province": null, + "domains": [ + "nsysu.edu.tw" + ], + "country": "Taiwan" + }, + "count": 1, + "id": 150, + "rank": 110 + }, + { + "name": "University of Rochester", + "domains": [ + "lle.rochester.edu" + ], + "university": { + "web_pages": [ + "http://www.rochester.edu/" + ], + "name": "University of Rochester", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "rochester.edu" + ], + "country": "United States" + }, + "count": 1, + "id": 151, + "rank": 110 + }, + { + "name": "Augsburg College", + "domains": [ + "augsburg.edu" + ], + "university": { + "web_pages": [ + "http://www.augsburg.edu/" + ], + "name": "Augsburg College", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "augsburg.edu" + ], + "country": "United States" + }, + "count": 1, + "id": 152, + "rank": 110 + }, + { + "name": "Tennessee Technological University", + "domains": [ + "math.tntech.edu" + ], + "university": { + "web_pages": [ + "http://www.tntech.edu/" + ], + "name": "Tennessee Technological University", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "tntech.edu" + ], + "country": "United States" + }, + "count": 1, + "id": 153, + "rank": 110 + }, + { + "name": "University of Massachusetts at Amherst", + "domains": [ + "cs.umass.edu" + ], + "university": { + "web_pages": [ + "http://www.umass.edu/" + ], + "name": "University of Massachusetts at Amherst", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "umass.edu" + ], + "country": "United States" + }, + "count": 1, + "id": 154, + "rank": 110 + }, + { + "name": "The Art Institutes", + "domains": [ + "ifa.hawaii.edu" + ], + "university": { + "web_pages": [ + "http://www.aii.edu/" + ], + "name": "The Art Institutes", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "aii.edu" + ], + "country": "United States" + }, + "count": 1, + "id": 155, + "rank": 110 + }, + { + "name": "Unknown (email.uophx.edu)", + "domains": [ + "email.uophx.edu" + ], + "university": null, + "count": 1, + "id": 156, + "rank": 110 + }, + { + "name": "University of Cincinnati", + "domains": [ + "cs.uiuc.edu" + ], + "university": { + "web_pages": [ + "http://www.uc.edu/" + ], + "name": "University of Cincinnati", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "uc.edu" + ], + "country": "United States" + }, + "count": 1, + "id": 157, + "rank": 110 + }, + { + "name": "Monash University", + "domains": [ + "infotech.monash.edu.au" + ], + "university": { + "web_pages": [ + "http://www.monash.edu/" + ], + "name": "Monash University", + "alpha_two_code": "AU", + "state-province": "Victoria", + "domains": [ + "monash.edu", + "monash.edu.au" + ], + "country": "Australia" + }, + "count": 1, + "id": 158, + "rank": 110 + }, + { + "name": "Unknown (lmc.cs.sunysb.edu)", + "domains": [ + "lmc.cs.sunysb.edu" + ], + "university": null, + "count": 1, + "id": 159, + "rank": 110 + }, + { + "name": "Nanyang Technological University", + "domains": [ + "ntu.edu.sg" + ], + "university": { + "web_pages": [ + "https://www.ntu.edu.sg/" + ], + "name": "Nanyang Technological University", + "alpha_two_code": "SG", + "state-province": null, + "domains": [ + "ntu.edu.sg" + ], + "country": "Singapore" + }, + "count": 1, + "id": 160, + "rank": 110 + }, + { + "name": "University of Massachusetts at Lowell", + "domains": [ + "cs.uml.edu" + ], + "university": { + "web_pages": [ + "http://www.uml.edu/" + ], + "name": "University of Massachusetts at Lowell", + "alpha_two_code": "US", + "state-province": null, + "domains": [ + "uml.edu", + "student.uml.edu" + ], + "country": "United States" + }, + "count": 1, + "id": 161, + "rank": 110 + } + ] +} \ No newline at end of file